From 3ccf0b317c3976c658470ee1df47f76a4487ff3c Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 31 Mar 2011 21:32:12 +0000 Subject: [PATCH] Creating llvm - final tag. git-svn-id: https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_29@128672 91177308-0d34-0410-b5e6-96231b3b80d8 --- final/.gitignore | 37 + final/CMakeLists.txt | 296 + final/CREDITS.TXT | 362 + final/LICENSE.TXT | 69 + final/Makefile | 250 + final/Makefile.common | 70 + final/Makefile.config.in | 359 + final/Makefile.rules | 2278 ++ final/ModuleInfo.txt | 4 + final/README.txt | 16 + final/autoconf/AutoRegen.sh | 58 + final/autoconf/ExportMap.map | 7 + final/autoconf/LICENSE.TXT | 24 + final/autoconf/README.TXT | 49 + final/autoconf/config.guess | 1498 + final/autoconf/config.sub | 1702 ++ final/autoconf/configure.ac | 1724 ++ final/autoconf/depcomp | 522 + final/autoconf/install-sh | 322 + final/autoconf/ltmain.sh | 6863 +++++ final/autoconf/m4/build_exeext.m4 | 42 + final/autoconf/m4/c_printf_a.m4 | 31 + final/autoconf/m4/check_gnu_make.m4 | 26 + final/autoconf/m4/config_makefile.m4 | 9 + final/autoconf/m4/config_project.m4 | 14 + final/autoconf/m4/cxx_flag_check.m4 | 2 + final/autoconf/m4/find_std_program.m4 | 118 + final/autoconf/m4/func_isinf.m4 | 36 + final/autoconf/m4/func_isnan.m4 | 27 + final/autoconf/m4/func_mmap_file.m4 | 26 + final/autoconf/m4/header_mmap_anonymous.m4 | 21 + final/autoconf/m4/huge_val.m4 | 20 + final/autoconf/m4/libtool.m4 | 6389 ++++ final/autoconf/m4/link_options.m4 | 108 + final/autoconf/m4/linux_mixed_64_32.m4 | 17 + final/autoconf/m4/ltdl.m4 | 418 + final/autoconf/m4/need_dev_zero_for_mmap.m4 | 17 + final/autoconf/m4/path_perl.m4 | 16 + final/autoconf/m4/path_tclsh.m4 | 39 + final/autoconf/m4/rand48.m4 | 12 + final/autoconf/m4/sanity_check.m4 | 31 + final/autoconf/m4/single_cxx_check.m4 | 10 + .../autoconf/m4/visibility_inlines_hidden.m4 | 22 + final/autoconf/missing | 353 + final/autoconf/mkinstalldirs | 150 + final/bindings/Makefile | 16 + final/bindings/README.txt | 3 + final/bindings/ocaml/Makefile | 19 + final/bindings/ocaml/Makefile.ocaml | 415 + final/bindings/ocaml/analysis/Makefile | 19 + .../bindings/ocaml/analysis/analysis_ocaml.c | 72 + .../bindings/ocaml/analysis/llvm_analysis.ml | 22 + .../bindings/ocaml/analysis/llvm_analysis.mli | 46 + final/bindings/ocaml/bitreader/Makefile | 19 + .../ocaml/bitreader/bitreader_ocaml.c | 73 + .../ocaml/bitreader/llvm_bitreader.ml | 20 + .../ocaml/bitreader/llvm_bitreader.mli | 29 + final/bindings/ocaml/bitwriter/Makefile | 19 + .../ocaml/bitwriter/bitwriter_ocaml.c | 45 + .../ocaml/bitwriter/llvm_bitwriter.ml | 25 + .../ocaml/bitwriter/llvm_bitwriter.mli | 30 + final/bindings/ocaml/executionengine/Makefile | 19 + .../executionengine/executionengine_ocaml.c | 323 + .../executionengine/llvm_executionengine.ml | 112 + .../executionengine/llvm_executionengine.mli | 163 + final/bindings/ocaml/llvm/Makefile | 19 + final/bindings/ocaml/llvm/llvm.ml | 1064 + final/bindings/ocaml/llvm/llvm.mli | 2259 ++ final/bindings/ocaml/llvm/llvm_ocaml.c | 1829 ++ final/bindings/ocaml/target/Makefile | 19 + final/bindings/ocaml/target/llvm_target.ml | 44 + final/bindings/ocaml/target/llvm_target.mli | 102 + final/bindings/ocaml/target/target_ocaml.c | 109 + final/bindings/ocaml/transforms/Makefile | 18 + .../bindings/ocaml/transforms/scalar/Makefile | 20 + .../transforms/scalar/llvm_scalar_opts.ml | 72 + .../transforms/scalar/llvm_scalar_opts.mli | 118 + .../transforms/scalar/scalar_opts_ocaml.c | 146 + final/build-for-llvm-top.sh | 68 + final/cmake/README | 1 + final/cmake/config-ix.cmake | 385 + final/cmake/modules/AddLLVM.cmake | 136 + final/cmake/modules/AddLLVMDefinitions.cmake | 13 + final/cmake/modules/CMakeLists.txt | 32 + final/cmake/modules/CheckAtomic.cmake | 29 + final/cmake/modules/ChooseMSVCCRT.cmake | 106 + final/cmake/modules/CrossCompileLLVM.cmake | 26 + final/cmake/modules/FindBison.cmake | 52 + final/cmake/modules/GetTargetTriple.cmake | 30 + final/cmake/modules/HandleLLVMOptions.cmake | 185 + final/cmake/modules/LLVM.cmake | 40 + final/cmake/modules/LLVMConfig.cmake | 189 + final/cmake/modules/LLVMLibDeps.cmake | 68 + final/cmake/modules/LLVMParseArguments.cmake | 80 + final/cmake/modules/LLVMProcessSources.cmake | 90 + final/cmake/modules/TableGen.cmake | 46 + final/cmake/modules/VersionFromVCS.cmake | 46 + final/configure | 24115 ++++++++++++++++ final/docs/AliasAnalysis.html | 1064 + final/docs/BitCodeFormat.html | 1487 + final/docs/Bugpoint.html | 250 + final/docs/CFEBuildInstrs.html | 29 + final/docs/CMake.html | 486 + final/docs/CodeGenerator.html | 2817 ++ final/docs/CodingStandards.html | 1499 + final/docs/CommandGuide/FileCheck.pod | 245 + final/docs/CommandGuide/Makefile | 103 + final/docs/CommandGuide/bugpoint.pod | 171 + final/docs/CommandGuide/html/manpage.css | 256 + final/docs/CommandGuide/index.html | 158 + final/docs/CommandGuide/lit.pod | 354 + final/docs/CommandGuide/llc.pod | 201 + final/docs/CommandGuide/lli.pod | 219 + final/docs/CommandGuide/llvm-ar.pod | 406 + final/docs/CommandGuide/llvm-as.pod | 77 + final/docs/CommandGuide/llvm-bcanalyzer.pod | 315 + final/docs/CommandGuide/llvm-config.pod | 131 + final/docs/CommandGuide/llvm-diff.pod | 53 + final/docs/CommandGuide/llvm-dis.pod | 60 + final/docs/CommandGuide/llvm-extract.pod | 73 + final/docs/CommandGuide/llvm-ld.pod | 234 + final/docs/CommandGuide/llvm-link.pod | 79 + final/docs/CommandGuide/llvm-nm.pod | 122 + final/docs/CommandGuide/llvm-prof.pod | 57 + final/docs/CommandGuide/llvm-ranlib.pod | 52 + final/docs/CommandGuide/llvmc.pod | 190 + final/docs/CommandGuide/llvmgcc.pod | 76 + final/docs/CommandGuide/llvmgxx.pod | 85 + final/docs/CommandGuide/manpage.css | 256 + final/docs/CommandGuide/opt.pod | 143 + final/docs/CommandGuide/tblgen.pod | 115 + final/docs/CommandLine.html | 1979 ++ final/docs/CompilerDriver.html | 756 + final/docs/CompilerDriverTutorial.html | 126 + final/docs/CompilerWriterInfo.html | 263 + final/docs/DebuggingJITedCode.html | 152 + final/docs/DeveloperPolicy.html | 618 + final/docs/ExceptionHandling.html | 644 + final/docs/ExtendedIntegerResults.txt | 133 + final/docs/ExtendingLLVM.html | 391 + final/docs/FAQ.html | 938 + final/docs/GCCFEBuildInstrs.html | 279 + final/docs/GarbageCollection.html | 1387 + final/docs/GetElementPtr.html | 739 + final/docs/GettingStarted.html | 1702 ++ final/docs/GettingStartedVS.html | 366 + final/docs/GoldPlugin.html | 213 + .../2000-11-18-EarlyDesignIdeas.txt | 74 + .../2000-11-18-EarlyDesignIdeasResp.txt | 199 + .../2000-12-06-EncodingIdea.txt | 30 + .../2000-12-06-MeetingSummary.txt | 83 + .../2001-01-31-UniversalIRIdea.txt | 39 + .../2001-02-06-TypeNotationDebate.txt | 67 + .../2001-02-06-TypeNotationDebateResp1.txt | 75 + .../2001-02-06-TypeNotationDebateResp2.txt | 53 + .../2001-02-06-TypeNotationDebateResp4.txt | 89 + .../2001-02-09-AdveComments.txt | 120 + .../2001-02-09-AdveCommentsResponse.txt | 245 + .../2001-02-13-Reference-Memory.txt | 39 + .../2001-02-13-Reference-MemoryResponse.txt | 47 + .../2001-04-16-DynamicCompilation.txt | 49 + .../2001-05-18-ExceptionHandling.txt | 202 + .../2001-05-19-ExceptionResponse.txt | 45 + .../2001-06-01-GCCOptimizations.txt | 63 + .../2001-06-01-GCCOptimizations2.txt | 71 + .../2001-06-20-.NET-Differences.txt | 30 + .../2001-07-06-LoweringIRForCodeGen.txt | 31 + .../2001-09-18-OptimizeExceptions.txt | 56 + .../2002-05-12-InstListChange.txt | 55 + .../2002-06-25-MegaPatchInfo.txt | 72 + .../2003-01-23-CygwinNotes.txt | 28 + .../2003-06-25-Reoptimizer1.txt | 137 + .../2003-06-26-Reoptimizer2.txt | 110 + .../2007-OriginalClangReadme.txt | 178 + final/docs/HowToReleaseLLVM.html | 626 + final/docs/HowToSubmitABug.html | 347 + final/docs/LangRef.html | 7799 +++++ final/docs/Lexicon.html | 277 + final/docs/LinkTimeOptimization.html | 390 + final/docs/Makefile | 130 + final/docs/MakefileGuide.html | 1034 + final/docs/Packaging.html | 118 + final/docs/Passes.html | 2249 ++ final/docs/ProgrammersManual.html | 3965 +++ final/docs/Projects.html | 460 + final/docs/ReleaseNotes.html | 1306 + final/docs/SourceLevelDebugging.html | 1783 ++ final/docs/SystemLibrary.html | 319 + final/docs/TableGenFundamentals.html | 911 + final/docs/TestingGuide.html | 1196 + final/docs/UsingLibraries.html | 443 + final/docs/WritingAnLLVMBackend.html | 2556 ++ final/docs/WritingAnLLVMPass.html | 1928 ++ final/docs/doxygen.cfg.in | 1419 + final/docs/doxygen.css | 378 + final/docs/doxygen.footer | 13 + final/docs/doxygen.header | 9 + final/docs/doxygen.intro | 18 + final/docs/img/Debugging.gif | Bin 0 -> 20390 bytes final/docs/img/libdeps.gif | Bin 0 -> 52679 bytes final/docs/img/lines.gif | Bin 0 -> 91 bytes final/docs/img/objdeps.gif | Bin 0 -> 16201 bytes final/docs/img/venusflytrap.jpg | Bin 0 -> 56606 bytes final/docs/index.html | 293 + final/docs/llvm.css | 100 + final/docs/re_format.7 | 756 + final/docs/tutorial/LangImpl1.html | 348 + final/docs/tutorial/LangImpl2.html | 1233 + final/docs/tutorial/LangImpl3.html | 1269 + final/docs/tutorial/LangImpl4.html | 1137 + final/docs/tutorial/LangImpl5-cfg.png | Bin 0 -> 38586 bytes final/docs/tutorial/LangImpl5.html | 1780 ++ final/docs/tutorial/LangImpl6.html | 1817 ++ final/docs/tutorial/LangImpl7.html | 2167 ++ final/docs/tutorial/LangImpl8.html | 365 + final/docs/tutorial/Makefile | 28 + final/docs/tutorial/OCamlLangImpl1.html | 365 + final/docs/tutorial/OCamlLangImpl2.html | 1045 + final/docs/tutorial/OCamlLangImpl3.html | 1093 + final/docs/tutorial/OCamlLangImpl4.html | 1029 + final/docs/tutorial/OCamlLangImpl5.html | 1569 + final/docs/tutorial/OCamlLangImpl6.html | 1574 + final/docs/tutorial/OCamlLangImpl7.html | 1907 ++ final/docs/tutorial/OCamlLangImpl8.html | 365 + final/docs/tutorial/index.html | 48 + final/examples/BrainF/BrainF.cpp | 468 + final/examples/BrainF/BrainF.h | 94 + final/examples/BrainF/BrainFDriver.cpp | 160 + final/examples/BrainF/CMakeLists.txt | 6 + final/examples/BrainF/Makefile | 15 + final/examples/CMakeLists.txt | 13 + final/examples/ExceptionDemo/CMakeLists.txt | 6 + .../examples/ExceptionDemo/ExceptionDemo.cpp | 2030 ++ final/examples/ExceptionDemo/Makefile | 16 + final/examples/Fibonacci/CMakeLists.txt | 5 + final/examples/Fibonacci/Makefile | 17 + final/examples/Fibonacci/fibonacci.cpp | 137 + final/examples/HowToUseJIT/CMakeLists.txt | 5 + final/examples/HowToUseJIT/HowToUseJIT.cpp | 124 + final/examples/HowToUseJIT/Makefile | 15 + final/examples/Kaleidoscope/CMakeLists.txt | 6 + .../Kaleidoscope/Chapter2/CMakeLists.txt | 3 + final/examples/Kaleidoscope/Chapter2/Makefile | 13 + final/examples/Kaleidoscope/Chapter2/toy.cpp | 398 + .../Kaleidoscope/Chapter3/CMakeLists.txt | 5 + final/examples/Kaleidoscope/Chapter3/Makefile | 15 + final/examples/Kaleidoscope/Chapter3/toy.cpp | 563 + .../Kaleidoscope/Chapter4/CMakeLists.txt | 5 + final/examples/Kaleidoscope/Chapter4/Makefile | 15 + final/examples/Kaleidoscope/Chapter4/toy.cpp | 613 + .../Kaleidoscope/Chapter5/CMakeLists.txt | 5 + final/examples/Kaleidoscope/Chapter5/Makefile | 15 + final/examples/Kaleidoscope/Chapter5/toy.cpp | 858 + .../Kaleidoscope/Chapter6/CMakeLists.txt | 5 + final/examples/Kaleidoscope/Chapter6/Makefile | 15 + final/examples/Kaleidoscope/Chapter6/toy.cpp | 976 + .../Kaleidoscope/Chapter7/CMakeLists.txt | 6 + final/examples/Kaleidoscope/Chapter7/Makefile | 16 + final/examples/Kaleidoscope/Chapter7/toy.cpp | 1142 + final/examples/Kaleidoscope/Makefile | 15 + final/examples/Makefile | 32 + final/examples/ModuleMaker/CMakeLists.txt | 5 + final/examples/ModuleMaker/Makefile | 14 + final/examples/ModuleMaker/ModuleMaker.cpp | 64 + final/examples/ModuleMaker/README.txt | 8 + .../OCaml-Kaleidoscope/Chapter2/Makefile | 22 + .../OCaml-Kaleidoscope/Chapter2/_tags | 1 + .../OCaml-Kaleidoscope/Chapter2/ast.ml | 25 + .../OCaml-Kaleidoscope/Chapter2/lexer.ml | 52 + .../OCaml-Kaleidoscope/Chapter2/parser.ml | 122 + .../OCaml-Kaleidoscope/Chapter2/token.ml | 15 + .../OCaml-Kaleidoscope/Chapter2/toplevel.ml | 34 + .../OCaml-Kaleidoscope/Chapter2/toy.ml | 21 + .../OCaml-Kaleidoscope/Chapter3/Makefile | 24 + .../OCaml-Kaleidoscope/Chapter3/_tags | 2 + .../OCaml-Kaleidoscope/Chapter3/ast.ml | 25 + .../OCaml-Kaleidoscope/Chapter3/codegen.ml | 100 + .../OCaml-Kaleidoscope/Chapter3/lexer.ml | 52 + .../Chapter3/myocamlbuild.ml | 6 + .../OCaml-Kaleidoscope/Chapter3/parser.ml | 122 + .../OCaml-Kaleidoscope/Chapter3/token.ml | 15 + .../OCaml-Kaleidoscope/Chapter3/toplevel.ml | 39 + .../OCaml-Kaleidoscope/Chapter3/toy.ml | 26 + .../OCaml-Kaleidoscope/Chapter4/Makefile | 25 + .../OCaml-Kaleidoscope/Chapter4/_tags | 4 + .../OCaml-Kaleidoscope/Chapter4/ast.ml | 25 + .../OCaml-Kaleidoscope/Chapter4/bindings.c | 7 + .../OCaml-Kaleidoscope/Chapter4/codegen.ml | 103 + .../OCaml-Kaleidoscope/Chapter4/lexer.ml | 52 + .../Chapter4/myocamlbuild.ml | 10 + .../OCaml-Kaleidoscope/Chapter4/parser.ml | 122 + .../OCaml-Kaleidoscope/Chapter4/token.ml | 15 + .../OCaml-Kaleidoscope/Chapter4/toplevel.ml | 49 + .../OCaml-Kaleidoscope/Chapter4/toy.ml | 53 + .../OCaml-Kaleidoscope/Chapter5/Makefile | 25 + .../OCaml-Kaleidoscope/Chapter5/_tags | 4 + .../OCaml-Kaleidoscope/Chapter5/ast.ml | 31 + .../OCaml-Kaleidoscope/Chapter5/bindings.c | 7 + .../OCaml-Kaleidoscope/Chapter5/codegen.ml | 225 + .../OCaml-Kaleidoscope/Chapter5/lexer.ml | 57 + .../Chapter5/myocamlbuild.ml | 10 + .../OCaml-Kaleidoscope/Chapter5/parser.ml | 158 + .../OCaml-Kaleidoscope/Chapter5/token.ml | 19 + .../OCaml-Kaleidoscope/Chapter5/toplevel.ml | 49 + .../OCaml-Kaleidoscope/Chapter5/toy.ml | 53 + .../OCaml-Kaleidoscope/Chapter6/Makefile | 34 + .../OCaml-Kaleidoscope/Chapter6/_tags | 4 + .../OCaml-Kaleidoscope/Chapter6/ast.ml | 36 + .../OCaml-Kaleidoscope/Chapter6/bindings.c | 13 + .../OCaml-Kaleidoscope/Chapter6/codegen.ml | 251 + .../OCaml-Kaleidoscope/Chapter6/lexer.ml | 59 + .../Chapter6/myocamlbuild.ml | 10 + .../OCaml-Kaleidoscope/Chapter6/parser.ml | 195 + .../OCaml-Kaleidoscope/Chapter6/token.ml | 22 + .../OCaml-Kaleidoscope/Chapter6/toplevel.ml | 49 + .../OCaml-Kaleidoscope/Chapter6/toy.ml | 53 + .../OCaml-Kaleidoscope/Chapter7/Makefile | 34 + .../OCaml-Kaleidoscope/Chapter7/_tags | 4 + .../OCaml-Kaleidoscope/Chapter7/ast.ml | 39 + .../OCaml-Kaleidoscope/Chapter7/bindings.c | 13 + .../OCaml-Kaleidoscope/Chapter7/codegen.ml | 370 + .../OCaml-Kaleidoscope/Chapter7/lexer.ml | 60 + .../Chapter7/myocamlbuild.ml | 10 + .../OCaml-Kaleidoscope/Chapter7/parser.ml | 221 + .../OCaml-Kaleidoscope/Chapter7/token.ml | 25 + .../OCaml-Kaleidoscope/Chapter7/toplevel.ml | 49 + .../OCaml-Kaleidoscope/Chapter7/toy.ml | 57 + final/examples/OCaml-Kaleidoscope/Makefile | 15 + final/examples/ParallelJIT/CMakeLists.txt | 9 + final/examples/ParallelJIT/Makefile | 17 + final/examples/ParallelJIT/ParallelJIT.cpp | 304 + final/include/llvm-c/Analysis.h | 55 + final/include/llvm-c/BitReader.h | 66 + final/include/llvm-c/BitWriter.h | 46 + final/include/llvm-c/Core.h | 1177 + final/include/llvm-c/EnhancedDisassembly.h | 513 + final/include/llvm-c/ExecutionEngine.h | 152 + final/include/llvm-c/Initialization.h | 40 + final/include/llvm-c/LinkTimeOptimizer.h | 58 + final/include/llvm-c/Target.h | 172 + final/include/llvm-c/Transforms/IPO.h | 76 + final/include/llvm-c/Transforms/Scalar.h | 102 + final/include/llvm-c/lto.h | 278 + final/include/llvm/ADT/APFloat.h | 452 + final/include/llvm/ADT/APInt.h | 1720 ++ final/include/llvm/ADT/APSInt.h | 266 + final/include/llvm/ADT/ArrayRef.h | 137 + final/include/llvm/ADT/BitVector.h | 433 + final/include/llvm/ADT/DAGDeltaAlgorithm.h | 75 + final/include/llvm/ADT/DeltaAlgorithm.h | 91 + final/include/llvm/ADT/DenseMap.h | 533 + final/include/llvm/ADT/DenseMapInfo.h | 165 + final/include/llvm/ADT/DenseSet.h | 129 + final/include/llvm/ADT/DepthFirstIterator.h | 268 + final/include/llvm/ADT/EquivalenceClasses.h | 281 + final/include/llvm/ADT/FoldingSet.h | 684 + final/include/llvm/ADT/GraphTraits.h | 103 + final/include/llvm/ADT/ImmutableIntervalMap.h | 242 + final/include/llvm/ADT/ImmutableList.h | 222 + final/include/llvm/ADT/ImmutableMap.h | 261 + final/include/llvm/ADT/ImmutableSet.h | 1084 + final/include/llvm/ADT/InMemoryStruct.h | 77 + final/include/llvm/ADT/IndexedMap.h | 87 + final/include/llvm/ADT/IntEqClasses.h | 88 + final/include/llvm/ADT/IntervalMap.h | 2139 ++ final/include/llvm/ADT/IntrusiveRefCntPtr.h | 230 + final/include/llvm/ADT/NullablePtr.h | 52 + final/include/llvm/ADT/Optional.h | 120 + final/include/llvm/ADT/OwningPtr.h | 133 + final/include/llvm/ADT/PointerIntPair.h | 163 + final/include/llvm/ADT/PointerUnion.h | 445 + final/include/llvm/ADT/PostOrderIterator.h | 230 + final/include/llvm/ADT/PriorityQueue.h | 84 + final/include/llvm/ADT/SCCIterator.h | 220 + final/include/llvm/ADT/STLExtras.h | 306 + final/include/llvm/ADT/ScopedHashTable.h | 256 + final/include/llvm/ADT/SetOperations.h | 71 + final/include/llvm/ADT/SetVector.h | 178 + final/include/llvm/ADT/SmallBitVector.h | 461 + final/include/llvm/ADT/SmallPtrSet.h | 294 + final/include/llvm/ADT/SmallSet.h | 118 + final/include/llvm/ADT/SmallString.h | 72 + final/include/llvm/ADT/SmallVector.h | 752 + final/include/llvm/ADT/SparseBitVector.h | 906 + final/include/llvm/ADT/Statistic.h | 135 + final/include/llvm/ADT/StringExtras.h | 171 + final/include/llvm/ADT/StringMap.h | 493 + final/include/llvm/ADT/StringRef.h | 458 + final/include/llvm/ADT/StringSet.h | 38 + final/include/llvm/ADT/StringSwitch.h | 126 + final/include/llvm/ADT/Trie.h | 336 + final/include/llvm/ADT/Triple.h | 333 + final/include/llvm/ADT/Twine.h | 465 + final/include/llvm/ADT/UniqueVector.h | 89 + final/include/llvm/ADT/ValueMap.h | 368 + final/include/llvm/ADT/VectorExtras.h | 41 + final/include/llvm/ADT/ilist.h | 708 + final/include/llvm/ADT/ilist_node.h | 106 + final/include/llvm/AbstractTypeUser.h | 205 + final/include/llvm/Analysis/AliasAnalysis.h | 507 + final/include/llvm/Analysis/AliasSetTracker.h | 440 + final/include/llvm/Analysis/CFGPrinter.h | 111 + final/include/llvm/Analysis/CallGraph.h | 375 + final/include/llvm/Analysis/CaptureTracking.h | 33 + final/include/llvm/Analysis/CodeMetrics.h | 95 + final/include/llvm/Analysis/ConstantFolding.h | 82 + .../include/llvm/Analysis/ConstantsScanner.h | 93 + final/include/llvm/Analysis/DIBuilder.h | 464 + .../llvm/Analysis/DOTGraphTraitsPass.h | 83 + final/include/llvm/Analysis/DebugInfo.h | 742 + final/include/llvm/Analysis/DomPrinter.h | 30 + .../include/llvm/Analysis/DominanceFrontier.h | 189 + .../llvm/Analysis/DominatorInternals.h | 289 + final/include/llvm/Analysis/Dominators.h | 876 + final/include/llvm/Analysis/FindUsedTypes.h | 66 + final/include/llvm/Analysis/IVUsers.h | 175 + final/include/llvm/Analysis/InlineCost.h | 182 + .../llvm/Analysis/InstructionSimplify.h | 143 + final/include/llvm/Analysis/Interval.h | 153 + .../include/llvm/Analysis/IntervalIterator.h | 259 + .../include/llvm/Analysis/IntervalPartition.h | 111 + final/include/llvm/Analysis/LazyValueInfo.h | 81 + .../llvm/Analysis/LibCallAliasAnalysis.h | 73 + .../include/llvm/Analysis/LibCallSemantics.h | 167 + final/include/llvm/Analysis/Lint.h | 51 + final/include/llvm/Analysis/Loads.h | 51 + .../llvm/Analysis/LoopDependenceAnalysis.h | 124 + final/include/llvm/Analysis/LoopInfo.h | 1100 + final/include/llvm/Analysis/LoopPass.h | 158 + final/include/llvm/Analysis/MemoryBuiltins.h | 84 + .../llvm/Analysis/MemoryDependenceAnalysis.h | 378 + final/include/llvm/Analysis/PHITransAddr.h | 117 + final/include/llvm/Analysis/Passes.h | 198 + final/include/llvm/Analysis/PathNumbering.h | 304 + final/include/llvm/Analysis/PathProfileInfo.h | 113 + final/include/llvm/Analysis/PostDominators.h | 137 + final/include/llvm/Analysis/ProfileInfo.h | 248 + .../include/llvm/Analysis/ProfileInfoLoader.h | 84 + .../include/llvm/Analysis/ProfileInfoTypes.h | 60 + final/include/llvm/Analysis/RegionInfo.h | 683 + final/include/llvm/Analysis/RegionIterator.h | 342 + final/include/llvm/Analysis/RegionPass.h | 126 + final/include/llvm/Analysis/RegionPrinter.h | 26 + final/include/llvm/Analysis/ScalarEvolution.h | 748 + .../llvm/Analysis/ScalarEvolutionExpander.h | 215 + .../Analysis/ScalarEvolutionExpressions.h | 491 + .../Analysis/ScalarEvolutionNormalization.h | 78 + .../include/llvm/Analysis/SparsePropagation.h | 206 + final/include/llvm/Analysis/Trace.h | 119 + final/include/llvm/Analysis/ValueTracking.h | 163 + final/include/llvm/Analysis/Verifier.h | 75 + final/include/llvm/Argument.h | 88 + .../llvm/Assembly/AssemblyAnnotationWriter.h | 63 + final/include/llvm/Assembly/Parser.h | 65 + final/include/llvm/Assembly/PrintModulePass.h | 42 + final/include/llvm/Assembly/Writer.h | 78 + final/include/llvm/Attributes.h | 290 + final/include/llvm/AutoUpgrade.h | 48 + final/include/llvm/BasicBlock.h | 269 + final/include/llvm/Bitcode/Archive.h | 546 + final/include/llvm/Bitcode/BitCodes.h | 185 + final/include/llvm/Bitcode/BitstreamReader.h | 642 + final/include/llvm/Bitcode/BitstreamWriter.h | 533 + final/include/llvm/Bitcode/LLVMBitCodes.h | 266 + final/include/llvm/Bitcode/ReaderWriter.h | 145 + final/include/llvm/CMakeLists.txt | 21 + final/include/llvm/CallGraphSCCPass.h | 104 + final/include/llvm/CallingConv.h | 103 + final/include/llvm/CodeGen/Analysis.h | 85 + final/include/llvm/CodeGen/AsmPrinter.h | 462 + final/include/llvm/CodeGen/BinaryObject.h | 353 + final/include/llvm/CodeGen/CalcSpillWeights.h | 83 + final/include/llvm/CodeGen/CallingConvLower.h | 300 + final/include/llvm/CodeGen/EdgeBundles.h | 61 + final/include/llvm/CodeGen/FastISel.h | 348 + .../llvm/CodeGen/FunctionLoweringInfo.h | 224 + final/include/llvm/CodeGen/GCMetadata.h | 193 + .../include/llvm/CodeGen/GCMetadataPrinter.h | 73 + final/include/llvm/CodeGen/GCStrategy.h | 142 + final/include/llvm/CodeGen/GCs.h | 35 + final/include/llvm/CodeGen/ISDOpcodes.h | 799 + .../include/llvm/CodeGen/IntrinsicLowering.h | 59 + final/include/llvm/CodeGen/JITCodeEmitter.h | 343 + .../llvm/CodeGen/LatencyPriorityQueue.h | 100 + .../llvm/CodeGen/LinkAllAsmWriterComponents.h | 37 + .../llvm/CodeGen/LinkAllCodegenComponents.h | 59 + final/include/llvm/CodeGen/LiveInterval.h | 578 + .../llvm/CodeGen/LiveIntervalAnalysis.h | 465 + .../include/llvm/CodeGen/LiveStackAnalysis.h | 97 + final/include/llvm/CodeGen/LiveVariables.h | 316 + final/include/llvm/CodeGen/MachORelocation.h | 56 + .../include/llvm/CodeGen/MachineBasicBlock.h | 493 + .../include/llvm/CodeGen/MachineCodeEmitter.h | 332 + final/include/llvm/CodeGen/MachineCodeInfo.h | 53 + .../llvm/CodeGen/MachineConstantPool.h | 170 + .../include/llvm/CodeGen/MachineDominators.h | 202 + final/include/llvm/CodeGen/MachineFrameInfo.h | 551 + final/include/llvm/CodeGen/MachineFunction.h | 478 + .../llvm/CodeGen/MachineFunctionAnalysis.h | 54 + .../llvm/CodeGen/MachineFunctionPass.h | 59 + final/include/llvm/CodeGen/MachineInstr.h | 578 + .../llvm/CodeGen/MachineInstrBuilder.h | 258 + .../llvm/CodeGen/MachineJumpTableInfo.h | 125 + final/include/llvm/CodeGen/MachineLocation.h | 98 + final/include/llvm/CodeGen/MachineLoopInfo.h | 178 + .../include/llvm/CodeGen/MachineLoopRanges.h | 112 + .../include/llvm/CodeGen/MachineMemOperand.h | 165 + .../include/llvm/CodeGen/MachineModuleInfo.h | 366 + .../llvm/CodeGen/MachineModuleInfoImpls.h | 97 + final/include/llvm/CodeGen/MachineOperand.h | 564 + .../llvm/CodeGen/MachinePassRegistry.h | 156 + .../llvm/CodeGen/MachineRegisterInfo.h | 404 + .../include/llvm/CodeGen/MachineRelocation.h | 342 + .../include/llvm/CodeGen/MachineSSAUpdater.h | 115 + .../include/llvm/CodeGen/ObjectCodeEmitter.h | 171 + final/include/llvm/CodeGen/PBQP/Graph.h | 425 + .../include/llvm/CodeGen/PBQP/HeuristicBase.h | 246 + .../llvm/CodeGen/PBQP/HeuristicSolver.h | 616 + .../llvm/CodeGen/PBQP/Heuristics/Briggs.h | 464 + final/include/llvm/CodeGen/PBQP/Math.h | 288 + final/include/llvm/CodeGen/PBQP/Solution.h | 94 + final/include/llvm/CodeGen/Passes.h | 241 + .../llvm/CodeGen/ProcessImplicitDefs.h | 45 + .../include/llvm/CodeGen/PseudoSourceValue.h | 112 + final/include/llvm/CodeGen/RegAllocPBQP.h | 167 + final/include/llvm/CodeGen/RegAllocRegistry.h | 66 + .../include/llvm/CodeGen/RegisterCoalescer.h | 244 + .../include/llvm/CodeGen/RegisterScavenging.h | 168 + final/include/llvm/CodeGen/RuntimeLibcalls.h | 313 + final/include/llvm/CodeGen/ScheduleDAG.h | 718 + .../llvm/CodeGen/ScheduleHazardRecognizer.h | 93 + .../include/llvm/CodeGen/SchedulerRegistry.h | 111 + .../llvm/CodeGen/ScoreboardHazardRecognizer.h | 129 + final/include/llvm/CodeGen/SelectionDAG.h | 1051 + final/include/llvm/CodeGen/SelectionDAGISel.h | 313 + .../include/llvm/CodeGen/SelectionDAGNodes.h | 1781 ++ final/include/llvm/CodeGen/SlotIndexes.h | 728 + .../CodeGen/TargetLoweringObjectFileImpl.h | 206 + final/include/llvm/CodeGen/ValueTypes.h | 690 + final/include/llvm/CodeGen/ValueTypes.td | 78 + final/include/llvm/CompilerDriver/Action.h | 54 + .../llvm/CompilerDriver/AutoGenerated.h | 40 + .../llvm/CompilerDriver/BuiltinOptions.h | 39 + final/include/llvm/CompilerDriver/Common.td | 124 + .../llvm/CompilerDriver/CompilationGraph.h | 330 + final/include/llvm/CompilerDriver/Error.h | 29 + final/include/llvm/CompilerDriver/Main.h | 21 + final/include/llvm/CompilerDriver/Main.inc | 23 + final/include/llvm/CompilerDriver/Tool.h | 100 + final/include/llvm/Config/AsmParsers.def.in | 29 + final/include/llvm/Config/AsmPrinters.def.in | 29 + .../include/llvm/Config/Disassemblers.def.in | 29 + final/include/llvm/Config/Targets.def.in | 28 + final/include/llvm/Config/config.h.cmake | 737 + final/include/llvm/Config/config.h.in | 687 + final/include/llvm/Config/llvm-config.h.cmake | 100 + final/include/llvm/Config/llvm-config.h.in | 97 + final/include/llvm/Constant.h | 164 + final/include/llvm/Constants.h | 971 + final/include/llvm/DerivedTypes.h | 513 + .../llvm/ExecutionEngine/ExecutionEngine.h | 574 + .../llvm/ExecutionEngine/GenericValue.h | 44 + .../llvm/ExecutionEngine/Interpreter.h | 38 + final/include/llvm/ExecutionEngine/JIT.h | 38 + .../llvm/ExecutionEngine/JITEventListener.h | 82 + .../llvm/ExecutionEngine/JITMemoryManager.h | 179 + final/include/llvm/ExecutionEngine/MCJIT.h | 38 + final/include/llvm/Function.h | 437 + final/include/llvm/GVMaterializer.h | 66 + final/include/llvm/GlobalAlias.h | 100 + final/include/llvm/GlobalValue.h | 296 + final/include/llvm/GlobalVariable.h | 180 + final/include/llvm/InitializePasses.h | 232 + final/include/llvm/InlineAsm.h | 256 + final/include/llvm/InstrTypes.h | 854 + final/include/llvm/Instruction.def | 196 + final/include/llvm/Instruction.h | 390 + final/include/llvm/Instructions.h | 3186 ++ final/include/llvm/IntrinsicInst.h | 306 + final/include/llvm/Intrinsics.h | 80 + final/include/llvm/Intrinsics.td | 493 + final/include/llvm/IntrinsicsARM.td | 391 + final/include/llvm/IntrinsicsAlpha.td | 18 + final/include/llvm/IntrinsicsCellSPU.td | 242 + final/include/llvm/IntrinsicsPTX.td | 32 + final/include/llvm/IntrinsicsPowerPC.td | 465 + final/include/llvm/IntrinsicsX86.td | 1584 + final/include/llvm/IntrinsicsXCore.td | 55 + final/include/llvm/LLVMContext.h | 107 + final/include/llvm/LinkAllPasses.h | 165 + final/include/llvm/LinkAllVMCore.h | 53 + final/include/llvm/Linker.h | 299 + final/include/llvm/MC/EDInstInfo.h | 29 + final/include/llvm/MC/MCAsmInfo.h | 479 + final/include/llvm/MC/MCAsmInfoCOFF.h | 24 + final/include/llvm/MC/MCAsmInfoDarwin.h | 32 + final/include/llvm/MC/MCAsmLayout.h | 104 + final/include/llvm/MC/MCAssembler.h | 916 + final/include/llvm/MC/MCCodeEmitter.h | 42 + final/include/llvm/MC/MCContext.h | 322 + final/include/llvm/MC/MCDirectives.h | 56 + final/include/llvm/MC/MCDisassembler.h | 60 + final/include/llvm/MC/MCDwarf.h | 279 + final/include/llvm/MC/MCELFObjectWriter.h | 47 + final/include/llvm/MC/MCELFSymbolFlags.h | 57 + final/include/llvm/MC/MCExpr.h | 432 + final/include/llvm/MC/MCFixup.h | 97 + final/include/llvm/MC/MCFixupKindInfo.h | 43 + final/include/llvm/MC/MCInst.h | 170 + final/include/llvm/MC/MCInstPrinter.h | 51 + final/include/llvm/MC/MCLabel.h | 56 + final/include/llvm/MC/MCMachOSymbolFlags.h | 46 + final/include/llvm/MC/MCMachObjectWriter.h | 65 + final/include/llvm/MC/MCObjectStreamer.h | 83 + final/include/llvm/MC/MCObjectWriter.h | 198 + final/include/llvm/MC/MCParser/AsmCond.h | 40 + final/include/llvm/MC/MCParser/AsmLexer.h | 70 + final/include/llvm/MC/MCParser/MCAsmLexer.h | 181 + final/include/llvm/MC/MCParser/MCAsmParser.h | 137 + .../llvm/MC/MCParser/MCAsmParserExtension.h | 80 + .../llvm/MC/MCParser/MCParsedAsmOperand.h | 37 + final/include/llvm/MC/MCSection.h | 76 + final/include/llvm/MC/MCSectionCOFF.h | 69 + final/include/llvm/MC/MCSectionELF.h | 87 + final/include/llvm/MC/MCSectionMachO.h | 179 + final/include/llvm/MC/MCStreamer.h | 544 + final/include/llvm/MC/MCSymbol.h | 163 + final/include/llvm/MC/MCValue.h | 87 + final/include/llvm/MC/SectionKind.h | 240 + final/include/llvm/Metadata.h | 237 + final/include/llvm/Module.h | 556 + final/include/llvm/Object/MachOFormat.h | 367 + final/include/llvm/Object/MachOObject.h | 180 + final/include/llvm/Object/ObjectFile.h | 262 + final/include/llvm/OperandTraits.h | 197 + final/include/llvm/Operator.h | 285 + final/include/llvm/Pass.h | 371 + final/include/llvm/PassAnalysisSupport.h | 250 + final/include/llvm/PassManager.h | 111 + final/include/llvm/PassManagers.h | 460 + final/include/llvm/PassRegistry.h | 84 + final/include/llvm/PassSupport.h | 336 + final/include/llvm/Support/AIXDataTypesFix.h | 25 + final/include/llvm/Support/AlignOf.h | 60 + final/include/llvm/Support/Allocator.h | 239 + final/include/llvm/Support/Atomic.h | 39 + final/include/llvm/Support/CFG.h | 341 + final/include/llvm/Support/COFF.h | 298 + final/include/llvm/Support/CallSite.h | 301 + final/include/llvm/Support/Casting.h | 241 + final/include/llvm/Support/CommandLine.h | 1391 + final/include/llvm/Support/Compiler.h | 129 + final/include/llvm/Support/ConstantFolder.h | 228 + final/include/llvm/Support/ConstantRange.h | 265 + .../llvm/Support/CrashRecoveryContext.h | 92 + final/include/llvm/Support/DOTGraphTraits.h | 161 + final/include/llvm/Support/DataFlow.h | 103 + final/include/llvm/Support/DataTypes.h.cmake | 189 + final/include/llvm/Support/DataTypes.h.in | 111 + final/include/llvm/Support/Debug.h | 101 + final/include/llvm/Support/DebugLoc.h | 80 + final/include/llvm/Support/Disassembler.h | 35 + final/include/llvm/Support/Dwarf.h | 677 + final/include/llvm/Support/DynamicLibrary.h | 86 + final/include/llvm/Support/ELF.h | 824 + final/include/llvm/Support/Endian.h | 213 + final/include/llvm/Support/Errno.h | 34 + final/include/llvm/Support/ErrorHandling.h | 103 + final/include/llvm/Support/FEnv.h | 56 + final/include/llvm/Support/FileSystem.h | 690 + final/include/llvm/Support/FileUtilities.h | 72 + final/include/llvm/Support/Format.h | 154 + final/include/llvm/Support/FormattedStream.h | 154 + .../llvm/Support/GetElementPtrTypeIterator.h | 113 + final/include/llvm/Support/GraphWriter.h | 357 + final/include/llvm/Support/Host.h | 66 + final/include/llvm/Support/IRBuilder.h | 1224 + final/include/llvm/Support/IRReader.h | 110 + final/include/llvm/Support/IncludeFile.h | 79 + final/include/llvm/Support/InstIterator.h | 147 + final/include/llvm/Support/InstVisitor.h | 217 + final/include/llvm/Support/LICENSE.TXT | 6 + final/include/llvm/Support/LeakDetector.h | 92 + final/include/llvm/Support/MachO.h | 696 + final/include/llvm/Support/ManagedStatic.h | 110 + final/include/llvm/Support/MathExtras.h | 460 + final/include/llvm/Support/Memory.h | 96 + final/include/llvm/Support/MemoryBuffer.h | 119 + final/include/llvm/Support/MemoryObject.h | 70 + final/include/llvm/Support/Mutex.h | 154 + final/include/llvm/Support/MutexGuard.h | 41 + final/include/llvm/Support/NoFolder.h | 288 + final/include/llvm/Support/OutputBuffer.h | 166 + final/include/llvm/Support/PassNameParser.h | 137 + final/include/llvm/Support/Path.h | 16 + final/include/llvm/Support/PathV1.h | 755 + final/include/llvm/Support/PathV2.h | 347 + final/include/llvm/Support/PatternMatch.h | 665 + final/include/llvm/Support/PluginLoader.h | 37 + .../llvm/Support/PointerLikeTypeTraits.h | 81 + .../include/llvm/Support/PredIteratorCache.h | 70 + final/include/llvm/Support/PrettyStackTrace.h | 71 + final/include/llvm/Support/Process.h | 146 + final/include/llvm/Support/Program.h | 157 + final/include/llvm/Support/RWMutex.h | 173 + final/include/llvm/Support/Recycler.h | 117 + .../include/llvm/Support/RecyclingAllocator.h | 73 + final/include/llvm/Support/Regex.h | 81 + final/include/llvm/Support/Registry.h | 223 + final/include/llvm/Support/RegistryParser.h | 55 + final/include/llvm/Support/SMLoc.h | 44 + final/include/llvm/Support/Signals.h | 59 + final/include/llvm/Support/Solaris.h | 40 + final/include/llvm/Support/SourceMgr.h | 185 + final/include/llvm/Support/StandardPasses.h | 242 + final/include/llvm/Support/StringPool.h | 139 + final/include/llvm/Support/SwapByteOrder.h | 101 + final/include/llvm/Support/SystemUtils.h | 44 + final/include/llvm/Support/TargetFolder.h | 242 + final/include/llvm/Support/ThreadLocal.h | 54 + final/include/llvm/Support/Threading.h | 59 + final/include/llvm/Support/TimeValue.h | 382 + final/include/llvm/Support/Timer.h | 194 + final/include/llvm/Support/ToolOutputFile.h | 62 + final/include/llvm/Support/TypeBuilder.h | 399 + final/include/llvm/Support/Valgrind.h | 32 + final/include/llvm/Support/ValueHandle.h | 408 + .../llvm/Support/circular_raw_ostream.h | 171 + final/include/llvm/Support/raw_os_ostream.h | 42 + final/include/llvm/Support/raw_ostream.h | 491 + final/include/llvm/Support/system_error.h | 910 + final/include/llvm/Support/type_traits.h | 126 + final/include/llvm/SymbolTableListTraits.h | 79 + final/include/llvm/Target/Mangler.h | 75 + final/include/llvm/Target/SubtargetFeature.h | 119 + final/include/llvm/Target/Target.td | 711 + final/include/llvm/Target/TargetAsmBackend.h | 123 + final/include/llvm/Target/TargetAsmInfo.h | 75 + final/include/llvm/Target/TargetAsmLexer.h | 89 + final/include/llvm/Target/TargetAsmParser.h | 90 + final/include/llvm/Target/TargetCallingConv.h | 140 + .../include/llvm/Target/TargetCallingConv.td | 135 + final/include/llvm/Target/TargetData.h | 336 + .../include/llvm/Target/TargetELFWriterInfo.h | 123 + .../include/llvm/Target/TargetFrameLowering.h | 196 + final/include/llvm/Target/TargetInstrDesc.h | 513 + final/include/llvm/Target/TargetInstrInfo.h | 713 + .../llvm/Target/TargetInstrItineraries.h | 248 + .../include/llvm/Target/TargetIntrinsicInfo.h | 64 + final/include/llvm/Target/TargetJITInfo.h | 142 + final/include/llvm/Target/TargetLibraryInfo.h | 75 + final/include/llvm/Target/TargetLowering.h | 1864 ++ .../llvm/Target/TargetLoweringObjectFile.h | 240 + final/include/llvm/Target/TargetMachine.h | 390 + final/include/llvm/Target/TargetOpcodes.h | 86 + final/include/llvm/Target/TargetOptions.h | 162 + .../include/llvm/Target/TargetRegisterInfo.h | 828 + final/include/llvm/Target/TargetRegistry.h | 779 + final/include/llvm/Target/TargetSchedule.td | 130 + final/include/llvm/Target/TargetSelect.h | 125 + .../include/llvm/Target/TargetSelectionDAG.td | 893 + .../llvm/Target/TargetSelectionDAGInfo.h | 101 + final/include/llvm/Target/TargetSubtarget.h | 67 + final/include/llvm/Transforms/IPO.h | 212 + .../include/llvm/Transforms/IPO/InlinerPass.h | 97 + .../include/llvm/Transforms/Instrumentation.h | 33 + final/include/llvm/Transforms/Scalar.h | 348 + .../llvm/Transforms/Utils/AddrModeMatcher.h | 108 + .../llvm/Transforms/Utils/BasicBlockUtils.h | 186 + .../llvm/Transforms/Utils/BasicInliner.h | 55 + .../llvm/Transforms/Utils/BuildLibCalls.h | 110 + final/include/llvm/Transforms/Utils/Cloning.h | 219 + .../llvm/Transforms/Utils/FunctionUtils.h | 41 + final/include/llvm/Transforms/Utils/Local.h | 162 + .../llvm/Transforms/Utils/PromoteMemToReg.h | 45 + .../llvm/Transforms/Utils/SSAUpdater.h | 163 + .../llvm/Transforms/Utils/SSAUpdaterImpl.h | 469 + .../Transforms/Utils/UnifyFunctionExitNodes.h | 51 + .../llvm/Transforms/Utils/UnrollLoop.h | 29 + .../llvm/Transforms/Utils/ValueMapper.h | 50 + final/include/llvm/Type.h | 564 + final/include/llvm/TypeSymbolTable.h | 152 + final/include/llvm/Use.h | 222 + final/include/llvm/User.h | 175 + final/include/llvm/Value.h | 409 + final/include/llvm/ValueSymbolTable.h | 133 + final/lib/Analysis/AliasAnalysis.cpp | 383 + final/lib/Analysis/AliasAnalysisCounter.cpp | 173 + final/lib/Analysis/AliasAnalysisEvaluator.cpp | 304 + final/lib/Analysis/AliasDebugger.cpp | 138 + final/lib/Analysis/AliasSetTracker.cpp | 648 + final/lib/Analysis/Analysis.cpp | 103 + final/lib/Analysis/BasicAliasAnalysis.cpp | 1170 + final/lib/Analysis/CFGPrinter.cpp | 165 + final/lib/Analysis/CMakeLists.txt | 59 + final/lib/Analysis/CaptureTracking.cpp | 147 + final/lib/Analysis/ConstantFolding.cpp | 1400 + final/lib/Analysis/DIBuilder.cpp | 801 + final/lib/Analysis/DbgInfoPrinter.cpp | 224 + final/lib/Analysis/DebugInfo.cpp | 948 + final/lib/Analysis/DomPrinter.cpp | 232 + final/lib/Analysis/DominanceFrontier.cpp | 137 + final/lib/Analysis/IPA/CMakeLists.txt | 7 + final/lib/Analysis/IPA/CallGraph.cpp | 340 + final/lib/Analysis/IPA/CallGraphSCCPass.cpp | 608 + final/lib/Analysis/IPA/FindUsedTypes.cpp | 103 + final/lib/Analysis/IPA/GlobalsModRef.cpp | 609 + final/lib/Analysis/IPA/IPA.cpp | 29 + final/lib/Analysis/IPA/Makefile | 15 + final/lib/Analysis/IVUsers.cpp | 263 + final/lib/Analysis/InlineCost.cpp | 648 + final/lib/Analysis/InstCount.cpp | 87 + final/lib/Analysis/InstructionSimplify.cpp | 2170 ++ final/lib/Analysis/Interval.cpp | 58 + final/lib/Analysis/IntervalPartition.cpp | 114 + final/lib/Analysis/LazyValueInfo.cpp | 1125 + final/lib/Analysis/LibCallAliasAnalysis.cpp | 137 + final/lib/Analysis/LibCallSemantics.cpp | 63 + final/lib/Analysis/Lint.cpp | 658 + final/lib/Analysis/Loads.cpp | 235 + final/lib/Analysis/LoopDependenceAnalysis.cpp | 358 + final/lib/Analysis/LoopInfo.cpp | 419 + final/lib/Analysis/LoopPass.cpp | 403 + final/lib/Analysis/Makefile | 16 + final/lib/Analysis/MemDepPrinter.cpp | 167 + final/lib/Analysis/MemoryBuiltins.cpp | 207 + .../lib/Analysis/MemoryDependenceAnalysis.cpp | 1324 + final/lib/Analysis/ModuleDebugInfoPrinter.cpp | 87 + final/lib/Analysis/NoAliasAnalysis.cpp | 88 + final/lib/Analysis/PHITransAddr.cpp | 441 + final/lib/Analysis/PathNumbering.cpp | 525 + final/lib/Analysis/PathProfileInfo.cpp | 434 + final/lib/Analysis/PathProfileVerifier.cpp | 207 + final/lib/Analysis/PostDominators.cpp | 102 + final/lib/Analysis/ProfileEstimatorPass.cpp | 426 + final/lib/Analysis/ProfileInfo.cpp | 1105 + final/lib/Analysis/ProfileInfoLoader.cpp | 158 + final/lib/Analysis/ProfileInfoLoaderPass.cpp | 267 + final/lib/Analysis/ProfileVerifierPass.cpp | 382 + final/lib/Analysis/README.txt | 30 + final/lib/Analysis/RegionInfo.cpp | 851 + final/lib/Analysis/RegionPass.cpp | 275 + final/lib/Analysis/RegionPrinter.cpp | 220 + final/lib/Analysis/ScalarEvolution.cpp | 6317 ++++ .../Analysis/ScalarEvolutionAliasAnalysis.cpp | 173 + .../lib/Analysis/ScalarEvolutionExpander.cpp | 1376 + .../Analysis/ScalarEvolutionNormalization.cpp | 183 + final/lib/Analysis/SparsePropagation.cpp | 347 + final/lib/Analysis/Trace.cpp | 51 + final/lib/Analysis/TypeBasedAliasAnalysis.cpp | 299 + final/lib/Analysis/ValueTracking.cpp | 1743 ++ final/lib/Archive/Archive.cpp | 261 + final/lib/Archive/ArchiveInternals.h | 89 + final/lib/Archive/ArchiveReader.cpp | 630 + final/lib/Archive/ArchiveWriter.cpp | 489 + final/lib/Archive/CMakeLists.txt | 5 + final/lib/Archive/Makefile | 17 + final/lib/AsmParser/CMakeLists.txt | 6 + final/lib/AsmParser/LLLexer.cpp | 874 + final/lib/AsmParser/LLLexer.h | 90 + final/lib/AsmParser/LLParser.cpp | 3976 +++ final/lib/AsmParser/LLParser.h | 378 + final/lib/AsmParser/LLToken.h | 148 + final/lib/AsmParser/Makefile | 14 + final/lib/AsmParser/Parser.cpp | 62 + final/lib/Bitcode/CMakeLists.txt | 2 + final/lib/Bitcode/Makefile | 14 + final/lib/Bitcode/Reader/BitReader.cpp | 88 + final/lib/Bitcode/Reader/BitcodeReader.cpp | 2690 ++ final/lib/Bitcode/Reader/BitcodeReader.h | 282 + final/lib/Bitcode/Reader/CMakeLists.txt | 4 + final/lib/Bitcode/Reader/Makefile | 15 + final/lib/Bitcode/Writer/BitWriter.cpp | 40 + final/lib/Bitcode/Writer/BitcodeWriter.cpp | 1672 ++ .../lib/Bitcode/Writer/BitcodeWriterPass.cpp | 41 + final/lib/Bitcode/Writer/CMakeLists.txt | 6 + final/lib/Bitcode/Writer/Makefile | 15 + final/lib/Bitcode/Writer/ValueEnumerator.cpp | 511 + final/lib/Bitcode/Writer/ValueEnumerator.h | 156 + final/lib/CMakeLists.txt | 14 + .../lib/CodeGen/AggressiveAntiDepBreaker.cpp | 963 + final/lib/CodeGen/AggressiveAntiDepBreaker.h | 184 + final/lib/CodeGen/AllocationOrder.cpp | 68 + final/lib/CodeGen/AllocationOrder.h | 56 + final/lib/CodeGen/Analysis.cpp | 303 + final/lib/CodeGen/AntiDepBreaker.h | 59 + final/lib/CodeGen/AsmPrinter/ARMException.cpp | 87 + final/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 1904 ++ .../CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 318 + .../AsmPrinter/AsmPrinterInlineAsm.cpp | 409 + final/lib/CodeGen/AsmPrinter/CMakeLists.txt | 13 + final/lib/CodeGen/AsmPrinter/DIE.cpp | 368 + final/lib/CodeGen/AsmPrinter/DIE.h | 434 + .../CodeGen/AsmPrinter/DwarfCFIException.cpp | 138 + final/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 3792 +++ final/lib/CodeGen/AsmPrinter/DwarfDebug.h | 602 + .../lib/CodeGen/AsmPrinter/DwarfException.cpp | 676 + final/lib/CodeGen/AsmPrinter/DwarfException.h | 274 + .../AsmPrinter/DwarfTableException.cpp | 349 + final/lib/CodeGen/AsmPrinter/Makefile | 13 + .../lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 166 + final/lib/CodeGen/BranchFolding.cpp | 1341 + final/lib/CodeGen/BranchFolding.h | 116 + final/lib/CodeGen/CMakeLists.txt | 99 + final/lib/CodeGen/CalcSpillWeights.cpp | 227 + final/lib/CodeGen/CallingConvLower.cpp | 177 + final/lib/CodeGen/CodeGen.cpp | 61 + final/lib/CodeGen/CodePlacementOpt.cpp | 425 + final/lib/CodeGen/CriticalAntiDepBreaker.cpp | 668 + final/lib/CodeGen/CriticalAntiDepBreaker.h | 106 + .../CodeGen/DeadMachineInstructionElim.cpp | 196 + final/lib/CodeGen/DwarfEHPrepare.cpp | 670 + final/lib/CodeGen/ELF.h | 227 + final/lib/CodeGen/ELFCodeEmitter.cpp | 205 + final/lib/CodeGen/ELFCodeEmitter.h | 78 + final/lib/CodeGen/ELFWriter.cpp | 1103 + final/lib/CodeGen/ELFWriter.h | 251 + final/lib/CodeGen/EdgeBundles.cpp | 86 + final/lib/CodeGen/ExpandISelPseudos.cpp | 82 + final/lib/CodeGen/GCMetadata.cpp | 213 + final/lib/CodeGen/GCMetadataPrinter.cpp | 27 + final/lib/CodeGen/GCStrategy.cpp | 416 + final/lib/CodeGen/IfConversion.cpp | 1528 + final/lib/CodeGen/InlineSpiller.cpp | 439 + final/lib/CodeGen/IntrinsicLowering.cpp | 564 + final/lib/CodeGen/LLVMTargetMachine.cpp | 453 + final/lib/CodeGen/LatencyPriorityQueue.cpp | 152 + final/lib/CodeGen/LiveDebugVariables.cpp | 711 + final/lib/CodeGen/LiveDebugVariables.h | 63 + final/lib/CodeGen/LiveInterval.cpp | 801 + final/lib/CodeGen/LiveIntervalAnalysis.cpp | 2162 ++ final/lib/CodeGen/LiveIntervalUnion.cpp | 315 + final/lib/CodeGen/LiveIntervalUnion.h | 258 + final/lib/CodeGen/LiveRangeEdit.cpp | 130 + final/lib/CodeGen/LiveRangeEdit.h | 135 + final/lib/CodeGen/LiveStackAnalysis.cpp | 82 + final/lib/CodeGen/LiveVariables.cpp | 772 + .../lib/CodeGen/LocalStackSlotAllocation.cpp | 359 + final/lib/CodeGen/LowerSubregs.cpp | 223 + final/lib/CodeGen/MachineBasicBlock.cpp | 692 + final/lib/CodeGen/MachineCSE.cpp | 531 + final/lib/CodeGen/MachineDominators.cpp | 59 + final/lib/CodeGen/MachineFunction.cpp | 752 + final/lib/CodeGen/MachineFunctionAnalysis.cpp | 58 + final/lib/CodeGen/MachineFunctionPass.cpp | 56 + .../CodeGen/MachineFunctionPrinterPass.cpp | 60 + final/lib/CodeGen/MachineInstr.cpp | 1671 ++ final/lib/CodeGen/MachineLICM.cpp | 1202 + final/lib/CodeGen/MachineLoopInfo.cpp | 83 + final/lib/CodeGen/MachineLoopRanges.cpp | 116 + final/lib/CodeGen/MachineModuleInfo.cpp | 567 + final/lib/CodeGen/MachineModuleInfoImpls.cpp | 45 + final/lib/CodeGen/MachinePassRegistry.cpp | 41 + final/lib/CodeGen/MachineRegisterInfo.cpp | 241 + final/lib/CodeGen/MachineSSAUpdater.cpp | 372 + final/lib/CodeGen/MachineSink.cpp | 607 + final/lib/CodeGen/MachineVerifier.cpp | 1216 + final/lib/CodeGen/Makefile | 22 + final/lib/CodeGen/ObjectCodeEmitter.cpp | 141 + final/lib/CodeGen/OcamlGC.cpp | 37 + final/lib/CodeGen/OptimizePHIs.cpp | 190 + final/lib/CodeGen/PHIElimination.cpp | 427 + final/lib/CodeGen/PHIEliminationUtils.cpp | 61 + final/lib/CodeGen/PHIEliminationUtils.h | 25 + final/lib/CodeGen/Passes.cpp | 68 + final/lib/CodeGen/PeepholeOptimizer.cpp | 372 + final/lib/CodeGen/PostRASchedulerList.cpp | 694 + final/lib/CodeGen/PreAllocSplitting.cpp | 1430 + final/lib/CodeGen/ProcessImplicitDefs.cpp | 298 + final/lib/CodeGen/PrologEpilogInserter.cpp | 850 + final/lib/CodeGen/PrologEpilogInserter.h | 177 + final/lib/CodeGen/PseudoSourceValue.cpp | 134 + final/lib/CodeGen/README.txt | 199 + final/lib/CodeGen/RegAllocBase.h | 182 + final/lib/CodeGen/RegAllocBasic.cpp | 537 + final/lib/CodeGen/RegAllocFast.cpp | 1076 + final/lib/CodeGen/RegAllocGreedy.cpp | 1286 + final/lib/CodeGen/RegAllocLinearScan.cpp | 1538 + final/lib/CodeGen/RegAllocPBQP.cpp | 720 + final/lib/CodeGen/RegisterCoalescer.cpp | 197 + final/lib/CodeGen/RegisterScavenging.cpp | 389 + final/lib/CodeGen/RenderMachineFunction.cpp | 1014 + final/lib/CodeGen/RenderMachineFunction.h | 338 + final/lib/CodeGen/ScheduleDAG.cpp | 595 + final/lib/CodeGen/ScheduleDAGEmit.cpp | 67 + final/lib/CodeGen/ScheduleDAGInstrs.cpp | 693 + final/lib/CodeGen/ScheduleDAGInstrs.h | 207 + final/lib/CodeGen/ScheduleDAGPrinter.cpp | 99 + .../CodeGen/ScoreboardHazardRecognizer.cpp | 243 + final/lib/CodeGen/SelectionDAG/CMakeLists.txt | 23 + .../lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 7641 +++++ final/lib/CodeGen/SelectionDAG/FastISel.cpp | 1251 + .../SelectionDAG/FunctionLoweringInfo.cpp | 477 + .../lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 897 + final/lib/CodeGen/SelectionDAG/InstrEmitter.h | 142 + .../lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 3577 +++ .../SelectionDAG/LegalizeFloatTypes.cpp | 1428 + .../SelectionDAG/LegalizeIntegerTypes.cpp | 2615 ++ .../CodeGen/SelectionDAG/LegalizeTypes.cpp | 1153 + .../lib/CodeGen/SelectionDAG/LegalizeTypes.h | 747 + .../SelectionDAG/LegalizeTypesGeneric.cpp | 480 + .../SelectionDAG/LegalizeVectorOps.cpp | 290 + .../SelectionDAG/LegalizeVectorTypes.cpp | 2585 ++ final/lib/CodeGen/SelectionDAG/Makefile | 13 + .../lib/CodeGen/SelectionDAG/SDNodeDbgValue.h | 114 + .../lib/CodeGen/SelectionDAG/SDNodeOrdering.h | 54 + .../CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 636 + .../CodeGen/SelectionDAG/ScheduleDAGList.cpp | 265 + .../SelectionDAG/ScheduleDAGRRList.cpp | 2715 ++ .../SelectionDAG/ScheduleDAGSDNodes.cpp | 763 + .../CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 151 + .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6623 +++++ .../SelectionDAG/SelectionDAGBuilder.cpp | 6484 +++++ .../SelectionDAG/SelectionDAGBuilder.h | 543 + .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 2783 ++ .../SelectionDAG/SelectionDAGPrinter.cpp | 302 + .../CodeGen/SelectionDAG/TargetLowering.cpp | 3214 ++ .../SelectionDAG/TargetSelectionDAGInfo.cpp | 23 + final/lib/CodeGen/ShadowStackGC.cpp | 451 + final/lib/CodeGen/ShrinkWrapping.cpp | 1152 + .../lib/CodeGen/SimpleRegisterCoalescing.cpp | 1789 ++ final/lib/CodeGen/SimpleRegisterCoalescing.h | 193 + final/lib/CodeGen/SjLjEHPrepare.cpp | 592 + final/lib/CodeGen/SlotIndexes.cpp | 181 + final/lib/CodeGen/SpillPlacement.cpp | 324 + final/lib/CodeGen/SpillPlacement.h | 113 + final/lib/CodeGen/Spiller.cpp | 243 + final/lib/CodeGen/Spiller.h | 56 + final/lib/CodeGen/SplitKit.cpp | 921 + final/lib/CodeGen/SplitKit.h | 346 + final/lib/CodeGen/Splitter.cpp | 827 + final/lib/CodeGen/Splitter.h | 101 + final/lib/CodeGen/StackProtector.cpp | 262 + final/lib/CodeGen/StackSlotColoring.cpp | 768 + final/lib/CodeGen/StrongPHIElimination.cpp | 829 + final/lib/CodeGen/TailDuplication.cpp | 658 + final/lib/CodeGen/TargetInstrInfoImpl.cpp | 449 + .../CodeGen/TargetLoweringObjectFileImpl.cpp | 1026 + .../lib/CodeGen/TwoAddressInstructionPass.cpp | 1527 + final/lib/CodeGen/UnreachableBlockElim.cpp | 212 + final/lib/CodeGen/VirtRegMap.cpp | 354 + final/lib/CodeGen/VirtRegMap.h | 523 + final/lib/CodeGen/VirtRegRewriter.cpp | 2604 ++ final/lib/CodeGen/VirtRegRewriter.h | 32 + final/lib/CompilerDriver/Action.cpp | 134 + final/lib/CompilerDriver/BuiltinOptions.cpp | 61 + final/lib/CompilerDriver/CMakeLists.txt | 10 + final/lib/CompilerDriver/CompilationGraph.cpp | 655 + final/lib/CompilerDriver/Main.cpp | 146 + final/lib/CompilerDriver/Makefile | 20 + final/lib/CompilerDriver/Tool.cpp | 95 + final/lib/ExecutionEngine/CMakeLists.txt | 8 + final/lib/ExecutionEngine/ExecutionEngine.cpp | 1103 + .../ExecutionEngineBindings.cpp | 254 + .../Interpreter/CMakeLists.txt | 17 + .../ExecutionEngine/Interpreter/Execution.cpp | 1350 + .../Interpreter/ExternalFunctions.cpp | 492 + .../Interpreter/Interpreter.cpp | 98 + .../ExecutionEngine/Interpreter/Interpreter.h | 242 + .../lib/ExecutionEngine/Interpreter/Makefile | 13 + final/lib/ExecutionEngine/JIT/CMakeLists.txt | 13 + final/lib/ExecutionEngine/JIT/Intercept.cpp | 161 + final/lib/ExecutionEngine/JIT/JIT.cpp | 843 + final/lib/ExecutionEngine/JIT/JIT.h | 237 + .../JIT/JITDebugRegisterer.cpp | 212 + .../ExecutionEngine/JIT/JITDebugRegisterer.h | 116 + .../ExecutionEngine/JIT/JITDwarfEmitter.cpp | 598 + .../lib/ExecutionEngine/JIT/JITDwarfEmitter.h | 73 + final/lib/ExecutionEngine/JIT/JITEmitter.cpp | 1305 + .../ExecutionEngine/JIT/JITMemoryManager.cpp | 727 + final/lib/ExecutionEngine/JIT/Makefile | 38 + .../JIT/OProfileJITEventListener.cpp | 192 + .../lib/ExecutionEngine/JIT/TargetSelect.cpp | 91 + .../lib/ExecutionEngine/MCJIT/CMakeLists.txt | 4 + final/lib/ExecutionEngine/MCJIT/MCJIT.cpp | 92 + final/lib/ExecutionEngine/MCJIT/MCJIT.h | 68 + final/lib/ExecutionEngine/MCJIT/Makefile | 13 + .../ExecutionEngine/MCJIT/TargetSelect.cpp | 91 + final/lib/ExecutionEngine/Makefile | 13 + final/lib/Linker/CMakeLists.txt | 6 + final/lib/Linker/LinkArchives.cpp | 198 + final/lib/Linker/LinkItems.cpp | 241 + final/lib/Linker/LinkModules.cpp | 1301 + final/lib/Linker/Linker.cpp | 174 + final/lib/Linker/Makefile | 15 + final/lib/MC/CMakeLists.txt | 40 + final/lib/MC/ELFObjectWriter.cpp | 1494 + final/lib/MC/ELFObjectWriter.h | 391 + final/lib/MC/MCAsmInfo.cpp | 108 + final/lib/MC/MCAsmInfoCOFF.cpp | 37 + final/lib/MC/MCAsmInfoDarwin.cpp | 59 + final/lib/MC/MCAsmStreamer.cpp | 974 + final/lib/MC/MCAssembler.cpp | 949 + final/lib/MC/MCCodeEmitter.cpp | 18 + final/lib/MC/MCContext.cpp | 312 + final/lib/MC/MCDisassembler.cpp | 14 + final/lib/MC/MCDisassembler/CMakeLists.txt | 7 + .../lib/MC/MCDisassembler/EDDisassembler.cpp | 402 + final/lib/MC/MCDisassembler/EDDisassembler.h | 273 + final/lib/MC/MCDisassembler/EDInfo.h | 73 + final/lib/MC/MCDisassembler/EDInst.cpp | 209 + final/lib/MC/MCDisassembler/EDInst.h | 182 + final/lib/MC/MCDisassembler/EDOperand.cpp | 293 + final/lib/MC/MCDisassembler/EDOperand.h | 91 + final/lib/MC/MCDisassembler/EDToken.cpp | 210 + final/lib/MC/MCDisassembler/EDToken.h | 139 + final/lib/MC/MCDisassembler/Makefile | 14 + final/lib/MC/MCDwarf.cpp | 814 + final/lib/MC/MCELF.cpp | 72 + final/lib/MC/MCELF.h | 35 + final/lib/MC/MCELFObjectTargetWriter.cpp | 23 + final/lib/MC/MCELFStreamer.cpp | 383 + final/lib/MC/MCELFStreamer.h | 268 + final/lib/MC/MCExpr.cpp | 556 + final/lib/MC/MCInst.cpp | 66 + final/lib/MC/MCInstPrinter.cpp | 26 + final/lib/MC/MCLabel.cpp | 21 + final/lib/MC/MCLoggingStreamer.cpp | 248 + final/lib/MC/MCMachOStreamer.cpp | 405 + final/lib/MC/MCMachObjectTargetWriter.cpp | 22 + final/lib/MC/MCNullStreamer.cpp | 104 + final/lib/MC/MCObjectStreamer.cpp | 270 + final/lib/MC/MCObjectWriter.cpp | 80 + final/lib/MC/MCParser/AsmLexer.cpp | 430 + final/lib/MC/MCParser/AsmParser.cpp | 2497 ++ final/lib/MC/MCParser/CMakeLists.txt | 11 + final/lib/MC/MCParser/COFFAsmParser.cpp | 144 + final/lib/MC/MCParser/DarwinAsmParser.cpp | 661 + final/lib/MC/MCParser/ELFAsmParser.cpp | 533 + final/lib/MC/MCParser/MCAsmLexer.cpp | 27 + final/lib/MC/MCParser/MCAsmParser.cpp | 44 + .../lib/MC/MCParser/MCAsmParserExtension.cpp | 22 + final/lib/MC/MCParser/Makefile | 15 + final/lib/MC/MCParser/TargetAsmParser.cpp | 19 + final/lib/MC/MCPureStreamer.cpp | 234 + final/lib/MC/MCSection.cpp | 22 + final/lib/MC/MCSectionCOFF.cpp | 84 + final/lib/MC/MCSectionELF.cpp | 150 + final/lib/MC/MCSectionMachO.cpp | 299 + final/lib/MC/MCStreamer.cpp | 315 + final/lib/MC/MCSymbol.cpp | 80 + final/lib/MC/MCValue.cpp | 36 + final/lib/MC/MachObjectWriter.cpp | 1598 + final/lib/MC/Makefile | 16 + final/lib/MC/TargetAsmBackend.cpp | 37 + final/lib/MC/WinCOFFObjectWriter.cpp | 877 + final/lib/MC/WinCOFFStreamer.cpp | 395 + final/lib/Makefile | 17 + final/lib/Object/CMakeLists.txt | 6 + final/lib/Object/COFFObjectFile.cpp | 375 + final/lib/Object/ELFObjectFile.cpp | 686 + final/lib/Object/MachOObject.cpp | 342 + final/lib/Object/Makefile | 14 + final/lib/Object/ObjectFile.cpp | 71 + final/lib/Support/APFloat.cpp | 3564 +++ final/lib/Support/APInt.cpp | 2904 ++ final/lib/Support/APSInt.cpp | 23 + final/lib/Support/Allocator.cpp | 180 + final/lib/Support/Atomic.cpp | 112 + final/lib/Support/CMakeLists.txt | 103 + final/lib/Support/COPYRIGHT.regex | 54 + final/lib/Support/CommandLine.cpp | 1295 + final/lib/Support/ConstantRange.cpp | 702 + final/lib/Support/CrashRecoveryContext.cpp | 230 + final/lib/Support/DAGDeltaAlgorithm.cpp | 357 + final/lib/Support/Debug.cpp | 134 + final/lib/Support/DeltaAlgorithm.cpp | 114 + final/lib/Support/Disassembler.cpp | 75 + final/lib/Support/Dwarf.cpp | 652 + final/lib/Support/DynamicLibrary.cpp | 170 + final/lib/Support/Errno.cpp | 74 + final/lib/Support/ErrorHandling.cpp | 100 + final/lib/Support/FileUtilities.cpp | 281 + final/lib/Support/FoldingSet.cpp | 421 + final/lib/Support/FormattedStream.cpp | 101 + final/lib/Support/GraphWriter.cpp | 200 + final/lib/Support/Host.cpp | 307 + final/lib/Support/IncludeFile.cpp | 20 + final/lib/Support/IntEqClasses.cpp | 70 + final/lib/Support/IntervalMap.cpp | 161 + final/lib/Support/IsInf.cpp | 49 + final/lib/Support/IsNAN.cpp | 33 + final/lib/Support/Makefile | 22 + final/lib/Support/ManagedStatic.cpp | 75 + final/lib/Support/Memory.cpp | 74 + final/lib/Support/MemoryBuffer.cpp | 298 + final/lib/Support/MemoryObject.cpp | 34 + final/lib/Support/Mutex.cpp | 157 + final/lib/Support/Path.cpp | 283 + final/lib/Support/PathV2.cpp | 774 + final/lib/Support/PluginLoader.cpp | 47 + final/lib/Support/PrettyStackTrace.cpp | 133 + final/lib/Support/Process.cpp | 33 + final/lib/Support/Program.cpp | 56 + final/lib/Support/README.txt.system | 43 + final/lib/Support/RWMutex.cpp | 157 + final/lib/Support/Regex.cpp | 168 + .../SearchForAddressOfSpecialSymbol.cpp | 73 + final/lib/Support/Signals.cpp | 34 + final/lib/Support/SmallPtrSet.cpp | 226 + final/lib/Support/SmallVector.cpp | 40 + final/lib/Support/SourceMgr.cpp | 230 + final/lib/Support/Statistic.cpp | 152 + final/lib/Support/StringExtras.cpp | 81 + final/lib/Support/StringMap.cpp | 215 + final/lib/Support/StringPool.cpp | 35 + final/lib/Support/StringRef.cpp | 415 + final/lib/Support/SystemUtils.cpp | 55 + final/lib/Support/TargetRegistry.cpp | 92 + final/lib/Support/ThreadLocal.cpp | 84 + final/lib/Support/Threading.cpp | 116 + final/lib/Support/TimeValue.cpp | 57 + final/lib/Support/Timer.cpp | 393 + final/lib/Support/ToolOutputFile.cpp | 43 + final/lib/Support/Triple.cpp | 640 + final/lib/Support/Twine.cpp | 160 + final/lib/Support/Unix/Host.inc | 97 + final/lib/Support/Unix/Memory.inc | 151 + final/lib/Support/Unix/Mutex.inc | 43 + final/lib/Support/Unix/Path.inc | 887 + final/lib/Support/Unix/PathV2.inc | 507 + final/lib/Support/Unix/Process.inc | 295 + final/lib/Support/Unix/Program.inc | 424 + final/lib/Support/Unix/README.txt | 16 + final/lib/Support/Unix/RWMutex.inc | 43 + final/lib/Support/Unix/Signals.inc | 303 + final/lib/Support/Unix/ThreadLocal.inc | 26 + final/lib/Support/Unix/TimeValue.inc | 56 + final/lib/Support/Unix/Unix.h | 87 + final/lib/Support/Unix/system_error.inc | 34 + final/lib/Support/Valgrind.cpp | 54 + final/lib/Support/Windows/DynamicLibrary.inc | 166 + final/lib/Support/Windows/Host.inc | 23 + final/lib/Support/Windows/Memory.inc | 73 + final/lib/Support/Windows/Mutex.inc | 58 + final/lib/Support/Windows/Path.inc | 931 + final/lib/Support/Windows/PathV2.inc | 750 + final/lib/Support/Windows/Process.inc | 222 + final/lib/Support/Windows/Program.inc | 403 + final/lib/Support/Windows/RWMutex.inc | 58 + final/lib/Support/Windows/Signals.inc | 328 + final/lib/Support/Windows/ThreadLocal.inc | 54 + final/lib/Support/Windows/TimeValue.inc | 51 + final/lib/Support/Windows/Windows.h | 120 + .../lib/Support/Windows/explicit_symbols.inc | 66 + final/lib/Support/Windows/system_error.inc | 142 + final/lib/Support/circular_raw_ostream.cpp | 45 + final/lib/Support/raw_os_ostream.cpp | 30 + final/lib/Support/raw_ostream.cpp | 763 + final/lib/Support/regcclass.h | 70 + final/lib/Support/regcname.h | 139 + final/lib/Support/regcomp.c | 1525 + final/lib/Support/regengine.inc | 1034 + final/lib/Support/regerror.c | 135 + final/lib/Support/regex2.h | 157 + final/lib/Support/regex_impl.h | 108 + final/lib/Support/regexec.c | 162 + final/lib/Support/regfree.c | 72 + final/lib/Support/regstrlcpy.c | 52 + final/lib/Support/regutils.h | 53 + final/lib/Support/system_error.cpp | 130 + final/lib/Target/ARM/ARM.h | 63 + final/lib/Target/ARM/ARM.td | 215 + final/lib/Target/ARM/ARMAddressingModes.h | 585 + final/lib/Target/ARM/ARMAsmBackend.cpp | 512 + final/lib/Target/ARM/ARMAsmPrinter.cpp | 1725 ++ final/lib/Target/ARM/ARMAsmPrinter.h | 114 + final/lib/Target/ARM/ARMBaseInfo.h | 249 + final/lib/Target/ARM/ARMBaseInstrInfo.cpp | 2331 ++ final/lib/Target/ARM/ARMBaseInstrInfo.h | 528 + final/lib/Target/ARM/ARMBaseRegisterInfo.cpp | 1248 + final/lib/Target/ARM/ARMBaseRegisterInfo.h | 209 + final/lib/Target/ARM/ARMBuildAttrs.h | 131 + final/lib/Target/ARM/ARMCallingConv.h | 160 + final/lib/Target/ARM/ARMCallingConv.td | 164 + final/lib/Target/ARM/ARMCodeEmitter.cpp | 1887 ++ .../lib/Target/ARM/ARMConstantIslandPass.cpp | 1900 ++ final/lib/Target/ARM/ARMConstantPoolValue.cpp | 130 + final/lib/Target/ARM/ARMConstantPoolValue.h | 122 + final/lib/Target/ARM/ARMELFWriterInfo.cpp | 83 + final/lib/Target/ARM/ARMELFWriterInfo.h | 58 + final/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 1241 + final/lib/Target/ARM/ARMFastISel.cpp | 1920 ++ final/lib/Target/ARM/ARMFixupKinds.h | 97 + final/lib/Target/ARM/ARMFrameLowering.cpp | 1041 + final/lib/Target/ARM/ARMFrameLowering.h | 75 + final/lib/Target/ARM/ARMGlobalMerge.cpp | 223 + final/lib/Target/ARM/ARMHazardRecognizer.cpp | 118 + final/lib/Target/ARM/ARMHazardRecognizer.h | 54 + final/lib/Target/ARM/ARMISelDAGToDAG.cpp | 2869 ++ final/lib/Target/ARM/ARMISelLowering.cpp | 7055 +++++ final/lib/Target/ARM/ARMISelLowering.h | 490 + final/lib/Target/ARM/ARMInstrFormats.td | 1815 ++ final/lib/Target/ARM/ARMInstrInfo.cpp | 61 + final/lib/Target/ARM/ARMInstrInfo.h | 44 + final/lib/Target/ARM/ARMInstrInfo.td | 3940 +++ final/lib/Target/ARM/ARMInstrNEON.td | 4852 ++++ final/lib/Target/ARM/ARMInstrThumb.td | 1550 + final/lib/Target/ARM/ARMInstrThumb2.td | 3432 +++ final/lib/Target/ARM/ARMInstrVFP.td | 1113 + final/lib/Target/ARM/ARMJITInfo.cpp | 336 + final/lib/Target/ARM/ARMJITInfo.h | 183 + .../lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 1838 ++ final/lib/Target/ARM/ARMMCAsmInfo.cpp | 80 + final/lib/Target/ARM/ARMMCAsmInfo.h | 31 + final/lib/Target/ARM/ARMMCCodeEmitter.cpp | 1263 + final/lib/Target/ARM/ARMMCExpr.cpp | 73 + final/lib/Target/ARM/ARMMCExpr.h | 73 + final/lib/Target/ARM/ARMMCInstLower.cpp | 115 + final/lib/Target/ARM/ARMMachineFunctionInfo.h | 250 + final/lib/Target/ARM/ARMPerfectShuffle.h | 6586 +++++ final/lib/Target/ARM/ARMRegisterInfo.cpp | 40 + final/lib/Target/ARM/ARMRegisterInfo.h | 33 + final/lib/Target/ARM/ARMRegisterInfo.td | 559 + final/lib/Target/ARM/ARMRelocations.h | 62 + final/lib/Target/ARM/ARMSchedule.td | 261 + final/lib/Target/ARM/ARMScheduleA8.td | 1034 + final/lib/Target/ARM/ARMScheduleA9.td | 1824 ++ final/lib/Target/ARM/ARMScheduleV6.td | 294 + final/lib/Target/ARM/ARMSelectionDAGInfo.cpp | 134 + final/lib/Target/ARM/ARMSelectionDAGInfo.h | 42 + final/lib/Target/ARM/ARMSubtarget.cpp | 254 + final/lib/Target/ARM/ARMSubtarget.h | 234 + final/lib/Target/ARM/ARMTargetMachine.cpp | 202 + final/lib/Target/ARM/ARMTargetMachine.h | 143 + final/lib/Target/ARM/ARMTargetObjectFile.cpp | 47 + final/lib/Target/ARM/ARMTargetObjectFile.h | 38 + .../lib/Target/ARM/AsmParser/ARMAsmLexer.cpp | 152 + .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1866 ++ final/lib/Target/ARM/AsmParser/CMakeLists.txt | 7 + final/lib/Target/ARM/AsmParser/Makefile | 15 + final/lib/Target/ARM/CMakeLists.txt | 69 + .../ARM/Disassembler/ARMDisassembler.cpp | 548 + .../Target/ARM/Disassembler/ARMDisassembler.h | 99 + .../ARM/Disassembler/ARMDisassemblerCore.cpp | 3247 +++ .../ARM/Disassembler/ARMDisassemblerCore.h | 262 + .../Target/ARM/Disassembler/CMakeLists.txt | 14 + final/lib/Target/ARM/Disassembler/Makefile | 16 + .../ARM/Disassembler/ThumbDisassemblerCore.h | 2251 ++ .../Target/ARM/InstPrinter/ARMInstPrinter.cpp | 714 + .../Target/ARM/InstPrinter/ARMInstPrinter.h | 112 + .../lib/Target/ARM/InstPrinter/CMakeLists.txt | 6 + final/lib/Target/ARM/InstPrinter/Makefile | 15 + final/lib/Target/ARM/MLxExpansionPass.cpp | 315 + final/lib/Target/ARM/Makefile | 25 + final/lib/Target/ARM/NEONMoveFix.cpp | 148 + final/lib/Target/ARM/README-Thumb.txt | 267 + final/lib/Target/ARM/README-Thumb2.txt | 6 + final/lib/Target/ARM/README.txt | 683 + .../Target/ARM/TargetInfo/ARMTargetInfo.cpp | 23 + .../lib/Target/ARM/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/ARM/TargetInfo/Makefile | 15 + final/lib/Target/ARM/Thumb1FrameLowering.cpp | 358 + final/lib/Target/ARM/Thumb1FrameLowering.h | 52 + final/lib/Target/ARM/Thumb1InstrInfo.cpp | 111 + final/lib/Target/ARM/Thumb1InstrInfo.h | 59 + final/lib/Target/ARM/Thumb1RegisterInfo.cpp | 705 + final/lib/Target/ARM/Thumb1RegisterInfo.h | 64 + final/lib/Target/ARM/Thumb2ITBlockPass.cpp | 255 + final/lib/Target/ARM/Thumb2InstrInfo.cpp | 625 + final/lib/Target/ARM/Thumb2InstrInfo.h | 78 + final/lib/Target/ARM/Thumb2RegisterInfo.cpp | 63 + final/lib/Target/ARM/Thumb2RegisterInfo.h | 43 + final/lib/Target/ARM/Thumb2SizeReduction.cpp | 779 + final/lib/Target/Alpha/Alpha.h | 53 + final/lib/Target/Alpha/Alpha.td | 68 + final/lib/Target/Alpha/AlphaAsmPrinter.cpp | 166 + .../lib/Target/Alpha/AlphaBranchSelector.cpp | 66 + final/lib/Target/Alpha/AlphaCallingConv.td | 38 + final/lib/Target/Alpha/AlphaFrameLowering.cpp | 143 + final/lib/Target/Alpha/AlphaFrameLowering.h | 43 + final/lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 426 + final/lib/Target/Alpha/AlphaISelLowering.cpp | 973 + final/lib/Target/Alpha/AlphaISelLowering.h | 145 + final/lib/Target/Alpha/AlphaInstrFormats.td | 268 + final/lib/Target/Alpha/AlphaInstrInfo.cpp | 379 + final/lib/Target/Alpha/AlphaInstrInfo.h | 82 + final/lib/Target/Alpha/AlphaInstrInfo.td | 1157 + final/lib/Target/Alpha/AlphaLLRP.cpp | 158 + final/lib/Target/Alpha/AlphaMCAsmInfo.cpp | 23 + final/lib/Target/Alpha/AlphaMCAsmInfo.h | 29 + .../Target/Alpha/AlphaMachineFunctionInfo.h | 62 + final/lib/Target/Alpha/AlphaRegisterInfo.cpp | 207 + final/lib/Target/Alpha/AlphaRegisterInfo.h | 57 + final/lib/Target/Alpha/AlphaRegisterInfo.td | 171 + final/lib/Target/Alpha/AlphaRelocations.h | 31 + final/lib/Target/Alpha/AlphaSchedule.td | 85 + .../Target/Alpha/AlphaSelectionDAGInfo.cpp | 23 + .../lib/Target/Alpha/AlphaSelectionDAGInfo.h | 31 + final/lib/Target/Alpha/AlphaSubtarget.cpp | 25 + final/lib/Target/Alpha/AlphaSubtarget.h | 46 + final/lib/Target/Alpha/AlphaTargetMachine.cpp | 54 + final/lib/Target/Alpha/AlphaTargetMachine.h | 65 + final/lib/Target/Alpha/CMakeLists.txt | 28 + final/lib/Target/Alpha/Makefile | 23 + final/lib/Target/Alpha/README.txt | 42 + .../Alpha/TargetInfo/AlphaTargetInfo.cpp | 20 + .../Target/Alpha/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/Alpha/TargetInfo/Makefile | 15 + final/lib/Target/Blackfin/Blackfin.h | 38 + final/lib/Target/Blackfin/Blackfin.td | 202 + .../Target/Blackfin/BlackfinAsmPrinter.cpp | 156 + .../Target/Blackfin/BlackfinCallingConv.td | 30 + .../Target/Blackfin/BlackfinFrameLowering.cpp | 124 + .../Target/Blackfin/BlackfinFrameLowering.h | 46 + .../Target/Blackfin/BlackfinISelDAGToDAG.cpp | 180 + .../Target/Blackfin/BlackfinISelLowering.cpp | 664 + .../Target/Blackfin/BlackfinISelLowering.h | 87 + .../Target/Blackfin/BlackfinInstrFormats.td | 34 + .../lib/Target/Blackfin/BlackfinInstrInfo.cpp | 253 + final/lib/Target/Blackfin/BlackfinInstrInfo.h | 78 + .../lib/Target/Blackfin/BlackfinInstrInfo.td | 862 + .../Target/Blackfin/BlackfinIntrinsicInfo.cpp | 104 + .../Target/Blackfin/BlackfinIntrinsicInfo.h | 32 + .../lib/Target/Blackfin/BlackfinIntrinsics.td | 34 + .../lib/Target/Blackfin/BlackfinMCAsmInfo.cpp | 22 + final/lib/Target/Blackfin/BlackfinMCAsmInfo.h | 29 + .../Target/Blackfin/BlackfinRegisterInfo.cpp | 355 + .../Target/Blackfin/BlackfinRegisterInfo.h | 80 + .../Target/Blackfin/BlackfinRegisterInfo.td | 365 + .../Blackfin/BlackfinSelectionDAGInfo.cpp | 24 + .../Blackfin/BlackfinSelectionDAGInfo.h | 31 + .../lib/Target/Blackfin/BlackfinSubtarget.cpp | 36 + final/lib/Target/Blackfin/BlackfinSubtarget.h | 45 + .../Target/Blackfin/BlackfinTargetMachine.cpp | 43 + .../Target/Blackfin/BlackfinTargetMachine.h | 67 + final/lib/Target/Blackfin/CMakeLists.txt | 28 + final/lib/Target/Blackfin/Makefile | 24 + final/lib/Target/Blackfin/README.txt | 244 + .../TargetInfo/BlackfinTargetInfo.cpp | 21 + .../Target/Blackfin/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/Blackfin/TargetInfo/Makefile | 15 + final/lib/Target/CBackend/CBackend.cpp | 3591 +++ final/lib/Target/CBackend/CMakeLists.txt | 5 + final/lib/Target/CBackend/CTargetMachine.h | 40 + final/lib/Target/CBackend/Makefile | 16 + .../TargetInfo/CBackendTargetInfo.cpp | 19 + .../Target/CBackend/TargetInfo/CMakeLists.txt | 6 + final/lib/Target/CBackend/TargetInfo/Makefile | 15 + final/lib/Target/CMakeLists.txt | 57 + final/lib/Target/CellSPU/CMakeLists.txt | 29 + final/lib/Target/CellSPU/CellSDKIntrinsics.td | 449 + final/lib/Target/CellSPU/Makefile | 21 + final/lib/Target/CellSPU/README.txt | 92 + final/lib/Target/CellSPU/SPU.h | 35 + final/lib/Target/CellSPU/SPU.td | 66 + final/lib/Target/CellSPU/SPU128InstrInfo.td | 41 + final/lib/Target/CellSPU/SPU64InstrInfo.td | 408 + final/lib/Target/CellSPU/SPUAsmPrinter.cpp | 334 + final/lib/Target/CellSPU/SPUCallingConv.td | 57 + final/lib/Target/CellSPU/SPUFrameLowering.cpp | 276 + final/lib/Target/CellSPU/SPUFrameLowering.h | 94 + .../Target/CellSPU/SPUHazardRecognizers.cpp | 141 + .../lib/Target/CellSPU/SPUHazardRecognizers.h | 41 + final/lib/Target/CellSPU/SPUISelDAGToDAG.cpp | 1204 + final/lib/Target/CellSPU/SPUISelLowering.cpp | 3258 +++ final/lib/Target/CellSPU/SPUISelLowering.h | 189 + final/lib/Target/CellSPU/SPUInstrBuilder.h | 43 + final/lib/Target/CellSPU/SPUInstrFormats.td | 320 + final/lib/Target/CellSPU/SPUInstrInfo.cpp | 449 + final/lib/Target/CellSPU/SPUInstrInfo.h | 81 + final/lib/Target/CellSPU/SPUInstrInfo.td | 4482 +++ final/lib/Target/CellSPU/SPUMCAsmInfo.cpp | 39 + final/lib/Target/CellSPU/SPUMCAsmInfo.h | 28 + final/lib/Target/CellSPU/SPUMachineFunction.h | 49 + final/lib/Target/CellSPU/SPUMathInstr.td | 97 + final/lib/Target/CellSPU/SPUNodes.td | 159 + final/lib/Target/CellSPU/SPUNopFiller.cpp | 153 + final/lib/Target/CellSPU/SPUOperands.td | 664 + final/lib/Target/CellSPU/SPURegisterInfo.cpp | 371 + final/lib/Target/CellSPU/SPURegisterInfo.h | 104 + final/lib/Target/CellSPU/SPURegisterInfo.td | 429 + final/lib/Target/CellSPU/SPURegisterNames.h | 18 + final/lib/Target/CellSPU/SPUSchedule.td | 59 + .../Target/CellSPU/SPUSelectionDAGInfo.cpp | 23 + .../lib/Target/CellSPU/SPUSelectionDAGInfo.h | 31 + final/lib/Target/CellSPU/SPUSubtarget.cpp | 57 + final/lib/Target/CellSPU/SPUSubtarget.h | 94 + final/lib/Target/CellSPU/SPUTargetMachine.cpp | 70 + final/lib/Target/CellSPU/SPUTargetMachine.h | 90 + .../Target/CellSPU/TargetInfo/CMakeLists.txt | 7 + .../CellSPU/TargetInfo/CellSPUTargetInfo.cpp | 20 + final/lib/Target/CellSPU/TargetInfo/Makefile | 15 + final/lib/Target/CppBackend/CMakeLists.txt | 5 + final/lib/Target/CppBackend/CPPBackend.cpp | 2056 ++ .../lib/Target/CppBackend/CPPTargetMachine.h | 43 + final/lib/Target/CppBackend/Makefile | 16 + .../CppBackend/TargetInfo/CMakeLists.txt | 6 + .../TargetInfo/CppBackendTargetInfo.cpp | 26 + .../lib/Target/CppBackend/TargetInfo/Makefile | 15 + .../Target/MBlaze/AsmParser/CMakeLists.txt | 8 + .../MBlaze/AsmParser/MBlazeAsmLexer.cpp | 127 + .../MBlaze/AsmParser/MBlazeAsmParser.cpp | 568 + final/lib/Target/MBlaze/AsmParser/Makefile | 15 + final/lib/Target/MBlaze/CMakeLists.txt | 40 + .../Target/MBlaze/Disassembler/CMakeLists.txt | 16 + .../Disassembler/MBlazeDisassembler.cpp | 647 + .../MBlaze/Disassembler/MBlazeDisassembler.h | 55 + final/lib/Target/MBlaze/Disassembler/Makefile | 16 + .../Target/MBlaze/InstPrinter/CMakeLists.txt | 8 + .../MBlaze/InstPrinter/MBlazeInstPrinter.cpp | 69 + .../MBlaze/InstPrinter/MBlazeInstPrinter.h | 43 + final/lib/Target/MBlaze/InstPrinter/Makefile | 16 + final/lib/Target/MBlaze/MBlaze.h | 47 + final/lib/Target/MBlaze/MBlaze.td | 94 + final/lib/Target/MBlaze/MBlazeAsmBackend.cpp | 163 + final/lib/Target/MBlaze/MBlazeAsmPrinter.cpp | 335 + final/lib/Target/MBlaze/MBlazeCallingConv.td | 28 + .../Target/MBlaze/MBlazeDelaySlotFiller.cpp | 258 + .../lib/Target/MBlaze/MBlazeELFWriterInfo.cpp | 111 + final/lib/Target/MBlaze/MBlazeELFWriterInfo.h | 58 + .../lib/Target/MBlaze/MBlazeFrameLowering.cpp | 450 + final/lib/Target/MBlaze/MBlazeFrameLowering.h | 53 + .../lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp | 277 + .../lib/Target/MBlaze/MBlazeISelLowering.cpp | 1171 + final/lib/Target/MBlaze/MBlazeISelLowering.h | 190 + final/lib/Target/MBlaze/MBlazeInstrFPU.td | 224 + final/lib/Target/MBlaze/MBlazeInstrFSL.td | 229 + final/lib/Target/MBlaze/MBlazeInstrFormats.td | 204 + final/lib/Target/MBlaze/MBlazeInstrInfo.cpp | 291 + final/lib/Target/MBlaze/MBlazeInstrInfo.h | 294 + final/lib/Target/MBlaze/MBlazeInstrInfo.td | 881 + .../lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp | 113 + final/lib/Target/MBlaze/MBlazeIntrinsicInfo.h | 33 + final/lib/Target/MBlaze/MBlazeIntrinsics.td | 131 + final/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp | 22 + final/lib/Target/MBlaze/MBlazeMCAsmInfo.h | 30 + .../lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp | 223 + final/lib/Target/MBlaze/MBlazeMCInstLower.cpp | 166 + final/lib/Target/MBlaze/MBlazeMCInstLower.h | 50 + .../lib/Target/MBlaze/MBlazeMachineFunction.h | 170 + .../lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 340 + final/lib/Target/MBlaze/MBlazeRegisterInfo.h | 80 + final/lib/Target/MBlaze/MBlazeRegisterInfo.td | 190 + final/lib/Target/MBlaze/MBlazeRelocations.h | 47 + final/lib/Target/MBlaze/MBlazeSchedule.td | 64 + .../Target/MBlaze/MBlazeSelectionDAGInfo.cpp | 23 + .../Target/MBlaze/MBlazeSelectionDAGInfo.h | 31 + final/lib/Target/MBlaze/MBlazeSubtarget.cpp | 31 + final/lib/Target/MBlaze/MBlazeSubtarget.h | 79 + .../lib/Target/MBlaze/MBlazeTargetMachine.cpp | 114 + final/lib/Target/MBlaze/MBlazeTargetMachine.h | 79 + .../Target/MBlaze/MBlazeTargetObjectFile.cpp | 90 + .../Target/MBlaze/MBlazeTargetObjectFile.h | 40 + final/lib/Target/MBlaze/Makefile | 25 + final/lib/Target/MBlaze/TODO | 26 + .../Target/MBlaze/TargetInfo/CMakeLists.txt | 8 + .../MBlaze/TargetInfo/MBlazeTargetInfo.cpp | 19 + final/lib/Target/MBlaze/TargetInfo/Makefile | 15 + final/lib/Target/MSP430/CMakeLists.txt | 29 + .../Target/MSP430/InstPrinter/CMakeLists.txt | 6 + .../MSP430/InstPrinter/MSP430InstPrinter.cpp | 113 + .../MSP430/InstPrinter/MSP430InstPrinter.h | 43 + final/lib/Target/MSP430/InstPrinter/Makefile | 15 + final/lib/Target/MSP430/MSP430.h | 55 + final/lib/Target/MSP430/MSP430.td | 66 + final/lib/Target/MSP430/MSP430AsmPrinter.cpp | 179 + .../Target/MSP430/MSP430BranchSelector.cpp | 180 + final/lib/Target/MSP430/MSP430CallingConv.td | 37 + .../lib/Target/MSP430/MSP430FrameLowering.cpp | 223 + final/lib/Target/MSP430/MSP430FrameLowering.h | 53 + .../lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 492 + .../lib/Target/MSP430/MSP430ISelLowering.cpp | 1199 + final/lib/Target/MSP430/MSP430ISelLowering.h | 185 + final/lib/Target/MSP430/MSP430InstrFormats.td | 211 + final/lib/Target/MSP430/MSP430InstrInfo.cpp | 333 + final/lib/Target/MSP430/MSP430InstrInfo.h | 89 + final/lib/Target/MSP430/MSP430InstrInfo.td | 1211 + final/lib/Target/MSP430/MSP430MCAsmInfo.cpp | 26 + final/lib/Target/MSP430/MSP430MCAsmInfo.h | 29 + final/lib/Target/MSP430/MSP430MCInstLower.cpp | 150 + final/lib/Target/MSP430/MSP430MCInstLower.h | 50 + .../Target/MSP430/MSP430MachineFunctionInfo.h | 46 + .../lib/Target/MSP430/MSP430RegisterInfo.cpp | 245 + final/lib/Target/MSP430/MSP430RegisterInfo.h | 61 + final/lib/Target/MSP430/MSP430RegisterInfo.td | 119 + .../Target/MSP430/MSP430SelectionDAGInfo.cpp | 23 + .../Target/MSP430/MSP430SelectionDAGInfo.h | 31 + final/lib/Target/MSP430/MSP430Subtarget.cpp | 25 + final/lib/Target/MSP430/MSP430Subtarget.h | 38 + .../lib/Target/MSP430/MSP430TargetMachine.cpp | 52 + final/lib/Target/MSP430/MSP430TargetMachine.h | 69 + final/lib/Target/MSP430/Makefile | 24 + final/lib/Target/MSP430/README.txt | 40 + .../Target/MSP430/TargetInfo/CMakeLists.txt | 7 + .../MSP430/TargetInfo/MSP430TargetInfo.cpp | 20 + final/lib/Target/MSP430/TargetInfo/Makefile | 15 + final/lib/Target/Makefile | 20 + final/lib/Target/Mangler.cpp | 235 + final/lib/Target/Mips/CMakeLists.txt | 28 + final/lib/Target/Mips/Makefile | 24 + final/lib/Target/Mips/Mips.h | 41 + final/lib/Target/Mips/Mips.td | 93 + final/lib/Target/Mips/MipsAsmPrinter.cpp | 399 + final/lib/Target/Mips/MipsCallingConv.td | 86 + final/lib/Target/Mips/MipsDelaySlotFiller.cpp | 82 + final/lib/Target/Mips/MipsFrameLowering.cpp | 390 + final/lib/Target/Mips/MipsFrameLowering.h | 48 + final/lib/Target/Mips/MipsISelDAGToDAG.cpp | 525 + final/lib/Target/Mips/MipsISelLowering.cpp | 1654 ++ final/lib/Target/Mips/MipsISelLowering.h | 174 + final/lib/Target/Mips/MipsInstrFPU.td | 316 + final/lib/Target/Mips/MipsInstrFormats.td | 182 + final/lib/Target/Mips/MipsInstrInfo.cpp | 522 + final/lib/Target/Mips/MipsInstrInfo.h | 235 + final/lib/Target/Mips/MipsInstrInfo.td | 681 + final/lib/Target/Mips/MipsMCAsmInfo.cpp | 27 + final/lib/Target/Mips/MipsMCAsmInfo.h | 30 + final/lib/Target/Mips/MipsMachineFunction.h | 147 + final/lib/Target/Mips/MipsRegisterInfo.cpp | 258 + final/lib/Target/Mips/MipsRegisterInfo.h | 70 + final/lib/Target/Mips/MipsRegisterInfo.td | 264 + final/lib/Target/Mips/MipsSchedule.td | 63 + .../lib/Target/Mips/MipsSelectionDAGInfo.cpp | 23 + final/lib/Target/Mips/MipsSelectionDAGInfo.h | 31 + final/lib/Target/Mips/MipsSubtarget.cpp | 51 + final/lib/Target/Mips/MipsSubtarget.h | 125 + final/lib/Target/Mips/MipsTargetMachine.cpp | 77 + final/lib/Target/Mips/MipsTargetMachine.h | 78 + .../lib/Target/Mips/MipsTargetObjectFile.cpp | 102 + final/lib/Target/Mips/MipsTargetObjectFile.h | 41 + .../lib/Target/Mips/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/Mips/TargetInfo/Makefile | 15 + .../Target/Mips/TargetInfo/MipsTargetInfo.cpp | 21 + final/lib/Target/PTX/CMakeLists.txt | 26 + final/lib/Target/PTX/Makefile | 26 + final/lib/Target/PTX/PTX.h | 49 + final/lib/Target/PTX/PTX.td | 83 + final/lib/Target/PTX/PTXAsmPrinter.cpp | 402 + final/lib/Target/PTX/PTXFrameLowering.cpp | 24 + final/lib/Target/PTX/PTXFrameLowering.h | 44 + final/lib/Target/PTX/PTXISelDAGToDAG.cpp | 180 + final/lib/Target/PTX/PTXISelLowering.cpp | 239 + final/lib/Target/PTX/PTXISelLowering.h | 67 + final/lib/Target/PTX/PTXInstrFormats.td | 24 + final/lib/Target/PTX/PTXInstrInfo.cpp | 97 + final/lib/Target/PTX/PTXInstrInfo.h | 75 + final/lib/Target/PTX/PTXInstrInfo.td | 396 + final/lib/Target/PTX/PTXIntrinsicInstrInfo.td | 35 + final/lib/Target/PTX/PTXMCAsmInfo.cpp | 30 + final/lib/Target/PTX/PTXMCAsmInfo.h | 28 + final/lib/Target/PTX/PTXMCAsmStreamer.cpp | 543 + final/lib/Target/PTX/PTXMFInfoExtract.cpp | 96 + final/lib/Target/PTX/PTXMachineFunctionInfo.h | 82 + final/lib/Target/PTX/PTXRegisterInfo.cpp | 19 + final/lib/Target/PTX/PTXRegisterInfo.h | 63 + final/lib/Target/PTX/PTXRegisterInfo.td | 271 + final/lib/Target/PTX/PTXSubtarget.cpp | 46 + final/lib/Target/PTX/PTXSubtarget.h | 62 + final/lib/Target/PTX/PTXTargetMachine.cpp | 71 + final/lib/Target/PTX/PTXTargetMachine.h | 60 + .../lib/Target/PTX/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/PTX/TargetInfo/Makefile | 15 + .../Target/PTX/TargetInfo/PTXTargetInfo.cpp | 21 + final/lib/Target/PowerPC/CMakeLists.txt | 37 + .../Target/PowerPC/InstPrinter/CMakeLists.txt | 6 + final/lib/Target/PowerPC/InstPrinter/Makefile | 16 + .../PowerPC/InstPrinter/PPCInstPrinter.cpp | 292 + .../PowerPC/InstPrinter/PPCInstPrinter.h | 69 + final/lib/Target/PowerPC/Makefile | 24 + final/lib/Target/PowerPC/PPC.h | 93 + final/lib/Target/PowerPC/PPC.td | 112 + final/lib/Target/PowerPC/PPCAsmBackend.cpp | 119 + final/lib/Target/PowerPC/PPCAsmPrinter.cpp | 696 + .../lib/Target/PowerPC/PPCBranchSelector.cpp | 174 + final/lib/Target/PowerPC/PPCCallingConv.td | 132 + final/lib/Target/PowerPC/PPCCodeEmitter.cpp | 261 + final/lib/Target/PowerPC/PPCFixupKinds.h | 45 + final/lib/Target/PowerPC/PPCFrameLowering.cpp | 971 + final/lib/Target/PowerPC/PPCFrameLowering.h | 322 + .../Target/PowerPC/PPCHazardRecognizers.cpp | 308 + .../lib/Target/PowerPC/PPCHazardRecognizers.h | 73 + final/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 1077 + final/lib/Target/PowerPC/PPCISelLowering.cpp | 5634 ++++ final/lib/Target/PowerPC/PPCISelLowering.h | 489 + final/lib/Target/PowerPC/PPCInstr64Bit.td | 744 + final/lib/Target/PowerPC/PPCInstrAltivec.td | 695 + final/lib/Target/PowerPC/PPCInstrBuilder.h | 43 + final/lib/Target/PowerPC/PPCInstrFormats.td | 907 + final/lib/Target/PowerPC/PPCInstrInfo.cpp | 651 + final/lib/Target/PowerPC/PPCInstrInfo.h | 146 + final/lib/Target/PowerPC/PPCInstrInfo.td | 1477 + final/lib/Target/PowerPC/PPCJITInfo.cpp | 446 + final/lib/Target/PowerPC/PPCJITInfo.h | 49 + final/lib/Target/PowerPC/PPCMCAsmInfo.cpp | 58 + final/lib/Target/PowerPC/PPCMCAsmInfo.h | 31 + final/lib/Target/PowerPC/PPCMCCodeEmitter.cpp | 195 + final/lib/Target/PowerPC/PPCMCInstLower.cpp | 172 + .../Target/PowerPC/PPCMachineFunctionInfo.h | 132 + final/lib/Target/PowerPC/PPCPerfectShuffle.h | 6586 +++++ final/lib/Target/PowerPC/PPCPredicates.cpp | 31 + final/lib/Target/PowerPC/PPCPredicates.h | 39 + final/lib/Target/PowerPC/PPCRegisterInfo.cpp | 694 + final/lib/Target/PowerPC/PPCRegisterInfo.h | 75 + final/lib/Target/PowerPC/PPCRegisterInfo.td | 389 + final/lib/Target/PowerPC/PPCRelocations.h | 56 + final/lib/Target/PowerPC/PPCSchedule.td | 505 + final/lib/Target/PowerPC/PPCScheduleG3.td | 64 + final/lib/Target/PowerPC/PPCScheduleG4.td | 74 + final/lib/Target/PowerPC/PPCScheduleG4Plus.td | 80 + final/lib/Target/PowerPC/PPCScheduleG5.td | 84 + .../Target/PowerPC/PPCSelectionDAGInfo.cpp | 23 + .../lib/Target/PowerPC/PPCSelectionDAGInfo.h | 31 + final/lib/Target/PowerPC/PPCSubtarget.cpp | 142 + final/lib/Target/PowerPC/PPCSubtarget.h | 151 + final/lib/Target/PowerPC/PPCTargetMachine.cpp | 147 + final/lib/Target/PowerPC/PPCTargetMachine.h | 93 + final/lib/Target/PowerPC/README.txt | 939 + final/lib/Target/PowerPC/README_ALTIVEC.txt | 211 + .../Target/PowerPC/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/PowerPC/TargetInfo/Makefile | 15 + .../PowerPC/TargetInfo/PowerPCTargetInfo.cpp | 23 + final/lib/Target/README.txt | 2268 ++ final/lib/Target/Sparc/CMakeLists.txt | 28 + final/lib/Target/Sparc/DelaySlotFiller.cpp | 323 + final/lib/Target/Sparc/FPMover.cpp | 141 + final/lib/Target/Sparc/Makefile | 23 + final/lib/Target/Sparc/README.txt | 59 + final/lib/Target/Sparc/Sparc.h | 121 + final/lib/Target/Sparc/Sparc.td | 72 + final/lib/Target/Sparc/SparcAsmPrinter.cpp | 251 + final/lib/Target/Sparc/SparcCallingConv.td | 36 + final/lib/Target/Sparc/SparcFrameLowering.cpp | 80 + final/lib/Target/Sparc/SparcFrameLowering.h | 41 + final/lib/Target/Sparc/SparcISelDAGToDAG.cpp | 212 + final/lib/Target/Sparc/SparcISelLowering.cpp | 1297 + final/lib/Target/Sparc/SparcISelLowering.h | 109 + final/lib/Target/Sparc/SparcInstrFormats.td | 114 + final/lib/Target/Sparc/SparcInstrInfo.cpp | 342 + final/lib/Target/Sparc/SparcInstrInfo.h | 97 + final/lib/Target/Sparc/SparcInstrInfo.td | 825 + final/lib/Target/Sparc/SparcMCAsmInfo.cpp | 34 + final/lib/Target/Sparc/SparcMCAsmInfo.h | 29 + .../Target/Sparc/SparcMachineFunctionInfo.h | 47 + final/lib/Target/Sparc/SparcRegisterInfo.cpp | 134 + final/lib/Target/Sparc/SparcRegisterInfo.h | 59 + final/lib/Target/Sparc/SparcRegisterInfo.td | 175 + .../Target/Sparc/SparcSelectionDAGInfo.cpp | 23 + .../lib/Target/Sparc/SparcSelectionDAGInfo.h | 31 + final/lib/Target/Sparc/SparcSubtarget.cpp | 34 + final/lib/Target/Sparc/SparcSubtarget.h | 54 + final/lib/Target/Sparc/SparcTargetMachine.cpp | 67 + final/lib/Target/Sparc/SparcTargetMachine.h | 78 + .../Target/Sparc/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/Sparc/TargetInfo/Makefile | 15 + .../Sparc/TargetInfo/SparcTargetInfo.cpp | 21 + final/lib/Target/SubtargetFeature.cpp | 384 + final/lib/Target/SystemZ/CMakeLists.txt | 26 + final/lib/Target/SystemZ/Makefile | 23 + final/lib/Target/SystemZ/SystemZ.h | 61 + final/lib/Target/SystemZ/SystemZ.td | 61 + .../lib/Target/SystemZ/SystemZAsmPrinter.cpp | 223 + .../lib/Target/SystemZ/SystemZCallingConv.td | 46 + .../Target/SystemZ/SystemZFrameLowering.cpp | 386 + .../lib/Target/SystemZ/SystemZFrameLowering.h | 57 + .../Target/SystemZ/SystemZISelDAGToDAG.cpp | 779 + .../Target/SystemZ/SystemZISelLowering.cpp | 863 + .../lib/Target/SystemZ/SystemZISelLowering.h | 150 + .../lib/Target/SystemZ/SystemZInstrBuilder.h | 128 + final/lib/Target/SystemZ/SystemZInstrFP.td | 340 + .../lib/Target/SystemZ/SystemZInstrFormats.td | 133 + final/lib/Target/SystemZ/SystemZInstrInfo.cpp | 435 + final/lib/Target/SystemZ/SystemZInstrInfo.h | 110 + final/lib/Target/SystemZ/SystemZInstrInfo.td | 1147 + final/lib/Target/SystemZ/SystemZMCAsmInfo.cpp | 30 + final/lib/Target/SystemZ/SystemZMCAsmInfo.h | 30 + .../SystemZ/SystemZMachineFunctionInfo.h | 51 + final/lib/Target/SystemZ/SystemZOperands.td | 325 + .../Target/SystemZ/SystemZRegisterInfo.cpp | 128 + .../lib/Target/SystemZ/SystemZRegisterInfo.h | 57 + .../lib/Target/SystemZ/SystemZRegisterInfo.td | 478 + .../SystemZ/SystemZSelectionDAGInfo.cpp | 23 + .../Target/SystemZ/SystemZSelectionDAGInfo.h | 31 + final/lib/Target/SystemZ/SystemZSubtarget.cpp | 47 + final/lib/Target/SystemZ/SystemZSubtarget.h | 45 + .../Target/SystemZ/SystemZTargetMachine.cpp | 44 + .../lib/Target/SystemZ/SystemZTargetMachine.h | 67 + .../Target/SystemZ/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/SystemZ/TargetInfo/Makefile | 15 + .../SystemZ/TargetInfo/SystemZTargetInfo.cpp | 19 + final/lib/Target/Target.cpp | 106 + final/lib/Target/TargetAsmInfo.cpp | 27 + final/lib/Target/TargetAsmLexer.cpp | 14 + final/lib/Target/TargetData.cpp | 639 + final/lib/Target/TargetELFWriterInfo.cpp | 25 + final/lib/Target/TargetFrameLowering.cpp | 53 + final/lib/Target/TargetInstrInfo.cpp | 178 + final/lib/Target/TargetIntrinsicInfo.cpp | 30 + final/lib/Target/TargetLibraryInfo.cpp | 61 + final/lib/Target/TargetLoweringObjectFile.cpp | 349 + final/lib/Target/TargetMachine.cpp | 306 + final/lib/Target/TargetRegisterInfo.cpp | 150 + final/lib/Target/TargetSubtarget.cpp | 33 + final/lib/Target/X86/AsmParser/CMakeLists.txt | 7 + final/lib/Target/X86/AsmParser/Makefile | 15 + .../lib/Target/X86/AsmParser/X86AsmLexer.cpp | 165 + .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 1034 + final/lib/Target/X86/CMakeLists.txt | 64 + .../Target/X86/Disassembler/CMakeLists.txt | 14 + final/lib/Target/X86/Disassembler/Makefile | 16 + .../X86/Disassembler/X86Disassembler.cpp | 554 + .../Target/X86/Disassembler/X86Disassembler.h | 155 + .../X86/Disassembler/X86DisassemblerDecoder.c | 1385 + .../X86/Disassembler/X86DisassemblerDecoder.h | 515 + .../X86DisassemblerDecoderCommon.h | 356 + .../lib/Target/X86/InstPrinter/CMakeLists.txt | 8 + final/lib/Target/X86/InstPrinter/Makefile | 15 + .../X86/InstPrinter/X86ATTInstPrinter.cpp | 127 + .../X86/InstPrinter/X86ATTInstPrinter.h | 81 + .../X86/InstPrinter/X86InstComments.cpp | 260 + .../Target/X86/InstPrinter/X86InstComments.h | 25 + .../X86/InstPrinter/X86IntelInstPrinter.cpp | 139 + .../X86/InstPrinter/X86IntelInstPrinter.h | 95 + final/lib/Target/X86/Makefile | 25 + final/lib/Target/X86/README-FPStack.txt | 85 + final/lib/Target/X86/README-MMX.txt | 71 + final/lib/Target/X86/README-SSE.txt | 937 + final/lib/Target/X86/README-UNIMPLEMENTED.txt | 14 + final/lib/Target/X86/README-X86-64.txt | 229 + final/lib/Target/X86/README.txt | 1949 ++ final/lib/Target/X86/SSEDomainFix.cpp | 506 + .../lib/Target/X86/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/X86/TargetInfo/Makefile | 16 + .../Target/X86/TargetInfo/X86TargetInfo.cpp | 23 + final/lib/Target/X86/Utils/CMakeLists.txt | 6 + final/lib/Target/X86/Utils/Makefile | 15 + .../lib/Target/X86/Utils/X86ShuffleDecode.cpp | 190 + final/lib/Target/X86/Utils/X86ShuffleDecode.h | 87 + final/lib/Target/X86/X86.h | 100 + final/lib/Target/X86/X86.td | 224 + final/lib/Target/X86/X86AsmBackend.cpp | 441 + final/lib/Target/X86/X86AsmPrinter.cpp | 728 + final/lib/Target/X86/X86AsmPrinter.h | 87 + .../Target/X86/X86COFFMachineModuleInfo.cpp | 20 + .../lib/Target/X86/X86COFFMachineModuleInfo.h | 46 + final/lib/Target/X86/X86CallingConv.td | 420 + final/lib/Target/X86/X86CodeEmitter.cpp | 997 + .../X86/X86CompilationCallback_Win64.asm | 68 + final/lib/Target/X86/X86ELFWriterInfo.cpp | 153 + final/lib/Target/X86/X86ELFWriterInfo.h | 59 + final/lib/Target/X86/X86FastISel.cpp | 1956 ++ final/lib/Target/X86/X86FixupKinds.h | 33 + final/lib/Target/X86/X86FloatingPoint.cpp | 1521 + final/lib/Target/X86/X86FrameLowering.cpp | 1016 + final/lib/Target/X86/X86FrameLowering.h | 65 + final/lib/Target/X86/X86ISelDAGToDAG.cpp | 2007 ++ final/lib/Target/X86/X86ISelLowering.cpp | 12814 ++++++++ final/lib/Target/X86/X86ISelLowering.h | 939 + final/lib/Target/X86/X86Instr3DNow.td | 77 + final/lib/Target/X86/X86InstrArithmetic.td | 1125 + final/lib/Target/X86/X86InstrBuilder.h | 184 + final/lib/Target/X86/X86InstrCMovSetCC.td | 104 + final/lib/Target/X86/X86InstrCompiler.td | 1626 ++ final/lib/Target/X86/X86InstrControl.td | 294 + final/lib/Target/X86/X86InstrExtension.td | 172 + final/lib/Target/X86/X86InstrFMA.td | 60 + final/lib/Target/X86/X86InstrFPStack.td | 684 + final/lib/Target/X86/X86InstrFormats.td | 528 + final/lib/Target/X86/X86InstrFragmentsSIMD.td | 461 + final/lib/Target/X86/X86InstrInfo.cpp | 3194 ++ final/lib/Target/X86/X86InstrInfo.h | 882 + final/lib/Target/X86/X86InstrInfo.td | 1628 ++ final/lib/Target/X86/X86InstrMMX.td | 454 + final/lib/Target/X86/X86InstrSSE.td | 5881 ++++ final/lib/Target/X86/X86InstrShiftRotate.td | 746 + final/lib/Target/X86/X86InstrSystem.td | 400 + final/lib/Target/X86/X86InstrVMX.td | 54 + final/lib/Target/X86/X86JITInfo.cpp | 574 + final/lib/Target/X86/X86JITInfo.h | 81 + final/lib/Target/X86/X86MCAsmInfo.cpp | 116 + final/lib/Target/X86/X86MCAsmInfo.h | 38 + final/lib/Target/X86/X86MCCodeEmitter.cpp | 1033 + final/lib/Target/X86/X86MCInstLower.cpp | 696 + final/lib/Target/X86/X86MCInstLower.h | 52 + final/lib/Target/X86/X86MachObjectWriter.cpp | 32 + final/lib/Target/X86/X86MachineFunctionInfo.h | 135 + final/lib/Target/X86/X86RegisterInfo.cpp | 868 + final/lib/Target/X86/X86RegisterInfo.h | 150 + final/lib/Target/X86/X86RegisterInfo.td | 853 + final/lib/Target/X86/X86Relocations.h | 52 + final/lib/Target/X86/X86SelectionDAGInfo.cpp | 259 + final/lib/Target/X86/X86SelectionDAGInfo.h | 56 + final/lib/Target/X86/X86Subtarget.cpp | 376 + final/lib/Target/X86/X86Subtarget.h | 259 + final/lib/Target/X86/X86TargetMachine.cpp | 265 + final/lib/Target/X86/X86TargetMachine.h | 134 + final/lib/Target/X86/X86TargetObjectFile.cpp | 118 + final/lib/Target/X86/X86TargetObjectFile.h | 54 + final/lib/Target/XCore/CMakeLists.txt | 27 + final/lib/Target/XCore/Makefile | 24 + final/lib/Target/XCore/README.txt | 7 + .../Target/XCore/TargetInfo/CMakeLists.txt | 7 + final/lib/Target/XCore/TargetInfo/Makefile | 16 + .../XCore/TargetInfo/XCoreTargetInfo.cpp | 19 + final/lib/Target/XCore/XCore.h | 41 + final/lib/Target/XCore/XCore.td | 46 + final/lib/Target/XCore/XCoreAsmPrinter.cpp | 280 + final/lib/Target/XCore/XCoreCallingConv.td | 36 + final/lib/Target/XCore/XCoreFrameLowering.cpp | 387 + final/lib/Target/XCore/XCoreFrameLowering.h | 59 + final/lib/Target/XCore/XCoreISelDAGToDAG.cpp | 215 + final/lib/Target/XCore/XCoreISelLowering.cpp | 1620 ++ final/lib/Target/XCore/XCoreISelLowering.h | 203 + final/lib/Target/XCore/XCoreInstrFormats.td | 120 + final/lib/Target/XCore/XCoreInstrInfo.cpp | 395 + final/lib/Target/XCore/XCoreInstrInfo.h | 85 + final/lib/Target/XCore/XCoreInstrInfo.td | 1121 + final/lib/Target/XCore/XCoreMCAsmInfo.cpp | 29 + final/lib/Target/XCore/XCoreMCAsmInfo.h | 30 + .../Target/XCore/XCoreMachineFunctionInfo.h | 69 + final/lib/Target/XCore/XCoreRegisterInfo.cpp | 324 + final/lib/Target/XCore/XCoreRegisterInfo.h | 80 + final/lib/Target/XCore/XCoreRegisterInfo.td | 91 + .../Target/XCore/XCoreSelectionDAGInfo.cpp | 23 + .../lib/Target/XCore/XCoreSelectionDAGInfo.h | 31 + final/lib/Target/XCore/XCoreSubtarget.cpp | 20 + final/lib/Target/XCore/XCoreSubtarget.h | 39 + final/lib/Target/XCore/XCoreTargetMachine.cpp | 45 + final/lib/Target/XCore/XCoreTargetMachine.h | 62 + .../Target/XCore/XCoreTargetObjectFile.cpp | 65 + .../lib/Target/XCore/XCoreTargetObjectFile.h | 25 + final/lib/Transforms/CMakeLists.txt | 6 + final/lib/Transforms/Hello/CMakeLists.txt | 3 + final/lib/Transforms/Hello/Hello.cpp | 64 + final/lib/Transforms/Hello/Hello.exports | 0 final/lib/Transforms/Hello/Makefile | 24 + .../lib/Transforms/IPO/ArgumentPromotion.cpp | 906 + final/lib/Transforms/IPO/CMakeLists.txt | 24 + final/lib/Transforms/IPO/ConstantMerge.cpp | 190 + .../IPO/DeadArgumentElimination.cpp | 1003 + .../Transforms/IPO/DeadTypeElimination.cpp | 111 + final/lib/Transforms/IPO/ExtractGV.cpp | 80 + final/lib/Transforms/IPO/FunctionAttrs.cpp | 380 + final/lib/Transforms/IPO/GlobalDCE.cpp | 211 + final/lib/Transforms/IPO/GlobalOpt.cpp | 2728 ++ .../Transforms/IPO/IPConstantPropagation.cpp | 279 + final/lib/Transforms/IPO/IPO.cpp | 118 + final/lib/Transforms/IPO/InlineAlways.cpp | 85 + final/lib/Transforms/IPO/InlineSimple.cpp | 118 + final/lib/Transforms/IPO/Inliner.cpp | 572 + final/lib/Transforms/IPO/Internalize.cpp | 194 + final/lib/Transforms/IPO/LoopExtractor.cpp | 248 + final/lib/Transforms/IPO/LowerSetJmp.cpp | 547 + final/lib/Transforms/IPO/Makefile | 15 + final/lib/Transforms/IPO/MergeFunctions.cpp | 868 + final/lib/Transforms/IPO/PartialInlining.cpp | 182 + final/lib/Transforms/IPO/PruneEH.cpp | 257 + .../Transforms/IPO/StripDeadPrototypes.cpp | 73 + final/lib/Transforms/IPO/StripSymbols.cpp | 408 + .../lib/Transforms/IPO/StructRetPromotion.cpp | 357 + .../lib/Transforms/InstCombine/CMakeLists.txt | 15 + .../lib/Transforms/InstCombine/InstCombine.h | 356 + .../InstCombine/InstCombineAddSub.cpp | 697 + .../InstCombine/InstCombineAndOrXor.cpp | 2240 ++ .../InstCombine/InstCombineCalls.cpp | 1259 + .../InstCombine/InstCombineCasts.cpp | 1709 ++ .../InstCombine/InstCombineCompares.cpp | 2817 ++ .../InstCombineLoadStoreAlloca.cpp | 642 + .../InstCombine/InstCombineMulDivRem.cpp | 622 + .../Transforms/InstCombine/InstCombinePHI.cpp | 891 + .../InstCombine/InstCombineSelect.cpp | 815 + .../InstCombine/InstCombineShifts.cpp | 746 + .../InstCombineSimplifyDemanded.cpp | 1145 + .../InstCombine/InstCombineVectorOps.cpp | 567 + .../InstCombine/InstCombineWorklist.h | 106 + .../InstCombine/InstructionCombining.cpp | 1662 ++ final/lib/Transforms/InstCombine/Makefile | 15 + .../Transforms/Instrumentation/CMakeLists.txt | 7 + .../Instrumentation/EdgeProfiling.cpp | 117 + .../Instrumentation/Instrumentation.cpp | 32 + final/lib/Transforms/Instrumentation/Makefile | 15 + .../Instrumentation/MaximumSpanningTree.h | 108 + .../Instrumentation/OptimalEdgeProfiling.cpp | 225 + .../Instrumentation/PathProfiling.cpp | 1423 + .../Instrumentation/ProfilingUtils.cpp | 133 + .../Instrumentation/ProfilingUtils.h | 34 + final/lib/Transforms/Makefile | 20 + final/lib/Transforms/Scalar/ADCE.cpp | 97 + .../Transforms/Scalar/BasicBlockPlacement.cpp | 152 + final/lib/Transforms/Scalar/CMakeLists.txt | 33 + .../lib/Transforms/Scalar/CodeGenPrepare.cpp | 1113 + final/lib/Transforms/Scalar/ConstantProp.cpp | 91 + .../Scalar/CorrelatedValuePropagation.cpp | 206 + final/lib/Transforms/Scalar/DCE.cpp | 136 + .../Scalar/DeadStoreElimination.cpp | 741 + final/lib/Transforms/Scalar/EarlyCSE.cpp | 470 + final/lib/Transforms/Scalar/GVN.cpp | 2044 ++ .../lib/Transforms/Scalar/IndVarSimplify.cpp | 1043 + final/lib/Transforms/Scalar/JumpThreading.cpp | 1576 + final/lib/Transforms/Scalar/LICM.cpp | 789 + final/lib/Transforms/Scalar/LoopDeletion.cpp | 246 + .../Transforms/Scalar/LoopIdiomRecognize.cpp | 606 + .../Transforms/Scalar/LoopInstSimplify.cpp | 170 + final/lib/Transforms/Scalar/LoopRotation.cpp | 348 + .../Transforms/Scalar/LoopStrengthReduce.cpp | 3845 +++ .../lib/Transforms/Scalar/LoopUnrollPass.cpp | 182 + final/lib/Transforms/Scalar/LoopUnswitch.cpp | 1045 + final/lib/Transforms/Scalar/LowerAtomic.cpp | 139 + final/lib/Transforms/Scalar/Makefile | 15 + .../lib/Transforms/Scalar/MemCpyOptimizer.cpp | 946 + final/lib/Transforms/Scalar/Reassociate.cpp | 1101 + final/lib/Transforms/Scalar/Reg2Mem.cpp | 134 + final/lib/Transforms/Scalar/SCCP.cpp | 2010 ++ final/lib/Transforms/Scalar/Scalar.cpp | 159 + .../Scalar/ScalarReplAggregates.cpp | 2336 ++ .../lib/Transforms/Scalar/SimplifyCFGPass.cpp | 329 + .../Transforms/Scalar/SimplifyLibCalls.cpp | 2388 ++ final/lib/Transforms/Scalar/Sink.cpp | 274 + .../lib/Transforms/Scalar/TailDuplication.cpp | 373 + .../Scalar/TailRecursionElimination.cpp | 630 + .../lib/Transforms/Utils/AddrModeMatcher.cpp | 582 + .../lib/Transforms/Utils/BasicBlockUtils.cpp | 540 + final/lib/Transforms/Utils/BasicInliner.cpp | 182 + .../Transforms/Utils/BreakCriticalEdges.cpp | 407 + final/lib/Transforms/Utils/BuildLibCalls.cpp | 483 + final/lib/Transforms/Utils/CMakeLists.txt | 29 + final/lib/Transforms/Utils/CloneFunction.cpp | 586 + final/lib/Transforms/Utils/CloneLoop.cpp | 128 + final/lib/Transforms/Utils/CloneModule.cpp | 137 + final/lib/Transforms/Utils/CodeExtractor.cpp | 795 + .../lib/Transforms/Utils/DemoteRegToStack.cpp | 146 + final/lib/Transforms/Utils/InlineFunction.cpp | 709 + .../lib/Transforms/Utils/InstructionNamer.cpp | 64 + final/lib/Transforms/Utils/LCSSA.cpp | 268 + final/lib/Transforms/Utils/Local.cpp | 757 + final/lib/Transforms/Utils/LoopSimplify.cpp | 753 + final/lib/Transforms/Utils/LoopUnroll.cpp | 388 + final/lib/Transforms/Utils/LowerInvoke.cpp | 613 + final/lib/Transforms/Utils/LowerSwitch.cpp | 323 + final/lib/Transforms/Utils/Makefile | 15 + final/lib/Transforms/Utils/Mem2Reg.cpp | 90 + .../Utils/PromoteMemoryToRegister.cpp | 1119 + final/lib/Transforms/Utils/SSAUpdater.cpp | 511 + final/lib/Transforms/Utils/SimplifyCFG.cpp | 2566 ++ .../Transforms/Utils/SimplifyInstructions.cpp | 94 + .../Utils/UnifyFunctionExitNodes.cpp | 141 + final/lib/Transforms/Utils/Utils.cpp | 37 + final/lib/Transforms/Utils/ValueMapper.cpp | 141 + final/lib/VMCore/AsmWriter.cpp | 2169 ++ final/lib/VMCore/Attributes.cpp | 349 + final/lib/VMCore/AutoUpgrade.cpp | 1406 + final/lib/VMCore/BasicBlock.cpp | 310 + final/lib/VMCore/CMakeLists.txt | 38 + final/lib/VMCore/ConstantFold.cpp | 2322 ++ final/lib/VMCore/ConstantFold.h | 56 + final/lib/VMCore/Constants.cpp | 2228 ++ final/lib/VMCore/ConstantsContext.h | 845 + final/lib/VMCore/Core.cpp | 2241 ++ final/lib/VMCore/DebugLoc.cpp | 288 + final/lib/VMCore/Dominators.cpp | 107 + final/lib/VMCore/Function.cpp | 409 + final/lib/VMCore/GVMaterializer.cpp | 18 + final/lib/VMCore/Globals.cpp | 261 + final/lib/VMCore/IRBuilder.cpp | 119 + final/lib/VMCore/InlineAsm.cpp | 289 + final/lib/VMCore/Instruction.cpp | 436 + final/lib/VMCore/Instructions.cpp | 3332 +++ final/lib/VMCore/IntrinsicInst.cpp | 73 + final/lib/VMCore/LLVMContext.cpp | 143 + final/lib/VMCore/LLVMContextImpl.cpp | 115 + final/lib/VMCore/LLVMContextImpl.h | 250 + final/lib/VMCore/LeakDetector.cpp | 69 + final/lib/VMCore/LeaksContext.h | 92 + final/lib/VMCore/Makefile | 34 + final/lib/VMCore/Metadata.cpp | 565 + final/lib/VMCore/Module.cpp | 473 + final/lib/VMCore/Pass.cpp | 293 + final/lib/VMCore/PassManager.cpp | 1849 ++ final/lib/VMCore/PassRegistry.cpp | 208 + final/lib/VMCore/PrintModulePass.cpp | 101 + final/lib/VMCore/SymbolTableListTraitsImpl.h | 118 + final/lib/VMCore/Type.cpp | 1230 + final/lib/VMCore/TypeSymbolTable.cpp | 169 + final/lib/VMCore/TypesContext.h | 425 + final/lib/VMCore/Use.cpp | 146 + final/lib/VMCore/User.cpp | 81 + final/lib/VMCore/Value.cpp | 640 + final/lib/VMCore/ValueSymbolTable.cpp | 117 + final/lib/VMCore/ValueTypes.cpp | 211 + final/lib/VMCore/Verifier.cpp | 1994 ++ final/llvm.spec.in | 67 + final/projects/CMakeLists.txt | 11 + final/projects/Makefile | 28 + final/projects/sample/Makefile | 18 + final/projects/sample/Makefile.common.in | 22 + final/projects/sample/autoconf/AutoRegen.sh | 52 + final/projects/sample/autoconf/LICENSE.TXT | 24 + final/projects/sample/autoconf/config.guess | 1388 + final/projects/sample/autoconf/config.sub | 1489 + final/projects/sample/autoconf/configure.ac | 73 + final/projects/sample/configure | 2722 ++ final/projects/sample/docs/index.html | 6 + final/projects/sample/include/sample.h | 8 + final/projects/sample/lib/Makefile | 13 + final/projects/sample/lib/sample/Makefile | 16 + final/projects/sample/lib/sample/sample.c | 25 + final/projects/sample/tools/Makefile | 13 + final/projects/sample/tools/sample/Makefile | 23 + final/projects/sample/tools/sample/main.c | 14 + final/runtime/Makefile | 31 + final/runtime/README.txt | 4 + final/runtime/libprofile/BasicBlockTracing.c | 67 + final/runtime/libprofile/CommonProfiling.c | 130 + final/runtime/libprofile/EdgeProfiling.c | 45 + final/runtime/libprofile/Makefile | 22 + .../runtime/libprofile/OptimalEdgeProfiling.c | 45 + final/runtime/libprofile/PathProfiling.c | 266 + final/runtime/libprofile/Profiling.h | 36 + final/runtime/libprofile/libprofile.exports | 7 + .../BasicAA/2003-02-26-AccessSizeTest.ll | 18 + .../Analysis/BasicAA/2003-03-04-GEPCrash.ll | 7 + .../Analysis/BasicAA/2003-04-22-GEPProblem.ll | 15 + .../Analysis/BasicAA/2003-04-25-GEPCrash.ll | 7 + .../BasicAA/2003-05-21-GEP-Problem.ll | 21 + .../Analysis/BasicAA/2003-06-01-AliasCrash.ll | 11 + .../BasicAA/2003-07-03-BasicAACrash.ll | 10 + .../BasicAA/2003-09-19-LocalArgument.ll | 12 + .../BasicAA/2003-11-04-SimpleCases.ll | 16 + .../BasicAA/2003-12-11-ConstExprGEP.ll | 18 + .../BasicAA/2004-07-28-MustAliasbug.ll | 10 + .../BasicAA/2004-12-08-BasicAACrash.ll | 22 + .../BasicAA/2004-12-08-BasicAACrash2.ll | 20 + .../BasicAA/2005-03-09-BrokenBasicAA.ll | 15 + .../BasicAA/2006-03-03-BadArraySubscript.ll | 31 + .../BasicAA/2006-11-03-BasicAAVectorCrash.ll | 48 + .../2007-01-13-BasePointerBadNoAlias.ll | 35 + .../BasicAA/2007-08-01-NoAliasAndCalls.ll | 10 + .../BasicAA/2007-08-01-NoAliasAndGEP.ll | 17 + .../BasicAA/2007-08-05-GetOverloadedModRef.ll | 17 + .../BasicAA/2007-10-24-ArgumentsGlobals.ll | 14 + .../Analysis/BasicAA/2007-11-05-SizeCrash.ll | 34 + .../BasicAA/2007-12-08-OutOfBoundsCrash.ll | 31 + .../test/Analysis/BasicAA/2008-04-15-Byval.ll | 18 + .../BasicAA/2008-06-02-GEPTailCrash.ll | 15 + .../Analysis/BasicAA/2008-11-23-NoaliasRet.ll | 12 + .../Analysis/BasicAA/2009-03-04-GEPNoalias.ll | 13 + .../BasicAA/2009-10-13-AtomicModRef.ll | 17 + .../BasicAA/2009-10-13-GEP-BaseNoAlias.ll | 30 + .../2010-09-15-GEP-SignedArithmetic.ll | 15 + .../BasicAA/args-rets-allocas-loads.ll | 310 + final/test/Analysis/BasicAA/byval.ll | 18 + final/test/Analysis/BasicAA/cas.ll | 15 + .../Analysis/BasicAA/constant-over-index.ll | 28 + final/test/Analysis/BasicAA/dg.exp | 3 + final/test/Analysis/BasicAA/empty.ll | 10 + final/test/Analysis/BasicAA/featuretest.ll | 127 + .../BasicAA/full-store-partial-alias.ll | 33 + final/test/Analysis/BasicAA/gcsetest.ll | 46 + final/test/Analysis/BasicAA/gep-alias.ll | 171 + .../Analysis/BasicAA/getmodrefinfo-cs-cs.ll | 26 + final/test/Analysis/BasicAA/global-size.ll | 40 + final/test/Analysis/BasicAA/modref.ll | 136 + final/test/Analysis/BasicAA/no-escape-call.ll | 23 + final/test/Analysis/BasicAA/nocapture.ll | 14 + final/test/Analysis/BasicAA/phi-aa.ll | 29 + final/test/Analysis/BasicAA/phi-and-select.ll | 73 + final/test/Analysis/BasicAA/pure-const-dce.ll | 33 + final/test/Analysis/BasicAA/store-promote.ll | 54 + .../test/Analysis/BasicAA/tailcall-modref.ll | 16 + .../Analysis/BasicAA/unreachable-block.ll | 16 + .../CallGraph/2008-09-09-DirectCall.ll | 13 + .../CallGraph/2008-09-09-UsedByGlobal.ll | 7 + final/test/Analysis/CallGraph/dg.exp | 3 + .../Dominators/2006-10-02-BreakCritEdges.ll | 20 + .../Dominators/2007-01-14-BreakCritEdges.ll | 187 + .../Dominators/2007-07-11-SplitBlock.ll | 21 + .../Dominators/2007-07-12-SplitBlock.ll | 13 + final/test/Analysis/Dominators/dg.exp | 3 + .../GlobalsModRef/2008-09-03-ReadGlobals.ll | 18 + .../test/Analysis/GlobalsModRef/aliastest.ll | 9 + .../GlobalsModRef/chaining-analysis.ll | 20 + final/test/Analysis/GlobalsModRef/dg.exp | 3 + .../Analysis/GlobalsModRef/indirect-global.ll | 20 + .../test/Analysis/GlobalsModRef/modreftest.ll | 13 + final/test/Analysis/GlobalsModRef/purecse.ll | 23 + .../Analysis/LoopDependenceAnalysis/alias.ll | 44 + .../Analysis/LoopDependenceAnalysis/dg.exp | 3 + .../LoopDependenceAnalysis/siv-strong.ll | 110 + .../siv-weak-crossing.ll | 118 + .../LoopDependenceAnalysis/siv-weak-zero.ll | 56 + .../Analysis/LoopDependenceAnalysis/ziv.ll | 63 + .../LoopInfo/2003-05-15-NestingProblem.ll | 30 + final/test/Analysis/LoopInfo/dg.exp | 3 + .../2006-09-26-PostDominanceFrontier.ll | 97 + .../2007-04-17-PostDominanceFrontier.ll | 692 + .../2007-04-20-PostDom-Reset.ll | 28 + final/test/Analysis/PostDominators/dg.exp | 3 + final/test/Analysis/PostDominators/pr1098.ll | 14 + .../test/Analysis/PostDominators/pr6047_a.ll | 15 + .../test/Analysis/PostDominators/pr6047_b.ll | 19 + .../test/Analysis/PostDominators/pr6047_c.ll | 147 + .../test/Analysis/PostDominators/pr6047_d.ll | 24 + final/test/Analysis/Profiling/dg.exp | 4 + .../test/Analysis/Profiling/edge-profiling.ll | 139 + .../Profiling/profiling-tool-chain.ll | 212 + .../RegionInfo/20100809_bb_not_in_domtree.ll | 20 + final/test/Analysis/RegionInfo/block_sort.ll | 42 + final/test/Analysis/RegionInfo/cond_loop.ll | 33 + .../RegionInfo/condition_complicated.ll | 60 + .../RegionInfo/condition_complicated_2.ll | 44 + .../RegionInfo/condition_forward_edge.ll | 26 + .../RegionInfo/condition_same_exit.ll | 31 + .../Analysis/RegionInfo/condition_simple.ll | 28 + final/test/Analysis/RegionInfo/dg.exp | 3 + .../Analysis/RegionInfo/exit_in_condition.ll | 38 + .../test/Analysis/RegionInfo/infinite_loop.ll | 20 + .../Analysis/RegionInfo/infinite_loop_2.ll | 36 + .../Analysis/RegionInfo/infinite_loop_3.ll | 52 + .../Analysis/RegionInfo/infinite_loop_4.ll | 48 + .../RegionInfo/loop_with_condition.ll | 46 + final/test/Analysis/RegionInfo/loops_1.ll | 40 + final/test/Analysis/RegionInfo/loops_2.ll | 49 + final/test/Analysis/RegionInfo/mix_1.ll | 69 + .../RegionInfo/multiple_exiting_edge.ll | 38 + .../test/Analysis/RegionInfo/nested_loops.ll | 33 + final/test/Analysis/RegionInfo/next.ll | 49 + final/test/Analysis/RegionInfo/paper.ll | 55 + .../RegionInfo/two_loops_same_header.ll | 46 + .../2007-07-15-NegativeStride.ll | 21 + .../2007-08-06-MisinterpretBranch.ll | 18 + .../ScalarEvolution/2007-08-06-Unsigned.ll | 30 + .../2007-09-27-LargeStepping.ll | 22 + .../2007-11-14-SignedAddRec.ll | 24 + .../2007-11-18-OrInstruction.ll | 21 + .../2008-02-11-ReversedCondition.ll | 15 + .../2008-02-12-SMAXTripCount.ll | 16 + .../ScalarEvolution/2008-02-15-UMax.ll | 17 + .../2008-05-25-NegativeStepToZero.ll | 22 + .../2008-06-12-BinomialInt64.ll | 43 + .../2008-07-12-UnneededSelect1.ll | 36 + .../2008-07-12-UnneededSelect2.ll | 30 + .../2008-07-19-InfiniteLoop.ll | 15 + .../ScalarEvolution/2008-07-19-WrappingIV.ll | 15 + .../2008-07-29-SGTTripCount.ll | 28 + .../ScalarEvolution/2008-07-29-SMinExpr.ll | 26 + .../ScalarEvolution/2008-08-04-IVOverflow.ll | 27 + .../ScalarEvolution/2008-08-04-LongAddRec.ll | 58 + .../2008-11-02-QuadraticCrash.ll | 21 + .../ScalarEvolution/2008-11-15-CubicOOM.ll | 19 + .../2008-11-18-LessThanOrEqual.ll | 31 + .../ScalarEvolution/2008-11-18-Stride1.ll | 35 + .../ScalarEvolution/2008-11-18-Stride2.ll | 34 + .../ScalarEvolution/2008-12-08-FiniteSGE.ll | 24 + .../2008-12-11-SMaxOverflow.ll | 30 + .../2008-12-14-StrideAndSigned.ll | 22 + .../ScalarEvolution/2008-12-15-DontUseSDiv.ll | 21 + .../2009-01-02-SignedNegativeStride.ll | 40 + .../ScalarEvolution/2009-04-22-TruncCast.ll | 37 + .../2009-05-09-PointerEdgeCount.ll | 28 + .../2009-07-04-GroupConstantsWidthMismatch.ll | 16 + .../2010-09-03-RequiredTransitive.ll | 24 + .../ScalarEvolution/SolveQuadraticEquation.ll | 32 + .../test/Analysis/ScalarEvolution/and-xor.ll | 8 + .../avoid-infinite-recursion-0.ll | 30 + .../avoid-infinite-recursion-1.ll | 354 + .../Analysis/ScalarEvolution/avoid-smax-0.ll | 35 + .../Analysis/ScalarEvolution/avoid-smax-1.ll | 236 + final/test/Analysis/ScalarEvolution/dg.exp | 3 + .../Analysis/ScalarEvolution/div-overflow.ll | 10 + .../test/Analysis/ScalarEvolution/do-loop.ll | 18 + final/test/Analysis/ScalarEvolution/fold.ll | 62 + .../ScalarEvolution/max-trip-count.ll | 72 + .../Analysis/ScalarEvolution/nsw-offset.ll | 77 + final/test/Analysis/ScalarEvolution/nsw.ll | 106 + .../ScalarEvolution/pointer-sign-bits.ll | 220 + final/test/Analysis/ScalarEvolution/pr3909.ll | 30 + .../test/Analysis/ScalarEvolution/scev-aa.ll | 215 + .../Analysis/ScalarEvolution/sext-inreg.ll | 30 + .../Analysis/ScalarEvolution/sext-iv-0.ll | 31 + .../Analysis/ScalarEvolution/sext-iv-1.ll | 100 + .../Analysis/ScalarEvolution/sext-iv-2.ll | 74 + final/test/Analysis/ScalarEvolution/sle.ll | 27 + final/test/Analysis/ScalarEvolution/smax.ll | 12 + .../Analysis/ScalarEvolution/trip-count.ll | 29 + .../Analysis/ScalarEvolution/trip-count10.ll | 126 + .../Analysis/ScalarEvolution/trip-count2.ll | 35 + .../Analysis/ScalarEvolution/trip-count3.ll | 78 + .../Analysis/ScalarEvolution/trip-count4.ll | 24 + .../Analysis/ScalarEvolution/trip-count5.ll | 48 + .../Analysis/ScalarEvolution/trip-count6.ll | 37 + .../Analysis/ScalarEvolution/trip-count7.ll | 150 + .../Analysis/ScalarEvolution/trip-count8.ll | 37 + .../Analysis/ScalarEvolution/trip-count9.ll | 408 + .../Analysis/ScalarEvolution/undefined.ll | 39 + .../ScalarEvolution/unreachable-code.ll | 13 + .../ScalarEvolution/unsimplified-loop.ll | 29 + .../test/Analysis/ScalarEvolution/xor-and.ll | 12 + .../Analysis/ScalarEvolution/zext-wrap.ll | 24 + .../TypeBasedAliasAnalysis/aliastest.ll | 62 + .../argument-promotion.ll | 31 + .../Analysis/TypeBasedAliasAnalysis/dg.exp | 3 + .../Analysis/TypeBasedAliasAnalysis/dse.ll | 66 + .../TypeBasedAliasAnalysis/functionattrs.ll | 81 + .../gvn-nonlocal-type-mismatch.ll | 91 + .../Analysis/TypeBasedAliasAnalysis/licm.ll | 61 + .../TypeBasedAliasAnalysis/memcpyopt.ll | 23 + .../TypeBasedAliasAnalysis/precedence.ll | 46 + .../Analysis/TypeBasedAliasAnalysis/sink.ll | 20 + final/test/Archive/GNU.a | Bin 0 -> 4210 bytes final/test/Archive/IsNAN.o | Bin 0 -> 2280 bytes final/test/Archive/MacOSX.a | Bin 0 -> 4166 bytes final/test/Archive/README.txt | 24 + final/test/Archive/SVR4.a | Bin 0 -> 4214 bytes final/test/Archive/dg.exp | 3 + final/test/Archive/evenlen | 1 + final/test/Archive/extract.ll | 16 + final/test/Archive/oddlen | 1 + final/test/Archive/toc_GNU.ll | 8 + final/test/Archive/toc_MacOSX.ll | 9 + final/test/Archive/toc_SVR4.ll | 8 + final/test/Archive/toc_xpg4.ll | 8 + .../Archive/very_long_bytecode_file_name.bc | Bin 0 -> 1465 bytes final/test/Archive/xpg4.a | Bin 0 -> 4214 bytes .../2002-01-24-BadSymbolTableAssert.ll | 11 + .../2002-01-24-ValueRefineAbsType.ll | 23 + .../test/Assembler/2002-02-19-TypeParsing.ll | 3 + .../Assembler/2002-03-08-NameCollision.ll | 15 + .../Assembler/2002-03-08-NameCollision2.ll | 12 + .../Assembler/2002-04-04-PureVirtMethCall.ll | 6 + .../Assembler/2002-04-04-PureVirtMethCall2.ll | 5 + .../test/Assembler/2002-04-05-TypeParsing.ll | 3 + .../Assembler/2002-04-07-HexFloatConstants.ll | 16 + .../test/Assembler/2002-04-07-InfConstant.ll | 9 + .../test/Assembler/2002-04-29-NameBinding.ll | 18 + .../Assembler/2002-05-02-InvalidForwardRef.ll | 10 + final/test/Assembler/2002-05-02-ParseError.ll | 7 + .../2002-07-08-HugePerformanceProblem.ll | 67 + .../Assembler/2002-07-14-InternalLossage.ll | 9 + final/test/Assembler/2002-07-14-OpaqueType.ll | 10 + .../2002-07-25-ParserAssertionFailure.ll | 13 + .../Assembler/2002-07-25-QuoteInString.ll | 5 + .../Assembler/2002-07-25-ReturnPtrFunction.ll | 15 + .../Assembler/2002-07-31-SlashInString.ll | 5 + .../Assembler/2002-08-15-CastAmbiguity.ll | 6 + .../2002-08-15-ConstantExprProblem.ll | 16 + .../2002-08-15-UnresolvedGlobalReference.ll | 8 + .../Assembler/2002-08-16-ConstExprInlined.ll | 22 + .../Assembler/2002-08-19-BytecodeReader.ll | 17 + .../Assembler/2002-08-22-DominanceProblem.ll | 17 + .../2002-10-08-LargeArrayPerformance.ll | 8 + .../2002-10-13-ConstantEncodingProblem.ll | 5 + final/test/Assembler/2002-10-15-NameClash.ll | 7 + .../Assembler/2002-12-15-GlobalResolve.ll | 7 + .../Assembler/2003-01-30-UnsignedString.ll | 4 + .../2003-04-15-ConstantInitAssertion.ll | 4 + .../2003-04-25-UnresolvedGlobalReference.ll | 7 + .../2003-05-03-BytecodeReaderProblem.ll | 6 + .../Assembler/2003-05-12-MinIntProblem.ll | 5 + .../Assembler/2003-05-15-AssemblerProblem.ll | 14 + final/test/Assembler/2003-05-15-SwitchBug.ll | 11 + .../Assembler/2003-05-21-ConstantShiftExpr.ll | 4 + .../Assembler/2003-05-21-EmptyStructTest.ll | 6 + .../2003-05-21-MalformedShiftCrash.ll | 4 + .../2003-05-21-MalformedStructCrash.ll | 4 + .../Assembler/2003-06-17-InvokeDisassemble.ll | 9 + .../2003-06-30-RecursiveTypeProblem.ll | 3 + .../2003-08-20-ConstantExprGEP-Fold.ll | 16 + .../2003-08-21-ConstantExprCast-Fold.ll | 4 + .../2003-10-04-NotMergingGlobalConstants.ll | 6 + .../Assembler/2003-11-05-ConstantExprShift.ll | 5 + .../Assembler/2003-11-11-ImplicitRename.ll | 8 + .../Assembler/2003-11-12-ConstantExprCast.ll | 10 + .../Assembler/2003-11-24-SymbolTableCrash.ll | 10 + .../2003-12-30-TypeMapInvalidMemory.ll | 55 + .../2004-01-11-getelementptrfolding.ll | 12 + .../test/Assembler/2004-01-20-MaxLongLong.ll | 4 + .../test/Assembler/2004-02-01-NegativeZero.ll | 5 + .../2004-02-27-SelfUseAssertError.ll | 25 + .../2004-03-07-FunctionAddressAlignment.ll | 15 + .../2004-03-30-UnclosedFunctionCrash.ll | 3 + .../2004-04-04-GetElementPtrIndexTypes.ll | 10 + .../test/Assembler/2004-06-07-VerifierBug.ll | 11 + .../Assembler/2004-10-22-BCWriterUndefBug.ll | 5 + .../Assembler/2004-11-28-InvalidTypeCrash.ll | 4 + .../2005-01-03-FPConstantDisassembly.ll | 6 + .../2005-01-31-CallingAggregateFunction.ll | 8 + .../Assembler/2005-02-09-AsmWriterStoreBug.ll | 14 + .../Assembler/2005-05-05-OpaqueUndefValues.ll | 4 + .../Assembler/2005-12-21-ZeroInitVector.ll | 6 + .../Assembler/2006-05-26-VarargsCallEncode.ll | 8 + .../Assembler/2006-09-28-CrashOnInvalid.ll | 8 + .../test/Assembler/2006-12-09-Cast-To-Bool.ll | 6 + .../2007-01-02-Undefined-Arg-Type.ll | 9 + .../Assembler/2007-01-05-Cmp-ConstExpr.ll | 18 + .../Assembler/2007-01-16-CrashOnBadCast.ll | 7 + .../Assembler/2007-01-16-CrashOnBadCast2.ll | 4 + .../2007-03-18-InvalidNumberedVar.ll | 9 + final/test/Assembler/2007-03-19-NegValue.ll | 7 + .../test/Assembler/2007-04-20-AlignedLoad.ll | 7 + .../test/Assembler/2007-04-20-AlignedStore.ll | 7 + .../2007-04-25-AssemblerFoldExternWeak.ll | 6 + final/test/Assembler/2007-05-21-Escape.ll | 22 + .../2007-07-19-ParamAttrAmbiguity.ll | 9 + .../2007-07-30-AutoUpgradeZextSext.ll | 12 + .../test/Assembler/2007-08-06-AliasInvalid.ll | 9 + .../test/Assembler/2007-09-10-AliasFwdRef.ll | 9 + final/test/Assembler/2007-09-29-GC.ll | 12 + .../Assembler/2007-11-26-AttributeOverload.ll | 4 + .../2007-11-27-AutoUpgradeAttributes.ll | 3 + .../Assembler/2007-12-11-AddressSpaces.ll | 25 + .../test/Assembler/2008-01-11-VarargAttrs.ll | 10 + .../Assembler/2008-02-18-IntPointerCrash.ll | 6 + .../2008-02-20-MultipleReturnValue.ll | 22 + final/test/Assembler/2008-07-10-APInt.ll | 9 + .../Assembler/2008-09-02-FunctionNotes.ll | 14 + .../Assembler/2008-09-02-FunctionNotes2.ll | 6 + final/test/Assembler/2008-09-29-RetAttr.ll | 13 + .../2008-10-14-NamedTypeOnInteger.ll | 6 + .../test/Assembler/2008-10-14-QuoteInName.ll | 3 + .../Assembler/2009-02-01-UnnamedForwardRef.ll | 6 + final/test/Assembler/2009-02-28-CastOpc.ll | 8 + .../Assembler/2009-02-28-StripOpaqueName.ll | 6 + .../Assembler/2009-03-24-ZextConstantExpr.ll | 11 + final/test/Assembler/2009-04-25-AliasGEP.ll | 8 + final/test/Assembler/2009-07-24-ZeroArgGEP.ll | 5 + ...-02-05-FunctionLocalMetadataBecomesNull.ll | 25 + final/test/Assembler/AutoUpgradeIntrinsics.ll | 81 + .../Assembler/AutoUpgradeMMXIntrinsics.ll | 223 + final/test/Assembler/ConstantExprFold.ll | 31 + final/test/Assembler/ConstantExprFoldCast.ll | 14 + .../test/Assembler/MultipleReturnValueType.ll | 13 + .../Assembler/aggregate-constant-values.ll | 27 + .../aggregate-return-single-value.ll | 14 + final/test/Assembler/align-inst-alloca.ll | 6 + final/test/Assembler/align-inst-load.ll | 6 + final/test/Assembler/align-inst-store.ll | 6 + final/test/Assembler/align-inst.ll | 10 + final/test/Assembler/alignstack.ll | 36 + final/test/Assembler/anon-functions.ll | 26 + final/test/Assembler/bcwrap.ll | 9 + final/test/Assembler/comment.ll | 20 + final/test/Assembler/dg.exp | 3 + .../Assembler/extractvalue-invalid-idx.ll | 8 + final/test/Assembler/flags.ll | 276 + .../test/Assembler/functionlocal-metadata.ll | 44 + final/test/Assembler/getelementptr.ll | 22 + final/test/Assembler/getelementptr_struct.ll | 12 + final/test/Assembler/huge-array.ll | 5 + final/test/Assembler/insertextractvalue.ll | 29 + .../test/Assembler/insertvalue-invalid-idx.ll | 7 + final/test/Assembler/metadata.ll | 22 + final/test/Assembler/numbered-values.ll | 16 + final/test/Assembler/private.ll | 9 + final/test/Assembler/select.ll | 9 + final/test/Assembler/unnamed-addr.ll | 18 + final/test/Assembler/unnamed.ll | 51 + final/test/Assembler/vbool-cmp.ll | 15 + final/test/Assembler/vector-cmp.ll | 16 + final/test/Assembler/vector-select.ll | 11 + final/test/Assembler/vector-shift.ll | 32 + final/test/Assembler/x86mmx.ll | 8 + final/test/Bindings/Ocaml/analysis.ml | 51 + final/test/Bindings/Ocaml/bitreader.ml | 78 + final/test/Bindings/Ocaml/bitwriter.ml | 47 + final/test/Bindings/Ocaml/dg.exp | 5 + final/test/Bindings/Ocaml/executionengine.ml | 115 + final/test/Bindings/Ocaml/ext_exc.ml | 17 + final/test/Bindings/Ocaml/scalar_opts.ml | 78 + final/test/Bindings/Ocaml/target.ml | 60 + final/test/Bindings/Ocaml/vmcore.ml | 1331 + .../test/Bitcode/2006-12-11-Cast-ConstExpr.ll | 10 + .../2009-06-11-FirstClassAggregateConstant.ll | 12 + final/test/Bitcode/AutoUpgradeGlobals.ll | 3 + final/test/Bitcode/AutoUpgradeGlobals.ll.bc | Bin 0 -> 312 bytes final/test/Bitcode/AutoUpgradeIntrinsics.ll | 10 + .../test/Bitcode/AutoUpgradeIntrinsics.ll.bc | Bin 0 -> 800 bytes final/test/Bitcode/dg.exp | 3 + final/test/Bitcode/extractelement.ll | 8 + final/test/Bitcode/flags.ll | 27 + final/test/Bitcode/memcpy.ll | 23 + final/test/Bitcode/metadata-2.ll | 87 + final/test/Bitcode/metadata.ll | 6 + final/test/Bitcode/neon-intrinsics.ll | 213 + final/test/Bitcode/neon-intrinsics.ll.bc | Bin 0 -> 5764 bytes final/test/Bitcode/null-type.ll | 2 + final/test/Bitcode/null-type.ll.bc | Bin 0 -> 312 bytes final/test/Bitcode/sse2_loadl_pd.ll | 2 + final/test/Bitcode/sse2_loadl_pd.ll.bc | Bin 0 -> 532 bytes final/test/Bitcode/sse2_movl_dq.ll | 2 + final/test/Bitcode/sse2_movl_dq.ll.bc | Bin 0 -> 480 bytes final/test/Bitcode/sse2_movs_d.ll | 2 + final/test/Bitcode/sse2_movs_d.ll.bc | Bin 0 -> 476 bytes final/test/Bitcode/sse2_punpck_qdq.ll | 3 + final/test/Bitcode/sse2_punpck_qdq.ll.bc | Bin 0 -> 576 bytes final/test/Bitcode/sse2_shuf_pd.ll | 2 + final/test/Bitcode/sse2_shuf_pd.ll.bc | Bin 0 -> 584 bytes final/test/Bitcode/sse2_unpck_pd.ll | 3 + final/test/Bitcode/sse2_unpck_pd.ll.bc | Bin 0 -> 572 bytes final/test/Bitcode/sse41_pmulld.ll | 2 + final/test/Bitcode/sse41_pmulld.ll.bc | Bin 0 -> 560 bytes final/test/Bitcode/ssse3_palignr.ll | 1 + final/test/Bitcode/ssse3_palignr.ll.bc | Bin 0 -> 1504 bytes .../test/BugPoint/crash-narrowfunctiontest.ll | 13 + final/test/BugPoint/dg.exp | 3 + final/test/BugPoint/metadata.ll | 35 + final/test/BugPoint/remove_arguments_test.ll | 18 + final/test/CMakeLists.txt | 97 + .../test/CodeGen/ARM/2006-11-10-CycleInDAG.ll | 20 + .../CodeGen/ARM/2007-01-19-InfiniteLoop.ll | 108 + .../CodeGen/ARM/2007-03-07-CombinerCrash.ll | 21 + .../test/CodeGen/ARM/2007-03-13-InstrSched.ll | 51 + .../ARM/2007-03-21-JoinIntervalsCrash.ll | 96 + .../ARM/2007-03-26-RegScavengerAssert.ll | 947 + .../ARM/2007-03-27-RegScavengerAssert.ll | 35 + .../ARM/2007-03-30-RegScavengerAssert.ll | 101 + .../ARM/2007-04-02-RegScavengerAssert.ll | 55 + final/test/CodeGen/ARM/2007-04-03-PEIBug.ll | 12 + .../CodeGen/ARM/2007-04-03-UndefinedSymbol.ll | 99 + .../CodeGen/ARM/2007-04-30-CombinerCrash.ll | 32 + .../ARM/2007-05-03-BadPostIndexedLd.ll | 113 + .../CodeGen/ARM/2007-05-07-jumptoentry.ll | 58 + .../CodeGen/ARM/2007-05-07-tailmerge-1.ll | 66 + .../CodeGen/ARM/2007-05-09-tailmerge-2.ll | 67 + .../ARM/2007-05-14-InlineAsmCstCrash.ll | 6 + .../ARM/2007-05-14-RegScavengerAssert.ll | 30 + .../CodeGen/ARM/2007-05-22-tailmerge-3.ll | 69 + .../ARM/2007-05-23-BadPreIndexedStore.ll | 34 + .../2007-05-31-RegScavengerInfiniteLoop.ll | 237 + final/test/CodeGen/ARM/2007-08-15-ReuseBug.ll | 106 + .../ARM/2008-02-04-LocalRegAllocBug.ll | 19 + .../CodeGen/ARM/2008-02-29-RegAllocLocal.ll | 21 + .../CodeGen/ARM/2008-03-05-SxtInRegBug.ll | 14 + .../ARM/2008-03-07-RegScavengerAssert.ll | 20 + .../CodeGen/ARM/2008-04-04-ScavengerAssert.ll | 60 + .../CodeGen/ARM/2008-04-10-ScavengerAssert.ll | 258 + .../CodeGen/ARM/2008-04-11-PHIofImpDef.ll | 3544 +++ .../ARM/2008-05-19-LiveIntervalsBug.ll | 55 + .../CodeGen/ARM/2008-05-19-ScavengerAssert.ll | 22 + final/test/CodeGen/ARM/2008-07-17-Fdiv.ll | 6 + .../ARM/2008-07-24-CodeGenPrepCrash.ll | 9 + .../CodeGen/ARM/2008-08-07-AsmPrintBug.ll | 13 + .../CodeGen/ARM/2008-09-14-CoalescerBug.ll | 29 + .../CodeGen/ARM/2008-09-17-CoalescerBug.ll | 17 + .../CodeGen/ARM/2008-11-18-ScavengerAssert.ll | 16 + .../test/CodeGen/ARM/2009-02-16-SpillerBug.ll | 117 + .../ARM/2009-02-22-SoftenFloatVaArg.ll | 20 + .../test/CodeGen/ARM/2009-02-27-SpillerBug.ll | 229 + .../test/CodeGen/ARM/2009-03-07-SpillerBug.ll | 78 + .../CodeGen/ARM/2009-03-09-AddrModeBug.ll | 13 + .../CodeGen/ARM/2009-04-06-AsmModifier.ll | 20 + .../CodeGen/ARM/2009-04-08-AggregateAddr.ll | 18 + final/test/CodeGen/ARM/2009-04-08-FREM.ll | 9 + .../test/CodeGen/ARM/2009-04-08-FloatUndef.ll | 11 + .../CodeGen/ARM/2009-04-09-RegScavengerAsm.ll | 14 + .../CodeGen/ARM/2009-05-05-DAGCombineBug.ll | 11 + .../CodeGen/ARM/2009-05-07-RegAllocLocal.ll | 12 + .../ARM/2009-05-11-CodePlacementCrash.ll | 30 + .../CodeGen/ARM/2009-05-18-InlineAsmMem.ll | 9 + .../test/CodeGen/ARM/2009-06-02-ISelCrash.ll | 62 + .../CodeGen/ARM/2009-06-04-MissingLiveIn.ll | 263 + .../ARM/2009-06-12-RegScavengerAssert.ll | 77 + .../ARM/2009-06-15-RegScavengerAssert.ll | 344 + .../ARM/2009-06-19-RegScavengerAssert.ll | 30 + .../CodeGen/ARM/2009-06-22-CoalescerBug.ll | 43 + .../ARM/2009-06-30-RegScavengerAssert.ll | 122 + .../ARM/2009-06-30-RegScavengerAssert2.ll | 116 + .../ARM/2009-06-30-RegScavengerAssert3.ll | 128 + .../ARM/2009-06-30-RegScavengerAssert4.ll | 128 + .../ARM/2009-06-30-RegScavengerAssert5.ll | 99 + .../test/CodeGen/ARM/2009-07-01-CommuteBug.ll | 130 + .../ARM/2009-07-09-asm-p-constraint.ll | 7 + .../CodeGen/ARM/2009-07-18-RewriterBug.ll | 1323 + .../CodeGen/ARM/2009-07-22-ScavengerAssert.ll | 94 + .../CodeGen/ARM/2009-07-22-SchedulerAssert.ll | 95 + .../CodeGen/ARM/2009-07-29-VFP3Registers.ll | 108 + .../ARM/2009-08-02-RegScavengerAssert-Neon.ll | 29 + .../ARM/2009-08-04-RegScavengerAssert-2.ll | 33 + .../ARM/2009-08-04-RegScavengerAssert.ll | 25 + .../2009-08-15-RegScavenger-EarlyClobber.ll | 42 + .../ARM/2009-08-15-RegScavengerAssert.ll | 10 + .../test/CodeGen/ARM/2009-08-21-PostRAKill.ll | 40 + .../CodeGen/ARM/2009-08-21-PostRAKill2.ll | 38 + .../CodeGen/ARM/2009-08-21-PostRAKill3.ll | 31 + .../CodeGen/ARM/2009-08-23-linkerprivate.ll | 8 + .../CodeGen/ARM/2009-08-26-ScalarToVector.ll | 27 + .../CodeGen/ARM/2009-08-27-ScalarToVector.ll | 35 + .../CodeGen/ARM/2009-08-29-ExtractEltf32.ll | 25 + .../CodeGen/ARM/2009-08-29-TooLongSplat.ll | 23 + .../test/CodeGen/ARM/2009-08-31-LSDA-Name.ll | 103 + .../CodeGen/ARM/2009-08-31-TwoRegShuffle.ll | 9 + final/test/CodeGen/ARM/2009-09-09-AllOnes.ll | 10 + .../test/CodeGen/ARM/2009-09-09-fpcmp-ole.ll | 18 + final/test/CodeGen/ARM/2009-09-10-postdec.ll | 11 + .../CodeGen/ARM/2009-09-13-InvalidSubreg.ll | 61 + .../CodeGen/ARM/2009-09-13-InvalidSuperReg.ll | 41 + .../ARM/2009-09-20-LiveIntervalsBug.ll | 34 + .../ARM/2009-09-21-LiveVariablesBug.ll | 14 + .../ARM/2009-09-22-LiveVariablesBug.ll | 23 + .../ARM/2009-09-23-LiveVariablesBug.ll | 21 + .../CodeGen/ARM/2009-09-24-spill-align.ll | 17 + .../CodeGen/ARM/2009-09-27-CoalescerBug.ll | 24 + .../CodeGen/ARM/2009-09-28-LdStOptiBug.ll | 19 + .../CodeGen/ARM/2009-10-02-NEONSubregsBug.ll | 63 + final/test/CodeGen/ARM/2009-10-16-Scope.ll | 32 + .../CodeGen/ARM/2009-10-21-InvalidFNeg.ll | 48 + .../CodeGen/ARM/2009-10-27-double-align.ll | 14 + final/test/CodeGen/ARM/2009-10-30.ll | 17 + .../test/CodeGen/ARM/2009-11-01-NeonMoves.ll | 40 + .../CodeGen/ARM/2009-11-02-NegativeLane.ll | 21 + .../ARM/2009-11-07-SubRegAsmPrinting.ll | 66 + .../CodeGen/ARM/2009-11-13-CoalescerCrash.ll | 20 + .../CodeGen/ARM/2009-11-13-ScavengerAssert.ll | 42 + .../ARM/2009-11-13-ScavengerAssert2.ll | 123 + .../CodeGen/ARM/2009-11-13-VRRewriterCrash.ll | 113 + .../ARM/2009-11-30-LiveVariablesBug.ll | 41 + .../test/CodeGen/ARM/2009-12-02-vtrn-undef.ll | 33 + .../CodeGen/ARM/2010-03-04-eabi-fp-spill.ll | 65 + .../CodeGen/ARM/2010-03-04-stm-undef-addr.ll | 54 + final/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll | 15 + .../ARM/2010-04-07-DbgValueOtherTargets.ll | 28 + .../test/CodeGen/ARM/2010-04-09-NeonSelect.ll | 23 + .../CodeGen/ARM/2010-04-13-v2f64SplitArg.ll | 7 + .../CodeGen/ARM/2010-04-14-SplitVector.ll | 16 + .../ARM/2010-04-15-ScavengerDebugValue.ll | 26 + .../CodeGen/ARM/2010-05-14-IllegalType.ll | 10 + .../CodeGen/ARM/2010-05-17-FastAllocCrash.ll | 105 + .../CodeGen/ARM/2010-05-18-LocalAllocCrash.ll | 36 + .../CodeGen/ARM/2010-05-18-PostIndexBug.ll | 25 + final/test/CodeGen/ARM/2010-05-19-Shuffles.ll | 21 + .../CodeGen/ARM/2010-05-20-NEONSpillCrash.ll | 45 + .../CodeGen/ARM/2010-05-21-BuildVector.ll | 43 + .../CodeGen/ARM/2010-06-11-vmovdrr-bitcast.ll | 19 + .../CodeGen/ARM/2010-06-21-LdStMultipleBug.ll | 148 + .../CodeGen/ARM/2010-06-21-nondarwin-tc.ll | 146 + .../ARM/2010-06-25-Thumb2ITInvalidIterator.ll | 75 + .../ARM/2010-06-29-PartialRedefFastAlloc.ll | 25 + .../CodeGen/ARM/2010-06-29-SubregImpDefs.ll | 15 + .../CodeGen/ARM/2010-07-26-GlobalMerge.ll | 95 + final/test/CodeGen/ARM/2010-08-04-EHCrash.ll | 65 + .../CodeGen/ARM/2010-08-04-StackVariable.ll | 124 + .../test/CodeGen/ARM/2010-09-21-OptCmpBug.ll | 84 + .../ARM/2010-09-29-mc-asm-header-test.ll | 13 + .../ARM/2010-10-19-mc-elf-objheader.ll | 37 + .../test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll | 31 + .../ARM/2010-11-15-SpillEarlyClobber.ll | 85 + .../CodeGen/ARM/2010-11-29-PrologueBug.ll | 28 + .../test/CodeGen/ARM/2010-11-30-reloc-movt.ll | 42 + final/test/CodeGen/ARM/2010-12-07-PEIBug.ll | 40 + final/test/CodeGen/ARM/2010-12-08-tpsoft.ll | 52 + .../test/CodeGen/ARM/2010-12-13-reloc-pic.ll | 100 + .../test/CodeGen/ARM/2010-12-15-elf-lcomm.ll | 35 + .../ARM/2010-12-17-LocalStackSlotCrash.ll | 15 + .../CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll | 126 + .../CodeGen/ARM/2011-02-04-AntidepMultidef.ll | 128 + .../CodeGen/ARM/2011-02-07-AntidepClobber.ll | 89 + final/test/CodeGen/ARM/addrmode.ll | 15 + final/test/CodeGen/ARM/aliases.ll | 31 + final/test/CodeGen/ARM/align.ll | 42 + final/test/CodeGen/ARM/alloca.ll | 12 + final/test/CodeGen/ARM/argaddr.ll | 19 + .../CodeGen/ARM/arguments-nosplit-double.ll | 9 + .../test/CodeGen/ARM/arguments-nosplit-i64.ll | 9 + final/test/CodeGen/ARM/arguments.ll | 43 + final/test/CodeGen/ARM/arguments2.ll | 9 + final/test/CodeGen/ARM/arguments3.ll | 9 + final/test/CodeGen/ARM/arguments4.ll | 9 + final/test/CodeGen/ARM/arguments5.ll | 9 + final/test/CodeGen/ARM/arguments6.ll | 9 + final/test/CodeGen/ARM/arguments7.ll | 9 + final/test/CodeGen/ARM/arguments8.ll | 9 + .../CodeGen/ARM/arguments_f64_backfill.ll | 9 + .../test/CodeGen/ARM/arm-and-tst-peephole.ll | 112 + final/test/CodeGen/ARM/arm-asm.ll | 7 + final/test/CodeGen/ARM/arm-frameaddr.ll | 17 + final/test/CodeGen/ARM/arm-negative-stride.ll | 47 + final/test/CodeGen/ARM/arm-returnaddr.ll | 26 + final/test/CodeGen/ARM/armv4.ll | 13 + final/test/CodeGen/ARM/atomic-cmp.ll | 17 + .../test/CodeGen/ARM/available_externally.ll | 16 + final/test/CodeGen/ARM/bfc.ll | 25 + final/test/CodeGen/ARM/bfi.ll | 64 + final/test/CodeGen/ARM/bfx.ll | 28 + final/test/CodeGen/ARM/bic.ll | 17 + final/test/CodeGen/ARM/bits.ll | 41 + final/test/CodeGen/ARM/bswap-inline-asm.ll | 9 + final/test/CodeGen/ARM/bx_fold.ll | 31 + final/test/CodeGen/ARM/call-tc.ll | 87 + final/test/CodeGen/ARM/call.ll | 36 + final/test/CodeGen/ARM/call_nolink.ll | 52 + final/test/CodeGen/ARM/carry.ll | 21 + final/test/CodeGen/ARM/clz.ll | 10 + final/test/CodeGen/ARM/code-placement.ll | 79 + final/test/CodeGen/ARM/compare-call.ll | 20 + final/test/CodeGen/ARM/constants.ll | 46 + final/test/CodeGen/ARM/crash-O0.ll | 28 + final/test/CodeGen/ARM/crash.ll | 29 + final/test/CodeGen/ARM/cse-libcalls.ll | 30 + final/test/CodeGen/ARM/ctors_dtors.ll | 25 + final/test/CodeGen/ARM/ctz.ll | 11 + final/test/CodeGen/ARM/dg.exp | 5 + final/test/CodeGen/ARM/div.ll | 34 + final/test/CodeGen/ARM/dyn-stackalloc.ll | 56 + final/test/CodeGen/ARM/extloadi1.ll | 20 + final/test/CodeGen/ARM/fabss.ll | 27 + final/test/CodeGen/ARM/fadds.ll | 23 + final/test/CodeGen/ARM/fast-isel-crash.ll | 21 + final/test/CodeGen/ARM/fast-isel-static.ll | 30 + final/test/CodeGen/ARM/fast-isel.ll | 16 + final/test/CodeGen/ARM/fcopysign.ll | 58 + final/test/CodeGen/ARM/fdivs.ll | 23 + final/test/CodeGen/ARM/fixunsdfdi.ll | 29 + final/test/CodeGen/ARM/flag-crash.ll | 27 + final/test/CodeGen/ARM/fmacs.ll | 51 + final/test/CodeGen/ARM/fmdrr-fmrrd.ll | 13 + final/test/CodeGen/ARM/fmscs.ll | 35 + final/test/CodeGen/ARM/fmuls.ll | 23 + final/test/CodeGen/ARM/fnegs.ll | 53 + final/test/CodeGen/ARM/fnmacs.ll | 35 + final/test/CodeGen/ARM/fnmscs.ll | 71 + final/test/CodeGen/ARM/fnmul.ll | 11 + final/test/CodeGen/ARM/fnmuls.ll | 21 + final/test/CodeGen/ARM/formal.ll | 8 + final/test/CodeGen/ARM/fp.ll | 78 + final/test/CodeGen/ARM/fp16.ll | 32 + final/test/CodeGen/ARM/fp_convert.ll | 48 + final/test/CodeGen/ARM/fparith.ll | 101 + final/test/CodeGen/ARM/fpcmp-opt.ll | 83 + final/test/CodeGen/ARM/fpcmp.ll | 71 + final/test/CodeGen/ARM/fpcmp_ueq.ll | 16 + final/test/CodeGen/ARM/fpconsts.ll | 33 + final/test/CodeGen/ARM/fpconv.ll | 102 + final/test/CodeGen/ARM/fpmem.ll | 23 + final/test/CodeGen/ARM/fpow.ll | 9 + final/test/CodeGen/ARM/fpowi.ll | 15 + final/test/CodeGen/ARM/fptoint.ll | 49 + final/test/CodeGen/ARM/fsubs.ll | 13 + final/test/CodeGen/ARM/global-merge.ll | 24 + final/test/CodeGen/ARM/globals.ll | 75 + final/test/CodeGen/ARM/hardfloat_neon.ll | 13 + final/test/CodeGen/ARM/hello.ll | 14 + final/test/CodeGen/ARM/hidden-vis-2.ll | 12 + final/test/CodeGen/ARM/hidden-vis-3.ll | 17 + final/test/CodeGen/ARM/hidden-vis.ll | 23 + final/test/CodeGen/ARM/iabs.ll | 16 + final/test/CodeGen/ARM/ifcvt1.ll | 15 + final/test/CodeGen/ARM/ifcvt10.ll | 43 + final/test/CodeGen/ARM/ifcvt11.ll | 59 + final/test/CodeGen/ARM/ifcvt2.ll | 42 + final/test/CodeGen/ARM/ifcvt3.ll | 19 + final/test/CodeGen/ARM/ifcvt4.ll | 38 + final/test/CodeGen/ARM/ifcvt5.ll | 25 + final/test/CodeGen/ARM/ifcvt6.ll | 20 + final/test/CodeGen/ARM/ifcvt7.ll | 32 + final/test/CodeGen/ARM/ifcvt8.ll | 19 + final/test/CodeGen/ARM/ifcvt9.ll | 12 + .../CodeGen/ARM/illegal-vector-bitcast.ll | 14 + final/test/CodeGen/ARM/imm.ll | 16 + final/test/CodeGen/ARM/indirectbr.ll | 64 + final/test/CodeGen/ARM/inlineasm-imm-arm.ll | 31 + final/test/CodeGen/ARM/inlineasm.ll | 11 + final/test/CodeGen/ARM/inlineasm2.ll | 11 + final/test/CodeGen/ARM/inlineasm3.ll | 25 + final/test/CodeGen/ARM/insn-sched1.ll | 11 + final/test/CodeGen/ARM/ispositive.ll | 10 + final/test/CodeGen/ARM/large-stack.ll | 20 + final/test/CodeGen/ARM/ldm.ll | 46 + final/test/CodeGen/ARM/ldr.ll | 71 + final/test/CodeGen/ARM/ldr_ext.ll | 37 + final/test/CodeGen/ARM/ldr_frame.ll | 31 + final/test/CodeGen/ARM/ldr_post.ll | 12 + final/test/CodeGen/ARM/ldr_pre.ll | 19 + final/test/CodeGen/ARM/ldrd.ll | 22 + final/test/CodeGen/ARM/ldst-f32-2-i32.ll | 28 + final/test/CodeGen/ARM/load-global.ll | 50 + final/test/CodeGen/ARM/load.ll | 34 + final/test/CodeGen/ARM/long-setcc.ll | 17 + final/test/CodeGen/ARM/long.ll | 90 + final/test/CodeGen/ARM/long_shift.ll | 45 + final/test/CodeGen/ARM/lsr-code-insertion.ll | 60 + .../test/CodeGen/ARM/lsr-on-unrolled-loops.ll | 642 + final/test/CodeGen/ARM/lsr-scale-addr-mode.ll | 19 + final/test/CodeGen/ARM/machine-cse-cmp.ll | 18 + final/test/CodeGen/ARM/machine-licm.ll | 66 + final/test/CodeGen/ARM/mem.ll | 14 + final/test/CodeGen/ARM/memcpy-inline.ll | 16 + final/test/CodeGen/ARM/memfunc.ll | 16 + final/test/CodeGen/ARM/mls.ll | 16 + final/test/CodeGen/ARM/movt-movw-global.ll | 20 + final/test/CodeGen/ARM/movt.ll | 19 + final/test/CodeGen/ARM/mul.ll | 22 + final/test/CodeGen/ARM/mul_const.ll | 43 + final/test/CodeGen/ARM/mulhi.ll | 22 + .../test/CodeGen/ARM/mult-alt-generic-arm.ll | 323 + final/test/CodeGen/ARM/mvn.ll | 74 + final/test/CodeGen/ARM/neon_arith1.ll | 7 + final/test/CodeGen/ARM/neon_div.ll | 48 + final/test/CodeGen/ARM/neon_ld1.ll | 22 + final/test/CodeGen/ARM/neon_ld2.ll | 23 + final/test/CodeGen/ARM/neon_minmax.ll | 81 + final/test/CodeGen/ARM/neon_shift.ll | 11 + final/test/CodeGen/ARM/pack.ll | 88 + final/test/CodeGen/ARM/phi.ll | 23 + final/test/CodeGen/ARM/pr3502.ll | 24 + final/test/CodeGen/ARM/prefetch.ll | 61 + final/test/CodeGen/ARM/private.ll | 22 + final/test/CodeGen/ARM/reg_sequence.ll | 348 + final/test/CodeGen/ARM/ret0.ll | 5 + final/test/CodeGen/ARM/ret_arg1.ll | 5 + final/test/CodeGen/ARM/ret_arg2.ll | 6 + final/test/CodeGen/ARM/ret_arg3.ll | 5 + final/test/CodeGen/ARM/ret_arg4.ll | 5 + final/test/CodeGen/ARM/ret_arg5.ll | 5 + final/test/CodeGen/ARM/ret_f32_arg2.ll | 6 + final/test/CodeGen/ARM/ret_f32_arg5.ll | 6 + final/test/CodeGen/ARM/ret_f64_arg2.ll | 6 + .../test/CodeGen/ARM/ret_f64_arg_reg_split.ll | 6 + final/test/CodeGen/ARM/ret_f64_arg_split.ll | 6 + final/test/CodeGen/ARM/ret_f64_arg_stack.ll | 6 + final/test/CodeGen/ARM/ret_i128_arg2.ll | 6 + final/test/CodeGen/ARM/ret_i64_arg2.ll | 6 + final/test/CodeGen/ARM/ret_i64_arg3.ll | 6 + final/test/CodeGen/ARM/ret_i64_arg_split.ll | 6 + final/test/CodeGen/ARM/ret_void.ll | 6 + final/test/CodeGen/ARM/rev.ll | 30 + final/test/CodeGen/ARM/sbfx.ll | 47 + final/test/CodeGen/ARM/section.ll | 7 + final/test/CodeGen/ARM/select-imm.ll | 78 + final/test/CodeGen/ARM/select.ll | 115 + final/test/CodeGen/ARM/select_xform.ll | 60 + final/test/CodeGen/ARM/shifter_operand.ll | 72 + final/test/CodeGen/ARM/smul.ll | 36 + final/test/CodeGen/ARM/spill-q.ll | 91 + final/test/CodeGen/ARM/stack-frame.ll | 13 + final/test/CodeGen/ARM/stm.ll | 16 + final/test/CodeGen/ARM/str_post.ll | 22 + final/test/CodeGen/ARM/str_pre-2.ll | 13 + final/test/CodeGen/ARM/str_pre.ll | 18 + final/test/CodeGen/ARM/str_trunc.ll | 16 + final/test/CodeGen/ARM/sub.ll | 29 + final/test/CodeGen/ARM/sxt_rot.ll | 29 + final/test/CodeGen/ARM/t2-imm.ll | 9 + final/test/CodeGen/ARM/tail-opts.ll | 67 + final/test/CodeGen/ARM/thread_pointer.ll | 10 + final/test/CodeGen/ARM/thumb1-varalloc.ll | 40 + final/test/CodeGen/ARM/tls1.ll | 20 + final/test/CodeGen/ARM/tls2.ll | 27 + final/test/CodeGen/ARM/tls3.ll | 11 + final/test/CodeGen/ARM/trap.ll | 12 + final/test/CodeGen/ARM/trunc_ldr.ll | 24 + .../CodeGen/ARM/truncstore-dag-combine.ll | 18 + final/test/CodeGen/ARM/tst_teq.ll | 18 + final/test/CodeGen/ARM/uint64tof64.ll | 17 + final/test/CodeGen/ARM/umulo-32.ll | 14 + .../test/CodeGen/ARM/unaligned_load_store.ll | 29 + final/test/CodeGen/ARM/unord.ll | 14 + final/test/CodeGen/ARM/uxt_rot.ll | 24 + final/test/CodeGen/ARM/uxtb.ll | 74 + final/test/CodeGen/ARM/va_arg.ll | 41 + final/test/CodeGen/ARM/vaba.ll | 221 + final/test/CodeGen/ARM/vabd.ll | 207 + final/test/CodeGen/ARM/vabs.ll | 131 + final/test/CodeGen/ARM/vadd.ll | 279 + final/test/CodeGen/ARM/vargs.ll | 12 + final/test/CodeGen/ARM/vargs_align.ll | 23 + final/test/CodeGen/ARM/vbits.ll | 547 + final/test/CodeGen/ARM/vbsl.ll | 105 + final/test/CodeGen/ARM/vceq.ll | 92 + final/test/CodeGen/ARM/vcge.ll | 203 + final/test/CodeGen/ARM/vcgt.ll | 197 + final/test/CodeGen/ARM/vcnt.ll | 132 + final/test/CodeGen/ARM/vcombine.ll | 72 + final/test/CodeGen/ARM/vcvt.ll | 158 + final/test/CodeGen/ARM/vdup.ll | 263 + final/test/CodeGen/ARM/vector-DAGCombine.ll | 107 + final/test/CodeGen/ARM/vext.ll | 135 + final/test/CodeGen/ARM/vfcmp.ll | 139 + final/test/CodeGen/ARM/vfp.ll | 155 + final/test/CodeGen/ARM/vget_lane.ll | 233 + final/test/CodeGen/ARM/vhadd.ll | 249 + final/test/CodeGen/ARM/vhsub.ll | 125 + final/test/CodeGen/ARM/vicmp.ll | 113 + final/test/CodeGen/ARM/vld1.ll | 142 + final/test/CodeGen/ARM/vld2.ll | 155 + final/test/CodeGen/ARM/vld3.ll | 158 + final/test/CodeGen/ARM/vld4.ll | 160 + final/test/CodeGen/ARM/vlddup.ll | 212 + final/test/CodeGen/ARM/vldlane.ll | 506 + final/test/CodeGen/ARM/vminmax.ll | 293 + final/test/CodeGen/ARM/vmla.ll | 215 + final/test/CodeGen/ARM/vmls.ll | 215 + final/test/CodeGen/ARM/vmov.ll | 355 + final/test/CodeGen/ARM/vmul.ll | 341 + final/test/CodeGen/ARM/vneg.ll | 121 + final/test/CodeGen/ARM/vpadal.ll | 125 + final/test/CodeGen/ARM/vpadd.ll | 155 + final/test/CodeGen/ARM/vpminmax.ll | 147 + final/test/CodeGen/ARM/vqadd.ll | 165 + final/test/CodeGen/ARM/vqdmul.ll | 281 + final/test/CodeGen/ARM/vqshl.ll | 531 + final/test/CodeGen/ARM/vqshrn.ll | 169 + final/test/CodeGen/ARM/vqsub.ll | 165 + final/test/CodeGen/ARM/vrec.ll | 119 + final/test/CodeGen/ARM/vrev.ll | 149 + final/test/CodeGen/ARM/vshift.ll | 432 + final/test/CodeGen/ARM/vshiftins.ll | 155 + final/test/CodeGen/ARM/vshl.ll | 654 + final/test/CodeGen/ARM/vshll.ll | 83 + final/test/CodeGen/ARM/vshrn.ll | 57 + final/test/CodeGen/ARM/vsra.ll | 341 + final/test/CodeGen/ARM/vst1.ll | 130 + final/test/CodeGen/ARM/vst2.ll | 122 + final/test/CodeGen/ARM/vst3.ll | 128 + final/test/CodeGen/ARM/vst4.ll | 127 + final/test/CodeGen/ARM/vstlane.ll | 364 + final/test/CodeGen/ARM/vsub.ll | 279 + final/test/CodeGen/ARM/vtbl.ll | 109 + final/test/CodeGen/ARM/vtrn.ll | 124 + final/test/CodeGen/ARM/vuzp.ll | 102 + final/test/CodeGen/ARM/vzip.ll | 102 + final/test/CodeGen/ARM/weak.ll | 16 + final/test/CodeGen/ARM/weak2.ll | 18 + .../Alpha/2005-07-12-TwoMallocCalls.ll | 17 + .../CodeGen/Alpha/2005-12-12-MissingFCMov.ll | 40 + .../CodeGen/Alpha/2006-01-18-MissedGlobal.ll | 27 + .../CodeGen/Alpha/2006-01-26-VaargBreak.ll | 14 + .../test/CodeGen/Alpha/2006-04-04-zextload.ll | 34 + .../Alpha/2006-07-03-ASMFormalLowering.ll | 18 + .../test/CodeGen/Alpha/2006-11-01-vastart.ll | 15 + .../test/CodeGen/Alpha/2007-11-27-mulneg3.ll | 13 + .../CodeGen/Alpha/2008-11-10-smul_lohi.ll | 22 + final/test/CodeGen/Alpha/2008-11-12-Add128.ll | 14 + .../Alpha/2009-07-16-PromoteFloatCompare.ll | 6 + .../Alpha/2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/Alpha/2010-08-01-mulreduce64.ll | 11 + final/test/CodeGen/Alpha/add.ll | 178 + final/test/CodeGen/Alpha/add128.ll | 9 + final/test/CodeGen/Alpha/bic.ll | 9 + final/test/CodeGen/Alpha/bsr.ll | 12 + final/test/CodeGen/Alpha/call_adj.ll | 13 + final/test/CodeGen/Alpha/cmov.ll | 23 + final/test/CodeGen/Alpha/cmpbge.ll | 16 + final/test/CodeGen/Alpha/ctlz.ll | 14 + final/test/CodeGen/Alpha/ctlz_e.ll | 11 + final/test/CodeGen/Alpha/ctpop.ll | 17 + final/test/CodeGen/Alpha/dg.exp | 5 + final/test/CodeGen/Alpha/eqv.ll | 10 + final/test/CodeGen/Alpha/i32_sub_1.ll | 9 + .../CodeGen/Alpha/illegal-element-type.ll | 23 + final/test/CodeGen/Alpha/jmp_table.ll | 99 + final/test/CodeGen/Alpha/mb.ll | 8 + final/test/CodeGen/Alpha/mul128.ll | 7 + final/test/CodeGen/Alpha/mul5.ll | 33 + final/test/CodeGen/Alpha/neg1.ll | 7 + final/test/CodeGen/Alpha/not.ll | 8 + final/test/CodeGen/Alpha/ornot.ll | 10 + final/test/CodeGen/Alpha/private.ll | 21 + final/test/CodeGen/Alpha/rpcc.ll | 9 + final/test/CodeGen/Alpha/srl_and.ll | 10 + final/test/CodeGen/Alpha/sub128.ll | 9 + final/test/CodeGen/Alpha/weak.ll | 16 + final/test/CodeGen/Alpha/wmb.ll | 8 + final/test/CodeGen/Alpha/zapnot.ll | 9 + final/test/CodeGen/Alpha/zapnot2.ll | 9 + final/test/CodeGen/Alpha/zapnot3.ll | 15 + final/test/CodeGen/Alpha/zapnot4.ll | 7 + .../Blackfin/2009-08-04-LowerExtract-Live.ll | 15 + .../Blackfin/2009-08-11-RegScavenger-CSR.ll | 17 + .../Blackfin/2009-08-15-LiveIn-SubReg.ll | 19 + .../Blackfin/2009-08-15-MissingDead.ll | 25 + .../Blackfin/2009-08-15-SetCC-Undef.ll | 16 + final/test/CodeGen/Blackfin/add-overflow.ll | 18 + final/test/CodeGen/Blackfin/add.ll | 5 + final/test/CodeGen/Blackfin/addsub-i128.ll | 42 + final/test/CodeGen/Blackfin/basic-i1.ll | 51 + final/test/CodeGen/Blackfin/basic-i16.ll | 36 + final/test/CodeGen/Blackfin/basic-i32.ll | 51 + final/test/CodeGen/Blackfin/basic-i64.ll | 51 + final/test/CodeGen/Blackfin/basic-i8.ll | 51 + final/test/CodeGen/Blackfin/basictest.ll | 19 + final/test/CodeGen/Blackfin/burg.ll | 19 + final/test/CodeGen/Blackfin/cmp-small-imm.ll | 6 + final/test/CodeGen/Blackfin/cmp64.ll | 17 + final/test/CodeGen/Blackfin/ct32.ll | 20 + final/test/CodeGen/Blackfin/ct64.ll | 20 + final/test/CodeGen/Blackfin/ctlz16.ll | 18 + final/test/CodeGen/Blackfin/ctlz64.ll | 15 + final/test/CodeGen/Blackfin/ctpop16.ll | 18 + final/test/CodeGen/Blackfin/cttz16.ll | 18 + final/test/CodeGen/Blackfin/cycles.ll | 17 + final/test/CodeGen/Blackfin/dg.exp | 5 + final/test/CodeGen/Blackfin/double-cast.ll | 8 + final/test/CodeGen/Blackfin/frameindex.ll | 10 + final/test/CodeGen/Blackfin/i17mem.ll | 9 + final/test/CodeGen/Blackfin/i1mem.ll | 9 + final/test/CodeGen/Blackfin/i1ops.ll | 10 + final/test/CodeGen/Blackfin/i216mem.ll | 9 + final/test/CodeGen/Blackfin/i248mem.ll | 9 + final/test/CodeGen/Blackfin/i256mem.ll | 9 + final/test/CodeGen/Blackfin/i256param.ll | 7 + final/test/CodeGen/Blackfin/i56param.ll | 8 + final/test/CodeGen/Blackfin/i8mem.ll | 10 + final/test/CodeGen/Blackfin/inline-asm.ll | 38 + final/test/CodeGen/Blackfin/int-setcc.ll | 80 + final/test/CodeGen/Blackfin/invalid-apint.ll | 15 + final/test/CodeGen/Blackfin/jumptable.ll | 53 + final/test/CodeGen/Blackfin/large-switch.ll | 187 + final/test/CodeGen/Blackfin/load-i16.ll | 13 + final/test/CodeGen/Blackfin/logic-i16.ll | 16 + final/test/CodeGen/Blackfin/many-args.ll | 23 + final/test/CodeGen/Blackfin/mulhu.ll | 106 + final/test/CodeGen/Blackfin/printf.ll | 10 + final/test/CodeGen/Blackfin/printf2.ll | 8 + final/test/CodeGen/Blackfin/promote-logic.ll | 42 + final/test/CodeGen/Blackfin/promote-setcc.ll | 37 + final/test/CodeGen/Blackfin/sdiv.ll | 5 + final/test/CodeGen/Blackfin/simple-select.ll | 11 + final/test/CodeGen/Blackfin/switch.ll | 18 + final/test/CodeGen/Blackfin/switch2.ll | 16 + final/test/CodeGen/Blackfin/sync-intr.ll | 16 + .../CBackend/2002-05-16-NameCollide.ll | 8 + .../CBackend/2002-05-21-MissingReturn.ll | 20 + .../CBackend/2002-08-19-ConstPointerRef.ll | 7 + .../CBackend/2002-08-19-ConstantExpr.ll | 8 + .../CBackend/2002-08-19-DataPointer.ll | 4 + .../CBackend/2002-08-19-FunctionPointer.ll | 5 + .../CBackend/2002-08-19-HardConstantExpr.ll | 5 + .../CBackend/2002-08-20-RecursiveTypes.ll | 3 + .../CBackend/2002-08-20-UnnamedArgument.ll | 10 + .../CBackend/2002-08-26-IndirectCallTest.ll | 17 + .../2002-08-30-StructureOrderingTest.ll | 8 + .../CBackend/2002-09-20-ArrayTypeFailure.ll | 7 + .../CBackend/2002-09-20-VarArgPrototypes.ll | 6 + .../CBackend/2002-10-15-OpaqueTypeProblem.ll | 6 + .../CodeGen/CBackend/2002-10-16-External.ll | 4 + .../2002-10-30-FunctionPointerAlloca.ll | 10 + .../CBackend/2002-11-06-PrintEscaped.ll | 11 + .../CBackend/2003-05-12-IntegerSizeWarning.ll | 8 + .../CBackend/2003-05-13-VarArgFunction.ll | 11 + .../CBackend/2003-05-31-MissingStructName.ll | 5 + .../CBackend/2003-06-01-NullPointerType.ll | 9 + .../CBackend/2003-06-11-HexConstant.ll | 4 + .../2003-06-11-LiteralStringProblem.ll | 3 + .../CBackend/2003-06-28-InvokeSupport.ll | 17 + .../CBackend/2003-06-28-LinkOnceGlobalVars.ll | 3 + .../CBackend/2003-10-12-NANGlobalInits.ll | 5 + .../CodeGen/CBackend/2003-10-23-UnusedType.ll | 8 + .../CBackend/2003-10-28-CastToPtrToStruct.ll | 12 + .../CBackend/2003-11-21-ConstantShiftExpr.ll | 13 + .../CBackend/2004-02-13-FrameReturnAddress.ll | 16 + .../2004-02-15-PreexistingExternals.ll | 18 + .../2004-02-26-FPNotPrintableConstants.ll | 11 + .../CBackend/2004-02-26-LinkOnceFunctions.ll | 6 + .../CBackend/2004-08-09-va-end-null.ll | 10 + .../2004-11-13-FunctionPointerCast.ll | 12 + .../CBackend/2004-12-03-ExternStatics.ll | 10 + .../2004-12-28-LogicalConstantExprs.ll | 5 + .../CBackend/2005-02-14-VolatileOperations.ll | 8 + .../CBackend/2005-03-08-RecursiveTypeCrash.ll | 5 + .../2005-07-14-NegationToMinusMinus.ll | 18 + .../test/CodeGen/CBackend/2005-08-23-Fmod.ll | 7 + .../CBackend/2005-09-27-VolatileFuncPtr.ll | 10 + .../CBackend/2006-12-11-Float-Bitcast.ll | 49 + .../CBackend/2007-01-08-ParamAttr-ICmp.ll | 26 + .../CBackend/2007-01-15-NamedArrayType.ll | 11 + .../CBackend/2007-01-17-StackSaveNRestore.ll | 12 + .../CodeGen/CBackend/2007-02-05-memset.ll | 13 + .../CBackend/2007-02-23-NameConflicts.ll | 14 + .../CBackend/2007-07-11-PackedStruct.ll | 9 + .../CBackend/2008-02-01-UnalignedLoadStore.ll | 15 + .../CBackend/2008-05-21-MRV-InlineAsm.ll | 19 + .../CBackend/2008-05-31-BoolOverflow.ll | 14 + .../CBackend/2008-06-04-IndirectMem.ll | 12 + .../2008-10-21-PPCLongDoubleConstant.ll | 29 + final/test/CodeGen/CBackend/dg.exp | 5 + final/test/CodeGen/CBackend/fneg.ll | 7 + final/test/CodeGen/CBackend/pr2408.ll | 12 + final/test/CodeGen/CBackend/vectors.ll | 37 + final/test/CodeGen/CPP/2007-06-16-Funcname.ll | 7 + .../CodeGen/CPP/2009-05-01-Long-Double.ll | 13 + final/test/CodeGen/CPP/2009-05-04-CondBr.ll | 28 + final/test/CodeGen/CPP/dg.exp | 5 + final/test/CodeGen/CPP/llvm2cpp.ll | 756 + .../test/CodeGen/CellSPU/2009-01-01-BrCond.ll | 31 + .../2010-04-07-DbgValueOtherTargets.ll | 28 + final/test/CodeGen/CellSPU/and_ops.ll | 279 + final/test/CodeGen/CellSPU/arg_ret.ll | 34 + final/test/CodeGen/CellSPU/bigstack.ll | 17 + final/test/CodeGen/CellSPU/bss.ll | 11 + final/test/CodeGen/CellSPU/call.ll | 53 + final/test/CodeGen/CellSPU/call_indirect.ll | 49 + final/test/CodeGen/CellSPU/crash.ll | 8 + final/test/CodeGen/CellSPU/ctpop.ll | 30 + final/test/CodeGen/CellSPU/dg.exp | 5 + final/test/CodeGen/CellSPU/div_ops.ll | 22 + final/test/CodeGen/CellSPU/dp_farith.ll | 102 + final/test/CodeGen/CellSPU/eqv.ll | 152 + final/test/CodeGen/CellSPU/extract_elt.ll | 277 + final/test/CodeGen/CellSPU/fcmp32.ll | 36 + final/test/CodeGen/CellSPU/fcmp64.ll | 7 + final/test/CodeGen/CellSPU/fdiv.ll | 22 + final/test/CodeGen/CellSPU/fneg-fabs.ll | 42 + final/test/CodeGen/CellSPU/i64ops.ll | 57 + final/test/CodeGen/CellSPU/i8ops.ll | 25 + final/test/CodeGen/CellSPU/icmp16.ll | 350 + final/test/CodeGen/CellSPU/icmp32.ll | 350 + final/test/CodeGen/CellSPU/icmp64.ll | 146 + final/test/CodeGen/CellSPU/icmp8.ll | 286 + final/test/CodeGen/CellSPU/immed16.ll | 40 + final/test/CodeGen/CellSPU/immed32.ll | 83 + final/test/CodeGen/CellSPU/immed64.ll | 95 + final/test/CodeGen/CellSPU/int2fp.ll | 41 + .../test/CodeGen/CellSPU/intrinsics_branch.ll | 150 + .../test/CodeGen/CellSPU/intrinsics_float.ll | 94 + .../CodeGen/CellSPU/intrinsics_logical.ll | 49 + final/test/CodeGen/CellSPU/jumptable.ll | 21 + final/test/CodeGen/CellSPU/loads.ll | 59 + .../test/CodeGen/CellSPU/mul-with-overflow.ll | 15 + final/test/CodeGen/CellSPU/mul_ops.ll | 88 + final/test/CodeGen/CellSPU/nand.ll | 121 + final/test/CodeGen/CellSPU/or_ops.ll | 264 + final/test/CodeGen/CellSPU/private.ll | 22 + final/test/CodeGen/CellSPU/rotate_ops.ll | 172 + final/test/CodeGen/CellSPU/select_bits.ll | 569 + final/test/CodeGen/CellSPU/sext128.ll | 71 + final/test/CodeGen/CellSPU/shift_ops.ll | 344 + final/test/CodeGen/CellSPU/shuffles.ll | 67 + final/test/CodeGen/CellSPU/sp_farith.ll | 90 + final/test/CodeGen/CellSPU/stores.ll | 181 + final/test/CodeGen/CellSPU/storestruct.ll | 13 + final/test/CodeGen/CellSPU/struct_1.ll | 144 + final/test/CodeGen/CellSPU/sub_ops.ll | 26 + final/test/CodeGen/CellSPU/trunc.ll | 94 + .../CellSPU/useful-harnesses/README.txt | 5 + .../CellSPU/useful-harnesses/i32operations.c | 69 + .../CellSPU/useful-harnesses/i64operations.c | 673 + .../CellSPU/useful-harnesses/i64operations.h | 43 + .../CellSPU/useful-harnesses/lit.local.cfg | 1 + .../CellSPU/useful-harnesses/vecoperations.c | 179 + final/test/CodeGen/CellSPU/v2f32.ll | 74 + final/test/CodeGen/CellSPU/v2i32.ll | 77 + final/test/CodeGen/CellSPU/vec_const.ll | 154 + final/test/CodeGen/CellSPU/vecinsert.ll | 131 + .../2002-04-14-UnexpectedUnsignedType.ll | 13 + .../2002-04-16-StackFrameSizeAlignment.ll | 14 + .../CodeGen/Generic/2003-05-27-phifcmpd.ll | 19 + .../Generic/2003-05-27-useboolinotherbb.ll | 13 + .../Generic/2003-05-27-usefsubasbool.ll | 14 + .../CodeGen/Generic/2003-05-28-ManyArgs.ll | 153 + .../CodeGen/Generic/2003-05-30-BadFoldGEP.ll | 39 + .../Generic/2003-05-30-BadPreselectPhi.ll | 33 + .../CodeGen/Generic/2003-07-06-BadIntCmp.ll | 51 + .../Generic/2003-07-07-BadLongConst.ll | 20 + .../Generic/2003-07-08-BadCastToBool.ll | 34 + .../Generic/2003-07-29-BadConstSbyte.ll | 40 + .../Generic/2004-02-08-UnwindSupport.ll | 17 + .../2004-05-09-LiveVarPartialRegister.ll | 13 + .../Generic/2005-01-18-SetUO-InfLoop.ll | 20 + .../CodeGen/Generic/2005-04-09-GlobalInPHI.ll | 20 + .../Generic/2005-07-12-memcpy-i64-length.ll | 11 + .../Generic/2005-10-18-ZeroSizeStackObject.ll | 6 + .../CodeGen/Generic/2005-10-21-longlonggtu.ll | 16 + .../test/CodeGen/Generic/2005-12-01-Crash.ll | 20 + .../Generic/2005-12-12-ExpandSextInreg.ll | 7 + .../Generic/2006-01-12-BadSetCCFold.ll | 35 + .../2006-01-18-InvalidBranchOpcodeAssert.ll | 15 + .../Generic/2006-02-12-InsertLibcall.ll | 60 + .../Generic/2006-03-01-dagcombineinfloop.ll | 95 + .../CodeGen/Generic/2006-04-26-SetCCAnd.ll | 40 + .../Generic/2006-04-28-Sign-extend-bool.ll | 9 + .../Generic/2006-05-06-GEP-Cast-Sink-Crash.ll | 29 + .../Generic/2006-06-12-LowerSwitchCrash.ll | 10 + .../2006-06-13-ComputeMaskedBitsCrash.ll | 35 + .../Generic/2006-06-28-SimplifySetCCCrash.ll | 279 + .../CodeGen/Generic/2006-07-03-schedulers.ll | 32 + .../Generic/2006-08-30-CoalescerCrash.ll | 112 + .../Generic/2006-09-02-LocalAllocCrash.ll | 117 + .../Generic/2006-09-06-SwitchLowering.ll | 96 + .../CodeGen/Generic/2006-10-27-CondFolding.ll | 21 + .../test/CodeGen/Generic/2006-10-29-Crash.ll | 22 + .../Generic/2006-11-20-DAGCombineCrash.ll | 41 + .../Generic/2007-01-15-LoadSelectCycle.ll | 12 + .../test/CodeGen/Generic/2007-02-25-invoke.ll | 12 + .../2007-04-08-MultipleFrameIndices.ll | 11 + .../Generic/2007-04-13-SwitchLowerBadPhi.ll | 24 + .../CodeGen/Generic/2007-04-17-lsr-crash.ll | 35 + .../Generic/2007-04-27-InlineAsm-X-Dest.ll | 8 + .../Generic/2007-04-27-LargeMemObject.ll | 13 + .../2007-04-30-LandingPadBranchFolding.ll | 59 + .../CodeGen/Generic/2007-05-03-EHTypeInfo.ll | 12 + .../Generic/2007-05-15-InfiniteRecursion.ll | 90 + .../Generic/2007-11-21-UndeadIllegalNode.ll | 157 + .../CodeGen/Generic/2007-12-17-InvokeAsm.ll | 13 + .../Generic/2007-12-31-UnusedSelector.ll | 34 + .../Generic/2008-01-25-dag-combine-mul.ll | 31 + .../CodeGen/Generic/2008-01-30-LoadCrash.ll | 19 + final/test/CodeGen/Generic/2008-02-04-Ctlz.ll | 21 + .../Generic/2008-02-04-ExtractSubvector.ll | 14 + .../CodeGen/Generic/2008-02-20-MatchingMem.ll | 9 + .../CodeGen/Generic/2008-02-25-NegateZero.ll | 14 + .../Generic/2008-02-26-NegatableCrash.ll | 50 + .../Generic/2008-08-07-PtrToInt-SmallerInt.ll | 5 + .../CodeGen/Generic/2009-03-17-LSR-APInt.ll | 92 + .../2009-03-29-SoftFloatVectorExtract.ll | 10 + .../CodeGen/Generic/2009-04-10-SinkCrash.ll | 16 + .../Generic/2009-04-28-i128-cmp-crash.ll | 32 + .../Generic/2009-06-03-UnreachableSplitPad.ll | 15 + .../Generic/2009-11-16-BadKillsCrash.ll | 73 + .../Generic/2010-07-27-DAGCombineCrash.ll | 6 + .../CodeGen/Generic/2010-11-04-BigByval.ll | 11 + .../test/CodeGen/Generic/2010-ZeroSizedArg.ll | 17 + .../Generic/2011-01-06-BigNumberCrash.ll | 15 + .../CodeGen/Generic/2011-02-12-shuffle.ll | 32 + final/test/CodeGen/Generic/APIntLoadStore.ll | 2049 ++ final/test/CodeGen/Generic/APIntParam.ll | 1537 + final/test/CodeGen/Generic/APIntSextParam.ll | 1537 + final/test/CodeGen/Generic/APIntZextParam.ll | 1537 + final/test/CodeGen/Generic/BasicInstrs.ll | 54 + final/test/CodeGen/Generic/BurgBadRegAlloc.ll | 829 + .../CodeGen/Generic/ConstantExprLowering.ll | 22 + final/test/CodeGen/Generic/Makefile | 23 + .../CodeGen/Generic/add-with-overflow-128.ll | 34 + .../CodeGen/Generic/add-with-overflow-24.ll | 42 + .../test/CodeGen/Generic/add-with-overflow.ll | 41 + final/test/CodeGen/Generic/addr-label.ll | 81 + .../CodeGen/Generic/asm-large-immediate.ll | 8 + .../test/CodeGen/Generic/badCallArgLRLLVM.ll | 31 + final/test/CodeGen/Generic/badFoldGEP.ll | 27 + final/test/CodeGen/Generic/badarg6.ll | 32 + final/test/CodeGen/Generic/badlive.ll | 28 + final/test/CodeGen/Generic/bool-to-double.ll | 6 + final/test/CodeGen/Generic/bool-vector.ll | 11 + final/test/CodeGen/Generic/call-ret0.ll | 10 + final/test/CodeGen/Generic/call-ret42.ll | 10 + final/test/CodeGen/Generic/call-void.ll | 11 + final/test/CodeGen/Generic/call2-ret0.ll | 16 + final/test/CodeGen/Generic/cast-fp.ll | 33 + final/test/CodeGen/Generic/constindices.ll | 44 + final/test/CodeGen/Generic/crash.ll | 40 + final/test/CodeGen/Generic/dbg_value.ll | 13 + final/test/CodeGen/Generic/dg.exp | 3 + final/test/CodeGen/Generic/div-neg-power-2.ll | 7 + .../test/CodeGen/Generic/empty-load-store.ll | 18 + .../CodeGen/Generic/externally_available.ll | 10 + final/test/CodeGen/Generic/fastcall.ll | 14 + final/test/CodeGen/Generic/fneg-fabs.ll | 26 + .../test/CodeGen/Generic/fp-to-int-invalid.ll | 18 + final/test/CodeGen/Generic/fp_to_int.ll | 81 + final/test/CodeGen/Generic/fpowi-promote.ll | 11 + final/test/CodeGen/Generic/fwdtwice.ll | 29 + final/test/CodeGen/Generic/getresult-undef.ll | 6 + final/test/CodeGen/Generic/global-ret0.ll | 8 + final/test/CodeGen/Generic/hello.ll | 11 + final/test/CodeGen/Generic/i128-addsub.ll | 39 + final/test/CodeGen/Generic/i128-arith.ll | 11 + .../Generic/inline-asm-special-strings.ll | 6 + final/test/CodeGen/Generic/intrinsics.ll | 40 + final/test/CodeGen/Generic/invalid-memcpy.ll | 19 + final/test/CodeGen/Generic/isunord.ll | 9 + .../CodeGen/Generic/legalize-dbg-value.ll | 25 + .../CodeGen/Generic/llvm-ct-intrinsics.ll | 62 + ...e-return-values-cross-block-with-invoke.ll | 18 + final/test/CodeGen/Generic/negintconst.ll | 47 + final/test/CodeGen/Generic/nested-select.ll | 19 + final/test/CodeGen/Generic/overflow.ll | 220 + final/test/CodeGen/Generic/pr2625.ll | 17 + final/test/CodeGen/Generic/pr3288.ll | 67 + final/test/CodeGen/Generic/print-add.ll | 18 + final/test/CodeGen/Generic/print-arith-fp.ll | 61 + final/test/CodeGen/Generic/print-arith-int.ll | 84 + final/test/CodeGen/Generic/print-int.ll | 13 + final/test/CodeGen/Generic/print-mul-exp.ll | 55 + final/test/CodeGen/Generic/print-mul.ll | 32 + final/test/CodeGen/Generic/print-shift.ll | 34 + final/test/CodeGen/Generic/ret0.ll | 5 + final/test/CodeGen/Generic/ret42.ll | 5 + final/test/CodeGen/Generic/select-cc.ll | 9 + final/test/CodeGen/Generic/select.ll | 187 + final/test/CodeGen/Generic/shift-int64.ll | 12 + final/test/CodeGen/Generic/spillccr.ll | 49 + .../test/CodeGen/Generic/stacksave-restore.ll | 14 + final/test/CodeGen/Generic/storetrunc-fp.ll | 8 + .../CodeGen/Generic/switch-lower-feature.ll | 63 + final/test/CodeGen/Generic/switch-lower.ll | 348 + final/test/CodeGen/Generic/trap.ll | 9 + final/test/CodeGen/Generic/v-split.ll | 11 + final/test/CodeGen/Generic/vector-casts.ll | 45 + .../CodeGen/Generic/vector-constantexpr.ll | 7 + .../Generic/vector-identity-shuffle.ll | 17 + final/test/CodeGen/Generic/vector.ll | 154 + .../MBlaze/2010-04-07-DbgValueOtherTargets.ll | 28 + final/test/CodeGen/MBlaze/brind.ll | 72 + final/test/CodeGen/MBlaze/callind.ll | 80 + final/test/CodeGen/MBlaze/cc.ll | 266 + final/test/CodeGen/MBlaze/dg.exp | 5 + final/test/CodeGen/MBlaze/div.ll | 75 + final/test/CodeGen/MBlaze/fpu.ll | 66 + final/test/CodeGen/MBlaze/fsl.ll | 323 + final/test/CodeGen/MBlaze/imm.ll | 70 + final/test/CodeGen/MBlaze/intr.ll | 48 + final/test/CodeGen/MBlaze/jumptable.ll | 79 + final/test/CodeGen/MBlaze/loop.ll | 46 + final/test/CodeGen/MBlaze/mul.ll | 51 + final/test/CodeGen/MBlaze/mul64.ll | 23 + final/test/CodeGen/MBlaze/select.ll | 15 + final/test/CodeGen/MBlaze/shift.ll | 115 + final/test/CodeGen/MBlaze/svol.ll | 80 + .../CodeGen/MSP430/2009-05-10-CyclicDAG.ll | 32 + final/test/CodeGen/MSP430/2009-05-17-Rot.ll | 17 + final/test/CodeGen/MSP430/2009-05-17-Shift.ll | 15 + .../CodeGen/MSP430/2009-05-19-DoubleSplit.ll | 11 + .../MSP430/2009-08-25-DynamicStackAlloc.ll | 30 + .../CodeGen/MSP430/2009-09-18-AbsoluteAddr.ll | 22 + .../CodeGen/MSP430/2009-10-10-OrImpDef.ll | 14 + .../CodeGen/MSP430/2009-11-05-8BitLibcalls.ll | 22 + .../CodeGen/MSP430/2009-11-08-InvalidResNo.ll | 64 + .../test/CodeGen/MSP430/2009-11-20-NewNode.ll | 36 + .../CodeGen/MSP430/2009-12-21-FrameAddr.ll | 13 + .../CodeGen/MSP430/2009-12-22-InlineAsm.ll | 29 + .../MSP430/2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/MSP430/2010-05-01-CombinerAnd.ll | 27 + final/test/CodeGen/MSP430/AddrMode-bis-rx.ll | 74 + final/test/CodeGen/MSP430/AddrMode-bis-xr.ll | 81 + final/test/CodeGen/MSP430/AddrMode-mov-rx.ll | 67 + final/test/CodeGen/MSP430/AddrMode-mov-xr.ll | 67 + final/test/CodeGen/MSP430/Inst16mi.ll | 48 + final/test/CodeGen/MSP430/Inst16mm.ll | 69 + final/test/CodeGen/MSP430/Inst16mr.ll | 58 + final/test/CodeGen/MSP430/Inst16ri.ll | 37 + final/test/CodeGen/MSP430/Inst16rm.ll | 46 + final/test/CodeGen/MSP430/Inst16rr.ll | 45 + final/test/CodeGen/MSP430/Inst8mi.ll | 48 + final/test/CodeGen/MSP430/Inst8mm.ll | 55 + final/test/CodeGen/MSP430/Inst8mr.ll | 58 + final/test/CodeGen/MSP430/Inst8ri.ll | 37 + final/test/CodeGen/MSP430/Inst8rm.ll | 46 + final/test/CodeGen/MSP430/Inst8rr.ll | 46 + final/test/CodeGen/MSP430/bit.ll | 166 + final/test/CodeGen/MSP430/dg.exp | 5 + final/test/CodeGen/MSP430/indirectbr.ll | 41 + final/test/CodeGen/MSP430/indirectbr2.ll | 29 + final/test/CodeGen/MSP430/inline-asm.ll | 26 + .../CodeGen/MSP430/mult-alt-generic-msp430.ll | 323 + final/test/CodeGen/MSP430/postinc.ll | 114 + final/test/CodeGen/MSP430/setcc.ll | 116 + final/test/CodeGen/MSP430/shifts.ll | 51 + final/test/CodeGen/Mips/2008-06-05-Carry.ll | 19 + final/test/CodeGen/Mips/2008-07-03-SRet.ll | 17 + final/test/CodeGen/Mips/2008-07-05-ByVal.ll | 18 + final/test/CodeGen/Mips/2008-07-06-fadd64.ll | 10 + .../test/CodeGen/Mips/2008-07-07-FPExtend.ll | 10 + .../test/CodeGen/Mips/2008-07-07-Float2Int.ll | 16 + .../Mips/2008-07-07-IntDoubleConvertions.ll | 33 + .../Mips/2008-07-15-InternalConstant.ll | 22 + .../CodeGen/Mips/2008-07-15-SmallSection.ll | 32 + .../CodeGen/Mips/2008-07-16-SignExtInReg.ll | 19 + final/test/CodeGen/Mips/2008-07-22-Cstpool.ll | 12 + final/test/CodeGen/Mips/2008-07-23-fpcmp.ll | 34 + final/test/CodeGen/Mips/2008-07-29-icmp.ll | 11 + .../test/CodeGen/Mips/2008-07-31-fcopysign.ll | 14 + .../test/CodeGen/Mips/2008-08-01-AsmInline.ll | 17 + .../CodeGen/Mips/2008-08-03-ReturnDouble.ll | 18 + final/test/CodeGen/Mips/2008-08-03-fabs64.ll | 16 + .../CodeGen/Mips/2008-08-04-Bitconvert.ll | 18 + final/test/CodeGen/Mips/2008-08-06-Alloca.ll | 16 + final/test/CodeGen/Mips/2008-08-07-CC.ll | 12 + final/test/CodeGen/Mips/2008-08-07-FPRound.ll | 10 + final/test/CodeGen/Mips/2008-08-08-bswap.ll | 12 + final/test/CodeGen/Mips/2008-08-08-ctlz.ll | 12 + .../CodeGen/Mips/2008-10-13-LegalizerBug.ll | 29 + .../CodeGen/Mips/2008-11-10-xint_to_fp.ll | 55 + .../CodeGen/Mips/2009-11-16-CstPoolLoad.ll | 10 + .../Mips/2010-04-07-DbgValueOtherTargets.ll | 28 + final/test/CodeGen/Mips/2010-07-20-Select.ll | 21 + final/test/CodeGen/Mips/2010-07-20-Switch.ll | 33 + .../CodeGen/Mips/2010-11-09-CountLeading.ll | 33 + final/test/CodeGen/Mips/2010-11-09-Mul.ll | 15 + final/test/CodeGen/Mips/blockaddr.ll | 26 + final/test/CodeGen/Mips/cmov.ll | 15 + final/test/CodeGen/Mips/dg.exp | 5 + final/test/CodeGen/Mips/divrem.ll | 51 + final/test/CodeGen/Mips/largeimm1.ll | 13 + final/test/CodeGen/Mips/madd-msub.ll | 65 + final/test/CodeGen/Mips/o32_cc.ll | 325 + final/test/CodeGen/Mips/private.ll | 21 + final/test/CodeGen/Mips/rotate.ll | 40 + final/test/CodeGen/PTX/add.ll | 71 + final/test/CodeGen/PTX/dg.exp | 5 + final/test/CodeGen/PTX/exit.ll | 14 + final/test/CodeGen/PTX/intrinsic.ll | 43 + final/test/CodeGen/PTX/ld.ll | 422 + final/test/CodeGen/PTX/mov.ll | 62 + final/test/CodeGen/PTX/mul.ll | 39 + final/test/CodeGen/PTX/options.ll | 9 + final/test/CodeGen/PTX/ret.ll | 7 + final/test/CodeGen/PTX/shl.ll | 22 + final/test/CodeGen/PTX/shr.ll | 43 + final/test/CodeGen/PTX/st.ll | 382 + final/test/CodeGen/PTX/sub.ll | 71 + .../CodeGen/PowerPC/2004-11-29-ShrCrash.ll | 6 + .../CodeGen/PowerPC/2004-11-30-shift-crash.ll | 7 + .../PowerPC/2004-11-30-shr-var-crash.ll | 9 + .../PowerPC/2004-12-12-ZeroSizeCommon.ll | 4 + .../PowerPC/2005-01-14-SetSelectCrash.ll | 8 + .../CodeGen/PowerPC/2005-01-14-UndefLong.ll | 5 + .../PowerPC/2005-08-12-rlwimi-crash.ll | 13 + .../2005-09-02-LegalizeDuplicatesCalls.ll | 11 + .../PowerPC/2005-10-08-ArithmeticRotate.ll | 11 + .../PowerPC/2005-11-30-vastart-crash.ll | 18 + .../PowerPC/2006-01-11-darwin-fp-argument.ll | 10 + .../PowerPC/2006-01-20-ShiftPartsCrash.ll | 19 + .../PowerPC/2006-04-01-FloatDoubleExtend.ll | 9 + .../CodeGen/PowerPC/2006-04-05-splat-ish.ll | 10 + .../PowerPC/2006-04-19-vmaddfp-crash.ll | 58 + .../PowerPC/2006-05-12-rlwimi-crash.ll | 55 + .../PowerPC/2006-07-07-ComputeMaskedBits.ll | 17 + .../PowerPC/2006-07-19-stwbrx-crash.ll | 11 + .../CodeGen/PowerPC/2006-08-11-RetVector.ll | 8 + .../PowerPC/2006-08-15-SelectionCrash.ll | 30 + .../CodeGen/PowerPC/2006-09-28-shift_64.ll | 25 + .../2006-10-11-combiner-aa-regression.ll | 23 + .../CodeGen/PowerPC/2006-10-13-Miscompile.ll | 16 + .../PowerPC/2006-10-17-brcc-miscompile.ll | 20 + .../PowerPC/2006-10-17-ppc64-alloca.ll | 7 + .../2006-11-10-DAGCombineMiscompile.ll | 13 + .../PowerPC/2006-11-29-AltivecFPSplat.ll | 10 + .../CodeGen/PowerPC/2006-12-07-LargeAlloca.ll | 24 + .../CodeGen/PowerPC/2006-12-07-SelectCrash.ll | 22 + .../PowerPC/2007-01-04-ArgExtension.ll | 10 + .../CodeGen/PowerPC/2007-01-15-AsmDialect.ll | 27 + .../CodeGen/PowerPC/2007-01-29-lbrx-asm.ll | 7 + .../PowerPC/2007-01-31-InlineAsmAddrMode.ll | 24 + .../CodeGen/PowerPC/2007-02-16-AlignPacked.ll | 4 + .../2007-02-16-InlineAsmNConstraint.ll | 11 + .../PowerPC/2007-02-23-lr-saved-twice.ll | 14 + .../test/CodeGen/PowerPC/2007-03-24-cntlzd.ll | 12 + .../PowerPC/2007-03-30-SpillerCrash.ll | 1801 ++ .../2007-04-24-InlineAsm-I-Modifier.ll | 14 + .../2007-04-30-InlineAsmEarlyClobber.ll | 31 + .../2007-05-03-InlineAsm-S-Constraint.ll | 12 + .../2007-05-14-InlineAsmSelectCrash.ll | 25 + .../CodeGen/PowerPC/2007-05-22-tailmerge-3.ll | 68 + .../PowerPC/2007-05-30-dagcombine-miscomp.ll | 14 + .../CodeGen/PowerPC/2007-06-28-BCCISelBug.ll | 85 + .../PowerPC/2007-08-04-CoalescerAssert.ll | 28 + .../CodeGen/PowerPC/2007-09-04-AltivecDST.ll | 15 + .../PowerPC/2007-09-07-LoadStoreIdxForms.ll | 16 + .../CodeGen/PowerPC/2007-09-08-unaligned.ll | 53 + .../PowerPC/2007-09-11-RegCoalescerAssert.ll | 9 + .../PowerPC/2007-09-12-LiveIntervalsAssert.ll | 15 + .../2007-10-16-InlineAsmFrameOffset.ll | 14 + .../PowerPC/2007-10-18-PtrArithmetic.ll | 22 + .../PowerPC/2007-10-21-LocalRegAllocAssert.ll | 27 + .../2007-10-21-LocalRegAllocAssert2.ll | 25 + .../PowerPC/2007-11-04-CoalescerCrash.ll | 148 + .../PowerPC/2007-11-16-landingpad-split.ll | 59 + .../PowerPC/2007-11-19-VectorSplitting.ll | 16 + .../PowerPC/2008-02-05-LiveIntervalsAssert.ll | 67 + .../PowerPC/2008-02-09-LocalRegAllocAssert.ll | 10 + .../PowerPC/2008-03-05-RegScavengerAssert.ll | 18 + .../PowerPC/2008-03-17-RegScavengerCrash.ll | 31 + .../PowerPC/2008-03-18-RegScavengerAssert.ll | 6 + .../PowerPC/2008-03-24-AddressRegImm.ll | 25 + .../PowerPC/2008-03-24-CoalescerBug.ll | 30 + .../PowerPC/2008-03-26-CoalescerBug.ll | 28 + .../PowerPC/2008-04-10-LiveIntervalCrash.ll | 100 + .../PowerPC/2008-04-16-CoalescerBug.ll | 14 + .../PowerPC/2008-04-23-CoalescerCrash.ll | 89 + .../CodeGen/PowerPC/2008-05-01-ppc_fp128.ll | 15 + .../PowerPC/2008-06-19-LegalizerCrash.ll | 6 + .../PowerPC/2008-06-21-F128LoadStore.ll | 10 + .../PowerPC/2008-06-23-LiveVariablesCrash.ll | 25 + .../PowerPC/2008-07-10-SplatMiscompile.ll | 10 + .../test/CodeGen/PowerPC/2008-07-15-Bswap.ll | 386 + final/test/CodeGen/PowerPC/2008-07-15-Fabs.ll | 19 + .../PowerPC/2008-07-15-SignExtendInreg.ll | 17 + final/test/CodeGen/PowerPC/2008-07-17-Fneg.ll | 18 + .../CodeGen/PowerPC/2008-07-24-PPC64-CCBug.ll | 11 + .../PowerPC/2008-09-12-CoalescerBug.ll | 254 + .../PowerPC/2008-10-17-AsmMatchingOperands.ll | 11 + .../PowerPC/2008-10-28-UnprocessedNode.ll | 11 + .../CodeGen/PowerPC/2008-10-28-f128-i32.ll | 33 + .../PowerPC/2008-10-30-IllegalShift.ll | 14 + .../PowerPC/2008-10-31-PPCF128Libcalls.ll | 44 + .../PowerPC/2008-12-02-LegalizeTypeAssert.ll | 18 + final/test/CodeGen/PowerPC/2008-12-12-EH.ll | 9 + .../PowerPC/2009-01-16-DeclareISelBug.ll | 19 + .../test/CodeGen/PowerPC/2009-03-17-LSRBug.ll | 51 + .../PowerPC/2009-05-28-LegalizeBRCC.ll | 15 + .../PowerPC/2009-07-16-InlineAsm-M-Operand.ll | 16 + ...009-08-17-inline-asm-addr-mode-breakage.ll | 25 + .../PowerPC/2009-08-23-linkerprivate.ll | 8 + .../CodeGen/PowerPC/2009-09-18-carrybit.ll | 62 + .../PowerPC/2009-11-15-ProcImpDefsBug.ll | 105 + .../CodeGen/PowerPC/2009-11-15-ReMatBug.ll | 155 + .../CodeGen/PowerPC/2009-11-25-ImpDefBug.ll | 56 + .../CodeGen/PowerPC/2010-02-04-EmptyGlobal.ll | 20 + .../test/CodeGen/PowerPC/2010-02-12-saveCR.ll | 30 + .../PowerPC/2010-03-09-indirect-call.ll | 19 + .../PowerPC/2010-04-01-MachineCSEBug.ll | 70 + .../2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/PowerPC/2010-05-03-retaddr1.ll | 24 + .../PowerPC/2010-10-11-Fast-Varargs.ll | 16 + .../PowerPC/2010-12-18-PPCStackRefs.ll | 22 + final/test/CodeGen/PowerPC/Atomics-32.ll | 749 + final/test/CodeGen/PowerPC/Atomics-64.ll | 773 + final/test/CodeGen/PowerPC/Frames-alloca.ll | 30 + final/test/CodeGen/PowerPC/Frames-large.ll | 52 + final/test/CodeGen/PowerPC/Frames-leaf.ll | 37 + final/test/CodeGen/PowerPC/Frames-small.ll | 29 + .../test/CodeGen/PowerPC/LargeAbsoluteAddr.ll | 17 + final/test/CodeGen/PowerPC/addc.ll | 33 + final/test/CodeGen/PowerPC/addi-reassoc.ll | 19 + final/test/CodeGen/PowerPC/align.ll | 46 + final/test/CodeGen/PowerPC/and-branch.ll | 17 + final/test/CodeGen/PowerPC/and-elim.ll | 18 + final/test/CodeGen/PowerPC/and-imm.ll | 14 + final/test/CodeGen/PowerPC/and_add.ll | 15 + final/test/CodeGen/PowerPC/and_sext.ll | 28 + final/test/CodeGen/PowerPC/and_sra.ll | 27 + final/test/CodeGen/PowerPC/atomic-1.ll | 21 + final/test/CodeGen/PowerPC/atomic-2.ll | 21 + .../CodeGen/PowerPC/available-externally.ll | 71 + .../CodeGen/PowerPC/big-endian-actual-args.ll | 9 + .../CodeGen/PowerPC/big-endian-call-result.ll | 13 + .../CodeGen/PowerPC/big-endian-formal-args.ll | 15 + final/test/CodeGen/PowerPC/branch-opt.ll | 71 + .../test/CodeGen/PowerPC/bswap-load-store.ll | 51 + .../CodeGen/PowerPC/buildvec_canonicalize.ll | 24 + final/test/CodeGen/PowerPC/calls.ll | 32 + final/test/CodeGen/PowerPC/cmp-cmp.ll | 13 + .../test/CodeGen/PowerPC/compare-duplicate.ll | 11 + final/test/CodeGen/PowerPC/compare-simm.ll | 14 + final/test/CodeGen/PowerPC/constants.ll | 52 + final/test/CodeGen/PowerPC/cr_spilling.ll | 27 + final/test/CodeGen/PowerPC/cttz.ll | 11 + final/test/CodeGen/PowerPC/darwin-labels.ll | 6 + final/test/CodeGen/PowerPC/delete-node.ll | 22 + final/test/CodeGen/PowerPC/dg.exp | 5 + final/test/CodeGen/PowerPC/div-2.ll | 30 + final/test/CodeGen/PowerPC/empty-functions.ll | 12 + .../test/CodeGen/PowerPC/eqv-andc-orc-nor.ll | 93 + final/test/CodeGen/PowerPC/extsh.ll | 8 + final/test/CodeGen/PowerPC/fabs.ll | 7 + final/test/CodeGen/PowerPC/fma.ll | 54 + final/test/CodeGen/PowerPC/fnabs.ll | 10 + final/test/CodeGen/PowerPC/fneg.ll | 12 + final/test/CodeGen/PowerPC/fold-li.ll | 15 + final/test/CodeGen/PowerPC/fp-branch.ll | 21 + final/test/CodeGen/PowerPC/fp-int-fp.ll | 27 + final/test/CodeGen/PowerPC/fp_to_uint.ll | 8 + final/test/CodeGen/PowerPC/fpcopy.ll | 7 + final/test/CodeGen/PowerPC/frounds.ll | 19 + final/test/CodeGen/PowerPC/fsqrt.ll | 19 + final/test/CodeGen/PowerPC/hello.ll | 12 + final/test/CodeGen/PowerPC/hidden-vis-2.ll | 12 + final/test/CodeGen/PowerPC/hidden-vis.ll | 9 + final/test/CodeGen/PowerPC/i128-and-beyond.ll | 8 + final/test/CodeGen/PowerPC/i64_fp.ll | 26 + final/test/CodeGen/PowerPC/iabs.ll | 15 + .../CodeGen/PowerPC/illegal-element-type.ll | 23 + final/test/CodeGen/PowerPC/indirectbr.ll | 55 + final/test/CodeGen/PowerPC/inlineasm-copy.ll | 14 + final/test/CodeGen/PowerPC/int-fp-conv-0.ll | 17 + final/test/CodeGen/PowerPC/int-fp-conv-1.ll | 11 + final/test/CodeGen/PowerPC/invalid-memcpy.ll | 20 + .../CodeGen/PowerPC/inverted-bool-compares.ll | 13 + final/test/CodeGen/PowerPC/ispositive.ll | 10 + final/test/CodeGen/PowerPC/itofp128.ll | 14 + final/test/CodeGen/PowerPC/lha.ll | 8 + .../CodeGen/PowerPC/load-constant-addr.ll | 9 + final/test/CodeGen/PowerPC/long-compare.ll | 9 + .../test/CodeGen/PowerPC/longdbl-truncate.ll | 9 + final/test/CodeGen/PowerPC/lsr-postinc-pos.ll | 32 + final/test/CodeGen/PowerPC/mask64.ll | 27 + .../test/CodeGen/PowerPC/mem-rr-addr-mode.ll | 18 + final/test/CodeGen/PowerPC/mem_update.ll | 68 + final/test/CodeGen/PowerPC/mul-neg-power-2.ll | 8 + .../test/CodeGen/PowerPC/mul-with-overflow.ll | 15 + final/test/CodeGen/PowerPC/mulhs.ll | 17 + .../PowerPC/mult-alt-generic-powerpc.ll | 321 + .../PowerPC/mult-alt-generic-powerpc64.ll | 321 + .../CodeGen/PowerPC/multiple-return-values.ll | 17 + final/test/CodeGen/PowerPC/neg.ll | 7 + final/test/CodeGen/PowerPC/no-dead-strip.ll | 8 + .../CodeGen/PowerPC/or-addressing-mode.ll | 22 + final/test/CodeGen/PowerPC/ppc-prologue.ll | 28 + final/test/CodeGen/PowerPC/ppcf128-1-opt.ll | 29 + final/test/CodeGen/PowerPC/ppcf128-1.ll | 92 + final/test/CodeGen/PowerPC/ppcf128-2.ll | 14 + final/test/CodeGen/PowerPC/ppcf128-3.ll | 32 + final/test/CodeGen/PowerPC/ppcf128-4.ll | 10 + .../test/CodeGen/PowerPC/pr3711_widen_bit.ll | 18 + final/test/CodeGen/PowerPC/private.ll | 24 + .../CodeGen/PowerPC/reg-coalesce-simple.ll | 12 + final/test/CodeGen/PowerPC/retaddr.ll | 15 + final/test/CodeGen/PowerPC/return-val-i128.ll | 36 + final/test/CodeGen/PowerPC/rlwimi-commute.ll | 34 + final/test/CodeGen/PowerPC/rlwimi-keep-rsh.ll | 28 + final/test/CodeGen/PowerPC/rlwimi.ll | 70 + final/test/CodeGen/PowerPC/rlwimi2.ll | 29 + final/test/CodeGen/PowerPC/rlwimi3.ll | 25 + final/test/CodeGen/PowerPC/rlwinm.ll | 61 + final/test/CodeGen/PowerPC/rlwinm2.ll | 28 + final/test/CodeGen/PowerPC/rotl-2.ll | 38 + final/test/CodeGen/PowerPC/rotl-64.ll | 20 + final/test/CodeGen/PowerPC/rotl.ll | 37 + final/test/CodeGen/PowerPC/sections.ll | 8 + final/test/CodeGen/PowerPC/select-cc.ll | 9 + final/test/CodeGen/PowerPC/select_lt0.ll | 50 + final/test/CodeGen/PowerPC/setcc_no_zext.ll | 9 + final/test/CodeGen/PowerPC/seteq-0.ll | 9 + final/test/CodeGen/PowerPC/shift128.ll | 14 + final/test/CodeGen/PowerPC/shl_elim.ll | 11 + final/test/CodeGen/PowerPC/shl_sext.ll | 18 + final/test/CodeGen/PowerPC/sign_ext_inreg1.ll | 12 + final/test/CodeGen/PowerPC/small-arguments.ll | 52 + final/test/CodeGen/PowerPC/stack-protector.ll | 25 + final/test/CodeGen/PowerPC/stfiwx-2.ll | 11 + final/test/CodeGen/PowerPC/stfiwx.ll | 24 + final/test/CodeGen/PowerPC/store-load-fwd.ll | 8 + final/test/CodeGen/PowerPC/stubs.ll | 22 + final/test/CodeGen/PowerPC/subc.ll | 25 + final/test/CodeGen/PowerPC/tailcall1-64.ll | 11 + final/test/CodeGen/PowerPC/tailcall1.ll | 11 + final/test/CodeGen/PowerPC/tailcallpic1.ll | 14 + final/test/CodeGen/PowerPC/trampoline.ll | 166 + final/test/CodeGen/PowerPC/unsafe-math.ll | 10 + final/test/CodeGen/PowerPC/varargs.ll | 22 + final/test/CodeGen/PowerPC/vcmp-fold.ll | 22 + .../test/CodeGen/PowerPC/vec_auto_constant.ll | 36 + final/test/CodeGen/PowerPC/vec_br_cmp.ll | 22 + .../PowerPC/vec_buildvector_loadstore.ll | 37 + final/test/CodeGen/PowerPC/vec_call.ll | 11 + final/test/CodeGen/PowerPC/vec_constants.ll | 44 + final/test/CodeGen/PowerPC/vec_fneg.ll | 8 + final/test/CodeGen/PowerPC/vec_insert.ll | 8 + final/test/CodeGen/PowerPC/vec_misaligned.ll | 37 + final/test/CodeGen/PowerPC/vec_mul.ll | 23 + .../test/CodeGen/PowerPC/vec_perf_shuffle.ll | 36 + final/test/CodeGen/PowerPC/vec_shift.ll | 10 + final/test/CodeGen/PowerPC/vec_shuffle.ll | 504 + final/test/CodeGen/PowerPC/vec_splat.ll | 71 + .../CodeGen/PowerPC/vec_splat_constant.ll | 24 + final/test/CodeGen/PowerPC/vec_vrsave.ll | 14 + final/test/CodeGen/PowerPC/vec_zero.ll | 9 + .../PowerPC/vector-identity-shuffle.ll | 17 + final/test/CodeGen/PowerPC/vector.ll | 158 + .../SPARC/2006-01-22-BitConvertLegalize.ll | 12 + .../CodeGen/SPARC/2007-05-09-JumpTables.ll | 30 + .../SPARC/2007-07-05-LiveIntervalAssert.ll | 11 + .../2008-10-10-InlineAsmMemoryOperand.ll | 16 + .../SPARC/2008-10-10-InlineAsmRegOperand.ll | 14 + final/test/CodeGen/SPARC/2009-08-28-PIC.ll | 9 + .../CodeGen/SPARC/2009-08-28-WeakLinkage.ll | 6 + .../SPARC/2010-04-07-DbgValueOtherTargets.ll | 28 + final/test/CodeGen/SPARC/2011-01-11-CC.ll | 105 + final/test/CodeGen/SPARC/2011-01-11-Call.ll | 13 + .../CodeGen/SPARC/2011-01-11-FrameAddr.ll | 64 + .../CodeGen/SPARC/2011-01-19-DelaySlot.ll | 90 + .../CodeGen/SPARC/2011-01-21-ByValArgs.ll | 18 + final/test/CodeGen/SPARC/2011-01-22-SRet.ll | 37 + final/test/CodeGen/SPARC/basictest.ll | 26 + final/test/CodeGen/SPARC/ctpop.ll | 10 + final/test/CodeGen/SPARC/dg.exp | 5 + .../CodeGen/SPARC/mult-alt-generic-sparc.ll | 323 + final/test/CodeGen/SPARC/private.ll | 21 + final/test/CodeGen/SystemZ/00-RetVoid.ll | 6 + final/test/CodeGen/SystemZ/01-RetArg.ll | 6 + final/test/CodeGen/SystemZ/01-RetImm.ll | 49 + final/test/CodeGen/SystemZ/02-MemArith.ll | 133 + final/test/CodeGen/SystemZ/02-RetAdd.ll | 6 + final/test/CodeGen/SystemZ/02-RetAddImm.ll | 6 + final/test/CodeGen/SystemZ/02-RetAnd.ll | 7 + final/test/CodeGen/SystemZ/02-RetAndImm.ll | 28 + final/test/CodeGen/SystemZ/02-RetNeg.ll | 7 + final/test/CodeGen/SystemZ/02-RetOr.ll | 6 + final/test/CodeGen/SystemZ/02-RetOrImm.ll | 28 + final/test/CodeGen/SystemZ/02-RetSub.ll | 7 + final/test/CodeGen/SystemZ/02-RetSubImm.ll | 7 + final/test/CodeGen/SystemZ/02-RetXor.ll | 6 + final/test/CodeGen/SystemZ/02-RetXorImm.ll | 6 + .../CodeGen/SystemZ/03-RetAddImmSubreg.ll | 42 + final/test/CodeGen/SystemZ/03-RetAddSubreg.ll | 22 + .../CodeGen/SystemZ/03-RetAndImmSubreg.ll | 38 + final/test/CodeGen/SystemZ/03-RetAndSubreg.ll | 21 + final/test/CodeGen/SystemZ/03-RetArgSubreg.ll | 19 + final/test/CodeGen/SystemZ/03-RetImmSubreg.ll | 42 + .../CodeGen/SystemZ/03-RetNegImmSubreg.ll | 8 + .../test/CodeGen/SystemZ/03-RetOrImmSubreg.ll | 60 + final/test/CodeGen/SystemZ/03-RetOrSubreg.ll | 23 + .../CodeGen/SystemZ/03-RetSubImmSubreg.ll | 42 + final/test/CodeGen/SystemZ/03-RetSubSubreg.ll | 22 + .../CodeGen/SystemZ/03-RetXorImmSubreg.ll | 58 + final/test/CodeGen/SystemZ/03-RetXorSubreg.ll | 23 + final/test/CodeGen/SystemZ/04-RetShifts.ll | 121 + final/test/CodeGen/SystemZ/05-LoadAddr.ll | 11 + final/test/CodeGen/SystemZ/05-MemImmStores.ll | 50 + .../test/CodeGen/SystemZ/05-MemLoadsStores.ll | 44 + .../CodeGen/SystemZ/05-MemLoadsStores16.ll | 85 + final/test/CodeGen/SystemZ/05-MemRegLoads.ll | 75 + final/test/CodeGen/SystemZ/05-MemRegStores.ll | 79 + final/test/CodeGen/SystemZ/06-CallViaStack.ll | 17 + final/test/CodeGen/SystemZ/06-FrameIdxLoad.ll | 16 + final/test/CodeGen/SystemZ/06-LocalFrame.ll | 13 + final/test/CodeGen/SystemZ/06-SimpleCall.ll | 12 + final/test/CodeGen/SystemZ/07-BrCond.ll | 141 + final/test/CodeGen/SystemZ/07-BrCond32.ll | 142 + final/test/CodeGen/SystemZ/07-BrUnCond.ll | 18 + final/test/CodeGen/SystemZ/07-CmpImm.ll | 137 + final/test/CodeGen/SystemZ/07-CmpImm32.ll | 139 + final/test/CodeGen/SystemZ/07-SelectCC.ll | 11 + final/test/CodeGen/SystemZ/08-DivRem.ll | 55 + final/test/CodeGen/SystemZ/08-DivRemMemOp.ll | 64 + final/test/CodeGen/SystemZ/08-SimpleMuls.ll | 29 + .../test/CodeGen/SystemZ/09-DynamicAlloca.ll | 14 + final/test/CodeGen/SystemZ/09-Globals.ll | 23 + final/test/CodeGen/SystemZ/09-Switches.ll | 39 + final/test/CodeGen/SystemZ/10-FuncsPic.ll | 27 + final/test/CodeGen/SystemZ/10-GlobalsPic.ll | 29 + final/test/CodeGen/SystemZ/11-BSwap.ll | 74 + .../SystemZ/2009-05-29-InvalidRetResult.ll | 12 + .../CodeGen/SystemZ/2009-06-02-And32Imm.ll | 14 + .../test/CodeGen/SystemZ/2009-06-02-Rotate.ll | 13 + .../SystemZ/2009-06-05-InvalidArgLoad.ll | 19 + .../test/CodeGen/SystemZ/2009-07-04-Shl32.ll | 27 + .../test/CodeGen/SystemZ/2009-07-05-Shifts.ll | 25 + .../2009-07-10-BadIncomingArgOffset.ll | 24 + .../SystemZ/2009-07-11-FloatBitConvert.ll | 16 + .../SystemZ/2009-07-11-InvalidRIISel.ll | 32 + .../2009-08-21-InlineAsmRConstraint.ll | 21 + .../CodeGen/SystemZ/2009-08-22-FCopySign.ll | 22 + .../test/CodeGen/SystemZ/2010-01-04-DivMem.ll | 50 + .../2010-04-07-DbgValueOtherTargets.ll | 28 + final/test/CodeGen/SystemZ/dg.exp | 5 + .../CodeGen/Thumb/2007-01-31-RegInfoAssert.ll | 16 + .../Thumb/2007-02-02-JoinIntervalsCrash.ll | 27 + final/test/CodeGen/Thumb/2007-03-06-AddR7.ll | 117 + .../Thumb/2007-05-05-InvalidPushPop.ll | 41 + .../Thumb/2009-06-18-ThumbCommuteMul.ll | 8 + .../test/CodeGen/Thumb/2009-07-19-SPDecBug.ll | 33 + .../CodeGen/Thumb/2009-07-20-TwoAddrBug.ll | 11 + .../CodeGen/Thumb/2009-07-27-PEIAssert.ll | 26 + .../Thumb/2009-08-12-ConstIslandAssert.ll | 737 + .../CodeGen/Thumb/2009-08-12-RegInfoAssert.ll | 40 + .../test/CodeGen/Thumb/2009-08-20-ISelBug.ll | 66 + .../Thumb/2009-12-17-pre-regalloc-taildup.ll | 66 + .../2010-01-15-local-alloc-spill-physical.ll | 20 + .../Thumb/2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/Thumb/2010-06-18-SibCallCrash.ll | 8 + .../CodeGen/Thumb/2010-07-01-FuncAlign.ll | 6 + .../CodeGen/Thumb/2010-07-15-debugOrdering.ll | 147 + final/test/CodeGen/Thumb/2011-EpilogueBug.ll | 17 + final/test/CodeGen/Thumb/asmprinter-bug.ll | 288 + final/test/CodeGen/Thumb/barrier.ll | 25 + final/test/CodeGen/Thumb/dg.exp | 5 + final/test/CodeGen/Thumb/dyn-stackalloc.ll | 74 + final/test/CodeGen/Thumb/fpconv.ll | 61 + final/test/CodeGen/Thumb/fpow.ll | 9 + final/test/CodeGen/Thumb/frame_thumb.ll | 9 + final/test/CodeGen/Thumb/iabs.ll | 17 + .../test/CodeGen/Thumb/inlineasm-imm-thumb.ll | 43 + final/test/CodeGen/Thumb/ispositive.ll | 11 + final/test/CodeGen/Thumb/large-stack.ll | 35 + final/test/CodeGen/Thumb/ldr_ext.ll | 57 + final/test/CodeGen/Thumb/ldr_frame.ll | 41 + final/test/CodeGen/Thumb/long-setcc.ll | 17 + final/test/CodeGen/Thumb/long.ll | 76 + final/test/CodeGen/Thumb/long_shift.ll | 26 + final/test/CodeGen/Thumb/mul.ll | 22 + final/test/CodeGen/Thumb/pop.ll | 13 + final/test/CodeGen/Thumb/push.ll | 10 + final/test/CodeGen/Thumb/select.ll | 55 + final/test/CodeGen/Thumb/stack-frame.ll | 13 + final/test/CodeGen/Thumb/thumb-imm.ll | 10 + final/test/CodeGen/Thumb/trap.ll | 12 + final/test/CodeGen/Thumb/tst_teq.ll | 17 + final/test/CodeGen/Thumb/unord.ll | 14 + final/test/CodeGen/Thumb/vargs.ll | 36 + .../Thumb2/2009-07-17-CrossRegClassCopy.ll | 35 + .../test/CodeGen/Thumb2/2009-07-21-ISelBug.ll | 36 + .../CodeGen/Thumb2/2009-07-23-CPIslandBug.ll | 22 + .../CodeGen/Thumb2/2009-07-30-PEICrash.ll | 193 + .../CodeGen/Thumb2/2009-08-01-WrongLDRBOpc.ll | 85 + .../CodeGen/Thumb2/2009-08-02-CoalescerBug.ll | 46 + .../Thumb2/2009-08-04-CoalescerAssert.ll | 29 + .../CodeGen/Thumb2/2009-08-04-CoalescerBug.ll | 153 + .../Thumb2/2009-08-04-ScavengerAssert.ll | 508 + .../Thumb2/2009-08-04-SubregLoweringBug.ll | 34 + .../Thumb2/2009-08-04-SubregLoweringBug2.ll | 42 + .../Thumb2/2009-08-04-SubregLoweringBug3.ll | 54 + .../CodeGen/Thumb2/2009-08-06-SpDecBug.ll | 29 + .../CodeGen/Thumb2/2009-08-07-CoalescerBug.ll | 16 + .../CodeGen/Thumb2/2009-08-07-NeonFPBug.ll | 80 + .../Thumb2/2009-08-08-ScavengerAssert.ll | 20 + .../test/CodeGen/Thumb2/2009-08-10-ISelBug.ll | 15 + .../CodeGen/Thumb2/2009-08-21-PostRAKill4.ll | 26 + .../CodeGen/Thumb2/2009-09-01-PostRAProlog.ll | 106 + .../CodeGen/Thumb2/2009-09-28-ITBlockBug.ll | 152 + .../Thumb2/2009-10-15-ITBlockBranch.ll | 41 + .../Thumb2/2009-11-01-CopyReg2RegBug.ll | 29 + .../Thumb2/2009-11-11-ScavengerAssert.ll | 85 + .../test/CodeGen/Thumb2/2009-11-13-STRDBug.ll | 20 + .../CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll | 128 + .../Thumb2/2010-01-06-TailDuplicateLabels.ll | 89 + .../Thumb2/2010-01-19-RemovePredicates.ll | 53 + .../CodeGen/Thumb2/2010-02-11-phi-cycle.ll | 76 + .../CodeGen/Thumb2/2010-02-24-BigStack.ll | 15 + .../CodeGen/Thumb2/2010-03-08-addi12-ccout.ll | 266 + .../CodeGen/Thumb2/2010-03-15-AsmCCClobber.ll | 68 + .../CodeGen/Thumb2/2010-04-15-DynAllocBug.ll | 18 + .../CodeGen/Thumb2/2010-04-26-CopyRegCrash.ll | 73 + final/test/CodeGen/Thumb2/2010-05-24-rsbs.ll | 9 + .../Thumb2/2010-06-14-NEONCoalescer.ll | 42 + .../CodeGen/Thumb2/2010-06-19-ITBlockCrash.ll | 35 + .../CodeGen/Thumb2/2010-06-21-TailMergeBug.ll | 127 + .../Thumb2/2010-08-10-VarSizedAllocaBug.ll | 59 + .../CodeGen/Thumb2/2010-11-22-EpilogueBug.ll | 34 + .../Thumb2/2010-12-03-AddSPNarrowing.ll | 11 + final/test/CodeGen/Thumb2/bfi.ll | 51 + final/test/CodeGen/Thumb2/bfx.ll | 28 + .../test/CodeGen/Thumb2/buildvector-crash.ll | 17 + final/test/CodeGen/Thumb2/carry.ll | 22 + final/test/CodeGen/Thumb2/cortex-fp.ll | 24 + final/test/CodeGen/Thumb2/crash.ll | 49 + .../CodeGen/Thumb2/cross-rc-coalescing-1.ll | 52 + .../CodeGen/Thumb2/cross-rc-coalescing-2.ll | 75 + final/test/CodeGen/Thumb2/dg.exp | 5 + final/test/CodeGen/Thumb2/div.ll | 45 + final/test/CodeGen/Thumb2/frameless.ll | 6 + final/test/CodeGen/Thumb2/frameless2.ll | 12 + final/test/CodeGen/Thumb2/ifcvt-neon.ll | 29 + final/test/CodeGen/Thumb2/large-stack.ll | 39 + final/test/CodeGen/Thumb2/ldr-str-imm12.ll | 76 + final/test/CodeGen/Thumb2/lsr-deficiency.ll | 41 + final/test/CodeGen/Thumb2/machine-licm.ll | 122 + final/test/CodeGen/Thumb2/mul_const.ll | 18 + final/test/CodeGen/Thumb2/pic-load.ll | 21 + final/test/CodeGen/Thumb2/thumb2-adc.ll | 48 + final/test/CodeGen/Thumb2/thumb2-add.ll | 50 + final/test/CodeGen/Thumb2/thumb2-add2.ll | 41 + final/test/CodeGen/Thumb2/thumb2-add3.ll | 9 + final/test/CodeGen/Thumb2/thumb2-add4.ll | 46 + final/test/CodeGen/Thumb2/thumb2-add5.ll | 42 + final/test/CodeGen/Thumb2/thumb2-add6.ll | 9 + final/test/CodeGen/Thumb2/thumb2-and.ll | 42 + final/test/CodeGen/Thumb2/thumb2-and2.ll | 41 + final/test/CodeGen/Thumb2/thumb2-asr.ll | 8 + final/test/CodeGen/Thumb2/thumb2-asr2.ll | 8 + final/test/CodeGen/Thumb2/thumb2-barrier.ll | 31 + final/test/CodeGen/Thumb2/thumb2-bcc.ll | 19 + final/test/CodeGen/Thumb2/thumb2-bfc.ll | 32 + final/test/CodeGen/Thumb2/thumb2-bic.ll | 105 + final/test/CodeGen/Thumb2/thumb2-branch.ll | 61 + final/test/CodeGen/Thumb2/thumb2-call-tc.ll | 38 + final/test/CodeGen/Thumb2/thumb2-call.ll | 27 + final/test/CodeGen/Thumb2/thumb2-cbnz.ll | 33 + final/test/CodeGen/Thumb2/thumb2-clz.ll | 10 + final/test/CodeGen/Thumb2/thumb2-cmn.ll | 72 + final/test/CodeGen/Thumb2/thumb2-cmn2.ll | 33 + final/test/CodeGen/Thumb2/thumb2-cmp.ll | 55 + final/test/CodeGen/Thumb2/thumb2-cmp2.ll | 49 + final/test/CodeGen/Thumb2/thumb2-eor.ll | 56 + final/test/CodeGen/Thumb2/thumb2-eor2.ll | 41 + final/test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll | 87 + final/test/CodeGen/Thumb2/thumb2-ifcvt1.ll | 84 + final/test/CodeGen/Thumb2/thumb2-ifcvt2.ll | 94 + final/test/CodeGen/Thumb2/thumb2-ifcvt3.ll | 31 + final/test/CodeGen/Thumb2/thumb2-jtb.ll | 120 + final/test/CodeGen/Thumb2/thumb2-ldm.ll | 40 + final/test/CodeGen/Thumb2/thumb2-ldr.ll | 72 + final/test/CodeGen/Thumb2/thumb2-ldr_ext.ll | 28 + final/test/CodeGen/Thumb2/thumb2-ldr_post.ll | 12 + final/test/CodeGen/Thumb2/thumb2-ldr_pre.ll | 28 + final/test/CodeGen/Thumb2/thumb2-ldrb.ll | 72 + final/test/CodeGen/Thumb2/thumb2-ldrd.ll | 12 + final/test/CodeGen/Thumb2/thumb2-ldrh.ll | 71 + final/test/CodeGen/Thumb2/thumb2-lsl.ll | 8 + final/test/CodeGen/Thumb2/thumb2-lsl2.ll | 8 + final/test/CodeGen/Thumb2/thumb2-lsr.ll | 8 + final/test/CodeGen/Thumb2/thumb2-lsr2.ll | 8 + final/test/CodeGen/Thumb2/thumb2-lsr3.ll | 19 + final/test/CodeGen/Thumb2/thumb2-mla.ll | 17 + final/test/CodeGen/Thumb2/thumb2-mls.ll | 19 + final/test/CodeGen/Thumb2/thumb2-mov.ll | 266 + final/test/CodeGen/Thumb2/thumb2-mul.ll | 26 + final/test/CodeGen/Thumb2/thumb2-mulhi.ll | 20 + final/test/CodeGen/Thumb2/thumb2-mvn.ll | 33 + final/test/CodeGen/Thumb2/thumb2-mvn2.ll | 49 + final/test/CodeGen/Thumb2/thumb2-neg.ll | 8 + final/test/CodeGen/Thumb2/thumb2-orn.ll | 72 + final/test/CodeGen/Thumb2/thumb2-orn2.ll | 38 + final/test/CodeGen/Thumb2/thumb2-orr.ll | 42 + final/test/CodeGen/Thumb2/thumb2-orr2.ll | 42 + final/test/CodeGen/Thumb2/thumb2-pack.ll | 97 + final/test/CodeGen/Thumb2/thumb2-rev.ll | 23 + final/test/CodeGen/Thumb2/thumb2-rev16.ll | 32 + final/test/CodeGen/Thumb2/thumb2-ror.ll | 11 + final/test/CodeGen/Thumb2/thumb2-ror2.ll | 11 + final/test/CodeGen/Thumb2/thumb2-rsb.ll | 35 + final/test/CodeGen/Thumb2/thumb2-rsb2.ll | 41 + final/test/CodeGen/Thumb2/thumb2-sbc.ll | 54 + final/test/CodeGen/Thumb2/thumb2-select.ll | 98 + .../CodeGen/Thumb2/thumb2-select_xform.ll | 39 + final/test/CodeGen/Thumb2/thumb2-shifter.ll | 48 + final/test/CodeGen/Thumb2/thumb2-smla.ll | 11 + final/test/CodeGen/Thumb2/thumb2-smul.ll | 24 + final/test/CodeGen/Thumb2/thumb2-spill-q.ll | 91 + final/test/CodeGen/Thumb2/thumb2-str.ll | 76 + final/test/CodeGen/Thumb2/thumb2-str_post.ll | 22 + final/test/CodeGen/Thumb2/thumb2-str_pre.ll | 21 + final/test/CodeGen/Thumb2/thumb2-strb.ll | 76 + final/test/CodeGen/Thumb2/thumb2-strh.ll | 76 + final/test/CodeGen/Thumb2/thumb2-sub.ll | 49 + final/test/CodeGen/Thumb2/thumb2-sub2.ll | 8 + final/test/CodeGen/Thumb2/thumb2-sub3.ll | 55 + final/test/CodeGen/Thumb2/thumb2-sub4.ll | 42 + final/test/CodeGen/Thumb2/thumb2-sub5.ll | 9 + final/test/CodeGen/Thumb2/thumb2-sxt_rot.ll | 31 + final/test/CodeGen/Thumb2/thumb2-tbb.ll | 57 + final/test/CodeGen/Thumb2/thumb2-tbh.ll | 84 + final/test/CodeGen/Thumb2/thumb2-teq.ll | 93 + final/test/CodeGen/Thumb2/thumb2-teq2.ll | 71 + final/test/CodeGen/Thumb2/thumb2-tst.ll | 92 + final/test/CodeGen/Thumb2/thumb2-tst2.ll | 71 + final/test/CodeGen/Thumb2/thumb2-uxt_rot.ll | 28 + final/test/CodeGen/Thumb2/thumb2-uxtb.ll | 141 + final/test/CodeGen/Thumb2/tls1.ll | 20 + final/test/CodeGen/Thumb2/tls2.ll | 29 + .../X86/2003-08-03-CallArgLiveRanges.ll | 18 + .../CodeGen/X86/2003-08-23-DeadBlockTest.ll | 12 + .../test/CodeGen/X86/2003-11-03-GlobalBool.ll | 4 + final/test/CodeGen/X86/2004-02-12-Memcpy.ll | 25 + .../X86/2004-02-13-FrameReturnAddress.ll | 18 + .../X86/2004-02-14-InefficientStackPointer.ll | 5 + final/test/CodeGen/X86/2004-02-22-Casts.ll | 12 + .../test/CodeGen/X86/2004-03-30-Select-Max.ll | 8 + .../X86/2004-04-09-SameValueCoalescing.ll | 13 + .../CodeGen/X86/2004-04-13-FPCMOV-Crash.ll | 7 + .../CodeGen/X86/2004-06-10-StackifierCrash.ll | 6 + .../CodeGen/X86/2004-10-08-SelectSetCCFold.ll | 8 + .../test/CodeGen/X86/2005-01-17-CycleInDAG.ll | 17 + .../X86/2005-02-14-IllegalAssembler.ll | 5 + .../CodeGen/X86/2005-05-08-FPStackifierPHI.ll | 38 + .../CodeGen/X86/2006-01-19-ISelFoldingBug.ll | 20 + .../CodeGen/X86/2006-03-01-InstrSchedBug.ll | 12 + .../CodeGen/X86/2006-03-02-InstrSchedBug.ll | 12 + .../CodeGen/X86/2006-04-04-CrossBlockCrash.ll | 50 + .../CodeGen/X86/2006-04-27-ISelFoldingBug.ll | 29 + .../X86/2006-05-01-SchedCausingSpills.ll | 76 + .../CodeGen/X86/2006-05-02-InstrSched1.ll | 23 + .../CodeGen/X86/2006-05-02-InstrSched2.ll | 24 + .../X86/2006-05-08-CoalesceSubRegClass.ll | 25 + .../test/CodeGen/X86/2006-05-08-InstrSched.ll | 25 + .../test/CodeGen/X86/2006-05-11-InstrSched.ll | 51 + .../test/CodeGen/X86/2006-05-17-VectorArg.ll | 15 + final/test/CodeGen/X86/2006-05-22-FPSetEQ.ll | 10 + .../test/CodeGen/X86/2006-05-25-CycleInDAG.ll | 20 + .../X86/2006-07-10-InlineAsmAConstraint.ll | 8 + .../X86/2006-07-12-InlineAsmQConstraint.ll | 12 + final/test/CodeGen/X86/2006-07-19-ATTAsm.ll | 49 + .../test/CodeGen/X86/2006-07-20-InlineAsm.ll | 23 + .../2006-07-28-AsmPrint-Long-As-Pointer.ll | 5 + .../CodeGen/X86/2006-07-31-SingleRegClass.ll | 10 + .../test/CodeGen/X86/2006-08-07-CycleInDAG.ll | 31 + .../test/CodeGen/X86/2006-08-16-CycleInDAG.ll | 23 + .../CodeGen/X86/2006-08-21-ExtraMovInst.ll | 17 + .../test/CodeGen/X86/2006-09-01-CycleInDAG.ll | 131 + .../CodeGen/X86/2006-10-02-BoolRetCrash.ll | 7 + .../X86/2006-10-07-ScalarSSEMiscompile.ll | 15 + .../test/CodeGen/X86/2006-10-09-CycleInDAG.ll | 11 + .../X86/2006-10-10-FindModifiedNodeSlotBug.ll | 28 + .../test/CodeGen/X86/2006-10-12-CycleInDAG.ll | 41 + .../test/CodeGen/X86/2006-10-13-CycleInDAG.ll | 19 + .../2006-10-19-SwitchUnnecessaryBranching.ll | 29 + final/test/CodeGen/X86/2006-11-12-CSRetCC.ll | 59 + .../CodeGen/X86/2006-11-17-IllegalMove.ll | 42 + .../CodeGen/X86/2006-11-27-SelectLegalize.ll | 9 + final/test/CodeGen/X86/2006-11-28-Memcpy.ll | 34 + .../CodeGen/X86/2006-12-16-InlineAsmCrash.ll | 30 + .../CodeGen/X86/2006-12-19-IntelSyntax.ll | 86 + .../test/CodeGen/X86/2007-01-08-InstrSched.ll | 22 + .../CodeGen/X86/2007-01-08-X86-64-Pointer.ll | 22 + .../CodeGen/X86/2007-01-13-StackPtrIndex.ll | 461 + .../CodeGen/X86/2007-01-29-InlineAsm-ir.ll | 7 + .../test/CodeGen/X86/2007-02-04-OrAddrMode.ll | 21 + .../test/CodeGen/X86/2007-02-16-BranchFold.ll | 95 + .../X86/2007-02-19-LiveIntervalAssert.ll | 21 + .../X86/2007-02-23-DAGCombine-Miscompile.ll | 13 + .../CodeGen/X86/2007-02-25-FastCCStack.ll | 5 + .../CodeGen/X86/2007-03-01-SpillerCrash.ll | 86 + .../CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll | 73 + .../test/CodeGen/X86/2007-03-16-InlineAsm.ll | 27 + .../X86/2007-03-18-LiveIntervalAssert.ll | 7 + .../2007-03-24-InlineAsmMultiRegConstraint.ll | 11 + .../X86/2007-03-24-InlineAsmPModifier.ll | 10 + .../X86/2007-03-24-InlineAsmVectorOp.ll | 11 + .../X86/2007-03-24-InlineAsmXConstraint.ll | 9 + .../CodeGen/X86/2007-03-26-CoalescerBug.ll | 49 + .../CodeGen/X86/2007-04-08-InlineAsmCrash.ll | 18 + .../X86/2007-04-11-InlineAsmVectorResult.ll | 21 + .../X86/2007-04-17-LiveIntervalAssert.ll | 42 + .../test/CodeGen/X86/2007-04-24-Huge-Stack.ll | 19 + .../CodeGen/X86/2007-04-24-VectorCrash.ll | 63 + .../test/CodeGen/X86/2007-04-25-MMX-PADDQ.ll | 64 + .../X86/2007-04-27-InlineAsm-IntMemInput.ll | 12 + .../CodeGen/X86/2007-05-05-Personality.ll | 35 + .../CodeGen/X86/2007-05-05-VecCastExpand.ll | 21 + .../test/CodeGen/X86/2007-05-07-InvokeSRet.ll | 15 + .../X86/2007-05-14-LiveIntervalAssert.ll | 27 + final/test/CodeGen/X86/2007-05-15-maskmovq.ll | 14 + .../CodeGen/X86/2007-05-17-ShuffleISelBug.ll | 23 + .../X86/2007-06-04-X86-64-CtorAsmBugs.ll | 28 + .../test/CodeGen/X86/2007-06-04-tailmerge4.ll | 454 + .../CodeGen/X86/2007-06-05-LSR-Dominator.ll | 129 + final/test/CodeGen/X86/2007-06-15-IntToMMX.ll | 16 + .../CodeGen/X86/2007-06-28-X86-64-isel.ll | 16 + .../CodeGen/X86/2007-06-29-DAGCombinerBug.ll | 50 + .../X86/2007-06-29-VecFPConstantCSEBug.ll | 11 + .../test/CodeGen/X86/2007-07-03-GR64ToVR64.ll | 18 + .../CodeGen/X86/2007-07-10-StackerAssert.ll | 41 + .../CodeGen/X86/2007-07-18-Vector-Extract.ll | 17 + .../X86/2007-08-01-LiveVariablesBug.ll | 8 + .../X86/2007-08-09-IllegalX86-64Asm.ll | 235 + .../CodeGen/X86/2007-08-10-SignExtSubreg.ll | 10 + .../X86/2007-08-13-AppendingLinkage.ll | 12 + .../test/CodeGen/X86/2007-09-05-InvalidAsm.ll | 49 + .../CodeGen/X86/2007-09-06-ExtWeakAliasee.ll | 4 + .../CodeGen/X86/2007-09-17-ObjcFrameEH.ll | 65 + .../CodeGen/X86/2007-09-18-ShuffleXformBug.ll | 30 + .../CodeGen/X86/2007-09-27-LDIntrinsics.ll | 30 + .../CodeGen/X86/2007-10-04-AvoidEFLAGSCopy.ll | 20 + .../CodeGen/X86/2007-10-05-3AddrConvert.ll | 48 + .../X86/2007-10-12-CoalesceExtSubReg.ll | 32 + .../CodeGen/X86/2007-10-12-SpillerUnfold1.ll | 45 + .../CodeGen/X86/2007-10-12-SpillerUnfold2.ll | 57 + .../CodeGen/X86/2007-10-14-CoalescerCrash.ll | 28 + .../CodeGen/X86/2007-10-15-CoalescerCrash.ll | 400 + .../CodeGen/X86/2007-10-16-CoalescerCrash.ll | 31 + .../test/CodeGen/X86/2007-10-17-IllegalAsm.ll | 87 + .../CodeGen/X86/2007-10-19-SpillerUnfold.ll | 84 + .../X86/2007-10-28-inlineasm-q-modifier.ll | 11 + .../CodeGen/X86/2007-10-29-ExtendSetCC.ll | 17 + final/test/CodeGen/X86/2007-10-30-LSRCrash.ll | 48 + .../X86/2007-10-31-extractelement-i64.ll | 82 + .../test/CodeGen/X86/2007-11-01-ISelCrash.ll | 12 + final/test/CodeGen/X86/2007-11-02-BadAsm.ll | 144 + .../X86/2007-11-03-x86-64-q-constraint.ll | 9 + .../X86/2007-11-04-LiveIntervalCrash.ll | 37 + .../X86/2007-11-04-LiveVariablesBug.ll | 16 + .../X86/2007-11-04-rip-immediate-constant.ll | 11 + .../test/CodeGen/X86/2007-11-06-InstrSched.ll | 25 + final/test/CodeGen/X86/2007-11-07-MulBy4.ll | 129 + .../CodeGen/X86/2007-11-30-LoadFolding-Bug.ll | 86 + .../CodeGen/X86/2007-12-11-FoldImpDefSpill.ll | 680 + .../CodeGen/X86/2007-12-16-BURRSchedCrash.ll | 35 + .../test/CodeGen/X86/2007-12-18-LoadCSEBug.ll | 28 + .../test/CodeGen/X86/2008-01-08-IllegalCMP.ll | 17 + .../CodeGen/X86/2008-01-08-SchedulerCrash.ll | 32 + .../CodeGen/X86/2008-01-09-LongDoubleSin.ll | 11 + .../X86/2008-01-16-FPStackifierAssert.ll | 35 + .../X86/2008-01-16-InvalidDAGCombineXform.ll | 30 + .../test/CodeGen/X86/2008-01-16-Trampoline.ll | 14 + .../test/CodeGen/X86/2008-02-05-ISelCrash.ll | 12 + .../CodeGen/X86/2008-02-06-LoadFoldingBug.ll | 20 + .../CodeGen/X86/2008-02-08-LoadFoldingBug.ll | 99 + .../CodeGen/X86/2008-02-14-BitMiscompile.ll | 8 + .../CodeGen/X86/2008-02-18-TailMergingBug.ll | 219 + .../X86/2008-02-20-InlineAsmClobber.ll | 24 + .../X86/2008-02-22-LocalRegAllocBug.ll | 55 + final/test/CodeGen/X86/2008-02-22-ReMatBug.ll | 49 + .../CodeGen/X86/2008-02-25-InlineAsmBug.ll | 33 + .../X86/2008-02-25-X86-64-CoalescerBug.ll | 55 + .../CodeGen/X86/2008-02-26-AsmDirectMemOp.ll | 17 + .../CodeGen/X86/2008-02-27-DeadSlotElimBug.ll | 66 + final/test/CodeGen/X86/2008-02-27-PEICrash.ll | 33 + .../CodeGen/X86/2008-03-06-frem-fpstack.ll | 7 + final/test/CodeGen/X86/2008-03-07-APIntBug.ll | 94 + .../CodeGen/X86/2008-03-10-RegAllocInfLoop.ll | 14 + .../X86/2008-03-12-ThreadLocalAlias.ll | 37 + .../X86/2008-03-13-TwoAddrPassCrash.ll | 68 + .../CodeGen/X86/2008-03-14-SpillerCrash.ll | 48 + .../CodeGen/X86/2008-03-18-CoalescerBug.ll | 51 + .../CodeGen/X86/2008-03-19-DAGCombinerBug.ll | 14 + .../X86/2008-03-23-DarwinAsmComments.ll | 49 + .../CodeGen/X86/2008-03-25-TwoAddrPassBug.ll | 24 + .../X86/2008-03-31-SpillerFoldingBug.ll | 40 + .../test/CodeGen/X86/2008-04-02-unnamedEH.ll | 16 + .../CodeGen/X86/2008-04-08-CoalescerCrash.ll | 19 + .../CodeGen/X86/2008-04-09-BranchFolding.ll | 48 + .../CodeGen/X86/2008-04-15-LiveVariableBug.ll | 50 + .../CodeGen/X86/2008-04-16-CoalescerBug.ll | 33 + final/test/CodeGen/X86/2008-04-16-ReMatBug.ll | 46 + .../CodeGen/X86/2008-04-17-CoalescerBug.ll | 171 + .../test/CodeGen/X86/2008-04-24-MemCpyBug.ll | 12 + .../X86/2008-04-24-pblendw-fold-crash.ll | 15 + .../X86/2008-04-26-Asm-Optimize-Imm.ll | 11 + .../CodeGen/X86/2008-04-28-CoalescerBug.ll | 167 + .../CodeGen/X86/2008-04-28-CyclicSchedUnit.ll | 6 + .../X86/2008-05-01-InvalidOrdCompare.ll | 15 + .../test/CodeGen/X86/2008-05-09-PHIElimBug.ll | 25 + .../X86/2008-05-09-ShuffleLoweringBug.ll | 10 + .../CodeGen/X86/2008-05-12-tailmerge-5.ll | 145 + .../CodeGen/X86/2008-05-21-CoalescerBug.ll | 98 + .../X86/2008-05-22-FoldUnalignedLoad.ll | 11 + .../CodeGen/X86/2008-05-28-CoalescerBug.ll | 10 + .../X86/2008-05-28-LocalRegAllocBug.ll | 30 + .../X86/2008-06-04-MemCpyLoweringBug.ll | 19 + .../X86/2008-06-13-NotVolatileLoadStore.ll | 23 + .../X86/2008-06-13-VolatileLoadStore.ll | 22 + .../test/CodeGen/X86/2008-06-16-SubregsBug.ll | 14 + .../test/CodeGen/X86/2008-06-18-BadShuffle.ll | 10 + .../test/CodeGen/X86/2008-06-25-VecISelBug.ll | 9 + .../X86/2008-07-07-DanglingDeadInsts.ll | 99 + .../X86/2008-07-09-ELFSectionAttributes.ll | 13 + final/test/CodeGen/X86/2008-07-11-SHLBy1.ll | 5 + .../test/CodeGen/X86/2008-07-11-SpillerBug.ll | 52 + .../CodeGen/X86/2008-07-16-CoalescerCrash.ll | 34 + .../CodeGen/X86/2008-07-19-movups-spills.ll | 639 + .../CodeGen/X86/2008-07-22-CombinerCrash.ll | 16 + final/test/CodeGen/X86/2008-07-23-VSetCC.ll | 32 + .../test/CodeGen/X86/2008-08-05-SpillerBug.ll | 44 + .../test/CodeGen/X86/2008-08-06-CmpStride.ll | 23 + .../CodeGen/X86/2008-08-06-RewriterBug.ll | 40 + .../CodeGen/X86/2008-08-17-UComiCodeGenBug.ll | 9 + .../CodeGen/X86/2008-08-19-SubAndFetch.ll | 14 + .../CodeGen/X86/2008-08-23-64Bit-maskmovq.ll | 29 + .../CodeGen/X86/2008-08-23-X86-64AsmBug.ll | 59 + .../X86/2008-08-25-AsmRegTypeMismatch.ll | 18 + .../CodeGen/X86/2008-08-31-EH_RETURN32.ll | 17 + .../CodeGen/X86/2008-08-31-EH_RETURN64.ll | 17 + .../CodeGen/X86/2008-09-05-sinttofp-2xi32.ll | 35 + .../CodeGen/X86/2008-09-09-LinearScanBug.ll | 65 + .../CodeGen/X86/2008-09-11-CoalescerBug.ll | 38 + .../CodeGen/X86/2008-09-11-CoalescerBug2.ll | 33 + .../CodeGen/X86/2008-09-17-inline-asm-1.ll | 30 + .../CodeGen/X86/2008-09-18-inline-asm-2.ll | 27 + .../CodeGen/X86/2008-09-19-RegAllocBug.ll | 22 + .../CodeGen/X86/2008-09-25-sseregparm-1.ll | 19 + .../CodeGen/X86/2008-09-26-FrameAddrBug.ll | 16 + final/test/CodeGen/X86/2008-09-29-ReMatBug.ll | 85 + .../CodeGen/X86/2008-09-29-VolatileBug.ll | 15 + .../CodeGen/X86/2008-10-02-Atomics32-2.ll | 969 + .../test/CodeGen/X86/2008-10-06-MMXISelBug.ll | 12 + .../CodeGen/X86/2008-10-06-x87ld-nan-1.ll | 13 + .../CodeGen/X86/2008-10-06-x87ld-nan-2.ll | 18 + .../test/CodeGen/X86/2008-10-07-SSEISelBug.ll | 22 + .../test/CodeGen/X86/2008-10-11-CallCrash.ll | 21 + .../CodeGen/X86/2008-10-13-CoalescerBug.ll | 42 + .../test/CodeGen/X86/2008-10-16-VecUnaryOp.ll | 8 + .../X86/2008-10-17-Asm64bitRConstraint.ll | 9 + .../CodeGen/X86/2008-10-20-AsmDoubleInI32.ll | 11 + .../CodeGen/X86/2008-10-24-FlippedCompare.ll | 17 + .../CodeGen/X86/2008-10-27-CoalescerBug.ll | 52 + .../X86/2008-10-27-StackRealignment.ll | 22 + .../CodeGen/X86/2008-10-29-ExpandVAARG.ll | 10 + final/test/CodeGen/X86/2008-11-03-F80VAARG.ll | 17 + final/test/CodeGen/X86/2008-11-06-testb.ll | 26 + .../CodeGen/X86/2008-11-13-inlineasm-3.ll | 19 + final/test/CodeGen/X86/2008-11-29-ULT-Sign.ll | 22 + .../CodeGen/X86/2008-12-01-SpillerAssert.ll | 15 + .../2008-12-01-loop-iv-used-outside-loop.ll | 30 + .../X86/2008-12-02-IllegalResultType.ll | 37 + .../CodeGen/X86/2008-12-02-dagcombine-1.ll | 19 + .../CodeGen/X86/2008-12-02-dagcombine-2.ll | 17 + .../CodeGen/X86/2008-12-02-dagcombine-3.ll | 18 + .../CodeGen/X86/2008-12-05-SpillerCrash.ll | 237 + .../CodeGen/X86/2008-12-12-PrivateEHSymbol.ll | 12 + final/test/CodeGen/X86/2008-12-16-BadShift.ll | 19 + .../CodeGen/X86/2008-12-16-dagcombine-4.ll | 14 + .../CodeGen/X86/2008-12-19-EarlyClobberBug.ll | 38 + .../CodeGen/X86/2008-12-22-dagcombine-5.ll | 14 + .../CodeGen/X86/2008-12-23-crazy-address.ll | 33 + .../CodeGen/X86/2008-12-23-dagcombine-6.ll | 24 + .../CodeGen/X86/2009-01-13-DoubleUpdate.ll | 21 + .../CodeGen/X86/2009-01-16-SchedulerBug.ll | 50 + final/test/CodeGen/X86/2009-01-16-UIntToFP.ll | 31 + .../X86/2009-01-18-ConstantExprCrash.ll | 36 + final/test/CodeGen/X86/2009-01-25-NoSSE.ll | 20 + .../test/CodeGen/X86/2009-01-26-WrongCheck.ll | 16 + .../CodeGen/X86/2009-01-27-NullStrings.ll | 7 + .../X86/2009-01-29-LocalRegAllocBug.ll | 38 + final/test/CodeGen/X86/2009-01-31-BigShift.ll | 9 + .../test/CodeGen/X86/2009-01-31-BigShift2.ll | 11 + .../test/CodeGen/X86/2009-01-31-BigShift3.ll | 31 + .../test/CodeGen/X86/2009-02-01-LargeMask.ll | 32 + .../CodeGen/X86/2009-02-03-AnalyzedTwice.ll | 30 + .../CodeGen/X86/2009-02-04-sext-i64-gep.ll | 9 + .../CodeGen/X86/2009-02-05-CoalescerBug.ll | 14 + .../CodeGen/X86/2009-02-08-CoalescerBug.ll | 22 + .../X86/2009-02-09-ivs-different-sizes.ll | 33 + .../X86/2009-02-11-codegenprepare-reuse.ll | 35 + .../CodeGen/X86/2009-02-12-DebugInfoVLA.ll | 85 + .../2009-02-12-InlineAsm-nieZ-constraints.ll | 18 + .../test/CodeGen/X86/2009-02-12-SpillerBug.ll | 29 + .../X86/2009-02-20-PreAllocSplit-Crash.ll | 71 + .../X86/2009-02-21-ExtWeakInitializer.ll | 20 + .../test/CodeGen/X86/2009-02-25-CommuteBug.ll | 14 + .../CodeGen/X86/2009-02-26-MachineLICMBug.ll | 56 + final/test/CodeGen/X86/2009-03-03-BTHang.ll | 37 + .../X86/2009-03-03-BitcastLongDouble.ll | 14 + .../CodeGen/X86/2009-03-05-burr-list-crash.ll | 35 + .../CodeGen/X86/2009-03-07-FPConstSelect.ll | 12 + .../test/CodeGen/X86/2009-03-09-APIntCrash.ll | 25 + .../test/CodeGen/X86/2009-03-09-SpillerBug.ll | 18 + .../CodeGen/X86/2009-03-10-CoalescerBug.ll | 28 + .../test/CodeGen/X86/2009-03-12-CPAlignBug.ll | 37 + .../test/CodeGen/X86/2009-03-13-PHIElimBug.ll | 32 + .../CodeGen/X86/2009-03-16-PHIElimInLPad.ll | 24 + .../test/CodeGen/X86/2009-03-16-SpillerBug.ll | 167 + .../CodeGen/X86/2009-03-23-LinearScanBug.ll | 23 + .../CodeGen/X86/2009-03-23-MultiUseSched.ll | 242 + final/test/CodeGen/X86/2009-03-23-i80-fp80.ll | 14 + final/test/CodeGen/X86/2009-03-25-TestBug.ll | 25 + .../CodeGen/X86/2009-03-26-NoImplicitFPBug.ll | 12 + .../CodeGen/X86/2009-04-09-InlineAsmCrash.ll | 165 + .../X86/2009-04-12-FastIselOverflowCrash.ll | 21 + final/test/CodeGen/X86/2009-04-12-picrel.ll | 13 + .../CodeGen/X86/2009-04-13-2AddrAssert-2.ll | 15 + .../CodeGen/X86/2009-04-13-2AddrAssert.ll | 16 + .../CodeGen/X86/2009-04-14-IllegalRegs.ll | 35 + .../CodeGen/X86/2009-04-16-SpillerUnfold.ll | 141 + .../CodeGen/X86/2009-04-20-LinearScanOpt.ll | 121 + .../CodeGen/X86/2009-04-21-NoReloadImpDef.ll | 31 + final/test/CodeGen/X86/2009-04-24.ll | 12 + .../CodeGen/X86/2009-04-25-CoalescerBug.ll | 19 + .../CodeGen/X86/2009-04-27-CoalescerAssert.ll | 1457 + .../X86/2009-04-27-LiveIntervalsAssert.ll | 24 + .../X86/2009-04-27-LiveIntervalsAssert2.ll | 23 + .../X86/2009-04-27-LiveIntervalsBug.ll | 165 + .../X86/2009-04-29-IndirectDestOperands.ll | 22 + .../CodeGen/X86/2009-04-29-LinearScanBug.ll | 215 + .../CodeGen/X86/2009-04-29-RegAllocAssert.ll | 117 + final/test/CodeGen/X86/2009-04-scale.ll | 23 + .../X86/2009-05-08-InlineAsmIOffset.ll | 17 + .../CodeGen/X86/2009-05-11-tailmerge-crash.ll | 23 + .../2009-05-19-SingleElementExtractElement.ll | 16 + .../X86/2009-05-23-available_externally.ll | 19 + .../X86/2009-05-23-dagcombine-shifts.ll | 20 + .../CodeGen/X86/2009-05-28-DAGCombineCrash.ll | 15 + final/test/CodeGen/X86/2009-05-30-ISelBug.ll | 28 + .../CodeGen/X86/2009-06-02-RewriterBug.ll | 362 + .../X86/2009-06-03-Win64DisableRedZone.ll | 8 + .../CodeGen/X86/2009-06-03-Win64SpillXMM.ll | 10 + .../CodeGen/X86/2009-06-04-VirtualLiveIn.ll | 48 + .../X86/2009-06-05-ScalarToVectorByteMMX.ll | 7 + .../CodeGen/X86/2009-06-05-VZextByteShort.ll | 37 + .../X86/2009-06-05-VariableIndexInsert.ll | 11 + .../CodeGen/X86/2009-06-05-sitofpCrash.ll | 13 + .../CodeGen/X86/2009-06-06-ConcatVectors.ll | 8 + .../X86/2009-06-07-ExpandMMXBitcast.ll | 10 + ...2-x86_64-tail-call-conv-out-of-sync-bug.ll | 15 + .../CodeGen/X86/2009-06-15-not-a-tail-call.ll | 14 + .../X86/2009-06-18-movlp-shuffle-register.ll | 9 + .../CodeGen/X86/2009-07-06-TwoAddrAssert.ll | 137 + .../test/CodeGen/X86/2009-07-07-SplitICmp.ll | 8 + .../X86/2009-07-09-ExtractBoolFromVector.ll | 11 + .../CodeGen/X86/2009-07-15-CoalescerBug.ll | 958 + .../CodeGen/X86/2009-07-16-CoalescerBug.ll | 210 + .../X86/2009-07-17-StackColoringBug.ll | 55 + .../X86/2009-07-19-AsmExtraOperands.ll | 11 + .../CodeGen/X86/2009-07-20-CoalescerBug.ll | 165 + .../CodeGen/X86/2009-07-20-DAGCombineBug.ll | 29 + .../X86/2009-08-02-mmx-scalar-to-vector.ll | 12 + .../X86/2009-08-06-branchfolder-crash.ll | 142 + .../test/CodeGen/X86/2009-08-06-inlineasm.ll | 30 + .../test/CodeGen/X86/2009-08-08-CastError.ll | 9 + .../test/CodeGen/X86/2009-08-12-badswitch.ll | 176 + .../X86/2009-08-14-Win64MemoryIndirectArg.ll | 57 + .../X86/2009-08-19-LoadNarrowingMiscompile.ll | 15 + .../CodeGen/X86/2009-08-23-SubRegReuseUndo.ll | 69 + .../CodeGen/X86/2009-08-23-linkerprivate.ll | 8 + .../CodeGen/X86/2009-09-10-LoadFoldingBug.ll | 47 + .../CodeGen/X86/2009-09-10-SpillComments.ll | 108 + .../CodeGen/X86/2009-09-16-CoalescerBug.ll | 64 + .../CodeGen/X86/2009-09-19-earlyclobber.ll | 15 + .../X86/2009-09-21-NoSpillLoopCount.ll | 36 + .../CodeGen/X86/2009-09-22-CoalescerBug.ll | 124 + .../X86/2009-09-23-LiveVariablesBug.ll | 91 + .../CodeGen/X86/2009-10-08-MachineLICMBug.ll | 264 + .../X86/2009-10-14-LiveVariablesBug.ll | 15 + final/test/CodeGen/X86/2009-10-16-Scope.ll | 32 + .../CodeGen/X86/2009-10-19-EmergencySpill.ll | 54 + .../X86/2009-10-19-atomic-cmp-eflags.ll | 69 + .../CodeGen/X86/2009-10-25-RewriterBug.ll | 171 + .../X86/2009-11-04-SubregCoalescingBug.ll | 15 + .../X86/2009-11-13-VirtRegRewriterBug.ll | 133 + .../CodeGen/X86/2009-11-16-MachineLICM.ll | 42 + .../CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll | 28 + .../X86/2009-11-17-UpdateTerminator.ll | 52 + .../CodeGen/X86/2009-11-18-TwoAddrKill.ll | 29 + .../test/CodeGen/X86/2009-11-25-ImpDefBug.ll | 116 + .../CodeGen/X86/2009-12-01-EarlyClobberBug.ll | 38 + .../CodeGen/X86/2009-12-11-TLSNoRedZone.ll | 63 + final/test/CodeGen/X86/20090313-signext.ll | 19 + final/test/CodeGen/X86/2010-01-05-ZExt-Shl.ll | 15 + final/test/CodeGen/X86/2010-01-07-ISelBug.ll | 27 + .../CodeGen/X86/2010-01-07-UAMemFeature.ll | 11 + .../CodeGen/X86/2010-01-08-Atomic64Bug.ll | 29 + .../CodeGen/X86/2010-01-11-ExtraPHIArg.ll | 97 + .../test/CodeGen/X86/2010-01-13-OptExtBug.ll | 46 + .../X86/2010-01-15-SelectionDAGCycle.ll | 28 + final/test/CodeGen/X86/2010-01-18-DbgValue.ll | 48 + .../test/CodeGen/X86/2010-01-19-OptExtBug.ll | 57 + .../CodeGen/X86/2010-02-01-DbgValueCrash.ll | 33 + .../CodeGen/X86/2010-02-01-TaillCallCrash.ll | 12 + .../test/CodeGen/X86/2010-02-03-DualUndef.ll | 27 + .../CodeGen/X86/2010-02-04-SchedulerBug.ll | 28 + .../CodeGen/X86/2010-02-11-NonTemporal.ll | 22 + .../X86/2010-02-12-CoalescerBug-Impdef.ll | 260 + .../CodeGen/X86/2010-02-15-ImplicitDefBug.ll | 80 + .../X86/2010-02-19-TailCallRetAddrBug.ll | 55 + .../CodeGen/X86/2010-02-23-DAGCombineBug.ll | 18 + .../CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll | 20 + .../X86/2010-02-23-RematImplicitSubreg.ll | 49 + .../X86/2010-02-23-SingleDefPhiJoin.ll | 146 + final/test/CodeGen/X86/2010-03-04-Mul8Bug.ll | 25 + .../CodeGen/X86/2010-03-05-ConstantFoldCFG.ll | 42 + .../CodeGen/X86/2010-03-05-EFLAGS-Redef.ll | 49 + final/test/CodeGen/X86/2010-03-17-ISelBug.ll | 67 + .../X86/2010-04-06-SSEDomainFixCrash.ll | 64 + .../X86/2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/X86/2010-04-08-CoalescerBug.ll | 26 + .../X86/2010-04-13-AnalyzeBranchCrash.ll | 42 + .../CodeGen/X86/2010-04-21-CoalescerBug.ll | 15 + .../CodeGen/X86/2010-04-23-mmx-movdq2q.ll | 93 + .../CodeGen/X86/2010-04-29-CoalescerCrash.ll | 142 + .../X86/2010-04-30-LocalAlloc-LandingPad.ll | 143 + .../X86/2010-05-03-CoalescerSubRegClobber.ll | 33 + .../X86/2010-05-05-LocalAllocEarlyClobber.ll | 32 + .../X86/2010-05-06-LocalInlineAsmClobber.ll | 10 + .../test/CodeGen/X86/2010-05-07-ldconvert.ll | 27 + .../CodeGen/X86/2010-05-10-DAGCombinerBug.ll | 11 + .../CodeGen/X86/2010-05-12-FastAllocKills.ll | 59 + .../CodeGen/X86/2010-05-16-nosseconversion.ll | 12 + .../CodeGen/X86/2010-05-25-DotDebugLoc.ll | 242 + .../CodeGen/X86/2010-05-26-DotDebugLoc.ll | 66 + .../CodeGen/X86/2010-05-26-FP_TO_INT-crash.ll | 16 + final/test/CodeGen/X86/2010-05-28-Crash.ll | 44 + .../CodeGen/X86/2010-06-01-DeadArg-DbgInfo.ll | 53 + .../X86/2010-06-09-FastAllocRegisters.ll | 17 + .../X86/2010-06-14-fast-isel-fs-load.ll | 6 + .../X86/2010-06-15-FastAllocEarlyCLobber.ll | 29 + .../X86/2010-06-24-g-constraint-crash.ll | 15 + .../X86/2010-06-25-CoalescerSubRegDefDead.ll | 39 + .../CodeGen/X86/2010-06-25-asm-RA-crash.ll | 19 + .../test/CodeGen/X86/2010-06-28-DbgEntryPC.ll | 108 + .../X86/2010-06-28-FastAllocTiedOperand.ll | 22 + .../X86/2010-06-28-matched-g-constraint.ll | 11 + .../test/CodeGen/X86/2010-07-02-UnfoldBug.ll | 99 + .../CodeGen/X86/2010-07-02-asm-alignstack.ll | 31 + final/test/CodeGen/X86/2010-07-06-DbgCrash.ll | 29 + final/test/CodeGen/X86/2010-07-06-asm-RIP.ll | 21 + .../CodeGen/X86/2010-07-11-FPStackLoneUse.ll | 28 + .../X86/2010-07-13-indirectXconstraint.ll | 18 + final/test/CodeGen/X86/2010-07-15-Crash.ll | 12 + .../CodeGen/X86/2010-07-29-SetccSimplify.ll | 14 + .../X86/2010-08-04-MaskedSignedCompare.ll | 36 + .../test/CodeGen/X86/2010-08-04-MingWCrash.ll | 39 + .../CodeGen/X86/2010-08-04-StackVariable.ll | 124 + .../CodeGen/X86/2010-08-10-DbgConstant.ll | 25 + .../2010-09-01-RemoveCopyByCommutingDef.ll | 28 + .../CodeGen/X86/2010-09-16-EmptyFilename.ll | 29 + final/test/CodeGen/X86/2010-09-16-asmcrash.ll | 56 + .../X86/2010-09-17-SideEffectsInChain.ll | 26 + .../X86/2010-09-30-CMOV-JumpTable-PHI.ll | 71 + .../test/CodeGen/X86/2010-10-08-cmpxchg8b.ll | 28 + .../CodeGen/X86/2010-11-02-DbgParameter.ll | 35 + final/test/CodeGen/X86/2010-11-09-MOVLPS.ll | 66 + .../CodeGen/X86/2010-11-18-SelectOfExtload.ll | 15 + final/test/CodeGen/X86/2010-12-02-MC-Set.ll | 22 + .../X86/2011-01-07-LegalizeTypesCrash.ll | 19 + .../CodeGen/X86/2011-01-10-DagCombineHang.ll | 15 + .../X86/2011-01-24-DbgValue-Before-Use.ll | 103 + .../X86/2011-02-04-FastRegallocNoFP.ll | 14 + .../2011-02-21-VirtRegRewriter-KillSubReg.ll | 50 + .../test/CodeGen/X86/2011-02-23-UnfoldBug.ll | 42 + final/test/CodeGen/X86/2011-02-27-Fpextend.ll | 7 + .../CodeGen/X86/2011-03-02-DAGCombiner.ll | 51 + .../X86/2011-03-09-Physreg-Coalescing.ll | 22 + final/test/CodeGen/X86/3addr-16bit.ll | 95 + final/test/CodeGen/X86/3addr-or.ll | 61 + final/test/CodeGen/X86/Atomics-32.ll | 818 + final/test/CodeGen/X86/Atomics-64.ll | 1015 + final/test/CodeGen/X86/GC/alloc_loop.ll | 53 + final/test/CodeGen/X86/GC/argpromotion.ll | 19 + final/test/CodeGen/X86/GC/badreadproto.ll | 13 + final/test/CodeGen/X86/GC/badrootproto.ll | 13 + final/test/CodeGen/X86/GC/badwriteproto.ll | 22 + final/test/CodeGen/X86/GC/deadargelim.ll | 16 + final/test/CodeGen/X86/GC/dg.exp | 5 + final/test/CodeGen/X86/GC/fat.ll | 10 + final/test/CodeGen/X86/GC/inline.ll | 23 + final/test/CodeGen/X86/GC/inline2.ll | 24 + final/test/CodeGen/X86/GC/lower_gcroot.ll | 11 + final/test/CodeGen/X86/GC/outside.ll | 10 + final/test/CodeGen/X86/GC/simple_ocaml.ll | 42 + .../test/CodeGen/X86/MachineSink-CritEdge.ll | 58 + final/test/CodeGen/X86/MachineSink-PHIUse.ll | 39 + final/test/CodeGen/X86/SIMD/dg.exp | 5 + final/test/CodeGen/X86/SIMD/notvunpcklpd.ll | 20 + final/test/CodeGen/X86/SIMD/notvunpcklps.ll | 20 + final/test/CodeGen/X86/SIMD/vunpcklpd.ll | 20 + final/test/CodeGen/X86/SIMD/vunpcklps.ll | 20 + final/test/CodeGen/X86/SwitchLowering.ll | 28 + final/test/CodeGen/X86/abi-isel.ll | 9660 +++++++ final/test/CodeGen/X86/add-of-carry.ll | 34 + final/test/CodeGen/X86/add.ll | 135 + final/test/CodeGen/X86/adde-carry.ll | 26 + .../test/CodeGen/X86/addr-label-difference.ll | 26 + final/test/CodeGen/X86/aliases.ll | 38 + final/test/CodeGen/X86/aligned-comm.ll | 6 + final/test/CodeGen/X86/alignment.ll | 43 + final/test/CodeGen/X86/all-ones-vector.ll | 14 + final/test/CodeGen/X86/alldiv-divdi3.ll | 17 + .../CodeGen/X86/alloca-align-rounding-32.ll | 15 + .../test/CodeGen/X86/alloca-align-rounding.ll | 15 + final/test/CodeGen/X86/and-or-fold.ll | 26 + final/test/CodeGen/X86/and-su.ll | 53 + final/test/CodeGen/X86/andimm8.ll | 19 + final/test/CodeGen/X86/anyext.ll | 18 + final/test/CodeGen/X86/apm.ll | 35 + final/test/CodeGen/X86/arg-cast.ll | 18 + final/test/CodeGen/X86/asm-block-labels.ll | 41 + final/test/CodeGen/X86/asm-global-imm.ll | 23 + final/test/CodeGen/X86/asm-indirect-mem.ll | 11 + final/test/CodeGen/X86/asm-modifier-P.ll | 79 + final/test/CodeGen/X86/asm-modifier.ll | 41 + final/test/CodeGen/X86/atomic_add.ll | 217 + final/test/CodeGen/X86/atomic_op.ll | 143 + final/test/CodeGen/X86/attribute-sections.ll | 18 + final/test/CodeGen/X86/avoid-lea-scale2.ll | 10 + final/test/CodeGen/X86/avoid-loop-align-2.ll | 49 + final/test/CodeGen/X86/avoid-loop-align.ll | 39 + final/test/CodeGen/X86/avx-128.ll | 12 + final/test/CodeGen/X86/avx-256.ll | 15 + final/test/CodeGen/X86/avx-intrinsics-x86.ll | 2578 ++ .../test/CodeGen/X86/avx-intrinsics-x86_64.ll | 50 + final/test/CodeGen/X86/barrier-sse.ll | 21 + final/test/CodeGen/X86/barrier.ll | 7 + final/test/CodeGen/X86/bc-extract.ll | 27 + final/test/CodeGen/X86/bigstructret.ll | 17 + final/test/CodeGen/X86/bigstructret2.ll | 12 + final/test/CodeGen/X86/bit-test-shift.ll | 13 + .../test/CodeGen/X86/bitcast-int-to-vector.ll | 10 + final/test/CodeGen/X86/bitcast.ll | 24 + final/test/CodeGen/X86/bitcast2.ll | 13 + final/test/CodeGen/X86/br-fold.ll | 20 + final/test/CodeGen/X86/brcond.ll | 108 + .../CodeGen/X86/break-anti-dependencies.ll | 34 + final/test/CodeGen/X86/break-sse-dep.ll | 63 + final/test/CodeGen/X86/bss_pagealigned.ll | 21 + final/test/CodeGen/X86/bswap-inline-asm.ll | 87 + final/test/CodeGen/X86/bswap.ll | 27 + final/test/CodeGen/X86/bt.ll | 442 + final/test/CodeGen/X86/byval.ll | 17 + final/test/CodeGen/X86/byval2.ll | 45 + final/test/CodeGen/X86/byval3.ll | 53 + final/test/CodeGen/X86/byval4.ll | 59 + final/test/CodeGen/X86/byval5.ll | 67 + final/test/CodeGen/X86/byval6.ll | 16 + final/test/CodeGen/X86/byval7.ll | 22 + final/test/CodeGen/X86/call-imm.ll | 18 + final/test/CodeGen/X86/call-push.ll | 29 + .../CodeGen/X86/change-compare-stride-0.ll | 77 + .../CodeGen/X86/change-compare-stride-1.ll | 86 + .../X86/change-compare-stride-trickiness-0.ll | 29 + .../X86/change-compare-stride-trickiness-1.ll | 28 + .../X86/change-compare-stride-trickiness-2.ll | 58 + final/test/CodeGen/X86/clz.ll | 33 + final/test/CodeGen/X86/cmov.ll | 157 + final/test/CodeGen/X86/cmp.ll | 92 + final/test/CodeGen/X86/coalesce-esp.ll | 36 + final/test/CodeGen/X86/coalescer-commute1.ll | 26 + final/test/CodeGen/X86/coalescer-commute2.ll | 39 + final/test/CodeGen/X86/coalescer-commute3.ll | 24 + final/test/CodeGen/X86/coalescer-commute4.ll | 30 + final/test/CodeGen/X86/coalescer-commute5.ll | 21 + final/test/CodeGen/X86/coalescer-cross.ll | 41 + final/test/CodeGen/X86/coalescer-remat.ll | 15 + final/test/CodeGen/X86/code_placement.ll | 136 + final/test/CodeGen/X86/code_placement_eh.ll | 45 + .../test/CodeGen/X86/codegen-prepare-cast.ll | 24 + .../CodeGen/X86/codegen-prepare-extload.ll | 21 + final/test/CodeGen/X86/codemodel.ll | 67 + final/test/CodeGen/X86/combine-lds.ll | 6 + final/test/CodeGen/X86/combiner-aa-0.ll | 20 + final/test/CodeGen/X86/combiner-aa-1.ll | 23 + final/test/CodeGen/X86/commute-intrinsic.ll | 15 + final/test/CodeGen/X86/commute-two-addr.ll | 62 + final/test/CodeGen/X86/compare-add.ll | 8 + final/test/CodeGen/X86/compare-inf.ll | 76 + final/test/CodeGen/X86/compare_folding.ll | 11 + final/test/CodeGen/X86/compiler_used.ll | 9 + final/test/CodeGen/X86/complex-asm.ll | 17 + final/test/CodeGen/X86/complex-fca.ll | 14 + .../CodeGen/X86/conditional-indecrement.ll | 89 + .../test/CodeGen/X86/constant-pool-remat-0.ll | 21 + .../test/CodeGen/X86/constant-pool-sharing.ll | 20 + final/test/CodeGen/X86/constpool.ll | 16 + .../X86/convert-2-addr-3-addr-inc64.ll | 26 + final/test/CodeGen/X86/copysign-zero.ll | 14 + final/test/CodeGen/X86/crash-O0.ll | 31 + final/test/CodeGen/X86/crash.ll | 201 + .../test/CodeGen/X86/critical-edge-split-2.ll | 29 + final/test/CodeGen/X86/cstring.ll | 4 + final/test/CodeGen/X86/ctpop-combine.ll | 40 + final/test/CodeGen/X86/dag-rauw-cse.ll | 9 + .../CodeGen/X86/dagcombine-buildvector.ll | 27 + final/test/CodeGen/X86/dagcombine-cse.ll | 27 + final/test/CodeGen/X86/darwin-bzero.ll | 8 + .../test/CodeGen/X86/darwin-no-dead-strip.ll | 7 + final/test/CodeGen/X86/darwin-quote.ll | 15 + final/test/CodeGen/X86/darwin-stub.ll | 12 + final/test/CodeGen/X86/dbg-byval-parameter.ll | 45 + final/test/CodeGen/X86/dbg-merge-loc-entry.ll | 71 + .../X86/dbg-value-inlined-parameter.ll | 86 + final/test/CodeGen/X86/dbg-value-location.ll | 70 + final/test/CodeGen/X86/dbg-value-range.ll | 56 + final/test/CodeGen/X86/dg.exp | 5 + final/test/CodeGen/X86/discontiguous-loops.ll | 72 + final/test/CodeGen/X86/divide-by-constant.ll | 62 + final/test/CodeGen/X86/divrem.ll | 58 + final/test/CodeGen/X86/dll-linkage.ll | 14 + final/test/CodeGen/X86/dllexport.ll | 12 + final/test/CodeGen/X86/dollar-name.ll | 18 + final/test/CodeGen/X86/dyn-stackalloc.ll | 19 + final/test/CodeGen/X86/empty-functions.ll | 15 + .../CodeGen/X86/empty-struct-return-type.ll | 15 + final/test/CodeGen/X86/epilogue.ll | 11 + final/test/CodeGen/X86/extend.ll | 18 + final/test/CodeGen/X86/extern_weak.ll | 13 + final/test/CodeGen/X86/extmul128.ll | 14 + final/test/CodeGen/X86/extmul64.ll | 14 + final/test/CodeGen/X86/extract-combine.ll | 15 + final/test/CodeGen/X86/extract-extract.ll | 24 + .../CodeGen/X86/extractelement-from-arg.ll | 7 + final/test/CodeGen/X86/extractelement-load.ll | 9 + .../CodeGen/X86/extractelement-shuffle.ll | 13 + final/test/CodeGen/X86/extractps.ll | 27 + final/test/CodeGen/X86/fabs.ll | 28 + final/test/CodeGen/X86/fast-cc-callee-pops.ll | 13 + .../CodeGen/X86/fast-cc-merge-stack-adj.ll | 13 + .../test/CodeGen/X86/fast-cc-pass-in-regs.ll | 29 + final/test/CodeGen/X86/fast-isel-atomic.ll | 17 + .../fast-isel-avoid-unnecessary-pic-base.ll | 23 + final/test/CodeGen/X86/fast-isel-bail.ll | 14 + final/test/CodeGen/X86/fast-isel-bc.ll | 23 + final/test/CodeGen/X86/fast-isel-call.ll | 13 + .../test/CodeGen/X86/fast-isel-cmp-branch.ll | 30 + final/test/CodeGen/X86/fast-isel-constpool.ll | 17 + final/test/CodeGen/X86/fast-isel-fneg.ll | 16 + final/test/CodeGen/X86/fast-isel-gep.ll | 109 + final/test/CodeGen/X86/fast-isel-gv.ll | 24 + final/test/CodeGen/X86/fast-isel-i1.ll | 19 + final/test/CodeGen/X86/fast-isel-mem.ll | 34 + final/test/CodeGen/X86/fast-isel-shift-imm.ll | 8 + final/test/CodeGen/X86/fast-isel-tailcall.ll | 13 + final/test/CodeGen/X86/fast-isel-tls.ll | 10 + final/test/CodeGen/X86/fast-isel-x86.ll | 33 + final/test/CodeGen/X86/fast-isel.ll | 94 + .../CodeGen/X86/fastcall-correct-mangling.ll | 9 + final/test/CodeGen/X86/fastcc-2.ll | 10 + final/test/CodeGen/X86/fastcc-byval.ll | 20 + final/test/CodeGen/X86/fastcc-sret.ll | 23 + final/test/CodeGen/X86/fastcc.ll | 20 + final/test/CodeGen/X86/fastcc3struct.ll | 15 + .../CodeGen/X86/field-extract-use-trunc.ll | 39 + final/test/CodeGen/X86/fildll.ll | 12 + final/test/CodeGen/X86/fltused.ll | 19 + final/test/CodeGen/X86/fmul-zero.ll | 9 + final/test/CodeGen/X86/fold-add.ll | 25 + final/test/CodeGen/X86/fold-and-shift.ll | 21 + final/test/CodeGen/X86/fold-call-2.ll | 10 + final/test/CodeGen/X86/fold-call-3.ll | 45 + final/test/CodeGen/X86/fold-call.ll | 10 + final/test/CodeGen/X86/fold-imm.ll | 14 + final/test/CodeGen/X86/fold-load.ll | 47 + final/test/CodeGen/X86/fold-mul-lohi.ll | 31 + final/test/CodeGen/X86/fold-pcmpeqd-0.ll | 105 + final/test/CodeGen/X86/fold-pcmpeqd-1.ll | 11 + final/test/CodeGen/X86/fold-pcmpeqd-2.ll | 94 + final/test/CodeGen/X86/fold-sext-trunc.ll | 20 + final/test/CodeGen/X86/force-align-stack.ll | 21 + final/test/CodeGen/X86/fp-elim.ll | 44 + .../test/CodeGen/X86/fp-immediate-shorten.ll | 9 + final/test/CodeGen/X86/fp-in-intregs.ll | 22 + final/test/CodeGen/X86/fp-stack-2results.ll | 60 + final/test/CodeGen/X86/fp-stack-O0-crash.ll | 30 + final/test/CodeGen/X86/fp-stack-compare.ll | 11 + final/test/CodeGen/X86/fp-stack-direct-ret.ll | 11 + final/test/CodeGen/X86/fp-stack-ret-conv.ll | 17 + final/test/CodeGen/X86/fp-stack-ret-store.ll | 26 + final/test/CodeGen/X86/fp-stack-ret.ll | 25 + final/test/CodeGen/X86/fp-stack-retcopy.ll | 12 + final/test/CodeGen/X86/fp-stack-set-st1.ll | 7 + final/test/CodeGen/X86/fp-stack.ll | 25 + final/test/CodeGen/X86/fp2sint.ll | 18 + final/test/CodeGen/X86/fp_constant_op.ll | 46 + final/test/CodeGen/X86/fp_load_cast_fold.ll | 20 + final/test/CodeGen/X86/fp_load_fold.ll | 40 + final/test/CodeGen/X86/fsxor-alignment.ll | 14 + final/test/CodeGen/X86/full-lsr.ll | 34 + final/test/CodeGen/X86/ga-offset.ll | 18 + final/test/CodeGen/X86/gather-addresses.ll | 41 + final/test/CodeGen/X86/ghc-cc.ll | 45 + final/test/CodeGen/X86/ghc-cc64.ll | 86 + final/test/CodeGen/X86/global-sections-tls.ll | 14 + final/test/CodeGen/X86/global-sections.ll | 160 + .../CodeGen/X86/h-register-addressing-32.ll | 53 + .../CodeGen/X86/h-register-addressing-64.ll | 53 + final/test/CodeGen/X86/h-register-store.ll | 47 + final/test/CodeGen/X86/h-registers-0.ll | 106 + final/test/CodeGen/X86/h-registers-1.ll | 39 + final/test/CodeGen/X86/h-registers-2.ll | 15 + final/test/CodeGen/X86/h-registers-3.ll | 12 + final/test/CodeGen/X86/hidden-vis-2.ll | 10 + final/test/CodeGen/X86/hidden-vis-3.ll | 19 + final/test/CodeGen/X86/hidden-vis-4.ll | 12 + final/test/CodeGen/X86/hidden-vis-pic.ll | 55 + final/test/CodeGen/X86/hidden-vis.ll | 24 + final/test/CodeGen/X86/i128-and-beyond.ll | 8 + final/test/CodeGen/X86/i128-immediate.ll | 5 + final/test/CodeGen/X86/i128-mul.ll | 12 + final/test/CodeGen/X86/i128-ret.ll | 10 + final/test/CodeGen/X86/i256-add.ll | 18 + final/test/CodeGen/X86/i2k.ll | 9 + final/test/CodeGen/X86/i64-mem-copy.ll | 17 + final/test/CodeGen/X86/iabs.ll | 16 + final/test/CodeGen/X86/illegal-insert.ll | 18 + .../CodeGen/X86/illegal-vector-args-return.ll | 14 + final/test/CodeGen/X86/imul-lea-2.ll | 15 + final/test/CodeGen/X86/imul-lea.ll | 10 + final/test/CodeGen/X86/inline-asm-2addr.ll | 9 + .../CodeGen/X86/inline-asm-R-constraint.ll | 18 + .../CodeGen/X86/inline-asm-flag-clobber.ll | 19 + final/test/CodeGen/X86/inline-asm-fpstack.ll | 88 + final/test/CodeGen/X86/inline-asm-fpstack2.ll | 21 + final/test/CodeGen/X86/inline-asm-fpstack3.ll | 20 + final/test/CodeGen/X86/inline-asm-fpstack4.ll | 24 + final/test/CodeGen/X86/inline-asm-fpstack5.ll | 15 + final/test/CodeGen/X86/inline-asm-h.ll | 12 + .../test/CodeGen/X86/inline-asm-modifier-n.ll | 8 + final/test/CodeGen/X86/inline-asm-mrv.ll | 35 + final/test/CodeGen/X86/inline-asm-out-regs.ll | 40 + final/test/CodeGen/X86/inline-asm-pic.ll | 10 + final/test/CodeGen/X86/inline-asm-ptr-cast.ll | 27 + final/test/CodeGen/X86/inline-asm-q-regs.ll | 10 + final/test/CodeGen/X86/inline-asm-tied.ll | 19 + final/test/CodeGen/X86/inline-asm-x-scalar.ll | 24 + final/test/CodeGen/X86/inline-asm.ll | 25 + .../test/CodeGen/X86/ins_subreg_coalesce-1.ll | 30 + .../test/CodeGen/X86/ins_subreg_coalesce-2.ll | 7 + .../test/CodeGen/X86/ins_subreg_coalesce-3.ll | 92 + final/test/CodeGen/X86/insert-positions.ll | 69 + .../CodeGen/X86/insertelement-copytoregs.ll | 11 + .../CodeGen/X86/insertelement-legalize.ll | 10 + final/test/CodeGen/X86/int-intrinsic.ll | 20 + .../CodeGen/X86/invalid-shift-immediate.ll | 30 + final/test/CodeGen/X86/isel-sink.ll | 18 + final/test/CodeGen/X86/isel-sink2.ll | 17 + final/test/CodeGen/X86/isel-sink3.ll | 25 + final/test/CodeGen/X86/isint.ll | 31 + final/test/CodeGen/X86/isnan.ll | 9 + final/test/CodeGen/X86/isnan2.ll | 11 + final/test/CodeGen/X86/ispositive.ll | 9 + .../CodeGen/X86/iv-users-in-other-loops.ll | 296 + final/test/CodeGen/X86/jump_sign.ll | 20 + final/test/CodeGen/X86/label-redefinition.ll | 15 + final/test/CodeGen/X86/large-gep-scale.ll | 12 + final/test/CodeGen/X86/ldzero.ll | 43 + final/test/CodeGen/X86/lea-2.ll | 13 + final/test/CodeGen/X86/lea-3.ll | 22 + final/test/CodeGen/X86/lea-4.ll | 19 + final/test/CodeGen/X86/lea-recursion.ll | 47 + final/test/CodeGen/X86/lea.ll | 35 + final/test/CodeGen/X86/leaf-fp-elim.ll | 30 + .../X86/legalize-fmp-oeq-vector-select.ll | 11 + final/test/CodeGen/X86/legalize-sub-zero-2.ll | 41 + final/test/CodeGen/X86/legalize-sub-zero.ll | 35 + final/test/CodeGen/X86/legalizedag_vec.ll | 17 + final/test/CodeGen/X86/lfence.ll | 8 + final/test/CodeGen/X86/licm-nested.ll | 89 + final/test/CodeGen/X86/licm-symbol.ll | 39 + final/test/CodeGen/X86/limited-prec.ll | 60 + final/test/CodeGen/X86/live-out-reg-info.ll | 20 + .../CodeGen/X86/liveness-local-regalloc.ll | 60 + final/test/CodeGen/X86/lock-inst-encoding.ll | 22 + final/test/CodeGen/X86/long-setcc.ll | 18 + final/test/CodeGen/X86/longlong-deadload.ll | 11 + final/test/CodeGen/X86/loop-blocks.ll | 208 + final/test/CodeGen/X86/loop-hoist.ll | 27 + .../CodeGen/X86/loop-strength-reduce-2.ll | 45 + .../CodeGen/X86/loop-strength-reduce-3.ll | 33 + .../test/CodeGen/X86/loop-strength-reduce.ll | 33 + .../test/CodeGen/X86/loop-strength-reduce2.ll | 29 + .../test/CodeGen/X86/loop-strength-reduce3.ll | 37 + .../test/CodeGen/X86/loop-strength-reduce4.ll | 63 + .../test/CodeGen/X86/loop-strength-reduce5.ll | 23 + .../test/CodeGen/X86/loop-strength-reduce6.ll | 66 + .../test/CodeGen/X86/loop-strength-reduce7.ll | 44 + .../test/CodeGen/X86/loop-strength-reduce8.ll | 84 + final/test/CodeGen/X86/lsr-delayed-fold.ll | 178 + final/test/CodeGen/X86/lsr-i386.ll | 44 + .../test/CodeGen/X86/lsr-interesting-step.ll | 51 + final/test/CodeGen/X86/lsr-loop-exit-cond.ll | 138 + final/test/CodeGen/X86/lsr-negative-stride.ll | 51 + final/test/CodeGen/X86/lsr-nonaffine.ll | 23 + final/test/CodeGen/X86/lsr-normalization.ll | 99 + final/test/CodeGen/X86/lsr-overflow.ll | 27 + .../test/CodeGen/X86/lsr-quadratic-expand.ll | 22 + .../CodeGen/X86/lsr-redundant-addressing.ll | 45 + final/test/CodeGen/X86/lsr-reuse-trunc.ll | 60 + final/test/CodeGen/X86/lsr-reuse.ll | 751 + final/test/CodeGen/X86/lsr-sort.ll | 23 + final/test/CodeGen/X86/lsr-static-addr.ll | 31 + final/test/CodeGen/X86/lsr-wrap.ll | 37 + final/test/CodeGen/X86/machine-cse.ll | 79 + final/test/CodeGen/X86/masked-iv-safe.ll | 244 + final/test/CodeGen/X86/masked-iv-unsafe.ll | 386 + final/test/CodeGen/X86/maskmovdqu.ll | 11 + .../test/CodeGen/X86/mcinst-lowering-cmp0.ll | 68 + final/test/CodeGen/X86/mcinst-lowering.ll | 26 + final/test/CodeGen/X86/memcmp.ll | 111 + final/test/CodeGen/X86/memcpy-2.ll | 167 + final/test/CodeGen/X86/memcpy.ll | 81 + final/test/CodeGen/X86/memmove-4.ll | 12 + final/test/CodeGen/X86/memset-2.ll | 39 + final/test/CodeGen/X86/memset-3.ll | 12 + final/test/CodeGen/X86/memset.ll | 18 + final/test/CodeGen/X86/memset64-on-x86-32.ll | 12 + final/test/CodeGen/X86/mfence.ll | 20 + final/test/CodeGen/X86/mingw-alloca.ll | 30 + final/test/CodeGen/X86/misaligned-memset.ll | 15 + final/test/CodeGen/X86/mmx-arg-passing.ll | 27 + final/test/CodeGen/X86/mmx-arg-passing2.ll | 28 + final/test/CodeGen/X86/mmx-arith.ll | 309 + final/test/CodeGen/X86/mmx-bitcast-to-i64.ll | 31 + final/test/CodeGen/X86/mmx-builtins.ll | 1324 + final/test/CodeGen/X86/mmx-copy-gprs.ll | 19 + final/test/CodeGen/X86/mmx-emms.ll | 11 + final/test/CodeGen/X86/mmx-insert-element.ll | 9 + final/test/CodeGen/X86/mmx-pinsrw.ll | 15 + final/test/CodeGen/X86/mmx-punpckhdq.ll | 31 + final/test/CodeGen/X86/mmx-s2v.ll | 15 + final/test/CodeGen/X86/mmx-shift.ll | 32 + final/test/CodeGen/X86/mmx-shuffle.ll | 31 + final/test/CodeGen/X86/mmx-vzmovl-2.ll | 29 + final/test/CodeGen/X86/mmx-vzmovl.ll | 15 + final/test/CodeGen/X86/movfs.ll | 8 + final/test/CodeGen/X86/movgs.ll | 58 + final/test/CodeGen/X86/mul-legalize.ll | 24 + final/test/CodeGen/X86/mul-remat.ll | 8 + final/test/CodeGen/X86/mul-shift-reassoc.ll | 12 + final/test/CodeGen/X86/mul128.ll | 6 + final/test/CodeGen/X86/mul64.ll | 6 + .../test/CodeGen/X86/mult-alt-generic-i686.ll | 321 + .../CodeGen/X86/mult-alt-generic-x86_64.ll | 321 + final/test/CodeGen/X86/mult-alt-x86.ll | 358 + .../CodeGen/X86/multiple-loop-post-inc.ll | 304 + .../X86/multiple-return-values-cross-block.ll | 15 + .../CodeGen/X86/multiple-return-values.ll | 16 + final/test/CodeGen/X86/nancvt.ll | 183 + final/test/CodeGen/X86/narrow-shl-load.ll | 83 + final/test/CodeGen/X86/narrow_op-1.ll | 23 + final/test/CodeGen/X86/neg-shl-add.ll | 17 + final/test/CodeGen/X86/neg_fp.ll | 12 + final/test/CodeGen/X86/negate-add-zero.ll | 1145 + final/test/CodeGen/X86/negative-sin.ll | 12 + .../X86/negative-stride-fptosi-user.ll | 25 + final/test/CodeGen/X86/negative-subscript.ll | 10 + final/test/CodeGen/X86/negative_zero.ll | 6 + final/test/CodeGen/X86/nobt.ll | 70 + final/test/CodeGen/X86/nofence.ll | 27 + final/test/CodeGen/X86/nosse-error1.ll | 33 + final/test/CodeGen/X86/nosse-error2.ll | 33 + final/test/CodeGen/X86/nosse-varargs.ll | 46 + final/test/CodeGen/X86/object-size.ll | 55 + final/test/CodeGen/X86/opt-ext-uses.ll | 19 + final/test/CodeGen/X86/optimize-max-0.ll | 461 + final/test/CodeGen/X86/optimize-max-1.ll | 78 + final/test/CodeGen/X86/optimize-max-2.ll | 30 + final/test/CodeGen/X86/optimize-max-3.ll | 77 + final/test/CodeGen/X86/or-address.ll | 90 + final/test/CodeGen/X86/or-branch.ll | 19 + final/test/CodeGen/X86/overlap-shift.ll | 19 + final/test/CodeGen/X86/packed_struct.ll | 34 + final/test/CodeGen/X86/palignr-2.ll | 28 + final/test/CodeGen/X86/palignr.ll | 58 + final/test/CodeGen/X86/peep-test-0.ll | 22 + final/test/CodeGen/X86/peep-test-1.ll | 23 + final/test/CodeGen/X86/peep-test-2.ll | 17 + final/test/CodeGen/X86/peep-test-3.ll | 89 + .../CodeGen/X86/peep-vector-extract-concat.ll | 11 + .../CodeGen/X86/peep-vector-extract-insert.ll | 12 + final/test/CodeGen/X86/personality.ll | 50 + final/test/CodeGen/X86/phi-bit-propagation.ll | 55 + .../CodeGen/X86/phi-immediate-factoring.ll | 54 + .../CodeGen/X86/phys-reg-local-regalloc.ll | 51 + .../CodeGen/X86/phys_subreg_coalesce-2.ll | 30 + .../CodeGen/X86/phys_subreg_coalesce-3.ll | 35 + .../test/CodeGen/X86/phys_subreg_coalesce.ll | 24 + final/test/CodeGen/X86/pic-load-remat.ll | 47 + final/test/CodeGen/X86/pic.ll | 208 + final/test/CodeGen/X86/pic_jumptable.ll | 83 + final/test/CodeGen/X86/pmul.ll | 32 + final/test/CodeGen/X86/pmulld.ll | 26 + final/test/CodeGen/X86/popcnt.ll | 38 + .../test/CodeGen/X86/postalloc-coalescing.ll | 35 + final/test/CodeGen/X86/postra-licm.ll | 185 + final/test/CodeGen/X86/powi.ll | 11 + final/test/CodeGen/X86/pr1462.ll | 25 + final/test/CodeGen/X86/pr1489.ll | 55 + final/test/CodeGen/X86/pr1505.ll | 12 + final/test/CodeGen/X86/pr1505b.ll | 59 + final/test/CodeGen/X86/pr2177.ll | 35 + final/test/CodeGen/X86/pr2182.ll | 24 + final/test/CodeGen/X86/pr2326.ll | 24 + final/test/CodeGen/X86/pr2623.ll | 44 + final/test/CodeGen/X86/pr2656.ll | 23 + final/test/CodeGen/X86/pr2659.ll | 40 + final/test/CodeGen/X86/pr2849.ll | 38 + final/test/CodeGen/X86/pr2924.ll | 24 + final/test/CodeGen/X86/pr2982.ll | 26 + final/test/CodeGen/X86/pr3154.ll | 104 + final/test/CodeGen/X86/pr3216.ll | 14 + final/test/CodeGen/X86/pr3241.ll | 29 + final/test/CodeGen/X86/pr3243.ll | 15 + final/test/CodeGen/X86/pr3244.ll | 26 + final/test/CodeGen/X86/pr3250.ll | 17 + final/test/CodeGen/X86/pr3317.ll | 46 + final/test/CodeGen/X86/pr3366.ll | 21 + final/test/CodeGen/X86/pr3457.ll | 16 + final/test/CodeGen/X86/pr3495-2.ll | 54 + final/test/CodeGen/X86/pr3495.ll | 79 + final/test/CodeGen/X86/pr3522.ll | 30 + final/test/CodeGen/X86/pr7882.ll | 17 + final/test/CodeGen/X86/pr9127.ll | 13 + final/test/CodeGen/X86/pre-split1.ll | 24 + final/test/CodeGen/X86/pre-split10.ll | 51 + final/test/CodeGen/X86/pre-split11.ll | 34 + final/test/CodeGen/X86/pre-split2.ll | 26 + final/test/CodeGen/X86/pre-split3.ll | 26 + final/test/CodeGen/X86/pre-split4.ll | 26 + final/test/CodeGen/X86/pre-split5.ll | 56 + final/test/CodeGen/X86/pre-split6.ll | 36 + final/test/CodeGen/X86/pre-split7.ll | 34 + final/test/CodeGen/X86/pre-split8.ll | 35 + final/test/CodeGen/X86/pre-split9.ll | 38 + final/test/CodeGen/X86/prefetch.ll | 16 + final/test/CodeGen/X86/private-2.ll | 13 + final/test/CodeGen/X86/private.ll | 20 + final/test/CodeGen/X86/promote-assert-zext.ll | 22 + final/test/CodeGen/X86/promote-i16.ll | 11 + final/test/CodeGen/X86/ptrtoint-constexpr.ll | 14 + final/test/CodeGen/X86/rdtsc.ll | 8 + final/test/CodeGen/X86/red-zone.ll | 25 + final/test/CodeGen/X86/red-zone2.ll | 9 + final/test/CodeGen/X86/regpressure.ll | 114 + final/test/CodeGen/X86/rem-2.ll | 7 + final/test/CodeGen/X86/rem.ll | 22 + final/test/CodeGen/X86/remat-constant.ll | 15 + final/test/CodeGen/X86/remat-mov-0.ll | 34 + final/test/CodeGen/X86/remat-scalar-zero.ll | 96 + final/test/CodeGen/X86/ret-addr.ll | 22 + final/test/CodeGen/X86/ret-i64-0.ll | 5 + final/test/CodeGen/X86/ret-mmx.ll | 26 + final/test/CodeGen/X86/rip-rel-address.ll | 14 + final/test/CodeGen/X86/rodata-relocs.ll | 23 + final/test/CodeGen/X86/rot16.ll | 85 + final/test/CodeGen/X86/rot32.ll | 85 + final/test/CodeGen/X86/rot64.ll | 73 + final/test/CodeGen/X86/rotate.ll | 100 + final/test/CodeGen/X86/rotate2.ll | 19 + final/test/CodeGen/X86/scalar-extract.ll | 13 + .../X86/scalar-min-max-fill-operand.ll | 27 + final/test/CodeGen/X86/scalar_sse_minmax.ll | 44 + final/test/CodeGen/X86/scalar_widen_div.ll | 183 + final/test/CodeGen/X86/scalarize-bitcast.ll | 29 + final/test/CodeGen/X86/scev-interchange.ll | 338 + final/test/CodeGen/X86/select.ll | 220 + final/test/CodeGen/X86/setcc.ll | 36 + final/test/CodeGen/X86/setoeq.ll | 11 + final/test/CodeGen/X86/setuge.ll | 13 + final/test/CodeGen/X86/sext-i1.ll | 63 + final/test/CodeGen/X86/sext-load.ll | 9 + final/test/CodeGen/X86/sext-ret-val.ll | 16 + final/test/CodeGen/X86/sext-subreg.ll | 17 + final/test/CodeGen/X86/sext-trunc.ll | 9 + final/test/CodeGen/X86/sfence.ll | 8 + final/test/CodeGen/X86/shift-and.ll | 24 + final/test/CodeGen/X86/shift-coalesce.ll | 15 + final/test/CodeGen/X86/shift-codegen.ll | 27 + final/test/CodeGen/X86/shift-combine.ll | 15 + final/test/CodeGen/X86/shift-double.ll | 41 + final/test/CodeGen/X86/shift-folding.ll | 28 + final/test/CodeGen/X86/shift-i128.ll | 9 + final/test/CodeGen/X86/shift-i256.ll | 9 + final/test/CodeGen/X86/shift-one.ll | 10 + final/test/CodeGen/X86/shift-parts.ll | 22 + final/test/CodeGen/X86/shl-anyext.ll | 40 + final/test/CodeGen/X86/shl_elim.ll | 13 + final/test/CodeGen/X86/shrink-fp-const1.ll | 7 + final/test/CodeGen/X86/shrink-fp-const2.ll | 7 + final/test/CodeGen/X86/sibcall-2.ll | 52 + final/test/CodeGen/X86/sibcall-3.ll | 16 + final/test/CodeGen/X86/sibcall-4.ll | 13 + final/test/CodeGen/X86/sibcall-5.ll | 31 + final/test/CodeGen/X86/sibcall.ll | 333 + final/test/CodeGen/X86/sincos.ll | 48 + final/test/CodeGen/X86/sink-hoist.ll | 174 + final/test/CodeGen/X86/small-byval-memcpy.ll | 20 + .../test/CodeGen/X86/smul-with-overflow-2.ll | 20 + .../test/CodeGen/X86/smul-with-overflow-3.ll | 23 + final/test/CodeGen/X86/smul-with-overflow.ll | 23 + final/test/CodeGen/X86/soft-fp.ll | 27 + final/test/CodeGen/X86/splat-scalar-load.ll | 17 + final/test/CodeGen/X86/split-eh-lpad-edges.ll | 34 + final/test/CodeGen/X86/split-vector-rem.ll | 15 + final/test/CodeGen/X86/sret.ll | 23 + final/test/CodeGen/X86/sse-align-0.ll | 13 + final/test/CodeGen/X86/sse-align-1.ll | 10 + final/test/CodeGen/X86/sse-align-10.ll | 6 + final/test/CodeGen/X86/sse-align-11.ll | 13 + final/test/CodeGen/X86/sse-align-12.ll | 57 + final/test/CodeGen/X86/sse-align-2.ll | 12 + final/test/CodeGen/X86/sse-align-3.ll | 15 + final/test/CodeGen/X86/sse-align-4.ll | 10 + final/test/CodeGen/X86/sse-align-5.ll | 6 + final/test/CodeGen/X86/sse-align-6.ll | 7 + final/test/CodeGen/X86/sse-align-7.ll | 8 + final/test/CodeGen/X86/sse-align-8.ll | 6 + final/test/CodeGen/X86/sse-align-9.ll | 10 + final/test/CodeGen/X86/sse-commute.ll | 20 + final/test/CodeGen/X86/sse-fcopysign.ll | 16 + final/test/CodeGen/X86/sse-load-ret.ll | 19 + final/test/CodeGen/X86/sse-minmax.ll | 932 + final/test/CodeGen/X86/sse-varargs.ll | 9 + final/test/CodeGen/X86/sse1.ll | 45 + final/test/CodeGen/X86/sse2.ll | 224 + final/test/CodeGen/X86/sse3.ll | 277 + final/test/CodeGen/X86/sse41.ll | 251 + final/test/CodeGen/X86/sse42.ll | 38 + final/test/CodeGen/X86/sse_reload_fold.ll | 125 + final/test/CodeGen/X86/stack-align.ll | 51 + .../test/CodeGen/X86/stack-protector-linux.ll | 28 + final/test/CodeGen/X86/stdarg.ll | 21 + final/test/CodeGen/X86/stdcall-notailcall.ll | 13 + final/test/CodeGen/X86/stdcall.ll | 16 + final/test/CodeGen/X86/store-empty-member.ll | 14 + final/test/CodeGen/X86/store-fp-constant.ll | 19 + .../test/CodeGen/X86/store-global-address.ll | 10 + final/test/CodeGen/X86/store-narrow.ll | 168 + final/test/CodeGen/X86/store_op_load_fold.ll | 13 + final/test/CodeGen/X86/store_op_load_fold2.ll | 24 + final/test/CodeGen/X86/storetrunc-fp.ll | 8 + .../CodeGen/X86/stride-nine-with-base-reg.ll | 38 + final/test/CodeGen/X86/stride-reuse.ll | 31 + final/test/CodeGen/X86/sub-with-overflow.ll | 41 + final/test/CodeGen/X86/subreg-to-reg-0.ll | 11 + final/test/CodeGen/X86/subreg-to-reg-1.ll | 13 + final/test/CodeGen/X86/subreg-to-reg-2.ll | 25 + final/test/CodeGen/X86/subreg-to-reg-3.ll | 10 + final/test/CodeGen/X86/subreg-to-reg-4.ll | 135 + final/test/CodeGen/X86/subreg-to-reg-6.ll | 29 + final/test/CodeGen/X86/switch-bt.ll | 81 + .../CodeGen/X86/switch-crit-edge-constant.ll | 52 + final/test/CodeGen/X86/switch-or.ll | 22 + final/test/CodeGen/X86/switch-zextload.ll | 34 + final/test/CodeGen/X86/swizzle.ll | 19 + final/test/CodeGen/X86/tail-opts.ll | 428 + final/test/CodeGen/X86/tailcall-fastisel.ll | 19 + final/test/CodeGen/X86/tailcall-i1.ll | 6 + final/test/CodeGen/X86/tailcall-largecode.ll | 71 + .../CodeGen/X86/tailcall-returndup-void.ll | 37 + final/test/CodeGen/X86/tailcall-ri64.ll | 24 + final/test/CodeGen/X86/tailcall-stackalign.ll | 23 + final/test/CodeGen/X86/tailcall-structret.ll | 6 + final/test/CodeGen/X86/tailcall-void.ll | 6 + final/test/CodeGen/X86/tailcall1.ll | 40 + final/test/CodeGen/X86/tailcallbyval.ll | 18 + final/test/CodeGen/X86/tailcallbyval64.ll | 42 + final/test/CodeGen/X86/tailcallfp.ll | 5 + final/test/CodeGen/X86/tailcallfp2.ll | 27 + final/test/CodeGen/X86/tailcallpic1.ll | 12 + final/test/CodeGen/X86/tailcallpic2.ll | 12 + final/test/CodeGen/X86/tailcallstack64.ll | 28 + final/test/CodeGen/X86/test-nofold.ll | 42 + final/test/CodeGen/X86/test-shrink-bug.ll | 23 + final/test/CodeGen/X86/test-shrink.ll | 159 + final/test/CodeGen/X86/testl-commute.ll | 56 + final/test/CodeGen/X86/tls-pic.ll | 67 + final/test/CodeGen/X86/tls1.ll | 12 + final/test/CodeGen/X86/tls10.ll | 13 + final/test/CodeGen/X86/tls11.ll | 12 + final/test/CodeGen/X86/tls12.ll | 12 + final/test/CodeGen/X86/tls13.ll | 24 + final/test/CodeGen/X86/tls14.ll | 24 + final/test/CodeGen/X86/tls15.ll | 18 + final/test/CodeGen/X86/tls2.ll | 13 + final/test/CodeGen/X86/tls3.ll | 14 + final/test/CodeGen/X86/tls4.ll | 13 + final/test/CodeGen/X86/tls5.ll | 12 + final/test/CodeGen/X86/tls6.ll | 13 + final/test/CodeGen/X86/tls7.ll | 12 + final/test/CodeGen/X86/tls8.ll | 13 + final/test/CodeGen/X86/tls9.ll | 12 + final/test/CodeGen/X86/tlv-1.ll | 35 + final/test/CodeGen/X86/tlv-2.ll | 32 + final/test/CodeGen/X86/trap.ll | 9 + final/test/CodeGen/X86/trunc-to-bool.ll | 59 + final/test/CodeGen/X86/twoaddr-coalesce-2.ll | 15 + final/test/CodeGen/X86/twoaddr-coalesce.ll | 24 + final/test/CodeGen/X86/twoaddr-lea.ll | 47 + final/test/CodeGen/X86/twoaddr-pass-sink.ll | 29 + final/test/CodeGen/X86/twoaddr-remat.ll | 67 + final/test/CodeGen/X86/uint64-to-float.ll | 21 + final/test/CodeGen/X86/uint_to_fp-2.ll | 8 + final/test/CodeGen/X86/uint_to_fp.ll | 14 + final/test/CodeGen/X86/umul-with-carry.ll | 26 + final/test/CodeGen/X86/umul-with-overflow.ll | 14 + final/test/CodeGen/X86/unaligned-load.ll | 36 + final/test/CodeGen/X86/unknown-location.ll | 34 + .../CodeGen/X86/unreachable-loop-sinking.ll | 30 + final/test/CodeGen/X86/urem-i8-constant.ll | 6 + final/test/CodeGen/X86/use-add-flags.ll | 57 + final/test/CodeGen/X86/v-binop-widen.ll | 12 + final/test/CodeGen/X86/v-binop-widen2.ll | 40 + final/test/CodeGen/X86/v2f32.ll | 115 + final/test/CodeGen/X86/v4f32-immediate.ll | 5 + .../X86/variable-sized-darwin-bzero.ll | 8 + final/test/CodeGen/X86/variadic-node-pic.ll | 11 + final/test/CodeGen/X86/vec-sign.ll | 30 + final/test/CodeGen/X86/vec-trunc-store.ll | 15 + final/test/CodeGen/X86/vec_add.ll | 7 + final/test/CodeGen/X86/vec_align.ll | 35 + final/test/CodeGen/X86/vec_anyext.ll | 77 + final/test/CodeGen/X86/vec_call.ll | 13 + final/test/CodeGen/X86/vec_cast.ll | 56 + final/test/CodeGen/X86/vec_clear.ll | 13 + final/test/CodeGen/X86/vec_compare-2.ll | 29 + final/test/CodeGen/X86/vec_compare.ll | 43 + final/test/CodeGen/X86/vec_ctbits.ll | 18 + final/test/CodeGen/X86/vec_ext_inreg.ll | 37 + final/test/CodeGen/X86/vec_extract-sse4.ll | 31 + final/test/CodeGen/X86/vec_extract.ll | 36 + final/test/CodeGen/X86/vec_fneg.ll | 11 + final/test/CodeGen/X86/vec_i64.ll | 22 + final/test/CodeGen/X86/vec_ins_extract-1.ll | 25 + final/test/CodeGen/X86/vec_ins_extract.ll | 52 + final/test/CodeGen/X86/vec_insert-2.ll | 25 + final/test/CodeGen/X86/vec_insert-3.ll | 6 + final/test/CodeGen/X86/vec_insert-4.ll | 11 + final/test/CodeGen/X86/vec_insert-5.ll | 33 + final/test/CodeGen/X86/vec_insert-6.ll | 8 + final/test/CodeGen/X86/vec_insert-7.ll | 15 + final/test/CodeGen/X86/vec_insert-8.ll | 15 + final/test/CodeGen/X86/vec_insert-9.ll | 9 + final/test/CodeGen/X86/vec_insert.ll | 19 + final/test/CodeGen/X86/vec_loadsingles.ll | 12 + final/test/CodeGen/X86/vec_logical.ll | 42 + final/test/CodeGen/X86/vec_return.ll | 12 + final/test/CodeGen/X86/vec_set-2.ll | 19 + final/test/CodeGen/X86/vec_set-3.ll | 17 + final/test/CodeGen/X86/vec_set-4.ll | 24 + final/test/CodeGen/X86/vec_set-5.ll | 28 + final/test/CodeGen/X86/vec_set-6.ll | 12 + final/test/CodeGen/X86/vec_set-7.ll | 11 + final/test/CodeGen/X86/vec_set-8.ll | 13 + final/test/CodeGen/X86/vec_set-9.ll | 9 + final/test/CodeGen/X86/vec_set-A.ll | 6 + final/test/CodeGen/X86/vec_set-B.ll | 24 + final/test/CodeGen/X86/vec_set-C.ll | 8 + final/test/CodeGen/X86/vec_set-D.ll | 7 + final/test/CodeGen/X86/vec_set-E.ll | 9 + final/test/CodeGen/X86/vec_set-F.ll | 19 + final/test/CodeGen/X86/vec_set-G.ll | 9 + final/test/CodeGen/X86/vec_set-H.ll | 15 + final/test/CodeGen/X86/vec_set-I.ll | 10 + final/test/CodeGen/X86/vec_set-J.ll | 10 + final/test/CodeGen/X86/vec_set.ll | 15 + final/test/CodeGen/X86/vec_sext.ll | 69 + final/test/CodeGen/X86/vec_shift.ll | 34 + final/test/CodeGen/X86/vec_shift2.ll | 17 + final/test/CodeGen/X86/vec_shift3.ll | 26 + final/test/CodeGen/X86/vec_shift4.ll | 25 + final/test/CodeGen/X86/vec_shuffle-11.ll | 11 + final/test/CodeGen/X86/vec_shuffle-14.ll | 42 + final/test/CodeGen/X86/vec_shuffle-15.ll | 81 + final/test/CodeGen/X86/vec_shuffle-16.ll | 27 + final/test/CodeGen/X86/vec_shuffle-17.ll | 16 + final/test/CodeGen/X86/vec_shuffle-18.ll | 25 + final/test/CodeGen/X86/vec_shuffle-19.ll | 8 + final/test/CodeGen/X86/vec_shuffle-20.ll | 7 + final/test/CodeGen/X86/vec_shuffle-22.ll | 15 + final/test/CodeGen/X86/vec_shuffle-23.ll | 18 + final/test/CodeGen/X86/vec_shuffle-24.ll | 18 + final/test/CodeGen/X86/vec_shuffle-25.ll | 34 + final/test/CodeGen/X86/vec_shuffle-26.ll | 29 + final/test/CodeGen/X86/vec_shuffle-27.ll | 38 + final/test/CodeGen/X86/vec_shuffle-28.ll | 12 + final/test/CodeGen/X86/vec_shuffle-30.ll | 22 + final/test/CodeGen/X86/vec_shuffle-31.ll | 8 + final/test/CodeGen/X86/vec_shuffle-34.ll | 7 + final/test/CodeGen/X86/vec_shuffle-35.ll | 20 + final/test/CodeGen/X86/vec_shuffle-36.ll | 16 + final/test/CodeGen/X86/vec_shuffle-37.ll | 25 + final/test/CodeGen/X86/vec_shuffle.ll | 45 + final/test/CodeGen/X86/vec_splat-2.ll | 26 + final/test/CodeGen/X86/vec_splat-3.ll | 55 + final/test/CodeGen/X86/vec_splat-4.ll | 104 + final/test/CodeGen/X86/vec_splat.ll | 22 + final/test/CodeGen/X86/vec_ss_load_fold.ll | 72 + final/test/CodeGen/X86/vec_zero-2.ll | 24 + final/test/CodeGen/X86/vec_zero.ll | 18 + final/test/CodeGen/X86/vec_zero_cse.ll | 35 + final/test/CodeGen/X86/vec_zext.ll | 69 + final/test/CodeGen/X86/vector-intrinsics.ll | 52 + final/test/CodeGen/X86/vector-rem.ll | 15 + final/test/CodeGen/X86/vector-variable-idx.ll | 11 + final/test/CodeGen/X86/vector.ll | 156 + final/test/CodeGen/X86/vfcmp.ll | 15 + final/test/CodeGen/X86/visibility.ll | 11 + final/test/CodeGen/X86/volatile.ll | 17 + final/test/CodeGen/X86/vortex-bug.ll | 21 + final/test/CodeGen/X86/vshift-1.ll | 79 + final/test/CodeGen/X86/vshift-2.ll | 78 + final/test/CodeGen/X86/vshift-3.ll | 67 + final/test/CodeGen/X86/vshift-4.ll | 85 + final/test/CodeGen/X86/vshift-5.ll | 56 + final/test/CodeGen/X86/vshift_scalar.ll | 11 + final/test/CodeGen/X86/vshift_split.ll | 8 + final/test/CodeGen/X86/vshift_split2.ll | 11 + final/test/CodeGen/X86/vsplit-and.ll | 22 + final/test/CodeGen/X86/weak.ll | 4 + final/test/CodeGen/X86/wide-integer-fold.ll | 12 + final/test/CodeGen/X86/widen_arith-1.ll | 46 + final/test/CodeGen/X86/widen_arith-2.ll | 59 + final/test/CodeGen/X86/widen_arith-3.ll | 52 + final/test/CodeGen/X86/widen_arith-4.ll | 49 + final/test/CodeGen/X86/widen_arith-5.ll | 50 + final/test/CodeGen/X86/widen_arith-6.ll | 49 + final/test/CodeGen/X86/widen_cast-1.ll | 44 + final/test/CodeGen/X86/widen_cast-2.ll | 46 + final/test/CodeGen/X86/widen_cast-3.ll | 17 + final/test/CodeGen/X86/widen_cast-4.ll | 67 + final/test/CodeGen/X86/widen_cast-5.ll | 13 + final/test/CodeGen/X86/widen_cast-6.ll | 10 + final/test/CodeGen/X86/widen_conv-1.ll | 13 + final/test/CodeGen/X86/widen_conv-2.ll | 12 + final/test/CodeGen/X86/widen_conv-3.ll | 11 + final/test/CodeGen/X86/widen_conv-4.ll | 11 + final/test/CodeGen/X86/widen_extract-1.ll | 12 + final/test/CodeGen/X86/widen_load-0.ll | 27 + final/test/CodeGen/X86/widen_load-1.ll | 45 + final/test/CodeGen/X86/widen_load-2.ll | 179 + final/test/CodeGen/X86/widen_shuffle-1.ll | 48 + final/test/CodeGen/X86/win64_params.ll | 11 + final/test/CodeGen/X86/win64_vararg.ll | 53 + final/test/CodeGen/X86/win_chkstk.ll | 46 + final/test/CodeGen/X86/x86-64-and-mask.ll | 49 + final/test/CodeGen/X86/x86-64-arg.ll | 15 + final/test/CodeGen/X86/x86-64-asm.ll | 12 + .../CodeGen/X86/x86-64-dead-stack-adjust.ll | 12 + final/test/CodeGen/X86/x86-64-disp.ll | 14 + final/test/CodeGen/X86/x86-64-extend-shift.ll | 10 + final/test/CodeGen/X86/x86-64-frameaddr.ll | 10 + final/test/CodeGen/X86/x86-64-gv-offset.ll | 14 + final/test/CodeGen/X86/x86-64-jumps.ll | 45 + final/test/CodeGen/X86/x86-64-malloc.ll | 12 + final/test/CodeGen/X86/x86-64-mem.ll | 36 + final/test/CodeGen/X86/x86-64-pic-1.ll | 10 + final/test/CodeGen/X86/x86-64-pic-10.ll | 12 + final/test/CodeGen/X86/x86-64-pic-11.ll | 8 + final/test/CodeGen/X86/x86-64-pic-2.ll | 11 + final/test/CodeGen/X86/x86-64-pic-3.ll | 14 + final/test/CodeGen/X86/x86-64-pic-4.ll | 10 + final/test/CodeGen/X86/x86-64-pic-5.ll | 11 + final/test/CodeGen/X86/x86-64-pic-6.ll | 11 + final/test/CodeGen/X86/x86-64-pic-7.ll | 9 + final/test/CodeGen/X86/x86-64-pic-8.ll | 10 + final/test/CodeGen/X86/x86-64-pic-9.ll | 13 + final/test/CodeGen/X86/x86-64-ret0.ll | 8 + final/test/CodeGen/X86/x86-64-shortint.ll | 12 + final/test/CodeGen/X86/x86-64-sret-return.ll | 63 + final/test/CodeGen/X86/x86-64-tls-1.ll | 6 + final/test/CodeGen/X86/x86-64-varargs.ll | 11 + final/test/CodeGen/X86/x86-frameaddr.ll | 9 + final/test/CodeGen/X86/x86-frameaddr2.ll | 9 + final/test/CodeGen/X86/x86-store-gv-addr.ll | 10 + final/test/CodeGen/X86/x86_64-mul-by-const.ll | 9 + final/test/CodeGen/X86/xmm-r64.ll | 12 + final/test/CodeGen/X86/xor-icmp.ll | 67 + final/test/CodeGen/X86/xor.ll | 145 + final/test/CodeGen/X86/zero-remat.ll | 40 + final/test/CodeGen/X86/zext-extract_subreg.ll | 60 + final/test/CodeGen/X86/zext-inreg-0.ll | 66 + final/test/CodeGen/X86/zext-inreg-1.ll | 18 + final/test/CodeGen/X86/zext-sext.ll | 54 + final/test/CodeGen/X86/zext-shl.ll | 25 + final/test/CodeGen/X86/zext-trunc.ll | 13 + final/test/CodeGen/XCore/2008-11-17-Shl64.ll | 6 + final/test/CodeGen/XCore/2009-01-08-Crash.ll | 12 + .../CodeGen/XCore/2009-01-14-Remat-Crash.ll | 18 + .../CodeGen/XCore/2009-03-27-v2f64-param.ll | 6 + .../test/CodeGen/XCore/2009-07-15-store192.ll | 7 + .../CodeGen/XCore/2010-02-25-LSR-Crash.ll | 26 + .../XCore/2010-04-07-DbgValueOtherTargets.ll | 28 + .../CodeGen/XCore/2011-01-31-DAGCombineBug.ll | 10 + final/test/CodeGen/XCore/addsub64.ll | 59 + final/test/CodeGen/XCore/ashr.ll | 76 + final/test/CodeGen/XCore/basictest.ll | 6 + final/test/CodeGen/XCore/bigstructret.ll | 43 + final/test/CodeGen/XCore/bitrev.ll | 8 + final/test/CodeGen/XCore/constants.ll | 11 + final/test/CodeGen/XCore/cos.ll | 16 + final/test/CodeGen/XCore/dg.exp | 5 + final/test/CodeGen/XCore/events.ll | 24 + final/test/CodeGen/XCore/exp.ll | 16 + final/test/CodeGen/XCore/exp2.ll | 16 + final/test/CodeGen/XCore/fneg.ll | 7 + final/test/CodeGen/XCore/getid.ll | 8 + final/test/CodeGen/XCore/globals.ll | 92 + final/test/CodeGen/XCore/indirectbr.ll | 45 + final/test/CodeGen/XCore/ladd_lsub_combine.ll | 67 + final/test/CodeGen/XCore/load.ll | 39 + final/test/CodeGen/XCore/log.ll | 16 + final/test/CodeGen/XCore/log10.ll | 16 + final/test/CodeGen/XCore/log2.ll | 16 + final/test/CodeGen/XCore/mul64.ll | 52 + final/test/CodeGen/XCore/pow.ll | 16 + final/test/CodeGen/XCore/powi.ll | 16 + final/test/CodeGen/XCore/private.ll | 21 + final/test/CodeGen/XCore/resources.ll | 176 + final/test/CodeGen/XCore/sext.ll | 32 + final/test/CodeGen/XCore/sin.ll | 16 + final/test/CodeGen/XCore/sqrt.ll | 16 + final/test/CodeGen/XCore/store.ll | 35 + final/test/CodeGen/XCore/switch.ll | 24 + final/test/CodeGen/XCore/switch_long.ll | 132 + final/test/CodeGen/XCore/tls.ll | 20 + final/test/CodeGen/XCore/trampoline.ll | 37 + final/test/CodeGen/XCore/trap.ll | 11 + final/test/CodeGen/XCore/unaligned_load.ll | 31 + final/test/CodeGen/XCore/unaligned_store.ll | 18 + .../CodeGen/XCore/unaligned_store_combine.ll | 12 + .../test/DebugInfo/2009-01-15-dbg_declare.ll | 16 + final/test/DebugInfo/2009-01-15-member.ll | 30 + ...2009-10-08-DebugInfo-NullGlobalVariable.ll | 72 + final/test/DebugInfo/2009-10-16-Phi.ll | 13 + .../2009-11-03-InsertExtractValue.ll | 11 + .../2009-11-05-DeadGlobalVariable.ll | 17 + .../2009-11-06-InvalidDerivedType.ll | 13 + .../2009-11-06-NamelessGlobalVariable.ll | 8 + final/test/DebugInfo/2009-11-10-CurrentFn.ll | 20 + .../test/DebugInfo/2009-11-10-ParentScope.ll | 26 + final/test/DebugInfo/2010-01-05-DbgScope.ll | 18 + final/test/DebugInfo/2010-01-19-DbgScope.ll | 28 + final/test/DebugInfo/2010-03-12-llc-crash.ll | 20 + final/test/DebugInfo/2010-03-19-DbgDeclare.ll | 12 + final/test/DebugInfo/2010-03-24-MemberFn.ll | 62 + .../2010-03-30-InvalidDbgInfoCrash.ll | 30 + .../DebugInfo/2010-04-06-NestedFnDbgInfo.ll | 89 + final/test/DebugInfo/2010-04-13-PubType.ll | 47 + final/test/DebugInfo/2010-04-19-FramePtr.ll | 30 + .../test/DebugInfo/2010-04-25-CU-entry_pc.ll | 9 + .../DebugInfo/2010-05-03-DisableFramePtr.ll | 34 + final/test/DebugInfo/2010-05-03-OriginDIE.ll | 86 + final/test/DebugInfo/2010-05-10-MultipleCU.ll | 44 + .../DebugInfo/2010-06-29-InlinedFnLocalVar.ll | 52 + final/test/DebugInfo/2010-07-19-Crash.ll | 24 + final/test/DebugInfo/2010-10-01-crash.ll | 21 + final/test/DebugInfo/dg.exp | 3 + final/test/DebugInfo/inheritance.ll | 151 + final/test/DebugInfo/printdbginfo2.ll | 66 + .../ExecutionEngine/2002-12-16-ArgTest.ll | 37 + .../ExecutionEngine/2003-01-04-ArgumentBug.ll | 13 + .../ExecutionEngine/2003-01-04-LoopTest.ll | 20 + .../ExecutionEngine/2003-01-04-PhiTest.ll | 12 + .../ExecutionEngine/2003-01-09-SARTest.ll | 11 + .../test/ExecutionEngine/2003-01-10-FUCOM.ll | 10 + .../2003-01-15-AlignmentTest.ll | 17 + .../2003-05-06-LivenessClobber.ll | 19 + .../2003-05-07-ArgumentTest.ll | 11 + .../2003-05-11-PHIRegAllocBug.ll | 15 + .../ExecutionEngine/2003-06-04-bzip2-bug.ll | 19 + .../test/ExecutionEngine/2003-06-05-PHIBug.ll | 17 + .../2003-08-15-AllocaAssertion.ll | 11 + .../2003-08-21-EnvironmentTest.ll | 21 + .../2003-08-23-RegisterAllocatePhysReg.ll | 34 + ...8-PHINode-ConstantExpr-CondCode-Failure.ll | 23 + .../ExecutionEngine/2005-12-02-TailCallBug.ll | 22 + .../2007-12-10-APIntLoadStore.ll | 19 + .../2008-06-05-APInt-OverAShr.ll | 59 + .../ExecutionEngine/2010-01-15-UndefValue.ll | 8 + final/test/ExecutionEngine/dg.exp | 3 + final/test/ExecutionEngine/fpbitcast.ll | 20 + final/test/ExecutionEngine/hello.ll | 11 + final/test/ExecutionEngine/hello2.ll | 17 + final/test/ExecutionEngine/simplesttest.ll | 6 + final/test/ExecutionEngine/simpletest.ll | 11 + final/test/ExecutionEngine/stubs.ll | 35 + final/test/ExecutionEngine/test-arith.ll | 34 + final/test/ExecutionEngine/test-branch.ll | 12 + final/test/ExecutionEngine/test-call.ll | 22 + final/test/ExecutionEngine/test-cast.ll | 109 + .../test/ExecutionEngine/test-constantexpr.ll | 12 + final/test/ExecutionEngine/test-fp.ll | 23 + final/test/ExecutionEngine/test-loadstore.ll | 31 + final/test/ExecutionEngine/test-logical.ll | 18 + final/test/ExecutionEngine/test-loop.ll | 14 + final/test/ExecutionEngine/test-malloc.ll | 13 + final/test/ExecutionEngine/test-phi.ll | 34 + final/test/ExecutionEngine/test-ret.ll | 46 + final/test/ExecutionEngine/test-setcond-fp.ll | 24 + .../test/ExecutionEngine/test-setcond-int.ll | 69 + final/test/ExecutionEngine/test-shift.ll | 32 + final/test/Feature/NamedMDNode.ll | 9 + final/test/Feature/NamedMDNode2.ll | 7 + final/test/Feature/README.txt | 6 + final/test/Feature/aliases.ll | 32 + final/test/Feature/alignment.ll | 25 + final/test/Feature/basictest.ll | 31 + final/test/Feature/callingconventions.ll | 50 + final/test/Feature/calltest.ll | 32 + final/test/Feature/casttest.ll | 12 + final/test/Feature/cfgstructures.ll | 53 + final/test/Feature/constexpr.ll | 80 + final/test/Feature/constpointer.ll | 31 + final/test/Feature/dg.exp | 3 + final/test/Feature/escaped_label.ll | 11 + final/test/Feature/float.ll | 6 + final/test/Feature/fold-fpcast.ll | 18 + final/test/Feature/forwardreftest.ll | 29 + final/test/Feature/global_section.ll | 10 + final/test/Feature/globalredefinition.ll | 18 + final/test/Feature/globalredefinition3.ll | 4 + final/test/Feature/globalvars.ll | 18 + final/test/Feature/indirectcall.ll | 49 + final/test/Feature/indirectcall2.ll | 22 + final/test/Feature/inlineasm.ll | 13 + final/test/Feature/instructions.ll | 24 + final/test/Feature/intrinsics.ll | 62 + final/test/Feature/linker_private_linkages.ll | 7 + final/test/Feature/llvm2cpp.exp | 3 + final/test/Feature/load_module.ll | 12 + final/test/Feature/md_on_instruction.ll | 22 + final/test/Feature/memorymarkers.ll | 36 + final/test/Feature/metadata.ll | 17 + final/test/Feature/newcasts.ll | 33 + final/test/Feature/noalias-ret.ll | 6 + final/test/Feature/opaquetypes.ll | 55 + final/test/Feature/packed.ll | 15 + final/test/Feature/packed_struct.ll | 33 + final/test/Feature/paramattrs.ll | 22 + final/test/Feature/ppcld.ll | 26 + final/test/Feature/properties.ll | 7 + final/test/Feature/prototype.ll | 11 + final/test/Feature/recursivetype.ll | 103 + final/test/Feature/simplecalltest.ll | 24 + final/test/Feature/small.ll | 11 + final/test/Feature/smallest.ll | 4 + final/test/Feature/sparcld.ll | 24 + final/test/Feature/terminators.ll | 43 + final/test/Feature/testalloca.ll | 22 + final/test/Feature/testconstants.ll | 29 + final/test/Feature/testlogical.ll | 11 + final/test/Feature/testmemory.ll | 36 + final/test/Feature/testtype.ll | 21 + final/test/Feature/testvarargs.ll | 12 + final/test/Feature/undefined.ll | 17 + final/test/Feature/unreachable.ll | 15 + final/test/Feature/varargs.ll | 29 + final/test/Feature/varargs_new.ll | 38 + .../Feature/vector-cast-constant-exprs.ll | 37 + final/test/Feature/weak_constant.ll | 38 + final/test/Feature/weirdnames.ll | 9 + final/test/Feature/x86ld.ll | 26 + .../test/FrontendAda/Support/element_copy.ads | 8 + final/test/FrontendAda/Support/fat_fields.ads | 6 + .../FrontendAda/Support/global_constant.ads | 4 + final/test/FrontendAda/Support/non_lvalue.ads | 11 + final/test/FrontendAda/Support/real_cst.ads | 4 + .../FrontendAda/Support/unc_constructor.ads | 8 + final/test/FrontendAda/Support/var_offset.ads | 9 + final/test/FrontendAda/Support/var_size.ads | 7 + final/test/FrontendAda/array_constructor.adb | 6 + final/test/FrontendAda/array_range_ref.adb | 7 + final/test/FrontendAda/array_ref.adb | 11 + final/test/FrontendAda/array_size.adb | 10 + final/test/FrontendAda/asm.adb | 6 + final/test/FrontendAda/constant_fold.ads | 4 + final/test/FrontendAda/debug_var_size.ads | 8 + final/test/FrontendAda/dg.exp | 6 + final/test/FrontendAda/element_copy.adb | 8 + final/test/FrontendAda/emit_var.ads | 5 + final/test/FrontendAda/fat_fields.adb | 10 + final/test/FrontendAda/field_order.ads | 7 + final/test/FrontendAda/global_constant.adb | 5 + final/test/FrontendAda/init_size.ads | 12 + .../FrontendAda/negative_field_offset.adb | 16 + final/test/FrontendAda/non_bitfield.ads | 12 + final/test/FrontendAda/non_lvalue.adb | 7 + final/test/FrontendAda/placeholder.adb | 12 + final/test/FrontendAda/real_cst.adb | 8 + final/test/FrontendAda/switch.adb | 12 + final/test/FrontendAda/unc_constructor.adb | 9 + final/test/FrontendAda/var_offset.adb | 7 + final/test/FrontendAda/var_size.adb | 7 + final/test/FrontendAda/vce.adb | 7 + final/test/FrontendAda/vce_lv.adb | 9 + .../FrontendC++/2003-11-02-WeakLinkage.cpp | 13 + .../2003-11-18-PtrMemConstantInitializer.cpp | 14 + .../2003-11-25-ReturningOpaqueByValue.cpp | 12 + .../2003-11-27-MultipleInheritanceThunk.cpp | 28 + .../2003-11-29-DuplicatedCleanupTest.cpp | 41 + .../2003-12-08-ArrayOfPtrToMemberFunc.cpp | 12 + .../2004-01-11-DynamicInitializedConstant.cpp | 6 + .../2004-03-08-ReinterpretCastCopy.cpp | 21 + .../2004-03-09-UnmangledBuiltinMethods.cpp | 8 + .../2004-03-15-CleanupsAndGotos.cpp | 14 + .../2004-06-08-LateTemplateInstantiation.cpp | 19 + .../FrontendC++/2004-09-27-CompilerCrash.cpp | 13 + .../2004-09-27-DidntEmitTemplate.cpp | 23 + .../2004-11-27-EmitsUnusedInlineFunctions.cpp | 7 + .../2004-11-27-ExceptionCleanupAssertion.cpp | 14 + .../2004-11-27-FriendDefaultArgCrash.cpp | 9 + ...04-11-27-InlineAsmFunctionRedefinition.cpp | 26 + .../2005-01-03-StaticInitializers.cpp | 8 + .../FrontendC++/2005-02-11-AnonymousUnion.cpp | 32 + .../FrontendC++/2005-02-13-BadDynamicInit.cpp | 9 + .../FrontendC++/2005-02-14-BitFieldOffset.cpp | 11 + .../2005-02-19-BitfieldStructCrash.cpp | 14 + ...2005-02-19-UnnamedVirtualThunkArgument.cpp | 22 + .../2005-02-20-BrokenReferenceTest.cpp | 11 + .../2005-02-27-PlacementArrayNewCrash.cpp | 8 + .../2005-07-21-VirtualBaseAccess.cpp | 14 + .../FrontendC++/2006-03-01-GimplifyCrash.cpp | 14 + .../2006-03-06-C++RecurseCrash.cpp | 24 + final/test/FrontendC++/2006-09-08-powi.cpp | 7 + .../2006-09-12-OpaqueStructCrash.cpp | 28 + .../2006-09-27-Debug-Protection.cpp | 12 + .../FrontendC++/2006-10-30-ClassBitfield.cpp | 16 + .../FrontendC++/2006-11-06-StackTrace.cpp | 38 + .../FrontendC++/2006-11-20-GlobalSymbols.cpp | 10 + .../2006-11-30-ConstantExprCrash.cpp | 27 + .../test/FrontendC++/2006-11-30-Pubnames.cpp | 22 + .../FrontendC++/2007-01-02-UnboundedArray.cpp | 14 + .../2007-01-06-ELF-Thunk-Sections.cpp | 49 + .../FrontendC++/2007-01-06-PtrMethodInit.cpp | 75 + .../2007-03-27-FunctionVarRename.cpp | 17 + .../2007-04-05-PackedBitFields-1.cpp | 23 + .../2007-04-05-PackedBitFieldsOverlap-2.cpp | 24 + .../2007-04-05-PackedBitFieldsOverlap.cpp | 24 + .../2007-04-05-PackedBitFieldsSmall.cpp | 27 + .../2007-04-05-StructPackedFieldUnpacked.cpp | 25 + .../FrontendC++/2007-04-10-PackedUnion.cpp | 41 + .../2007-04-11-InlineStorageClassC++.cpp | 44 + .../FrontendC++/2007-04-14-FNoBuiltin.cpp | 7 + .../test/FrontendC++/2007-04-31-TryCatch.cpp | 12 + .../FrontendC++/2007-05-03-VectorInit.cpp | 17 + .../2007-05-16-ReverseBitFieldCrash.cpp | 24 + .../FrontendC++/2007-05-23-TryFinally.cpp | 16 + .../FrontendC++/2007-07-04-NestedCatches.cpp | 32 + .../FrontendC++/2007-07-29-RestrictPtrArg.cpp | 6 + .../FrontendC++/2007-07-29-RestrictRefArg.cpp | 6 + .../FrontendC++/2007-08-01-RestrictMethod.cpp | 13 + .../2007-09-10-RecursiveTypeResolution.cpp | 88 + .../FrontendC++/2007-10-01-StructResize.cpp | 14 + .../FrontendC++/2008-01-11-BadWarning.cpp | 6 + final/test/FrontendC++/2008-01-12-VecInit.cpp | 6 + .../FrontendC++/2008-05-07-CrazyOffsetOf.cpp | 8 + .../FrontendC++/2008-10-29-WrongOffset.cpp | 489 + .../2009-02-07-VolatileArrayRefHack.cpp | 7 + .../FrontendC++/2009-02-16-CtorNames-dbg.cpp | 10 + final/test/FrontendC++/2009-03-17-dbg.cpp | 16 + .../FrontendC++/2009-04-21-DtorNames-dbg.cpp | 32 + final/test/FrontendC++/2009-04-23-bool2.cpp | 15 + .../2009-05-04-PureConstNounwind.cpp | 8 + .../FrontendC++/2009-06-16-DebugInfoCrash.cpp | 10 + .../2009-06-20-DarwinPPCLayout.cpp | 32 + .../FrontendC++/2009-06-30-ByrefBlock.cpp | 11 + .../FrontendC++/2009-07-15-LineNumbers.cpp | 27 + .../2009-07-16-PrivateCopyConstructor.cpp | 15 + final/test/FrontendC++/2009-07-16-Using.cpp | 8 + .../FrontendC++/2009-08-05-ZeroInitWidth.cpp | 12 + .../FrontendC++/2009-08-11-VectorRetTy.cpp | 13 + .../FrontendC++/2009-09-04-modify-crash.cpp | 7 + .../FrontendC++/2009-09-09-packed-layout.cpp | 18 + final/test/FrontendC++/2009-10-27-crash.cpp | 43 + .../FrontendC++/2009-12-23-MissingSext.cpp | 16 + .../2010-02-17-DbgArtificialArg.cpp | 16 + .../2010-03-22-empty-baseclass.cpp | 134 + .../2010-04-30-OptimizedMethod-Dbg.cpp | 18 + .../FrontendC++/2010-05-10-Var-DbgInfo.cpp | 43 + .../2010-05-11-alwaysinlineinstantiation.cpp | 31 + .../2010-05-12-PtrToMember-Dbg.cpp | 17 + .../FrontendC++/2010-06-21-LocalVarDbg.cpp | 13 + .../FrontendC++/2010-06-22-BitfieldInit.cpp | 20 + .../FrontendC++/2010-06-22-ZeroBitfield.cpp | 5 + final/test/FrontendC++/2010-07-19-nowarn.cpp | 21 + final/test/FrontendC++/2010-07-23-DeclLoc.cpp | 86 + .../test/FrontendC++/2010-08-31-ByValArg.cpp | 53 + final/test/FrontendC++/alignstack.cpp | 23 + final/test/FrontendC++/dg.exp | 5 + final/test/FrontendC++/integration-O2.cpp | 19 + final/test/FrontendC++/m64-ptr.cpp | 19 + final/test/FrontendC++/member-alignment.cpp | 20 + .../test/FrontendC++/ptr-to-method-devirt.cpp | 14 + final/test/FrontendC++/thunk-linkonce-odr.cpp | 33 + final/test/FrontendC++/varargs.cpp | 19 + final/test/FrontendC++/weak-external.cpp | 17 + .../x86-64-abi-sret-vs-2word-struct-param.cpp | 27 + .../2002-01-23-LoadQISIReloadFailure.c | 11 + .../FrontendC/2002-01-24-ComplexSpaceInType.c | 11 + .../FrontendC/2002-01-24-HandleCallInsnSEGV.c | 9 + .../FrontendC/2002-02-13-ConditionalInCall.c | 11 + .../test/FrontendC/2002-02-13-ReloadProblem.c | 18 + .../2002-02-13-TypeVarNameCollision.c | 16 + .../test/FrontendC/2002-02-13-UnnamedLocal.c | 21 + .../FrontendC/2002-02-14-EntryNodePreds.c | 37 + .../test/FrontendC/2002-02-16-RenamingTest.c | 18 + .../FrontendC/2002-02-17-ArgumentAddress.c | 39 + .../test/FrontendC/2002-02-18-64bitConstant.c | 10 + final/test/FrontendC/2002-02-18-StaticData.c | 13 + .../FrontendC/2002-03-11-LargeCharInString.c | 10 + .../2002-03-12-ArrayInitialization.c | 19 + .../FrontendC/2002-03-12-StructInitialize.c | 14 + .../FrontendC/2002-03-12-StructInitializer.c | 18 + .../test/FrontendC/2002-03-14-BrokenPHINode.c | 19 + final/test/FrontendC/2002-03-14-BrokenSSA.c | 17 + .../FrontendC/2002-03-14-QuotesInStrConst.c | 10 + final/test/FrontendC/2002-04-07-SwitchStmt.c | 22 + final/test/FrontendC/2002-04-08-LocalArray.c | 14 + .../test/FrontendC/2002-04-09-StructRetVal.c | 12 + .../FrontendC/2002-04-10-StructParameters.c | 25 + .../test/FrontendC/2002-05-23-StaticValues.c | 15 + .../FrontendC/2002-05-23-TypeNameCollision.c | 19 + final/test/FrontendC/2002-05-24-Alloca.c | 11 + .../2002-06-25-FWriteInterfaceFailure.c | 7 + .../test/FrontendC/2002-07-14-MiscListTests.c | 71 + final/test/FrontendC/2002-07-14-MiscTests.c | 57 + final/test/FrontendC/2002-07-14-MiscTests2.c | 13 + final/test/FrontendC/2002-07-14-MiscTests3.c | 187 + .../FrontendC/2002-07-16-HardStringInit.c | 8 + .../FrontendC/2002-07-17-StringConstant.c | 4 + final/test/FrontendC/2002-07-29-Casts.c | 86 + .../FrontendC/2002-07-30-SubregSetAssertion.c | 12 + final/test/FrontendC/2002-07-30-UnionTest.c | 22 + .../FrontendC/2002-07-30-VarArgsCallFailure.c | 8 + final/test/FrontendC/2002-07-31-BadAssert.c | 16 + .../test/FrontendC/2002-07-31-SubregFailure.c | 14 + final/test/FrontendC/2002-08-02-UnionTest.c | 19 + .../FrontendC/2002-08-19-RecursiveLocals.c | 18 + .../test/FrontendC/2002-09-08-PointerShifts.c | 6 + .../test/FrontendC/2002-09-18-UnionProblem.c | 26 + final/test/FrontendC/2002-09-19-StarInLabel.c | 9 + .../FrontendC/2002-10-12-TooManyArguments.c | 8 + .../FrontendC/2002-12-15-GlobalBoolTest.c | 5 + .../FrontendC/2002-12-15-GlobalConstantTest.c | 8 + .../FrontendC/2002-12-15-GlobalRedefinition.c | 5 + .../FrontendC/2002-12-15-StructParameters.c | 18 + final/test/FrontendC/2003-01-30-UnionInit.c | 8 + .../test/FrontendC/2003-03-03-DeferredType.c | 12 + final/test/FrontendC/2003-06-22-UnionCrash.c | 13 + .../2003-06-23-GCC-fold-infinite-recursion.c | 6 + final/test/FrontendC/2003-06-26-CFECrash.c | 19 + .../2003-06-29-MultipleFunctionDefinition.c | 8 + .../2003-07-22-ArrayAccessTypeSafety.c | 7 + .../2003-08-06-BuiltinSetjmpLongjmp.c | 14 + .../2003-08-17-DeadCodeShortCircuit.c | 7 + final/test/FrontendC/2003-08-18-SigSetJmp.c | 10 + .../test/FrontendC/2003-08-18-StructAsValue.c | 11 + .../FrontendC/2003-08-20-BadBitfieldRef.c | 8 + .../FrontendC/2003-08-20-PrototypeMismatch.c | 15 + final/test/FrontendC/2003-08-20-vfork-bug.c | 6 + .../2003-08-21-BinOp-Type-Mismatch.c | 10 + final/test/FrontendC/2003-08-21-StmtExpr.c | 12 + final/test/FrontendC/2003-08-21-WideString.c | 7 + .../FrontendC/2003-08-23-LocalUnionTest.c | 11 + .../FrontendC/2003-08-29-BitFieldStruct.c | 13 + .../test/FrontendC/2003-08-29-HugeCharConst.c | 5 + .../FrontendC/2003-08-29-StructLayoutBug.c | 10 + .../2003-08-30-AggregateInitializer.c | 16 + .../2003-08-30-LargeIntegerBitfieldMember.c | 9 + .../test/FrontendC/2003-09-18-BitfieldTests.c | 30 + .../test/FrontendC/2003-09-30-StructLayout.c | 18 + .../FrontendC/2003-10-02-UnionLValueError.c | 13 + .../FrontendC/2003-10-06-NegateExprType.c | 8 + .../2003-10-09-UnionInitializerBug.c | 17 + final/test/FrontendC/2003-10-28-ident.c | 4 + final/test/FrontendC/2003-10-29-AsmRename.c | 22 + .../2003-11-01-C99-CompoundLiteral.c | 8 + .../FrontendC/2003-11-01-EmptyStructCrash.c | 6 + .../FrontendC/2003-11-01-GlobalUnionInit.c | 7 + .../FrontendC/2003-11-03-AddrArrayElement.c | 11 + final/test/FrontendC/2003-11-04-EmptyStruct.c | 6 + final/test/FrontendC/2003-11-04-OutOfMemory.c | 9 + .../2003-11-08-PointerSubNotGetelementptr.c | 9 + final/test/FrontendC/2003-11-12-VoidString.c | 4 + final/test/FrontendC/2003-11-13-TypeSafety.c | 5 + .../FrontendC/2003-11-16-StaticArrayInit.c | 8 + .../FrontendC/2003-11-18-CondExprLValue.c | 9 + .../FrontendC/2003-11-19-AddressOfRegister.c | 12 + .../test/FrontendC/2003-11-19-BitFieldArray.c | 12 + final/test/FrontendC/2003-11-20-Bitfields.c | 12 + .../FrontendC/2003-11-20-ComplexDivision.c | 7 + .../test/FrontendC/2003-11-20-UnionBitfield.c | 12 + .../test/FrontendC/2003-11-26-PointerShift.c | 6 + .../FrontendC/2003-11-27-ConstructorCast.c | 14 + .../2003-11-27-UnionCtorInitialization.c | 16 + .../2003-12-14-ExternInlineSupport.c | 3 + .../FrontendC/2004-01-01-UnknownInitSize.c | 14 + .../2004-01-08-ExternInlineRedefine.c | 14 + .../FrontendC/2004-02-12-LargeAggregateCopy.c | 8 + .../2004-02-13-BuiltinFrameReturnAddress.c | 8 + .../test/FrontendC/2004-02-13-IllegalVararg.c | 13 + final/test/FrontendC/2004-02-13-Memset.c | 9 + .../FrontendC/2004-02-14-ZeroInitializer.c | 4 + final/test/FrontendC/2004-02-20-Builtins.c | 8 + .../FrontendC/2004-03-07-ComplexDivEquals.c | 6 + .../FrontendC/2004-03-07-ExternalConstant.c | 7 + .../2004-03-09-LargeArrayInitializers.c | 32 + .../FrontendC/2004-03-15-SimpleIndirectGoto.c | 23 + .../FrontendC/2004-03-16-AsmRegisterCrash.c | 10 + final/test/FrontendC/2004-05-07-VarArrays.c | 5 + .../FrontendC/2004-05-21-IncompleteEnum.c | 5 + .../FrontendC/2004-06-08-OpaqueStructArg.c | 7 + .../FrontendC/2004-06-17-UnorderedBuiltins.c | 24 + .../FrontendC/2004-06-17-UnorderedCompares.c | 21 + ...04-06-18-VariableLengthArrayOfStructures.c | 10 + .../test/FrontendC/2004-07-06-FunctionCast.c | 10 + .../FrontendC/2004-08-06-LargeStructTest.c | 19 + .../2004-11-25-UnnamedBitfieldPadding.c | 8 + .../2004-11-27-InvalidConstantExpr.c | 10 + .../2004-11-27-StaticFunctionRedeclare.c | 15 + .../2004-11-27-VariableSizeInStructure.c | 11 + .../test/FrontendC/2005-01-02-ConstantInits.c | 24 + .../FrontendC/2005-01-02-PointerDifference.c | 3 + .../FrontendC/2005-01-02-VAArgError-ICE.c | 10 + .../FrontendC/2005-02-20-AggregateSAVEEXPR.c | 19 + .../FrontendC/2005-02-27-MarkGlobalConstant.c | 10 + .../test/FrontendC/2005-03-05-OffsetOfHack.c | 12 + .../2005-03-06-OffsetOfStructCrash.c | 14 + final/test/FrontendC/2005-03-11-Prefetch.c | 6 + final/test/FrontendC/2005-04-09-ComplexOps.c | 9 + .../test/FrontendC/2005-05-06-CountBuiltins.c | 17 + .../FrontendC/2005-05-10-GlobalUnionInit.c | 6 + .../2005-06-15-ExpandGotoInternalProblem.c | 14 + final/test/FrontendC/2005-07-20-SqrtNoErrno.c | 11 + .../FrontendC/2005-07-26-UnionInitCrash.c | 3 + .../2005-07-28-IncorrectWeakGlobal.c | 5 + .../FrontendC/2005-09-20-ComplexConstants.c | 4 + .../test/FrontendC/2005-09-24-AsmUserPrefix.c | 8 + .../test/FrontendC/2005-09-24-BitFieldCrash.c | 33 + .../2005-10-18-VariableSizedElementCrash.c | 9 + .../test/FrontendC/2005-12-04-AttributeUsed.c | 8 + .../2005-12-04-DeclarationLineNumbers.c | 23 + final/test/FrontendC/2006-01-13-Includes.c | 8 + final/test/FrontendC/2006-01-13-StackSave.c | 11 + .../2006-01-16-BitCountIntrinsicsUnsigned.c | 9 + .../test/FrontendC/2006-01-23-FileScopeAsm.c | 8 + .../FrontendC/2006-03-03-MissingInitializer.c | 11 + final/test/FrontendC/2006-03-16-VectorCtor.c | 10 + final/test/FrontendC/2006-03-17-KnRMismatch.c | 8 + .../2006-05-01-AppleAlignmentPragma.c | 12 + .../FrontendC/2006-05-19-SingleEltReturn.c | 23 + final/test/FrontendC/2006-07-31-PR854.c | 11 + .../FrontendC/2006-09-11-BitfieldRefCrash.c | 12 + .../FrontendC/2006-09-18-fwrite-cast-crash.c | 15 + .../2006-09-21-IncompleteElementType.c | 3 + .../test/FrontendC/2006-09-25-DebugFilename.c | 6 + .../test/FrontendC/2006-09-25-DebugFilename.h | 6 + final/test/FrontendC/2006-09-28-SimpleAsm.c | 10 + final/test/FrontendC/2006-10-30-ArrayCrash.c | 17 + .../test/FrontendC/2006-12-14-ordered_expr.c | 6 + final/test/FrontendC/2007-01-06-KNR-Proto.c | 10 + final/test/FrontendC/2007-01-20-VectorICE.c | 11 + .../FrontendC/2007-01-24-InlineAsmCModifier.c | 10 + .../test/FrontendC/2007-02-04-AddrLValue-2.c | 13 + final/test/FrontendC/2007-02-04-AddrLValue.c | 23 + final/test/FrontendC/2007-02-04-EmptyStruct.c | 9 + .../FrontendC/2007-02-04-WITH_SIZE_EXPR.c | 21 + final/test/FrontendC/2007-02-05-nested.c | 54 + final/test/FrontendC/2007-02-07-AddrLabel.c | 10 + .../2007-02-16-VariableSizeStructArg.c | 7 + final/test/FrontendC/2007-02-16-VoidPtrDiff.c | 5 + .../FrontendC/2007-02-16-WritableStrings.c | 7 + final/test/FrontendC/2007-02-25-C-DotDotDot.c | 12 + .../FrontendC/2007-03-01-VarSizeArrayIdx.c | 7 + final/test/FrontendC/2007-03-05-DataLayout.c | 53 + .../FrontendC/2007-03-06-VarSizeInStruct1.c | 8 + .../FrontendC/2007-03-06-VarSizeInStruct2.c | 8 + .../2007-03-26-BitfieldAfterZeroWidth.c | 6 + .../FrontendC/2007-03-26-ZeroWidthBitfield.c | 2 + .../FrontendC/2007-03-27-ArrayCompatible.c | 10 + .../FrontendC/2007-03-27-VarLengthArray.c | 7 + .../FrontendC/2007-04-05-PackedBitFields-2.c | 16 + .../FrontendC/2007-04-05-PackedBitFields.c | 16 + .../test/FrontendC/2007-04-05-PackedStruct.c | 18 + .../2007-04-05-PadBeforeZeroLengthField.c | 9 + .../FrontendC/2007-04-05-UnPackedStruct.c | 16 + .../FrontendC/2007-04-11-InlineAsmStruct.c | 9 + .../FrontendC/2007-04-11-InlineAsmUnion.c | 7 + .../2007-04-11-InlineStorageClassC89.c | 46 + .../2007-04-11-InlineStorageClassC99.c | 46 + final/test/FrontendC/2007-04-11-PR1321.c | 12 + .../FrontendC/2007-04-13-InlineAsmStruct2.c | 9 + .../FrontendC/2007-04-13-InlineAsmUnion2.c | 7 + final/test/FrontendC/2007-04-14-FNoBuiltin.c | 7 + .../FrontendC/2007-04-17-ZeroSizeBitFields.c | 4 + .../FrontendC/2007-04-24-VolatileStructCopy.c | 10 + .../test/FrontendC/2007-04-24-bit-not-expr.c | 7 + final/test/FrontendC/2007-04-24-str-const.c | 17 + .../FrontendC/2007-05-07-NestedStructReturn.c | 13 + .../FrontendC/2007-05-07-PaddingElements.c | 12 + final/test/FrontendC/2007-05-08-PCH.c | 7 + final/test/FrontendC/2007-05-11-str-const.c | 5 + .../FrontendC/2007-05-15-PaddingElement.c | 23 + final/test/FrontendC/2007-05-16-EmptyStruct.c | 5 + final/test/FrontendC/2007-05-29-UnionCopy.c | 18 + .../FrontendC/2007-06-05-NoInlineAttribute.c | 13 + .../FrontendC/2007-06-15-AnnotateAttribute.c | 24 + .../FrontendC/2007-06-18-SextAttrAggregate.c | 11 + .../FrontendC/2007-07-29-RestrictPtrArg.c | 6 + .../FrontendC/2007-08-01-LoadStoreAlign.c | 17 + final/test/FrontendC/2007-08-21-ComplexCst.c | 3 + final/test/FrontendC/2007-08-22-CTTZ.c | 6 + final/test/FrontendC/2007-09-05-ConstCtor.c | 14 + final/test/FrontendC/2007-09-12-PragmaPack.c | 30 + .../test/FrontendC/2007-09-14-NegatePointer.c | 7 + final/test/FrontendC/2007-09-17-WeakRef.c | 10 + .../FrontendC/2007-09-20-GcrootAttribute.c | 29 + final/test/FrontendC/2007-09-26-Alignment.c | 7 + .../FrontendC/2007-09-27-ComplexIntCompare.c | 17 + .../FrontendC/2007-09-28-PackedUnionMember.c | 38 + .../test/FrontendC/2007-10-01-BuildArrayRef.c | 20 + .../test/FrontendC/2007-10-02-VolatileArray.c | 7 + final/test/FrontendC/2007-10-15-VoidPtr.c | 4 + final/test/FrontendC/2007-10-30-Volatile.c | 6 + .../test/FrontendC/2007-11-07-AlignedMemcpy.c | 4 + .../FrontendC/2007-11-07-CopyAggregateAlign.c | 3 + .../FrontendC/2007-11-07-ZeroAggregateAlign.c | 3 + final/test/FrontendC/2007-11-27-SExtZExt.c | 12 + .../FrontendC/2007-11-28-GlobalInitializer.c | 8 + final/test/FrontendC/2007-12-16-AsmNoUnwind.c | 3 + final/test/FrontendC/2007-12-VarArrayDebug.c | 18 + .../test/FrontendC/2008-01-04-WideBitfield.c | 13 + .../FrontendC/2008-01-07-UnusualIntSize.c | 11 + .../FrontendC/2008-01-11-ChainConsistency.c | 3 + .../FrontendC/2008-01-21-PackedBitFields.c | 7 + .../FrontendC/2008-01-21-PackedStructField.c | 18 + .../2008-01-24-StructAlignAndBitFields.c | 4 + .../test/FrontendC/2008-01-25-ByValReadNone.c | 15 + .../FrontendC/2008-01-25-ZeroSizedAggregate.c | 39 + final/test/FrontendC/2008-01-28-PragmaMark.c | 6 + final/test/FrontendC/2008-01-28-UnionSize.c | 24 + .../FrontendC/2008-02-11-AnnotateBuiltin.c | 7 + .../test/FrontendC/2008-03-03-CtorAttrType.c | 6 + final/test/FrontendC/2008-03-05-syncPtr.c | 27 + .../2008-03-24-BitField-And-Alloca.c | 89 + .../FrontendC/2008-03-26-PackedBitFields.c | 7 + .../test/FrontendC/2008-04-08-NoExceptions.c | 7 + final/test/FrontendC/2008-05-06-CFECrash.c | 4 + .../FrontendC/2008-05-12-TempUsedBeforeDef.c | 10 + .../test/FrontendC/2008-05-19-AlwaysInline.c | 12 + .../FrontendC/2008-07-08-FAbsAttributes.c | 4 + final/test/FrontendC/2008-07-29-EHLabel.ll | 282 + .../test/FrontendC/2008-08-07-AlignPadding1.c | 29 + .../test/FrontendC/2008-08-07-AlignPadding2.c | 18 + final/test/FrontendC/2008-08-07-GEPIntToPtr.c | 14 + final/test/FrontendC/2008-09-03-WeakAlias.c | 9 + .../test/FrontendC/2008-10-13-FrontendCrash.c | 9 + .../test/FrontendC/2008-10-30-ZeroPlacement.c | 9 + final/test/FrontendC/2008-11-02-WeakAlias.c | 5 + .../FrontendC/2008-11-08-InstCombineSelect.c | 17 + .../2008-11-11-AnnotateStructFieldAttribute.c | 18 + .../FrontendC/2008-12-23-AsmIntPointerTie.c | 9 + .../test/FrontendC/2009-01-05-BlockInlining.c | 28 + final/test/FrontendC/2009-01-20-k8.c | 4 + .../FrontendC/2009-01-21-InvalidIterator.c | 74 + .../2009-02-13-zerosize-union-field-ppc.c | 14 + .../2009-02-13-zerosize-union-field.c | 14 + .../test/FrontendC/2009-02-17-BitField-dbg.c | 14 + .../test/FrontendC/2009-03-01-MallocNoAlias.c | 3 + .../FrontendC/2009-03-08-ZeroEltStructCrash.c | 14 + .../FrontendC/2009-03-09-WeakDeclarations-1.c | 22 + final/test/FrontendC/2009-03-13-dbg.c | 5 + final/test/FrontendC/2009-04-22-UnknownSize.c | 4 + .../FrontendC/2009-04-28-UnionArrayCrash.c | 11 + final/test/FrontendC/2009-05-04-EnumInreg.c | 18 + .../test/FrontendC/2009-05-17-AlwaysInline.c | 17 + .../test/FrontendC/2009-06-14-HighlyAligned.c | 8 + .../2009-06-18-StaticInitTailPadPack.c | 26 + final/test/FrontendC/2009-07-14-VoidPtr.c | 6 + .../FrontendC/2009-07-15-pad-wchar_t-array.c | 7 + .../test/FrontendC/2009-07-17-VoidParameter.c | 4 + .../test/FrontendC/2009-07-22-StructLayout.c | 34 + .../2009-08-11-AsmBlocksComplexJumpTarget.c | 10 + final/test/FrontendC/2009-09-24-SqrtErrno.c | 12 + .../FrontendC/2009-12-07-BitFieldAlignment.c | 15 + final/test/FrontendC/2010-01-05-LinkageName.c | 15 + final/test/FrontendC/2010-01-13-MemBarrier.c | 11 + .../FrontendC/2010-01-14-FnType-DebugInfo.c | 4 + .../FrontendC/2010-01-14-StaticVariable.c | 12 + .../test/FrontendC/2010-01-18-Inlined-Debug.c | 12 + final/test/FrontendC/2010-02-10-PointerName.c | 7 + .../test/FrontendC/2010-02-15-DbgStaticVar.c | 13 + final/test/FrontendC/2010-02-16-DbgVarScope.c | 30 + .../FrontendC/2010-02-18-Dbg-VectorType.c | 9 + final/test/FrontendC/2010-03-10-arm-asmreg.c | 15 + final/test/FrontendC/2010-03-5-LexicalScope.c | 10 + .../FrontendC/2010-05-14-Optimized-VarType.c | 23 + final/test/FrontendC/2010-05-18-asmsched.c | 17 + final/test/FrontendC/2010-05-18-palignr.c | 24 + .../test/FrontendC/2010-05-26-AsmSideEffect.c | 12 + final/test/FrontendC/2010-05-31-palignr.c | 24 + final/test/FrontendC/2010-06-11-SaveExpr.c | 8 + final/test/FrontendC/2010-06-17-asmcrash.c | 16 + final/test/FrontendC/2010-06-28-DbgLocalVar.c | 14 + final/test/FrontendC/2010-06-28-nowarn.c | 21 + .../FrontendC/2010-07-08-DeclDebugLineNo.c | 10 + .../2010-07-14-overconservative-align.c | 14 + final/test/FrontendC/2010-07-14-ref-off-end.c | 27 + .../FrontendC/2010-07-27-MinNoFoldConst.c | 18 + .../test/FrontendC/2010-08-12-asm-aggr-arg.c | 16 + final/test/FrontendC/2010-11-16-asmblock.c | 16 + .../test/FrontendC/2010-12-01-CommonGlobal.c | 7 + final/test/FrontendC/2011-02-21-DATA-common.c | 5 + final/test/FrontendC/Atomics-no64bit.c | 190 + final/test/FrontendC/Atomics.c | 236 + final/test/FrontendC/BasicInstrs.c | 26 + final/test/FrontendC/alignstack.c | 23 + final/test/FrontendC/always-inline.c | 12 + final/test/FrontendC/arrayderef.c | 17 + final/test/FrontendC/asm-reg-var-local.c | 32 + final/test/FrontendC/attribute_constructor.c | 6 + final/test/FrontendC/block-copy.c | 20 + final/test/FrontendC/crash-invalid-array.c | 17 + final/test/FrontendC/cstring-align.c | 11 + final/test/FrontendC/dg.exp | 5 + final/test/FrontendC/exact-div-expr.c | 6 + final/test/FrontendC/extern-weak.c | 12 + final/test/FrontendC/fp-logical.c | 15 + final/test/FrontendC/func-aligned.c | 7 + final/test/FrontendC/funccall.c | 17 + final/test/FrontendC/hidden-visibility.c | 3 + final/test/FrontendC/implicit-arg.c | 10 + final/test/FrontendC/inline-asm-function.c | 6 + final/test/FrontendC/inline-asm-mrv.c | 12 + final/test/FrontendC/libcalls-d.c | 14 + final/test/FrontendC/libcalls-ld.c | 17 + final/test/FrontendC/libcalls.c | 14 + final/test/FrontendC/misaligned-param.c | 15 + final/test/FrontendC/nested-functions.c | 18 + final/test/FrontendC/pr2394.c | 6 + final/test/FrontendC/pr3518.c | 24 + final/test/FrontendC/pr4349.c | 38 + final/test/FrontendC/pr5406.c | 20 + final/test/FrontendC/ptr-rotate.c | 7 + final/test/FrontendC/redef-ext-inline.c | 6 + final/test/FrontendC/sret.c | 15 + final/test/FrontendC/sret2.c | 9 + final/test/FrontendC/unaligned-memcpy.c | 5 + final/test/FrontendC/union-align.c | 17 + final/test/FrontendC/vla-1.c | 9 + final/test/FrontendC/vla-2.c | 10 + final/test/FrontendC/wchar-const.c | 9 + final/test/FrontendC/weak_constant.c | 12 + .../2008-11-03-OptionOverride.f90 | 4 + .../2009-02-09-FloorDivExpr.f90 | 32 + final/test/FrontendFortran/cpow.f90 | 18 + final/test/FrontendFortran/dg.exp | 6 + .../2007-10-03-MetadataPointers.mm | 7 + .../2010-08-02-NonPODObjectValue.mm | 27 + .../FrontendObjC++/2010-08-04-Template.mm | 10 + .../FrontendObjC++/2010-08-06-X.Y-syntax.mm | 16 + final/test/FrontendObjC++/dg.exp | 5 + final/test/FrontendObjC/2007-04-03-ObjcEH.m | 29 + final/test/FrontendObjC/2007-05-02-Strong.m | 23 + final/test/FrontendObjC/2007-09-25-EH.m | 27 + .../FrontendObjC/2007-10-17-SJLJExceptions.m | 24 + .../FrontendObjC/2007-10-18-ProDescriptor.m | 19 + .../FrontendObjC/2007-10-23-GC-WriteBarrier.m | 9 + final/test/FrontendObjC/2008-10-3-EhValue.m | 50 + final/test/FrontendObjC/2008-11-12-Metadata.m | 14 + .../FrontendObjC/2008-11-24-ConstCFStrings.m | 11 + final/test/FrontendObjC/2008-11-25-Blocks.m | 17 + .../FrontendObjC/2009-01-26-WriteBarrier-2.m | 14 + .../FrontendObjC/2009-02-05-VolatileProp.m | 11 + .../test/FrontendObjC/2009-04-14-AsmSection.m | 9 + .../2009-04-27-bitfield-vs-ivar.m | 44 + .../FrontendObjC/2009-04-28-bitfield-vs-vbc.m | 127 + final/test/FrontendObjC/2009-08-05-utf16.m | 5 + .../test/FrontendObjC/2009-08-17-DebugInfo.m | 28 + final/test/FrontendObjC/2009-11-30-Objc-ID.m | 14 + .../FrontendObjC/2010-02-01-utf16-with-null.m | 5 + .../2010-02-11-fwritable-stringsBug.m | 17 + .../FrontendObjC/2010-02-23-DbgInheritance.m | 9 + .../test/FrontendObjC/2010-03-17-StructRef.m | 43 + .../2010-06-04-UnnamedCFString-dbg.m | 6 + .../2011-03-02-ConstCFStringLiteralAlign.m | 11 + final/test/FrontendObjC/dg.exp | 5 + final/test/Integer/2007-01-19-TruncSext.ll | 29 + final/test/Integer/BitArith.ll | 25 + final/test/Integer/BitBit.ll | 24 + final/test/Integer/BitCast.ll | 26 + final/test/Integer/BitIcmp.ll | 43 + final/test/Integer/BitMem.ll | 29 + final/test/Integer/BitMisc.ll | 24 + final/test/Integer/BitPacked.ll | 21 + final/test/Integer/alignment_bt.ll | 21 + final/test/Integer/basictest_bt.ll | 31 + final/test/Integer/cfgstructures_bt.ll | 56 + final/test/Integer/constexpr_bt.ll | 84 + final/test/Integer/constpointer_bt.ll | 32 + final/test/Integer/dg.exp | 3 + final/test/Integer/fold-fpcast_bt.ll | 33 + final/test/Integer/forwardreftest_bt.ll | 33 + final/test/Integer/globalredefinition_bt.ll | 18 + final/test/Integer/globalvars_bt.ll | 26 + final/test/Integer/indirectcall2_bt.ll | 24 + final/test/Integer/indirectcall_bt.ll | 52 + final/test/Integer/instructions_bt.ll | 26 + final/test/Integer/newcasts_bt.ll | 28 + final/test/Integer/opaquetypes_bt.ll | 58 + final/test/Integer/packed_bt.ll | 16 + final/test/Integer/packed_struct_bt.ll | 33 + final/test/Integer/paramattrs_bt.ll | 19 + final/test/Integer/properties_bt.ll | 9 + final/test/Integer/prototype_bt.ll | 13 + final/test/Integer/recursivetype_bt.ll | 108 + final/test/Integer/simplecalltest_bt.ll | 28 + final/test/Integer/small_bt.ll | 13 + final/test/Integer/testalloca_bt.ll | 28 + final/test/Integer/testarith_bt.ll | 21 + final/test/Integer/testconstants_bt.ll | 32 + final/test/Integer/testicmp_bt.ll | 23 + final/test/Integer/testlogical_bt.ll | 13 + final/test/Integer/testlogical_new_bt.ll | 15 + final/test/Integer/testmemory_bt.ll | 45 + final/test/Integer/testswitch_bt.ll | 24 + final/test/Integer/testvarargs_bt.ll | 14 + final/test/Integer/undefined_bt.ll | 18 + final/test/Integer/unreachable_bt.ll | 16 + final/test/Integer/varargs_bt.ll | 23 + final/test/Integer/varargs_new_bt.ll | 32 + final/test/LLVMC/Alias.td | 24 + final/test/LLVMC/AppendCmdHook.td | 29 + final/test/LLVMC/C++/dash-x.cpp | 10 + final/test/LLVMC/C++/dg.exp | 5 + final/test/LLVMC/C++/filelist.cpp | 3 + final/test/LLVMC/C++/hello.cpp | 9 + final/test/LLVMC/C++/just-compile.cpp | 10 + final/test/LLVMC/C++/together.cpp | 10 + final/test/LLVMC/C++/unknown_suffix.unk | 9 + final/test/LLVMC/C/dg.exp | 5 + final/test/LLVMC/C/emit-llvm-opt.c | 9 + final/test/LLVMC/C/emit-llvm.c | 8 + final/test/LLVMC/C/hello.c | 13 + final/test/LLVMC/C/include.c | 10 + final/test/LLVMC/C/opt-test.c | 13 + final/test/LLVMC/C/sink.c | 13 + final/test/LLVMC/C/wall.c | 13 + final/test/LLVMC/EmptyCompilationGraph.td | 8 + final/test/LLVMC/EnvParentheses.td | 18 + final/test/LLVMC/ForwardAs.td | 21 + final/test/LLVMC/ForwardTransformedValue.td | 27 + final/test/LLVMC/ForwardValue.td | 24 + final/test/LLVMC/HookWithArguments.td | 20 + final/test/LLVMC/HookWithInFile.td | 16 + final/test/LLVMC/Init.td | 25 + final/test/LLVMC/LanguageMap.td | 29 + final/test/LLVMC/MultiValuedOption.td | 24 + final/test/LLVMC/MultipleCompilationGraphs.td | 10 + final/test/LLVMC/MultipleOutputLanguages.td | 27 + final/test/LLVMC/NoActions.td | 16 + final/test/LLVMC/NoCompilationGraph.td | 6 + final/test/LLVMC/ObjC++/dg.exp | 5 + final/test/LLVMC/ObjC++/hello.mm | 8 + final/test/LLVMC/ObjC/dg.exp | 5 + final/test/LLVMC/ObjC/hello.m | 12 + final/test/LLVMC/OneOrMore.td | 25 + final/test/LLVMC/OptionPreprocessor.td | 67 + final/test/LLVMC/OutputSuffixHook.td | 24 + final/test/LLVMC/TestWarnings.td | 8 + final/test/LLVMC/dg.exp | 3 + final/test/LLVMC/test_data/false.c | 10 + final/test/LLVMC/test_data/false.cpp | 16 + final/test/LLVMC/test_data/false2.cpp | 5 + final/test/LLVMC/test_data/together.c | 5 + final/test/Linker/2002-07-17-GlobalFail.ll | 8 + final/test/Linker/2002-07-17-LinkTest2.ll | 10 + final/test/Linker/2002-08-20-ConstantExpr.ll | 9 + final/test/Linker/2003-01-30-LinkerRename.ll | 9 + .../Linker/2003-01-30-LinkerTypeRename.ll | 9 + final/test/Linker/2003-04-21-Linkage.ll | 14 + final/test/Linker/2003-04-23-LinkOnceLost.ll | 10 + .../Linker/2003-04-26-NullPtrLinkProblem.ll | 17 + final/test/Linker/2003-05-15-TypeProblem.ll | 10 + final/test/Linker/2003-05-31-LinkerRename.ll | 17 + .../Linker/2003-06-02-TypeResolveProblem.ll | 7 + .../Linker/2003-06-02-TypeResolveProblem2.ll | 7 + .../Linker/2003-08-20-OpaqueTypeResolve.ll | 8 + .../Linker/2003-08-23-GlobalVarLinking.ll | 10 + .../2003-08-23-RecursiveOpaqueTypeResolve.ll | 9 + .../test/Linker/2003-08-24-InheritPtrSize.ll | 9 + .../Linker/2003-08-28-TypeResolvesGlobal.ll | 12 + .../Linker/2003-08-28-TypeResolvesGlobal2.ll | 18 + .../Linker/2003-08-28-TypeResolvesGlobal3.ll | 15 + .../2003-10-21-ConflictingTypesTolerance.ll | 6 + .../test/Linker/2003-10-27-LinkOncePromote.ll | 8 + .../test/Linker/2003-11-18-TypeResolution.ll | 20 + .../Linker/2004-02-17-WeakStrongLinkage.ll | 7 + .../test/Linker/2004-05-07-TypeResolution1.ll | 35 + .../test/Linker/2004-05-07-TypeResolution2.ll | 15 + .../test/Linker/2004-12-03-DisagreeingType.ll | 9 + .../Linker/2005-02-12-ConstantGlobals-2.ll | 8 + .../test/Linker/2005-02-12-ConstantGlobals.ll | 8 + .../2005-12-06-AppendingZeroLengthArrays.ll | 10 + .../test/Linker/2006-01-19-ConstantPacked.ll | 13 + .../Linker/2006-06-15-GlobalVarAlignment.ll | 7 + .../test/Linker/2008-03-05-AliasReference.ll | 17 + .../test/Linker/2008-03-05-AliasReference2.ll | 11 + .../Linker/2008-03-07-DroppedSection_a.ll | 11 + .../Linker/2008-03-07-DroppedSection_b.ll | 10 + .../Linker/2008-06-13-LinkOnceRedefinition.ll | 8 + final/test/Linker/2008-06-26-AddressSpace.ll | 9 + final/test/Linker/2008-07-06-AliasFnDecl.ll | 14 + final/test/Linker/2008-07-06-AliasFnDecl2.ll | 13 + final/test/Linker/2008-07-06-AliasWeakDest.ll | 18 + .../test/Linker/2008-07-06-AliasWeakDest2.ll | 18 + final/test/Linker/2009-09-03-mdnode.ll | 30 + final/test/Linker/2009-09-03-mdnode2.ll | 25 + final/test/Linker/AppendingLinkage.ll | 15 + final/test/Linker/AppendingLinkage2.ll | 8 + final/test/Linker/ConstantGlobals1.ll | 9 + final/test/Linker/ConstantGlobals2.ll | 9 + final/test/Linker/ConstantGlobals3.ll | 8 + final/test/Linker/LinkOnce.ll | 8 + final/test/Linker/PR8300.ll | 13 + final/test/Linker/available_externally_a.ll | 5 + final/test/Linker/available_externally_b.ll | 4 + final/test/Linker/basiclink.ll | 13 + final/test/Linker/dg.exp | 3 + final/test/Linker/link-archive.ll | 16 + final/test/Linker/link-global-to-func.ll | 13 + final/test/Linker/link-messages.ll | 11 + final/test/Linker/linkmdnode.ll | 13 + final/test/Linker/linkmdnode2.ll | 22 + final/test/Linker/linknamedmdnode.ll | 6 + final/test/Linker/linknamedmdnode2.ll | 6 + final/test/Linker/metadata-a.ll | 15 + final/test/Linker/metadata-b.ll | 9 + .../Linker/partial-type-refinement-link.ll | 20 + final/test/Linker/partial-type-refinement.ll | 24 + final/test/Linker/redefinition.ll | 10 + final/test/Linker/testlink1.ll | 42 + final/test/Linker/testlink2.ll | 41 + final/test/Linker/unnamed-addr1-a.ll | 27 + final/test/Linker/unnamed-addr1-b.ll | 12 + final/test/Linker/weakextern.ll | 11 + final/test/MC/ARM/arm_fixups.s | 7 + final/test/MC/ARM/arm_instructions.s | 284 + final/test/MC/ARM/arm_word_directive.s | 6 + final/test/MC/ARM/bracket-darwin.s | 5 + final/test/MC/ARM/bracket-exprs.s | 15 + final/test/MC/ARM/darwin-ARM-reloc.s | 171 + final/test/MC/ARM/darwin-Thumb-reloc.s | 139 + final/test/MC/ARM/dg.exp | 5 + final/test/MC/ARM/elf-eflags-eabi.s | 13 + final/test/MC/ARM/elf-movt.s | 39 + final/test/MC/ARM/elf-reloc-01.ll | 71 + final/test/MC/ARM/elf-reloc-02.ll | 51 + final/test/MC/ARM/elf-reloc-03.ll | 98 + final/test/MC/ARM/full_line_comment.s | 8 + final/test/MC/ARM/hilo-16bit-relocations.s | 20 + final/test/MC/ARM/neon-abs-encoding.s | 31 + final/test/MC/ARM/neon-absdiff-encoding.s | 82 + final/test/MC/ARM/neon-add-encoding.s | 137 + final/test/MC/ARM/neon-bitcount-encoding.s | 31 + final/test/MC/ARM/neon-bitwise-encoding.s | 47 + final/test/MC/ARM/neon-cmp-encoding.s | 115 + final/test/MC/ARM/neon-convert-encoding.s | 38 + final/test/MC/ARM/neon-dup-encoding.s | 27 + final/test/MC/ARM/neon-minmax-encoding.s | 58 + final/test/MC/ARM/neon-mov-encoding.s | 117 + final/test/MC/ARM/neon-mul-accum-encoding.s | 67 + final/test/MC/ARM/neon-mul-encoding.s | 56 + final/test/MC/ARM/neon-neg-encoding.s | 30 + final/test/MC/ARM/neon-pairwise-encoding.s | 86 + final/test/MC/ARM/neon-reciprocal-encoding.s | 26 + final/test/MC/ARM/neon-reverse-encoding.s | 26 + final/test/MC/ARM/neon-satshift-encoding.s | 150 + final/test/MC/ARM/neon-shift-encoding.s | 174 + final/test/MC/ARM/neon-shiftaccum-encoding.s | 98 + final/test/MC/ARM/neon-shuffle-encoding.s | 46 + final/test/MC/ARM/neon-sub-encoding.s | 108 + final/test/MC/ARM/neon-table-encoding.s | 19 + final/test/MC/ARM/neon-vld-encoding.s | 110 + final/test/MC/ARM/neon-vst-encoding.s | 101 + final/test/MC/ARM/neont2-abs-encoding.s | 33 + final/test/MC/ARM/neont2-absdiff-encoding.s | 86 + final/test/MC/ARM/neont2-add-encoding.s | 138 + final/test/MC/ARM/neont2-bitcount-encoding.s | 34 + final/test/MC/ARM/neont2-bitwise-encoding.s | 49 + final/test/MC/ARM/neont2-cmp-encoding.s | 36 + final/test/MC/ARM/neont2-convert-encoding.s | 40 + final/test/MC/ARM/neont2-dup-encoding.s | 29 + final/test/MC/ARM/neont2-minmax-encoding.s | 60 + final/test/MC/ARM/neont2-mov-encoding.s | 119 + final/test/MC/ARM/neont2-mul-accum-encoding.s | 69 + final/test/MC/ARM/neont2-mul-encoding.s | 58 + final/test/MC/ARM/neont2-neg-encoding.s | 32 + final/test/MC/ARM/neont2-pairwise-encoding.s | 89 + .../test/MC/ARM/neont2-reciprocal-encoding.s | 28 + final/test/MC/ARM/neont2-reverse-encoding.s | 26 + final/test/MC/ARM/neont2-satshift-encoding.s | 152 + final/test/MC/ARM/neont2-shift-encoding.s | 162 + .../test/MC/ARM/neont2-shiftaccum-encoding.s | 100 + final/test/MC/ARM/neont2-shuffle-encoding.s | 48 + final/test/MC/ARM/neont2-sub-encoding.s | 46 + final/test/MC/ARM/neont2-table-encoding.s | 21 + final/test/MC/ARM/neont2-vld-encoding.s | 112 + final/test/MC/ARM/neont2-vst-encoding.s | 103 + final/test/MC/ARM/prefetch.ll | 58 + final/test/MC/ARM/reg-list.s | 8 + final/test/MC/ARM/simple-encoding.ll | 237 + final/test/MC/ARM/simple-fp-encoding.s | 236 + final/test/MC/ARM/thumb.s | 70 + final/test/MC/ARM/thumb2.s | 286 + final/test/MC/ARM/thumb2_instructions.s | 12 + final/test/MC/AsmParser/assignment.s | 11 + final/test/MC/AsmParser/conditional_asm.s | 12 + final/test/MC/AsmParser/dash-n.s | 7 + final/test/MC/AsmParser/dg.exp | 5 + final/test/MC/AsmParser/directive_abort.s | 6 + final/test/MC/AsmParser/directive_align.s | 16 + final/test/MC/AsmParser/directive_ascii.s | 41 + final/test/MC/AsmParser/directive_comm.s | 8 + .../MC/AsmParser/directive_darwin_section.s | 4 + final/test/MC/AsmParser/directive_desc.s | 8 + final/test/MC/AsmParser/directive_elf_size.s | 8 + final/test/MC/AsmParser/directive_file.s | 8 + final/test/MC/AsmParser/directive_fill.s | 17 + final/test/MC/AsmParser/directive_include.s | 9 + final/test/MC/AsmParser/directive_lcomm.s | 10 + final/test/MC/AsmParser/directive_line.s | 5 + final/test/MC/AsmParser/directive_loc.s | 8 + final/test/MC/AsmParser/directive_lsym.s | 13 + final/test/MC/AsmParser/directive_org.s | 11 + final/test/MC/AsmParser/directive_set.s | 12 + final/test/MC/AsmParser/directive_space.s | 11 + .../directive_subsections_via_symbols.s | 6 + .../MC/AsmParser/directive_symbol_attrs.s | 7 + final/test/MC/AsmParser/directive_tbss.s | 7 + final/test/MC/AsmParser/directive_tdata.s | 9 + .../MC/AsmParser/directive_thread_init_func.s | 7 + final/test/MC/AsmParser/directive_tlv.s | 13 + final/test/MC/AsmParser/directive_values.s | 58 + final/test/MC/AsmParser/directive_zerofill.s | 14 + .../MC/AsmParser/dollars-in-identifiers.s | 7 + final/test/MC/AsmParser/equ.s | 9 + .../test/MC/AsmParser/expr_symbol_modifiers.s | 14 + final/test/MC/AsmParser/exprs-invalid.s | 13 + final/test/MC/AsmParser/exprs.s | 77 + final/test/MC/AsmParser/floating-literals.s | 35 + final/test/MC/AsmParser/hello.s | 28 + final/test/MC/AsmParser/ifdef.s | 29 + final/test/MC/AsmParser/ifndef.s | 29 + final/test/MC/AsmParser/labels.s | 59 + .../MC/AsmParser/macro-def-in-instantiation.s | 13 + final/test/MC/AsmParser/macros-parsing.s | 23 + final/test/MC/AsmParser/macros.s | 39 + final/test/MC/AsmParser/rename.s | 10 + final/test/MC/AsmParser/section.s | 107 + final/test/MC/AsmParser/variables-invalid.s | 17 + final/test/MC/AsmParser/variables.s | 15 + final/test/MC/COFF/align-nops.s | 50 + final/test/MC/COFF/basic-coff.s | 133 + final/test/MC/COFF/bss.s | 15 + final/test/MC/COFF/dg.exp | 5 + final/test/MC/COFF/module-asm.ll | 26 + final/test/MC/COFF/simple-fixups.s | 50 + final/test/MC/COFF/switch-relocations.ll | 37 + final/test/MC/COFF/symbol-alias.s | 62 + final/test/MC/COFF/symbol-fragment-offset.s | 187 + final/test/MC/COFF/weak.s | 51 + final/test/MC/Disassembler/ARM/arm-tests.txt | 141 + final/test/MC/Disassembler/ARM/dg.exp | 6 + final/test/MC/Disassembler/ARM/neon-tests.txt | 61 + .../test/MC/Disassembler/ARM/thumb-tests.txt | 123 + final/test/MC/Disassembler/MBlaze/dg.exp | 6 + .../MC/Disassembler/MBlaze/mblaze_branch.txt | 119 + .../MC/Disassembler/MBlaze/mblaze_fpu.txt | 47 + .../MC/Disassembler/MBlaze/mblaze_fsl.txt | 338 + .../MC/Disassembler/MBlaze/mblaze_imm.txt | 121 + .../MC/Disassembler/MBlaze/mblaze_memory.txt | 65 + .../Disassembler/MBlaze/mblaze_operands.txt | 197 + .../MC/Disassembler/MBlaze/mblaze_pattern.txt | 14 + .../MC/Disassembler/MBlaze/mblaze_shift.txt | 29 + .../MC/Disassembler/MBlaze/mblaze_special.txt | 105 + .../MC/Disassembler/MBlaze/mblaze_typea.txt | 74 + .../MC/Disassembler/MBlaze/mblaze_typeb.txt | 56 + final/test/MC/Disassembler/X86/dg.exp | 6 + final/test/MC/Disassembler/X86/enhanced.txt | 6 + .../test/MC/Disassembler/X86/simple-tests.txt | 68 + .../MC/Disassembler/X86/truncated-input.txt | 4 + final/test/MC/ELF/abs.s | 16 + final/test/MC/ELF/alias-reloc.s | 52 + final/test/MC/ELF/alias.s | 85 + final/test/MC/ELF/align-bss.s | 17 + final/test/MC/ELF/align-nops.s | 40 + final/test/MC/ELF/align-size.s | 13 + final/test/MC/ELF/align-text.s | 19 + final/test/MC/ELF/align.s | 32 + final/test/MC/ELF/bad-section.s | 9 + final/test/MC/ELF/basic-elf-32.s | 78 + final/test/MC/ELF/basic-elf-64.s | 82 + final/test/MC/ELF/bracket-exprs.s | 15 + final/test/MC/ELF/bracket.s | 8 + final/test/MC/ELF/bss.ll | 8 + final/test/MC/ELF/call-abs.s | 24 + final/test/MC/ELF/cfi-advance-loc2.s | 45 + final/test/MC/ELF/cfi-def-cfa-offset.s | 46 + final/test/MC/ELF/cfi-def-cfa-register.s | 41 + final/test/MC/ELF/cfi-def-cfa.s | 42 + final/test/MC/ELF/cfi-offset.s | 42 + final/test/MC/ELF/cfi-remember.s | 45 + final/test/MC/ELF/cfi-zero-addr-delta.s | 48 + final/test/MC/ELF/cfi.s | 674 + final/test/MC/ELF/comdat.s | 86 + final/test/MC/ELF/common.s | 88 + final/test/MC/ELF/common2.s | 21 + final/test/MC/ELF/debug-line.s | 22 + final/test/MC/ELF/debug-loc.s | 32 + final/test/MC/ELF/dg.exp | 5 + final/test/MC/ELF/diff.s | 15 + final/test/MC/ELF/diff2.s | 13 + final/test/MC/ELF/elf_directive_previous.s | 13 + final/test/MC/ELF/elf_directive_section.s | 23 + final/test/MC/ELF/empty-dwarf-lines.s | 21 + final/test/MC/ELF/empty.s | 70 + final/test/MC/ELF/entsize.ll | 44 + final/test/MC/ELF/entsize.s | 69 + final/test/MC/ELF/file.s | 23 + final/test/MC/ELF/global-offset.s | 18 + final/test/MC/ELF/got.s | 25 + final/test/MC/ELF/ident.s | 17 + final/test/MC/ELF/invalid-symver.s | 7 + final/test/MC/ELF/leb128.s | 19 + final/test/MC/ELF/local-reloc.s | 31 + final/test/MC/ELF/merge.s | 97 + final/test/MC/ELF/n_bytes.s | 20 + final/test/MC/ELF/no-fixup.s | 16 + final/test/MC/ELF/noexec.s | 24 + final/test/MC/ELF/norelocation.s | 18 + final/test/MC/ELF/org.s | 13 + final/test/MC/ELF/pic-diff.s | 29 + final/test/MC/ELF/plt.s | 14 + final/test/MC/ELF/pr9292.s | 26 + final/test/MC/ELF/relax-arith.s | 75 + final/test/MC/ELF/relax-crash.s | 11 + final/test/MC/ELF/relax.s | 27 + final/test/MC/ELF/relocation-386.s | 226 + final/test/MC/ELF/relocation-pc.s | 33 + final/test/MC/ELF/relocation.s | 114 + final/test/MC/ELF/rename.s | 46 + final/test/MC/ELF/section-quoting.s | 10 + final/test/MC/ELF/section.s | 110 + final/test/MC/ELF/set.s | 34 + final/test/MC/ELF/sleb.s | 29 + final/test/MC/ELF/symref.s | 165 + final/test/MC/ELF/tls-i386.s | 74 + final/test/MC/ELF/tls.s | 48 + final/test/MC/ELF/type.s | 32 + final/test/MC/ELF/uleb.s | 22 + final/test/MC/ELF/undef.s | 46 + final/test/MC/ELF/undef2.s | 10 + final/test/MC/ELF/weak-relocation.s | 15 + final/test/MC/ELF/weak.s | 30 + final/test/MC/ELF/weakref-plt.s | 8 + final/test/MC/ELF/weakref-reloc.s | 49 + final/test/MC/ELF/weakref.s | 234 + final/test/MC/ELF/zero.s | 16 + final/test/MC/MBlaze/dg.exp | 5 + final/test/MC/MBlaze/mblaze_branch.s | 197 + final/test/MC/MBlaze/mblaze_fpu.s | 77 + final/test/MC/MBlaze/mblaze_fsl.s | 568 + final/test/MC/MBlaze/mblaze_imm.s | 194 + final/test/MC/MBlaze/mblaze_memory.s | 107 + final/test/MC/MBlaze/mblaze_operands.s | 328 + final/test/MC/MBlaze/mblaze_pattern.s | 22 + final/test/MC/MBlaze/mblaze_shift.s | 47 + final/test/MC/MBlaze/mblaze_special.s | 167 + final/test/MC/MBlaze/mblaze_typea.s | 122 + final/test/MC/MBlaze/mblaze_typeb.s | 92 + final/test/MC/MachO/absolutize.s | 213 + final/test/MC/MachO/comm-1.s | 114 + .../test/MC/MachO/darwin-complex-difference.s | 129 + .../test/MC/MachO/darwin-x86_64-diff-relocs.s | 329 + .../MC/MachO/darwin-x86_64-reloc-offsets.s | 343 + final/test/MC/MachO/darwin-x86_64-reloc.s | 405 + final/test/MC/MachO/data.s | 67 + final/test/MC/MachO/dg.exp | 6 + final/test/MC/MachO/diff-with-two-sections.s | 64 + final/test/MC/MachO/direction_labels.s | 95 + final/test/MC/MachO/empty-dwarf-lines.s | 25 + final/test/MC/MachO/indirect-symbols.s | 188 + final/test/MC/MachO/jcc.s | 106 + final/test/MC/MachO/lcomm-attributes.s | 136 + final/test/MC/MachO/loc.s | 25 + final/test/MC/MachO/pcrel-to-other-section.s | 107 + final/test/MC/MachO/relax-jumps.s | 31 + final/test/MC/MachO/relax-recompute-align.s | 37 + final/test/MC/MachO/reloc-diff.s | 55 + final/test/MC/MachO/reloc-pcrel-offset.s | 14 + final/test/MC/MachO/reloc-pcrel.s | 62 + final/test/MC/MachO/reloc.s | 292 + final/test/MC/MachO/section-align-1.s | 87 + final/test/MC/MachO/section-align-2.s | 137 + final/test/MC/MachO/section-flags.s | 14 + final/test/MC/MachO/string-table.s | 100 + final/test/MC/MachO/symbol-diff.s | 122 + final/test/MC/MachO/symbol-flags.s | 341 + final/test/MC/MachO/symbol-indirect.s | 268 + final/test/MC/MachO/symbols-1.s | 310 + final/test/MC/MachO/tbss.s | 114 + final/test/MC/MachO/tdata.s | 106 + final/test/MC/MachO/thread_init_func.s | 63 + final/test/MC/MachO/tls.s | 270 + final/test/MC/MachO/tlv-reloc.s | 174 + final/test/MC/MachO/tlv.s | 110 + final/test/MC/MachO/values.s | 135 + final/test/MC/MachO/weakdef.s | 141 + final/test/MC/MachO/x86_32-optimal_nop.s | 257 + final/test/MC/MachO/x86_32-sections.s | 536 + final/test/MC/MachO/x86_32-symbols.s | 1041 + final/test/MC/MachO/x86_64-sections.s | 561 + final/test/MC/MachO/x86_64-symbols.s | 998 + final/test/MC/MachO/zerofill-1.s | 121 + final/test/MC/MachO/zerofill-2.s | 103 + final/test/MC/MachO/zerofill-3.s | 141 + final/test/MC/MachO/zerofill-4.s | 35 + final/test/MC/MachO/zerofill-5.s | 109 + final/test/MC/MachO/zerofill-sect-align.s | 15 + final/test/MC/X86/3DNow.s | 92 + final/test/MC/X86/dg.exp | 5 + final/test/MC/X86/x86-32-avx.s | 3283 +++ final/test/MC/X86/x86-32-coverage.s | 19564 +++++++++++++ final/test/MC/X86/x86-32-fma3.s | 674 + final/test/MC/X86/x86-32.s | 826 + final/test/MC/X86/x86-64.s | 991 + final/test/MC/X86/x86_64-avx-clmul-encoding.s | 42 + final/test/MC/X86/x86_64-avx-encoding.s | 3318 +++ final/test/MC/X86/x86_64-encoding.s | 157 + final/test/MC/X86/x86_64-fma3-encoding.s | 674 + final/test/MC/X86/x86_64-imm-widths.s | 105 + final/test/MC/X86/x86_directives.s | 6 + final/test/MC/X86/x86_errors.s | 5 + final/test/MC/X86/x86_operands.s | 58 + final/test/Makefile | 196 + final/test/Makefile.tests | 80 + .../trivial-object-test.coff-i386 | Bin 0 -> 346 bytes .../trivial-object-test.coff-x86-64 | Bin 0 -> 347 bytes .../trivial-object-test.elf-i386 | Bin 0 -> 716 bytes .../trivial-object-test.elf-x86-64 | Bin 0 -> 1024 bytes .../trivial-object-test.macho-i386 | Bin 0 -> 552 bytes .../trivial-object-test.macho-x86-64 | Bin 0 -> 552 bytes final/test/Object/dg.exp | 3 + .../test/Object/nm-trivial-object.test-broken | 19 + .../Object/objdump-trivial-object.test-broken | 54 + final/test/Other/2002-01-31-CallGraph.ll | 13 + .../Other/2002-02-24-InlineBrokePHINodes.ll | 23 + final/test/Other/2002-03-11-ConstPropCrash.ll | 24 + .../Other/2003-02-19-LoopInfoNestingBug.ll | 29 + .../2004-08-16-PackedConstantInlineStore.ll | 8 + .../Other/2004-08-16-PackedGlobalConstant.ll | 11 + final/test/Other/2004-08-16-PackedSelect.ll | 13 + final/test/Other/2004-08-16-PackedSimple.ll | 13 + .../Other/2004-08-20-PackedControlFlow.ll | 22 + final/test/Other/2006-02-05-PassManager.ll | 5 + ...007-04-24-eliminate-mostly-empty-blocks.ll | 309 + final/test/Other/2007-06-05-PassID.ll | 11 + final/test/Other/2007-06-28-PassManager.ll | 7 + final/test/Other/2007-09-10-PassManager.ll | 32 + final/test/Other/2008-02-14-PassManager.ll | 5 + .../Other/2008-06-04-FieldSizeInPacked.ll | 14 + final/test/Other/2008-10-06-RemoveDeadPass.ll | 11 + final/test/Other/2008-10-15-MissingSpace.ll | 7 + final/test/Other/2009-03-31-CallGraph.ll | 31 + .../Other/2009-06-05-no-implicit-float.ll | 4 + .../Other/2009-09-14-function-elements.ll | 6 + final/test/Other/2010-05-06-Printer.ll | 6 + final/test/Other/close-stderr.ll | 11 + final/test/Other/constant-fold-gep.ll | 459 + final/test/Other/dg.exp | 3 + final/test/Other/extract.ll | 27 + .../Other/inline-asm-newline-terminator.ll | 6 + .../test/Other/invalid-commandline-option.ll | 3 + final/test/Other/lint.ll | 167 + final/test/Scripts/README.txt | 2 + final/test/Scripts/coff-dump.py | 590 + final/test/Scripts/coff-dump.py.bat | 7 + final/test/Scripts/common_dump.py | 46 + final/test/Scripts/elf-dump | 231 + final/test/Scripts/elf-dump.bat | 7 + final/test/Scripts/ignore | 10 + final/test/Scripts/macho-dumpx | 294 + final/test/Scripts/macho-dumpx.bat | 7 + final/test/TableGen/2003-08-03-PassCode.td | 8 + final/test/TableGen/2006-09-18-LargeInt.td | 6 + .../TableGen/2010-03-24-PrematureDefaults.td | 44 + final/test/TableGen/AnonDefinitionOnDemand.td | 13 + final/test/TableGen/BitsInitOverflow.td | 5 + final/test/TableGen/CStyleComment.td | 14 + final/test/TableGen/Dag.td | 71 + final/test/TableGen/DefmInherit.td | 33 + final/test/TableGen/DefmInsideMultiClass.td | 25 + final/test/TableGen/FieldAccess.td | 16 + final/test/TableGen/ForwardRef.td | 16 + final/test/TableGen/GeneralList.td | 9 + final/test/TableGen/Include.inc | 4 + final/test/TableGen/Include.td | 7 + final/test/TableGen/IntBitInit.td | 6 + final/test/TableGen/LazyChange.td | 11 + final/test/TableGen/LetInsideMultiClasses.td | 29 + final/test/TableGen/ListArgs.td | 12 + final/test/TableGen/ListArgsSimple.td | 9 + final/test/TableGen/ListConversion.td | 11 + final/test/TableGen/ListManip.td | 12 + final/test/TableGen/ListSlices.td | 19 + final/test/TableGen/MultiClass.td | 26 + final/test/TableGen/MultiClassDefName.td | 13 + final/test/TableGen/MultiClassInherit.td | 65 + final/test/TableGen/Slice.td | 88 + final/test/TableGen/String.td | 6 + final/test/TableGen/SuperSubclassSameName.td | 21 + final/test/TableGen/TargetInstrInfo.td | 148 + final/test/TableGen/TargetInstrSpec.td | 98 + final/test/TableGen/TemplateArgRename.td | 18 + final/test/TableGen/Tree.td | 19 + final/test/TableGen/TreeNames.td | 18 + final/test/TableGen/UnsetBitInit.td | 11 + final/test/TableGen/UnterminatedComment.td | 6 + final/test/TableGen/cast.td | 91 + final/test/TableGen/defmclass.td | 50 + final/test/TableGen/dg.exp | 3 + final/test/TableGen/eq.td | 14 + final/test/TableGen/eqbit.td | 11 + final/test/TableGen/foreach.td | 32 + final/test/TableGen/if.td | 45 + final/test/TableGen/ifbit.td | 11 + final/test/TableGen/lisp.td | 22 + final/test/TableGen/nested-comment.td | 12 + final/test/TableGen/strconcat.td | 11 + final/test/TableGen/subst.td | 30 + final/test/TableGen/subst2.td | 16 + final/test/TableGen/usevalname.td | 24 + final/test/TestRunner.sh | 5 + .../ADCE/2002-01-31-UseStuckAround.ll | 13 + .../Transforms/ADCE/2002-05-22-PHITest.ll | 16 + .../ADCE/2002-05-23-ZeroArgPHITest.ll | 32 + .../ADCE/2002-05-28-Crash-distilled.ll | 17 + .../test/Transforms/ADCE/2002-05-28-Crash.ll | 54 + .../ADCE/2002-07-17-AssertionFailure.ll | 13 + .../ADCE/2002-07-17-PHIAssertion.ll | 48 + .../Transforms/ADCE/2002-07-29-Segfault.ll | 9 + .../ADCE/2003-01-22-PredecessorProblem.ll | 25 + .../ADCE/2003-04-25-PHIPostDominateProblem.ll | 35 + .../Transforms/ADCE/2003-06-11-InvalidCFG.ll | 28 + .../ADCE/2003-06-24-BadSuccessor.ll | 91 + .../ADCE/2003-06-24-BasicFunctionality.ll | 41 + .../ADCE/2003-09-10-UnwindInstFail.ll | 19 + .../ADCE/2003-09-15-InfLoopCrash.ll | 9 + .../2003-11-16-MissingPostDominanceInfo.ll | 18 + .../ADCE/2004-05-04-UnreachableBlock.ll | 16 + .../ADCE/2005-02-17-PHI-Invoke-Crash.ll | 45 + final/test/Transforms/ADCE/basictest.ll | 19 + final/test/Transforms/ADCE/basictest1.ll | 97 + final/test/Transforms/ADCE/basictest2.ll | 97 + final/test/Transforms/ADCE/dce_pure_call.ll | 8 + final/test/Transforms/ADCE/dce_pure_invoke.ll | 15 + final/test/Transforms/ADCE/dg.exp | 3 + .../Transforms/ADCE/unreachable-function.ll | 5 + .../2008-02-01-ReturnAttrs.ll | 15 + .../2008-07-02-array-indexing.ll | 25 + .../ArgumentPromotion/2008-09-07-CGUpdate.ll | 12 + .../2008-09-08-CGUpdateSelfEdge.ll | 25 + .../ArgumentPromotion/aggregate-promote.ll | 24 + .../Transforms/ArgumentPromotion/attrs.ll | 25 + .../Transforms/ArgumentPromotion/basictest.ll | 23 + .../Transforms/ArgumentPromotion/byval-2.ll | 26 + .../Transforms/ArgumentPromotion/byval.ll | 25 + .../ArgumentPromotion/callgraph-update.ll | 23 + .../Transforms/ArgumentPromotion/chained.ll | 17 + .../ArgumentPromotion/control-flow.ll | 19 + .../ArgumentPromotion/control-flow2.ll | 22 + .../Transforms/ArgumentPromotion/crash.ll | 59 + .../test/Transforms/ArgumentPromotion/dg.exp | 3 + .../Transforms/ArgumentPromotion/pr3085.ll | 1944 ++ .../Transforms/BlockPlacement/basictest.ll | 15 + final/test/Transforms/BlockPlacement/dg.exp | 3 + .../2007-10-19-InlineAsmDirectives.ll | 18 + .../2004-03-13-LoopExtractorCrash.ll | 75 + .../2004-03-14-DominanceProblem.ll | 33 + .../2004-03-14-NoSwitchSupport.ll | 28 + .../CodeExtractor/2004-03-17-MissedLiveIns.ll | 47 + .../2004-03-17-OutputMismatch.ll | 20 + .../2004-03-17-UpdatePHIsOutsideRegion.ll | 23 + .../2004-03-18-InvokeHandling.ll | 194 + .../2004-08-12-BlockExtractPHI.ll | 26 + .../CodeExtractor/2004-11-12-InvokeExtract.ll | 15 + final/test/Transforms/CodeExtractor/dg.exp | 3 + .../CodeGenPrepare/2008-11-24-RAUW-Self.ll | 511 + final/test/Transforms/CodeGenPrepare/basic.ll | 29 + final/test/Transforms/CodeGenPrepare/dg.exp | 3 + .../2002-05-03-DivideByZeroException.ll | 15 + .../ConstProp/2002-05-03-NotOperator.ll | 19 + .../ConstProp/2002-09-03-SetCC-Bools.ll | 20 + .../ConstProp/2003-05-12-DivideError.ll | 15 + .../ConstProp/2005-01-28-SetCCGEP.ll | 10 + .../ConstProp/2006-11-30-vector-cast.ll | 10 + .../ConstProp/2006-12-01-TruncBoolBug.ll | 7 + .../ConstProp/2006-12-01-bool-casts.ll | 15 + .../ConstProp/2007-02-05-BitCast.ll | 7 + .../Transforms/ConstProp/2007-02-23-sdiv.ll | 5 + .../Transforms/ConstProp/2007-11-23-cttz.ll | 8 + .../ConstProp/2008-07-07-VectorCompare.ll | 28 + .../2009-06-20-constexpr-zero-lhs.ll | 11 + .../ConstProp/2009-09-01-GEP-Crash.ll | 24 + final/test/Transforms/ConstProp/basictest.ll | 42 + final/test/Transforms/ConstProp/bitcast.ll | 10 + final/test/Transforms/ConstProp/bswap.ll | 25 + final/test/Transforms/ConstProp/calls.ll | 56 + .../Transforms/ConstProp/constant-expr.ll | 111 + final/test/Transforms/ConstProp/dg.exp | 3 + final/test/Transforms/ConstProp/div-zero.ll | 12 + .../test/Transforms/ConstProp/extractvalue.ll | 68 + .../Transforms/ConstProp/float-to-ptr-cast.ll | 15 + .../test/Transforms/ConstProp/insertvalue.ll | 68 + final/test/Transforms/ConstProp/loads.ll | 139 + .../test/Transforms/ConstProp/logicaltest.ll | 35 + .../test/Transforms/ConstProp/overflow-ops.ll | 183 + final/test/Transforms/ConstProp/phi.ll | 17 + final/test/Transforms/ConstProp/remtest.ll | 24 + .../ConstantMerge/2002-09-23-CPR-Update.ll | 13 + .../2003-10-28-MergeExternalConstants.ll | 7 + .../ConstantMerge/2011-01-15-EitherOrder.ll | 18 + final/test/Transforms/ConstantMerge/dg.exp | 3 + .../Transforms/ConstantMerge/dont-merge.ll | 44 + .../Transforms/ConstantMerge/merge-both.ll | 26 + .../Transforms/ConstantMerge/unnamed-addr.ll | 40 + .../2010-09-02-Trunc.ll | 25 + .../2010-09-26-MergeConstantRange.ll | 82 + .../CorrelatedValuePropagation/basic.ll | 82 + .../CorrelatedValuePropagation/crash.ll | 37 + .../CorrelatedValuePropagation/dg.exp | 3 + .../CorrelatedValuePropagation/non-null.ll | 103 + .../DeadArgElim/2006-06-27-struct-ret.ll | 11 + .../DeadArgElim/2007-02-07-FuncRename.ll | 11 + .../DeadArgElim/2007-10-18-VarargsReturn.ll | 12 + .../DeadArgElim/2007-12-20-ParamAttrs.ll | 20 + .../2008-01-16-VarargsParamAttrs.ll | 31 + .../DeadArgElim/2008-06-23-DeadAfterLive.ll | 23 + .../DeadArgElim/2009-03-17-MRE-Invoke.ll | 26 + .../DeadArgElim/2010-04-30-DbgInfo.ll | 68 + .../test/Transforms/DeadArgElim/basictest.ll | 36 + final/test/Transforms/DeadArgElim/canon.ll | 24 + .../Transforms/DeadArgElim/dead_vaargs.ll | 12 + .../Transforms/DeadArgElim/deadexternal.ll | 52 + .../test/Transforms/DeadArgElim/deadretval.ll | 18 + .../Transforms/DeadArgElim/deadretval2.ll | 59 + final/test/Transforms/DeadArgElim/dg.exp | 3 + .../test/Transforms/DeadArgElim/keepalive.ll | 30 + .../Transforms/DeadArgElim/multdeadretval.ll | 68 + .../2011-03-25-DSEMiscompile.ll | 23 + .../DeadStoreElimination/PartialStore.ll | 71 + .../DeadStoreElimination/const-pointers.ll | 39 + .../Transforms/DeadStoreElimination/crash.ll | 74 + .../Transforms/DeadStoreElimination/dg.exp | 3 + .../Transforms/DeadStoreElimination/free.ll | 40 + .../DeadStoreElimination/lifetime.ll | 37 + .../DeadStoreElimination/memintrinsics.ll | 47 + .../DeadStoreElimination/no-targetdata.ll | 15 + .../Transforms/DeadStoreElimination/simple.ll | 238 + final/test/Transforms/EarlyCSE/basic.ll | 121 + final/test/Transforms/EarlyCSE/dg.exp | 3 + .../FunctionAttrs/2008-09-03-Mutual.ll | 11 + .../FunctionAttrs/2008-09-03-ReadNone.ll | 18 + .../FunctionAttrs/2008-09-03-ReadOnly.ll | 9 + .../FunctionAttrs/2008-09-13-VolatileRead.ll | 9 + .../FunctionAttrs/2008-10-04-LocalMemory.ll | 64 + .../FunctionAttrs/2008-12-29-Constant.ll | 8 + .../FunctionAttrs/2008-12-31-NoCapture.ll | 101 + .../FunctionAttrs/2009-01-02-LocalStores.ll | 14 + .../FunctionAttrs/2009-05-06-Malloc.ll | 7 + .../FunctionAttrs/2010-10-30-volatile.ll | 10 + final/test/Transforms/FunctionAttrs/dg.exp | 3 + .../GVN/2007-07-25-DominatedLoop.ll | 86 + .../Transforms/GVN/2007-07-25-InfiniteLoop.ll | 14 + final/test/Transforms/GVN/2007-07-25-Loop.ll | 15 + .../Transforms/GVN/2007-07-25-NestedLoop.ll | 38 + .../GVN/2007-07-25-SinglePredecessor.ll | 29 + .../GVN/2007-07-26-InterlockingLoops.ll | 33 + .../Transforms/GVN/2007-07-26-NonRedundant.ll | 16 + .../Transforms/GVN/2007-07-26-PhiErasure.ll | 28 + .../Transforms/GVN/2007-07-30-PredIDom.ll | 274 + .../Transforms/GVN/2007-07-31-NoDomInherit.ll | 313 + .../Transforms/GVN/2007-07-31-RedundantPhi.ll | 22 + .../Transforms/GVN/2008-02-12-UndefLoad.ll | 20 + .../test/Transforms/GVN/2008-02-13-NewPHI.ll | 22 + .../GVN/2008-02-24-NonDominatedMemcpy.ll | 25 + .../Transforms/GVN/2008-02-26-MemCpySize.ll | 46 + .../Transforms/GVN/2008-07-02-Unreachable.ll | 35 + .../Transforms/GVN/2008-12-09-SelfRemove.ll | 26 + .../Transforms/GVN/2008-12-12-RLE-Crash.ll | 35 + .../GVN/2008-12-14-rle-reanalyze.ll | 18 + .../Transforms/GVN/2008-12-15-CacheVisited.ll | 28 + .../GVN/2009-01-21-SortInvalidation.ll | 55 + .../GVN/2009-01-22-SortInvalidation.ll | 100 + .../Transforms/GVN/2009-02-17-LoadPRECrash.ll | 193 + .../Transforms/GVN/2009-03-10-PREOnVoid.ll | 82 + .../Transforms/GVN/2009-06-17-InvalidPRE.ll | 72 + .../GVN/2009-07-13-MemDepSortFail.ll | 67 + .../GVN/2009-11-12-MemDepMallocBitCast.ll | 15 + .../GVN/2010-03-31-RedundantPHIs.ll | 42 + .../test/Transforms/GVN/2010-05-08-OneBit.ll | 63 + .../Transforms/GVN/2010-11-13-Simplify.ll | 15 + final/test/Transforms/GVN/basic.ll | 10 + final/test/Transforms/GVN/bitcast-of-call.ll | 12 + final/test/Transforms/GVN/calls-nonlocal.ll | 49 + final/test/Transforms/GVN/calls-readonly.ll | 29 + final/test/Transforms/GVN/condprop.ll | 55 + final/test/Transforms/GVN/crash-no-aa.ll | 16 + final/test/Transforms/GVN/crash.ll | 153 + final/test/Transforms/GVN/dg.exp | 3 + final/test/Transforms/GVN/invariant-simple.ll | 36 + final/test/Transforms/GVN/lifetime-simple.ll | 20 + .../test/Transforms/GVN/load-constant-mem.ll | 13 + final/test/Transforms/GVN/load-pre-align.ll | 44 + final/test/Transforms/GVN/load-pre-licm.ll | 39 + final/test/Transforms/GVN/local-pre.ll | 18 + final/test/Transforms/GVN/lpre-call-wrap-2.ll | 40 + final/test/Transforms/GVN/lpre-call-wrap.ll | 55 + final/test/Transforms/GVN/mixed.ll | 13 + final/test/Transforms/GVN/non-local-offset.ll | 59 + .../test/Transforms/GVN/nonescaping-malloc.ll | 108 + .../Transforms/GVN/null-aliases-nothing.ll | 20 + final/test/Transforms/GVN/phi-translate.ll | 31 + final/test/Transforms/GVN/pre-basic-add.ll | 27 + final/test/Transforms/GVN/pre-load.ll | 391 + final/test/Transforms/GVN/pre-single-pred.ll | 45 + final/test/Transforms/GVN/preserve-tbaa.ll | 28 + final/test/Transforms/GVN/rle-must-alias.ll | 46 + .../Transforms/GVN/rle-no-phi-translate.ll | 28 + final/test/Transforms/GVN/rle-nonlocal.ll | 24 + .../test/Transforms/GVN/rle-phi-translate.ll | 146 + .../test/Transforms/GVN/rle-semidominated.ll | 19 + final/test/Transforms/GVN/rle.ll | 546 + .../GlobalDCE/2002-07-17-CastRef.ll | 11 + .../GlobalDCE/2002-07-17-ConstantRef.ll | 13 + .../GlobalDCE/2002-08-17-FunctionDGE.ll | 17 + .../GlobalDCE/2002-08-17-WorkListTest.ll | 12 + .../GlobalDCE/2002-09-12-Redeletion.ll | 11 + .../GlobalDCE/2003-07-01-SelfReference.ll | 11 + .../2003-10-09-PreserveWeakGlobals.ll | 6 + .../GlobalDCE/2009-01-05-DeadAliases.ll | 8 + .../GlobalDCE/2009-02-17-AliasUsesAliasee.ll | 4 + .../Transforms/GlobalDCE/2009-09-03-MDNode.ll | 264 + .../Transforms/GlobalDCE/basicvariabletest.ll | 5 + final/test/Transforms/GlobalDCE/dg.exp | 3 + .../GlobalDCE/externally_available.ll | 10 + .../GlobalOpt/2004-10-10-CastStoreOnce.ll | 17 + .../2005-06-15-LocalizeConstExprCrash.ll | 10 + .../Transforms/GlobalOpt/2005-09-27-Crash.ll | 27 + .../GlobalOpt/2006-07-07-InlineAsmCrash.ll | 135 + .../2006-11-01-ShrinkGlobalPhiCrash.ll | 33 + .../Transforms/GlobalOpt/2007-04-05-Crash.ll | 34 + .../Transforms/GlobalOpt/2007-05-13-Crash.ll | 74 + .../GlobalOpt/2007-06-04-PackedStruct.ll | 36 + .../GlobalOpt/2007-11-09-GEP-GEP-Crash.ll | 19 + .../Transforms/GlobalOpt/2008-01-03-Crash.ll | 26 + .../GlobalOpt/2008-01-13-OutOfRangeSROA.ll | 16 + .../GlobalOpt/2008-01-29-VolatileGlobal.ll | 9 + .../GlobalOpt/2008-02-16-NestAttr.ll | 57 + .../GlobalOpt/2008-04-26-SROA-Global-Align.ll | 32 + .../GlobalOpt/2008-07-17-addrspace.ll | 28 + .../GlobalOpt/2008-12-16-HeapSRACrash-2.ll | 24 + .../GlobalOpt/2008-12-16-HeapSRACrash.ll | 27 + .../GlobalOpt/2009-01-13-phi-user.ll | 35 + .../GlobalOpt/2009-02-15-BitcastAlias.ll | 10 + .../GlobalOpt/2009-02-15-ResolveAlias.ll | 24 + .../Transforms/GlobalOpt/2009-03-05-dbg.ll | 76 + .../GlobalOpt/2009-03-06-Anonymous.ll | 11 + .../GlobalOpt/2009-03-07-PromotePtrToBool.ll | 17 + .../GlobalOpt/2009-06-01-RecursivePHI.ll | 122 + .../2009-11-16-BrokenPerformHeapAllocSRoA.ll | 26 + ...2009-11-16-MallocSingleStoreToGlobalVar.ll | 30 + .../GlobalOpt/2010-02-25-MallocPromote.ll | 18 + .../GlobalOpt/2010-02-26-MallocSROA.ll | 27 + .../GlobalOpt/2010-10-19-WeakOdr.ll | 16 + .../Transforms/GlobalOpt/alias-resolve.ll | 19 + final/test/Transforms/GlobalOpt/basictest.ll | 9 + .../GlobalOpt/constantexpr-dangle.ll | 13 + .../GlobalOpt/constantfold-initializers.ll | 8 + final/test/Transforms/GlobalOpt/crash.ll | 66 + .../GlobalOpt/ctor-list-opt-constexpr.ll | 23 + .../GlobalOpt/ctor-list-opt-inbounds.ll | 23 + .../Transforms/GlobalOpt/ctor-list-opt.ll | 100 + .../test/Transforms/GlobalOpt/deadglobal-2.ll | 11 + final/test/Transforms/GlobalOpt/deadglobal.ll | 9 + final/test/Transforms/GlobalOpt/dg.exp | 3 + .../Transforms/GlobalOpt/globalsra-partial.ll | 24 + .../GlobalOpt/globalsra-unknown-index.ll | 41 + final/test/Transforms/GlobalOpt/globalsra.ll | 24 + final/test/Transforms/GlobalOpt/heap-sra-1.ll | 38 + final/test/Transforms/GlobalOpt/heap-sra-2.ll | 38 + final/test/Transforms/GlobalOpt/heap-sra-3.ll | 39 + final/test/Transforms/GlobalOpt/heap-sra-4.ll | 39 + .../test/Transforms/GlobalOpt/heap-sra-phi.ll | 43 + .../test/Transforms/GlobalOpt/integer-bool.ll | 23 + final/test/Transforms/GlobalOpt/iterate.ll | 11 + .../Transforms/GlobalOpt/load-store-global.ll | 15 + .../Transforms/GlobalOpt/malloc-promote-1.ll | 24 + .../Transforms/GlobalOpt/malloc-promote-2.ll | 19 + final/test/Transforms/GlobalOpt/memcpy.ll | 15 + final/test/Transforms/GlobalOpt/memset.ll | 21 + final/test/Transforms/GlobalOpt/metadata.ll | 26 + final/test/Transforms/GlobalOpt/phi-select.ll | 31 + .../GlobalOpt/storepointer-compare.ll | 30 + .../test/Transforms/GlobalOpt/storepointer.ll | 19 + .../test/Transforms/GlobalOpt/trivialstore.ll | 19 + final/test/Transforms/GlobalOpt/undef-init.ll | 17 + .../test/Transforms/GlobalOpt/unnamed-addr.ll | 54 + .../IPConstantProp/2008-06-09-WeakProp.ll | 15 + .../IPConstantProp/2009-09-24-byval-ptr.ll | 40 + .../IPConstantProp/dangling-block-address.ll | 42 + .../test/Transforms/IPConstantProp/deadarg.ll | 6 + final/test/Transforms/IPConstantProp/dg.exp | 3 + .../Transforms/IPConstantProp/recursion.ll | 12 + .../IPConstantProp/return-argument.ll | 49 + .../IPConstantProp/return-constant.ll | 26 + .../IPConstantProp/return-constants.ll | 41 + .../IPConstantProp/user-with-multiple-uses.ll | 30 + .../2002-09-09-PointerIndVar.ll | 17 + .../IndVarSimplify/2003-04-16-ExprAnalysis.ll | 17 + .../IndVarSimplify/2003-09-12-MultiplePred.ll | 15 + .../IndVarSimplify/2003-09-23-NotAtTop.ll | 20 + .../2003-12-10-RemoveInstrCrash.ll | 18 + .../IndVarSimplify/2003-12-15-Crash.ll | 24 + .../IndVarSimplify/2003-12-21-IndVarSize.ll | 15 + .../2004-03-10-PHIInsertionBug.ll | 26 + .../2004-04-05-InvokeCastCrash.ll | 283 + .../2004-04-07-ScalarEvolutionCrash.ll | 27 + .../IndVarSimplify/2005-02-11-InvokeCrash.ll | 23 + .../2005-02-17-TruncateExprCrash.ll | 61 + .../2005-02-26-ExitValueCompute.ll | 20 + .../2005-06-15-InstMoveCrash.ll | 37 + .../IndVarSimplify/2005-11-18-Crash.ll | 17 + .../2006-03-31-NegativeStride.ll | 22 + .../2006-06-16-Indvar-LCSSA-Crash.ll | 22 + .../IndVarSimplify/2006-09-20-LFTR-Crash.ll | 44 + .../IndVarSimplify/2006-12-10-BitCast.ll | 33 + .../IndVarSimplify/2007-01-06-TripCount.ll | 38 + .../2007-06-06-DeleteDanglesPtr.ll | 117 + .../IndVarSimplify/2007-11-23-BitcastCrash.ll | 20 + .../2008-06-15-SCEVExpanderBug.ll | 17 + .../IndVarSimplify/2008-09-02-IVType.ll | 58 + .../2008-10-03-CouldNotCompute.ll | 32 + .../2008-11-25-APFloatAssert.ll | 11 + .../2009-04-14-shorten_iv_vars.ll | 114 + .../2009-04-15-shorten-iv-vars-2.ll | 160 + .../IndVarSimplify/2009-04-22-IndvarCrash.ll | 35 + .../IndVarSimplify/2009-04-27-Floating.ll | 18 + .../IndVarSimplify/2009-05-24-useafterfree.ll | 41 + .../Transforms/IndVarSimplify/ada-loops.ll | 90 + .../Transforms/IndVarSimplify/addrec-gep.ll | 78 + .../IndVarSimplify/ashr-tripcount.ll | 107 + .../Transforms/IndVarSimplify/avoid-i0.ll | 126 + .../IndVarSimplify/casted-argument.ll | 50 + .../Transforms/IndVarSimplify/complex-scev.ll | 29 + final/test/Transforms/IndVarSimplify/crash.ll | 55 + .../Transforms/IndVarSimplify/dangling-use.ll | 41 + final/test/Transforms/IndVarSimplify/dg.exp | 3 + .../IndVarSimplify/divide-pointer.ll | 95 + .../IndVarSimplify/eliminate-comparison.ll | 108 + .../IndVarSimplify/eliminate-max.ll | 52 + .../IndVarSimplify/eliminate-rem.ll | 121 + .../IndVarSimplify/exit_value_tests.ll | 114 + .../IndVarSimplify/floating-point-iv.ll | 92 + .../IndVarSimplify/gep-with-mul-base.ll | 59 + .../Transforms/IndVarSimplify/indirectbr.ll | 39 + .../IndVarSimplify/interesting-invoke-use.ll | 57 + .../iterationCount_zext_or_trunc.ll | 25 + .../test/Transforms/IndVarSimplify/iv-sext.ll | 143 + .../test/Transforms/IndVarSimplify/iv-zext.ll | 33 + .../IndVarSimplify/lftr-other-uses.ll | 36 + .../Transforms/IndVarSimplify/lftr-promote.ll | 38 + .../Transforms/IndVarSimplify/lftr_simple.ll | 22 + .../IndVarSimplify/loop_evaluate10.ll | 47 + .../IndVarSimplify/loop_evaluate11.ll | 36 + .../IndVarSimplify/loop_evaluate7.ll | 61 + .../IndVarSimplify/loop_evaluate8.ll | 63 + .../IndVarSimplify/loop_evaluate9.ll | 78 + .../IndVarSimplify/loop_evaluate_1.ll | 21 + .../IndVarSimplify/loop_evaluate_2.ll | 28 + .../IndVarSimplify/loop_evaluate_3.ll | 19 + .../IndVarSimplify/loop_evaluate_4.ll | 20 + .../IndVarSimplify/loop_evaluate_5.ll | 32 + .../IndVarSimplify/loop_evaluate_6.ll | 31 + .../Transforms/IndVarSimplify/masked-iv.ll | 26 + .../Transforms/IndVarSimplify/max-pointer.ll | 39 + .../phi-uses-value-multiple-times.ll | 33 + .../IndVarSimplify/pointer-indvars.ll | 15 + .../test/Transforms/IndVarSimplify/pointer.ll | 38 + .../IndVarSimplify/polynomial-expand.ll | 38 + .../preserve-gep-loop-variant.ll | 42 + .../IndVarSimplify/preserve-gep-nested.ll | 75 + .../IndVarSimplify/preserve-gep-remainder.ll | 20 + .../Transforms/IndVarSimplify/preserve-gep.ll | 39 + .../IndVarSimplify/preserve-signed-wrap.ll | 38 + .../promote-iv-to-eliminate-casts.ll | 99 + .../IndVarSimplify/shrunk-constant.ll | 15 + .../IndVarSimplify/signed-trip-count.ll | 30 + .../IndVarSimplify/single-element-range.ll | 27 + .../Transforms/IndVarSimplify/sink-alloca.ll | 31 + .../IndVarSimplify/sink-trapping.ll | 19 + .../Transforms/IndVarSimplify/subtract.ll | 15 + .../IndVarSimplify/tripcount_compute.ll | 162 + .../IndVarSimplify/tripcount_infinite.ll | 38 + final/test/Transforms/IndVarSimplify/udiv.ll | 162 + .../test/Transforms/IndVarSimplify/uglygep.ll | 40 + .../IndVarSimplify/variable-stride-ivs-0.ll | 43 + .../IndVarSimplify/variable-stride-ivs-1.ll | 43 + .../Inline/2003-09-14-InlineValue.ll | 21 + .../Inline/2003-09-22-PHINodeInlineFail.ll | 16 + .../2003-09-22-PHINodesInExceptionDest.ll | 25 + .../2003-09-22-PHINodesInNormalInvokeDest.ll | 23 + .../2003-10-13-AllocaDominanceProblem.ll | 19 + ...2003-10-26-InlineInvokeExceptionDestPhi.ll | 20 + .../Inline/2004-04-15-InlineDeletesCall.ll | 20 + .../Inline/2004-04-20-InlineLinkOnce.ll | 11 + .../2004-10-17-InlineFunctionWithoutReturn.ll | 11 + .../Inline/2006-01-14-CallGraphUpdate.ll | 25 + .../Inline/2006-07-12-InlinePruneCGUpdate.ll | 840 + .../Inline/2006-11-09-InlineCGUpdate-2.ll | 245 + .../Inline/2006-11-09-InlineCGUpdate.ll | 338 + .../Transforms/Inline/2007-04-15-InlineEH.ll | 49 + .../Transforms/Inline/2007-06-06-NoInline.ll | 46 + .../Inline/2007-06-25-WeakInline.ll | 14 + .../Inline/2007-12-19-InlineNoUnwind.ll | 19 + .../Transforms/Inline/2008-03-04-StructRet.ll | 28 + .../Transforms/Inline/2008-03-07-Inline-2.ll | 53 + .../Transforms/Inline/2008-03-07-Inline.ll | 57 + .../Inline/2008-09-02-AlwaysInline.ll | 10 + .../Transforms/Inline/2008-09-02-NoInline.ll | 10 + .../Inline/2008-10-30-AlwaysInline.ll | 14 + .../Inline/2008-11-04-AlwaysInline.ll | 7 + .../2009-01-08-NoInlineDynamicAlloca.ll | 36 + .../Inline/2009-01-13-RecursiveInlineCrash.ll | 293 + .../Inline/2009-05-07-CallUsingSelfCrash.ll | 20 + .../Transforms/Inline/2010-05-12-ValueMap.ll | 28 + .../Inline/2010-05-31-ByvalTailcall.ll | 24 + final/test/Transforms/Inline/PR4909.ll | 15 + final/test/Transforms/Inline/alloca-in-scc.ll | 31 + final/test/Transforms/Inline/alloca_test.ll | 23 + .../Inline/always_inline_dyn_alloca.ll | 15 + final/test/Transforms/Inline/array_merge.ll | 26 + final/test/Transforms/Inline/basictest.ll | 47 + final/test/Transforms/Inline/byval.ll | 106 + .../Transforms/Inline/callgraph-update.ll | 33 + final/test/Transforms/Inline/casts.ll | 19 + .../Transforms/Inline/cfg_preserve_test.ll | 16 + final/test/Transforms/Inline/crash.ll | 119 + final/test/Transforms/Inline/crash2.ll | 29 + final/test/Transforms/Inline/delete-call.ll | 22 + .../test/Transforms/Inline/devirtualize-2.ll | 44 + .../test/Transforms/Inline/devirtualize-3.ll | 79 + final/test/Transforms/Inline/devirtualize.ll | 182 + final/test/Transforms/Inline/dg.exp | 3 + .../Transforms/Inline/dynamic_alloca_test.ll | 35 + .../Transforms/Inline/externally_available.ll | 16 + .../Transforms/Inline/gvn-inline-iteration.ll | 23 + .../Transforms/Inline/inline-invoke-tail.ll | 35 + final/test/Transforms/Inline/inline-tail.ll | 15 + .../test/Transforms/Inline/inline_cleanup.ll | 63 + .../Transforms/Inline/inline_constprop.ll | 14 + final/test/Transforms/Inline/inline_dce.ll | 25 + final/test/Transforms/Inline/inline_prune.ll | 45 + final/test/Transforms/Inline/invoke_test-1.ll | 24 + final/test/Transforms/Inline/invoke_test-2.ll | 30 + final/test/Transforms/Inline/invoke_test-3.ll | 32 + final/test/Transforms/Inline/nested-inline.ll | 111 + .../Inline/noinline-recursive-fn.ll | 73 + final/test/Transforms/Inline/noinline.ll | 18 + .../InstCombine/2002-03-11-InstCombineHang.ll | 9 + .../InstCombine/2002-05-14-SubFailure.ll | 10 + .../InstCombine/2002-08-02-CastTest.ll | 11 + .../InstCombine/2002-12-05-MissedConstProp.ll | 11 + .../InstCombine/2003-05-26-CastMiscompile.ll | 8 + .../InstCombine/2003-05-27-ConstExprCrash.ll | 10 + .../2003-06-05-BranchInvertInfLoop.ll | 16 + .../2003-07-21-ExternalConstant.ll | 44 + .../InstCombine/2003-08-12-AllocaNonNull.ll | 20 + .../2003-09-09-VolatileLoadElim.ll | 7 + .../InstCombine/2003-10-29-CallSiteResolve.ll | 15 + .../InstCombine/2003-11-03-VarargsCallBug.ll | 13 + .../2004-01-13-InstCombineInvokePHI.ll | 28 + .../2004-02-23-ShiftShiftOverflow.ll | 15 + .../2004-03-13-InstCombineInfLoop.ll | 13 + ...004-04-04-InstCombineReplaceAllUsesWith.ll | 10 + .../InstCombine/2004-05-07-UnsizedCastLoad.ll | 10 + .../InstCombine/2004-07-27-ConstantExprMul.ll | 9 + .../InstCombine/2004-08-09-RemInfLoop.ll | 9 + .../InstCombine/2004-08-10-BoolSetCC.ll | 8 + .../InstCombine/2004-09-20-BadLoadCombine.ll | 18 + .../InstCombine/2004-09-20-BadLoadCombine2.ll | 25 + .../2004-09-28-BadShiftAndSetCC.ll | 9 + .../InstCombine/2004-11-22-Missed-and-fold.ll | 10 + ...004-11-27-SetCCForCastLargerAndConstant.ll | 192 + .../InstCombine/2004-12-08-RemInfiniteLoop.ll | 7 + .../InstCombine/2005-03-04-ShiftOverflow.ll | 9 + .../InstCombine/2005-04-07-UDivSelectCrash.ll | 8 + .../InstCombine/2005-06-15-DivSelectCrash.ll | 10 + .../InstCombine/2005-06-15-ShiftSetCCCrash.ll | 9 + .../InstCombine/2005-06-16-RangeCrash.ll | 9 + .../2005-06-16-SetCCOrSetCCMiscompile.ll | 14 + .../InstCombine/2005-07-07-DeadPHILoop.ll | 14 + .../2006-02-13-DemandedMiscompile.ll | 10 + .../InstCombine/2006-02-28-Crash.ll | 8 + .../InstCombine/2006-03-30-ExtractElement.ll | 8 + .../2006-04-28-ShiftShiftLongLong.ll | 13 + .../2006-05-04-DemandedBitCrash.ll | 51 + .../InstCombine/2006-09-15-CastToBool.ll | 14 + ...06-10-19-SignedToUnsignedCastAndConst-2.ll | 10 + .../Transforms/InstCombine/2006-10-20-mask.ll | 11 + .../InstCombine/2006-10-26-VectorReassoc.ll | 9 + .../InstCombine/2006-11-03-Memmove64.ll | 16 + .../InstCombine/2006-11-10-ashr-miscompile.ll | 9 + .../2006-12-01-BadFPVectorXform.ll | 9 + .../InstCombine/2006-12-05-fp-to-int-ext.ll | 12 + .../2006-12-08-Phi-ICmp-Op-Fold.ll | 51 + .../InstCombine/2006-12-08-Select-ICmp.ll | 41 + .../InstCombine/2006-12-15-Range-Test.ll | 31 + .../InstCombine/2006-12-23-Select-Cmp-Cmp.ll | 30 + .../2007-01-13-ExtCompareMiscompile.ll | 10 + .../InstCombine/2007-01-14-FcmpSelf.ll | 6 + .../InstCombine/2007-01-18-VectorInfLoop.ll | 7 + .../InstCombine/2007-01-27-AndICmp.ll | 8 + .../InstCombine/2007-02-01-LoadSinkAlloca.ll | 45 + .../InstCombine/2007-02-07-PointerCast.ll | 22 + .../InstCombine/2007-02-23-PhiFoldInfLoop.ll | 31 + .../InstCombine/2007-03-13-CompareMerge.ll | 9 + .../2007-03-19-BadTruncChangePR1261.ll | 10 + .../InstCombine/2007-03-21-SignedRangeTest.ll | 7 + .../InstCombine/2007-03-25-BadShiftMask.ll | 29 + .../InstCombine/2007-03-25-DoubleShift.ll | 9 + .../InstCombine/2007-03-26-BadShiftMask.ll | 35 + .../2007-04-04-BadFoldBitcastIntoMalloc.ll | 19 + .../2007-04-08-SingleEltVectorCrash.ll | 7 + .../InstCombine/2007-05-04-Crash.ll | 30 + .../InstCombine/2007-05-10-icmp-or.ll | 8 + .../InstCombine/2007-05-14-Crash.ll | 18 + .../InstCombine/2007-05-18-CastFoldBug.ll | 10 + .../InstCombine/2007-06-06-AshrSignBit.ll | 22 + .../2007-06-21-DivCompareMiscomp.ll | 9 + .../InstCombine/2007-08-02-InfiniteLoop.ll | 10 + .../InstCombine/2007-09-10-AliasConstFold.ll | 13 + .../InstCombine/2007-09-11-Trampoline.ll | 24 + .../InstCombine/2007-09-17-AliasConstFold2.ll | 14 + .../InstCombine/2007-10-10-EliminateMemCpy.ll | 21 + .../InstCombine/2007-10-12-Crash.ll | 38 + .../InstCombine/2007-10-28-stacksave.ll | 47 + .../InstCombine/2007-10-31-RangeCrash.ll | 35 + .../InstCombine/2007-10-31-StringCrash.ll | 21 + .../2007-11-07-OpaqueAlignCrash.ll | 22 + .../InstCombine/2007-11-15-CompareMiscomp.ll | 10 + .../InstCombine/2007-11-22-IcmpCrash.ll | 16 + .../2007-11-25-CompatibleAttributes.ll | 12 + .../2007-12-10-ConstFoldCompare.ll | 9 + .../InstCombine/2007-12-12-GEPScale.ll | 10 + .../InstCombine/2007-12-16-AsmNoUnwind.ll | 7 + .../InstCombine/2007-12-18-AddSelCmpSub.ll | 29 + .../InstCombine/2007-12-28-IcmpSub2.ll | 89 + .../2008-01-06-BitCastAttributes.ll | 23 + .../InstCombine/2008-01-06-CastCrash.ll | 10 + .../InstCombine/2008-01-06-VoidCast.ll | 10 + .../InstCombine/2008-01-13-AndCmpCmp.ll | 9 + .../2008-01-13-NoBitCastAttributes.ll | 15 + .../InstCombine/2008-01-14-DoubleNest.ll | 24 + .../2008-01-14-VarArgTrampoline.ll | 24 + .../2008-01-21-MismatchedCastAndCompare.ll | 20 + .../InstCombine/2008-01-21-MulTrunc.ll | 17 + .../InstCombine/2008-01-27-FloatSelect.ll | 7 + .../InstCombine/2008-01-29-AddICmp.ll | 20 + .../InstCombine/2008-02-13-MulURem.ll | 8 + .../InstCombine/2008-02-16-SDivOverflow.ll | 14 + .../InstCombine/2008-02-16-SDivOverflow2.ll | 9 + .../InstCombine/2008-02-23-MulSub.ll | 9 + .../InstCombine/2008-02-28-OrFCmpCrash.ll | 16 + .../InstCombine/2008-03-13-IntToPtr.ll | 9 + .../InstCombine/2008-04-22-ByValBitcast.ll | 15 + .../InstCombine/2008-04-28-VolatileStore.ll | 8 + .../2008-04-29-VolatileLoadDontMerge.ll | 25 + .../2008-04-29-VolatileLoadMerge.ll | 21 + .../InstCombine/2008-05-08-LiveStoreDelete.ll | 25 + .../InstCombine/2008-05-08-StrLenSink.ll | 32 + .../InstCombine/2008-05-09-SinkOfInvoke.ll | 33 + .../InstCombine/2008-05-17-InfLoop.ll | 23 + .../InstCombine/2008-05-18-FoldIntToPtr.ll | 13 + .../InstCombine/2008-05-22-IDivVector.ll | 6 + .../InstCombine/2008-05-22-NegValVector.ll | 8 + .../InstCombine/2008-05-23-CompareFold.ll | 11 + .../InstCombine/2008-05-31-AddBool.ll | 7 + .../InstCombine/2008-05-31-Bools.ll | 24 + .../InstCombine/2008-06-05-ashr-crash.ll | 7 + .../InstCombine/2008-06-08-ICmpPHI.ll | 47 + .../2008-06-13-InfiniteLoopStore.ll | 20 + .../2008-06-13-ReadOnlyCallStore.ll | 19 + .../InstCombine/2008-06-19-UncondLoad.ll | 16 + .../InstCombine/2008-06-21-CompareMiscomp.ll | 11 + .../InstCombine/2008-06-24-StackRestore.ll | 39 + .../InstCombine/2008-07-08-AndICmp.ll | 10 + .../InstCombine/2008-07-08-ShiftOneAndOne.ll | 10 + .../InstCombine/2008-07-08-SubAnd.ll | 9 + .../2008-07-08-VolatileLoadMerge.ll | 26 + .../InstCombine/2008-07-09-SubAndError.ll | 9 + .../InstCombine/2008-07-10-CastSextBool.ll | 17 + .../InstCombine/2008-07-10-ICmpBinOp.ll | 19 + .../InstCombine/2008-07-11-RemAnd.ll | 9 + .../InstCombine/2008-07-13-DivZero.ll | 16 + .../Transforms/InstCombine/2008-07-16-fsub.ll | 8 + .../InstCombine/2008-07-16-sse2_storel_dq.ll | 13 + .../Transforms/InstCombine/2008-08-05-And.ll | 23 + .../InstCombine/2008-08-17-ICmpXorSignbit.ll | 41 + .../InstCombine/2008-09-02-VectorCrash.ll | 27 + .../InstCombine/2008-09-29-FoldingOr.ll | 10 + .../InstCombine/2008-10-11-DivCompareFold.ll | 8 + .../2008-10-23-ConstFoldWithoutMask.ll | 8 + .../2008-11-01-SRemDemandedBits.ll | 8 + .../Transforms/InstCombine/2008-11-08-FCmp.ll | 47 + .../InstCombine/2008-11-20-DivMulRem.ll | 67 + .../InstCombine/2008-11-27-IDivVector.ll | 11 + .../InstCombine/2008-11-27-MultiplyIntVec.ll | 11 + .../InstCombine/2008-11-27-UDivNegative.ll | 6 + .../InstCombine/2008-12-17-SRemNegConstVec.ll | 7 + .../InstCombine/2009-01-05-i128-crash.ll | 27 + .../InstCombine/2009-01-08-AlignAlloca.ll | 28 + .../2009-01-16-PointerAddrSpace.ll | 11 + ...2009-01-19-fmod-constant-float-specials.ll | 315 + .../2009-01-19-fmod-constant-float.ll | 75 + .../InstCombine/2009-01-24-EmptyStruct.ll | 18 + .../InstCombine/2009-01-31-InfIterate.ll | 22 + .../InstCombine/2009-01-31-Pressure.ll | 22 + .../InstCombine/2009-02-04-FPBitcast.ll | 12 + .../2009-02-20-InstCombine-SROA.ll | 278 + .../InstCombine/2009-02-21-LoadCST.ll | 12 + .../2009-02-25-CrashZeroSizeArray.ll | 38 + .../2009-03-18-vector-ashr-crash.ll | 11 + .../InstCombine/2009-03-20-AShrOverShift.ll | 9 + .../InstCombine/2009-03-24-InfLoop.ll | 9 + .../InstCombine/2009-04-07-MulPromoteToI96.ll | 13 + .../InstCombine/2009-05-23-FCmpToICmp.ll | 9 + .../InstCombine/2009-06-11-StoreAddrSpace.ll | 7 + .../2009-06-16-SRemDemandedBits.ll | 9 + .../InstCombine/2009-07-02-MaskedIntVector.ll | 15 + .../InstCombine/2009-12-17-CmpSelectNull.ll | 16 + .../InstCombine/2010-01-28-NegativeSRem.ll | 19 + .../InstCombine/2010-03-03-ExtElim.ll | 18 + .../InstCombine/2010-11-01-lshr-mask.ll | 46 + .../InstCombine/2010-11-21-SizeZeroTypeGEP.ll | 17 + .../InstCombine/2010-11-23-Distributed.ll | 23 + .../InstCombine/2011-02-14-InfLoop.ll | 19 + .../2011-02-16-InsertelementHang.ll | 11 + .../Transforms/InstCombine/CPP_min_max.ll | 34 + .../test/Transforms/InstCombine/IntPtrCast.ll | 10 + .../Transforms/InstCombine/JavaCompare.ll | 14 + final/test/Transforms/InstCombine/README.txt | 4 + .../test/Transforms/InstCombine/add-shrink.ll | 14 + .../test/Transforms/InstCombine/add-sitofp.ll | 9 + final/test/Transforms/InstCombine/add.ll | 301 + final/test/Transforms/InstCombine/add2.ll | 43 + final/test/Transforms/InstCombine/add3.ll | 21 + .../test/Transforms/InstCombine/addnegneg.ll | 12 + .../InstCombine/adjust-for-sminmax.ll | 85 + .../Transforms/InstCombine/align-2d-gep.ll | 44 + .../test/Transforms/InstCombine/align-addr.ll | 60 + .../Transforms/InstCombine/align-external.ll | 22 + final/test/Transforms/InstCombine/alloca.ll | 46 + .../Transforms/InstCombine/and-compare.ll | 11 + final/test/Transforms/InstCombine/and-fcmp.ll | 34 + .../test/Transforms/InstCombine/and-not-or.ll | 34 + .../test/Transforms/InstCombine/and-or-and.ll | 61 + .../test/Transforms/InstCombine/and-or-not.ll | 46 + final/test/Transforms/InstCombine/and-or.ll | 39 + .../Transforms/InstCombine/and-xor-merge.ll | 19 + final/test/Transforms/InstCombine/and.ll | 255 + final/test/Transforms/InstCombine/and2.ll | 37 + .../test/Transforms/InstCombine/apint-add1.ll | 34 + .../test/Transforms/InstCombine/apint-add2.ll | 46 + .../InstCombine/apint-and-compare.ll | 16 + .../InstCombine/apint-and-or-and.ll | 50 + .../InstCombine/apint-and-xor-merge.ll | 22 + .../test/Transforms/InstCombine/apint-and1.ll | 57 + .../test/Transforms/InstCombine/apint-and2.ll | 82 + .../InstCombine/apint-call-cast-target.ll | 17 + .../InstCombine/apint-cast-and-cast.ll | 15 + .../InstCombine/apint-cast-cast-to-and.ll | 8 + .../test/Transforms/InstCombine/apint-cast.ll | 30 + .../test/Transforms/InstCombine/apint-div1.ll | 22 + .../test/Transforms/InstCombine/apint-div2.ll | 22 + .../test/Transforms/InstCombine/apint-mul1.ll | 11 + .../test/Transforms/InstCombine/apint-mul2.ll | 12 + .../test/Transforms/InstCombine/apint-not.ll | 42 + .../test/Transforms/InstCombine/apint-or1.ll | 36 + .../test/Transforms/InstCombine/apint-or2.ll | 35 + .../test/Transforms/InstCombine/apint-rem1.ll | 22 + .../test/Transforms/InstCombine/apint-rem2.ll | 22 + .../Transforms/InstCombine/apint-select.ll | 44 + .../InstCombine/apint-shift-simplify.ll | 23 + .../Transforms/InstCombine/apint-shift.ll | 184 + .../Transforms/InstCombine/apint-shl-trunc.ll | 14 + .../test/Transforms/InstCombine/apint-sub.ll | 141 + .../test/Transforms/InstCombine/apint-xor1.ll | 50 + .../test/Transforms/InstCombine/apint-xor2.ll | 51 + .../Transforms/InstCombine/apint-zext1.ll | 11 + .../Transforms/InstCombine/apint-zext2.ll | 11 + final/test/Transforms/InstCombine/ashr-nop.ll | 8 + .../test/Transforms/InstCombine/badmalloc.ll | 20 + .../test/Transforms/InstCombine/binop-cast.ll | 9 + .../test/Transforms/InstCombine/bit-checks.ll | 372 + .../Transforms/InstCombine/bit-tracking.ll | 26 + .../InstCombine/bitcast-sext-vector.ll | 11 + .../Transforms/InstCombine/bitcast-store.ll | 21 + .../InstCombine/bitcast-vec-canon.ll | 22 + .../InstCombine/bitcast-vec-uniform.ll | 70 + .../InstCombine/bitcast-vector-fold.ll | 33 + final/test/Transforms/InstCombine/bitcast.ll | 105 + final/test/Transforms/InstCombine/bitcount.ll | 19 + final/test/Transforms/InstCombine/bittest.ll | 30 + .../test/Transforms/InstCombine/bswap-fold.ll | 75 + final/test/Transforms/InstCombine/bswap.ll | 74 + .../InstCombine/call-cast-target.ll | 14 + .../Transforms/InstCombine/call-intrinsics.ll | 19 + final/test/Transforms/InstCombine/call.ll | 132 + final/test/Transforms/InstCombine/call2.ll | 27 + .../InstCombine/canonicalize_branch.ll | 44 + .../Transforms/InstCombine/cast-mul-select.ll | 41 + final/test/Transforms/InstCombine/cast-set.ll | 65 + final/test/Transforms/InstCombine/cast.ll | 651 + final/test/Transforms/InstCombine/cast_ptr.ll | 79 + .../Transforms/InstCombine/compare-signs.ll | 58 + .../InstCombine/constant-fold-compare.ll | 8 + .../InstCombine/constant-fold-gep.ll | 74 + final/test/Transforms/InstCombine/crash.ll | 372 + .../Transforms/InstCombine/dce-iterate.ll | 24 + final/test/Transforms/InstCombine/deadcode.ll | 24 + final/test/Transforms/InstCombine/dg.exp | 3 + final/test/Transforms/InstCombine/div.ll | 84 + .../InstCombine/enforce-known-alignment.ll | 18 + final/test/Transforms/InstCombine/exact.ll | 154 + .../Transforms/InstCombine/extractvalue.ll | 107 + .../Transforms/InstCombine/fcmp-select.ll | 53 + .../Transforms/InstCombine/fcmp-special.ll | 155 + .../InstCombine/fold-bin-operand.ll | 14 + .../test/Transforms/InstCombine/fold-calls.ll | 19 + .../InstCombine/fold-vector-select.ll | 13 + .../InstCombine/fold-vector-zero.ll | 35 + .../Transforms/InstCombine/fp-ret-bitcast.ll | 28 + final/test/Transforms/InstCombine/fpcast.ll | 15 + final/test/Transforms/InstCombine/fpextend.ll | 36 + final/test/Transforms/InstCombine/fsub.ll | 23 + final/test/Transforms/InstCombine/gepgep.ll | 13 + .../Transforms/InstCombine/getelementptr.ll | 479 + .../Transforms/InstCombine/hoist_instr.ll | 18 + final/test/Transforms/InstCombine/icmp.ll | 496 + final/test/Transforms/InstCombine/idioms.ll | 32 + .../test/Transforms/InstCombine/intrinsics.ll | 190 + .../test/Transforms/InstCombine/invariant.ll | 16 + .../Transforms/InstCombine/known_align.ll | 27 + final/test/Transforms/InstCombine/load-cmp.ll | 112 + .../Transforms/InstCombine/load-select.ll | 16 + final/test/Transforms/InstCombine/load.ll | 98 + final/test/Transforms/InstCombine/load3.ll | 27 + .../InstCombine/loadstore-alignment.ll | 67 + .../Transforms/InstCombine/logical-select.ll | 68 + final/test/Transforms/InstCombine/lshr-phi.ll | 35 + .../InstCombine/malloc-free-delete.ll | 25 + final/test/Transforms/InstCombine/malloc.ll | 7 + final/test/Transforms/InstCombine/malloc2.ll | 22 + final/test/Transforms/InstCombine/malloc3.ll | 26 + .../Transforms/InstCombine/memcpy-to-load.ll | 14 + final/test/Transforms/InstCombine/memcpy.ll | 19 + final/test/Transforms/InstCombine/memmove.ll | 42 + final/test/Transforms/InstCombine/memset.ll | 15 + final/test/Transforms/InstCombine/memset2.ll | 15 + .../test/Transforms/InstCombine/memset_chk.ll | 18 + .../Transforms/InstCombine/mul-masked-bits.ll | 10 + final/test/Transforms/InstCombine/mul.ll | 116 + .../Transforms/InstCombine/multi-use-or.ll | 24 + final/test/Transforms/InstCombine/narrow.ll | 18 + .../Transforms/InstCombine/neon-intrinsics.ll | 25 + .../test/Transforms/InstCombine/no-negzero.ll | 33 + final/test/Transforms/InstCombine/not-fcmp.ll | 10 + final/test/Transforms/InstCombine/not.ll | 54 + final/test/Transforms/InstCombine/nothrow.ll | 8 + final/test/Transforms/InstCombine/nsw.ll | 39 + final/test/Transforms/InstCombine/objsize.ll | 162 + .../Transforms/InstCombine/odr-linkage.ll | 19 + final/test/Transforms/InstCombine/or-fcmp.ll | 58 + .../test/Transforms/InstCombine/or-to-xor.ll | 42 + final/test/Transforms/InstCombine/or-xor.ll | 94 + final/test/Transforms/InstCombine/or.ll | 392 + final/test/Transforms/InstCombine/overflow.ll | 133 + .../Transforms/InstCombine/phi-merge-gep.ll | 102 + final/test/Transforms/InstCombine/phi.ll | 546 + final/test/Transforms/InstCombine/pr2645-0.ll | 33 + final/test/Transforms/InstCombine/pr2645-1.ll | 39 + final/test/Transforms/InstCombine/pr2996.ll | 12 + final/test/Transforms/InstCombine/pr8547.ll | 26 + .../InstCombine/preserve-sminmax.ll | 32 + .../Transforms/InstCombine/ptr-int-cast.ll | 29 + final/test/Transforms/InstCombine/rem.ll | 88 + final/test/Transforms/InstCombine/sdiv-1.ll | 22 + final/test/Transforms/InstCombine/sdiv-2.ll | 28 + .../test/Transforms/InstCombine/sdiv-shift.ll | 9 + final/test/Transforms/InstCombine/select-2.ll | 18 + .../Transforms/InstCombine/select-crash.ll | 20 + .../InstCombine/select-load-call.ll | 15 + final/test/Transforms/InstCombine/select.ll | 726 + final/test/Transforms/InstCombine/set.ll | 171 + .../InstCombine/setcc-strength-reduce.ll | 37 + final/test/Transforms/InstCombine/sext.ll | 128 + .../test/Transforms/InstCombine/shift-sra.ll | 78 + final/test/Transforms/InstCombine/shift.ll | 487 + .../InstCombine/shufflemask-undef.ll | 109 + .../InstCombine/shufflevec-constant.ll | 14 + .../InstCombine/signed-comparison.ll | 28 + final/test/Transforms/InstCombine/signext.ll | 87 + .../simplify-demanded-bits-pointer.ll | 84 + .../InstCombine/sink_instruction.ll | 56 + final/test/Transforms/InstCombine/sitofp.ll | 55 + final/test/Transforms/InstCombine/sqrt.ll | 32 + .../InstCombine/srem-simplify-bug.ll | 9 + final/test/Transforms/InstCombine/srem.ll | 8 + final/test/Transforms/InstCombine/srem1.ll | 18 + .../Transforms/InstCombine/stack-overalign.ll | 29 + .../InstCombine/stacksaverestore.ll | 56 + final/test/Transforms/InstCombine/store.ll | 85 + .../test/Transforms/InstCombine/strcpy_chk.ll | 13 + final/test/Transforms/InstCombine/sub.ll | 303 + final/test/Transforms/InstCombine/trunc.ll | 119 + .../InstCombine/udiv-simplify-bug-0.ll | 14 + .../InstCombine/udiv-simplify-bug-1.ll | 20 + .../udiv_select_to_select_shift.ll | 17 + .../InstCombine/udivrem-change-width.ll | 21 + .../InstCombine/urem-simplify-bug.ll | 32 + final/test/Transforms/InstCombine/urem.ll | 8 + .../InstCombine/vec_demanded_elts.ll | 138 + .../Transforms/InstCombine/vec_extract_elt.ll | 9 + .../Transforms/InstCombine/vec_insertelt.ll | 7 + .../test/Transforms/InstCombine/vec_narrow.ll | 12 + final/test/Transforms/InstCombine/vec_sext.ll | 22 + .../Transforms/InstCombine/vec_shuffle.ll | 112 + .../Transforms/InstCombine/vector-casts.ll | 151 + .../Transforms/InstCombine/vector-srem.ll | 9 + .../Transforms/InstCombine/volatile_store.ll | 14 + .../test/Transforms/InstCombine/xor-undef.ll | 6 + final/test/Transforms/InstCombine/xor.ll | 193 + final/test/Transforms/InstCombine/xor2.ll | 53 + .../InstCombine/zero-point-zero-add.ll | 15 + .../InstCombine/zeroext-and-reduce.ll | 10 + .../InstCombine/zext-bool-add-sub.ll | 29 + .../test/Transforms/InstCombine/zext-fold.ll | 12 + .../Transforms/InstCombine/zext-or-icmp.ll | 35 + final/test/Transforms/InstCombine/zext.ll | 11 + .../InstSimplify/2010-12-20-Boolean.ll | 29 + .../InstSimplify/2010-12-20-Distribute.ll | 62 + .../InstSimplify/2011-01-14-Thread.ll | 9 + .../InstSimplify/2011-02-01-Vector.ll | 8 + final/test/Transforms/InstSimplify/compare.ll | 295 + final/test/Transforms/InstSimplify/dg.exp | 3 + .../Transforms/InstSimplify/exact-nsw-nuw.ll | 44 + final/test/Transforms/InstSimplify/fdiv.ll | 17 + .../Transforms/InstSimplify/reassociate.ll | 186 + .../Internalize/2008-05-09-AllButMain.ll | 27 + .../2008-05-09-AllButMain.ll.apifile | 2 + .../2009-01-05-InternalizeAliases.ll | 10 + .../Internalize/available_externally.ll | 16 + final/test/Transforms/Internalize/dg.exp | 3 + .../JumpThreading/2008-11-27-EntryMunge.ll | 13 + .../JumpThreading/2010-08-26-and.ll | 162 + .../Transforms/JumpThreading/and-and-cond.ll | 37 + .../test/Transforms/JumpThreading/and-cond.ll | 35 + final/test/Transforms/JumpThreading/basic.ll | 478 + .../JumpThreading/branch-no-const.ll | 21 + .../test/Transforms/JumpThreading/compare.ll | 30 + final/test/Transforms/JumpThreading/crash.ll | 513 + .../JumpThreading/degenerate-phi.ll | 24 + final/test/Transforms/JumpThreading/dg.exp | 3 + .../Transforms/JumpThreading/indirectbr.ll | 94 + .../test/Transforms/JumpThreading/lvi-load.ll | 49 + .../JumpThreading/no-irreducible-loops.ll | 38 + .../test/Transforms/JumpThreading/or-undef.ll | 69 + final/test/Transforms/JumpThreading/select.ll | 123 + .../Transforms/JumpThreading/thread-loads.ll | 41 + .../LCSSA/2006-06-03-IncorrectIDFPhis.ll | 23 + .../2006-06-12-MultipleExitsSameBlock.ll | 27 + .../LCSSA/2006-07-09-NoDominator.ll | 24 + .../LCSSA/2006-10-31-UnreachableBlock-2.ll | 145 + .../LCSSA/2006-10-31-UnreachableBlock.ll | 184 + .../Transforms/LCSSA/2007-07-12-LICM-2.ll | 17 + .../Transforms/LCSSA/2007-07-12-LICM-3.ll | 24 + .../test/Transforms/LCSSA/2007-07-12-LICM.ll | 14 + final/test/Transforms/LCSSA/basictest.ll | 24 + final/test/Transforms/LCSSA/dg.exp | 3 + final/test/Transforms/LCSSA/indirectbr.ll | 542 + final/test/Transforms/LCSSA/invoke-dest.ll | 143 + .../test/Transforms/LCSSA/unreachable-use.ll | 27 + .../LICM/2003-02-26-LoopExitNotDominated.ll | 18 + .../LICM/2003-02-27-NestedLoopExitBlocks.ll | 17 + .../2003-02-27-PreheaderExitNodeUpdate.ll | 16 + .../LICM/2003-02-27-PreheaderProblem.ll | 24 + .../LICM/2003-02-27-StoreSinkPHIs.ll | 15 + .../LICM/2003-02-28-PromoteDifferentType.ll | 15 + .../Transforms/LICM/2003-05-02-LoadHoist.ll | 23 + .../LICM/2003-12-11-SinkingToPHI.ll | 16 + .../2004-09-14-AliasAnalysisInvalidate.ll | 19 + .../LICM/2004-11-17-UndefIndexCrash.ll | 20 + .../LICM/2005-03-24-LICM-Aggregate-Crash.ll | 9 + .../LICM/2006-09-12-DeadUserOfSunkInstr.ll | 148 + .../LICM/2007-05-22-VolatileSink.ll | 56 + .../Transforms/LICM/2007-07-30-AliasSet.ll | 39 + .../LICM/2007-09-17-PromoteValue.ll | 61 + .../LICM/2007-09-24-PromoteNullValue.ll | 46 + .../LICM/2007-10-01-PromoteSafeValue.ll | 21 + .../LICM/2008-05-20-AliasSetVAArg.ll | 30 + .../LICM/2008-07-22-LoadGlobalConstant.ll | 39 + .../LICM/2009-12-10-LICM-Indbr-Crash.ll | 21 + final/test/Transforms/LICM/Preserve-LCSSA.ll | 25 + final/test/Transforms/LICM/basictest.ll | 15 + final/test/Transforms/LICM/crash.ll | 74 + final/test/Transforms/LICM/dg.exp | 3 + final/test/Transforms/LICM/hoisting.ll | 66 + .../test/Transforms/LICM/no-preheader-test.ll | 20 + final/test/Transforms/LICM/scalar_promote.ll | 150 + final/test/Transforms/LICM/sinking.ll | 249 + .../LoopDeletion/2007-07-23-InfiniteLoop.ll | 13 + .../Transforms/LoopDeletion/2008-05-06-Phi.ll | 109 + final/test/Transforms/LoopDeletion/dcetest.ll | 36 + final/test/Transforms/LoopDeletion/dg.exp | 3 + .../LoopDeletion/multiple-exit-conditions.ll | 27 + .../Transforms/LoopDeletion/multiple-exits.ll | 26 + .../LoopDeletion/simplify-then-delete.ll | 65 + final/test/Transforms/LoopIdiom/basic.ll | 349 + final/test/Transforms/LoopIdiom/debug-line.ll | 49 + final/test/Transforms/LoopIdiom/dg.exp | 3 + .../LoopRotate/2009-01-25-SingleEntryPhi.ll | 21 + .../test/Transforms/LoopRotate/PhiRename-1.ll | 95 + .../LoopRotate/PhiSelfRefernce-1.ll | 39 + final/test/Transforms/LoopRotate/basic.ll | 35 + final/test/Transforms/LoopRotate/crash.ll | 139 + final/test/Transforms/LoopRotate/dbgvalue.ll | 59 + final/test/Transforms/LoopRotate/dg.exp | 3 + .../test/Transforms/LoopRotate/indirectbr.ll | 43 + .../Transforms/LoopRotate/phi-duplicate.ll | 40 + final/test/Transforms/LoopRotate/pr2639.ll | 38 + .../Transforms/LoopRotate/preserve-scev.ll | 47 + .../LoopSimplify/2003-04-25-AssertFail.ll | 20 + .../2003-05-12-PreheaderExitOfChild.ll | 42 + .../LoopSimplify/2003-08-15-PreheadersFail.ll | 52 + .../2003-12-10-ExitBlocksProblem.ll | 36 + .../2004-02-05-DominatorInfoCorruption.ll | 14 + .../2004-03-15-IncorrectDomUpdate.ll | 11 + .../2004-04-01-IncorrectDomUpdate.ll | 20 + ...2004-04-12-LoopSimplify-SwitchBackedges.ll | 18 + ...004-04-13-LoopSimplifyUpdateDomFrontier.ll | 18 + .../LoopSimplify/2007-10-28-InvokeCrash.ll | 892 + .../2010-07-15-IncorrectDomFrontierUpdate.ll | 20 + .../2010-12-26-PHIInfiniteLoop.ll | 43 + .../test/Transforms/LoopSimplify/basictest.ll | 16 + final/test/Transforms/LoopSimplify/dg.exp | 3 + .../Transforms/LoopSimplify/hardertest.ll | 15 + .../LoopSimplify/indirectbr-backedge.ll | 35 + .../Transforms/LoopSimplify/indirectbr.ll | 100 + .../Transforms/LoopSimplify/merge-exits.ll | 44 + .../LoopSimplify/phi-node-simplify.ll | 55 + .../Transforms/LoopSimplify/preserve-scev.ll | 50 + .../LoopSimplify/single-backedge.ll | 20 + .../LoopSimplify/unreachable-loop-pred.ll | 20 + .../LoopStrengthReduce/2005-08-15-AddRecIV.ll | 57 + .../2005-08-17-OutOfLoopVariant.ll | 17 + .../2005-09-12-UsesOutOutsideOfLoop.ll | 32 + .../2007-04-23-UseIterator.ll | 71 + .../2008-08-13-CmpStride.ll | 31 + .../LoopStrengthReduce/2008-08-14-ShadowIV.ll | 99 + .../LoopStrengthReduce/2008-09-09-Overflow.ll | 48 + ...9-01-13-nonconstant-stride-outside-loop.ll | 39 + .../2009-04-28-no-reduce-mul.ll | 48 + .../LoopStrengthReduce/2009-11-10-LSRCrash.ll | 130 + .../LoopStrengthReduce/count-to-zero.ll | 42 + .../Transforms/LoopStrengthReduce/dead-phi.ll | 21 + .../test/Transforms/LoopStrengthReduce/dg.exp | 3 + .../LoopStrengthReduce/different-type-ivs.ll | 25 + .../dont-hoist-simple-loop-constants.ll | 23 + .../dont_insert_redundant_ops.ll | 36 + .../LoopStrengthReduce/dont_reduce_bytes.ll | 22 + .../LoopStrengthReduce/dont_reverse.ll | 21 + .../exit_compare_live_range.ll | 21 + .../hoist-parent-preheader.ll | 32 + .../invariant_value_first.ll | 23 + .../invariant_value_first_arg.ll | 20 + .../LoopStrengthReduce/nested-reduce.ll | 49 + .../LoopStrengthReduce/nonlinear-postinc.ll | 44 + .../LoopStrengthReduce/ops_after_indvar.ll | 24 + .../phi_node_update_multiple_preds.ll | 28 + .../Transforms/LoopStrengthReduce/pr2537.ll | 21 + .../Transforms/LoopStrengthReduce/pr2570.ll | 287 + .../Transforms/LoopStrengthReduce/pr3086.ll | 29 + .../Transforms/LoopStrengthReduce/pr3399.ll | 32 + .../Transforms/LoopStrengthReduce/pr3571.ll | 27 + .../quadradic-exit-value.ll | 18 + .../LoopStrengthReduce/related_indvars.ll | 27 + .../LoopStrengthReduce/remove_indvar.ll | 21 + .../share_code_in_preheader.ll | 27 + .../LoopStrengthReduce/share_ivs.ll | 24 + .../Transforms/LoopStrengthReduce/uglygep.ll | 66 + .../use_postinc_value_outside_loop.ll | 29 + .../var_stride_used_by_compare.ll | 41 + .../LoopStrengthReduce/variable_stride.ll | 18 + .../2004-05-13-DontUnrollTooMuch.ll | 14 + .../2005-03-06-BadLoopInfoUpdate.ll | 22 + .../LoopUnroll/2006-08-24-MultiBlockLoop.ll | 16 + .../LoopUnroll/2007-04-16-PhiUpdate.ll | 17 + .../LoopUnroll/2007-05-05-UnrollMiscomp.ll | 36 + .../LoopUnroll/2007-05-09-UnknownTripCount.ll | 18 + .../Transforms/LoopUnroll/2007-11-05-Crash.ll | 295 + final/test/Transforms/LoopUnroll/basic.ll | 24 + final/test/Transforms/LoopUnroll/dg.exp | 3 + .../LoopUnroll/shifted-tripcount.ll | 28 + .../LoopUnswitch/2006-06-13-SingleEntryPHI.ll | 35 + .../LoopUnswitch/2006-06-27-DeadSwitchCase.ll | 25 + .../LoopUnswitch/2007-05-09-Unreachable.ll | 28 + .../Transforms/LoopUnswitch/2007-05-09-tl.ll | 95 + .../LoopUnswitch/2007-07-12-ExitDomInfo.ll | 45 + .../LoopUnswitch/2007-07-13-DomInfo.ll | 27 + .../LoopUnswitch/2007-07-18-DomInfo.ll | 66 + .../Transforms/LoopUnswitch/2007-08-01-Dom.ll | 30 + .../LoopUnswitch/2007-08-01-LCSSA.ll | 55 + .../LoopUnswitch/2007-10-04-DomFrontier.ll | 29 + .../LoopUnswitch/2008-06-02-DomInfo.ll | 26 + .../LoopUnswitch/2008-06-17-DomFrontier.ll | 22 + .../LoopUnswitch/2008-11-03-Invariant.ll | 36 + .../LoopUnswitch/2010-11-18-LCSSA.ll | 28 + .../test/Transforms/LoopUnswitch/basictest.ll | 31 + final/test/Transforms/LoopUnswitch/crash.ll | 66 + final/test/Transforms/LoopUnswitch/dg.exp | 3 + .../Transforms/LoopUnswitch/infinite-loop.ll | 53 + .../LoopUnswitch/preserve-analyses.ll | 129 + .../Transforms/LowerAtomic/atomic-load.ll | 40 + .../Transforms/LowerAtomic/atomic-swap.ll | 26 + final/test/Transforms/LowerAtomic/barrier.ll | 10 + final/test/Transforms/LowerAtomic/dg.exp | 3 + .../LowerInvoke/2003-12-10-Crash.ll | 22 + .../LowerInvoke/2004-02-29-PHICrash.ll | 15 + .../LowerInvoke/2005-08-03-InvokeWithPHI.ll | 17 + .../2005-08-03-InvokeWithPHIUse.ll | 15 + .../2008-02-14-CritEdgePhiCrash.ll | 14 + .../test/Transforms/LowerInvoke/basictest.ll | 30 + final/test/Transforms/LowerInvoke/dg.exp | 3 + .../2003-11-05-DominanceProperties.ll | 16 + final/test/Transforms/LowerSetJmp/dg.exp | 3 + .../test/Transforms/LowerSetJmp/simpletest.ll | 32 + .../LowerSwitch/2003-05-01-PHIProblem.ll | 15 + .../LowerSwitch/2003-08-23-EmptySwitch.ll | 9 + .../2004-03-13-SwitchIsDefaultCrash.ll | 19 + final/test/Transforms/LowerSwitch/dg.exp | 3 + final/test/Transforms/LowerSwitch/feature.ll | 51 + .../Mem2Reg/2002-03-28-UninitializedVal.ll | 11 + .../2002-05-01-ShouldNotPromoteThisAlloca.ll | 12 + .../Mem2Reg/2003-04-10-DFNotFound.ll | 10 + .../Mem2Reg/2003-04-18-DeadBlockProblem.ll | 16 + .../2003-04-24-MultipleIdenticalSuccessors.ll | 16 + .../Mem2Reg/2003-06-26-IterativePromote.ll | 16 + .../Mem2Reg/2003-10-05-DeadPHIInsertion.ll | 22 + .../Mem2Reg/2005-06-30-ReadBeforeWrite.ll | 47 + .../Transforms/Mem2Reg/2005-11-28-Crash.ll | 62 + .../Mem2Reg/2007-08-27-VolatileLoadsStores.ll | 47 + .../Transforms/Mem2Reg/ConvertDebugInfo.ll | 45 + .../Transforms/Mem2Reg/ConvertDebugInfo2.ll | 52 + .../Mem2Reg/PromoteMemToRegister.ll | 18 + .../Transforms/Mem2Reg/UndefValuesMerge.ll | 13 + final/test/Transforms/Mem2Reg/crash.ll | 41 + final/test/Transforms/Mem2Reg/dg.exp | 3 + .../MemCpyOpt/2008-02-24-MultipleUseofSRet.ll | 34 + .../MemCpyOpt/2008-03-13-ReturnSlotBitcast.ll | 20 + final/test/Transforms/MemCpyOpt/align.ll | 19 + final/test/Transforms/MemCpyOpt/crash.ll | 58 + final/test/Transforms/MemCpyOpt/dg.exp | 3 + .../test/Transforms/MemCpyOpt/form-memset.ll | 222 + .../Transforms/MemCpyOpt/loadstore-sret.ll | 25 + .../Transforms/MemCpyOpt/memcpy-to-memset.ll | 19 + final/test/Transforms/MemCpyOpt/memcpy.ll | 111 + final/test/Transforms/MemCpyOpt/memmove.ll | 37 + final/test/Transforms/MemCpyOpt/smaller.ll | 28 + final/test/Transforms/MemCpyOpt/sret.ll | 28 + .../MergeFunc/2011-02-08-RemoveEqual.ll | 276 + final/test/Transforms/MergeFunc/dg.exp | 3 + final/test/Transforms/MergeFunc/fold-weak.ll | 17 + .../Transforms/MergeFunc/phi-speculation1.ll | 29 + .../Transforms/MergeFunc/phi-speculation2.ll | 29 + final/test/Transforms/MergeFunc/vector.ll | 76 + .../MergeFunc/vectors-and-arrays.ll | 18 + .../PruneEH/2003-09-14-ExternalCall.ll | 11 + .../PruneEH/2003-11-21-PHIUpdate.ll | 15 + .../Transforms/PruneEH/2008-06-02-Weak.ll | 12 + .../Transforms/PruneEH/2008-09-05-CGUpdate.ll | 1445 + final/test/Transforms/PruneEH/dg.exp | 3 + .../test/Transforms/PruneEH/recursivetest.ll | 20 + .../Transforms/PruneEH/simplenoreturntest.ll | 13 + final/test/Transforms/PruneEH/simpletest.ll | 19 + .../2002-05-15-AgressiveSubMove.ll | 9 + .../Reassociate/2002-05-15-MissedTree.ll | 9 + .../Reassociate/2002-05-15-SubReassociate.ll | 12 + .../Reassociate/2002-05-15-SubReassociate2.ll | 13 + .../2002-07-09-DominanceProblem.ll | 10 + .../Reassociate/2003-08-12-InfiniteLoop.ll | 9 + .../Reassociate/2005-08-24-Crash.ll | 13 + .../2005-09-01-ArrayOutOfBounds.ll | 23 + .../2006-04-27-ReassociateVector.ll | 8 + .../Reassociate/2011-01-26-UseAfterFree.ll | 35 + .../test/Transforms/Reassociate/basictest.ll | 216 + final/test/Transforms/Reassociate/crash.ll | 44 + final/test/Transforms/Reassociate/dg.exp | 3 + final/test/Transforms/Reassociate/inverses.ll | 34 + final/test/Transforms/Reassociate/looptest.ll | 50 + .../test/Transforms/Reassociate/mulfactor.ll | 14 + .../test/Transforms/Reassociate/mulfactor2.ll | 15 + final/test/Transforms/Reassociate/negation.ll | 21 + .../Transforms/Reassociate/optional-flags.ll | 29 + final/test/Transforms/Reassociate/otherops.ll | 28 + .../Transforms/Reassociate/shift-factor.ll | 12 + .../test/Transforms/Reassociate/shifttest.ll | 12 + final/test/Transforms/Reassociate/subtest.ll | 11 + final/test/Transforms/Reassociate/subtest2.ll | 13 + .../Transforms/SCCP/2002-05-02-EdgeFailure.ll | 26 + .../SCCP/2002-05-02-MissSecondInst.ll | 8 + .../SCCP/2002-05-20-MissedIncomingValue.ll | 19 + .../SCCP/2002-05-21-InvalidSimplify.ll | 33 + .../SCCP/2002-08-30-GetElementPtrTest.ll | 9 + .../SCCP/2003-06-24-OverdefinedPHIValue.ll | 30 + .../SCCP/2003-08-26-InvokeHandling.ll | 18 + .../Transforms/SCCP/2004-11-16-DeadInvoke.ll | 13 + .../SCCP/2004-12-10-UndefBranchBug.ll | 12 + .../SCCP/2006-10-23-IPSCCP-Crash.ll | 103 + .../Transforms/SCCP/2006-12-04-PackedType.ll | 140 + .../Transforms/SCCP/2006-12-19-UndefBug.ll | 8 + .../Transforms/SCCP/2007-05-16-InvokeCrash.ll | 41 + .../SCCP/2008-01-27-UndefCorrelate.ll | 36 + .../SCCP/2008-04-22-multiple-ret-sccp.ll | 11 + .../SCCP/2008-05-23-UndefCallFold.ll | 14 + .../SCCP/2009-01-14-IPSCCP-Invoke.ll | 28 + .../SCCP/2009-05-27-VectorOperandZero.ll | 10 + final/test/Transforms/SCCP/apint-array.ll | 23 + final/test/Transforms/SCCP/apint-basictest.ll | 16 + .../test/Transforms/SCCP/apint-basictest2.ll | 17 + .../test/Transforms/SCCP/apint-basictest3.ll | 23 + .../test/Transforms/SCCP/apint-basictest4.ll | 25 + final/test/Transforms/SCCP/apint-bigarray.ll | 23 + final/test/Transforms/SCCP/apint-bigint.ll | 9 + final/test/Transforms/SCCP/apint-bigint2.ll | 18 + final/test/Transforms/SCCP/apint-ipsccp1.ll | 24 + final/test/Transforms/SCCP/apint-ipsccp2.ll | 19 + final/test/Transforms/SCCP/apint-ipsccp3.ll | 23 + final/test/Transforms/SCCP/apint-ipsccp4.ll | 49 + final/test/Transforms/SCCP/apint-load.ll | 36 + final/test/Transforms/SCCP/apint-phi.ll | 19 + final/test/Transforms/SCCP/apint-select.ll | 21 + final/test/Transforms/SCCP/calltest.ll | 21 + final/test/Transforms/SCCP/crash.ll | 29 + final/test/Transforms/SCCP/dg.exp | 3 + .../test/Transforms/SCCP/ipsccp-addr-taken.ll | 28 + final/test/Transforms/SCCP/ipsccp-basic.ll | 206 + final/test/Transforms/SCCP/loadtest.ll | 33 + final/test/Transforms/SCCP/logical-nuke.ll | 9 + final/test/Transforms/SCCP/phitest.ll | 20 + final/test/Transforms/SCCP/retvalue-undef.ll | 32 + final/test/Transforms/SCCP/sccptest.ll | 58 + final/test/Transforms/SCCP/select.ll | 12 + final/test/Transforms/SCCP/undef-resolve.ll | 106 + .../SRETPromotion/2008-03-11-attributes.ll | 7 + .../2008-06-04-function-pointer-passing.ll | 24 + .../SRETPromotion/2008-06-05-non-call-use.ll | 20 + .../Transforms/SRETPromotion/basictest.ll | 33 + final/test/Transforms/SRETPromotion/dg.exp | 3 + .../ScalarRepl/2003-05-29-ArrayFail.ll | 13 + .../ScalarRepl/2003-09-12-IncorrectPromote.ll | 13 + .../ScalarRepl/2003-10-29-ArrayProblem.ll | 16 + .../2006-11-07-InvalidArrayPromote.ll | 20 + .../ScalarRepl/2007-05-24-LargeAggregate.ll | 27 + .../ScalarRepl/2007-05-29-MemcpyPreserve.ll | 23 + .../ScalarRepl/2007-11-03-bigendian_apint.ll | 30 + .../ScalarRepl/2008-01-29-PromoteBug.ll | 21 + .../2008-02-28-SubElementExtractCrash.ll | 16 + .../ScalarRepl/2008-06-05-loadstore-agg.ll | 33 + .../ScalarRepl/2008-06-22-LargeArray.ll | 17 + .../2008-08-22-out-of-range-array-promote.ll | 22 + .../ScalarRepl/2008-09-22-vector-gep.ll | 25 + .../2009-02-02-ScalarPromoteOutOfRange.ll | 16 + .../ScalarRepl/2009-02-05-LoadFCA.ll | 20 + .../ScalarRepl/2009-03-04-MemCpyAlign.ll | 20 + .../ScalarRepl/2009-03-05-Aggre2Scalar-dbg.ll | 184 + .../ScalarRepl/2009-12-11-NeonTypes.ll | 89 + .../ScalarRepl/2010-01-18-SelfCopy.ll | 18 + .../Transforms/ScalarRepl/AggregatePromote.ll | 51 + .../Transforms/ScalarRepl/DifferingTypes.ll | 16 + .../Transforms/ScalarRepl/address-space.ll | 35 + final/test/Transforms/ScalarRepl/arraytest.ll | 11 + final/test/Transforms/ScalarRepl/badarray.ll | 57 + final/test/Transforms/ScalarRepl/basictest.ll | 30 + .../Transforms/ScalarRepl/bitfield-sroa.ll | 17 + .../Transforms/ScalarRepl/copy-aggregate.ll | 108 + final/test/Transforms/ScalarRepl/crash.ll | 260 + final/test/Transforms/ScalarRepl/debuginfo.ll | 106 + final/test/Transforms/ScalarRepl/dg.exp | 3 + .../ScalarRepl/load-store-aggregate.ll | 31 + .../Transforms/ScalarRepl/memcpy-align.ll | 32 + .../ScalarRepl/memcpy-from-global.ll | 96 + .../memset-aggregate-byte-leader.ll | 23 + .../Transforms/ScalarRepl/memset-aggregate.ll | 66 + .../ScalarRepl/nonzero-first-index.ll | 53 + .../Transforms/ScalarRepl/not-a-vector.ll | 20 + .../test/Transforms/ScalarRepl/phi-select.ll | 153 + .../Transforms/ScalarRepl/phinodepromote.ll | 34 + .../Transforms/ScalarRepl/select_promote.ll | 18 + final/test/Transforms/ScalarRepl/sroa-fca.ll | 21 + final/test/Transforms/ScalarRepl/sroa_two.ll | 13 + .../Transforms/ScalarRepl/union-fp-int.ll | 14 + .../Transforms/ScalarRepl/union-packed.ll | 14 + .../Transforms/ScalarRepl/union-pointer.ll | 41 + .../Transforms/ScalarRepl/vector_memcpy.ll | 30 + .../Transforms/ScalarRepl/vector_promote.ll | 100 + final/test/Transforms/ScalarRepl/volatile.ll | 12 + .../SimplifyCFG/2002-05-05-EmptyBlockMerge.ll | 22 + .../SimplifyCFG/2002-05-21-PHIElimination.ll | 19 + .../SimplifyCFG/2002-06-24-PHINode.ll | 14 + .../SimplifyCFG/2002-09-24-PHIAssertion.ll | 13 + .../SimplifyCFG/2003-03-07-DominateProblem.ll | 17 + .../SimplifyCFG/2003-08-05-InvokeCrash.ll | 13 + .../SimplifyCFG/2003-08-05-MishandleInvoke.ll | 12 + .../SimplifyCFG/2003-08-17-BranchFold.ll | 22 + .../2003-08-17-BranchFoldOrdering.ll | 26 + .../SimplifyCFG/2003-08-17-FoldSwitch-dbg.ll | 58 + .../SimplifyCFG/2003-08-17-FoldSwitch.ll | 80 + .../2004-12-10-SimplifyCFGCrash.ll | 40 + .../SimplifyCFG/2005-06-16-PHICrash.ll | 95 + .../SimplifyCFG/2005-08-01-PHIUpdateFail.ll | 71 + .../SimplifyCFG/2005-08-03-PHIFactorCrash.ll | 75 + .../SimplifyCFG/2005-10-02-InvokeSimplify.ll | 15 + .../2005-12-03-IncorrectPHIFold.ll | 124 + .../SimplifyCFG/2006-02-17-InfiniteUnroll.ll | 27 + .../SimplifyCFG/2006-06-12-InfLoop.ll | 413 + .../SimplifyCFG/2006-08-03-Crash.ll | 98 + .../SimplifyCFG/2006-10-19-UncondDiv.ll | 28 + .../SimplifyCFG/2006-10-29-InvokeCrash.ll | 555 + .../SimplifyCFG/2006-12-08-Ptr-ICmp-Branch.ll | 131 + .../SimplifyCFG/2007-11-22-InvokeNoUnwind.ll | 14 + .../SimplifyCFG/2007-12-21-Crash.ll | 37 + .../SimplifyCFG/2008-01-02-hoist-fp-add.ll | 26 + .../2008-04-23-MergeMultipleResultRet.ll | 43 + .../2008-04-27-MultipleReturnCrash.ll | 30 + .../SimplifyCFG/2008-05-16-PHIBlockMerge.ll | 131 + .../2008-07-13-InfLoopMiscompile.ll | 36 + .../SimplifyCFG/2008-09-08-MultiplePred.ll | 60 + .../2008-09-17-SpeculativeHoist.ll | 18 + ...008-10-03-SpeculativelyExecuteBeforePHI.ll | 36 + .../SimplifyCFG/2008-12-06-SingleEntryPhi.ll | 13 + .../SimplifyCFG/2008-12-16-DCECond.ll | 46 + .../SimplifyCFG/2009-01-18-PHIPropCrash.ll | 30 + ...01-19-UnconditionalTrappingConstantExpr.ll | 31 + .../2009-03-05-Speculative-Hoist-Dbg.ll | 108 + .../SimplifyCFG/2009-05-12-externweak.ll | 47 + .../SimplifyCFG/2009-06-15-InvokeCrash.ll | 557 + .../SimplifyCFG/2010-03-30-InvokeCrash.ll | 18 + .../2010-10-24-OnlyUnwindInEntry.ll | 6 + final/test/Transforms/SimplifyCFG/BrUnwind.ll | 15 + .../test/Transforms/SimplifyCFG/DeadSetCC.ll | 28 + .../SimplifyCFG/EqualPHIEdgeBlockMerge.ll | 18 + .../test/Transforms/SimplifyCFG/HoistCode.ll | 11 + .../Transforms/SimplifyCFG/MagicPointer.ll | 75 + .../Transforms/SimplifyCFG/PhiBlockMerge.ll | 25 + .../Transforms/SimplifyCFG/PhiBlockMerge2.ll | 27 + .../Transforms/SimplifyCFG/PhiEliminate.ll | 27 + .../Transforms/SimplifyCFG/PhiEliminate2.ll | 14 + .../Transforms/SimplifyCFG/PhiNoEliminate.ll | 27 + .../Transforms/SimplifyCFG/SpeculativeExec.ll | 21 + .../SimplifyCFG/UncondBranchToReturn.ll | 33 + .../SimplifyCFG/UnreachableEliminate.ll | 33 + .../test/Transforms/SimplifyCFG/basictest.ll | 43 + .../SimplifyCFG/branch-branch-dbginfo.ll | 70 + .../SimplifyCFG/branch-cond-merge.ll | 19 + .../SimplifyCFG/branch-cond-prop.ll | 17 + .../SimplifyCFG/branch-fold-test.ll | 17 + .../Transforms/SimplifyCFG/branch-fold.ll | 13 + .../SimplifyCFG/branch-phi-thread.ll | 66 + .../Transforms/SimplifyCFG/branch_fold_dbg.ll | 122 + final/test/Transforms/SimplifyCFG/dbginfo.ll | 71 + final/test/Transforms/SimplifyCFG/dg.exp | 3 + .../Transforms/SimplifyCFG/duplicate-phis.ll | 21 + .../SimplifyCFG/hoist-common-code.dbg.ll | 33 + .../SimplifyCFG/hoist-common-code.ll | 18 + .../test/Transforms/SimplifyCFG/indirectbr.ll | 182 + .../Transforms/SimplifyCFG/invoke_unwind.ll | 32 + .../SimplifyCFG/iterative-simplify.ll | 100 + .../Transforms/SimplifyCFG/noreturn-call.ll | 11 + .../Transforms/SimplifyCFG/return-merge.ll | 19 + .../test/Transforms/SimplifyCFG/select-gep.ll | 40 + .../SimplifyCFG/speculate-with-offset.ll | 94 + .../SimplifyCFG/switch-on-const-select.ll | 138 + .../SimplifyCFG/switch-simplify-crash.ll | 108 + .../Transforms/SimplifyCFG/switch-to-icmp.ll | 39 + .../Transforms/SimplifyCFG/switch_create.ll | 481 + .../SimplifyCFG/switch_formation.dbg.ll | 50 + .../SimplifyCFG/switch_switch_fold.ll | 47 + .../SimplifyCFG/switch_switch_fold_dbginfo.ll | 116 + .../Transforms/SimplifyCFG/switch_thread.ll | 79 + .../SimplifyCFG/trapping-load-unreachable.ll | 44 + .../SimplifyCFG/two-entry-phi-return.dbg.ll | 28 + .../SimplifyCFG/two-entry-phi-return.ll | 15 + .../2005-05-20-sprintf-crash.ll | 11 + .../2007-04-06-strchr-miscompile.ll | 29 + .../SimplifyLibCalls/2008-05-19-memcmp.ll | 14 + .../SimplifyLibCalls/2009-01-04-Annotate.ll | 12 + .../2009-02-11-NotInitialized.ll | 13 + .../SimplifyLibCalls/2009-02-12-StrTo.ll | 14 + .../2009-05-30-memcmp-byte.ll | 14 + .../SimplifyLibCalls/2009-07-28-Exit.ll | 22 + .../SimplifyLibCalls/2009-07-29-Exit2.ll | 24 + .../2010-05-30-memcpy-Struct.ll | 20 + final/test/Transforms/SimplifyLibCalls/FFS.ll | 36 + .../Transforms/SimplifyLibCalls/FPrintF.ll | 28 + .../test/Transforms/SimplifyLibCalls/FPuts.ll | 29 + .../Transforms/SimplifyLibCalls/IsDigit.ll | 21 + .../Transforms/SimplifyLibCalls/MemCpy.ll | 20 + .../Transforms/SimplifyLibCalls/PR7357.ll | 16 + .../Transforms/SimplifyLibCalls/Printf.ll | 36 + .../test/Transforms/SimplifyLibCalls/Puts.ll | 15 + .../Transforms/SimplifyLibCalls/SPrintF.ll | 40 + .../Transforms/SimplifyLibCalls/StrCat.ll | 33 + .../Transforms/SimplifyLibCalls/StrChr.ll | 26 + .../Transforms/SimplifyLibCalls/StrCmp.ll | 28 + .../Transforms/SimplifyLibCalls/StrCpy.ll | 37 + .../Transforms/SimplifyLibCalls/StrLen.ll | 56 + .../Transforms/SimplifyLibCalls/StrNCat.ll | 31 + .../Transforms/SimplifyLibCalls/StrNCmp.ll | 35 + .../Transforms/SimplifyLibCalls/StrNCpy.ll | 29 + .../Transforms/SimplifyLibCalls/StrPBrk.ll | 25 + .../Transforms/SimplifyLibCalls/StrRChr.ll | 23 + .../Transforms/SimplifyLibCalls/StrSpn.ll | 41 + .../Transforms/SimplifyLibCalls/StrStr.ll | 60 + .../Transforms/SimplifyLibCalls/ToAscii.ll | 21 + final/test/Transforms/SimplifyLibCalls/abs.ll | 11 + final/test/Transforms/SimplifyLibCalls/dg.exp | 3 + .../test/Transforms/SimplifyLibCalls/exp2.ll | 38 + .../test/Transforms/SimplifyLibCalls/floor.ll | 41 + .../Transforms/SimplifyLibCalls/iprintf.ll | 71 + .../Transforms/SimplifyLibCalls/memcmp.ll | 35 + .../Transforms/SimplifyLibCalls/memmove.ll | 12 + .../Transforms/SimplifyLibCalls/memset-64.ll | 12 + .../Transforms/SimplifyLibCalls/memset.ll | 12 + .../SimplifyLibCalls/pow-to-sqrt.ll | 33 + .../test/Transforms/SimplifyLibCalls/pow2.ll | 37 + .../SimplifyLibCalls/weak-symbols.ll | 26 + final/test/Transforms/Sink/basic.ll | 22 + final/test/Transforms/Sink/dg.exp | 3 + .../StripSymbols/2007-01-15-llvm.used.ll | 15 + .../StripSymbols/2010-06-30-StripDebug.ll | 28 + .../StripSymbols/2010-07-01-DeadDbgInfo.ll | 47 + .../StripSymbols/2010-08-25-crash.ll | 19 + final/test/Transforms/StripSymbols/dg.exp | 3 + .../2010-06-26-MultipleReturnValues.ll | 20 + .../TailCallElim/accum_recursion.ll | 74 + .../test/Transforms/TailCallElim/ackermann.ll | 25 + final/test/Transforms/TailCallElim/dg.exp | 3 + .../TailCallElim/dont-tce-tail-marked-call.ll | 13 + .../TailCallElim/dont_reorder_load.ll | 64 + .../test/Transforms/TailCallElim/dup_tail.ll | 23 + .../Transforms/TailCallElim/inf-recursion.ll | 34 + .../TailCallElim/intervening-inst.ll | 17 + .../TailCallElim/move_alloca_for_tail_call.ll | 15 + .../test/Transforms/TailCallElim/nocapture.ll | 25 + .../Transforms/TailCallElim/reorder_load.ll | 101 + .../TailCallElim/return_constant.ll | 17 + .../TailCallElim/trivial_codegen_tailcall.ll | 11 + .../TailDup/2003-06-24-Simpleloop.ll | 15 + .../TailDup/2003-07-22-InfiniteLoop.ll | 11 + .../TailDup/2003-08-23-InvalidatedPointers.ll | 29 + .../TailDup/2003-08-31-UnreachableBlocks.ll | 17 + .../TailDup/2004-04-01-DemoteRegToStack.ll | 20 + .../TailDup/2008-05-13-InfiniteLoop.ll | 26 + .../TailDup/2008-06-11-AvoidDupLoopHeader.ll | 27 + .../Transforms/TailDup/2009-07-31-phicrash.ll | 14 + final/test/Transforms/TailDup/MergeTest.ll | 27 + .../test/Transforms/TailDup/PHIUpdateTest.ll | 16 + final/test/Transforms/TailDup/basictest.ll | 20 + final/test/Transforms/TailDup/basictest2.ll | 15 + final/test/Transforms/TailDup/dg.exp | 3 + final/test/Transforms/TailDup/if-tail-dup.ll | 49 + final/test/Unit/lit.cfg | 83 + final/test/Unit/lit.site.cfg.in | 22 + final/test/Verifier/2002-04-13-RetTypes.ll | 10 + .../2002-11-05-GetelementptrPointers.ll | 9 + .../2004-05-21-SwitchConstantMismatch.ll | 13 + .../2005-03-21-UndefinedTypeReference.ll | 7 + final/test/Verifier/2006-07-11-StoreStruct.ll | 11 + final/test/Verifier/2006-10-15-AddrLabel.ll | 8 + .../Verifier/2006-12-12-IntrinsicDefine.ll | 7 + .../Verifier/2007-12-21-InvokeParamAttrs.ll | 10 + final/test/Verifier/2008-01-11-VarargAttrs.ll | 10 + final/test/Verifier/2008-03-01-AllocaSized.ll | 8 + .../Verifier/2008-08-22-MemCpyAlignment.ll | 11 + final/test/Verifier/2008-11-15-RetVoid.ll | 5 + .../test/Verifier/2009-05-29-InvokeResult1.ll | 15 + .../test/Verifier/2009-05-29-InvokeResult2.ll | 16 + .../test/Verifier/2009-05-29-InvokeResult3.ll | 19 + .../Verifier/2010-08-07-PointerIntrinsic.ll | 21 + final/test/Verifier/AmbiguousPhi.ll | 10 + final/test/Verifier/PhiGrouping.ll | 17 + final/test/Verifier/README.txt | 3 + final/test/Verifier/SelfReferential.ll | 9 + final/test/Verifier/aliasing-chain.ll | 6 + final/test/Verifier/byval-1.ll | 2 + final/test/Verifier/byval-2.ll | 4 + final/test/Verifier/byval-4.ll | 4 + final/test/Verifier/dg.exp | 3 + final/test/Verifier/gcread-ptrptr.ll | 13 + final/test/Verifier/gcroot-alloca.ll | 14 + final/test/Verifier/gcroot-meta.ll | 16 + final/test/Verifier/gcroot-ptrptr.ll | 14 + final/test/Verifier/gcwrite-ptrptr.ll | 13 + final/test/Verifier/invoke-1.ll | 10 + final/test/Verifier/invoke-2.ll | 14 + final/test/lib/llvm.exp | 313 + final/test/lib/llvm2cpp.exp | 100 + final/test/lit.cfg | 308 + final/test/lit.site.cfg.in | 20 + final/test/site.exp.in | 28 + final/tools/CMakeLists.txt | 53 + final/tools/Makefile | 76 + final/tools/bugpoint-passes/CMakeLists.txt | 5 + final/tools/bugpoint-passes/Makefile | 23 + final/tools/bugpoint-passes/TestPasses.cpp | 75 + final/tools/bugpoint-passes/bugpoint.exports | 0 final/tools/bugpoint/BugDriver.cpp | 246 + final/tools/bugpoint/BugDriver.h | 330 + final/tools/bugpoint/CMakeLists.txt | 14 + final/tools/bugpoint/CrashDebugger.cpp | 667 + final/tools/bugpoint/ExecutionDriver.cpp | 515 + final/tools/bugpoint/ExtractFunction.cpp | 369 + final/tools/bugpoint/FindBugs.cpp | 113 + final/tools/bugpoint/ListReducer.h | 201 + final/tools/bugpoint/Makefile | 16 + final/tools/bugpoint/Miscompilation.cpp | 1082 + final/tools/bugpoint/OptimizerDriver.cpp | 265 + final/tools/bugpoint/ToolRunner.cpp | 969 + final/tools/bugpoint/ToolRunner.h | 247 + final/tools/bugpoint/bugpoint.cpp | 184 + final/tools/edis/CMakeLists.txt | 11 + final/tools/edis/EDMain.cpp | 284 + final/tools/edis/EnhancedDisassembly.exports | 36 + final/tools/edis/Makefile | 54 + final/tools/gold/Makefile | 31 + final/tools/gold/README.txt | 21 + final/tools/gold/gold-plugin.cpp | 503 + final/tools/gold/gold.exports | 1 + final/tools/llc/CMakeLists.txt | 5 + final/tools/llc/Makefile | 21 + final/tools/llc/llc.cpp | 348 + final/tools/lli/CMakeLists.txt | 5 + final/tools/lli/Makefile | 15 + final/tools/lli/lli.cpp | 270 + final/tools/llvm-ar/CMakeLists.txt | 8 + final/tools/llvm-ar/Makefile | 25 + final/tools/llvm-ar/llvm-ar.cpp | 781 + final/tools/llvm-as/CMakeLists.txt | 6 + final/tools/llvm-as/Makefile | 17 + final/tools/llvm-as/llvm-as.cpp | 119 + final/tools/llvm-bcanalyzer/CMakeLists.txt | 6 + final/tools/llvm-bcanalyzer/Makefile | 17 + .../tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 635 + final/tools/llvm-config/CMakeLists.txt | 162 + final/tools/llvm-config/Makefile | 131 + final/tools/llvm-config/find-cycles.pl | 170 + final/tools/llvm-config/llvm-config.in.in | 463 + final/tools/llvm-diff/CMakeLists.txt | 6 + final/tools/llvm-diff/DifferenceEngine.cpp | 676 + final/tools/llvm-diff/DifferenceEngine.h | 179 + final/tools/llvm-diff/Makefile | 17 + final/tools/llvm-diff/llvm-diff.cpp | 314 + final/tools/llvm-dis/CMakeLists.txt | 6 + final/tools/llvm-dis/Makefile | 17 + final/tools/llvm-dis/llvm-dis.cpp | 141 + final/tools/llvm-extract/CMakeLists.txt | 5 + final/tools/llvm-extract/Makefile | 18 + final/tools/llvm-extract/llvm-extract.cpp | 174 + final/tools/llvm-ld/CMakeLists.txt | 8 + final/tools/llvm-ld/Makefile | 15 + final/tools/llvm-ld/Optimize.cpp | 128 + final/tools/llvm-ld/llvm-ld.cpp | 732 + final/tools/llvm-link/CMakeLists.txt | 5 + final/tools/llvm-link/Makefile | 17 + final/tools/llvm-link/llvm-link.cpp | 141 + final/tools/llvm-mc/CMakeLists.txt | 6 + final/tools/llvm-mc/Disassembler.cpp | 346 + final/tools/llvm-mc/Disassembler.h | 40 + final/tools/llvm-mc/Makefile | 24 + final/tools/llvm-mc/llvm-mc.cpp | 451 + final/tools/llvm-nm/CMakeLists.txt | 5 + final/tools/llvm-nm/Makefile | 17 + final/tools/llvm-nm/llvm-nm.cpp | 361 + final/tools/llvm-objdump/CMakeLists.txt | 11 + final/tools/llvm-objdump/Makefile | 17 + final/tools/llvm-objdump/llvm-objdump.cpp | 255 + final/tools/llvm-prof/CMakeLists.txt | 5 + final/tools/llvm-prof/Makefile | 17 + final/tools/llvm-prof/llvm-prof.cpp | 293 + final/tools/llvm-ranlib/CMakeLists.txt | 6 + final/tools/llvm-ranlib/Makefile | 18 + final/tools/llvm-ranlib/llvm-ranlib.cpp | 101 + final/tools/llvm-shlib/Makefile | 120 + final/tools/llvm-stub/CMakeLists.txt | 3 + final/tools/llvm-stub/Makefile | 13 + final/tools/llvm-stub/llvm-stub.c | 77 + final/tools/llvmc/CMakeLists.txt | 4 + final/tools/llvmc/Makefile | 18 + final/tools/llvmc/doc/LLVMC-Reference.rst | 842 + final/tools/llvmc/doc/LLVMC-Tutorial.rst | 129 + final/tools/llvmc/doc/Makefile | 33 + final/tools/llvmc/doc/img/lines.gif | Bin 0 -> 91 bytes final/tools/llvmc/examples/Hello/Hello.cpp | 29 + final/tools/llvmc/examples/Hello/Makefile | 14 + final/tools/llvmc/examples/Makefile | 14 + final/tools/llvmc/examples/Simple/Makefile | 15 + final/tools/llvmc/examples/Simple/Simple.cpp | 2 + final/tools/llvmc/examples/Simple/Simple.td | 41 + .../llvmc/examples/Skeleton/AutoGenerated.td | 7 + final/tools/llvmc/examples/Skeleton/Hooks.cpp | 12 + final/tools/llvmc/examples/Skeleton/Main.cpp | 15 + final/tools/llvmc/examples/Skeleton/Makefile | 20 + final/tools/llvmc/examples/Skeleton/README | 6 + final/tools/llvmc/examples/mcc16/Hooks.cpp | 109 + final/tools/llvmc/examples/mcc16/Main.cpp | 57 + final/tools/llvmc/examples/mcc16/Makefile | 15 + final/tools/llvmc/examples/mcc16/PIC16.td | 234 + final/tools/llvmc/examples/mcc16/README | 75 + final/tools/llvmc/src/AutoGenerated.td | 17 + final/tools/llvmc/src/Base.td.in | 461 + final/tools/llvmc/src/Clang.td | 87 + final/tools/llvmc/src/Hooks.cpp | 194 + final/tools/llvmc/src/Main.cpp | 16 + final/tools/llvmc/src/Makefile | 14 + final/tools/lto/LTOCodeGenerator.cpp | 415 + final/tools/lto/LTOCodeGenerator.h | 72 + final/tools/lto/LTOModule.cpp | 748 + final/tools/lto/LTOModule.h | 120 + final/tools/lto/Makefile | 58 + final/tools/lto/lto.cpp | 291 + final/tools/lto/lto.exports | 27 + final/tools/macho-dump/CMakeLists.txt | 5 + final/tools/macho-dump/Makefile | 23 + final/tools/macho-dump/macho-dump.cpp | 391 + final/tools/opt/AnalysisWrappers.cpp | 94 + final/tools/opt/CMakeLists.txt | 8 + final/tools/opt/GraphPrinters.cpp | 120 + final/tools/opt/Makefile | 14 + final/tools/opt/PrintSCC.cpp | 112 + final/tools/opt/opt.cpp | 696 + final/unittests/ADT/APFloatTest.cpp | 579 + final/unittests/ADT/APIntTest.cpp | 369 + final/unittests/ADT/BitVectorTest.cpp | 201 + final/unittests/ADT/DAGDeltaAlgorithmTest.cpp | 122 + final/unittests/ADT/DeltaAlgorithmTest.cpp | 100 + final/unittests/ADT/DenseMapTest.cpp | 179 + final/unittests/ADT/DenseSetTest.cpp | 30 + final/unittests/ADT/FoldingSet.cpp | 39 + final/unittests/ADT/ImmutableSetTest.cpp | 201 + final/unittests/ADT/IntEqClassesTest.cpp | 107 + final/unittests/ADT/IntervalMapTest.cpp | 716 + final/unittests/ADT/Makefile | 23 + final/unittests/ADT/SmallBitVectorTest.cpp | 196 + final/unittests/ADT/SmallStringTest.cpp | 48 + final/unittests/ADT/SmallVectorTest.cpp | 410 + final/unittests/ADT/SparseBitVectorTest.cpp | 36 + final/unittests/ADT/StringMapTest.cpp | 207 + final/unittests/ADT/StringRefTest.cpp | 282 + final/unittests/ADT/TripleTest.cpp | 270 + final/unittests/ADT/TwineTest.cpp | 83 + final/unittests/ADT/ilistTest.cpp | 44 + final/unittests/Analysis/Makefile | 15 + .../Analysis/ScalarEvolutionTest.cpp | 82 + final/unittests/CMakeLists.txt | 144 + .../ExecutionEngine/ExecutionEngineTest.cpp | 129 + .../JIT/JITEventListenerTest.cpp | 238 + .../JIT/JITMemoryManagerTest.cpp | 279 + .../unittests/ExecutionEngine/JIT/JITTest.cpp | 779 + .../ExecutionEngine/JIT/JITTests.def | 4 + final/unittests/ExecutionEngine/JIT/Makefile | 18 + .../ExecutionEngine/JIT/MultiJITTest.cpp | 164 + final/unittests/ExecutionEngine/Makefile | 18 + final/unittests/Makefile | 17 + final/unittests/Makefile.unittest | 62 + final/unittests/Support/AllocatorTest.cpp | 143 + final/unittests/Support/Casting.cpp | 154 + final/unittests/Support/CommandLineTest.cpp | 60 + final/unittests/Support/ConstantRangeTest.cpp | 440 + final/unittests/Support/EndianTest.cpp | 72 + final/unittests/Support/LeakDetectorTest.cpp | 31 + final/unittests/Support/Makefile | 15 + final/unittests/Support/MathExtrasTest.cpp | 104 + final/unittests/Support/Path.cpp | 253 + final/unittests/Support/RegexTest.cpp | 94 + final/unittests/Support/SwapByteOrderTest.cpp | 128 + final/unittests/Support/TimeValue.cpp | 23 + final/unittests/Support/TypeBuilderTest.cpp | 253 + final/unittests/Support/ValueHandleTest.cpp | 411 + final/unittests/Support/raw_ostream_test.cpp | 146 + final/unittests/Transforms/Makefile | 17 + final/unittests/Transforms/Utils/Cloning.cpp | 141 + final/unittests/Transforms/Utils/Local.cpp | 60 + final/unittests/Transforms/Utils/Makefile | 15 + final/unittests/VMCore/ConstantsTest.cpp | 122 + final/unittests/VMCore/DerivedTypesTest.cpp | 88 + final/unittests/VMCore/InstructionsTest.cpp | 111 + final/unittests/VMCore/Makefile | 15 + final/unittests/VMCore/MetadataTest.cpp | 145 + final/unittests/VMCore/PassManagerTest.cpp | 548 + final/unittests/VMCore/ValueMapTest.cpp | 294 + final/unittests/VMCore/VerifierTest.cpp | 64 + final/utils/CollectDebugInfoUsingLLDB.py | 182 + final/utils/CompareDebugInfo.py | 182 + final/utils/DSAclean.py | 32 + final/utils/DSAextract.py | 111 + final/utils/FileCheck/CMakeLists.txt | 11 + final/utils/FileCheck/FileCheck.cpp | 757 + final/utils/FileCheck/Makefile | 21 + final/utils/FileUpdate/CMakeLists.txt | 11 + final/utils/FileUpdate/FileUpdate.cpp | 87 + final/utils/FileUpdate/Makefile | 21 + final/utils/GenLibDeps.pl | 386 + final/utils/GetRepositoryPath | 27 + final/utils/GetSourceVersion | 27 + final/utils/KillTheDoctor/CMakeLists.txt | 5 + final/utils/KillTheDoctor/KillTheDoctor.cpp | 596 + final/utils/Makefile | 22 + final/utils/Misc/zkill | 276 + final/utils/NLT.schema | 8 + final/utils/NewNightlyTest.pl | 836 + final/utils/NightlyTest.gnuplot | 214 + final/utils/NightlyTestTemplate.html | 244 + final/utils/PerfectShuffle/Makefile | 18 + final/utils/PerfectShuffle/PerfectShuffle.cpp | 572 + final/utils/TableGen/ARMDecoderEmitter.cpp | 1857 ++ final/utils/TableGen/ARMDecoderEmitter.h | 50 + final/utils/TableGen/AsmMatcherEmitter.cpp | 2371 ++ final/utils/TableGen/AsmMatcherEmitter.h | 33 + final/utils/TableGen/AsmWriterEmitter.cpp | 803 + final/utils/TableGen/AsmWriterEmitter.h | 55 + final/utils/TableGen/AsmWriterInst.cpp | 233 + final/utils/TableGen/AsmWriterInst.h | 113 + final/utils/TableGen/CMakeLists.txt | 56 + final/utils/TableGen/CallingConvEmitter.cpp | 212 + final/utils/TableGen/CallingConvEmitter.h | 38 + final/utils/TableGen/ClangASTNodesEmitter.cpp | 165 + final/utils/TableGen/ClangASTNodesEmitter.h | 84 + final/utils/TableGen/ClangAttrEmitter.cpp | 708 + final/utils/TableGen/ClangAttrEmitter.h | 101 + .../TableGen/ClangDiagnosticsEmitter.cpp | 296 + .../utils/TableGen/ClangDiagnosticsEmitter.h | 46 + .../utils/TableGen/ClangSACheckersEmitter.cpp | 230 + final/utils/TableGen/ClangSACheckersEmitter.h | 31 + final/utils/TableGen/CodeEmitterGen.cpp | 295 + final/utils/TableGen/CodeEmitterGen.h | 49 + final/utils/TableGen/CodeGenDAGPatterns.cpp | 3179 ++ final/utils/TableGen/CodeGenDAGPatterns.h | 758 + final/utils/TableGen/CodeGenInstruction.cpp | 537 + final/utils/TableGen/CodeGenInstruction.h | 316 + final/utils/TableGen/CodeGenIntrinsics.h | 87 + final/utils/TableGen/CodeGenRegisters.h | 101 + final/utils/TableGen/CodeGenTarget.cpp | 582 + final/utils/TableGen/CodeGenTarget.h | 269 + final/utils/TableGen/DAGISelEmitter.cpp | 159 + final/utils/TableGen/DAGISelEmitter.h | 38 + final/utils/TableGen/DAGISelMatcher.cpp | 401 + final/utils/TableGen/DAGISelMatcher.h | 1114 + .../utils/TableGen/DAGISelMatcherEmitter.cpp | 827 + final/utils/TableGen/DAGISelMatcherGen.cpp | 909 + final/utils/TableGen/DAGISelMatcherOpt.cpp | 514 + final/utils/TableGen/DisassemblerEmitter.cpp | 138 + final/utils/TableGen/DisassemblerEmitter.h | 28 + final/utils/TableGen/EDEmitter.cpp | 920 + final/utils/TableGen/EDEmitter.h | 34 + final/utils/TableGen/FastISelEmitter.cpp | 653 + final/utils/TableGen/FastISelEmitter.h | 39 + .../utils/TableGen/FixedLenDecoderEmitter.cpp | 1372 + final/utils/TableGen/FixedLenDecoderEmitter.h | 56 + final/utils/TableGen/InstrEnumEmitter.cpp | 48 + final/utils/TableGen/InstrEnumEmitter.h | 33 + final/utils/TableGen/InstrInfoEmitter.cpp | 336 + final/utils/TableGen/InstrInfoEmitter.h | 66 + final/utils/TableGen/IntrinsicEmitter.cpp | 679 + final/utils/TableGen/IntrinsicEmitter.h | 63 + .../TableGen/LLVMCConfigurationEmitter.cpp | 3105 ++ .../TableGen/LLVMCConfigurationEmitter.h | 34 + final/utils/TableGen/Makefile | 20 + final/utils/TableGen/NeonEmitter.cpp | 1522 + final/utils/TableGen/NeonEmitter.h | 180 + final/utils/TableGen/OptParserEmitter.cpp | 194 + final/utils/TableGen/OptParserEmitter.h | 34 + final/utils/TableGen/Record.cpp | 1564 + final/utils/TableGen/Record.h | 1507 + final/utils/TableGen/RegisterInfoEmitter.cpp | 1009 + final/utils/TableGen/RegisterInfoEmitter.h | 40 + final/utils/TableGen/StringMatcher.cpp | 149 + final/utils/TableGen/StringMatcher.h | 54 + final/utils/TableGen/StringToOffsetTable.h | 81 + final/utils/TableGen/SubtargetEmitter.cpp | 663 + final/utils/TableGen/SubtargetEmitter.h | 70 + final/utils/TableGen/TGLexer.cpp | 442 + final/utils/TableGen/TGLexer.h | 122 + final/utils/TableGen/TGParser.cpp | 2151 ++ final/utils/TableGen/TGParser.h | 118 + final/utils/TableGen/TGValueTypes.cpp | 106 + final/utils/TableGen/TableGen.cpp | 377 + final/utils/TableGen/TableGenBackend.cpp | 25 + final/utils/TableGen/TableGenBackend.h | 43 + final/utils/TableGen/X86DisassemblerShared.h | 38 + .../utils/TableGen/X86DisassemblerTables.cpp | 601 + final/utils/TableGen/X86DisassemblerTables.h | 291 + final/utils/TableGen/X86ModRMFilters.h | 197 + final/utils/TableGen/X86RecognizableInstr.cpp | 1006 + final/utils/TableGen/X86RecognizableInstr.h | 240 + final/utils/Target/ARM/analyze-match-table.py | 61 + final/utils/UpdateCMakeLists.pl | 119 + final/utils/bugpoint/RemoteRunSafely.sh | 105 + final/utils/buildit/GNUmakefile | 135 + final/utils/buildit/build_llvm | 375 + final/utils/cgiplotNLT.pl | 68 + final/utils/check-each-file | 150 + final/utils/codegen-diff | 135 + final/utils/count/CMakeLists.txt | 3 + final/utils/count/Makefile | 20 + final/utils/count/count.c | 50 + final/utils/countloc.sh | 40 + final/utils/crosstool/ARM/README | 37 + .../crosstool/ARM/build-install-linux.sh | 200 + final/utils/crosstool/create-snapshots.sh | 41 + final/utils/emacs/README | 27 + final/utils/emacs/emacs.el | 39 + final/utils/emacs/llvm-mode.el | 133 + final/utils/emacs/tablegen-mode.el | 122 + final/utils/findmisopt | 178 + final/utils/findoptdiff | 101 + final/utils/findsym.pl | 33 + final/utils/fpcmp/Makefile | 16 + final/utils/fpcmp/fpcmp.cpp | 43 + final/utils/getsrcs.sh | 34 + final/utils/git/find-rev | 50 + final/utils/importNLT.pl | 86 + final/utils/jedit/README | 14 + final/utils/jedit/tablegen.xml | 39 + final/utils/kate/README | 12 + final/utils/kate/llvm.xml | 255 + final/utils/lint/common_lint.py | 97 + final/utils/lint/cpp_lint.py | 94 + final/utils/lint/generic_lint.py | 24 + .../utils/lint/remove_trailing_whitespace.sh | 6 + final/utils/lit/TODO | 9 + final/utils/lit/lit.py | 5 + .../lit/lit/ExampleTests.ObjDir/lit.site.cfg | 15 + .../lit/lit/ExampleTests/Clang/fsyntax-only.c | 4 + .../utils/lit/lit/ExampleTests/Clang/lit.cfg | 47 + .../LLVM.InTree/test/Bar/bar-test.ll | 3 + .../ExampleTests/LLVM.InTree/test/Bar/dg.exp | 6 + .../lit/ExampleTests/LLVM.InTree/test/lit.cfg | 151 + .../LLVM.InTree/test/lit.site.cfg | 10 + .../ExampleTests/LLVM.InTree/test/site.exp | 28 + .../ExampleTests/LLVM.OutOfTree/lit.local.cfg | 1 + .../LLVM.OutOfTree/obj/test/Foo/lit.local.cfg | 0 .../LLVM.OutOfTree/obj/test/lit.site.cfg | 11 + .../LLVM.OutOfTree/obj/test/site.exp | 28 + .../LLVM.OutOfTree/src/test/Foo/data.txt | 1 + .../LLVM.OutOfTree/src/test/Foo/dg.exp | 6 + .../LLVM.OutOfTree/src/test/Foo/pct-S.ll | 1 + .../LLVM.OutOfTree/src/test/lit.cfg | 151 + .../lit/ExampleTests/ShExternal/lit.local.cfg | 6 + .../lit/ExampleTests/ShInternal/lit.local.cfg | 6 + .../lit/ExampleTests/TclTest/lit.local.cfg | 5 + .../lit/ExampleTests/TclTest/stderr-pipe.ll | 1 + .../lit/ExampleTests/TclTest/tcl-redir-1.ll | 7 + final/utils/lit/lit/ExampleTests/fail.c | 2 + final/utils/lit/lit/ExampleTests/lit.cfg | 26 + final/utils/lit/lit/ExampleTests/pass.c | 1 + .../lit/ExampleTests/required-and-missing.c | 4 + .../lit/ExampleTests/required-and-present.c | 2 + final/utils/lit/lit/ExampleTests/xfail.c | 2 + final/utils/lit/lit/ExampleTests/xpass.c | 2 + final/utils/lit/lit/LitConfig.py | 131 + final/utils/lit/lit/LitFormats.py | 3 + final/utils/lit/lit/LitTestCase.py | 30 + final/utils/lit/lit/ProgressBar.py | 267 + final/utils/lit/lit/ShCommands.py | 85 + final/utils/lit/lit/ShUtil.py | 353 + final/utils/lit/lit/TclUtil.py | 322 + final/utils/lit/lit/Test.py | 79 + final/utils/lit/lit/TestFormats.py | 228 + final/utils/lit/lit/TestRunner.py | 600 + final/utils/lit/lit/TestingConfig.py | 103 + final/utils/lit/lit/Util.py | 141 + final/utils/lit/lit/__init__.py | 10 + final/utils/lit/lit/main.py | 648 + final/utils/lit/setup.py | 70 + final/utils/llvm-lit/CMakeLists.txt | 12 + final/utils/llvm-lit/Makefile | 22 + final/utils/llvm-lit/llvm-lit.in | 27 + final/utils/llvm-native-gcc | 249 + final/utils/llvm-native-gxx | 249 + final/utils/llvm.grm | 418 + final/utils/llvmbuild | 749 + final/utils/llvmdo | 184 + final/utils/llvmgrep | 39 + final/utils/makellvm | 145 + final/utils/not/CMakeLists.txt | 11 + final/utils/not/Makefile | 21 + final/utils/not/not.cpp | 27 + final/utils/parseNLT.pl | 34 + final/utils/plotNLT.pl | 53 + final/utils/profile.pl | 74 + final/utils/release/test-release.sh | 381 + final/utils/test_debuginfo.pl | 61 + final/utils/unittest/CMakeLists.txt | 41 + final/utils/unittest/Makefile | 13 + final/utils/unittest/UnitTestMain/Makefile | 32 + .../utils/unittest/UnitTestMain/TestMain.cpp | 42 + final/utils/unittest/googletest/LICENSE.TXT | 28 + final/utils/unittest/googletest/Makefile | 39 + final/utils/unittest/googletest/README.LLVM | 31 + .../unittest/googletest/gtest-death-test.cc | 1172 + .../unittest/googletest/gtest-filepath.cc | 380 + final/utils/unittest/googletest/gtest-port.cc | 711 + .../unittest/googletest/gtest-test-part.cc | 110 + .../unittest/googletest/gtest-typed-test.cc | 110 + final/utils/unittest/googletest/gtest.cc | 4675 +++ .../include/gtest/gtest-death-test.h | 283 + .../googletest/include/gtest/gtest-message.h | 230 + .../include/gtest/gtest-param-test.h | 1397 + .../googletest/include/gtest/gtest-spi.h | 232 + .../include/gtest/gtest-test-part.h | 176 + .../include/gtest/gtest-typed-test.h | 259 + .../unittest/googletest/include/gtest/gtest.h | 2054 ++ .../include/gtest/gtest_pred_impl.h | 368 + .../googletest/include/gtest/gtest_prod.h | 58 + .../internal/gtest-death-test-internal.h | 275 + .../include/gtest/internal/gtest-filepath.h | 210 + .../gtest/internal/gtest-internal-inl.h | 1074 + .../include/gtest/internal/gtest-internal.h | 943 + .../include/gtest/internal/gtest-linked_ptr.h | 243 + .../internal/gtest-param-util-generated.h | 4820 +++ .../include/gtest/internal/gtest-param-util.h | 619 + .../include/gtest/internal/gtest-port.h | 1502 + .../include/gtest/internal/gtest-string.h | 350 + .../include/gtest/internal/gtest-tuple.h | 968 + .../include/gtest/internal/gtest-type-util.h | 3321 +++ final/utils/valgrind/i386-pc-linux-gnu.supp | 41 + final/utils/valgrind/x86_64-pc-linux-gnu.supp | 46 + final/utils/vim/README | 43 + final/utils/vim/llvm.vim | 110 + final/utils/vim/tablegen.vim | 54 + final/utils/vim/vimrc | 221 + final/utils/webNLT.pl | 83 + final/website/index.html | 26 + 8270 files changed, 1242821 insertions(+) create mode 100644 final/.gitignore create mode 100644 final/CMakeLists.txt create mode 100644 final/CREDITS.TXT create mode 100644 final/LICENSE.TXT create mode 100644 final/Makefile create mode 100644 final/Makefile.common create mode 100644 final/Makefile.config.in create mode 100644 final/Makefile.rules create mode 100644 final/ModuleInfo.txt create mode 100644 final/README.txt create mode 100755 final/autoconf/AutoRegen.sh create mode 100644 final/autoconf/ExportMap.map create mode 100644 final/autoconf/LICENSE.TXT create mode 100644 final/autoconf/README.TXT create mode 100755 final/autoconf/config.guess create mode 100755 final/autoconf/config.sub create mode 100644 final/autoconf/configure.ac create mode 100755 final/autoconf/depcomp create mode 100755 final/autoconf/install-sh create mode 100644 final/autoconf/ltmain.sh create mode 100644 final/autoconf/m4/build_exeext.m4 create mode 100644 final/autoconf/m4/c_printf_a.m4 create mode 100644 final/autoconf/m4/check_gnu_make.m4 create mode 100644 final/autoconf/m4/config_makefile.m4 create mode 100644 final/autoconf/m4/config_project.m4 create mode 100644 final/autoconf/m4/cxx_flag_check.m4 create mode 100644 final/autoconf/m4/find_std_program.m4 create mode 100644 final/autoconf/m4/func_isinf.m4 create mode 100644 final/autoconf/m4/func_isnan.m4 create mode 100644 final/autoconf/m4/func_mmap_file.m4 create mode 100644 final/autoconf/m4/header_mmap_anonymous.m4 create mode 100644 final/autoconf/m4/huge_val.m4 create mode 100644 final/autoconf/m4/libtool.m4 create mode 100644 final/autoconf/m4/link_options.m4 create mode 100644 final/autoconf/m4/linux_mixed_64_32.m4 create mode 100644 final/autoconf/m4/ltdl.m4 create mode 100644 final/autoconf/m4/need_dev_zero_for_mmap.m4 create mode 100644 final/autoconf/m4/path_perl.m4 create mode 100644 final/autoconf/m4/path_tclsh.m4 create mode 100644 final/autoconf/m4/rand48.m4 create mode 100644 final/autoconf/m4/sanity_check.m4 create mode 100644 final/autoconf/m4/single_cxx_check.m4 create mode 100644 final/autoconf/m4/visibility_inlines_hidden.m4 create mode 100755 final/autoconf/missing create mode 100755 final/autoconf/mkinstalldirs create mode 100644 final/bindings/Makefile create mode 100644 final/bindings/README.txt create mode 100644 final/bindings/ocaml/Makefile create mode 100644 final/bindings/ocaml/Makefile.ocaml create mode 100644 final/bindings/ocaml/analysis/Makefile create mode 100644 final/bindings/ocaml/analysis/analysis_ocaml.c create mode 100644 final/bindings/ocaml/analysis/llvm_analysis.ml create mode 100644 final/bindings/ocaml/analysis/llvm_analysis.mli create mode 100644 final/bindings/ocaml/bitreader/Makefile create mode 100644 final/bindings/ocaml/bitreader/bitreader_ocaml.c create mode 100644 final/bindings/ocaml/bitreader/llvm_bitreader.ml create mode 100644 final/bindings/ocaml/bitreader/llvm_bitreader.mli create mode 100644 final/bindings/ocaml/bitwriter/Makefile create mode 100644 final/bindings/ocaml/bitwriter/bitwriter_ocaml.c create mode 100644 final/bindings/ocaml/bitwriter/llvm_bitwriter.ml create mode 100644 final/bindings/ocaml/bitwriter/llvm_bitwriter.mli create mode 100644 final/bindings/ocaml/executionengine/Makefile create mode 100644 final/bindings/ocaml/executionengine/executionengine_ocaml.c create mode 100644 final/bindings/ocaml/executionengine/llvm_executionengine.ml create mode 100644 final/bindings/ocaml/executionengine/llvm_executionengine.mli create mode 100644 final/bindings/ocaml/llvm/Makefile create mode 100644 final/bindings/ocaml/llvm/llvm.ml create mode 100644 final/bindings/ocaml/llvm/llvm.mli create mode 100644 final/bindings/ocaml/llvm/llvm_ocaml.c create mode 100644 final/bindings/ocaml/target/Makefile create mode 100644 final/bindings/ocaml/target/llvm_target.ml create mode 100644 final/bindings/ocaml/target/llvm_target.mli create mode 100644 final/bindings/ocaml/target/target_ocaml.c create mode 100644 final/bindings/ocaml/transforms/Makefile create mode 100644 final/bindings/ocaml/transforms/scalar/Makefile create mode 100644 final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml create mode 100644 final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli create mode 100644 final/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c create mode 100755 final/build-for-llvm-top.sh create mode 100644 final/cmake/README create mode 100755 final/cmake/config-ix.cmake create mode 100755 final/cmake/modules/AddLLVM.cmake create mode 100644 final/cmake/modules/AddLLVMDefinitions.cmake create mode 100644 final/cmake/modules/CMakeLists.txt create mode 100644 final/cmake/modules/CheckAtomic.cmake create mode 100644 final/cmake/modules/ChooseMSVCCRT.cmake create mode 100644 final/cmake/modules/CrossCompileLLVM.cmake create mode 100755 final/cmake/modules/FindBison.cmake create mode 100644 final/cmake/modules/GetTargetTriple.cmake create mode 100644 final/cmake/modules/HandleLLVMOptions.cmake create mode 100644 final/cmake/modules/LLVM.cmake create mode 100755 final/cmake/modules/LLVMConfig.cmake create mode 100644 final/cmake/modules/LLVMLibDeps.cmake create mode 100644 final/cmake/modules/LLVMParseArguments.cmake create mode 100644 final/cmake/modules/LLVMProcessSources.cmake create mode 100644 final/cmake/modules/TableGen.cmake create mode 100644 final/cmake/modules/VersionFromVCS.cmake create mode 100755 final/configure create mode 100644 final/docs/AliasAnalysis.html create mode 100644 final/docs/BitCodeFormat.html create mode 100644 final/docs/Bugpoint.html create mode 100644 final/docs/CFEBuildInstrs.html create mode 100644 final/docs/CMake.html create mode 100644 final/docs/CodeGenerator.html create mode 100644 final/docs/CodingStandards.html create mode 100644 final/docs/CommandGuide/FileCheck.pod create mode 100644 final/docs/CommandGuide/Makefile create mode 100644 final/docs/CommandGuide/bugpoint.pod create mode 100644 final/docs/CommandGuide/html/manpage.css create mode 100644 final/docs/CommandGuide/index.html create mode 100644 final/docs/CommandGuide/lit.pod create mode 100644 final/docs/CommandGuide/llc.pod create mode 100644 final/docs/CommandGuide/lli.pod create mode 100644 final/docs/CommandGuide/llvm-ar.pod create mode 100644 final/docs/CommandGuide/llvm-as.pod create mode 100644 final/docs/CommandGuide/llvm-bcanalyzer.pod create mode 100644 final/docs/CommandGuide/llvm-config.pod create mode 100644 final/docs/CommandGuide/llvm-diff.pod create mode 100644 final/docs/CommandGuide/llvm-dis.pod create mode 100644 final/docs/CommandGuide/llvm-extract.pod create mode 100644 final/docs/CommandGuide/llvm-ld.pod create mode 100644 final/docs/CommandGuide/llvm-link.pod create mode 100644 final/docs/CommandGuide/llvm-nm.pod create mode 100644 final/docs/CommandGuide/llvm-prof.pod create mode 100644 final/docs/CommandGuide/llvm-ranlib.pod create mode 100644 final/docs/CommandGuide/llvmc.pod create mode 100644 final/docs/CommandGuide/llvmgcc.pod create mode 100644 final/docs/CommandGuide/llvmgxx.pod create mode 100644 final/docs/CommandGuide/manpage.css create mode 100644 final/docs/CommandGuide/opt.pod create mode 100644 final/docs/CommandGuide/tblgen.pod create mode 100644 final/docs/CommandLine.html create mode 100644 final/docs/CompilerDriver.html create mode 100644 final/docs/CompilerDriverTutorial.html create mode 100644 final/docs/CompilerWriterInfo.html create mode 100644 final/docs/DebuggingJITedCode.html create mode 100644 final/docs/DeveloperPolicy.html create mode 100644 final/docs/ExceptionHandling.html create mode 100644 final/docs/ExtendedIntegerResults.txt create mode 100644 final/docs/ExtendingLLVM.html create mode 100644 final/docs/FAQ.html create mode 100644 final/docs/GCCFEBuildInstrs.html create mode 100644 final/docs/GarbageCollection.html create mode 100644 final/docs/GetElementPtr.html create mode 100644 final/docs/GettingStarted.html create mode 100644 final/docs/GettingStartedVS.html create mode 100644 final/docs/GoldPlugin.html create mode 100644 final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt create mode 100644 final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt create mode 100644 final/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt create mode 100644 final/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt create mode 100644 final/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt create mode 100644 final/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt create mode 100644 final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt create mode 100644 final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt create mode 100644 final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt create mode 100644 final/docs/HistoricalNotes/2001-02-09-AdveComments.txt create mode 100644 final/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt create mode 100644 final/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt create mode 100644 final/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt create mode 100644 final/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt create mode 100644 final/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt create mode 100644 final/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt create mode 100644 final/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt create mode 100644 final/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt create mode 100644 final/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt create mode 100644 final/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt create mode 100644 final/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt create mode 100644 final/docs/HistoricalNotes/2002-05-12-InstListChange.txt create mode 100644 final/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt create mode 100644 final/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt create mode 100644 final/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt create mode 100644 final/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt create mode 100644 final/docs/HistoricalNotes/2007-OriginalClangReadme.txt create mode 100644 final/docs/HowToReleaseLLVM.html create mode 100644 final/docs/HowToSubmitABug.html create mode 100644 final/docs/LangRef.html create mode 100644 final/docs/Lexicon.html create mode 100644 final/docs/LinkTimeOptimization.html create mode 100644 final/docs/Makefile create mode 100644 final/docs/MakefileGuide.html create mode 100644 final/docs/Packaging.html create mode 100644 final/docs/Passes.html create mode 100644 final/docs/ProgrammersManual.html create mode 100644 final/docs/Projects.html create mode 100644 final/docs/ReleaseNotes.html create mode 100644 final/docs/SourceLevelDebugging.html create mode 100644 final/docs/SystemLibrary.html create mode 100644 final/docs/TableGenFundamentals.html create mode 100644 final/docs/TestingGuide.html create mode 100644 final/docs/UsingLibraries.html create mode 100644 final/docs/WritingAnLLVMBackend.html create mode 100644 final/docs/WritingAnLLVMPass.html create mode 100644 final/docs/doxygen.cfg.in create mode 100644 final/docs/doxygen.css create mode 100644 final/docs/doxygen.footer create mode 100644 final/docs/doxygen.header create mode 100644 final/docs/doxygen.intro create mode 100644 final/docs/img/Debugging.gif create mode 100644 final/docs/img/libdeps.gif create mode 100644 final/docs/img/lines.gif create mode 100644 final/docs/img/objdeps.gif create mode 100644 final/docs/img/venusflytrap.jpg create mode 100644 final/docs/index.html create mode 100644 final/docs/llvm.css create mode 100644 final/docs/re_format.7 create mode 100644 final/docs/tutorial/LangImpl1.html create mode 100644 final/docs/tutorial/LangImpl2.html create mode 100644 final/docs/tutorial/LangImpl3.html create mode 100644 final/docs/tutorial/LangImpl4.html create mode 100644 final/docs/tutorial/LangImpl5-cfg.png create mode 100644 final/docs/tutorial/LangImpl5.html create mode 100644 final/docs/tutorial/LangImpl6.html create mode 100644 final/docs/tutorial/LangImpl7.html create mode 100644 final/docs/tutorial/LangImpl8.html create mode 100644 final/docs/tutorial/Makefile create mode 100644 final/docs/tutorial/OCamlLangImpl1.html create mode 100644 final/docs/tutorial/OCamlLangImpl2.html create mode 100644 final/docs/tutorial/OCamlLangImpl3.html create mode 100644 final/docs/tutorial/OCamlLangImpl4.html create mode 100644 final/docs/tutorial/OCamlLangImpl5.html create mode 100644 final/docs/tutorial/OCamlLangImpl6.html create mode 100644 final/docs/tutorial/OCamlLangImpl7.html create mode 100644 final/docs/tutorial/OCamlLangImpl8.html create mode 100644 final/docs/tutorial/index.html create mode 100644 final/examples/BrainF/BrainF.cpp create mode 100644 final/examples/BrainF/BrainF.h create mode 100644 final/examples/BrainF/BrainFDriver.cpp create mode 100644 final/examples/BrainF/CMakeLists.txt create mode 100644 final/examples/BrainF/Makefile create mode 100644 final/examples/CMakeLists.txt create mode 100644 final/examples/ExceptionDemo/CMakeLists.txt create mode 100644 final/examples/ExceptionDemo/ExceptionDemo.cpp create mode 100644 final/examples/ExceptionDemo/Makefile create mode 100644 final/examples/Fibonacci/CMakeLists.txt create mode 100644 final/examples/Fibonacci/Makefile create mode 100644 final/examples/Fibonacci/fibonacci.cpp create mode 100644 final/examples/HowToUseJIT/CMakeLists.txt create mode 100644 final/examples/HowToUseJIT/HowToUseJIT.cpp create mode 100644 final/examples/HowToUseJIT/Makefile create mode 100644 final/examples/Kaleidoscope/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter2/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter2/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter2/toy.cpp create mode 100644 final/examples/Kaleidoscope/Chapter3/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter3/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter3/toy.cpp create mode 100644 final/examples/Kaleidoscope/Chapter4/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter4/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter4/toy.cpp create mode 100644 final/examples/Kaleidoscope/Chapter5/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter5/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter5/toy.cpp create mode 100644 final/examples/Kaleidoscope/Chapter6/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter6/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter6/toy.cpp create mode 100644 final/examples/Kaleidoscope/Chapter7/CMakeLists.txt create mode 100644 final/examples/Kaleidoscope/Chapter7/Makefile create mode 100644 final/examples/Kaleidoscope/Chapter7/toy.cpp create mode 100644 final/examples/Kaleidoscope/Makefile create mode 100644 final/examples/Makefile create mode 100644 final/examples/ModuleMaker/CMakeLists.txt create mode 100644 final/examples/ModuleMaker/Makefile create mode 100644 final/examples/ModuleMaker/ModuleMaker.cpp create mode 100644 final/examples/ModuleMaker/README.txt create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter2/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter3/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/bindings.c create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/codegen.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter4/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/bindings.c create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/codegen.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter5/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/bindings.c create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/codegen.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter6/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/Makefile create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/_tags create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/ast.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/bindings.c create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/codegen.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/lexer.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/parser.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/token.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Chapter7/toy.ml create mode 100644 final/examples/OCaml-Kaleidoscope/Makefile create mode 100644 final/examples/ParallelJIT/CMakeLists.txt create mode 100644 final/examples/ParallelJIT/Makefile create mode 100644 final/examples/ParallelJIT/ParallelJIT.cpp create mode 100644 final/include/llvm-c/Analysis.h create mode 100644 final/include/llvm-c/BitReader.h create mode 100644 final/include/llvm-c/BitWriter.h create mode 100644 final/include/llvm-c/Core.h create mode 100644 final/include/llvm-c/EnhancedDisassembly.h create mode 100644 final/include/llvm-c/ExecutionEngine.h create mode 100644 final/include/llvm-c/Initialization.h create mode 100644 final/include/llvm-c/LinkTimeOptimizer.h create mode 100644 final/include/llvm-c/Target.h create mode 100644 final/include/llvm-c/Transforms/IPO.h create mode 100644 final/include/llvm-c/Transforms/Scalar.h create mode 100644 final/include/llvm-c/lto.h create mode 100644 final/include/llvm/ADT/APFloat.h create mode 100644 final/include/llvm/ADT/APInt.h create mode 100644 final/include/llvm/ADT/APSInt.h create mode 100644 final/include/llvm/ADT/ArrayRef.h create mode 100644 final/include/llvm/ADT/BitVector.h create mode 100644 final/include/llvm/ADT/DAGDeltaAlgorithm.h create mode 100644 final/include/llvm/ADT/DeltaAlgorithm.h create mode 100644 final/include/llvm/ADT/DenseMap.h create mode 100644 final/include/llvm/ADT/DenseMapInfo.h create mode 100644 final/include/llvm/ADT/DenseSet.h create mode 100644 final/include/llvm/ADT/DepthFirstIterator.h create mode 100644 final/include/llvm/ADT/EquivalenceClasses.h create mode 100644 final/include/llvm/ADT/FoldingSet.h create mode 100644 final/include/llvm/ADT/GraphTraits.h create mode 100644 final/include/llvm/ADT/ImmutableIntervalMap.h create mode 100644 final/include/llvm/ADT/ImmutableList.h create mode 100644 final/include/llvm/ADT/ImmutableMap.h create mode 100644 final/include/llvm/ADT/ImmutableSet.h create mode 100644 final/include/llvm/ADT/InMemoryStruct.h create mode 100644 final/include/llvm/ADT/IndexedMap.h create mode 100644 final/include/llvm/ADT/IntEqClasses.h create mode 100644 final/include/llvm/ADT/IntervalMap.h create mode 100644 final/include/llvm/ADT/IntrusiveRefCntPtr.h create mode 100644 final/include/llvm/ADT/NullablePtr.h create mode 100644 final/include/llvm/ADT/Optional.h create mode 100644 final/include/llvm/ADT/OwningPtr.h create mode 100644 final/include/llvm/ADT/PointerIntPair.h create mode 100644 final/include/llvm/ADT/PointerUnion.h create mode 100644 final/include/llvm/ADT/PostOrderIterator.h create mode 100644 final/include/llvm/ADT/PriorityQueue.h create mode 100644 final/include/llvm/ADT/SCCIterator.h create mode 100644 final/include/llvm/ADT/STLExtras.h create mode 100644 final/include/llvm/ADT/ScopedHashTable.h create mode 100644 final/include/llvm/ADT/SetOperations.h create mode 100644 final/include/llvm/ADT/SetVector.h create mode 100644 final/include/llvm/ADT/SmallBitVector.h create mode 100644 final/include/llvm/ADT/SmallPtrSet.h create mode 100644 final/include/llvm/ADT/SmallSet.h create mode 100644 final/include/llvm/ADT/SmallString.h create mode 100644 final/include/llvm/ADT/SmallVector.h create mode 100644 final/include/llvm/ADT/SparseBitVector.h create mode 100644 final/include/llvm/ADT/Statistic.h create mode 100644 final/include/llvm/ADT/StringExtras.h create mode 100644 final/include/llvm/ADT/StringMap.h create mode 100644 final/include/llvm/ADT/StringRef.h create mode 100644 final/include/llvm/ADT/StringSet.h create mode 100644 final/include/llvm/ADT/StringSwitch.h create mode 100644 final/include/llvm/ADT/Trie.h create mode 100644 final/include/llvm/ADT/Triple.h create mode 100644 final/include/llvm/ADT/Twine.h create mode 100644 final/include/llvm/ADT/UniqueVector.h create mode 100644 final/include/llvm/ADT/ValueMap.h create mode 100644 final/include/llvm/ADT/VectorExtras.h create mode 100644 final/include/llvm/ADT/ilist.h create mode 100644 final/include/llvm/ADT/ilist_node.h create mode 100644 final/include/llvm/AbstractTypeUser.h create mode 100644 final/include/llvm/Analysis/AliasAnalysis.h create mode 100644 final/include/llvm/Analysis/AliasSetTracker.h create mode 100644 final/include/llvm/Analysis/CFGPrinter.h create mode 100644 final/include/llvm/Analysis/CallGraph.h create mode 100644 final/include/llvm/Analysis/CaptureTracking.h create mode 100644 final/include/llvm/Analysis/CodeMetrics.h create mode 100644 final/include/llvm/Analysis/ConstantFolding.h create mode 100644 final/include/llvm/Analysis/ConstantsScanner.h create mode 100644 final/include/llvm/Analysis/DIBuilder.h create mode 100644 final/include/llvm/Analysis/DOTGraphTraitsPass.h create mode 100644 final/include/llvm/Analysis/DebugInfo.h create mode 100644 final/include/llvm/Analysis/DomPrinter.h create mode 100644 final/include/llvm/Analysis/DominanceFrontier.h create mode 100644 final/include/llvm/Analysis/DominatorInternals.h create mode 100644 final/include/llvm/Analysis/Dominators.h create mode 100644 final/include/llvm/Analysis/FindUsedTypes.h create mode 100644 final/include/llvm/Analysis/IVUsers.h create mode 100644 final/include/llvm/Analysis/InlineCost.h create mode 100644 final/include/llvm/Analysis/InstructionSimplify.h create mode 100644 final/include/llvm/Analysis/Interval.h create mode 100644 final/include/llvm/Analysis/IntervalIterator.h create mode 100644 final/include/llvm/Analysis/IntervalPartition.h create mode 100644 final/include/llvm/Analysis/LazyValueInfo.h create mode 100644 final/include/llvm/Analysis/LibCallAliasAnalysis.h create mode 100644 final/include/llvm/Analysis/LibCallSemantics.h create mode 100644 final/include/llvm/Analysis/Lint.h create mode 100644 final/include/llvm/Analysis/Loads.h create mode 100644 final/include/llvm/Analysis/LoopDependenceAnalysis.h create mode 100644 final/include/llvm/Analysis/LoopInfo.h create mode 100644 final/include/llvm/Analysis/LoopPass.h create mode 100644 final/include/llvm/Analysis/MemoryBuiltins.h create mode 100644 final/include/llvm/Analysis/MemoryDependenceAnalysis.h create mode 100644 final/include/llvm/Analysis/PHITransAddr.h create mode 100644 final/include/llvm/Analysis/Passes.h create mode 100644 final/include/llvm/Analysis/PathNumbering.h create mode 100644 final/include/llvm/Analysis/PathProfileInfo.h create mode 100644 final/include/llvm/Analysis/PostDominators.h create mode 100644 final/include/llvm/Analysis/ProfileInfo.h create mode 100644 final/include/llvm/Analysis/ProfileInfoLoader.h create mode 100644 final/include/llvm/Analysis/ProfileInfoTypes.h create mode 100644 final/include/llvm/Analysis/RegionInfo.h create mode 100644 final/include/llvm/Analysis/RegionIterator.h create mode 100644 final/include/llvm/Analysis/RegionPass.h create mode 100644 final/include/llvm/Analysis/RegionPrinter.h create mode 100644 final/include/llvm/Analysis/ScalarEvolution.h create mode 100644 final/include/llvm/Analysis/ScalarEvolutionExpander.h create mode 100644 final/include/llvm/Analysis/ScalarEvolutionExpressions.h create mode 100644 final/include/llvm/Analysis/ScalarEvolutionNormalization.h create mode 100644 final/include/llvm/Analysis/SparsePropagation.h create mode 100644 final/include/llvm/Analysis/Trace.h create mode 100644 final/include/llvm/Analysis/ValueTracking.h create mode 100644 final/include/llvm/Analysis/Verifier.h create mode 100644 final/include/llvm/Argument.h create mode 100644 final/include/llvm/Assembly/AssemblyAnnotationWriter.h create mode 100644 final/include/llvm/Assembly/Parser.h create mode 100644 final/include/llvm/Assembly/PrintModulePass.h create mode 100644 final/include/llvm/Assembly/Writer.h create mode 100644 final/include/llvm/Attributes.h create mode 100644 final/include/llvm/AutoUpgrade.h create mode 100644 final/include/llvm/BasicBlock.h create mode 100644 final/include/llvm/Bitcode/Archive.h create mode 100644 final/include/llvm/Bitcode/BitCodes.h create mode 100644 final/include/llvm/Bitcode/BitstreamReader.h create mode 100644 final/include/llvm/Bitcode/BitstreamWriter.h create mode 100644 final/include/llvm/Bitcode/LLVMBitCodes.h create mode 100644 final/include/llvm/Bitcode/ReaderWriter.h create mode 100644 final/include/llvm/CMakeLists.txt create mode 100644 final/include/llvm/CallGraphSCCPass.h create mode 100644 final/include/llvm/CallingConv.h create mode 100644 final/include/llvm/CodeGen/Analysis.h create mode 100644 final/include/llvm/CodeGen/AsmPrinter.h create mode 100644 final/include/llvm/CodeGen/BinaryObject.h create mode 100644 final/include/llvm/CodeGen/CalcSpillWeights.h create mode 100644 final/include/llvm/CodeGen/CallingConvLower.h create mode 100644 final/include/llvm/CodeGen/EdgeBundles.h create mode 100644 final/include/llvm/CodeGen/FastISel.h create mode 100644 final/include/llvm/CodeGen/FunctionLoweringInfo.h create mode 100644 final/include/llvm/CodeGen/GCMetadata.h create mode 100644 final/include/llvm/CodeGen/GCMetadataPrinter.h create mode 100644 final/include/llvm/CodeGen/GCStrategy.h create mode 100644 final/include/llvm/CodeGen/GCs.h create mode 100644 final/include/llvm/CodeGen/ISDOpcodes.h create mode 100644 final/include/llvm/CodeGen/IntrinsicLowering.h create mode 100644 final/include/llvm/CodeGen/JITCodeEmitter.h create mode 100644 final/include/llvm/CodeGen/LatencyPriorityQueue.h create mode 100644 final/include/llvm/CodeGen/LinkAllAsmWriterComponents.h create mode 100644 final/include/llvm/CodeGen/LinkAllCodegenComponents.h create mode 100644 final/include/llvm/CodeGen/LiveInterval.h create mode 100644 final/include/llvm/CodeGen/LiveIntervalAnalysis.h create mode 100644 final/include/llvm/CodeGen/LiveStackAnalysis.h create mode 100644 final/include/llvm/CodeGen/LiveVariables.h create mode 100644 final/include/llvm/CodeGen/MachORelocation.h create mode 100644 final/include/llvm/CodeGen/MachineBasicBlock.h create mode 100644 final/include/llvm/CodeGen/MachineCodeEmitter.h create mode 100644 final/include/llvm/CodeGen/MachineCodeInfo.h create mode 100644 final/include/llvm/CodeGen/MachineConstantPool.h create mode 100644 final/include/llvm/CodeGen/MachineDominators.h create mode 100644 final/include/llvm/CodeGen/MachineFrameInfo.h create mode 100644 final/include/llvm/CodeGen/MachineFunction.h create mode 100644 final/include/llvm/CodeGen/MachineFunctionAnalysis.h create mode 100644 final/include/llvm/CodeGen/MachineFunctionPass.h create mode 100644 final/include/llvm/CodeGen/MachineInstr.h create mode 100644 final/include/llvm/CodeGen/MachineInstrBuilder.h create mode 100644 final/include/llvm/CodeGen/MachineJumpTableInfo.h create mode 100644 final/include/llvm/CodeGen/MachineLocation.h create mode 100644 final/include/llvm/CodeGen/MachineLoopInfo.h create mode 100644 final/include/llvm/CodeGen/MachineLoopRanges.h create mode 100644 final/include/llvm/CodeGen/MachineMemOperand.h create mode 100644 final/include/llvm/CodeGen/MachineModuleInfo.h create mode 100644 final/include/llvm/CodeGen/MachineModuleInfoImpls.h create mode 100644 final/include/llvm/CodeGen/MachineOperand.h create mode 100644 final/include/llvm/CodeGen/MachinePassRegistry.h create mode 100644 final/include/llvm/CodeGen/MachineRegisterInfo.h create mode 100644 final/include/llvm/CodeGen/MachineRelocation.h create mode 100644 final/include/llvm/CodeGen/MachineSSAUpdater.h create mode 100644 final/include/llvm/CodeGen/ObjectCodeEmitter.h create mode 100644 final/include/llvm/CodeGen/PBQP/Graph.h create mode 100644 final/include/llvm/CodeGen/PBQP/HeuristicBase.h create mode 100644 final/include/llvm/CodeGen/PBQP/HeuristicSolver.h create mode 100644 final/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h create mode 100644 final/include/llvm/CodeGen/PBQP/Math.h create mode 100644 final/include/llvm/CodeGen/PBQP/Solution.h create mode 100644 final/include/llvm/CodeGen/Passes.h create mode 100644 final/include/llvm/CodeGen/ProcessImplicitDefs.h create mode 100644 final/include/llvm/CodeGen/PseudoSourceValue.h create mode 100644 final/include/llvm/CodeGen/RegAllocPBQP.h create mode 100644 final/include/llvm/CodeGen/RegAllocRegistry.h create mode 100644 final/include/llvm/CodeGen/RegisterCoalescer.h create mode 100644 final/include/llvm/CodeGen/RegisterScavenging.h create mode 100644 final/include/llvm/CodeGen/RuntimeLibcalls.h create mode 100644 final/include/llvm/CodeGen/ScheduleDAG.h create mode 100644 final/include/llvm/CodeGen/ScheduleHazardRecognizer.h create mode 100644 final/include/llvm/CodeGen/SchedulerRegistry.h create mode 100644 final/include/llvm/CodeGen/ScoreboardHazardRecognizer.h create mode 100644 final/include/llvm/CodeGen/SelectionDAG.h create mode 100644 final/include/llvm/CodeGen/SelectionDAGISel.h create mode 100644 final/include/llvm/CodeGen/SelectionDAGNodes.h create mode 100644 final/include/llvm/CodeGen/SlotIndexes.h create mode 100644 final/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h create mode 100644 final/include/llvm/CodeGen/ValueTypes.h create mode 100644 final/include/llvm/CodeGen/ValueTypes.td create mode 100644 final/include/llvm/CompilerDriver/Action.h create mode 100644 final/include/llvm/CompilerDriver/AutoGenerated.h create mode 100644 final/include/llvm/CompilerDriver/BuiltinOptions.h create mode 100644 final/include/llvm/CompilerDriver/Common.td create mode 100644 final/include/llvm/CompilerDriver/CompilationGraph.h create mode 100644 final/include/llvm/CompilerDriver/Error.h create mode 100644 final/include/llvm/CompilerDriver/Main.h create mode 100644 final/include/llvm/CompilerDriver/Main.inc create mode 100644 final/include/llvm/CompilerDriver/Tool.h create mode 100644 final/include/llvm/Config/AsmParsers.def.in create mode 100644 final/include/llvm/Config/AsmPrinters.def.in create mode 100644 final/include/llvm/Config/Disassemblers.def.in create mode 100644 final/include/llvm/Config/Targets.def.in create mode 100644 final/include/llvm/Config/config.h.cmake create mode 100644 final/include/llvm/Config/config.h.in create mode 100644 final/include/llvm/Config/llvm-config.h.cmake create mode 100644 final/include/llvm/Config/llvm-config.h.in create mode 100644 final/include/llvm/Constant.h create mode 100644 final/include/llvm/Constants.h create mode 100644 final/include/llvm/DerivedTypes.h create mode 100644 final/include/llvm/ExecutionEngine/ExecutionEngine.h create mode 100644 final/include/llvm/ExecutionEngine/GenericValue.h create mode 100644 final/include/llvm/ExecutionEngine/Interpreter.h create mode 100644 final/include/llvm/ExecutionEngine/JIT.h create mode 100644 final/include/llvm/ExecutionEngine/JITEventListener.h create mode 100644 final/include/llvm/ExecutionEngine/JITMemoryManager.h create mode 100644 final/include/llvm/ExecutionEngine/MCJIT.h create mode 100644 final/include/llvm/Function.h create mode 100644 final/include/llvm/GVMaterializer.h create mode 100644 final/include/llvm/GlobalAlias.h create mode 100644 final/include/llvm/GlobalValue.h create mode 100644 final/include/llvm/GlobalVariable.h create mode 100644 final/include/llvm/InitializePasses.h create mode 100644 final/include/llvm/InlineAsm.h create mode 100644 final/include/llvm/InstrTypes.h create mode 100644 final/include/llvm/Instruction.def create mode 100644 final/include/llvm/Instruction.h create mode 100644 final/include/llvm/Instructions.h create mode 100644 final/include/llvm/IntrinsicInst.h create mode 100644 final/include/llvm/Intrinsics.h create mode 100644 final/include/llvm/Intrinsics.td create mode 100644 final/include/llvm/IntrinsicsARM.td create mode 100644 final/include/llvm/IntrinsicsAlpha.td create mode 100644 final/include/llvm/IntrinsicsCellSPU.td create mode 100644 final/include/llvm/IntrinsicsPTX.td create mode 100644 final/include/llvm/IntrinsicsPowerPC.td create mode 100644 final/include/llvm/IntrinsicsX86.td create mode 100644 final/include/llvm/IntrinsicsXCore.td create mode 100644 final/include/llvm/LLVMContext.h create mode 100644 final/include/llvm/LinkAllPasses.h create mode 100644 final/include/llvm/LinkAllVMCore.h create mode 100644 final/include/llvm/Linker.h create mode 100644 final/include/llvm/MC/EDInstInfo.h create mode 100644 final/include/llvm/MC/MCAsmInfo.h create mode 100644 final/include/llvm/MC/MCAsmInfoCOFF.h create mode 100644 final/include/llvm/MC/MCAsmInfoDarwin.h create mode 100644 final/include/llvm/MC/MCAsmLayout.h create mode 100644 final/include/llvm/MC/MCAssembler.h create mode 100644 final/include/llvm/MC/MCCodeEmitter.h create mode 100644 final/include/llvm/MC/MCContext.h create mode 100644 final/include/llvm/MC/MCDirectives.h create mode 100644 final/include/llvm/MC/MCDisassembler.h create mode 100644 final/include/llvm/MC/MCDwarf.h create mode 100644 final/include/llvm/MC/MCELFObjectWriter.h create mode 100644 final/include/llvm/MC/MCELFSymbolFlags.h create mode 100644 final/include/llvm/MC/MCExpr.h create mode 100644 final/include/llvm/MC/MCFixup.h create mode 100644 final/include/llvm/MC/MCFixupKindInfo.h create mode 100644 final/include/llvm/MC/MCInst.h create mode 100644 final/include/llvm/MC/MCInstPrinter.h create mode 100644 final/include/llvm/MC/MCLabel.h create mode 100644 final/include/llvm/MC/MCMachOSymbolFlags.h create mode 100644 final/include/llvm/MC/MCMachObjectWriter.h create mode 100644 final/include/llvm/MC/MCObjectStreamer.h create mode 100644 final/include/llvm/MC/MCObjectWriter.h create mode 100644 final/include/llvm/MC/MCParser/AsmCond.h create mode 100644 final/include/llvm/MC/MCParser/AsmLexer.h create mode 100644 final/include/llvm/MC/MCParser/MCAsmLexer.h create mode 100644 final/include/llvm/MC/MCParser/MCAsmParser.h create mode 100644 final/include/llvm/MC/MCParser/MCAsmParserExtension.h create mode 100644 final/include/llvm/MC/MCParser/MCParsedAsmOperand.h create mode 100644 final/include/llvm/MC/MCSection.h create mode 100644 final/include/llvm/MC/MCSectionCOFF.h create mode 100644 final/include/llvm/MC/MCSectionELF.h create mode 100644 final/include/llvm/MC/MCSectionMachO.h create mode 100644 final/include/llvm/MC/MCStreamer.h create mode 100644 final/include/llvm/MC/MCSymbol.h create mode 100644 final/include/llvm/MC/MCValue.h create mode 100644 final/include/llvm/MC/SectionKind.h create mode 100644 final/include/llvm/Metadata.h create mode 100644 final/include/llvm/Module.h create mode 100644 final/include/llvm/Object/MachOFormat.h create mode 100644 final/include/llvm/Object/MachOObject.h create mode 100644 final/include/llvm/Object/ObjectFile.h create mode 100644 final/include/llvm/OperandTraits.h create mode 100644 final/include/llvm/Operator.h create mode 100644 final/include/llvm/Pass.h create mode 100644 final/include/llvm/PassAnalysisSupport.h create mode 100644 final/include/llvm/PassManager.h create mode 100644 final/include/llvm/PassManagers.h create mode 100644 final/include/llvm/PassRegistry.h create mode 100644 final/include/llvm/PassSupport.h create mode 100644 final/include/llvm/Support/AIXDataTypesFix.h create mode 100644 final/include/llvm/Support/AlignOf.h create mode 100644 final/include/llvm/Support/Allocator.h create mode 100644 final/include/llvm/Support/Atomic.h create mode 100644 final/include/llvm/Support/CFG.h create mode 100644 final/include/llvm/Support/COFF.h create mode 100644 final/include/llvm/Support/CallSite.h create mode 100644 final/include/llvm/Support/Casting.h create mode 100644 final/include/llvm/Support/CommandLine.h create mode 100644 final/include/llvm/Support/Compiler.h create mode 100644 final/include/llvm/Support/ConstantFolder.h create mode 100644 final/include/llvm/Support/ConstantRange.h create mode 100644 final/include/llvm/Support/CrashRecoveryContext.h create mode 100644 final/include/llvm/Support/DOTGraphTraits.h create mode 100644 final/include/llvm/Support/DataFlow.h create mode 100644 final/include/llvm/Support/DataTypes.h.cmake create mode 100644 final/include/llvm/Support/DataTypes.h.in create mode 100644 final/include/llvm/Support/Debug.h create mode 100644 final/include/llvm/Support/DebugLoc.h create mode 100644 final/include/llvm/Support/Disassembler.h create mode 100644 final/include/llvm/Support/Dwarf.h create mode 100644 final/include/llvm/Support/DynamicLibrary.h create mode 100644 final/include/llvm/Support/ELF.h create mode 100644 final/include/llvm/Support/Endian.h create mode 100644 final/include/llvm/Support/Errno.h create mode 100644 final/include/llvm/Support/ErrorHandling.h create mode 100644 final/include/llvm/Support/FEnv.h create mode 100644 final/include/llvm/Support/FileSystem.h create mode 100644 final/include/llvm/Support/FileUtilities.h create mode 100644 final/include/llvm/Support/Format.h create mode 100644 final/include/llvm/Support/FormattedStream.h create mode 100644 final/include/llvm/Support/GetElementPtrTypeIterator.h create mode 100644 final/include/llvm/Support/GraphWriter.h create mode 100644 final/include/llvm/Support/Host.h create mode 100644 final/include/llvm/Support/IRBuilder.h create mode 100644 final/include/llvm/Support/IRReader.h create mode 100644 final/include/llvm/Support/IncludeFile.h create mode 100644 final/include/llvm/Support/InstIterator.h create mode 100644 final/include/llvm/Support/InstVisitor.h create mode 100644 final/include/llvm/Support/LICENSE.TXT create mode 100644 final/include/llvm/Support/LeakDetector.h create mode 100644 final/include/llvm/Support/MachO.h create mode 100644 final/include/llvm/Support/ManagedStatic.h create mode 100644 final/include/llvm/Support/MathExtras.h create mode 100644 final/include/llvm/Support/Memory.h create mode 100644 final/include/llvm/Support/MemoryBuffer.h create mode 100644 final/include/llvm/Support/MemoryObject.h create mode 100644 final/include/llvm/Support/Mutex.h create mode 100644 final/include/llvm/Support/MutexGuard.h create mode 100644 final/include/llvm/Support/NoFolder.h create mode 100644 final/include/llvm/Support/OutputBuffer.h create mode 100644 final/include/llvm/Support/PassNameParser.h create mode 100644 final/include/llvm/Support/Path.h create mode 100644 final/include/llvm/Support/PathV1.h create mode 100644 final/include/llvm/Support/PathV2.h create mode 100644 final/include/llvm/Support/PatternMatch.h create mode 100644 final/include/llvm/Support/PluginLoader.h create mode 100644 final/include/llvm/Support/PointerLikeTypeTraits.h create mode 100644 final/include/llvm/Support/PredIteratorCache.h create mode 100644 final/include/llvm/Support/PrettyStackTrace.h create mode 100644 final/include/llvm/Support/Process.h create mode 100644 final/include/llvm/Support/Program.h create mode 100644 final/include/llvm/Support/RWMutex.h create mode 100644 final/include/llvm/Support/Recycler.h create mode 100644 final/include/llvm/Support/RecyclingAllocator.h create mode 100644 final/include/llvm/Support/Regex.h create mode 100644 final/include/llvm/Support/Registry.h create mode 100644 final/include/llvm/Support/RegistryParser.h create mode 100644 final/include/llvm/Support/SMLoc.h create mode 100644 final/include/llvm/Support/Signals.h create mode 100644 final/include/llvm/Support/Solaris.h create mode 100644 final/include/llvm/Support/SourceMgr.h create mode 100644 final/include/llvm/Support/StandardPasses.h create mode 100644 final/include/llvm/Support/StringPool.h create mode 100644 final/include/llvm/Support/SwapByteOrder.h create mode 100644 final/include/llvm/Support/SystemUtils.h create mode 100644 final/include/llvm/Support/TargetFolder.h create mode 100644 final/include/llvm/Support/ThreadLocal.h create mode 100644 final/include/llvm/Support/Threading.h create mode 100644 final/include/llvm/Support/TimeValue.h create mode 100644 final/include/llvm/Support/Timer.h create mode 100644 final/include/llvm/Support/ToolOutputFile.h create mode 100644 final/include/llvm/Support/TypeBuilder.h create mode 100644 final/include/llvm/Support/Valgrind.h create mode 100644 final/include/llvm/Support/ValueHandle.h create mode 100644 final/include/llvm/Support/circular_raw_ostream.h create mode 100644 final/include/llvm/Support/raw_os_ostream.h create mode 100644 final/include/llvm/Support/raw_ostream.h create mode 100644 final/include/llvm/Support/system_error.h create mode 100644 final/include/llvm/Support/type_traits.h create mode 100644 final/include/llvm/SymbolTableListTraits.h create mode 100644 final/include/llvm/Target/Mangler.h create mode 100644 final/include/llvm/Target/SubtargetFeature.h create mode 100644 final/include/llvm/Target/Target.td create mode 100644 final/include/llvm/Target/TargetAsmBackend.h create mode 100644 final/include/llvm/Target/TargetAsmInfo.h create mode 100644 final/include/llvm/Target/TargetAsmLexer.h create mode 100644 final/include/llvm/Target/TargetAsmParser.h create mode 100644 final/include/llvm/Target/TargetCallingConv.h create mode 100644 final/include/llvm/Target/TargetCallingConv.td create mode 100644 final/include/llvm/Target/TargetData.h create mode 100644 final/include/llvm/Target/TargetELFWriterInfo.h create mode 100644 final/include/llvm/Target/TargetFrameLowering.h create mode 100644 final/include/llvm/Target/TargetInstrDesc.h create mode 100644 final/include/llvm/Target/TargetInstrInfo.h create mode 100644 final/include/llvm/Target/TargetInstrItineraries.h create mode 100644 final/include/llvm/Target/TargetIntrinsicInfo.h create mode 100644 final/include/llvm/Target/TargetJITInfo.h create mode 100644 final/include/llvm/Target/TargetLibraryInfo.h create mode 100644 final/include/llvm/Target/TargetLowering.h create mode 100644 final/include/llvm/Target/TargetLoweringObjectFile.h create mode 100644 final/include/llvm/Target/TargetMachine.h create mode 100644 final/include/llvm/Target/TargetOpcodes.h create mode 100644 final/include/llvm/Target/TargetOptions.h create mode 100644 final/include/llvm/Target/TargetRegisterInfo.h create mode 100644 final/include/llvm/Target/TargetRegistry.h create mode 100644 final/include/llvm/Target/TargetSchedule.td create mode 100644 final/include/llvm/Target/TargetSelect.h create mode 100644 final/include/llvm/Target/TargetSelectionDAG.td create mode 100644 final/include/llvm/Target/TargetSelectionDAGInfo.h create mode 100644 final/include/llvm/Target/TargetSubtarget.h create mode 100644 final/include/llvm/Transforms/IPO.h create mode 100644 final/include/llvm/Transforms/IPO/InlinerPass.h create mode 100644 final/include/llvm/Transforms/Instrumentation.h create mode 100644 final/include/llvm/Transforms/Scalar.h create mode 100644 final/include/llvm/Transforms/Utils/AddrModeMatcher.h create mode 100644 final/include/llvm/Transforms/Utils/BasicBlockUtils.h create mode 100644 final/include/llvm/Transforms/Utils/BasicInliner.h create mode 100644 final/include/llvm/Transforms/Utils/BuildLibCalls.h create mode 100644 final/include/llvm/Transforms/Utils/Cloning.h create mode 100644 final/include/llvm/Transforms/Utils/FunctionUtils.h create mode 100644 final/include/llvm/Transforms/Utils/Local.h create mode 100644 final/include/llvm/Transforms/Utils/PromoteMemToReg.h create mode 100644 final/include/llvm/Transforms/Utils/SSAUpdater.h create mode 100644 final/include/llvm/Transforms/Utils/SSAUpdaterImpl.h create mode 100644 final/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h create mode 100644 final/include/llvm/Transforms/Utils/UnrollLoop.h create mode 100644 final/include/llvm/Transforms/Utils/ValueMapper.h create mode 100644 final/include/llvm/Type.h create mode 100644 final/include/llvm/TypeSymbolTable.h create mode 100644 final/include/llvm/Use.h create mode 100644 final/include/llvm/User.h create mode 100644 final/include/llvm/Value.h create mode 100644 final/include/llvm/ValueSymbolTable.h create mode 100644 final/lib/Analysis/AliasAnalysis.cpp create mode 100644 final/lib/Analysis/AliasAnalysisCounter.cpp create mode 100644 final/lib/Analysis/AliasAnalysisEvaluator.cpp create mode 100644 final/lib/Analysis/AliasDebugger.cpp create mode 100644 final/lib/Analysis/AliasSetTracker.cpp create mode 100644 final/lib/Analysis/Analysis.cpp create mode 100644 final/lib/Analysis/BasicAliasAnalysis.cpp create mode 100644 final/lib/Analysis/CFGPrinter.cpp create mode 100644 final/lib/Analysis/CMakeLists.txt create mode 100644 final/lib/Analysis/CaptureTracking.cpp create mode 100644 final/lib/Analysis/ConstantFolding.cpp create mode 100644 final/lib/Analysis/DIBuilder.cpp create mode 100644 final/lib/Analysis/DbgInfoPrinter.cpp create mode 100644 final/lib/Analysis/DebugInfo.cpp create mode 100644 final/lib/Analysis/DomPrinter.cpp create mode 100644 final/lib/Analysis/DominanceFrontier.cpp create mode 100644 final/lib/Analysis/IPA/CMakeLists.txt create mode 100644 final/lib/Analysis/IPA/CallGraph.cpp create mode 100644 final/lib/Analysis/IPA/CallGraphSCCPass.cpp create mode 100644 final/lib/Analysis/IPA/FindUsedTypes.cpp create mode 100644 final/lib/Analysis/IPA/GlobalsModRef.cpp create mode 100644 final/lib/Analysis/IPA/IPA.cpp create mode 100644 final/lib/Analysis/IPA/Makefile create mode 100644 final/lib/Analysis/IVUsers.cpp create mode 100644 final/lib/Analysis/InlineCost.cpp create mode 100644 final/lib/Analysis/InstCount.cpp create mode 100644 final/lib/Analysis/InstructionSimplify.cpp create mode 100644 final/lib/Analysis/Interval.cpp create mode 100644 final/lib/Analysis/IntervalPartition.cpp create mode 100644 final/lib/Analysis/LazyValueInfo.cpp create mode 100644 final/lib/Analysis/LibCallAliasAnalysis.cpp create mode 100644 final/lib/Analysis/LibCallSemantics.cpp create mode 100644 final/lib/Analysis/Lint.cpp create mode 100644 final/lib/Analysis/Loads.cpp create mode 100644 final/lib/Analysis/LoopDependenceAnalysis.cpp create mode 100644 final/lib/Analysis/LoopInfo.cpp create mode 100644 final/lib/Analysis/LoopPass.cpp create mode 100644 final/lib/Analysis/Makefile create mode 100644 final/lib/Analysis/MemDepPrinter.cpp create mode 100644 final/lib/Analysis/MemoryBuiltins.cpp create mode 100644 final/lib/Analysis/MemoryDependenceAnalysis.cpp create mode 100644 final/lib/Analysis/ModuleDebugInfoPrinter.cpp create mode 100644 final/lib/Analysis/NoAliasAnalysis.cpp create mode 100644 final/lib/Analysis/PHITransAddr.cpp create mode 100644 final/lib/Analysis/PathNumbering.cpp create mode 100644 final/lib/Analysis/PathProfileInfo.cpp create mode 100644 final/lib/Analysis/PathProfileVerifier.cpp create mode 100644 final/lib/Analysis/PostDominators.cpp create mode 100644 final/lib/Analysis/ProfileEstimatorPass.cpp create mode 100644 final/lib/Analysis/ProfileInfo.cpp create mode 100644 final/lib/Analysis/ProfileInfoLoader.cpp create mode 100644 final/lib/Analysis/ProfileInfoLoaderPass.cpp create mode 100644 final/lib/Analysis/ProfileVerifierPass.cpp create mode 100644 final/lib/Analysis/README.txt create mode 100644 final/lib/Analysis/RegionInfo.cpp create mode 100644 final/lib/Analysis/RegionPass.cpp create mode 100644 final/lib/Analysis/RegionPrinter.cpp create mode 100644 final/lib/Analysis/ScalarEvolution.cpp create mode 100644 final/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp create mode 100644 final/lib/Analysis/ScalarEvolutionExpander.cpp create mode 100644 final/lib/Analysis/ScalarEvolutionNormalization.cpp create mode 100644 final/lib/Analysis/SparsePropagation.cpp create mode 100644 final/lib/Analysis/Trace.cpp create mode 100644 final/lib/Analysis/TypeBasedAliasAnalysis.cpp create mode 100644 final/lib/Analysis/ValueTracking.cpp create mode 100644 final/lib/Archive/Archive.cpp create mode 100644 final/lib/Archive/ArchiveInternals.h create mode 100644 final/lib/Archive/ArchiveReader.cpp create mode 100644 final/lib/Archive/ArchiveWriter.cpp create mode 100644 final/lib/Archive/CMakeLists.txt create mode 100644 final/lib/Archive/Makefile create mode 100644 final/lib/AsmParser/CMakeLists.txt create mode 100644 final/lib/AsmParser/LLLexer.cpp create mode 100644 final/lib/AsmParser/LLLexer.h create mode 100644 final/lib/AsmParser/LLParser.cpp create mode 100644 final/lib/AsmParser/LLParser.h create mode 100644 final/lib/AsmParser/LLToken.h create mode 100644 final/lib/AsmParser/Makefile create mode 100644 final/lib/AsmParser/Parser.cpp create mode 100644 final/lib/Bitcode/CMakeLists.txt create mode 100644 final/lib/Bitcode/Makefile create mode 100644 final/lib/Bitcode/Reader/BitReader.cpp create mode 100644 final/lib/Bitcode/Reader/BitcodeReader.cpp create mode 100644 final/lib/Bitcode/Reader/BitcodeReader.h create mode 100644 final/lib/Bitcode/Reader/CMakeLists.txt create mode 100644 final/lib/Bitcode/Reader/Makefile create mode 100644 final/lib/Bitcode/Writer/BitWriter.cpp create mode 100644 final/lib/Bitcode/Writer/BitcodeWriter.cpp create mode 100644 final/lib/Bitcode/Writer/BitcodeWriterPass.cpp create mode 100644 final/lib/Bitcode/Writer/CMakeLists.txt create mode 100644 final/lib/Bitcode/Writer/Makefile create mode 100644 final/lib/Bitcode/Writer/ValueEnumerator.cpp create mode 100644 final/lib/Bitcode/Writer/ValueEnumerator.h create mode 100644 final/lib/CMakeLists.txt create mode 100644 final/lib/CodeGen/AggressiveAntiDepBreaker.cpp create mode 100644 final/lib/CodeGen/AggressiveAntiDepBreaker.h create mode 100644 final/lib/CodeGen/AllocationOrder.cpp create mode 100644 final/lib/CodeGen/AllocationOrder.h create mode 100644 final/lib/CodeGen/Analysis.cpp create mode 100644 final/lib/CodeGen/AntiDepBreaker.h create mode 100644 final/lib/CodeGen/AsmPrinter/ARMException.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/AsmPrinter.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/CMakeLists.txt create mode 100644 final/lib/CodeGen/AsmPrinter/DIE.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/DIE.h create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfDebug.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfDebug.h create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfException.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfException.h create mode 100644 final/lib/CodeGen/AsmPrinter/DwarfTableException.cpp create mode 100644 final/lib/CodeGen/AsmPrinter/Makefile create mode 100644 final/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp create mode 100644 final/lib/CodeGen/BranchFolding.cpp create mode 100644 final/lib/CodeGen/BranchFolding.h create mode 100644 final/lib/CodeGen/CMakeLists.txt create mode 100644 final/lib/CodeGen/CalcSpillWeights.cpp create mode 100644 final/lib/CodeGen/CallingConvLower.cpp create mode 100644 final/lib/CodeGen/CodeGen.cpp create mode 100644 final/lib/CodeGen/CodePlacementOpt.cpp create mode 100644 final/lib/CodeGen/CriticalAntiDepBreaker.cpp create mode 100644 final/lib/CodeGen/CriticalAntiDepBreaker.h create mode 100644 final/lib/CodeGen/DeadMachineInstructionElim.cpp create mode 100644 final/lib/CodeGen/DwarfEHPrepare.cpp create mode 100644 final/lib/CodeGen/ELF.h create mode 100644 final/lib/CodeGen/ELFCodeEmitter.cpp create mode 100644 final/lib/CodeGen/ELFCodeEmitter.h create mode 100644 final/lib/CodeGen/ELFWriter.cpp create mode 100644 final/lib/CodeGen/ELFWriter.h create mode 100644 final/lib/CodeGen/EdgeBundles.cpp create mode 100644 final/lib/CodeGen/ExpandISelPseudos.cpp create mode 100644 final/lib/CodeGen/GCMetadata.cpp create mode 100644 final/lib/CodeGen/GCMetadataPrinter.cpp create mode 100644 final/lib/CodeGen/GCStrategy.cpp create mode 100644 final/lib/CodeGen/IfConversion.cpp create mode 100644 final/lib/CodeGen/InlineSpiller.cpp create mode 100644 final/lib/CodeGen/IntrinsicLowering.cpp create mode 100644 final/lib/CodeGen/LLVMTargetMachine.cpp create mode 100644 final/lib/CodeGen/LatencyPriorityQueue.cpp create mode 100644 final/lib/CodeGen/LiveDebugVariables.cpp create mode 100644 final/lib/CodeGen/LiveDebugVariables.h create mode 100644 final/lib/CodeGen/LiveInterval.cpp create mode 100644 final/lib/CodeGen/LiveIntervalAnalysis.cpp create mode 100644 final/lib/CodeGen/LiveIntervalUnion.cpp create mode 100644 final/lib/CodeGen/LiveIntervalUnion.h create mode 100644 final/lib/CodeGen/LiveRangeEdit.cpp create mode 100644 final/lib/CodeGen/LiveRangeEdit.h create mode 100644 final/lib/CodeGen/LiveStackAnalysis.cpp create mode 100644 final/lib/CodeGen/LiveVariables.cpp create mode 100644 final/lib/CodeGen/LocalStackSlotAllocation.cpp create mode 100644 final/lib/CodeGen/LowerSubregs.cpp create mode 100644 final/lib/CodeGen/MachineBasicBlock.cpp create mode 100644 final/lib/CodeGen/MachineCSE.cpp create mode 100644 final/lib/CodeGen/MachineDominators.cpp create mode 100644 final/lib/CodeGen/MachineFunction.cpp create mode 100644 final/lib/CodeGen/MachineFunctionAnalysis.cpp create mode 100644 final/lib/CodeGen/MachineFunctionPass.cpp create mode 100644 final/lib/CodeGen/MachineFunctionPrinterPass.cpp create mode 100644 final/lib/CodeGen/MachineInstr.cpp create mode 100644 final/lib/CodeGen/MachineLICM.cpp create mode 100644 final/lib/CodeGen/MachineLoopInfo.cpp create mode 100644 final/lib/CodeGen/MachineLoopRanges.cpp create mode 100644 final/lib/CodeGen/MachineModuleInfo.cpp create mode 100644 final/lib/CodeGen/MachineModuleInfoImpls.cpp create mode 100644 final/lib/CodeGen/MachinePassRegistry.cpp create mode 100644 final/lib/CodeGen/MachineRegisterInfo.cpp create mode 100644 final/lib/CodeGen/MachineSSAUpdater.cpp create mode 100644 final/lib/CodeGen/MachineSink.cpp create mode 100644 final/lib/CodeGen/MachineVerifier.cpp create mode 100644 final/lib/CodeGen/Makefile create mode 100644 final/lib/CodeGen/ObjectCodeEmitter.cpp create mode 100644 final/lib/CodeGen/OcamlGC.cpp create mode 100644 final/lib/CodeGen/OptimizePHIs.cpp create mode 100644 final/lib/CodeGen/PHIElimination.cpp create mode 100644 final/lib/CodeGen/PHIEliminationUtils.cpp create mode 100644 final/lib/CodeGen/PHIEliminationUtils.h create mode 100644 final/lib/CodeGen/Passes.cpp create mode 100644 final/lib/CodeGen/PeepholeOptimizer.cpp create mode 100644 final/lib/CodeGen/PostRASchedulerList.cpp create mode 100644 final/lib/CodeGen/PreAllocSplitting.cpp create mode 100644 final/lib/CodeGen/ProcessImplicitDefs.cpp create mode 100644 final/lib/CodeGen/PrologEpilogInserter.cpp create mode 100644 final/lib/CodeGen/PrologEpilogInserter.h create mode 100644 final/lib/CodeGen/PseudoSourceValue.cpp create mode 100644 final/lib/CodeGen/README.txt create mode 100644 final/lib/CodeGen/RegAllocBase.h create mode 100644 final/lib/CodeGen/RegAllocBasic.cpp create mode 100644 final/lib/CodeGen/RegAllocFast.cpp create mode 100644 final/lib/CodeGen/RegAllocGreedy.cpp create mode 100644 final/lib/CodeGen/RegAllocLinearScan.cpp create mode 100644 final/lib/CodeGen/RegAllocPBQP.cpp create mode 100644 final/lib/CodeGen/RegisterCoalescer.cpp create mode 100644 final/lib/CodeGen/RegisterScavenging.cpp create mode 100644 final/lib/CodeGen/RenderMachineFunction.cpp create mode 100644 final/lib/CodeGen/RenderMachineFunction.h create mode 100644 final/lib/CodeGen/ScheduleDAG.cpp create mode 100644 final/lib/CodeGen/ScheduleDAGEmit.cpp create mode 100644 final/lib/CodeGen/ScheduleDAGInstrs.cpp create mode 100644 final/lib/CodeGen/ScheduleDAGInstrs.h create mode 100644 final/lib/CodeGen/ScheduleDAGPrinter.cpp create mode 100644 final/lib/CodeGen/ScoreboardHazardRecognizer.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/CMakeLists.txt create mode 100644 final/lib/CodeGen/SelectionDAG/DAGCombiner.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/FastISel.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/InstrEmitter.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/InstrEmitter.h create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeTypes.h create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/Makefile create mode 100644 final/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h create mode 100644 final/lib/CodeGen/SelectionDAG/SDNodeOrdering.h create mode 100644 final/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h create mode 100644 final/lib/CodeGen/SelectionDAG/SelectionDAG.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h create mode 100644 final/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/TargetLowering.cpp create mode 100644 final/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp create mode 100644 final/lib/CodeGen/ShadowStackGC.cpp create mode 100644 final/lib/CodeGen/ShrinkWrapping.cpp create mode 100644 final/lib/CodeGen/SimpleRegisterCoalescing.cpp create mode 100644 final/lib/CodeGen/SimpleRegisterCoalescing.h create mode 100644 final/lib/CodeGen/SjLjEHPrepare.cpp create mode 100644 final/lib/CodeGen/SlotIndexes.cpp create mode 100644 final/lib/CodeGen/SpillPlacement.cpp create mode 100644 final/lib/CodeGen/SpillPlacement.h create mode 100644 final/lib/CodeGen/Spiller.cpp create mode 100644 final/lib/CodeGen/Spiller.h create mode 100644 final/lib/CodeGen/SplitKit.cpp create mode 100644 final/lib/CodeGen/SplitKit.h create mode 100644 final/lib/CodeGen/Splitter.cpp create mode 100644 final/lib/CodeGen/Splitter.h create mode 100644 final/lib/CodeGen/StackProtector.cpp create mode 100644 final/lib/CodeGen/StackSlotColoring.cpp create mode 100644 final/lib/CodeGen/StrongPHIElimination.cpp create mode 100644 final/lib/CodeGen/TailDuplication.cpp create mode 100644 final/lib/CodeGen/TargetInstrInfoImpl.cpp create mode 100644 final/lib/CodeGen/TargetLoweringObjectFileImpl.cpp create mode 100644 final/lib/CodeGen/TwoAddressInstructionPass.cpp create mode 100644 final/lib/CodeGen/UnreachableBlockElim.cpp create mode 100644 final/lib/CodeGen/VirtRegMap.cpp create mode 100644 final/lib/CodeGen/VirtRegMap.h create mode 100644 final/lib/CodeGen/VirtRegRewriter.cpp create mode 100644 final/lib/CodeGen/VirtRegRewriter.h create mode 100644 final/lib/CompilerDriver/Action.cpp create mode 100644 final/lib/CompilerDriver/BuiltinOptions.cpp create mode 100644 final/lib/CompilerDriver/CMakeLists.txt create mode 100644 final/lib/CompilerDriver/CompilationGraph.cpp create mode 100644 final/lib/CompilerDriver/Main.cpp create mode 100644 final/lib/CompilerDriver/Makefile create mode 100644 final/lib/CompilerDriver/Tool.cpp create mode 100644 final/lib/ExecutionEngine/CMakeLists.txt create mode 100644 final/lib/ExecutionEngine/ExecutionEngine.cpp create mode 100644 final/lib/ExecutionEngine/ExecutionEngineBindings.cpp create mode 100644 final/lib/ExecutionEngine/Interpreter/CMakeLists.txt create mode 100644 final/lib/ExecutionEngine/Interpreter/Execution.cpp create mode 100644 final/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp create mode 100644 final/lib/ExecutionEngine/Interpreter/Interpreter.cpp create mode 100644 final/lib/ExecutionEngine/Interpreter/Interpreter.h create mode 100644 final/lib/ExecutionEngine/Interpreter/Makefile create mode 100644 final/lib/ExecutionEngine/JIT/CMakeLists.txt create mode 100644 final/lib/ExecutionEngine/JIT/Intercept.cpp create mode 100644 final/lib/ExecutionEngine/JIT/JIT.cpp create mode 100644 final/lib/ExecutionEngine/JIT/JIT.h create mode 100644 final/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp create mode 100644 final/lib/ExecutionEngine/JIT/JITDebugRegisterer.h create mode 100644 final/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp create mode 100644 final/lib/ExecutionEngine/JIT/JITDwarfEmitter.h create mode 100644 final/lib/ExecutionEngine/JIT/JITEmitter.cpp create mode 100644 final/lib/ExecutionEngine/JIT/JITMemoryManager.cpp create mode 100644 final/lib/ExecutionEngine/JIT/Makefile create mode 100644 final/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp create mode 100644 final/lib/ExecutionEngine/JIT/TargetSelect.cpp create mode 100644 final/lib/ExecutionEngine/MCJIT/CMakeLists.txt create mode 100644 final/lib/ExecutionEngine/MCJIT/MCJIT.cpp create mode 100644 final/lib/ExecutionEngine/MCJIT/MCJIT.h create mode 100644 final/lib/ExecutionEngine/MCJIT/Makefile create mode 100644 final/lib/ExecutionEngine/MCJIT/TargetSelect.cpp create mode 100644 final/lib/ExecutionEngine/Makefile create mode 100644 final/lib/Linker/CMakeLists.txt create mode 100644 final/lib/Linker/LinkArchives.cpp create mode 100644 final/lib/Linker/LinkItems.cpp create mode 100644 final/lib/Linker/LinkModules.cpp create mode 100644 final/lib/Linker/Linker.cpp create mode 100644 final/lib/Linker/Makefile create mode 100644 final/lib/MC/CMakeLists.txt create mode 100644 final/lib/MC/ELFObjectWriter.cpp create mode 100644 final/lib/MC/ELFObjectWriter.h create mode 100644 final/lib/MC/MCAsmInfo.cpp create mode 100644 final/lib/MC/MCAsmInfoCOFF.cpp create mode 100644 final/lib/MC/MCAsmInfoDarwin.cpp create mode 100644 final/lib/MC/MCAsmStreamer.cpp create mode 100644 final/lib/MC/MCAssembler.cpp create mode 100644 final/lib/MC/MCCodeEmitter.cpp create mode 100644 final/lib/MC/MCContext.cpp create mode 100644 final/lib/MC/MCDisassembler.cpp create mode 100644 final/lib/MC/MCDisassembler/CMakeLists.txt create mode 100644 final/lib/MC/MCDisassembler/EDDisassembler.cpp create mode 100644 final/lib/MC/MCDisassembler/EDDisassembler.h create mode 100644 final/lib/MC/MCDisassembler/EDInfo.h create mode 100644 final/lib/MC/MCDisassembler/EDInst.cpp create mode 100644 final/lib/MC/MCDisassembler/EDInst.h create mode 100644 final/lib/MC/MCDisassembler/EDOperand.cpp create mode 100644 final/lib/MC/MCDisassembler/EDOperand.h create mode 100644 final/lib/MC/MCDisassembler/EDToken.cpp create mode 100644 final/lib/MC/MCDisassembler/EDToken.h create mode 100644 final/lib/MC/MCDisassembler/Makefile create mode 100644 final/lib/MC/MCDwarf.cpp create mode 100644 final/lib/MC/MCELF.cpp create mode 100644 final/lib/MC/MCELF.h create mode 100644 final/lib/MC/MCELFObjectTargetWriter.cpp create mode 100644 final/lib/MC/MCELFStreamer.cpp create mode 100644 final/lib/MC/MCELFStreamer.h create mode 100644 final/lib/MC/MCExpr.cpp create mode 100644 final/lib/MC/MCInst.cpp create mode 100644 final/lib/MC/MCInstPrinter.cpp create mode 100644 final/lib/MC/MCLabel.cpp create mode 100644 final/lib/MC/MCLoggingStreamer.cpp create mode 100644 final/lib/MC/MCMachOStreamer.cpp create mode 100644 final/lib/MC/MCMachObjectTargetWriter.cpp create mode 100644 final/lib/MC/MCNullStreamer.cpp create mode 100644 final/lib/MC/MCObjectStreamer.cpp create mode 100644 final/lib/MC/MCObjectWriter.cpp create mode 100644 final/lib/MC/MCParser/AsmLexer.cpp create mode 100644 final/lib/MC/MCParser/AsmParser.cpp create mode 100644 final/lib/MC/MCParser/CMakeLists.txt create mode 100644 final/lib/MC/MCParser/COFFAsmParser.cpp create mode 100644 final/lib/MC/MCParser/DarwinAsmParser.cpp create mode 100644 final/lib/MC/MCParser/ELFAsmParser.cpp create mode 100644 final/lib/MC/MCParser/MCAsmLexer.cpp create mode 100644 final/lib/MC/MCParser/MCAsmParser.cpp create mode 100644 final/lib/MC/MCParser/MCAsmParserExtension.cpp create mode 100644 final/lib/MC/MCParser/Makefile create mode 100644 final/lib/MC/MCParser/TargetAsmParser.cpp create mode 100644 final/lib/MC/MCPureStreamer.cpp create mode 100644 final/lib/MC/MCSection.cpp create mode 100644 final/lib/MC/MCSectionCOFF.cpp create mode 100644 final/lib/MC/MCSectionELF.cpp create mode 100644 final/lib/MC/MCSectionMachO.cpp create mode 100644 final/lib/MC/MCStreamer.cpp create mode 100644 final/lib/MC/MCSymbol.cpp create mode 100644 final/lib/MC/MCValue.cpp create mode 100644 final/lib/MC/MachObjectWriter.cpp create mode 100644 final/lib/MC/Makefile create mode 100644 final/lib/MC/TargetAsmBackend.cpp create mode 100644 final/lib/MC/WinCOFFObjectWriter.cpp create mode 100644 final/lib/MC/WinCOFFStreamer.cpp create mode 100644 final/lib/Makefile create mode 100644 final/lib/Object/CMakeLists.txt create mode 100644 final/lib/Object/COFFObjectFile.cpp create mode 100644 final/lib/Object/ELFObjectFile.cpp create mode 100644 final/lib/Object/MachOObject.cpp create mode 100644 final/lib/Object/Makefile create mode 100644 final/lib/Object/ObjectFile.cpp create mode 100644 final/lib/Support/APFloat.cpp create mode 100644 final/lib/Support/APInt.cpp create mode 100644 final/lib/Support/APSInt.cpp create mode 100644 final/lib/Support/Allocator.cpp create mode 100644 final/lib/Support/Atomic.cpp create mode 100644 final/lib/Support/CMakeLists.txt create mode 100644 final/lib/Support/COPYRIGHT.regex create mode 100644 final/lib/Support/CommandLine.cpp create mode 100644 final/lib/Support/ConstantRange.cpp create mode 100644 final/lib/Support/CrashRecoveryContext.cpp create mode 100644 final/lib/Support/DAGDeltaAlgorithm.cpp create mode 100644 final/lib/Support/Debug.cpp create mode 100644 final/lib/Support/DeltaAlgorithm.cpp create mode 100644 final/lib/Support/Disassembler.cpp create mode 100644 final/lib/Support/Dwarf.cpp create mode 100644 final/lib/Support/DynamicLibrary.cpp create mode 100644 final/lib/Support/Errno.cpp create mode 100644 final/lib/Support/ErrorHandling.cpp create mode 100644 final/lib/Support/FileUtilities.cpp create mode 100644 final/lib/Support/FoldingSet.cpp create mode 100644 final/lib/Support/FormattedStream.cpp create mode 100644 final/lib/Support/GraphWriter.cpp create mode 100644 final/lib/Support/Host.cpp create mode 100644 final/lib/Support/IncludeFile.cpp create mode 100644 final/lib/Support/IntEqClasses.cpp create mode 100644 final/lib/Support/IntervalMap.cpp create mode 100644 final/lib/Support/IsInf.cpp create mode 100644 final/lib/Support/IsNAN.cpp create mode 100644 final/lib/Support/Makefile create mode 100644 final/lib/Support/ManagedStatic.cpp create mode 100644 final/lib/Support/Memory.cpp create mode 100644 final/lib/Support/MemoryBuffer.cpp create mode 100644 final/lib/Support/MemoryObject.cpp create mode 100644 final/lib/Support/Mutex.cpp create mode 100644 final/lib/Support/Path.cpp create mode 100644 final/lib/Support/PathV2.cpp create mode 100644 final/lib/Support/PluginLoader.cpp create mode 100644 final/lib/Support/PrettyStackTrace.cpp create mode 100644 final/lib/Support/Process.cpp create mode 100644 final/lib/Support/Program.cpp create mode 100644 final/lib/Support/README.txt.system create mode 100644 final/lib/Support/RWMutex.cpp create mode 100644 final/lib/Support/Regex.cpp create mode 100644 final/lib/Support/SearchForAddressOfSpecialSymbol.cpp create mode 100644 final/lib/Support/Signals.cpp create mode 100644 final/lib/Support/SmallPtrSet.cpp create mode 100644 final/lib/Support/SmallVector.cpp create mode 100644 final/lib/Support/SourceMgr.cpp create mode 100644 final/lib/Support/Statistic.cpp create mode 100644 final/lib/Support/StringExtras.cpp create mode 100644 final/lib/Support/StringMap.cpp create mode 100644 final/lib/Support/StringPool.cpp create mode 100644 final/lib/Support/StringRef.cpp create mode 100644 final/lib/Support/SystemUtils.cpp create mode 100644 final/lib/Support/TargetRegistry.cpp create mode 100644 final/lib/Support/ThreadLocal.cpp create mode 100644 final/lib/Support/Threading.cpp create mode 100644 final/lib/Support/TimeValue.cpp create mode 100644 final/lib/Support/Timer.cpp create mode 100644 final/lib/Support/ToolOutputFile.cpp create mode 100644 final/lib/Support/Triple.cpp create mode 100644 final/lib/Support/Twine.cpp create mode 100644 final/lib/Support/Unix/Host.inc create mode 100644 final/lib/Support/Unix/Memory.inc create mode 100644 final/lib/Support/Unix/Mutex.inc create mode 100644 final/lib/Support/Unix/Path.inc create mode 100644 final/lib/Support/Unix/PathV2.inc create mode 100644 final/lib/Support/Unix/Process.inc create mode 100644 final/lib/Support/Unix/Program.inc create mode 100644 final/lib/Support/Unix/README.txt create mode 100644 final/lib/Support/Unix/RWMutex.inc create mode 100644 final/lib/Support/Unix/Signals.inc create mode 100644 final/lib/Support/Unix/ThreadLocal.inc create mode 100644 final/lib/Support/Unix/TimeValue.inc create mode 100644 final/lib/Support/Unix/Unix.h create mode 100644 final/lib/Support/Unix/system_error.inc create mode 100644 final/lib/Support/Valgrind.cpp create mode 100644 final/lib/Support/Windows/DynamicLibrary.inc create mode 100644 final/lib/Support/Windows/Host.inc create mode 100644 final/lib/Support/Windows/Memory.inc create mode 100644 final/lib/Support/Windows/Mutex.inc create mode 100644 final/lib/Support/Windows/Path.inc create mode 100644 final/lib/Support/Windows/PathV2.inc create mode 100644 final/lib/Support/Windows/Process.inc create mode 100644 final/lib/Support/Windows/Program.inc create mode 100644 final/lib/Support/Windows/RWMutex.inc create mode 100644 final/lib/Support/Windows/Signals.inc create mode 100644 final/lib/Support/Windows/ThreadLocal.inc create mode 100644 final/lib/Support/Windows/TimeValue.inc create mode 100644 final/lib/Support/Windows/Windows.h create mode 100644 final/lib/Support/Windows/explicit_symbols.inc create mode 100644 final/lib/Support/Windows/system_error.inc create mode 100644 final/lib/Support/circular_raw_ostream.cpp create mode 100644 final/lib/Support/raw_os_ostream.cpp create mode 100644 final/lib/Support/raw_ostream.cpp create mode 100644 final/lib/Support/regcclass.h create mode 100644 final/lib/Support/regcname.h create mode 100644 final/lib/Support/regcomp.c create mode 100644 final/lib/Support/regengine.inc create mode 100644 final/lib/Support/regerror.c create mode 100644 final/lib/Support/regex2.h create mode 100644 final/lib/Support/regex_impl.h create mode 100644 final/lib/Support/regexec.c create mode 100644 final/lib/Support/regfree.c create mode 100644 final/lib/Support/regstrlcpy.c create mode 100644 final/lib/Support/regutils.h create mode 100644 final/lib/Support/system_error.cpp create mode 100644 final/lib/Target/ARM/ARM.h create mode 100644 final/lib/Target/ARM/ARM.td create mode 100644 final/lib/Target/ARM/ARMAddressingModes.h create mode 100644 final/lib/Target/ARM/ARMAsmBackend.cpp create mode 100644 final/lib/Target/ARM/ARMAsmPrinter.cpp create mode 100644 final/lib/Target/ARM/ARMAsmPrinter.h create mode 100644 final/lib/Target/ARM/ARMBaseInfo.h create mode 100644 final/lib/Target/ARM/ARMBaseInstrInfo.cpp create mode 100644 final/lib/Target/ARM/ARMBaseInstrInfo.h create mode 100644 final/lib/Target/ARM/ARMBaseRegisterInfo.cpp create mode 100644 final/lib/Target/ARM/ARMBaseRegisterInfo.h create mode 100644 final/lib/Target/ARM/ARMBuildAttrs.h create mode 100644 final/lib/Target/ARM/ARMCallingConv.h create mode 100644 final/lib/Target/ARM/ARMCallingConv.td create mode 100644 final/lib/Target/ARM/ARMCodeEmitter.cpp create mode 100644 final/lib/Target/ARM/ARMConstantIslandPass.cpp create mode 100644 final/lib/Target/ARM/ARMConstantPoolValue.cpp create mode 100644 final/lib/Target/ARM/ARMConstantPoolValue.h create mode 100644 final/lib/Target/ARM/ARMELFWriterInfo.cpp create mode 100644 final/lib/Target/ARM/ARMELFWriterInfo.h create mode 100644 final/lib/Target/ARM/ARMExpandPseudoInsts.cpp create mode 100644 final/lib/Target/ARM/ARMFastISel.cpp create mode 100644 final/lib/Target/ARM/ARMFixupKinds.h create mode 100644 final/lib/Target/ARM/ARMFrameLowering.cpp create mode 100644 final/lib/Target/ARM/ARMFrameLowering.h create mode 100644 final/lib/Target/ARM/ARMGlobalMerge.cpp create mode 100644 final/lib/Target/ARM/ARMHazardRecognizer.cpp create mode 100644 final/lib/Target/ARM/ARMHazardRecognizer.h create mode 100644 final/lib/Target/ARM/ARMISelDAGToDAG.cpp create mode 100644 final/lib/Target/ARM/ARMISelLowering.cpp create mode 100644 final/lib/Target/ARM/ARMISelLowering.h create mode 100644 final/lib/Target/ARM/ARMInstrFormats.td create mode 100644 final/lib/Target/ARM/ARMInstrInfo.cpp create mode 100644 final/lib/Target/ARM/ARMInstrInfo.h create mode 100644 final/lib/Target/ARM/ARMInstrInfo.td create mode 100644 final/lib/Target/ARM/ARMInstrNEON.td create mode 100644 final/lib/Target/ARM/ARMInstrThumb.td create mode 100644 final/lib/Target/ARM/ARMInstrThumb2.td create mode 100644 final/lib/Target/ARM/ARMInstrVFP.td create mode 100644 final/lib/Target/ARM/ARMJITInfo.cpp create mode 100644 final/lib/Target/ARM/ARMJITInfo.h create mode 100644 final/lib/Target/ARM/ARMLoadStoreOptimizer.cpp create mode 100644 final/lib/Target/ARM/ARMMCAsmInfo.cpp create mode 100644 final/lib/Target/ARM/ARMMCAsmInfo.h create mode 100644 final/lib/Target/ARM/ARMMCCodeEmitter.cpp create mode 100644 final/lib/Target/ARM/ARMMCExpr.cpp create mode 100644 final/lib/Target/ARM/ARMMCExpr.h create mode 100644 final/lib/Target/ARM/ARMMCInstLower.cpp create mode 100644 final/lib/Target/ARM/ARMMachineFunctionInfo.h create mode 100644 final/lib/Target/ARM/ARMPerfectShuffle.h create mode 100644 final/lib/Target/ARM/ARMRegisterInfo.cpp create mode 100644 final/lib/Target/ARM/ARMRegisterInfo.h create mode 100644 final/lib/Target/ARM/ARMRegisterInfo.td create mode 100644 final/lib/Target/ARM/ARMRelocations.h create mode 100644 final/lib/Target/ARM/ARMSchedule.td create mode 100644 final/lib/Target/ARM/ARMScheduleA8.td create mode 100644 final/lib/Target/ARM/ARMScheduleA9.td create mode 100644 final/lib/Target/ARM/ARMScheduleV6.td create mode 100644 final/lib/Target/ARM/ARMSelectionDAGInfo.cpp create mode 100644 final/lib/Target/ARM/ARMSelectionDAGInfo.h create mode 100644 final/lib/Target/ARM/ARMSubtarget.cpp create mode 100644 final/lib/Target/ARM/ARMSubtarget.h create mode 100644 final/lib/Target/ARM/ARMTargetMachine.cpp create mode 100644 final/lib/Target/ARM/ARMTargetMachine.h create mode 100644 final/lib/Target/ARM/ARMTargetObjectFile.cpp create mode 100644 final/lib/Target/ARM/ARMTargetObjectFile.h create mode 100644 final/lib/Target/ARM/AsmParser/ARMAsmLexer.cpp create mode 100644 final/lib/Target/ARM/AsmParser/ARMAsmParser.cpp create mode 100644 final/lib/Target/ARM/AsmParser/CMakeLists.txt create mode 100644 final/lib/Target/ARM/AsmParser/Makefile create mode 100644 final/lib/Target/ARM/CMakeLists.txt create mode 100644 final/lib/Target/ARM/Disassembler/ARMDisassembler.cpp create mode 100644 final/lib/Target/ARM/Disassembler/ARMDisassembler.h create mode 100644 final/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp create mode 100644 final/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h create mode 100644 final/lib/Target/ARM/Disassembler/CMakeLists.txt create mode 100644 final/lib/Target/ARM/Disassembler/Makefile create mode 100644 final/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h create mode 100644 final/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp create mode 100644 final/lib/Target/ARM/InstPrinter/ARMInstPrinter.h create mode 100644 final/lib/Target/ARM/InstPrinter/CMakeLists.txt create mode 100644 final/lib/Target/ARM/InstPrinter/Makefile create mode 100644 final/lib/Target/ARM/MLxExpansionPass.cpp create mode 100644 final/lib/Target/ARM/Makefile create mode 100644 final/lib/Target/ARM/NEONMoveFix.cpp create mode 100644 final/lib/Target/ARM/README-Thumb.txt create mode 100644 final/lib/Target/ARM/README-Thumb2.txt create mode 100644 final/lib/Target/ARM/README.txt create mode 100644 final/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp create mode 100644 final/lib/Target/ARM/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/ARM/TargetInfo/Makefile create mode 100644 final/lib/Target/ARM/Thumb1FrameLowering.cpp create mode 100644 final/lib/Target/ARM/Thumb1FrameLowering.h create mode 100644 final/lib/Target/ARM/Thumb1InstrInfo.cpp create mode 100644 final/lib/Target/ARM/Thumb1InstrInfo.h create mode 100644 final/lib/Target/ARM/Thumb1RegisterInfo.cpp create mode 100644 final/lib/Target/ARM/Thumb1RegisterInfo.h create mode 100644 final/lib/Target/ARM/Thumb2ITBlockPass.cpp create mode 100644 final/lib/Target/ARM/Thumb2InstrInfo.cpp create mode 100644 final/lib/Target/ARM/Thumb2InstrInfo.h create mode 100644 final/lib/Target/ARM/Thumb2RegisterInfo.cpp create mode 100644 final/lib/Target/ARM/Thumb2RegisterInfo.h create mode 100644 final/lib/Target/ARM/Thumb2SizeReduction.cpp create mode 100644 final/lib/Target/Alpha/Alpha.h create mode 100644 final/lib/Target/Alpha/Alpha.td create mode 100644 final/lib/Target/Alpha/AlphaAsmPrinter.cpp create mode 100644 final/lib/Target/Alpha/AlphaBranchSelector.cpp create mode 100644 final/lib/Target/Alpha/AlphaCallingConv.td create mode 100644 final/lib/Target/Alpha/AlphaFrameLowering.cpp create mode 100644 final/lib/Target/Alpha/AlphaFrameLowering.h create mode 100644 final/lib/Target/Alpha/AlphaISelDAGToDAG.cpp create mode 100644 final/lib/Target/Alpha/AlphaISelLowering.cpp create mode 100644 final/lib/Target/Alpha/AlphaISelLowering.h create mode 100644 final/lib/Target/Alpha/AlphaInstrFormats.td create mode 100644 final/lib/Target/Alpha/AlphaInstrInfo.cpp create mode 100644 final/lib/Target/Alpha/AlphaInstrInfo.h create mode 100644 final/lib/Target/Alpha/AlphaInstrInfo.td create mode 100644 final/lib/Target/Alpha/AlphaLLRP.cpp create mode 100644 final/lib/Target/Alpha/AlphaMCAsmInfo.cpp create mode 100644 final/lib/Target/Alpha/AlphaMCAsmInfo.h create mode 100644 final/lib/Target/Alpha/AlphaMachineFunctionInfo.h create mode 100644 final/lib/Target/Alpha/AlphaRegisterInfo.cpp create mode 100644 final/lib/Target/Alpha/AlphaRegisterInfo.h create mode 100644 final/lib/Target/Alpha/AlphaRegisterInfo.td create mode 100644 final/lib/Target/Alpha/AlphaRelocations.h create mode 100644 final/lib/Target/Alpha/AlphaSchedule.td create mode 100644 final/lib/Target/Alpha/AlphaSelectionDAGInfo.cpp create mode 100644 final/lib/Target/Alpha/AlphaSelectionDAGInfo.h create mode 100644 final/lib/Target/Alpha/AlphaSubtarget.cpp create mode 100644 final/lib/Target/Alpha/AlphaSubtarget.h create mode 100644 final/lib/Target/Alpha/AlphaTargetMachine.cpp create mode 100644 final/lib/Target/Alpha/AlphaTargetMachine.h create mode 100644 final/lib/Target/Alpha/CMakeLists.txt create mode 100644 final/lib/Target/Alpha/Makefile create mode 100644 final/lib/Target/Alpha/README.txt create mode 100644 final/lib/Target/Alpha/TargetInfo/AlphaTargetInfo.cpp create mode 100644 final/lib/Target/Alpha/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/Alpha/TargetInfo/Makefile create mode 100644 final/lib/Target/Blackfin/Blackfin.h create mode 100644 final/lib/Target/Blackfin/Blackfin.td create mode 100644 final/lib/Target/Blackfin/BlackfinAsmPrinter.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinCallingConv.td create mode 100644 final/lib/Target/Blackfin/BlackfinFrameLowering.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinFrameLowering.h create mode 100644 final/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinISelLowering.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinISelLowering.h create mode 100644 final/lib/Target/Blackfin/BlackfinInstrFormats.td create mode 100644 final/lib/Target/Blackfin/BlackfinInstrInfo.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinInstrInfo.h create mode 100644 final/lib/Target/Blackfin/BlackfinInstrInfo.td create mode 100644 final/lib/Target/Blackfin/BlackfinIntrinsicInfo.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinIntrinsicInfo.h create mode 100644 final/lib/Target/Blackfin/BlackfinIntrinsics.td create mode 100644 final/lib/Target/Blackfin/BlackfinMCAsmInfo.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinMCAsmInfo.h create mode 100644 final/lib/Target/Blackfin/BlackfinRegisterInfo.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinRegisterInfo.h create mode 100644 final/lib/Target/Blackfin/BlackfinRegisterInfo.td create mode 100644 final/lib/Target/Blackfin/BlackfinSelectionDAGInfo.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinSelectionDAGInfo.h create mode 100644 final/lib/Target/Blackfin/BlackfinSubtarget.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinSubtarget.h create mode 100644 final/lib/Target/Blackfin/BlackfinTargetMachine.cpp create mode 100644 final/lib/Target/Blackfin/BlackfinTargetMachine.h create mode 100644 final/lib/Target/Blackfin/CMakeLists.txt create mode 100644 final/lib/Target/Blackfin/Makefile create mode 100644 final/lib/Target/Blackfin/README.txt create mode 100644 final/lib/Target/Blackfin/TargetInfo/BlackfinTargetInfo.cpp create mode 100644 final/lib/Target/Blackfin/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/Blackfin/TargetInfo/Makefile create mode 100644 final/lib/Target/CBackend/CBackend.cpp create mode 100644 final/lib/Target/CBackend/CMakeLists.txt create mode 100644 final/lib/Target/CBackend/CTargetMachine.h create mode 100644 final/lib/Target/CBackend/Makefile create mode 100644 final/lib/Target/CBackend/TargetInfo/CBackendTargetInfo.cpp create mode 100644 final/lib/Target/CBackend/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/CBackend/TargetInfo/Makefile create mode 100644 final/lib/Target/CMakeLists.txt create mode 100644 final/lib/Target/CellSPU/CMakeLists.txt create mode 100644 final/lib/Target/CellSPU/CellSDKIntrinsics.td create mode 100644 final/lib/Target/CellSPU/Makefile create mode 100644 final/lib/Target/CellSPU/README.txt create mode 100644 final/lib/Target/CellSPU/SPU.h create mode 100644 final/lib/Target/CellSPU/SPU.td create mode 100644 final/lib/Target/CellSPU/SPU128InstrInfo.td create mode 100644 final/lib/Target/CellSPU/SPU64InstrInfo.td create mode 100644 final/lib/Target/CellSPU/SPUAsmPrinter.cpp create mode 100644 final/lib/Target/CellSPU/SPUCallingConv.td create mode 100644 final/lib/Target/CellSPU/SPUFrameLowering.cpp create mode 100644 final/lib/Target/CellSPU/SPUFrameLowering.h create mode 100644 final/lib/Target/CellSPU/SPUHazardRecognizers.cpp create mode 100644 final/lib/Target/CellSPU/SPUHazardRecognizers.h create mode 100644 final/lib/Target/CellSPU/SPUISelDAGToDAG.cpp create mode 100644 final/lib/Target/CellSPU/SPUISelLowering.cpp create mode 100644 final/lib/Target/CellSPU/SPUISelLowering.h create mode 100644 final/lib/Target/CellSPU/SPUInstrBuilder.h create mode 100644 final/lib/Target/CellSPU/SPUInstrFormats.td create mode 100644 final/lib/Target/CellSPU/SPUInstrInfo.cpp create mode 100644 final/lib/Target/CellSPU/SPUInstrInfo.h create mode 100644 final/lib/Target/CellSPU/SPUInstrInfo.td create mode 100644 final/lib/Target/CellSPU/SPUMCAsmInfo.cpp create mode 100644 final/lib/Target/CellSPU/SPUMCAsmInfo.h create mode 100644 final/lib/Target/CellSPU/SPUMachineFunction.h create mode 100644 final/lib/Target/CellSPU/SPUMathInstr.td create mode 100644 final/lib/Target/CellSPU/SPUNodes.td create mode 100644 final/lib/Target/CellSPU/SPUNopFiller.cpp create mode 100644 final/lib/Target/CellSPU/SPUOperands.td create mode 100644 final/lib/Target/CellSPU/SPURegisterInfo.cpp create mode 100644 final/lib/Target/CellSPU/SPURegisterInfo.h create mode 100644 final/lib/Target/CellSPU/SPURegisterInfo.td create mode 100644 final/lib/Target/CellSPU/SPURegisterNames.h create mode 100644 final/lib/Target/CellSPU/SPUSchedule.td create mode 100644 final/lib/Target/CellSPU/SPUSelectionDAGInfo.cpp create mode 100644 final/lib/Target/CellSPU/SPUSelectionDAGInfo.h create mode 100644 final/lib/Target/CellSPU/SPUSubtarget.cpp create mode 100644 final/lib/Target/CellSPU/SPUSubtarget.h create mode 100644 final/lib/Target/CellSPU/SPUTargetMachine.cpp create mode 100644 final/lib/Target/CellSPU/SPUTargetMachine.h create mode 100644 final/lib/Target/CellSPU/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/CellSPU/TargetInfo/CellSPUTargetInfo.cpp create mode 100644 final/lib/Target/CellSPU/TargetInfo/Makefile create mode 100644 final/lib/Target/CppBackend/CMakeLists.txt create mode 100644 final/lib/Target/CppBackend/CPPBackend.cpp create mode 100644 final/lib/Target/CppBackend/CPPTargetMachine.h create mode 100644 final/lib/Target/CppBackend/Makefile create mode 100644 final/lib/Target/CppBackend/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/CppBackend/TargetInfo/CppBackendTargetInfo.cpp create mode 100644 final/lib/Target/CppBackend/TargetInfo/Makefile create mode 100644 final/lib/Target/MBlaze/AsmParser/CMakeLists.txt create mode 100644 final/lib/Target/MBlaze/AsmParser/MBlazeAsmLexer.cpp create mode 100644 final/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp create mode 100644 final/lib/Target/MBlaze/AsmParser/Makefile create mode 100644 final/lib/Target/MBlaze/CMakeLists.txt create mode 100644 final/lib/Target/MBlaze/Disassembler/CMakeLists.txt create mode 100644 final/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp create mode 100644 final/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.h create mode 100644 final/lib/Target/MBlaze/Disassembler/Makefile create mode 100644 final/lib/Target/MBlaze/InstPrinter/CMakeLists.txt create mode 100644 final/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp create mode 100644 final/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.h create mode 100644 final/lib/Target/MBlaze/InstPrinter/Makefile create mode 100644 final/lib/Target/MBlaze/MBlaze.h create mode 100644 final/lib/Target/MBlaze/MBlaze.td create mode 100644 final/lib/Target/MBlaze/MBlazeAsmBackend.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeAsmPrinter.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeCallingConv.td create mode 100644 final/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeELFWriterInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeFrameLowering.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeFrameLowering.h create mode 100644 final/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeISelLowering.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeISelLowering.h create mode 100644 final/lib/Target/MBlaze/MBlazeInstrFPU.td create mode 100644 final/lib/Target/MBlaze/MBlazeInstrFSL.td create mode 100644 final/lib/Target/MBlaze/MBlazeInstrFormats.td create mode 100644 final/lib/Target/MBlaze/MBlazeInstrInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeInstrInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeInstrInfo.td create mode 100644 final/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeIntrinsicInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeIntrinsics.td create mode 100644 final/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeMCAsmInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeMCInstLower.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeMCInstLower.h create mode 100644 final/lib/Target/MBlaze/MBlazeMachineFunction.h create mode 100644 final/lib/Target/MBlaze/MBlazeRegisterInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeRegisterInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeRegisterInfo.td create mode 100644 final/lib/Target/MBlaze/MBlazeRelocations.h create mode 100644 final/lib/Target/MBlaze/MBlazeSchedule.td create mode 100644 final/lib/Target/MBlaze/MBlazeSelectionDAGInfo.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeSelectionDAGInfo.h create mode 100644 final/lib/Target/MBlaze/MBlazeSubtarget.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeSubtarget.h create mode 100644 final/lib/Target/MBlaze/MBlazeTargetMachine.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeTargetMachine.h create mode 100644 final/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp create mode 100644 final/lib/Target/MBlaze/MBlazeTargetObjectFile.h create mode 100644 final/lib/Target/MBlaze/Makefile create mode 100644 final/lib/Target/MBlaze/TODO create mode 100644 final/lib/Target/MBlaze/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp create mode 100644 final/lib/Target/MBlaze/TargetInfo/Makefile create mode 100644 final/lib/Target/MSP430/CMakeLists.txt create mode 100644 final/lib/Target/MSP430/InstPrinter/CMakeLists.txt create mode 100644 final/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.cpp create mode 100644 final/lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h create mode 100644 final/lib/Target/MSP430/InstPrinter/Makefile create mode 100644 final/lib/Target/MSP430/MSP430.h create mode 100644 final/lib/Target/MSP430/MSP430.td create mode 100644 final/lib/Target/MSP430/MSP430AsmPrinter.cpp create mode 100644 final/lib/Target/MSP430/MSP430BranchSelector.cpp create mode 100644 final/lib/Target/MSP430/MSP430CallingConv.td create mode 100644 final/lib/Target/MSP430/MSP430FrameLowering.cpp create mode 100644 final/lib/Target/MSP430/MSP430FrameLowering.h create mode 100644 final/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp create mode 100644 final/lib/Target/MSP430/MSP430ISelLowering.cpp create mode 100644 final/lib/Target/MSP430/MSP430ISelLowering.h create mode 100644 final/lib/Target/MSP430/MSP430InstrFormats.td create mode 100644 final/lib/Target/MSP430/MSP430InstrInfo.cpp create mode 100644 final/lib/Target/MSP430/MSP430InstrInfo.h create mode 100644 final/lib/Target/MSP430/MSP430InstrInfo.td create mode 100644 final/lib/Target/MSP430/MSP430MCAsmInfo.cpp create mode 100644 final/lib/Target/MSP430/MSP430MCAsmInfo.h create mode 100644 final/lib/Target/MSP430/MSP430MCInstLower.cpp create mode 100644 final/lib/Target/MSP430/MSP430MCInstLower.h create mode 100644 final/lib/Target/MSP430/MSP430MachineFunctionInfo.h create mode 100644 final/lib/Target/MSP430/MSP430RegisterInfo.cpp create mode 100644 final/lib/Target/MSP430/MSP430RegisterInfo.h create mode 100644 final/lib/Target/MSP430/MSP430RegisterInfo.td create mode 100644 final/lib/Target/MSP430/MSP430SelectionDAGInfo.cpp create mode 100644 final/lib/Target/MSP430/MSP430SelectionDAGInfo.h create mode 100644 final/lib/Target/MSP430/MSP430Subtarget.cpp create mode 100644 final/lib/Target/MSP430/MSP430Subtarget.h create mode 100644 final/lib/Target/MSP430/MSP430TargetMachine.cpp create mode 100644 final/lib/Target/MSP430/MSP430TargetMachine.h create mode 100644 final/lib/Target/MSP430/Makefile create mode 100644 final/lib/Target/MSP430/README.txt create mode 100644 final/lib/Target/MSP430/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/MSP430/TargetInfo/MSP430TargetInfo.cpp create mode 100644 final/lib/Target/MSP430/TargetInfo/Makefile create mode 100644 final/lib/Target/Makefile create mode 100644 final/lib/Target/Mangler.cpp create mode 100644 final/lib/Target/Mips/CMakeLists.txt create mode 100644 final/lib/Target/Mips/Makefile create mode 100644 final/lib/Target/Mips/Mips.h create mode 100644 final/lib/Target/Mips/Mips.td create mode 100644 final/lib/Target/Mips/MipsAsmPrinter.cpp create mode 100644 final/lib/Target/Mips/MipsCallingConv.td create mode 100644 final/lib/Target/Mips/MipsDelaySlotFiller.cpp create mode 100644 final/lib/Target/Mips/MipsFrameLowering.cpp create mode 100644 final/lib/Target/Mips/MipsFrameLowering.h create mode 100644 final/lib/Target/Mips/MipsISelDAGToDAG.cpp create mode 100644 final/lib/Target/Mips/MipsISelLowering.cpp create mode 100644 final/lib/Target/Mips/MipsISelLowering.h create mode 100644 final/lib/Target/Mips/MipsInstrFPU.td create mode 100644 final/lib/Target/Mips/MipsInstrFormats.td create mode 100644 final/lib/Target/Mips/MipsInstrInfo.cpp create mode 100644 final/lib/Target/Mips/MipsInstrInfo.h create mode 100644 final/lib/Target/Mips/MipsInstrInfo.td create mode 100644 final/lib/Target/Mips/MipsMCAsmInfo.cpp create mode 100644 final/lib/Target/Mips/MipsMCAsmInfo.h create mode 100644 final/lib/Target/Mips/MipsMachineFunction.h create mode 100644 final/lib/Target/Mips/MipsRegisterInfo.cpp create mode 100644 final/lib/Target/Mips/MipsRegisterInfo.h create mode 100644 final/lib/Target/Mips/MipsRegisterInfo.td create mode 100644 final/lib/Target/Mips/MipsSchedule.td create mode 100644 final/lib/Target/Mips/MipsSelectionDAGInfo.cpp create mode 100644 final/lib/Target/Mips/MipsSelectionDAGInfo.h create mode 100644 final/lib/Target/Mips/MipsSubtarget.cpp create mode 100644 final/lib/Target/Mips/MipsSubtarget.h create mode 100644 final/lib/Target/Mips/MipsTargetMachine.cpp create mode 100644 final/lib/Target/Mips/MipsTargetMachine.h create mode 100644 final/lib/Target/Mips/MipsTargetObjectFile.cpp create mode 100644 final/lib/Target/Mips/MipsTargetObjectFile.h create mode 100644 final/lib/Target/Mips/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/Mips/TargetInfo/Makefile create mode 100644 final/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp create mode 100644 final/lib/Target/PTX/CMakeLists.txt create mode 100644 final/lib/Target/PTX/Makefile create mode 100644 final/lib/Target/PTX/PTX.h create mode 100644 final/lib/Target/PTX/PTX.td create mode 100644 final/lib/Target/PTX/PTXAsmPrinter.cpp create mode 100644 final/lib/Target/PTX/PTXFrameLowering.cpp create mode 100644 final/lib/Target/PTX/PTXFrameLowering.h create mode 100644 final/lib/Target/PTX/PTXISelDAGToDAG.cpp create mode 100644 final/lib/Target/PTX/PTXISelLowering.cpp create mode 100644 final/lib/Target/PTX/PTXISelLowering.h create mode 100644 final/lib/Target/PTX/PTXInstrFormats.td create mode 100644 final/lib/Target/PTX/PTXInstrInfo.cpp create mode 100644 final/lib/Target/PTX/PTXInstrInfo.h create mode 100644 final/lib/Target/PTX/PTXInstrInfo.td create mode 100644 final/lib/Target/PTX/PTXIntrinsicInstrInfo.td create mode 100644 final/lib/Target/PTX/PTXMCAsmInfo.cpp create mode 100644 final/lib/Target/PTX/PTXMCAsmInfo.h create mode 100644 final/lib/Target/PTX/PTXMCAsmStreamer.cpp create mode 100644 final/lib/Target/PTX/PTXMFInfoExtract.cpp create mode 100644 final/lib/Target/PTX/PTXMachineFunctionInfo.h create mode 100644 final/lib/Target/PTX/PTXRegisterInfo.cpp create mode 100644 final/lib/Target/PTX/PTXRegisterInfo.h create mode 100644 final/lib/Target/PTX/PTXRegisterInfo.td create mode 100644 final/lib/Target/PTX/PTXSubtarget.cpp create mode 100644 final/lib/Target/PTX/PTXSubtarget.h create mode 100644 final/lib/Target/PTX/PTXTargetMachine.cpp create mode 100644 final/lib/Target/PTX/PTXTargetMachine.h create mode 100644 final/lib/Target/PTX/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/PTX/TargetInfo/Makefile create mode 100644 final/lib/Target/PTX/TargetInfo/PTXTargetInfo.cpp create mode 100644 final/lib/Target/PowerPC/CMakeLists.txt create mode 100644 final/lib/Target/PowerPC/InstPrinter/CMakeLists.txt create mode 100644 final/lib/Target/PowerPC/InstPrinter/Makefile create mode 100644 final/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp create mode 100644 final/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h create mode 100644 final/lib/Target/PowerPC/Makefile create mode 100644 final/lib/Target/PowerPC/PPC.h create mode 100644 final/lib/Target/PowerPC/PPC.td create mode 100644 final/lib/Target/PowerPC/PPCAsmBackend.cpp create mode 100644 final/lib/Target/PowerPC/PPCAsmPrinter.cpp create mode 100644 final/lib/Target/PowerPC/PPCBranchSelector.cpp create mode 100644 final/lib/Target/PowerPC/PPCCallingConv.td create mode 100644 final/lib/Target/PowerPC/PPCCodeEmitter.cpp create mode 100644 final/lib/Target/PowerPC/PPCFixupKinds.h create mode 100644 final/lib/Target/PowerPC/PPCFrameLowering.cpp create mode 100644 final/lib/Target/PowerPC/PPCFrameLowering.h create mode 100644 final/lib/Target/PowerPC/PPCHazardRecognizers.cpp create mode 100644 final/lib/Target/PowerPC/PPCHazardRecognizers.h create mode 100644 final/lib/Target/PowerPC/PPCISelDAGToDAG.cpp create mode 100644 final/lib/Target/PowerPC/PPCISelLowering.cpp create mode 100644 final/lib/Target/PowerPC/PPCISelLowering.h create mode 100644 final/lib/Target/PowerPC/PPCInstr64Bit.td create mode 100644 final/lib/Target/PowerPC/PPCInstrAltivec.td create mode 100644 final/lib/Target/PowerPC/PPCInstrBuilder.h create mode 100644 final/lib/Target/PowerPC/PPCInstrFormats.td create mode 100644 final/lib/Target/PowerPC/PPCInstrInfo.cpp create mode 100644 final/lib/Target/PowerPC/PPCInstrInfo.h create mode 100644 final/lib/Target/PowerPC/PPCInstrInfo.td create mode 100644 final/lib/Target/PowerPC/PPCJITInfo.cpp create mode 100644 final/lib/Target/PowerPC/PPCJITInfo.h create mode 100644 final/lib/Target/PowerPC/PPCMCAsmInfo.cpp create mode 100644 final/lib/Target/PowerPC/PPCMCAsmInfo.h create mode 100644 final/lib/Target/PowerPC/PPCMCCodeEmitter.cpp create mode 100644 final/lib/Target/PowerPC/PPCMCInstLower.cpp create mode 100644 final/lib/Target/PowerPC/PPCMachineFunctionInfo.h create mode 100644 final/lib/Target/PowerPC/PPCPerfectShuffle.h create mode 100644 final/lib/Target/PowerPC/PPCPredicates.cpp create mode 100644 final/lib/Target/PowerPC/PPCPredicates.h create mode 100644 final/lib/Target/PowerPC/PPCRegisterInfo.cpp create mode 100644 final/lib/Target/PowerPC/PPCRegisterInfo.h create mode 100644 final/lib/Target/PowerPC/PPCRegisterInfo.td create mode 100644 final/lib/Target/PowerPC/PPCRelocations.h create mode 100644 final/lib/Target/PowerPC/PPCSchedule.td create mode 100644 final/lib/Target/PowerPC/PPCScheduleG3.td create mode 100644 final/lib/Target/PowerPC/PPCScheduleG4.td create mode 100644 final/lib/Target/PowerPC/PPCScheduleG4Plus.td create mode 100644 final/lib/Target/PowerPC/PPCScheduleG5.td create mode 100644 final/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp create mode 100644 final/lib/Target/PowerPC/PPCSelectionDAGInfo.h create mode 100644 final/lib/Target/PowerPC/PPCSubtarget.cpp create mode 100644 final/lib/Target/PowerPC/PPCSubtarget.h create mode 100644 final/lib/Target/PowerPC/PPCTargetMachine.cpp create mode 100644 final/lib/Target/PowerPC/PPCTargetMachine.h create mode 100644 final/lib/Target/PowerPC/README.txt create mode 100644 final/lib/Target/PowerPC/README_ALTIVEC.txt create mode 100644 final/lib/Target/PowerPC/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/PowerPC/TargetInfo/Makefile create mode 100644 final/lib/Target/PowerPC/TargetInfo/PowerPCTargetInfo.cpp create mode 100644 final/lib/Target/README.txt create mode 100644 final/lib/Target/Sparc/CMakeLists.txt create mode 100644 final/lib/Target/Sparc/DelaySlotFiller.cpp create mode 100644 final/lib/Target/Sparc/FPMover.cpp create mode 100644 final/lib/Target/Sparc/Makefile create mode 100644 final/lib/Target/Sparc/README.txt create mode 100644 final/lib/Target/Sparc/Sparc.h create mode 100644 final/lib/Target/Sparc/Sparc.td create mode 100644 final/lib/Target/Sparc/SparcAsmPrinter.cpp create mode 100644 final/lib/Target/Sparc/SparcCallingConv.td create mode 100644 final/lib/Target/Sparc/SparcFrameLowering.cpp create mode 100644 final/lib/Target/Sparc/SparcFrameLowering.h create mode 100644 final/lib/Target/Sparc/SparcISelDAGToDAG.cpp create mode 100644 final/lib/Target/Sparc/SparcISelLowering.cpp create mode 100644 final/lib/Target/Sparc/SparcISelLowering.h create mode 100644 final/lib/Target/Sparc/SparcInstrFormats.td create mode 100644 final/lib/Target/Sparc/SparcInstrInfo.cpp create mode 100644 final/lib/Target/Sparc/SparcInstrInfo.h create mode 100644 final/lib/Target/Sparc/SparcInstrInfo.td create mode 100644 final/lib/Target/Sparc/SparcMCAsmInfo.cpp create mode 100644 final/lib/Target/Sparc/SparcMCAsmInfo.h create mode 100644 final/lib/Target/Sparc/SparcMachineFunctionInfo.h create mode 100644 final/lib/Target/Sparc/SparcRegisterInfo.cpp create mode 100644 final/lib/Target/Sparc/SparcRegisterInfo.h create mode 100644 final/lib/Target/Sparc/SparcRegisterInfo.td create mode 100644 final/lib/Target/Sparc/SparcSelectionDAGInfo.cpp create mode 100644 final/lib/Target/Sparc/SparcSelectionDAGInfo.h create mode 100644 final/lib/Target/Sparc/SparcSubtarget.cpp create mode 100644 final/lib/Target/Sparc/SparcSubtarget.h create mode 100644 final/lib/Target/Sparc/SparcTargetMachine.cpp create mode 100644 final/lib/Target/Sparc/SparcTargetMachine.h create mode 100644 final/lib/Target/Sparc/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/Sparc/TargetInfo/Makefile create mode 100644 final/lib/Target/Sparc/TargetInfo/SparcTargetInfo.cpp create mode 100644 final/lib/Target/SubtargetFeature.cpp create mode 100644 final/lib/Target/SystemZ/CMakeLists.txt create mode 100644 final/lib/Target/SystemZ/Makefile create mode 100644 final/lib/Target/SystemZ/SystemZ.h create mode 100644 final/lib/Target/SystemZ/SystemZ.td create mode 100644 final/lib/Target/SystemZ/SystemZAsmPrinter.cpp create mode 100644 final/lib/Target/SystemZ/SystemZCallingConv.td create mode 100644 final/lib/Target/SystemZ/SystemZFrameLowering.cpp create mode 100644 final/lib/Target/SystemZ/SystemZFrameLowering.h create mode 100644 final/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp create mode 100644 final/lib/Target/SystemZ/SystemZISelLowering.cpp create mode 100644 final/lib/Target/SystemZ/SystemZISelLowering.h create mode 100644 final/lib/Target/SystemZ/SystemZInstrBuilder.h create mode 100644 final/lib/Target/SystemZ/SystemZInstrFP.td create mode 100644 final/lib/Target/SystemZ/SystemZInstrFormats.td create mode 100644 final/lib/Target/SystemZ/SystemZInstrInfo.cpp create mode 100644 final/lib/Target/SystemZ/SystemZInstrInfo.h create mode 100644 final/lib/Target/SystemZ/SystemZInstrInfo.td create mode 100644 final/lib/Target/SystemZ/SystemZMCAsmInfo.cpp create mode 100644 final/lib/Target/SystemZ/SystemZMCAsmInfo.h create mode 100644 final/lib/Target/SystemZ/SystemZMachineFunctionInfo.h create mode 100644 final/lib/Target/SystemZ/SystemZOperands.td create mode 100644 final/lib/Target/SystemZ/SystemZRegisterInfo.cpp create mode 100644 final/lib/Target/SystemZ/SystemZRegisterInfo.h create mode 100644 final/lib/Target/SystemZ/SystemZRegisterInfo.td create mode 100644 final/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp create mode 100644 final/lib/Target/SystemZ/SystemZSelectionDAGInfo.h create mode 100644 final/lib/Target/SystemZ/SystemZSubtarget.cpp create mode 100644 final/lib/Target/SystemZ/SystemZSubtarget.h create mode 100644 final/lib/Target/SystemZ/SystemZTargetMachine.cpp create mode 100644 final/lib/Target/SystemZ/SystemZTargetMachine.h create mode 100644 final/lib/Target/SystemZ/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/SystemZ/TargetInfo/Makefile create mode 100644 final/lib/Target/SystemZ/TargetInfo/SystemZTargetInfo.cpp create mode 100644 final/lib/Target/Target.cpp create mode 100644 final/lib/Target/TargetAsmInfo.cpp create mode 100644 final/lib/Target/TargetAsmLexer.cpp create mode 100644 final/lib/Target/TargetData.cpp create mode 100644 final/lib/Target/TargetELFWriterInfo.cpp create mode 100644 final/lib/Target/TargetFrameLowering.cpp create mode 100644 final/lib/Target/TargetInstrInfo.cpp create mode 100644 final/lib/Target/TargetIntrinsicInfo.cpp create mode 100644 final/lib/Target/TargetLibraryInfo.cpp create mode 100644 final/lib/Target/TargetLoweringObjectFile.cpp create mode 100644 final/lib/Target/TargetMachine.cpp create mode 100644 final/lib/Target/TargetRegisterInfo.cpp create mode 100644 final/lib/Target/TargetSubtarget.cpp create mode 100644 final/lib/Target/X86/AsmParser/CMakeLists.txt create mode 100644 final/lib/Target/X86/AsmParser/Makefile create mode 100644 final/lib/Target/X86/AsmParser/X86AsmLexer.cpp create mode 100644 final/lib/Target/X86/AsmParser/X86AsmParser.cpp create mode 100644 final/lib/Target/X86/CMakeLists.txt create mode 100644 final/lib/Target/X86/Disassembler/CMakeLists.txt create mode 100644 final/lib/Target/X86/Disassembler/Makefile create mode 100644 final/lib/Target/X86/Disassembler/X86Disassembler.cpp create mode 100644 final/lib/Target/X86/Disassembler/X86Disassembler.h create mode 100644 final/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c create mode 100644 final/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h create mode 100644 final/lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h create mode 100644 final/lib/Target/X86/InstPrinter/CMakeLists.txt create mode 100644 final/lib/Target/X86/InstPrinter/Makefile create mode 100644 final/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp create mode 100644 final/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h create mode 100644 final/lib/Target/X86/InstPrinter/X86InstComments.cpp create mode 100644 final/lib/Target/X86/InstPrinter/X86InstComments.h create mode 100644 final/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp create mode 100644 final/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h create mode 100644 final/lib/Target/X86/Makefile create mode 100644 final/lib/Target/X86/README-FPStack.txt create mode 100644 final/lib/Target/X86/README-MMX.txt create mode 100644 final/lib/Target/X86/README-SSE.txt create mode 100644 final/lib/Target/X86/README-UNIMPLEMENTED.txt create mode 100644 final/lib/Target/X86/README-X86-64.txt create mode 100644 final/lib/Target/X86/README.txt create mode 100644 final/lib/Target/X86/SSEDomainFix.cpp create mode 100644 final/lib/Target/X86/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/X86/TargetInfo/Makefile create mode 100644 final/lib/Target/X86/TargetInfo/X86TargetInfo.cpp create mode 100644 final/lib/Target/X86/Utils/CMakeLists.txt create mode 100644 final/lib/Target/X86/Utils/Makefile create mode 100644 final/lib/Target/X86/Utils/X86ShuffleDecode.cpp create mode 100644 final/lib/Target/X86/Utils/X86ShuffleDecode.h create mode 100644 final/lib/Target/X86/X86.h create mode 100644 final/lib/Target/X86/X86.td create mode 100644 final/lib/Target/X86/X86AsmBackend.cpp create mode 100644 final/lib/Target/X86/X86AsmPrinter.cpp create mode 100644 final/lib/Target/X86/X86AsmPrinter.h create mode 100644 final/lib/Target/X86/X86COFFMachineModuleInfo.cpp create mode 100644 final/lib/Target/X86/X86COFFMachineModuleInfo.h create mode 100644 final/lib/Target/X86/X86CallingConv.td create mode 100644 final/lib/Target/X86/X86CodeEmitter.cpp create mode 100644 final/lib/Target/X86/X86CompilationCallback_Win64.asm create mode 100644 final/lib/Target/X86/X86ELFWriterInfo.cpp create mode 100644 final/lib/Target/X86/X86ELFWriterInfo.h create mode 100644 final/lib/Target/X86/X86FastISel.cpp create mode 100644 final/lib/Target/X86/X86FixupKinds.h create mode 100644 final/lib/Target/X86/X86FloatingPoint.cpp create mode 100644 final/lib/Target/X86/X86FrameLowering.cpp create mode 100644 final/lib/Target/X86/X86FrameLowering.h create mode 100644 final/lib/Target/X86/X86ISelDAGToDAG.cpp create mode 100644 final/lib/Target/X86/X86ISelLowering.cpp create mode 100644 final/lib/Target/X86/X86ISelLowering.h create mode 100644 final/lib/Target/X86/X86Instr3DNow.td create mode 100644 final/lib/Target/X86/X86InstrArithmetic.td create mode 100644 final/lib/Target/X86/X86InstrBuilder.h create mode 100644 final/lib/Target/X86/X86InstrCMovSetCC.td create mode 100644 final/lib/Target/X86/X86InstrCompiler.td create mode 100644 final/lib/Target/X86/X86InstrControl.td create mode 100644 final/lib/Target/X86/X86InstrExtension.td create mode 100644 final/lib/Target/X86/X86InstrFMA.td create mode 100644 final/lib/Target/X86/X86InstrFPStack.td create mode 100644 final/lib/Target/X86/X86InstrFormats.td create mode 100644 final/lib/Target/X86/X86InstrFragmentsSIMD.td create mode 100644 final/lib/Target/X86/X86InstrInfo.cpp create mode 100644 final/lib/Target/X86/X86InstrInfo.h create mode 100644 final/lib/Target/X86/X86InstrInfo.td create mode 100644 final/lib/Target/X86/X86InstrMMX.td create mode 100644 final/lib/Target/X86/X86InstrSSE.td create mode 100644 final/lib/Target/X86/X86InstrShiftRotate.td create mode 100644 final/lib/Target/X86/X86InstrSystem.td create mode 100644 final/lib/Target/X86/X86InstrVMX.td create mode 100644 final/lib/Target/X86/X86JITInfo.cpp create mode 100644 final/lib/Target/X86/X86JITInfo.h create mode 100644 final/lib/Target/X86/X86MCAsmInfo.cpp create mode 100644 final/lib/Target/X86/X86MCAsmInfo.h create mode 100644 final/lib/Target/X86/X86MCCodeEmitter.cpp create mode 100644 final/lib/Target/X86/X86MCInstLower.cpp create mode 100644 final/lib/Target/X86/X86MCInstLower.h create mode 100644 final/lib/Target/X86/X86MachObjectWriter.cpp create mode 100644 final/lib/Target/X86/X86MachineFunctionInfo.h create mode 100644 final/lib/Target/X86/X86RegisterInfo.cpp create mode 100644 final/lib/Target/X86/X86RegisterInfo.h create mode 100644 final/lib/Target/X86/X86RegisterInfo.td create mode 100644 final/lib/Target/X86/X86Relocations.h create mode 100644 final/lib/Target/X86/X86SelectionDAGInfo.cpp create mode 100644 final/lib/Target/X86/X86SelectionDAGInfo.h create mode 100644 final/lib/Target/X86/X86Subtarget.cpp create mode 100644 final/lib/Target/X86/X86Subtarget.h create mode 100644 final/lib/Target/X86/X86TargetMachine.cpp create mode 100644 final/lib/Target/X86/X86TargetMachine.h create mode 100644 final/lib/Target/X86/X86TargetObjectFile.cpp create mode 100644 final/lib/Target/X86/X86TargetObjectFile.h create mode 100644 final/lib/Target/XCore/CMakeLists.txt create mode 100644 final/lib/Target/XCore/Makefile create mode 100644 final/lib/Target/XCore/README.txt create mode 100644 final/lib/Target/XCore/TargetInfo/CMakeLists.txt create mode 100644 final/lib/Target/XCore/TargetInfo/Makefile create mode 100644 final/lib/Target/XCore/TargetInfo/XCoreTargetInfo.cpp create mode 100644 final/lib/Target/XCore/XCore.h create mode 100644 final/lib/Target/XCore/XCore.td create mode 100644 final/lib/Target/XCore/XCoreAsmPrinter.cpp create mode 100644 final/lib/Target/XCore/XCoreCallingConv.td create mode 100644 final/lib/Target/XCore/XCoreFrameLowering.cpp create mode 100644 final/lib/Target/XCore/XCoreFrameLowering.h create mode 100644 final/lib/Target/XCore/XCoreISelDAGToDAG.cpp create mode 100644 final/lib/Target/XCore/XCoreISelLowering.cpp create mode 100644 final/lib/Target/XCore/XCoreISelLowering.h create mode 100644 final/lib/Target/XCore/XCoreInstrFormats.td create mode 100644 final/lib/Target/XCore/XCoreInstrInfo.cpp create mode 100644 final/lib/Target/XCore/XCoreInstrInfo.h create mode 100644 final/lib/Target/XCore/XCoreInstrInfo.td create mode 100644 final/lib/Target/XCore/XCoreMCAsmInfo.cpp create mode 100644 final/lib/Target/XCore/XCoreMCAsmInfo.h create mode 100644 final/lib/Target/XCore/XCoreMachineFunctionInfo.h create mode 100644 final/lib/Target/XCore/XCoreRegisterInfo.cpp create mode 100644 final/lib/Target/XCore/XCoreRegisterInfo.h create mode 100644 final/lib/Target/XCore/XCoreRegisterInfo.td create mode 100644 final/lib/Target/XCore/XCoreSelectionDAGInfo.cpp create mode 100644 final/lib/Target/XCore/XCoreSelectionDAGInfo.h create mode 100644 final/lib/Target/XCore/XCoreSubtarget.cpp create mode 100644 final/lib/Target/XCore/XCoreSubtarget.h create mode 100644 final/lib/Target/XCore/XCoreTargetMachine.cpp create mode 100644 final/lib/Target/XCore/XCoreTargetMachine.h create mode 100644 final/lib/Target/XCore/XCoreTargetObjectFile.cpp create mode 100644 final/lib/Target/XCore/XCoreTargetObjectFile.h create mode 100644 final/lib/Transforms/CMakeLists.txt create mode 100644 final/lib/Transforms/Hello/CMakeLists.txt create mode 100644 final/lib/Transforms/Hello/Hello.cpp create mode 100644 final/lib/Transforms/Hello/Hello.exports create mode 100644 final/lib/Transforms/Hello/Makefile create mode 100644 final/lib/Transforms/IPO/ArgumentPromotion.cpp create mode 100644 final/lib/Transforms/IPO/CMakeLists.txt create mode 100644 final/lib/Transforms/IPO/ConstantMerge.cpp create mode 100644 final/lib/Transforms/IPO/DeadArgumentElimination.cpp create mode 100644 final/lib/Transforms/IPO/DeadTypeElimination.cpp create mode 100644 final/lib/Transforms/IPO/ExtractGV.cpp create mode 100644 final/lib/Transforms/IPO/FunctionAttrs.cpp create mode 100644 final/lib/Transforms/IPO/GlobalDCE.cpp create mode 100644 final/lib/Transforms/IPO/GlobalOpt.cpp create mode 100644 final/lib/Transforms/IPO/IPConstantPropagation.cpp create mode 100644 final/lib/Transforms/IPO/IPO.cpp create mode 100644 final/lib/Transforms/IPO/InlineAlways.cpp create mode 100644 final/lib/Transforms/IPO/InlineSimple.cpp create mode 100644 final/lib/Transforms/IPO/Inliner.cpp create mode 100644 final/lib/Transforms/IPO/Internalize.cpp create mode 100644 final/lib/Transforms/IPO/LoopExtractor.cpp create mode 100644 final/lib/Transforms/IPO/LowerSetJmp.cpp create mode 100644 final/lib/Transforms/IPO/Makefile create mode 100644 final/lib/Transforms/IPO/MergeFunctions.cpp create mode 100644 final/lib/Transforms/IPO/PartialInlining.cpp create mode 100644 final/lib/Transforms/IPO/PruneEH.cpp create mode 100644 final/lib/Transforms/IPO/StripDeadPrototypes.cpp create mode 100644 final/lib/Transforms/IPO/StripSymbols.cpp create mode 100644 final/lib/Transforms/IPO/StructRetPromotion.cpp create mode 100644 final/lib/Transforms/InstCombine/CMakeLists.txt create mode 100644 final/lib/Transforms/InstCombine/InstCombine.h create mode 100644 final/lib/Transforms/InstCombine/InstCombineAddSub.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineCalls.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineCasts.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineCompares.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombinePHI.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineSelect.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineShifts.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineVectorOps.cpp create mode 100644 final/lib/Transforms/InstCombine/InstCombineWorklist.h create mode 100644 final/lib/Transforms/InstCombine/InstructionCombining.cpp create mode 100644 final/lib/Transforms/InstCombine/Makefile create mode 100644 final/lib/Transforms/Instrumentation/CMakeLists.txt create mode 100644 final/lib/Transforms/Instrumentation/EdgeProfiling.cpp create mode 100644 final/lib/Transforms/Instrumentation/Instrumentation.cpp create mode 100644 final/lib/Transforms/Instrumentation/Makefile create mode 100644 final/lib/Transforms/Instrumentation/MaximumSpanningTree.h create mode 100644 final/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp create mode 100644 final/lib/Transforms/Instrumentation/PathProfiling.cpp create mode 100644 final/lib/Transforms/Instrumentation/ProfilingUtils.cpp create mode 100644 final/lib/Transforms/Instrumentation/ProfilingUtils.h create mode 100644 final/lib/Transforms/Makefile create mode 100644 final/lib/Transforms/Scalar/ADCE.cpp create mode 100644 final/lib/Transforms/Scalar/BasicBlockPlacement.cpp create mode 100644 final/lib/Transforms/Scalar/CMakeLists.txt create mode 100644 final/lib/Transforms/Scalar/CodeGenPrepare.cpp create mode 100644 final/lib/Transforms/Scalar/ConstantProp.cpp create mode 100644 final/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp create mode 100644 final/lib/Transforms/Scalar/DCE.cpp create mode 100644 final/lib/Transforms/Scalar/DeadStoreElimination.cpp create mode 100644 final/lib/Transforms/Scalar/EarlyCSE.cpp create mode 100644 final/lib/Transforms/Scalar/GVN.cpp create mode 100644 final/lib/Transforms/Scalar/IndVarSimplify.cpp create mode 100644 final/lib/Transforms/Scalar/JumpThreading.cpp create mode 100644 final/lib/Transforms/Scalar/LICM.cpp create mode 100644 final/lib/Transforms/Scalar/LoopDeletion.cpp create mode 100644 final/lib/Transforms/Scalar/LoopIdiomRecognize.cpp create mode 100644 final/lib/Transforms/Scalar/LoopInstSimplify.cpp create mode 100644 final/lib/Transforms/Scalar/LoopRotation.cpp create mode 100644 final/lib/Transforms/Scalar/LoopStrengthReduce.cpp create mode 100644 final/lib/Transforms/Scalar/LoopUnrollPass.cpp create mode 100644 final/lib/Transforms/Scalar/LoopUnswitch.cpp create mode 100644 final/lib/Transforms/Scalar/LowerAtomic.cpp create mode 100644 final/lib/Transforms/Scalar/Makefile create mode 100644 final/lib/Transforms/Scalar/MemCpyOptimizer.cpp create mode 100644 final/lib/Transforms/Scalar/Reassociate.cpp create mode 100644 final/lib/Transforms/Scalar/Reg2Mem.cpp create mode 100644 final/lib/Transforms/Scalar/SCCP.cpp create mode 100644 final/lib/Transforms/Scalar/Scalar.cpp create mode 100644 final/lib/Transforms/Scalar/ScalarReplAggregates.cpp create mode 100644 final/lib/Transforms/Scalar/SimplifyCFGPass.cpp create mode 100644 final/lib/Transforms/Scalar/SimplifyLibCalls.cpp create mode 100644 final/lib/Transforms/Scalar/Sink.cpp create mode 100644 final/lib/Transforms/Scalar/TailDuplication.cpp create mode 100644 final/lib/Transforms/Scalar/TailRecursionElimination.cpp create mode 100644 final/lib/Transforms/Utils/AddrModeMatcher.cpp create mode 100644 final/lib/Transforms/Utils/BasicBlockUtils.cpp create mode 100644 final/lib/Transforms/Utils/BasicInliner.cpp create mode 100644 final/lib/Transforms/Utils/BreakCriticalEdges.cpp create mode 100644 final/lib/Transforms/Utils/BuildLibCalls.cpp create mode 100644 final/lib/Transforms/Utils/CMakeLists.txt create mode 100644 final/lib/Transforms/Utils/CloneFunction.cpp create mode 100644 final/lib/Transforms/Utils/CloneLoop.cpp create mode 100644 final/lib/Transforms/Utils/CloneModule.cpp create mode 100644 final/lib/Transforms/Utils/CodeExtractor.cpp create mode 100644 final/lib/Transforms/Utils/DemoteRegToStack.cpp create mode 100644 final/lib/Transforms/Utils/InlineFunction.cpp create mode 100644 final/lib/Transforms/Utils/InstructionNamer.cpp create mode 100644 final/lib/Transforms/Utils/LCSSA.cpp create mode 100644 final/lib/Transforms/Utils/Local.cpp create mode 100644 final/lib/Transforms/Utils/LoopSimplify.cpp create mode 100644 final/lib/Transforms/Utils/LoopUnroll.cpp create mode 100644 final/lib/Transforms/Utils/LowerInvoke.cpp create mode 100644 final/lib/Transforms/Utils/LowerSwitch.cpp create mode 100644 final/lib/Transforms/Utils/Makefile create mode 100644 final/lib/Transforms/Utils/Mem2Reg.cpp create mode 100644 final/lib/Transforms/Utils/PromoteMemoryToRegister.cpp create mode 100644 final/lib/Transforms/Utils/SSAUpdater.cpp create mode 100644 final/lib/Transforms/Utils/SimplifyCFG.cpp create mode 100644 final/lib/Transforms/Utils/SimplifyInstructions.cpp create mode 100644 final/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp create mode 100644 final/lib/Transforms/Utils/Utils.cpp create mode 100644 final/lib/Transforms/Utils/ValueMapper.cpp create mode 100644 final/lib/VMCore/AsmWriter.cpp create mode 100644 final/lib/VMCore/Attributes.cpp create mode 100644 final/lib/VMCore/AutoUpgrade.cpp create mode 100644 final/lib/VMCore/BasicBlock.cpp create mode 100644 final/lib/VMCore/CMakeLists.txt create mode 100644 final/lib/VMCore/ConstantFold.cpp create mode 100644 final/lib/VMCore/ConstantFold.h create mode 100644 final/lib/VMCore/Constants.cpp create mode 100644 final/lib/VMCore/ConstantsContext.h create mode 100644 final/lib/VMCore/Core.cpp create mode 100644 final/lib/VMCore/DebugLoc.cpp create mode 100644 final/lib/VMCore/Dominators.cpp create mode 100644 final/lib/VMCore/Function.cpp create mode 100644 final/lib/VMCore/GVMaterializer.cpp create mode 100644 final/lib/VMCore/Globals.cpp create mode 100644 final/lib/VMCore/IRBuilder.cpp create mode 100644 final/lib/VMCore/InlineAsm.cpp create mode 100644 final/lib/VMCore/Instruction.cpp create mode 100644 final/lib/VMCore/Instructions.cpp create mode 100644 final/lib/VMCore/IntrinsicInst.cpp create mode 100644 final/lib/VMCore/LLVMContext.cpp create mode 100644 final/lib/VMCore/LLVMContextImpl.cpp create mode 100644 final/lib/VMCore/LLVMContextImpl.h create mode 100644 final/lib/VMCore/LeakDetector.cpp create mode 100644 final/lib/VMCore/LeaksContext.h create mode 100644 final/lib/VMCore/Makefile create mode 100644 final/lib/VMCore/Metadata.cpp create mode 100644 final/lib/VMCore/Module.cpp create mode 100644 final/lib/VMCore/Pass.cpp create mode 100644 final/lib/VMCore/PassManager.cpp create mode 100644 final/lib/VMCore/PassRegistry.cpp create mode 100644 final/lib/VMCore/PrintModulePass.cpp create mode 100644 final/lib/VMCore/SymbolTableListTraitsImpl.h create mode 100644 final/lib/VMCore/Type.cpp create mode 100644 final/lib/VMCore/TypeSymbolTable.cpp create mode 100644 final/lib/VMCore/TypesContext.h create mode 100644 final/lib/VMCore/Use.cpp create mode 100644 final/lib/VMCore/User.cpp create mode 100644 final/lib/VMCore/Value.cpp create mode 100644 final/lib/VMCore/ValueSymbolTable.cpp create mode 100644 final/lib/VMCore/ValueTypes.cpp create mode 100644 final/lib/VMCore/Verifier.cpp create mode 100644 final/llvm.spec.in create mode 100644 final/projects/CMakeLists.txt create mode 100644 final/projects/Makefile create mode 100644 final/projects/sample/Makefile create mode 100644 final/projects/sample/Makefile.common.in create mode 100755 final/projects/sample/autoconf/AutoRegen.sh create mode 100644 final/projects/sample/autoconf/LICENSE.TXT create mode 100755 final/projects/sample/autoconf/config.guess create mode 100755 final/projects/sample/autoconf/config.sub create mode 100644 final/projects/sample/autoconf/configure.ac create mode 100755 final/projects/sample/configure create mode 100644 final/projects/sample/docs/index.html create mode 100644 final/projects/sample/include/sample.h create mode 100644 final/projects/sample/lib/Makefile create mode 100644 final/projects/sample/lib/sample/Makefile create mode 100644 final/projects/sample/lib/sample/sample.c create mode 100644 final/projects/sample/tools/Makefile create mode 100644 final/projects/sample/tools/sample/Makefile create mode 100644 final/projects/sample/tools/sample/main.c create mode 100644 final/runtime/Makefile create mode 100644 final/runtime/README.txt create mode 100644 final/runtime/libprofile/BasicBlockTracing.c create mode 100644 final/runtime/libprofile/CommonProfiling.c create mode 100644 final/runtime/libprofile/EdgeProfiling.c create mode 100644 final/runtime/libprofile/Makefile create mode 100644 final/runtime/libprofile/OptimalEdgeProfiling.c create mode 100644 final/runtime/libprofile/PathProfiling.c create mode 100644 final/runtime/libprofile/Profiling.h create mode 100644 final/runtime/libprofile/libprofile.exports create mode 100644 final/test/Analysis/BasicAA/2003-02-26-AccessSizeTest.ll create mode 100644 final/test/Analysis/BasicAA/2003-03-04-GEPCrash.ll create mode 100644 final/test/Analysis/BasicAA/2003-04-22-GEPProblem.ll create mode 100644 final/test/Analysis/BasicAA/2003-04-25-GEPCrash.ll create mode 100644 final/test/Analysis/BasicAA/2003-05-21-GEP-Problem.ll create mode 100644 final/test/Analysis/BasicAA/2003-06-01-AliasCrash.ll create mode 100644 final/test/Analysis/BasicAA/2003-07-03-BasicAACrash.ll create mode 100644 final/test/Analysis/BasicAA/2003-09-19-LocalArgument.ll create mode 100644 final/test/Analysis/BasicAA/2003-11-04-SimpleCases.ll create mode 100644 final/test/Analysis/BasicAA/2003-12-11-ConstExprGEP.ll create mode 100644 final/test/Analysis/BasicAA/2004-07-28-MustAliasbug.ll create mode 100644 final/test/Analysis/BasicAA/2004-12-08-BasicAACrash.ll create mode 100644 final/test/Analysis/BasicAA/2004-12-08-BasicAACrash2.ll create mode 100644 final/test/Analysis/BasicAA/2005-03-09-BrokenBasicAA.ll create mode 100644 final/test/Analysis/BasicAA/2006-03-03-BadArraySubscript.ll create mode 100644 final/test/Analysis/BasicAA/2006-11-03-BasicAAVectorCrash.ll create mode 100644 final/test/Analysis/BasicAA/2007-01-13-BasePointerBadNoAlias.ll create mode 100644 final/test/Analysis/BasicAA/2007-08-01-NoAliasAndCalls.ll create mode 100644 final/test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll create mode 100644 final/test/Analysis/BasicAA/2007-08-05-GetOverloadedModRef.ll create mode 100644 final/test/Analysis/BasicAA/2007-10-24-ArgumentsGlobals.ll create mode 100644 final/test/Analysis/BasicAA/2007-11-05-SizeCrash.ll create mode 100644 final/test/Analysis/BasicAA/2007-12-08-OutOfBoundsCrash.ll create mode 100644 final/test/Analysis/BasicAA/2008-04-15-Byval.ll create mode 100644 final/test/Analysis/BasicAA/2008-06-02-GEPTailCrash.ll create mode 100644 final/test/Analysis/BasicAA/2008-11-23-NoaliasRet.ll create mode 100644 final/test/Analysis/BasicAA/2009-03-04-GEPNoalias.ll create mode 100644 final/test/Analysis/BasicAA/2009-10-13-AtomicModRef.ll create mode 100644 final/test/Analysis/BasicAA/2009-10-13-GEP-BaseNoAlias.ll create mode 100644 final/test/Analysis/BasicAA/2010-09-15-GEP-SignedArithmetic.ll create mode 100644 final/test/Analysis/BasicAA/args-rets-allocas-loads.ll create mode 100644 final/test/Analysis/BasicAA/byval.ll create mode 100644 final/test/Analysis/BasicAA/cas.ll create mode 100644 final/test/Analysis/BasicAA/constant-over-index.ll create mode 100644 final/test/Analysis/BasicAA/dg.exp create mode 100644 final/test/Analysis/BasicAA/empty.ll create mode 100644 final/test/Analysis/BasicAA/featuretest.ll create mode 100644 final/test/Analysis/BasicAA/full-store-partial-alias.ll create mode 100644 final/test/Analysis/BasicAA/gcsetest.ll create mode 100644 final/test/Analysis/BasicAA/gep-alias.ll create mode 100644 final/test/Analysis/BasicAA/getmodrefinfo-cs-cs.ll create mode 100644 final/test/Analysis/BasicAA/global-size.ll create mode 100644 final/test/Analysis/BasicAA/modref.ll create mode 100644 final/test/Analysis/BasicAA/no-escape-call.ll create mode 100644 final/test/Analysis/BasicAA/nocapture.ll create mode 100644 final/test/Analysis/BasicAA/phi-aa.ll create mode 100644 final/test/Analysis/BasicAA/phi-and-select.ll create mode 100644 final/test/Analysis/BasicAA/pure-const-dce.ll create mode 100644 final/test/Analysis/BasicAA/store-promote.ll create mode 100644 final/test/Analysis/BasicAA/tailcall-modref.ll create mode 100644 final/test/Analysis/BasicAA/unreachable-block.ll create mode 100644 final/test/Analysis/CallGraph/2008-09-09-DirectCall.ll create mode 100644 final/test/Analysis/CallGraph/2008-09-09-UsedByGlobal.ll create mode 100644 final/test/Analysis/CallGraph/dg.exp create mode 100644 final/test/Analysis/Dominators/2006-10-02-BreakCritEdges.ll create mode 100644 final/test/Analysis/Dominators/2007-01-14-BreakCritEdges.ll create mode 100644 final/test/Analysis/Dominators/2007-07-11-SplitBlock.ll create mode 100644 final/test/Analysis/Dominators/2007-07-12-SplitBlock.ll create mode 100644 final/test/Analysis/Dominators/dg.exp create mode 100644 final/test/Analysis/GlobalsModRef/2008-09-03-ReadGlobals.ll create mode 100644 final/test/Analysis/GlobalsModRef/aliastest.ll create mode 100644 final/test/Analysis/GlobalsModRef/chaining-analysis.ll create mode 100644 final/test/Analysis/GlobalsModRef/dg.exp create mode 100644 final/test/Analysis/GlobalsModRef/indirect-global.ll create mode 100644 final/test/Analysis/GlobalsModRef/modreftest.ll create mode 100644 final/test/Analysis/GlobalsModRef/purecse.ll create mode 100644 final/test/Analysis/LoopDependenceAnalysis/alias.ll create mode 100644 final/test/Analysis/LoopDependenceAnalysis/dg.exp create mode 100644 final/test/Analysis/LoopDependenceAnalysis/siv-strong.ll create mode 100644 final/test/Analysis/LoopDependenceAnalysis/siv-weak-crossing.ll create mode 100644 final/test/Analysis/LoopDependenceAnalysis/siv-weak-zero.ll create mode 100644 final/test/Analysis/LoopDependenceAnalysis/ziv.ll create mode 100644 final/test/Analysis/LoopInfo/2003-05-15-NestingProblem.ll create mode 100644 final/test/Analysis/LoopInfo/dg.exp create mode 100644 final/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll create mode 100644 final/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll create mode 100644 final/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll create mode 100644 final/test/Analysis/PostDominators/dg.exp create mode 100644 final/test/Analysis/PostDominators/pr1098.ll create mode 100644 final/test/Analysis/PostDominators/pr6047_a.ll create mode 100644 final/test/Analysis/PostDominators/pr6047_b.ll create mode 100644 final/test/Analysis/PostDominators/pr6047_c.ll create mode 100644 final/test/Analysis/PostDominators/pr6047_d.ll create mode 100644 final/test/Analysis/Profiling/dg.exp create mode 100644 final/test/Analysis/Profiling/edge-profiling.ll create mode 100644 final/test/Analysis/Profiling/profiling-tool-chain.ll create mode 100644 final/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll create mode 100644 final/test/Analysis/RegionInfo/block_sort.ll create mode 100644 final/test/Analysis/RegionInfo/cond_loop.ll create mode 100644 final/test/Analysis/RegionInfo/condition_complicated.ll create mode 100644 final/test/Analysis/RegionInfo/condition_complicated_2.ll create mode 100644 final/test/Analysis/RegionInfo/condition_forward_edge.ll create mode 100644 final/test/Analysis/RegionInfo/condition_same_exit.ll create mode 100644 final/test/Analysis/RegionInfo/condition_simple.ll create mode 100644 final/test/Analysis/RegionInfo/dg.exp create mode 100644 final/test/Analysis/RegionInfo/exit_in_condition.ll create mode 100644 final/test/Analysis/RegionInfo/infinite_loop.ll create mode 100644 final/test/Analysis/RegionInfo/infinite_loop_2.ll create mode 100644 final/test/Analysis/RegionInfo/infinite_loop_3.ll create mode 100644 final/test/Analysis/RegionInfo/infinite_loop_4.ll create mode 100644 final/test/Analysis/RegionInfo/loop_with_condition.ll create mode 100644 final/test/Analysis/RegionInfo/loops_1.ll create mode 100644 final/test/Analysis/RegionInfo/loops_2.ll create mode 100644 final/test/Analysis/RegionInfo/mix_1.ll create mode 100644 final/test/Analysis/RegionInfo/multiple_exiting_edge.ll create mode 100644 final/test/Analysis/RegionInfo/nested_loops.ll create mode 100644 final/test/Analysis/RegionInfo/next.ll create mode 100644 final/test/Analysis/RegionInfo/paper.ll create mode 100644 final/test/Analysis/RegionInfo/two_loops_same_header.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll create mode 100644 final/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll create mode 100644 final/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll create mode 100644 final/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll create mode 100644 final/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll create mode 100644 final/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll create mode 100644 final/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll create mode 100644 final/test/Analysis/ScalarEvolution/2010-09-03-RequiredTransitive.ll create mode 100644 final/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll create mode 100644 final/test/Analysis/ScalarEvolution/and-xor.ll create mode 100644 final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll create mode 100644 final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll create mode 100644 final/test/Analysis/ScalarEvolution/avoid-smax-0.ll create mode 100644 final/test/Analysis/ScalarEvolution/avoid-smax-1.ll create mode 100644 final/test/Analysis/ScalarEvolution/dg.exp create mode 100644 final/test/Analysis/ScalarEvolution/div-overflow.ll create mode 100644 final/test/Analysis/ScalarEvolution/do-loop.ll create mode 100644 final/test/Analysis/ScalarEvolution/fold.ll create mode 100644 final/test/Analysis/ScalarEvolution/max-trip-count.ll create mode 100644 final/test/Analysis/ScalarEvolution/nsw-offset.ll create mode 100644 final/test/Analysis/ScalarEvolution/nsw.ll create mode 100644 final/test/Analysis/ScalarEvolution/pointer-sign-bits.ll create mode 100644 final/test/Analysis/ScalarEvolution/pr3909.ll create mode 100644 final/test/Analysis/ScalarEvolution/scev-aa.ll create mode 100644 final/test/Analysis/ScalarEvolution/sext-inreg.ll create mode 100644 final/test/Analysis/ScalarEvolution/sext-iv-0.ll create mode 100644 final/test/Analysis/ScalarEvolution/sext-iv-1.ll create mode 100644 final/test/Analysis/ScalarEvolution/sext-iv-2.ll create mode 100644 final/test/Analysis/ScalarEvolution/sle.ll create mode 100644 final/test/Analysis/ScalarEvolution/smax.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count10.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count2.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count3.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count4.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count5.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count6.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count7.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count8.ll create mode 100644 final/test/Analysis/ScalarEvolution/trip-count9.ll create mode 100644 final/test/Analysis/ScalarEvolution/undefined.ll create mode 100644 final/test/Analysis/ScalarEvolution/unreachable-code.ll create mode 100644 final/test/Analysis/ScalarEvolution/unsimplified-loop.ll create mode 100644 final/test/Analysis/ScalarEvolution/xor-and.ll create mode 100644 final/test/Analysis/ScalarEvolution/zext-wrap.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/aliastest.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/argument-promotion.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/dg.exp create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/dse.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/gvn-nonlocal-type-mismatch.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/licm.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/precedence.ll create mode 100644 final/test/Analysis/TypeBasedAliasAnalysis/sink.ll create mode 100644 final/test/Archive/GNU.a create mode 100644 final/test/Archive/IsNAN.o create mode 100644 final/test/Archive/MacOSX.a create mode 100644 final/test/Archive/README.txt create mode 100644 final/test/Archive/SVR4.a create mode 100644 final/test/Archive/dg.exp create mode 100644 final/test/Archive/evenlen create mode 100644 final/test/Archive/extract.ll create mode 100644 final/test/Archive/oddlen create mode 100644 final/test/Archive/toc_GNU.ll create mode 100644 final/test/Archive/toc_MacOSX.ll create mode 100644 final/test/Archive/toc_SVR4.ll create mode 100644 final/test/Archive/toc_xpg4.ll create mode 100644 final/test/Archive/very_long_bytecode_file_name.bc create mode 100644 final/test/Archive/xpg4.a create mode 100644 final/test/Assembler/2002-01-24-BadSymbolTableAssert.ll create mode 100644 final/test/Assembler/2002-01-24-ValueRefineAbsType.ll create mode 100644 final/test/Assembler/2002-02-19-TypeParsing.ll create mode 100644 final/test/Assembler/2002-03-08-NameCollision.ll create mode 100644 final/test/Assembler/2002-03-08-NameCollision2.ll create mode 100644 final/test/Assembler/2002-04-04-PureVirtMethCall.ll create mode 100644 final/test/Assembler/2002-04-04-PureVirtMethCall2.ll create mode 100644 final/test/Assembler/2002-04-05-TypeParsing.ll create mode 100644 final/test/Assembler/2002-04-07-HexFloatConstants.ll create mode 100644 final/test/Assembler/2002-04-07-InfConstant.ll create mode 100644 final/test/Assembler/2002-04-29-NameBinding.ll create mode 100644 final/test/Assembler/2002-05-02-InvalidForwardRef.ll create mode 100644 final/test/Assembler/2002-05-02-ParseError.ll create mode 100644 final/test/Assembler/2002-07-08-HugePerformanceProblem.ll create mode 100644 final/test/Assembler/2002-07-14-InternalLossage.ll create mode 100644 final/test/Assembler/2002-07-14-OpaqueType.ll create mode 100644 final/test/Assembler/2002-07-25-ParserAssertionFailure.ll create mode 100644 final/test/Assembler/2002-07-25-QuoteInString.ll create mode 100644 final/test/Assembler/2002-07-25-ReturnPtrFunction.ll create mode 100644 final/test/Assembler/2002-07-31-SlashInString.ll create mode 100644 final/test/Assembler/2002-08-15-CastAmbiguity.ll create mode 100644 final/test/Assembler/2002-08-15-ConstantExprProblem.ll create mode 100644 final/test/Assembler/2002-08-15-UnresolvedGlobalReference.ll create mode 100644 final/test/Assembler/2002-08-16-ConstExprInlined.ll create mode 100644 final/test/Assembler/2002-08-19-BytecodeReader.ll create mode 100644 final/test/Assembler/2002-08-22-DominanceProblem.ll create mode 100644 final/test/Assembler/2002-10-08-LargeArrayPerformance.ll create mode 100644 final/test/Assembler/2002-10-13-ConstantEncodingProblem.ll create mode 100644 final/test/Assembler/2002-10-15-NameClash.ll create mode 100644 final/test/Assembler/2002-12-15-GlobalResolve.ll create mode 100644 final/test/Assembler/2003-01-30-UnsignedString.ll create mode 100644 final/test/Assembler/2003-04-15-ConstantInitAssertion.ll create mode 100644 final/test/Assembler/2003-04-25-UnresolvedGlobalReference.ll create mode 100644 final/test/Assembler/2003-05-03-BytecodeReaderProblem.ll create mode 100644 final/test/Assembler/2003-05-12-MinIntProblem.ll create mode 100644 final/test/Assembler/2003-05-15-AssemblerProblem.ll create mode 100644 final/test/Assembler/2003-05-15-SwitchBug.ll create mode 100644 final/test/Assembler/2003-05-21-ConstantShiftExpr.ll create mode 100644 final/test/Assembler/2003-05-21-EmptyStructTest.ll create mode 100644 final/test/Assembler/2003-05-21-MalformedShiftCrash.ll create mode 100644 final/test/Assembler/2003-05-21-MalformedStructCrash.ll create mode 100644 final/test/Assembler/2003-06-17-InvokeDisassemble.ll create mode 100644 final/test/Assembler/2003-06-30-RecursiveTypeProblem.ll create mode 100644 final/test/Assembler/2003-08-20-ConstantExprGEP-Fold.ll create mode 100644 final/test/Assembler/2003-08-21-ConstantExprCast-Fold.ll create mode 100644 final/test/Assembler/2003-10-04-NotMergingGlobalConstants.ll create mode 100644 final/test/Assembler/2003-11-05-ConstantExprShift.ll create mode 100644 final/test/Assembler/2003-11-11-ImplicitRename.ll create mode 100644 final/test/Assembler/2003-11-12-ConstantExprCast.ll create mode 100644 final/test/Assembler/2003-11-24-SymbolTableCrash.ll create mode 100644 final/test/Assembler/2003-12-30-TypeMapInvalidMemory.ll create mode 100644 final/test/Assembler/2004-01-11-getelementptrfolding.ll create mode 100644 final/test/Assembler/2004-01-20-MaxLongLong.ll create mode 100644 final/test/Assembler/2004-02-01-NegativeZero.ll create mode 100644 final/test/Assembler/2004-02-27-SelfUseAssertError.ll create mode 100644 final/test/Assembler/2004-03-07-FunctionAddressAlignment.ll create mode 100644 final/test/Assembler/2004-03-30-UnclosedFunctionCrash.ll create mode 100644 final/test/Assembler/2004-04-04-GetElementPtrIndexTypes.ll create mode 100644 final/test/Assembler/2004-06-07-VerifierBug.ll create mode 100644 final/test/Assembler/2004-10-22-BCWriterUndefBug.ll create mode 100644 final/test/Assembler/2004-11-28-InvalidTypeCrash.ll create mode 100644 final/test/Assembler/2005-01-03-FPConstantDisassembly.ll create mode 100644 final/test/Assembler/2005-01-31-CallingAggregateFunction.ll create mode 100644 final/test/Assembler/2005-02-09-AsmWriterStoreBug.ll create mode 100644 final/test/Assembler/2005-05-05-OpaqueUndefValues.ll create mode 100644 final/test/Assembler/2005-12-21-ZeroInitVector.ll create mode 100644 final/test/Assembler/2006-05-26-VarargsCallEncode.ll create mode 100644 final/test/Assembler/2006-09-28-CrashOnInvalid.ll create mode 100644 final/test/Assembler/2006-12-09-Cast-To-Bool.ll create mode 100644 final/test/Assembler/2007-01-02-Undefined-Arg-Type.ll create mode 100644 final/test/Assembler/2007-01-05-Cmp-ConstExpr.ll create mode 100644 final/test/Assembler/2007-01-16-CrashOnBadCast.ll create mode 100644 final/test/Assembler/2007-01-16-CrashOnBadCast2.ll create mode 100644 final/test/Assembler/2007-03-18-InvalidNumberedVar.ll create mode 100644 final/test/Assembler/2007-03-19-NegValue.ll create mode 100644 final/test/Assembler/2007-04-20-AlignedLoad.ll create mode 100644 final/test/Assembler/2007-04-20-AlignedStore.ll create mode 100644 final/test/Assembler/2007-04-25-AssemblerFoldExternWeak.ll create mode 100644 final/test/Assembler/2007-05-21-Escape.ll create mode 100644 final/test/Assembler/2007-07-19-ParamAttrAmbiguity.ll create mode 100644 final/test/Assembler/2007-07-30-AutoUpgradeZextSext.ll create mode 100644 final/test/Assembler/2007-08-06-AliasInvalid.ll create mode 100644 final/test/Assembler/2007-09-10-AliasFwdRef.ll create mode 100644 final/test/Assembler/2007-09-29-GC.ll create mode 100644 final/test/Assembler/2007-11-26-AttributeOverload.ll create mode 100644 final/test/Assembler/2007-11-27-AutoUpgradeAttributes.ll create mode 100644 final/test/Assembler/2007-12-11-AddressSpaces.ll create mode 100644 final/test/Assembler/2008-01-11-VarargAttrs.ll create mode 100644 final/test/Assembler/2008-02-18-IntPointerCrash.ll create mode 100644 final/test/Assembler/2008-02-20-MultipleReturnValue.ll create mode 100644 final/test/Assembler/2008-07-10-APInt.ll create mode 100644 final/test/Assembler/2008-09-02-FunctionNotes.ll create mode 100644 final/test/Assembler/2008-09-02-FunctionNotes2.ll create mode 100644 final/test/Assembler/2008-09-29-RetAttr.ll create mode 100644 final/test/Assembler/2008-10-14-NamedTypeOnInteger.ll create mode 100644 final/test/Assembler/2008-10-14-QuoteInName.ll create mode 100644 final/test/Assembler/2009-02-01-UnnamedForwardRef.ll create mode 100644 final/test/Assembler/2009-02-28-CastOpc.ll create mode 100644 final/test/Assembler/2009-02-28-StripOpaqueName.ll create mode 100644 final/test/Assembler/2009-03-24-ZextConstantExpr.ll create mode 100644 final/test/Assembler/2009-04-25-AliasGEP.ll create mode 100644 final/test/Assembler/2009-07-24-ZeroArgGEP.ll create mode 100644 final/test/Assembler/2010-02-05-FunctionLocalMetadataBecomesNull.ll create mode 100644 final/test/Assembler/AutoUpgradeIntrinsics.ll create mode 100644 final/test/Assembler/AutoUpgradeMMXIntrinsics.ll create mode 100644 final/test/Assembler/ConstantExprFold.ll create mode 100644 final/test/Assembler/ConstantExprFoldCast.ll create mode 100644 final/test/Assembler/MultipleReturnValueType.ll create mode 100644 final/test/Assembler/aggregate-constant-values.ll create mode 100644 final/test/Assembler/aggregate-return-single-value.ll create mode 100644 final/test/Assembler/align-inst-alloca.ll create mode 100644 final/test/Assembler/align-inst-load.ll create mode 100644 final/test/Assembler/align-inst-store.ll create mode 100644 final/test/Assembler/align-inst.ll create mode 100644 final/test/Assembler/alignstack.ll create mode 100644 final/test/Assembler/anon-functions.ll create mode 100644 final/test/Assembler/bcwrap.ll create mode 100644 final/test/Assembler/comment.ll create mode 100644 final/test/Assembler/dg.exp create mode 100644 final/test/Assembler/extractvalue-invalid-idx.ll create mode 100644 final/test/Assembler/flags.ll create mode 100644 final/test/Assembler/functionlocal-metadata.ll create mode 100644 final/test/Assembler/getelementptr.ll create mode 100644 final/test/Assembler/getelementptr_struct.ll create mode 100644 final/test/Assembler/huge-array.ll create mode 100644 final/test/Assembler/insertextractvalue.ll create mode 100644 final/test/Assembler/insertvalue-invalid-idx.ll create mode 100644 final/test/Assembler/metadata.ll create mode 100644 final/test/Assembler/numbered-values.ll create mode 100644 final/test/Assembler/private.ll create mode 100644 final/test/Assembler/select.ll create mode 100644 final/test/Assembler/unnamed-addr.ll create mode 100644 final/test/Assembler/unnamed.ll create mode 100644 final/test/Assembler/vbool-cmp.ll create mode 100644 final/test/Assembler/vector-cmp.ll create mode 100644 final/test/Assembler/vector-select.ll create mode 100644 final/test/Assembler/vector-shift.ll create mode 100644 final/test/Assembler/x86mmx.ll create mode 100644 final/test/Bindings/Ocaml/analysis.ml create mode 100644 final/test/Bindings/Ocaml/bitreader.ml create mode 100644 final/test/Bindings/Ocaml/bitwriter.ml create mode 100644 final/test/Bindings/Ocaml/dg.exp create mode 100644 final/test/Bindings/Ocaml/executionengine.ml create mode 100644 final/test/Bindings/Ocaml/ext_exc.ml create mode 100644 final/test/Bindings/Ocaml/scalar_opts.ml create mode 100644 final/test/Bindings/Ocaml/target.ml create mode 100644 final/test/Bindings/Ocaml/vmcore.ml create mode 100644 final/test/Bitcode/2006-12-11-Cast-ConstExpr.ll create mode 100644 final/test/Bitcode/2009-06-11-FirstClassAggregateConstant.ll create mode 100644 final/test/Bitcode/AutoUpgradeGlobals.ll create mode 100644 final/test/Bitcode/AutoUpgradeGlobals.ll.bc create mode 100644 final/test/Bitcode/AutoUpgradeIntrinsics.ll create mode 100644 final/test/Bitcode/AutoUpgradeIntrinsics.ll.bc create mode 100644 final/test/Bitcode/dg.exp create mode 100644 final/test/Bitcode/extractelement.ll create mode 100644 final/test/Bitcode/flags.ll create mode 100644 final/test/Bitcode/memcpy.ll create mode 100644 final/test/Bitcode/metadata-2.ll create mode 100644 final/test/Bitcode/metadata.ll create mode 100644 final/test/Bitcode/neon-intrinsics.ll create mode 100644 final/test/Bitcode/neon-intrinsics.ll.bc create mode 100644 final/test/Bitcode/null-type.ll create mode 100644 final/test/Bitcode/null-type.ll.bc create mode 100644 final/test/Bitcode/sse2_loadl_pd.ll create mode 100644 final/test/Bitcode/sse2_loadl_pd.ll.bc create mode 100644 final/test/Bitcode/sse2_movl_dq.ll create mode 100644 final/test/Bitcode/sse2_movl_dq.ll.bc create mode 100644 final/test/Bitcode/sse2_movs_d.ll create mode 100644 final/test/Bitcode/sse2_movs_d.ll.bc create mode 100644 final/test/Bitcode/sse2_punpck_qdq.ll create mode 100644 final/test/Bitcode/sse2_punpck_qdq.ll.bc create mode 100644 final/test/Bitcode/sse2_shuf_pd.ll create mode 100644 final/test/Bitcode/sse2_shuf_pd.ll.bc create mode 100644 final/test/Bitcode/sse2_unpck_pd.ll create mode 100644 final/test/Bitcode/sse2_unpck_pd.ll.bc create mode 100644 final/test/Bitcode/sse41_pmulld.ll create mode 100644 final/test/Bitcode/sse41_pmulld.ll.bc create mode 100644 final/test/Bitcode/ssse3_palignr.ll create mode 100644 final/test/Bitcode/ssse3_palignr.ll.bc create mode 100644 final/test/BugPoint/crash-narrowfunctiontest.ll create mode 100644 final/test/BugPoint/dg.exp create mode 100644 final/test/BugPoint/metadata.ll create mode 100644 final/test/BugPoint/remove_arguments_test.ll create mode 100644 final/test/CMakeLists.txt create mode 100644 final/test/CodeGen/ARM/2006-11-10-CycleInDAG.ll create mode 100644 final/test/CodeGen/ARM/2007-01-19-InfiniteLoop.ll create mode 100644 final/test/CodeGen/ARM/2007-03-07-CombinerCrash.ll create mode 100644 final/test/CodeGen/ARM/2007-03-13-InstrSched.ll create mode 100644 final/test/CodeGen/ARM/2007-03-21-JoinIntervalsCrash.ll create mode 100644 final/test/CodeGen/ARM/2007-03-26-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2007-03-27-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2007-03-30-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2007-04-02-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2007-04-03-PEIBug.ll create mode 100644 final/test/CodeGen/ARM/2007-04-03-UndefinedSymbol.ll create mode 100644 final/test/CodeGen/ARM/2007-04-30-CombinerCrash.ll create mode 100644 final/test/CodeGen/ARM/2007-05-03-BadPostIndexedLd.ll create mode 100644 final/test/CodeGen/ARM/2007-05-07-jumptoentry.ll create mode 100644 final/test/CodeGen/ARM/2007-05-07-tailmerge-1.ll create mode 100644 final/test/CodeGen/ARM/2007-05-09-tailmerge-2.ll create mode 100644 final/test/CodeGen/ARM/2007-05-14-InlineAsmCstCrash.ll create mode 100644 final/test/CodeGen/ARM/2007-05-14-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2007-05-22-tailmerge-3.ll create mode 100644 final/test/CodeGen/ARM/2007-05-23-BadPreIndexedStore.ll create mode 100644 final/test/CodeGen/ARM/2007-05-31-RegScavengerInfiniteLoop.ll create mode 100644 final/test/CodeGen/ARM/2007-08-15-ReuseBug.ll create mode 100644 final/test/CodeGen/ARM/2008-02-04-LocalRegAllocBug.ll create mode 100644 final/test/CodeGen/ARM/2008-02-29-RegAllocLocal.ll create mode 100644 final/test/CodeGen/ARM/2008-03-05-SxtInRegBug.ll create mode 100644 final/test/CodeGen/ARM/2008-03-07-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2008-04-04-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2008-04-10-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2008-04-11-PHIofImpDef.ll create mode 100644 final/test/CodeGen/ARM/2008-05-19-LiveIntervalsBug.ll create mode 100644 final/test/CodeGen/ARM/2008-05-19-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2008-07-17-Fdiv.ll create mode 100644 final/test/CodeGen/ARM/2008-07-24-CodeGenPrepCrash.ll create mode 100644 final/test/CodeGen/ARM/2008-08-07-AsmPrintBug.ll create mode 100644 final/test/CodeGen/ARM/2008-09-14-CoalescerBug.ll create mode 100644 final/test/CodeGen/ARM/2008-09-17-CoalescerBug.ll create mode 100644 final/test/CodeGen/ARM/2008-11-18-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-02-16-SpillerBug.ll create mode 100644 final/test/CodeGen/ARM/2009-02-22-SoftenFloatVaArg.ll create mode 100644 final/test/CodeGen/ARM/2009-02-27-SpillerBug.ll create mode 100644 final/test/CodeGen/ARM/2009-03-07-SpillerBug.ll create mode 100644 final/test/CodeGen/ARM/2009-03-09-AddrModeBug.ll create mode 100644 final/test/CodeGen/ARM/2009-04-06-AsmModifier.ll create mode 100644 final/test/CodeGen/ARM/2009-04-08-AggregateAddr.ll create mode 100644 final/test/CodeGen/ARM/2009-04-08-FREM.ll create mode 100644 final/test/CodeGen/ARM/2009-04-08-FloatUndef.ll create mode 100644 final/test/CodeGen/ARM/2009-04-09-RegScavengerAsm.ll create mode 100644 final/test/CodeGen/ARM/2009-05-05-DAGCombineBug.ll create mode 100644 final/test/CodeGen/ARM/2009-05-07-RegAllocLocal.ll create mode 100644 final/test/CodeGen/ARM/2009-05-11-CodePlacementCrash.ll create mode 100644 final/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll create mode 100644 final/test/CodeGen/ARM/2009-06-02-ISelCrash.ll create mode 100644 final/test/CodeGen/ARM/2009-06-04-MissingLiveIn.ll create mode 100644 final/test/CodeGen/ARM/2009-06-12-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-06-15-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-06-19-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-06-22-CoalescerBug.ll create mode 100644 final/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-06-30-RegScavengerAssert2.ll create mode 100644 final/test/CodeGen/ARM/2009-06-30-RegScavengerAssert3.ll create mode 100644 final/test/CodeGen/ARM/2009-06-30-RegScavengerAssert4.ll create mode 100644 final/test/CodeGen/ARM/2009-06-30-RegScavengerAssert5.ll create mode 100644 final/test/CodeGen/ARM/2009-07-01-CommuteBug.ll create mode 100644 final/test/CodeGen/ARM/2009-07-09-asm-p-constraint.ll create mode 100644 final/test/CodeGen/ARM/2009-07-18-RewriterBug.ll create mode 100644 final/test/CodeGen/ARM/2009-07-22-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-07-22-SchedulerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-07-29-VFP3Registers.ll create mode 100644 final/test/CodeGen/ARM/2009-08-02-RegScavengerAssert-Neon.ll create mode 100644 final/test/CodeGen/ARM/2009-08-04-RegScavengerAssert-2.ll create mode 100644 final/test/CodeGen/ARM/2009-08-04-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-08-15-RegScavenger-EarlyClobber.ll create mode 100644 final/test/CodeGen/ARM/2009-08-15-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-08-21-PostRAKill.ll create mode 100644 final/test/CodeGen/ARM/2009-08-21-PostRAKill2.ll create mode 100644 final/test/CodeGen/ARM/2009-08-21-PostRAKill3.ll create mode 100644 final/test/CodeGen/ARM/2009-08-23-linkerprivate.ll create mode 100644 final/test/CodeGen/ARM/2009-08-26-ScalarToVector.ll create mode 100644 final/test/CodeGen/ARM/2009-08-27-ScalarToVector.ll create mode 100644 final/test/CodeGen/ARM/2009-08-29-ExtractEltf32.ll create mode 100644 final/test/CodeGen/ARM/2009-08-29-TooLongSplat.ll create mode 100644 final/test/CodeGen/ARM/2009-08-31-LSDA-Name.ll create mode 100644 final/test/CodeGen/ARM/2009-08-31-TwoRegShuffle.ll create mode 100644 final/test/CodeGen/ARM/2009-09-09-AllOnes.ll create mode 100644 final/test/CodeGen/ARM/2009-09-09-fpcmp-ole.ll create mode 100644 final/test/CodeGen/ARM/2009-09-10-postdec.ll create mode 100644 final/test/CodeGen/ARM/2009-09-13-InvalidSubreg.ll create mode 100644 final/test/CodeGen/ARM/2009-09-13-InvalidSuperReg.ll create mode 100644 final/test/CodeGen/ARM/2009-09-20-LiveIntervalsBug.ll create mode 100644 final/test/CodeGen/ARM/2009-09-21-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/ARM/2009-09-22-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/ARM/2009-09-23-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/ARM/2009-09-24-spill-align.ll create mode 100644 final/test/CodeGen/ARM/2009-09-27-CoalescerBug.ll create mode 100644 final/test/CodeGen/ARM/2009-09-28-LdStOptiBug.ll create mode 100644 final/test/CodeGen/ARM/2009-10-02-NEONSubregsBug.ll create mode 100644 final/test/CodeGen/ARM/2009-10-16-Scope.ll create mode 100644 final/test/CodeGen/ARM/2009-10-21-InvalidFNeg.ll create mode 100644 final/test/CodeGen/ARM/2009-10-27-double-align.ll create mode 100644 final/test/CodeGen/ARM/2009-10-30.ll create mode 100644 final/test/CodeGen/ARM/2009-11-01-NeonMoves.ll create mode 100644 final/test/CodeGen/ARM/2009-11-02-NegativeLane.ll create mode 100644 final/test/CodeGen/ARM/2009-11-07-SubRegAsmPrinting.ll create mode 100644 final/test/CodeGen/ARM/2009-11-13-CoalescerCrash.ll create mode 100644 final/test/CodeGen/ARM/2009-11-13-ScavengerAssert.ll create mode 100644 final/test/CodeGen/ARM/2009-11-13-ScavengerAssert2.ll create mode 100644 final/test/CodeGen/ARM/2009-11-13-VRRewriterCrash.ll create mode 100644 final/test/CodeGen/ARM/2009-11-30-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/ARM/2009-12-02-vtrn-undef.ll create mode 100644 final/test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll create mode 100644 final/test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll create mode 100644 final/test/CodeGen/ARM/2010-03-18-ldm-rtrn.ll create mode 100644 final/test/CodeGen/ARM/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/ARM/2010-04-09-NeonSelect.ll create mode 100644 final/test/CodeGen/ARM/2010-04-13-v2f64SplitArg.ll create mode 100644 final/test/CodeGen/ARM/2010-04-14-SplitVector.ll create mode 100644 final/test/CodeGen/ARM/2010-04-15-ScavengerDebugValue.ll create mode 100644 final/test/CodeGen/ARM/2010-05-14-IllegalType.ll create mode 100644 final/test/CodeGen/ARM/2010-05-17-FastAllocCrash.ll create mode 100644 final/test/CodeGen/ARM/2010-05-18-LocalAllocCrash.ll create mode 100644 final/test/CodeGen/ARM/2010-05-18-PostIndexBug.ll create mode 100644 final/test/CodeGen/ARM/2010-05-19-Shuffles.ll create mode 100644 final/test/CodeGen/ARM/2010-05-20-NEONSpillCrash.ll create mode 100644 final/test/CodeGen/ARM/2010-05-21-BuildVector.ll create mode 100644 final/test/CodeGen/ARM/2010-06-11-vmovdrr-bitcast.ll create mode 100644 final/test/CodeGen/ARM/2010-06-21-LdStMultipleBug.ll create mode 100755 final/test/CodeGen/ARM/2010-06-21-nondarwin-tc.ll create mode 100644 final/test/CodeGen/ARM/2010-06-25-Thumb2ITInvalidIterator.ll create mode 100644 final/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll create mode 100644 final/test/CodeGen/ARM/2010-06-29-SubregImpDefs.ll create mode 100644 final/test/CodeGen/ARM/2010-07-26-GlobalMerge.ll create mode 100644 final/test/CodeGen/ARM/2010-08-04-EHCrash.ll create mode 100644 final/test/CodeGen/ARM/2010-08-04-StackVariable.ll create mode 100644 final/test/CodeGen/ARM/2010-09-21-OptCmpBug.ll create mode 100644 final/test/CodeGen/ARM/2010-09-29-mc-asm-header-test.ll create mode 100644 final/test/CodeGen/ARM/2010-10-19-mc-elf-objheader.ll create mode 100644 final/test/CodeGen/ARM/2010-10-25-ifcvt-ldm.ll create mode 100644 final/test/CodeGen/ARM/2010-11-15-SpillEarlyClobber.ll create mode 100644 final/test/CodeGen/ARM/2010-11-29-PrologueBug.ll create mode 100644 final/test/CodeGen/ARM/2010-11-30-reloc-movt.ll create mode 100644 final/test/CodeGen/ARM/2010-12-07-PEIBug.ll create mode 100644 final/test/CodeGen/ARM/2010-12-08-tpsoft.ll create mode 100644 final/test/CodeGen/ARM/2010-12-13-reloc-pic.ll create mode 100644 final/test/CodeGen/ARM/2010-12-15-elf-lcomm.ll create mode 100644 final/test/CodeGen/ARM/2010-12-17-LocalStackSlotCrash.ll create mode 100644 final/test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll create mode 100644 final/test/CodeGen/ARM/2011-02-04-AntidepMultidef.ll create mode 100644 final/test/CodeGen/ARM/2011-02-07-AntidepClobber.ll create mode 100644 final/test/CodeGen/ARM/addrmode.ll create mode 100644 final/test/CodeGen/ARM/aliases.ll create mode 100644 final/test/CodeGen/ARM/align.ll create mode 100644 final/test/CodeGen/ARM/alloca.ll create mode 100644 final/test/CodeGen/ARM/argaddr.ll create mode 100644 final/test/CodeGen/ARM/arguments-nosplit-double.ll create mode 100644 final/test/CodeGen/ARM/arguments-nosplit-i64.ll create mode 100644 final/test/CodeGen/ARM/arguments.ll create mode 100644 final/test/CodeGen/ARM/arguments2.ll create mode 100644 final/test/CodeGen/ARM/arguments3.ll create mode 100644 final/test/CodeGen/ARM/arguments4.ll create mode 100644 final/test/CodeGen/ARM/arguments5.ll create mode 100644 final/test/CodeGen/ARM/arguments6.ll create mode 100644 final/test/CodeGen/ARM/arguments7.ll create mode 100644 final/test/CodeGen/ARM/arguments8.ll create mode 100644 final/test/CodeGen/ARM/arguments_f64_backfill.ll create mode 100644 final/test/CodeGen/ARM/arm-and-tst-peephole.ll create mode 100644 final/test/CodeGen/ARM/arm-asm.ll create mode 100644 final/test/CodeGen/ARM/arm-frameaddr.ll create mode 100644 final/test/CodeGen/ARM/arm-negative-stride.ll create mode 100644 final/test/CodeGen/ARM/arm-returnaddr.ll create mode 100644 final/test/CodeGen/ARM/armv4.ll create mode 100644 final/test/CodeGen/ARM/atomic-cmp.ll create mode 100644 final/test/CodeGen/ARM/available_externally.ll create mode 100644 final/test/CodeGen/ARM/bfc.ll create mode 100644 final/test/CodeGen/ARM/bfi.ll create mode 100644 final/test/CodeGen/ARM/bfx.ll create mode 100644 final/test/CodeGen/ARM/bic.ll create mode 100644 final/test/CodeGen/ARM/bits.ll create mode 100644 final/test/CodeGen/ARM/bswap-inline-asm.ll create mode 100644 final/test/CodeGen/ARM/bx_fold.ll create mode 100644 final/test/CodeGen/ARM/call-tc.ll create mode 100644 final/test/CodeGen/ARM/call.ll create mode 100644 final/test/CodeGen/ARM/call_nolink.ll create mode 100644 final/test/CodeGen/ARM/carry.ll create mode 100644 final/test/CodeGen/ARM/clz.ll create mode 100644 final/test/CodeGen/ARM/code-placement.ll create mode 100644 final/test/CodeGen/ARM/compare-call.ll create mode 100644 final/test/CodeGen/ARM/constants.ll create mode 100644 final/test/CodeGen/ARM/crash-O0.ll create mode 100644 final/test/CodeGen/ARM/crash.ll create mode 100644 final/test/CodeGen/ARM/cse-libcalls.ll create mode 100644 final/test/CodeGen/ARM/ctors_dtors.ll create mode 100644 final/test/CodeGen/ARM/ctz.ll create mode 100644 final/test/CodeGen/ARM/dg.exp create mode 100644 final/test/CodeGen/ARM/div.ll create mode 100644 final/test/CodeGen/ARM/dyn-stackalloc.ll create mode 100644 final/test/CodeGen/ARM/extloadi1.ll create mode 100644 final/test/CodeGen/ARM/fabss.ll create mode 100644 final/test/CodeGen/ARM/fadds.ll create mode 100644 final/test/CodeGen/ARM/fast-isel-crash.ll create mode 100644 final/test/CodeGen/ARM/fast-isel-static.ll create mode 100644 final/test/CodeGen/ARM/fast-isel.ll create mode 100644 final/test/CodeGen/ARM/fcopysign.ll create mode 100644 final/test/CodeGen/ARM/fdivs.ll create mode 100644 final/test/CodeGen/ARM/fixunsdfdi.ll create mode 100644 final/test/CodeGen/ARM/flag-crash.ll create mode 100644 final/test/CodeGen/ARM/fmacs.ll create mode 100644 final/test/CodeGen/ARM/fmdrr-fmrrd.ll create mode 100644 final/test/CodeGen/ARM/fmscs.ll create mode 100644 final/test/CodeGen/ARM/fmuls.ll create mode 100644 final/test/CodeGen/ARM/fnegs.ll create mode 100644 final/test/CodeGen/ARM/fnmacs.ll create mode 100644 final/test/CodeGen/ARM/fnmscs.ll create mode 100644 final/test/CodeGen/ARM/fnmul.ll create mode 100644 final/test/CodeGen/ARM/fnmuls.ll create mode 100644 final/test/CodeGen/ARM/formal.ll create mode 100644 final/test/CodeGen/ARM/fp.ll create mode 100644 final/test/CodeGen/ARM/fp16.ll create mode 100644 final/test/CodeGen/ARM/fp_convert.ll create mode 100644 final/test/CodeGen/ARM/fparith.ll create mode 100644 final/test/CodeGen/ARM/fpcmp-opt.ll create mode 100644 final/test/CodeGen/ARM/fpcmp.ll create mode 100644 final/test/CodeGen/ARM/fpcmp_ueq.ll create mode 100644 final/test/CodeGen/ARM/fpconsts.ll create mode 100644 final/test/CodeGen/ARM/fpconv.ll create mode 100644 final/test/CodeGen/ARM/fpmem.ll create mode 100644 final/test/CodeGen/ARM/fpow.ll create mode 100644 final/test/CodeGen/ARM/fpowi.ll create mode 100644 final/test/CodeGen/ARM/fptoint.ll create mode 100644 final/test/CodeGen/ARM/fsubs.ll create mode 100644 final/test/CodeGen/ARM/global-merge.ll create mode 100644 final/test/CodeGen/ARM/globals.ll create mode 100644 final/test/CodeGen/ARM/hardfloat_neon.ll create mode 100644 final/test/CodeGen/ARM/hello.ll create mode 100644 final/test/CodeGen/ARM/hidden-vis-2.ll create mode 100644 final/test/CodeGen/ARM/hidden-vis-3.ll create mode 100644 final/test/CodeGen/ARM/hidden-vis.ll create mode 100644 final/test/CodeGen/ARM/iabs.ll create mode 100644 final/test/CodeGen/ARM/ifcvt1.ll create mode 100644 final/test/CodeGen/ARM/ifcvt10.ll create mode 100644 final/test/CodeGen/ARM/ifcvt11.ll create mode 100644 final/test/CodeGen/ARM/ifcvt2.ll create mode 100644 final/test/CodeGen/ARM/ifcvt3.ll create mode 100644 final/test/CodeGen/ARM/ifcvt4.ll create mode 100644 final/test/CodeGen/ARM/ifcvt5.ll create mode 100644 final/test/CodeGen/ARM/ifcvt6.ll create mode 100644 final/test/CodeGen/ARM/ifcvt7.ll create mode 100644 final/test/CodeGen/ARM/ifcvt8.ll create mode 100644 final/test/CodeGen/ARM/ifcvt9.ll create mode 100644 final/test/CodeGen/ARM/illegal-vector-bitcast.ll create mode 100644 final/test/CodeGen/ARM/imm.ll create mode 100644 final/test/CodeGen/ARM/indirectbr.ll create mode 100644 final/test/CodeGen/ARM/inlineasm-imm-arm.ll create mode 100644 final/test/CodeGen/ARM/inlineasm.ll create mode 100644 final/test/CodeGen/ARM/inlineasm2.ll create mode 100644 final/test/CodeGen/ARM/inlineasm3.ll create mode 100644 final/test/CodeGen/ARM/insn-sched1.ll create mode 100644 final/test/CodeGen/ARM/ispositive.ll create mode 100644 final/test/CodeGen/ARM/large-stack.ll create mode 100644 final/test/CodeGen/ARM/ldm.ll create mode 100644 final/test/CodeGen/ARM/ldr.ll create mode 100644 final/test/CodeGen/ARM/ldr_ext.ll create mode 100644 final/test/CodeGen/ARM/ldr_frame.ll create mode 100644 final/test/CodeGen/ARM/ldr_post.ll create mode 100644 final/test/CodeGen/ARM/ldr_pre.ll create mode 100644 final/test/CodeGen/ARM/ldrd.ll create mode 100644 final/test/CodeGen/ARM/ldst-f32-2-i32.ll create mode 100644 final/test/CodeGen/ARM/load-global.ll create mode 100644 final/test/CodeGen/ARM/load.ll create mode 100644 final/test/CodeGen/ARM/long-setcc.ll create mode 100644 final/test/CodeGen/ARM/long.ll create mode 100644 final/test/CodeGen/ARM/long_shift.ll create mode 100644 final/test/CodeGen/ARM/lsr-code-insertion.ll create mode 100644 final/test/CodeGen/ARM/lsr-on-unrolled-loops.ll create mode 100644 final/test/CodeGen/ARM/lsr-scale-addr-mode.ll create mode 100644 final/test/CodeGen/ARM/machine-cse-cmp.ll create mode 100644 final/test/CodeGen/ARM/machine-licm.ll create mode 100644 final/test/CodeGen/ARM/mem.ll create mode 100644 final/test/CodeGen/ARM/memcpy-inline.ll create mode 100644 final/test/CodeGen/ARM/memfunc.ll create mode 100644 final/test/CodeGen/ARM/mls.ll create mode 100644 final/test/CodeGen/ARM/movt-movw-global.ll create mode 100644 final/test/CodeGen/ARM/movt.ll create mode 100644 final/test/CodeGen/ARM/mul.ll create mode 100644 final/test/CodeGen/ARM/mul_const.ll create mode 100644 final/test/CodeGen/ARM/mulhi.ll create mode 100644 final/test/CodeGen/ARM/mult-alt-generic-arm.ll create mode 100644 final/test/CodeGen/ARM/mvn.ll create mode 100644 final/test/CodeGen/ARM/neon_arith1.ll create mode 100644 final/test/CodeGen/ARM/neon_div.ll create mode 100644 final/test/CodeGen/ARM/neon_ld1.ll create mode 100644 final/test/CodeGen/ARM/neon_ld2.ll create mode 100644 final/test/CodeGen/ARM/neon_minmax.ll create mode 100644 final/test/CodeGen/ARM/neon_shift.ll create mode 100644 final/test/CodeGen/ARM/pack.ll create mode 100644 final/test/CodeGen/ARM/phi.ll create mode 100644 final/test/CodeGen/ARM/pr3502.ll create mode 100644 final/test/CodeGen/ARM/prefetch.ll create mode 100644 final/test/CodeGen/ARM/private.ll create mode 100644 final/test/CodeGen/ARM/reg_sequence.ll create mode 100644 final/test/CodeGen/ARM/ret0.ll create mode 100644 final/test/CodeGen/ARM/ret_arg1.ll create mode 100644 final/test/CodeGen/ARM/ret_arg2.ll create mode 100644 final/test/CodeGen/ARM/ret_arg3.ll create mode 100644 final/test/CodeGen/ARM/ret_arg4.ll create mode 100644 final/test/CodeGen/ARM/ret_arg5.ll create mode 100644 final/test/CodeGen/ARM/ret_f32_arg2.ll create mode 100644 final/test/CodeGen/ARM/ret_f32_arg5.ll create mode 100644 final/test/CodeGen/ARM/ret_f64_arg2.ll create mode 100644 final/test/CodeGen/ARM/ret_f64_arg_reg_split.ll create mode 100644 final/test/CodeGen/ARM/ret_f64_arg_split.ll create mode 100644 final/test/CodeGen/ARM/ret_f64_arg_stack.ll create mode 100644 final/test/CodeGen/ARM/ret_i128_arg2.ll create mode 100644 final/test/CodeGen/ARM/ret_i64_arg2.ll create mode 100644 final/test/CodeGen/ARM/ret_i64_arg3.ll create mode 100644 final/test/CodeGen/ARM/ret_i64_arg_split.ll create mode 100644 final/test/CodeGen/ARM/ret_void.ll create mode 100644 final/test/CodeGen/ARM/rev.ll create mode 100644 final/test/CodeGen/ARM/sbfx.ll create mode 100644 final/test/CodeGen/ARM/section.ll create mode 100644 final/test/CodeGen/ARM/select-imm.ll create mode 100644 final/test/CodeGen/ARM/select.ll create mode 100644 final/test/CodeGen/ARM/select_xform.ll create mode 100644 final/test/CodeGen/ARM/shifter_operand.ll create mode 100644 final/test/CodeGen/ARM/smul.ll create mode 100644 final/test/CodeGen/ARM/spill-q.ll create mode 100644 final/test/CodeGen/ARM/stack-frame.ll create mode 100644 final/test/CodeGen/ARM/stm.ll create mode 100644 final/test/CodeGen/ARM/str_post.ll create mode 100644 final/test/CodeGen/ARM/str_pre-2.ll create mode 100644 final/test/CodeGen/ARM/str_pre.ll create mode 100644 final/test/CodeGen/ARM/str_trunc.ll create mode 100644 final/test/CodeGen/ARM/sub.ll create mode 100644 final/test/CodeGen/ARM/sxt_rot.ll create mode 100644 final/test/CodeGen/ARM/t2-imm.ll create mode 100644 final/test/CodeGen/ARM/tail-opts.ll create mode 100644 final/test/CodeGen/ARM/thread_pointer.ll create mode 100644 final/test/CodeGen/ARM/thumb1-varalloc.ll create mode 100644 final/test/CodeGen/ARM/tls1.ll create mode 100644 final/test/CodeGen/ARM/tls2.ll create mode 100644 final/test/CodeGen/ARM/tls3.ll create mode 100644 final/test/CodeGen/ARM/trap.ll create mode 100644 final/test/CodeGen/ARM/trunc_ldr.ll create mode 100644 final/test/CodeGen/ARM/truncstore-dag-combine.ll create mode 100644 final/test/CodeGen/ARM/tst_teq.ll create mode 100644 final/test/CodeGen/ARM/uint64tof64.ll create mode 100644 final/test/CodeGen/ARM/umulo-32.ll create mode 100644 final/test/CodeGen/ARM/unaligned_load_store.ll create mode 100644 final/test/CodeGen/ARM/unord.ll create mode 100644 final/test/CodeGen/ARM/uxt_rot.ll create mode 100644 final/test/CodeGen/ARM/uxtb.ll create mode 100644 final/test/CodeGen/ARM/va_arg.ll create mode 100644 final/test/CodeGen/ARM/vaba.ll create mode 100644 final/test/CodeGen/ARM/vabd.ll create mode 100644 final/test/CodeGen/ARM/vabs.ll create mode 100644 final/test/CodeGen/ARM/vadd.ll create mode 100644 final/test/CodeGen/ARM/vargs.ll create mode 100644 final/test/CodeGen/ARM/vargs_align.ll create mode 100644 final/test/CodeGen/ARM/vbits.ll create mode 100644 final/test/CodeGen/ARM/vbsl.ll create mode 100644 final/test/CodeGen/ARM/vceq.ll create mode 100644 final/test/CodeGen/ARM/vcge.ll create mode 100644 final/test/CodeGen/ARM/vcgt.ll create mode 100644 final/test/CodeGen/ARM/vcnt.ll create mode 100644 final/test/CodeGen/ARM/vcombine.ll create mode 100644 final/test/CodeGen/ARM/vcvt.ll create mode 100644 final/test/CodeGen/ARM/vdup.ll create mode 100644 final/test/CodeGen/ARM/vector-DAGCombine.ll create mode 100644 final/test/CodeGen/ARM/vext.ll create mode 100644 final/test/CodeGen/ARM/vfcmp.ll create mode 100644 final/test/CodeGen/ARM/vfp.ll create mode 100644 final/test/CodeGen/ARM/vget_lane.ll create mode 100644 final/test/CodeGen/ARM/vhadd.ll create mode 100644 final/test/CodeGen/ARM/vhsub.ll create mode 100644 final/test/CodeGen/ARM/vicmp.ll create mode 100644 final/test/CodeGen/ARM/vld1.ll create mode 100644 final/test/CodeGen/ARM/vld2.ll create mode 100644 final/test/CodeGen/ARM/vld3.ll create mode 100644 final/test/CodeGen/ARM/vld4.ll create mode 100644 final/test/CodeGen/ARM/vlddup.ll create mode 100644 final/test/CodeGen/ARM/vldlane.ll create mode 100644 final/test/CodeGen/ARM/vminmax.ll create mode 100644 final/test/CodeGen/ARM/vmla.ll create mode 100644 final/test/CodeGen/ARM/vmls.ll create mode 100644 final/test/CodeGen/ARM/vmov.ll create mode 100644 final/test/CodeGen/ARM/vmul.ll create mode 100644 final/test/CodeGen/ARM/vneg.ll create mode 100644 final/test/CodeGen/ARM/vpadal.ll create mode 100644 final/test/CodeGen/ARM/vpadd.ll create mode 100644 final/test/CodeGen/ARM/vpminmax.ll create mode 100644 final/test/CodeGen/ARM/vqadd.ll create mode 100644 final/test/CodeGen/ARM/vqdmul.ll create mode 100644 final/test/CodeGen/ARM/vqshl.ll create mode 100644 final/test/CodeGen/ARM/vqshrn.ll create mode 100644 final/test/CodeGen/ARM/vqsub.ll create mode 100644 final/test/CodeGen/ARM/vrec.ll create mode 100644 final/test/CodeGen/ARM/vrev.ll create mode 100644 final/test/CodeGen/ARM/vshift.ll create mode 100644 final/test/CodeGen/ARM/vshiftins.ll create mode 100644 final/test/CodeGen/ARM/vshl.ll create mode 100644 final/test/CodeGen/ARM/vshll.ll create mode 100644 final/test/CodeGen/ARM/vshrn.ll create mode 100644 final/test/CodeGen/ARM/vsra.ll create mode 100644 final/test/CodeGen/ARM/vst1.ll create mode 100644 final/test/CodeGen/ARM/vst2.ll create mode 100644 final/test/CodeGen/ARM/vst3.ll create mode 100644 final/test/CodeGen/ARM/vst4.ll create mode 100644 final/test/CodeGen/ARM/vstlane.ll create mode 100644 final/test/CodeGen/ARM/vsub.ll create mode 100644 final/test/CodeGen/ARM/vtbl.ll create mode 100644 final/test/CodeGen/ARM/vtrn.ll create mode 100644 final/test/CodeGen/ARM/vuzp.ll create mode 100644 final/test/CodeGen/ARM/vzip.ll create mode 100644 final/test/CodeGen/ARM/weak.ll create mode 100644 final/test/CodeGen/ARM/weak2.ll create mode 100644 final/test/CodeGen/Alpha/2005-07-12-TwoMallocCalls.ll create mode 100644 final/test/CodeGen/Alpha/2005-12-12-MissingFCMov.ll create mode 100644 final/test/CodeGen/Alpha/2006-01-18-MissedGlobal.ll create mode 100644 final/test/CodeGen/Alpha/2006-01-26-VaargBreak.ll create mode 100644 final/test/CodeGen/Alpha/2006-04-04-zextload.ll create mode 100644 final/test/CodeGen/Alpha/2006-07-03-ASMFormalLowering.ll create mode 100644 final/test/CodeGen/Alpha/2006-11-01-vastart.ll create mode 100644 final/test/CodeGen/Alpha/2007-11-27-mulneg3.ll create mode 100644 final/test/CodeGen/Alpha/2008-11-10-smul_lohi.ll create mode 100644 final/test/CodeGen/Alpha/2008-11-12-Add128.ll create mode 100644 final/test/CodeGen/Alpha/2009-07-16-PromoteFloatCompare.ll create mode 100644 final/test/CodeGen/Alpha/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/Alpha/2010-08-01-mulreduce64.ll create mode 100644 final/test/CodeGen/Alpha/add.ll create mode 100644 final/test/CodeGen/Alpha/add128.ll create mode 100644 final/test/CodeGen/Alpha/bic.ll create mode 100644 final/test/CodeGen/Alpha/bsr.ll create mode 100644 final/test/CodeGen/Alpha/call_adj.ll create mode 100644 final/test/CodeGen/Alpha/cmov.ll create mode 100644 final/test/CodeGen/Alpha/cmpbge.ll create mode 100644 final/test/CodeGen/Alpha/ctlz.ll create mode 100644 final/test/CodeGen/Alpha/ctlz_e.ll create mode 100644 final/test/CodeGen/Alpha/ctpop.ll create mode 100644 final/test/CodeGen/Alpha/dg.exp create mode 100644 final/test/CodeGen/Alpha/eqv.ll create mode 100644 final/test/CodeGen/Alpha/i32_sub_1.ll create mode 100644 final/test/CodeGen/Alpha/illegal-element-type.ll create mode 100644 final/test/CodeGen/Alpha/jmp_table.ll create mode 100644 final/test/CodeGen/Alpha/mb.ll create mode 100644 final/test/CodeGen/Alpha/mul128.ll create mode 100644 final/test/CodeGen/Alpha/mul5.ll create mode 100644 final/test/CodeGen/Alpha/neg1.ll create mode 100644 final/test/CodeGen/Alpha/not.ll create mode 100644 final/test/CodeGen/Alpha/ornot.ll create mode 100644 final/test/CodeGen/Alpha/private.ll create mode 100644 final/test/CodeGen/Alpha/rpcc.ll create mode 100644 final/test/CodeGen/Alpha/srl_and.ll create mode 100644 final/test/CodeGen/Alpha/sub128.ll create mode 100644 final/test/CodeGen/Alpha/weak.ll create mode 100644 final/test/CodeGen/Alpha/wmb.ll create mode 100644 final/test/CodeGen/Alpha/zapnot.ll create mode 100644 final/test/CodeGen/Alpha/zapnot2.ll create mode 100644 final/test/CodeGen/Alpha/zapnot3.ll create mode 100644 final/test/CodeGen/Alpha/zapnot4.ll create mode 100644 final/test/CodeGen/Blackfin/2009-08-04-LowerExtract-Live.ll create mode 100644 final/test/CodeGen/Blackfin/2009-08-11-RegScavenger-CSR.ll create mode 100644 final/test/CodeGen/Blackfin/2009-08-15-LiveIn-SubReg.ll create mode 100644 final/test/CodeGen/Blackfin/2009-08-15-MissingDead.ll create mode 100644 final/test/CodeGen/Blackfin/2009-08-15-SetCC-Undef.ll create mode 100644 final/test/CodeGen/Blackfin/add-overflow.ll create mode 100644 final/test/CodeGen/Blackfin/add.ll create mode 100644 final/test/CodeGen/Blackfin/addsub-i128.ll create mode 100644 final/test/CodeGen/Blackfin/basic-i1.ll create mode 100644 final/test/CodeGen/Blackfin/basic-i16.ll create mode 100644 final/test/CodeGen/Blackfin/basic-i32.ll create mode 100644 final/test/CodeGen/Blackfin/basic-i64.ll create mode 100644 final/test/CodeGen/Blackfin/basic-i8.ll create mode 100644 final/test/CodeGen/Blackfin/basictest.ll create mode 100644 final/test/CodeGen/Blackfin/burg.ll create mode 100644 final/test/CodeGen/Blackfin/cmp-small-imm.ll create mode 100644 final/test/CodeGen/Blackfin/cmp64.ll create mode 100644 final/test/CodeGen/Blackfin/ct32.ll create mode 100644 final/test/CodeGen/Blackfin/ct64.ll create mode 100644 final/test/CodeGen/Blackfin/ctlz16.ll create mode 100644 final/test/CodeGen/Blackfin/ctlz64.ll create mode 100644 final/test/CodeGen/Blackfin/ctpop16.ll create mode 100644 final/test/CodeGen/Blackfin/cttz16.ll create mode 100644 final/test/CodeGen/Blackfin/cycles.ll create mode 100644 final/test/CodeGen/Blackfin/dg.exp create mode 100644 final/test/CodeGen/Blackfin/double-cast.ll create mode 100644 final/test/CodeGen/Blackfin/frameindex.ll create mode 100644 final/test/CodeGen/Blackfin/i17mem.ll create mode 100644 final/test/CodeGen/Blackfin/i1mem.ll create mode 100644 final/test/CodeGen/Blackfin/i1ops.ll create mode 100644 final/test/CodeGen/Blackfin/i216mem.ll create mode 100644 final/test/CodeGen/Blackfin/i248mem.ll create mode 100644 final/test/CodeGen/Blackfin/i256mem.ll create mode 100644 final/test/CodeGen/Blackfin/i256param.ll create mode 100644 final/test/CodeGen/Blackfin/i56param.ll create mode 100644 final/test/CodeGen/Blackfin/i8mem.ll create mode 100644 final/test/CodeGen/Blackfin/inline-asm.ll create mode 100644 final/test/CodeGen/Blackfin/int-setcc.ll create mode 100644 final/test/CodeGen/Blackfin/invalid-apint.ll create mode 100644 final/test/CodeGen/Blackfin/jumptable.ll create mode 100644 final/test/CodeGen/Blackfin/large-switch.ll create mode 100644 final/test/CodeGen/Blackfin/load-i16.ll create mode 100644 final/test/CodeGen/Blackfin/logic-i16.ll create mode 100644 final/test/CodeGen/Blackfin/many-args.ll create mode 100644 final/test/CodeGen/Blackfin/mulhu.ll create mode 100644 final/test/CodeGen/Blackfin/printf.ll create mode 100644 final/test/CodeGen/Blackfin/printf2.ll create mode 100644 final/test/CodeGen/Blackfin/promote-logic.ll create mode 100644 final/test/CodeGen/Blackfin/promote-setcc.ll create mode 100644 final/test/CodeGen/Blackfin/sdiv.ll create mode 100644 final/test/CodeGen/Blackfin/simple-select.ll create mode 100644 final/test/CodeGen/Blackfin/switch.ll create mode 100644 final/test/CodeGen/Blackfin/switch2.ll create mode 100644 final/test/CodeGen/Blackfin/sync-intr.ll create mode 100644 final/test/CodeGen/CBackend/2002-05-16-NameCollide.ll create mode 100644 final/test/CodeGen/CBackend/2002-05-21-MissingReturn.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-19-ConstPointerRef.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-19-ConstantExpr.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-19-DataPointer.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-19-FunctionPointer.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-19-HardConstantExpr.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-20-RecursiveTypes.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-20-UnnamedArgument.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-26-IndirectCallTest.ll create mode 100644 final/test/CodeGen/CBackend/2002-08-30-StructureOrderingTest.ll create mode 100644 final/test/CodeGen/CBackend/2002-09-20-ArrayTypeFailure.ll create mode 100644 final/test/CodeGen/CBackend/2002-09-20-VarArgPrototypes.ll create mode 100644 final/test/CodeGen/CBackend/2002-10-15-OpaqueTypeProblem.ll create mode 100644 final/test/CodeGen/CBackend/2002-10-16-External.ll create mode 100644 final/test/CodeGen/CBackend/2002-10-30-FunctionPointerAlloca.ll create mode 100644 final/test/CodeGen/CBackend/2002-11-06-PrintEscaped.ll create mode 100644 final/test/CodeGen/CBackend/2003-05-12-IntegerSizeWarning.ll create mode 100644 final/test/CodeGen/CBackend/2003-05-13-VarArgFunction.ll create mode 100644 final/test/CodeGen/CBackend/2003-05-31-MissingStructName.ll create mode 100644 final/test/CodeGen/CBackend/2003-06-01-NullPointerType.ll create mode 100644 final/test/CodeGen/CBackend/2003-06-11-HexConstant.ll create mode 100644 final/test/CodeGen/CBackend/2003-06-11-LiteralStringProblem.ll create mode 100644 final/test/CodeGen/CBackend/2003-06-28-InvokeSupport.ll create mode 100644 final/test/CodeGen/CBackend/2003-06-28-LinkOnceGlobalVars.ll create mode 100644 final/test/CodeGen/CBackend/2003-10-12-NANGlobalInits.ll create mode 100644 final/test/CodeGen/CBackend/2003-10-23-UnusedType.ll create mode 100644 final/test/CodeGen/CBackend/2003-10-28-CastToPtrToStruct.ll create mode 100644 final/test/CodeGen/CBackend/2003-11-21-ConstantShiftExpr.ll create mode 100644 final/test/CodeGen/CBackend/2004-02-13-FrameReturnAddress.ll create mode 100644 final/test/CodeGen/CBackend/2004-02-15-PreexistingExternals.ll create mode 100644 final/test/CodeGen/CBackend/2004-02-26-FPNotPrintableConstants.ll create mode 100644 final/test/CodeGen/CBackend/2004-02-26-LinkOnceFunctions.ll create mode 100644 final/test/CodeGen/CBackend/2004-08-09-va-end-null.ll create mode 100644 final/test/CodeGen/CBackend/2004-11-13-FunctionPointerCast.ll create mode 100644 final/test/CodeGen/CBackend/2004-12-03-ExternStatics.ll create mode 100644 final/test/CodeGen/CBackend/2004-12-28-LogicalConstantExprs.ll create mode 100644 final/test/CodeGen/CBackend/2005-02-14-VolatileOperations.ll create mode 100644 final/test/CodeGen/CBackend/2005-03-08-RecursiveTypeCrash.ll create mode 100644 final/test/CodeGen/CBackend/2005-07-14-NegationToMinusMinus.ll create mode 100644 final/test/CodeGen/CBackend/2005-08-23-Fmod.ll create mode 100644 final/test/CodeGen/CBackend/2005-09-27-VolatileFuncPtr.ll create mode 100644 final/test/CodeGen/CBackend/2006-12-11-Float-Bitcast.ll create mode 100644 final/test/CodeGen/CBackend/2007-01-08-ParamAttr-ICmp.ll create mode 100644 final/test/CodeGen/CBackend/2007-01-15-NamedArrayType.ll create mode 100644 final/test/CodeGen/CBackend/2007-01-17-StackSaveNRestore.ll create mode 100644 final/test/CodeGen/CBackend/2007-02-05-memset.ll create mode 100644 final/test/CodeGen/CBackend/2007-02-23-NameConflicts.ll create mode 100644 final/test/CodeGen/CBackend/2007-07-11-PackedStruct.ll create mode 100644 final/test/CodeGen/CBackend/2008-02-01-UnalignedLoadStore.ll create mode 100644 final/test/CodeGen/CBackend/2008-05-21-MRV-InlineAsm.ll create mode 100644 final/test/CodeGen/CBackend/2008-05-31-BoolOverflow.ll create mode 100644 final/test/CodeGen/CBackend/2008-06-04-IndirectMem.ll create mode 100644 final/test/CodeGen/CBackend/2008-10-21-PPCLongDoubleConstant.ll create mode 100644 final/test/CodeGen/CBackend/dg.exp create mode 100644 final/test/CodeGen/CBackend/fneg.ll create mode 100644 final/test/CodeGen/CBackend/pr2408.ll create mode 100644 final/test/CodeGen/CBackend/vectors.ll create mode 100644 final/test/CodeGen/CPP/2007-06-16-Funcname.ll create mode 100644 final/test/CodeGen/CPP/2009-05-01-Long-Double.ll create mode 100644 final/test/CodeGen/CPP/2009-05-04-CondBr.ll create mode 100644 final/test/CodeGen/CPP/dg.exp create mode 100644 final/test/CodeGen/CPP/llvm2cpp.ll create mode 100644 final/test/CodeGen/CellSPU/2009-01-01-BrCond.ll create mode 100644 final/test/CodeGen/CellSPU/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/CellSPU/and_ops.ll create mode 100644 final/test/CodeGen/CellSPU/arg_ret.ll create mode 100644 final/test/CodeGen/CellSPU/bigstack.ll create mode 100644 final/test/CodeGen/CellSPU/bss.ll create mode 100644 final/test/CodeGen/CellSPU/call.ll create mode 100644 final/test/CodeGen/CellSPU/call_indirect.ll create mode 100644 final/test/CodeGen/CellSPU/crash.ll create mode 100644 final/test/CodeGen/CellSPU/ctpop.ll create mode 100644 final/test/CodeGen/CellSPU/dg.exp create mode 100644 final/test/CodeGen/CellSPU/div_ops.ll create mode 100644 final/test/CodeGen/CellSPU/dp_farith.ll create mode 100644 final/test/CodeGen/CellSPU/eqv.ll create mode 100644 final/test/CodeGen/CellSPU/extract_elt.ll create mode 100644 final/test/CodeGen/CellSPU/fcmp32.ll create mode 100644 final/test/CodeGen/CellSPU/fcmp64.ll create mode 100644 final/test/CodeGen/CellSPU/fdiv.ll create mode 100644 final/test/CodeGen/CellSPU/fneg-fabs.ll create mode 100644 final/test/CodeGen/CellSPU/i64ops.ll create mode 100644 final/test/CodeGen/CellSPU/i8ops.ll create mode 100644 final/test/CodeGen/CellSPU/icmp16.ll create mode 100644 final/test/CodeGen/CellSPU/icmp32.ll create mode 100644 final/test/CodeGen/CellSPU/icmp64.ll create mode 100644 final/test/CodeGen/CellSPU/icmp8.ll create mode 100644 final/test/CodeGen/CellSPU/immed16.ll create mode 100644 final/test/CodeGen/CellSPU/immed32.ll create mode 100644 final/test/CodeGen/CellSPU/immed64.ll create mode 100644 final/test/CodeGen/CellSPU/int2fp.ll create mode 100644 final/test/CodeGen/CellSPU/intrinsics_branch.ll create mode 100644 final/test/CodeGen/CellSPU/intrinsics_float.ll create mode 100644 final/test/CodeGen/CellSPU/intrinsics_logical.ll create mode 100644 final/test/CodeGen/CellSPU/jumptable.ll create mode 100644 final/test/CodeGen/CellSPU/loads.ll create mode 100644 final/test/CodeGen/CellSPU/mul-with-overflow.ll create mode 100644 final/test/CodeGen/CellSPU/mul_ops.ll create mode 100644 final/test/CodeGen/CellSPU/nand.ll create mode 100644 final/test/CodeGen/CellSPU/or_ops.ll create mode 100644 final/test/CodeGen/CellSPU/private.ll create mode 100644 final/test/CodeGen/CellSPU/rotate_ops.ll create mode 100644 final/test/CodeGen/CellSPU/select_bits.ll create mode 100644 final/test/CodeGen/CellSPU/sext128.ll create mode 100644 final/test/CodeGen/CellSPU/shift_ops.ll create mode 100644 final/test/CodeGen/CellSPU/shuffles.ll create mode 100644 final/test/CodeGen/CellSPU/sp_farith.ll create mode 100644 final/test/CodeGen/CellSPU/stores.ll create mode 100644 final/test/CodeGen/CellSPU/storestruct.ll create mode 100644 final/test/CodeGen/CellSPU/struct_1.ll create mode 100644 final/test/CodeGen/CellSPU/sub_ops.ll create mode 100644 final/test/CodeGen/CellSPU/trunc.ll create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/README.txt create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/i32operations.c create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/i64operations.c create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/i64operations.h create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/lit.local.cfg create mode 100644 final/test/CodeGen/CellSPU/useful-harnesses/vecoperations.c create mode 100644 final/test/CodeGen/CellSPU/v2f32.ll create mode 100644 final/test/CodeGen/CellSPU/v2i32.ll create mode 100644 final/test/CodeGen/CellSPU/vec_const.ll create mode 100644 final/test/CodeGen/CellSPU/vecinsert.ll create mode 100644 final/test/CodeGen/Generic/2002-04-14-UnexpectedUnsignedType.ll create mode 100644 final/test/CodeGen/Generic/2002-04-16-StackFrameSizeAlignment.ll create mode 100644 final/test/CodeGen/Generic/2003-05-27-phifcmpd.ll create mode 100644 final/test/CodeGen/Generic/2003-05-27-useboolinotherbb.ll create mode 100644 final/test/CodeGen/Generic/2003-05-27-usefsubasbool.ll create mode 100644 final/test/CodeGen/Generic/2003-05-28-ManyArgs.ll create mode 100644 final/test/CodeGen/Generic/2003-05-30-BadFoldGEP.ll create mode 100644 final/test/CodeGen/Generic/2003-05-30-BadPreselectPhi.ll create mode 100644 final/test/CodeGen/Generic/2003-07-06-BadIntCmp.ll create mode 100644 final/test/CodeGen/Generic/2003-07-07-BadLongConst.ll create mode 100644 final/test/CodeGen/Generic/2003-07-08-BadCastToBool.ll create mode 100644 final/test/CodeGen/Generic/2003-07-29-BadConstSbyte.ll create mode 100644 final/test/CodeGen/Generic/2004-02-08-UnwindSupport.ll create mode 100644 final/test/CodeGen/Generic/2004-05-09-LiveVarPartialRegister.ll create mode 100644 final/test/CodeGen/Generic/2005-01-18-SetUO-InfLoop.ll create mode 100644 final/test/CodeGen/Generic/2005-04-09-GlobalInPHI.ll create mode 100644 final/test/CodeGen/Generic/2005-07-12-memcpy-i64-length.ll create mode 100644 final/test/CodeGen/Generic/2005-10-18-ZeroSizeStackObject.ll create mode 100644 final/test/CodeGen/Generic/2005-10-21-longlonggtu.ll create mode 100644 final/test/CodeGen/Generic/2005-12-01-Crash.ll create mode 100644 final/test/CodeGen/Generic/2005-12-12-ExpandSextInreg.ll create mode 100644 final/test/CodeGen/Generic/2006-01-12-BadSetCCFold.ll create mode 100644 final/test/CodeGen/Generic/2006-01-18-InvalidBranchOpcodeAssert.ll create mode 100644 final/test/CodeGen/Generic/2006-02-12-InsertLibcall.ll create mode 100644 final/test/CodeGen/Generic/2006-03-01-dagcombineinfloop.ll create mode 100644 final/test/CodeGen/Generic/2006-04-26-SetCCAnd.ll create mode 100644 final/test/CodeGen/Generic/2006-04-28-Sign-extend-bool.ll create mode 100644 final/test/CodeGen/Generic/2006-05-06-GEP-Cast-Sink-Crash.ll create mode 100644 final/test/CodeGen/Generic/2006-06-12-LowerSwitchCrash.ll create mode 100644 final/test/CodeGen/Generic/2006-06-13-ComputeMaskedBitsCrash.ll create mode 100644 final/test/CodeGen/Generic/2006-06-28-SimplifySetCCCrash.ll create mode 100644 final/test/CodeGen/Generic/2006-07-03-schedulers.ll create mode 100644 final/test/CodeGen/Generic/2006-08-30-CoalescerCrash.ll create mode 100644 final/test/CodeGen/Generic/2006-09-02-LocalAllocCrash.ll create mode 100644 final/test/CodeGen/Generic/2006-09-06-SwitchLowering.ll create mode 100644 final/test/CodeGen/Generic/2006-10-27-CondFolding.ll create mode 100644 final/test/CodeGen/Generic/2006-10-29-Crash.ll create mode 100644 final/test/CodeGen/Generic/2006-11-20-DAGCombineCrash.ll create mode 100644 final/test/CodeGen/Generic/2007-01-15-LoadSelectCycle.ll create mode 100644 final/test/CodeGen/Generic/2007-02-25-invoke.ll create mode 100644 final/test/CodeGen/Generic/2007-04-08-MultipleFrameIndices.ll create mode 100644 final/test/CodeGen/Generic/2007-04-13-SwitchLowerBadPhi.ll create mode 100644 final/test/CodeGen/Generic/2007-04-17-lsr-crash.ll create mode 100644 final/test/CodeGen/Generic/2007-04-27-InlineAsm-X-Dest.ll create mode 100644 final/test/CodeGen/Generic/2007-04-27-LargeMemObject.ll create mode 100644 final/test/CodeGen/Generic/2007-04-30-LandingPadBranchFolding.ll create mode 100644 final/test/CodeGen/Generic/2007-05-03-EHTypeInfo.ll create mode 100644 final/test/CodeGen/Generic/2007-05-15-InfiniteRecursion.ll create mode 100644 final/test/CodeGen/Generic/2007-11-21-UndeadIllegalNode.ll create mode 100644 final/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll create mode 100644 final/test/CodeGen/Generic/2007-12-31-UnusedSelector.ll create mode 100644 final/test/CodeGen/Generic/2008-01-25-dag-combine-mul.ll create mode 100644 final/test/CodeGen/Generic/2008-01-30-LoadCrash.ll create mode 100644 final/test/CodeGen/Generic/2008-02-04-Ctlz.ll create mode 100644 final/test/CodeGen/Generic/2008-02-04-ExtractSubvector.ll create mode 100644 final/test/CodeGen/Generic/2008-02-20-MatchingMem.ll create mode 100644 final/test/CodeGen/Generic/2008-02-25-NegateZero.ll create mode 100644 final/test/CodeGen/Generic/2008-02-26-NegatableCrash.ll create mode 100644 final/test/CodeGen/Generic/2008-08-07-PtrToInt-SmallerInt.ll create mode 100644 final/test/CodeGen/Generic/2009-03-17-LSR-APInt.ll create mode 100644 final/test/CodeGen/Generic/2009-03-29-SoftFloatVectorExtract.ll create mode 100644 final/test/CodeGen/Generic/2009-04-10-SinkCrash.ll create mode 100644 final/test/CodeGen/Generic/2009-04-28-i128-cmp-crash.ll create mode 100644 final/test/CodeGen/Generic/2009-06-03-UnreachableSplitPad.ll create mode 100644 final/test/CodeGen/Generic/2009-11-16-BadKillsCrash.ll create mode 100644 final/test/CodeGen/Generic/2010-07-27-DAGCombineCrash.ll create mode 100644 final/test/CodeGen/Generic/2010-11-04-BigByval.ll create mode 100644 final/test/CodeGen/Generic/2010-ZeroSizedArg.ll create mode 100644 final/test/CodeGen/Generic/2011-01-06-BigNumberCrash.ll create mode 100644 final/test/CodeGen/Generic/2011-02-12-shuffle.ll create mode 100644 final/test/CodeGen/Generic/APIntLoadStore.ll create mode 100644 final/test/CodeGen/Generic/APIntParam.ll create mode 100644 final/test/CodeGen/Generic/APIntSextParam.ll create mode 100644 final/test/CodeGen/Generic/APIntZextParam.ll create mode 100644 final/test/CodeGen/Generic/BasicInstrs.ll create mode 100644 final/test/CodeGen/Generic/BurgBadRegAlloc.ll create mode 100644 final/test/CodeGen/Generic/ConstantExprLowering.ll create mode 100644 final/test/CodeGen/Generic/Makefile create mode 100644 final/test/CodeGen/Generic/add-with-overflow-128.ll create mode 100644 final/test/CodeGen/Generic/add-with-overflow-24.ll create mode 100644 final/test/CodeGen/Generic/add-with-overflow.ll create mode 100644 final/test/CodeGen/Generic/addr-label.ll create mode 100644 final/test/CodeGen/Generic/asm-large-immediate.ll create mode 100644 final/test/CodeGen/Generic/badCallArgLRLLVM.ll create mode 100644 final/test/CodeGen/Generic/badFoldGEP.ll create mode 100644 final/test/CodeGen/Generic/badarg6.ll create mode 100644 final/test/CodeGen/Generic/badlive.ll create mode 100644 final/test/CodeGen/Generic/bool-to-double.ll create mode 100644 final/test/CodeGen/Generic/bool-vector.ll create mode 100644 final/test/CodeGen/Generic/call-ret0.ll create mode 100644 final/test/CodeGen/Generic/call-ret42.ll create mode 100644 final/test/CodeGen/Generic/call-void.ll create mode 100644 final/test/CodeGen/Generic/call2-ret0.ll create mode 100644 final/test/CodeGen/Generic/cast-fp.ll create mode 100644 final/test/CodeGen/Generic/constindices.ll create mode 100644 final/test/CodeGen/Generic/crash.ll create mode 100644 final/test/CodeGen/Generic/dbg_value.ll create mode 100644 final/test/CodeGen/Generic/dg.exp create mode 100644 final/test/CodeGen/Generic/div-neg-power-2.ll create mode 100644 final/test/CodeGen/Generic/empty-load-store.ll create mode 100644 final/test/CodeGen/Generic/externally_available.ll create mode 100644 final/test/CodeGen/Generic/fastcall.ll create mode 100644 final/test/CodeGen/Generic/fneg-fabs.ll create mode 100644 final/test/CodeGen/Generic/fp-to-int-invalid.ll create mode 100644 final/test/CodeGen/Generic/fp_to_int.ll create mode 100644 final/test/CodeGen/Generic/fpowi-promote.ll create mode 100644 final/test/CodeGen/Generic/fwdtwice.ll create mode 100644 final/test/CodeGen/Generic/getresult-undef.ll create mode 100644 final/test/CodeGen/Generic/global-ret0.ll create mode 100644 final/test/CodeGen/Generic/hello.ll create mode 100644 final/test/CodeGen/Generic/i128-addsub.ll create mode 100644 final/test/CodeGen/Generic/i128-arith.ll create mode 100644 final/test/CodeGen/Generic/inline-asm-special-strings.ll create mode 100644 final/test/CodeGen/Generic/intrinsics.ll create mode 100644 final/test/CodeGen/Generic/invalid-memcpy.ll create mode 100644 final/test/CodeGen/Generic/isunord.ll create mode 100644 final/test/CodeGen/Generic/legalize-dbg-value.ll create mode 100644 final/test/CodeGen/Generic/llvm-ct-intrinsics.ll create mode 100644 final/test/CodeGen/Generic/multiple-return-values-cross-block-with-invoke.ll create mode 100644 final/test/CodeGen/Generic/negintconst.ll create mode 100644 final/test/CodeGen/Generic/nested-select.ll create mode 100644 final/test/CodeGen/Generic/overflow.ll create mode 100644 final/test/CodeGen/Generic/pr2625.ll create mode 100644 final/test/CodeGen/Generic/pr3288.ll create mode 100644 final/test/CodeGen/Generic/print-add.ll create mode 100644 final/test/CodeGen/Generic/print-arith-fp.ll create mode 100644 final/test/CodeGen/Generic/print-arith-int.ll create mode 100644 final/test/CodeGen/Generic/print-int.ll create mode 100644 final/test/CodeGen/Generic/print-mul-exp.ll create mode 100644 final/test/CodeGen/Generic/print-mul.ll create mode 100644 final/test/CodeGen/Generic/print-shift.ll create mode 100644 final/test/CodeGen/Generic/ret0.ll create mode 100644 final/test/CodeGen/Generic/ret42.ll create mode 100644 final/test/CodeGen/Generic/select-cc.ll create mode 100644 final/test/CodeGen/Generic/select.ll create mode 100644 final/test/CodeGen/Generic/shift-int64.ll create mode 100644 final/test/CodeGen/Generic/spillccr.ll create mode 100644 final/test/CodeGen/Generic/stacksave-restore.ll create mode 100644 final/test/CodeGen/Generic/storetrunc-fp.ll create mode 100644 final/test/CodeGen/Generic/switch-lower-feature.ll create mode 100644 final/test/CodeGen/Generic/switch-lower.ll create mode 100644 final/test/CodeGen/Generic/trap.ll create mode 100644 final/test/CodeGen/Generic/v-split.ll create mode 100644 final/test/CodeGen/Generic/vector-casts.ll create mode 100644 final/test/CodeGen/Generic/vector-constantexpr.ll create mode 100644 final/test/CodeGen/Generic/vector-identity-shuffle.ll create mode 100644 final/test/CodeGen/Generic/vector.ll create mode 100644 final/test/CodeGen/MBlaze/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/MBlaze/brind.ll create mode 100644 final/test/CodeGen/MBlaze/callind.ll create mode 100644 final/test/CodeGen/MBlaze/cc.ll create mode 100644 final/test/CodeGen/MBlaze/dg.exp create mode 100644 final/test/CodeGen/MBlaze/div.ll create mode 100644 final/test/CodeGen/MBlaze/fpu.ll create mode 100644 final/test/CodeGen/MBlaze/fsl.ll create mode 100644 final/test/CodeGen/MBlaze/imm.ll create mode 100644 final/test/CodeGen/MBlaze/intr.ll create mode 100644 final/test/CodeGen/MBlaze/jumptable.ll create mode 100644 final/test/CodeGen/MBlaze/loop.ll create mode 100644 final/test/CodeGen/MBlaze/mul.ll create mode 100644 final/test/CodeGen/MBlaze/mul64.ll create mode 100644 final/test/CodeGen/MBlaze/select.ll create mode 100644 final/test/CodeGen/MBlaze/shift.ll create mode 100644 final/test/CodeGen/MBlaze/svol.ll create mode 100644 final/test/CodeGen/MSP430/2009-05-10-CyclicDAG.ll create mode 100644 final/test/CodeGen/MSP430/2009-05-17-Rot.ll create mode 100644 final/test/CodeGen/MSP430/2009-05-17-Shift.ll create mode 100644 final/test/CodeGen/MSP430/2009-05-19-DoubleSplit.ll create mode 100644 final/test/CodeGen/MSP430/2009-08-25-DynamicStackAlloc.ll create mode 100644 final/test/CodeGen/MSP430/2009-09-18-AbsoluteAddr.ll create mode 100644 final/test/CodeGen/MSP430/2009-10-10-OrImpDef.ll create mode 100644 final/test/CodeGen/MSP430/2009-11-05-8BitLibcalls.ll create mode 100644 final/test/CodeGen/MSP430/2009-11-08-InvalidResNo.ll create mode 100644 final/test/CodeGen/MSP430/2009-11-20-NewNode.ll create mode 100644 final/test/CodeGen/MSP430/2009-12-21-FrameAddr.ll create mode 100644 final/test/CodeGen/MSP430/2009-12-22-InlineAsm.ll create mode 100644 final/test/CodeGen/MSP430/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/MSP430/2010-05-01-CombinerAnd.ll create mode 100644 final/test/CodeGen/MSP430/AddrMode-bis-rx.ll create mode 100644 final/test/CodeGen/MSP430/AddrMode-bis-xr.ll create mode 100644 final/test/CodeGen/MSP430/AddrMode-mov-rx.ll create mode 100644 final/test/CodeGen/MSP430/AddrMode-mov-xr.ll create mode 100644 final/test/CodeGen/MSP430/Inst16mi.ll create mode 100644 final/test/CodeGen/MSP430/Inst16mm.ll create mode 100644 final/test/CodeGen/MSP430/Inst16mr.ll create mode 100644 final/test/CodeGen/MSP430/Inst16ri.ll create mode 100644 final/test/CodeGen/MSP430/Inst16rm.ll create mode 100644 final/test/CodeGen/MSP430/Inst16rr.ll create mode 100644 final/test/CodeGen/MSP430/Inst8mi.ll create mode 100644 final/test/CodeGen/MSP430/Inst8mm.ll create mode 100644 final/test/CodeGen/MSP430/Inst8mr.ll create mode 100644 final/test/CodeGen/MSP430/Inst8ri.ll create mode 100644 final/test/CodeGen/MSP430/Inst8rm.ll create mode 100644 final/test/CodeGen/MSP430/Inst8rr.ll create mode 100644 final/test/CodeGen/MSP430/bit.ll create mode 100644 final/test/CodeGen/MSP430/dg.exp create mode 100644 final/test/CodeGen/MSP430/indirectbr.ll create mode 100644 final/test/CodeGen/MSP430/indirectbr2.ll create mode 100644 final/test/CodeGen/MSP430/inline-asm.ll create mode 100644 final/test/CodeGen/MSP430/mult-alt-generic-msp430.ll create mode 100644 final/test/CodeGen/MSP430/postinc.ll create mode 100644 final/test/CodeGen/MSP430/setcc.ll create mode 100644 final/test/CodeGen/MSP430/shifts.ll create mode 100644 final/test/CodeGen/Mips/2008-06-05-Carry.ll create mode 100644 final/test/CodeGen/Mips/2008-07-03-SRet.ll create mode 100644 final/test/CodeGen/Mips/2008-07-05-ByVal.ll create mode 100644 final/test/CodeGen/Mips/2008-07-06-fadd64.ll create mode 100644 final/test/CodeGen/Mips/2008-07-07-FPExtend.ll create mode 100644 final/test/CodeGen/Mips/2008-07-07-Float2Int.ll create mode 100644 final/test/CodeGen/Mips/2008-07-07-IntDoubleConvertions.ll create mode 100644 final/test/CodeGen/Mips/2008-07-15-InternalConstant.ll create mode 100644 final/test/CodeGen/Mips/2008-07-15-SmallSection.ll create mode 100644 final/test/CodeGen/Mips/2008-07-16-SignExtInReg.ll create mode 100644 final/test/CodeGen/Mips/2008-07-22-Cstpool.ll create mode 100644 final/test/CodeGen/Mips/2008-07-23-fpcmp.ll create mode 100644 final/test/CodeGen/Mips/2008-07-29-icmp.ll create mode 100644 final/test/CodeGen/Mips/2008-07-31-fcopysign.ll create mode 100644 final/test/CodeGen/Mips/2008-08-01-AsmInline.ll create mode 100644 final/test/CodeGen/Mips/2008-08-03-ReturnDouble.ll create mode 100644 final/test/CodeGen/Mips/2008-08-03-fabs64.ll create mode 100644 final/test/CodeGen/Mips/2008-08-04-Bitconvert.ll create mode 100644 final/test/CodeGen/Mips/2008-08-06-Alloca.ll create mode 100644 final/test/CodeGen/Mips/2008-08-07-CC.ll create mode 100644 final/test/CodeGen/Mips/2008-08-07-FPRound.ll create mode 100644 final/test/CodeGen/Mips/2008-08-08-bswap.ll create mode 100644 final/test/CodeGen/Mips/2008-08-08-ctlz.ll create mode 100644 final/test/CodeGen/Mips/2008-10-13-LegalizerBug.ll create mode 100644 final/test/CodeGen/Mips/2008-11-10-xint_to_fp.ll create mode 100644 final/test/CodeGen/Mips/2009-11-16-CstPoolLoad.ll create mode 100644 final/test/CodeGen/Mips/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/Mips/2010-07-20-Select.ll create mode 100644 final/test/CodeGen/Mips/2010-07-20-Switch.ll create mode 100644 final/test/CodeGen/Mips/2010-11-09-CountLeading.ll create mode 100644 final/test/CodeGen/Mips/2010-11-09-Mul.ll create mode 100644 final/test/CodeGen/Mips/blockaddr.ll create mode 100755 final/test/CodeGen/Mips/cmov.ll create mode 100644 final/test/CodeGen/Mips/dg.exp create mode 100644 final/test/CodeGen/Mips/divrem.ll create mode 100644 final/test/CodeGen/Mips/largeimm1.ll create mode 100644 final/test/CodeGen/Mips/madd-msub.ll create mode 100644 final/test/CodeGen/Mips/o32_cc.ll create mode 100644 final/test/CodeGen/Mips/private.ll create mode 100644 final/test/CodeGen/Mips/rotate.ll create mode 100644 final/test/CodeGen/PTX/add.ll create mode 100644 final/test/CodeGen/PTX/dg.exp create mode 100644 final/test/CodeGen/PTX/exit.ll create mode 100644 final/test/CodeGen/PTX/intrinsic.ll create mode 100644 final/test/CodeGen/PTX/ld.ll create mode 100644 final/test/CodeGen/PTX/mov.ll create mode 100644 final/test/CodeGen/PTX/mul.ll create mode 100644 final/test/CodeGen/PTX/options.ll create mode 100644 final/test/CodeGen/PTX/ret.ll create mode 100644 final/test/CodeGen/PTX/shl.ll create mode 100644 final/test/CodeGen/PTX/shr.ll create mode 100644 final/test/CodeGen/PTX/st.ll create mode 100644 final/test/CodeGen/PTX/sub.ll create mode 100644 final/test/CodeGen/PowerPC/2004-11-29-ShrCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2004-11-30-shift-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2004-11-30-shr-var-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2004-12-12-ZeroSizeCommon.ll create mode 100644 final/test/CodeGen/PowerPC/2005-01-14-SetSelectCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2005-01-14-UndefLong.ll create mode 100644 final/test/CodeGen/PowerPC/2005-08-12-rlwimi-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2005-09-02-LegalizeDuplicatesCalls.ll create mode 100644 final/test/CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll create mode 100644 final/test/CodeGen/PowerPC/2005-11-30-vastart-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-01-11-darwin-fp-argument.ll create mode 100644 final/test/CodeGen/PowerPC/2006-01-20-ShiftPartsCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-04-01-FloatDoubleExtend.ll create mode 100644 final/test/CodeGen/PowerPC/2006-04-05-splat-ish.ll create mode 100644 final/test/CodeGen/PowerPC/2006-04-19-vmaddfp-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-05-12-rlwimi-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-07-07-ComputeMaskedBits.ll create mode 100644 final/test/CodeGen/PowerPC/2006-07-19-stwbrx-crash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-08-11-RetVector.ll create mode 100644 final/test/CodeGen/PowerPC/2006-08-15-SelectionCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2006-09-28-shift_64.ll create mode 100644 final/test/CodeGen/PowerPC/2006-10-11-combiner-aa-regression.ll create mode 100644 final/test/CodeGen/PowerPC/2006-10-13-Miscompile.ll create mode 100644 final/test/CodeGen/PowerPC/2006-10-17-brcc-miscompile.ll create mode 100644 final/test/CodeGen/PowerPC/2006-10-17-ppc64-alloca.ll create mode 100644 final/test/CodeGen/PowerPC/2006-11-10-DAGCombineMiscompile.ll create mode 100644 final/test/CodeGen/PowerPC/2006-11-29-AltivecFPSplat.ll create mode 100644 final/test/CodeGen/PowerPC/2006-12-07-LargeAlloca.ll create mode 100644 final/test/CodeGen/PowerPC/2006-12-07-SelectCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2007-01-04-ArgExtension.ll create mode 100644 final/test/CodeGen/PowerPC/2007-01-15-AsmDialect.ll create mode 100644 final/test/CodeGen/PowerPC/2007-01-29-lbrx-asm.ll create mode 100644 final/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll create mode 100644 final/test/CodeGen/PowerPC/2007-02-16-AlignPacked.ll create mode 100644 final/test/CodeGen/PowerPC/2007-02-16-InlineAsmNConstraint.ll create mode 100644 final/test/CodeGen/PowerPC/2007-02-23-lr-saved-twice.ll create mode 100644 final/test/CodeGen/PowerPC/2007-03-24-cntlzd.ll create mode 100644 final/test/CodeGen/PowerPC/2007-03-30-SpillerCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2007-04-24-InlineAsm-I-Modifier.ll create mode 100644 final/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll create mode 100644 final/test/CodeGen/PowerPC/2007-05-03-InlineAsm-S-Constraint.ll create mode 100644 final/test/CodeGen/PowerPC/2007-05-14-InlineAsmSelectCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2007-05-22-tailmerge-3.ll create mode 100644 final/test/CodeGen/PowerPC/2007-05-30-dagcombine-miscomp.ll create mode 100644 final/test/CodeGen/PowerPC/2007-06-28-BCCISelBug.ll create mode 100644 final/test/CodeGen/PowerPC/2007-08-04-CoalescerAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2007-09-04-AltivecDST.ll create mode 100644 final/test/CodeGen/PowerPC/2007-09-07-LoadStoreIdxForms.ll create mode 100644 final/test/CodeGen/PowerPC/2007-09-08-unaligned.ll create mode 100644 final/test/CodeGen/PowerPC/2007-09-11-RegCoalescerAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2007-09-12-LiveIntervalsAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2007-10-16-InlineAsmFrameOffset.ll create mode 100644 final/test/CodeGen/PowerPC/2007-10-18-PtrArithmetic.ll create mode 100644 final/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2007-10-21-LocalRegAllocAssert2.ll create mode 100644 final/test/CodeGen/PowerPC/2007-11-04-CoalescerCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2007-11-16-landingpad-split.ll create mode 100644 final/test/CodeGen/PowerPC/2007-11-19-VectorSplitting.ll create mode 100644 final/test/CodeGen/PowerPC/2008-02-05-LiveIntervalsAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2008-02-09-LocalRegAllocAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-05-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-17-RegScavengerCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-18-RegScavengerAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-24-AddressRegImm.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-24-CoalescerBug.ll create mode 100644 final/test/CodeGen/PowerPC/2008-03-26-CoalescerBug.ll create mode 100644 final/test/CodeGen/PowerPC/2008-04-10-LiveIntervalCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2008-04-16-CoalescerBug.ll create mode 100644 final/test/CodeGen/PowerPC/2008-04-23-CoalescerCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2008-05-01-ppc_fp128.ll create mode 100644 final/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll create mode 100644 final/test/CodeGen/PowerPC/2008-06-23-LiveVariablesCrash.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-10-SplatMiscompile.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-15-Bswap.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-15-Fabs.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-15-SignExtendInreg.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-17-Fneg.ll create mode 100644 final/test/CodeGen/PowerPC/2008-07-24-PPC64-CCBug.ll create mode 100644 final/test/CodeGen/PowerPC/2008-09-12-CoalescerBug.ll create mode 100644 final/test/CodeGen/PowerPC/2008-10-17-AsmMatchingOperands.ll create mode 100644 final/test/CodeGen/PowerPC/2008-10-28-UnprocessedNode.ll create mode 100644 final/test/CodeGen/PowerPC/2008-10-28-f128-i32.ll create mode 100644 final/test/CodeGen/PowerPC/2008-10-30-IllegalShift.ll create mode 100644 final/test/CodeGen/PowerPC/2008-10-31-PPCF128Libcalls.ll create mode 100644 final/test/CodeGen/PowerPC/2008-12-02-LegalizeTypeAssert.ll create mode 100644 final/test/CodeGen/PowerPC/2008-12-12-EH.ll create mode 100644 final/test/CodeGen/PowerPC/2009-01-16-DeclareISelBug.ll create mode 100644 final/test/CodeGen/PowerPC/2009-03-17-LSRBug.ll create mode 100644 final/test/CodeGen/PowerPC/2009-05-28-LegalizeBRCC.ll create mode 100644 final/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll create mode 100644 final/test/CodeGen/PowerPC/2009-08-17-inline-asm-addr-mode-breakage.ll create mode 100644 final/test/CodeGen/PowerPC/2009-08-23-linkerprivate.ll create mode 100644 final/test/CodeGen/PowerPC/2009-09-18-carrybit.ll create mode 100644 final/test/CodeGen/PowerPC/2009-11-15-ProcImpDefsBug.ll create mode 100644 final/test/CodeGen/PowerPC/2009-11-15-ReMatBug.ll create mode 100644 final/test/CodeGen/PowerPC/2009-11-25-ImpDefBug.ll create mode 100644 final/test/CodeGen/PowerPC/2010-02-04-EmptyGlobal.ll create mode 100644 final/test/CodeGen/PowerPC/2010-02-12-saveCR.ll create mode 100644 final/test/CodeGen/PowerPC/2010-03-09-indirect-call.ll create mode 100644 final/test/CodeGen/PowerPC/2010-04-01-MachineCSEBug.ll create mode 100644 final/test/CodeGen/PowerPC/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll create mode 100644 final/test/CodeGen/PowerPC/2010-10-11-Fast-Varargs.ll create mode 100644 final/test/CodeGen/PowerPC/2010-12-18-PPCStackRefs.ll create mode 100644 final/test/CodeGen/PowerPC/Atomics-32.ll create mode 100644 final/test/CodeGen/PowerPC/Atomics-64.ll create mode 100644 final/test/CodeGen/PowerPC/Frames-alloca.ll create mode 100644 final/test/CodeGen/PowerPC/Frames-large.ll create mode 100644 final/test/CodeGen/PowerPC/Frames-leaf.ll create mode 100644 final/test/CodeGen/PowerPC/Frames-small.ll create mode 100644 final/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll create mode 100644 final/test/CodeGen/PowerPC/addc.ll create mode 100644 final/test/CodeGen/PowerPC/addi-reassoc.ll create mode 100644 final/test/CodeGen/PowerPC/align.ll create mode 100644 final/test/CodeGen/PowerPC/and-branch.ll create mode 100644 final/test/CodeGen/PowerPC/and-elim.ll create mode 100644 final/test/CodeGen/PowerPC/and-imm.ll create mode 100644 final/test/CodeGen/PowerPC/and_add.ll create mode 100644 final/test/CodeGen/PowerPC/and_sext.ll create mode 100644 final/test/CodeGen/PowerPC/and_sra.ll create mode 100644 final/test/CodeGen/PowerPC/atomic-1.ll create mode 100644 final/test/CodeGen/PowerPC/atomic-2.ll create mode 100644 final/test/CodeGen/PowerPC/available-externally.ll create mode 100644 final/test/CodeGen/PowerPC/big-endian-actual-args.ll create mode 100644 final/test/CodeGen/PowerPC/big-endian-call-result.ll create mode 100644 final/test/CodeGen/PowerPC/big-endian-formal-args.ll create mode 100644 final/test/CodeGen/PowerPC/branch-opt.ll create mode 100644 final/test/CodeGen/PowerPC/bswap-load-store.ll create mode 100644 final/test/CodeGen/PowerPC/buildvec_canonicalize.ll create mode 100644 final/test/CodeGen/PowerPC/calls.ll create mode 100644 final/test/CodeGen/PowerPC/cmp-cmp.ll create mode 100644 final/test/CodeGen/PowerPC/compare-duplicate.ll create mode 100644 final/test/CodeGen/PowerPC/compare-simm.ll create mode 100644 final/test/CodeGen/PowerPC/constants.ll create mode 100644 final/test/CodeGen/PowerPC/cr_spilling.ll create mode 100644 final/test/CodeGen/PowerPC/cttz.ll create mode 100644 final/test/CodeGen/PowerPC/darwin-labels.ll create mode 100644 final/test/CodeGen/PowerPC/delete-node.ll create mode 100644 final/test/CodeGen/PowerPC/dg.exp create mode 100644 final/test/CodeGen/PowerPC/div-2.ll create mode 100644 final/test/CodeGen/PowerPC/empty-functions.ll create mode 100644 final/test/CodeGen/PowerPC/eqv-andc-orc-nor.ll create mode 100644 final/test/CodeGen/PowerPC/extsh.ll create mode 100644 final/test/CodeGen/PowerPC/fabs.ll create mode 100644 final/test/CodeGen/PowerPC/fma.ll create mode 100644 final/test/CodeGen/PowerPC/fnabs.ll create mode 100644 final/test/CodeGen/PowerPC/fneg.ll create mode 100644 final/test/CodeGen/PowerPC/fold-li.ll create mode 100644 final/test/CodeGen/PowerPC/fp-branch.ll create mode 100644 final/test/CodeGen/PowerPC/fp-int-fp.ll create mode 100644 final/test/CodeGen/PowerPC/fp_to_uint.ll create mode 100644 final/test/CodeGen/PowerPC/fpcopy.ll create mode 100644 final/test/CodeGen/PowerPC/frounds.ll create mode 100644 final/test/CodeGen/PowerPC/fsqrt.ll create mode 100644 final/test/CodeGen/PowerPC/hello.ll create mode 100644 final/test/CodeGen/PowerPC/hidden-vis-2.ll create mode 100644 final/test/CodeGen/PowerPC/hidden-vis.ll create mode 100644 final/test/CodeGen/PowerPC/i128-and-beyond.ll create mode 100644 final/test/CodeGen/PowerPC/i64_fp.ll create mode 100644 final/test/CodeGen/PowerPC/iabs.ll create mode 100644 final/test/CodeGen/PowerPC/illegal-element-type.ll create mode 100644 final/test/CodeGen/PowerPC/indirectbr.ll create mode 100644 final/test/CodeGen/PowerPC/inlineasm-copy.ll create mode 100644 final/test/CodeGen/PowerPC/int-fp-conv-0.ll create mode 100644 final/test/CodeGen/PowerPC/int-fp-conv-1.ll create mode 100644 final/test/CodeGen/PowerPC/invalid-memcpy.ll create mode 100644 final/test/CodeGen/PowerPC/inverted-bool-compares.ll create mode 100644 final/test/CodeGen/PowerPC/ispositive.ll create mode 100644 final/test/CodeGen/PowerPC/itofp128.ll create mode 100644 final/test/CodeGen/PowerPC/lha.ll create mode 100644 final/test/CodeGen/PowerPC/load-constant-addr.ll create mode 100644 final/test/CodeGen/PowerPC/long-compare.ll create mode 100644 final/test/CodeGen/PowerPC/longdbl-truncate.ll create mode 100644 final/test/CodeGen/PowerPC/lsr-postinc-pos.ll create mode 100644 final/test/CodeGen/PowerPC/mask64.ll create mode 100644 final/test/CodeGen/PowerPC/mem-rr-addr-mode.ll create mode 100644 final/test/CodeGen/PowerPC/mem_update.ll create mode 100644 final/test/CodeGen/PowerPC/mul-neg-power-2.ll create mode 100644 final/test/CodeGen/PowerPC/mul-with-overflow.ll create mode 100644 final/test/CodeGen/PowerPC/mulhs.ll create mode 100644 final/test/CodeGen/PowerPC/mult-alt-generic-powerpc.ll create mode 100644 final/test/CodeGen/PowerPC/mult-alt-generic-powerpc64.ll create mode 100644 final/test/CodeGen/PowerPC/multiple-return-values.ll create mode 100644 final/test/CodeGen/PowerPC/neg.ll create mode 100644 final/test/CodeGen/PowerPC/no-dead-strip.ll create mode 100644 final/test/CodeGen/PowerPC/or-addressing-mode.ll create mode 100644 final/test/CodeGen/PowerPC/ppc-prologue.ll create mode 100644 final/test/CodeGen/PowerPC/ppcf128-1-opt.ll create mode 100644 final/test/CodeGen/PowerPC/ppcf128-1.ll create mode 100644 final/test/CodeGen/PowerPC/ppcf128-2.ll create mode 100644 final/test/CodeGen/PowerPC/ppcf128-3.ll create mode 100644 final/test/CodeGen/PowerPC/ppcf128-4.ll create mode 100644 final/test/CodeGen/PowerPC/pr3711_widen_bit.ll create mode 100644 final/test/CodeGen/PowerPC/private.ll create mode 100644 final/test/CodeGen/PowerPC/reg-coalesce-simple.ll create mode 100644 final/test/CodeGen/PowerPC/retaddr.ll create mode 100644 final/test/CodeGen/PowerPC/return-val-i128.ll create mode 100644 final/test/CodeGen/PowerPC/rlwimi-commute.ll create mode 100644 final/test/CodeGen/PowerPC/rlwimi-keep-rsh.ll create mode 100644 final/test/CodeGen/PowerPC/rlwimi.ll create mode 100644 final/test/CodeGen/PowerPC/rlwimi2.ll create mode 100644 final/test/CodeGen/PowerPC/rlwimi3.ll create mode 100644 final/test/CodeGen/PowerPC/rlwinm.ll create mode 100644 final/test/CodeGen/PowerPC/rlwinm2.ll create mode 100644 final/test/CodeGen/PowerPC/rotl-2.ll create mode 100644 final/test/CodeGen/PowerPC/rotl-64.ll create mode 100644 final/test/CodeGen/PowerPC/rotl.ll create mode 100644 final/test/CodeGen/PowerPC/sections.ll create mode 100644 final/test/CodeGen/PowerPC/select-cc.ll create mode 100644 final/test/CodeGen/PowerPC/select_lt0.ll create mode 100644 final/test/CodeGen/PowerPC/setcc_no_zext.ll create mode 100644 final/test/CodeGen/PowerPC/seteq-0.ll create mode 100644 final/test/CodeGen/PowerPC/shift128.ll create mode 100644 final/test/CodeGen/PowerPC/shl_elim.ll create mode 100644 final/test/CodeGen/PowerPC/shl_sext.ll create mode 100644 final/test/CodeGen/PowerPC/sign_ext_inreg1.ll create mode 100644 final/test/CodeGen/PowerPC/small-arguments.ll create mode 100644 final/test/CodeGen/PowerPC/stack-protector.ll create mode 100644 final/test/CodeGen/PowerPC/stfiwx-2.ll create mode 100644 final/test/CodeGen/PowerPC/stfiwx.ll create mode 100644 final/test/CodeGen/PowerPC/store-load-fwd.ll create mode 100644 final/test/CodeGen/PowerPC/stubs.ll create mode 100644 final/test/CodeGen/PowerPC/subc.ll create mode 100644 final/test/CodeGen/PowerPC/tailcall1-64.ll create mode 100644 final/test/CodeGen/PowerPC/tailcall1.ll create mode 100644 final/test/CodeGen/PowerPC/tailcallpic1.ll create mode 100644 final/test/CodeGen/PowerPC/trampoline.ll create mode 100644 final/test/CodeGen/PowerPC/unsafe-math.ll create mode 100644 final/test/CodeGen/PowerPC/varargs.ll create mode 100644 final/test/CodeGen/PowerPC/vcmp-fold.ll create mode 100644 final/test/CodeGen/PowerPC/vec_auto_constant.ll create mode 100644 final/test/CodeGen/PowerPC/vec_br_cmp.ll create mode 100644 final/test/CodeGen/PowerPC/vec_buildvector_loadstore.ll create mode 100644 final/test/CodeGen/PowerPC/vec_call.ll create mode 100644 final/test/CodeGen/PowerPC/vec_constants.ll create mode 100644 final/test/CodeGen/PowerPC/vec_fneg.ll create mode 100644 final/test/CodeGen/PowerPC/vec_insert.ll create mode 100644 final/test/CodeGen/PowerPC/vec_misaligned.ll create mode 100644 final/test/CodeGen/PowerPC/vec_mul.ll create mode 100644 final/test/CodeGen/PowerPC/vec_perf_shuffle.ll create mode 100644 final/test/CodeGen/PowerPC/vec_shift.ll create mode 100644 final/test/CodeGen/PowerPC/vec_shuffle.ll create mode 100644 final/test/CodeGen/PowerPC/vec_splat.ll create mode 100644 final/test/CodeGen/PowerPC/vec_splat_constant.ll create mode 100644 final/test/CodeGen/PowerPC/vec_vrsave.ll create mode 100644 final/test/CodeGen/PowerPC/vec_zero.ll create mode 100644 final/test/CodeGen/PowerPC/vector-identity-shuffle.ll create mode 100644 final/test/CodeGen/PowerPC/vector.ll create mode 100644 final/test/CodeGen/SPARC/2006-01-22-BitConvertLegalize.ll create mode 100644 final/test/CodeGen/SPARC/2007-05-09-JumpTables.ll create mode 100644 final/test/CodeGen/SPARC/2007-07-05-LiveIntervalAssert.ll create mode 100644 final/test/CodeGen/SPARC/2008-10-10-InlineAsmMemoryOperand.ll create mode 100644 final/test/CodeGen/SPARC/2008-10-10-InlineAsmRegOperand.ll create mode 100644 final/test/CodeGen/SPARC/2009-08-28-PIC.ll create mode 100644 final/test/CodeGen/SPARC/2009-08-28-WeakLinkage.ll create mode 100644 final/test/CodeGen/SPARC/2010-04-07-DbgValueOtherTargets.ll create mode 100755 final/test/CodeGen/SPARC/2011-01-11-CC.ll create mode 100644 final/test/CodeGen/SPARC/2011-01-11-Call.ll create mode 100644 final/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll create mode 100644 final/test/CodeGen/SPARC/2011-01-19-DelaySlot.ll create mode 100644 final/test/CodeGen/SPARC/2011-01-21-ByValArgs.ll create mode 100644 final/test/CodeGen/SPARC/2011-01-22-SRet.ll create mode 100644 final/test/CodeGen/SPARC/basictest.ll create mode 100644 final/test/CodeGen/SPARC/ctpop.ll create mode 100644 final/test/CodeGen/SPARC/dg.exp create mode 100644 final/test/CodeGen/SPARC/mult-alt-generic-sparc.ll create mode 100644 final/test/CodeGen/SPARC/private.ll create mode 100644 final/test/CodeGen/SystemZ/00-RetVoid.ll create mode 100644 final/test/CodeGen/SystemZ/01-RetArg.ll create mode 100644 final/test/CodeGen/SystemZ/01-RetImm.ll create mode 100644 final/test/CodeGen/SystemZ/02-MemArith.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetAdd.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetAddImm.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetAnd.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetAndImm.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetNeg.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetOr.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetOrImm.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetSub.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetSubImm.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetXor.ll create mode 100644 final/test/CodeGen/SystemZ/02-RetXorImm.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetAddImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetAddSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetAndImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetAndSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetArgSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetNegImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetOrImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetOrSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetSubImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetSubSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetXorImmSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/03-RetXorSubreg.ll create mode 100644 final/test/CodeGen/SystemZ/04-RetShifts.ll create mode 100644 final/test/CodeGen/SystemZ/05-LoadAddr.ll create mode 100644 final/test/CodeGen/SystemZ/05-MemImmStores.ll create mode 100644 final/test/CodeGen/SystemZ/05-MemLoadsStores.ll create mode 100644 final/test/CodeGen/SystemZ/05-MemLoadsStores16.ll create mode 100644 final/test/CodeGen/SystemZ/05-MemRegLoads.ll create mode 100644 final/test/CodeGen/SystemZ/05-MemRegStores.ll create mode 100644 final/test/CodeGen/SystemZ/06-CallViaStack.ll create mode 100644 final/test/CodeGen/SystemZ/06-FrameIdxLoad.ll create mode 100644 final/test/CodeGen/SystemZ/06-LocalFrame.ll create mode 100644 final/test/CodeGen/SystemZ/06-SimpleCall.ll create mode 100644 final/test/CodeGen/SystemZ/07-BrCond.ll create mode 100644 final/test/CodeGen/SystemZ/07-BrCond32.ll create mode 100644 final/test/CodeGen/SystemZ/07-BrUnCond.ll create mode 100644 final/test/CodeGen/SystemZ/07-CmpImm.ll create mode 100644 final/test/CodeGen/SystemZ/07-CmpImm32.ll create mode 100644 final/test/CodeGen/SystemZ/07-SelectCC.ll create mode 100644 final/test/CodeGen/SystemZ/08-DivRem.ll create mode 100644 final/test/CodeGen/SystemZ/08-DivRemMemOp.ll create mode 100644 final/test/CodeGen/SystemZ/08-SimpleMuls.ll create mode 100644 final/test/CodeGen/SystemZ/09-DynamicAlloca.ll create mode 100644 final/test/CodeGen/SystemZ/09-Globals.ll create mode 100644 final/test/CodeGen/SystemZ/09-Switches.ll create mode 100644 final/test/CodeGen/SystemZ/10-FuncsPic.ll create mode 100644 final/test/CodeGen/SystemZ/10-GlobalsPic.ll create mode 100644 final/test/CodeGen/SystemZ/11-BSwap.ll create mode 100644 final/test/CodeGen/SystemZ/2009-05-29-InvalidRetResult.ll create mode 100644 final/test/CodeGen/SystemZ/2009-06-02-And32Imm.ll create mode 100644 final/test/CodeGen/SystemZ/2009-06-02-Rotate.ll create mode 100644 final/test/CodeGen/SystemZ/2009-06-05-InvalidArgLoad.ll create mode 100644 final/test/CodeGen/SystemZ/2009-07-04-Shl32.ll create mode 100644 final/test/CodeGen/SystemZ/2009-07-05-Shifts.ll create mode 100644 final/test/CodeGen/SystemZ/2009-07-10-BadIncomingArgOffset.ll create mode 100644 final/test/CodeGen/SystemZ/2009-07-11-FloatBitConvert.ll create mode 100644 final/test/CodeGen/SystemZ/2009-07-11-InvalidRIISel.ll create mode 100644 final/test/CodeGen/SystemZ/2009-08-21-InlineAsmRConstraint.ll create mode 100644 final/test/CodeGen/SystemZ/2009-08-22-FCopySign.ll create mode 100644 final/test/CodeGen/SystemZ/2010-01-04-DivMem.ll create mode 100644 final/test/CodeGen/SystemZ/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/SystemZ/dg.exp create mode 100644 final/test/CodeGen/Thumb/2007-01-31-RegInfoAssert.ll create mode 100644 final/test/CodeGen/Thumb/2007-02-02-JoinIntervalsCrash.ll create mode 100644 final/test/CodeGen/Thumb/2007-03-06-AddR7.ll create mode 100644 final/test/CodeGen/Thumb/2007-05-05-InvalidPushPop.ll create mode 100644 final/test/CodeGen/Thumb/2009-06-18-ThumbCommuteMul.ll create mode 100644 final/test/CodeGen/Thumb/2009-07-19-SPDecBug.ll create mode 100644 final/test/CodeGen/Thumb/2009-07-20-TwoAddrBug.ll create mode 100644 final/test/CodeGen/Thumb/2009-07-27-PEIAssert.ll create mode 100644 final/test/CodeGen/Thumb/2009-08-12-ConstIslandAssert.ll create mode 100644 final/test/CodeGen/Thumb/2009-08-12-RegInfoAssert.ll create mode 100644 final/test/CodeGen/Thumb/2009-08-20-ISelBug.ll create mode 100644 final/test/CodeGen/Thumb/2009-12-17-pre-regalloc-taildup.ll create mode 100644 final/test/CodeGen/Thumb/2010-01-15-local-alloc-spill-physical.ll create mode 100644 final/test/CodeGen/Thumb/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/Thumb/2010-06-18-SibCallCrash.ll create mode 100644 final/test/CodeGen/Thumb/2010-07-01-FuncAlign.ll create mode 100644 final/test/CodeGen/Thumb/2010-07-15-debugOrdering.ll create mode 100644 final/test/CodeGen/Thumb/2011-EpilogueBug.ll create mode 100644 final/test/CodeGen/Thumb/asmprinter-bug.ll create mode 100644 final/test/CodeGen/Thumb/barrier.ll create mode 100644 final/test/CodeGen/Thumb/dg.exp create mode 100644 final/test/CodeGen/Thumb/dyn-stackalloc.ll create mode 100644 final/test/CodeGen/Thumb/fpconv.ll create mode 100644 final/test/CodeGen/Thumb/fpow.ll create mode 100644 final/test/CodeGen/Thumb/frame_thumb.ll create mode 100644 final/test/CodeGen/Thumb/iabs.ll create mode 100644 final/test/CodeGen/Thumb/inlineasm-imm-thumb.ll create mode 100644 final/test/CodeGen/Thumb/ispositive.ll create mode 100644 final/test/CodeGen/Thumb/large-stack.ll create mode 100644 final/test/CodeGen/Thumb/ldr_ext.ll create mode 100644 final/test/CodeGen/Thumb/ldr_frame.ll create mode 100644 final/test/CodeGen/Thumb/long-setcc.ll create mode 100644 final/test/CodeGen/Thumb/long.ll create mode 100644 final/test/CodeGen/Thumb/long_shift.ll create mode 100644 final/test/CodeGen/Thumb/mul.ll create mode 100644 final/test/CodeGen/Thumb/pop.ll create mode 100644 final/test/CodeGen/Thumb/push.ll create mode 100644 final/test/CodeGen/Thumb/select.ll create mode 100644 final/test/CodeGen/Thumb/stack-frame.ll create mode 100644 final/test/CodeGen/Thumb/thumb-imm.ll create mode 100644 final/test/CodeGen/Thumb/trap.ll create mode 100644 final/test/CodeGen/Thumb/tst_teq.ll create mode 100644 final/test/CodeGen/Thumb/unord.ll create mode 100644 final/test/CodeGen/Thumb/vargs.ll create mode 100644 final/test/CodeGen/Thumb2/2009-07-17-CrossRegClassCopy.ll create mode 100644 final/test/CodeGen/Thumb2/2009-07-21-ISelBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-07-23-CPIslandBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-07-30-PEICrash.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-01-WrongLDRBOpc.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-02-CoalescerBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-CoalescerAssert.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-CoalescerBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-ScavengerAssert.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-SubregLoweringBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-SubregLoweringBug2.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-04-SubregLoweringBug3.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-07-CoalescerBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-07-NeonFPBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-08-ScavengerAssert.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-10-ISelBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-08-21-PostRAKill4.ll create mode 100644 final/test/CodeGen/Thumb2/2009-09-01-PostRAProlog.ll create mode 100644 final/test/CodeGen/Thumb2/2009-09-28-ITBlockBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-10-15-ITBlockBranch.ll create mode 100644 final/test/CodeGen/Thumb2/2009-11-01-CopyReg2RegBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-11-11-ScavengerAssert.ll create mode 100644 final/test/CodeGen/Thumb2/2009-11-13-STRDBug.ll create mode 100644 final/test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll create mode 100644 final/test/CodeGen/Thumb2/2010-01-06-TailDuplicateLabels.ll create mode 100644 final/test/CodeGen/Thumb2/2010-01-19-RemovePredicates.ll create mode 100644 final/test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll create mode 100644 final/test/CodeGen/Thumb2/2010-02-24-BigStack.ll create mode 100644 final/test/CodeGen/Thumb2/2010-03-08-addi12-ccout.ll create mode 100644 final/test/CodeGen/Thumb2/2010-03-15-AsmCCClobber.ll create mode 100644 final/test/CodeGen/Thumb2/2010-04-15-DynAllocBug.ll create mode 100644 final/test/CodeGen/Thumb2/2010-04-26-CopyRegCrash.ll create mode 100644 final/test/CodeGen/Thumb2/2010-05-24-rsbs.ll create mode 100644 final/test/CodeGen/Thumb2/2010-06-14-NEONCoalescer.ll create mode 100644 final/test/CodeGen/Thumb2/2010-06-19-ITBlockCrash.ll create mode 100644 final/test/CodeGen/Thumb2/2010-06-21-TailMergeBug.ll create mode 100644 final/test/CodeGen/Thumb2/2010-08-10-VarSizedAllocaBug.ll create mode 100644 final/test/CodeGen/Thumb2/2010-11-22-EpilogueBug.ll create mode 100644 final/test/CodeGen/Thumb2/2010-12-03-AddSPNarrowing.ll create mode 100644 final/test/CodeGen/Thumb2/bfi.ll create mode 100644 final/test/CodeGen/Thumb2/bfx.ll create mode 100644 final/test/CodeGen/Thumb2/buildvector-crash.ll create mode 100644 final/test/CodeGen/Thumb2/carry.ll create mode 100644 final/test/CodeGen/Thumb2/cortex-fp.ll create mode 100644 final/test/CodeGen/Thumb2/crash.ll create mode 100644 final/test/CodeGen/Thumb2/cross-rc-coalescing-1.ll create mode 100644 final/test/CodeGen/Thumb2/cross-rc-coalescing-2.ll create mode 100644 final/test/CodeGen/Thumb2/dg.exp create mode 100644 final/test/CodeGen/Thumb2/div.ll create mode 100644 final/test/CodeGen/Thumb2/frameless.ll create mode 100644 final/test/CodeGen/Thumb2/frameless2.ll create mode 100644 final/test/CodeGen/Thumb2/ifcvt-neon.ll create mode 100644 final/test/CodeGen/Thumb2/large-stack.ll create mode 100644 final/test/CodeGen/Thumb2/ldr-str-imm12.ll create mode 100644 final/test/CodeGen/Thumb2/lsr-deficiency.ll create mode 100644 final/test/CodeGen/Thumb2/machine-licm.ll create mode 100644 final/test/CodeGen/Thumb2/mul_const.ll create mode 100644 final/test/CodeGen/Thumb2/pic-load.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-adc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add3.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add4.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add5.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-add6.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-and.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-and2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-asr.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-asr2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-barrier.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-bcc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-bfc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-bic.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-branch.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-call-tc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-call.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-cbnz.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-clz.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-cmn.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-cmn2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-cmp.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-cmp2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-eor.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-eor2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ifcvt1-tc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ifcvt1.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ifcvt2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ifcvt3.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-jtb.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldm.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldr.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldr_ext.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldr_post.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldr_pre.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldrb.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldrd.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ldrh.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-lsl.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-lsl2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-lsr.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-lsr2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-lsr3.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mla.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mls.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mov.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mul.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mulhi.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mvn.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-mvn2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-neg.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-orn.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-orn2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-orr.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-orr2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-pack.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-rev.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-rev16.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ror.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-ror2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-rsb.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-rsb2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sbc.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-select.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-select_xform.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-shifter.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-smla.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-smul.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-spill-q.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-str.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-str_post.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-str_pre.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-strb.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-strh.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sub.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sub2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sub3.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sub4.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sub5.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-sxt_rot.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-tbb.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-tbh.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-teq.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-teq2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-tst.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-tst2.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-uxt_rot.ll create mode 100644 final/test/CodeGen/Thumb2/thumb2-uxtb.ll create mode 100644 final/test/CodeGen/Thumb2/tls1.ll create mode 100644 final/test/CodeGen/Thumb2/tls2.ll create mode 100644 final/test/CodeGen/X86/2003-08-03-CallArgLiveRanges.ll create mode 100644 final/test/CodeGen/X86/2003-08-23-DeadBlockTest.ll create mode 100644 final/test/CodeGen/X86/2003-11-03-GlobalBool.ll create mode 100644 final/test/CodeGen/X86/2004-02-12-Memcpy.ll create mode 100644 final/test/CodeGen/X86/2004-02-13-FrameReturnAddress.ll create mode 100644 final/test/CodeGen/X86/2004-02-14-InefficientStackPointer.ll create mode 100644 final/test/CodeGen/X86/2004-02-22-Casts.ll create mode 100644 final/test/CodeGen/X86/2004-03-30-Select-Max.ll create mode 100644 final/test/CodeGen/X86/2004-04-09-SameValueCoalescing.ll create mode 100644 final/test/CodeGen/X86/2004-04-13-FPCMOV-Crash.ll create mode 100644 final/test/CodeGen/X86/2004-06-10-StackifierCrash.ll create mode 100644 final/test/CodeGen/X86/2004-10-08-SelectSetCCFold.ll create mode 100644 final/test/CodeGen/X86/2005-01-17-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2005-02-14-IllegalAssembler.ll create mode 100644 final/test/CodeGen/X86/2005-05-08-FPStackifierPHI.ll create mode 100644 final/test/CodeGen/X86/2006-01-19-ISelFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2006-03-01-InstrSchedBug.ll create mode 100644 final/test/CodeGen/X86/2006-03-02-InstrSchedBug.ll create mode 100644 final/test/CodeGen/X86/2006-04-04-CrossBlockCrash.ll create mode 100644 final/test/CodeGen/X86/2006-04-27-ISelFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2006-05-01-SchedCausingSpills.ll create mode 100644 final/test/CodeGen/X86/2006-05-02-InstrSched1.ll create mode 100644 final/test/CodeGen/X86/2006-05-02-InstrSched2.ll create mode 100644 final/test/CodeGen/X86/2006-05-08-CoalesceSubRegClass.ll create mode 100644 final/test/CodeGen/X86/2006-05-08-InstrSched.ll create mode 100644 final/test/CodeGen/X86/2006-05-11-InstrSched.ll create mode 100644 final/test/CodeGen/X86/2006-05-17-VectorArg.ll create mode 100644 final/test/CodeGen/X86/2006-05-22-FPSetEQ.ll create mode 100644 final/test/CodeGen/X86/2006-05-25-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-07-10-InlineAsmAConstraint.ll create mode 100644 final/test/CodeGen/X86/2006-07-12-InlineAsmQConstraint.ll create mode 100644 final/test/CodeGen/X86/2006-07-19-ATTAsm.ll create mode 100644 final/test/CodeGen/X86/2006-07-20-InlineAsm.ll create mode 100644 final/test/CodeGen/X86/2006-07-28-AsmPrint-Long-As-Pointer.ll create mode 100644 final/test/CodeGen/X86/2006-07-31-SingleRegClass.ll create mode 100644 final/test/CodeGen/X86/2006-08-07-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-08-16-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-08-21-ExtraMovInst.ll create mode 100644 final/test/CodeGen/X86/2006-09-01-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-10-02-BoolRetCrash.ll create mode 100644 final/test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll create mode 100644 final/test/CodeGen/X86/2006-10-09-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-10-10-FindModifiedNodeSlotBug.ll create mode 100644 final/test/CodeGen/X86/2006-10-12-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-10-13-CycleInDAG.ll create mode 100644 final/test/CodeGen/X86/2006-10-19-SwitchUnnecessaryBranching.ll create mode 100644 final/test/CodeGen/X86/2006-11-12-CSRetCC.ll create mode 100644 final/test/CodeGen/X86/2006-11-17-IllegalMove.ll create mode 100644 final/test/CodeGen/X86/2006-11-27-SelectLegalize.ll create mode 100644 final/test/CodeGen/X86/2006-11-28-Memcpy.ll create mode 100644 final/test/CodeGen/X86/2006-12-16-InlineAsmCrash.ll create mode 100644 final/test/CodeGen/X86/2006-12-19-IntelSyntax.ll create mode 100644 final/test/CodeGen/X86/2007-01-08-InstrSched.ll create mode 100644 final/test/CodeGen/X86/2007-01-08-X86-64-Pointer.ll create mode 100644 final/test/CodeGen/X86/2007-01-13-StackPtrIndex.ll create mode 100644 final/test/CodeGen/X86/2007-01-29-InlineAsm-ir.ll create mode 100644 final/test/CodeGen/X86/2007-02-04-OrAddrMode.ll create mode 100644 final/test/CodeGen/X86/2007-02-16-BranchFold.ll create mode 100644 final/test/CodeGen/X86/2007-02-19-LiveIntervalAssert.ll create mode 100644 final/test/CodeGen/X86/2007-02-23-DAGCombine-Miscompile.ll create mode 100644 final/test/CodeGen/X86/2007-02-25-FastCCStack.ll create mode 100644 final/test/CodeGen/X86/2007-03-01-SpillerCrash.ll create mode 100644 final/test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll create mode 100644 final/test/CodeGen/X86/2007-03-16-InlineAsm.ll create mode 100644 final/test/CodeGen/X86/2007-03-18-LiveIntervalAssert.ll create mode 100644 final/test/CodeGen/X86/2007-03-24-InlineAsmMultiRegConstraint.ll create mode 100644 final/test/CodeGen/X86/2007-03-24-InlineAsmPModifier.ll create mode 100644 final/test/CodeGen/X86/2007-03-24-InlineAsmVectorOp.ll create mode 100644 final/test/CodeGen/X86/2007-03-24-InlineAsmXConstraint.ll create mode 100644 final/test/CodeGen/X86/2007-03-26-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2007-04-08-InlineAsmCrash.ll create mode 100644 final/test/CodeGen/X86/2007-04-11-InlineAsmVectorResult.ll create mode 100644 final/test/CodeGen/X86/2007-04-17-LiveIntervalAssert.ll create mode 100644 final/test/CodeGen/X86/2007-04-24-Huge-Stack.ll create mode 100644 final/test/CodeGen/X86/2007-04-24-VectorCrash.ll create mode 100644 final/test/CodeGen/X86/2007-04-25-MMX-PADDQ.ll create mode 100644 final/test/CodeGen/X86/2007-04-27-InlineAsm-IntMemInput.ll create mode 100644 final/test/CodeGen/X86/2007-05-05-Personality.ll create mode 100644 final/test/CodeGen/X86/2007-05-05-VecCastExpand.ll create mode 100644 final/test/CodeGen/X86/2007-05-07-InvokeSRet.ll create mode 100644 final/test/CodeGen/X86/2007-05-14-LiveIntervalAssert.ll create mode 100644 final/test/CodeGen/X86/2007-05-15-maskmovq.ll create mode 100644 final/test/CodeGen/X86/2007-05-17-ShuffleISelBug.ll create mode 100644 final/test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll create mode 100644 final/test/CodeGen/X86/2007-06-04-tailmerge4.ll create mode 100644 final/test/CodeGen/X86/2007-06-05-LSR-Dominator.ll create mode 100644 final/test/CodeGen/X86/2007-06-15-IntToMMX.ll create mode 100644 final/test/CodeGen/X86/2007-06-28-X86-64-isel.ll create mode 100644 final/test/CodeGen/X86/2007-06-29-DAGCombinerBug.ll create mode 100644 final/test/CodeGen/X86/2007-06-29-VecFPConstantCSEBug.ll create mode 100644 final/test/CodeGen/X86/2007-07-03-GR64ToVR64.ll create mode 100644 final/test/CodeGen/X86/2007-07-10-StackerAssert.ll create mode 100644 final/test/CodeGen/X86/2007-07-18-Vector-Extract.ll create mode 100644 final/test/CodeGen/X86/2007-08-01-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/X86/2007-08-09-IllegalX86-64Asm.ll create mode 100644 final/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll create mode 100644 final/test/CodeGen/X86/2007-08-13-AppendingLinkage.ll create mode 100644 final/test/CodeGen/X86/2007-09-05-InvalidAsm.ll create mode 100644 final/test/CodeGen/X86/2007-09-06-ExtWeakAliasee.ll create mode 100644 final/test/CodeGen/X86/2007-09-17-ObjcFrameEH.ll create mode 100644 final/test/CodeGen/X86/2007-09-18-ShuffleXformBug.ll create mode 100644 final/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll create mode 100644 final/test/CodeGen/X86/2007-10-04-AvoidEFLAGSCopy.ll create mode 100644 final/test/CodeGen/X86/2007-10-05-3AddrConvert.ll create mode 100644 final/test/CodeGen/X86/2007-10-12-CoalesceExtSubReg.ll create mode 100644 final/test/CodeGen/X86/2007-10-12-SpillerUnfold1.ll create mode 100644 final/test/CodeGen/X86/2007-10-12-SpillerUnfold2.ll create mode 100644 final/test/CodeGen/X86/2007-10-14-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2007-10-15-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2007-10-16-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2007-10-17-IllegalAsm.ll create mode 100644 final/test/CodeGen/X86/2007-10-19-SpillerUnfold.ll create mode 100644 final/test/CodeGen/X86/2007-10-28-inlineasm-q-modifier.ll create mode 100644 final/test/CodeGen/X86/2007-10-29-ExtendSetCC.ll create mode 100644 final/test/CodeGen/X86/2007-10-30-LSRCrash.ll create mode 100644 final/test/CodeGen/X86/2007-10-31-extractelement-i64.ll create mode 100644 final/test/CodeGen/X86/2007-11-01-ISelCrash.ll create mode 100644 final/test/CodeGen/X86/2007-11-02-BadAsm.ll create mode 100644 final/test/CodeGen/X86/2007-11-03-x86-64-q-constraint.ll create mode 100644 final/test/CodeGen/X86/2007-11-04-LiveIntervalCrash.ll create mode 100644 final/test/CodeGen/X86/2007-11-04-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/X86/2007-11-04-rip-immediate-constant.ll create mode 100644 final/test/CodeGen/X86/2007-11-06-InstrSched.ll create mode 100644 final/test/CodeGen/X86/2007-11-07-MulBy4.ll create mode 100644 final/test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll create mode 100644 final/test/CodeGen/X86/2007-12-11-FoldImpDefSpill.ll create mode 100644 final/test/CodeGen/X86/2007-12-16-BURRSchedCrash.ll create mode 100644 final/test/CodeGen/X86/2007-12-18-LoadCSEBug.ll create mode 100644 final/test/CodeGen/X86/2008-01-08-IllegalCMP.ll create mode 100644 final/test/CodeGen/X86/2008-01-08-SchedulerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-01-09-LongDoubleSin.ll create mode 100644 final/test/CodeGen/X86/2008-01-16-FPStackifierAssert.ll create mode 100644 final/test/CodeGen/X86/2008-01-16-InvalidDAGCombineXform.ll create mode 100644 final/test/CodeGen/X86/2008-01-16-Trampoline.ll create mode 100644 final/test/CodeGen/X86/2008-02-05-ISelCrash.ll create mode 100644 final/test/CodeGen/X86/2008-02-06-LoadFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-08-LoadFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-14-BitMiscompile.ll create mode 100644 final/test/CodeGen/X86/2008-02-18-TailMergingBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-20-InlineAsmClobber.ll create mode 100644 final/test/CodeGen/X86/2008-02-22-LocalRegAllocBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-22-ReMatBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-25-InlineAsmBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-25-X86-64-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-26-AsmDirectMemOp.ll create mode 100644 final/test/CodeGen/X86/2008-02-27-DeadSlotElimBug.ll create mode 100644 final/test/CodeGen/X86/2008-02-27-PEICrash.ll create mode 100644 final/test/CodeGen/X86/2008-03-06-frem-fpstack.ll create mode 100644 final/test/CodeGen/X86/2008-03-07-APIntBug.ll create mode 100644 final/test/CodeGen/X86/2008-03-10-RegAllocInfLoop.ll create mode 100644 final/test/CodeGen/X86/2008-03-12-ThreadLocalAlias.ll create mode 100644 final/test/CodeGen/X86/2008-03-13-TwoAddrPassCrash.ll create mode 100644 final/test/CodeGen/X86/2008-03-14-SpillerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-03-18-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-03-19-DAGCombinerBug.ll create mode 100644 final/test/CodeGen/X86/2008-03-23-DarwinAsmComments.ll create mode 100644 final/test/CodeGen/X86/2008-03-25-TwoAddrPassBug.ll create mode 100644 final/test/CodeGen/X86/2008-03-31-SpillerFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-02-unnamedEH.ll create mode 100644 final/test/CodeGen/X86/2008-04-08-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-04-09-BranchFolding.ll create mode 100644 final/test/CodeGen/X86/2008-04-15-LiveVariableBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-16-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-16-ReMatBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-17-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-24-MemCpyBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-24-pblendw-fold-crash.ll create mode 100644 final/test/CodeGen/X86/2008-04-26-Asm-Optimize-Imm.ll create mode 100644 final/test/CodeGen/X86/2008-04-28-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-04-28-CyclicSchedUnit.ll create mode 100644 final/test/CodeGen/X86/2008-05-01-InvalidOrdCompare.ll create mode 100644 final/test/CodeGen/X86/2008-05-09-PHIElimBug.ll create mode 100644 final/test/CodeGen/X86/2008-05-09-ShuffleLoweringBug.ll create mode 100644 final/test/CodeGen/X86/2008-05-12-tailmerge-5.ll create mode 100644 final/test/CodeGen/X86/2008-05-21-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-05-22-FoldUnalignedLoad.ll create mode 100644 final/test/CodeGen/X86/2008-05-28-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-05-28-LocalRegAllocBug.ll create mode 100644 final/test/CodeGen/X86/2008-06-04-MemCpyLoweringBug.ll create mode 100644 final/test/CodeGen/X86/2008-06-13-NotVolatileLoadStore.ll create mode 100644 final/test/CodeGen/X86/2008-06-13-VolatileLoadStore.ll create mode 100644 final/test/CodeGen/X86/2008-06-16-SubregsBug.ll create mode 100644 final/test/CodeGen/X86/2008-06-18-BadShuffle.ll create mode 100644 final/test/CodeGen/X86/2008-06-25-VecISelBug.ll create mode 100644 final/test/CodeGen/X86/2008-07-07-DanglingDeadInsts.ll create mode 100644 final/test/CodeGen/X86/2008-07-09-ELFSectionAttributes.ll create mode 100644 final/test/CodeGen/X86/2008-07-11-SHLBy1.ll create mode 100644 final/test/CodeGen/X86/2008-07-11-SpillerBug.ll create mode 100644 final/test/CodeGen/X86/2008-07-16-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-07-19-movups-spills.ll create mode 100644 final/test/CodeGen/X86/2008-07-22-CombinerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-07-23-VSetCC.ll create mode 100644 final/test/CodeGen/X86/2008-08-05-SpillerBug.ll create mode 100644 final/test/CodeGen/X86/2008-08-06-CmpStride.ll create mode 100644 final/test/CodeGen/X86/2008-08-06-RewriterBug.ll create mode 100644 final/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll create mode 100644 final/test/CodeGen/X86/2008-08-19-SubAndFetch.ll create mode 100644 final/test/CodeGen/X86/2008-08-23-64Bit-maskmovq.ll create mode 100644 final/test/CodeGen/X86/2008-08-23-X86-64AsmBug.ll create mode 100644 final/test/CodeGen/X86/2008-08-25-AsmRegTypeMismatch.ll create mode 100644 final/test/CodeGen/X86/2008-08-31-EH_RETURN32.ll create mode 100644 final/test/CodeGen/X86/2008-08-31-EH_RETURN64.ll create mode 100644 final/test/CodeGen/X86/2008-09-05-sinttofp-2xi32.ll create mode 100644 final/test/CodeGen/X86/2008-09-09-LinearScanBug.ll create mode 100644 final/test/CodeGen/X86/2008-09-11-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-09-11-CoalescerBug2.ll create mode 100644 final/test/CodeGen/X86/2008-09-17-inline-asm-1.ll create mode 100644 final/test/CodeGen/X86/2008-09-18-inline-asm-2.ll create mode 100644 final/test/CodeGen/X86/2008-09-19-RegAllocBug.ll create mode 100644 final/test/CodeGen/X86/2008-09-25-sseregparm-1.ll create mode 100644 final/test/CodeGen/X86/2008-09-26-FrameAddrBug.ll create mode 100644 final/test/CodeGen/X86/2008-09-29-ReMatBug.ll create mode 100644 final/test/CodeGen/X86/2008-09-29-VolatileBug.ll create mode 100644 final/test/CodeGen/X86/2008-10-02-Atomics32-2.ll create mode 100644 final/test/CodeGen/X86/2008-10-06-MMXISelBug.ll create mode 100644 final/test/CodeGen/X86/2008-10-06-x87ld-nan-1.ll create mode 100644 final/test/CodeGen/X86/2008-10-06-x87ld-nan-2.ll create mode 100644 final/test/CodeGen/X86/2008-10-07-SSEISelBug.ll create mode 100644 final/test/CodeGen/X86/2008-10-11-CallCrash.ll create mode 100644 final/test/CodeGen/X86/2008-10-13-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-10-16-VecUnaryOp.ll create mode 100644 final/test/CodeGen/X86/2008-10-17-Asm64bitRConstraint.ll create mode 100644 final/test/CodeGen/X86/2008-10-20-AsmDoubleInI32.ll create mode 100644 final/test/CodeGen/X86/2008-10-24-FlippedCompare.ll create mode 100644 final/test/CodeGen/X86/2008-10-27-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2008-10-27-StackRealignment.ll create mode 100644 final/test/CodeGen/X86/2008-10-29-ExpandVAARG.ll create mode 100644 final/test/CodeGen/X86/2008-11-03-F80VAARG.ll create mode 100644 final/test/CodeGen/X86/2008-11-06-testb.ll create mode 100644 final/test/CodeGen/X86/2008-11-13-inlineasm-3.ll create mode 100644 final/test/CodeGen/X86/2008-11-29-ULT-Sign.ll create mode 100644 final/test/CodeGen/X86/2008-12-01-SpillerAssert.ll create mode 100644 final/test/CodeGen/X86/2008-12-01-loop-iv-used-outside-loop.ll create mode 100644 final/test/CodeGen/X86/2008-12-02-IllegalResultType.ll create mode 100644 final/test/CodeGen/X86/2008-12-02-dagcombine-1.ll create mode 100644 final/test/CodeGen/X86/2008-12-02-dagcombine-2.ll create mode 100644 final/test/CodeGen/X86/2008-12-02-dagcombine-3.ll create mode 100644 final/test/CodeGen/X86/2008-12-05-SpillerCrash.ll create mode 100644 final/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll create mode 100644 final/test/CodeGen/X86/2008-12-16-BadShift.ll create mode 100644 final/test/CodeGen/X86/2008-12-16-dagcombine-4.ll create mode 100644 final/test/CodeGen/X86/2008-12-19-EarlyClobberBug.ll create mode 100644 final/test/CodeGen/X86/2008-12-22-dagcombine-5.ll create mode 100644 final/test/CodeGen/X86/2008-12-23-crazy-address.ll create mode 100644 final/test/CodeGen/X86/2008-12-23-dagcombine-6.ll create mode 100644 final/test/CodeGen/X86/2009-01-13-DoubleUpdate.ll create mode 100644 final/test/CodeGen/X86/2009-01-16-SchedulerBug.ll create mode 100644 final/test/CodeGen/X86/2009-01-16-UIntToFP.ll create mode 100644 final/test/CodeGen/X86/2009-01-18-ConstantExprCrash.ll create mode 100644 final/test/CodeGen/X86/2009-01-25-NoSSE.ll create mode 100644 final/test/CodeGen/X86/2009-01-26-WrongCheck.ll create mode 100644 final/test/CodeGen/X86/2009-01-27-NullStrings.ll create mode 100644 final/test/CodeGen/X86/2009-01-29-LocalRegAllocBug.ll create mode 100644 final/test/CodeGen/X86/2009-01-31-BigShift.ll create mode 100644 final/test/CodeGen/X86/2009-01-31-BigShift2.ll create mode 100644 final/test/CodeGen/X86/2009-01-31-BigShift3.ll create mode 100644 final/test/CodeGen/X86/2009-02-01-LargeMask.ll create mode 100644 final/test/CodeGen/X86/2009-02-03-AnalyzedTwice.ll create mode 100644 final/test/CodeGen/X86/2009-02-04-sext-i64-gep.ll create mode 100644 final/test/CodeGen/X86/2009-02-05-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-02-08-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-02-09-ivs-different-sizes.ll create mode 100644 final/test/CodeGen/X86/2009-02-11-codegenprepare-reuse.ll create mode 100644 final/test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll create mode 100644 final/test/CodeGen/X86/2009-02-12-InlineAsm-nieZ-constraints.ll create mode 100644 final/test/CodeGen/X86/2009-02-12-SpillerBug.ll create mode 100644 final/test/CodeGen/X86/2009-02-20-PreAllocSplit-Crash.ll create mode 100644 final/test/CodeGen/X86/2009-02-21-ExtWeakInitializer.ll create mode 100644 final/test/CodeGen/X86/2009-02-25-CommuteBug.ll create mode 100644 final/test/CodeGen/X86/2009-02-26-MachineLICMBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-03-BTHang.ll create mode 100644 final/test/CodeGen/X86/2009-03-03-BitcastLongDouble.ll create mode 100644 final/test/CodeGen/X86/2009-03-05-burr-list-crash.ll create mode 100644 final/test/CodeGen/X86/2009-03-07-FPConstSelect.ll create mode 100644 final/test/CodeGen/X86/2009-03-09-APIntCrash.ll create mode 100644 final/test/CodeGen/X86/2009-03-09-SpillerBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-10-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-12-CPAlignBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-13-PHIElimBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-16-PHIElimInLPad.ll create mode 100644 final/test/CodeGen/X86/2009-03-16-SpillerBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-23-LinearScanBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-23-MultiUseSched.ll create mode 100644 final/test/CodeGen/X86/2009-03-23-i80-fp80.ll create mode 100644 final/test/CodeGen/X86/2009-03-25-TestBug.ll create mode 100644 final/test/CodeGen/X86/2009-03-26-NoImplicitFPBug.ll create mode 100644 final/test/CodeGen/X86/2009-04-09-InlineAsmCrash.ll create mode 100644 final/test/CodeGen/X86/2009-04-12-FastIselOverflowCrash.ll create mode 100644 final/test/CodeGen/X86/2009-04-12-picrel.ll create mode 100644 final/test/CodeGen/X86/2009-04-13-2AddrAssert-2.ll create mode 100644 final/test/CodeGen/X86/2009-04-13-2AddrAssert.ll create mode 100644 final/test/CodeGen/X86/2009-04-14-IllegalRegs.ll create mode 100644 final/test/CodeGen/X86/2009-04-16-SpillerUnfold.ll create mode 100644 final/test/CodeGen/X86/2009-04-20-LinearScanOpt.ll create mode 100644 final/test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll create mode 100644 final/test/CodeGen/X86/2009-04-24.ll create mode 100644 final/test/CodeGen/X86/2009-04-25-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-04-27-CoalescerAssert.ll create mode 100644 final/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert.ll create mode 100644 final/test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll create mode 100644 final/test/CodeGen/X86/2009-04-27-LiveIntervalsBug.ll create mode 100644 final/test/CodeGen/X86/2009-04-29-IndirectDestOperands.ll create mode 100644 final/test/CodeGen/X86/2009-04-29-LinearScanBug.ll create mode 100644 final/test/CodeGen/X86/2009-04-29-RegAllocAssert.ll create mode 100644 final/test/CodeGen/X86/2009-04-scale.ll create mode 100644 final/test/CodeGen/X86/2009-05-08-InlineAsmIOffset.ll create mode 100644 final/test/CodeGen/X86/2009-05-11-tailmerge-crash.ll create mode 100644 final/test/CodeGen/X86/2009-05-19-SingleElementExtractElement.ll create mode 100644 final/test/CodeGen/X86/2009-05-23-available_externally.ll create mode 100644 final/test/CodeGen/X86/2009-05-23-dagcombine-shifts.ll create mode 100644 final/test/CodeGen/X86/2009-05-28-DAGCombineCrash.ll create mode 100644 final/test/CodeGen/X86/2009-05-30-ISelBug.ll create mode 100644 final/test/CodeGen/X86/2009-06-02-RewriterBug.ll create mode 100644 final/test/CodeGen/X86/2009-06-03-Win64DisableRedZone.ll create mode 100644 final/test/CodeGen/X86/2009-06-03-Win64SpillXMM.ll create mode 100644 final/test/CodeGen/X86/2009-06-04-VirtualLiveIn.ll create mode 100644 final/test/CodeGen/X86/2009-06-05-ScalarToVectorByteMMX.ll create mode 100644 final/test/CodeGen/X86/2009-06-05-VZextByteShort.ll create mode 100644 final/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll create mode 100644 final/test/CodeGen/X86/2009-06-05-sitofpCrash.ll create mode 100644 final/test/CodeGen/X86/2009-06-06-ConcatVectors.ll create mode 100644 final/test/CodeGen/X86/2009-06-07-ExpandMMXBitcast.ll create mode 100644 final/test/CodeGen/X86/2009-06-12-x86_64-tail-call-conv-out-of-sync-bug.ll create mode 100644 final/test/CodeGen/X86/2009-06-15-not-a-tail-call.ll create mode 100644 final/test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll create mode 100644 final/test/CodeGen/X86/2009-07-06-TwoAddrAssert.ll create mode 100644 final/test/CodeGen/X86/2009-07-07-SplitICmp.ll create mode 100644 final/test/CodeGen/X86/2009-07-09-ExtractBoolFromVector.ll create mode 100644 final/test/CodeGen/X86/2009-07-15-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-07-16-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-07-17-StackColoringBug.ll create mode 100644 final/test/CodeGen/X86/2009-07-19-AsmExtraOperands.ll create mode 100644 final/test/CodeGen/X86/2009-07-20-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-07-20-DAGCombineBug.ll create mode 100644 final/test/CodeGen/X86/2009-08-02-mmx-scalar-to-vector.ll create mode 100644 final/test/CodeGen/X86/2009-08-06-branchfolder-crash.ll create mode 100644 final/test/CodeGen/X86/2009-08-06-inlineasm.ll create mode 100644 final/test/CodeGen/X86/2009-08-08-CastError.ll create mode 100644 final/test/CodeGen/X86/2009-08-12-badswitch.ll create mode 100644 final/test/CodeGen/X86/2009-08-14-Win64MemoryIndirectArg.ll create mode 100644 final/test/CodeGen/X86/2009-08-19-LoadNarrowingMiscompile.ll create mode 100644 final/test/CodeGen/X86/2009-08-23-SubRegReuseUndo.ll create mode 100644 final/test/CodeGen/X86/2009-08-23-linkerprivate.ll create mode 100644 final/test/CodeGen/X86/2009-09-10-LoadFoldingBug.ll create mode 100644 final/test/CodeGen/X86/2009-09-10-SpillComments.ll create mode 100644 final/test/CodeGen/X86/2009-09-16-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-09-19-earlyclobber.ll create mode 100644 final/test/CodeGen/X86/2009-09-21-NoSpillLoopCount.ll create mode 100644 final/test/CodeGen/X86/2009-09-22-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2009-09-23-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/X86/2009-10-08-MachineLICMBug.ll create mode 100644 final/test/CodeGen/X86/2009-10-14-LiveVariablesBug.ll create mode 100644 final/test/CodeGen/X86/2009-10-16-Scope.ll create mode 100644 final/test/CodeGen/X86/2009-10-19-EmergencySpill.ll create mode 100644 final/test/CodeGen/X86/2009-10-19-atomic-cmp-eflags.ll create mode 100644 final/test/CodeGen/X86/2009-10-25-RewriterBug.ll create mode 100644 final/test/CodeGen/X86/2009-11-04-SubregCoalescingBug.ll create mode 100644 final/test/CodeGen/X86/2009-11-13-VirtRegRewriterBug.ll create mode 100644 final/test/CodeGen/X86/2009-11-16-MachineLICM.ll create mode 100644 final/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll create mode 100644 final/test/CodeGen/X86/2009-11-17-UpdateTerminator.ll create mode 100644 final/test/CodeGen/X86/2009-11-18-TwoAddrKill.ll create mode 100644 final/test/CodeGen/X86/2009-11-25-ImpDefBug.ll create mode 100644 final/test/CodeGen/X86/2009-12-01-EarlyClobberBug.ll create mode 100644 final/test/CodeGen/X86/2009-12-11-TLSNoRedZone.ll create mode 100644 final/test/CodeGen/X86/20090313-signext.ll create mode 100644 final/test/CodeGen/X86/2010-01-05-ZExt-Shl.ll create mode 100644 final/test/CodeGen/X86/2010-01-07-ISelBug.ll create mode 100644 final/test/CodeGen/X86/2010-01-07-UAMemFeature.ll create mode 100644 final/test/CodeGen/X86/2010-01-08-Atomic64Bug.ll create mode 100644 final/test/CodeGen/X86/2010-01-11-ExtraPHIArg.ll create mode 100644 final/test/CodeGen/X86/2010-01-13-OptExtBug.ll create mode 100644 final/test/CodeGen/X86/2010-01-15-SelectionDAGCycle.ll create mode 100644 final/test/CodeGen/X86/2010-01-18-DbgValue.ll create mode 100644 final/test/CodeGen/X86/2010-01-19-OptExtBug.ll create mode 100644 final/test/CodeGen/X86/2010-02-01-DbgValueCrash.ll create mode 100644 final/test/CodeGen/X86/2010-02-01-TaillCallCrash.ll create mode 100644 final/test/CodeGen/X86/2010-02-03-DualUndef.ll create mode 100644 final/test/CodeGen/X86/2010-02-04-SchedulerBug.ll create mode 100644 final/test/CodeGen/X86/2010-02-11-NonTemporal.ll create mode 100644 final/test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll create mode 100644 final/test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll create mode 100644 final/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll create mode 100644 final/test/CodeGen/X86/2010-02-23-DAGCombineBug.ll create mode 100644 final/test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll create mode 100644 final/test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll create mode 100644 final/test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll create mode 100644 final/test/CodeGen/X86/2010-03-04-Mul8Bug.ll create mode 100644 final/test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll create mode 100644 final/test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll create mode 100644 final/test/CodeGen/X86/2010-03-17-ISelBug.ll create mode 100644 final/test/CodeGen/X86/2010-04-06-SSEDomainFixCrash.ll create mode 100644 final/test/CodeGen/X86/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/X86/2010-04-08-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2010-04-13-AnalyzeBranchCrash.ll create mode 100644 final/test/CodeGen/X86/2010-04-21-CoalescerBug.ll create mode 100644 final/test/CodeGen/X86/2010-04-23-mmx-movdq2q.ll create mode 100644 final/test/CodeGen/X86/2010-04-29-CoalescerCrash.ll create mode 100644 final/test/CodeGen/X86/2010-04-30-LocalAlloc-LandingPad.ll create mode 100644 final/test/CodeGen/X86/2010-05-03-CoalescerSubRegClobber.ll create mode 100644 final/test/CodeGen/X86/2010-05-05-LocalAllocEarlyClobber.ll create mode 100644 final/test/CodeGen/X86/2010-05-06-LocalInlineAsmClobber.ll create mode 100644 final/test/CodeGen/X86/2010-05-07-ldconvert.ll create mode 100644 final/test/CodeGen/X86/2010-05-10-DAGCombinerBug.ll create mode 100644 final/test/CodeGen/X86/2010-05-12-FastAllocKills.ll create mode 100644 final/test/CodeGen/X86/2010-05-16-nosseconversion.ll create mode 100644 final/test/CodeGen/X86/2010-05-25-DotDebugLoc.ll create mode 100644 final/test/CodeGen/X86/2010-05-26-DotDebugLoc.ll create mode 100644 final/test/CodeGen/X86/2010-05-26-FP_TO_INT-crash.ll create mode 100644 final/test/CodeGen/X86/2010-05-28-Crash.ll create mode 100644 final/test/CodeGen/X86/2010-06-01-DeadArg-DbgInfo.ll create mode 100644 final/test/CodeGen/X86/2010-06-09-FastAllocRegisters.ll create mode 100644 final/test/CodeGen/X86/2010-06-14-fast-isel-fs-load.ll create mode 100644 final/test/CodeGen/X86/2010-06-15-FastAllocEarlyCLobber.ll create mode 100644 final/test/CodeGen/X86/2010-06-24-g-constraint-crash.ll create mode 100644 final/test/CodeGen/X86/2010-06-25-CoalescerSubRegDefDead.ll create mode 100644 final/test/CodeGen/X86/2010-06-25-asm-RA-crash.ll create mode 100644 final/test/CodeGen/X86/2010-06-28-DbgEntryPC.ll create mode 100644 final/test/CodeGen/X86/2010-06-28-FastAllocTiedOperand.ll create mode 100644 final/test/CodeGen/X86/2010-06-28-matched-g-constraint.ll create mode 100644 final/test/CodeGen/X86/2010-07-02-UnfoldBug.ll create mode 100644 final/test/CodeGen/X86/2010-07-02-asm-alignstack.ll create mode 100644 final/test/CodeGen/X86/2010-07-06-DbgCrash.ll create mode 100644 final/test/CodeGen/X86/2010-07-06-asm-RIP.ll create mode 100644 final/test/CodeGen/X86/2010-07-11-FPStackLoneUse.ll create mode 100644 final/test/CodeGen/X86/2010-07-13-indirectXconstraint.ll create mode 100644 final/test/CodeGen/X86/2010-07-15-Crash.ll create mode 100644 final/test/CodeGen/X86/2010-07-29-SetccSimplify.ll create mode 100644 final/test/CodeGen/X86/2010-08-04-MaskedSignedCompare.ll create mode 100644 final/test/CodeGen/X86/2010-08-04-MingWCrash.ll create mode 100644 final/test/CodeGen/X86/2010-08-04-StackVariable.ll create mode 100644 final/test/CodeGen/X86/2010-08-10-DbgConstant.ll create mode 100644 final/test/CodeGen/X86/2010-09-01-RemoveCopyByCommutingDef.ll create mode 100644 final/test/CodeGen/X86/2010-09-16-EmptyFilename.ll create mode 100644 final/test/CodeGen/X86/2010-09-16-asmcrash.ll create mode 100644 final/test/CodeGen/X86/2010-09-17-SideEffectsInChain.ll create mode 100644 final/test/CodeGen/X86/2010-09-30-CMOV-JumpTable-PHI.ll create mode 100644 final/test/CodeGen/X86/2010-10-08-cmpxchg8b.ll create mode 100644 final/test/CodeGen/X86/2010-11-02-DbgParameter.ll create mode 100644 final/test/CodeGen/X86/2010-11-09-MOVLPS.ll create mode 100644 final/test/CodeGen/X86/2010-11-18-SelectOfExtload.ll create mode 100644 final/test/CodeGen/X86/2010-12-02-MC-Set.ll create mode 100644 final/test/CodeGen/X86/2011-01-07-LegalizeTypesCrash.ll create mode 100644 final/test/CodeGen/X86/2011-01-10-DagCombineHang.ll create mode 100644 final/test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll create mode 100644 final/test/CodeGen/X86/2011-02-04-FastRegallocNoFP.ll create mode 100644 final/test/CodeGen/X86/2011-02-21-VirtRegRewriter-KillSubReg.ll create mode 100644 final/test/CodeGen/X86/2011-02-23-UnfoldBug.ll create mode 100644 final/test/CodeGen/X86/2011-02-27-Fpextend.ll create mode 100644 final/test/CodeGen/X86/2011-03-02-DAGCombiner.ll create mode 100644 final/test/CodeGen/X86/2011-03-09-Physreg-Coalescing.ll create mode 100644 final/test/CodeGen/X86/3addr-16bit.ll create mode 100644 final/test/CodeGen/X86/3addr-or.ll create mode 100644 final/test/CodeGen/X86/Atomics-32.ll create mode 100644 final/test/CodeGen/X86/Atomics-64.ll create mode 100644 final/test/CodeGen/X86/GC/alloc_loop.ll create mode 100644 final/test/CodeGen/X86/GC/argpromotion.ll create mode 100644 final/test/CodeGen/X86/GC/badreadproto.ll create mode 100644 final/test/CodeGen/X86/GC/badrootproto.ll create mode 100644 final/test/CodeGen/X86/GC/badwriteproto.ll create mode 100644 final/test/CodeGen/X86/GC/deadargelim.ll create mode 100644 final/test/CodeGen/X86/GC/dg.exp create mode 100644 final/test/CodeGen/X86/GC/fat.ll create mode 100644 final/test/CodeGen/X86/GC/inline.ll create mode 100644 final/test/CodeGen/X86/GC/inline2.ll create mode 100644 final/test/CodeGen/X86/GC/lower_gcroot.ll create mode 100644 final/test/CodeGen/X86/GC/outside.ll create mode 100644 final/test/CodeGen/X86/GC/simple_ocaml.ll create mode 100644 final/test/CodeGen/X86/MachineSink-CritEdge.ll create mode 100644 final/test/CodeGen/X86/MachineSink-PHIUse.ll create mode 100644 final/test/CodeGen/X86/SIMD/dg.exp create mode 100644 final/test/CodeGen/X86/SIMD/notvunpcklpd.ll create mode 100644 final/test/CodeGen/X86/SIMD/notvunpcklps.ll create mode 100644 final/test/CodeGen/X86/SIMD/vunpcklpd.ll create mode 100644 final/test/CodeGen/X86/SIMD/vunpcklps.ll create mode 100644 final/test/CodeGen/X86/SwitchLowering.ll create mode 100644 final/test/CodeGen/X86/abi-isel.ll create mode 100644 final/test/CodeGen/X86/add-of-carry.ll create mode 100644 final/test/CodeGen/X86/add.ll create mode 100644 final/test/CodeGen/X86/adde-carry.ll create mode 100644 final/test/CodeGen/X86/addr-label-difference.ll create mode 100644 final/test/CodeGen/X86/aliases.ll create mode 100644 final/test/CodeGen/X86/aligned-comm.ll create mode 100644 final/test/CodeGen/X86/alignment.ll create mode 100644 final/test/CodeGen/X86/all-ones-vector.ll create mode 100644 final/test/CodeGen/X86/alldiv-divdi3.ll create mode 100644 final/test/CodeGen/X86/alloca-align-rounding-32.ll create mode 100644 final/test/CodeGen/X86/alloca-align-rounding.ll create mode 100644 final/test/CodeGen/X86/and-or-fold.ll create mode 100644 final/test/CodeGen/X86/and-su.ll create mode 100644 final/test/CodeGen/X86/andimm8.ll create mode 100644 final/test/CodeGen/X86/anyext.ll create mode 100644 final/test/CodeGen/X86/apm.ll create mode 100644 final/test/CodeGen/X86/arg-cast.ll create mode 100644 final/test/CodeGen/X86/asm-block-labels.ll create mode 100644 final/test/CodeGen/X86/asm-global-imm.ll create mode 100644 final/test/CodeGen/X86/asm-indirect-mem.ll create mode 100644 final/test/CodeGen/X86/asm-modifier-P.ll create mode 100644 final/test/CodeGen/X86/asm-modifier.ll create mode 100644 final/test/CodeGen/X86/atomic_add.ll create mode 100644 final/test/CodeGen/X86/atomic_op.ll create mode 100644 final/test/CodeGen/X86/attribute-sections.ll create mode 100644 final/test/CodeGen/X86/avoid-lea-scale2.ll create mode 100644 final/test/CodeGen/X86/avoid-loop-align-2.ll create mode 100644 final/test/CodeGen/X86/avoid-loop-align.ll create mode 100644 final/test/CodeGen/X86/avx-128.ll create mode 100644 final/test/CodeGen/X86/avx-256.ll create mode 100644 final/test/CodeGen/X86/avx-intrinsics-x86.ll create mode 100644 final/test/CodeGen/X86/avx-intrinsics-x86_64.ll create mode 100644 final/test/CodeGen/X86/barrier-sse.ll create mode 100644 final/test/CodeGen/X86/barrier.ll create mode 100644 final/test/CodeGen/X86/bc-extract.ll create mode 100644 final/test/CodeGen/X86/bigstructret.ll create mode 100644 final/test/CodeGen/X86/bigstructret2.ll create mode 100644 final/test/CodeGen/X86/bit-test-shift.ll create mode 100644 final/test/CodeGen/X86/bitcast-int-to-vector.ll create mode 100644 final/test/CodeGen/X86/bitcast.ll create mode 100644 final/test/CodeGen/X86/bitcast2.ll create mode 100644 final/test/CodeGen/X86/br-fold.ll create mode 100644 final/test/CodeGen/X86/brcond.ll create mode 100644 final/test/CodeGen/X86/break-anti-dependencies.ll create mode 100644 final/test/CodeGen/X86/break-sse-dep.ll create mode 100644 final/test/CodeGen/X86/bss_pagealigned.ll create mode 100644 final/test/CodeGen/X86/bswap-inline-asm.ll create mode 100644 final/test/CodeGen/X86/bswap.ll create mode 100644 final/test/CodeGen/X86/bt.ll create mode 100644 final/test/CodeGen/X86/byval.ll create mode 100644 final/test/CodeGen/X86/byval2.ll create mode 100644 final/test/CodeGen/X86/byval3.ll create mode 100644 final/test/CodeGen/X86/byval4.ll create mode 100644 final/test/CodeGen/X86/byval5.ll create mode 100644 final/test/CodeGen/X86/byval6.ll create mode 100644 final/test/CodeGen/X86/byval7.ll create mode 100644 final/test/CodeGen/X86/call-imm.ll create mode 100644 final/test/CodeGen/X86/call-push.ll create mode 100644 final/test/CodeGen/X86/change-compare-stride-0.ll create mode 100644 final/test/CodeGen/X86/change-compare-stride-1.ll create mode 100644 final/test/CodeGen/X86/change-compare-stride-trickiness-0.ll create mode 100644 final/test/CodeGen/X86/change-compare-stride-trickiness-1.ll create mode 100644 final/test/CodeGen/X86/change-compare-stride-trickiness-2.ll create mode 100644 final/test/CodeGen/X86/clz.ll create mode 100644 final/test/CodeGen/X86/cmov.ll create mode 100644 final/test/CodeGen/X86/cmp.ll create mode 100644 final/test/CodeGen/X86/coalesce-esp.ll create mode 100644 final/test/CodeGen/X86/coalescer-commute1.ll create mode 100644 final/test/CodeGen/X86/coalescer-commute2.ll create mode 100644 final/test/CodeGen/X86/coalescer-commute3.ll create mode 100644 final/test/CodeGen/X86/coalescer-commute4.ll create mode 100644 final/test/CodeGen/X86/coalescer-commute5.ll create mode 100644 final/test/CodeGen/X86/coalescer-cross.ll create mode 100644 final/test/CodeGen/X86/coalescer-remat.ll create mode 100644 final/test/CodeGen/X86/code_placement.ll create mode 100644 final/test/CodeGen/X86/code_placement_eh.ll create mode 100644 final/test/CodeGen/X86/codegen-prepare-cast.ll create mode 100644 final/test/CodeGen/X86/codegen-prepare-extload.ll create mode 100644 final/test/CodeGen/X86/codemodel.ll create mode 100644 final/test/CodeGen/X86/combine-lds.ll create mode 100644 final/test/CodeGen/X86/combiner-aa-0.ll create mode 100644 final/test/CodeGen/X86/combiner-aa-1.ll create mode 100644 final/test/CodeGen/X86/commute-intrinsic.ll create mode 100644 final/test/CodeGen/X86/commute-two-addr.ll create mode 100644 final/test/CodeGen/X86/compare-add.ll create mode 100644 final/test/CodeGen/X86/compare-inf.ll create mode 100644 final/test/CodeGen/X86/compare_folding.ll create mode 100644 final/test/CodeGen/X86/compiler_used.ll create mode 100644 final/test/CodeGen/X86/complex-asm.ll create mode 100644 final/test/CodeGen/X86/complex-fca.ll create mode 100644 final/test/CodeGen/X86/conditional-indecrement.ll create mode 100644 final/test/CodeGen/X86/constant-pool-remat-0.ll create mode 100644 final/test/CodeGen/X86/constant-pool-sharing.ll create mode 100644 final/test/CodeGen/X86/constpool.ll create mode 100644 final/test/CodeGen/X86/convert-2-addr-3-addr-inc64.ll create mode 100644 final/test/CodeGen/X86/copysign-zero.ll create mode 100644 final/test/CodeGen/X86/crash-O0.ll create mode 100644 final/test/CodeGen/X86/crash.ll create mode 100644 final/test/CodeGen/X86/critical-edge-split-2.ll create mode 100644 final/test/CodeGen/X86/cstring.ll create mode 100644 final/test/CodeGen/X86/ctpop-combine.ll create mode 100644 final/test/CodeGen/X86/dag-rauw-cse.ll create mode 100644 final/test/CodeGen/X86/dagcombine-buildvector.ll create mode 100644 final/test/CodeGen/X86/dagcombine-cse.ll create mode 100644 final/test/CodeGen/X86/darwin-bzero.ll create mode 100644 final/test/CodeGen/X86/darwin-no-dead-strip.ll create mode 100644 final/test/CodeGen/X86/darwin-quote.ll create mode 100644 final/test/CodeGen/X86/darwin-stub.ll create mode 100644 final/test/CodeGen/X86/dbg-byval-parameter.ll create mode 100644 final/test/CodeGen/X86/dbg-merge-loc-entry.ll create mode 100644 final/test/CodeGen/X86/dbg-value-inlined-parameter.ll create mode 100644 final/test/CodeGen/X86/dbg-value-location.ll create mode 100644 final/test/CodeGen/X86/dbg-value-range.ll create mode 100644 final/test/CodeGen/X86/dg.exp create mode 100644 final/test/CodeGen/X86/discontiguous-loops.ll create mode 100644 final/test/CodeGen/X86/divide-by-constant.ll create mode 100644 final/test/CodeGen/X86/divrem.ll create mode 100644 final/test/CodeGen/X86/dll-linkage.ll create mode 100644 final/test/CodeGen/X86/dllexport.ll create mode 100644 final/test/CodeGen/X86/dollar-name.ll create mode 100644 final/test/CodeGen/X86/dyn-stackalloc.ll create mode 100644 final/test/CodeGen/X86/empty-functions.ll create mode 100644 final/test/CodeGen/X86/empty-struct-return-type.ll create mode 100644 final/test/CodeGen/X86/epilogue.ll create mode 100644 final/test/CodeGen/X86/extend.ll create mode 100644 final/test/CodeGen/X86/extern_weak.ll create mode 100644 final/test/CodeGen/X86/extmul128.ll create mode 100644 final/test/CodeGen/X86/extmul64.ll create mode 100644 final/test/CodeGen/X86/extract-combine.ll create mode 100644 final/test/CodeGen/X86/extract-extract.ll create mode 100644 final/test/CodeGen/X86/extractelement-from-arg.ll create mode 100644 final/test/CodeGen/X86/extractelement-load.ll create mode 100644 final/test/CodeGen/X86/extractelement-shuffle.ll create mode 100644 final/test/CodeGen/X86/extractps.ll create mode 100644 final/test/CodeGen/X86/fabs.ll create mode 100644 final/test/CodeGen/X86/fast-cc-callee-pops.ll create mode 100644 final/test/CodeGen/X86/fast-cc-merge-stack-adj.ll create mode 100644 final/test/CodeGen/X86/fast-cc-pass-in-regs.ll create mode 100644 final/test/CodeGen/X86/fast-isel-atomic.ll create mode 100644 final/test/CodeGen/X86/fast-isel-avoid-unnecessary-pic-base.ll create mode 100644 final/test/CodeGen/X86/fast-isel-bail.ll create mode 100644 final/test/CodeGen/X86/fast-isel-bc.ll create mode 100644 final/test/CodeGen/X86/fast-isel-call.ll create mode 100644 final/test/CodeGen/X86/fast-isel-cmp-branch.ll create mode 100644 final/test/CodeGen/X86/fast-isel-constpool.ll create mode 100644 final/test/CodeGen/X86/fast-isel-fneg.ll create mode 100644 final/test/CodeGen/X86/fast-isel-gep.ll create mode 100644 final/test/CodeGen/X86/fast-isel-gv.ll create mode 100644 final/test/CodeGen/X86/fast-isel-i1.ll create mode 100644 final/test/CodeGen/X86/fast-isel-mem.ll create mode 100644 final/test/CodeGen/X86/fast-isel-shift-imm.ll create mode 100644 final/test/CodeGen/X86/fast-isel-tailcall.ll create mode 100644 final/test/CodeGen/X86/fast-isel-tls.ll create mode 100644 final/test/CodeGen/X86/fast-isel-x86.ll create mode 100644 final/test/CodeGen/X86/fast-isel.ll create mode 100644 final/test/CodeGen/X86/fastcall-correct-mangling.ll create mode 100644 final/test/CodeGen/X86/fastcc-2.ll create mode 100644 final/test/CodeGen/X86/fastcc-byval.ll create mode 100644 final/test/CodeGen/X86/fastcc-sret.ll create mode 100644 final/test/CodeGen/X86/fastcc.ll create mode 100644 final/test/CodeGen/X86/fastcc3struct.ll create mode 100644 final/test/CodeGen/X86/field-extract-use-trunc.ll create mode 100644 final/test/CodeGen/X86/fildll.ll create mode 100644 final/test/CodeGen/X86/fltused.ll create mode 100644 final/test/CodeGen/X86/fmul-zero.ll create mode 100644 final/test/CodeGen/X86/fold-add.ll create mode 100644 final/test/CodeGen/X86/fold-and-shift.ll create mode 100644 final/test/CodeGen/X86/fold-call-2.ll create mode 100644 final/test/CodeGen/X86/fold-call-3.ll create mode 100644 final/test/CodeGen/X86/fold-call.ll create mode 100644 final/test/CodeGen/X86/fold-imm.ll create mode 100644 final/test/CodeGen/X86/fold-load.ll create mode 100644 final/test/CodeGen/X86/fold-mul-lohi.ll create mode 100644 final/test/CodeGen/X86/fold-pcmpeqd-0.ll create mode 100644 final/test/CodeGen/X86/fold-pcmpeqd-1.ll create mode 100644 final/test/CodeGen/X86/fold-pcmpeqd-2.ll create mode 100644 final/test/CodeGen/X86/fold-sext-trunc.ll create mode 100644 final/test/CodeGen/X86/force-align-stack.ll create mode 100644 final/test/CodeGen/X86/fp-elim.ll create mode 100644 final/test/CodeGen/X86/fp-immediate-shorten.ll create mode 100644 final/test/CodeGen/X86/fp-in-intregs.ll create mode 100644 final/test/CodeGen/X86/fp-stack-2results.ll create mode 100644 final/test/CodeGen/X86/fp-stack-O0-crash.ll create mode 100644 final/test/CodeGen/X86/fp-stack-compare.ll create mode 100644 final/test/CodeGen/X86/fp-stack-direct-ret.ll create mode 100644 final/test/CodeGen/X86/fp-stack-ret-conv.ll create mode 100644 final/test/CodeGen/X86/fp-stack-ret-store.ll create mode 100644 final/test/CodeGen/X86/fp-stack-ret.ll create mode 100644 final/test/CodeGen/X86/fp-stack-retcopy.ll create mode 100644 final/test/CodeGen/X86/fp-stack-set-st1.ll create mode 100644 final/test/CodeGen/X86/fp-stack.ll create mode 100644 final/test/CodeGen/X86/fp2sint.ll create mode 100644 final/test/CodeGen/X86/fp_constant_op.ll create mode 100644 final/test/CodeGen/X86/fp_load_cast_fold.ll create mode 100644 final/test/CodeGen/X86/fp_load_fold.ll create mode 100644 final/test/CodeGen/X86/fsxor-alignment.ll create mode 100644 final/test/CodeGen/X86/full-lsr.ll create mode 100644 final/test/CodeGen/X86/ga-offset.ll create mode 100644 final/test/CodeGen/X86/gather-addresses.ll create mode 100644 final/test/CodeGen/X86/ghc-cc.ll create mode 100644 final/test/CodeGen/X86/ghc-cc64.ll create mode 100644 final/test/CodeGen/X86/global-sections-tls.ll create mode 100644 final/test/CodeGen/X86/global-sections.ll create mode 100644 final/test/CodeGen/X86/h-register-addressing-32.ll create mode 100644 final/test/CodeGen/X86/h-register-addressing-64.ll create mode 100644 final/test/CodeGen/X86/h-register-store.ll create mode 100644 final/test/CodeGen/X86/h-registers-0.ll create mode 100644 final/test/CodeGen/X86/h-registers-1.ll create mode 100644 final/test/CodeGen/X86/h-registers-2.ll create mode 100644 final/test/CodeGen/X86/h-registers-3.ll create mode 100644 final/test/CodeGen/X86/hidden-vis-2.ll create mode 100644 final/test/CodeGen/X86/hidden-vis-3.ll create mode 100644 final/test/CodeGen/X86/hidden-vis-4.ll create mode 100644 final/test/CodeGen/X86/hidden-vis-pic.ll create mode 100644 final/test/CodeGen/X86/hidden-vis.ll create mode 100644 final/test/CodeGen/X86/i128-and-beyond.ll create mode 100644 final/test/CodeGen/X86/i128-immediate.ll create mode 100644 final/test/CodeGen/X86/i128-mul.ll create mode 100644 final/test/CodeGen/X86/i128-ret.ll create mode 100644 final/test/CodeGen/X86/i256-add.ll create mode 100644 final/test/CodeGen/X86/i2k.ll create mode 100644 final/test/CodeGen/X86/i64-mem-copy.ll create mode 100644 final/test/CodeGen/X86/iabs.ll create mode 100644 final/test/CodeGen/X86/illegal-insert.ll create mode 100644 final/test/CodeGen/X86/illegal-vector-args-return.ll create mode 100644 final/test/CodeGen/X86/imul-lea-2.ll create mode 100644 final/test/CodeGen/X86/imul-lea.ll create mode 100644 final/test/CodeGen/X86/inline-asm-2addr.ll create mode 100644 final/test/CodeGen/X86/inline-asm-R-constraint.ll create mode 100644 final/test/CodeGen/X86/inline-asm-flag-clobber.ll create mode 100644 final/test/CodeGen/X86/inline-asm-fpstack.ll create mode 100644 final/test/CodeGen/X86/inline-asm-fpstack2.ll create mode 100644 final/test/CodeGen/X86/inline-asm-fpstack3.ll create mode 100644 final/test/CodeGen/X86/inline-asm-fpstack4.ll create mode 100644 final/test/CodeGen/X86/inline-asm-fpstack5.ll create mode 100644 final/test/CodeGen/X86/inline-asm-h.ll create mode 100644 final/test/CodeGen/X86/inline-asm-modifier-n.ll create mode 100644 final/test/CodeGen/X86/inline-asm-mrv.ll create mode 100644 final/test/CodeGen/X86/inline-asm-out-regs.ll create mode 100644 final/test/CodeGen/X86/inline-asm-pic.ll create mode 100644 final/test/CodeGen/X86/inline-asm-ptr-cast.ll create mode 100644 final/test/CodeGen/X86/inline-asm-q-regs.ll create mode 100644 final/test/CodeGen/X86/inline-asm-tied.ll create mode 100644 final/test/CodeGen/X86/inline-asm-x-scalar.ll create mode 100644 final/test/CodeGen/X86/inline-asm.ll create mode 100644 final/test/CodeGen/X86/ins_subreg_coalesce-1.ll create mode 100644 final/test/CodeGen/X86/ins_subreg_coalesce-2.ll create mode 100644 final/test/CodeGen/X86/ins_subreg_coalesce-3.ll create mode 100644 final/test/CodeGen/X86/insert-positions.ll create mode 100644 final/test/CodeGen/X86/insertelement-copytoregs.ll create mode 100644 final/test/CodeGen/X86/insertelement-legalize.ll create mode 100644 final/test/CodeGen/X86/int-intrinsic.ll create mode 100644 final/test/CodeGen/X86/invalid-shift-immediate.ll create mode 100644 final/test/CodeGen/X86/isel-sink.ll create mode 100644 final/test/CodeGen/X86/isel-sink2.ll create mode 100644 final/test/CodeGen/X86/isel-sink3.ll create mode 100644 final/test/CodeGen/X86/isint.ll create mode 100644 final/test/CodeGen/X86/isnan.ll create mode 100644 final/test/CodeGen/X86/isnan2.ll create mode 100644 final/test/CodeGen/X86/ispositive.ll create mode 100644 final/test/CodeGen/X86/iv-users-in-other-loops.ll create mode 100644 final/test/CodeGen/X86/jump_sign.ll create mode 100644 final/test/CodeGen/X86/label-redefinition.ll create mode 100644 final/test/CodeGen/X86/large-gep-scale.ll create mode 100644 final/test/CodeGen/X86/ldzero.ll create mode 100644 final/test/CodeGen/X86/lea-2.ll create mode 100644 final/test/CodeGen/X86/lea-3.ll create mode 100644 final/test/CodeGen/X86/lea-4.ll create mode 100644 final/test/CodeGen/X86/lea-recursion.ll create mode 100644 final/test/CodeGen/X86/lea.ll create mode 100644 final/test/CodeGen/X86/leaf-fp-elim.ll create mode 100644 final/test/CodeGen/X86/legalize-fmp-oeq-vector-select.ll create mode 100644 final/test/CodeGen/X86/legalize-sub-zero-2.ll create mode 100644 final/test/CodeGen/X86/legalize-sub-zero.ll create mode 100644 final/test/CodeGen/X86/legalizedag_vec.ll create mode 100644 final/test/CodeGen/X86/lfence.ll create mode 100644 final/test/CodeGen/X86/licm-nested.ll create mode 100644 final/test/CodeGen/X86/licm-symbol.ll create mode 100644 final/test/CodeGen/X86/limited-prec.ll create mode 100644 final/test/CodeGen/X86/live-out-reg-info.ll create mode 100644 final/test/CodeGen/X86/liveness-local-regalloc.ll create mode 100644 final/test/CodeGen/X86/lock-inst-encoding.ll create mode 100644 final/test/CodeGen/X86/long-setcc.ll create mode 100644 final/test/CodeGen/X86/longlong-deadload.ll create mode 100644 final/test/CodeGen/X86/loop-blocks.ll create mode 100644 final/test/CodeGen/X86/loop-hoist.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce-2.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce-3.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce2.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce3.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce4.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce5.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce6.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce7.ll create mode 100644 final/test/CodeGen/X86/loop-strength-reduce8.ll create mode 100644 final/test/CodeGen/X86/lsr-delayed-fold.ll create mode 100644 final/test/CodeGen/X86/lsr-i386.ll create mode 100644 final/test/CodeGen/X86/lsr-interesting-step.ll create mode 100644 final/test/CodeGen/X86/lsr-loop-exit-cond.ll create mode 100644 final/test/CodeGen/X86/lsr-negative-stride.ll create mode 100644 final/test/CodeGen/X86/lsr-nonaffine.ll create mode 100644 final/test/CodeGen/X86/lsr-normalization.ll create mode 100644 final/test/CodeGen/X86/lsr-overflow.ll create mode 100644 final/test/CodeGen/X86/lsr-quadratic-expand.ll create mode 100644 final/test/CodeGen/X86/lsr-redundant-addressing.ll create mode 100644 final/test/CodeGen/X86/lsr-reuse-trunc.ll create mode 100644 final/test/CodeGen/X86/lsr-reuse.ll create mode 100644 final/test/CodeGen/X86/lsr-sort.ll create mode 100644 final/test/CodeGen/X86/lsr-static-addr.ll create mode 100644 final/test/CodeGen/X86/lsr-wrap.ll create mode 100644 final/test/CodeGen/X86/machine-cse.ll create mode 100644 final/test/CodeGen/X86/masked-iv-safe.ll create mode 100644 final/test/CodeGen/X86/masked-iv-unsafe.ll create mode 100644 final/test/CodeGen/X86/maskmovdqu.ll create mode 100644 final/test/CodeGen/X86/mcinst-lowering-cmp0.ll create mode 100644 final/test/CodeGen/X86/mcinst-lowering.ll create mode 100644 final/test/CodeGen/X86/memcmp.ll create mode 100644 final/test/CodeGen/X86/memcpy-2.ll create mode 100644 final/test/CodeGen/X86/memcpy.ll create mode 100644 final/test/CodeGen/X86/memmove-4.ll create mode 100644 final/test/CodeGen/X86/memset-2.ll create mode 100644 final/test/CodeGen/X86/memset-3.ll create mode 100644 final/test/CodeGen/X86/memset.ll create mode 100644 final/test/CodeGen/X86/memset64-on-x86-32.ll create mode 100644 final/test/CodeGen/X86/mfence.ll create mode 100644 final/test/CodeGen/X86/mingw-alloca.ll create mode 100644 final/test/CodeGen/X86/misaligned-memset.ll create mode 100644 final/test/CodeGen/X86/mmx-arg-passing.ll create mode 100644 final/test/CodeGen/X86/mmx-arg-passing2.ll create mode 100644 final/test/CodeGen/X86/mmx-arith.ll create mode 100644 final/test/CodeGen/X86/mmx-bitcast-to-i64.ll create mode 100644 final/test/CodeGen/X86/mmx-builtins.ll create mode 100644 final/test/CodeGen/X86/mmx-copy-gprs.ll create mode 100644 final/test/CodeGen/X86/mmx-emms.ll create mode 100644 final/test/CodeGen/X86/mmx-insert-element.ll create mode 100644 final/test/CodeGen/X86/mmx-pinsrw.ll create mode 100644 final/test/CodeGen/X86/mmx-punpckhdq.ll create mode 100644 final/test/CodeGen/X86/mmx-s2v.ll create mode 100644 final/test/CodeGen/X86/mmx-shift.ll create mode 100644 final/test/CodeGen/X86/mmx-shuffle.ll create mode 100644 final/test/CodeGen/X86/mmx-vzmovl-2.ll create mode 100644 final/test/CodeGen/X86/mmx-vzmovl.ll create mode 100644 final/test/CodeGen/X86/movfs.ll create mode 100644 final/test/CodeGen/X86/movgs.ll create mode 100644 final/test/CodeGen/X86/mul-legalize.ll create mode 100644 final/test/CodeGen/X86/mul-remat.ll create mode 100644 final/test/CodeGen/X86/mul-shift-reassoc.ll create mode 100644 final/test/CodeGen/X86/mul128.ll create mode 100644 final/test/CodeGen/X86/mul64.ll create mode 100644 final/test/CodeGen/X86/mult-alt-generic-i686.ll create mode 100644 final/test/CodeGen/X86/mult-alt-generic-x86_64.ll create mode 100644 final/test/CodeGen/X86/mult-alt-x86.ll create mode 100644 final/test/CodeGen/X86/multiple-loop-post-inc.ll create mode 100644 final/test/CodeGen/X86/multiple-return-values-cross-block.ll create mode 100644 final/test/CodeGen/X86/multiple-return-values.ll create mode 100644 final/test/CodeGen/X86/nancvt.ll create mode 100644 final/test/CodeGen/X86/narrow-shl-load.ll create mode 100644 final/test/CodeGen/X86/narrow_op-1.ll create mode 100644 final/test/CodeGen/X86/neg-shl-add.ll create mode 100644 final/test/CodeGen/X86/neg_fp.ll create mode 100644 final/test/CodeGen/X86/negate-add-zero.ll create mode 100644 final/test/CodeGen/X86/negative-sin.ll create mode 100644 final/test/CodeGen/X86/negative-stride-fptosi-user.ll create mode 100644 final/test/CodeGen/X86/negative-subscript.ll create mode 100644 final/test/CodeGen/X86/negative_zero.ll create mode 100644 final/test/CodeGen/X86/nobt.ll create mode 100644 final/test/CodeGen/X86/nofence.ll create mode 100644 final/test/CodeGen/X86/nosse-error1.ll create mode 100644 final/test/CodeGen/X86/nosse-error2.ll create mode 100644 final/test/CodeGen/X86/nosse-varargs.ll create mode 100644 final/test/CodeGen/X86/object-size.ll create mode 100644 final/test/CodeGen/X86/opt-ext-uses.ll create mode 100644 final/test/CodeGen/X86/optimize-max-0.ll create mode 100644 final/test/CodeGen/X86/optimize-max-1.ll create mode 100644 final/test/CodeGen/X86/optimize-max-2.ll create mode 100644 final/test/CodeGen/X86/optimize-max-3.ll create mode 100644 final/test/CodeGen/X86/or-address.ll create mode 100644 final/test/CodeGen/X86/or-branch.ll create mode 100644 final/test/CodeGen/X86/overlap-shift.ll create mode 100644 final/test/CodeGen/X86/packed_struct.ll create mode 100644 final/test/CodeGen/X86/palignr-2.ll create mode 100644 final/test/CodeGen/X86/palignr.ll create mode 100644 final/test/CodeGen/X86/peep-test-0.ll create mode 100644 final/test/CodeGen/X86/peep-test-1.ll create mode 100644 final/test/CodeGen/X86/peep-test-2.ll create mode 100644 final/test/CodeGen/X86/peep-test-3.ll create mode 100644 final/test/CodeGen/X86/peep-vector-extract-concat.ll create mode 100644 final/test/CodeGen/X86/peep-vector-extract-insert.ll create mode 100644 final/test/CodeGen/X86/personality.ll create mode 100644 final/test/CodeGen/X86/phi-bit-propagation.ll create mode 100644 final/test/CodeGen/X86/phi-immediate-factoring.ll create mode 100644 final/test/CodeGen/X86/phys-reg-local-regalloc.ll create mode 100644 final/test/CodeGen/X86/phys_subreg_coalesce-2.ll create mode 100644 final/test/CodeGen/X86/phys_subreg_coalesce-3.ll create mode 100644 final/test/CodeGen/X86/phys_subreg_coalesce.ll create mode 100644 final/test/CodeGen/X86/pic-load-remat.ll create mode 100644 final/test/CodeGen/X86/pic.ll create mode 100644 final/test/CodeGen/X86/pic_jumptable.ll create mode 100644 final/test/CodeGen/X86/pmul.ll create mode 100644 final/test/CodeGen/X86/pmulld.ll create mode 100644 final/test/CodeGen/X86/popcnt.ll create mode 100644 final/test/CodeGen/X86/postalloc-coalescing.ll create mode 100644 final/test/CodeGen/X86/postra-licm.ll create mode 100644 final/test/CodeGen/X86/powi.ll create mode 100644 final/test/CodeGen/X86/pr1462.ll create mode 100644 final/test/CodeGen/X86/pr1489.ll create mode 100644 final/test/CodeGen/X86/pr1505.ll create mode 100644 final/test/CodeGen/X86/pr1505b.ll create mode 100644 final/test/CodeGen/X86/pr2177.ll create mode 100644 final/test/CodeGen/X86/pr2182.ll create mode 100644 final/test/CodeGen/X86/pr2326.ll create mode 100644 final/test/CodeGen/X86/pr2623.ll create mode 100644 final/test/CodeGen/X86/pr2656.ll create mode 100644 final/test/CodeGen/X86/pr2659.ll create mode 100644 final/test/CodeGen/X86/pr2849.ll create mode 100644 final/test/CodeGen/X86/pr2924.ll create mode 100644 final/test/CodeGen/X86/pr2982.ll create mode 100644 final/test/CodeGen/X86/pr3154.ll create mode 100644 final/test/CodeGen/X86/pr3216.ll create mode 100644 final/test/CodeGen/X86/pr3241.ll create mode 100644 final/test/CodeGen/X86/pr3243.ll create mode 100644 final/test/CodeGen/X86/pr3244.ll create mode 100644 final/test/CodeGen/X86/pr3250.ll create mode 100644 final/test/CodeGen/X86/pr3317.ll create mode 100644 final/test/CodeGen/X86/pr3366.ll create mode 100644 final/test/CodeGen/X86/pr3457.ll create mode 100644 final/test/CodeGen/X86/pr3495-2.ll create mode 100644 final/test/CodeGen/X86/pr3495.ll create mode 100644 final/test/CodeGen/X86/pr3522.ll create mode 100644 final/test/CodeGen/X86/pr7882.ll create mode 100644 final/test/CodeGen/X86/pr9127.ll create mode 100644 final/test/CodeGen/X86/pre-split1.ll create mode 100644 final/test/CodeGen/X86/pre-split10.ll create mode 100644 final/test/CodeGen/X86/pre-split11.ll create mode 100644 final/test/CodeGen/X86/pre-split2.ll create mode 100644 final/test/CodeGen/X86/pre-split3.ll create mode 100644 final/test/CodeGen/X86/pre-split4.ll create mode 100644 final/test/CodeGen/X86/pre-split5.ll create mode 100644 final/test/CodeGen/X86/pre-split6.ll create mode 100644 final/test/CodeGen/X86/pre-split7.ll create mode 100644 final/test/CodeGen/X86/pre-split8.ll create mode 100644 final/test/CodeGen/X86/pre-split9.ll create mode 100644 final/test/CodeGen/X86/prefetch.ll create mode 100644 final/test/CodeGen/X86/private-2.ll create mode 100644 final/test/CodeGen/X86/private.ll create mode 100644 final/test/CodeGen/X86/promote-assert-zext.ll create mode 100644 final/test/CodeGen/X86/promote-i16.ll create mode 100644 final/test/CodeGen/X86/ptrtoint-constexpr.ll create mode 100644 final/test/CodeGen/X86/rdtsc.ll create mode 100644 final/test/CodeGen/X86/red-zone.ll create mode 100644 final/test/CodeGen/X86/red-zone2.ll create mode 100644 final/test/CodeGen/X86/regpressure.ll create mode 100644 final/test/CodeGen/X86/rem-2.ll create mode 100644 final/test/CodeGen/X86/rem.ll create mode 100644 final/test/CodeGen/X86/remat-constant.ll create mode 100644 final/test/CodeGen/X86/remat-mov-0.ll create mode 100644 final/test/CodeGen/X86/remat-scalar-zero.ll create mode 100644 final/test/CodeGen/X86/ret-addr.ll create mode 100644 final/test/CodeGen/X86/ret-i64-0.ll create mode 100644 final/test/CodeGen/X86/ret-mmx.ll create mode 100644 final/test/CodeGen/X86/rip-rel-address.ll create mode 100644 final/test/CodeGen/X86/rodata-relocs.ll create mode 100644 final/test/CodeGen/X86/rot16.ll create mode 100644 final/test/CodeGen/X86/rot32.ll create mode 100644 final/test/CodeGen/X86/rot64.ll create mode 100644 final/test/CodeGen/X86/rotate.ll create mode 100644 final/test/CodeGen/X86/rotate2.ll create mode 100644 final/test/CodeGen/X86/scalar-extract.ll create mode 100644 final/test/CodeGen/X86/scalar-min-max-fill-operand.ll create mode 100644 final/test/CodeGen/X86/scalar_sse_minmax.ll create mode 100644 final/test/CodeGen/X86/scalar_widen_div.ll create mode 100644 final/test/CodeGen/X86/scalarize-bitcast.ll create mode 100644 final/test/CodeGen/X86/scev-interchange.ll create mode 100644 final/test/CodeGen/X86/select.ll create mode 100644 final/test/CodeGen/X86/setcc.ll create mode 100644 final/test/CodeGen/X86/setoeq.ll create mode 100644 final/test/CodeGen/X86/setuge.ll create mode 100644 final/test/CodeGen/X86/sext-i1.ll create mode 100644 final/test/CodeGen/X86/sext-load.ll create mode 100644 final/test/CodeGen/X86/sext-ret-val.ll create mode 100644 final/test/CodeGen/X86/sext-subreg.ll create mode 100644 final/test/CodeGen/X86/sext-trunc.ll create mode 100644 final/test/CodeGen/X86/sfence.ll create mode 100644 final/test/CodeGen/X86/shift-and.ll create mode 100644 final/test/CodeGen/X86/shift-coalesce.ll create mode 100644 final/test/CodeGen/X86/shift-codegen.ll create mode 100644 final/test/CodeGen/X86/shift-combine.ll create mode 100644 final/test/CodeGen/X86/shift-double.ll create mode 100644 final/test/CodeGen/X86/shift-folding.ll create mode 100644 final/test/CodeGen/X86/shift-i128.ll create mode 100644 final/test/CodeGen/X86/shift-i256.ll create mode 100644 final/test/CodeGen/X86/shift-one.ll create mode 100644 final/test/CodeGen/X86/shift-parts.ll create mode 100644 final/test/CodeGen/X86/shl-anyext.ll create mode 100644 final/test/CodeGen/X86/shl_elim.ll create mode 100644 final/test/CodeGen/X86/shrink-fp-const1.ll create mode 100644 final/test/CodeGen/X86/shrink-fp-const2.ll create mode 100644 final/test/CodeGen/X86/sibcall-2.ll create mode 100644 final/test/CodeGen/X86/sibcall-3.ll create mode 100644 final/test/CodeGen/X86/sibcall-4.ll create mode 100644 final/test/CodeGen/X86/sibcall-5.ll create mode 100644 final/test/CodeGen/X86/sibcall.ll create mode 100644 final/test/CodeGen/X86/sincos.ll create mode 100644 final/test/CodeGen/X86/sink-hoist.ll create mode 100644 final/test/CodeGen/X86/small-byval-memcpy.ll create mode 100644 final/test/CodeGen/X86/smul-with-overflow-2.ll create mode 100644 final/test/CodeGen/X86/smul-with-overflow-3.ll create mode 100644 final/test/CodeGen/X86/smul-with-overflow.ll create mode 100644 final/test/CodeGen/X86/soft-fp.ll create mode 100644 final/test/CodeGen/X86/splat-scalar-load.ll create mode 100644 final/test/CodeGen/X86/split-eh-lpad-edges.ll create mode 100644 final/test/CodeGen/X86/split-vector-rem.ll create mode 100644 final/test/CodeGen/X86/sret.ll create mode 100644 final/test/CodeGen/X86/sse-align-0.ll create mode 100644 final/test/CodeGen/X86/sse-align-1.ll create mode 100644 final/test/CodeGen/X86/sse-align-10.ll create mode 100644 final/test/CodeGen/X86/sse-align-11.ll create mode 100644 final/test/CodeGen/X86/sse-align-12.ll create mode 100644 final/test/CodeGen/X86/sse-align-2.ll create mode 100644 final/test/CodeGen/X86/sse-align-3.ll create mode 100644 final/test/CodeGen/X86/sse-align-4.ll create mode 100644 final/test/CodeGen/X86/sse-align-5.ll create mode 100644 final/test/CodeGen/X86/sse-align-6.ll create mode 100644 final/test/CodeGen/X86/sse-align-7.ll create mode 100644 final/test/CodeGen/X86/sse-align-8.ll create mode 100644 final/test/CodeGen/X86/sse-align-9.ll create mode 100644 final/test/CodeGen/X86/sse-commute.ll create mode 100644 final/test/CodeGen/X86/sse-fcopysign.ll create mode 100644 final/test/CodeGen/X86/sse-load-ret.ll create mode 100644 final/test/CodeGen/X86/sse-minmax.ll create mode 100644 final/test/CodeGen/X86/sse-varargs.ll create mode 100644 final/test/CodeGen/X86/sse1.ll create mode 100644 final/test/CodeGen/X86/sse2.ll create mode 100644 final/test/CodeGen/X86/sse3.ll create mode 100644 final/test/CodeGen/X86/sse41.ll create mode 100644 final/test/CodeGen/X86/sse42.ll create mode 100644 final/test/CodeGen/X86/sse_reload_fold.ll create mode 100644 final/test/CodeGen/X86/stack-align.ll create mode 100644 final/test/CodeGen/X86/stack-protector-linux.ll create mode 100644 final/test/CodeGen/X86/stdarg.ll create mode 100644 final/test/CodeGen/X86/stdcall-notailcall.ll create mode 100644 final/test/CodeGen/X86/stdcall.ll create mode 100644 final/test/CodeGen/X86/store-empty-member.ll create mode 100644 final/test/CodeGen/X86/store-fp-constant.ll create mode 100644 final/test/CodeGen/X86/store-global-address.ll create mode 100644 final/test/CodeGen/X86/store-narrow.ll create mode 100644 final/test/CodeGen/X86/store_op_load_fold.ll create mode 100644 final/test/CodeGen/X86/store_op_load_fold2.ll create mode 100644 final/test/CodeGen/X86/storetrunc-fp.ll create mode 100644 final/test/CodeGen/X86/stride-nine-with-base-reg.ll create mode 100644 final/test/CodeGen/X86/stride-reuse.ll create mode 100644 final/test/CodeGen/X86/sub-with-overflow.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-0.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-1.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-2.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-3.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-4.ll create mode 100644 final/test/CodeGen/X86/subreg-to-reg-6.ll create mode 100644 final/test/CodeGen/X86/switch-bt.ll create mode 100644 final/test/CodeGen/X86/switch-crit-edge-constant.ll create mode 100644 final/test/CodeGen/X86/switch-or.ll create mode 100644 final/test/CodeGen/X86/switch-zextload.ll create mode 100644 final/test/CodeGen/X86/swizzle.ll create mode 100644 final/test/CodeGen/X86/tail-opts.ll create mode 100644 final/test/CodeGen/X86/tailcall-fastisel.ll create mode 100644 final/test/CodeGen/X86/tailcall-i1.ll create mode 100644 final/test/CodeGen/X86/tailcall-largecode.ll create mode 100644 final/test/CodeGen/X86/tailcall-returndup-void.ll create mode 100644 final/test/CodeGen/X86/tailcall-ri64.ll create mode 100644 final/test/CodeGen/X86/tailcall-stackalign.ll create mode 100644 final/test/CodeGen/X86/tailcall-structret.ll create mode 100644 final/test/CodeGen/X86/tailcall-void.ll create mode 100644 final/test/CodeGen/X86/tailcall1.ll create mode 100644 final/test/CodeGen/X86/tailcallbyval.ll create mode 100644 final/test/CodeGen/X86/tailcallbyval64.ll create mode 100644 final/test/CodeGen/X86/tailcallfp.ll create mode 100644 final/test/CodeGen/X86/tailcallfp2.ll create mode 100644 final/test/CodeGen/X86/tailcallpic1.ll create mode 100644 final/test/CodeGen/X86/tailcallpic2.ll create mode 100644 final/test/CodeGen/X86/tailcallstack64.ll create mode 100644 final/test/CodeGen/X86/test-nofold.ll create mode 100644 final/test/CodeGen/X86/test-shrink-bug.ll create mode 100644 final/test/CodeGen/X86/test-shrink.ll create mode 100644 final/test/CodeGen/X86/testl-commute.ll create mode 100644 final/test/CodeGen/X86/tls-pic.ll create mode 100644 final/test/CodeGen/X86/tls1.ll create mode 100644 final/test/CodeGen/X86/tls10.ll create mode 100644 final/test/CodeGen/X86/tls11.ll create mode 100644 final/test/CodeGen/X86/tls12.ll create mode 100644 final/test/CodeGen/X86/tls13.ll create mode 100644 final/test/CodeGen/X86/tls14.ll create mode 100644 final/test/CodeGen/X86/tls15.ll create mode 100644 final/test/CodeGen/X86/tls2.ll create mode 100644 final/test/CodeGen/X86/tls3.ll create mode 100644 final/test/CodeGen/X86/tls4.ll create mode 100644 final/test/CodeGen/X86/tls5.ll create mode 100644 final/test/CodeGen/X86/tls6.ll create mode 100644 final/test/CodeGen/X86/tls7.ll create mode 100644 final/test/CodeGen/X86/tls8.ll create mode 100644 final/test/CodeGen/X86/tls9.ll create mode 100644 final/test/CodeGen/X86/tlv-1.ll create mode 100644 final/test/CodeGen/X86/tlv-2.ll create mode 100644 final/test/CodeGen/X86/trap.ll create mode 100644 final/test/CodeGen/X86/trunc-to-bool.ll create mode 100644 final/test/CodeGen/X86/twoaddr-coalesce-2.ll create mode 100644 final/test/CodeGen/X86/twoaddr-coalesce.ll create mode 100644 final/test/CodeGen/X86/twoaddr-lea.ll create mode 100644 final/test/CodeGen/X86/twoaddr-pass-sink.ll create mode 100644 final/test/CodeGen/X86/twoaddr-remat.ll create mode 100644 final/test/CodeGen/X86/uint64-to-float.ll create mode 100644 final/test/CodeGen/X86/uint_to_fp-2.ll create mode 100644 final/test/CodeGen/X86/uint_to_fp.ll create mode 100644 final/test/CodeGen/X86/umul-with-carry.ll create mode 100644 final/test/CodeGen/X86/umul-with-overflow.ll create mode 100644 final/test/CodeGen/X86/unaligned-load.ll create mode 100644 final/test/CodeGen/X86/unknown-location.ll create mode 100644 final/test/CodeGen/X86/unreachable-loop-sinking.ll create mode 100644 final/test/CodeGen/X86/urem-i8-constant.ll create mode 100644 final/test/CodeGen/X86/use-add-flags.ll create mode 100644 final/test/CodeGen/X86/v-binop-widen.ll create mode 100644 final/test/CodeGen/X86/v-binop-widen2.ll create mode 100644 final/test/CodeGen/X86/v2f32.ll create mode 100644 final/test/CodeGen/X86/v4f32-immediate.ll create mode 100644 final/test/CodeGen/X86/variable-sized-darwin-bzero.ll create mode 100644 final/test/CodeGen/X86/variadic-node-pic.ll create mode 100644 final/test/CodeGen/X86/vec-sign.ll create mode 100644 final/test/CodeGen/X86/vec-trunc-store.ll create mode 100644 final/test/CodeGen/X86/vec_add.ll create mode 100644 final/test/CodeGen/X86/vec_align.ll create mode 100644 final/test/CodeGen/X86/vec_anyext.ll create mode 100644 final/test/CodeGen/X86/vec_call.ll create mode 100644 final/test/CodeGen/X86/vec_cast.ll create mode 100644 final/test/CodeGen/X86/vec_clear.ll create mode 100644 final/test/CodeGen/X86/vec_compare-2.ll create mode 100644 final/test/CodeGen/X86/vec_compare.ll create mode 100644 final/test/CodeGen/X86/vec_ctbits.ll create mode 100644 final/test/CodeGen/X86/vec_ext_inreg.ll create mode 100644 final/test/CodeGen/X86/vec_extract-sse4.ll create mode 100644 final/test/CodeGen/X86/vec_extract.ll create mode 100644 final/test/CodeGen/X86/vec_fneg.ll create mode 100644 final/test/CodeGen/X86/vec_i64.ll create mode 100644 final/test/CodeGen/X86/vec_ins_extract-1.ll create mode 100644 final/test/CodeGen/X86/vec_ins_extract.ll create mode 100644 final/test/CodeGen/X86/vec_insert-2.ll create mode 100644 final/test/CodeGen/X86/vec_insert-3.ll create mode 100644 final/test/CodeGen/X86/vec_insert-4.ll create mode 100644 final/test/CodeGen/X86/vec_insert-5.ll create mode 100644 final/test/CodeGen/X86/vec_insert-6.ll create mode 100644 final/test/CodeGen/X86/vec_insert-7.ll create mode 100644 final/test/CodeGen/X86/vec_insert-8.ll create mode 100644 final/test/CodeGen/X86/vec_insert-9.ll create mode 100644 final/test/CodeGen/X86/vec_insert.ll create mode 100644 final/test/CodeGen/X86/vec_loadsingles.ll create mode 100644 final/test/CodeGen/X86/vec_logical.ll create mode 100644 final/test/CodeGen/X86/vec_return.ll create mode 100644 final/test/CodeGen/X86/vec_set-2.ll create mode 100644 final/test/CodeGen/X86/vec_set-3.ll create mode 100644 final/test/CodeGen/X86/vec_set-4.ll create mode 100644 final/test/CodeGen/X86/vec_set-5.ll create mode 100644 final/test/CodeGen/X86/vec_set-6.ll create mode 100644 final/test/CodeGen/X86/vec_set-7.ll create mode 100644 final/test/CodeGen/X86/vec_set-8.ll create mode 100644 final/test/CodeGen/X86/vec_set-9.ll create mode 100644 final/test/CodeGen/X86/vec_set-A.ll create mode 100644 final/test/CodeGen/X86/vec_set-B.ll create mode 100644 final/test/CodeGen/X86/vec_set-C.ll create mode 100644 final/test/CodeGen/X86/vec_set-D.ll create mode 100644 final/test/CodeGen/X86/vec_set-E.ll create mode 100644 final/test/CodeGen/X86/vec_set-F.ll create mode 100644 final/test/CodeGen/X86/vec_set-G.ll create mode 100644 final/test/CodeGen/X86/vec_set-H.ll create mode 100644 final/test/CodeGen/X86/vec_set-I.ll create mode 100644 final/test/CodeGen/X86/vec_set-J.ll create mode 100644 final/test/CodeGen/X86/vec_set.ll create mode 100644 final/test/CodeGen/X86/vec_sext.ll create mode 100644 final/test/CodeGen/X86/vec_shift.ll create mode 100644 final/test/CodeGen/X86/vec_shift2.ll create mode 100644 final/test/CodeGen/X86/vec_shift3.ll create mode 100644 final/test/CodeGen/X86/vec_shift4.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-11.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-14.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-15.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-16.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-17.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-18.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-19.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-20.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-22.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-23.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-24.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-25.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-26.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-27.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-28.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-30.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-31.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-34.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-35.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-36.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle-37.ll create mode 100644 final/test/CodeGen/X86/vec_shuffle.ll create mode 100644 final/test/CodeGen/X86/vec_splat-2.ll create mode 100644 final/test/CodeGen/X86/vec_splat-3.ll create mode 100644 final/test/CodeGen/X86/vec_splat-4.ll create mode 100644 final/test/CodeGen/X86/vec_splat.ll create mode 100644 final/test/CodeGen/X86/vec_ss_load_fold.ll create mode 100644 final/test/CodeGen/X86/vec_zero-2.ll create mode 100644 final/test/CodeGen/X86/vec_zero.ll create mode 100644 final/test/CodeGen/X86/vec_zero_cse.ll create mode 100644 final/test/CodeGen/X86/vec_zext.ll create mode 100644 final/test/CodeGen/X86/vector-intrinsics.ll create mode 100644 final/test/CodeGen/X86/vector-rem.ll create mode 100644 final/test/CodeGen/X86/vector-variable-idx.ll create mode 100644 final/test/CodeGen/X86/vector.ll create mode 100644 final/test/CodeGen/X86/vfcmp.ll create mode 100644 final/test/CodeGen/X86/visibility.ll create mode 100644 final/test/CodeGen/X86/volatile.ll create mode 100644 final/test/CodeGen/X86/vortex-bug.ll create mode 100644 final/test/CodeGen/X86/vshift-1.ll create mode 100644 final/test/CodeGen/X86/vshift-2.ll create mode 100644 final/test/CodeGen/X86/vshift-3.ll create mode 100644 final/test/CodeGen/X86/vshift-4.ll create mode 100644 final/test/CodeGen/X86/vshift-5.ll create mode 100644 final/test/CodeGen/X86/vshift_scalar.ll create mode 100644 final/test/CodeGen/X86/vshift_split.ll create mode 100644 final/test/CodeGen/X86/vshift_split2.ll create mode 100644 final/test/CodeGen/X86/vsplit-and.ll create mode 100644 final/test/CodeGen/X86/weak.ll create mode 100644 final/test/CodeGen/X86/wide-integer-fold.ll create mode 100644 final/test/CodeGen/X86/widen_arith-1.ll create mode 100644 final/test/CodeGen/X86/widen_arith-2.ll create mode 100644 final/test/CodeGen/X86/widen_arith-3.ll create mode 100644 final/test/CodeGen/X86/widen_arith-4.ll create mode 100644 final/test/CodeGen/X86/widen_arith-5.ll create mode 100644 final/test/CodeGen/X86/widen_arith-6.ll create mode 100644 final/test/CodeGen/X86/widen_cast-1.ll create mode 100644 final/test/CodeGen/X86/widen_cast-2.ll create mode 100644 final/test/CodeGen/X86/widen_cast-3.ll create mode 100644 final/test/CodeGen/X86/widen_cast-4.ll create mode 100644 final/test/CodeGen/X86/widen_cast-5.ll create mode 100644 final/test/CodeGen/X86/widen_cast-6.ll create mode 100644 final/test/CodeGen/X86/widen_conv-1.ll create mode 100644 final/test/CodeGen/X86/widen_conv-2.ll create mode 100644 final/test/CodeGen/X86/widen_conv-3.ll create mode 100644 final/test/CodeGen/X86/widen_conv-4.ll create mode 100644 final/test/CodeGen/X86/widen_extract-1.ll create mode 100644 final/test/CodeGen/X86/widen_load-0.ll create mode 100644 final/test/CodeGen/X86/widen_load-1.ll create mode 100644 final/test/CodeGen/X86/widen_load-2.ll create mode 100644 final/test/CodeGen/X86/widen_shuffle-1.ll create mode 100644 final/test/CodeGen/X86/win64_params.ll create mode 100644 final/test/CodeGen/X86/win64_vararg.ll create mode 100644 final/test/CodeGen/X86/win_chkstk.ll create mode 100644 final/test/CodeGen/X86/x86-64-and-mask.ll create mode 100644 final/test/CodeGen/X86/x86-64-arg.ll create mode 100644 final/test/CodeGen/X86/x86-64-asm.ll create mode 100644 final/test/CodeGen/X86/x86-64-dead-stack-adjust.ll create mode 100644 final/test/CodeGen/X86/x86-64-disp.ll create mode 100644 final/test/CodeGen/X86/x86-64-extend-shift.ll create mode 100644 final/test/CodeGen/X86/x86-64-frameaddr.ll create mode 100644 final/test/CodeGen/X86/x86-64-gv-offset.ll create mode 100644 final/test/CodeGen/X86/x86-64-jumps.ll create mode 100644 final/test/CodeGen/X86/x86-64-malloc.ll create mode 100644 final/test/CodeGen/X86/x86-64-mem.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-1.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-10.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-11.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-2.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-3.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-4.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-5.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-6.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-7.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-8.ll create mode 100644 final/test/CodeGen/X86/x86-64-pic-9.ll create mode 100644 final/test/CodeGen/X86/x86-64-ret0.ll create mode 100644 final/test/CodeGen/X86/x86-64-shortint.ll create mode 100644 final/test/CodeGen/X86/x86-64-sret-return.ll create mode 100644 final/test/CodeGen/X86/x86-64-tls-1.ll create mode 100644 final/test/CodeGen/X86/x86-64-varargs.ll create mode 100644 final/test/CodeGen/X86/x86-frameaddr.ll create mode 100644 final/test/CodeGen/X86/x86-frameaddr2.ll create mode 100644 final/test/CodeGen/X86/x86-store-gv-addr.ll create mode 100644 final/test/CodeGen/X86/x86_64-mul-by-const.ll create mode 100644 final/test/CodeGen/X86/xmm-r64.ll create mode 100644 final/test/CodeGen/X86/xor-icmp.ll create mode 100644 final/test/CodeGen/X86/xor.ll create mode 100644 final/test/CodeGen/X86/zero-remat.ll create mode 100644 final/test/CodeGen/X86/zext-extract_subreg.ll create mode 100644 final/test/CodeGen/X86/zext-inreg-0.ll create mode 100644 final/test/CodeGen/X86/zext-inreg-1.ll create mode 100644 final/test/CodeGen/X86/zext-sext.ll create mode 100644 final/test/CodeGen/X86/zext-shl.ll create mode 100644 final/test/CodeGen/X86/zext-trunc.ll create mode 100644 final/test/CodeGen/XCore/2008-11-17-Shl64.ll create mode 100644 final/test/CodeGen/XCore/2009-01-08-Crash.ll create mode 100644 final/test/CodeGen/XCore/2009-01-14-Remat-Crash.ll create mode 100644 final/test/CodeGen/XCore/2009-03-27-v2f64-param.ll create mode 100644 final/test/CodeGen/XCore/2009-07-15-store192.ll create mode 100644 final/test/CodeGen/XCore/2010-02-25-LSR-Crash.ll create mode 100644 final/test/CodeGen/XCore/2010-04-07-DbgValueOtherTargets.ll create mode 100644 final/test/CodeGen/XCore/2011-01-31-DAGCombineBug.ll create mode 100644 final/test/CodeGen/XCore/addsub64.ll create mode 100644 final/test/CodeGen/XCore/ashr.ll create mode 100644 final/test/CodeGen/XCore/basictest.ll create mode 100644 final/test/CodeGen/XCore/bigstructret.ll create mode 100644 final/test/CodeGen/XCore/bitrev.ll create mode 100644 final/test/CodeGen/XCore/constants.ll create mode 100644 final/test/CodeGen/XCore/cos.ll create mode 100644 final/test/CodeGen/XCore/dg.exp create mode 100644 final/test/CodeGen/XCore/events.ll create mode 100644 final/test/CodeGen/XCore/exp.ll create mode 100644 final/test/CodeGen/XCore/exp2.ll create mode 100644 final/test/CodeGen/XCore/fneg.ll create mode 100644 final/test/CodeGen/XCore/getid.ll create mode 100644 final/test/CodeGen/XCore/globals.ll create mode 100644 final/test/CodeGen/XCore/indirectbr.ll create mode 100644 final/test/CodeGen/XCore/ladd_lsub_combine.ll create mode 100644 final/test/CodeGen/XCore/load.ll create mode 100644 final/test/CodeGen/XCore/log.ll create mode 100644 final/test/CodeGen/XCore/log10.ll create mode 100644 final/test/CodeGen/XCore/log2.ll create mode 100644 final/test/CodeGen/XCore/mul64.ll create mode 100644 final/test/CodeGen/XCore/pow.ll create mode 100644 final/test/CodeGen/XCore/powi.ll create mode 100644 final/test/CodeGen/XCore/private.ll create mode 100644 final/test/CodeGen/XCore/resources.ll create mode 100644 final/test/CodeGen/XCore/sext.ll create mode 100644 final/test/CodeGen/XCore/sin.ll create mode 100644 final/test/CodeGen/XCore/sqrt.ll create mode 100644 final/test/CodeGen/XCore/store.ll create mode 100644 final/test/CodeGen/XCore/switch.ll create mode 100644 final/test/CodeGen/XCore/switch_long.ll create mode 100644 final/test/CodeGen/XCore/tls.ll create mode 100644 final/test/CodeGen/XCore/trampoline.ll create mode 100644 final/test/CodeGen/XCore/trap.ll create mode 100644 final/test/CodeGen/XCore/unaligned_load.ll create mode 100644 final/test/CodeGen/XCore/unaligned_store.ll create mode 100644 final/test/CodeGen/XCore/unaligned_store_combine.ll create mode 100644 final/test/DebugInfo/2009-01-15-dbg_declare.ll create mode 100644 final/test/DebugInfo/2009-01-15-member.ll create mode 100644 final/test/DebugInfo/2009-10-08-DebugInfo-NullGlobalVariable.ll create mode 100644 final/test/DebugInfo/2009-10-16-Phi.ll create mode 100644 final/test/DebugInfo/2009-11-03-InsertExtractValue.ll create mode 100644 final/test/DebugInfo/2009-11-05-DeadGlobalVariable.ll create mode 100644 final/test/DebugInfo/2009-11-06-InvalidDerivedType.ll create mode 100644 final/test/DebugInfo/2009-11-06-NamelessGlobalVariable.ll create mode 100644 final/test/DebugInfo/2009-11-10-CurrentFn.ll create mode 100644 final/test/DebugInfo/2009-11-10-ParentScope.ll create mode 100644 final/test/DebugInfo/2010-01-05-DbgScope.ll create mode 100644 final/test/DebugInfo/2010-01-19-DbgScope.ll create mode 100644 final/test/DebugInfo/2010-03-12-llc-crash.ll create mode 100644 final/test/DebugInfo/2010-03-19-DbgDeclare.ll create mode 100644 final/test/DebugInfo/2010-03-24-MemberFn.ll create mode 100644 final/test/DebugInfo/2010-03-30-InvalidDbgInfoCrash.ll create mode 100644 final/test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll create mode 100644 final/test/DebugInfo/2010-04-13-PubType.ll create mode 100644 final/test/DebugInfo/2010-04-19-FramePtr.ll create mode 100644 final/test/DebugInfo/2010-04-25-CU-entry_pc.ll create mode 100644 final/test/DebugInfo/2010-05-03-DisableFramePtr.ll create mode 100644 final/test/DebugInfo/2010-05-03-OriginDIE.ll create mode 100644 final/test/DebugInfo/2010-05-10-MultipleCU.ll create mode 100644 final/test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll create mode 100644 final/test/DebugInfo/2010-07-19-Crash.ll create mode 100644 final/test/DebugInfo/2010-10-01-crash.ll create mode 100644 final/test/DebugInfo/dg.exp create mode 100644 final/test/DebugInfo/inheritance.ll create mode 100644 final/test/DebugInfo/printdbginfo2.ll create mode 100644 final/test/ExecutionEngine/2002-12-16-ArgTest.ll create mode 100644 final/test/ExecutionEngine/2003-01-04-ArgumentBug.ll create mode 100644 final/test/ExecutionEngine/2003-01-04-LoopTest.ll create mode 100644 final/test/ExecutionEngine/2003-01-04-PhiTest.ll create mode 100644 final/test/ExecutionEngine/2003-01-09-SARTest.ll create mode 100644 final/test/ExecutionEngine/2003-01-10-FUCOM.ll create mode 100644 final/test/ExecutionEngine/2003-01-15-AlignmentTest.ll create mode 100644 final/test/ExecutionEngine/2003-05-06-LivenessClobber.ll create mode 100644 final/test/ExecutionEngine/2003-05-07-ArgumentTest.ll create mode 100644 final/test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll create mode 100644 final/test/ExecutionEngine/2003-06-04-bzip2-bug.ll create mode 100644 final/test/ExecutionEngine/2003-06-05-PHIBug.ll create mode 100644 final/test/ExecutionEngine/2003-08-15-AllocaAssertion.ll create mode 100644 final/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll create mode 100644 final/test/ExecutionEngine/2003-08-23-RegisterAllocatePhysReg.ll create mode 100644 final/test/ExecutionEngine/2003-10-18-PHINode-ConstantExpr-CondCode-Failure.ll create mode 100644 final/test/ExecutionEngine/2005-12-02-TailCallBug.ll create mode 100644 final/test/ExecutionEngine/2007-12-10-APIntLoadStore.ll create mode 100644 final/test/ExecutionEngine/2008-06-05-APInt-OverAShr.ll create mode 100644 final/test/ExecutionEngine/2010-01-15-UndefValue.ll create mode 100644 final/test/ExecutionEngine/dg.exp create mode 100644 final/test/ExecutionEngine/fpbitcast.ll create mode 100644 final/test/ExecutionEngine/hello.ll create mode 100644 final/test/ExecutionEngine/hello2.ll create mode 100644 final/test/ExecutionEngine/simplesttest.ll create mode 100644 final/test/ExecutionEngine/simpletest.ll create mode 100644 final/test/ExecutionEngine/stubs.ll create mode 100644 final/test/ExecutionEngine/test-arith.ll create mode 100644 final/test/ExecutionEngine/test-branch.ll create mode 100644 final/test/ExecutionEngine/test-call.ll create mode 100644 final/test/ExecutionEngine/test-cast.ll create mode 100644 final/test/ExecutionEngine/test-constantexpr.ll create mode 100644 final/test/ExecutionEngine/test-fp.ll create mode 100644 final/test/ExecutionEngine/test-loadstore.ll create mode 100644 final/test/ExecutionEngine/test-logical.ll create mode 100644 final/test/ExecutionEngine/test-loop.ll create mode 100644 final/test/ExecutionEngine/test-malloc.ll create mode 100644 final/test/ExecutionEngine/test-phi.ll create mode 100644 final/test/ExecutionEngine/test-ret.ll create mode 100644 final/test/ExecutionEngine/test-setcond-fp.ll create mode 100644 final/test/ExecutionEngine/test-setcond-int.ll create mode 100644 final/test/ExecutionEngine/test-shift.ll create mode 100644 final/test/Feature/NamedMDNode.ll create mode 100644 final/test/Feature/NamedMDNode2.ll create mode 100644 final/test/Feature/README.txt create mode 100644 final/test/Feature/aliases.ll create mode 100644 final/test/Feature/alignment.ll create mode 100644 final/test/Feature/basictest.ll create mode 100644 final/test/Feature/callingconventions.ll create mode 100644 final/test/Feature/calltest.ll create mode 100644 final/test/Feature/casttest.ll create mode 100644 final/test/Feature/cfgstructures.ll create mode 100644 final/test/Feature/constexpr.ll create mode 100644 final/test/Feature/constpointer.ll create mode 100644 final/test/Feature/dg.exp create mode 100644 final/test/Feature/escaped_label.ll create mode 100644 final/test/Feature/float.ll create mode 100644 final/test/Feature/fold-fpcast.ll create mode 100644 final/test/Feature/forwardreftest.ll create mode 100644 final/test/Feature/global_section.ll create mode 100644 final/test/Feature/globalredefinition.ll create mode 100644 final/test/Feature/globalredefinition3.ll create mode 100644 final/test/Feature/globalvars.ll create mode 100644 final/test/Feature/indirectcall.ll create mode 100644 final/test/Feature/indirectcall2.ll create mode 100644 final/test/Feature/inlineasm.ll create mode 100644 final/test/Feature/instructions.ll create mode 100644 final/test/Feature/intrinsics.ll create mode 100644 final/test/Feature/linker_private_linkages.ll create mode 100644 final/test/Feature/llvm2cpp.exp create mode 100644 final/test/Feature/load_module.ll create mode 100644 final/test/Feature/md_on_instruction.ll create mode 100644 final/test/Feature/memorymarkers.ll create mode 100644 final/test/Feature/metadata.ll create mode 100644 final/test/Feature/newcasts.ll create mode 100644 final/test/Feature/noalias-ret.ll create mode 100644 final/test/Feature/opaquetypes.ll create mode 100644 final/test/Feature/packed.ll create mode 100644 final/test/Feature/packed_struct.ll create mode 100644 final/test/Feature/paramattrs.ll create mode 100644 final/test/Feature/ppcld.ll create mode 100644 final/test/Feature/properties.ll create mode 100644 final/test/Feature/prototype.ll create mode 100644 final/test/Feature/recursivetype.ll create mode 100644 final/test/Feature/simplecalltest.ll create mode 100644 final/test/Feature/small.ll create mode 100644 final/test/Feature/smallest.ll create mode 100644 final/test/Feature/sparcld.ll create mode 100644 final/test/Feature/terminators.ll create mode 100644 final/test/Feature/testalloca.ll create mode 100644 final/test/Feature/testconstants.ll create mode 100644 final/test/Feature/testlogical.ll create mode 100644 final/test/Feature/testmemory.ll create mode 100644 final/test/Feature/testtype.ll create mode 100644 final/test/Feature/testvarargs.ll create mode 100644 final/test/Feature/undefined.ll create mode 100644 final/test/Feature/unreachable.ll create mode 100644 final/test/Feature/varargs.ll create mode 100644 final/test/Feature/varargs_new.ll create mode 100644 final/test/Feature/vector-cast-constant-exprs.ll create mode 100644 final/test/Feature/weak_constant.ll create mode 100644 final/test/Feature/weirdnames.ll create mode 100644 final/test/Feature/x86ld.ll create mode 100644 final/test/FrontendAda/Support/element_copy.ads create mode 100644 final/test/FrontendAda/Support/fat_fields.ads create mode 100644 final/test/FrontendAda/Support/global_constant.ads create mode 100644 final/test/FrontendAda/Support/non_lvalue.ads create mode 100644 final/test/FrontendAda/Support/real_cst.ads create mode 100644 final/test/FrontendAda/Support/unc_constructor.ads create mode 100644 final/test/FrontendAda/Support/var_offset.ads create mode 100644 final/test/FrontendAda/Support/var_size.ads create mode 100644 final/test/FrontendAda/array_constructor.adb create mode 100644 final/test/FrontendAda/array_range_ref.adb create mode 100644 final/test/FrontendAda/array_ref.adb create mode 100644 final/test/FrontendAda/array_size.adb create mode 100644 final/test/FrontendAda/asm.adb create mode 100644 final/test/FrontendAda/constant_fold.ads create mode 100644 final/test/FrontendAda/debug_var_size.ads create mode 100644 final/test/FrontendAda/dg.exp create mode 100644 final/test/FrontendAda/element_copy.adb create mode 100644 final/test/FrontendAda/emit_var.ads create mode 100644 final/test/FrontendAda/fat_fields.adb create mode 100644 final/test/FrontendAda/field_order.ads create mode 100644 final/test/FrontendAda/global_constant.adb create mode 100644 final/test/FrontendAda/init_size.ads create mode 100644 final/test/FrontendAda/negative_field_offset.adb create mode 100644 final/test/FrontendAda/non_bitfield.ads create mode 100644 final/test/FrontendAda/non_lvalue.adb create mode 100644 final/test/FrontendAda/placeholder.adb create mode 100644 final/test/FrontendAda/real_cst.adb create mode 100644 final/test/FrontendAda/switch.adb create mode 100644 final/test/FrontendAda/unc_constructor.adb create mode 100644 final/test/FrontendAda/var_offset.adb create mode 100644 final/test/FrontendAda/var_size.adb create mode 100644 final/test/FrontendAda/vce.adb create mode 100644 final/test/FrontendAda/vce_lv.adb create mode 100644 final/test/FrontendC++/2003-11-02-WeakLinkage.cpp create mode 100644 final/test/FrontendC++/2003-11-18-PtrMemConstantInitializer.cpp create mode 100644 final/test/FrontendC++/2003-11-25-ReturningOpaqueByValue.cpp create mode 100644 final/test/FrontendC++/2003-11-27-MultipleInheritanceThunk.cpp create mode 100644 final/test/FrontendC++/2003-11-29-DuplicatedCleanupTest.cpp create mode 100644 final/test/FrontendC++/2003-12-08-ArrayOfPtrToMemberFunc.cpp create mode 100644 final/test/FrontendC++/2004-01-11-DynamicInitializedConstant.cpp create mode 100644 final/test/FrontendC++/2004-03-08-ReinterpretCastCopy.cpp create mode 100644 final/test/FrontendC++/2004-03-09-UnmangledBuiltinMethods.cpp create mode 100644 final/test/FrontendC++/2004-03-15-CleanupsAndGotos.cpp create mode 100644 final/test/FrontendC++/2004-06-08-LateTemplateInstantiation.cpp create mode 100644 final/test/FrontendC++/2004-09-27-CompilerCrash.cpp create mode 100644 final/test/FrontendC++/2004-09-27-DidntEmitTemplate.cpp create mode 100644 final/test/FrontendC++/2004-11-27-EmitsUnusedInlineFunctions.cpp create mode 100644 final/test/FrontendC++/2004-11-27-ExceptionCleanupAssertion.cpp create mode 100644 final/test/FrontendC++/2004-11-27-FriendDefaultArgCrash.cpp create mode 100644 final/test/FrontendC++/2004-11-27-InlineAsmFunctionRedefinition.cpp create mode 100644 final/test/FrontendC++/2005-01-03-StaticInitializers.cpp create mode 100644 final/test/FrontendC++/2005-02-11-AnonymousUnion.cpp create mode 100644 final/test/FrontendC++/2005-02-13-BadDynamicInit.cpp create mode 100644 final/test/FrontendC++/2005-02-14-BitFieldOffset.cpp create mode 100644 final/test/FrontendC++/2005-02-19-BitfieldStructCrash.cpp create mode 100644 final/test/FrontendC++/2005-02-19-UnnamedVirtualThunkArgument.cpp create mode 100644 final/test/FrontendC++/2005-02-20-BrokenReferenceTest.cpp create mode 100644 final/test/FrontendC++/2005-02-27-PlacementArrayNewCrash.cpp create mode 100644 final/test/FrontendC++/2005-07-21-VirtualBaseAccess.cpp create mode 100644 final/test/FrontendC++/2006-03-01-GimplifyCrash.cpp create mode 100644 final/test/FrontendC++/2006-03-06-C++RecurseCrash.cpp create mode 100644 final/test/FrontendC++/2006-09-08-powi.cpp create mode 100644 final/test/FrontendC++/2006-09-12-OpaqueStructCrash.cpp create mode 100644 final/test/FrontendC++/2006-09-27-Debug-Protection.cpp create mode 100644 final/test/FrontendC++/2006-10-30-ClassBitfield.cpp create mode 100644 final/test/FrontendC++/2006-11-06-StackTrace.cpp create mode 100644 final/test/FrontendC++/2006-11-20-GlobalSymbols.cpp create mode 100644 final/test/FrontendC++/2006-11-30-ConstantExprCrash.cpp create mode 100644 final/test/FrontendC++/2006-11-30-Pubnames.cpp create mode 100644 final/test/FrontendC++/2007-01-02-UnboundedArray.cpp create mode 100644 final/test/FrontendC++/2007-01-06-ELF-Thunk-Sections.cpp create mode 100644 final/test/FrontendC++/2007-01-06-PtrMethodInit.cpp create mode 100644 final/test/FrontendC++/2007-03-27-FunctionVarRename.cpp create mode 100644 final/test/FrontendC++/2007-04-05-PackedBitFields-1.cpp create mode 100644 final/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap-2.cpp create mode 100644 final/test/FrontendC++/2007-04-05-PackedBitFieldsOverlap.cpp create mode 100644 final/test/FrontendC++/2007-04-05-PackedBitFieldsSmall.cpp create mode 100644 final/test/FrontendC++/2007-04-05-StructPackedFieldUnpacked.cpp create mode 100644 final/test/FrontendC++/2007-04-10-PackedUnion.cpp create mode 100644 final/test/FrontendC++/2007-04-11-InlineStorageClassC++.cpp create mode 100644 final/test/FrontendC++/2007-04-14-FNoBuiltin.cpp create mode 100644 final/test/FrontendC++/2007-04-31-TryCatch.cpp create mode 100644 final/test/FrontendC++/2007-05-03-VectorInit.cpp create mode 100644 final/test/FrontendC++/2007-05-16-ReverseBitFieldCrash.cpp create mode 100644 final/test/FrontendC++/2007-05-23-TryFinally.cpp create mode 100644 final/test/FrontendC++/2007-07-04-NestedCatches.cpp create mode 100644 final/test/FrontendC++/2007-07-29-RestrictPtrArg.cpp create mode 100644 final/test/FrontendC++/2007-07-29-RestrictRefArg.cpp create mode 100644 final/test/FrontendC++/2007-08-01-RestrictMethod.cpp create mode 100644 final/test/FrontendC++/2007-09-10-RecursiveTypeResolution.cpp create mode 100644 final/test/FrontendC++/2007-10-01-StructResize.cpp create mode 100644 final/test/FrontendC++/2008-01-11-BadWarning.cpp create mode 100644 final/test/FrontendC++/2008-01-12-VecInit.cpp create mode 100644 final/test/FrontendC++/2008-05-07-CrazyOffsetOf.cpp create mode 100644 final/test/FrontendC++/2008-10-29-WrongOffset.cpp create mode 100644 final/test/FrontendC++/2009-02-07-VolatileArrayRefHack.cpp create mode 100644 final/test/FrontendC++/2009-02-16-CtorNames-dbg.cpp create mode 100644 final/test/FrontendC++/2009-03-17-dbg.cpp create mode 100644 final/test/FrontendC++/2009-04-21-DtorNames-dbg.cpp create mode 100644 final/test/FrontendC++/2009-04-23-bool2.cpp create mode 100644 final/test/FrontendC++/2009-05-04-PureConstNounwind.cpp create mode 100644 final/test/FrontendC++/2009-06-16-DebugInfoCrash.cpp create mode 100644 final/test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp create mode 100644 final/test/FrontendC++/2009-06-30-ByrefBlock.cpp create mode 100644 final/test/FrontendC++/2009-07-15-LineNumbers.cpp create mode 100644 final/test/FrontendC++/2009-07-16-PrivateCopyConstructor.cpp create mode 100644 final/test/FrontendC++/2009-07-16-Using.cpp create mode 100644 final/test/FrontendC++/2009-08-05-ZeroInitWidth.cpp create mode 100644 final/test/FrontendC++/2009-08-11-VectorRetTy.cpp create mode 100644 final/test/FrontendC++/2009-09-04-modify-crash.cpp create mode 100644 final/test/FrontendC++/2009-09-09-packed-layout.cpp create mode 100644 final/test/FrontendC++/2009-10-27-crash.cpp create mode 100644 final/test/FrontendC++/2009-12-23-MissingSext.cpp create mode 100644 final/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp create mode 100644 final/test/FrontendC++/2010-03-22-empty-baseclass.cpp create mode 100644 final/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp create mode 100644 final/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp create mode 100644 final/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp create mode 100644 final/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp create mode 100644 final/test/FrontendC++/2010-06-21-LocalVarDbg.cpp create mode 100644 final/test/FrontendC++/2010-06-22-BitfieldInit.cpp create mode 100644 final/test/FrontendC++/2010-06-22-ZeroBitfield.cpp create mode 100644 final/test/FrontendC++/2010-07-19-nowarn.cpp create mode 100644 final/test/FrontendC++/2010-07-23-DeclLoc.cpp create mode 100644 final/test/FrontendC++/2010-08-31-ByValArg.cpp create mode 100644 final/test/FrontendC++/alignstack.cpp create mode 100644 final/test/FrontendC++/dg.exp create mode 100644 final/test/FrontendC++/integration-O2.cpp create mode 100644 final/test/FrontendC++/m64-ptr.cpp create mode 100644 final/test/FrontendC++/member-alignment.cpp create mode 100644 final/test/FrontendC++/ptr-to-method-devirt.cpp create mode 100644 final/test/FrontendC++/thunk-linkonce-odr.cpp create mode 100644 final/test/FrontendC++/varargs.cpp create mode 100644 final/test/FrontendC++/weak-external.cpp create mode 100644 final/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp create mode 100644 final/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c create mode 100644 final/test/FrontendC/2002-01-24-ComplexSpaceInType.c create mode 100644 final/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c create mode 100644 final/test/FrontendC/2002-02-13-ConditionalInCall.c create mode 100644 final/test/FrontendC/2002-02-13-ReloadProblem.c create mode 100644 final/test/FrontendC/2002-02-13-TypeVarNameCollision.c create mode 100644 final/test/FrontendC/2002-02-13-UnnamedLocal.c create mode 100644 final/test/FrontendC/2002-02-14-EntryNodePreds.c create mode 100644 final/test/FrontendC/2002-02-16-RenamingTest.c create mode 100644 final/test/FrontendC/2002-02-17-ArgumentAddress.c create mode 100644 final/test/FrontendC/2002-02-18-64bitConstant.c create mode 100644 final/test/FrontendC/2002-02-18-StaticData.c create mode 100644 final/test/FrontendC/2002-03-11-LargeCharInString.c create mode 100644 final/test/FrontendC/2002-03-12-ArrayInitialization.c create mode 100644 final/test/FrontendC/2002-03-12-StructInitialize.c create mode 100644 final/test/FrontendC/2002-03-12-StructInitializer.c create mode 100644 final/test/FrontendC/2002-03-14-BrokenPHINode.c create mode 100644 final/test/FrontendC/2002-03-14-BrokenSSA.c create mode 100644 final/test/FrontendC/2002-03-14-QuotesInStrConst.c create mode 100644 final/test/FrontendC/2002-04-07-SwitchStmt.c create mode 100644 final/test/FrontendC/2002-04-08-LocalArray.c create mode 100644 final/test/FrontendC/2002-04-09-StructRetVal.c create mode 100644 final/test/FrontendC/2002-04-10-StructParameters.c create mode 100644 final/test/FrontendC/2002-05-23-StaticValues.c create mode 100644 final/test/FrontendC/2002-05-23-TypeNameCollision.c create mode 100644 final/test/FrontendC/2002-05-24-Alloca.c create mode 100644 final/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c create mode 100644 final/test/FrontendC/2002-07-14-MiscListTests.c create mode 100644 final/test/FrontendC/2002-07-14-MiscTests.c create mode 100644 final/test/FrontendC/2002-07-14-MiscTests2.c create mode 100644 final/test/FrontendC/2002-07-14-MiscTests3.c create mode 100644 final/test/FrontendC/2002-07-16-HardStringInit.c create mode 100644 final/test/FrontendC/2002-07-17-StringConstant.c create mode 100644 final/test/FrontendC/2002-07-29-Casts.c create mode 100644 final/test/FrontendC/2002-07-30-SubregSetAssertion.c create mode 100644 final/test/FrontendC/2002-07-30-UnionTest.c create mode 100644 final/test/FrontendC/2002-07-30-VarArgsCallFailure.c create mode 100644 final/test/FrontendC/2002-07-31-BadAssert.c create mode 100644 final/test/FrontendC/2002-07-31-SubregFailure.c create mode 100644 final/test/FrontendC/2002-08-02-UnionTest.c create mode 100644 final/test/FrontendC/2002-08-19-RecursiveLocals.c create mode 100644 final/test/FrontendC/2002-09-08-PointerShifts.c create mode 100644 final/test/FrontendC/2002-09-18-UnionProblem.c create mode 100644 final/test/FrontendC/2002-09-19-StarInLabel.c create mode 100644 final/test/FrontendC/2002-10-12-TooManyArguments.c create mode 100644 final/test/FrontendC/2002-12-15-GlobalBoolTest.c create mode 100644 final/test/FrontendC/2002-12-15-GlobalConstantTest.c create mode 100644 final/test/FrontendC/2002-12-15-GlobalRedefinition.c create mode 100644 final/test/FrontendC/2002-12-15-StructParameters.c create mode 100644 final/test/FrontendC/2003-01-30-UnionInit.c create mode 100644 final/test/FrontendC/2003-03-03-DeferredType.c create mode 100644 final/test/FrontendC/2003-06-22-UnionCrash.c create mode 100644 final/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c create mode 100644 final/test/FrontendC/2003-06-26-CFECrash.c create mode 100644 final/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c create mode 100644 final/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c create mode 100644 final/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c create mode 100644 final/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c create mode 100644 final/test/FrontendC/2003-08-18-SigSetJmp.c create mode 100644 final/test/FrontendC/2003-08-18-StructAsValue.c create mode 100644 final/test/FrontendC/2003-08-20-BadBitfieldRef.c create mode 100644 final/test/FrontendC/2003-08-20-PrototypeMismatch.c create mode 100644 final/test/FrontendC/2003-08-20-vfork-bug.c create mode 100644 final/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c create mode 100644 final/test/FrontendC/2003-08-21-StmtExpr.c create mode 100644 final/test/FrontendC/2003-08-21-WideString.c create mode 100644 final/test/FrontendC/2003-08-23-LocalUnionTest.c create mode 100644 final/test/FrontendC/2003-08-29-BitFieldStruct.c create mode 100644 final/test/FrontendC/2003-08-29-HugeCharConst.c create mode 100644 final/test/FrontendC/2003-08-29-StructLayoutBug.c create mode 100644 final/test/FrontendC/2003-08-30-AggregateInitializer.c create mode 100644 final/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c create mode 100644 final/test/FrontendC/2003-09-18-BitfieldTests.c create mode 100644 final/test/FrontendC/2003-09-30-StructLayout.c create mode 100644 final/test/FrontendC/2003-10-02-UnionLValueError.c create mode 100644 final/test/FrontendC/2003-10-06-NegateExprType.c create mode 100644 final/test/FrontendC/2003-10-09-UnionInitializerBug.c create mode 100644 final/test/FrontendC/2003-10-28-ident.c create mode 100644 final/test/FrontendC/2003-10-29-AsmRename.c create mode 100644 final/test/FrontendC/2003-11-01-C99-CompoundLiteral.c create mode 100644 final/test/FrontendC/2003-11-01-EmptyStructCrash.c create mode 100644 final/test/FrontendC/2003-11-01-GlobalUnionInit.c create mode 100644 final/test/FrontendC/2003-11-03-AddrArrayElement.c create mode 100644 final/test/FrontendC/2003-11-04-EmptyStruct.c create mode 100644 final/test/FrontendC/2003-11-04-OutOfMemory.c create mode 100644 final/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c create mode 100644 final/test/FrontendC/2003-11-12-VoidString.c create mode 100644 final/test/FrontendC/2003-11-13-TypeSafety.c create mode 100644 final/test/FrontendC/2003-11-16-StaticArrayInit.c create mode 100644 final/test/FrontendC/2003-11-18-CondExprLValue.c create mode 100644 final/test/FrontendC/2003-11-19-AddressOfRegister.c create mode 100644 final/test/FrontendC/2003-11-19-BitFieldArray.c create mode 100644 final/test/FrontendC/2003-11-20-Bitfields.c create mode 100644 final/test/FrontendC/2003-11-20-ComplexDivision.c create mode 100644 final/test/FrontendC/2003-11-20-UnionBitfield.c create mode 100644 final/test/FrontendC/2003-11-26-PointerShift.c create mode 100644 final/test/FrontendC/2003-11-27-ConstructorCast.c create mode 100644 final/test/FrontendC/2003-11-27-UnionCtorInitialization.c create mode 100644 final/test/FrontendC/2003-12-14-ExternInlineSupport.c create mode 100644 final/test/FrontendC/2004-01-01-UnknownInitSize.c create mode 100644 final/test/FrontendC/2004-01-08-ExternInlineRedefine.c create mode 100644 final/test/FrontendC/2004-02-12-LargeAggregateCopy.c create mode 100644 final/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c create mode 100644 final/test/FrontendC/2004-02-13-IllegalVararg.c create mode 100644 final/test/FrontendC/2004-02-13-Memset.c create mode 100644 final/test/FrontendC/2004-02-14-ZeroInitializer.c create mode 100644 final/test/FrontendC/2004-02-20-Builtins.c create mode 100644 final/test/FrontendC/2004-03-07-ComplexDivEquals.c create mode 100644 final/test/FrontendC/2004-03-07-ExternalConstant.c create mode 100644 final/test/FrontendC/2004-03-09-LargeArrayInitializers.c create mode 100644 final/test/FrontendC/2004-03-15-SimpleIndirectGoto.c create mode 100644 final/test/FrontendC/2004-03-16-AsmRegisterCrash.c create mode 100644 final/test/FrontendC/2004-05-07-VarArrays.c create mode 100644 final/test/FrontendC/2004-05-21-IncompleteEnum.c create mode 100644 final/test/FrontendC/2004-06-08-OpaqueStructArg.c create mode 100644 final/test/FrontendC/2004-06-17-UnorderedBuiltins.c create mode 100644 final/test/FrontendC/2004-06-17-UnorderedCompares.c create mode 100644 final/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c create mode 100644 final/test/FrontendC/2004-07-06-FunctionCast.c create mode 100644 final/test/FrontendC/2004-08-06-LargeStructTest.c create mode 100644 final/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c create mode 100644 final/test/FrontendC/2004-11-27-InvalidConstantExpr.c create mode 100644 final/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c create mode 100644 final/test/FrontendC/2004-11-27-VariableSizeInStructure.c create mode 100644 final/test/FrontendC/2005-01-02-ConstantInits.c create mode 100644 final/test/FrontendC/2005-01-02-PointerDifference.c create mode 100644 final/test/FrontendC/2005-01-02-VAArgError-ICE.c create mode 100644 final/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c create mode 100644 final/test/FrontendC/2005-02-27-MarkGlobalConstant.c create mode 100644 final/test/FrontendC/2005-03-05-OffsetOfHack.c create mode 100644 final/test/FrontendC/2005-03-06-OffsetOfStructCrash.c create mode 100644 final/test/FrontendC/2005-03-11-Prefetch.c create mode 100644 final/test/FrontendC/2005-04-09-ComplexOps.c create mode 100644 final/test/FrontendC/2005-05-06-CountBuiltins.c create mode 100644 final/test/FrontendC/2005-05-10-GlobalUnionInit.c create mode 100644 final/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c create mode 100644 final/test/FrontendC/2005-07-20-SqrtNoErrno.c create mode 100644 final/test/FrontendC/2005-07-26-UnionInitCrash.c create mode 100644 final/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c create mode 100644 final/test/FrontendC/2005-09-20-ComplexConstants.c create mode 100644 final/test/FrontendC/2005-09-24-AsmUserPrefix.c create mode 100644 final/test/FrontendC/2005-09-24-BitFieldCrash.c create mode 100644 final/test/FrontendC/2005-10-18-VariableSizedElementCrash.c create mode 100644 final/test/FrontendC/2005-12-04-AttributeUsed.c create mode 100644 final/test/FrontendC/2005-12-04-DeclarationLineNumbers.c create mode 100644 final/test/FrontendC/2006-01-13-Includes.c create mode 100644 final/test/FrontendC/2006-01-13-StackSave.c create mode 100644 final/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c create mode 100644 final/test/FrontendC/2006-01-23-FileScopeAsm.c create mode 100644 final/test/FrontendC/2006-03-03-MissingInitializer.c create mode 100644 final/test/FrontendC/2006-03-16-VectorCtor.c create mode 100644 final/test/FrontendC/2006-03-17-KnRMismatch.c create mode 100644 final/test/FrontendC/2006-05-01-AppleAlignmentPragma.c create mode 100644 final/test/FrontendC/2006-05-19-SingleEltReturn.c create mode 100644 final/test/FrontendC/2006-07-31-PR854.c create mode 100644 final/test/FrontendC/2006-09-11-BitfieldRefCrash.c create mode 100644 final/test/FrontendC/2006-09-18-fwrite-cast-crash.c create mode 100644 final/test/FrontendC/2006-09-21-IncompleteElementType.c create mode 100644 final/test/FrontendC/2006-09-25-DebugFilename.c create mode 100644 final/test/FrontendC/2006-09-25-DebugFilename.h create mode 100644 final/test/FrontendC/2006-09-28-SimpleAsm.c create mode 100644 final/test/FrontendC/2006-10-30-ArrayCrash.c create mode 100644 final/test/FrontendC/2006-12-14-ordered_expr.c create mode 100644 final/test/FrontendC/2007-01-06-KNR-Proto.c create mode 100644 final/test/FrontendC/2007-01-20-VectorICE.c create mode 100644 final/test/FrontendC/2007-01-24-InlineAsmCModifier.c create mode 100644 final/test/FrontendC/2007-02-04-AddrLValue-2.c create mode 100644 final/test/FrontendC/2007-02-04-AddrLValue.c create mode 100644 final/test/FrontendC/2007-02-04-EmptyStruct.c create mode 100644 final/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c create mode 100644 final/test/FrontendC/2007-02-05-nested.c create mode 100644 final/test/FrontendC/2007-02-07-AddrLabel.c create mode 100644 final/test/FrontendC/2007-02-16-VariableSizeStructArg.c create mode 100644 final/test/FrontendC/2007-02-16-VoidPtrDiff.c create mode 100644 final/test/FrontendC/2007-02-16-WritableStrings.c create mode 100644 final/test/FrontendC/2007-02-25-C-DotDotDot.c create mode 100644 final/test/FrontendC/2007-03-01-VarSizeArrayIdx.c create mode 100644 final/test/FrontendC/2007-03-05-DataLayout.c create mode 100644 final/test/FrontendC/2007-03-06-VarSizeInStruct1.c create mode 100644 final/test/FrontendC/2007-03-06-VarSizeInStruct2.c create mode 100644 final/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c create mode 100644 final/test/FrontendC/2007-03-26-ZeroWidthBitfield.c create mode 100644 final/test/FrontendC/2007-03-27-ArrayCompatible.c create mode 100644 final/test/FrontendC/2007-03-27-VarLengthArray.c create mode 100644 final/test/FrontendC/2007-04-05-PackedBitFields-2.c create mode 100644 final/test/FrontendC/2007-04-05-PackedBitFields.c create mode 100644 final/test/FrontendC/2007-04-05-PackedStruct.c create mode 100644 final/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c create mode 100644 final/test/FrontendC/2007-04-05-UnPackedStruct.c create mode 100644 final/test/FrontendC/2007-04-11-InlineAsmStruct.c create mode 100644 final/test/FrontendC/2007-04-11-InlineAsmUnion.c create mode 100644 final/test/FrontendC/2007-04-11-InlineStorageClassC89.c create mode 100644 final/test/FrontendC/2007-04-11-InlineStorageClassC99.c create mode 100644 final/test/FrontendC/2007-04-11-PR1321.c create mode 100644 final/test/FrontendC/2007-04-13-InlineAsmStruct2.c create mode 100644 final/test/FrontendC/2007-04-13-InlineAsmUnion2.c create mode 100644 final/test/FrontendC/2007-04-14-FNoBuiltin.c create mode 100644 final/test/FrontendC/2007-04-17-ZeroSizeBitFields.c create mode 100644 final/test/FrontendC/2007-04-24-VolatileStructCopy.c create mode 100644 final/test/FrontendC/2007-04-24-bit-not-expr.c create mode 100644 final/test/FrontendC/2007-04-24-str-const.c create mode 100644 final/test/FrontendC/2007-05-07-NestedStructReturn.c create mode 100644 final/test/FrontendC/2007-05-07-PaddingElements.c create mode 100644 final/test/FrontendC/2007-05-08-PCH.c create mode 100644 final/test/FrontendC/2007-05-11-str-const.c create mode 100644 final/test/FrontendC/2007-05-15-PaddingElement.c create mode 100644 final/test/FrontendC/2007-05-16-EmptyStruct.c create mode 100644 final/test/FrontendC/2007-05-29-UnionCopy.c create mode 100644 final/test/FrontendC/2007-06-05-NoInlineAttribute.c create mode 100644 final/test/FrontendC/2007-06-15-AnnotateAttribute.c create mode 100644 final/test/FrontendC/2007-06-18-SextAttrAggregate.c create mode 100644 final/test/FrontendC/2007-07-29-RestrictPtrArg.c create mode 100644 final/test/FrontendC/2007-08-01-LoadStoreAlign.c create mode 100644 final/test/FrontendC/2007-08-21-ComplexCst.c create mode 100644 final/test/FrontendC/2007-08-22-CTTZ.c create mode 100644 final/test/FrontendC/2007-09-05-ConstCtor.c create mode 100644 final/test/FrontendC/2007-09-12-PragmaPack.c create mode 100644 final/test/FrontendC/2007-09-14-NegatePointer.c create mode 100644 final/test/FrontendC/2007-09-17-WeakRef.c create mode 100644 final/test/FrontendC/2007-09-20-GcrootAttribute.c create mode 100644 final/test/FrontendC/2007-09-26-Alignment.c create mode 100644 final/test/FrontendC/2007-09-27-ComplexIntCompare.c create mode 100644 final/test/FrontendC/2007-09-28-PackedUnionMember.c create mode 100644 final/test/FrontendC/2007-10-01-BuildArrayRef.c create mode 100644 final/test/FrontendC/2007-10-02-VolatileArray.c create mode 100644 final/test/FrontendC/2007-10-15-VoidPtr.c create mode 100644 final/test/FrontendC/2007-10-30-Volatile.c create mode 100644 final/test/FrontendC/2007-11-07-AlignedMemcpy.c create mode 100644 final/test/FrontendC/2007-11-07-CopyAggregateAlign.c create mode 100644 final/test/FrontendC/2007-11-07-ZeroAggregateAlign.c create mode 100644 final/test/FrontendC/2007-11-27-SExtZExt.c create mode 100644 final/test/FrontendC/2007-11-28-GlobalInitializer.c create mode 100644 final/test/FrontendC/2007-12-16-AsmNoUnwind.c create mode 100644 final/test/FrontendC/2007-12-VarArrayDebug.c create mode 100644 final/test/FrontendC/2008-01-04-WideBitfield.c create mode 100644 final/test/FrontendC/2008-01-07-UnusualIntSize.c create mode 100644 final/test/FrontendC/2008-01-11-ChainConsistency.c create mode 100644 final/test/FrontendC/2008-01-21-PackedBitFields.c create mode 100644 final/test/FrontendC/2008-01-21-PackedStructField.c create mode 100644 final/test/FrontendC/2008-01-24-StructAlignAndBitFields.c create mode 100644 final/test/FrontendC/2008-01-25-ByValReadNone.c create mode 100644 final/test/FrontendC/2008-01-25-ZeroSizedAggregate.c create mode 100644 final/test/FrontendC/2008-01-28-PragmaMark.c create mode 100644 final/test/FrontendC/2008-01-28-UnionSize.c create mode 100644 final/test/FrontendC/2008-02-11-AnnotateBuiltin.c create mode 100644 final/test/FrontendC/2008-03-03-CtorAttrType.c create mode 100644 final/test/FrontendC/2008-03-05-syncPtr.c create mode 100644 final/test/FrontendC/2008-03-24-BitField-And-Alloca.c create mode 100644 final/test/FrontendC/2008-03-26-PackedBitFields.c create mode 100644 final/test/FrontendC/2008-04-08-NoExceptions.c create mode 100644 final/test/FrontendC/2008-05-06-CFECrash.c create mode 100644 final/test/FrontendC/2008-05-12-TempUsedBeforeDef.c create mode 100644 final/test/FrontendC/2008-05-19-AlwaysInline.c create mode 100644 final/test/FrontendC/2008-07-08-FAbsAttributes.c create mode 100644 final/test/FrontendC/2008-07-29-EHLabel.ll create mode 100644 final/test/FrontendC/2008-08-07-AlignPadding1.c create mode 100644 final/test/FrontendC/2008-08-07-AlignPadding2.c create mode 100644 final/test/FrontendC/2008-08-07-GEPIntToPtr.c create mode 100644 final/test/FrontendC/2008-09-03-WeakAlias.c create mode 100644 final/test/FrontendC/2008-10-13-FrontendCrash.c create mode 100644 final/test/FrontendC/2008-10-30-ZeroPlacement.c create mode 100644 final/test/FrontendC/2008-11-02-WeakAlias.c create mode 100644 final/test/FrontendC/2008-11-08-InstCombineSelect.c create mode 100644 final/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c create mode 100644 final/test/FrontendC/2008-12-23-AsmIntPointerTie.c create mode 100644 final/test/FrontendC/2009-01-05-BlockInlining.c create mode 100644 final/test/FrontendC/2009-01-20-k8.c create mode 100644 final/test/FrontendC/2009-01-21-InvalidIterator.c create mode 100644 final/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c create mode 100644 final/test/FrontendC/2009-02-13-zerosize-union-field.c create mode 100644 final/test/FrontendC/2009-02-17-BitField-dbg.c create mode 100644 final/test/FrontendC/2009-03-01-MallocNoAlias.c create mode 100644 final/test/FrontendC/2009-03-08-ZeroEltStructCrash.c create mode 100644 final/test/FrontendC/2009-03-09-WeakDeclarations-1.c create mode 100644 final/test/FrontendC/2009-03-13-dbg.c create mode 100644 final/test/FrontendC/2009-04-22-UnknownSize.c create mode 100644 final/test/FrontendC/2009-04-28-UnionArrayCrash.c create mode 100644 final/test/FrontendC/2009-05-04-EnumInreg.c create mode 100644 final/test/FrontendC/2009-05-17-AlwaysInline.c create mode 100644 final/test/FrontendC/2009-06-14-HighlyAligned.c create mode 100644 final/test/FrontendC/2009-06-18-StaticInitTailPadPack.c create mode 100644 final/test/FrontendC/2009-07-14-VoidPtr.c create mode 100644 final/test/FrontendC/2009-07-15-pad-wchar_t-array.c create mode 100644 final/test/FrontendC/2009-07-17-VoidParameter.c create mode 100644 final/test/FrontendC/2009-07-22-StructLayout.c create mode 100644 final/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c create mode 100644 final/test/FrontendC/2009-09-24-SqrtErrno.c create mode 100644 final/test/FrontendC/2009-12-07-BitFieldAlignment.c create mode 100644 final/test/FrontendC/2010-01-05-LinkageName.c create mode 100644 final/test/FrontendC/2010-01-13-MemBarrier.c create mode 100644 final/test/FrontendC/2010-01-14-FnType-DebugInfo.c create mode 100644 final/test/FrontendC/2010-01-14-StaticVariable.c create mode 100644 final/test/FrontendC/2010-01-18-Inlined-Debug.c create mode 100644 final/test/FrontendC/2010-02-10-PointerName.c create mode 100644 final/test/FrontendC/2010-02-15-DbgStaticVar.c create mode 100644 final/test/FrontendC/2010-02-16-DbgVarScope.c create mode 100644 final/test/FrontendC/2010-02-18-Dbg-VectorType.c create mode 100644 final/test/FrontendC/2010-03-10-arm-asmreg.c create mode 100644 final/test/FrontendC/2010-03-5-LexicalScope.c create mode 100644 final/test/FrontendC/2010-05-14-Optimized-VarType.c create mode 100644 final/test/FrontendC/2010-05-18-asmsched.c create mode 100644 final/test/FrontendC/2010-05-18-palignr.c create mode 100644 final/test/FrontendC/2010-05-26-AsmSideEffect.c create mode 100644 final/test/FrontendC/2010-05-31-palignr.c create mode 100644 final/test/FrontendC/2010-06-11-SaveExpr.c create mode 100644 final/test/FrontendC/2010-06-17-asmcrash.c create mode 100644 final/test/FrontendC/2010-06-28-DbgLocalVar.c create mode 100644 final/test/FrontendC/2010-06-28-nowarn.c create mode 100644 final/test/FrontendC/2010-07-08-DeclDebugLineNo.c create mode 100644 final/test/FrontendC/2010-07-14-overconservative-align.c create mode 100644 final/test/FrontendC/2010-07-14-ref-off-end.c create mode 100644 final/test/FrontendC/2010-07-27-MinNoFoldConst.c create mode 100644 final/test/FrontendC/2010-08-12-asm-aggr-arg.c create mode 100644 final/test/FrontendC/2010-11-16-asmblock.c create mode 100644 final/test/FrontendC/2010-12-01-CommonGlobal.c create mode 100644 final/test/FrontendC/2011-02-21-DATA-common.c create mode 100644 final/test/FrontendC/Atomics-no64bit.c create mode 100644 final/test/FrontendC/Atomics.c create mode 100644 final/test/FrontendC/BasicInstrs.c create mode 100644 final/test/FrontendC/alignstack.c create mode 100644 final/test/FrontendC/always-inline.c create mode 100644 final/test/FrontendC/arrayderef.c create mode 100644 final/test/FrontendC/asm-reg-var-local.c create mode 100644 final/test/FrontendC/attribute_constructor.c create mode 100644 final/test/FrontendC/block-copy.c create mode 100644 final/test/FrontendC/crash-invalid-array.c create mode 100644 final/test/FrontendC/cstring-align.c create mode 100644 final/test/FrontendC/dg.exp create mode 100644 final/test/FrontendC/exact-div-expr.c create mode 100644 final/test/FrontendC/extern-weak.c create mode 100644 final/test/FrontendC/fp-logical.c create mode 100644 final/test/FrontendC/func-aligned.c create mode 100644 final/test/FrontendC/funccall.c create mode 100644 final/test/FrontendC/hidden-visibility.c create mode 100644 final/test/FrontendC/implicit-arg.c create mode 100644 final/test/FrontendC/inline-asm-function.c create mode 100644 final/test/FrontendC/inline-asm-mrv.c create mode 100644 final/test/FrontendC/libcalls-d.c create mode 100644 final/test/FrontendC/libcalls-ld.c create mode 100644 final/test/FrontendC/libcalls.c create mode 100644 final/test/FrontendC/misaligned-param.c create mode 100644 final/test/FrontendC/nested-functions.c create mode 100644 final/test/FrontendC/pr2394.c create mode 100644 final/test/FrontendC/pr3518.c create mode 100644 final/test/FrontendC/pr4349.c create mode 100644 final/test/FrontendC/pr5406.c create mode 100644 final/test/FrontendC/ptr-rotate.c create mode 100644 final/test/FrontendC/redef-ext-inline.c create mode 100644 final/test/FrontendC/sret.c create mode 100644 final/test/FrontendC/sret2.c create mode 100644 final/test/FrontendC/unaligned-memcpy.c create mode 100644 final/test/FrontendC/union-align.c create mode 100644 final/test/FrontendC/vla-1.c create mode 100644 final/test/FrontendC/vla-2.c create mode 100644 final/test/FrontendC/wchar-const.c create mode 100644 final/test/FrontendC/weak_constant.c create mode 100644 final/test/FrontendFortran/2008-11-03-OptionOverride.f90 create mode 100644 final/test/FrontendFortran/2009-02-09-FloorDivExpr.f90 create mode 100644 final/test/FrontendFortran/cpow.f90 create mode 100644 final/test/FrontendFortran/dg.exp create mode 100644 final/test/FrontendObjC++/2007-10-03-MetadataPointers.mm create mode 100644 final/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm create mode 100644 final/test/FrontendObjC++/2010-08-04-Template.mm create mode 100644 final/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm create mode 100644 final/test/FrontendObjC++/dg.exp create mode 100644 final/test/FrontendObjC/2007-04-03-ObjcEH.m create mode 100644 final/test/FrontendObjC/2007-05-02-Strong.m create mode 100644 final/test/FrontendObjC/2007-09-25-EH.m create mode 100644 final/test/FrontendObjC/2007-10-17-SJLJExceptions.m create mode 100644 final/test/FrontendObjC/2007-10-18-ProDescriptor.m create mode 100644 final/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m create mode 100644 final/test/FrontendObjC/2008-10-3-EhValue.m create mode 100644 final/test/FrontendObjC/2008-11-12-Metadata.m create mode 100644 final/test/FrontendObjC/2008-11-24-ConstCFStrings.m create mode 100644 final/test/FrontendObjC/2008-11-25-Blocks.m create mode 100644 final/test/FrontendObjC/2009-01-26-WriteBarrier-2.m create mode 100644 final/test/FrontendObjC/2009-02-05-VolatileProp.m create mode 100644 final/test/FrontendObjC/2009-04-14-AsmSection.m create mode 100644 final/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m create mode 100644 final/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m create mode 100644 final/test/FrontendObjC/2009-08-05-utf16.m create mode 100644 final/test/FrontendObjC/2009-08-17-DebugInfo.m create mode 100644 final/test/FrontendObjC/2009-11-30-Objc-ID.m create mode 100644 final/test/FrontendObjC/2010-02-01-utf16-with-null.m create mode 100644 final/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m create mode 100644 final/test/FrontendObjC/2010-02-23-DbgInheritance.m create mode 100644 final/test/FrontendObjC/2010-03-17-StructRef.m create mode 100644 final/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m create mode 100644 final/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m create mode 100644 final/test/FrontendObjC/dg.exp create mode 100644 final/test/Integer/2007-01-19-TruncSext.ll create mode 100644 final/test/Integer/BitArith.ll create mode 100644 final/test/Integer/BitBit.ll create mode 100644 final/test/Integer/BitCast.ll create mode 100644 final/test/Integer/BitIcmp.ll create mode 100644 final/test/Integer/BitMem.ll create mode 100644 final/test/Integer/BitMisc.ll create mode 100644 final/test/Integer/BitPacked.ll create mode 100644 final/test/Integer/alignment_bt.ll create mode 100644 final/test/Integer/basictest_bt.ll create mode 100644 final/test/Integer/cfgstructures_bt.ll create mode 100644 final/test/Integer/constexpr_bt.ll create mode 100644 final/test/Integer/constpointer_bt.ll create mode 100644 final/test/Integer/dg.exp create mode 100644 final/test/Integer/fold-fpcast_bt.ll create mode 100644 final/test/Integer/forwardreftest_bt.ll create mode 100644 final/test/Integer/globalredefinition_bt.ll create mode 100644 final/test/Integer/globalvars_bt.ll create mode 100644 final/test/Integer/indirectcall2_bt.ll create mode 100644 final/test/Integer/indirectcall_bt.ll create mode 100644 final/test/Integer/instructions_bt.ll create mode 100644 final/test/Integer/newcasts_bt.ll create mode 100644 final/test/Integer/opaquetypes_bt.ll create mode 100644 final/test/Integer/packed_bt.ll create mode 100644 final/test/Integer/packed_struct_bt.ll create mode 100644 final/test/Integer/paramattrs_bt.ll create mode 100644 final/test/Integer/properties_bt.ll create mode 100644 final/test/Integer/prototype_bt.ll create mode 100644 final/test/Integer/recursivetype_bt.ll create mode 100644 final/test/Integer/simplecalltest_bt.ll create mode 100644 final/test/Integer/small_bt.ll create mode 100644 final/test/Integer/testalloca_bt.ll create mode 100644 final/test/Integer/testarith_bt.ll create mode 100644 final/test/Integer/testconstants_bt.ll create mode 100644 final/test/Integer/testicmp_bt.ll create mode 100644 final/test/Integer/testlogical_bt.ll create mode 100644 final/test/Integer/testlogical_new_bt.ll create mode 100644 final/test/Integer/testmemory_bt.ll create mode 100644 final/test/Integer/testswitch_bt.ll create mode 100644 final/test/Integer/testvarargs_bt.ll create mode 100644 final/test/Integer/undefined_bt.ll create mode 100644 final/test/Integer/unreachable_bt.ll create mode 100644 final/test/Integer/varargs_bt.ll create mode 100644 final/test/Integer/varargs_new_bt.ll create mode 100644 final/test/LLVMC/Alias.td create mode 100644 final/test/LLVMC/AppendCmdHook.td create mode 100644 final/test/LLVMC/C++/dash-x.cpp create mode 100644 final/test/LLVMC/C++/dg.exp create mode 100644 final/test/LLVMC/C++/filelist.cpp create mode 100644 final/test/LLVMC/C++/hello.cpp create mode 100644 final/test/LLVMC/C++/just-compile.cpp create mode 100644 final/test/LLVMC/C++/together.cpp create mode 100644 final/test/LLVMC/C++/unknown_suffix.unk create mode 100644 final/test/LLVMC/C/dg.exp create mode 100644 final/test/LLVMC/C/emit-llvm-opt.c create mode 100644 final/test/LLVMC/C/emit-llvm.c create mode 100644 final/test/LLVMC/C/hello.c create mode 100644 final/test/LLVMC/C/include.c create mode 100644 final/test/LLVMC/C/opt-test.c create mode 100644 final/test/LLVMC/C/sink.c create mode 100644 final/test/LLVMC/C/wall.c create mode 100644 final/test/LLVMC/EmptyCompilationGraph.td create mode 100644 final/test/LLVMC/EnvParentheses.td create mode 100644 final/test/LLVMC/ForwardAs.td create mode 100644 final/test/LLVMC/ForwardTransformedValue.td create mode 100644 final/test/LLVMC/ForwardValue.td create mode 100644 final/test/LLVMC/HookWithArguments.td create mode 100644 final/test/LLVMC/HookWithInFile.td create mode 100644 final/test/LLVMC/Init.td create mode 100644 final/test/LLVMC/LanguageMap.td create mode 100644 final/test/LLVMC/MultiValuedOption.td create mode 100644 final/test/LLVMC/MultipleCompilationGraphs.td create mode 100644 final/test/LLVMC/MultipleOutputLanguages.td create mode 100644 final/test/LLVMC/NoActions.td create mode 100644 final/test/LLVMC/NoCompilationGraph.td create mode 100644 final/test/LLVMC/ObjC++/dg.exp create mode 100644 final/test/LLVMC/ObjC++/hello.mm create mode 100644 final/test/LLVMC/ObjC/dg.exp create mode 100644 final/test/LLVMC/ObjC/hello.m create mode 100644 final/test/LLVMC/OneOrMore.td create mode 100644 final/test/LLVMC/OptionPreprocessor.td create mode 100644 final/test/LLVMC/OutputSuffixHook.td create mode 100644 final/test/LLVMC/TestWarnings.td create mode 100644 final/test/LLVMC/dg.exp create mode 100644 final/test/LLVMC/test_data/false.c create mode 100644 final/test/LLVMC/test_data/false.cpp create mode 100644 final/test/LLVMC/test_data/false2.cpp create mode 100644 final/test/LLVMC/test_data/together.c create mode 100644 final/test/Linker/2002-07-17-GlobalFail.ll create mode 100644 final/test/Linker/2002-07-17-LinkTest2.ll create mode 100644 final/test/Linker/2002-08-20-ConstantExpr.ll create mode 100644 final/test/Linker/2003-01-30-LinkerRename.ll create mode 100644 final/test/Linker/2003-01-30-LinkerTypeRename.ll create mode 100644 final/test/Linker/2003-04-21-Linkage.ll create mode 100644 final/test/Linker/2003-04-23-LinkOnceLost.ll create mode 100644 final/test/Linker/2003-04-26-NullPtrLinkProblem.ll create mode 100644 final/test/Linker/2003-05-15-TypeProblem.ll create mode 100644 final/test/Linker/2003-05-31-LinkerRename.ll create mode 100644 final/test/Linker/2003-06-02-TypeResolveProblem.ll create mode 100644 final/test/Linker/2003-06-02-TypeResolveProblem2.ll create mode 100644 final/test/Linker/2003-08-20-OpaqueTypeResolve.ll create mode 100644 final/test/Linker/2003-08-23-GlobalVarLinking.ll create mode 100644 final/test/Linker/2003-08-23-RecursiveOpaqueTypeResolve.ll create mode 100644 final/test/Linker/2003-08-24-InheritPtrSize.ll create mode 100644 final/test/Linker/2003-08-28-TypeResolvesGlobal.ll create mode 100644 final/test/Linker/2003-08-28-TypeResolvesGlobal2.ll create mode 100644 final/test/Linker/2003-08-28-TypeResolvesGlobal3.ll create mode 100644 final/test/Linker/2003-10-21-ConflictingTypesTolerance.ll create mode 100644 final/test/Linker/2003-10-27-LinkOncePromote.ll create mode 100644 final/test/Linker/2003-11-18-TypeResolution.ll create mode 100644 final/test/Linker/2004-02-17-WeakStrongLinkage.ll create mode 100644 final/test/Linker/2004-05-07-TypeResolution1.ll create mode 100644 final/test/Linker/2004-05-07-TypeResolution2.ll create mode 100644 final/test/Linker/2004-12-03-DisagreeingType.ll create mode 100644 final/test/Linker/2005-02-12-ConstantGlobals-2.ll create mode 100644 final/test/Linker/2005-02-12-ConstantGlobals.ll create mode 100644 final/test/Linker/2005-12-06-AppendingZeroLengthArrays.ll create mode 100644 final/test/Linker/2006-01-19-ConstantPacked.ll create mode 100644 final/test/Linker/2006-06-15-GlobalVarAlignment.ll create mode 100644 final/test/Linker/2008-03-05-AliasReference.ll create mode 100644 final/test/Linker/2008-03-05-AliasReference2.ll create mode 100644 final/test/Linker/2008-03-07-DroppedSection_a.ll create mode 100644 final/test/Linker/2008-03-07-DroppedSection_b.ll create mode 100644 final/test/Linker/2008-06-13-LinkOnceRedefinition.ll create mode 100644 final/test/Linker/2008-06-26-AddressSpace.ll create mode 100644 final/test/Linker/2008-07-06-AliasFnDecl.ll create mode 100644 final/test/Linker/2008-07-06-AliasFnDecl2.ll create mode 100644 final/test/Linker/2008-07-06-AliasWeakDest.ll create mode 100644 final/test/Linker/2008-07-06-AliasWeakDest2.ll create mode 100644 final/test/Linker/2009-09-03-mdnode.ll create mode 100644 final/test/Linker/2009-09-03-mdnode2.ll create mode 100644 final/test/Linker/AppendingLinkage.ll create mode 100644 final/test/Linker/AppendingLinkage2.ll create mode 100644 final/test/Linker/ConstantGlobals1.ll create mode 100644 final/test/Linker/ConstantGlobals2.ll create mode 100644 final/test/Linker/ConstantGlobals3.ll create mode 100644 final/test/Linker/LinkOnce.ll create mode 100644 final/test/Linker/PR8300.ll create mode 100644 final/test/Linker/available_externally_a.ll create mode 100644 final/test/Linker/available_externally_b.ll create mode 100644 final/test/Linker/basiclink.ll create mode 100644 final/test/Linker/dg.exp create mode 100644 final/test/Linker/link-archive.ll create mode 100644 final/test/Linker/link-global-to-func.ll create mode 100644 final/test/Linker/link-messages.ll create mode 100644 final/test/Linker/linkmdnode.ll create mode 100644 final/test/Linker/linkmdnode2.ll create mode 100644 final/test/Linker/linknamedmdnode.ll create mode 100644 final/test/Linker/linknamedmdnode2.ll create mode 100644 final/test/Linker/metadata-a.ll create mode 100644 final/test/Linker/metadata-b.ll create mode 100644 final/test/Linker/partial-type-refinement-link.ll create mode 100644 final/test/Linker/partial-type-refinement.ll create mode 100644 final/test/Linker/redefinition.ll create mode 100644 final/test/Linker/testlink1.ll create mode 100644 final/test/Linker/testlink2.ll create mode 100644 final/test/Linker/unnamed-addr1-a.ll create mode 100644 final/test/Linker/unnamed-addr1-b.ll create mode 100644 final/test/Linker/weakextern.ll create mode 100644 final/test/MC/ARM/arm_fixups.s create mode 100644 final/test/MC/ARM/arm_instructions.s create mode 100644 final/test/MC/ARM/arm_word_directive.s create mode 100644 final/test/MC/ARM/bracket-darwin.s create mode 100644 final/test/MC/ARM/bracket-exprs.s create mode 100644 final/test/MC/ARM/darwin-ARM-reloc.s create mode 100644 final/test/MC/ARM/darwin-Thumb-reloc.s create mode 100644 final/test/MC/ARM/dg.exp create mode 100644 final/test/MC/ARM/elf-eflags-eabi.s create mode 100644 final/test/MC/ARM/elf-movt.s create mode 100644 final/test/MC/ARM/elf-reloc-01.ll create mode 100644 final/test/MC/ARM/elf-reloc-02.ll create mode 100644 final/test/MC/ARM/elf-reloc-03.ll create mode 100644 final/test/MC/ARM/full_line_comment.s create mode 100644 final/test/MC/ARM/hilo-16bit-relocations.s create mode 100644 final/test/MC/ARM/neon-abs-encoding.s create mode 100644 final/test/MC/ARM/neon-absdiff-encoding.s create mode 100644 final/test/MC/ARM/neon-add-encoding.s create mode 100644 final/test/MC/ARM/neon-bitcount-encoding.s create mode 100644 final/test/MC/ARM/neon-bitwise-encoding.s create mode 100644 final/test/MC/ARM/neon-cmp-encoding.s create mode 100644 final/test/MC/ARM/neon-convert-encoding.s create mode 100644 final/test/MC/ARM/neon-dup-encoding.s create mode 100644 final/test/MC/ARM/neon-minmax-encoding.s create mode 100644 final/test/MC/ARM/neon-mov-encoding.s create mode 100644 final/test/MC/ARM/neon-mul-accum-encoding.s create mode 100644 final/test/MC/ARM/neon-mul-encoding.s create mode 100644 final/test/MC/ARM/neon-neg-encoding.s create mode 100644 final/test/MC/ARM/neon-pairwise-encoding.s create mode 100644 final/test/MC/ARM/neon-reciprocal-encoding.s create mode 100644 final/test/MC/ARM/neon-reverse-encoding.s create mode 100644 final/test/MC/ARM/neon-satshift-encoding.s create mode 100644 final/test/MC/ARM/neon-shift-encoding.s create mode 100644 final/test/MC/ARM/neon-shiftaccum-encoding.s create mode 100644 final/test/MC/ARM/neon-shuffle-encoding.s create mode 100644 final/test/MC/ARM/neon-sub-encoding.s create mode 100644 final/test/MC/ARM/neon-table-encoding.s create mode 100644 final/test/MC/ARM/neon-vld-encoding.s create mode 100644 final/test/MC/ARM/neon-vst-encoding.s create mode 100644 final/test/MC/ARM/neont2-abs-encoding.s create mode 100644 final/test/MC/ARM/neont2-absdiff-encoding.s create mode 100644 final/test/MC/ARM/neont2-add-encoding.s create mode 100644 final/test/MC/ARM/neont2-bitcount-encoding.s create mode 100644 final/test/MC/ARM/neont2-bitwise-encoding.s create mode 100644 final/test/MC/ARM/neont2-cmp-encoding.s create mode 100644 final/test/MC/ARM/neont2-convert-encoding.s create mode 100644 final/test/MC/ARM/neont2-dup-encoding.s create mode 100644 final/test/MC/ARM/neont2-minmax-encoding.s create mode 100644 final/test/MC/ARM/neont2-mov-encoding.s create mode 100644 final/test/MC/ARM/neont2-mul-accum-encoding.s create mode 100644 final/test/MC/ARM/neont2-mul-encoding.s create mode 100644 final/test/MC/ARM/neont2-neg-encoding.s create mode 100644 final/test/MC/ARM/neont2-pairwise-encoding.s create mode 100644 final/test/MC/ARM/neont2-reciprocal-encoding.s create mode 100644 final/test/MC/ARM/neont2-reverse-encoding.s create mode 100644 final/test/MC/ARM/neont2-satshift-encoding.s create mode 100644 final/test/MC/ARM/neont2-shift-encoding.s create mode 100644 final/test/MC/ARM/neont2-shiftaccum-encoding.s create mode 100644 final/test/MC/ARM/neont2-shuffle-encoding.s create mode 100644 final/test/MC/ARM/neont2-sub-encoding.s create mode 100644 final/test/MC/ARM/neont2-table-encoding.s create mode 100644 final/test/MC/ARM/neont2-vld-encoding.s create mode 100644 final/test/MC/ARM/neont2-vst-encoding.s create mode 100644 final/test/MC/ARM/prefetch.ll create mode 100644 final/test/MC/ARM/reg-list.s create mode 100644 final/test/MC/ARM/simple-encoding.ll create mode 100644 final/test/MC/ARM/simple-fp-encoding.s create mode 100644 final/test/MC/ARM/thumb.s create mode 100644 final/test/MC/ARM/thumb2.s create mode 100644 final/test/MC/ARM/thumb2_instructions.s create mode 100644 final/test/MC/AsmParser/assignment.s create mode 100644 final/test/MC/AsmParser/conditional_asm.s create mode 100644 final/test/MC/AsmParser/dash-n.s create mode 100644 final/test/MC/AsmParser/dg.exp create mode 100644 final/test/MC/AsmParser/directive_abort.s create mode 100644 final/test/MC/AsmParser/directive_align.s create mode 100644 final/test/MC/AsmParser/directive_ascii.s create mode 100644 final/test/MC/AsmParser/directive_comm.s create mode 100644 final/test/MC/AsmParser/directive_darwin_section.s create mode 100644 final/test/MC/AsmParser/directive_desc.s create mode 100644 final/test/MC/AsmParser/directive_elf_size.s create mode 100644 final/test/MC/AsmParser/directive_file.s create mode 100644 final/test/MC/AsmParser/directive_fill.s create mode 100644 final/test/MC/AsmParser/directive_include.s create mode 100644 final/test/MC/AsmParser/directive_lcomm.s create mode 100644 final/test/MC/AsmParser/directive_line.s create mode 100644 final/test/MC/AsmParser/directive_loc.s create mode 100644 final/test/MC/AsmParser/directive_lsym.s create mode 100644 final/test/MC/AsmParser/directive_org.s create mode 100644 final/test/MC/AsmParser/directive_set.s create mode 100644 final/test/MC/AsmParser/directive_space.s create mode 100644 final/test/MC/AsmParser/directive_subsections_via_symbols.s create mode 100644 final/test/MC/AsmParser/directive_symbol_attrs.s create mode 100644 final/test/MC/AsmParser/directive_tbss.s create mode 100644 final/test/MC/AsmParser/directive_tdata.s create mode 100644 final/test/MC/AsmParser/directive_thread_init_func.s create mode 100644 final/test/MC/AsmParser/directive_tlv.s create mode 100644 final/test/MC/AsmParser/directive_values.s create mode 100644 final/test/MC/AsmParser/directive_zerofill.s create mode 100644 final/test/MC/AsmParser/dollars-in-identifiers.s create mode 100644 final/test/MC/AsmParser/equ.s create mode 100644 final/test/MC/AsmParser/expr_symbol_modifiers.s create mode 100644 final/test/MC/AsmParser/exprs-invalid.s create mode 100644 final/test/MC/AsmParser/exprs.s create mode 100644 final/test/MC/AsmParser/floating-literals.s create mode 100644 final/test/MC/AsmParser/hello.s create mode 100644 final/test/MC/AsmParser/ifdef.s create mode 100644 final/test/MC/AsmParser/ifndef.s create mode 100644 final/test/MC/AsmParser/labels.s create mode 100644 final/test/MC/AsmParser/macro-def-in-instantiation.s create mode 100644 final/test/MC/AsmParser/macros-parsing.s create mode 100644 final/test/MC/AsmParser/macros.s create mode 100644 final/test/MC/AsmParser/rename.s create mode 100644 final/test/MC/AsmParser/section.s create mode 100644 final/test/MC/AsmParser/variables-invalid.s create mode 100644 final/test/MC/AsmParser/variables.s create mode 100644 final/test/MC/COFF/align-nops.s create mode 100644 final/test/MC/COFF/basic-coff.s create mode 100644 final/test/MC/COFF/bss.s create mode 100644 final/test/MC/COFF/dg.exp create mode 100644 final/test/MC/COFF/module-asm.ll create mode 100644 final/test/MC/COFF/simple-fixups.s create mode 100644 final/test/MC/COFF/switch-relocations.ll create mode 100644 final/test/MC/COFF/symbol-alias.s create mode 100644 final/test/MC/COFF/symbol-fragment-offset.s create mode 100644 final/test/MC/COFF/weak.s create mode 100644 final/test/MC/Disassembler/ARM/arm-tests.txt create mode 100644 final/test/MC/Disassembler/ARM/dg.exp create mode 100644 final/test/MC/Disassembler/ARM/neon-tests.txt create mode 100644 final/test/MC/Disassembler/ARM/thumb-tests.txt create mode 100644 final/test/MC/Disassembler/MBlaze/dg.exp create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_branch.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_fpu.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_fsl.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_imm.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_memory.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_operands.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_pattern.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_shift.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_special.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_typea.txt create mode 100644 final/test/MC/Disassembler/MBlaze/mblaze_typeb.txt create mode 100644 final/test/MC/Disassembler/X86/dg.exp create mode 100644 final/test/MC/Disassembler/X86/enhanced.txt create mode 100644 final/test/MC/Disassembler/X86/simple-tests.txt create mode 100644 final/test/MC/Disassembler/X86/truncated-input.txt create mode 100644 final/test/MC/ELF/abs.s create mode 100644 final/test/MC/ELF/alias-reloc.s create mode 100644 final/test/MC/ELF/alias.s create mode 100644 final/test/MC/ELF/align-bss.s create mode 100644 final/test/MC/ELF/align-nops.s create mode 100644 final/test/MC/ELF/align-size.s create mode 100644 final/test/MC/ELF/align-text.s create mode 100644 final/test/MC/ELF/align.s create mode 100644 final/test/MC/ELF/bad-section.s create mode 100644 final/test/MC/ELF/basic-elf-32.s create mode 100644 final/test/MC/ELF/basic-elf-64.s create mode 100644 final/test/MC/ELF/bracket-exprs.s create mode 100644 final/test/MC/ELF/bracket.s create mode 100644 final/test/MC/ELF/bss.ll create mode 100644 final/test/MC/ELF/call-abs.s create mode 100644 final/test/MC/ELF/cfi-advance-loc2.s create mode 100644 final/test/MC/ELF/cfi-def-cfa-offset.s create mode 100644 final/test/MC/ELF/cfi-def-cfa-register.s create mode 100644 final/test/MC/ELF/cfi-def-cfa.s create mode 100644 final/test/MC/ELF/cfi-offset.s create mode 100644 final/test/MC/ELF/cfi-remember.s create mode 100644 final/test/MC/ELF/cfi-zero-addr-delta.s create mode 100644 final/test/MC/ELF/cfi.s create mode 100644 final/test/MC/ELF/comdat.s create mode 100644 final/test/MC/ELF/common.s create mode 100644 final/test/MC/ELF/common2.s create mode 100644 final/test/MC/ELF/debug-line.s create mode 100644 final/test/MC/ELF/debug-loc.s create mode 100644 final/test/MC/ELF/dg.exp create mode 100644 final/test/MC/ELF/diff.s create mode 100644 final/test/MC/ELF/diff2.s create mode 100644 final/test/MC/ELF/elf_directive_previous.s create mode 100644 final/test/MC/ELF/elf_directive_section.s create mode 100644 final/test/MC/ELF/empty-dwarf-lines.s create mode 100644 final/test/MC/ELF/empty.s create mode 100644 final/test/MC/ELF/entsize.ll create mode 100644 final/test/MC/ELF/entsize.s create mode 100644 final/test/MC/ELF/file.s create mode 100644 final/test/MC/ELF/global-offset.s create mode 100644 final/test/MC/ELF/got.s create mode 100644 final/test/MC/ELF/ident.s create mode 100644 final/test/MC/ELF/invalid-symver.s create mode 100644 final/test/MC/ELF/leb128.s create mode 100644 final/test/MC/ELF/local-reloc.s create mode 100644 final/test/MC/ELF/merge.s create mode 100644 final/test/MC/ELF/n_bytes.s create mode 100644 final/test/MC/ELF/no-fixup.s create mode 100644 final/test/MC/ELF/noexec.s create mode 100644 final/test/MC/ELF/norelocation.s create mode 100644 final/test/MC/ELF/org.s create mode 100644 final/test/MC/ELF/pic-diff.s create mode 100644 final/test/MC/ELF/plt.s create mode 100644 final/test/MC/ELF/pr9292.s create mode 100644 final/test/MC/ELF/relax-arith.s create mode 100644 final/test/MC/ELF/relax-crash.s create mode 100644 final/test/MC/ELF/relax.s create mode 100644 final/test/MC/ELF/relocation-386.s create mode 100644 final/test/MC/ELF/relocation-pc.s create mode 100644 final/test/MC/ELF/relocation.s create mode 100644 final/test/MC/ELF/rename.s create mode 100644 final/test/MC/ELF/section-quoting.s create mode 100644 final/test/MC/ELF/section.s create mode 100644 final/test/MC/ELF/set.s create mode 100644 final/test/MC/ELF/sleb.s create mode 100644 final/test/MC/ELF/symref.s create mode 100644 final/test/MC/ELF/tls-i386.s create mode 100644 final/test/MC/ELF/tls.s create mode 100644 final/test/MC/ELF/type.s create mode 100644 final/test/MC/ELF/uleb.s create mode 100644 final/test/MC/ELF/undef.s create mode 100644 final/test/MC/ELF/undef2.s create mode 100644 final/test/MC/ELF/weak-relocation.s create mode 100644 final/test/MC/ELF/weak.s create mode 100644 final/test/MC/ELF/weakref-plt.s create mode 100644 final/test/MC/ELF/weakref-reloc.s create mode 100644 final/test/MC/ELF/weakref.s create mode 100644 final/test/MC/ELF/zero.s create mode 100644 final/test/MC/MBlaze/dg.exp create mode 100644 final/test/MC/MBlaze/mblaze_branch.s create mode 100644 final/test/MC/MBlaze/mblaze_fpu.s create mode 100644 final/test/MC/MBlaze/mblaze_fsl.s create mode 100644 final/test/MC/MBlaze/mblaze_imm.s create mode 100644 final/test/MC/MBlaze/mblaze_memory.s create mode 100644 final/test/MC/MBlaze/mblaze_operands.s create mode 100644 final/test/MC/MBlaze/mblaze_pattern.s create mode 100644 final/test/MC/MBlaze/mblaze_shift.s create mode 100644 final/test/MC/MBlaze/mblaze_special.s create mode 100644 final/test/MC/MBlaze/mblaze_typea.s create mode 100644 final/test/MC/MBlaze/mblaze_typeb.s create mode 100644 final/test/MC/MachO/absolutize.s create mode 100644 final/test/MC/MachO/comm-1.s create mode 100644 final/test/MC/MachO/darwin-complex-difference.s create mode 100644 final/test/MC/MachO/darwin-x86_64-diff-relocs.s create mode 100644 final/test/MC/MachO/darwin-x86_64-reloc-offsets.s create mode 100644 final/test/MC/MachO/darwin-x86_64-reloc.s create mode 100644 final/test/MC/MachO/data.s create mode 100644 final/test/MC/MachO/dg.exp create mode 100644 final/test/MC/MachO/diff-with-two-sections.s create mode 100644 final/test/MC/MachO/direction_labels.s create mode 100644 final/test/MC/MachO/empty-dwarf-lines.s create mode 100644 final/test/MC/MachO/indirect-symbols.s create mode 100644 final/test/MC/MachO/jcc.s create mode 100644 final/test/MC/MachO/lcomm-attributes.s create mode 100644 final/test/MC/MachO/loc.s create mode 100644 final/test/MC/MachO/pcrel-to-other-section.s create mode 100644 final/test/MC/MachO/relax-jumps.s create mode 100644 final/test/MC/MachO/relax-recompute-align.s create mode 100644 final/test/MC/MachO/reloc-diff.s create mode 100644 final/test/MC/MachO/reloc-pcrel-offset.s create mode 100644 final/test/MC/MachO/reloc-pcrel.s create mode 100644 final/test/MC/MachO/reloc.s create mode 100644 final/test/MC/MachO/section-align-1.s create mode 100644 final/test/MC/MachO/section-align-2.s create mode 100644 final/test/MC/MachO/section-flags.s create mode 100644 final/test/MC/MachO/string-table.s create mode 100644 final/test/MC/MachO/symbol-diff.s create mode 100644 final/test/MC/MachO/symbol-flags.s create mode 100644 final/test/MC/MachO/symbol-indirect.s create mode 100644 final/test/MC/MachO/symbols-1.s create mode 100644 final/test/MC/MachO/tbss.s create mode 100644 final/test/MC/MachO/tdata.s create mode 100644 final/test/MC/MachO/thread_init_func.s create mode 100644 final/test/MC/MachO/tls.s create mode 100644 final/test/MC/MachO/tlv-reloc.s create mode 100644 final/test/MC/MachO/tlv.s create mode 100644 final/test/MC/MachO/values.s create mode 100644 final/test/MC/MachO/weakdef.s create mode 100644 final/test/MC/MachO/x86_32-optimal_nop.s create mode 100644 final/test/MC/MachO/x86_32-sections.s create mode 100644 final/test/MC/MachO/x86_32-symbols.s create mode 100644 final/test/MC/MachO/x86_64-sections.s create mode 100644 final/test/MC/MachO/x86_64-symbols.s create mode 100644 final/test/MC/MachO/zerofill-1.s create mode 100644 final/test/MC/MachO/zerofill-2.s create mode 100644 final/test/MC/MachO/zerofill-3.s create mode 100644 final/test/MC/MachO/zerofill-4.s create mode 100644 final/test/MC/MachO/zerofill-5.s create mode 100644 final/test/MC/MachO/zerofill-sect-align.s create mode 100644 final/test/MC/X86/3DNow.s create mode 100644 final/test/MC/X86/dg.exp create mode 100644 final/test/MC/X86/x86-32-avx.s create mode 100644 final/test/MC/X86/x86-32-coverage.s create mode 100644 final/test/MC/X86/x86-32-fma3.s create mode 100644 final/test/MC/X86/x86-32.s create mode 100644 final/test/MC/X86/x86-64.s create mode 100644 final/test/MC/X86/x86_64-avx-clmul-encoding.s create mode 100644 final/test/MC/X86/x86_64-avx-encoding.s create mode 100644 final/test/MC/X86/x86_64-encoding.s create mode 100644 final/test/MC/X86/x86_64-fma3-encoding.s create mode 100644 final/test/MC/X86/x86_64-imm-widths.s create mode 100644 final/test/MC/X86/x86_directives.s create mode 100644 final/test/MC/X86/x86_errors.s create mode 100644 final/test/MC/X86/x86_operands.s create mode 100644 final/test/Makefile create mode 100644 final/test/Makefile.tests create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.coff-i386 create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.coff-x86-64 create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.elf-i386 create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.elf-x86-64 create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.macho-i386 create mode 100644 final/test/Object/TestObjectFiles/trivial-object-test.macho-x86-64 create mode 100644 final/test/Object/dg.exp create mode 100644 final/test/Object/nm-trivial-object.test-broken create mode 100644 final/test/Object/objdump-trivial-object.test-broken create mode 100644 final/test/Other/2002-01-31-CallGraph.ll create mode 100644 final/test/Other/2002-02-24-InlineBrokePHINodes.ll create mode 100644 final/test/Other/2002-03-11-ConstPropCrash.ll create mode 100644 final/test/Other/2003-02-19-LoopInfoNestingBug.ll create mode 100644 final/test/Other/2004-08-16-PackedConstantInlineStore.ll create mode 100644 final/test/Other/2004-08-16-PackedGlobalConstant.ll create mode 100644 final/test/Other/2004-08-16-PackedSelect.ll create mode 100644 final/test/Other/2004-08-16-PackedSimple.ll create mode 100644 final/test/Other/2004-08-20-PackedControlFlow.ll create mode 100644 final/test/Other/2006-02-05-PassManager.ll create mode 100644 final/test/Other/2007-04-24-eliminate-mostly-empty-blocks.ll create mode 100644 final/test/Other/2007-06-05-PassID.ll create mode 100644 final/test/Other/2007-06-28-PassManager.ll create mode 100644 final/test/Other/2007-09-10-PassManager.ll create mode 100644 final/test/Other/2008-02-14-PassManager.ll create mode 100644 final/test/Other/2008-06-04-FieldSizeInPacked.ll create mode 100644 final/test/Other/2008-10-06-RemoveDeadPass.ll create mode 100644 final/test/Other/2008-10-15-MissingSpace.ll create mode 100644 final/test/Other/2009-03-31-CallGraph.ll create mode 100644 final/test/Other/2009-06-05-no-implicit-float.ll create mode 100644 final/test/Other/2009-09-14-function-elements.ll create mode 100644 final/test/Other/2010-05-06-Printer.ll create mode 100644 final/test/Other/close-stderr.ll create mode 100644 final/test/Other/constant-fold-gep.ll create mode 100644 final/test/Other/dg.exp create mode 100644 final/test/Other/extract.ll create mode 100644 final/test/Other/inline-asm-newline-terminator.ll create mode 100644 final/test/Other/invalid-commandline-option.ll create mode 100644 final/test/Other/lint.ll create mode 100644 final/test/Scripts/README.txt create mode 100755 final/test/Scripts/coff-dump.py create mode 100644 final/test/Scripts/coff-dump.py.bat create mode 100644 final/test/Scripts/common_dump.py create mode 100755 final/test/Scripts/elf-dump create mode 100644 final/test/Scripts/elf-dump.bat create mode 100755 final/test/Scripts/ignore create mode 100755 final/test/Scripts/macho-dumpx create mode 100644 final/test/Scripts/macho-dumpx.bat create mode 100644 final/test/TableGen/2003-08-03-PassCode.td create mode 100644 final/test/TableGen/2006-09-18-LargeInt.td create mode 100644 final/test/TableGen/2010-03-24-PrematureDefaults.td create mode 100644 final/test/TableGen/AnonDefinitionOnDemand.td create mode 100644 final/test/TableGen/BitsInitOverflow.td create mode 100644 final/test/TableGen/CStyleComment.td create mode 100644 final/test/TableGen/Dag.td create mode 100644 final/test/TableGen/DefmInherit.td create mode 100644 final/test/TableGen/DefmInsideMultiClass.td create mode 100644 final/test/TableGen/FieldAccess.td create mode 100644 final/test/TableGen/ForwardRef.td create mode 100644 final/test/TableGen/GeneralList.td create mode 100644 final/test/TableGen/Include.inc create mode 100644 final/test/TableGen/Include.td create mode 100644 final/test/TableGen/IntBitInit.td create mode 100644 final/test/TableGen/LazyChange.td create mode 100644 final/test/TableGen/LetInsideMultiClasses.td create mode 100644 final/test/TableGen/ListArgs.td create mode 100644 final/test/TableGen/ListArgsSimple.td create mode 100644 final/test/TableGen/ListConversion.td create mode 100644 final/test/TableGen/ListManip.td create mode 100644 final/test/TableGen/ListSlices.td create mode 100644 final/test/TableGen/MultiClass.td create mode 100644 final/test/TableGen/MultiClassDefName.td create mode 100644 final/test/TableGen/MultiClassInherit.td create mode 100644 final/test/TableGen/Slice.td create mode 100644 final/test/TableGen/String.td create mode 100644 final/test/TableGen/SuperSubclassSameName.td create mode 100644 final/test/TableGen/TargetInstrInfo.td create mode 100644 final/test/TableGen/TargetInstrSpec.td create mode 100644 final/test/TableGen/TemplateArgRename.td create mode 100644 final/test/TableGen/Tree.td create mode 100644 final/test/TableGen/TreeNames.td create mode 100644 final/test/TableGen/UnsetBitInit.td create mode 100644 final/test/TableGen/UnterminatedComment.td create mode 100644 final/test/TableGen/cast.td create mode 100644 final/test/TableGen/defmclass.td create mode 100644 final/test/TableGen/dg.exp create mode 100644 final/test/TableGen/eq.td create mode 100644 final/test/TableGen/eqbit.td create mode 100644 final/test/TableGen/foreach.td create mode 100644 final/test/TableGen/if.td create mode 100644 final/test/TableGen/ifbit.td create mode 100644 final/test/TableGen/lisp.td create mode 100644 final/test/TableGen/nested-comment.td create mode 100644 final/test/TableGen/strconcat.td create mode 100644 final/test/TableGen/subst.td create mode 100644 final/test/TableGen/subst2.td create mode 100644 final/test/TableGen/usevalname.td create mode 100755 final/test/TestRunner.sh create mode 100644 final/test/Transforms/ADCE/2002-01-31-UseStuckAround.ll create mode 100644 final/test/Transforms/ADCE/2002-05-22-PHITest.ll create mode 100644 final/test/Transforms/ADCE/2002-05-23-ZeroArgPHITest.ll create mode 100644 final/test/Transforms/ADCE/2002-05-28-Crash-distilled.ll create mode 100644 final/test/Transforms/ADCE/2002-05-28-Crash.ll create mode 100644 final/test/Transforms/ADCE/2002-07-17-AssertionFailure.ll create mode 100644 final/test/Transforms/ADCE/2002-07-17-PHIAssertion.ll create mode 100644 final/test/Transforms/ADCE/2002-07-29-Segfault.ll create mode 100644 final/test/Transforms/ADCE/2003-01-22-PredecessorProblem.ll create mode 100644 final/test/Transforms/ADCE/2003-04-25-PHIPostDominateProblem.ll create mode 100644 final/test/Transforms/ADCE/2003-06-11-InvalidCFG.ll create mode 100644 final/test/Transforms/ADCE/2003-06-24-BadSuccessor.ll create mode 100644 final/test/Transforms/ADCE/2003-06-24-BasicFunctionality.ll create mode 100644 final/test/Transforms/ADCE/2003-09-10-UnwindInstFail.ll create mode 100644 final/test/Transforms/ADCE/2003-09-15-InfLoopCrash.ll create mode 100644 final/test/Transforms/ADCE/2003-11-16-MissingPostDominanceInfo.ll create mode 100644 final/test/Transforms/ADCE/2004-05-04-UnreachableBlock.ll create mode 100644 final/test/Transforms/ADCE/2005-02-17-PHI-Invoke-Crash.ll create mode 100644 final/test/Transforms/ADCE/basictest.ll create mode 100644 final/test/Transforms/ADCE/basictest1.ll create mode 100644 final/test/Transforms/ADCE/basictest2.ll create mode 100644 final/test/Transforms/ADCE/dce_pure_call.ll create mode 100644 final/test/Transforms/ADCE/dce_pure_invoke.ll create mode 100644 final/test/Transforms/ADCE/dg.exp create mode 100644 final/test/Transforms/ADCE/unreachable-function.ll create mode 100644 final/test/Transforms/ArgumentPromotion/2008-02-01-ReturnAttrs.ll create mode 100644 final/test/Transforms/ArgumentPromotion/2008-07-02-array-indexing.ll create mode 100644 final/test/Transforms/ArgumentPromotion/2008-09-07-CGUpdate.ll create mode 100644 final/test/Transforms/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll create mode 100644 final/test/Transforms/ArgumentPromotion/aggregate-promote.ll create mode 100644 final/test/Transforms/ArgumentPromotion/attrs.ll create mode 100644 final/test/Transforms/ArgumentPromotion/basictest.ll create mode 100644 final/test/Transforms/ArgumentPromotion/byval-2.ll create mode 100644 final/test/Transforms/ArgumentPromotion/byval.ll create mode 100644 final/test/Transforms/ArgumentPromotion/callgraph-update.ll create mode 100644 final/test/Transforms/ArgumentPromotion/chained.ll create mode 100644 final/test/Transforms/ArgumentPromotion/control-flow.ll create mode 100644 final/test/Transforms/ArgumentPromotion/control-flow2.ll create mode 100644 final/test/Transforms/ArgumentPromotion/crash.ll create mode 100644 final/test/Transforms/ArgumentPromotion/dg.exp create mode 100644 final/test/Transforms/ArgumentPromotion/pr3085.ll create mode 100644 final/test/Transforms/BlockPlacement/basictest.ll create mode 100644 final/test/Transforms/BlockPlacement/dg.exp create mode 100644 final/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-13-LoopExtractorCrash.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-14-DominanceProblem.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-14-NoSwitchSupport.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-17-MissedLiveIns.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-17-OutputMismatch.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-17-UpdatePHIsOutsideRegion.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-03-18-InvokeHandling.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-08-12-BlockExtractPHI.ll create mode 100644 final/test/Transforms/CodeExtractor/2004-11-12-InvokeExtract.ll create mode 100644 final/test/Transforms/CodeExtractor/dg.exp create mode 100644 final/test/Transforms/CodeGenPrepare/2008-11-24-RAUW-Self.ll create mode 100644 final/test/Transforms/CodeGenPrepare/basic.ll create mode 100644 final/test/Transforms/CodeGenPrepare/dg.exp create mode 100644 final/test/Transforms/ConstProp/2002-05-03-DivideByZeroException.ll create mode 100644 final/test/Transforms/ConstProp/2002-05-03-NotOperator.ll create mode 100644 final/test/Transforms/ConstProp/2002-09-03-SetCC-Bools.ll create mode 100644 final/test/Transforms/ConstProp/2003-05-12-DivideError.ll create mode 100644 final/test/Transforms/ConstProp/2005-01-28-SetCCGEP.ll create mode 100644 final/test/Transforms/ConstProp/2006-11-30-vector-cast.ll create mode 100644 final/test/Transforms/ConstProp/2006-12-01-TruncBoolBug.ll create mode 100644 final/test/Transforms/ConstProp/2006-12-01-bool-casts.ll create mode 100644 final/test/Transforms/ConstProp/2007-02-05-BitCast.ll create mode 100644 final/test/Transforms/ConstProp/2007-02-23-sdiv.ll create mode 100644 final/test/Transforms/ConstProp/2007-11-23-cttz.ll create mode 100644 final/test/Transforms/ConstProp/2008-07-07-VectorCompare.ll create mode 100644 final/test/Transforms/ConstProp/2009-06-20-constexpr-zero-lhs.ll create mode 100644 final/test/Transforms/ConstProp/2009-09-01-GEP-Crash.ll create mode 100644 final/test/Transforms/ConstProp/basictest.ll create mode 100644 final/test/Transforms/ConstProp/bitcast.ll create mode 100644 final/test/Transforms/ConstProp/bswap.ll create mode 100644 final/test/Transforms/ConstProp/calls.ll create mode 100644 final/test/Transforms/ConstProp/constant-expr.ll create mode 100644 final/test/Transforms/ConstProp/dg.exp create mode 100644 final/test/Transforms/ConstProp/div-zero.ll create mode 100644 final/test/Transforms/ConstProp/extractvalue.ll create mode 100644 final/test/Transforms/ConstProp/float-to-ptr-cast.ll create mode 100644 final/test/Transforms/ConstProp/insertvalue.ll create mode 100644 final/test/Transforms/ConstProp/loads.ll create mode 100644 final/test/Transforms/ConstProp/logicaltest.ll create mode 100644 final/test/Transforms/ConstProp/overflow-ops.ll create mode 100644 final/test/Transforms/ConstProp/phi.ll create mode 100644 final/test/Transforms/ConstProp/remtest.ll create mode 100644 final/test/Transforms/ConstantMerge/2002-09-23-CPR-Update.ll create mode 100644 final/test/Transforms/ConstantMerge/2003-10-28-MergeExternalConstants.ll create mode 100644 final/test/Transforms/ConstantMerge/2011-01-15-EitherOrder.ll create mode 100644 final/test/Transforms/ConstantMerge/dg.exp create mode 100644 final/test/Transforms/ConstantMerge/dont-merge.ll create mode 100644 final/test/Transforms/ConstantMerge/merge-both.ll create mode 100644 final/test/Transforms/ConstantMerge/unnamed-addr.ll create mode 100644 final/test/Transforms/CorrelatedValuePropagation/2010-09-02-Trunc.ll create mode 100644 final/test/Transforms/CorrelatedValuePropagation/2010-09-26-MergeConstantRange.ll create mode 100644 final/test/Transforms/CorrelatedValuePropagation/basic.ll create mode 100644 final/test/Transforms/CorrelatedValuePropagation/crash.ll create mode 100644 final/test/Transforms/CorrelatedValuePropagation/dg.exp create mode 100644 final/test/Transforms/CorrelatedValuePropagation/non-null.ll create mode 100644 final/test/Transforms/DeadArgElim/2006-06-27-struct-ret.ll create mode 100644 final/test/Transforms/DeadArgElim/2007-02-07-FuncRename.ll create mode 100644 final/test/Transforms/DeadArgElim/2007-10-18-VarargsReturn.ll create mode 100644 final/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll create mode 100644 final/test/Transforms/DeadArgElim/2008-01-16-VarargsParamAttrs.ll create mode 100644 final/test/Transforms/DeadArgElim/2008-06-23-DeadAfterLive.ll create mode 100644 final/test/Transforms/DeadArgElim/2009-03-17-MRE-Invoke.ll create mode 100644 final/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll create mode 100644 final/test/Transforms/DeadArgElim/basictest.ll create mode 100644 final/test/Transforms/DeadArgElim/canon.ll create mode 100644 final/test/Transforms/DeadArgElim/dead_vaargs.ll create mode 100644 final/test/Transforms/DeadArgElim/deadexternal.ll create mode 100644 final/test/Transforms/DeadArgElim/deadretval.ll create mode 100644 final/test/Transforms/DeadArgElim/deadretval2.ll create mode 100644 final/test/Transforms/DeadArgElim/dg.exp create mode 100644 final/test/Transforms/DeadArgElim/keepalive.ll create mode 100644 final/test/Transforms/DeadArgElim/multdeadretval.ll create mode 100644 final/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll create mode 100644 final/test/Transforms/DeadStoreElimination/PartialStore.ll create mode 100644 final/test/Transforms/DeadStoreElimination/const-pointers.ll create mode 100644 final/test/Transforms/DeadStoreElimination/crash.ll create mode 100644 final/test/Transforms/DeadStoreElimination/dg.exp create mode 100644 final/test/Transforms/DeadStoreElimination/free.ll create mode 100644 final/test/Transforms/DeadStoreElimination/lifetime.ll create mode 100644 final/test/Transforms/DeadStoreElimination/memintrinsics.ll create mode 100644 final/test/Transforms/DeadStoreElimination/no-targetdata.ll create mode 100644 final/test/Transforms/DeadStoreElimination/simple.ll create mode 100644 final/test/Transforms/EarlyCSE/basic.ll create mode 100644 final/test/Transforms/EarlyCSE/dg.exp create mode 100644 final/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-09-13-VolatileRead.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-10-04-LocalMemory.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll create mode 100644 final/test/Transforms/FunctionAttrs/2008-12-31-NoCapture.ll create mode 100644 final/test/Transforms/FunctionAttrs/2009-01-02-LocalStores.ll create mode 100644 final/test/Transforms/FunctionAttrs/2009-05-06-Malloc.ll create mode 100644 final/test/Transforms/FunctionAttrs/2010-10-30-volatile.ll create mode 100644 final/test/Transforms/FunctionAttrs/dg.exp create mode 100644 final/test/Transforms/GVN/2007-07-25-DominatedLoop.ll create mode 100644 final/test/Transforms/GVN/2007-07-25-InfiniteLoop.ll create mode 100644 final/test/Transforms/GVN/2007-07-25-Loop.ll create mode 100644 final/test/Transforms/GVN/2007-07-25-NestedLoop.ll create mode 100644 final/test/Transforms/GVN/2007-07-25-SinglePredecessor.ll create mode 100644 final/test/Transforms/GVN/2007-07-26-InterlockingLoops.ll create mode 100644 final/test/Transforms/GVN/2007-07-26-NonRedundant.ll create mode 100644 final/test/Transforms/GVN/2007-07-26-PhiErasure.ll create mode 100644 final/test/Transforms/GVN/2007-07-30-PredIDom.ll create mode 100644 final/test/Transforms/GVN/2007-07-31-NoDomInherit.ll create mode 100644 final/test/Transforms/GVN/2007-07-31-RedundantPhi.ll create mode 100644 final/test/Transforms/GVN/2008-02-12-UndefLoad.ll create mode 100644 final/test/Transforms/GVN/2008-02-13-NewPHI.ll create mode 100644 final/test/Transforms/GVN/2008-02-24-NonDominatedMemcpy.ll create mode 100644 final/test/Transforms/GVN/2008-02-26-MemCpySize.ll create mode 100644 final/test/Transforms/GVN/2008-07-02-Unreachable.ll create mode 100644 final/test/Transforms/GVN/2008-12-09-SelfRemove.ll create mode 100644 final/test/Transforms/GVN/2008-12-12-RLE-Crash.ll create mode 100644 final/test/Transforms/GVN/2008-12-14-rle-reanalyze.ll create mode 100644 final/test/Transforms/GVN/2008-12-15-CacheVisited.ll create mode 100644 final/test/Transforms/GVN/2009-01-21-SortInvalidation.ll create mode 100644 final/test/Transforms/GVN/2009-01-22-SortInvalidation.ll create mode 100644 final/test/Transforms/GVN/2009-02-17-LoadPRECrash.ll create mode 100644 final/test/Transforms/GVN/2009-03-10-PREOnVoid.ll create mode 100644 final/test/Transforms/GVN/2009-06-17-InvalidPRE.ll create mode 100644 final/test/Transforms/GVN/2009-07-13-MemDepSortFail.ll create mode 100644 final/test/Transforms/GVN/2009-11-12-MemDepMallocBitCast.ll create mode 100644 final/test/Transforms/GVN/2010-03-31-RedundantPHIs.ll create mode 100644 final/test/Transforms/GVN/2010-05-08-OneBit.ll create mode 100644 final/test/Transforms/GVN/2010-11-13-Simplify.ll create mode 100644 final/test/Transforms/GVN/basic.ll create mode 100644 final/test/Transforms/GVN/bitcast-of-call.ll create mode 100644 final/test/Transforms/GVN/calls-nonlocal.ll create mode 100644 final/test/Transforms/GVN/calls-readonly.ll create mode 100644 final/test/Transforms/GVN/condprop.ll create mode 100644 final/test/Transforms/GVN/crash-no-aa.ll create mode 100644 final/test/Transforms/GVN/crash.ll create mode 100644 final/test/Transforms/GVN/dg.exp create mode 100644 final/test/Transforms/GVN/invariant-simple.ll create mode 100644 final/test/Transforms/GVN/lifetime-simple.ll create mode 100644 final/test/Transforms/GVN/load-constant-mem.ll create mode 100644 final/test/Transforms/GVN/load-pre-align.ll create mode 100644 final/test/Transforms/GVN/load-pre-licm.ll create mode 100644 final/test/Transforms/GVN/local-pre.ll create mode 100644 final/test/Transforms/GVN/lpre-call-wrap-2.ll create mode 100644 final/test/Transforms/GVN/lpre-call-wrap.ll create mode 100644 final/test/Transforms/GVN/mixed.ll create mode 100644 final/test/Transforms/GVN/non-local-offset.ll create mode 100644 final/test/Transforms/GVN/nonescaping-malloc.ll create mode 100644 final/test/Transforms/GVN/null-aliases-nothing.ll create mode 100644 final/test/Transforms/GVN/phi-translate.ll create mode 100644 final/test/Transforms/GVN/pre-basic-add.ll create mode 100644 final/test/Transforms/GVN/pre-load.ll create mode 100644 final/test/Transforms/GVN/pre-single-pred.ll create mode 100644 final/test/Transforms/GVN/preserve-tbaa.ll create mode 100644 final/test/Transforms/GVN/rle-must-alias.ll create mode 100644 final/test/Transforms/GVN/rle-no-phi-translate.ll create mode 100644 final/test/Transforms/GVN/rle-nonlocal.ll create mode 100644 final/test/Transforms/GVN/rle-phi-translate.ll create mode 100644 final/test/Transforms/GVN/rle-semidominated.ll create mode 100644 final/test/Transforms/GVN/rle.ll create mode 100644 final/test/Transforms/GlobalDCE/2002-07-17-CastRef.ll create mode 100644 final/test/Transforms/GlobalDCE/2002-07-17-ConstantRef.ll create mode 100644 final/test/Transforms/GlobalDCE/2002-08-17-FunctionDGE.ll create mode 100644 final/test/Transforms/GlobalDCE/2002-08-17-WorkListTest.ll create mode 100644 final/test/Transforms/GlobalDCE/2002-09-12-Redeletion.ll create mode 100644 final/test/Transforms/GlobalDCE/2003-07-01-SelfReference.ll create mode 100644 final/test/Transforms/GlobalDCE/2003-10-09-PreserveWeakGlobals.ll create mode 100644 final/test/Transforms/GlobalDCE/2009-01-05-DeadAliases.ll create mode 100644 final/test/Transforms/GlobalDCE/2009-02-17-AliasUsesAliasee.ll create mode 100644 final/test/Transforms/GlobalDCE/2009-09-03-MDNode.ll create mode 100644 final/test/Transforms/GlobalDCE/basicvariabletest.ll create mode 100644 final/test/Transforms/GlobalDCE/dg.exp create mode 100644 final/test/Transforms/GlobalDCE/externally_available.ll create mode 100644 final/test/Transforms/GlobalOpt/2004-10-10-CastStoreOnce.ll create mode 100644 final/test/Transforms/GlobalOpt/2005-06-15-LocalizeConstExprCrash.ll create mode 100644 final/test/Transforms/GlobalOpt/2005-09-27-Crash.ll create mode 100644 final/test/Transforms/GlobalOpt/2006-07-07-InlineAsmCrash.ll create mode 100644 final/test/Transforms/GlobalOpt/2006-11-01-ShrinkGlobalPhiCrash.ll create mode 100644 final/test/Transforms/GlobalOpt/2007-04-05-Crash.ll create mode 100644 final/test/Transforms/GlobalOpt/2007-05-13-Crash.ll create mode 100644 final/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll create mode 100644 final/test/Transforms/GlobalOpt/2007-11-09-GEP-GEP-Crash.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-01-03-Crash.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-01-13-OutOfRangeSROA.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-01-29-VolatileGlobal.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-02-16-NestAttr.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-04-26-SROA-Global-Align.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-07-17-addrspace.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash-2.ll create mode 100644 final/test/Transforms/GlobalOpt/2008-12-16-HeapSRACrash.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-01-13-phi-user.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-03-05-dbg.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-03-06-Anonymous.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-03-07-PromotePtrToBool.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-06-01-RecursivePHI.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-11-16-BrokenPerformHeapAllocSRoA.ll create mode 100644 final/test/Transforms/GlobalOpt/2009-11-16-MallocSingleStoreToGlobalVar.ll create mode 100644 final/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll create mode 100644 final/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll create mode 100644 final/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll create mode 100644 final/test/Transforms/GlobalOpt/alias-resolve.ll create mode 100644 final/test/Transforms/GlobalOpt/basictest.ll create mode 100644 final/test/Transforms/GlobalOpt/constantexpr-dangle.ll create mode 100644 final/test/Transforms/GlobalOpt/constantfold-initializers.ll create mode 100644 final/test/Transforms/GlobalOpt/crash.ll create mode 100644 final/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll create mode 100644 final/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll create mode 100644 final/test/Transforms/GlobalOpt/ctor-list-opt.ll create mode 100644 final/test/Transforms/GlobalOpt/deadglobal-2.ll create mode 100644 final/test/Transforms/GlobalOpt/deadglobal.ll create mode 100644 final/test/Transforms/GlobalOpt/dg.exp create mode 100644 final/test/Transforms/GlobalOpt/globalsra-partial.ll create mode 100644 final/test/Transforms/GlobalOpt/globalsra-unknown-index.ll create mode 100644 final/test/Transforms/GlobalOpt/globalsra.ll create mode 100644 final/test/Transforms/GlobalOpt/heap-sra-1.ll create mode 100644 final/test/Transforms/GlobalOpt/heap-sra-2.ll create mode 100644 final/test/Transforms/GlobalOpt/heap-sra-3.ll create mode 100644 final/test/Transforms/GlobalOpt/heap-sra-4.ll create mode 100644 final/test/Transforms/GlobalOpt/heap-sra-phi.ll create mode 100644 final/test/Transforms/GlobalOpt/integer-bool.ll create mode 100644 final/test/Transforms/GlobalOpt/iterate.ll create mode 100644 final/test/Transforms/GlobalOpt/load-store-global.ll create mode 100644 final/test/Transforms/GlobalOpt/malloc-promote-1.ll create mode 100644 final/test/Transforms/GlobalOpt/malloc-promote-2.ll create mode 100644 final/test/Transforms/GlobalOpt/memcpy.ll create mode 100644 final/test/Transforms/GlobalOpt/memset.ll create mode 100644 final/test/Transforms/GlobalOpt/metadata.ll create mode 100644 final/test/Transforms/GlobalOpt/phi-select.ll create mode 100644 final/test/Transforms/GlobalOpt/storepointer-compare.ll create mode 100644 final/test/Transforms/GlobalOpt/storepointer.ll create mode 100644 final/test/Transforms/GlobalOpt/trivialstore.ll create mode 100644 final/test/Transforms/GlobalOpt/undef-init.ll create mode 100644 final/test/Transforms/GlobalOpt/unnamed-addr.ll create mode 100644 final/test/Transforms/IPConstantProp/2008-06-09-WeakProp.ll create mode 100644 final/test/Transforms/IPConstantProp/2009-09-24-byval-ptr.ll create mode 100644 final/test/Transforms/IPConstantProp/dangling-block-address.ll create mode 100644 final/test/Transforms/IPConstantProp/deadarg.ll create mode 100644 final/test/Transforms/IPConstantProp/dg.exp create mode 100644 final/test/Transforms/IPConstantProp/recursion.ll create mode 100644 final/test/Transforms/IPConstantProp/return-argument.ll create mode 100644 final/test/Transforms/IPConstantProp/return-constant.ll create mode 100644 final/test/Transforms/IPConstantProp/return-constants.ll create mode 100644 final/test/Transforms/IPConstantProp/user-with-multiple-uses.ll create mode 100644 final/test/Transforms/IndVarSimplify/2002-09-09-PointerIndVar.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-04-16-ExprAnalysis.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-09-23-NotAtTop.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2003-12-21-IndVarSize.ll create mode 100644 final/test/Transforms/IndVarSimplify/2004-03-10-PHIInsertionBug.ll create mode 100644 final/test/Transforms/IndVarSimplify/2004-04-05-InvokeCastCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2004-04-07-ScalarEvolutionCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2005-02-11-InvokeCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2005-02-17-TruncateExprCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2005-02-26-ExitValueCompute.ll create mode 100644 final/test/Transforms/IndVarSimplify/2005-06-15-InstMoveCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2006-03-31-NegativeStride.ll create mode 100644 final/test/Transforms/IndVarSimplify/2006-06-16-Indvar-LCSSA-Crash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2006-09-20-LFTR-Crash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll create mode 100644 final/test/Transforms/IndVarSimplify/2007-01-06-TripCount.ll create mode 100644 final/test/Transforms/IndVarSimplify/2007-06-06-DeleteDanglesPtr.ll create mode 100644 final/test/Transforms/IndVarSimplify/2007-11-23-BitcastCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2008-06-15-SCEVExpanderBug.ll create mode 100644 final/test/Transforms/IndVarSimplify/2008-09-02-IVType.ll create mode 100644 final/test/Transforms/IndVarSimplify/2008-10-03-CouldNotCompute.ll create mode 100644 final/test/Transforms/IndVarSimplify/2008-11-25-APFloatAssert.ll create mode 100644 final/test/Transforms/IndVarSimplify/2009-04-14-shorten_iv_vars.ll create mode 100644 final/test/Transforms/IndVarSimplify/2009-04-15-shorten-iv-vars-2.ll create mode 100644 final/test/Transforms/IndVarSimplify/2009-04-22-IndvarCrash.ll create mode 100644 final/test/Transforms/IndVarSimplify/2009-04-27-Floating.ll create mode 100644 final/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll create mode 100644 final/test/Transforms/IndVarSimplify/ada-loops.ll create mode 100644 final/test/Transforms/IndVarSimplify/addrec-gep.ll create mode 100644 final/test/Transforms/IndVarSimplify/ashr-tripcount.ll create mode 100644 final/test/Transforms/IndVarSimplify/avoid-i0.ll create mode 100644 final/test/Transforms/IndVarSimplify/casted-argument.ll create mode 100644 final/test/Transforms/IndVarSimplify/complex-scev.ll create mode 100644 final/test/Transforms/IndVarSimplify/crash.ll create mode 100644 final/test/Transforms/IndVarSimplify/dangling-use.ll create mode 100644 final/test/Transforms/IndVarSimplify/dg.exp create mode 100644 final/test/Transforms/IndVarSimplify/divide-pointer.ll create mode 100644 final/test/Transforms/IndVarSimplify/eliminate-comparison.ll create mode 100644 final/test/Transforms/IndVarSimplify/eliminate-max.ll create mode 100644 final/test/Transforms/IndVarSimplify/eliminate-rem.ll create mode 100644 final/test/Transforms/IndVarSimplify/exit_value_tests.ll create mode 100644 final/test/Transforms/IndVarSimplify/floating-point-iv.ll create mode 100644 final/test/Transforms/IndVarSimplify/gep-with-mul-base.ll create mode 100644 final/test/Transforms/IndVarSimplify/indirectbr.ll create mode 100644 final/test/Transforms/IndVarSimplify/interesting-invoke-use.ll create mode 100644 final/test/Transforms/IndVarSimplify/iterationCount_zext_or_trunc.ll create mode 100644 final/test/Transforms/IndVarSimplify/iv-sext.ll create mode 100644 final/test/Transforms/IndVarSimplify/iv-zext.ll create mode 100644 final/test/Transforms/IndVarSimplify/lftr-other-uses.ll create mode 100644 final/test/Transforms/IndVarSimplify/lftr-promote.ll create mode 100644 final/test/Transforms/IndVarSimplify/lftr_simple.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate10.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate11.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate7.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate8.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate9.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_1.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_2.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_3.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_4.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_5.ll create mode 100644 final/test/Transforms/IndVarSimplify/loop_evaluate_6.ll create mode 100644 final/test/Transforms/IndVarSimplify/masked-iv.ll create mode 100644 final/test/Transforms/IndVarSimplify/max-pointer.ll create mode 100644 final/test/Transforms/IndVarSimplify/phi-uses-value-multiple-times.ll create mode 100644 final/test/Transforms/IndVarSimplify/pointer-indvars.ll create mode 100644 final/test/Transforms/IndVarSimplify/pointer.ll create mode 100644 final/test/Transforms/IndVarSimplify/polynomial-expand.ll create mode 100644 final/test/Transforms/IndVarSimplify/preserve-gep-loop-variant.ll create mode 100644 final/test/Transforms/IndVarSimplify/preserve-gep-nested.ll create mode 100644 final/test/Transforms/IndVarSimplify/preserve-gep-remainder.ll create mode 100644 final/test/Transforms/IndVarSimplify/preserve-gep.ll create mode 100644 final/test/Transforms/IndVarSimplify/preserve-signed-wrap.ll create mode 100644 final/test/Transforms/IndVarSimplify/promote-iv-to-eliminate-casts.ll create mode 100644 final/test/Transforms/IndVarSimplify/shrunk-constant.ll create mode 100644 final/test/Transforms/IndVarSimplify/signed-trip-count.ll create mode 100644 final/test/Transforms/IndVarSimplify/single-element-range.ll create mode 100644 final/test/Transforms/IndVarSimplify/sink-alloca.ll create mode 100644 final/test/Transforms/IndVarSimplify/sink-trapping.ll create mode 100644 final/test/Transforms/IndVarSimplify/subtract.ll create mode 100644 final/test/Transforms/IndVarSimplify/tripcount_compute.ll create mode 100644 final/test/Transforms/IndVarSimplify/tripcount_infinite.ll create mode 100644 final/test/Transforms/IndVarSimplify/udiv.ll create mode 100644 final/test/Transforms/IndVarSimplify/uglygep.ll create mode 100644 final/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll create mode 100644 final/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll create mode 100644 final/test/Transforms/Inline/2003-09-14-InlineValue.ll create mode 100644 final/test/Transforms/Inline/2003-09-22-PHINodeInlineFail.ll create mode 100644 final/test/Transforms/Inline/2003-09-22-PHINodesInExceptionDest.ll create mode 100644 final/test/Transforms/Inline/2003-09-22-PHINodesInNormalInvokeDest.ll create mode 100644 final/test/Transforms/Inline/2003-10-13-AllocaDominanceProblem.ll create mode 100644 final/test/Transforms/Inline/2003-10-26-InlineInvokeExceptionDestPhi.ll create mode 100644 final/test/Transforms/Inline/2004-04-15-InlineDeletesCall.ll create mode 100644 final/test/Transforms/Inline/2004-04-20-InlineLinkOnce.ll create mode 100644 final/test/Transforms/Inline/2004-10-17-InlineFunctionWithoutReturn.ll create mode 100644 final/test/Transforms/Inline/2006-01-14-CallGraphUpdate.ll create mode 100644 final/test/Transforms/Inline/2006-07-12-InlinePruneCGUpdate.ll create mode 100644 final/test/Transforms/Inline/2006-11-09-InlineCGUpdate-2.ll create mode 100644 final/test/Transforms/Inline/2006-11-09-InlineCGUpdate.ll create mode 100644 final/test/Transforms/Inline/2007-04-15-InlineEH.ll create mode 100644 final/test/Transforms/Inline/2007-06-06-NoInline.ll create mode 100644 final/test/Transforms/Inline/2007-06-25-WeakInline.ll create mode 100644 final/test/Transforms/Inline/2007-12-19-InlineNoUnwind.ll create mode 100644 final/test/Transforms/Inline/2008-03-04-StructRet.ll create mode 100644 final/test/Transforms/Inline/2008-03-07-Inline-2.ll create mode 100644 final/test/Transforms/Inline/2008-03-07-Inline.ll create mode 100644 final/test/Transforms/Inline/2008-09-02-AlwaysInline.ll create mode 100644 final/test/Transforms/Inline/2008-09-02-NoInline.ll create mode 100644 final/test/Transforms/Inline/2008-10-30-AlwaysInline.ll create mode 100644 final/test/Transforms/Inline/2008-11-04-AlwaysInline.ll create mode 100644 final/test/Transforms/Inline/2009-01-08-NoInlineDynamicAlloca.ll create mode 100644 final/test/Transforms/Inline/2009-01-13-RecursiveInlineCrash.ll create mode 100644 final/test/Transforms/Inline/2009-05-07-CallUsingSelfCrash.ll create mode 100644 final/test/Transforms/Inline/2010-05-12-ValueMap.ll create mode 100644 final/test/Transforms/Inline/2010-05-31-ByvalTailcall.ll create mode 100644 final/test/Transforms/Inline/PR4909.ll create mode 100644 final/test/Transforms/Inline/alloca-in-scc.ll create mode 100644 final/test/Transforms/Inline/alloca_test.ll create mode 100644 final/test/Transforms/Inline/always_inline_dyn_alloca.ll create mode 100644 final/test/Transforms/Inline/array_merge.ll create mode 100644 final/test/Transforms/Inline/basictest.ll create mode 100644 final/test/Transforms/Inline/byval.ll create mode 100644 final/test/Transforms/Inline/callgraph-update.ll create mode 100644 final/test/Transforms/Inline/casts.ll create mode 100644 final/test/Transforms/Inline/cfg_preserve_test.ll create mode 100644 final/test/Transforms/Inline/crash.ll create mode 100644 final/test/Transforms/Inline/crash2.ll create mode 100644 final/test/Transforms/Inline/delete-call.ll create mode 100644 final/test/Transforms/Inline/devirtualize-2.ll create mode 100644 final/test/Transforms/Inline/devirtualize-3.ll create mode 100644 final/test/Transforms/Inline/devirtualize.ll create mode 100644 final/test/Transforms/Inline/dg.exp create mode 100644 final/test/Transforms/Inline/dynamic_alloca_test.ll create mode 100644 final/test/Transforms/Inline/externally_available.ll create mode 100644 final/test/Transforms/Inline/gvn-inline-iteration.ll create mode 100644 final/test/Transforms/Inline/inline-invoke-tail.ll create mode 100644 final/test/Transforms/Inline/inline-tail.ll create mode 100644 final/test/Transforms/Inline/inline_cleanup.ll create mode 100644 final/test/Transforms/Inline/inline_constprop.ll create mode 100644 final/test/Transforms/Inline/inline_dce.ll create mode 100644 final/test/Transforms/Inline/inline_prune.ll create mode 100644 final/test/Transforms/Inline/invoke_test-1.ll create mode 100644 final/test/Transforms/Inline/invoke_test-2.ll create mode 100644 final/test/Transforms/Inline/invoke_test-3.ll create mode 100644 final/test/Transforms/Inline/nested-inline.ll create mode 100644 final/test/Transforms/Inline/noinline-recursive-fn.ll create mode 100644 final/test/Transforms/Inline/noinline.ll create mode 100644 final/test/Transforms/InstCombine/2002-03-11-InstCombineHang.ll create mode 100644 final/test/Transforms/InstCombine/2002-05-14-SubFailure.ll create mode 100644 final/test/Transforms/InstCombine/2002-08-02-CastTest.ll create mode 100644 final/test/Transforms/InstCombine/2002-12-05-MissedConstProp.ll create mode 100644 final/test/Transforms/InstCombine/2003-05-26-CastMiscompile.ll create mode 100644 final/test/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll create mode 100644 final/test/Transforms/InstCombine/2003-06-05-BranchInvertInfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2003-07-21-ExternalConstant.ll create mode 100644 final/test/Transforms/InstCombine/2003-08-12-AllocaNonNull.ll create mode 100644 final/test/Transforms/InstCombine/2003-09-09-VolatileLoadElim.ll create mode 100644 final/test/Transforms/InstCombine/2003-10-29-CallSiteResolve.ll create mode 100644 final/test/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll create mode 100644 final/test/Transforms/InstCombine/2004-01-13-InstCombineInvokePHI.ll create mode 100644 final/test/Transforms/InstCombine/2004-02-23-ShiftShiftOverflow.ll create mode 100644 final/test/Transforms/InstCombine/2004-03-13-InstCombineInfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2004-04-04-InstCombineReplaceAllUsesWith.ll create mode 100644 final/test/Transforms/InstCombine/2004-05-07-UnsizedCastLoad.ll create mode 100644 final/test/Transforms/InstCombine/2004-07-27-ConstantExprMul.ll create mode 100644 final/test/Transforms/InstCombine/2004-08-09-RemInfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2004-08-10-BoolSetCC.ll create mode 100644 final/test/Transforms/InstCombine/2004-09-20-BadLoadCombine.ll create mode 100644 final/test/Transforms/InstCombine/2004-09-20-BadLoadCombine2.ll create mode 100644 final/test/Transforms/InstCombine/2004-09-28-BadShiftAndSetCC.ll create mode 100644 final/test/Transforms/InstCombine/2004-11-22-Missed-and-fold.ll create mode 100644 final/test/Transforms/InstCombine/2004-11-27-SetCCForCastLargerAndConstant.ll create mode 100644 final/test/Transforms/InstCombine/2004-12-08-RemInfiniteLoop.ll create mode 100644 final/test/Transforms/InstCombine/2005-03-04-ShiftOverflow.ll create mode 100644 final/test/Transforms/InstCombine/2005-04-07-UDivSelectCrash.ll create mode 100644 final/test/Transforms/InstCombine/2005-06-15-DivSelectCrash.ll create mode 100644 final/test/Transforms/InstCombine/2005-06-15-ShiftSetCCCrash.ll create mode 100644 final/test/Transforms/InstCombine/2005-06-16-RangeCrash.ll create mode 100644 final/test/Transforms/InstCombine/2005-06-16-SetCCOrSetCCMiscompile.ll create mode 100644 final/test/Transforms/InstCombine/2005-07-07-DeadPHILoop.ll create mode 100644 final/test/Transforms/InstCombine/2006-02-13-DemandedMiscompile.ll create mode 100644 final/test/Transforms/InstCombine/2006-02-28-Crash.ll create mode 100644 final/test/Transforms/InstCombine/2006-03-30-ExtractElement.ll create mode 100644 final/test/Transforms/InstCombine/2006-04-28-ShiftShiftLongLong.ll create mode 100644 final/test/Transforms/InstCombine/2006-05-04-DemandedBitCrash.ll create mode 100644 final/test/Transforms/InstCombine/2006-09-15-CastToBool.ll create mode 100644 final/test/Transforms/InstCombine/2006-10-19-SignedToUnsignedCastAndConst-2.ll create mode 100644 final/test/Transforms/InstCombine/2006-10-20-mask.ll create mode 100644 final/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll create mode 100644 final/test/Transforms/InstCombine/2006-11-03-Memmove64.ll create mode 100644 final/test/Transforms/InstCombine/2006-11-10-ashr-miscompile.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-01-BadFPVectorXform.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-05-fp-to-int-ext.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-08-Phi-ICmp-Op-Fold.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-08-Select-ICmp.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-15-Range-Test.ll create mode 100644 final/test/Transforms/InstCombine/2006-12-23-Select-Cmp-Cmp.ll create mode 100644 final/test/Transforms/InstCombine/2007-01-13-ExtCompareMiscompile.ll create mode 100644 final/test/Transforms/InstCombine/2007-01-14-FcmpSelf.ll create mode 100644 final/test/Transforms/InstCombine/2007-01-18-VectorInfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2007-01-27-AndICmp.ll create mode 100644 final/test/Transforms/InstCombine/2007-02-01-LoadSinkAlloca.ll create mode 100644 final/test/Transforms/InstCombine/2007-02-07-PointerCast.ll create mode 100644 final/test/Transforms/InstCombine/2007-02-23-PhiFoldInfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-13-CompareMerge.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-19-BadTruncChangePR1261.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-21-SignedRangeTest.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-25-BadShiftMask.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-25-DoubleShift.ll create mode 100644 final/test/Transforms/InstCombine/2007-03-26-BadShiftMask.ll create mode 100644 final/test/Transforms/InstCombine/2007-04-04-BadFoldBitcastIntoMalloc.ll create mode 100644 final/test/Transforms/InstCombine/2007-04-08-SingleEltVectorCrash.ll create mode 100644 final/test/Transforms/InstCombine/2007-05-04-Crash.ll create mode 100644 final/test/Transforms/InstCombine/2007-05-10-icmp-or.ll create mode 100644 final/test/Transforms/InstCombine/2007-05-14-Crash.ll create mode 100644 final/test/Transforms/InstCombine/2007-05-18-CastFoldBug.ll create mode 100644 final/test/Transforms/InstCombine/2007-06-06-AshrSignBit.ll create mode 100644 final/test/Transforms/InstCombine/2007-06-21-DivCompareMiscomp.ll create mode 100644 final/test/Transforms/InstCombine/2007-08-02-InfiniteLoop.ll create mode 100644 final/test/Transforms/InstCombine/2007-09-10-AliasConstFold.ll create mode 100644 final/test/Transforms/InstCombine/2007-09-11-Trampoline.ll create mode 100644 final/test/Transforms/InstCombine/2007-09-17-AliasConstFold2.ll create mode 100644 final/test/Transforms/InstCombine/2007-10-10-EliminateMemCpy.ll create mode 100644 final/test/Transforms/InstCombine/2007-10-12-Crash.ll create mode 100644 final/test/Transforms/InstCombine/2007-10-28-stacksave.ll create mode 100644 final/test/Transforms/InstCombine/2007-10-31-RangeCrash.ll create mode 100644 final/test/Transforms/InstCombine/2007-10-31-StringCrash.ll create mode 100644 final/test/Transforms/InstCombine/2007-11-07-OpaqueAlignCrash.ll create mode 100644 final/test/Transforms/InstCombine/2007-11-15-CompareMiscomp.ll create mode 100644 final/test/Transforms/InstCombine/2007-11-22-IcmpCrash.ll create mode 100644 final/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll create mode 100644 final/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll create mode 100644 final/test/Transforms/InstCombine/2007-12-12-GEPScale.ll create mode 100644 final/test/Transforms/InstCombine/2007-12-16-AsmNoUnwind.ll create mode 100644 final/test/Transforms/InstCombine/2007-12-18-AddSelCmpSub.ll create mode 100644 final/test/Transforms/InstCombine/2007-12-28-IcmpSub2.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-06-BitCastAttributes.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-06-CastCrash.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-06-VoidCast.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-13-AndCmpCmp.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-13-NoBitCastAttributes.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-21-MismatchedCastAndCompare.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-21-MulTrunc.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-27-FloatSelect.ll create mode 100644 final/test/Transforms/InstCombine/2008-01-29-AddICmp.ll create mode 100644 final/test/Transforms/InstCombine/2008-02-13-MulURem.ll create mode 100644 final/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll create mode 100644 final/test/Transforms/InstCombine/2008-02-16-SDivOverflow2.ll create mode 100644 final/test/Transforms/InstCombine/2008-02-23-MulSub.ll create mode 100644 final/test/Transforms/InstCombine/2008-02-28-OrFCmpCrash.ll create mode 100644 final/test/Transforms/InstCombine/2008-03-13-IntToPtr.ll create mode 100644 final/test/Transforms/InstCombine/2008-04-22-ByValBitcast.ll create mode 100644 final/test/Transforms/InstCombine/2008-04-28-VolatileStore.ll create mode 100644 final/test/Transforms/InstCombine/2008-04-29-VolatileLoadDontMerge.ll create mode 100644 final/test/Transforms/InstCombine/2008-04-29-VolatileLoadMerge.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-08-LiveStoreDelete.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-08-StrLenSink.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-09-SinkOfInvoke.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-17-InfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-18-FoldIntToPtr.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-22-IDivVector.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-22-NegValVector.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-23-CompareFold.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-31-AddBool.ll create mode 100644 final/test/Transforms/InstCombine/2008-05-31-Bools.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-05-ashr-crash.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-08-ICmpPHI.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-13-InfiniteLoopStore.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-13-ReadOnlyCallStore.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll create mode 100644 final/test/Transforms/InstCombine/2008-06-24-StackRestore.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-08-AndICmp.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-08-ShiftOneAndOne.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-08-SubAnd.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-08-VolatileLoadMerge.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-09-SubAndError.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-10-CastSextBool.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-10-ICmpBinOp.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-11-RemAnd.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-13-DivZero.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-16-fsub.ll create mode 100644 final/test/Transforms/InstCombine/2008-07-16-sse2_storel_dq.ll create mode 100644 final/test/Transforms/InstCombine/2008-08-05-And.ll create mode 100644 final/test/Transforms/InstCombine/2008-08-17-ICmpXorSignbit.ll create mode 100644 final/test/Transforms/InstCombine/2008-09-02-VectorCrash.ll create mode 100644 final/test/Transforms/InstCombine/2008-09-29-FoldingOr.ll create mode 100644 final/test/Transforms/InstCombine/2008-10-11-DivCompareFold.ll create mode 100644 final/test/Transforms/InstCombine/2008-10-23-ConstFoldWithoutMask.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-01-SRemDemandedBits.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-08-FCmp.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-20-DivMulRem.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-27-IDivVector.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-27-MultiplyIntVec.ll create mode 100644 final/test/Transforms/InstCombine/2008-11-27-UDivNegative.ll create mode 100644 final/test/Transforms/InstCombine/2008-12-17-SRemNegConstVec.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-05-i128-crash.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-08-AlignAlloca.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-16-PointerAddrSpace.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-19-fmod-constant-float.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-24-EmptyStruct.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-31-InfIterate.ll create mode 100644 final/test/Transforms/InstCombine/2009-01-31-Pressure.ll create mode 100644 final/test/Transforms/InstCombine/2009-02-04-FPBitcast.ll create mode 100644 final/test/Transforms/InstCombine/2009-02-20-InstCombine-SROA.ll create mode 100644 final/test/Transforms/InstCombine/2009-02-21-LoadCST.ll create mode 100644 final/test/Transforms/InstCombine/2009-02-25-CrashZeroSizeArray.ll create mode 100644 final/test/Transforms/InstCombine/2009-03-18-vector-ashr-crash.ll create mode 100644 final/test/Transforms/InstCombine/2009-03-20-AShrOverShift.ll create mode 100644 final/test/Transforms/InstCombine/2009-03-24-InfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2009-04-07-MulPromoteToI96.ll create mode 100644 final/test/Transforms/InstCombine/2009-05-23-FCmpToICmp.ll create mode 100644 final/test/Transforms/InstCombine/2009-06-11-StoreAddrSpace.ll create mode 100644 final/test/Transforms/InstCombine/2009-06-16-SRemDemandedBits.ll create mode 100644 final/test/Transforms/InstCombine/2009-07-02-MaskedIntVector.ll create mode 100644 final/test/Transforms/InstCombine/2009-12-17-CmpSelectNull.ll create mode 100644 final/test/Transforms/InstCombine/2010-01-28-NegativeSRem.ll create mode 100644 final/test/Transforms/InstCombine/2010-03-03-ExtElim.ll create mode 100644 final/test/Transforms/InstCombine/2010-11-01-lshr-mask.ll create mode 100644 final/test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll create mode 100644 final/test/Transforms/InstCombine/2010-11-23-Distributed.ll create mode 100644 final/test/Transforms/InstCombine/2011-02-14-InfLoop.ll create mode 100644 final/test/Transforms/InstCombine/2011-02-16-InsertelementHang.ll create mode 100644 final/test/Transforms/InstCombine/CPP_min_max.ll create mode 100644 final/test/Transforms/InstCombine/IntPtrCast.ll create mode 100644 final/test/Transforms/InstCombine/JavaCompare.ll create mode 100644 final/test/Transforms/InstCombine/README.txt create mode 100644 final/test/Transforms/InstCombine/add-shrink.ll create mode 100644 final/test/Transforms/InstCombine/add-sitofp.ll create mode 100644 final/test/Transforms/InstCombine/add.ll create mode 100644 final/test/Transforms/InstCombine/add2.ll create mode 100644 final/test/Transforms/InstCombine/add3.ll create mode 100644 final/test/Transforms/InstCombine/addnegneg.ll create mode 100644 final/test/Transforms/InstCombine/adjust-for-sminmax.ll create mode 100644 final/test/Transforms/InstCombine/align-2d-gep.ll create mode 100644 final/test/Transforms/InstCombine/align-addr.ll create mode 100644 final/test/Transforms/InstCombine/align-external.ll create mode 100644 final/test/Transforms/InstCombine/alloca.ll create mode 100644 final/test/Transforms/InstCombine/and-compare.ll create mode 100644 final/test/Transforms/InstCombine/and-fcmp.ll create mode 100644 final/test/Transforms/InstCombine/and-not-or.ll create mode 100644 final/test/Transforms/InstCombine/and-or-and.ll create mode 100644 final/test/Transforms/InstCombine/and-or-not.ll create mode 100644 final/test/Transforms/InstCombine/and-or.ll create mode 100644 final/test/Transforms/InstCombine/and-xor-merge.ll create mode 100644 final/test/Transforms/InstCombine/and.ll create mode 100644 final/test/Transforms/InstCombine/and2.ll create mode 100644 final/test/Transforms/InstCombine/apint-add1.ll create mode 100644 final/test/Transforms/InstCombine/apint-add2.ll create mode 100644 final/test/Transforms/InstCombine/apint-and-compare.ll create mode 100644 final/test/Transforms/InstCombine/apint-and-or-and.ll create mode 100644 final/test/Transforms/InstCombine/apint-and-xor-merge.ll create mode 100644 final/test/Transforms/InstCombine/apint-and1.ll create mode 100644 final/test/Transforms/InstCombine/apint-and2.ll create mode 100644 final/test/Transforms/InstCombine/apint-call-cast-target.ll create mode 100644 final/test/Transforms/InstCombine/apint-cast-and-cast.ll create mode 100644 final/test/Transforms/InstCombine/apint-cast-cast-to-and.ll create mode 100644 final/test/Transforms/InstCombine/apint-cast.ll create mode 100644 final/test/Transforms/InstCombine/apint-div1.ll create mode 100644 final/test/Transforms/InstCombine/apint-div2.ll create mode 100644 final/test/Transforms/InstCombine/apint-mul1.ll create mode 100644 final/test/Transforms/InstCombine/apint-mul2.ll create mode 100644 final/test/Transforms/InstCombine/apint-not.ll create mode 100644 final/test/Transforms/InstCombine/apint-or1.ll create mode 100644 final/test/Transforms/InstCombine/apint-or2.ll create mode 100644 final/test/Transforms/InstCombine/apint-rem1.ll create mode 100644 final/test/Transforms/InstCombine/apint-rem2.ll create mode 100644 final/test/Transforms/InstCombine/apint-select.ll create mode 100644 final/test/Transforms/InstCombine/apint-shift-simplify.ll create mode 100644 final/test/Transforms/InstCombine/apint-shift.ll create mode 100644 final/test/Transforms/InstCombine/apint-shl-trunc.ll create mode 100644 final/test/Transforms/InstCombine/apint-sub.ll create mode 100644 final/test/Transforms/InstCombine/apint-xor1.ll create mode 100644 final/test/Transforms/InstCombine/apint-xor2.ll create mode 100644 final/test/Transforms/InstCombine/apint-zext1.ll create mode 100644 final/test/Transforms/InstCombine/apint-zext2.ll create mode 100644 final/test/Transforms/InstCombine/ashr-nop.ll create mode 100644 final/test/Transforms/InstCombine/badmalloc.ll create mode 100644 final/test/Transforms/InstCombine/binop-cast.ll create mode 100644 final/test/Transforms/InstCombine/bit-checks.ll create mode 100644 final/test/Transforms/InstCombine/bit-tracking.ll create mode 100644 final/test/Transforms/InstCombine/bitcast-sext-vector.ll create mode 100644 final/test/Transforms/InstCombine/bitcast-store.ll create mode 100644 final/test/Transforms/InstCombine/bitcast-vec-canon.ll create mode 100644 final/test/Transforms/InstCombine/bitcast-vec-uniform.ll create mode 100644 final/test/Transforms/InstCombine/bitcast-vector-fold.ll create mode 100644 final/test/Transforms/InstCombine/bitcast.ll create mode 100644 final/test/Transforms/InstCombine/bitcount.ll create mode 100644 final/test/Transforms/InstCombine/bittest.ll create mode 100644 final/test/Transforms/InstCombine/bswap-fold.ll create mode 100644 final/test/Transforms/InstCombine/bswap.ll create mode 100644 final/test/Transforms/InstCombine/call-cast-target.ll create mode 100644 final/test/Transforms/InstCombine/call-intrinsics.ll create mode 100644 final/test/Transforms/InstCombine/call.ll create mode 100644 final/test/Transforms/InstCombine/call2.ll create mode 100644 final/test/Transforms/InstCombine/canonicalize_branch.ll create mode 100644 final/test/Transforms/InstCombine/cast-mul-select.ll create mode 100644 final/test/Transforms/InstCombine/cast-set.ll create mode 100644 final/test/Transforms/InstCombine/cast.ll create mode 100644 final/test/Transforms/InstCombine/cast_ptr.ll create mode 100644 final/test/Transforms/InstCombine/compare-signs.ll create mode 100644 final/test/Transforms/InstCombine/constant-fold-compare.ll create mode 100644 final/test/Transforms/InstCombine/constant-fold-gep.ll create mode 100644 final/test/Transforms/InstCombine/crash.ll create mode 100644 final/test/Transforms/InstCombine/dce-iterate.ll create mode 100644 final/test/Transforms/InstCombine/deadcode.ll create mode 100644 final/test/Transforms/InstCombine/dg.exp create mode 100644 final/test/Transforms/InstCombine/div.ll create mode 100644 final/test/Transforms/InstCombine/enforce-known-alignment.ll create mode 100644 final/test/Transforms/InstCombine/exact.ll create mode 100644 final/test/Transforms/InstCombine/extractvalue.ll create mode 100644 final/test/Transforms/InstCombine/fcmp-select.ll create mode 100644 final/test/Transforms/InstCombine/fcmp-special.ll create mode 100644 final/test/Transforms/InstCombine/fold-bin-operand.ll create mode 100644 final/test/Transforms/InstCombine/fold-calls.ll create mode 100644 final/test/Transforms/InstCombine/fold-vector-select.ll create mode 100644 final/test/Transforms/InstCombine/fold-vector-zero.ll create mode 100644 final/test/Transforms/InstCombine/fp-ret-bitcast.ll create mode 100644 final/test/Transforms/InstCombine/fpcast.ll create mode 100644 final/test/Transforms/InstCombine/fpextend.ll create mode 100644 final/test/Transforms/InstCombine/fsub.ll create mode 100644 final/test/Transforms/InstCombine/gepgep.ll create mode 100644 final/test/Transforms/InstCombine/getelementptr.ll create mode 100644 final/test/Transforms/InstCombine/hoist_instr.ll create mode 100644 final/test/Transforms/InstCombine/icmp.ll create mode 100644 final/test/Transforms/InstCombine/idioms.ll create mode 100644 final/test/Transforms/InstCombine/intrinsics.ll create mode 100644 final/test/Transforms/InstCombine/invariant.ll create mode 100644 final/test/Transforms/InstCombine/known_align.ll create mode 100644 final/test/Transforms/InstCombine/load-cmp.ll create mode 100644 final/test/Transforms/InstCombine/load-select.ll create mode 100644 final/test/Transforms/InstCombine/load.ll create mode 100644 final/test/Transforms/InstCombine/load3.ll create mode 100644 final/test/Transforms/InstCombine/loadstore-alignment.ll create mode 100644 final/test/Transforms/InstCombine/logical-select.ll create mode 100644 final/test/Transforms/InstCombine/lshr-phi.ll create mode 100644 final/test/Transforms/InstCombine/malloc-free-delete.ll create mode 100644 final/test/Transforms/InstCombine/malloc.ll create mode 100644 final/test/Transforms/InstCombine/malloc2.ll create mode 100644 final/test/Transforms/InstCombine/malloc3.ll create mode 100644 final/test/Transforms/InstCombine/memcpy-to-load.ll create mode 100644 final/test/Transforms/InstCombine/memcpy.ll create mode 100644 final/test/Transforms/InstCombine/memmove.ll create mode 100644 final/test/Transforms/InstCombine/memset.ll create mode 100644 final/test/Transforms/InstCombine/memset2.ll create mode 100644 final/test/Transforms/InstCombine/memset_chk.ll create mode 100644 final/test/Transforms/InstCombine/mul-masked-bits.ll create mode 100644 final/test/Transforms/InstCombine/mul.ll create mode 100644 final/test/Transforms/InstCombine/multi-use-or.ll create mode 100644 final/test/Transforms/InstCombine/narrow.ll create mode 100644 final/test/Transforms/InstCombine/neon-intrinsics.ll create mode 100644 final/test/Transforms/InstCombine/no-negzero.ll create mode 100644 final/test/Transforms/InstCombine/not-fcmp.ll create mode 100644 final/test/Transforms/InstCombine/not.ll create mode 100644 final/test/Transforms/InstCombine/nothrow.ll create mode 100644 final/test/Transforms/InstCombine/nsw.ll create mode 100644 final/test/Transforms/InstCombine/objsize.ll create mode 100644 final/test/Transforms/InstCombine/odr-linkage.ll create mode 100644 final/test/Transforms/InstCombine/or-fcmp.ll create mode 100644 final/test/Transforms/InstCombine/or-to-xor.ll create mode 100644 final/test/Transforms/InstCombine/or-xor.ll create mode 100644 final/test/Transforms/InstCombine/or.ll create mode 100644 final/test/Transforms/InstCombine/overflow.ll create mode 100644 final/test/Transforms/InstCombine/phi-merge-gep.ll create mode 100644 final/test/Transforms/InstCombine/phi.ll create mode 100644 final/test/Transforms/InstCombine/pr2645-0.ll create mode 100644 final/test/Transforms/InstCombine/pr2645-1.ll create mode 100644 final/test/Transforms/InstCombine/pr2996.ll create mode 100644 final/test/Transforms/InstCombine/pr8547.ll create mode 100644 final/test/Transforms/InstCombine/preserve-sminmax.ll create mode 100644 final/test/Transforms/InstCombine/ptr-int-cast.ll create mode 100644 final/test/Transforms/InstCombine/rem.ll create mode 100644 final/test/Transforms/InstCombine/sdiv-1.ll create mode 100644 final/test/Transforms/InstCombine/sdiv-2.ll create mode 100644 final/test/Transforms/InstCombine/sdiv-shift.ll create mode 100644 final/test/Transforms/InstCombine/select-2.ll create mode 100644 final/test/Transforms/InstCombine/select-crash.ll create mode 100644 final/test/Transforms/InstCombine/select-load-call.ll create mode 100644 final/test/Transforms/InstCombine/select.ll create mode 100644 final/test/Transforms/InstCombine/set.ll create mode 100644 final/test/Transforms/InstCombine/setcc-strength-reduce.ll create mode 100644 final/test/Transforms/InstCombine/sext.ll create mode 100644 final/test/Transforms/InstCombine/shift-sra.ll create mode 100644 final/test/Transforms/InstCombine/shift.ll create mode 100644 final/test/Transforms/InstCombine/shufflemask-undef.ll create mode 100644 final/test/Transforms/InstCombine/shufflevec-constant.ll create mode 100644 final/test/Transforms/InstCombine/signed-comparison.ll create mode 100644 final/test/Transforms/InstCombine/signext.ll create mode 100644 final/test/Transforms/InstCombine/simplify-demanded-bits-pointer.ll create mode 100644 final/test/Transforms/InstCombine/sink_instruction.ll create mode 100644 final/test/Transforms/InstCombine/sitofp.ll create mode 100644 final/test/Transforms/InstCombine/sqrt.ll create mode 100644 final/test/Transforms/InstCombine/srem-simplify-bug.ll create mode 100644 final/test/Transforms/InstCombine/srem.ll create mode 100644 final/test/Transforms/InstCombine/srem1.ll create mode 100644 final/test/Transforms/InstCombine/stack-overalign.ll create mode 100644 final/test/Transforms/InstCombine/stacksaverestore.ll create mode 100644 final/test/Transforms/InstCombine/store.ll create mode 100644 final/test/Transforms/InstCombine/strcpy_chk.ll create mode 100644 final/test/Transforms/InstCombine/sub.ll create mode 100644 final/test/Transforms/InstCombine/trunc.ll create mode 100644 final/test/Transforms/InstCombine/udiv-simplify-bug-0.ll create mode 100644 final/test/Transforms/InstCombine/udiv-simplify-bug-1.ll create mode 100644 final/test/Transforms/InstCombine/udiv_select_to_select_shift.ll create mode 100644 final/test/Transforms/InstCombine/udivrem-change-width.ll create mode 100644 final/test/Transforms/InstCombine/urem-simplify-bug.ll create mode 100644 final/test/Transforms/InstCombine/urem.ll create mode 100644 final/test/Transforms/InstCombine/vec_demanded_elts.ll create mode 100644 final/test/Transforms/InstCombine/vec_extract_elt.ll create mode 100644 final/test/Transforms/InstCombine/vec_insertelt.ll create mode 100644 final/test/Transforms/InstCombine/vec_narrow.ll create mode 100644 final/test/Transforms/InstCombine/vec_sext.ll create mode 100644 final/test/Transforms/InstCombine/vec_shuffle.ll create mode 100644 final/test/Transforms/InstCombine/vector-casts.ll create mode 100644 final/test/Transforms/InstCombine/vector-srem.ll create mode 100644 final/test/Transforms/InstCombine/volatile_store.ll create mode 100644 final/test/Transforms/InstCombine/xor-undef.ll create mode 100644 final/test/Transforms/InstCombine/xor.ll create mode 100644 final/test/Transforms/InstCombine/xor2.ll create mode 100644 final/test/Transforms/InstCombine/zero-point-zero-add.ll create mode 100644 final/test/Transforms/InstCombine/zeroext-and-reduce.ll create mode 100644 final/test/Transforms/InstCombine/zext-bool-add-sub.ll create mode 100644 final/test/Transforms/InstCombine/zext-fold.ll create mode 100644 final/test/Transforms/InstCombine/zext-or-icmp.ll create mode 100644 final/test/Transforms/InstCombine/zext.ll create mode 100644 final/test/Transforms/InstSimplify/2010-12-20-Boolean.ll create mode 100644 final/test/Transforms/InstSimplify/2010-12-20-Distribute.ll create mode 100644 final/test/Transforms/InstSimplify/2011-01-14-Thread.ll create mode 100644 final/test/Transforms/InstSimplify/2011-02-01-Vector.ll create mode 100644 final/test/Transforms/InstSimplify/compare.ll create mode 100644 final/test/Transforms/InstSimplify/dg.exp create mode 100644 final/test/Transforms/InstSimplify/exact-nsw-nuw.ll create mode 100644 final/test/Transforms/InstSimplify/fdiv.ll create mode 100644 final/test/Transforms/InstSimplify/reassociate.ll create mode 100644 final/test/Transforms/Internalize/2008-05-09-AllButMain.ll create mode 100644 final/test/Transforms/Internalize/2008-05-09-AllButMain.ll.apifile create mode 100644 final/test/Transforms/Internalize/2009-01-05-InternalizeAliases.ll create mode 100644 final/test/Transforms/Internalize/available_externally.ll create mode 100644 final/test/Transforms/Internalize/dg.exp create mode 100644 final/test/Transforms/JumpThreading/2008-11-27-EntryMunge.ll create mode 100644 final/test/Transforms/JumpThreading/2010-08-26-and.ll create mode 100644 final/test/Transforms/JumpThreading/and-and-cond.ll create mode 100644 final/test/Transforms/JumpThreading/and-cond.ll create mode 100644 final/test/Transforms/JumpThreading/basic.ll create mode 100644 final/test/Transforms/JumpThreading/branch-no-const.ll create mode 100644 final/test/Transforms/JumpThreading/compare.ll create mode 100644 final/test/Transforms/JumpThreading/crash.ll create mode 100644 final/test/Transforms/JumpThreading/degenerate-phi.ll create mode 100644 final/test/Transforms/JumpThreading/dg.exp create mode 100644 final/test/Transforms/JumpThreading/indirectbr.ll create mode 100644 final/test/Transforms/JumpThreading/lvi-load.ll create mode 100644 final/test/Transforms/JumpThreading/no-irreducible-loops.ll create mode 100644 final/test/Transforms/JumpThreading/or-undef.ll create mode 100644 final/test/Transforms/JumpThreading/select.ll create mode 100644 final/test/Transforms/JumpThreading/thread-loads.ll create mode 100644 final/test/Transforms/LCSSA/2006-06-03-IncorrectIDFPhis.ll create mode 100644 final/test/Transforms/LCSSA/2006-06-12-MultipleExitsSameBlock.ll create mode 100644 final/test/Transforms/LCSSA/2006-07-09-NoDominator.ll create mode 100644 final/test/Transforms/LCSSA/2006-10-31-UnreachableBlock-2.ll create mode 100644 final/test/Transforms/LCSSA/2006-10-31-UnreachableBlock.ll create mode 100644 final/test/Transforms/LCSSA/2007-07-12-LICM-2.ll create mode 100644 final/test/Transforms/LCSSA/2007-07-12-LICM-3.ll create mode 100644 final/test/Transforms/LCSSA/2007-07-12-LICM.ll create mode 100644 final/test/Transforms/LCSSA/basictest.ll create mode 100644 final/test/Transforms/LCSSA/dg.exp create mode 100644 final/test/Transforms/LCSSA/indirectbr.ll create mode 100644 final/test/Transforms/LCSSA/invoke-dest.ll create mode 100644 final/test/Transforms/LCSSA/unreachable-use.ll create mode 100644 final/test/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll create mode 100644 final/test/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll create mode 100644 final/test/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll create mode 100644 final/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll create mode 100644 final/test/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll create mode 100644 final/test/Transforms/LICM/2003-02-28-PromoteDifferentType.ll create mode 100644 final/test/Transforms/LICM/2003-05-02-LoadHoist.ll create mode 100644 final/test/Transforms/LICM/2003-12-11-SinkingToPHI.ll create mode 100644 final/test/Transforms/LICM/2004-09-14-AliasAnalysisInvalidate.ll create mode 100644 final/test/Transforms/LICM/2004-11-17-UndefIndexCrash.ll create mode 100644 final/test/Transforms/LICM/2005-03-24-LICM-Aggregate-Crash.ll create mode 100644 final/test/Transforms/LICM/2006-09-12-DeadUserOfSunkInstr.ll create mode 100644 final/test/Transforms/LICM/2007-05-22-VolatileSink.ll create mode 100644 final/test/Transforms/LICM/2007-07-30-AliasSet.ll create mode 100644 final/test/Transforms/LICM/2007-09-17-PromoteValue.ll create mode 100644 final/test/Transforms/LICM/2007-09-24-PromoteNullValue.ll create mode 100644 final/test/Transforms/LICM/2007-10-01-PromoteSafeValue.ll create mode 100644 final/test/Transforms/LICM/2008-05-20-AliasSetVAArg.ll create mode 100644 final/test/Transforms/LICM/2008-07-22-LoadGlobalConstant.ll create mode 100644 final/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll create mode 100644 final/test/Transforms/LICM/Preserve-LCSSA.ll create mode 100644 final/test/Transforms/LICM/basictest.ll create mode 100644 final/test/Transforms/LICM/crash.ll create mode 100644 final/test/Transforms/LICM/dg.exp create mode 100644 final/test/Transforms/LICM/hoisting.ll create mode 100644 final/test/Transforms/LICM/no-preheader-test.ll create mode 100644 final/test/Transforms/LICM/scalar_promote.ll create mode 100644 final/test/Transforms/LICM/sinking.ll create mode 100644 final/test/Transforms/LoopDeletion/2007-07-23-InfiniteLoop.ll create mode 100644 final/test/Transforms/LoopDeletion/2008-05-06-Phi.ll create mode 100644 final/test/Transforms/LoopDeletion/dcetest.ll create mode 100644 final/test/Transforms/LoopDeletion/dg.exp create mode 100644 final/test/Transforms/LoopDeletion/multiple-exit-conditions.ll create mode 100644 final/test/Transforms/LoopDeletion/multiple-exits.ll create mode 100644 final/test/Transforms/LoopDeletion/simplify-then-delete.ll create mode 100644 final/test/Transforms/LoopIdiom/basic.ll create mode 100644 final/test/Transforms/LoopIdiom/debug-line.ll create mode 100644 final/test/Transforms/LoopIdiom/dg.exp create mode 100644 final/test/Transforms/LoopRotate/2009-01-25-SingleEntryPhi.ll create mode 100644 final/test/Transforms/LoopRotate/PhiRename-1.ll create mode 100644 final/test/Transforms/LoopRotate/PhiSelfRefernce-1.ll create mode 100644 final/test/Transforms/LoopRotate/basic.ll create mode 100644 final/test/Transforms/LoopRotate/crash.ll create mode 100644 final/test/Transforms/LoopRotate/dbgvalue.ll create mode 100644 final/test/Transforms/LoopRotate/dg.exp create mode 100644 final/test/Transforms/LoopRotate/indirectbr.ll create mode 100644 final/test/Transforms/LoopRotate/phi-duplicate.ll create mode 100644 final/test/Transforms/LoopRotate/pr2639.ll create mode 100644 final/test/Transforms/LoopRotate/preserve-scev.ll create mode 100644 final/test/Transforms/LoopSimplify/2003-04-25-AssertFail.ll create mode 100644 final/test/Transforms/LoopSimplify/2003-05-12-PreheaderExitOfChild.ll create mode 100644 final/test/Transforms/LoopSimplify/2003-08-15-PreheadersFail.ll create mode 100644 final/test/Transforms/LoopSimplify/2003-12-10-ExitBlocksProblem.ll create mode 100644 final/test/Transforms/LoopSimplify/2004-02-05-DominatorInfoCorruption.ll create mode 100644 final/test/Transforms/LoopSimplify/2004-03-15-IncorrectDomUpdate.ll create mode 100644 final/test/Transforms/LoopSimplify/2004-04-01-IncorrectDomUpdate.ll create mode 100644 final/test/Transforms/LoopSimplify/2004-04-12-LoopSimplify-SwitchBackedges.ll create mode 100644 final/test/Transforms/LoopSimplify/2004-04-13-LoopSimplifyUpdateDomFrontier.ll create mode 100644 final/test/Transforms/LoopSimplify/2007-10-28-InvokeCrash.ll create mode 100644 final/test/Transforms/LoopSimplify/2010-07-15-IncorrectDomFrontierUpdate.ll create mode 100644 final/test/Transforms/LoopSimplify/2010-12-26-PHIInfiniteLoop.ll create mode 100644 final/test/Transforms/LoopSimplify/basictest.ll create mode 100644 final/test/Transforms/LoopSimplify/dg.exp create mode 100644 final/test/Transforms/LoopSimplify/hardertest.ll create mode 100644 final/test/Transforms/LoopSimplify/indirectbr-backedge.ll create mode 100644 final/test/Transforms/LoopSimplify/indirectbr.ll create mode 100644 final/test/Transforms/LoopSimplify/merge-exits.ll create mode 100644 final/test/Transforms/LoopSimplify/phi-node-simplify.ll create mode 100644 final/test/Transforms/LoopSimplify/preserve-scev.ll create mode 100644 final/test/Transforms/LoopSimplify/single-backedge.ll create mode 100644 final/test/Transforms/LoopSimplify/unreachable-loop-pred.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2005-08-15-AddRecIV.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2005-08-17-OutOfLoopVariant.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2005-09-12-UsesOutOutsideOfLoop.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2007-04-23-UseIterator.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2008-08-13-CmpStride.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2008-09-09-Overflow.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2009-01-13-nonconstant-stride-outside-loop.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/2009-11-10-LSRCrash.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/count-to-zero.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dead-phi.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dg.exp create mode 100644 final/test/Transforms/LoopStrengthReduce/different-type-ivs.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dont-hoist-simple-loop-constants.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dont_insert_redundant_ops.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dont_reduce_bytes.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/dont_reverse.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/exit_compare_live_range.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/hoist-parent-preheader.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/invariant_value_first.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/nested-reduce.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/nonlinear-postinc.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/phi_node_update_multiple_preds.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/pr2537.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/pr2570.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/pr3086.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/pr3399.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/pr3571.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/related_indvars.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/remove_indvar.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/share_code_in_preheader.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/share_ivs.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/uglygep.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/use_postinc_value_outside_loop.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/var_stride_used_by_compare.ll create mode 100644 final/test/Transforms/LoopStrengthReduce/variable_stride.ll create mode 100644 final/test/Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll create mode 100644 final/test/Transforms/LoopUnroll/2005-03-06-BadLoopInfoUpdate.ll create mode 100644 final/test/Transforms/LoopUnroll/2006-08-24-MultiBlockLoop.ll create mode 100644 final/test/Transforms/LoopUnroll/2007-04-16-PhiUpdate.ll create mode 100644 final/test/Transforms/LoopUnroll/2007-05-05-UnrollMiscomp.ll create mode 100644 final/test/Transforms/LoopUnroll/2007-05-09-UnknownTripCount.ll create mode 100644 final/test/Transforms/LoopUnroll/2007-11-05-Crash.ll create mode 100644 final/test/Transforms/LoopUnroll/basic.ll create mode 100644 final/test/Transforms/LoopUnroll/dg.exp create mode 100644 final/test/Transforms/LoopUnroll/shifted-tripcount.ll create mode 100644 final/test/Transforms/LoopUnswitch/2006-06-13-SingleEntryPHI.ll create mode 100644 final/test/Transforms/LoopUnswitch/2006-06-27-DeadSwitchCase.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-05-09-Unreachable.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-05-09-tl.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-07-12-ExitDomInfo.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-07-13-DomInfo.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-07-18-DomInfo.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-08-01-Dom.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-08-01-LCSSA.ll create mode 100644 final/test/Transforms/LoopUnswitch/2007-10-04-DomFrontier.ll create mode 100644 final/test/Transforms/LoopUnswitch/2008-06-02-DomInfo.ll create mode 100644 final/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll create mode 100644 final/test/Transforms/LoopUnswitch/2008-11-03-Invariant.ll create mode 100644 final/test/Transforms/LoopUnswitch/2010-11-18-LCSSA.ll create mode 100644 final/test/Transforms/LoopUnswitch/basictest.ll create mode 100644 final/test/Transforms/LoopUnswitch/crash.ll create mode 100644 final/test/Transforms/LoopUnswitch/dg.exp create mode 100644 final/test/Transforms/LoopUnswitch/infinite-loop.ll create mode 100644 final/test/Transforms/LoopUnswitch/preserve-analyses.ll create mode 100644 final/test/Transforms/LowerAtomic/atomic-load.ll create mode 100644 final/test/Transforms/LowerAtomic/atomic-swap.ll create mode 100644 final/test/Transforms/LowerAtomic/barrier.ll create mode 100644 final/test/Transforms/LowerAtomic/dg.exp create mode 100644 final/test/Transforms/LowerInvoke/2003-12-10-Crash.ll create mode 100644 final/test/Transforms/LowerInvoke/2004-02-29-PHICrash.ll create mode 100644 final/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHI.ll create mode 100644 final/test/Transforms/LowerInvoke/2005-08-03-InvokeWithPHIUse.ll create mode 100644 final/test/Transforms/LowerInvoke/2008-02-14-CritEdgePhiCrash.ll create mode 100644 final/test/Transforms/LowerInvoke/basictest.ll create mode 100644 final/test/Transforms/LowerInvoke/dg.exp create mode 100644 final/test/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll create mode 100644 final/test/Transforms/LowerSetJmp/dg.exp create mode 100644 final/test/Transforms/LowerSetJmp/simpletest.ll create mode 100644 final/test/Transforms/LowerSwitch/2003-05-01-PHIProblem.ll create mode 100644 final/test/Transforms/LowerSwitch/2003-08-23-EmptySwitch.ll create mode 100644 final/test/Transforms/LowerSwitch/2004-03-13-SwitchIsDefaultCrash.ll create mode 100644 final/test/Transforms/LowerSwitch/dg.exp create mode 100644 final/test/Transforms/LowerSwitch/feature.ll create mode 100644 final/test/Transforms/Mem2Reg/2002-03-28-UninitializedVal.ll create mode 100644 final/test/Transforms/Mem2Reg/2002-05-01-ShouldNotPromoteThisAlloca.ll create mode 100644 final/test/Transforms/Mem2Reg/2003-04-10-DFNotFound.ll create mode 100644 final/test/Transforms/Mem2Reg/2003-04-18-DeadBlockProblem.ll create mode 100644 final/test/Transforms/Mem2Reg/2003-04-24-MultipleIdenticalSuccessors.ll create mode 100644 final/test/Transforms/Mem2Reg/2003-06-26-IterativePromote.ll create mode 100644 final/test/Transforms/Mem2Reg/2003-10-05-DeadPHIInsertion.ll create mode 100644 final/test/Transforms/Mem2Reg/2005-06-30-ReadBeforeWrite.ll create mode 100644 final/test/Transforms/Mem2Reg/2005-11-28-Crash.ll create mode 100644 final/test/Transforms/Mem2Reg/2007-08-27-VolatileLoadsStores.ll create mode 100644 final/test/Transforms/Mem2Reg/ConvertDebugInfo.ll create mode 100644 final/test/Transforms/Mem2Reg/ConvertDebugInfo2.ll create mode 100644 final/test/Transforms/Mem2Reg/PromoteMemToRegister.ll create mode 100644 final/test/Transforms/Mem2Reg/UndefValuesMerge.ll create mode 100644 final/test/Transforms/Mem2Reg/crash.ll create mode 100644 final/test/Transforms/Mem2Reg/dg.exp create mode 100644 final/test/Transforms/MemCpyOpt/2008-02-24-MultipleUseofSRet.ll create mode 100644 final/test/Transforms/MemCpyOpt/2008-03-13-ReturnSlotBitcast.ll create mode 100644 final/test/Transforms/MemCpyOpt/align.ll create mode 100644 final/test/Transforms/MemCpyOpt/crash.ll create mode 100644 final/test/Transforms/MemCpyOpt/dg.exp create mode 100644 final/test/Transforms/MemCpyOpt/form-memset.ll create mode 100644 final/test/Transforms/MemCpyOpt/loadstore-sret.ll create mode 100644 final/test/Transforms/MemCpyOpt/memcpy-to-memset.ll create mode 100644 final/test/Transforms/MemCpyOpt/memcpy.ll create mode 100644 final/test/Transforms/MemCpyOpt/memmove.ll create mode 100644 final/test/Transforms/MemCpyOpt/smaller.ll create mode 100644 final/test/Transforms/MemCpyOpt/sret.ll create mode 100644 final/test/Transforms/MergeFunc/2011-02-08-RemoveEqual.ll create mode 100644 final/test/Transforms/MergeFunc/dg.exp create mode 100644 final/test/Transforms/MergeFunc/fold-weak.ll create mode 100644 final/test/Transforms/MergeFunc/phi-speculation1.ll create mode 100644 final/test/Transforms/MergeFunc/phi-speculation2.ll create mode 100644 final/test/Transforms/MergeFunc/vector.ll create mode 100644 final/test/Transforms/MergeFunc/vectors-and-arrays.ll create mode 100644 final/test/Transforms/PruneEH/2003-09-14-ExternalCall.ll create mode 100644 final/test/Transforms/PruneEH/2003-11-21-PHIUpdate.ll create mode 100644 final/test/Transforms/PruneEH/2008-06-02-Weak.ll create mode 100644 final/test/Transforms/PruneEH/2008-09-05-CGUpdate.ll create mode 100644 final/test/Transforms/PruneEH/dg.exp create mode 100644 final/test/Transforms/PruneEH/recursivetest.ll create mode 100644 final/test/Transforms/PruneEH/simplenoreturntest.ll create mode 100644 final/test/Transforms/PruneEH/simpletest.ll create mode 100644 final/test/Transforms/Reassociate/2002-05-15-AgressiveSubMove.ll create mode 100644 final/test/Transforms/Reassociate/2002-05-15-MissedTree.ll create mode 100644 final/test/Transforms/Reassociate/2002-05-15-SubReassociate.ll create mode 100644 final/test/Transforms/Reassociate/2002-05-15-SubReassociate2.ll create mode 100644 final/test/Transforms/Reassociate/2002-07-09-DominanceProblem.ll create mode 100644 final/test/Transforms/Reassociate/2003-08-12-InfiniteLoop.ll create mode 100644 final/test/Transforms/Reassociate/2005-08-24-Crash.ll create mode 100644 final/test/Transforms/Reassociate/2005-09-01-ArrayOutOfBounds.ll create mode 100644 final/test/Transforms/Reassociate/2006-04-27-ReassociateVector.ll create mode 100644 final/test/Transforms/Reassociate/2011-01-26-UseAfterFree.ll create mode 100644 final/test/Transforms/Reassociate/basictest.ll create mode 100644 final/test/Transforms/Reassociate/crash.ll create mode 100644 final/test/Transforms/Reassociate/dg.exp create mode 100644 final/test/Transforms/Reassociate/inverses.ll create mode 100644 final/test/Transforms/Reassociate/looptest.ll create mode 100644 final/test/Transforms/Reassociate/mulfactor.ll create mode 100644 final/test/Transforms/Reassociate/mulfactor2.ll create mode 100644 final/test/Transforms/Reassociate/negation.ll create mode 100644 final/test/Transforms/Reassociate/optional-flags.ll create mode 100644 final/test/Transforms/Reassociate/otherops.ll create mode 100644 final/test/Transforms/Reassociate/shift-factor.ll create mode 100644 final/test/Transforms/Reassociate/shifttest.ll create mode 100644 final/test/Transforms/Reassociate/subtest.ll create mode 100644 final/test/Transforms/Reassociate/subtest2.ll create mode 100644 final/test/Transforms/SCCP/2002-05-02-EdgeFailure.ll create mode 100644 final/test/Transforms/SCCP/2002-05-02-MissSecondInst.ll create mode 100644 final/test/Transforms/SCCP/2002-05-20-MissedIncomingValue.ll create mode 100644 final/test/Transforms/SCCP/2002-05-21-InvalidSimplify.ll create mode 100644 final/test/Transforms/SCCP/2002-08-30-GetElementPtrTest.ll create mode 100644 final/test/Transforms/SCCP/2003-06-24-OverdefinedPHIValue.ll create mode 100644 final/test/Transforms/SCCP/2003-08-26-InvokeHandling.ll create mode 100644 final/test/Transforms/SCCP/2004-11-16-DeadInvoke.ll create mode 100644 final/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll create mode 100644 final/test/Transforms/SCCP/2006-10-23-IPSCCP-Crash.ll create mode 100644 final/test/Transforms/SCCP/2006-12-04-PackedType.ll create mode 100644 final/test/Transforms/SCCP/2006-12-19-UndefBug.ll create mode 100644 final/test/Transforms/SCCP/2007-05-16-InvokeCrash.ll create mode 100644 final/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll create mode 100644 final/test/Transforms/SCCP/2008-04-22-multiple-ret-sccp.ll create mode 100644 final/test/Transforms/SCCP/2008-05-23-UndefCallFold.ll create mode 100644 final/test/Transforms/SCCP/2009-01-14-IPSCCP-Invoke.ll create mode 100644 final/test/Transforms/SCCP/2009-05-27-VectorOperandZero.ll create mode 100644 final/test/Transforms/SCCP/apint-array.ll create mode 100644 final/test/Transforms/SCCP/apint-basictest.ll create mode 100644 final/test/Transforms/SCCP/apint-basictest2.ll create mode 100644 final/test/Transforms/SCCP/apint-basictest3.ll create mode 100644 final/test/Transforms/SCCP/apint-basictest4.ll create mode 100644 final/test/Transforms/SCCP/apint-bigarray.ll create mode 100644 final/test/Transforms/SCCP/apint-bigint.ll create mode 100644 final/test/Transforms/SCCP/apint-bigint2.ll create mode 100644 final/test/Transforms/SCCP/apint-ipsccp1.ll create mode 100644 final/test/Transforms/SCCP/apint-ipsccp2.ll create mode 100644 final/test/Transforms/SCCP/apint-ipsccp3.ll create mode 100644 final/test/Transforms/SCCP/apint-ipsccp4.ll create mode 100644 final/test/Transforms/SCCP/apint-load.ll create mode 100644 final/test/Transforms/SCCP/apint-phi.ll create mode 100644 final/test/Transforms/SCCP/apint-select.ll create mode 100644 final/test/Transforms/SCCP/calltest.ll create mode 100644 final/test/Transforms/SCCP/crash.ll create mode 100644 final/test/Transforms/SCCP/dg.exp create mode 100644 final/test/Transforms/SCCP/ipsccp-addr-taken.ll create mode 100644 final/test/Transforms/SCCP/ipsccp-basic.ll create mode 100644 final/test/Transforms/SCCP/loadtest.ll create mode 100644 final/test/Transforms/SCCP/logical-nuke.ll create mode 100644 final/test/Transforms/SCCP/phitest.ll create mode 100644 final/test/Transforms/SCCP/retvalue-undef.ll create mode 100644 final/test/Transforms/SCCP/sccptest.ll create mode 100644 final/test/Transforms/SCCP/select.ll create mode 100644 final/test/Transforms/SCCP/undef-resolve.ll create mode 100644 final/test/Transforms/SRETPromotion/2008-03-11-attributes.ll create mode 100644 final/test/Transforms/SRETPromotion/2008-06-04-function-pointer-passing.ll create mode 100644 final/test/Transforms/SRETPromotion/2008-06-05-non-call-use.ll create mode 100644 final/test/Transforms/SRETPromotion/basictest.ll create mode 100644 final/test/Transforms/SRETPromotion/dg.exp create mode 100644 final/test/Transforms/ScalarRepl/2003-05-29-ArrayFail.ll create mode 100644 final/test/Transforms/ScalarRepl/2003-09-12-IncorrectPromote.ll create mode 100644 final/test/Transforms/ScalarRepl/2003-10-29-ArrayProblem.ll create mode 100644 final/test/Transforms/ScalarRepl/2006-11-07-InvalidArrayPromote.ll create mode 100644 final/test/Transforms/ScalarRepl/2007-05-24-LargeAggregate.ll create mode 100644 final/test/Transforms/ScalarRepl/2007-05-29-MemcpyPreserve.ll create mode 100644 final/test/Transforms/ScalarRepl/2007-11-03-bigendian_apint.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-01-29-PromoteBug.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-02-28-SubElementExtractCrash.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-08-22-out-of-range-array-promote.ll create mode 100644 final/test/Transforms/ScalarRepl/2008-09-22-vector-gep.ll create mode 100644 final/test/Transforms/ScalarRepl/2009-02-02-ScalarPromoteOutOfRange.ll create mode 100644 final/test/Transforms/ScalarRepl/2009-02-05-LoadFCA.ll create mode 100644 final/test/Transforms/ScalarRepl/2009-03-04-MemCpyAlign.ll create mode 100644 final/test/Transforms/ScalarRepl/2009-03-05-Aggre2Scalar-dbg.ll create mode 100644 final/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll create mode 100644 final/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll create mode 100644 final/test/Transforms/ScalarRepl/AggregatePromote.ll create mode 100644 final/test/Transforms/ScalarRepl/DifferingTypes.ll create mode 100644 final/test/Transforms/ScalarRepl/address-space.ll create mode 100644 final/test/Transforms/ScalarRepl/arraytest.ll create mode 100644 final/test/Transforms/ScalarRepl/badarray.ll create mode 100644 final/test/Transforms/ScalarRepl/basictest.ll create mode 100644 final/test/Transforms/ScalarRepl/bitfield-sroa.ll create mode 100644 final/test/Transforms/ScalarRepl/copy-aggregate.ll create mode 100644 final/test/Transforms/ScalarRepl/crash.ll create mode 100644 final/test/Transforms/ScalarRepl/debuginfo.ll create mode 100644 final/test/Transforms/ScalarRepl/dg.exp create mode 100644 final/test/Transforms/ScalarRepl/load-store-aggregate.ll create mode 100644 final/test/Transforms/ScalarRepl/memcpy-align.ll create mode 100644 final/test/Transforms/ScalarRepl/memcpy-from-global.ll create mode 100644 final/test/Transforms/ScalarRepl/memset-aggregate-byte-leader.ll create mode 100644 final/test/Transforms/ScalarRepl/memset-aggregate.ll create mode 100644 final/test/Transforms/ScalarRepl/nonzero-first-index.ll create mode 100644 final/test/Transforms/ScalarRepl/not-a-vector.ll create mode 100644 final/test/Transforms/ScalarRepl/phi-select.ll create mode 100644 final/test/Transforms/ScalarRepl/phinodepromote.ll create mode 100644 final/test/Transforms/ScalarRepl/select_promote.ll create mode 100644 final/test/Transforms/ScalarRepl/sroa-fca.ll create mode 100644 final/test/Transforms/ScalarRepl/sroa_two.ll create mode 100644 final/test/Transforms/ScalarRepl/union-fp-int.ll create mode 100644 final/test/Transforms/ScalarRepl/union-packed.ll create mode 100644 final/test/Transforms/ScalarRepl/union-pointer.ll create mode 100644 final/test/Transforms/ScalarRepl/vector_memcpy.ll create mode 100644 final/test/Transforms/ScalarRepl/vector_promote.ll create mode 100644 final/test/Transforms/ScalarRepl/volatile.ll create mode 100644 final/test/Transforms/SimplifyCFG/2002-05-05-EmptyBlockMerge.ll create mode 100644 final/test/Transforms/SimplifyCFG/2002-05-21-PHIElimination.ll create mode 100644 final/test/Transforms/SimplifyCFG/2002-06-24-PHINode.ll create mode 100644 final/test/Transforms/SimplifyCFG/2002-09-24-PHIAssertion.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-03-07-DominateProblem.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-05-InvokeCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-05-MishandleInvoke.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-17-BranchFold.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-17-BranchFoldOrdering.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch-dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/2003-08-17-FoldSwitch.ll create mode 100644 final/test/Transforms/SimplifyCFG/2004-12-10-SimplifyCFGCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2005-06-16-PHICrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2005-08-01-PHIUpdateFail.ll create mode 100644 final/test/Transforms/SimplifyCFG/2005-08-03-PHIFactorCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll create mode 100644 final/test/Transforms/SimplifyCFG/2005-12-03-IncorrectPHIFold.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-02-17-InfiniteUnroll.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-06-12-InfLoop.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-08-03-Crash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-10-19-UncondDiv.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-10-29-InvokeCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2006-12-08-Ptr-ICmp-Branch.ll create mode 100644 final/test/Transforms/SimplifyCFG/2007-11-22-InvokeNoUnwind.ll create mode 100644 final/test/Transforms/SimplifyCFG/2007-12-21-Crash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-01-02-hoist-fp-add.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-04-27-MultipleReturnCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-05-16-PHIBlockMerge.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-07-13-InfLoopMiscompile.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-09-08-MultiplePred.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-09-17-SpeculativeHoist.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-10-03-SpeculativelyExecuteBeforePHI.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-12-06-SingleEntryPhi.ll create mode 100644 final/test/Transforms/SimplifyCFG/2008-12-16-DCECond.ll create mode 100644 final/test/Transforms/SimplifyCFG/2009-01-18-PHIPropCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2009-01-19-UnconditionalTrappingConstantExpr.ll create mode 100644 final/test/Transforms/SimplifyCFG/2009-03-05-Speculative-Hoist-Dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/2009-05-12-externweak.ll create mode 100644 final/test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2010-03-30-InvokeCrash.ll create mode 100644 final/test/Transforms/SimplifyCFG/2010-10-24-OnlyUnwindInEntry.ll create mode 100644 final/test/Transforms/SimplifyCFG/BrUnwind.ll create mode 100644 final/test/Transforms/SimplifyCFG/DeadSetCC.ll create mode 100644 final/test/Transforms/SimplifyCFG/EqualPHIEdgeBlockMerge.ll create mode 100644 final/test/Transforms/SimplifyCFG/HoistCode.ll create mode 100644 final/test/Transforms/SimplifyCFG/MagicPointer.ll create mode 100644 final/test/Transforms/SimplifyCFG/PhiBlockMerge.ll create mode 100644 final/test/Transforms/SimplifyCFG/PhiBlockMerge2.ll create mode 100644 final/test/Transforms/SimplifyCFG/PhiEliminate.ll create mode 100644 final/test/Transforms/SimplifyCFG/PhiEliminate2.ll create mode 100644 final/test/Transforms/SimplifyCFG/PhiNoEliminate.ll create mode 100644 final/test/Transforms/SimplifyCFG/SpeculativeExec.ll create mode 100644 final/test/Transforms/SimplifyCFG/UncondBranchToReturn.ll create mode 100644 final/test/Transforms/SimplifyCFG/UnreachableEliminate.ll create mode 100644 final/test/Transforms/SimplifyCFG/basictest.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-branch-dbginfo.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-cond-merge.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-cond-prop.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-fold-test.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-fold.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch-phi-thread.ll create mode 100644 final/test/Transforms/SimplifyCFG/branch_fold_dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/dbginfo.ll create mode 100644 final/test/Transforms/SimplifyCFG/dg.exp create mode 100644 final/test/Transforms/SimplifyCFG/duplicate-phis.ll create mode 100644 final/test/Transforms/SimplifyCFG/hoist-common-code.dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/hoist-common-code.ll create mode 100644 final/test/Transforms/SimplifyCFG/indirectbr.ll create mode 100644 final/test/Transforms/SimplifyCFG/invoke_unwind.ll create mode 100644 final/test/Transforms/SimplifyCFG/iterative-simplify.ll create mode 100644 final/test/Transforms/SimplifyCFG/noreturn-call.ll create mode 100644 final/test/Transforms/SimplifyCFG/return-merge.ll create mode 100644 final/test/Transforms/SimplifyCFG/select-gep.ll create mode 100644 final/test/Transforms/SimplifyCFG/speculate-with-offset.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch-on-const-select.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch-simplify-crash.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch-to-icmp.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch_create.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch_formation.dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch_switch_fold.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch_switch_fold_dbginfo.ll create mode 100644 final/test/Transforms/SimplifyCFG/switch_thread.ll create mode 100644 final/test/Transforms/SimplifyCFG/trapping-load-unreachable.ll create mode 100644 final/test/Transforms/SimplifyCFG/two-entry-phi-return.dbg.ll create mode 100644 final/test/Transforms/SimplifyCFG/two-entry-phi-return.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2005-05-20-sprintf-crash.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2007-04-06-strchr-miscompile.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2008-05-19-memcmp.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-01-04-Annotate.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-02-11-NotInitialized.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-02-12-StrTo.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-05-30-memcmp-byte.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-07-28-Exit.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2009-07-29-Exit2.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/2010-05-30-memcpy-Struct.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/FFS.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/FPrintF.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/FPuts.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/IsDigit.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/MemCpy.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/PR7357.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/Printf.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/Puts.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/SPrintF.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrCat.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrChr.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrCmp.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrCpy.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrLen.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrNCat.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrNCmp.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrNCpy.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrPBrk.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrRChr.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrSpn.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/StrStr.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/ToAscii.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/abs.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/dg.exp create mode 100644 final/test/Transforms/SimplifyLibCalls/exp2.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/floor.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/iprintf.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/memcmp.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/memmove.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/memset-64.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/memset.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/pow-to-sqrt.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/pow2.ll create mode 100644 final/test/Transforms/SimplifyLibCalls/weak-symbols.ll create mode 100644 final/test/Transforms/Sink/basic.ll create mode 100644 final/test/Transforms/Sink/dg.exp create mode 100644 final/test/Transforms/StripSymbols/2007-01-15-llvm.used.ll create mode 100644 final/test/Transforms/StripSymbols/2010-06-30-StripDebug.ll create mode 100644 final/test/Transforms/StripSymbols/2010-07-01-DeadDbgInfo.ll create mode 100644 final/test/Transforms/StripSymbols/2010-08-25-crash.ll create mode 100644 final/test/Transforms/StripSymbols/dg.exp create mode 100644 final/test/Transforms/TailCallElim/2010-06-26-MultipleReturnValues.ll create mode 100644 final/test/Transforms/TailCallElim/accum_recursion.ll create mode 100644 final/test/Transforms/TailCallElim/ackermann.ll create mode 100644 final/test/Transforms/TailCallElim/dg.exp create mode 100644 final/test/Transforms/TailCallElim/dont-tce-tail-marked-call.ll create mode 100644 final/test/Transforms/TailCallElim/dont_reorder_load.ll create mode 100644 final/test/Transforms/TailCallElim/dup_tail.ll create mode 100644 final/test/Transforms/TailCallElim/inf-recursion.ll create mode 100644 final/test/Transforms/TailCallElim/intervening-inst.ll create mode 100644 final/test/Transforms/TailCallElim/move_alloca_for_tail_call.ll create mode 100644 final/test/Transforms/TailCallElim/nocapture.ll create mode 100644 final/test/Transforms/TailCallElim/reorder_load.ll create mode 100644 final/test/Transforms/TailCallElim/return_constant.ll create mode 100644 final/test/Transforms/TailCallElim/trivial_codegen_tailcall.ll create mode 100644 final/test/Transforms/TailDup/2003-06-24-Simpleloop.ll create mode 100644 final/test/Transforms/TailDup/2003-07-22-InfiniteLoop.ll create mode 100644 final/test/Transforms/TailDup/2003-08-23-InvalidatedPointers.ll create mode 100644 final/test/Transforms/TailDup/2003-08-31-UnreachableBlocks.ll create mode 100644 final/test/Transforms/TailDup/2004-04-01-DemoteRegToStack.ll create mode 100644 final/test/Transforms/TailDup/2008-05-13-InfiniteLoop.ll create mode 100644 final/test/Transforms/TailDup/2008-06-11-AvoidDupLoopHeader.ll create mode 100644 final/test/Transforms/TailDup/2009-07-31-phicrash.ll create mode 100644 final/test/Transforms/TailDup/MergeTest.ll create mode 100644 final/test/Transforms/TailDup/PHIUpdateTest.ll create mode 100644 final/test/Transforms/TailDup/basictest.ll create mode 100644 final/test/Transforms/TailDup/basictest2.ll create mode 100644 final/test/Transforms/TailDup/dg.exp create mode 100644 final/test/Transforms/TailDup/if-tail-dup.ll create mode 100644 final/test/Unit/lit.cfg create mode 100644 final/test/Unit/lit.site.cfg.in create mode 100644 final/test/Verifier/2002-04-13-RetTypes.ll create mode 100644 final/test/Verifier/2002-11-05-GetelementptrPointers.ll create mode 100644 final/test/Verifier/2004-05-21-SwitchConstantMismatch.ll create mode 100644 final/test/Verifier/2005-03-21-UndefinedTypeReference.ll create mode 100644 final/test/Verifier/2006-07-11-StoreStruct.ll create mode 100644 final/test/Verifier/2006-10-15-AddrLabel.ll create mode 100644 final/test/Verifier/2006-12-12-IntrinsicDefine.ll create mode 100644 final/test/Verifier/2007-12-21-InvokeParamAttrs.ll create mode 100644 final/test/Verifier/2008-01-11-VarargAttrs.ll create mode 100644 final/test/Verifier/2008-03-01-AllocaSized.ll create mode 100644 final/test/Verifier/2008-08-22-MemCpyAlignment.ll create mode 100644 final/test/Verifier/2008-11-15-RetVoid.ll create mode 100644 final/test/Verifier/2009-05-29-InvokeResult1.ll create mode 100644 final/test/Verifier/2009-05-29-InvokeResult2.ll create mode 100644 final/test/Verifier/2009-05-29-InvokeResult3.ll create mode 100644 final/test/Verifier/2010-08-07-PointerIntrinsic.ll create mode 100644 final/test/Verifier/AmbiguousPhi.ll create mode 100644 final/test/Verifier/PhiGrouping.ll create mode 100644 final/test/Verifier/README.txt create mode 100644 final/test/Verifier/SelfReferential.ll create mode 100644 final/test/Verifier/aliasing-chain.ll create mode 100644 final/test/Verifier/byval-1.ll create mode 100644 final/test/Verifier/byval-2.ll create mode 100644 final/test/Verifier/byval-4.ll create mode 100644 final/test/Verifier/dg.exp create mode 100644 final/test/Verifier/gcread-ptrptr.ll create mode 100644 final/test/Verifier/gcroot-alloca.ll create mode 100644 final/test/Verifier/gcroot-meta.ll create mode 100644 final/test/Verifier/gcroot-ptrptr.ll create mode 100644 final/test/Verifier/gcwrite-ptrptr.ll create mode 100644 final/test/Verifier/invoke-1.ll create mode 100644 final/test/Verifier/invoke-2.ll create mode 100644 final/test/lib/llvm.exp create mode 100644 final/test/lib/llvm2cpp.exp create mode 100644 final/test/lit.cfg create mode 100644 final/test/lit.site.cfg.in create mode 100644 final/test/site.exp.in create mode 100644 final/tools/CMakeLists.txt create mode 100644 final/tools/Makefile create mode 100644 final/tools/bugpoint-passes/CMakeLists.txt create mode 100644 final/tools/bugpoint-passes/Makefile create mode 100644 final/tools/bugpoint-passes/TestPasses.cpp create mode 100644 final/tools/bugpoint-passes/bugpoint.exports create mode 100644 final/tools/bugpoint/BugDriver.cpp create mode 100644 final/tools/bugpoint/BugDriver.h create mode 100644 final/tools/bugpoint/CMakeLists.txt create mode 100644 final/tools/bugpoint/CrashDebugger.cpp create mode 100644 final/tools/bugpoint/ExecutionDriver.cpp create mode 100644 final/tools/bugpoint/ExtractFunction.cpp create mode 100644 final/tools/bugpoint/FindBugs.cpp create mode 100644 final/tools/bugpoint/ListReducer.h create mode 100644 final/tools/bugpoint/Makefile create mode 100644 final/tools/bugpoint/Miscompilation.cpp create mode 100644 final/tools/bugpoint/OptimizerDriver.cpp create mode 100644 final/tools/bugpoint/ToolRunner.cpp create mode 100644 final/tools/bugpoint/ToolRunner.h create mode 100644 final/tools/bugpoint/bugpoint.cpp create mode 100644 final/tools/edis/CMakeLists.txt create mode 100644 final/tools/edis/EDMain.cpp create mode 100644 final/tools/edis/EnhancedDisassembly.exports create mode 100644 final/tools/edis/Makefile create mode 100644 final/tools/gold/Makefile create mode 100644 final/tools/gold/README.txt create mode 100644 final/tools/gold/gold-plugin.cpp create mode 100644 final/tools/gold/gold.exports create mode 100644 final/tools/llc/CMakeLists.txt create mode 100644 final/tools/llc/Makefile create mode 100644 final/tools/llc/llc.cpp create mode 100644 final/tools/lli/CMakeLists.txt create mode 100644 final/tools/lli/Makefile create mode 100644 final/tools/lli/lli.cpp create mode 100644 final/tools/llvm-ar/CMakeLists.txt create mode 100644 final/tools/llvm-ar/Makefile create mode 100644 final/tools/llvm-ar/llvm-ar.cpp create mode 100644 final/tools/llvm-as/CMakeLists.txt create mode 100644 final/tools/llvm-as/Makefile create mode 100644 final/tools/llvm-as/llvm-as.cpp create mode 100644 final/tools/llvm-bcanalyzer/CMakeLists.txt create mode 100644 final/tools/llvm-bcanalyzer/Makefile create mode 100644 final/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp create mode 100644 final/tools/llvm-config/CMakeLists.txt create mode 100644 final/tools/llvm-config/Makefile create mode 100755 final/tools/llvm-config/find-cycles.pl create mode 100644 final/tools/llvm-config/llvm-config.in.in create mode 100644 final/tools/llvm-diff/CMakeLists.txt create mode 100644 final/tools/llvm-diff/DifferenceEngine.cpp create mode 100644 final/tools/llvm-diff/DifferenceEngine.h create mode 100644 final/tools/llvm-diff/Makefile create mode 100644 final/tools/llvm-diff/llvm-diff.cpp create mode 100644 final/tools/llvm-dis/CMakeLists.txt create mode 100644 final/tools/llvm-dis/Makefile create mode 100644 final/tools/llvm-dis/llvm-dis.cpp create mode 100644 final/tools/llvm-extract/CMakeLists.txt create mode 100644 final/tools/llvm-extract/Makefile create mode 100644 final/tools/llvm-extract/llvm-extract.cpp create mode 100644 final/tools/llvm-ld/CMakeLists.txt create mode 100644 final/tools/llvm-ld/Makefile create mode 100644 final/tools/llvm-ld/Optimize.cpp create mode 100644 final/tools/llvm-ld/llvm-ld.cpp create mode 100644 final/tools/llvm-link/CMakeLists.txt create mode 100644 final/tools/llvm-link/Makefile create mode 100644 final/tools/llvm-link/llvm-link.cpp create mode 100644 final/tools/llvm-mc/CMakeLists.txt create mode 100644 final/tools/llvm-mc/Disassembler.cpp create mode 100644 final/tools/llvm-mc/Disassembler.h create mode 100644 final/tools/llvm-mc/Makefile create mode 100644 final/tools/llvm-mc/llvm-mc.cpp create mode 100644 final/tools/llvm-nm/CMakeLists.txt create mode 100644 final/tools/llvm-nm/Makefile create mode 100644 final/tools/llvm-nm/llvm-nm.cpp create mode 100644 final/tools/llvm-objdump/CMakeLists.txt create mode 100644 final/tools/llvm-objdump/Makefile create mode 100644 final/tools/llvm-objdump/llvm-objdump.cpp create mode 100644 final/tools/llvm-prof/CMakeLists.txt create mode 100644 final/tools/llvm-prof/Makefile create mode 100644 final/tools/llvm-prof/llvm-prof.cpp create mode 100644 final/tools/llvm-ranlib/CMakeLists.txt create mode 100644 final/tools/llvm-ranlib/Makefile create mode 100644 final/tools/llvm-ranlib/llvm-ranlib.cpp create mode 100644 final/tools/llvm-shlib/Makefile create mode 100644 final/tools/llvm-stub/CMakeLists.txt create mode 100644 final/tools/llvm-stub/Makefile create mode 100644 final/tools/llvm-stub/llvm-stub.c create mode 100644 final/tools/llvmc/CMakeLists.txt create mode 100644 final/tools/llvmc/Makefile create mode 100644 final/tools/llvmc/doc/LLVMC-Reference.rst create mode 100644 final/tools/llvmc/doc/LLVMC-Tutorial.rst create mode 100644 final/tools/llvmc/doc/Makefile create mode 100644 final/tools/llvmc/doc/img/lines.gif create mode 100644 final/tools/llvmc/examples/Hello/Hello.cpp create mode 100644 final/tools/llvmc/examples/Hello/Makefile create mode 100644 final/tools/llvmc/examples/Makefile create mode 100644 final/tools/llvmc/examples/Simple/Makefile create mode 100644 final/tools/llvmc/examples/Simple/Simple.cpp create mode 100644 final/tools/llvmc/examples/Simple/Simple.td create mode 100644 final/tools/llvmc/examples/Skeleton/AutoGenerated.td create mode 100644 final/tools/llvmc/examples/Skeleton/Hooks.cpp create mode 100644 final/tools/llvmc/examples/Skeleton/Main.cpp create mode 100644 final/tools/llvmc/examples/Skeleton/Makefile create mode 100644 final/tools/llvmc/examples/Skeleton/README create mode 100644 final/tools/llvmc/examples/mcc16/Hooks.cpp create mode 100644 final/tools/llvmc/examples/mcc16/Main.cpp create mode 100644 final/tools/llvmc/examples/mcc16/Makefile create mode 100644 final/tools/llvmc/examples/mcc16/PIC16.td create mode 100644 final/tools/llvmc/examples/mcc16/README create mode 100644 final/tools/llvmc/src/AutoGenerated.td create mode 100644 final/tools/llvmc/src/Base.td.in create mode 100644 final/tools/llvmc/src/Clang.td create mode 100644 final/tools/llvmc/src/Hooks.cpp create mode 100644 final/tools/llvmc/src/Main.cpp create mode 100644 final/tools/llvmc/src/Makefile create mode 100644 final/tools/lto/LTOCodeGenerator.cpp create mode 100644 final/tools/lto/LTOCodeGenerator.h create mode 100644 final/tools/lto/LTOModule.cpp create mode 100644 final/tools/lto/LTOModule.h create mode 100644 final/tools/lto/Makefile create mode 100644 final/tools/lto/lto.cpp create mode 100644 final/tools/lto/lto.exports create mode 100644 final/tools/macho-dump/CMakeLists.txt create mode 100644 final/tools/macho-dump/Makefile create mode 100644 final/tools/macho-dump/macho-dump.cpp create mode 100644 final/tools/opt/AnalysisWrappers.cpp create mode 100644 final/tools/opt/CMakeLists.txt create mode 100644 final/tools/opt/GraphPrinters.cpp create mode 100644 final/tools/opt/Makefile create mode 100644 final/tools/opt/PrintSCC.cpp create mode 100644 final/tools/opt/opt.cpp create mode 100644 final/unittests/ADT/APFloatTest.cpp create mode 100644 final/unittests/ADT/APIntTest.cpp create mode 100644 final/unittests/ADT/BitVectorTest.cpp create mode 100644 final/unittests/ADT/DAGDeltaAlgorithmTest.cpp create mode 100644 final/unittests/ADT/DeltaAlgorithmTest.cpp create mode 100644 final/unittests/ADT/DenseMapTest.cpp create mode 100644 final/unittests/ADT/DenseSetTest.cpp create mode 100644 final/unittests/ADT/FoldingSet.cpp create mode 100644 final/unittests/ADT/ImmutableSetTest.cpp create mode 100644 final/unittests/ADT/IntEqClassesTest.cpp create mode 100644 final/unittests/ADT/IntervalMapTest.cpp create mode 100644 final/unittests/ADT/Makefile create mode 100644 final/unittests/ADT/SmallBitVectorTest.cpp create mode 100644 final/unittests/ADT/SmallStringTest.cpp create mode 100644 final/unittests/ADT/SmallVectorTest.cpp create mode 100644 final/unittests/ADT/SparseBitVectorTest.cpp create mode 100644 final/unittests/ADT/StringMapTest.cpp create mode 100644 final/unittests/ADT/StringRefTest.cpp create mode 100644 final/unittests/ADT/TripleTest.cpp create mode 100644 final/unittests/ADT/TwineTest.cpp create mode 100644 final/unittests/ADT/ilistTest.cpp create mode 100644 final/unittests/Analysis/Makefile create mode 100644 final/unittests/Analysis/ScalarEvolutionTest.cpp create mode 100644 final/unittests/CMakeLists.txt create mode 100644 final/unittests/ExecutionEngine/ExecutionEngineTest.cpp create mode 100644 final/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp create mode 100644 final/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp create mode 100644 final/unittests/ExecutionEngine/JIT/JITTest.cpp create mode 100644 final/unittests/ExecutionEngine/JIT/JITTests.def create mode 100644 final/unittests/ExecutionEngine/JIT/Makefile create mode 100644 final/unittests/ExecutionEngine/JIT/MultiJITTest.cpp create mode 100644 final/unittests/ExecutionEngine/Makefile create mode 100644 final/unittests/Makefile create mode 100644 final/unittests/Makefile.unittest create mode 100644 final/unittests/Support/AllocatorTest.cpp create mode 100644 final/unittests/Support/Casting.cpp create mode 100644 final/unittests/Support/CommandLineTest.cpp create mode 100644 final/unittests/Support/ConstantRangeTest.cpp create mode 100644 final/unittests/Support/EndianTest.cpp create mode 100644 final/unittests/Support/LeakDetectorTest.cpp create mode 100644 final/unittests/Support/Makefile create mode 100644 final/unittests/Support/MathExtrasTest.cpp create mode 100644 final/unittests/Support/Path.cpp create mode 100644 final/unittests/Support/RegexTest.cpp create mode 100644 final/unittests/Support/SwapByteOrderTest.cpp create mode 100644 final/unittests/Support/TimeValue.cpp create mode 100644 final/unittests/Support/TypeBuilderTest.cpp create mode 100644 final/unittests/Support/ValueHandleTest.cpp create mode 100644 final/unittests/Support/raw_ostream_test.cpp create mode 100644 final/unittests/Transforms/Makefile create mode 100644 final/unittests/Transforms/Utils/Cloning.cpp create mode 100644 final/unittests/Transforms/Utils/Local.cpp create mode 100644 final/unittests/Transforms/Utils/Makefile create mode 100644 final/unittests/VMCore/ConstantsTest.cpp create mode 100644 final/unittests/VMCore/DerivedTypesTest.cpp create mode 100644 final/unittests/VMCore/InstructionsTest.cpp create mode 100644 final/unittests/VMCore/Makefile create mode 100644 final/unittests/VMCore/MetadataTest.cpp create mode 100644 final/unittests/VMCore/PassManagerTest.cpp create mode 100644 final/unittests/VMCore/ValueMapTest.cpp create mode 100644 final/unittests/VMCore/VerifierTest.cpp create mode 100755 final/utils/CollectDebugInfoUsingLLDB.py create mode 100755 final/utils/CompareDebugInfo.py create mode 100755 final/utils/DSAclean.py create mode 100644 final/utils/DSAextract.py create mode 100644 final/utils/FileCheck/CMakeLists.txt create mode 100644 final/utils/FileCheck/FileCheck.cpp create mode 100644 final/utils/FileCheck/Makefile create mode 100644 final/utils/FileUpdate/CMakeLists.txt create mode 100644 final/utils/FileUpdate/FileUpdate.cpp create mode 100644 final/utils/FileUpdate/Makefile create mode 100755 final/utils/GenLibDeps.pl create mode 100755 final/utils/GetRepositoryPath create mode 100755 final/utils/GetSourceVersion create mode 100644 final/utils/KillTheDoctor/CMakeLists.txt create mode 100644 final/utils/KillTheDoctor/KillTheDoctor.cpp create mode 100644 final/utils/Makefile create mode 100755 final/utils/Misc/zkill create mode 100644 final/utils/NLT.schema create mode 100755 final/utils/NewNightlyTest.pl create mode 100644 final/utils/NightlyTest.gnuplot create mode 100644 final/utils/NightlyTestTemplate.html create mode 100644 final/utils/PerfectShuffle/Makefile create mode 100644 final/utils/PerfectShuffle/PerfectShuffle.cpp create mode 100644 final/utils/TableGen/ARMDecoderEmitter.cpp create mode 100644 final/utils/TableGen/ARMDecoderEmitter.h create mode 100644 final/utils/TableGen/AsmMatcherEmitter.cpp create mode 100644 final/utils/TableGen/AsmMatcherEmitter.h create mode 100644 final/utils/TableGen/AsmWriterEmitter.cpp create mode 100644 final/utils/TableGen/AsmWriterEmitter.h create mode 100644 final/utils/TableGen/AsmWriterInst.cpp create mode 100644 final/utils/TableGen/AsmWriterInst.h create mode 100644 final/utils/TableGen/CMakeLists.txt create mode 100644 final/utils/TableGen/CallingConvEmitter.cpp create mode 100644 final/utils/TableGen/CallingConvEmitter.h create mode 100644 final/utils/TableGen/ClangASTNodesEmitter.cpp create mode 100644 final/utils/TableGen/ClangASTNodesEmitter.h create mode 100644 final/utils/TableGen/ClangAttrEmitter.cpp create mode 100644 final/utils/TableGen/ClangAttrEmitter.h create mode 100644 final/utils/TableGen/ClangDiagnosticsEmitter.cpp create mode 100644 final/utils/TableGen/ClangDiagnosticsEmitter.h create mode 100644 final/utils/TableGen/ClangSACheckersEmitter.cpp create mode 100644 final/utils/TableGen/ClangSACheckersEmitter.h create mode 100644 final/utils/TableGen/CodeEmitterGen.cpp create mode 100644 final/utils/TableGen/CodeEmitterGen.h create mode 100644 final/utils/TableGen/CodeGenDAGPatterns.cpp create mode 100644 final/utils/TableGen/CodeGenDAGPatterns.h create mode 100644 final/utils/TableGen/CodeGenInstruction.cpp create mode 100644 final/utils/TableGen/CodeGenInstruction.h create mode 100644 final/utils/TableGen/CodeGenIntrinsics.h create mode 100644 final/utils/TableGen/CodeGenRegisters.h create mode 100644 final/utils/TableGen/CodeGenTarget.cpp create mode 100644 final/utils/TableGen/CodeGenTarget.h create mode 100644 final/utils/TableGen/DAGISelEmitter.cpp create mode 100644 final/utils/TableGen/DAGISelEmitter.h create mode 100644 final/utils/TableGen/DAGISelMatcher.cpp create mode 100644 final/utils/TableGen/DAGISelMatcher.h create mode 100644 final/utils/TableGen/DAGISelMatcherEmitter.cpp create mode 100644 final/utils/TableGen/DAGISelMatcherGen.cpp create mode 100644 final/utils/TableGen/DAGISelMatcherOpt.cpp create mode 100644 final/utils/TableGen/DisassemblerEmitter.cpp create mode 100644 final/utils/TableGen/DisassemblerEmitter.h create mode 100644 final/utils/TableGen/EDEmitter.cpp create mode 100644 final/utils/TableGen/EDEmitter.h create mode 100644 final/utils/TableGen/FastISelEmitter.cpp create mode 100644 final/utils/TableGen/FastISelEmitter.h create mode 100644 final/utils/TableGen/FixedLenDecoderEmitter.cpp create mode 100644 final/utils/TableGen/FixedLenDecoderEmitter.h create mode 100644 final/utils/TableGen/InstrEnumEmitter.cpp create mode 100644 final/utils/TableGen/InstrEnumEmitter.h create mode 100644 final/utils/TableGen/InstrInfoEmitter.cpp create mode 100644 final/utils/TableGen/InstrInfoEmitter.h create mode 100644 final/utils/TableGen/IntrinsicEmitter.cpp create mode 100644 final/utils/TableGen/IntrinsicEmitter.h create mode 100644 final/utils/TableGen/LLVMCConfigurationEmitter.cpp create mode 100644 final/utils/TableGen/LLVMCConfigurationEmitter.h create mode 100644 final/utils/TableGen/Makefile create mode 100644 final/utils/TableGen/NeonEmitter.cpp create mode 100644 final/utils/TableGen/NeonEmitter.h create mode 100644 final/utils/TableGen/OptParserEmitter.cpp create mode 100644 final/utils/TableGen/OptParserEmitter.h create mode 100644 final/utils/TableGen/Record.cpp create mode 100644 final/utils/TableGen/Record.h create mode 100644 final/utils/TableGen/RegisterInfoEmitter.cpp create mode 100644 final/utils/TableGen/RegisterInfoEmitter.h create mode 100644 final/utils/TableGen/StringMatcher.cpp create mode 100644 final/utils/TableGen/StringMatcher.h create mode 100644 final/utils/TableGen/StringToOffsetTable.h create mode 100644 final/utils/TableGen/SubtargetEmitter.cpp create mode 100644 final/utils/TableGen/SubtargetEmitter.h create mode 100644 final/utils/TableGen/TGLexer.cpp create mode 100644 final/utils/TableGen/TGLexer.h create mode 100644 final/utils/TableGen/TGParser.cpp create mode 100644 final/utils/TableGen/TGParser.h create mode 100644 final/utils/TableGen/TGValueTypes.cpp create mode 100644 final/utils/TableGen/TableGen.cpp create mode 100644 final/utils/TableGen/TableGenBackend.cpp create mode 100644 final/utils/TableGen/TableGenBackend.h create mode 100644 final/utils/TableGen/X86DisassemblerShared.h create mode 100644 final/utils/TableGen/X86DisassemblerTables.cpp create mode 100644 final/utils/TableGen/X86DisassemblerTables.h create mode 100644 final/utils/TableGen/X86ModRMFilters.h create mode 100644 final/utils/TableGen/X86RecognizableInstr.cpp create mode 100644 final/utils/TableGen/X86RecognizableInstr.h create mode 100644 final/utils/Target/ARM/analyze-match-table.py create mode 100755 final/utils/UpdateCMakeLists.pl create mode 100644 final/utils/bugpoint/RemoteRunSafely.sh create mode 100644 final/utils/buildit/GNUmakefile create mode 100755 final/utils/buildit/build_llvm create mode 100755 final/utils/cgiplotNLT.pl create mode 100755 final/utils/check-each-file create mode 100755 final/utils/codegen-diff create mode 100644 final/utils/count/CMakeLists.txt create mode 100644 final/utils/count/Makefile create mode 100644 final/utils/count/count.c create mode 100755 final/utils/countloc.sh create mode 100644 final/utils/crosstool/ARM/README create mode 100755 final/utils/crosstool/ARM/build-install-linux.sh create mode 100755 final/utils/crosstool/create-snapshots.sh create mode 100644 final/utils/emacs/README create mode 100644 final/utils/emacs/emacs.el create mode 100644 final/utils/emacs/llvm-mode.el create mode 100644 final/utils/emacs/tablegen-mode.el create mode 100755 final/utils/findmisopt create mode 100755 final/utils/findoptdiff create mode 100755 final/utils/findsym.pl create mode 100644 final/utils/fpcmp/Makefile create mode 100644 final/utils/fpcmp/fpcmp.cpp create mode 100755 final/utils/getsrcs.sh create mode 100755 final/utils/git/find-rev create mode 100644 final/utils/importNLT.pl create mode 100644 final/utils/jedit/README create mode 100644 final/utils/jedit/tablegen.xml create mode 100644 final/utils/kate/README create mode 100644 final/utils/kate/llvm.xml create mode 100644 final/utils/lint/common_lint.py create mode 100755 final/utils/lint/cpp_lint.py create mode 100755 final/utils/lint/generic_lint.py create mode 100755 final/utils/lint/remove_trailing_whitespace.sh create mode 100644 final/utils/lit/TODO create mode 100755 final/utils/lit/lit.py create mode 100644 final/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg create mode 100644 final/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c create mode 100644 final/utils/lit/lit/ExampleTests/Clang/lit.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/data.txt create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll create mode 100644 final/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg create mode 100644 final/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg create mode 100644 final/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg create mode 100644 final/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg create mode 100644 final/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll create mode 100644 final/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll create mode 100644 final/utils/lit/lit/ExampleTests/fail.c create mode 100644 final/utils/lit/lit/ExampleTests/lit.cfg create mode 100644 final/utils/lit/lit/ExampleTests/pass.c create mode 100644 final/utils/lit/lit/ExampleTests/required-and-missing.c create mode 100644 final/utils/lit/lit/ExampleTests/required-and-present.c create mode 100644 final/utils/lit/lit/ExampleTests/xfail.c create mode 100644 final/utils/lit/lit/ExampleTests/xpass.c create mode 100644 final/utils/lit/lit/LitConfig.py create mode 100644 final/utils/lit/lit/LitFormats.py create mode 100644 final/utils/lit/lit/LitTestCase.py create mode 100644 final/utils/lit/lit/ProgressBar.py create mode 100644 final/utils/lit/lit/ShCommands.py create mode 100644 final/utils/lit/lit/ShUtil.py create mode 100644 final/utils/lit/lit/TclUtil.py create mode 100644 final/utils/lit/lit/Test.py create mode 100644 final/utils/lit/lit/TestFormats.py create mode 100644 final/utils/lit/lit/TestRunner.py create mode 100644 final/utils/lit/lit/TestingConfig.py create mode 100644 final/utils/lit/lit/Util.py create mode 100644 final/utils/lit/lit/__init__.py create mode 100755 final/utils/lit/lit/main.py create mode 100644 final/utils/lit/setup.py create mode 100644 final/utils/llvm-lit/CMakeLists.txt create mode 100644 final/utils/llvm-lit/Makefile create mode 100755 final/utils/llvm-lit/llvm-lit.in create mode 100755 final/utils/llvm-native-gcc create mode 100755 final/utils/llvm-native-gxx create mode 100644 final/utils/llvm.grm create mode 100755 final/utils/llvmbuild create mode 100755 final/utils/llvmdo create mode 100755 final/utils/llvmgrep create mode 100755 final/utils/makellvm create mode 100644 final/utils/not/CMakeLists.txt create mode 100644 final/utils/not/Makefile create mode 100644 final/utils/not/not.cpp create mode 100644 final/utils/parseNLT.pl create mode 100644 final/utils/plotNLT.pl create mode 100755 final/utils/profile.pl create mode 100755 final/utils/release/test-release.sh create mode 100755 final/utils/test_debuginfo.pl create mode 100644 final/utils/unittest/CMakeLists.txt create mode 100644 final/utils/unittest/Makefile create mode 100644 final/utils/unittest/UnitTestMain/Makefile create mode 100644 final/utils/unittest/UnitTestMain/TestMain.cpp create mode 100644 final/utils/unittest/googletest/LICENSE.TXT create mode 100644 final/utils/unittest/googletest/Makefile create mode 100644 final/utils/unittest/googletest/README.LLVM create mode 100644 final/utils/unittest/googletest/gtest-death-test.cc create mode 100644 final/utils/unittest/googletest/gtest-filepath.cc create mode 100644 final/utils/unittest/googletest/gtest-port.cc create mode 100644 final/utils/unittest/googletest/gtest-test-part.cc create mode 100644 final/utils/unittest/googletest/gtest-typed-test.cc create mode 100644 final/utils/unittest/googletest/gtest.cc create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-death-test.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-message.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-param-test.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-spi.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-test-part.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest-typed-test.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest_pred_impl.h create mode 100644 final/utils/unittest/googletest/include/gtest/gtest_prod.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-internal.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-port.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-string.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h create mode 100644 final/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h create mode 100644 final/utils/valgrind/i386-pc-linux-gnu.supp create mode 100644 final/utils/valgrind/x86_64-pc-linux-gnu.supp create mode 100644 final/utils/vim/README create mode 100644 final/utils/vim/llvm.vim create mode 100644 final/utils/vim/tablegen.vim create mode 100644 final/utils/vim/vimrc create mode 100755 final/utils/webNLT.pl create mode 100644 final/website/index.html diff --git a/final/.gitignore b/final/.gitignore new file mode 100644 index 00000000000..2e2713a48ae --- /dev/null +++ b/final/.gitignore @@ -0,0 +1,37 @@ +#==============================================================================# +# This file specifies intentionally untracked files that git should ignore. +# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html +# +# This file is intentionally different from the output of `git svn show-ignore`, +# as most of those are useless. +#==============================================================================# + +#==============================================================================# +# File extensions to be ignored anywhere in the tree. +#==============================================================================# +# Temp files created by most text editors. +*~ +# Merge files created by git. +*.orig +# Byte compiled python modules. +*.pyc + +#==============================================================================# +# Explicit files to ignore (only matches one). +#==============================================================================# +.gitusers +cscope.files +cscope.out +autoconf/aclocal.m4 +autoconf/autom4te.cache + +#==============================================================================# +# Directories to ignore (do not add trailing '/'s, they skip symlinks). +#==============================================================================# +# External projects that are tracked independently. +projects/* +!projects/sample +!projects/CMakeLists.txt +!projects/Makefile +# Clang, which is tracked independently. +tools/clang diff --git a/final/CMakeLists.txt b/final/CMakeLists.txt new file mode 100644 index 00000000000..2d201df2f06 --- /dev/null +++ b/final/CMakeLists.txt @@ -0,0 +1,296 @@ +# See docs/CMake.html for instructions about how to build LLVM with CMake. + +project(LLVM) +cmake_minimum_required(VERSION 2.8) + +# Add path for custom modules +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + ) + +set(PACKAGE_VERSION "2.9") + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +include(VersionFromVCS) + +option(LLVM_APPEND_VC_REV + "Append the version control system revision id to LLVM version" OFF) + +if( LLVM_APPEND_VC_REV ) + add_version_info_from_vcs(PACKAGE_VERSION) +endif() + +set(PACKAGE_NAME llvm) +set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") +set(PACKAGE_BUGREPORT "llvmbugs@cs.uiuc.edu") + +if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE ) + message(FATAL_ERROR "In-source builds are not allowed. +CMake would overwrite the makefiles distributed with LLVM. +Please create a directory and run cmake from there, passing the path +to this source directory as the last argument. +This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. +Please delete them.") +endif() + +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + +set(LLVM_MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(LLVM_MAIN_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/include) +set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(LLVM_TOOLS_BINARY_DIR ${LLVM_BINARY_DIR}/bin) +set(LLVM_EXAMPLES_BINARY_DIR ${LLVM_BINARY_DIR}/examples) +set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) + +if( NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) + file(GLOB_RECURSE + tablegenned_files_on_include_dir + "${LLVM_MAIN_SRC_DIR}/include/llvm/*.gen") + file(GLOB_RECURSE + tablegenned_files_on_lib_dir + "${LLVM_MAIN_SRC_DIR}/lib/Target/*.inc") + if( tablegenned_files_on_include_dir OR tablegenned_files_on_lib_dir) + message(FATAL_ERROR "Apparently there is a previous in-source build, +probably as the result of running `configure' and `make' on +${LLVM_MAIN_SRC_DIR}. +This may cause problems. The suspicious files are: +${tablegenned_files_on_lib_dir} +${tablegenned_files_on_include_dir} +Please clean the source directory.") + endif() +endif() + +set(LLVM_ALL_TARGETS + Alpha + ARM + Blackfin + CBackend + CellSPU + CppBackend + Mips + MBlaze + MSP430 + PowerPC + PTX + Sparc + SystemZ + X86 + XCore + ) + +if( MSVC ) + set(LLVM_TARGETS_TO_BUILD X86 + CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") +else( MSVC ) + set(LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} + CACHE STRING "Semicolon-separated list of targets to build, or \"all\".") +endif( MSVC ) + +option(LLVM_ENABLE_CBE_PRINTF_A "Set to ON if CBE is enabled for printf %a output" ON) +if(LLVM_ENABLE_CBE_PRINTF_A) + set(ENABLE_CBE_PRINTF_A 1) +endif() + +option(LLVM_ENABLE_TIMESTAMPS "Enable embedding timestamp information in build" ON) +if(LLVM_ENABLE_TIMESTAMPS) + set(ENABLE_TIMESTAMPS 1) +endif() + +option(LLVM_ENABLE_FFI "Use libffi to call external functions from the interpreter" OFF) +set(FFI_LIBRARY_DIR "" CACHE PATH "Additional directory, where CMake should search for libffi.so") +set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should search for ffi.h or ffi/ffi.h") + +set(LLVM_TARGET_ARCH "host" + CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.") + +option(LLVM_ENABLE_THREADS "Use threads if available." ON) + +if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) + set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) +endif() + +set(LLVM_ENUM_TARGETS "") +foreach(c ${LLVM_TARGETS_TO_BUILD}) + list(FIND LLVM_ALL_TARGETS ${c} idx) + if( idx LESS 0 ) + message(FATAL_ERROR "The target `${c}' does not exist. + It should be one of\n${LLVM_ALL_TARGETS}") + else() + set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${c})\n") + endif() +endforeach(c) + +# Produce llvm/Config/Targets.def +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Targets.def.in + ${LLVM_BINARY_DIR}/include/llvm/Config/Targets.def + ) + +set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm) + +include(AddLLVMDefinitions) + +option(LLVM_ENABLE_PIC "Build Position-Independent Code" ON) + +# MSVC has a gazillion warnings with this. +if( MSVC ) + option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." OFF) +else( MSVC ) + option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON) +endif() + +option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) +option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) + +if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF) +else() + option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON) +endif() + +# All options refered to from HandleLLVMOptions have to be specified +# BEFORE this include, otherwise options will not be correctly set on +# first cmake run +include(config-ix) +include(HandleLLVMOptions) + +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/config.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Config/config.h) + +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/llvm-config.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Config/llvm-config.h) + +configure_file( + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/DataTypes.h.cmake + ${LLVM_BINARY_DIR}/include/llvm/Support/DataTypes.h) + +set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR} ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +include_directories( ${LLVM_BINARY_DIR}/include ${LLVM_MAIN_INCLUDE_DIR}) + +if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-include llvm/Support/Solaris.h") +endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS ) + +include(AddLLVM) +include(TableGen) + +if( MINGW ) + get_system_libs(LLVM_SYSTEM_LIBS_LIST) + foreach(l ${LLVM_SYSTEM_LIBS_LIST}) + set(LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS} -l${l}") + endforeach() + set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES}${LLVM_SYSTEM_LIBS}") + set(CMAKE_C_STANDARD_LIBRARIES "${CMAKE_C_STANDARD_LIBRARIES}${LLVM_SYSTEM_LIBS}") +endif() + +if( MINGW ) + # People report that -O3 is unreliable on MinGW. The traditional + # build also uses -O2 for that reason: + llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O3" "-O2") +endif() + +# Put this before tblgen. Else we have a circular dependence. +add_subdirectory(lib/Support) + +set(LLVM_TABLEGEN "tblgen" CACHE + STRING "Native TableGen executable. Saves building one when cross-compiling.") +# Effective tblgen executable to be used: +set(LLVM_TABLEGEN_EXE ${LLVM_TABLEGEN}) + +add_subdirectory(utils/TableGen) + +if( CMAKE_CROSSCOMPILING ) + # This adds a dependency on target `tblgen', so must go after utils/TableGen + include( CrossCompileLLVM ) +endif( CMAKE_CROSSCOMPILING ) + +add_subdirectory(include/llvm) + +add_subdirectory(lib) + +add_subdirectory(utils/FileCheck) +add_subdirectory(utils/FileUpdate) +add_subdirectory(utils/count) +add_subdirectory(utils/not) +add_subdirectory(utils/llvm-lit) + +add_subdirectory(projects) + +option(LLVM_BUILD_TOOLS + "Build the LLVM tools. If OFF, just generate build targets." ON) +option(LLVM_INCLUDE_TOOLS "Generate build targets for the LLVM tools." ON) +if( LLVM_INCLUDE_TOOLS ) + add_subdirectory(tools) +endif() + +option(LLVM_BUILD_EXAMPLES + "Build the LLVM example programs. If OFF, just generate build targets." OFF) +option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) +if( LLVM_INCLUDE_EXAMPLES ) + add_subdirectory(examples) +endif() + +option(LLVM_BUILD_TESTS + "Build LLVM unit tests. If OFF, just generate build targes." OFF) +if( LLVM_INCLUDE_TESTS ) + add_subdirectory(test) + add_subdirectory(utils/unittest) + add_subdirectory(unittests) + if (MSVC) + # This utility is used to prevent chrashing tests from calling Dr. Watson on + # Windows. + add_subdirectory(utils/KillTheDoctor) + endif() +endif() + +add_subdirectory(cmake/modules) + +install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.td" + PATTERN "*.inc" + PATTERN "LICENSE.TXT" + PATTERN ".svn" EXCLUDE + ) + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.def" + PATTERN "*.h" + PATTERN "*.gen" + PATTERN "*.inc" + # Exclude include/llvm/CMakeFiles/intrinsics_gen.dir, matched by "*.def" + PATTERN "CMakeFiles" EXCLUDE + PATTERN ".svn" EXCLUDE + ) + +# TODO: make and install documentation. + +set(CPACK_PACKAGE_VENDOR "LLVM") +set(CPACK_PACKAGE_VERSION_MAJOR 2) +set(CPACK_PACKAGE_VERSION_MINOR 9) +add_version_info_from_vcs(CPACK_PACKAGE_VERSION_PATCH) +include(CPack) + +# Workaround for MSVS10 to avoid the Dialog Hell +# FIXME: This could be removed with future version of CMake. +if(MSVC_VERSION EQUAL 1600) + set(LLVM_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/LLVM.sln") + if( EXISTS "${LLVM_SLN_FILENAME}" ) + file(APPEND "${LLVM_SLN_FILENAME}" "\n# This should be regenerated!\n") + endif() +endif() diff --git a/final/CREDITS.TXT b/final/CREDITS.TXT new file mode 100644 index 00000000000..ab01dde338a --- /dev/null +++ b/final/CREDITS.TXT @@ -0,0 +1,362 @@ +This file is a partial list of people who have contributed to the LLVM +project. If you have contributed a patch or made some other contribution to +LLVM, please submit a patch to this file to add yourself, and it will be +done! + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), and snail-mail address +(S). + + +N: Vikram Adve +E: vadve@cs.uiuc.edu +W: http://www.cs.uiuc.edu/~vadve/ +D: The Sparc64 backend, provider of much wisdom, and motivator for LLVM + +N: Owen Anderson +E: resistor@mac.com +D: LCSSA pass and related LoopUnswitch work +D: GVNPRE pass, TargetData refactoring, random improvements + +N: Henrik Bach +D: MingW Win32 API portability layer + +N: Nate Begeman +E: natebegeman@mac.com +D: PowerPC backend developer +D: Target-independent code generator and analysis improvements + +N: Daniel Berlin +E: dberlin@dberlin.org +D: ET-Forest implementation. +D: Sparse bitmap + +N: Neil Booth +E: neil@daikokuya.co.uk +D: APFloat implementation. + +N: Misha Brukman +E: brukman+llvm@uiuc.edu +W: http://misha.brukman.net +D: Portions of X86 and Sparc JIT compilers, PowerPC backend +D: Incremental bitcode loader + +N: Cameron Buschardt +E: buschard@uiuc.edu +D: The `mem2reg' pass - promotes values stored in memory to registers + +N: Chandler Carruth +E: chandlerc@gmail.com +D: LinkTimeOptimizer for Linux, via binutils integration, and C API + +N: Casey Carter +E: ccarter@uiuc.edu +D: Fixes to the Reassociation pass, various improvement patches + +N: Evan Cheng +E: evan.cheng@apple.com +D: ARM and X86 backends +D: Instruction scheduler improvements +D: Register allocator improvements +D: Loop optimizer improvements +D: Target-independent code generator improvements + +N: Dan Villiom Podlaski Christiansen +E: danchr@gmail.com +E: danchr@cs.au.dk +W: http://villiom.dk +D: LLVM Makefile improvements +D: Clang diagnostic & driver tweaks +S: Aarhus, Denmark + +N: Jeff Cohen +E: jeffc@jolt-lang.org +W: http://jolt-lang.org +D: Native Win32 API portability layer + +N: John T. Criswell +E: criswell@uiuc.edu +D: Original Autoconf support, documentation improvements, bug fixes + +N: Stefanus Du Toit +E: stefanus.dutoit@rapidmind.com +D: Bug fixes and minor improvements + +N: Rafael Avila de Espindola +E: rafael.espindola@gmail.com +D: The ARM backend + +N: Alkis Evlogimenos +E: alkis@evlogimenos.com +D: Linear scan register allocator, many codegen improvements, Java frontend + +N: Ryan Flynn +E: pizza@parseerror.com +D: Miscellaneous bug fixes + +N: Brian Gaeke +E: gaeke@uiuc.edu +W: http://www.students.uiuc.edu/~gaeke/ +D: Portions of X86 static and JIT compilers; initial SparcV8 backend +D: Dynamic trace optimizer +D: FreeBSD/X86 compatibility fixes, the llvm-nm tool + +N: Nicolas Geoffray +E: nicolas.geoffray@lip6.fr +W: http://www-src.lip6.fr/homepages/Nicolas.Geoffray/ +D: PPC backend fixes for Linux + +N: Louis Gerbarg +D: Portions of the PowerPC backend + +N: Saem Ghani +E: saemghani@gmail.com +D: Callgraph class cleanups + +N: Mikhail Glushenkov +E: foldr@codedgers.com +D: Author of llvmc2 + +N: Dan Gohman +E: gohman@apple.com +D: Miscellaneous bug fixes + +N: David Goodwin +E: david@goodwinz.net +D: Thumb-2 code generator + +N: David Greene +E: greened@obbligato.org +D: Miscellaneous bug fixes +D: Register allocation refactoring + +N: Gabor Greif +E: ggreif@gmail.com +D: Improvements for space efficiency + +N: James Grosbach +E: grosbach@apple.com +D: SjLj exception handling support +D: General fixes and improvements for the ARM back-end + +N: Lang Hames +E: lhames@gmail.com +D: PBQP-based register allocator + +N: Gordon Henriksen +E: gordonhenriksen@mac.com +D: Pluggable GC support +D: C interface +D: Ocaml bindings + +N: Raul Fernandes Herbster +E: raul@dsc.ufcg.edu.br +D: JIT support for ARM + +N: Paolo Invernizzi +E: arathorn@fastwebnet.it +D: Visual C++ compatibility fixes + +N: Patrick Jenkins +E: patjenk@wam.umd.edu +D: Nightly Tester + +N: Dale Johannesen +E: dalej@apple.com +D: ARM constant islands improvements +D: Tail merging improvements +D: Rewrite X87 back end +D: Use APFloat for floating point constants widely throughout compiler +D: Implement X87 long double + +N: Brad Jones +E: kungfoomaster@nondot.org +D: Support for packed types + +N: Rod Kay +E: rkay@auroraux.org +D: Author of LLVM Ada bindings + +N: Eric Kidd +W: http://randomhacks.net/ +D: llvm-config script + +N: Anton Korobeynikov +E: asl@math.spbu.ru +D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv. +D: x86/linux PIC codegen, aliases, regparm/visibility attributes +D: Switch lowering refactoring + +N: Sumant Kowshik +E: kowshik@uiuc.edu +D: Author of the original C backend + +N: Benjamin Kramer +E: benny.kra@gmail.com +D: Miscellaneous bug fixes + +N: Christopher Lamb +E: christopher.lamb@gmail.com +D: aligned load/store support, parts of noalias and restrict support +D: vreg subreg infrastructure, X86 codegen improvements based on subregs +D: address spaces + +N: Jim Laskey +E: jlaskey@apple.com +D: Improvements to the PPC backend, instruction scheduling +D: Debug and Dwarf implementation +D: Auto upgrade mangler +D: llvm-gcc4 svn wrangler + +N: Chris Lattner +E: sabre@nondot.org +W: http://nondot.org/~sabre/ +D: Primary architect of LLVM + +N: Tanya Lattner (Tanya Brethour) +E: tonic@nondot.org +W: http://nondot.org/~tonic/ +D: The initial llvm-ar tool, converted regression testsuite to dejagnu +D: Modulo scheduling in the SparcV9 backend +D: Release manager (1.7+) + +N: Andrew Lenharth +E: alenhar2@cs.uiuc.edu +W: http://www.lenharth.org/~andrewl/ +D: Alpha backend +D: Sampling based profiling + +N: Nick Lewycky +E: nicholas@mxc.ca +D: PredicateSimplifier pass + +N: Bruno Cardoso Lopes +E: bruno.cardoso@gmail.com +W: http://www.brunocardoso.org +D: The Mips backend + +N: Duraid Madina +E: duraid@octopus.com.au +W: http://kinoko.c.u-tokyo.ac.jp/~duraid/ +D: IA64 backend, BigBlock register allocator + +N: Michael McCracken +E: michael.mccracken@gmail.com +D: Line number support for llvmgcc + +N: Vladimir Merzliakov +E: wanderer@rsu.ru +D: Test suite fixes for FreeBSD + +N: Scott Michel +E: scottm@aero.org +D: Added STI Cell SPU backend. + +N: Takumi Nakamura +E: geek4civic@gmail.com +E: chapuni@hf.rim.or.jp +D: Cygwin and MinGW support. +S: Yokohama, Japan + +N: Edward O'Callaghan +E: eocallaghan@auroraux.org +W: http://www.auroraux.org +D: Add Clang support with various other improvements to utils/NewNightlyTest.pl +D: Fix and maintain Solaris & AuroraUX support for llvm, various build warnings +D: and error clean ups. + +N: Morten Ofstad +E: morten@hue.no +D: Visual C++ compatibility fixes + +N: Jakob Stoklund Olesen +E: stoklund@2pi.dk +D: Machine code verifier +D: Blackfin backend + +N: Richard Osborne +E: richard@xmos.com +D: XCore backend + +N: Devang Patel +E: dpatel@apple.com +D: LTO tool, PassManager rewrite, Loop Pass Manager, Loop Rotate +D: GCC PCH Integration (llvm-gcc), llvm-gcc improvements +D: Optimizer improvements, Loop Index Split + +N: Sandeep Patel +E: deeppatel1987@gmail.com +D: ARM calling conventions rewrite, hard float support + +N: Wesley Peck +E: peckw@wesleypeck.com +W: http://wesleypeck.com/ +D: MicroBlaze backend + +N: Vladimir Prus +W: http://vladimir_prus.blogspot.com +E: ghost@cs.msu.su +D: Made inst_iterator behave like a proper iterator, LowerConstantExprs pass + +N: Roman Samoilov +E: roman@codedgers.com +D: MSIL backend + +N: Duncan Sands +E: baldrick@free.fr +D: Ada support in llvm-gcc +D: Dragonegg plugin +D: Exception handling improvements +D: Type legalizer rewrite + +N: Ruchira Sasanka +E: sasanka@uiuc.edu +D: Graph coloring register allocator for the Sparc64 backend + +N: Arnold Schwaighofer +E: arnold.schwaighofer@gmail.com +D: Tail call optimization for the x86 backend + +N: Shantonu Sen +E: ssen@apple.com +D: Miscellaneous bug fixes + +N: Anand Shukla +E: ashukla@cs.uiuc.edu +D: The `paths' pass + +N: Michael J. Spencer +E: bigcheesegs@gmail.com +D: Shepherding Windows COFF support into MC. +D: Lots of Windows stuff. + +N: Reid Spencer +E: rspencer@reidspencer.com +W: http://reidspencer.com/ +D: Lots of stuff, see: http://wiki.llvm.org/index.php/User:Reid + +N: Edwin Torok +E: edwintorok@gmail.com +D: Miscellaneous bug fixes + +N: Adam Treat +E: manyoso@yahoo.com +D: C++ bugs filed, and C++ front-end bug fixes. + +N: Lauro Ramos Venancio +E: lauro.venancio@indt.org.br +D: ARM backend improvements +D: Thread Local Storage implementation + +N: Xerxes Ranby +E: xerxes@zafena.se +D: Cmake dependency chain and various bug fixes + +N: Bill Wendling +E: wendling@apple.com +D: Bunches of stuff + +N: Bob Wilson +E: bob.wilson@acm.org +D: Advanced SIMD (NEON) support in the ARM backend diff --git a/final/LICENSE.TXT b/final/LICENSE.TXT new file mode 100644 index 00000000000..b8d2c742096 --- /dev/null +++ b/final/LICENSE.TXT @@ -0,0 +1,69 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + +The following pieces of software have additional or alternate copyrights, +licenses, and/or restrictions: + +Program Directory +------- --------- +Autoconf llvm/autoconf + llvm/projects/ModuleMaker/autoconf + llvm/projects/sample/autoconf +CellSPU backend llvm/lib/Target/CellSPU/README.txt +Google Test llvm/utils/unittest/googletest +OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} diff --git a/final/Makefile b/final/Makefile new file mode 100644 index 00000000000..dbb759dd5fc --- /dev/null +++ b/final/Makefile @@ -0,0 +1,250 @@ +#===- ./Makefile -------------------------------------------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +LEVEL := . + +# Top-Level LLVM Build Stages: +# 1. Build lib/Support, which is used by utils (tblgen). +# 2. Build utils, which is used by VMCore. +# 3. Build VMCore, which builds the Intrinsics.inc file used by libs. +# 4. Build libs, which are needed by llvm-config. +# 5. Build llvm-config, which determines inter-lib dependencies for tools. +# 6. Build tools, runtime, docs. +# +# When cross-compiling, there are some things (tablegen) that need to +# be build for the build system first. + +# If "RC_ProjectName" exists in the environment, and its value is +# "llvmCore", then this is an "Apple-style" build; search for +# "Apple-style" in the comments for more info. Anything else is a +# normal build. +ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style"). + +ifeq ($(BUILD_DIRS_ONLY),1) + DIRS := lib/Support utils + OPTIONAL_DIRS := +else + DIRS := lib/Support utils lib/VMCore lib tools/llvm-shlib \ + tools/llvm-config tools runtime docs unittests + OPTIONAL_DIRS := projects bindings +endif + +ifeq ($(BUILD_EXAMPLES),1) + OPTIONAL_DIRS += examples +endif + +EXTRA_DIST := test unittests llvm.spec include win32 Xcode + +include $(LEVEL)/Makefile.config + +ifneq ($(ENABLE_SHARED),1) + DIRS := $(filter-out tools/llvm-shlib, $(DIRS)) +endif + +ifneq ($(ENABLE_DOCS),1) + DIRS := $(filter-out docs, $(DIRS)) +endif + +ifeq ($(MAKECMDGOALS),libs-only) + DIRS := $(filter-out tools runtime docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-libs) + DIRS := $(filter-out tools runtime docs, $(DIRS)) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +ifeq ($(MAKECMDGOALS),tools-only) + DIRS := $(filter-out runtime docs, $(DIRS)) + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),install-clang) + DIRS := tools/clang/tools/driver tools/clang/lib/Headers \ + tools/clang/runtime tools/clang/docs \ + tools/lto + OPTIONAL_DIRS := + NO_INSTALL = 1 +endif + +ifeq ($(MAKECMDGOALS),install-clang-c) + DIRS := tools/clang/tools/driver tools/clang/lib/Headers \ + tools/clang/tools/libclang tools/clang/tools/c-index-test \ + tools/clang/include/clang-c + OPTIONAL_DIRS := + NO_INSTALL = 1 +endif + +ifeq ($(MAKECMDGOALS),clang-only) + DIRS := $(filter-out tools runtime docs unittests, $(DIRS)) \ + tools/clang tools/lto + OPTIONAL_DIRS := +endif + +ifeq ($(MAKECMDGOALS),unittests) + DIRS := $(filter-out tools runtime docs, $(DIRS)) utils unittests + OPTIONAL_DIRS := +endif + +# Use NO_INSTALL define of the Makefile of each directory for deciding +# if the directory is installed or not +ifeq ($(MAKECMDGOALS),install) + OPTIONAL_DIRS := $(filter bindings, $(OPTIONAL_DIRS)) +endif + +# Don't build unittests when ONLY_TOOLS is set. +ifneq ($(ONLY_TOOLS),) + DIRS := $(filter-out unittests, $(DIRS)) +endif + +# If we're cross-compiling, build the build-hosted tools first +ifeq ($(LLVM_CROSS_COMPILING),1) +all:: cross-compile-build-tools + +clean:: + $(Verb) rm -rf BuildTools + +cross-compile-build-tools: + $(Verb) if [ ! -f BuildTools/Makefile ]; then \ + $(MKDIR) BuildTools; \ + cd BuildTools ; \ + unset CFLAGS ; \ + unset CXXFLAGS ; \ + $(PROJ_SRC_DIR)/configure --build=$(BUILD_TRIPLE) \ + --host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE); \ + cd .. ; \ + fi; \ + (unset SDKROOT; \ + $(MAKE) -C BuildTools \ + BUILD_DIRS_ONLY=1 \ + UNIVERSAL= \ + ENABLE_OPTIMIZED=$(ENABLE_OPTIMIZED) \ + ENABLE_PROFILING=$(ENABLE_PROFILING) \ + ENABLE_COVERAGE=$(ENABLE_COVERAGE) \ + DISABLE_ASSERTIONS=$(DISABLE_ASSERTIONS) \ + ENABLE_EXPENSIVE_CHECKS=$(ENABLE_EXPENSIVE_CHECKS) \ + CFLAGS= \ + CXXFLAGS= \ + ) || exit 1; +endif + +# Include the main makefile machinery. +include $(LLVM_SRC_ROOT)/Makefile.rules + +# Specify options to pass to configure script when we're +# running the dist-check target +DIST_CHECK_CONFIG_OPTIONS = --with-llvmgccdir=$(LLVMGCCDIR) + +.PHONY: debug-opt-prof +debug-opt-prof: + $(Echo) Building Debug Version + $(Verb) $(MAKE) + $(Echo) + $(Echo) Building Optimized Version + $(Echo) + $(Verb) $(MAKE) ENABLE_OPTIMIZED=1 + $(Echo) + $(Echo) Building Profiling Version + $(Echo) + $(Verb) $(MAKE) ENABLE_PROFILING=1 + +dist-hook:: + $(Echo) Eliminating files constructed by configure + $(Verb) $(RM) -f \ + $(TopDistDir)/include/llvm/Config/config.h \ + $(TopDistDir)/include/llvm/Support/DataTypes.h + +clang-only: all +tools-only: all +libs-only: all +install-clang: install +install-clang-c: install +install-libs: install + +#------------------------------------------------------------------------ +# Make sure the generated headers are up-to-date. This must be kept in +# sync with the AC_CONFIG_HEADER invocations in autoconf/configure.ac +#------------------------------------------------------------------------ +FilesToConfig := \ + include/llvm/Config/config.h \ + include/llvm/Config/Targets.def \ + include/llvm/Config/AsmPrinters.def \ + include/llvm/Config/AsmParsers.def \ + include/llvm/Config/Disassemblers.def \ + include/llvm/Support/DataTypes.h \ + tools/llvmc/src/Base.td +FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig)) + +all-local:: $(FilesToConfigPATH) +$(FilesToConfigPATH) : $(LLVM_OBJ_ROOT)/% : $(LLVM_SRC_ROOT)/%.in + $(Echo) Regenerating $* + $(Verb) cd $(LLVM_OBJ_ROOT) && $(ConfigStatusScript) $* +.PRECIOUS: $(FilesToConfigPATH) + +# NOTE: This needs to remain as the last target definition in this file so +# that it gets executed last. +ifneq ($(BUILD_DIRS_ONLY),1) +all:: + $(Echo) '*****' Completed $(BuildMode) Build +ifneq ($(ENABLE_OPTIMIZED),1) + $(Echo) '*****' Note: Debug build can be 10 times slower than an + $(Echo) '*****' optimized build. Use 'make ENABLE_OPTIMIZED=1' to + $(Echo) '*****' make an optimized build. Alternatively you can + $(Echo) '*****' configure with --enable-optimized. +endif +endif + +check-llvm2cpp: + $(Verb)$(MAKE) check TESTSUITE=Feature RUNLLVM2CPP=1 + +srpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bs $(LLVM_OBJ_ROOT)/llvm.spec + +rpm: $(LLVM_OBJ_ROOT)/llvm.spec + rpmbuild -bb --target $(TARGET_TRIPLE) $(LLVM_OBJ_ROOT)/llvm.spec + +show-footprint: + $(Verb) du -sk $(LibDir) + $(Verb) du -sk $(ToolDir) + $(Verb) du -sk $(ExmplDir) + $(Verb) du -sk $(ObjDir) + +build-for-llvm-top: + $(Verb) if test ! -f ./config.status ; then \ + ./configure --prefix="$(LLVM_TOP)/install" \ + --with-llvm-gcc="$(LLVM_TOP)/llvm-gcc" ; \ + fi + $(Verb) $(MAKE) tools-only + +SVN = svn +SVN-UPDATE-OPTIONS = +AWK = awk +SUB-SVN-DIRS = $(AWK) '/\?\ \ \ \ \ \ / {print $$2}' \ + | LC_ALL=C xargs $(SVN) info 2>/dev/null \ + | $(AWK) '/Path:\ / {print $$2}' + +update: + $(SVN) $(SVN-UPDATE-OPTIONS) update $(LLVM_SRC_ROOT) + @ $(SVN) status $(LLVM_SRC_ROOT) | $(SUB-SVN-DIRS) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update + +happiness: update all check-all + +.PHONY: srpm rpm update happiness + +# declare all targets at this level to be serial: + +.NOTPARALLEL: + +else # Building "Apple-style." +# In an Apple-style build, once configuration is done, lines marked +# "Apple-style" are removed with sed! Please don't remove these! +# Look for the string "Apple-style" in utils/buildit/build_llvm. +include $(shell find . -name GNUmakefile) # Building "Apple-style." +endif # Building "Apple-style." diff --git a/final/Makefile.common b/final/Makefile.common new file mode 100644 index 00000000000..e1f52036f6f --- /dev/null +++ b/final/Makefile.common @@ -0,0 +1,70 @@ +#===-- Makefile.common - Common make rules for LLVM --------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. This file defines common +# rules to do things like compile a .cpp file or generate dependency info. +# These are platform dependent, so this is the file used to specify these +# system dependent operations. +# +# The following functionality can be set by setting incoming variables. +# The variable $(LEVEL) *must* be set: +# +# 1. LEVEL - The level of the current subdirectory from the top of the +# source directory. This level should be expressed as a path, for +# example, ../.. for two levels deep. +# +# 2. DIRS - A list of subdirectories to be built. Fake targets are set up +# so that each of the targets "all", "install", and "clean" each build +# the subdirectories before the local target. DIRS are guaranteed to be +# built in order. +# +# 3. PARALLEL_DIRS - A list of subdirectories to be built, but that may be +# built in any order. All DIRS are built in order before PARALLEL_DIRS are +# built, which are then built in any order. +# +# 4. Source - If specified, this sets the source code filenames. If this +# is not set, it defaults to be all of the .cpp, .c, .y, and .l files +# in the current directory. Also, if you want to build files in addition +# to the local files, you can use the ExtraSource variable +# +# 5. SourceDir - If specified, this specifies a directory that the source files +# are in, if they are not in the current directory. This should include a +# trailing / character. +# +# 6. LLVM_SRC_ROOT - If specified, points to the top of the LLVM source tree. +# +# 8. PROJ_SRC_DIR - The directory which contains the current set of Makefiles +# and usually the source code too (unless SourceDir is set). +# +# 9. PROJ_SRC_ROOT - The root directory of the source code being compiled. +# +# 10. PROJ_OBJ_DIR - The directory where object code should be placed. +# +# 11. PROJ_OBJ_ROOT - The root directory for where object code should be +# placed. +# +# For building, +# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT +# +#===-----------------------------------------------------------------------==== + +# +# Configuration file to set paths specific to local installation of LLVM +# +ifndef LLVM_OBJ_ROOT +include $(LEVEL)/Makefile.config +else +include $(LLVM_OBJ_ROOT)/Makefile.config +endif + +# +# Include all of the build rules used for making LLVM +# +include $(LLVM_SRC_ROOT)/Makefile.rules + diff --git a/final/Makefile.config.in b/final/Makefile.config.in new file mode 100644 index 00000000000..5c737580632 --- /dev/null +++ b/final/Makefile.config.in @@ -0,0 +1,359 @@ +#===-- Makefile.config - Local configuration for LLVM ------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by Makefile.common. It defines paths and other +# values specific to a particular installation of LLVM. +# +#===------------------------------------------------------------------------===# + +# Define LLVM specific info and directories based on the autoconf variables +LLVMPackageName := @PACKAGE_NAME@ +LLVMVersion := @PACKAGE_VERSION@ +LLVM_CONFIGTIME := @LLVM_CONFIGTIME@ + +########################################################################### +# Directory Configuration +# This section of the Makefile determines what is where. To be +# specific, there are several locations that need to be defined: +# +# o LLVM_SRC_ROOT : The root directory of the LLVM source code. +# o LLVM_OBJ_ROOT : The root directory containing the built LLVM code. +# +# o PROJ_SRC_DIR : The directory containing the code to build. +# o PROJ_SRC_ROOT : The root directory of the code to build. +# +# o PROJ_OBJ_DIR : The directory in which compiled code will be placed. +# o PROJ_OBJ_ROOT : The root directory in which compiled code is placed. +# +########################################################################### + +PWD := @BINPWD@ +# Set the project name to LLVM if its not defined +ifndef PROJECT_NAME +PROJECT_NAME := $(LLVMPackageName) +endif + +# The macro below is expanded when 'realpath' is not built-in. +# Built-in 'realpath' is available on GNU Make 3.81. +realpath = $(shell cd $(1); $(PWD)) + +PROJ_OBJ_DIR := $(call realpath, .) +PROJ_OBJ_ROOT := $(call realpath, $(PROJ_OBJ_DIR)/$(LEVEL)) + +ifeq ($(PROJECT_NAME),llvm) +LLVM_SRC_ROOT := $(call realpath, @abs_top_srcdir@) +LLVM_OBJ_ROOT := $(call realpath, @abs_top_builddir@) +PROJ_SRC_ROOT := $(LLVM_SRC_ROOT) +PROJ_SRC_DIR := $(call realpath, $(LLVM_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))) +prefix := @prefix@ +PROJ_prefix := $(prefix) +PROJ_VERSION := $(LLVMVersion) +else +ifndef PROJ_SRC_ROOT +$(error Projects must define PROJ_SRC_ROOT) +endif +ifndef PROJ_OBJ_ROOT +$(error Projects must define PROJ_OBJ_ROOT) +endif +ifndef PROJ_INSTALL_ROOT +$(error Projects must define PROJ_INSTALL_ROOT) +endif +ifndef LLVM_SRC_ROOT +$(error Projects must define LLVM_SRC_ROOT) +endif +ifndef LLVM_OBJ_ROOT +$(error Projects must define LLVM_OBJ_ROOT) +endif +PROJ_SRC_DIR := $(call realpath, $(PROJ_SRC_ROOT)/$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))) +prefix := $(PROJ_INSTALL_ROOT) +PROJ_prefix := $(prefix) +ifndef PROJ_VERSION +PROJ_VERSION := 1.0 +endif +endif + +LLVMMAKE := $(LLVM_SRC_ROOT)/make + +PROJ_bindir := $(PROJ_prefix)/bin +PROJ_libdir := $(PROJ_prefix)/lib +PROJ_datadir := $(PROJ_prefix)/share +PROJ_docsdir := $(PROJ_prefix)/docs/llvm +PROJ_etcdir := $(PROJ_prefix)/etc/llvm +PROJ_includedir := $(PROJ_prefix)/include +PROJ_infodir := $(PROJ_prefix)/info +PROJ_mandir := $(PROJ_prefix)/share/man + +# Determine if we're on a unix type operating system +LLVM_ON_UNIX:=@LLVM_ON_UNIX@ +LLVM_ON_WIN32:=@LLVM_ON_WIN32@ + +# Host operating system for which LLVM will be run. +OS=@OS@ +HOST_OS=@HOST_OS@ +# Target operating system for which LLVM will compile for. +TARGET_OS=@TARGET_OS@ + +# Target hardware architecture +ARCH=@ARCH@ + +# Indicates, whether we're cross-compiling LLVM or not +LLVM_CROSS_COMPILING=@LLVM_CROSS_COMPILING@ + +# Executable file extension for build platform (mainly for +# tablegen call if we're cross-compiling). +BUILD_EXEEXT=@BUILD_EXEEXT@ + +# Compilers for the build platflorm (mainly for tablegen +# call if we're cross-compiling). +BUILD_CC=@BUILD_CC@ +BUILD_CXX=@BUILD_CXX@ + +# Triple for configuring build tools when cross-compiling +BUILD_TRIPLE=@build@ + +# Target triple (cpu-vendor-os) for which we should generate code +TARGET_TRIPLE=@target@ + +# Extra options to compile LLVM with +EXTRA_OPTIONS=@EXTRA_OPTIONS@ + +# Endian-ness of the target +ENDIAN=@ENDIAN@ + +# Path to the C++ compiler to use. This is an optional setting, which defaults +# to whatever your gmake defaults to. +CXX = @CXX@ + +# Path to the CC binary, which use used by testcases for native builds. +CC := @CC@ + +# Linker flags. +LDFLAGS+=@LDFLAGS@ + +# Path to the library archiver program. +AR_PATH = @AR@ +AR = @AR@ + +# Path to the nm program +NM_PATH = @NM@ + +# The pathnames of the programs we require to build +CMP := @CMP@ +CP := @CP@ +DATE := @DATE@ +FIND := @FIND@ +GREP := @GREP@ +INSTALL := @INSTALL@ +MKDIR := $(LLVM_SRC_ROOT)/autoconf/mkinstalldirs +MV := @MV@ +RANLIB := @RANLIB@ +RM := @RM@ +SED := @SED@ +TAR := @TAR@ + +# Paths to miscellaneous programs we hope are present but might not be +PERL := @PERL@ +BZIP2 := @BZIP2@ +CAT := @CAT@ +DOT := @DOT@ +DOXYGEN := @DOXYGEN@ +GROFF := @GROFF@ +GZIPBIN := @GZIPBIN@ +OCAMLC := @OCAMLC@ +OCAMLOPT := @OCAMLOPT@ +OCAMLDEP := @OCAMLDEP@ +OCAMLDOC := @OCAMLDOC@ +GAS := @GAS@ +POD2HTML := @POD2HTML@ +POD2MAN := @POD2MAN@ +PDFROFF := @PDFROFF@ +RUNTEST := @RUNTEST@ +TCLSH := @TCLSH@ +ZIP := @ZIP@ + +HAVE_PERL := @HAVE_PERL@ +HAVE_PTHREAD := @HAVE_PTHREAD@ + +LIBS := @LIBS@ + +# Targets that we should build +TARGETS_TO_BUILD=@TARGETS_TO_BUILD@ + +# Path to location for LLVM C/C++ front-end. You can modify this if you +# want to override the value set by configure. +LLVMGCCDIR := @LLVMGCCDIR@ + +# Full pathnames of LLVM C/C++ front-end 'cc1' and 'cc1plus' binaries: +LLVMGCC := @LLVMGCC@ +LLVMGXX := @LLVMGXX@ +LLVMCC1 := @LLVMCC1@ +LLVMCC1PLUS := @LLVMCC1PLUS@ +LLVMGCC_LANGS := @LLVMGCC_LANGS@ +LLVMGCC_DRAGONEGG := @LLVMGCC_DRAGONEGG@ + +# Information on Clang, if configured. +CLANGPATH := @CLANGPATH@ +CLANGXXPATH := @CLANGXXPATH@ +ENABLE_BUILT_CLANG := @ENABLE_BUILT_CLANG@ + +# The LLVM capable compiler to use. +LLVMCC_OPTION := @LLVMCC_OPTION@ + +# The flag used to emit LLVM IR. +LLVMCC_EMITIR_FLAG = @LLVMCC_EMITIR_FLAG@ +LLVMCC_DISABLEOPT_FLAGS := @LLVMCC_DISABLEOPT_FLAGS@ + +# Path to directory where object files should be stored during a build. +# Set OBJ_ROOT to "." if you do not want to use a separate place for +# object files. +OBJ_ROOT := . + +# What to pass as rpath flag to g++ +RPATH := @RPATH@ + +# What to pass as -rdynamic flag to g++ +RDYNAMIC := @RDYNAMIC@ + +# These are options that can either be enabled here, or can be enabled on the +# make command line (ie, make ENABLE_PROFILING=1): + +# When ENABLE_OPTIMIZED is enabled, LLVM code is optimized and output is put +# into the "Release" directories. Otherwise, LLVM code is not optimized and +# output is put in the "Debug" directories. +#ENABLE_OPTIMIZED = 1 +@ENABLE_OPTIMIZED@ + +# When ENABLE_PROFILING is enabled, profile instrumentation is done +# and output is put into the "+Profile" directories, where +# is either Debug or Release depending on how other build +# flags are set. Otherwise, output is put in the +# directories. +#ENABLE_PROFILING = 1 +@ENABLE_PROFILING@ + +# When DISABLE_ASSERTIONS is enabled, builds of all of the LLVM code will +# exclude assertion checks, otherwise they are included. +#DISABLE_ASSERTIONS = 1 +@DISABLE_ASSERTIONS@ + +# When ENABLE_EXPENSIVE_CHECKS is enabled, builds of all of the LLVM +# code will include expensive checks, otherwise they are excluded. +#ENABLE_EXPENSIVE_CHECKS = 0 +@ENABLE_EXPENSIVE_CHECKS@ + +# When DEBUG_RUNTIME is enabled, the runtime libraries will retain debug +# symbols. +#DEBUG_RUNTIME = 1 +@DEBUG_RUNTIME@ + +# When DEBUG_SYMBOLS is enabled, the compiler libraries will retain debug +# symbols. +#DEBUG_SYMBOLS = 1 +@DEBUG_SYMBOLS@ + +# The compiler flags to use for optimized builds. +OPTIMIZE_OPTION := @OPTIMIZE_OPTION@ + +# When ENABLE_PROFILING is enabled, the llvm source base is built with profile +# information to allow gprof to be used to get execution frequencies. +#ENABLE_PROFILING = 1 + +# When ENABLE_DOCS is disabled, docs/ will not be built. +ENABLE_DOCS = @ENABLE_DOCS@ + +# When ENABLE_DOXYGEN is enabled, the doxygen documentation will be built +ENABLE_DOXYGEN = @ENABLE_DOXYGEN@ + +# Do we want to enable threads? +ENABLE_THREADS := @ENABLE_THREADS@ + +# Do we want to build with position independent code? +ENABLE_PIC := @ENABLE_PIC@ + +# Do we want to build a shared library and link the tools with it? +ENABLE_SHARED := @ENABLE_SHARED@ + +# Do we want to link the stdc++ into a shared library? (Cygming) +ENABLE_EMBED_STDCXX := @ENABLE_EMBED_STDCXX@ + +# Use -fvisibility-inlines-hidden? +ENABLE_VISIBILITY_INLINES_HIDDEN := @ENABLE_VISIBILITY_INLINES_HIDDEN@ + +# Do we want to allow timestamping information into builds? +ENABLE_TIMESTAMPS := @ENABLE_TIMESTAMPS@ + +# This option tells the Makefiles to produce verbose output. +# It essentially prints the commands that make is executing +#VERBOSE = 1 + +# Enable JIT for this platform +TARGET_HAS_JIT = @TARGET_HAS_JIT@ + +# Environment variable to set to change the runtime shared library search path. +SHLIBPATH_VAR = @SHLIBPATH_VAR@ + +# Shared library extension for host platform. +SHLIBEXT = @SHLIBEXT@ + +# Executable file extension for host platform. +EXEEXT = @EXEEXT@ + +# Things we just assume are "there" +ECHO := echo + +# Get the options for causing archives to link all their content instead of +# just missing symbols, and the inverse of that. This is used for certain LLVM +# tools that permit loadable modules. It ensures that the LLVM symbols will be +# available to those loadable modules. +LINKALL := @LINKALL@ +NOLINKALL := @NOLINKALL@ + +# Get the value of HUGE_VAL_SANITY which will be either "yes" or "no" depending +# on the check. +HUGE_VAL_SANITY = @HUGE_VAL_SANITY@ + +# Bindings that we should build +BINDINGS_TO_BUILD := @BINDINGS_TO_BUILD@ +ALL_BINDINGS := @ALL_BINDINGS@ +OCAML_LIBDIR := @OCAML_LIBDIR@ + +# When compiling under Mingw/Cygwin, executables such as tblgen +# expect Windows paths, whereas the build system uses Unix paths. +# The function SYSPATH transforms Unix paths into Windows paths. +ifneq (,$(findstring -mno-cygwin, $(CXX))) + SYSPATH = $(shell echo $(1) | cygpath -m -f -) +else + SYSPATH = $(1) +endif + +# Location of the plugin header file for gold. +BINUTILS_INCDIR := @BINUTILS_INCDIR@ + +# When ENABLE_LLVMC_DYNAMIC is enabled, LLVMC will link libCompilerDriver +# dynamically. This is needed to make dynamic plugins work on some targets +# (Windows). +ENABLE_LLVMC_DYNAMIC = 0 +#@ENABLE_LLVMC_DYNAMIC@ + +# When ENABLE_LLVMC_DYNAMIC_PLUGINS is enabled, LLVMC will have dynamic plugin +# support (via the -load option). +ENABLE_LLVMC_DYNAMIC_PLUGINS = 1 +#@ENABLE_LLVMC_DYNAMIC_PLUGINS@ + +# Optional flags supported by the compiler +# -Wno-missing-field-initializers +NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@ +# -Wno-variadic-macros +NO_VARIADIC_MACROS = @NO_VARIADIC_MACROS@ + +# Was polly found in tools/polly? +LLVM_HAS_POLLY = @LLVM_HAS_POLLY@ +# Flags supported by the linker. +# bfd ld / gold --version-script=file +HAVE_LINK_VERSION_SCRIPT = @HAVE_LINK_VERSION_SCRIPT@ diff --git a/final/Makefile.rules b/final/Makefile.rules new file mode 100644 index 00000000000..5fc77a5e510 --- /dev/null +++ b/final/Makefile.rules @@ -0,0 +1,2278 @@ +#===-- Makefile.rules - Common make rules for LLVM ---------*- Makefile -*--===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +# +# This file is included by all of the LLVM makefiles. For details on how to use +# it properly, please see the document MakefileGuide.html in the docs directory. +# +#===-----------------------------------------------------------------------====# + +################################################################################ +# TARGETS: Define standard targets that can be invoked +################################################################################ + +#-------------------------------------------------------------------- +# Define the various target sets +#-------------------------------------------------------------------- +RecursiveTargets := all clean clean-all install uninstall install-bytecode \ + unitcheck +LocalTargets := all-local clean-local clean-all-local check-local \ + install-local printvars uninstall-local \ + install-bytecode-local +TopLevelTargets := check dist dist-check dist-clean dist-gzip dist-bzip2 \ + dist-zip unittests +UserTargets := $(RecursiveTargets) $(LocalTargets) $(TopLevelTargets) +InternalTargets := preconditions distdir dist-hook + +################################################################################ +# INITIALIZATION: Basic things the makefile needs +################################################################################ + +#-------------------------------------------------------------------- +# Set the VPATH so that we can find source files. +#-------------------------------------------------------------------- +VPATH=$(PROJ_SRC_DIR) + +#-------------------------------------------------------------------- +# Reset the list of suffixes we know how to build. +#-------------------------------------------------------------------- +.SUFFIXES: +.SUFFIXES: .c .cpp .cc .h .hpp .o .a .bc .td .ps .dot .ll .m .mm +.SUFFIXES: $(SHLIBEXT) $(SUFFIXES) + +#-------------------------------------------------------------------- +# Mark all of these targets as phony to avoid implicit rule search +#-------------------------------------------------------------------- +.PHONY: $(UserTargets) $(InternalTargets) + +#-------------------------------------------------------------------- +# Make sure all the user-target rules are double colon rules and +# they are defined first. +#-------------------------------------------------------------------- + +$(UserTargets):: + +################################################################################ +# PRECONDITIONS: that which must be built/checked first +################################################################################ + +SrcMakefiles := $(filter %Makefile %Makefile.tests,\ + $(wildcard $(PROJ_SRC_DIR)/Makefile*)) +ObjMakefiles := $(subst $(PROJ_SRC_DIR),$(PROJ_OBJ_DIR),$(SrcMakefiles)) +ConfigureScript := $(PROJ_SRC_ROOT)/configure +ConfigStatusScript := $(PROJ_OBJ_ROOT)/config.status +MakefileConfigIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.config.in)) +MakefileCommonIn := $(strip $(wildcard $(PROJ_SRC_ROOT)/Makefile.common.in)) +MakefileConfig := $(PROJ_OBJ_ROOT)/Makefile.config +MakefileCommon := $(PROJ_OBJ_ROOT)/Makefile.common +PreConditions := $(ConfigStatusScript) $(ObjMakefiles) +ifneq ($(MakefileCommonIn),) +PreConditions += $(MakefileCommon) +endif + +ifneq ($(MakefileConfigIn),) +PreConditions += $(MakefileConfig) +endif + +preconditions: $(PreConditions) + +#------------------------------------------------------------------------ +# Make sure the BUILT_SOURCES are built first +#------------------------------------------------------------------------ +$(filter-out clean clean-local,$(UserTargets)):: $(BUILT_SOURCES) + +clean-all-local:: +ifneq ($(strip $(BUILT_SOURCES)),) + -$(Verb) $(RM) -f $(BUILT_SOURCES) +endif + +ifneq ($(PROJ_OBJ_ROOT),$(PROJ_SRC_ROOT)) +spotless: + $(Verb) if test -x config.status ; then \ + $(EchoCmd) Wiping out $(PROJ_OBJ_ROOT) ; \ + $(MKDIR) .spotless.save ; \ + $(MV) config.status .spotless.save ; \ + $(MV) mklib .spotless.save ; \ + $(MV) projects .spotless.save ; \ + $(RM) -rf * ; \ + $(MV) .spotless.save/config.status . ; \ + $(MV) .spotless.save/mklib . ; \ + $(MV) .spotless.save/projects . ; \ + $(RM) -rf .spotless.save ; \ + $(EchoCmd) Rebuilding configuration of $(PROJ_OBJ_ROOT) ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) ; \ + else \ + $(EchoCmd) "make spotless" can only be run from $(PROJ_OBJ_ROOT); \ + fi +else +spotless: + $(EchoCmd) "spotless target not supported for objdir == srcdir" +endif + +$(BUILT_SOURCES) : $(ObjMakefiles) + +#------------------------------------------------------------------------ +# Make sure we're not using a stale configuration +#------------------------------------------------------------------------ +reconfigure: + $(Echo) Reconfiguring $(PROJ_OBJ_ROOT) + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + if test -w $(PROJ_OBJ_ROOT)/config.cache ; then \ + $(RM) $(PROJ_OBJ_ROOT)/config.cache ; \ + fi ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +.PRECIOUS: $(ConfigStatusScript) +$(ConfigStatusScript): $(ConfigureScript) + $(Echo) Reconfiguring with $< + $(Verb) cd $(PROJ_OBJ_ROOT) && \ + if test -w $(PROJ_OBJ_ROOT)/config.cache ; then \ + $(RM) $(PROJ_OBJ_ROOT)/config.cache ; \ + fi ; \ + $(ConfigStatusScript) --recheck $(ConfigureScriptFLAGS) && \ + $(ConfigStatusScript) + +#------------------------------------------------------------------------ +# Make sure the configuration makefile is up to date +#------------------------------------------------------------------------ +ifneq ($(MakefileConfigIn),) +$(MakefileConfig): $(MakefileConfigIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.config +endif + +ifneq ($(MakefileCommonIn),) +$(MakefileCommon): $(MakefileCommonIn) $(ConfigStatusScript) + $(Echo) Regenerating $@ + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ConfigStatusScript) Makefile.common +endif + +#------------------------------------------------------------------------ +# If the Makefile in the source tree has been updated, copy it over into the +# build tree. But, only do this if the source and object makefiles differ +#------------------------------------------------------------------------ +ifndef PROJ_MAKEFILE +PROJ_MAKEFILE := $(PROJ_SRC_DIR)/Makefile +endif + +ifneq ($(PROJ_OBJ_DIR),$(PROJ_SRC_DIR)) + +Makefile: $(PROJ_MAKEFILE) $(ExtraMakefiles) + $(Echo) "Updating Makefile" + $(Verb) $(MKDIR) $(@D) + $(Verb) $(CP) -f $< $@ + +# Copy the Makefile.* files unless we're in the root directory which avoids +# the copying of Makefile.config.in or other things that should be explicitly +# taken care of. +$(PROJ_OBJ_DIR)/Makefile% : $(PROJ_MAKEFILE)% + @case '$?' in \ + *Makefile.rules) ;; \ + *.in) ;; \ + *) $(EchoCmd) "Updating $(@F)" ; \ + $(MKDIR) $(@D) ; \ + $(CP) -f $< $@ ;; \ + esac + +endif + +#------------------------------------------------------------------------ +# Set up the basic dependencies +#------------------------------------------------------------------------ +$(UserTargets):: $(PreConditions) + +all:: all-local +clean:: clean-local +clean-all:: clean-local clean-all-local +install:: install-local +uninstall:: uninstall-local +install-local:: all-local +install-bytecode:: install-bytecode-local + +############################################################################### +# LLVMC: Provide rules for compiling llvmc-based driver +############################################################################### + +ifdef LLVMC_BASED_DRIVER + +TOOLNAME = $(LLVMC_BASED_DRIVER) + +LLVMLIBS = CompilerDriver.a +LINK_COMPONENTS = support + +endif # LLVMC_BASED_DRIVER + +############################################################################### +# VARIABLES: Set up various variables based on configuration data +############################################################################### + +# Variable for if this make is for a "cleaning" target +ifneq ($(strip $(filter clean clean-local dist-clean,$(MAKECMDGOALS))),) + IS_CLEANING_TARGET=1 +endif + +#-------------------------------------------------------------------- +# Variables derived from configuration we are building +#-------------------------------------------------------------------- + +CPP.Defines := +ifeq ($(ENABLE_OPTIMIZED),1) + BuildMode := Release + # Don't use -fomit-frame-pointer on Darwin or FreeBSD. + ifneq ($(HOST_OS),FreeBSD) + ifneq ($(HOST_OS),Darwin) + OmitFramePointer := -fomit-frame-pointer + endif + endif + + # Darwin requires -fstrict-aliasing to be explicitly enabled. + # Avoid -fstrict-aliasing on Darwin for now, there are unresolved issues + # with -fstrict-aliasing and ipa-type-escape radr://6756684 + #ifeq ($(HOST_OS),Darwin) + # EXTRA_OPTIONS += -fstrict-aliasing -Wstrict-aliasing + #endif + CXX.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + C.Flags += $(OPTIMIZE_OPTION) $(OmitFramePointer) + LD.Flags += $(OPTIMIZE_OPTION) + ifdef DEBUG_SYMBOLS + BuildMode := $(BuildMode)+Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +else + ifdef NO_DEBUG_SYMBOLS + BuildMode := Unoptimized + CXX.Flags += + C.Flags += + LD.Flags += + KEEP_SYMBOLS := 1 + else + BuildMode := Debug + CXX.Flags += -g + C.Flags += -g + LD.Flags += -g + KEEP_SYMBOLS := 1 + endif +endif + +ifeq ($(ENABLE_PROFILING),1) + BuildMode := $(BuildMode)+Profile + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) -pg -g + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) -pg -g + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) -pg -g + KEEP_SYMBOLS := 1 +endif + +#ifeq ($(ENABLE_VISIBILITY_INLINES_HIDDEN),1) +# CXX.Flags += -fvisibility-inlines-hidden +#endif + +ifdef ENABLE_EXPENSIVE_CHECKS + # GNU libstdc++ uses RTTI if you define _GLIBCXX_DEBUG, which we did above. + # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40160 + REQUIRES_RTTI := 1 +endif + +# IF REQUIRES_EH=1 is specified then don't disable exceptions +ifndef REQUIRES_EH + CXX.Flags += -fno-exceptions +else + # If the library requires EH, it also requires RTTI. + REQUIRES_RTTI := 1 +endif + +ifdef REQUIRES_FRAME_POINTER + CXX.Flags := $(filter-out -fomit-frame-pointer,$(CXX.Flags)) + C.Flags := $(filter-out -fomit-frame-pointer,$(C.Flags)) + LD.Flags := $(filter-out -fomit-frame-pointer,$(LD.Flags)) +endif + +# If REQUIRES_RTTI=1 is specified then don't disable run-time type id. +ifneq ($(REQUIRES_RTTI), 1) + CXX.Flags += -fno-rtti +endif + +ifeq ($(ENABLE_COVERAGE),1) + BuildMode := $(BuildMode)+Coverage + CXX.Flags += -ftest-coverage -fprofile-arcs + C.Flags += -ftest-coverage -fprofile-arcs +endif + +# If DISABLE_ASSERTIONS=1 is specified (make command line or configured), +# then disable assertions by defining the appropriate preprocessor symbols. +ifeq ($(DISABLE_ASSERTIONS),1) + CPP.Defines += -DNDEBUG +else + BuildMode := $(BuildMode)+Asserts + CPP.Defines += -D_DEBUG +endif + +# If ENABLE_EXPENSIVE_CHECKS=1 is specified (make command line or +# configured), then enable expensive checks by defining the +# appropriate preprocessor symbols. +ifeq ($(ENABLE_EXPENSIVE_CHECKS),1) + BuildMode := $(BuildMode)+Checks + CPP.Defines += -D_GLIBCXX_DEBUG -DXDEBUG +endif + +# LOADABLE_MODULE implies several other things so we force them to be +# defined/on. +ifdef LOADABLE_MODULE + SHARED_LIBRARY := 1 + LINK_LIBS_IN_SHARED := 1 +endif + +ifdef SHARED_LIBRARY + ENABLE_PIC := 1 + PIC_FLAG = "(PIC)" +endif + +ifeq ($(ENABLE_PIC),1) + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + # Nothing. Win32 defaults to PIC and warns when given -fPIC + else + ifeq ($(HOST_OS),Darwin) + # Common symbols not allowed in dylib files + CXX.Flags += -fno-common + C.Flags += -fno-common + else + # Linux and others; pass -fPIC + CXX.Flags += -fPIC + C.Flags += -fPIC + endif + endif +else + ifeq ($(HOST_OS),Darwin) + CXX.Flags += -mdynamic-no-pic + C.Flags += -mdynamic-no-pic + endif +endif + +# Support makefile variable to disable any kind of timestamp/non-deterministic +# info from being used in the build. +ifeq ($(ENABLE_TIMESTAMPS),1) + DOTDIR_TIMESTAMP_COMMAND := $(DATE) +else + DOTDIR_TIMESTAMP_COMMAND := echo 'Created.' +endif + +ifeq ($(HOST_OS),MingW) + # Work around PR4957 + CPP.Defines += -D__NO_CTYPE_INLINE + ifeq ($(LLVM_CROSS_COMPILING),1) + # Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=525016 + ifdef TOOLNAME + LD.Flags += -Wl,--allow-multiple-definition + endif + endif +endif + +CXX.Flags += -Woverloaded-virtual +CPP.BaseFlags += $(CPP.Defines) +AR.Flags := cru + +# Make Floating point IEEE compliant on Alpha. +ifeq ($(ARCH),Alpha) + CXX.Flags += -mieee + CPP.BaseFlags += -mieee +ifeq ($(ENABLE_PIC),0) + CXX.Flags += -fPIC + CPP.BaseFlags += -fPIC +endif + + LD.Flags += -Wl,--no-relax +endif + +# GNU ld/PECOFF accepts but ignores them below; +# --version-script +# --export-dynamic +# --rpath +# FIXME: autoconf should be aware of them. +ifneq (,$(filter $(HOST_OS),Cygwin MingW)) + HAVE_LINK_VERSION_SCRIPT := 0 + RPATH := + RDYNAMIC := -Wl,--export-all-symbols +endif + +#-------------------------------------------------------------------- +# Directory locations +#-------------------------------------------------------------------- +TargetMode := +ifeq ($(LLVM_CROSS_COMPILING),1) + BuildLLVMToolDir := $(LLVM_OBJ_ROOT)/BuildTools/$(BuildMode)/bin +endif + +ObjRootDir := $(PROJ_OBJ_DIR)/$(BuildMode) +ObjDir := $(ObjRootDir) +LibDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/lib +ToolDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/bin +ExmplDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/examples +LLVMLibDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/lib +LLVMToolDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/bin +LLVMExmplDir:= $(LLVM_OBJ_ROOT)/$(BuildMode)/examples + +#-------------------------------------------------------------------- +# Locations of shared libraries +#-------------------------------------------------------------------- + +SharedPrefix := lib +SharedLibDir := $(LibDir) +LLVMSharedLibDir := $(LLVMLibDir) + +# Win32.DLL prefers to be located on the "PATH" of binaries. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + SharedLibDir := $(ToolDir) + LLVMSharedLibDir := $(LLVMToolDir) + + ifeq ($(HOST_OS),Cygwin) + SharedPrefix := cyg + else + SharedPrefix := + endif +endif + +#-------------------------------------------------------------------- +# LLVM Capable Compiler +#-------------------------------------------------------------------- + +ifeq ($(LLVMCC_OPTION),llvm-gcc) + LLVMCC := $(LLVMGCC) + LLVMCXX := $(LLVMGXX) +else + ifeq ($(LLVMCC_OPTION),clang) + ifneq ($(CLANGPATH),) + LLVMCC := $(CLANGPATH) + LLVMCXX := $(CLANGXXPATH) + else + ifeq ($(ENABLE_BUILT_CLANG),1) + LLVMCC := $(LLVMToolDir)/clang + LLVMCXX := $(LLVMToolDir)/clang++ + endif + endif + endif +endif + +#-------------------------------------------------------------------- +# Full Paths To Compiled Tools and Utilities +#-------------------------------------------------------------------- +EchoCmd = $(ECHO) llvm[$(MAKELEVEL)]: +Echo = @$(EchoCmd) +ifndef LLVMAS +LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT) +endif +ifndef TBLGEN + ifeq ($(LLVM_CROSS_COMPILING),1) + TBLGEN := $(BuildLLVMToolDir)/tblgen$(BUILD_EXEEXT) + else + TBLGEN := $(LLVMToolDir)/tblgen$(EXEEXT) + endif +endif +LLVM_CONFIG := $(LLVMToolDir)/llvm-config +ifndef LLVMLD +LLVMLD := $(LLVMToolDir)/llvm-ld$(EXEEXT) +endif +ifndef LLVMDIS +LLVMDIS := $(LLVMToolDir)/llvm-dis$(EXEEXT) +endif +ifndef LLI +LLI := $(LLVMToolDir)/lli$(EXEEXT) +endif +ifndef LLC +LLC := $(LLVMToolDir)/llc$(EXEEXT) +endif +ifndef LOPT +LOPT := $(LLVMToolDir)/opt$(EXEEXT) +endif +ifndef LBUGPOINT +LBUGPOINT := $(LLVMToolDir)/bugpoint$(EXEEXT) +endif + +#-------------------------------------------------------------------- +# Adjust to user's request +#-------------------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) + DARWIN_VERSION := `sw_vers -productVersion` + # Strip a number like 10.4.7 to 10.4 + DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]).*/\1/') + # Get "4" out of 10.4 for later pieces in the makefile. + DARWIN_MAJVERS := $(shell echo $(DARWIN_VERSION)| sed -E 's/10.([0-9]).*/\1/') + + LoadableModuleOptions := -Wl,-flat_namespace -Wl,-undefined,suppress + SharedLinkOptions := -dynamiclib + ifneq ($(ARCH),ARM) + SharedLinkOptions += -mmacosx-version-min=$(DARWIN_VERSION) + endif +else + SharedLinkOptions=-shared +endif + +ifeq ($(TARGET_OS),Darwin) + ifneq ($(ARCH),ARM) + TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION) + endif +endif + +ifdef SHARED_LIBRARY +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) + LD.Flags += $(RPATH) -Wl,'$$ORIGIN' +endif +endif +endif + +ifdef TOOL_VERBOSE + C.Flags += -v + CXX.Flags += -v + LD.Flags += -v + VERBOSE := 1 +endif + +# Adjust settings for verbose mode +ifndef VERBOSE + Verb := @ + AR.Flags += >/dev/null 2>/dev/null + ConfigureScriptFLAGS += >$(PROJ_OBJ_DIR)/configure.out 2>&1 +else + ConfigureScriptFLAGS := +endif + +# By default, strip symbol information from executable +ifndef KEEP_SYMBOLS + Strip := $(PLATFORMSTRIPOPTS) + StripWarnMsg := "(without symbols)" + Install.StripFlag += -s +endif + +ifdef TOOL_NO_EXPORTS + DynamicFlags := +else + DynamicFlag := $(RDYNAMIC) +endif + +# Adjust linker flags for building an executable +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS), Darwin) +ifdef TOOLNAME + LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' + ifdef EXAMPLE_TOOL + LD.Flags += $(RPATH) -Wl,$(ExmplDir) $(DynamicFlag) + else + LD.Flags += $(RPATH) -Wl,$(ToolDir) $(DynamicFlag) + endif +endif +else +ifneq ($(DARWIN_MAJVERS),4) + LD.Flags += $(RPATH) -Wl,@executable_path/../lib +endif +endif +endif + + +#---------------------------------------------------------- +# Options To Invoke Tools +#---------------------------------------------------------- + +ifndef NO_PEDANTIC +CompileCommonOpts += -pedantic -Wno-long-long +endif +CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ + $(EXTRA_OPTIONS) +# Enable cast-qual for C++; the workaround is to use const_cast. +CXX.Flags += -Wcast-qual + +ifeq ($(HOST_OS),HP-UX) + CompileCommonOpts := -D_REENTRANT -D_HPUX_SOURCE +endif + +# If we are building a universal binary on Mac OS/X, pass extra options. This +# is useful to people that want to link the LLVM libraries into their universal +# apps. +# +# The following can be optionally specified: +# UNIVERSAL_SDK_PATH variable can be specified as a path to the SDK to use. +# For Mac OS/X 10.4 Intel machines, the traditional one is: +# UNIVERSAL_SDK_PATH=/Developer/SDKs/MacOSX10.4u.sdk/ +# UNIVERSAL_ARCH can be optionally specified to be a list of architectures +# to build for, e.g. UNIVERSAL_ARCH="i386 ppc ppc64". This defaults to +# i386/ppc only. +ifdef UNIVERSAL + ifndef UNIVERSAL_ARCH + UNIVERSAL_ARCH := i386 ppc + endif + UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %) + CompileCommonOpts += $(UNIVERSAL_ARCH_OPTIONS) + ifdef UNIVERSAL_SDK_PATH + CompileCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH) + endif + + # Building universal cannot compute dependencies automatically. + DISABLE_AUTO_DEPENDENCIES=1 +else + ifeq ($(TARGET_OS),Darwin) + ifeq ($(ARCH),x86_64) + TargetCommonOpts = -m64 + else + ifeq ($(ARCH),x86) + TargetCommonOpts = -m32 + endif + endif + endif +endif + +ifeq ($(HOST_OS),SunOS) +CPP.BaseFlags += -include llvm/Support/Solaris.h +endif + +ifeq ($(HOST_OS),AuroraUX) +CPP.BaseFlags += -include llvm/Support/Solaris.h +endif # !HOST_OS - AuroraUX. + +LD.Flags += -L$(LibDir) -L$(LLVMLibDir) +CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS +# All -I flags should go here, so that they don't confuse llvm-config. +CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \ + $(patsubst %,-I%/include,\ + $(PROJ_OBJ_ROOT) $(PROJ_SRC_ROOT) \ + $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ + $(CPP.BaseFlags) + +ifeq ($(BUILD_COMPONENT), 1) + Compile.C = $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Compile.CXX = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Preprocess.CXX= $(BUILD_CXX) $(CPP.Flags) $(CPPFLAGS) $(TargetCommonOpts) \ + $(CompileCommonOpts) $(CXX.Flags) -E + Link = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + $(LD.Flags) $(LDFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) +else + Compile.C = $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Compile.CXX = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -c + Preprocess.CXX= $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ + $(CompileCommonOpts) $(CXX.Flags) -E + Link = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ + $(LDFLAGS) $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) +endif + +BCCompile.C = $(LLVMCC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) +Preprocess.C = $(CC) $(CPP.Flags) $(C.Flags) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) -E + +BCCompile.CXX = $(LLVMCXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + $(TargetCommonOpts) $(CompileCommonOpts) + +ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 +ScriptInstall = $(INSTALL) -m 0755 +DataInstall = $(INSTALL) -m 0644 + +# When compiling under Mingw/Cygwin, the tblgen tool expects Windows +# paths. In this case, the SYSPATH function (defined in +# Makefile.config) transforms Unix paths into Windows paths. +TableGen = $(TBLGEN) -I $(call SYSPATH, $(PROJ_SRC_DIR)) \ + -I $(call SYSPATH, $(LLVM_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \ + -I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target) + +Archive = $(AR) $(AR.Flags) +LArchive = $(LLVMToolDir)/llvm-ar rcsf +ifdef RANLIB +Ranlib = $(RANLIB) +else +Ranlib = ranlib +endif + +AliasTool = ln -s + +#---------------------------------------------------------- +# Get the list of source files and compute object file +# names from them. +#---------------------------------------------------------- + +ifndef SOURCES + Sources := $(notdir $(wildcard $(PROJ_SRC_DIR)/*.cpp \ + $(PROJ_SRC_DIR)/*.cc $(PROJ_SRC_DIR)/*.c)) +else + Sources := $(SOURCES) +endif + +ifdef BUILT_SOURCES +Sources += $(filter %.cpp %.c %.cc,$(BUILT_SOURCES)) +endif + +BaseNameSources := $(sort $(basename $(Sources))) + +ObjectsO := $(BaseNameSources:%=$(ObjDir)/%.o) +ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) + +#---------------------------------------------------------- +# For Mingw MSYS bash and Python/w32: +# +# $(ECHOPATH) prints DOSish pathstring. +# ex) $(ECHOPATH) /include/sys/types.h +# --> C:/mingw/include/sys/types.h +# built-in "echo" does not transform path to DOSish path. +# +# FIXME: It would not be needed when MSYS's python +# were provided. +#---------------------------------------------------------- + +ifeq (-mingw32,$(findstring -mingw32,$(BUILD_TRIPLE))) + ECHOPATH := $(Verb)python -u -c "import sys;print ' '.join(sys.argv[1:])" +else + ECHOPATH := $(Verb)$(ECHO) +endif + +############################################################################### +# DIRECTORIES: Handle recursive descent of directory structure +############################################################################### + +#--------------------------------------------------------- +# Provide rules to make install dirs. This must be early +# in the file so they get built before dependencies +#--------------------------------------------------------- + +$(DESTDIR)$(PROJ_bindir) $(DESTDIR)$(PROJ_libdir) $(DESTDIR)$(PROJ_includedir) $(DESTDIR)$(PROJ_etcdir):: + $(Verb) $(MKDIR) $@ + +# To create other directories, as needed, and timestamp their creation +%/.dir: + $(Verb) $(MKDIR) $* > /dev/null + $(Verb) $(DOTDIR_TIMESTAMP_COMMAND) > $@ + +.PRECIOUS: $(ObjDir)/.dir $(LibDir)/.dir $(ToolDir)/.dir $(ExmplDir)/.dir +.PRECIOUS: $(LLVMLibDir)/.dir $(LLVMToolDir)/.dir $(LLVMExmplDir)/.dir + +#--------------------------------------------------------- +# Handle the DIRS options for sequential construction +#--------------------------------------------------------- + +SubDirs := +ifdef DIRS +SubDirs += $(DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(DIRS); do \ + ($(MAKE) -C $$dir $@ ) || exit 1; \ + done +endif + +endif + +#--------------------------------------------------------- +# Handle the EXPERIMENTAL_DIRS options ensuring success +# after each directory is built. +#--------------------------------------------------------- +ifdef EXPERIMENTAL_DIRS +$(RecursiveTargets):: + $(Verb) for dir in $(EXPERIMENTAL_DIRS); do \ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ ) || exit 0; \ + done +endif + +#----------------------------------------------------------- +# Handle the OPTIONAL_PARALLEL_DIRS options for optional parallel construction +#----------------------------------------------------------- +ifdef OPTIONAL_PARALLEL_DIRS + PARALLEL_DIRS += $(foreach T,$(OPTIONAL_PARALLEL_DIRS),$(shell test -d $(PROJ_SRC_DIR)/$(T) && echo "$(T)")) +endif + +#----------------------------------------------------------- +# Handle the PARALLEL_DIRS options for parallel construction +#----------------------------------------------------------- +ifdef PARALLEL_DIRS + +SubDirs += $(PARALLEL_DIRS) + +# Unfortunately, this list must be maintained if new recursive targets are added +all :: $(addsuffix /.makeall ,$(PARALLEL_DIRS)) +clean :: $(addsuffix /.makeclean ,$(PARALLEL_DIRS)) +clean-all:: $(addsuffix /.makeclean-all,$(PARALLEL_DIRS)) +install :: $(addsuffix /.makeinstall ,$(PARALLEL_DIRS)) +uninstall:: $(addsuffix /.makeuninstall,$(PARALLEL_DIRS)) +install-bytecode :: $(addsuffix /.makeinstall-bytecode,$(PARALLEL_DIRS)) +unitcheck:: $(addsuffix /.makeunitcheck,$(PARALLEL_DIRS)) + +ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T)) + +$(ParallelTargets) : + $(Verb) if ([ ! -f $(@D)/Makefile ] || \ + command test $(@D)/Makefile -ot \ + $(PROJ_SRC_DIR)/$(@D)/Makefile ); then \ + $(MKDIR) $(@D); \ + $(CP) $(PROJ_SRC_DIR)/$(@D)/Makefile $(@D)/Makefile; \ + fi; \ + $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) +endif + +#--------------------------------------------------------- +# Handle the OPTIONAL_DIRS options for directores that may +# or may not exist. +#--------------------------------------------------------- +ifdef OPTIONAL_DIRS + +SubDirs += $(OPTIONAL_DIRS) + +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\ + if ([ ! -f $$dir/Makefile ] || \ + command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \ + $(MKDIR) $$dir; \ + $(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + fi \ + done +else +$(RecursiveTargets):: + $(Verb) for dir in $(OPTIONAL_DIRS); do \ + if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\ + ($(MAKE) -C$$dir $@ ) || exit 1; \ + fi \ + done +endif +endif + +#--------------------------------------------------------- +# Handle the CONFIG_FILES options +#--------------------------------------------------------- +ifdef CONFIG_FILES + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) UnInstall circumvented with NO_INSTALL +else +install-local:: $(DESTDIR)$(PROJ_etcdir) $(CONFIG_FILES) + $(Echo) Installing Configuration Files To $(DESTDIR)$(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + if test -f $(PROJ_OBJ_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_OBJ_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ + elif test -f $(PROJ_SRC_DIR)/$${file} ; then \ + $(DataInstall) $(PROJ_SRC_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ + else \ + $(ECHO) Error: cannot find config file $${file}. ; \ + fi \ + done + +uninstall-local:: + $(Echo) Uninstalling Configuration Files From $(DESTDIR)$(PROJ_etcdir) + $(Verb)for file in $(CONFIG_FILES); do \ + $(RM) -f $(DESTDIR)$(PROJ_etcdir)/$${file} ; \ + done +endif + +endif + +############################################################################### +# Set up variables for building libraries +############################################################################### + +#--------------------------------------------------------- +# Define various command line options pertaining to the +# libraries needed when linking. There are "Proj" libs +# (defined by the user's project) and "LLVM" libs (defined +# by the LLVM project). +#--------------------------------------------------------- + +ifdef USEDLIBS +ProjLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +ProjLibsOptions := $(patsubst %.o, $(LibDir)/%.o, $(ProjLibsOptions)) +ProjUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(USEDLIBS))) +ProjLibsPaths := $(addprefix $(LibDir)/,$(ProjUsedLibs)) +endif + +ifdef LLVMLIBS +LLVMLibsOptions := $(patsubst %.a.o, -l%, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsOptions := $(patsubst %.o, $(LLVMLibDir)/%.o, $(LLVMLibsOptions)) +LLVMUsedLibs := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(LLVMLIBS))) +LLVMLibsPaths := $(addprefix $(LLVMLibDir)/,$(LLVMUsedLibs)) +endif + +# Loadable module for Win32 requires all symbols resolved for linking. +# Then all symbols in LLVM.dll will be available. +ifeq ($(ENABLE_SHARED),1) + ifdef LOADABLE_MODULE + ifneq (,$(filter $(HOST_OS),Cygwin MingW)) + LINK_COMPONENTS += all + endif + endif +endif + +ifndef IS_CLEANING_TARGET +ifdef LINK_COMPONENTS + +# If LLVM_CONFIG doesn't exist, build it. This can happen if you do a make +# clean in tools, then do a make in tools (instead of at the top level). +$(LLVM_CONFIG): + @echo "*** llvm-config doesn't exist - rebuilding it." + @$(MAKE) -C $(PROJ_OBJ_ROOT)/tools/llvm-config + +$(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT): $(LLVM_CONFIG) + +ifeq ($(ENABLE_SHARED), 1) +# We can take the "auto-import" feature to get rid of using dllimport. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +LLVMLibsOptions += -Wl,--enable-auto-import,--enable-runtime-pseudo-reloc \ + -L $(SharedLibDir) +endif +LLVMLibsOptions += -lLLVM-$(LLVMVersion) +LLVMLibsPaths += $(SharedLibDir)/$(SharedPrefix)LLVM-$(LLVMVersion)$(SHLIBEXT) +else + +ifndef NO_LLVM_CONFIG +LLVMConfigLibs := $(shell $(LLVM_CONFIG) --libs $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibs),Error) +$(error llvm-config --libs failed) +endif +LLVMLibsOptions += $(LLVMConfigLibs) +LLVMConfigLibfiles := $(shell $(LLVM_CONFIG) --libfiles $(LINK_COMPONENTS) || echo Error) +ifeq ($(LLVMConfigLibfiles),Error) +$(error llvm-config --libfiles failed) +endif +LLVMLibsPaths += $(LLVM_CONFIG) $(LLVMConfigLibfiles) +endif + +endif +endif +endif + +# Set up the library exports file. +ifdef EXPORTED_SYMBOL_FILE + +# First, set up the native export file, which may differ from the source +# export file. + +ifeq ($(HOST_OS),Darwin) +# Darwin convention prefixes symbols with underscores. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).sed +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Verb) sed -e 's/^/_/' < $< > $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +ifeq ($(HAVE_LINK_VERSION_SCRIPT),1) +# Gold and BFD ld require a version script rather than a plain list. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).map +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Verb) echo "{" > $@ + $(Verb) grep -q "\<" $< && echo " global:" >> $@ || : + $(Verb) sed -e 's/$$/;/' -e 's/^/ /' < $< >> $@ +ifneq ($(HOST_OS),OpenBSD) + $(Verb) echo " local: *;" >> $@ +endif + $(Verb) echo "};" >> $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +# GNU ld Win32 accepts .DEF files that contain "DATA" entries. +NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE:.exports=.def)) +$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir + $(Echo) Generating $(notdir $@) + $(Verb) $(ECHO) "EXPORTS" > $@ + $(Verb) $(CAT) $< >> $@ +clean-local:: + -$(Verb) $(RM) -f $(NativeExportsFile) +else +# Default behavior: just use the exports file verbatim. +NativeExportsFile := $(EXPORTED_SYMBOL_FILE) +endif +endif +endif + +# Now add the linker command-line options to use the native export file. + +# Darwin +ifeq ($(HOST_OS),Darwin) +LLVMLibsOptions += -Wl,-exported_symbols_list,$(NativeExportsFile) +endif + +# gold, bfd ld, etc. +ifeq ($(HAVE_LINK_VERSION_SCRIPT),1) +LLVMLibsOptions += -Wl,--version-script,$(NativeExportsFile) +endif + +# Windows +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +# LLVMLibsOptions is invalidated at processing tools/llvm-shlib. +SharedLinkOptions += $(NativeExportsFile) +endif + +endif + +############################################################################### +# Library Build Rules: Four ways to build a library +############################################################################### + +#--------------------------------------------------------- +# Bytecode Module Targets: +# If the user set MODULE_NAME then they want to build a +# bytecode module from the sources. We compile all the +# sources and link it together into a single bytecode +# module. +#--------------------------------------------------------- + +ifdef MODULE_NAME +ifeq ($(strip $(LLVMCC)),) +$(warning Modules require LLVM capable compiler but none is available ****) +else + +Module := $(LibDir)/$(MODULE_NAME).bc +LinkModule := $(LLVMLD) -r + + +ifdef EXPORTED_SYMBOL_FILE +LinkModule += -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) +endif + +$(Module): $(BUILT_SOURCES) $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) + $(Echo) Building $(BuildMode) Bytecode Module $(notdir $@) + $(Verb) $(LinkModule) -o $@ $(ObjectsBC) + +all-local:: $(Module) + +clean-local:: +ifneq ($(strip $(Module)),) + -$(Verb) $(RM) -f $(Module) +endif + +ifdef BYTECODE_DESTINATION +ModuleDestDir := $(BYTECODE_DESTINATION) +else +ModuleDestDir := $(DESTDIR)$(PROJ_libdir) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestModule := $(ModuleDestDir)/$(MODULE_NAME).bc + +install-module:: $(DestModule) +install-local:: $(DestModule) + +$(DestModule): $(ModuleDestDir) $(Module) + $(Echo) Installing $(BuildMode) Bytecode Module $(DestModule) + $(Verb) $(DataInstall) $(Module) $(DestModule) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Bytecode Module $(DestModule) + -$(Verb) $(RM) -f $(DestModule) +endif + +endif +endif + +# if we're building a library ... +ifdef LIBRARYNAME + +# Make sure there isn't any extraneous whitespace on the LIBRARYNAME option +LIBRARYNAME := $(strip $(LIBRARYNAME)) +ifdef LOADABLE_MODULE +BaseLibName.A := $(LIBRARYNAME).a +BaseLibName.SO := $(LIBRARYNAME)$(SHLIBEXT) +else +BaseLibName.A := lib$(LIBRARYNAME).a +BaseLibName.SO := $(SharedPrefix)$(LIBRARYNAME)$(SHLIBEXT) +endif +LibName.A := $(LibDir)/$(BaseLibName.A) +LibName.SO := $(SharedLibDir)/$(BaseLibName.SO) +LibName.O := $(LibDir)/$(LIBRARYNAME).o +LibName.BCA:= $(LibDir)/lib$(LIBRARYNAME).bca + +#--------------------------------------------------------- +# Shared Library Targets: +# If the user asked for a shared library to be built +# with the SHARED_LIBRARY variable, then we provide +# targets for building them. +#--------------------------------------------------------- +ifdef SHARED_LIBRARY + +all-local:: $(LibName.SO) + +ifdef EXPORTED_SYMBOL_FILE +$(LibName.SO): $(NativeExportsFile) +endif + +ifdef LINK_LIBS_IN_SHARED +ifdef LOADABLE_MODULE +SharedLibKindMessage := "Loadable Module" +SharedLinkOptions := $(LoadableModuleOptions) $(SharedLinkOptions) +else +SharedLibKindMessage := "Shared Library" +endif +$(LibName.SO): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(SharedLibDir)/.dir + $(Echo) Linking $(BuildMode) $(SharedLibKindMessage) \ + $(notdir $@) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) \ + $(ProjLibsOptions) $(LLVMLibsOptions) $(LIBS) +else +$(LibName.SO): $(ObjectsO) $(SharedLibDir)/.dir + $(Echo) Linking $(BuildMode) Shared Library $(notdir $@) + $(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO) +endif + +clean-local:: +ifneq ($(strip $(LibName.SO)),) + -$(Verb) $(RM) -f $(LibName.SO) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else + +# Win32.DLL prefers to be located on the "PATH" of binaries. +ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +DestSharedLibDir := $(DESTDIR)$(PROJ_bindir) +else +DestSharedLibDir := $(DESTDIR)$(PROJ_libdir) +endif +DestSharedLib := $(DestSharedLibDir)/$(BaseLibName.SO) + +install-local:: $(DestSharedLib) + +$(DestSharedLib): $(LibName.SO) $(DestSharedLibDir) + $(Echo) Installing $(BuildMode) Shared Library $(DestSharedLib) + $(Verb) $(INSTALL) $(LibName.SO) $(DestSharedLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) + -$(Verb) $(RM) -f $(DestSharedLibDir)/$(SharedPrefix)$(LIBRARYNAME).* +endif +endif + +#--------------------------------------------------------- +# Bytecode Library Targets: +# If the user asked for a bytecode library to be built +# with the BYTECODE_LIBRARY variable, then we provide +# targets for building them. +#--------------------------------------------------------- +ifdef BYTECODE_LIBRARY +ifeq ($(strip $(LLVMCC)),) +$(warning Bytecode libraries require LLVM capable compiler but none is available ****) +else + +all-local:: $(LibName.BCA) + +ifdef EXPORTED_SYMBOL_FILE +BCLinkLib = $(LLVMLD) -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) + +$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) \ + $(LLVMToolDir)/llvm-ar + $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) \ + "(internalize)" + $(Verb) $(BCLinkLib) -o $(ObjDir)/$(LIBRARYNAME).internalize $(ObjectsBC) + $(Verb) $(RM) -f $@ + $(Verb) $(LArchive) $@ $(ObjDir)/$(LIBRARYNAME).internalize.bc +else +$(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir \ + $(LLVMToolDir)/llvm-ar + $(Echo) Building $(BuildMode) Bytecode Archive $(notdir $@) + $(Verb) $(RM) -f $@ + $(Verb) $(LArchive) $@ $(ObjectsBC) + +endif + +clean-local:: +ifneq ($(strip $(LibName.BCA)),) + -$(Verb) $(RM) -f $(LibName.BCA) +endif + +ifdef BYTECODE_DESTINATION +BytecodeDestDir := $(BYTECODE_DESTINATION) +else +BytecodeDestDir := $(DESTDIR)$(PROJ_libdir) +endif + +DestBytecodeLib = $(BytecodeDestDir)/lib$(LIBRARYNAME).bca + +install-bytecode-local:: $(DestBytecodeLib) + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +install-local:: $(DestBytecodeLib) + +$(DestBytecodeLib): $(LibName.BCA) $(BytecodeDestDir) + $(Echo) Installing $(BuildMode) Bytecode Archive $(DestBytecodeLib) + $(Verb) $(DataInstall) $(LibName.BCA) $(DestBytecodeLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Bytecode Archive $(DestBytecodeLib) + -$(Verb) $(RM) -f $(DestBytecodeLib) +endif +endif +endif + +#--------------------------------------------------------- +# Library Targets: +# If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to +# building an archive. +#--------------------------------------------------------- +ifndef NO_BUILD_ARCHIVE +ifndef BUILD_ARCHIVE +ifndef LOADABLE_MODULE +BUILD_ARCHIVE = 1 +endif +endif +endif + +#--------------------------------------------------------- +# Archive Library Targets: +# If the user wanted a regular archive library built, +# then we provide targets for building them. +#--------------------------------------------------------- +ifdef BUILD_ARCHIVE + +all-local:: $(LibName.A) + +$(LibName.A): $(ObjectsO) $(LibDir)/.dir + $(Echo) Building $(BuildMode) Archive Library $(notdir $@) + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-local:: +ifneq ($(strip $(LibName.A)),) + -$(Verb) $(RM) -f $(LibName.A) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +ifdef NO_INSTALL_ARCHIVES +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestArchiveLib := $(DESTDIR)$(PROJ_libdir)/lib$(LIBRARYNAME).a + +install-local:: $(DestArchiveLib) + +$(DestArchiveLib): $(LibName.A) $(DESTDIR)$(PROJ_libdir) + $(Echo) Installing $(BuildMode) Archive Library $(DestArchiveLib) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_libdir) + $(Verb) $(INSTALL) $(LibName.A) $(DestArchiveLib) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) Archive Library $(DestArchiveLib) + -$(Verb) $(RM) -f $(DestArchiveLib) +endif +endif +endif + +# endif LIBRARYNAME +endif + +############################################################################### +# Tool Build Rules: Build executable tool based on TOOLNAME option +############################################################################### + +ifdef TOOLNAME + +#--------------------------------------------------------- +# Set up variables for building a tool. +#--------------------------------------------------------- +TOOLEXENAME := $(strip $(TOOLNAME))$(EXEEXT) +ifdef EXAMPLE_TOOL +ToolBuildPath := $(ExmplDir)/$(TOOLEXENAME) +else +ToolBuildPath := $(ToolDir)/$(TOOLEXENAME) +endif + +# TOOLALIAS is a name to symlink (or copy) the tool to. +ifdef TOOLALIAS +ifdef EXAMPLE_TOOL +ToolAliasBuildPath := $(ExmplDir)/$(strip $(TOOLALIAS))$(EXEEXT) +else +ToolAliasBuildPath := $(ToolDir)/$(strip $(TOOLALIAS))$(EXEEXT) +endif +endif + +#--------------------------------------------------------- +# Prune Exports +#--------------------------------------------------------- + +# If the tool opts in with TOOL_NO_EXPORTS, optimize startup time of the app by +# not exporting all of the weak symbols from the binary. This reduces dyld +# startup time by 4x on darwin in some cases. +ifdef TOOL_NO_EXPORTS +ifeq ($(HOST_OS),Darwin) + +# Tiger tools don't support this. +ifneq ($(DARWIN_MAJVERS),4) +LD.Flags += -Wl,-exported_symbol,_main +endif +endif + +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux NetBSD FreeBSD)) +ifneq ($(ARCH), Mips) + LD.Flags += -Wl,--version-script=$(LLVM_SRC_ROOT)/autoconf/ExportMap.map +endif +endif +endif + +#--------------------------------------------------------- +# Tool Order File Support +#--------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) +ifdef TOOL_ORDER_FINE + +LD.Flags += -Wl,-order_file,$(TOOL_ORDER_FILE) + +endif +endif + +#--------------------------------------------------------- +# Tool Version Info Support +#--------------------------------------------------------- + +ifeq ($(HOST_OS),Darwin) +ifdef TOOL_INFO_PLIST + +LD.Flags += -Wl,-sectcreate,__TEXT,__info_plist,$(ObjDir)/$(TOOL_INFO_PLIST) + +$(ToolBuildPath): $(ObjDir)/$(TOOL_INFO_PLIST) + +$(ObjDir)/$(TOOL_INFO_PLIST): $(PROJ_SRC_DIR)/$(TOOL_INFO_PLIST).in $(ObjDir)/.dir + $(Echo) "Creating $(TOOLNAME) '$(TOOL_INFO_PLIST)' file..." + $(Verb)sed -e "s#@TOOL_INFO_UTI@#$(TOOL_INFO_UTI)#g" \ + -e "s#@TOOL_INFO_NAME@#$(TOOL_INFO_NAME)#g" \ + -e "s#@TOOL_INFO_VERSION@#$(TOOL_INFO_VERSION)#g" \ + -e "s#@TOOL_INFO_BUILD_VERSION@#$(TOOL_INFO_BUILD_VERSION)#g" \ + $< > $@ + +endif +endif + +#--------------------------------------------------------- +# Provide targets for building the tools +#--------------------------------------------------------- +all-local:: $(ToolBuildPath) $(ToolAliasBuildPath) + +clean-local:: +ifneq ($(strip $(ToolBuildPath)),) + -$(Verb) $(RM) -f $(ToolBuildPath) +endif +ifneq ($(strip $(ToolAliasBuildPath)),) + -$(Verb) $(RM) -f $(ToolAliasBuildPath) +endif + +ifdef EXAMPLE_TOOL +$(ToolBuildPath): $(ExmplDir)/.dir +else +$(ToolBuildPath): $(ToolDir)/.dir +endif + +$(ToolBuildPath): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) + $(Echo) Linking $(BuildMode) executable $(TOOLNAME) $(StripWarnMsg) + $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \ + $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS) + $(Echo) ======= Finished Linking $(BuildMode) Executable $(TOOLNAME) \ + $(StripWarnMsg) + +ifneq ($(strip $(ToolAliasBuildPath)),) +$(ToolAliasBuildPath): $(ToolBuildPath) + $(Echo) Creating $(BuildMode) Alias $(TOOLALIAS) $(StripWarnMsg) + $(Verb) $(RM) -f $(ToolAliasBuildPath) + $(Verb) $(AliasTool) $(TOOLEXENAME) $(ToolAliasBuildPath) + $(Echo) ======= Finished Creating $(BuildMode) Alias $(TOOLALIAS) \ + $(StripWarnMsg) +endif + +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +DestTool = $(DESTDIR)$(PROJ_bindir)/$(TOOLEXENAME) + +install-local:: $(DestTool) + +$(DestTool): $(ToolBuildPath) $(DESTDIR)$(PROJ_bindir) + $(Echo) Installing $(BuildMode) $(DestTool) + $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestTool) + -$(Verb) $(RM) -f $(DestTool) + +# TOOLALIAS install. +ifdef TOOLALIAS +DestToolAlias = $(DESTDIR)$(PROJ_bindir)/$(TOOLALIAS)$(EXEEXT) + +install-local:: $(DestToolAlias) + +$(DestToolAlias): $(DestTool) + $(Echo) Installing $(BuildMode) $(DestToolAlias) + $(Verb) $(RM) -f $(DestToolAlias) + $(Verb) $(AliasTool) $(TOOLEXENAME) $(DestToolAlias) + +uninstall-local:: + $(Echo) Uninstalling $(BuildMode) $(DestToolAlias) + -$(Verb) $(RM) -f $(DestToolAlias) +endif + +endif +endif + +############################################################################### +# Object Build Rules: Build object files based on sources +############################################################################### + +# FIXME: This should be checking for "if not GCC or ICC", not for "if HP-UX" +ifeq ($(HOST_OS),HP-UX) + DISABLE_AUTO_DEPENDENCIES=1 +endif + +# Provide rule sets for when dependency generation is enabled +ifndef DISABLE_AUTO_DEPENDENCIES + +#--------------------------------------------------------- +# Create .o files in the ObjDir directory from the .cpp and .c files... +#--------------------------------------------------------- + +DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.d.tmp" \ + -MT "$(ObjDir)/$*.o" -MT "$(ObjDir)/$*.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.d.tmp" "$(ObjDir)/$*.d"; \ + else $(RM) "$(ObjDir)/$*.d.tmp"; exit 1; fi + +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_MAKEFILE) + $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) + $(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \ + $(DEPEND_MOVEFILE) + +#--------------------------------------------------------- +# Create .bc files in the ObjDir directory from .cpp .cc and .c files... +#--------------------------------------------------------- + +BC_DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.bc.d.tmp" \ + -MT "$(ObjDir)/$*.ll" -MT "$(ObjDir)/$*.bc.d" + +# If the build succeeded, move the dependency file over, otherwise +# remove it. +BC_DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.bc.d.tmp" "$(ObjDir)/$*.bc.d"; \ + else $(RM) "$(ObjDir)/$*.bc.d.tmp"; exit 1; fi + +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -$(LLVMCC_EMITIR_FLAG) ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -$(LLVMCC_EMITIR_FLAG) ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -$(LLVMCC_EMITIR_FLAG) ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) + $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -$(LLVMCC_EMITIR_FLAG) ; \ + $(BC_DEPEND_MOVEFILE) + +$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) + $(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)" + $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ + $< -o $(ObjDir)/$*.ll -S -$(LLVMCC_EMITIR_FLAG) ; \ + $(BC_DEPEND_MOVEFILE) + +# Provide alternate rule sets if dependencies are disabled +else + +$(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ + +$(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ + +$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ + +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" + $(BCCompile.CXX) $< -o $@ -S -$(LLVMCC_EMITIR_FLAG) + +$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)" + $(BCCompile.CXX) $< -o $@ -S -$(LLVMCC_EMITIR_FLAG) + +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) + $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" + $(BCCompile.CXX) $< -o $@ -S -$(LLVMCC_EMITIR_FLAG) + +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) + $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" + $(BCCompile.C) $< -o $@ -S -$(LLVMCC_EMITIR_FLAG) + +$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) + $(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)" + $(BCCompile.C) $< -o $@ -S -$(LLVMCC_EMITIR_FLAG) + +endif + + +## Rules for building preprocessed (.i/.ii) outputs. +$(BuildMode)/%.ii: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.mm for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + +$(BuildMode)/%.i: %.m $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.m for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + + +$(ObjDir)/%.s: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.mm to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.CXX) $< -o $@ -S + +$(ObjDir)/%.s: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ -S + +$(ObjDir)/%.s: %.m $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.m to asm for $(BuildMode) build" $(PIC_FLAG) + $(Compile.C) $< -o $@ -S + + +# make the C and C++ compilers strip debug info out of bytecode libraries. +ifdef DEBUG_RUNTIME +$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) + $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" + $(Verb) $(LOPT) $< -std-compile-opts -o $@ +else +$(ObjectsBC): $(ObjDir)/%.bc: $(ObjDir)/%.ll $(LOPT) + $(Echo) "Compiling $*.ll to $*.bc for $(BuildMode) build (bytecode)" + $(Verb) $(LOPT) $< -std-compile-opts -strip-debug -o $@ +endif + + +#--------------------------------------------------------- +# Provide rule to build .bc files from .ll sources, +# regardless of dependencies +#--------------------------------------------------------- +$(ObjDir)/%.bc: %.ll $(ObjDir)/.dir $(LLVMAS) + $(Echo) "Compiling $*.ll for $(BuildMode) build" + $(Verb) $(LLVMAS) $< -f -o $@ + +############################################################################### +# TABLEGEN: Provide rules for running tblgen to produce *.inc files +############################################################################### + +ifdef TARGET +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef LLVMC_BASED_DRIVER +TABLEGEN_INC_FILES_COMMON = 1 +endif + +ifdef TABLEGEN_INC_FILES_COMMON + +INCFiles := $(filter %.inc,$(BUILT_SOURCES)) +INCTMPFiles := $(INCFiles:%=$(ObjDir)/%.tmp) +.PRECIOUS: $(INCTMPFiles) $(INCFiles) + +# INCFiles rule: All of the tblgen generated files are emitted to +# $(ObjDir)/%.inc.tmp, instead of emitting them directly to %.inc. This allows +# us to only "touch" the real file if the contents of it change. IOW, if +# tblgen is modified, all of the .inc.tmp files are regenerated, but no +# dependencies of the .inc files are, unless the contents of the .inc file +# changes. +$(INCFiles) : %.inc : $(ObjDir)/%.inc.tmp + $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ + +endif # TABLEGEN_INC_FILES_COMMON + +ifdef TARGET + +TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \ + $(LLVM_SRC_ROOT)/include/llvm/Target/Target.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetCallingConv.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSchedule.td \ + $(LLVM_SRC_ROOT)/include/llvm/Target/TargetSelectionDAG.td \ + $(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \ + $(wildcard $(LLVM_SRC_ROOT)/include/llvm/Intrinsics*.td) + +# All of these files depend on tblgen and the .td files. +$(INCTMPFiles) : $(TBLGEN) $(TDFiles) + +$(TARGET:%=$(ObjDir)/%GenRegisterNames.inc.tmp): \ +$(ObjDir)/%GenRegisterNames.inc.tmp : %.td $(ObjDir)/.dir + $(Echo) "Building $( $@ +else +%.ps: %.dot + $(Echo) "Cannot build $@: The program dot is not installed" +endif + +# This rules ensures that header files that are removed still have a rule for +# which they can be "generated." This allows make to ignore them and +# reproduce the dependency lists. +%.h:: ; +%.hpp:: ; + +# Define clean-local to clean the current directory. Note that this uses a +# very conservative approach ensuring that empty variables do not cause +# errors or disastrous removal. +clean-local:: +ifneq ($(strip $(ObjRootDir)),) + -$(Verb) $(RM) -rf $(ObjRootDir) +endif + -$(Verb) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc +ifneq ($(strip $(SHLIBEXT)),) # Extra paranoia - make real sure SHLIBEXT is set + -$(Verb) $(RM) -f *$(SHLIBEXT) +endif + +clean-all-local:: + -$(Verb) $(RM) -rf Debug Release Profile + + +############################################################################### +# DEPENDENCIES: Include the dependency files if we should +############################################################################### +ifndef DISABLE_AUTO_DEPENDENCIES + +# If its not one of the cleaning targets +ifndef IS_CLEANING_TARGET + +# Get the list of dependency files +DependSourceFiles := $(basename $(filter %.cpp %.c %.cc %.m %.mm, $(Sources))) +DependFiles := $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.d) + +# Include bitcode dependency files if using bitcode libraries +ifdef BYTECODE_LIBRARY +DependFiles += $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.bc.d) +endif + +-include $(DependFiles) "" + +endif + +endif + +############################################################################### +# CHECK: Running the test suite +############################################################################### + +check:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local \ + TESTSUITE=$(TESTSUITE) ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +check-lit:: check + +check-dg:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local-dg ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +check-all:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/test" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/test/Makefile" ; then \ + $(EchoCmd) Running test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/test check-local-all ; \ + else \ + $(EchoCmd) No Makefile in test directory ; \ + fi ; \ + else \ + $(EchoCmd) No test directory ; \ + fi + +############################################################################### +# UNITTESTS: Running the unittests test suite +############################################################################### + +unittests:: + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/unittests" ; then \ + if test -f "$(PROJ_OBJ_ROOT)/unittests/Makefile" ; then \ + $(EchoCmd) Running unittests test suite ; \ + $(MAKE) -C $(PROJ_OBJ_ROOT)/unittests unitcheck; \ + else \ + $(EchoCmd) No Makefile in unittests directory ; \ + fi ; \ + else \ + $(EchoCmd) No unittests directory ; \ + fi + +############################################################################### +# DISTRIBUTION: Handle construction of a distribution tarball +############################################################################### + +#------------------------------------------------------------------------ +# Define distribution related variables +#------------------------------------------------------------------------ +DistName := $(PROJECT_NAME)-$(PROJ_VERSION) +DistDir := $(PROJ_OBJ_ROOT)/$(DistName) +TopDistDir := $(PROJ_OBJ_ROOT)/$(DistName) +DistTarGZip := $(PROJ_OBJ_ROOT)/$(DistName).tar.gz +DistZip := $(PROJ_OBJ_ROOT)/$(DistName).zip +DistTarBZ2 := $(PROJ_OBJ_ROOT)/$(DistName).tar.bz2 +DistAlways := CREDITS.TXT LICENSE.TXT README.txt README AUTHORS COPYING \ + ChangeLog INSTALL NEWS Makefile Makefile.common Makefile.rules \ + Makefile.config.in configure autoconf +DistOther := $(notdir $(wildcard \ + $(PROJ_SRC_DIR)/*.h \ + $(PROJ_SRC_DIR)/*.td \ + $(PROJ_SRC_DIR)/*.def \ + $(PROJ_SRC_DIR)/*.ll \ + $(PROJ_SRC_DIR)/*.in)) +DistSubDirs := $(SubDirs) +DistSources = $(Sources) $(EXTRA_DIST) +DistFiles = $(DistAlways) $(DistSources) $(DistOther) + +#------------------------------------------------------------------------ +# We MUST build distribution with OBJ_DIR != SRC_DIR +#------------------------------------------------------------------------ +ifeq ($(PROJ_SRC_DIR),$(PROJ_OBJ_DIR)) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: Target $@ only available with OBJ_DIR != SRC_DIR + +else + +#------------------------------------------------------------------------ +# Prevent attempt to run dist targets from anywhere but the top level +#------------------------------------------------------------------------ +ifneq ($(LEVEL),.) +dist dist-check dist-clean dist-gzip dist-bzip2 dist-zip :: + $(Echo) ERROR: You must run $@ from $(PROJ_OBJ_ROOT) +else + +#------------------------------------------------------------------------ +# Provide the top level targets +#------------------------------------------------------------------------ + +dist-gzip:: $(DistTarGZip) + +$(DistTarGZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing gzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - "$(DistName)" | \ + $(GZIP) -c > "$(DistTarGZip)" + +dist-bzip2:: $(DistTarBZ2) + +$(DistTarBZ2) : $(TopDistDir)/.makedistdir + $(Echo) Packing bzipped distribution tar file. + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(TAR) chf - $(DistName) | \ + $(BZIP2) -c >$(DistTarBZ2) + +dist-zip:: $(DistZip) + +$(DistZip) : $(TopDistDir)/.makedistdir + $(Echo) Packing zipped distribution file. + $(Verb) rm -f $(DistZip) + $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ZIP) -rq $(DistZip) $(DistName) + +dist :: $(DistTarGZip) $(DistTarBZ2) $(DistZip) + $(Echo) ===== DISTRIBUTION PACKAGING SUCESSFUL ===== + +DistCheckDir := $(PROJ_OBJ_ROOT)/_distcheckdir + +dist-check:: $(DistTarGZip) + $(Echo) Checking distribution tar file. + $(Verb) if test -d $(DistCheckDir) ; then \ + $(RM) -rf $(DistCheckDir) ; \ + fi + $(Verb) $(MKDIR) $(DistCheckDir) + $(Verb) cd $(DistCheckDir) && \ + $(MKDIR) $(DistCheckDir)/build && \ + $(MKDIR) $(DistCheckDir)/install && \ + gunzip -c $(DistTarGZip) | $(TAR) xf - && \ + cd build && \ + ../$(DistName)/configure --prefix="$(DistCheckDir)/install" \ + --srcdir=../$(DistName) $(DIST_CHECK_CONFIG_OPTIONS) && \ + $(MAKE) all && \ + $(MAKE) check && \ + $(MAKE) unittests && \ + $(MAKE) install && \ + $(MAKE) uninstall && \ + $(MAKE) dist-clean && \ + $(EchoCmd) ===== $(DistTarGZip) Ready For Distribution ===== + +dist-clean:: + $(Echo) Cleaning distribution files + -$(Verb) $(RM) -rf $(DistTarGZip) $(DistTarBZ2) $(DistZip) $(DistName) \ + $(DistCheckDir) + +endif + +#------------------------------------------------------------------------ +# Provide the recursive distdir target for building the distribution directory +#------------------------------------------------------------------------ +distdir: $(DistDir)/.makedistdir +$(DistDir)/.makedistdir: $(DistSources) + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + if test -d "$(DistDir)" ; then \ + find $(DistDir) -type d ! -perm -200 -exec chmod u+w {} ';' || \ + exit 1 ; \ + fi ; \ + $(EchoCmd) Removing old $(DistDir) ; \ + $(RM) -rf $(DistDir); \ + $(EchoCmd) Making 'all' to verify build ; \ + $(MAKE) ENABLE_OPTIMIZED=1 all ; \ + fi + $(Echo) Building Distribution Directory $(DistDir) + $(Verb) $(MKDIR) $(DistDir) + $(Verb) srcdirstrip=`echo "$(PROJ_SRC_DIR)" | sed 's|.|.|g'`; \ + srcrootstrip=`echo "$(PROJ_SRC_ROOT)" | sed 's|.|.|g'`; \ + for file in $(DistFiles) ; do \ + case "$$file" in \ + $(PROJ_SRC_DIR)/*) \ + file=`echo "$$file" | sed "s#^$$srcdirstrip/##"` \ + ;; \ + $(PROJ_SRC_ROOT)/*) \ + file=`echo "$$file" | \ + sed "s#^$$srcrootstrip/##"` \ + ;; \ + esac; \ + if test -f "$(PROJ_SRC_DIR)/$$file" || \ + test -d "$(PROJ_SRC_DIR)/$$file" ; then \ + from_dir="$(PROJ_SRC_DIR)" ; \ + elif test -f "$$file" || test -d "$$file" ; then \ + from_dir=. ; \ + fi ; \ + to_dir=`echo "$$file" | sed -e 's#/[^/]*$$##'` ; \ + if test "$$to_dir" != "$$file" && test "$$to_dir" != "."; then \ + to_dir="$(DistDir)/$$dir"; \ + $(MKDIR) "$$to_dir" ; \ + else \ + to_dir="$(DistDir)"; \ + fi; \ + mid_dir=`echo "$$file" | sed -n -e 's#^\(.*\)/[^/]*$$#\1#p'`; \ + if test -n "$$mid_dir" ; then \ + $(MKDIR) "$$to_dir/$$mid_dir" || exit 1; \ + fi ; \ + if test -d "$$from_dir/$$file"; then \ + if test -d "$(PROJ_SRC_DIR)/$$file" && \ + test "$$from_dir" != "$(PROJ_SRC_DIR)" ; then \ + cd $(PROJ_SRC_DIR) ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + else \ + cd $$from_dir ; \ + $(TAR) cf - $$file --exclude .svn --exclude CVS | \ + ( cd $$to_dir ; $(TAR) xf - ) ; \ + cd $(PROJ_OBJ_DIR) ; \ + fi; \ + elif test -f "$$from_dir/$$file" ; then \ + $(CP) -p "$$from_dir/$$file" "$(DistDir)/$$file" || exit 1; \ + elif test -L "$$from_dir/$$file" ; then \ + $(CP) -pd "$$from_dir/$$file" $(DistDir)/$$file || exit 1; \ + elif echo "$(DistAlways)" | grep -v "$$file" >/dev/null ; then \ + $(EchoCmd) "===== WARNING: Distribution Source " \ + "$$from_dir/$$file Not Found!" ; \ + elif test "$(Verb)" != '@' ; then \ + $(EchoCmd) "Skipping non-existent $$from_dir/$$file" ; \ + fi; \ + done + $(Verb) for subdir in $(DistSubDirs) ; do \ + if test "$$subdir" \!= "." ; then \ + new_distdir="$(DistDir)/$$subdir" ; \ + test -d "$$new_distdir" || $(MKDIR) "$$new_distdir" || exit 1; \ + ( cd $$subdir && $(MAKE) ENABLE_OPTIMIZED=1 \ + DistDir="$$new_distdir" distdir ) || exit 1; \ + fi; \ + done + $(Verb) if test "$(DistDir)" = "$(TopDistDir)" ; then \ + $(EchoCmd) Eliminating CVS/.svn directories from distribution ; \ + $(RM) -rf `find $(TopDistDir) -type d \( -name CVS -o \ + -name .svn \) -print` ;\ + $(MAKE) dist-hook ; \ + $(FIND) $(TopDistDir) -type d ! -perm -777 -exec chmod a+rwx {} \; \ + -o ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -400 -exec chmod a+r {} \; \ + -o ! -type d ! -perm -444 -exec \ + $(SHELL) $(INSTALL_SH) -c -m a+r {} {} \; \ + || chmod -R a+r $(DistDir) ; \ + fi + +# This is invoked by distdir target, define it as a no-op to avoid errors if not +# defined by user. +dist-hook:: + +endif + +############################################################################### +# TOP LEVEL - targets only to apply at the top level directory +############################################################################### + +ifeq ($(LEVEL),.) + +#------------------------------------------------------------------------ +# Install support for the project's include files: +#------------------------------------------------------------------------ +ifdef NO_INSTALL +install-local:: + $(Echo) Install circumvented with NO_INSTALL +uninstall-local:: + $(Echo) Uninstall circumvented with NO_INSTALL +else +install-local:: + $(Echo) Installing include files + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) + $(Verb) if test -d "$(PROJ_SRC_ROOT)/include" ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + for hdr in `find . -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + -o -name '*.td' \ + ')' -print | grep -v CVS | \ + grep -v .svn` ; do \ + instdir=`dirname "$(DESTDIR)$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) + $(Verb) if test -d "$(PROJ_OBJ_ROOT)/include" ; then \ + cd $(PROJ_OBJ_ROOT)/include && \ + for hdr in `find . -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + -o -name '*.td' \ + ')' -print | grep -v CVS | \ + grep -v .svn` ; do \ + instdir=`dirname "$(DESTDIR)$(PROJ_includedir)/$$hdr"` ; \ + if test \! -d "$$instdir" ; then \ + $(EchoCmd) Making install directory $$instdir ; \ + $(MKDIR) $$instdir ;\ + fi ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ + done ; \ + fi +endif + +uninstall-local:: + $(Echo) Uninstalling include files + $(Verb) if [ -d "$(PROJ_SRC_ROOT)/include" ] ; then \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f \ + '!' '(' -name '*~' -o -name '.#*' \ + -o -name '*.in' ')' -print ')' | \ + grep -v CVS | sed 's#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ + cd $(PROJ_SRC_ROOT)/include && \ + $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f -name '*.in' \ + -print ')' | sed 's#\.in$$##;s#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ + fi +endif +endif + +check-line-length: + @echo searching for overlength lines in files: $(Sources) + @echo + @echo + egrep -n '.{81}' $(Sources) /dev/null + +check-for-tabs: + @echo searching for tabs in files: $(Sources) + @echo + @echo + egrep -n ' ' $(Sources) /dev/null + +check-footprint: + @ls -l $(LibDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Libraries: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' + @ls -l $(ToolDir) | awk '\ + BEGIN { sum = 0; } \ + { sum += $$5; } \ + END { printf("Programs: %6.3f MBytes\n", sum/(1024.0*1024.0)); }' +#------------------------------------------------------------------------ +# Print out the directories used for building +#------------------------------------------------------------------------ +printvars:: + $(Echo) "BuildMode : " '$(BuildMode)' + $(Echo) "PROJ_SRC_ROOT: " '$(PROJ_SRC_ROOT)' + $(Echo) "PROJ_SRC_DIR : " '$(PROJ_SRC_DIR)' + $(Echo) "PROJ_OBJ_ROOT: " '$(PROJ_OBJ_ROOT)' + $(Echo) "PROJ_OBJ_DIR : " '$(PROJ_OBJ_DIR)' + $(Echo) "LLVM_SRC_ROOT: " '$(LLVM_SRC_ROOT)' + $(Echo) "LLVM_OBJ_ROOT: " '$(LLVM_OBJ_ROOT)' + $(Echo) "PROJ_prefix : " '$(PROJ_prefix)' + $(Echo) "PROJ_bindir : " '$(PROJ_bindir)' + $(Echo) "PROJ_libdir : " '$(PROJ_libdir)' + $(Echo) "PROJ_etcdir : " '$(PROJ_etcdir)' + $(Echo) "PROJ_includedir : " '$(PROJ_includedir)' + $(Echo) "UserTargets : " '$(UserTargets)' + $(Echo) "ObjMakefiles : " '$(ObjMakefiles)' + $(Echo) "SrcMakefiles : " '$(SrcMakefiles)' + $(Echo) "ObjDir : " '$(ObjDir)' + $(Echo) "LibDir : " '$(LibDir)' + $(Echo) "ToolDir : " '$(ToolDir)' + $(Echo) "ExmplDir : " '$(ExmplDir)' + $(Echo) "Sources : " '$(Sources)' + $(Echo) "TDFiles : " '$(TDFiles)' + $(Echo) "INCFiles : " '$(INCFiles)' + $(Echo) "INCTMPFiles : " '$(INCTMPFiles)' + $(Echo) "PreConditions: " '$(PreConditions)' + $(Echo) "Compile.CXX : " '$(Compile.CXX)' + $(Echo) "Compile.C : " '$(Compile.C)' + $(Echo) "Archive : " '$(Archive)' + $(Echo) "YaccFiles : " '$(YaccFiles)' + $(Echo) "LexFiles : " '$(LexFiles)' + $(Echo) "Module : " '$(Module)' + $(Echo) "FilesToConfig: " '$(FilesToConfigPATH)' + $(Echo) "SubDirs : " '$(SubDirs)' + $(Echo) "ProjLibsPaths: " '$(ProjLibsPaths)' + $(Echo) "ProjLibsOptions: " '$(ProjLibsOptions)' + +### +# Debugging + +# General debugging rule, use 'make dbg-print-XXX' to print the +# definition, value and origin of XXX. +make-print-%: + $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) diff --git a/final/ModuleInfo.txt b/final/ModuleInfo.txt new file mode 100644 index 00000000000..40607c71a94 --- /dev/null +++ b/final/ModuleInfo.txt @@ -0,0 +1,4 @@ +DepModule: +BuildCmd: ./build-for-llvm-top.sh +CleanCmd: make clean -C ../build.llvm +InstallCmd: make install -C ../build.llvm diff --git a/final/README.txt b/final/README.txt new file mode 100644 index 00000000000..0dad9f5e0a6 --- /dev/null +++ b/final/README.txt @@ -0,0 +1,16 @@ +Low Level Virtual Machine (LLVM) +================================ + +This directory and its subdirectories contain source code for the Low Level +Virtual Machine, a toolkit for the construction of highly optimized compilers, +optimizers, and runtime environments. + +LLVM is open source software. You may freely distribute it under the terms of +the license agreement found in LICENSE.txt. + +Please see the HTML documentation provided in docs/index.html for further +assistance with LLVM. + +If you're writing a package for LLVM, see docs/Packaging.html for our +suggestions. + diff --git a/final/autoconf/AutoRegen.sh b/final/autoconf/AutoRegen.sh new file mode 100755 index 00000000000..7809667ac5f --- /dev/null +++ b/final/autoconf/AutoRegen.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +die() { + echo "$@" 1>&2 + exit 1 +} + +clean() { + echo $1 | sed -e 's/\\//g' +} + +### NOTE: ############################################################ +### These variables specify the tool versions we want to use. +### Periods should be escaped with backslash for use by grep. +### +### If you update these, please also update docs/GettingStarted.html +want_autoconf_version='2\.60' +want_autoheader_version=$want_autoconf_version +want_aclocal_version='1\.9\.6' +want_libtool_version='1\.5\.22' +### END NOTE ######################################################### + +outfile=configure +configfile=configure.ac + +want_autoconf_version_clean=$(clean $want_autoconf_version) +want_autoheader_version_clean=$(clean $want_autoheader_version) +want_aclocal_version_clean=$(clean $want_aclocal_version) +want_libtool_version_clean=$(clean $want_libtool_version) + +test -d autoconf && test -f autoconf/$configfile && cd autoconf +test -f $configfile || die "Can't find 'autoconf' dir; please cd into it first" +autoconf --version | grep $want_autoconf_version > /dev/null +test $? -eq 0 || die "Your autoconf was not detected as being $want_autoconf_version_clean" +aclocal --version | grep '^aclocal.*'$want_aclocal_version > /dev/null +test $? -eq 0 || die "Your aclocal was not detected as being $want_aclocal_version_clean" +autoheader --version | grep '^autoheader.*'$want_autoheader_version > /dev/null +test $? -eq 0 || die "Your autoheader was not detected as being $want_autoheader_version_clean" +libtool --version | grep $want_libtool_version > /dev/null +test $? -eq 0 || die "Your libtool was not detected as being $want_libtool_version_clean" +echo "" +echo "### NOTE: ############################################################" +echo "### If you get *any* warnings from autoconf below you MUST fix the" +echo "### scripts in the m4 directory because there are future forward" +echo "### compatibility or platform support issues at risk. Please do NOT" +echo "### commit any configure script that was generated with warnings" +echo "### present. You should get just three 'Regenerating..' lines." +echo "######################################################################" +echo "" +echo "Regenerating aclocal.m4 with aclocal $want_aclocal_version_clean" +cwd=`pwd` +aclocal --force -I $cwd/m4 || die "aclocal failed" +echo "Regenerating configure with autoconf $want_autoconf_version_clean" +autoconf --force --warnings=all -o ../$outfile $configfile || die "autoconf failed" +cd .. +echo "Regenerating config.h.in with autoheader $want_autoheader_version_clean" +autoheader --warnings=all -I autoconf -I autoconf/m4 autoconf/$configfile || die "autoheader failed" +exit 0 diff --git a/final/autoconf/ExportMap.map b/final/autoconf/ExportMap.map new file mode 100644 index 00000000000..17b185fed91 --- /dev/null +++ b/final/autoconf/ExportMap.map @@ -0,0 +1,7 @@ +{ + global: main; + __progname; + environ; + + local: *; +}; diff --git a/final/autoconf/LICENSE.TXT b/final/autoconf/LICENSE.TXT new file mode 100644 index 00000000000..72fdd39edcc --- /dev/null +++ b/final/autoconf/LICENSE.TXT @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------ +Autoconf Files +------------------------------------------------------------------------------ +All autoconf files are licensed under the LLVM license with the following +additions: + +llvm/autoconf/install-sh: + This script is licensed under the LLVM license, with the following + additional copyrights and restrictions: + + Copyright 1991 by the Massachusetts Institute of Technology + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation, and that the name of M.I.T. not be used in advertising or + publicity pertaining to distribution of the software without specific, + written prior permission. M.I.T. makes no representations about the + suitability of this software for any purpose. It is provided "as is" + without express or implied warranty. + +Please see the source files for additional copyrights. + diff --git a/final/autoconf/README.TXT b/final/autoconf/README.TXT new file mode 100644 index 00000000000..3dabdf7b879 --- /dev/null +++ b/final/autoconf/README.TXT @@ -0,0 +1,49 @@ +Upgrading Libtool +=============================================================================== + +If you are in the mood to upgrade libtool, you must do the following: + + 1. Get the new version of libtool and put it in + 2. configure/build/install libtool with --prefix= + 3. Copy /ltdl.m4 to llvm/autoconf/m4 + 4. Copy /share/aclocal/libtool.m4 to llvm/autoconf/m4/libtool.m4 + 5. Copy /share/libtool/ltmain.sh to llvm/autoconf/ltmain.sh + 6. Copy /share/libtool/libltdl/ltdl.c to llvm/lib/System + 7. Copy /share/libtool/libltdl/ltdl.h to llvm/lib/System + 8. Edit the ltdl.h file to #include "llvm/Config/config.h" at the very top. You + might also need to resolve some compiler warnings (typically about + comparison of signed vs. unsigned values). But, you won't find out about + those until you build LLVM (step 13). + 9. Edit the llvm/autoconf/m4/libtool.m4 file so that: + a) in AC_PROB_LIBTOOL macro, the value of LIBTOOL is set to + $(top_builddir)/mklib, not $(top_builddir)/libtool + b) in AC_LIBTOOL_SETUP macro, the variable default_ofile is set to + "mklib" instead of "libtool" + c) s/AC_ENABLE_SHARED_DEFAULT/enable_shared_default/g + d) s/AC_ENABLE_STATIC_DEFAULT/enable_static_default/g + e) s/AC_ENABLE_FAST_INSTALL_DEFAULT/enable_fast_install_default/g +10. Run "autoupdate libtool.m4 ltdl.m4" in the llvm/autoconf/m4 directory. + This should correctly update the macro definitions in the libtool m4 + files to match the version of autoconf that LLVM uses. This converts + AC_HELP_STRING to AS_HELP_STRING and AC_TRY_LINK to AC_LINK_IFELSE, amongst + other things. You may need to manually adjust the files. +11. Run AutoRegen.sh to get the new macros into configure script +12. If there are any warnings from AutoRegen.sh, go to step 9. +13. Rebuild LLVM, making sure it reconfigures +14. Test the JIT which uses libltdl +15. If it all works, only THEN commit the changes. + +Upgrading autoconf +=============================================================================== + +If you are in the mood to upgrade autoconf, you should: + + 1. Consider not upgrading. + 2. No really, this is a hassle, you don't want to do it. + 3. Get the new version of autoconf and put it in + 4. configure/build/install autoconf with --prefix= + 5. Run autoupdate on all the m4 macros in llvm/autoconf/m4 + 6. Run autoupdate on llvm/autoconf/configure.ac + 7. Regenerate configure script with AutoRegen.sh + 8. If there are any warnings from AutoRegen.sh, fix them and go to step 7. + 9. Test, test, test. diff --git a/final/autoconf/config.guess b/final/autoconf/config.guess new file mode 100755 index 00000000000..865fe53d6b1 --- /dev/null +++ b/final/autoconf/config.guess @@ -0,0 +1,1498 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-09-18' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + AUX_ARCH="i386" + echo ${AUX_ARCH}-pc-auroraux`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/final/autoconf/config.sub b/final/autoconf/config.sub new file mode 100755 index 00000000000..183976a066a --- /dev/null +++ b/final/autoconf/config.sub @@ -0,0 +1,1702 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-08-19' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -auroraux) + os=-auroraux + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/final/autoconf/configure.ac b/final/autoconf/configure.ac new file mode 100644 index 00000000000..27d9bd4949f --- /dev/null +++ b/final/autoconf/configure.ac @@ -0,0 +1,1724 @@ +dnl === configure.ac --------------------------------------------------------=== +dnl The LLVM Compiler Infrastructure +dnl +dnl This file is distributed under the University of Illinois Open Source +dnl License. See LICENSE.TXT for details. +dnl +dnl===-----------------------------------------------------------------------=== +dnl This is the LLVM configuration script. It is processed by the autoconf +dnl program to produce a script named configure. This script contains the +dnl configuration checks that LLVM needs in order to support multiple platforms. +dnl This file is composed of 10 sections per the recommended organization of +dnl autoconf input defined in the autoconf documentation. As this file evolves, +dnl please keep the various types of checks within their sections. The sections +dnl are as follows: +dnl +dnl SECTION 1: Initialization & Setup +dnl SECTION 2: Architecture, target, and host checks +dnl SECTION 3: Command line arguments for the configure script. +dnl SECTION 4: Check for programs we need and that they are the right version +dnl SECTION 5: Check for libraries +dnl SECTION 6: Check for header files +dnl SECTION 7: Check for types and structures +dnl SECTION 8: Check for specific functions needed +dnl SECTION 9: Additional checks, variables, etc. +dnl SECTION 10: Specify the output files and generate it +dnl +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 1: Initialization & Setup +dnl=== +dnl===-----------------------------------------------------------------------=== +dnl Initialize autoconf and define the package name, version number and +dnl email address for reporting bugs. +AC_INIT([[llvm]],[[2.9]],[llvmbugs@cs.uiuc.edu]) + +dnl Provide a copyright substitution and ensure the copyright notice is included +dnl in the output of --version option of the generated configure script. +AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign."]) +AC_COPYRIGHT([Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.]) + +dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we +dnl use some autoconf macros only available in 2.59. +AC_PREREQ(2.59) + +dnl Verify that the source directory is valid. This makes sure that we are +dnl configuring LLVM and not some other package (it validates --srcdir argument) +AC_CONFIG_SRCDIR([lib/VMCore/Module.cpp]) + +dnl Place all of the extra autoconf files into the config subdirectory. Tell +dnl various tools where the m4 autoconf macros are. +AC_CONFIG_AUX_DIR([autoconf]) + +dnl Quit if the source directory has already been configured. +dnl NOTE: This relies upon undocumented autoconf behavior. +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + AC_MSG_ERROR([Already configured in ${srcdir}]) + fi +fi + +dnl Configure all of the projects present in our source tree. While we could +dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a +dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated. +dnl Instead we match on the known projects. + +dnl +dnl One tricky part of doing this is that some projects depend upon other +dnl projects. For example, several projects rely upon the LLVM test suite. +dnl We want to configure those projects first so that their object trees are +dnl created before running the configure scripts of projects that depend upon +dnl them. +dnl + +dnl Several projects use llvm-gcc, so configure that first +if test -d ${srcdir}/projects/llvm-gcc ; then + AC_CONFIG_SUBDIRS([projects/llvm-gcc]) +fi + +dnl Several projects use the LLVM test suite, so configure it next. +if test -d ${srcdir}/projects/test-suite ; then + AC_CONFIG_SUBDIRS([projects/test-suite]) +fi + +dnl llvm-test is the old name of the test-suite, kept here for backwards +dnl compatibility +if test -d ${srcdir}/projects/llvm-test ; then + AC_CONFIG_SUBDIRS([projects/llvm-test]) +fi + +dnl Some projects use poolalloc; configure that next +if test -d ${srcdir}/projects/poolalloc ; then + AC_CONFIG_SUBDIRS([projects/poolalloc]) +fi + +if test -d ${srcdir}/projects/llvm-poolalloc ; then + AC_CONFIG_SUBDIRS([projects/llvm-poolalloc]) +fi + +dnl Check for all other projects +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + sample) AC_CONFIG_SUBDIRS([projects/sample]) ;; + privbracket) AC_CONFIG_SUBDIRS([projects/privbracket]) ;; + llvm-stacker) AC_CONFIG_SUBDIRS([projects/llvm-stacker]) ;; + llvm-reopt) AC_CONFIG_SUBDIRS([projects/llvm-reopt]);; + llvm-java) AC_CONFIG_SUBDIRS([projects/llvm-java]) ;; + llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;; + safecode) AC_CONFIG_SUBDIRS([projects/safecode]) ;; + llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;; + llvm-gcc) ;; + test-suite) ;; + llvm-test) ;; + poolalloc) ;; + llvm-poolalloc) ;; + *) + AC_MSG_WARN([Unknown project (${i}) won't be configured automatically]) + ;; + esac + fi +done + +dnl Disable the build of polly, even if it is checked out into tools/polly. +AC_ARG_ENABLE(polly, + AS_HELP_STRING([--enable-polly], + [Use polly if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_POLLY,[1]) ;; + no) AC_SUBST(ENABLE_POLLY,[0]) ;; + default) AC_SUBST(ENABLE_POLLY,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-polly. Use "yes" or "no"]) ;; +esac + + +dnl Check if polly is checked out into tools/polly and configure it if +dnl available. +if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then + AC_SUBST(LLVM_HAS_POLLY,1) + AC_CONFIG_SUBDIRS([tools/polly]) +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 2: Architecture, target, and host checks +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Check the target for which we're compiling and the host that will do the +dnl compilations. This will tell us which LLVM compiler will be used for +dnl compiling SSA into object code. This needs to be done early because +dnl following tests depend on it. +AC_CANONICAL_TARGET + +dnl Determine the platform type and cache its value. This helps us configure +dnl the System library to the correct build platform. +AC_CACHE_CHECK([type of operating system we're going to host on], + [llvm_cv_os_type], +[case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-minix*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Minix" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac]) + +AC_CACHE_CHECK([type of operating system we're going to target], + [llvm_cv_target_os_type], +[case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-minix*) + llvm_cv_target_os_type="Minix" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac]) + +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_os_type" = "Unknown" ; then + AC_MSG_ERROR([Operating system is unknown, configure can't continue]) +fi + +dnl Set the "OS" Makefile variable based on the platform type so the +dnl makefile can configure itself to specific build hosts +AC_SUBST(OS,$llvm_cv_os_type) +AC_SUBST(HOST_OS,$llvm_cv_os_type) +AC_SUBST(TARGET_OS,$llvm_cv_target_os_type) + +dnl Set the LINKALL and NOLINKALL Makefile variables based on the platform +AC_SUBST(LINKALL,$llvm_cv_link_all_option) +AC_SUBST(NOLINKALL,$llvm_cv_no_link_all_option) + +dnl Set the "LLVM_ON_*" variables based on llvm_cv_platform_type +dnl This is used by lib/Support to determine the basic kind of implementation +dnl to use. +case $llvm_cv_platform_type in + Unix) + AC_DEFINE([LLVM_ON_UNIX],[1],[Define if this is Unixish platform]) + AC_SUBST(LLVM_ON_UNIX,[1]) + AC_SUBST(LLVM_ON_WIN32,[0]) + ;; + Win32) + AC_DEFINE([LLVM_ON_WIN32],[1],[Define if this is Win32ish platform]) + AC_SUBST(LLVM_ON_UNIX,[0]) + AC_SUBST(LLVM_ON_WIN32,[1]) + ;; +esac + +dnl Determine what our target architecture is and configure accordingly. +dnl This will allow Makefiles to make a distinction between the hardware and +dnl the OS. +AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], +[case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + alpha*-*) llvm_cv_target_arch="Alpha" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + mips-*) llvm_cv_target_arch="Mips" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + bfin-*) llvm_cv_target_arch="Blackfin" ;; + mblaze-*) llvm_cv_target_arch="MBlaze" ;; + ptx-*) llvm_cv_target_arch="PTX" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac]) + +if test "$llvm_cv_target_arch" = "Unknown" ; then + AC_MSG_WARN([Configuring LLVM for an unknown target archicture]) +fi + +# Determine the LLVM native architecture for the target +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +dnl Define a substitution, ARCH, for the target architecture +AC_SUBST(ARCH,$llvm_cv_target_arch) + +dnl Check for the endianness of the target +AC_C_BIGENDIAN(AC_SUBST([ENDIAN],[big]),AC_SUBST([ENDIAN],[little])) + +dnl Check for build platform executable suffix if we're crosscompiling +if test "$cross_compiling" = yes; then + AC_SUBST(LLVM_CROSS_COMPILING, [1]) + AC_BUILD_EXEEXT + ac_build_prefix=${build_alias}- + AC_CHECK_PROG(BUILD_CXX, ${ac_build_prefix}g++, ${ac_build_prefix}g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, g++, g++) + if test -z "$BUILD_CXX"; then + AC_CHECK_PROG(BUILD_CXX, c++, c++, , , /usr/ucb/c++) + fi + fi +else + AC_SUBST(LLVM_CROSS_COMPILING, [0]) +fi + +dnl Check to see if there's a .svn or .git directory indicating that this +dnl build is being done from a checkout. This sets up several defaults for +dnl the command line switches. When we build with a checkout directory, +dnl we get a debug with assertions turned on. Without, we assume a source +dnl release and we get an optimized build without assertions. +dnl See --enable-optimized and --enable-assertions below +if test -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + AC_SUBST(CVSBUILD,[[CVSBUILD=1]]) +else + cvsbuild="no" + optimize="yes" +fi + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 3: Command line arguments for the configure script. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl --enable-optimized : check whether they want to do an optimized build: +AC_ARG_ENABLE(optimized, AS_HELP_STRING( + --enable-optimized,[Compile with optimizations enabled (default is YES)]),,enableval=$optimize) +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_OPTIMIZED,[[]]) +else + AC_SUBST(ENABLE_OPTIMIZED,[[ENABLE_OPTIMIZED=1]]) +fi + +dnl --enable-profiling : check whether they want to do a profile build: +AC_ARG_ENABLE(profiling, AS_HELP_STRING( + --enable-profiling,[Compile with profiling enabled (default is NO)]),,enableval="no") +if test ${enableval} = "no" ; then + AC_SUBST(ENABLE_PROFILING,[[]]) +else + AC_SUBST(ENABLE_PROFILING,[[ENABLE_PROFILING=1]]) +fi + +dnl --enable-assertions : check whether they want to turn on assertions or not: +AC_ARG_ENABLE(assertions,AS_HELP_STRING( + --enable-assertions,[Compile with assertion checks enabled (default is NO)]),, enableval="no") +if test ${enableval} = "yes" ; then + AC_SUBST(DISABLE_ASSERTIONS,[[]]) +else + AC_SUBST(DISABLE_ASSERTIONS,[[DISABLE_ASSERTIONS=1]]) +fi + +dnl --enable-expensive-checks : check whether they want to turn on expensive debug checks: +AC_ARG_ENABLE(expensive-checks,AS_HELP_STRING( + --enable-expensive-checks,[Compile with expensive debug checks enabled (default is NO)]),, enableval="no") +if test ${enableval} = "yes" ; then + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[ENABLE_EXPENSIVE_CHECKS=1]]) + AC_SUBST(EXPENSIVE_CHECKS,[[yes]]) +else + AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[]]) + AC_SUBST(EXPENSIVE_CHECKS,[[no]]) +fi + +dnl --enable-debug-runtime : should runtime libraries have debug symbols? +AC_ARG_ENABLE(debug-runtime, + AS_HELP_STRING(--enable-debug-runtime,[Build runtime libs with debug symbols (default is NO)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_RUNTIME,[[]]) +else + AC_SUBST(DEBUG_RUNTIME,[[DEBUG_RUNTIME=1]]) +fi + +dnl --enable-debug-symbols : should even optimized compiler libraries +dnl have debug symbols? +AC_ARG_ENABLE(debug-symbols, + AS_HELP_STRING(--enable-debug-symbols,[Build compiler with debug symbols (default is NO if optimization is on and YES if it's off)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(DEBUG_SYMBOLS,[[]]) +else + AC_SUBST(DEBUG_SYMBOLS,[[DEBUG_SYMBOLS=1]]) +fi + +dnl --enable-jit: check whether they want to enable the jit +AC_ARG_ENABLE(jit, + AS_HELP_STRING(--enable-jit, + [Enable Just In Time Compiling (default is YES)]),, + enableval=default) +if test ${enableval} = "no" +then + AC_SUBST(JIT,[[]]) +else + case "$llvm_cv_target_arch" in + x86) AC_SUBST(TARGET_HAS_JIT,1) ;; + Sparc) AC_SUBST(TARGET_HAS_JIT,0) ;; + PowerPC) AC_SUBST(TARGET_HAS_JIT,1) ;; + x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;; + Alpha) AC_SUBST(TARGET_HAS_JIT,0) ;; + ARM) AC_SUBST(TARGET_HAS_JIT,1) ;; + Mips) AC_SUBST(TARGET_HAS_JIT,0) ;; + XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; + MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; + SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;; + Blackfin) AC_SUBST(TARGET_HAS_JIT,0) ;; + MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;; + PTX) AC_SUBST(TARGET_HAS_JIT,0) ;; + *) AC_SUBST(TARGET_HAS_JIT,0) ;; + esac +fi + +dnl Allow enablement of building and installing docs +AC_ARG_ENABLE(docs, + AS_HELP_STRING([--enable-docs], + [Build documents (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_DOCS,[1]) ;; + no) AC_SUBST(ENABLE_DOCS,[0]) ;; + default) AC_SUBST(ENABLE_DOCS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-docs. Use "yes" or "no"]) ;; +esac + +dnl Allow enablement of doxygen generated documentation +AC_ARG_ENABLE(doxygen, + AS_HELP_STRING([--enable-doxygen], + [Build doxygen documentation (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_DOXYGEN,[1]) ;; + no) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + default) AC_SUBST(ENABLE_DOXYGEN,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-doxygen. Use "yes" or "no"]) ;; +esac + +dnl Allow disablement of threads +AC_ARG_ENABLE(threads, + AS_HELP_STRING([--enable-threads], + [Use threads if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_THREADS,[1]) ;; + no) AC_SUBST(ENABLE_THREADS,[0]) ;; + default) AC_SUBST(ENABLE_THREADS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-threads. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_THREADS],$ENABLE_THREADS,[Define if threads enabled]) + +dnl Allow disablement of pthread.h +AC_ARG_ENABLE(pthreads, + AS_HELP_STRING([--enable-pthreads], + [Use pthreads if available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_PTHREADS,[1]) ;; + no) AC_SUBST(ENABLE_PTHREADS,[0]) ;; + default) AC_SUBST(ENABLE_PTHREADS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-pthreads. Use "yes" or "no"]) ;; +esac + +dnl Allow building without position independent code +AC_ARG_ENABLE(pic, + AS_HELP_STRING([--enable-pic], + [Build LLVM with Position Independent Code (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_PIC,[1]) ;; + no) AC_SUBST(ENABLE_PIC,[0]) ;; + default) AC_SUBST(ENABLE_PIC,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-pic. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_PIC],$ENABLE_PIC, + [Define if position independent code is enabled]) + +dnl Allow building a shared library and linking tools against it. +AC_ARG_ENABLE(shared, + AS_HELP_STRING([--enable-shared], + [Build a shared library and link tools against it (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_SHARED,[1]) ;; + no) AC_SUBST(ENABLE_SHARED,[0]) ;; + default) AC_SUBST(ENABLE_SHARED,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-shared. Use "yes" or "no"]) ;; +esac + +dnl Allow libstdc++ is embedded in LLVM.dll. +AC_ARG_ENABLE(embed-stdcxx, + AS_HELP_STRING([--enable-embed-stdcxx], + [Build a shared library with embedded libstdc++ for Win32 DLL (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;; + no) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;; + default) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-embed-stdcxx. Use "yes" or "no"]) ;; +esac + +dnl Enable embedding timestamp information into build. +AC_ARG_ENABLE(timestamps, + AS_HELP_STRING([--enable-timestamps], + [Enable embedding timestamp information in build (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_TIMESTAMPS,[1]) ;; + no) AC_SUBST(ENABLE_TIMESTAMPS,[0]) ;; + default) AC_SUBST(ENABLE_TIMESTAMPS,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-timestamps. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_TIMESTAMPS],$ENABLE_TIMESTAMPS, + [Define if timestamp information (e.g., __DATE___) is allowed]) + +dnl Allow specific targets to be specified for building (or not) +TARGETS_TO_BUILD="" +AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], + [Build specific host targets: all or target1,target2,... Valid targets are: + host, x86, x86_64, sparc, powerpc, alpha, arm, mips, spu, + xcore, msp430, systemz, blackfin, ptx, cbe, and cpp (default=all)]),, + enableval=all) +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU XCore MSP430 SystemZ Blackfin CBackend CppBackend MBlaze PTX" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; + ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; + CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + s390x) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + Blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; + *) AC_MSG_ERROR([Can not set target to build]) ;; + esac ;; + *) AC_MSG_ERROR([Unrecognized target $a_target]) ;; + esac + done + ;; +esac +AC_SUBST(TARGETS_TO_BUILD,$TARGETS_TO_BUILD) + +# Determine whether we are building LLVM support for the native architecture. +# If so, define LLVM_NATIVE_ARCH to that LLVM target. +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ARCH, $LLVM_NATIVE_ARCH, + [LLVM architecture name for the native architecture, if available]) + LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target" + LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo" + LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter" + AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGET, $LLVM_NATIVE_TARGET, + [LLVM name for the native Target init function, if available]) + AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETINFO, $LLVM_NATIVE_TARGETINFO, + [LLVM name for the native TargetInfo init function, if available]) + AC_DEFINE_UNQUOTED(LLVM_NATIVE_ASMPRINTER, $LLVM_NATIVE_ASMPRINTER, + [LLVM name for the native AsmPrinter init function, if available]) + fi +done + +# Build the LLVM_TARGET and LLVM_... macros for Targets.def and the individual +# target feature def files. +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/*AsmPrinter.cpp ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done +AC_SUBST(LLVM_ENUM_TARGETS) +AC_SUBST(LLVM_ENUM_ASM_PRINTERS) +AC_SUBST(LLVM_ENUM_ASM_PARSERS) +AC_SUBST(LLVM_ENUM_DISASSEMBLERS) + +dnl Prevent the CBackend from using printf("%a") for floating point so older +dnl C compilers that cannot deal with the 0x0p+0 hex floating point format +dnl can still compile the CBE's output +AC_ARG_ENABLE([cbe-printf-a],AS_HELP_STRING([--enable-cbe-printf-a], + [Enable C Backend output with hex floating point via %a (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; + no) AC_SUBST(ENABLE_CBE_PRINTF_A,[0]) ;; + default) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-cbe-printf-a. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([ENABLE_CBE_PRINTF_A],$ENABLE_CBE_PRINTF_A, + [Define if CBE is enabled for printf %a output]) + +dnl Allow a specific llvm-gcc/llvm-g++ pair to be used with this LLVM config. +AC_ARG_WITH(llvmgccdir, + AS_HELP_STRING([--with-llvmgccdir], + [Specify location of llvm-gcc install dir (default searches PATH)]),, + withval=default) +case "$withval" in + default) WITH_LLVMGCCDIR=default ;; + /* | [[A-Za-z]]:[[\\/]]*) WITH_LLVMGCCDIR=$withval ;; + *) AC_MSG_ERROR([Invalid path for --with-llvmgccdir. Provide full path]) ;; +esac + +dnl Allow a specific llvm-gcc compiler to be used with this LLVM config. +AC_ARG_WITH(llvmgcc, + AS_HELP_STRING([--with-llvmgcc], + [Specify location of llvm-gcc driver (default searches PATH)]), + LLVMGCC=$with_llvmgcc + WITH_LLVMGCCDIR="",) + +dnl Allow a specific llvm-g++ compiler to be used with this LLVM config. +AC_ARG_WITH(llvmgxx, + AS_HELP_STRING([--with-llvmgxx], + [Specify location of llvm-g++ driver (default searches PATH)]), + LLVMGXX=$with_llvmgxx + WITH_LLVMGCCDIR="",) + +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi + +if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then + AC_MSG_ERROR([Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used]); +fi + +if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then + AC_MSG_ERROR([Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used]); +fi + +dnl Allow a specific Clang compiler to be used with this LLVM config. +AC_ARG_WITH(clang, + AS_HELP_STRING([--with-clang], + [Specify location of clang compiler (default is --with-built-clang)]), + [],[with_clang=default]) + +dnl Enable use of the built Clang. +AC_ARG_WITH(built-clang, + AS_HELP_STRING([--with-built-clang], + [Use the compiled Clang as the LLVM compiler (default=check)]), + [],[with_built_clang=check]) + +dnl Select the Clang compiler option. +dnl +dnl If --with-clang is given, always honor that; otherwise honor +dnl --with-built-clang, or check if we have the clang sources. +AC_MSG_CHECKING([clang compiler]) +WITH_CLANGPATH="" +WITH_BUILT_CLANG=0 +if test "$with_clang" != "default"; then + WITH_CLANGPATH="$with_clang" + if ! test -x "$WITH_CLANGPATH"; then + AC_MSG_ERROR([invalid --with-clang, path does not specify an executable]) + fi +elif test "$with_built_clang" = "yes"; then + WITH_BUILT_CLANG=1 +elif test "$with_built_clang" = "no"; then + WITH_BUILT_CLANG=0 +else + if test "$with_built_clang" != "check"; then + AC_MSG_ERROR([invalid value for --with-built-clang.]) + fi + + if test -f ${srcdir}/tools/clang/README.txt; then + WITH_BUILT_CLANG=1 + fi +fi + +if ! test -z "$WITH_CLANGPATH"; then + AC_MSG_RESULT([$WITH_CLANGPATH]) + WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++` +elif test "$WITH_BUILT_CLANG" = "1"; then + AC_MSG_RESULT([built]) +else + AC_MSG_RESULT([none]) +fi +AC_SUBST(CLANGPATH,$WITH_CLANGPATH) +AC_SUBST(CLANGXXPATH,$WITH_CLANGXXPATH) +AC_SUBST(ENABLE_BUILT_CLANG,$WITH_BUILT_CLANG) + +dnl Override the option to use for optimized builds. +AC_ARG_WITH(optimize-option, + AS_HELP_STRING([--with-optimize-option], + [Select the compiler options to use for optimized builds]),, + withval=default) +AC_MSG_CHECKING([optimization flags]) +case "$withval" in + default) + case "$llvm_cv_os_type" in + FreeBSD) optimize_option=-O2 ;; + MingW) optimize_option=-O2 ;; + *) optimize_option=-O3 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +AC_SUBST(OPTIMIZE_OPTION,$optimize_option) +AC_MSG_RESULT([$optimize_option]) + +dnl Specify extra build options +AC_ARG_WITH(extra-options, + AS_HELP_STRING([--with-extra-options], + [Specify additional options to compile LLVM with]),, + withval=default) +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +AC_SUBST(EXTRA_OPTIONS,$EXTRA_OPTIONS) + +dnl Allow specific bindings to be specified for building (or not) +AC_ARG_ENABLE([bindings],AS_HELP_STRING([--enable-bindings], + [Build specific language bindings: all,auto,none,{binding-name} (default=auto)]),, + enableval=default) +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) AC_MSG_ERROR([Unrecognized binding $a_binding]) ;; + esac + done + ;; +esac + +dnl Allow the ocaml libdir to be overridden. This could go in a configure +dnl script for bindings/ocaml/configure, except that its auto value depends on +dnl OCAMLC, which is found here to support tests. +AC_ARG_WITH([ocaml-libdir], + [AS_HELP_STRING([--with-ocaml-libdir], + [Specify install location for ocaml bindings (default is stdlib)])], + [], + [withval=auto]) +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [[A-Za-z]]:[[\\/]]*) with_ocaml_libdir="$withval" ;; + *) AC_MSG_ERROR([Invalid path for --with-ocaml-libdir. Provide full path]) ;; +esac + +AC_ARG_WITH(clang-resource-dir, + AS_HELP_STRING([--with-clang-resource-dir], + [Relative directory from the Clang binary for resource files]),, + withval="") +AC_DEFINE_UNQUOTED(CLANG_RESOURCE_DIR,"$withval", + [Relative directory for resource files]) + +AC_ARG_WITH(c-include-dirs, + AS_HELP_STRING([--with-c-include-dirs], + [Colon separated list of directories clang will search for headers]),, + withval="") +AC_DEFINE_UNQUOTED(C_INCLUDE_DIRS,"$withval", + [Directories clang will search for headers]) + +AC_ARG_WITH(cxx-include-root, + AS_HELP_STRING([--with-cxx-include-root], + [Directory with the libstdc++ headers.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_ROOT,"$withval", + [Directory with the libstdc++ headers.]) + +AC_ARG_WITH(cxx-include-arch, + AS_HELP_STRING([--with-cxx-include-arch], + [Architecture of the libstdc++ headers.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_ARCH,"$withval", + [Arch the libstdc++ headers.]) + +AC_ARG_WITH(cxx-include-32bit-dir, + AS_HELP_STRING([--with-cxx-include-32bit-dir], + [32 bit multilib dir.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_32BIT_DIR,"$withval", + [32 bit multilib directory.]) + +AC_ARG_WITH(cxx-include-64bit-dir, + AS_HELP_STRING([--with-cxx-include-64bit-dir], + [64 bit multilib directory.]),, + withval="") +AC_DEFINE_UNQUOTED(CXX_INCLUDE_64BIT_DIR,"$withval", + [64 bit multilib directory.]) + +dnl Allow linking of LLVM with GPLv3 binutils code. +AC_ARG_WITH(binutils-include, + AS_HELP_STRING([--with-binutils-include], + [Specify path to binutils/include/ containing plugin-api.h file for gold plugin.]),, + withval=default) +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [[A-Za-z]]:[[\\/]]*) WITH_BINUTILS_INCDIR=$withval ;; + *) AC_MSG_ERROR([Invalid path for --with-binutils-include. Provide full path]) ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + AC_SUBST(BINUTILS_INCDIR,$WITH_BINUTILS_INCDIR) + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + AC_MSG_ERROR([Invalid path to directory containing plugin-api.h.]); + fi +fi + +dnl --enable-libffi : check whether the user wants to turn off libffi: +AC_ARG_ENABLE(libffi,AS_HELP_STRING( + --enable-libffi,[Check for the presence of libffi (default is NO)]), + [case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-libffi. Use "yes" or "no"]) ;; + esac], + llvm_cv_enable_libffi=no) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 4: Check for programs we need and that they are the right version +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Check for compilation tools +AC_PROG_CPP +AC_PROG_CC(gcc) +AC_PROG_CXX(g++) + +AC_PROG_NM +AC_SUBST(NM) + +dnl Check for the tools that the makefiles require +AC_CHECK_GNU_MAKE +AC_PROG_LN_S +AC_PATH_PROG(CMP, [cmp], [cmp]) +AC_PATH_PROG(CP, [cp], [cp]) +AC_PATH_PROG(DATE, [date], [date]) +AC_PATH_PROG(FIND, [find], [find]) +AC_PATH_PROG(GREP, [grep], [grep]) +AC_PATH_PROG(MKDIR,[mkdir],[mkdir]) +AC_PATH_PROG(MV, [mv], [mv]) +AC_PROG_RANLIB +AC_CHECK_TOOL(AR, ar, false) +AC_PATH_PROG(RM, [rm], [rm]) +AC_PATH_PROG(SED, [sed], [sed]) +AC_PATH_PROG(TAR, [tar], [gtar]) +AC_PATH_PROG(BINPWD,[pwd], [pwd]) + +dnl Looking for misc. graph plotting software +AC_PATH_PROG(GRAPHVIZ, [Graphviz], [echo Graphviz]) +if test "$GRAPHVIZ" != "echo Graphviz" ; then + AC_DEFINE([HAVE_GRAPHVIZ],[1],[Define if the Graphviz program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GRAPHVIZ],"$GRAPHVIZ${EXEEXT}", + [Define to path to Graphviz program if found or 'echo Graphviz' otherwise]) +fi +AC_PATH_PROG(DOT, [dot], [echo dot]) +if test "$DOT" != "echo dot" ; then + AC_DEFINE([HAVE_DOT],[1],[Define if the dot program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOT],"$DOT${EXEEXT}", + [Define to path to dot program if found or 'echo dot' otherwise]) +fi +AC_PATH_PROG(FDP, [fdp], [echo fdp]) +if test "$FDP" != "echo fdp" ; then + AC_DEFINE([HAVE_FDP],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_FDP],"$FDP${EXEEXT}", + [Define to path to fdp program if found or 'echo fdp' otherwise]) +fi +AC_PATH_PROG(NEATO, [neato], [echo neato]) +if test "$NEATO" != "echo neato" ; then + AC_DEFINE([HAVE_NEATO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_NEATO],"$NEATO${EXEEXT}", + [Define to path to neato program if found or 'echo neato' otherwise]) +fi +AC_PATH_PROG(TWOPI, [twopi], [echo twopi]) +if test "$TWOPI" != "echo twopi" ; then + AC_DEFINE([HAVE_TWOPI],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_TWOPI],"$TWOPI${EXEEXT}", + [Define to path to twopi program if found or 'echo twopi' otherwise]) +fi +AC_PATH_PROG(CIRCO, [circo], [echo circo]) +if test "$CIRCO" != "echo circo" ; then + AC_DEFINE([HAVE_CIRCO],[1],[Define if the neat program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_CIRCO],"$CIRCO${EXEEXT}", + [Define to path to circo program if found or 'echo circo' otherwise]) +fi +AC_PATH_PROGS(GV, [gv gsview32], [echo gv]) +if test "$GV" != "echo gv" ; then + AC_DEFINE([HAVE_GV],[1],[Define if the gv program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_GV],"$GV${EXEEXT}", + [Define to path to gv program if found or 'echo gv' otherwise]) +fi +AC_PATH_PROG(DOTTY, [dotty], [echo dotty]) +if test "$DOTTY" != "echo dotty" ; then + AC_DEFINE([HAVE_DOTTY],[1],[Define if the dotty program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_DOTTY],"$DOTTY${EXEEXT}", + [Define to path to dotty program if found or 'echo dotty' otherwise]) +fi +AC_PATH_PROG(XDOT_PY, [xdot.py], [echo xdot.py]) +if test "$XDOT_PY" != "echo xdot.py" ; then + AC_DEFINE([HAVE_XDOT_PY],[1],[Define if the xdot.py program is available]) + dnl If we're targeting for mingw we should emit windows paths, not msys + if test "$llvm_cv_os_type" = "MingW" ; then + XDOT_PY=`echo $XDOT_PY | sed 's/^\/\([[A-Za-z]]\)\//\1:\//' ` + fi + AC_DEFINE_UNQUOTED([LLVM_PATH_XDOT_PY],"$XDOT_PY${EXEEXT}", + [Define to path to xdot.py program if found or 'echo xdot.py' otherwise]) +fi + +dnl Look for a sufficiently recent version of Perl. +LLVM_PROG_PERL([5.006]) +AC_SUBST(PERL) +if test x"$PERL" = xnone; then + AC_SUBST(HAVE_PERL,0) + AC_MSG_ERROR([perl is required but was not found, please install it]) +else + AC_SUBST(HAVE_PERL,1) +fi + +dnl Find the install program +AC_PROG_INSTALL +dnl Prepend src dir to install path dir if it's a relative path +dnl This is a hack for installs that take place in something other +dnl than the top level. +case "$INSTALL" in + [[\\/$]]* | ?:[[\\/]]* ) ;; + *) INSTALL="\\\$(TOPSRCDIR)/$INSTALL" ;; +esac + +dnl Checks for documentation and testing tools that we can do without. If these +dnl are not found then they are set to "true" which always succeeds but does +dnl nothing. This just lets the build output show that we could have done +dnl something if the tool was available. +AC_PATH_PROG(BZIP2, [bzip2]) +AC_PATH_PROG(CAT, [cat]) +AC_PATH_PROG(DOXYGEN, [doxygen]) +AC_PATH_PROG(GROFF, [groff]) +AC_PATH_PROG(GZIPBIN, [gzip]) +AC_PATH_PROG(POD2HTML, [pod2html]) +AC_PATH_PROG(POD2MAN, [pod2man]) +AC_PATH_PROG(PDFROFF, [pdfroff]) +AC_PATH_PROG(RUNTEST, [runtest]) +DJ_AC_PATH_TCLSH +AC_PATH_PROG(ZIP, [zip]) +AC_PATH_PROGS(OCAMLC, [ocamlc]) +AC_PATH_PROGS(OCAMLOPT, [ocamlopt]) +AC_PATH_PROGS(OCAMLDEP, [ocamldep]) +AC_PATH_PROGS(OCAMLDOC, [ocamldoc]) +AC_PATH_PROGS(GAS, [gas as]) + +dnl Get the version of the linker in use. +AC_LINK_GET_VERSION + +dnl Determine whether the linker supports the -R option. +AC_LINK_USE_R + +dnl Determine whether the linker supports the -export-dynamic option. +AC_LINK_EXPORT_DYNAMIC + +dnl Determine whether the linker supports the --version-script option. +AC_LINK_VERSION_SCRIPT + +dnl Check for libtool and the library that has dlopen function (which must come +dnl before the AC_PROG_LIBTOOL check in order to enable dlopening libraries with +dnl libtool). +AC_LIBTOOL_DLOPEN +AC_LIB_LTDL + +if test "$WITH_LLVMGCCDIR" = "default" ; then + LLVMGCC="llvm-gcc${EXEEXT}" + LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) + AC_PATH_PROG(LLVMGCC, $LLVMGCC, []) + AC_PATH_PROG(LLVMGXX, $LLVMGXX, []) +else + if test -z "$LLVMGCC"; then + LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + fi + if test -z "$LLVMGXX"; then + LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" + fi + + AC_SUBST(LLVMGCC,$LLVMGCC) + AC_SUBST(LLVMGXX,$LLVMGXX) + AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND) + AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) +fi + +dnl Select the LLVM capable compiler to use, we default to using llvm-gcc if +dnl found, otherwise clang if available. +AC_ARG_WITH(llvmcc, + AS_HELP_STRING([--with-llvmcc=], + [Choose the LLVM capable compiler to use (llvm-gcc, clang, or none; default=check)]), + [],[with_llvmcc=check]) +AC_MSG_CHECKING([LLVM capable compiler]) +if test "$with_llvmcc" != "check"; then + if (test "$with_llvmcc" != "llvm-gcc" && + test "$with_llvmcc" != "clang" && + test "$with_llvmcc" != "none"); then + AC_MSG_ERROR([invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'.]) + fi + WITH_LLVMCC="$with_llvmcc" +elif test -n "$LLVMGCC"; then + WITH_LLVMCC=llvm-gcc +elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then + WITH_LLVMCC=clang +else + WITH_LLVMCC=none +fi +AC_MSG_RESULT([$WITH_LLVMCC]) +AC_SUBST(LLVMCC_OPTION,$WITH_LLVMCC) + +AC_MSG_CHECKING([tool compatibility]) + +dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as +dnl ICC; we use GCC specific options in the makefiles so the compiler needs +dnl to support those options. +dnl "icc" emits gcc signatures +dnl "icc -no-gcc" emits no gcc signature BUT is still compatible +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + AC_MSG_ERROR([gcc|icc required but not found]) +fi + +dnl Ensure that compilation tools are compatible with GCC extensions +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + AC_MSG_ERROR([g++|clang++|icc required but not found]) +fi + +dnl Verify that GCC is version 3.0 or higher +if test "$GCC" = "yes" +then + AC_COMPILE_IFELSE([[#if !defined(__GNUC__) || __GNUC__ < 3 +#error Unsupported GCC version +#endif +]], [], [AC_MSG_ERROR([gcc 3.x required, but you have a lower version])]) +fi + +dnl Check for GNU Make. We use its extensions, so don't build without it +if test -z "$llvm_cv_gnu_make_command" +then + AC_MSG_ERROR([GNU Make required but not found]) +fi + +dnl Tool compatibility is okay if we make it here. +AC_MSG_RESULT([ok]) + +dnl Check optional compiler flags. +AC_MSG_CHECKING([optional compiler flags]) +CXX_FLAG_CHECK(NO_VARIADIC_MACROS, [-Wno-variadic-macros]) +CXX_FLAG_CHECK(NO_MISSING_FIELD_INITIALIZERS, [-Wno-missing-field-initializers]) +AC_MSG_RESULT([$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 5: Check for libraries +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_LIB(m,sin) +if test "$llvm_cv_os_type" = "MingW" ; then + AC_CHECK_LIB(imagehlp, main) + AC_CHECK_LIB(psapi, main) +fi + +dnl dlopen() is required for plugin support. +AC_SEARCH_LIBS(dlopen,dl,AC_DEFINE([HAVE_DLOPEN],[1], + [Define if dlopen() is available on this platform.]), + AC_MSG_WARN([dlopen() not found - disabling plugin support])) + +dnl libffi is optional; used to call external functions from the interpreter +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1], + [Define if libffi is available on this platform.]), + AC_MSG_ERROR([libffi not found - configure without --enable-libffi to compile without it])) +fi + +dnl mallinfo is optional; the code can compile (minus features) without it +AC_SEARCH_LIBS(mallinfo,malloc,AC_DEFINE([HAVE_MALLINFO],[1], + [Define if mallinfo() is available on this platform.])) + +dnl pthread locking functions are optional - but llvm will not be thread-safe +dnl without locks. +if test "$ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + AC_CHECK_LIB(pthread, pthread_mutex_init) + AC_SEARCH_LIBS(pthread_mutex_lock,pthread, + AC_DEFINE([HAVE_PTHREAD_MUTEX_LOCK],[1], + [Have pthread_mutex_lock])) + AC_SEARCH_LIBS(pthread_rwlock_init,pthread, + AC_DEFINE([HAVE_PTHREAD_RWLOCK_INIT],[1], + [Have pthread_rwlock_init])) + AC_SEARCH_LIBS(pthread_getspecific,pthread, + AC_DEFINE([HAVE_PTHREAD_GETSPECIFIC],[1], + [Have pthread_getspecific])) +fi + +dnl Allow extra x86-disassembler library +AC_ARG_WITH(udis86, + AS_HELP_STRING([--with-udis86=], + [Use udis86 external x86 disassembler library]), + [ + AC_SUBST(USE_UDIS86, [1]) + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + AC_CHECK_LIB(udis86, ud_init, [], [ + echo "Error! You need to have libudis86 around." + exit -1 + ]) + ], + AC_SUBST(USE_UDIS86, [0])) +AC_DEFINE_UNQUOTED([USE_UDIS86],$USE_UDIS86, + [Define if use udis86 library]) + +dnl Allow OProfile support for JIT output. +AC_ARG_WITH(oprofile, + AS_HELP_STRING([--with-oprofile=], + [Tell OProfile >= 0.9.4 how to symbolize JIT output]), + [ + AC_SUBST(USE_OPROFILE, [1]) + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + AC_SUBST(USE_OPROFILE, [0]) ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + dnl Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537744: + dnl libbfd is not included properly in libopagent in some Debian + dnl versions. If libbfd isn't found at all, we assume opagent works + dnl anyway. + AC_SEARCH_LIBS(bfd_init, bfd, [], []) + AC_SEARCH_LIBS(op_open_agent, opagent, [], [ + echo "Error! You need to have libopagent around." + exit -1 + ]) + AC_CHECK_HEADER([opagent.h], [], [ + echo "Error! You need to have opagent.h around." + exit -1 + ]) + fi + ], + [ + AC_SUBST(USE_OPROFILE, [0]) + ]) +AC_DEFINE_UNQUOTED([USE_OPROFILE],$USE_OPROFILE, + [Define if we have the oprofile JIT-support library]) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 6: Check for header files +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl First, use autoconf provided macros for specific headers that we need +dnl We don't check for ancient stuff or things that are guaranteed to be there +dnl by the C++ standard. We always use the versions of C headers. +dnl Generally we're looking for POSIX headers. +AC_HEADER_DIRENT +AC_HEADER_MMAP_ANONYMOUS +AC_HEADER_STAT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_HEADER_TIME + +AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h]) +AC_CHECK_HEADERS([malloc.h setjmp.h signal.h stdint.h termios.h unistd.h]) +AC_CHECK_HEADERS([utime.h windows.h]) +AC_CHECK_HEADERS([sys/mman.h sys/param.h sys/resource.h sys/time.h sys/uio.h]) +AC_CHECK_HEADERS([sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h]) +AC_CHECK_HEADERS([valgrind/valgrind.h]) +AC_CHECK_HEADERS([fenv.h]) +if test "$ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + AC_CHECK_HEADERS(pthread.h, + AC_SUBST(HAVE_PTHREAD, 1), + AC_SUBST(HAVE_PTHREAD, 0)) +else + AC_SUBST(HAVE_PTHREAD, 0) +fi + +dnl Try to find ffi.h. +if test "$llvm_cv_enable_libffi" = "yes" ; then + AC_CHECK_HEADERS([ffi.h ffi/ffi.h]) +fi + +dnl Try to find Darwin specific crash reporting libraries. +AC_CHECK_HEADERS([CrashReporterClient.h]) + +dnl Try to find Darwin specific crash reporting global. +AC_MSG_CHECKING([__crashreporter_info__]) +AC_LINK_IFELSE( + AC_LANG_SOURCE( + [[extern const char *__crashreporter_info__; + int main() { + __crashreporter_info__ = "test"; + return 0; + } + ]]), + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_CRASHREPORTER_INFO, 1, Can use __crashreporter_info__), + AC_MSG_RESULT(no) + AC_DEFINE(HAVE_CRASHREPORTER_INFO, 0, + Define if __crashreporter_info__ exists.)) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 7: Check for types and structures +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_HUGE_VAL_CHECK +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_DEFINE_UNQUOTED([RETSIGTYPE],[void],[Define as the return type of signal handlers (`int' or `void').]) +AC_STRUCT_TM +AC_CHECK_TYPES([int64_t],,AC_MSG_ERROR([Type int64_t required but not found])) +AC_CHECK_TYPES([uint64_t],, + AC_CHECK_TYPES([u_int64_t],, + AC_MSG_ERROR([Type uint64_t or u_int64_t required but not found]))) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 8: Check for specific functions needed +dnl=== +dnl===-----------------------------------------------------------------------=== + +AC_CHECK_FUNCS([backtrace ceilf floorf roundf rintf nearbyintf getcwd ]) +AC_CHECK_FUNCS([powf fmodf strtof round ]) +AC_CHECK_FUNCS([getpagesize getrusage getrlimit setrlimit gettimeofday ]) +AC_CHECK_FUNCS([isatty mkdtemp mkstemp ]) +AC_CHECK_FUNCS([mktemp posix_spawn realpath sbrk setrlimit strdup ]) +AC_CHECK_FUNCS([strerror strerror_r setenv ]) +AC_CHECK_FUNCS([strtoll strtoq sysconf malloc_zone_statistics ]) +AC_CHECK_FUNCS([setjmp longjmp sigsetjmp siglongjmp writev]) +AC_C_PRINTF_A +AC_FUNC_RAND48 + +dnl Check the declaration "Secure API" on Windows environments. +AC_CHECK_DECLS([strerror_s]) + +dnl Check symbols in libgcc.a for JIT on Mingw. +if test "$llvm_cv_os_type" = "MingW" ; then + AC_CHECK_LIB(gcc,_alloca,AC_DEFINE([HAVE__ALLOCA],[1],[Have host's _alloca])) + AC_CHECK_LIB(gcc,__alloca,AC_DEFINE([HAVE___ALLOCA],[1],[Have host's __alloca])) + AC_CHECK_LIB(gcc,__chkstk,AC_DEFINE([HAVE___CHKSTK],[1],[Have host's __chkstk])) + AC_CHECK_LIB(gcc,___chkstk,AC_DEFINE([HAVE____CHKSTK],[1],[Have host's ___chkstk])) + + AC_CHECK_LIB(gcc,__ashldi3,AC_DEFINE([HAVE___ASHLDI3],[1],[Have host's __ashldi3])) + AC_CHECK_LIB(gcc,__ashrdi3,AC_DEFINE([HAVE___ASHRDI3],[1],[Have host's __ashrdi3])) + AC_CHECK_LIB(gcc,__divdi3,AC_DEFINE([HAVE___DIVDI3],[1],[Have host's __divdi3])) + AC_CHECK_LIB(gcc,__fixdfdi,AC_DEFINE([HAVE___FIXDFDI],[1],[Have host's __fixdfdi])) + AC_CHECK_LIB(gcc,__fixsfdi,AC_DEFINE([HAVE___FIXSFDI],[1],[Have host's __fixsfdi])) + AC_CHECK_LIB(gcc,__floatdidf,AC_DEFINE([HAVE___FLOATDIDF],[1],[Have host's __floatdidf])) + AC_CHECK_LIB(gcc,__lshrdi3,AC_DEFINE([HAVE___LSHRDI3],[1],[Have host's __lshrdi3])) + AC_CHECK_LIB(gcc,__moddi3,AC_DEFINE([HAVE___MODDI3],[1],[Have host's __moddi3])) + AC_CHECK_LIB(gcc,__udivdi3,AC_DEFINE([HAVE___UDIVDI3],[1],[Have host's __udivdi3])) + AC_CHECK_LIB(gcc,__umoddi3,AC_DEFINE([HAVE___UMODDI3],[1],[Have host's __umoddi3])) + + AC_CHECK_LIB(gcc,__main,AC_DEFINE([HAVE___MAIN],[1],[Have host's __main])) + AC_CHECK_LIB(gcc,__cmpdi2,AC_DEFINE([HAVE___CMPDI2],[1],[Have host's __cmpdi2])) +fi + +dnl Check for variations in the Standard C++ library and STL. These macros are +dnl provided by LLVM in the autoconf/m4 directory. +AC_FUNC_ISNAN +AC_FUNC_ISINF + +dnl Check for mmap support.We also need to know if /dev/zero is required to +dnl be opened for allocating RWX memory. +dnl Make sure we aren't attempting to configure for an unknown system +if test "$llvm_cv_platform_type" = "Unix" ; then + AC_FUNC_MMAP + AC_FUNC_MMAP_FILE + AC_NEED_DEV_ZERO_FOR_MMAP + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + AC_MSG_WARN([mmap() of a fixed address required but not supported]) + fi + if test "$ac_cv_func_mmap_file" = "no" + then + AC_MSG_WARN([mmap() of files required but not found]) + fi +fi + +dnl atomic builtins are required for threading support. +AC_MSG_CHECKING(for GCC atomic builtins) +dnl Since we'll be using these atomic builtins in C++ files we should test +dnl the C++ compiler. +AC_LANG_PUSH([C++]) +AC_LINK_IFELSE( + AC_LANG_SOURCE( + [[int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + ]]), + AC_LANG_POP([C++]) + AC_MSG_RESULT(yes) + AC_DEFINE(LLVM_MULTITHREADED, 1, Build multithreading support into LLVM), + AC_MSG_RESULT(no) + AC_DEFINE(LLVM_MULTITHREADED, 0, Build multithreading support into LLVM) + AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing])) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 9: Additional checks, variables, etc. +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Handle 32-bit linux systems running a 64-bit kernel. +dnl This has to come after section 4 because it invokes the compiler. +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + AC_IS_LINUX_MIXED + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + +dnl Check, whether __dso_handle is present +AC_CHECK_FUNCS([__dso_handle]) + +dnl Check wether llvm-gcc is based on dragonegg +AC_CACHE_CHECK([whether llvm-gcc is dragonegg],[llvm_cv_llvmgcc_dragonegg], +[llvm_cv_llvmgcc_dragonegg="no" +if test -n "$LLVMGCC" ; then + cp /dev/null conftest.c + $LLVMGCC -fplugin-arg-dragonegg-emit-ir -S -o - conftest.c > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_dragonegg="yes" + fi + rm conftest.c +fi]) + +dnl Set the flags needed to emit LLVM IR and to disable optimizations +dnl in llvmgcc +if test "$llvm_cv_llvmgcc_dragonegg" = "yes" ; then + LLVMCC_EMITIR_FLAG="-fplugin-arg-dragonegg-emit-ir" + LLVMCC_DISABLEOPT_FLAGS="-fplugin-arg-dragonegg-disable-llvm-optzns" +else + LLVMCC_EMITIR_FLAG="-emit-llvm" + LLVMCC_DISABLEOPT_FLAGS="-mllvm -disable-llvm-optzns" +fi + +AC_SUBST(LLVMCC_EMITIR_FLAG) + +dnl See if the llvm-gcc executable can compile to LLVM assembly +AC_CACHE_CHECK([whether llvm-gcc is sane],[llvm_cv_llvmgcc_sanity], +[llvm_cv_llvmgcc_sanity="no" +if test -n "$LLVMGCC" ; then + cp /dev/null conftest.c + $LLVMGCC "$LLVMCC_EMITIR_FLAG" -S -o - conftest.c | \ + grep 'target datalayout =' > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_sanity="yes" + fi + rm conftest.c +fi]) + +dnl Since we have a sane llvm-gcc, identify it and its sub-tools +dnl Furthermore, add some information about the tools +if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then + AC_MSG_CHECKING([llvm-gcc component support]) + llvmcc1path=`$LLVMGCC --print-prog-name=cc1` + AC_SUBST(LLVMCC1,$llvmcc1path) + llvmcc1pluspath=`$LLVMGCC --print-prog-name=cc1plus` + AC_SUBST(LLVMCC1PLUS,$llvmcc1pluspath) + llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` + AC_SUBST(LLVMGCCDIR,$llvmgccdir) + llvmgcclangs=[`$LLVMGCC -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`] + AC_SUBST(LLVMGCC_LANGS,$llvmgcclangs) + AC_SUBST(LLVMGCC_DRAGONEGG,$llvm_cv_llvmgcc_dragonegg) + AC_SUBST(LLVMCC_DISABLEOPT_FLAGS) + AC_MSG_RESULT([ok]) +fi + +dnl Propagate the shared library extension that the libltdl checks did to +dnl the Makefiles so we can use it there too +AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext) + +dnl Propagate the run-time library path variable that the libltdl +dnl checks found to the Makefiles so we can use it there too +AC_SUBST(SHLIBPATH_VAR,$libltdl_cv_shlibpath_var) + +# Translate the various configuration directories and other basic +# information into substitutions that will end up in Makefile.config.in +# that these configured values can be used by the makefiles +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_LIBDIR="${prefix}/lib"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` +AC_SUBST(LLVM_PREFIX) +AC_SUBST(LLVM_BINDIR) +AC_SUBST(LLVM_LIBDIR) +AC_SUBST(LLVM_DATADIR) +AC_SUBST(LLVM_DOCSDIR) +AC_SUBST(LLVM_ETCDIR) +AC_SUBST(LLVM_INCLUDEDIR) +AC_SUBST(LLVM_INFODIR) +AC_SUBST(LLVM_MANDIR) +AC_SUBST(LLVM_CONFIGTIME) + +# Place the various directores into the config.h file as #defines so that we +# can know about the installation paths within LLVM. +AC_DEFINE_UNQUOTED(LLVM_PREFIX,"$LLVM_PREFIX", + [Installation prefix directory]) +AC_DEFINE_UNQUOTED(LLVM_BINDIR, "$LLVM_BINDIR", + [Installation directory for binary executables]) +AC_DEFINE_UNQUOTED(LLVM_LIBDIR, "$LLVM_LIBDIR", + [Installation directory for libraries]) +AC_DEFINE_UNQUOTED(LLVM_DATADIR, "$LLVM_DATADIR", + [Installation directory for data files]) +AC_DEFINE_UNQUOTED(LLVM_DOCSDIR, "$LLVM_DOCSDIR", + [Installation directory for documentation]) +AC_DEFINE_UNQUOTED(LLVM_ETCDIR, "$LLVM_ETCDIR", + [Installation directory for config files]) +AC_DEFINE_UNQUOTED(LLVM_INCLUDEDIR, "$LLVM_INCLUDEDIR", + [Installation directory for include files]) +AC_DEFINE_UNQUOTED(LLVM_INFODIR, "$LLVM_INFODIR", + [Installation directory for .info files]) +AC_DEFINE_UNQUOTED(LLVM_MANDIR, "$LLVM_MANDIR", + [Installation directory for man pages]) +AC_DEFINE_UNQUOTED(LLVM_CONFIGTIME, "$LLVM_CONFIGTIME", + [Time at which LLVM was configured]) +AC_DEFINE_UNQUOTED(LLVM_HOSTTRIPLE, "$host", + [Host triple we were built on]) + +# Determine which bindings to build. +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +AC_SUBST(BINDINGS_TO_BUILD,$BINDINGS_TO_BUILD) + +# This isn't really configurey, but it avoids having to repeat the list in +# other files. +AC_SUBST(ALL_BINDINGS,ocaml) + +# Do any work necessary to ensure that bindings have what they need. +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep]) + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt]) + dnl ocamlopt is optional! + fi + if test "x$with_ocaml_libdir" != xauto ; then + AC_SUBST(OCAML_LIBDIR,$with_ocaml_libdir) + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + AC_SUBST(OCAML_LIBDIR,$ocaml_stdlib) + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + AC_SUBST(OCAML_LIBDIR,$LLVM_LIBDIR/ocaml) + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + AC_MSG_ERROR([Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings.]) +fi + +dnl Determine whether the compiler supports -fvisibility-inlines-hidden. +AC_CXX_USE_VISIBILITY_INLINES_HIDDEN + +dnl Determine linker rpath flag +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi +AC_SUBST(RPATH) + +dnl Determine linker rdynamic flag +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-Wl,-export-dynamic" +else + RDYNAMIC="" +fi +AC_SUBST(RDYNAMIC) + +dnl===-----------------------------------------------------------------------=== +dnl=== +dnl=== SECTION 10: Specify the output files and generate it +dnl=== +dnl===-----------------------------------------------------------------------=== + +dnl Configure header files +dnl WARNING: dnl If you add or remove any of the following config headers, then +dnl you MUST also update Makefile.rules so that the variable FilesToConfig +dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the +dnl files can be updated automatically when their *.in sources change. +AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h]) +AH_TOP([#ifndef CONFIG_H +#define CONFIG_H]) +AH_BOTTOM([#endif]) + +AC_CONFIG_FILES([include/llvm/Config/Targets.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmPrinters.def]) +AC_CONFIG_FILES([include/llvm/Config/AsmParsers.def]) +AC_CONFIG_FILES([include/llvm/Config/Disassemblers.def]) +AC_CONFIG_HEADERS([include/llvm/Support/DataTypes.h]) + +dnl Configure the makefile's configuration data +AC_CONFIG_FILES([Makefile.config]) + +dnl Configure the RPM spec file for LLVM +AC_CONFIG_FILES([llvm.spec]) + +dnl Configure llvmc's Base plugin +AC_CONFIG_FILES([tools/llvmc/src/Base.td]) + +dnl Do the first stage of configuration for llvm-config.in. +AC_CONFIG_FILES([tools/llvm-config/llvm-config.in]) + +dnl Do special configuration of Makefiles +AC_CONFIG_COMMANDS([setup],,[llvm_src="${srcdir}"]) +AC_CONFIG_MAKEFILE(Makefile) +AC_CONFIG_MAKEFILE(Makefile.common) +AC_CONFIG_MAKEFILE(examples/Makefile) +AC_CONFIG_MAKEFILE(lib/Makefile) +AC_CONFIG_MAKEFILE(runtime/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile) +AC_CONFIG_MAKEFILE(test/Makefile.tests) +AC_CONFIG_MAKEFILE(unittests/Makefile) +AC_CONFIG_MAKEFILE(tools/Makefile) +AC_CONFIG_MAKEFILE(utils/Makefile) +AC_CONFIG_MAKEFILE(projects/Makefile) +AC_CONFIG_MAKEFILE(bindings/Makefile) +AC_CONFIG_MAKEFILE(bindings/ocaml/Makefile.ocaml) + +dnl Finally, crank out the output +AC_OUTPUT diff --git a/final/autoconf/depcomp b/final/autoconf/depcomp new file mode 100755 index 00000000000..11e2d3bfe1c --- /dev/null +++ b/final/autoconf/depcomp @@ -0,0 +1,522 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2004-05-31.23 + +# Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit 0 + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit 0 + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + outname="$stripped.o" + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # Dependencies are output in .lo.d with libtool 1.4. + # With libtool 1.5 they are output both in $dir.libs/$base.o.d + # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the + # latter, because the former will be cleaned when $dir.libs is + # erased. + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir$base.o.d" + tmpdepfile3="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + tmpdepfile3="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + elif test -f "$tmpdepfile2"; then + tmpdepfile="$tmpdepfile2" + else + tmpdepfile="$tmpdepfile3" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/final/autoconf/install-sh b/final/autoconf/install-sh new file mode 100755 index 00000000000..dd97db7aa1c --- /dev/null +++ b/final/autoconf/install-sh @@ -0,0 +1,322 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2004-09-10.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/final/autoconf/ltmain.sh b/final/autoconf/ltmain.sh new file mode 100644 index 00000000000..06823e057a5 --- /dev/null +++ b/final/autoconf/ltmain.sh @@ -0,0 +1,6863 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/final/autoconf/m4/build_exeext.m4 b/final/autoconf/m4/build_exeext.m4 new file mode 100644 index 00000000000..1bdecc1ba57 --- /dev/null +++ b/final/autoconf/m4/build_exeext.m4 @@ -0,0 +1,42 @@ +# Check for the extension used for executables on build platform. +# This is necessary for cross-compiling where the build platform +# may differ from the host platform. +AC_DEFUN([AC_BUILD_EXEEXT], +[ +AC_MSG_CHECKING([for executable suffix on build platform]) +AC_CACHE_VAL(ac_cv_build_exeext, +[if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + AC_CHECK_PROG(BUILD_CC, ${ac_build_prefix}gcc, ${ac_build_prefix}gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, gcc, gcc) + if test -z "$BUILD_CC"; then + AC_CHECK_PROG(BUILD_CC, cc, cc, , , /usr/ucb/cc) + fi + fi + test -z "$BUILD_CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH]) + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AS_MESSAGE_LOG_FD' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if AC_TRY_EVAL(ac_build_link); then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + AC_MSG_ERROR([installation or configuration problem: compiler cannot create executables.]) + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi]) +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +AC_MSG_RESULT(${ac_cv_build_exeext}) +ac_build_exeext=$BUILD_EXEEXT +AC_SUBST(BUILD_EXEEXT)]) diff --git a/final/autoconf/m4/c_printf_a.m4 b/final/autoconf/m4/c_printf_a.m4 new file mode 100644 index 00000000000..61bac8c9dd1 --- /dev/null +++ b/final/autoconf/m4/c_printf_a.m4 @@ -0,0 +1,31 @@ +# +# Determine if the printf() functions have the %a format character. +# This is modified from: +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +AC_DEFUN([AC_C_PRINTF_A], +[AC_CACHE_CHECK([if printf has the %a format character],[llvm_cv_c_printf_a], +[AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +]],[[ +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0);]])], + llvm_cv_c_printf_a=yes, + llvmac_cv_c_printf_a=no, + llvmac_cv_c_printf_a=no) + AC_LANG_POP([C])]) + if test "$llvm_cv_c_printf_a" = "yes"; then + AC_DEFINE([HAVE_PRINTF_A],[1],[Define to have the %a format string]) + fi +]) diff --git a/final/autoconf/m4/check_gnu_make.m4 b/final/autoconf/m4/check_gnu_make.m4 new file mode 100644 index 00000000000..7355e1c85bb --- /dev/null +++ b/final/autoconf/m4/check_gnu_make.m4 @@ -0,0 +1,26 @@ +# +# Check for GNU Make. This is originally from +# http://www.gnu.org/software/ac-archive/htmldoc/check_gnu_make.html +# +AC_DEFUN([AC_CHECK_GNU_MAKE], +[AC_CACHE_CHECK([for GNU make],[llvm_cv_gnu_make_command], +dnl Search all the common names for GNU make +[llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done]) +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, +dnl '#' otherwise + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + AC_MSG_RESULT("Not found"); + fi + AC_SUBST(ifGNUmake) +]) diff --git a/final/autoconf/m4/config_makefile.m4 b/final/autoconf/m4/config_makefile.m4 new file mode 100644 index 00000000000..b1eaffdcd85 --- /dev/null +++ b/final/autoconf/m4/config_makefile.m4 @@ -0,0 +1,9 @@ +# +# Configure a Makefile without clobbering it if it exists and is not out of +# date. This macro is unique to LLVM. +# +AC_DEFUN([AC_CONFIG_MAKEFILE], +[AC_CONFIG_COMMANDS($1, + [${llvm_src}/autoconf/mkinstalldirs `dirname $1` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/$1 $1]) +]) diff --git a/final/autoconf/m4/config_project.m4 b/final/autoconf/m4/config_project.m4 new file mode 100644 index 00000000000..eea7faf165c --- /dev/null +++ b/final/autoconf/m4/config_project.m4 @@ -0,0 +1,14 @@ +# +# Provide the arguments and other processing needed for an LLVM project +# +AC_DEFUN([LLVM_CONFIG_PROJECT], + [AC_ARG_WITH([llvmsrc], + AS_HELP_STRING([--with-llvmsrc],[Location of LLVM Source Code]), + [llvm_src="$withval"],[llvm_src="]$1["]) + AC_SUBST(LLVM_SRC,$llvm_src) + AC_ARG_WITH([llvmobj], + AS_HELP_STRING([--with-llvmobj],[Location of LLVM Object Code]), + [llvm_obj="$withval"],[llvm_obj="]$2["]) + AC_SUBST(LLVM_OBJ,$llvm_obj) + AC_CONFIG_COMMANDS([setup],,[llvm_src="${LLVM_SRC}"]) +]) diff --git a/final/autoconf/m4/cxx_flag_check.m4 b/final/autoconf/m4/cxx_flag_check.m4 new file mode 100644 index 00000000000..ab09f2af5cf --- /dev/null +++ b/final/autoconf/m4/cxx_flag_check.m4 @@ -0,0 +1,2 @@ +AC_DEFUN([CXX_FLAG_CHECK], + [AC_SUBST($1, `$CXX $2 -fsyntax-only -xc /dev/null 2>/dev/null && echo $2`)]) diff --git a/final/autoconf/m4/find_std_program.m4 b/final/autoconf/m4/find_std_program.m4 new file mode 100644 index 00000000000..c789df8e641 --- /dev/null +++ b/final/autoconf/m4/find_std_program.m4 @@ -0,0 +1,118 @@ +dnl Check for a standard program that has a bin, include and lib directory +dnl +dnl Parameters: +dnl $1 - prefix directory to check +dnl $2 - program name to check +dnl $3 - header file to check +dnl $4 - library file to check +AC_DEFUN([CHECK_STD_PROGRAM], +[m4_define([allcapsname],translit($2,a-z,A-Z)) +if test -n "$1" -a -d "$1" -a -n "$2" -a -d "$1/bin" -a -x "$1/bin/$2" ; then + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_SUBST(allcapsname(),[$1/bin/$2]) + AC_SUBST(allcapsname()[_BIN],[$1/bin]) + AC_SUBST(allcapsname()[_DIR],[$1]) + if test -n "$3" -a -d "$1/include" -a -f "$1/include/$3" ; then + AC_SUBST(allcapsname()[_INC],[$1/include]) + fi + if test -n "$4" -a -d "$1/lib" -a -f "$1/lib/$4" ; then + AC_SUBST(allcapsname()[_LIB],[$1/lib]) + fi +fi +]) + +dnl Find a program via --with options, in the path, or well known places +dnl +dnl Parameters: +dnl $1 - program's executable name +dnl $2 - header file name to check (optional) +dnl $3 - library file name to check (optional) +dnl $4 - alternate (long) name for the program +AC_DEFUN([FIND_STD_PROGRAM], +[m4_define([allcapsname],translit($1,a-z,A-Z)) +m4_define([stdprog_long_name],ifelse($4,,translit($1,[ !@#$%^&*()-+={}[]:;"',./?],[-]),translit($4,[ !@#$%^&*()-+={}[]:;"',./?],[-]))) +AC_MSG_CHECKING([for ]stdprog_long_name()[ bin/lib/include locations]) +AC_ARG_WITH($1, + AS_HELP_STRING([--with-]stdprog_long_name()[=DIR], + [Specify that the ]stdprog_long_name()[ install prefix is DIR]), + $1[pfxdir=$withval],$1[pfxdir=nada]) +AC_ARG_WITH($1[-bin], + AS_HELP_STRING([--with-]stdprog_long_name()[-bin=DIR], + [Specify that the ]stdprog_long_name()[ binary is in DIR]), + $1[bindir=$withval],$1[bindir=nada]) +AC_ARG_WITH($1[-lib], + AS_HELP_STRING([--with-]stdprog_long_name()[-lib=DIR], + [Specify that ]stdprog_long_name()[ libraries are in DIR]), + $1[libdir=$withval],$1[libdir=nada]) +AC_ARG_WITH($1[-inc], + AS_HELP_STRING([--with-]stdprog_long_name()[-inc=DIR], + [Specify that the ]stdprog_long_name()[ includes are in DIR]), + $1[incdir=$withval],$1[incdir=nada]) +eval pfxval=\$\{$1pfxdir\} +eval binval=\$\{$1bindir\} +eval incval=\$\{$1incdir\} +eval libval=\$\{$1libdir\} +if test "${pfxval}" != "nada" ; then + CHECK_STD_PROGRAM(${pfxval},$1,$2,$3) +elif test "${binval}" != "nada" ; then + if test "${libval}" != "nada" ; then + if test "${incval}" != "nada" ; then + if test -d "${binval}" ; then + if test -d "${incval}" ; then + if test -d "${libval}" ; then + AC_SUBST(allcapsname(),${binval}/$1) + AC_SUBST(allcapsname()[_BIN],${binval}) + AC_SUBST(allcapsname()[_INC],${incval}) + AC_SUBST(allcapsname()[_LIB],${libval}) + AC_SUBST([USE_]allcapsname(),["USE_]allcapsname()[ = 1"]) + AC_MSG_RESULT([found via --with options]) + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-bindir value must be a directory]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-incdir option must be specified]) + fi + else + AC_MSG_RESULT([failed]) + AC_MSG_ERROR([The --with-]$1[-libdir option must be specified]) + fi +else + tmppfxdir=`which $1 2>&1` + if test -n "$tmppfxdir" -a -d "${tmppfxdir%*$1}" -a \ + -d "${tmppfxdir%*$1}/.." ; then + tmppfxdir=`cd "${tmppfxdir%*$1}/.." ; pwd` + CHECK_STD_PROGRAM($tmppfxdir,$1,$2,$3) + AC_MSG_RESULT([found in PATH at ]$tmppfxdir) + else + checkresult="yes" + eval checkval=\$\{"USE_"allcapsname()\} + CHECK_STD_PROGRAM([/usr],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/usr/local],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/sw],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/opt],$1,$2,$3) + if test -z "${checkval}" ; then + CHECK_STD_PROGRAM([/],$1,$2,$3) + if test -z "${checkval}" ; then + checkresult="no" + fi + fi + fi + fi + fi + AC_MSG_RESULT($checkresult) + fi +fi +]) diff --git a/final/autoconf/m4/func_isinf.m4 b/final/autoconf/m4/func_isinf.m4 new file mode 100644 index 00000000000..c936bf920d0 --- /dev/null +++ b/final/autoconf/m4/func_isinf.m4 @@ -0,0 +1,36 @@ +# +# This function determins if the the isinf function isavailable on this +# platform. +# +AC_DEFUN([AC_FUNC_ISINF],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_math_h], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_MATH_H],1,[Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isinf_in_cmath], + [isinf], [], + [float f; isinf(f);]) +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISINF_IN_CMATH],1,[Set to 1 if the isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isinf_in_cmath], + [std::isinf], [], + [float f; std::isinf(f)}]) +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISINF_IN_CMATH],1,[Set to 1 if the std::isinf function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_finite_in_ieeefp_h], + [finite], [], + [float f; finite(f);]) +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + AC_DEFINE([HAVE_FINITE_IN_IEEEFP_H],1,[Set to 1 if the finite function is found in ]) +fi + +]) + + diff --git a/final/autoconf/m4/func_isnan.m4 b/final/autoconf/m4/func_isnan.m4 new file mode 100644 index 00000000000..eb5ca0daeb5 --- /dev/null +++ b/final/autoconf/m4/func_isnan.m4 @@ -0,0 +1,27 @@ +# +# This function determines if the isnan function is available on this +# platform. +# +AC_DEFUN([AC_FUNC_ISNAN],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_math_h], + [isnan], [], + [float f; isnan(f);]) + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_MATH_H],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_isnan_in_cmath], + [isnan], [], + [float f; isnan(f);]) +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_ISNAN_IN_CMATH],1,[Set to 1 if the isnan function is found in ]) +fi + +AC_SINGLE_CXX_CHECK([ac_cv_func_std_isnan_in_cmath], + [std::isnan], [], + [float f; std::isnan(f);]) +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + AC_DEFINE([HAVE_STD_ISNAN_IN_CMATH],1,[Set to 1 if the std::isnan function is found in ]) +fi +]) diff --git a/final/autoconf/m4/func_mmap_file.m4 b/final/autoconf/m4/func_mmap_file.m4 new file mode 100644 index 00000000000..372c87fbe5c --- /dev/null +++ b/final/autoconf/m4/func_mmap_file.m4 @@ -0,0 +1,26 @@ +# +# Check for the ability to mmap a file. +# +AC_DEFUN([AC_FUNC_MMAP_FILE], +[AC_CACHE_CHECK(for mmap of files, +ac_cv_func_mmap_file, +[ AC_LANG_PUSH([C]) + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ +#include +#include +#include +]],[[ + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED);]])], + [ac_cv_func_mmap_file=yes],[ac_cv_func_mmap_file=no],[ac_cv_func_mmap_file=no]) + AC_LANG_POP([C]) +]) +if test "$ac_cv_func_mmap_file" = yes; then + AC_DEFINE([HAVE_MMAP_FILE],[],[Define if mmap() can map files into memory]) + AC_SUBST(MMAP_FILE,[yes]) +fi +]) diff --git a/final/autoconf/m4/header_mmap_anonymous.m4 b/final/autoconf/m4/header_mmap_anonymous.m4 new file mode 100644 index 00000000000..2270d29557b --- /dev/null +++ b/final/autoconf/m4/header_mmap_anonymous.m4 @@ -0,0 +1,21 @@ +# +# Check for anonymous mmap macros. This is modified from +# http://www.gnu.org/software/ac-archive/htmldoc/ac_cxx_have_ext_slist.html +# +AC_DEFUN([AC_HEADER_MMAP_ANONYMOUS], +[AC_CACHE_CHECK(for MAP_ANONYMOUS vs. MAP_ANON, +ac_cv_header_mmap_anon, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#include +#include +#include ]], + [[mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0);]])], + ac_cv_header_mmap_anon=yes, + ac_cv_header_mmap_anon=no) + AC_LANG_POP([C]) +]) +if test "$ac_cv_header_mmap_anon" = yes; then + AC_DEFINE([HAVE_MMAP_ANONYMOUS],[1],[Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if it uses MAP_ANON]) +fi +]) diff --git a/final/autoconf/m4/huge_val.m4 b/final/autoconf/m4/huge_val.m4 new file mode 100644 index 00000000000..5fffbfc8d37 --- /dev/null +++ b/final/autoconf/m4/huge_val.m4 @@ -0,0 +1,20 @@ +# +# This function determins if the the HUGE_VAL macro is compilable with the +# -pedantic switch or not. XCode < 2.4.1 doesn't get it right. +# +AC_DEFUN([AC_HUGE_VAL_CHECK],[ + AC_CACHE_CHECK([for HUGE_VAL sanity], [ac_cv_huge_val_sanity],[ + AC_LANG_PUSH([C++]) + ac_save_CXXFLAGS=$CXXFLAGS + CXXFLAGS=-pedantic + AC_RUN_IFELSE( + AC_LANG_PROGRAM( + [#include ], + [double x = HUGE_VAL; return x != x; ]), + [ac_cv_huge_val_sanity=yes],[ac_cv_huge_val_sanity=no], + [ac_cv_huge_val_sanity=yes]) + CXXFLAGS=$ac_save_CXXFLAGS + AC_LANG_POP([C++]) + ]) + AC_SUBST(HUGE_VAL_SANITY,$ac_cv_huge_val_sanity) +]) diff --git a/final/autoconf/m4/libtool.m4 b/final/autoconf/m4/libtool.m4 new file mode 100644 index 00000000000..a8b5e6a94fc --- /dev/null +++ b/final/autoconf/m4/libtool.m4 @@ -0,0 +1,6389 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/mklib' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.60)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=mklib +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic],[try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock],[avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AS_HELP_STRING([--with-tags@<:@=TAGS@:>@],[include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name "$tagname" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([enable_shared_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],[build shared libraries @<:@default=enable_shared_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]enable_shared_default) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([enable_static_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],[build static libraries @<:@default=enable_static_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]enable_static_default) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([enable_Fast_install_default], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],[optimize for fast installation @<:@default=enable_Fast_install_default@:>@]), + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]enable_Fast_install_default) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld],[assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/final/autoconf/m4/link_options.m4 b/final/autoconf/m4/link_options.m4 new file mode 100644 index 00000000000..4c5f2f435d0 --- /dev/null +++ b/final/autoconf/m4/link_options.m4 @@ -0,0 +1,108 @@ +# +# Get the linker version string. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_GET_VERSION], + [AC_CACHE_CHECK([for linker version],[llvm_cv_link_version], + [ + version_string="$(ld -v 2>&1 | head -1)" + + # Check for ld64. + if (echo "$version_string" | grep -q "ld64"); then + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#.*ld64-\([^ ]*\)#\1#") + else + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#[^0-9]*\([0-9.]*\).*#\1#") + fi + ]) + AC_DEFINE_UNQUOTED([HOST_LINK_VERSION],"$llvm_cv_link_version", + [Linker version detected at compile time.]) +]) + +# +# Determine if the system can handle the -R option being passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_USE_R], +[AC_CACHE_CHECK([for compiler -Wl,-R option],[llvm_cv_link_use_r], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_r=yes],[llvm_cv_link_use_r=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_r" = yes ; then + AC_DEFINE([HAVE_LINK_R],[1],[Define if you can use -Wl,-R. to pass -R. to the linker, in order to add the current directory to the dynamic linker search path.]) + fi +]) + +# +# Determine if the system can handle the -R option being passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_EXPORT_DYNAMIC], +[AC_CACHE_CHECK([for compiler -Wl,-export-dynamic option], + [llvm_cv_link_use_export_dynamic], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-export-dynamic" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_export_dynamic=yes],[llvm_cv_link_use_export_dynamic=no]) + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + AC_DEFINE([HAVE_LINK_EXPORT_DYNAMIC],[1],[Define if you can use -Wl,-export-dynamic.]) + fi +]) + +# +# Determine if the system can handle the --version-script option being +# passed to the linker. +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_LINK_VERSION_SCRIPT], +[AC_CACHE_CHECK([for compiler -Wl,--version-script option], + [llvm_cv_link_use_version_script], +[ AC_LANG_PUSH([C]) + oldcflags="$CFLAGS" + + # The following code is from the autoconf manual, + # "11.13: Limitations of Usual Tools". + # Create a temporary directory $tmp in $TMPDIR (default /tmp). + # Use mktemp if possible; otherwise fall back on mkdir, + # with $RANDOM to make collisions less likely. + : ${TMPDIR=/tmp} + { + tmp=` + (umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null + ` && + test -n "$tmp" && test -d "$tmp" + } || { + tmp=$TMPDIR/foo$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || exit $? + + echo "{" > "$tmp/export.map" + echo " global: main;" >> "$tmp/export.map" + echo " local: *;" >> "$tmp/export.map" + echo "};" >> "$tmp/export.map" + + CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [llvm_cv_link_use_version_script=yes],[llvm_cv_link_use_version_script=no]) + rm "$tmp/export.map" + rmdir "$tmp" + CFLAGS="$oldcflags" + AC_LANG_POP([C]) +]) +if test "$llvm_cv_link_use_version_script" = yes ; then + AC_SUBST(HAVE_LINK_VERSION_SCRIPT,1) + fi +]) + diff --git a/final/autoconf/m4/linux_mixed_64_32.m4 b/final/autoconf/m4/linux_mixed_64_32.m4 new file mode 100644 index 00000000000..123491f87e5 --- /dev/null +++ b/final/autoconf/m4/linux_mixed_64_32.m4 @@ -0,0 +1,17 @@ +# +# Some Linux machines run a 64-bit kernel with a 32-bit userspace. 'uname -m' +# shows these as x86_64. Ask the system 'gcc' what it thinks. +# +AC_DEFUN([AC_IS_LINUX_MIXED], +[AC_CACHE_CHECK(for 32-bit userspace on 64-bit system,llvm_cv_linux_mixed, +[ AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + ]])], + [llvm_cv_linux_mixed=no], + [llvm_cv_linux_mixed=yes]) + AC_LANG_POP([C]) +]) +]) diff --git a/final/autoconf/m4/ltdl.m4 b/final/autoconf/m4/ltdl.m4 new file mode 100644 index 00000000000..bc9e2ad2419 --- /dev/null +++ b/final/autoconf/m4/ltdl.m4 @@ -0,0 +1,418 @@ +## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- +## Copyright (C) 1999-2000 Free Software Foundation, Inc. +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 7 AC_LIB_LTDL + +# AC_WITH_LTDL +# ------------ +# Clients of libltdl can use this macro to allow the installer to +# choose between a shipped copy of the ltdl sources or a preinstalled +# version of the library. +AC_DEFUN([AC_WITH_LTDL], +[AC_REQUIRE([AC_LIB_LTDL]) +AC_SUBST([LIBLTDL]) +AC_SUBST([INCLTDL]) + +# Unless the user asks us to check, assume no installed ltdl exists. +use_installed_libltdl=no + +AC_ARG_WITH([included_ltdl], + [ --with-included-ltdl use the GNU ltdl sources included here]) + +if test "x$with_included_ltdl" != xyes; then + # We are not being forced to use the included libltdl sources, so + # decide whether there is a useful installed version we can use. + AC_CHECK_HEADER([ltdl.h], + [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], + [with_included_ltdl=no], + [with_included_ltdl=yes]) + ]) +fi + +if test "x$enable_ltdl_install" != xyes; then + # If the user did not specify an installable libltdl, then default + # to a convenience lib. + AC_LIBLTDL_CONVENIENCE +fi + +if test "x$with_included_ltdl" = xno; then + # If the included ltdl is not to be used. then Use the + # preinstalled libltdl we found. + AC_DEFINE([HAVE_LTDL], [1], + [Define this if a modern libltdl is already installed]) + LIBLTDL=-lltdl +fi + +# Report our decision... +AC_MSG_CHECKING([whether to use included libltdl]) +AC_MSG_RESULT([$with_included_ltdl]) + +AC_CONFIG_SUBDIRS([libltdl]) +])# AC_WITH_LTDL + + +# AC_LIB_LTDL +# ----------- +# Perform all the checks necessary for compilation of the ltdl objects +# -- including compiler checks and header checks. +AC_DEFUN([AC_LIB_LTDL], +[AC_PREREQ(2.60) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_C_CONST]) +AC_REQUIRE([AC_HEADER_STDC]) +AC_REQUIRE([AC_HEADER_DIRENT]) +AC_REQUIRE([_LT_AC_CHECK_DLFCN]) +AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) +AC_REQUIRE([AC_LTDL_SHLIBEXT]) +AC_REQUIRE([AC_LTDL_SHLIBPATH]) +AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) +AC_REQUIRE([AC_LTDL_OBJDIR]) +AC_REQUIRE([AC_LTDL_DLPREOPEN]) +AC_REQUIRE([AC_LTDL_DLLIB]) +AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) +AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) +AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) + +AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h]) +AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) +AC_CHECK_HEADERS([string.h strings.h], [break]) + +AC_CHECK_FUNCS([strchr index], [break]) +AC_CHECK_FUNCS([strrchr rindex], [break]) +AC_CHECK_FUNCS([memcpy bcopy], [break]) +AC_CHECK_FUNCS([memmove strcmp]) +AC_CHECK_FUNCS([closedir opendir readdir]) +])# AC_LIB_LTDL + + +# AC_LTDL_ENABLE_INSTALL +# ---------------------- +AC_DEFUN([AC_LTDL_ENABLE_INSTALL], +[AC_ARG_ENABLE([ltdl-install], + [AS_HELP_STRING([--enable-ltdl-install],[install libltdl])]) + +AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno) +AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno) +])# AC_LTDL_ENABLE_INSTALL + + +# AC_LTDL_SYS_DLOPEN_DEPLIBS +# -------------------------- +AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_CACHE_CHECK([whether deplibs are loaded by dlopen], + [libltdl_cv_sys_dlopen_deplibs], + [# PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[[45]]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[[12345]]*|irix6.[[01]]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[[1234]]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + ]) +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], + [Define if the OS needs help to load dependent libraries for dlopen().]) +fi +])# AC_LTDL_SYS_DLOPEN_DEPLIBS + + +# AC_LTDL_SHLIBEXT +# ---------------- +AC_DEFUN([AC_LTDL_SHLIBEXT], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which extension is used for loadable modules], + [libltdl_cv_shlibext], +[ +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + ]) +if test -n "$libltdl_cv_shlibext"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIB_EXT], ["$libltdl_cv_shlibext"], + [Define to the extension used for shared libraries, say, ".so".]) +fi +])# AC_LTDL_SHLIBEXT + + +# AC_LTDL_SHLIBPATH +# ----------------- +AC_DEFUN([AC_LTDL_SHLIBPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([which variable specifies run-time library path], + [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) +if test -n "$libltdl_cv_shlibpath_var"; then + AC_DEFINE_UNQUOTED([LTDL_SHLIBPATH_VAR], ["$libltdl_cv_shlibpath_var"], + [Define to the name of the environment variable that determines the dynamic library search path.]) +fi +])# AC_LTDL_SHLIBPATH + + +# AC_LTDL_SYSSEARCHPATH +# --------------------- +AC_DEFUN([AC_LTDL_SYSSEARCHPATH], +[AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) +AC_CACHE_CHECK([for the default library search path], + [libltdl_cv_sys_search_path], + [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + AC_DEFINE_UNQUOTED([LTDL_SYSSEARCHPATH], ["$sys_search_path"], + [Define to the system default library search path.]) +fi +])# AC_LTDL_SYSSEARCHPATH + + +# AC_LTDL_OBJDIR +# -------------- +AC_DEFUN([AC_LTDL_OBJDIR], +[AC_CACHE_CHECK([for objdir], + [libltdl_cv_objdir], + [libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + ]) +AC_DEFINE_UNQUOTED([LTDL_OBJDIR], ["$libltdl_cv_objdir/"], + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# AC_LTDL_OBJDIR + + +# AC_LTDL_DLPREOPEN +# ----------------- +AC_DEFUN([AC_LTDL_DLPREOPEN], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], + [libltdl_cv_preloaded_symbols], + [if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + ]) +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1], + [Define if libtool can extract symbol lists from object files.]) +fi +])# AC_LTDL_DLPREOPEN + + +# AC_LTDL_DLLIB +# ------------- +AC_DEFUN([AC_LTDL_DLLIB], +[LIBADD_DL= +AC_SUBST(LIBADD_DL) +AC_LANG_PUSH([C]) + +AC_CHECK_FUNC([shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.])], + [AC_CHECK_LIB([dld], [shl_load], + [AC_DEFINE([HAVE_SHL_LOAD], [1], + [Define if you have the shl_load function.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_LIB([dl], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H +# include +#endif + ]], [[dlopen(0, 0);]])],[AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"],[AC_CHECK_LIB([svld], [dlopen], + [AC_DEFINE([HAVE_LIBDL], [1], + [Define if you have the libdl library or equivalent.]) + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], + [AC_CHECK_LIB([dld], [dld_link], + [AC_DEFINE([HAVE_DLD], [1], + [Define if you have the GNU dld library.]) + LIBADD_DL="$LIBADD_DL -ldld"], + [AC_CHECK_FUNC([_dyld_func_lookup], + [AC_DEFINE([HAVE_DYLD], [1], + [Define if you have the _dyld_func_lookup function.])]) + ]) + ]) + ]) + ]) + ]) +]) + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + AC_CHECK_FUNCS([dlerror]) + LIBS="$lt_save_LIBS" +fi +AC_LANG_POP +])# AC_LTDL_DLLIB + + +# AC_LTDL_SYMBOL_USCORE +# --------------------- +# does the compiler prefix global symbols with an underscore? +AC_DEFUN([AC_LTDL_SYMBOL_USCORE], +[AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) +AC_CACHE_CHECK([for _ prefix in compiled symbols], + [ac_cv_sys_symbol_underscore], + [ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.c >&AS_MESSAGE_LOG_FD + fi + rm -rf conftest* + ]) +])# AC_LTDL_SYMBOL_USCORE + + +# AC_LTDL_DLSYM_USCORE +# -------------------- +AC_DEFUN([AC_LTDL_DLSYM_USCORE], +[AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + AC_CACHE_CHECK([whether we have to add an underscore for dlsym], + [libltdl_cv_need_uscore], + [libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + _LT_AC_TRY_DLOPEN_SELF( + [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], + [], [libltdl_cv_need_uscore=cross]) + LIBS="$save_LIBS" + ]) + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + AC_DEFINE([NEED_USCORE], [1], + [Define if dlsym() requires a leading underscore in symbol names.]) +fi +])# AC_LTDL_DLSYM_USCORE + +# AC_LTDL_FUNC_ARGZ +# ----------------- +AC_DEFUN([AC_LTDL_FUNC_ARGZ], +[AC_CHECK_HEADERS([argz.h]) + +AC_CHECK_TYPES([error_t], + [], + [AC_DEFINE([error_t], [int], + [Define to a type to use for `error_t' if it is not otherwise available.])], + [#if HAVE_ARGZ_H +# include +#endif]) + +AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) +])# AC_LTDL_FUNC_ARGZ diff --git a/final/autoconf/m4/need_dev_zero_for_mmap.m4 b/final/autoconf/m4/need_dev_zero_for_mmap.m4 new file mode 100644 index 00000000000..57b32283017 --- /dev/null +++ b/final/autoconf/m4/need_dev_zero_for_mmap.m4 @@ -0,0 +1,17 @@ +# +# When allocating RWX memory, check whether we need to use /dev/zero +# as the file descriptor or not. +# +AC_DEFUN([AC_NEED_DEV_ZERO_FOR_MMAP], +[AC_CACHE_CHECK([if /dev/zero is needed for mmap], +ac_cv_need_dev_zero_for_mmap, +[if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi +]) +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + AC_DEFINE([NEED_DEV_ZERO_FOR_MMAP],[1], + [Define if /dev/zero should be used when mapping RWX memory, or undefine if its not necessary]) +fi]) diff --git a/final/autoconf/m4/path_perl.m4 b/final/autoconf/m4/path_perl.m4 new file mode 100644 index 00000000000..406656cb032 --- /dev/null +++ b/final/autoconf/m4/path_perl.m4 @@ -0,0 +1,16 @@ +dnl Check for a reasonable version of Perl. +dnl $1 - Minimum Perl version. Typically 5.006. +dnl +AC_DEFUN([LLVM_PROG_PERL], [ +AC_PATH_PROG(PERL, [perl], [none]) +if test "$PERL" != "none"; then + AC_MSG_CHECKING(for Perl $1 or newer) + if $PERL -e 'use $1;' 2>&1 > /dev/null; then + AC_MSG_RESULT(yes) + else + PERL=none + AC_MSG_RESULT(not found) + fi +fi +]) + diff --git a/final/autoconf/m4/path_tclsh.m4 b/final/autoconf/m4/path_tclsh.m4 new file mode 100644 index 00000000000..85433de71cc --- /dev/null +++ b/final/autoconf/m4/path_tclsh.m4 @@ -0,0 +1,39 @@ +dnl This macro checks for tclsh which is required to run dejagnu. On some +dnl platforms (notably FreeBSD), tclsh is named tclshX.Y - this handles +dnl that for us so we can get the latest installed tclsh version. +dnl +AC_DEFUN([DJ_AC_PATH_TCLSH], [ +no_itcl=true +AC_MSG_CHECKING(for the tclsh program in tclinclude directory) +AC_ARG_WITH(tclinclude, + AS_HELP_STRING([--with-tclinclude], + [directory where tcl headers are]), + [with_tclinclude=${withval}],[with_tclinclude='']) +AC_CACHE_VAL(ac_cv_path_tclsh,[ +dnl first check to see if --with-itclinclude was specified +if test x"${with_tclinclude}" != x ; then + if test -f ${with_tclinclude}/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}; pwd)` + elif test -f ${with_tclinclude}/src/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}/src; pwd)` + else + AC_MSG_ERROR([${with_tclinclude} directory doesn't contain tclsh]) + fi +fi]) + +dnl see if one is installed +if test x"${ac_cv_path_tclsh}" = x ; then + AC_MSG_RESULT(none) + AC_PATH_PROGS([TCLSH],[tclsh8.4 tclsh8.4.8 tclsh8.4.7 tclsh8.4.6 tclsh8.4.5 tclsh8.4.4 tclsh8.4.3 tclsh8.4.2 tclsh8.4.1 tclsh8.4.0 tclsh8.3 tclsh8.3.5 tclsh8.3.4 tclsh8.3.3 tclsh8.3.2 tclsh8.3.1 tclsh8.3.0 tclsh]) + if test x"${TCLSH}" = x ; then + ac_cv_path_tclsh=''; + else + ac_cv_path_tclsh="${TCLSH}"; + fi +else + AC_MSG_RESULT(${ac_cv_path_tclsh}) + TCLSH="${ac_cv_path_tclsh}" + AC_SUBST(TCLSH) +fi +]) + diff --git a/final/autoconf/m4/rand48.m4 b/final/autoconf/m4/rand48.m4 new file mode 100644 index 00000000000..56705d85c9c --- /dev/null +++ b/final/autoconf/m4/rand48.m4 @@ -0,0 +1,12 @@ +# +# This function determins if the the srand48,drand48,lrand48 functions are +# available on this platform. +# +AC_DEFUN([AC_FUNC_RAND48],[ +AC_SINGLE_CXX_CHECK([ac_cv_func_rand48], + [srand48/lrand48/drand48], [], + [srand48(0);lrand48();drand48();]) +if test "$ac_cv_func_rand48" = "yes" ; then +AC_DEFINE([HAVE_RAND48],1,[Define to 1 if srand48/lrand48/drand48 exist in ]) +fi +]) diff --git a/final/autoconf/m4/sanity_check.m4 b/final/autoconf/m4/sanity_check.m4 new file mode 100644 index 00000000000..639fccca246 --- /dev/null +++ b/final/autoconf/m4/sanity_check.m4 @@ -0,0 +1,31 @@ +dnl Check a program for version sanity. The test runs a program, passes it an +dnl argument to make it print out some identification string, and filters that +dnl output with a regular expression. If the output is non-empty, the program +dnl passes the sanity check. +dnl $1 - Name or full path of the program to run +dnl $2 - Argument to pass to print out identification string +dnl $3 - grep RE to match identification string +dnl $4 - set to 1 to make errors only a warning +AC_DEFUN([CHECK_PROGRAM_SANITY], +[ +AC_MSG_CHECKING([sanity for program ]$1) +sanity="0" +sanity_path=`which $1 2>/dev/null` +if test "$?" -eq 0 -a -x "$sanity_path" ; then + sanity=`$1 $2 2>&1 | grep "$3"` + if test -z "$sanity" ; then + AC_MSG_RESULT([no]) + sanity="0" + if test "$4" -eq 1 ; then + AC_MSG_WARN([Program ]$1[ failed to pass sanity check.]) + else + AC_MSG_ERROR([Program ]$1[ failed to pass sanity check.]) + fi + else + AC_MSG_RESULT([yes]) + sanity="1" + fi +else + AC_MSG_RESULT([not found]) +fi +]) diff --git a/final/autoconf/m4/single_cxx_check.m4 b/final/autoconf/m4/single_cxx_check.m4 new file mode 100644 index 00000000000..21efa4bed35 --- /dev/null +++ b/final/autoconf/m4/single_cxx_check.m4 @@ -0,0 +1,10 @@ +dnl AC_SINGLE_CXX_CHECK(CACHEVAR, FUNCTION, HEADER, PROGRAM) +dnl $1, $2, $3, $4, +dnl +AC_DEFUN([AC_SINGLE_CXX_CHECK], + [AC_CACHE_CHECK([for $2 in $3], [$1], + [AC_LANG_PUSH([C++]) + AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include $3],[$4]),[$1=yes],[$1=no]) + AC_LANG_POP([C++])]) + ]) + diff --git a/final/autoconf/m4/visibility_inlines_hidden.m4 b/final/autoconf/m4/visibility_inlines_hidden.m4 new file mode 100644 index 00000000000..42ddbe9128b --- /dev/null +++ b/final/autoconf/m4/visibility_inlines_hidden.m4 @@ -0,0 +1,22 @@ +# +# Determine if the compiler accepts -fvisibility-inlines-hidden +# +# This macro is specific to LLVM. +# +AC_DEFUN([AC_CXX_USE_VISIBILITY_INLINES_HIDDEN], +[AC_CACHE_CHECK([for compiler -fvisibility-inlines-hidden option], + [llvm_cv_cxx_visibility_inlines_hidden], +[ AC_LANG_PUSH([C++]) + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [llvm_cv_cxx_visibility_inlines_hidden=yes],[llvm_cv_cxx_visibility_inlines_hidden=no]) + CXXFLAGS="$oldcxxflags" + AC_LANG_POP([C++]) +]) +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[1]) +else + AC_SUBST([ENABLE_VISIBILITY_INLINES_HIDDEN],[0]) +fi +]) diff --git a/final/autoconf/missing b/final/autoconf/missing new file mode 100755 index 00000000000..64b5f901dd5 --- /dev/null +++ b/final/autoconf/missing @@ -0,0 +1,353 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2004-09-07.08 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit 0 + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit 0 + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case "$1" in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/final/autoconf/mkinstalldirs b/final/autoconf/mkinstalldirs new file mode 100755 index 00000000000..1ee2d580177 --- /dev/null +++ b/final/autoconf/mkinstalldirs @@ -0,0 +1,150 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy + +scriptversion=2004-02-15.20 + +# Original author: Noah Friedman +# Created: 1993-05-16 +# Public domain. +# +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... + +Create each directory DIR (with mode MODE, if specified), including all +leading file name components. + +Report bugs to ." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --version) + echo "$0 $scriptversion" + exit 0 + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +# Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and +# mkdir -p a/c at the same time, both will detect that a is missing, +# one will create a, then the other will try to create a and die with +# a "File exists" error. This is a problem when calling mkinstalldirs +# from a parallel make. We use --version in the probe to restrict +# ourselves to GNU mkdir, which is thread-safe. +case $dirmode in + '') + if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then + # echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + else + # On NextStep and OpenStep, the `mkdir' command does not + # recognize any option. It will interpret all options as + # directories to create, and then abort because `.' already + # exists. + test -d ./-p && rmdir ./-p + test -d ./--version && rmdir ./--version + fi + ;; + *) + if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && + test ! -d ./--version; then + # echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + else + # Clean up after NextStep and OpenStep mkdir. + for d in ./-m ./-p ./--version "./$dirmode"; + do + test -d $d && rmdir $d + done + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + # echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + # echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/final/bindings/Makefile b/final/bindings/Makefile new file mode 100644 index 00000000000..c545b28854c --- /dev/null +++ b/final/bindings/Makefile @@ -0,0 +1,16 @@ +##===- bindings/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 + +PARALLEL_DIRS = $(BINDINGS_TO_BUILD) + +include $(LEVEL)/Makefile.common diff --git a/final/bindings/README.txt b/final/bindings/README.txt new file mode 100644 index 00000000000..7693cb2cead --- /dev/null +++ b/final/bindings/README.txt @@ -0,0 +1,3 @@ +This directory contains bindings for the LLVM compiler infrastructure to allow +programs written in languages other than C or C++ to take advantage of the LLVM +infrastructure--for instance, a self-hosted compiler front-end. diff --git a/final/bindings/ocaml/Makefile b/final/bindings/ocaml/Makefile new file mode 100644 index 00000000000..a89caefb4de --- /dev/null +++ b/final/bindings/ocaml/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/Makefile -----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +DIRS = llvm bitreader bitwriter analysis target executionengine transforms +ExtraMakefiles = $(PROJ_OBJ_DIR)/Makefile.ocaml + +ocamldoc: + $(Verb) for i in $(DIRS) ; do \ + $(MAKE) -C $$i ocamldoc; \ + done + +include $(LEVEL)/Makefile.common diff --git a/final/bindings/ocaml/Makefile.ocaml b/final/bindings/ocaml/Makefile.ocaml new file mode 100644 index 00000000000..40ecc9c08e0 --- /dev/null +++ b/final/bindings/ocaml/Makefile.ocaml @@ -0,0 +1,415 @@ +##===- tools/ml/Makefile -----------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# An ocaml library is a unique project type in the context of LLVM, so rules are +# here rather than in Makefile.rules. +# +# Reference materials on installing ocaml libraries: +# +# https://fedoraproject.org/wiki/Packaging/OCaml +# http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt +# +##===----------------------------------------------------------------------===## + +include $(LEVEL)/Makefile.config + +# CFLAGS needs to be set before Makefile.rules is included. +CXX.Flags += -I"$(shell $(OCAMLC) -where)" +C.Flags += -I"$(shell $(OCAMLC) -where)" + +include $(LEVEL)/Makefile.common + +# Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the +# user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. +PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) +OcamlDir := $(LibDir)/ocaml + +# Info from llvm-config and similar +ifndef IS_CLEANING_TARGET +ifdef UsedComponents +UsedLibs = $(shell $(LLVM_CONFIG) --libs $(UsedComponents)) +UsedLibNames = $(shell $(LLVM_CONFIG) --libnames $(UsedComponents)) +endif +endif + +# Tools +OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) +ifndef IS_CLEANING_TARGET +ifneq ($(ObjectsO),) +OCAMLAFLAGS += $(patsubst %,-cclib %, \ + $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ + $(shell $(LLVM_CONFIG) --ldflags)) \ + $(UsedLibs)) +else +OCAMLAFLAGS += $(patsubst %,-cclib %, \ + $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ + $(UsedLibs)) +endif +endif + +# -g was introduced in 3.10.0. +#ifneq ($(ENABLE_OPTIMIZED),1) +# OCAMLDEBUGFLAG := -g +#endif + +Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + -o) + +Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) + +ifdef OCAMLOPT +Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) +else +Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) +endif + +# Source files +ifndef OcamlSources1 +OcamlSources1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.ml)) +endif + +ifndef OcamlHeaders1 +OcamlHeaders1 := $(sort $(wildcard $(PROJ_SRC_DIR)/*.mli)) +endif + +OcamlSources2 := $(filter-out $(ExcludeSources),$(OcamlSources1)) +OcamlHeaders2 := $(filter-out $(ExcludeHeaders),$(OcamlHeaders1)) + +OcamlSources := $(OcamlSources2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) +OcamlHeaders := $(OcamlHeaders2:$(PROJ_SRC_DIR)/%=$(ObjDir)/%) + +# Intermediate files +ObjectsCMI := $(OcamlSources:%.ml=%.cmi) +ObjectsCMO := $(OcamlSources:%.ml=%.cmo) +ObjectsCMX := $(OcamlSources:%.ml=%.cmx) + +ifdef LIBRARYNAME +LibraryCMA := $(ObjDir)/$(LIBRARYNAME).cma +LibraryCMXA := $(ObjDir)/$(LIBRARYNAME).cmxa +endif + +ifdef TOOLNAME +ToolEXE := $(ObjDir)/$(TOOLNAME)$(EXEEXT) +endif + +# Output files +# The .cmo files are the only intermediates; all others are to be installed. +OutputsCMI := $(ObjectsCMI:$(ObjDir)/%.cmi=$(OcamlDir)/%.cmi) +OutputsCMX := $(ObjectsCMX:$(ObjDir)/%.cmx=$(OcamlDir)/%.cmx) +OutputLibs := $(UsedLibNames:%=$(OcamlDir)/%) + +ifdef LIBRARYNAME +LibraryA := $(OcamlDir)/lib$(LIBRARYNAME).a +OutputCMA := $(LibraryCMA:$(ObjDir)/%.cma=$(OcamlDir)/%.cma) +OutputCMXA := $(LibraryCMXA:$(ObjDir)/%.cmxa=$(OcamlDir)/%.cmxa) +endif + +ifdef TOOLNAME +ifdef EXAMPLE_TOOL +OutputEXE := $(ExmplDir)/$(strip $(TOOLNAME))$(EXEEXT) +else +OutputEXE := $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT) +endif +endif + +# Installation targets +DestLibs := $(UsedLibNames:%=$(PROJ_libocamldir)/%) + +ifdef LIBRARYNAME +DestA := $(PROJ_libocamldir)/lib$(LIBRARYNAME).a +DestCMA := $(PROJ_libocamldir)/$(LIBRARYNAME).cma +DestCMXA := $(PROJ_libocamldir)/$(LIBRARYNAME).cmxa +endif + +##===- Dependencies -------------------------------------------------------===## +# Copy the sources into the intermediate directory because older ocamlc doesn't +# support -o except when linking (outputs are placed next to inputs). + +$(ObjDir)/%.mli: $(PROJ_SRC_DIR)/%.mli $(ObjDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.ml: $(PROJ_SRC_DIR)/%.ml $(ObjDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) + +ifdef LIBRARYNAME +$(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ + $(OcamlDir)/.dir $(ObjDir)/.dir + $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + +-include $(ObjDir)/$(LIBRARYNAME).ocamldep +endif + +ifdef TOOLNAME +$(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ + $(OcamlDir)/.dir $(ObjDir)/.dir + $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + +-include $(ObjDir)/$(TOOLNAME).ocamldep +endif + +##===- Build static library from C sources --------------------------------===## + +ifdef LibraryA +all-local:: $(LibraryA) +clean-local:: clean-a +install-local:: install-a +uninstall-local:: uninstall-a + +$(LibraryA): $(ObjectsO) $(OcamlDir)/.dir + $(Echo) "Building $(BuildMode) $(notdir $@)" + -$(Verb) $(RM) -f $@ + $(Verb) $(Archive) $@ $(ObjectsO) + $(Verb) $(Ranlib) $@ + +clean-a:: + -$(Verb) $(RM) -f $(LibraryA) + +install-a:: $(LibraryA) + $(Echo) "Installing $(BuildMode) $(DestA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(INSTALL) $(LibraryA) $(DestA) + $(Verb) + +uninstall-a:: + $(Echo) "Uninstalling $(DestA)" + -$(Verb) $(RM) -f $(DestA) +endif + + +##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## + +all-local:: build-deplibs +clean-local:: clean-deplibs +install-local:: install-deplibs +uninstall-local:: uninstall-deplibs + +build-deplibs: $(OutputLibs) + +$(OcamlDir)/%.a: $(LibDir)/%.a + $(Verb) ln -sf $< $@ + +$(OcamlDir)/%.o: $(LibDir)/%.o + $(Verb) ln -sf $< $@ + +clean-deplibs: + $(Verb) $(RM) -f $(OutputLibs) + +install-deplibs: + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) for i in $(DestLibs:$(PROJ_libocamldir)/%=%); do \ + ln -sf "$(PROJ_libdir)/$$i" "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-deplibs: + $(Verb) $(RM) -f $(DestLibs) + + +##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## + +ifneq ($(OcamlHeaders),) +all-local:: build-cmis +clean-local:: clean-cmis +install-local:: install-cmis +uninstall-local:: uninstall-cmis + +build-cmis: $(OutputsCMI) + +$(OcamlDir)/%.cmi: $(ObjDir)/%.cmi $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.cmi: $(ObjDir)/%.mli $(ObjDir)/.dir + $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMI) $@ $< + +clean-cmis:: + -$(Verb) $(RM) -f $(OutputsCMI) + +# Also install the .mli's (headers) as documentation. +install-cmis: $(OutputsCMI) $(OcamlHeaders) + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(ObjDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-cmis:: + $(Verb) for i in $(OutputsCMI:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f "$(PROJ_libocamldir)/$$i"; \ + done + $(Verb) for i in $(OcamlHeaders:$(ObjDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f "$(PROJ_libocamldir)/$$i"; \ + done +endif + + +##===- Build ocaml bytecode archive (.ml's -> .cmo's -> .cma) -------------===## + +$(ObjDir)/%.cmo: $(ObjDir)/%.ml + $(Echo) "Compiling $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMO) $@ $< + +ifdef LIBRARYNAME +all-local:: $(OutputCMA) +clean-local:: clean-cma +install-local:: install-cma +uninstall-local:: uninstall-cma + +$(OutputCMA): $(LibraryCMA) $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +$(LibraryCMA): $(ObjectsCMO) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.CMA) $@ $(ObjectsCMO) + +clean-cma:: + $(Verb) $(RM) -f $(OutputCMA) $(UsedLibNames:%=$(OcamlDir)/%) + +install-cma:: $(OutputCMA) + $(Echo) "Installing $(BuildMode) $(DestCMA)" + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Verb) $(DataInstall) $(OutputCMA) "$(DestCMA)" + +uninstall-cma:: + $(Echo) "Uninstalling $(DestCMA)" + -$(Verb) $(RM) -f $(DestCMA) +endif + +##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## + +# The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. +# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config. +ifdef OCAMLOPT + +$(OcamlDir)/%.cmx: $(ObjDir)/%.cmx + $(Verb) $(CP) -f $< $@ + +$(ObjDir)/%.cmx: $(ObjDir)/%.ml + $(Echo) "Compiling optimized $(notdir $<) for $(BuildMode) build" + $(Verb) $(Compile.CMX) $@ $< + +ifdef LIBRARYNAME +all-local:: $(OutputCMXA) $(OutputsCMX) +clean-local:: clean-cmxa +install-local:: install-cmxa +uninstall-local:: uninstall-cmxa + +$(OutputCMXA): $(LibraryCMXA) + $(Verb) $(CP) -f $< $@ + $(Verb) $(CP) -f $(<:.cmxa=.a) $(@:.cmxa=.a) + +$(LibraryCMXA): $(ObjectsCMX) + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.CMXA) $@ $(ObjectsCMX) + $(Verb) $(RM) -f $(@:.cmxa=.o) + +clean-cmxa:: + $(Verb) $(RM) -f $(OutputCMXA) $(OutputCMXA:.cmxa=.a) $(OutputsCMX) + +install-cmxa:: $(OutputCMXA) $(OutputsCMX) + $(Verb) $(MKDIR) $(PROJ_libocamldir) + $(Echo) "Installing $(BuildMode) $(DestCMXA)" + $(Verb) $(DataInstall) $(OutputCMXA) $(DestCMXA) + $(Echo) "Installing $(BuildMode) $(DestCMXA:.cmxa=.a)" + $(Verb) $(DataInstall) $(OutputCMXA:.cmxa=.a) $(DestCMXA:.cmxa=.a) + $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Installing $(BuildMode) $(PROJ_libocamldir)/$$i"; \ + $(DataInstall) $(OcamlDir)/$$i "$(PROJ_libocamldir)/$$i"; \ + done + +uninstall-cmxa:: + $(Echo) "Uninstalling $(DestCMXA)" + $(Verb) $(RM) -f $(DestCMXA) + $(Echo) "Uninstalling $(DestCMXA:.cmxa=.a)" + $(Verb) $(RM) -f $(DestCMXA:.cmxa=.a) + $(Verb) for i in $(OutputsCMX:$(OcamlDir)/%=%); do \ + $(EchoCmd) "Uninstalling $(PROJ_libocamldir)/$$i"; \ + $(RM) -f $(PROJ_libocamldir)/$$i; \ + done +endif +endif + +##===- Build executables --------------------------------------------------===## + +ifdef TOOLNAME +all-local:: $(OutputEXE) +clean-local:: clean-exe + +$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir + $(Verb) $(CP) -f $< $@ + +ifndef OCAMLOPT +$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.EXE) $@ $(ObjectsCMO) +else +$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir + $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" + $(Verb) $(Archive.EXE) $@ $(ObjectsCMX) +endif +endif + +##===- Generate documentation ---------------------------------------------===## + +$(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) + $(Echo) "Documenting $(notdir $@)" + $(Verb) $(OCAMLDOC) -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) + +ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc + +##===- Debugging gunk -----------------------------------------------------===## +printvars:: printcamlvars + +printcamlvars:: + $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' + $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' + $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' + $(Echo) "OCAMLC : " '$(OCAMLC)' + $(Echo) "OCAMLOPT : " '$(OCAMLOPT)' + $(Echo) "OCAMLDEP : " '$(OCAMLDEP)' + $(Echo) "Compile.CMI : " '$(Compile.CMI)' + $(Echo) "Compile.CMO : " '$(Compile.CMO)' + $(Echo) "Archive.CMA : " '$(Archive.CMA)' + $(Echo) "Compile.CMX : " '$(Compile.CMX)' + $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' + $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' + $(Echo) "LibraryCMA : " '$(LibraryCMA)' + $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' + $(Echo) "OcamlSources1: " '$(OcamlSources1)' + $(Echo) "OcamlSources2: " '$(OcamlSources2)' + $(Echo) "OcamlSources : " '$(OcamlSources)' + $(Echo) "OcamlHeaders1: " '$(OcamlHeaders1)' + $(Echo) "OcamlHeaders2: " '$(OcamlHeaders2)' + $(Echo) "OcamlHeaders : " '$(OcamlHeaders)' + $(Echo) "ObjectsCMI : " '$(ObjectsCMI)' + $(Echo) "ObjectsCMO : " '$(ObjectsCMO)' + $(Echo) "ObjectsCMX : " '$(ObjectsCMX)' + $(Echo) "OCAML_LIBDIR : " '$(OCAML_LIBDIR)' + $(Echo) "DestA : " '$(DestA)' + $(Echo) "DestCMA : " '$(DestCMA)' + $(Echo) "DestCMXA : " '$(DestCMXA)' + $(Echo) "UsedLibs : " '$(UsedLibs)' + $(Echo) "UsedLibNames : " '$(UsedLibNames)' + +.PHONY: printcamlvars build-cmis \ + clean-a clean-cmis clean-cma clean-cmxa \ + install-a install-cmis install-cma install-cmxa \ + install-exe \ + uninstall-a uninstall-cmis uninstall-cma uninstall-cmxa \ + uninstall-exe diff --git a/final/bindings/ocaml/analysis/Makefile b/final/bindings/ocaml/analysis/Makefile new file mode 100644 index 00000000000..cbfcb246704 --- /dev/null +++ b/final/bindings/ocaml/analysis/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/analysis/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_analysis interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_analysis +UsedComponents := analysis +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/analysis/analysis_ocaml.c b/final/bindings/ocaml/analysis/analysis_ocaml.c new file mode 100644 index 00000000000..97167055f70 --- /dev/null +++ b/final/bindings/ocaml/analysis/analysis_ocaml.c @@ -0,0 +1,72 @@ +/*===-- analysis_ocaml.c - LLVM Ocaml Glue ----------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Analysis.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" + + +/* Llvm.llmodule -> string option */ +CAMLprim value llvm_verify_module(LLVMModuleRef M) { + CAMLparam0(); + CAMLlocal2(String, Option); + + char *Message; + int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message); + + if (0 == Result) { + Option = Val_int(0); + } else { + Option = alloc(1, 0); + String = copy_string(Message); + Store_field(Option, 0, String); + } + + LLVMDisposeMessage(Message); + + CAMLreturn(Option); +} + +/* Llvm.llvalue -> bool */ +CAMLprim value llvm_verify_function(LLVMValueRef Fn) { + return Val_bool(LLVMVerifyFunction(Fn, LLVMReturnStatusAction) == 0); +} + +/* Llvm.llmodule -> unit */ +CAMLprim value llvm_assert_valid_module(LLVMModuleRef M) { + LLVMVerifyModule(M, LLVMAbortProcessAction, 0); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_assert_valid_function(LLVMValueRef Fn) { + LLVMVerifyFunction(Fn, LLVMAbortProcessAction); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_view_function_cfg(LLVMValueRef Fn) { + LLVMViewFunctionCFG(Fn); + return Val_unit; +} + +/* Llvm.llvalue -> unit */ +CAMLprim value llvm_view_function_cfg_only(LLVMValueRef Fn) { + LLVMViewFunctionCFGOnly(Fn); + return Val_unit; +} diff --git a/final/bindings/ocaml/analysis/llvm_analysis.ml b/final/bindings/ocaml/analysis/llvm_analysis.ml new file mode 100644 index 00000000000..fc4d2037074 --- /dev/null +++ b/final/bindings/ocaml/analysis/llvm_analysis.ml @@ -0,0 +1,22 @@ +(*===-- llvm_analysis.ml - LLVM Ocaml Interface -----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" +external view_function_cfg : Llvm.llvalue -> unit = "llvm_view_function_cfg" +external view_function_cfg_only : Llvm.llvalue -> unit + = "llvm_view_function_cfg_only" diff --git a/final/bindings/ocaml/analysis/llvm_analysis.mli b/final/bindings/ocaml/analysis/llvm_analysis.mli new file mode 100644 index 00000000000..793f482e3c6 --- /dev/null +++ b/final/bindings/ocaml/analysis/llvm_analysis.mli @@ -0,0 +1,46 @@ +(*===-- llvm_analysis.mli - LLVM Ocaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Intermediate representation analysis. + + This interface provides an ocaml API for LLVM IR analyses, the classes in + the Analysis library. *) + +(** [verify_module m] returns [None] if the module [m] is valid, and + [Some reason] if it is invalid. [reason] is a string containing a + human-readable validation report. See [llvm::verifyModule]. *) +external verify_module : Llvm.llmodule -> string option = "llvm_verify_module" + +(** [verify_function f] returns [None] if the function [f] is valid, and + [Some reason] if it is invalid. [reason] is a string containing a + human-readable validation report. See [llvm::verifyFunction]. *) +external verify_function : Llvm.llvalue -> bool = "llvm_verify_function" + +(** [verify_module m] returns if the module [m] is valid, but prints a + validation report to [stderr] and aborts the program if it is invalid. See + [llvm::verifyModule]. *) +external assert_valid_module : Llvm.llmodule -> unit + = "llvm_assert_valid_module" + +(** [verify_function f] returns if the function [f] is valid, but prints a + validation report to [stderr] and aborts the program if it is invalid. See + [llvm::verifyFunction]. *) +external assert_valid_function : Llvm.llvalue -> unit + = "llvm_assert_valid_function" + +(** [view_function_cfg f] opens up a ghostscript window displaying the CFG of + the current function with the code for each basic block inside. + See [llvm::Function::viewCFG]. *) +external view_function_cfg : Llvm.llvalue -> unit = "llvm_view_function_cfg" + +(** [view_function_cfg_only f] works just like [view_function_cfg], but does not + include the contents of basic blocks into the nodes. + See [llvm::Function::viewCFGOnly]. *) +external view_function_cfg_only : Llvm.llvalue -> unit + = "llvm_view_function_cfg_only" diff --git a/final/bindings/ocaml/bitreader/Makefile b/final/bindings/ocaml/bitreader/Makefile new file mode 100644 index 00000000000..a1c7de895cf --- /dev/null +++ b/final/bindings/ocaml/bitreader/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/bitreader/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_bitreader interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_bitreader +UsedComponents := bitreader +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/bitreader/bitreader_ocaml.c b/final/bindings/ocaml/bitreader/bitreader_ocaml.c new file mode 100644 index 00000000000..ef72ce213d8 --- /dev/null +++ b/final/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -0,0 +1,73 @@ +/*===-- bitwriter_ocaml.c - LLVM Ocaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/BitReader.h" +#include "caml/alloc.h" +#include "caml/fail.h" +#include "caml/memory.h" + + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_bitreader_error_exn; + +CAMLprim value llvm_register_bitreader_exns(value Error) { + llvm_bitreader_error_exn = Field(Error, 0); + register_global_root(&llvm_bitreader_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ +CAMLprim value llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + char *Message; + + LLVMModuleRef M; + if (LLVMGetBitcodeModuleInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_bitreader_error_exn, Message); + + CAMLreturn((value) M); +} + +/* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ +CAMLprim value llvm_parse_bitcode(LLVMContextRef C, + LLVMMemoryBufferRef MemBuf) { + CAMLparam0(); + CAMLlocal2(Variant, MessageVal); + LLVMModuleRef M; + char *Message; + + if (LLVMParseBitcodeInContext(C, MemBuf, &M, &Message)) + llvm_raise(llvm_bitreader_error_exn, Message); + + CAMLreturn((value) M); +} diff --git a/final/bindings/ocaml/bitreader/llvm_bitreader.ml b/final/bindings/ocaml/bitreader/llvm_bitreader.ml new file mode 100644 index 00000000000..8b9d01d8fb0 --- /dev/null +++ b/final/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -0,0 +1,20 @@ +(*===-- llvm_bitreader.ml - LLVM Ocaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns : exn -> unit = "llvm_register_bitreader_exns" +let _ = register_exns (Error "") + +external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" + +external parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_bitcode" diff --git a/final/bindings/ocaml/bitreader/llvm_bitreader.mli b/final/bindings/ocaml/bitreader/llvm_bitreader.mli new file mode 100644 index 00000000000..1d333191c1d --- /dev/null +++ b/final/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -0,0 +1,29 @@ +(*===-- llvm_bitreader.mli - LLVM Ocaml Interface ---------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Bitcode reader. + + This interface provides an ocaml API for the LLVM bitcode reader, the + classes in the Bitreader library. *) + +exception Error of string + +(** [get_module context mb] reads the bitcode for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::getBitcodeModule]. *) +val get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + + +(** [parse_bitcode context mb] parses the bitcode for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::ParseBitcodeFile]. *) +val parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + diff --git a/final/bindings/ocaml/bitwriter/Makefile b/final/bindings/ocaml/bitwriter/Makefile new file mode 100644 index 00000000000..cec0a59c31b --- /dev/null +++ b/final/bindings/ocaml/bitwriter/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/bitwriter/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_bitwriter interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_bitwriter +UsedComponents := bitwriter +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/final/bindings/ocaml/bitwriter/bitwriter_ocaml.c new file mode 100644 index 00000000000..53c93cbdfe9 --- /dev/null +++ b/final/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -0,0 +1,45 @@ +/*===-- bitwriter_ocaml.c - LLVM Ocaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/BitWriter.h" +#include "llvm-c/Core.h" +#include "caml/alloc.h" +#include "caml/mlvalues.h" +#include "caml/memory.h" + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Llvm.llmodule -> string -> bool */ +CAMLprim value llvm_write_bitcode_file(value M, value Path) { + int res = LLVMWriteBitcodeToFile((LLVMModuleRef) M, String_val(Path)); + return Val_bool(res == 0); +} + +/* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */ +CAMLprim value llvm_write_bitcode_to_fd(value U, value M, value FD) { + int Unbuffered; + int res; + + if (U == Val_int(0)) { + Unbuffered = 0; + } else { + Unbuffered = Bool_val(Field(U,0)); + } + + res = LLVMWriteBitcodeToFD((LLVMModuleRef) M, Int_val(FD), 0, Unbuffered); + return Val_bool(res == 0); +} diff --git a/final/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/final/bindings/ocaml/bitwriter/llvm_bitwriter.ml new file mode 100644 index 00000000000..3e69a3cc8fb --- /dev/null +++ b/final/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -0,0 +1,25 @@ +(*===-- llvm_bitwriter.ml - LLVM Ocaml Interface ----------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------=== + * + * This interface provides an ocaml API for the LLVM intermediate + * representation, the classes in the VMCore library. + * + *===----------------------------------------------------------------------===*) + + +(* Writes the bitcode for module the given path. Returns true if successful. *) +external write_bitcode_file : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" + +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +let output_bitcode ?unbuffered channel m = + write_bitcode_to_fd ?unbuffered m (Unix.descr_of_out_channel channel) diff --git a/final/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/final/bindings/ocaml/bitwriter/llvm_bitwriter.mli new file mode 100644 index 00000000000..ea9a87600a7 --- /dev/null +++ b/final/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -0,0 +1,30 @@ +(*===-- llvm_bitwriter.mli - LLVM Ocaml Interface ---------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Bitcode writer. + + This interface provides an ocaml API for the LLVM bitcode writer, the + classes in the Bitwriter library. *) + +(** [write_bitcode_file m path] writes the bitcode for module [m] to the file at + [path]. Returns [true] if successful, [false] otherwise. *) +external write_bitcode_file : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" + +(** [write_bitcode_to_fd ~unbuffered fd m] writes the bitcode for module + [m] to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +(** [output_bitcode ~unbuffered c m] writes the bitcode for module [m] + to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +val output_bitcode : ?unbuffered:bool -> out_channel -> Llvm.llmodule -> bool diff --git a/final/bindings/ocaml/executionengine/Makefile b/final/bindings/ocaml/executionengine/Makefile new file mode 100644 index 00000000000..5fa3f22048f --- /dev/null +++ b/final/bindings/ocaml/executionengine/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/executionengine/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_executionengine interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_executionengine +UsedComponents := executionengine jit interpreter native +UsedOcamlInterfaces := llvm llvm_target + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/executionengine/executionengine_ocaml.c b/final/bindings/ocaml/executionengine/executionengine_ocaml.c new file mode 100644 index 00000000000..5b1e32efefc --- /dev/null +++ b/final/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -0,0 +1,323 @@ +/*===-- executionengine_ocaml.c - LLVM Ocaml Glue ---------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Target.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/memory.h" +#include +#include + +/* Force the LLVM interpreter and JIT to be linked in. */ +void llvm_initialize(void) { + LLVMLinkInInterpreter(); + LLVMLinkInJIT(); +} + +/* unit -> bool */ +CAMLprim value llvm_initialize_native_target(value Unit) { + return Val_bool(LLVMInitializeNativeTarget()); +} + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_ee_error_exn; + +CAMLprim value llvm_register_ee_exns(value Error) { + llvm_ee_error_exn = Field(Error, 0); + register_global_root(&llvm_ee_error_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + + +/*--... Operations on generic values .......................................--*/ + +#define Genericvalue_val(v) (*(LLVMGenericValueRef *)(Data_custom_val(v))) + +static void llvm_finalize_generic_value(value GenVal) { + LLVMDisposeGenericValue(Genericvalue_val(GenVal)); +} + +static struct custom_operations generic_value_ops = { + (char *) "LLVMGenericValue", + llvm_finalize_generic_value, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +}; + +static value alloc_generic_value(LLVMGenericValueRef Ref) { + value Val = alloc_custom(&generic_value_ops, sizeof(LLVMGenericValueRef), 0, 1); + Genericvalue_val(Val) = Ref; + return Val; +} + +/* Llvm.lltype -> float -> t */ +CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) { + CAMLparam1(N); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfFloat(Ty, Double_val(N)))); +} + +/* 'a -> t */ +CAMLprim value llvm_genericvalue_of_pointer(value V) { + CAMLparam1(V); + CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)))); +} + +/* Llvm.lltype -> int -> t */ +CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) { + return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1)); +} + +/* Llvm.lltype -> int32 -> t */ +CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) { + CAMLparam1(Int32); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32), 1))); +} + +/* Llvm.lltype -> nativeint -> t */ +CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) { + CAMLparam1(NatInt); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Nativeint_val(NatInt), 1))); +} + +/* Llvm.lltype -> int64 -> t */ +CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) { + CAMLparam1(Int64); + CAMLreturn(alloc_generic_value( + LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64), 1))); +} + +/* Llvm.lltype -> t -> float */ +CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) { + CAMLparam1(GenVal); + CAMLreturn(copy_double( + LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal)))); +} + +/* t -> 'a */ +CAMLprim value llvm_genericvalue_as_pointer(value GenVal) { + return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal))); +} + +/* t -> int */ +CAMLprim value llvm_genericvalue_as_int(value GenVal) { + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) + && "Generic value too wide to treat as an int!"); + return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)); +} + +/* t -> int32 */ +CAMLprim value llvm_genericvalue_as_int32(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32 + && "Generic value too wide to treat as an int32!"); + CAMLreturn(copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); +} + +/* t -> int64 */ +CAMLprim value llvm_genericvalue_as_int64(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64 + && "Generic value too wide to treat as an int64!"); + CAMLreturn(copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); +} + +/* t -> nativeint */ +CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) { + CAMLparam1(GenVal); + assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) + && "Generic value too wide to treat as a nativeint!"); + CAMLreturn(copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1))); +} + + +/*--... Operations on execution engines ....................................--*/ + +/* llmodule -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleRef M) { + LLVMExecutionEngineRef Interp; + char *Error; + if (LLVMCreateExecutionEngineForModule(&Interp, M, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return Interp; +} + +/* llmodule -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef +llvm_ee_create_interpreter(LLVMModuleRef M) { + LLVMExecutionEngineRef Interp; + char *Error; + if (LLVMCreateInterpreterForModule(&Interp, M, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return Interp; +} + +/* llmodule -> int -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef +llvm_ee_create_jit(LLVMModuleRef M, value OptLevel) { + LLVMExecutionEngineRef JIT; + char *Error; + if (LLVMCreateJITCompilerForModule(&JIT, M, Int_val(OptLevel), &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return JIT; +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_dispose(LLVMExecutionEngineRef EE) { + LLVMDisposeExecutionEngine(EE); + return Val_unit; +} + +/* llmodule -> ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { + LLVMAddModule(EE, M); + return Val_unit; +} + +/* llmodule -> ExecutionEngine.t -> llmodule */ +CAMLprim LLVMModuleRef llvm_ee_remove_module(LLVMModuleRef M, + LLVMExecutionEngineRef EE) { + LLVMModuleRef RemovedModule; + char *Error; + if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) + llvm_raise(llvm_ee_error_exn, Error); + return RemovedModule; +} + +/* string -> ExecutionEngine.t -> llvalue option */ +CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) { + CAMLparam1(Name); + CAMLlocal1(Option); + LLVMValueRef Found; + if (LLVMFindFunction(EE, String_val(Name), &Found)) + CAMLreturn(Val_unit); + Option = alloc(1, 0); + Field(Option, 0) = Val_op(Found); + CAMLreturn(Option); +} + +/* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */ +CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args, + LLVMExecutionEngineRef EE) { + unsigned NumArgs; + LLVMGenericValueRef Result, *GVArgs; + unsigned I; + + NumArgs = Wosize_val(Args); + GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef)); + for (I = 0; I != NumArgs; ++I) + GVArgs[I] = Genericvalue_val(Field(Args, I)); + + Result = LLVMRunFunction(EE, F, NumArgs, GVArgs); + + free(GVArgs); + return alloc_generic_value(Result); +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_run_static_ctors(LLVMExecutionEngineRef EE) { + LLVMRunStaticConstructors(EE); + return Val_unit; +} + +/* ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) { + LLVMRunStaticDestructors(EE); + return Val_unit; +} + +/* llvalue -> string array -> (string * string) array -> ExecutionEngine.t -> + int */ +CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F, + value Args, value Env, + LLVMExecutionEngineRef EE) { + CAMLparam2(Args, Env); + int I, NumArgs, NumEnv, EnvSize, Result; + const char **CArgs, **CEnv; + char *CEnvBuf, *Pos; + + NumArgs = Wosize_val(Args); + NumEnv = Wosize_val(Env); + + /* Build the environment. */ + CArgs = (const char **) malloc(NumArgs * sizeof(char*)); + for (I = 0; I != NumArgs; ++I) + CArgs[I] = String_val(Field(Args, I)); + + /* Compute the size of the environment string buffer. */ + for (I = 0, EnvSize = 0; I != NumEnv; ++I) { + EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1; + EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1; + } + + /* Build the environment. */ + CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*)); + CEnvBuf = (char*) malloc(EnvSize); + Pos = CEnvBuf; + for (I = 0; I != NumEnv; ++I) { + char *Name = String_val(Field(Field(Env, I), 0)), + *Value = String_val(Field(Field(Env, I), 1)); + int NameLen = strlen(Name), + ValueLen = strlen(Value); + + CEnv[I] = Pos; + memcpy(Pos, Name, NameLen); + Pos += NameLen; + *Pos++ = '='; + memcpy(Pos, Value, ValueLen); + Pos += ValueLen; + *Pos++ = '\0'; + } + CEnv[NumEnv] = NULL; + + Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv); + + free(CArgs); + free(CEnv); + free(CEnvBuf); + + CAMLreturn(Val_int(Result)); +} + +/* llvalue -> ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F, + LLVMExecutionEngineRef EE) { + LLVMFreeMachineCodeForFunction(EE, F); + return Val_unit; +} + diff --git a/final/bindings/ocaml/executionengine/llvm_executionengine.ml b/final/bindings/ocaml/executionengine/llvm_executionengine.ml new file mode 100644 index 00000000000..a8535b24640 --- /dev/null +++ b/final/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -0,0 +1,112 @@ +(*===-- llvm_executionengine.ml - LLVM Ocaml Interface ----------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +exception Error of string + +external register_exns: exn -> unit + = "llvm_register_ee_exns" + + +module GenericValue = struct + type t + + external of_float: Llvm.lltype -> float -> t + = "llvm_genericvalue_of_float" + external of_pointer: 'a -> t + = "llvm_genericvalue_of_pointer" + external of_int32: Llvm.lltype -> int32 -> t + = "llvm_genericvalue_of_int32" + external of_int: Llvm.lltype -> int -> t + = "llvm_genericvalue_of_int" + external of_nativeint: Llvm.lltype -> nativeint -> t + = "llvm_genericvalue_of_nativeint" + external of_int64: Llvm.lltype -> int64 -> t + = "llvm_genericvalue_of_int64" + + external as_float: Llvm.lltype -> t -> float + = "llvm_genericvalue_as_float" + external as_pointer: t -> 'a + = "llvm_genericvalue_as_pointer" + external as_int32: t -> int32 + = "llvm_genericvalue_as_int32" + external as_int: t -> int + = "llvm_genericvalue_as_int" + external as_nativeint: t -> nativeint + = "llvm_genericvalue_as_nativeint" + external as_int64: t -> int64 + = "llvm_genericvalue_as_int64" +end + + +module ExecutionEngine = struct + type t + + (* FIXME: Ocaml is not running this setup code unless we use 'val' in the + interface, which causes the emission of a stub for each function; + using 'external' in the module allows direct calls into + ocaml_executionengine.c. This is hardly fatal, but it is unnecessary + overhead on top of the two stubs that are already invoked for each + call into LLVM. *) + let _ = register_exns (Error "") + + external create: Llvm.llmodule -> t + = "llvm_ee_create" + external create_interpreter: Llvm.llmodule -> t + = "llvm_ee_create_interpreter" + external create_jit: Llvm.llmodule -> int -> t + = "llvm_ee_create_jit" + external dispose: t -> unit + = "llvm_ee_dispose" + external add_module: Llvm.llmodule -> t -> unit + = "llvm_ee_add_module" + external remove_module: Llvm.llmodule -> t -> Llvm.llmodule + = "llvm_ee_remove_module" + external find_function: string -> t -> Llvm.llvalue option + = "llvm_ee_find_function" + external run_function: Llvm.llvalue -> GenericValue.t array -> t -> + GenericValue.t + = "llvm_ee_run_function" + external run_static_ctors: t -> unit + = "llvm_ee_run_static_ctors" + external run_static_dtors: t -> unit + = "llvm_ee_run_static_dtors" + external run_function_as_main: Llvm.llvalue -> string array -> + (string * string) array -> t -> int + = "llvm_ee_run_function_as_main" + external free_machine_code: Llvm.llvalue -> t -> unit + = "llvm_ee_free_machine_code" + + external target_data: t -> Llvm_target.TargetData.t + = "LLVMGetExecutionEngineTargetData" + + (* The following are not bound. Patches are welcome. + + get_target_data: t -> lltargetdata + add_global_mapping: llvalue -> llgenericvalue -> t -> unit + clear_all_global_mappings: t -> unit + update_global_mapping: llvalue -> llgenericvalue -> t -> unit + get_pointer_to_global_if_available: llvalue -> t -> llgenericvalue + get_pointer_to_global: llvalue -> t -> llgenericvalue + get_pointer_to_function: llvalue -> t -> llgenericvalue + get_pointer_to_function_or_stub: llvalue -> t -> llgenericvalue + get_global_value_at_address: llgenericvalue -> t -> llvalue option + store_value_to_memory: llgenericvalue -> llgenericvalue -> lltype -> unit + initialize_memory: llvalue -> llgenericvalue -> t -> unit + recompile_and_relink_function: llvalue -> t -> llgenericvalue + get_or_emit_global_variable: llvalue -> t -> llgenericvalue + disable_lazy_compilation: t -> unit + lazy_compilation_enabled: t -> bool + install_lazy_function_creator: (string -> llgenericvalue) -> t -> unit + + *) +end + +external initialize_native_target : unit -> bool + = "llvm_initialize_native_target" diff --git a/final/bindings/ocaml/executionengine/llvm_executionengine.mli b/final/bindings/ocaml/executionengine/llvm_executionengine.mli new file mode 100644 index 00000000000..166b7bcddca --- /dev/null +++ b/final/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -0,0 +1,163 @@ +(*===-- llvm_executionengine.mli - LLVM Ocaml Interface ---------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** JIT Interpreter. + + This interface provides an ocaml API for LLVM execution engine (JIT/ + interpreter), the classes in the ExecutionEngine library. *) + +exception Error of string + +module GenericValue: sig + (** [GenericValue.t] is a boxed union type used to portably pass arguments to + and receive values from the execution engine. It supports only a limited + selection of types; for more complex argument types, it is necessary to + generate a stub function by hand or to pass parameters by reference. + See the struct [llvm::GenericValue]. *) + type t + + (** [of_float fpty n] boxes the float [n] in a float-valued generic value + according to the floating point type [fpty]. See the fields + [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) + val of_float : Llvm.lltype -> float -> t + + (** [of_pointer v] boxes the pointer value [v] in a generic value. See the + field [llvm::GenericValue::PointerVal]. *) + val of_pointer : 'a -> t + + (** [of_int32 n w] boxes the int32 [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int32 : Llvm.lltype -> int32 -> t + + (** [of_int n w] boxes the int [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int : Llvm.lltype -> int -> t + + (** [of_natint n w] boxes the native int [i] in a generic value with the + bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_nativeint : Llvm.lltype -> nativeint -> t + + + (** [of_int64 n w] boxes the int64 [i] in a generic value with the bitwidth + [w]. See the field [llvm::GenericValue::IntVal]. *) + val of_int64 : Llvm.lltype -> int64 -> t + + (** [as_float fpty gv] unboxes the floating point-valued generic value [gv] of + floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] + and [llvm::GenericValue::FloatVal]. *) + val as_float : Llvm.lltype -> t -> float + + (** [as_pointer gv] unboxes the pointer-valued generic value [gv]. See the + field [llvm::GenericValue::PointerVal]. *) + val as_pointer : t -> 'a + + (** [as_int32 gv] unboxes the integer-valued generic value [gv] as an [int32]. + Is invalid if [gv] has a bitwidth greater than 32 bits. See the field + [llvm::GenericValue::IntVal]. *) + val as_int32 : t -> int32 + + (** [as_int gv] unboxes the integer-valued generic value [gv] as an [int]. + Is invalid if [gv] has a bitwidth greater than the host bit width (but the + most significant bit may be lost). See the field + [llvm::GenericValue::IntVal]. *) + val as_int : t -> int + + (** [as_natint gv] unboxes the integer-valued generic value [gv] as a + [nativeint]. Is invalid if [gv] has a bitwidth greater than + [nativeint]. See the field [llvm::GenericValue::IntVal]. *) + val as_nativeint : t -> nativeint + + (** [as_int64 gv] returns the integer-valued generic value [gv] as an [int64]. + Is invalid if [gv] has a bitwidth greater than [int64]. See the field + [llvm::GenericValue::IntVal]. *) + val as_int64 : t -> int64 +end + + +module ExecutionEngine: sig + (** An execution engine is either a JIT compiler or an interpreter, capable of + directly loading an LLVM module and executing its functions without first + invoking a static compiler and generating a native executable. *) + type t + + (** [create m] creates a new execution engine, taking ownership of the + module [m] if successful. Creates a JIT if possible, else falls back to an + interpreter. Raises [Error msg] if an error occurrs. The execution engine + is not garbage collected and must be destroyed with [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create : Llvm.llmodule -> t + + (** [create_interpreter m] creates a new interpreter, taking ownership of the + module [m] if successful. Raises [Error msg] if an error occurrs. The + execution engine is not garbage collected and must be destroyed with + [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create_interpreter : Llvm.llmodule -> t + + (** [create_jit m optlevel] creates a new JIT (just-in-time compiler), taking + ownership of the module [m] if successful with the desired optimization + level [optlevel]. Raises [Error msg] if an error occurrs. The execution + engine is not garbage collected and must be destroyed with [dispose ee]. + See the function [llvm::EngineBuilder::create]. *) + val create_jit : Llvm.llmodule -> int -> t + + (** [dispose ee] releases the memory used by the execution engine and must be + invoked to avoid memory leaks. *) + val dispose : t -> unit + + (** [add_module m ee] adds the module [m] to the execution engine [ee]. *) + val add_module : Llvm.llmodule -> t -> unit + + (** [remove_module m ee] removes the module [m] from the execution engine + [ee], disposing of [m] and the module referenced by [mp]. Raises + [Error msg] if an error occurs. *) + val remove_module : Llvm.llmodule -> t -> Llvm.llmodule + + + (** [find_function n ee] finds the function named [n] defined in any of the + modules owned by the execution engine [ee]. Returns [None] if the function + is not found and [Some f] otherwise. *) + val find_function : string -> t -> Llvm.llvalue option + + + (** [run_function f args ee] synchronously executes the function [f] with the + arguments [args], which must be compatible with the parameter types. *) + val run_function : Llvm.llvalue -> GenericValue.t array -> t -> + GenericValue.t + + + (** [run_static_ctors ee] executes the static constructors of each module in + the execution engine [ee]. *) + val run_static_ctors : t -> unit + + (** [run_static_dtors ee] executes the static destructors of each module in + the execution engine [ee]. *) + val run_static_dtors : t -> unit + + (** [run_function_as_main f args env ee] executes the function [f] as a main + function, passing it [argv] and [argc] according to the string array + [args], and [envp] as specified by the array [env]. Returns the integer + return value of the function. *) + val run_function_as_main : Llvm.llvalue -> string array -> + (string * string) array -> t -> int + + + (** [free_machine_code f ee] releases the memory in the execution engine [ee] + used to store the machine code for the function [f]. *) + val free_machine_code : Llvm.llvalue -> t -> unit + + + (** [target_data ee] is the target data owned by the execution engine + [ee]. *) + val target_data : t -> Llvm_target.TargetData.t + +end + +val initialize_native_target : unit -> bool + diff --git a/final/bindings/ocaml/llvm/Makefile b/final/bindings/ocaml/llvm/Makefile new file mode 100644 index 00000000000..99e347bc131 --- /dev/null +++ b/final/bindings/ocaml/llvm/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/llvm/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm +UsedComponents := core +UsedOcamLibs := llvm + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/llvm/llvm.ml b/final/bindings/ocaml/llvm/llvm.ml new file mode 100644 index 00000000000..462eb201694 --- /dev/null +++ b/final/bindings/ocaml/llvm/llvm.ml @@ -0,0 +1,1064 @@ +(*===-- llvm/llvm.ml - LLVM Ocaml Interface --------------------------------===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + + +type llcontext +type llmodule +type lltype +type lltypehandle +type llvalue +type lluse +type llbasicblock +type llbuilder +type llmemorybuffer + +module TypeKind = struct + type t = + | Void + | Float + | Double + | X86fp80 + | Fp128 + | Ppc_fp128 + | Label + | Integer + | Function + | Struct + | Array + | Pointer + | Opaque + | Vector + | Metadata +end + +module Linkage = struct + type t = + | External + | Available_externally + | Link_once + | Link_once_odr + | Weak + | Weak_odr + | Appending + | Internal + | Private + | Dllimport + | Dllexport + | External_weak + | Ghost + | Common + | Linker_private +end + +module Visibility = struct + type t = + | Default + | Hidden + | Protected +end + +module CallConv = struct + let c = 0 + let fast = 8 + let cold = 9 + let x86_stdcall = 64 + let x86_fastcall = 65 +end + +module Attribute = struct + type t = + | Zext + | Sext + | Noreturn + | Inreg + | Structret + | Nounwind + | Noalias + | Byval + | Nest + | Readnone + | Readonly + | Noinline + | Alwaysinline + | Optsize + | Ssp + | Sspreq + | Alignment of int + | Nocapture + | Noredzone + | Noimplicitfloat + | Naked + | Inlinehint + | Stackalignment of int +end + +module Icmp = struct + type t = + | Eq + | Ne + | Ugt + | Uge + | Ult + | Ule + | Sgt + | Sge + | Slt + | Sle +end + +module Fcmp = struct + type t = + | False + | Oeq + | Ogt + | Oge + | Olt + | Ole + | One + | Ord + | Uno + | Ueq + | Ugt + | Uge + | Ult + | Ule + | Une + | True +end + +exception IoError of string + +external register_exns : exn -> unit = "llvm_register_core_exns" +let _ = register_exns (IoError "") + +type ('a, 'b) llpos = +| At_end of 'a +| Before of 'b + +type ('a, 'b) llrev_pos = +| At_start of 'a +| After of 'b + +(*===-- Contexts ----------------------------------------------------------===*) +external create_context : unit -> llcontext = "llvm_create_context" +external dispose_context : llcontext -> unit = "llvm_dispose_context" +external global_context : unit -> llcontext = "llvm_global_context" +external mdkind_id : llcontext -> string -> int = "llvm_mdkind_id" + +(*===-- Modules -----------------------------------------------------------===*) +external create_module : llcontext -> string -> llmodule = "llvm_create_module" +external dispose_module : llmodule -> unit = "llvm_dispose_module" +external target_triple: llmodule -> string + = "llvm_target_triple" +external set_target_triple: string -> llmodule -> unit + = "llvm_set_target_triple" +external data_layout: llmodule -> string + = "llvm_data_layout" +external set_data_layout: string -> llmodule -> unit + = "llvm_set_data_layout" +external define_type_name : string -> lltype -> llmodule -> bool + = "llvm_add_type_name" +external delete_type_name : string -> llmodule -> unit + = "llvm_delete_type_name" +external type_by_name : llmodule -> string -> lltype option + = "llvm_type_by_name" +external dump_module : llmodule -> unit = "llvm_dump_module" +external set_module_inline_asm : llmodule -> string -> unit + = "llvm_set_module_inline_asm" + +(*===-- Types -------------------------------------------------------------===*) +external classify_type : lltype -> TypeKind.t = "llvm_classify_type" +external type_context : lltype -> llcontext = "llvm_type_context" + +(*--... Operations on integer types ........................................--*) +external i1_type : llcontext -> lltype = "llvm_i1_type" +external i8_type : llcontext -> lltype = "llvm_i8_type" +external i16_type : llcontext -> lltype = "llvm_i16_type" +external i32_type : llcontext -> lltype = "llvm_i32_type" +external i64_type : llcontext -> lltype = "llvm_i64_type" + +external integer_type : llcontext -> int -> lltype = "llvm_integer_type" +external integer_bitwidth : lltype -> int = "llvm_integer_bitwidth" + +(*--... Operations on real types ...........................................--*) +external float_type : llcontext -> lltype = "llvm_float_type" +external double_type : llcontext -> lltype = "llvm_double_type" +external x86fp80_type : llcontext -> lltype = "llvm_x86fp80_type" +external fp128_type : llcontext -> lltype = "llvm_fp128_type" +external ppc_fp128_type : llcontext -> lltype = "llvm_ppc_fp128_type" + +(*--... Operations on function types .......................................--*) +external function_type : lltype -> lltype array -> lltype = "llvm_function_type" +external var_arg_function_type : lltype -> lltype array -> lltype + = "llvm_var_arg_function_type" +external is_var_arg : lltype -> bool = "llvm_is_var_arg" +external return_type : lltype -> lltype = "LLVMGetReturnType" +external param_types : lltype -> lltype array = "llvm_param_types" + +(*--... Operations on struct types .........................................--*) +external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type" +external packed_struct_type : llcontext -> lltype array -> lltype + = "llvm_packed_struct_type" +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" +external is_packed : lltype -> bool = "llvm_is_packed" + +(*--... Operations on pointer, vector, and array types .....................--*) +external array_type : lltype -> int -> lltype = "llvm_array_type" +external pointer_type : lltype -> lltype = "llvm_pointer_type" +external qualified_pointer_type : lltype -> int -> lltype + = "llvm_qualified_pointer_type" +external vector_type : lltype -> int -> lltype = "llvm_vector_type" + +external element_type : lltype -> lltype = "LLVMGetElementType" +external array_length : lltype -> int = "llvm_array_length" +external address_space : lltype -> int = "llvm_address_space" +external vector_size : lltype -> int = "llvm_vector_size" + +(*--... Operations on other types ..........................................--*) +external opaque_type : llcontext -> lltype = "llvm_opaque_type" +external void_type : llcontext -> lltype = "llvm_void_type" +external label_type : llcontext -> lltype = "llvm_label_type" + +(*--... Operations on type handles .........................................--*) +external handle_to_type : lltype -> lltypehandle = "llvm_handle_to_type" +external type_of_handle : lltypehandle -> lltype = "llvm_type_of_handle" +external refine_type : lltype -> lltype -> unit = "llvm_refine_type" + + +(*===-- Values ------------------------------------------------------------===*) +external type_of : llvalue -> lltype = "llvm_type_of" +external value_name : llvalue -> string = "llvm_value_name" +external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" +external dump_value : llvalue -> unit = "llvm_dump_value" +external replace_all_uses_with : llvalue -> llvalue -> unit + = "LLVMReplaceAllUsesWith" + +(*--... Operations on uses .................................................--*) +external use_begin : llvalue -> lluse option = "llvm_use_begin" +external use_succ : lluse -> lluse option = "llvm_use_succ" +external user : lluse -> llvalue = "llvm_user" +external used_value : lluse -> llvalue = "llvm_used_value" + +let iter_uses f v = + let rec aux = function + | None -> () + | Some u -> + f u; + aux (use_succ u) + in + aux (use_begin v) + +let fold_left_uses f init v = + let rec aux init u = + match u with + | None -> init + | Some u -> aux (f init u) (use_succ u) + in + aux init (use_begin v) + +let fold_right_uses f v init = + let rec aux u init = + match u with + | None -> init + | Some u -> f u (aux (use_succ u) init) + in + aux (use_begin v) init + + +(*--... Operations on users ................................................--*) +external operand : llvalue -> int -> llvalue = "llvm_operand" +external set_operand : llvalue -> int -> llvalue -> unit = "llvm_set_operand" +external num_operands : llvalue -> int = "llvm_num_operands" + +(*--... Operations on constants of (mostly) any type .......................--*) +external is_constant : llvalue -> bool = "llvm_is_constant" +external const_null : lltype -> llvalue = "LLVMConstNull" +external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes" +external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull" +external undef : lltype -> llvalue = "LLVMGetUndef" +external is_null : llvalue -> bool = "llvm_is_null" +external is_undef : llvalue -> bool = "llvm_is_undef" + +(*--... Operations on instructions .........................................--*) +external has_metadata : llvalue -> bool = "llvm_has_metadata" +external metadata : llvalue -> int -> llvalue option = "llvm_metadata" +external set_metadata : llvalue -> int -> llvalue -> unit = "llvm_set_metadata" +external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata" + +(*--... Operations on metadata .......,.....................................--*) +external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" +external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" + +(*--... Operations on scalar constants .....................................--*) +external const_int : lltype -> int -> llvalue = "llvm_const_int" +external const_of_int64 : lltype -> Int64.t -> bool -> llvalue + = "llvm_const_of_int64" +external const_int_of_string : lltype -> string -> int -> llvalue + = "llvm_const_int_of_string" +external const_float : lltype -> float -> llvalue = "llvm_const_float" +external const_float_of_string : lltype -> string -> llvalue + = "llvm_const_float_of_string" + +(*--... Operations on composite constants ..................................--*) +external const_string : llcontext -> string -> llvalue = "llvm_const_string" +external const_stringz : llcontext -> string -> llvalue = "llvm_const_stringz" +external const_array : lltype -> llvalue array -> llvalue = "llvm_const_array" +external const_struct : llcontext -> llvalue array -> llvalue + = "llvm_const_struct" +external const_packed_struct : llcontext -> llvalue array -> llvalue + = "llvm_const_packed_struct" +external const_vector : llvalue array -> llvalue = "llvm_const_vector" + +(*--... Constant expressions ...............................................--*) +external align_of : lltype -> llvalue = "LLVMAlignOf" +external size_of : lltype -> llvalue = "LLVMSizeOf" +external const_neg : llvalue -> llvalue = "LLVMConstNeg" +external const_nsw_neg : llvalue -> llvalue = "LLVMConstNSWNeg" +external const_nuw_neg : llvalue -> llvalue = "LLVMConstNUWNeg" +external const_fneg : llvalue -> llvalue = "LLVMConstFNeg" +external const_not : llvalue -> llvalue = "LLVMConstNot" +external const_add : llvalue -> llvalue -> llvalue = "LLVMConstAdd" +external const_nsw_add : llvalue -> llvalue -> llvalue = "LLVMConstNSWAdd" +external const_nuw_add : llvalue -> llvalue -> llvalue = "LLVMConstNUWAdd" +external const_fadd : llvalue -> llvalue -> llvalue = "LLVMConstFAdd" +external const_sub : llvalue -> llvalue -> llvalue = "LLVMConstSub" +external const_nsw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNSWSub" +external const_nuw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNUWSub" +external const_fsub : llvalue -> llvalue -> llvalue = "LLVMConstFSub" +external const_mul : llvalue -> llvalue -> llvalue = "LLVMConstMul" +external const_nsw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNSWMul" +external const_nuw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNUWMul" +external const_fmul : llvalue -> llvalue -> llvalue = "LLVMConstFMul" +external const_udiv : llvalue -> llvalue -> llvalue = "LLVMConstUDiv" +external const_sdiv : llvalue -> llvalue -> llvalue = "LLVMConstSDiv" +external const_exact_sdiv : llvalue -> llvalue -> llvalue = "LLVMConstExactSDiv" +external const_fdiv : llvalue -> llvalue -> llvalue = "LLVMConstFDiv" +external const_urem : llvalue -> llvalue -> llvalue = "LLVMConstURem" +external const_srem : llvalue -> llvalue -> llvalue = "LLVMConstSRem" +external const_frem : llvalue -> llvalue -> llvalue = "LLVMConstFRem" +external const_and : llvalue -> llvalue -> llvalue = "LLVMConstAnd" +external const_or : llvalue -> llvalue -> llvalue = "LLVMConstOr" +external const_xor : llvalue -> llvalue -> llvalue = "LLVMConstXor" +external const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue + = "llvm_const_icmp" +external const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue + = "llvm_const_fcmp" +external const_shl : llvalue -> llvalue -> llvalue = "LLVMConstShl" +external const_lshr : llvalue -> llvalue -> llvalue = "LLVMConstLShr" +external const_ashr : llvalue -> llvalue -> llvalue = "LLVMConstAShr" +external const_gep : llvalue -> llvalue array -> llvalue = "llvm_const_gep" +external const_in_bounds_gep : llvalue -> llvalue array -> llvalue + = "llvm_const_in_bounds_gep" +external const_trunc : llvalue -> lltype -> llvalue = "LLVMConstTrunc" +external const_sext : llvalue -> lltype -> llvalue = "LLVMConstSExt" +external const_zext : llvalue -> lltype -> llvalue = "LLVMConstZExt" +external const_fptrunc : llvalue -> lltype -> llvalue = "LLVMConstFPTrunc" +external const_fpext : llvalue -> lltype -> llvalue = "LLVMConstFPExt" +external const_uitofp : llvalue -> lltype -> llvalue = "LLVMConstUIToFP" +external const_sitofp : llvalue -> lltype -> llvalue = "LLVMConstSIToFP" +external const_fptoui : llvalue -> lltype -> llvalue = "LLVMConstFPToUI" +external const_fptosi : llvalue -> lltype -> llvalue = "LLVMConstFPToSI" +external const_ptrtoint : llvalue -> lltype -> llvalue = "LLVMConstPtrToInt" +external const_inttoptr : llvalue -> lltype -> llvalue = "LLVMConstIntToPtr" +external const_bitcast : llvalue -> lltype -> llvalue = "LLVMConstBitCast" +external const_zext_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstZExtOrBitCast" +external const_sext_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstSExtOrBitCast" +external const_trunc_or_bitcast : llvalue -> lltype -> llvalue + = "LLVMConstTruncOrBitCast" +external const_pointercast : llvalue -> lltype -> llvalue + = "LLVMConstPointerCast" +external const_intcast : llvalue -> lltype -> llvalue = "LLVMConstIntCast" +external const_fpcast : llvalue -> lltype -> llvalue = "LLVMConstFPCast" +external const_select : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstSelect" +external const_extractelement : llvalue -> llvalue -> llvalue + = "LLVMConstExtractElement" +external const_insertelement : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstInsertElement" +external const_shufflevector : llvalue -> llvalue -> llvalue -> llvalue + = "LLVMConstShuffleVector" +external const_extractvalue : llvalue -> int array -> llvalue + = "llvm_const_extractvalue" +external const_insertvalue : llvalue -> llvalue -> int array -> llvalue + = "llvm_const_insertvalue" +external const_inline_asm : lltype -> string -> string -> bool -> bool -> + llvalue + = "llvm_const_inline_asm" +external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress" + +(*--... Operations on global variables, functions, and aliases (globals) ...--*) +external global_parent : llvalue -> llmodule = "LLVMGetGlobalParent" +external is_declaration : llvalue -> bool = "llvm_is_declaration" +external linkage : llvalue -> Linkage.t = "llvm_linkage" +external set_linkage : Linkage.t -> llvalue -> unit = "llvm_set_linkage" +external section : llvalue -> string = "llvm_section" +external set_section : string -> llvalue -> unit = "llvm_set_section" +external visibility : llvalue -> Visibility.t = "llvm_visibility" +external set_visibility : Visibility.t -> llvalue -> unit = "llvm_set_visibility" +external alignment : llvalue -> int = "llvm_alignment" +external set_alignment : int -> llvalue -> unit = "llvm_set_alignment" +external is_global_constant : llvalue -> bool = "llvm_is_global_constant" +external set_global_constant : bool -> llvalue -> unit + = "llvm_set_global_constant" + +(*--... Operations on global variables .....................................--*) +external declare_global : lltype -> string -> llmodule -> llvalue + = "llvm_declare_global" +external declare_qualified_global : lltype -> string -> int -> llmodule -> + llvalue + = "llvm_declare_qualified_global" +external define_global : string -> llvalue -> llmodule -> llvalue + = "llvm_define_global" +external define_qualified_global : string -> llvalue -> int -> llmodule -> + llvalue + = "llvm_define_qualified_global" +external lookup_global : string -> llmodule -> llvalue option + = "llvm_lookup_global" +external delete_global : llvalue -> unit = "llvm_delete_global" +external global_initializer : llvalue -> llvalue = "LLVMGetInitializer" +external set_initializer : llvalue -> llvalue -> unit = "llvm_set_initializer" +external remove_initializer : llvalue -> unit = "llvm_remove_initializer" +external is_thread_local : llvalue -> bool = "llvm_is_thread_local" +external set_thread_local : bool -> llvalue -> unit = "llvm_set_thread_local" +external global_begin : llmodule -> (llmodule, llvalue) llpos + = "llvm_global_begin" +external global_succ : llvalue -> (llmodule, llvalue) llpos + = "llvm_global_succ" +external global_end : llmodule -> (llmodule, llvalue) llrev_pos + = "llvm_global_end" +external global_pred : llvalue -> (llmodule, llvalue) llrev_pos + = "llvm_global_pred" + +let rec iter_global_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid global variable range.") + | Before bb -> + f bb; + iter_global_range f (global_succ bb) e + +let iter_globals f m = + iter_global_range f (global_begin m) (At_end m) + +let rec fold_left_global_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid global variable range.") + | Before bb -> fold_left_global_range f (f init bb) (global_succ bb) e + +let fold_left_globals f init m = + fold_left_global_range f init (global_begin m) (At_end m) + +let rec rev_iter_global_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid global variable range.") + | After bb -> + f bb; + rev_iter_global_range f (global_pred bb) e + +let rev_iter_globals f m = + rev_iter_global_range f (global_end m) (At_start m) + +let rec fold_right_global_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid global variable range.") + | After bb -> fold_right_global_range f (global_pred bb) e (f bb init) + +let fold_right_globals f m init = + fold_right_global_range f (global_end m) (At_start m) init + +(*--... Operations on aliases ..............................................--*) +external add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + = "llvm_add_alias" + +(*--... Operations on functions ............................................--*) +external declare_function : string -> lltype -> llmodule -> llvalue + = "llvm_declare_function" +external define_function : string -> lltype -> llmodule -> llvalue + = "llvm_define_function" +external lookup_function : string -> llmodule -> llvalue option + = "llvm_lookup_function" +external delete_function : llvalue -> unit = "llvm_delete_function" +external is_intrinsic : llvalue -> bool = "llvm_is_intrinsic" +external function_call_conv : llvalue -> int = "llvm_function_call_conv" +external set_function_call_conv : int -> llvalue -> unit + = "llvm_set_function_call_conv" +external gc : llvalue -> string option = "llvm_gc" +external set_gc : string option -> llvalue -> unit = "llvm_set_gc" +external function_begin : llmodule -> (llmodule, llvalue) llpos + = "llvm_function_begin" +external function_succ : llvalue -> (llmodule, llvalue) llpos + = "llvm_function_succ" +external function_end : llmodule -> (llmodule, llvalue) llrev_pos + = "llvm_function_end" +external function_pred : llvalue -> (llmodule, llvalue) llrev_pos + = "llvm_function_pred" + +let rec iter_function_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid function range.") + | Before fn -> + f fn; + iter_function_range f (function_succ fn) e + +let iter_functions f m = + iter_function_range f (function_begin m) (At_end m) + +let rec fold_left_function_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid function range.") + | Before fn -> fold_left_function_range f (f init fn) (function_succ fn) e + +let fold_left_functions f init m = + fold_left_function_range f init (function_begin m) (At_end m) + +let rec rev_iter_function_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid function range.") + | After fn -> + f fn; + rev_iter_function_range f (function_pred fn) e + +let rev_iter_functions f m = + rev_iter_function_range f (function_end m) (At_start m) + +let rec fold_right_function_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid function range.") + | After fn -> fold_right_function_range f (function_pred fn) e (f fn init) + +let fold_right_functions f m init = + fold_right_function_range f (function_end m) (At_start m) init + +external llvm_add_function_attr : llvalue -> int -> unit + = "llvm_add_function_attr" +external llvm_remove_function_attr : llvalue -> int -> unit + = "llvm_remove_function_attr" + +let pack_attr (attr:Attribute.t) : int = + match attr with + Attribute.Zext -> 1 lsl 0 + | Attribute.Sext -> 1 lsl 1 + | Attribute.Noreturn -> 1 lsl 2 + | Attribute.Inreg -> 1 lsl 3 + | Attribute.Structret -> 1 lsl 4 + | Attribute.Nounwind -> 1 lsl 5 + | Attribute.Noalias -> 1 lsl 6 + | Attribute.Byval -> 1 lsl 7 + | Attribute.Nest -> 1 lsl 8 + | Attribute.Readnone -> 1 lsl 9 + | Attribute.Readonly -> 1 lsl 10 + | Attribute.Noinline -> 1 lsl 11 + | Attribute.Alwaysinline -> 1 lsl 12 + | Attribute.Optsize -> 1 lsl 13 + | Attribute.Ssp -> 1 lsl 14 + | Attribute.Sspreq -> 1 lsl 15 + | Attribute.Alignment n -> n lsl 16 + | Attribute.Nocapture -> 1 lsl 21 + | Attribute.Noredzone -> 1 lsl 22 + | Attribute.Noimplicitfloat -> 1 lsl 23 + | Attribute.Naked -> 1 lsl 24 + | Attribute.Inlinehint -> 1 lsl 25 + | Attribute.Stackalignment n -> n lsl 26 + +let add_function_attr llval attr = + llvm_add_function_attr llval (pack_attr attr) + +let remove_function_attr llval attr = + llvm_remove_function_attr llval (pack_attr attr) + +(*--... Operations on params ...............................................--*) +external params : llvalue -> llvalue array = "llvm_params" +external param : llvalue -> int -> llvalue = "llvm_param" +external param_parent : llvalue -> llvalue = "LLVMGetParamParent" +external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin" +external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ" +external param_end : llvalue -> (llvalue, llvalue) llrev_pos = "llvm_param_end" +external param_pred : llvalue -> (llvalue, llvalue) llrev_pos ="llvm_param_pred" + +let rec iter_param_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid parameter range.") + | Before p -> + f p; + iter_param_range f (param_succ p) e + +let iter_params f fn = + iter_param_range f (param_begin fn) (At_end fn) + +let rec fold_left_param_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid parameter range.") + | Before p -> fold_left_param_range f (f init p) (param_succ p) e + +let fold_left_params f init fn = + fold_left_param_range f init (param_begin fn) (At_end fn) + +let rec rev_iter_param_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid parameter range.") + | After p -> + f p; + rev_iter_param_range f (param_pred p) e + +let rev_iter_params f fn = + rev_iter_param_range f (param_end fn) (At_start fn) + +let rec fold_right_param_range f init i e = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid parameter range.") + | After p -> fold_right_param_range f (f p init) (param_pred p) e + +let fold_right_params f fn init = + fold_right_param_range f init (param_end fn) (At_start fn) + +external llvm_add_param_attr : llvalue -> int -> unit + = "llvm_add_param_attr" +external llvm_remove_param_attr : llvalue -> int -> unit + = "llvm_remove_param_attr" + +let add_param_attr llval attr = + llvm_add_param_attr llval (pack_attr attr) + +let remove_param_attr llval attr = + llvm_remove_param_attr llval (pack_attr attr) + +external set_param_alignment : llvalue -> int -> unit + = "llvm_set_param_alignment" + +(*--... Operations on basic blocks .........................................--*) +external value_of_block : llbasicblock -> llvalue = "LLVMBasicBlockAsValue" +external value_is_block : llvalue -> bool = "llvm_value_is_block" +external block_of_value : llvalue -> llbasicblock = "LLVMValueAsBasicBlock" +external block_parent : llbasicblock -> llvalue = "LLVMGetBasicBlockParent" +external basic_blocks : llvalue -> llbasicblock array = "llvm_basic_blocks" +external entry_block : llvalue -> llbasicblock = "LLVMGetEntryBasicBlock" +external delete_block : llbasicblock -> unit = "llvm_delete_block" +external append_block : llcontext -> string -> llvalue -> llbasicblock + = "llvm_append_block" +external insert_block : llcontext -> string -> llbasicblock -> llbasicblock + = "llvm_insert_block" +external block_begin : llvalue -> (llvalue, llbasicblock) llpos + = "llvm_block_begin" +external block_succ : llbasicblock -> (llvalue, llbasicblock) llpos + = "llvm_block_succ" +external block_end : llvalue -> (llvalue, llbasicblock) llrev_pos + = "llvm_block_end" +external block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos + = "llvm_block_pred" + +let rec iter_block_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid block range.") + | Before bb -> + f bb; + iter_block_range f (block_succ bb) e + +let iter_blocks f fn = + iter_block_range f (block_begin fn) (At_end fn) + +let rec fold_left_block_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid block range.") + | Before bb -> fold_left_block_range f (f init bb) (block_succ bb) e + +let fold_left_blocks f init fn = + fold_left_block_range f init (block_begin fn) (At_end fn) + +let rec rev_iter_block_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid block range.") + | After bb -> + f bb; + rev_iter_block_range f (block_pred bb) e + +let rev_iter_blocks f fn = + rev_iter_block_range f (block_end fn) (At_start fn) + +let rec fold_right_block_range f init i e = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid block range.") + | After bb -> fold_right_block_range f (f bb init) (block_pred bb) e + +let fold_right_blocks f fn init = + fold_right_block_range f init (block_end fn) (At_start fn) + +(*--... Operations on instructions .........................................--*) +external instr_parent : llvalue -> llbasicblock = "LLVMGetInstructionParent" +external instr_begin : llbasicblock -> (llbasicblock, llvalue) llpos + = "llvm_instr_begin" +external instr_succ : llvalue -> (llbasicblock, llvalue) llpos + = "llvm_instr_succ" +external instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos + = "llvm_instr_end" +external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos + = "llvm_instr_pred" + +let rec iter_instrs_range f i e = + if i = e then () else + match i with + | At_end _ -> raise (Invalid_argument "Invalid instruction range.") + | Before i -> + f i; + iter_instrs_range f (instr_succ i) e + +let iter_instrs f bb = + iter_instrs_range f (instr_begin bb) (At_end bb) + +let rec fold_left_instrs_range f init i e = + if i = e then init else + match i with + | At_end _ -> raise (Invalid_argument "Invalid instruction range.") + | Before i -> fold_left_instrs_range f (f init i) (instr_succ i) e + +let fold_left_instrs f init bb = + fold_left_instrs_range f init (instr_begin bb) (At_end bb) + +let rec rev_iter_instrs_range f i e = + if i = e then () else + match i with + | At_start _ -> raise (Invalid_argument "Invalid instruction range.") + | After i -> + f i; + rev_iter_instrs_range f (instr_pred i) e + +let rev_iter_instrs f bb = + rev_iter_instrs_range f (instr_end bb) (At_start bb) + +let rec fold_right_instr_range f i e init = + if i = e then init else + match i with + | At_start _ -> raise (Invalid_argument "Invalid instruction range.") + | After i -> fold_right_instr_range f (instr_pred i) e (f i init) + +let fold_right_instrs f bb init = + fold_right_instr_range f (instr_end bb) (At_start bb) init + + +(*--... Operations on call sites ...........................................--*) +external instruction_call_conv: llvalue -> int + = "llvm_instruction_call_conv" +external set_instruction_call_conv: int -> llvalue -> unit + = "llvm_set_instruction_call_conv" + +external llvm_add_instruction_param_attr : llvalue -> int -> int -> unit + = "llvm_add_instruction_param_attr" +external llvm_remove_instruction_param_attr : llvalue -> int -> int -> unit + = "llvm_remove_instruction_param_attr" + +let add_instruction_param_attr llval i attr = + llvm_add_instruction_param_attr llval i (pack_attr attr) + +let remove_instruction_param_attr llval i attr = + llvm_remove_instruction_param_attr llval i (pack_attr attr) + +(*--... Operations on call instructions (only) .............................--*) +external is_tail_call : llvalue -> bool = "llvm_is_tail_call" +external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call" + +(*--... Operations on phi nodes ............................................--*) +external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit + = "llvm_add_incoming" +external incoming : llvalue -> (llvalue * llbasicblock) list = "llvm_incoming" + + +(*===-- Instruction builders ----------------------------------------------===*) +external builder : llcontext -> llbuilder = "llvm_builder" +external position_builder : (llbasicblock, llvalue) llpos -> llbuilder -> unit + = "llvm_position_builder" +external insertion_block : llbuilder -> llbasicblock = "llvm_insertion_block" +external insert_into_builder : llvalue -> string -> llbuilder -> unit + = "llvm_insert_into_builder" + +let builder_at context ip = + let b = builder context in + position_builder ip b; + b + +let builder_before context i = builder_at context (Before i) +let builder_at_end context bb = builder_at context (At_end bb) + +let position_before i = position_builder (Before i) +let position_at_end bb = position_builder (At_end bb) + + +(*--... Metadata ...........................................................--*) +external set_current_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_current_debug_location" +external clear_current_debug_location : llbuilder -> unit + = "llvm_clear_current_debug_location" +external current_debug_location : llbuilder -> llvalue option + = "llvm_current_debug_location" +external set_inst_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_inst_debug_location" + + +(*--... Terminators ........................................................--*) +external build_ret_void : llbuilder -> llvalue = "llvm_build_ret_void" +external build_ret : llvalue -> llbuilder -> llvalue = "llvm_build_ret" +external build_aggregate_ret : llvalue array -> llbuilder -> llvalue + = "llvm_build_aggregate_ret" +external build_br : llbasicblock -> llbuilder -> llvalue = "llvm_build_br" +external build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder -> + llvalue = "llvm_build_cond_br" +external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue + = "llvm_build_switch" +external add_case : llvalue -> llvalue -> llbasicblock -> unit + = "llvm_add_case" +external build_indirect_br : llvalue -> int -> llbuilder -> llvalue + = "llvm_build_indirect_br" +external add_destination : llvalue -> llbasicblock -> unit + = "llvm_add_destination" +external build_invoke : llvalue -> llvalue array -> llbasicblock -> + llbasicblock -> string -> llbuilder -> llvalue + = "llvm_build_invoke_bc" "llvm_build_invoke_nat" +external build_unwind : llbuilder -> llvalue = "llvm_build_unwind" +external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable" + +(*--... Arithmetic .........................................................--*) +external build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_add" +external build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_add" +external build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_add" +external build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fadd" +external build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_sub" +external build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_sub" +external build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_sub" +external build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fsub" +external build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_mul" +external build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_mul" +external build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_mul" +external build_fmul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fmul" +external build_udiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_udiv" +external build_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_sdiv" +external build_exact_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_exact_sdiv" +external build_fdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fdiv" +external build_urem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_urem" +external build_srem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_srem" +external build_frem : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_frem" +external build_shl : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_shl" +external build_lshr : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_lshr" +external build_ashr : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_ashr" +external build_and : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_and" +external build_or : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_or" +external build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_xor" +external build_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_neg" +external build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_neg" +external build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_neg" +external build_fneg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fneg" +external build_not : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_not" + +(*--... Memory .............................................................--*) +external build_alloca : lltype -> string -> llbuilder -> llvalue + = "llvm_build_alloca" +external build_array_alloca : lltype -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_array_alloca" +external build_load : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_load" +external build_store : llvalue -> llvalue -> llbuilder -> llvalue + = "llvm_build_store" +external build_gep : llvalue -> llvalue array -> string -> llbuilder -> llvalue + = "llvm_build_gep" +external build_in_bounds_gep : llvalue -> llvalue array -> string -> + llbuilder -> llvalue = "llvm_build_in_bounds_gep" +external build_struct_gep : llvalue -> int -> string -> llbuilder -> llvalue + = "llvm_build_struct_gep" + +external build_global_string : string -> string -> llbuilder -> llvalue + = "llvm_build_global_string" +external build_global_stringptr : string -> string -> llbuilder -> llvalue + = "llvm_build_global_stringptr" + +(*--... Casts ..............................................................--*) +external build_trunc : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_trunc" +external build_zext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_zext" +external build_sext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_sext" +external build_fptoui : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptoui" +external build_fptosi : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptosi" +external build_uitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_uitofp" +external build_sitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_sitofp" +external build_fptrunc : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fptrunc" +external build_fpext : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fpext" +external build_ptrtoint : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_prttoint" +external build_inttoptr : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_inttoptr" +external build_bitcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_bitcast" +external build_zext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_zext_or_bitcast" +external build_sext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_sext_or_bitcast" +external build_trunc_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue = "llvm_build_trunc_or_bitcast" +external build_pointercast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_pointercast" +external build_intcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_intcast" +external build_fpcast : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_fpcast" + +(*--... Comparisons ........................................................--*) +external build_icmp : Icmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_icmp" +external build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_fcmp" + +(*--... Miscellaneous instructions .........................................--*) +external build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> + llvalue = "llvm_build_phi" +external build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue + = "llvm_build_call" +external build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_select" +external build_va_arg : llvalue -> lltype -> string -> llbuilder -> llvalue + = "llvm_build_va_arg" +external build_extractelement : llvalue -> llvalue -> string -> llbuilder -> + llvalue = "llvm_build_extractelement" +external build_insertelement : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_insertelement" +external build_shufflevector : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue = "llvm_build_shufflevector" +external build_extractvalue : llvalue -> int -> string -> llbuilder -> llvalue + = "llvm_build_extractvalue" +external build_insertvalue : llvalue -> llvalue -> int -> string -> llbuilder -> + llvalue = "llvm_build_insertvalue" + +external build_is_null : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_is_null" +external build_is_not_null : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_is_not_null" +external build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_ptrdiff" + + +(*===-- Memory buffers ----------------------------------------------------===*) + +module MemoryBuffer = struct + external of_file : string -> llmemorybuffer = "llvm_memorybuffer_of_file" + external of_stdin : unit -> llmemorybuffer = "llvm_memorybuffer_of_stdin" + external dispose : llmemorybuffer -> unit = "llvm_memorybuffer_dispose" +end + + +(*===-- Pass Manager ------------------------------------------------------===*) + +module PassManager = struct + type 'a t + type any = [ `Module | `Function ] + external create : unit -> [ `Module ] t = "llvm_passmanager_create" + external create_function : llmodule -> [ `Function ] t + = "LLVMCreateFunctionPassManager" + external run_module : llmodule -> [ `Module ] t -> bool + = "llvm_passmanager_run_module" + external initialize : [ `Function ] t -> bool = "llvm_passmanager_initialize" + external run_function : llvalue -> [ `Function ] t -> bool + = "llvm_passmanager_run_function" + external finalize : [ `Function ] t -> bool = "llvm_passmanager_finalize" + external dispose : [< any ] t -> unit = "llvm_passmanager_dispose" +end + + +(*===-- Non-Externs -------------------------------------------------------===*) +(* These functions are built using the externals, so must be declared late. *) + +let concat2 sep arr = + let s = ref "" in + if 0 < Array.length arr then begin + s := !s ^ arr.(0); + for i = 1 to (Array.length arr) - 1 do + s := !s ^ sep ^ arr.(i) + done + end; + !s + +let rec string_of_lltype ty = + (* FIXME: stop infinite recursion! :) *) + match classify_type ty with + TypeKind.Integer -> "i" ^ string_of_int (integer_bitwidth ty) + | TypeKind.Pointer -> (string_of_lltype (element_type ty)) ^ "*" + | TypeKind.Struct -> + let s = "{ " ^ (concat2 ", " ( + Array.map string_of_lltype (struct_element_types ty) + )) ^ " }" in + if is_packed ty + then "<" ^ s ^ ">" + else s + | TypeKind.Array -> "[" ^ (string_of_int (array_length ty)) ^ + " x " ^ (string_of_lltype (element_type ty)) ^ "]" + | TypeKind.Vector -> "<" ^ (string_of_int (vector_size ty)) ^ + " x " ^ (string_of_lltype (element_type ty)) ^ ">" + | TypeKind.Opaque -> "opaque" + | TypeKind.Function -> string_of_lltype (return_type ty) ^ + " (" ^ (concat2 ", " ( + Array.map string_of_lltype (param_types ty) + )) ^ ")" + | TypeKind.Label -> "label" + | TypeKind.Ppc_fp128 -> "ppc_fp128" + | TypeKind.Fp128 -> "fp128" + | TypeKind.X86fp80 -> "x86_fp80" + | TypeKind.Double -> "double" + | TypeKind.Float -> "float" + | TypeKind.Void -> "void" + | TypeKind.Metadata -> "metadata" diff --git a/final/bindings/ocaml/llvm/llvm.mli b/final/bindings/ocaml/llvm/llvm.mli new file mode 100644 index 00000000000..9b037aae7a4 --- /dev/null +++ b/final/bindings/ocaml/llvm/llvm.mli @@ -0,0 +1,2259 @@ +(*===-- llvm/llvm.mli - LLVM Ocaml Interface -------------------------------===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Core API. + + This interface provides an ocaml API for the LLVM intermediate + representation, the classes in the VMCore library. *) + + +(** {6 Abstract types} + + These abstract types correlate directly to the LLVM VMCore classes. *) + +(** The top-level container for all LLVM global data. See the + [llvm::LLVMContext] class. *) +type llcontext + +(** The top-level container for all other LLVM Intermediate Representation (IR) + objects. See the [llvm::Module] class. *) +type llmodule + +(** Each value in the LLVM IR has a type, an instance of [lltype]. See the + [llvm::Type] class. *) +type lltype + +(** When building recursive types using {!refine_type}, [lltype] values may + become invalid; use [lltypehandle] to resolve this problem. See the + [llvm::AbstractTypeHolder] class. *) +type lltypehandle + +(** Any value in the LLVM IR. Functions, instructions, global variables, + constants, and much more are all [llvalues]. See the [llvm::Value] class. + This type covers a wide range of subclasses. *) +type llvalue + +(** Used to store users and usees of values. See the [llvm::Use] class. *) +type lluse + +(** A basic block in LLVM IR. See the [llvm::BasicBlock] class. *) +type llbasicblock + +(** Used to generate instructions in the LLVM IR. See the [llvm::LLVMBuilder] + class. *) +type llbuilder + +(** Used to efficiently handle large buffers of read-only binary data. + See the [llvm::MemoryBuffer] class. *) +type llmemorybuffer + +(** The kind of an [lltype], the result of [classify_type ty]. See the + [llvm::Type::TypeID] enumeration. *) +module TypeKind : sig + type t = + Void + | Float + | Double + | X86fp80 + | Fp128 + | Ppc_fp128 + | Label + | Integer + | Function + | Struct + | Array + | Pointer + | Opaque + | Vector + | Metadata +end + +(** The linkage of a global value, accessed with {!linkage} and + {!set_linkage}. See [llvm::GlobalValue::LinkageTypes]. *) +module Linkage : sig + type t = + External + | Available_externally + | Link_once + | Link_once_odr + | Weak + | Weak_odr + | Appending + | Internal + | Private + | Dllimport + | Dllexport + | External_weak + | Ghost + | Common + | Linker_private +end + +(** The linker visibility of a global value, accessed with {!visibility} and + {!set_visibility}. See [llvm::GlobalValue::VisibilityTypes]. *) +module Visibility : sig + type t = + Default + | Hidden + | Protected +end + +(** The following calling convention values may be accessed with + {!function_call_conv} and {!set_function_call_conv}. Calling + conventions are open-ended. *) +module CallConv : sig + val c : int (** [c] is the C calling convention. *) + val fast : int (** [fast] is the calling convention to allow LLVM + maximum optimization opportunities. Use only with + internal linkage. *) + val cold : int (** [cold] is the calling convention for + callee-save. *) + val x86_stdcall : int (** [x86_stdcall] is the familiar stdcall calling + convention from C. *) + val x86_fastcall : int (** [x86_fastcall] is the familiar fastcall calling + convention from C. *) +end + +module Attribute : sig + type t = + | Zext + | Sext + | Noreturn + | Inreg + | Structret + | Nounwind + | Noalias + | Byval + | Nest + | Readnone + | Readonly + | Noinline + | Alwaysinline + | Optsize + | Ssp + | Sspreq + | Alignment of int + | Nocapture + | Noredzone + | Noimplicitfloat + | Naked + | Inlinehint + | Stackalignment of int +end + +(** The predicate for an integer comparison ([icmp]) instruction. + See the [llvm::ICmpInst::Predicate] enumeration. *) +module Icmp : sig + type t = + | Eq + | Ne + | Ugt + | Uge + | Ult + | Ule + | Sgt + | Sge + | Slt + | Sle +end + +(** The predicate for a floating-point comparison ([fcmp]) instruction. + See the [llvm::FCmpInst::Predicate] enumeration. *) +module Fcmp : sig + type t = + | False + | Oeq + | Ogt + | Oge + | Olt + | Ole + | One + | Ord + | Uno + | Ueq + | Ugt + | Uge + | Ult + | Ule + | Une + | True +end + + +(** {6 Iteration} *) + +(** [Before b] and [At_end a] specify positions from the start of the ['b] list + of [a]. [llpos] is used to specify positions in and for forward iteration + through the various value lists maintained by the LLVM IR. *) +type ('a, 'b) llpos = +| At_end of 'a +| Before of 'b + +(** [After b] and [At_start a] specify positions from the end of the ['b] list + of [a]. [llrev_pos] is used for reverse iteration through the various value + lists maintained by the LLVM IR. *) +type ('a, 'b) llrev_pos = +| At_start of 'a +| After of 'b + + +(** {6 Exceptions} *) + +exception IoError of string + + +(** {6 Contexts} *) + +(** [create_context ()] creates a context for storing the "global" state in + LLVM. See the constructor [llvm::LLVMContext]. *) +val create_context : unit -> llcontext + +(** [destroy_context ()] destroys a context. See the destructor + [llvm::LLVMContext::~LLVMContext]. *) +val dispose_context : llcontext -> unit + +(** See the function [llvm::getGlobalContext]. *) +val global_context : unit -> llcontext + +(** [mdkind_id context name] returns the MDKind ID that corresponds to the + name [name] in the context [context]. See the function + [llvm::LLVMContext::getMDKindID]. *) +val mdkind_id : llcontext -> string -> int + + +(** {6 Modules} *) + +(** [create_module context id] creates a module with the supplied module ID in + the context [context]. Modules are not garbage collected; it is mandatory + to call {!dispose_module} to free memory. See the constructor + [llvm::Module::Module]. *) +val create_module : llcontext -> string -> llmodule + +(** [dispose_module m] destroys a module [m] and all of the IR objects it + contained. All references to subordinate objects are invalidated; + referencing them will invoke undefined behavior. See the destructor + [llvm::Module::~Module]. *) +val dispose_module : llmodule -> unit + +(** [target_triple m] is the target specifier for the module [m], something like + [i686-apple-darwin8]. See the method [llvm::Module::getTargetTriple]. *) +val target_triple: llmodule -> string + + +(** [target_triple triple m] changes the target specifier for the module [m] to + the string [triple]. See the method [llvm::Module::setTargetTriple]. *) +val set_target_triple: string -> llmodule -> unit + + +(** [data_layout m] is the data layout specifier for the module [m], something + like [e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-...-a0:0:64-f80:128:128]. See the + method [llvm::Module::getDataLayout]. *) +val data_layout: llmodule -> string + + +(** [set_data_layout s m] changes the data layout specifier for the module [m] + to the string [s]. See the method [llvm::Module::setDataLayout]. *) +val set_data_layout: string -> llmodule -> unit + + +(** [define_type_name name ty m] adds a named type to the module's symbol table. + Returns [true] if successful. If such a name already exists, then no entry + is added and [false] is returned. See the [llvm::Module::addTypeName] + method. *) +val define_type_name : string -> lltype -> llmodule -> bool + + +(** [delete_type_name name] removes a type name from the module's symbol + table. *) +val delete_type_name : string -> llmodule -> unit + + +(** [type_by_name m n] returns the type in the module [m] named [n], or [None] + if it does not exist. See the method [llvm::Module::getTypeByName]. *) +val type_by_name : llmodule -> string -> lltype option + + +(** [dump_module m] prints the .ll representation of the module [m] to standard + error. See the method [llvm::Module::dump]. *) +val dump_module : llmodule -> unit + +(** [set_module_inline_asm m asm] sets the inline assembler for the module. See + the method [llvm::Module::setModuleInlineAsm]. *) +val set_module_inline_asm : llmodule -> string -> unit + + + +(** {6 Types} *) + +(** [classify_type ty] returns the {!TypeKind.t} corresponding to the type [ty]. + See the method [llvm::Type::getTypeID]. *) +val classify_type : lltype -> TypeKind.t + +(** [type_context ty] returns the {!llcontext} corresponding to the type [ty]. + See the method [llvm::Type::getContext]. *) +val type_context : lltype -> llcontext + +(** [string_of_lltype ty] returns a string describing the type [ty]. *) +val string_of_lltype : lltype -> string + +(** {7 Operations on integer types} *) + +(** [i1_type c] returns an integer type of bitwidth 1 in the context [c]. See + [llvm::Type::Int1Ty]. *) +val i1_type : llcontext -> lltype + +(** [i8_type c] returns an integer type of bitwidth 8 in the context [c]. See + [llvm::Type::Int8Ty]. *) +val i8_type : llcontext -> lltype + +(** [i16_type c] returns an integer type of bitwidth 16 in the context [c]. See + [llvm::Type::Int16Ty]. *) +val i16_type : llcontext -> lltype + +(** [i32_type c] returns an integer type of bitwidth 32 in the context [c]. See + [llvm::Type::Int32Ty]. *) +val i32_type : llcontext -> lltype + +(** [i64_type c] returns an integer type of bitwidth 64 in the context [c]. See + [llvm::Type::Int64Ty]. *) +val i64_type : llcontext -> lltype + +(** [integer_type c n] returns an integer type of bitwidth [n] in the context + [c]. See the method [llvm::IntegerType::get]. *) +val integer_type : llcontext -> int -> lltype + +(** [integer_bitwidth c ty] returns the number of bits in the integer type [ty] + in the context [c]. See the method [llvm::IntegerType::getBitWidth]. *) +val integer_bitwidth : lltype -> int + + +(** {7 Operations on real types} *) + +(** [float_type c] returns the IEEE 32-bit floating point type in the context + [c]. See [llvm::Type::FloatTy]. *) +val float_type : llcontext -> lltype + +(** [double_type c] returns the IEEE 64-bit floating point type in the context + [c]. See [llvm::Type::DoubleTy]. *) +val double_type : llcontext -> lltype + +(** [x86fp80_type c] returns the x87 80-bit floating point type in the context + [c]. See [llvm::Type::X86_FP80Ty]. *) +val x86fp80_type : llcontext -> lltype + +(** [fp128_type c] returns the IEEE 128-bit floating point type in the context + [c]. See [llvm::Type::FP128Ty]. *) +val fp128_type : llcontext -> lltype + +(** [ppc_fp128_type c] returns the PowerPC 128-bit floating point type in the + context [c]. See [llvm::Type::PPC_FP128Ty]. *) +val ppc_fp128_type : llcontext -> lltype + + +(** {7 Operations on function types} *) + +(** [function_type ret_ty param_tys] returns the function type returning + [ret_ty] and taking [param_tys] as parameters. + See the method [llvm::FunctionType::get]. *) +val function_type : lltype -> lltype array -> lltype + +(** [va_arg_function_type ret_ty param_tys] is just like + [function_type ret_ty param_tys] except that it returns the function type + which also takes a variable number of arguments. + See the method [llvm::FunctionType::get]. *) +val var_arg_function_type : lltype -> lltype array -> lltype + + +(** [is_var_arg fty] returns [true] if [fty] is a varargs function type, [false] + otherwise. See the method [llvm::FunctionType::isVarArg]. *) +val is_var_arg : lltype -> bool + +(** [return_type fty] gets the return type of the function type [fty]. + See the method [llvm::FunctionType::getReturnType]. *) +val return_type : lltype -> lltype + +(** [param_types fty] gets the parameter types of the function type [fty]. + See the method [llvm::FunctionType::getParamType]. *) +val param_types : lltype -> lltype array + + +(** {7 Operations on struct types} *) + +(** [struct_type context tys] returns the structure type in the context + [context] containing in the types in the array [tys]. See the method + [llvm::StructType::get]. *) +val struct_type : llcontext -> lltype array -> lltype + + +(** [packed_struct_type context ys] returns the packed structure type in the + context [context] containing in the types in the array [tys]. See the method + [llvm::StructType::get]. *) +val packed_struct_type : llcontext -> lltype array -> lltype + + +(** [struct_element_types sty] returns the constituent types of the struct type + [sty]. See the method [llvm::StructType::getElementType]. *) +val struct_element_types : lltype -> lltype array + + +(** [is_packed sty] returns [true] if the structure type [sty] is packed, + [false] otherwise. See the method [llvm::StructType::isPacked]. *) +val is_packed : lltype -> bool + + +(** {7 Operations on pointer, vector, and array types} *) + +(** [array_type ty n] returns the array type containing [n] elements of type + [ty]. See the method [llvm::ArrayType::get]. *) +val array_type : lltype -> int -> lltype + +(** [pointer_type ty] returns the pointer type referencing objects of type + [ty] in the default address space (0). + See the method [llvm::PointerType::getUnqual]. *) +val pointer_type : lltype -> lltype + +(** [qualified_pointer_type ty as] returns the pointer type referencing objects + of type [ty] in address space [as]. + See the method [llvm::PointerType::get]. *) +val qualified_pointer_type : lltype -> int -> lltype + + +(** [vector_type ty n] returns the array type containing [n] elements of the + primitive type [ty]. See the method [llvm::ArrayType::get]. *) +val vector_type : lltype -> int -> lltype + +(** [element_type ty] returns the element type of the pointer, vector, or array + type [ty]. See the method [llvm::SequentialType::get]. *) +val element_type : lltype -> lltype + +(** [element_type aty] returns the element count of the array type [aty]. + See the method [llvm::ArrayType::getNumElements]. *) +val array_length : lltype -> int + +(** [address_space pty] returns the address space qualifier of the pointer type + [pty]. See the method [llvm::PointerType::getAddressSpace]. *) +val address_space : lltype -> int + +(** [element_type ty] returns the element count of the vector type [ty]. + See the method [llvm::VectorType::getNumElements]. *) +val vector_size : lltype -> int + + +(** {7 Operations on other types} *) + +(** [opaque_type c] creates a new opaque type distinct from any other in the + context [c]. Opaque types are useful for building recursive types in + combination with {!refine_type}. See [llvm::OpaqueType::get]. *) +val opaque_type : llcontext -> lltype + +(** [void_type c] creates a type of a function which does not return any + value in the context [c]. See [llvm::Type::VoidTy]. *) +val void_type : llcontext -> lltype + +(** [label_type c] creates a type of a basic block in the context [c]. See + [llvm::Type::LabelTy]. *) +val label_type : llcontext -> lltype + +(** {7 Operations on type handles} *) + +(** [handle_to_type ty] creates a handle to the type [ty]. If [ty] is later + refined as a result of a call to {!refine_type}, the handle will be updated; + any bare [lltype] references will become invalid. + See the class [llvm::PATypeHolder]. *) +val handle_to_type : lltype -> lltypehandle + +(** [type_of_handle tyh] resolves the type handle [tyh]. + See the method [llvm::PATypeHolder::get()]. *) +val type_of_handle : lltypehandle -> lltype + +(** [refine_type opaque_ty ty] replaces the abstract type [opaque_ty] with the + concrete type [ty] in all users. Warning: This may invalidate {!lltype} + values! Use {!lltypehandle} to manipulate potentially abstract types. See + the method [llvm::Type::refineAbstractType]. *) +val refine_type : lltype -> lltype -> unit + + +(* {6 Values} *) + +(** [type_of v] returns the type of the value [v]. + See the method [llvm::Value::getType]. *) +val type_of : llvalue -> lltype + +(** [value_name v] returns the name of the value [v]. For global values, this is + the symbol name. For instructions and basic blocks, it is the SSA register + name. It is meaningless for constants. + See the method [llvm::Value::getName]. *) +val value_name : llvalue -> string + +(** [set_value_name n v] sets the name of the value [v] to [n]. See the method + [llvm::Value::setName]. *) +val set_value_name : string -> llvalue -> unit + +(** [dump_value v] prints the .ll representation of the value [v] to standard + error. See the method [llvm::Value::dump]. *) +val dump_value : llvalue -> unit + +(** [replace_all_uses_with old new] replaces all uses of the value [old] + * with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) +val replace_all_uses_with : llvalue -> llvalue -> unit + + + +(* {6 Uses} *) + +(** [use_begin v] returns the first position in the use list for the value [v]. + [use_begin] and [use_succ] can e used to iterate over the use list in order. + See the method [llvm::Value::use_begin]. *) +val use_begin : llvalue -> lluse option + +(** [use_succ u] returns the use list position succeeding [u]. + See the method [llvm::use_value_iterator::operator++]. *) +val use_succ : lluse -> lluse option + +(** [user u] returns the user of the use [u]. + See the method [llvm::Use::getUser]. *) +val user : lluse -> llvalue + +(** [used_value u] returns the usee of the use [u]. + See the method [llvm::Use::getUsedValue]. *) +val used_value : lluse -> llvalue + +(** [iter_uses f v] applies function [f] to each of the users of the value [v] + in order. Tail recursive. *) +val iter_uses : (lluse -> unit) -> llvalue -> unit + +(** [fold_left_uses f init v] is [f (... (f init u1) ...) uN] where + [u1,...,uN] are the users of the value [v]. Tail recursive. *) +val fold_left_uses : ('a -> lluse -> 'a) -> 'a -> llvalue -> 'a + +(** [fold_right_uses f v init] is [f u1 (... (f uN init) ...)] where + [u1,...,uN] are the users of the value [v]. Not tail recursive. *) +val fold_right_uses : (lluse -> 'a -> 'a) -> llvalue -> 'a -> 'a + + +(* {6 Users} *) + +(** [operand v i] returns the operand at index [i] for the value [v]. See the + method [llvm::User::getOperand]. *) +val operand : llvalue -> int -> llvalue + +(** [set_operand v i o] sets the operand of the value [v] at the index [i] to + the value [o]. + See the method [llvm::User::setOperand]. *) +val set_operand : llvalue -> int -> llvalue -> unit + +(** [num_operands v] returns the number of operands for the value [v]. + See the method [llvm::User::getNumOperands]. *) +val num_operands : llvalue -> int + +(** {7 Operations on constants of (mostly) any type} *) + +(** [is_constant v] returns [true] if the value [v] is a constant, [false] + otherwise. Similar to [llvm::isa]. *) +val is_constant : llvalue -> bool + +(** [const_null ty] returns the constant null (zero) of the type [ty]. + See the method [llvm::Constant::getNullValue]. *) +val const_null : lltype -> llvalue + +(** [const_all_ones ty] returns the constant '-1' of the integer or vector type + [ty]. See the method [llvm::Constant::getAllOnesValue]. *) +val const_all_ones : (*int|vec*)lltype -> llvalue + +(** [const_pointer_null ty] returns the constant null (zero) pointer of the type + [ty]. See the method [llvm::ConstantPointerNull::get]. *) +val const_pointer_null : lltype -> llvalue + +(** [undef ty] returns the undefined value of the type [ty]. + See the method [llvm::UndefValue::get]. *) +val undef : lltype -> llvalue + +(** [is_null v] returns [true] if the value [v] is the null (zero) value. + See the method [llvm::Constant::isNullValue]. *) +val is_null : llvalue -> bool + +(** [is_undef v] returns [true] if the value [v] is an undefined value, [false] + otherwise. Similar to [llvm::isa]. *) +val is_undef : llvalue -> bool + + +(** {7 Operations on instructions} *) + +(** [has_metadata i] returns whether or not the instruction [i] has any + metadata attached to it. See the function + [llvm::Instruction::hasMetadata]. *) +val has_metadata : llvalue -> bool + +(** [metadata i kind] optionally returns the metadata associated with the + kind [kind] in the instruction [i] See the function + [llvm::Instruction::getMetadata]. *) +val metadata : llvalue -> int -> llvalue option + +(** [set_metadata i kind md] sets the metadata [md] of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +val set_metadata : llvalue -> int -> llvalue -> unit + +(** [clear_metadata i kind] clears the metadata of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +val clear_metadata : llvalue -> int -> unit + + +(** {7 Operations on metadata} *) + +(** [mdstring c s] returns the MDString of the string [s] in the context [c]. + See the method [llvm::MDNode::get]. *) +val mdstring : llcontext -> string -> llvalue + +(** [mdnode c elts] returns the MDNode containing the values [elts] in the + context [c]. + See the method [llvm::MDNode::get]. *) +val mdnode : llcontext -> llvalue array -> llvalue + + +(** {7 Operations on scalar constants} *) + +(** [const_int ty i] returns the integer constant of type [ty] and value [i]. + See the method [llvm::ConstantInt::get]. *) +val const_int : lltype -> int -> llvalue + +(** [const_of_int64 ty i] returns the integer constant of type [ty] and value + [i]. See the method [llvm::ConstantInt::get]. *) +val const_of_int64 : lltype -> Int64.t -> bool -> llvalue + + +(** [const_int_of_string ty s r] returns the integer constant of type [ty] and + * value [s], with the radix [r]. See the method [llvm::ConstantInt::get]. *) +val const_int_of_string : lltype -> string -> int -> llvalue + + +(** [const_float ty n] returns the floating point constant of type [ty] and + value [n]. See the method [llvm::ConstantFP::get]. *) +val const_float : lltype -> float -> llvalue + +(** [const_float_of_string ty s] returns the floating point constant of type + [ty] and value [n]. See the method [llvm::ConstantFP::get]. *) +val const_float_of_string : lltype -> string -> llvalue + + + +(** {7 Operations on composite constants} *) + +(** [const_string c s] returns the constant [i8] array with the values of the + characters in the string [s] in the context [c]. The array is not + null-terminated (but see {!const_stringz}). This value can in turn be used + as the initializer for a global variable. See the method + [llvm::ConstantArray::get]. *) +val const_string : llcontext -> string -> llvalue + +(** [const_stringz c s] returns the constant [i8] array with the values of the + characters in the string [s] and a null terminator in the context [c]. This + value can in turn be used as the initializer for a global variable. + See the method [llvm::ConstantArray::get]. *) +val const_stringz : llcontext -> string -> llvalue + +(** [const_array ty elts] returns the constant array of type + [array_type ty (Array.length elts)] and containing the values [elts]. + This value can in turn be used as the initializer for a global variable. + See the method [llvm::ConstantArray::get]. *) +val const_array : lltype -> llvalue array -> llvalue + +(** [const_struct context elts] returns the structured constant of type + [struct_type (Array.map type_of elts)] and containing the values [elts] + in the context [context]. This value can in turn be used as the initializer + for a global variable. See the method [llvm::ConstantStruct::get]. *) +val const_struct : llcontext -> llvalue array -> llvalue + + +(** [const_packed_struct context elts] returns the structured constant of + type {!packed_struct_type} [(Array.map type_of elts)] and containing the + values [elts] in the context [context]. This value can in turn be used as + the initializer for a global variable. See the method + [llvm::ConstantStruct::get]. *) +val const_packed_struct : llcontext -> llvalue array -> llvalue + + +(** [const_vector elts] returns the vector constant of type + [vector_type (type_of elts.(0)) (Array.length elts)] and containing the + values [elts]. See the method [llvm::ConstantVector::get]. *) +val const_vector : llvalue array -> llvalue + + +(** {7 Constant expressions} *) + +(** [align_of ty] returns the alignof constant for the type [ty]. This is + equivalent to [const_ptrtoint (const_gep (const_null (pointer_type {i8,ty})) + (const_int i32_type 0) (const_int i32_type 1)) i32_type], but considerably + more readable. See the method [llvm::ConstantExpr::getAlignOf]. *) +val align_of : lltype -> llvalue + +(** [size_of ty] returns the sizeof constant for the type [ty]. This is + equivalent to [const_ptrtoint (const_gep (const_null (pointer_type ty)) + (const_int i32_type 1)) i64_type], but considerably more readable. + See the method [llvm::ConstantExpr::getSizeOf]. *) +val size_of : lltype -> llvalue + +(** [const_neg c] returns the arithmetic negation of the constant [c]. + See the method [llvm::ConstantExpr::getNeg]. *) +val const_neg : llvalue -> llvalue + +(** [const_nsw_neg c] returns the arithmetic negation of the constant [c] with + no signed wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNSWNeg]. *) +val const_nsw_neg : llvalue -> llvalue + +(** [const_nuw_neg c] returns the arithmetic negation of the constant [c] with + no unsigned wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNUWNeg]. *) +val const_nuw_neg : llvalue -> llvalue + +(** [const_fneg c] returns the arithmetic negation of the constant float [c]. + See the method [llvm::ConstantExpr::getFNeg]. *) +val const_fneg : llvalue -> llvalue + +(** [const_not c] returns the bitwise inverse of the constant [c]. + See the method [llvm::ConstantExpr::getNot]. *) +val const_not : llvalue -> llvalue + +(** [const_add c1 c2] returns the constant sum of two constants. + See the method [llvm::ConstantExpr::getAdd]. *) +val const_add : llvalue -> llvalue -> llvalue + +(** [const_nsw_add c1 c2] returns the constant sum of two constants with no + signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWAdd]. *) +val const_nsw_add : llvalue -> llvalue -> llvalue + +(** [const_nuw_add c1 c2] returns the constant sum of two constants with no + unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWAdd]. *) +val const_nuw_add : llvalue -> llvalue -> llvalue + +(** [const_fadd c1 c2] returns the constant sum of two constant floats. + See the method [llvm::ConstantExpr::getFAdd]. *) +val const_fadd : llvalue -> llvalue -> llvalue + +(** [const_sub c1 c2] returns the constant difference, [c1 - c2], of two + constants. See the method [llvm::ConstantExpr::getSub]. *) +val const_sub : llvalue -> llvalue -> llvalue + +(** [const_nsw_sub c1 c2] returns the constant difference of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +val const_nsw_sub : llvalue -> llvalue -> llvalue + +(** [const_nuw_sub c1 c2] returns the constant difference of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +val const_nuw_sub : llvalue -> llvalue -> llvalue + +(** [const_fsub c1 c2] returns the constant difference, [c1 - c2], of two + constant floats. See the method [llvm::ConstantExpr::getFSub]. *) +val const_fsub : llvalue -> llvalue -> llvalue + +(** [const_mul c1 c2] returns the constant product of two constants. + See the method [llvm::ConstantExpr::getMul]. *) +val const_mul : llvalue -> llvalue -> llvalue + +(** [const_nsw_mul c1 c2] returns the constant product of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +val const_nsw_mul : llvalue -> llvalue -> llvalue + +(** [const_nuw_mul c1 c2] returns the constant product of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +val const_nuw_mul : llvalue -> llvalue -> llvalue + +(** [const_fmul c1 c2] returns the constant product of two constants floats. + See the method [llvm::ConstantExpr::getFMul]. *) +val const_fmul : llvalue -> llvalue -> llvalue + +(** [const_udiv c1 c2] returns the constant quotient [c1 / c2] of two unsigned + integer constants. + See the method [llvm::ConstantExpr::getUDiv]. *) +val const_udiv : llvalue -> llvalue -> llvalue + +(** [const_sdiv c1 c2] returns the constant quotient [c1 / c2] of two signed + integer constants. + See the method [llvm::ConstantExpr::getSDiv]. *) +val const_sdiv : llvalue -> llvalue -> llvalue + +(** [const_exact_sdiv c1 c2] returns the constant quotient [c1 / c2] of two + signed integer constants. The result is undefined if the result is rounded + or overflows. See the method [llvm::ConstantExpr::getExactSDiv]. *) +val const_exact_sdiv : llvalue -> llvalue -> llvalue + +(** [const_fdiv c1 c2] returns the constant quotient [c1 / c2] of two floating + point constants. + See the method [llvm::ConstantExpr::getFDiv]. *) +val const_fdiv : llvalue -> llvalue -> llvalue + +(** [const_urem c1 c2] returns the constant remainder [c1 MOD c2] of two + unsigned integer constants. + See the method [llvm::ConstantExpr::getURem]. *) +val const_urem : llvalue -> llvalue -> llvalue + +(** [const_srem c1 c2] returns the constant remainder [c1 MOD c2] of two + signed integer constants. + See the method [llvm::ConstantExpr::getSRem]. *) +val const_srem : llvalue -> llvalue -> llvalue + +(** [const_frem c1 c2] returns the constant remainder [c1 MOD c2] of two + signed floating point constants. + See the method [llvm::ConstantExpr::getFRem]. *) +val const_frem : llvalue -> llvalue -> llvalue + +(** [const_and c1 c2] returns the constant bitwise [AND] of two integer + constants. + See the method [llvm::ConstantExpr::getAnd]. *) +val const_and : llvalue -> llvalue -> llvalue + +(** [const_or c1 c2] returns the constant bitwise [OR] of two integer + constants. + See the method [llvm::ConstantExpr::getOr]. *) +val const_or : llvalue -> llvalue -> llvalue + +(** [const_xor c1 c2] returns the constant bitwise [XOR] of two integer + constants. + See the method [llvm::ConstantExpr::getXor]. *) +val const_xor : llvalue -> llvalue -> llvalue + +(** [const_icmp pred c1 c2] returns the constant comparison of two integer + constants, [c1 pred c2]. + See the method [llvm::ConstantExpr::getICmp]. *) +val const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue + + +(** [const_fcmp pred c1 c2] returns the constant comparison of two floating + point constants, [c1 pred c2]. + See the method [llvm::ConstantExpr::getFCmp]. *) +val const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue + + +(** [const_shl c1 c2] returns the constant integer [c1] left-shifted by the + constant integer [c2]. + See the method [llvm::ConstantExpr::getShl]. *) +val const_shl : llvalue -> llvalue -> llvalue + +(** [const_lshr c1 c2] returns the constant integer [c1] right-shifted by the + constant integer [c2] with zero extension. + See the method [llvm::ConstantExpr::getLShr]. *) +val const_lshr : llvalue -> llvalue -> llvalue + +(** [const_ashr c1 c2] returns the constant integer [c1] right-shifted by the + constant integer [c2] with sign extension. + See the method [llvm::ConstantExpr::getAShr]. *) +val const_ashr : llvalue -> llvalue -> llvalue + +(** [const_gep pc indices] returns the constant [getElementPtr] of [p1] with the + constant integers indices from the array [indices]. + See the method [llvm::ConstantExpr::getGetElementPtr]. *) +val const_gep : llvalue -> llvalue array -> llvalue + +(** [const_in_bounds_gep pc indices] returns the constant [getElementPtr] of [p1] + with the constant integers indices from the array [indices]. + See the method [llvm::ConstantExpr::getInBoundsGetElementPtr]. *) +val const_in_bounds_gep : llvalue -> llvalue array -> llvalue + + +(** [const_trunc c ty] returns the constant truncation of integer constant [c] + to the smaller integer type [ty]. + See the method [llvm::ConstantExpr::getTrunc]. *) +val const_trunc : llvalue -> lltype -> llvalue + +(** [const_sext c ty] returns the constant sign extension of integer constant + [c] to the larger integer type [ty]. + See the method [llvm::ConstantExpr::getSExt]. *) +val const_sext : llvalue -> lltype -> llvalue + +(** [const_zext c ty] returns the constant zero extension of integer constant + [c] to the larger integer type [ty]. + See the method [llvm::ConstantExpr::getZExt]. *) +val const_zext : llvalue -> lltype -> llvalue + +(** [const_fptrunc c ty] returns the constant truncation of floating point + constant [c] to the smaller floating point type [ty]. + See the method [llvm::ConstantExpr::getFPTrunc]. *) +val const_fptrunc : llvalue -> lltype -> llvalue + +(** [const_fpext c ty] returns the constant extension of floating point constant + [c] to the larger floating point type [ty]. + See the method [llvm::ConstantExpr::getFPExt]. *) +val const_fpext : llvalue -> lltype -> llvalue + +(** [const_uitofp c ty] returns the constant floating point conversion of + unsigned integer constant [c] to the floating point type [ty]. + See the method [llvm::ConstantExpr::getUIToFP]. *) +val const_uitofp : llvalue -> lltype -> llvalue + +(** [const_sitofp c ty] returns the constant floating point conversion of + signed integer constant [c] to the floating point type [ty]. + See the method [llvm::ConstantExpr::getSIToFP]. *) +val const_sitofp : llvalue -> lltype -> llvalue + +(** [const_fptoui c ty] returns the constant unsigned integer conversion of + floating point constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getFPToUI]. *) +val const_fptoui : llvalue -> lltype -> llvalue + +(** [const_fptoui c ty] returns the constant unsigned integer conversion of + floating point constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getFPToSI]. *) +val const_fptosi : llvalue -> lltype -> llvalue + +(** [const_ptrtoint c ty] returns the constant integer conversion of + pointer constant [c] to integer type [ty]. + See the method [llvm::ConstantExpr::getPtrToInt]. *) +val const_ptrtoint : llvalue -> lltype -> llvalue + +(** [const_inttoptr c ty] returns the constant pointer conversion of + integer constant [c] to pointer type [ty]. + See the method [llvm::ConstantExpr::getIntToPtr]. *) +val const_inttoptr : llvalue -> lltype -> llvalue + +(** [const_bitcast c ty] returns the constant bitwise conversion of constant [c] + to type [ty] of equal size. + See the method [llvm::ConstantExpr::getBitCast]. *) +val const_bitcast : llvalue -> lltype -> llvalue + +(** [const_zext_or_bitcast c ty] returns a constant zext or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getZExtOrBitCast]. *) +val const_zext_or_bitcast : llvalue -> lltype -> llvalue + + +(** [const_sext_or_bitcast c ty] returns a constant sext or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getSExtOrBitCast]. *) +val const_sext_or_bitcast : llvalue -> lltype -> llvalue + + +(** [const_trunc_or_bitcast c ty] returns a constant trunc or bitwise cast + conversion of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getTruncOrBitCast]. *) +val const_trunc_or_bitcast : llvalue -> lltype -> llvalue + + +(** [const_pointercast c ty] returns a constant bitcast or a pointer-to-int + cast conversion of constant [c] to type [ty] of equal size. + See the method [llvm::ConstantExpr::getPointerCast]. *) +val const_pointercast : llvalue -> lltype -> llvalue + + +(** [const_intcast c ty] returns a constant zext, bitcast, or trunc for integer + -> integer casts of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getIntCast]. *) +val const_intcast : llvalue -> lltype -> llvalue + + +(** [const_fpcast c ty] returns a constant fpext, bitcast, or fptrunc for fp -> + fp casts of constant [c] to type [ty]. + See the method [llvm::ConstantExpr::getFPCast]. *) +val const_fpcast : llvalue -> lltype -> llvalue + + +(** [const_select cond t f] returns the constant conditional which returns value + [t] if the boolean constant [cond] is true and the value [f] otherwise. + See the method [llvm::ConstantExpr::getSelect]. *) +val const_select : llvalue -> llvalue -> llvalue -> llvalue + + +(** [const_extractelement vec i] returns the constant [i]th element of + constant vector [vec]. [i] must be a constant [i32] value unsigned less than + the size of the vector. + See the method [llvm::ConstantExpr::getExtractElement]. *) +val const_extractelement : llvalue -> llvalue -> llvalue + + +(** [const_insertelement vec v i] returns the constant vector with the same + elements as constant vector [v] but the [i]th element replaced by the + constant [v]. [v] must be a constant value with the type of the vector + elements. [i] must be a constant [i32] value unsigned less than the size + of the vector. + See the method [llvm::ConstantExpr::getInsertElement]. *) +val const_insertelement : llvalue -> llvalue -> llvalue -> llvalue + + +(** [const_shufflevector a b mask] returns a constant [shufflevector]. + See the LLVM Language Reference for details on the [shufflevector] + instruction. + See the method [llvm::ConstantExpr::getShuffleVector]. *) +val const_shufflevector : llvalue -> llvalue -> llvalue -> llvalue + + +(** [const_extractvalue agg idxs] returns the constant [idxs]th value of + constant aggregate [agg]. Each [idxs] must be less than the size of the + aggregate. See the method [llvm::ConstantExpr::getExtractValue]. *) +val const_extractvalue : llvalue -> int array -> llvalue + + +(** [const_insertvalue agg val idxs] inserts the value [val] in the specified + indexs [idxs] in the aggegate [agg]. Each [idxs] must be less than the size + of the aggregate. See the method [llvm::ConstantExpr::getInsertValue]. *) +val const_insertvalue : llvalue -> llvalue -> int array -> llvalue + + +(** [const_inline_asm ty asm con side align] inserts a inline assembly string. + See the method [llvm::InlineAsm::get]. *) +val const_inline_asm : lltype -> string -> string -> bool -> bool -> + llvalue + + +(** [block_address f bb] returns the address of the basic block [bb] in the + function [f]. See the method [llvm::BasicBlock::get]. *) +val block_address : llvalue -> llbasicblock -> llvalue + + +(** {7 Operations on global variables, functions, and aliases (globals)} *) + +(** [global_parent g] is the enclosing module of the global value [g]. + See the method [llvm::GlobalValue::getParent]. *) +val global_parent : llvalue -> llmodule + +(** [is_declaration g] returns [true] if the global value [g] is a declaration + only. Returns [false] otherwise. + See the method [llvm::GlobalValue::isDeclaration]. *) +val is_declaration : llvalue -> bool + +(** [linkage g] returns the linkage of the global value [g]. + See the method [llvm::GlobalValue::getLinkage]. *) +val linkage : llvalue -> Linkage.t + +(** [set_linkage l g] sets the linkage of the global value [g] to [l]. + See the method [llvm::GlobalValue::setLinkage]. *) +val set_linkage : Linkage.t -> llvalue -> unit + +(** [section g] returns the linker section of the global value [g]. + See the method [llvm::GlobalValue::getSection]. *) +val section : llvalue -> string + +(** [set_section s g] sets the linker section of the global value [g] to [s]. + See the method [llvm::GlobalValue::setSection]. *) +val set_section : string -> llvalue -> unit + +(** [visibility g] returns the linker visibility of the global value [g]. + See the method [llvm::GlobalValue::getVisibility]. *) +val visibility : llvalue -> Visibility.t + +(** [set_visibility v g] sets the linker visibility of the global value [g] to + [v]. See the method [llvm::GlobalValue::setVisibility]. *) +val set_visibility : Visibility.t -> llvalue -> unit + + +(** [alignment g] returns the required alignment of the global value [g]. + See the method [llvm::GlobalValue::getAlignment]. *) +val alignment : llvalue -> int + +(** [set_alignment n g] sets the required alignment of the global value [g] to + [n] bytes. See the method [llvm::GlobalValue::setAlignment]. *) +val set_alignment : int -> llvalue -> unit + + +(** {7 Operations on global variables} *) + +(** [declare_global ty name m] returns a new global variable of type [ty] and + with name [name] in module [m] in the default address space (0). If such a + global variable already exists, it is returned. If the type of the existing + global differs, then a bitcast to [ty] is returned. *) +val declare_global : lltype -> string -> llmodule -> llvalue + + +(** [declare_qualified_global ty name addrspace m] returns a new global variable + of type [ty] and with name [name] in module [m] in the address space + [addrspace]. If such a global variable already exists, it is returned. If + the type of the existing global differs, then a bitcast to [ty] is + returned. *) +val declare_qualified_global : lltype -> string -> int -> llmodule -> + llvalue + + +(** [define_global name init m] returns a new global with name [name] and + initializer [init] in module [m] in the default address space (0). If the + named global already exists, it is renamed. + See the constructor of [llvm::GlobalVariable]. *) +val define_global : string -> llvalue -> llmodule -> llvalue + + +(** [define_qualified_global name init addrspace m] returns a new global with + name [name] and initializer [init] in module [m] in the address space + [addrspace]. If the named global already exists, it is renamed. + See the constructor of [llvm::GlobalVariable]. *) +val define_qualified_global : string -> llvalue -> int -> llmodule -> + llvalue + + +(** [lookup_global name m] returns [Some g] if a global variable with name + [name] exists in module [m]. If no such global exists, returns [None]. + See the [llvm::GlobalVariable] constructor. *) +val lookup_global : string -> llmodule -> llvalue option + + +(** [delete_global gv] destroys the global variable [gv]. + See the method [llvm::GlobalVariable::eraseFromParent]. *) +val delete_global : llvalue -> unit + +(** [global_begin m] returns the first position in the global variable list of + the module [m]. [global_begin] and [global_succ] can be used to iterate + over the global list in order. + See the method [llvm::Module::global_begin]. *) +val global_begin : llmodule -> (llmodule, llvalue) llpos + + +(** [global_succ gv] returns the global variable list position succeeding + [Before gv]. + See the method [llvm::Module::global_iterator::operator++]. *) +val global_succ : llvalue -> (llmodule, llvalue) llpos + + +(** [iter_globals f m] applies function [f] to each of the global variables of + module [m] in order. Tail recursive. *) +val iter_globals : (llvalue -> unit) -> llmodule -> unit + +(** [fold_left_globals f init m] is [f (... (f init g1) ...) gN] where + [g1,...,gN] are the global variables of module [m]. Tail recursive. *) +val fold_left_globals : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a + +(** [global_end m] returns the last position in the global variable list of the + module [m]. [global_end] and [global_pred] can be used to iterate over the + global list in reverse. + See the method [llvm::Module::global_end]. *) +val global_end : llmodule -> (llmodule, llvalue) llrev_pos + + +(** [global_pred gv] returns the global variable list position preceding + [After gv]. + See the method [llvm::Module::global_iterator::operator--]. *) +val global_pred : llvalue -> (llmodule, llvalue) llrev_pos + + +(** [rev_iter_globals f m] applies function [f] to each of the global variables + of module [m] in reverse order. Tail recursive. *) +val rev_iter_globals : (llvalue -> unit) -> llmodule -> unit + +(** [fold_right_globals f m init] is [f g1 (... (f gN init) ...)] where + [g1,...,gN] are the global variables of module [m]. Tail recursive. *) +val fold_right_globals : (llvalue -> 'a -> 'a) -> llmodule -> 'a -> 'a + +(** [is_global_constant gv] returns [true] if the global variabile [gv] is a + constant. Returns [false] otherwise. + See the method [llvm::GlobalVariable::isConstant]. *) +val is_global_constant : llvalue -> bool + +(** [set_global_constant c gv] sets the global variable [gv] to be a constant if + [c] is [true] and not if [c] is [false]. + See the method [llvm::GlobalVariable::setConstant]. *) +val set_global_constant : bool -> llvalue -> unit + + +(** [global_initializer gv] returns the initializer for the global variable + [gv]. See the method [llvm::GlobalVariable::getInitializer]. *) +val global_initializer : llvalue -> llvalue + +(** [set_initializer c gv] sets the initializer for the global variable + [gv] to the constant [c]. + See the method [llvm::GlobalVariable::setInitializer]. *) +val set_initializer : llvalue -> llvalue -> unit + +(** [remove_initializer gv] unsets the initializer for the global variable + [gv]. + See the method [llvm::GlobalVariable::setInitializer]. *) +val remove_initializer : llvalue -> unit + +(** [is_thread_local gv] returns [true] if the global variable [gv] is + thread-local and [false] otherwise. + See the method [llvm::GlobalVariable::isThreadLocal]. *) +val is_thread_local : llvalue -> bool + +(** [set_thread_local c gv] sets the global variable [gv] to be thread local if + [c] is [true] and not otherwise. + See the method [llvm::GlobalVariable::setThreadLocal]. *) +val set_thread_local : bool -> llvalue -> unit + + +(** {7 Operations on aliases} *) + +(** [add_alias m t a n] inserts an alias in the module [m] with the type [t] and + the aliasee [a] with the name [n]. + See the constructor for [llvm::GlobalAlias]. *) +val add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + + + +(** {7 Operations on functions} *) + +(** [declare_function name ty m] returns a new function of type [ty] and + with name [name] in module [m]. If such a function already exists, + it is returned. If the type of the existing function differs, then a bitcast + to [ty] is returned. *) +val declare_function : string -> lltype -> llmodule -> llvalue + + +(** [define_function name ty m] creates a new function with name [name] and + type [ty] in module [m]. If the named function already exists, it is + renamed. An entry basic block is created in the function. + See the constructor of [llvm::GlobalVariable]. *) +val define_function : string -> lltype -> llmodule -> llvalue + + +(** [lookup_function name m] returns [Some f] if a function with name + [name] exists in module [m]. If no such function exists, returns [None]. + See the method [llvm::Module] constructor. *) +val lookup_function : string -> llmodule -> llvalue option + + +(** [delete_function f] destroys the function [f]. + See the method [llvm::Function::eraseFromParent]. *) +val delete_function : llvalue -> unit + +(** [function_begin m] returns the first position in the function list of the + module [m]. [function_begin] and [function_succ] can be used to iterate over + the function list in order. + See the method [llvm::Module::begin]. *) +val function_begin : llmodule -> (llmodule, llvalue) llpos + + +(** [function_succ gv] returns the function list position succeeding + [Before gv]. + See the method [llvm::Module::iterator::operator++]. *) +val function_succ : llvalue -> (llmodule, llvalue) llpos + + +(** [iter_functions f m] applies function [f] to each of the functions of module + [m] in order. Tail recursive. *) +val iter_functions : (llvalue -> unit) -> llmodule -> unit + +(** [fold_left_function f init m] is [f (... (f init f1) ...) fN] where + [f1,...,fN] are the functions of module [m]. Tail recursive. *) +val fold_left_functions : ('a -> llvalue -> 'a) -> 'a -> llmodule -> 'a + +(** [function_end m] returns the last position in the function list of + the module [m]. [function_end] and [function_pred] can be used to iterate + over the function list in reverse. + See the method [llvm::Module::end]. *) +val function_end : llmodule -> (llmodule, llvalue) llrev_pos + + +(** [function_pred gv] returns the function list position preceding [After gv]. + See the method [llvm::Module::iterator::operator--]. *) +val function_pred : llvalue -> (llmodule, llvalue) llrev_pos + + +(** [rev_iter_functions f fn] applies function [f] to each of the functions of + module [m] in reverse order. Tail recursive. *) +val rev_iter_functions : (llvalue -> unit) -> llmodule -> unit + +(** [fold_right_functions f m init] is [f (... (f init fN) ...) f1] where + [f1,...,fN] are the functions of module [m]. Tail recursive. *) +val fold_right_functions : (llvalue -> 'a -> 'a) -> llmodule -> 'a -> 'a + +(** [is_intrinsic f] returns true if the function [f] is an intrinsic. + See the method [llvm::Function::isIntrinsic]. *) +val is_intrinsic : llvalue -> bool + +(** [function_call_conv f] returns the calling convention of the function [f]. + See the method [llvm::Function::getCallingConv]. *) +val function_call_conv : llvalue -> int + +(** [set_function_call_conv cc f] sets the calling convention of the function + [f] to the calling convention numbered [cc]. + See the method [llvm::Function::setCallingConv]. *) +val set_function_call_conv : int -> llvalue -> unit + + +(** [gc f] returns [Some name] if the function [f] has a garbage + collection algorithm specified and [None] otherwise. + See the method [llvm::Function::getGC]. *) +val gc : llvalue -> string option + +(** [set_gc gc f] sets the collection algorithm for the function [f] to + [gc]. See the method [llvm::Function::setGC]. *) +val set_gc : string option -> llvalue -> unit + +(** [add_function_attr f a] adds attribute [a] to the return type of function + [f]. *) +val add_function_attr : llvalue -> Attribute.t -> unit + +(** [remove_function_attr f a] removes attribute [a] from the return type of + function [f]. *) +val remove_function_attr : llvalue -> Attribute.t -> unit + +(** {7 Operations on params} *) + +(** [params f] returns the parameters of function [f]. + See the method [llvm::Function::getArgumentList]. *) +val params : llvalue -> llvalue array + +(** [param f n] returns the [n]th parameter of function [f]. + See the method [llvm::Function::getArgumentList]. *) +val param : llvalue -> int -> llvalue + +(** [param_parent p] returns the parent function that owns the parameter. + See the method [llvm::Argument::getParent]. *) +val param_parent : llvalue -> llvalue + +(** [param_begin f] returns the first position in the parameter list of the + function [f]. [param_begin] and [param_succ] can be used to iterate over + the parameter list in order. + See the method [llvm::Function::arg_begin]. *) +val param_begin : llvalue -> (llvalue, llvalue) llpos + +(** [param_succ bb] returns the parameter list position succeeding + [Before bb]. + See the method [llvm::Function::arg_iterator::operator++]. *) +val param_succ : llvalue -> (llvalue, llvalue) llpos + +(** [iter_params f fn] applies function [f] to each of the parameters + of function [fn] in order. Tail recursive. *) +val iter_params : (llvalue -> unit) -> llvalue -> unit + +(** [fold_left_params f init fn] is [f (... (f init b1) ...) bN] where + [b1,...,bN] are the parameters of function [fn]. Tail recursive. *) +val fold_left_params : ('a -> llvalue -> 'a) -> 'a -> llvalue -> 'a + +(** [param_end f] returns the last position in the parameter list of + the function [f]. [param_end] and [param_pred] can be used to iterate + over the parameter list in reverse. + See the method [llvm::Function::arg_end]. *) +val param_end : llvalue -> (llvalue, llvalue) llrev_pos + +(** [param_pred gv] returns the function list position preceding [After gv]. + See the method [llvm::Function::arg_iterator::operator--]. *) +val param_pred : llvalue -> (llvalue, llvalue) llrev_pos + + +(** [rev_iter_params f fn] applies function [f] to each of the parameters + of function [fn] in reverse order. Tail recursive. *) +val rev_iter_params : (llvalue -> unit) -> llvalue -> unit + +(** [fold_right_params f fn init] is [f (... (f init bN) ...) b1] where + [b1,...,bN] are the parameters of function [fn]. Tail recursive. *) +val fold_right_params : (llvalue -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** [add_param p a] adds attribute [a] to parameter [p]. *) +val add_param_attr : llvalue -> Attribute.t -> unit + +(** [remove_param_attr p a] removes attribute [a] from parameter [p]. *) +val remove_param_attr : llvalue -> Attribute.t -> unit + +(** [set_param_alignment p a] set the alignment of parameter [p] to [a]. *) +val set_param_alignment : llvalue -> int -> unit + + +(** {7 Operations on basic blocks} *) + +(** [basic_blocks fn] returns the basic blocks of the function [f]. + See the method [llvm::Function::getBasicBlockList]. *) +val basic_blocks : llvalue -> llbasicblock array + +(** [entry_block fn] returns the entry basic block of the function [f]. + See the method [llvm::Function::getEntryBlock]. *) +val entry_block : llvalue -> llbasicblock + +(** [delete_block bb] deletes the basic block [bb]. + See the method [llvm::BasicBlock::eraseFromParent]. *) +val delete_block : llbasicblock -> unit + +(** [append_block c name f] creates a new basic block named [name] at the end of + function [f] in the context [c]. + See the constructor of [llvm::BasicBlock]. *) +val append_block : llcontext -> string -> llvalue -> llbasicblock + + +(** [insert_block c name bb] creates a new basic block named [name] before the + basic block [bb] in the context [c]. + See the constructor of [llvm::BasicBlock]. *) +val insert_block : llcontext -> string -> llbasicblock -> llbasicblock + + +(** [block_parent bb] returns the parent function that owns the basic block. + See the method [llvm::BasicBlock::getParent]. *) +val block_parent : llbasicblock -> llvalue + +(** [block_begin f] returns the first position in the basic block list of the + function [f]. [block_begin] and [block_succ] can be used to iterate over + the basic block list in order. + See the method [llvm::Function::begin]. *) +val block_begin : llvalue -> (llvalue, llbasicblock) llpos + + +(** [block_succ bb] returns the basic block list position succeeding + [Before bb]. + See the method [llvm::Function::iterator::operator++]. *) +val block_succ : llbasicblock -> (llvalue, llbasicblock) llpos + + +(** [iter_blocks f fn] applies function [f] to each of the basic blocks + of function [fn] in order. Tail recursive. *) +val iter_blocks : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_left_blocks f init fn] is [f (... (f init b1) ...) bN] where + [b1,...,bN] are the basic blocks of function [fn]. Tail recursive. *) +val fold_left_blocks : ('a -> llbasicblock -> 'a) -> 'a -> llvalue -> 'a + +(** [block_end f] returns the last position in the basic block list of + the function [f]. [block_end] and [block_pred] can be used to iterate + over the basic block list in reverse. + See the method [llvm::Function::end]. *) +val block_end : llvalue -> (llvalue, llbasicblock) llrev_pos + + +(** [block_pred gv] returns the function list position preceding [After gv]. + See the method [llvm::Function::iterator::operator--]. *) +val block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos + + +(** [rev_iter_blocks f fn] applies function [f] to each of the basic blocks + of function [fn] in reverse order. Tail recursive. *) +val rev_iter_blocks : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_right_blocks f fn init] is [f (... (f init bN) ...) b1] where + [b1,...,bN] are the basic blocks of function [fn]. Tail recursive. *) +val fold_right_blocks : (llbasicblock -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** [value_of_block bb] losslessly casts [bb] to an [llvalue]. *) +val value_of_block : llbasicblock -> llvalue + +(** [value_is_block v] returns [true] if the value [v] is a basic block and + [false] otherwise. + Similar to [llvm::isa]. *) +val value_is_block : llvalue -> bool + +(** [block_of_value v] losslessly casts [v] to an [llbasicblock]. *) +val block_of_value : llvalue -> llbasicblock + + +(** {7 Operations on instructions} *) + +(** [instr_parent i] is the enclosing basic block of the instruction [i]. + See the method [llvm::Instruction::getParent]. *) +val instr_parent : llvalue -> llbasicblock + +(** [instr_begin bb] returns the first position in the instruction list of the + basic block [bb]. [instr_begin] and [instr_succ] can be used to iterate over + the instruction list in order. + See the method [llvm::BasicBlock::begin]. *) +val instr_begin : llbasicblock -> (llbasicblock, llvalue) llpos + + +(** [instr_succ i] returns the instruction list position succeeding [Before i]. + See the method [llvm::BasicBlock::iterator::operator++]. *) +val instr_succ : llvalue -> (llbasicblock, llvalue) llpos + + +(** [iter_instrs f bb] applies function [f] to each of the instructions of basic + block [bb] in order. Tail recursive. *) +val iter_instrs: (llvalue -> unit) -> llbasicblock -> unit + +(** [fold_left_instrs f init bb] is [f (... (f init g1) ...) gN] where + [g1,...,gN] are the instructions of basic block [bb]. Tail recursive. *) +val fold_left_instrs: ('a -> llvalue -> 'a) -> 'a -> llbasicblock -> 'a + +(** [instr_end bb] returns the last position in the instruction list of the + basic block [bb]. [instr_end] and [instr_pred] can be used to iterate over + the instruction list in reverse. + See the method [llvm::BasicBlock::end]. *) +val instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos + + +(** [instr_pred i] returns the instruction list position preceding [After i]. + See the method [llvm::BasicBlock::iterator::operator--]. *) +val instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos + + +(** [fold_right_instrs f bb init] is [f (... (f init fN) ...) f1] where + [f1,...,fN] are the instructions of basic block [bb]. Tail recursive. *) +val fold_right_instrs: (llvalue -> 'a -> 'a) -> llbasicblock -> 'a -> 'a + + +(** {7 Operations on call sites} *) + +(** [instruction_call_conv ci] is the calling convention for the call or invoke + instruction [ci], which may be one of the values from the module + {!CallConv}. See the method [llvm::CallInst::getCallingConv] and + [llvm::InvokeInst::getCallingConv]. *) +val instruction_call_conv: llvalue -> int + + +(** [set_instruction_call_conv cc ci] sets the calling convention for the call + or invoke instruction [ci] to the integer [cc], which can be one of the + values from the module {!CallConv}. + See the method [llvm::CallInst::setCallingConv] + and [llvm::InvokeInst::setCallingConv]. *) +val set_instruction_call_conv: int -> llvalue -> unit + + +(** [add_instruction_param_attr ci i a] adds attribute [a] to the [i]th + parameter of the call or invoke instruction [ci]. [i]=0 denotes the return + value. *) +val add_instruction_param_attr : llvalue -> int -> Attribute.t -> unit + +(** [remove_instruction_param_attr ci i a] removes attribute [a] from the + [i]th parameter of the call or invoke instruction [ci]. [i]=0 denotes the + return value. *) +val remove_instruction_param_attr : llvalue -> int -> Attribute.t -> unit + +(** {Operations on call instructions (only)} *) + +(** [is_tail_call ci] is [true] if the call instruction [ci] is flagged as + eligible for tail call optimization, [false] otherwise. + See the method [llvm::CallInst::isTailCall]. *) +val is_tail_call : llvalue -> bool + +(** [set_tail_call tc ci] flags the call instruction [ci] as eligible for tail + call optimization if [tc] is [true], clears otherwise. + See the method [llvm::CallInst::setTailCall]. *) +val set_tail_call : bool -> llvalue -> unit + +(** {7 Operations on phi nodes} *) + +(** [add_incoming (v, bb) pn] adds the value [v] to the phi node [pn] for use + with branches from [bb]. See the method [llvm::PHINode::addIncoming]. *) +val add_incoming : (llvalue * llbasicblock) -> llvalue -> unit + + +(** [incoming pn] returns the list of value-block pairs for phi node [pn]. + See the method [llvm::PHINode::getIncomingValue]. *) +val incoming : llvalue -> (llvalue * llbasicblock) list + + + +(** {6 Instruction builders} *) + +(** [builder context] creates an instruction builder with no position in + the context [context]. It is invalid to use this builder until its position + is set with {!position_before} or {!position_at_end}. See the constructor + for [llvm::LLVMBuilder]. *) +val builder : llcontext -> llbuilder + +(** [builder_at ip] creates an instruction builder positioned at [ip]. + See the constructor for [llvm::LLVMBuilder]. *) +val builder_at : llcontext -> (llbasicblock, llvalue) llpos -> llbuilder + +(** [builder_before ins] creates an instruction builder positioned before the + instruction [isn]. See the constructor for [llvm::LLVMBuilder]. *) +val builder_before : llcontext -> llvalue -> llbuilder + +(** [builder_at_end bb] creates an instruction builder positioned at the end of + the basic block [bb]. See the constructor for [llvm::LLVMBuilder]. *) +val builder_at_end : llcontext -> llbasicblock -> llbuilder + +(** [position_builder ip bb] moves the instruction builder [bb] to the position + [ip]. + See the constructor for [llvm::LLVMBuilder]. *) +val position_builder : (llbasicblock, llvalue) llpos -> llbuilder -> unit + + +(** [position_before ins b] moves the instruction builder [b] to before the + instruction [isn]. See the method [llvm::LLVMBuilder::SetInsertPoint]. *) +val position_before : llvalue -> llbuilder -> unit + +(** [position_at_end bb b] moves the instruction builder [b] to the end of the + basic block [bb]. See the method [llvm::LLVMBuilder::SetInsertPoint]. *) +val position_at_end : llbasicblock -> llbuilder -> unit + +(** [insertion_block b] returns the basic block that the builder [b] is + positioned to insert into. Raises [Not_Found] if the instruction builder is + uninitialized. + See the method [llvm::LLVMBuilder::GetInsertBlock]. *) +val insertion_block : llbuilder -> llbasicblock + +(** [insert_into_builder i name b] inserts the specified instruction [i] at the + position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::Insert]. *) +val insert_into_builder : llvalue -> string -> llbuilder -> unit + + +(** {7 Metadata} *) + +(** [set_current_debug_location b md] sets the current debug location [md] in + the builder [b]. + See the method [llvm::IRBuilder::SetDebugLocation]. *) +val set_current_debug_location : llbuilder -> llvalue -> unit + + +(** [clear_current_debug_location b] clears the current debug location in the + builder [b]. *) +val clear_current_debug_location : llbuilder -> unit + + +(** [current_debug_location b] returns the current debug location, or None + if none is currently set. + See the method [llvm::IRBuilder::GetDebugLocation]. *) +val current_debug_location : llbuilder -> llvalue option + + +(** [set_inst_debug_location b i] sets the current debug location of the builder + [b] to the instruction [i]. + See the method [llvm::IRBuilder::SetInstDebugLocation]. *) +val set_inst_debug_location : llbuilder -> llvalue -> unit + + +(** {7 Terminators} *) + +(** [build_ret_void b] creates a + [ret void] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateRetVoid]. *) +val build_ret_void : llbuilder -> llvalue + +(** [build_ret v b] creates a + [ret %v] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateRet]. *) +val build_ret : llvalue -> llbuilder -> llvalue + +(** [build_aggregate_ret vs b] creates a + [ret {...} { %v1, %v2, ... } ] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAggregateRet]. *) +val build_aggregate_ret : llvalue array -> llbuilder -> llvalue + + +(** [build_br bb b] creates a + [br %bb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateBr]. *) +val build_br : llbasicblock -> llbuilder -> llvalue + +(** [build_cond_br cond tbb fbb b] creates a + [br %cond, %tbb, %fbb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateCondBr]. *) +val build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder -> + llvalue + +(** [build_switch case elsebb count b] creates an empty + [switch %case, %elsebb] + instruction at the position specified by the instruction builder [b] with + space reserved for [count] cases. + See the method [llvm::LLVMBuilder::CreateSwitch]. *) +val build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue + + +(** [add_case sw onval bb] causes switch instruction [sw] to branch to [bb] + when its input matches the constant [onval]. + See the method [llvm::SwitchInst::addCase]. **) +val add_case : llvalue -> llvalue -> llbasicblock -> unit + + +(** [build_indirect_br addr count b] creates a + [indirectbr %addr] + instruction at the position specified by the instruction builder [b] with + space reserved for [count] destinations. + See the method [llvm::LLVMBuilder::CreateIndirectBr]. *) +val build_indirect_br : llvalue -> int -> llbuilder -> llvalue + + +(** [add_destination br bb] adds the basic block [bb] as a possible branch + location for the indirectbr instruction [br]. + See the method [llvm::IndirectBrInst::addDestination]. **) +val add_destination : llvalue -> llbasicblock -> unit + + +(** [build_invoke fn args tobb unwindbb name b] creates an + [%name = invoke %fn(args) to %tobb unwind %unwindbb] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInvoke]. *) +val build_invoke : llvalue -> llvalue array -> llbasicblock -> + llbasicblock -> string -> llbuilder -> llvalue + + +(** [build_unwind b] creates an + [unwind] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUnwind]. *) +val build_unwind : llbuilder -> llvalue + +(** [build_unreachable b] creates an + [unreachable] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUnwind]. *) +val build_unreachable : llbuilder -> llvalue + + +(** {7 Arithmetic} *) + +(** [build_add x y name b] creates a + [%name = add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAdd]. *) +val build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nsw_add x y name b] creates a + [%name = nsw add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWAdd]. *) +val build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nuw_add x y name b] creates a + [%name = nuw add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWAdd]. *) +val build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_fadd x y name b] creates a + [%name = fadd %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFAdd]. *) +val build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_sub x y name b] creates a + [%name = sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSub]. *) +val build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nsw_sub x y name b] creates a + [%name = nsw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWSub]. *) +val build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nuw_sub x y name b] creates a + [%name = nuw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWSub]. *) +val build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_fsub x y name b] creates a + [%name = fsub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFSub]. *) +val build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_mul x y name b] creates a + [%name = mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateMul]. *) +val build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nsw_mul x y name b] creates a + [%name = nsw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWMul]. *) +val build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_nuw_mul x y name b] creates a + [%name = nuw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWMul]. *) +val build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_fmul x y name b] creates a + [%name = fmul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFMul]. *) +val build_fmul : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_udiv x y name b] creates a + [%name = udiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUDiv]. *) +val build_udiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_sdiv x y name b] creates a + [%name = sdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSDiv]. *) +val build_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_exact_sdiv x y name b] creates a + [%name = exact sdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExactSDiv]. *) +val build_exact_sdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_fdiv x y name b] creates a + [%name = fdiv %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFDiv]. *) +val build_fdiv : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_urem x y name b] creates a + [%name = urem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateURem]. *) +val build_urem : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_SRem x y name b] creates a + [%name = srem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSRem]. *) +val build_srem : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_frem x y name b] creates a + [%name = frem %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFRem]. *) +val build_frem : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_shl x y name b] creates a + [%name = shl %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateShl]. *) +val build_shl : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_lshr x y name b] creates a + [%name = lshr %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateLShr]. *) +val build_lshr : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_ashr x y name b] creates a + [%name = ashr %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAShr]. *) +val build_ashr : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_and x y name b] creates a + [%name = and %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAnd]. *) +val build_and : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_or x y name b] creates a + [%name = or %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateOr]. *) +val build_or : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_xor x y name b] creates a + [%name = xor %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateXor]. *) +val build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue + + +(** [build_neg x name b] creates a + [%name = sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_neg : llvalue -> string -> llbuilder -> llvalue + + +(** [build_nsw_neg x name b] creates a + [%name = nsw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + + +(** [build_nuw_neg x name b] creates a + [%name = nuw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +val build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + + +(** [build_fneg x name b] creates a + [%name = fsub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateFNeg]. *) +val build_fneg : llvalue -> string -> llbuilder -> llvalue + + +(** [build_xor x name b] creates a + [%name = xor %x, -1] + instruction at the position specified by the instruction builder [b]. + [-1] is the correct "all ones" value for the type of [x]. + See the method [llvm::LLVMBuilder::CreateXor]. *) +val build_not : llvalue -> string -> llbuilder -> llvalue + + + +(** {7 Memory} *) + +(** [build_alloca ty name b] creates a + [%name = alloca %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAlloca]. *) +val build_alloca : lltype -> string -> llbuilder -> llvalue + + +(** [build_array_alloca ty n name b] creates a + [%name = alloca %ty, %n] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateAlloca]. *) +val build_array_alloca : lltype -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_load v name b] creates a + [%name = load %v] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateLoad]. *) +val build_load : llvalue -> string -> llbuilder -> llvalue + + +(** [build_store v p b] creates a + [store %v, %p] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateStore]. *) +val build_store : llvalue -> llvalue -> llbuilder -> llvalue + + +(** [build_gep p indices name b] creates a + [%name = getelementptr %p, indices...] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateGetElementPtr]. *) +val build_gep : llvalue -> llvalue array -> string -> llbuilder -> llvalue + + +(** [build_in_bounds_gep p indices name b] creates a + [%name = gelementptr inbounds %p, indices...] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInBoundsGetElementPtr]. *) +val build_in_bounds_gep : llvalue -> llvalue array -> string -> llbuilder -> + llvalue + +(** [build_struct_gep p idx name b] creates a + [%name = getelementptr %p, 0, idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateStructGetElementPtr]. *) +val build_struct_gep : llvalue -> int -> string -> llbuilder -> + llvalue + +(** [build_global_string str name b] creates a series of instructions that adds + a global string at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateGlobalString]. *) +val build_global_string : string -> string -> llbuilder -> llvalue + + +(** [build_global_stringptr str name b] creates a series of instructions that + adds a global string pointer at the position specified by the instruction + builder [b]. + See the method [llvm::LLVMBuilder::CreateGlobalStringPtr]. *) +val build_global_stringptr : string -> string -> llbuilder -> llvalue + + + +(** {7 Casts} *) + +(** [build_trunc v ty name b] creates a + [%name = trunc %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateTrunc]. *) +val build_trunc : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_zext v ty name b] creates a + [%name = zext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExt]. *) +val build_zext : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_sext v ty name b] creates a + [%name = sext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSExt]. *) +val build_sext : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_fptoui v ty name b] creates a + [%name = fptoui %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPToUI]. *) +val build_fptoui : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_fptosi v ty name b] creates a + [%name = fptosi %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPToSI]. *) +val build_fptosi : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_uitofp v ty name b] creates a + [%name = uitofp %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateUIToFP]. *) +val build_uitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_sitofp v ty name b] creates a + [%name = sitofp %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSIToFP]. *) +val build_sitofp : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_fptrunc v ty name b] creates a + [%name = fptrunc %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPTrunc]. *) +val build_fptrunc : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_fpext v ty name b] creates a + [%name = fpext %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPExt]. *) +val build_fpext : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_ptrtoint v ty name b] creates a + [%name = prtotint %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePtrToInt]. *) +val build_ptrtoint : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_inttoptr v ty name b] creates a + [%name = inttoptr %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIntToPtr]. *) +val build_inttoptr : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_bitcast v ty name b] creates a + [%name = bitcast %p to %ty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateBitCast]. *) +val build_bitcast : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_zext_or_bitcast v ty name b] creates a zext or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExtOrBitCast]. *) +val build_zext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_sext_or_bitcast v ty name b] creates a sext or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSExtOrBitCast]. *) +val build_sext_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_trunc_or_bitcast v ty name b] creates a trunc or bitcast + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateZExtOrBitCast]. *) +val build_trunc_or_bitcast : llvalue -> lltype -> string -> llbuilder -> + llvalue + +(** [build_pointercast v ty name b] creates a bitcast or pointer-to-int + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePointerCast]. *) +val build_pointercast : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_intcast v ty name b] creates a zext, bitcast, or trunc + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIntCast]. *) +val build_intcast : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_fpcast v ty name b] creates a fpext, bitcast, or fptrunc + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFPCast]. *) +val build_fpcast : llvalue -> lltype -> string -> llbuilder -> llvalue + + + +(** {7 Comparisons} *) + +(** [build_icmp pred x y name b] creates a + [%name = icmp %pred %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateICmp]. *) +val build_icmp : Icmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_fcmp pred x y name b] creates a + [%name = fcmp %pred %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateFCmp]. *) +val build_fcmp : Fcmp.t -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + + +(** {7 Miscellaneous instructions} *) + +(** [build_phi incoming name b] creates a + [%name = phi %incoming] + instruction at the position specified by the instruction builder [b]. + [incoming] is a list of [(llvalue, llbasicblock)] tuples. + See the method [llvm::LLVMBuilder::CreatePHI]. *) +val build_phi : (llvalue * llbasicblock) list -> string -> llbuilder -> + llvalue + +(** [build_call fn args name b] creates a + [%name = call %fn(args...)] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateCall]. *) +val build_call : llvalue -> llvalue array -> string -> llbuilder -> llvalue + + +(** [build_select cond thenv elsev name b] creates a + [%name = select %cond, %thenv, %elsev] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateSelect]. *) +val build_select : llvalue -> llvalue -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_va_arg valist argty name b] creates a + [%name = va_arg %valist, %argty] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateVAArg]. *) +val build_va_arg : llvalue -> lltype -> string -> llbuilder -> llvalue + + +(** [build_extractelement vec i name b] creates a + [%name = extractelement %vec, %i] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExtractElement]. *) +val build_extractelement : llvalue -> llvalue -> string -> llbuilder -> + llvalue + +(** [build_insertelement vec elt i name b] creates a + [%name = insertelement %vec, %elt, %i] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInsertElement]. *) +val build_insertelement : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_shufflevector veca vecb mask name b] creates a + [%name = shufflevector %veca, %vecb, %mask] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateShuffleVector]. *) +val build_shufflevector : llvalue -> llvalue -> llvalue -> string -> + llbuilder -> llvalue + +(** [build_insertvalue agg idx name b] creates a + [%name = extractvalue %agg, %idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateExtractValue]. *) +val build_extractvalue : llvalue -> int -> string -> llbuilder -> llvalue + + +(** [build_insertvalue agg val idx name b] creates a + [%name = insertvalue %agg, %val, %idx] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateInsertValue]. *) +val build_insertvalue : llvalue -> llvalue -> int -> string -> llbuilder -> + llvalue + +(** [build_is_null val name b] creates a + [%name = icmp eq %val, null] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIsNull]. *) +val build_is_null : llvalue -> string -> llbuilder -> llvalue + + +(** [build_is_not_null val name b] creates a + [%name = icmp ne %val, null] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateIsNotNull]. *) +val build_is_not_null : llvalue -> string -> llbuilder -> llvalue + + +(** [build_ptrdiff lhs rhs name b] creates a series of instructions that measure + the difference between two pointer values at the position specified by the + instruction builder [b]. + See the method [llvm::LLVMBuilder::CreatePtrDiff]. *) +val build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue + + + +(** {6 Memory buffers} *) + +module MemoryBuffer : sig + (** [of_file p] is the memory buffer containing the contents of the file at + path [p]. If the file could not be read, then [IoError msg] is + raised. *) + val of_file : string -> llmemorybuffer + + (** [stdin ()] is the memory buffer containing the contents of standard input. + If standard input is empty, then [IoError msg] is raised. *) + val of_stdin : unit -> llmemorybuffer + + (** Disposes of a memory buffer. *) + val dispose : llmemorybuffer -> unit +end + + +(** {6 Pass Managers} *) + +module PassManager : sig + (** *) + type 'a t + type any = [ `Module | `Function ] + + (** [PassManager.create ()] constructs a new whole-module pass pipeline. This + type of pipeline is suitable for link-time optimization and whole-module + transformations. + See the constructor of [llvm::PassManager]. *) + val create : unit -> [ `Module ] t + + (** [PassManager.create_function m] constructs a new function-by-function + pass pipeline over the module [m]. It does not take ownership of [m]. + This type of pipeline is suitable for code generation and JIT compilation + tasks. + See the constructor of [llvm::FunctionPassManager]. *) + val create_function : llmodule -> [ `Function ] t + + + (** [run_module m pm] initializes, executes on the module [m], and finalizes + all of the passes scheduled in the pass manager [pm]. Returns [true] if + any of the passes modified the module, [false] otherwise. + See the [llvm::PassManager::run] method. *) + val run_module : llmodule -> [ `Module ] t -> bool + + + (** [initialize fpm] initializes all of the function passes scheduled in the + function pass manager [fpm]. Returns [true] if any of the passes modified + the module, [false] otherwise. + See the [llvm::FunctionPassManager::doInitialization] method. *) + val initialize : [ `Function ] t -> bool + + (** [run_function f fpm] executes all of the function passes scheduled in the + function pass manager [fpm] over the function [f]. Returns [true] if any + of the passes modified [f], [false] otherwise. + See the [llvm::FunctionPassManager::run] method. *) + val run_function : llvalue -> [ `Function ] t -> bool + + + (** [finalize fpm] finalizes all of the function passes scheduled in in the + function pass manager [fpm]. Returns [true] if any of the passes + modified the module, [false] otherwise. + See the [llvm::FunctionPassManager::doFinalization] method. *) + val finalize : [ `Function ] t -> bool + + (** Frees the memory of a pass pipeline. For function pipelines, does not free + the module. + See the destructor of [llvm::BasePassManager]. *) + val dispose : [< any ] t -> unit +end diff --git a/final/bindings/ocaml/llvm/llvm_ocaml.c b/final/bindings/ocaml/llvm/llvm_ocaml.c new file mode 100644 index 00000000000..ce6cf8ea79e --- /dev/null +++ b/final/bindings/ocaml/llvm/llvm_ocaml.c @@ -0,0 +1,1829 @@ +/*===-- llvm_ocaml.c - LLVM Ocaml Glue --------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Core.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/memory.h" +#include "caml/fail.h" +#include "caml/callback.h" +#include "llvm/Config/config.h" +#include +#include + + +/* Can't use the recommended caml_named_value mechanism for backwards + compatibility reasons. This is largely equivalent. */ +static value llvm_ioerror_exn; + +CAMLprim value llvm_register_core_exns(value IoError) { + llvm_ioerror_exn = Field(IoError, 0); + register_global_root(&llvm_ioerror_exn); + return Val_unit; +} + +static void llvm_raise(value Prototype, char *Message) { + CAMLparam1(Prototype); + CAMLlocal1(CamlMessage); + + CamlMessage = copy_string(Message); + LLVMDisposeMessage(Message); + + raise_with_arg(Prototype, CamlMessage); + abort(); /* NOTREACHED */ +#ifdef CAMLnoreturn + CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ +#endif +} + +static value alloc_variant(int tag, void *Value) { + value Iter = alloc_small(1, tag); + Field(Iter, 0) = Val_op(Value); + return Iter; +} + +/* Macro to convert the C first/next/last/prev idiom to the Ocaml llpos/ + llrev_pos idiom. */ +#define DEFINE_ITERATORS(camlname, cname, pty, cty, pfun) \ + /* llmodule -> ('a, 'b) llpos */ \ + CAMLprim value llvm_##camlname##_begin(pty Mom) { \ + cty First = LLVMGetFirst##cname(Mom); \ + if (First) \ + return alloc_variant(1, First); \ + return alloc_variant(0, Mom); \ + } \ + \ + /* llvalue -> ('a, 'b) llpos */ \ + CAMLprim value llvm_##camlname##_succ(cty Kid) { \ + cty Next = LLVMGetNext##cname(Kid); \ + if (Next) \ + return alloc_variant(1, Next); \ + return alloc_variant(0, pfun(Kid)); \ + } \ + \ + /* llmodule -> ('a, 'b) llrev_pos */ \ + CAMLprim value llvm_##camlname##_end(pty Mom) { \ + cty Last = LLVMGetLast##cname(Mom); \ + if (Last) \ + return alloc_variant(1, Last); \ + return alloc_variant(0, Mom); \ + } \ + \ + /* llvalue -> ('a, 'b) llrev_pos */ \ + CAMLprim value llvm_##camlname##_pred(cty Kid) { \ + cty Prev = LLVMGetPrevious##cname(Kid); \ + if (Prev) \ + return alloc_variant(1, Prev); \ + return alloc_variant(0, pfun(Kid)); \ + } + + +/*===-- Contexts ----------------------------------------------------------===*/ + +/* unit -> llcontext */ +CAMLprim LLVMContextRef llvm_create_context(value Unit) { + return LLVMContextCreate(); +} + +/* llcontext -> unit */ +CAMLprim value llvm_dispose_context(LLVMContextRef C) { + LLVMContextDispose(C); + return Val_unit; +} + +/* unit -> llcontext */ +CAMLprim LLVMContextRef llvm_global_context(value Unit) { + return LLVMGetGlobalContext(); +} + +/* llcontext -> string -> int */ +CAMLprim value llvm_mdkind_id(LLVMContextRef C, value Name) { + unsigned MDKindID = LLVMGetMDKindIDInContext(C, String_val(Name), + caml_string_length(Name)); + return Val_int(MDKindID); +} + +/*===-- Modules -----------------------------------------------------------===*/ + +/* llcontext -> string -> llmodule */ +CAMLprim LLVMModuleRef llvm_create_module(LLVMContextRef C, value ModuleID) { + return LLVMModuleCreateWithNameInContext(String_val(ModuleID), C); +} + +/* llmodule -> unit */ +CAMLprim value llvm_dispose_module(LLVMModuleRef M) { + LLVMDisposeModule(M); + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_target_triple(LLVMModuleRef M) { + return copy_string(LLVMGetTarget(M)); +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_set_target_triple(value Trip, LLVMModuleRef M) { + LLVMSetTarget(M, String_val(Trip)); + return Val_unit; +} + +/* llmodule -> string */ +CAMLprim value llvm_data_layout(LLVMModuleRef M) { + return copy_string(LLVMGetDataLayout(M)); +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_set_data_layout(value Layout, LLVMModuleRef M) { + LLVMSetDataLayout(M, String_val(Layout)); + return Val_unit; +} + +/* string -> lltype -> llmodule -> bool */ +CAMLprim value llvm_add_type_name(value Name, LLVMTypeRef Ty, LLVMModuleRef M) { + int res = LLVMAddTypeName(M, String_val(Name), Ty); + return Val_bool(res == 0); +} + +/* string -> llmodule -> unit */ +CAMLprim value llvm_delete_type_name(value Name, LLVMModuleRef M) { + LLVMDeleteTypeName(M, String_val(Name)); + return Val_unit; +} + +/* llmodule -> string -> lltype option */ +CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name) { + CAMLparam1(Name); + LLVMTypeRef T; + if ((T = LLVMGetTypeByName(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) T; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llmodule -> unit */ +CAMLprim value llvm_dump_module(LLVMModuleRef M) { + LLVMDumpModule(M); + return Val_unit; +} + +/* llmodule -> string -> unit */ +CAMLprim value llvm_set_module_inline_asm(LLVMModuleRef M, value Asm) { + LLVMSetModuleInlineAsm(M, String_val(Asm)); + return Val_unit; +} + +/*===-- Types -------------------------------------------------------------===*/ + +/* lltype -> TypeKind.t */ +CAMLprim value llvm_classify_type(LLVMTypeRef Ty) { + return Val_int(LLVMGetTypeKind(Ty)); +} + +/* lltype -> llcontext */ +CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) { + return LLVMGetTypeContext(Ty); +} + +/*--... Operations on integer types ........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i1_type (LLVMContextRef Context) { + return LLVMInt1TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i8_type (LLVMContextRef Context) { + return LLVMInt8TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i16_type (LLVMContextRef Context) { + return LLVMInt16TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i32_type (LLVMContextRef Context) { + return LLVMInt32TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_i64_type (LLVMContextRef Context) { + return LLVMInt64TypeInContext(Context); +} + +/* llcontext -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_integer_type(LLVMContextRef Context, value Width) { + return LLVMIntTypeInContext(Context, Int_val(Width)); +} + +/* lltype -> int */ +CAMLprim value llvm_integer_bitwidth(LLVMTypeRef IntegerTy) { + return Val_int(LLVMGetIntTypeWidth(IntegerTy)); +} + +/*--... Operations on real types ...........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_float_type(LLVMContextRef Context) { + return LLVMFloatTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_double_type(LLVMContextRef Context) { + return LLVMDoubleTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_x86fp80_type(LLVMContextRef Context) { + return LLVMX86FP80TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_fp128_type(LLVMContextRef Context) { + return LLVMFP128TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_ppc_fp128_type(LLVMContextRef Context) { + return LLVMPPCFP128TypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_x86mmx_type(LLVMContextRef Context) { + return LLVMX86MMXTypeInContext(Context); +} + +/*--... Operations on function types .......................................--*/ + +/* lltype -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_function_type(LLVMTypeRef RetTy, value ParamTys) { + return LLVMFunctionType(RetTy, (LLVMTypeRef *) ParamTys, + Wosize_val(ParamTys), 0); +} + +/* lltype -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_var_arg_function_type(LLVMTypeRef RetTy, + value ParamTys) { + return LLVMFunctionType(RetTy, (LLVMTypeRef *) ParamTys, + Wosize_val(ParamTys), 1); +} + +/* lltype -> bool */ +CAMLprim value llvm_is_var_arg(LLVMTypeRef FunTy) { + return Val_bool(LLVMIsFunctionVarArg(FunTy)); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_param_types(LLVMTypeRef FunTy) { + value Tys = alloc(LLVMCountParamTypes(FunTy), 0); + LLVMGetParamTypes(FunTy, (LLVMTypeRef *) Tys); + return Tys; +} + +/*--... Operations on struct types .........................................--*/ + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_struct_type(LLVMContextRef C, value ElementTypes) { + return LLVMStructTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes), 0); +} + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C, + value ElementTypes) { + return LLVMStructTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes), 1); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) { + value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0); + LLVMGetStructElementTypes(StructTy, (LLVMTypeRef *) Tys); + return Tys; +} + +/* lltype -> bool */ +CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) { + return Val_bool(LLVMIsPackedStruct(StructTy)); +} + +/*--... Operations on array, pointer, and vector types .....................--*/ + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_array_type(LLVMTypeRef ElementTy, value Count) { + return LLVMArrayType(ElementTy, Int_val(Count)); +} + +/* lltype -> lltype */ +CAMLprim LLVMTypeRef llvm_pointer_type(LLVMTypeRef ElementTy) { + return LLVMPointerType(ElementTy, 0); +} + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_qualified_pointer_type(LLVMTypeRef ElementTy, + value AddressSpace) { + return LLVMPointerType(ElementTy, Int_val(AddressSpace)); +} + +/* lltype -> int -> lltype */ +CAMLprim LLVMTypeRef llvm_vector_type(LLVMTypeRef ElementTy, value Count) { + return LLVMVectorType(ElementTy, Int_val(Count)); +} + +/* lltype -> int */ +CAMLprim value llvm_array_length(LLVMTypeRef ArrayTy) { + return Val_int(LLVMGetArrayLength(ArrayTy)); +} + +/* lltype -> int */ +CAMLprim value llvm_address_space(LLVMTypeRef PtrTy) { + return Val_int(LLVMGetPointerAddressSpace(PtrTy)); +} + +/* lltype -> int */ +CAMLprim value llvm_vector_size(LLVMTypeRef VectorTy) { + return Val_int(LLVMGetVectorSize(VectorTy)); +} + +/*--... Operations on other types ..........................................--*/ + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_void_type (LLVMContextRef Context) { + return LLVMVoidTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_label_type(LLVMContextRef Context) { + return LLVMLabelTypeInContext(Context); +} + +/* llcontext -> lltype */ +CAMLprim LLVMTypeRef llvm_opaque_type(LLVMContextRef Context) { + return LLVMOpaqueTypeInContext(Context); +} + +/*--... Operations on type handles .........................................--*/ + +#define Typehandle_val(v) (*(LLVMTypeHandleRef *)(Data_custom_val(v))) + +static void llvm_finalize_handle(value TH) { + LLVMDisposeTypeHandle(Typehandle_val(TH)); +} + +static struct custom_operations typehandle_ops = { + (char *) "LLVMTypeHandle", + llvm_finalize_handle, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +}; + +CAMLprim value llvm_handle_to_type(LLVMTypeRef PATy) { + value TH = alloc_custom(&typehandle_ops, sizeof(LLVMBuilderRef), 0, 1); + Typehandle_val(TH) = LLVMCreateTypeHandle(PATy); + return TH; +} + +CAMLprim LLVMTypeRef llvm_type_of_handle(value TH) { + return LLVMResolveTypeHandle(Typehandle_val(TH)); +} + +CAMLprim value llvm_refine_type(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy){ + LLVMRefineType(AbstractTy, ConcreteTy); + return Val_unit; +} + + +/*===-- VALUES ------------------------------------------------------------===*/ + +/* llvalue -> lltype */ +CAMLprim LLVMTypeRef llvm_type_of(LLVMValueRef Val) { + return LLVMTypeOf(Val); +} + +/* llvalue -> string */ +CAMLprim value llvm_value_name(LLVMValueRef Val) { + return copy_string(LLVMGetValueName(Val)); +} + +/* string -> llvalue -> unit */ +CAMLprim value llvm_set_value_name(value Name, LLVMValueRef Val) { + LLVMSetValueName(Val, String_val(Name)); + return Val_unit; +} + +/* llvalue -> unit */ +CAMLprim value llvm_dump_value(LLVMValueRef Val) { + LLVMDumpValue(Val); + return Val_unit; +} + +/*--... Operations on users ................................................--*/ + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_operand(LLVMValueRef V, value I) { + return LLVMGetOperand(V, Int_val(I)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) { + LLVMSetOperand(U, Int_val(I), V); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_num_operands(LLVMValueRef V) { + return Val_int(LLVMGetNumOperands(V)); +} + +/*--... Operations on constants of (mostly) any type .......................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_constant(LLVMValueRef Val) { + return Val_bool(LLVMIsConstant(Val)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_null(LLVMValueRef Val) { + return Val_bool(LLVMIsNull(Val)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_undef(LLVMValueRef Val) { + return Val_bool(LLVMIsUndef(Val)); +} + +/*--... Operations on instructions .........................................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_has_metadata(LLVMValueRef Val) { + return Val_bool(LLVMHasMetadata(Val)); +} + +/* llvalue -> int -> llvalue option */ +CAMLprim value llvm_metadata(LLVMValueRef Val, value MDKindID) { + CAMLparam1(MDKindID); + LLVMValueRef MD; + if ((MD = LLVMGetMetadata(Val, Int_val(MDKindID)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) MD; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_metadata(LLVMValueRef Val, value MDKindID, + LLVMValueRef MD) { + LLVMSetMetadata(Val, Int_val(MDKindID), MD); + return Val_unit; +} + +/* llvalue -> int -> unit */ +CAMLprim value llvm_clear_metadata(LLVMValueRef Val, value MDKindID) { + LLVMSetMetadata(Val, Int_val(MDKindID), NULL); + return Val_unit; +} + + +/*--... Operations on metadata .............................................--*/ + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_mdstring(LLVMContextRef C, value S) { + return LLVMMDStringInContext(C, String_val(S), caml_string_length(S)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) { + return LLVMMDNodeInContext(C, (LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/*--... Operations on scalar constants .....................................--*/ + +/* lltype -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) { + return LLVMConstInt(IntTy, (long long) Int_val(N), 1); +} + +/* lltype -> Int64.t -> bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N, + value SExt) { + return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt)); +} + +/* lltype -> string -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S, + value Radix) { + return LLVMConstIntOfStringAndSize(IntTy, String_val(S), caml_string_length(S), + Int_val(Radix)); +} + +/* lltype -> float -> llvalue */ +CAMLprim LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) { + return LLVMConstReal(RealTy, Double_val(N)); +} + +/* lltype -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) { + return LLVMConstRealOfStringAndSize(RealTy, String_val(S), + caml_string_length(S)); +} + +/*--... Operations on composite constants ..................................--*/ + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_string(LLVMContextRef Context, value Str, + value NullTerminate) { + return LLVMConstStringInContext(Context, String_val(Str), string_length(Str), + 1); +} + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_const_stringz(LLVMContextRef Context, value Str, + value NullTerminate) { + return LLVMConstStringInContext(Context, String_val(Str), string_length(Str), + 0); +} + +/* lltype -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_array(LLVMTypeRef ElementTy, + value ElementVals) { + return LLVMConstArray(ElementTy, (LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_struct(LLVMContextRef C, value ElementVals) { + return LLVMConstStructInContext(C, (LLVMValueRef *) Op_val(ElementVals), + Wosize_val(ElementVals), 0); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_packed_struct(LLVMContextRef C, + value ElementVals) { + return LLVMConstStructInContext(C, (LLVMValueRef *) Op_val(ElementVals), + Wosize_val(ElementVals), 1); +} + +/* llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_vector(value ElementVals) { + return LLVMConstVector((LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + +/*--... Constant expressions ...............................................--*/ + +/* Icmp.t -> llvalue -> llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_const_icmp(value Pred, + LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return LLVMConstICmp(Int_val(Pred) + LLVMIntEQ, LHSConstant, RHSConstant); +} + +/* Fcmp.t -> llvalue -> llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_const_fcmp(value Pred, + LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return LLVMConstFCmp(Int_val(Pred), LHSConstant, RHSConstant); +} + +/* llvalue -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_gep(LLVMValueRef ConstantVal, value Indices) { + return LLVMConstGEP(ConstantVal, (LLVMValueRef*) Op_val(Indices), + Wosize_val(Indices)); +} + +/* llvalue -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_in_bounds_gep(LLVMValueRef ConstantVal, + value Indices) { + return LLVMConstInBoundsGEP(ConstantVal, (LLVMValueRef*) Op_val(Indices), + Wosize_val(Indices)); +} + +/* llvalue -> int array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_extractvalue(LLVMValueRef Aggregate, + value Indices) { + CAMLparam1(Indices); + int size = Wosize_val(Indices); + int i; + LLVMValueRef result; + + unsigned* idxs = (unsigned*)malloc(size * sizeof(unsigned)); + for (i = 0; i < size; i++) { + idxs[i] = Int_val(Field(Indices, i)); + } + + result = LLVMConstExtractValue(Aggregate, idxs, size); + free(idxs); + CAMLreturnT(LLVMValueRef, result); +} + +/* llvalue -> llvalue -> int array -> llvalue */ +CAMLprim LLVMValueRef llvm_const_insertvalue(LLVMValueRef Aggregate, + LLVMValueRef Val, value Indices) { + CAMLparam1(Indices); + int size = Wosize_val(Indices); + int i; + LLVMValueRef result; + + unsigned* idxs = (unsigned*)malloc(size * sizeof(unsigned)); + for (i = 0; i < size; i++) { + idxs[i] = Int_val(Field(Indices, i)); + } + + result = LLVMConstInsertValue(Aggregate, Val, idxs, size); + free(idxs); + CAMLreturnT(LLVMValueRef, result); +} + +/* lltype -> string -> string -> bool -> bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_inline_asm(LLVMTypeRef Ty, value Asm, + value Constraints, value HasSideEffects, + value IsAlignStack) { + return LLVMConstInlineAsm(Ty, String_val(Asm), String_val(Constraints), + Bool_val(HasSideEffects), Bool_val(IsAlignStack)); +} + +/*--... Operations on global variables, functions, and aliases (globals) ...--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_declaration(LLVMValueRef Global) { + return Val_bool(LLVMIsDeclaration(Global)); +} + +/* llvalue -> Linkage.t */ +CAMLprim value llvm_linkage(LLVMValueRef Global) { + return Val_int(LLVMGetLinkage(Global)); +} + +/* Linkage.t -> llvalue -> unit */ +CAMLprim value llvm_set_linkage(value Linkage, LLVMValueRef Global) { + LLVMSetLinkage(Global, Int_val(Linkage)); + return Val_unit; +} + +/* llvalue -> string */ +CAMLprim value llvm_section(LLVMValueRef Global) { + return copy_string(LLVMGetSection(Global)); +} + +/* string -> llvalue -> unit */ +CAMLprim value llvm_set_section(value Section, LLVMValueRef Global) { + LLVMSetSection(Global, String_val(Section)); + return Val_unit; +} + +/* llvalue -> Visibility.t */ +CAMLprim value llvm_visibility(LLVMValueRef Global) { + return Val_int(LLVMGetVisibility(Global)); +} + +/* Visibility.t -> llvalue -> unit */ +CAMLprim value llvm_set_visibility(value Viz, LLVMValueRef Global) { + LLVMSetVisibility(Global, Int_val(Viz)); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_alignment(LLVMValueRef Global) { + return Val_int(LLVMGetAlignment(Global)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_alignment(value Bytes, LLVMValueRef Global) { + LLVMSetAlignment(Global, Int_val(Bytes)); + return Val_unit; +} + +/*--... Operations on uses .................................................--*/ + +/* llvalue -> lluse option */ +CAMLprim value llvm_use_begin(LLVMValueRef Val) { + CAMLparam0(); + LLVMUseRef First; + if ((First = LLVMGetFirstUse(Val))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) First; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> lluse option */ +CAMLprim value llvm_use_succ(LLVMUseRef U) { + CAMLparam0(); + LLVMUseRef Next; + if ((Next = LLVMGetNextUse(U))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Next; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_user(LLVMUseRef UR) { + return LLVMGetUser(UR); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_used_value(LLVMUseRef UR) { + return LLVMGetUsedValue(UR); +} + +/*--... Operations on global variables .....................................--*/ + +DEFINE_ITERATORS(global, Global, LLVMModuleRef, LLVMValueRef, + LLVMGetGlobalParent) + +/* lltype -> string -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_global(LLVMTypeRef Ty, value Name, + LLVMModuleRef M) { + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(GlobalVar)) != Ty) + return LLVMConstBitCast(GlobalVar, LLVMPointerType(Ty, 0)); + return GlobalVar; + } + return LLVMAddGlobal(M, Ty, String_val(Name)); +} + +/* lltype -> string -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_qualified_global(LLVMTypeRef Ty, value Name, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(GlobalVar)) != Ty) + return LLVMConstBitCast(GlobalVar, + LLVMPointerType(Ty, Int_val(AddressSpace))); + return GlobalVar; + } + return LLVMAddGlobal(M, Ty, String_val(Name)); +} + +/* string -> llmodule -> llvalue option */ +CAMLprim value llvm_lookup_global(value Name, LLVMModuleRef M) { + CAMLparam1(Name); + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) GlobalVar; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* string -> llvalue -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_global(value Name, LLVMValueRef Initializer, + LLVMModuleRef M) { + LLVMValueRef GlobalVar = LLVMAddGlobal(M, LLVMTypeOf(Initializer), + String_val(Name)); + LLVMSetInitializer(GlobalVar, Initializer); + return GlobalVar; +} + +/* string -> llvalue -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_qualified_global(value Name, + LLVMValueRef Initializer, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar = LLVMAddGlobalInAddressSpace(M, + LLVMTypeOf(Initializer), + String_val(Name), + Int_val(AddressSpace)); + LLVMSetInitializer(GlobalVar, Initializer); + return GlobalVar; +} + +/* llvalue -> unit */ +CAMLprim value llvm_delete_global(LLVMValueRef GlobalVar) { + LLVMDeleteGlobal(GlobalVar); + return Val_unit; +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_set_initializer(LLVMValueRef ConstantVal, + LLVMValueRef GlobalVar) { + LLVMSetInitializer(GlobalVar, ConstantVal); + return Val_unit; +} + +/* llvalue -> unit */ +CAMLprim value llvm_remove_initializer(LLVMValueRef GlobalVar) { + LLVMSetInitializer(GlobalVar, NULL); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_thread_local(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsThreadLocal(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_thread_local(value IsThreadLocal, + LLVMValueRef GlobalVar) { + LLVMSetThreadLocal(GlobalVar, Bool_val(IsThreadLocal)); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_global_constant(LLVMValueRef GlobalVar) { + return Val_bool(LLVMIsGlobalConstant(GlobalVar)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_global_constant(value Flag, LLVMValueRef GlobalVar) { + LLVMSetGlobalConstant(GlobalVar, Bool_val(Flag)); + return Val_unit; +} + +/*--... Operations on aliases ..............................................--*/ + +CAMLprim LLVMValueRef llvm_add_alias(LLVMModuleRef M, LLVMTypeRef Ty, + LLVMValueRef Aliasee, value Name) { + return LLVMAddAlias(M, Ty, Aliasee, String_val(Name)); +} + +/*--... Operations on functions ............................................--*/ + +DEFINE_ITERATORS(function, Function, LLVMModuleRef, LLVMValueRef, + LLVMGetGlobalParent) + +/* string -> lltype -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_function(value Name, LLVMTypeRef Ty, + LLVMModuleRef M) { + LLVMValueRef Fn; + if ((Fn = LLVMGetNamedFunction(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(Fn)) != Ty) + return LLVMConstBitCast(Fn, LLVMPointerType(Ty, 0)); + return Fn; + } + return LLVMAddFunction(M, String_val(Name), Ty); +} + +/* string -> llmodule -> llvalue option */ +CAMLprim value llvm_lookup_function(value Name, LLVMModuleRef M) { + CAMLparam1(Name); + LLVMValueRef Fn; + if ((Fn = LLVMGetNamedFunction(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Fn; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* string -> lltype -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_function(value Name, LLVMTypeRef Ty, + LLVMModuleRef M) { + LLVMValueRef Fn = LLVMAddFunction(M, String_val(Name), Ty); + LLVMAppendBasicBlockInContext(LLVMGetTypeContext(Ty), Fn, "entry"); + return Fn; +} + +/* llvalue -> unit */ +CAMLprim value llvm_delete_function(LLVMValueRef Fn) { + LLVMDeleteFunction(Fn); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_intrinsic(LLVMValueRef Fn) { + return Val_bool(LLVMGetIntrinsicID(Fn)); +} + +/* llvalue -> int */ +CAMLprim value llvm_function_call_conv(LLVMValueRef Fn) { + return Val_int(LLVMGetFunctionCallConv(Fn)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_function_call_conv(value Id, LLVMValueRef Fn) { + LLVMSetFunctionCallConv(Fn, Int_val(Id)); + return Val_unit; +} + +/* llvalue -> string option */ +CAMLprim value llvm_gc(LLVMValueRef Fn) { + const char *GC; + CAMLparam0(); + CAMLlocal2(Name, Option); + + if ((GC = LLVMGetGC(Fn))) { + Name = copy_string(GC); + + Option = alloc(1, 0); + Field(Option, 0) = Name; + CAMLreturn(Option); + } else { + CAMLreturn(Val_int(0)); + } +} + +/* string option -> llvalue -> unit */ +CAMLprim value llvm_set_gc(value GC, LLVMValueRef Fn) { + LLVMSetGC(Fn, GC == Val_int(0)? 0 : String_val(Field(GC, 0))); + return Val_unit; +} + +/* llvalue -> Attribute.t -> unit */ +CAMLprim value llvm_add_function_attr(LLVMValueRef Arg, value PA) { + LLVMAddFunctionAttr(Arg, Int_val(PA)); + return Val_unit; +} + +/* llvalue -> Attribute.t -> unit */ +CAMLprim value llvm_remove_function_attr(LLVMValueRef Arg, value PA) { + LLVMRemoveFunctionAttr(Arg, Int_val(PA)); + return Val_unit; +} +/*--... Operations on parameters ...........................................--*/ + +DEFINE_ITERATORS(param, Param, LLVMValueRef, LLVMValueRef, LLVMGetParamParent) + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_param(LLVMValueRef Fn, value Index) { + return LLVMGetParam(Fn, Int_val(Index)); +} + +/* llvalue -> llvalue */ +CAMLprim value llvm_params(LLVMValueRef Fn) { + value Params = alloc(LLVMCountParams(Fn), 0); + LLVMGetParams(Fn, (LLVMValueRef *) Op_val(Params)); + return Params; +} + +/* llvalue -> Attribute.t -> unit */ +CAMLprim value llvm_add_param_attr(LLVMValueRef Arg, value PA) { + LLVMAddAttribute(Arg, Int_val(PA)); + return Val_unit; +} + +/* llvalue -> Attribute.t -> unit */ +CAMLprim value llvm_remove_param_attr(LLVMValueRef Arg, value PA) { + LLVMRemoveAttribute(Arg, Int_val(PA)); + return Val_unit; +} + +/* llvalue -> int -> unit */ +CAMLprim value llvm_set_param_alignment(LLVMValueRef Arg, value align) { + LLVMSetParamAlignment(Arg, Int_val(align)); + return Val_unit; +} + +/*--... Operations on basic blocks .........................................--*/ + +DEFINE_ITERATORS( + block, BasicBlock, LLVMValueRef, LLVMBasicBlockRef, LLVMGetBasicBlockParent) + +/* llvalue -> llbasicblock array */ +CAMLprim value llvm_basic_blocks(LLVMValueRef Fn) { + value MLArray = alloc(LLVMCountBasicBlocks(Fn), 0); + LLVMGetBasicBlocks(Fn, (LLVMBasicBlockRef *) Op_val(MLArray)); + return MLArray; +} + +/* llbasicblock -> unit */ +CAMLprim value llvm_delete_block(LLVMBasicBlockRef BB) { + LLVMDeleteBasicBlock(BB); + return Val_unit; +} + +/* string -> llvalue -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_append_block(LLVMContextRef Context, value Name, + LLVMValueRef Fn) { + return LLVMAppendBasicBlockInContext(Context, Fn, String_val(Name)); +} + +/* string -> llbasicblock -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_insert_block(LLVMContextRef Context, value Name, + LLVMBasicBlockRef BB) { + return LLVMInsertBasicBlockInContext(Context, BB, String_val(Name)); +} + +/* llvalue -> bool */ +CAMLprim value llvm_value_is_block(LLVMValueRef Val) { + return Val_bool(LLVMValueIsBasicBlock(Val)); +} + +/*--... Operations on instructions .........................................--*/ + +DEFINE_ITERATORS(instr, Instruction, LLVMBasicBlockRef, LLVMValueRef, + LLVMGetInstructionParent) + + +/*--... Operations on call sites ...........................................--*/ + +/* llvalue -> int */ +CAMLprim value llvm_instruction_call_conv(LLVMValueRef Inst) { + return Val_int(LLVMGetInstructionCallConv(Inst)); +} + +/* int -> llvalue -> unit */ +CAMLprim value llvm_set_instruction_call_conv(value CC, LLVMValueRef Inst) { + LLVMSetInstructionCallConv(Inst, Int_val(CC)); + return Val_unit; +} + +/* llvalue -> int -> Attribute.t -> unit */ +CAMLprim value llvm_add_instruction_param_attr(LLVMValueRef Instr, + value index, + value PA) { + LLVMAddInstrAttribute(Instr, Int_val(index), Int_val(PA)); + return Val_unit; +} + +/* llvalue -> int -> Attribute.t -> unit */ +CAMLprim value llvm_remove_instruction_param_attr(LLVMValueRef Instr, + value index, + value PA) { + LLVMRemoveInstrAttribute(Instr, Int_val(index), Int_val(PA)); + return Val_unit; +} + +/*--... Operations on call instructions (only) .............................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_is_tail_call(LLVMValueRef CallInst) { + return Val_bool(LLVMIsTailCall(CallInst)); +} + +/* bool -> llvalue -> unit */ +CAMLprim value llvm_set_tail_call(value IsTailCall, + LLVMValueRef CallInst) { + LLVMSetTailCall(CallInst, Bool_val(IsTailCall)); + return Val_unit; +} + +/*--... Operations on phi nodes ............................................--*/ + +/* (llvalue * llbasicblock) -> llvalue -> unit */ +CAMLprim value llvm_add_incoming(value Incoming, LLVMValueRef PhiNode) { + LLVMAddIncoming(PhiNode, + (LLVMValueRef*) &Field(Incoming, 0), + (LLVMBasicBlockRef*) &Field(Incoming, 1), + 1); + return Val_unit; +} + +/* llvalue -> (llvalue * llbasicblock) list */ +CAMLprim value llvm_incoming(LLVMValueRef PhiNode) { + unsigned I; + CAMLparam0(); + CAMLlocal3(Hd, Tl, Tmp); + + /* Build a tuple list of them. */ + Tl = Val_int(0); + for (I = LLVMCountIncoming(PhiNode); I != 0; ) { + Hd = alloc(2, 0); + Store_field(Hd, 0, (value) LLVMGetIncomingValue(PhiNode, --I)); + Store_field(Hd, 1, (value) LLVMGetIncomingBlock(PhiNode, I)); + + Tmp = alloc(2, 0); + Store_field(Tmp, 0, Hd); + Store_field(Tmp, 1, Tl); + Tl = Tmp; + } + + CAMLreturn(Tl); +} + + +/*===-- Instruction builders ----------------------------------------------===*/ + +#define Builder_val(v) (*(LLVMBuilderRef *)(Data_custom_val(v))) + +static void llvm_finalize_builder(value B) { + LLVMDisposeBuilder(Builder_val(B)); +} + +static struct custom_operations builder_ops = { + (char *) "IRBuilder", + llvm_finalize_builder, + custom_compare_default, + custom_hash_default, + custom_serialize_default, + custom_deserialize_default +}; + +static value alloc_builder(LLVMBuilderRef B) { + value V = alloc_custom(&builder_ops, sizeof(LLVMBuilderRef), 0, 1); + Builder_val(V) = B; + return V; +} + +/* llcontext -> llbuilder */ +CAMLprim value llvm_builder(LLVMContextRef C) { + return alloc_builder(LLVMCreateBuilderInContext(C)); +} + +/* (llbasicblock, llvalue) llpos -> llbuilder -> unit */ +CAMLprim value llvm_position_builder(value Pos, value B) { + if (Tag_val(Pos) == 0) { + LLVMBasicBlockRef BB = (LLVMBasicBlockRef) Op_val(Field(Pos, 0)); + LLVMPositionBuilderAtEnd(Builder_val(B), BB); + } else { + LLVMValueRef I = (LLVMValueRef) Op_val(Field(Pos, 0)); + LLVMPositionBuilderBefore(Builder_val(B), I); + } + return Val_unit; +} + +/* llbuilder -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) { + LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B)); + if (!InsertBlock) + raise_not_found(); + return InsertBlock; +} + +/* llvalue -> string -> llbuilder -> unit */ +CAMLprim value llvm_insert_into_builder(LLVMValueRef I, value Name, value B) { + LLVMInsertIntoBuilderWithName(Builder_val(B), I, String_val(Name)); + return Val_unit; +} + +/*--... Metadata ...........................................................--*/ + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_current_debug_location(value B, LLVMValueRef V) { + LLVMSetCurrentDebugLocation(Builder_val(B), V); + return Val_unit; +} + +/* llbuilder -> unit */ +CAMLprim value llvm_clear_current_debug_location(value B) { + LLVMSetCurrentDebugLocation(Builder_val(B), NULL); + return Val_unit; +} + +/* llbuilder -> llvalue option */ +CAMLprim value llvm_current_debug_location(value B) { + CAMLparam0(); + LLVMValueRef L; + if ((L = LLVMGetCurrentDebugLocation(Builder_val(B)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) L; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_inst_debug_location(value B, LLVMValueRef V) { + LLVMSetInstDebugLocation(Builder_val(B), V); + return Val_unit; +} + + +/*--... Terminators ........................................................--*/ + +/* llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ret_void(value B) { + return LLVMBuildRetVoid(Builder_val(B)); +} + +/* llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ret(LLVMValueRef Val, value B) { + return LLVMBuildRet(Builder_val(B), Val); +} + +/* llvalue array -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_aggregate_ret(value RetVals, value B) { + return LLVMBuildAggregateRet(Builder_val(B), (LLVMValueRef *) Op_val(RetVals), + Wosize_val(RetVals)); +} + +/* llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_br(LLVMBasicBlockRef BB, value B) { + return LLVMBuildBr(Builder_val(B), BB); +} + +/* llvalue -> llbasicblock -> llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_cond_br(LLVMValueRef If, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Else, + value B) { + return LLVMBuildCondBr(Builder_val(B), If, Then, Else); +} + +/* llvalue -> llbasicblock -> int -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_switch(LLVMValueRef Of, + LLVMBasicBlockRef Else, + value EstimatedCount, + value B) { + return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount)); +} + +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal, + LLVMBasicBlockRef Dest) { + LLVMAddCase(Switch, OnVal, Dest); + return Val_unit; +} + +/* llvalue -> llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_indirect_br(LLVMValueRef Addr, + value EstimatedDests, + value B) { + return LLVMBuildIndirectBr(Builder_val(B), Addr, EstimatedDests); +} + +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_destination(LLVMValueRef IndirectBr, + LLVMBasicBlockRef Dest) { + LLVMAddDestination(IndirectBr, Dest); + return Val_unit; +} + +/* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> + llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_invoke_nat(LLVMValueRef Fn, value Args, + LLVMBasicBlockRef Then, + LLVMBasicBlockRef Catch, + value Name, value B) { + return LLVMBuildInvoke(Builder_val(B), Fn, (LLVMValueRef *) Op_val(Args), + Wosize_val(Args), Then, Catch, String_val(Name)); +} + +/* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> + llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_invoke_bc(value Args[], int NumArgs) { + return llvm_build_invoke_nat((LLVMValueRef) Args[0], Args[1], + (LLVMBasicBlockRef) Args[2], + (LLVMBasicBlockRef) Args[3], + Args[4], Args[5]); +} + +/* llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_unwind(value B) { + return LLVMBuildUnwind(Builder_val(B)); +} + +/* llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_unreachable(value B) { + return LLVMBuildUnreachable(Builder_val(B)); +} + +/*--... Arithmetic .........................................................--*/ + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fadd(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fsub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fmul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_udiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildUDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_exact_sdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildExactSDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fdiv(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFDiv(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_urem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildURem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_srem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildSRem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_frem(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFRem(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_shl(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildShl(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_lshr(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildLShr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ashr(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAShr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_and(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildAnd(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_or(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildOr(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_xor(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildXor(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNSWNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNUWNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fneg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildFNeg(Builder_val(B), X, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_not(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNot(Builder_val(B), X, String_val(Name)); +} + +/*--... Memory .............................................................--*/ + +/* lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_alloca(LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildAlloca(Builder_val(B), Ty, String_val(Name)); +} + +/* lltype -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_array_alloca(LLVMTypeRef Ty, LLVMValueRef Size, + value Name, value B) { + return LLVMBuildArrayAlloca(Builder_val(B), Ty, Size, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_load(LLVMValueRef Pointer, + value Name, value B) { + return LLVMBuildLoad(Builder_val(B), Pointer, String_val(Name)); +} + +/* llvalue -> llvalue -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_store(LLVMValueRef Value, LLVMValueRef Pointer, + value B) { + return LLVMBuildStore(Builder_val(B), Value, Pointer); +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_gep(LLVMValueRef Pointer, value Indices, + value Name, value B) { + return LLVMBuildGEP(Builder_val(B), Pointer, + (LLVMValueRef *) Op_val(Indices), Wosize_val(Indices), + String_val(Name)); +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_in_bounds_gep(LLVMValueRef Pointer, + value Indices, value Name, + value B) { + return LLVMBuildInBoundsGEP(Builder_val(B), Pointer, + (LLVMValueRef *) Op_val(Indices), + Wosize_val(Indices), String_val(Name)); +} + +/* llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_struct_gep(LLVMValueRef Pointer, + value Index, value Name, + value B) { + return LLVMBuildStructGEP(Builder_val(B), Pointer, + Int_val(Index), String_val(Name)); +} + +/* string -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_global_string(value Str, value Name, value B) { + return LLVMBuildGlobalString(Builder_val(B), String_val(Str), + String_val(Name)); +} + +/* string -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_global_stringptr(value Str, value Name, + value B) { + return LLVMBuildGlobalStringPtr(Builder_val(B), String_val(Str), + String_val(Name)); +} + +/*--... Casts ..............................................................--*/ + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_trunc(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildTrunc(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_zext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildZExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptoui(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPToUI(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptosi(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPToSI(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_uitofp(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildUIToFP(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sitofp(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSIToFP(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fptrunc(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPTrunc(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fpext(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPExt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_prttoint(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildPtrToInt(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_inttoptr(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildIntToPtr(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_zext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildZExtOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_sext_or_bitcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildSExtOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_trunc_or_bitcast(LLVMValueRef X, + LLVMTypeRef Ty, value Name, + value B) { + return LLVMBuildTruncOrBitCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_pointercast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildPointerCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_intcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildIntCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fpcast(LLVMValueRef X, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildFPCast(Builder_val(B), X, Ty, String_val(Name)); +} + +/*--... Comparisons ........................................................--*/ + +/* Icmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_icmp(value Pred, + LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildICmp(Builder_val(B), Int_val(Pred) + LLVMIntEQ, LHS, RHS, + String_val(Name)); +} + +/* Fcmp.t -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fcmp(value Pred, + LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildFCmp(Builder_val(B), Int_val(Pred), LHS, RHS, + String_val(Name)); +} + +/*--... Miscellaneous instructions .........................................--*/ + +/* (llvalue * llbasicblock) list -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { + value Hd, Tl; + LLVMValueRef FirstValue, PhiNode; + + assert(Incoming != Val_int(0) && "Empty list passed to Llvm.build_phi!"); + + Hd = Field(Incoming, 0); + FirstValue = (LLVMValueRef) Field(Hd, 0); + PhiNode = LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue), + String_val(Name)); + + for (Tl = Incoming; Tl != Val_int(0); Tl = Field(Tl, 1)) { + value Hd = Field(Tl, 0); + LLVMAddIncoming(PhiNode, (LLVMValueRef*) &Field(Hd, 0), + (LLVMBasicBlockRef*) &Field(Hd, 1), 1); + } + + return PhiNode; +} + +/* llvalue -> llvalue array -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_call(LLVMValueRef Fn, value Params, + value Name, value B) { + return LLVMBuildCall(Builder_val(B), Fn, (LLVMValueRef *) Op_val(Params), + Wosize_val(Params), String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_select(LLVMValueRef If, + LLVMValueRef Then, LLVMValueRef Else, + value Name, value B) { + return LLVMBuildSelect(Builder_val(B), If, Then, Else, String_val(Name)); +} + +/* llvalue -> lltype -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_va_arg(LLVMValueRef List, LLVMTypeRef Ty, + value Name, value B) { + return LLVMBuildVAArg(Builder_val(B), List, Ty, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_extractelement(LLVMValueRef Vec, + LLVMValueRef Idx, + value Name, value B) { + return LLVMBuildExtractElement(Builder_val(B), Vec, Idx, String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_insertelement(LLVMValueRef Vec, + LLVMValueRef Element, + LLVMValueRef Idx, + value Name, value B) { + return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, + String_val(Name)); +} + +/* llvalue -> llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_shufflevector(LLVMValueRef V1, LLVMValueRef V2, + LLVMValueRef Mask, + value Name, value B) { + return LLVMBuildShuffleVector(Builder_val(B), V1, V2, Mask, String_val(Name)); +} + +/* llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_extractvalue(LLVMValueRef Aggregate, + value Idx, value Name, value B) { + return LLVMBuildExtractValue(Builder_val(B), Aggregate, Int_val(Idx), + String_val(Name)); +} + +/* llvalue -> llvalue -> int -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_insertvalue(LLVMValueRef Aggregate, + LLVMValueRef Val, value Idx, + value Name, value B) { + return LLVMBuildInsertValue(Builder_val(B), Aggregate, Val, Int_val(Idx), + String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_is_null(LLVMValueRef Val, value Name, + value B) { + return LLVMBuildIsNull(Builder_val(B), Val, String_val(Name)); +} + +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_is_not_null(LLVMValueRef Val, value Name, + value B) { + return LLVMBuildIsNotNull(Builder_val(B), Val, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_ptrdiff(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildPtrDiff(Builder_val(B), LHS, RHS, String_val(Name)); +} + + +/*===-- Memory buffers ----------------------------------------------------===*/ + +/* string -> llmemorybuffer + raises IoError msg on error */ +CAMLprim value llvm_memorybuffer_of_file(value Path) { + CAMLparam1(Path); + char *Message; + LLVMMemoryBufferRef MemBuf; + + if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path), + &MemBuf, &Message)) + llvm_raise(llvm_ioerror_exn, Message); + + CAMLreturn((value) MemBuf); +} + +/* unit -> llmemorybuffer + raises IoError msg on error */ +CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) { + char *Message; + LLVMMemoryBufferRef MemBuf; + + if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message)) + llvm_raise(llvm_ioerror_exn, Message); + + return MemBuf; +} + +/* llmemorybuffer -> unit */ +CAMLprim value llvm_memorybuffer_dispose(LLVMMemoryBufferRef MemBuf) { + LLVMDisposeMemoryBuffer(MemBuf); + return Val_unit; +} + +/*===-- Pass Managers -----------------------------------------------------===*/ + +/* unit -> [ `Module ] PassManager.t */ +CAMLprim LLVMPassManagerRef llvm_passmanager_create(value Unit) { + return LLVMCreatePassManager(); +} + +/* llmodule -> [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_run_module(LLVMModuleRef M, + LLVMPassManagerRef PM) { + return Val_bool(LLVMRunPassManager(PM, M)); +} + +/* [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_initialize(LLVMPassManagerRef FPM) { + return Val_bool(LLVMInitializeFunctionPassManager(FPM)); +} + +/* llvalue -> [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_run_function(LLVMValueRef F, + LLVMPassManagerRef FPM) { + return Val_bool(LLVMRunFunctionPassManager(FPM, F)); +} + +/* [ `Function ] PassManager.t -> bool */ +CAMLprim value llvm_passmanager_finalize(LLVMPassManagerRef FPM) { + return Val_bool(LLVMFinalizeFunctionPassManager(FPM)); +} + +/* PassManager.any PassManager.t -> unit */ +CAMLprim value llvm_passmanager_dispose(LLVMPassManagerRef PM) { + LLVMDisposePassManager(PM); + return Val_unit; +} diff --git a/final/bindings/ocaml/target/Makefile b/final/bindings/ocaml/target/Makefile new file mode 100644 index 00000000000..3c48cd8fc20 --- /dev/null +++ b/final/bindings/ocaml/target/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/target/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_target interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +LIBRARYNAME := llvm_target +UsedComponents := target +UsedOcamlInterfaces := llvm + +include ../Makefile.ocaml diff --git a/final/bindings/ocaml/target/llvm_target.ml b/final/bindings/ocaml/target/llvm_target.ml new file mode 100644 index 00000000000..ea5341d5e8b --- /dev/null +++ b/final/bindings/ocaml/target/llvm_target.ml @@ -0,0 +1,44 @@ +(*===-- llvm_target.ml - LLVM Ocaml Interface ------------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +module Endian = struct + type t = + | Big + | Little +end + +module TargetData = struct + type t + + external create : string -> t = "llvm_targetdata_create" + external add : t -> [ unit + = "llvm_targetdata_add" + external as_string : t -> string = "llvm_targetdata_as_string" + external invalidate_struct_layout : t -> Llvm.lltype -> unit + = "llvm_targetdata_invalidate_struct_layout" + external dispose : t -> unit = "llvm_targetdata_dispose" +end + +external byte_order : TargetData.t -> Endian.t = "llvm_byte_order" +external pointer_size : TargetData.t -> int = "llvm_pointer_size" +external intptr_type : TargetData.t -> Llvm.lltype = "LLVMIntPtrType" +external size_in_bits : TargetData.t -> Llvm.lltype -> Int64.t + = "llvm_size_in_bits" +external store_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_store_size" +external abi_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" +external abi_align : TargetData.t -> Llvm.lltype -> int = "llvm_abi_align" +external stack_align : TargetData.t -> Llvm.lltype -> int = "llvm_stack_align" +external preferred_align : TargetData.t -> Llvm.lltype -> int + = "llvm_preferred_align" +external preferred_align_of_global : TargetData.t -> Llvm.llvalue -> int + = "llvm_preferred_align_of_global" +external element_at_offset : TargetData.t -> Llvm.lltype -> Int64.t -> int + = "llvm_element_at_offset" +external offset_of_element : TargetData.t -> Llvm.lltype -> int -> Int64.t + = "llvm_offset_of_element" diff --git a/final/bindings/ocaml/target/llvm_target.mli b/final/bindings/ocaml/target/llvm_target.mli new file mode 100644 index 00000000000..a82e1b684fa --- /dev/null +++ b/final/bindings/ocaml/target/llvm_target.mli @@ -0,0 +1,102 @@ +(*===-- llvm_target.mli - LLVM Ocaml Interface -----------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Target Information. + + This interface provides an ocaml API for LLVM target information, + the classes in the Target library. *) + +module Endian : sig + type t = + | Big + | Little +end + +module TargetData : sig + type t + + (** [TargetData.create rep] parses the target data string representation [rep]. + See the constructor llvm::TargetData::TargetData. *) + external create : string -> t = "llvm_targetdata_create" + + (** [add_target_data td pm] adds the target data [td] to the pass manager [pm]. + Does not take ownership of the target data. + See the method llvm::PassManagerBase::add. *) + external add : t -> [ unit + = "llvm_targetdata_add" + + (** [as_string td] is the string representation of the target data [td]. + See the constructor llvm::TargetData::TargetData. *) + external as_string : t -> string = "llvm_targetdata_as_string" + + (** Struct layouts are speculatively cached. If a TargetDataRef is alive when + types are being refined and removed, this method must be called whenever a + struct type is removed to avoid a dangling pointer in this cache. + See the method llvm::TargetData::InvalidateStructLayoutInfo. *) + external invalidate_struct_layout : t -> Llvm.lltype -> unit + = "llvm_targetdata_invalidate_struct_layout" + + (** Deallocates a TargetData. + See the destructor llvm::TargetData::~TargetData. *) + external dispose : t -> unit = "llvm_targetdata_dispose" +end + +(** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::TargetData::isLittleEndian. *) +external byte_order : TargetData.t -> Endian.t = "llvm_byte_order" + +(** Returns the pointer size in bytes for a target. + See the method llvm::TargetData::getPointerSize. *) +external pointer_size : TargetData.t -> int = "llvm_pointer_size" + +(** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::TargetData::getIntPtrType. *) +external intptr_type : TargetData.t -> Llvm.lltype = "LLVMIntPtrType" + +(** Computes the size of a type in bytes for a target. + See the method llvm::TargetData::getTypeSizeInBits. *) +external size_in_bits : TargetData.t -> Llvm.lltype -> Int64.t + = "llvm_size_in_bits" + +(** Computes the storage size of a type in bytes for a target. + See the method llvm::TargetData::getTypeStoreSize. *) +external store_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_store_size" + +(** Computes the ABI size of a type in bytes for a target. + See the method llvm::TargetData::getTypeAllocSize. *) +external abi_size : TargetData.t -> Llvm.lltype -> Int64.t = "llvm_abi_size" + +(** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external abi_align : TargetData.t -> Llvm.lltype -> int = "llvm_abi_align" + +(** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external stack_align : TargetData.t -> Llvm.lltype -> int = "llvm_stack_align" + +(** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. *) +external preferred_align : TargetData.t -> Llvm.lltype -> int + = "llvm_preferred_align" + +(** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::TargetData::getPreferredAlignment. *) +external preferred_align_of_global : TargetData.t -> Llvm.llvalue -> int + = "llvm_preferred_align_of_global" + +(** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. *) +external element_at_offset : TargetData.t -> Llvm.lltype -> Int64.t -> int + = "llvm_element_at_offset" + +(** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. *) +external offset_of_element : TargetData.t -> Llvm.lltype -> int -> Int64.t + = "llvm_offset_of_element" diff --git a/final/bindings/ocaml/target/target_ocaml.c b/final/bindings/ocaml/target/target_ocaml.c new file mode 100644 index 00000000000..cc20e8187a7 --- /dev/null +++ b/final/bindings/ocaml/target/target_ocaml.c @@ -0,0 +1,109 @@ +/*===-- target_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Target.h" +#include "caml/alloc.h" + +/* string -> TargetData.t */ +CAMLprim LLVMTargetDataRef llvm_targetdata_create(value StringRep) { + return LLVMCreateTargetData(String_val(StringRep)); +} + +/* TargetData.t -> [ unit */ +CAMLprim value llvm_targetdata_add(LLVMTargetDataRef TD, LLVMPassManagerRef PM){ + LLVMAddTargetData(TD, PM); + return Val_unit; +} + +/* TargetData.t -> string */ +CAMLprim value llvm_targetdata_as_string(LLVMTargetDataRef TD) { + char *StringRep = LLVMCopyStringRepOfTargetData(TD); + value Copy = copy_string(StringRep); + LLVMDisposeMessage(StringRep); + return Copy; +} + +/* TargetData.t -> Llvm.lltype -> unit */ +CAMLprim value llvm_targetdata_invalidate_struct_layout(LLVMTargetDataRef TD, + LLVMTypeRef Ty) { + LLVMInvalidateStructLayout(TD, Ty); + return Val_unit; +} + +/* TargetData.t -> unit */ +CAMLprim value llvm_targetdata_dispose(LLVMTargetDataRef TD) { + LLVMDisposeTargetData(TD); + return Val_unit; +} + +/* TargetData.t -> Endian.t */ +CAMLprim value llvm_byte_order(LLVMTargetDataRef TD) { + return Val_int(LLVMByteOrder(TD)); +} + +/* TargetData.t -> int */ +CAMLprim value llvm_pointer_size(LLVMTargetDataRef TD) { + return Val_int(LLVMPointerSize(TD)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_size_in_bits(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMSizeOfTypeInBits(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_store_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMStoreSizeOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t */ +CAMLprim value llvm_abi_size(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return caml_copy_int64(LLVMABISizeOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_abi_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMABIAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_stack_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMCallFrameAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.lltype -> int */ +CAMLprim value llvm_preferred_align(LLVMTargetDataRef TD, LLVMTypeRef Ty) { + return Val_int(LLVMPreferredAlignmentOfType(TD, Ty)); +} + +/* TargetData.t -> Llvm.llvalue -> int */ +CAMLprim value llvm_preferred_align_of_global(LLVMTargetDataRef TD, + LLVMValueRef GlobalVar) { + return Val_int(LLVMPreferredAlignmentOfGlobal(TD, GlobalVar)); +} + +/* TargetData.t -> Llvm.lltype -> Int64.t -> int */ +CAMLprim value llvm_element_at_offset(LLVMTargetDataRef TD, LLVMTypeRef Ty, + value Offset) { + return Val_int(LLVMElementAtOffset(TD, Ty, Int_val(Offset))); +} + +/* TargetData.t -> Llvm.lltype -> int -> Int64.t */ +CAMLprim value llvm_offset_of_element(LLVMTargetDataRef TD, LLVMTypeRef Ty, + value Index) { + return caml_copy_int64(LLVMOffsetOfElement(TD, Ty, Int_val(Index))); +} diff --git a/final/bindings/ocaml/transforms/Makefile b/final/bindings/ocaml/transforms/Makefile new file mode 100644 index 00000000000..95b00c8d74a --- /dev/null +++ b/final/bindings/ocaml/transforms/Makefile @@ -0,0 +1,18 @@ +##===- bindings/ocaml/transforms/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +DIRS = scalar + +ocamldoc: + $(Verb) for i in $(DIRS) ; do \ + $(MAKE) -C $$i ocamldoc; \ + done + +include $(LEVEL)/Makefile.common diff --git a/final/bindings/ocaml/transforms/scalar/Makefile b/final/bindings/ocaml/transforms/scalar/Makefile new file mode 100644 index 00000000000..cbaffa4ea7a --- /dev/null +++ b/final/bindings/ocaml/transforms/scalar/Makefile @@ -0,0 +1,20 @@ +##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_scalar_opts +DONT_BUILD_RELINKED := 1 +UsedComponents := scalaropts +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml new file mode 100644 index 00000000000..276e1182d05 --- /dev/null +++ b/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml @@ -0,0 +1,72 @@ +(*===-- llvm_scalar_opts.ml - LLVM Ocaml Interface -------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external add_constant_propagation : [ unit + = "llvm_add_constant_propagation" +external add_sccp : [ unit + = "llvm_add_sccp" +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" +external add_licm : [ unit + = "llvm_add_licm" +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" +external +add_memory_to_register_promotion : [ unit + = "llvm_add_memory_to_register_promotion" +external +add_memory_to_register_demotion : [ unit + = "llvm_add_memory_to_register_demotion" +external add_reassociation : [ unit + = "llvm_add_reassociation" +external add_jump_threading : [ unit + = "llvm_add_jump_threading" +external add_cfg_simplification : [ unit + = "llvm_add_cfg_simplification" +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" +external add_gvn : [ unit + = "llvm_add_gvn" +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" diff --git a/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli new file mode 100644 index 00000000000..d7162c769e4 --- /dev/null +++ b/final/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli @@ -0,0 +1,118 @@ +(*===-- llvm_scalar_opts.mli - LLVM Ocaml Interface ------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Scalar Transforms. + + This interface provides an ocaml API for LLVM scalar transforms, the + classes in the [LLVMScalarOpts] library. *) + +(** See the [llvm::createConstantPropogationPass] function. *) +external add_constant_propagation : [ unit + = "llvm_add_constant_propagation" + +(** See the [llvm::createSCCPPass] function. *) +external add_sccp : [ unit + = "llvm_add_sccp" + +(** See [llvm::createDeadStoreEliminationPass] function. *) +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" + +(** See The [llvm::createAggressiveDCEPass] function. *) +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" + +(** See the [llvm::createScalarReplAggregatesPass] function. *) +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" + +(** See the [llvm::createIndVarSimplifyPass] function. *) +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" + +(** See the [llvm::createInstructionCombiningPass] function. *) +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" + +(** See the [llvm::createLICMPass] function. *) +external add_licm : [ unit + = "llvm_add_licm" + +(** See the [llvm::createLoopUnswitchPass] function. *) +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" + +(** See the [llvm::createLoopUnrollPass] function. *) +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" + +(** See the [llvm::createLoopRotatePass] function. *) +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" + +(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) +external +add_memory_to_register_promotion : [ unit + = "llvm_add_memory_to_register_promotion" + +(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) +external +add_memory_to_register_demotion : [ unit + = "llvm_add_memory_to_register_demotion" + +(** See the [llvm::createReassociatePass] function. *) +external add_reassociation : [ unit + = "llvm_add_reassociation" + +(** See the [llvm::createJumpThreadingPass] function. *) +external add_jump_threading : [ unit + = "llvm_add_jump_threading" + +(** See the [llvm::createCFGSimplificationPass] function. *) +external add_cfg_simplification : [ unit + = "llvm_add_cfg_simplification" + +(** See the [llvm::createTailCallEliminationPass] function. *) +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" + +(** See the [llvm::createGVNPass] function. *) +external add_gvn : [ unit + = "llvm_add_gvn" + +(** See the [llvm::createMemCpyOptPass] function. *) +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" + +(** See the [llvm::createLoopDeletionPass] function. *) +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" + +(** See the [llvm::createSimplifyLibCallsPass] function. *) +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" diff --git a/final/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/final/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c new file mode 100644 index 00000000000..df44807859c --- /dev/null +++ b/final/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c @@ -0,0 +1,146 @@ +/*===-- scalar_opts_ocaml.c - LLVM Ocaml Glue -------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's ocaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/Scalar.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [ unit */ +CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { + LLVMAddConstantPropagationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { + LLVMAddSCCPPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadStoreEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { + LLVMAddAggressiveDCEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) { + LLVMAddIndVarSimplifyPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_instruction_combination(LLVMPassManagerRef PM) { + LLVMAddInstructionCombiningPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { + LLVMAddLICMPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_rotation(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memory_to_register_promotion(LLVMPassManagerRef PM) { + LLVMAddPromoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memory_to_register_demotion(LLVMPassManagerRef PM) { + LLVMAddDemoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { + LLVMAddReassociatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { + LLVMAddJumpThreadingPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { + LLVMAddTailCallEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { + LLVMAddGVNPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { + LLVMAddMemCpyOptPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { + LLVMAddLoopDeletionPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) { + LLVMAddSimplifyLibCallsPass(PM); + return Val_unit; +} diff --git a/final/build-for-llvm-top.sh b/final/build-for-llvm-top.sh new file mode 100755 index 00000000000..78e3ed87f09 --- /dev/null +++ b/final/build-for-llvm-top.sh @@ -0,0 +1,68 @@ +#!/bin/sh + +# This includes the Bourne shell library from llvm-top. Since this file is +# generally only used when building from llvm-top, it is safe to assume that +# llvm is checked out into llvm-top in which case .. just works. +. ../library.sh + +# Process the options passed in to us by the build script into standard +# variables. +process_arguments "$@" + +# First, see if the build directory is there. If not, create it. +build_dir="$LLVM_TOP/build.llvm" +if test ! -d "$build_dir" ; then + mkdir -p "$build_dir" +fi + +# See if we have previously been configured by sensing the presence +# of the config.status scripts +config_status="$build_dir/config.status" +if test ! -f "$config_status" -o "$config_status" -ot "$0" ; then + # We must configure so build a list of configure options + config_options="--prefix=$PREFIX --with-llvmgccdir=$PREFIX" + if test "$OPTIMIZED" -eq 1 ; then + config_options="$config_options --enable-optimized" + else + config_options="$config_options --disable-optimized" + fi + if test "$DEBUG" -eq 1 ; then + config_options="$config_options --enable-debug" + else + config_options="$config_options --disable-debug" + fi + if test "$ASSERTIONS" -eq 1 ; then + config_options="$config_options --enable-assertions" + else + config_options="$config_options --disable-assertions" + fi + if test "$CHECKING" -eq 1 ; then + config_options="$config_options --enable-expensive-checks" + else + config_options="$config_options --disable-expensive-checks" + fi + if test "$DOXYGEN" -eq 1 ; then + config_options="$config_options --enable-doxygen" + else + config_options="$config_options --disable-doxygen" + fi + if test "$THREADS" -eq 1 ; then + config_options="$config_options --enable-threads" + else + config_options="$config_options --disable-threads" + fi + config_options="$config_options $OPTIONS_DASH $OPTIONS_DASH_DASH" + src_dir=`pwd` + cd "$build_dir" + msg 0 Configuring $module with: + msg 0 " $src_dir/configure" $config_options + $src_dir/configure $config_options || \ + die $? "Configuring $module module failed" +else + msg 0 Module $module already configured, ignoring configure options. + cd "$build_dir" +fi + +msg 0 Building $module with: +msg 0 " make" $OPTIONS_ASSIGN tools-only +make $OPTIONS_ASSIGN tools-only diff --git a/final/cmake/README b/final/cmake/README new file mode 100644 index 00000000000..4aafdbf32a3 --- /dev/null +++ b/final/cmake/README @@ -0,0 +1 @@ +See docs/CMake.html for instructions on how to build LLVM with CMake. diff --git a/final/cmake/config-ix.cmake b/final/cmake/config-ix.cmake new file mode 100755 index 00000000000..e2817f1316b --- /dev/null +++ b/final/cmake/config-ix.cmake @@ -0,0 +1,385 @@ +if( WIN32 AND NOT CYGWIN ) + # We consider Cygwin as another Unix + set(PURE_WINDOWS 1) +endif() + +include(CheckIncludeFile) +include(CheckLibraryExists) +include(CheckSymbolExists) +include(CheckFunctionExists) +include(CheckCXXSourceCompiles) +include(TestBigEndian) + +if( UNIX AND NOT BEOS ) + # Used by check_symbol_exists: + set(CMAKE_REQUIRED_LIBRARIES m) +endif() + +# Helper macros and functions +macro(add_cxx_include result files) + set(${result} "") + foreach (file_name ${files}) + set(${result} "${${result}}#include<${file_name}>\n") + endforeach() +endmacro(add_cxx_include files result) + +function(check_type_exists type files variable) + add_cxx_include(includes "${files}") + CHECK_CXX_SOURCE_COMPILES(" + ${includes} ${type} typeVar; + int main() { + return 0; + } + " ${variable}) +endfunction() + +# include checks +check_include_file(argz.h HAVE_ARGZ_H) +check_include_file(assert.h HAVE_ASSERT_H) +check_include_file(ctype.h HAVE_CTYPE_H) +check_include_file(dirent.h HAVE_DIRENT_H) +check_include_file(dl.h HAVE_DL_H) +check_include_file(dld.h HAVE_DLD_H) +check_include_file(dlfcn.h HAVE_DLFCN_H) +check_include_file(errno.h HAVE_ERRNO_H) +check_include_file(execinfo.h HAVE_EXECINFO_H) +check_include_file(fcntl.h HAVE_FCNTL_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(link.h HAVE_LINK_H) +check_include_file(malloc.h HAVE_MALLOC_H) +check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(ndir.h HAVE_NDIR_H) +if( NOT PURE_WINDOWS ) + check_include_file(pthread.h HAVE_PTHREAD_H) +endif() +check_include_file(setjmp.h HAVE_SETJMP_H) +check_include_file(signal.h HAVE_SIGNAL_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stdio.h HAVE_STDIO_H) +check_include_file(stdlib.h HAVE_STDLIB_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(strings.h HAVE_STRINGS_H) +check_include_file(sys/dir.h HAVE_SYS_DIR_H) +check_include_file(sys/dl.h HAVE_SYS_DL_H) +check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) +check_include_file(sys/mman.h HAVE_SYS_MMAN_H) +check_include_file(sys/ndir.h HAVE_SYS_NDIR_H) +check_include_file(sys/param.h HAVE_SYS_PARAM_H) +check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/time.h HAVE_SYS_TIME_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(sys/uio.h HAVE_SYS_UIO_H) +check_include_file(sys/wait.h HAVE_SYS_WAIT_H) +check_include_file(termios.h HAVE_TERMIOS_H) +check_include_file(unistd.h HAVE_UNISTD_H) +check_include_file(utime.h HAVE_UTIME_H) +check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H) +check_include_file(windows.h HAVE_WINDOWS_H) +check_include_file(fenv.h HAVE_FENV_H) +check_include_file(mach/mach.h HAVE_MACH_MACH_H) +check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H) + +# library checks +if( NOT PURE_WINDOWS ) + check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) + check_library_exists(pthread pthread_getspecific "" HAVE_PTHREAD_GETSPECIFIC) + check_library_exists(pthread pthread_rwlock_init "" HAVE_PTHREAD_RWLOCK_INIT) + check_library_exists(dl dlopen "" HAVE_LIBDL) +endif() + +# function checks +check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE) +check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE) +check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT) +check_function_exists(isatty HAVE_ISATTY) +check_symbol_exists(index strings.h HAVE_INDEX) +check_symbol_exists(isinf cmath HAVE_ISINF_IN_CMATH) +check_symbol_exists(isinf math.h HAVE_ISINF_IN_MATH_H) +check_symbol_exists(finite ieeefp.h HAVE_FINITE_IN_IEEEFP_H) +check_symbol_exists(isnan cmath HAVE_ISNAN_IN_CMATH) +check_symbol_exists(isnan math.h HAVE_ISNAN_IN_MATH_H) +check_symbol_exists(ceilf math.h HAVE_CEILF) +check_symbol_exists(floorf math.h HAVE_FLOORF) +check_symbol_exists(fmodf math.h HAVE_FMODF) +if( HAVE_SETJMP_H ) + check_symbol_exists(longjmp setjmp.h HAVE_LONGJMP) + check_symbol_exists(setjmp setjmp.h HAVE_SETJMP) + check_symbol_exists(siglongjmp setjmp.h HAVE_SIGLONGJMP) + check_symbol_exists(sigsetjmp setjmp.h HAVE_SIGSETJMP) +endif() +if( HAVE_SYS_UIO_H ) + check_symbol_exists(writev sys/uio.h HAVE_WRITEV) +endif() +check_symbol_exists(nearbyintf math.h HAVE_NEARBYINTF) +check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO) +check_symbol_exists(malloc_zone_statistics malloc/malloc.h + HAVE_MALLOC_ZONE_STATISTICS) +check_symbol_exists(mkdtemp "stdlib.h;unistd.h" HAVE_MKDTEMP) +check_symbol_exists(mkstemp "stdlib.h;unistd.h" HAVE_MKSTEMP) +check_symbol_exists(mktemp "stdlib.h;unistd.h" HAVE_MKTEMP) +check_symbol_exists(closedir "sys/types.h;dirent.h" HAVE_CLOSEDIR) +check_symbol_exists(opendir "sys/types.h;dirent.h" HAVE_OPENDIR) +check_symbol_exists(readdir "sys/types.h;dirent.h" HAVE_READDIR) +check_symbol_exists(getcwd unistd.h HAVE_GETCWD) +check_symbol_exists(gettimeofday sys/time.h HAVE_GETTIMEOFDAY) +check_symbol_exists(getrlimit "sys/types.h;sys/time.h;sys/resource.h" HAVE_GETRLIMIT) +check_symbol_exists(rindex strings.h HAVE_RINDEX) +check_symbol_exists(strchr string.h HAVE_STRCHR) +check_symbol_exists(strcmp string.h HAVE_STRCMP) +check_symbol_exists(strdup string.h HAVE_STRDUP) +check_symbol_exists(strrchr string.h HAVE_STRRCHR) +if( NOT PURE_WINDOWS ) + check_symbol_exists(pthread_mutex_lock pthread.h HAVE_PTHREAD_MUTEX_LOCK) +endif() +check_symbol_exists(sbrk unistd.h HAVE_SBRK) +check_symbol_exists(srand48 stdlib.h HAVE_RAND48_SRAND48) +if( HAVE_RAND48_SRAND48 ) + check_symbol_exists(lrand48 stdlib.h HAVE_RAND48_LRAND48) + if( HAVE_RAND48_LRAND48 ) + check_symbol_exists(drand48 stdlib.h HAVE_RAND48_DRAND48) + if( HAVE_RAND48_DRAND48 ) + set(HAVE_RAND48 1 CACHE INTERNAL "are srand48/lrand48/drand48 available?") + endif() + endif() +endif() +check_symbol_exists(strtoll stdlib.h HAVE_STRTOLL) +check_symbol_exists(strtoq stdlib.h HAVE_STRTOQ) +check_symbol_exists(strerror string.h HAVE_STRERROR) +check_symbol_exists(strerror_r string.h HAVE_STRERROR_R) +check_symbol_exists(strerror_s string.h HAVE_DECL_STRERROR_S) +check_symbol_exists(memcpy string.h HAVE_MEMCPY) +check_symbol_exists(memmove string.h HAVE_MEMMOVE) +check_symbol_exists(setenv stdlib.h HAVE_SETENV) +if( PURE_WINDOWS ) + check_symbol_exists(_chsize_s io.h HAVE__CHSIZE_S) + + check_function_exists(_alloca HAVE__ALLOCA) + check_function_exists(__alloca HAVE___ALLOCA) + check_function_exists(__chkstk HAVE___CHKSTK) + check_function_exists(___chkstk HAVE____CHKSTK) + + check_function_exists(__ashldi3 HAVE___ASHLDI3) + check_function_exists(__ashrdi3 HAVE___ASHRDI3) + check_function_exists(__divdi3 HAVE___DIVDI3) + check_function_exists(__fixdfdi HAVE___FIXDFDI) + check_function_exists(__fixsfdi HAVE___FIXSFDI) + check_function_exists(__floatdidf HAVE___FLOATDIDF) + check_function_exists(__lshrdi3 HAVE___LSHRDI3) + check_function_exists(__moddi3 HAVE___MODDI3) + check_function_exists(__udivdi3 HAVE___UDIVDI3) + check_function_exists(__umoddi3 HAVE___UMODDI3) + + check_function_exists(__main HAVE___MAIN) + check_function_exists(__cmpdi2 HAVE___CMPDI2) +endif() +if( HAVE_ARGZ_H ) + check_symbol_exists(argz_append argz.h HAVE_ARGZ_APPEND) + check_symbol_exists(argz_create_sep argz.h HAVE_ARGZ_CREATE_SEP) + check_symbol_exists(argz_insert argz.h HAVE_ARGZ_INSERT) + check_symbol_exists(argz_next argz.h HAVE_ARGZ_NEXT) + check_symbol_exists(argz_stringify argz.h HAVE_ARGZ_STRINGIFY) +endif() +if( HAVE_DLFCN_H ) + if( HAVE_LIBDL ) + list(APPEND CMAKE_REQUIRED_LIBRARIES dl) + endif() + check_symbol_exists(dlerror dlfcn.h HAVE_DLERROR) + check_symbol_exists(dlopen dlfcn.h HAVE_DLOPEN) + if( HAVE_LIBDL ) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES dl) + endif() +endif() + +check_symbol_exists(__GLIBC__ stdio.h LLVM_USING_GLIBC) +if( LLVM_USING_GLIBC ) + add_llvm_definitions( -D_GNU_SOURCE ) +endif() + +# Type checks +check_type_exists(std::bidirectional_iterator "iterator;iostream" HAVE_BI_ITERATOR) +check_type_exists(std::iterator iterator HAVE_STD_ITERATOR) +check_type_exists(std::forward_iterator iterator HAVE_FWD_ITERATOR) + +set(headers "") +if (HAVE_SYS_TYPES_H) + set(headers ${headers} "sys/types.h") +endif() + +if (HAVE_INTTYPES_H) + set(headers ${headers} "inttypes.h") +endif() + +if (HAVE_STDINT_H) + set(headers ${headers} "stdint.h") +endif() + +check_type_exists(int64_t "${headers}" HAVE_INT64_T) +check_type_exists(uint64_t "${headers}" HAVE_UINT64_T) +check_type_exists(u_int64_t "${headers}" HAVE_U_INT64_T) +check_type_exists(error_t errno.h HAVE_ERROR_T) + +# available programs checks +function(llvm_find_program name) + string(TOUPPER ${name} NAME) + string(REGEX REPLACE "\\." "_" NAME ${NAME}) + find_program(LLVM_PATH_${NAME} ${name}) + mark_as_advanced(LLVM_PATH_${NAME}) + if(LLVM_PATH_${NAME}) + set(HAVE_${NAME} 1 CACHE INTERNAL "Is ${name} available ?") + mark_as_advanced(HAVE_${NAME}) + else(LLVM_PATH_${NAME}) + set(HAVE_${NAME} "" CACHE INTERNAL "Is ${name} available ?") + endif(LLVM_PATH_${NAME}) +endfunction() + +llvm_find_program(gv) +llvm_find_program(circo) +llvm_find_program(twopi) +llvm_find_program(neato) +llvm_find_program(fdp) +llvm_find_program(dot) +llvm_find_program(dotty) +llvm_find_program(xdot.py) + +if( LLVM_ENABLE_FFI ) + find_path(FFI_INCLUDE_PATH ffi.h PATHS ${FFI_INCLUDE_DIR}) + if( FFI_INCLUDE_PATH ) + set(FFI_HEADER ffi.h CACHE INTERNAL "") + set(HAVE_FFI_H 1 CACHE INTERNAL "") + else() + find_path(FFI_INCLUDE_PATH ffi/ffi.h PATHS ${FFI_INCLUDE_DIR}) + if( FFI_INCLUDE_PATH ) + set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "") + set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "") + endif() + endif() + + if( NOT FFI_HEADER ) + message(FATAL_ERROR "libffi includes are not found.") + endif() + + find_library(FFI_LIBRARY_PATH ffi PATHS ${FFI_LIBRARY_DIR}) + if( NOT FFI_LIBRARY_PATH ) + message(FATAL_ERROR "libffi is not found.") + endif() + + list(APPEND CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH}) + check_symbol_exists(ffi_call ${FFI_HEADER} HAVE_FFI_CALL) + list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES ${FFI_INCLUDE_PATH}) + list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${FFI_LIBRARY_PATH}) +endif( LLVM_ENABLE_FFI ) + +# Define LLVM_MULTITHREADED if gcc atomic builtins exists. +include(CheckAtomic) + +if( LLVM_ENABLE_PIC ) + set(ENABLE_PIC 1) +else() + set(ENABLE_PIC 0) +endif() + +include(CheckCXXCompilerFlag) + +check_cxx_compiler_flag("-Wno-variadic-macros" SUPPORTS_NO_VARIADIC_MACROS_FLAG) + +include(GetTargetTriple) +get_target_triple(LLVM_HOSTTRIPLE) + +# FIXME: We don't distinguish the target and the host. :( +set(TARGET_TRIPLE "${LLVM_HOSTTRIPLE}") + +# Determine the native architecture. +string(TOLOWER "${LLVM_TARGET_ARCH}" LLVM_NATIVE_ARCH) +if( LLVM_NATIVE_ARCH STREQUAL "host" ) + string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOSTTRIPLE}) +endif () + +if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "amd64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH STREQUAL "x86_64") + set(LLVM_NATIVE_ARCH X86) +elseif (LLVM_NATIVE_ARCH MATCHES "sparc") + set(LLVM_NATIVE_ARCH Sparc) +elseif (LLVM_NATIVE_ARCH MATCHES "powerpc") + set(LLVM_NATIVE_ARCH PowerPC) +elseif (LLVM_NATIVE_ARCH MATCHES "alpha") + set(LLVM_NATIVE_ARCH Alpha) +elseif (LLVM_NATIVE_ARCH MATCHES "arm") + set(LLVM_NATIVE_ARCH ARM) +elseif (LLVM_NATIVE_ARCH MATCHES "mips") + set(LLVM_NATIVE_ARCH Mips) +elseif (LLVM_NATIVE_ARCH MATCHES "xcore") + set(LLVM_NATIVE_ARCH XCore) +elseif (LLVM_NATIVE_ARCH MATCHES "msp430") + set(LLVM_NATIVE_ARCH MSP430) +else () + message(STATUS + "Unknown architecture ${LLVM_NATIVE_ARCH}; lli will not JIT code") + set(LLVM_NATIVE_ARCH) +endif () + +if (LLVM_NATIVE_ARCH) + list(FIND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH} NATIVE_ARCH_IDX) + if (NATIVE_ARCH_IDX EQUAL -1) + message(STATUS + "Native target ${LLVM_NATIVE_ARCH} is not selected; lli will not JIT code") + set(LLVM_NATIVE_ARCH) + else () + message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}") + set(LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target) + set(LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo) + set(LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter) + endif () +endif() + +if( MINGW ) + set(HAVE_LIBIMAGEHLP 1) + set(HAVE_LIBPSAPI 1) + # TODO: Check existence of libraries. + # include(CheckLibraryExists) + # CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP) +endif( MINGW ) + +if( MSVC ) + set(error_t int) + set(mode_t "unsigned short") + set(LTDL_SHLIBPATH_VAR "PATH") + set(LTDL_SYSSEARCHPATH "") + set(LTDL_DLOPEN_DEPLIBS 1) + set(SHLIBEXT ".lib") + set(LTDL_OBJDIR "_libs") + set(HAVE_STRTOLL 1) + set(strtoll "_strtoi64") + set(strtoull "_strtoui64") + set(stricmp "_stricmp") + set(strdup "_strdup") +else( MSVC ) + set(LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH") + set(LTDL_SYSSEARCHPATH "") # TODO + set(LTDL_DLOPEN_DEPLIBS 0) # TODO +endif( MSVC ) + +# FIXME: Signal handler return type, currently hardcoded to 'void' +set(RETSIGTYPE void) + +if( LLVM_ENABLE_THREADS ) + if( HAVE_PTHREAD_H OR WIN32 ) + set(ENABLE_THREADS 1) + endif() +endif() + +if( ENABLE_THREADS ) + message(STATUS "Threads enabled.") +else( ENABLE_THREADS ) + message(STATUS "Threads disabled.") +endif() + +set(LLVM_PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/final/cmake/modules/AddLLVM.cmake b/final/cmake/modules/AddLLVM.cmake new file mode 100755 index 00000000000..764c6591c45 --- /dev/null +++ b/final/cmake/modules/AddLLVM.cmake @@ -0,0 +1,136 @@ +include(LLVMProcessSources) +include(LLVMConfig) + +macro(add_llvm_library name) + llvm_process_sources( ALL_FILES ${ARGN} ) + add_library( ${name} ${ALL_FILES} ) + set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} ) + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) + + if( BUILD_SHARED_LIBS ) + get_system_libs(sl) + target_link_libraries( ${name} ${sl} ) + endif() + + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + # The LLVM Target library shall be built before its sublibraries + # (asmprinter, etc) because those may use tablegenned files which + # generation is triggered by the main LLVM target library. Necessary + # for parallel builds: + if( CURRENT_LLVM_TARGET ) + add_dependencies(${name} ${CURRENT_LLVM_TARGET}) + endif() + set_target_properties(${name} PROPERTIES FOLDER "Libraries") +endmacro(add_llvm_library name) + + +macro(add_llvm_loadable_module name) + if( NOT LLVM_ON_UNIX OR CYGWIN ) + message(STATUS "Loadable modules not supported on this platform. +${name} ignored.") + # Add empty "phony" target + add_custom_target(${name}) + else() + llvm_process_sources( ALL_FILES ${ARGN} ) + if (MODULE) + set(libkind MODULE) + else() + set(libkind SHARED) + endif() + + add_library( ${name} ${libkind} ${ALL_FILES} ) + set_target_properties( ${name} PROPERTIES PREFIX "" ) + + if (APPLE) + # Darwin-specific linker flags for loadable modules. + set_target_properties(${name} PROPERTIES + LINK_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress") + endif() + + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + endif() + + set_target_properties(${name} PROPERTIES FOLDER "Loadable modules") +endmacro(add_llvm_loadable_module name) + + +macro(add_llvm_executable name) + llvm_process_sources( ALL_FILES ${ARGN} ) + if( EXCLUDE_FROM_ALL ) + add_executable(${name} EXCLUDE_FROM_ALL ${ALL_FILES}) + else() + add_executable(${name} ${ALL_FILES}) + endif() + set(EXCLUDE_FROM_ALL OFF) + if( LLVM_USED_LIBS ) + foreach(lib ${LLVM_USED_LIBS}) + target_link_libraries( ${name} ${lib} ) + endforeach(lib) + endif( LLVM_USED_LIBS ) + if( LLVM_LINK_COMPONENTS ) + llvm_config(${name} ${LLVM_LINK_COMPONENTS}) + endif( LLVM_LINK_COMPONENTS ) + if( LLVM_COMMON_DEPENDS ) + add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} ) + endif( LLVM_COMMON_DEPENDS ) + if( NOT MINGW ) + get_system_libs(llvm_system_libs) + if( llvm_system_libs ) + target_link_libraries(${name} ${llvm_system_libs}) + endif() + endif() +endmacro(add_llvm_executable name) + + +macro(add_llvm_tool name) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) + if( NOT LLVM_BUILD_TOOLS ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + if( LLVM_BUILD_TOOLS ) + install(TARGETS ${name} RUNTIME DESTINATION bin) + endif() + set_target_properties(${name} PROPERTIES FOLDER "Tools") +endmacro(add_llvm_tool name) + + +macro(add_llvm_example name) +# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_EXAMPLES_BINARY_DIR}) + if( NOT LLVM_BUILD_EXAMPLES ) + set(EXCLUDE_FROM_ALL ON) + endif() + add_llvm_executable(${name} ${ARGN}) + if( LLVM_BUILD_EXAMPLES ) + install(TARGETS ${name} RUNTIME DESTINATION examples) + endif() + set_target_properties(${name} PROPERTIES FOLDER "Examples") +endmacro(add_llvm_example name) + + +macro(add_llvm_utility name) + add_llvm_executable(${name} ${ARGN}) + set_target_properties(${name} PROPERTIES FOLDER "Utils") +endmacro(add_llvm_utility name) + + +macro(add_llvm_target target_name) + if( TABLEGEN_OUTPUT ) + add_custom_target(${target_name}Table_gen + DEPENDS ${TABLEGEN_OUTPUT}) + add_dependencies(${target_name}Table_gen ${LLVM_COMMON_DEPENDS}) + endif( TABLEGEN_OUTPUT ) + include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) + add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT}) + if ( TABLEGEN_OUTPUT ) + add_dependencies(LLVM${target_name} ${target_name}Table_gen) + set_target_properties(${target_name}Table_gen PROPERTIES FOLDER "Tablegenning") + endif (TABLEGEN_OUTPUT) + set( CURRENT_LLVM_TARGET LLVM${target_name} ) +endmacro(add_llvm_target) diff --git a/final/cmake/modules/AddLLVMDefinitions.cmake b/final/cmake/modules/AddLLVMDefinitions.cmake new file mode 100644 index 00000000000..33ac9731db5 --- /dev/null +++ b/final/cmake/modules/AddLLVMDefinitions.cmake @@ -0,0 +1,13 @@ +# There is no clear way of keeping track of compiler command-line +# options chosen via `add_definitions', so we need our own method for +# using it on tools/llvm-config/CMakeLists.txt. + +# Beware that there is no implementation of remove_llvm_definitions. + +macro(add_llvm_definitions) + # We don't want no semicolons on LLVM_DEFINITIONS: + foreach(arg ${ARGN}) + set(LLVM_DEFINITIONS "${LLVM_DEFINITIONS} ${arg}") + endforeach(arg) + add_definitions( ${ARGN} ) +endmacro(add_llvm_definitions) diff --git a/final/cmake/modules/CMakeLists.txt b/final/cmake/modules/CMakeLists.txt new file mode 100644 index 00000000000..1ab94749f15 --- /dev/null +++ b/final/cmake/modules/CMakeLists.txt @@ -0,0 +1,32 @@ +set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/share/llvm/cmake") + +get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) + +configure_file( + LLVM.cmake + ${llvm_cmake_builddir}/LLVM.cmake + @ONLY) + +install(FILES + ${llvm_cmake_builddir}/LLVM.cmake + LLVMConfig.cmake + LLVMLibDeps.cmake + DESTINATION share/llvm/cmake) + +install(DIRECTORY . + DESTINATION share/llvm/cmake + FILES_MATCHING PATTERN *.cmake + PATTERN .svn EXCLUDE + PATTERN LLVM.cmake EXCLUDE + PATTERN LLVMConfig.cmake EXCLUDE + PATTERN LLVMLibDeps.cmake EXCLUDE + PATTERN FindBison.cmake EXCLUDE + PATTERN GetTargetTriple.cmake EXCLUDE + PATTERN VersionFromVCS.cmake EXCLUDE + PATTERN CheckAtomic.cmake EXCLUDE) + +install(FILES + ${llvm_cmake_builddir}/LLVM.cmake + LLVMConfig.cmake + LLVMLibDeps.cmake + DESTINATION share/llvm/cmake) diff --git a/final/cmake/modules/CheckAtomic.cmake b/final/cmake/modules/CheckAtomic.cmake new file mode 100644 index 00000000000..f40ff4dfbd3 --- /dev/null +++ b/final/cmake/modules/CheckAtomic.cmake @@ -0,0 +1,29 @@ +# atomic builtins are required for threading support. + +INCLUDE(CheckCXXSourceCompiles) + +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER +#include +#endif +int main() { +#ifdef _MSC_VER + volatile LONG val = 1; + MemoryBarrier(); + InterlockedCompareExchange(&val, 0, 1); + InterlockedIncrement(&val); + InterlockedDecrement(&val); +#else + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); +#endif + return 0; + } +" LLVM_MULTITHREADED) + +if( NOT LLVM_MULTITHREADED ) + message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") +endif() diff --git a/final/cmake/modules/ChooseMSVCCRT.cmake b/final/cmake/modules/ChooseMSVCCRT.cmake new file mode 100644 index 00000000000..eb78f45c885 --- /dev/null +++ b/final/cmake/modules/ChooseMSVCCRT.cmake @@ -0,0 +1,106 @@ +# The macro choose_msvc_crt() takes a list of possible +# C runtimes to choose from, in the form of compiler flags, +# to present to the user. (MTd for /MTd, etc) +# +# The macro is invoked at the end of the file. +# +# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and +# CMAKE_C_FLAGS_* variables by default. To let the user +# override that for each build type: +# 1. Detect which CRT is already selected, and reflect this in +# LLVM_USE_CRT_* so the user can have a better idea of what +# changes they're making. +# 2. Replace the flags in both variables with the new flag via a regex. +# 3. set() the variables back into the cache so the changes +# are user-visible. + +### Helper macros: ### +macro(make_crt_regex regex crts) + set(${regex} "") + foreach(crt ${${crts}}) + # Trying to match the beginning or end of the string with stuff + # like [ ^]+ didn't work, so use a bunch of parentheses instead. + set(${regex} "${${regex}}|(^| +)/${crt}($| +)") + endforeach(crt) + string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}") +endmacro(make_crt_regex) + +macro(get_current_crt crt_current regex flagsvar) + # Find the selected-by-CMake CRT for each build type, if any. + # Strip off the leading slash and any whitespace. + string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}") + string(REPLACE "/" " " ${crt_current} "${${crt_current}}") + string(STRIP "${${crt_current}}" ${crt_current}) +endmacro(get_current_crt) + +# Replaces or adds a flag to a variable. +# Expects 'flag' to be padded with spaces. +macro(set_flag_in_var flagsvar regex flag) + string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}") + if("${current_flag}" STREQUAL "") + set(${flagsvar} "${${flagsvar}}${${flag}}") + else() + string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}") + endif() + string(STRIP "${${flagsvar}}" ${flagsvar}) + # Make sure this change gets reflected in the cache/gui. + # CMake requires the docstring parameter whenever set() touches the cache, + # so get the existing docstring and re-use that. + get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING) + set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE) +endmacro(set_flag_in_var) + + +macro(choose_msvc_crt MSVC_CRT) + if(LLVM_USE_CRT) + message(FATAL_ERROR + "LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific +variables (LLVM_USE_CRT_DEBUG, etc) instead.") + endif() + + make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT}) + + foreach(build_type ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${build_type}" build) + if (NOT LLVM_USE_CRT_${build}) + get_current_crt(LLVM_USE_CRT_${build} + MSVC_CRT_REGEX + CMAKE_CXX_FLAGS_${build}) + set(LLVM_USE_CRT_${build} + "${LLVM_USE_CRT_${build}}" + CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations." + FORCE) + set_property(CACHE LLVM_USE_CRT_${build} + PROPERTY STRINGS "";${${MSVC_CRT}}) + endif(NOT LLVM_USE_CRT_${build}) + endforeach(build_type) + + foreach(build_type ${CMAKE_CONFIGURATION_TYPES}) + string(TOUPPER "${build_type}" build) + if ("${LLVM_USE_CRT_${build}}" STREQUAL "") + set(flag_string " ") + else() + set(flag_string " /${LLVM_USE_CRT_${build}} ") + list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx) + if (idx LESS 0) + message(FATAL_ERROR + "Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}") + endif (idx LESS 0) + message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}") + endif() + foreach(lang C CXX) + set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string) + endforeach(lang) + endforeach(build_type) +endmacro(choose_msvc_crt MSVC_CRT) + + +# List of valid CRTs for MSVC +set(MSVC_CRT + MD + MDd + MT + MTd) + +choose_msvc_crt(MSVC_CRT) + diff --git a/final/cmake/modules/CrossCompileLLVM.cmake b/final/cmake/modules/CrossCompileLLVM.cmake new file mode 100644 index 00000000000..98e60a54366 --- /dev/null +++ b/final/cmake/modules/CrossCompileLLVM.cmake @@ -0,0 +1,26 @@ + +if( ${LLVM_TABLEGEN} STREQUAL "tblgen" ) + set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native") + set(LLVM_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/tblgen") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR} + COMMENT "Creating ${CX_NATIVE_TG_DIR}...") + + add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt + COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} + DEPENDS ${CX_NATIVE_TG_DIR} + COMMENT "Configuring native TableGen...") + + add_custom_command(OUTPUT ${LLVM_TABLEGEN_EXE} + COMMAND ${CMAKE_BUILD_TOOL} + DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt + WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}/utils/TableGen + COMMENT "Building native TableGen...") + add_custom_target(NativeTableGen DEPENDS ${LLVM_TABLEGEN_EXE}) + + add_dependencies(tblgen NativeTableGen) + + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR}) +endif() diff --git a/final/cmake/modules/FindBison.cmake b/final/cmake/modules/FindBison.cmake new file mode 100755 index 00000000000..0320ae3ce14 --- /dev/null +++ b/final/cmake/modules/FindBison.cmake @@ -0,0 +1,52 @@ +# - Try to find Bison +# Once done this will define +# +# BISON_FOUND - system has Bison +# BISON_EXECUTABLE - path of the bison executable +# BISON_VERSION - the version string, like "2.5.31" +# + +MACRO(FIND_BISON) + FIND_PROGRAM(BISON_EXECUTABLE NAMES bison) + + IF(BISON_EXECUTABLE) + SET(BISON_FOUND TRUE) + + EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version + OUTPUT_VARIABLE _BISON_VERSION + ) + string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" BISON_VERSION "${_bison_VERSION}") + ENDIF(BISON_EXECUTABLE) + + IF(BISON_FOUND) + IF(NOT Bison_FIND_QUIETLY) + MESSAGE(STATUS "Found Bison: ${BISON_EXECUTABLE}") + ENDIF(NOT Bison_FIND_QUIETLY) + ELSE(BISON_FOUND) + IF(Bison_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find Bison") + ENDIF(Bison_FIND_REQUIRED) + ENDIF(BISON_FOUND) +ENDMACRO(FIND_BISON) + +MACRO(BISON_GENERATOR _PREFIX _Y_INPUT _H_OUTPUT _CPP_OUTPUT) + IF(BISON_EXECUTABLE) + GET_FILENAME_COMPONENT(_Y_DIR ${_Y_INPUT} PATH) + ADD_CUSTOM_COMMAND( + OUTPUT ${_CPP_OUTPUT} + OUTPUT ${_H_OUTPUT} + DEPENDS ${_Y_INPUT} + COMMAND ${BISON_EXECUTABLE} + ARGS + -p ${_PREFIX} -o"${_CPP_OUTPUT}" + --defines="${_H_OUTPUT}" ${_Y_INPUT} + WORKING_DIRECTORY ${_Y_DIR} + ) + SET_SOURCE_FILES_PROPERTIES( + ${_CPP_OUTPUT} ${_H_OUTPUT} + GENERATED + ) + ELSE(BISON_EXECUTABLE) + MESSAGE(SEND_ERROR "Can't find bison program, and it's required") + ENDIF(BISON_EXECUTABLE) +ENDMACRO(BISON_GENERATOR) diff --git a/final/cmake/modules/GetTargetTriple.cmake b/final/cmake/modules/GetTargetTriple.cmake new file mode 100644 index 00000000000..f4321c9b67e --- /dev/null +++ b/final/cmake/modules/GetTargetTriple.cmake @@ -0,0 +1,30 @@ +# Returns the host triple. +# Invokes config.guess + +function( get_target_triple var ) + if( MSVC ) + if( CMAKE_CL_64 ) + set( value "x86_64-pc-win32" ) + else() + set( value "i686-pc-win32" ) + endif() + elseif( MINGW AND NOT MSYS ) + if( CMAKE_SIZEOF_VOID_P EQUAL 8 ) + set( value "x86_64-w64-mingw32" ) + else() + set( value "i686-pc-mingw32" ) + endif() + else( MSVC ) + set(config_guess ${LLVM_MAIN_SRC_DIR}/autoconf/config.guess) + execute_process(COMMAND sh ${config_guess} + RESULT_VARIABLE TT_RV + OUTPUT_VARIABLE TT_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + if( NOT TT_RV EQUAL 0 ) + message(FATAL_ERROR "Failed to execute ${config_guess}") + endif( NOT TT_RV EQUAL 0 ) + set( value ${TT_OUT} ) + endif( MSVC ) + set( ${var} ${value} PARENT_SCOPE ) + message(STATUS "Target triple: ${value}") +endfunction( get_target_triple var ) diff --git a/final/cmake/modules/HandleLLVMOptions.cmake b/final/cmake/modules/HandleLLVMOptions.cmake new file mode 100644 index 00000000000..e1f06a7ab9c --- /dev/null +++ b/final/cmake/modules/HandleLLVMOptions.cmake @@ -0,0 +1,185 @@ +include(AddLLVMDefinitions) + +# Run-time build mode; It is used for unittests. +if(MSVC_IDE) + # Expect "$(Configuration)", "$(OutDir)", etc. + # It is expanded by msbuild or similar. + set(RUNTIME_BUILD_MODE "${CMAKE_CFG_INTDIR}") +elseif(NOT CMAKE_BUILD_TYPE STREQUAL "") + # Expect "Release" "Debug", etc. + # Or unittests could not run. + set(RUNTIME_BUILD_MODE ${CMAKE_BUILD_TYPE}) +else() + # It might be "." + set(RUNTIME_BUILD_MODE "${CMAKE_CFG_INTDIR}") +endif() + +set(LIT_ARGS_DEFAULT "-sv") +if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") +endif() +set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" + CACHE STRING "Default options for lit") + +if( LLVM_ENABLE_ASSERTIONS ) + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + if( NOT MSVC ) + add_definitions( -D_DEBUG ) + endif() + # On Release builds cmake automatically defines NDEBUG, so we + # explicitly undefine it: + if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + add_definitions( -UNDEBUG ) + endif() +else() + if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" ) + if( NOT MSVC_IDE AND NOT XCODE ) + add_definitions( -DNDEBUG ) + endif() + endif() +endif() + +if(WIN32) + if(CYGWIN) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + else(CYGWIN) + set(LLVM_ON_WIN32 1) + set(LLVM_ON_UNIX 0) + + # This is effective only on Win32 hosts to use gnuwin32 tools. + set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") + endif(CYGWIN) + set(LTDL_SHLIB_EXT ".dll") + set(EXEEXT ".exe") + # Maximum path length is 160 for non-unicode paths + set(MAXPATHLEN 160) +else(WIN32) + if(UNIX) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + if(APPLE) + set(LTDL_SHLIB_EXT ".dylib") + else(APPLE) + set(LTDL_SHLIB_EXT ".so") + endif(APPLE) + set(EXEEXT "") + # FIXME: Maximum path length is currently set to 'safe' fixed value + set(MAXPATHLEN 2024) + else(UNIX) + MESSAGE(SEND_ERROR "Unable to determine platform") + endif(UNIX) +endif(WIN32) + +if( LLVM_ENABLE_PIC ) + if( XCODE ) + # Xcode has -mdynamic-no-pic on by default, which overrides -fPIC. I don't + # know how to disable this, so just force ENABLE_PIC off for now. + message(WARNING "-fPIC not supported with Xcode.") + elseif( WIN32 ) + # On Windows all code is PIC. MinGW warns if -fPIC is used. + else() + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("-fPIC" SUPPORTS_FPIC_FLAG) + if( SUPPORTS_FPIC_FLAG ) + message(STATUS "Building with -fPIC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + else( SUPPORTS_FPIC_FLAG ) + message(WARNING "-fPIC not supported.") + endif() + endif() +endif() + +if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + # TODO: support other platforms and toolchains. + option(LLVM_BUILD_32_BITS "Build 32 bits executables and libraries." OFF) + if( LLVM_BUILD_32_BITS ) + message(STATUS "Building 32 bits executables and libraries.") + add_llvm_definitions( -m32 ) + list(APPEND CMAKE_EXE_LINKER_FLAGS -m32) + list(APPEND CMAKE_SHARED_LINKER_FLAGS -m32) + endif( LLVM_BUILD_32_BITS ) +endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) + +if( MSVC_IDE AND ( MSVC90 OR MSVC10 ) ) + # Only Visual Studio 2008 and 2010 officially supports /MP. + # Visual Studio 2005 do support it but it's experimental there. + set(LLVM_COMPILER_JOBS "0" CACHE STRING + "Number of parallel compiler jobs. 0 means use all processors. Default is 0.") + if( NOT LLVM_COMPILER_JOBS STREQUAL "1" ) + if( LLVM_COMPILER_JOBS STREQUAL "0" ) + add_llvm_definitions( /MP ) + else() + if (MSVC10) + message(FATAL_ERROR + "Due to a bug in CMake only 0 and 1 is supported for " + "LLVM_COMPILER_JOBS when generating for Visual Studio 2010") + else() + message(STATUS "Number of parallel compiler jobs set to " ${LLVM_COMPILER_JOBS}) + add_llvm_definitions( /MP${LLVM_COMPILER_JOBS} ) + endif() + endif() + else() + message(STATUS "Parallel compilation disabled") + endif() +endif() + +if( MSVC ) + include(ChooseMSVCCRT) + + # Add definitions that make MSVC much less annoying. + add_llvm_definitions( + # For some reason MS wants to deprecate a bunch of standard functions... + -D_CRT_SECURE_NO_DEPRECATE + -D_CRT_SECURE_NO_WARNINGS + -D_CRT_NONSTDC_NO_DEPRECATE + -D_CRT_NONSTDC_NO_WARNINGS + -D_SCL_SECURE_NO_DEPRECATE + -D_SCL_SECURE_NO_WARNINGS + + -wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned' + -wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored' + -wd4224 # Suppress 'nonstandard extension used : formal parameter 'identifier' was previously defined as a type' + -wd4244 # Suppress ''argument' : conversion from 'type1' to 'type2', possible loss of data' + -wd4267 # Suppress ''var' : conversion from 'size_t' to 'type', possible loss of data' + -wd4275 # Suppress 'An exported class was derived from a class that was not exported.' + -wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception' + -wd4345 # Suppress 'behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized' + -wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized' + -wd4355 # Suppress ''this' : used in base member initializer list' + -wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated' + -wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible' + -wd4715 # Suppress ''function' : not all control paths return a value' + -wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)' + -wd4065 # Suppress 'switch statement contains 'default' but no 'case' labels' + + -w14062 # Promote "enumerator in switch of enum is not handled" to level 1 warning. + ) + + # Enable warnings + if (LLVM_ENABLE_WARNINGS) + add_llvm_definitions( /W4 /Wall ) + if (LLVM_ENABLE_PEDANTIC) + # No MSVC equivalent available + endif (LLVM_ENABLE_PEDANTIC) + endif (LLVM_ENABLE_WARNINGS) + if (LLVM_ENABLE_WERROR) + add_llvm_definitions( /WX ) + endif (LLVM_ENABLE_WERROR) +elseif( CMAKE_COMPILER_IS_GNUCXX ) + if (LLVM_ENABLE_WARNINGS) + add_llvm_definitions( -Wall -W -Wno-unused-parameter -Wwrite-strings ) + if (LLVM_ENABLE_PEDANTIC) + add_llvm_definitions( -pedantic -Wno-long-long ) + endif (LLVM_ENABLE_PEDANTIC) + endif (LLVM_ENABLE_WARNINGS) + if (LLVM_ENABLE_WERROR) + add_llvm_definitions( -Werror ) + endif (LLVM_ENABLE_WERROR) +endif( MSVC ) + +add_llvm_definitions( -D__STDC_LIMIT_MACROS ) +add_llvm_definitions( -D__STDC_CONSTANT_MACROS ) + +option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON) diff --git a/final/cmake/modules/LLVM.cmake b/final/cmake/modules/LLVM.cmake new file mode 100644 index 00000000000..9182afdf275 --- /dev/null +++ b/final/cmake/modules/LLVM.cmake @@ -0,0 +1,40 @@ +# This file provides information and services to the final user. + +set(LLVM_PACKAGE_VERSION @PACKAGE_VERSION@) + +set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@) + +set_property( GLOBAL PROPERTY LLVM_LIBS "@llvm_libs@") + +set(LLVM_ALL_TARGETS @LLVM_ALL_TARGETS@) + +set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@) + +set(TARGET_TRIPLE "@TARGET_TRIPLE@") + +set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) + +set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) + +set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@) + +set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) + +set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS) + +set(HAVE_LIBDL @HAVE_LIBDL@) +set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD) + +# We try to include using the current setting of CMAKE_MODULE_PATH, +# which suppossedly was filled by the user with the directory where +# this file was installed: +include( LLVMConfig OPTIONAL RESULT_VARIABLE LLVMCONFIG_INCLUDED ) + +# If failed, we assume that this is an un-installed build: +if( NOT LLVMCONFIG_INCLUDED ) + set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} + "@LLVM_SOURCE_DIR@/cmake/modules") + include( LLVMConfig ) +endif() + diff --git a/final/cmake/modules/LLVMConfig.cmake b/final/cmake/modules/LLVMConfig.cmake new file mode 100755 index 00000000000..e8308f680b0 --- /dev/null +++ b/final/cmake/modules/LLVMConfig.cmake @@ -0,0 +1,189 @@ +function(get_system_libs return_var) + # Returns in `return_var' a list of system libraries used by LLVM. + if( NOT MSVC ) + if( MINGW ) + set(system_libs ${system_libs} imagehlp psapi) + elseif( CMAKE_HOST_UNIX ) + if( HAVE_LIBDL ) + set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) + set(system_libs ${system_libs} pthread) + endif() + endif( MINGW ) + endif( NOT MSVC ) + set(${return_var} ${system_libs} PARENT_SCOPE) +endfunction(get_system_libs) + + +function(is_llvm_target_library library return_var) + # Sets variable `return_var' to ON if `library' corresponds to a + # LLVM supported target. To OFF if it doesn't. + set(${return_var} OFF PARENT_SCOPE) + string(TOUPPER "${library}" capitalized_lib) + string(TOUPPER "${LLVM_ALL_TARGETS}" targets) + foreach(t ${targets}) + if( capitalized_lib STREQUAL "LLVM${t}" OR + capitalized_lib STREQUAL "LLVM${t}CODEGEN" OR + capitalized_lib STREQUAL "LLVM${t}ASMPARSER" OR + capitalized_lib STREQUAL "LLVM${t}ASMPRINTER" OR + capitalized_lib STREQUAL "LLVM${t}DISASSEMBLER" OR + capitalized_lib STREQUAL "LLVM${t}INFO" ) + set(${return_var} ON PARENT_SCOPE) + break() + endif() + endforeach() +endfunction(is_llvm_target_library) + + +macro(llvm_config executable) + explicit_llvm_config(${executable} ${ARGN}) +endmacro(llvm_config) + + +function(explicit_llvm_config executable) + set( link_components ${ARGN} ) + + explicit_map_components_to_libraries(LIBRARIES ${link_components}) + target_link_libraries(${executable} ${LIBRARIES}) +endfunction(explicit_llvm_config) + + +# This is a variant intended for the final user: +function(llvm_map_components_to_libraries OUT_VAR) + explicit_map_components_to_libraries(result ${ARGN}) + get_system_libs(sys_result) + set( ${OUT_VAR} ${result} ${sys_result} PARENT_SCOPE ) +endfunction(llvm_map_components_to_libraries) + + +function(explicit_map_components_to_libraries out_libs) + set( link_components ${ARGN} ) + get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS) + string(TOUPPER "${llvm_libs}" capitalized_libs) + + # Expand some keywords: + list(FIND link_components "engine" engine_required) + if( engine_required ) + # TODO: as we assume we are on X86, this is `jit'. + list(APPEND link_components "jit") + list(APPEND link_components "native") + endif() + list(FIND link_components "native" native_required) + if( native_required ) + list(APPEND link_components "X86") + endif() + + # Translate symbolic component names to real libraries: + foreach(c ${link_components}) + # add codegen, asmprinter, asmparser, disassembler + list(FIND LLVM_TARGETS_TO_BUILD ${c} idx) + if( NOT idx LESS 0 ) + list(FIND llvm_libs "LLVM${c}CodeGen" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}CodeGen") + else() + list(FIND llvm_libs "LLVM${c}" idx) + if( NOT idx LESS 0 ) + list(APPEND expanded_components "LLVM${c}") + else() + message(FATAL_ERROR "Target ${c} is not in the set of libraries.") + endif() + endif() + list(FIND llvm_libs "LLVM${c}AsmPrinter" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmPrinter") + endif() + list(FIND llvm_libs "LLVM${c}AsmParser" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}AsmParser") + endif() + list(FIND llvm_libs "LLVM${c}Info" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Info") + endif() + list(FIND llvm_libs "LLVM${c}Disassembler" asmidx) + if( NOT asmidx LESS 0 ) + list(APPEND expanded_components "LLVM${c}Disassembler") + endif() + elseif( c STREQUAL "native" ) + # already processed + elseif( c STREQUAL "nativecodegen" ) + list(APPEND expanded_components "LLVM${LLVM_NATIVE_ARCH}CodeGen") + elseif( c STREQUAL "backend" ) + # same case as in `native'. + elseif( c STREQUAL "engine" ) + # already processed + elseif( c STREQUAL "all" ) + list(APPEND expanded_components ${llvm_libs}) + else( NOT idx LESS 0 ) + # Canonize the component name: + string(TOUPPER "${c}" capitalized) + list(FIND capitalized_libs LLVM${capitalized} lib_idx) + if( lib_idx LESS 0 ) + # The component is unkown. Maybe is an ommitted target? + is_llvm_target_library(${c} iltl_result) + if( NOT iltl_result ) + message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.") + endif() + else( lib_idx LESS 0 ) + list(GET llvm_libs ${lib_idx} canonical_lib) + list(APPEND expanded_components ${canonical_lib}) + endif( lib_idx LESS 0 ) + endif( NOT idx LESS 0 ) + endforeach(c) + # Expand dependencies while topologically sorting the list of libraries: + list(LENGTH expanded_components lst_size) + set(cursor 0) + set(processed) + while( cursor LESS lst_size ) + list(GET expanded_components ${cursor} lib) + list(APPEND expanded_components ${MSVC_LIB_DEPS_${lib}}) + # Remove duplicates at the front: + list(REVERSE expanded_components) + list(REMOVE_DUPLICATES expanded_components) + list(REVERSE expanded_components) + list(APPEND processed ${lib}) + # Find the maximum index that doesn't have to be re-processed: + while(NOT "${expanded_components}" MATCHES "^${processed}.*" ) + list(REMOVE_AT processed -1) + endwhile() + list(LENGTH processed cursor) + list(LENGTH expanded_components lst_size) + endwhile( cursor LESS lst_size ) + # Return just the libraries included in this build: + set(result) + foreach(c ${expanded_components}) + list(FIND llvm_libs ${c} lib_idx) + if( NOT lib_idx LESS 0 ) + set(result ${result} ${c}) + endif() + endforeach(c) + set(${out_libs} ${result} PARENT_SCOPE) +endfunction(explicit_map_components_to_libraries) + + +# The library dependency data is contained in the file +# LLVMLibDeps.cmake on this directory. It is automatically generated +# by tools/llvm-config/CMakeLists.txt when the build comprises all the +# targets and we are on a environment Posix enough to build the +# llvm-config script. This, in practice, just excludes MSVC. + +# When you remove or rename a library from the build, be sure to +# remove its file from lib/ as well, or the GenLibDeps.pl script will +# include it on its analysis! + +# The format generated by GenLibDeps.pl + +# LLVMARMAsmPrinter.o: LLVMARMCodeGen.o libLLVMAsmPrinter.a libLLVMCodeGen.a libLLVMCore.a libLLVMSupport.a libLLVMTarget.a + +# is translated to: + +# set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMTarget) + +# It is necessary to remove the `lib' prefix and the `.a'. + +# This 'sed' script should do the trick: +# sed -e s'#\.a##g' -e 's#libLLVM#LLVM#g' -e 's#: # #' -e 's#\(.*\)#set(MSVC_LIB_DEPS_\1)#' ~/llvm/tools/llvm-config/LibDeps.txt + +include(LLVMLibDeps) diff --git a/final/cmake/modules/LLVMLibDeps.cmake b/final/cmake/modules/LLVMLibDeps.cmake new file mode 100644 index 00000000000..e70ea8aca4e --- /dev/null +++ b/final/cmake/modules/LLVMLibDeps.cmake @@ -0,0 +1,68 @@ +set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMCodeGen LLVMARMInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMAsmPrinter LLVMARMInfo LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMARMDisassembler LLVMARMCodeGen LLVMARMInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMARMInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAlphaCodeGen LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMAlphaInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAnalysis LLVMCore LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMArchive LLVMBitReader LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAsmParser LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMAsmPrinter LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMMCParser LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMBitReader LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMAsmPrinter LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa) +set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMAsmPrinter LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMCellSPUInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCodeGen LLVMAnalysis LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMCppBackend LLVMCore LLVMCppBackendInfo LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMCppBackendInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMExecutionEngine LLVMCore LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMInstCombine LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMSupport LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMJIT LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMBlazeAsmPrinter LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMBlazeAsmPrinter LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMBlazeDisassembler LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMCDisassembler LLVMARMAsmParser LLVMARMCodeGen LLVMARMDisassembler LLVMARMInfo LLVMAlphaCodeGen LLVMAlphaInfo LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCBackend LLVMCBackendInfo LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCppBackend LLVMCppBackendInfo LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeDisassembler LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMMSP430CodeGen LLVMMSP430Info LLVMMipsCodeGen LLVMMipsInfo LLVMPTXCodeGen LLVMPTXInfo LLVMPowerPCCodeGen LLVMPowerPCInfo LLVMSparcCodeGen LLVMSparcInfo LLVMSupport LLVMSystemZCodeGen LLVMSystemZInfo LLVMX86AsmParser LLVMX86CodeGen LLVMX86Disassembler LLVMX86Info LLVMXCoreCodeGen LLVMXCoreInfo) +set(MSVC_LIB_DEPS_LLVMMCJIT LLVMExecutionEngine LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430AsmPrinter LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMObject LLVMSupport) +set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCAsmPrinter LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMPowerPCInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMScalarOpts LLVMAnalysis LLVMCore LLVMInstCombine LLVMSupport LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget LLVMTransformUtils) +set(MSVC_LIB_DEPS_LLVMSparcCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSparcInfo LLVMSupport LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSparcInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMSupport ) +set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystemZInfo LLVMTarget) +set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMipa) +set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMTarget LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMMC LLVMSupport LLVMX86Utils) +set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMX86AsmPrinter LLVMX86Info LLVMX86Utils) +set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info) +set(MSVC_LIB_DEPS_LLVMX86Info LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMX86Utils LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMXCoreCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMXCoreInfo) +set(MSVC_LIB_DEPS_LLVMXCoreInfo LLVMMC LLVMSupport) +set(MSVC_LIB_DEPS_LLVMipa LLVMAnalysis LLVMCore LLVMSupport) +set(MSVC_LIB_DEPS_LLVMipo LLVMAnalysis LLVMCore LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa) diff --git a/final/cmake/modules/LLVMParseArguments.cmake b/final/cmake/modules/LLVMParseArguments.cmake new file mode 100644 index 00000000000..ce19be114b3 --- /dev/null +++ b/final/cmake/modules/LLVMParseArguments.cmake @@ -0,0 +1,80 @@ +# Copied from http://www.itk.org/Wiki/CMakeMacroParseArguments under +# http://creativecommons.org/licenses/by/2.5/. +# +# The PARSE_ARGUMENTS macro will take the arguments of another macro and define +# several variables. The first argument to PARSE_ARGUMENTS is a prefix to put on +# all variables it creates. The second argument is a list of names, and the +# third argument is a list of options. Both of these lists should be quoted. The +# rest of PARSE_ARGUMENTS are arguments from another macro to be parsed. +# +# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...) +# +# For each item in options, PARSE_ARGUMENTS will create a variable with that +# name, prefixed with prefix_. So, for example, if prefix is MY_MACRO and +# options is OPTION1;OPTION2, then PARSE_ARGUMENTS will create the variables +# MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These variables will be set to true if +# the option exists in the command line or false otherwise. +# +#For each item in arg_names, PARSE_ARGUMENTS will create a variable with that +#name, prefixed with prefix_. Each variable will be filled with the arguments +#that occur after the given arg_name is encountered up to the next arg_name or +#the end of the arguments. All options are removed from these +#lists. PARSE_ARGUMENTS also creates a prefix_DEFAULT_ARGS variable containing +#the list of all arguments up to the first arg_name encountered. +# +#Here is a simple, albeit impractical, example of using PARSE_ARGUMENTS that +#demonstrates its behavior. +# +# SET(arguments +# hello OPTION3 world +# LIST3 foo bar +# OPTION2 +# LIST1 fuz baz +# ) +# +# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) +# +# PARSE_ARGUMENTS creates 7 variables and sets them as follows: +# ARG_DEFAULT_ARGS: hello;world +# ARG_LIST1: fuz;baz +# ARG_LIST2: +# ARG_LIST3: foo;bar +# ARG_OPTION1: FALSE +# ARG_OPTION2: TRUE +# ARG_OPTION3: TRUE +# +# If you don't have any options, use an empty string in its place. +# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "" ${arguments}) +# Likewise if you have no lists. +# PARSE_ARGUMENTS(ARG "" "OPTION1;OPTION2;OPTION3" ${arguments}) + +MACRO(PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + SET(larg_names ${arg_names}) + LIST(FIND larg_names "${arg}" is_arg_name) + IF (is_arg_name GREATER -1) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name GREATER -1) + SET(loption_names ${option_names}) + LIST(FIND loption_names "${arg}" is_option) + IF (is_option GREATER -1) + SET(${prefix}_${arg} TRUE) + ELSE (is_option GREATER -1) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option GREATER -1) + ENDIF (is_arg_name GREATER -1) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO(PARSE_ARGUMENTS) diff --git a/final/cmake/modules/LLVMProcessSources.cmake b/final/cmake/modules/LLVMProcessSources.cmake new file mode 100644 index 00000000000..270292ad3b8 --- /dev/null +++ b/final/cmake/modules/LLVMProcessSources.cmake @@ -0,0 +1,90 @@ +include(AddFileDependencies) + +function(llvm_replace_compiler_option var old new) + # Replaces a compiler option or switch `old' in `var' by `new'. + # If `old' is not in `var', appends `new' to `var'. + # Example: llvm_replace_compiler_option(CMAKE_CXX_FLAGS_RELEASE "-O3" "-O2") + # If the option already is on the variable, don't add it: + if( "${${var}}" MATCHES "(^| )${new}($| )" ) + set(n "") + else() + set(n "${new}") + endif() + if( "${${var}}" MATCHES "(^| )${old}($| )" ) + string( REGEX REPLACE "(^| )${old}($| )" " ${n} " ${var} "${${var}}" ) + else() + set( ${var} "${${var}} ${n}" ) + endif() + set( ${var} "${${var}}" PARENT_SCOPE ) +endfunction(llvm_replace_compiler_option) + +macro(add_td_sources srcs) + file(GLOB tds *.td) + if( tds ) + source_group("TableGen descriptions" FILES ${tds}) + set_source_files_properties(${tds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${tds}) + endif() +endmacro(add_td_sources) + + +macro(add_header_files srcs) + file(GLOB hds *.h *.def) + if( hds ) + set_source_files_properties(${hds} PROPERTIES HEADER_FILE_ONLY ON) + list(APPEND ${srcs} ${hds}) + endif() +endmacro(add_header_files) + + +function(llvm_process_sources OUT_VAR) + set( sources ${ARGN} ) + llvm_check_source_file_list( ${sources} ) + # Create file dependencies on the tablegenned files, if any. Seems + # that this is not strictly needed, as dependencies of the .cpp + # sources on the tablegenned .inc files are detected and handled, + # but just in case... + foreach( s ${sources} ) + set( f ${CMAKE_CURRENT_SOURCE_DIR}/${s} ) + add_file_dependencies( ${f} ${TABLEGEN_OUTPUT} ) + endforeach(s) + if( MSVC_IDE ) + # This adds .td and .h files to the Visual Studio solution: + add_td_sources(sources) + add_header_files(sources) + endif() + + # Set common compiler options: + if( NOT LLVM_REQUIRES_EH ) + if( CMAKE_COMPILER_IS_GNUCXX ) + add_definitions( -fno-exceptions ) + elseif( MSVC ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/EHsc" "/EHs-c-") + add_definitions( /D_HAS_EXCEPTIONS=0 ) + endif() + endif() + if( NOT LLVM_REQUIRES_RTTI ) + if( CMAKE_COMPILER_IS_GNUCXX ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-frtti" "-fno-rtti") + elseif( MSVC ) + llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR" "/GR-") + endif() + endif() + + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE ) + set( ${OUT_VAR} ${sources} PARENT_SCOPE ) +endfunction(llvm_process_sources) + + +function(llvm_check_source_file_list) + set(listed ${ARGN}) + file(GLOB globbed *.cpp) + foreach(g ${globbed}) + get_filename_component(fn ${g} NAME) + list(FIND listed ${fn} idx) + if( idx LESS 0 ) + message(SEND_ERROR "Found unknown source file ${g} +Please update ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt\n") + endif() + endforeach() +endfunction(llvm_check_source_file_list) diff --git a/final/cmake/modules/TableGen.cmake b/final/cmake/modules/TableGen.cmake new file mode 100644 index 00000000000..9d67137bb42 --- /dev/null +++ b/final/cmake/modules/TableGen.cmake @@ -0,0 +1,46 @@ +# LLVM_TARGET_DEFINITIONS must contain the name of the .td file to process. +# Extra parameters for `tblgen' may come after `ofn' parameter. +# Adds the name of the generated file to TABLEGEN_OUTPUT. + +macro(tablegen ofn) + file(GLOB local_tds "*.td") + file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td") + + if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) + set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS}) + else() + set(LLVM_TARGET_DEFINITIONS_ABSOLUTE + ${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}) + endif() + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # Generate tablegen output in a temporary file. + COMMAND ${LLVM_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + # The file in LLVM_TARGET_DEFINITIONS may be not in the current + # directory and local_tds may not contain it, so we must + # explicitly list it here: + DEPENDS ${LLVM_TABLEGEN_EXE} ${local_tds} ${global_tds} + ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} + COMMENT "Building ${ofn}..." + ) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + # Only update the real output file if there are any differences. + # This prevents recompilation of all the files depending on it if there + # aren't any. + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + ${CMAKE_CURRENT_BINARY_DIR}/${ofn} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp + COMMENT "" + ) + + # `make clean' must remove all those generated files: + set_property(DIRECTORY APPEND + PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${ofn}.tmp ${ofn}) + + set(TABLEGEN_OUTPUT ${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/${ofn}) + set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn} + PROPERTIES GENERATED 1) +endmacro(tablegen) diff --git a/final/cmake/modules/VersionFromVCS.cmake b/final/cmake/modules/VersionFromVCS.cmake new file mode 100644 index 00000000000..81739be927a --- /dev/null +++ b/final/cmake/modules/VersionFromVCS.cmake @@ -0,0 +1,46 @@ +# Adds version control information to the variable VERS. For +# determining the Version Control System used (if any) it inspects the +# existence of certain subdirectories under CMAKE_CURRENT_SOURCE_DIR. + +function(add_version_info_from_vcs VERS) + set(result ${${VERS}}) + if( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn" ) + set(result "${result}svn") + # FindSubversion does not work with symlinks. See PR 8437 + if( NOT IS_SYMLINK "${CMAKE_CURRENT_SOURCE_DIR}" ) + find_package(Subversion) + endif() + if( Subversion_FOUND ) + subversion_wc_info( ${CMAKE_CURRENT_SOURCE_DIR} Project ) + if( Project_WC_REVISION ) + set(result "${result}-r${Project_WC_REVISION}") + endif() + endif() + elseif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git ) + set(result "${result}git") + # Try to get a ref-id + find_program(git_executable NAMES git git.exe git.cmd) + if( git_executable ) + execute_process(COMMAND ${git_executable} show-ref HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if( git_result EQUAL 0 ) + string(SUBSTRING ${git_output} 0 7 git_ref_id) + set(result "${result}-${git_ref_id}") + else() + execute_process(COMMAND ${git_executable} svn log --limit=1 --oneline + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if( git_result EQUAL 0 ) + string(REGEX MATCH r[0-9]+ git_svn_rev ${git_output}) + set(result "${result}-svn-${git_svn_rev}") + endif() + endif() + endif() + endif() + set(${VERS} ${result} PARENT_SCOPE) +endfunction(add_version_info_from_vcs) diff --git a/final/configure b/final/configure new file mode 100755 index 00000000000..52bf988247b --- /dev/null +++ b/final/configure @@ -0,0 +1,24115 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60 for llvm 2.9. +# +# Report bugs to . +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='llvm' +PACKAGE_TARNAME='-llvm-' +PACKAGE_VERSION='2.9' +PACKAGE_STRING='llvm 2.9' +PACKAGE_BUGREPORT='llvmbugs@cs.uiuc.edu' + +ac_unique_file="lib/VMCore/Module.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +LLVM_COPYRIGHT +subdirs +ENABLE_POLLY +LLVM_HAS_POLLY +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +OS +HOST_OS +TARGET_OS +LINKALL +NOLINKALL +LLVM_ON_UNIX +LLVM_ON_WIN32 +ARCH +ENDIAN +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CPP +GREP +EGREP +LLVM_CROSS_COMPILING +BUILD_CC +BUILD_EXEEXT +BUILD_CXX +CVSBUILD +ENABLE_OPTIMIZED +ENABLE_PROFILING +DISABLE_ASSERTIONS +ENABLE_EXPENSIVE_CHECKS +EXPENSIVE_CHECKS +DEBUG_RUNTIME +DEBUG_SYMBOLS +JIT +TARGET_HAS_JIT +ENABLE_DOCS +ENABLE_DOXYGEN +ENABLE_THREADS +ENABLE_PTHREADS +ENABLE_PIC +ENABLE_SHARED +ENABLE_EMBED_STDCXX +ENABLE_TIMESTAMPS +TARGETS_TO_BUILD +LLVM_ENUM_TARGETS +LLVM_ENUM_ASM_PRINTERS +LLVM_ENUM_ASM_PARSERS +LLVM_ENUM_DISASSEMBLERS +ENABLE_CBE_PRINTF_A +CLANGPATH +CLANGXXPATH +ENABLE_BUILT_CLANG +OPTIMIZE_OPTION +EXTRA_OPTIONS +BINUTILS_INCDIR +CXX +CXXFLAGS +ac_ct_CXX +NM +ifGNUmake +LN_S +CMP +CP +DATE +FIND +MKDIR +MV +RANLIB +AR +RM +SED +TAR +BINPWD +GRAPHVIZ +DOT +FDP +NEATO +TWOPI +CIRCO +GV +DOTTY +XDOT_PY +PERL +HAVE_PERL +INSTALL_PROGRAM +INSTALL_SCRIPT +INSTALL_DATA +BZIP2 +CAT +DOXYGEN +GROFF +GZIPBIN +POD2HTML +POD2MAN +PDFROFF +RUNTEST +TCLSH +ZIP +OCAMLC +OCAMLOPT +OCAMLDEP +OCAMLDOC +GAS +HAVE_LINK_VERSION_SCRIPT +INSTALL_LTDL_TRUE +INSTALL_LTDL_FALSE +CONVENIENCE_LTDL_TRUE +CONVENIENCE_LTDL_FALSE +LIBADD_DL +LLVMGCCCOMMAND +LLVMGXXCOMMAND +LLVMGCC +LLVMGXX +LLVMCC_OPTION +NO_VARIADIC_MACROS +NO_MISSING_FIELD_INITIALIZERS +USE_UDIS86 +USE_OPROFILE +HAVE_PTHREAD +HUGE_VAL_SANITY +MMAP_FILE +LLVMCC_EMITIR_FLAG +LLVMCC1 +LLVMCC1PLUS +LLVMGCCDIR +LLVMGCC_LANGS +LLVMGCC_DRAGONEGG +LLVMCC_DISABLEOPT_FLAGS +SHLIBEXT +SHLIBPATH_VAR +LLVM_PREFIX +LLVM_BINDIR +LLVM_LIBDIR +LLVM_DATADIR +LLVM_DOCSDIR +LLVM_ETCDIR +LLVM_INCLUDEDIR +LLVM_INFODIR +LLVM_MANDIR +LLVM_CONFIGTIME +BINDINGS_TO_BUILD +ALL_BINDINGS +OCAML_LIBDIR +ENABLE_VISIBILITY_INLINES_HIDDEN +RPATH +RDYNAMIC +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC' +ac_subdirs_all='projects/llvm-gcc +projects/test-suite +projects/llvm-test +projects/poolalloc +projects/llvm-poolalloc +projects/sample +projects/privbracket +projects/llvm-stacker +projects/llvm-reopt +projects/llvm-java +projects/llvm-tv +projects/safecode +projects/llvm-kernel +tools/polly' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures llvm 2.9 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/-llvm-] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of llvm 2.9:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-polly Use polly if available (default is YES) + --enable-optimized Compile with optimizations enabled (default is YES) + --enable-profiling Compile with profiling enabled (default is NO) + --enable-assertions Compile with assertion checks enabled (default is NO) + --enable-expensive-checks + Compile with expensive debug checks enabled (default + is NO) + --enable-debug-runtime Build runtime libs with debug symbols (default is + NO) + --enable-debug-symbols Build compiler with debug symbols (default is NO if + optimization is on and YES if it's off) + --enable-jit Enable Just In Time Compiling (default is YES) + --enable-docs Build documents (default is YES) + --enable-doxygen Build doxygen documentation (default is NO) + --enable-threads Use threads if available (default is YES) + --enable-pthreads Use pthreads if available (default is YES) + --enable-pic Build LLVM with Position Independent Code (default + is YES) + --enable-shared Build a shared library and link tools against it + (default is NO) + --enable-embed-stdcxx Build a shared library with embedded libstdc++ for + Win32 DLL (default is YES) + --enable-timestamps Enable embedding timestamp information in build + (default is YES) + --enable-targets Build specific host targets: all or + target1,target2,... Valid targets are: host, x86, + x86_64, sparc, powerpc, alpha, arm, mips, spu, + xcore, msp430, systemz, blackfin, ptx, cbe, and cpp + (default=all) + --enable-cbe-printf-a Enable C Backend output with hex floating point via + %a (default is YES) + --enable-bindings Build specific language bindings: + all,auto,none,{binding-name} (default=auto) + --enable-libffi Check for the presence of libffi (default is NO) + --enable-ltdl-install install libltdl + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-llvmgccdir Specify location of llvm-gcc install dir (default + searches PATH) + --with-llvmgcc Specify location of llvm-gcc driver (default + searches PATH) + --with-llvmgxx Specify location of llvm-g++ driver (default + searches PATH) + --with-clang Specify location of clang compiler (default is + --with-built-clang) + --with-built-clang Use the compiled Clang as the LLVM compiler + (default=check) + --with-optimize-option Select the compiler options to use for optimized + builds + --with-extra-options Specify additional options to compile LLVM with + --with-ocaml-libdir Specify install location for ocaml bindings (default + is stdlib) + --with-clang-resource-dir + Relative directory from the Clang binary for + resource files + --with-c-include-dirs Colon separated list of directories clang will + search for headers + --with-cxx-include-root Directory with the libstdc++ headers. + --with-cxx-include-arch Architecture of the libstdc++ headers. + --with-cxx-include-32bit-dir + 32 bit multilib dir. + --with-cxx-include-64bit-dir + 64 bit multilib directory. + --with-binutils-include Specify path to binutils/include/ containing + plugin-api.h file for gold plugin. + --with-tclinclude directory where tcl headers are + --with-llvmcc= Choose the LLVM capable compiler to use (llvm-gcc, + clang, or none; default=check) + --with-udis86= Use udis86 external x86 disassembler library + --with-oprofile= + Tell OProfile >= 0.9.4 how to symbolize JIT output + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +llvm configure 2.9 +generated by GNU Autoconf 2.60 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by llvm $as_me 2.9, which was +generated by GNU Autoconf 2.60. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +LLVM_COPYRIGHT="Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign." + + + + + + + +ac_aux_dir= +for ac_dir in autoconf "$srcdir"/autoconf; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in autoconf \"$srcdir\"/autoconf" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +if test ${srcdir} != "." ; then + if test -f ${srcdir}/include/llvm/Config/config.h ; then + { { echo "$as_me:$LINENO: error: Already configured in ${srcdir}" >&5 +echo "$as_me: error: Already configured in ${srcdir}" >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +if test -d ${srcdir}/projects/llvm-gcc ; then + subdirs="$subdirs projects/llvm-gcc" + +fi + +if test -d ${srcdir}/projects/test-suite ; then + subdirs="$subdirs projects/test-suite" + +fi + +if test -d ${srcdir}/projects/llvm-test ; then + subdirs="$subdirs projects/llvm-test" + +fi + +if test -d ${srcdir}/projects/poolalloc ; then + subdirs="$subdirs projects/poolalloc" + +fi + +if test -d ${srcdir}/projects/llvm-poolalloc ; then + subdirs="$subdirs projects/llvm-poolalloc" + +fi + +for i in `ls ${srcdir}/projects` +do + if test -d ${srcdir}/projects/${i} ; then + case ${i} in + sample) subdirs="$subdirs projects/sample" + ;; + privbracket) subdirs="$subdirs projects/privbracket" + ;; + llvm-stacker) subdirs="$subdirs projects/llvm-stacker" + ;; + llvm-reopt) subdirs="$subdirs projects/llvm-reopt" +;; + llvm-java) subdirs="$subdirs projects/llvm-java" + ;; + llvm-tv) subdirs="$subdirs projects/llvm-tv" + ;; + safecode) subdirs="$subdirs projects/safecode" + ;; + llvm-kernel) subdirs="$subdirs projects/llvm-kernel" + ;; + llvm-gcc) ;; + test-suite) ;; + llvm-test) ;; + poolalloc) ;; + llvm-poolalloc) ;; + *) + { echo "$as_me:$LINENO: WARNING: Unknown project (${i}) won't be configured automatically" >&5 +echo "$as_me: WARNING: Unknown project (${i}) won't be configured automatically" >&2;} + ;; + esac + fi +done + +# Check whether --enable-polly was given. +if test "${enable_polly+set}" = set; then + enableval=$enable_polly; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_POLLY=1 + ;; + no) ENABLE_POLLY=0 + ;; + default) ENABLE_POLLY=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-polly. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +if (test -d ${srcdir}/tools/polly) && (test $ENABLE_POLLY -eq 1) ; then + LLVM_HAS_POLLY=1 + + subdirs="$subdirs tools/polly" + +fi + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +{ echo "$as_me:$LINENO: checking type of operating system we're going to host on" >&5 +echo $ECHO_N "checking type of operating system we're going to host on... $ECHO_C" >&6; } +if test "${llvm_cv_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $host in + *-*-aix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="AIX" + llvm_cv_platform_type="Unix" ;; + *-*-irix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="IRIX" + llvm_cv_platform_type="Unix" ;; + *-*-cygwin*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Cygwin" + llvm_cv_platform_type="Unix" ;; + *-*-darwin*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Darwin" + llvm_cv_platform_type="Unix" ;; + *-*-minix*) + llvm_cv_link_all_option="-Wl,-all_load" + llvm_cv_no_link_all_option="-Wl,-noall_load" + llvm_cv_os_type="Minix" + llvm_cv_platform_type="Unix" ;; + *-*-freebsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="FreeBSD" + llvm_cv_platform_type="Unix" ;; + *-*-openbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="OpenBSD" + llvm_cv_platform_type="Unix" ;; + *-*-netbsd*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="NetBSD" + llvm_cv_platform_type="Unix" ;; + *-*-dragonfly*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="DragonFly" + llvm_cv_platform_type="Unix" ;; + *-*-hpux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="HP-UX" + llvm_cv_platform_type="Unix" ;; + *-*-interix*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Interix" + llvm_cv_platform_type="Unix" ;; + *-*-linux*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Linux" + llvm_cv_platform_type="Unix" ;; + *-*-solaris*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_no_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="SunOS" + llvm_cv_platform_type="Unix" ;; + *-*-auroraux*) + llvm_cv_link_all_option="-Wl,-z,allextract" + llvm_cv_link_all_option="-Wl,-z,defaultextract" + llvm_cv_os_type="AuroraUX" + llvm_cv_platform_type="Unix" ;; + *-*-win32*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Win32" + llvm_cv_platform_type="Win32" ;; + *-*-mingw*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="MingW" + llvm_cv_platform_type="Win32" ;; + *-*-haiku*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Haiku" + llvm_cv_platform_type="Unix" ;; + *-unknown-eabi*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *-unknown-elf*) + llvm_cv_link_all_option="-Wl,--whole-archive" + llvm_cv_no_link_all_option="-Wl,--no-whole-archive" + llvm_cv_os_type="Freestanding" + llvm_cv_platform_type="Unix" ;; + *) + llvm_cv_link_all_option="" + llvm_cv_no_link_all_option="" + llvm_cv_os_type="Unknown" + llvm_cv_platform_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_os_type" >&5 +echo "${ECHO_T}$llvm_cv_os_type" >&6; } + +{ echo "$as_me:$LINENO: checking type of operating system we're going to target" >&5 +echo $ECHO_N "checking type of operating system we're going to target... $ECHO_C" >&6; } +if test "${llvm_cv_target_os_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + *-*-aix*) + llvm_cv_target_os_type="AIX" ;; + *-*-irix*) + llvm_cv_target_os_type="IRIX" ;; + *-*-cygwin*) + llvm_cv_target_os_type="Cygwin" ;; + *-*-darwin*) + llvm_cv_target_os_type="Darwin" ;; + *-*-minix*) + llvm_cv_target_os_type="Minix" ;; + *-*-freebsd*) + llvm_cv_target_os_type="FreeBSD" ;; + *-*-openbsd*) + llvm_cv_target_os_type="OpenBSD" ;; + *-*-netbsd*) + llvm_cv_target_os_type="NetBSD" ;; + *-*-dragonfly*) + llvm_cv_target_os_type="DragonFly" ;; + *-*-hpux*) + llvm_cv_target_os_type="HP-UX" ;; + *-*-interix*) + llvm_cv_target_os_type="Interix" ;; + *-*-linux*) + llvm_cv_target_os_type="Linux" ;; + *-*-solaris*) + llvm_cv_target_os_type="SunOS" ;; + *-*-auroraux*) + llvm_cv_target_os_type="AuroraUX" ;; + *-*-win32*) + llvm_cv_target_os_type="Win32" ;; + *-*-mingw*) + llvm_cv_target_os_type="MingW" ;; + *-*-haiku*) + llvm_cv_target_os_type="Haiku" ;; + *-unknown-eabi*) + llvm_cv_target_os_type="Freestanding" ;; + *) + llvm_cv_target_os_type="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_os_type" >&5 +echo "${ECHO_T}$llvm_cv_target_os_type" >&6; } + +if test "$llvm_cv_os_type" = "Unknown" ; then + { { echo "$as_me:$LINENO: error: Operating system is unknown, configure can't continue" >&5 +echo "$as_me: error: Operating system is unknown, configure can't continue" >&2;} + { (exit 1); exit 1; }; } +fi + +OS=$llvm_cv_os_type + +HOST_OS=$llvm_cv_os_type + +TARGET_OS=$llvm_cv_target_os_type + + +LINKALL=$llvm_cv_link_all_option + +NOLINKALL=$llvm_cv_no_link_all_option + + +case $llvm_cv_platform_type in + Unix) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_UNIX 1 +_ACEOF + + LLVM_ON_UNIX=1 + + LLVM_ON_WIN32=0 + + ;; + Win32) + +cat >>confdefs.h <<\_ACEOF +#define LLVM_ON_WIN32 1 +_ACEOF + + LLVM_ON_UNIX=0 + + LLVM_ON_WIN32=1 + + ;; +esac + +{ echo "$as_me:$LINENO: checking target architecture" >&5 +echo $ECHO_N "checking target architecture... $ECHO_C" >&6; } +if test "${llvm_cv_target_arch+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $target in + i?86-*) llvm_cv_target_arch="x86" ;; + amd64-* | x86_64-*) llvm_cv_target_arch="x86_64" ;; + sparc*-*) llvm_cv_target_arch="Sparc" ;; + powerpc*-*) llvm_cv_target_arch="PowerPC" ;; + alpha*-*) llvm_cv_target_arch="Alpha" ;; + arm*-*) llvm_cv_target_arch="ARM" ;; + mips-*) llvm_cv_target_arch="Mips" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; + msp430-*) llvm_cv_target_arch="MSP430" ;; + s390x-*) llvm_cv_target_arch="SystemZ" ;; + bfin-*) llvm_cv_target_arch="Blackfin" ;; + mblaze-*) llvm_cv_target_arch="MBlaze" ;; + ptx-*) llvm_cv_target_arch="PTX" ;; + *) llvm_cv_target_arch="Unknown" ;; +esac +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_target_arch" >&5 +echo "${ECHO_T}$llvm_cv_target_arch" >&6; } + +if test "$llvm_cv_target_arch" = "Unknown" ; then + { echo "$as_me:$LINENO: WARNING: Configuring LLVM for an unknown target archicture" >&5 +echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;} +fi + +# Determine the LLVM native architecture for the target +case "$llvm_cv_target_arch" in + x86) LLVM_NATIVE_ARCH="X86" ;; + x86_64) LLVM_NATIVE_ARCH="X86" ;; + *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;; +esac + +ARCH=$llvm_cv_target_arch + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_bigendian=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6; } +case $ac_cv_c_bigendian in + yes) + ENDIAN=big + ;; + no) + ENDIAN=little + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +if test "$cross_compiling" = yes; then + LLVM_CROSS_COMPILING=1 + + +{ echo "$as_me:$LINENO: checking for executable suffix on build platform" >&5 +echo $ECHO_N "checking for executable suffix on build platform... $ECHO_C" >&6; } +if test "${ac_cv_build_exeext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$CYGWIN" = yes || test "$MINGW32" = yes; then + ac_cv_build_exeext=.exe +else + ac_build_prefix=${build_alias}- + + # Extract the first word of "${ac_build_prefix}gcc", so it can be a program name with args. +set dummy ${ac_build_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="${ac_build_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CC to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi + test -z "$BUILD_CC" && { { echo "$as_me:$LINENO: error: no acceptable cc found in \$PATH" >&5 +echo "$as_me: error: no acceptable cc found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + ac_build_link='${BUILD_CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' + rm -f conftest* + echo 'int main () { return 0; }' > conftest.$ac_ext + ac_cv_build_exeext= + if { (eval echo "$as_me:$LINENO: \"$ac_build_link\"") >&5 + (eval $ac_build_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for file in conftest.*; do + case $file in + *.c | *.o | *.obj | *.dSYM) ;; + *) ac_cv_build_exeext=`echo $file | sed -e s/conftest//` ;; + esac + done + else + { { echo "$as_me:$LINENO: error: installation or configuration problem: compiler cannot create executables." >&5 +echo "$as_me: error: installation or configuration problem: compiler cannot create executables." >&2;} + { (exit 1); exit 1; }; } + fi + rm -f conftest* + test x"${ac_cv_build_exeext}" = x && ac_cv_build_exeext=blank +fi +fi + +BUILD_EXEEXT="" +test x"${ac_cv_build_exeext}" != xblank && BUILD_EXEEXT=${ac_cv_build_exeext} +{ echo "$as_me:$LINENO: result: ${ac_cv_build_exeext}" >&5 +echo "${ECHO_T}${ac_cv_build_exeext}" >&6; } +ac_build_exeext=$BUILD_EXEEXT + + ac_build_prefix=${build_alias}- + # Extract the first word of "${ac_build_prefix}g++", so it can be a program name with args. +set dummy ${ac_build_prefix}g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="${ac_build_prefix}g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "g++", so it can be a program name with args. +set dummy g++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_BUILD_CXX="g++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test -z "$BUILD_CXX"; then + # Extract the first word of "c++", so it can be a program name with args. +set dummy c++; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_BUILD_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CXX"; then + ac_cv_prog_BUILD_CXX="$BUILD_CXX" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/c++"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_BUILD_CXX="c++" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_BUILD_CXX + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set BUILD_CXX to just the basename; use the full file name. + shift + ac_cv_prog_BUILD_CXX="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +BUILD_CXX=$ac_cv_prog_BUILD_CXX +if test -n "$BUILD_CXX"; then + { echo "$as_me:$LINENO: result: $BUILD_CXX" >&5 +echo "${ECHO_T}$BUILD_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi + fi +else + LLVM_CROSS_COMPILING=0 + +fi + +if test -d ".svn" -o -d "${srcdir}/.svn" -o -d ".git" -o -d "${srcdir}/.git"; then + cvsbuild="yes" + optimize="no" + CVSBUILD=CVSBUILD=1 + +else + cvsbuild="no" + optimize="yes" +fi + + +# Check whether --enable-optimized was given. +if test "${enable_optimized+set}" = set; then + enableval=$enable_optimized; +else + enableval=$optimize +fi + +if test ${enableval} = "no" ; then + ENABLE_OPTIMIZED= + +else + ENABLE_OPTIMIZED=ENABLE_OPTIMIZED=1 + +fi + +# Check whether --enable-profiling was given. +if test "${enable_profiling+set}" = set; then + enableval=$enable_profiling; +else + enableval="no" +fi + +if test ${enableval} = "no" ; then + ENABLE_PROFILING= + +else + ENABLE_PROFILING=ENABLE_PROFILING=1 + +fi + +# Check whether --enable-assertions was given. +if test "${enable_assertions+set}" = set; then + enableval=$enable_assertions; +else + enableval="no" +fi + +if test ${enableval} = "yes" ; then + DISABLE_ASSERTIONS= + +else + DISABLE_ASSERTIONS=DISABLE_ASSERTIONS=1 + +fi + +# Check whether --enable-expensive-checks was given. +if test "${enable_expensive_checks+set}" = set; then + enableval=$enable_expensive_checks; +else + enableval="no" +fi + +if test ${enableval} = "yes" ; then + ENABLE_EXPENSIVE_CHECKS=ENABLE_EXPENSIVE_CHECKS=1 + + EXPENSIVE_CHECKS=yes + +else + ENABLE_EXPENSIVE_CHECKS= + + EXPENSIVE_CHECKS=no + +fi + +# Check whether --enable-debug-runtime was given. +if test "${enable_debug_runtime+set}" = set; then + enableval=$enable_debug_runtime; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_RUNTIME= + +else + DEBUG_RUNTIME=DEBUG_RUNTIME=1 + +fi + +# Check whether --enable-debug-symbols was given. +if test "${enable_debug_symbols+set}" = set; then + enableval=$enable_debug_symbols; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + DEBUG_SYMBOLS= + +else + DEBUG_SYMBOLS=DEBUG_SYMBOLS=1 + +fi + +# Check whether --enable-jit was given. +if test "${enable_jit+set}" = set; then + enableval=$enable_jit; +else + enableval=default +fi + +if test ${enableval} = "no" +then + JIT= + +else + case "$llvm_cv_target_arch" in + x86) TARGET_HAS_JIT=1 + ;; + Sparc) TARGET_HAS_JIT=0 + ;; + PowerPC) TARGET_HAS_JIT=1 + ;; + x86_64) TARGET_HAS_JIT=1 + ;; + Alpha) TARGET_HAS_JIT=0 + ;; + ARM) TARGET_HAS_JIT=1 + ;; + Mips) TARGET_HAS_JIT=0 + ;; + XCore) TARGET_HAS_JIT=0 + ;; + MSP430) TARGET_HAS_JIT=0 + ;; + SystemZ) TARGET_HAS_JIT=0 + ;; + Blackfin) TARGET_HAS_JIT=0 + ;; + MBlaze) TARGET_HAS_JIT=0 + ;; + PTX) TARGET_HAS_JIT=0 + ;; + *) TARGET_HAS_JIT=0 + ;; + esac +fi + +# Check whether --enable-docs was given. +if test "${enable_docs+set}" = set; then + enableval=$enable_docs; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_DOCS=1 + ;; + no) ENABLE_DOCS=0 + ;; + default) ENABLE_DOCS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-docs. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-docs. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-doxygen was given. +if test "${enable_doxygen+set}" = set; then + enableval=$enable_doxygen; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_DOXYGEN=1 + ;; + no) ENABLE_DOXYGEN=0 + ;; + default) ENABLE_DOXYGEN=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-doxygen. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then + enableval=$enable_threads; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_THREADS=1 + ;; + no) ENABLE_THREADS=0 + ;; + default) ENABLE_THREADS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-threads. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_THREADS $ENABLE_THREADS +_ACEOF + + +# Check whether --enable-pthreads was given. +if test "${enable_pthreads+set}" = set; then + enableval=$enable_pthreads; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_PTHREADS=1 + ;; + no) ENABLE_PTHREADS=0 + ;; + default) ENABLE_PTHREADS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-pthreads. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-pthreads. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-pic was given. +if test "${enable_pic+set}" = set; then + enableval=$enable_pic; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_PIC=1 + ;; + no) ENABLE_PIC=0 + ;; + default) ENABLE_PIC=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-pic. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_PIC $ENABLE_PIC +_ACEOF + + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_SHARED=1 + ;; + no) ENABLE_SHARED=0 + ;; + default) ENABLE_SHARED=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-embed-stdcxx was given. +if test "${enable_embed_stdcxx+set}" = set; then + enableval=$enable_embed_stdcxx; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_EMBED_STDCXX=1 + ;; + no) ENABLE_EMBED_STDCXX=0 + ;; + default) ENABLE_EMBED_STDCXX=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-embed-stdcxx. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +# Check whether --enable-timestamps was given. +if test "${enable_timestamps+set}" = set; then + enableval=$enable_timestamps; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_TIMESTAMPS=1 + ;; + no) ENABLE_TIMESTAMPS=0 + ;; + default) ENABLE_TIMESTAMPS=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-timestamps. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-timestamps. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_TIMESTAMPS $ENABLE_TIMESTAMPS +_ACEOF + + +TARGETS_TO_BUILD="" +# Check whether --enable-targets was given. +if test "${enable_targets+set}" = set; then + enableval=$enable_targets; +else + enableval=all +fi + +if test "$enableval" = host-only ; then + enableval=host +fi +case "$enableval" in + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU XCore MSP430 SystemZ Blackfin CBackend CppBackend MBlaze PTX" ;; + *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_target" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + powerpc) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; + cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; + ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; + host) case "$llvm_cv_target_arch" in + x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; + Sparc) TARGETS_TO_BUILD="Sparc $TARGETS_TO_BUILD" ;; + PowerPC) TARGETS_TO_BUILD="PowerPC $TARGETS_TO_BUILD" ;; + Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; + ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; + Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; + CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; + XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; + MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; + s390x) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + Blackfin) TARGETS_TO_BUILD="Blackfin $TARGETS_TO_BUILD" ;; + PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 +echo "$as_me: error: Can not set target to build" >&2;} + { (exit 1); exit 1; }; } ;; + esac ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized target $a_target" >&5 +echo "$as_me: error: Unrecognized target $a_target" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac +TARGETS_TO_BUILD=$TARGETS_TO_BUILD + + +# Determine whether we are building LLVM support for the native architecture. +# If so, define LLVM_NATIVE_ARCH to that LLVM target. +for a_target in $TARGETS_TO_BUILD; do + if test "$a_target" = "$LLVM_NATIVE_ARCH"; then + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ARCH $LLVM_NATIVE_ARCH +_ACEOF + + LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target" + LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo" + LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter" + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_TARGET $LLVM_NATIVE_TARGET +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_TARGETINFO $LLVM_NATIVE_TARGETINFO +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_NATIVE_ASMPRINTER $LLVM_NATIVE_ASMPRINTER +_ACEOF + + fi +done + +# Build the LLVM_TARGET and LLVM_... macros for Targets.def and the individual +# target feature def files. +LLVM_ENUM_TARGETS="" +LLVM_ENUM_ASM_PRINTERS="" +LLVM_ENUM_ASM_PARSERS="" +LLVM_ENUM_DISASSEMBLERS="" +for target_to_build in $TARGETS_TO_BUILD; do + LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS" + if test -f ${srcdir}/lib/Target/${target_to_build}/*AsmPrinter.cpp ; then + LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/AsmParser/Makefile ; then + LLVM_ENUM_ASM_PARSERS="LLVM_ASM_PARSER($target_to_build) $LLVM_ENUM_ASM_PARSERS"; + fi + if test -f ${srcdir}/lib/Target/${target_to_build}/Disassembler/Makefile ; then + LLVM_ENUM_DISASSEMBLERS="LLVM_DISASSEMBLER($target_to_build) $LLVM_ENUM_DISASSEMBLERS"; + fi +done + + + + + +# Check whether --enable-cbe-printf-a was given. +if test "${enable_cbe_printf_a+set}" = set; then + enableval=$enable_cbe_printf_a; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_CBE_PRINTF_A=1 + ;; + no) ENABLE_CBE_PRINTF_A=0 + ;; + default) ENABLE_CBE_PRINTF_A=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define ENABLE_CBE_PRINTF_A $ENABLE_CBE_PRINTF_A +_ACEOF + + + +# Check whether --with-llvmgccdir was given. +if test "${with_llvmgccdir+set}" = set; then + withval=$with_llvmgccdir; +else + withval=default +fi + +case "$withval" in + default) WITH_LLVMGCCDIR=default ;; + /* | [A-Za-z]:[\\/]*) WITH_LLVMGCCDIR=$withval ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-llvmgccdir. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-llvmgccdir. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Check whether --with-llvmgcc was given. +if test "${with_llvmgcc+set}" = set; then + withval=$with_llvmgcc; LLVMGCC=$with_llvmgcc + WITH_LLVMGCCDIR="" +fi + + + +# Check whether --with-llvmgxx was given. +if test "${with_llvmgxx+set}" = set; then + withval=$with_llvmgxx; LLVMGXX=$with_llvmgxx + WITH_LLVMGCCDIR="" +fi + + +if test -n "$LLVMGCC"; then + LLVMGCCCOMMAND="$LLVMGCC" +fi + +if test -n "$LLVMGXX"; then + LLVMGXXCOMMAND="$LLVMGXX" +fi + +if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then + { { echo "$as_me:$LINENO: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&5 +echo "$as_me: error: Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used" >&2;} + { (exit 1); exit 1; }; }; +fi + +if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then + { { echo "$as_me:$LINENO: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&5 +echo "$as_me: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used" >&2;} + { (exit 1); exit 1; }; }; +fi + + +# Check whether --with-clang was given. +if test "${with_clang+set}" = set; then + withval=$with_clang; +else + with_clang=default +fi + + + +# Check whether --with-built-clang was given. +if test "${with_built_clang+set}" = set; then + withval=$with_built_clang; +else + with_built_clang=check +fi + + +{ echo "$as_me:$LINENO: checking clang compiler" >&5 +echo $ECHO_N "checking clang compiler... $ECHO_C" >&6; } +WITH_CLANGPATH="" +WITH_BUILT_CLANG=0 +if test "$with_clang" != "default"; then + WITH_CLANGPATH="$with_clang" + if ! test -x "$WITH_CLANGPATH"; then + { { echo "$as_me:$LINENO: error: invalid --with-clang, path does not specify an executable" >&5 +echo "$as_me: error: invalid --with-clang, path does not specify an executable" >&2;} + { (exit 1); exit 1; }; } + fi +elif test "$with_built_clang" = "yes"; then + WITH_BUILT_CLANG=1 +elif test "$with_built_clang" = "no"; then + WITH_BUILT_CLANG=0 +else + if test "$with_built_clang" != "check"; then + { { echo "$as_me:$LINENO: error: invalid value for --with-built-clang." >&5 +echo "$as_me: error: invalid value for --with-built-clang." >&2;} + { (exit 1); exit 1; }; } + fi + + if test -f ${srcdir}/tools/clang/README.txt; then + WITH_BUILT_CLANG=1 + fi +fi + +if ! test -z "$WITH_CLANGPATH"; then + { echo "$as_me:$LINENO: result: $WITH_CLANGPATH" >&5 +echo "${ECHO_T}$WITH_CLANGPATH" >&6; } + WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++` +elif test "$WITH_BUILT_CLANG" = "1"; then + { echo "$as_me:$LINENO: result: built" >&5 +echo "${ECHO_T}built" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi +CLANGPATH=$WITH_CLANGPATH + +CLANGXXPATH=$WITH_CLANGXXPATH + +ENABLE_BUILT_CLANG=$WITH_BUILT_CLANG + + + +# Check whether --with-optimize-option was given. +if test "${with_optimize_option+set}" = set; then + withval=$with_optimize_option; +else + withval=default +fi + +{ echo "$as_me:$LINENO: checking optimization flags" >&5 +echo $ECHO_N "checking optimization flags... $ECHO_C" >&6; } +case "$withval" in + default) + case "$llvm_cv_os_type" in + FreeBSD) optimize_option=-O2 ;; + MingW) optimize_option=-O2 ;; + *) optimize_option=-O3 ;; + esac ;; + *) optimize_option="$withval" ;; +esac +OPTIMIZE_OPTION=$optimize_option + +{ echo "$as_me:$LINENO: result: $optimize_option" >&5 +echo "${ECHO_T}$optimize_option" >&6; } + + +# Check whether --with-extra-options was given. +if test "${with_extra_options+set}" = set; then + withval=$with_extra_options; +else + withval=default +fi + +case "$withval" in + default) EXTRA_OPTIONS= ;; + *) EXTRA_OPTIONS=$withval ;; +esac +EXTRA_OPTIONS=$EXTRA_OPTIONS + + +# Check whether --enable-bindings was given. +if test "${enable_bindings+set}" = set; then + enableval=$enable_bindings; +else + enableval=default +fi + +BINDINGS_TO_BUILD="" +case "$enableval" in + yes | default | auto) BINDINGS_TO_BUILD="auto" ;; + all ) BINDINGS_TO_BUILD="ocaml" ;; + none | no) BINDINGS_TO_BUILD="" ;; + *)for a_binding in `echo $enableval|sed -e 's/,/ /g' ` ; do + case "$a_binding" in + ocaml) BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" ;; + *) { { echo "$as_me:$LINENO: error: Unrecognized binding $a_binding" >&5 +echo "$as_me: error: Unrecognized binding $a_binding" >&2;} + { (exit 1); exit 1; }; } ;; + esac + done + ;; +esac + + +# Check whether --with-ocaml-libdir was given. +if test "${with_ocaml_libdir+set}" = set; then + withval=$with_ocaml_libdir; +else + withval=auto +fi + +case "$withval" in + auto) with_ocaml_libdir="$withval" ;; + /* | [A-Za-z]:[\\/]*) with_ocaml_libdir="$withval" ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-ocaml-libdir. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-ocaml-libdir. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +# Check whether --with-clang-resource-dir was given. +if test "${with_clang_resource_dir+set}" = set; then + withval=$with_clang_resource_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CLANG_RESOURCE_DIR "$withval" +_ACEOF + + + +# Check whether --with-c-include-dirs was given. +if test "${with_c_include_dirs+set}" = set; then + withval=$with_c_include_dirs; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define C_INCLUDE_DIRS "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-root was given. +if test "${with_cxx_include_root+set}" = set; then + withval=$with_cxx_include_root; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_ROOT "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-arch was given. +if test "${with_cxx_include_arch+set}" = set; then + withval=$with_cxx_include_arch; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_ARCH "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-32bit-dir was given. +if test "${with_cxx_include_32bit_dir+set}" = set; then + withval=$with_cxx_include_32bit_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_32BIT_DIR "$withval" +_ACEOF + + + +# Check whether --with-cxx-include-64bit-dir was given. +if test "${with_cxx_include_64bit_dir+set}" = set; then + withval=$with_cxx_include_64bit_dir; +else + withval="" +fi + + +cat >>confdefs.h <<_ACEOF +#define CXX_INCLUDE_64BIT_DIR "$withval" +_ACEOF + + + +# Check whether --with-binutils-include was given. +if test "${with_binutils_include+set}" = set; then + withval=$with_binutils_include; +else + withval=default +fi + +case "$withval" in + default) WITH_BINUTILS_INCDIR=default ;; + /* | [A-Za-z]:[\\/]*) WITH_BINUTILS_INCDIR=$withval ;; + *) { { echo "$as_me:$LINENO: error: Invalid path for --with-binutils-include. Provide full path" >&5 +echo "$as_me: error: Invalid path for --with-binutils-include. Provide full path" >&2;} + { (exit 1); exit 1; }; } ;; +esac +if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then + BINUTILS_INCDIR=$WITH_BINUTILS_INCDIR + + if test ! -f "$WITH_BINUTILS_INCDIR/plugin-api.h"; then + echo "$WITH_BINUTILS_INCDIR/plugin-api.h" + { { echo "$as_me:$LINENO: error: Invalid path to directory containing plugin-api.h." >&5 +echo "$as_me: error: Invalid path to directory containing plugin-api.h." >&2;} + { (exit 1); exit 1; }; }; + fi +fi + +# Check whether --enable-libffi was given. +if test "${enable_libffi+set}" = set; then + enableval=$enable_libffi; case "$enableval" in + yes) llvm_cv_enable_libffi="yes" ;; + no) llvm_cv_enable_libffi="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_libffi=no +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in gcc + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in gcc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + + + +{ echo "$as_me:$LINENO: checking for GNU make" >&5 +echo $ECHO_N "checking for GNU make... $ECHO_C" >&6; } +if test "${llvm_cv_gnu_make_command+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_gnu_make_command='' + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) + then + llvm_cv_gnu_make_command=$a ; + break; + fi + done +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_gnu_make_command" >&5 +echo "${ECHO_T}$llvm_cv_gnu_make_command" >&6; } + if test "x$llvm_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + else + ifGNUmake='#' ; + { echo "$as_me:$LINENO: result: \"Not found\"" >&5 +echo "${ECHO_T}\"Not found\"" >&6; }; + fi + + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +# Extract the first word of "cmp", so it can be a program name with args. +set dummy cmp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CMP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CMP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CMP="$CMP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CMP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CMP" && ac_cv_path_CMP="cmp" + ;; +esac +fi +CMP=$ac_cv_path_CMP +if test -n "$CMP"; then + { echo "$as_me:$LINENO: result: $CMP" >&5 +echo "${ECHO_T}$CMP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CP" && ac_cv_path_CP="cp" + ;; +esac +fi +CP=$ac_cv_path_CP +if test -n "$CP"; then + { echo "$as_me:$LINENO: result: $CP" >&5 +echo "${ECHO_T}$CP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "date", so it can be a program name with args. +set dummy date; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DATE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_DATE="$DATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DATE="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DATE" && ac_cv_path_DATE="date" + ;; +esac +fi +DATE=$ac_cv_path_DATE +if test -n "$DATE"; then + { echo "$as_me:$LINENO: result: $DATE" >&5 +echo "${ECHO_T}$DATE" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "find", so it can be a program name with args. +set dummy find; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FIND+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FIND in + [\\/]* | ?:[\\/]*) + ac_cv_path_FIND="$FIND" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FIND="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FIND" && ac_cv_path_FIND="find" + ;; +esac +fi +FIND=$ac_cv_path_FIND +if test -n "$FIND"; then + { echo "$as_me:$LINENO: result: $FIND" >&5 +echo "${ECHO_T}$FIND" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "grep", so it can be a program name with args. +set dummy grep; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GREP in + [\\/]* | ?:[\\/]*) + ac_cv_path_GREP="$GREP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GREP" && ac_cv_path_GREP="grep" + ;; +esac +fi +GREP=$ac_cv_path_GREP +if test -n "$GREP"; then + { echo "$as_me:$LINENO: result: $GREP" >&5 +echo "${ECHO_T}$GREP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MKDIR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MKDIR in + [\\/]* | ?:[\\/]*) + ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="mkdir" + ;; +esac +fi +MKDIR=$ac_cv_path_MKDIR +if test -n "$MKDIR"; then + { echo "$as_me:$LINENO: result: $MKDIR" >&5 +echo "${ECHO_T}$MKDIR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_MV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MV in + [\\/]* | ?:[\\/]*) + ac_cv_path_MV="$MV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_MV" && ac_cv_path_MV="mv" + ;; +esac +fi +MV=$ac_cv_path_MV +if test -n "$MV"; then + { echo "$as_me:$LINENO: result: $MV" >&5 +echo "${ECHO_T}$MV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RM in + [\\/]* | ?:[\\/]*) + ac_cv_path_RM="$RM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" + ;; +esac +fi +RM=$ac_cv_path_RM +if test -n "$RM"; then + { echo "$as_me:$LINENO: result: $RM" >&5 +echo "${ECHO_T}$RM" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SED in + [\\/]* | ?:[\\/]*) + ac_cv_path_SED="$SED" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SED" && ac_cv_path_SED="sed" + ;; +esac +fi +SED=$ac_cv_path_SED +if test -n "$SED"; then + { echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "tar", so it can be a program name with args. +set dummy tar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TAR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TAR in + [\\/]* | ?:[\\/]*) + ac_cv_path_TAR="$TAR" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TAR" && ac_cv_path_TAR="gtar" + ;; +esac +fi +TAR=$ac_cv_path_TAR +if test -n "$TAR"; then + { echo "$as_me:$LINENO: result: $TAR" >&5 +echo "${ECHO_T}$TAR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pwd", so it can be a program name with args. +set dummy pwd; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BINPWD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BINPWD in + [\\/]* | ?:[\\/]*) + ac_cv_path_BINPWD="$BINPWD" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BINPWD="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BINPWD" && ac_cv_path_BINPWD="pwd" + ;; +esac +fi +BINPWD=$ac_cv_path_BINPWD +if test -n "$BINPWD"; then + { echo "$as_me:$LINENO: result: $BINPWD" >&5 +echo "${ECHO_T}$BINPWD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +# Extract the first word of "Graphviz", so it can be a program name with args. +set dummy Graphviz; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GRAPHVIZ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GRAPHVIZ in + [\\/]* | ?:[\\/]*) + ac_cv_path_GRAPHVIZ="$GRAPHVIZ" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GRAPHVIZ="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GRAPHVIZ" && ac_cv_path_GRAPHVIZ="echo Graphviz" + ;; +esac +fi +GRAPHVIZ=$ac_cv_path_GRAPHVIZ +if test -n "$GRAPHVIZ"; then + { echo "$as_me:$LINENO: result: $GRAPHVIZ" >&5 +echo "${ECHO_T}$GRAPHVIZ" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$GRAPHVIZ" != "echo Graphviz" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GRAPHVIZ 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GRAPHVIZ=`echo $GRAPHVIZ | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GRAPHVIZ "$GRAPHVIZ${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dot", so it can be a program name with args. +set dummy dot; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOT in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOT="$DOT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOT" && ac_cv_path_DOT="echo dot" + ;; +esac +fi +DOT=$ac_cv_path_DOT +if test -n "$DOT"; then + { echo "$as_me:$LINENO: result: $DOT" >&5 +echo "${ECHO_T}$DOT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOT" != "echo dot" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOT 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOT=`echo $DOT | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOT "$DOT${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "fdp", so it can be a program name with args. +set dummy fdp; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_FDP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $FDP in + [\\/]* | ?:[\\/]*) + ac_cv_path_FDP="$FDP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_FDP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FDP" && ac_cv_path_FDP="echo fdp" + ;; +esac +fi +FDP=$ac_cv_path_FDP +if test -n "$FDP"; then + { echo "$as_me:$LINENO: result: $FDP" >&5 +echo "${ECHO_T}$FDP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$FDP" != "echo fdp" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FDP 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + FDP=`echo $FDP | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_FDP "$FDP${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "neato", so it can be a program name with args. +set dummy neato; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_NEATO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $NEATO in + [\\/]* | ?:[\\/]*) + ac_cv_path_NEATO="$NEATO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_NEATO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_NEATO" && ac_cv_path_NEATO="echo neato" + ;; +esac +fi +NEATO=$ac_cv_path_NEATO +if test -n "$NEATO"; then + { echo "$as_me:$LINENO: result: $NEATO" >&5 +echo "${ECHO_T}$NEATO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$NEATO" != "echo neato" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NEATO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + NEATO=`echo $NEATO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_NEATO "$NEATO${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "twopi", so it can be a program name with args. +set dummy twopi; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TWOPI+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TWOPI in + [\\/]* | ?:[\\/]*) + ac_cv_path_TWOPI="$TWOPI" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TWOPI="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_TWOPI" && ac_cv_path_TWOPI="echo twopi" + ;; +esac +fi +TWOPI=$ac_cv_path_TWOPI +if test -n "$TWOPI"; then + { echo "$as_me:$LINENO: result: $TWOPI" >&5 +echo "${ECHO_T}$TWOPI" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$TWOPI" != "echo twopi" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_TWOPI 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + TWOPI=`echo $TWOPI | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_TWOPI "$TWOPI${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "circo", so it can be a program name with args. +set dummy circo; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CIRCO+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CIRCO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CIRCO="$CIRCO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CIRCO="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_CIRCO" && ac_cv_path_CIRCO="echo circo" + ;; +esac +fi +CIRCO=$ac_cv_path_CIRCO +if test -n "$CIRCO"; then + { echo "$as_me:$LINENO: result: $CIRCO" >&5 +echo "${ECHO_T}$CIRCO" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$CIRCO" != "echo circo" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CIRCO 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + CIRCO=`echo $CIRCO | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_CIRCO "$CIRCO${EXEEXT}" +_ACEOF + +fi +for ac_prog in gv gsview32 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GV+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GV in + [\\/]* | ?:[\\/]*) + ac_cv_path_GV="$GV" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GV="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GV=$ac_cv_path_GV +if test -n "$GV"; then + { echo "$as_me:$LINENO: result: $GV" >&5 +echo "${ECHO_T}$GV" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GV" && break +done +test -n "$GV" || GV="echo gv" + +if test "$GV" != "echo gv" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_GV 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + GV=`echo $GV | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_GV "$GV${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "dotty", so it can be a program name with args. +set dummy dotty; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOTTY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOTTY in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOTTY="$DOTTY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOTTY="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DOTTY" && ac_cv_path_DOTTY="echo dotty" + ;; +esac +fi +DOTTY=$ac_cv_path_DOTTY +if test -n "$DOTTY"; then + { echo "$as_me:$LINENO: result: $DOTTY" >&5 +echo "${ECHO_T}$DOTTY" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$DOTTY" != "echo dotty" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DOTTY 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + DOTTY=`echo $DOTTY | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_DOTTY "$DOTTY${EXEEXT}" +_ACEOF + +fi +# Extract the first word of "xdot.py", so it can be a program name with args. +set dummy xdot.py; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_XDOT_PY+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $XDOT_PY in + [\\/]* | ?:[\\/]*) + ac_cv_path_XDOT_PY="$XDOT_PY" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_XDOT_PY="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_XDOT_PY" && ac_cv_path_XDOT_PY="echo xdot.py" + ;; +esac +fi +XDOT_PY=$ac_cv_path_XDOT_PY +if test -n "$XDOT_PY"; then + { echo "$as_me:$LINENO: result: $XDOT_PY" >&5 +echo "${ECHO_T}$XDOT_PY" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$XDOT_PY" != "echo xdot.py" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_XDOT_PY 1 +_ACEOF + + if test "$llvm_cv_os_type" = "MingW" ; then + XDOT_PY=`echo $XDOT_PY | sed 's/^\/\([A-Za-z]\)\//\1:\//' ` + fi + +cat >>confdefs.h <<_ACEOF +#define LLVM_PATH_XDOT_PY "$XDOT_PY${EXEEXT}" +_ACEOF + +fi + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="none" + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { echo "$as_me:$LINENO: result: $PERL" >&5 +echo "${ECHO_T}$PERL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +if test "$PERL" != "none"; then + { echo "$as_me:$LINENO: checking for Perl 5.006 or newer" >&5 +echo $ECHO_N "checking for Perl 5.006 or newer... $ECHO_C" >&6; } + if $PERL -e 'use 5.006;' 2>&1 > /dev/null; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + PERL=none + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + fi +fi + + +if test x"$PERL" = xnone; then + HAVE_PERL=0 + + { { echo "$as_me:$LINENO: error: perl is required but was not found, please install it" >&5 +echo "$as_me: error: perl is required but was not found, please install it" >&2;} + { (exit 1); exit 1; }; } +else + HAVE_PERL=1 + +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done +IFS=$as_save_IFS + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +case "$INSTALL" in + [\\/$]* | ?:[\\/]* ) ;; + *) INSTALL="\\\$(TOPSRCDIR)/$INSTALL" ;; +esac + +# Extract the first word of "bzip2", so it can be a program name with args. +set dummy bzip2; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_BZIP2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BZIP2 in + [\\/]* | ?:[\\/]*) + ac_cv_path_BZIP2="$BZIP2" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_BZIP2="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +BZIP2=$ac_cv_path_BZIP2 +if test -n "$BZIP2"; then + { echo "$as_me:$LINENO: result: $BZIP2" >&5 +echo "${ECHO_T}$BZIP2" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "cat", so it can be a program name with args. +set dummy cat; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_CAT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $CAT in + [\\/]* | ?:[\\/]*) + ac_cv_path_CAT="$CAT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +CAT=$ac_cv_path_CAT +if test -n "$CAT"; then + { echo "$as_me:$LINENO: result: $CAT" >&5 +echo "${ECHO_T}$CAT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "doxygen", so it can be a program name with args. +set dummy doxygen; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_DOXYGEN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $DOXYGEN in + [\\/]* | ?:[\\/]*) + ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +DOXYGEN=$ac_cv_path_DOXYGEN +if test -n "$DOXYGEN"; then + { echo "$as_me:$LINENO: result: $DOXYGEN" >&5 +echo "${ECHO_T}$DOXYGEN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "groff", so it can be a program name with args. +set dummy groff; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GROFF=$ac_cv_path_GROFF +if test -n "$GROFF"; then + { echo "$as_me:$LINENO: result: $GROFF" >&5 +echo "${ECHO_T}$GROFF" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "gzip", so it can be a program name with args. +set dummy gzip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GZIPBIN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GZIPBIN in + [\\/]* | ?:[\\/]*) + ac_cv_path_GZIPBIN="$GZIPBIN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GZIPBIN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GZIPBIN=$ac_cv_path_GZIPBIN +if test -n "$GZIPBIN"; then + { echo "$as_me:$LINENO: result: $GZIPBIN" >&5 +echo "${ECHO_T}$GZIPBIN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pod2html", so it can be a program name with args. +set dummy pod2html; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_POD2HTML+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $POD2HTML in + [\\/]* | ?:[\\/]*) + ac_cv_path_POD2HTML="$POD2HTML" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_POD2HTML="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +POD2HTML=$ac_cv_path_POD2HTML +if test -n "$POD2HTML"; then + { echo "$as_me:$LINENO: result: $POD2HTML" >&5 +echo "${ECHO_T}$POD2HTML" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pod2man", so it can be a program name with args. +set dummy pod2man; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_POD2MAN+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $POD2MAN in + [\\/]* | ?:[\\/]*) + ac_cv_path_POD2MAN="$POD2MAN" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_POD2MAN="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +POD2MAN=$ac_cv_path_POD2MAN +if test -n "$POD2MAN"; then + { echo "$as_me:$LINENO: result: $POD2MAN" >&5 +echo "${ECHO_T}$POD2MAN" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "pdfroff", so it can be a program name with args. +set dummy pdfroff; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PDFROFF+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PDFROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_PDFROFF="$PDFROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PDFROFF="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PDFROFF=$ac_cv_path_PDFROFF +if test -n "$PDFROFF"; then + { echo "$as_me:$LINENO: result: $PDFROFF" >&5 +echo "${ECHO_T}$PDFROFF" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +# Extract the first word of "runtest", so it can be a program name with args. +set dummy runtest; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_RUNTEST+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $RUNTEST in + [\\/]* | ?:[\\/]*) + ac_cv_path_RUNTEST="$RUNTEST" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_RUNTEST="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +RUNTEST=$ac_cv_path_RUNTEST +if test -n "$RUNTEST"; then + { echo "$as_me:$LINENO: result: $RUNTEST" >&5 +echo "${ECHO_T}$RUNTEST" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + +no_itcl=true +{ echo "$as_me:$LINENO: checking for the tclsh program in tclinclude directory" >&5 +echo $ECHO_N "checking for the tclsh program in tclinclude directory... $ECHO_C" >&6; } + +# Check whether --with-tclinclude was given. +if test "${with_tclinclude+set}" = set; then + withval=$with_tclinclude; with_tclinclude=${withval} +else + with_tclinclude='' +fi + +if test "${ac_cv_path_tclsh+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +if test x"${with_tclinclude}" != x ; then + if test -f ${with_tclinclude}/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}; pwd)` + elif test -f ${with_tclinclude}/src/tclsh ; then + ac_cv_path_tclsh=`(cd ${with_tclinclude}/src; pwd)` + else + { { echo "$as_me:$LINENO: error: ${with_tclinclude} directory doesn't contain tclsh" >&5 +echo "$as_me: error: ${with_tclinclude} directory doesn't contain tclsh" >&2;} + { (exit 1); exit 1; }; } + fi +fi +fi + + +if test x"${ac_cv_path_tclsh}" = x ; then + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } + for ac_prog in tclsh8.4 tclsh8.4.8 tclsh8.4.7 tclsh8.4.6 tclsh8.4.5 tclsh8.4.4 tclsh8.4.3 tclsh8.4.2 tclsh8.4.1 tclsh8.4.0 tclsh8.3 tclsh8.3.5 tclsh8.3.4 tclsh8.3.3 tclsh8.3.2 tclsh8.3.1 tclsh8.3.0 tclsh +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_TCLSH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $TCLSH in + [\\/]* | ?:[\\/]*) + ac_cv_path_TCLSH="$TCLSH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_TCLSH="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +TCLSH=$ac_cv_path_TCLSH +if test -n "$TCLSH"; then + { echo "$as_me:$LINENO: result: $TCLSH" >&5 +echo "${ECHO_T}$TCLSH" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$TCLSH" && break +done + + if test x"${TCLSH}" = x ; then + ac_cv_path_tclsh=''; + else + ac_cv_path_tclsh="${TCLSH}"; + fi +else + { echo "$as_me:$LINENO: result: ${ac_cv_path_tclsh}" >&5 +echo "${ECHO_T}${ac_cv_path_tclsh}" >&6; } + TCLSH="${ac_cv_path_tclsh}" + +fi + +# Extract the first word of "zip", so it can be a program name with args. +set dummy zip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_ZIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +ZIP=$ac_cv_path_ZIP +if test -n "$ZIP"; then + { echo "$as_me:$LINENO: result: $ZIP" >&5 +echo "${ECHO_T}$ZIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +for ac_prog in ocamlc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLC="$OCAMLC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLC=$ac_cv_path_OCAMLC +if test -n "$OCAMLC"; then + { echo "$as_me:$LINENO: result: $OCAMLC" >&5 +echo "${ECHO_T}$OCAMLC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLC" && break +done + +for ac_prog in ocamlopt +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLOPT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLOPT in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLOPT="$OCAMLOPT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLOPT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLOPT=$ac_cv_path_OCAMLOPT +if test -n "$OCAMLOPT"; then + { echo "$as_me:$LINENO: result: $OCAMLOPT" >&5 +echo "${ECHO_T}$OCAMLOPT" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLOPT" && break +done + +for ac_prog in ocamldep +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDEP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDEP in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDEP="$OCAMLDEP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDEP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDEP=$ac_cv_path_OCAMLDEP +if test -n "$OCAMLDEP"; then + { echo "$as_me:$LINENO: result: $OCAMLDEP" >&5 +echo "${ECHO_T}$OCAMLDEP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDEP" && break +done + +for ac_prog in ocamldoc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_OCAMLDOC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $OCAMLDOC in + [\\/]* | ?:[\\/]*) + ac_cv_path_OCAMLDOC="$OCAMLDOC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_OCAMLDOC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +OCAMLDOC=$ac_cv_path_OCAMLDOC +if test -n "$OCAMLDOC"; then + { echo "$as_me:$LINENO: result: $OCAMLDOC" >&5 +echo "${ECHO_T}$OCAMLDOC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$OCAMLDOC" && break +done + +for ac_prog in gas as +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_GAS+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $GAS in + [\\/]* | ?:[\\/]*) + ac_cv_path_GAS="$GAS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GAS="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +GAS=$ac_cv_path_GAS +if test -n "$GAS"; then + { echo "$as_me:$LINENO: result: $GAS" >&5 +echo "${ECHO_T}$GAS" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$GAS" && break +done + + +{ echo "$as_me:$LINENO: checking for linker version" >&5 +echo $ECHO_N "checking for linker version... $ECHO_C" >&6; } +if test "${llvm_cv_link_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + version_string="$(ld -v 2>&1 | head -1)" + + # Check for ld64. + if (echo "$version_string" | grep -q "ld64"); then + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#.*ld64-\([^ ]*\)#\1#") + else + llvm_cv_link_version=$(echo "$version_string" | sed -e "s#[^0-9]*\([0-9.]*\).*#\1#") + fi + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_version" >&5 +echo "${ECHO_T}$llvm_cv_link_version" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HOST_LINK_VERSION "$llvm_cv_link_version" +_ACEOF + + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,-R option" >&5 +echo $ECHO_N "checking for compiler -Wl,-R option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_r+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-R." + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_r=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_r=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_r" >&5 +echo "${ECHO_T}$llvm_cv_link_use_r" >&6; } +if test "$llvm_cv_link_use_r" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_R 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,-export-dynamic option" >&5 +echo $ECHO_N "checking for compiler -Wl,-export-dynamic option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_export_dynamic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + CFLAGS="$CFLAGS -Wl,-export-dynamic" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_export_dynamic=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_export_dynamic=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_export_dynamic" >&5 +echo "${ECHO_T}$llvm_cv_link_use_export_dynamic" >&6; } +if test "$llvm_cv_link_use_export_dynamic" = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LINK_EXPORT_DYNAMIC 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for compiler -Wl,--version-script option" >&5 +echo $ECHO_N "checking for compiler -Wl,--version-script option... $ECHO_C" >&6; } +if test "${llvm_cv_link_use_version_script+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + oldcflags="$CFLAGS" + + # The following code is from the autoconf manual, + # "11.13: Limitations of Usual Tools". + # Create a temporary directory $tmp in $TMPDIR (default /tmp). + # Use mktemp if possible; otherwise fall back on mkdir, + # with $RANDOM to make collisions less likely. + : ${TMPDIR=/tmp} + { + tmp=` + (umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null + ` && + test -n "$tmp" && test -d "$tmp" + } || { + tmp=$TMPDIR/foo$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || exit $? + + echo "{" > "$tmp/export.map" + echo " global: main;" >> "$tmp/export.map" + echo " local: *;" >> "$tmp/export.map" + echo "};" >> "$tmp/export.map" + + CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_link_use_version_script=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_link_use_version_script=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + rm "$tmp/export.map" + rmdir "$tmp" + CFLAGS="$oldcflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_version_script" >&5 +echo "${ECHO_T}$llvm_cv_link_use_version_script" >&6; } +if test "$llvm_cv_link_use_version_script" = yes ; then + HAVE_LINK_VERSION_SCRIPT=1 + + fi + + + + +{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 +echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } +if test "${ac_cv_c_const+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset x; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *ccp; + char **p; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + ccp = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++ccp; + p = (char**) ccp; + ccp = (char const *const *) p; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !x[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_const=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_c_const=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 +echo "${ECHO_T}$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +cat >>confdefs.h <<\_ACEOF +#define const +_ACEOF + +fi + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +# Check whether --enable-ltdl-install was given. +if test "${enable_ltdl_install+set}" = set; then + enableval=$enable_ltdl_install; +fi + + + + +if test x"${enable_ltdl_install-no}" != xno; then + INSTALL_LTDL_TRUE= + INSTALL_LTDL_FALSE='#' +else + INSTALL_LTDL_TRUE='#' + INSTALL_LTDL_FALSE= +fi + + + +if test x"${enable_ltdl_convenience-no}" != xno; then + CONVENIENCE_LTDL_TRUE= + CONVENIENCE_LTDL_FALSE='#' +else + CONVENIENCE_LTDL_TRUE='#' + CONVENIENCE_LTDL_FALSE= +fi + + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='.dylib' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + + +{ echo "$as_me:$LINENO: checking which extension is used for loadable modules" >&5 +echo $ECHO_N "checking which extension is used for loadable modules... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +module=yes +eval libltdl_cv_shlibext=$shrext_cmds + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibext" >&5 +echo "${ECHO_T}$libltdl_cv_shlibext" >&6; } +if test -n "$libltdl_cv_shlibext"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking which variable specifies run-time library path" >&5 +echo $ECHO_N "checking which variable specifies run-time library path... $ECHO_C" >&6; } +if test "${libltdl_cv_shlibpath_var+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_shlibpath_var="$shlibpath_var" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_shlibpath_var" >&5 +echo "${ECHO_T}$libltdl_cv_shlibpath_var" >&6; } +if test -n "$libltdl_cv_shlibpath_var"; then + +cat >>confdefs.h <<_ACEOF +#define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for the default library search path" >&5 +echo $ECHO_N "checking for the default library search path... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_search_path+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_search_path" >&5 +echo "${ECHO_T}$libltdl_cv_sys_search_path" >&6; } +if test -n "$libltdl_cv_sys_search_path"; then + sys_search_path= + for dir in $libltdl_cv_sys_search_path; do + if test -z "$sys_search_path"; then + sys_search_path="$dir" + else + sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" + fi + done + +cat >>confdefs.h <<_ACEOF +#define LTDL_SYSSEARCHPATH "$sys_search_path" +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${libltdl_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_objdir="$objdir" + if test -n "$objdir"; then + : + else + rm -f .libs 2>/dev/null + mkdir .libs 2>/dev/null + if test -d .libs; then + libltdl_cv_objdir=.libs + else + # MS-DOS does not allow filenames that begin with a dot. + libltdl_cv_objdir=_libs + fi + rmdir .libs 2>/dev/null + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_objdir" >&5 +echo "${ECHO_T}$libltdl_cv_objdir" >&6; } + +cat >>confdefs.h <<_ACEOF +#define LTDL_OBJDIR "$libltdl_cv_objdir/" +_ACEOF + + + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + + +{ echo "$as_me:$LINENO: checking whether libtool supports -dlopen/-dlpreopen" >&5 +echo $ECHO_N "checking whether libtool supports -dlopen/-dlpreopen... $ECHO_C" >&6; } +if test "${libltdl_cv_preloaded_symbols+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$lt_cv_sys_global_symbol_pipe"; then + libltdl_cv_preloaded_symbols=yes + else + libltdl_cv_preloaded_symbols=no + fi + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_preloaded_symbols" >&5 +echo "${ECHO_T}$libltdl_cv_preloaded_symbols" >&6; } +if test x"$libltdl_cv_preloaded_symbols" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRELOADED_SYMBOLS 1 +_ACEOF + +fi + +LIBADD_DL= + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case declares shl_load. + For example, HP-UX 11i declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SHL_LOAD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_DLFCN_H +# include +#endif + +int +main () +{ +dlopen(0, 0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + libltdl_cv_func_dlopen="yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLD 1 +_ACEOF + + LIBADD_DL="$LIBADD_DL -ldld" +else + { echo "$as_me:$LINENO: checking for _dyld_func_lookup" >&5 +echo $ECHO_N "checking for _dyld_func_lookup... $ECHO_C" >&6; } +if test "${ac_cv_func__dyld_func_lookup+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define _dyld_func_lookup to an innocuous variant, in case declares _dyld_func_lookup. + For example, HP-UX 11i declares gettimeofday. */ +#define _dyld_func_lookup innocuous__dyld_func_lookup + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char _dyld_func_lookup (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef _dyld_func_lookup + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _dyld_func_lookup (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub__dyld_func_lookup || defined __stub____dyld_func_lookup +choke me +#endif + +int +main () +{ +return _dyld_func_lookup (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func__dyld_func_lookup=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func__dyld_func_lookup=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func__dyld_func_lookup" >&5 +echo "${ECHO_T}$ac_cv_func__dyld_func_lookup" >&6; } +if test $ac_cv_func__dyld_func_lookup = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DYLD 1 +_ACEOF + +fi + + +fi + + +fi + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi + + +fi + + +fi + + +if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes +then + lt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + +for ac_func in dlerror +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + LIBS="$lt_save_LIBS" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +{ echo "$as_me:$LINENO: checking for _ prefix in compiled symbols" >&5 +echo $ECHO_N "checking for _ prefix in compiled symbols... $ECHO_C" >&6; } +if test "${ac_cv_sys_symbol_underscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_symbol_underscore=no + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + ac_nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$ac_nlist"; then + # See whether the symbols have a leading underscore. + if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then + ac_cv_sys_symbol_underscore=yes + else + if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then + : + else + echo "configure: cannot find nm_test_func in $ac_nlist" >&5 + fi + fi + else + echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "configure: failed program was:" >&5 + cat conftest.c >&5 + fi + rm -rf conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_sys_symbol_underscore" >&5 +echo "${ECHO_T}$ac_cv_sys_symbol_underscore" >&6; } + + +if test x"$ac_cv_sys_symbol_underscore" = xyes; then + if test x"$libltdl_cv_func_dlopen" = xyes || + test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then + { echo "$as_me:$LINENO: checking whether we have to add an underscore for dlsym" >&5 +echo $ECHO_N "checking whether we have to add an underscore for dlsym... $ECHO_C" >&6; } +if test "${libltdl_cv_need_uscore+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + libltdl_cv_need_uscore=unknown + save_LIBS="$LIBS" + LIBS="$LIBS $LIBADD_DL" + if test "$cross_compiling" = yes; then : + libltdl_cv_need_uscore=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; + x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; + x$lt_dlunknown|x*) ;; + esac + else : + # compilation failed + + fi +fi +rm -fr conftest* + + LIBS="$save_LIBS" + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_need_uscore" >&5 +echo "${ECHO_T}$libltdl_cv_need_uscore" >&6; } + fi +fi + +if test x"$libltdl_cv_need_uscore" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_USCORE 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether deplibs are loaded by dlopen" >&5 +echo $ECHO_N "checking whether deplibs are loaded by dlopen... $ECHO_C" >&6; } +if test "${libltdl_cv_sys_dlopen_deplibs+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # PORTME does your system automatically load deplibs for dlopen? + # or its logical equivalent (e.g. shl_load for HP-UX < 11) + # For now, we just catch OSes we know something about -- in the + # future, we'll try test this programmatically. + libltdl_cv_sys_dlopen_deplibs=unknown + case "$host_os" in + aix3*|aix4.1.*|aix4.2.*) + # Unknown whether this is true for these versions of AIX, but + # we want this `case' here to explicitly catch those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + aix[45]*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + darwin*) + # Assuming the user has installed a libdl from somewhere, this is true + # If you are looking for one http://www.opendarwin.org/projects/dlcompat + libltdl_cv_sys_dlopen_deplibs=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + # GNU and its variants, using gnu ld.so (Glibc) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + hpux10*|hpux11*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + interix*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + irix[12345]*|irix6.[01]*) + # Catch all versions of IRIX before 6.2, and indicate that we don't + # know how it worked for any of those versions. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + irix*) + # The case above catches anything before 6.2, and it's known that + # at 6.2 and later dlopen does load deplibs. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + netbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + openbsd*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + osf[1234]*) + # dlopen did load deplibs (at least at 4.x), but until the 5.x series, + # it did *not* use an RPATH in a shared library to find objects the + # library depends on, so we explictly say `no'. + libltdl_cv_sys_dlopen_deplibs=no + ;; + osf5.0|osf5.0a|osf5.1) + # dlopen *does* load deplibs and with the right loader patch applied + # it even uses RPATH in a shared library to search for shared objects + # that the library depends on, but there's no easy way to know if that + # patch is installed. Since this is the case, all we can really + # say is unknown -- it depends on the patch being installed. If + # it is, this changes to `yes'. Without it, it would be `no'. + libltdl_cv_sys_dlopen_deplibs=unknown + ;; + osf*) + # the two cases above should catch all versions of osf <= 5.1. Read + # the comments above for what we know about them. + # At > 5.1, deplibs are loaded *and* any RPATH in a shared library + # is used to find them so we can finally say `yes'. + libltdl_cv_sys_dlopen_deplibs=yes + ;; + solaris*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + libltdl_cv_sys_dlopen_deplibs=yes + ;; + esac + +fi +{ echo "$as_me:$LINENO: result: $libltdl_cv_sys_dlopen_deplibs" >&5 +echo "${ECHO_T}$libltdl_cv_sys_dlopen_deplibs" >&6; } +if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then + +cat >>confdefs.h <<\_ACEOF +#define LTDL_DLOPEN_DEPLIBS 1 +_ACEOF + +fi + + +for ac_header in argz.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking for error_t" >&5 +echo $ECHO_N "checking for error_t... $ECHO_C" >&6; } +if test "${ac_cv_type_error_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if HAVE_ARGZ_H +# include +#endif + +typedef error_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_error_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_error_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_error_t" >&5 +echo "${ECHO_T}$ac_cv_type_error_t" >&6; } +if test $ac_cv_type_error_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ERROR_T 1 +_ACEOF + + +else + +cat >>confdefs.h <<\_ACEOF +#define error_t int +_ACEOF + +fi + + + + + + + +for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + + + + + + + + + + + + + + + + + + + + +for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ + stdio.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in string.h strings.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + break +fi + +done + + + + +for ac_func in strchr index +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in strrchr rindex +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memcpy bcopy +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + break +fi +done + + + +for ac_func in memmove strcmp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in closedir opendir readdir +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +if test "$WITH_LLVMGCCDIR" = "default" ; then + LLVMGCC="llvm-gcc${EXEEXT}" + LLVMGXX="llvm-g++${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + LLVMGXXCOMMAND="$LLVMGXX" + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + + # Extract the first word of "$LLVMGCC", so it can be a program name with args. +set dummy $LLVMGCC; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_LLVMGCC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $LLVMGCC in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVMGCC="$LLVMGCC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_LLVMGCC="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +LLVMGCC=$ac_cv_path_LLVMGCC +if test -n "$LLVMGCC"; then + { echo "$as_me:$LINENO: result: $LLVMGCC" >&5 +echo "${ECHO_T}$LLVMGCC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + # Extract the first word of "$LLVMGXX", so it can be a program name with args. +set dummy $LLVMGXX; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_LLVMGXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $LLVMGXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_LLVMGXX="$LLVMGXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_LLVMGXX="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +LLVMGXX=$ac_cv_path_LLVMGXX +if test -n "$LLVMGXX"; then + { echo "$as_me:$LINENO: result: $LLVMGXX" >&5 +echo "${ECHO_T}$LLVMGXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +else + if test -z "$LLVMGCC"; then + LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}" + LLVMGCCCOMMAND="$LLVMGCC" + fi + if test -z "$LLVMGXX"; then + LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}" + LLVMGXXCOMMAND="$LLVMGXX" + fi + + LLVMGCC=$LLVMGCC + + LLVMGXX=$LLVMGXX + + LLVMGCCCOMMAND=$LLVMGCCCOMMAND + + LLVMGXXCOMMAND=$LLVMGXXCOMMAND + +fi + + +# Check whether --with-llvmcc was given. +if test "${with_llvmcc+set}" = set; then + withval=$with_llvmcc; +else + with_llvmcc=check +fi + +{ echo "$as_me:$LINENO: checking LLVM capable compiler" >&5 +echo $ECHO_N "checking LLVM capable compiler... $ECHO_C" >&6; } +if test "$with_llvmcc" != "check"; then + if (test "$with_llvmcc" != "llvm-gcc" && + test "$with_llvmcc" != "clang" && + test "$with_llvmcc" != "none"); then + { { echo "$as_me:$LINENO: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&5 +echo "$as_me: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&2;} + { (exit 1); exit 1; }; } + fi + WITH_LLVMCC="$with_llvmcc" +elif test -n "$LLVMGCC"; then + WITH_LLVMCC=llvm-gcc +elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then + WITH_LLVMCC=clang +else + WITH_LLVMCC=none +fi +{ echo "$as_me:$LINENO: result: $WITH_LLVMCC" >&5 +echo "${ECHO_T}$WITH_LLVMCC" >&6; } +LLVMCC_OPTION=$WITH_LLVMCC + + +{ echo "$as_me:$LINENO: checking tool compatibility" >&5 +echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; } + +ICC=no +IXX=no +case $CC in + icc*|icpc*) + ICC=yes + IXX=yes + ;; + *) + ;; +esac + +if test "$GCC" != "yes" && test "$ICC" != "yes" +then + { { echo "$as_me:$LINENO: error: gcc|icc required but not found" >&5 +echo "$as_me: error: gcc|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GXX" != "yes" && test "$IXX" != "yes" +then + { { echo "$as_me:$LINENO: error: g++|clang++|icc required but not found" >&5 +echo "$as_me: error: g++|clang++|icc required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +if test "$GCC" = "yes" +then + cat >conftest.$ac_ext <<_ACEOF +#if !defined(__GNUC__) || __GNUC__ < 3 +#error Unsupported GCC version +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { { echo "$as_me:$LINENO: error: gcc 3.x required, but you have a lower version" >&5 +echo "$as_me: error: gcc 3.x required, but you have a lower version" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if test -z "$llvm_cv_gnu_make_command" +then + { { echo "$as_me:$LINENO: error: GNU Make required but not found" >&5 +echo "$as_me: error: GNU Make required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } + +{ echo "$as_me:$LINENO: checking optional compiler flags" >&5 +echo $ECHO_N "checking optional compiler flags... $ECHO_C" >&6; } +NO_VARIADIC_MACROS=`$CXX -Wno-variadic-macros -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-variadic-macros` + +NO_MISSING_FIELD_INITIALIZERS=`$CXX -Wno-missing-field-initializers -fsyntax-only -xc /dev/null 2>/dev/null && echo -Wno-missing-field-initializers` + +{ echo "$as_me:$LINENO: result: $NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS" >&5 +echo "${ECHO_T}$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS" >&6; } + + + +{ echo "$as_me:$LINENO: checking for sin in -lm" >&5 +echo $ECHO_N "checking for sin in -lm... $ECHO_C" >&6; } +if test "${ac_cv_lib_m_sin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sin (); +int +main () +{ +return sin (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_sin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_m_sin=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_m_sin" >&5 +echo "${ECHO_T}$ac_cv_lib_m_sin" >&6; } +if test $ac_cv_lib_m_sin = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +if test "$llvm_cv_os_type" = "MingW" ; then + +{ echo "$as_me:$LINENO: checking for main in -limagehlp" >&5 +echo $ECHO_N "checking for main in -limagehlp... $ECHO_C" >&6; } +if test "${ac_cv_lib_imagehlp_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-limagehlp $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_imagehlp_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_imagehlp_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_imagehlp_main" >&5 +echo "${ECHO_T}$ac_cv_lib_imagehlp_main" >&6; } +if test $ac_cv_lib_imagehlp_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBIMAGEHLP 1 +_ACEOF + + LIBS="-limagehlp $LIBS" + +fi + + +{ echo "$as_me:$LINENO: checking for main in -lpsapi" >&5 +echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; } +if test "${ac_cv_lib_psapi_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpsapi $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_psapi_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_psapi_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_psapi_main" >&5 +echo "${ECHO_T}$ac_cv_lib_psapi_main" >&6; } +if test $ac_cv_lib_psapi_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPSAPI 1 +_ACEOF + + LIBS="-lpsapi $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing dlopen" >&5 +echo $ECHO_N "checking for library containing dlopen... $ECHO_C" >&6; } +if test "${ac_cv_search_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_dlopen=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_dlopen+set}" = set; then + break +fi +done +if test "${ac_cv_search_dlopen+set}" = set; then + : +else + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_dlopen" >&5 +echo "${ECHO_T}$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DLOPEN 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: dlopen() not found - disabling plugin support" >&5 +echo "$as_me: WARNING: dlopen() not found - disabling plugin support" >&2;} +fi + + +if test "$llvm_cv_enable_libffi" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing ffi_call" >&5 +echo $ECHO_N "checking for library containing ffi_call... $ECHO_C" >&6; } +if test "${ac_cv_search_ffi_call+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ffi_call (); +int +main () +{ +return ffi_call (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ffi; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_ffi_call=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_ffi_call+set}" = set; then + break +fi +done +if test "${ac_cv_search_ffi_call+set}" = set; then + : +else + ac_cv_search_ffi_call=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_ffi_call" >&5 +echo "${ECHO_T}$ac_cv_search_ffi_call" >&6; } +ac_res=$ac_cv_search_ffi_call +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FFI_CALL 1 +_ACEOF + +else + { { echo "$as_me:$LINENO: error: libffi not found - configure without --enable-libffi to compile without it" >&5 +echo "$as_me: error: libffi not found - configure without --enable-libffi to compile without it" >&2;} + { (exit 1); exit 1; }; } +fi + +fi + +{ echo "$as_me:$LINENO: checking for library containing mallinfo" >&5 +echo $ECHO_N "checking for library containing mallinfo... $ECHO_C" >&6; } +if test "${ac_cv_search_mallinfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mallinfo (); +int +main () +{ +return mallinfo (); + ; + return 0; +} +_ACEOF +for ac_lib in '' malloc; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_mallinfo=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_mallinfo+set}" = set; then + break +fi +done +if test "${ac_cv_search_mallinfo+set}" = set; then + : +else + ac_cv_search_mallinfo=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_mallinfo" >&5 +echo "${ECHO_T}$ac_cv_search_mallinfo" >&6; } +ac_res=$ac_cv_search_mallinfo +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MALLINFO 1 +_ACEOF + +fi + + +if test "$ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + +{ echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 +echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6; } +if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_init (); +int +main () +{ +return pthread_mutex_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_mutex_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_pthread_pthread_mutex_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6; } +if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_mutex_lock" >&5 +echo $ECHO_N "checking for library containing pthread_mutex_lock... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_mutex_lock (); +int +main () +{ +return pthread_mutex_lock (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_mutex_lock=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_mutex_lock+set}" = set; then + : +else + ac_cv_search_pthread_mutex_lock=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_mutex_lock" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_mutex_lock" >&6; } +ac_res=$ac_cv_search_pthread_mutex_lock +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_MUTEX_LOCK 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_rwlock_init" >&5 +echo $ECHO_N "checking for library containing pthread_rwlock_init... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_rwlock_init (); +int +main () +{ +return pthread_rwlock_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_rwlock_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then + : +else + ac_cv_search_pthread_rwlock_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_rwlock_init" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_rwlock_init" >&6; } +ac_res=$ac_cv_search_pthread_rwlock_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_RWLOCK_INIT 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for library containing pthread_getspecific" >&5 +echo $ECHO_N "checking for library containing pthread_getspecific... $ECHO_C" >&6; } +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_getspecific (); +int +main () +{ +return pthread_getspecific (); + ; + return 0; +} +_ACEOF +for ac_lib in '' pthread; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_pthread_getspecific=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_pthread_getspecific+set}" = set; then + break +fi +done +if test "${ac_cv_search_pthread_getspecific+set}" = set; then + : +else + ac_cv_search_pthread_getspecific=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_getspecific" >&5 +echo "${ECHO_T}$ac_cv_search_pthread_getspecific" >&6; } +ac_res=$ac_cv_search_pthread_getspecific +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PTHREAD_GETSPECIFIC 1 +_ACEOF + +fi + +fi + + +# Check whether --with-udis86 was given. +if test "${with_udis86+set}" = set; then + withval=$with_udis86; + USE_UDIS86=1 + + case "$withval" in + /usr/lib|yes) ;; + *) LDFLAGS="$LDFLAGS -L${withval}" ;; + esac + +{ echo "$as_me:$LINENO: checking for ud_init in -ludis86" >&5 +echo $ECHO_N "checking for ud_init in -ludis86... $ECHO_C" >&6; } +if test "${ac_cv_lib_udis86_ud_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ludis86 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ud_init (); +int +main () +{ +return ud_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_udis86_ud_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_udis86_ud_init=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_udis86_ud_init" >&5 +echo "${ECHO_T}$ac_cv_lib_udis86_ud_init" >&6; } +if test $ac_cv_lib_udis86_ud_init = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBUDIS86 1 +_ACEOF + + LIBS="-ludis86 $LIBS" + +else + + echo "Error! You need to have libudis86 around." + exit -1 + +fi + + +else + USE_UDIS86=0 + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_UDIS86 $USE_UDIS86 +_ACEOF + + + +# Check whether --with-oprofile was given. +if test "${with_oprofile+set}" = set; then + withval=$with_oprofile; + USE_OPROFILE=1 + + case "$withval" in + /usr|yes) llvm_cv_oppath=/usr/lib/oprofile ;; + no) llvm_cv_oppath= + USE_OPROFILE=0 + ;; + *) llvm_cv_oppath="${withval}/lib/oprofile" + CPPFLAGS="-I${withval}/include";; + esac + if test -n "$llvm_cv_oppath" ; then + LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}" + { echo "$as_me:$LINENO: checking for library containing bfd_init" >&5 +echo $ECHO_N "checking for library containing bfd_init... $ECHO_C" >&6; } +if test "${ac_cv_search_bfd_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bfd_init (); +int +main () +{ +return bfd_init (); + ; + return 0; +} +_ACEOF +for ac_lib in '' bfd; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_bfd_init=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_bfd_init+set}" = set; then + break +fi +done +if test "${ac_cv_search_bfd_init+set}" = set; then + : +else + ac_cv_search_bfd_init=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_bfd_init" >&5 +echo "${ECHO_T}$ac_cv_search_bfd_init" >&6; } +ac_res=$ac_cv_search_bfd_init +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for library containing op_open_agent" >&5 +echo $ECHO_N "checking for library containing op_open_agent... $ECHO_C" >&6; } +if test "${ac_cv_search_op_open_agent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char op_open_agent (); +int +main () +{ +return op_open_agent (); + ; + return 0; +} +_ACEOF +for ac_lib in '' opagent; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_op_open_agent=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_op_open_agent+set}" = set; then + break +fi +done +if test "${ac_cv_search_op_open_agent+set}" = set; then + : +else + ac_cv_search_op_open_agent=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_op_open_agent" >&5 +echo "${ECHO_T}$ac_cv_search_op_open_agent" >&6; } +ac_res=$ac_cv_search_op_open_agent +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +else + + echo "Error! You need to have libopagent around." + exit -1 + +fi + + if test "${ac_cv_header_opagent_h+set}" = set; then + { echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking opagent.h usability" >&5 +echo $ECHO_N "checking opagent.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking opagent.h presence" >&5 +echo $ECHO_N "checking opagent.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: opagent.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: opagent.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: opagent.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: opagent.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: opagent.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: opagent.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: opagent.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: opagent.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: opagent.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for opagent.h" >&5 +echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; } +if test "${ac_cv_header_opagent_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_opagent_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_opagent_h" >&5 +echo "${ECHO_T}$ac_cv_header_opagent_h" >&6; } + +fi +if test $ac_cv_header_opagent_h = yes; then + : +else + + echo "Error! You need to have opagent.h around." + exit -1 + +fi + + + fi + +else + + USE_OPROFILE=0 + + +fi + + +cat >>confdefs.h <<_ACEOF +#define USE_OPROFILE $USE_OPROFILE +_ACEOF + + + + + + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 +echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { echo "$as_me:$LINENO: checking for library containing opendir" >&5 +echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } +if test "${ac_cv_search_opendir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_opendir=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then + : +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 +echo "${ECHO_T}$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ echo "$as_me:$LINENO: checking for MAP_ANONYMOUS vs. MAP_ANON" >&5 +echo $ECHO_N "checking for MAP_ANONYMOUS vs. MAP_ANON... $ECHO_C" >&6; } +if test "${ac_cv_header_mmap_anon+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +int +main () +{ +mmap (0, 1, PROT_READ, MAP_ANONYMOUS, -1, 0); return (0); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_mmap_anon=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_mmap_anon=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_mmap_anon" >&5 +echo "${ECHO_T}$ac_cv_header_mmap_anon" >&6; } +if test "$ac_cv_header_mmap_anon" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_ANONYMOUS 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether stat file-mode macros are broken" >&5 +echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6; } +if test "${ac_cv_header_stat_broken+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +#if defined S_ISBLK && defined S_IFDIR +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined S_ISBLK && defined S_IFCHR +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined S_ISLNK && defined S_IFREG +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined S_ISSOCK && defined S_IFREG +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "You lose" >/dev/null 2>&1; then + ac_cv_header_stat_broken=yes +else + ac_cv_header_stat_broken=no +fi +rm -f conftest* + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5 +echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; } +if test $ac_cv_header_stat_broken = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STAT_MACROS_BROKEN 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 +echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_wait_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_sys_wait_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_sys_wait_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SYS_WAIT_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 +echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } +if test "${ac_cv_header_time+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_time=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_time=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 +echo "${ECHO_T}$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +cat >>confdefs.h <<\_ACEOF +#define TIME_WITH_SYS_TIME 1 +_ACEOF + +fi + + + + + + + + +for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.h limits.h link.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + +for ac_header in malloc.h setjmp.h signal.h stdint.h termios.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in utime.h windows.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + +for ac_header in sys/mman.h sys/param.h sys/resource.h sys/time.h sys/uio.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + +for ac_header in sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in valgrind/valgrind.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in fenv.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +if test "$ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then + +for ac_header in pthread.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + HAVE_PTHREAD=1 + +else + HAVE_PTHREAD=0 + +fi + +done + +else + HAVE_PTHREAD=0 + +fi + +if test "$llvm_cv_enable_libffi" = "yes" ; then + + +for ac_header in ffi.h ffi/ffi.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + + +for ac_header in CrashReporterClient.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ echo "$as_me:$LINENO: checking __crashreporter_info__" >&5 +echo $ECHO_N "checking __crashreporter_info__... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +extern const char *__crashreporter_info__; + int main() { + __crashreporter_info__ = "test"; + return 0; + } + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CRASHREPORTER_INFO 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CRASHREPORTER_INFO 0 +_ACEOF + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + + + + { echo "$as_me:$LINENO: checking for HUGE_VAL sanity" >&5 +echo $ECHO_N "checking for HUGE_VAL sanity... $ECHO_C" >&6; } +if test "${ac_cv_huge_val_sanity+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ac_save_CXXFLAGS=$CXXFLAGS + CXXFLAGS=-pedantic + if test "$cross_compiling" = yes; then + ac_cv_huge_val_sanity=yes +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +double x = HUGE_VAL; return x != x; + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_huge_val_sanity=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_huge_val_sanity=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + CXXFLAGS=$ac_save_CXXFLAGS + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_huge_val_sanity" >&5 +echo "${ECHO_T}$ac_cv_huge_val_sanity" >&6; } + HUGE_VAL_SANITY=$ac_cv_huge_val_sanity + + +{ echo "$as_me:$LINENO: checking for pid_t" >&5 +echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } +if test "${ac_cv_type_pid_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef pid_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_pid_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_pid_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 +echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } +if test $ac_cv_type_pid_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define pid_t int +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for size_t" >&5 +echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } +if test "${ac_cv_type_size_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef size_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_size_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_size_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 +echo "${ECHO_T}$ac_cv_type_size_t" >&6; } +if test $ac_cv_type_size_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE void +_ACEOF + +{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 +echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; } +if test "${ac_cv_struct_tm+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm *tp; tp->tm_sec; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_struct_tm=time.h +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_struct_tm=sys/time.h +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 +echo "${ECHO_T}$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +cat >>confdefs.h <<\_ACEOF +#define TM_IN_SYS_TIME 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for int64_t" >&5 +echo $ECHO_N "checking for int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_int64_t" >&6; } +if test $ac_cv_type_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type int64_t required but not found" >&5 +echo "$as_me: error: Type int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for uint64_t" >&5 +echo $ECHO_N "checking for uint64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_uint64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef uint64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_uint64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_uint64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_uint64_t" >&5 +echo "${ECHO_T}$ac_cv_type_uint64_t" >&6; } +if test $ac_cv_type_uint64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_UINT64_T 1 +_ACEOF + + +else + { echo "$as_me:$LINENO: checking for u_int64_t" >&5 +echo $ECHO_N "checking for u_int64_t... $ECHO_C" >&6; } +if test "${ac_cv_type_u_int64_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +typedef u_int64_t ac__type_new_; +int +main () +{ +if ((ac__type_new_ *) 0) + return 0; +if (sizeof (ac__type_new_)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_u_int64_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_type_u_int64_t=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_type_u_int64_t" >&5 +echo "${ECHO_T}$ac_cv_type_u_int64_t" >&6; } +if test $ac_cv_type_u_int64_t = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_U_INT64_T 1 +_ACEOF + + +else + { { echo "$as_me:$LINENO: error: Type uint64_t or u_int64_t required but not found" >&5 +echo "$as_me: error: Type uint64_t or u_int64_t required but not found" >&2;} + { (exit 1); exit 1; }; } +fi + +fi + + + + + + + + + + +for ac_func in backtrace ceilf floorf roundf rintf nearbyintf getcwd +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in powf fmodf strtof round +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in getpagesize getrusage getrlimit setrlimit gettimeofday +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in isatty mkdtemp mkstemp +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + +for ac_func in mktemp posix_spawn realpath sbrk setrlimit strdup +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in strerror strerror_r setenv +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + +for ac_func in strtoll strtoq sysconf malloc_zone_statistics +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + +for ac_func in setjmp longjmp sigsetjmp siglongjmp writev +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking if printf has the %a format character" >&5 +echo $ECHO_N "checking if printf has the %a format character... $ECHO_C" >&6; } +if test "${llvm_cv_c_printf_a+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + llvmac_cv_c_printf_a=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include + +int +main () +{ + +volatile double A, B; +char Buffer[100]; +A = 1; +A /= 10.0; +sprintf(Buffer, "%a", A); +B = atof(Buffer); +if (A != B) + return (1); +if (A != 0x1.999999999999ap-4) + return (1); +return (0); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_c_printf_a=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +llvmac_cv_c_printf_a=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_c_printf_a" >&5 +echo "${ECHO_T}$llvm_cv_c_printf_a" >&6; } + if test "$llvm_cv_c_printf_a" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_PRINTF_A 1 +_ACEOF + + fi + + +{ echo "$as_me:$LINENO: checking for srand48/lrand48/drand48 in " >&5 +echo $ECHO_N "checking for srand48/lrand48/drand48 in ... $ECHO_C" >&6; } +if test "${ac_cv_func_rand48+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +srand48(0);lrand48();drand48(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_rand48=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_rand48=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_rand48" >&5 +echo "${ECHO_T}$ac_cv_func_rand48" >&6; } + +if test "$ac_cv_func_rand48" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_RAND48 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking whether strerror_s is declared" >&5 +echo $ECHO_N "checking whether strerror_s is declared... $ECHO_C" >&6; } +if test "${ac_cv_have_decl_strerror_s+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +#ifndef strerror_s + char *p = (char *) strerror_s; + return !p; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_strerror_s=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_have_decl_strerror_s=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_decl_strerror_s" >&5 +echo "${ECHO_T}$ac_cv_have_decl_strerror_s" >&6; } +if test $ac_cv_have_decl_strerror_s = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_S 1 +_ACEOF + + +else + cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRERROR_S 0 +_ACEOF + + +fi + + + +if test "$llvm_cv_os_type" = "MingW" ; then + { echo "$as_me:$LINENO: checking for _alloca in -lgcc" >&5 +echo $ECHO_N "checking for _alloca in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc__alloca+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char _alloca (); +int +main () +{ +return _alloca (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc__alloca=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc__alloca=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc__alloca" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc__alloca" >&6; } +if test $ac_cv_lib_gcc__alloca = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE__ALLOCA 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __alloca in -lgcc" >&5 +echo $ECHO_N "checking for __alloca in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___alloca+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __alloca (); +int +main () +{ +return __alloca (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___alloca=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___alloca=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___alloca" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___alloca" >&6; } +if test $ac_cv_lib_gcc___alloca = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ALLOCA 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __chkstk in -lgcc" >&5 +echo $ECHO_N "checking for __chkstk in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___chkstk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __chkstk (); +int +main () +{ +return __chkstk (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___chkstk=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___chkstk=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___chkstk" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___chkstk" >&6; } +if test $ac_cv_lib_gcc___chkstk = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___CHKSTK 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for ___chkstk in -lgcc" >&5 +echo $ECHO_N "checking for ___chkstk in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc____chkstk+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ___chkstk (); +int +main () +{ +return ___chkstk (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc____chkstk=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc____chkstk=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc____chkstk" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc____chkstk" >&6; } +if test $ac_cv_lib_gcc____chkstk = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE____CHKSTK 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for __ashldi3 in -lgcc" >&5 +echo $ECHO_N "checking for __ashldi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___ashldi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __ashldi3 (); +int +main () +{ +return __ashldi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___ashldi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___ashldi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___ashldi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___ashldi3" >&6; } +if test $ac_cv_lib_gcc___ashldi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ASHLDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __ashrdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __ashrdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___ashrdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __ashrdi3 (); +int +main () +{ +return __ashrdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___ashrdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___ashrdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___ashrdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___ashrdi3" >&6; } +if test $ac_cv_lib_gcc___ashrdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___ASHRDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __divdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __divdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___divdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __divdi3 (); +int +main () +{ +return __divdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___divdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___divdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___divdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___divdi3" >&6; } +if test $ac_cv_lib_gcc___divdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___DIVDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __fixdfdi in -lgcc" >&5 +echo $ECHO_N "checking for __fixdfdi in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___fixdfdi+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __fixdfdi (); +int +main () +{ +return __fixdfdi (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___fixdfdi=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___fixdfdi=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___fixdfdi" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___fixdfdi" >&6; } +if test $ac_cv_lib_gcc___fixdfdi = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FIXDFDI 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __fixsfdi in -lgcc" >&5 +echo $ECHO_N "checking for __fixsfdi in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___fixsfdi+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __fixsfdi (); +int +main () +{ +return __fixsfdi (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___fixsfdi=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___fixsfdi=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___fixsfdi" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___fixsfdi" >&6; } +if test $ac_cv_lib_gcc___fixsfdi = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FIXSFDI 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __floatdidf in -lgcc" >&5 +echo $ECHO_N "checking for __floatdidf in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___floatdidf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __floatdidf (); +int +main () +{ +return __floatdidf (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___floatdidf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___floatdidf=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___floatdidf" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___floatdidf" >&6; } +if test $ac_cv_lib_gcc___floatdidf = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___FLOATDIDF 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __lshrdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __lshrdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___lshrdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __lshrdi3 (); +int +main () +{ +return __lshrdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___lshrdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___lshrdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___lshrdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___lshrdi3" >&6; } +if test $ac_cv_lib_gcc___lshrdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___LSHRDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __moddi3 in -lgcc" >&5 +echo $ECHO_N "checking for __moddi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___moddi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __moddi3 (); +int +main () +{ +return __moddi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___moddi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___moddi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___moddi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___moddi3" >&6; } +if test $ac_cv_lib_gcc___moddi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___MODDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __udivdi3 in -lgcc" >&5 +echo $ECHO_N "checking for __udivdi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___udivdi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __udivdi3 (); +int +main () +{ +return __udivdi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___udivdi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___udivdi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___udivdi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___udivdi3" >&6; } +if test $ac_cv_lib_gcc___udivdi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___UDIVDI3 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __umoddi3 in -lgcc" >&5 +echo $ECHO_N "checking for __umoddi3 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___umoddi3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __umoddi3 (); +int +main () +{ +return __umoddi3 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___umoddi3=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___umoddi3=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___umoddi3" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___umoddi3" >&6; } +if test $ac_cv_lib_gcc___umoddi3 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___UMODDI3 1 +_ACEOF + +fi + + + { echo "$as_me:$LINENO: checking for __main in -lgcc" >&5 +echo $ECHO_N "checking for __main in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __main (); +int +main () +{ +return __main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___main" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___main" >&6; } +if test $ac_cv_lib_gcc___main = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___MAIN 1 +_ACEOF + +fi + + { echo "$as_me:$LINENO: checking for __cmpdi2 in -lgcc" >&5 +echo $ECHO_N "checking for __cmpdi2 in -lgcc... $ECHO_C" >&6; } +if test "${ac_cv_lib_gcc___cmpdi2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char __cmpdi2 (); +int +main () +{ +return __cmpdi2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gcc___cmpdi2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gcc___cmpdi2=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gcc___cmpdi2" >&5 +echo "${ECHO_T}$ac_cv_lib_gcc___cmpdi2" >&6; } +if test $ac_cv_lib_gcc___cmpdi2 = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE___CMPDI2 1 +_ACEOF + +fi + +fi + + +{ echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_math_h" >&6; } + + +if test "$ac_cv_func_isnan_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_MATH_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for isnan in " >&5 +echo $ECHO_N "checking for isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISNAN_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for std::isnan in " >&5 +echo $ECHO_N "checking for std::isnan in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isnan_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isnan(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isnan_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isnan_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isnan_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isnan_in_cmath" >&6; } + +if test "$ac_cv_func_std_isnan_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISNAN_IN_CMATH 1 +_ACEOF + +fi + + +{ echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_math_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_math_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_math_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_math_h" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_math_h" >&6; } + +if test "$ac_cv_func_isinf_in_math_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_MATH_H 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for isinf in " >&5 +echo $ECHO_N "checking for isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; isinf(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ISINF_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for std::isinf in " >&5 +echo $ECHO_N "checking for std::isinf in ... $ECHO_C" >&6; } +if test "${ac_cv_func_std_isinf_in_cmath+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; std::isinf(f)} + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_std_isinf_in_cmath=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_std_isinf_in_cmath=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_std_isinf_in_cmath" >&5 +echo "${ECHO_T}$ac_cv_func_std_isinf_in_cmath" >&6; } + +if test "$ac_cv_func_std_isinf_in_cmath" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_STD_ISINF_IN_CMATH 1 +_ACEOF + +fi + +{ echo "$as_me:$LINENO: checking for finite in " >&5 +echo $ECHO_N "checking for finite in ... $ECHO_C" >&6; } +if test "${ac_cv_func_finite_in_ieeefp_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +float f; finite(f); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_finite_in_ieeefp_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_finite_in_ieeefp_h=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_finite_in_ieeefp_h" >&5 +echo "${ECHO_T}$ac_cv_func_finite_in_ieeefp_h" >&6; } + +if test "$ac_cv_func_finite_in_ieeefp_h" = "yes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FINITE_IN_IEEEFP_H 1 +_ACEOF + +fi + + + +if test "$llvm_cv_platform_type" = "Unix" ; then + + +for ac_header in stdlib.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------- ## +## Report this to llvmbugs@cs.uiuc.edu ## +## ----------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking for working mmap" >&5 +echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !STDC_HEADERS && !HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#if !HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# if !HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# if HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 1; + if (write (fd, data, pagesize) != pagesize) + return 1; + close (fd); + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 1; + data2 = (char *) malloc (2 * pagesize); + if (!data2) + return 1; + data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 1; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 1; + if (read (fd, data3, pagesize) != pagesize) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 1; + close (fd); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -f conftest.mmap + + { echo "$as_me:$LINENO: checking for mmap of files" >&5 +echo $ECHO_N "checking for mmap of files... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_file+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_file=no +else + cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + + int fd; + fd = creat ("foo",0777); + fd = (int) mmap (0, 1, PROT_READ, MAP_SHARED, fd, 0); + unlink ("foo"); + return (fd != (int) MAP_FAILED); + ; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_file=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_file=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_file" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_file" >&6; } +if test "$ac_cv_func_mmap_file" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP_FILE +_ACEOF + + MMAP_FILE=yes + +fi + + { echo "$as_me:$LINENO: checking if /dev/zero is needed for mmap" >&5 +echo $ECHO_N "checking if /dev/zero is needed for mmap... $ECHO_C" >&6; } +if test "${ac_cv_need_dev_zero_for_mmap+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$llvm_cv_os_type" = "Interix" ; then + ac_cv_need_dev_zero_for_mmap=yes + else + ac_cv_need_dev_zero_for_mmap=no + fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_need_dev_zero_for_mmap" >&5 +echo "${ECHO_T}$ac_cv_need_dev_zero_for_mmap" >&6; } +if test "$ac_cv_need_dev_zero_for_mmap" = yes; then + +cat >>confdefs.h <<\_ACEOF +#define NEED_DEV_ZERO_FOR_MMAP 1 +_ACEOF + +fi + + if test "$ac_cv_func_mmap_fixed_mapped" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of a fixed address required but not supported" >&5 +echo "$as_me: WARNING: mmap() of a fixed address required but not supported" >&2;} + fi + if test "$ac_cv_func_mmap_file" = "no" + then + { echo "$as_me:$LINENO: WARNING: mmap() of files required but not found" >&5 +echo "$as_me: WARNING: mmap() of files required but not found" >&2;} + fi +fi + +{ echo "$as_me:$LINENO: checking for GCC atomic builtins" >&5 +echo $ECHO_N "checking for GCC atomic builtins... $ECHO_C" >&6; } +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int main() { + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); + return 0; + } + +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_MULTITHREADED 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + +cat >>confdefs.h <<\_ACEOF +#define LLVM_MULTITHREADED 0 +_ACEOF + + { echo "$as_me:$LINENO: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&5 +echo "$as_me: WARNING: LLVM will be built thread-unsafe because atomic builtins are missing" >&2;} +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then + { echo "$as_me:$LINENO: checking for 32-bit userspace on 64-bit system" >&5 +echo $ECHO_N "checking for 32-bit userspace on 64-bit system... $ECHO_C" >&6; } +if test "${llvm_cv_linux_mixed+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __x86_64__ + error: Not x86-64 even if uname says so! + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_linux_mixed=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_linux_mixed=yes +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_linux_mixed" >&5 +echo "${ECHO_T}$llvm_cv_linux_mixed" >&6; } + + if test "$llvm_cv_linux_mixed" = "yes"; then + llvm_cv_target_arch="x86" + ARCH="x86" + fi +fi + + +for ac_func in __dso_handle +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +{ echo "$as_me:$LINENO: checking whether llvm-gcc is dragonegg" >&5 +echo $ECHO_N "checking whether llvm-gcc is dragonegg... $ECHO_C" >&6; } +if test "${llvm_cv_llvmgcc_dragonegg+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_llvmgcc_dragonegg="no" +if test -n "$LLVMGCC" ; then + cp /dev/null conftest.c + $LLVMGCC -fplugin-arg-dragonegg-emit-ir -S -o - conftest.c > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_dragonegg="yes" + fi + rm conftest.c +fi +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_llvmgcc_dragonegg" >&5 +echo "${ECHO_T}$llvm_cv_llvmgcc_dragonegg" >&6; } + +if test "$llvm_cv_llvmgcc_dragonegg" = "yes" ; then + LLVMCC_EMITIR_FLAG="-fplugin-arg-dragonegg-emit-ir" + LLVMCC_DISABLEOPT_FLAGS="-fplugin-arg-dragonegg-disable-llvm-optzns" +else + LLVMCC_EMITIR_FLAG="-emit-llvm" + LLVMCC_DISABLEOPT_FLAGS="-mllvm -disable-llvm-optzns" +fi + + + +{ echo "$as_me:$LINENO: checking whether llvm-gcc is sane" >&5 +echo $ECHO_N "checking whether llvm-gcc is sane... $ECHO_C" >&6; } +if test "${llvm_cv_llvmgcc_sanity+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + llvm_cv_llvmgcc_sanity="no" +if test -n "$LLVMGCC" ; then + cp /dev/null conftest.c + $LLVMGCC "$LLVMCC_EMITIR_FLAG" -S -o - conftest.c | \ + grep 'target datalayout =' > /dev/null 2>&1 + if test $? -eq 0 ; then + llvm_cv_llvmgcc_sanity="yes" + fi + rm conftest.c +fi +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_llvmgcc_sanity" >&5 +echo "${ECHO_T}$llvm_cv_llvmgcc_sanity" >&6; } + +if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then + { echo "$as_me:$LINENO: checking llvm-gcc component support" >&5 +echo $ECHO_N "checking llvm-gcc component support... $ECHO_C" >&6; } + llvmcc1path=`$LLVMGCC --print-prog-name=cc1` + LLVMCC1=$llvmcc1path + + llvmcc1pluspath=`$LLVMGCC --print-prog-name=cc1plus` + LLVMCC1PLUS=$llvmcc1pluspath + + llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` + LLVMGCCDIR=$llvmgccdir + + llvmgcclangs=`$LLVMGCC -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'` + LLVMGCC_LANGS=$llvmgcclangs + + LLVMGCC_DRAGONEGG=$llvm_cv_llvmgcc_dragonegg + + + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +SHLIBEXT=$libltdl_cv_shlibext + + +SHLIBPATH_VAR=$libltdl_cv_shlibpath_var + + +# Translate the various configuration directories and other basic +# information into substitutions that will end up in Makefile.config.in +# that these configured values can be used by the makefiles +if test "${prefix}" = "NONE" ; then + prefix="/usr/local" +fi +eval LLVM_PREFIX="${prefix}"; +eval LLVM_BINDIR="${prefix}/bin"; +eval LLVM_LIBDIR="${prefix}/lib"; +eval LLVM_DATADIR="${prefix}/share/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; +eval LLVM_ETCDIR="${prefix}/etc/llvm"; +eval LLVM_INCLUDEDIR="${prefix}/include"; +eval LLVM_INFODIR="${prefix}/info"; +eval LLVM_MANDIR="${prefix}/man"; +LLVM_CONFIGTIME=`date` + + + + + + + + + + + +# Place the various directores into the config.h file as #defines so that we +# can know about the installation paths within LLVM. + +cat >>confdefs.h <<_ACEOF +#define LLVM_PREFIX "$LLVM_PREFIX" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_BINDIR "$LLVM_BINDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_LIBDIR "$LLVM_LIBDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DATADIR "$LLVM_DATADIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_DOCSDIR "$LLVM_DOCSDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_ETCDIR "$LLVM_ETCDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INCLUDEDIR "$LLVM_INCLUDEDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_INFODIR "$LLVM_INFODIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_MANDIR "$LLVM_MANDIR" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_CONFIGTIME "$LLVM_CONFIGTIME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LLVM_HOSTTRIPLE "$host" +_ACEOF + + +# Determine which bindings to build. +if test "$BINDINGS_TO_BUILD" = auto ; then + BINDINGS_TO_BUILD="" + if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" + fi +fi +BINDINGS_TO_BUILD=$BINDINGS_TO_BUILD + + +# This isn't really configurey, but it avoids having to repeat the list in +# other files. +ALL_BINDINGS=ocaml + + +# Do any work necessary to ensure that bindings have what they need. +binding_prereqs_failed=0 +for a_binding in $BINDINGS_TO_BUILD ; do + case "$a_binding" in + ocaml) + if test "x$OCAMLC" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLDEP" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&2;} + binding_prereqs_failed=1 + fi + if test "x$OCAMLOPT" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&2;} + fi + if test "x$with_ocaml_libdir" != xauto ; then + OCAML_LIBDIR=$with_ocaml_libdir + + else + ocaml_stdlib="`"$OCAMLC" -where`" + if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" + then + # ocaml stdlib is beneath our prefix; use stdlib + OCAML_LIBDIR=$ocaml_stdlib + + else + # ocaml stdlib is outside our prefix; use libdir/ocaml + OCAML_LIBDIR=$LLVM_LIBDIR/ocaml + + fi + fi + ;; + esac +done +if test "$binding_prereqs_failed" = 1 ; then + { { echo "$as_me:$LINENO: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&5 +echo "$as_me: error: Prequisites for bindings not satisfied. Fix them or use configure --disable-bindings." >&2;} + { (exit 1); exit 1; }; } +fi + +{ echo "$as_me:$LINENO: checking for compiler -fvisibility-inlines-hidden option" >&5 +echo $ECHO_N "checking for compiler -fvisibility-inlines-hidden option... $ECHO_C" >&6; } +if test "${llvm_cv_cxx_visibility_inlines_hidden+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + oldcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + llvm_cv_cxx_visibility_inlines_hidden=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + llvm_cv_cxx_visibility_inlines_hidden=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CXXFLAGS="$oldcxxflags" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +fi +{ echo "$as_me:$LINENO: result: $llvm_cv_cxx_visibility_inlines_hidden" >&5 +echo "${ECHO_T}$llvm_cv_cxx_visibility_inlines_hidden" >&6; } +if test "$llvm_cv_cxx_visibility_inlines_hidden" = yes ; then + ENABLE_VISIBILITY_INLINES_HIDDEN=1 + +else + ENABLE_VISIBILITY_INLINES_HIDDEN=0 + +fi + + +if test "$llvm_cv_link_use_r" = "yes" ; then + RPATH="-Wl,-R" +else + RPATH="-Wl,-rpath" +fi + + +if test "$llvm_cv_link_use_export_dynamic" = "yes" ; then + RDYNAMIC="-Wl,-export-dynamic" +else + RDYNAMIC="" +fi + + + +ac_config_headers="$ac_config_headers include/llvm/Config/config.h include/llvm/Config/llvm-config.h" + + + + + + +ac_config_files="$ac_config_files include/llvm/Config/Targets.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmPrinters.def" + +ac_config_files="$ac_config_files include/llvm/Config/AsmParsers.def" + +ac_config_files="$ac_config_files include/llvm/Config/Disassemblers.def" + +ac_config_headers="$ac_config_headers include/llvm/Support/DataTypes.h" + + +ac_config_files="$ac_config_files Makefile.config" + + +ac_config_files="$ac_config_files llvm.spec" + + +ac_config_files="$ac_config_files tools/llvmc/src/Base.td" + + +ac_config_files="$ac_config_files tools/llvm-config/llvm-config.in" + + +ac_config_commands="$ac_config_commands setup" + +ac_config_commands="$ac_config_commands Makefile" + + +ac_config_commands="$ac_config_commands Makefile.common" + + +ac_config_commands="$ac_config_commands examples/Makefile" + + +ac_config_commands="$ac_config_commands lib/Makefile" + + +ac_config_commands="$ac_config_commands runtime/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile" + + +ac_config_commands="$ac_config_commands test/Makefile.tests" + + +ac_config_commands="$ac_config_commands unittests/Makefile" + + +ac_config_commands="$ac_config_commands tools/Makefile" + + +ac_config_commands="$ac_config_commands utils/Makefile" + + +ac_config_commands="$ac_config_commands projects/Makefile" + + +ac_config_commands="$ac_config_commands bindings/Makefile" + + +ac_config_commands="$ac_config_commands bindings/ocaml/Makefile.ocaml" + + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"INSTALL_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"CONVENIENCE_LTDL\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by llvm $as_me 2.9, which was +generated by GNU Autoconf 2.60. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +llvm config.status 2.9 +configured by $0, generated by GNU Autoconf 2.60, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS +# +llvm_src="${srcdir}" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "include/llvm/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/config.h" ;; + "include/llvm/Config/llvm-config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/llvm-config.h" ;; + "include/llvm/Config/Targets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Targets.def" ;; + "include/llvm/Config/AsmPrinters.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmPrinters.def" ;; + "include/llvm/Config/AsmParsers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmParsers.def" ;; + "include/llvm/Config/Disassemblers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Disassemblers.def" ;; + "include/llvm/Support/DataTypes.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Support/DataTypes.h" ;; + "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; + "llvm.spec") CONFIG_FILES="$CONFIG_FILES llvm.spec" ;; + "tools/llvmc/src/Base.td") CONFIG_FILES="$CONFIG_FILES tools/llvmc/src/Base.td" ;; + "tools/llvm-config/llvm-config.in") CONFIG_FILES="$CONFIG_FILES tools/llvm-config/llvm-config.in" ;; + "setup") CONFIG_COMMANDS="$CONFIG_COMMANDS setup" ;; + "Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile" ;; + "Makefile.common") CONFIG_COMMANDS="$CONFIG_COMMANDS Makefile.common" ;; + "examples/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS examples/Makefile" ;; + "lib/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS lib/Makefile" ;; + "runtime/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS runtime/Makefile" ;; + "test/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile" ;; + "test/Makefile.tests") CONFIG_COMMANDS="$CONFIG_COMMANDS test/Makefile.tests" ;; + "unittests/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS unittests/Makefile" ;; + "tools/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS tools/Makefile" ;; + "utils/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS utils/Makefile" ;; + "projects/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS projects/Makefile" ;; + "bindings/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/Makefile" ;; + "bindings/ocaml/Makefile.ocaml") CONFIG_COMMANDS="$CONFIG_COMMANDS bindings/ocaml/Makefile.ocaml" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +LLVM_COPYRIGHT!$LLVM_COPYRIGHT$ac_delim +subdirs!$subdirs$ac_delim +ENABLE_POLLY!$ENABLE_POLLY$ac_delim +LLVM_HAS_POLLY!$LLVM_HAS_POLLY$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +OS!$OS$ac_delim +HOST_OS!$HOST_OS$ac_delim +TARGET_OS!$TARGET_OS$ac_delim +LINKALL!$LINKALL$ac_delim +NOLINKALL!$NOLINKALL$ac_delim +LLVM_ON_UNIX!$LLVM_ON_UNIX$ac_delim +LLVM_ON_WIN32!$LLVM_ON_WIN32$ac_delim +ARCH!$ARCH$ac_delim +ENDIAN!$ENDIAN$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CPP!$CPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LLVM_CROSS_COMPILING!$LLVM_CROSS_COMPILING$ac_delim +BUILD_CC!$BUILD_CC$ac_delim +BUILD_EXEEXT!$BUILD_EXEEXT$ac_delim +BUILD_CXX!$BUILD_CXX$ac_delim +CVSBUILD!$CVSBUILD$ac_delim +ENABLE_OPTIMIZED!$ENABLE_OPTIMIZED$ac_delim +ENABLE_PROFILING!$ENABLE_PROFILING$ac_delim +DISABLE_ASSERTIONS!$DISABLE_ASSERTIONS$ac_delim +ENABLE_EXPENSIVE_CHECKS!$ENABLE_EXPENSIVE_CHECKS$ac_delim +EXPENSIVE_CHECKS!$EXPENSIVE_CHECKS$ac_delim +DEBUG_RUNTIME!$DEBUG_RUNTIME$ac_delim +DEBUG_SYMBOLS!$DEBUG_SYMBOLS$ac_delim +JIT!$JIT$ac_delim +TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim +ENABLE_DOCS!$ENABLE_DOCS$ac_delim +ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim +ENABLE_THREADS!$ENABLE_THREADS$ac_delim +ENABLE_PTHREADS!$ENABLE_PTHREADS$ac_delim +ENABLE_PIC!$ENABLE_PIC$ac_delim +ENABLE_SHARED!$ENABLE_SHARED$ac_delim +ENABLE_EMBED_STDCXX!$ENABLE_EMBED_STDCXX$ac_delim +ENABLE_TIMESTAMPS!$ENABLE_TIMESTAMPS$ac_delim +TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim +LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim +LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim +LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim +ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim +CLANGPATH!$CLANGPATH$ac_delim +CLANGXXPATH!$CLANGXXPATH$ac_delim +ENABLE_BUILT_CLANG!$ENABLE_BUILT_CLANG$ac_delim +OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim +EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim +BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +NM!$NM$ac_delim +ifGNUmake!$ifGNUmake$ac_delim +LN_S!$LN_S$ac_delim +CMP!$CMP$ac_delim +CP!$CP$ac_delim +DATE!$DATE$ac_delim +FIND!$FIND$ac_delim +MKDIR!$MKDIR$ac_delim +MV!$MV$ac_delim +RANLIB!$RANLIB$ac_delim +AR!$AR$ac_delim +RM!$RM$ac_delim +SED!$SED$ac_delim +TAR!$TAR$ac_delim +BINPWD!$BINPWD$ac_delim +GRAPHVIZ!$GRAPHVIZ$ac_delim +DOT!$DOT$ac_delim +FDP!$FDP$ac_delim +NEATO!$NEATO$ac_delim +TWOPI!$TWOPI$ac_delim +CIRCO!$CIRCO$ac_delim +GV!$GV$ac_delim +DOTTY!$DOTTY$ac_delim +XDOT_PY!$XDOT_PY$ac_delim +PERL!$PERL$ac_delim +HAVE_PERL!$HAVE_PERL$ac_delim +INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim +INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim +INSTALL_DATA!$INSTALL_DATA$ac_delim +BZIP2!$BZIP2$ac_delim +CAT!$CAT$ac_delim +DOXYGEN!$DOXYGEN$ac_delim +GROFF!$GROFF$ac_delim +GZIPBIN!$GZIPBIN$ac_delim +POD2HTML!$POD2HTML$ac_delim +POD2MAN!$POD2MAN$ac_delim +PDFROFF!$PDFROFF$ac_delim +RUNTEST!$RUNTEST$ac_delim +TCLSH!$TCLSH$ac_delim +ZIP!$ZIP$ac_delim +OCAMLC!$OCAMLC$ac_delim +OCAMLOPT!$OCAMLOPT$ac_delim +OCAMLDEP!$OCAMLDEP$ac_delim +OCAMLDOC!$OCAMLDOC$ac_delim +GAS!$GAS$ac_delim +HAVE_LINK_VERSION_SCRIPT!$HAVE_LINK_VERSION_SCRIPT$ac_delim +INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim +INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim +CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim +CONVENIENCE_LTDL_FALSE!$CONVENIENCE_LTDL_FALSE$ac_delim +LIBADD_DL!$LIBADD_DL$ac_delim +LLVMGCCCOMMAND!$LLVMGCCCOMMAND$ac_delim +LLVMGXXCOMMAND!$LLVMGXXCOMMAND$ac_delim +LLVMGCC!$LLVMGCC$ac_delim +LLVMGXX!$LLVMGXX$ac_delim +LLVMCC_OPTION!$LLVMCC_OPTION$ac_delim +NO_VARIADIC_MACROS!$NO_VARIADIC_MACROS$ac_delim +NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim +USE_UDIS86!$USE_UDIS86$ac_delim +USE_OPROFILE!$USE_OPROFILE$ac_delim +HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim +HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim +MMAP_FILE!$MMAP_FILE$ac_delim +LLVMCC_EMITIR_FLAG!$LLVMCC_EMITIR_FLAG$ac_delim +LLVMCC1!$LLVMCC1$ac_delim +LLVMCC1PLUS!$LLVMCC1PLUS$ac_delim +LLVMGCCDIR!$LLVMGCCDIR$ac_delim +LLVMGCC_LANGS!$LLVMGCC_LANGS$ac_delim +LLVMGCC_DRAGONEGG!$LLVMGCC_DRAGONEGG$ac_delim +LLVMCC_DISABLEOPT_FLAGS!$LLVMCC_DISABLEOPT_FLAGS$ac_delim +SHLIBEXT!$SHLIBEXT$ac_delim +SHLIBPATH_VAR!$SHLIBPATH_VAR$ac_delim +LLVM_PREFIX!$LLVM_PREFIX$ac_delim +LLVM_BINDIR!$LLVM_BINDIR$ac_delim +LLVM_LIBDIR!$LLVM_LIBDIR$ac_delim +LLVM_DATADIR!$LLVM_DATADIR$ac_delim +LLVM_DOCSDIR!$LLVM_DOCSDIR$ac_delim +LLVM_ETCDIR!$LLVM_ETCDIR$ac_delim +LLVM_INCLUDEDIR!$LLVM_INCLUDEDIR$ac_delim +LLVM_INFODIR!$LLVM_INFODIR$ac_delim +LLVM_MANDIR!$LLVM_MANDIR$ac_delim +LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim +BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim +ALL_BINDINGS!$ALL_BINDINGS$ac_delim +OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +CEOF$ac_eof +_ACEOF + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim +RPATH!$RPATH$ac_delim +RDYNAMIC!$RDYNAMIC$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 5; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-3.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 +echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile Makefile ;; + "Makefile.common":C) ${llvm_src}/autoconf/mkinstalldirs `dirname Makefile.common` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/Makefile.common Makefile.common ;; + "examples/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname examples/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/examples/Makefile examples/Makefile ;; + "lib/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname lib/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/lib/Makefile lib/Makefile ;; + "runtime/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname runtime/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/runtime/Makefile runtime/Makefile ;; + "test/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile test/Makefile ;; + "test/Makefile.tests":C) ${llvm_src}/autoconf/mkinstalldirs `dirname test/Makefile.tests` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/test/Makefile.tests test/Makefile.tests ;; + "unittests/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname unittests/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/unittests/Makefile unittests/Makefile ;; + "tools/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname tools/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/tools/Makefile tools/Makefile ;; + "utils/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname utils/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/utils/Makefile utils/Makefile ;; + "projects/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname projects/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/projects/Makefile projects/Makefile ;; + "bindings/Makefile":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/Makefile` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/Makefile bindings/Makefile ;; + "bindings/ocaml/Makefile.ocaml":C) ${llvm_src}/autoconf/mkinstalldirs `dirname bindings/ocaml/Makefile.ocaml` + ${SHELL} ${llvm_src}/autoconf/install-sh -m 0644 -c ${srcdir}/bindings/ocaml/Makefile.ocaml bindings/ocaml/Makefile.ocaml ;; + + esac +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + +# +# CONFIG_SUBDIRS section. +# +if test "$no_recursion" != yes; then + + # Remove --cache-file and --srcdir arguments so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_arg $ac_sub_configure_args" + + ac_popdir=`pwd` + for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue + + # Do not complain, so a configure script can configure whichever + # parts of a large source tree are present. + test -d "$srcdir/$ac_dir" || continue + + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + echo "$as_me:$LINENO: $ac_msg" >&5 + echo "$ac_msg" >&6 + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + cd "$ac_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure + else + { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 +echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + ac_sub_configure= + fi + + # The recursion is here. + if test -n "$ac_sub_configure"; then + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + # The eval makes quoting arguments work. + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 +echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} + { (exit 1); exit 1; }; } + fi + + cd "$ac_popdir" + done +fi + diff --git a/final/docs/AliasAnalysis.html b/final/docs/AliasAnalysis.html new file mode 100644 index 00000000000..7baa9467697 --- /dev/null +++ b/final/docs/AliasAnalysis.html @@ -0,0 +1,1064 @@ + + + + LLVM Alias Analysis Infrastructure + + + + +
+ LLVM Alias Analysis Infrastructure +
+ +
    +
  1. Introduction
  2. + +
  3. AliasAnalysis Class Overview + +
  4. + +
  5. Writing a new AliasAnalysis Implementation + +
  6. + +
  7. Using alias analysis results + +
  8. + +
  9. Existing alias analysis implementations and clients + +
  10. +
  11. Memory Dependence Analysis
  12. +
+ +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Alias Analysis (aka Pointer Analysis) is a class of techniques which attempt +to determine whether or not two pointers ever can point to the same object in +memory. There are many different algorithms for alias analysis and many +different ways of classifying them: flow-sensitive vs flow-insensitive, +context-sensitive vs context-insensitive, field-sensitive vs field-insensitive, +unification-based vs subset-based, etc. Traditionally, alias analyses respond +to a query with a Must, May, or No alias response, +indicating that two pointers always point to the same object, might point to the +same object, or are known to never point to the same object.

+ +

The LLVM AliasAnalysis +class is the primary interface used by clients and implementations of alias +analyses in the LLVM system. This class is the common interface between clients +of alias analysis information and the implementations providing it, and is +designed to support a wide range of implementations and clients (but currently +all clients are assumed to be flow-insensitive). In addition to simple alias +analysis information, this class exposes Mod/Ref information from those +implementations which can provide it, allowing for powerful analyses and +transformations to work well together.

+ +

This document contains information necessary to successfully implement this +interface, use it, and to test both sides. It also explains some of the finer +points about what exactly results mean. If you feel that something is unclear +or should be added, please let me +know.

+ +
+ + + + + +
+ +

The AliasAnalysis +class defines the interface that the various alias analysis implementations +should support. This class exports two important enums: AliasResult +and ModRefResult which represent the result of an alias query or a +mod/ref query, respectively.

+ +

The AliasAnalysis interface exposes information about memory, +represented in several different ways. In particular, memory objects are +represented as a starting address and size, and function calls are represented +as the actual call or invoke instructions that performs the +call. The AliasAnalysis interface also exposes some helper methods +which allow you to get mod/ref information for arbitrary instructions.

+ +

All AliasAnalysis interfaces require that in queries involving +multiple values, values which are not +constants are all defined within the +same function.

+ +
+ + + + +
+ +

Most importantly, the AliasAnalysis class provides several methods +which are used to query whether or not two memory objects alias, whether +function calls can modify or read a memory object, etc. For all of these +queries, memory objects are represented as a pair of their starting address (a +symbolic LLVM Value*) and a static size.

+ +

Representing memory objects as a starting address and a size is critically +important for correct Alias Analyses. For example, consider this (silly, but +possible) C code:

+ +
+
+int i;
+char C[2];
+char A[10]; 
+/* ... */
+for (i = 0; i != 10; ++i) {
+  C[0] = A[i];          /* One byte store */
+  C[1] = A[9-i];        /* One byte store */
+}
+
+
+ +

In this case, the basicaa pass will disambiguate the stores to +C[0] and C[1] because they are accesses to two distinct +locations one byte apart, and the accesses are each one byte. In this case, the +LICM pass can use store motion to remove the stores from the loop. In +constrast, the following code:

+ +
+
+int i;
+char C[2];
+char A[10]; 
+/* ... */
+for (i = 0; i != 10; ++i) {
+  ((short*)C)[0] = A[i];  /* Two byte store! */
+  C[1] = A[9-i];          /* One byte store */
+}
+
+
+ +

In this case, the two stores to C do alias each other, because the access to +the &C[0] element is a two byte access. If size information wasn't +available in the query, even the first case would have to conservatively assume +that the accesses alias.

+ +
+ + + + +
+

The alias method is the primary interface used to determine whether +or not two memory objects alias each other. It takes two memory objects as +input and returns MustAlias, PartialAlias, MayAlias, or NoAlias as +appropriate.

+ +

Like all AliasAnalysis interfaces, the alias method requires +that either the two pointer values be defined within the same function, or at +least one of the values is a constant.

+
+ + + + +
+

The NoAlias response may be used when there is never an immediate dependence +between any memory reference based on one pointer and any memory +reference based the other. The most obvious example is when the two +pointers point to non-overlapping memory ranges. Another is when the two +pointers are only ever used for reading memory. Another is when the memory is +freed and reallocated between accesses through one pointer and accesses through +the other -- in this case, there is a dependence, but it's mediated by the free +and reallocation.

+ +

As an exception to this is with the +noalias keyword; the "irrelevant" +dependencies are ignored.

+ +

The MayAlias response is used whenever the two pointers might refer to the +same object.

+ +

The PartialAlias response is used when the two memory objects are known +to be overlapping in some way, but do not start at the same address.

+ +

The MustAlias response may only be returned if the two memory objects are +guaranteed to always start at exactly the same location. A MustAlias response +implies that the pointers compare equal.

+ +
+ + + + +
+ +

The getModRefInfo methods return information about whether the +execution of an instruction can read or modify a memory location. Mod/Ref +information is always conservative: if an instruction might read or write +a location, ModRef is returned.

+ +

The AliasAnalysis class also provides a getModRefInfo +method for testing dependencies between function calls. This method takes two +call sites (CS1 & CS2), returns NoModRef if neither call writes to memory +read or written by the other, Ref if CS1 reads memory written by CS2, Mod if CS1 +writes to memory read or written by CS2, or ModRef if CS1 might read or write +memory written to by CS2. Note that this relation is not commutative.

+ +
+ + + + + +
+ +

+Several other tidbits of information are often collected by various alias +analysis implementations and can be put to good use by various clients. +

+ +
+ + +
+ The pointsToConstantMemory method +
+ +
+ +

The pointsToConstantMemory method returns true if and only if the +analysis can prove that the pointer only points to unchanging memory locations +(functions, constant global variables, and the null pointer). This information +can be used to refine mod/ref information: it is impossible for an unchanging +memory location to be modified.

+ +
+ + + + +
+ +

These methods are used to provide very simple mod/ref information for +function calls. The doesNotAccessMemory method returns true for a +function if the analysis can prove that the function never reads or writes to +memory, or if the function only reads from constant memory. Functions with this +property are side-effect free and only depend on their input arguments, allowing +them to be eliminated if they form common subexpressions or be hoisted out of +loops. Many common functions behave this way (e.g., sin and +cos) but many others do not (e.g., acos, which modifies the +errno variable).

+ +

The onlyReadsMemory method returns true for a function if analysis +can prove that (at most) the function only reads from non-volatile memory. +Functions with this property are side-effect free, only depending on their input +arguments and the state of memory when they are called. This property allows +calls to these functions to be eliminated and moved around, as long as there is +no store instruction that changes the contents of memory. Note that all +functions that satisfy the doesNotAccessMemory method also satisfies +onlyReadsMemory.

+ +
+ + + + + +
+ +

Writing a new alias analysis implementation for LLVM is quite +straight-forward. There are already several implementations that you can use +for examples, and the following information should help fill in any details. +For a examples, take a look at the various alias analysis +implementations included with LLVM.

+ +
+ + + + +
+ +

The first step to determining what type of LLVM pass you need to use for your Alias +Analysis. As is the case with most other analyses and transformations, the +answer should be fairly obvious from what type of problem you are trying to +solve:

+ +
    +
  1. If you require interprocedural analysis, it should be a + Pass.
  2. +
  3. If you are a function-local analysis, subclass FunctionPass.
  4. +
  5. If you don't need to look at the program at all, subclass + ImmutablePass.
  6. +
+ +

In addition to the pass that you subclass, you should also inherit from the +AliasAnalysis interface, of course, and use the +RegisterAnalysisGroup template to register as an implementation of +AliasAnalysis.

+ +
+ + + + +
+ +

Your subclass of AliasAnalysis is required to invoke two methods on +the AliasAnalysis base class: getAnalysisUsage and +InitializeAliasAnalysis. In particular, your implementation of +getAnalysisUsage should explicitly call into the +AliasAnalysis::getAnalysisUsage method in addition to doing any +declaring any pass dependencies your pass has. Thus you should have something +like this:

+ +
+
+void getAnalysisUsage(AnalysisUsage &AU) const {
+  AliasAnalysis::getAnalysisUsage(AU);
+  // declare your dependencies here.
+}
+
+
+ +

Additionally, your must invoke the InitializeAliasAnalysis method +from your analysis run method (run for a Pass, +runOnFunction for a FunctionPass, or InitializePass +for an ImmutablePass). For example (as part of a Pass):

+ +
+
+bool run(Module &M) {
+  InitializeAliasAnalysis(this);
+  // Perform analysis here...
+  return false;
+}
+
+
+ +
+ + + + +
+ +

All of the AliasAnalysis +virtual methods default to providing chaining to another +alias analysis implementation, which ends up returning conservatively correct +information (returning "May" Alias and "Mod/Ref" for alias and mod/ref queries +respectively). Depending on the capabilities of the analysis you are +implementing, you just override the interfaces you can improve.

+ +
+ + + + + + +
+ +

With only two special exceptions (the basicaa and no-aa +passes) every alias analysis pass chains to another alias analysis +implementation (for example, the user can specify "-basicaa -ds-aa +-licm" to get the maximum benefit from both alias +analyses). The alias analysis class automatically takes care of most of this +for methods that you don't override. For methods that you do override, in code +paths that return a conservative MayAlias or Mod/Ref result, simply return +whatever the superclass computes. For example:

+ +
+
+AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size,
+                                 const Value *V2, unsigned V2Size) {
+  if (...)
+    return NoAlias;
+  ...
+
+  // Couldn't determine a must or no-alias result.
+  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
+}
+
+
+ +

In addition to analysis queries, you must make sure to unconditionally pass +LLVM update notification methods to the superclass as +well if you override them, which allows all alias analyses in a change to be +updated.

+ +
+ + + + + +
+

+Alias analysis information is initially computed for a static snapshot of the +program, but clients will use this information to make transformations to the +code. All but the most trivial forms of alias analysis will need to have their +analysis results updated to reflect the changes made by these transformations. +

+ +

+The AliasAnalysis interface exposes four methods which are used to +communicate program changes from the clients to the analysis implementations. +Various alias analysis implementations should use these methods to ensure that +their internal data structures are kept up-to-date as the program changes (for +example, when an instruction is deleted), and clients of alias analysis must be +sure to call these interfaces appropriately. +

+
+ + +
The deleteValue method
+ +
+The deleteValue method is called by transformations when they remove an +instruction or any other value from the program (including values that do not +use pointers). Typically alias analyses keep data structures that have entries +for each value in the program. When this method is called, they should remove +any entries for the specified value, if they exist. +
+ + +
The copyValue method
+ +
+The copyValue method is used when a new value is introduced into the +program. There is no way to introduce a value into the program that did not +exist before (this doesn't make sense for a safe compiler transformation), so +this is the only way to introduce a new value. This method indicates that the +new value has exactly the same properties as the value being copied. +
+ + +
The replaceWithNewValue method
+ +
+This method is a simple helper method that is provided to make clients easier to +use. It is implemented by copying the old analysis information to the new +value, then deleting the old value. This method cannot be overridden by alias +analysis implementations. +
+ + +
The addEscapingUse method
+ +
+

The addEscapingUse method is used when the uses of a pointer +value have changed in ways that may invalidate precomputed analysis information. +Implementations may either use this callback to provide conservative responses +for points whose uses have change since analysis time, or may recompute some +or all of their internal state to continue providing accurate responses.

+ +

In general, any new use of a pointer value is considered an escaping use, +and must be reported through this callback, except for the +uses below:

+ +
    +
  • A bitcast or getelementptr of the pointer
  • +
  • A store through the pointer (but not a store + of the pointer)
  • +
  • A load through the pointer
  • +
+
+ + + + +
+ +

From the LLVM perspective, the only thing you need to do to provide an +efficient alias analysis is to make sure that alias analysis queries are +serviced quickly. The actual calculation of the alias analysis results (the +"run" method) is only performed once, but many (perhaps duplicate) queries may +be performed. Because of this, try to move as much computation to the run +method as possible (within reason).

+ +
+ + + + +
+ +

The AliasAnalysis infrastructure has several limitations which make +writing a new AliasAnalysis implementation difficult.

+ +

There is no way to override the default alias analysis. It would +be very useful to be able to do something like "opt -my-aa -O2" and +have it use -my-aa for all passes which need AliasAnalysis, but there +is currently no support for that, short of changing the source code +and recompiling. Similarly, there is also no way of setting a chain +of analyses as the default.

+ +

There is no way for transform passes to declare that they preserve +AliasAnalysis implementations. The AliasAnalysis +interface includes deleteValue and copyValue methods +which are intended to allow a pass to keep an AliasAnalysis consistent, +however there's no way for a pass to declare in its +getAnalysisUsage that it does so. Some passes attempt to use +AU.addPreserved<AliasAnalysis>, however this doesn't +actually have any effect. + +

AliasAnalysisCounter (-count-aa) and AliasDebugger +(-debug-aa) are implemented as ModulePass classes, so if your +alias analysis uses FunctionPass, it won't be able to use +these utilities. If you try to use them, the pass manager will +silently route alias analysis queries directly to +BasicAliasAnalysis instead.

+ +

Similarly, the opt -p option introduces ModulePass +passes between each pass, which prevents the use of FunctionPass +alias analysis passes.

+ +

The AliasAnalysis API does have functions for notifying +implementations when values are deleted or copied, however these +aren't sufficient. There are many other ways that LLVM IR can be +modified which could be relevant to AliasAnalysis +implementations which can not be expressed.

+ +

The AliasAnalysisDebugger utility seems to suggest that +AliasAnalysis implementations can expect that they will be +informed of any relevant Value before it appears in an +alias query. However, popular clients such as GVN don't +support this, and are known to trigger errors when run with the +AliasAnalysisDebugger.

+ +

Due to several of the above limitations, the most obvious use for +the AliasAnalysisCounter utility, collecting stats on all +alias queries in a compilation, doesn't work, even if the +AliasAnalysis implementations don't use FunctionPass. +There's no way to set a default, much less a default sequence, +and there's no way to preserve it.

+ +

The AliasSetTracker class (which is used by LICM +makes a non-deterministic number of alias queries. This can cause stats +collected by AliasAnalysisCounter to have fluctuations among +identical runs, for example. Another consequence is that debugging +techniques involving pausing execution after a predetermined number +of queries can be unreliable.

+ +

Many alias queries can be reformulated in terms of other alias +queries. When multiple AliasAnalysis queries are chained together, +it would make sense to start those queries from the beginning of the chain, +with care taken to avoid infinite looping, however currently an +implementation which wants to do this can only start such queries +from itself.

+ +
+ + + + + +
+ +

There are several different ways to use alias analysis results. In order of +preference, these are...

+ +
+ + + + +
+ +

The memdep pass uses alias analysis to provide high-level dependence +information about memory-using instructions. This will tell you which store +feeds into a load, for example. It uses caching and other techniques to be +efficient, and is used by Dead Store Elimination, GVN, and memcpy optimizations. +

+ +
+ + + + +
+ +

Many transformations need information about alias sets that are active +in some scope, rather than information about pairwise aliasing. The AliasSetTracker class +is used to efficiently build these Alias Sets from the pairwise alias analysis +information provided by the AliasAnalysis interface.

+ +

First you initialize the AliasSetTracker by using the "add" methods +to add information about various potentially aliasing instructions in the scope +you are interested in. Once all of the alias sets are completed, your pass +should simply iterate through the constructed alias sets, using the +AliasSetTracker begin()/end() methods.

+ +

The AliasSets formed by the AliasSetTracker are guaranteed +to be disjoint, calculate mod/ref information and volatility for the set, and +keep track of whether or not all of the pointers in the set are Must aliases. +The AliasSetTracker also makes sure that sets are properly folded due to call +instructions, and can provide a list of pointers in each set.

+ +

As an example user of this, the Loop +Invariant Code Motion pass uses AliasSetTrackers to calculate alias +sets for each loop nest. If an AliasSet in a loop is not modified, +then all load instructions from that set may be hoisted out of the loop. If any +alias sets are stored to and are must alias sets, then the stores may be +sunk to outside of the loop, promoting the memory location to a register for the +duration of the loop nest. Both of these transformations only apply if the +pointer argument is loop-invariant.

+ +
+ + +
+ The AliasSetTracker implementation +
+ +
+ +

The AliasSetTracker class is implemented to be as efficient as possible. It +uses the union-find algorithm to efficiently merge AliasSets when a pointer is +inserted into the AliasSetTracker that aliases multiple sets. The primary data +structure is a hash table mapping pointers to the AliasSet they are in.

+ +

The AliasSetTracker class must maintain a list of all of the LLVM Value*'s +that are in each AliasSet. Since the hash table already has entries for each +LLVM Value* of interest, the AliasesSets thread the linked list through these +hash-table nodes to avoid having to allocate memory unnecessarily, and to make +merging alias sets extremely efficient (the linked list merge is constant time). +

+ +

You shouldn't need to understand these details if you are just a client of +the AliasSetTracker, but if you look at the code, hopefully this brief +description will help make sense of why things are designed the way they +are.

+ +
+ + + + +
+ +

If neither of these utility class are what your pass needs, you should use +the interfaces exposed by the AliasAnalysis class directly. Try to use +the higher-level methods when possible (e.g., use mod/ref information instead of +the alias method directly if possible) to get the +best precision and efficiency.

+ +
+ + + + + +
+ +

If you're going to be working with the LLVM alias analysis infrastructure, +you should know what clients and implementations of alias analysis are +available. In particular, if you are implementing an alias analysis, you should +be aware of the the clients that are useful +for monitoring and evaluating different implementations.

+ +
+ + + + +
+ +

This section lists the various implementations of the AliasAnalysis +interface. With the exception of the -no-aa and +-basicaa implementations, all of these chain to other alias analysis implementations.

+ +
+ + + + +
+ +

The -no-aa pass is just like what it sounds: an alias analysis that +never returns any useful information. This pass can be useful if you think that +alias analysis is doing something wrong and are trying to narrow down a +problem.

+ +
+ + + + +
+ +

The -basicaa pass is an aggressive local analysis that "knows" +many important facts:

+ +
    +
  • Distinct globals, stack allocations, and heap allocations can never + alias.
  • +
  • Globals, stack allocations, and heap allocations never alias the null + pointer.
  • +
  • Different fields of a structure do not alias.
  • +
  • Indexes into arrays with statically differing subscripts cannot alias.
  • +
  • Many common standard C library functions never access memory or only read memory.
  • +
  • Pointers that obviously point to constant globals + "pointToConstantMemory".
  • +
  • Function calls can not modify or references stack allocations if they never + escape from the function that allocates them (a common case for automatic + arrays).
  • +
+ +
+ + + + +
+ +

This pass implements a simple context-sensitive mod/ref and alias analysis +for internal global variables that don't "have their address taken". If a +global does not have its address taken, the pass knows that no pointers alias +the global. This pass also keeps track of functions that it knows never access +memory or never read memory. This allows certain optimizations (e.g. GVN) to +eliminate call instructions entirely. +

+ +

The real power of this pass is that it provides context-sensitive mod/ref +information for call instructions. This allows the optimizer to know that +calls to a function do not clobber or read the value of the global, allowing +loads and stores to be eliminated.

+ +

Note that this pass is somewhat limited in its scope (only support +non-address taken globals), but is very quick analysis.

+
+ + + + +
+ +

The -steens-aa pass implements a variation on the well-known +"Steensgaard's algorithm" for interprocedural alias analysis. Steensgaard's +algorithm is a unification-based, flow-insensitive, context-insensitive, and +field-insensitive alias analysis that is also very scalable (effectively linear +time).

+ +

The LLVM -steens-aa pass implements a "speculatively +field-sensitive" version of Steensgaard's algorithm using the Data +Structure Analysis framework. This gives it substantially more precision than +the standard algorithm while maintaining excellent analysis scalability.

+ +

Note that -steens-aa is available in the optional "poolalloc" +module, it is not part of the LLVM core.

+ +
+ + + + +
+ +

The -ds-aa pass implements the full Data Structure Analysis +algorithm. Data Structure Analysis is a modular unification-based, +flow-insensitive, context-sensitive, and speculatively +field-sensitive alias analysis that is also quite scalable, usually at +O(n*log(n)).

+ +

This algorithm is capable of responding to a full variety of alias analysis +queries, and can provide context-sensitive mod/ref information as well. The +only major facility not implemented so far is support for must-alias +information.

+ +

Note that -ds-aa is available in the optional "poolalloc" +module, it is not part of the LLVM core.

+ +
+ + + + +
+ +

The -scev-aa pass implements AliasAnalysis queries by +translating them into ScalarEvolution queries. This gives it a +more complete understanding of getelementptr instructions +and loop induction variables than other alias analyses have.

+ +
+ + + + +
+LLVM includes several alias-analysis driven transformations which can be used +with any of the implementations above. +
+ + + + +
+ +

The -adce pass, which implements Aggressive Dead Code Elimination +uses the AliasAnalysis interface to delete calls to functions that do +not have side-effects and are not used.

+ +
+ + + + + +
+ +

The -licm pass implements various Loop Invariant Code Motion related +transformations. It uses the AliasAnalysis interface for several +different transformations:

+ +
    +
  • It uses mod/ref information to hoist or sink load instructions out of loops +if there are no instructions in the loop that modifies the memory loaded.
  • + +
  • It uses mod/ref information to hoist function calls out of loops that do not +write to memory and are loop-invariant.
  • + +
  • If uses alias information to promote memory objects that are loaded and +stored to in loops to live in a register instead. It can do this if there are +no may aliases to the loaded/stored memory location.
  • +
+ +
+ + + + +
+

+The -argpromotion pass promotes by-reference arguments to be passed in +by-value instead. In particular, if pointer arguments are only loaded from it +passes in the value loaded instead of the address to the function. This pass +uses alias information to make sure that the value loaded from the argument +pointer is not modified between the entry of the function and any load of the +pointer.

+
+ + + + +
+ +

These passes use AliasAnalysis information to reason about loads and stores. +

+ +
+ + + + +
+ +

These passes are useful for evaluating the various alias analysis +implementations. You can use them with commands like 'opt -ds-aa +-aa-eval foo.bc -disable-output -stats'.

+ +
+ + + + +
+ +

The -print-alias-sets pass is exposed as part of the +opt tool to print out the Alias Sets formed by the AliasSetTracker class. This is useful if you're using +the AliasSetTracker class. To use it, use something like:

+ +
+
+% opt -ds-aa -print-alias-sets -disable-output
+
+
+ +
+ + + + + +
+ +

The -count-aa pass is useful to see how many queries a particular +pass is making and what responses are returned by the alias analysis. As an +example,

+ +
+
+% opt -basicaa -count-aa -ds-aa -count-aa -licm
+
+
+ +

will print out how many queries (and what responses are returned) by the +-licm pass (of the -ds-aa pass) and how many queries are made +of the -basicaa pass by the -ds-aa pass. This can be useful +when debugging a transformation or an alias analysis implementation.

+ +
+ + + + +
+ +

The -aa-eval pass simply iterates through all pairs of pointers in a +function and asks an alias analysis whether or not the pointers alias. This +gives an indication of the precision of the alias analysis. Statistics are +printed indicating the percent of no/may/must aliases found (a more precise +algorithm will have a lower number of may aliases).

+ +
+ + + + + +
+ +

If you're just looking to be a client of alias analysis information, consider +using the Memory Dependence Analysis interface instead. MemDep is a lazy, +caching layer on top of alias analysis that is able to answer the question of +what preceding memory operations a given instruction depends on, either at an +intra- or inter-block level. Because of its laziness and caching +policy, using MemDep can be a significant performance win over accessing alias +analysis directly.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/BitCodeFormat.html b/final/docs/BitCodeFormat.html new file mode 100644 index 00000000000..0b8747c261f --- /dev/null +++ b/final/docs/BitCodeFormat.html @@ -0,0 +1,1487 @@ + + + + + LLVM Bitcode File Format + + + +
LLVM Bitcode File Format
+
    +
  1. Abstract
  2. +
  3. Overview
  4. +
  5. Bitstream Format +
      +
    1. Magic Numbers
    2. +
    3. Primitives
    4. +
    5. Abbreviation IDs
    6. +
    7. Blocks
    8. +
    9. Data Records
    10. +
    11. Abbreviations
    12. +
    13. Standard Blocks
    14. +
    +
  6. +
  7. Bitcode Wrapper Format +
  8. +
  9. LLVM IR Encoding +
      +
    1. Basics
    2. +
    3. MODULE_BLOCK Contents
    4. +
    5. PARAMATTR_BLOCK Contents
    6. +
    7. TYPE_BLOCK Contents
    8. +
    9. CONSTANTS_BLOCK Contents
    10. +
    11. FUNCTION_BLOCK Contents
    12. +
    13. TYPE_SYMTAB_BLOCK Contents
    14. +
    15. VALUE_SYMTAB_BLOCK Contents
    16. +
    17. METADATA_BLOCK Contents
    18. +
    19. METADATA_ATTACHMENT Contents
    20. +
    +
  10. +
+
+

Written by Chris Lattner, + Joshua Haberman, + and Peter S. Housel. +

+
+ + + + + +
+ +

This document describes the LLVM bitstream file format and the encoding of +the LLVM IR into it.

+ +
+ + + + + +
+ +

+What is commonly known as the LLVM bitcode file format (also, sometimes +anachronistically known as bytecode) is actually two things: a bitstream container format +and an encoding of LLVM IR into the container format.

+ +

+The bitstream format is an abstract encoding of structured data, very +similar to XML in some ways. Like XML, bitstream files contain tags, and nested +structures, and you can parse the file without having to understand the tags. +Unlike XML, the bitstream format is a binary encoding, and unlike XML it +provides a mechanism for the file to self-describe "abbreviations", which are +effectively size optimizations for the content.

+ +

LLVM IR files may be optionally embedded into a wrapper structure that makes it easy to embed extra data +along with LLVM IR files.

+ +

This document first describes the LLVM bitstream format, describes the +wrapper format, then describes the record structure used by LLVM IR files. +

+ +
+ + + + + +
+ +

+The bitstream format is literally a stream of bits, with a very simple +structure. This structure consists of the following concepts: +

+ +
    +
  • A "magic number" that identifies the contents of + the stream.
  • +
  • Encoding primitives like variable bit-rate + integers.
  • +
  • Blocks, which define nested content.
  • +
  • Data Records, which describe entities within the + file.
  • +
  • Abbreviations, which specify compression optimizations for the file.
  • +
+ +

Note that the llvm-bcanalyzer tool can be +used to dump and inspect arbitrary bitstreams, which is very useful for +understanding the encoding.

+ +
+ + + + +
+ +

The first two bytes of a bitcode file are 'BC' (0x42, 0x43). +The second two bytes are an application-specific magic number. Generic +bitcode tools can look at only the first two bytes to verify the file is +bitcode, while application-specific programs will want to look at all four.

+ +
+ + + + +
+ +

+A bitstream literally consists of a stream of bits, which are read in order +starting with the least significant bit of each byte. The stream is made up of a +number of primitive values that encode a stream of unsigned integer values. +These integers are encoded in two ways: either as Fixed +Width Integers or as Variable Width +Integers. +

+ +
+ + + + +
+ +

Fixed-width integer values have their low bits emitted directly to the file. + For example, a 3-bit integer value encodes 1 as 001. Fixed width integers + are used when there are a well-known number of options for a field. For + example, boolean values are usually encoded with a 1-bit wide integer. +

+ +
+ + + + +
+ +

Variable-width integer (VBR) values encode values of arbitrary size, +optimizing for the case where the values are small. Given a 4-bit VBR field, +any 3-bit value (0 through 7) is encoded directly, with the high bit set to +zero. Values larger than N-1 bits emit their bits in a series of N-1 bit +chunks, where all but the last set the high bit.

+ +

For example, the value 27 (0x1B) is encoded as 1011 0011 when emitted as a +vbr4 value. The first set of four bits indicates the value 3 (011) with a +continuation piece (indicated by a high bit of 1). The next word indicates a +value of 24 (011 << 3) with no continuation. The sum (3+24) yields the value +27. +

+ +
+ + + + +
+ +

6-bit characters encode common characters into a fixed 6-bit field. They +represent the following characters with the following 6-bit values:

+ +
+
+'a' .. 'z' —  0 .. 25
+'A' .. 'Z' — 26 .. 51
+'0' .. '9' — 52 .. 61
+       '.' — 62
+       '_' — 63
+
+
+ +

This encoding is only suitable for encoding characters and strings that +consist only of the above characters. It is completely incapable of encoding +characters not in the set.

+ +
+ + + + +
+ +

Occasionally, it is useful to emit zero bits until the bitstream is a +multiple of 32 bits. This ensures that the bit position in the stream can be +represented as a multiple of 32-bit words.

+ +
+ + + + + +
+ +

+A bitstream is a sequential series of Blocks and +Data Records. Both of these start with an +abbreviation ID encoded as a fixed-bitwidth field. The width is specified by +the current block, as described below. The value of the abbreviation ID +specifies either a builtin ID (which have special meanings, defined below) or +one of the abbreviation IDs defined for the current block by the stream itself. +

+ +

+The set of builtin abbrev IDs is: +

+ +
    +
  • 0 - END_BLOCK — This abbrev ID marks + the end of the current block.
  • +
  • 1 - ENTER_SUBBLOCK — This + abbrev ID marks the beginning of a new block.
  • +
  • 2 - DEFINE_ABBREV — This defines + a new abbreviation.
  • +
  • 3 - UNABBREV_RECORD — This ID + specifies the definition of an unabbreviated record.
  • +
+ +

Abbreviation IDs 4 and above are defined by the stream itself, and specify +an abbreviated record encoding.

+ +
+ + + + +
+ +

+Blocks in a bitstream denote nested regions of the stream, and are identified by +a content-specific id number (for example, LLVM IR uses an ID of 12 to represent +function bodies). Block IDs 0-7 are reserved for standard blocks +whose meaning is defined by Bitcode; block IDs 8 and greater are +application specific. Nested blocks capture the hierarchical structure of the data +encoded in it, and various properties are associated with blocks as the file is +parsed. Block definitions allow the reader to efficiently skip blocks +in constant time if the reader wants a summary of blocks, or if it wants to +efficiently skip data it does not understand. The LLVM IR reader uses this +mechanism to skip function bodies, lazily reading them on demand. +

+ +

+When reading and encoding the stream, several properties are maintained for the +block. In particular, each block maintains: +

+ +
    +
  1. A current abbrev id width. This value starts at 2 at the beginning of + the stream, and is set every time a + block record is entered. The block entry specifies the abbrev id width for + the body of the block.
  2. + +
  3. A set of abbreviations. Abbreviations may be defined within a block, in + which case they are only defined in that block (neither subblocks nor + enclosing blocks see the abbreviation). Abbreviations can also be defined + inside a BLOCKINFO block, in which case + they are defined in all blocks that match the ID that the BLOCKINFO block is + describing. +
  4. +
+ +

+As sub blocks are entered, these properties are saved and the new sub-block has +its own set of abbreviations, and its own abbrev id width. When a sub-block is +popped, the saved values are restored. +

+ +
+ + + + +
+ +

[ENTER_SUBBLOCK, blockidvbr8, newabbrevlenvbr4, + <align32bits>, blocklen32]

+ +

+The ENTER_SUBBLOCK abbreviation ID specifies the start of a new block +record. The blockid value is encoded as an 8-bit VBR identifier, and +indicates the type of block being entered, which can be +a standard block or an application-specific block. +The newabbrevlen value is a 4-bit VBR, which specifies the abbrev id +width for the sub-block. The blocklen value is a 32-bit aligned value +that specifies the size of the subblock in 32-bit words. This value allows the +reader to skip over the entire block in one jump. +

+ +
+ + + + +
+ +

[END_BLOCK, <align32bits>]

+ +

+The END_BLOCK abbreviation ID specifies the end of the current block +record. Its end is aligned to 32-bits to ensure that the size of the block is +an even multiple of 32-bits. +

+ +
+ + + + + + +
+

+Data records consist of a record code and a number of (up to) 64-bit +integer values. The interpretation of the code and values is +application specific and may vary between different block types. +Records can be encoded either using an unabbrev record, or with an +abbreviation. In the LLVM IR format, for example, there is a record +which encodes the target triple of a module. The code is +MODULE_CODE_TRIPLE, and the values of the record are the +ASCII codes for the characters in the string. +

+ +
+ + + + +
+ +

[UNABBREV_RECORD, codevbr6, numopsvbr6, + op0vbr6, op1vbr6, ...]

+ +

+An UNABBREV_RECORD provides a default fallback encoding, which is both +completely general and extremely inefficient. It can describe an arbitrary +record by emitting the code and operands as VBRs. +

+ +

+For example, emitting an LLVM IR target triple as an unabbreviated record +requires emitting the UNABBREV_RECORD abbrevid, a vbr6 for the +MODULE_CODE_TRIPLE code, a vbr6 for the length of the string, which is +equal to the number of operands, and a vbr6 for each character. Because there +are no letters with values less than 32, each letter would need to be emitted as +at least a two-part VBR, which means that each letter would require at least 12 +bits. This is not an efficient encoding, but it is fully general. +

+ +
+ + + + +
+ +

[<abbrevid>, fields...]

+ +

+An abbreviated record is a abbreviation id followed by a set of fields that are +encoded according to the abbreviation definition. +This allows records to be encoded significantly more densely than records +encoded with the UNABBREV_RECORD type, +and allows the abbreviation types to be specified in the stream itself, which +allows the files to be completely self describing. The actual encoding of +abbreviations is defined below. +

+ +

The record code, which is the first field of an abbreviated record, +may be encoded in the abbreviation definition (as a literal +operand) or supplied in the abbreviated record (as a Fixed or VBR +operand value).

+ +
+ + + + +
+

+Abbreviations are an important form of compression for bitstreams. The idea is +to specify a dense encoding for a class of records once, then use that encoding +to emit many records. It takes space to emit the encoding into the file, but +the space is recouped (hopefully plus some) when the records that use it are +emitted. +

+ +

+Abbreviations can be determined dynamically per client, per file. Because the +abbreviations are stored in the bitstream itself, different streams of the same +format can contain different sets of abbreviations according to the needs +of the specific stream. +As a concrete example, LLVM IR files usually emit an abbreviation +for binary operators. If a specific LLVM module contained no or few binary +operators, the abbreviation does not need to be emitted. +

+
+ + + + +
+ +

[DEFINE_ABBREV, numabbrevopsvbr5, abbrevop0, abbrevop1, + ...]

+ +

+A DEFINE_ABBREV record adds an abbreviation to the list of currently +defined abbreviations in the scope of this block. This definition only exists +inside this immediate block — it is not visible in subblocks or enclosing +blocks. Abbreviations are implicitly assigned IDs sequentially starting from 4 +(the first application-defined abbreviation ID). Any abbreviations defined in a +BLOCKINFO record for the particular block type +receive IDs first, in order, followed by any +abbreviations defined within the block itself. Abbreviated data records +reference this ID to indicate what abbreviation they are invoking. +

+ +

+An abbreviation definition consists of the DEFINE_ABBREV abbrevid +followed by a VBR that specifies the number of abbrev operands, then the abbrev +operands themselves. Abbreviation operands come in three forms. They all start +with a single bit that indicates whether the abbrev operand is a literal operand +(when the bit is 1) or an encoding operand (when the bit is 0). +

+ +
    +
  1. Literal operands — [11, litvaluevbr8] +— Literal operands specify that the value in the result is always a single +specific value. This specific value is emitted as a vbr8 after the bit +indicating that it is a literal operand.
  2. +
  3. Encoding info without data — [01, + encoding3] — Operand encodings that do not have extra + data are just emitted as their code. +
  4. +
  5. Encoding info with data — [01, encoding3, +valuevbr5] — Operand encodings that do have extra data are +emitted as their code, followed by the extra data. +
  6. +
+ +

The possible operand encodings are:

+ +
    +
  • Fixed (code 1): The field should be emitted as + a fixed-width value, whose width is specified by + the operand's extra data.
  • +
  • VBR (code 2): The field should be emitted as + a variable-width value, whose width is + specified by the operand's extra data.
  • +
  • Array (code 3): This field is an array of values. The array operand + has no extra data, but expects another operand to follow it, indicating + the element type of the array. When reading an array in an abbreviated + record, the first integer is a vbr6 that indicates the array length, + followed by the encoded elements of the array. An array may only occur as + the last operand of an abbreviation (except for the one final operand that + gives the array's type).
  • +
  • Char6 (code 4): This field should be emitted as + a char6-encoded value. This operand type takes no + extra data. Char6 encoding is normally used as an array element type. +
  • +
  • Blob (code 5): This field is emitted as a vbr6, followed by padding to a + 32-bit boundary (for alignment) and an array of 8-bit objects. The array of + bytes is further followed by tail padding to ensure that its total length is + a multiple of 4 bytes. This makes it very efficient for the reader to + decode the data without having to make a copy of it: it can use a pointer to + the data in the mapped in file and poke directly at it. A blob may only + occur as the last operand of an abbreviation.
  • +
+ +

+For example, target triples in LLVM modules are encoded as a record of the +form [TRIPLE, 'a', 'b', 'c', 'd']. Consider if the bitstream emitted +the following abbrev entry: +

+ +
+
+[0, Fixed, 4]
+[0, Array]
+[0, Char6]
+
+
+ +

+When emitting a record with this abbreviation, the above entry would be emitted +as: +

+ +
+

+[4abbrevwidth, 24, 4vbr6, 06, +16, 26, 36] +

+
+ +

These values are:

+ +
    +
  1. The first value, 4, is the abbreviation ID for this abbreviation.
  2. +
  3. The second value, 2, is the record code for TRIPLE records within LLVM IR file MODULE_BLOCK blocks.
  4. +
  5. The third value, 4, is the length of the array.
  6. +
  7. The rest of the values are the char6 encoded values + for "abcd".
  8. +
+ +

+With this abbreviation, the triple is emitted with only 37 bits (assuming a +abbrev id width of 3). Without the abbreviation, significantly more space would +be required to emit the target triple. Also, because the TRIPLE value +is not emitted as a literal in the abbreviation, the abbreviation can also be +used for any other string value. +

+ +
+ + + + +
+ +

+In addition to the basic block structure and record encodings, the bitstream +also defines specific built-in block types. These block types specify how the +stream is to be decoded or other metadata. In the future, new standard blocks +may be added. Block IDs 0-7 are reserved for standard blocks. +

+ +
+ + + + +
+ +

+The BLOCKINFO block allows the description of metadata for other +blocks. The currently specified records are: +

+ +
+
+[SETBID (#1), blockid]
+[DEFINE_ABBREV, ...]
+[BLOCKNAME, ...name...]
+[SETRECORDNAME, RecordID, ...name...]
+
+
+ +

+The SETBID record (code 1) indicates which block ID is being +described. SETBID records can occur multiple times throughout the +block to change which block ID is being described. There must be +a SETBID record prior to any other records. +

+ +

+Standard DEFINE_ABBREV records can occur inside BLOCKINFO +blocks, but unlike their occurrence in normal blocks, the abbreviation is +defined for blocks matching the block ID we are describing, not the +BLOCKINFO block itself. The abbreviations defined +in BLOCKINFO blocks receive abbreviation IDs as described +in DEFINE_ABBREV. +

+ +

The BLOCKNAME record (code 2) can optionally occur in this block. The elements of +the record are the bytes of the string name of the block. llvm-bcanalyzer can use +this to dump out bitcode files symbolically.

+ +

The SETRECORDNAME record (code 3) can also optionally occur in this block. The +first operand value is a record ID number, and the rest of the elements of the record are +the bytes for the string name of the record. llvm-bcanalyzer can use +this to dump out bitcode files symbolically.

+ +

+Note that although the data in BLOCKINFO blocks is described as +"metadata," the abbreviations they contain are essential for parsing records +from the corresponding blocks. It is not safe to skip them. +

+ +
+ + + + + +
+ +

+Bitcode files for LLVM IR may optionally be wrapped in a simple wrapper +structure. This structure contains a simple header that indicates the offset +and size of the embedded BC file. This allows additional information to be +stored alongside the BC file. The structure of this file header is: +

+ +
+

+[Magic32, Version32, Offset32, +Size32, CPUType32] +

+
+ +

+Each of the fields are 32-bit fields stored in little endian form (as with +the rest of the bitcode file fields). The Magic number is always +0x0B17C0DE and the version is currently always 0. The Offset +field is the offset in bytes to the start of the bitcode stream in the file, and +the Size field is the size in bytes of the stream. CPUType is a target-specific +value that can be used to encode the CPU of the target. +

+ +
+ + + + + +
+ +

+LLVM IR is encoded into a bitstream by defining blocks and records. It uses +blocks for things like constant pools, functions, symbol tables, etc. It uses +records for things like instructions, global variable descriptors, type +descriptions, etc. This document does not describe the set of abbreviations +that the writer uses, as these are fully self-described in the file, and the +reader is not allowed to build in any knowledge of this. +

+ +
+ + + + + + + +
+ +

+The magic number for LLVM IR files is: +

+ +
+

+[0x04, 0xC4, 0xE4, 0xD4] +

+
+ +

+When combined with the bitcode magic number and viewed as bytes, this is +"BC 0xC0DE". +

+ +
+ + + + +
+ +

+Variable Width Integer encoding is an efficient way to +encode arbitrary sized unsigned values, but is an extremely inefficient for +encoding signed values, as signed values are otherwise treated as maximally large +unsigned values. +

+ +

+As such, signed VBR values of a specific width are emitted as follows: +

+ +
    +
  • Positive values are emitted as VBRs of the specified width, but with their + value shifted left by one.
  • +
  • Negative values are emitted as VBRs of the specified width, but the negated + value is shifted left by one, and the low bit is set.
  • +
+ +

+With this encoding, small positive and small negative values can both +be emitted efficiently. Signed VBR encoding is used in +CST_CODE_INTEGER and CST_CODE_WIDE_INTEGER records +within CONSTANTS_BLOCK blocks. +

+ +
+ + + + + +
+ +

+LLVM IR is defined with the following blocks: +

+ +
    +
  • 8 — MODULE_BLOCK — This is the top-level block that + contains the entire module, and describes a variety of per-module + information.
  • +
  • 9 — PARAMATTR_BLOCK — This enumerates the parameter + attributes.
  • +
  • 10 — TYPE_BLOCK — This describes all of the types in + the module.
  • +
  • 11 — CONSTANTS_BLOCK — This describes constants for a + module or function.
  • +
  • 12 — FUNCTION_BLOCK — This describes a function + body.
  • +
  • 13 — TYPE_SYMTAB_BLOCK — This describes the type symbol + table.
  • +
  • 14 — VALUE_SYMTAB_BLOCK — This describes a value symbol + table.
  • +
  • 15 — METADATA_BLOCK — This describes metadata items.
  • +
  • 16 — METADATA_ATTACHMENT — This contains records associating metadata with function instruction values.
  • +
+ +
+ + + + +
+ +

The MODULE_BLOCK block (id 8) is the top-level block for LLVM +bitcode files, and each bitcode file must contain exactly one. In +addition to records (described below) containing information +about the module, a MODULE_BLOCK block may contain the +following sub-blocks: +

+ + + +
+ + + + +
+ +

[VERSION, version#]

+ +

The VERSION record (code 1) contains a single value +indicating the format version. Only version 0 is supported at this +time.

+
+ + + + +
+

[TRIPLE, ...string...]

+ +

The TRIPLE record (code 2) contains a variable number of +values representing the bytes of the target triple +specification string.

+
+ + + + +
+

[DATALAYOUT, ...string...]

+ +

The DATALAYOUT record (code 3) contains a variable number of +values representing the bytes of the target datalayout +specification string.

+
+ + + + +
+

[ASM, ...string...]

+ +

The ASM record (code 4) contains a variable number of +values representing the bytes of module asm strings, with +individual assembly blocks separated by newline (ASCII 10) characters.

+
+ + + + +
+

[SECTIONNAME, ...string...]

+ +

The SECTIONNAME record (code 5) contains a variable number +of values representing the bytes of a single section name +string. There should be one SECTIONNAME record for each +section name referenced (e.g., in global variable or function +section attributes) within the module. These records can be +referenced by the 1-based index in the section fields of +GLOBALVAR or FUNCTION records.

+
+ + + + +
+

[DEPLIB, ...string...]

+ +

The DEPLIB record (code 6) contains a variable number of +values representing the bytes of a single dependent library name +string, one of the libraries mentioned in a deplibs +declaration. There should be one DEPLIB record for each +library name referenced.

+
+ + + + +
+

[GLOBALVAR, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal]

+ +

The GLOBALVAR record (code 7) marks the declaration or +definition of a global variable. The operand fields are:

+ +
    +
  • pointer type: The type index of the pointer type used to point to +this global variable
  • + +
  • isconst: Non-zero if the variable is treated as constant within +the module, or zero if it is not
  • + +
  • initid: If non-zero, the value index of the initializer for this +variable, plus 1.
  • + +
  • linkage: An encoding of the linkage +type for this variable: +
      +
    • external: code 0
    • +
    • weak: code 1
    • +
    • appending: code 2
    • +
    • internal: code 3
    • +
    • linkonce: code 4
    • +
    • dllimport: code 5
    • +
    • dllexport: code 6
    • +
    • extern_weak: code 7
    • +
    • common: code 8
    • +
    • private: code 9
    • +
    • weak_odr: code 10
    • +
    • linkonce_odr: code 11
    • +
    • available_externally: code 12
    • +
    • linker_private: code 13
    • +
    +
  • + +
  • alignment: The logarithm base 2 of the variable's requested +alignment, plus 1
  • + +
  • section: If non-zero, the 1-based section index in the +table of MODULE_CODE_SECTIONNAME +entries.
  • + +
  • visibility: If present, an +encoding of the visibility of this variable: +
      +
    • default: code 0
    • +
    • hidden: code 1
    • +
    • protected: code 2
    • +
    +
  • + +
  • threadlocal: If present and non-zero, indicates that the variable +is thread_local
  • + +
  • unnamed_addr: If present and non-zero, indicates that the variable +has unnamed_addr
  • + +
+
+ + + + +
+ +

[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc]

+ +

The FUNCTION record (code 8) marks the declaration or +definition of a function. The operand fields are:

+ +
    +
  • type: The type index of the function type describing this function
  • + +
  • callingconv: The calling convention number: +
      +
    • ccc: code 0
    • +
    • fastcc: code 8
    • +
    • coldcc: code 9
    • +
    • x86_stdcallcc: code 64
    • +
    • x86_fastcallcc: code 65
    • +
    • arm_apcscc: code 66
    • +
    • arm_aapcscc: code 67
    • +
    • arm_aapcs_vfpcc: code 68
    • +
    +
  • + +
  • isproto: Non-zero if this entry represents a declaration +rather than a definition
  • + +
  • linkage: An encoding of the linkage type +for this function
  • + +
  • paramattr: If nonzero, the 1-based parameter attribute index +into the table of PARAMATTR_CODE_ENTRY +entries.
  • + +
  • alignment: The logarithm base 2 of the function's requested +alignment, plus 1
  • + +
  • section: If non-zero, the 1-based section index in the +table of MODULE_CODE_SECTIONNAME +entries.
  • + +
  • visibility: An encoding of the visibility + of this function
  • + +
  • gc: If present and nonzero, the 1-based garbage collector +index in the table of +MODULE_CODE_GCNAME entries.
  • + +
  • unnamed_addr: If present and non-zero, indicates that the function +has unnamed_addr
  • + +
+
+ + + + +
+ +

[ALIAS, alias type, aliasee val#, linkage, visibility]

+ +

The ALIAS record (code 9) marks the definition of an +alias. The operand fields are

+ +
    +
  • alias type: The type index of the alias
  • + +
  • aliasee val#: The value index of the aliased value
  • + +
  • linkage: An encoding of the linkage type +for this alias
  • + +
  • visibility: If present, an encoding of the +visibility of the alias
  • + +
+
+ + + + +
+

[PURGEVALS, numvals]

+ +

The PURGEVALS record (code 10) resets the module-level +value list to the size given by the single operand value. Module-level +value list items are added by GLOBALVAR, FUNCTION, +and ALIAS records. After a PURGEVALS record is seen, +new value indices will start from the given numvals value.

+
+ + + + +
+

[GCNAME, ...string...]

+ +

The GCNAME record (code 11) contains a variable number of +values representing the bytes of a single garbage collector name +string. There should be one GCNAME record for each garbage +collector name referenced in function gc attributes within +the module. These records can be referenced by 1-based index in the gc +fields of FUNCTION records.

+
+ + + + +
+ +

The PARAMATTR_BLOCK block (id 9) contains a table of +entries describing the attributes of function parameters. These +entries are referenced by 1-based index in the paramattr field +of module block FUNCTION +records, or within the attr field of function block INST_INVOKE and INST_CALL records.

+ +

Entries within PARAMATTR_BLOCK are constructed to ensure +that each is unique (i.e., no two indicies represent equivalent +attribute lists).

+ +
+ + + + + +
+ +

[ENTRY, paramidx0, attr0, paramidx1, attr1...]

+ +

The ENTRY record (code 1) contains an even number of +values describing a unique set of function parameter attributes. Each +paramidx value indicates which set of attributes is +represented, with 0 representing the return value attributes, +0xFFFFFFFF representing function attributes, and other values +representing 1-based function parameters. Each attr value is a +bitmap with the following interpretation: +

+ +
    +
  • bit 0: zeroext
  • +
  • bit 1: signext
  • +
  • bit 2: noreturn
  • +
  • bit 3: inreg
  • +
  • bit 4: sret
  • +
  • bit 5: nounwind
  • +
  • bit 6: noalias
  • +
  • bit 7: byval
  • +
  • bit 8: nest
  • +
  • bit 9: readnone
  • +
  • bit 10: readonly
  • +
  • bit 11: noinline
  • +
  • bit 12: alwaysinline
  • +
  • bit 13: optsize
  • +
  • bit 14: ssp
  • +
  • bit 15: sspreq
  • +
  • bits 16–31: align n
  • +
  • bit 32: nocapture
  • +
  • bit 33: noredzone
  • +
  • bit 34: noimplicitfloat
  • +
  • bit 35: naked
  • +
  • bit 36: inlinehint
  • +
  • bits 37–39: alignstack n, represented as +the logarithm base 2 of the requested alignment, plus 1
  • +
+
+ + + + +
+ +

The TYPE_BLOCK block (id 10) contains records which +constitute a table of type operator entries used to represent types +referenced within an LLVM module. Each record (with the exception of +NUMENTRY) generates a +single type table entry, which may be referenced by 0-based index from +instructions, constants, metadata, type symbol table entries, or other +type operator records. +

+ +

Entries within TYPE_BLOCK are constructed to ensure that +each entry is unique (i.e., no two indicies represent structurally +equivalent types).

+ +
+ + + + +
+ +

[NUMENTRY, numentries]

+ +

The NUMENTRY record (code 1) contains a single value which +indicates the total number of type code entries in the type table of +the module. If present, NUMENTRY should be the first record +in the block. +

+
+ + + + +
+ +

[VOID]

+ +

The VOID record (code 2) adds a void type to the +type table. +

+
+ + + + +
+ +

[FLOAT]

+ +

The FLOAT record (code 3) adds a float (32-bit +floating point) type to the type table. +

+
+ + + + +
+ +

[DOUBLE]

+ +

The DOUBLE record (code 4) adds a double (64-bit +floating point) type to the type table. +

+
+ + + + +
+ +

[LABEL]

+ +

The LABEL record (code 5) adds a label type to +the type table. +

+
+ + + + +
+ +

[OPAQUE]

+ +

The OPAQUE record (code 6) adds an opaque type to +the type table. Note that distinct opaque types are not +unified. +

+
+ + + + +
+ +

[INTEGER, width]

+ +

The INTEGER record (code 7) adds an integer type to the +type table. The single width field indicates the width of the +integer type. +

+
+ + + + +
+ +

[POINTER, pointee type, address space]

+ +

The POINTER record (code 8) adds a pointer type to the +type table. The operand fields are

+ +
    +
  • pointee type: The type index of the pointed-to type
  • + +
  • address space: If supplied, the target-specific numbered +address space where the pointed-to object resides. Otherwise, the +default address space is zero. +
  • +
+
+ + + + +
+ +

[FUNCTION, vararg, ignored, retty, ...paramty... ]

+ +

The FUNCTION record (code 9) adds a function type to the +type table. The operand fields are

+ +
    +
  • vararg: Non-zero if the type represents a varargs function
  • + +
  • ignored: This value field is present for backward +compatibility only, and is ignored
  • + +
  • retty: The type index of the function's return type
  • + +
  • paramty: Zero or more type indices representing the +parameter types of the function
  • +
+ +
+ + + + +
+ +

[STRUCT, ispacked, ...eltty...]

+ +

The STRUCT record (code 10) adds a struct type to the +type table. The operand fields are

+ +
    +
  • ispacked: Non-zero if the type represents a packed structure
  • + +
  • eltty: Zero or more type indices representing the element +types of the structure
  • +
+
+ + + + +
+ +

[ARRAY, numelts, eltty]

+ +

The ARRAY record (code 11) adds an array type to the type +table. The operand fields are

+ +
    +
  • numelts: The number of elements in arrays of this type
  • + +
  • eltty: The type index of the array element type
  • +
+
+ + + + +
+ +

[VECTOR, numelts, eltty]

+ +

The VECTOR record (code 12) adds a vector type to the type +table. The operand fields are

+ +
    +
  • numelts: The number of elements in vectors of this type
  • + +
  • eltty: The type index of the vector element type
  • +
+
+ + + + +
+ +

[X86_FP80]

+ +

The X86_FP80 record (code 13) adds an x86_fp80 (80-bit +floating point) type to the type table. +

+
+ + + + +
+ +

[FP128]

+ +

The FP128 record (code 14) adds an fp128 (128-bit +floating point) type to the type table. +

+
+ + + + +
+ +

[PPC_FP128]

+ +

The PPC_FP128 record (code 15) adds a ppc_fp128 +(128-bit floating point) type to the type table. +

+
+ + + + +
+ +

[METADATA]

+ +

The METADATA record (code 16) adds a metadata +type to the type table. +

+
+ + + + +
+ +

The CONSTANTS_BLOCK block (id 11) ... +

+ +
+ + + + + +
+ +

The FUNCTION_BLOCK block (id 12) ... +

+ +

In addition to the record types described below, a +FUNCTION_BLOCK block may contain the following sub-blocks: +

+ + + +
+ + + + + +
+ +

The TYPE_SYMTAB_BLOCK block (id 13) contains entries which +map between module-level named types and their corresponding type +indices. +

+ +
+ + + + +
+ +

[ENTRY, typeid, ...string...]

+ +

The ENTRY record (code 1) contains a variable number of +values, with the first giving the type index of the designated type, +and the remaining values giving the character codes of the type +name. Each entry corresponds to a single named type. +

+
+ + + + + +
+ +

The VALUE_SYMTAB_BLOCK block (id 14) ... +

+ +
+ + + + + +
+ +

The METADATA_BLOCK block (id 15) ... +

+ +
+ + + + + +
+ +

The METADATA_ATTACHMENT block (id 16) ... +

+ +
+ + + +
+
Valid CSS +Valid HTML 4.01 + Chris Lattner
+The LLVM Compiler Infrastructure
+Last modified: $Date$ +
+ + diff --git a/final/docs/Bugpoint.html b/final/docs/Bugpoint.html new file mode 100644 index 00000000000..bf75b5ba44c --- /dev/null +++ b/final/docs/Bugpoint.html @@ -0,0 +1,250 @@ + + + + LLVM bugpoint tool: design and usage + + + +
+ LLVM bugpoint tool: design and usage +
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

bugpoint narrows down the source of problems in LLVM tools and +passes. It can be used to debug three types of failures: optimizer crashes, +miscompilations by optimizers, or bad native code generation (including problems +in the static and JIT compilers). It aims to reduce large test cases to small, +useful ones. For example, if opt crashes while optimizing a +file, it will identify the optimization (or combination of optimizations) that +causes the crash, and reduce the file down to a small example which triggers the +crash.

+ +

For detailed case scenarios, such as debugging opt, +llvm-ld, or one of the LLVM code generators, see How To Submit a Bug Report document.

+ +
+ + + + + +
+ +

bugpoint is designed to be a useful tool without requiring any +hooks into the LLVM infrastructure at all. It works with any and all LLVM +passes and code generators, and does not need to "know" how they work. Because +of this, it may appear to do stupid things or miss obvious +simplifications. bugpoint is also designed to trade off programmer +time for computer time in the compiler-debugging process; consequently, it may +take a long period of (unattended) time to reduce a test case, but we feel it +is still worth it. Note that bugpoint is generally very quick unless +debugging a miscompilation where each test of the program (which requires +executing it) takes a long time.

+ +
+ + + + +
+ +

bugpoint reads each .bc or .ll file specified on +the command line and links them together into a single module, called the test +program. If any LLVM passes are specified on the command line, it runs these +passes on the test program. If any of the passes crash, or if they produce +malformed output (which causes the verifier to abort), bugpoint starts +the crash debugger.

+ +

Otherwise, if the -output option was not specified, +bugpoint runs the test program with the C backend (which is assumed to +generate good code) to generate a reference output. Once bugpoint has +a reference output for the test program, it tries executing it with the +selected code generator. If the selected code generator crashes, +bugpoint starts the crash debugger on the +code generator. Otherwise, if the resulting output differs from the reference +output, it assumes the difference resulted from a code generator failure, and +starts the code generator debugger.

+ +

Finally, if the output of the selected code generator matches the reference +output, bugpoint runs the test program after all of the LLVM passes +have been applied to it. If its output differs from the reference output, it +assumes the difference resulted from a failure in one of the LLVM passes, and +enters the miscompilation debugger. +Otherwise, there is no problem bugpoint can debug.

+ +
+ + + + +
+ +

If an optimizer or code generator crashes, bugpoint will try as hard +as it can to reduce the list of passes (for optimizer crashes) and the size of +the test program. First, bugpoint figures out which combination of +optimizer passes triggers the bug. This is useful when debugging a problem +exposed by opt, for example, because it runs over 38 passes.

+ +

Next, bugpoint tries removing functions from the test program, to +reduce its size. Usually it is able to reduce a test program to a single +function, when debugging intraprocedural optimizations. Once the number of +functions has been reduced, it attempts to delete various edges in the control +flow graph, to reduce the size of the function as much as possible. Finally, +bugpoint deletes any individual LLVM instructions whose absence does +not eliminate the failure. At the end, bugpoint should tell you what +passes crash, give you a bitcode file, and give you instructions on how to +reproduce the failure with opt or llc.

+ +
+ + + + +
+ +

The code generator debugger attempts to narrow down the amount of code that +is being miscompiled by the selected code generator. To do this, it takes the +test program and partitions it into two pieces: one piece which it compiles +with the C backend (into a shared object), and one piece which it runs with +either the JIT or the static LLC compiler. It uses several techniques to +reduce the amount of code pushed through the LLVM code generator, to reduce the +potential scope of the problem. After it is finished, it emits two bitcode +files (called "test" [to be compiled with the code generator] and "safe" [to be +compiled with the C backend], respectively), and instructions for reproducing +the problem. The code generator debugger assumes that the C backend produces +good code.

+ +
+ + + + +
+ +

The miscompilation debugger works similarly to the code generator debugger. +It works by splitting the test program into two pieces, running the +optimizations specified on one piece, linking the two pieces back together, and +then executing the result. It attempts to narrow down the list of passes to +the one (or few) which are causing the miscompilation, then reduce the portion +of the test program which is being miscompiled. The miscompilation debugger +assumes that the selected code generator is working properly.

+ +
+ + + + + +
+ +bugpoint can be a remarkably useful tool, but it sometimes works in +non-obvious ways. Here are some hints and tips:

+ +

    +
  1. In the code generator and miscompilation debuggers, bugpoint only + works with programs that have deterministic output. Thus, if the program + outputs argv[0], the date, time, or any other "random" data, + bugpoint may misinterpret differences in these data, when output, + as the result of a miscompilation. Programs should be temporarily modified + to disable outputs that are likely to vary from run to run. + +
  2. In the code generator and miscompilation debuggers, debugging will go + faster if you manually modify the program or its inputs to reduce the + runtime, but still exhibit the problem. + +
  3. bugpoint is extremely useful when working on a new optimization: + it helps track down regressions quickly. To avoid having to relink + bugpoint every time you change your optimization however, have + bugpoint dynamically load your optimization with the + -load option. + +
  4. bugpoint can generate a lot of output and run for a long period + of time. It is often useful to capture the output of the program to file. + For example, in the C shell, you can run:

    + +
    +

    bugpoint ... |& tee bugpoint.log

    +
    + +

    to get a copy of bugpoint's output in the file + bugpoint.log, as well as on your terminal.

    + +
  5. bugpoint cannot debug problems with the LLVM linker. If + bugpoint crashes before you see its "All input ok" message, + you might try llvm-link -v on the same set of input files. If + that also crashes, you may be experiencing a linker bug. + +
  6. bugpoint is useful for proactively finding bugs in LLVM. + Invoking bugpoint with the -find-bugs option will cause + the list of specified optimizations to be randomized and applied to the + program. This process will repeat until a bug is found or the user + kills bugpoint. + +
  7. bugpoint does not understand the -O option + that is used to specify optimization level to opt. You + can use e.g.

    + +
    +

    opt -O2 -debug-pass=Arguments foo.bc -disable-output

    +
    + +

    to get a list of passes that are used with -O2 and + then pass this list to bugpoint.

    + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/CFEBuildInstrs.html b/final/docs/CFEBuildInstrs.html new file mode 100644 index 00000000000..ed2f295b7af --- /dev/null +++ b/final/docs/CFEBuildInstrs.html @@ -0,0 +1,29 @@ + + + + + + Building the LLVM C/C++ Front-End + + + +
+This page has moved here. +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date: 2008-02-13 17:46:10 +0100 (Wed, 13 Feb 2008) $ +
+ + + diff --git a/final/docs/CMake.html b/final/docs/CMake.html new file mode 100644 index 00000000000..c88b1249021 --- /dev/null +++ b/final/docs/CMake.html @@ -0,0 +1,486 @@ + + + + Building LLVM with CMake + + + +
+ Building LLVM with CMake +
+ + + +
+

Written by Oscar Fuentes

+
+ + + + + +
+ +

CMake is a cross-platform + build-generator tool. CMake does not build the project, it generates + the files needed by your build tool (GNU make, Visual Studio, etc) for + building LLVM.

+ +

If you are really anxious about getting a functional LLVM build, + go to the Quick start section. If you + are a CMake novice, start on Basic CMake + usage and then go back to the Quick + start once you know what you are + doing. The Options and variables section + is a reference for customizing your build. If you already have + experience with CMake, this is the recommended starting point. +

+ + + + + +
+ +

We use here the command-line, non-interactive CMake interface

+ +
    + +
  1. Download + and install CMake. Version 2.8 is the minimum required.

    + +
  2. Open a shell. Your development tools must be reachable from this + shell through the PATH environment variable.

    + +
  3. Create a directory for containing the build. It is not + supported to build LLVM on the source directory. cd to this + directory:

    +
    +

    mkdir mybuilddir

    +

    cd mybuilddir

    +
    + +
  4. Execute this command on the shell + replacing path/to/llvm/source/root with the path to the + root of your LLVM source tree:

    +
    +

    cmake path/to/llvm/source/root

    +
    + +

    CMake will detect your development environment, perform a + series of test and generate the files required for building + LLVM. CMake will use default values for all build + parameters. See the Options and variables + section for fine-tuning your build

    + +

    This can fail if CMake can't detect your toolset, or if it + thinks that the environment is not sane enough. On this case + make sure that the toolset that you intend to use is the only + one reachable from the shell and that the shell itself is the + correct one for you development environment. CMake will refuse + to build MinGW makefiles if you have a POSIX shell reachable + through the PATH environment variable, for instance. You can + force CMake to use a given build tool, see + the Usage section.

    + +
+ +
+ + + + + +
+ +

This section explains basic aspects of CMake, mostly for + explaining those options which you may need on your day-to-day + usage.

+ +

CMake comes with extensive documentation in the form of html + files and on the cmake executable itself. Execute cmake + --help for further help options.

+ +

CMake requires to know for which build tool it shall generate + files (GNU make, Visual Studio, Xcode, etc). If not specified on + the command line, it tries to guess it based on you + environment. Once identified the build tool, CMake uses the + corresponding Generator for creating files for your build + tool. You can explicitly specify the generator with the command + line option -G "Name of the generator". For knowing the + available generators on your platform, execute

+ +
+

cmake --help

+
+ +

This will list the generator's names at the end of the help + text. Generator's names are case-sensitive. Example:

+ +
+

cmake -G "Visual Studio 8 2005" path/to/llvm/source/root

+
+ +

For a given development platform there can be more than one + adequate generator. If you use Visual Studio "NMake Makefiles" + is a generator you can use for building with NMake. By default, + CMake chooses the more specific generator supported by your + development environment. If you want an alternative generator, + you must tell this to CMake with the -G option.

+ +

TODO: explain variables and cache. Move explanation here from + #options section.

+ +
+ + + + + +
+ +

Variables customize how the build will be generated. Options are + boolean variables, with possible values ON/OFF. Options and + variables are defined on the CMake command line like this:

+ +
+

cmake -DVARIABLE=value path/to/llvm/source

+
+ +

You can set a variable after the initial CMake invocation for + changing its value. You can also undefine a variable:

+ +
+

cmake -UVARIABLE path/to/llvm/source

+
+ +

Variables are stored on the CMake cache. This is a file + named CMakeCache.txt on the root of the build + directory. Do not hand-edit it.

+ +

Variables are listed here appending its type after a colon. It is + correct to write the variable and the type on the CMake command + line:

+ +
+

cmake -DVARIABLE:TYPE=value path/to/llvm/source

+
+ +
+ + + + +
+ +

Here are listed some of the CMake variables that are used often, + along with a brief explanation and LLVM-specific notes. For full + documentation, check the CMake docs or execute cmake + --help-variable VARIABLE_NAME.

+ +
+
CMAKE_BUILD_TYPE:STRING
+ +
Sets the build type for make based generators. Possible + values are Release, Debug, RelWithDebInfo and MinSizeRel. On + systems like Visual Studio the user sets the build type with the IDE + settings.
+ +
CMAKE_INSTALL_PREFIX:PATH
+
Path where LLVM will be installed if "make install" is invoked + or the "INSTALL" target is built.
+ +
LLVM_LIBDIR_SUFFIX:STRING
+
Extra suffix to append to the directory where libraries are to + be installed. On a 64-bit architecture, one could use + -DLLVM_LIBDIR_SUFFIX=64 to install libraries to /usr/lib64.
+ +
CMAKE_C_FLAGS:STRING
+
Extra flags to use when compiling C source files.
+ +
CMAKE_CXX_FLAGS:STRING
+
Extra flags to use when compiling C++ source files.
+ +
BUILD_SHARED_LIBS:BOOL
+
Flag indicating is shared libraries will be built. Its default + value is OFF. Shared libraries are not supported on Windows and + not recommended in the other OSes.
+
+ +
+ + + + +
+ +
+
LLVM_TARGETS_TO_BUILD:STRING
+
Semicolon-separated list of targets to build, or all for + building all targets. Case-sensitive. For Visual C++ defaults + to X86. On the other cases defaults to all. Example: + -DLLVM_TARGETS_TO_BUILD="X86;PowerPC;Alpha".
+ +
LLVM_BUILD_TOOLS:BOOL
+
Build LLVM tools. Defaults to ON. Targets for building each tool + are generated in any case. You can build an tool separately by + invoking its target. For example, you can build llvm-as + with a makefile-based system executing make llvm-as on the + root of your build directory.
+ +
LLVM_INCLUDE_TOOLS:BOOL
+
Generate build targets for the LLVM tools. Defaults to + ON. You can use that option for disabling the generation of build + targets for the LLVM tools.
+ +
LLVM_BUILD_EXAMPLES:BOOL
+
Build LLVM examples. Defaults to OFF. Targets for building each + example are generated in any case. See documentation + for LLVM_BUILD_TOOLS above for more details.
+ +
LLVM_INCLUDE_EXAMPLES:BOOL
+
Generate build targets for the LLVM examples. Defaults to + ON. You can use that option for disabling the generation of build + targets for the LLVM examples.
+ +
LLVM_BUILD_TESTS:BOOL
+
Build LLVM unit tests. Defaults to OFF. Targets for building + each unit test are generated in any case. You can build a specific + unit test with the target UnitTestNameTests (where at this + time UnitTestName can be ADT, Analysis, ExecutionEngine, + JIT, Support, Transform, VMCore; see the subdirectories + of unittests for an updated list.) It is possible to build + all unit tests with the target UnitTests.
+ +
LLVM_INCLUDE_TESTS:BOOL
+
Generate build targets for the LLVM unit tests. Defaults to + ON. You can use that option for disabling the generation of build + targets for the LLVM unit tests.
+ +
LLVM_APPEND_VC_REV:BOOL
+
Append version control revision info (svn revision number or git + revision id) to LLVM version string (stored in the PACKAGE_VERSION + macro). For this to work cmake must be invoked before the + build. Defaults to OFF.
+ +
LLVM_ENABLE_THREADS:BOOL
+
Build with threads support, if available. Defaults to ON.
+ +
LLVM_ENABLE_ASSERTIONS:BOOL
+
Enables code assertions. Defaults to OFF if and only if + CMAKE_BUILD_TYPE is Release.
+ +
LLVM_ENABLE_PIC:BOOL
+
Add the -fPIC flag for the compiler command-line, if the + compiler supports this flag. Some systems, like Windows, do not + need this flag. Defaults to ON.
+ +
LLVM_ENABLE_WARNINGS:BOOL
+
Enable all compiler warnings. Defaults to ON.
+ +
LLVM_ENABLE_PEDANTIC:BOOL
+
Enable pedantic mode. This disable compiler specific extensions, is + possible. Defaults to ON.
+ +
LLVM_ENABLE_WERROR:BOOL
+
Stop and fail build, if a compiler warning is + triggered. Defaults to OFF.
+ +
LLVM_BUILD_32_BITS:BOOL
+
Build 32-bits executables and libraries on 64-bits systems. This + option is available only on some 64-bits unix systems. Defaults to + OFF.
+ +
LLVM_TARGET_ARCH:STRING
+
LLVM target to use for native code generation. This is required + for JIT generation. It defaults to "host", meaning that it shall + pick the architecture of the machine where LLVM is being built. If + you are cross-compiling, set it to the target architecture + name.
+ +
LLVM_TABLEGEN:STRING
+
Full path to a native TableGen executable (usually + named tblgen). This is intented for cross-compiling: if the + user sets this variable, no native TableGen will be created.
+ +
LLVM_LIT_ARGS:STRING
+
Arguments given to lit. + make check and make clang-test are affected. + By default, "-sv --no-progress-bar" + on Visual C++ and Xcode, + "-sv" on others.
+ +
LLVM_LIT_TOOLS_DIR:STRING
+
The path to GnuWin32 tools for tests. Valid on Windows host. + Defaults to "", then Lit seeks tools according to %PATH%. + Lit can find tools(eg. grep, sort, &c) on LLVM_LIT_TOOLS_DIR at first, + without specifying GnuWin32 to %PATH%.
+ +
LLVM_ENABLE_FFI:BOOL
+
Indicates whether LLVM Interpreter will be linked with Foreign + Function Interface library. If the library or its headers are + installed on a custom location, you can set the variables + FFI_INCLUDE_DIR and FFI_LIBRARY_DIR. Defaults to OFF.
+
+ +
+ + + + + +
+ +

Testing is performed when the check target is built. For + instance, if you are using makefiles, execute this command while on + the top level of your build directory:

+ +
+

make check

+
+ +

On Visual Studio, you may run tests to build the project "check".

+ +
+ + + + + +
+ +

See this + wiki page for generic instructions on how to cross-compile + with CMake. It goes into detailed explanations and may seem + daunting, but it is not. On the wiki page there are several + examples including toolchain files. Go directly to + this + section for a quick solution.

+ +

Also see the LLVM-specific variables + section for variables used when cross-compiling.

+ +
+ + + + + +
+ +

The most difficult part of adding LLVM to the build of a project + is to determine the set of LLVM libraries corresponding to the set + of required LLVM features. What follows is an example of how to + obtain this information:

+ +
+
+    # A convenience variable:
+    set(LLVM_ROOT "" CACHE PATH "Root of LLVM install.")
+    # A bit of a sanity check:
+    if( NOT EXISTS ${LLVM_ROOT}/include/llvm )
+    message(FATAL_ERROR "LLVM_ROOT (${LLVM_ROOT}) is not a valid LLVM install")
+    endif()
+    # We incorporate the CMake features provided by LLVM:
+    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LLVM_ROOT}/share/llvm/cmake")
+    include(LLVM)
+    # Now set the header and library paths:
+    include_directories( ${LLVM_ROOT}/include )
+    link_directories( ${LLVM_ROOT}/lib )
+    # Let's suppose we want to build a JIT compiler with support for
+    # binary code (no interpreter):
+    llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native)
+    # Finally, we link the LLVM libraries to our executable:
+    target_link_libraries(mycompiler ${REQ_LLVM_LIBRARIES})
+    
+
+ +

This assumes that LLVM_ROOT points to an install of LLVM. The + procedure works too for uninstalled builds although we need to take + care to add an include_directories for the location of the + headers on the LLVM source directory (if we are building + out-of-source.)

+ +
+ + + + + + + +
+ +

Notes for specific compilers and/or platforms.

+ +
+ + + +
+ +
+
LLVM_COMPILER_JOBS:STRING
+
Specifies the maximum number of parallell compiler jobs to use + per project when building with msbuild or Visual Studio. Only supported for + Visual Studio 2008 and Visual Studio 2010 CMake generators. 0 means use all + processors. Default is 0.
+
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Oscar Fuentes
+ LLVM Compiler Infrastructure
+ Last modified: $Date: 2010-08-09 03:59:36 +0100 (Mon, 9 Aug 2010) $ +
+ + + diff --git a/final/docs/CodeGenerator.html b/final/docs/CodeGenerator.html new file mode 100644 index 00000000000..a84534644cf --- /dev/null +++ b/final/docs/CodeGenerator.html @@ -0,0 +1,2817 @@ + + + + + The LLVM Target-Independent Code Generator + + + + + + + +
+ The LLVM Target-Independent Code Generator +
+ +
    +
  1. Introduction + +
  2. +
  3. Target description classes + +
  4. +
  5. The "Machine" Code Generator classes + +
  6. +
  7. The "MC" Layer + +
  8. +
  9. Target-independent code generation algorithms + +
  10. +
  11. Implementing a Native Assembler
  12. + +
  13. Target-specific Implementation Notes +
  14. + +
+ +
+

Written by the LLVM Team.

+
+ +
+

Warning: This is a work in progress.

+
+ + + + + +
+ +

The LLVM target-independent code generator is a framework that provides a + suite of reusable components for translating the LLVM internal representation + to the machine code for a specified target—either in assembly form + (suitable for a static compiler) or in binary machine code format (usable for + a JIT compiler). The LLVM target-independent code generator consists of six + main components:

+ +
    +
  1. Abstract target description interfaces which + capture important properties about various aspects of the machine, + independently of how they will be used. These interfaces are defined in + include/llvm/Target/.
  2. + +
  3. Classes used to represent the code being + generated for a target. These classes are intended to be abstract + enough to represent the machine code for any target machine. These + classes are defined in include/llvm/CodeGen/. At this level, + concepts like "constant pool entries" and "jump tables" are explicitly + exposed.
  4. + +
  5. Classes and algorithms used to represent code as the object file level, + the MC Layer. These classes represent assembly level + constructs like labels, sections, and instructions. At this level, + concepts like "constant pool entries" and "jump tables" don't exist.
  6. + +
  7. Target-independent algorithms used to implement + various phases of native code generation (register allocation, scheduling, + stack frame representation, etc). This code lives + in lib/CodeGen/.
  8. + +
  9. Implementations of the abstract target description + interfaces for particular targets. These machine descriptions make + use of the components provided by LLVM, and can optionally provide custom + target-specific passes, to build complete code generators for a specific + target. Target descriptions live in lib/Target/.
  10. + +
  11. The target-independent JIT components. The LLVM JIT is + completely target independent (it uses the TargetJITInfo + structure to interface for target-specific issues. The code for the + target-independent JIT lives in lib/ExecutionEngine/JIT.
  12. +
+ +

Depending on which part of the code generator you are interested in working + on, different pieces of this will be useful to you. In any case, you should + be familiar with the target description + and machine code representation classes. If you + want to add a backend for a new target, you will need + to implement the target description classes for + your new target and understand the LLVM code + representation. If you are interested in implementing a + new code generation algorithm, it should only + depend on the target-description and machine code representation classes, + ensuring that it is portable.

+ +
+ + + + +
+ +

The two pieces of the LLVM code generator are the high-level interface to the + code generator and the set of reusable components that can be used to build + target-specific backends. The two most important interfaces + (TargetMachine + and TargetData) are the only ones that are + required to be defined for a backend to fit into the LLVM system, but the + others must be defined if the reusable code generator components are going to + be used.

+ +

This design has two important implications. The first is that LLVM can + support completely non-traditional code generation targets. For example, the + C backend does not require register allocation, instruction selection, or any + of the other standard components provided by the system. As such, it only + implements these two interfaces, and does its own thing. Another example of + a code generator like this is a (purely hypothetical) backend that converts + LLVM to the GCC RTL form and uses GCC to emit machine code for a target.

+ +

This design also implies that it is possible to design and implement + radically different code generators in the LLVM system that do not make use + of any of the built-in components. Doing so is not recommended at all, but + could be required for radically different targets that do not fit into the + LLVM machine description model: FPGAs for example.

+ +
+ + + + +
+ +

The LLVM target-independent code generator is designed to support efficient + and quality code generation for standard register-based microprocessors. + Code generation in this model is divided into the following stages:

+ +
    +
  1. Instruction Selection — This phase + determines an efficient way to express the input LLVM code in the target + instruction set. This stage produces the initial code for the program in + the target instruction set, then makes use of virtual registers in SSA + form and physical registers that represent any required register + assignments due to target constraints or calling conventions. This step + turns the LLVM code into a DAG of target instructions.
  2. + +
  3. Scheduling and Formation — + This phase takes the DAG of target instructions produced by the + instruction selection phase, determines an ordering of the instructions, + then emits the instructions + as MachineInstrs with that ordering. + Note that we describe this in the instruction + selection section because it operates on + a SelectionDAG.
  4. + +
  5. SSA-based Machine Code Optimizations — + This optional stage consists of a series of machine-code optimizations + that operate on the SSA-form produced by the instruction selector. + Optimizations like modulo-scheduling or peephole optimization work + here.
  6. + +
  7. Register Allocation — The target code + is transformed from an infinite virtual register file in SSA form to the + concrete register file used by the target. This phase introduces spill + code and eliminates all virtual register references from the program.
  8. + +
  9. Prolog/Epilog Code Insertion — Once + the machine code has been generated for the function and the amount of + stack space required is known (used for LLVM alloca's and spill slots), + the prolog and epilog code for the function can be inserted and "abstract + stack location references" can be eliminated. This stage is responsible + for implementing optimizations like frame-pointer elimination and stack + packing.
  10. + +
  11. Late Machine Code Optimizations — + Optimizations that operate on "final" machine code can go here, such as + spill code scheduling and peephole optimizations.
  12. + +
  13. Code Emission — The final stage + actually puts out the code for the current function, either in the target + assembler format or in machine code.
  14. +
+ +

The code generator is based on the assumption that the instruction selector + will use an optimal pattern matching selector to create high-quality + sequences of native instructions. Alternative code generator designs based + on pattern expansion and aggressive iterative peephole optimization are much + slower. This design permits efficient compilation (important for JIT + environments) and aggressive optimization (used when generating code offline) + by allowing components of varying levels of sophistication to be used for any + step of compilation.

+ +

In addition to these stages, target implementations can insert arbitrary + target-specific passes into the flow. For example, the X86 target uses a + special pass to handle the 80x87 floating point stack architecture. Other + targets with unusual requirements can be supported with custom passes as + needed.

+ +
+ + + + +
+ +

The target description classes require a detailed description of the target + architecture. These target descriptions often have a large amount of common + information (e.g., an add instruction is almost identical to a + sub instruction). In order to allow the maximum amount of + commonality to be factored out, the LLVM code generator uses + the TableGen tool to describe big + chunks of the target machine, which allows the use of domain-specific and + target-specific abstractions to reduce the amount of repetition.

+ +

As LLVM continues to be developed and refined, we plan to move more and more + of the target description to the .td form. Doing so gives us a + number of advantages. The most important is that it makes it easier to port + LLVM because it reduces the amount of C++ code that has to be written, and + the surface area of the code generator that needs to be understood before + someone can get something working. Second, it makes it easier to change + things. In particular, if tables and other things are all emitted + by tblgen, we only need a change in one place (tblgen) to + update all of the targets to a new interface.

+ +
+ + + + + +
+ +

The LLVM target description classes (located in the + include/llvm/Target directory) provide an abstract description of + the target machine independent of any particular client. These classes are + designed to capture the abstract properties of the target (such as the + instructions and registers it has), and do not incorporate any particular + pieces of code generation algorithms.

+ +

All of the target description classes (except the + TargetData class) are designed to be + subclassed by the concrete target implementation, and have virtual methods + implemented. To get to these implementations, the + TargetMachine class provides accessors + that should be implemented by the target.

+ +
+ + + + +
+ +

The TargetMachine class provides virtual methods that are used to + access the target-specific implementations of the various target description + classes via the get*Info methods (getInstrInfo, + getRegisterInfo, getFrameInfo, etc.). This class is + designed to be specialized by a concrete target implementation + (e.g., X86TargetMachine) which implements the various virtual + methods. The only required target description class is + the TargetData class, but if the code + generator components are to be used, the other interfaces should be + implemented as well.

+ +
+ + + + +
+ +

The TargetData class is the only required target description class, + and it is the only class that is not extensible (you cannot derived a new + class from it). TargetData specifies information about how the + target lays out memory for structures, the alignment requirements for various + data types, the size of pointers in the target, and whether the target is + little-endian or big-endian.

+ +
+ + + + +
+ +

The TargetLowering class is used by SelectionDAG based instruction + selectors primarily to describe how LLVM code should be lowered to + SelectionDAG operations. Among other things, this class indicates:

+ +
    +
  • an initial register class to use for various ValueTypes,
  • + +
  • which operations are natively supported by the target machine,
  • + +
  • the return type of setcc operations,
  • + +
  • the type to use for shift amounts, and
  • + +
  • various high-level characteristics, like whether it is profitable to turn + division by a constant into a multiplication sequence
  • +
+ +
+ + + + +
+ +

The TargetRegisterInfo class is used to describe the register file + of the target and any interactions between the registers.

+ +

Registers in the code generator are represented in the code generator by + unsigned integers. Physical registers (those that actually exist in the + target description) are unique small numbers, and virtual registers are + generally large. Note that register #0 is reserved as a flag value.

+ +

Each register in the processor description has an associated + TargetRegisterDesc entry, which provides a textual name for the + register (used for assembly output and debugging dumps) and a set of aliases + (used to indicate whether one register overlaps with another).

+ +

In addition to the per-register description, the TargetRegisterInfo + class exposes a set of processor specific register classes (instances of the + TargetRegisterClass class). Each register class contains sets of + registers that have the same properties (for example, they are all 32-bit + integer registers). Each SSA virtual register created by the instruction + selector has an associated register class. When the register allocator runs, + it replaces virtual registers with a physical register in the set.

+ +

The target-specific implementations of these classes is auto-generated from + a TableGen description of the + register file.

+ +
+ + + + +
+ +

The TargetInstrInfo class is used to describe the machine + instructions supported by the target. It is essentially an array of + TargetInstrDescriptor objects, each of which describes one + instruction the target supports. Descriptors define things like the mnemonic + for the opcode, the number of operands, the list of implicit register uses + and defs, whether the instruction has certain target-independent properties + (accesses memory, is commutable, etc), and holds any target-specific + flags.

+ +
+ + + + +
+ +

The TargetFrameInfo class is used to provide information about the + stack frame layout of the target. It holds the direction of stack growth, the + known stack alignment on entry to each function, and the offset to the local + area. The offset to the local area is the offset from the stack pointer on + function entry to the first location where function data (local variables, + spill locations) can be stored.

+ +
+ + + + +
+ +

The TargetSubtarget class is used to provide information about the + specific chip set being targeted. A sub-target informs code generation of + which instructions are supported, instruction latencies and instruction + execution itinerary; i.e., which processing units are used, in what order, + and for how long.

+ +
+ + + + + +
+ +

The TargetJITInfo class exposes an abstract interface used by the + Just-In-Time code generator to perform target-specific activities, such as + emitting stubs. If a TargetMachine supports JIT code generation, it + should provide one of these objects through the getJITInfo + method.

+ +
+ + + + + +
+ +

At the high-level, LLVM code is translated to a machine specific + representation formed out of + MachineFunction, + MachineBasicBlock, + and MachineInstr instances (defined + in include/llvm/CodeGen). This representation is completely target + agnostic, representing instructions in their most abstract form: an opcode + and a series of operands. This representation is designed to support both an + SSA representation for machine code, as well as a register allocated, non-SSA + form.

+ +
+ + + + +
+ +

Target machine instructions are represented as instances of the + MachineInstr class. This class is an extremely abstract way of + representing machine instructions. In particular, it only keeps track of an + opcode number and a set of operands.

+ +

The opcode number is a simple unsigned integer that only has meaning to a + specific backend. All of the instructions for a target should be defined in + the *InstrInfo.td file for the target. The opcode enum values are + auto-generated from this description. The MachineInstr class does + not have any information about how to interpret the instruction (i.e., what + the semantics of the instruction are); for that you must refer to the + TargetInstrInfo class.

+ +

The operands of a machine instruction can be of several different types: a + register reference, a constant integer, a basic block reference, etc. In + addition, a machine operand should be marked as a def or a use of the value + (though only registers are allowed to be defs).

+ +

By convention, the LLVM code generator orders instruction operands so that + all register definitions come before the register uses, even on architectures + that are normally printed in other orders. For example, the SPARC add + instruction: "add %i1, %i2, %i3" adds the "%i1", and "%i2" registers + and stores the result into the "%i3" register. In the LLVM code generator, + the operands should be stored as "%i3, %i1, %i2": with the + destination first.

+ +

Keeping destination (definition) operands at the beginning of the operand + list has several advantages. In particular, the debugging printer will print + the instruction like this:

+ +
+
+%r3 = add %i1, %i2
+
+
+ +

Also if the first operand is a def, it is easier to create + instructions whose only def is the first operand.

+ +
+ + + + +
+ +

Machine instructions are created by using the BuildMI functions, + located in the include/llvm/CodeGen/MachineInstrBuilder.h file. The + BuildMI functions make it easy to build arbitrary machine + instructions. Usage of the BuildMI functions look like this:

+ +
+
+// Create a 'DestReg = mov 42' (rendered in X86 assembly as 'mov DestReg, 42')
+// instruction.  The '1' specifies how many operands will be added.
+MachineInstr *MI = BuildMI(X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create the same instr, but insert it at the end of a basic block.
+MachineBasicBlock &MBB = ...
+BuildMI(MBB, X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create the same instr, but insert it before a specified iterator point.
+MachineBasicBlock::iterator MBBI = ...
+BuildMI(MBB, MBBI, X86::MOV32ri, 1, DestReg).addImm(42);
+
+// Create a 'cmp Reg, 0' instruction, no destination reg.
+MI = BuildMI(X86::CMP32ri, 2).addReg(Reg).addImm(0);
+// Create an 'sahf' instruction which takes no operands and stores nothing.
+MI = BuildMI(X86::SAHF, 0);
+
+// Create a self looping branch instruction.
+BuildMI(MBB, X86::JNE, 1).addMBB(&MBB);
+
+
+ +

The key thing to remember with the BuildMI functions is that you + have to specify the number of operands that the machine instruction will + take. This allows for efficient memory allocation. You also need to specify + if operands default to be uses of values, not definitions. If you need to + add a definition operand (other than the optional destination register), you + must explicitly mark it as such:

+ +
+
+MI.addReg(Reg, RegState::Define);
+
+
+ +
+ + + + +
+ +

One important issue that the code generator needs to be aware of is the + presence of fixed registers. In particular, there are often places in the + instruction stream where the register allocator must arrange for a + particular value to be in a particular register. This can occur due to + limitations of the instruction set (e.g., the X86 can only do a 32-bit divide + with the EAX/EDX registers), or external factors like + calling conventions. In any case, the instruction selector should emit code + that copies a virtual register into or out of a physical register when + needed.

+ +

For example, consider this simple LLVM example:

+ +
+
+define i32 @test(i32 %X, i32 %Y) {
+  %Z = udiv i32 %X, %Y
+  ret i32 %Z
+}
+
+
+ +

The X86 instruction selector produces this machine code for the div + and ret (use "llc X.bc -march=x86 -print-machineinstrs" to + get this):

+ +
+
+;; Start of div
+%EAX = mov %reg1024           ;; Copy X (in reg1024) into EAX
+%reg1027 = sar %reg1024, 31
+%EDX = mov %reg1027           ;; Sign extend X into EDX
+idiv %reg1025                 ;; Divide by Y (in reg1025)
+%reg1026 = mov %EAX           ;; Read the result (Z) out of EAX
+
+;; Start of ret
+%EAX = mov %reg1026           ;; 32-bit return value goes in EAX
+ret
+
+
+ +

By the end of code generation, the register allocator has coalesced the + registers and deleted the resultant identity moves producing the following + code:

+ +
+
+;; X is in EAX, Y is in ECX
+mov %EAX, %EDX
+sar %EDX, 31
+idiv %ECX
+ret 
+
+
+ +

This approach is extremely general (if it can handle the X86 architecture, it + can handle anything!) and allows all of the target specific knowledge about + the instruction stream to be isolated in the instruction selector. Note that + physical registers should have a short lifetime for good code generation, and + all physical registers are assumed dead on entry to and exit from basic + blocks (before register allocation). Thus, if you need a value to be live + across basic block boundaries, it must live in a virtual + register.

+ +
+ + + + +
+ +

MachineInstr's are initially selected in SSA-form, and are + maintained in SSA-form until register allocation happens. For the most part, + this is trivially simple since LLVM is already in SSA form; LLVM PHI nodes + become machine code PHI nodes, and virtual registers are only allowed to have + a single definition.

+ +

After register allocation, machine code is no longer in SSA-form because + there are no virtual registers left in the code.

+ +
+ + + + +
+ +

The MachineBasicBlock class contains a list of machine instructions + (MachineInstr instances). It roughly + corresponds to the LLVM code input to the instruction selector, but there can + be a one-to-many mapping (i.e. one LLVM basic block can map to multiple + machine basic blocks). The MachineBasicBlock class has a + "getBasicBlock" method, which returns the LLVM basic block that it + comes from.

+ +
+ + + + +
+ +

The MachineFunction class contains a list of machine basic blocks + (MachineBasicBlock instances). It + corresponds one-to-one with the LLVM function input to the instruction + selector. In addition to a list of basic blocks, + the MachineFunction contains a a MachineConstantPool, + a MachineFrameInfo, a MachineFunctionInfo, and a + MachineRegisterInfo. See + include/llvm/CodeGen/MachineFunction.h for more information.

+ +
+ + + + + + +
+ +

+The MC Layer is used to represent and process code at the raw machine code +level, devoid of "high level" information like "constant pools", "jump tables", +"global variables" or anything like that. At this level, LLVM handles things +like label names, machine instructions, and sections in the object file. The +code in this layer is used for a number of important purposes: the tail end of +the code generator uses it to write a .s or .o file, and it is also used by the +llvm-mc tool to implement standalone machine codeassemblers and disassemblers. +

+ +

+This section describes some of the important classes. There are also a number +of important subsystems that interact at this layer, they are described later +in this manual. +

+ +
+ + + + + +
+ +

+MCStreamer is best thought of as an assembler API. It is an abstract API which +is implemented in different ways (e.g. to output a .s file, output an +ELF .o file, etc) but whose API correspond directly to what you see in a .s +file. MCStreamer has one method per directive, such as EmitLabel, +EmitSymbolAttribute, SwitchSection, EmitValue (for .byte, .word), etc, which +directly correspond to assembly level directives. It also has an +EmitInstruction method, which is used to output an MCInst to the streamer. +

+ +

+This API is most important for two clients: the llvm-mc stand-alone assembler is +effectively a parser that parses a line, then invokes a method on MCStreamer. In +the code generator, the Code Emission phase of the code +generator lowers higher level LLVM IR and Machine* constructs down to the MC +layer, emitting directives through MCStreamer.

+ +

+On the implementation side of MCStreamer, there are two major implementations: +one for writing out a .s file (MCAsmStreamer), and one for writing out a .o +file (MCObjectStreamer). MCAsmStreamer is a straight-forward implementation +that prints out a directive for each method (e.g. EmitValue -> .byte), but +MCObjectStreamer implements a full assembler. +

+ +
+ + + + +
+ +

+The MCContext class is the owner of a variety of uniqued data structures at the +MC layer, including symbols, sections, etc. As such, this is the class that you +interact with to create symbols and sections. This class can not be subclassed. +

+ +
+ + + + +
+ +

+The MCSymbol class represents a symbol (aka label) in the assembly file. There +are two interesting kinds of symbols: assembler temporary symbols, and normal +symbols. Assembler temporary symbols are used and processed by the assembler +but are discarded when the object file is produced. The distinction is usually +represented by adding a prefix to the label, for example "L" labels are +assembler temporary labels in MachO. +

+ +

MCSymbols are created by MCContext and uniqued there. This means that +MCSymbols can be compared for pointer equivalence to find out if they are the +same symbol. Note that pointer inequality does not guarantee the labels will +end up at different addresses though. It's perfectly legal to output something +like this to the .s file:

+ +

+  foo:
+  bar:
+    .byte 4
+
+ +

In this case, both the foo and bar symbols will have the same address.

+ +
+ + + + +
+ +

+The MCSection class represents an object-file specific section. It is subclassed +by object file specific implementations (e.g. MCSectionMachO, +MCSectionCOFF, MCSectionELF) and these are created and uniqued +by MCContext. The MCStreamer has a notion of the current section, which can be +changed with the SwitchToSection method (which corresponds to a ".section" +directive in a .s file). +

+ +
+ + + + +
+ +

+The MCInst class is a target-independent representation of an instruction. It +is a simple class (much more so than MachineInstr) +that holds a target-specific opcode and a vector of MCOperands. MCOperand, in +turn, is a simple discriminated union of three cases: 1) a simple immediate, +2) a target register ID, 3) a symbolic expression (e.g. "Lfoo-Lbar+42") as an +MCExpr. +

+ +

MCInst is the common currency used to represent machine instructions at the +MC layer. It is the type used by the instruction encoder, the instruction +printer, and the type generated by the assembly parser and disassembler. +

+ +
+ + + + + + +
+ +

This section documents the phases described in the + high-level design of the code generator. + It explains how they work and some of the rationale behind their design.

+ +
+ + + + +
+ +

Instruction Selection is the process of translating LLVM code presented to + the code generator into target-specific machine instructions. There are + several well-known ways to do this in the literature. LLVM uses a + SelectionDAG based instruction selector.

+ +

Portions of the DAG instruction selector are generated from the target + description (*.td) files. Our goal is for the entire instruction + selector to be generated from these .td files, though currently + there are still things that require custom C++ code.

+ +
+ + + + +
+ +

The SelectionDAG provides an abstraction for code representation in a way + that is amenable to instruction selection using automatic techniques + (e.g. dynamic-programming based optimal pattern matching selectors). It is + also well-suited to other phases of code generation; in particular, + instruction scheduling (SelectionDAG's are very close to scheduling DAGs + post-selection). Additionally, the SelectionDAG provides a host + representation where a large variety of very-low-level (but + target-independent) optimizations may be + performed; ones which require extensive information about the instructions + efficiently supported by the target.

+ +

The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the + SDNode class. The primary payload of the SDNode is its + operation code (Opcode) that indicates what operation the node performs and + the operands to the operation. The various operation node types are + described at the top of the include/llvm/CodeGen/SelectionDAGNodes.h + file.

+ +

Although most operations define a single value, each node in the graph may + define multiple values. For example, a combined div/rem operation will + define both the dividend and the remainder. Many other situations require + multiple values as well. Each node also has some number of operands, which + are edges to the node defining the used value. Because nodes may define + multiple values, edges are represented by instances of the SDValue + class, which is a <SDNode, unsigned> pair, indicating the node + and result value being used, respectively. Each value produced by + an SDNode has an associated MVT (Machine Value Type) + indicating what the type of the value is.

+ +

SelectionDAGs contain two different kinds of values: those that represent + data flow and those that represent control flow dependencies. Data values + are simple edges with an integer or floating point value type. Control edges + are represented as "chain" edges which are of type MVT::Other. + These edges provide an ordering between nodes that have side effects (such as + loads, stores, calls, returns, etc). All nodes that have side effects should + take a token chain as input and produce a new one as output. By convention, + token chain inputs are always operand #0, and chain results are always the + last value produced by an operation.

+ +

A SelectionDAG has designated "Entry" and "Root" nodes. The Entry node is + always a marker node with an Opcode of ISD::EntryToken. The Root + node is the final side-effecting node in the token chain. For example, in a + single basic block function it would be the return node.

+ +

One important concept for SelectionDAGs is the notion of a "legal" vs. + "illegal" DAG. A legal DAG for a target is one that only uses supported + operations and supported types. On a 32-bit PowerPC, for example, a DAG with + a value of type i1, i8, i16, or i64 would be illegal, as would a DAG that + uses a SREM or UREM operation. The + legalize types and + legalize operations phases are + responsible for turning an illegal DAG into a legal DAG.

+ +
+ + + + +
+ +

SelectionDAG-based instruction selection consists of the following steps:

+ +
    +
  1. Build initial DAG — This stage + performs a simple translation from the input LLVM code to an illegal + SelectionDAG.
  2. + +
  3. Optimize SelectionDAG — This + stage performs simple optimizations on the SelectionDAG to simplify it, + and recognize meta instructions (like rotates + and div/rem pairs) for targets that support these meta + operations. This makes the resultant code more efficient and + the select instructions from DAG phase + (below) simpler.
  4. + +
  5. Legalize SelectionDAG Types + — This stage transforms SelectionDAG nodes to eliminate any types + that are unsupported on the target.
  6. + +
  7. Optimize SelectionDAG — The + SelectionDAG optimizer is run to clean up redundancies exposed by type + legalization.
  8. + +
  9. Legalize SelectionDAG Ops — + This stage transforms SelectionDAG nodes to eliminate any operations + that are unsupported on the target.
  10. + +
  11. Optimize SelectionDAG — The + SelectionDAG optimizer is run to eliminate inefficiencies introduced by + operation legalization.
  12. + +
  13. Select instructions from DAG — + Finally, the target instruction selector matches the DAG operations to + target instructions. This process translates the target-independent input + DAG into another DAG of target instructions.
  14. + +
  15. SelectionDAG Scheduling and Formation + — The last phase assigns a linear order to the instructions in the + target-instruction DAG and emits them into the MachineFunction being + compiled. This step uses traditional prepass scheduling techniques.
  16. +
+ +

After all of these steps are complete, the SelectionDAG is destroyed and the + rest of the code generation passes are run.

+ +

One great way to visualize what is going on here is to take advantage of a + few LLC command line options. The following options pop up a window + displaying the SelectionDAG at specific times (if you only get errors printed + to the console while using this, you probably + need to configure your system + to add support for it).

+ +
    +
  • -view-dag-combine1-dags displays the DAG after being built, + before the first optimization pass.
  • + +
  • -view-legalize-dags displays the DAG before Legalization.
  • + +
  • -view-dag-combine2-dags displays the DAG before the second + optimization pass.
  • + +
  • -view-isel-dags displays the DAG before the Select phase.
  • + +
  • -view-sched-dags displays the DAG before Scheduling.
  • +
+ +

The -view-sunit-dags displays the Scheduler's dependency graph. + This graph is based on the final SelectionDAG, with nodes that must be + scheduled together bundled into a single scheduling-unit node, and with + immediate operands and other nodes that aren't relevant for scheduling + omitted.

+ +
+ + + + +
+ +

The initial SelectionDAG is naïvely peephole expanded from the LLVM + input by the SelectionDAGLowering class in the + lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp file. The intent of + this pass is to expose as much low-level, target-specific details to the + SelectionDAG as possible. This pass is mostly hard-coded (e.g. an + LLVM add turns into an SDNode add while a + getelementptr is expanded into the obvious arithmetic). This pass + requires target-specific hooks to lower calls, returns, varargs, etc. For + these features, the TargetLowering + interface is used.

+ +
+ + + + +
+ +

The Legalize phase is in charge of converting a DAG to only use the types + that are natively supported by the target.

+ +

There are two main ways of converting values of unsupported scalar types to + values of supported types: converting small types to larger types + ("promoting"), and breaking up large integer types into smaller ones + ("expanding"). For example, a target might require that all f32 values are + promoted to f64 and that all i1/i8/i16 values are promoted to i32. The same + target might require that all i64 values be expanded into pairs of i32 + values. These changes can insert sign and zero extensions as needed to make + sure that the final code has the same behavior as the input.

+ +

There are two main ways of converting values of unsupported vector types to + value of supported types: splitting vector types, multiple times if + necessary, until a legal type is found, and extending vector types by adding + elements to the end to round them out to legal types ("widening"). If a + vector gets split all the way down to single-element parts with no supported + vector type being found, the elements are converted to scalars + ("scalarizing").

+ +

A target implementation tells the legalizer which types are supported (and + which register class to use for them) by calling the + addRegisterClass method in its TargetLowering constructor.

+ +
+ + + + +
+ +

The Legalize phase is in charge of converting a DAG to only use the + operations that are natively supported by the target.

+ +

Targets often have weird constraints, such as not supporting every operation + on every supported datatype (e.g. X86 does not support byte conditional moves + and PowerPC does not support sign-extending loads from a 16-bit memory + location). Legalize takes care of this by open-coding another sequence of + operations to emulate the operation ("expansion"), by promoting one type to a + larger type that supports the operation ("promotion"), or by using a + target-specific hook to implement the legalization ("custom").

+ +

A target implementation tells the legalizer which operations are not + supported (and which of the above three actions to take) by calling the + setOperationAction method in its TargetLowering + constructor.

+ +

Prior to the existence of the Legalize passes, we required that every target + selector supported and handled every + operator and type even if they are not natively supported. The introduction + of the Legalize phases allows all of the canonicalization patterns to be + shared across targets, and makes it very easy to optimize the canonicalized + code because it is still in the form of a DAG.

+ +
+ + + + +
+ +

The SelectionDAG optimization phase is run multiple times for code + generation, immediately after the DAG is built and once after each + legalization. The first run of the pass allows the initial code to be + cleaned up (e.g. performing optimizations that depend on knowing that the + operators have restricted type inputs). Subsequent runs of the pass clean up + the messy code generated by the Legalize passes, which allows Legalize to be + very simple (it can focus on making code legal instead of focusing on + generating good and legal code).

+ +

One important class of optimizations performed is optimizing inserted sign + and zero extension instructions. We currently use ad-hoc techniques, but + could move to more rigorous techniques in the future. Here are some good + papers on the subject:

+ +

"Widening + integer arithmetic"
+ Kevin Redwine and Norman Ramsey
+ International Conference on Compiler Construction (CC) 2004

+ +

"Effective + sign extension elimination"
+ Motohiro Kawahito, Hideaki Komatsu, and Toshio Nakatani
+ Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language Design + and Implementation.

+ +
+ + + + +
+ +

The Select phase is the bulk of the target-specific code for instruction + selection. This phase takes a legal SelectionDAG as input, pattern matches + the instructions supported by the target to this DAG, and produces a new DAG + of target code. For example, consider the following LLVM fragment:

+ +
+
+%t1 = fadd float %W, %X
+%t2 = fmul float %t1, %Y
+%t3 = fadd float %t2, %Z
+
+
+ +

This LLVM code corresponds to a SelectionDAG that looks basically like + this:

+ +
+
+(fadd:f32 (fmul:f32 (fadd:f32 W, X), Y), Z)
+
+
+ +

If a target supports floating point multiply-and-add (FMA) operations, one of + the adds can be merged with the multiply. On the PowerPC, for example, the + output of the instruction selector might look like this DAG:

+ +
+
+(FMADDS (FADDS W, X), Y, Z)
+
+
+ +

The FMADDS instruction is a ternary instruction that multiplies its +first two operands and adds the third (as single-precision floating-point +numbers). The FADDS instruction is a simple binary single-precision +add instruction. To perform this pattern match, the PowerPC backend includes +the following instruction definitions:

+ +
+
+def FMADDS : AForm_1<59, 29,
+                    (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRC, F4RC:$FRB),
+                    "fmadds $FRT, $FRA, $FRC, $FRB",
+                    [(set F4RC:$FRT, (fadd (fmul F4RC:$FRA, F4RC:$FRC),
+                                           F4RC:$FRB))]>;
+def FADDS : AForm_2<59, 21,
+                    (ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
+                    "fadds $FRT, $FRA, $FRB",
+                    [(set F4RC:$FRT, (fadd F4RC:$FRA, F4RC:$FRB))]>;
+
+
+ +

The portion of the instruction definition in bold indicates the pattern used + to match the instruction. The DAG operators + (like fmul/fadd) are defined in + the include/llvm/Target/TargetSelectionDAG.td file. " + F4RC" is the register class of the input and result values.

+ +

The TableGen DAG instruction selector generator reads the instruction + patterns in the .td file and automatically builds parts of the + pattern matching code for your target. It has the following strengths:

+ +
    +
  • At compiler-compiler time, it analyzes your instruction patterns and tells + you if your patterns make sense or not.
  • + +
  • It can handle arbitrary constraints on operands for the pattern match. In + particular, it is straight-forward to say things like "match any immediate + that is a 13-bit sign-extended value". For examples, see the + immSExt16 and related tblgen classes in the PowerPC + backend.
  • + +
  • It knows several important identities for the patterns defined. For + example, it knows that addition is commutative, so it allows the + FMADDS pattern above to match "(fadd X, (fmul Y, Z))" as + well as "(fadd (fmul X, Y), Z)", without the target author having + to specially handle this case.
  • + +
  • It has a full-featured type-inferencing system. In particular, you should + rarely have to explicitly tell the system what type parts of your patterns + are. In the FMADDS case above, we didn't have to tell + tblgen that all of the nodes in the pattern are of type 'f32'. + It was able to infer and propagate this knowledge from the fact that + F4RC has type 'f32'.
  • + +
  • Targets can define their own (and rely on built-in) "pattern fragments". + Pattern fragments are chunks of reusable patterns that get inlined into + your patterns during compiler-compiler time. For example, the integer + "(not x)" operation is actually defined as a pattern fragment + that expands as "(xor x, -1)", since the SelectionDAG does not + have a native 'not' operation. Targets can define their own + short-hand fragments as they see fit. See the definition of + 'not' and 'ineg' for examples.
  • + +
  • In addition to instructions, targets can specify arbitrary patterns that + map to one or more instructions using the 'Pat' class. For example, the + PowerPC has no way to load an arbitrary integer immediate into a register + in one instruction. To tell tblgen how to do this, it defines: +
    +
    +
    +
    +// Arbitrary immediate support.  Implement in terms of LIS/ORI.
    +def : Pat<(i32 imm:$imm),
    +          (ORI (LIS (HI16 imm:$imm)), (LO16 imm:$imm))>;
    +
    +
    +
    + If none of the single-instruction patterns for loading an immediate into a + register match, this will be used. This rule says "match an arbitrary i32 + immediate, turning it into an ORI ('or a 16-bit immediate') and + an LIS ('load 16-bit immediate, where the immediate is shifted to + the left 16 bits') instruction". To make this work, the + LO16/HI16 node transformations are used to manipulate + the input immediate (in this case, take the high or low 16-bits of the + immediate).
  • + +
  • While the system does automate a lot, it still allows you to write custom + C++ code to match special cases if there is something that is hard to + express.
  • +
+ +

While it has many strengths, the system currently has some limitations, + primarily because it is a work in progress and is not yet finished:

+ +
    +
  • Overall, there is no way to define or match SelectionDAG nodes that define + multiple values (e.g. SMUL_LOHI, LOAD, CALL, + etc). This is the biggest reason that you currently still have + to write custom C++ code for your instruction selector.
  • + +
  • There is no great way to support matching complex addressing modes yet. + In the future, we will extend pattern fragments to allow them to define + multiple values (e.g. the four operands of the X86 + addressing mode, which are currently matched with custom C++ code). + In addition, we'll extend fragments so that a fragment can match multiple + different patterns.
  • + +
  • We don't automatically infer flags like isStore/isLoad yet.
  • + +
  • We don't automatically generate the set of supported registers and + operations for the Legalizer + yet.
  • + +
  • We don't have a way of tying in custom legalized nodes yet.
  • +
+ +

Despite these limitations, the instruction selector generator is still quite + useful for most of the binary and logical operations in typical instruction + sets. If you run into any problems or can't figure out how to do something, + please let Chris know!

+ +
+ + + + +
+ +

The scheduling phase takes the DAG of target instructions from the selection + phase and assigns an order. The scheduler can pick an order depending on + various constraints of the machines (i.e. order for minimal register pressure + or try to cover instruction latencies). Once an order is established, the + DAG is converted to a list + of MachineInstrs and the SelectionDAG is + destroyed.

+ +

Note that this phase is logically separate from the instruction selection + phase, but is tied to it closely in the code because it operates on + SelectionDAGs.

+ +
+ + + + +
+ +
    +
  1. Optional function-at-a-time selection.
  2. + +
  3. Auto-generate entire selector from .td file.
  4. +
+ +
+ + + +

To Be Written

+ + + + +
+ +

Live Intervals are the ranges (intervals) where a variable is live. + They are used by some register allocator passes to + determine if two or more virtual registers which require the same physical + register are live at the same point in the program (i.e., they conflict). + When this situation occurs, one virtual register must be spilled.

+ +
+ + + + +
+ +

The first step in determining the live intervals of variables is to calculate + the set of registers that are immediately dead after the instruction (i.e., + the instruction calculates the value, but it is never used) and the set of + registers that are used by the instruction, but are never used after the + instruction (i.e., they are killed). Live variable information is computed + for each virtual register and register allocatable physical + register in the function. This is done in a very efficient manner because it + uses SSA to sparsely compute lifetime information for virtual registers + (which are in SSA form) and only has to track physical registers within a + block. Before register allocation, LLVM can assume that physical registers + are only live within a single basic block. This allows it to do a single, + local analysis to resolve physical register lifetimes within each basic + block. If a physical register is not register allocatable (e.g., a stack + pointer or condition codes), it is not tracked.

+ +

Physical registers may be live in to or out of a function. Live in values are + typically arguments in registers. Live out values are typically return values + in registers. Live in values are marked as such, and are given a dummy + "defining" instruction during live intervals analysis. If the last basic + block of a function is a return, then it's marked as using all live + out values in the function.

+ +

PHI nodes need to be handled specially, because the calculation of + the live variable information from a depth first traversal of the CFG of the + function won't guarantee that a virtual register used by the PHI + node is defined before it's used. When a PHI node is encountered, + only the definition is handled, because the uses will be handled in other + basic blocks.

+ +

For each PHI node of the current basic block, we simulate an + assignment at the end of the current basic block and traverse the successor + basic blocks. If a successor basic block has a PHI node and one of + the PHI node's operands is coming from the current basic block, then + the variable is marked as alive within the current basic block and all + of its predecessor basic blocks, until the basic block with the defining + instruction is encountered.

+ +
+ + + + +
+ +

We now have the information available to perform the live intervals analysis + and build the live intervals themselves. We start off by numbering the basic + blocks and machine instructions. We then handle the "live-in" values. These + are in physical registers, so the physical register is assumed to be killed + by the end of the basic block. Live intervals for virtual registers are + computed for some ordering of the machine instructions [1, N]. A + live interval is an interval [i, j), where 1 <= i <= j + < N, for which a variable is live.

+ +

More to come...

+ +
+ + + + +
+ +

The Register Allocation problem consists in mapping a program + Pv, that can use an unbounded number of virtual registers, + to a program Pp that contains a finite (possibly small) + number of physical registers. Each target architecture has a different number + of physical registers. If the number of physical registers is not enough to + accommodate all the virtual registers, some of them will have to be mapped + into memory. These virtuals are called spilled virtuals.

+ +
+ + + + + +
+ +

In LLVM, physical registers are denoted by integer numbers that normally + range from 1 to 1023. To see how this numbering is defined for a particular + architecture, you can read the GenRegisterNames.inc file for that + architecture. For instance, by + inspecting lib/Target/X86/X86GenRegisterNames.inc we see that the + 32-bit register EAX is denoted by 15, and the MMX register + MM0 is mapped to 48.

+ +

Some architectures contain registers that share the same physical location. A + notable example is the X86 platform. For instance, in the X86 architecture, + the registers EAX, AX and AL share the first eight + bits. These physical registers are marked as aliased in LLVM. Given a + particular architecture, you can check which registers are aliased by + inspecting its RegisterInfo.td file. Moreover, the method + TargetRegisterInfo::getAliasSet(p_reg) returns an array containing + all the physical registers aliased to the register p_reg.

+ +

Physical registers, in LLVM, are grouped in Register Classes. + Elements in the same register class are functionally equivalent, and can be + interchangeably used. Each virtual register can only be mapped to physical + registers of a particular class. For instance, in the X86 architecture, some + virtuals can only be allocated to 8 bit registers. A register class is + described by TargetRegisterClass objects. To discover if a virtual + register is compatible with a given physical, this code can be used:

+ +
+
+bool RegMapping_Fer::compatible_class(MachineFunction &mf,
+                                      unsigned v_reg,
+                                      unsigned p_reg) {
+  assert(TargetRegisterInfo::isPhysicalRegister(p_reg) &&
+         "Target register must be physical");
+  const TargetRegisterClass *trc = mf.getRegInfo().getRegClass(v_reg);
+  return trc->contains(p_reg);
+}
+
+
+ +

Sometimes, mostly for debugging purposes, it is useful to change the number + of physical registers available in the target architecture. This must be done + statically, inside the TargetRegsterInfo.td file. Just grep + for RegisterClass, the last parameter of which is a list of + registers. Just commenting some out is one simple way to avoid them being + used. A more polite way is to explicitly exclude some registers from + the allocation order. See the definition of the GR8 register + class in lib/Target/X86/X86RegisterInfo.td for an example of this. +

+ +

Virtual registers are also denoted by integer numbers. Contrary to physical + registers, different virtual registers never share the same number. Whereas + physical registers are statically defined in a TargetRegisterInfo.td + file and cannot be created by the application developer, that is not the case + with virtual registers. In order to create new virtual registers, use the + method MachineRegisterInfo::createVirtualRegister(). This method + will return a new virtual register. Use an IndexedMap<Foo, + VirtReg2IndexFunctor> to hold information per virtual register. If you + need to enumerate all virtual registers, use the function + TargetRegisterInfo::index2VirtReg() to find the virtual register + numbers:

+ +
+
+  for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
+    unsigned VirtReg = TargetRegisterInfo::index2VirtReg(i);
+    stuff(VirtReg);
+  }
+
+
+ +

Before register allocation, the operands of an instruction are mostly virtual + registers, although physical registers may also be used. In order to check if + a given machine operand is a register, use the boolean + function MachineOperand::isRegister(). To obtain the integer code of + a register, use MachineOperand::getReg(). An instruction may define + or use a register. For instance, ADD reg:1026 := reg:1025 reg:1024 + defines the registers 1024, and uses registers 1025 and 1026. Given a + register operand, the method MachineOperand::isUse() informs if that + register is being used by the instruction. The + method MachineOperand::isDef() informs if that registers is being + defined.

+ +

We will call physical registers present in the LLVM bitcode before register + allocation pre-colored registers. Pre-colored registers are used in + many different situations, for instance, to pass parameters of functions + calls, and to store results of particular instructions. There are two types + of pre-colored registers: the ones implicitly defined, and + those explicitly defined. Explicitly defined registers are normal + operands, and can be accessed + with MachineInstr::getOperand(int)::getReg(). In order to check + which registers are implicitly defined by an instruction, use + the TargetInstrInfo::get(opcode)::ImplicitDefs, + where opcode is the opcode of the target instruction. One important + difference between explicit and implicit physical registers is that the + latter are defined statically for each instruction, whereas the former may + vary depending on the program being compiled. For example, an instruction + that represents a function call will always implicitly define or use the same + set of physical registers. To read the registers implicitly used by an + instruction, + use TargetInstrInfo::get(opcode)::ImplicitUses. Pre-colored + registers impose constraints on any register allocation algorithm. The + register allocator must make sure that none of them are overwritten by + the values of virtual registers while still alive.

+ +
+ + + + + +
+ +

There are two ways to map virtual registers to physical registers (or to + memory slots). The first way, that we will call direct mapping, is + based on the use of methods of the classes TargetRegisterInfo, + and MachineOperand. The second way, that we will call indirect + mapping, relies on the VirtRegMap class in order to insert loads + and stores sending and getting values to and from memory.

+ +

The direct mapping provides more flexibility to the developer of the register + allocator; however, it is more error prone, and demands more implementation + work. Basically, the programmer will have to specify where load and store + instructions should be inserted in the target function being compiled in + order to get and store values in memory. To assign a physical register to a + virtual register present in a given operand, + use MachineOperand::setReg(p_reg). To insert a store instruction, + use TargetInstrInfo::storeRegToStackSlot(...), and to insert a + load instruction, use TargetInstrInfo::loadRegFromStackSlot.

+ +

The indirect mapping shields the application developer from the complexities + of inserting load and store instructions. In order to map a virtual register + to a physical one, use VirtRegMap::assignVirt2Phys(vreg, preg). In + order to map a certain virtual register to memory, + use VirtRegMap::assignVirt2StackSlot(vreg). This method will return + the stack slot where vreg's value will be located. If it is + necessary to map another virtual register to the same stack slot, + use VirtRegMap::assignVirt2StackSlot(vreg, stack_location). One + important point to consider when using the indirect mapping, is that even if + a virtual register is mapped to memory, it still needs to be mapped to a + physical register. This physical register is the location where the virtual + register is supposed to be found before being stored or after being + reloaded.

+ +

If the indirect strategy is used, after all the virtual registers have been + mapped to physical registers or stack slots, it is necessary to use a spiller + object to place load and store instructions in the code. Every virtual that + has been mapped to a stack slot will be stored to memory after been defined + and will be loaded before being used. The implementation of the spiller tries + to recycle load/store instructions, avoiding unnecessary instructions. For an + example of how to invoke the spiller, + see RegAllocLinearScan::runOnMachineFunction + in lib/CodeGen/RegAllocLinearScan.cpp.

+ +
+ + + + +
+ +

With very rare exceptions (e.g., function calls), the LLVM machine code + instructions are three address instructions. That is, each instruction is + expected to define at most one register, and to use at most two registers. + However, some architectures use two address instructions. In this case, the + defined register is also one of the used register. For instance, an + instruction such as ADD %EAX, %EBX, in X86 is actually equivalent + to %EAX = %EAX + %EBX.

+ +

In order to produce correct code, LLVM must convert three address + instructions that represent two address instructions into true two address + instructions. LLVM provides the pass TwoAddressInstructionPass for + this specific purpose. It must be run before register allocation takes + place. After its execution, the resulting code may no longer be in SSA + form. This happens, for instance, in situations where an instruction such + as %a = ADD %b %c is converted to two instructions such as:

+ +
+
+%a = MOVE %b
+%a = ADD %a %c
+
+
+ +

Notice that, internally, the second instruction is represented as + ADD %a[def/use] %c. I.e., the register operand %a is both + used and defined by the instruction.

+ +
+ + + + +
+ +

An important transformation that happens during register allocation is called + the SSA Deconstruction Phase. The SSA form simplifies many analyses + that are performed on the control flow graph of programs. However, + traditional instruction sets do not implement PHI instructions. Thus, in + order to generate executable code, compilers must replace PHI instructions + with other instructions that preserve their semantics.

+ +

There are many ways in which PHI instructions can safely be removed from the + target code. The most traditional PHI deconstruction algorithm replaces PHI + instructions with copy instructions. That is the strategy adopted by + LLVM. The SSA deconstruction algorithm is implemented + in lib/CodeGen/PHIElimination.cpp. In order to invoke this pass, the + identifier PHIEliminationID must be marked as required in the code + of the register allocator.

+ +
+ + + + +
+ +

Instruction folding is an optimization performed during register + allocation that removes unnecessary copy instructions. For instance, a + sequence of instructions such as:

+ +
+
+%EBX = LOAD %mem_address
+%EAX = COPY %EBX
+
+
+ +

can be safely substituted by the single instruction:

+ +
+
+%EAX = LOAD %mem_address
+
+
+ +

Instructions can be folded with + the TargetRegisterInfo::foldMemoryOperand(...) method. Care must be + taken when folding instructions; a folded instruction can be quite different + from the original + instruction. See LiveIntervals::addIntervalsForSpills + in lib/CodeGen/LiveIntervalAnalysis.cpp for an example of its + use.

+ +
+ + + + + +
+ +

The LLVM infrastructure provides the application developer with three + different register allocators:

+ +
    +
  • Linear ScanThe default allocator. This is the + well-know linear scan register allocator. Whereas the + Simple and Local algorithms use a direct mapping + implementation technique, the Linear Scan implementation + uses a spiller in order to place load and stores.
  • + +
  • Fast — This register allocator is the default for debug + builds. It allocates registers on a basic block level, attempting to keep + values in registers and reusing registers as appropriate.
  • + +
  • PBQP — A Partitioned Boolean Quadratic Programming (PBQP) + based register allocator. This allocator works by constructing a PBQP + problem representing the register allocation problem under consideration, + solving this using a PBQP solver, and mapping the solution back to a + register assignment.
  • + +
+ +

The type of register allocator used in llc can be chosen with the + command line option -regalloc=...:

+ +
+
+$ llc -regalloc=linearscan file.bc -o ln.s;
+$ llc -regalloc=fast file.bc -o fa.s;
+$ llc -regalloc=pbqp file.bc -o pbqp.s;
+
+
+ +
+ + + +

To Be Written

+ + +

To Be Written

+ + + + +
+ +

The code emission step of code generation is responsible for lowering from +the code generator abstractions (like MachineFunction, MachineInstr, etc) down +to the abstractions used by the MC layer (MCInst, +MCStreamer, etc). This is +done with a combination of several different classes: the (misnamed) +target-independent AsmPrinter class, target-specific subclasses of AsmPrinter +(such as SparcAsmPrinter), and the TargetLoweringObjectFile class.

+ +

Since the MC layer works at the level of abstraction of object files, it +doesn't have a notion of functions, global variables etc. Instead, it thinks +about labels, directives, and instructions. A key class used at this time is +the MCStreamer class. This is an abstract API that is implemented in different +ways (e.g. to output a .s file, output an ELF .o file, etc) that is effectively +an "assembler API". MCStreamer has one method per directive, such as EmitLabel, +EmitSymbolAttribute, SwitchSection, etc, which directly correspond to assembly +level directives. +

+ +

If you are interested in implementing a code generator for a target, there +are three important things that you have to implement for your target:

+ +
    +
  1. First, you need a subclass of AsmPrinter for your target. This class +implements the general lowering process converting MachineFunction's into MC +label constructs. The AsmPrinter base class provides a number of useful methods +and routines, and also allows you to override the lowering process in some +important ways. You should get much of the lowering for free if you are +implementing an ELF, COFF, or MachO target, because the TargetLoweringObjectFile +class implements much of the common logic.
  2. + +
  3. Second, you need to implement an instruction printer for your target. The +instruction printer takes an MCInst and renders it to a +raw_ostream as text. Most of this is automatically generated from the .td file +(when you specify something like "add $dst, $src1, $src2" in the +instructions), but you need to implement routines to print operands.
  4. + +
  5. Third, you need to implement code that lowers a MachineInstr to an MCInst, usually implemented in +"<target>MCInstLower.cpp". This lowering process is often target +specific, and is responsible for turning jump table entries, constant pool +indices, global variable addresses, etc into MCLabels as appropriate. This +translation layer is also responsible for expanding pseudo ops used by the code +generator into the actual machine instructions they correspond to. The MCInsts +that are generated by this are fed into the instruction printer or the encoder. +
  6. + +
+ +

Finally, at your choosing, you can also implement an subclass of +MCCodeEmitter which lowers MCInst's into machine code bytes and relocations. +This is important if you want to support direct .o file emission, or would like +to implement an assembler for your target.

+ +
+ + + + + + +
+ +

Though you're probably reading this because you want to write or maintain a +compiler backend, LLVM also fully supports building a native assemblers too. +We've tried hard to automate the generation of the assembler from the .td files +(in particular the instruction syntax and encodings), which means that a large +part of the manual and repetitive data entry can be factored and shared with the +compiler.

+ +
+ + +
Instruction Parsing
+ +

To Be Written

+ + + +
+ Instruction Alias Processing +
+ +
+

Once the instruction is parsed, it enters the MatchInstructionImpl function. +The MatchInstructionImpl function performs alias processing and then does +actual matching.

+ +

Alias processing is the phase that canonicalizes different lexical forms of +the same instructions down to one representation. There are several different +kinds of alias that are possible to implement and they are listed below in the +order that they are processed (which is in order from simplest/weakest to most +complex/powerful). Generally you want to use the first alias mechanism that +meets the needs of your instruction, because it will allow a more concise +description.

+ +
+ + +
Mnemonic Aliases
+ +
+ +

The first phase of alias processing is simple instruction mnemonic +remapping for classes of instructions which are allowed with two different +mnemonics. This phase is a simple and unconditionally remapping from one input +mnemonic to one output mnemonic. It isn't possible for this form of alias to +look at the operands at all, so the remapping must apply for all forms of a +given mnemonic. Mnemonic aliases are defined simply, for example X86 has: +

+ +
+
+def : MnemonicAlias<"cbw",     "cbtw">;
+def : MnemonicAlias<"smovq",   "movsq">;
+def : MnemonicAlias<"fldcww",  "fldcw">;
+def : MnemonicAlias<"fucompi", "fucomip">;
+def : MnemonicAlias<"ud2a",    "ud2">;
+
+
+ +

... and many others. With a MnemonicAlias definition, the mnemonic is +remapped simply and directly. Though MnemonicAlias's can't look at any aspect +of the instruction (such as the operands) they can depend on global modes (the +same ones supported by the matcher), through a Requires clause:

+ +
+
+def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
+def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
+
+
+ +

In this example, the mnemonic gets mapped into different a new one depending +on the current instruction set.

+ +
+ + +
Instruction Aliases
+ +
+ +

The most general phase of alias processing occurs while matching is +happening: it provides new forms for the matcher to match along with a specific +instruction to generate. An instruction alias has two parts: the string to +match and the instruction to generate. For example: +

+ +
+
+def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8  :$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX32rr8  GR32:$dst, GR8  :$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16 :$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX64rr8  GR64:$dst, GR8  :$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16 :$src)>;
+def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32 :$src)>;
+
+
+ +

This shows a powerful example of the instruction aliases, matching the +same mnemonic in multiple different ways depending on what operands are present +in the assembly. The result of instruction aliases can include operands in a +different order than the destination instruction, and can use an input +multiple times, for example:

+ +
+
+def : InstAlias<"clrb $reg", (XOR8rr  GR8 :$reg, GR8 :$reg)>;
+def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>;
+def : InstAlias<"clrl $reg", (XOR32rr GR32:$reg, GR32:$reg)>;
+def : InstAlias<"clrq $reg", (XOR64rr GR64:$reg, GR64:$reg)>;
+
+
+ +

This example also shows that tied operands are only listed once. In the X86 +backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied +to the output). InstAliases take a flattened operand list without duplicates +for tied operands. The result of an instruction alias can also use immediates +and fixed physical registers which are added as simple immediate operands in the +result, for example:

+ +
+
+// Fixed Immediate operand.
+def : InstAlias<"aad", (AAD8i8 10)>;
+
+// Fixed register operand.
+def : InstAlias<"fcomi", (COM_FIr ST1)>;
+
+// Simple alias.
+def : InstAlias<"fcomi $reg", (COM_FIr RST:$reg)>;
+
+
+ + +

Instruction aliases can also have a Requires clause to make them +subtarget specific.

+ +
+ + + + +
Instruction Matching
+ +

To Be Written

+ + + + + + + + +
+ +

This section of the document explains features or design decisions that are + specific to the code generator for a particular target. First we start + with a table that summarizes what features are supported by each target.

+ +
+ + + + +
+ +

Note that this table does not include the C backend or Cpp backends, since +they do not use the target independent code generator infrastructure. It also +doesn't list features that are not supported fully by any target yet. It +considers a feature to be supported if at least one subtarget supports it. A +feature being supported means that it is useful and works for most cases, it +does not indicate that there are zero known bugs in the implementation. Here +is the key:

+ + + + + + + + + + + + + + + +
UnknownNo supportPartial SupportComplete Support
+ +

Here is the table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Target
FeatureARMAlphaBlackfinCellSPUMBlazeMSP430MipsPTXPowerPCSparcSystemZX86XCore
is generally reliable
assembly parser
disassembler
inline asm *
jit*
.o file writing
tail calls
+ +
+ + +
Is Generally Reliable
+ +
+

This box indicates whether the target is considered to be production quality. +This indicates that the target has been used as a static compiler to +compile large amounts of code by a variety of different people and is in +continuous use.

+
+ + +
Assembly Parser
+ +
+

This box indicates whether the target supports parsing target specific .s +files by implementing the MCAsmParser interface. This is required for llvm-mc +to be able to act as a native assembler and is required for inline assembly +support in the native .o file writer.

+ +
+ + + +
Disassembler
+ +
+

This box indicates whether the target supports the MCDisassembler API for +disassembling machine opcode bytes into MCInst's.

+ +
+ + +
Inline Asm
+ +
+

This box indicates whether the target supports most popular inline assembly +constraints and modifiers.

+ +

X86 lacks reliable support for inline assembly +constraints relating to the X86 floating point stack.

+ +
+ + +
JIT Support
+ +
+

This box indicates whether the target supports the JIT compiler through +the ExecutionEngine interface.

+ +

The ARM backend has basic support for integer code +in ARM codegen mode, but lacks NEON and full Thumb support.

+ +
+ + +
.o File Writing
+ +
+ +

This box indicates whether the target supports writing .o files (e.g. MachO, +ELF, and/or COFF) files directly from the target. Note that the target also +must include an assembly parser and general inline assembly support for full +inline assembly support in the .o writer.

+ +

Targets that don't support this feature can obviously still write out .o +files, they just rely on having an external assembler to translate from a .s +file to a .o file (as is the case for many C compilers).

+ +
+ + +
Tail Calls
+ +
+ +

This box indicates whether the target supports guaranteed tail calls. These +are calls marked "tail" and use the fastcc +calling convention. Please see the tail call section +more more details.

+ +
+ + + + + + + +
+ +

Tail call optimization, callee reusing the stack of the caller, is currently + supported on x86/x86-64 and PowerPC. It is performed if:

+ +
    +
  • Caller and callee have the calling convention fastcc or + cc 10 (GHC call convention).
  • + +
  • The call is a tail call - in tail position (ret immediately follows call + and ret uses value of call or is void).
  • + +
  • Option -tailcallopt is enabled.
  • + +
  • Platform specific constraints are met.
  • +
+ +

x86/x86-64 constraints:

+ +
    +
  • No variable argument lists are used.
  • + +
  • On x86-64 when generating GOT/PIC code only module-local calls (visibility + = hidden or protected) are supported.
  • +
+ +

PowerPC constraints:

+ +
    +
  • No variable argument lists are used.
  • + +
  • No byval parameters are used.
  • + +
  • On ppc32/64 GOT/PIC only module-local calls (visibility = hidden or protected) are supported.
  • +
+ +

Example:

+ +

Call as llc -tailcallopt test.ll.

+ +
+
+declare fastcc i32 @tailcallee(i32 inreg %a1, i32 inreg %a2, i32 %a3, i32 %a4)
+
+define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
+  %l1 = add i32 %in1, %in2
+  %tmp = tail call fastcc i32 @tailcallee(i32 %in1 inreg, i32 %in2 inreg, i32 %in1, i32 %l1)
+  ret i32 %tmp
+}
+
+
+ +

Implications of -tailcallopt:

+ +

To support tail call optimization in situations where the callee has more + arguments than the caller a 'callee pops arguments' convention is used. This + currently causes each fastcc call that is not tail call optimized + (because one or more of above constraints are not met) to be followed by a + readjustment of the stack. So performance might be worse in such cases.

+ +
+ + + +
+ +

Sibling call optimization is a restricted form of tail call optimization. + Unlike tail call optimization described in the previous section, it can be + performed automatically on any tail calls when -tailcallopt option + is not specified.

+ +

Sibling call optimization is currently performed on x86/x86-64 when the + following constraints are met:

+ +
    +
  • Caller and callee have the same calling convention. It can be either + c or fastcc. + +
  • The call is a tail call - in tail position (ret immediately follows call + and ret uses value of call or is void).
  • + +
  • Caller and callee have matching return type or the callee result is not + used. + +
  • If any of the callee arguments are being passed in stack, they must be + available in caller's own incoming argument stack and the frame offsets + must be the same. +
+ +

Example:

+
+
+declare i32 @bar(i32, i32)
+
+define i32 @foo(i32 %a, i32 %b, i32 %c) {
+entry:
+  %0 = tail call i32 @bar(i32 %a, i32 %b)
+  ret i32 %0
+}
+
+
+ +
+ + + +
+ +

The X86 code generator lives in the lib/Target/X86 directory. This + code generator is capable of targeting a variety of x86-32 and x86-64 + processors, and includes support for ISA extensions such as MMX and SSE.

+ +
+ + + + +
+ +

The following are the known target triples that are supported by the X86 + backend. This is not an exhaustive list, and it would be useful to add those + that people test.

+ +
    +
  • i686-pc-linux-gnu — Linux
  • + +
  • i386-unknown-freebsd5.3 — FreeBSD 5.3
  • + +
  • i686-pc-cygwin — Cygwin on Win32
  • + +
  • i686-pc-mingw32 — MingW on Win32
  • + +
  • i386-pc-mingw32msvc — MingW crosscompiler on Linux
  • + +
  • i686-apple-darwin* — Apple Darwin on X86
  • + +
  • x86_64-unknown-linux-gnu — Linux
  • +
+ +
+ + + + + +
+ +

The following target-specific calling conventions are known to backend:

+ +
    +
  • x86_StdCall — stdcall calling convention seen on Microsoft + Windows platform (CC ID = 64).
  • + +
  • x86_FastCall — fastcall calling convention seen on Microsoft + Windows platform (CC ID = 65).
  • +
+ +
+ + + + +
+ +

The x86 has a very flexible way of accessing memory. It is capable of + forming memory addresses of the following expression directly in integer + instructions (which use ModR/M addressing):

+ +
+
+SegmentReg: Base + [1,2,4,8] * IndexReg + Disp32
+
+
+ +

In order to represent this, LLVM tracks no less than 5 operands for each + memory operand of this form. This means that the "load" form of + 'mov' has the following MachineOperands in this order:

+ +
+
+Index:        0     |    1        2       3           4          5
+Meaning:   DestReg, | BaseReg,  Scale, IndexReg, Displacement Segment
+OperandTy: VirtReg, | VirtReg, UnsImm, VirtReg,   SignExtImm  PhysReg
+
+
+ +

Stores, and all other instructions, treat the four memory operands in the + same way and in the same order. If the segment register is unspecified + (regno = 0), then no segment override is generated. "Lea" operations do not + have a segment register specified, so they only have 4 operands for their + memory reference.

+ +
+ + + + +
+ +

x86 has an experimental feature which provides + the ability to perform loads and stores to different address spaces + via the x86 segment registers. A segment override prefix byte on an + instruction causes the instruction's memory access to go to the specified + segment. LLVM address space 0 is the default address space, which includes + the stack, and any unqualified memory accesses in a program. Address spaces + 1-255 are currently reserved for user-defined code. The GS-segment is + represented by address space 256, while the FS-segment is represented by + address space 257. Other x86 segments have yet to be allocated address space + numbers.

+ +

While these address spaces may seem similar to TLS via the + thread_local keyword, and often use the same underlying hardware, + there are some fundamental differences.

+ +

The thread_local keyword applies to global variables and + specifies that they are to be allocated in thread-local memory. There are + no type qualifiers involved, and these variables can be pointed to with + normal pointers and accessed with normal loads and stores. + The thread_local keyword is target-independent at the LLVM IR + level (though LLVM doesn't yet have implementations of it for some + configurations).

+ +

Special address spaces, in contrast, apply to static types. Every + load and store has a particular address space in its address operand type, + and this is what determines which address space is accessed. + LLVM ignores these special address space qualifiers on global variables, + and does not provide a way to directly allocate storage in them. + At the LLVM IR level, the behavior of these special address spaces depends + in part on the underlying OS or runtime environment, and they are specific + to x86 (and LLVM doesn't yet handle them correctly in some cases).

+ +

Some operating systems and runtime environments use (or may in the future + use) the FS/GS-segment registers for various low-level purposes, so care + should be taken when considering them.

+ +
+ + + + +
+ +

An instruction name consists of the base name, a default operand size, and a + a character per operand with an optional special size. For example:

+ +
+
+ADD8rr      -> add, 8-bit register, 8-bit register
+IMUL16rmi   -> imul, 16-bit register, 16-bit memory, 16-bit immediate
+IMUL16rmi8  -> imul, 16-bit register, 16-bit memory, 8-bit immediate
+MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
+
+
+ +
+ + + + +
+ +

The PowerPC code generator lives in the lib/Target/PowerPC directory. The + code generation is retargetable to several variations or subtargets of + the PowerPC ISA; including ppc32, ppc64 and altivec.

+ +
+ + + + +
+ +

LLVM follows the AIX PowerPC ABI, with two deviations. LLVM uses a PC + relative (PIC) or static addressing for accessing global values, so no TOC + (r2) is used. Second, r31 is used as a frame pointer to allow dynamic growth + of a stack frame. LLVM takes advantage of having no TOC to provide space to + save the frame pointer in the PowerPC linkage area of the caller frame. + Other details of PowerPC ABI can be found at PowerPC ABI. Note: This link describes the 32 bit ABI. The 64 bit ABI + is similar except space for GPRs are 8 bytes wide (not 4) and r13 is reserved + for system use.

+ +
+ + + + +
+ +

The size of a PowerPC frame is usually fixed for the duration of a + function's invocation. Since the frame is fixed size, all references + into the frame can be accessed via fixed offsets from the stack pointer. The + exception to this is when dynamic alloca or variable sized arrays are + present, then a base pointer (r31) is used as a proxy for the stack pointer + and stack pointer is free to grow or shrink. A base pointer is also used if + llvm-gcc is not passed the -fomit-frame-pointer flag. The stack pointer is + always aligned to 16 bytes, so that space allocated for altivec vectors will + be properly aligned.

+ +

An invocation frame is laid out as follows (low memory at top);

+ + + + + + + + + + + + + + + + + + + + + + + +
Linkage

Parameter area

Dynamic area

Locals area

Saved registers area


Previous Frame

+ +

The linkage area is used by a callee to save special registers prior + to allocating its own frame. Only three entries are relevant to LLVM. The + first entry is the previous stack pointer (sp), aka link. This allows + probing tools like gdb or exception handlers to quickly scan the frames in + the stack. A function epilog can also use the link to pop the frame from the + stack. The third entry in the linkage area is used to save the return + address from the lr register. Finally, as mentioned above, the last entry is + used to save the previous frame pointer (r31.) The entries in the linkage + area are the size of a GPR, thus the linkage area is 24 bytes long in 32 bit + mode and 48 bytes in 64 bit mode.

+ +

32 bit linkage area

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
0Saved SP (r1)
4Saved CR
8Saved LR
12Reserved
16Reserved
20Saved FP (r31)
+ +

64 bit linkage area

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
0Saved SP (r1)
8Saved CR
16Saved LR
24Reserved
32Reserved
40Saved FP (r31)
+ +

The parameter area is used to store arguments being passed to a callee + function. Following the PowerPC ABI, the first few arguments are actually + passed in registers, with the space in the parameter area unused. However, + if there are not enough registers or the callee is a thunk or vararg + function, these register arguments can be spilled into the parameter area. + Thus, the parameter area must be large enough to store all the parameters for + the largest call sequence made by the caller. The size must also be + minimally large enough to spill registers r3-r10. This allows callees blind + to the call signature, such as thunks and vararg functions, enough space to + cache the argument registers. Therefore, the parameter area is minimally 32 + bytes (64 bytes in 64 bit mode.) Also note that since the parameter area is + a fixed offset from the top of the frame, that a callee can access its spilt + arguments using fixed offsets from the stack pointer (or base pointer.)

+ +

Combining the information about the linkage, parameter areas and alignment. A + stack frame is minimally 64 bytes in 32 bit mode and 128 bytes in 64 bit + mode.

+ +

The dynamic area starts out as size zero. If a function uses dynamic + alloca then space is added to the stack, the linkage and parameter areas are + shifted to top of stack, and the new space is available immediately below the + linkage and parameter areas. The cost of shifting the linkage and parameter + areas is minor since only the link value needs to be copied. The link value + can be easily fetched by adding the original frame size to the base pointer. + Note that allocations in the dynamic space need to observe 16 byte + alignment.

+ +

The locals area is where the llvm compiler reserves space for local + variables.

+ +

The saved registers area is where the llvm compiler spills callee + saved registers on entry to the callee.

+ +
+ + + + +
+ +

The llvm prolog and epilog are the same as described in the PowerPC ABI, with + the following exceptions. Callee saved registers are spilled after the frame + is created. This allows the llvm epilog/prolog support to be common with + other targets. The base pointer callee saved register r31 is saved in the + TOC slot of linkage area. This simplifies allocation of space for the base + pointer and makes it convenient to locate programatically and during + debugging.

+ +
+ + + + +
+ +

TODO - More to come.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/CodingStandards.html b/final/docs/CodingStandards.html new file mode 100644 index 00000000000..f290712eebf --- /dev/null +++ b/final/docs/CodingStandards.html @@ -0,0 +1,1499 @@ + + + + + LLVM Coding Standards + + + +
+ LLVM Coding Standards +
+ +
    +
  1. Introduction
  2. +
  3. Mechanical Source Issues +
      +
    1. Source Code Formatting +
        +
      1. Commenting
      2. +
      3. Comment Formatting
      4. +
      5. #include Style
      6. +
      7. Source Code Width
      8. +
      9. Use Spaces Instead of Tabs
      10. +
      11. Indent Code Consistently
      12. +
    2. +
    3. Compiler Issues +
        +
      1. Treat Compiler Warnings Like + Errors
      2. +
      3. Write Portable Code
      4. +
      5. Do not use RTTI or Exceptions
      6. +
      7. Use of class/struct Keywords
      8. +
    4. +
  4. +
  5. Style Issues +
      +
    1. The High-Level Issues +
        +
      1. A Public Header File is a + Module
      2. +
      3. #include as Little as Possible
      4. +
      5. Keep "internal" Headers + Private
      6. +
      7. Use Early Exits and continue to Simplify + Code
      8. +
      9. Don't use else after a + return
      10. +
      11. Turn Predicate Loops into Predicate + Functions
      12. +
    2. +
    3. The Low-Level Issues +
        +
      1. Name Types, Functions, Variables, and Enumerators Properly
      2. +
      3. Assert Liberally
      4. +
      5. Do not use 'using namespace std'
      6. +
      7. Provide a virtual method anchor for + classes in headers
      8. +
      9. Don't evaluate end() every time through a + loop
      10. +
      11. #include <iostream> is + forbidden
      12. +
      13. Use raw_ostream
      14. +
      15. Avoid std::endl
      16. +
    4. + +
    5. Microscopic Details +
        +
      1. Spaces Before Parentheses
      2. +
      3. Prefer Preincrement
      4. +
      5. Namespace Indentation
      6. +
      7. Anonymous Namespaces
      8. +
    6. + + +
  6. +
  7. See Also
  8. +
+ +
+

Written by Chris Lattner

+
+ + + + + + +
+ +

This document attempts to describe a few coding standards that are being used +in the LLVM source tree. Although no coding standards should be regarded as +absolute requirements to be followed in all instances, coding standards can be +useful.

+ +

This document intentionally does not prescribe fixed standards for religious +issues such as brace placement and space usage. For issues like this, follow +the golden rule:

+ +
+ +

If you are adding a significant body of source to a +project, feel free to use whatever style you are most comfortable with. If you +are extending, enhancing, or bug fixing already implemented code, use the style +that is already being used so that the source is uniform and easy to +follow.

+ +
+ +

The ultimate goal of these guidelines is the increase readability and +maintainability of our common source base. If you have suggestions for topics to +be included, please mail them to Chris.

+ +
+ + + + + + + + + + + +
+ +

Comments are one critical part of readability and maintainability. Everyone +knows they should comment, so should you. When writing comments, write them as +English prose, which means they should use proper capitalization, punctuation, +etc. Although we all should probably +comment our code more than we do, there are a few very critical places that +documentation is very useful:

+ +File Headers + +

Every source file should have a header on it that describes the basic +purpose of the file. If a file does not have a header, it should not be +checked into Subversion. Most source trees will probably have a standard +file header format. The standard format for the LLVM source tree looks like +this:

+ +
+
+//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the Instruction class, which is the
+// base class for all of the VM instructions.
+//
+//===----------------------------------------------------------------------===//
+
+
+ +

A few things to note about this particular format: The "-*- C++ +-*-" string on the first line is there to tell Emacs that the source file +is a C++ file, not a C file (Emacs assumes .h files are C files by default). +Note that this tag is not necessary in .cpp files. The name of the file is also +on the first line, along with a very short description of the purpose of the +file. This is important when printing out code and flipping though lots of +pages.

+ +

The next section in the file is a concise note that defines the license +that the file is released under. This makes it perfectly clear what terms the +source code can be distributed under and should not be modified in any way.

+ +

The main body of the description does not have to be very long in most cases. +Here it's only two lines. If an algorithm is being implemented or something +tricky is going on, a reference to the paper where it is published should be +included, as well as any notes or "gotchas" in the code to watch out for.

+ +Class overviews + +

Classes are one fundamental part of a good object oriented design. As such, +a class definition should have a comment block that explains what the class is +used for... if it's not obvious. If it's so completely obvious your grandma +could figure it out, it's probably safe to leave it out. Naming classes +something sane goes a long ways towards avoiding writing documentation.

+ + +Method information + +

Methods defined in a class (as well as any global functions) should also be +documented properly. A quick note about what it does and a description of the +borderline behaviour is all that is necessary here (unless something +particularly tricky or insidious is going on). The hope is that people can +figure out how to use your interfaces without reading the code itself... that is +the goal metric.

+ +

Good things to talk about here are what happens when something unexpected +happens: does the method return null? Abort? Format your hard disk?

+ +
+ + + + +
+ +

In general, prefer C++ style (//) comments. They take less space, +require less typing, don't have nesting problems, etc. There are a few cases +when it is useful to use C style (/* */) comments however:

+ +
    +
  1. When writing C code: Obviously if you are writing C code, use C style + comments.
  2. +
  3. When writing a header file that may be #included by a C source + file.
  4. +
  5. When writing a source file that is used by a tool that only accepts C + style comments.
  6. +
+ +

To comment out a large block of code, use #if 0 and #endif. +These nest properly and are better behaved in general than C style comments.

+ +
+ + + + +
+ +

Immediately after the header file comment (and +include guards if working on a header file), the minimal list of #includes required by the +file should be listed. We prefer these #includes to be listed in this +order:

+ +
    +
  1. Main Module Header
  2. +
  3. Local/Private Headers
  4. +
  5. llvm/*
  6. +
  7. llvm/Analysis/*
  8. +
  9. llvm/Assembly/*
  10. +
  11. llvm/Bitcode/*
  12. +
  13. llvm/CodeGen/*
  14. +
  15. ...
  16. +
  17. Support/*
  18. +
  19. Config/*
  20. +
  21. System #includes
  22. +
+ +

and each category should be sorted by name.

+ +

The "Main Module Header" file applies to .cpp files +which implement an interface defined by a .h file. This #include +should always be included first regardless of where it lives on the file +system. By including a header file first in the .cpp files that implement the +interfaces, we ensure that the header does not have any hidden dependencies +which are not explicitly #included in the header, but should be. It is also a +form of documentation in the .cpp file to indicate where the interfaces it +implements are defined.

+ +
+ + + + +
+ +

Write your code to fit within 80 columns of text. This helps those of us who +like to print out code and look at your code in an xterm without resizing +it.

+ +

The longer answer is that there must be some limit to the width of the code +in order to reasonably allow developers to have multiple files side-by-side in +windows on a modest display. If you are going to pick a width limit, it is +somewhat arbitrary but you might as well pick something standard. Going with +90 columns (for example) instead of 80 columns wouldn't add any significant +value and would be detrimental to printing out code. Also many other projects +have standardized on 80 columns, so some people have already configured their +editors for it (vs something else, like 90 columns).

+ +

This is one of many contentious issues in coding standards, but it is not up +for debate.

+ +
+ + + + +
+ +

In all cases, prefer spaces to tabs in source files. People have different +preferred indentation levels, and different styles of indentation that they +like; this is fine. What isn't fine is that different editors/viewers expand +tabs out to different tab stops. This can cause your code to look completely +unreadable, and it is not worth dealing with.

+ +

As always, follow the Golden Rule above: follow the +style of existing code if you are modifying and extending it. If you like four +spaces of indentation, DO NOT do that in the middle of a chunk of code +with two spaces of indentation. Also, do not reindent a whole source file: it +makes for incredible diffs that are absolutely worthless.

+ +
+ + + + +
+ +

Okay, in your first year of programming you were told that indentation is +important. If you didn't believe and internalize this then, now is the time. +Just do it.

+ +
+ + + + + + + + + +
+ +

If your code has compiler warnings in it, something is wrong — you +aren't casting values correctly, your have "questionable" constructs in your +code, or you are doing something legitimately wrong. Compiler warnings can +cover up legitimate errors in output and make dealing with a translation unit +difficult.

+ +

It is not possible to prevent all warnings from all compilers, nor is it +desirable. Instead, pick a standard compiler (like gcc) that provides +a good thorough set of warnings, and stick to it. At least in the case of +gcc, it is possible to work around any spurious errors by changing the +syntax of the code slightly. For example, a warning that annoys me occurs when +I write code like this:

+ +
+
+if (V = getValue()) {
+  ...
+}
+
+
+ +

gcc will warn me that I probably want to use the == +operator, and that I probably mistyped it. In most cases, I haven't, and I +really don't want the spurious errors. To fix this particular problem, I +rewrite the code like this:

+ +
+
+if ((V = getValue())) {
+  ...
+}
+
+
+ +

which shuts gcc up. Any gcc warning that annoys you can +be fixed by massaging the code appropriately.

+ +

These are the gcc warnings that I prefer to enable:

+ +
+
+-Wall -Winline -W -Wwrite-strings -Wno-unused
+
+
+ +
+ + + + +
+ +

In almost all cases, it is possible and within reason to write completely +portable code. If there are cases where it isn't possible to write portable +code, isolate it behind a well defined (and well documented) interface.

+ +

In practice, this means that you shouldn't assume much about the host +compiler, and Visual Studio tends to be the lowest common denominator. +If advanced features are used, they should only be an implementation detail of +a library which has a simple exposed API, and preferably be buried in +libSystem.

+ +
+ + + +
+ +

In an effort to reduce code and executable size, LLVM does not use RTTI +(e.g. dynamic_cast<>) or exceptions. These two language features +violate the general C++ principle of "you only pay for what you use", +causing executable bloat even if exceptions are never used in the code base, or +if RTTI is never used for a class. Because of this, we turn them off globally +in the code.

+ +

That said, LLVM does make extensive use of a hand-rolled form of RTTI that +use templates like isa<>, +cast<>, and dyn_cast<>. This form of RTTI is +opt-in and can be added to any class. It is also substantially more efficient +than dynamic_cast<>.

+ +
+ + + +
+ +

In C++, the class and struct keywords can be used almost +interchangeably. The only difference is when they are used to declare a class: +class makes all members private by default while struct makes +all members public by default.

+ +

Unfortunately, not all compilers follow the rules and some will generate +different symbols based on whether class or struct was used to +declare the symbol. This can lead to problems at link time.

+ +

So, the rule for LLVM is to always use the class keyword, unless +all members are public and the type is a C++ +POD type, in +which case struct is allowed.

+ +
+ + + + + + + + + + + + + + +
+ +

C++ doesn't do too well in the modularity department. There is no real +encapsulation or data hiding (unless you use expensive protocol classes), but it +is what we have to work with. When you write a public header file (in the LLVM +source tree, they live in the top level "include" directory), you are +defining a module of functionality.

+ +

Ideally, modules should be completely independent of each other, and their +header files should only #include the absolute minimum number of +headers possible. A module is not just a class, a function, or a +namespace: it's +a collection of these that defines an interface. This interface may be +several functions, classes, or data structures, but the important issue is how +they work together.

+ +

In general, a module should be implemented by one or more .cpp +files. Each of these .cpp files should include the header that defines +their interface first. This ensures that all of the dependences of the module +header have been properly added to the module header itself, and are not +implicit. System headers should be included after user headers for a +translation unit.

+ +
+ + + + +
+ +

#include hurts compile time performance. Don't do it unless you +have to, especially in header files.

+ +

But wait! Sometimes you need to have the definition of a class to use it, or +to inherit from it. In these cases go ahead and #include that header +file. Be aware however that there are many cases where you don't need to have +the full definition of a class. If you are using a pointer or reference to a +class, you don't need the header file. If you are simply returning a class +instance from a prototyped function or method, you don't need it. In fact, for +most cases, you simply don't need the definition of a class. And not +#include'ing speeds up compilation.

+ +

It is easy to try to go too overboard on this recommendation, however. You +must include all of the header files that you are using — you can +include them either directly or indirectly (through another header file). To +make sure that you don't accidentally forget to include a header file in your +module header, make sure to include your module header first in the +implementation file (as mentioned above). This way there won't be any hidden +dependencies that you'll find out about later.

+ +
+ + + + +
+ +

Many modules have a complex implementation that causes them to use more than +one implementation (.cpp) file. It is often tempting to put the +internal communication interface (helper classes, extra functions, etc) in the +public module header file. Don't do this!

+ +

If you really need to do something like this, put a private header file in +the same directory as the source files, and include it locally. This ensures +that your private interface remains private and undisturbed by outsiders.

+ +

Note however, that it's okay to put extra implementation methods in a public +class itself. Just make them private (or protected) and all is well.

+ +
+ + + + +
+ +

When reading code, keep in mind how much state and how many previous +decisions have to be remembered by the reader to understand a block of code. +Aim to reduce indentation where possible when it doesn't make it more difficult +to understand the code. One great way to do this is by making use of early +exits and the continue keyword in long loops. As an example of using +an early exit from a function, consider this "bad" code:

+ +
+
+Value *DoSomething(Instruction *I) {
+  if (!isa<TerminatorInst>(I) &&
+      I->hasOneUse() && SomeOtherThing(I)) {
+    ... some long code ....
+  }
+  
+  return 0;
+}
+
+
+ +

This code has several problems if the body of the 'if' is large. +When you're looking at the top of the function, it isn't immediately clear that +this only does interesting things with non-terminator instructions, and +only applies to things with the other predicates. Second, it is relatively +difficult to describe (in comments) why these predicates are important because +the if statement makes it difficult to lay out the comments. Third, +when you're deep within the body of the code, it is indented an extra level. +Finally, when reading the top of the function, it isn't clear what the result is +if the predicate isn't true; you have to read to the end of the function to know +that it returns null.

+ +

It is much preferred to format the code like this:

+ +
+
+Value *DoSomething(Instruction *I) {
+  // Terminators never need 'something' done to them because ... 
+  if (isa<TerminatorInst>(I))
+    return 0;
+
+  // We conservatively avoid transforming instructions with multiple uses
+  // because goats like cheese.
+  if (!I->hasOneUse())
+    return 0;
+
+  // This is really just here for example.
+  if (!SomeOtherThing(I))
+    return 0;
+    
+  ... some long code ....
+}
+
+
+ +

This fixes these problems. A similar problem frequently happens in for +loops. A silly example is something like this:

+ +
+
+  for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
+    if (BinaryOperator *BO = dyn_cast<BinaryOperator>(II)) {
+      Value *LHS = BO->getOperand(0);
+      Value *RHS = BO->getOperand(1);
+      if (LHS != RHS) {
+        ...
+      }
+    }
+  }
+
+
+ +

When you have very, very small loops, this sort of structure is fine. But if +it exceeds more than 10-15 lines, it becomes difficult for people to read and +understand at a glance. The problem with this sort of code is that it gets very +nested very quickly. Meaning that the reader of the code has to keep a lot of +context in their brain to remember what is going immediately on in the loop, +because they don't know if/when the if conditions will have elses etc. +It is strongly preferred to structure the loop like this:

+ +
+
+  for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
+    BinaryOperator *BO = dyn_cast<BinaryOperator>(II);
+    if (!BO) continue;
+    
+    Value *LHS = BO->getOperand(0);
+    Value *RHS = BO->getOperand(1);
+    if (LHS == RHS) continue;
+
+    ...
+  }
+
+
+ +

This has all the benefits of using early exits for functions: it reduces +nesting of the loop, it makes it easier to describe why the conditions are true, +and it makes it obvious to the reader that there is no else coming up +that they have to push context into their brain for. If a loop is large, this +can be a big understandability win.

+ +
+ + + + +
+ +

For similar reasons above (reduction of indentation and easier reading), +please do not use 'else' or 'else if' after something that +interrupts control flow — like return, break, +continue, goto, etc. For example, this is bad:

+ +
+
+  case 'J': {
+    if (Signed) {
+      Type = Context.getsigjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_sigjmp_buf;
+        return QualType();
+      } else {
+        break;
+      }
+    } else {
+      Type = Context.getjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_jmp_buf;
+        return QualType();
+      } else {
+        break;
+      }
+    }
+  }
+  }
+
+
+ +

It is better to write it like this:

+ +
+
+  case 'J':
+    if (Signed) {
+      Type = Context.getsigjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_sigjmp_buf;
+        return QualType();
+      }
+    } else {
+      Type = Context.getjmp_bufType();
+      if (Type.isNull()) {
+        Error = ASTContext::GE_Missing_jmp_buf;
+        return QualType();
+      }
+    }
+    break;
+
+
+ +

Or better yet (in this case) as:

+ +
+
+  case 'J':
+    if (Signed)
+      Type = Context.getsigjmp_bufType();
+    else
+      Type = Context.getjmp_bufType();
+    
+    if (Type.isNull()) {
+      Error = Signed ? ASTContext::GE_Missing_sigjmp_buf :
+                       ASTContext::GE_Missing_jmp_buf;
+      return QualType();
+    }
+    break;
+
+
+ +

The idea is to reduce indentation and the amount of code you have to keep +track of when reading the code.

+ +
+ + + + +
+ +

It is very common to write small loops that just compute a boolean value. +There are a number of ways that people commonly write these, but an example of +this sort of thing is:

+ +
+
+  bool FoundFoo = false;
+  for (unsigned i = 0, e = BarList.size(); i != e; ++i)
+    if (BarList[i]->isFoo()) {
+      FoundFoo = true;
+      break;
+    }
+    
+  if (FoundFoo) {
+    ...
+  }
+
+
+ +

This sort of code is awkward to write, and is almost always a bad sign. +Instead of this sort of loop, we strongly prefer to use a predicate function +(which may be static) that uses +early exits to compute the predicate. We prefer +the code to be structured like this:

+ +
+
+/// ListContainsFoo - Return true if the specified list has an element that is
+/// a foo.
+static bool ListContainsFoo(const std::vector<Bar*> &List) {
+  for (unsigned i = 0, e = List.size(); i != e; ++i)
+    if (List[i]->isFoo())
+      return true;
+  return false;
+}
+...
+
+  if (ListContainsFoo(BarList)) {
+    ...
+  }
+
+
+ +

There are many reasons for doing this: it reduces indentation and factors out +code which can often be shared by other code that checks for the same predicate. +More importantly, it forces you to pick a name for the function, and +forces you to write a comment for it. In this silly example, this doesn't add +much value. However, if the condition is complex, this can make it a lot easier +for the reader to understand the code that queries for this predicate. Instead +of being faced with the in-line details of how we check to see if the BarList +contains a foo, we can trust the function name and continue reading with better +locality.

+ +
+ + + + + + + + + + +
+ +

Poorly-chosen names can mislead the reader and cause bugs. We cannot stress +enough how important it is to use descriptive names. Pick names that +match the semantics and role of the underlying entities, within reason. Avoid +abbreviations unless they are well known. After picking a good name, make sure +to use consistent capitalization for the name, as inconsistency requires clients +to either memorize the APIs or to look it up to find the exact spelling.

+ +

In general, names should be in camel case (e.g. TextFileReader +and isLValue()). Different kinds of declarations have different +rules:

+ +
    +
  • Type names (including classes, structs, enums, typedefs, etc) + should be nouns and start with an upper-case letter (e.g. + TextFileReader).

  • + +
  • Function names should be verb phrases (as they represent + actions), and command-like function should be imperative. The name should + be camel case, and start with a lower case letter (e.g. openFile() + or isFoo()).

  • + +
  • Enum declarations (e.g. enum Foo {...}) are types, so + they should follow the naming conventions for types. A common use for enums + is as a discriminator for a union, or an indicator of a subclass. When an + enum is used for something like this, it should have a Kind suffix + (e.g. ValueKind).

  • + +
  • Enumerators (e.g. enum { Foo, Bar }) and public member + variables should start with an upper-case letter, just like types. + Unless the enumerators are defined in their own small namespace or inside a + class, enumerators should have a prefix corresponding to the enum + declaration name. For example, enum ValueKind { ... }; may contain + enumerators like VK_Argument, VK_BasicBlock, etc. + Enumerators that are just convenience constants are exempt from the + requirement for a prefix. For instance:

    + +
    +
    +enum {
    +  MaxSize = 42,
    +  Density = 12
    +};
    +
    +
    +
  • + +
+ +

As an exception, classes that mimic STL classes can have member names in +STL's style of lower-case words separated by underscores (e.g. begin(), +push_back(), and empty()).

+ +

Here are some examples of good and bad names:

+ +
+
+class VehicleMaker {
+  ...
+  Factory<Tire> F;            // Bad -- abbreviation and non-descriptive.
+  Factory<Tire> Factory;      // Better.
+  Factory<Tire> TireFactory;  // Even better -- if VehicleMaker has more than one
+                              // kind of factories.
+};
+
+Vehicle MakeVehicle(VehicleType Type) {
+  VehicleMaker M;                         // Might be OK if having a short life-span.
+  Tire tmp1 = M.makeTire();               // Bad -- 'tmp1' provides no information.
+  Light headlight = M.makeLight("head");  // Good -- descriptive.
+  ...
+}
+
+
+ +
+ + + + + +
+ +

Use the "assert" macro to its fullest. Check all of your +preconditions and assumptions, you never know when a bug (not necessarily even +yours) might be caught early by an assertion, which reduces debugging time +dramatically. The "<cassert>" header file is probably already +included by the header files you are using, so it doesn't cost anything to use +it.

+ +

To further assist with debugging, make sure to put some kind of error message +in the assertion statement, which is printed if the assertion is tripped. This +helps the poor debugger make sense of why an assertion is being made and +enforced, and hopefully what to do about it. Here is one complete example:

+ +
+
+inline Value *getOperand(unsigned i) { 
+  assert(i < Operands.size() && "getOperand() out of range!");
+  return Operands[i]; 
+}
+
+
+ +

Here are more examples:

+ +
+
+assert(Ty->isPointerType() && "Can't allocate a non pointer type!");
+
+assert((Opcode == Shl || Opcode == Shr) && "ShiftInst Opcode invalid!");
+
+assert(idx < getNumSuccessors() && "Successor # out of range!");
+
+assert(V1.getType() == V2.getType() && "Constant types must be identical!");
+
+assert(isa<PHINode>(Succ->front()) && "Only works on PHId BBs!");
+
+
+ +

You get the idea.

+ +

Please be aware that, when adding assert statements, not all compilers are aware of +the semantics of the assert. In some places, asserts are used to indicate a piece of +code that should not be reached. These are typically of the form:

+ +
+
+assert(0 && "Some helpful error message");
+
+
+ +

When used in a function that returns a value, they should be followed with a return +statement and a comment indicating that this line is never reached. This will prevent +a compiler which is unable to deduce that the assert statement never returns from +generating a warning.

+ +
+
+assert(0 && "Some helpful error message");
+// Not reached
+return 0;
+
+
+ +

Another issue is that values used only by assertions will produce an "unused +value" warning when assertions are disabled. For example, this code will +warn:

+ +
+
+unsigned Size = V.size();
+assert(Size > 42 && "Vector smaller than it should be");
+
+bool NewToSet = Myset.insert(Value);
+assert(NewToSet && "The value shouldn't be in the set yet");
+
+
+ +

These are two interesting different cases. In the first case, the call to +V.size() is only useful for the assert, and we don't want it executed when +assertions are disabled. Code like this should move the call into the assert +itself. In the second case, the side effects of the call must happen whether +the assert is enabled or not. In this case, the value should be cast to void to +disable the warning. To be specific, it is preferred to write the code like +this:

+ +
+
+assert(V.size() > 42 && "Vector smaller than it should be");
+
+bool NewToSet = Myset.insert(Value); (void)NewToSet;
+assert(NewToSet && "The value shouldn't be in the set yet");
+
+
+ + +
+ + + + +
+ +

In LLVM, we prefer to explicitly prefix all identifiers from the standard +namespace with an "std::" prefix, rather than rely on +"using namespace std;".

+ +

In header files, adding a 'using namespace XXX' directive pollutes +the namespace of any source file that #includes the header. This is +clearly a bad thing.

+ +

In implementation files (e.g. .cpp files), the rule is more of a stylistic +rule, but is still important. Basically, using explicit namespace prefixes +makes the code clearer, because it is immediately obvious what facilities +are being used and where they are coming from. And more portable, because +namespace clashes cannot occur between LLVM code and other namespaces. The +portability rule is important because different standard library implementations +expose different symbols (potentially ones they shouldn't), and future revisions +to the C++ standard will add more symbols to the std namespace. As +such, we never use 'using namespace std;' in LLVM.

+ +

The exception to the general rule (i.e. it's not an exception for +the std namespace) is for implementation files. For example, all of +the code in the LLVM project implements code that lives in the 'llvm' namespace. +As such, it is ok, and actually clearer, for the .cpp files to have a +'using namespace llvm;' directive at the top, after the +#includes. This reduces indentation in the body of the file for source +editors that indent based on braces, and keeps the conceptual context cleaner. +The general form of this rule is that any .cpp file that implements +code in any namespace may use that namespace (and its parents'), but should not +use any others.

+ +
+ + + + +
+ +

If a class is defined in a header file and has a v-table (either it has +virtual methods or it derives from classes with virtual methods), it must +always have at least one out-of-line virtual method in the class. Without +this, the compiler will copy the vtable and RTTI into every .o file +that #includes the header, bloating .o file sizes and +increasing link times.

+ +
+ + + + +
+ +

Because C++ doesn't have a standard "foreach" loop (though it can be +emulated with macros and may be coming in C++'0x) we end up writing a lot of +loops that manually iterate from begin to end on a variety of containers or +through other data structures. One common mistake is to write a loop in this +style:

+ +
+
+  BasicBlock *BB = ...
+  for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
+     ... use I ...
+
+
+ +

The problem with this construct is that it evaluates "BB->end()" +every time through the loop. Instead of writing the loop like this, we strongly +prefer loops to be written so that they evaluate it once before the loop starts. +A convenient way to do this is like so:

+ +
+
+  BasicBlock *BB = ...
+  for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+     ... use I ...
+
+
+ +

The observant may quickly point out that these two loops may have different +semantics: if the container (a basic block in this case) is being mutated, then +"BB->end()" may change its value every time through the loop and the +second loop may not in fact be correct. If you actually do depend on this +behavior, please write the loop in the first form and add a comment indicating +that you did it intentionally.

+ +

Why do we prefer the second form (when correct)? Writing the loop in the +first form has two problems. First it may be less efficient than evaluating it +at the start of the loop. In this case, the cost is probably minor — a +few extra loads every time through the loop. However, if the base expression is +more complex, then the cost can rise quickly. I've seen loops where the end +expression was actually something like: "SomeMap[x]->end()" and map +lookups really aren't cheap. By writing it in the second form consistently, you +eliminate the issue entirely and don't even have to think about it.

+ +

The second (even bigger) issue is that writing the loop in the first form +hints to the reader that the loop is mutating the container (a fact that a +comment would handily confirm!). If you write the loop in the second form, it +is immediately obvious without even looking at the body of the loop that the +container isn't being modified, which makes it easier to read the code and +understand what it does.

+ +

While the second form of the loop is a few extra keystrokes, we do strongly +prefer it.

+ +
+ + + + +
+ +

The use of #include <iostream> in library files is +hereby forbidden. The primary reason for doing this is to +support clients using LLVM libraries as part of larger systems. In particular, +we statically link LLVM into some dynamic libraries. Even if LLVM isn't used, +the static constructors are run whenever an application starts up that uses the +dynamic library. There are two problems with this:

+ +
    +
  1. The time to run the static c'tors impacts startup time of applications + — a critical time for GUI apps.
  2. + +
  3. The static c'tors cause the app to pull many extra pages of memory off the + disk: both the code for the static c'tors in each .o file and the + small amount of data that gets touched. In addition, touched/dirty pages + put more pressure on the VM system on low-memory machines.
  4. +
+ +

Note that using the other stream headers (<sstream> for +example) is not problematic in this regard — +just <iostream>. However, raw_ostream provides various +APIs that are better performing for almost every use than std::ostream +style APIs. Therefore new code should always +use raw_ostream for writing, or +the llvm::MemoryBuffer API for reading files.

+ +
+ + + + + +
+ +

LLVM includes a lightweight, simple, and efficient stream implementation +in llvm/Support/raw_ostream.h, which provides all of the common +features of std::ostream. All new code should use raw_ostream +instead of ostream.

+ +

Unlike std::ostream, raw_ostream is not a template and can +be forward declared as class raw_ostream. Public headers should +generally not include the raw_ostream header, but use forward +declarations and constant references to raw_ostream instances.

+ +
+ + + + + +
+ +

The std::endl modifier, when used with iostreams outputs a +newline to the output stream specified. In addition to doing this, however, it +also flushes the output stream. In other words, these are equivalent:

+ +
+
+std::cout << std::endl;
+std::cout << '\n' << std::flush;
+
+
+ +

Most of the time, you probably have no reason to flush the output stream, so +it's better to use a literal '\n'.

+ +
+ + + + + + +

This section describes preferred low-level formatting guidelines along with +reasoning on why we prefer them.

+ + + + +
+ +

We prefer to put a space before an open parenthesis only in control flow +statements, but not in normal function call expressions and function-like +macros. For example, this is good:

+ +
+
+if (x) ...
+for (i = 0; i != 100; ++i) ...
+while (llvm_rocks) ...
+
+somefunc(42);
+assert(3 != 4 && "laws of math are failing me");
+  
+a = foo(42, 92) + bar(x);
+
+
+ +

and this is bad:

+ +
+
+if(x) ...
+for(i = 0; i != 100; ++i) ...
+while(llvm_rocks) ...
+
+somefunc (42);
+assert (3 != 4 && "laws of math are failing me");
+  
+a = foo (42, 92) + bar (x);
+
+
+ +

The reason for doing this is not completely arbitrary. This style makes +control flow operators stand out more, and makes expressions flow better. The +function call operator binds very tightly as a postfix operator. Putting a +space after a function name (as in the last example) makes it appear that the +code might bind the arguments of the left-hand-side of a binary operator with +the argument list of a function and the name of the right side. More +specifically, it is easy to misread the "a" example as:

+ +
+
+a = foo ((42, 92) + bar) (x);
+
+
+ +

when skimming through the code. By avoiding a space in a function, we avoid +this misinterpretation.

+ +
+ + + + +
+ +

Hard fast rule: Preincrement (++X) may be no slower than +postincrement (X++) and could very well be a lot faster than it. Use +preincrementation whenever possible.

+ +

The semantics of postincrement include making a copy of the value being +incremented, returning it, and then preincrementing the "work value". For +primitive types, this isn't a big deal... but for iterators, it can be a huge +issue (for example, some iterators contains stack and set objects in them... +copying an iterator could invoke the copy ctor's of these as well). In general, +get in the habit of always using preincrement, and you won't have a problem.

+ +
+ + + + +
+ +

+In general, we strive to reduce indentation wherever possible. This is useful +because we want code to fit into 80 columns without +wrapping horribly, but also because it makes it easier to understand the code. +Namespaces are a funny thing: they are often large, and we often desire to put +lots of stuff into them (so they can be large). Other times they are tiny, +because they just hold an enum or something similar. In order to balance this, +we use different approaches for small versus large namespaces. +

+ +

+If a namespace definition is small and easily fits on a screen (say, +less than 35 lines of code), then you should indent its body. Here's an +example: +

+ +
+
+namespace llvm {
+  namespace X86 {
+    /// RelocationType - An enum for the x86 relocation codes. Note that
+    /// the terminology here doesn't follow x86 convention - word means
+    /// 32-bit and dword means 64-bit.
+    enum RelocationType {
+      /// reloc_pcrel_word - PC relative relocation, add the relocated value to
+      /// the value already in memory, after we adjust it for where the PC is.
+      reloc_pcrel_word = 0,
+
+      /// reloc_picrel_word - PIC base relative relocation, add the relocated
+      /// value to the value already in memory, after we adjust it for where the
+      /// PIC base is.
+      reloc_picrel_word = 1,
+      
+      /// reloc_absolute_word, reloc_absolute_dword - Absolute relocation, just
+      /// add the relocated value to the value already in memory.
+      reloc_absolute_word = 2,
+      reloc_absolute_dword = 3
+    };
+  }
+}
+
+
+ +

Since the body is small, indenting adds value because it makes it very clear +where the namespace starts and ends, and it is easy to take the whole thing in +in one "gulp" when reading the code. If the blob of code in the namespace is +larger (as it typically is in a header in the llvm or clang namespaces), do not +indent the code, and add a comment indicating what namespace is being closed. +For example:

+ +
+
+namespace llvm {
+namespace knowledge {
+
+/// Grokable - This class represents things that Smith can have an intimate
+/// understanding of and contains the data associated with it.
+class Grokable {
+...
+public:
+  explicit Grokable() { ... }
+  virtual ~Grokable() = 0;
+  
+  ...
+
+};
+
+} // end namespace knowledge
+} // end namespace llvm
+
+
+ +

Because the class is large, we don't expect that the reader can easily +understand the entire concept in a glance, and the end of the file (where the +namespaces end) may be a long ways away from the place they open. As such, +indenting the contents of the namespace doesn't add any value, and detracts from +the readability of the class. In these cases it is best to not indent +the contents of the namespace.

+ +
+ + + + +
+ +

After talking about namespaces in general, you may be wondering about +anonymous namespaces in particular. +Anonymous namespaces are a great language feature that tells the C++ compiler +that the contents of the namespace are only visible within the current +translation unit, allowing more aggressive optimization and eliminating the +possibility of symbol name collisions. Anonymous namespaces are to C++ as +"static" is to C functions and global variables. While "static" is available +in C++, anonymous namespaces are more general: they can make entire classes +private to a file.

+ +

The problem with anonymous namespaces is that they naturally want to +encourage indentation of their body, and they reduce locality of reference: if +you see a random function definition in a C++ file, it is easy to see if it is +marked static, but seeing if it is in an anonymous namespace requires scanning +a big chunk of the file.

+ +

Because of this, we have a simple guideline: make anonymous namespaces as +small as possible, and only use them for class declarations. For example, this +is good:

+ +
+
+namespace {
+  class StringSort {
+  ...
+  public:
+    StringSort(...)
+    bool operator<(const char *RHS) const;
+  };
+} // end anonymous namespace
+
+static void Helper() { 
+  ... 
+}
+
+bool StringSort::operator<(const char *RHS) const {
+  ...
+}
+
+
+
+ +

This is bad:

+ + +
+
+namespace {
+class StringSort {
+...
+public:
+  StringSort(...)
+  bool operator<(const char *RHS) const;
+};
+
+void Helper() { 
+  ... 
+}
+
+bool StringSort::operator<(const char *RHS) const {
+  ...
+}
+
+} // end anonymous namespace
+
+
+
+ + +

This is bad specifically because if you're looking at "Helper" in the middle +of a large C++ file, that you have no immediate way to tell if it is local to +the file. When it is marked static explicitly, this is immediately obvious. +Also, there is no reason to enclose the definition of "operator<" in the +namespace just because it was declared there. +

+ +
+ + + + + + + +
+ +

A lot of these comments and recommendations have been culled for other +sources. Two particularly important books for our work are:

+ +
    + +
  1. Effective +C++ by Scott Meyers. Also +interesting and useful are "More Effective C++" and "Effective STL" by the same +author.
  2. + +
  3. Large-Scale C++ Software Design by John Lakos
  4. + +
+ +

If you get some free time, and you haven't read them: do so, you might learn +something.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/CommandGuide/FileCheck.pod b/final/docs/CommandGuide/FileCheck.pod new file mode 100644 index 00000000000..3ccaa63e176 --- /dev/null +++ b/final/docs/CommandGuide/FileCheck.pod @@ -0,0 +1,245 @@ + +=pod + +=head1 NAME + +FileCheck - Flexible pattern matching file verifier + +=head1 SYNOPSIS + +B I [I<--check-prefix=XXX>] [I<--strict-whitespace>] + +=head1 DESCRIPTION + +B reads two files (one from standard input, and one specified on the +command line) and uses one to verify the other. This behavior is particularly +useful for the testsuite, which wants to verify that the output of some tool +(e.g. llc) contains the expected information (for example, a movsd from esp or +whatever is interesting). This is similar to using grep, but it is optimized +for matching multiple different inputs in one file in a specific order. + +The I file specifies the file that contains the patterns to +match. The file to verify is always read from standard input. + +=head1 OPTIONS + +=over + +=item B<-help> + +Print a summary of command line options. + +=item B<--check-prefix> I + +FileCheck searches the contents of I for patterns to match. By +default, these patterns are prefixed with "CHECK:". If you'd like to use a +different prefix (e.g. because the same input file is checking multiple +different tool or options), the B<--check-prefix> argument allows you to specify +a specific prefix to match. + +=item B<--strict-whitespace> + +By default, FileCheck canonicalizes input horizontal whitespace (spaces and +tabs) which causes it to ignore these differences (a space will match a tab). +The --strict-whitespace argument disables this behavior. + +=item B<-version> + +Show the version number of this program. + +=back + +=head1 EXIT STATUS + +If B verifies that the file matches the expected contents, it exits +with 0. Otherwise, if not, or if an error occurs, it will exit with a non-zero +value. + +=head1 TUTORIAL + +FileCheck is typically used from LLVM regression tests, being invoked on the RUN +line of the test. A simple example of using FileCheck from a RUN line looks +like this: + + ; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s + +This syntax says to pipe the current file ("%s") into llvm-as, pipe that into +llc, then pipe the output of llc into FileCheck. This means that FileCheck will +be verifying its standard input (the llc output) against the filename argument +specified (the original .ll file specified by "%s"). To see how this works, +lets look at the rest of the .ll file (after the RUN line): + + define void @sub1(i32* %p, i32 %v) { + entry: + ; CHECK: sub1: + ; CHECK: subl + %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v) + ret void + } + + define void @inc4(i64* %p) { + entry: + ; CHECK: inc4: + ; CHECK: incq + %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1) + ret void + } + +Here you can see some "CHECK:" lines specified in comments. Now you can see +how the file is piped into llvm-as, then llc, and the machine code output is +what we are verifying. FileCheck checks the machine code output to verify that +it matches what the "CHECK:" lines specify. + +The syntax of the CHECK: lines is very simple: they are fixed strings that +must occur in order. FileCheck defaults to ignoring horizontal whitespace +differences (e.g. a space is allowed to match a tab) but otherwise, the contents +of the CHECK: line is required to match some thing in the test file exactly. + +One nice thing about FileCheck (compared to grep) is that it allows merging +test cases together into logical groups. For example, because the test above +is checking for the "sub1:" and "inc4:" labels, it will not match unless there +is a "subl" in between those labels. If it existed somewhere else in the file, +that would not count: "grep subl" matches if subl exists anywhere in the +file. + + + +=head2 The FileCheck -check-prefix option + +The FileCheck -check-prefix option allows multiple test configurations to be +driven from one .ll file. This is useful in many circumstances, for example, +testing different architectural variants with llc. Here's a simple example: + + ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X32 + ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \ + ; RUN: | FileCheck %s -check-prefix=X64 + + define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind { + %tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1 + ret <4 x i32> %tmp1 + ; X32: pinsrd_1: + ; X32: pinsrd $1, 4(%esp), %xmm0 + + ; X64: pinsrd_1: + ; X64: pinsrd $1, %edi, %xmm0 + } + +In this case, we're testing that we get the expected code generation with +both 32-bit and 64-bit code generation. + + + +=head2 The "CHECK-NEXT:" directive + +Sometimes you want to match lines and would like to verify that matches +happen on exactly consecutive lines with no other lines in between them. In +this case, you can use CHECK: and CHECK-NEXT: directives to specify this. If +you specified a custom check prefix, just use "-NEXT:". For +example, something like this works as you'd expect: + + define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) { + %tmp3 = load <2 x double>* %A, align 16 + %tmp7 = insertelement <2 x double> undef, double %B, i32 0 + %tmp9 = shufflevector <2 x double> %tmp3, + <2 x double> %tmp7, + <2 x i32> < i32 0, i32 2 > + store <2 x double> %tmp9, <2 x double>* %r, align 16 + ret void + + ; CHECK: t2: + ; CHECK: movl 8(%esp), %eax + ; CHECK-NEXT: movapd (%eax), %xmm0 + ; CHECK-NEXT: movhpd 12(%esp), %xmm0 + ; CHECK-NEXT: movl 4(%esp), %eax + ; CHECK-NEXT: movapd %xmm0, (%eax) + ; CHECK-NEXT: ret + } + +CHECK-NEXT: directives reject the input unless there is exactly one newline +between it an the previous directive. A CHECK-NEXT cannot be the first +directive in a file. + + + +=head2 The "CHECK-NOT:" directive + +The CHECK-NOT: directive is used to verify that a string doesn't occur +between two matches (or before the first match, or after the last match). For +example, to verify that a load is removed by a transformation, a test like this +can be used: + + define i8 @coerce_offset0(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = bitcast i32* %P to i8* + %P3 = getelementptr i8* %P2, i32 2 + + %A = load i8* %P3 + ret i8 %A + ; CHECK: @coerce_offset0 + ; CHECK-NOT: load + ; CHECK: ret i8 + } + + + +=head2 FileCheck Pattern Matching Syntax + +The CHECK: and CHECK-NOT: directives both take a pattern to match. For most +uses of FileCheck, fixed string matching is perfectly sufficient. For some +things, a more flexible form of matching is desired. To support this, FileCheck +allows you to specify regular expressions in matching strings, surrounded by +double braces: B<{{yourregex}}>. Because we want to use fixed string +matching for a majority of what we do, FileCheck has been designed to support +mixing and matching fixed string matching with regular expressions. This allows +you to write things like this: + + ; CHECK: movhpd {{[0-9]+}}(%esp), {{%xmm[0-7]}} + +In this case, any offset from the ESP register will be allowed, and any xmm +register will be allowed. + +Because regular expressions are enclosed with double braces, they are +visually distinct, and you don't need to use escape characters within the double +braces like you would in C. In the rare case that you want to match double +braces explicitly from the input, you can use something ugly like +B<{{[{][{]}}> as your pattern. + + + +=head2 FileCheck Variables + +It is often useful to match a pattern and then verify that it occurs again +later in the file. For codegen tests, this can be useful to allow any register, +but verify that that register is used consistently later. To do this, FileCheck +allows named variables to be defined and substituted into patterns. Here is a +simple example: + + ; CHECK: test5: + ; CHECK: notw [[REGISTER:%[a-z]+]] + ; CHECK: andw {{.*}}[[REGISTER]] + +The first check line matches a regex (%[a-z]+) and captures it into +the variables "REGISTER". The second line verifies that whatever is in REGISTER +occurs later in the file after an "andw". FileCheck variable references are +always contained in [[ ]] pairs, are named, and their names can be +formed with the regex "[a-zA-Z_][a-zA-Z0-9_]*". If a colon follows the +name, then it is a definition of the variable, if not, it is a use. + +FileCheck variables can be defined multiple times, and uses always get the +latest value. Note that variables are all read at the start of a "CHECK" line +and are all defined at the end. This means that if you have something like +"CHECK: [[XYZ:.*]]x[[XYZ]]" that the check line will read the previous +value of the XYZ variable and define a new one after the match is performed. If +you need to do something like this you can probably take advantage of the fact +that FileCheck is not actually line-oriented when it matches, this allows you to +define two separate CHECK lines that match on the same line. + + + +=head1 AUTHORS + +Maintained by The LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/Makefile b/final/docs/CommandGuide/Makefile new file mode 100644 index 00000000000..2c2d0760e79 --- /dev/null +++ b/final/docs/CommandGuide/Makefile @@ -0,0 +1,103 @@ +##===- docs/CommandGuide/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +ifdef BUILD_FOR_WEBSITE +# This special case is for keeping the CommandGuide on the LLVM web site +# up to date automatically as the documents are checked in. It must build +# the POD files to HTML only and keep them in the src directories. It must also +# build in an unconfigured tree, hence the ifdef. To use this, run +# make -s BUILD_FOR_WEBSITE=1 inside the cvs commit script. +SRC_DOC_DIR= +DST_HTML_DIR=html/ +DST_MAN_DIR=man/man1/ +DST_PS_DIR=ps/ + +# If we are in BUILD_FOR_WEBSITE mode, default to the all target. +all:: html man ps + +clean: + rm -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) + +# To create other directories, as needed, and timestamp their creation +%/.dir: + -mkdir $* > /dev/null + date > $@ + +else + +# Otherwise, if not in BUILD_FOR_WEBSITE mode, use the project info. +LEVEL := ../.. +include $(LEVEL)/Makefile.common + +SRC_DOC_DIR=$(PROJ_SRC_DIR)/ +DST_HTML_DIR=$(PROJ_OBJ_DIR)/ +DST_MAN_DIR=$(PROJ_OBJ_DIR)/ +DST_PS_DIR=$(PROJ_OBJ_DIR)/ + +endif + + +POD := $(wildcard $(SRC_DOC_DIR)*.pod) +HTML := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_HTML_DIR)%.html, $(POD)) +MAN := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_MAN_DIR)%.1, $(POD)) +PS := $(patsubst $(SRC_DOC_DIR)%.pod, $(DST_PS_DIR)%.ps, $(POD)) + +# The set of man pages we will not install +NO_INSTALL_MANS = $(DST_MAN_DIR)FileCheck.1 + +# The set of man pages that we will install +INSTALL_MANS = $(filter-out $(NO_INSTALL_MANS), $(MAN)) + +.SUFFIXES: +.SUFFIXES: .html .pod .1 .ps + +$(DST_HTML_DIR)%.html: %.pod $(DST_HTML_DIR)/.dir + pod2html --css=manpage.css --htmlroot=. \ + --podpath=. --noindex --infile=$< --outfile=$@ --title=$* + +$(DST_MAN_DIR)%.1: %.pod $(DST_MAN_DIR)/.dir + pod2man --release=CVS --center="LLVM Command Guide" $< $@ + +$(DST_PS_DIR)%.ps: $(DST_MAN_DIR)%.1 $(DST_PS_DIR)/.dir + groff -Tps -man $< > $@ + + +html: $(HTML) +man: $(MAN) +ps: $(PS) + +EXTRA_DIST := $(POD) index.html + +clean-local:: + $(Verb) $(RM) -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) + +HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/CommandGuide +MAN_DIR := $(DESTDIR)$(PROJ_mandir)/man1 +PS_DIR := $(DESTDIR)$(PROJ_docsdir)/ps + +install-local:: $(HTML) $(INSTALL_MANS) $(PS) + $(Echo) Installing HTML CommandGuide Documentation + $(Verb) $(MKDIR) $(HTML_DIR) + $(Verb) $(DataInstall) $(HTML) $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/manpage.css $(HTML_DIR) + $(Echo) Installing MAN CommandGuide Documentation + $(Verb) $(MKDIR) $(MAN_DIR) + $(Verb) $(DataInstall) $(INSTALL_MANS) $(MAN_DIR) + $(Echo) Installing PS CommandGuide Documentation + $(Verb) $(MKDIR) $(PS_DIR) + $(Verb) $(DataInstall) $(PS) $(PS_DIR) + +uninstall-local:: + $(Echo) Uninstalling CommandGuide Documentation + $(Verb) $(RM) -rf $(HTML_DIR) $(MAN_DIR) $(PS_DIR) + +printvars:: + $(Echo) "POD : " '$(POD)' + $(Echo) "HTML : " '$(HTML)' diff --git a/final/docs/CommandGuide/bugpoint.pod b/final/docs/CommandGuide/bugpoint.pod new file mode 100644 index 00000000000..1870a0d84b6 --- /dev/null +++ b/final/docs/CommandGuide/bugpoint.pod @@ -0,0 +1,171 @@ +=pod + +=head1 NAME + +bugpoint - automatic test case reduction tool + +=head1 SYNOPSIS + +B [I] [I] [I] B<--args> +I + +=head1 DESCRIPTION + +B narrows down the source of problems in LLVM tools and passes. It +can be used to debug three types of failures: optimizer crashes, miscompilations +by optimizers, or bad native code generation (including problems in the static +and JIT compilers). It aims to reduce large test cases to small, useful ones. +For more information on the design and inner workings of B, as well as +advice for using bugpoint, see F in the LLVM +distribution. + +=head1 OPTIONS + +=over + +=item B<--additional-so> F + +Load the dynamic shared object F into the test program whenever it is +run. This is useful if you are debugging programs which depend on non-LLVM +libraries (such as the X or curses libraries) to run. + +=item B<--append-exit-code>=I<{true,false}> + +Append the test programs exit code to the output file so that a change in exit +code is considered a test failure. Defaults to false. + +=item B<--args> I + +Pass all arguments specified after -args to the test program whenever it runs. +Note that if any of the I start with a '-', you should use: + + bugpoint [bugpoint args] --args -- [program args] + +The "--" right after the B<--args> option tells B to consider any +options starting with C<-> to be part of the B<--args> option, not as options to +B itself. + +=item B<--tool-args> I + +Pass all arguments specified after --tool-args to the LLVM tool under test +(B, B, etc.) whenever it runs. You should use this option in the +following way: + + bugpoint [bugpoint args] --tool-args -- [tool args] + +The "--" right after the B<--tool-args> option tells B to consider any +options starting with C<-> to be part of the B<--tool-args> option, not as +options to B itself. (See B<--args>, above.) + +=item B<--safe-tool-args> I + +Pass all arguments specified after B<--safe-tool-args> to the "safe" execution +tool. + +=item B<--gcc-tool-args> I + +Pass all arguments specified after B<--gcc-tool-args> to the invocation of +B. + +=item B<--opt-args> I + +Pass all arguments specified after B<--opt-args> to the invocation of B. + +=item B<--disable-{dce,simplifycfg}> + +Do not run the specified passes to clean up and reduce the size of the test +program. By default, B uses these passes internally when attempting to +reduce test programs. If you're trying to find a bug in one of these passes, +B may crash. + +=item B<--enable-valgrind> + +Use valgrind to find faults in the optimization phase. This will allow +bugpoint to find otherwise asymptomatic problems caused by memory +mis-management. + +=item B<-find-bugs> + +Continually randomize the specified passes and run them on the test program +until a bug is found or the user kills B. + +=item B<-help> + +Print a summary of command line options. + +=item B<--input> F + +Open F and redirect the standard input of the test program, whenever +it runs, to come from that file. + +=item B<--load> F + +Load the dynamic object F into B itself. This object should +register new optimization passes. Once loaded, the object will add new command +line options to enable various optimizations. To see the new complete list of +optimizations, use the B<-help> and B<--load> options together; for example: + + bugpoint --load myNewPass.so -help + +=item B<--mlimit> F + +Specifies an upper limit on memory usage of the optimization and codegen. Set +to zero to disable the limit. + +=item B<--output> F + +Whenever the test program produces output on its standard output stream, it +should match the contents of F (the "reference output"). If you +do not use this option, B will attempt to generate a reference output +by compiling the program with the "safe" backend and running it. + +=item B<--profile-info-file> F + +Profile file loaded by B<--profile-loader>. + +=item B<--run-{int,jit,llc,cbe,custom}> + +Whenever the test program is compiled, B should generate code for it +using the specified code generator. These options allow you to choose the +interpreter, the JIT compiler, the static native code compiler, the C +backend, or a custom command (see B<--exec-command>) respectively. + +=item B<--safe-{llc,cbe,custom}> + +When debugging a code generator, B should use the specified code +generator as the "safe" code generator. This is a known-good code generator +used to generate the "reference output" if it has not been provided, and to +compile portions of the program that as they are excluded from the testcase. +These options allow you to choose the +static native code compiler, the C backend, or a custom command, +(see B<--exec-command>) respectively. The interpreter and the JIT backends +cannot currently be used as the "safe" backends. + +=item B<--exec-command> I + +This option defines the command to use with the B<--run-custom> and +B<--safe-custom> options to execute the bitcode testcase. This can +be useful for cross-compilation. + +=item B<--safe-path> I + +This option defines the path to the command to execute with the +B<--safe-{int,jit,llc,cbe,custom}> +option. + +=back + +=head1 EXIT STATUS + +If B succeeds in finding a problem, it will exit with 0. Otherwise, +if an error occurs, it will exit with a non-zero value. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/html/manpage.css b/final/docs/CommandGuide/html/manpage.css new file mode 100644 index 00000000000..b2003434901 --- /dev/null +++ b/final/docs/CommandGuide/html/manpage.css @@ -0,0 +1,256 @@ +/* Based on http://www.perldoc.com/css/perldoc.css */ + +@import url("../llvm.css"); + +body { font-family: Arial,Helvetica; } + +blockquote { margin: 10pt; } + +h1, a { color: #336699; } + + +/*** Top menu style ****/ +.mmenuon { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ff6600; font-size: 10pt; + } +.mmenuoff { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: 10pt; +} +.cpyright { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; +} +.cpyrightText { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; +} +.sections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 11pt; +} +.dsections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 12pt; +} +.slink { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #000000; font-size: 9pt; +} + +.slink2 { font-family: Arial,Helvetica; text-decoration: none; color: #336699; } + +.maintitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 18pt; +} +.dblArrow { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; +} +.menuSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; +} + +.newstext { + font-family: Arial,Helvetica; font-size: small; +} + +.linkmenu { + font-family: Arial,Helvetica; color: #000000; font-weight: bold; + text-decoration: none; +} + +P { + font-family: Arial,Helvetica; +} + +PRE { + font-size: 10pt; +} +.quote { + font-family: Times; text-decoration: none; + color: #000000; font-size: 9pt; font-style: italic; +} +.smstd { font-family: Arial,Helvetica; color: #000000; font-size: x-small; } +.std { font-family: Arial,Helvetica; color: #000000; } +.meerkatTitle { + font-family: sans-serif; font-size: x-small; color: black; } + +.meerkatDescription { font-family: sans-serif; font-size: 10pt; color: black } +.meerkatCategory { + font-family: sans-serif; font-size: 9pt; font-weight: bold; font-style: italic; + color: brown; } +.meerkatChannel { + font-family: sans-serif; font-size: 9pt; font-style: italic; color: brown; } +.meerkatDate { font-family: sans-serif; font-size: xx-small; color: #336699; } + +.tocTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 10pt; +} + +.toc-item { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: underline; +} + +.perlVersion { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: none; +} + +.podTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; +} + +.docTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; font-size: 10pt; +} +.dotDot { + font-family: Arial,Helvetica; font-weight: bold; + color: #000000; font-size: 9pt; +} + +.docSec { + font-family: Arial,Helvetica; font-weight: normal; + color: #333333; font-size: 9pt; +} +.docVersion { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; +} + +.docSecs-on { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #ff0000; font-size: 10pt; +} +.docSecs-off { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; +} + +h2 { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: medium; +} +h1 { + font-family: Verdana,Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: large; +} + +DL { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; +} + +UL > LI > A { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; +} + +.moduleInfo { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 11pt; +} + +.moduleInfoSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; +} + +.moduleInfoVal { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: underline; + color: #000000; font-size: 10pt; +} + +.cpanNavTitle { + font-family: Arial,Helvetica; font-weight: bold; + color: #ffffff; font-size: 10pt; +} +.cpanNavLetter { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 9pt; +} +.cpanCat { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 9pt; +} + +.bttndrkblue-bkgd-top { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgtop.gif); +} +.bttndrkblue-bkgd-left { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgleft.gif); +} +.bttndrkblue-bkgd { + padding-top: 0px; + padding-bottom: 0px; + margin-bottom: 0px; + margin-top: 0px; + background-repeat: no-repeat; + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgmiddle.gif); + vertical-align: top; +} +.bttndrkblue-bkgd-right { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgright.gif); +} +.bttndrkblue-bkgd-bottom { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgbottom.gif); +} +.bttndrkblue-text a { + color: #ffffff; + text-decoration: none; +} +a.bttndrkblue-text:hover { + color: #ffDD3C; + text-decoration: none; +} +.bg-ltblue { + background-color: #f0f5fa; +} + +.border-left-b { + background: #f0f5fa url(/i/corner-leftline.gif) repeat-y; +} + +.border-right-b { + background: #f0f5fa url(/i/corner-rightline.gif) repeat-y; +} + +.border-top-b { + background: #f0f5fa url(/i/corner-topline.gif) repeat-x; +} + +.border-bottom-b { + background: #f0f5fa url(/i/corner-botline.gif) repeat-x; +} + +.border-right-w { + background: #ffffff url(/i/corner-rightline.gif) repeat-y; +} + +.border-top-w { + background: #ffffff url(/i/corner-topline.gif) repeat-x; +} + +.border-bottom-w { + background: #ffffff url(/i/corner-botline.gif) repeat-x; +} + +.bg-white { + background-color: #ffffff; +} + +.border-left-w { + background: #ffffff url(/i/corner-leftline.gif) repeat-y; +} diff --git a/final/docs/CommandGuide/index.html b/final/docs/CommandGuide/index.html new file mode 100644 index 00000000000..8854fbbebe6 --- /dev/null +++ b/final/docs/CommandGuide/index.html @@ -0,0 +1,158 @@ + + + + LLVM Command Guide + + + + +
+ LLVM Command Guide +
+ +
+ +

These documents are HTML versions of the man pages +for all of the LLVM tools. These pages describe how to use the LLVM commands +and what their options are. Note that these pages do not describe all of the +options available for all tools. To get a complete listing, pass the +-help (general options) or -help-hidden (general+debugging +options) arguments to the tool you are interested in.

+ +
+ + + + + +
+ +
    + +
  • llvm-as - + assemble a human-readable .ll file into bytecode
  • + +
  • llvm-dis - + disassemble a bytecode file into a human-readable .ll file
  • + +
  • opt - + run a series of LLVM-to-LLVM optimizations on a bytecode file
  • + +
  • llc - + generate native machine code for a bytecode file
  • + +
  • lli - + directly run a program compiled to bytecode using a JIT compiler or + interpreter
  • + +
  • llvm-link - + link several bytecode files into one
  • + +
  • llvm-ar - + archive bytecode files
  • + +
  • llvm-ranlib - + create an index for archives made with llvm-ar
  • + +
  • llvm-nm - + print out the names and types of symbols in a bytecode file
  • + +
  • llvm-prof - + format raw `llvmprof.out' data into a human-readable report
  • + +
  • llvm-ld - + general purpose linker with loadable runtime optimization support
  • + +
  • llvm-config - + print out LLVM compilation options, libraries, etc. as configured
  • + +
  • llvmc - + a generic customizable compiler driver
  • + +
  • llvm-diff - + structurally compare two modules
  • + +
+ +
+ + + + + +
+
    + +
  • llvm-gcc - + GCC-based C front-end for LLVM + +
  • llvm-g++ - + GCC-based C++ front-end for LLVM
  • + +
+ +
+ + + + + + +
+ +
    + +
  • bugpoint - + automatic test-case reducer
  • + +
  • llvm-extract - + extract a function from an LLVM bytecode file
  • + +
  • llvm-bcanalyzer - + bytecode analyzer (analyzes the binary encoding itself, not the program it + represents)
  • + +
+
+ + + + + +
+
    + +
  • FileCheck - + Flexible file verifier used extensively by the testing harness
  • +
  • tblgen - + target description reader and generator
  • +
  • lit - + LLVM Integrated Tester, for running tests
  • + +
+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/CommandGuide/lit.pod b/final/docs/CommandGuide/lit.pod new file mode 100644 index 00000000000..989a5d7acb5 --- /dev/null +++ b/final/docs/CommandGuide/lit.pod @@ -0,0 +1,354 @@ +=pod + +=head1 NAME + +lit - LLVM Integrated Tester + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +B is a portable tool for executing LLVM and Clang style test suites, +summarizing their results, and providing indication of failures. B is +designed to be a lightweight testing tool with as simple a user interface as +possible. + +B should be run with one or more I to run specified on the command +line. Tests can be either individual test files or directories to search for +tests (see L<"TEST DISCOVERY">). + +Each specified test will be executed (potentially in parallel) and once all +tests have been run B will print summary information on the number of tests +which passed or failed (see L<"TEST STATUS RESULTS">). The B program will +execute with a non-zero exit code if any tests fail. + +By default B will use a succinct progress display and will only print +summary information for test failures. See L<"OUTPUT OPTIONS"> for options +controlling the B progress display and output. + +B also includes a number of options for controlling how tests are exected +(specific features may depend on the particular test format). See L<"EXECUTION +OPTIONS"> for more information. + +Finally, B also supports additional options for only running a subset of +the options specified on the command line, see L<"SELECTION OPTIONS"> for +more information. + +Users interested in the B architecture or designing a B testing +implementation should see L<"LIT ARCHITECTURE"> + +=head1 GENERAL OPTIONS + +=over + +=item B<-h>, B<--help> + +Show the B help message. + +=item B<-j> I, B<--threads>=I + +Run I tests in parallel. By default, this is automatically chosen to match +the number of detected available CPUs. + +=item B<--config-prefix>=I + +Search for I and I when searching for test suites, +instead of I and I. + +=item B<--param> I, B<--param> I=I + +Add a user defined parameter I with the given I (or the empty +string if not given). The meaning and use of these parameters is test suite +dependent. + +=back + +=head1 OUTPUT OPTIONS + +=over + +=item B<-q>, B<--quiet> + +Suppress any output except for test failures. + +=item B<-s>, B<--succinct> + +Show less output, for example don't show information on tests that pass. + +=item B<-v>, B<--verbose> + +Show more information on test failures, for example the entire test output +instead of just the test result. + +=item B<--no-progress-bar> + +Do not use curses based progress bar. + +=back + +=head1 EXECUTION OPTIONS + +=over + +=item B<--path>=I + +Specify an addition I to use when searching for executables in tests. + +=item B<--vg> + +Run individual tests under valgrind (using the memcheck tool). The +I<--error-exitcode> argument for valgrind is used so that valgrind failures will +cause the program to exit with a non-zero status. + +=item B<--vg-arg>=I + +When I<--vg> is used, specify an additional argument to pass to valgrind itself. + +=item B<--time-tests> + +Track the wall time individual tests take to execute and includes the results in +the summary output. This is useful for determining which tests in a test suite +take the most time to execute. Note that this option is most useful with I<-j +1>. + +=back + +=head1 SELECTION OPTIONS + +=over + +=item B<--max-tests>=I + +Run at most I tests and then terminate. + +=item B<--max-time>=I + +Spend at most I seconds (approximately) running tests and then terminate. + +=item B<--shuffle> + +Run the tests in a random order. + +=back + +=head1 ADDITIONAL OPTIONS + +=over + +=item B<--debug> + +Run B in debug mode, for debugging configuration issues and B itself. + +=item B<--show-suites> + +List the discovered test suites as part of the standard output. + +=item B<--no-tcl-as-sh> + +Run Tcl scripts internally (instead of converting to shell scripts). + +=item B<--repeat>=I + +Run each test I times. Currently this is primarily useful for timing tests, +other results are not collated in any reasonable fashion. + +=back + +=head1 EXIT STATUS + +B will exit with an exit code of 1 if there are any FAIL or XPASS +results. Otherwise, it will exit with the status 0. Other exit codes used for +non-test related failures (for example a user error or an internal program +error). + +=head1 TEST DISCOVERY + +The inputs passed to B can be either individual tests, or entire +directories or hierarchies of tests to run. When B starts up, the first +thing it does is convert the inputs into a complete list of tests to run as part +of I. + +In the B model, every test must exist inside some I. B +resolves the inputs specified on the command line to test suites by searching +upwards from the input path until it finds a I or I +file. These files serve as both a marker of test suites and as configuration +files which B loads in order to understand how to find and run the tests +inside the test suite. + +Once B has mapped the inputs into test suites it traverses the list of +inputs adding tests for individual files and recursively searching for tests in +directories. + +This behavior makes it easy to specify a subset of tests to run, while still +allowing the test suite configuration to control exactly how tests are +interpreted. In addition, B always identifies tests by the test suite they +are in, and their relative path inside the test suite. For appropriately +configured projects, this allows B to provide convenient and flexible +support for out-of-tree builds. + +=head1 TEST STATUS RESULTS + +Each test ultimately produces one of the following six results: + +=over + +=item B + +The test succeeded. + +=item B + +The test failed, but that is expected. This is used for test formats which allow +specifying that a test does not currently work, but wish to leave it in the test +suite. + +=item B + +The test succeeded, but it was expected to fail. This is used for tests which +were specified as expected to fail, but are now succeeding (generally because +the feautre they test was broken and has been fixed). + +=item B + +The test failed. + +=item B + +The test result could not be determined. For example, this occurs when the test +could not be run, the test itself is invalid, or the test was interrupted. + +=item B + +The test is not supported in this environment. This is used by test formats +which can report unsupported tests. + +=back + +Depending on the test format tests may produce additional information about +their status (generally only for failures). See the L +section for more information. + +=head1 LIT INFRASTRUCTURE + +This section describes the B testing architecture for users interested in +creating a new B testing implementation, or extending an existing one. + +B proper is primarily an infrastructure for discovering and running +arbitrary tests, and to expose a single convenient interface to these +tests. B itself doesn't know how to run tests, rather this logic is +defined by I. + +=head2 TEST SUITES + +As described in L<"TEST DISCOVERY">, tests are always located inside a I. Test suites serve to define the format of the tests they contain, the +logic for finding those tests, and any additional information to run the tests. + +B identifies test suites as directories containing I or +I files (see also B<--config-prefix>. Test suites are initially +discovered by recursively searching up the directory hierarchy for all the input +files passed on the command line. You can use B<--show-suites> to display the +discovered test suites at startup. + +Once a test suite is discovered, its config file is loaded. Config files +themselves are Python modules which will be executed. When the config file is +executed, two important global variables are predefined: + +=over + +=item B + +The global B configuration object (a I instance), which defines +the builtin test formats, global configuration parameters, and other helper +routines for implementing test configurations. + +=item B + +This is the config object (a I instance) for the test suite, +which the config file is expected to populate. The following variables are also +available on the I object, some of which must be set by the config and +others are optional or predefined: + +B I<[required]> The name of the test suite, for use in reports and +diagnostics. + +B I<[required]> The test format object which will be used to +discover and run tests in the test suite. Generally this will be a builtin test +format available from the I module. + +B The filesystem path to the test suite root. For out-of-dir +builds this is the directory that will be scanned for tests. + +B For out-of-dir builds, the path to the test suite root inside +the object directory. This is where tests will be run and temporary output files +places. + +B A dictionary representing the environment to use when executing +tests in the suite. + +B For B test formats which scan directories for tests, this +variable as a list of suffixes to identify test files. Used by: I, +I. + +B For B test formats which substitute variables into a test +script, the list of substitutions to perform. Used by: I, I. + +B Mark an unsupported directory, all tests within it will be +reported as unsupported. Used by: I, I. + +B The parent configuration, this is the config object for the directory +containing the test suite, or None. + +B The config is actually cloned for every subdirectory inside a test +suite, to allow local configuration on a per-directory basis. The I +variable can be set to a Python function which will be called whenever a +configuration is cloned (for a subdirectory). The function should takes three +arguments: (1) the parent configuration, (2) the new configuration (which the +I function will generally modify), and (3) the test path to the new +directory being scanned. + +=back + +=head2 TEST DISCOVERY + +Once test suites are located, B recursively traverses the source directory +(following I) looking for tests. When B enters a +sub-directory, it first checks to see if a nest test suite is defined in that +directory. If so, it loads that test suite recursively, otherwise it +instantiates a local test config for the directory (see L<"LOCAL CONFIGURATION +FILES">). + +Tests are identified by the test suite they are contained within, and the +relative path inside that suite. Note that the relative path may not refer to an +actual file on disk; some test formats (such as I) define "virtual +tests" which have a path that contains both the path to the actual test file and +a subpath to identify the virtual test. + +=head2 LOCAL CONFIGURATION FILES + +When B loads a subdirectory in a test suite, it instantiates a local test +configuration by cloning the configuration for the parent direction -- the root +of this configuration chain will always be a test suite. Once the test +configuration is cloned B checks for a I file in the +subdirectory. If present, this file will be loaded and can be used to specialize +the configuration for each individual directory. This facility can be used to +define subdirectories of optional tests, or to change other configuration +parameters -- for example, to change the test format, or the suffixes which +identify test files. + +=head2 LIT EXAMPLE TESTS + +The B distribution contains several example implementations of test suites +in the I directory. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Written by Daniel Dunbar and maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/llc.pod b/final/docs/CommandGuide/llc.pod new file mode 100644 index 00000000000..eb26ec00fd7 --- /dev/null +++ b/final/docs/CommandGuide/llc.pod @@ -0,0 +1,201 @@ +=pod + +=head1 NAME + +llc - LLVM static compiler + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +The B command compiles LLVM source inputs into assembly language for a +specified architecture. The assembly language output can then be passed through +a native assembler and linker to generate a native executable. + +The choice of architecture for the output assembly code is automatically +determined from the input file, unless the B<-march> option is used to override +the default. + +=head1 OPTIONS + +If I is - or omitted, B reads from standard input. Otherwise, it +will from I. Inputs can be in either the LLVM assembly language +format (.ll) or the LLVM bitcode format (.bc). + +If the B<-o> option is omitted, then B will send its output to standard +output if the input is from standard input. If the B<-o> option specifies -, +then the output will also be sent to standard output. + +If no B<-o> option is specified and an input file other than - is specified, +then B creates the output filename by taking the input filename, +removing any existing F<.bc> extension, and adding a F<.s> suffix. + +Other B options are as follows: + +=head2 End-user Options + +=over + +=item B<-help> + +Print a summary of command line options. + +=item B<-O>=I + +Generate code at different optimization levels. These correspond to the I<-O0>, +I<-O1>, I<-O2>, I<-O3>, and I<-O4> optimization levels used by B and +B. + +=item B<-mtriple>=I + +Override the target triple specified in the input file with the specified +string. + +=item B<-march>=I + +Specify the architecture for which to generate assembly, overriding the target +encoded in the input file. See the output of B for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. + +=item B<-mcpu>=I + +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +B /dev/null | llc -march=xyz -mcpu=help> + +=item B<-mattr>=I + +Override or control specific attributes of the target, such as whether SIMD +operations are enabled or not. The default set of attributes is set by the +current CPU. For a list of available attributes, use: +B /dev/null | llc -march=xyz -mattr=help> + +=item B<--disable-fp-elim> + +Disable frame pointer elimination optimization. + +=item B<--disable-excess-fp-precision> + +Disable optimizations that may produce excess precision for floating point. +Note that this option can dramatically slow down code on some systems +(e.g. X86). + +=item B<--enable-no-infs-fp-math> + +Enable optimizations that assume no Inf values. + +=item B<--enable-no-nans-fp-math> + +Enable optimizations that assume no NAN values. + +=item B<--enable-unsafe-fp-math> + +Enable optimizations that make unsafe assumptions about IEEE math (e.g. that +addition is associative) or may not work for all input ranges. These +optimizations allow the code generator to make use of some instructions which +would otherwise not be usable (such as fsin on X86). + +=item B<--enable-correct-eh-support> + +Instruct the B pass to insert code for correct exception handling +support. This is expensive and is by default omitted for efficiency. + +=item B<--stats> + +Print statistics recorded by code-generation passes. + +=item B<--time-passes> + +Record the amount of time needed for each pass and print a report to standard +error. + +=item B<--load>=F + +Dynamically load F (a path to a dynamically shared object) that +implements an LLVM target. This will permit the target name to be used with the +B<-march> option so that code can be generated for that target. + +=back + +=head2 Tuning/Configuration Options + +=over + +=item B<--print-machineinstrs> + +Print generated machine code between compilation phases (useful for debugging). + +=item B<--regalloc>=I + +Specify the register allocator to use. The default I is I. +Valid register allocators are: + +=over + +=item I + +Very simple "always spill" register allocator + +=item I + +Local register allocator + +=item I + +Linear scan global register allocator + +=item I + +Iterative scan global register allocator + +=back + +=item B<--spiller>=I + +Specify the spiller to use for register allocators that support it. Currently +this option is used only by the linear scan register allocator. The default +I is I. Valid spillers are: + +=over + +=item I + +Simple spiller + +=item I + +Local spiller + +=back + +=back + +=head2 Intel IA-32-specific Options + +=over + +=item B<--x86-asm-syntax=att|intel> + +Specify whether to emit assembly code in AT&T syntax (the default) or intel +syntax. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error occurs, +it will exit with a non-zero value. + +=head1 SEE ALSO + +L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/lli.pod b/final/docs/CommandGuide/lli.pod new file mode 100644 index 00000000000..52a2721e7d7 --- /dev/null +++ b/final/docs/CommandGuide/lli.pod @@ -0,0 +1,219 @@ +=pod + +=head1 NAME + +lli - directly execute programs from LLVM bitcode + +=head1 SYNOPSIS + +B [I] [I] [I] + +=head1 DESCRIPTION + +B directly executes programs in LLVM bitcode format. It takes a program +in LLVM bitcode format and executes it using a just-in-time compiler, if one is +available for the current architecture, or an interpreter. B takes all of +the same code generator options as L, but they are only effective when +B is using the just-in-time compiler. + +If I is not specified, then B reads the LLVM bitcode for the +program from standard input. + +The optional I specified on the command line are passed to the program as +arguments. + +=head1 GENERAL OPTIONS + +=over + +=item B<-fake-argv0>=I + +Override the C value passed into the executing program. + +=item B<-force-interpreter>=I<{false,true}> + +If set to true, use the interpreter even if a just-in-time compiler is available +for this architecture. Defaults to false. + +=item B<-help> + +Print a summary of command line options. + +=item B<-load>=I + +Causes B to load the plugin (shared object) named I and use +it for optimization. + +=item B<-stats> + +Print statistics from the code-generation passes. This is only meaningful for +the just-in-time compiler, at present. + +=item B<-time-passes> + +Record the amount of time needed for each code-generation pass and print it to +standard error. + +=item B<-version> + +Print out the version of B and exit without doing anything else. + +=back + +=head1 TARGET OPTIONS + +=over + +=item B<-mtriple>=I + +Override the target triple specified in the input bitcode file with the +specified string. This may result in a crash if you pick an +architecture which is not compatible with the current system. + +=item B<-march>=I + +Specify the architecture for which to generate assembly, overriding the target +encoded in the bitcode file. See the output of B for a list of +valid architectures. By default this is inferred from the target triple or +autodetected to the current architecture. + +=item B<-mcpu>=I + +Specify a specific chip in the current architecture to generate code for. +By default this is inferred from the target triple and autodetected to +the current architecture. For a list of available CPUs, use: +B /dev/null | llc -march=xyz -mcpu=help> + +=item B<-mattr>=I + +Override or control specific attributes of the target, such as whether SIMD +operations are enabled or not. The default set of attributes is set by the +current CPU. For a list of available attributes, use: +B /dev/null | llc -march=xyz -mattr=help> + +=back + + +=head1 FLOATING POINT OPTIONS + +=over + +=item B<-disable-excess-fp-precision> + +Disable optimizations that may increase floating point precision. + +=item B<-enable-no-infs-fp-math> + +Enable optimizations that assume no Inf values. + +=item B<-enable-no-nans-fp-math> + +Enable optimizations that assume no NAN values. + +=item B<-enable-unsafe-fp-math> + +Causes B to enable optimizations that may decrease floating point +precision. + +=item B<-soft-float> + +Causes B to generate software floating point library calls instead of +equivalent hardware instructions. + +=back + +=head1 CODE GENERATION OPTIONS + +=over + +=item B<-code-model>=I + +Choose the code model from: + + default: Target default code model + small: Small code model + kernel: Kernel code model + medium: Medium code model + large: Large code model + +=item B<-disable-post-RA-scheduler> + +Disable scheduling after register allocation. + +=item B<-disable-spill-fusing> + +Disable fusing of spill code into instructions. + +=item B<-enable-correct-eh-support> + +Make the -lowerinvoke pass insert expensive, but correct, EH code. + +=item B<-jit-enable-eh> + +Exception handling should be enabled in the just-in-time compiler. + +=item B<-join-liveintervals> + +Coalesce copies (default=true). + +=item B<-nozero-initialized-in-bss> +Don't place zero-initialized symbols into the BSS section. + +=item B<-pre-RA-sched>=I + +Instruction schedulers available (before register allocation): + + =default: Best scheduler for the target + =none: No scheduling: breadth first sequencing + =simple: Simple two pass scheduling: minimize critical path and maximize processor utilization + =simple-noitin: Simple two pass scheduling: Same as simple except using generic latency + =list-burr: Bottom-up register reduction list scheduling + =list-tdrr: Top-down register reduction list scheduling + =list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code + +=item B<-regalloc>=I + +Register allocator to use (default=linearscan) + + =bigblock: Big-block register allocator + =linearscan: linear scan register allocator =local - local register allocator + =simple: simple register allocator + +=item B<-relocation-model>=I + +Choose relocation model from: + + =default: Target default relocation model + =static: Non-relocatable code =pic - Fully relocatable, position independent code + =dynamic-no-pic: Relocatable external references, non-relocatable code + +=item B<-spiller> + +Spiller to use (default=local) + + =simple: simple spiller + =local: local spiller + +=item B<-x86-asm-syntax>=I + +Choose style of code to emit from X86 backend: + + =att: Emit AT&T-style assembly + =intel: Emit Intel-style assembly + +=back + +=head1 EXIT STATUS + +If B fails to load the program, it will exit with an exit code of 1. +Otherwise, it will return the exit code of the program it executes. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/llvm-ar.pod b/final/docs/CommandGuide/llvm-ar.pod new file mode 100644 index 00000000000..63ba43f6f6f --- /dev/null +++ b/final/docs/CommandGuide/llvm-ar.pod @@ -0,0 +1,406 @@ +=pod + +=head1 NAME + +llvm-ar - LLVM archiver + +=head1 SYNOPSIS + +B [-]{dmpqrtx}[Rabfikouz] [relpos] [count] [files...] + + +=head1 DESCRIPTION + +The B command is similar to the common Unix utility, C. It +archives several files together into a single file. The intent for this is +to produce archive libraries by LLVM bitcode that can be linked into an +LLVM program. However, the archive can contain any kind of file. By default, +B generates a symbol table that makes linking faster because +only the symbol table needs to be consulted, not each individual file member +of the archive. + +The B command can be used to I both SVR4 and BSD style archive +files. However, it cannot be used to write them. While the B command +produces files that are I identical to the format used by other C +implementations, it has two significant departures in order to make the +archive appropriate for LLVM. The first departure is that B only +uses BSD4.4 style long path names (stored immediately after the header) and +never contains a string table for long names. The second departure is that the +symbol table is formated for efficient construction of an in-memory data +structure that permits rapid (red-black tree) lookups. Consequently, archives +produced with B usually won't be readable or editable with any +C implementation or useful for linking. Using the C modifier to flatten +file names will make the archive readable by other C implementations +but not for linking because the symbol table format for LLVM is unique. If an +SVR4 or BSD style archive is used with the C (replace) or C (quick +update) operations, the archive will be reconstructed in LLVM format. This +means that the string table will be dropped (in deference to BSD 4.4 long names) +and an LLVM symbol table will be added (by default). The system symbol table +will be retained. + +Here's where B departs from previous C implementations: + +=over + +=item I + +Since B is intended to archive bitcode files, the symbol table +won't make much sense to anything but LLVM. Consequently, the symbol table's +format has been simplified. It consists simply of a sequence of pairs +of a file member index number as an LSB 4byte integer and a null-terminated +string. + +=item I + +Some C implementations (SVR4) use a separate file member to record long +path names (> 15 characters). B takes the BSD 4.4 and Mac OS X +approach which is to simply store the full path name immediately preceding +the data for the file. The path name is null terminated and may contain the +slash (/) character. + +=item I + +B can compress the members of an archive to save space. The +compression used depends on what's available on the platform and what choices +the LLVM Compressor utility makes. It generally favors bzip2 but will select +between "no compression" or bzip2 depending on what makes sense for the +file's content. + +=item I + +Most C implementations do not recurse through directories but simply +ignore directories if they are presented to the program in the F +option. B, however, can recurse through directory structures and +add all the files under a directory, if requested. + +=item I + +When B prints out the verbose table of contents (C option), it +precedes the usual output with a character indicating the basic kind of +content in the file. A blank means the file is a regular file. A 'Z' means +the file is compressed. A 'B' means the file is an LLVM bitcode file. An +'S' means the file is the symbol table. + +=back + +=head1 OPTIONS + +The options to B are compatible with other C implementations. +However, there are a few modifiers (F) that are not found in other +Cs. The options to B specify a single basic operation to +perform on the archive, a variety of modifiers for that operation, the +name of the archive file, and an optional list of file names. These options +are used to determine how B should process the archive file. + +The Operations and Modifiers are explained in the sections below. The minimal +set of options is at least one operator and the name of the archive. Typically +archive files end with a C<.a> suffix, but this is not required. Following +the F comes a list of F that indicate the specific members +of the archive to operate on. If the F option is not specified, it +generally means either "none" or "all" members, depending on the operation. + +=head2 Operations + +=over + +=item d + +Delete files from the archive. No modifiers are applicable to this operation. +The F options specify which members should be removed from the +archive. It is not an error if a specified file does not appear in the archive. +If no F are specified, the archive is not modified. + +=item m[abi] + +Move files from one location in the archive to another. The F, F, and +F modifiers apply to this operation. The F will all be moved +to the location given by the modifiers. If no modifiers are used, the files +will be moved to the end of the archive. If no F are specified, the +archive is not modified. + +=item p[k] + +Print files to the standard output. The F modifier applies to this +operation. This operation simply prints the F indicated to the +standard output. If no F are specified, the entire archive is printed. +Printing bitcode files is ill-advised as they might confuse your terminal +settings. The F

operation is used. This modifier defeats the default and allows the +bitcode members to be printed. + +=item [N] + +This option is ignored by B but provided for compatibility. + +=item [o] + +When extracting files, this option will cause B to preserve the +original modification times of the files it writes. + +=item [P] + +use full path names when matching + +=item [R] + +This modifier instructions the F option to recursively process directories. +Without F, directories are ignored and only those F that refer to +files will be added to the archive. When F is used, any directories specified +with F will be scanned (recursively) to find files to be added to the +archive. Any file whose name begins with a dot will not be added. + +=item [u] + +When replacing existing files in the archive, only replace those files that have +a time stamp than the time stamp of the member in the archive. + +=item [z] + +When inserting or replacing any file in the archive, compress the file first. +This +modifier is safe to use when (previously) compressed bitcode files are added to +the archive; the compressed bitcode files will not be doubly compressed. + +=back + +=head2 Modifiers (generic) + +The modifiers below may be applied to any operation. + +=over + +=item [c] + +For all operations, B will always create the archive if it doesn't +exist. Normally, B will print a warning message indicating that the +archive is being created. Using this modifier turns off that warning. + +=item [s] + +This modifier requests that an archive index (or symbol table) be added to the +archive. This is the default mode of operation. The symbol table will contain +all the externally visible functions and global variables defined by all the +bitcode files in the archive. Using this modifier is more efficient that using +L which also creates the symbol table. + +=item [S] + +This modifier is the opposite of the F modifier. It instructs B to +not build the symbol table. If both F and F are used, the last modifier to +occur in the options will prevail. + +=item [v] + +This modifier instructs B to be verbose about what it is doing. Each +editing operation taken against the archive will produce a line of output saying +what is being done. + +=back + +=head1 STANDARDS + +The B utility is intended to provide a superset of the IEEE Std 1003.2 +(POSIX.2) functionality for C. B can read both SVR4 and BSD4.4 (or +Mac OS X) archives. If the C modifier is given to the C or C operations +then B will write SVR4 compatible archives. Without this modifier, +B will write BSD4.4 compatible archives that have long names +immediately after the header and indicated using the "#1/ddd" notation for the +name in the header. + +=head1 FILE FORMAT + +The file format for LLVM Archive files is similar to that of BSD 4.4 or Mac OSX +archive files. In fact, except for the symbol table, the C commands on those +operating systems should be able to read LLVM archive files. The details of the +file format follow. + +Each archive begins with the archive magic number which is the eight printable +characters "!\n" where \n represents the newline character (0x0A). +Following the magic number, the file is composed of even length members that +begin with an archive header and end with a \n padding character if necessary +(to make the length even). Each file member is composed of a header (defined +below), an optional newline-terminated "long file name" and the contents of +the file. + +The fields of the header are described in the items below. All fields of the +header contain only ASCII characters, are left justified and are right padded +with space characters. + +=over + +=item name - char[16] + +This field of the header provides the name of the archive member. If the name is +longer than 15 characters or contains a slash (/) character, then this field +contains C<#1/nnn> where C provides the length of the name and the C<#1/> +is literal. In this case, the actual name of the file is provided in the C +bytes immediately following the header. If the name is 15 characters or less, it +is contained directly in this field and terminated with a slash (/) character. + +=item date - char[12] + +This field provides the date of modification of the file in the form of a +decimal encoded number that provides the number of seconds since the epoch +(since 00:00:00 Jan 1, 1970) per Posix specifications. + +=item uid - char[6] + +This field provides the user id of the file encoded as a decimal ASCII string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_uid field of the stat structure returned by the stat(2) +operating system call. + +=item gid - char[6] + +This field provides the group id of the file encoded as a decimal ASCII string. +This field might not make much sense on non-Unix systems. On Unix, it is the +same value as the st_gid field of the stat structure returned by the stat(2) +operating system call. + +=item mode - char[8] + +This field provides the access mode of the file encoded as an octal ASCII +string. This field might not make much sense on non-Unix systems. On Unix, it +is the same value as the st_mode field of the stat structure returned by the +stat(2) operating system call. + +=item size - char[10] + +This field provides the size of the file, in bytes, encoded as a decimal ASCII +string. If the size field is negative (starts with a minus sign, 0x02D), then +the archive member is stored in compressed form. The first byte of the archive +member's data indicates the compression type used. A value of 0 (0x30) indicates +that no compression was used. A value of 2 (0x32) indicates that bzip2 +compression was used. + +=item fmag - char[2] + +This field is the archive file member magic number. Its content is always the +two characters back tick (0x60) and newline (0x0A). This provides some measure +utility in identifying archive files that have been corrupted. + +=back + +The LLVM symbol table has the special name "#_LLVM_SYM_TAB_#". It is presumed +that no regular archive member file will want this name. The LLVM symbol table +is simply composed of a sequence of triplets: byte offset, length of symbol, +and the symbol itself. Symbols are not null or newline terminated. Here are +the details on each of these items: + +=over + +=item offset - vbr encoded 32-bit integer + +The offset item provides the offset into the archive file where the bitcode +member is stored that is associated with the symbol. The offset value is 0 +based at the start of the first "normal" file member. To derive the actual +file offset of the member, you must add the number of bytes occupied by the file +signature (8 bytes) and the symbol tables. The value of this item is encoded +using variable bit rate encoding to reduce the size of the symbol table. +Variable bit rate encoding uses the high bit (0x80) of each byte to indicate +if there are more bytes to follow. The remaining 7 bits in each byte carry bits +from the value. The final byte does not have the high bit set. + +=item length - vbr encoded 32-bit integer + +The length item provides the length of the symbol that follows. Like this +I item, the length is variable bit rate encoded. + +=item symbol - character array + +The symbol item provides the text of the symbol that is associated with the +I. The symbol is not terminated by any character. Its length is provided +by the I field. Note that is allowed (but unwise) to use non-printing +characters (even 0x00) in the symbol. This allows for multiple encodings of +symbol names. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. A usage error, results +in an exit code of 1. A hard (file system typically) error results in an +exit code of 2. Miscellaneous or unknown errors result in an +exit code of 3. + +=head1 SEE ALSO + +L, ar(1) + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/llvm-as.pod b/final/docs/CommandGuide/llvm-as.pod new file mode 100644 index 00000000000..185c009698f --- /dev/null +++ b/final/docs/CommandGuide/llvm-as.pod @@ -0,0 +1,77 @@ +=pod + +=head1 NAME + +llvm-as - LLVM assembler + +=head1 SYNOPSIS + +B [I] [I] + +=head1 DESCRIPTION + +B is the LLVM assembler. It reads a file containing human-readable +LLVM assembly language, translates it to LLVM bitcode, and writes the result +into a file or to standard output. + +If F is omitted or is C<->, then B reads its input from +standard input. + +If an output file is not specified with the B<-o> option, then +B sends its output to a file or standard output by following +these rules: + +=over + +=item * + +If the input is standard input, then the output is standard output. + +=item * + +If the input is a file that ends with C<.ll>, then the output file is of +the same name, except that the suffix is changed to C<.bc>. + +=item * + +If the input is a file that does not end with the C<.ll> suffix, then the +output file has the same name as the input file, except that the C<.bc> +suffix is appended. + +=back + +=head1 OPTIONS + +=over + +=item B<-f> + +Enable binary output on terminals. Normally, B will refuse to +write raw bitcode output if the output stream is a terminal. With this option, +B will write raw bitcode regardless of the output device. + +=item B<-help> + +Print a summary of command line options. + +=item B<-o> F + +Specify the output file name. If F is C<->, then B +sends its output to standard output. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value. + +=head1 SEE ALSO + +L, L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/llvm-bcanalyzer.pod b/final/docs/CommandGuide/llvm-bcanalyzer.pod new file mode 100644 index 00000000000..b0bc0cddba8 --- /dev/null +++ b/final/docs/CommandGuide/llvm-bcanalyzer.pod @@ -0,0 +1,315 @@ +=pod + +=head1 NAME + +llvm-bcanalyzer - LLVM bitcode analyzer + +=head1 SYNOPSIS + +B [I] [F] + +=head1 DESCRIPTION + +The B command is a small utility for analyzing bitcode files. +The tool reads a bitcode file (such as generated with the B tool) and +produces a statistical report on the contents of the bitcode file. The tool +can also dump a low level but human readable version of the bitcode file. +This tool is probably not of much interest or utility except for those working +directly with the bitcode file format. Most LLVM users can just ignore +this tool. + +If F is omitted or is C<->, then B reads its input +from standard input. This is useful for combining the tool into a pipeline. +Output is written to the standard output. + +=head1 OPTIONS + +=over + +=item B<-nodetails> + +Causes B to abbreviate its output by writing out only a module +level summary. The details for individual functions are not displayed. + +=item B<-dump> + +Causes B to dump the bitcode in a human readable format. This +format is significantly different from LLVM assembly and provides details about +the encoding of the bitcode file. + +=item B<-verify> + +Causes B to verify the module produced by reading the +bitcode. This ensures that the statistics generated are based on a consistent +module. + +=item B<-help> + +Print a summary of command line options. + +=back + +=head1 EXIT STATUS + +If B succeeds, it will exit with 0. Otherwise, if an error +occurs, it will exit with a non-zero value, usually 1. + +=head1 SUMMARY OUTPUT DEFINITIONS + +The following items are always printed by llvm-bcanalyzer. They comprize the +summary output. + +=over + +=item B + +This just provides the name of the module for which bitcode analysis is being +generated. + +=item B + +The bitcode version (not LLVM version) of the file read by the analyzer. + +=item B + +The size, in bytes, of the entire bitcode file. + +=item B + +The size, in bytes, of the module block. Percentage is relative to File Size. + +=item B + +The size, in bytes, of all the function blocks. Percentage is relative to File +Size. + +=item B + +The size, in bytes, of the Global Types Pool. Percentage is relative to File +Size. This is the size of the definitions of all types in the bitcode file. + +=item B + +The size, in bytes, of the Constant Pool Blocks Percentage is relative to File +Size. + +=item B + +Ths size, in bytes, of the Global Variable Definitions and their initializers. +Percentage is relative to File Size. + +=item B + +The size, in bytes, of all the instruction lists in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. + +=item B + +The size, in bytes, of all the compaction tables in all the functions. +Percentage is relative to File Size. Note that this value is also included in +the Function Bytes. + +=item B + +The size, in bytes, of all the symbol tables in all the functions. Percentage is +relative to File Size. Note that this value is also included in the Function +Bytes. + +=item B + +The size, in bytes, of the list of dependent libraries in the module. Percentage +is relative to File Size. Note that this value is also included in the Module +Global Bytes. + +=item B + +The total number of blocks of any kind in the bitcode file. + +=item B + +The total number of function definitions in the bitcode file. + +=item B + +The total number of types defined in the Global Types Pool. + +=item B + +The total number of constants (of any type) defined in the Constant Pool. + +=item B + +The total number of basic blocks defined in all functions in the bitcode file. + +=item B + +The total number of instructions defined in all functions in the bitcode file. + +=item B + +The total number of long instructions defined in all functions in the bitcode +file. Long instructions are those taking greater than 4 bytes. Typically long +instructions are GetElementPtr with several indices, PHI nodes, and calls to +functions with large numbers of arguments. + +=item B + +The total number of operands used in all instructions in the bitcode file. + +=item B + +The total number of compaction tables in all functions in the bitcode file. + +=item B + +The total number of symbol tables in all functions in the bitcode file. + +=item B + +The total number of dependent libraries found in the bitcode file. + +=item B + +The total size of the instructions in all functions in the bitcode file. + +=item B + +The average number of bytes per instruction across all functions in the bitcode +file. This value is computed by dividing Total Instruction Size by Number Of +Instructions. + +=item B + +The maximum value used for a type's slot number. Larger slot number values take +more bytes to encode. + +=item B + +The maximum value used for a value's slot number. Larger slot number values take +more bytes to encode. + +=item B + +The average size of a Value definition (of any type). This is computed by +dividing File Size by the total number of values of any type. + +=item B + +The average size of a global definition (constants and global variables). + +=item B + +The average number of bytes per function definition. This is computed by +dividing Function Bytes by Number Of Functions. + +=item B<# of VBR 32-bit Integers> + +The total number of 32-bit integers encoded using the Variable Bit Rate +encoding scheme. + +=item B<# of VBR 64-bit Integers> + +The total number of 64-bit integers encoded using the Variable Bit Rate encoding +scheme. + +=item B<# of VBR Compressed Bytes> + +The total number of bytes consumed by the 32-bit and 64-bit integers that use +the Variable Bit Rate encoding scheme. + +=item B<# of VBR Expanded Bytes> + +The total number of bytes that would have been consumed by the 32-bit and 64-bit +integers had they not been compressed with the Variable Bit Rage encoding +scheme. + +=item B + +The total number of bytes saved by using the Variable Bit Rate encoding scheme. +The percentage is relative to # of VBR Expanded Bytes. + +=back + +=head1 DETAILED OUTPUT DEFINITIONS + +The following definitions occur only if the -nodetails option was not given. +The detailed output provides additional information on a per-function basis. + +=over + +=item B + +The type signature of the function. + +=item B + +The total number of bytes in the function's block. + +=item B + +The number of basic blocks defined by the function. + +=item B + +The number of instructions defined by the function. + +=item B + +The number of instructions using the long instruction format in the function. + +=item B + +The number of operands used by all instructions in the function. + +=item B + +The number of bytes consumed by instructions in the function. + +=item B + +The average number of bytes consumed by the instructions in the funtion. This +value is computed by dividing Instruction Size by Instructions. + +=item B + +The average number of bytes used by the function per instruction. This value is +computed by dividing Byte Size by Instructions. Note that this is not the same +as Average Instruction Size. It computes a number relative to the total function +size not just the size of the instruction list. + +=item B + +The total number of 32-bit integers found in this function (for any use). + +=item B + +The total number of 64-bit integers found in this function (for any use). + +=item B + +The total number of bytes in this function consumed by the 32-bit and 64-bit +integers that use the Variable Bit Rate encoding scheme. + +=item B + +The total number of bytes in this function that would have been consumed by +the 32-bit and 64-bit integers had they not been compressed with the Variable +Bit Rate encoding scheme. + +=item B + +The total number of bytes saved in this function by using the Variable Bit +Rate encoding scheme. The percentage is relative to # of VBR Expanded Bytes. + +=back + +=head1 SEE ALSO + +L, L + +=head1 AUTHORS + +Maintained by the LLVM Team (L). + +=cut diff --git a/final/docs/CommandGuide/llvm-config.pod b/final/docs/CommandGuide/llvm-config.pod new file mode 100644 index 00000000000..4e38dae3df6 --- /dev/null +++ b/final/docs/CommandGuide/llvm-config.pod @@ -0,0 +1,131 @@ +=pod + +=head1 NAME + +llvm-config - Print LLVM compilation options + +=head1 SYNOPSIS + +B I

+ +
    +
  1. Introduction
  2. + +
  3. Quick Start Guide +
      +
    1. Boolean Arguments
    2. +
    3. Argument Aliases
    4. +
    5. Selecting an alternative from a + set of possibilities
    6. +
    7. Named alternatives
    8. +
    9. Parsing a list of options
    10. +
    11. Collecting options as a set of flags
    12. +
    13. Adding freeform text to help output
    14. +
  4. + +
  5. Reference Guide +
      +
    1. Positional Arguments +
    2. + +
    3. Internal vs External Storage
    4. + +
    5. Option Attributes
    6. + +
    7. Option Modifiers +
    8. + +
    9. Top-Level Classes and Functions +
    10. + +
    11. Builtin parsers +
    12. +
  6. +
  7. Extension Guide +
      +
    1. Writing a custom parser
    2. +
    3. Exploiting external storage
    4. +
    5. Dynamically adding command line + options
    6. +
  8. +
+ +
+

Written by Chris Lattner

+
+ + + + + +
+ +

This document describes the CommandLine argument processing library. It will +show you how to use it, and what it can do. The CommandLine library uses a +declarative approach to specifying the command line options that your program +takes. By default, these options declarations implicitly hold the value parsed +for the option declared (of course this can be +changed).

+ +

Although there are a lot of command line argument parsing libraries +out there in many different languages, none of them fit well with what I needed. +By looking at the features and problems of other libraries, I designed the +CommandLine library to have the following features:

+ +
    +
  1. Speed: The CommandLine library is very quick and uses little resources. The +parsing time of the library is directly proportional to the number of arguments +parsed, not the the number of options recognized. Additionally, command line +argument values are captured transparently into user defined global variables, +which can be accessed like any other variable (and with the same +performance).
  2. + +
  3. Type Safe: As a user of CommandLine, you don't have to worry about +remembering the type of arguments that you want (is it an int? a string? a +bool? an enum?) and keep casting it around. Not only does this help prevent +error prone constructs, it also leads to dramatically cleaner source code.
  4. + +
  5. No subclasses required: To use CommandLine, you instantiate variables that +correspond to the arguments that you would like to capture, you don't subclass a +parser. This means that you don't have to write any boilerplate +code.
  6. + +
  7. Globally accessible: Libraries can specify command line arguments that are +automatically enabled in any tool that links to the library. This is possible +because the application doesn't have to keep a list of arguments to pass to +the parser. This also makes supporting dynamically +loaded options trivial.
  8. + +
  9. Cleaner: CommandLine supports enum and other types directly, meaning that +there is less error and more security built into the library. You don't have to +worry about whether your integral command line argument accidentally got +assigned a value that is not valid for your enum type.
  10. + +
  11. Powerful: The CommandLine library supports many different types of +arguments, from simple boolean flags to scalars arguments (strings, integers, enums, doubles), to lists of +arguments. This is possible because CommandLine is...
  12. + +
  13. Extensible: It is very simple to add a new argument type to CommandLine. +Simply specify the parser that you want to use with the command line option when +you declare it. Custom parsers are no problem.
  14. + +
  15. Labor Saving: The CommandLine library cuts down on the amount of grunt work +that you, the user, have to do. For example, it automatically provides a +-help option that shows the available command line options for your +tool. Additionally, it does most of the basic correctness checking for +you.
  16. + +
  17. Capable: The CommandLine library can handle lots of different forms of +options often found in real programs. For example, positional arguments, ls style grouping options (to allow processing 'ls +-lad' naturally), ld style prefix +options (to parse '-lmalloc -L/usr/lib'), and interpreter style options.
  18. + +
+ +

This document will hopefully let you jump in and start using CommandLine in +your utility quickly and painlessly. Additionally it should be a simple +reference manual to figure out how stuff works. If it is failing in some area +(or you want an extension to the library), nag the author, Chris Lattner.

+ +
+ + + + + +
+ +

This section of the manual runs through a simple CommandLine'ification of a +basic compiler tool. This is intended to show you how to jump into using the +CommandLine library in your own program, and show you some of the cool things it +can do.

+ +

To start out, you need to include the CommandLine header file into your +program:

+ +
+  #include "llvm/Support/CommandLine.h"
+
+ +

Additionally, you need to add this as the first line of your main +program:

+ +
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv);
+  ...
+}
+
+ +

... which actually parses the arguments and fills in the variable +declarations.

+ +

Now that you are ready to support command line arguments, we need to tell the +system which ones we want, and what type of arguments they are. The CommandLine +library uses a declarative syntax to model command line arguments with the +global variable declarations that capture the parsed values. This means that +for every command line option that you would like to support, there should be a +global variable declaration to capture the result. For example, in a compiler, +we would like to support the Unix-standard '-o <filename>' option +to specify where to put the output. With the CommandLine library, this is +represented like this:

+ + +
+cl::opt<string> OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename"));
+
+ +

This declares a global variable "OutputFilename" that is used to +capture the result of the "o" argument (first parameter). We specify +that this is a simple scalar option by using the "cl::opt" template (as opposed to the "cl::list template), and tell the CommandLine library +that the data type that we are parsing is a string.

+ +

The second and third parameters (which are optional) are used to specify what +to output for the "-help" option. In this case, we get a line that +looks like this:

+ +
+USAGE: compiler [options]
+
+OPTIONS:
+  -help             - display available options (-help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +

Because we specified that the command line option should parse using the +string data type, the variable declared is automatically usable as a +real string in all contexts that a normal C++ string object may be used. For +example:

+ +
+  ...
+  std::ofstream Output(OutputFilename.c_str());
+  if (Output.good()) ...
+  ...
+
+ +

There are many different options that you can use to customize the command +line option handling library, but the above example shows the general interface +to these options. The options can be specified in any order, and are specified +with helper functions like cl::desc(...), so +there are no positional dependencies to remember. The available options are +discussed in detail in the Reference Guide.

+ +

Continuing the example, we would like to have our compiler take an input +filename as well as an output filename, but we do not want the input filename to +be specified with a hyphen (ie, not -filename.c). To support this +style of argument, the CommandLine library allows for positional arguments to be specified for the program. +These positional arguments are filled with command line parameters that are not +in option form. We use this feature like this:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ +

This declaration indicates that the first positional argument should be +treated as the input filename. Here we use the cl::init option to specify an initial value for the +command line option, which is used if the option is not specified (if you do not +specify a cl::init modifier for an option, then +the default constructor for the data type is used to initialize the value). +Command line options default to being optional, so if we would like to require +that the user always specify an input filename, we would add the cl::Required flag, and we could eliminate the +cl::init modifier, like this:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::Required);
+
+ +

Again, the CommandLine library does not require the options to be specified +in any particular order, so the above declaration is equivalent to:

+ +
+cl::opt<string> InputFilename(cl::Positional, cl::Required, cl::desc("<input file>"));
+
+ +

By simply adding the cl::Required flag, +the CommandLine library will automatically issue an error if the argument is not +specified, which shifts all of the command line option verification code out of +your application into the library. This is just one example of how using flags +can alter the default behaviour of the library, on a per-option basis. By +adding one of the declarations above, the -help option synopsis is now +extended to:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -help             - display available options (-help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +

... indicating that an input filename is expected.

+ +
+ + + + +
+ +

In addition to input and output filenames, we would like the compiler example +to support three boolean flags: "-f" to force writing binary output to +a terminal, "--quiet" to enable quiet mode, and "-q" for +backwards compatibility with some of our users. We can support these by +declaring options of boolean type like this:

+ +
+cl::opt<bool> Force ("f", cl::desc("Enable binary output on terminals"));
+cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages"));
+cl::opt<bool> Quiet2("q", cl::desc("Don't print informational messages"), cl::Hidden);
+
+ +

This does what you would expect: it declares three boolean variables +("Force", "Quiet", and "Quiet2") to recognize these +options. Note that the "-q" option is specified with the "cl::Hidden" flag. This modifier prevents it +from being shown by the standard "-help" output (note that it is still +shown in the "-help-hidden" output).

+ +

The CommandLine library uses a different parser +for different data types. For example, in the string case, the argument passed +to the option is copied literally into the content of the string variable... we +obviously cannot do that in the boolean case, however, so we must use a smarter +parser. In the case of the boolean parser, it allows no options (in which case +it assigns the value of true to the variable), or it allows the values +"true" or "false" to be specified, allowing any of the +following inputs:

+ +
+ compiler -f          # No value, 'Force' == true
+ compiler -f=true     # Value specified, 'Force' == true
+ compiler -f=TRUE     # Value specified, 'Force' == true
+ compiler -f=FALSE    # Value specified, 'Force' == false
+
+ +

... you get the idea. The bool parser just turns +the string values into boolean values, and rejects things like 'compiler +-f=foo'. Similarly, the float, double, and int parsers work +like you would expect, using the 'strtol' and 'strtod' C +library calls to parse the string value into the specified data type.

+ +

With the declarations above, "compiler -help" emits this:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -f     - Enable binary output on terminals
+  -o     - Override output filename
+  -quiet - Don't print informational messages
+  -help  - display available options (-help-hidden for more)
+
+ +

and "compiler -help-hidden" prints this:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  -f     - Enable binary output on terminals
+  -o     - Override output filename
+  -q     - Don't print informational messages
+  -quiet - Don't print informational messages
+  -help  - display available options (-help-hidden for more)
+
+ +

This brief example has shown you how to use the 'cl::opt' class to parse simple scalar command line +arguments. In addition to simple scalar arguments, the CommandLine library also +provides primitives to support CommandLine option aliases, +and lists of options.

+ +
+ + + + +
+ +

So far, the example works well, except for the fact that we need to check the +quiet condition like this now:

+ +
+...
+  if (!Quiet && !Quiet2) printInformationalMessage(...);
+...
+
+ +

... which is a real pain! Instead of defining two values for the same +condition, we can use the "cl::alias" class to make the "-q" +option an alias for the "-quiet" option, instead of providing +a value itself:

+ +
+cl::opt<bool> Force ("f", cl::desc("Overwrite output files"));
+cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages"));
+cl::alias     QuietA("q", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet));
+
+ +

The third line (which is the only one we modified from above) defines a +"-q" alias that updates the "Quiet" variable (as specified by +the cl::aliasopt modifier) whenever it is +specified. Because aliases do not hold state, the only thing the program has to +query is the Quiet variable now. Another nice feature of aliases is +that they automatically hide themselves from the -help output +(although, again, they are still visible in the -help-hidden +output).

+ +

Now the application code can simply use:

+ +
+...
+  if (!Quiet) printInformationalMessage(...);
+...
+
+ +

... which is much nicer! The "cl::alias" +can be used to specify an alternative name for any variable type, and has many +uses.

+ +
+ + + + +
+ +

So far we have seen how the CommandLine library handles builtin types like +std::string, bool and int, but how does it handle +things it doesn't know about, like enums or 'int*'s?

+ +

The answer is that it uses a table-driven generic parser (unless you specify +your own parser, as described in the Extension +Guide). This parser maps literal strings to whatever type is required, and +requires you to tell it what this mapping should be.

+ +

Let's say that we would like to add four optimization levels to our +optimizer, using the standard flags "-g", "-O0", +"-O1", and "-O2". We could easily implement this with boolean +options like above, but there are several problems with this strategy:

+ +
    +
  1. A user could specify more than one of the options at a time, for example, +"compiler -O3 -O2". The CommandLine library would not be able to +catch this erroneous input for us.
  2. + +
  3. We would have to test 4 different variables to see which ones are set.
  4. + +
  5. This doesn't map to the numeric levels that we want... so we cannot easily +see if some level >= "-O1" is enabled.
  6. + +
+ +

To cope with these problems, we can use an enum value, and have the +CommandLine library fill it in with the appropriate level directly, which is +used like this:

+ +
+enum OptLevel {
+  g, O1, O2, O3
+};
+
+cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
+  cl::values(
+    clEnumVal(g , "No optimizations, enable debugging"),
+    clEnumVal(O1, "Enable trivial optimizations"),
+    clEnumVal(O2, "Enable default optimizations"),
+    clEnumVal(O3, "Enable expensive optimizations"),
+   clEnumValEnd));
+
+...
+  if (OptimizationLevel >= O2) doPartialRedundancyElimination(...);
+...
+
+ +

This declaration defines a variable "OptimizationLevel" of the +"OptLevel" enum type. This variable can be assigned any of the values +that are listed in the declaration (Note that the declaration list must be +terminated with the "clEnumValEnd" argument!). The CommandLine +library enforces +that the user can only specify one of the options, and it ensure that only valid +enum values can be specified. The "clEnumVal" macros ensure that the +command line arguments matched the enum values. With this option added, our +help output now is:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  Choose optimization level:
+    -g          - No optimizations, enable debugging
+    -O1         - Enable trivial optimizations
+    -O2         - Enable default optimizations
+    -O3         - Enable expensive optimizations
+  -f            - Enable binary output on terminals
+  -help         - display available options (-help-hidden for more)
+  -o <filename> - Specify output filename
+  -quiet        - Don't print informational messages
+
+ +

In this case, it is sort of awkward that flag names correspond directly to +enum names, because we probably don't want a enum definition named "g" +in our program. Because of this, we can alternatively write this example like +this:

+ +
+enum OptLevel {
+  Debug, O1, O2, O3
+};
+
+cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"),
+  cl::values(
+   clEnumValN(Debug, "g", "No optimizations, enable debugging"),
+    clEnumVal(O1        , "Enable trivial optimizations"),
+    clEnumVal(O2        , "Enable default optimizations"),
+    clEnumVal(O3        , "Enable expensive optimizations"),
+   clEnumValEnd));
+
+...
+  if (OptimizationLevel == Debug) outputDebugInfo(...);
+...
+
+ +

By using the "clEnumValN" macro instead of "clEnumVal", we +can directly specify the name that the flag should get. In general a direct +mapping is nice, but sometimes you can't or don't want to preserve the mapping, +which is when you would use it.

+ +
+ + + + +
+ +

Another useful argument form is a named alternative style. We shall use this +style in our compiler to specify different debug levels that can be used. +Instead of each debug level being its own switch, we want to support the +following options, of which only one can be specified at a time: +"--debug-level=none", "--debug-level=quick", +"--debug-level=detailed". To do this, we use the exact same format as +our optimization level flags, but we also specify an option name. For this +case, the code looks like this:

+ +
+enum DebugLev {
+  nodebuginfo, quick, detailed
+};
+
+// Enable Debug Options to be specified on the command line
+cl::opt<DebugLev> DebugLevel("debug_level", cl::desc("Set the debugging level:"),
+  cl::values(
+    clEnumValN(nodebuginfo, "none", "disable debug information"),
+     clEnumVal(quick,               "enable quick debug information"),
+     clEnumVal(detailed,            "enable detailed debug information"),
+    clEnumValEnd));
+
+ +

This definition defines an enumerated command line variable of type "enum +DebugLev", which works exactly the same way as before. The difference here +is just the interface exposed to the user of your program and the help output by +the "-help" option:

+ +
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  Choose optimization level:
+    -g          - No optimizations, enable debugging
+    -O1         - Enable trivial optimizations
+    -O2         - Enable default optimizations
+    -O3         - Enable expensive optimizations
+  -debug_level  - Set the debugging level:
+    =none       - disable debug information
+    =quick      - enable quick debug information
+    =detailed   - enable detailed debug information
+  -f            - Enable binary output on terminals
+  -help         - display available options (-help-hidden for more)
+  -o <filename> - Specify output filename
+  -quiet        - Don't print informational messages
+
+ +

Again, the only structural difference between the debug level declaration and +the optimization level declaration is that the debug level declaration includes +an option name ("debug_level"), which automatically changes how the +library processes the argument. The CommandLine library supports both forms so +that you can choose the form most appropriate for your application.

+ +
+ + + + +
+ +

Now that we have the standard run-of-the-mill argument types out of the way, +lets get a little wild and crazy. Lets say that we want our optimizer to accept +a list of optimizations to perform, allowing duplicates. For example, we +might want to run: "compiler -dce -constprop -inline -dce -strip". In +this case, the order of the arguments and the number of appearances is very +important. This is what the "cl::list" +template is for. First, start by defining an enum of the optimizations that you +would like to perform:

+ +
+enum Opts {
+  // 'inline' is a C++ keyword, so name it 'inlining'
+  dce, constprop, inlining, strip
+};
+
+ +

Then define your "cl::list" variable:

+ +
+cl::list<Opts> OptimizationList(cl::desc("Available Optimizations:"),
+  cl::values(
+    clEnumVal(dce               , "Dead Code Elimination"),
+    clEnumVal(constprop         , "Constant Propagation"),
+   clEnumValN(inlining, "inline", "Procedure Integration"),
+    clEnumVal(strip             , "Strip Symbols"),
+  clEnumValEnd));
+
+ +

This defines a variable that is conceptually of the type +"std::vector<enum Opts>". Thus, you can access it with standard +vector methods:

+ +
+  for (unsigned i = 0; i != OptimizationList.size(); ++i)
+    switch (OptimizationList[i])
+       ...
+
+ +

... to iterate through the list of options specified.

+ +

Note that the "cl::list" template is +completely general and may be used with any data types or other arguments that +you can use with the "cl::opt" template. One +especially useful way to use a list is to capture all of the positional +arguments together if there may be more than one specified. In the case of a +linker, for example, the linker takes several '.o' files, and needs to +capture them into a list. This is naturally specified as:

+ +
+...
+cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore);
+...
+
+ +

This variable works just like a "vector<string>" object. As +such, accessing the list is simple, just like above. In this example, we used +the cl::OneOrMore modifier to inform the +CommandLine library that it is an error if the user does not specify any +.o files on our command line. Again, this just reduces the amount of +checking we have to do.

+ +
+ + + + +
+ +

Instead of collecting sets of options in a list, it is also possible to +gather information for enum values in a bit vector. The representation used by +the cl::bits class is an unsigned +integer. An enum value is represented by a 0/1 in the enum's ordinal value bit +position. 1 indicating that the enum was specified, 0 otherwise. As each +specified value is parsed, the resulting enum's bit is set in the option's bit +vector:

+ +
+  bits |= 1 << (unsigned)enum;
+
+ +

Options that are specified multiple times are redundant. Any instances after +the first are discarded.

+ +

Reworking the above list example, we could replace +cl::list with cl::bits:

+ +
+cl::bits<Opts> OptimizationBits(cl::desc("Available Optimizations:"),
+  cl::values(
+    clEnumVal(dce               , "Dead Code Elimination"),
+    clEnumVal(constprop         , "Constant Propagation"),
+   clEnumValN(inlining, "inline", "Procedure Integration"),
+    clEnumVal(strip             , "Strip Symbols"),
+  clEnumValEnd));
+
+ +

To test to see if constprop was specified, we can use the +cl:bits::isSet function:

+ +
+  if (OptimizationBits.isSet(constprop)) {
+    ...
+  }
+
+ +

It's also possible to get the raw bit vector using the +cl::bits::getBits function:

+ +
+  unsigned bits = OptimizationBits.getBits();
+
+ +

Finally, if external storage is used, then the location specified must be of +type unsigned. In all other ways a cl::bits option is equivalent to a cl::list option.

+ +
+ + + + + +
+ +

As our program grows and becomes more mature, we may decide to put summary +information about what it does into the help output. The help output is styled +to look similar to a Unix man page, providing concise information about +a program. Unix man pages, however often have a description about what +the program does. To add this to your CommandLine program, simply pass a third +argument to the cl::ParseCommandLineOptions +call in main. This additional argument is then printed as the overview +information for your program, allowing you to include any additional information +that you want. For example:

+ +
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv, " CommandLine compiler example\n\n"
+                              "  This program blah blah blah...\n");
+  ...
+}
+
+ +

would yield the help output:

+ +
+OVERVIEW: CommandLine compiler example
+
+  This program blah blah blah...
+
+USAGE: compiler [options] <input file>
+
+OPTIONS:
+  ...
+  -help             - display available options (-help-hidden for more)
+  -o <filename>     - Specify output filename
+
+ +
+ + + + + + +
+ +

Now that you know the basics of how to use the CommandLine library, this +section will give you the detailed information you need to tune how command line +options work, as well as information on more "advanced" command line option +processing capabilities.

+ +
+ + + + +
+ +

Positional arguments are those arguments that are not named, and are not +specified with a hyphen. Positional arguments should be used when an option is +specified by its position alone. For example, the standard Unix grep +tool takes a regular expression argument, and an optional filename to search +through (which defaults to standard input if a filename is not specified). +Using the CommandLine library, this would be specified as:

+ +
+cl::opt<string> Regex   (cl::Positional, cl::desc("<regular expression>"), cl::Required);
+cl::opt<string> Filename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+
+ +

Given these two option declarations, the -help output for our grep +replacement would look like this:

+ +
+USAGE: spiffygrep [options] <regular expression> <input file>
+
+OPTIONS:
+  -help - display available options (-help-hidden for more)
+
+ +

... and the resultant program could be used just like the standard +grep tool.

+ +

Positional arguments are sorted by their order of construction. This means +that command line options will be ordered according to how they are listed in a +.cpp file, but will not have an ordering defined if the positional arguments +are defined in multiple .cpp files. The fix for this problem is simply to +define all of your positional arguments in one .cpp file.

+ +
+ + + + + +
+ +

Sometimes you may want to specify a value to your positional argument that +starts with a hyphen (for example, searching for '-foo' in a file). At +first, you will have trouble doing this, because it will try to find an argument +named '-foo', and will fail (and single quotes will not save you). +Note that the system grep has the same problem:

+ +
+  $ spiffygrep '-foo' test.txt
+  Unknown command line argument '-foo'.  Try: spiffygrep -help'
+
+  $ grep '-foo' test.txt
+  grep: illegal option -- f
+  grep: illegal option -- o
+  grep: illegal option -- o
+  Usage: grep -hblcnsviw pattern file . . .
+
+ +

The solution for this problem is the same for both your tool and the system +version: use the '--' marker. When the user specifies '--' on +the command line, it is telling the program that all options after the +'--' should be treated as positional arguments, not options. Thus, we +can use it like this:

+ +
+  $ spiffygrep -- -foo test.txt
+    ...output...
+
+ +
+ + + +
+

Sometimes an option can affect or modify the meaning of another option. For + example, consider gcc's -x LANG option. This tells + gcc to ignore the suffix of subsequent positional arguments and force + the file to be interpreted as if it contained source code in language + LANG. In order to handle this properly, you need to know the + absolute position of each argument, especially those in lists, so their + interaction(s) can be applied correctly. This is also useful for options like + -llibname which is actually a positional argument that starts with + a dash.

+

So, generally, the problem is that you have two cl::list variables + that interact in some way. To ensure the correct interaction, you can use the + cl::list::getPosition(optnum) method. This method returns the + absolute position (as found on the command line) of the optnum + item in the cl::list.

+

The idiom for usage is like this:

+ +
+  static cl::list<std::string> Files(cl::Positional, cl::OneOrMore);
+  static cl::list<std::string> Libraries("l", cl::ZeroOrMore);
+
+  int main(int argc, char**argv) {
+    // ...
+    std::vector<std::string>::iterator fileIt = Files.begin();
+    std::vector<std::string>::iterator libIt  = Libraries.begin();
+    unsigned libPos = 0, filePos = 0;
+    while ( 1 ) {
+      if ( libIt != Libraries.end() )
+        libPos = Libraries.getPosition( libIt - Libraries.begin() );
+      else
+        libPos = 0;
+      if ( fileIt != Files.end() )
+        filePos = Files.getPosition( fileIt - Files.begin() );
+      else
+        filePos = 0;
+
+      if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
+        // Source File Is next
+        ++fileIt;
+      }
+      else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
+        // Library is next
+        ++libIt;
+      }
+      else
+        break; // we're done with the list
+    }
+  }
+ +

Note that, for compatibility reasons, the cl::opt also supports an + unsigned getPosition() option that will provide the absolute position + of that option. You can apply the same approach as above with a + cl::opt and a cl::list option as you can with two lists.

+
+ + + + +
+ +

The cl::ConsumeAfter formatting option is +used to construct programs that use "interpreter style" option processing. With +this style of option processing, all arguments specified after the last +positional argument are treated as special interpreter arguments that are not +interpreted by the command line argument.

+ +

As a concrete example, lets say we are developing a replacement for the +standard Unix Bourne shell (/bin/sh). To run /bin/sh, first +you specify options to the shell itself (like -x which turns on trace +output), then you specify the name of the script to run, then you specify +arguments to the script. These arguments to the script are parsed by the Bourne +shell command line option processor, but are not interpreted as options to the +shell itself. Using the CommandLine library, we would specify this as:

+ +
+cl::opt<string> Script(cl::Positional, cl::desc("<input script>"), cl::init("-"));
+cl::list<string>  Argv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
+cl::opt<bool>    Trace("x", cl::desc("Enable trace output"));
+
+ +

which automatically provides the help output:

+ +
+USAGE: spiffysh [options] <input script> <program arguments>...
+
+OPTIONS:
+  -help - display available options (-help-hidden for more)
+  -x    - Enable trace output
+
+ +

At runtime, if we run our new shell replacement as `spiffysh -x test.sh +-a -x -y bar', the Trace variable will be set to true, the +Script variable will be set to "test.sh", and the +Argv list will contain ["-a", "-x", "-y", "bar"], because they +were specified after the last positional argument (which is the script +name).

+ +

There are several limitations to when cl::ConsumeAfter options can +be specified. For example, only one cl::ConsumeAfter can be specified +per program, there must be at least one positional +argument specified, there must not be any cl::list +positional arguments, and the cl::ConsumeAfter option should be a cl::list option.

+ +
+ + + + +
+ +

By default, all command line options automatically hold the value that they +parse from the command line. This is very convenient in the common case, +especially when combined with the ability to define command line options in the +files that use them. This is called the internal storage model.

+ +

Sometimes, however, it is nice to separate the command line option processing +code from the storage of the value parsed. For example, lets say that we have a +'-debug' option that we would like to use to enable debug information +across the entire body of our program. In this case, the boolean value +controlling the debug code should be globally accessible (in a header file, for +example) yet the command line option processing code should not be exposed to +all of these clients (requiring lots of .cpp files to #include +CommandLine.h).

+ +

To do this, set up your .h file with your option, like this for example:

+ +
+
+// DebugFlag.h - Get access to the '-debug' command line option
+//
+
+// DebugFlag - This boolean is set to true if the '-debug' command line option
+// is specified.  This should probably not be referenced directly, instead, use
+// the DEBUG macro below.
+//
+extern bool DebugFlag;
+
+// DEBUG macro - This macro should be used by code to emit debug information.
+// In the '-debug' option is specified on the command line, and if this is a
+// debug build, then the code specified as the option to the macro will be
+// executed.  Otherwise it will not be.
+#ifdef NDEBUG
+#define DEBUG(X)
+#else
+#define DEBUG(X) do { if (DebugFlag) { X; } } while (0)
+#endif
+
+
+ +

This allows clients to blissfully use the DEBUG() macro, or the +DebugFlag explicitly if they want to. Now we just need to be able to +set the DebugFlag boolean when the option is set. To do this, we pass +an additional argument to our command line argument processor, and we specify +where to fill in with the cl::location +attribute:

+ +
+
+bool DebugFlag;                  // the actual value
+static cl::opt<bool, true>       // The parser
+Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag));
+
+
+ +

In the above example, we specify "true" as the second argument to +the cl::opt template, indicating that the +template should not maintain a copy of the value itself. In addition to this, +we specify the cl::location attribute, so +that DebugFlag is automatically set.

+ +
+ + + + +
+ +

This section describes the basic attributes that you can specify on +options.

+ +
    + +
  • The option name attribute (which is required for all options, except positional options) specifies what the option name is. +This option is specified in simple double quotes: + +
    +cl::opt<bool> Quiet("quiet");
    +
    + +
  • + +
  • The cl::desc attribute specifies a +description for the option to be shown in the -help output for the +program.
  • + +
  • The cl::value_desc attribute +specifies a string that can be used to fine tune the -help output for +a command line option. Look here for an +example.
  • + +
  • The cl::init attribute specifies an +initial value for a scalar option. If this attribute is +not specified then the command line option value defaults to the value created +by the default constructor for the type. Warning: If you specify both +cl::init and cl::location for an option, +you must specify cl::location first, so that when the +command-line parser sees cl::init, it knows where to put the +initial value. (You will get an error at runtime if you don't put them in +the right order.)
  • + +
  • The cl::location attribute where +to store the value for a parsed command line option if using external storage. +See the section on Internal vs External Storage for more +information.
  • + +
  • The cl::aliasopt attribute +specifies which option a cl::alias option is +an alias for.
  • + +
  • The cl::values attribute specifies +the string-to-value mapping to be used by the generic parser. It takes a +clEnumValEnd terminated list of (option, value, description) triplets +that +specify the option name, the value mapped to, and the description shown in the +-help for the tool. Because the generic parser is used most +frequently with enum values, two macros are often useful: + +
      + +
    1. The clEnumVal macro is used as a +nice simple way to specify a triplet for an enum. This macro automatically +makes the option name be the same as the enum name. The first option to the +macro is the enum, the second is the description for the command line +option.
    2. + +
    3. The clEnumValN macro is used to +specify macro options where the option name doesn't equal the enum name. For +this macro, the first argument is the enum value, the second is the flag name, +and the second is the description.
    4. + +
    + +You will get a compile time error if you try to use cl::values with a parser +that does not support it.
  • + +
  • The cl::multi_val +attribute specifies that this option takes has multiple values +(example: -sectalign segname sectname sectvalue). This +attribute takes one unsigned argument - the number of values for the +option. This attribute is valid only on cl::list options (and +will fail with compile error if you try to use it with other option +types). It is allowed to use all of the usual modifiers on +multi-valued options (besides cl::ValueDisallowed, +obviously).
  • + +
+ +
+ + + + +
+ +

Option modifiers are the flags and expressions that you pass into the +constructors for cl::opt and cl::list. These modifiers give you the ability to +tweak how options are parsed and how -help output is generated to fit +your application well.

+ +

These options fall into five main categories:

+ +
    +
  1. Hiding an option from -help output
  2. +
  3. Controlling the number of occurrences + required and allowed
  4. +
  5. Controlling whether or not a value must be + specified
  6. +
  7. Controlling other formatting options
  8. +
  9. Miscellaneous option modifiers
  10. +
+ +

It is not possible to specify two options from the same category (you'll get +a runtime error) to a single option, except for options in the miscellaneous +category. The CommandLine library specifies defaults for all of these settings +that are the most useful in practice and the most common, which mean that you +usually shouldn't have to worry about these.

+ +
+ + + + +
+ +

The cl::NotHidden, cl::Hidden, and +cl::ReallyHidden modifiers are used to control whether or not an option +appears in the -help and -help-hidden output for the +compiled program:

+ +
    + +
  • The cl::NotHidden modifier +(which is the default for cl::opt and cl::list options) indicates the option is to appear +in both help listings.
  • + +
  • The cl::Hidden modifier (which is the +default for cl::alias options) indicates that +the option should not appear in the -help output, but should appear in +the -help-hidden output.
  • + +
  • The cl::ReallyHidden modifier +indicates that the option should not appear in any help output.
  • + +
+ +
+ + + + +
+ +

This group of options is used to control how many time an option is allowed +(or required) to be specified on the command line of your program. Specifying a +value for this setting allows the CommandLine library to do error checking for +you.

+ +

The allowed values for this option group are:

+ +
    + +
  • The cl::Optional modifier (which +is the default for the cl::opt and cl::alias classes) indicates that your program will +allow either zero or one occurrence of the option to be specified.
  • + +
  • The cl::ZeroOrMore modifier +(which is the default for the cl::list class) +indicates that your program will allow the option to be specified zero or more +times.
  • + +
  • The cl::Required modifier +indicates that the specified option must be specified exactly one time.
  • + +
  • The cl::OneOrMore modifier +indicates that the option must be specified at least one time.
  • + +
  • The cl::ConsumeAfter modifier is described in the Positional arguments section.
  • + +
+ +

If an option is not specified, then the value of the option is equal to the +value specified by the cl::init attribute. If +the cl::init attribute is not specified, the +option value is initialized with the default constructor for the data type.

+ +

If an option is specified multiple times for an option of the cl::opt class, only the last value will be +retained.

+ +
+ + + + +
+ +

This group of options is used to control whether or not the option allows a +value to be present. In the case of the CommandLine library, a value is either +specified with an equal sign (e.g. '-index-depth=17') or as a trailing +string (e.g. '-o a.out').

+ +

The allowed values for this option group are:

+ +
    + +
  • The cl::ValueOptional modifier +(which is the default for bool typed options) specifies that it is +acceptable to have a value, or not. A boolean argument can be enabled just by +appearing on the command line, or it can have an explicit '-foo=true'. +If an option is specified with this mode, it is illegal for the value to be +provided without the equal sign. Therefore '-foo true' is illegal. To +get this behavior, you must use the cl::ValueRequired modifier.
  • + +
  • The cl::ValueRequired modifier +(which is the default for all other types except for unnamed alternatives using the generic parser) +specifies that a value must be provided. This mode informs the command line +library that if an option is not provides with an equal sign, that the next +argument provided must be the value. This allows things like '-o +a.out' to work.
  • + +
  • The cl::ValueDisallowed +modifier (which is the default for unnamed +alternatives using the generic parser) indicates that it is a runtime error +for the user to specify a value. This can be provided to disallow users from +providing options to boolean options (like '-foo=true').
  • + +
+ +

In general, the default values for this option group work just like you would +want them to. As mentioned above, you can specify the cl::ValueDisallowed modifier to a boolean +argument to restrict your command line parser. These options are mostly useful +when extending the library.

+ +
+ + + + +
+ +

The formatting option group is used to specify that the command line option +has special abilities and is otherwise different from other command line +arguments. As usual, you can only specify one of these arguments at most.

+ +
    + +
  • The cl::NormalFormatting +modifier (which is the default all options) specifies that this option is +"normal".
  • + +
  • The cl::Positional modifier +specifies that this is a positional argument that does not have a command line +option associated with it. See the Positional +Arguments section for more information.
  • + +
  • The cl::ConsumeAfter modifier +specifies that this option is used to capture "interpreter style" arguments. See this section for more information.
  • + +
  • The cl::Prefix modifier specifies +that this option prefixes its value. With 'Prefix' options, the equal sign does +not separate the value from the option name specified. Instead, the value is +everything after the prefix, including any equal sign if present. This is useful +for processing odd arguments like -lmalloc and -L/usr/lib in a +linker tool or -DNAME=value in a compiler tool. Here, the +'l', 'D' and 'L' options are normal string (or list) +options, that have the cl::Prefix +modifier added to allow the CommandLine library to recognize them. Note that +cl::Prefix options must not have the +cl::ValueDisallowed modifier +specified.
  • + +
  • The cl::Grouping modifier is used +to implement Unix-style tools (like ls) that have lots of single letter +arguments, but only require a single dash. For example, the 'ls -labF' +command actually enables four different options, all of which are single +letters. Note that cl::Grouping +options cannot have values.
  • + +
+ +

The CommandLine library does not restrict how you use the cl::Prefix or cl::Grouping modifiers, but it is possible to +specify ambiguous argument settings. Thus, it is possible to have multiple +letter options that are prefix or grouping options, and they will still work as +designed.

+ +

To do this, the CommandLine library uses a greedy algorithm to parse the +input option into (potentially multiple) prefix and grouping options. The +strategy basically looks like this:

+ +
parse(string OrigInput) { + +
    +
  1. string input = OrigInput; +
  2. if (isOption(input)) return getOption(input).parse();    // Normal option +
  3. while (!isOption(input) && !input.empty()) input.pop_back();    // Remove the last letter +
  4. if (input.empty()) return error();    // No matching option +
  5. if (getOption(input).isPrefix())
    +  return getOption(input).parse(input);
    +
  6. while (!input.empty()) {    // Must be grouping options
    +  getOption(input).parse();
    +  OrigInput.erase(OrigInput.begin(), OrigInput.begin()+input.length());
    +  input = OrigInput;
    +  while (!isOption(input) && !input.empty()) input.pop_back();
    +}
    +
  7. if (!OrigInput.empty()) error();
  8. +
+ +

}

+
+ +
+ + + + +
+ +

The miscellaneous option modifiers are the only flags where you can specify +more than one flag from the set: they are not mutually exclusive. These flags +specify boolean properties that modify the option.

+ +
    + +
  • The cl::CommaSeparated modifier +indicates that any commas specified for an option's value should be used to +split the value up into multiple values for the option. For example, these two +options are equivalent when cl::CommaSeparated is specified: +"-foo=a -foo=b -foo=c" and "-foo=a,b,c". This option only +makes sense to be used in a case where the option is allowed to accept one or +more values (i.e. it is a cl::list option).
  • + +
  • The +cl::PositionalEatsArgs modifier (which only applies to +positional arguments, and only makes sense for lists) indicates that positional +argument should consume any strings after it (including strings that start with +a "-") up until another recognized positional argument. For example, if you +have two "eating" positional arguments, "pos1" and "pos2", the +string "-pos1 -foo -bar baz -pos2 -bork" would cause the "-foo -bar +-baz" strings to be applied to the "-pos1" option and the +"-bork" string to be applied to the "-pos2" option.
  • + +
  • The cl::Sink modifier is +used to handle unknown options. If there is at least one option with +cl::Sink modifier specified, the parser passes +unrecognized option strings to it as values instead of signaling an +error. As with cl::CommaSeparated, this modifier +only makes sense with a cl::list option.
  • + +
+ +

So far, these are the only three miscellaneous option modifiers.

+ +
+ + + + +
+ +

Some systems, such as certain variants of Microsoft Windows and +some older Unices have a relatively low limit on command-line +length. It is therefore customary to use the so-called 'response +files' to circumvent this restriction. These files are mentioned on +the command-line (using the "@file") syntax. The program reads these +files and inserts the contents into argv, thereby working around the +command-line length limits. Response files are enabled by an optional +fourth argument to +cl::ParseEnvironmentOptions +and +cl::ParseCommandLineOptions. +

+ +
+ + + + + +
+ +

Despite all of the built-in flexibility, the CommandLine option library +really only consists of one function (cl::ParseCommandLineOptions) +and three main classes: cl::opt, cl::list, and cl::alias. This section describes these three +classes in detail.

+ +
+ + + + +
+ +

The cl::ParseCommandLineOptions function is designed to be called +directly from main, and is used to fill in the values of all of the +command line option variables once argc and argv are +available.

+ +

The cl::ParseCommandLineOptions function requires two parameters +(argc and argv), but may also take an optional third parameter +which holds additional extra text to emit when the +-help option is invoked, and a fourth boolean parameter that enables +response files.

+ +
+ + + + +
+ +

The cl::ParseEnvironmentOptions function has mostly the same effects +as cl::ParseCommandLineOptions, +except that it is designed to take values for options from an environment +variable, for those cases in which reading the command line is not convenient or +desired. It fills in the values of all the command line option variables just +like cl::ParseCommandLineOptions +does.

+ +

It takes four parameters: the name of the program (since argv may +not be available, it can't just look in argv[0]), the name of the +environment variable to examine, the optional +additional extra text to emit when the +-help option is invoked, and the boolean +switch that controls whether response files +should be read.

+ +

cl::ParseEnvironmentOptions will break the environment +variable's value up into words and then process them using +cl::ParseCommandLineOptions. +Note: Currently cl::ParseEnvironmentOptions does not support +quoting, so an environment variable containing -option "foo bar" will +be parsed as three words, -option, "foo, and bar", +which is different from what you would get from the shell with the same +input.

+ +
+ + + + +
+ +

The cl::SetVersionPrinter function is designed to be called +directly from main and before +cl::ParseCommandLineOptions. Its use is optional. It simply arranges +for a function to be called in response to the --version option instead +of having the CommandLine library print out the usual version string +for LLVM. This is useful for programs that are not part of LLVM but wish to use +the CommandLine facilities. Such programs should just define a small +function that takes no arguments and returns void and that prints out +whatever version information is appropriate for the program. Pass the address +of that function to cl::SetVersionPrinter to arrange for it to be +called when the --version option is given by the user.

+ +
+ + + +
+ +

The cl::opt class is the class used to represent scalar command line +options, and is the one used most of the time. It is a templated class which +can take up to three arguments (all except for the first have default values +though):

+ +
+namespace cl {
+  template <class DataType, bool ExternalStorage = false,
+            class ParserClass = parser<DataType> >
+  class opt;
+}
+
+ +

The first template argument specifies what underlying data type the command +line argument is, and is used to select a default parser implementation. The +second template argument is used to specify whether the option should contain +the storage for the option (the default) or whether external storage should be +used to contain the value parsed for the option (see Internal +vs External Storage for more information).

+ +

The third template argument specifies which parser to use. The default value +selects an instantiation of the parser class based on the underlying +data type of the option. In general, this default works well for most +applications, so this option is only used when using a custom parser.

+ +
+ + + + +
+ +

The cl::list class is the class used to represent a list of command +line options. It too is a templated class which can take up to three +arguments:

+ +
+namespace cl {
+  template <class DataType, class Storage = bool,
+            class ParserClass = parser<DataType> >
+  class list;
+}
+
+ +

This class works the exact same as the cl::opt class, except that the second argument is +the type of the external storage, not a boolean value. For this class, +the marker type 'bool' is used to indicate that internal storage should +be used.

+ +
+ + + + +
+ +

The cl::bits class is the class used to represent a list of command +line options in the form of a bit vector. It is also a templated class which +can take up to three arguments:

+ +
+namespace cl {
+  template <class DataType, class Storage = bool,
+            class ParserClass = parser<DataType> >
+  class bits;
+}
+
+ +

This class works the exact same as the cl::lists class, except that the second argument +must be of type unsigned if external storage is used.

+ +
+ + + + +
+ +

The cl::alias class is a nontemplated class that is used to form +aliases for other arguments.

+ +
+namespace cl {
+  class alias;
+}
+
+ +

The cl::aliasopt attribute should be +used to specify which option this is an alias for. Alias arguments default to +being Hidden, and use the aliased options parser to do +the conversion from string to data.

+ +
+ + + + +
+ +

The cl::extrahelp class is a nontemplated class that allows extra +help text to be printed out for the -help option.

+ +
+namespace cl {
+  struct extrahelp;
+}
+
+ +

To use the extrahelp, simply construct one with a const char* +parameter to the constructor. The text passed to the constructor will be printed +at the bottom of the help message, verbatim. Note that multiple +cl::extrahelp can be used, but this practice is discouraged. If +your tool needs to print additional help information, put all that help into a +single cl::extrahelp instance.

+

For example:

+
+  cl::extrahelp("\nADDITIONAL HELP:\n\n  This is the extra help\n");
+
+
+ + + + +
+ +

Parsers control how the string value taken from the command line is +translated into a typed value, suitable for use in a C++ program. By default, +the CommandLine library uses an instance of parser<type> if the +command line option specifies that it uses values of type 'type'. +Because of this, custom option processing is specified with specializations of +the 'parser' class.

+ +

The CommandLine library provides the following builtin parser +specializations, which are sufficient for most applications. It can, however, +also be extended to work with new data types and new ways of interpreting the +same data. See the Writing a Custom Parser for more +details on this type of library extension.

+ +
    + +
  • The generic parser<t> parser +can be used to map strings values to any data type, through the use of the cl::values property, which specifies the mapping +information. The most common use of this parser is for parsing enum values, +which allows you to use the CommandLine library for all of the error checking to +make sure that only valid enum values are specified (as opposed to accepting +arbitrary strings). Despite this, however, the generic parser class can be used +for any data type.
  • + +
  • The parser<bool> specialization +is used to convert boolean strings to a boolean value. Currently accepted +strings are "true", "TRUE", "True", "1", +"false", "FALSE", "False", and "0".
  • + +
  • The parser<boolOrDefault> + specialization is used for cases where the value is boolean, +but we also need to know whether the option was specified at all. boolOrDefault +is an enum with 3 values, BOU_UNSET, BOU_TRUE and BOU_FALSE. This parser accepts +the same strings as parser<bool>.
  • + +
  • The parser<string> +specialization simply stores the parsed string into the string value +specified. No conversion or modification of the data is performed.
  • + +
  • The parser<int> specialization +uses the C strtol function to parse the string input. As such, it will +accept a decimal number (with an optional '+' or '-' prefix) which must start +with a non-zero digit. It accepts octal numbers, which are identified with a +'0' prefix digit, and hexadecimal numbers with a prefix of +'0x' or '0X'.
  • + +
  • The parser<double> and +parser<float> specializations use the standard C +strtod function to convert floating point strings into floating point +values. As such, a broad range of string formats is supported, including +exponential notation (ex: 1.7e15) and properly supports locales. +
  • + +
+ +
+ + + + + +
+ +

Although the CommandLine library has a lot of functionality built into it +already (as discussed previously), one of its true strengths lie in its +extensibility. This section discusses how the CommandLine library works under +the covers and illustrates how to do some simple, common, extensions.

+ +
+ + + + +
+ +

One of the simplest and most common extensions is the use of a custom parser. +As discussed previously, parsers are the portion +of the CommandLine library that turns string input from the user into a +particular parsed data type, validating the input in the process.

+ +

There are two ways to use a new parser:

+ +
    + +
  1. + +

    Specialize the cl::parser template for +your custom data type.

    + +

    This approach has the advantage that users of your custom data type will +automatically use your custom parser whenever they define an option with a value +type of your data type. The disadvantage of this approach is that it doesn't +work if your fundamental data type is something that is already supported.

    + +
  2. + +
  3. + +

    Write an independent class, using it explicitly from options that need +it.

    + +

    This approach works well in situations where you would line to parse an +option using special syntax for a not-very-special data-type. The drawback of +this approach is that users of your parser have to be aware that they are using +your parser instead of the builtin ones.

    + +
  4. + +
+ +

To guide the discussion, we will discuss a custom parser that accepts file +sizes, specified with an optional unit after the numeric size. For example, we +would like to parse "102kb", "41M", "1G" into the appropriate integer value. In +this case, the underlying data type we want to parse into is +'unsigned'. We choose approach #2 above because we don't want to make +this the default for all unsigned options.

+ +

To start out, we declare our new FileSizeParser class:

+ +
+struct FileSizeParser : public cl::basic_parser<unsigned> {
+  // parse - Return true on error.
+  bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue,
+             unsigned &Val);
+};
+
+ +

Our new class inherits from the cl::basic_parser template class to +fill in the default, boiler plate code for us. We give it the data type that +we parse into, the last argument to the parse method, so that clients of +our custom parser know what object type to pass in to the parse method. (Here we +declare that we parse into 'unsigned' variables.)

+ +

For most purposes, the only method that must be implemented in a custom +parser is the parse method. The parse method is called +whenever the option is invoked, passing in the option itself, the option name, +the string to parse, and a reference to a return value. If the string to parse +is not well-formed, the parser should output an error message and return true. +Otherwise it should return false and set 'Val' to the parsed value. In +our example, we implement parse as:

+ +
+bool FileSizeParser::parse(cl::Option &O, const char *ArgName,
+                           const std::string &Arg, unsigned &Val) {
+  const char *ArgStart = Arg.c_str();
+  char *End;
+
+  // Parse integer part, leaving 'End' pointing to the first non-integer char
+  Val = (unsigned)strtol(ArgStart, &End, 0);
+
+  while (1) {
+    switch (*End++) {
+    case 0: return false;   // No error
+    case 'i':               // Ignore the 'i' in KiB if people use that
+    case 'b': case 'B':     // Ignore B suffix
+      break;
+
+    case 'g': case 'G': Val *= 1024*1024*1024; break;
+    case 'm': case 'M': Val *= 1024*1024;      break;
+    case 'k': case 'K': Val *= 1024;           break;
+
+    default:
+      // Print an error message if unrecognized character!
+      return O.error("'" + Arg + "' value invalid for file size argument!");
+    }
+  }
+}
+
+ +

This function implements a very simple parser for the kinds of strings we are +interested in. Although it has some holes (it allows "123KKK" for +example), it is good enough for this example. Note that we use the option +itself to print out the error message (the error method always returns +true) in order to get a nice error message (shown below). Now that we have our +parser class, we can use it like this:

+ +
+static cl::opt<unsigned, false, FileSizeParser>
+MFS("max-file-size", cl::desc("Maximum file size to accept"),
+    cl::value_desc("size"));
+
+ +

Which adds this to the output of our program:

+ +
+OPTIONS:
+  -help                 - display available options (-help-hidden for more)
+  ...
+  -max-file-size=<size> - Maximum file size to accept
+
+ +

And we can test that our parse works correctly now (the test program just +prints out the max-file-size argument value):

+ +
+$ ./test
+MFS: 0
+$ ./test -max-file-size=123MB
+MFS: 128974848
+$ ./test -max-file-size=3G
+MFS: 3221225472
+$ ./test -max-file-size=dog
+-max-file-size option: 'dog' value invalid for file size argument!
+
+ +

It looks like it works. The error message that we get is nice and helpful, +and we seem to accept reasonable file sizes. This wraps up the "custom parser" +tutorial.

+ +
+ + + + +
+

Several of the LLVM libraries define static cl::opt instances that + will automatically be included in any program that links with that library. + This is a feature. However, sometimes it is necessary to know the value of the + command line option outside of the library. In these cases the library does or + should provide an external storage location that is accessible to users of the + library. Examples of this include the llvm::DebugFlag exported by the + lib/Support/Debug.cpp file and the llvm::TimePassesIsEnabled + flag exported by the lib/VMCore/Pass.cpp file.

+ +

TODO: complete this section

+ +
+ + + + +
+ +

TODO: fill in this section

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/CompilerDriver.html b/final/docs/CompilerDriver.html new file mode 100644 index 00000000000..3c82e2b0769 --- /dev/null +++ b/final/docs/CompilerDriver.html @@ -0,0 +1,756 @@ + + + + + + +Customizing LLVMC: Reference Manual + + + +
+

Customizing LLVMC: Reference Manual

+ + + +
+

Written by Mikhail Glushenkov

+
+

Introduction

+

LLVMC is a generic compiler driver, designed to be customizable and +extensible. It plays the same role for LLVM as the gcc program +does for GCC - LLVMC's job is essentially to transform a set of input +files into a set of targets depending on configuration rules and user +options. What makes LLVMC different is that these transformation rules +are completely customizable - in fact, LLVMC knows nothing about the +specifics of transformation (even the command-line options are mostly +not hard-coded) and regards the transformation structure as an +abstract graph. The structure of this graph is completely determined +by plugins, which can be either statically or dynamically linked. This +makes it possible to easily adapt LLVMC for other purposes - for +example, as a build tool for game resources.

+

Because LLVMC employs TableGen as its configuration language, you +need to be familiar with it to customize LLVMC.

+
+
+

Compiling with LLVMC

+

LLVMC tries hard to be as compatible with gcc as possible, +although there are some small differences. Most of the time, however, +you shouldn't be able to notice them:

+
+$ # This works as expected:
+$ llvmc -O3 -Wall hello.cpp
+$ ./a.out
+hello
+
+

One nice feature of LLVMC is that one doesn't have to distinguish between +different compilers for different languages (think g++ vs. gcc) - the +right toolchain is chosen automatically based on input language names (which +are, in turn, determined from file extensions). If you want to force files +ending with ".c" to compile as C++, use the -x option, just like you would +do it with gcc:

+
+$ # hello.c is really a C++ file
+$ llvmc -x c++ hello.c
+$ ./a.out
+hello
+
+

On the other hand, when using LLVMC as a linker to combine several C++ +object files you should provide the --linker option since it's +impossible for LLVMC to choose the right linker in that case:

+
+$ llvmc -c hello.cpp
+$ llvmc hello.o
+[A lot of link-time errors skipped]
+$ llvmc --linker=c++ hello.o
+$ ./a.out
+hello
+
+

By default, LLVMC uses llvm-gcc to compile the source code. It is also +possible to choose the clang compiler with the -clang option.

+
+
+

Predefined options

+

LLVMC has some built-in options that can't be overridden in the +configuration libraries:

+
    +
  • -o FILE - Output file name.
  • +
  • -x LANGUAGE - Specify the language of the following input files +until the next -x option.
  • +
  • -load PLUGIN_NAME - Load the specified plugin DLL. Example: +-load $LLVM_DIR/Release/lib/LLVMCSimple.so.
  • +
  • -v - Enable verbose mode, i.e. print out all executed commands.
  • +
  • --save-temps - Write temporary files to the current directory and do not +delete them on exit. This option can also take an argument: the +--save-temps=obj switch will write files into the directory specified with +the -o option. The --save-temps=cwd and --save-temps switches are +both synonyms for the default behaviour.
  • +
  • --temp-dir DIRECTORY - Store temporary files in the given directory. This +directory is deleted on exit unless --save-temps is specified. If +--save-temps=obj is also specified, --temp-dir is given the +precedence.
  • +
  • --check-graph - Check the compilation for common errors like mismatched +output/input language names, multiple default edges and cycles. Because of +plugins, these checks can't be performed at compile-time. Exit with code zero +if no errors were found, and return the number of found errors +otherwise. Hidden option, useful for debugging LLVMC plugins.
  • +
  • --view-graph - Show a graphical representation of the compilation graph +and exit. Requires that you have dot and gv programs installed. Hidden +option, useful for debugging LLVMC plugins.
  • +
  • --write-graph - Write a compilation-graph.dot file in the current +directory with the compilation graph description in Graphviz format (identical +to the file used by the --view-graph option). The -o option can be +used to set the output file name. Hidden option, useful for debugging LLVMC +plugins.
  • +
  • -help, -help-hidden, --version - These options have +their standard meaning.
  • +
+
+
+

Compiling LLVMC plugins

+

It's easiest to start working on your own LLVMC plugin by copying the +skeleton project which lives under $LLVMC_DIR/plugins/Simple:

+
+$ cd $LLVMC_DIR/plugins
+$ cp -r Simple MyPlugin
+$ cd MyPlugin
+$ ls
+Makefile PluginMain.cpp Simple.td
+
+

As you can see, our basic plugin consists of only two files (not +counting the build script). Simple.td contains TableGen +description of the compilation graph; its format is documented in the +following sections. PluginMain.cpp is just a helper file used to +compile the auto-generated C++ code produced from TableGen source. It +can also contain hook definitions (see below).

+

The first thing that you should do is to change the LLVMC_PLUGIN +variable in the Makefile to avoid conflicts (since this variable +is used to name the resulting library):

+
+LLVMC_PLUGIN=MyPlugin
+
+

It is also a good idea to rename Simple.td to something less +generic:

+
+$ mv Simple.td MyPlugin.td
+
+

To build your plugin as a dynamic library, just cd to its source +directory and run make. The resulting file will be called +plugin_llvmc_$(LLVMC_PLUGIN).$(DLL_EXTENSION) (in our case, +plugin_llvmc_MyPlugin.so). This library can be then loaded in with the +-load option. Example:

+
+$ cd $LLVMC_DIR/plugins/Simple
+$ make
+$ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
+
+
+
+

Compiling standalone LLVMC-based drivers

+

By default, the llvmc executable consists of a driver core plus several +statically linked plugins (Base and Clang at the moment). You can +produce a standalone LLVMC-based driver executable by linking the core with your +own plugins. The recommended way to do this is by starting with the provided +Skeleton example ($LLVMC_DIR/example/Skeleton):

+
+$ cd $LLVMC_DIR/example/
+$ cp -r Skeleton mydriver
+$ cd mydriver
+$ vim Makefile
+[...]
+$ make
+
+

If you're compiling LLVM with different source and object directories, then you +must perform the following additional steps before running make:

+
+# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
+# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
+$ cp $LLVMC_SRC_DIR/example/mydriver/Makefile \
+  $LLVMC_OBJ_DIR/example/mydriver/
+$ cd $LLVMC_OBJ_DIR/example/mydriver
+$ make
+
+

Another way to do the same thing is by using the following command:

+
+$ cd $LLVMC_DIR
+$ make LLVMC_BUILTIN_PLUGINS=MyPlugin LLVMC_BASED_DRIVER_NAME=mydriver
+
+

This works with both srcdir == objdir and srcdir != objdir, but assumes that the +plugin source directory was placed under $LLVMC_DIR/plugins.

+

Sometimes, you will want a 'bare-bones' version of LLVMC that has no +built-in plugins. It can be compiled with the following command:

+
+$ cd $LLVMC_DIR
+$ make LLVMC_BUILTIN_PLUGINS=""
+
+
+
+

Customizing LLVMC: the compilation graph

+

Each TableGen configuration file should include the common +definitions:

+
+include "llvm/CompilerDriver/Common.td"
+
+

Internally, LLVMC stores information about possible source +transformations in form of a graph. Nodes in this graph represent +tools, and edges between two nodes represent a transformation path. A +special "root" node is used to mark entry points for the +transformations. LLVMC also assigns a weight to each edge (more on +this later) to choose between several alternative edges.

+

The definition of the compilation graph (see file +plugins/Base/Base.td for an example) is just a list of edges:

+
+def CompilationGraph : CompilationGraph<[
+    Edge<"root", "llvm_gcc_c">,
+    Edge<"root", "llvm_gcc_assembler">,
+    ...
+
+    Edge<"llvm_gcc_c", "llc">,
+    Edge<"llvm_gcc_cpp", "llc">,
+    ...
+
+    OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
+                                      (inc_weight))>,
+    OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
+                                              (inc_weight))>,
+    ...
+
+    OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
+        (case (input_languages_contain "c++"), (inc_weight),
+              (or (parameter_equals "linker", "g++"),
+                  (parameter_equals "linker", "c++")), (inc_weight))>,
+    ...
+
+    ]>;
+
+

As you can see, the edges can be either default or optional, where +optional edges are differentiated by an additional case expression +used to calculate the weight of this edge. Notice also that we refer +to tools via their names (as strings). This makes it possible to add +edges to an existing compilation graph in plugins without having to +know about all tool definitions used in the graph.

+

The default edges are assigned a weight of 1, and optional edges get a +weight of 0 + 2*N where N is the number of tests that evaluated to +true in the case expression. It is also possible to provide an +integer parameter to inc_weight and dec_weight - in this case, +the weight is increased (or decreased) by the provided value instead +of the default 2. It is also possible to change the default weight of +an optional edge by using the default clause of the case +construct.

+

When passing an input file through the graph, LLVMC picks the edge +with the maximum weight. To avoid ambiguity, there should be only one +default edge between two nodes (with the exception of the root node, +which gets a special treatment - there you are allowed to specify one +default edge per language).

+

When multiple plugins are loaded, their compilation graphs are merged +together. Since multiple edges that have the same end nodes are not +allowed (i.e. the graph is not a multigraph), an edge defined in +several plugins will be replaced by the definition from the plugin +that was loaded last. Plugin load order can be controlled by using the +plugin priority feature described above.

+

To get a visual representation of the compilation graph (useful for +debugging), run llvmc --view-graph. You will need dot and +gsview installed for this to work properly.

+
+
+

Describing options

+

Command-line options that the plugin supports are defined by using an +OptionList:

+
+def Options : OptionList<[
+(switch_option "E", (help "Help string")),
+(alias_option "quiet", "q")
+...
+]>;
+
+

As you can see, the option list is just a list of DAGs, where each DAG +is an option description consisting of the option name and some +properties. A plugin can define more than one option list (they are +all merged together in the end), which can be handy if one wants to +separate option groups syntactically.

+
    +
  • Possible option types:

    +
    +
      +
    • switch_option - a simple boolean switch without arguments, for example +-O2 or -time. At most one occurrence is allowed.
    • +
    • parameter_option - option that takes one argument, for example +-std=c99. It is also allowed to use spaces instead of the equality +sign: -std c99. At most one occurrence is allowed.
    • +
    • parameter_list_option - same as the above, but more than one option +occurence is allowed.
    • +
    • prefix_option - same as the parameter_option, but the option name and +argument do not have to be separated. Example: -ofile. This can be also +specified as -o file; however, -o=file will be parsed incorrectly +(=file will be interpreted as option value). At most one occurrence is +allowed.
    • +
    • prefix_list_option - same as the above, but more than one occurence of +the option is allowed; example: -lm -lpthread.
    • +
    • alias_option - a special option type for creating aliases. Unlike other +option types, aliases are not allowed to have any properties besides the +aliased option name. Usage example: (alias_option "preprocess", "E")
    • +
    +
    +
  • +
  • Possible option properties:

    +
    +
      +
    • help - help string associated with this option. Used for -help +output.
    • +
    • required - this option must be specified exactly once (or, in case of +the list options without the multi_val property, at least +once). Incompatible with zero_or_one and one_or_more.
    • +
    • one_or_more - the option must be specified at least one time. Useful +only for list options in conjunction with multi_val; for ordinary lists +it is synonymous with required. Incompatible with required and +zero_or_one.
    • +
    • optional - the option can be specified zero or one times. Useful only +for list options in conjunction with multi_val. Incompatible with +required and one_or_more.
    • +
    • hidden - the description of this option will not appear in +the -help output (but will appear in the -help-hidden +output).
    • +
    • really_hidden - the option will not be mentioned in any help +output.
    • +
    • comma_separated - Indicates that any commas specified for an option's +value should be used to split the value up into multiple values for the +option. This property is valid only for list options. In conjunction with +forward_value can be used to implement option forwarding in style of +gcc's -Wa,.
    • +
    • multi_val n - this option takes n arguments (can be useful in some +special cases). Usage example: (parameter_list_option "foo", (multi_val +3)); the command-line syntax is '-foo a b c'. Only list options can have +this attribute; you can, however, use the one_or_more, optional +and required properties.
    • +
    • init - this option has a default value, either a string (if it is a +parameter), or a boolean (if it is a switch; as in C++, boolean constants +are called true and false). List options can't have init +attribute. +Usage examples: (switch_option "foo", (init true)); (prefix_option +"bar", (init "baz")).
    • +
    • extern - this option is defined in some other plugin, see below.
    • +
    +
    +
  • +
+
+

External options

+

Sometimes, when linking several plugins together, one plugin needs to +access options defined in some other plugin. Because of the way +options are implemented, such options must be marked as +extern. This is what the extern option property is +for. Example:

+
+...
+(switch_option "E", (extern))
+...
+
+

If an external option has additional attributes besides 'extern', they are +ignored. See also the section on plugin priorities.

+
+
+
+

Conditional evaluation

+

The 'case' construct is the main means by which programmability is +achieved in LLVMC. It can be used to calculate edge weights, program +actions and modify the shell commands to be executed. The 'case' +expression is designed after the similarly-named construct in +functional languages and takes the form (case (test_1), statement_1, +(test_2), statement_2, ... (test_N), statement_N). The statements +are evaluated only if the corresponding tests evaluate to true.

+

Examples:

+
+// Edge weight calculation
+
+// Increases edge weight by 5 if "-A" is provided on the
+// command-line, and by 5 more if "-B" is also provided.
+(case
+    (switch_on "A"), (inc_weight 5),
+    (switch_on "B"), (inc_weight 5))
+
+
+// Tool command line specification
+
+// Evaluates to "cmdline1" if the option "-A" is provided on the
+// command line; to "cmdline2" if "-B" is provided;
+// otherwise to "cmdline3".
+
+(case
+    (switch_on "A"), "cmdline1",
+    (switch_on "B"), "cmdline2",
+    (default), "cmdline3")
+
+

Note the slight difference in 'case' expression handling in contexts +of edge weights and command line specification - in the second example +the value of the "B" switch is never checked when switch "A" is +enabled, and the whole expression always evaluates to "cmdline1" in +that case.

+

Case expressions can also be nested, i.e. the following is legal:

+
+(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
+      (default), ...)
+
+

You should, however, try to avoid doing that because it hurts +readability. It is usually better to split tool descriptions and/or +use TableGen inheritance instead.

+
    +
  • Possible tests are:
      +
    • switch_on - Returns true if a given command-line switch is provided by +the user. Can be given a list as argument, in that case (switch_on ["foo", +"bar", "baz"]) is equivalent to (and (switch_on "foo"), (switch_on +"bar"), (switch_on "baz")). +Example: (switch_on "opt").
    • +
    • any_switch_on - Given a list of switch options, returns true if any of +the switches is turned on. +Example: (any_switch_on ["foo", "bar", "baz"]) is equivalent to (or +(switch_on "foo"), (switch_on "bar"), (switch_on "baz")).
    • +
    • parameter_equals - Returns true if a command-line parameter equals +a given value. +Example: (parameter_equals "W", "all").
    • +
    • element_in_list - Returns true if a command-line parameter +list contains a given value. +Example: (element_in_list "l", "pthread").
    • +
    • input_languages_contain - Returns true if a given language +belongs to the current input language set. +Example: (input_languages_contain "c++").
    • +
    • in_language - Evaluates to true if the input file language is equal to +the argument. At the moment works only with cmd_line and actions (on +non-join nodes). +Example: (in_language "c++").
    • +
    • not_empty - Returns true if a given option (which should be either a +parameter or a parameter list) is set by the user. Like switch_on, can +be also given a list as argument. +Example: (not_empty "o").
    • +
    • any_not_empty - Returns true if not_empty returns true for any of +the options in the list. +Example: (any_not_empty ["foo", "bar", "baz"]) is equivalent to (or +(not_empty "foo"), (not_empty "bar"), (not_empty "baz")).
    • +
    • empty - The opposite of not_empty. Equivalent to (not (not_empty +X)). Provided for convenience. Can be given a list as argument.
    • +
    • any_not_empty - Returns true if not_empty returns true for any of +the options in the list. +Example: (any_empty ["foo", "bar", "baz"]) is equivalent to (not (and +(not_empty "foo"), (not_empty "bar"), (not_empty "baz"))).
    • +
    • single_input_file - Returns true if there was only one input file +provided on the command-line. Used without arguments: +(single_input_file).
    • +
    • multiple_input_files - Equivalent to (not (single_input_file)) (the +case of zero input files is considered an error).
    • +
    • default - Always evaluates to true. Should always be the last +test in the case expression.
    • +
    • and - A standard binary logical combinator that returns true iff all of +its arguments return true. Used like this: (and (test1), (test2), +... (testN)). Nesting of and and or is allowed, but not +encouraged.
    • +
    • or - A binary logical combinator that returns true iff any of its +arguments returns true. Example: (or (test1), (test2), ... (testN)).
    • +
    • not - Standard unary logical combinator that negates its +argument. Example: (not (or (test1), (test2), ... (testN))).
    • +
    +
  • +
+
+
+

Writing a tool description

+

As was said earlier, nodes in the compilation graph represent tools, +which are described separately. A tool definition looks like this +(taken from the include/llvm/CompilerDriver/Tools.td file):

+
+def llvm_gcc_cpp : Tool<[
+    (in_language "c++"),
+    (out_language "llvm-assembler"),
+    (output_suffix "bc"),
+    (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
+    (sink)
+    ]>;
+
+

This defines a new tool called llvm_gcc_cpp, which is an alias for +llvm-g++. As you can see, a tool definition is just a list of +properties; most of them should be self-explanatory. The sink +property means that this tool should be passed all command-line +options that aren't mentioned in the option list.

+

The complete list of all currently implemented tool properties follows.

+
    +
  • Possible tool properties:
      +
    • in_language - input language name. Can be either a string or a +list, in case the tool supports multiple input languages.
    • +
    • out_language - output language name. Multiple output languages are not +allowed.
    • +
    • output_suffix - output file suffix. Can also be changed +dynamically, see documentation on actions.
    • +
    • cmd_line - the actual command used to run the tool. You can +use $INFILE and $OUTFILE variables, output redirection +with >, hook invocations ($CALL), environment variables +(via $ENV) and the case construct.
    • +
    • join - this tool is a "join node" in the graph, i.e. it gets a +list of input files and joins them together. Used for linkers.
    • +
    • sink - all command-line options that are not handled by other +tools are passed to this tool.
    • +
    • actions - A single big case expression that specifies how +this tool reacts on command-line options (described in more detail +below).
    • +
    +
  • +
+
+

Actions

+

A tool often needs to react to command-line options, and this is +precisely what the actions property is for. The next example +illustrates this feature:

+
+def llvm_gcc_linker : Tool<[
+    (in_language "object-code"),
+    (out_language "executable"),
+    (output_suffix "out"),
+    (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+    (join),
+    (actions (case (not_empty "L"), (forward "L"),
+                   (not_empty "l"), (forward "l"),
+                   (not_empty "dummy"),
+                             [(append_cmd "-dummy1"), (append_cmd "-dummy2")])
+    ]>;
+
+

The actions tool property is implemented on top of the omnipresent +case expression. It associates one or more different actions +with given conditions - in the example, the actions are forward, +which forwards a given option unchanged, and append_cmd, which +appends a given string to the tool execution command. Multiple actions +can be associated with a single condition by using a list of actions +(used in the example to append some dummy options). The same case +construct can also be used in the cmd_line property to modify the +tool command line.

+

The "join" property used in the example means that this tool behaves +like a linker.

+

The list of all possible actions follows.

+
    +
  • Possible actions:

    +
    +
      +
    • append_cmd - Append a string to the tool invocation command. +Example: (case (switch_on "pthread"), (append_cmd "-lpthread")).
    • +
    • error - Exit with error. +Example: (error "Mixing -c and -S is not allowed!").
    • +
    • warning - Print a warning. +Example: (warning "Specifying both -O1 and -O2 is meaningless!").
    • +
    • forward - Forward the option unchanged. +Example: (forward "Wall").
    • +
    • forward_as - Change the option's name, but forward the argument +unchanged. +Example: (forward_as "O0", "--disable-optimization").
    • +
    • forward_value - Forward only option's value. Cannot be used with switch +options (since they don't have values), but works fine with lists. +Example: (forward_value "Wa,").
    • +
    • forward_transformed_value - As above, but applies a hook to the +option's value before forwarding (see below). When +forward_transformed_value is applied to a list +option, the hook must have signature +std::string hooks::HookName (const std::vector<std::string>&). +Example: (forward_transformed_value "m", "ConvertToMAttr").
    • +
    • output_suffix - Modify the output suffix of this tool. +Example: (output_suffix "i").
    • +
    • stop_compilation - Stop compilation after this tool processes its +input. Used without arguments. +Example: (stop_compilation).
    • +
    +
    +
  • +
+
+
+
+

Language map

+

If you are adding support for a new language to LLVMC, you'll need to +modify the language map, which defines mappings from file extensions +to language names. It is used to choose the proper toolchain(s) for a +given input file set. Language map definition looks like this:

+
+def LanguageMap : LanguageMap<
+    [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
+     LangToSuffixes<"c", ["c"]>,
+     ...
+    ]>;
+
+

For example, without those definitions the following command wouldn't work:

+
+$ llvmc hello.cpp
+llvmc: Unknown suffix: cpp
+
+

The language map entries are needed only for the tools that are linked from the +root node. Since a tool can't have multiple output languages, for inner nodes of +the graph the input and output languages should match. This is enforced at +compile-time.

+
+
+

Option preprocessor

+

It is sometimes useful to run error-checking code before processing the +compilation graph. For example, if optimization options "-O1" and "-O2" are +implemented as switches, we might want to output a warning if the user invokes +the driver with both of these options enabled.

+

The OptionPreprocessor feature is reserved specially for these +occasions. Example (adapted from the built-in Base plugin):

+
+def Preprocess : OptionPreprocessor<
+(case (not (any_switch_on ["O0", "O1", "O2", "O3"])),
+           (set_option "O2"),
+      (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])),
+           (unset_option ["O0", "O1", "O2"]),
+      (and (switch_on "O2"), (any_switch_on ["O0", "O1"])),
+           (unset_option ["O0", "O1"]),
+      (and (switch_on "O1"), (switch_on "O0")),
+           (unset_option "O0"))
+>;
+
+

Here, OptionPreprocessor is used to unset all spurious -O options so +that they are not forwarded to the compiler. If no optimization options are +specified, -O2 is enabled.

+

OptionPreprocessor is basically a single big case expression, which is +evaluated only once right after the plugin is loaded. The only allowed actions +in OptionPreprocessor are error, warning, and two special actions: +unset_option and set_option. As their names suggest, they can be used to +set or unset a given option. To set an option with set_option, use the +two-argument form: (set_option "parameter", VALUE). Here, VALUE can be +either a string, a string list, or a boolean constant.

+

For convenience, set_option and unset_option also work on lists. That +is, instead of [(unset_option "A"), (unset_option "B")] you can use +(unset_option ["A", "B"]). Obviously, (set_option ["A", "B"]) is valid +only if both A and B are switches.

+
+
+

More advanced topics

+
+

Hooks and environment variables

+

Normally, LLVMC executes programs from the system PATH. Sometimes, +this is not sufficient: for example, we may want to specify tool paths +or names in the configuration file. This can be easily achieved via +the hooks mechanism. To write your own hooks, just add their +definitions to the PluginMain.cpp or drop a .cpp file into the +your plugin directory. Hooks should live in the hooks namespace +and have the signature std::string hooks::MyHookName ([const char* +Arg0 [ const char* Arg2 [, ...]]]). They can be used from the +cmd_line tool property:

+
+(cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
+
+

To pass arguments to hooks, use the following syntax:

+
+(cmd_line "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
+
+

It is also possible to use environment variables in the same manner:

+
+(cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
+
+

To change the command line string based on user-provided options use +the case expression (documented above):

+
+(cmd_line
+  (case
+    (switch_on "E"),
+       "llvm-g++ -E -x c $INFILE -o $OUTFILE",
+    (default),
+       "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
+
+
+
+

How plugins are loaded

+

It is possible for LLVMC plugins to depend on each other. For example, +one can create edges between nodes defined in some other plugin. To +make this work, however, that plugin should be loaded first. To +achieve this, the concept of plugin priority was introduced. By +default, every plugin has priority zero; to specify the priority +explicitly, put the following line in your plugin's TableGen file:

+
+def Priority : PluginPriority<$PRIORITY_VALUE>;
+# Where PRIORITY_VALUE is some integer > 0
+
+

Plugins are loaded in order of their (increasing) priority, starting +with 0. Therefore, the plugin with the highest priority value will be +loaded last.

+
+
+

Debugging

+

When writing LLVMC plugins, it can be useful to get a visual view of +the resulting compilation graph. This can be achieved via the command +line option --view-graph. This command assumes that Graphviz and +Ghostview are installed. There is also a --write-graph option that +creates a Graphviz source file (compilation-graph.dot) in the +current directory.

+

Another useful llvmc option is --check-graph. It checks the +compilation graph for common errors like mismatched output/input +language names, multiple default edges and cycles. These checks can't +be performed at compile-time because the plugins can load code +dynamically. When invoked with --check-graph, llvmc doesn't +perform any compilation tasks and returns the number of encountered +errors as its status code.

+
+
+

Conditioning on the executable name

+

For now, the executable name (the value passed to the driver in argv[0]) is +accessible only in the C++ code (i.e. hooks). Use the following code:

+
+namespace llvmc {
+extern const char* ProgramName;
+}
+
+namespace hooks {
+
+std::string MyHook() {
+//...
+if (strcmp(ProgramName, "mydriver") == 0) {
+   //...
+
+}
+
+} // end namespace hooks
+
+

In general, you're encouraged not to make the behaviour dependent on the +executable file name, and use command-line switches instead. See for example how +the Base plugin behaves when it needs to choose the correct linker options +(think g++ vs. gcc).

+
+
+ +Valid CSS + +Valid XHTML 1.0 Transitional + +Mikhail Glushenkov
+LLVM Compiler Infrastructure
+ +Last modified: $Date$ +
+
+
+ + diff --git a/final/docs/CompilerDriverTutorial.html b/final/docs/CompilerDriverTutorial.html new file mode 100644 index 00000000000..317b1d12712 --- /dev/null +++ b/final/docs/CompilerDriverTutorial.html @@ -0,0 +1,126 @@ + + + + + + +Tutorial - Using LLVMC + + + +
+

Tutorial - Using LLVMC

+ + + +
+

Written by Mikhail Glushenkov

+
+

Introduction

+

LLVMC is a generic compiler driver, which plays the same role for LLVM +as the gcc program does for GCC - the difference being that LLVMC +is designed to be more adaptable and easier to customize. Most of +LLVMC functionality is implemented via plugins, which can be loaded +dynamically or compiled in. This tutorial describes the basic usage +and configuration of LLVMC.

+
+
+

Compiling with LLVMC

+

In general, LLVMC tries to be command-line compatible with gcc as +much as possible, so most of the familiar options work:

+
+$ llvmc -O3 -Wall hello.cpp
+$ ./a.out
+hello
+
+

This will invoke llvm-g++ under the hood (you can see which +commands are executed by using the -v option). For further help on +command-line LLVMC usage, refer to the llvmc --help output.

+
+
+

Using LLVMC to generate toolchain drivers

+

LLVMC plugins are written mostly using TableGen, so you need to +be familiar with it to get anything done.

+

Start by compiling example/Simple, which is a primitive wrapper for +gcc:

+
+$ cd $LLVM_DIR/tools/llvmc
+$ cp -r example/Simple plugins/Simple
+
+  # NB: A less verbose way to compile standalone LLVMC-based drivers is
+  # described in the reference manual.
+
+$ make LLVMC_BASED_DRIVER_NAME=mygcc LLVMC_BUILTIN_PLUGINS=Simple
+$ cat > hello.c
+[...]
+$ mygcc hello.c
+$ ./hello.out
+Hello
+
+

Here we link our plugin with the LLVMC core statically to form an executable +file called mygcc. It is also possible to build our plugin as a dynamic +library to be loaded by the llvmc executable (or any other LLVMC-based +standalone driver); this is described in the reference manual.

+

Contents of the file Simple.td look like this:

+
+// Include common definitions
+include "llvm/CompilerDriver/Common.td"
+
+// Tool descriptions
+def gcc : Tool<
+[(in_language "c"),
+ (out_language "executable"),
+ (output_suffix "out"),
+ (cmd_line "gcc $INFILE -o $OUTFILE"),
+ (sink)
+]>;
+
+// Language map
+def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
+
+// Compilation graph
+def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
+
+

As you can see, this file consists of three parts: tool descriptions, +language map, and the compilation graph definition.

+

At the heart of LLVMC is the idea of a compilation graph: vertices in +this graph are tools, and edges represent a transformation path +between two tools (for example, assembly source produced by the +compiler can be transformed into executable code by an assembler). The +compilation graph is basically a list of edges; a special node named +root is used to mark graph entry points.

+

Tool descriptions are represented as property lists: most properties +in the example above should be self-explanatory; the sink property +means that all options lacking an explicit description should be +forwarded to this tool.

+

The LanguageMap associates a language name with a list of suffixes +and is used for deciding which toolchain corresponds to a given input +file.

+

To learn more about LLVMC customization, refer to the reference +manual and plugin source code in the plugins directory.

+
+
+ +Valid CSS + +Valid XHTML 1.0 Transitional + +Mikhail Glushenkov
+LLVM Compiler Infrastructure
+ +Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $ +
+
+ + diff --git a/final/docs/CompilerWriterInfo.html b/final/docs/CompilerWriterInfo.html new file mode 100644 index 00000000000..5d071f73262 --- /dev/null +++ b/final/docs/CompilerWriterInfo.html @@ -0,0 +1,263 @@ + + + + + Architecture/platform information for compiler writers + + + + + +
+ Architecture/platform information for compiler writers +
+ +
+

Note: This document is a work-in-progress. Additions and clarifications + are welcome.

+
+ +
    +
  1. Hardware +
      +
    1. Alpha
    2. +
    3. ARM
    4. +
    5. Itanium
    6. +
    7. MIPS
    8. +
    9. PowerPC
    10. +
    11. SPARC
    12. +
    13. X86
    14. +
    15. Other lists
    16. +
  2. +
  3. Application Binary Interface (ABI) +
      +
    1. Linux
    2. +
    3. OS X
    4. +
  4. +
  5. Miscellaneous resources
  6. +
+ +
+

Compiled by Misha Brukman

+
+ + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
IBM - Official manuals and docs
+ + + + +
Other documents, collections, notes
+ + + + + + + + + + + + +
AMD - Official manuals and docs
+ + + + +
Intel - Official manuals and docs
+ + + + +
Other x86-specific information
+ + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+ Valid CSS + Valid HTML 4.01 + + Misha Brukman
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/DebuggingJITedCode.html b/final/docs/DebuggingJITedCode.html new file mode 100644 index 00000000000..7c998bbe9c1 --- /dev/null +++ b/final/docs/DebuggingJITedCode.html @@ -0,0 +1,152 @@ + + + + Debugging JITed Code With GDB + + + + +
Debugging JITed Code With GDB
+
    +
  1. Example usage
  2. +
  3. Background
  4. +
+
Written by Reid Kleckner
+ + + + +
+ +

In order to debug code JITed by LLVM, you need GDB 7.0 or newer, which is +available on most modern distributions of Linux. The version of GDB that Apple +ships with XCode has been frozen at 6.3 for a while. LLDB may be a better +option for debugging JITed code on Mac OS X. +

+ +

Consider debugging the following code compiled with clang and run through +lli: +

+ +
+#include <stdio.h>
+
+void foo() {
+    printf("%d\n", *(int*)NULL);  // Crash here
+}
+
+void bar() {
+    foo();
+}
+
+void baz() {
+    bar();
+}
+
+int main(int argc, char **argv) {
+    baz();
+}
+
+ +

Here are the commands to run that application under GDB and print the stack +trace at the crash: +

+ +
+# Compile foo.c to bitcode.  You can use either clang or llvm-gcc with this
+# command line.  Both require -fexceptions, or the calls are all marked
+# 'nounwind' which disables DWARF exception handling info.  Custom frontends
+# should avoid adding this attribute to JITed code, since it interferes with
+# DWARF CFA generation at the moment.
+$ clang foo.c -fexceptions -emit-llvm -c -o foo.bc
+
+# Run foo.bc under lli with -jit-emit-debug.  If you built lli in debug mode,
+# -jit-emit-debug defaults to true.
+$ $GDB_INSTALL/gdb --args lli -jit-emit-debug foo.bc
+...
+
+# Run the code.
+(gdb) run
+Starting program: /tmp/gdb/lli -jit-emit-debug foo.bc
+[Thread debugging using libthread_db enabled]
+
+Program received signal SIGSEGV, Segmentation fault.
+0x00007ffff7f55164 in foo ()
+
+# Print the backtrace, this time with symbols instead of ??.
+(gdb) bt
+#0  0x00007ffff7f55164 in foo ()
+#1  0x00007ffff7f550f9 in bar ()
+#2  0x00007ffff7f55099 in baz ()
+#3  0x00007ffff7f5502a in main ()
+#4  0x00000000007c0225 in llvm::JIT::runFunction(llvm::Function*,
+    std::vector<llvm::GenericValue,
+    std::allocator<llvm::GenericValue> > const&) ()
+#5  0x00000000007d6d98 in
+    llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
+    std::vector<std::string,
+    std::allocator<std::string> > const&, char const* const*) ()
+#6  0x00000000004dab76 in main ()
+
+ +

As you can see, GDB can correctly unwind the stack and has the appropriate +function names. +

+
+ + + + +
+ +

Without special runtime support, debugging dynamically generated code with +GDB (as well as most debuggers) can be quite painful. Debuggers generally read +debug information from the object file of the code, but for JITed code, there is +no such file to look for. +

+ +

Depending on the architecture, this can impact the debugging experience in +different ways. For example, on most 32-bit x86 architectures, you can simply +compile with -fno-omit-frame-pointer for GCC and -disable-fp-elim for LLVM. +When GDB creates a backtrace, it can properly unwind the stack, but the stack +frames owned by JITed code have ??'s instead of the appropriate symbol name. +However, on Linux x86_64 in particular, GDB relies on the DWARF call frame +address (CFA) debug information to unwind the stack, so even if you compile +your program to leave the frame pointer untouched, GDB will usually be unable +to unwind the stack past any JITed code stack frames. +

+ +

In order to communicate the necessary debug info to GDB, an interface for +registering JITed code with debuggers has been designed and implemented for +GDB and LLVM. At a high level, whenever LLVM generates new machine code, it +also generates an object file in memory containing the debug information. LLVM +then adds the object file to the global list of object files and calls a special +function (__jit_debug_register_code) marked noinline that GDB knows about. When +GDB attaches to a process, it puts a breakpoint in this function and loads all +of the object files in the global list. When LLVM calls the registration +function, GDB catches the breakpoint signal, loads the new object file from +LLVM's memory, and resumes the execution. In this way, GDB can get the +necessary debug information. +

+ +

At the time of this writing, LLVM only supports architectures that use ELF +object files and it only generates symbols and DWARF CFA information. However, +it would be easy to add more information to the object file, so we don't need to +coordinate with GDB to get better debug information. +

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + Reid Kleckner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/DeveloperPolicy.html b/final/docs/DeveloperPolicy.html new file mode 100644 index 00000000000..ef7ba39397c --- /dev/null +++ b/final/docs/DeveloperPolicy.html @@ -0,0 +1,618 @@ + + + + + LLVM Developer Policy + + + + +
LLVM Developer Policy
+
    +
  1. Introduction
  2. +
  3. Developer Policies +
      +
    1. Stay Informed
    2. +
    3. Making a Patch
    4. +
    5. Code Reviews
    6. +
    7. Code Owners
    8. +
    9. Test Cases
    10. +
    11. Quality
    12. +
    13. Obtaining Commit Access
    14. +
    15. Making a Major Change
    16. +
    17. Incremental Development
    18. +
    19. Attribution of Changes
    20. +
  4. +
  5. Copyright, License, and Patents +
      +
    1. Copyright
    2. +
    3. License
    4. +
    5. Patents
    6. +
  6. +
+
Written by the LLVM Oversight Team
+ + + + +
+

This document contains the LLVM Developer Policy which defines the project's + policy towards developers and their contributions. The intent of this policy + is to eliminate miscommunication, rework, and confusion that might arise from + the distributed nature of LLVM's development. By stating the policy in clear + terms, we hope each developer can know ahead of time what to expect when + making LLVM contributions. This policy covers all llvm.org subprojects, + including Clang, LLDB, etc.

+

This policy is also designed to accomplish the following objectives:

+ +
    +
  1. Attract both users and developers to the LLVM project.
  2. + +
  3. Make life as simple and easy for contributors as possible.
  4. + +
  5. Keep the top of Subversion trees as stable as possible.
  6. +
+ +

This policy is aimed at frequent contributors to LLVM. People interested in + contributing one-off patches can do so in an informal way by sending them to + the + llvm-commits + mailing list and engaging another developer to see it through the + process.

+
+ + + + +
+

This section contains policies that pertain to frequent LLVM developers. We + always welcome one-off patches from people who do not + routinely contribute to LLVM, but we expect more from frequent contributors + to keep the system as efficient as possible for everyone. Frequent LLVM + contributors are expected to meet the following requirements in order for + LLVM to maintain a high standard of quality.

+

+ + + +
+

Developers should stay informed by reading at least the "dev" mailing list + for the projects you are interested in, such as + llvmdev for + LLVM, cfe-dev + for Clang, or lldb-dev + for LLDB. If you are doing anything more than just casual work on LLVM, it + is suggested that you also subscribe to the "commits" mailing list for the + subproject you're interested in, such as + llvm-commits, + cfe-commits, + or lldb-commits. + Reading the "commits" list and paying attention to changes being made by + others is a good way to see what other people are interested in and watching + the flow of the project as a whole.

+ +

We recommend that active developers register an email account with + LLVM Bugzilla and preferably subscribe to + the llvm-bugs + email list to keep track of bugs and enhancements occurring in LLVM. We + really appreciate people who are proactive at catching incoming bugs in their + components and dealing with them promptly.

+
+ + + + +
+

When making a patch for review, the goal is to make it as easy for the + reviewer to read it as possible. As such, we recommend that you:

+ +
    +
  1. Make your patch against the Subversion trunk, not a branch, and not an old + version of LLVM. This makes it easy to apply the patch. For information + on how to check out SVN trunk, please see the Getting Started Guide.
  2. + +
  3. Similarly, patches should be submitted soon after they are generated. Old + patches may not apply correctly if the underlying code changes between the + time the patch was created and the time it is applied.
  4. + +
  5. Patches should be made with svn diff, or similar. If you use + a different tool, make sure it uses the diff -u format and + that it doesn't contain clutter which makes it hard to read.
  6. + +
  7. If you are modifying generated files, such as the top-level + configure script, please separate out those changes into + a separate patch from the rest of your changes.
  8. +
+ +

When sending a patch to a mailing list, it is a good idea to send it as an + attachment to the message, not embedded into the text of the + message. This ensures that your mailer will not mangle the patch when it + sends it (e.g. by making whitespace changes or by wrapping lines).

+ +

For Thunderbird users: Before submitting a patch, please open + Preferences → Advanced → General → Config Editor, + find the key mail.content_disposition_type, and set its value to + 1. Without this setting, Thunderbird sends your attachment using + Content-Disposition: inline rather than Content-Disposition: + attachment. Apple Mail gamely displays such a file inline, making it + difficult to work with for reviewers using that program.

+
+ + + +
+

LLVM has a code review policy. Code review is one way to increase the quality + of software. We generally follow these policies:

+ +
    +
  1. All developers are required to have significant changes reviewed before + they are committed to the repository.
  2. + +
  3. Code reviews are conducted by email, usually on the llvm-commits + list.
  4. + +
  5. Code can be reviewed either before it is committed or after. We expect + major changes to be reviewed before being committed, but smaller changes + (or changes where the developer owns the component) can be reviewed after + commit.
  6. + +
  7. The developer responsible for a code change is also responsible for making + all necessary review-related changes.
  8. + +
  9. Code review can be an iterative process, which continues until the patch + is ready to be committed.
  10. +
+ +

Developers should participate in code reviews as both reviewers and + reviewees. If someone is kind enough to review your code, you should return + the favor for someone else. Note that anyone is welcome to review and give + feedback on a patch, but only people with Subversion write access can approve + it.

+
+ + + +
+ +

The LLVM Project relies on two features of its process to maintain rapid + development in addition to the high quality of its source base: the + combination of code review plus post-commit review for trusted maintainers. + Having both is a great way for the project to take advantage of the fact that + most people do the right thing most of the time, and only commit patches + without pre-commit review when they are confident they are right.

+ +

The trick to this is that the project has to guarantee that all patches that + are committed are reviewed after they go in: you don't want everyone to + assume someone else will review it, allowing the patch to go unreviewed. To + solve this problem, we have a notion of an 'owner' for a piece of the code. + The sole responsibility of a code owner is to ensure that a commit to their + area of the code is appropriately reviewed, either by themself or by someone + else. The current code owners are:

+ +
    +
  1. Evan Cheng: Code generator and all targets.
  2. + +
  3. Greg Clayton: LLDB.
  4. + +
  5. Doug Gregor: Clang Frontend Libraries.
  6. + +
  7. Howard Hinnant: libc++.
  8. + +
  9. Anton Korobeynikov: Exception handling, debug information, and + Windows codegen.
  10. + +
  11. Ted Kremenek: Clang Static Analyzer.
  12. + +
  13. Chris Lattner: Everything not covered by someone else.
  14. + +
  15. Duncan Sands: llvm-gcc 4.2.
  16. +
+ +

Note that code ownership is completely different than reviewers: anyone can + review a piece of code, and we welcome code review from anyone who is + interested. Code owners are the "last line of defense" to guarantee that all + patches that are committed are actually reviewed.

+ +

Being a code owner is a somewhat unglamorous position, but it is incredibly + important for the ongoing success of the project. Because people get busy, + interests change, and unexpected things happen, code ownership is purely + opt-in, and anyone can choose to resign their "title" at any time. For now, + we do not have an official policy on how one gets elected to be a code + owner.

+
+ + + +
+

Developers are required to create test cases for any bugs fixed and any new + features added. Some tips for getting your testcase approved:

+ +
    +
  1. All feature and regression test cases are added to the + llvm/test directory. The appropriate sub-directory should be + selected (see the Testing Guide for + details).
  2. + +
  3. Test cases should be written in LLVM assembly + language unless the feature or regression being tested requires + another language (e.g. the bug being fixed or feature being implemented is + in the llvm-gcc C++ front-end, in which case it must be written in + C++).
  4. + +
  5. Test cases, especially for regressions, should be reduced as much as + possible, by bugpoint or manually. It is + unacceptable to place an entire failing program into llvm/test as + this creates a time-to-test burden on all developers. Please keep + them short.
  6. +
+ +

Note that llvm/test and clang/test are designed for regression and small + feature tests only. More extensive test cases (e.g., entire applications, + benchmarks, etc) + should be added to the llvm-test test suite. The llvm-test suite is + for coverage (correctness, performance, etc) testing, not feature or + regression testing.

+
+ + + +
+

The minimum quality standards that any change must satisfy before being + committed to the main development branch are:

+ +
    +
  1. Code must adhere to the LLVM Coding + Standards.
  2. + +
  3. Code must compile cleanly (no errors, no warnings) on at least one + platform.
  4. + +
  5. Bug fixes and new features should include a + testcase so we know if the fix/feature ever regresses in the + future.
  6. + +
  7. Code must pass the llvm/test test suite.
  8. + +
  9. The code must not cause regressions on a reasonable subset of llvm-test, + where "reasonable" depends on the contributor's judgement and the scope of + the change (more invasive changes require more testing). A reasonable + subset might be something like + "llvm-test/MultiSource/Benchmarks".
  10. +
+ +

Additionally, the committer is responsible for addressing any problems found + in the future that the change is responsible for. For example:

+ +
    +
  • The code should compile cleanly on all supported platforms.
  • + +
  • The changes should not cause any correctness regressions in the + llvm-test suite and must not cause any major performance + regressions.
  • + +
  • The change set should not cause performance or correctness regressions for + the LLVM tools.
  • + +
  • The changes should not cause performance or correctness regressions in + code compiled by LLVM on all applicable targets.
  • + +
  • You are expected to address any bugzilla + bugs that result from your change.
  • +
+ +

We prefer for this to be handled before submission but understand that it + isn't possible to test all of this for every submission. Our build bots and + nightly testing infrastructure normally finds these problems. A good rule of + thumb is to check the nightly testers for regressions the day after your + change. Build bots will directly email you if a group of commits that + included yours caused a failure. You are expected to check the build bot + messages to see if they are your fault and, if so, fix the breakage.

+ +

Commits that violate these quality standards (e.g. are very broken) may be + reverted. This is necessary when the change blocks other developers from + making progress. The developer is welcome to re-commit the change after the + problem has been fixed.

+
+ + + +
+ +

We grant commit access to contributors with a track record of submitting high + quality patches. If you would like commit access, please send an email to + Chris with the following + information:

+ +
    +
  1. The user name you want to commit with, e.g. "hacker".
  2. + +
  3. The full name and email address you want message to llvm-commits to come + from, e.g. "J. Random Hacker <hacker@yoyodyne.com>".
  4. + +
  5. A "password hash" of the password you want to use, e.g. "2ACR96qjUqsyM". + Note that you don't ever tell us what your password is, you just give it + to us in an encrypted form. To get this, run "htpasswd" (a utility that + comes with apache) in crypt mode (often enabled with "-d"), or find a web + page that will do it for you.
  6. +
+ +

Once you've been granted commit access, you should be able to check out an + LLVM tree with an SVN URL of "https://username@llvm.org/..." instead of the + normal anonymous URL of "http://llvm.org/...". The first time you commit + you'll have to type in your password. Note that you may get a warning from + SVN about an untrusted key, you can ignore this. To verify that your commit + access works, please do a test commit (e.g. change a comment or add a blank + line). Your first commit to a repository may require the autogenerated email + to be approved by a mailing list. This is normal, and will be done when + the mailing list owner has time.

+ +

If you have recently been granted commit access, these policies apply:

+ +
    +
  1. You are granted commit-after-approval to all parts of LLVM. To get + approval, submit a patch to + llvm-commits. + When approved you may commit it yourself.
  2. + +
  3. You are allowed to commit patches without approval which you think are + obvious. This is clearly a subjective decision — we simply expect + you to use good judgement. Examples include: fixing build breakage, + reverting obviously broken patches, documentation/comment changes, any + other minor changes.
  4. + +
  5. You are allowed to commit patches without approval to those portions of + LLVM that you have contributed or maintain (i.e., have been assigned + responsibility for), with the proviso that such commits must not break the + build. This is a "trust but verify" policy and commits of this nature are + reviewed after they are committed.
  6. + +
  7. Multiple violations of these policies or a single egregious violation may + cause commit access to be revoked.
  8. +
+ +

In any case, your changes are still subject to code + review (either before or after they are committed, depending on the + nature of the change). You are encouraged to review other peoples' patches + as well, but you aren't required to.

+
+ + + +
+

When a developer begins a major new project with the aim of contributing it + back to LLVM, s/he should inform the community with an email to + the llvmdev + email list, to the extent possible. The reason for this is to: + +

    +
  1. keep the community informed about future changes to LLVM,
  2. + +
  3. avoid duplication of effort by preventing multiple parties working on the + same thing and not knowing about it, and
  4. + +
  5. ensure that any technical issues around the proposed work are discussed + and resolved before any significant work is done.
  6. +
+ +

The design of LLVM is carefully controlled to ensure that all the pieces fit + together well and are as consistent as possible. If you plan to make a major + change to the way LLVM works or want to add a major new extension, it is a + good idea to get consensus with the development community before you start + working on it.

+ +

Once the design of the new feature is finalized, the work itself should be + done as a series of incremental changes, not as a + long-term development branch.

+
+ + + +
+

In the LLVM project, we do all significant changes as a series of incremental + patches. We have a strong dislike for huge changes or long-term development + branches. Long-term development branches have a number of drawbacks:

+ +
    +
  1. Branches must have mainline merged into them periodically. If the branch + development and mainline development occur in the same pieces of code, + resolving merge conflicts can take a lot of time.
  2. + +
  3. Other people in the community tend to ignore work on branches.
  4. + +
  5. Huge changes (produced when a branch is merged back onto mainline) are + extremely difficult to code review.
  6. + +
  7. Branches are not routinely tested by our nightly tester + infrastructure.
  8. + +
  9. Changes developed as monolithic large changes often don't work until the + entire set of changes is done. Breaking it down into a set of smaller + changes increases the odds that any of the work will be committed to the + main repository.
  10. +
+ +

To address these problems, LLVM uses an incremental development style and we + require contributors to follow this practice when making a large/invasive + change. Some tips:

+ +
    +
  • Large/invasive changes usually have a number of secondary changes that are + required before the big change can be made (e.g. API cleanup, etc). These + sorts of changes can often be done before the major change is done, + independently of that work.
  • + +
  • The remaining inter-related work should be decomposed into unrelated sets + of changes if possible. Once this is done, define the first increment and + get consensus on what the end goal of the change is.
  • + +
  • Each change in the set can be stand alone (e.g. to fix a bug), or part of + a planned series of changes that works towards the development goal.
  • + +
  • Each change should be kept as small as possible. This simplifies your work + (into a logical progression), simplifies code review and reduces the + chance that you will get negative feedback on the change. Small increments + also facilitate the maintenance of a high quality code base.
  • + +
  • Often, an independent precursor to a big change is to add a new API and + slowly migrate clients to use the new API. Each change to use the new API + is often "obvious" and can be committed without review. Once the new API + is in place and used, it is much easier to replace the underlying + implementation of the API. This implementation change is logically + separate from the API change.
  • +
+ +

If you are interested in making a large change, and this scares you, please + make sure to first discuss the change/gather consensus + then ask about the best way to go about making the change.

+
+ + + +
+

We believe in correct attribution of contributions to their contributors. + However, we do not want the source code to be littered with random + attributions "this code written by J. Random Hacker" (this is noisy and + distracting). In practice, the revision control system keeps a perfect + history of who changed what, and the CREDITS.txt file describes higher-level + contributions. If you commit a patch for someone else, please say "patch + contributed by J. Random Hacker!" in the commit message.

+ +

Overall, please do not add contributor names to the source code.

+
+ + + + + +
+

This section addresses the issues of copyright, license and patents for the + LLVM project. Currently, the University of Illinois is the LLVM copyright + holder and the terms of its license to LLVM users and developers is the + University of + Illinois/NCSA Open Source License.

+ +
+

NOTE: This section deals with + legal matters but does not provide legal advice. We are not lawyers, please + seek legal counsel from an attorney.

+
+
+ + + +
+ +

The LLVM project does not require copyright assignments, which means that the + copyright for the code in the project is held by its respective contributors + who have each agreed to release their contributed code under the terms of the + LLVM License.

+ +

An implication of this is that the LLVM license is unlikely to ever change: + changing it would require tracking down all the contributors to LLVM and + getting them to agree that a license change is acceptable for their + contribution. Since there are no plans to change the license, this is not a + cause for concern.

+ +

As a contributor to the project, this means that you (or your company) retain + ownership of the code you contribute, that it cannot be used in a way that + contradicts the license (which is a liberal BSD-style license), and that the + license for your contributions won't change without your approval in the + future.

+ +
+ + + +
+

We intend to keep LLVM perpetually open source and to use a liberal open + source license. All of the code in LLVM is available under the + University of + Illinois/NCSA Open Source License, which boils down to this:

+ +
    +
  • You can freely distribute LLVM.
  • +
  • You must retain the copyright notice if you redistribute LLVM.
  • +
  • Binaries derived from LLVM must reproduce the copyright notice (e.g. in an + included readme file).
  • +
  • You can't use our names to promote your LLVM derived products.
  • +
  • There's no warranty on LLVM at all.
  • +
+ +

We believe this fosters the widest adoption of LLVM because it allows + commercial products to be derived from LLVM with few restrictions and + without a requirement for making any derived works also open source (i.e. + LLVM's license is not a "copyleft" license like the GPL). We suggest that you + read the License + if further clarification is needed.

+ +

In addition to the UIUC license, the runtime library components of LLVM + (compiler_rt and libc++) are also licensed under the MIT license, + which does not contain the binary redistribution clause. As a user of these + runtime libraries, it means that you can choose to use the code under either + license (and thus don't need the binary redistribution clause), and as a + contributor to the code that you agree that any contributions to these + libraries be licensed under both licenses. We feel that this is important + for runtime libraries, because they are implicitly linked into applications + and therefore should not subject those applications to the binary + redistribution clause. This also means that it is ok to move code from (e.g.) + libc++ to the LLVM core without concern, but that code cannot be moved from + the LLVM core to libc++ without the copyright owner's permission. +

+ +

Note that the LLVM Project does distribute llvm-gcc, which is GPL. + This means that anything "linked" into llvm-gcc must itself be compatible + with the GPL, and must be releasable under the terms of the GPL. This + implies that any code linked into llvm-gcc and distributed to others may + be subject to the viral aspects of the GPL (for example, a proprietary + code generator linked into llvm-gcc must be made available under the GPL). + This is not a problem for code already distributed under a more liberal + license (like the UIUC license), and does not affect code generated by + llvm-gcc. It may be a problem if you intend to base commercial development + on llvm-gcc without redistributing your source code.

+ +

We have no plans to change the license of LLVM. If you have questions or + comments about the license, please contact the + LLVM Developer's Mailing List.

+
+ + + +
+

To the best of our knowledge, LLVM does not infringe on any patents (we have + actually removed code from LLVM in the past that was found to infringe). + Having code in LLVM that infringes on patents would violate an important goal + of the project by making it hard or impossible to reuse the code for + arbitrary purposes (including commercial use).

+ +

When contributing code, we expect contributors to notify us of any potential + for patent-related trouble with their changes. If you or your employer own + the rights to a patent and would like to contribute code to LLVM that relies + on it, we require that the copyright owner sign an agreement that allows any + other user of LLVM to freely use your patent. Please contact + the oversight group for more + details.

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + Written by the + LLVM Oversight Group
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/ExceptionHandling.html b/final/docs/ExceptionHandling.html new file mode 100644 index 00000000000..d597ffb3c8b --- /dev/null +++ b/final/docs/ExceptionHandling.html @@ -0,0 +1,644 @@ + + + + Exception Handling in LLVM + + + + + + + +
Exception Handling in LLVM
+ + + + +
+ +
+ +
+

Written by Jim Laskey

+
+ + + + + + +
+ +

This document is the central repository for all information pertaining to + exception handling in LLVM. It describes the format that LLVM exception + handling information takes, which is useful for those interested in creating + front-ends or dealing directly with the information. Further, this document + provides specific examples of what exception handling information is used for + in C/C++.

+ +
+ + + + +
+ +

Exception handling for most programming languages is designed to recover from + conditions that rarely occur during general use of an application. To that + end, exception handling should not interfere with the main flow of an + application's algorithm by performing checkpointing tasks, such as saving the + current pc or register state.

+ +

The Itanium ABI Exception Handling Specification defines a methodology for + providing outlying data in the form of exception tables without inlining + speculative exception handling code in the flow of an application's main + algorithm. Thus, the specification is said to add "zero-cost" to the normal + execution of an application.

+ +

A more complete description of the Itanium ABI exception handling runtime + support of can be found at + Itanium C++ ABI: + Exception Handling. A description of the exception frame format can be + found at + Exception + Frames, with details of the DWARF 3 specification at + DWARF 3 Standard. + A description for the C++ exception table formats can be found at + Exception Handling + Tables.

+ +
+ + + + +
+ +

Setjmp/Longjmp (SJLJ) based exception handling uses LLVM intrinsics + llvm.eh.sjlj.setjmp and + llvm.eh.sjlj.longjmp to + handle control flow for exception handling.

+ +

For each function which does exception processing, be it try/catch blocks + or cleanups, that function registers itself on a global frame list. When + exceptions are being unwound, the runtime uses this list to identify which + functions need processing.

+ +

Landing pad selection is encoded in the call site entry of the function + context. The runtime returns to the function via + llvm.eh.sjlj.longjmp, where + a switch table transfers control to the appropriate landing pad based on + the index stored in the function context.

+ +

In contrast to DWARF exception handling, which encodes exception regions + and frame information in out-of-line tables, SJLJ exception handling + builds and removes the unwind frame context at runtime. This results in + faster exception handling at the expense of slower execution when no + exceptions are thrown. As exceptions are, by their nature, intended for + uncommon code paths, DWARF exception handling is generally preferred to + SJLJ.

+
+ + + + +
+ +

When an exception is thrown in LLVM code, the runtime does its best to find a + handler suited to processing the circumstance.

+ +

The runtime first attempts to find an exception frame corresponding to + the function where the exception was thrown. If the programming language + (e.g. C++) supports exception handling, the exception frame contains a + reference to an exception table describing how to process the exception. If + the language (e.g. C) does not support exception handling, or if the + exception needs to be forwarded to a prior activation, the exception frame + contains information about how to unwind the current activation and restore + the state of the prior activation. This process is repeated until the + exception is handled. If the exception is not handled and no activations + remain, then the application is terminated with an appropriate error + message.

+ +

Because different programming languages have different behaviors when + handling exceptions, the exception handling ABI provides a mechanism for + supplying personalities. An exception handling personality is defined + by way of a personality function (e.g. __gxx_personality_v0 + in C++), which receives the context of the exception, an exception + structure containing the exception object type and value, and a reference + to the exception table for the current function. The personality function + for the current compile unit is specified in a common exception + frame.

+ +

The organization of an exception table is language dependent. For C++, an + exception table is organized as a series of code ranges defining what to do + if an exception occurs in that range. Typically, the information associated + with a range defines which types of exception objects (using C++ type + info) that are handled in that range, and an associated action that + should take place. Actions typically pass control to a landing + pad.

+ +

A landing pad corresponds to the code found in the catch portion of + a try/catch sequence. When execution resumes at a landing + pad, it receives the exception structure and a selector corresponding to + the type of exception thrown. The selector is then used to determine + which catch should actually process the exception.

+ +
+ + + + +
+ +

At the time of this writing, only C++ exception handling support is available + in LLVM. So the remainder of this document will be somewhat C++-centric.

+ +

From the C++ developers perspective, exceptions are defined in terms of the + throw and try/catch statements. In this section + we will describe the implementation of LLVM exception handling in terms of + C++ examples.

+ +
+ + +
+ Throw +
+ +
+ +

Languages that support exception handling typically provide a throw + operation to initiate the exception process. Internally, a throw operation + breaks down into two steps. First, a request is made to allocate exception + space for an exception structure. This structure needs to survive beyond the + current activation. This structure will contain the type and value of the + object being thrown. Second, a call is made to the runtime to raise the + exception, passing the exception structure as an argument.

+ +

In C++, the allocation of the exception structure is done by + the __cxa_allocate_exception runtime function. The exception + raising is handled by __cxa_throw. The type of the exception is + represented using a C++ RTTI structure.

+ +
+ + + + +
+ +

A call within the scope of a try statement can potentially raise an + exception. In those circumstances, the LLVM C++ front-end replaces the call + with an invoke instruction. Unlike a call, the invoke has + two potential continuation points: where to continue when the call succeeds + as per normal; and where to continue if the call raises an exception, either + by a throw or the unwinding of a throw.

+ +

The term used to define a the place where an invoke continues after + an exception is called a landing pad. LLVM landing pads are + conceptually alternative function entry points where an exception structure + reference and a type info index are passed in as arguments. The landing pad + saves the exception structure reference and then proceeds to select the catch + block that corresponds to the type info of the exception object.

+ +

Two LLVM intrinsic functions are used to convey information about the landing + pad to the back end.

+ +
    +
  1. llvm.eh.exception takes no + arguments and returns a pointer to the exception structure. This only + returns a sensible value if called after an invoke has branched + to a landing pad. Due to code generation limitations, it must currently + be called in the landing pad itself.
  2. + +
  3. llvm.eh.selector takes a minimum + of three arguments. The first argument is the reference to the exception + structure. The second argument is a reference to the personality function + to be used for this try/catch sequence. Each of the + remaining arguments is either a reference to the type info for + a catch statement, a filter + expression, or the number zero (0) representing + a cleanup. The exception is tested against the + arguments sequentially from first to last. The result of + the llvm.eh.selector is a + positive number if the exception matched a type info, a negative number if + it matched a filter, and zero if it matched a cleanup. If nothing is + matched, the behaviour of the program + is undefined. This only returns a sensible + value if called after an invoke has branched to a landing pad. + Due to codegen limitations, it must currently be called in the landing pad + itself. If a type info matched, then the selector value is the index of + the type info in the exception table, which can be obtained using the + llvm.eh.typeid.for + intrinsic.
  4. +
+ +

Once the landing pad has the type info selector, the code branches to the + code for the first catch. The catch then checks the value of the type info + selector against the index of type info for that catch. Since the type info + index is not known until all the type info have been gathered in the backend, + the catch code will call the + llvm.eh.typeid.for intrinsic + to determine the index for a given type info. If the catch fails to match + the selector then control is passed on to the next catch. Note: Since the + landing pad will not be used if there is no match in the list of type info on + the call to llvm.eh.selector, then + neither the last catch nor catch all need to perform the check + against the selector.

+ +

Finally, the entry and exit of catch code is bracketed with calls + to __cxa_begin_catch and __cxa_end_catch.

+ +
    +
  • __cxa_begin_catch takes a exception structure reference as an + argument and returns the value of the exception object.
  • + +
  • __cxa_end_catch takes no arguments. This function:

    +
      +
    1. Locates the most recently caught exception and decrements its handler + count,
    2. +
    3. Removes the exception from the "caught" stack if the handler count + goes to zero, and
    4. +
    5. Destroys the exception if the handler count goes to zero, and the + exception was not re-thrown by throw.
    6. +
    +

    Note: a rethrow from within the catch may replace this call with + a __cxa_rethrow.

  • +
+ +
+ + + + +
+ +

To handle destructors and cleanups in try code, control may not run + directly from a landing pad to the first catch. Control may actually flow + from the landing pad to clean up code and then to the first catch. Since the + required clean up for each invoke in a try may be different + (e.g. intervening constructor), there may be several landing pads for a given + try. If cleanups need to be run, an i32 0 should be passed as the + last llvm.eh.selector argument. + However, when using DWARF exception handling with C++, a i8* null + must be passed instead.

+ +
+ + + + +
+ +

C++ allows the specification of which exception types can be thrown from a + function. To represent this a top level landing pad may exist to filter out + invalid types. To express this in LLVM code the landing pad will + call llvm.eh.selector. The + arguments are a reference to the exception structure, a reference to the + personality function, the length of the filter expression (the number of type + infos plus one), followed by the type infos themselves. + llvm.eh.selector will return a + negative value if the exception does not match any of the type infos. If no + match is found then a call to __cxa_call_unexpected should be made, + otherwise _Unwind_Resume. Each of these functions requires a + reference to the exception structure. Note that the most general form of an + llvm.eh.selector call can contain + any number of type infos, filter expressions and cleanups (though having more + than one cleanup is pointless). The LLVM C++ front-end can generate such + llvm.eh.selector calls due to + inlining creating nested exception handling scopes.

+ +
+ + + + +
+ +

The semantics of the invoke instruction require that any exception that + unwinds through an invoke call should result in a branch to the invoke's + unwind label. However such a branch will only happen if the + llvm.eh.selector matches. Thus in + order to ensure correct operation, the front-end must only generate + llvm.eh.selector calls that are + guaranteed to always match whatever exception unwinds through the invoke. + For most languages it is enough to pass zero, indicating the presence of + a cleanup, as the + last llvm.eh.selector argument. + However for C++ this is not sufficient, because the C++ personality function + will terminate the program if it detects that unwinding the exception only + results in matches with cleanups. For C++ a null i8* should be + passed as the last llvm.eh.selector + argument instead. This is interpreted as a catch-all by the C++ personality + function, and will always match.

+ +
+ + + + +
+ +

LLVM uses several intrinsic functions (name prefixed with "llvm.eh") to + provide exception handling information at various points in generated + code.

+ +
+ + + + +
+ +
+  i8* %llvm.eh.exception()
+
+ +

This intrinsic returns a pointer to the exception structure.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.selector(i8*, i8*, ...)
+
+ +

This intrinsic is used to compare the exception with the given type infos, + filters and cleanups.

+ +

llvm.eh.selector takes a minimum of + three arguments. The first argument is the reference to the exception + structure. The second argument is a reference to the personality function to + be used for this try catch sequence. Each of the remaining arguments is + either a reference to the type info for a catch statement, + a filter expression, or the number zero + representing a cleanup. The exception is tested + against the arguments sequentially from first to last. The result of + the llvm.eh.selector is a positive + number if the exception matched a type info, a negative number if it matched + a filter, and zero if it matched a cleanup. If nothing is matched, the + behaviour of the program is undefined. If a type + info matched then the selector value is the index of the type info in the + exception table, which can be obtained using the + llvm.eh.typeid.for intrinsic.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.typeid.for(i8*)
+
+ +

This intrinsic returns the type info index in the exception table of the + current function. This value can be used to compare against the result + of llvm.eh.selector. The single + argument is a reference to a type info.

+ +
+ + + + +
+ +
+  i32 %llvm.eh.sjlj.setjmp(i8*)
+
+ +

The SJLJ exception handling uses this intrinsic to force register saving for + the current function and to store the address of the following instruction + for use as a destination address by + llvm.eh.sjlj.longjmp. The buffer format and the overall + functioning of this intrinsic is compatible with the GCC + __builtin_setjmp implementation, allowing code built with the + two compilers to interoperate.

+ +

The single parameter is a pointer to a five word buffer in which the calling + context is saved. The front end places the frame pointer in the first word, + and the target implementation of this intrinsic should place the destination + address for a + llvm.eh.sjlj.longjmp in the + second word. The following three words are available for use in a + target-specific manner.

+ +
+ + + + +
+ +
+  void %llvm.eh.sjlj.setjmp(i8*)
+
+ +

The llvm.eh.sjlj.longjmp + intrinsic is used to implement __builtin_longjmp() for SJLJ + style exception handling. The single parameter is a pointer to a + buffer populated by + llvm.eh.sjlj.setjmp. The frame pointer and stack pointer + are restored from the buffer, then control is transfered to the + destination address.

+ +
+ + + +
+ +
+  i8* %llvm.eh.sjlj.lsda()
+
+ +

Used for SJLJ based exception handling, the + llvm.eh.sjlj.lsda intrinsic returns the address of the Language + Specific Data Area (LSDA) for the current function. The SJLJ front-end code + stores this address in the exception handling function context for use by the + runtime.

+ +
+ + + + +
+ +
+  void %llvm.eh.sjlj.callsite(i32)
+
+ +

For SJLJ based exception handling, the + llvm.eh.sjlj.callsite intrinsic identifies the callsite value + associated with the following invoke instruction. This is used to ensure + that landing pad entries in the LSDA are generated in the matching order.

+ +
+ + + + +
+ +
+  void %llvm.eh.sjlj.dispatchsetup(i32)
+
+ +

For SJLJ based exception handling, the + llvm.eh.sjlj.dispatchsetup intrinsic is used by targets to do + any unwind-edge setup they need. By default, no action is taken.

+ +
+ + + + +
+ +

There are two tables that are used by the exception handling runtime to + determine which actions should take place when an exception is thrown.

+ +
+ + + + +
+ +

An exception handling frame eh_frame is very similar to the unwind + frame used by dwarf debug info. The frame contains all the information + necessary to tear down the current frame and restore the state of the prior + frame. There is an exception handling frame for each function in a compile + unit, plus a common exception handling frame that defines information common + to all functions in the unit.

+ +

Todo - Table details here.

+ +
+ + + + +
+ +

An exception table contains information about what actions to take when an + exception is thrown in a particular part of a function's code. There is one + exception table per function except leaf routines and functions that have + only calls to non-throwing functions will not need an exception table.

+ +

Todo - Table details here.

+ +
+ + +
+ ToDo +
+ +
+ +
    + +
  1. Testing/Testing/Testing.
  2. + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/ExtendedIntegerResults.txt b/final/docs/ExtendedIntegerResults.txt new file mode 100644 index 00000000000..44e9fbf0e76 --- /dev/null +++ b/final/docs/ExtendedIntegerResults.txt @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// Representing sign/zero extension of function results +//===----------------------------------------------------------------------===// + +Mar 25, 2009 - Initial Revision + +Most ABIs specify that functions which return small integers do so in a +specific integer GPR. This is an efficient way to go, but raises the question: +if the returned value is smaller than the register, what do the high bits hold? + +There are three (interesting) possible answers: undefined, zero extended, or +sign extended. The number of bits in question depends on the data-type that +the front-end is referencing (typically i1/i8/i16/i32). + +Knowing the answer to this is important for two reasons: 1) we want to be able +to implement the ABI correctly. If we need to sign extend the result according +to the ABI, we really really do need to do this to preserve correctness. 2) +this information is often useful for optimization purposes, and we want the +mid-level optimizers to be able to process this (e.g. eliminate redundant +extensions). + +For example, lets pretend that X86 requires the caller to properly extend the +result of a return (I'm not sure this is the case, but the argument doesn't +depend on this). Given this, we should compile this: + +int a(); +short b() { return a(); } + +into: + +_b: + subl $12, %esp + call L_a$stub + addl $12, %esp + cwtl + ret + +An optimization example is that we should be able to eliminate the explicit +sign extension in this example: + +short y(); +int z() { + return ((int)y() << 16) >> 16; +} + +_z: + subl $12, %esp + call _y + ;; movswl %ax, %eax -> not needed because eax is already sext'd + addl $12, %esp + ret + +//===----------------------------------------------------------------------===// +// What we have right now. +//===----------------------------------------------------------------------===// + +Currently, these sorts of things are modelled by compiling a function to return +the small type and a signext/zeroext marker is used. For example, we compile +Z into: + +define i32 @z() nounwind { +entry: + %0 = tail call signext i16 (...)* @y() nounwind + %1 = sext i16 %0 to i32 + ret i32 %1 +} + +and b into: + +define signext i16 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind ; [#uses=1] + %retval12 = trunc i32 %0 to i16 ; [#uses=1] + ret i16 %retval12 +} + +This has some problems: 1) the actual precise semantics are really poorly +defined (see PR3779). 2) some targets might want the caller to extend, some +might want the callee to extend 3) the mid-level optimizer doesn't know the +size of the GPR, so it doesn't know that %0 is sign extended up to 32-bits +here, and even if it did, it could not eliminate the sext. 4) the code +generator has historically assumed that the result is extended to i32, which is +a problem on PIC16 (and is also probably wrong on alpha and other 64-bit +targets). + +//===----------------------------------------------------------------------===// +// The proposal +//===----------------------------------------------------------------------===// + +I suggest that we have the front-end fully lower out the ABI issues here to +LLVM IR. This makes it 100% explicit what is going on and means that there is +no cause for confusion. For example, the cases above should compile into: + +define i32 @z() nounwind { +entry: + %0 = tail call i32 (...)* @y() nounwind + %1 = trunc i32 %0 to i16 + %2 = sext i16 %1 to i32 + ret i32 %2 +} +define i32 @b() nounwind { +entry: + %0 = tail call i32 (...)* @a() nounwind + %retval12 = trunc i32 %0 to i16 + %tmp = sext i16 %retval12 to i32 + ret i32 %tmp +} + +In this model, no functions will return an i1/i8/i16 (and on a x86-64 target +that extends results to i64, no i32). This solves the ambiguity issue, allows us +to fully describe all possible ABIs, and now allows the optimizers to reason +about and eliminate these extensions. + +The one thing that is missing is the ability for the front-end and optimizer to +specify/infer the guarantees provided by the ABI to allow other optimizations. +For example, in the y/z case, since y is known to return a sign extended value, +the trunc/sext in z should be eliminable. + +This can be done by introducing new sext/zext attributes which mean "I know +that the result of the function is sign extended at least N bits. Given this, +and given that it is stuck on the y function, the mid-level optimizer could +easily eliminate the extensions etc with existing functionality. + +The major disadvantage of doing this sort of thing is that it makes the ABI +lowering stuff even more explicit in the front-end, and that we would like to +eventually move to having the code generator do more of this work. However, +the sad truth of the matter is that this is a) unlikely to happen anytime in +the near future, and b) this is no worse than we have now with the existing +attributes. + +C compilers fundamentally have to reason about the target in many ways. +This is ugly and horrible, but a fact of life. + diff --git a/final/docs/ExtendingLLVM.html b/final/docs/ExtendingLLVM.html new file mode 100644 index 00000000000..647fa01d53b --- /dev/null +++ b/final/docs/ExtendingLLVM.html @@ -0,0 +1,391 @@ + + + + Extending LLVM: Adding instructions, intrinsics, types, etc. + + + + + +
+ Extending LLVM: Adding instructions, intrinsics, types, etc. +
+ +
    +
  1. Introduction and Warning
  2. +
  3. Adding a new intrinsic function
  4. +
  5. Adding a new instruction
  6. +
  7. Adding a new SelectionDAG node
  8. +
  9. Adding a new type +
      +
    1. Adding a new fundamental type
    2. +
    3. Adding a new derived type
    4. +
  10. +
+ +
+

Written by Misha Brukman, + Brad Jones, Nate Begeman, + and Chris Lattner

+
+ + + + + +
+ +

During the course of using LLVM, you may wish to customize it for your +research project or for experimentation. At this point, you may realize that +you need to add something to LLVM, whether it be a new fundamental type, a new +intrinsic function, or a whole new instruction.

+ +

When you come to this realization, stop and think. Do you really need to +extend LLVM? Is it a new fundamental capability that LLVM does not support at +its current incarnation or can it be synthesized from already pre-existing LLVM +elements? If you are not sure, ask on the LLVM-dev list. The +reason is that extending LLVM will get involved as you need to update all the +different passes that you intend to use with your extension, and there are +many LLVM analyses and transformations, so it may be quite a bit of +work.

+ +

Adding an intrinsic function is far easier than +adding an instruction, and is transparent to optimization passes. If your added +functionality can be expressed as a +function call, an intrinsic function is the method of choice for LLVM +extension.

+ +

Before you invest a significant amount of effort into a non-trivial +extension, ask on the list if what you are +looking to do can be done with already-existing infrastructure, or if maybe +someone else is already working on it. You will save yourself a lot of time and +effort by doing so.

+ +
+ + + + + +
+ +

Adding a new intrinsic function to LLVM is much easier than adding a new +instruction. Almost all extensions to LLVM should start as an intrinsic +function and then be turned into an instruction if warranted.

+ +
    +
  1. llvm/docs/LangRef.html: + Document the intrinsic. Decide whether it is code generator specific and + what the restrictions are. Talk to other people about it so that you are + sure it's a good idea.
  2. + +
  3. llvm/include/llvm/Intrinsics*.td: + Add an entry for your intrinsic. Describe its memory access characteristics + for optimization (this controls whether it will be DCE'd, CSE'd, etc). Note + that any intrinsic using the llvm_int_ty type for an argument will + be deemed by tblgen as overloaded and the corresponding suffix + will be required on the intrinsic's name.
  4. + +
  5. llvm/lib/Analysis/ConstantFolding.cpp: If it is possible to + constant fold your intrinsic, add support to it in the + canConstantFoldCallTo and ConstantFoldCall functions.
  6. + +
  7. llvm/test/Regression/*: Add test cases for your test cases to the + test suite
  8. +
+ +

Once the intrinsic has been added to the system, you must add code generator +support for it. Generally you must do the following steps:

+ +
+
Add support to the C backend in lib/Target/CBackend/
+ +
Depending on the intrinsic, there are a few ways to implement this. For + most intrinsics, it makes sense to add code to lower your intrinsic in + LowerIntrinsicCall in lib/CodeGen/IntrinsicLowering.cpp. + Second, if it makes sense to lower the intrinsic to an expanded sequence of + C code in all cases, just emit the expansion in visitCallInst in + Writer.cpp. If the intrinsic has some way to express it with GCC + (or any other compiler) extensions, it can be conditionally supported based + on the compiler compiling the CBE output (see llvm.prefetch for an + example). Third, if the intrinsic really has no way to be lowered, just + have the code generator emit code that prints an error message and calls + abort if executed.
+ +
Add support to the .td file for the target(s) of your choice in + lib/Target/*/*.td.
+ +
This is usually a matter of adding a pattern to the .td file that matches + the intrinsic, though it may obviously require adding the instructions you + want to generate as well. There are lots of examples in the PowerPC and X86 + backend to follow.
+
+ +
+ + + + + +
+ +

As with intrinsics, adding a new SelectionDAG node to LLVM is much easier +than adding a new instruction. New nodes are often added to help represent +instructions common to many targets. These nodes often map to an LLVM +instruction (add, sub) or intrinsic (byteswap, population count). In other +cases, new nodes have been added to allow many targets to perform a common task +(converting between floating point and integer representation) or capture more +complicated behavior in a single node (rotate).

+ +
    +
  1. include/llvm/CodeGen/SelectionDAGNodes.h: + Add an enum value for the new SelectionDAG node.
  2. +
  3. lib/CodeGen/SelectionDAG/SelectionDAG.cpp: + Add code to print the node to getOperationName. If your new node + can be evaluated at compile time when given constant arguments (such as an + add of a constant with another constant), find the getNode method + that takes the appropriate number of arguments, and add a case for your node + to the switch statement that performs constant folding for nodes that take + the same number of arguments as your new node.
  4. +
  5. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + Add code to legalize, + promote, and expand the node as necessary. At a minimum, you will need + to add a case statement for your node in LegalizeOp which calls + LegalizeOp on the node's operands, and returns a new node if any of the + operands changed as a result of being legalized. It is likely that not all + targets supported by the SelectionDAG framework will natively support the + new node. In this case, you must also add code in your node's case + statement in LegalizeOp to Expand your node into simpler, legal + operations. The case for ISD::UREM for expanding a remainder into + a divide, multiply, and a subtract is a good example.
  6. +
  7. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + If targets may support the new node being added only at certain sizes, you + will also need to add code to your node's case statement in + LegalizeOp to Promote your node's operands to a larger size, and + perform the correct operation. You will also need to add code to + PromoteOp to do this as well. For a good example, see + ISD::BSWAP, + which promotes its operand to a wider size, performs the byteswap, and then + shifts the correct bytes right to emulate the narrower byteswap in the + wider type.
  8. +
  9. lib/CodeGen/SelectionDAG/LegalizeDAG.cpp: + Add a case for your node in ExpandOp to teach the legalizer how to + perform the action represented by the new node on a value that has been + split into high and low halves. This case will be used to support your + node with a 64 bit operand on a 32 bit target.
  10. +
  11. lib/CodeGen/SelectionDAG/DAGCombiner.cpp: + If your node can be combined with itself, or other existing nodes in a + peephole-like fashion, add a visit function for it, and call that function + from . There are several good examples for simple combines you + can do; visitFABS and visitSRL are good starting places. +
  12. +
  13. lib/Target/PowerPC/PPCISelLowering.cpp: + Each target has an implementation of the TargetLowering class, + usually in its own file (although some targets include it in the same + file as the DAGToDAGISel). The default behavior for a target is to + assume that your new node is legal for all types that are legal for + that target. If this target does not natively support your node, then + tell the target to either Promote it (if it is supported at a larger + type) or Expand it. This will cause the code you wrote in + LegalizeOp above to decompose your new node into other legal + nodes for this target.
  14. +
  15. lib/Target/TargetSelectionDAG.td: + Most current targets supported by LLVM generate code using the DAGToDAG + method, where SelectionDAG nodes are pattern matched to target-specific + nodes, which represent individual instructions. In order for the targets + to match an instruction to your new node, you must add a def for that node + to the list in this file, with the appropriate type constraints. Look at + add, bswap, and fadd for examples.
  16. +
  17. lib/Target/PowerPC/PPCInstrInfo.td: + Each target has a tablegen file that describes the target's instruction + set. For targets that use the DAGToDAG instruction selection framework, + add a pattern for your new node that uses one or more target nodes. + Documentation for this is a bit sparse right now, but there are several + decent examples. See the patterns for rotl in + PPCInstrInfo.td.
  18. +
  19. TODO: document complex patterns.
  20. +
  21. llvm/test/Regression/CodeGen/*: Add test cases for your new node + to the test suite. llvm/test/Regression/CodeGen/X86/bswap.ll is + a good example.
  22. +
+ +
+ + + + + +
+ +

WARNING: adding instructions changes the bitcode +format, and it will take some effort to maintain compatibility with +the previous version. Only add an instruction if it is absolutely +necessary.

+ +
    + +
  1. llvm/include/llvm/Instruction.def: + add a number for your instruction and an enum name
  2. + +
  3. llvm/include/llvm/Instructions.h: + add a definition for the class that will represent your instruction
  4. + +
  5. llvm/include/llvm/Support/InstVisitor.h: + add a prototype for a visitor to your new instruction type
  6. + +
  7. llvm/lib/AsmParser/Lexer.l: + add a new token to parse your instruction from assembly text file
  8. + +
  9. llvm/lib/AsmParser/llvmAsmParser.y: + add the grammar on how your instruction can be read and what it will + construct as a result
  10. + +
  11. llvm/lib/Bitcode/Reader/Reader.cpp: + add a case for your instruction and how it will be parsed from bitcode
  12. + +
  13. llvm/lib/VMCore/Instruction.cpp: + add a case for how your instruction will be printed out to assembly
  14. + +
  15. llvm/lib/VMCore/Instructions.cpp: + implement the class you defined in + llvm/include/llvm/Instructions.h
  16. + +
  17. Test your instruction
  18. + +
  19. llvm/lib/Target/*: + Add support for your instruction to code generators, or add a lowering + pass.
  20. + +
  21. llvm/test/Regression/*: add your test cases to the test suite.
  22. + +
+ +

Also, you need to implement (or modify) any analyses or passes that you want +to understand this new instruction.

+ +
+ + + + + + +
+ +

WARNING: adding new types changes the bitcode +format, and will break compatibility with currently-existing LLVM +installations. Only add new types if it is absolutely necessary.

+ +
+ + + + +
+ +
    + +
  1. llvm/include/llvm/Type.h: + add enum for the new type; add static Type* for this type
  2. + +
  3. llvm/lib/VMCore/Type.cpp: + add mapping from TypeID => Type*; + initialize the static Type*
  4. + +
  5. llvm/lib/AsmReader/Lexer.l: + add ability to parse in the type from text assembly
  6. + +
  7. llvm/lib/AsmReader/llvmAsmParser.y: + add a token for that type
  8. + +
+ +
+ + + + +
+ +
    +
  1. llvm/include/llvm/Type.h: + add enum for the new type; add a forward declaration of the type + also
  2. + +
  3. llvm/include/llvm/DerivedTypes.h: + add new class to represent new class in the hierarchy; add forward + declaration to the TypeMap value type
  4. + +
  5. llvm/lib/VMCore/Type.cpp: + add support for derived type to: +
    +
    +std::string getTypeDescription(const Type &Ty,
    +  std::vector<const Type*> &TypeStack)
    +bool TypesEqual(const Type *Ty, const Type *Ty2,
    +  std::map<const Type*, const Type*> & EqTypes)
    +
    +
    + add necessary member functions for type, and factory methods
  6. + +
  7. llvm/lib/AsmReader/Lexer.l: + add ability to parse in the type from text assembly
  8. + +
  9. llvm/lib/BitCode/Writer/Writer.cpp: + modify void BitcodeWriter::outputType(const Type *T) to serialize + your type
  10. + +
  11. llvm/lib/BitCode/Reader/Reader.cpp: + modify const Type *BitcodeReader::ParseType() to read your data + type
  12. + +
  13. llvm/lib/VMCore/AsmWriter.cpp: + modify +
    +
    +void calcTypeName(const Type *Ty,
    +                  std::vector<const Type*> &TypeStack,
    +                  std::map<const Type*,std::string> &TypeNames,
    +                  std::string & Result)
    +
    +
    + to output the new derived type +
  14. + + +
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/FAQ.html b/final/docs/FAQ.html new file mode 100644 index 00000000000..88c76767bd4 --- /dev/null +++ b/final/docs/FAQ.html @@ -0,0 +1,938 @@ + + + + + LLVM: Frequently Asked Questions + + + + +
+ LLVM: Frequently Asked Questions +
+ +
    +
  1. License +
      +
    1. Why are the LLVM source code and the front-end distributed under + different licenses?
    2. + +
    3. Does the University of Illinois Open Source License really qualify as an + "open source" license?
    4. + +
    5. Can I modify LLVM source code and redistribute the modified source?
    6. + +
    7. Can I modify LLVM source code and redistribute binaries or other tools + based on it, without redistributing the source?
    8. +
  2. + +
  3. Source code +
      +
    1. In what language is LLVM written?
    2. + +
    3. How portable is the LLVM source code?
    4. +
  4. + +
  5. Build Problems +
      +
    1. When I run configure, it finds the wrong C compiler.
    2. + +
    3. The configure script finds the right C compiler, but it uses + the LLVM linker from a previous build. What do I do?
    4. + +
    5. When creating a dynamic library, I get a strange GLIBC error.
    6. + +
    7. I've updated my source tree from Subversion, and now my build is trying + to use a file/directory that doesn't exist.
    8. + +
    9. I've modified a Makefile in my source tree, but my build tree keeps + using the old version. What do I do?
    10. + +
    11. I've upgraded to a new version of LLVM, and I get strange build + errors.
    12. + +
    13. I've built LLVM and am testing it, but the tests freeze.
    14. + +
    15. Why do test results differ when I perform different types of + builds?
    16. + +
    17. Compiling LLVM with GCC 3.3.2 fails, what should I do?
    18. + +
    19. Compiling LLVM with GCC succeeds, but the resulting tools do not work, + what can be wrong?
    20. + +
    21. When I use the test suite, all of the C Backend tests fail. What is + wrong?
    22. + +
    23. After Subversion update, rebuilding gives the error "No rule to make + target".
    24. + +
    25. The llvmc program gives me errors/doesn't + work.
    26. + +
    27. When I compile LLVM-GCC with srcdir == objdir, + it fails. Why?
    28. +
  6. + +
  7. Source Languages +
      +
    1. What source languages are supported?
    2. + +
    3. I'd like to write a self-hosting LLVM compiler. How + should I interface with the LLVM middle-end optimizers and back-end code + generators?
    4. + +
    5. What support is there for higher level source + language constructs for building a compiler?
    6. + +
    7. I don't understand the GetElementPtr + instruction. Help!
    8. +
    + +
  8. Using the GCC Front End +
      +
    1. When I compile software that uses a configure script, the configure + script thinks my system has all of the header files and libraries it is + testing for. How do I get configure to work correctly?
    2. + +
    3. When I compile code using the LLVM GCC front end, it complains that it + cannot find libcrtend.a?
    4. + +
    5. How can I disable all optimizations when compiling code using the LLVM + GCC front end?
    6. + +
    7. Can I use LLVM to convert C++ code to C + code?
    8. + +
    9. Can I compile C or C++ code to + platform-independent LLVM bitcode?
    10. +
    +
  9. + +
  10. Questions about code generated by the GCC front-end +
      +
    1. What is this llvm.global_ctors and + _GLOBAL__I__tmp_webcompile... stuff that happens when I + #include <iostream>?
    2. + +
    3. Where did all of my code go??
    4. + +
    5. What is this "undef" thing that shows up in + my code?
    6. + +
    7. Why does instcombine + simplifycfg turn + a call to a function with a mismatched calling convention into "unreachable"? + Why not make the verifier reject it?
    8. +
    +
  11. +
+ +
+

Written by The LLVM Team

+
+ + + +
+ License +
+ + +
+

Why are the LLVM source code and the front-end distributed under different + licenses?

+
+ +
+

The C/C++ front-ends are based on GCC and must be distributed under the GPL. + Our aim is to distribute LLVM source code under a much less + restrictive license, in particular one that does not compel users who + distribute tools based on modifying the source to redistribute the modified + source code as well.

+
+ +
+

Does the University of Illinois Open Source License really qualify as an + "open source" license?

+
+ +
+

Yes, the license + is certified by + the Open Source Initiative (OSI).

+
+ +
+

Can I modify LLVM source code and redistribute the modified source?

+
+ +
+

Yes. The modified source distribution must retain the copyright notice and + follow the three bulletted conditions listed in + the LLVM + license.

+
+ +
+

Can I modify LLVM source code and redistribute binaries or other tools based + on it, without redistributing the source?

+
+ +
+

Yes. This is why we distribute LLVM under a less restrictive license than + GPL, as explained in the first question above.

+
+ + + + + +
+

In what language is LLVM written?

+
+ +
+

All of the LLVM tools and libraries are written in C++ with extensive use of + the STL.

+
+ +
+

How portable is the LLVM source code?

+
+ +
+

The LLVM source code should be portable to most modern UNIX-like operating +systems. Most of the code is written in standard C++ with operating system +services abstracted to a support library. The tools required to build and test +LLVM have been ported to a plethora of platforms.

+ +

Some porting problems may exist in the following areas:

+ +
    +
  • The GCC front end code is not as portable as the LLVM suite, so it may not + compile as well on unsupported platforms.
  • + +
  • The LLVM build system relies heavily on UNIX shell tools, like the Bourne + Shell and sed. Porting to systems without these tools (MacOS 9, Plan 9) + will require more effort.
  • +
+ +
+ + + + + +
+

When I run configure, it finds the wrong C compiler.

+
+ +
+

The configure script attempts to locate first gcc and then + cc, unless it finds compiler paths set in CC + and CXX for the C and C++ compiler, respectively.

+ +

If configure finds the wrong compiler, either adjust your + PATH environment variable or set CC and CXX + explicitly.

+ +
+ +
+

The configure script finds the right C compiler, but it uses the + LLVM linker from a previous build. What do I do?

+
+ +
+

The configure script uses the PATH to find executables, so + if it's grabbing the wrong linker/assembler/etc, there are two ways to fix + it:

+ +
    +
  1. Adjust your PATH environment variable so that the correct + program appears first in the PATH. This may work, but may not be + convenient when you want them first in your path for other + work.

  2. + +
  3. Run configure with an alternative PATH that is + correct. In a Borne compatible shell, the syntax would be:

    + +
    +% PATH=[the path without the bad program] ./configure ...
    +
    + +

    This is still somewhat inconvenient, but it allows configure + to do its work without having to adjust your PATH + permanently.

  4. +
+
+ +
+

When creating a dynamic library, I get a strange GLIBC error.

+
+ +
+

Under some operating systems (i.e. Linux), libtool does not work correctly if + GCC was compiled with the --disable-shared option. To work around this, + install your own version of GCC that has shared libraries enabled by + default.

+
+ +
+

I've updated my source tree from Subversion, and now my build is trying to + use a file/directory that doesn't exist.

+
+ +
+

You need to re-run configure in your object directory. When new Makefiles + are added to the source tree, they have to be copied over to the object tree + in order to be used by the build.

+
+ +
+

I've modified a Makefile in my source tree, but my build tree keeps using the + old version. What do I do?

+
+ +
+

If the Makefile already exists in your object tree, you can just run the + following command in the top level directory of your object tree:

+ +
+% ./config.status <relative path to Makefile>
+
+ +

If the Makefile is new, you will have to modify the configure script to copy + it over.

+
+ +
+

I've upgraded to a new version of LLVM, and I get strange build errors.

+
+ +
+ +

Sometimes, changes to the LLVM source code alters how the build system works. + Changes in libtool, autoconf, or header file dependencies are especially + prone to this sort of problem.

+ +

The best thing to try is to remove the old files and re-build. In most + cases, this takes care of the problem. To do this, just type make + clean and then make in the directory that fails to build.

+
+ +
+

I've built LLVM and am testing it, but the tests freeze.

+
+ +
+

This is most likely occurring because you built a profile or release + (optimized) build of LLVM and have not specified the same information on the + gmake command line.

+ +

For example, if you built LLVM with the command:

+ +
+% gmake ENABLE_PROFILING=1
+
+ +

...then you must run the tests with the following commands:

+ +
+% cd llvm/test
+% gmake ENABLE_PROFILING=1
+
+
+ +
+

Why do test results differ when I perform different types of builds?

+
+ +
+

The LLVM test suite is dependent upon several features of the LLVM tools and + libraries.

+ +

First, the debugging assertions in code are not enabled in optimized or + profiling builds. Hence, tests that used to fail may pass.

+ +

Second, some tests may rely upon debugging options or behavior that is only + available in the debug build. These tests will fail in an optimized or + profile build.

+
+ +
+

Compiling LLVM with GCC 3.3.2 fails, what should I do?

+
+ +
+

This is a bug in + GCC, and affects projects other than LLVM. Try upgrading or downgrading + your GCC.

+
+ +
+

Compiling LLVM with GCC succeeds, but the resulting tools do not work, what + can be wrong?

+
+ +
+

Several versions of GCC have shown a weakness in miscompiling the LLVM + codebase. Please consult your compiler version (gcc --version) to + find out whether it is broken. + If so, your only option is to upgrade GCC to a known good version.

+
+ +
+

After Subversion update, rebuilding gives the error "No rule to make + target".

+
+ +
+

If the error is of the form:

+ +
+gmake[2]: *** No rule to make target `/path/to/somefile', needed by
+`/path/to/another/file.d'.
+Stop. +
+ +

This may occur anytime files are moved within the Subversion repository or + removed entirely. In this case, the best solution is to erase all + .d files, which list dependencies for source files, and rebuild:

+ +
+% cd $LLVM_OBJ_DIR
+% rm -f `find . -name \*\.d` 
+% gmake 
+
+ +

In other cases, it may be necessary to run make clean before + rebuilding.

+
+ + + +
+

llvmc is experimental and isn't really supported. We suggest + using llvm-gcc instead.

+
+ + + +
+

The GNUmakefile in the top-level directory of LLVM-GCC is a special + Makefile used by Apple to invoke the build_gcc script after + setting up a special environment. This has the unfortunate side-effect that + trying to build LLVM-GCC with srcdir == objdir in a "non-Apple way" invokes + the GNUmakefile instead of Makefile. Because the + environment isn't set up correctly to do this, the build fails.

+ +

People not building LLVM-GCC the "Apple way" need to build LLVM-GCC with + srcdir != objdir, or simply remove the GNUmakefile entirely.

+ +

We regret the inconvenience.

+
+ + + + + + +
+

LLVM currently has full support for C and C++ source languages. These are + available through a special version of GCC that LLVM calls the + C Front End

+ +

There is an incomplete version of a Java front end available in the + java module. There is no documentation on this yet so you'll need to + download the code, compile it, and try it.

+ +

The PyPy developers are working on integrating LLVM into the PyPy backend so + that PyPy language can translate to LLVM.

+
+ + + +
+

Your compiler front-end will communicate with LLVM by creating a module in + the LLVM intermediate representation (IR) format. Assuming you want to write + your language's compiler in the language itself (rather than C++), there are + 3 major ways to tackle generating LLVM IR from a front-end:

+ +
    +
  • Call into the LLVM libraries code using your language's FFI + (foreign function interface). + +
      +
    • for: best tracks changes to the LLVM IR, .ll syntax, and .bc + format
    • + +
    • for: enables running LLVM optimization passes without a + emit/parse overhead
    • + +
    • for: adapts well to a JIT context
    • + +
    • against: lots of ugly glue code to write
    • +
  • + +
  • Emit LLVM assembly from your compiler's native language. +
      +
    • for: very straightforward to get started
    • + +
    • against: the .ll parser is slower than the bitcode reader + when interfacing to the middle end
    • + +
    • against: you'll have to re-engineer the LLVM IR object model + and asm writer in your language
    • + +
    • against: it may be harder to track changes to the IR
    • +
  • + +
  • Emit LLVM bitcode from your compiler's native language. + +
      +
    • for: can use the more-efficient bitcode reader when + interfacing to the middle end
    • + +
    • against: you'll have to re-engineer the LLVM IR object + model and bitcode writer in your language
    • + +
    • against: it may be harder to track changes to the IR
    • +
  • +
+ +

If you go with the first option, the C bindings in include/llvm-c should help + a lot, since most languages have strong support for interfacing with C. The + most common hurdle with calling C from managed code is interfacing with the + garbage collector. The C interface was designed to require very little memory + management, and so is straightforward in this regard.

+
+ + + +
+

Currently, there isn't much. LLVM supports an intermediate representation + which is useful for code representation but will not support the high level + (abstract syntax tree) representation needed by most compilers. There are no + facilities for lexical nor semantic analysis. There is, however, a mostly + implemented configuration-driven + compiler driver which simplifies the task + of running optimizations, linking, and executable generation.

+
+ + + + + + + + +
+

When I compile software that uses a configure script, the configure script + thinks my system has all of the header files and libraries it is testing for. + How do I get configure to work correctly?

+
+ +
+

The configure script is getting things wrong because the LLVM linker allows + symbols to be undefined at link time (so that they can be resolved during JIT + or translation to the C back end). That is why configure thinks your system + "has everything."

+ +

To work around this, perform the following steps:

+ +
    +
  1. Make sure the CC and CXX environment variables contains the full path to + the LLVM GCC front end.
  2. + +
  3. Make sure that the regular C compiler is first in your PATH.
  4. + +
  5. Add the string "-Wl,-native" to your CFLAGS environment variable.
  6. +
+ +

This will allow the llvm-ld linker to create a native code + executable instead of shell script that runs the JIT. Creating native code + requires standard linkage, which in turn will allow the configure script to + find out if code is not linking on your system because the feature isn't + available on your system.

+
+ +
+

When I compile code using the LLVM GCC front end, it complains that it cannot + find libcrtend.a. +

+
+ +
+

The only way this can happen is if you haven't installed the runtime + library. To correct this, do:

+ +
+% cd llvm/runtime
+% make clean ; make install-bytecode
+
+
+ +
+

How can I disable all optimizations when compiling code using the LLVM GCC + front end?

+
+ +
+

Passing "-Wa,-disable-opt -Wl,-disable-opt" will disable *all* cleanup and + optimizations done at the llvm level, leaving you with the truly horrible + code that you desire.

+
+ + + + +
+

Yes, you can use LLVM to convert code from any language LLVM supports to C. + Note that the generated C code will be very low level (all loops are lowered + to gotos, etc) and not very pretty (comments are stripped, original source + formatting is totally lost, variables are renamed, expressions are + regrouped), so this may not be what you're looking for. Also, there are + several limitations noted below.

+ +

Use commands like this:

+ +
    +
  1. Compile your program with llvm-g++:

    + +
    +% llvm-g++ -emit-llvm x.cpp -o program.bc -c
    +
    + +

    or:

    + +
    +% llvm-g++ a.cpp -c -emit-llvm
    +% llvm-g++ b.cpp -c -emit-llvm
    +% llvm-ld a.o b.o -o program
    +
    + +

    This will generate program and program.bc. The .bc + file is the LLVM version of the program all linked together.

  2. + +
  3. Convert the LLVM code to C code, using the LLC tool with the C + backend:

    + +
    +% llc -march=c program.bc -o program.c
    +
  4. + +
  5. Finally, compile the C file:

    + +
    +% cc x.c -lstdc++
    +
  6. + +
+ +

Using LLVM does not eliminate the need for C++ library support. If you use + the llvm-g++ front-end, the generated code will depend on g++'s C++ support + libraries in the same way that code generated from g++ would. If you use + another C++ front-end, the generated code will depend on whatever library + that front-end would normally require.

+ +

If you are working on a platform that does not provide any C++ libraries, you + may be able to manually compile libstdc++ to LLVM bitcode, statically link it + into your program, then use the commands above to convert the whole result + into C code. Alternatively, you might compile the libraries and your + application into two different chunks of C code and link them.

+ +

Note that, by default, the C back end does not support exception handling. + If you want/need it for a certain program, you can enable it by passing + "-enable-correct-eh-support" to the llc program. The resultant code will use + setjmp/longjmp to implement exception support that is relatively slow, and + not C++-ABI-conforming on most platforms, but otherwise correct.

+ +

Also, there are a number of other limitations of the C backend that cause it + to produce code that does not fully conform to the C++ ABI on most + platforms. Some of the C++ programs in LLVM's test suite are known to fail + when compiled with the C back end because of ABI incompatibilities with + standard C++ libraries.

+
+ + + +
+

No. C and C++ are inherently platform-dependent languages. The most obvious + example of this is the preprocessor. A very common way that C code is made + portable is by using the preprocessor to include platform-specific code. In + practice, information about other platforms is lost after preprocessing, so + the result is inherently dependent on the platform that the preprocessing was + targeting.

+ +

Another example is sizeof. It's common for sizeof(long) to + vary between platforms. In most C front-ends, sizeof is expanded to + a constant immediately, thus hard-wiring a platform-specific detail.

+ +

Also, since many platforms define their ABIs in terms of C, and since LLVM is + lower-level than C, front-ends currently must emit platform-specific IR in + order to have the result conform to the platform ABI.

+
+ + + + + + +
+

If you #include the <iostream> header into a C++ + translation unit, the file will probably use + the std::cin/std::cout/... global objects. However, C++ + does not guarantee an order of initialization between static objects in + different translation units, so if a static ctor/dtor in your .cpp file + used std::cout, for example, the object would not necessarily be + automatically initialized before your use.

+ +

To make std::cout and friends work correctly in these scenarios, the + STL that we use declares a static object that gets created in every + translation unit that includes <iostream>. This object has a + static constructor and destructor that initializes and destroys the global + iostream objects before they could possibly be used in the file. The code + that you see in the .ll file corresponds to the constructor and destructor + registration code. +

+ +

If you would like to make it easier to understand the LLVM code + generated by the compiler in the demo page, consider using printf() + instead of iostreams to print values.

+
+ + + + + +
+

If you are using the LLVM demo page, you may often wonder what happened to + all of the code that you typed in. Remember that the demo script is running + the code through the LLVM optimizers, so if your code doesn't actually do + anything useful, it might all be deleted.

+ +

To prevent this, make sure that the code is actually needed. For example, if + you are computing some expression, return the value from the function instead + of leaving it in a local variable. If you really want to constrain the + optimizer, you can read from and assign to volatile global + variables.

+
+ + + + + +
+

undef is the LLVM way of + representing a value that is not defined. You can get these if you do not + initialize a variable before you use it. For example, the C function:

+ +
+int X() { int i; return i; }
+
+ +

Is compiled to "ret i32 undef" because "i" never has a + value specified for it.

+
+ + + + + +
+

This is a common problem run into by authors of front-ends that are using +custom calling conventions: you need to make sure to set the right calling +convention on both the function and on each call to the function. For example, +this code:

+ +
+define fastcc void @foo() {
+        ret void
+}
+define void @bar() {
+        call void @foo()
+        ret void
+}
+
+ +

Is optimized to:

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @bar() {
+	unreachable
+}
+
+ +

... with "opt -instcombine -simplifycfg". This often bites people because +"all their code disappears". Setting the calling convention on the caller and +callee is required for indirect calls to work, so people often ask why not make +the verifier reject this sort of thing.

+ +

The answer is that this code has undefined behavior, but it is not illegal. +If we made it illegal, then every transformation that could potentially create +this would have to ensure that it doesn't, and there is valid code that can +create this sort of construct (in dead code). The sorts of things that can +cause this to happen are fairly contrived, but we still need to accept them. +Here's an example:

+ +
+define fastcc void @foo() {
+        ret void
+}
+define internal void @bar(void()* %FP, i1 %cond) {
+        br i1 %cond, label %T, label %F
+T:  
+        call void %FP()
+        ret void
+F:
+        call fastcc void %FP()
+        ret void
+}
+define void @test() {
+        %X = or i1 false, false
+        call void @bar(void()* @foo, i1 %X)
+        ret void
+} 
+
+ +

In this example, "test" always passes @foo/false into bar, which ensures that + it is dynamically called with the right calling conv (thus, the code is + perfectly well defined). If you run this through the inliner, you get this + (the explicit "or" is there so that the inliner doesn't dead code eliminate + a bunch of stuff): +

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @test() {
+	%X = or i1 false, false
+	br i1 %X, label %T.i, label %F.i
+T.i:
+	call void @foo()
+	br label %bar.exit
+F.i:
+	call fastcc void @foo()
+	br label %bar.exit
+bar.exit:
+	ret void
+}
+
+ +

Here you can see that the inlining pass made an undefined call to @foo with + the wrong calling convention. We really don't want to make the inliner have + to know about this sort of thing, so it needs to be valid code. In this case, + dead code elimination can trivially remove the undefined code. However, if %X + was an input argument to @test, the inliner would produce this: +

+ +
+define fastcc void @foo() {
+	ret void
+}
+
+define void @test(i1 %X) {
+	br i1 %X, label %T.i, label %F.i
+T.i:
+	call void @foo()
+	br label %bar.exit
+F.i:
+	call fastcc void @foo()
+	br label %bar.exit
+bar.exit:
+	ret void
+}
+
+ +

The interesting thing about this is that %X must be false for the +code to be well-defined, but no amount of dead code elimination will be able to +delete the broken call as unreachable. However, since instcombine/simplifycfg +turns the undefined call into unreachable, we end up with a branch on a +condition that goes to unreachable: a branch to unreachable can never happen, so +"-inline -instcombine -simplifycfg" is able to produce:

+ +
+define fastcc void @foo() {
+	ret void
+}
+define void @test(i1 %X) {
+F.i:
+	call fastcc void @foo()
+	ret void
+}
+
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/GCCFEBuildInstrs.html b/final/docs/GCCFEBuildInstrs.html new file mode 100644 index 00000000000..8fe0c31cb64 --- /dev/null +++ b/final/docs/GCCFEBuildInstrs.html @@ -0,0 +1,279 @@ + + + + + + Building the LLVM GCC Front-End + + + +
+ Building the LLVM GCC Front-End +
+ +
    +
  1. Building llvm-gcc from Source
  2. +
  3. Building the Ada front-end
  4. +
  5. Building the Fortran front-end
  6. +
  7. License Information
  8. +
+ +
+

Written by the LLVM Team

+
+ + +

Building llvm-gcc from Source

+ + +
+ +

This section describes how to acquire and build llvm-gcc 4.2, which is based +on the GCC 4.2.1 front-end. Supported languages are Ada, C, C++, Fortran, +Objective-C and Objective-C++. Note that the instructions for building these +front-ends are completely different (and much easier!) than those for building +llvm-gcc3 in the past.

+ +
    +
  1. Retrieve the appropriate llvm-gcc-4.2-version.source.tar.gz + archive from the LLVM web + site.

    + +

    It is also possible to download the sources of the llvm-gcc front end + from a read-only mirror using subversion. To check out the 4.2 code + for first time use:

    + +
    +
    +svn co http://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk dst-directory
    +
    +
    + +

    After that, the code can be be updated in the destination directory + using:

    + +
    +
    svn update
    +
    + +

    The mirror is brought up to date every evening.

  2. + +
  3. Follow the directions in the top-level README.LLVM file for + up-to-date instructions on how to build llvm-gcc. See below for building + with support for Ada or Fortran. +
+ +
+ + +

Building the Ada front-end

+ + +
+

Building with support for Ada amounts to following the directions in the +top-level README.LLVM file, adding ",ada" to EXTRALANGS, for example: +EXTRALANGS=,ada

+ +

There are some complications however:

+ +
    +
  1. The only platform for which the Ada front-end is known to build is + 32 bit intel x86 running linux. It is unlikely to build for other + systems without some work.

  2. +
  3. The build requires having a compiler that supports Ada, C and C++. + The Ada front-end is written in Ada so an Ada compiler is needed to + build it. Compilers known to work with the + LLVM 2.7 release + are gcc-4.2 and the + 2005, 2006 and 2007 versions of the + GNAT GPL Edition. + GNAT GPL 2008, gcc-4.3 and later will not work. + The LLVM parts of llvm-gcc are written in C++ so a C++ compiler is + needed to build them. The rest of gcc is written in C. + Some linux distributions provide a version of gcc that supports all + three languages (the Ada part often comes as an add-on package to + the rest of gcc). Otherwise it is possible to combine two versions + of gcc, one that supports Ada and C (such as the + 2007 GNAT GPL Edition) + and another which supports C++, see below.

  4. +
  5. Because the Ada front-end is experimental, it is wise to build the + compiler with checking enabled. This causes it to run much slower, but + helps catch mistakes in the compiler (please report any problems using + LLVM bugzilla).

  6. +
  7. The Ada front-end fails to + bootstrap, due to lack of LLVM support for + setjmp/longjmp style exception handling (used + internally by the compiler), so you must specify + --disable-bootstrap.

  8. +
+ +

Supposing appropriate compilers are available, llvm-gcc with Ada support can + be built on an x86-32 linux box using the following recipe:

+ +
    +
  1. Download the LLVM source + and unpack it:

    + +
    +wget http://llvm.org/releases/2.7/llvm-2.7.tgz
    +tar xzf llvm-2.7.tgz
    +mv llvm-2.7 llvm
    +
    + +

    or check out the + latest version from subversion:

    + +
    svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
    + +
  2. + +
  3. Download the + llvm-gcc-4.2 source + and unpack it:

    + +
    +wget http://llvm.org/releases/2.7/llvm-gcc-4.2-2.7.source.tgz
    +tar xzf llvm-gcc-4.2-2.7.source.tgz
    +mv llvm-gcc-4.2-2.7.source llvm-gcc-4.2
    +
    + +

    or check out the + latest version from subversion:

    + +
    +svn co http://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk llvm-gcc-4.2
    +
    +
  4. + +
  5. Make a build directory llvm-objects for llvm and make it the + current directory:

    + +
    +mkdir llvm-objects
    +cd llvm-objects
    +
    +
  6. + +
  7. Configure LLVM (here it is configured to install into /usr/local):

    + +
    +../llvm/configure --prefix=/usr/local --enable-optimized --enable-assertions
    +
    + +

    If you have a multi-compiler setup and the C++ compiler is not the + default, then you can configure like this:

    + +
    +CXX=PATH_TO_C++_COMPILER ../llvm/configure --prefix=/usr/local --enable-optimized --enable-assertions
    +
    + +

    To compile without checking (not recommended), replace + --enable-assertions with --disable-assertions.

    + +
  8. + +
  9. Build LLVM:

    + +
    +make
    +
    +
  10. + +
  11. Install LLVM (optional):

    + +
    +make install
    +
    +
  12. + +
  13. Make a build directory llvm-gcc-4.2-objects for llvm-gcc and make it the + current directory:

    + +
    +cd ..
    +mkdir llvm-gcc-4.2-objects
    +cd llvm-gcc-4.2-objects
    +
    +
  14. + +
  15. Configure llvm-gcc (here it is configured to install into /usr/local). + The --enable-checking flag turns on sanity checks inside the compiler. + To turn off these checks (not recommended), replace --enable-checking + with --disable-checking. + Additional languages can be appended to the --enable-languages switch, + for example --enable-languages=ada,c,c++.

    + +
    +../llvm-gcc-4.2/configure --prefix=/usr/local --enable-languages=ada,c \
    +                          --enable-checking --enable-llvm=$PWD/../llvm-objects \
    +			  --disable-bootstrap --disable-multilib
    +
    + +

    If you have a multi-compiler setup, then you can configure like this:

    + +
    +export CC=PATH_TO_C_AND_ADA_COMPILER
    +export CXX=PATH_TO_C++_COMPILER
    +../llvm-gcc-4.2/configure --prefix=/usr/local --enable-languages=ada,c \
    +                          --enable-checking --enable-llvm=$PWD/../llvm-objects \
    +			  --disable-bootstrap --disable-multilib
    +
    +
  16. + +
  17. Build and install the compiler:

    + +
    +make
    +make install
    +
    +
  18. +
+ +
+ + +

Building the Fortran front-end

+ + +
+

To build with support for Fortran, follow the directions in the top-level +README.LLVM file, adding ",fortran" to EXTRALANGS, for example:

+ +
+EXTRALANGS=,fortran
+
+ +
+ + +

License Information

+ + +
+

+The LLVM GCC frontend is licensed to you under the GNU General Public License +and the GNU Lesser General Public License. Please see the files COPYING and +COPYING.LIB for more details. +

+ +

+More information is available in the FAQ. +

+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/GarbageCollection.html b/final/docs/GarbageCollection.html new file mode 100644 index 00000000000..56085ca710b --- /dev/null +++ b/final/docs/GarbageCollection.html @@ -0,0 +1,1387 @@ + + + + + Accurate Garbage Collection with LLVM + + + + + +
+ Accurate Garbage Collection with LLVM +
+ +
    +
  1. Introduction + +
  2. + +
  3. Getting started + +
  4. + +
  5. Core support + +
  6. + +
  7. Compiler plugin interface + +
  8. + +
  9. Implementing a collector runtime + +
  10. + +
  11. References
  12. + +
+ +
+

Written by Chris Lattner and + Gordon Henriksen

+
+ + + + + +
+ +

Garbage collection is a widely used technique that frees the programmer from +having to know the lifetimes of heap objects, making software easier to produce +and maintain. Many programming languages rely on garbage collection for +automatic memory management. There are two primary forms of garbage collection: +conservative and accurate.

+ +

Conservative garbage collection often does not require any special support +from either the language or the compiler: it can handle non-type-safe +programming languages (such as C/C++) and does not require any special +information from the compiler. The +Boehm collector is +an example of a state-of-the-art conservative collector.

+ +

Accurate garbage collection requires the ability to identify all pointers in +the program at run-time (which requires that the source-language be type-safe in +most cases). Identifying pointers at run-time requires compiler support to +locate all places that hold live pointer variables at run-time, including the +processor stack and registers.

+ +

Conservative garbage collection is attractive because it does not require any +special compiler support, but it does have problems. In particular, because the +conservative garbage collector cannot know that a particular word in the +machine is a pointer, it cannot move live objects in the heap (preventing the +use of compacting and generational GC algorithms) and it can occasionally suffer +from memory leaks due to integer values that happen to point to objects in the +program. In addition, some aggressive compiler transformations can break +conservative garbage collectors (though these seem rare in practice).

+ +

Accurate garbage collectors do not suffer from any of these problems, but +they can suffer from degraded scalar optimization of the program. In particular, +because the runtime must be able to identify and update all pointers active in +the program, some optimizations are less effective. In practice, however, the +locality and performance benefits of using aggressive garbage collection +techniques dominates any low-level losses.

+ +

This document describes the mechanisms and interfaces provided by LLVM to +support accurate garbage collection.

+ +
+ + + + +
+ +

LLVM's intermediate representation provides garbage +collection intrinsics that offer support for a broad class of +collector models. For instance, the intrinsics permit:

+ +
    +
  • semi-space collectors
  • +
  • mark-sweep collectors
  • +
  • generational collectors
  • +
  • reference counting
  • +
  • incremental collectors
  • +
  • concurrent collectors
  • +
  • cooperative collectors
  • +
+ +

We hope that the primitive support built into the LLVM IR is sufficient to +support a broad class of garbage collected languages including Scheme, ML, Java, +C#, Perl, Python, Lua, Ruby, other scripting languages, and more.

+ +

However, LLVM does not itself provide a garbage collector—this should +be part of your language's runtime library. LLVM provides a framework for +compile time code generation plugins. The role of these +plugins is to generate code and data structures which conforms to the binary +interface specified by the runtime library. This is similar to the +relationship between LLVM and DWARF debugging info, for example. The +difference primarily lies in the lack of an established standard in the domain +of garbage collection—thus the plugins.

+ +

The aspects of the binary interface with which LLVM's GC support is +concerned are:

+ +
    +
  • Creation of GC-safe points within code where collection is allowed to + execute safely.
  • +
  • Computation of the stack map. For each safe point in the code, object + references within the stack frame must be identified so that the + collector may traverse and perhaps update them.
  • +
  • Write barriers when storing object references to the heap. These are + commonly used to optimize incremental scans in generational + collectors.
  • +
  • Emission of read barriers when loading object references. These are + useful for interoperating with concurrent collectors.
  • +
+ +

There are additional areas that LLVM does not directly address:

+ +
    +
  • Registration of global roots with the runtime.
  • +
  • Registration of stack map entries with the runtime.
  • +
  • The functions used by the program to allocate memory, trigger a + collection, etc.
  • +
  • Computation or compilation of type maps, or registration of them with + the runtime. These are used to crawl the heap for object + references.
  • +
+ +

In general, LLVM's support for GC does not include features which can be +adequately addressed with other features of the IR and does not specify a +particular binary interface. On the plus side, this means that you should be +able to integrate LLVM with an existing runtime. On the other hand, it leaves +a lot of work for the developer of a novel language. However, it's easy to get +started quickly and scale up to a more sophisticated implementation as your +compiler matures.

+ +
+ + + + + +
+ +

Using a GC with LLVM implies many things, for example:

+ +
    +
  • Write a runtime library or find an existing one which implements a GC + heap.
      +
    1. Implement a memory allocator.
    2. +
    3. Design a binary interface for the stack map, used to identify + references within a stack frame on the machine stack.*
    4. +
    5. Implement a stack crawler to discover functions on the call stack.*
    6. +
    7. Implement a registry for global roots.
    8. +
    9. Design a binary interface for type maps, used to identify references + within heap objects.
    10. +
    11. Implement a collection routine bringing together all of the above.
    12. +
  • +
  • Emit compatible code from your compiler.
      +
    • Initialization in the main function.
    • +
    • Use the gc "..." attribute to enable GC code generation + (or F.setGC("...")).
    • +
    • Use @llvm.gcroot to mark stack roots.
    • +
    • Use @llvm.gcread and/or @llvm.gcwrite to + manipulate GC references, if necessary.
    • +
    • Allocate memory using the GC allocation routine provided by the + runtime library.
    • +
    • Generate type maps according to your runtime's binary interface.
    • +
  • +
  • Write a compiler plugin to interface LLVM with the runtime library.*
      +
    • Lower @llvm.gcread and @llvm.gcwrite to appropriate + code sequences.*
    • +
    • Compile LLVM's stack map to the binary form expected by the + runtime.
    • +
  • +
  • Load the plugin into the compiler. Use llc -load or link the + plugin statically with your language's compiler.*
  • +
  • Link program executables with the runtime.
  • +
+ +

To help with several of these tasks (those indicated with a *), LLVM +includes a highly portable, built-in ShadowStack code generator. It is compiled +into llc and works even with the interpreter and C backends.

+ +
+ + + + +
+ +

To turn the shadow stack on for your functions, first call:

+ +
F.setGC("shadow-stack");
+ +

for each function your compiler emits. Since the shadow stack is built into +LLVM, you do not need to load a plugin.

+ +

Your compiler must also use @llvm.gcroot as documented. +Don't forget to create a root for each intermediate value that is generated +when evaluating an expression. In h(f(), g()), the result of +f() could easily be collected if evaluating g() triggers a +collection.

+ +

There's no need to use @llvm.gcread and @llvm.gcwrite over +plain load and store for now. You will need them when +switching to a more advanced GC.

+ +
+ + + + +
+ +

The shadow stack doesn't imply a memory allocation algorithm. A semispace +collector or building atop malloc are great places to start, and can +be implemented with very little code.

+ +

When it comes time to collect, however, your runtime needs to traverse the +stack roots, and for this it needs to integrate with the shadow stack. Luckily, +doing so is very simple. (This code is heavily commented to help you +understand the data structure, but there are only 20 lines of meaningful +code.)

+ +
+ +
/// @brief The map for a single function's stack frame. One of these is
+///        compiled as constant data into the executable for each function.
+/// 
+/// Storage of metadata values is elided if the %metadata parameter to
+/// @llvm.gcroot is null.
+struct FrameMap {
+  int32_t NumRoots;    //< Number of roots in stack frame.
+  int32_t NumMeta;     //< Number of metadata entries. May be < NumRoots.
+  const void *Meta[0]; //< Metadata for each root.
+};
+
+/// @brief A link in the dynamic shadow stack. One of these is embedded in the
+///        stack frame of each function on the call stack.
+struct StackEntry {
+  StackEntry *Next;    //< Link to next stack entry (the caller's).
+  const FrameMap *Map; //< Pointer to constant FrameMap.
+  void *Roots[0];      //< Stack roots (in-place array).
+};
+
+/// @brief The head of the singly-linked list of StackEntries. Functions push
+///        and pop onto this in their prologue and epilogue.
+/// 
+/// Since there is only a global list, this technique is not threadsafe.
+StackEntry *llvm_gc_root_chain;
+
+/// @brief Calls Visitor(root, meta) for each GC root on the stack.
+///        root and meta are exactly the values passed to
+///        @llvm.gcroot.
+/// 
+/// Visitor could be a function to recursively mark live objects. Or it
+/// might copy them to another heap or generation.
+/// 
+/// @param Visitor A function to invoke for every GC root on the stack.
+void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) {
+  for (StackEntry *R = llvm_gc_root_chain; R; R = R->Next) {
+    unsigned i = 0;
+    
+    // For roots [0, NumMeta), the metadata pointer is in the FrameMap.
+    for (unsigned e = R->Map->NumMeta; i != e; ++i)
+      Visitor(&R->Roots[i], R->Map->Meta[i]);
+    
+    // For roots [NumMeta, NumRoots), the metadata pointer is null.
+    for (unsigned e = R->Map->NumRoots; i != e; ++i)
+      Visitor(&R->Roots[i], NULL);
+  }
+}
+ + + + +
+ +

Unlike many GC algorithms which rely on a cooperative code generator to +compile stack maps, this algorithm carefully maintains a linked list of stack +roots [Henderson2002]. This so-called "shadow stack" +mirrors the machine stack. Maintaining this data structure is slower than using +a stack map compiled into the executable as constant data, but has a significant +portability advantage because it requires no special support from the target +code generator, and does not require tricky platform-specific code to crawl +the machine stack.

+ +

The tradeoff for this simplicity and portability is:

+ +
    +
  • High overhead per function call.
  • +
  • Not thread-safe.
  • +
+ +

Still, it's an easy way to get started. After your compiler and runtime are +up and running, writing a plugin will allow you to take +advantage of more advanced GC features of LLVM +in order to improve performance.

+ +
+ + + + + +
+ +

This section describes the garbage collection facilities provided by the +LLVM intermediate representation. The exact behavior +of these IR features is specified by the binary interface implemented by a +code generation plugin, not by this document.

+ +

These facilities are limited to those strictly necessary; they are not +intended to be a complete interface to any garbage collector. A program will +need to interface with the GC library using the facilities provided by that +program.

+ +
+ + + + +
+ define ty @name(...) gc "name" { ... +
+ +
+ +

The gc function attribute is used to specify the desired GC style +to the compiler. Its programmatic equivalent is the setGC method of +Function.

+ +

Setting gc "name" on a function triggers a search for a +matching code generation plugin "name"; it is that plugin which defines +the exact nature of the code generated to support GC. If none is found, the +compiler will raise an error.

+ +

Specifying the GC style on a per-function basis allows LLVM to link together +programs that use different garbage collection algorithms (or none at all).

+ +
+ + + + +
+ void @llvm.gcroot(i8** %ptrloc, i8* %metadata) +
+ +
+ +

The llvm.gcroot intrinsic is used to inform LLVM that a stack +variable references an object on the heap and is to be tracked for garbage +collection. The exact impact on generated code is specified by a compiler plugin.

+ +

A compiler which uses mem2reg to raise imperative code using alloca +into SSA form need only add a call to @llvm.gcroot for those variables +which a pointers into the GC heap.

+ +

It is also important to mark intermediate values with llvm.gcroot. +For example, consider h(f(), g()). Beware leaking the result of +f() in the case that g() triggers a collection.

+ +

The first argument must be a value referring to an alloca instruction +or a bitcast of an alloca. The second contains a pointer to metadata that +should be associated with the pointer, and must be a constant or global +value address. If your target collector uses tags, use a null pointer for +metadata.

+ +

The %metadata argument can be used to avoid requiring heap objects +to have 'isa' pointers or tag bits. [Appel89, Goldberg91, Tolmach94] If +specified, its value will be tracked along with the location of the pointer in +the stack frame.

+ +

Consider the following fragment of Java code:

+ +
+       {
+         Object X;   // A null-initialized reference to an object
+         ...
+       }
+
+ +

This block (which may be located in the middle of a function or in a loop +nest), could be compiled to this LLVM code:

+ +
+Entry:
+   ;; In the entry block for the function, allocate the
+   ;; stack space for X, which is an LLVM pointer.
+   %X = alloca %Object*
+   
+   ;; Tell LLVM that the stack space is a stack root.
+   ;; Java has type-tags on objects, so we pass null as metadata.
+   %tmp = bitcast %Object** %X to i8**
+   call void @llvm.gcroot(i8** %X, i8* null)
+   ...
+
+   ;; "CodeBlock" is the block corresponding to the start
+   ;;  of the scope above.
+CodeBlock:
+   ;; Java null-initializes pointers.
+   store %Object* null, %Object** %X
+
+   ...
+
+   ;; As the pointer goes out of scope, store a null value into
+   ;; it, to indicate that the value is no longer live.
+   store %Object* null, %Object** %X
+   ...
+
+ +
+ + + + +
+ +

Some collectors need to be informed when the mutator (the program that needs +garbage collection) either reads a pointer from or writes a pointer to a field +of a heap object. The code fragments inserted at these points are called +read barriers and write barriers, respectively. The amount of +code that needs to be executed is usually quite small and not on the critical +path of any computation, so the overall performance impact of the barrier is +tolerable.

+ +

Barriers often require access to the object pointer rather than the +derived pointer (which is a pointer to the field within the +object). Accordingly, these intrinsics take both pointers as separate arguments +for completeness. In this snippet, %object is the object pointer, and +%derived is the derived pointer:

+ +
+    ;; An array type.
+    %class.Array = type { %class.Object, i32, [0 x %class.Object*] }
+    ...
+
+    ;; Load the object pointer from a gcroot.
+    %object = load %class.Array** %object_addr
+
+    ;; Compute the derived pointer.
+    %derived = getelementptr %object, i32 0, i32 2, i32 %n
+ +

LLVM does not enforce this relationship between the object and derived +pointer (although a plugin might). However, it would be +an unusual collector that violated it.

+ +

The use of these intrinsics is naturally optional if the target GC does +require the corresponding barrier. Such a GC plugin will replace the intrinsic +calls with the corresponding load or store instruction if they +are used.

+ +
+ + + + +
+void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived) +
+ +
+ +

For write barriers, LLVM provides the llvm.gcwrite intrinsic +function. It has exactly the same semantics as a non-volatile store to +the derived pointer (the third argument). The exact code generated is specified +by a compiler plugin.

+ +

Many important algorithms require write barriers, including generational +and concurrent collectors. Additionally, write barriers could be used to +implement reference counting.

+ +
+ + + + +
+i8* @llvm.gcread(i8* %object, i8** %derived)
+
+ +
+ +

For read barriers, LLVM provides the llvm.gcread intrinsic function. +It has exactly the same semantics as a non-volatile load from the +derived pointer (the second argument). The exact code generated is specified by +a compiler plugin.

+ +

Read barriers are needed by fewer algorithms than write barriers, and may +have a greater performance impact since pointer reads are more frequent than +writes.

+ +
+ + + + + +
+ +

User code specifies which GC code generation to use with the gc +function attribute or, equivalently, with the setGC method of +Function.

+ +

To implement a GC plugin, it is necessary to subclass +llvm::GCStrategy, which can be accomplished in a few lines of +boilerplate code. LLVM's infrastructure provides access to several important +algorithms. For an uncontroversial collector, all that remains may be to +compile LLVM's computed stack map to assembly code (using the binary +representation expected by the runtime library). This can be accomplished in +about 100 lines of code.

+ +

This is not the appropriate place to implement a garbage collected heap or a +garbage collector itself. That code should exist in the language's runtime +library. The compiler plugin is responsible for generating code which +conforms to the binary interface defined by library, most essentially the +stack map.

+ +

To subclass llvm::GCStrategy and register it with the compiler:

+ +
// lib/MyGC/MyGC.cpp - Example LLVM GC plugin
+
+#include "llvm/CodeGen/GCStrategy.h"
+#include "llvm/CodeGen/GCMetadata.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  class LLVM_LIBRARY_VISIBILITY MyGC : public GCStrategy {
+  public:
+    MyGC() {}
+  };
+  
+  GCRegistry::Add<MyGC>
+  X("mygc", "My bespoke garbage collector.");
+}
+ +

This boilerplate collector does nothing. More specifically:

+ +
    +
  • llvm.gcread calls are replaced with the corresponding + load instruction.
  • +
  • llvm.gcwrite calls are replaced with the corresponding + store instruction.
  • +
  • No safe points are added to the code.
  • +
  • The stack map is not compiled into the executable.
  • +
+ +

Using the LLVM makefiles (like the sample +project), this code can be compiled as a plugin using a simple +makefile:

+ +
# lib/MyGC/Makefile
+
+LEVEL := ../..
+LIBRARYNAME = MyGC
+LOADABLE_MODULE = 1
+
+include $(LEVEL)/Makefile.common
+ +

Once the plugin is compiled, code using it may be compiled using llc +-load=MyGC.so (though MyGC.so may have some other +platform-specific extension):

+ +
$ cat sample.ll
+define void @f() gc "mygc" {
+entry:
+        ret void
+}
+$ llvm-as < sample.ll | llc -load=MyGC.so
+ +

It is also possible to statically link the collector plugin into tools, such +as a language-specific compiler front-end.

+ +
+ + + + +
+ +

GCStrategy provides a range of features through which a plugin +may do useful work. Some of these are callbacks, some are algorithms that can +be enabled, disabled, or customized. This matrix summarizes the supported (and +planned) features and correlates them with the collection techniques which +typically require them.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AlgorithmDoneshadow stackrefcountmark-sweepcopyingincrementalthreadedconcurrent
stack map
initialize roots
derived pointersNO✘*✘*
custom lowering
gcroot
gcwrite
gcread
safe points
in calls
before calls
for loopsNO
before escape
emit code at safe pointsNO
output
assembly
JITNO
objNO
live analysisNO
register mapNO
+
* Derived pointers only pose a + hazard to copying collectors.
+
in gray denotes a feature which + could be utilized if available.
+
+ +

To be clear, the collection techniques above are defined as:

+ +
+
Shadow Stack
+
The mutator carefully maintains a linked list of stack roots.
+
Reference Counting
+
The mutator maintains a reference count for each object and frees an + object when its count falls to zero.
+
Mark-Sweep
+
When the heap is exhausted, the collector marks reachable objects starting + from the roots, then deallocates unreachable objects in a sweep + phase.
+
Copying
+
As reachability analysis proceeds, the collector copies objects from one + heap area to another, compacting them in the process. Copying collectors + enable highly efficient "bump pointer" allocation and can improve locality + of reference.
+
Incremental
+
(Including generational collectors.) Incremental collectors generally have + all the properties of a copying collector (regardless of whether the + mature heap is compacting), but bring the added complexity of requiring + write barriers.
+
Threaded
+
Denotes a multithreaded mutator; the collector must still stop the mutator + ("stop the world") before beginning reachability analysis. Stopping a + multithreaded mutator is a complicated problem. It generally requires + highly platform specific code in the runtime, and the production of + carefully designed machine code at safe points.
+
Concurrent
+
In this technique, the mutator and the collector run concurrently, with + the goal of eliminating pause times. In a cooperative collector, + the mutator further aids with collection should a pause occur, allowing + collection to take advantage of multiprocessor hosts. The "stop the world" + problem of threaded collectors is generally still present to a limited + extent. Sophisticated marking algorithms are necessary. Read barriers may + be necessary.
+
+ +

As the matrix indicates, LLVM's garbage collection infrastructure is already +suitable for a wide variety of collectors, but does not currently extend to +multithreaded programs. This will be added in the future as there is +interest.

+ +
+ + + + +
+ +

LLVM automatically computes a stack map. One of the most important features +of a GCStrategy is to compile this information into the executable in +the binary representation expected by the runtime library.

+ +

The stack map consists of the location and identity of each GC root in the +each function in the module. For each root:

+ +
    +
  • RootNum: The index of the root.
  • +
  • StackOffset: The offset of the object relative to the frame + pointer.
  • +
  • RootMetadata: The value passed as the %metadata + parameter to the @llvm.gcroot intrinsic.
  • +
+ +

Also, for the function as a whole:

+ +
    +
  • getFrameSize(): The overall size of the function's initial + stack frame, not accounting for any dynamic allocation.
  • +
  • roots_size(): The count of roots in the function.
  • +
+ +

To access the stack map, use GCFunctionMetadata::roots_begin() and +-end() from the GCMetadataPrinter:

+ +
for (iterator I = begin(), E = end(); I != E; ++I) {
+  GCFunctionInfo *FI = *I;
+  unsigned FrameSize = FI->getFrameSize();
+  size_t RootCount = FI->roots_size();
+
+  for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(),
+                                      RE = FI->roots_end();
+                                      RI != RE; ++RI) {
+    int RootNum = RI->Num;
+    int RootStackOffset = RI->StackOffset;
+    Constant *RootMetadata = RI->Metadata;
+  }
+}
+ +

If the llvm.gcroot intrinsic is eliminated before code generation by +a custom lowering pass, LLVM will compute an empty stack map. This may be useful +for collector plugins which implement reference counting or a shadow stack.

+ +
+ + + + + +
+ +
MyGC::MyGC() {
+  InitRoots = true;
+}
+ +

When set, LLVM will automatically initialize each root to null upon +entry to the function. This prevents the GC's sweep phase from visiting +uninitialized pointers, which will almost certainly cause it to crash. This +initialization occurs before custom lowering, so the two may be used +together.

+ +

Since LLVM does not yet compute liveness information, there is no means of +distinguishing an uninitialized stack root from an initialized one. Therefore, +this feature should be used by all GC plugins. It is enabled by default.

+ +
+ + + + + +
+ +

For GCs which use barriers or unusual treatment of stack roots, these +flags allow the collector to perform arbitrary transformations of the LLVM +IR:

+ +
class MyGC : public GCStrategy {
+public:
+  MyGC() {
+    CustomRoots = true;
+    CustomReadBarriers = true;
+    CustomWriteBarriers = true;
+  }
+  
+  virtual bool initializeCustomLowering(Module &M);
+  virtual bool performCustomLowering(Function &F);
+};
+ +

If any of these flags are set, then LLVM suppresses its default lowering for +the corresponding intrinsics and instead calls +performCustomLowering.

+ +

LLVM's default action for each intrinsic is as follows:

+ +
    +
  • llvm.gcroot: Leave it alone. The code generator must see it + or the stack map will not be computed.
  • +
  • llvm.gcread: Substitute a load instruction.
  • +
  • llvm.gcwrite: Substitute a store instruction.
  • +
+ +

If CustomReadBarriers or CustomWriteBarriers are specified, +then performCustomLowering must eliminate the +corresponding barriers.

+ +

performCustomLowering must comply with the same restrictions as FunctionPass::runOnFunction. +Likewise, initializeCustomLowering has the same semantics as Pass::doInitialization(Module&).

+ +

The following can be used as a template:

+ +
#include "llvm/Module.h"
+#include "llvm/IntrinsicInst.h"
+
+bool MyGC::initializeCustomLowering(Module &M) {
+  return false;
+}
+
+bool MyGC::performCustomLowering(Function &F) {
+  bool MadeChange = false;
+  
+  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+    for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; )
+      if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++))
+        if (Function *F = CI->getCalledFunction())
+          switch (F->getIntrinsicID()) {
+          case Intrinsic::gcwrite:
+            // Handle llvm.gcwrite.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          case Intrinsic::gcread:
+            // Handle llvm.gcread.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          case Intrinsic::gcroot:
+            // Handle llvm.gcroot.
+            CI->eraseFromParent();
+            MadeChange = true;
+            break;
+          }
+  
+  return MadeChange;
+}
+ +
+ + + + + +
+ +

LLVM can compute four kinds of safe points:

+ +
namespace GC {
+  /// PointKind - The type of a collector-safe point.
+  /// 
+  enum PointKind {
+    Loop,    //< Instr is a loop (backwards branch).
+    Return,  //< Instr is a return instruction.
+    PreCall, //< Instr is a call instruction.
+    PostCall //< Instr is the return address of a call.
+  };
+}
+ +

A collector can request any combination of the four by setting the +NeededSafePoints mask:

+ +
MyGC::MyGC() {
+  NeededSafePoints = 1 << GC::Loop
+                   | 1 << GC::Return
+                   | 1 << GC::PreCall
+                   | 1 << GC::PostCall;
+}
+ +

It can then use the following routines to access safe points.

+ +
for (iterator I = begin(), E = end(); I != E; ++I) {
+  GCFunctionInfo *MD = *I;
+  size_t PointCount = MD->size();
+
+  for (GCFunctionInfo::iterator PI = MD->begin(),
+                                PE = MD->end(); PI != PE; ++PI) {
+    GC::PointKind PointKind = PI->Kind;
+    unsigned PointNum = PI->Num;
+  }
+}
+
+ +

Almost every collector requires PostCall safe points, since these +correspond to the moments when the function is suspended during a call to a +subroutine.

+ +

Threaded programs generally require Loop safe points to guarantee +that the application will reach a safe point within a bounded amount of time, +even if it is executing a long-running loop which contains no function +calls.

+ +

Threaded collectors may also require Return and PreCall +safe points to implement "stop the world" techniques using self-modifying code, +where it is important that the program not exit the function without reaching a +safe point (because only the topmost function has been patched).

+ +
+ + + + + +
+ +

LLVM allows a plugin to print arbitrary assembly code before and after the +rest of a module's assembly code. At the end of the module, the GC can compile +the LLVM stack map into assembly code. (At the beginning, this information is not +yet computed.)

+ +

Since AsmWriter and CodeGen are separate components of LLVM, a separate +abstract base class and registry is provided for printing assembly code, the +GCMetadaPrinter and GCMetadataPrinterRegistry. The AsmWriter +will look for such a subclass if the GCStrategy sets +UsesMetadata:

+ +
MyGC::MyGC() {
+  UsesMetadata = true;
+}
+ +

This separation allows JIT-only clients to be smaller.

+ +

Note that LLVM does not currently have analogous APIs to support code +generation in the JIT, nor using the object writers.

+ +
// lib/MyGC/MyGCPrinter.cpp - Example LLVM GC printer
+
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/Support/Compiler.h"
+
+using namespace llvm;
+
+namespace {
+  class LLVM_LIBRARY_VISIBILITY MyGCPrinter : public GCMetadataPrinter {
+  public:
+    virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP,
+                               const TargetAsmInfo &TAI);
+  
+    virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP,
+                                const TargetAsmInfo &TAI);
+  };
+  
+  GCMetadataPrinterRegistry::Add<MyGCPrinter>
+  X("mygc", "My bespoke garbage collector.");
+}
+ +

The collector should use AsmPrinter and TargetAsmInfo to +print portable assembly code to the std::ostream. The collector itself +contains the stack map for the entire module, and may access the +GCFunctionInfo using its own begin() and end() +methods. Here's a realistic example:

+ +
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Function.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetAsmInfo.h"
+
+void MyGCPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP,
+                                const TargetAsmInfo &TAI) {
+  // Nothing to do.
+}
+
+void MyGCPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP,
+                                 const TargetAsmInfo &TAI) {
+  // Set up for emitting addresses.
+  const char *AddressDirective;
+  int AddressAlignLog;
+  if (AP.TM.getTargetData()->getPointerSize() == sizeof(int32_t)) {
+    AddressDirective = TAI.getData32bitsDirective();
+    AddressAlignLog = 2;
+  } else {
+    AddressDirective = TAI.getData64bitsDirective();
+    AddressAlignLog = 3;
+  }
+  
+  // Put this in the data section.
+  AP.SwitchToDataSection(TAI.getDataSection());
+  
+  // For each function...
+  for (iterator FI = begin(), FE = end(); FI != FE; ++FI) {
+    GCFunctionInfo &MD = **FI;
+    
+    // Emit this data structure:
+    // 
+    // struct {
+    //   int32_t PointCount;
+    //   struct {
+    //     void *SafePointAddress;
+    //     int32_t LiveCount;
+    //     int32_t LiveOffsets[LiveCount];
+    //   } Points[PointCount];
+    // } __gcmap_<FUNCTIONNAME>;
+    
+    // Align to address width.
+    AP.EmitAlignment(AddressAlignLog);
+    
+    // Emit the symbol by which the stack map entry can be found.
+    std::string Symbol;
+    Symbol += TAI.getGlobalPrefix();
+    Symbol += "__gcmap_";
+    Symbol += MD.getFunction().getName();
+    if (const char *GlobalDirective = TAI.getGlobalDirective())
+      OS << GlobalDirective << Symbol << "\n";
+    OS << TAI.getGlobalPrefix() << Symbol << ":\n";
+    
+    // Emit PointCount.
+    AP.EmitInt32(MD.size());
+    AP.EOL("safe point count");
+    
+    // And each safe point...
+    for (GCFunctionInfo::iterator PI = MD.begin(),
+                                     PE = MD.end(); PI != PE; ++PI) {
+      // Align to address width.
+      AP.EmitAlignment(AddressAlignLog);
+      
+      // Emit the address of the safe point.
+      OS << AddressDirective
+         << TAI.getPrivateGlobalPrefix() << "label" << PI->Num;
+      AP.EOL("safe point address");
+      
+      // Emit the stack frame size.
+      AP.EmitInt32(MD.getFrameSize());
+      AP.EOL("stack frame size");
+      
+      // Emit the number of live roots in the function.
+      AP.EmitInt32(MD.live_size(PI));
+      AP.EOL("live root count");
+      
+      // And for each live root...
+      for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
+                                            LE = MD.live_end(PI);
+                                            LI != LE; ++LI) {
+        // Print its offset within the stack frame.
+        AP.EmitInt32(LI->StackOffset);
+        AP.EOL("stack offset");
+      }
+    }
+  }
+}
+
+ +
+ + + + + + +
+ +

[Appel89] Runtime Tags Aren't Necessary. Andrew +W. Appel. Lisp and Symbolic Computation 19(7):703-705, July 1989.

+ +

[Goldberg91] Tag-free garbage collection for +strongly typed programming languages. Benjamin Goldberg. ACM SIGPLAN +PLDI'91.

+ +

[Tolmach94] Tag-free garbage collection using +explicit type parameters. Andrew Tolmach. Proceedings of the 1994 ACM +conference on LISP and functional programming.

+ +

[Henderson2002] +Accurate Garbage Collection in an Uncooperative Environment. +Fergus Henderson. International Symposium on Memory Management 2002.

+ +
+ + + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/GetElementPtr.html b/final/docs/GetElementPtr.html new file mode 100644 index 00000000000..41c45cab12d --- /dev/null +++ b/final/docs/GetElementPtr.html @@ -0,0 +1,739 @@ + + + + + The Often Misunderstood GEP Instruction + + + + + +
+ The Often Misunderstood GEP Instruction +
+ +
    +
  1. Introduction
  2. +
  3. Address Computation +
      +
    1. Why is the extra 0 index required?
    2. +
    3. What is dereferenced by GEP?
    4. +
    5. Why can you index through the first pointer but not + subsequent ones?
    6. +
    7. Why don't GEP x,0,0,1 and GEP x,1 alias?
    8. +
    9. Why do GEP x,1,0,0 and GEP x,1 alias?
    10. +
    11. Can GEP index into vector elements? +
    12. What effect do address spaces have on GEPs? +
    13. How is GEP different from ptrtoint, arithmetic, and inttoptr?
    14. +
    15. I'm writing a backend for a target which needs custom lowering for GEP. How do I do this? +
    16. How does VLA addressing work with GEPs? +
  4. +
  5. Rules +
      +
    1. What happens if an array index is out of bounds? +
    2. Can array indices be negative? +
    3. Can I compare two values computed with GEPs? +
    4. Can I do GEP with a different pointer type than the type of the underlying object? +
    5. Can I cast an object's address to integer and add it to null? +
    6. Can I compute the distance between two objects, and add that value to one address to compute the other address? +
    7. Can I do type-based alias analysis on LLVM IR? +
    8. What happens if a GEP computation overflows? +
    9. How can I tell if my front-end is following the rules? +
  6. +
  7. Rationale +
      +
    1. Why is GEP designed this way?
    2. +
    3. Why do struct member indices always use i32?
    4. +
    5. What's an uglygep? +
  8. +
  9. Summary
  10. +
+ +
+

Written by: Reid Spencer.

+
+ + + + + + +
+

This document seeks to dispel the mystery and confusion surrounding LLVM's + GetElementPtr (GEP) instruction. + Questions about the wily GEP instruction are + probably the most frequently occurring questions once a developer gets down to + coding with LLVM. Here we lay out the sources of confusion and show that the + GEP instruction is really quite simple. +

+
+ + + + +
+

When people are first confronted with the GEP instruction, they tend to + relate it to known concepts from other programming paradigms, most notably C + array indexing and field selection. GEP closely resembles C array indexing + and field selection, however it's is a little different and this leads to + the following questions.

+
+ + + +
+

Quick answer: The index stepping through the first operand.

+

The confusion with the first index usually arises from thinking about + the GetElementPtr instruction as if it was a C index operator. They aren't the + same. For example, when we write, in "C":

+ +
+
+AType *Foo;
+...
+X = &Foo->F;
+
+
+ +

it is natural to think that there is only one index, the selection of the + field F. However, in this example, Foo is a pointer. That + pointer must be indexed explicitly in LLVM. C, on the other hand, indices + through it transparently. To arrive at the same address location as the C + code, you would provide the GEP instruction with two index operands. The + first operand indexes through the pointer; the second operand indexes the + field F of the structure, just as if you wrote:

+ +
+
+X = &Foo[0].F;
+
+
+ +

Sometimes this question gets rephrased as:

+

Why is it okay to index through the first pointer, but + subsequent pointers won't be dereferenced?

+

The answer is simply because memory does not have to be accessed to + perform the computation. The first operand to the GEP instruction must be a + value of a pointer type. The value of the pointer is provided directly to + the GEP instruction as an operand without any need for accessing memory. It + must, therefore be indexed and requires an index operand. Consider this + example:

+ +
+
+struct munger_struct {
+  int f1;
+  int f2;
+};
+void munge(struct munger_struct *P) {
+  P[0].f1 = P[1].f1 + P[2].f2;
+}
+...
+munger_struct Array[3];
+...
+munge(Array);
+
+
+ +

In this "C" example, the front end compiler (llvm-gcc) will generate three + GEP instructions for the three indices through "P" in the assignment + statement. The function argument P will be the first operand of each + of these GEP instructions. The second operand indexes through that pointer. + The third operand will be the field offset into the + struct munger_struct type, for either the f1 or + f2 field. So, in LLVM assembly the munge function looks + like:

+ +
+
+void %munge(%struct.munger_struct* %P) {
+entry:
+  %tmp = getelementptr %struct.munger_struct* %P, i32 1, i32 0
+  %tmp = load i32* %tmp
+  %tmp6 = getelementptr %struct.munger_struct* %P, i32 2, i32 1
+  %tmp7 = load i32* %tmp6
+  %tmp8 = add i32 %tmp7, %tmp
+  %tmp9 = getelementptr %struct.munger_struct* %P, i32 0, i32 0
+  store i32 %tmp8, i32* %tmp9
+  ret void
+}
+
+
+ +

In each case the first operand is the pointer through which the GEP + instruction starts. The same is true whether the first operand is an + argument, allocated memory, or a global variable.

+

To make this clear, let's consider a more obtuse example:

+ +
+
+%MyVar = uninitialized global i32
+...
+%idx1 = getelementptr i32* %MyVar, i64 0
+%idx2 = getelementptr i32* %MyVar, i64 1
+%idx3 = getelementptr i32* %MyVar, i64 2
+
+
+ +

These GEP instructions are simply making address computations from the + base address of MyVar. They compute, as follows (using C syntax): +

+ +
+
+idx1 = (char*) &MyVar + 0
+idx2 = (char*) &MyVar + 4
+idx3 = (char*) &MyVar + 8
+
+
+ +

Since the type i32 is known to be four bytes long, the indices + 0, 1 and 2 translate into memory offsets of 0, 4, and 8, respectively. No + memory is accessed to make these computations because the address of + %MyVar is passed directly to the GEP instructions.

+

The obtuse part of this example is in the cases of %idx2 and + %idx3. They result in the computation of addresses that point to + memory past the end of the %MyVar global, which is only one + i32 long, not three i32s long. While this is legal in LLVM, + it is inadvisable because any load or store with the pointer that results + from these GEP instructions would produce undefined results.

+
+ + + + +
+

Quick answer: there are no superfluous indices.

+

This question arises most often when the GEP instruction is applied to a + global variable which is always a pointer type. For example, consider + this:

+ +
+
+%MyStruct = uninitialized global { float*, i32 }
+...
+%idx = getelementptr { float*, i32 }* %MyStruct, i64 0, i32 1
+
+
+ +

The GEP above yields an i32* by indexing the i32 typed + field of the structure %MyStruct. When people first look at it, they + wonder why the i64 0 index is needed. However, a closer inspection + of how globals and GEPs work reveals the need. Becoming aware of the following + facts will dispel the confusion:

+
    +
  1. The type of %MyStruct is not { float*, i32 } + but rather { float*, i32 }*. That is, %MyStruct is a + pointer to a structure containing a pointer to a float and an + i32.
  2. +
  3. Point #1 is evidenced by noticing the type of the first operand of + the GEP instruction (%MyStruct) which is + { float*, i32 }*.
  4. +
  5. The first index, i64 0 is required to step over the global + variable %MyStruct. Since the first argument to the GEP + instruction must always be a value of pointer type, the first index + steps through that pointer. A value of 0 means 0 elements offset from that + pointer.
  6. +
  7. The second index, i32 1 selects the second field of the + structure (the i32).
  8. +
+
+ + + +
+

Quick answer: nothing.

+

The GetElementPtr instruction dereferences nothing. That is, it doesn't + access memory in any way. That's what the Load and Store instructions are for. + GEP is only involved in the computation of addresses. For example, consider + this:

+ +
+
+%MyVar = uninitialized global { [40 x i32 ]* }
+...
+%idx = getelementptr { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17
+
+
+ +

In this example, we have a global variable, %MyVar that is a + pointer to a structure containing a pointer to an array of 40 ints. The + GEP instruction seems to be accessing the 18th integer of the structure's + array of ints. However, this is actually an illegal GEP instruction. It + won't compile. The reason is that the pointer in the structure must + be dereferenced in order to index into the array of 40 ints. Since the + GEP instruction never accesses memory, it is illegal.

+

In order to access the 18th integer in the array, you would need to do the + following:

+ +
+
+%idx = getelementptr { [40 x i32]* }* %, i64 0, i32 0
+%arr = load [40 x i32]** %idx
+%idx = getelementptr [40 x i32]* %arr, i64 0, i64 17
+
+
+ +

In this case, we have to load the pointer in the structure with a load + instruction before we can index into the array. If the example was changed + to:

+ +
+
+%MyVar = uninitialized global { [40 x i32 ] }
+...
+%idx = getelementptr { [40 x i32] }*, i64 0, i32 0, i64 17
+
+
+ +

then everything works fine. In this case, the structure does not contain a + pointer and the GEP instruction can index through the global variable, + into the first field of the structure and access the 18th i32 in the + array there.

+
+ + + +
+

Quick Answer: They compute different address locations.

+

If you look at the first indices in these GEP + instructions you find that they are different (0 and 1), therefore the address + computation diverges with that index. Consider this example:

+ +
+
+%MyVar = global { [10 x i32 ] }
+%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
+%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
+
+
+ +

In this example, idx1 computes the address of the second integer + in the array that is in the structure in %MyVar, that is + MyVar+4. The type of idx1 is i32*. However, + idx2 computes the address of the next structure after + %MyVar. The type of idx2 is { [10 x i32] }* and its + value is equivalent to MyVar + 40 because it indexes past the ten + 4-byte integers in MyVar. Obviously, in such a situation, the + pointers don't alias.

+ +
+ + + +
+

Quick Answer: They compute the same address location.

+

These two GEP instructions will compute the same address because indexing + through the 0th element does not change the address. However, it does change + the type. Consider this example:

+ +
+
+%MyVar = global { [10 x i32 ] }
+%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
+%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
+
+
+ +

In this example, the value of %idx1 is %MyVar+40 and + its type is i32*. The value of %idx2 is also + MyVar+40 but its type is { [10 x i32] }*.

+
+ + + + +
+

This hasn't always been forcefully disallowed, though it's not recommended. + It leads to awkward special cases in the optimizers, and fundamental + inconsistency in the IR. In the future, it will probably be outright + disallowed.

+ +
+ + + + +
+

None, except that the address space qualifier on the first operand pointer + type always matches the address space qualifier on the result type.

+ +
+ + + + +
+

It's very similar; there are only subtle differences.

+ +

With ptrtoint, you have to pick an integer type. One approach is to pick i64; + this is safe on everything LLVM supports (LLVM internally assumes pointers + are never wider than 64 bits in many places), and the optimizer will actually + narrow the i64 arithmetic down to the actual pointer size on targets which + don't support 64-bit arithmetic in most cases. However, there are some cases + where it doesn't do this. With GEP you can avoid this problem. + +

Also, GEP carries additional pointer aliasing rules. It's invalid to take a + GEP from one object, address into a different separately allocated + object, and dereference it. IR producers (front-ends) must follow this rule, + and consumers (optimizers, specifically alias analysis) benefit from being + able to rely on it. See the Rules section for more + information.

+ +

And, GEP is more concise in common cases.

+ +

However, for the underlying integer computation implied, there + is no difference.

+ +
+ + + + +
+

You don't. The integer computation implied by a GEP is target-independent. + Typically what you'll need to do is make your backend pattern-match + expressions trees involving ADD, MUL, etc., which are what GEP is lowered + into. This has the advantage of letting your code work correctly in more + cases.

+ +

GEP does use target-dependent parameters for the size and layout of data + types, which targets can customize.

+ +

If you require support for addressing units which are not 8 bits, you'll + need to fix a lot of code in the backend, with GEP lowering being only a + small piece of the overall picture.

+ +
+ + + + +
+

GEPs don't natively support VLAs. LLVM's type system is entirely static, + and GEP address computations are guided by an LLVM type.

+ +

VLA indices can be implemented as linearized indices. For example, an + expression like X[a][b][c], must be effectively lowered into a form + like X[a*m+b*n+c], so that it appears to the GEP as a single-dimensional + array reference.

+ +

This means if you want to write an analysis which understands array + indices and you want to support VLAs, your code will have to be + prepared to reverse-engineer the linearization. One way to solve this + problem is to use the ScalarEvolution library, which always presents + VLA and non-VLA indexing in the same manner.

+
+ + + + + + + + +
+

There are two senses in which an array index can be out of bounds.

+ +

First, there's the array type which comes from the (static) type of + the first operand to the GEP. Indices greater than the number of elements + in the corresponding static array type are valid. There is no problem with + out of bounds indices in this sense. Indexing into an array only depends + on the size of the array element, not the number of elements.

+ +

A common example of how this is used is arrays where the size is not known. + It's common to use array types with zero length to represent these. The + fact that the static type says there are zero elements is irrelevant; it's + perfectly valid to compute arbitrary element indices, as the computation + only depends on the size of the array element, not the number of + elements. Note that zero-sized arrays are not a special case here.

+ +

This sense is unconnected with inbounds keyword. The + inbounds keyword is designed to describe low-level pointer + arithmetic overflow conditions, rather than high-level array + indexing rules. + +

Analysis passes which wish to understand array indexing should not + assume that the static array type bounds are respected.

+ +

The second sense of being out of bounds is computing an address that's + beyond the actual underlying allocated object.

+ +

With the inbounds keyword, the result value of the GEP is + undefined if the address is outside the actual underlying allocated + object and not the address one-past-the-end.

+ +

Without the inbounds keyword, there are no restrictions + on computing out-of-bounds addresses. Obviously, performing a load or + a store requires an address of allocated and sufficiently aligned + memory. But the GEP itself is only concerned with computing addresses.

+ +
+ + + +
+

Yes. This is basically a special case of array indices being out + of bounds.

+ +
+ + + +
+

Yes. If both addresses are within the same allocated object, or + one-past-the-end, you'll get the comparison result you expect. If either + is outside of it, integer arithmetic wrapping may occur, so the + comparison may not be meaningful.

+ +
+ + + +
+

Yes. There are no restrictions on bitcasting a pointer value to an arbitrary + pointer type. The types in a GEP serve only to define the parameters for the + underlying integer computation. They need not correspond with the actual + type of the underlying object.

+ +

Furthermore, loads and stores don't have to use the same types as the type + of the underlying object. Types in this context serve only to specify + memory size and alignment. Beyond that there are merely a hint to the + optimizer indicating how the value will likely be used.

+ +
+ + + +
+

You can compute an address that way, but if you use GEP to do the add, + you can't use that pointer to actually access the object, unless the + object is managed outside of LLVM.

+ +

The underlying integer computation is sufficiently defined; null has a + defined value -- zero -- and you can add whatever value you want to it.

+ +

However, it's invalid to access (load from or store to) an LLVM-aware + object with such a pointer. This includes GlobalVariables, Allocas, and + objects pointed to by noalias pointers.

+ +

If you really need this functionality, you can do the arithmetic with + explicit integer instructions, and use inttoptr to convert the result to + an address. Most of GEP's special aliasing rules do not apply to pointers + computed from ptrtoint, arithmetic, and inttoptr sequences.

+ +
+ + + +
+

As with arithmetic on null, You can use GEP to compute an address that + way, but you can't use that pointer to actually access the object if you + do, unless the object is managed outside of LLVM.

+ +

Also as above, ptrtoint and inttoptr provide an alternative way to do this + which do not have this restriction.

+ +
+ + + +
+

You can't do type-based alias analysis using LLVM's built-in type system, + because LLVM has no restrictions on mixing types in addressing, loads or + stores.

+ +

It would be possible to add special annotations to the IR, probably using + metadata, to describe a different type system (such as the C type system), + and do type-based aliasing on top of that. This is a much bigger + undertaking though.

+ +
+ + + + +
+

If the GEP lacks the inbounds keyword, the value is the result + from evaluating the implied two's complement integer computation. However, + since there's no guarantee of where an object will be allocated in the + address space, such values have limited meaning.

+ +

If the GEP has the inbounds keyword, the result value is + undefined (a "trap value") if the GEP + overflows (i.e. wraps around the end of the address space).

+ +

As such, there are some ramifications of this for inbounds GEPs: scales + implied by array/vector/pointer indices are always known to be "nsw" since + they are signed values that are scaled by the element size. These values + are also allowed to be negative (e.g. "gep i32 *%P, i32 -1") but the + pointer itself is logically treated as an unsigned value. This means that + GEPs have an asymmetric relation between the pointer base (which is treated + as unsigned) and the offset applied to it (which is treated as signed). The + result of the additions within the offset calculation cannot have signed + overflow, but when applied to the base pointer, there can be signed + overflow. +

+ + +
+ + + + +
+

There is currently no checker for the getelementptr rules. Currently, + the only way to do this is to manually check each place in your front-end + where GetElementPtr operators are created.

+ +

It's not possible to write a checker which could find all rule + violations statically. It would be possible to write a checker which + works by instrumenting the code with dynamic checks though. Alternatively, + it would be possible to write a static checker which catches a subset of + possible problems. However, no such checker exists today.

+ +
+ + + + + + + + +
+

The design of GEP has the following goals, in rough unofficial + order of priority:

+
    +
  • Support C, C-like languages, and languages which can be + conceptually lowered into C (this covers a lot).
  • +
  • Support optimizations such as those that are common in + C compilers. In particular, GEP is a cornerstone of LLVM's + pointer aliasing model.
  • +
  • Provide a consistent method for computing addresses so that + address computations don't need to be a part of load and + store instructions in the IR.
  • +
  • Support non-C-like languages, to the extent that it doesn't + interfere with other goals.
  • +
  • Minimize target-specific information in the IR.
  • +
+
+ + + +
+

The specific type i32 is probably just a historical artifact, however it's + wide enough for all practical purposes, so there's been no need to change it. + It doesn't necessarily imply i32 address arithmetic; it's just an identifier + which identifies a field in a struct. Requiring that all struct indices be + the same reduces the range of possibilities for cases where two GEPs are + effectively the same but have distinct operand types.

+ +
+ + + + +
+

Some LLVM optimizers operate on GEPs by internally lowering them into + more primitive integer expressions, which allows them to be combined + with other integer expressions and/or split into multiple separate + integer expressions. If they've made non-trivial changes, translating + back into LLVM IR can involve reverse-engineering the structure of + the addressing in order to fit it into the static type of the original + first operand. It isn't always possibly to fully reconstruct this + structure; sometimes the underlying addressing doesn't correspond with + the static type at all. In such cases the optimizer instead will emit + a GEP with the base pointer casted to a simple address-unit pointer, + using the name "uglygep". This isn't pretty, but it's just as + valid, and it's sufficient to preserve the pointer aliasing guarantees + that GEP provides.

+ +
+ + + + + +
+

In summary, here's some things to always remember about the GetElementPtr + instruction:

+
    +
  1. The GEP instruction never accesses memory, it only provides pointer + computations.
  2. +
  3. The first operand to the GEP instruction is always a pointer and it must + be indexed.
  4. +
  5. There are no superfluous indices for the GEP instruction.
  6. +
  7. Trailing zero indices are superfluous for pointer aliasing, but not for + the types of the pointers.
  8. +
  9. Leading zero indices are not superfluous for pointer aliasing nor the + types of the pointers.
  10. +
+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/GettingStarted.html b/final/docs/GettingStarted.html new file mode 100644 index 00000000000..9fa8a7793df --- /dev/null +++ b/final/docs/GettingStarted.html @@ -0,0 +1,1702 @@ + + + + + Getting Started with LLVM System + + + + +
+ Getting Started with the LLVM System +
+ + + +
+

Written by: + John Criswell, + Chris Lattner, + Misha Brukman, + Vikram Adve, and + Guochun Shi. +

+
+ + + + + + +
+ +

Welcome to LLVM! In order to get started, you first need to know some +basic information.

+ +

First, LLVM comes in three pieces. The first piece is the LLVM +suite. This contains all of the tools, libraries, and header files +needed to use the low level virtual machine. It contains an +assembler, disassembler, bitcode analyzer and bitcode optimizer. It +also contains basic regression tests that can be used to test the LLVM +tools and the GCC front end.

+ +

The second piece is the GCC front end. This component provides a version of +GCC that compiles C and C++ code into LLVM bitcode. Currently, the GCC front +end uses the GCC parser to convert code to LLVM. Once +compiled into LLVM bitcode, a program can be manipulated with the LLVM tools +from the LLVM suite.

+ +

+There is a third, optional piece called Test Suite. It is a suite of programs +with a testing harness that can be used to further test LLVM's functionality +and performance. +

+ +
+ + + + + +
+ +

Here's the short story for getting up and running quickly with LLVM:

+ +
    +
  1. Read the documentation.
  2. +
  3. Read the documentation.
  4. +
  5. Remember that you were warned twice about reading the documentation.
  6. +
  7. Install the llvm-gcc-4.2 front end if you intend to compile C or C++ + (see Install the GCC Front End for details):
  8. +
      +
    1. cd where-you-want-the-C-front-end-to-live
    2. +
    3. gunzip --stdout llvm-gcc-4.2-version-platform.tar.gz | tar -xvf -
    4. +
    5. install-binutils-binary-from-MinGW (Windows only)
    6. +
    7. Note: If the binary extension is ".bz" use bunzip2 instead of gunzip.
    8. +
    9. Note: On Windows, use 7-Zip or a similar archiving tool.
    10. +
    11. Add llvm-gcc's "bin" directory to your PATH environment variable.
    12. +
    + +
  9. Get the LLVM Source Code +
      +
    • With the distributed files (or use SVN): +
        +
      1. cd where-you-want-llvm-to-live +
      2. gunzip --stdout llvm-version.tar.gz | tar -xvf - +
    • + +
  10. + +
  11. [Optional] Get the Test Suite Source Code +
      +
    • With the distributed files (or use SVN): +
        +
      1. cd where-you-want-llvm-to-live +
      2. cd llvm/projects +
      3. gunzip --stdout llvm-test-version.tar.gz | tar -xvf - +
      4. mv llvm-test-version test-suite +
    • + +
  12. + + +
  13. Configure the LLVM Build Environment +
      +
    1. cd where-you-want-to-build-llvm
    2. +
    3. /path/to/llvm/configure [options]
      + Some common options: + +
        +
      • --prefix=directory +

        Specify for directory the full pathname of where you + want the LLVM tools and libraries to be installed (default + /usr/local).

      • +
      • --with-llvmgccdir=directory +

        Optionally, specify for directory the full pathname of the + C/C++ front end installation to use with this LLVM configuration. If + not specified, the PATH will be searched. This is only needed if you + want to run test-suite or do some special kinds of LLVM builds.

      • +
      • --enable-spec2000=directory +

        Enable the SPEC2000 benchmarks for testing. The SPEC2000 + benchmarks should be available in + directory.

      • +
      +
  14. + +
  15. Build the LLVM Suite: +
      +
    1. gmake -k |& tee gnumake.out +    # this is csh or tcsh syntax
    2. +
    3. If you get an "internal compiler error (ICE)" or test failures, see + below.
    4. +
    + +
+ +

Consult the Getting Started with LLVM section for +detailed information on configuring and compiling LLVM. See Setting Up Your Environment for tips that simplify +working with the GCC front end and LLVM tools. Go to Program +Layout to learn about the layout of the source code tree.

+ +
+ + + + + +
+ +

Before you begin to use the LLVM system, review the requirements given below. +This may save you some trouble by knowing ahead of time what hardware and +software you will need.

+ +
+ + + + +
+ +

LLVM is known to work on the following platforms:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSArchCompilers
AuroraUXx861GCC
Linuxx861GCC
Linuxamd64GCC
SolarisV9 (Ultrasparc)GCC
FreeBSDx861GCC
FreeBSDamd64GCC
MacOS X2PowerPCGCC
MacOS X2,9x86GCC
Cygwin/Win32x861,8, + 11GCC 3.4.X, binutils 2.20
MinGW/Win32x861,6, + 8, 10GCC 3.4.X, binutils 2.20
+ +

LLVM has partial support for the following platforms:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OSArchCompilers
Windowsx861Visual Studio 2005 SP1 or higher4,5
AIX3,4PowerPCGCC
Linux3,5PowerPCGCC
Linux7AlphaGCC
Linux7Itanium (IA-64)GCC
HP-UX7Itanium (IA-64)HP aCC
+ +

Notes:

+ + + +

Note that you will need about 1-3 GB of space for a full LLVM build in Debug +mode, depending on the system (it is so large because of all the debugging +information and the fact that the libraries are statically linked into multiple +tools). If you do not need many of the tools and you are space-conscious, you +can pass ONLY_TOOLS="tools you need" to make. The Release build +requires considerably less space.

+ +

The LLVM suite may compile on other platforms, but it is not +guaranteed to do so. If compilation is successful, the LLVM utilities should be +able to assemble, disassemble, analyze, and optimize LLVM bitcode. Code +generation should work as well, although the generated native code may not work +on your platform.

+ +

The GCC front end is not very portable at the moment. If you want to get it +to work on another platform, you can download a copy of the source and try to compile it on your platform.

+ +
+ + + +
+

Compiling LLVM requires that you have several software packages + installed. The table below lists those required packages. The Package column + is the usual name for the software package that LLVM depends on. The Version + column provides "known to work" versions of the package. The Notes column + describes how LLVM uses the package and provides other details.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PackageVersionNotes
GNU Make3.79, 3.79.1Makefile/build processor
GCC3.4.2C/C++ compiler1
TeXinfo4.5For building the CFE
SVN≥1.3Subversion access to LLVM2
DejaGnu1.4.2Automated test suite3
tcl8.3, 8.4Automated test suite3
expect5.38.0Automated test suite3
perl≥5.6.0Nightly tester, utilities
GNU M4 + 1.4Macro processor for configuration4
GNU Autoconf2.60Configuration script builder4
GNU Automake1.9.6aclocal macro generator4
libtool1.5.22Shared library manager4
+ +

Notes:

+ + +

Additionally, your compilation host is expected to have the usual + plethora of Unix utilities. Specifically:

+
    +
  • ar - archive library builder
  • +
  • bzip2* - bzip2 command for distribution generation
  • +
  • bunzip2* - bunzip2 command for distribution checking
  • +
  • chmod - change permissions on a file
  • +
  • cat - output concatenation utility
  • +
  • cp - copy files
  • +
  • date - print the current date/time
  • +
  • echo - print to standard output
  • +
  • egrep - extended regular expression search utility
  • +
  • find - find files/dirs in a file system
  • +
  • grep - regular expression search utility
  • +
  • gzip* - gzip command for distribution generation
  • +
  • gunzip* - gunzip command for distribution checking
  • +
  • install - install directories/files
  • +
  • mkdir - create a directory
  • +
  • mv - move (rename) files
  • +
  • ranlib - symbol table builder for archive libraries
  • +
  • rm - remove (delete) files and directories
  • +
  • sed - stream editor for transforming output
  • +
  • sh - Bourne shell for make build scripts
  • +
  • tar - tape archive for distribution generation
  • +
  • test - test things in file system
  • +
  • unzip* - unzip command for distribution checking
  • +
  • zip* - zip command for distribution generation
  • +
+
+ + + + +
+ +

LLVM is very demanding of the host C++ compiler, and as such tends to expose +bugs in the compiler. In particular, several versions of GCC crash when trying +to compile LLVM. We routinely use GCC 3.3.3, 3.4.0, and Apple 4.0.1 +successfully with them (however, see important notes below). Other versions +of GCC will probably work as well. GCC versions listed +here are known to not work. If you are using one of these versions, please try +to upgrade your GCC to something more recent. If you run into a problem with a +version of GCC not listed here, please let +us know. Please use the "gcc -v" command to find out which version +of GCC you are using. +

+ +

GCC versions prior to 3.0: GCC 2.96.x and before had several +problems in the STL that effectively prevent it from compiling LLVM. +

+ +

GCC 3.2.2 and 3.2.3: These versions of GCC fails to compile LLVM with +a bogus template error. This was fixed in later GCCs.

+ +

GCC 3.3.2: This version of GCC suffered from a serious bug which causes it to crash in +the "convert_from_eh_region_ranges_1" GCC function.

+ +

Cygwin GCC 3.3.3: The version of GCC 3.3.3 commonly shipped with + Cygwin does not work. Please upgrade + to a newer version if possible.

+

SuSE GCC 3.3.3: The version of GCC 3.3.3 shipped with SuSE 9.1 (and + possibly others) does not compile LLVM correctly (it appears that exception + handling is broken in some cases). Please download the FSF 3.3.3 or upgrade + to a newer version of GCC.

+

GCC 3.4.0 on linux/x86 (32-bit): GCC miscompiles portions of the + code generator, causing an infinite loop in the llvm-gcc build when built + with optimizations enabled (i.e. a release build).

+

GCC 3.4.2 on linux/x86 (32-bit): GCC miscompiles portions of the + code generator at -O3, as with 3.4.0. However gcc 3.4.2 (unlike 3.4.0) + correctly compiles LLVM at -O2. A work around is to build release LLVM + builds with "make ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2 ..."

+

GCC 3.4.x on X86-64/amd64: GCC + miscompiles portions of LLVM.

+

GCC 3.4.4 (CodeSourcery ARM 2005q3-2): this compiler miscompiles LLVM + when building with optimizations enabled. It appears to work with + "make ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O1" or build a debug + build.

+

IA-64 GCC 4.0.0: The IA-64 version of GCC 4.0.0 is known to + miscompile LLVM.

+

Apple Xcode 2.3: GCC crashes when compiling LLVM at -O3 (which is the + default with ENABLE_OPTIMIZED=1. To work around this, build with + "ENABLE_OPTIMIZED=1 OPTIMIZE_OPTION=-O2".

+

GCC 4.1.1: GCC fails to build LLVM with template concept check errors + compiling some files. At the time of this writing, GCC mainline (4.2) + did not share the problem.

+

GCC 4.1.1 on X86-64/amd64: GCC + miscompiles portions of LLVM when compiling llvm itself into 64-bit + code. LLVM will appear to mostly work but will be buggy, e.g. failing + portions of its testsuite.

+

GCC 4.1.2 on OpenSUSE: Seg faults during libstdc++ build and on x86_64 +platforms compiling md5.c gets a mangled constant.

+

GCC 4.1.2 (20061115 (prerelease) (Debian 4.1.1-21)) on Debian: Appears +to miscompile parts of LLVM 2.4. One symptom is ValueSymbolTable complaining +about symbols remaining in the table on destruction.

+

GCC 4.1.2 20071124 (Red Hat 4.1.2-42): Suffers from the same symptoms +as the previous one. It appears to work with ENABLE_OPTIMIZED=0 (the default).

+

Cygwin GCC 4.3.2 20080827 (beta) 2: + Users reported various problems related + with link errors when using this GCC version.

+

Debian GCC 4.3.2 on X86: Crashes building some files in LLVM 2.6.

+

GCC 4.3.3 (Debian 4.3.3-10) on ARM: Miscompiles parts of LLVM 2.6 +when optimizations are turned on. The symptom is an infinite loop in +FoldingSetImpl::RemoveNode while running the code generator.

+

GCC 4.3.5 and GCC 4.4.5 on ARM: These can miscompile value >> +1 even at -O0. A test failure in test/Assembler/alignstack.ll is +one symptom of the problem. +

GNU ld 2.16.X. Some 2.16.X versions of the ld linker will produce very +long warning messages complaining that some ".gnu.linkonce.t.*" symbol was +defined in a discarded section. You can safely ignore these messages as they are +erroneous and the linkage is correct. These messages disappear using ld +2.17.

+ +

GNU binutils 2.17: Binutils 2.17 contains a bug which +causes huge link times (minutes instead of seconds) when building LLVM. We +recommend upgrading to a newer version (2.17.50.0.4 or later).

+ +

GNU Binutils 2.19.1 Gold: This version of Gold contained +a bug +which causes intermittent failures when building LLVM with position independent +code. The symptom is an error about cyclic dependencies. We recommend +upgrading to a newer version of Gold.

+ +
+ + + + + + + +
+ +

The remainder of this guide is meant to get you up and running with +LLVM and to give you some basic information about the LLVM environment.

+ +

The later sections of this guide describe the general layout of the the LLVM source tree, a simple example using the LLVM tool chain, and links to find more information about LLVM or to get +help via e-mail.

+
+ + + + +
+ +

Throughout this manual, the following names are used to denote paths +specific to the local system and working environment. These are not +environment variables you need to set but just strings used in the rest +of this document below. In any of the examples below, simply replace +each of these names with the appropriate pathname on your local system. +All these paths are absolute:

+ +
+
SRC_ROOT +
+ This is the top level directory of the LLVM source tree. +

+ +
OBJ_ROOT +
+ This is the top level directory of the LLVM object tree (i.e. the + tree where object files and compiled programs will be placed. It + can be the same as SRC_ROOT). +

+ +
LLVMGCCDIR +
+ This is where the LLVM GCC Front End is installed. +

+ For the pre-built GCC front end binaries, the LLVMGCCDIR is + llvm-gcc/platform/llvm-gcc. +

+ +
+ + + + +
+ +

+In order to compile and use LLVM, you may need to set some environment +variables. + +

+
LLVM_LIB_SEARCH_PATH=/path/to/your/bitcode/libs
+
[Optional] This environment variable helps LLVM linking tools find the + locations of your bitcode libraries. It is provided only as a + convenience since you can specify the paths using the -L options of the + tools and the C/C++ front-end will automatically use the bitcode files + installed in its + lib directory.
+
+ +
+ + + + +
+ +

+If you have the LLVM distribution, you will need to unpack it before you +can begin to compile it. LLVM is distributed as a set of two files: the LLVM +suite and the LLVM GCC front end compiled for your platform. There is an +additional test suite that is optional. Each file is a TAR archive that is +compressed with the gzip program. +

+ +

The files are as follows, with x.y marking the version number: +

+
llvm-x.y.tar.gz
+
Source release for the LLVM libraries and tools.
+ +
llvm-test-x.y.tar.gz
+
Source release for the LLVM test-suite.
+ +
llvm-gcc-4.2-x.y.source.tar.gz
+
Source release of the llvm-gcc-4.2 front end. See README.LLVM in the root + directory for build instructions.
+ +
llvm-gcc-4.2-x.y-platform.tar.gz
+
Binary release of the llvm-gcc-4.2 front end for a specific platform.
+ +
+ +
+ + + + +
+ +

If you have access to our Subversion repository, you can get a fresh copy of +the entire source code. All you need to do is check it out from Subversion as +follows:

+ +
    +
  • cd where-you-want-llvm-to-live
  • +
  • Read-Only: svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
  • +
  • Read-Write:svn co https://user@llvm.org/svn/llvm-project/llvm/trunk + llvm
  • +
+ + +

This will create an 'llvm' directory in the current +directory and fully populate it with the LLVM source code, Makefiles, +test directories, and local copies of documentation files.

+ +

If you want to get a specific release (as opposed to the most recent +revision), you can checkout it from the 'tags' directory (instead of +'trunk'). The following releases are located in the following +subdirectories of the 'tags' directory:

+ +
    +
  • Release 2.9: RELEASE_29
  • +
  • Release 2.8: RELEASE_28
  • +
  • Release 2.7: RELEASE_27
  • +
  • Release 2.6: RELEASE_26
  • +
  • Release 2.5: RELEASE_25
  • +
  • Release 2.4: RELEASE_24
  • +
  • Release 2.3: RELEASE_23
  • +
  • Release 2.2: RELEASE_22
  • +
  • Release 2.1: RELEASE_21
  • +
  • Release 2.0: RELEASE_20
  • +
  • Release 1.9: RELEASE_19
  • +
  • Release 1.8: RELEASE_18
  • +
  • Release 1.7: RELEASE_17
  • +
  • Release 1.6: RELEASE_16
  • +
  • Release 1.5: RELEASE_15
  • +
  • Release 1.4: RELEASE_14
  • +
  • Release 1.3: RELEASE_13
  • +
  • Release 1.2: RELEASE_12
  • +
  • Release 1.1: RELEASE_11
  • +
  • Release 1.0: RELEASE_1
  • +
+ +

If you would like to get the LLVM test suite (a separate package as of 1.4), +you get it from the Subversion repository:

+ +
+
+% cd llvm/projects
+% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
+
+
+ +

By placing it in the llvm/projects, it will be automatically +configured by the LLVM configure script as well as automatically updated when +you run svn update.

+ +

If you would like to get the GCC front end source code, you can also get it +and build it yourself. Please follow these +instructions to successfully get and build the LLVM GCC front-end.

+ +
+ + + + +
+ +

GIT mirrors are available for a number of LLVM subprojects. These mirrors + sync automatically with each Subversion commit and contain all necessary + git-svn marks (so, you can recreate git-svn metadata locally). Note that right + now mirrors reflect only trunk for each project. You can do the + read-only GIT clone of LLVM via: +

+% git clone http://llvm.org/git/llvm.git
+
+

+ +
+ + + + +
+ +

Before configuring and compiling the LLVM suite (or if you want to use just the LLVM +GCC front end) you can optionally extract the front end from the binary distribution. +It is used for running the LLVM test-suite and for compiling C/C++ programs. Note that +you can optionally build llvm-gcc yourself after building the +main LLVM repository.

+ +

To install the GCC front end, do the following (on Windows, use an archival tool +like 7-zip that understands gzipped tars):

+ +
    +
  1. cd where-you-want-the-front-end-to-live
  2. +
  3. gunzip --stdout llvm-gcc-4.2-version-platform.tar.gz | tar -xvf + -
  4. +
+ +

Once the binary is uncompressed, if you're using a *nix-based system, add a symlink for +llvm-gcc and llvm-g++ to some directory in your path. If you're using a +Windows-based system, add the bin subdirectory of your front end installation directory +to your PATH environment variable. For example, if you uncompressed the binary to +c:\llvm-gcc, add c:\llvm-gcc\bin to your PATH.

+ +

If you now want to build LLVM from source, when you configure LLVM, it will +automatically detect llvm-gcc's presence (if it is in your path) enabling its +use in test-suite. Note that you can always build or install llvm-gcc at any +point after building the main LLVM repository: just reconfigure llvm and +test-suite will pick it up. +

+ +

As a convenience for Windows users, the front end binaries for MinGW/x86 include +versions of the required w32api and mingw-runtime binaries. The last remaining step for +Windows users is to simply uncompress the binary binutils package from +MinGW into your front end installation directory. While the +front end installation steps are not quite the same as a typical manual MinGW installation, +they should be similar enough to those who have previously installed MinGW on Windows systems.

+ +

To install binutils on Windows:

+ +
    +
  1. download GNU Binutils from MinGW Downloads
  2. +
  3. cd where-you-uncompressed-the-front-end
  4. +
  5. uncompress archived binutils directories (not the tar file) into the current directory
  6. +
+ +

The binary versions of the LLVM GCC front end may not suit all of your needs. For +example, the binary distribution may include an old version of a system header +file, not "fix" a header file that needs to be fixed for GCC, or it may be linked with +libraries not available on your system. In cases like these, you may want to try +building the GCC front end from source. Thankfully, +this is much easier now than it was in the past.

+ +

We also do not currently support updating of the GCC front end by manually overlaying +newer versions of the w32api and mingw-runtime binary packages that may become available +from MinGW. At this time, it's best to think of the MinGW LLVM GCC front end binary as +a self-contained convenience package that requires Windows users to simply download and +uncompress the GNU Binutils binary package from the MinGW project.

+ +

Regardless of your platform, if you discover that installing the LLVM GCC front end +binaries is not as easy as previously described, or you would like to suggest improvements, +please let us know how you would like to see things improved by dropping us a note on our +mailing list.

+ +
+ + + + +
+ +

Once checked out from the Subversion repository, the LLVM suite source + code must be +configured via the configure script. This script sets variables in the +various *.in files, most notably llvm/Makefile.config and +llvm/include/Config/config.h. It also populates OBJ_ROOT with +the Makefiles needed to begin building LLVM.

+ +

The following environment variables are used by the configure +script to configure the build system:

+ + + + + + + + + + + +
VariablePurpose
CCTells configure which C compiler to use. By default, + configure will look for the first GCC C compiler in + PATH. Use this variable to override + configure's default behavior.
CXXTells configure which C++ compiler to use. By default, + configure will look for the first GCC C++ compiler in + PATH. Use this variable to override + configure's default behavior.
+ +

The following options can be used to set or enable LLVM specific options:

+ +
+
--with-llvmgccdir
+
Path to the LLVM C/C++ FrontEnd to be used with this LLVM configuration. + The value of this option should specify the full pathname of the C/C++ Front + End to be used. If this option is not provided, the PATH will be searched for + a program named llvm-gcc and the C/C++ FrontEnd install directory will + be inferred from the path found. If the option is not given, and no llvm-gcc + can be found in the path then a warning will be produced by + configure indicating this situation. LLVM may still be built with + the tools-only target but attempting to build the runtime libraries + will fail as these libraries require llvm-gcc and llvm-g++. See + Install the GCC Front End for details on installing + the C/C++ Front End. See + Bootstrapping the LLVM C/C++ Front-End + for details on building the C/C++ Front End.
+
--with-tclinclude
+
Path to the tcl include directory under which tclsh can be + found. Use this if you have multiple tcl installations on your machine and you + want to use a specific one (8.x) for LLVM. LLVM only uses tcl for running the + dejagnu based test suite in llvm/test. If you don't specify this + option, the LLVM configure script will search for the tcl 8.4 and 8.3 + releases. +

+
+
--enable-optimized
+
+ Enables optimized compilation (debugging symbols are removed + and GCC optimization flags are enabled). Note that this is the default + setting if you are using the LLVM distribution. The default behavior + of an Subversion checkout is to use an unoptimized build (also known as a + debug build). +

+
+
--enable-debug-runtime
+
+ Enables debug symbols in the runtime libraries. The default is to strip + debug symbols from the runtime libraries. +
+
--enable-jit
+
+ Compile the Just In Time (JIT) compiler functionality. This is not + available + on all platforms. The default is dependent on platform, so it is best + to explicitly enable it if you want it. +

+
+
--enable-targets=target-option
+
Controls which targets will be built and linked into llc. The default + value for target_options is "all" which builds and links all + available targets. The value "host-only" can be specified to build only a + native compiler (no cross-compiler targets available). The "native" target is + selected as the target of the build host. You can also specify a comma + separated list of target names that you want available in llc. The target + names use all lower case. The current set of targets is:
+ alpha, ia64, powerpc, skeleton, sparc, x86. +

+
--enable-doxygen
+
Look for the doxygen program and enable construction of doxygen based + documentation from the source code. This is disabled by default because + generating the documentation can take a long time and producess 100s of + megabytes of output.
+
--with-udis86
+
LLVM can use external disassembler library for various purposes (now it's + used only for examining code produced by JIT). This option will enable usage + of udis86 x86 (both 32 and 64 + bits) disassembler library.
+
+ +

To configure LLVM, follow these steps:

+ +
    +
  1. Change directory into the object root directory:

    + +
    % cd OBJ_ROOT
  2. + +
  3. Run the configure script located in the LLVM source + tree:

    + +
    +
    % SRC_ROOT/configure --prefix=/install/path [other options]
    +
  4. +
+ +
+ + + + +
+ +

Once you have configured LLVM, you can build it. There are three types of +builds:

+ +
+
Debug Builds +
+ These builds are the default when one is using an Subversion checkout and + types gmake (unless the --enable-optimized option was + used during configuration). The build system will compile the tools and + libraries with debugging information. To get a Debug Build using the + LLVM distribution the --disable-optimized option must be passed + to configure. +

+ +
Release (Optimized) Builds +
+ These builds are enabled with the --enable-optimized option to + configure or by specifying ENABLE_OPTIMIZED=1 on the + gmake command line. For these builds, the build system will + compile the tools and libraries with GCC optimizations enabled and strip + debugging information from the libraries and executables it generates. + Note that Release Builds are default when using an LLVM distribution. +

+ +
Profile Builds +
+ These builds are for use with profiling. They compile profiling + information into the code for use with programs like gprof. + Profile builds must be started by specifying ENABLE_PROFILING=1 + on the gmake command line. +
+ +

Once you have LLVM configured, you can build it by entering the +OBJ_ROOT directory and issuing the following command:

+ +
% gmake
+ +

If the build fails, please check here to see if you +are using a version of GCC that is known not to compile LLVM.

+ +

+If you have multiple processors in your machine, you may wish to use some of +the parallel build options provided by GNU Make. For example, you could use the +command:

+ +
% gmake -j2
+ +

There are several special targets which are useful when working with the LLVM +source code:

+ +
+
gmake clean +
+ Removes all files generated by the build. This includes object files, + generated C/C++ files, libraries, and executables. +

+ +
gmake dist-clean +
+ Removes everything that gmake clean does, but also removes files + generated by configure. It attempts to return the source tree to the + original state in which it was shipped. +

+ +
gmake install +
+ Installs LLVM header files, libraries, tools, and documentation in a + hierarchy + under $PREFIX, specified with ./configure --prefix=[dir], which + defaults to /usr/local. +

+ +
gmake -C runtime install-bytecode +
+ Assuming you built LLVM into $OBJDIR, when this command is run, it will + install bitcode libraries into the GCC front end's bitcode library + directory. If you need to update your bitcode libraries, + this is the target to use once you've built them. +

+
+ +

Please see the Makefile Guide for further +details on these make targets and descriptions of other targets +available.

+ +

It is also possible to override default values from configure by +declaring variables on the command line. The following are some examples:

+ +
+
gmake ENABLE_OPTIMIZED=1 +
+ Perform a Release (Optimized) build. +

+ +
gmake ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1 +
+ Perform a Release (Optimized) build without assertions enabled. +

+ +
gmake ENABLE_OPTIMIZED=0 +
+ Perform a Debug build. +

+ +
gmake ENABLE_PROFILING=1 +
+ Perform a Profiling build. +

+ +
gmake VERBOSE=1 +
+ Print what gmake is doing on standard output. +

+ +
gmake TOOL_VERBOSE=1
+
Ask each tool invoked by the makefiles to print out what it is doing on + the standard output. This also implies VERBOSE=1. +

+
+ +

Every directory in the LLVM object tree includes a Makefile to build +it and any subdirectories that it contains. Entering any directory inside the +LLVM object tree and typing gmake should rebuild anything in or below +that directory that is out of date.

+ +
+ + + + +
+

It is possible to cross-compile LLVM itself. That is, you can create LLVM + executables and libraries to be hosted on a platform different from the + platform where they are build (a Canadian Cross build). To configure a + cross-compile, supply the configure script with --build and + --host options that are different. The values of these options must + be legal target triples that your GCC compiler supports.

+ +

The result of such a build is executables that are not runnable on + on the build host (--build option) but can be executed on the compile host + (--host option).

+
+ + + + +
+ +

The LLVM build system is capable of sharing a single LLVM source tree among +several LLVM builds. Hence, it is possible to build LLVM for several different +platforms or configurations using the same source tree.

+ +

This is accomplished in the typical autoconf manner:

+ +
    +
  • Change directory to where the LLVM object files should live:

    + +
    % cd OBJ_ROOT
  • + +
  • Run the configure script found in the LLVM source + directory:

    + +
    % SRC_ROOT/configure
  • +
+ +

The LLVM build will place files underneath OBJ_ROOT in directories +named after the build type:

+ +
+
Debug Builds with assertions enabled (the default) +
+
+
Tools +
OBJ_ROOT/Debug+Asserts/bin +
Libraries +
OBJ_ROOT/Debug+Asserts/lib +
+

+ +
Release Builds +
+
+
Tools +
OBJ_ROOT/Release/bin +
Libraries +
OBJ_ROOT/Release/lib +
+

+ +
Profile Builds +
+
+
Tools +
OBJ_ROOT/Profile/bin +
Libraries +
OBJ_ROOT/Profile/lib +
+
+ +
+ + + + +
+ +

+If you're running on a Linux system that supports the "binfmt_misc" +module, and you have root access on the system, you can set your system up to +execute LLVM bitcode files directly. To do this, use commands like this (the +first command may not be required if you are already using the module):

+ +
+
+$ mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
+$ echo ':llvm:M::BC::/path/to/lli:' > /proc/sys/fs/binfmt_misc/register
+$ chmod u+x hello.bc   (if needed)
+$ ./hello.bc
+
+
+ +

+This allows you to execute LLVM bitcode files directly. On Debian, you +can also use this command instead of the 'echo' command above:

+

+ +
+
+$ sudo update-binfmts --install llvm /path/to/lli --magic 'BC'
+
+
+ +
+ + + + + +
+ +

One useful source of information about the LLVM source base is the LLVM doxygen documentation available at http://llvm.org/doxygen/. +The following is a brief introduction to code layout:

+ +
+ + + +
+

This directory contains some simple examples of how to use the LLVM IR and + JIT.

+
+ + + +
+ +

This directory contains public header files exported from the LLVM +library. The three main subdirectories of this directory are:

+ +
+
llvm/include/llvm
+
This directory contains all of the LLVM specific header files. This + directory also has subdirectories for different portions of LLVM: + Analysis, CodeGen, Target, Transforms, + etc...
+ +
llvm/include/llvm/Support
+
This directory contains generic support libraries that are provided with + LLVM but not necessarily specific to LLVM. For example, some C++ STL utilities + and a Command Line option processing library store their header files here. +
+ +
llvm/include/llvm/Config
+
This directory contains header files configured by the configure + script. They wrap "standard" UNIX and C header files. Source code can + include these header files which automatically take care of the conditional + #includes that the configure script generates.
+
+
+ + + +
+ +

This directory contains most of the source files of the LLVM system. In LLVM, +almost all code exists in libraries, making it very easy to share code among the +different tools.

+ +
+
llvm/lib/VMCore/
+
This directory holds the core LLVM source files that implement core + classes like Instruction and BasicBlock.
+ +
llvm/lib/AsmParser/
+
This directory holds the source code for the LLVM assembly language parser + library.
+ +
llvm/lib/BitCode/
+
This directory holds code for reading and write LLVM bitcode.
+ +
llvm/lib/Analysis/
This directory contains a variety of + different program analyses, such as Dominator Information, Call Graphs, + Induction Variables, Interval Identification, Natural Loop Identification, + etc.
+ +
llvm/lib/Transforms/
+
This directory contains the source code for the LLVM to LLVM program + transformations, such as Aggressive Dead Code Elimination, Sparse Conditional + Constant Propagation, Inlining, Loop Invariant Code Motion, Dead Global + Elimination, and many others.
+ +
llvm/lib/Target/
+
This directory contains files that describe various target architectures + for code generation. For example, the llvm/lib/Target/X86 + directory holds the X86 machine description while + llvm/lib/Target/CBackend implements the LLVM-to-C converter.
+ +
llvm/lib/CodeGen/
+
This directory contains the major parts of the code generator: Instruction + Selector, Instruction Scheduling, and Register Allocation.
+ +
llvm/lib/Debugger/
+
This directory contains the source level debugger library that makes + it possible to instrument LLVM programs so that a debugger could identify + source code locations at which the program is executing.
+ +
llvm/lib/ExecutionEngine/
+
This directory contains libraries for executing LLVM bitcode directly + at runtime in both interpreted and JIT compiled fashions.
+ +
llvm/lib/Support/
+
This directory contains the source code that corresponds to the header + files located in llvm/include/Support/.
+ +
llvm/lib/System/
+
This directory contains the operating system abstraction layer that + shields LLVM from platform-specific coding.
+
+ +
+ + + +
+

This directory contains projects that are not strictly part of LLVM but are + shipped with LLVM. This is also the directory where you should create your own + LLVM-based projects. See llvm/projects/sample for an example of how + to set up your own project.

+
+ + + +
+ +

This directory contains libraries which are compiled into LLVM bitcode and +used when linking programs with the GCC front end. Most of these libraries are +skeleton versions of real libraries; for example, libc is a stripped down +version of glibc.

+ +

Unlike the rest of the LLVM suite, this directory needs the LLVM GCC front +end to compile.

+ +
+ + + +
+

This directory contains feature and regression tests and other basic sanity + checks on the LLVM infrastructure. These are intended to run quickly and cover + a lot of territory without being exhaustive.

+
+ + + +
+

This is not a directory in the normal llvm module; it is a separate + Subversion + module that must be checked out (usually to projects/test-suite). + This + module contains a comprehensive correctness, performance, and benchmarking + test + suite for LLVM. It is a separate Subversion module because not every LLVM + user is + interested in downloading or building such a comprehensive test suite. For + further details on this test suite, please see the + Testing Guide document.

+
+ + + +
+ +

The tools directory contains the executables built out of the +libraries above, which form the main part of the user interface. You can +always get help for a tool by typing tool_name -help. The +following is a brief introduction to the most important tools. More detailed +information is in the Command Guide.

+ +
+ +
bugpoint
+
bugpoint is used to debug + optimization passes or code generation backends by narrowing down the + given test case to the minimum number of passes and/or instructions that + still cause a problem, whether it is a crash or miscompilation. See HowToSubmitABug.html for more information + on using bugpoint.
+ +
llvmc
+
The LLVM Compiler Driver. This program can + be configured to utilize both LLVM and non-LLVM compilation tools to enable + pre-processing, translation, optimization, assembly, and linking of programs + all from one command line. llvmc also takes care of processing the + dependent libraries found in bitcode. This reduces the need to get the + traditional -l<name> options right on the command line. Please + note that this tool, while functional, is still experimental and not feature + complete.
+ +
llvm-ar
+
The archiver produces an archive containing + the given LLVM bitcode files, optionally with an index for faster + lookup.
+ +
llvm-as
+
The assembler transforms the human readable LLVM assembly to LLVM + bitcode.
+ +
llvm-dis
+
The disassembler transforms the LLVM bitcode to human readable + LLVM assembly.
+ +
llvm-ld
+
llvm-ld is a general purpose and extensible linker for LLVM. + This is the linker invoked by llvmc. It performs standard link time + optimizations and allows optimization modules to be loaded and run so that + language specific optimizations can be applied at link time.
+ +
llvm-link
+
llvm-link, not surprisingly, links multiple LLVM modules into + a single program.
+ +
lli
+
lli is the LLVM interpreter, which + can directly execute LLVM bitcode (although very slowly...). For architectures + that support it (currently x86, Sparc, and PowerPC), by default, lli + will function as a Just-In-Time compiler (if the functionality was compiled + in), and will execute the code much faster than the interpreter.
+ +
llc
+
llc is the LLVM backend compiler, which + translates LLVM bitcode to a native code assembly file or to C code (with + the -march=c option).
+ +
llvm-gcc
+
llvm-gcc is a GCC-based C frontend that has been retargeted to + use LLVM as its backend instead of GCC's RTL backend. It can also emit LLVM + bitcode or assembly (with the -emit-llvm option) instead of the + usual machine code output. It works just like any other GCC compiler, + taking the typical -c, -S, -E, -o options that are typically used. + Additionally, the the source code for llvm-gcc is available as a + separate Subversion module.
+ +
opt
+
opt reads LLVM bitcode, applies a series of LLVM to LLVM + transformations (which are specified on the command line), and then outputs + the resultant bitcode. The 'opt -help' command is a good way to + get a list of the program transformations available in LLVM.
+
opt can also be used to run a specific analysis on an input + LLVM bitcode file and print out the results. It is primarily useful for + debugging analyses, or familiarizing yourself with what an analysis does.
+
+
+ + + +
+ +

This directory contains utilities for working with LLVM source code, and some +of the utilities are actually required as part of the build process because they +are code generators for parts of LLVM infrastructure.

+ +
+
codegen-diff
codegen-diff is a script + that finds differences between code that LLC generates and code that LLI + generates. This is a useful tool if you are debugging one of them, + assuming that the other generates correct output. For the full user + manual, run `perldoc codegen-diff'.

+ +
emacs/
The emacs directory contains + syntax-highlighting files which will work with Emacs and XEmacs editors, + providing syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

+ +
getsrcs.sh
The getsrcs.sh script finds + and outputs all non-generated source files, which is useful if one wishes + to do a lot of development across directories and does not want to + individually find each file. One way to use it is to run, for example: + xemacs `utils/getsources.sh` from the top of your LLVM source + tree.

+ +
llvmgrep
+
This little tool performs an "egrep -H -n" on each source file in LLVM and + passes to it a regular expression provided on llvmgrep's command + line. This is a very efficient way of searching the source base for a + particular regular expression.
+ +
makellvm
The makellvm script compiles all + files in the current directory and then compiles and links the tool that + is the first argument. For example, assuming you are in the directory + llvm/lib/Target/Sparc, if makellvm is in your path, + simply running makellvm llc will make a build of the current + directory, switch to directory llvm/tools/llc and build it, + causing a re-linking of LLC.

+ +
NewNightlyTest.pl and + NightlyTestTemplate.html
These files are used in a + cron script to generate nightly status reports of the functionality of + tools, and the results can be seen by following the appropriate link on + the LLVM homepage.

+ +
TableGen/
The TableGen directory contains + the tool used to generate register descriptions, instruction set + descriptions, and even assemblers from common TableGen description + files.

+ +
vim/
The vim directory contains + syntax-highlighting files which will work with the VIM editor, providing + syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

+ +
+ +
+ + + + + +
+

This section gives an example of using LLVM. llvm-gcc3 is now obsolete, +so we only include instructions for llvm-gcc4. +

+ +

Note: The gcc4 frontend's invocation is considerably different +from the previous gcc3 frontend. In particular, the gcc4 frontend does not +create bitcode by default: gcc4 produces native code. As the example below illustrates, +the '--emit-llvm' flag is needed to produce LLVM bitcode output. For makefiles and +configure scripts, the CFLAGS variable needs '--emit-llvm' to produce bitcode +output.

+
+ + + + +
+ +
    +
  1. First, create a simple C file, name it 'hello.c':

    + +
    +
    +#include <stdio.h>
    +
    +int main() {
    +  printf("hello world\n");
    +  return 0;
    +}
    +
  2. + +
  3. Next, compile the C file into a native executable:

    + +
    % llvm-gcc hello.c -o hello
    + +

    Note that llvm-gcc works just like GCC by default. The standard -S and + -c arguments work as usual (producing a native .s or .o file, + respectively).

  4. + +
  5. Next, compile the C file into a LLVM bitcode file:

    + +
    +
    % llvm-gcc -O3 -emit-llvm hello.c -c -o hello.bc
    + +

    The -emit-llvm option can be used with the -S or -c options to emit an + LLVM ".ll" or ".bc" file (respectively) for the code. This allows you + to use the standard LLVM tools on + the bitcode file.

    + +

    Unlike llvm-gcc3, llvm-gcc4 correctly responds to -O[0123] arguments. +

  6. + +
  7. Run the program in both forms. To run the program, use:

    + +
    % ./hello
    + +

    and

    + +
    % lli hello.bc
    + +

    The second examples shows how to invoke the LLVM JIT, lli.

  8. + +
  9. Use the llvm-dis utility to take a look at the LLVM assembly + code:

    + +
    +
    llvm-dis < hello.bc | less
    +
  10. + +
  11. Compile the program to native assembly using the LLC code + generator:

    + +
    % llc hello.bc -o hello.s
  12. + +
  13. Assemble the native assembly language file into a program:

    + +
    +
    +Solaris: % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.native
    +
    +Others:  % gcc hello.s -o hello.native
    +
    +
  14. + +
  15. Execute the native code program:

    + +
    % ./hello.native
    + +

    Note that using llvm-gcc to compile directly to native code (i.e. when + the -emit-llvm option is not present) does steps 6/7/8 for you.

    +
  16. + +
+ +
+ + + + + + +
+ +

If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the Frequently +Asked Questions page.

+ +
+ + +
+ Links +
+ + +
+ +

This document is just an introduction on how to use LLVM to do +some simple things... there are many more interesting and complicated things +that you can do that aren't documented here (but we'll gladly accept a patch +if you want to write something up!). For more information about LLVM, check +out:

+ + + +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ Reid Spencer
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/GettingStartedVS.html b/final/docs/GettingStartedVS.html new file mode 100644 index 00000000000..74759047978 --- /dev/null +++ b/final/docs/GettingStartedVS.html @@ -0,0 +1,366 @@ + + + + + Getting Started with LLVM System for Microsoft Visual Studio + + + + +
+ Getting Started with the LLVM System using Microsoft Visual Studio +
+ + + +
+

Written by: The LLVM Team

+
+ + + + + + +
+ +

Welcome to LLVM on Windows! This document only covers LLVM on Windows using + Visual Studio, not mingw or cygwin. In order to get started, you first need to + know some basic information.

+ +

There are many different projects that compose LLVM. The first is the LLVM + suite. This contains all of the tools, libraries, and header files needed to + use the low level virtual machine. It contains an assembler, disassembler, + bitcode analyzer and bitcode optimizer. It also contains a test suite that can + be used to test the LLVM tools.

+ +

Another useful project on Windows is + clang. Clang is a C family + ([Objective]C/C++) compiler. Clang mostly works on Windows, but does not + currently understand all of the Microsoft extensions to C and C++. Because of + this, clang cannot parse the C++ standard library included with Visual Studio, + nor parts of the Windows Platform SDK. However, most standard C programs do + compile. Clang can be used to emit bitcode, directly emit object files or + even linked executables using Visual Studio's link.exe

+ +

The large LLVM test suite cannot be run on the Visual Studio port at this + time.

+ +

Most of the tools build and work. bugpoint does build, but does + not work.

+ +

Additional information about the LLVM directory structure and tool chain + can be found on the main Getting Started + page.

+ +
+ + + + + +
+ +

Before you begin to use the LLVM system, review the requirements given + below. This may save you some trouble by knowing ahead of time what hardware + and software you will need.

+ +
+ + + + +
+ +

Any system that can adequately run Visual Studio .NET 2005 SP1 is fine. + The LLVM source tree and object files, libraries and executables will consume + approximately 3GB.

+ +
+ + + +
+ +

You will need Visual Studio .NET 2005 SP1 or higher. The VS2005 SP1 + beta and the normal VS2005 still have bugs that are not completely + compatible. Earlier versions of Visual Studio do not support the C++ standard + well enough and will not work.

+ +

You will also need the CMake build + system since it generates the project files you will use to build with.

+ +

If you would like to run the LLVM tests you will need + Python. Versions 2.4-2.7 are known to + work. You will need "GnuWin32" + tools, too.

+ +

Do not install the LLVM directory tree into a path containing spaces (e.g. + C:\Documents and Settings\...) as the configure step will fail.

+ +
+ + + + + +
+ +

Here's the short story for getting up and running quickly with LLVM:

+ +
    +
  1. Read the documentation.
  2. +
  3. Seriously, read the documentation.
  4. +
  5. Remember that you were warned twice about reading the documentation.
  6. + +
  7. Get the Source Code +
      +
    • With the distributed files: +
        +
      1. cd where-you-want-llvm-to-live +
      2. gunzip --stdout llvm-version.tar.gz | tar -xvf - +       or use WinZip +
      3. cd llvm
      4. +
    • + +
    • With anonymous Subversion access: +
        +
      1. cd where-you-want-llvm-to-live
      2. +
      3. svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
      4. +
      5. cd llvm
      6. +
    • +
  8. + +
  9. Use CMake to generate up-to-date + project files: +
      +
    • Once CMake is installed then the simplest way is to just start the + CMake GUI, select the directory where you have LLVM extracted to, and the + default options should all be fine. One option you may really want to + change, regardless of anything else, might be the CMAKE_INSTALL_PREFIX + setting to select a directory to INSTALL to once compiling is complete, + although installation is not mandatory for using LLVM. Another important + option is LLVM_TARGETS_TO_BUILD, which controls the LLVM target + architectures that are included on the build. +
    • See the LLVM CMake guide for + detailed information about how to configure the LLVM + build.
    • +
    +
  10. + +
  11. Start Visual Studio +
      +
    • In the directory you created the project files will have + an llvm.sln file, just double-click on that to open + Visual Studio.
    • +
  12. + +
  13. Build the LLVM Suite: +
      +
    • The projects may still be built individually, but + to build them all do not just select all of them in batch build (as some + are meant as configuration projects), but rather select and build just + the ALL_BUILD project to build everything, or the INSTALL project, which + first builds the ALL_BUILD project, then installs the LLVM headers, libs, + and other useful things to the directory set by the CMAKE_INSTALL_PREFIX + setting when you first configured CMake.
    • +
    • The Fibonacci project is a sample program that uses the JIT. + Modify the project's debugging properties to provide a numeric + command line argument or run it from the command line. The + program will print the corresponding fibonacci value.
    • +
  14. + +
  15. Test LLVM on Visual Studio: +
      +
    • If %PATH% does not contain GnuWin32, you may specify LLVM_LIT_TOOLS_DIR + on CMake for the path to GnuWin32.
    • +
    • You can run LLVM tests to build the project "check".
    • +
    +
  16. + + +
  17. Test LLVM: +
      +
    • The LLVM tests can be run by cding to the llvm source directory + and running: + +
      +
      +% llvm-lit test
      +
      +
      + +

      Note that quite a few of these test will fail.

      +
    • + +
    • A specific test or test directory can be run with:
    • + +
      +
      +% llvm-lit test/path/to/test
      +
      +
      + +
+ +
+ + + + + +
+ +
    +
  1. First, create a simple C file, name it 'hello.c':

    + +
    +
    +#include <stdio.h>
    +int main() {
    +  printf("hello world\n");
    +  return 0;
    +}
    +
  2. + +
  3. Next, compile the C file into a LLVM bitcode file:

    + +
    +
    +% clang -c hello.c -emit-llvm -o hello.bc
    +
    +
    + +

    This will create the result file hello.bc which is the LLVM + bitcode that corresponds the the compiled program and the library + facilities that it required. You can execute this file directly using + lli tool, compile it to native assembly with the llc, + optimize or analyze it further with the opt tool, etc.

    + +

    Alternatively you can directly output an executable with clang with: +

    + +
    +
    +% clang hello.c -o hello.exe
    +
    +
    + +

    The -o hello.exe is required because clang currently outputs + a.out when neither -o nor -c are given.

    + +
  4. Run the program using the just-in-time compiler:

    + +
    +
    +% lli hello.bc
    +
    +
    + +
  5. Use the llvm-dis utility to take a look at the LLVM assembly + code:

    + +
    +
    +% llvm-dis < hello.bc | more
    +
    +
  6. + +
  7. Compile the program to object code using the LLC code generator:

    + +
    +
    +% llc -filetype=obj hello.bc
    +
    +
  8. + +
  9. Link to binary using Microsoft link:

    + +
    +
    +% link hello.obj -defaultlib:libcmt
    +
    +
    + +
  10. Execute the native code program:

    + +
    +
    +% hello.exe
    +
    +
  11. +
+ +
+ + + + + +
+ +

If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the Frequently +Asked Questions page.

+ +
+ + +
+ Links +
+ + +
+ +

This document is just an introduction to how to use LLVM to do +some simple things... there are many more interesting and complicated things +that you can do that aren't documented here (but we'll gladly accept a patch +if you want to write something up!). For more information about LLVM, check +out:

+ + + +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/GoldPlugin.html b/final/docs/GoldPlugin.html new file mode 100644 index 00000000000..68c5cf19280 --- /dev/null +++ b/final/docs/GoldPlugin.html @@ -0,0 +1,213 @@ + + + + LLVM gold plugin + + + + +
LLVM gold plugin
+
    +
  1. Introduction
  2. +
  3. How to build it
  4. +
  5. Usage +
  6. +
  7. Licensing
  8. +
+
Written by Nick Lewycky
+ + + + +
+

Building with link time optimization requires cooperation from the +system linker. LTO support on Linux systems requires that you use +the gold linker which supports +LTO via plugins. This is the same mechanism used by the +GCC LTO +project.

+

The LLVM gold plugin implements the +gold plugin interface +on top of +libLTO. +The same plugin can also be used by other tools such as ar and +nm. +

+ + + +
+

You need to have gold with plugin support and build the LLVMgold +plugin. Check whether you have gold running /usr/bin/ld -v. It will +report “GNU gold” or else “GNU ld” if not. If you have +gold, check for plugin support by running /usr/bin/ld -plugin. If it +complains “missing argument” then you have plugin support. If not, +such as an “unknown option” error then you will either need to +build gold or install a version with plugin support.

+
    +
  • To build gold with plugin support: +
    +mkdir binutils
    +cd binutils
    +cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src login
    +{enter "anoncvs" as the password}
    +cvs -z 9 -d :pserver:anoncvs@sourceware.org:/cvs/src co binutils
    +mkdir build
    +cd build
    +../src/configure --enable-gold --enable-plugins
    +make all-gold
    +
    + That should leave you with binutils/build/gold/ld-new which supports the -plugin option. It also built would have +binutils/build/binutils/ar and nm-new which support plugins +but don't have a visible -plugin option, instead relying on the gold plugin +being present in ../lib/bfd-plugins relative to where the binaries are +placed. +
  • Build the LLVMgold plugin: Configure LLVM with + --with-binutils-include=/path/to/binutils/src/include and run + make. +
+
+ + + +
+

The linker takes a -plugin option that points to the path of + the plugin .so file. To find out what link command gcc + would run in a given situation, run gcc -v [...] and look + for the line where it runs collect2. Replace that with + ld-new -plugin /path/to/LLVMgold.so to test it out. Once you're + ready to switch to using gold, backup your existing /usr/bin/ld + then replace it with ld-new.

+

You can produce bitcode files from llvm-gcc using + -emit-llvm or -flto, or the -O4 flag which is + synonymous with -O3 -flto.

+

llvm-gcc has a -use-gold-plugin option which looks + for the gold plugin in the same directories as it looks for cc1 and + passes the -plugin option to ld. It will not look for an alternate + linker, which is why you need gold to be the installed system linker in your + path.

+

If you want ar and nm to work seamlessly as well, install + LLVMgold.so to /usr/lib/bfd-plugins. If you built your + own gold, be sure to install the ar and nm-new you built to + /usr/bin. +

+

+ + + + +
+

The following example shows a worked example of the gold plugin mixing + LLVM bitcode and native code. +

+--- a.c ---
+#include <stdio.h>
+
+extern void foo1(void);
+extern void foo4(void);
+
+void foo2(void) {
+  printf("Foo2\n");
+}
+
+void foo3(void) {
+  foo4();
+}
+
+int main(void) {
+  foo1();
+}
+
+--- b.c ---
+#include <stdio.h>
+
+extern void foo2(void);
+
+void foo1(void) {
+  foo2();
+}
+
+void foo4(void) {
+  printf("Foo4");
+}
+
+--- command lines ---
+$ llvm-gcc -flto a.c -c -o a.o              # <-- a.o is LLVM bitcode file
+$ ar q a.a a.o                              # <-- a.a is an archive with LLVM bitcode
+$ llvm-gcc b.c -c -o b.o                    # <-- b.o is native object file
+$ llvm-gcc -use-gold-plugin a.a b.o -o main # <-- link with LLVMgold plugin
+
+

Gold informs the plugin that foo3 is never referenced outside the IR, + leading LLVM to delete that function. However, unlike in the + libLTO + example gold does not currently eliminate foo4.

+
+ + + + +
+

Once your system ld, ar and nm all support LLVM + bitcode, everything is in place for an easy to use LTO build of autotooled + projects:

+
    +
  • Follow the instructions on how to build LLVMgold.so.
  • +
  • Install the newly built binutils to $PREFIX
  • +
  • Copy Release/lib/LLVMgold.so to + $PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/ and + $PREFIX/lib/bfd-plugins/
  • +
  • Set environment variables ($PREFIX is where you installed llvm-gcc and + binutils): +
    +export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin"
    +export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin"
    +export AR="$PREFIX/bin/ar"
    +export NM="$PREFIX/bin/nm"
    +export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
    +export CFLAGS="-O4"
    +
    +
  • +
  • Or you can just set your path: +
    +export PATH="$PREFIX/bin:$PATH"
    +export CC="llvm-gcc -use-gold-plugin"
    +export CXX="llvm-g++ -use-gold-plugin"
    +export RANLIB=/bin/true
    +export CFLAGS="-O4"
    +
    +
  • +
  • Configure & build the project as usual: ./configure && make && make check
  • +
+

The environment variable settings may work for non-autotooled projects + too, but you may need to set the LD environment variable as well.

+
+ + + + +
+

Gold is licensed under the GPLv3. LLVMgold uses the interface file +plugin-api.h from gold which means that the resulting LLVMgold.so +binary is also GPLv3. This can still be used to link non-GPLv3 programs just +as much as gold could without the plugin.

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + Nick Lewycky
+ The LLVM Compiler Infrastructure
+ Last modified: $Date: 2010-04-16 23:58:21 -0800 (Fri, 16 Apr 2010) $ +
+ + diff --git a/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt b/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt new file mode 100644 index 00000000000..f0861811920 --- /dev/null +++ b/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeas.txt @@ -0,0 +1,74 @@ +Date: Sat, 18 Nov 2000 09:19:35 -0600 (CST) +From: Vikram Adve +To: Chris Lattner +Subject: a few thoughts + +I've been mulling over the virtual machine problem and I had some +thoughts about some things for us to think about discuss: + +1. We need to be clear on our goals for the VM. Do we want to emphasize + portability and safety like the Java VM? Or shall we focus on the + architecture interface first (i.e., consider the code generation and + processor issues), since the architecture interface question is also + important for portable Java-type VMs? + + This is important because the audiences for these two goals are very + different. Architects and many compiler people care much more about + the second question. The Java compiler and OS community care much more + about the first one. + + Also, while the architecture interface question is important for + Java-type VMs, the design constraints are very different. + + +2. Design issues to consider (an initial list that we should continue + to modify). Note that I'm not trying to suggest actual solutions here, + but just various directions we can pursue: + + a. A single-assignment VM, which we've both already been thinking about. + + b. A strongly-typed VM. One question is do we need the types to be + explicitly declared or should they be inferred by the dynamic compiler? + + c. How do we get more high-level information into the VM while keeping + to a low-level VM design? + + o Explicit array references as operands? An alternative is + to have just an array type, and let the index computations be + separate 3-operand instructions. + + o Explicit instructions to handle aliasing, e.g.s: + -- an instruction to say "I speculate that these two values are not + aliased, but check at runtime", like speculative execution in + EPIC? + -- or an instruction to check whether two values are aliased and + execute different code depending on the answer, somewhat like + predicated code in EPIC + + o (This one is a difficult but powerful idea.) + A "thread-id" field on every instruction that allows the static + compiler to generate a set of parallel threads, and then have + the runtime compiler and hardware do what they please with it. + This has very powerful uses, but thread-id on every instruction + is expensive in terms of instruction size and code size. + We would need to compactly encode it somehow. + + Also, this will require some reading on at least two other + projects: + -- Multiscalar architecture from Wisconsin + -- Simultaneous multithreading architecture from Washington + + o Or forget all this and stick to a traditional instruction set? + + +BTW, on an unrelated note, after the meeting yesterday, I did remember +that you had suggested doing instruction scheduling on SSA form instead +of a dependence DAG earlier in the semester. When we talked about +it yesterday, I didn't remember where the idea had come from but I +remembered later. Just giving credit where its due... + +Perhaps you can save the above as a file under RCS so you and I can +continue to expand on this. + +--Vikram + diff --git a/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt b/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt new file mode 100644 index 00000000000..1c725f5aa71 --- /dev/null +++ b/final/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt @@ -0,0 +1,199 @@ +Date: Sun, 19 Nov 2000 16:23:57 -0600 (CST) +From: Chris Lattner +To: Vikram Adve +Subject: Re: a few thoughts + +Okay... here are a few of my thoughts on this (it's good to know that we +think so alike!): + +> 1. We need to be clear on our goals for the VM. Do we want to emphasize +> portability and safety like the Java VM? Or shall we focus on the +> architecture interface first (i.e., consider the code generation and +> processor issues), since the architecture interface question is also +> important for portable Java-type VMs? + +I forsee the architecture looking kinda like this: (which is completely +subject to change) + +1. The VM code is NOT guaranteed safe in a java sense. Doing so makes it + basically impossible to support C like languages. Besides that, + certifying a register based language as safe at run time would be a + pretty expensive operation to have to do. Additionally, we would like + to be able to statically eliminate many bounds checks in Java + programs... for example. + + 2. Instead, we can do the following (eventually): + * Java bytecode is used as our "safe" representation (to avoid + reinventing something that we don't add much value to). When the + user chooses to execute Java bytecodes directly (ie, not + precompiled) the runtime compiler can do some very simple + transformations (JIT style) to convert it into valid input for our + VM. Performance is not wonderful, but it works right. + * The file is scheduled to be compiled (rigorously) at a later + time. This could be done by some background process or by a second + processor in the system during idle time or something... + * To keep things "safe" ie to enforce a sandbox on Java/foreign code, + we could sign the generated VM code with a host specific private + key. Then before the code is executed/loaded, we can check to see if + the trusted compiler generated the code. This would be much quicker + than having to validate consistency (especially if bounds checks have + been removed, for example) + +> This is important because the audiences for these two goals are very +> different. Architects and many compiler people care much more about +> the second question. The Java compiler and OS community care much more +> about the first one. + +3. By focusing on a more low level virtual machine, we have much more room + for value add. The nice safe "sandbox" VM can be provided as a layer + on top of it. It also lets us focus on the more interesting compilers + related projects. + +> 2. Design issues to consider (an initial list that we should continue +> to modify). Note that I'm not trying to suggest actual solutions here, +> but just various directions we can pursue: + +Understood. :) + +> a. A single-assignment VM, which we've both already been thinking +> about. + +Yup, I think that this makes a lot of sense. I am still intrigued, +however, by the prospect of a minimally allocated VM representation... I +think that it could have definate advantages for certain applications +(think very small machines, like PDAs). I don't, however, think that our +initial implementations should focus on this. :) + +Here are some other auxilliary goals that I think we should consider: + +1. Primary goal: Support a high performance dynamic compilation + system. This means that we have an "ideal" division of labor between + the runtime and static compilers. Of course, the other goals of the + system somewhat reduce the importance of this point (f.e. portability + reduces performance, but hopefully not much) +2. Portability to different processors. Since we are most familiar with + x86 and solaris, I think that these two are excellent candidates when + we get that far... +3. Support for all languages & styles of programming (general purpose + VM). This is the point that disallows java style bytecodes, where all + array refs are checked for bounds, etc... +4. Support linking between different language families. For example, call + C functions directly from Java without using the nasty/slow/gross JNI + layer. This involves several subpoints: + A. Support for languages that require garbage collectors and integration + with languages that don't. As a base point, we could insist on + always using a conservative GC, but implement free as a noop, f.e. + +> b. A strongly-typed VM. One question is do we need the types to be +> explicitly declared or should they be inferred by the dynamic +> compiler? + + B. This is kind of similar to another idea that I have: make OOP + constructs (virtual function tables, class heirarchies, etc) explicit + in the VM representation. I believe that the number of additional + constructs would be fairly low, but would give us lots of important + information... something else that would/could be important is to + have exceptions as first class types so that they would be handled in + a uniform way for the entire VM... so that C functions can call Java + functions for example... + +> c. How do we get more high-level information into the VM while keeping +> to a low-level VM design? +> o Explicit array references as operands? An alternative is +> to have just an array type, and let the index computations be +> separate 3-operand instructions. + + C. In the model I was thinking of (subject to change of course), we + would just have an array type (distinct from the pointer + types). This would allow us to have arbitrarily complex index + expressions, while still distinguishing "load" from "Array load", + for example. Perhaps also, switch jump tables would be first class + types as well? This would allow better reasoning about the program. + +5. Support dynamic loading of code from various sources. Already + mentioned above was the example of loading java bytecodes, but we want + to support dynamic loading of VM code as well. This makes the job of + the runtime compiler much more interesting: it can do interprocedural + optimizations that the static compiler can't do, because it doesn't + have all of the required information (for example, inlining from + shared libraries, etc...) + +6. Define a set of generally useful annotations to add to the VM + representation. For example, a function can be analysed to see if it + has any sideeffects when run... also, the MOD/REF sets could be + calculated, etc... we would have to determine what is reasonable. This + would generally be used to make IP optimizations cheaper for the + runtime compiler... + +> o Explicit instructions to handle aliasing, e.g.s: +> -- an instruction to say "I speculate that these two values are not +> aliased, but check at runtime", like speculative execution in +> EPIC? +> -- or an instruction to check whether two values are aliased and +> execute different code depending on the answer, somewhat like +> predicated code in EPIC + +These are also very good points... if this can be determined at compile +time. I think that an epic style of representation (not the instruction +packing, just the information presented) could be a very interesting model +to use... more later... + +> o (This one is a difficult but powerful idea.) +> A "thread-id" field on every instruction that allows the static +> compiler to generate a set of parallel threads, and then have +> the runtime compiler and hardware do what they please with it. +> This has very powerful uses, but thread-id on every instruction +> is expensive in terms of instruction size and code size. +> We would need to compactly encode it somehow. + +Yes yes yes! :) I think it would be *VERY* useful to include this kind +of information (which EPIC architectures *implicitly* encode. The trend +that we are seeing supports this greatly: + +1. Commodity processors are getting massive SIMD support: + * Intel/Amd MMX/MMX2 + * AMD's 3Dnow! + * Intel's SSE/SSE2 + * Sun's VIS +2. SMP is becoming much more common, especially in the server space. +3. Multiple processors on a die are right around the corner. + +If nothing else, not designing this in would severely limit our future +expansion of the project... + +> Also, this will require some reading on at least two other +> projects: +> -- Multiscalar architecture from Wisconsin +> -- Simultaneous multithreading architecture from Washington +> +> o Or forget all this and stick to a traditional instruction set? + +Heh... :) Well, from a pure research point of view, it is almost more +attactive to go with the most extreme/different ISA possible. On one axis +you get safety and conservatism, and on the other you get degree of +influence that the results have. Of course the problem with pure research +is that often times there is no concrete product of the research... :) + +> BTW, on an unrelated note, after the meeting yesterday, I did remember +> that you had suggested doing instruction scheduling on SSA form instead +> of a dependence DAG earlier in the semester. When we talked about +> it yesterday, I didn't remember where the idea had come from but I +> remembered later. Just giving credit where its due... + +:) Thanks. + +> Perhaps you can save the above as a file under RCS so you and I can +> continue to expand on this. + +I think it makes sense to do so when we get our ideas more formalized and +bounce it back and forth a couple of times... then I'll do a more formal +writeup of our goals and ideas. Obviously our first implementation will +not want to do all of the stuff that I pointed out above... be we will +want to design the project so that we do not artificially limit ourselves +at sometime in the future... + +Anyways, let me know what you think about these ideas... and if they sound +reasonable... + +-Chris + diff --git a/final/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt b/final/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt new file mode 100644 index 00000000000..8c452924dd1 --- /dev/null +++ b/final/docs/HistoricalNotes/2000-12-06-EncodingIdea.txt @@ -0,0 +1,30 @@ +From: Chris Lattner [mailto:sabre@nondot.org] +Sent: Wednesday, December 06, 2000 6:41 PM +To: Vikram S. Adve +Subject: Additional idea with respect to encoding + +Here's another idea with respect to keeping the common case instruction +size down (less than 32 bits ideally): + +Instead of encoding an instruction to operate on two register numbers, +have it operate on two negative offsets based on the current register +number. Therefore, instead of using: + +r57 = add r55, r56 (r57 is the implicit dest register, of course) + +We could use: + +r57 = add -2, -1 + +My guess is that most SSA references are to recent values (especially if +they correspond to expressions like (x+y*z+p*q/ ...), so the negative +numbers would tend to stay small, even at the end of the procedure (where +the implicit register destination number could be quite large). Of course +the negative sign is reduntant, so you would be storing small integers +almost all of the time, and 5-6 bits worth of register number would be +plenty for most cases... + +What do you think? + +-Chris + diff --git a/final/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt b/final/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt new file mode 100644 index 00000000000..b66e18556f5 --- /dev/null +++ b/final/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt @@ -0,0 +1,83 @@ +SUMMARY +------- + +We met to discuss the LLVM instruction format and bytecode representation: + +ISSUES RESOLVED +--------------- + +1. We decided that we shall use a flat namespace to represent our + variables in SSA form, as opposed to having a two dimensional namespace + of the original variable and the SSA instance subscript. + +ARGUMENT AGAINST: + * A two dimensional namespace would be valuable when doing alias + analysis because the extra information can help limit the scope of + analysis. + +ARGUMENT FOR: + * Including this information would require that all users of the LLVM + bytecode would have to parse and handle it. This would slow down the + common case and inflate the instruction representation with another + infinite variable space. + +REASONING: + * It was decided that because original variable sources could be + reconstructed from SSA form in linear time, that it would be an + unjustified expense for the common case to include the extra + information for one optimization. Alias analysis itself is typically + greater than linear in asymptotic complexity, so this extra analaysis + would not affect the runtime of the optimization in a significant + way. Additionally, this would be an unlikely optimization to do at + runtime. + + +IDEAS TO CONSIDER +----------------- + +1. Including dominator information in the LLVM bytecode + representation. This is one example of an analysis result that may be + packaged with the bytecodes themselves. As a conceptual implementation + idea, we could include an immediate dominator number for each basic block + in the LLVM bytecode program. Basic blocks could be numbered according + to the order of occurance in the bytecode representation. + +2. Including loop header and body information. This would facilitate + detection of intervals and natural loops. + +UNRESOLVED ISSUES +----------------- + +1. Will oSUIF provide enough of an infrastructure to support the research + that we will be doing? We know that it has less than stellar + performance, but hope that this will be of little importance for our + static compiler. This could affect us if we decided to do some IP + research. Also we do not yet understand the level of exception support + currently implemented. + +2. Should we consider the requirements of a direct hardware implementation + of the LLVM when we design it? If so, several design issues should + have their priorities shifted. The other option is to focus on a + software layer interpreting the LLVM in all cases. + +3. Should we use some form of packetized format to improve forward + compatibility? For example, we could design the system to encode a + packet type and length field before analysis information, to allow a + runtime to skip information that it didn't understand in a bytecode + stream. The obvious benefit would be for compatibility, the drawback + is that it would tend to splinter that 'standard' LLVM definition. + +4. Should we use fixed length instructions or variable length + instructions? Fetching variable length instructions is expensive (for + either hardware or software based LLVM runtimes), but we have several + 'infinite' spaces that instructions operate in (SSA register numbers, + type spaces, or packet length [if packets were implemented]). Several + options were mentioned including: + A. Using 16 or 32 bit numbers, which would be 'big enough' + B. A scheme similar to how UTF-8 works, to encode infinite numbers + while keeping small number small. + C. Use something similar to Huffman encoding, so that the most common + numbers are the smallest. + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt b/final/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt new file mode 100644 index 00000000000..111706a3447 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-01-31-UniversalIRIdea.txt @@ -0,0 +1,39 @@ +Date: Wed, 31 Jan 2001 12:04:33 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: another thought + +I have a budding idea about making LLVM a little more ambitious: a +customizable runtime system that can be used to implement language-specific +virtual machines for many different languages. E.g., a C vm, a C++ vm, a +Java vm, a Lisp vm, .. + +The idea would be that LLVM would provide a standard set of runtime features +(some low-level like standard assembly instructions with code generation and +static and runtime optimization; some higher-level like type-safety and +perhaps a garbage collection library). Each language vm would select the +runtime features needed for that language, extending or customizing them as +needed. Most of the machine-dependent code-generation and optimization +features as well as low-level machine-independent optimizations (like PRE) +could be provided by LLVM and should be sufficient for any language, +simplifying the language compiler. (This would also help interoperability +between languages.) Also, some or most of the higher-level +machine-independent features like type-safety and access safety should be +reusable by different languages, with minor extensions. The language +compiler could then focus on language-specific analyses and optimizations. + +The risk is that this sounds like a universal IR -- something that the +compiler community has tried and failed to develop for decades, and is +universally skeptical about. No matter what we say, we won't be able to +convince anyone that we have a universal IR that will work. We need to +think about whether LLVM is different or if has something novel that might +convince people. E.g., the idea of providing a package of separable +features that different languages select from. Also, using SSA with or +without type-safety as the intermediate representation. + +One interesting starting point would be to discuss how a JVM would be +implemented on top of LLVM a bit more. That might give us clues on how to +structure LLVM to support one or more language VMs. + +--Vikram + diff --git a/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt new file mode 100644 index 00000000000..c09cf1f03cc --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebate.txt @@ -0,0 +1,67 @@ +Date: Tue, 6 Feb 2001 20:27:37 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: Type notation debate... + +This is the way that I am currently planning on implementing types: + +Primitive Types: +type ::= void|bool|sbyte|ubyte|short|ushort|int|uint|long|ulong + +Method: +typelist ::= typelisth | /*empty*/ +typelisth ::= type | typelisth ',' type +type ::= type (typelist) + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']' + +Pointer: +type ::= type '*' + +Structure: +type ::= '{' typelist '}' + +Packed: +type ::= '<' INT ',' type '>' + +Simple examples: + +[[ %4, int ]] - array of (array of 4 (int)) +[ { int, int } ] - Array of structure +[ < %4, int > ] - Array of 128 bit SIMD packets +int (int, [[int, %4]]) - Method taking a 2d array and int, returning int + + +Okay before you comment, please look at: + +http://www.research.att.com/~bs/devXinterview.html + +Search for "In another interview, you defined the C declarator syntax as +an experiment that failed. However, this syntactic construct has been +around for 27 years and perhaps more; why do you consider it problematic +(except for its cumbersome syntax)?" and read that response for me. :) + +Now with this syntax, his example would be represented as: + +[ %10, bool (int, int) * ] * + +vs + +bool (*(*)[10])(int, int) + +in C. + +Basically, my argument for this type construction system is that it is +VERY simple to use and understand (although it IS different than C, it is +very simple and straightforward, which C is NOT). In fact, I would assert +that most programmers TODAY do not understand pointers to member +functions, and have to look up an example when they have to write them. + +In my opinion, it is critically important to have clear and concise type +specifications, because types are going to be all over the programs. + +Let me know your thoughts on this. :) + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt new file mode 100644 index 00000000000..8bfefbf69f6 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp1.txt @@ -0,0 +1,75 @@ +Date: Thu, 8 Feb 2001 08:42:04 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: Type notation debate... + +Chris, + +> Okay before you comment, please look at: +> +> http://www.research.att.com/~bs/devXinterview.html + +I read this argument. Even before that, I was already in agreement with you +and him that the C declarator syntax is difficult and confusing. + +But in fact, if you read the entire answer carefully, he came to the same +conclusion I do: that you have to go with familiar syntax over logical +syntax because familiarity is such a strong force: + + "However, familiarity is a strong force. To compare, in English, we +live +more or less happily with the absurd rules for "to be" (am, are, is, been, +was, were, ...) and all attempts to simplify are treated with contempt or +(preferably) humor. It be a curious world and it always beed." + +> Basically, my argument for this type construction system is that it is +> VERY simple to use and understand (although it IS different than C, it is +> very simple and straightforward, which C is NOT). In fact, I would assert +> that most programmers TODAY do not understand pointers to member +> functions, and have to look up an example when they have to write them. + +Again, I don't disagree with this at all. But to some extent this +particular problem is inherently difficult. Your syntax for the above +example may be easier for you to read because this is the way you have been +thinking about it. Honestly, I don't find it much easier than the C syntax. +In either case, I would have to look up an example to write pointers to +member functions. + +But pointers to member functions are nowhere near as common as arrays. And +the old array syntax: + type [ int, int, ...] +is just much more familiar and clear to people than anything new you +introduce, no matter how logical it is. Introducing a new syntax that may +make function pointers easier but makes arrays much more difficult seems +very risky to me. + +> In my opinion, it is critically important to have clear and concise type +> specifications, because types are going to be all over the programs. + +I absolutely agree. But the question is, what is more clear and concise? +The syntax programmers are used to out of years of experience or a new +syntax that they have never seen that has a more logical structure. I think +the answer is the former. Sometimes, you have to give up a better idea +because you can't overcome sociological barriers to it. Qwerty keyboards +and Windows are two classic examples of bad technology that are difficult to +root out. + +P.S. Also, while I agree that most your syntax is more logical, there is +one part that isn't: + +Arrays (without and with size): +type ::= '[' type ']' | '[' INT ',' type ']'. + +The arrays with size lists the dimensions and the type in a single list. +That is just too confusing: + [10, 40, int] +This seems to be a 3-D array where the third dimension is something strange. +It is too confusing to have a list of 3 things, some of which are dimensions +and one is a type. Either of the following would be better: + + array [10, 40] of int +or + int [10, 40] + +--Vikram + diff --git a/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt new file mode 100644 index 00000000000..6e9784158a3 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp2.txt @@ -0,0 +1,53 @@ +Date: Thu, 8 Feb 2001 14:31:05 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Type notation debate... + +> Arrays (without and with size): +> type ::= '[' type ']' | '[' INT ',' type ']'. +> +> The arrays with size lists the dimensions and the type in a single list. +> That is just too confusing: + +> [10, 40, int] +> This seems to be a 3-D array where the third dimension is something strange. +> It is too confusing to have a list of 3 things, some of which are dimensions +> and one is a type. + +The above grammar indicates that there is only one integer parameter, ie +the upper bound. The lower bound is always implied to be zero, for +several reasons: + +* As a low level VM, we want to expose addressing computations + explicitly. Since the lower bound must always be known in a high level + language statically, the language front end can do the translation + automatically. +* This fits more closely with what Java needs, ie what we need in the + short term. Java arrays are always zero based. + +If a two element list is too confusing, I would recommend an alternate +syntax of: + +type ::= '[' type ']' | '[' INT 'x' type ']'. + +For example: + [12 x int] + [12x int] + [ 12 x [ 4x int ]] + +Which is syntactically nicer, and more explicit. + +> Either of the following would be better: +> array [10, 40] of int + +I considered this approach for arrays in general (ie array of int/ array +of 12 int), but found that it made declarations WAY too long. Remember +that because of the nature of llvm, you get a lot of types strewn all over +the program, and using the 'typedef' like facility is not a wonderful +option, because then types aren't explicit anymore. + +I find this email interesting, because you contradict the previous email +you sent, where you recommend that we stick to C syntax.... + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt new file mode 100644 index 00000000000..7b9032742a2 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt @@ -0,0 +1,89 @@ +> But in fact, if you read the entire answer carefully, he came to the same +> conclusion I do: that you have to go with familiar syntax over logical +> syntax because familiarity is such a strong force: +> "However, familiarity is a strong force. To compare, in English, we +live +> more or less happily with the absurd rules for "to be" (am, are, is, been, +> was, were, ...) and all attempts to simplify are treated with contempt or +> (preferably) humor. It be a curious world and it always beed." + +Although you have to remember that his situation was considerably +different than ours. He was in a position where he was designing a high +level language that had to be COMPATIBLE with C. Our language is such +that a new person would have to learn the new, different, syntax +anyways. Making them learn about the type system does not seem like much +of a stretch from learning the opcodes and how SSA form works, and how +everything ties together... + +> > Basically, my argument for this type construction system is that it is +> > VERY simple to use and understand (although it IS different than C, it is +> > very simple and straightforward, which C is NOT). In fact, I would assert +> > that most programmers TODAY do not understand pointers to member +> > functions, and have to look up an example when they have to write them. + +> Again, I don't disagree with this at all. But to some extent this +> particular problem is inherently difficult. Your syntax for the above +> example may be easier for you to read because this is the way you have been +> thinking about it. Honestly, I don't find it much easier than the C syntax. +> In either case, I would have to look up an example to write pointers to +> member functions. + +I would argue that because the lexical structure of the language is self +consistent, any person who spent a significant amount of time programming +in LLVM directly would understand how to do it without looking it up in a +manual. The reason this does not work for C is because you rarely have to +declare these pointers, and the syntax is inconsistent with the method +declaration and calling syntax. + +> But pointers to member functions are nowhere near as common as arrays. + +Very true. If you're implementing an object oriented language, however, +remember that you have to do all the pointer to member function stuff +yourself.... so everytime you invoke a virtual method one is involved +(instead of having C++ hide it for you behind "syntactic sugar"). + +> And the old array syntax: +> type [ int, int, ...] +> is just much more familiar and clear to people than anything new you +> introduce, no matter how logical it is. + +Erm... excuse me but how is this the "old array syntax"? If you are +arguing for consistency with C, you should be asking for 'type int []', +which is significantly different than the above (beside the above +introduces a new operator and duplicates information +needlessly). Basically what I am suggesting is exactly the above without +the fluff. So instead of: + + type [ int, int, ...] + +you use: + + type [ int ] + +> Introducing a new syntax that may +> make function pointers easier but makes arrays much more difficult seems +> very risky to me. + +This is not about function pointers. This is about consistency in the +type system, and consistency with the rest of the language. The point +above does not make arrays any more difficult to use, and makes the +structure of types much more obvious than the "c way". + +> > In my opinion, it is critically important to have clear and concise type +> > specifications, because types are going to be all over the programs. +> +> I absolutely agree. But the question is, what is more clear and concise? +> The syntax programmers are used to out of years of experience or a new +> syntax that they have never seen that has a more logical structure. I think +> the answer is the former. Sometimes, you have to give up a better idea +> because you can't overcome sociological barriers to it. Qwerty keyboards +> and Windows are two classic examples of bad technology that are difficult to +> root out. + +Very true, but you seem to be advocating a completely different Type +system than C has, in addition to it not offering the advantages of clear +structure that the system I recommended does... so you seem to not have a +problem with changing this, just with what I change it to. :) + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-02-09-AdveComments.txt b/final/docs/HistoricalNotes/2001-02-09-AdveComments.txt new file mode 100644 index 00000000000..5503233c1ed --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-09-AdveComments.txt @@ -0,0 +1,120 @@ +Ok, here are my comments and suggestions about the LLVM instruction set. +We should discuss some now, but can discuss many of them later, when we +revisit synchronization, type inference, and other issues. +(We have discussed some of the comments already.) + + +o We should consider eliminating the type annotation in cases where it is + essentially obvious from the instruction type, e.g., in br, it is obvious + that the first arg. should be a bool and the other args should be labels: + + br bool , label , label + + I think your point was that making all types explicit improves clarity + and readability. I agree to some extent, but it also comes at the cost + of verbosity. And when the types are obvious from people's experience + (e.g., in the br instruction), it doesn't seem to help as much. + + +o On reflection, I really like your idea of having the two different switch + types (even though they encode implementation techniques rather than + semantics). It should simplify building the CFG and my guess is it could + enable some significant optimizations, though we should think about which. + + +o In the lookup-indirect form of the switch, is there a reason not to make + the val-type uint? Most HLL switch statements (including Java and C++) + require that anyway. And it would also make the val-type uniform + in the two forms of the switch. + + I did see the switch-on-bool examples and, while cute, we can just use + the branch instructions in that particular case. + + +o I agree with your comment that we don't need 'neg'. + + +o There's a trade-off with the cast instruction: + + it avoids having to define all the upcasts and downcasts that are + valid for the operands of each instruction (you probably have thought + of other benefits also) + - it could make the bytecode significantly larger because there could + be a lot of cast operations + + +o Making the second arg. to 'shl' a ubyte seems good enough to me. + 255 positions seems adequate for several generations of machines + and is more compact than uint. + + +o I still have some major concerns about including malloc and free in the + language (either as builtin functions or instructions). LLVM must be + able to represent code from many different languages. Languages such as + C, C++ Java and Fortran 90 would not be able to use our malloc anyway + because each of them will want to provide a library implementation of it. + + This gets even worse when code from different languages is linked + into a single executable (which is fairly common in large apps). + Having a single malloc would just not suffice, and instead would simply + complicate the picture further because it adds an extra variant in + addition to the one each language provides. + + Instead, providing a default library version of malloc and free + (and perhaps a malloc_gc with garbage collection instead of free) + would make a good implementation available to anyone who wants it. + + I don't recall all your arguments in favor so let's discuss this again, + and soon. + + +o 'alloca' on the other hand sounds like a good idea, and the + implementation seems fairly language-independent so it doesn't have the + problems with malloc listed above. + + +o About indirect call: + Your option #2 sounded good to me. I'm not sure I understand your + concern about an explicit 'icall' instruction? + + +o A pair of important synchronization instr'ns to think about: + load-linked + store-conditional + + +o Other classes of instructions that are valuable for pipeline performance: + conditional-move + predicated instructions + + +o I believe tail calls are relatively easy to identify; do you know why + .NET has a tailcall instruction? + + +o I agree that we need a static data space. Otherwise, emulating global + data gets unnecessarily complex. + + +o About explicit parallelism: + + We once talked about adding a symbolic thread-id field to each + instruction. (It could be optional so single-threaded codes are + not penalized.) This could map well to multi-threaded architectures + while providing easy ILP for single-threaded onces. But it is probably + too radical an idea to include in a base version of LLVM. Instead, it + could a great topic for a separate study. + + What is the semantics of the IA64 stop bit? + + + + +o And finally, another thought about the syntax for arrays :-) + + Although this syntax: + array of + is verbose, it will be used only in the human-readable assembly code so + size should not matter. I think we should consider it because I find it + to be the clearest syntax. It could even make arrays of function + pointers somewhat readable. + diff --git a/final/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt b/final/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt new file mode 100644 index 00000000000..5c87330fb7e --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt @@ -0,0 +1,245 @@ +From: Chris Lattner +To: "Vikram S. Adve" +Subject: Re: LLVM Feedback + +I've included your feedback in the /home/vadve/lattner/llvm/docs directory +so that it will live in CVS eventually with the rest of LLVM. I've +significantly updated the documentation to reflect the changes you +suggested, as specified below: + +> We should consider eliminating the type annotation in cases where it is +> essentially obvious from the instruction type: +> br bool , label , label +> I think your point was that making all types explicit improves clarity +> and readability. I agree to some extent, but it also comes at the +> cost of verbosity. And when the types are obvious from people's +> experience (e.g., in the br instruction), it doesn't seem to help as +> much. + +Very true. We should discuss this more, but my reasoning is more of a +consistency argument. There are VERY few instructions that can have all +of the types eliminated, and doing so when available unnecesarily makes +the language more difficult to handle. Especially when you see 'int +%this' and 'bool %that' all over the place, I think it would be +disorienting to see: + + br %predicate, %iftrue, %iffalse + +for branches. Even just typing that once gives me the creeps. ;) Like I +said, we should probably discuss this further in person... + +> On reflection, I really like your idea of having the two different +> switch types (even though they encode implementation techniques rather +> than semantics). It should simplify building the CFG and my guess is it +> could enable some significant optimizations, though we should think +> about which. + +Great. I added a note to the switch section commenting on how the VM +should just use the instruction type as a hint, and that the +implementation may choose altermate representations (such as predicated +branches). + +> In the lookup-indirect form of the switch, is there a reason not to +> make the val-type uint? + +No. This was something I was debating for a while, and didn't really feel +strongly about either way. It is common to switch on other types in HLL's +(for example signed int's are particually common), but in this case, all +that will be added is an additional 'cast' instruction. I removed that +from the spec. + +> I agree with your comment that we don't need 'neg' + +Removed. + +> There's a trade-off with the cast instruction: +> + it avoids having to define all the upcasts and downcasts that are +> valid for the operands of each instruction (you probably have +> thought of other benefits also) +> - it could make the bytecode significantly larger because there could +> be a lot of cast operations + + + You NEED casts to represent things like: + void foo(float); + ... + int x; + ... + foo(x); + in a language like C. Even in a Java like language, you need upcasts + and some way to implement dynamic downcasts. + + Not all forms of instructions take every type (for example you can't + shift by a floating point number of bits), thus SOME programs will need + implicit casts. + +To be efficient and to avoid your '-' point above, we just have to be +careful to specify that the instructions shall operate on all common +types, therefore casting should be relatively uncommon. For example all +of the arithmetic operations work on almost all data types. + +> Making the second arg. to 'shl' a ubyte seems good enough to me. +> 255 positions seems adequate for several generations of machines + +Okay, that comment is removed. + +> and is more compact than uint. + +No, it isn't. Remember that the bytecode encoding saves value slots into +the bytecode instructions themselves, not constant values. This is +another case where we may introduce more cast instructions (but we will +also reduce the number of opcode variants that must be supported by a +virtual machine). Because most shifts are by constant values, I don't +think that we'll have to cast many shifts. :) + +> I still have some major concerns about including malloc and free in the +> language (either as builtin functions or instructions). + +Agreed. How about this proposal: + +malloc/free are either built in functions or actual opcodes. They provide +all of the type safety that the document would indicate, blah blah +blah. :) + +Now, because of all of the excellent points that you raised, an +implementation may want to override the default malloc/free behavior of +the program. To do this, they simply implement a "malloc" and +"free" function. The virtual machine will then be defined to use the user +defined malloc/free function (which return/take void*'s, not type'd +pointers like the builtin function would) if one is available, otherwise +fall back on a system malloc/free. + +Does this sound like a good compromise? It would give us all of the +typesafety/elegance in the language while still allowing the user to do +all the cool stuff they want to... + +> 'alloca' on the other hand sounds like a good idea, and the +> implementation seems fairly language-independent so it doesn't have the +> problems with malloc listed above. + +Okay, once we get the above stuff figured out, I'll put it all in the +spec. + +> About indirect call: +> Your option #2 sounded good to me. I'm not sure I understand your +> concern about an explicit 'icall' instruction? + +I worry too much. :) The other alternative has been removed. 'icall' is +now up in the instruction list next to 'call'. + +> I believe tail calls are relatively easy to identify; do you know why +> .NET has a tailcall instruction? + +Although I am just guessing, I believe it probably has to do with the fact +that they want languages like Haskell and lisp to be efficiently runnable +on their VM. Of course this means that the VM MUST implement tail calls +'correctly', or else life will suck. :) I would put this into a future +feature bin, because it could be pretty handy... + +> A pair of important synchronization instr'ns to think about: +> load-linked +> store-conditional + +What is 'load-linked'? I think that (at least for now) I should add these +to the 'possible extensions' section, because they are not immediately +needed... + +> Other classes of instructions that are valuable for pipeline +> performance: +> conditional-move +> predicated instructions + +Conditional move is effectly a special case of a predicated +instruction... and I think that all predicated instructions can possibly +be implemented later in LLVM. It would significantly change things, and +it doesn't seem to be very necessary right now. It would seem to +complicate flow control analysis a LOT in the virtual machine. I would +tend to prefer that a predicated architecture like IA64 convert from a +"basic block" representation to a predicated rep as part of it's dynamic +complication phase. Also, if a basic block contains ONLY a move, then +that can be trivally translated into a conditional move... + +> I agree that we need a static data space. Otherwise, emulating global +> data gets unnecessarily complex. + +Definately. Also a later item though. :) + +> We once talked about adding a symbolic thread-id field to each +> .. +> Instead, it could a great topic for a separate study. + +Agreed. :) + +> What is the semantics of the IA64 stop bit? + +Basically, the IA64 writes instructions like this: +mov ... +add ... +sub ... +op xxx +op xxx +;; +mov ... +add ... +sub ... +op xxx +op xxx +;; + +Where the ;; delimits a group of instruction with no dependencies between +them, which can all be executed concurrently (to the limits of the +available functional units). The ;; gets translated into a bit set in one +of the opcodes. + +The advantages of this representation is that you don't have to do some +kind of 'thread id scheduling' pass by having to specify ahead of time how +many threads to use, and the representation doesn't have a per instruction +overhead... + +> And finally, another thought about the syntax for arrays :-) +> Although this syntax: +> array of +> is verbose, it will be used only in the human-readable assembly code so +> size should not matter. I think we should consider it because I find it +> to be the clearest syntax. It could even make arrays of function +> pointers somewhat readable. + +My only comment will be to give you an example of why this is a bad +idea. :) + +Here is an example of using the switch statement (with my recommended +syntax): + +switch uint %val, label %otherwise, + [%3 x {uint, label}] [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +Here it is with the syntax you are proposing: + +switch uint %val, label %otherwise, + array %3 of {uint, label} + array of {uint, label} + { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } + +Which is ambiguous and very verbose. It would be possible to specify +constants with [] brackets as in my syntax, which would look like this: + +switch uint %val, label %otherwise, + array %3 of {uint, label} [ { uint %57, label %l1 }, + { uint %20, label %l2 }, + { uint %14, label %l3 } ] + +But then the syntax is inconsistent between type definition and constant +definition (why do []'s enclose the constants but not the types??). + +Anyways, I'm sure that there is much debate still to be had over +this... :) + +-Chris + +http://www.nondot.org/~sabre/os/ +http://www.nondot.org/MagicStats/ +http://korbit.sourceforge.net/ + + diff --git a/final/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt b/final/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt new file mode 100644 index 00000000000..2c7534d9da1 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-13-Reference-Memory.txt @@ -0,0 +1,39 @@ +Date: Tue, 13 Feb 2001 13:29:52 -0600 (CST) +From: Chris Lattner +To: Vikram S. Adve +Subject: LLVM Concerns... + + +I've updated the documentation to include load store and allocation +instructions (please take a look and let me know if I'm on the right +track): + +file:/home/vadve/lattner/llvm/docs/LangRef.html#memoryops + +I have a couple of concerns I would like to bring up: + +1. Reference types + Right now, I've spec'd out the language to have a pointer type, which + works fine for lots of stuff... except that Java really has + references: constrained pointers that cannot be manipulated: added and + subtracted, moved, etc... Do we want to have a type like this? It + could be very nice for analysis (pointer always points to the start of + an object, etc...) and more closely matches Java semantics. The + pointer type would be kept for C++ like semantics. Through analysis, + C++ pointers could be promoted to references in the LLVM + representation. + +2. Our "implicit" memory references in assembly language: + After thinking about it, this model has two problems: + A. If you do pointer analysis and realize that two stores are + independent and can share the same memory source object, there is + no way to represent this in either the bytecode or assembly. + B. When parsing assembly/bytecode, we effectively have to do a full + SSA generation/PHI node insertion pass to build the dependencies + when we don't want the "pinned" representation. This is not + cool. + I'm tempted to make memory references explicit in both the assembly and + bytecode to get around this... what do you think? + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt b/final/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt new file mode 100644 index 00000000000..505343378df --- /dev/null +++ b/final/docs/HistoricalNotes/2001-02-13-Reference-MemoryResponse.txt @@ -0,0 +1,47 @@ +Date: Tue, 13 Feb 2001 18:25:42 -0600 +From: Vikram S. Adve +To: Chris Lattner +Subject: RE: LLVM Concerns... + +> 1. Reference types +> Right now, I've spec'd out the language to have a pointer type, which +> works fine for lots of stuff... except that Java really has +> references: constrained pointers that cannot be manipulated: added and +> subtracted, moved, etc... Do we want to have a type like this? It +> could be very nice for analysis (pointer always points to the start of +> an object, etc...) and more closely matches Java semantics. The +> pointer type would be kept for C++ like semantics. Through analysis, +> C++ pointers could be promoted to references in the LLVM +> representation. + + +You're right, having references would be useful. Even for C++ the *static* +compiler could generate references instead of pointers with fairly +straightforward analysis. Let's include a reference type for now. But I'm +also really concerned that LLVM is becoming big and complex and (perhaps) +too high-level. After we get some initial performance results, we may have +a clearer idea of what our goals should be and we should revisit this +question then. + +> 2. Our "implicit" memory references in assembly language: +> After thinking about it, this model has two problems: +> A. If you do pointer analysis and realize that two stores are +> independent and can share the same memory source object, + +not sure what you meant by "share the same memory source object" + +> there is +> no way to represent this in either the bytecode or assembly. +> B. When parsing assembly/bytecode, we effectively have to do a full +> SSA generation/PHI node insertion pass to build the dependencies +> when we don't want the "pinned" representation. This is not +> cool. + +I understand the concern. But again, let's focus on the performance first +and then look at the language design issues. E.g., it would be good to know +how big the bytecode files are before expanding them further. I am pretty +keen to explore the implications of LLVM for mobile devices. Both bytecode +size and power consumption are important to consider there. + +--Vikram + diff --git a/final/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt b/final/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt new file mode 100644 index 00000000000..5f7843ab563 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt @@ -0,0 +1,49 @@ +By Chris: + +LLVM has been designed with two primary goals in mind. First we strive to +enable the best possible division of labor between static and dynamic +compilers, and second, we need a flexible and powerful interface +between these two complementary stages of compilation. We feel that +providing a solution to these two goals will yield an excellent solution +to the performance problem faced by modern architectures and programming +languages. + +A key insight into current compiler and runtime systems is that a +compiler may fall in anywhere in a "continuum of compilation" to do its +job. On one side, scripting languages statically compile nothing and +dynamically compile (or equivalently, interpret) everything. On the far +other side, traditional static compilers process everything statically and +nothing dynamically. These approaches have typically been seen as a +tradeoff between performance and portability. On a deeper level, however, +there are two reasons that optimal system performance may be obtained by a +system somewhere in between these two extremes: Dynamic application +behavior and social constraints. + +From a technical perspective, pure static compilation cannot ever give +optimal performance in all cases, because applications have varying dynamic +behavior that the static compiler cannot take into consideration. Even +compilers that support profile guided optimization generate poor code in +the real world, because using such optimization tunes that application +to one particular usage pattern, whereas real programs (as opposed to +benchmarks) often have several different usage patterns. + +On a social level, static compilation is a very shortsighted solution to +the performance problem. Instruction set architectures (ISAs) continuously +evolve, and each implementation of an ISA (a processor) must choose a set +of tradeoffs that make sense in the market context that it is designed for. +With every new processor introduced, the vendor faces two fundamental +problems: First, there is a lag time between when a processor is introduced +to when compilers generate quality code for the architecture. Secondly, +even when compilers catch up to the new architecture there is often a large +body of legacy code that was compiled for previous generations and will +not or can not be upgraded. Thus a large percentage of code running on a +processor may be compiled quite sub-optimally for the current +characteristics of the dynamic execution environment. + +For these reasons, LLVM has been designed from the beginning as a long-term +solution to these problems. Its design allows the large body of platform +independent, static, program optimizations currently in compilers to be +reused unchanged in their current form. It also provides important static +type information to enable powerful dynamic and link time optimizations +to be performed quickly and efficiently. This combination enables an +increase in effective system performance for real world environments. diff --git a/final/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt b/final/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt new file mode 100644 index 00000000000..b546301d35a --- /dev/null +++ b/final/docs/HistoricalNotes/2001-05-18-ExceptionHandling.txt @@ -0,0 +1,202 @@ +Meeting notes: Implementation idea: Exception Handling in C++/Java + +The 5/18/01 meeting discussed ideas for implementing exceptions in LLVM. +We decided that the best solution requires a set of library calls provided by +the VM, as well as an extension to the LLVM function invocation syntax. + +The LLVM function invocation instruction previously looks like this (ignoring +types): + + call func(arg1, arg2, arg3) + +The extension discussed today adds an optional "with" clause that +associates a label with the call site. The new syntax looks like this: + + call func(arg1, arg2, arg3) with funcCleanup + +This funcHandler always stays tightly associated with the call site (being +encoded directly into the call opcode itself), and should be used whenever +there is cleanup work that needs to be done for the current function if +an exception is thrown by func (or if we are in a try block). + +To support this, the VM/Runtime provide the following simple library +functions (all syntax in this document is very abstract): + +typedef struct { something } %frame; + The VM must export a "frame type", that is an opaque structure used to + implement different types of stack walking that may be used by various + language runtime libraries. We imagine that it would be typical to + represent a frame with a PC and frame pointer pair, although that is not + required. + +%frame getStackCurrentFrame(); + Get a frame object for the current function. Note that if the current + function was inlined into its caller, the "current" frame will belong to + the "caller". + +bool isFirstFrame(%frame f); + Returns true if the specified frame is the top level (first activated) frame + for this thread. For the main thread, this corresponds to the main() + function, for a spawned thread, it corresponds to the thread function. + +%frame getNextFrame(%frame f); + Return the previous frame on the stack. This function is undefined if f + satisfies the predicate isFirstFrame(f). + +Label *getFrameLabel(%frame f); + If a label was associated with f (as discussed below), this function returns + it. Otherwise, it returns a null pointer. + +doNonLocalBranch(Label *L); + At this point, it is not clear whether this should be a function or + intrinsic. It should probably be an intrinsic in LLVM, but we'll deal with + this issue later. + + +Here is a motivating example that illustrates how these facilities could be +used to implement the C++ exception model: + +void TestFunction(...) { + A a; B b; + foo(); // Any function call may throw + bar(); + C c; + + try { + D d; + baz(); + } catch (int) { + ...int Stuff... + // execution continues after the try block: the exception is consumed + } catch (double) { + ...double stuff... + throw; // Exception is propogated + } +} + +This function would compile to approximately the following code (heavy +pseudo code follows): + +Func: + %a = alloca A + A::A(%a) // These ctors & dtors could throw, but we ignore this + %b = alloca B // minor detail for this example + B::B(%b) + + call foo() with fooCleanup // An exception in foo is propogated to fooCleanup + call bar() with barCleanup // An exception in bar is propogated to barCleanup + + %c = alloca C + C::C(c) + %d = alloca D + D::D(d) + call baz() with bazCleanup // An exception in baz is propogated to bazCleanup + d->~D(); +EndTry: // This label corresponds to the end of the try block + c->~C() // These could also throw, these are also ignored + b->~B() + a->~A() + return + +Note that this is a very straight forward and literal translation: exactly +what we want for zero cost (when unused) exception handling. Especially on +platforms with many registers (ie, the IA64) setjmp/longjmp style exception +handling is *very* impractical. Also, the "with" clauses describe the +control flow paths explicitly so that analysis is not adversly effected. + +The foo/barCleanup labels are implemented as: + +TryCleanup: // Executed if an exception escapes the try block + c->~C() +barCleanup: // Executed if an exception escapes from bar() + // fall through +fooCleanup: // Executed if an exception escapes from foo() + b->~B() + a->~A() + Exception *E = getThreadLocalException() + call throw(E) // Implemented by the C++ runtime, described below + +Which does the work one would expect. getThreadLocalException is a function +implemented by the C++ support library. It returns the current exception +object for the current thread. Note that we do not attempt to recycle the +shutdown code from before, because performance of the mainline code is +critically important. Also, obviously fooCleanup and barCleanup may be +merged and one of them eliminated. This just shows how the code generator +would most likely emit code. + +The bazCleanup label is more interesting. Because the exception may be caught +by the try block, we must dispatch to its handler... but it does not exist +on the call stack (it does not have a VM Call->Label mapping installed), so +we must dispatch statically with a goto. The bazHandler thus appears as: + +bazHandler: + d->~D(); // destruct D as it goes out of scope when entering catch clauses + goto TryHandler + +In general, TryHandler is not the same as bazHandler, because multiple +function calls could be made from the try block. In this case, trivial +optimization could merge the two basic blocks. TryHandler is the code +that actually determines the type of exception, based on the Exception object +itself. For this discussion, assume that the exception object contains *at +least*: + +1. A pointer to the RTTI info for the contained object +2. A pointer to the dtor for the contained object +3. The contained object itself + +Note that it is necessary to maintain #1 & #2 in the exception object itself +because objects without virtual function tables may be thrown (as in this +example). Assuming this, TryHandler would look something like this: + +TryHandler: + Exception *E = getThreadLocalException(); + switch (E->RTTIType) { + case IntRTTIInfo: + ...int Stuff... // The action to perform from the catch block + break; + case DoubleRTTIInfo: + ...double Stuff... // The action to perform from the catch block + goto TryCleanup // This catch block rethrows the exception + break; // Redundant, eliminated by the optimizer + default: + goto TryCleanup // Exception not caught, rethrow + } + + // Exception was consumed + if (E->dtor) + E->dtor(E->object) // Invoke the dtor on the object if it exists + goto EndTry // Continue mainline code... + +And that is all there is to it. + +The throw(E) function would then be implemented like this (which may be +inlined into the caller through standard optimization): + +function throw(Exception *E) { + // Get the start of the stack trace... + %frame %f = call getStackCurrentFrame() + + // Get the label information that corresponds to it + label * %L = call getFrameLabel(%f) + while (%L == 0 && !isFirstFrame(%f)) { + // Loop until a cleanup handler is found + %f = call getNextFrame(%f) + %L = call getFrameLabel(%f) + } + + if (%L != 0) { + call setThreadLocalException(E) // Allow handlers access to this... + call doNonLocalBranch(%L) + } + // No handler found! + call BlowUp() // Ends up calling the terminate() method in use +} + +That's a brief rundown of how C++ exception handling could be implemented in +llvm. Java would be very similar, except it only uses destructors to unlock +synchronized blocks, not to destroy data. Also, it uses two stack walks: a +nondestructive walk that builds a stack trace, then a destructive walk that +unwinds the stack as shown here. + +It would be trivial to get exception interoperability between C++ and Java. + diff --git a/final/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt b/final/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt new file mode 100644 index 00000000000..3375365f54c --- /dev/null +++ b/final/docs/HistoricalNotes/2001-05-19-ExceptionResponse.txt @@ -0,0 +1,45 @@ +Date: Sat, 19 May 2001 19:09:13 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Meeting writeup + +> I read it through and it looks great! + +Thanks! + +> The finally clause in Java may need more thought. The code for this clause +> is like a subroutine because it needs to be entered from many points (end of +> try block and beginning of each catch block), and then needs to *return to +> the place from where the code was entered*. That's why JVM has the +> jsr/jsr_w instruction. + +Hrm... I guess that is an implementation decision. It can either be +modelled as a subroutine (as java bytecodes do), which is really +gross... or it can be modelled as code duplication (emitted once inline, +then once in the exception path). Because this could, at worst, +slightly less than double the amount of code in a function (it is +bounded) I don't think this is a big deal. One of the really nice things +about the LLVM representation is that it still allows for runtime code +generation for exception paths (exceptions paths are not compiled until +needed). Obviously a static compiler couldn't do this though. :) + +In this case, only one copy of the code would be compiled... until the +other one is needed on demand. Also this strategy fits with the "zero +cost" exception model... the standard case is not burdened with extra +branches or "call"s. + +> I suppose you could save the return address in a particular register +> (specific to this finally block), jump to the finally block, and then at the +> end of the finally block, jump back indirectly through this register. It +> will complicate building the CFG but I suppose that can be handled. It is +> also unsafe in terms of checking where control returns (which is I suppose +> why the JVM doesn't use this). + +I think that a code duplication method would be cleaner, and would avoid +the caveats that you mention. Also, it does not slow down the normal case +with an indirect branch... + +Like everything, we can probably defer a final decision until later. :) + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt b/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt new file mode 100644 index 00000000000..97af16a2dad --- /dev/null +++ b/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations.txt @@ -0,0 +1,63 @@ +Date: Fri, 1 Jun 2001 16:38:17 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Interesting: GCC passes + + +Take a look at this document (which describes the order of optimizations +that GCC performs): + +http://gcc.gnu.org/onlinedocs/gcc_17.html + +The rundown is that after RTL generation, the following happens: + +1 . [t] jump optimization (jumps to jumps, etc) +2 . [t] Delete unreachable code +3 . Compute live ranges for CSE +4 . [t] Jump threading (jumps to jumps with identical or inverse conditions) +5 . [t] CSE +6 . *** Conversion to SSA +7 . [t] SSA Based DCE +8 . *** Conversion to LLVM +9 . UnSSA +10. GCSE +11. LICM +12. Strength Reduction +13. Loop unrolling +14. [t] CSE +15. [t] DCE +16. Instruction combination, register movement, scheduling... etc. + +I've marked optimizations with a [t] to indicate things that I believe to +be relatively trivial to implement in LLVM itself. The time consuming +things to reimplement would be SSA based PRE, Strength reduction & loop +unrolling... these would be the major things we would miss out on if we +did LLVM creation from tree code [inlining and other high level +optimizations are done on the tree representation]. + +Given the lack of "strong" optimizations that would take a long time to +reimplement, I am leaning a bit more towards creating LLVM from the tree +code. Especially given that SGI has GPL'd their compiler, including many +SSA based optimizations that could be adapted (besides the fact that their +code looks MUCH nicer than GCC :) + +Even if we choose to do LLVM code emission from RTL, we will almost +certainly want to move LLVM emission from step 8 down until at least CSE +has been rerun... which causes me to wonder if the SSA generation code +will still work (due to global variable dependencies and stuff). I assume +that it can be made to work, but might be a little more involved than we +would like. + +I'm continuing to look at the Tree -> RTL code. It is pretty gross +because they do some of the translation a statement at a time, and some +of it a function at a time... I'm not quite clear why and how the +distinction is drawn, but it does not appear that there is a wonderful +place to attach extra info. + +Anyways, I'm proceeding with the RTL -> LLVM conversion phase for now. We +can talk about this more on Monday. + +Wouldn't it be nice if there were a obvious decision to be made? :) + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt b/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt new file mode 100644 index 00000000000..6c9e0971a04 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt @@ -0,0 +1,71 @@ +Date: Fri, 1 Jun 2001 17:08:44 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: RE: Interesting: GCC passes + +> That is very interesting. I agree that some of these could be done on LLVM +> at link-time, but it is the extra time required that concerns me. Link-time +> optimization is severely time-constrained. + +If we were to reimplement any of these optimizations, I assume that we +could do them a translation unit at a time, just as GCC does now. This +would lead to a pipeline like this: + +Static optimizations, xlation unit at a time: +.c --GCC--> .llvm --llvmopt--> .llvm + +Link time optimizations: +.llvm --llvm-ld--> .llvm --llvm-link-opt--> .llvm + +Of course, many optimizations could be shared between llvmopt and +llvm-link-opt, but the wouldn't need to be shared... Thus compile time +could be faster, because we are using a "smarter" IR (SSA based). + +> BTW, about SGI, "borrowing" SSA-based optimizations from one compiler and +> putting it into another is not necessarily easier than re-doing it. +> Optimization code is usually heavily tied in to the specific IR they use. + +Understood. The only reason that I brought this up is because SGI's IR is +more similar to LLVM than it is different in many respects (SSA based, +relatively low level, etc), and could be easily adapted. Also their +optimizations are written in C++ and are actually somewhat +structured... of course it would be no walk in the park, but it would be +much less time consuming to adapt, say, SSA-PRE than to rewrite it. + +> But your larger point is valid that adding SSA based optimizations is +> feasible and should be fun. (Again, link time cost is the issue.) + +Assuming linktime cost wasn't an issue, the question is: +Does using GCC's backend buy us anything? + +> It also occurs to me that GCC is probably doing quite a bit of back-end +> optimization (step 16 in your list). Do you have a breakdown of that? + +Not really. The irritating part of GCC is that it mixes it all up and +doesn't have a clean seperation of concerns. A lot of the "back end +optimization" happens right along with other data optimizations (ie, CSE +of machine specific things). + +As far as REAL back end optimizations go, it looks something like this: + +1. Instruction combination: try to make CISCy instructions, if available +2. Register movement: try to get registers in the right places for the +architecture to avoid register to register moves. For example, try to get +the first argument of a function to naturally land in %o0 for sparc. +3. Instruction scheduling: 'nuff said :) +4. Register class preferencing: ?? +5. Local register allocation +6. global register allocation +7. Spilling +8. Local regalloc +9. Jump optimization +10. Delay slot scheduling +11. Branch shorting for CISC machines +12. Instruction selection & peephole optimization +13. Debug info output + +But none of this would be usable for LLVM anyways, unless we were using +GCC as a static compiler. + +-Chris + diff --git a/final/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt b/final/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt new file mode 100644 index 00000000000..1bc2eae746c --- /dev/null +++ b/final/docs/HistoricalNotes/2001-06-20-.NET-Differences.txt @@ -0,0 +1,30 @@ +Date: Wed, 20 Jun 2001 12:32:22 -0500 +From: Vikram Adve +To: Chris Lattner +Subject: .NET vs. our VM + +One significant difference between .NET CLR and our VM is that the CLR +includes full information about classes and inheritance. In fact, I just +sat through the paper on adding templates to .NET CLR, and the speaker +indicated that the goal seems to be to do simple static compilation (very +little lowering or optimization). Also, the templates implementation in CLR +"relies on dynamic class loading and JIT compilation". + +This is an important difference because I think there are some significant +advantages to have a much lower level VM layer, and do significant static +analysis and optimization. + +I also talked to the lead guy for KAI's C++ compiler (Arch Robison) and he +said that SGI and other commercial compilers have included options to export +their *IR* next to the object code (i.e., .il files) and use them for +link-time code generation. In fact, he said that the .o file was nearly +empty and was entirely generated from the .il at link-time. But he agreed +that this limited the link-time interprocedural optimization to modules +compiled by the same compiler, whereas our approach allows us to link and +optimize modules from multiple different compilers. (Also, of course, they +don't do anything for runtime optimization). + +All issues to bring up in Related Work. + +--Vikram + diff --git a/final/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt b/final/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt new file mode 100644 index 00000000000..3e10416fe67 --- /dev/null +++ b/final/docs/HistoricalNotes/2001-07-06-LoweringIRForCodeGen.txt @@ -0,0 +1,31 @@ +Date: Fri, 6 Jul 2001 16:56:56 -0500 +From: Vikram S. Adve +To: Chris Lattner +Subject: lowering the IR + +BTW, I do think that we should consider lowering the IR as you said. I +didn't get time to raise it today, but it comes up with the SPARC +move-conditional instruction. I don't think we want to put that in the core +VM -- it is a little too specialized. But without a corresponding +conditional move instruction in the VM, it is pretty difficult to maintain a +close mapping between VM and machine code. Other architectures may have +other such instructions. + +What I was going to suggest was that for a particular processor, we define +additional VM instructions that match some of the unusual opcodes on the +processor but have VM semantics otherwise, i.e., all operands are in SSA +form and typed. This means that we can re-generate core VM code from the +more specialized code any time we want (so that portability is not lost). + +Typically, a static compiler like gcc would generate just the core VM, which +is relatively portable. Anyone (an offline tool, the linker, etc., or even +the static compiler itself if it chooses) can transform that into more +specialized target-specific VM code for a particular architecture. If the +linker does it, it can do it after all machine-independent optimizations. +This would be the most convenient, but not necessary. + +The main benefit of lowering will be that we will be able to retain a close +mapping between VM and machine code. + +--Vikram + diff --git a/final/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt b/final/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt new file mode 100644 index 00000000000..9379081018d --- /dev/null +++ b/final/docs/HistoricalNotes/2001-09-18-OptimizeExceptions.txt @@ -0,0 +1,56 @@ +Date: Tue, 18 Sep 2001 00:38:37 -0500 (CDT) +From: Chris Lattner +To: Vikram S. Adve +Subject: Idea for a simple, useful link time optimization + + +In C++ programs, exceptions suck, and here's why: + +1. In virtually all function calls, you must assume that the function + throws an exception, unless it is defined as 'nothrow'. This means + that every function call has to have code to invoke dtors on objects + locally if one is thrown by the function. Most functions don't throw + exceptions, so this code is dead [with all the bad effects of dead + code, including icache pollution]. +2. Declaring a function nothrow causes catch blocks to be added to every + call that isnot provably nothrow. This makes them very slow. +3. Extra extraneous exception edges reduce the opportunity for code + motion. +4. EH is typically implemented with large lookup tables. Ours is going to + be much smaller (than the "standard" way of doing it) to start with, + but eliminating it entirely would be nice. :) +5. It is physically impossible to correctly put (accurate, correct) + exception specifications on generic, templated code. But it is trivial + to analyze instantiations of said code. +6. Most large C++ programs throw few exceptions. Most well designed + programs only throw exceptions in specific planned portions of the + code. + +Given our _planned_ model of handling exceptions, all of this would be +pretty trivial to eliminate through some pretty simplistic interprocedural +analysis. The DCE factor alone could probably be pretty significant. The +extra code motion opportunities could also be exploited though... + +Additionally, this optimization can be implemented in a straight forward +conservative manner, allowing libraries to be optimized or individual +files even (if there are leaf functions visible in the translation unit +that are called). + +I think it's a reasonable optimization that hasn't really been addressed +(because assembly is way too low level for this), and could have decent +payoffs... without being a overly complex optimization. + +After I wrote all of that, I found this page that is talking about +basically the same thing I just wrote, except that it is translation unit +at a time, tree based approach: +http://www.ocston.org/~jls/ehopt.html + +but is very useful from "expected gain" and references perspective. Note +that their compiler is apparently unable to inline functions that use +exceptions, so there numbers are pretty worthless... also our results +would (hopefully) be better because it's interprocedural... + +What do you think? + +-Chris + diff --git a/final/docs/HistoricalNotes/2002-05-12-InstListChange.txt b/final/docs/HistoricalNotes/2002-05-12-InstListChange.txt new file mode 100644 index 00000000000..004edb068d7 --- /dev/null +++ b/final/docs/HistoricalNotes/2002-05-12-InstListChange.txt @@ -0,0 +1,55 @@ +Date: Sun, 12 May 2002 17:12:53 -0500 (CDT) +From: Chris Lattner +To: "Vikram S. Adve" +Subject: LLVM change + +There is a fairly fundemental change that I would like to make to the LLVM +infrastructure, but I'd like to know if you see any drawbacks that I +don't... + +Basically right now at the basic block level, each basic block contains an +instruction list (returned by getInstList()) that is a ValueHolder of +instructions. To iterate over instructions, we must actually iterate over +the instlist, and access the instructions through the instlist. + +To add or remove an instruction from a basic block, we need to get an +iterator to an instruction, which, given just an Instruction*, requires a +linear search of the basic block the instruction is contained in... just +to insert an instruction before another instruction, or to delete an +instruction! This complicates algorithms that should be very simple (like +simple constant propogation), because they aren't actually sparse anymore, +they have to traverse basic blocks to remove constant propogated +instructions. + +Additionally, adding or removing instructions to a basic block +_invalidates all iterators_ pointing into that block, which is really +irritating. + +To fix these problems (and others), I would like to make the ordering of +the instructions be represented with a doubly linked list in the +instructions themselves, instead of an external data structure. This is +how many other representations do it, and frankly I can't remember why I +originally implemented it the way I did. + +Long term, all of the code that depends on the nasty features in the +instruction list (which can be found by grep'ing for getInstList()) will +be changed to do nice local transformations. In the short term, I'll +change the representation, but preserve the interface (including +getInstList()) so that all of the code doesn't have to change. + +Iteration over the instructions in a basic block remains the simple: +for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) ... + +But we will also support: +for (Instruction *I = BB->front(); I; I = I->getNext()) ... + +After converting instructions over, I'll convert basic blocks and +functions to have a similar interface. + +The only negative aspect of this change that I see is that it increases +the amount of memory consumed by one pointer per instruction. Given the +benefits, I think this is a very reasonable tradeoff. + +What do you think? + +-Chris diff --git a/final/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt b/final/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt new file mode 100644 index 00000000000..2ca46117ca8 --- /dev/null +++ b/final/docs/HistoricalNotes/2002-06-25-MegaPatchInfo.txt @@ -0,0 +1,72 @@ +Changes: +* Change the casting code to be const correct. Now, doing this is invalid: + const Value *V = ...; + Instruction *I = dyn_cast(V); + instead, the second line should be: + const Instruction *I = dyn_cast(V); + +* Change the casting code to allow casting a reference value thus: + const Value &V = ...; + Instruction &I = cast(V); + + dyn_cast does not work with references, because it must return a null pointer + on failure. + +* Fundamentally change how instructions and other values are represented. + Before, every llvm container was an instance of the ValueHolder template, + instantiated for each container type. This ValueHolder was effectively a + wrapper around a vector of pointers to the sub-objects. + + Now, instead of having a vector to pointers of objects, the objects are + maintained in a doubly linked list of values (ie each Instruction now has + Next & Previous fields). The containers are now instances of ilist (intrusive + linked list class), which use the next and previous fields to chain them + together. The advantage of this implementation is that iterators can be + formed directly from pointers to the LLVM value, and invalidation is much + easier to handle. + +* As part of the above change, dereferencing an iterator (for example: + BasicBlock::iterator) now produces a reference to the underlying type (same + example: Instruction&) instead of a pointer to the underlying object. This + makes it much easier to write nested loops that iterator over things, changing + this: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = (*BI)->begin(); II != (*BI)->end(); ++II) + (*II)->dump(); + + into: + + for (Function::iterator BI = Func->begin(); BI != Func->end(); ++BI) + for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) + II->dump(); + + which is much more natural and what users expect. + +* Simplification of #include's: Before, it was necessary for a .cpp file to + include every .h file that it used. Now things are batched a little bit more + to make it easier to use. Specifically, the include graph now includes these + edges: + Module.h -> Function.h, GlobalVariable.h + Function.h -> BasicBlock.h, Argument.h + BasicBlock.h -> Instruction.h + + Which means that #including Function.h is usually sufficient for getting the + lower level #includes. + +* Printing out a Value* has now changed: Printing a Value* will soon print out + the address of the value instead of the contents of the Value. To print out + the contents, you must convert it to a reference with (for example) + 'cout << *I' instead of 'cout << I;'. This conversion is not yet complete, + but will be eventually. In the mean time, both forms print out the contents. + +* References are used much more throughout the code base. In general, if a + pointer is known to never be null, it is passed in as a reference instead of a + pointer. For example, the instruction visitor class uses references instead + of pointers, and that Pass subclasses now all receive references to Values + instead of pointers, because they may never be null. + +* The Function class now has helper functions for accessing the Arguments list. + Instead of having to go through getArgumentList for simple things like + iterator over the arguments, now the a*() methods can be used to access them. + diff --git a/final/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt b/final/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt new file mode 100644 index 00000000000..fbe811d627f --- /dev/null +++ b/final/docs/HistoricalNotes/2003-01-23-CygwinNotes.txt @@ -0,0 +1,28 @@ +Date: Mon, 20 Jan 2003 00:00:28 -0600 +From: Brian R. Gaeke +Subject: windows vs. llvm + +If you're interested, here are some of the major problems compiling LLVM +under Cygwin and/or Mingw. + +1. Cygwin doesn't have or , so all the INT*_MAX + symbols and standard int*_t types are off in limbo somewhere. Mingw has + , but Cygwin doesn't like it. + +2. Mingw doesn't have (because Windows doesn't have it.) + +3. SA_SIGINFO and friends are not around; only signal() seems to work. + +4. Relink, aka ld -r, doesn't work (probably an ld bug); you need + DONT_BUILD_RELINKED. This breaks all the tools makefiles; you just need to + change them to have .a's. + +5. There isn't a . + +6. There isn't a mallinfo() (or, at least, it's documented, but it doesn't seem + to link). + +7. The version of Bison that cygwin (and newer Linux versions) comes with + does not like = signs in rules. Burg's gram.yc source file uses them. I think + you can just take them out. + diff --git a/final/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt b/final/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt new file mode 100644 index 00000000000..a7457846395 --- /dev/null +++ b/final/docs/HistoricalNotes/2003-06-25-Reoptimizer1.txt @@ -0,0 +1,137 @@ +Wed Jun 25 15:13:51 CDT 2003 + +First-level instrumentation +--------------------------- + +We use opt to do Bytecode-to-bytecode instrumentation. Look at +back-edges and insert llvm_first_trigger() function call which takes +no arguments and no return value. This instrumentation is designed to +be easy to remove, for instance by writing a NOP over the function +call instruction. + +Keep count of every call to llvm_first_trigger(), and maintain +counters in a map indexed by return address. If the trigger count +exceeds a threshold, we identify a hot loop and perform second-level +instrumentation on the hot loop region (the instructions between the +target of the back-edge and the branch that causes the back-edge). We +do not move code across basic-block boundaries. + + +Second-level instrumentation +--------------------------- + +We remove the first-level instrumentation by overwriting the CALL to +llvm_first_trigger() with a NOP. + +The reoptimizer maintains a map between machine-code basic blocks and +LLVM BasicBlock*s. We only keep track of paths that start at the +first machine-code basic block of the hot loop region. + +How do we keep track of which edges to instrument, and which edges are +exits from the hot region? 3 step process. + +1) Do a DFS from the first machine-code basic block of the hot loop +region and mark reachable edges. + +2) Do a DFS from the last machine-code basic block of the hot loop +region IGNORING back edges, and mark the edges which are reachable in +1) and also in 2) (i.e., must be reachable from both the start BB and +the end BB of the hot region). + +3) Mark BBs which end in edges that exit the hot region; we need to +instrument these differently. + +Assume that there is 1 free register. On SPARC we use %g1, which LLC +has agreed not to use. Shift a 1 into it at the beginning. At every +edge which corresponds to a conditional branch, we shift 0 for not +taken and 1 for taken into a register. This uniquely numbers the paths +through the hot region. Silently fail if we need more than 64 bits. + +At the end BB we call countPath and increment the counter based on %g1 +and the return address of the countPath call. We keep track of the +number of iterations and the number of paths. We only run this +version 30 or 40 times. + +Find the BBs that total 90% or more of execution, and aggregate them +together to form our trace. But we do not allow more than 5 paths; if +we have more than 5 we take the ones that are executed the most. We +verify our assumption that we picked a hot back-edge in first-level +instrumentation, by making sure that the number of times we took an +exit edge from the hot trace is less than 10% of the number of +iterations. + +LLC has been taught to recognize llvm_first_trigger() calls and NOT +generate saves and restores of caller-saved registers around these +calls. + + +Phase behavior +-------------- + +We turn off llvm_first_trigger() calls with NOPs, but this would hide +phase behavior from us (when some funcs/traces stop being hot and +others become hot.) + +We have a SIGALRM timer that counts time for us. Every time we get a +SIGALRM we look at our priority queue of locations where we have +removed llvm_first_trigger() calls. Each location is inserted along +with a time when we will next turn instrumentation back on for that +call site. If the time has arrived for a particular call site, we pop +that off the prio. queue and turn instrumentation back on for that +call site. + + +Generating traces +----------------- + +When we finally generate an optimized trace we first copy the code +into the trace cache. This leaves us with 3 copies of the code: the +original code, the instrumented code, and the optimized trace. The +optimized trace does not have instrumentation. The original code and +the instrumented code are modified to have a branch to the trace +cache, where the optimized traces are kept. + +We copy the code from the original to the instrumentation version +by tracing the LLVM-to-Machine code basic block map and then copying +each machine code basic block we think is in the hot region into the +trace cache. Then we instrument that code. The process is similar for +generating the final optimized trace; we copy the same basic blocks +because we might need to put in fixup code for exit BBs. + +LLVM basic blocks are not typically used in the Reoptimizer except +for the mapping information. + +We are restricted to using single instructions to branch between the +original code, trace, and instrumented code. So we have to keep the +code copies in memory near the original code (they can't be far enough +away that a single pc-relative branch would not work.) Malloc() or +data region space is too far away. this impacts the design of the +trace cache. + +We use a dummy function that is full of a bunch of for loops which we +overwrite with trace-cache code. The trace manager keeps track of +whether or not we have enough space in the trace cache, etc. + +The trace insertion routine takes an original start address, a vector +of machine instructions representing the trace, index of branches and +their corresponding absolute targets, and index of calls and their +corresponding absolute targets. + +The trace insertion routine is responsible for inserting branches from +the beginning of the original code to the beginning of the optimized +trace. This is because at some point the trace cache may run out of +space and it may have to evict a trace, at which point the branch to +the trace would also have to be removed. It uses a round-robin +replacement policy; we have found that this is almost as good as LRU +and better than random (especially because of problems fitting the new +trace in.) + +We cannot deal with discontiguous trace cache areas. The trace cache +is supposed to be cache-line-aligned, but it is not page-aligned. + +We generate instrumentation traces and optimized traces into separate +trace caches. We keep the instrumented code around because you don't +want to delete a trace when you still might have to return to it +(i.e., return from a llvm_first_trigger() or countPath() call.) + + diff --git a/final/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt b/final/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt new file mode 100644 index 00000000000..ec4b93fea0a --- /dev/null +++ b/final/docs/HistoricalNotes/2003-06-26-Reoptimizer2.txt @@ -0,0 +1,110 @@ +Thu Jun 26 14:43:04 CDT 2003 + +Information about BinInterface +------------------------------ + +Take in a set of instructions with some particular register +allocation. It allows you to add, modify, or delete some instructions, +in SSA form (kind of like LLVM's MachineInstrs.) Then re-allocate +registers. It assumes that the transformations you are doing are safe. +It does not update the mapping information or the LLVM representation +for the modified trace (so it would not, for instance, support +multiple optimization passes; passes have to be aware of and update +manually the mapping information.) + +The way you use it is you take the original code and provide it to +BinInterface; then you do optimizations to it, then you put it in the +trace cache. + +The BinInterface tries to find live-outs for traces so that it can do +register allocation on just the trace, and stitch the trace back into +the original code. It has to preserve the live-ins and live-outs when +it does its register allocation. (On exits from the trace we have +epilogues that copy live-outs back into the right registers, but +live-ins have to be in the right registers.) + + +Limitations of BinInterface +--------------------------- + +It does copy insertions for PHIs, which it infers from the machine +code. The mapping info inserted by LLC is not sufficient to determine +the PHIs. + +It does not handle integer or floating-point condition codes and it +does not handle floating-point register allocation. + +It is not aggressively able to use lots of registers. + +There is a problem with alloca: we cannot find our spill space for +spilling registers, normally allocated on the stack, if the trace +follows an alloca(). What might be an acceptable solution would be to +disable trace generation on functions that have variable-sized +alloca()s. Variable-sized allocas in the trace would also probably +screw things up. + +Because of the FP and alloca limitations, the BinInterface is +completely disabled right now. + + +Demo +---- + +This is a demo of the Ball & Larus version that does NOT use 2-level +profiling. + +1. Compile program with llvm-gcc. +2. Run opt -lowerswitch -paths -emitfuncs on the bytecode. + -lowerswitch change switch statements to branches + -paths Ball & Larus path-profiling algorithm + -emitfuncs emit the table of functions +3. Run llc to generate SPARC assembly code for the result of step 2. +4. Use g++ to link the (instrumented) assembly code. + +We use a script to do all this: +------------------------------------------------------------------------------ +#!/bin/sh +llvm-gcc $1.c -o $1 +opt -lowerswitch -paths -emitfuncs $1.bc > $1.run.bc +llc -f $1.run.bc +LIBS=$HOME/llvm_sparc/lib/Debug +GXX=/usr/dcs/software/evaluation/bin/g++ +$GXX -g -L $LIBS $1.run.s -o $1.run.llc \ +$LIBS/tracecache.o \ +$LIBS/mapinfo.o \ +$LIBS/trigger.o \ +$LIBS/profpaths.o \ +$LIBS/bininterface.o \ +$LIBS/support.o \ +$LIBS/vmcore.o \ +$LIBS/transformutils.o \ +$LIBS/bcreader.o \ +-lscalaropts -lscalaropts -lanalysis \ +-lmalloc -lcpc -lm -ldl +------------------------------------------------------------------------------ + +5. Run the resulting binary. You will see output from BinInterface +(described below) intermixed with the output from the program. + + +Output from BinInterface +------------------------ + +BinInterface's debugging code prints out the following stuff in order: + +1. Initial code provided to BinInterface with original register +allocation. + +2. Section 0 is the trace prolog, consisting mainly of live-ins and +register saves which will be restored in epilogs. + +3. Section 1 is the trace itself, in SSA form used by BinInterface, +along with the PHIs that are inserted. +PHIs are followed by the copies that implement them. +Each branch (i.e., out of the trace) is annotated with the +section number that represents the epilog it branches to. + +4. All the other sections starting with Section 2 are trace epilogs. +Every branch from the trace has to go to some epilog. + +5. After the last section is the register allocation output. diff --git a/final/docs/HistoricalNotes/2007-OriginalClangReadme.txt b/final/docs/HistoricalNotes/2007-OriginalClangReadme.txt new file mode 100644 index 00000000000..611dc9d2c01 --- /dev/null +++ b/final/docs/HistoricalNotes/2007-OriginalClangReadme.txt @@ -0,0 +1,178 @@ +//===----------------------------------------------------------------------===// +// C Language Family Front-end +//===----------------------------------------------------------------------===// + Chris Lattner + +I. Introduction: + + clang: noun + 1. A loud, resonant, metallic sound. + 2. The strident call of a crane or goose. + 3. C-language family front-end toolkit. + + The world needs better compiler tools, tools which are built as libraries. This + design point allows reuse of the tools in new and novel ways. However, building + the tools as libraries isn't enough: they must have clean APIs, be as + decoupled from each other as possible, and be easy to modify/extend. This + requires clean layering, decent design, and avoiding tying the libraries to a + specific use. Oh yeah, did I mention that we want the resultant libraries to + be as fast as possible? :) + + This front-end is built as a component of the LLVM toolkit that can be used + with the LLVM backend or independently of it. In this spirit, the API has been + carefully designed as the following components: + + libsupport - Basic support library, reused from LLVM. + + libsystem - System abstraction library, reused from LLVM. + + libbasic - Diagnostics, SourceLocations, SourceBuffer abstraction, + file system caching for input source files. This depends on + libsupport and libsystem. + + libast - Provides classes to represent the C AST, the C type system, + builtin functions, and various helpers for analyzing and + manipulating the AST (visitors, pretty printers, etc). This + library depends on libbasic. + + + liblex - C/C++/ObjC lexing and preprocessing, identifier hash table, + pragma handling, tokens, and macros. This depends on libbasic. + + libparse - C (for now) parsing and local semantic analysis. This library + invokes coarse-grained 'Actions' provided by the client to do + stuff (e.g. libsema builds ASTs). This depends on liblex. + + libsema - Provides a set of parser actions to build a standardized AST + for programs. AST's are 'streamed' out a top-level declaration + at a time, allowing clients to use decl-at-a-time processing, + build up entire translation units, or even build 'whole + program' ASTs depending on how they use the APIs. This depends + on libast and libparse. + + librewrite - Fast, scalable rewriting of source code. This operates on + the raw syntactic text of source code, allowing a client + to insert and delete text in very large source files using + the same source location information embedded in ASTs. This + is intended to be a low-level API that is useful for + higher-level clients and libraries such as code refactoring. + + libanalysis - Source-level dataflow analysis useful for performing analyses + such as computing live variables. It also includes a + path-sensitive "graph-reachability" engine for writing + analyses that reason about different possible paths of + execution through source code. This is currently being + employed to write a set of checks for finding bugs in software. + + libcodegen - Lower the AST to LLVM IR for optimization & codegen. Depends + on libast. + + clang - An example driver, client of the libraries at various levels. + This depends on all these libraries, and on LLVM VMCore. + + This front-end has been intentionally built as a DAG of libraries, making it + easy to reuse individual parts or replace pieces if desired. For example, to + build a preprocessor, you take the Basic and Lexer libraries. If you want an + indexer, you take those plus the Parser library and provide some actions for + indexing. If you want a refactoring, static analysis, or source-to-source + compiler tool, it makes sense to take those plus the AST building and semantic + analyzer library. Finally, if you want to use this with the LLVM backend, + you'd take these components plus the AST to LLVM lowering code. + + In the future I hope this toolkit will grow to include new and interesting + components, including a C++ front-end, ObjC support, and a whole lot of other + things. + + Finally, it should be pointed out that the goal here is to build something that + is high-quality and industrial-strength: all the obnoxious features of the C + family must be correctly supported (trigraphs, preprocessor arcana, K&R-style + prototypes, GCC/MS extensions, etc). It cannot be used if it is not 'real'. + + +II. Usage of clang driver: + + * Basic Command-Line Options: + - Help: clang --help + - Standard GCC options accepted: -E, -I*, -i*, -pedantic, -std=c90, etc. + - To make diagnostics more gcc-like: -fno-caret-diagnostics -fno-show-column + - Enable metric printing: -stats + + * -fsyntax-only is currently the default mode. + + * -E mode works the same way as GCC. + + * -Eonly mode does all preprocessing, but does not print the output, + useful for timing the preprocessor. + + * -fsyntax-only is currently partially implemented, lacking some + semantic analysis (some errors and warnings are not produced). + + * -parse-noop parses code without building an AST. This is useful + for timing the cost of the parser without including AST building + time. + + * -parse-ast builds ASTs, but doesn't print them. This is most + useful for timing AST building vs -parse-noop. + + * -parse-ast-print pretty prints most expression and statements nodes. + + * -parse-ast-check checks that diagnostic messages that are expected + are reported and that those which are reported are expected. + + * -dump-cfg builds ASTs and then CFGs. CFGs are then pretty-printed. + + * -view-cfg builds ASTs and then CFGs. CFGs are then visualized by + invoking Graphviz. + + For more information on getting Graphviz to work with clang/LLVM, + see: http://llvm.org/docs/ProgrammersManual.html#ViewGraph + + +III. Current advantages over GCC: + + * Column numbers are fully tracked (no 256 col limit, no GCC-style pruning). + * All diagnostics have column numbers, includes 'caret diagnostics', and they + highlight regions of interesting code (e.g. the LHS and RHS of a binop). + * Full diagnostic customization by client (can format diagnostics however they + like, e.g. in an IDE or refactoring tool) through DiagnosticClient interface. + * Built as a framework, can be reused by multiple tools. + * All languages supported linked into same library (no cc1,cc1obj, ...). + * mmap's code in read-only, does not dirty the pages like GCC (mem footprint). + * LLVM License, can be linked into non-GPL projects. + * Full diagnostic control, per diagnostic. Diagnostics are identified by ID. + * Significantly faster than GCC at semantic analysis, parsing, preprocessing + and lexing. + * Defers exposing platform-specific stuff to as late as possible, tracks use of + platform-specific features (e.g. #ifdef PPC) to allow 'portable bytecodes'. + * The lexer doesn't rely on the "lexer hack": it has no notion of scope and + does not categorize identifiers as types or variables -- this is up to the + parser to decide. + +Potential Future Features: + + * Fine grained diag control within the source (#pragma enable/disable warning). + * Better token tracking within macros? (Token came from this line, which is + a macro argument instantiated here, recursively instantiated here). + * Fast #import with a module system. + * Dependency tracking: change to header file doesn't recompile every function + that texually depends on it: recompile only those functions that need it. + This is aka 'incremental parsing'. + + +IV. Missing Functionality / Improvements + +Lexer: + * Source character mapping. GCC supports ASCII and UTF-8. + See GCC options: -ftarget-charset and -ftarget-wide-charset. + * Universal character support. Experimental in GCC, enabled with + -fextended-identifiers. + * -fpreprocessed mode. + +Preprocessor: + * #assert/#unassert + * MSExtension: "L#param" stringizes to a wide string literal. + * Add support for -M* + +Traditional Preprocessor: + * Currently, we have none. :) + diff --git a/final/docs/HowToReleaseLLVM.html b/final/docs/HowToReleaseLLVM.html new file mode 100644 index 00000000000..a428ddfbe0a --- /dev/null +++ b/final/docs/HowToReleaseLLVM.html @@ -0,0 +1,626 @@ + + + + How To Release LLVM To The Public + + + + +
How To Release LLVM To The Public
+
    +
  1. Introduction
  2. +
  3. Qualification Criteria
  4. +
  5. Release Timeline
  6. +
  7. Release Process
  8. +
+ + + + + + +
+ +

This document contains information about successfully releasing LLVM — + including subprojects: e.g., llvm-gcc and clang — to + the public. It is the Release Manager's responsibility to ensure that a high + quality build of LLVM is released.

+ +
+ + + + +
+ +

LLVM is released on a time based schedule — roughly every 6 months. We + do not normally have dot releases because of the nature of LLVM's incremental + development philosophy. That said, the only thing preventing dot releases for + critical bug fixes from happening is a lack of resources — testers, + machines, time, etc. And, because of the high quality we desire for LLVM + releases, we cannot allow for a truncated form of release qualification.

+ +

The release process is roughly as follows:

+ +
    +
  • Set code freeze and branch creation date for 6 months after last code + freeze date. Announce release schedule to the LLVM community and update + the website.

  • + +
  • Create release branch and begin release process.

  • + +
  • Send out release candidate sources for first round of testing. Testing + lasts 7-10 days. During the first round of testing, any regressions found + should be fixed. Patches are merged from mainline into the release + branch. Also, all features need to be completed during this time. Any + features not completed at the end of the first round of testing will be + removed or disabled for the release.

  • + +
  • Generate and send out the second release candidate sources. Only + critial bugs found during this testing phase will be fixed. Any + bugs introduced by merged patches will be fixed. If so a third round of + testing is needed.

  • + +
  • The release notes are updated.

  • + +
  • Finally, release!

  • +
+ +
+ + + + + + + + + + +
+ +

This section describes a few administrative tasks that need to be done for + the release process to begin. Specifically, it involves:

+ +
    +
  • Creating the release branch,
  • +
  • Setting version numbers, and
  • +
  • Tagging release candidates for the release team to begin testing
  • +
+ +
+ + + + +
+ +

Branch the Subversion trunk using the following procedure:

+ +
    +
  1. Remind developers that the release branching is imminent and to refrain + from committing patches that might break the build. E.g., new features, + large patches for works in progress, an overhaul of the type system, an + exciting new TableGen feature, etc.

  2. + +
  3. Verify that the current Subversion trunk is in decent shape by + examining nightly tester and buildbot results.

  4. + +
  5. Create the release branch for llvm, llvm-gcc-4.2, + clang, and the test-suite from the last known good + revision. The branch's name is release_XY, where X is + the major and Y the minor release numbers. The branches should be + created using the following commands:

    + +
    +
    +$ svn copy https://llvm.org/svn/llvm-project/llvm/trunk \
    +           https://llvm.org/svn/llvm-project/llvm/branches/release_XY
    +
    +$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk \
    +           https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY
    +
    +$ svn copy https://llvm.org/svn/llvm-project/test-suite/trunk \
    +           https://llvm.org/svn/llvm-project/test-suite/branches/release_XY
    +
    +$ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
    +           https://llvm.org/svn/llvm-project/cfe/branches/release_XY
    +
    +
  6. + +
  7. Advise developers that they may now check their patches into the + Subversion tree again.

  8. + +
  9. The Release Manager should switch to the release branch, because all + changes to the release will now be done in the branch. The easiest way to + do this is to grab a working copy using the following commands:

    + +
    +
    +$ svn co https://llvm.org/svn/llvm-project/llvm/branches/release_XY llvm-X.Y
    +
    +$ svn co https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY llvm-gcc-4.2-X.Y
    +
    +$ svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_XY test-suite-X.Y
    +
    +$ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_XY clang-X.Y
    +
    +
  10. +
+ +
+ + + + +
+ +

After creating the LLVM release branch, update the release branches' + autoconf and configure.ac versions from 'X.Ysvn' + to 'X.Y'. Update it on mainline as well to be the next version + ('X.Y+1svn'). Regenerate the configure scripts for both + llvm and the test-suite.

+ +

In addition, the version numbers of all the Bugzilla components must be + updated for the next release.

+ +
+ + + + +
+ +

Create release candidates for llvm, llvm-gcc, + clang, and the LLVM test-suite by tagging the branch with + the respective release candidate number. For instance, to create Release + Candidate 1 you would issue the following commands:

+ +
+
+$ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY
+$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
+           https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/rc1
+
+$ svn mkdir https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_XY
+$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY \
+           https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_XY/rc1
+
+$ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY
+$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
+           https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/rc1
+
+$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY
+$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
+           https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/rc1
+
+
+ +

Similarly, Release Candidate 2 would be named RC2 and so + on. This keeps a permanent copy of the release candidate around for people to + export and build as they wish. The final released sources will be tagged in + the RELEASE_XY directory as Final + (c.f. Tag the LLVM Final Release).

+ +

The Release Manager may supply pre-packaged source tarballs for users. This + can be done with the following commands:

+ +
+
+$ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/rc1 llvm-X.Yrc1
+$ svn export https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_XY/rc1 llvm-gcc4.2-X.Yrc1
+$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/rc1 llvm-test-X.Yrc1
+$ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/rc1 clang-X.Yrc1
+
+$ tar -czvf - llvm-X.Yrc1        | gzip > llvm-X.Yrc1.src.tar.gz
+$ tar -czvf - llvm-test-X.Yrc1   | gzip > llvm-test-X.Yrc1.src.tar.gz
+$ tar -czvf - llvm-gcc4.2-X.Yrc1 | gzip > llvm-gcc-4.2-X.Yrc1.src.tar.gz
+$ tar -czvf - clang-X.Yrc1       | gzip > clang-X.Yrc1.src.tar.gz
+
+
+ +
+ + + + +
+ +

The builds of llvm, llvm-gcc, and clang + must be free of errors and warnings in Debug, Release+Asserts, and + Release builds. If all builds are clean, then the release passes Build + Qualification.

+ +

The make options for building the different modes:

+ + + + + + +
ModeOptions
DebugENABLE_OPTIMIZED=0
Release+AssertsENABLE_OPTIMIZED=1
ReleaseENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1
+ +
+ + + + +
+ +

Build Debug, Release+Asserts, and Release versions + of llvm on all supported platforms. Directions to build + llvm are + here.

+ +
+ + + + +
+ +

Creating the llvm-gcc binary distribution (Release/Optimized) + requires performing the following steps for each supported platform:

+ +
    +
  1. Build the llvm-gcc front-end by following the directions in + the README.LLVM file. The front-end must be compiled with C, C++, + Objective-C (Mac only), Objective-C++ (Mac only), and Fortran + support.

  2. + +
  3. Boostrapping must be enabled.

  4. + +
  5. Be sure to build with LLVM_VERSION_INFO=X.Y, where X + is the major and Y is the minor release numbers.

  6. + +
  7. Copy the installation directory to a directory named for the specific + target. For example on Red Hat Enterprise Linux, the directory would be + named llvm-gcc4.2-2.6-x86-linux-RHEL4. Archive and compress the + new directory.

  8. +
+ +
+ + + + +
+ +

Creating the clang binary distribution + (Debug/Release+Asserts/Release) requires performing the following steps for + each supported platform:

+ +
    +
  1. Build clang according to the directions + here.
  2. + +
  3. Build both a debug and release version of clang. The binary will be the + release build.
  4. + +
  5. Package clang (details to follow).
  6. +
+ +
+ + + + +
+ +

The table below specifies which compilers are used for each Arch/OS + combination when qualifying the build of llvm, llvm-gcc, + and clang.

+ + + + + + + + + + +
ArchitectureOScompiler
x86-32Mac OS 10.5gcc 4.0.1
x86-32Linuxgcc 4.2.X, gcc 4.3.X
x86-32FreeBSDgcc 4.2.X
x86-32mingwgcc 3.4.5
x86-64Mac OS 10.5gcc 4.0.1
x86-64Linuxgcc 4.2.X, gcc 4.3.X
x86-64FreeBSDgcc 4.2.X
+ +
+ + + + +
+ +

A release is qualified when it has no regressions from the previous release + (or baseline). Regressions are related to correctness first and performance + second. (We may tolerate some minor performance regressions if they are + deemed necessary for the general quality of the compiler.)

+ +

Regressions are new failures in the set of tests that are used to qualify + each product and only include things on the list. Every release will have + some bugs in it. It is the reality of developing a complex piece of + software. We need a very concrete and definitive release criteria that + ensures we have monotonically improving quality on some metric. The metric we + use is described below. This doesn't mean that we don't care about other + criteria, but these are the criteria which we found to be most important and + which must be satisfied before a release can go out

+ +
+ + + + +
+ +

LLVM is qualified when it has a clean test run without a front-end. And it + has no regressions when using either llvm-gcc or clang with + the test-suite from the previous release.

+ +
+ + + + +
+ +

LLVM-GCC is qualified when front-end specific tests in the + llvm regression test suite all pass and there are no regressions in + the test-suite.

+ +

We do not use the GCC DejaGNU test suite as release criteria.

+ +
+ + + + +
+ +

Clang is qualified when front-end specific tests in the + llvm dejagnu test suite all pass, clang's own test suite passes + cleanly, and there are no regressions in the test-suite.

+ +
+ + + + +
+ + + + + + + + + +
ArchitectureOSllvm-gcc baselineclang baselinetests
x86-32Linuxlast releaselast releasellvm dejagnu, clang tests, test-suite (including spec)
x86-32FreeBSDnonelast releasellvm dejagnu, clang tests, test-suite
x86-32mingwlast releasenoneQT
x86-64Mac OS 10.Xlast releaselast releasellvm dejagnu, clang tests, test-suite (including spec)
x86-64Linuxlast releaselast releasellvm dejagnu, clang tests, test-suite (including spec)
x86-64FreeBSDnonelast releasellvm dejagnu, clang tests, test-suite
+ +
+ + + +
+ +

Once all testing has been completed and appropriate bugs filed, the release + candidate tarballs are put on the website and the LLVM community is + notified. Ask that all LLVM developers test the release in 2 ways:

+ +
    +
  1. Download llvm-X.Y, llvm-test-X.Y, and the + appropriate llvm-gcc and/or clang binary. Build + LLVM. Run make check and the full LLVM test suite (make + TEST=nightly report).
  2. + +
  3. Download llvm-X.Y, llvm-test-X.Y, and the + llvm-gcc and/or clang source. Compile everything. Run + make check and the full LLVM test suite (make TEST=nightly + report).
  4. +
+ +

Ask LLVM developers to submit the test suite report and make check + results to the list. Verify that there are no regressions from the previous + release. The results are not used to qualify a release, but to spot other + potential problems. For unsupported targets, verify that make check + is at least clean.

+ +

During the first round of testing, all regressions must be fixed before the + second release candidate is tagged.

+ +

If this is the second round of testing, the testing is only to ensure that + bug fixes previously merged in have not created new major problems. This + is not the time to solve additional and unrelated bugs! If no patches are + merged in, the release is determined to be ready and the release manager may + move onto the next stage.

+ +
+ + + + +
+ +

Below are the rules regarding patching the release branch:

+ +
    +
  1. Patches applied to the release branch may only be applied by the + release manager.

  2. + +
  3. During the first round of testing, patches that fix regressions or that + are small and relatively risk free (verified by the appropriate code + owner) are applied to the branch. Code owners are asked to be very + conservative in approving patches for the branch. We reserve the right to + reject any patch that does not fix a regression as previously + defined.

  4. + +
  5. During the remaining rounds of testing, only patches that fix critical + regressions may be applied.

  6. +
+ +
+ + + + +
+ +

The final stages of the release process involves tagging the "final" release + branch, updating documentation that refers to the release, and updating the + demo page.

+ +
+ + + + + +
+ +

Review the documentation and ensure that it is up to date. The "Release + Notes" must be updated to reflect new features, bug fixes, new known issues, + and changes in the list of supported platforms. The "Getting Started Guide" + should be updated to reflect the new release version number tag avaiable from + Subversion and changes in basic system requirements. Merge both changes from + mainline into the release branch.

+ +
+ + + + +
+ +

Tag the final release sources using the following procedure:

+ +
+
+$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
+           https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XY/Final
+
+$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY \
+           https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_XY/Final
+
+$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
+           https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XY/Final
+
+$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
+           https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XY/Final
+
+
+ +
+ + + + +
+ +

The LLVM demo page must be updated to use the new release. This consists of + using the new llvm-gcc binary and building LLVM.

+ +
+ + + + +
+ +

The website must be updated before the release announcement is sent out. Here + is what to do:

+ +
    +
  1. Check out the www module from Subversion.
  2. + +
  3. Create a new subdirectory X.Y in the releases directory.
  4. + +
  5. Commit the llvm, test-suite, llvm-gcc source, + clang source, clang binaries, and llvm-gcc + binaries in this new directory.
  6. + +
  7. Copy and commit the llvm/docs and LICENSE.txt files + into this new directory. The docs should be built with + BUILD_FOR_WEBSITE=1.
  8. + +
  9. Commit the index.html to the release/X.Y directory to + redirect (use from previous release.
  10. + +
  11. Update the releases/download.html file with the new release.
  12. + +
  13. Update the releases/index.html with the new release and link to + release documentation.
  14. + +
  15. Finally, update the main page (index.html and sidebar) to point + to the new release and release announcement. Make sure this all gets + committed back into Subversion.
  16. +
+ +
+ + + + +
+ +

Have Chris send out the release announcement when everything is finished.

+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + diff --git a/final/docs/HowToSubmitABug.html b/final/docs/HowToSubmitABug.html new file mode 100644 index 00000000000..90efbe321b1 --- /dev/null +++ b/final/docs/HowToSubmitABug.html @@ -0,0 +1,347 @@ + + + + How to submit an LLVM bug report + + + + +
+ How to submit an LLVM bug report +
+ + + + + + +
+
    +
  1. Introduction - Got bugs?
  2. +
  3. Crashing Bugs +
  4. +
  5. Miscompilations
  6. +
  7. Incorrect code generation (JIT and LLC)
  8. +
+
+

Written by Chris Lattner and + Misha Brukman

+
+
+ Debugging +
+ + + + + +
+ +

If you're working with LLVM and run into a bug, we definitely want to know +about it. This document describes what you can do to increase the odds of +getting it fixed quickly.

+ +

Basically you have to do two things at a minimum. First, decide whether the +bug crashes the compiler (or an LLVM pass), or if the +compiler is miscompiling the program (i.e., the +compiler successfully produces an executable, but it doesn't run right). Based +on +what type of bug it is, follow the instructions in the linked section to narrow +down the bug so that the person who fixes it will be able to find the problem +more easily.

+ +

Once you have a reduced test-case, go to the LLVM Bug Tracking +System and fill out the form with the necessary details (note that you don't +need to pick a category, just use the "new-bugs" category if you're not sure). +The bug description should contain the following +information:

+ +
    +
  • All information necessary to reproduce the problem.
  • +
  • The reduced test-case that triggers the bug.
  • +
  • The location where you obtained LLVM (if not from our Subversion + repository).
  • +
+ +

Thanks for helping us make LLVM better!

+ +
+ + + + + +
+ +

More often than not, bugs in the compiler cause it to crash—often due +to an assertion failure of some sort. The most important +piece of the puzzle is to figure out if it is crashing in the GCC front-end +or if it is one of the LLVM libraries (e.g. the optimizer or code generator) +that has problems.

+ +

To figure out which component is crashing (the front-end, +optimizer or code generator), run the +llvm-gcc command line as you were when the crash occurred, but +with the following extra command line options:

+ +
    +
  • -O0 -emit-llvm: If llvm-gcc still crashes when + passed these options (which disable the optimizer and code generator), then + the crash is in the front-end. Jump ahead to the section on front-end bugs.
  • + +
  • -emit-llvm: If llvm-gcc crashes with this option + (which disables the code generator), you found an optimizer bug. Jump ahead + to compile-time optimization bugs.
  • + +
  • Otherwise, you have a code generator crash. Jump ahead to code generator bugs.
  • + +
+ +
+ + + + +
+ +

If the problem is in the front-end, you should re-run the same +llvm-gcc command that resulted in the crash, but add the +-save-temps option. The compiler will crash again, but it will leave +behind a foo.i file (containing preprocessed C source code) and +possibly foo.s for each +compiled foo.c file. Send us the foo.i file, +along with the options you passed to llvm-gcc, and a brief description of the +error it caused.

+ +

The delta tool helps to reduce the +preprocessed file down to the smallest amount of code that still replicates the +problem. You're encouraged to use delta to reduce the code to make the +developers' lives easier. This website +has instructions on the best way to use delta.

+ +
+ + + + +
+ +

If you find that a bug crashes in the optimizer, compile your test-case to a +.bc file by passing "-emit-llvm -O0 -c -o foo.bc". +Then run:

+ +
+

opt -std-compile-opts -debug-pass=Arguments foo.bc + -disable-output

+
+ +

This command should do two things: it should print out a list of passes, and +then it should crash in the same was as llvm-gcc. If it doesn't crash, please +follow the instructions for a front-end bug.

+ +

If this does crash, then you should be able to debug this with the following +bugpoint command:

+ +
+

bugpoint foo.bc <list of passes printed by +opt>

+
+ +

Please run this, then file a bug with the instructions and reduced .bc files +that bugpoint emits. If something goes wrong with bugpoint, please submit the +"foo.bc" file and the list of passes printed by opt.

+ +
+ + + + +
+ +

If you find a bug that crashes llvm-gcc in the code generator, compile your +source file to a .bc file by passing "-emit-llvm -c -o foo.bc" +to llvm-gcc (in addition to the options you already pass). Once your have +foo.bc, one of the following commands should fail:

+ +
    +
  1. llc foo.bc
  2. +
  3. llc foo.bc -relocation-model=pic
  4. +
  5. llc foo.bc -relocation-model=static
  6. +
+ +

If none of these crash, please follow the instructions for a +front-end bug. If one of these do crash, you should +be able to reduce this with one of the following bugpoint command lines (use +the one corresponding to the command above that failed):

+ +
    +
  1. bugpoint -run-llc foo.bc
  2. +
  3. bugpoint -run-llc foo.bc --tool-args + -relocation-model=pic
  4. +
  5. bugpoint -run-llc foo.bc --tool-args + -relocation-model=static
  6. +
+ +

Please run this, then file a bug with the instructions and reduced .bc file +that bugpoint emits. If something goes wrong with bugpoint, please submit the +"foo.bc" file and the option that llc crashes with.

+ +
+ + + + + +
+ +

If llvm-gcc successfully produces an executable, but that executable doesn't +run right, this is either a bug in the code or a bug in the +compiler. The first thing to check is to make sure it is not using undefined +behavior (e.g. reading a variable before it is defined). In particular, check +to see if the program valgrinds clean, +passes purify, or some other memory checker tool. Many of the "LLVM bugs" that +we have chased down ended up being bugs in the program being compiled, not + LLVM.

+ +

Once you determine that the program itself is not buggy, you should choose +which code generator you wish to compile the program with (e.g. C backend, the +JIT, or LLC) and optionally a series of LLVM passes to run. For example:

+ +
+

+bugpoint -run-cbe [... optzn passes ...] file-to-test.bc --args -- [program arguments]

+
+ +

bugpoint will try to narrow down your list of passes to the one pass +that causes an error, and simplify the bitcode file as much as it can to assist +you. It will print a message letting you know how to reproduce the resulting +error.

+ +
+ + + + + +
+ +

Similarly to debugging incorrect compilation by mis-behaving passes, you can +debug incorrect code generation by either LLC or the JIT, using +bugpoint. The process bugpoint follows in this case is to try +to narrow the code down to a function that is miscompiled by one or the other +method, but since for correctness, the entire program must be run, +bugpoint will compile the code it deems to not be affected with the C +Backend, and then link in the shared object it generates.

+ +

To debug the JIT:

+ +
+
+bugpoint -run-jit -output=[correct output file] [bitcode file]  \
+         --tool-args -- [arguments to pass to lli]              \
+         --args -- [program arguments]
+
+
+ +

Similarly, to debug the LLC, one would run:

+ +
+
+bugpoint -run-llc -output=[correct output file] [bitcode file]  \
+         --tool-args -- [arguments to pass to llc]              \
+         --args -- [program arguments]
+
+
+ +

Special note: if you are debugging MultiSource or SPEC tests that +already exist in the llvm/test hierarchy, there is an easier way to +debug the JIT, LLC, and CBE, using the pre-written Makefile targets, which +will pass the program options specified in the Makefiles:

+ +
+

+cd llvm/test/../../program
+make bugpoint-jit +

+
+ +

At the end of a successful bugpoint run, you will be presented +with two bitcode files: a safe file which can be compiled with the C +backend and the test file which either LLC or the JIT +mis-codegenerates, and thus causes the error.

+ +

To reproduce the error that bugpoint found, it is sufficient to do +the following:

+ +
    + +
  1. Regenerate the shared object from the safe bitcode file:

    + +
    +

    +llc -march=c safe.bc -o safe.c
    +gcc -shared safe.c -o safe.so +

    +
  2. + +
  3. If debugging LLC, compile test bitcode native and link with the shared + object:

    + +
    +

    +llc test.bc -o test.s
    +gcc test.s safe.so -o test.llc
    +./test.llc [program options] +

    +
  4. + +
  5. If debugging the JIT, load the shared object and supply the test + bitcode:

    + +
    +

    lli -load=safe.so test.bc [program options]

    +
  6. + +
+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/LangRef.html b/final/docs/LangRef.html new file mode 100644 index 00000000000..893876620a4 --- /dev/null +++ b/final/docs/LangRef.html @@ -0,0 +1,7799 @@ + + + + LLVM Assembly Language Reference Manual + + + + + + + + +
LLVM Language Reference Manual
+
    +
  1. Abstract
  2. +
  3. Introduction
  4. +
  5. Identifiers
  6. +
  7. High Level Structure +
      +
    1. Module Structure
    2. +
    3. Linkage Types +
        +
      1. 'private' Linkage
      2. +
      3. 'linker_private' Linkage
      4. +
      5. 'linker_private_weak' Linkage
      6. +
      7. 'linker_private_weak_def_auto' Linkage
      8. +
      9. 'internal' Linkage
      10. +
      11. 'available_externally' Linkage
      12. +
      13. 'linkonce' Linkage
      14. +
      15. 'common' Linkage
      16. +
      17. 'weak' Linkage
      18. +
      19. 'appending' Linkage
      20. +
      21. 'extern_weak' Linkage
      22. +
      23. 'linkonce_odr' Linkage
      24. +
      25. 'weak_odr' Linkage
      26. +
      27. 'externally visible' Linkage
      28. +
      29. 'dllimport' Linkage
      30. +
      31. 'dllexport' Linkage
      32. +
      +
    4. +
    5. Calling Conventions
    6. +
    7. Named Types
    8. +
    9. Global Variables
    10. +
    11. Functions
    12. +
    13. Aliases
    14. +
    15. Named Metadata
    16. +
    17. Parameter Attributes
    18. +
    19. Function Attributes
    20. +
    21. Garbage Collector Names
    22. +
    23. Module-Level Inline Assembly
    24. +
    25. Data Layout
    26. +
    27. Pointer Aliasing Rules
    28. +
    29. Volatile Memory Accesses
    30. +
    +
  8. +
  9. Type System +
      +
    1. Type Classifications
    2. +
    3. Primitive Types +
        +
      1. Integer Type
      2. +
      3. Floating Point Types
      4. +
      5. X86mmx Type
      6. +
      7. Void Type
      8. +
      9. Label Type
      10. +
      11. Metadata Type
      12. +
      +
    4. +
    5. Derived Types +
        +
      1. Aggregate Types +
          +
        1. Array Type
        2. +
        3. Structure Type
        4. +
        5. Packed Structure Type
        6. +
        7. Vector Type
        8. +
        +
      2. +
      3. Function Type
      4. +
      5. Pointer Type
      6. +
      7. Opaque Type
      8. +
      +
    6. +
    7. Type Up-references
    8. +
    +
  10. +
  11. Constants +
      +
    1. Simple Constants
    2. +
    3. Complex Constants
    4. +
    5. Global Variable and Function Addresses
    6. +
    7. Undefined Values
    8. +
    9. Trap Values
    10. +
    11. Addresses of Basic Blocks
    12. +
    13. Constant Expressions
    14. +
    +
  12. +
  13. Other Values +
      +
    1. Inline Assembler Expressions
    2. +
    3. Metadata Nodes and Metadata Strings
    4. +
    +
  14. +
  15. Intrinsic Global Variables +
      +
    1. The 'llvm.used' Global Variable
    2. +
    3. The 'llvm.compiler.used' + Global Variable
    4. +
    5. The 'llvm.global_ctors' + Global Variable
    6. +
    7. The 'llvm.global_dtors' + Global Variable
    8. +
    +
  16. +
  17. Instruction Reference +
      +
    1. Terminator Instructions +
        +
      1. 'ret' Instruction
      2. +
      3. 'br' Instruction
      4. +
      5. 'switch' Instruction
      6. +
      7. 'indirectbr' Instruction
      8. +
      9. 'invoke' Instruction
      10. +
      11. 'unwind' Instruction
      12. +
      13. 'unreachable' Instruction
      14. +
      +
    2. +
    3. Binary Operations +
        +
      1. 'add' Instruction
      2. +
      3. 'fadd' Instruction
      4. +
      5. 'sub' Instruction
      6. +
      7. 'fsub' Instruction
      8. +
      9. 'mul' Instruction
      10. +
      11. 'fmul' Instruction
      12. +
      13. 'udiv' Instruction
      14. +
      15. 'sdiv' Instruction
      16. +
      17. 'fdiv' Instruction
      18. +
      19. 'urem' Instruction
      20. +
      21. 'srem' Instruction
      22. +
      23. 'frem' Instruction
      24. +
      +
    4. +
    5. Bitwise Binary Operations +
        +
      1. 'shl' Instruction
      2. +
      3. 'lshr' Instruction
      4. +
      5. 'ashr' Instruction
      6. +
      7. 'and' Instruction
      8. +
      9. 'or' Instruction
      10. +
      11. 'xor' Instruction
      12. +
      +
    6. +
    7. Vector Operations +
        +
      1. 'extractelement' Instruction
      2. +
      3. 'insertelement' Instruction
      4. +
      5. 'shufflevector' Instruction
      6. +
      +
    8. +
    9. Aggregate Operations +
        +
      1. 'extractvalue' Instruction
      2. +
      3. 'insertvalue' Instruction
      4. +
      +
    10. +
    11. Memory Access and Addressing Operations +
        +
      1. 'alloca' Instruction
      2. +
      3. 'load' Instruction
      4. +
      5. 'store' Instruction
      6. +
      7. 'getelementptr' Instruction
      8. +
      +
    12. +
    13. Conversion Operations +
        +
      1. 'trunc .. to' Instruction
      2. +
      3. 'zext .. to' Instruction
      4. +
      5. 'sext .. to' Instruction
      6. +
      7. 'fptrunc .. to' Instruction
      8. +
      9. 'fpext .. to' Instruction
      10. +
      11. 'fptoui .. to' Instruction
      12. +
      13. 'fptosi .. to' Instruction
      14. +
      15. 'uitofp .. to' Instruction
      16. +
      17. 'sitofp .. to' Instruction
      18. +
      19. 'ptrtoint .. to' Instruction
      20. +
      21. 'inttoptr .. to' Instruction
      22. +
      23. 'bitcast .. to' Instruction
      24. +
      +
    14. +
    15. Other Operations +
        +
      1. 'icmp' Instruction
      2. +
      3. 'fcmp' Instruction
      4. +
      5. 'phi' Instruction
      6. +
      7. 'select' Instruction
      8. +
      9. 'call' Instruction
      10. +
      11. 'va_arg' Instruction
      12. +
      +
    16. +
    +
  18. +
  19. Intrinsic Functions +
      +
    1. Variable Argument Handling Intrinsics +
        +
      1. 'llvm.va_start' Intrinsic
      2. +
      3. 'llvm.va_end' Intrinsic
      4. +
      5. 'llvm.va_copy' Intrinsic
      6. +
      +
    2. +
    3. Accurate Garbage Collection Intrinsics +
        +
      1. 'llvm.gcroot' Intrinsic
      2. +
      3. 'llvm.gcread' Intrinsic
      4. +
      5. 'llvm.gcwrite' Intrinsic
      6. +
      +
    4. +
    5. Code Generator Intrinsics +
        +
      1. 'llvm.returnaddress' Intrinsic
      2. +
      3. 'llvm.frameaddress' Intrinsic
      4. +
      5. 'llvm.stacksave' Intrinsic
      6. +
      7. 'llvm.stackrestore' Intrinsic
      8. +
      9. 'llvm.prefetch' Intrinsic
      10. +
      11. 'llvm.pcmarker' Intrinsic
      12. +
      13. 'llvm.readcyclecounter' Intrinsic
      14. +
      +
    6. +
    7. Standard C Library Intrinsics +
        +
      1. 'llvm.memcpy.*' Intrinsic
      2. +
      3. 'llvm.memmove.*' Intrinsic
      4. +
      5. 'llvm.memset.*' Intrinsic
      6. +
      7. 'llvm.sqrt.*' Intrinsic
      8. +
      9. 'llvm.powi.*' Intrinsic
      10. +
      11. 'llvm.sin.*' Intrinsic
      12. +
      13. 'llvm.cos.*' Intrinsic
      14. +
      15. 'llvm.pow.*' Intrinsic
      16. +
      +
    8. +
    9. Bit Manipulation Intrinsics +
        +
      1. 'llvm.bswap.*' Intrinsics
      2. +
      3. 'llvm.ctpop.*' Intrinsic
      4. +
      5. 'llvm.ctlz.*' Intrinsic
      6. +
      7. 'llvm.cttz.*' Intrinsic
      8. +
      +
    10. +
    11. Arithmetic with Overflow Intrinsics +
        +
      1. 'llvm.sadd.with.overflow.* Intrinsics
      2. +
      3. 'llvm.uadd.with.overflow.* Intrinsics
      4. +
      5. 'llvm.ssub.with.overflow.* Intrinsics
      6. +
      7. 'llvm.usub.with.overflow.* Intrinsics
      8. +
      9. 'llvm.smul.with.overflow.* Intrinsics
      10. +
      11. 'llvm.umul.with.overflow.* Intrinsics
      12. +
      +
    12. +
    13. Half Precision Floating Point Intrinsics +
        +
      1. 'llvm.convert.to.fp16' Intrinsic
      2. +
      3. 'llvm.convert.from.fp16' Intrinsic
      4. +
      +
    14. +
    15. Debugger intrinsics
    16. +
    17. Exception Handling intrinsics
    18. +
    19. Trampoline Intrinsic +
        +
      1. 'llvm.init.trampoline' Intrinsic
      2. +
      +
    20. +
    21. Atomic intrinsics +
        +
      1. llvm.memory_barrier
      2. +
      3. llvm.atomic.cmp.swap
      4. +
      5. llvm.atomic.swap
      6. +
      7. llvm.atomic.load.add
      8. +
      9. llvm.atomic.load.sub
      10. +
      11. llvm.atomic.load.and
      12. +
      13. llvm.atomic.load.nand
      14. +
      15. llvm.atomic.load.or
      16. +
      17. llvm.atomic.load.xor
      18. +
      19. llvm.atomic.load.max
      20. +
      21. llvm.atomic.load.min
      22. +
      23. llvm.atomic.load.umax
      24. +
      25. llvm.atomic.load.umin
      26. +
      +
    22. +
    23. Memory Use Markers +
        +
      1. llvm.lifetime.start
      2. +
      3. llvm.lifetime.end
      4. +
      5. llvm.invariant.start
      6. +
      7. llvm.invariant.end
      8. +
      +
    24. +
    25. General intrinsics +
        +
      1. + 'llvm.var.annotation' Intrinsic
      2. +
      3. + 'llvm.annotation.*' Intrinsic
      4. +
      5. + 'llvm.trap' Intrinsic
      6. +
      7. + 'llvm.stackprotector' Intrinsic
      8. +
      9. + 'llvm.objectsize' Intrinsic
      10. +
      +
    26. +
    +
  20. +
+ +
+

Written by Chris Lattner + and Vikram Adve

+
+ + + + + +
+ +

This document is a reference manual for the LLVM assembly language. LLVM is + a Static Single Assignment (SSA) based representation that provides type + safety, low-level operations, flexibility, and the capability of representing + 'all' high-level languages cleanly. It is the common code representation + used throughout all phases of the LLVM compilation strategy.

+ +
+ + + + + +
+ +

The LLVM code representation is designed to be used in three different forms: + as an in-memory compiler IR, as an on-disk bitcode representation (suitable + for fast loading by a Just-In-Time compiler), and as a human readable + assembly language representation. This allows LLVM to provide a powerful + intermediate representation for efficient compiler transformations and + analysis, while providing a natural means to debug and visualize the + transformations. The three different forms of LLVM are all equivalent. This + document describes the human readable representation and notation.

+ +

The LLVM representation aims to be light-weight and low-level while being + expressive, typed, and extensible at the same time. It aims to be a + "universal IR" of sorts, by being at a low enough level that high-level ideas + may be cleanly mapped to it (similar to how microprocessors are "universal + IR's", allowing many source languages to be mapped to them). By providing + type information, LLVM can be used as the target of optimizations: for + example, through pointer analysis, it can be proven that a C automatic + variable is never accessed outside of the current function, allowing it to + be promoted to a simple SSA value instead of a memory location.

+ +
+ + + + +
+ +

It is important to note that this document describes 'well formed' LLVM + assembly language. There is a difference between what the parser accepts and + what is considered 'well formed'. For example, the following instruction is + syntactically okay, but not well formed:

+ +
+%x = add i32 1, %x
+
+ +

because the definition of %x does not dominate all of its uses. The + LLVM infrastructure provides a verification pass that may be used to verify + that an LLVM module is well formed. This pass is automatically run by the + parser after parsing input assembly and by the optimizer before it outputs + bitcode. The violations pointed out by the verifier pass indicate bugs in + transformation passes or input to the parser.

+ +
+ + + + + + + +
+ +

LLVM identifiers come in two basic types: global and local. Global + identifiers (functions, global variables) begin with the '@' + character. Local identifiers (register names, types) begin with + the '%' character. Additionally, there are three different formats + for identifiers, for different purposes:

+ +
    +
  1. Named values are represented as a string of characters with their prefix. + For example, %foo, @DivisionByZero, + %a.really.long.identifier. The actual regular expression used is + '[%@][a-zA-Z$._][a-zA-Z$._0-9]*'. Identifiers which require + other characters in their names can be surrounded with quotes. Special + characters may be escaped using "\xx" where xx is the + ASCII code for the character in hexadecimal. In this way, any character + can be used in a name value, even quotes themselves.
  2. + +
  3. Unnamed values are represented as an unsigned numeric value with their + prefix. For example, %12, @2, %44.
  4. + +
  5. Constants, which are described in a section about + constants, below.
  6. +
+ +

LLVM requires that values start with a prefix for two reasons: Compilers + don't need to worry about name clashes with reserved words, and the set of + reserved words may be expanded in the future without penalty. Additionally, + unnamed identifiers allow a compiler to quickly come up with a temporary + variable without having to avoid symbol table conflicts.

+ +

Reserved words in LLVM are very similar to reserved words in other + languages. There are keywords for different opcodes + ('add', + 'bitcast', + 'ret', etc...), for primitive type names + ('void', + 'i32', etc...), and others. These + reserved words cannot conflict with variable names, because none of them + start with a prefix character ('%' or '@').

+ +

Here is an example of LLVM code to multiply the integer variable + '%X' by 8:

+ +

The easy way:

+ +
+%result = mul i32 %X, 8
+
+ +

After strength reduction:

+ +
+%result = shl i32 %X, i8 3
+
+ +

And the hard way:

+ +
+%0 = add i32 %X, %X           ; yields {i32}:%0
+%1 = add i32 %0, %0           ; yields {i32}:%1
+%result = add i32 %1, %1
+
+ +

This last way of multiplying %X by 8 illustrates several important + lexical features of LLVM:

+ +
    +
  1. Comments are delimited with a ';' and go until the end of + line.
  2. + +
  3. Unnamed temporaries are created when the result of a computation is not + assigned to a named value.
  4. + +
  5. Unnamed temporaries are numbered sequentially
  6. +
+ +

It also shows a convention that we follow in this document. When + demonstrating instructions, we will follow an instruction with a comment that + defines the type and name of value produced. Comments are shown in italic + text.

+ +
+ + + + + + + + +
+ +

LLVM programs are composed of "Module"s, each of which is a translation unit + of the input programs. Each module consists of functions, global variables, + and symbol table entries. Modules may be combined together with the LLVM + linker, which merges function (and global variable) definitions, resolves + forward declarations, and merges symbol table entries. Here is an example of + the "hello world" module:

+ +
+; Declare the string constant as a global constant. 
+@.LC0 = internal constant [13 x i8] c"hello world\0A\00"      ; [13 x i8]* 
+
+; External declaration of the puts function 
+declare i32 @puts(i8*)                                      ; i32 (i8*)*  
+
+; Definition of main function
+define i32 @main() {   ; i32()*  
+  ; Convert [13 x i8]* to i8  *... 
+  %cast210 = getelementptr [13 x i8]* @.LC0, i64 0, i64 0   ; i8* 
+
+  ; Call puts function to write out the string to stdout. 
+  call i32 @puts(i8* %cast210)           ; i32 
+  ret i32 0 
+}
+
+; Named metadata
+!1 = metadata !{i32 41}
+!foo = !{!1, null}
+
+ +

This example is made up of a global variable named + ".LC0", an external declaration of the "puts" function, + a function definition for + "main" and named metadata + "foo".

+ +

In general, a module is made up of a list of global values, where both + functions and global variables are global values. Global values are + represented by a pointer to a memory location (in this case, a pointer to an + array of char, and a pointer to a function), and have one of the + following linkage types.

+ +
+ + + + +
+ +

All Global Variables and Functions have one of the following types of + linkage:

+ +
+
private
+
Global values with "private" linkage are only directly accessible + by objects in the current module. In particular, linking code into a + module with an private global value may cause the private to be renamed as + necessary to avoid collisions. Because the symbol is private to the + module, all references can be updated. This doesn't show up in any symbol + table in the object file.
+ +
linker_private
+
Similar to private, but the symbol is passed through the + assembler and evaluated by the linker. Unlike normal strong symbols, they + are removed by the linker from the final linked image (executable or + dynamic library).
+ +
linker_private_weak
+
Similar to "linker_private", but the symbol is weak. Note that + linker_private_weak symbols are subject to coalescing by the + linker. The symbols are removed by the linker from the final linked image + (executable or dynamic library).
+ +
linker_private_weak_def_auto
+
Similar to "linker_private_weak", but it's known that the address + of the object is not taken. For instance, functions that had an inline + definition, but the compiler decided not to inline it. Note, + unlike linker_private and linker_private_weak, + linker_private_weak_def_auto may have only default + visibility. The symbols are removed by the linker from the final linked + image (executable or dynamic library).
+ +
internal
+
Similar to private, but the value shows as a local symbol + (STB_LOCAL in the case of ELF) in the object file. This + corresponds to the notion of the 'static' keyword in C.
+ +
available_externally
+
Globals with "available_externally" linkage are never emitted + into the object file corresponding to the LLVM module. They exist to + allow inlining and other optimizations to take place given knowledge of + the definition of the global, which is known to be somewhere outside the + module. Globals with available_externally linkage are allowed to + be discarded at will, and are otherwise the same as linkonce_odr. + This linkage type is only allowed on definitions, not declarations.
+ +
linkonce
+
Globals with "linkonce" linkage are merged with other globals of + the same name when linkage occurs. This can be used to implement + some forms of inline functions, templates, or other code which must be + generated in each translation unit that uses it, but where the body may + be overridden with a more definitive definition later. Unreferenced + linkonce globals are allowed to be discarded. Note that + linkonce linkage does not actually allow the optimizer to + inline the body of this function into callers because it doesn't know if + this definition of the function is the definitive definition within the + program or whether it will be overridden by a stronger definition. + To enable inlining and other optimizations, use "linkonce_odr" + linkage.
+ +
weak
+
"weak" linkage has the same merging semantics as + linkonce linkage, except that unreferenced globals with + weak linkage may not be discarded. This is used for globals that + are declared "weak" in C source code.
+ +
common
+
"common" linkage is most similar to "weak" linkage, but + they are used for tentative definitions in C, such as "int X;" at + global scope. + Symbols with "common" linkage are merged in the same way as + weak symbols, and they may not be deleted if unreferenced. + common symbols may not have an explicit section, + must have a zero initializer, and may not be marked 'constant'. Functions and aliases may not + have common linkage.
+ + +
appending
+
"appending" linkage may only be applied to global variables of + pointer to array type. When two global variables with appending linkage + are linked together, the two global arrays are appended together. This is + the LLVM, typesafe, equivalent of having the system linker append together + "sections" with identical names when .o files are linked.
+ +
extern_weak
+
The semantics of this linkage follow the ELF object file model: the symbol + is weak until linked, if not linked, the symbol becomes null instead of + being an undefined reference.
+ +
linkonce_odr
+
weak_odr
+
Some languages allow differing globals to be merged, such as two functions + with different semantics. Other languages, such as C++, ensure + that only equivalent globals are ever merged (the "one definition rule" + — "ODR"). Such languages can use the linkonce_odr + and weak_odr linkage types to indicate that the global will only + be merged with equivalent globals. These linkage types are otherwise the + same as their non-odr versions.
+ +
externally visible:
+
If none of the above identifiers are used, the global is externally + visible, meaning that it participates in linkage and can be used to + resolve external symbol references.
+
+ +

The next two types of linkage are targeted for Microsoft Windows platform + only. They are designed to support importing (exporting) symbols from (to) + DLLs (Dynamic Link Libraries).

+ +
+
dllimport
+
"dllimport" linkage causes the compiler to reference a function + or variable via a global pointer to a pointer that is set up by the DLL + exporting the symbol. On Microsoft Windows targets, the pointer name is + formed by combining __imp_ and the function or variable + name.
+ +
dllexport
+
"dllexport" linkage causes the compiler to provide a global + pointer to a pointer in a DLL, so that it can be referenced with the + dllimport attribute. On Microsoft Windows targets, the pointer + name is formed by combining __imp_ and the function or + variable name.
+
+ +

For example, since the ".LC0" variable is defined to be internal, if + another module defined a ".LC0" variable and was linked with this + one, one of the two would be renamed, preventing a collision. Since + "main" and "puts" are external (i.e., lacking any linkage + declarations), they are accessible outside of the current module.

+ +

It is illegal for a function declaration to have any linkage type + other than "externally visible", dllimport + or extern_weak.

+ +

Aliases can have only external, internal, weak + or weak_odr linkages.

+ +
+ + + + +
+ +

LLVM functions, calls + and invokes can all have an optional calling + convention specified for the call. The calling convention of any pair of + dynamic caller/callee must match, or the behavior of the program is + undefined. The following calling conventions are supported by LLVM, and more + may be added in the future:

+ +
+
"ccc" - The C calling convention:
+
This calling convention (the default if no other calling convention is + specified) matches the target C calling conventions. This calling + convention supports varargs function calls and tolerates some mismatch in + the declared prototype and implemented declaration of the function (as + does normal C).
+ +
"fastcc" - The fast calling convention:
+
This calling convention attempts to make calls as fast as possible + (e.g. by passing things in registers). This calling convention allows the + target to use whatever tricks it wants to produce fast code for the + target, without having to conform to an externally specified ABI + (Application Binary Interface). + Tail calls can only be optimized + when this or the GHC convention is used. This calling convention + does not support varargs and requires the prototype of all callees to + exactly match the prototype of the function definition.
+ +
"coldcc" - The cold calling convention:
+
This calling convention attempts to make code in the caller as efficient + as possible under the assumption that the call is not commonly executed. + As such, these calls often preserve all registers so that the call does + not break any live ranges in the caller side. This calling convention + does not support varargs and requires the prototype of all callees to + exactly match the prototype of the function definition.
+ +
"cc 10" - GHC convention:
+
This calling convention has been implemented specifically for use by the + Glasgow Haskell Compiler (GHC). + It passes everything in registers, going to extremes to achieve this by + disabling callee save registers. This calling convention should not be + used lightly but only for specific situations such as an alternative to + the register pinning performance technique often used when + implementing functional programming languages.At the moment only X86 + supports this convention and it has the following limitations: +
    +
  • On X86-32 only supports up to 4 bit type parameters. No + floating point types are supported.
  • +
  • On X86-64 only supports up to 10 bit type parameters and + 6 floating point parameters.
  • +
+ This calling convention supports + tail call optimization but + requires both the caller and callee are using it. +
+ +
"cc <n>" - Numbered convention:
+
Any calling convention may be specified by number, allowing + target-specific calling conventions to be used. Target specific calling + conventions start at 64.
+
+ +

More calling conventions can be added/defined on an as-needed basis, to + support Pascal conventions or any other well-known target-independent + convention.

+ +
+ + + + +
+ +

All Global Variables and Functions have one of the following visibility + styles:

+ +
+
"default" - Default style:
+
On targets that use the ELF object file format, default visibility means + that the declaration is visible to other modules and, in shared libraries, + means that the declared entity may be overridden. On Darwin, default + visibility means that the declaration is visible to other modules. Default + visibility corresponds to "external linkage" in the language.
+ +
"hidden" - Hidden style:
+
Two declarations of an object with hidden visibility refer to the same + object if they are in the same shared object. Usually, hidden visibility + indicates that the symbol will not be placed into the dynamic symbol + table, so no other module (executable or shared library) can reference it + directly.
+ +
"protected" - Protected style:
+
On ELF, protected visibility indicates that the symbol will be placed in + the dynamic symbol table, but that references within the defining module + will bind to the local symbol. That is, the symbol cannot be overridden by + another module.
+
+ +
+ + + + +
+ +

LLVM IR allows you to specify name aliases for certain types. This can make + it easier to read the IR and make the IR more condensed (particularly when + recursive types are involved). An example of a name specification is:

+ +
+%mytype = type { %mytype*, i32 }
+
+ +

You may give a name to any type except + "void". Type name aliases may be used anywhere a type + is expected with the syntax "%mytype".

+ +

Note that type names are aliases for the structural type that they indicate, + and that you can therefore specify multiple names for the same type. This + often leads to confusing behavior when dumping out a .ll file. Since LLVM IR + uses structural typing, the name is not part of the type. When printing out + LLVM IR, the printer will pick one name to render all types of a + particular shape. This means that if you have code where two different + source types end up having the same LLVM type, that the dumper will sometimes + print the "wrong" or unexpected type. This is an important design point and + isn't going to change.

+ +
+ + + + +
+ +

Global variables define regions of memory allocated at compilation time + instead of run-time. Global variables may optionally be initialized, may + have an explicit section to be placed in, and may have an optional explicit + alignment specified. A variable may be defined as "thread_local", which + means that it will not be shared by threads (each thread will have a + separated copy of the variable). A variable may be defined as a global + "constant," which indicates that the contents of the variable + will never be modified (enabling better optimization, allowing the + global data to be placed in the read-only section of an executable, etc). + Note that variables that need runtime initialization cannot be marked + "constant" as there is a store to the variable.

+ +

LLVM explicitly allows declarations of global variables to be marked + constant, even if the final definition of the global is not. This capability + can be used to enable slightly better optimization of the program, but + requires the language definition to guarantee that optimizations based on the + 'constantness' are valid for the translation units that do not include the + definition.

+ +

As SSA values, global variables define pointer values that are in scope + (i.e. they dominate) all basic blocks in the program. Global variables + always define a pointer to their "content" type because they describe a + region of memory, and all memory objects in LLVM are accessed through + pointers.

+ +

Global variables can be marked with unnamed_addr which indicates + that the address is not significant, only the content. Constants marked + like this can be merged with other constants if they have the same + initializer. Note that a constant with significant address can + be merged with a unnamed_addr constant, the result being a + constant whose address is significant.

+ +

A global variable may be declared to reside in a target-specific numbered + address space. For targets that support them, address spaces may affect how + optimizations are performed and/or what target instructions are used to + access the variable. The default address space is zero. The address space + qualifier must precede any other attributes.

+ +

LLVM allows an explicit section to be specified for globals. If the target + supports it, it will emit globals to the section specified.

+ +

An explicit alignment may be specified for a global, which must be a power + of 2. If not present, or if the alignment is set to zero, the alignment of + the global is set by the target to whatever it feels convenient. If an + explicit alignment is specified, the global is forced to have exactly that + alignment. Targets and optimizers are not allowed to over-align the global + if the global has an assigned section. In this case, the extra alignment + could be observable: for example, code could assume that the globals are + densely packed in their section and try to iterate over them as an array, + alignment padding would break this iteration.

+ +

For example, the following defines a global in a numbered address space with + an initializer, section, and alignment:

+ +
+@G = addrspace(5) constant float 1.0, section "foo", align 4
+
+ +
+ + + + + +
+ +

LLVM function definitions consist of the "define" keyword, an + optional linkage type, an optional + visibility style, an optional + calling convention, + an optional unnamed_addr attribute, a return type, an optional + parameter attribute for the return type, a function + name, a (possibly empty) argument list (each with optional + parameter attributes), optional + function attributes, an optional section, an optional + alignment, an optional garbage collector name, an opening + curly brace, a list of basic blocks, and a closing curly brace.

+ +

LLVM function declarations consist of the "declare" keyword, an + optional linkage type, an optional + visibility style, an optional + calling convention, + an optional unnamed_addr attribute, a return type, an optional + parameter attribute for the return type, a function + name, a possibly empty list of arguments, an optional alignment, and an + optional garbage collector name.

+ +

A function definition contains a list of basic blocks, forming the CFG + (Control Flow Graph) for the function. Each basic block may optionally start + with a label (giving the basic block a symbol table entry), contains a list + of instructions, and ends with a terminator + instruction (such as a branch or function return).

+ +

The first basic block in a function is special in two ways: it is immediately + executed on entrance to the function, and it is not allowed to have + predecessor basic blocks (i.e. there can not be any branches to the entry + block of a function). Because the block can have no predecessors, it also + cannot have any PHI nodes.

+ +

LLVM allows an explicit section to be specified for functions. If the target + supports it, it will emit functions to the section specified.

+ +

An explicit alignment may be specified for a function. If not present, or if + the alignment is set to zero, the alignment of the function is set by the + target to whatever it feels convenient. If an explicit alignment is + specified, the function is forced to have at least that much alignment. All + alignments must be a power of 2.

+ +

If the unnamed_addr attribute is given, the address is know to not + be significant and two identical functions can be merged

. + +
Syntax:
+
+define [linkage] [visibility]
+       [cconv] [ret attrs]
+       <ResultType> @<FunctionName> ([argument list])
+       [fn Attrs] [section "name"] [align N]
+       [gc] { ... }
+
+ +
+ + +
+ Aliases +
+ +
+ +

Aliases act as "second name" for the aliasee value (which can be either + function, global variable, another alias or bitcast of global value). Aliases + may have an optional linkage type, and an + optional visibility style.

+ +
Syntax:
+
+@<Name> = alias [Linkage] [Visibility] <AliaseeTy> @<Aliasee>
+
+ +
+ + + + +
+ +

Named metadata is a collection of metadata. Metadata + nodes (but not metadata strings) are the only valid operands for + a named metadata.

+ +
Syntax:
+
+; Some unnamed metadata nodes, which are referenced by the named metadata.
+!0 = metadata !{metadata !"zero"}
+!1 = metadata !{metadata !"one"}
+!2 = metadata !{metadata !"two"}
+; A named metadata.
+!name = !{!0, !1, !2}
+
+ +
+ + + + +
+ +

The return type and each parameter of a function type may have a set of + parameter attributes associated with them. Parameter attributes are + used to communicate additional information about the result or parameters of + a function. Parameter attributes are considered to be part of the function, + not of the function type, so functions with different parameter attributes + can have the same function type.

+ +

Parameter attributes are simple keywords that follow the type specified. If + multiple parameter attributes are needed, they are space separated. For + example:

+ +
+declare i32 @printf(i8* noalias nocapture, ...)
+declare i32 @atoi(i8 zeroext)
+declare signext i8 @returns_signed_char()
+
+ +

Note that any attributes for the function result (nounwind, + readonly) come immediately after the argument list.

+ +

Currently, only the following parameter attributes are defined:

+ +
+
zeroext
+
This indicates to the code generator that the parameter or return value + should be zero-extended to a 32-bit value by the caller (for a parameter) + or the callee (for a return value).
+ +
signext
+
This indicates to the code generator that the parameter or return value + should be sign-extended to a 32-bit value by the caller (for a parameter) + or the callee (for a return value).
+ +
inreg
+
This indicates that this parameter or return value should be treated in a + special target-dependent fashion during while emitting code for a function + call or return (usually, by putting it in a register as opposed to memory, + though some targets use it to distinguish between two different kinds of + registers). Use of this attribute is target-specific.
+ +
byval
+

This indicates that the pointer parameter should really be passed by + value to the function. The attribute implies that a hidden copy of the + pointee + is made between the caller and the callee, so the callee is unable to + modify the value in the callee. This attribute is only valid on LLVM + pointer arguments. It is generally used to pass structs and arrays by + value, but is also valid on pointers to scalars. The copy is considered + to belong to the caller not the callee (for example, + readonly functions should not write to + byval parameters). This is not a valid attribute for return + values.

+ +

The byval attribute also supports specifying an alignment with + the align attribute. It indicates the alignment of the stack slot to + form and the known alignment of the pointer specified to the call site. If + the alignment is not specified, then the code generator makes a + target-specific assumption.

+ +
sret
+
This indicates that the pointer parameter specifies the address of a + structure that is the return value of the function in the source program. + This pointer must be guaranteed by the caller to be valid: loads and + stores to the structure may be assumed by the callee to not to trap. This + may only be applied to the first parameter. This is not a valid attribute + for return values.
+ +
noalias
+
This indicates that pointer values + based on the argument or return + value do not alias pointer values which are not based on it, + ignoring certain "irrelevant" dependencies. + For a call to the parent function, dependencies between memory + references from before or after the call and from those during the call + are "irrelevant" to the noalias keyword for the arguments and + return value used in that call. + The caller shares the responsibility with the callee for ensuring that + these requirements are met. + For further details, please see the discussion of the NoAlias response in + alias analysis.
+
+ Note that this definition of noalias is intentionally + similar to the definition of restrict in C99 for function + arguments, though it is slightly weaker. +
+ For function return values, C99's restrict is not meaningful, + while LLVM's noalias is. +
+ +
nocapture
+
This indicates that the callee does not make any copies of the pointer + that outlive the callee itself. This is not a valid attribute for return + values.
+ +
nest
+
This indicates that the pointer parameter can be excised using the + trampoline intrinsics. This is not a valid + attribute for return values.
+
+ +
+ + + + +
+ +

Each function may specify a garbage collector name, which is simply a + string:

+ +
+define void @f() gc "name" { ... }
+
+ +

The compiler declares the supported values of name. Specifying a + collector which will cause the compiler to alter its output in order to + support the named garbage collection algorithm.

+ +
+ + + + +
+ +

Function attributes are set to communicate additional information about a + function. Function attributes are considered to be part of the function, not + of the function type, so functions with different parameter attributes can + have the same function type.

+ +

Function attributes are simple keywords that follow the type specified. If + multiple attributes are needed, they are space separated. For example:

+ +
+define void @f() noinline { ... }
+define void @f() alwaysinline { ... }
+define void @f() alwaysinline optsize { ... }
+define void @f() optsize { ... }
+
+ +
+
alignstack(<n>)
+
This attribute indicates that, when emitting the prologue and epilogue, + the backend should forcibly align the stack pointer. Specify the + desired alignment, which must be a power of two, in parentheses. + +
alwaysinline
+
This attribute indicates that the inliner should attempt to inline this + function into callers whenever possible, ignoring any active inlining size + threshold for this caller.
+ +
hotpatch
+
This attribute indicates that the function should be 'hotpatchable', + meaning the function can be patched and/or hooked even while it is + loaded into memory. On x86, the function prologue will be preceded + by six bytes of padding and will begin with a two-byte instruction. + Most of the functions in the Windows system DLLs in Windows XP SP2 or + higher were compiled in this fashion.
+ +
inlinehint
+
This attribute indicates that the source code contained a hint that inlining + this function is desirable (such as the "inline" keyword in C/C++). It + is just a hint; it imposes no requirements on the inliner.
+ +
naked
+
This attribute disables prologue / epilogue emission for the function. + This can have very system-specific consequences.
+ +
noimplicitfloat
+
This attributes disables implicit floating point instructions.
+ +
noinline
+
This attribute indicates that the inliner should never inline this + function in any situation. This attribute may not be used together with + the alwaysinline attribute.
+ +
noredzone
+
This attribute indicates that the code generator should not use a red + zone, even if the target-specific ABI normally permits it.
+ +
noreturn
+
This function attribute indicates that the function never returns + normally. This produces undefined behavior at runtime if the function + ever does dynamically return.
+ +
nounwind
+
This function attribute indicates that the function never returns with an + unwind or exceptional control flow. If the function does unwind, its + runtime behavior is undefined.
+ +
optsize
+
This attribute suggests that optimization passes and code generator passes + make choices that keep the code size of this function low, and otherwise + do optimizations specifically to reduce code size.
+ +
readnone
+
This attribute indicates that the function computes its result (or decides + to unwind an exception) based strictly on its arguments, without + dereferencing any pointer arguments or otherwise accessing any mutable + state (e.g. memory, control registers, etc) visible to caller functions. + It does not write through any pointer arguments + (including byval arguments) and never + changes any state visible to callers. This means that it cannot unwind + exceptions by calling the C++ exception throwing methods, but + could use the unwind instruction.
+ +
readonly
+
This attribute indicates that the function does not write through any + pointer arguments (including byval + arguments) or otherwise modify any state (e.g. memory, control registers, + etc) visible to caller functions. It may dereference pointer arguments + and read state that may be set in the caller. A readonly function always + returns the same value (or unwinds an exception identically) when called + with the same set of arguments and global state. It cannot unwind an + exception by calling the C++ exception throwing methods, but may + use the unwind instruction.
+ +
ssp
+
This attribute indicates that the function should emit a stack smashing + protector. It is in the form of a "canary"—a random value placed on + the stack before the local variables that's checked upon return from the + function to see if it has been overwritten. A heuristic is used to + determine if a function needs stack protectors or not.
+
+ If a function that has an ssp attribute is inlined into a + function that doesn't have an ssp attribute, then the resulting + function will have an ssp attribute.
+ +
sspreq
+
This attribute indicates that the function should always emit a + stack smashing protector. This overrides + the ssp function attribute.
+
+ If a function that has an sspreq attribute is inlined into a + function that doesn't have an sspreq attribute or which has + an ssp attribute, then the resulting function will have + an sspreq attribute.
+
+ +
+ + + + +
+ +

Modules may contain "module-level inline asm" blocks, which corresponds to + the GCC "file scope inline asm" blocks. These blocks are internally + concatenated by LLVM and treated as a single unit, but may be separated in + the .ll file if desired. The syntax is very simple:

+ +
+module asm "inline asm code goes here"
+module asm "more can go here"
+
+ +

The strings can contain any character by escaping non-printable characters. + The escape sequence used is simply "\xx" where "xx" is the two digit hex code + for the number.

+ +

The inline asm code is simply printed to the machine code .s file when + assembly code is generated.

+ +
+ + + + +
+ +

A module may specify a target specific data layout string that specifies how + data is to be laid out in memory. The syntax for the data layout is + simply:

+ +
+target datalayout = "layout specification"
+
+ +

The layout specification consists of a list of specifications + separated by the minus sign character ('-'). Each specification starts with + a letter and may include other information after the letter to define some + aspect of the data layout. The specifications accepted are as follows:

+ +
+
E
+
Specifies that the target lays out data in big-endian form. That is, the + bits with the most significance have the lowest address location.
+ +
e
+
Specifies that the target lays out data in little-endian form. That is, + the bits with the least significance have the lowest address + location.
+ +
p:size:abi:pref
+
This specifies the size of a pointer and its abi and + preferred alignments. All sizes are in bits. Specifying + the pref alignment is optional. If omitted, the + preceding : should be omitted too.
+ +
isize:abi:pref
+
This specifies the alignment for an integer type of a given bit + size. The value of size must be in the range [1,2^23).
+ +
vsize:abi:pref
+
This specifies the alignment for a vector type of a given bit + size.
+ +
fsize:abi:pref
+
This specifies the alignment for a floating point type of a given bit + size. Only values of size that are supported by the target + will work. 32 (float) and 64 (double) are supported on all targets; + 80 or 128 (different flavors of long double) are also supported on some + targets. + +
asize:abi:pref
+
This specifies the alignment for an aggregate type of a given bit + size.
+ +
ssize:abi:pref
+
This specifies the alignment for a stack object of a given bit + size.
+ +
nsize1:size2:size3...
+
This specifies a set of native integer widths for the target CPU + in bits. For example, it might contain "n32" for 32-bit PowerPC, + "n32:64" for PowerPC 64, or "n8:16:32:64" for X86-64. Elements of + this set are considered to support most general arithmetic + operations efficiently.
+
+ +

When constructing the data layout for a given target, LLVM starts with a + default set of specifications which are then (possibly) overridden by the + specifications in the datalayout keyword. The default specifications + are given in this list:

+ +
    +
  • E - big endian
  • +
  • p:64:64:64 - 64-bit pointers with 64-bit alignment
  • +
  • i1:8:8 - i1 is 8-bit (byte) aligned
  • +
  • i8:8:8 - i8 is 8-bit (byte) aligned
  • +
  • i16:16:16 - i16 is 16-bit aligned
  • +
  • i32:32:32 - i32 is 32-bit aligned
  • +
  • i64:32:64 - i64 has ABI alignment of 32-bits but preferred + alignment of 64-bits
  • +
  • f32:32:32 - float is 32-bit aligned
  • +
  • f64:64:64 - double is 64-bit aligned
  • +
  • v64:64:64 - 64-bit vector is 64-bit aligned
  • +
  • v128:128:128 - 128-bit vector is 128-bit aligned
  • +
  • a0:0:1 - aggregates are 8-bit aligned
  • +
  • s0:64:64 - stack objects are 64-bit aligned
  • +
+ +

When LLVM is determining the alignment for a given type, it uses the + following rules:

+ +
    +
  1. If the type sought is an exact match for one of the specifications, that + specification is used.
  2. + +
  3. If no match is found, and the type sought is an integer type, then the + smallest integer type that is larger than the bitwidth of the sought type + is used. If none of the specifications are larger than the bitwidth then + the the largest integer type is used. For example, given the default + specifications above, the i7 type will use the alignment of i8 (next + largest) while both i65 and i256 will use the alignment of i64 (largest + specified).
  4. + +
  5. If no match is found, and the type sought is a vector type, then the + largest vector type that is smaller than the sought vector type will be + used as a fall back. This happens because <128 x double> can be + implemented in terms of 64 <2 x double>, for example.
  6. +
+ +
+ + + + +
+ +

Any memory access must be done through a pointer value associated +with an address range of the memory access, otherwise the behavior +is undefined. Pointer values are associated with address ranges +according to the following rules:

+ +
    +
  • A pointer value is associated with the addresses associated with + any value it is based on. +
  • An address of a global variable is associated with the address + range of the variable's storage.
  • +
  • The result value of an allocation instruction is associated with + the address range of the allocated storage.
  • +
  • A null pointer in the default address-space is associated with + no address.
  • +
  • An integer constant other than zero or a pointer value returned + from a function not defined within LLVM may be associated with address + ranges allocated through mechanisms other than those provided by + LLVM. Such ranges shall not overlap with any ranges of addresses + allocated by mechanisms provided by LLVM.
  • +
+ +

A pointer value is based on another pointer value according + to the following rules:

+ +
    +
  • A pointer value formed from a + getelementptr operation + is based on the first operand of the getelementptr.
  • +
  • The result value of a + bitcast is based on the operand + of the bitcast.
  • +
  • A pointer value formed by an + inttoptr is based on all + pointer values that contribute (directly or indirectly) to the + computation of the pointer's value.
  • +
  • The "based on" relationship is transitive.
  • +
+ +

Note that this definition of "based" is intentionally + similar to the definition of "based" in C99, though it is + slightly weaker.

+ +

LLVM IR does not associate types with memory. The result type of a +load merely indicates the size and +alignment of the memory from which to load, as well as the +interpretation of the value. The first operand type of a +store similarly only indicates the size +and alignment of the store.

+ +

Consequently, type-based alias analysis, aka TBAA, aka +-fstrict-aliasing, is not applicable to general unadorned +LLVM IR. Metadata may be used to encode +additional information which specialized optimization passes may use +to implement type-based alias analysis.

+ +
+ + + + +
+ +

Certain memory accesses, such as loads, stores, and llvm.memcpys may be marked volatile. +The optimizers must not change the number of volatile operations or change their +order of execution relative to other volatile operations. The optimizers +may change the order of volatile operations relative to non-volatile +operations. This is not Java's "volatile" and has no cross-thread +synchronization behavior.

+ +
+ + + + + +
+ +

The LLVM type system is one of the most important features of the + intermediate representation. Being typed enables a number of optimizations + to be performed on the intermediate representation directly, without having + to do extra analyses on the side before the transformation. A strong type + system makes it easier to read the generated code and enables novel analyses + and transformations that are not feasible to perform on normal three address + code representations.

+ +
+ + + + +
+ +

The types fall into a few useful classifications:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ClassificationTypes
integeri1, i2, i3, ... i8, ... i16, ... i32, ... i64, ...
floating pointfloat, double, x86_fp80, fp128, ppc_fp128
first classinteger, + floating point, + pointer, + vector, + structure, + array, + label, + metadata. +
primitivelabel, + void, + integer, + floating point, + x86mmx, + metadata.
derivedarray, + function, + pointer, + structure, + packed structure, + vector, + opaque. +
+ +

The first class types are perhaps the most + important. Values of these types are the only ones which can be produced by + instructions.

+ +
+ + + + +
+ +

The primitive types are the fundamental building blocks of the LLVM + system.

+ +
+ + + + +
+ +
Overview:
+

The integer type is a very simple type that simply specifies an arbitrary + bit width for the integer type desired. Any bit width from 1 bit to + 223-1 (about 8 million) can be specified.

+ +
Syntax:
+
+  iN
+
+ +

The number of bits the integer will occupy is specified by the N + value.

+ +
Examples:
+ + + + + + + + + + + + + +
i1a single-bit integer.
i32a 32-bit integer.
i1942652a really big integer of over 1 million bits.
+ +
+ + + + +
+ + + + + + + + + + +
TypeDescription
float32-bit floating point value
double64-bit floating point value
fp128128-bit floating point value (112-bit mantissa)
x86_fp8080-bit floating point value (X87)
ppc_fp128128-bit floating point value (two 64-bits)
+ +
+ + + + +
+ +
Overview:
+

The x86mmx type represents a value held in an MMX register on an x86 machine. The operations allowed on it are quite limited: parameters and return values, load and store, and bitcast. User-specified MMX instructions are represented as intrinsic or asm calls with arguments and/or results of this type. There are no arrays, vectors or constants of this type.

+ +
Syntax:
+
+  x86mmx
+
+ +
+ + + + +
+ +
Overview:
+

The void type does not represent any value and has no size.

+ +
Syntax:
+
+  void
+
+ +
+ + + + +
+ +
Overview:
+

The label type represents code labels.

+ +
Syntax:
+
+  label
+
+ +
+ + + + +
+ +
Overview:
+

The metadata type represents embedded metadata. No derived types may be + created from metadata except for function + arguments. + +

Syntax:
+
+  metadata
+
+ +
+ + + + + +
+ +

The real power in LLVM comes from the derived types in the system. This is + what allows a programmer to represent arrays, functions, pointers, and other + useful types. Each of these types contain one or more element types which + may be a primitive type, or another derived type. For example, it is + possible to have a two dimensional array, using an array as the element type + of another array.

+ + +
+ + + + +
+ +

Aggregate Types are a subset of derived types that can contain multiple + member types. Arrays, + structs, and vectors are + aggregate types.

+ +
+ + + + +
+ +
Overview:
+

The array type is a very simple derived type that arranges elements + sequentially in memory. The array type requires a size (number of elements) + and an underlying data type.

+ +
Syntax:
+
+  [<# elements> x <elementtype>]
+
+ +

The number of elements is a constant integer value; elementtype may + be any type with a size.

+ +
Examples:
+ + + + + + + + + + + + + +
[40 x i32]Array of 40 32-bit integer values.
[41 x i32]Array of 41 32-bit integer values.
[4 x i8]Array of 4 8-bit integer values.
+

Here are some examples of multidimensional arrays:

+ + + + + + + + + + + + + +
[3 x [4 x i32]]3x4 array of 32-bit integer values.
[12 x [10 x float]]12x10 array of single precision floating point values.
[2 x [3 x [4 x i16]]]2x3x4 array of 16-bit integer values.
+ +

There is no restriction on indexing beyond the end of the array implied by + a static type (though there are restrictions on indexing beyond the bounds + of an allocated object in some cases). This means that single-dimension + 'variable sized array' addressing can be implemented in LLVM with a zero + length array type. An implementation of 'pascal style arrays' in LLVM could + use the type "{ i32, [0 x float]}", for example.

+ +
+ + + + +
+ +
Overview:
+

The function type can be thought of as a function signature. It consists of + a return type and a list of formal parameter types. The return type of a + function type is a first class type or a void type.

+ +
Syntax:
+
+  <returntype> (<parameter list>)
+
+ +

...where '<parameter list>' is a comma-separated list of type + specifiers. Optionally, the parameter list may include a type ..., + which indicates that the function takes a variable number of arguments. + Variable argument functions can access their arguments with + the variable argument handling intrinsic + functions. '<returntype>' is any type except + label.

+ +
Examples:
+ + + + + + + + + + + + + + +
i32 (i32)function taking an i32, returning an i32 +
float (i16, i32 *) * + Pointer to a function that takes + an i16 and a pointer to i32, + returning float. +
i32 (i8*, ...)A vararg function that takes at least one + pointer to i8 (char in C), + which returns an integer. This is the signature for printf in + LLVM. +
{i32, i32} (i32)A function taking an i32, returning a + structure containing two i32 values +
+ +
+ + + + +
+ +
Overview:
+

The structure type is used to represent a collection of data members together + in memory. The packing of the field types is defined to match the ABI of the + underlying processor. The elements of a structure may be any type that has a + size.

+ +

Structures in memory are accessed using 'load' + and 'store' by getting a pointer to a field + with the 'getelementptr' instruction. + Structures in registers are accessed using the + 'extractvalue' and + 'insertvalue' instructions.

+
Syntax:
+
+  { <type list> }
+
+ +
Examples:
+ + + + + + + + +
{ i32, i32, i32 }A triple of three i32 values
{ float, i32 (i32) * }A pair, where the first element is a float and the + second element is a pointer to a + function that takes an i32, returning + an i32.
+ +
+ + + + +
+ +
Overview:
+

The packed structure type is used to represent a collection of data members + together in memory. There is no padding between fields. Further, the + alignment of a packed structure is 1 byte. The elements of a packed + structure may be any type that has a size.

+ +

Structures are accessed using 'load and + 'store' by getting a pointer to a field with + the 'getelementptr' instruction.

+ +
Syntax:
+
+  < { <type list> } >
+
+ +
Examples:
+ + + + + + + + +
< { i32, i32, i32 } >A triple of three i32 values
+< { float, i32 (i32)* } >A pair, where the first element is a float and the + second element is a pointer to a + function that takes an i32, returning + an i32.
+ +
+ + + + +
+ +
Overview:
+

The pointer type is used to specify memory locations. + Pointers are commonly used to reference objects in memory.

+ +

Pointer types may have an optional address space attribute defining the + numbered address space where the pointed-to object resides. The default + address space is number zero. The semantics of non-zero address + spaces are target-specific.

+ +

Note that LLVM does not permit pointers to void (void*) nor does it + permit pointers to labels (label*). Use i8* instead.

+ +
Syntax:
+
+  <type> *
+
+ +
Examples:
+ + + + + + + + + + + + + +
[4 x i32]*A pointer to array of four i32 values.
i32 (i32*) * A pointer to a function that takes an i32*, returning an + i32.
i32 addrspace(5)*A pointer to an i32 value + that resides in address space #5.
+ +
+ + + + +
+ +
Overview:
+

A vector type is a simple derived type that represents a vector of elements. + Vector types are used when multiple primitive data are operated in parallel + using a single instruction (SIMD). A vector type requires a size (number of + elements) and an underlying primitive data type. Vector types are considered + first class.

+ +
Syntax:
+
+  < <# elements> x <elementtype> >
+
+ +

The number of elements is a constant integer value larger than 0; elementtype + may be any integer or floating point type. Vectors of size zero are not + allowed, and pointers are not allowed as the element type.

+ +
Examples:
+ + + + + + + + + + + + + +
<4 x i32>Vector of 4 32-bit integer values.
<8 x float>Vector of 8 32-bit floating-point values.
<2 x i64>Vector of 2 64-bit integer values.
+ +
+ + + +
+ +
Overview:
+

Opaque types are used to represent unknown types in the system. This + corresponds (for example) to the C notion of a forward declared structure + type. In LLVM, opaque types can eventually be resolved to any type (not just + a structure type).

+ +
Syntax:
+
+  opaque
+
+ +
Examples:
+ + + + + +
opaqueAn opaque type.
+ +
+ + + + +
+ +
Overview:
+

An "up reference" allows you to refer to a lexically enclosing type without + requiring it to have a name. For instance, a structure declaration may + contain a pointer to any of the types it is lexically a member of. Example + of up references (with their equivalent as named type declarations) + include:

+ +
+   { \2 * }                %x = type { %x* }
+   { \2 }*                 %y = type { %y }*
+   \1*                     %z = type %z*
+
+ +

An up reference is needed by the asmprinter for printing out cyclic types + when there is no declared name for a type in the cycle. Because the + asmprinter does not want to print out an infinite type string, it needs a + syntax to handle recursive types that have no names (all names are optional + in llvm IR).

+ +
Syntax:
+
+   \<level>
+
+ +

The level is the count of the lexical type that is being referred to.

+ +
Examples:
+ + + + + + + + + +
\1*Self-referential pointer.
{ { \3*, i8 }, i32 }Recursive structure where the upref refers to the out-most + structure.
+ +
+ + + + + +
+ +

LLVM has several different basic types of constants. This section describes + them all and their syntax.

+ +
+ + + + +
+ +
+
Boolean constants
+
The two strings 'true' and 'false' are both valid + constants of the i1 type.
+ +
Integer constants
+
Standard integers (such as '4') are constants of + the integer type. Negative numbers may be used + with integer types.
+ +
Floating point constants
+
Floating point constants use standard decimal notation (e.g. 123.421), + exponential notation (e.g. 1.23421e+2), or a more precise hexadecimal + notation (see below). The assembler requires the exact decimal value of a + floating-point constant. For example, the assembler accepts 1.25 but + rejects 1.3 because 1.3 is a repeating decimal in binary. Floating point + constants must have a floating point type.
+ +
Null pointer constants
+
The identifier 'null' is recognized as a null pointer constant + and must be of pointer type.
+
+ +

The one non-intuitive notation for constants is the hexadecimal form of + floating point constants. For example, the form 'double + 0x432ff973cafa8000' is equivalent to (but harder to read than) + 'double 4.5e+15'. The only time hexadecimal floating point + constants are required (and the only time that they are generated by the + disassembler) is when a floating point constant must be emitted but it cannot + be represented as a decimal floating point number in a reasonable number of + digits. For example, NaN's, infinities, and other special values are + represented in their IEEE hexadecimal format so that assembly and disassembly + do not cause any bits to change in the constants.

+ +

When using the hexadecimal form, constants of types float and double are + represented using the 16-digit form shown above (which matches the IEEE754 + representation for double); float values must, however, be exactly + representable as IEE754 single precision. Hexadecimal format is always used + for long double, and there are three forms of long double. The 80-bit format + used by x86 is represented as 0xK followed by 20 hexadecimal digits. + The 128-bit format used by PowerPC (two adjacent doubles) is represented + by 0xM followed by 32 hexadecimal digits. The IEEE 128-bit format + is represented by 0xL followed by 32 hexadecimal digits; no + currently supported target uses this format. Long doubles will only work if + they match the long double format on your target. All hexadecimal formats + are big-endian (sign bit at the left).

+ +

There are no constants of type x86mmx.

+
+ + + + +
+ +

Complex constants are a (potentially recursive) combination of simple + constants and smaller complex constants.

+ +
+
Structure constants
+
Structure constants are represented with notation similar to structure + type definitions (a comma separated list of elements, surrounded by braces + ({})). For example: "{ i32 4, float 17.0, i32* @G }", + where "@G" is declared as "@G = external global i32". + Structure constants must have structure type, and + the number and types of elements must match those specified by the + type.
+ +
Array constants
+
Array constants are represented with notation similar to array type + definitions (a comma separated list of elements, surrounded by square + brackets ([])). For example: "[ i32 42, i32 11, i32 74 + ]". Array constants must have array type, and + the number and types of elements must match those specified by the + type.
+ +
Vector constants
+
Vector constants are represented with notation similar to vector type + definitions (a comma separated list of elements, surrounded by + less-than/greater-than's (<>)). For example: "< i32 + 42, i32 11, i32 74, i32 100 >". Vector constants must + have vector type, and the number and types of + elements must match those specified by the type.
+ +
Zero initialization
+
The string 'zeroinitializer' can be used to zero initialize a + value to zero of any type, including scalar and + aggregate types. + This is often used to avoid having to print large zero initializers + (e.g. for large arrays) and is always exactly equivalent to using explicit + zero initializers.
+ +
Metadata node
+
A metadata node is a structure-like constant with + metadata type. For example: "metadata !{ + i32 0, metadata !"test" }". Unlike other constants that are meant to + be interpreted as part of the instruction stream, metadata is a place to + attach additional information such as debug info.
+
+ +
+ + + + +
+ +

The addresses of global variables + and functions are always implicitly valid + (link-time) constants. These constants are explicitly referenced when + the identifier for the global is used and always + have pointer type. For example, the following is a + legal LLVM file:

+ +
+@X = global i32 17
+@Y = global i32 42
+@Z = global [2 x i32*] [ i32* @X, i32* @Y ]
+
+ +
+ + + +
+ +

The string 'undef' can be used anywhere a constant is expected, and + indicates that the user of the value may receive an unspecified bit-pattern. + Undefined values may be of any type (other than 'label' + or 'void') and be used anywhere a constant is permitted.

+ +

Undefined values are useful because they indicate to the compiler that the + program is well defined no matter what value is used. This gives the + compiler more freedom to optimize. Here are some examples of (potentially + surprising) transformations that are valid (in pseudo IR):

+ + +
+  %A = add %X, undef
+  %B = sub %X, undef
+  %C = xor %X, undef
+Safe:
+  %A = undef
+  %B = undef
+  %C = undef
+
+ +

This is safe because all of the output bits are affected by the undef bits. + Any output bit can have a zero or one depending on the input bits.

+ +
+  %A = or %X, undef
+  %B = and %X, undef
+Safe:
+  %A = -1
+  %B = 0
+Unsafe:
+  %A = undef
+  %B = undef
+
+ +

These logical operations have bits that are not always affected by the input. + For example, if %X has a zero bit, then the output of the + 'and' operation will always be a zero for that bit, no matter what + the corresponding bit from the 'undef' is. As such, it is unsafe to + optimize or assume that the result of the 'and' is 'undef'. + However, it is safe to assume that all bits of the 'undef' could be + 0, and optimize the 'and' to 0. Likewise, it is safe to assume that + all the bits of the 'undef' operand to the 'or' could be + set, allowing the 'or' to be folded to -1.

+ +
+  %A = select undef, %X, %Y
+  %B = select undef, 42, %Y
+  %C = select %X, %Y, undef
+Safe:
+  %A = %X     (or %Y)
+  %B = 42     (or %Y)
+  %C = %Y
+Unsafe:
+  %A = undef
+  %B = undef
+  %C = undef
+
+ +

This set of examples shows that undefined 'select' (and conditional + branch) conditions can go either way, but they have to come from one + of the two operands. In the %A example, if %X and + %Y were both known to have a clear low bit, then %A would + have to have a cleared low bit. However, in the %C example, the + optimizer is allowed to assume that the 'undef' operand could be the + same as %Y, allowing the whole 'select' to be + eliminated.

+ +
+  %A = xor undef, undef
+
+  %B = undef
+  %C = xor %B, %B
+
+  %D = undef
+  %E = icmp lt %D, 4
+  %F = icmp gte %D, 4
+
+Safe:
+  %A = undef
+  %B = undef
+  %C = undef
+  %D = undef
+  %E = undef
+  %F = undef
+
+ +

This example points out that two 'undef' operands are not + necessarily the same. This can be surprising to people (and also matches C + semantics) where they assume that "X^X" is always zero, even + if X is undefined. This isn't true for a number of reasons, but the + short answer is that an 'undef' "variable" can arbitrarily change + its value over its "live range". This is true because the variable doesn't + actually have a live range. Instead, the value is logically read + from arbitrary registers that happen to be around when needed, so the value + is not necessarily consistent over time. In fact, %A and %C + need to have the same semantics or the core LLVM "replace all uses with" + concept would not hold.

+ +
+  %A = fdiv undef, %X
+  %B = fdiv %X, undef
+Safe:
+  %A = undef
+b: unreachable
+
+ +

These examples show the crucial difference between an undefined + value and undefined behavior. An undefined value (like + 'undef') is allowed to have an arbitrary bit-pattern. This means that + the %A operation can be constant folded to 'undef', because + the 'undef' could be an SNaN, and fdiv is not (currently) + defined on SNaN's. However, in the second example, we can make a more + aggressive assumption: because the undef is allowed to be an + arbitrary value, we are allowed to assume that it could be zero. Since a + divide by zero has undefined behavior, we are allowed to assume that + the operation does not execute at all. This allows us to delete the divide and + all code after it. Because the undefined operation "can't happen", the + optimizer can assume that it occurs in dead code.

+ +
+a:  store undef -> %X
+b:  store %X -> undef
+Safe:
+a: <deleted>
+b: unreachable
+
+ +

These examples reiterate the fdiv example: a store of an + undefined value can be assumed to not have any effect; we can assume that the + value is overwritten with bits that happen to match what was already there. + However, a store to an undefined location could clobber arbitrary + memory, therefore, it has undefined behavior.

+ +
+ + + +
+ +

Trap values are similar to undef values, however + instead of representing an unspecified bit pattern, they represent the + fact that an instruction or constant expression which cannot evoke side + effects has nevertheless detected a condition which results in undefined + behavior.

+ +

There is currently no way of representing a trap value in the IR; they + only exist when produced by operations such as + add with the nsw flag.

+ +

Trap value behavior is defined in terms of value dependence:

+ +
    +
  • Values other than phi nodes depend on + their operands.
  • + +
  • Phi nodes depend on the operand corresponding + to their dynamic predecessor basic block.
  • + +
  • Function arguments depend on the corresponding actual argument values in + the dynamic callers of their functions.
  • + +
  • Call instructions depend on the + ret instructions that dynamically transfer + control back to them.
  • + +
  • Invoke instructions depend on the + ret, unwind, + or exception-throwing call instructions that dynamically transfer control + back to them.
  • + +
  • Non-volatile loads and stores depend on the most recent stores to all of the + referenced memory addresses, following the order in the IR + (including loads and stores implied by intrinsics such as + @llvm.memcpy.)
  • + + + + + +
  • An instruction with externally visible side effects depends on the most + recent preceding instruction with externally visible side effects, following + the order in the IR. (This includes + volatile operations.)
  • + +
  • An instruction control-depends on a + terminator instruction + if the terminator instruction has multiple successors and the instruction + is always executed when control transfers to one of the successors, and + may not be executed when control is transfered to another.
  • + +
  • Dependence is transitive.
  • + +
+ +

Whenever a trap value is generated, all values which depend on it evaluate + to trap. If they have side effects, the evoke their side effects as if each + operand with a trap value were undef. If they have externally-visible side + effects, the behavior is undefined.

+ +

Here are some examples:

+ +
+entry:
+  %trap = sub nuw i32 0, 1           ; Results in a trap value.
+  %still_trap = and i32 %trap, 0     ; Whereas (and i32 undef, 0) would return 0.
+  %trap_yet_again = getelementptr i32* @h, i32 %still_trap
+  store i32 0, i32* %trap_yet_again  ; undefined behavior
+
+  store i32 %trap, i32* @g           ; Trap value conceptually stored to memory.
+  %trap2 = load i32* @g              ; Returns a trap value, not just undef.
+
+  volatile store i32 %trap, i32* @g  ; External observation; undefined behavior.
+
+  %narrowaddr = bitcast i32* @g to i16*
+  %wideaddr = bitcast i32* @g to i64*
+  %trap3 = load 16* %narrowaddr      ; Returns a trap value.
+  %trap4 = load i64* %widaddr        ; Returns a trap value.
+
+  %cmp = icmp i32 slt %trap, 0       ; Returns a trap value.
+  %br i1 %cmp, %true, %end           ; Branch to either destination.
+
+true:
+  volatile store i32 0, i32* @g      ; This is control-dependent on %cmp, so
+                                     ; it has undefined behavior.
+  br label %end
+
+end:
+  %p = phi i32 [ 0, %entry ], [ 1, %true ]
+                                     ; Both edges into this PHI are
+                                     ; control-dependent on %cmp, so this
+                                     ; always results in a trap value.
+
+  volatile store i32 0, i32* @g      ; %end is control-equivalent to %entry
+                                     ; so this is defined (ignoring earlier
+                                     ; undefined behavior in this example).
+
+ +
+ + + +
+ +

blockaddress(@function, %block)

+ +

The 'blockaddress' constant computes the address of the specified + basic block in the specified function, and always has an i8* type. Taking + the address of the entry block is illegal.

+ +

This value only has defined behavior when used as an operand to the + 'indirectbr' instruction, or for + comparisons against null. Pointer equality tests between labels addresses + results in undefined behavior — though, again, comparison against null + is ok, and no label is equal to the null pointer. This may be passed around + as an opaque pointer sized value as long as the bits are not inspected. This + allows ptrtoint and arithmetic to be performed on these values so + long as the original value is reconstituted before the indirectbr + instruction.

+ +

Finally, some targets may provide defined semantics when using the value as + the operand to an inline assembly, but that is target specific.

+ +
+ + + + + +
+ +

Constant expressions are used to allow expressions involving other constants + to be used as constants. Constant expressions may be of + any first class type and may involve any LLVM + operation that does not have side effects (e.g. load and call are not + supported). The following is the syntax for constant expressions:

+ +
+
trunc (CST to TYPE)
+
Truncate a constant to another type. The bit size of CST must be larger + than the bit size of TYPE. Both types must be integers.
+ +
zext (CST to TYPE)
+
Zero extend a constant to another type. The bit size of CST must be + smaller than the bit size of TYPE. Both types must be integers.
+ +
sext (CST to TYPE)
+
Sign extend a constant to another type. The bit size of CST must be + smaller than the bit size of TYPE. Both types must be integers.
+ +
fptrunc (CST to TYPE)
+
Truncate a floating point constant to another floating point type. The + size of CST must be larger than the size of TYPE. Both types must be + floating point.
+ +
fpext (CST to TYPE)
+
Floating point extend a constant to another type. The size of CST must be + smaller or equal to the size of TYPE. Both types must be floating + point.
+ +
fptoui (CST to TYPE)
+
Convert a floating point constant to the corresponding unsigned integer + constant. TYPE must be a scalar or vector integer type. CST must be of + scalar or vector floating point type. Both CST and TYPE must be scalars, + or vectors of the same number of elements. If the value won't fit in the + integer type, the results are undefined.
+ +
fptosi (CST to TYPE)
+
Convert a floating point constant to the corresponding signed integer + constant. TYPE must be a scalar or vector integer type. CST must be of + scalar or vector floating point type. Both CST and TYPE must be scalars, + or vectors of the same number of elements. If the value won't fit in the + integer type, the results are undefined.
+ +
uitofp (CST to TYPE)
+
Convert an unsigned integer constant to the corresponding floating point + constant. TYPE must be a scalar or vector floating point type. CST must be + of scalar or vector integer type. Both CST and TYPE must be scalars, or + vectors of the same number of elements. If the value won't fit in the + floating point type, the results are undefined.
+ +
sitofp (CST to TYPE)
+
Convert a signed integer constant to the corresponding floating point + constant. TYPE must be a scalar or vector floating point type. CST must be + of scalar or vector integer type. Both CST and TYPE must be scalars, or + vectors of the same number of elements. If the value won't fit in the + floating point type, the results are undefined.
+ +
ptrtoint (CST to TYPE)
+
Convert a pointer typed constant to the corresponding integer constant + TYPE must be an integer type. CST must be of pointer + type. The CST value is zero extended, truncated, or unchanged to + make it fit in TYPE.
+ +
inttoptr (CST to TYPE)
+
Convert a integer constant to a pointer constant. TYPE must be a pointer + type. CST must be of integer type. The CST value is zero extended, + truncated, or unchanged to make it fit in a pointer size. This one is + really dangerous!
+ +
bitcast (CST to TYPE)
+
Convert a constant, CST, to another TYPE. The constraints of the operands + are the same as those for the bitcast + instruction.
+ +
getelementptr (CSTPTR, IDX0, IDX1, ...)
+
getelementptr inbounds (CSTPTR, IDX0, IDX1, ...)
+
Perform the getelementptr operation on + constants. As with the getelementptr + instruction, the index list may have zero or more indexes, which are + required to make sense for the type of "CSTPTR".
+ +
select (COND, VAL1, VAL2)
+
Perform the select operation on constants.
+ +
icmp COND (VAL1, VAL2)
+
Performs the icmp operation on constants.
+ +
fcmp COND (VAL1, VAL2)
+
Performs the fcmp operation on constants.
+ +
extractelement (VAL, IDX)
+
Perform the extractelement operation on + constants.
+ +
insertelement (VAL, ELT, IDX)
+
Perform the insertelement operation on + constants.
+ +
shufflevector (VEC1, VEC2, IDXMASK)
+
Perform the shufflevector operation on + constants.
+ +
extractvalue (VAL, IDX0, IDX1, ...)
+
Perform the extractvalue operation on + constants. The index list is interpreted in a similar manner as indices in + a 'getelementptr' operation. At least one + index value must be specified.
+ +
insertvalue (VAL, ELT, IDX0, IDX1, ...)
+
Perform the insertvalue operation on + constants. The index list is interpreted in a similar manner as indices in + a 'getelementptr' operation. At least one + index value must be specified.
+ +
OPCODE (LHS, RHS)
+
Perform the specified operation of the LHS and RHS constants. OPCODE may + be any of the binary + or bitwise binary operations. The constraints + on operands are the same as those for the corresponding instruction + (e.g. no bitwise operations on floating point values are allowed).
+
+ +
+ + + + + + + + +
+ +

LLVM supports inline assembler expressions (as opposed + to Module-Level Inline Assembly) through the use of + a special value. This value represents the inline assembler as a string + (containing the instructions to emit), a list of operand constraints (stored + as a string), a flag that indicates whether or not the inline asm + expression has side effects, and a flag indicating whether the function + containing the asm needs to align its stack conservatively. An example + inline assembler expression is:

+ +
+i32 (i32) asm "bswap $0", "=r,r"
+
+ +

Inline assembler expressions may only be used as the callee operand of + a call instruction. Thus, typically we + have:

+ +
+%X = call i32 asm "bswap $0", "=r,r"(i32 %Y)
+
+ +

Inline asms with side effects not visible in the constraint list must be + marked as having side effects. This is done through the use of the + 'sideeffect' keyword, like so:

+ +
+call void asm sideeffect "eieio", ""()
+
+ +

In some cases inline asms will contain code that will not work unless the + stack is aligned in some way, such as calls or SSE instructions on x86, + yet will not contain code that does that alignment within the asm. + The compiler should make conservative assumptions about what the asm might + contain and should generate its usual stack alignment code in the prologue + if the 'alignstack' keyword is present:

+ +
+call void asm alignstack "eieio", ""()
+
+ +

If both keywords appear the 'sideeffect' keyword must come + first.

+ +

TODO: The format of the asm and constraints string still need to be + documented here. Constraints on what can be done (e.g. duplication, moving, + etc need to be documented). This is probably best done by reference to + another document that covers inline asm from a holistic perspective.

+
+ + + +
+ +

The call instructions that wrap inline asm nodes may have a "!srcloc" MDNode + attached to it that contains a list of constant integers. If present, the + code generator will use the integer as the location cookie value when report + errors through the LLVMContext error reporting mechanisms. This allows a + front-end to correlate backend errors that occur with inline asm back to the + source code that produced it. For example:

+ +
+call void asm sideeffect "something bad", ""(), !srcloc !42
+...
+!42 = !{ i32 1234567 }
+
+ +

It is up to the front-end to make sense of the magic numbers it places in the + IR. If the MDNode contains multiple constants, the code generator will use + the one that corresponds to the line of the asm that the error occurs on.

+ +
+ + + + +
+ +

LLVM IR allows metadata to be attached to instructions in the program that + can convey extra information about the code to the optimizers and code + generator. One example application of metadata is source-level debug + information. There are two metadata primitives: strings and nodes. All + metadata has the metadata type and is identified in syntax by a + preceding exclamation point ('!').

+ +

A metadata string is a string surrounded by double quotes. It can contain + any character by escaping non-printable characters with "\xx" where "xx" is + the two digit hex code. For example: "!"test\00"".

+ +

Metadata nodes are represented with notation similar to structure constants + (a comma separated list of elements, surrounded by braces and preceded by an + exclamation point). For example: "!{ metadata !"test\00", i32 + 10}". Metadata nodes can have any values as their operand.

+ +

A named metadata is a collection of + metadata nodes, which can be looked up in the module symbol table. For + example: "!foo = metadata !{!4, !3}". + +

Metadata can be used as function arguments. Here llvm.dbg.value + function is using two metadata arguments.

+ +
+
+call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
+
+
+ +

Metadata can be attached with an instruction. Here metadata !21 is + attached with add instruction using !dbg identifier.

+ +
+
+%indvar.next = add i64 %indvar, 1, !dbg !21
+
+
+ +
+ + + + + + +

LLVM has a number of "magic" global variables that contain data that affect +code generation or other IR semantics. These are documented here. All globals +of this sort should have a section specified as "llvm.metadata". This +section and all globals that start with "llvm." are reserved for use +by LLVM.

+ + + + +
+ +

The @llvm.used global is an array with i8* element type which has appending linkage. This array contains a list of +pointers to global variables and functions which may optionally have a pointer +cast formed of bitcast or getelementptr. For example, a legal use of it is:

+ +
+  @X = global i8 4
+  @Y = global i32 123
+
+  @llvm.used = appending global [2 x i8*] [
+     i8* @X,
+     i8* bitcast (i32* @Y to i8*)
+  ], section "llvm.metadata"
+
+ +

If a global variable appears in the @llvm.used list, then the +compiler, assembler, and linker are required to treat the symbol as if there is +a reference to the global that it cannot see. For example, if a variable has +internal linkage and no references other than that from the @llvm.used +list, it cannot be deleted. This is commonly used to represent references from +inline asms and other things the compiler cannot "see", and corresponds to +"attribute((used))" in GNU C.

+ +

On some targets, the code generator must emit a directive to the assembler or +object file to prevent the assembler and linker from molesting the symbol.

+ +
+ + + + +
+ +

The @llvm.compiler.used directive is the same as the +@llvm.used directive, except that it only prevents the compiler from +touching the symbol. On targets that support it, this allows an intelligent +linker to optimize references to the symbol without being impeded as it would be +by @llvm.used.

+ +

This is a rare construct that should only be used in rare circumstances, and +should not be exposed to source languages.

+ +
+ + + + +
+
+%0 = type { i32, void ()* }
+@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @ctor }]
+
+

The @llvm.global_ctors array contains a list of constructor functions and associated priorities. The functions referenced by this array will be called in ascending order of priority (i.e. lowest first) when the module is loaded. The order of functions with the same priority is not defined. +

+ +
+ + + + +
+
+%0 = type { i32, void ()* }
+@llvm.global_dtors = appending global [1 x %0] [%0 { i32 65535, void ()* @dtor }]
+
+ +

The @llvm.global_dtors array contains a list of destructor functions and associated priorities. The functions referenced by this array will be called in descending order of priority (i.e. highest first) when the module is loaded. The order of functions with the same priority is not defined. +

+ +
+ + + + + + +
+ +

The LLVM instruction set consists of several different classifications of + instructions: terminator + instructions, binary instructions, + bitwise binary instructions, + memory instructions, and + other instructions.

+ +
+ + + + +
+ +

As mentioned previously, every basic block + in a program ends with a "Terminator" instruction, which indicates which + block should be executed after the current block is finished. These + terminator instructions typically yield a 'void' value: they produce + control flow, not values (the one exception being the + 'invoke' instruction).

+ +

There are seven different terminator instructions: the + 'ret' instruction, the + 'br' instruction, the + 'switch' instruction, the + ''indirectbr' Instruction, the + 'invoke' instruction, the + 'unwind' instruction, and the + 'unreachable' instruction.

+ +
+ + + + +
+ +
Syntax:
+
+  ret <type> <value>       ; Return a value from a non-void function
+  ret void                 ; Return from void function
+
+ +
Overview:
+

The 'ret' instruction is used to return control flow (and optionally + a value) from a function back to the caller.

+ +

There are two forms of the 'ret' instruction: one that returns a + value and then causes control flow, and one that just causes control flow to + occur.

+ +
Arguments:
+

The 'ret' instruction optionally accepts a single argument, the + return value. The type of the return value must be a + 'first class' type.

+ +

A function is not well formed if it it has a + non-void return type and contains a 'ret' instruction with no return + value or a return value with a type that does not match its type, or if it + has a void return type and contains a 'ret' instruction with a + return value.

+ +
Semantics:
+

When the 'ret' instruction is executed, control flow returns back to + the calling function's context. If the caller is a + "call" instruction, execution continues at the + instruction after the call. If the caller was an + "invoke" instruction, execution continues at + the beginning of the "normal" destination block. If the instruction returns + a value, that value shall set the call or invoke instruction's return + value.

+ +
Example:
+
+  ret i32 5                       ; Return an integer value of 5
+  ret void                        ; Return from a void function
+  ret { i32, i8 } { i32 4, i8 2 } ; Return a struct of values 4 and 2
+
+ +
+ + + +
+ +
Syntax:
+
+  br i1 <cond>, label <iftrue>, label <iffalse>
br label <dest> ; Unconditional branch +
+ +
Overview:
+

The 'br' instruction is used to cause control flow to transfer to a + different basic block in the current function. There are two forms of this + instruction, corresponding to a conditional branch and an unconditional + branch.

+ +
Arguments:
+

The conditional branch form of the 'br' instruction takes a single + 'i1' value and two 'label' values. The unconditional form + of the 'br' instruction takes a single 'label' value as a + target.

+ +
Semantics:
+

Upon execution of a conditional 'br' instruction, the 'i1' + argument is evaluated. If the value is true, control flows to the + 'iftrue' label argument. If "cond" is false, + control flows to the 'iffalse' label argument.

+ +
Example:
+
+Test:
+  %cond = icmp eq i32 %a, %b
+  br i1 %cond, label %IfEqual, label %IfUnequal
+IfEqual:
+  ret i32 1
+IfUnequal:
+  ret i32 0
+
+ +
+ + + + +
+ +
Syntax:
+
+  switch <intty> <value>, label <defaultdest> [ <intty> <val>, label <dest> ... ]
+
+ +
Overview:
+

The 'switch' instruction is used to transfer control flow to one of + several different places. It is a generalization of the 'br' + instruction, allowing a branch to occur to one of many possible + destinations.

+ +
Arguments:
+

The 'switch' instruction uses three parameters: an integer + comparison value 'value', a default 'label' destination, + and an array of pairs of comparison value constants and 'label's. + The table is not allowed to contain duplicate constant entries.

+ +
Semantics:
+

The switch instruction specifies a table of values and + destinations. When the 'switch' instruction is executed, this table + is searched for the given value. If the value is found, control flow is + transferred to the corresponding destination; otherwise, control flow is + transferred to the default destination.

+ +
Implementation:
+

Depending on properties of the target machine and the particular + switch instruction, this instruction may be code generated in + different ways. For example, it could be generated as a series of chained + conditional branches or with a lookup table.

+ +
Example:
+
+ ; Emulate a conditional br instruction
+ %Val = zext i1 %value to i32
+ switch i32 %Val, label %truedest [ i32 0, label %falsedest ]
+
+ ; Emulate an unconditional br instruction
+ switch i32 0, label %dest [ ]
+
+ ; Implement a jump table:
+ switch i32 %val, label %otherwise [ i32 0, label %onzero
+                                     i32 1, label %onone
+                                     i32 2, label %ontwo ]
+
+ +
+ + + + + +
+ +
Syntax:
+
+  indirectbr <somety>* <address>, [ label <dest1>, label <dest2>, ... ]
+
+ +
Overview:
+ +

The 'indirectbr' instruction implements an indirect branch to a label + within the current function, whose address is specified by + "address". Address must be derived from a blockaddress constant.

+ +
Arguments:
+ +

The 'address' argument is the address of the label to jump to. The + rest of the arguments indicate the full set of possible destinations that the + address may point to. Blocks are allowed to occur multiple times in the + destination list, though this isn't particularly useful.

+ +

This destination list is required so that dataflow analysis has an accurate + understanding of the CFG.

+ +
Semantics:
+ +

Control transfers to the block specified in the address argument. All + possible destination blocks must be listed in the label list, otherwise this + instruction has undefined behavior. This implies that jumps to labels + defined in other functions have undefined behavior as well.

+ +
Implementation:
+ +

This is typically implemented with a jump through a register.

+ +
Example:
+
+ indirectbr i8* %Addr, [ label %bb1, label %bb2, label %bb3 ]
+
+ +
+ + + + + +
+ +
Syntax:
+
+  <result> = invoke [cconv] [ret attrs] <ptr to function ty> <function ptr val>(<function args>) [fn attrs]
+                to label <normal label> unwind label <exception label>
+
+ +
Overview:
+

The 'invoke' instruction causes control to transfer to a specified + function, with the possibility of control flow transfer to either the + 'normal' label or the 'exception' label. If the callee + function returns with the "ret" instruction, + control flow will return to the "normal" label. If the callee (or any + indirect callees) returns with the "unwind" + instruction, control is interrupted and continued at the dynamically nearest + "exception" label.

+ +
Arguments:
+

This instruction requires several arguments:

+ +
    +
  1. The optional "cconv" marker indicates which calling + convention the call should use. If none is specified, the call + defaults to using C calling conventions.
  2. + +
  3. The optional Parameter Attributes list for + return values. Only 'zeroext', 'signext', and + 'inreg' attributes are valid here.
  4. + +
  5. 'ptr to function ty': shall be the signature of the pointer to + function value being invoked. In most cases, this is a direct function + invocation, but indirect invokes are just as possible, branching + off an arbitrary pointer to function value.
  6. + +
  7. 'function ptr val': An LLVM value containing a pointer to a + function to be invoked.
  8. + +
  9. 'function args': argument list whose types match the function + signature argument types and parameter attributes. All arguments must be + of first class type. If the function + signature indicates the function accepts a variable number of arguments, + the extra arguments can be specified.
  10. + +
  11. 'normal label': the label reached when the called function + executes a 'ret' instruction.
  12. + +
  13. 'exception label': the label reached when a callee returns with + the unwind instruction.
  14. + +
  15. The optional function attributes list. Only + 'noreturn', 'nounwind', 'readonly' and + 'readnone' attributes are valid here.
  16. +
+ +
Semantics:
+

This instruction is designed to operate as a standard + 'call' instruction in most regards. The + primary difference is that it establishes an association with a label, which + is used by the runtime library to unwind the stack.

+ +

This instruction is used in languages with destructors to ensure that proper + cleanup is performed in the case of either a longjmp or a thrown + exception. Additionally, this is important for implementation of + 'catch' clauses in high-level languages that support them.

+ +

For the purposes of the SSA form, the definition of the value returned by the + 'invoke' instruction is deemed to occur on the edge from the current + block to the "normal" label. If the callee unwinds then no return value is + available.

+ +

Note that the code generator does not yet completely support unwind, and +that the invoke/unwind semantics are likely to change in future versions.

+ +
Example:
+
+  %retval = invoke i32 @Test(i32 15) to label %Continue
+              unwind label %TestCleanup              ; {i32}:retval set
+  %retval = invoke coldcc i32 %Testfnptr(i32 15) to label %Continue
+              unwind label %TestCleanup              ; {i32}:retval set
+
+ +
+ + + + + +
+ +
Syntax:
+
+  unwind
+
+ +
Overview:
+

The 'unwind' instruction unwinds the stack, continuing control flow + at the first callee in the dynamic call stack which used + an invoke instruction to perform the call. + This is primarily used to implement exception handling.

+ +
Semantics:
+

The 'unwind' instruction causes execution of the current function to + immediately halt. The dynamic call stack is then searched for the + first invoke instruction on the call stack. + Once found, execution continues at the "exceptional" destination block + specified by the invoke instruction. If there is no invoke + instruction in the dynamic call chain, undefined behavior results.

+ +

Note that the code generator does not yet completely support unwind, and +that the invoke/unwind semantics are likely to change in future versions.

+ +
+ + + + + +
+ +
Syntax:
+
+  unreachable
+
+ +
Overview:
+

The 'unreachable' instruction has no defined semantics. This + instruction is used to inform the optimizer that a particular portion of the + code is not reachable. This can be used to indicate that the code after a + no-return function cannot be reached, and other facts.

+ +
Semantics:
+

The 'unreachable' instruction has no defined semantics.

+ +
+ + + + +
+ +

Binary operators are used to do most of the computation in a program. They + require two operands of the same type, execute an operation on them, and + produce a single value. The operands might represent multiple data, as is + the case with the vector data type. The result value + has the same type as its operands.

+ +

There are several different binary operators:

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = add <ty> <op1>, <op2>          ; yields {ty}:result
+  <result> = add nuw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = add nsw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = add nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
+
+ +
Overview:
+

The 'add' instruction returns the sum of its two operands.

+ +
Arguments:
+

The two arguments to the 'add' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the integer sum of the two operands.

+ +

If the sum has unsigned overflow, the result returned is the mathematical + result modulo 2n, where n is the bit width of the result.

+ +

Because LLVM integers use a two's complement representation, this instruction + is appropriate for both signed and unsigned integers.

+ +

nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the add + is a trap value if unsigned and/or signed overflow, + respectively, occurs.

+ +
Example:
+
+  <result> = add i32 4, %var          ; yields {i32}:result = 4 + %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fadd <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'fadd' instruction returns the sum of its two operands.

+ +
Arguments:
+

The two arguments to the 'fadd' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the floating point sum of the two operands.

+ +
Example:
+
+  <result> = fadd float 4.0, %var          ; yields {float}:result = 4.0 + %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = sub <ty> <op1>, <op2>          ; yields {ty}:result
+  <result> = sub nuw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = sub nsw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = sub nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
+
+ +
Overview:
+

The 'sub' instruction returns the difference of its two + operands.

+ +

Note that the 'sub' instruction is used to represent the + 'neg' instruction present in most other intermediate + representations.

+ +
Arguments:
+

The two arguments to the 'sub' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the integer difference of the two operands.

+ +

If the difference has unsigned overflow, the result returned is the + mathematical result modulo 2n, where n is the bit width of the + result.

+ +

Because LLVM integers use a two's complement representation, this instruction + is appropriate for both signed and unsigned integers.

+ +

nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the sub + is a trap value if unsigned and/or signed overflow, + respectively, occurs.

+ +
Example:
+
+  <result> = sub i32 4, %var          ; yields {i32}:result = 4 - %var
+  <result> = sub i32 0, %val          ; yields {i32}:result = -%var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fsub <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'fsub' instruction returns the difference of its two + operands.

+ +

Note that the 'fsub' instruction is used to represent the + 'fneg' instruction present in most other intermediate + representations.

+ +
Arguments:
+

The two arguments to the 'fsub' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the floating point difference of the two operands.

+ +
Example:
+
+  <result> = fsub float 4.0, %var           ; yields {float}:result = 4.0 - %var
+  <result> = fsub float -0.0, %val          ; yields {float}:result = -%var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = mul <ty> <op1>, <op2>          ; yields {ty}:result
+  <result> = mul nuw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = mul nsw <ty> <op1>, <op2>      ; yields {ty}:result
+  <result> = mul nuw nsw <ty> <op1>, <op2>  ; yields {ty}:result
+
+ +
Overview:
+

The 'mul' instruction returns the product of its two operands.

+ +
Arguments:
+

The two arguments to the 'mul' instruction must + be integer or vector of + integer values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the integer product of the two operands.

+ +

If the result of the multiplication has unsigned overflow, the result + returned is the mathematical result modulo 2n, where n is the bit + width of the result.

+ +

Because LLVM integers use a two's complement representation, and the result + is the same width as the operands, this instruction returns the correct + result for both signed and unsigned integers. If a full product + (e.g. i32xi32->i64) is needed, the operands should + be sign-extended or zero-extended as appropriate to the width of the full + product.

+ +

nuw and nsw stand for "No Unsigned Wrap" + and "No Signed Wrap", respectively. If the nuw and/or + nsw keywords are present, the result value of the mul + is a trap value if unsigned and/or signed overflow, + respectively, occurs.

+ +
Example:
+
+  <result> = mul i32 4, %var          ; yields {i32}:result = 4 * %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fmul <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'fmul' instruction returns the product of its two operands.

+ +
Arguments:
+

The two arguments to the 'fmul' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the floating point product of the two operands.

+ +
Example:
+
+  <result> = fmul float 4.0, %var          ; yields {float}:result = 4.0 * %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = udiv <ty> <op1>, <op2>         ; yields {ty}:result
+  <result> = udiv exact <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'udiv' instruction returns the quotient of its two operands.

+ +
Arguments:
+

The two arguments to the 'udiv' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the unsigned integer quotient of the two operands.

+ +

Note that unsigned integer division and signed integer division are distinct + operations; for signed integer division, use 'sdiv'.

+ +

Division by zero leads to undefined behavior.

+ +

If the exact keyword is present, the result value of the + udiv is a trap value if %op1 is not a + multiple of %op2 (as such, "((a udiv exact b) mul b) == a").

+ + +
Example:
+
+  <result> = udiv i32 4, %var          ; yields {i32}:result = 4 / %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = sdiv <ty> <op1>, <op2>         ; yields {ty}:result
+  <result> = sdiv exact <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'sdiv' instruction returns the quotient of its two operands.

+ +
Arguments:
+

The two arguments to the 'sdiv' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the signed integer quotient of the two operands rounded + towards zero.

+ +

Note that signed integer division and unsigned integer division are distinct + operations; for unsigned integer division, use 'udiv'.

+ +

Division by zero leads to undefined behavior. Overflow also leads to + undefined behavior; this is a rare case, but can occur, for example, by doing + a 32-bit division of -2147483648 by -1.

+ +

If the exact keyword is present, the result value of the + sdiv is a trap value if the result would + be rounded.

+ +
Example:
+
+  <result> = sdiv i32 4, %var          ; yields {i32}:result = 4 / %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fdiv <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'fdiv' instruction returns the quotient of its two operands.

+ +
Arguments:
+

The two arguments to the 'fdiv' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

+ +
Semantics:
+

The value produced is the floating point quotient of the two operands.

+ +
Example:
+
+  <result> = fdiv float 4.0, %var          ; yields {float}:result = 4.0 / %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = urem <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'urem' instruction returns the remainder from the unsigned + division of its two arguments.

+ +
Arguments:
+

The two arguments to the 'urem' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

This instruction returns the unsigned integer remainder of a division. + This instruction always performs an unsigned division to get the + remainder.

+ +

Note that unsigned integer remainder and signed integer remainder are + distinct operations; for signed integer remainder, use 'srem'.

+ +

Taking the remainder of a division by zero leads to undefined behavior.

+ +
Example:
+
+  <result> = urem i32 4, %var          ; yields {i32}:result = 4 % %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = srem <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'srem' instruction returns the remainder from the signed + division of its two operands. This instruction can also take + vector versions of the values in which case the + elements must be integers.

+ +
Arguments:
+

The two arguments to the 'srem' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

This instruction returns the remainder of a division (where the result + is either zero or has the same sign as the dividend, op1), not the + modulo operator (where the result is either zero or has the same sign + as the divisor, op2) of a value. + For more information about the difference, + see The + Math Forum. For a table of how this is implemented in various languages, + please see + Wikipedia: modulo operation.

+ +

Note that signed integer remainder and unsigned integer remainder are + distinct operations; for unsigned integer remainder, use 'urem'.

+ +

Taking the remainder of a division by zero leads to undefined behavior. + Overflow also leads to undefined behavior; this is a rare case, but can + occur, for example, by taking the remainder of a 32-bit division of + -2147483648 by -1. (The remainder doesn't actually overflow, but this rule + lets srem be implemented using instructions that return both the result of + the division and the remainder.)

+ +
Example:
+
+  <result> = srem i32 4, %var          ; yields {i32}:result = 4 % %var
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = frem <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'frem' instruction returns the remainder from the division of + its two operands.

+ +
Arguments:
+

The two arguments to the 'frem' instruction must be + floating point or vector of + floating point values. Both arguments must have identical types.

+ +
Semantics:
+

This instruction returns the remainder of a division. The remainder + has the same sign as the dividend.

+ +
Example:
+
+  <result> = frem float 4.0, %var          ; yields {float}:result = 4.0 % %var
+
+ +
+ + + + +
+ +

Bitwise binary operators are used to do various forms of bit-twiddling in a + program. They are generally very efficient instructions and can commonly be + strength reduced from other instructions. They require two operands of the + same type, execute an operation on them, and produce a single value. The + resulting value is the same type as its operands.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = shl <ty> <op1>, <op2>           ; yields {ty}:result
+  <result> = shl nuw <ty> <op1>, <op2>       ; yields {ty}:result
+  <result> = shl nsw <ty> <op1>, <op2>       ; yields {ty}:result
+  <result> = shl nuw nsw <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'shl' instruction returns the first operand shifted to the left + a specified number of bits.

+ +
Arguments:
+

Both arguments to the 'shl' instruction must be the + same integer or vector of + integer type. 'op2' is treated as an unsigned value.

+ +
Semantics:
+

The value produced is op1 * 2op2 mod + 2n, where n is the width of the result. If op2 + is (statically or dynamically) negative or equal to or larger than the number + of bits in op1, the result is undefined. If the arguments are + vectors, each vector element of op1 is shifted by the corresponding + shift amount in op2.

+ +

If the nuw keyword is present, then the shift produces a + trap value if it shifts out any non-zero bits. If + the nsw keyword is present, then the shift produces a + trap value if it shifts out any bits that disagree + with the resultant sign bit. As such, NUW/NSW have the same semantics as + they would if the shift were expressed as a mul instruction with the same + nsw/nuw bits in (mul %op1, (shl 1, %op2)).

+ +
Example:
+
+  <result> = shl i32 4, %var   ; yields {i32}: 4 << %var
+  <result> = shl i32 4, 2      ; yields {i32}: 16
+  <result> = shl i32 1, 10     ; yields {i32}: 1024
+  <result> = shl i32 1, 32     ; undefined
+  <result> = shl <2 x i32> < i32 1, i32 1>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 2, i32 4>
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = lshr <ty> <op1>, <op2>         ; yields {ty}:result
+  <result> = lshr exact <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'lshr' instruction (logical shift right) returns the first + operand shifted to the right a specified number of bits with zero fill.

+ +
Arguments:
+

Both arguments to the 'lshr' instruction must be the same + integer or vector of integer + type. 'op2' is treated as an unsigned value.

+ +
Semantics:
+

This instruction always performs a logical shift right operation. The most + significant bits of the result will be filled with zero bits after the shift. + If op2 is (statically or dynamically) equal to or larger than the + number of bits in op1, the result is undefined. If the arguments are + vectors, each vector element of op1 is shifted by the corresponding + shift amount in op2.

+ +

If the exact keyword is present, the result value of the + lshr is a trap value if any of the bits + shifted out are non-zero.

+ + +
Example:
+
+  <result> = lshr i32 4, 1   ; yields {i32}:result = 2
+  <result> = lshr i32 4, 2   ; yields {i32}:result = 1
+  <result> = lshr i8  4, 3   ; yields {i8}:result = 0
+  <result> = lshr i8 -2, 1   ; yields {i8}:result = 0x7FFFFFFF 
+  <result> = lshr i32 1, 32  ; undefined
+  <result> = lshr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 2>   ; yields: result=<2 x i32> < i32 0x7FFFFFFF, i32 1>
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = ashr <ty> <op1>, <op2>         ; yields {ty}:result
+  <result> = ashr exact <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'ashr' instruction (arithmetic shift right) returns the first + operand shifted to the right a specified number of bits with sign + extension.

+ +
Arguments:
+

Both arguments to the 'ashr' instruction must be the same + integer or vector of integer + type. 'op2' is treated as an unsigned value.

+ +
Semantics:
+

This instruction always performs an arithmetic shift right operation, The + most significant bits of the result will be filled with the sign bit + of op1. If op2 is (statically or dynamically) equal to or + larger than the number of bits in op1, the result is undefined. If + the arguments are vectors, each vector element of op1 is shifted by + the corresponding shift amount in op2.

+ +

If the exact keyword is present, the result value of the + ashr is a trap value if any of the bits + shifted out are non-zero.

+ +
Example:
+
+  <result> = ashr i32 4, 1   ; yields {i32}:result = 2
+  <result> = ashr i32 4, 2   ; yields {i32}:result = 1
+  <result> = ashr i8  4, 3   ; yields {i8}:result = 0
+  <result> = ashr i8 -2, 1   ; yields {i8}:result = -1
+  <result> = ashr i32 1, 32  ; undefined
+  <result> = ashr <2 x i32> < i32 -2, i32 4>, < i32 1, i32 3>   ; yields: result=<2 x i32> < i32 -1, i32 0>
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = and <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'and' instruction returns the bitwise logical and of its two + operands.

+ +
Arguments:
+

The two arguments to the 'and' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

The truth table used for the 'and' instruction is:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
In0In1Out
000
010
100
111
+ +
Example:
+
+  <result> = and i32 4, %var         ; yields {i32}:result = 4 & %var
+  <result> = and i32 15, 40          ; yields {i32}:result = 8
+  <result> = and i32 4, 8            ; yields {i32}:result = 0
+
+
+ + + +
+ +
Syntax:
+
+  <result> = or <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'or' instruction returns the bitwise logical inclusive or of its + two operands.

+ +
Arguments:
+

The two arguments to the 'or' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

The truth table used for the 'or' instruction is:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
In0In1Out
000
011
101
111
+ +
Example:
+
+  <result> = or i32 4, %var         ; yields {i32}:result = 4 | %var
+  <result> = or i32 15, 40          ; yields {i32}:result = 47
+  <result> = or i32 4, 8            ; yields {i32}:result = 12
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = xor <ty> <op1>, <op2>   ; yields {ty}:result
+
+ +
Overview:
+

The 'xor' instruction returns the bitwise logical exclusive or of + its two operands. The xor is used to implement the "one's + complement" operation, which is the "~" operator in C.

+ +
Arguments:
+

The two arguments to the 'xor' instruction must be + integer or vector of integer + values. Both arguments must have identical types.

+ +
Semantics:
+

The truth table used for the 'xor' instruction is:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
In0In1Out
000
011
101
110
+ +
Example:
+
+  <result> = xor i32 4, %var         ; yields {i32}:result = 4 ^ %var
+  <result> = xor i32 15, 40          ; yields {i32}:result = 39
+  <result> = xor i32 4, 8            ; yields {i32}:result = 12
+  <result> = xor i32 %V, -1          ; yields {i32}:result = ~%V
+
+ +
+ + + + +
+ +

LLVM supports several instructions to represent vector operations in a + target-independent manner. These instructions cover the element-access and + vector-specific operations needed to process vectors effectively. While LLVM + does directly support these vector operations, many sophisticated algorithms + will want to use target-specific intrinsics to take full advantage of a + specific target.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = extractelement <n x <ty>> <val>, i32 <idx>    ; yields <ty>
+
+ +
Overview:
+

The 'extractelement' instruction extracts a single scalar element + from a vector at a specified index.

+ + +
Arguments:
+

The first operand of an 'extractelement' instruction is a value + of vector type. The second operand is an index + indicating the position from which to extract the element. The index may be + a variable.

+ +
Semantics:
+

The result is a scalar of the same type as the element type of + val. Its value is the value at position idx of + val. If idx exceeds the length of val, the + results are undefined.

+ +
Example:
+
+  <result> = extractelement <4 x i32> %vec, i32 0    ; yields i32
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = insertelement <n x <ty>> <val>, <ty> <elt>, i32 <idx>    ; yields <n x <ty>>
+
+ +
Overview:
+

The 'insertelement' instruction inserts a scalar element into a + vector at a specified index.

+ +
Arguments:
+

The first operand of an 'insertelement' instruction is a value + of vector type. The second operand is a scalar value + whose type must equal the element type of the first operand. The third + operand is an index indicating the position at which to insert the value. + The index may be a variable.

+ +
Semantics:
+

The result is a vector of the same type as val. Its element values + are those of val except at position idx, where it gets the + value elt. If idx exceeds the length of val, the + results are undefined.

+ +
Example:
+
+  <result> = insertelement <4 x i32> %vec, i32 1, i32 0    ; yields <4 x i32>
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask>    ; yields <m x <ty>>
+
+ +
Overview:
+

The 'shufflevector' instruction constructs a permutation of elements + from two input vectors, returning a vector with the same element type as the + input and length that is the same as the shuffle mask.

+ +
Arguments:
+

The first two operands of a 'shufflevector' instruction are vectors + with types that match each other. The third argument is a shuffle mask whose + element type is always 'i32'. The result of the instruction is a vector + whose length is the same as the shuffle mask and whose element type is the + same as the element type of the first two operands.

+ +

The shuffle mask operand is required to be a constant vector with either + constant integer or undef values.

+ +
Semantics:
+

The elements of the two input vectors are numbered from left to right across + both of the vectors. The shuffle mask operand specifies, for each element of + the result vector, which element of the two input vectors the result element + gets. The element selector may be undef (meaning "don't care") and the + second operand may be undef if performing a shuffle from only one vector.

+ +
Example:
+
+  <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
+                          <4 x i32> <i32 0, i32 4, i32 1, i32 5>  ; yields <4 x i32>
+  <result> = shufflevector <4 x i32> %v1, <4 x i32> undef,
+                          <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32> - Identity shuffle.
+  <result> = shufflevector <8 x i32> %v1, <8 x i32> undef,
+                          <4 x i32> <i32 0, i32 1, i32 2, i32 3>  ; yields <4 x i32>
+  <result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
+                          <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 >  ; yields <8 x i32>
+
+ +
+ + + + +
+ +

LLVM supports several instructions for working with + aggregate values.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = extractvalue <aggregate type> <val>, <idx>{, <idx>}*
+
+ +
Overview:
+

The 'extractvalue' instruction extracts the value of a member field + from an aggregate value.

+ +
Arguments:
+

The first operand of an 'extractvalue' instruction is a value + of struct or + array type. The operands are constant indices to + specify which value to extract in a similar manner as indices in a + 'getelementptr' instruction.

+

The major differences to getelementptr indexing are:

+
    +
  • Since the value being indexed is not a pointer, the first index is + omitted and assumed to be zero.
  • +
  • At least one index must be specified.
  • +
  • Not only struct indices but also array indices must be in + bounds.
  • +
+ +
Semantics:
+

The result is the value at the position in the aggregate specified by the + index operands.

+ +
Example:
+
+  <result> = extractvalue {i32, float} %agg, 0    ; yields i32
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = insertvalue <aggregate type> <val>, <ty> <elt>, <idx>    ; yields <aggregate type>
+
+ +
Overview:
+

The 'insertvalue' instruction inserts a value into a member field + in an aggregate value.

+ +
Arguments:
+

The first operand of an 'insertvalue' instruction is a value + of struct or + array type. The second operand is a first-class + value to insert. The following operands are constant indices indicating + the position at which to insert the value in a similar manner as indices in a + 'extractvalue' instruction. The + value to insert must have the same type as the value identified by the + indices.

+ +
Semantics:
+

The result is an aggregate of the same type as val. Its value is + that of val except that the value at the position specified by the + indices is that of elt.

+ +
Example:
+
+  %agg1 = insertvalue {i32, float} undef, i32 1, 0         ; yields {i32 1, float undef}
+  %agg2 = insertvalue {i32, float} %agg1, float %val, 1    ; yields {i32 1, float %val}
+
+ +
+ + + + + +
+ +

A key design point of an SSA-based representation is how it represents + memory. In LLVM, no memory locations are in SSA form, which makes things + very simple. This section describes how to read, write, and allocate + memory in LLVM.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = alloca <type>[, <ty> <NumElements>][, align <alignment>]     ; yields {type*}:result
+
+ +
Overview:
+

The 'alloca' instruction allocates memory on the stack frame of the + currently executing function, to be automatically released when this function + returns to its caller. The object is always allocated in the generic address + space (address space zero).

+ +
Arguments:
+

The 'alloca' instruction + allocates sizeof(<type>)*NumElements bytes of memory on the + runtime stack, returning a pointer of the appropriate type to the program. + If "NumElements" is specified, it is the number of elements allocated, + otherwise "NumElements" is defaulted to be one. If a constant alignment is + specified, the value result of the allocation is guaranteed to be aligned to + at least that boundary. If not specified, or if zero, the target can choose + to align the allocation on any convenient boundary compatible with the + type.

+ +

'type' may be any sized type.

+ +
Semantics:
+

Memory is allocated; a pointer is returned. The operation is undefined if + there is insufficient stack space for the allocation. 'alloca'd + memory is automatically released when the function returns. The + 'alloca' instruction is commonly used to represent automatic + variables that must have an address available. When the function returns + (either with the ret + or unwind instructions), the memory is + reclaimed. Allocating zero bytes is legal, but the result is undefined.

+ +
Example:
+
+  %ptr = alloca i32                             ; yields {i32*}:ptr
+  %ptr = alloca i32, i32 4                      ; yields {i32*}:ptr
+  %ptr = alloca i32, i32 4, align 1024          ; yields {i32*}:ptr
+  %ptr = alloca i32, align 1024                 ; yields {i32*}:ptr
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
+  <result> = volatile load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
+  !<index> = !{ i32 1 }
+
+ +
Overview:
+

The 'load' instruction is used to read from memory.

+ +
Arguments:
+

The argument to the 'load' instruction specifies the memory address + from which to load. The pointer must point to + a first class type. If the load is + marked as volatile, then the optimizer is not allowed to modify the + number or order of execution of this load with other volatile operations.

+ +

The optional constant align argument specifies the alignment of the + operation (that is, the alignment of the memory address). A value of 0 or an + omitted align argument means that the operation has the preferential + alignment for the target. It is the responsibility of the code emitter to + ensure that the alignment information is correct. Overestimating the + alignment results in undefined behavior. Underestimating the alignment may + produce less efficient code. An alignment of 1 is always safe.

+ +

The optional !nontemporal metadata must reference a single + metatadata name <index> corresponding to a metadata node with + one i32 entry of value 1. The existence of + the !nontemporal metatadata on the instruction tells the optimizer + and code generator that this load is not expected to be reused in the cache. + The code generator may select special instructions to save cache bandwidth, + such as the MOVNT instruction on x86.

+ +
Semantics:
+

The location of memory pointed to is loaded. If the value being loaded is of + scalar type then the number of bytes read does not exceed the minimum number + of bytes needed to hold all bits of the type. For example, loading an + i24 reads at most three bytes. When loading a value of a type like + i20 with a size that is not an integral number of bytes, the result + is undefined if the value was not originally written using a store of the + same type.

+ +
Examples:
+
+  %ptr = alloca i32                               ; yields {i32*}:ptr
+  store i32 3, i32* %ptr                          ; yields {void}
+  %val = load i32* %ptr                           ; yields {i32}:val = i32 3
+
+ +
+ + + + +
+ +
Syntax:
+
+  store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]                   ; yields {void}
+  volatile store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]          ; yields {void}
+
+ +
Overview:
+

The 'store' instruction is used to write to memory.

+ +
Arguments:
+

There are two arguments to the 'store' instruction: a value to store + and an address at which to store it. The type of the + '<pointer>' operand must be a pointer to + the first class type of the + '<value>' operand. If the store is marked as + volatile, then the optimizer is not allowed to modify the number or + order of execution of this store with other volatile operations.

+ +

The optional constant "align" argument specifies the alignment of the + operation (that is, the alignment of the memory address). A value of 0 or an + omitted "align" argument means that the operation has the preferential + alignment for the target. It is the responsibility of the code emitter to + ensure that the alignment information is correct. Overestimating the + alignment results in an undefined behavior. Underestimating the alignment may + produce less efficient code. An alignment of 1 is always safe.

+ +

The optional !nontemporal metadata must reference a single metatadata + name <index> corresponding to a metadata node with one i32 entry of + value 1. The existence of the !nontemporal metatadata on the + instruction tells the optimizer and code generator that this load is + not expected to be reused in the cache. The code generator may + select special instructions to save cache bandwidth, such as the + MOVNT instruction on x86.

+ + +
Semantics:
+

The contents of memory are updated to contain '<value>' at the + location specified by the '<pointer>' operand. If + '<value>' is of scalar type then the number of bytes written + does not exceed the minimum number of bytes needed to hold all bits of the + type. For example, storing an i24 writes at most three bytes. When + writing a value of a type like i20 with a size that is not an + integral number of bytes, it is unspecified what happens to the extra bits + that do not belong to the type, but they will typically be overwritten.

+ +
Example:
+
+  %ptr = alloca i32                               ; yields {i32*}:ptr
+  store i32 3, i32* %ptr                          ; yields {void}
+  %val = load i32* %ptr                           ; yields {i32}:val = i32 3
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
+  <result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
+
+ +
Overview:
+

The 'getelementptr' instruction is used to get the address of a + subelement of an aggregate data structure. + It performs address calculation only and does not access memory.

+ +
Arguments:
+

The first argument is always a pointer, and forms the basis of the + calculation. The remaining arguments are indices that indicate which of the + elements of the aggregate object are indexed. The interpretation of each + index is dependent on the type being indexed into. The first index always + indexes the pointer value given as the first argument, the second index + indexes a value of the type pointed to (not necessarily the value directly + pointed to, since the first index can be non-zero), etc. The first type + indexed into must be a pointer value, subsequent types can be arrays, + vectors, and structs. Note that subsequent types being indexed into + can never be pointers, since that would require loading the pointer before + continuing calculation.

+ +

The type of each index argument depends on the type it is indexing into. + When indexing into a (optionally packed) structure, only i32 + integer constants are allowed. When indexing into an array, pointer + or vector, integers of any width are allowed, and they are not required to be + constant.

+ +

For example, let's consider a C code fragment and how it gets compiled to + LLVM:

+ +
+struct RT {
+  char A;
+  int B[10][20];
+  char C;
+};
+struct ST {
+  int X;
+  double Y;
+  struct RT Z;
+};
+
+int *foo(struct ST *s) {
+  return &s[1].Z.B[5][13];
+}
+
+ +

The LLVM code generated by the GCC frontend is:

+ +
+%RT = type { i8 , [10 x [20 x i32]], i8  }
+%ST = type { i32, double, %RT }
+
+define i32* @foo(%ST* %s) {
+entry:
+  %reg = getelementptr %ST* %s, i32 1, i32 2, i32 1, i32 5, i32 13
+  ret i32* %reg
+}
+
+ +
Semantics:
+

In the example above, the first index is indexing into the '%ST*' + type, which is a pointer, yielding a '%ST' = '{ i32, double, %RT + }' type, a structure. The second index indexes into the third element + of the structure, yielding a '%RT' = '{ i8 , [10 x [20 x i32]], + i8 }' type, another structure. The third index indexes into the second + element of the structure, yielding a '[10 x [20 x i32]]' type, an + array. The two dimensions of the array are subscripted into, yielding an + 'i32' type. The 'getelementptr' instruction returns a + pointer to this element, thus computing a value of 'i32*' type.

+ +

Note that it is perfectly legal to index partially through a structure, + returning a pointer to an inner element. Because of this, the LLVM code for + the given testcase is equivalent to:

+ +
+  define i32* @foo(%ST* %s) {
+    %t1 = getelementptr %ST* %s, i32 1                        ; yields %ST*:%t1
+    %t2 = getelementptr %ST* %t1, i32 0, i32 2                ; yields %RT*:%t2
+    %t3 = getelementptr %RT* %t2, i32 0, i32 1                ; yields [10 x [20 x i32]]*:%t3
+    %t4 = getelementptr [10 x [20 x i32]]* %t3, i32 0, i32 5  ; yields [20 x i32]*:%t4
+    %t5 = getelementptr [20 x i32]* %t4, i32 0, i32 13        ; yields i32*:%t5
+    ret i32* %t5
+  }
+
+ +

If the inbounds keyword is present, the result value of the + getelementptr is a trap value if the + base pointer is not an in bounds address of an allocated object, + or if any of the addresses that would be formed by successive addition of + the offsets implied by the indices to the base address with infinitely + precise arithmetic are not an in bounds address of that allocated + object. The in bounds addresses for an allocated object are all + the addresses that point into the object, plus the address one byte past + the end.

+ +

If the inbounds keyword is not present, the offsets are added to + the base address with silently-wrapping two's complement arithmetic, and + the result value of the getelementptr may be outside the object + pointed to by the base pointer. The result value may not necessarily be + used to access memory though, even if it happens to point into allocated + storage. See the Pointer Aliasing Rules + section for more information.

+ +

The getelementptr instruction is often confusing. For some more insight into + how it works, see the getelementptr FAQ.

+ +
Example:
+
+    ; yields [12 x i8]*:aptr
+    %aptr = getelementptr {i32, [12 x i8]}* %saptr, i64 0, i32 1
+    ; yields i8*:vptr
+    %vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1
+    ; yields i8*:eptr
+    %eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1
+    ; yields i32*:iptr
+    %iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0
+
+ +
+ + + + +
+ +

The instructions in this category are the conversion instructions (casting) + which all take a single operand and a type. They perform various bit + conversions on the operand.

+ +
+ + + +
+ +
Syntax:
+
+  <result> = trunc <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'trunc' instruction truncates its operand to the + type ty2.

+ +
Arguments:
+

The 'trunc' instruction takes a value to trunc, and a type to trunc it to. + Both types must be of integer types, or vectors + of the same number of integers. + The bit size of the value must be larger than + the bit size of the destination type, ty2. + Equal sized types are not allowed.

+ +
Semantics:
+

The 'trunc' instruction truncates the high order bits + in value and converts the remaining bits to ty2. Since the + source size must be larger than the destination size, trunc cannot + be a no-op cast. It will always truncate bits.

+ +
Example:
+
+  %X = trunc i32 257 to i8                        ; yields i8:1
+  %Y = trunc i32 123 to i1                        ; yields i1:true
+  %Z = trunc i32 122 to i1                        ; yields i1:false
+  %W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> ; yields <i8 8, i8 7>
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = zext <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'zext' instruction zero extends its operand to type + ty2.

+ + +
Arguments:
+

The 'zext' instruction takes a value to cast, and a type to cast it to. + Both types must be of integer types, or vectors + of the same number of integers. + The bit size of the value must be smaller than + the bit size of the destination type, + ty2.

+ +
Semantics:
+

The zext fills the high order bits of the value with zero + bits until it reaches the size of the destination type, ty2.

+ +

When zero extending from i1, the result will always be either 0 or 1.

+ +
Example:
+
+  %X = zext i32 257 to i64              ; yields i64:257
+  %Y = zext i1 true to i32              ; yields i32:1
+  %Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = sext <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'sext' sign extends value to the type ty2.

+ +
Arguments:
+

The 'sext' instruction takes a value to cast, and a type to cast it to. + Both types must be of integer types, or vectors + of the same number of integers. + The bit size of the value must be smaller than + the bit size of the destination type, + ty2.

+ +
Semantics:
+

The 'sext' instruction performs a sign extension by copying the sign + bit (highest order bit) of the value until it reaches the bit size + of the type ty2.

+ +

When sign extending from i1, the extension always results in -1 or 0.

+ +
Example:
+
+  %X = sext i8  -1 to i16              ; yields i16   :65535
+  %Y = sext i1 true to i32             ; yields i32:-1
+  %Z = sext <2 x i16> <i16 8, i16 7> to <2 x i32> ; yields <i32 8, i32 7>
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fptrunc <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'fptrunc' instruction truncates value to type + ty2.

+ +
Arguments:
+

The 'fptrunc' instruction takes a floating + point value to cast and a floating point type + to cast it to. The size of value must be larger than the size of + ty2. This implies that fptrunc cannot be used to make a + no-op cast.

+ +
Semantics:
+

The 'fptrunc' instruction truncates a value from a larger + floating point type to a smaller + floating point type. If the value cannot fit + within the destination type, ty2, then the results are + undefined.

+ +
Example:
+
+  %X = fptrunc double 123.0 to float         ; yields float:123.0
+  %Y = fptrunc double 1.0E+300 to float      ; yields undefined
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = fpext <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'fpext' extends a floating point value to a larger + floating point value.

+ +
Arguments:
+

The 'fpext' instruction takes a + floating point value to cast, and + a floating point type to cast it to. The source + type must be smaller than the destination type.

+ +
Semantics:
+

The 'fpext' instruction extends the value from a smaller + floating point type to a larger + floating point type. The fpext cannot be + used to make a no-op cast because it always changes bits. Use + bitcast to make a no-op cast for a floating point cast.

+ +
Example:
+
+  %X = fpext float 3.1415 to double        ; yields double:3.1415
+  %Y = fpext float 1.0 to float            ; yields float:1.0 (no-op)
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = fptoui <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'fptoui' converts a floating point value to its + unsigned integer equivalent of type ty2.

+ +
Arguments:
+

The 'fptoui' instruction takes a value to cast, which must be a + scalar or vector floating point value, and a type + to cast it to ty2, which must be an integer + type. If ty is a vector floating point type, ty2 must be a + vector integer type with the same number of elements as ty

+ +
Semantics:
+

The 'fptoui' instruction converts its + floating point operand into the nearest (rounding + towards zero) unsigned integer value. If the value cannot fit + in ty2, the results are undefined.

+ +
Example:
+
+  %X = fptoui double 123.0 to i32      ; yields i32:123
+  %Y = fptoui float 1.0E+300 to i1     ; yields undefined:1
+  %Z = fptoui float 1.04E+17 to i8     ; yields undefined:1
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = fptosi <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'fptosi' instruction converts + floating point value to + type ty2.

+ +
Arguments:
+

The 'fptosi' instruction takes a value to cast, which must be a + scalar or vector floating point value, and a type + to cast it to ty2, which must be an integer + type. If ty is a vector floating point type, ty2 must be a + vector integer type with the same number of elements as ty

+ +
Semantics:
+

The 'fptosi' instruction converts its + floating point operand into the nearest (rounding + towards zero) signed integer value. If the value cannot fit in ty2, + the results are undefined.

+ +
Example:
+
+  %X = fptosi double -123.0 to i32      ; yields i32:-123
+  %Y = fptosi float 1.0E-247 to i1      ; yields undefined:1
+  %Z = fptosi float 1.04E+17 to i8      ; yields undefined:1
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = uitofp <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'uitofp' instruction regards value as an unsigned + integer and converts that value to the ty2 type.

+ +
Arguments:
+

The 'uitofp' instruction takes a value to cast, which must be a + scalar or vector integer value, and a type to cast + it to ty2, which must be an floating point + type. If ty is a vector integer type, ty2 must be a vector + floating point type with the same number of elements as ty

+ +
Semantics:
+

The 'uitofp' instruction interprets its operand as an unsigned + integer quantity and converts it to the corresponding floating point + value. If the value cannot fit in the floating point value, the results are + undefined.

+ +
Example:
+
+  %X = uitofp i32 257 to float         ; yields float:257.0
+  %Y = uitofp i8 -1 to double          ; yields double:255.0
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = sitofp <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'sitofp' instruction regards value as a signed integer + and converts that value to the ty2 type.

+ +
Arguments:
+

The 'sitofp' instruction takes a value to cast, which must be a + scalar or vector integer value, and a type to cast + it to ty2, which must be an floating point + type. If ty is a vector integer type, ty2 must be a vector + floating point type with the same number of elements as ty

+ +
Semantics:
+

The 'sitofp' instruction interprets its operand as a signed integer + quantity and converts it to the corresponding floating point value. If the + value cannot fit in the floating point value, the results are undefined.

+ +
Example:
+
+  %X = sitofp i32 257 to float         ; yields float:257.0
+  %Y = sitofp i8 -1 to double          ; yields double:-1.0
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = ptrtoint <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'ptrtoint' instruction converts the pointer value to + the integer type ty2.

+ +
Arguments:
+

The 'ptrtoint' instruction takes a value to cast, which + must be a pointer value, and a type to cast it to + ty2, which must be an integer type.

+ +
Semantics:
+

The 'ptrtoint' instruction converts value to integer type + ty2 by interpreting the pointer value as an integer and either + truncating or zero extending that value to the size of the integer type. If + value is smaller than ty2 then a zero extension is done. If + value is larger than ty2 then a truncation is done. If they + are the same size, then nothing is done (no-op cast) other than a type + change.

+ +
Example:
+
+  %X = ptrtoint i32* %X to i8           ; yields truncation on 32-bit architecture
+  %Y = ptrtoint i32* %x to i64          ; yields zero extension on 32-bit architecture
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = inttoptr <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'inttoptr' instruction converts an integer value to a + pointer type, ty2.

+ +
Arguments:
+

The 'inttoptr' instruction takes an integer + value to cast, and a type to cast it to, which must be a + pointer type.

+ +
Semantics:
+

The 'inttoptr' instruction converts value to type + ty2 by applying either a zero extension or a truncation depending on + the size of the integer value. If value is larger than the + size of a pointer then a truncation is done. If value is smaller + than the size of a pointer then a zero extension is done. If they are the + same size, nothing is done (no-op cast).

+ +
Example:
+
+  %X = inttoptr i32 255 to i32*          ; yields zero extension on 64-bit architecture
+  %Y = inttoptr i32 255 to i32*          ; yields no-op on 32-bit architecture
+  %Z = inttoptr i64 0 to i32*            ; yields truncation on 32-bit architecture
+
+ +
+ + + +
+ +
Syntax:
+
+  <result> = bitcast <ty> <value> to <ty2>             ; yields ty2
+
+ +
Overview:
+

The 'bitcast' instruction converts value to type + ty2 without changing any bits.

+ +
Arguments:
+

The 'bitcast' instruction takes a value to cast, which must be a + non-aggregate first class value, and a type to cast it to, which must also be + a non-aggregate first class type. The bit sizes + of value and the destination type, ty2, must be + identical. If the source type is a pointer, the destination type must also be + a pointer. This instruction supports bitwise conversion of vectors to + integers and to vectors of other types (as long as they have the same + size).

+ +
Semantics:
+

The 'bitcast' instruction converts value to type + ty2. It is always a no-op cast because no bits change with + this conversion. The conversion is done as if the value had been + stored to memory and read back as type ty2. Pointer types may only + be converted to other pointer types with this instruction. To convert + pointers to other types, use the inttoptr or + ptrtoint instructions first.

+ +
Example:
+
+  %X = bitcast i8 255 to i8              ; yields i8 :-1
+  %Y = bitcast i32* %x to sint*          ; yields sint*:%x
+  %Z = bitcast <2 x int> %V to i64;      ; yields i64: %V
+
+ +
+ + + + +
+ +

The instructions in this category are the "miscellaneous" instructions, which + defy better classification.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = icmp <cond> <ty> <op1>, <op2>   ; yields {i1} or {<N x i1>}:result
+
+ +
Overview:
+

The 'icmp' instruction returns a boolean value or a vector of + boolean values based on comparison of its two integer, integer vector, or + pointer operands.

+ +
Arguments:
+

The 'icmp' instruction takes three operands. The first operand is + the condition code indicating the kind of comparison to perform. It is not a + value, just a keyword. The possible condition code are:

+ +
    +
  1. eq: equal
  2. +
  3. ne: not equal
  4. +
  5. ugt: unsigned greater than
  6. +
  7. uge: unsigned greater or equal
  8. +
  9. ult: unsigned less than
  10. +
  11. ule: unsigned less or equal
  12. +
  13. sgt: signed greater than
  14. +
  15. sge: signed greater or equal
  16. +
  17. slt: signed less than
  18. +
  19. sle: signed less or equal
  20. +
+ +

The remaining two arguments must be integer or + pointer or integer vector + typed. They must also be identical types.

+ +
Semantics:
+

The 'icmp' compares op1 and op2 according to the + condition code given as cond. The comparison performed always yields + either an i1 or vector of i1 + result, as follows:

+ +
    +
  1. eq: yields true if the operands are equal, + false otherwise. No sign interpretation is necessary or + performed.
  2. + +
  3. ne: yields true if the operands are unequal, + false otherwise. No sign interpretation is necessary or + performed.
  4. + +
  5. ugt: interprets the operands as unsigned values and yields + true if op1 is greater than op2.
  6. + +
  7. uge: interprets the operands as unsigned values and yields + true if op1 is greater than or equal + to op2.
  8. + +
  9. ult: interprets the operands as unsigned values and yields + true if op1 is less than op2.
  10. + +
  11. ule: interprets the operands as unsigned values and yields + true if op1 is less than or equal to op2.
  12. + +
  13. sgt: interprets the operands as signed values and yields + true if op1 is greater than op2.
  14. + +
  15. sge: interprets the operands as signed values and yields + true if op1 is greater than or equal + to op2.
  16. + +
  17. slt: interprets the operands as signed values and yields + true if op1 is less than op2.
  18. + +
  19. sle: interprets the operands as signed values and yields + true if op1 is less than or equal to op2.
  20. +
+ +

If the operands are pointer typed, the pointer + values are compared as if they were integers.

+ +

If the operands are integer vectors, then they are compared element by + element. The result is an i1 vector with the same number of elements + as the values being compared. Otherwise, the result is an i1.

+ +
Example:
+
+  <result> = icmp eq i32 4, 5          ; yields: result=false
+  <result> = icmp ne float* %X, %X     ; yields: result=false
+  <result> = icmp ult i16  4, 5        ; yields: result=true
+  <result> = icmp sgt i16  4, 5        ; yields: result=false
+  <result> = icmp ule i16 -4, 5        ; yields: result=false
+  <result> = icmp sge i16  4, 5        ; yields: result=false
+
+ +

Note that the code generator does not yet support vector types with + the icmp instruction.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = fcmp <cond> <ty> <op1>, <op2>     ; yields {i1} or {<N x i1>}:result
+
+ +
Overview:
+

The 'fcmp' instruction returns a boolean value or vector of boolean + values based on comparison of its operands.

+ +

If the operands are floating point scalars, then the result type is a boolean +(i1).

+ +

If the operands are floating point vectors, then the result type is a vector + of boolean with the same number of elements as the operands being + compared.

+ +
Arguments:
+

The 'fcmp' instruction takes three operands. The first operand is + the condition code indicating the kind of comparison to perform. It is not a + value, just a keyword. The possible condition code are:

+ +
    +
  1. false: no comparison, always returns false
  2. +
  3. oeq: ordered and equal
  4. +
  5. ogt: ordered and greater than
  6. +
  7. oge: ordered and greater than or equal
  8. +
  9. olt: ordered and less than
  10. +
  11. ole: ordered and less than or equal
  12. +
  13. one: ordered and not equal
  14. +
  15. ord: ordered (no nans)
  16. +
  17. ueq: unordered or equal
  18. +
  19. ugt: unordered or greater than
  20. +
  21. uge: unordered or greater than or equal
  22. +
  23. ult: unordered or less than
  24. +
  25. ule: unordered or less than or equal
  26. +
  27. une: unordered or not equal
  28. +
  29. uno: unordered (either nans)
  30. +
  31. true: no comparison, always returns true
  32. +
+ +

Ordered means that neither operand is a QNAN while + unordered means that either operand may be a QNAN.

+ +

Each of val1 and val2 arguments must be either + a floating point type or + a vector of floating point type. They must have + identical types.

+ +
Semantics:
+

The 'fcmp' instruction compares op1 and op2 + according to the condition code given as cond. If the operands are + vectors, then the vectors are compared element by element. Each comparison + performed always yields an i1 result, as + follows:

+ +
    +
  1. false: always yields false, regardless of operands.
  2. + +
  3. oeq: yields true if both operands are not a QNAN and + op1 is equal to op2.
  4. + +
  5. ogt: yields true if both operands are not a QNAN and + op1 is greater than op2.
  6. + +
  7. oge: yields true if both operands are not a QNAN and + op1 is greater than or equal to op2.
  8. + +
  9. olt: yields true if both operands are not a QNAN and + op1 is less than op2.
  10. + +
  11. ole: yields true if both operands are not a QNAN and + op1 is less than or equal to op2.
  12. + +
  13. one: yields true if both operands are not a QNAN and + op1 is not equal to op2.
  14. + +
  15. ord: yields true if both operands are not a QNAN.
  16. + +
  17. ueq: yields true if either operand is a QNAN or + op1 is equal to op2.
  18. + +
  19. ugt: yields true if either operand is a QNAN or + op1 is greater than op2.
  20. + +
  21. uge: yields true if either operand is a QNAN or + op1 is greater than or equal to op2.
  22. + +
  23. ult: yields true if either operand is a QNAN or + op1 is less than op2.
  24. + +
  25. ule: yields true if either operand is a QNAN or + op1 is less than or equal to op2.
  26. + +
  27. une: yields true if either operand is a QNAN or + op1 is not equal to op2.
  28. + +
  29. uno: yields true if either operand is a QNAN.
  30. + +
  31. true: always yields true, regardless of operands.
  32. +
+ +
Example:
+
+  <result> = fcmp oeq float 4.0, 5.0    ; yields: result=false
+  <result> = fcmp one float 4.0, 5.0    ; yields: result=true
+  <result> = fcmp olt float 4.0, 5.0    ; yields: result=true
+  <result> = fcmp ueq double 1.0, 2.0   ; yields: result=false
+
+ +

Note that the code generator does not yet support vector types with + the fcmp instruction.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = phi <ty> [ <val0>, <label0>], ...
+
+ +
Overview:
+

The 'phi' instruction is used to implement the φ node in the + SSA graph representing the function.

+ +
Arguments:
+

The type of the incoming values is specified with the first type field. After + this, the 'phi' instruction takes a list of pairs as arguments, with + one pair for each predecessor basic block of the current block. Only values + of first class type may be used as the value + arguments to the PHI node. Only labels may be used as the label + arguments.

+ +

There must be no non-phi instructions between the start of a basic block and + the PHI instructions: i.e. PHI instructions must be first in a basic + block.

+ +

For the purposes of the SSA form, the use of each incoming value is deemed to + occur on the edge from the corresponding predecessor block to the current + block (but after any definition of an 'invoke' instruction's return + value on the same edge).

+ +
Semantics:
+

At runtime, the 'phi' instruction logically takes on the value + specified by the pair corresponding to the predecessor basic block that + executed just prior to the current block.

+ +
Example:
+
+Loop:       ; Infinite loop that counts from 0 on up...
+  %indvar = phi i32 [ 0, %LoopHeader ], [ %nextindvar, %Loop ]
+  %nextindvar = add i32 %indvar, 1
+  br label %Loop
+
+ +
+ + + + +
+ +
Syntax:
+
+  <result> = select selty <cond>, <ty> <val1>, <ty> <val2>             ; yields ty
+
+  selty is either i1 or {<N x i1>}
+
+ +
Overview:
+

The 'select' instruction is used to choose one value based on a + condition, without branching.

+ + +
Arguments:
+

The 'select' instruction requires an 'i1' value or a vector of 'i1' + values indicating the condition, and two values of the + same first class type. If the val1/val2 are + vectors and the condition is a scalar, then entire vectors are selected, not + individual elements.

+ +
Semantics:
+

If the condition is an i1 and it evaluates to 1, the instruction returns the + first value argument; otherwise, it returns the second value argument.

+ +

If the condition is a vector of i1, then the value arguments must be vectors + of the same size, and the selection is done element by element.

+ +
Example:
+
+  %X = select i1 true, i8 17, i8 42          ; yields i8:17
+
+ +

Note that the code generator does not yet support conditions + with vector type.

+ +
+ + + + +
+ +
Syntax:
+
+  <result> = [tail] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
+
+ +
Overview:
+

The 'call' instruction represents a simple function call.

+ +
Arguments:
+

This instruction requires several arguments:

+ +
    +
  1. The optional "tail" marker indicates that the callee function does not + access any allocas or varargs in the caller. Note that calls may be + marked "tail" even if they do not occur before + a ret instruction. If the "tail" marker is + present, the function call is eligible for tail call optimization, + but might not in fact be + optimized into a jump. The code generator may optimize calls marked + "tail" with either 1) automatic + sibling call optimization when the caller and callee have + matching signatures, or 2) forced tail call optimization when the + following extra requirements are met: +
      +
    • Caller and callee both have the calling + convention fastcc.
    • +
    • The call is in tail position (ret immediately follows call and ret + uses value of call or is void).
    • +
    • Option -tailcallopt is enabled, + or llvm::GuaranteedTailCallOpt is true.
    • +
    • Platform specific + constraints are met.
    • +
    +
  2. + +
  3. The optional "cconv" marker indicates which calling + convention the call should use. If none is specified, the call + defaults to using C calling conventions. The calling convention of the + call must match the calling convention of the target function, or else the + behavior is undefined.
  4. + +
  5. The optional Parameter Attributes list for + return values. Only 'zeroext', 'signext', and + 'inreg' attributes are valid here.
  6. + +
  7. 'ty': the type of the call instruction itself which is also the + type of the return value. Functions that return no value are marked + void.
  8. + +
  9. 'fnty': shall be the signature of the pointer to function value + being invoked. The argument types must match the types implied by this + signature. This type can be omitted if the function is not varargs and if + the function type does not return a pointer to a function.
  10. + +
  11. 'fnptrval': An LLVM value containing a pointer to a function to + be invoked. In most cases, this is a direct function invocation, but + indirect calls are just as possible, calling an arbitrary pointer + to function value.
  12. + +
  13. 'function args': argument list whose types match the function + signature argument types and parameter attributes. All arguments must be + of first class type. If the function + signature indicates the function accepts a variable number of arguments, + the extra arguments can be specified.
  14. + +
  15. The optional function attributes list. Only + 'noreturn', 'nounwind', 'readonly' and + 'readnone' attributes are valid here.
  16. +
+ +
Semantics:
+

The 'call' instruction is used to cause control flow to transfer to + a specified function, with its incoming arguments bound to the specified + values. Upon a 'ret' instruction in the called + function, control flow continues with the instruction after the function + call, and the return value of the function is bound to the result + argument.

+ +
Example:
+
+  %retval = call i32 @test(i32 %argc)
+  call i32 (i8*, ...)* @printf(i8* %msg, i32 12, i8 42)        ; yields i32
+  %X = tail call i32 @foo()                                    ; yields i32
+  %Y = tail call fastcc i32 @foo()  ; yields i32
+  call void %foo(i8 97 signext)
+
+  %struct.A = type { i32, i8 }
+  %r = call %struct.A @foo()                        ; yields { 32, i8 }
+  %gr = extractvalue %struct.A %r, 0                ; yields i32
+  %gr1 = extractvalue %struct.A %r, 1               ; yields i8
+  %Z = call void @foo() noreturn                    ; indicates that %foo never returns normally
+  %ZZ = call zeroext i32 @bar()                     ; Return value is %zero extended
+
+ +

llvm treats calls to some functions with names and arguments that match the +standard C99 library as being the C99 library functions, and may perform +optimizations or generate code for them under that assumption. This is +something we'd like to change in the future to provide better support for +freestanding environments and non-C-based languages.

+ +
+ + + + +
+ +
Syntax:
+
+  <resultval> = va_arg <va_list*> <arglist>, <argty>
+
+ +
Overview:
+

The 'va_arg' instruction is used to access arguments passed through + the "variable argument" area of a function call. It is used to implement the + va_arg macro in C.

+ +
Arguments:
+

This instruction takes a va_list* value and the type of the + argument. It returns a value of the specified argument type and increments + the va_list to point to the next argument. The actual type + of va_list is target specific.

+ +
Semantics:
+

The 'va_arg' instruction loads an argument of the specified type + from the specified va_list and causes the va_list to point + to the next argument. For more information, see the variable argument + handling Intrinsic Functions.

+ +

It is legal for this instruction to be called in a function which does not + take a variable number of arguments, for example, the vfprintf + function.

+ +

va_arg is an LLVM instruction instead of + an intrinsic function because it takes a type as an + argument.

+ +
Example:
+

See the variable argument processing section.

+ +

Note that the code generator does not yet fully support va_arg on many + targets. Also, it does not currently support va_arg with aggregate types on + any target.

+ +
+ + + + + +
+ +

LLVM supports the notion of an "intrinsic function". These functions have + well known names and semantics and are required to follow certain + restrictions. Overall, these intrinsics represent an extension mechanism for + the LLVM language that does not require changing all of the transformations + in LLVM when adding to the language (or the bitcode reader/writer, the + parser, etc...).

+ +

Intrinsic function names must all start with an "llvm." prefix. This + prefix is reserved in LLVM for intrinsic names; thus, function names may not + begin with this prefix. Intrinsic functions must always be external + functions: you cannot define the body of intrinsic functions. Intrinsic + functions may only be used in call or invoke instructions: it is illegal to + take the address of an intrinsic function. Additionally, because intrinsic + functions are part of the LLVM language, it is required if any are added that + they be documented here.

+ +

Some intrinsic functions can be overloaded, i.e., the intrinsic represents a + family of functions that perform the same operation but on different data + types. Because LLVM can represent over 8 million different integer types, + overloading is used commonly to allow an intrinsic function to operate on any + integer type. One or more of the argument types or the result type can be + overloaded to accept any integer type. Argument types may also be defined as + exactly matching a previous argument's type or the result type. This allows + an intrinsic function which accepts multiple arguments, but needs all of them + to be of the same type, to only be overloaded with respect to a single + argument or the result.

+ +

Overloaded intrinsics will have the names of its overloaded argument types + encoded into its function name, each preceded by a period. Only those types + which are overloaded result in a name suffix. Arguments whose type is matched + against another type do not. For example, the llvm.ctpop function + can take an integer of any width and returns an integer of exactly the same + integer width. This leads to a family of functions such as + i8 @llvm.ctpop.i8(i8 %val) and i29 @llvm.ctpop.i29(i29 + %val). Only one type, the return type, is overloaded, and only one type + suffix is required. Because the argument's type is matched against the return + type, it does not require its own name suffix.

+ +

To learn how to add an intrinsic function, please see the + Extending LLVM Guide.

+ +
+ + + + +
+ +

Variable argument support is defined in LLVM with + the va_arg instruction and these three + intrinsic functions. These functions are related to the similarly named + macros defined in the <stdarg.h> header file.

+ +

All of these functions operate on arguments that use a target-specific value + type "va_list". The LLVM assembly language reference manual does + not define what this type is, so all transformations should be prepared to + handle these functions regardless of the type used.

+ +

This example shows how the va_arg + instruction and the variable argument handling intrinsic functions are + used.

+ +
+define i32 @test(i32 %X, ...) {
+  ; Initialize variable argument processing
+  %ap = alloca i8*
+  %ap2 = bitcast i8** %ap to i8*
+  call void @llvm.va_start(i8* %ap2)
+
+  ; Read a single integer argument
+  %tmp = va_arg i8** %ap, i32
+
+  ; Demonstrate usage of llvm.va_copy and llvm.va_end
+  %aq = alloca i8*
+  %aq2 = bitcast i8** %aq to i8*
+  call void @llvm.va_copy(i8* %aq2, i8* %ap2)
+  call void @llvm.va_end(i8* %aq2)
+
+  ; Stop processing of arguments.
+  call void @llvm.va_end(i8* %ap2)
+  ret i32 %tmp
+}
+
+declare void @llvm.va_start(i8*)
+declare void @llvm.va_copy(i8*, i8*)
+declare void @llvm.va_end(i8*)
+
+ +
+ + + + + +
+ +
Syntax:
+
+  declare void %llvm.va_start(i8* <arglist>)
+
+ +
Overview:
+

The 'llvm.va_start' intrinsic initializes *<arglist> + for subsequent use by va_arg.

+ +
Arguments:
+

The argument is a pointer to a va_list element to initialize.

+ +
Semantics:
+

The 'llvm.va_start' intrinsic works just like the va_start + macro available in C. In a target-dependent way, it initializes + the va_list element to which the argument points, so that the next + call to va_arg will produce the first variable argument passed to + the function. Unlike the C va_start macro, this intrinsic does not + need to know the last argument of the function as the compiler can figure + that out.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.va_end(i8* <arglist>)
+
+ +
Overview:
+

The 'llvm.va_end' intrinsic destroys *<arglist>, + which has been initialized previously + with llvm.va_start + or llvm.va_copy.

+ +
Arguments:
+

The argument is a pointer to a va_list to destroy.

+ +
Semantics:
+

The 'llvm.va_end' intrinsic works just like the va_end + macro available in C. In a target-dependent way, it destroys + the va_list element to which the argument points. Calls + to llvm.va_start + and llvm.va_copy must be matched exactly + with calls to llvm.va_end.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.va_copy(i8* <destarglist>, i8* <srcarglist>)
+
+ +
Overview:
+

The 'llvm.va_copy' intrinsic copies the current argument position + from the source argument list to the destination argument list.

+ +
Arguments:
+

The first argument is a pointer to a va_list element to initialize. + The second argument is a pointer to a va_list element to copy + from.

+ +
Semantics:
+

The 'llvm.va_copy' intrinsic works just like the va_copy + macro available in C. In a target-dependent way, it copies the + source va_list element into the destination va_list + element. This intrinsic is necessary because + the llvm.va_start intrinsic may be + arbitrarily complex and require, for example, memory allocation.

+ +
+ + + + +
+ +

LLVM support for Accurate Garbage +Collection (GC) requires the implementation and generation of these +intrinsics. These intrinsics allow identification of GC +roots on the stack, as well as garbage collector implementations that +require read and write +barriers. Front-ends for type-safe garbage collected languages should generate +these intrinsics to make use of the LLVM garbage collectors. For more details, +see Accurate Garbage Collection with +LLVM.

+ +

The garbage collection intrinsics only operate on objects in the generic + address space (address space zero).

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.gcroot(i8** %ptrloc, i8* %metadata)
+
+ +
Overview:
+

The 'llvm.gcroot' intrinsic declares the existence of a GC root to + the code generator, and allows some metadata to be associated with it.

+ +
Arguments:
+

The first argument specifies the address of a stack object that contains the + root pointer. The second pointer (which must be either a constant or a + global value address) contains the meta-data to be associated with the + root.

+ +
Semantics:
+

At runtime, a call to this intrinsic stores a null pointer into the "ptrloc" + location. At compile-time, the code generator generates information to allow + the runtime to find the pointer at GC safe points. The 'llvm.gcroot' + intrinsic may only be used in a function which specifies a GC + algorithm.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i8* @llvm.gcread(i8* %ObjPtr, i8** %Ptr)
+
+ +
Overview:
+

The 'llvm.gcread' intrinsic identifies reads of references from heap + locations, allowing garbage collector implementations that require read + barriers.

+ +
Arguments:
+

The second argument is the address to read from, which should be an address + allocated from the garbage collector. The first object is a pointer to the + start of the referenced object, if needed by the language runtime (otherwise + null).

+ +
Semantics:
+

The 'llvm.gcread' intrinsic has the same semantics as a load + instruction, but may be replaced with substantially more complex code by the + garbage collector runtime, as needed. The 'llvm.gcread' intrinsic + may only be used in a function which specifies a GC + algorithm.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.gcwrite(i8* %P1, i8* %Obj, i8** %P2)
+
+ +
Overview:
+

The 'llvm.gcwrite' intrinsic identifies writes of references to heap + locations, allowing garbage collector implementations that require write + barriers (such as generational or reference counting collectors).

+ +
Arguments:
+

The first argument is the reference to store, the second is the start of the + object to store it to, and the third is the address of the field of Obj to + store to. If the runtime does not require a pointer to the object, Obj may + be null.

+ +
Semantics:
+

The 'llvm.gcwrite' intrinsic has the same semantics as a store + instruction, but may be replaced with substantially more complex code by the + garbage collector runtime, as needed. The 'llvm.gcwrite' intrinsic + may only be used in a function which specifies a GC + algorithm.

+ +
+ + + + +
+ +

These intrinsics are provided by LLVM to expose special features that may + only be implemented with code generator support.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i8  *@llvm.returnaddress(i32 <level>)
+
+ +
Overview:
+

The 'llvm.returnaddress' intrinsic attempts to compute a + target-specific value indicating the return address of the current function + or one of its callers.

+ +
Arguments:
+

The argument to this intrinsic indicates which function to return the address + for. Zero indicates the calling function, one indicates its caller, etc. + The argument is required to be a constant integer value.

+ +
Semantics:
+

The 'llvm.returnaddress' intrinsic either returns a pointer + indicating the return address of the specified call frame, or zero if it + cannot be identified. The value returned by this intrinsic is likely to be + incorrect or 0 for arguments other than zero, so it should only be used for + debugging purposes.

+ +

Note that calling this intrinsic does not prevent function inlining or other + aggressive transformations, so the value returned may not be that of the + obvious source-language caller.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i8* @llvm.frameaddress(i32 <level>)
+
+ +
Overview:
+

The 'llvm.frameaddress' intrinsic attempts to return the + target-specific frame pointer value for the specified stack frame.

+ +
Arguments:
+

The argument to this intrinsic indicates which function to return the frame + pointer for. Zero indicates the calling function, one indicates its caller, + etc. The argument is required to be a constant integer value.

+ +
Semantics:
+

The 'llvm.frameaddress' intrinsic either returns a pointer + indicating the frame address of the specified call frame, or zero if it + cannot be identified. The value returned by this intrinsic is likely to be + incorrect or 0 for arguments other than zero, so it should only be used for + debugging purposes.

+ +

Note that calling this intrinsic does not prevent function inlining or other + aggressive transformations, so the value returned may not be that of the + obvious source-language caller.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i8* @llvm.stacksave()
+
+ +
Overview:
+

The 'llvm.stacksave' intrinsic is used to remember the current state + of the function stack, for use + with llvm.stackrestore. This is + useful for implementing language features like scoped automatic variable + sized arrays in C99.

+ +
Semantics:
+

This intrinsic returns a opaque pointer value that can be passed + to llvm.stackrestore. When + an llvm.stackrestore intrinsic is executed with a value saved + from llvm.stacksave, it effectively restores the state of the stack + to the state it was in when the llvm.stacksave intrinsic executed. + In practice, this pops any alloca blocks from the + stack that were allocated after the llvm.stacksave was executed.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.stackrestore(i8* %ptr)
+
+ +
Overview:
+

The 'llvm.stackrestore' intrinsic is used to restore the state of + the function stack to the state it was in when the + corresponding llvm.stacksave intrinsic + executed. This is useful for implementing language features like scoped + automatic variable sized arrays in C99.

+ +
Semantics:
+

See the description + for llvm.stacksave.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.prefetch(i8* <address>, i32 <rw>, i32 <locality>)
+
+ +
Overview:
+

The 'llvm.prefetch' intrinsic is a hint to the code generator to + insert a prefetch instruction if supported; otherwise, it is a noop. + Prefetches have no effect on the behavior of the program but can change its + performance characteristics.

+ +
Arguments:
+

address is the address to be prefetched, rw is the + specifier determining if the fetch should be for a read (0) or write (1), + and locality is a temporal locality specifier ranging from (0) - no + locality, to (3) - extremely local keep in cache. The rw + and locality arguments must be constant integers.

+ +
Semantics:
+

This intrinsic does not modify the behavior of the program. In particular, + prefetches cannot trap and do not produce a value. On targets that support + this intrinsic, the prefetch can provide hints to the processor cache for + better performance.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.pcmarker(i32 <id>)
+
+ +
Overview:
+

The 'llvm.pcmarker' intrinsic is a method to export a Program + Counter (PC) in a region of code to simulators and other tools. The method + is target specific, but it is expected that the marker will use exported + symbols to transmit the PC of the marker. The marker makes no guarantees + that it will remain with any specific instruction after optimizations. It is + possible that the presence of a marker will inhibit optimizations. The + intended use is to be inserted after optimizations to allow correlations of + simulation runs.

+ +
Arguments:
+

id is a numerical id identifying the marker.

+ +
Semantics:
+

This intrinsic does not modify the behavior of the program. Backends that do + not support this intrinsic may ignore it.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i64 @llvm.readcyclecounter()
+
+ +
Overview:
+

The 'llvm.readcyclecounter' intrinsic provides access to the cycle + counter register (or similar low latency, high accuracy clocks) on those + targets that support it. On X86, it should map to RDTSC. On Alpha, it + should map to RPCC. As the backing counters overflow quickly (on the order + of 9 seconds on alpha), this should only be used for small timings.

+ +
Semantics:
+

When directly supported, reading the cycle counter should not modify any + memory. Implementations are allowed to either return a application specific + value or a system wide value. On backends without support, this is lowered + to a constant 0.

+ +
+ + + + +
+ +

LLVM provides intrinsics for a few important standard C library functions. + These intrinsics allow source-language front-ends to pass information about + the alignment of the pointer arguments to the code generator, providing + opportunity for more efficient code generation.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.memcpy on any + integer bit width and for different address spaces. Not all targets support + all bit widths however.

+ +
+  declare void @llvm.memcpy.p0i8.p0i8.i32(i8* <dest>, i8* <src>,
+                                          i32 <len>, i32 <align>, i1 <isvolatile>)
+  declare void @llvm.memcpy.p0i8.p0i8.i64(i8* <dest>, i8* <src>,
+                                          i64 <len>, i32 <align>, i1 <isvolatile>)
+
+ +
Overview:
+

The 'llvm.memcpy.*' intrinsics copy a block of memory from the + source location to the destination location.

+ +

Note that, unlike the standard libc function, the llvm.memcpy.* + intrinsics do not return a value, takes extra alignment/isvolatile arguments + and the pointers can be in specified address spaces.

+ +
Arguments:
+ +

The first argument is a pointer to the destination, the second is a pointer + to the source. The third argument is an integer argument specifying the + number of bytes to copy, the fourth argument is the alignment of the + source and destination locations, and the fifth is a boolean indicating a + volatile access.

+ +

If the call to this intrinsic has an alignment value that is not 0 or 1, + then the caller guarantees that both the source and destination pointers are + aligned to that boundary.

+ +

If the isvolatile parameter is true, the + llvm.memcpy call is a volatile operation. + The detailed access behavior is not very cleanly specified and it is unwise + to depend on it.

+ +
Semantics:
+ +

The 'llvm.memcpy.*' intrinsics copy a block of memory from the + source location to the destination location, which are not allowed to + overlap. It copies "len" bytes of memory over. If the argument is known to + be aligned to some boundary, this can be specified as the fourth argument, + otherwise it should be set to 0 or 1.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.memmove on any integer bit + width and for different address space. Not all targets support all bit + widths however.

+ +
+  declare void @llvm.memmove.p0i8.p0i8.i32(i8* <dest>, i8* <src>,
+                                           i32 <len>, i32 <align>, i1 <isvolatile>)
+  declare void @llvm.memmove.p0i8.p0i8.i64(i8* <dest>, i8* <src>,
+                                           i64 <len>, i32 <align>, i1 <isvolatile>)
+
+ +
Overview:
+

The 'llvm.memmove.*' intrinsics move a block of memory from the + source location to the destination location. It is similar to the + 'llvm.memcpy' intrinsic but allows the two memory locations to + overlap.

+ +

Note that, unlike the standard libc function, the llvm.memmove.* + intrinsics do not return a value, takes extra alignment/isvolatile arguments + and the pointers can be in specified address spaces.

+ +
Arguments:
+ +

The first argument is a pointer to the destination, the second is a pointer + to the source. The third argument is an integer argument specifying the + number of bytes to copy, the fourth argument is the alignment of the + source and destination locations, and the fifth is a boolean indicating a + volatile access.

+ +

If the call to this intrinsic has an alignment value that is not 0 or 1, + then the caller guarantees that the source and destination pointers are + aligned to that boundary.

+ +

If the isvolatile parameter is true, the + llvm.memmove call is a volatile operation. + The detailed access behavior is not very cleanly specified and it is unwise + to depend on it.

+ +
Semantics:
+ +

The 'llvm.memmove.*' intrinsics copy a block of memory from the + source location to the destination location, which may overlap. It copies + "len" bytes of memory over. If the argument is known to be aligned to some + boundary, this can be specified as the fourth argument, otherwise it should + be set to 0 or 1.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.memset on any integer bit + width and for different address spaces. However, not all targets support all + bit widths.

+ +
+  declare void @llvm.memset.p0i8.i32(i8* <dest>, i8 <val>,
+                                     i32 <len>, i32 <align>, i1 <isvolatile>)
+  declare void @llvm.memset.p0i8.i64(i8* <dest>, i8 <val>,
+                                     i64 <len>, i32 <align>, i1 <isvolatile>)
+
+ +
Overview:
+

The 'llvm.memset.*' intrinsics fill a block of memory with a + particular byte value.

+ +

Note that, unlike the standard libc function, the llvm.memset + intrinsic does not return a value and takes extra alignment/volatile + arguments. Also, the destination can be in an arbitrary address space.

+ +
Arguments:
+

The first argument is a pointer to the destination to fill, the second is the + byte value with which to fill it, the third argument is an integer argument + specifying the number of bytes to fill, and the fourth argument is the known + alignment of the destination location.

+ +

If the call to this intrinsic has an alignment value that is not 0 or 1, + then the caller guarantees that the destination pointer is aligned to that + boundary.

+ +

If the isvolatile parameter is true, the + llvm.memset call is a volatile operation. + The detailed access behavior is not very cleanly specified and it is unwise + to depend on it.

+ +
Semantics:
+

The 'llvm.memset.*' intrinsics fill "len" bytes of memory starting + at the destination location. If the argument is known to be aligned to some + boundary, this can be specified as the fourth argument, otherwise it should + be set to 0 or 1.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.sqrt on any + floating point or vector of floating point type. Not all targets support all + types however.

+ +
+  declare float     @llvm.sqrt.f32(float %Val)
+  declare double    @llvm.sqrt.f64(double %Val)
+  declare x86_fp80  @llvm.sqrt.f80(x86_fp80 %Val)
+  declare fp128     @llvm.sqrt.f128(fp128 %Val)
+  declare ppc_fp128 @llvm.sqrt.ppcf128(ppc_fp128 %Val)
+
+ +
Overview:
+

The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, + returning the same value as the libm 'sqrt' functions would. + Unlike sqrt in libm, however, llvm.sqrt has undefined + behavior for negative numbers other than -0.0 (which allows for better + optimization, because there is no need to worry about errno being + set). llvm.sqrt(-0.0) is defined to return -0.0 like IEEE sqrt.

+ +
Arguments:
+

The argument and return value are floating point numbers of the same + type.

+ +
Semantics:
+

This function returns the sqrt of the specified operand if it is a + nonnegative floating point number.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.powi on any + floating point or vector of floating point type. Not all targets support all + types however.

+ +
+  declare float     @llvm.powi.f32(float  %Val, i32 %power)
+  declare double    @llvm.powi.f64(double %Val, i32 %power)
+  declare x86_fp80  @llvm.powi.f80(x86_fp80  %Val, i32 %power)
+  declare fp128     @llvm.powi.f128(fp128 %Val, i32 %power)
+  declare ppc_fp128 @llvm.powi.ppcf128(ppc_fp128  %Val, i32 %power)
+
+ +
Overview:
+

The 'llvm.powi.*' intrinsics return the first operand raised to the + specified (positive or negative) power. The order of evaluation of + multiplications is not defined. When a vector of floating point type is + used, the second argument remains a scalar integer value.

+ +
Arguments:
+

The second argument is an integer power, and the first is a value to raise to + that power.

+ +
Semantics:
+

This function returns the first value raised to the second power with an + unspecified sequence of rounding operations.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.sin on any + floating point or vector of floating point type. Not all targets support all + types however.

+ +
+  declare float     @llvm.sin.f32(float  %Val)
+  declare double    @llvm.sin.f64(double %Val)
+  declare x86_fp80  @llvm.sin.f80(x86_fp80  %Val)
+  declare fp128     @llvm.sin.f128(fp128 %Val)
+  declare ppc_fp128 @llvm.sin.ppcf128(ppc_fp128  %Val)
+
+ +
Overview:
+

The 'llvm.sin.*' intrinsics return the sine of the operand.

+ +
Arguments:
+

The argument and return value are floating point numbers of the same + type.

+ +
Semantics:
+

This function returns the sine of the specified operand, returning the same + values as the libm sin functions would, and handles error conditions + in the same way.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.cos on any + floating point or vector of floating point type. Not all targets support all + types however.

+ +
+  declare float     @llvm.cos.f32(float  %Val)
+  declare double    @llvm.cos.f64(double %Val)
+  declare x86_fp80  @llvm.cos.f80(x86_fp80  %Val)
+  declare fp128     @llvm.cos.f128(fp128 %Val)
+  declare ppc_fp128 @llvm.cos.ppcf128(ppc_fp128  %Val)
+
+ +
Overview:
+

The 'llvm.cos.*' intrinsics return the cosine of the operand.

+ +
Arguments:
+

The argument and return value are floating point numbers of the same + type.

+ +
Semantics:
+

This function returns the cosine of the specified operand, returning the same + values as the libm cos functions would, and handles error conditions + in the same way.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.pow on any + floating point or vector of floating point type. Not all targets support all + types however.

+ +
+  declare float     @llvm.pow.f32(float  %Val, float %Power)
+  declare double    @llvm.pow.f64(double %Val, double %Power)
+  declare x86_fp80  @llvm.pow.f80(x86_fp80  %Val, x86_fp80 %Power)
+  declare fp128     @llvm.pow.f128(fp128 %Val, fp128 %Power)
+  declare ppc_fp128 @llvm.pow.ppcf128(ppc_fp128  %Val, ppc_fp128 Power)
+
+ +
Overview:
+

The 'llvm.pow.*' intrinsics return the first operand raised to the + specified (positive or negative) power.

+ +
Arguments:
+

The second argument is a floating point power, and the first is a value to + raise to that power.

+ +
Semantics:
+

This function returns the first value raised to the second power, returning + the same values as the libm pow functions would, and handles error + conditions in the same way.

+ +
+ + + + +
+ +

LLVM provides intrinsics for a few important bit manipulation operations. + These allow efficient code generation for some algorithms.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic function. You can use bswap on any integer + type that is an even number of bytes (i.e. BitWidth % 16 == 0).

+ +
+  declare i16 @llvm.bswap.i16(i16 <id>)
+  declare i32 @llvm.bswap.i32(i32 <id>)
+  declare i64 @llvm.bswap.i64(i64 <id>)
+
+ +
Overview:
+

The 'llvm.bswap' family of intrinsics is used to byte swap integer + values with an even number of bytes (positive multiple of 16 bits). These + are useful for performing operations on data that is not in the target's + native byte order.

+ +
Semantics:
+

The llvm.bswap.i16 intrinsic returns an i16 value that has the high + and low byte of the input i16 swapped. Similarly, + the llvm.bswap.i32 intrinsic returns an i32 value that has the four + bytes of the input i32 swapped, so that if the input bytes are numbered 0, 1, + 2, 3 then the returned i32 will have its bytes in 3, 2, 1, 0 order. + The llvm.bswap.i48, llvm.bswap.i64 and other intrinsics + extend this concept to additional even-byte lengths (6 bytes, 8 bytes and + more, respectively).

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.ctpop on any integer bit + width. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.ctpop.i8(i8  <src>)
+  declare i16 @llvm.ctpop.i16(i16 <src>)
+  declare i32 @llvm.ctpop.i32(i32 <src>)
+  declare i64 @llvm.ctpop.i64(i64 <src>)
+  declare i256 @llvm.ctpop.i256(i256 <src>)
+
+ +
Overview:
+

The 'llvm.ctpop' family of intrinsics counts the number of bits set + in a value.

+ +
Arguments:
+

The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

+ +
Semantics:
+

The 'llvm.ctpop' intrinsic counts the 1's in a variable.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.ctlz on any + integer bit width. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.ctlz.i8 (i8  <src>)
+  declare i16 @llvm.ctlz.i16(i16 <src>)
+  declare i32 @llvm.ctlz.i32(i32 <src>)
+  declare i64 @llvm.ctlz.i64(i64 <src>)
+  declare i256 @llvm.ctlz.i256(i256 <src>)
+
+ +
Overview:
+

The 'llvm.ctlz' family of intrinsic functions counts the number of + leading zeros in a variable.

+ +
Arguments:
+

The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

+ +
Semantics:
+

The 'llvm.ctlz' intrinsic counts the leading (most significant) + zeros in a variable. If the src == 0 then the result is the size in bits of + the type of src. For example, llvm.ctlz(i32 2) = 30.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.cttz on any + integer bit width. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.cttz.i8 (i8  <src>)
+  declare i16 @llvm.cttz.i16(i16 <src>)
+  declare i32 @llvm.cttz.i32(i32 <src>)
+  declare i64 @llvm.cttz.i64(i64 <src>)
+  declare i256 @llvm.cttz.i256(i256 <src>)
+
+ +
Overview:
+

The 'llvm.cttz' family of intrinsic functions counts the number of + trailing zeros.

+ +
Arguments:
+

The only argument is the value to be counted. The argument may be of any + integer type. The return type must match the argument type.

+ +
Semantics:
+

The 'llvm.cttz' intrinsic counts the trailing (least significant) + zeros in a variable. If the src == 0 then the result is the size in bits of + the type of src. For example, llvm.cttz(2) = 1.

+ +
+ + + + +
+ +

LLVM provides intrinsics for some arithmetic with overflow operations.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.sadd.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.sadd.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.sadd.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+

The 'llvm.sadd.with.overflow' family of intrinsic functions perform + a signed addition of the two arguments, and indicate whether an overflow + occurred during the signed summation.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed addition.

+ +
Semantics:
+

The 'llvm.sadd.with.overflow' family of intrinsic functions perform + a signed addition of the two variables. They return a structure — the + first element of which is the signed summation, and the second element of + which is a bit specifying if the signed summation resulted in an + overflow.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %overflow, label %normal
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.uadd.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.uadd.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.uadd.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+

The 'llvm.uadd.with.overflow' family of intrinsic functions perform + an unsigned addition of the two arguments, and indicate whether a carry + occurred during the unsigned summation.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned addition.

+ +
Semantics:
+

The 'llvm.uadd.with.overflow' family of intrinsic functions perform + an unsigned addition of the two arguments. They return a structure — + the first element of which is the sum, and the second element of which is a + bit specifying if the unsigned summation resulted in a carry.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %carry, label %normal
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.ssub.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+

The 'llvm.ssub.with.overflow' family of intrinsic functions perform + a signed subtraction of the two arguments, and indicate whether an overflow + occurred during the signed subtraction.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed subtraction.

+ +
Semantics:
+

The 'llvm.ssub.with.overflow' family of intrinsic functions perform + a signed subtraction of the two arguments. They return a structure — + the first element of which is the subtraction, and the second element of + which is a bit specifying if the signed subtraction resulted in an + overflow.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %overflow, label %normal
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.usub.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+

The 'llvm.usub.with.overflow' family of intrinsic functions perform + an unsigned subtraction of the two arguments, and indicate whether an + overflow occurred during the unsigned subtraction.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned subtraction.

+ +
Semantics:
+

The 'llvm.usub.with.overflow' family of intrinsic functions perform + an unsigned subtraction of the two arguments. They return a structure — + the first element of which is the subtraction, and the second element of + which is a bit specifying if the unsigned subtraction resulted in an + overflow.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %overflow, label %normal
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.smul.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.smul.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+ +

The 'llvm.smul.with.overflow' family of intrinsic functions perform + a signed multiplication of the two arguments, and indicate whether an + overflow occurred during the signed multiplication.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo signed multiplication.

+ +
Semantics:
+

The 'llvm.smul.with.overflow' family of intrinsic functions perform + a signed multiplication of the two arguments. They return a structure — + the first element of which is the multiplication, and the second element of + which is a bit specifying if the signed multiplication resulted in an + overflow.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %overflow, label %normal
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.umul.with.overflow + on any integer bit width.

+ +
+  declare {i16, i1} @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
+  declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
+  declare {i64, i1} @llvm.umul.with.overflow.i64(i64 %a, i64 %b)
+
+ +
Overview:
+

The 'llvm.umul.with.overflow' family of intrinsic functions perform + a unsigned multiplication of the two arguments, and indicate whether an + overflow occurred during the unsigned multiplication.

+ +
Arguments:
+

The arguments (%a and %b) and the first element of the result structure may + be of integer types of any bit width, but they must have the same bit + width. The second element of the result structure must be of + type i1. %a and %b are the two values that will + undergo unsigned multiplication.

+ +
Semantics:
+

The 'llvm.umul.with.overflow' family of intrinsic functions perform + an unsigned multiplication of the two arguments. They return a structure + — the first element of which is the multiplication, and the second + element of which is a bit specifying if the unsigned multiplication resulted + in an overflow.

+ +
Examples:
+
+  %res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
+  %sum = extractvalue {i32, i1} %res, 0
+  %obit = extractvalue {i32, i1} %res, 1
+  br i1 %obit, label %overflow, label %normal
+
+ +
+ + + + +
+ +

Half precision floating point is a storage-only format. This means that it is + a dense encoding (in memory) but does not support computation in the + format.

+ +

This means that code must first load the half-precision floating point + value as an i16, then convert it to float with llvm.convert.from.fp16. + Computation can then be performed on the float value (including extending to + double etc). To store the value back to memory, it is first converted to + float if needed, then converted to i16 with + llvm.convert.to.fp16, then + storing as an i16 value.

+
+ + + + +
+ +
Syntax:
+
+  declare i16 @llvm.convert.to.fp16(f32 %a)
+
+ +
Overview:
+

The 'llvm.convert.to.fp16' intrinsic function performs + a conversion from single precision floating point format to half precision + floating point format.

+ +
Arguments:
+

The intrinsic function contains single argument - the value to be + converted.

+ +
Semantics:
+

The 'llvm.convert.to.fp16' intrinsic function performs + a conversion from single precision floating point format to half precision + floating point format. The return value is an i16 which + contains the converted number.

+ +
Examples:
+
+  %res = call i16 @llvm.convert.to.fp16(f32 %a)
+  store i16 %res, i16* @x, align 2
+
+ +
+ + + + +
+ +
Syntax:
+
+  declare f32 @llvm.convert.from.fp16(i16 %a)
+
+ +
Overview:
+

The 'llvm.convert.from.fp16' intrinsic function performs + a conversion from half precision floating point format to single precision + floating point format.

+ +
Arguments:
+

The intrinsic function contains single argument - the value to be + converted.

+ +
Semantics:
+

The 'llvm.convert.from.fp16' intrinsic function performs a + conversion from half single precision floating point format to single + precision floating point format. The input half-float value is represented by + an i16 value.

+ +
Examples:
+
+  %a = load i16* @x, align 2
+  %res = call f32 @llvm.convert.from.fp16(i16 %a)
+
+ +
+ + + + +
+ +

The LLVM debugger intrinsics (which all start with llvm.dbg. + prefix), are described in + the LLVM Source + Level Debugging document.

+ +
+ + + + +
+ +

The LLVM exception handling intrinsics (which all start with + llvm.eh. prefix), are described in + the LLVM Exception + Handling document.

+ +
+ + + + +
+ +

This intrinsic makes it possible to excise one parameter, marked with + the nest attribute, from a function. + The result is a callable + function pointer lacking the nest parameter - the caller does not need to + provide a value for it. Instead, the value to use is stored in advance in a + "trampoline", a block of memory usually allocated on the stack, which also + contains code to splice the nest value into the argument list. This is used + to implement the GCC nested function address extension.

+ +

For example, if the function is + i32 f(i8* nest %c, i32 %x, i32 %y) then the resulting function + pointer has signature i32 (i32, i32)*. It can be created as + follows:

+ +
+  %tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
+  %tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0
+  %p = call i8* @llvm.init.trampoline(i8* %tramp1, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval)
+  %fp = bitcast i8* %p to i32 (i32, i32)*
+
+ +

The call %val = call i32 %fp(i32 %x, i32 %y) is then equivalent + to %val = call i32 %f(i8* %nval, i32 %x, i32 %y).

+ +
+ + + + +
+ +
Syntax:
+
+  declare i8* @llvm.init.trampoline(i8* <tramp>, i8* <func>, i8* <nval>)
+
+ +
Overview:
+

This fills the memory pointed to by tramp with code and returns a + function pointer suitable for executing it.

+ +
Arguments:
+

The llvm.init.trampoline intrinsic takes three arguments, all + pointers. The tramp argument must point to a sufficiently large and + sufficiently aligned block of memory; this memory is written to by the + intrinsic. Note that the size and the alignment are target-specific - LLVM + currently provides no portable way of determining them, so a front-end that + generates this intrinsic needs to have some target-specific knowledge. + The func argument must hold a function bitcast to + an i8*.

+ +
Semantics:
+

The block of memory pointed to by tramp is filled with target + dependent code, turning it into a function. A pointer to this function is + returned, but needs to be bitcast to an appropriate + function pointer type before being called. The new function's signature + is the same as that of func with any arguments marked with + the nest attribute removed. At most one such nest argument + is allowed, and it must be of pointer type. Calling the new function is + equivalent to calling func with the same argument list, but + with nval used for the missing nest argument. If, after + calling llvm.init.trampoline, the memory pointed to + by tramp is modified, then the effect of any later call to the + returned function pointer is undefined.

+ +
+ + + + +
+ +

These intrinsic functions expand the "universal IR" of LLVM to represent + hardware constructs for atomic operations and memory synchronization. This + provides an interface to the hardware, not an interface to the programmer. It + is aimed at a low enough level to allow any programming models or APIs + (Application Programming Interfaces) which need atomic behaviors to map + cleanly onto it. It is also modeled primarily on hardware behavior. Just as + hardware provides a "universal IR" for source languages, it also provides a + starting point for developing a "universal" atomic operation and + synchronization IR.

+ +

These do not form an API such as high-level threading libraries, + software transaction memory systems, atomic primitives, and intrinsic + functions as found in BSD, GNU libc, atomic_ops, APR, and other system and + application libraries. The hardware interface provided by LLVM should allow + a clean implementation of all of these APIs and parallel programming models. + No one model or paradigm should be selected above others unless the hardware + itself ubiquitously does so.

+ +
+ + + +
+
Syntax:
+
+  declare void @llvm.memory.barrier(i1 <ll>, i1 <ls>, i1 <sl>, i1 <ss>, i1 <device>)
+
+ +
Overview:
+

The llvm.memory.barrier intrinsic guarantees ordering between + specific pairs of memory access types.

+ +
Arguments:
+

The llvm.memory.barrier intrinsic requires five boolean arguments. + The first four arguments enables a specific barrier as listed below. The + fifth argument specifies that the barrier applies to io or device or uncached + memory.

+ +
    +
  • ll: load-load barrier
  • +
  • ls: load-store barrier
  • +
  • sl: store-load barrier
  • +
  • ss: store-store barrier
  • +
  • device: barrier applies to device and uncached memory also.
  • +
+ +
Semantics:
+

This intrinsic causes the system to enforce some ordering constraints upon + the loads and stores of the program. This barrier does not + indicate when any events will occur, it only enforces + an order in which they occur. For any of the specified pairs of load + and store operations (f.ex. load-load, or store-load), all of the first + operations preceding the barrier will complete before any of the second + operations succeeding the barrier begin. Specifically the semantics for each + pairing is as follows:

+ +
    +
  • ll: All loads before the barrier must complete before any load + after the barrier begins.
  • +
  • ls: All loads before the barrier must complete before any + store after the barrier begins.
  • +
  • ss: All stores before the barrier must complete before any + store after the barrier begins.
  • +
  • sl: All stores before the barrier must complete before any + load after the barrier begins.
  • +
+ +

These semantics are applied with a logical "and" behavior when more than one + is enabled in a single memory barrier intrinsic.

+ +

Backends may implement stronger barriers than those requested when they do + not support as fine grained a barrier as requested. Some architectures do + not need all types of barriers and on such architectures, these become + noops.

+ +
Example:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 4, %ptr
+
+%result1  = load i32* %ptr      ; yields {i32}:result1 = 4
+            call void @llvm.memory.barrier(i1 false, i1 true, i1 false, i1 false)
+                                ; guarantee the above finishes
+            store i32 8, %ptr   ; before this begins
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.atomic.cmp.swap on + any integer bit width and for different address spaces. Not all targets + support all bit widths however.

+ +
+  declare i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* <ptr>, i8 <cmp>, i8 <val>)
+  declare i16 @llvm.atomic.cmp.swap.i16.p0i16(i16* <ptr>, i16 <cmp>, i16 <val>)
+  declare i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* <ptr>, i32 <cmp>, i32 <val>)
+  declare i64 @llvm.atomic.cmp.swap.i64.p0i64(i64* <ptr>, i64 <cmp>, i64 <val>)
+
+ +
Overview:
+

This loads a value in memory and compares it to a given value. If they are + equal, it stores a new value into the memory.

+ +
Arguments:
+

The llvm.atomic.cmp.swap intrinsic takes three arguments. The result + as well as both cmp and val must be integer values with the + same bit width. The ptr argument must be a pointer to a value of + this integer type. While any bit width integer may be used, targets may only + lower representations they support in hardware.

+ +
Semantics:
+

This entire intrinsic must be executed atomically. It first loads the value + in memory pointed to by ptr and compares it with the + value cmp. If they are equal, val is stored into the + memory. The loaded value is yielded in all cases. This provides the + equivalent of an atomic compare-and-swap operation within the SSA + framework.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 4, %ptr
+
+%val1     = add i32 4, 4
+%result1  = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %ptr, i32 4, %val1)
+                                          ; yields {i32}:result1 = 4
+%stored1  = icmp eq i32 %result1, 4       ; yields {i1}:stored1 = true
+%memval1  = load i32* %ptr                ; yields {i32}:memval1 = 8
+
+%val2     = add i32 1, 1
+%result2  = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %ptr, i32 5, %val2)
+                                          ; yields {i32}:result2 = 8
+%stored2  = icmp eq i32 %result2, 5       ; yields {i1}:stored2 = false
+
+%memval2  = load i32* %ptr                ; yields {i32}:memval2 = 8
+
+ +
+ + + +
+
Syntax:
+ +

This is an overloaded intrinsic. You can use llvm.atomic.swap on any + integer bit width. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.atomic.swap.i8.p0i8(i8* <ptr>, i8 <val>)
+  declare i16 @llvm.atomic.swap.i16.p0i16(i16* <ptr>, i16 <val>)
+  declare i32 @llvm.atomic.swap.i32.p0i32(i32* <ptr>, i32 <val>)
+  declare i64 @llvm.atomic.swap.i64.p0i64(i64* <ptr>, i64 <val>)
+
+ +
Overview:
+

This intrinsic loads the value stored in memory at ptr and yields + the value from memory. It then stores the value in val in the memory + at ptr.

+ +
Arguments:
+

The llvm.atomic.swap intrinsic takes two arguments. Both + the val argument and the result must be integers of the same bit + width. The first argument, ptr, must be a pointer to a value of this + integer type. The targets may only lower integer representations they + support.

+ +
Semantics:
+

This intrinsic loads the value pointed to by ptr, yields it, and + stores val back into ptr atomically. This provides the + equivalent of an atomic swap operation within the SSA framework.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 4, %ptr
+
+%val1     = add i32 4, 4
+%result1  = call i32 @llvm.atomic.swap.i32.p0i32(i32* %ptr, i32 %val1)
+                                        ; yields {i32}:result1 = 4
+%stored1  = icmp eq i32 %result1, 4     ; yields {i1}:stored1 = true
+%memval1  = load i32* %ptr              ; yields {i32}:memval1 = 8
+
+%val2     = add i32 1, 1
+%result2  = call i32 @llvm.atomic.swap.i32.p0i32(i32* %ptr, i32 %val2)
+                                        ; yields {i32}:result2 = 8
+
+%stored2  = icmp eq i32 %result2, 8     ; yields {i1}:stored2 = true
+%memval2  = load i32* %ptr              ; yields {i32}:memval2 = 2
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.atomic.load.add on + any integer bit width. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.atomic.load.add.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.add.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.add.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.add.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
Overview:
+

This intrinsic adds delta to the value stored in memory + at ptr. It yields the original value at ptr.

+ +
Arguments:
+

The intrinsic takes two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

+ +
Semantics:
+

This intrinsic does a series of operations atomically. It first loads the + value stored at ptr. It then adds delta, stores the result + to ptr. It yields the original value stored at ptr.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 4, %ptr
+%result1  = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %ptr, i32 4)
+                                ; yields {i32}:result1 = 4
+%result2  = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %ptr, i32 2)
+                                ; yields {i32}:result2 = 8
+%result3  = call i32 @llvm.atomic.load.add.i32.p0i32(i32* %ptr, i32 5)
+                                ; yields {i32}:result3 = 10
+%memval1  = load i32* %ptr      ; yields {i32}:memval1 = 15
+
+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use llvm.atomic.load.sub on + any integer bit width and for different address spaces. Not all targets + support all bit widths however.

+ +
+  declare i8 @llvm.atomic.load.sub.i8.p0i32(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.sub.i16.p0i32(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.sub.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.sub.i64.p0i32(i64* <ptr>, i64 <delta>)
+
+ +
Overview:
+

This intrinsic subtracts delta to the value stored in memory at + ptr. It yields the original value at ptr.

+ +
Arguments:
+

The intrinsic takes two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

+ +
Semantics:
+

This intrinsic does a series of operations atomically. It first loads the + value stored at ptr. It then subtracts delta, stores the + result to ptr. It yields the original value stored + at ptr.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 8, %ptr
+%result1  = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %ptr, i32 4)
+                                ; yields {i32}:result1 = 8
+%result2  = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %ptr, i32 2)
+                                ; yields {i32}:result2 = 4
+%result3  = call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %ptr, i32 5)
+                                ; yields {i32}:result3 = 2
+%memval1  = load i32* %ptr      ; yields {i32}:memval1 = -3
+
+ +
+ + + + +
+ +
Syntax:
+

These are overloaded intrinsics. You can + use llvm.atomic.load_and, llvm.atomic.load_nand, + llvm.atomic.load_or, and llvm.atomic.load_xor on any integer + bit width and for different address spaces. Not all targets support all bit + widths however.

+ +
+  declare i8 @llvm.atomic.load.and.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.and.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.and.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.and.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.or.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.or.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.or.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.or.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.nand.i8.p0i32(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.nand.i16.p0i32(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.nand.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.nand.i64.p0i32(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.xor.i8.p0i32(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.xor.i16.p0i32(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.xor.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.xor.i64.p0i32(i64* <ptr>, i64 <delta>)
+
+ +
Overview:
+

These intrinsics bitwise the operation (and, nand, or, xor) delta to + the value stored in memory at ptr. It yields the original value + at ptr.

+ +
Arguments:
+

These intrinsics take two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

+ +
Semantics:
+

These intrinsics does a series of operations atomically. They first load the + value stored at ptr. They then do the bitwise + operation delta, store the result to ptr. They yield the + original value stored at ptr.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 0x0F0F, %ptr
+%result0  = call i32 @llvm.atomic.load.nand.i32.p0i32(i32* %ptr, i32 0xFF)
+                                ; yields {i32}:result0 = 0x0F0F
+%result1  = call i32 @llvm.atomic.load.and.i32.p0i32(i32* %ptr, i32 0xFF)
+                                ; yields {i32}:result1 = 0xFFFFFFF0
+%result2  = call i32 @llvm.atomic.load.or.i32.p0i32(i32* %ptr, i32 0F)
+                                ; yields {i32}:result2 = 0xF0
+%result3  = call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %ptr, i32 0F)
+                                ; yields {i32}:result3 = FF
+%memval1  = load i32* %ptr      ; yields {i32}:memval1 = F0
+
+ +
+ + + + +
+ +
Syntax:
+

These are overloaded intrinsics. You can use llvm.atomic.load_max, + llvm.atomic.load_min, llvm.atomic.load_umax, and + llvm.atomic.load_umin on any integer bit width and for different + address spaces. Not all targets support all bit widths however.

+ +
+  declare i8 @llvm.atomic.load.max.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.max.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.max.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.max.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.min.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.min.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.min.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.min.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.umax.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.umax.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.umax.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.umax.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
+  declare i8 @llvm.atomic.load.umin.i8.p0i8(i8* <ptr>, i8 <delta>)
+  declare i16 @llvm.atomic.load.umin.i16.p0i16(i16* <ptr>, i16 <delta>)
+  declare i32 @llvm.atomic.load.umin.i32.p0i32(i32* <ptr>, i32 <delta>)
+  declare i64 @llvm.atomic.load.umin.i64.p0i64(i64* <ptr>, i64 <delta>)
+
+ +
Overview:
+

These intrinsics takes the signed or unsigned minimum or maximum of + delta and the value stored in memory at ptr. It yields the + original value at ptr.

+ +
Arguments:
+

These intrinsics take two arguments, the first a pointer to an integer value + and the second an integer value. The result is also an integer value. These + integer types can have any bit width, but they must all have the same bit + width. The targets may only lower integer representations they support.

+ +
Semantics:
+

These intrinsics does a series of operations atomically. They first load the + value stored at ptr. They then do the signed or unsigned min or + max delta and the value, store the result to ptr. They + yield the original value stored at ptr.

+ +
Examples:
+
+%mallocP  = tail call i8* @malloc(i32 ptrtoint (i32* getelementptr (i32* null, i32 1) to i32))
+%ptr      = bitcast i8* %mallocP to i32*
+            store i32 7, %ptr
+%result0  = call i32 @llvm.atomic.load.min.i32.p0i32(i32* %ptr, i32 -2)
+                                ; yields {i32}:result0 = 7
+%result1  = call i32 @llvm.atomic.load.max.i32.p0i32(i32* %ptr, i32 8)
+                                ; yields {i32}:result1 = -2
+%result2  = call i32 @llvm.atomic.load.umin.i32.p0i32(i32* %ptr, i32 10)
+                                ; yields {i32}:result2 = 8
+%result3  = call i32 @llvm.atomic.load.umax.i32.p0i32(i32* %ptr, i32 30)
+                                ; yields {i32}:result3 = 8
+%memval1  = load i32* %ptr      ; yields {i32}:memval1 = 30
+
+ +
+ + + + + +
+ +

This class of intrinsics exists to information about the lifetime of memory + objects and ranges where variables are immutable.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.lifetime.start(i64 <size>, i8* nocapture <ptr>)
+
+ +
Overview:
+

The 'llvm.lifetime.start' intrinsic specifies the start of a memory + object's lifetime.

+ +
Arguments:
+

The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

+ +
Semantics:
+

This intrinsic indicates that before this point in the code, the value of the + memory pointed to by ptr is dead. This means that it is known to + never be used and has an undefined value. A load from the pointer that + precedes this intrinsic can be replaced with + 'undef'.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.lifetime.end(i64 <size>, i8* nocapture <ptr>)
+
+ +
Overview:
+

The 'llvm.lifetime.end' intrinsic specifies the end of a memory + object's lifetime.

+ +
Arguments:
+

The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

+ +
Semantics:
+

This intrinsic indicates that after this point in the code, the value of the + memory pointed to by ptr is dead. This means that it is known to + never be used and has an undefined value. Any stores into the memory object + following this intrinsic may be removed as dead. + +

+ + + + +
+ +
Syntax:
+
+  declare {}* @llvm.invariant.start(i64 <size>, i8* nocapture <ptr>)
+
+ +
Overview:
+

The 'llvm.invariant.start' intrinsic specifies that the contents of + a memory object will not change.

+ +
Arguments:
+

The first argument is a constant integer representing the size of the + object, or -1 if it is variable sized. The second argument is a pointer to + the object.

+ +
Semantics:
+

This intrinsic indicates that until an llvm.invariant.end that uses + the return value, the referenced memory location is constant and + unchanging.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.invariant.end({}* <start>, i64 <size>, i8* nocapture <ptr>)
+
+ +
Overview:
+

The 'llvm.invariant.end' intrinsic specifies that the contents of + a memory object are mutable.

+ +
Arguments:
+

The first argument is the matching llvm.invariant.start intrinsic. + The second argument is a constant integer representing the size of the + object, or -1 if it is variable sized and the third argument is a pointer + to the object.

+ +
Semantics:
+

This intrinsic indicates that the memory is mutable again.

+ +
+ + + + +
+ +

This class of intrinsics is designed to be generic and has no specific + purpose.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.var.annotation(i8* <val>, i8* <str>, i8* <str>, i32  <int>)
+
+ +
Overview:
+

The 'llvm.var.annotation' intrinsic.

+ +
Arguments:
+

The first argument is a pointer to a value, the second is a pointer to a + global string, the third is a pointer to a global string which is the source + file name, and the last argument is the line number.

+ +
Semantics:
+

This intrinsic allows annotation of local variables with arbitrary strings. + This can be useful for special purpose optimizations that want to look for + these annotations. These have no other defined use, they are ignored by code + generation and optimization.

+ +
+ + + + +
+ +
Syntax:
+

This is an overloaded intrinsic. You can use 'llvm.annotation' on + any integer bit width.

+ +
+  declare i8 @llvm.annotation.i8(i8 <val>, i8* <str>, i8* <str>, i32  <int>)
+  declare i16 @llvm.annotation.i16(i16 <val>, i8* <str>, i8* <str>, i32  <int>)
+  declare i32 @llvm.annotation.i32(i32 <val>, i8* <str>, i8* <str>, i32  <int>)
+  declare i64 @llvm.annotation.i64(i64 <val>, i8* <str>, i8* <str>, i32  <int>)
+  declare i256 @llvm.annotation.i256(i256 <val>, i8* <str>, i8* <str>, i32  <int>)
+
+ +
Overview:
+

The 'llvm.annotation' intrinsic.

+ +
Arguments:
+

The first argument is an integer value (result of some expression), the + second is a pointer to a global string, the third is a pointer to a global + string which is the source file name, and the last argument is the line + number. It returns the value of the first argument.

+ +
Semantics:
+

This intrinsic allows annotations to be put on arbitrary expressions with + arbitrary strings. This can be useful for special purpose optimizations that + want to look for these annotations. These have no other defined use, they + are ignored by code generation and optimization.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.trap()
+
+ +
Overview:
+

The 'llvm.trap' intrinsic.

+ +
Arguments:
+

None.

+ +
Semantics:
+

This intrinsics is lowered to the target dependent trap instruction. If the + target does not have a trap instruction, this intrinsic will be lowered to + the call of the abort() function.

+ +
+ + + + +
+ +
Syntax:
+
+  declare void @llvm.stackprotector(i8* <guard>, i8** <slot>)
+
+ +
Overview:
+

The llvm.stackprotector intrinsic takes the guard and + stores it onto the stack at slot. The stack slot is adjusted to + ensure that it is placed on the stack before local variables.

+ +
Arguments:
+

The llvm.stackprotector intrinsic requires two pointer + arguments. The first argument is the value loaded from the stack + guard @__stack_chk_guard. The second variable is an alloca + that has enough space to hold the value of the guard.

+ +
Semantics:
+

This intrinsic causes the prologue/epilogue inserter to force the position of + the AllocaInst stack slot to be before local variables on the + stack. This is to ensure that if a local variable on the stack is + overwritten, it will destroy the value of the guard. When the function exits, + the guard on the stack is checked against the original guard. If they are + different, then the program aborts by calling the __stack_chk_fail() + function.

+ +
+ + + + +
+ +
Syntax:
+
+  declare i32 @llvm.objectsize.i32(i8* <object>, i1 <type>)
+  declare i64 @llvm.objectsize.i64(i8* <object>, i1 <type>)
+
+ +
Overview:
+

The llvm.objectsize intrinsic is designed to provide information to + the optimizers to determine at compile time whether a) an operation (like + memcpy) will overflow a buffer that corresponds to an object, or b) that a + runtime check for overflow isn't necessary. An object in this context means + an allocation of a specific class, structure, array, or other object.

+ +
Arguments:
+

The llvm.objectsize intrinsic takes two arguments. The first + argument is a pointer to or into the object. The second argument + is a boolean 0 or 1. This argument determines whether you want the + maximum (0) or minimum (1) bytes remaining. This needs to be a literal 0 or + 1, variables are not allowed.

+ +
Semantics:
+

The llvm.objectsize intrinsic is lowered to either a constant + representing the size of the object concerned, or i32/i64 -1 or 0, + depending on the type argument, if the size cannot be determined at + compile time.

+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/Lexicon.html b/final/docs/Lexicon.html new file mode 100644 index 00000000000..82a58aa1482 --- /dev/null +++ b/final/docs/Lexicon.html @@ -0,0 +1,277 @@ + + + + + The LLVM Lexicon + + + + + +
The LLVM Lexicon
+

NOTE: This document is a work in progress!

+ +
Table Of Contents
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- A -
ADCE
- B -
BURS
- C -
CSE
- D -
DAGDerived PointerDSADSE
- G -
GC
- I -
IPAIPOISel
- L -
LCSSALICMLoad-VNLTO
- M -
MC
- O -
Object Pointer
- P -
PRE
- R -
RAUWReassociationRoot
- S -
Safe PointSCCSCCPSDISelSRoAStack Map
+
+ + +
Definitions
+ + + +
+
+
ADCE
+
Aggressive Dead Code Elimination
+
+
+ + +
+
+
BURS
+
Bottom Up Rewriting System—A method of instruction selection for + code generation. An example is the BURG tool.
+
+
+ + +
+
+
CSE
+
Common Subexpression Elimination. An optimization that removes common + subexpression compuation. For example (a+b)*(a+b) has two + subexpressions that are the same: (a+b). This optimization would + perform the addition only once and then perform the multiply (but only if + it's compulationally correct/safe). +
+
+ + +
+
+
DAG
+
Directed Acyclic Graph
+
Derived Pointer
+
A pointer to the interior of an object, such that a garbage collector + is unable to use the pointer for reachability analysis. While a derived + pointer is live, the corresponding object pointer must be kept in a root, + otherwise the collector might free the referenced object. With copying + collectors, derived pointers pose an additional hazard that they may be + invalidated at any safe point. This term is used in + opposition to object pointer.
+
DSA
+
Data Structure Analysis
+
DSE
+
Dead Store Elimination
+
+
+ + +
+
+
GC
+
Garbage Collection. The practice of using reachability analysis instead + of explicit memory management to reclaim unused memory.
+
+
+ + +
+
+
Heap
+
In garbage collection, the region of memory which is managed using + reachability analysis.
+
+
+ + +
+
+
IPA
+
Inter-Procedural Analysis. Refers to any variety of code analysis that + occurs between procedures, functions or compilation units (modules).
+
IPO
+
Inter-Procedural Optimization. Refers to any variety of code + optimization that occurs between procedures, functions or compilation units + (modules).
+
ISel
+
Instruction Selection.
+
+
+ + +
+
+
LCSSA
+
Loop-Closed Static Single Assignment Form
+
LICM
+
Loop Invariant Code Motion
+
Load-VN
+
Load Value Numbering
+
LTO
+
Link-Time Optimization
+
+
+ + +
+
+
MC
+
Machine Code
+
+
+ + +
+
+
Object Pointer
+
A pointer to an object such that the garbage collector is able to trace + references contained within the object. This term is used in opposition to + derived pointer.
+
+
+ + + +
+
+
PRE
+
Partial Redundancy Elimination
+
+
+ + + +
+
+
RAUW
An abbreviation for Replace + All Uses With. The functions User::replaceUsesOfWith(), + Value::replaceAllUsesWith(), and Constant::replaceUsesOfWithOnConstant() + implement the replacement of one Value with another by iterating over its + def/use chain and fixing up all of the pointers to point to the new value. + See also def/use chains. +
+
Reassociation
Rearranging + associative expressions to promote better redundancy elimination and other + optimization. For example, changing (A+B-A) into (B+A-A), permitting it to + be optimized into (B+0) then (B).
+
Root
In garbage collection, a + pointer variable lying outside of the heap from which + the collector begins its reachability analysis. In the context of code + generation, "root" almost always refers to a "stack root" -- a local or + temporary variable within an executing function.
+
+
+ + + +
+
+
Safe Point
+
In garbage collection, it is necessary to identify stack + roots so that reachability analysis may proceed. It may be infeasible to + provide this information for every instruction, so instead the information + may is calculated only at designated safe points. With a copying collector, + derived pointers must not be retained across + safe points and object pointers must be + reloaded from stack roots.
+
SDISel
+
Selection DAG Instruction Selection.
+
SCC
+
Strongly Connected Component
+
SCCP
+
Sparse Conditional Constant Propagation
+
SRoA
+
Scalar Replacement of Aggregates
+
SSA
+
Static Single Assignment
+
Stack Map
+
In garbage collection, metadata emitted by the code generator which + identifies roots within the stack frame of an executing + function.
+
+
+ +
+
Valid CSSValid HTML 4.01The LLVM Team
+The LLVM Compiler Infrastructure
+Last modified: $Date$ +
+ + + diff --git a/final/docs/LinkTimeOptimization.html b/final/docs/LinkTimeOptimization.html new file mode 100644 index 00000000000..dbe8f389ce8 --- /dev/null +++ b/final/docs/LinkTimeOptimization.html @@ -0,0 +1,390 @@ + + + + LLVM Link Time Optimization: Design and Implementation + + + +
+ LLVM Link Time Optimization: Design and Implementation +
+ + + +
+

Written by Devang Patel and Nick Kledzik

+
+ + + + + +
+

+LLVM features powerful intermodular optimizations which can be used at link +time. Link Time Optimization (LTO) is another name for intermodular optimization +when performed during the link stage. This document describes the interface +and design between the LTO optimizer and the linker.

+
+ + + + + +
+

+The LLVM Link Time Optimizer provides complete transparency, while doing +intermodular optimization, in the compiler tool chain. Its main goal is to let +the developer take advantage of intermodular optimizations without making any +significant changes to the developer's makefiles or build system. This is +achieved through tight integration with the linker. In this model, the linker +treates LLVM bitcode files like native object files and allows mixing and +matching among them. The linker uses libLTO, a shared +object, to handle LLVM bitcode files. This tight integration between +the linker and LLVM optimizer helps to do optimizations that are not possible +in other models. The linker input allows the optimizer to avoid relying on +conservative escape analysis. +

+
+ + + + +
+

The following example illustrates the advantages of LTO's integrated + approach and clean interface. This example requires a system linker which + supports LTO through the interface described in this document. Here, + llvm-gcc transparently invokes system linker.

+
    +
  • Input source file a.c is compiled into LLVM bitcode form. +
  • Input source file main.c is compiled into native object code. +
+
+--- a.h ---
+extern int foo1(void);
+extern void foo2(void);
+extern void foo4(void);
+--- a.c ---
+#include "a.h"
+
+static signed int i = 0;
+
+void foo2(void) {
+ i = -1;
+}
+
+static int foo3() {
+foo4();
+return 10;
+}
+
+int foo1(void) {
+int data = 0;
+
+if (i < 0) { data = foo3(); }
+
+data = data + 42;
+return data;
+}
+
+--- main.c ---
+#include <stdio.h>
+#include "a.h"
+
+void foo4(void) {
+ printf ("Hi\n");
+}
+
+int main() {
+ return foo1();
+}
+
+--- command lines ---
+$ llvm-gcc --emit-llvm -c a.c -o a.o  # <-- a.o is LLVM bitcode file
+$ llvm-gcc -c main.c -o main.o # <-- main.o is native object file
+$ llvm-gcc a.o main.o -o main # <-- standard link command without any modifications
+
+

In this example, the linker recognizes that foo2() is an + externally visible symbol defined in LLVM bitcode file. The linker completes + its usual symbol resolution + pass and finds that foo2() is not used anywhere. This information + is used by the LLVM optimizer and it removes foo2(). As soon as + foo2() is removed, the optimizer recognizes that condition + i < 0 is always false, which means foo3() is never + used. Hence, the optimizer removes foo3(), also. And this in turn, + enables linker to remove foo4(). This example illustrates the + advantage of tight integration with the linker. Here, the optimizer can not + remove foo3() without the linker's input. +

+
+ + + + +
+
+
Compiler driver invokes link time optimizer separately.
+
In this model the link time optimizer is not able to take advantage of + information collected during the linker's normal symbol resolution phase. + In the above example, the optimizer can not remove foo2() without + the linker's input because it is externally visible. This in turn prohibits + the optimizer from removing foo3().
+
Use separate tool to collect symbol information from all object + files.
+
In this model, a new, separate, tool or library replicates the linker's + capability to collect information for link time optimization. Not only is + this code duplication difficult to justify, but it also has several other + disadvantages. For example, the linking semantics and the features + provided by the linker on various platform are not unique. This means, + this new tool needs to support all such features and platforms in one + super tool or a separate tool per platform is required. This increases + maintenance cost for link time optimizer significantly, which is not + necessary. This approach also requires staying synchronized with linker + developements on various platforms, which is not the main focus of the link + time optimizer. Finally, this approach increases end user's build time due + to the duplication of work done by this separate tool and the linker itself. +
+
+
+ + + + +
+

The linker collects information about symbol defininitions and uses in + various link objects which is more accurate than any information collected + by other tools during typical build cycles. The linker collects this + information by looking at the definitions and uses of symbols in native .o + files and using symbol visibility information. The linker also uses + user-supplied information, such as a list of exported symbols. LLVM + optimizer collects control flow information, data flow information and knows + much more about program structure from the optimizer's point of view. + Our goal is to take advantage of tight integration between the linker and + the optimizer by sharing this information during various linking phases. +

+
+ + + + +
+

The linker first reads all object files in natural order and collects + symbol information. This includes native object files as well as LLVM bitcode + files. To minimize the cost to the linker in the case that all .o files + are native object files, the linker only calls lto_module_create() + when a supplied object file is found to not be a native object file. If + lto_module_create() returns that the file is an LLVM bitcode file, + the linker + then iterates over the module using lto_module_get_symbol_name() and + lto_module_get_symbol_attribute() to get all symbols defined and + referenced. + This information is added to the linker's global symbol table. +

+

The lto* functions are all implemented in a shared object libLTO. This + allows the LLVM LTO code to be updated independently of the linker tool. + On platforms that support it, the shared object is lazily loaded. +

+
+ + + + +
+

In this stage, the linker resolves symbols using global symbol table. + It may report undefined symbol errors, read archive members, replace + weak symbols, etc. The linker is able to do this seamlessly even though it + does not know the exact content of input LLVM bitcode files. If dead code + stripping is enabled then the linker collects the list of live symbols. +

+
+ + + +
+

After symbol resolution, the linker tells the LTO shared object which + symbols are needed by native object files. In the example above, the linker + reports that only foo1() is used by native object files using + lto_codegen_add_must_preserve_symbol(). Next the linker invokes + the LLVM optimizer and code generators using lto_codegen_compile() + which returns a native object file creating by merging the LLVM bitcode files + and applying various optimization passes. +

+
+ + + + +
+

In this phase, the linker reads optimized a native object file and + updates the internal global symbol table to reflect any changes. The linker + also collects information about any changes in use of external symbols by + LLVM bitcode files. In the example above, the linker notes that + foo4() is not used any more. If dead code stripping is enabled then + the linker refreshes the live symbol information appropriately and performs + dead code stripping.

+

After this phase, the linker continues linking as if it never saw LLVM + bitcode files.

+
+ + +
+libLTO +
+ +
+

libLTO is a shared object that is part of the LLVM tools, and + is intended for use by a linker. libLTO provides an abstract C + interface to use the LLVM interprocedural optimizer without exposing details + of LLVM's internals. The intention is to keep the interface as stable as + possible even when the LLVM optimizer continues to evolve. It should even + be possible for a completely different compilation technology to provide + a different libLTO that works with their object files and the standard + linker tool.

+
+ + + + +
+ +

A non-native object file is handled via an lto_module_t. +The following functions allow the linker to check if a file (on disk +or in a memory buffer) is a file which libLTO can process:

+ +
+lto_module_is_object_file(const char*)
+lto_module_is_object_file_for_target(const char*, const char*)
+lto_module_is_object_file_in_memory(const void*, size_t)
+lto_module_is_object_file_in_memory_for_target(const void*, size_t, const char*)
+
+ +

If the object file can be processed by libLTO, the linker creates a +lto_module_t by using one of

+ +
+lto_module_create(const char*)
+lto_module_create_from_memory(const void*, size_t)
+
+ +

and when done, the handle is released via

+ +
+lto_module_dispose(lto_module_t)
+
+ +

The linker can introspect the non-native object file by getting the number of +symbols and getting the name and attributes of each symbol via:

+ +
+lto_module_get_num_symbols(lto_module_t)
+lto_module_get_symbol_name(lto_module_t, unsigned int)
+lto_module_get_symbol_attribute(lto_module_t, unsigned int)
+
+ +

The attributes of a symbol include the alignment, visibility, and kind.

+
+ + + + +
+ +

Once the linker has loaded each non-native object files into an +lto_module_t, it can request libLTO to process them all and +generate a native object file. This is done in a couple of steps. +First, a code generator is created with:

+ +
lto_codegen_create()
+ +

Then, each non-native object file is added to the code generator with:

+ +
+lto_codegen_add_module(lto_code_gen_t, lto_module_t)
+
+ +

The linker then has the option of setting some codegen options. Whether or +not to generate DWARF debug info is set with:

+ +
lto_codegen_set_debug_model(lto_code_gen_t)
+ +

Which kind of position independence is set with:

+ +
lto_codegen_set_pic_model(lto_code_gen_t) 
+ +

And each symbol that is referenced by a native object file or otherwise must +not be optimized away is set with:

+ +
+lto_codegen_add_must_preserve_symbol(lto_code_gen_t, const char*)
+
+ +

After all these settings are done, the linker requests that a native object +file be created from the modules with the settings using:

+ +
lto_codegen_compile(lto_code_gen_t, size*)
+ +

which returns a pointer to a buffer containing the generated native +object file. The linker then parses that and links it with the rest +of the native object files.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Devang Patel and Nick Kledzik
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + + diff --git a/final/docs/Makefile b/final/docs/Makefile new file mode 100644 index 00000000000..389fd90a485 --- /dev/null +++ b/final/docs/Makefile @@ -0,0 +1,130 @@ +##===- docs/Makefile ---------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := .. +DIRS := CommandGuide tutorial + +ifdef BUILD_FOR_WEBSITE +PROJ_OBJ_DIR = . +DOXYGEN = doxygen + +$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in + cat $< | sed \ + -e 's/@abs_top_srcdir@/../g' \ + -e 's/@DOT@/dot/g' \ + -e 's/@PACKAGE_VERSION@/mainline/' \ + -e 's/@abs_top_builddir@/../g' > $@ +endif + +include $(LEVEL)/Makefile.common + +HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \ + $(wildcard $(PROJ_SRC_DIR)/*.css) +IMAGES := $(wildcard $(PROJ_SRC_DIR)/img/*.*) +DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \ + doxygen.intro +EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide img + +.PHONY: install-html install-doxygen doxygen install-ocamldoc ocamldoc generated + +install_targets := install-html +ifeq ($(ENABLE_DOXYGEN),1) +install_targets += install-doxygen +endif +ifdef OCAMLDOC +ifneq (,$(filter ocaml,$(BINDINGS_TO_BUILD))) +install_targets += install-ocamldoc +endif +endif +install-local:: $(install_targets) + +generated_targets := doxygen +ifdef OCAMLDOC +generated_targets += ocamldoc +endif + +# Live documentation is generated for the web site using this target: +# 'make generated BUILD_FOR_WEBSITE=1' +generated:: $(generated_targets) + +install-html: $(PROJ_OBJ_DIR)/html.tar.gz + $(Echo) Installing HTML documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(HTML) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(DataInstall) $(IMAGES) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(DESTDIR)$(PROJ_docsdir) + +$(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) + $(Echo) Packaging HTML documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar + $(Verb) cd $(PROJ_SRC_DIR) && \ + $(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/html.tar + +install-doxygen: doxygen + $(Echo) Installing doxygen documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \; + +doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz + +regendoc: + $(Echo) Building doxygen documentation + $(Verb) if test -e $(PROJ_OBJ_DIR)/doxygen ; then \ + $(RM) -rf $(PROJ_OBJ_DIR)/doxygen ; \ + fi + $(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg + +$(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg + $(Echo) Packaging doxygen documentation + $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/doxygen.tar doxygen + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/doxygen.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_OBJ_DIR)/doxygen/html/ + +userloc: $(LLVM_SRC_ROOT)/docs/userloc.html + +$(LLVM_SRC_ROOT)/docs/userloc.html: + $(Echo) Making User LOC Table + $(Verb) cd $(LLVM_SRC_ROOT) ; ./utils/userloc.pl -details -recurse \ + -html lib include tools runtime utils examples autoconf test > docs/userloc.html + +install-ocamldoc: ocamldoc + $(Echo) Installing ocamldoc documentation + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(DESTDIR)$(PROJ_docsdir) + $(Verb) cd $(PROJ_OBJ_DIR)/ocamldoc && \ + $(FIND) . -type f -exec \ + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html \; + +ocamldoc: regen-ocamldoc + $(Echo) Packaging ocamldoc documentation + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc.tar* + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc + $(Verb) $(GZIPBIN) $(PROJ_OBJ_DIR)/ocamldoc.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/ + +regen-ocamldoc: + $(Echo) Building ocamldoc documentation + $(Verb) if test -e $(PROJ_OBJ_DIR)/ocamldoc ; then \ + $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc ; \ + fi + $(Verb) $(MAKE) -C $(LEVEL)/bindings/ocaml ocamldoc + $(Verb) $(MKDIR) $(PROJ_OBJ_DIR)/ocamldoc/html + $(Verb) \ + $(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \ + `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'` + +uninstall-local:: + $(Echo) Uninstalling Documentation + $(Verb) $(RM) -rf $(DESTDIR)$(PROJ_docsdir) diff --git a/final/docs/MakefileGuide.html b/final/docs/MakefileGuide.html new file mode 100644 index 00000000000..2ef0954a8bb --- /dev/null +++ b/final/docs/MakefileGuide.html @@ -0,0 +1,1034 @@ + + + + + LLVM Makefile Guide + + + + +
LLVM Makefile Guide
+ +
    +
  1. Introduction
  2. +
  3. General Concepts +
      +
    1. Projects
    2. +
    3. Variable Values
    4. +
    5. Including Makefiles +
        +
      1. Makefile
      2. +
      3. Makefile.common
      4. +
      5. Makefile.config
      6. +
      7. Makefile.rules
      8. +
      +
    6. +
    7. Comments
    8. +
    +
  4. +
  5. Tutorial +
      +
    1. Libraries +
        +
      1. Bitcode Modules
      2. +
      3. Loadable Modules
      4. +
      +
    2. +
    3. Tools +
        +
      1. JIT Tools
      2. +
      +
    4. +
    5. Projects
    6. +
    +
  6. +
  7. Targets Supported +
      +
    1. all
    2. +
    3. all-local
    4. +
    5. check
    6. +
    7. check-local
    8. +
    9. clean
    10. +
    11. clean-local
    12. +
    13. dist
    14. +
    15. dist-check
    16. +
    17. dist-clean
    18. +
    19. install
    20. +
    21. preconditions
    22. +
    23. printvars
    24. +
    25. reconfigure
    26. +
    27. spotless
    28. +
    29. tags
    30. +
    31. uninstall
    32. +
    +
  8. +
  9. Using Variables +
      +
    1. Control Variables
    2. +
    3. Override Variables
    4. +
    5. Readable Variables
    6. +
    7. Internal Variables
    8. +
    +
  10. +
+ +
+

Written by Reid Spencer

+
+ + + + + +
+

This document provides usage information about the LLVM makefile + system. While loosely patterned after the BSD makefile system, LLVM has taken + a departure from BSD in order to implement additional features needed by LLVM. + Although makefile systems such as automake were attempted at one point, it + has become clear that the features needed by LLVM and the Makefile norm are + too great to use a more limited tool. Consequently, LLVM requires simply GNU + Make 3.79, a widely portable makefile processor. LLVM unabashedly makes heavy + use of the features of GNU Make so the dependency on GNU Make is firm. If + you're not familiar with make, it is recommended that you read the + GNU Makefile + Manual.

+

While this document is rightly part of the + LLVM Programmer's Manual, it is treated + separately here because of the volume of content and because it is often an + early source of bewilderment for new developers.

+
+ + + + + +
+

The LLVM Makefile System is the component of LLVM that is responsible for + building the software, testing it, generating distributions, checking those + distributions, installing and uninstalling, etc. It consists of a several + files throughout the source tree. These files and other general concepts are + described in this section.

+
+ + + +
+

The LLVM Makefile System is quite generous. It not only builds its own + software, but it can build yours too. Built into the system is knowledge of + the llvm/projects directory. Any directory under projects + that has both a configure script and a Makefile is assumed + to be a project that uses the LLVM Makefile system. Building software that + uses LLVM does not require the LLVM Makefile System nor even placement in the + llvm/projects directory. However, doing so will allow your project + to get up and running quickly by utilizing the built-in features that are used + to compile LLVM. LLVM compiles itself using the same features of the makefile + system as used for projects.

+

For complete details on setting up your projects configuration, simply + mimic the llvm/projects/sample project or for further details, + consult the Projects.html page.

+
+ + + +
+

To use the makefile system, you simply create a file named + Makefile in your directory and declare values for certain variables. + The variables and values that you select determine what the makefile system + will do. These variables enable rules and processing in the makefile system + that automatically Do The Right Thing™. +

+ + + +
+

Setting variables alone is not enough. You must include into your Makefile + additional files that provide the rules of the LLVM Makefile system. The + various files involved are described in the sections that follow.

+
+ + + +
+

Each directory to participate in the build needs to have a file named + Makefile. This is the file first read by make. It has three + sections:

+
    +
  1. Settable Variables - Required that must be set + first.
  2. +
  3. include $(LEVEL)/Makefile.common + - include the LLVM Makefile system. +
  4. Override Variables - Override variables set by + the LLVM Makefile system. +
+
+ + + +
+

Every project must have a Makefile.common file at its top source + directory. This file serves three purposes:

+
    +
  1. It includes the project's configuration makefile to obtain values + determined by the configure script. This is done by including the + $(LEVEL)/Makefile.config file.
  2. +
  3. It specifies any other (static) values that are needed throughout the + project. Only values that are used in all or a large proportion of the + project's directories should be placed here.
  4. +
  5. It includes the standard rules for the LLVM Makefile system, + $(LLVM_SRC_ROOT)/Makefile.rules. + This file is the "guts" of the LLVM Makefile system.
  6. +
+
+ + + +
+

Every project must have a Makefile.config at the top of its + build directory. This file is generated by the + configure script from the pattern provided by the + Makefile.config.in file located at the top of the project's + source directory. The contents of this file depend largely on what + configuration items the project uses, however most projects can get what they + need by just relying on LLVM's configuration found in + $(LLVM_OBJ_ROOT)/Makefile.config. +

+ + + +
+

This file, located at $(LLVM_SRC_ROOT)/Makefile.rules is the heart + of the LLVM Makefile System. It provides all the logic, dependencies, and + rules for building the targets supported by the system. What it does largely + depends on the values of make variables that + have been set before Makefile.rules is included. +

+ + + +
+

User Makefiles need not have comments in them unless the construction is + unusual or it does not strictly follow the rules and patterns of the LLVM + makefile system. Makefile comments are invoked with the pound (#) character. + The # character and any text following it, to the end of the line, are ignored + by make.

+
+ + + + +
+

This section provides some examples of the different kinds of modules you + can build with the LLVM makefile system. In general, each directory you + provide will build a single object although that object may be composed of + additionally compiled components.

+
+ + + +
+

Only a few variable definitions are needed to build a regular library. + Normally, the makefile system will build all the software into a single + libname.o (pre-linked) object. This means the library is not + searchable and that the distinction between compilation units has been + dissolved. Optionally, you can ask for a shared library (.so) or archive + library (.a) built. Archive libraries are the default. For example:

+

+      LIBRARYNAME = mylib
+      SHARED_LIBRARY = 1
+      ARCHIVE_LIBRARY = 1
+  
+

says to build a library named "mylib" with both a shared library + (mylib.so) and an archive library (mylib.a) version. The + contents of all the + libraries produced will be the same, they are just constructed differently. + Note that you normally do not need to specify the sources involved. The LLVM + Makefile system will infer the source files from the contents of the source + directory.

+

The LOADABLE_MODULE=1 directive can be used in conjunction with + SHARED_LIBRARY=1 to indicate that the resulting shared library should + be openable with the dlopen function and searchable with the + dlsym function (or your operating system's equivalents). While this + isn't strictly necessary on Linux and a few other platforms, it is required + on systems like HP-UX and Darwin. You should use LOADABLE_MODULE for + any shared library that you intend to be loaded into an tool via the + -load option. See the + WritingAnLLVMPass.html document + for an example of why you might want to do this. +

+ + + +
+

In some situations, it is desirable to build a single bitcode module from + a variety of sources, instead of an archive, shared library, or bitcode + library. Bitcode modules can be specified in addition to any of the other + types of libraries by defining the MODULE_NAME + variable. For example:

+

+      LIBRARYNAME = mylib
+      BYTECODE_LIBRARY = 1
+      MODULE_NAME = mymod
+  
+

will build a module named mymod.bc from the sources in the + directory. This module will be an aggregation of all the bitcode modules + derived from the sources. The example will also build a bitcode archive + containing a bitcode module for each compiled source file. The difference is + subtle, but important depending on how the module or library is to be linked. +

+
+ + + +
+

In some situations, you need to create a loadable module. Loadable modules + can be loaded into programs like opt or llc to specify + additional passes to run or targets to support. Loadable modules are also + useful for debugging a pass or providing a pass with another package if that + pass can't be included in LLVM.

+

LLVM provides complete support for building such a module. All you need to + do is use the LOADABLE_MODULE variable in your Makefile. For example, to + build a loadable module named MyMod that uses the LLVM libraries + LLVMSupport.a and LLVMSystem.a, you would specify:

+

+     LIBRARYNAME := MyMod
+     LOADABLE_MODULE := 1
+     LINK_COMPONENTS := support system
+  
+

Use of the LOADABLE_MODULE facility implies several things:

+
    +
  1. There will be no "lib" prefix on the module. This differentiates it from + a standard shared library of the same name.
  2. +
  3. The SHARED_LIBRARY variable is turned + on.
  4. +
  5. The LINK_LIBS_IN_SHARED variable + is turned on.
  6. +
+

A loadable module is loaded by LLVM via the facilities of libtool's libltdl + library which is part of lib/System implementation.

+
+ + + +
+

For building executable programs (tools), you must provide the name of the + tool and the names of the libraries you wish to link with the tool. For + example:

+

+      TOOLNAME = mytool
+      USEDLIBS = mylib
+      LINK_COMPONENTS = support system
+  
+

says that we are to build a tool name mytool and that it requires + three libraries: mylib, LLVMSupport.a and + LLVMSystem.a.

+

Note that two different variables are use to indicate which libraries are + linked: USEDLIBS and LLVMLIBS. This distinction is necessary + to support projects. LLVMLIBS refers to the LLVM libraries found in + the LLVM object directory. USEDLIBS refers to the libraries built by + your project. In the case of building LLVM tools, USEDLIBS and + LLVMLIBS can be used interchangeably since the "project" is LLVM + itself and USEDLIBS refers to the same place as LLVMLIBS. +

+

Also note that there are two different ways of specifying a library: with a + .a suffix and without. Without the suffix, the entry refers to the + re-linked (.o) file which will include all symbols of the library. + This is useful, for example, to include all passes from a library of passes. + If the .a suffix is used then the library is linked as a searchable + library (with the -l option). In this case, only the symbols that are + unresolved at that point will be resolved from the library, if they + exist. Other (unreferenced) symbols will not be included when the .a + syntax is used. Note that in order to use the .a suffix, the library + in question must have been built with the ARCHIVE_LIBRARY option set. +

+
+ + + +
+

Many tools will want to use the JIT features of LLVM. To do this, you + simply specify that you want an execution 'engine', and the makefiles will + automatically link in the appropriate JIT for the host or an interpreter + if none is available:

+

+      TOOLNAME = my_jit_tool
+      USEDLIBS = mylib
+      LINK_COMPONENTS = engine
+  
+

Of course, any additional libraries may be listed as other components. To + get a full understanding of how this changes the linker command, it is + recommended that you:

+

+      cd examples/Fibonacci
+      make VERBOSE=1
+  
+
+ + + + + +
+

This section describes each of the targets that can be built using the LLVM + Makefile system. Any target can be invoked from any directory but not all are + applicable to a given directory (e.g. "check", "dist" and "install" will + always operate as if invoked from the top level directory).

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Target NameImplied TargetsTarget Description
allCompile the software recursively. Default target. +
all-localCompile the software in the local directory only. +
checkChange to the test directory in a project and run the + test suite there. +
check-localRun a local test suite. Generally this is only defined in the + Makefile of the project's test directory. +
cleanRemove built objects recursively. +
clean-localRemove built objects from the local directory only. +
distallPrepare a source distribution tarball. +
dist-checkallPrepare a source distribution tarball and check that it builds. +
dist-cleancleanClean source distribution tarball temporary files. +
installallCopy built objects to installation directory. +
preconditionsallCheck to make sure configuration and makefiles are up to date. +
printvarsallPrints variables defined by the makefile system (for debugging). +
tagsMake C and C++ tags files for emacs and vi. +
uninstallRemove built objects from installation directory. +
+
+ + + +
+

When you invoke make with no arguments, you are implicitly + instructing it to seek the "all" target (goal). This target is used for + building the software recursively and will do different things in different + directories. For example, in a lib directory, the "all" target will + compile source files and generate libraries. But, in a tools + directory, it will link libraries and generate executables.

+
+ + + +
+

This target is the same as all but it operates only on + the current directory instead of recursively.

+
+ + + +
+

This target can be invoked from anywhere within a project's directories + but always invokes the check-local target + in the project's test directory, if it exists and has a + Makefile. A warning is produced otherwise. If + TESTSUITE is defined on the make + command line, it will be passed down to the invocation of + make check-local in the test directory. The intended usage + for this is to assist in running specific suites of tests. If + TESTSUITE is not set, the implementation of check-local + should run all normal tests. It is up to the project to define what + different values for TESTSUTE will do. See the + TestingGuide for further details.

+
+ + + +
+

This target should be implemented by the Makefile in the project's + test directory. It is invoked by the check target elsewhere. + Each project is free to define the actions of check-local as + appropriate for that project. The LLVM project itself uses dejagnu to run a + suite of feature and regresson tests. Other projects may choose to use + dejagnu or any other testing mechanism.

+
+ + + +
+

This target cleans the build directory, recursively removing all things + that the Makefile builds. The cleaning rules have been made guarded so they + shouldn't go awry (via rm -f $(UNSET_VARIABLE)/* which will attempt + to erase the entire directory structure.

+
+ + + +
+

This target does the same thing as clean but only for the current + (local) directory.

+
+ + + +
+

This target builds a distribution tarball. It first builds the entire + project using the all target and then tars up the necessary files and + compresses it. The generated tarball is sufficient for a casual source + distribution, but probably not for a release (see dist-check).

+
+ + + +
+

This target does the same thing as the dist target but also checks + the distribution tarball. The check is made by unpacking the tarball to a new + directory, configuring it, building it, installing it, and then verifying that + the installation results are correct (by comparing to the original build). + This target can take a long time to run but should be done before a release + goes out to make sure that the distributed tarball can actually be built into + a working release.

+
+ + + +
+

This is a special form of the clean clean target. It performs a + normal clean but also removes things pertaining to building the + distribution.

+
+ + + +
+

This target finalizes shared objects and executables and copies all + libraries, headers, executables and documentation to the directory given + with the --prefix option to configure. When completed, + the prefix directory will have everything needed to use LLVM.

+

The LLVM makefiles can generate complete internal documentation + for all the classes by using doxygen. By default, this feature is + not enabled because it takes a long time and generates a massive + amount of data (>100MB). If you want this feature, you must configure LLVM + with the --enable-doxygen switch and ensure that a modern version of doxygen + (1.3.7 or later) is available in your PATH. You can download + doxygen from + + here. +

+ + + +
+

This utility target checks to see if the Makefile in the object + directory is older than the Makefile in the source directory and + copies it if so. It also reruns the configure script if that needs to + be done and rebuilds the Makefile.config file similarly. Users may + overload this target to ensure that sanity checks are run before any + building of targets as all the targets depend on preconditions.

+
+ + + +
+

This utility target just causes the LLVM makefiles to print out some of + the makefile variables so that you can double check how things are set.

+
+ + + +
+

This utility target will force a reconfigure of LLVM or your project. It + simply runs $(PROJ_OBJ_ROOT)/config.status --recheck to rerun the + configuration tests and rebuild the configured files. This isn't generally + useful as the makefiles will reconfigure themselves whenever its necessary. +

+
+ + + +
+

This utility target, only available when $(PROJ_OBJ_ROOT) is not + the same as $(PROJ_SRC_ROOT), will completely clean the + $(PROJ_OBJ_ROOT) directory by removing its content entirely and + reconfiguring the directory. This returns the $(PROJ_OBJ_ROOT) + directory to a completely fresh state. All content in the directory except + configured files and top-level makefiles will be lost.

+

Use with caution.

+
+ + + +
+

This target will generate a TAGS file in the top-level source + directory. It is meant for use with emacs, XEmacs, or ViM. The TAGS file + provides an index of symbol definitions so that the editor can jump you to the + definition quickly.

+
+ + + +
+

This target is the opposite of the install target. It removes the + header, library and executable files from the installation directories. Note + that the directories themselves are not removed because it is not guaranteed + that LLVM is the only thing installing there (e.g. --prefix=/usr).

+
+ + + + +
+

Variables are used to tell the LLVM Makefile System what to do and to + obtain information from it. Variables are also used internally by the LLVM + Makefile System. Variable names that contain only the upper case alphabetic + letters and underscore are intended for use by the end user. All other + variables are internal to the LLVM Makefile System and should not be relied + upon nor modified. The sections below describe how to use the LLVM Makefile + variables.

+
+ + + +
+

Variables listed in the table below should be set before the + inclusion of $(LEVEL)/Makefile.common. + These variables provide input to the LLVM make system that tell it what to do + for the current directory.

+
+
BUILD_ARCHIVE
+
If set to any value, causes an archive (.a) library to be built.
+
BUILT_SOURCES
+
Specifies a set of source files that are generated from other source + files. These sources will be built before any other target processing to + ensure they are present.
+
BYTECODE_LIBRARY
+
If set to any value, causes a bitcode library (.bc) to be built.
+
CONFIG_FILES
+
Specifies a set of configuration files to be installed.
+
DEBUG_SYMBOLS
+
If set to any value, causes the build to include debugging + symbols even in optimized objects, libraries and executables. This + alters the flags specified to the compilers and linkers. Debugging + isn't fun in an optimized build, but it is possible.
+
DIRS
+
Specifies a set of directories, usually children of the current + directory, that should also be made using the same goal. These directories + will be built serially.
+
DISABLE_AUTO_DEPENDENCIES
+
If set to any value, causes the makefiles to not automatically + generate dependencies when running the compiler. Use of this feature is + discouraged and it may be removed at a later date.
+
ENABLE_OPTIMIZED
+
If set to 1, causes the build to generate optimized objects, + libraries and executables. This alters the flags specified to the compilers + and linkers. Generally debugging won't be a fun experience with an optimized + build.
+
ENABLE_PROFILING
+
If set to 1, causes the build to generate both optimized and + profiled objects, libraries and executables. This alters the flags specified + to the compilers and linkers to ensure that profile data can be collected + from the tools built. Use the gprof tool to analyze the output from + the profiled tools (gmon.out).
+
DISABLE_ASSERTIONS
+
If set to 1, causes the build to disable assertions, even if + building a debug or profile build. This will exclude all assertion check + code from the build. LLVM will execute faster, but with little help when + things go wrong.
+
EXPERIMENTAL_DIRS
+
Specify a set of directories that should be built, but if they fail, it + should not cause the build to fail. Note that this should only be used + temporarily while code is being written.
+
EXPORTED_SYMBOL_FILE
+
Specifies the name of a single file that contains a list of the + symbols to be exported by the linker. One symbol per line.
+
EXPORTED_SYMBOL_LIST
+
Specifies a set of symbols to be exported by the linker.
+
EXTRA_DIST
+
Specifies additional files that should be distributed with LLVM. All + source files, all built sources, all Makefiles, and most documentation files + will be automatically distributed. Use this variable to distribute any + files that are not automatically distributed.
+
KEEP_SYMBOLS
+
If set to any value, specifies that when linking executables the + makefiles should retain debug symbols in the executable. Normally, symbols + are stripped from the executable.
+
LEVEL(required)
+
Specify the level of nesting from the top level. This variable must be + set in each makefile as it is used to find the top level and thus the other + makefiles.
+
LIBRARYNAME
+
Specify the name of the library to be built. (Required For + Libraries)
+
LINK_COMPONENTS
+
When specified for building a tool, the value of this variable will be + passed to the llvm-config tool to generate a link line for the + tool. Unlike USEDLIBS and LLVMLIBS, not all libraries need + to be specified. The llvm-config tool will figure out the library + dependencies and add any libraries that are needed. The USEDLIBS + variable can still be used in conjunction with LINK_COMPONENTS so + that additional project-specific libraries can be linked with the LLVM + libraries specified by LINK_COMPONENTS
+
LINK_LIBS_IN_SHARED
+
By default, shared library linking will ignore any libraries specified + with the LLVMLIBS or USEDLIBS. + This prevents shared libs from including things that will be in the LLVM + tool the shared library will be loaded into. However, sometimes it is useful + to link certain libraries into your shared library and this option enables + that feature.
+
LLVMLIBS
+
Specifies the set of libraries from the LLVM $(ObjDir) that will be + linked into the tool or library.
+
LOADABLE_MODULE
+
If set to any value, causes the shared library being built to also be + a loadable module. Loadable modules can be opened with the dlopen() function + and searched with dlsym (or the operating system's equivalent). Note that + setting this variable without also setting SHARED_LIBRARY will have + no effect.
+
MODULE_NAME
+
Specifies the name of a bitcode module to be created. A bitcode + module can be specified in conjunction with other kinds of library builds + or by itself. It constructs from the sources a single linked bitcode + file.
+
NO_INSTALL
+
Specifies that the build products of the directory should not be + installed but should be built even if the install target is given. + This is handy for directories that build libraries or tools that are only + used as part of the build process, such as code generators (e.g. + tblgen).
+
OPTIONAL_DIRS
+
Specify a set of directories that may be built, if they exist, but its + not an error for them not to exist.
+
PARALLEL_DIRS
+
Specify a set of directories to build recursively and in parallel if + the -j option was used with make.
+
SHARED_LIBRARY
+
If set to any value, causes a shared library (.so) to be built in + addition to any other kinds of libraries. Note that this option will cause + all source files to be built twice: once with options for position + independent code and once without. Use it only where you really need a + shared library.
+
SOURCES(optional)
+
Specifies the list of source files in the current directory to be + built. Source files of any type may be specified (programs, documentation, + config files, etc.). If not specified, the makefile system will infer the + set of source files from the files present in the current directory.
+
SUFFIXES
+
Specifies a set of filename suffixes that occur in suffix match rules. + Only set this if your local Makefile specifies additional suffix + match rules.
+
TARGET
+
Specifies the name of the LLVM code generation target that the + current directory builds. Setting this variable enables additional rules to + build .inc files from .td files.
+
TESTSUITE
+
Specifies the directory of tests to run in llvm/test.
+
TOOLNAME
+
Specifies the name of the tool that the current directory should + build.
+
TOOL_VERBOSE
+
Implies VERBOSE and also tells each tool invoked to be verbose. This is + handy when you're trying to see the sub-tools invoked by each tool invoked + by the makefile. For example, this will pass -v to the GCC + compilers which causes it to print out the command lines it uses to invoke + sub-tools (compiler, assembler, linker).
+
USEDLIBS
+
Specifies the list of project libraries that will be linked into the + tool or library.
+
VERBOSE
+
Tells the Makefile system to produce detailed output of what it is doing + instead of just summary comments. This will generate a LOT of output.
+
+
+ + + +
+

Override variables can be used to override the default + values provided by the LLVM makefile system. These variables can be set in + several ways:

+
    +
  • In the environment (e.g. setenv, export) -- not recommended.
  • +
  • On the make command line -- recommended.
  • +
  • On the configure command line
  • +
  • In the Makefile (only after the inclusion of $(LEVEL)/Makefile.common).
  • +
+

The override variables are given below:

+
+
AR (defaulted)
+
Specifies the path to the ar tool.
+
PROJ_OBJ_DIR
+
The directory into which the products of build rules will be placed. + This might be the same as + PROJ_SRC_DIR but typically is + not.
+
PROJ_SRC_DIR
+
The directory which contains the source files to be built.
+
BUILD_EXAMPLES
+
If set to 1, build examples in examples and (if building + Clang) tools/clang/examples directories.
+
BZIP2(configured)
+
The path to the bzip2 tool.
+
CC(configured)
+
The path to the 'C' compiler.
+
CFLAGS
+
Additional flags to be passed to the 'C' compiler.
+
CXX
+
Specifies the path to the C++ compiler.
+
CXXFLAGS
+
Additional flags to be passed to the C++ compiler.
+
DATE(configured)
+
Specifies the path to the date program or any program that can + generate the current date and time on its standard output
+
DOT(configured)
+
Specifies the path to the dot tool or false if there + isn't one.
+
ECHO(configured)
+
Specifies the path to the echo tool for printing output.
+
EXEEXT(configured)
+
Provides the extension to be used on executables built by the makefiles. + The value may be empty on platforms that do not use file extensions for + executables (e.g. Unix).
+
INSTALL(configured)
+
Specifies the path to the install tool.
+
LDFLAGS(configured)
+
Allows users to specify additional flags to pass to the linker.
+
LIBS(configured)
+
The list of libraries that should be linked with each tool.
+
LIBTOOL(configured)
+
Specifies the path to the libtool tool. This tool is renamed + mklib by the configure script and always located in the +
LLVMAS(defaulted)
+
Specifies the path to the llvm-as tool.
+
LLVMCC
+
Specifies the path to the LLVM capable compiler.
+
LLVMCXX
+
Specifies the path to the LLVM C++ capable compiler.
+
LLVMGCC(defaulted)
+
Specifies the path to the LLVM version of the GCC 'C' Compiler
+
LLVMGXX(defaulted)
+
Specifies the path to the LLVM version of the GCC C++ Compiler
+
LLVMLD(defaulted)
+
Specifies the path to the LLVM bitcode linker tool
+
LLVM_OBJ_ROOT(configured) +
+
Specifies the top directory into which the output of the build is + placed.
+
LLVM_SRC_ROOT(configured) +
+
Specifies the top directory in which the sources are found.
+
LLVM_TARBALL_NAME + (configured)
+
Specifies the name of the distribution tarball to create. This is + configured from the name of the project and its version number.
+
MKDIR(defaulted)
+
Specifies the path to the mkdir tool that creates + directories.
+
ONLY_TOOLS
+
If set, specifies the list of tools to build.
+
PLATFORMSTRIPOPTS
+
The options to provide to the linker to specify that a stripped (no + symbols) executable should be built.
+
RANLIB(defaulted)
+
Specifies the path to the ranlib tool.
+
RM(defaulted)
+
Specifies the path to the rm tool.
+
SED(defaulted)
+
Specifies the path to the sed tool.
+
SHLIBEXT(configured)
+
Provides the filename extension to use for shared libraries.
+
TBLGEN(defaulted)
+
Specifies the path to the tblgen tool.
+
TAR(defaulted)
+
Specifies the path to the tar tool.
+
ZIP(defaulted)
+
Specifies the path to the zip tool.
+
+
+ + + +
+

Variables listed in the table below can be used by the user's Makefile but + should not be changed. Changing the value will generally cause the build to go + wrong, so don't do it.

+
+
bindir
+
The directory into which executables will ultimately be installed. This + value is derived from the --prefix option given to + configure.
+
BuildMode
+
The name of the type of build being performed: Debug, Release, or + Profile
+
bytecode_libdir
+
The directory into which bitcode libraries will ultimately be + installed. This value is derived from the --prefix option given to + configure.
+
ConfigureScriptFLAGS
+
Additional flags given to the configure script when + reconfiguring.
+
DistDir
+
The current directory for which a distribution copy is being + made.
+
Echo
+
The LLVM Makefile System output command. This provides the + llvm[n] prefix and starts with @ so the command itself is not + printed by make.
+
EchoCmd
+
Same as Echo but without the leading @. +
+
includedir
+
The directory into which include files will ultimately be installed. + This value is derived from the --prefix option given to + configure.
+
libdir
+
The directory into which native libraries will ultimately be installed. + This value is derived from the --prefix option given to + configure.
+
LibDir
+
The configuration specific directory into which libraries are placed + before installation.
+
MakefileConfig
+
Full path of the Makefile.config file.
+
MakefileConfigIn
+
Full path of the Makefile.config.in file.
+
ObjDir
+
The configuration and directory specific directory where build objects + (compilation results) are placed.
+
SubDirs
+
The complete list of sub-directories of the current directory as + specified by other variables.
+
Sources
+
The complete list of source files.
+
sysconfdir
+
The directory into which configuration files will ultimately be + installed. This value is derived from the --prefix option given to + configure.
+
ToolDir
+
The configuration specific directory into which executables are placed + before they are installed.
+
TopDistDir
+
The top most directory into which the distribution files are copied. +
+
Verb
+
Use this as the first thing on your build script lines to enable or + disable verbose mode. It expands to either an @ (quiet mode) or nothing + (verbose mode).
+
+
+ + + +
+

Variables listed below are used by the LLVM Makefile System + and considered internal. You should not use these variables under any + circumstances.

+

+ Archive + AR.Flags + BaseNameSources + BCCompile.C + BCCompile.CXX + BCLinkLib + C.Flags + Compile.C + CompileCommonOpts + Compile.CXX + ConfigStatusScript + ConfigureScript + CPP.Flags + CPP.Flags + CXX.Flags + DependFiles + DestArchiveLib + DestBitcodeLib + DestModule + DestSharedLib + DestTool + DistAlways + DistCheckDir + DistCheckTop + DistFiles + DistName + DistOther + DistSources + DistSubDirs + DistTarBZ2 + DistTarGZip + DistZip + ExtraLibs + FakeSources + INCFiles + InternalTargets + LD.Flags + LibName.A + LibName.BC + LibName.LA + LibName.O + LibTool.Flags + Link + LinkModule + LLVMLibDir + LLVMLibsOptions + LLVMLibsPaths + LLVMToolDir + LLVMUsedLibs + LocalTargets + Module + ObjectsBC + ObjectsLO + ObjectsO + ObjMakefiles + ParallelTargets + PreConditions + ProjLibsOptions + ProjLibsPaths + ProjUsedLibs + Ranlib + RecursiveTargets + SrcMakefiles + Strip + StripWarnMsg + TableGen + TDFiles + ToolBuildPath + TopLevelTargets + UserTargets +

+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + + Reid Spencer
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/Packaging.html b/final/docs/Packaging.html new file mode 100644 index 00000000000..217590e6c24 --- /dev/null +++ b/final/docs/Packaging.html @@ -0,0 +1,118 @@ + + + + Advice on Packaging LLVM + + + + +
Advice on Packaging LLVM
+
    +
  1. Overview
  2. +
  3. Compile Flags
  4. +
  5. C++ Features
  6. +
  7. Shared Library
  8. +
  9. Dependencies
  10. +
+ + + + +
+ +

LLVM sets certain default configure options to make sure our developers don't +break things for constrained platforms. These settings are not optimal for most +desktop systems, and we hope that packagers (e.g., Redhat, Debian, MacPorts, +etc.) will tweak them. This document lists settings we suggest you tweak. +

+ +

LLVM's API changes with each release, so users are likely to want, for +example, both LLVM-2.6 and LLVM-2.7 installed at the same time to support apps +developed against each. +

+
+ + + + +
+ +

LLVM runs much more quickly when it's optimized and assertions are removed. +However, such a build is currently incompatible with users who build without +defining NDEBUG, and the lack of assertions makes it hard to debug problems in +user code. We recommend allowing users to install both optimized and debug +versions of LLVM in parallel. The following configure flags are relevant: +

+ +
+
--disable-assertions
Builds LLVM with NDEBUG + defined. Changes the LLVM ABI. Also available by setting + DISABLE_ASSERTIONS=0|1 in make's environment. This defaults + to enabled regardless of the optimization setting, but it slows things + down.
+ +
--enable-debug-symbols
Builds LLVM with -g. + Also available by setting DEBUG_SYMBOLS=0|1 in make's + environment. This defaults to disabled when optimizing, so you should turn it + back on to let users debug their programs.
+ +
--enable-optimized
(For svn checkouts) Builds LLVM with + -O2 and, by default, turns off debug symbols. Also available by + setting ENABLE_OPTIMIZED=0|1 in make's environment. This + defaults to enabled when not in a checkout.
+
+
+ + + + +
+ +
+
RTTI
LLVM disables RTTI by default. Add REQUIRES_RTTI=1 + to your environment while running make to re-enable it. This will + allow users to build with RTTI enabled and still inherit from LLVM + classes.
+
+
+ + + + +
+ +

Configure with --enable-shared to build +libLLVM-major.minor.(so|dylib) and link the tools +against it. This saves lots of binary size at the cost of some startup time. +

+
+ + + + +
+ +
+
--enable-libffi
Depend on libffi to allow the LLVM +interpreter to call external functions.
+
--with-oprofile
Depend on libopagent +(>=version 0.9.4) to let the LLVM JIT tell oprofile about function addresses and +line numbers.
+
+
+ + +
+
+ Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/Passes.html b/final/docs/Passes.html new file mode 100644 index 00000000000..a5349c3b85c --- /dev/null +++ b/final/docs/Passes.html @@ -0,0 +1,2249 @@ + + + + LLVM's Analysis and Transform Passes + + + + + + + +
LLVM's Analysis and Transform Passes
+ +
    +
  1. Introduction
  2. +
  3. Analysis Passes +
  4. Transform Passes
  5. +
  6. Utility Passes
  7. +
+ +
+

Written by Reid Spencer + and Gordon Henriksen

+
+ + + +
+

This document serves as a high level summary of the optimization features + that LLVM provides. Optimizations are implemented as Passes that traverse some + portion of a program to either collect information or transform the program. + The table below divides the passes that LLVM provides into three categories. + Analysis passes compute information that other passes can use or for debugging + or program visualization purposes. Transform passes can use (or invalidate) + the analysis passes. Transform passes all mutate the program in some way. + Utility passes provides some utility but don't otherwise fit categorization. + For example passes to extract functions to bitcode or write a module to + bitcode are neither analysis nor transform passes. +

The table below provides a quick summary of each pass and links to the more + complete pass description later in the document.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ANALYSIS PASSES
OptionName
-aa-evalExhaustive Alias Analysis Precision Evaluator
-basicaaBasic Alias Analysis (default AA impl)
-basiccgBasic CallGraph Construction
-codegenprepareOptimize for code generation
-count-aaCount Alias Analysis Query Responses
-debug-aaAA use debugger
-domfrontierDominance Frontier Construction
-domtreeDominator Tree Construction
-dot-callgraphPrint Call Graph to 'dot' file
-dot-cfgPrint CFG of function to 'dot' file
-dot-cfg-onlyPrint CFG of function to 'dot' file (with no function bodies)
-dot-domPrint dominator tree of function to 'dot' file
-dot-dom-onlyPrint dominator tree of function to 'dot' file (with no function bodies)
-dot-postdomPrint post dominator tree of function to 'dot' file
-dot-postdom-onlyPrint post dominator tree of function to 'dot' file (with no function bodies)
-globalsmodref-aaSimple mod/ref analysis for globals
-instcountCounts the various types of Instructions
-interprocedural-aa-evalExhaustive Interprocedural Alias Analysis Precision Evaluator
-interprocedural-basic-aaInterprocedural Basic Alias Analysis
-intervalsInterval Partition Construction
-iv-usersInduction Variable Users
-lazy-value-infoLazy Value Information Analysis
-ldaLoop Dependence Analysis
-libcall-aaLibCall Alias Analysis
-lintCheck for common errors in LLVM IR
-live-valuesValue Liveness Analysis
-loopsNatural Loop Information
-memdepMemory Dependence Analysis
-module-debuginfoPrints module debug info metadata
-no-aaNo Alias Analysis (always returns 'may' alias)
-no-profileNo Profile Information
-pointertrackingTrack pointer bounds
-postdomfrontierPost-Dominance Frontier Construction
-postdomtreePost-Dominator Tree Construction
-print-alias-setsAlias Set Printer
-print-callgraphPrint a call graph
-print-callgraph-sccsPrint SCCs of the Call Graph
-print-cfg-sccsPrint SCCs of each function CFG
-print-dbginfoPrint debug info in human readable form
-print-dom-infoDominator Info Printer
-print-externalfnconstantsPrint external fn callsites passed constants
-print-functionPrint function to stderr
-print-modulePrint module to stderr
-print-used-typesFind Used Types
-profile-estimatorEstimate profiling information
-profile-loaderLoad profile information from llvmprof.out
-regionsDetect single entry single exit regions in a function
-profile-verifierVerify profiling information
-scalar-evolutionScalar Evolution Analysis
-scev-aaScalarEvolution-based Alias Analysis
-targetdataTarget Data Layout
TRANSFORM PASSES
OptionName
-abcdRemove redundant conditional branches
-adceAggressive Dead Code Elimination
-always-inlineInliner for always_inline functions
-argpromotionPromote 'by reference' arguments to scalars
-block-placementProfile Guided Basic Block Placement
-break-crit-edgesBreak critical edges in CFG
-codegenpreparePrepare a function for code generation
-constmergeMerge Duplicate Global Constants
-constpropSimple constant propagation
-dceDead Code Elimination
-deadargelimDead Argument Elimination
-deadtypeelimDead Type Elimination
-dieDead Instruction Elimination
-dseDead Store Elimination
-functionattrsDeduce function attributes
-globaldceDead Global Elimination
-globaloptGlobal Variable Optimizer
-gvnGlobal Value Numbering
-indvarsCanonicalize Induction Variables
-inlineFunction Integration/Inlining
-insert-edge-profilingInsert instrumentation for edge profiling
-insert-optimal-edge-profilingInsert optimal instrumentation for edge profiling
-instcombineCombine redundant instructions
-internalizeInternalize Global Symbols
-ipconstpropInterprocedural constant propagation
-ipsccpInterprocedural Sparse Conditional Constant Propagation
-jump-threadingThread control through conditional blocks
-lcssaLoop-Closed SSA Form Pass
-licmLoop Invariant Code Motion
-loop-deletionDead Loop Deletion Pass
-loop-extractExtract loops into new functions
-loop-extract-singleExtract at most one loop into a new function
-loop-index-splitIndex Split Loops
-loop-reduceLoop Strength Reduction
-loop-rotateRotate Loops
-loop-unrollUnroll loops
-loop-unswitchUnswitch loops
-loop-simplifyCanonicalize natural loops
-loweratomicLower atomic intrinsics
-lowerinvokeLower invoke and unwind, for unwindless code generators
-lowersetjmpLower Set Jump
-lowerswitchLower SwitchInst's to branches
-mem2regPromote Memory to Register
-memcpyoptOptimize use of memcpy and friends
-mergefuncMerge Functions
-mergereturnUnify function exit nodes
-partial-inlinerPartial Inliner
-partialspecializationPartial Specialization
-prune-ehRemove unused exception handling info
-reassociateReassociate expressions
-reg2memDemote all values to stack slots
-scalarreplScalar Replacement of Aggregates
-sccpSparse Conditional Constant Propagation
-sinkCode Sinking
-simplify-libcallsSimplify well-known library calls
-simplify-libcalls-halfpowrSimplify half_powr library calls
-simplifycfgSimplify the CFG
-split-gepsSplit complex GEPs into simple GEPs
-ssiStatic Single Information Construction
-ssi-everythingStatic Single Information Construction (everything, intended for debugging)
-stripStrip all symbols from a module
-strip-dead-debug-infoStrip debug info for unused symbols
-strip-dead-prototypesRemove unused function declarations
-strip-debug-declareStrip all llvm.dbg.declare intrinsics
-strip-nondebugStrip all symbols, except dbg symbols, from a module
-sretpromotionPromote sret arguments
-tailcallelimTail Call Elimination
-tailduplicateTail Duplication
UTILITY PASSES
OptionName
-deadarghaX0rDead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)
-extract-blocksExtract Basic Blocks From Module (for bugpoint use)
-instnamerAssign names to anonymous instructions
-preverifyPreliminary module verification
-verifyModule Verifier
-view-cfgView CFG of function
-view-cfg-onlyView CFG of function (with no function bodies)
-view-domView dominator tree of function
-view-dom-onlyView dominator tree of function (with no function bodies)
-view-postdomView post dominator tree of function
-view-postdom-onlyView post dominator tree of function (with no function bodies)
+
+ + + +
+

This section describes the LLVM Analysis Passes.

+
+ + + +
+

This is a simple N^2 alias analysis accuracy evaluator. + Basically, for each function in the program, it simply queries to see how the + alias analysis implementation answers alias queries between each pair of + pointers in the function.

+ +

This is inspired and adapted from code by: Naveen Neelakantam, Francesco + Spadini, and Wojciech Stryjewski.

+
+ + + +
+

+ This is the default implementation of the Alias Analysis interface + that simply implements a few identities (two different globals cannot alias, + etc), but otherwise does no analysis. +

+
+ + + +
+

Yet to be written.

+
+ + + +
+

+ This pass munges the code in the input function to better prepare it for + SelectionDAG-based code generation. This works around limitations in it's + basic-block-at-a-time approach. It should eventually be removed. +

+
+ + + +
+

+ A pass which can be used to count how many alias queries + are being made and how the alias analysis implementation being used responds. +

+
+ + + +
+

+ This simple pass checks alias analysis users to ensure that if they + create a new value, they do not query AA without informing it of the value. + It acts as a shim over any other AA pass you want. +

+ +

+ Yes keeping track of every value in the program is expensive, but this is + a debugging pass. +

+
+ + + +
+

+ This pass is a simple dominator construction algorithm for finding forward + dominator frontiers. +

+
+ + + +
+

+ This pass is a simple dominator construction algorithm for finding forward + dominators. +

+
+ + + +
+

+ This pass, only available in opt, prints the call graph into a + .dot graph. This graph can then be processed with the "dot" tool + to convert it to postscript or some other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the control flow graph + into a .dot graph. This graph can then be processed with the + "dot" tool to convert it to postscript or some other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the control flow graph + into a .dot graph, omitting the function bodies. This graph can + then be processed with the "dot" tool to convert it to postscript or some + other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the dominator tree + into a .dot graph. This graph can then be processed with the + "dot" tool to convert it to postscript or some other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the dominator tree + into a .dot graph, omitting the function bodies. This graph can + then be processed with the "dot" tool to convert it to postscript or some + other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the post dominator tree + into a .dot graph. This graph can then be processed with the + "dot" tool to convert it to postscript or some other suitable format. +

+
+ + + +
+

+ This pass, only available in opt, prints the post dominator tree + into a .dot graph, omitting the function bodies. This graph can + then be processed with the "dot" tool to convert it to postscript or some + other suitable format. +

+
+ + + +
+

+ This simple pass provides alias and mod/ref information for global values + that do not have their address taken, and keeps track of whether functions + read or write memory (are "pure"). For this simple (but very common) case, + we can provide pretty accurate and useful information. +

+
+ + + +
+

+ This pass collects the count of all instructions and reports them +

+
+ + + +
+

This pass implements a simple N^2 alias analysis accuracy evaluator. + Basically, for each function in the program, it simply queries to see how the + alias analysis implementation answers alias queries between each pair of + pointers in the function. +

+
+ + + +
+

This pass defines the default implementation of the Alias Analysis interface + that simply implements a few identities (two different globals cannot alias, + etc), but otherwise does no analysis. +

+
+ + + +
+

+ This analysis calculates and represents the interval partition of a function, + or a preexisting interval partition. +

+ +

+ In this way, the interval partition may be used to reduce a flow graph down + to its degenerate single node interval partition (unless it is irreducible). +

+
+ + + +
+

Bookkeeping for "interesting" users of expressions computed from + induction variables.

+
+ + + +
+

Interface for lazy computation of value constraint information.

+
+ + + +
+

Loop dependence analysis framework, which is used to detect dependences in + memory accesses in loops.

+
+ + + +
+

LibCall Alias Analysis.

+
+ + + +
+

This pass statically checks for common and easily-identified constructs + which produce undefined or likely unintended behavior in LLVM IR.

+ +

It is not a guarantee of correctness, in two ways. First, it isn't + comprehensive. There are checks which could be done statically which are + not yet implemented. Some of these are indicated by TODO comments, but + those aren't comprehensive either. Second, many conditions cannot be + checked statically. This pass does no dynamic instrumentation, so it + can't check for all possible problems.

+ +

Another limitation is that it assumes all code will be executed. A store + through a null pointer in a basic block which is never reached is harmless, + but this pass will warn about it anyway.

+ +

Optimization passes may make conditions that this pass checks for more or + less obvious. If an optimization pass appears to be introducing a warning, + it may be that the optimization pass is merely exposing an existing + condition in the code.

+ +

This code may be run before instcombine. In many cases, instcombine checks + for the same kinds of things and turns instructions with undefined behavior + into unreachable (or equivalent). Because of this, this pass makes some + effort to look through bitcasts and so on. +

+
+ + + +
+

LLVM IR Value liveness analysis pass.

+
+ + + +
+

+ This analysis is used to identify natural loops and determine the loop depth + of various nodes of the CFG. Note that the loops identified may actually be + several natural loops that share the same header node... not just a single + natural loop. +

+
+ + + +
+

+ An analysis that determines, for a given memory operation, what preceding + memory operations it depends on. It builds on alias analysis information, and + tries to provide a lazy, caching interface to a common kind of alias + information query. +

+
+ + + +
+

This pass decodes the debug info metadata in a module and prints in a + (sufficiently-prepared-) human-readable form. + + For example, run this pass from opt along with the -analyze option, and + it'll print to standard output. +

+
+ + + +
+

+ Always returns "I don't know" for alias queries. NoAA is unlike other alias + analysis implementations, in that it does not chain to a previous analysis. As + such it doesn't follow many of the rules that other alias analyses must. +

+
+ + + +
+

+ The default "no profile" implementation of the abstract + ProfileInfo interface. +

+
+ + + +
+

Tracking of pointer bounds. +

+
+ + + +
+

+ This pass is a simple post-dominator construction algorithm for finding + post-dominator frontiers. +

+
+ + + +
+

+ This pass is a simple post-dominator construction algorithm for finding + post-dominators. +

+
+ + + +
+

Yet to be written.

+
+ + + +
+

+ This pass, only available in opt, prints the call graph to + standard error in a human-readable form. +

+
+ + + +
+

+ This pass, only available in opt, prints the SCCs of the call + graph to standard error in a human-readable form. +

+
+ + + +
+

+ This pass, only available in opt, prints the SCCs of each + function CFG to standard error in a human-readable form. +

+
+ + + +
+

Pass that prints instructions, and associated debug info:

+
    + +
  • source/line/col information
  • +
  • original variable name
  • +
  • original type name
  • +
+
+ + + +
+

Dominator Info Printer.

+
+ + + +
+

+ This pass, only available in opt, prints out call sites to + external functions that are called with constant arguments. This can be + useful when looking for standard library functions we should constant fold + or handle in alias analyses. +

+
+ + + +
+

+ The PrintFunctionPass class is designed to be pipelined with + other FunctionPasses, and prints out the functions of the module + as they are processed. +

+
+ + + +
+

+ This pass simply prints out the entire module when it is executed. +

+
+ + + +
+

+ This pass is used to seek out all of the types in use by the program. Note + that this analysis explicitly does not include types only used by the symbol + table. +

+ + + +
+

Profiling information that estimates the profiling information + in a very crude and unimaginative way. +

+
+ + + +
+

+ A concrete implementation of profiling information that loads the information + from a profile dump file. +

+
+ + + +
+

Pass that checks profiling information for plausibility.

+
+ +
+

+ The RegionInfo pass detects single entry single exit regions in a + function, where a region is defined as any subgraph that is connected to the + remaining graph at only two spots. Furthermore, an hierarchical region tree is + built. +

+
+ + + +
+

+ The ScalarEvolution analysis can be used to analyze and + catagorize scalar expressions in loops. It specializes in recognizing general + induction variables, representing them with the abstract and opaque + SCEV class. Given this analysis, trip counts of loops and other + important properties can be obtained. +

+ +

+ This analysis is primarily useful for induction variable substitution and + strength reduction. +

+
+ + + +
+

Simple alias analysis implemented in terms of ScalarEvolution queries. + + This differs from traditional loop dependence analysis in that it tests + for dependencies within a single iteration of a loop, rather than + dependencies between different iterations. + + ScalarEvolution has a more complete understanding of pointer arithmetic + than BasicAliasAnalysis' collection of ad-hoc analyses. +

+
+ + + +
+

+ performs code stripping. this transformation can delete: +

+ +
    +
  1. names for virtual registers
  2. +
  3. symbols for internal globals and functions
  4. +
  5. debug information
  6. +
+ +

+ note that this transformation makes code much less readable, so it should + only be used in situations where the strip utility would be used, + such as reducing code size or making it harder to reverse engineer code. +

+
+ + + +
+

Provides other passes access to information on how the size and alignment + required by the the target ABI for various data types.

+
+ + + +
+

This section describes the LLVM Transform Passes.

+
+ + + +
+

ABCD removes conditional branch instructions that can be proved redundant. + With the SSI representation, each variable has a constraint. By analyzing these + constraints we can prove that a branch is redundant. When a branch is proved + redundant it means that one direction will always be taken; thus, we can change + this branch into an unconditional jump.

+

It is advisable to run SimplifyCFG and + Aggressive Dead Code Elimination after ABCD + to clean up the code.

+
+ + + +
+

ADCE aggressively tries to eliminate code. This pass is similar to + DCE but it assumes that values are dead until proven + otherwise. This is similar to SCCP, except applied to + the liveness of values.

+
+ + + +
+

A custom inliner that handles only functions that are marked as + "always inline".

+
+ + + +
+

+ This pass promotes "by reference" arguments to be "by value" arguments. In + practice, this means looking for internal functions that have pointer + arguments. If it can prove, through the use of alias analysis, that an + argument is *only* loaded, then it can pass the value into the function + instead of the address of the value. This can cause recursive simplification + of code and lead to the elimination of allocas (especially in C++ template + code like the STL). +

+ +

+ This pass also handles aggregate arguments that are passed into a function, + scalarizing them if the elements of the aggregate are only loaded. Note that + it refuses to scalarize aggregates which would require passing in more than + three operands to the function, because passing thousands of operands for a + large array or structure is unprofitable! +

+ +

+ Note that this transformation could also be done for arguments that are only + stored to (returning the value instead), but does not currently. This case + would be best handled when and if LLVM starts supporting multiple return + values from functions. +

+
+ + + +
+

This pass is a very simple profile guided basic block placement algorithm. + The idea is to put frequently executed blocks together at the start of the + function and hopefully increase the number of fall-through conditional + branches. If there is no profile information for a particular function, this + pass basically orders blocks in depth-first order.

+
+ + + +
+

+ Break all of the critical edges in the CFG by inserting a dummy basic block. + It may be "required" by passes that cannot deal with critical edges. This + transformation obviously invalidates the CFG, but can update forward dominator + (set, immediate dominators, tree, and frontier) information. +

+
+ + + +
+ This pass munges the code in the input function to better prepare it for + SelectionDAG-based code generation. This works around limitations in it's + basic-block-at-a-time approach. It should eventually be removed. +
+ + + +
+

+ Merges duplicate global constants together into a single constant that is + shared. This is useful because some passes (ie TraceValues) insert a lot of + string constants into the program, regardless of whether or not an existing + string is available. +

+
+ + + +
+

This file implements constant propagation and merging. It looks for + instructions involving only constant operands and replaces them with a + constant value instead of an instruction. For example:

+
add i32 1, 2
+

becomes

+
i32 3
+

NOTE: this pass has a habit of making definitions be dead. It is a good + idea to to run a DIE (Dead Instruction Elimination) pass + sometime after running this pass.

+
+ + + +
+

+ Dead code elimination is similar to dead instruction + elimination, but it rechecks instructions that were used by removed + instructions to see if they are newly dead. +

+
+ + + +
+

+ This pass deletes dead arguments from internal functions. Dead argument + elimination removes arguments which are directly dead, as well as arguments + only passed into function calls as dead arguments of other functions. This + pass also deletes dead arguments in a similar way. +

+ +

+ This pass is often useful as a cleanup pass to run after aggressive + interprocedural passes, which add possibly-dead arguments. +

+
+ + + +
+

+ This pass is used to cleanup the output of GCC. It eliminate names for types + that are unused in the entire translation unit, using the find used types pass. +

+
+ + + +
+

+ Dead instruction elimination performs a single pass over the function, + removing instructions that are obviously dead. +

+
+ + + +
+

+ A trivial dead store elimination that only considers basic-block local + redundant stores. +

+
+ + + +
+

A simple interprocedural pass which walks the call-graph, looking for + functions which do not access or only read non-local memory, and marking them + readnone/readonly. In addition, it marks function arguments (of pointer type) + 'nocapture' if a call to the function does not create any copies of the pointer + value that outlive the call. This more or less means that the pointer is only + dereferenced, and not returned from the function or stored in a global. + This pass is implemented as a bottom-up traversal of the call-graph. +

+
+ + + +
+

+ This transform is designed to eliminate unreachable internal globals from the + program. It uses an aggressive algorithm, searching out globals that are + known to be alive. After it finds all of the globals which are needed, it + deletes whatever is left over. This allows it to delete recursive chunks of + the program which are unreachable. +

+
+ + + +
+

+ This pass transforms simple global variables that never have their address + taken. If obviously true, it marks read/write globals as constant, deletes + variables only stored to, etc. +

+
+ + + +
+

+ This pass performs global value numbering to eliminate fully and partially + redundant instructions. It also performs redundant load elimination. +

+
+ + + +
+

+ This transformation analyzes and transforms the induction variables (and + computations derived from them) into simpler forms suitable for subsequent + analysis and transformation. +

+ +

+ This transformation makes the following changes to each loop with an + identifiable induction variable: +

+ +
    +
  1. All loops are transformed to have a single canonical + induction variable which starts at zero and steps by one.
  2. +
  3. The canonical induction variable is guaranteed to be the first PHI node + in the loop header block.
  4. +
  5. Any pointer arithmetic recurrences are raised to use array + subscripts.
  6. +
+ +

+ If the trip count of a loop is computable, this pass also makes the following + changes: +

+ +
    +
  1. The exit condition for the loop is canonicalized to compare the + induction value against the exit value. This turns loops like: +
    for (i = 7; i*i < 1000; ++i)
    + into +
    for (i = 0; i != 25; ++i)
  2. +
  3. Any use outside of the loop of an expression derived from the indvar + is changed to compute the derived value outside of the loop, eliminating + the dependence on the exit value of the induction variable. If the only + purpose of the loop is to compute the exit value of some derived + expression, this transformation will make the loop dead.
  4. +
+ +

+ This transformation should be followed by strength reduction after all of the + desired loop transformations have been performed. Additionally, on targets + where it is profitable, the loop could be transformed to count down to zero + (the "do loop" optimization). +

+
+ + + +
+

+ Bottom-up inlining of functions into callees. +

+
+ + + +
+

+ This pass instruments the specified program with counters for edge profiling. + Edge profiling can give a reasonable approximation of the hot paths through a + program, and is used for a wide variety of program transformations. +

+ +

+ Note that this implementation is very naïve. It inserts a counter for + every edge in the program, instead of using control flow information + to prune the number of counters inserted. +

+
+ + + +
+

This pass instruments the specified program with counters for edge profiling. + Edge profiling can give a reasonable approximation of the hot paths through a + program, and is used for a wide variety of program transformations. +

+
+ + + +
+

+ Combine instructions to form fewer, simple + instructions. This pass does not modify the CFG This pass is where algebraic + simplification happens. +

+ +

+ This pass combines things like: +

+ +
%Y = add i32 %X, 1
+%Z = add i32 %Y, 1
+ +

+ into: +

+ +
%Z = add i32 %X, 2
+ +

+ This is a simple worklist driven algorithm. +

+ +

+ This pass guarantees that the following canonicalizations are performed on + the program: +

+ +
    +
  • If a binary operator has a constant operand, it is moved to the right- + hand side.
  • +
  • Bitwise operators with constant operands are always grouped so that + shifts are performed first, then ors, then + ands, then xors.
  • +
  • Compare instructions are converted from <, + >, ≤, or ≥ to + = or ≠ if possible.
  • +
  • All cmp instructions on boolean values are replaced with + logical operations.
  • +
  • add X, X is represented as + mul X, 2 ⇒ shl X, 1
  • +
  • Multiplies with a constant power-of-two argument are transformed into + shifts.
  • +
  • … etc.
  • +
+
+ + + +
+

+ This pass loops over all of the functions in the input module, looking for a + main function. If a main function is found, all other functions and all + global variables with initializers are marked as internal. +

+
+ + + +
+

+ This pass implements an extremely simple interprocedural constant + propagation pass. It could certainly be improved in many different ways, + like using a worklist. This pass makes arguments dead, but does not remove + them. The existing dead argument elimination pass should be run after this + to clean up the mess. +

+
+ + + +
+

+ An interprocedural variant of Sparse Conditional Constant + Propagation. +

+
+ + + +
+

+ Jump threading tries to find distinct threads of control flow running through + a basic block. This pass looks at blocks that have multiple predecessors and + multiple successors. If one or more of the predecessors of the block can be + proven to always cause a jump to one of the successors, we forward the edge + from the predecessor to the successor by duplicating the contents of this + block. +

+

+ An example of when this can occur is code like this: +

+ +
if () { ...
+  X = 4;
+}
+if (X < 3) {
+ +

+ In this case, the unconditional branch at the end of the first if can be + revectored to the false side of the second if. +

+
+ + + +
+

+ This pass transforms loops by placing phi nodes at the end of the loops for + all values that are live across the loop boundary. For example, it turns + the left into the right code: +

+ +
for (...)                for (...)
+  if (c)                   if (c)
+    X1 = ...                 X1 = ...
+  else                     else
+    X2 = ...                 X2 = ...
+  X3 = phi(X1, X2)         X3 = phi(X1, X2)
+... = X3 + 4              X4 = phi(X3)
+                          ... = X4 + 4
+ +

+ This is still valid LLVM; the extra phi nodes are purely redundant, and will + be trivially eliminated by InstCombine. The major benefit of + this transformation is that it makes many other loop optimizations, such as + LoopUnswitching, simpler. +

+
+ + + +
+

+ This pass performs loop invariant code motion, attempting to remove as much + code from the body of a loop as possible. It does this by either hoisting + code into the preheader block, or by sinking code to the exit blocks if it is + safe. This pass also promotes must-aliased memory locations in the loop to + live in registers, thus hoisting and sinking "invariant" loads and stores. +

+ +

+ This pass uses alias analysis for two purposes: +

+ +
    +
  • Moving loop invariant loads and calls out of loops. If we can determine + that a load or call inside of a loop never aliases anything stored to, + we can hoist it or sink it like any other instruction.
  • +
  • Scalar Promotion of Memory - If there is a store instruction inside of + the loop, we try to move the store to happen AFTER the loop instead of + inside of the loop. This can only happen if a few conditions are true: +
      +
    • The pointer stored through is loop invariant.
    • +
    • There are no stores or loads in the loop which may alias + the pointer. There are no calls in the loop which mod/ref the + pointer.
    • +
    + If these conditions are true, we can promote the loads and stores in the + loop of the pointer to use a temporary alloca'd variable. We then use + the mem2reg functionality to construct the appropriate SSA form for the + variable.
  • +
+
+ + +
+

+ This file implements the Dead Loop Deletion Pass. This pass is responsible + for eliminating loops with non-infinite computable trip counts that have no + side effects or volatile instructions, and do not contribute to the + computation of the function's return value. +

+
+ + + +
+

+ A pass wrapper around the ExtractLoop() scalar transformation to + extract each top-level loop into its own new function. If the loop is the + only loop in a given function, it is not touched. This is a pass most + useful for debugging via bugpoint. +

+
+ + + +
+

+ Similar to Extract loops into new functions, + this pass extracts one natural loop from the program into a function if it + can. This is used by bugpoint. +

+
+ + + +
+

+ This pass divides loop's iteration range by spliting loop such that each + individual loop is executed efficiently. +

+
+ + + +
+

+ This pass performs a strength reduction on array references inside loops that + have as one or more of their components the loop induction variable. This is + accomplished by creating a new value to hold the initial value of the array + access for the first iteration, and then creating a new GEP instruction in + the loop to increment the value by the appropriate amount. +

+
+ + + +
+

A simple loop rotation transformation.

+
+ + + +
+

+ This pass implements a simple loop unroller. It works best when loops have + been canonicalized by the -indvars pass, + allowing it to determine the trip counts of loops easily. +

+
+ + + +
+

+ This pass transforms loops that contain branches on loop-invariant conditions + to have multiple loops. For example, it turns the left into the right code: +

+ +
for (...)                  if (lic)
+  A                          for (...)
+  if (lic)                     A; B; C
+    B                      else
+  C                          for (...)
+                               A; C
+ +

+ This can increase the size of the code exponentially (doubling it every time + a loop is unswitched) so we only unswitch if the resultant code will be + smaller than a threshold. +

+ +

+ This pass expects LICM to be run before it to hoist invariant conditions out + of the loop, to make the unswitching opportunity obvious. +

+
+ + + +
+

+ This pass performs several transformations to transform natural loops into a + simpler form, which makes subsequent analyses and transformations simpler and + more effective. +

+ +

+ Loop pre-header insertion guarantees that there is a single, non-critical + entry edge from outside of the loop to the loop header. This simplifies a + number of analyses and transformations, such as LICM. +

+ +

+ Loop exit-block insertion guarantees that all exit blocks from the loop + (blocks which are outside of the loop that have predecessors inside of the + loop) only have predecessors from inside of the loop (and are thus dominated + by the loop header). This simplifies transformations such as store-sinking + that are built into LICM. +

+ +

+ This pass also guarantees that loops will have exactly one backedge. +

+ +

+ Note that the simplifycfg pass will clean up blocks which are split out but + end up being unnecessary, so usage of this pass should not pessimize + generated code. +

+ +

+ This pass obviously modifies the CFG, but updates loop information and + dominator information. +

+
+ + + +
+

+ Turn malloc and free instructions into @malloc and + @free calls. +

+ +

+ This is a target-dependent tranformation because it depends on the size of + data types and alignment constraints. +

+
+ + + +
+

+ This pass lowers atomic intrinsics to non-atomic form for use in a known + non-preemptible environment. +

+ +

+ The pass does not verify that the environment is non-preemptible (in + general this would require knowledge of the entire call graph of the + program including any libraries which may not be available in bitcode form); + it simply lowers every atomic intrinsic. +

+
+ + + +
+

+ This transformation is designed for use by code generators which do not yet + support stack unwinding. This pass supports two models of exception handling + lowering, the 'cheap' support and the 'expensive' support. +

+ +

+ 'Cheap' exception handling support gives the program the ability to execute + any program which does not "throw an exception", by turning 'invoke' + instructions into calls and by turning 'unwind' instructions into calls to + abort(). If the program does dynamically use the unwind instruction, the + program will print a message then abort. +

+ +

+ 'Expensive' exception handling support gives the full exception handling + support to the program at the cost of making the 'invoke' instruction + really expensive. It basically inserts setjmp/longjmp calls to emulate the + exception handling as necessary. +

+ +

+ Because the 'expensive' support slows down programs a lot, and EH is only + used for a subset of the programs, it must be specifically enabled by the + -enable-correct-eh-support option. +

+ +

+ Note that after this pass runs the CFG is not entirely accurate (exceptional + control flow edges are not correct anymore) so only very simple things should + be done after the lowerinvoke pass has run (like generation of native code). + This should not be used as a general purpose "my LLVM-to-LLVM pass doesn't + support the invoke instruction yet" lowering pass. +

+
+ + + +
+

+ Lowers setjmp and longjmp to use the LLVM invoke and unwind + instructions as necessary. +

+ +

+ Lowering of longjmp is fairly trivial. We replace the call with a + call to the LLVM library function __llvm_sjljeh_throw_longjmp(). + This unwinds the stack for us calling all of the destructors for + objects allocated on the stack. +

+ +

+ At a setjmp call, the basic block is split and the setjmp + removed. The calls in a function that have a setjmp are converted to + invoke where the except part checks to see if it's a longjmp + exception and, if so, if it's handled in the function. If it is, then it gets + the value returned by the longjmp and goes to where the basic block + was split. invoke instructions are handled in a similar fashion with + the original except block being executed if it isn't a longjmp + except that is handled by that function. +

+
+ + + +
+

+ Rewrites switch instructions with a sequence of branches, which + allows targets to get away with not implementing the switch instruction until + it is convenient. +

+
+ + + +
+

+ This file promotes memory references to be register references. It promotes + alloca instructions which only have loads and + stores as uses. An alloca is transformed by using dominator + frontiers to place phi nodes, then traversing the function in + depth-first order to rewrite loads and stores as + appropriate. This is just the standard SSA construction algorithm to construct + "pruned" SSA form. +

+
+ + + +
+

+ This pass performs various transformations related to eliminating memcpy + calls, or transforming sets of stores into memset's. +

+
+ + + +
+

This pass looks for equivalent functions that are mergable and folds them. + + A hash is computed from the function, based on its type and number of + basic blocks. + + Once all hashes are computed, we perform an expensive equality comparison + on each function pair. This takes n^2/2 comparisons per bucket, so it's + important that the hash function be high quality. The equality comparison + iterates through each instruction in each basic block. + + When a match is found the functions are folded. If both functions are + overridable, we move the functionality into a new internal function and + leave two overridable thunks to it. +

+
+ + + +
+

+ Ensure that functions have at most one ret instruction in them. + Additionally, it keeps track of which node is the new exit node of the CFG. +

+
+ + + +
+

This pass performs partial inlining, typically by inlining an if + statement that surrounds the body of the function. +

+
+ + + +
+

This pass finds function arguments that are often a common constant and + specializes a version of the called function for that constant. + + This pass simply does the cloning for functions it specializes. It depends + on IPSCCP and DAE to clean up the results. + + The initial heuristic favors constant arguments that are used in control + flow. +

+
+ + + +
+

+ This file implements a simple interprocedural pass which walks the call-graph, + turning invoke instructions into call instructions if and + only if the callee cannot throw an exception. It implements this as a + bottom-up traversal of the call-graph. +

+
+ + + +
+

+ This pass reassociates commutative expressions in an order that is designed + to promote better constant propagation, GCSE, LICM, PRE, etc. +

+ +

+ For example: 4 + (x + 5) ⇒ x + (4 + 5) +

+ +

+ In the implementation of this algorithm, constants are assigned rank = 0, + function arguments are rank = 1, and other values are assigned ranks + corresponding to the reverse post order traversal of current function + (starting at 2), which effectively gives values in deep loops higher rank + than values not in loops. +

+
+ + + +
+

+ This file demotes all registers to memory references. It is intented to be + the inverse of -mem2reg. By converting to + load instructions, the only values live across basic blocks are + alloca instructions and load instructions before + phi nodes. It is intended that this should make CFG hacking much + easier. To make later hacking easier, the entry block is split into two, such + that all introduced alloca instructions (and nothing else) are in the + entry block. +

+
+ + + +
+

+ The well-known scalar replacement of aggregates transformation. This + transform breaks up alloca instructions of aggregate type (structure + or array) into individual alloca instructions for each member if + possible. Then, if possible, it transforms the individual alloca + instructions into nice clean scalar SSA form. +

+ +

+ This combines a simple scalar replacement of aggregates algorithm with the mem2reg algorithm because often interact, + especially for C++ programs. As such, iterating between scalarrepl, + then mem2reg until we run out of things to + promote works well. +

+
+ + + +
+

+ Sparse conditional constant propagation and merging, which can be summarized + as: +

+ +
    +
  1. Assumes values are constant unless proven otherwise
  2. +
  3. Assumes BasicBlocks are dead unless proven otherwise
  4. +
  5. Proves values to be constant, and replaces them with constants
  6. +
  7. Proves conditional branches to be unconditional
  8. +
+ +

+ Note that this pass has a habit of making definitions be dead. It is a good + idea to to run a DCE pass sometime after running this pass. +

+
+ + + +
+

This pass moves instructions into successor blocks, when possible, so that + they aren't executed on paths where their results aren't needed. +

+
+ + + +
+

+ Applies a variety of small optimizations for calls to specific well-known + function calls (e.g. runtime library functions). For example, a call + exit(3) that occurs within the main() function can be + transformed into simply return 3. +

+
+ + + +
+

Simple pass that applies an experimental transformation on calls + to specific functions. +

+
+ + + +
+

+ Performs dead code elimination and basic block merging. Specifically: +

+ +
    +
  1. Removes basic blocks with no predecessors.
  2. +
  3. Merges a basic block into its predecessor if there is only one and the + predecessor only has one successor.
  4. +
  5. Eliminates PHI nodes for basic blocks with a single predecessor.
  6. +
  7. Eliminates a basic block that only contains an unconditional + branch.
  8. +
+
+ + + +
+

This function breaks GEPs with more than 2 non-zero operands into smaller + GEPs each with no more than 2 non-zero operands. This exposes redundancy + between GEPs with common initial operand sequences. +

+
+ + + +
+

This pass converts a list of variables to the Static Single Information + form. + + We are building an on-demand representation, that is, we do not convert + every single variable in the target function to SSI form. Rather, we receive + a list of target variables that must be converted. We also do not + completely convert a target variable to the SSI format. Instead, we only + change the variable in the points where new information can be attached + to its live range, that is, at branch points. +

+
+ + + +
+

A pass that runs SSI on every non-void variable, intended for debugging. +

+
+ + + +
+

+ performs code stripping. this transformation can delete: +

+ +
    +
  1. names for virtual registers
  2. +
  3. symbols for internal globals and functions
  4. +
  5. debug information
  6. +
+ +

+ note that this transformation makes code much less readable, so it should + only be used in situations where the strip utility would be used, + such as reducing code size or making it harder to reverse engineer code. +

+
+ + + +
+

+ This pass loops over all of the functions in the input module, looking for + dead declarations and removes them. Dead declarations are declarations of + functions for which no implementation is available (i.e., declarations for + unused library functions). +

+
+ + + +
+

This pass implements code stripping. Specifically, it can delete:

+
    +
  • names for virtual registers
  • +
  • symbols for internal globals and functions
  • +
  • debug information
  • +
+

+ Note that this transformation makes code much less readable, so it should + only be used in situations where the 'strip' utility would be used, such as + reducing code size or making it harder to reverse engineer code. +

+
+ + + +
+

This pass implements code stripping. Specifically, it can delete:

+
    +
  • names for virtual registers
  • +
  • symbols for internal globals and functions
  • +
  • debug information
  • +
+

+ Note that this transformation makes code much less readable, so it should + only be used in situations where the 'strip' utility would be used, such as + reducing code size or making it harder to reverse engineer code. +

+
+ + + +
+

+ This pass finds functions that return a struct (using a pointer to the struct + as the first argument of the function, marked with the 'sret' attribute) and + replaces them with a new function that simply returns each of the elements of + that struct (using multiple return values). +

+ +

+ This pass works under a number of conditions: +

+ +
    +
  • The returned struct must not contain other structs
  • +
  • The returned struct must only be used to load values from
  • +
  • The placeholder struct passed in is the result of an alloca
  • +
+
+ + + +
+

+ This file transforms calls of the current function (self recursion) followed + by a return instruction with a branch to the entry of the function, creating + a loop. This pass also implements the following extensions to the basic + algorithm: +

+ +
    +
  • Trivial instructions between the call and return do not prevent the + transformation from taking place, though currently the analysis cannot + support moving any really useful instructions (only dead ones). +
  • This pass transforms functions that are prevented from being tail + recursive by an associative expression to use an accumulator variable, + thus compiling the typical naive factorial or fib implementation + into efficient code. +
  • TRE is performed if the function returns void, if the return + returns the result returned by the call, or if the function returns a + run-time constant on all exits from the function. It is possible, though + unlikely, that the return returns something else (like constant 0), and + can still be TRE'd. It can be TRE'd if all other return + instructions in the function return the exact same value. +
  • If it can prove that callees do not access theier caller stack frame, + they are marked as eligible for tail call elimination (by the code + generator). +
+
+ + + +
+

+ This pass performs a limited form of tail duplication, intended to simplify + CFGs by removing some unconditional branches. This pass is necessary to + straighten out loops created by the C front-end, but also is capable of + making other code nicer. After this pass is run, the CFG simplify pass + should be run to clean up the mess. +

+
+ + + +
+

This section describes the LLVM Utility Passes.

+
+ + + +
+

+ Same as dead argument elimination, but deletes arguments to functions which + are external. This is only for use by bugpoint.

+
+ + + +
+

+ This pass is used by bugpoint to extract all blocks from the module into their + own functions.

+
+ + + +
+

This is a little utility pass that gives instructions names, this is mostly + useful when diffing the effect of an optimization because deleting an + unnamed instruction can change all other instruction numbering, making the + diff very noisy. +

+
+ + + +
+

+ Ensures that the module is in the form required by the Module Verifier pass. +

+ +

+ Running the verifier runs this pass automatically, so there should be no need + to use it directly. +

+
+ + + +
+

+ Verifies an LLVM IR code. This is useful to run after an optimization which is + undergoing testing. Note that llvm-as verifies its input before + emitting bitcode, and also that malformed bitcode is likely to make LLVM + crash. All language front-ends are therefore encouraged to verify their output + before performing optimizing transformations. +

+ +
    +
  • Both of a binary operator's parameters are of the same type.
  • +
  • Verify that the indices of mem access instructions match other + operands.
  • +
  • Verify that arithmetic and other things are only performed on + first-class types. Verify that shifts and logicals only happen on + integrals f.e.
  • +
  • All of the constants in a switch statement are of the correct type.
  • +
  • The code is in valid SSA form.
  • +
  • It is illegal to put a label into any other type (like a structure) or + to return one.
  • +
  • Only phi nodes can be self referential: %x = add i32 %x, %x is + invalid.
  • +
  • PHI nodes must have an entry for each predecessor, with no extras.
  • +
  • PHI nodes must be the first thing in a basic block, all grouped + together.
  • +
  • PHI nodes must have at least one entry.
  • +
  • All basic blocks should only end with terminator insts, not contain + them.
  • +
  • The entry node to a function must not have predecessors.
  • +
  • All Instructions must be embedded into a basic block.
  • +
  • Functions cannot take a void-typed parameter.
  • +
  • Verify that a function's argument list agrees with its declared + type.
  • +
  • It is illegal to specify a name for a void value.
  • +
  • It is illegal to have a internal global value with no initializer.
  • +
  • It is illegal to have a ret instruction that returns a value that does + not agree with the function return value type.
  • +
  • Function call argument types match the function prototype.
  • +
  • All other things that are tested by asserts spread about the code.
  • +
+ +

+ Note that this does not provide full security verification (like Java), but + instead just tries to ensure that code is well-formed. +

+
+ + + +
+

+ Displays the control flow graph using the GraphViz tool. +

+
+ + + +
+

+ Displays the control flow graph using the GraphViz tool, but omitting function + bodies. +

+
+ + + +
+

+ Displays the dominator tree using the GraphViz tool. +

+
+ + + +
+

+ Displays the dominator tree using the GraphViz tool, but omitting function + bodies. +

+
+ + + +
+

+ Displays the post dominator tree using the GraphViz tool. +

+
+ + + +
+

+ Displays the post dominator tree using the GraphViz tool, but omitting + function bodies. +

+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Reid Spencer
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/ProgrammersManual.html b/final/docs/ProgrammersManual.html new file mode 100644 index 00000000000..bc09ca957d0 --- /dev/null +++ b/final/docs/ProgrammersManual.html @@ -0,0 +1,3965 @@ + + + + + LLVM Programmer's Manual + + + + +
+ LLVM Programmer's Manual +
+ +
    +
  1. Introduction
  2. +
  3. General Information + +
  4. +
  5. Important and useful LLVM APIs + +
  6. +
  7. Picking the Right Data Structure for a Task + +
  8. +
  9. Helpful Hints for Common Operations + +
  10. + +
  11. Threads and LLVM + +
  12. + +
  13. Advanced Topics +
  14. + +
  15. The Core LLVM Class Hierarchy Reference + +
  16. +
+ + + + + + + +
+ +

This document is meant to highlight some of the important classes and +interfaces available in the LLVM source-base. This manual is not +intended to explain what LLVM is, how it works, and what LLVM code looks +like. It assumes that you know the basics of LLVM and are interested +in writing transformations or otherwise analyzing or manipulating the +code.

+ +

This document should get you oriented so that you can find your +way in the continuously growing source code that makes up the LLVM +infrastructure. Note that this manual is not intended to serve as a +replacement for reading the source code, so if you think there should be +a method in one of these classes to do something, but it's not listed, +check the source. Links to the doxygen sources +are provided to make this as easy as possible.

+ +

The first section of this document describes general information that is +useful to know when working in the LLVM infrastructure, and the second describes +the Core LLVM classes. In the future this manual will be extended with +information describing how to use extension libraries, such as dominator +information, CFG traversal routines, and useful utilities like the InstVisitor template.

+ +
+ + + + + +
+ +

This section contains general information that is useful if you are working +in the LLVM source-base, but that isn't specific to any particular API.

+ +
+ + + + +
+ +

LLVM makes heavy use of the C++ Standard Template Library (STL), +perhaps much more than you are used to, or have seen before. Because of +this, you might want to do a little background reading in the +techniques used and capabilities of the library. There are many good +pages that discuss the STL, and several books on the subject that you +can get, so it will not be discussed in this document.

+ +

Here are some useful links:

+ +
    + +
  1. Dinkumware +C++ Library reference - an excellent reference for the STL and other parts +of the standard C++ library.
  2. + +
  3. C++ In a Nutshell - This is an +O'Reilly book in the making. It has a decent Standard Library +Reference that rivals Dinkumware's, and is unfortunately no longer free since the +book has been published.
  4. + +
  5. C++ Frequently Asked +Questions
  6. + +
  7. SGI's STL Programmer's Guide - +Contains a useful Introduction to the +STL.
  8. + +
  9. Bjarne Stroustrup's C++ +Page
  10. + +
  11. +Bruce Eckel's Thinking in C++, 2nd ed. Volume 2 Revision 4.0 (even better, get +the book).
  12. + +
+ +

You are also encouraged to take a look at the LLVM Coding Standards guide which focuses on how +to write maintainable code more than where to put your curly braces.

+ +
+ + + + + + + + + + +
+ +

Here we highlight some LLVM APIs that are generally useful and good to +know about when writing transformations.

+ +
+ + + + +
+ +

The LLVM source-base makes extensive use of a custom form of RTTI. +These templates have many similarities to the C++ dynamic_cast<> +operator, but they don't have some drawbacks (primarily stemming from +the fact that dynamic_cast<> only works on classes that +have a v-table). Because they are used so often, you must know what they +do and how they work. All of these templates are defined in the llvm/Support/Casting.h +file (note that you very rarely have to include this file directly).

+ +
+
isa<>:
+ +

The isa<> operator works exactly like the Java + "instanceof" operator. It returns true or false depending on whether + a reference or pointer points to an instance of the specified class. This can + be very useful for constraint checking of various sorts (example below).

+
+ +
cast<>:
+ +

The cast<> operator is a "checked cast" operation. It + converts a pointer or reference from a base class to a derived class, causing + an assertion failure if it is not really an instance of the right type. This + should be used in cases where you have some information that makes you believe + that something is of the right type. An example of the isa<> + and cast<> template is:

+ +
+
+static bool isLoopInvariant(const Value *V, const Loop *L) {
+  if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
+    return true;
+
+  // Otherwise, it must be an instruction...
+  return !L->contains(cast<Instruction>(V)->getParent());
+}
+
+
+ +

Note that you should not use an isa<> test followed + by a cast<>, for that use the dyn_cast<> + operator.

+ +
+ +
dyn_cast<>:
+ +

The dyn_cast<> operator is a "checking cast" operation. + It checks to see if the operand is of the specified type, and if so, returns a + pointer to it (this operator does not work with references). If the operand is + not of the correct type, a null pointer is returned. Thus, this works very + much like the dynamic_cast<> operator in C++, and should be + used in the same circumstances. Typically, the dyn_cast<> + operator is used in an if statement or some other flow control + statement like this:

+ +
+
+if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) {
+  // ...
+}
+
+
+ +

This form of the if statement effectively combines together a call + to isa<> and a call to cast<> into one + statement, which is very convenient.

+ +

Note that the dyn_cast<> operator, like C++'s + dynamic_cast<> or Java's instanceof operator, can be + abused. In particular, you should not use big chained if/then/else + blocks to check for lots of different variants of classes. If you find + yourself wanting to do this, it is much cleaner and more efficient to use the + InstVisitor class to dispatch over the instruction type directly.

+ +
+ +
cast_or_null<>:
+ +

The cast_or_null<> operator works just like the + cast<> operator, except that it allows for a null pointer as an + argument (which it then propagates). This can sometimes be useful, allowing + you to combine several null checks into one.

+ +
dyn_cast_or_null<>:
+ +

The dyn_cast_or_null<> operator works just like the + dyn_cast<> operator, except that it allows for a null pointer + as an argument (which it then propagates). This can sometimes be useful, + allowing you to combine several null checks into one.

+ +
+ +

These five templates can be used with any classes, whether they have a +v-table or not. To add support for these templates, you simply need to add +classof static methods to the class you are interested casting +to. Describing this is currently outside the scope of this document, but there +are lots of examples in the LLVM source base.

+ +
+ + + + + +
+ +

Although LLVM generally does not do much string manipulation, we do have +several important APIs which take strings. Two important examples are the +Value class -- which has names for instructions, functions, etc. -- and the +StringMap class which is used extensively in LLVM and Clang.

+ +

These are generic classes, and they need to be able to accept strings which +may have embedded null characters. Therefore, they cannot simply take +a const char *, and taking a const std::string& requires +clients to perform a heap allocation which is usually unnecessary. Instead, +many LLVM APIs use a StringRef or a const Twine& for +passing strings efficiently.

+ +
+ + + + +
+ +

The StringRef data type represents a reference to a constant string +(a character array and a length) and supports the common operations available +on std:string, but does not require heap allocation.

+ +

It can be implicitly constructed using a C style null-terminated string, +an std::string, or explicitly with a character pointer and length. +For example, the StringRef find function is declared as:

+ +
+  iterator find(StringRef Key);
+
+ +

and clients can call it using any one of:

+ +
+  Map.find("foo");                 // Lookup "foo"
+  Map.find(std::string("bar"));    // Lookup "bar"
+  Map.find(StringRef("\0baz", 4)); // Lookup "\0baz"
+
+ +

Similarly, APIs which need to return a string may return a StringRef +instance, which can be used directly or converted to an std::string +using the str member function. See +"llvm/ADT/StringRef.h" +for more information.

+ +

You should rarely use the StringRef class directly, because it contains +pointers to external memory it is not generally safe to store an instance of the +class (unless you know that the external storage will not be freed). StringRef is +small and pervasive enough in LLVM that it should always be passed by value.

+ +
+ + + + +
+ +

The Twine class is an efficient way for APIs to accept concatenated +strings. For example, a common LLVM paradigm is to name one instruction based on +the name of another instruction with a suffix, for example:

+ +
+
+    New = CmpInst::Create(..., SO->getName() + ".cmp");
+
+
+ +

The Twine class is effectively a +lightweight rope +which points to temporary (stack allocated) objects. Twines can be implicitly +constructed as the result of the plus operator applied to strings (i.e., a C +strings, an std::string, or a StringRef). The twine delays the +actual concatenation of strings until it is actually required, at which point +it can be efficiently rendered directly into a character array. This avoids +unnecessary heap allocation involved in constructing the temporary results of +string concatenation. See +"llvm/ADT/Twine.h" +for more information.

+ +

As with a StringRef, Twine objects point to external memory +and should almost never be stored or mentioned directly. They are intended +solely for use when defining a function which should be able to efficiently +accept concatenated strings.

+ +
+ + + + + +
+ +

Often when working on your pass you will put a bunch of debugging printouts +and other code into your pass. After you get it working, you want to remove +it, but you may need it again in the future (to work out new bugs that you run +across).

+ +

Naturally, because of this, you don't want to delete the debug printouts, +but you don't want them to always be noisy. A standard compromise is to comment +them out, allowing you to enable them if you need them in the future.

+ +

The "llvm/Support/Debug.h" +file provides a macro named DEBUG() that is a much nicer solution to +this problem. Basically, you can put arbitrary code into the argument of the +DEBUG macro, and it is only executed if 'opt' (or any other +tool) is run with the '-debug' command line argument:

+ +
+
+DEBUG(errs() << "I am here!\n");
+
+
+ +

Then you can run your pass like this:

+ +
+
+$ opt < a.bc > /dev/null -mypass
+<no output>
+$ opt < a.bc > /dev/null -mypass -debug
+I am here!
+
+
+ +

Using the DEBUG() macro instead of a home-brewed solution allows you +to not have to create "yet another" command line option for the debug output for +your pass. Note that DEBUG() macros are disabled for optimized builds, +so they do not cause a performance impact at all (for the same reason, they +should also not contain side-effects!).

+ +

One additional nice thing about the DEBUG() macro is that you can +enable or disable it directly in gdb. Just use "set DebugFlag=0" or +"set DebugFlag=1" from the gdb if the program is running. If the +program hasn't been started yet, you can always just run it with +-debug.

+ +
+ + + + +
+ +

Sometimes you may find yourself in a situation where enabling -debug +just turns on too much information (such as when working on the code +generator). If you want to enable debug information with more fine-grained +control, you define the DEBUG_TYPE macro and the -debug only +option as follows:

+ +
+
+#undef  DEBUG_TYPE
+DEBUG(errs() << "No debug type\n");
+#define DEBUG_TYPE "foo"
+DEBUG(errs() << "'foo' debug type\n");
+#undef  DEBUG_TYPE
+#define DEBUG_TYPE "bar"
+DEBUG(errs() << "'bar' debug type\n"));
+#undef  DEBUG_TYPE
+#define DEBUG_TYPE ""
+DEBUG(errs() << "No debug type (2)\n");
+
+
+ +

Then you can run your pass like this:

+ +
+
+$ opt < a.bc > /dev/null -mypass
+<no output>
+$ opt < a.bc > /dev/null -mypass -debug
+No debug type
+'foo' debug type
+'bar' debug type
+No debug type (2)
+$ opt < a.bc > /dev/null -mypass -debug-only=foo
+'foo' debug type
+$ opt < a.bc > /dev/null -mypass -debug-only=bar
+'bar' debug type
+
+
+ +

Of course, in practice, you should only set DEBUG_TYPE at the top of +a file, to specify the debug type for the entire module (if you do this before +you #include "llvm/Support/Debug.h", you don't have to insert the ugly +#undef's). Also, you should use names more meaningful than "foo" and +"bar", because there is no system in place to ensure that names do not +conflict. If two different modules use the same string, they will all be turned +on when the name is specified. This allows, for example, all debug information +for instruction scheduling to be enabled with -debug-type=InstrSched, +even if the source lives in multiple files.

+ +

The DEBUG_WITH_TYPE macro is also available for situations where you +would like to set DEBUG_TYPE, but only for one specific DEBUG +statement. It takes an additional first parameter, which is the type to use. For +example, the preceding example could be written as:

+ + +
+
+DEBUG_WITH_TYPE("", errs() << "No debug type\n");
+DEBUG_WITH_TYPE("foo", errs() << "'foo' debug type\n");
+DEBUG_WITH_TYPE("bar", errs() << "'bar' debug type\n"));
+DEBUG_WITH_TYPE("", errs() << "No debug type (2)\n");
+
+
+ +
+ + + + +
+ +

The "llvm/ADT/Statistic.h" file +provides a class named Statistic that is used as a unified way to +keep track of what the LLVM compiler is doing and how effective various +optimizations are. It is useful to see what optimizations are contributing to +making a particular program run faster.

+ +

Often you may run your pass on some big program, and you're interested to see +how many times it makes a certain transformation. Although you can do this with +hand inspection, or some ad-hoc method, this is a real pain and not very useful +for big programs. Using the Statistic class makes it very easy to +keep track of this information, and the calculated information is presented in a +uniform manner with the rest of the passes being executed.

+ +

There are many examples of Statistic uses, but the basics of using +it are as follows:

+ +
    +
  1. Define your statistic like this:

    + +
    +
    +#define DEBUG_TYPE "mypassname"   // This goes before any #includes.
    +STATISTIC(NumXForms, "The # of times I did stuff");
    +
    +
    + +

    The STATISTIC macro defines a static variable, whose name is + specified by the first argument. The pass name is taken from the DEBUG_TYPE + macro, and the description is taken from the second argument. The variable + defined ("NumXForms" in this case) acts like an unsigned integer.

  2. + +
  3. Whenever you make a transformation, bump the counter:

    + +
    +
    +++NumXForms;   // I did stuff!
    +
    +
    + +
  4. +
+ +

That's all you have to do. To get 'opt' to print out the + statistics gathered, use the '-stats' option:

+ +
+
+$ opt -stats -mypassname < program.bc > /dev/null
+... statistics output ...
+
+
+ +

When running opt on a C file from the SPEC benchmark +suite, it gives a report that looks like this:

+ +
+
+   7646 bitcodewriter   - Number of normal instructions
+    725 bitcodewriter   - Number of oversized instructions
+ 129996 bitcodewriter   - Number of bitcode bytes written
+   2817 raise           - Number of insts DCEd or constprop'd
+   3213 raise           - Number of cast-of-self removed
+   5046 raise           - Number of expression trees converted
+     75 raise           - Number of other getelementptr's formed
+    138 raise           - Number of load/store peepholes
+     42 deadtypeelim    - Number of unused typenames removed from symtab
+    392 funcresolve     - Number of varargs functions resolved
+     27 globaldce       - Number of global variables removed
+      2 adce            - Number of basic blocks removed
+    134 cee             - Number of branches revectored
+     49 cee             - Number of setcc instruction eliminated
+    532 gcse            - Number of loads removed
+   2919 gcse            - Number of instructions removed
+     86 indvars         - Number of canonical indvars added
+     87 indvars         - Number of aux indvars removed
+     25 instcombine     - Number of dead inst eliminate
+    434 instcombine     - Number of insts combined
+    248 licm            - Number of load insts hoisted
+   1298 licm            - Number of insts hoisted to a loop pre-header
+      3 licm            - Number of insts hoisted to multiple loop preds (bad, no loop pre-header)
+     75 mem2reg         - Number of alloca's promoted
+   1444 cfgsimplify     - Number of blocks simplified
+
+
+ +

Obviously, with so many optimizations, having a unified framework for this +stuff is very nice. Making your pass fit well into the framework makes it more +maintainable and useful.

+ +
+ + + + +
+ +

Several of the important data structures in LLVM are graphs: for example +CFGs made out of LLVM BasicBlocks, CFGs made out of +LLVM MachineBasicBlocks, and +Instruction Selection +DAGs. In many cases, while debugging various parts of the compiler, it is +nice to instantly visualize these graphs.

+ +

LLVM provides several callbacks that are available in a debug build to do +exactly that. If you call the Function::viewCFG() method, for example, +the current LLVM tool will pop up a window containing the CFG for the function +where each basic block is a node in the graph, and each node contains the +instructions in the block. Similarly, there also exists +Function::viewCFGOnly() (does not include the instructions), the +MachineFunction::viewCFG() and MachineFunction::viewCFGOnly(), +and the SelectionDAG::viewGraph() methods. Within GDB, for example, +you can usually use something like call DAG.viewGraph() to pop +up a window. Alternatively, you can sprinkle calls to these functions in your +code in places you want to debug.

+ +

Getting this to work requires a small amount of configuration. On Unix +systems with X11, install the graphviz +toolkit, and make sure 'dot' and 'gv' are in your path. If you are running on +Mac OS/X, download and install the Mac OS/X Graphviz program, and add +/Applications/Graphviz.app/Contents/MacOS/ (or wherever you install +it) to your path. Once in your system and path are set up, rerun the LLVM +configure script and rebuild LLVM to enable this functionality.

+ +

SelectionDAG has been extended to make it easier to locate +interesting nodes in large complex graphs. From gdb, if you +call DAG.setGraphColor(node, "color"), then the +next call DAG.viewGraph() would highlight the node in the +specified color (choices of colors can be found at colors.) More +complex node attributes can be provided with call +DAG.setGraphAttrs(node, "attributes") (choices can be +found at Graph +Attributes.) If you want to restart and clear all the current graph +attributes, then you can call DAG.clearGraphAttrs().

+ +
+ + + + + +
+ +

LLVM has a plethora of data structures in the llvm/ADT/ directory, + and we commonly use STL data structures. This section describes the trade-offs + you should consider when you pick one.

+ +

+The first step is a choose your own adventure: do you want a sequential +container, a set-like container, or a map-like container? The most important +thing when choosing a container is the algorithmic properties of how you plan to +access the container. Based on that, you should use:

+ +
    +
  • a map-like container if you need efficient look-up + of an value based on another value. Map-like containers also support + efficient queries for containment (whether a key is in the map). Map-like + containers generally do not support efficient reverse mapping (values to + keys). If you need that, use two maps. Some map-like containers also + support efficient iteration through the keys in sorted order. Map-like + containers are the most expensive sort, only use them if you need one of + these capabilities.
  • + +
  • a set-like container if you need to put a bunch of + stuff into a container that automatically eliminates duplicates. Some + set-like containers support efficient iteration through the elements in + sorted order. Set-like containers are more expensive than sequential + containers. +
  • + +
  • a sequential container provides + the most efficient way to add elements and keeps track of the order they are + added to the collection. They permit duplicates and support efficient + iteration, but do not support efficient look-up based on a key. +
  • + +
  • a string container is a specialized sequential + container or reference structure that is used for character or byte + arrays.
  • + +
  • a bit container provides an efficient way to store and + perform set operations on sets of numeric id's, while automatically + eliminating duplicates. Bit containers require a maximum of 1 bit for each + identifier you want to store. +
  • +
+ +

+Once the proper category of container is determined, you can fine tune the +memory use, constant factors, and cache behaviors of access by intelligently +picking a member of the category. Note that constant factors and cache behavior +can be a big deal. If you have a vector that usually only contains a few +elements (but could contain many), for example, it's much better to use +SmallVector than vector +. Doing so avoids (relatively) expensive malloc/free calls, which dwarf the +cost of adding the elements to the container.

+ +
+ + + + +
+There are a variety of sequential containers available for you, based on your +needs. Pick the first in this section that will do what you want. +
+ + + + +
+

Fixed size arrays are very simple and very fast. They are good if you know +exactly how many elements you have, or you have a (low) upper bound on how many +you have.

+
+ + + + +
+

Heap allocated arrays (new[] + delete[]) are also simple. They are good if +the number of elements is variable, if you know how many elements you will need +before the array is allocated, and if the array is usually large (if not, +consider a SmallVector). The cost of a heap +allocated array is the cost of the new/delete (aka malloc/free). Also note that +if you are allocating an array of a type with a constructor, the constructor and +destructors will be run for every element in the array (re-sizable vectors only +construct those elements actually used).

+
+ + + + +
+

SmallVector<Type, N> is a simple class that looks and smells +just like vector<Type>: +it supports efficient iteration, lays out elements in memory order (so you can +do pointer arithmetic between elements), supports efficient push_back/pop_back +operations, supports efficient random access to its elements, etc.

+ +

The advantage of SmallVector is that it allocates space for +some number of elements (N) in the object itself. Because of this, if +the SmallVector is dynamically smaller than N, no malloc is performed. This can +be a big win in cases where the malloc/free call is far more expensive than the +code that fiddles around with the elements.

+ +

This is good for vectors that are "usually small" (e.g. the number of +predecessors/successors of a block is usually less than 8). On the other hand, +this makes the size of the SmallVector itself large, so you don't want to +allocate lots of them (doing so will waste a lot of space). As such, +SmallVectors are most useful when on the stack.

+ +

SmallVector also provides a nice portable and efficient replacement for +alloca.

+ +
+ + + + +
+

+std::vector is well loved and respected. It is useful when SmallVector isn't: +when the size of the vector is often large (thus the small optimization will +rarely be a benefit) or if you will be allocating many instances of the vector +itself (which would waste space for elements that aren't in the container). +vector is also useful when interfacing with code that expects vectors :). +

+ +

One worthwhile note about std::vector: avoid code like this:

+ +
+
+for ( ... ) {
+   std::vector<foo> V;
+   use V;
+}
+
+
+ +

Instead, write this as:

+ +
+
+std::vector<foo> V;
+for ( ... ) {
+   use V;
+   V.clear();
+}
+
+
+ +

Doing so will save (at least) one heap allocation and free per iteration of +the loop.

+ +
+ + +
+ <deque> +
+ +
+

std::deque is, in some senses, a generalized version of std::vector. Like +std::vector, it provides constant time random access and other similar +properties, but it also provides efficient access to the front of the list. It +does not guarantee continuity of elements within memory.

+ +

In exchange for this extra flexibility, std::deque has significantly higher +constant factor costs than std::vector. If possible, use std::vector or +something cheaper.

+
+ + +
+ <list> +
+ +
+

std::list is an extremely inefficient class that is rarely useful. +It performs a heap allocation for every element inserted into it, thus having an +extremely high constant factor, particularly for small data types. std::list +also only supports bidirectional iteration, not random access iteration.

+ +

In exchange for this high cost, std::list supports efficient access to both +ends of the list (like std::deque, but unlike std::vector or SmallVector). In +addition, the iterator invalidation characteristics of std::list are stronger +than that of a vector class: inserting or removing an element into the list does +not invalidate iterator or pointers to other elements in the list.

+
+ + + + +
+

ilist<T> implements an 'intrusive' doubly-linked list. It is +intrusive, because it requires the element to store and provide access to the +prev/next pointers for the list.

+ +

ilist has the same drawbacks as std::list, and additionally +requires an ilist_traits implementation for the element type, but it +provides some novel characteristics. In particular, it can efficiently store +polymorphic objects, the traits class is informed when an element is inserted or +removed from the list, and ilists are guaranteed to support a +constant-time splice operation.

+ +

These properties are exactly what we want for things like +Instructions and basic blocks, which is why these are implemented with +ilists.

+ +Related classes of interest are explained in the following subsections: + +
+ + + + +
+

ilist_traits<T> is ilist<T>'s customization +mechanism. iplist<T> (and consequently ilist<T>) +publicly derive from this traits class.

+
+ + +
+ iplist +
+ +
+

iplist<T> is ilist<T>'s base and as such +supports a slightly narrower interface. Notably, inserters from +T& are absent.

+ +

ilist_traits<T> is a public base of this class and can be +used for a wide variety of customizations.

+
+ + + + +
+

ilist_node<T> implements a the forward and backward links +that are expected by the ilist<T> (and analogous containers) +in the default manner.

+ +

ilist_node<T>s are meant to be embedded in the node type +T, usually T publicly derives from +ilist_node<T>.

+
+ + + + +
+

ilists have another specialty that must be considered. To be a good +citizen in the C++ ecosystem, it needs to support the standard container +operations, such as begin and end iterators, etc. Also, the +operator-- must work correctly on the end iterator in the +case of non-empty ilists.

+ +

The only sensible solution to this problem is to allocate a so-called +sentinel along with the intrusive list, which serves as the end +iterator, providing the back-link to the last element. However conforming to the +C++ convention it is illegal to operator++ beyond the sentinel and it +also must not be dereferenced.

+ +

These constraints allow for some implementation freedom to the ilist +how to allocate and store the sentinel. The corresponding policy is dictated +by ilist_traits<T>. By default a T gets heap-allocated +whenever the need for a sentinel arises.

+ +

While the default policy is sufficient in most cases, it may break down when +T does not provide a default constructor. Also, in the case of many +instances of ilists, the memory overhead of the associated sentinels +is wasted. To alleviate the situation with numerous and voluminous +T-sentinels, sometimes a trick is employed, leading to ghostly +sentinels.

+ +

Ghostly sentinels are obtained by specially-crafted ilist_traits<T> +which superpose the sentinel with the ilist instance in memory. Pointer +arithmetic is used to obtain the sentinel, which is relative to the +ilist's this pointer. The ilist is augmented by an +extra pointer, which serves as the back-link of the sentinel. This is the only +field in the ghostly sentinel which can be legally accessed.

+
+ + + + +
+

Other STL containers are available, such as std::string.

+ +

There are also various STL adapter classes such as std::queue, +std::priority_queue, std::stack, etc. These provide simplified access to an +underlying container but don't affect the cost of the container itself.

+ +
+ + + + + +
+ +

Set-like containers are useful when you need to canonicalize multiple values +into a single representation. There are several different choices for how to do +this, providing various trade-offs.

+ +
+ + + + + +
+ +

If you intend to insert a lot of elements, then do a lot of queries, a +great approach is to use a vector (or other sequential container) with +std::sort+std::unique to remove duplicates. This approach works really well if +your usage pattern has these two distinct phases (insert then query), and can be +coupled with a good choice of sequential container. +

+ +

+This combination provides the several nice properties: the result data is +contiguous in memory (good for cache locality), has few allocations, is easy to +address (iterators in the final vector are just indices or pointers), and can be +efficiently queried with a standard binary or radix search.

+ +
+ + + + +
+ +

If you have a set-like data structure that is usually small and whose elements +are reasonably small, a SmallSet<Type, N> is a good choice. This set +has space for N elements in place (thus, if the set is dynamically smaller than +N, no malloc traffic is required) and accesses them with a simple linear search. +When the set grows beyond 'N' elements, it allocates a more expensive representation that +guarantees efficient access (for most types, it falls back to std::set, but for +pointers it uses something far better, SmallPtrSet).

+ +

The magic of this class is that it handles small sets extremely efficiently, +but gracefully handles extremely large sets without loss of efficiency. The +drawback is that the interface is quite small: it supports insertion, queries +and erasing, but does not support iteration.

+ +
+ + + + +
+ +

SmallPtrSet has all the advantages of SmallSet (and a SmallSet of pointers is +transparently implemented with a SmallPtrSet), but also supports iterators. If +more than 'N' insertions are performed, a single quadratically +probed hash table is allocated and grows as needed, providing extremely +efficient access (constant time insertion/deleting/queries with low constant +factors) and is very stingy with malloc traffic.

+ +

Note that, unlike std::set, the iterators of SmallPtrSet are invalidated +whenever an insertion occurs. Also, the values visited by the iterators are not +visited in sorted order.

+ +
+ + + + +
+ +

+DenseSet is a simple quadratically probed hash table. It excels at supporting +small values: it uses a single allocation to hold all of the pairs that +are currently inserted in the set. DenseSet is a great way to unique small +values that are not simple pointers (use SmallPtrSet for pointers). Note that DenseSet has +the same requirements for the value type that DenseMap has. +

+ +
+ + + + +
+ +

+FoldingSet is an aggregate class that is really good at uniquing +expensive-to-create or polymorphic objects. It is a combination of a chained +hash table with intrusive links (uniqued objects are required to inherit from +FoldingSetNode) that uses SmallVector as part of +its ID process.

+ +

Consider a case where you want to implement a "getOrCreateFoo" method for +a complex object (for example, a node in the code generator). The client has a +description of *what* it wants to generate (it knows the opcode and all the +operands), but we don't want to 'new' a node, then try inserting it into a set +only to find out it already exists, at which point we would have to delete it +and return the node that already exists. +

+ +

To support this style of client, FoldingSet perform a query with a +FoldingSetNodeID (which wraps SmallVector) that can be used to describe the +element that we want to query for. The query either returns the element +matching the ID or it returns an opaque ID that indicates where insertion should +take place. Construction of the ID usually does not require heap traffic.

+ +

Because FoldingSet uses intrusive links, it can support polymorphic objects +in the set (for example, you can have SDNode instances mixed with LoadSDNodes). +Because the elements are individually allocated, pointers to the elements are +stable: inserting or removing elements does not invalidate any pointers to other +elements. +

+ +
+ + +
+ <set> +
+ +
+ +

std::set is a reasonable all-around set class, which is decent at +many things but great at nothing. std::set allocates memory for each element +inserted (thus it is very malloc intensive) and typically stores three pointers +per element in the set (thus adding a large amount of per-element space +overhead). It offers guaranteed log(n) performance, which is not particularly +fast from a complexity standpoint (particularly if the elements of the set are +expensive to compare, like strings), and has extremely high constant factors for +lookup, insertion and removal.

+ +

The advantages of std::set are that its iterators are stable (deleting or +inserting an element from the set does not affect iterators or pointers to other +elements) and that iteration over the set is guaranteed to be in sorted order. +If the elements in the set are large, then the relative overhead of the pointers +and malloc traffic is not a big deal, but if the elements of the set are small, +std::set is almost never a good choice.

+ +
+ + + + +
+

LLVM's SetVector<Type> is an adapter class that combines your choice of +a set-like container along with a Sequential +Container. The important property +that this provides is efficient insertion with uniquing (duplicate elements are +ignored) with iteration support. It implements this by inserting elements into +both a set-like container and the sequential container, using the set-like +container for uniquing and the sequential container for iteration. +

+ +

The difference between SetVector and other sets is that the order of +iteration is guaranteed to match the order of insertion into the SetVector. +This property is really important for things like sets of pointers. Because +pointer values are non-deterministic (e.g. vary across runs of the program on +different machines), iterating over the pointers in the set will +not be in a well-defined order.

+ +

+The drawback of SetVector is that it requires twice as much space as a normal +set and has the sum of constant factors from the set-like container and the +sequential container that it uses. Use it *only* if you need to iterate over +the elements in a deterministic order. SetVector is also expensive to delete +elements out of (linear time), unless you use it's "pop_back" method, which is +faster. +

+ +

SetVector is an adapter class that defaults to using std::vector and std::set +for the underlying containers, so it is quite expensive. However, +"llvm/ADT/SetVector.h" also provides a SmallSetVector class, which +defaults to using a SmallVector and SmallSet of a specified size. If you use +this, and if your sets are dynamically smaller than N, you will save a lot of +heap traffic.

+ +
+ + + + +
+ +

+UniqueVector is similar to SetVector, but it +retains a unique ID for each element inserted into the set. It internally +contains a map and a vector, and it assigns a unique ID for each value inserted +into the set.

+ +

UniqueVector is very expensive: its cost is the sum of the cost of +maintaining both the map and vector, it has high complexity, high constant +factors, and produces a lot of malloc traffic. It should be avoided.

+ +
+ + + + + +
+ +

+The STL provides several other options, such as std::multiset and the various +"hash_set" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable. +

+ +

std::multiset is useful if you're not interested in elimination of +duplicates, but has all the drawbacks of std::set. A sorted vector (where you +don't delete duplicate entries) or some other approach is almost always +better.

+ +
+ + + + +
+Map-like containers are useful when you want to associate data to a key. As +usual, there are a lot of different ways to do this. :) +
+ + + + +
+ +

+If your usage pattern follows a strict insert-then-query approach, you can +trivially use the same approach as sorted vectors +for set-like containers. The only difference is that your query function +(which uses std::lower_bound to get efficient log(n) lookup) should only compare +the key, not both the key and value. This yields the same advantages as sorted +vectors for sets. +

+
+ + + + +
+ +

+Strings are commonly used as keys in maps, and they are difficult to support +efficiently: they are variable length, inefficient to hash and compare when +long, expensive to copy, etc. StringMap is a specialized container designed to +cope with these issues. It supports mapping an arbitrary range of bytes to an +arbitrary other object.

+ +

The StringMap implementation uses a quadratically-probed hash table, where +the buckets store a pointer to the heap allocated entries (and some other +stuff). The entries in the map must be heap allocated because the strings are +variable length. The string data (key) and the element object (value) are +stored in the same allocation with the string data immediately after the element +object. This container guarantees the "(char*)(&Value+1)" points +to the key string for a value.

+ +

The StringMap is very fast for several reasons: quadratic probing is very +cache efficient for lookups, the hash value of strings in buckets is not +recomputed when looking up an element, StringMap rarely has to touch the +memory for unrelated objects when looking up a value (even when hash collisions +happen), hash table growth does not recompute the hash values for strings +already in the table, and each pair in the map is store in a single allocation +(the string data is stored in the same allocation as the Value of a pair).

+ +

StringMap also provides query methods that take byte ranges, so it only ever +copies a string if a value is inserted into the table.

+
+ + + + +
+

+IndexedMap is a specialized container for mapping small dense integers (or +values that can be mapped to small dense integers) to some other type. It is +internally implemented as a vector with a mapping function that maps the keys to +the dense integer range. +

+ +

+This is useful for cases like virtual registers in the LLVM code generator: they +have a dense mapping that is offset by a compile-time constant (the first +virtual register ID).

+ +
+ + + + +
+ +

+DenseMap is a simple quadratically probed hash table. It excels at supporting +small keys and values: it uses a single allocation to hold all of the pairs that +are currently inserted in the map. DenseMap is a great way to map pointers to +pointers, or map other small types to each other. +

+ +

+There are several aspects of DenseMap that you should be aware of, however. The +iterators in a densemap are invalidated whenever an insertion occurs, unlike +map. Also, because DenseMap allocates space for a large number of key/value +pairs (it starts with 64 by default), it will waste a lot of space if your keys +or values are large. Finally, you must implement a partial specialization of +DenseMapInfo for the key that you want, if it isn't already supported. This +is required to tell DenseMap about two special marker values (which can never be +inserted into the map) that it needs internally.

+ +
+ + + + +
+ +

+ValueMap is a wrapper around a DenseMap mapping +Value*s (or subclasses) to another type. When a Value is deleted or RAUW'ed, +ValueMap will update itself so the new version of the key is mapped to the same +value, just as if the key were a WeakVH. You can configure exactly how this +happens, and what else happens on these two events, by passing +a Config parameter to the ValueMap template.

+ +
+ + + + +
+ +

IntervalMap is a compact map for small keys and values. It maps key +intervals instead of single keys, and it will automatically coalesce adjacent +intervals. When then map only contains a few intervals, they are stored in the +map object itself to avoid allocations.

+ +

The IntervalMap iterators are quite big, so they should not be passed around +as STL iterators. The heavyweight iterators allow a smaller data structure.

+ +
+ + +
+ <map> +
+ +
+ +

+std::map has similar characteristics to std::set: it uses +a single allocation per pair inserted into the map, it offers log(n) lookup with +an extremely large constant factor, imposes a space penalty of 3 pointers per +pair in the map, etc.

+ +

std::map is most useful when your keys or values are very large, if you need +to iterate over the collection in sorted order, or if you need stable iterators +into the map (i.e. they don't get invalidated if an insertion or deletion of +another element takes place).

+ +
+ + + + +
+ +

+The STL provides several other options, such as std::multimap and the various +"hash_map" like containers (whether from C++ TR1 or from the SGI library). We +never use hash_set and unordered_set because they are generally very expensive +(each insertion requires a malloc) and very non-portable.

+ +

std::multimap is useful if you want to map a key to multiple values, but has +all the drawbacks of std::map. A sorted vector or some other approach is almost +always better.

+ +
+ + + + +
+ +

+TODO: const char* vs stringref vs smallstring vs std::string. Describe twine, +xref to #string_apis. +

+ +
+ + + + +
+

Unlike the other containers, there are only two bit storage containers, and +choosing when to use each is relatively straightforward.

+ +

One additional option is +std::vector<bool>: we discourage its use for two reasons 1) the +implementation in many common compilers (e.g. commonly available versions of +GCC) is extremely inefficient and 2) the C++ standards committee is likely to +deprecate this container and/or change it significantly somehow. In any case, +please don't use it.

+
+ + + + +
+

The BitVector container provides a dynamic size set of bits for manipulation. +It supports individual bit setting/testing, as well as set operations. The set +operations take time O(size of bitvector), but operations are performed one word +at a time, instead of one bit at a time. This makes the BitVector very fast for +set operations compared to other containers. Use the BitVector when you expect +the number of set bits to be high (IE a dense set). +

+
+ + + + +
+

The SmallBitVector container provides the same interface as BitVector, but +it is optimized for the case where only a small number of bits, less than +25 or so, are needed. It also transparently supports larger bit counts, but +slightly less efficiently than a plain BitVector, so SmallBitVector should +only be used when larger counts are rare. +

+ +

+At this time, SmallBitVector does not support set operations (and, or, xor), +and its operator[] does not provide an assignable lvalue. +

+
+ + + + +
+

The SparseBitVector container is much like BitVector, with one major +difference: Only the bits that are set, are stored. This makes the +SparseBitVector much more space efficient than BitVector when the set is sparse, +as well as making set operations O(number of set bits) instead of O(size of +universe). The downside to the SparseBitVector is that setting and testing of random bits is O(N), and on large SparseBitVectors, this can be slower than BitVector. In our implementation, setting or testing bits in sorted order +(either forwards or reverse) is O(1) worst case. Testing and setting bits within 128 bits (depends on size) of the current bit is also O(1). As a general statement, testing/setting bits in a SparseBitVector is O(distance away from last set bit). +

+
+ + + + + +
+ +

This section describes how to perform some very simple transformations of +LLVM code. This is meant to give examples of common idioms used, showing the +practical side of LLVM transformations.

Because this is a "how-to" section, +you should also read about the main classes that you will be working with. The +Core LLVM Class Hierarchy Reference contains details +and descriptions of the main classes that you should know about.

+ +
+ + + + + +
+ +

The LLVM compiler infrastructure have many different data structures that may +be traversed. Following the example of the C++ standard template library, the +techniques used to traverse these various data structures are all basically the +same. For a enumerable sequence of values, the XXXbegin() function (or +method) returns an iterator to the start of the sequence, the XXXend() +function returns an iterator pointing to one past the last valid element of the +sequence, and there is some XXXiterator data type that is common +between the two operations.

+ +

Because the pattern for iteration is common across many different aspects of +the program representation, the standard template library algorithms may be used +on them, and it is easier to remember how to iterate. First we show a few common +examples of the data structures that need to be traversed. Other data +structures are traversed in very similar ways.

+ +
+ + + + +
+ +

It's quite common to have a Function instance that you'd like to +transform in some way; in particular, you'd like to manipulate its +BasicBlocks. To facilitate this, you'll need to iterate over all of +the BasicBlocks that constitute the Function. The following is +an example that prints the name of a BasicBlock and the number of +Instructions it contains:

+ +
+
+// func is a pointer to a Function instance
+for (Function::iterator i = func->begin(), e = func->end(); i != e; ++i)
+  // Print out the name of the basic block if it has one, and then the
+  // number of instructions that it contains
+  errs() << "Basic block (name=" << i->getName() << ") has "
+             << i->size() << " instructions.\n";
+
+
+ +

Note that i can be used as if it were a pointer for the purposes of +invoking member functions of the Instruction class. This is +because the indirection operator is overloaded for the iterator +classes. In the above code, the expression i->size() is +exactly equivalent to (*i).size() just like you'd expect.

+ +
+ + + + +
+ +

Just like when dealing with BasicBlocks in Functions, it's +easy to iterate over the individual instructions that make up +BasicBlocks. Here's a code snippet that prints out each instruction in +a BasicBlock:

+ +
+
+// blk is a pointer to a BasicBlock instance
+for (BasicBlock::iterator i = blk->begin(), e = blk->end(); i != e; ++i)
+   // The next statement works since operator<<(ostream&,...)
+   // is overloaded for Instruction&
+   errs() << *i << "\n";
+
+
+ +

However, this isn't really the best way to print out the contents of a +BasicBlock! Since the ostream operators are overloaded for virtually +anything you'll care about, you could have just invoked the print routine on the +basic block itself: errs() << *blk << "\n";.

+ +
+ + + + +
+ +

If you're finding that you commonly iterate over a Function's +BasicBlocks and then that BasicBlock's Instructions, +InstIterator should be used instead. You'll need to include llvm/Support/InstIterator.h, +and then instantiate InstIterators explicitly in your code. Here's a +small example that shows how to dump all instructions in a function to the standard error stream:

+ +

+
+#include "llvm/Support/InstIterator.h"
+
+// F is a pointer to a Function instance
+for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
+  errs() << *I << "\n";
+
+
+ +

Easy, isn't it? You can also use InstIterators to fill a +work list with its initial contents. For example, if you wanted to +initialize a work list to contain all instructions in a Function +F, all you would need to do is something like:

+ +
+
+std::set<Instruction*> worklist;
+// or better yet, SmallPtrSet<Instruction*, 64> worklist;
+
+for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
+   worklist.insert(&*I);
+
+
+ +

The STL set worklist would now contain all instructions in the +Function pointed to by F.

+ +
+ + + + +
+ +

Sometimes, it'll be useful to grab a reference (or pointer) to a class +instance when all you've got at hand is an iterator. Well, extracting +a reference or a pointer from an iterator is very straight-forward. +Assuming that i is a BasicBlock::iterator and j +is a BasicBlock::const_iterator:

+ +
+
+Instruction& inst = *i;   // Grab reference to instruction reference
+Instruction* pinst = &*i; // Grab pointer to instruction reference
+const Instruction& inst = *j;
+
+
+ +

However, the iterators you'll be working with in the LLVM framework are +special: they will automatically convert to a ptr-to-instance type whenever they +need to. Instead of dereferencing the iterator and then taking the address of +the result, you can simply assign the iterator to the proper pointer type and +you get the dereference and address-of operation as a result of the assignment +(behind the scenes, this is a result of overloading casting mechanisms). Thus +the last line of the last example,

+ +
+
+Instruction *pinst = &*i;
+
+
+ +

is semantically equivalent to

+ +
+
+Instruction *pinst = i;
+
+
+ +

It's also possible to turn a class pointer into the corresponding iterator, +and this is a constant time operation (very efficient). The following code +snippet illustrates use of the conversion constructors provided by LLVM +iterators. By using these, you can explicitly grab the iterator of something +without actually obtaining it via iteration over some structure:

+ +
+
+void printNextInstruction(Instruction* inst) {
+  BasicBlock::iterator it(inst);
+  ++it; // After this line, it refers to the instruction after *inst
+  if (it != inst->getParent()->end()) errs() << *it << "\n";
+}
+
+
+ +

Unfortunately, these implicit conversions come at a cost; they prevent +these iterators from conforming to standard iterator conventions, and thus +from being usable with standard algorithms and containers. For example, they +prevent the following code, where B is a BasicBlock, +from compiling:

+ +
+
+  llvm::SmallVector<llvm::Instruction *, 16>(B->begin(), B->end());
+
+
+ +

Because of this, these implicit conversions may be removed some day, +and operator* changed to return a pointer instead of a reference.

+ +
+ + + + +
+ +

Say that you're writing a FunctionPass and would like to count all the +locations in the entire module (that is, across every Function) where a +certain function (i.e., some Function*) is already in scope. As you'll +learn later, you may want to use an InstVisitor to accomplish this in a +much more straight-forward manner, but this example will allow us to explore how +you'd do it if you didn't have InstVisitor around. In pseudo-code, this +is what we want to do:

+ +
+
+initialize callCounter to zero
+for each Function f in the Module
+  for each BasicBlock b in f
+    for each Instruction i in b
+      if (i is a CallInst and calls the given function)
+        increment callCounter
+
+
+ +

And the actual code is (remember, because we're writing a +FunctionPass, our FunctionPass-derived class simply has to +override the runOnFunction method):

+ +
+
+Function* targetFunc = ...;
+
+class OurFunctionPass : public FunctionPass {
+  public:
+    OurFunctionPass(): callCounter(0) { }
+
+    virtual runOnFunction(Function& F) {
+      for (Function::iterator b = F.begin(), be = F.end(); b != be; ++b) {
+        for (BasicBlock::iterator i = b->begin(), ie = b->end(); i != ie; ++i) {
+          if (CallInst* callInst = dyn_cast<CallInst>(&*i)) {
+            // We know we've encountered a call instruction, so we
+            // need to determine if it's a call to the
+            // function pointed to by m_func or not.
+            if (callInst->getCalledFunction() == targetFunc)
+              ++callCounter;
+          }
+        }
+      }
+    }
+
+  private:
+    unsigned callCounter;
+};
+
+
+ +
+ + + + +
+ +

You may have noticed that the previous example was a bit oversimplified in +that it did not deal with call sites generated by 'invoke' instructions. In +this, and in other situations, you may find that you want to treat +CallInsts and InvokeInsts the same way, even though their +most-specific common base class is Instruction, which includes lots of +less closely-related things. For these cases, LLVM provides a handy wrapper +class called CallSite. +It is essentially a wrapper around an Instruction pointer, with some +methods that provide functionality common to CallInsts and +InvokeInsts.

+ +

This class has "value semantics": it should be passed by value, not by +reference and it should not be dynamically allocated or deallocated using +operator new or operator delete. It is efficiently copyable, +assignable and constructable, with costs equivalents to that of a bare pointer. +If you look at its definition, it has only a single pointer member.

+ +
+ + + + +
+ +

Frequently, we might have an instance of the Value Class and we want to +determine which Users use the Value. The list of all +Users of a particular Value is called a def-use chain. +For example, let's say we have a Function* named F to a +particular function foo. Finding all of the instructions that +use foo is as simple as iterating over the def-use chain +of F:

+ +
+
+Function *F = ...;
+
+for (Value::use_iterator i = F->use_begin(), e = F->use_end(); i != e; ++i)
+  if (Instruction *Inst = dyn_cast<Instruction>(*i)) {
+    errs() << "F is used in instruction:\n";
+    errs() << *Inst << "\n";
+  }
+
+
+ +

Note that dereferencing a Value::use_iterator is not a very cheap +operation. Instead of performing *i above several times, consider +doing it only once in the loop body and reusing its result.

+ +

Alternatively, it's common to have an instance of the User Class and need to know what +Values are used by it. The list of all Values used by a +User is known as a use-def chain. Instances of class +Instruction are common Users, so we might want to iterate over +all of the values that a particular instruction uses (that is, the operands of +the particular Instruction):

+ +
+
+Instruction *pi = ...;
+
+for (User::op_iterator i = pi->op_begin(), e = pi->op_end(); i != e; ++i) {
+  Value *v = *i;
+  // ...
+}
+
+
+ +

Declaring objects as const is an important tool of enforcing +mutation free algorithms (such as analyses, etc.). For this purpose above +iterators come in constant flavors as Value::const_use_iterator +and Value::const_op_iterator. They automatically arise when +calling use/op_begin() on const Value*s or +const User*s respectively. Upon dereferencing, they return +const Use*s. Otherwise the above patterns remain unchanged.

+ +
+ + + + +
+ +

Iterating over the predecessors and successors of a block is quite easy +with the routines defined in "llvm/Support/CFG.h". Just use code like +this to iterate over all predecessors of BB:

+ +
+
+#include "llvm/Support/CFG.h"
+BasicBlock *BB = ...;
+
+for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
+  BasicBlock *Pred = *PI;
+  // ...
+}
+
+
+ +

Similarly, to iterate over successors use +succ_iterator/succ_begin/succ_end.

+ +
+ + + + + +
+ +

There are some primitive transformation operations present in the LLVM +infrastructure that are worth knowing about. When performing +transformations, it's fairly common to manipulate the contents of basic +blocks. This section describes some of the common methods for doing so +and gives example code.

+ +
+ + + + +
+ +

Instantiating Instructions

+ +

Creation of Instructions is straight-forward: simply call the +constructor for the kind of instruction to instantiate and provide the necessary +parameters. For example, an AllocaInst only requires a +(const-ptr-to) Type. Thus:

+ +
+
+AllocaInst* ai = new AllocaInst(Type::Int32Ty);
+
+
+ +

will create an AllocaInst instance that represents the allocation of +one integer in the current stack frame, at run time. Each Instruction +subclass is likely to have varying default parameters which change the semantics +of the instruction, so refer to the doxygen documentation for the subclass of +Instruction that you're interested in instantiating.

+ +

Naming values

+ +

It is very useful to name the values of instructions when you're able to, as +this facilitates the debugging of your transformations. If you end up looking +at generated LLVM machine code, you definitely want to have logical names +associated with the results of instructions! By supplying a value for the +Name (default) parameter of the Instruction constructor, you +associate a logical name with the result of the instruction's execution at +run time. For example, say that I'm writing a transformation that dynamically +allocates space for an integer on the stack, and that integer is going to be +used as some kind of index by some other code. To accomplish this, I place an +AllocaInst at the first point in the first BasicBlock of some +Function, and I'm intending to use it within the same +Function. I might do:

+ +
+
+AllocaInst* pa = new AllocaInst(Type::Int32Ty, 0, "indexLoc");
+
+
+ +

where indexLoc is now the logical name of the instruction's +execution value, which is a pointer to an integer on the run time stack.

+ +

Inserting instructions

+ +

There are essentially two ways to insert an Instruction +into an existing sequence of instructions that form a BasicBlock:

+ +
    +
  • Insertion into an explicit instruction list + +

    Given a BasicBlock* pb, an Instruction* pi within that + BasicBlock, and a newly-created instruction we wish to insert + before *pi, we do the following:

    + +
    +
    +BasicBlock *pb = ...;
    +Instruction *pi = ...;
    +Instruction *newInst = new Instruction(...);
    +
    +pb->getInstList().insert(pi, newInst); // Inserts newInst before pi in pb
    +
    +
    + +

    Appending to the end of a BasicBlock is so common that + the Instruction class and Instruction-derived + classes provide constructors which take a pointer to a + BasicBlock to be appended to. For example code that + looked like:

    + +
    +
    +BasicBlock *pb = ...;
    +Instruction *newInst = new Instruction(...);
    +
    +pb->getInstList().push_back(newInst); // Appends newInst to pb
    +
    +
    + +

    becomes:

    + +
    +
    +BasicBlock *pb = ...;
    +Instruction *newInst = new Instruction(..., pb);
    +
    +
    + +

    which is much cleaner, especially if you are creating + long instruction streams.

  • + +
  • Insertion into an implicit instruction list + +

    Instruction instances that are already in BasicBlocks + are implicitly associated with an existing instruction list: the instruction + list of the enclosing basic block. Thus, we could have accomplished the same + thing as the above code without being given a BasicBlock by doing: +

    + +
    +
    +Instruction *pi = ...;
    +Instruction *newInst = new Instruction(...);
    +
    +pi->getParent()->getInstList().insert(pi, newInst);
    +
    +
    + +

    In fact, this sequence of steps occurs so frequently that the + Instruction class and Instruction-derived classes provide + constructors which take (as a default parameter) a pointer to an + Instruction which the newly-created Instruction should + precede. That is, Instruction constructors are capable of + inserting the newly-created instance into the BasicBlock of a + provided instruction, immediately before that instruction. Using an + Instruction constructor with a insertBefore (default) + parameter, the above code becomes:

    + +
    +
    +Instruction* pi = ...;
    +Instruction* newInst = new Instruction(..., pi);
    +
    +
    + +

    which is much cleaner, especially if you're creating a lot of + instructions and adding them to BasicBlocks.

  • +
+ +
+ + + + +
+ +

Deleting an instruction from an existing sequence of instructions that form a +BasicBlock is very straight-forward. First, +you must have a pointer to the instruction that you wish to delete. Second, you +need to obtain the pointer to that instruction's basic block. You use the +pointer to the basic block to get its list of instructions and then use the +erase function to remove your instruction. For example:

+ +
+
+Instruction *I = .. ;
+I->eraseFromParent();
+
+
+ +
+ + + + +
+ +

Replacing individual instructions

+ +

Including "llvm/Transforms/Utils/BasicBlockUtils.h" +permits use of two very useful replace functions: ReplaceInstWithValue +and ReplaceInstWithInst.

+ +

Deleting Instructions

+ +
    +
  • ReplaceInstWithValue + +

    This function replaces all uses of a given instruction with a value, + and then removes the original instruction. The following example + illustrates the replacement of the result of a particular + AllocaInst that allocates memory for a single integer with a null + pointer to an integer.

    + +
    +
    +AllocaInst* instToReplace = ...;
    +BasicBlock::iterator ii(instToReplace);
    +
    +ReplaceInstWithValue(instToReplace->getParent()->getInstList(), ii,
    +                     Constant::getNullValue(PointerType::getUnqual(Type::Int32Ty)));
    +
  • + +
  • ReplaceInstWithInst + +

    This function replaces a particular instruction with another + instruction, inserting the new instruction into the basic block at the + location where the old instruction was, and replacing any uses of the old + instruction with the new instruction. The following example illustrates + the replacement of one AllocaInst with another.

    + +
    +
    +AllocaInst* instToReplace = ...;
    +BasicBlock::iterator ii(instToReplace);
    +
    +ReplaceInstWithInst(instToReplace->getParent()->getInstList(), ii,
    +                    new AllocaInst(Type::Int32Ty, 0, "ptrToReplacedInt"));
    +
  • +
+ +

Replacing multiple uses of Users and Values

+ +

You can use Value::replaceAllUsesWith and +User::replaceUsesOfWith to change more than one use at a time. See the +doxygen documentation for the Value Class +and User Class, respectively, for more +information.

+ + + +
+ + + + +
+ +

Deleting a global variable from a module is just as easy as deleting an +Instruction. First, you must have a pointer to the global variable that you wish + to delete. You use this pointer to erase it from its parent, the module. + For example:

+ +
+
+GlobalVariable *GV = .. ;
+
+GV->eraseFromParent();
+
+
+ +
+ + + + +
+ +

In generating IR, you may need some complex types. If you know these types +statically, you can use TypeBuilder<...>::get(), defined +in llvm/Support/TypeBuilder.h, to retrieve them. TypeBuilder +has two forms depending on whether you're building types for cross-compilation +or native library use. TypeBuilder<T, true> requires +that T be independent of the host environment, meaning that it's built +out of types from +the llvm::types +namespace and pointers, functions, arrays, etc. built of +those. TypeBuilder<T, false> additionally allows native C types +whose size may depend on the host compiler. For example,

+ +
+
+FunctionType *ft = TypeBuilder<types::i<8>(types::i<32>*), true>::get();
+
+
+ +

is easier to read and write than the equivalent

+ +
+
+std::vector<const Type*> params;
+params.push_back(PointerType::getUnqual(Type::Int32Ty));
+FunctionType *ft = FunctionType::get(Type::Int8Ty, params, false);
+
+
+ +

See the class +comment for more details.

+ +
+ + + + + +
+

+This section describes the interaction of the LLVM APIs with multithreading, +both on the part of client applications, and in the JIT, in the hosted +application. +

+ +

+Note that LLVM's support for multithreading is still relatively young. Up +through version 2.5, the execution of threaded hosted applications was +supported, but not threaded client access to the APIs. While this use case is +now supported, clients must adhere to the guidelines specified below to +ensure proper operation in multithreaded mode. +

+ +

+Note that, on Unix-like platforms, LLVM requires the presence of GCC's atomic +intrinsics in order to support threaded operation. If you need a +multhreading-capable LLVM on a platform without a suitably modern system +compiler, consider compiling LLVM and LLVM-GCC in single-threaded mode, and +using the resultant compiler to build a copy of LLVM with multithreading +support. +

+
+ + + + +
+ +

+In order to properly protect its internal data structures while avoiding +excessive locking overhead in the single-threaded case, the LLVM must intialize +certain data structures necessary to provide guards around its internals. To do +so, the client program must invoke llvm_start_multithreaded() before +making any concurrent LLVM API calls. To subsequently tear down these +structures, use the llvm_stop_multithreaded() call. You can also use +the llvm_is_multithreaded() call to check the status of multithreaded +mode. +

+ +

+Note that both of these calls must be made in isolation. That is to +say that no other LLVM API calls may be executing at any time during the +execution of llvm_start_multithreaded() or llvm_stop_multithreaded +. It's is the client's responsibility to enforce this isolation. +

+ +

+The return value of llvm_start_multithreaded() indicates the success or +failure of the initialization. Failure typically indicates that your copy of +LLVM was built without multithreading support, typically because GCC atomic +intrinsics were not found in your system compiler. In this case, the LLVM API +will not be safe for concurrent calls. However, it will be safe for +hosting threaded applications in the JIT, though care +must be taken to ensure that side exits and the like do not accidentally +result in concurrent LLVM API calls. +

+
+ + + + +
+

+When you are done using the LLVM APIs, you should call llvm_shutdown() +to deallocate memory used for internal structures. This will also invoke +llvm_stop_multithreaded() if LLVM is operating in multithreaded mode. +As such, llvm_shutdown() requires the same isolation guarantees as +llvm_stop_multithreaded(). +

+ +

+Note that, if you use scope-based shutdown, you can use the +llvm_shutdown_obj class, which calls llvm_shutdown() in its +destructor. +

+ + + + +
+

+ManagedStatic is a utility class in LLVM used to implement static +initialization of static resources, such as the global type tables. Before the +invocation of llvm_shutdown(), it implements a simple lazy +initialization scheme. Once llvm_start_multithreaded() returns, +however, it uses double-checked locking to implement thread-safe lazy +initialization. +

+ +

+Note that, because no other threads are allowed to issue LLVM API calls before +llvm_start_multithreaded() returns, it is possible to have +ManagedStatics of llvm::sys::Mutexs. +

+ +

+The llvm_acquire_global_lock() and llvm_release_global_lock +APIs provide access to the global lock used to implement the double-checked +locking for lazy initialization. These should only be used internally to LLVM, +and only if you know what you're doing! +

+
+ + + + +
+

+LLVMContext is an opaque class in the LLVM API which clients can use +to operate multiple, isolated instances of LLVM concurrently within the same +address space. For instance, in a hypothetical compile-server, the compilation +of an individual translation unit is conceptually independent from all the +others, and it would be desirable to be able to compile incoming translation +units concurrently on independent server threads. Fortunately, +LLVMContext exists to enable just this kind of scenario! +

+ +

+Conceptually, LLVMContext provides isolation. Every LLVM entity +(Modules, Values, Types, Constants, etc.) +in LLVM's in-memory IR belongs to an LLVMContext. Entities in +different contexts cannot interact with each other: Modules in +different contexts cannot be linked together, Functions cannot be added +to Modules in different contexts, etc. What this means is that is is +safe to compile on multiple threads simultaneously, as long as no two threads +operate on entities within the same context. +

+ +

+In practice, very few places in the API require the explicit specification of a +LLVMContext, other than the Type creation/lookup APIs. +Because every Type carries a reference to its owning context, most +other entities can determine what context they belong to by looking at their +own Type. If you are adding new entities to LLVM IR, please try to +maintain this interface design. +

+ +

+For clients that do not require the benefits of isolation, LLVM +provides a convenience API getGlobalContext(). This returns a global, +lazily initialized LLVMContext that may be used in situations where +isolation is not a concern. +

+
+ + + + +
+

+LLVM's "eager" JIT compiler is safe to use in threaded programs. Multiple +threads can call ExecutionEngine::getPointerToFunction() or +ExecutionEngine::runFunction() concurrently, and multiple threads can +run code output by the JIT concurrently. The user must still ensure that only +one thread accesses IR in a given LLVMContext while another thread +might be modifying it. One way to do that is to always hold the JIT lock while +accessing IR outside the JIT (the JIT modifies the IR by adding +CallbackVHs). Another way is to only +call getPointerToFunction() from the LLVMContext's thread. +

+ +

When the JIT is configured to compile lazily (using +ExecutionEngine::DisableLazyCompilation(false)), there is currently a +race condition in +updating call sites after a function is lazily-jitted. It's still possible to +use the lazy JIT in a threaded program if you ensure that only one thread at a +time can call any particular lazy stub and that the JIT lock guards any IR +access, but we suggest using only the eager JIT in threaded programs. +

+
+ + + + + +
+

+This section describes some of the advanced or obscure API's that most clients +do not need to be aware of. These API's tend manage the inner workings of the +LLVM system, and only need to be accessed in unusual circumstances. +

+
+ + + + +
+ +

+The LLVM type system has a very simple goal: allow clients to compare types for +structural equality with a simple pointer comparison (aka a shallow compare). +This goal makes clients much simpler and faster, and is used throughout the LLVM +system. +

+ +

+Unfortunately achieving this goal is not a simple matter. In particular, +recursive types and late resolution of opaque types makes the situation very +difficult to handle. Fortunately, for the most part, our implementation makes +most clients able to be completely unaware of the nasty internal details. The +primary case where clients are exposed to the inner workings of it are when +building a recursive type. In addition to this case, the LLVM bitcode reader, +assembly parser, and linker also have to be aware of the inner workings of this +system. +

+ +

+For our purposes below, we need three concepts. First, an "Opaque Type" is +exactly as defined in the language +reference. Second an "Abstract Type" is any type which includes an +opaque type as part of its type graph (for example "{ opaque, i32 }"). +Third, a concrete type is a type that is not an abstract type (e.g. "{ i32, +float }"). +

+ +
+ + + + +
+ +

+Because the most common question is "how do I build a recursive type with LLVM", +we answer it now and explain it as we go. Here we include enough to cause this +to be emitted to an output .ll file: +

+ +
+
+%mylist = type { %mylist*, i32 }
+
+
+ +

+To build this, use the following LLVM APIs: +

+ +
+
+// Create the initial outer struct
+PATypeHolder StructTy = OpaqueType::get();
+std::vector<const Type*> Elts;
+Elts.push_back(PointerType::getUnqual(StructTy));
+Elts.push_back(Type::Int32Ty);
+StructType *NewSTy = StructType::get(Elts);
+
+// At this point, NewSTy = "{ opaque*, i32 }". Tell VMCore that
+// the struct and the opaque type are actually the same.
+cast<OpaqueType>(StructTy.get())->refineAbstractTypeTo(NewSTy);
+
+// NewSTy is potentially invalidated, but StructTy (a PATypeHolder) is
+// kept up-to-date
+NewSTy = cast<StructType>(StructTy.get());
+
+// Add a name for the type to the module symbol table (optional)
+MyModule->addTypeName("mylist", NewSTy);
+
+
+ +

+This code shows the basic approach used to build recursive types: build a +non-recursive type using 'opaque', then use type unification to close the cycle. +The type unification step is performed by the refineAbstractTypeTo method, which is +described next. After that, we describe the PATypeHolder class. +

+ +
+ + + + +
+

+The refineAbstractTypeTo method starts the type unification process. +While this method is actually a member of the DerivedType class, it is most +often used on OpaqueType instances. Type unification is actually a recursive +process. After unification, types can become structurally isomorphic to +existing types, and all duplicates are deleted (to preserve pointer equality). +

+ +

+In the example above, the OpaqueType object is definitely deleted. +Additionally, if there is an "{ \2*, i32}" type already created in the system, +the pointer and struct type created are also deleted. Obviously whenever +a type is deleted, any "Type*" pointers in the program are invalidated. As +such, it is safest to avoid having any "Type*" pointers to abstract types +live across a call to refineAbstractTypeTo (note that non-abstract +types can never move or be deleted). To deal with this, the PATypeHolder class is used to maintain a stable +reference to a possibly refined type, and the AbstractTypeUser class is used to update more +complex datastructures. +

+ +
+ + + + +
+

+PATypeHolder is a form of a "smart pointer" for Type objects. When VMCore +happily goes about nuking types that become isomorphic to existing types, it +automatically updates all PATypeHolder objects to point to the new type. In the +example above, this allows the code to maintain a pointer to the resultant +resolved recursive type, even though the Type*'s are potentially invalidated. +

+ +

+PATypeHolder is an extremely light-weight object that uses a lazy union-find +implementation to update pointers. For example the pointer from a Value to its +Type is maintained by PATypeHolder objects. +

+ +
+ + + + +
+ +

+Some data structures need more to perform more complex updates when types get +resolved. To support this, a class can derive from the AbstractTypeUser class. +This class +allows it to get callbacks when certain types are resolved. To register to get +callbacks for a particular type, the DerivedType::{add/remove}AbstractTypeUser +methods can be called on a type. Note that these methods only work for + abstract types. Concrete types (those that do not include any opaque +objects) can never be refined. +

+
+ + + + + +
+

The +ValueSymbolTable class provides a symbol table that the Function and +Module classes use for naming value definitions. The symbol table +can provide a name for any Value. +The +TypeSymbolTable class is used by the Module class to store +names for types.

+ +

Note that the SymbolTable class should not be directly accessed +by most clients. It should only be used when iteration over the symbol table +names themselves are required, which is very special purpose. Note that not +all LLVM +Values have names, and those without names (i.e. they have +an empty name) do not exist in the symbol table. +

+ +

These symbol tables support iteration over the values/types in the symbol +table with begin/end/iterator and supports querying to see if a +specific name is in the symbol table (with lookup). The +ValueSymbolTable class exposes no public mutator methods, instead, +simply call setName on a value, which will autoinsert it into the +appropriate symbol table. For types, use the Module::addTypeName method to +insert entries into the symbol table.

+ +
+ + + + + + +
+

The +User class provides a basis for expressing the ownership of User +towards other +Values. The +Use helper class is employed to do the bookkeeping and to facilitate O(1) +addition and removal.

+ + + + +
+

+A subclass of User can choose between incorporating its Use objects +or refer to them out-of-line by means of a pointer. A mixed variant +(some Uses inline others hung off) is impractical and breaks the invariant +that the Use objects belonging to the same User form a contiguous array. +

+
+ +

+We have 2 different layouts in the User (sub)classes: +

    +
  • Layout a) +The Use object(s) are inside (resp. at fixed offset) of the User +object and there are a fixed number of them.

    + +
  • Layout b) +The Use object(s) are referenced by a pointer to an +array from the User object and there may be a variable +number of them.

    +
+

+As of v2.4 each layout still possesses a direct pointer to the +start of the array of Uses. Though not mandatory for layout a), +we stick to this redundancy for the sake of simplicity. +The User object also stores the number of Use objects it +has. (Theoretically this information can also be calculated +given the scheme presented below.)

+

+Special forms of allocation operators (operator new) +enforce the following memory layouts:

+ +
    +
  • Layout a) is modelled by prepending the User object by the Use[] array.

    + +
    +...---.---.---.---.-------...
    +  | P | P | P | P | User
    +'''---'---'---'---'-------'''
    +
    + +
  • Layout b) is modelled by pointing at the Use[] array.

    +
    +.-------...
    +| User
    +'-------'''
    +    |
    +    v
    +    .---.---.---.---...
    +    | P | P | P | P |
    +    '---'---'---'---'''
    +
    +
+(In the above figures 'P' stands for the Use** that + is stored in each Use object in the member Use::Prev) + + + + +
+

+Since the Use objects are deprived of the direct (back)pointer to +their User objects, there must be a fast and exact method to +recover it. This is accomplished by the following scheme:

+
+ +A bit-encoding in the 2 LSBits (least significant bits) of the Use::Prev allows to find the +start of the User object: +
    +
  • 00 —> binary digit 0
  • +
  • 01 —> binary digit 1
  • +
  • 10 —> stop and calculate (s)
  • +
  • 11 —> full stop (S)
  • +
+

+Given a Use*, all we have to do is to walk till we get +a stop and we either have a User immediately behind or +we have to walk to the next stop picking up digits +and calculating the offset:

+
+.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
+| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
+'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
+    |+15                |+10            |+6         |+3     |+1
+    |                   |               |           |       |__>
+    |                   |               |           |__________>
+    |                   |               |______________________>
+    |                   |______________________________________>
+    |__________________________________________________________>
+
+

+Only the significant number of bits need to be stored between the +stops, so that the worst case is 20 memory accesses when there are +1000 Use objects associated with a User.

+ + + + +
+

+The following literate Haskell fragment demonstrates the concept:

+
+ +
+
+> import Test.QuickCheck
+> 
+> digits :: Int -> [Char] -> [Char]
+> digits 0 acc = '0' : acc
+> digits 1 acc = '1' : acc
+> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc
+> 
+> dist :: Int -> [Char] -> [Char]
+> dist 0 [] = ['S']
+> dist 0 acc = acc
+> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r
+> dist n acc = dist (n - 1) $ dist 1 acc
+> 
+> takeLast n ss = reverse $ take n $ reverse ss
+> 
+> test = takeLast 40 $ dist 20 []
+> 
+
+
+

+Printing <test> gives: "1s100000s11010s10100s1111s1010s110s11s1S"

+

+The reverse algorithm computes the length of the string just by examining +a certain prefix:

+ +
+
+> pref :: [Char] -> Int
+> pref "S" = 1
+> pref ('s':'1':rest) = decode 2 1 rest
+> pref (_:rest) = 1 + pref rest
+> 
+> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest
+> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
+> decode walk acc _ = walk + acc
+> 
+
+
+

+Now, as expected, printing <pref test> gives 40.

+

+We can quickCheck this with following property:

+ +
+
+> testcase = dist 2000 []
+> testcaseLength = length testcase
+> 
+> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
+>     where arr = takeLast n testcase
+> 
+
+
+

+As expected <quickCheck identityProp> gives:

+ +
+*Main> quickCheck identityProp
+OK, passed 100 tests.
+
+

+Let's be a bit more exhaustive:

+ +
+
+> 
+> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
+> 
+
+
+

+And here is the result of <deepCheck identityProp>:

+ +
+*Main> deepCheck identityProp
+OK, passed 500 tests.
+
+ + + + +

+To maintain the invariant that the 2 LSBits of each Use** in Use +never change after being set up, setters of Use::Prev must re-tag the +new Use** on every modification. Accordingly getters must strip the +tag bits.

+

+For layout b) instead of the User we find a pointer (User* with LSBit set). +Following this pointer brings us to the User. A portable trick ensures +that the first bytes of User (if interpreted as a pointer) never has +the LSBit set. (Portability is relying on the fact that all known compilers place the +vptr in the first word of the instances.)

+ +
+ + + + + +
+

#include "llvm/Type.h" +
doxygen info: Type Class

+ +

The Core LLVM classes are the primary means of representing the program +being inspected or transformed. The core LLVM classes are defined in +header files in the include/llvm/ directory, and implemented in +the lib/VMCore directory.

+ +
+ + + + +
+ +

Type is a superclass of all type classes. Every Value has + a Type. Type cannot be instantiated directly but only + through its subclasses. Certain primitive types (VoidType, + LabelType, FloatType and DoubleType) have hidden + subclasses. They are hidden because they offer no useful functionality beyond + what the Type class offers except to distinguish themselves from + other subclasses of Type.

+

All other types are subclasses of DerivedType. Types can be + named, but this is not a requirement. There exists exactly + one instance of a given shape at any one time. This allows type equality to + be performed with address equality of the Type Instance. That is, given two + Type* values, the types are identical if the pointers are identical. +

+
+ + + + +
+ +
    +
  • bool isIntegerTy() const: Returns true for any integer type.
  • + +
  • bool isFloatingPointTy(): Return true if this is one of the five + floating point types.
  • + +
  • bool isAbstract(): Return true if the type is abstract (contains + an OpaqueType anywhere in its definition).
  • + +
  • bool isSized(): Return true if the type has known size. Things + that don't have a size are abstract types, labels and void.
  • + +
+
+ + + +
+
+
IntegerType
+
Subclass of DerivedType that represents integer types of any bit width. + Any bit width between IntegerType::MIN_INT_BITS (1) and + IntegerType::MAX_INT_BITS (~8 million) can be represented. +
    +
  • static const IntegerType* get(unsigned NumBits): get an integer + type of a specific bit width.
  • +
  • unsigned getBitWidth() const: Get the bit width of an integer + type.
  • +
+
+
SequentialType
+
This is subclassed by ArrayType and PointerType +
    +
  • const Type * getElementType() const: Returns the type of each + of the elements in the sequential type.
  • +
+
+
ArrayType
+
This is a subclass of SequentialType and defines the interface for array + types. +
    +
  • unsigned getNumElements() const: Returns the number of + elements in the array.
  • +
+
+
PointerType
+
Subclass of SequentialType for pointer types.
+
VectorType
+
Subclass of SequentialType for vector types. A + vector type is similar to an ArrayType but is distinguished because it is + a first class type whereas ArrayType is not. Vector types are used for + vector operations and are usually small vectors of of an integer or floating + point type.
+
StructType
+
Subclass of DerivedTypes for struct types.
+
FunctionType
+
Subclass of DerivedTypes for function types. +
    +
  • bool isVarArg() const: Returns true if it's a vararg + function
  • +
  • const Type * getReturnType() const: Returns the + return type of the function.
  • +
  • const Type * getParamType (unsigned i): Returns + the type of the ith parameter.
  • +
  • const unsigned getNumParams() const: Returns the + number of formal parameters.
  • +
+
+
OpaqueType
+
Sublcass of DerivedType for abstract types. This class + defines no content and is used as a placeholder for some other type. Note + that OpaqueType is used (temporarily) during type resolution for forward + references of types. Once the referenced type is resolved, the OpaqueType + is replaced with the actual type. OpaqueType can also be used for data + abstraction. At link time opaque types can be resolved to actual types + of the same name.
+
+
+ + + + + + +
+ +

#include "llvm/Module.h"
doxygen info: +Module Class

+ +

The Module class represents the top level structure present in LLVM +programs. An LLVM module is effectively either a translation unit of the +original program or a combination of several translation units merged by the +linker. The Module class keeps track of a list of Functions, a list of GlobalVariables, and a SymbolTable. Additionally, it contains a few +helpful member functions that try to make common operations easy.

+ +
+ + + + +
+ +
    +
  • Module::Module(std::string name = "")
  • +
+ +

Constructing a Module is easy. You can optionally +provide a name for it (probably based on the name of the translation unit).

+ +
    +
  • Module::iterator - Typedef for function list iterator
    + Module::const_iterator - Typedef for const_iterator.
    + + begin(), end() + size(), empty() + +

    These are forwarding methods that make it easy to access the contents of + a Module object's Function + list.

  • + +
  • Module::FunctionListType &getFunctionList() + +

    Returns the list of Functions. This is + necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

    + +

  • +
+ +
+ +
    +
  • Module::global_iterator - Typedef for global variable list iterator
    + + Module::const_global_iterator - Typedef for const_iterator.
    + + global_begin(), global_end() + global_size(), global_empty() + +

    These are forwarding methods that make it easy to access the contents of + a Module object's GlobalVariable list.

  • + +
  • Module::GlobalListType &getGlobalList() + +

    Returns the list of GlobalVariables. This is necessary to + use when you need to update the list or perform a complex action that + doesn't have a forwarding method.

    + +

  • +
+ +
+ + + +
+ +
    +
  • Function *getFunction(const std::string + &Name, const FunctionType *Ty) + +

    Look up the specified function in the Module SymbolTable. If it does not exist, return + null.

  • + +
  • Function *getOrInsertFunction(const + std::string &Name, const FunctionType *T) + +

    Look up the specified function in the Module SymbolTable. If it does not exist, add an + external declaration for the function and return it.

  • + +
  • std::string getTypeName(const Type *Ty) + +

    If there is at least one entry in the SymbolTable for the specified Type, return it. Otherwise return the empty + string.

  • + +
  • bool addTypeName(const std::string &Name, const Type *Ty) + +

    Insert an entry in the SymbolTable + mapping Name to Ty. If there is already an entry for this + name, true is returned and the SymbolTable is not modified.

  • +
+ +
+ + + + + +
+ +

#include "llvm/Value.h" +
+doxygen info: Value Class

+ +

The Value class is the most important class in the LLVM Source +base. It represents a typed value that may be used (among other things) as an +operand to an instruction. There are many different types of Values, +such as Constants,Arguments. Even Instructions and Functions are Values.

+ +

A particular Value may be used many times in the LLVM representation +for a program. For example, an incoming argument to a function (represented +with an instance of the Argument class) is "used" by +every instruction in the function that references the argument. To keep track +of this relationship, the Value class keeps a list of all of the Users that is using it (the User class is a base class for all nodes in the LLVM +graph that can refer to Values). This use list is how LLVM represents +def-use information in the program, and is accessible through the use_* +methods, shown below.

+ +

Because LLVM is a typed representation, every LLVM Value is typed, +and this Type is available through the getType() +method. In addition, all LLVM values can be named. The "name" of the +Value is a symbolic string printed in the LLVM code:

+ +
+
+%foo = add i32 1, 2
+
+
+ +

The name of this instruction is "foo". NOTE +that the name of any value may be missing (an empty string), so names should +ONLY be used for debugging (making the source code easier to read, +debugging printouts), they should not be used to keep track of values or map +between them. For this purpose, use a std::map of pointers to the +Value itself instead.

+ +

One important aspect of LLVM is that there is no distinction between an SSA +variable and the operation that produces it. Because of this, any reference to +the value produced by an instruction (or the value available as an incoming +argument, for example) is represented as a direct pointer to the instance of +the class that +represents this value. Although this may take some getting used to, it +simplifies the representation and makes it easier to manipulate.

+ +
+ + + + +
+ +
    +
  • Value::use_iterator - Typedef for iterator over the +use-list
    + Value::const_use_iterator - Typedef for const_iterator over +the use-list
    + unsigned use_size() - Returns the number of users of the +value.
    + bool use_empty() - Returns true if there are no users.
    + use_iterator use_begin() - Get an iterator to the start of +the use-list.
    + use_iterator use_end() - Get an iterator to the end of the +use-list.
    + User *use_back() - Returns the last +element in the list. +

    These methods are the interface to access the def-use +information in LLVM. As with all other iterators in LLVM, the naming +conventions follow the conventions defined by the STL.

    +
  • +
  • Type *getType() const +

    This method returns the Type of the Value.

    +
  • +
  • bool hasName() const
    + std::string getName() const
    + void setName(const std::string &Name) +

    This family of methods is used to access and assign a name to a Value, +be aware of the precaution above.

    +
  • +
  • void replaceAllUsesWith(Value *V) + +

    This method traverses the use list of a Value changing all Users of the current value to refer to + "V" instead. For example, if you detect that an instruction always + produces a constant value (for example through constant folding), you can + replace all uses of the instruction with the constant like this:

    + +
    +
    +Inst->replaceAllUsesWith(ConstVal);
    +
    +
    + +
+ +
+ + + + +
+ +

+#include "llvm/User.h"
+doxygen info: User Class
+Superclass: Value

+ +

The User class is the common base class of all LLVM nodes that may +refer to Values. It exposes a list of "Operands" +that are all of the Values that the User is +referring to. The User class itself is a subclass of +Value.

+ +

The operands of a User point directly to the LLVM Value that it refers to. Because LLVM uses Static +Single Assignment (SSA) form, there can only be one definition referred to, +allowing this direct connection. This connection provides the use-def +information in LLVM.

+ +
+ + + + +
+ +

The User class exposes the operand list in two ways: through +an index access interface and through an iterator based interface.

+ +
    +
  • Value *getOperand(unsigned i)
    + unsigned getNumOperands() +

    These two methods expose the operands of the User in a +convenient form for direct access.

  • + +
  • User::op_iterator - Typedef for iterator over the operand +list
    + op_iterator op_begin() - Get an iterator to the start of +the operand list.
    + op_iterator op_end() - Get an iterator to the end of the +operand list. +

    Together, these methods make up the iterator based interface to +the operands of a User.

  • +
+ +
+ + + + +
+ +

#include "llvm/Instruction.h"
+doxygen info: Instruction Class
+Superclasses: User, Value

+ +

The Instruction class is the common base class for all LLVM +instructions. It provides only a few methods, but is a very commonly used +class. The primary data tracked by the Instruction class itself is the +opcode (instruction type) and the parent BasicBlock the Instruction is embedded +into. To represent a specific type of instruction, one of many subclasses of +Instruction are used.

+ +

Because the Instruction class subclasses the User class, its operands can be accessed in the same +way as for other Users (with the +getOperand()/getNumOperands() and +op_begin()/op_end() methods).

An important file for +the Instruction class is the llvm/Instruction.def file. This +file contains some meta-data about the various different types of instructions +in LLVM. It describes the enum values that are used as opcodes (for example +Instruction::Add and Instruction::ICmp), as well as the +concrete sub-classes of Instruction that implement the instruction (for +example BinaryOperator and CmpInst). Unfortunately, the use of macros in +this file confuses doxygen, so these enum values don't show up correctly in the +doxygen output.

+ +
+ + + +
+
    +
  • BinaryOperator +

    This subclasses represents all two operand instructions whose operands + must be the same type, except for the comparison instructions.

  • +
  • CastInst +

    This subclass is the parent of the 12 casting instructions. It provides + common operations on cast instructions.

    +
  • CmpInst +

    This subclass respresents the two comparison instructions, + ICmpInst (integer opreands), and + FCmpInst (floating point operands).

    +
  • TerminatorInst +

    This subclass is the parent of all terminator instructions (those which + can terminate a block).

    +
+
+ + + + +
+ +
    +
  • BasicBlock *getParent() +

    Returns the BasicBlock that +this Instruction is embedded into.

  • +
  • bool mayWriteToMemory() +

    Returns true if the instruction writes to memory, i.e. it is a + call,free,invoke, or store.

  • +
  • unsigned getOpcode() +

    Returns the opcode for the Instruction.

  • +
  • Instruction *clone() const +

    Returns another instance of the specified instruction, identical +in all ways to the original except that the instruction has no parent +(ie it's not embedded into a BasicBlock), +and it has no name

  • +
+ +
+ + + + +
+ +

Constant represents a base class for different types of constants. It +is subclassed by ConstantInt, ConstantArray, etc. for representing +the various types of Constants. GlobalValue is also +a subclass, which represents the address of a global variable or function. +

+ +
+ + +
Important Subclasses of Constant
+
+
    +
  • ConstantInt : This subclass of Constant represents an integer constant of + any width. +
      +
    • const APInt& getValue() const: Returns the underlying + value of this constant, an APInt value.
    • +
    • int64_t getSExtValue() const: Converts the underlying APInt + value to an int64_t via sign extension. If the value (not the bit width) + of the APInt is too large to fit in an int64_t, an assertion will result. + For this reason, use of this method is discouraged.
    • +
    • uint64_t getZExtValue() const: Converts the underlying APInt + value to a uint64_t via zero extension. IF the value (not the bit width) + of the APInt is too large to fit in a uint64_t, an assertion will result. + For this reason, use of this method is discouraged.
    • +
    • static ConstantInt* get(const APInt& Val): Returns the + ConstantInt object that represents the value provided by Val. + The type is implied as the IntegerType that corresponds to the bit width + of Val.
    • +
    • static ConstantInt* get(const Type *Ty, uint64_t Val): + Returns the ConstantInt object that represents the value provided by + Val for integer type Ty.
    • +
    +
  • +
  • ConstantFP : This class represents a floating point constant. +
      +
    • double getValue() const: Returns the underlying value of + this constant.
    • +
    +
  • +
  • ConstantArray : This represents a constant array. +
      +
    • const std::vector<Use> &getValues() const: Returns + a vector of component constants that makeup this array.
    • +
    +
  • +
  • ConstantStruct : This represents a constant struct. +
      +
    • const std::vector<Use> &getValues() const: Returns + a vector of component constants that makeup this array.
    • +
    +
  • +
  • GlobalValue : This represents either a global variable or a function. In + either case, the value is a constant fixed address (after linking). +
  • +
+
+ + + + + +
+ +

#include "llvm/GlobalValue.h"
+doxygen info: GlobalValue +Class
+Superclasses: Constant, +User, Value

+ +

Global values (GlobalVariables or Functions) are the only LLVM values that are +visible in the bodies of all Functions. +Because they are visible at global scope, they are also subject to linking with +other globals defined in different translation units. To control the linking +process, GlobalValues know their linkage rules. Specifically, +GlobalValues know whether they have internal or external linkage, as +defined by the LinkageTypes enumeration.

+ +

If a GlobalValue has internal linkage (equivalent to being +static in C), it is not visible to code outside the current translation +unit, and does not participate in linking. If it has external linkage, it is +visible to external code, and does participate in linking. In addition to +linkage information, GlobalValues keep track of which Module they are currently part of.

+ +

Because GlobalValues are memory objects, they are always referred to +by their address. As such, the Type of a +global is always a pointer to its contents. It is important to remember this +when using the GetElementPtrInst instruction because this pointer must +be dereferenced first. For example, if you have a GlobalVariable (a +subclass of GlobalValue) that is an array of 24 ints, type [24 x +i32], then the GlobalVariable is a pointer to that array. Although +the address of the first element of this array and the value of the +GlobalVariable are the same, they have different types. The +GlobalVariable's type is [24 x i32]. The first element's type +is i32. Because of this, accessing a global value requires you to +dereference the pointer with GetElementPtrInst first, then its elements +can be accessed. This is explained in the LLVM +Language Reference Manual.

+ +
+ + + + +
+ +
    +
  • bool hasInternalLinkage() const
    + bool hasExternalLinkage() const
    + void setInternalLinkage(bool HasInternalLinkage) +

    These methods manipulate the linkage characteristics of the GlobalValue.

    +

    +
  • +
  • Module *getParent() +

    This returns the Module that the +GlobalValue is currently embedded into.

  • +
+ +
+ + + + +
+ +

#include "llvm/Function.h"
doxygen +info: Function Class
+Superclasses: GlobalValue, +Constant, +User, +Value

+ +

The Function class represents a single procedure in LLVM. It is +actually one of the more complex classes in the LLVM hierarchy because it must +keep track of a large amount of data. The Function class keeps track +of a list of BasicBlocks, a list of formal +Arguments, and a +SymbolTable.

+ +

The list of BasicBlocks is the most +commonly used part of Function objects. The list imposes an implicit +ordering of the blocks in the function, which indicate how the code will be +laid out by the backend. Additionally, the first BasicBlock is the implicit entry node for the +Function. It is not legal in LLVM to explicitly branch to this initial +block. There are no implicit exit nodes, and in fact there may be multiple exit +nodes from a single Function. If the BasicBlock list is empty, this indicates that +the Function is actually a function declaration: the actual body of the +function hasn't been linked in yet.

+ +

In addition to a list of BasicBlocks, the +Function class also keeps track of the list of formal Arguments that the function receives. This +container manages the lifetime of the Argument +nodes, just like the BasicBlock list does for +the BasicBlocks.

+ +

The SymbolTable is a very rarely used +LLVM feature that is only used when you have to look up a value by name. Aside +from that, the SymbolTable is used +internally to make sure that there are not conflicts between the names of Instructions, BasicBlocks, or Arguments in the function body.

+ +

Note that Function is a GlobalValue +and therefore also a Constant. The value of the function +is its address (after linking) which is guaranteed to be constant.

+
+ + + + +
+ +
    +
  • Function(const FunctionType + *Ty, LinkageTypes Linkage, const std::string &N = "", Module* Parent = 0) + +

    Constructor used when you need to create new Functions to add + the the program. The constructor must specify the type of the function to + create and what type of linkage the function should have. The FunctionType argument + specifies the formal arguments and return value for the function. The same + FunctionType value can be used to + create multiple functions. The Parent argument specifies the Module + in which the function is defined. If this argument is provided, the function + will automatically be inserted into that module's list of + functions.

  • + +
  • bool isDeclaration() + +

    Return whether or not the Function has a body defined. If the + function is "external", it does not have a body, and thus must be resolved + by linking with a function defined in a different translation unit.

  • + +
  • Function::iterator - Typedef for basic block list iterator
    + Function::const_iterator - Typedef for const_iterator.
    + + begin(), end() + size(), empty() + +

    These are forwarding methods that make it easy to access the contents of + a Function object's BasicBlock + list.

  • + +
  • Function::BasicBlockListType &getBasicBlockList() + +

    Returns the list of BasicBlocks. This + is necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

  • + +
  • Function::arg_iterator - Typedef for the argument list +iterator
    + Function::const_arg_iterator - Typedef for const_iterator.
    + + arg_begin(), arg_end() + arg_size(), arg_empty() + +

    These are forwarding methods that make it easy to access the contents of + a Function object's Argument + list.

  • + +
  • Function::ArgumentListType &getArgumentList() + +

    Returns the list of Arguments. This is + necessary to use when you need to update the list or perform a complex + action that doesn't have a forwarding method.

  • + +
  • BasicBlock &getEntryBlock() + +

    Returns the entry BasicBlock for the + function. Because the entry block for the function is always the first + block, this returns the first block of the Function.

  • + +
  • Type *getReturnType()
    + FunctionType *getFunctionType() + +

    This traverses the Type of the + Function and returns the return type of the function, or the FunctionType of the actual + function.

  • + +
  • SymbolTable *getSymbolTable() + +

    Return a pointer to the SymbolTable + for this Function.

  • +
+ +
+ + + + +
+ +

#include "llvm/GlobalVariable.h" +
+doxygen info: GlobalVariable + Class
+Superclasses: GlobalValue, +Constant, +User, +Value

+ +

Global variables are represented with the (surprise surprise) +GlobalVariable class. Like functions, GlobalVariables are also +subclasses of GlobalValue, and as such are +always referenced by their address (global values must live in memory, so their +"name" refers to their constant address). See +GlobalValue for more on this. Global +variables may have an initial value (which must be a +Constant), and if they have an initializer, +they may be marked as "constant" themselves (indicating that their contents +never change at runtime).

+
+ + + + +
+ +
    +
  • GlobalVariable(const Type *Ty, bool + isConstant, LinkageTypes& Linkage, Constant + *Initializer = 0, const std::string &Name = "", Module* Parent = 0) + +

    Create a new global variable of the specified type. If + isConstant is true then the global variable will be marked as + unchanging for the program. The Linkage parameter specifies the type of + linkage (internal, external, weak, linkonce, appending) for the variable. + If the linkage is InternalLinkage, WeakAnyLinkage, WeakODRLinkage, + LinkOnceAnyLinkage or LinkOnceODRLinkage,  then the resultant + global variable will have internal linkage. AppendingLinkage concatenates + together all instances (in different translation units) of the variable + into a single variable but is only applicable to arrays.  See + the LLVM Language Reference for + further details on linkage types. Optionally an initializer, a name, and the + module to put the variable into may be specified for the global variable as + well.

  • + +
  • bool isConstant() const + +

    Returns true if this is a global variable that is known not to + be modified at runtime.

  • + +
  • bool hasInitializer() + +

    Returns true if this GlobalVariable has an intializer.

  • + +
  • Constant *getInitializer() + +

    Returns the initial value for a GlobalVariable. It is not legal + to call this method if there is no initializer.

  • +
+ +
+ + + + + +
+ +

#include "llvm/BasicBlock.h"
+doxygen info: BasicBlock +Class
+Superclass: Value

+ +

This class represents a single entry single exit section of the code, +commonly known as a basic block by the compiler community. The +BasicBlock class maintains a list of Instructions, which form the body of the block. +Matching the language definition, the last element of this list of instructions +is always a terminator instruction (a subclass of the TerminatorInst class).

+ +

In addition to tracking the list of instructions that make up the block, the +BasicBlock class also keeps track of the Function that it is embedded into.

+ +

Note that BasicBlocks themselves are Values, because they are referenced by instructions +like branches and can go in the switch tables. BasicBlocks have type +label.

+ +
+ + + + +
+
    + +
  • BasicBlock(const std::string &Name = "", Function *Parent = 0) + +

    The BasicBlock constructor is used to create new basic blocks for +insertion into a function. The constructor optionally takes a name for the new +block, and a Function to insert it into. If +the Parent parameter is specified, the new BasicBlock is +automatically inserted at the end of the specified Function, if not specified, the BasicBlock must be +manually inserted into the Function.

  • + +
  • BasicBlock::iterator - Typedef for instruction list iterator
    +BasicBlock::const_iterator - Typedef for const_iterator.
    +begin(), end(), front(), back(), +size(), empty() +STL-style functions for accessing the instruction list. + +

    These methods and typedefs are forwarding functions that have the same +semantics as the standard library methods of the same names. These methods +expose the underlying instruction list of a basic block in a way that is easy to +manipulate. To get the full complement of container operations (including +operations to update the list), you must use the getInstList() +method.

  • + +
  • BasicBlock::InstListType &getInstList() + +

    This method is used to get access to the underlying container that actually +holds the Instructions. This method must be used when there isn't a forwarding +function in the BasicBlock class for the operation that you would like +to perform. Because there are no forwarding functions for "updating" +operations, you need to use this if you want to update the contents of a +BasicBlock.

  • + +
  • Function *getParent() + +

    Returns a pointer to Function the block is +embedded into, or a null pointer if it is homeless.

  • + +
  • TerminatorInst *getTerminator() + +

    Returns a pointer to the terminator instruction that appears at the end of +the BasicBlock. If there is no terminator instruction, or if the last +instruction in the block is not a terminator, then a null pointer is +returned.

  • + +
+ +
+ + + + + +
+ +

This subclass of Value defines the interface for incoming formal +arguments to a function. A Function maintains a list of its formal +arguments. An argument has a pointer to the parent Function.

+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 Strict + + Dinakar Dhurjati and + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/Projects.html b/final/docs/Projects.html new file mode 100644 index 00000000000..ada6196be2a --- /dev/null +++ b/final/docs/Projects.html @@ -0,0 +1,460 @@ + + + + Creating an LLVM Project + + + + +
Creating an LLVM Project
+ +
    +
  1. Overview
  2. +
  3. Create a project from the Sample Project
  4. +
  5. Source tree layout
  6. +
  7. Writing LLVM-style Makefiles +
      +
    1. Required Variables
    2. +
    3. Variables for Building Subdirectories
    4. +
    5. Variables for Building Libraries
    6. +
    7. Variables for Building Programs
    8. +
    9. Miscellaneous Variables
    10. +
  8. +
  9. Placement of object code
  10. +
  11. Further help
  12. +
+ +
+

Written by John Criswell

+
+ + + + + +
+ +

The LLVM build system is designed to facilitate the building of third party +projects that use LLVM header files, libraries, and tools. In order to use +these facilities, a Makefile from a project must do the following things:

+ +
    +
  1. Set make variables. There are several variables that a Makefile + needs to set to use the LLVM build system: +
      +
    • PROJECT_NAME - The name by which your project is known.
    • +
    • LLVM_SRC_ROOT - The root of the LLVM source tree.
    • +
    • LLVM_OBJ_ROOT - The root of the LLVM object tree.
    • +
    • PROJ_SRC_ROOT - The root of the project's source tree.
    • +
    • PROJ_OBJ_ROOT - The root of the project's object tree.
    • +
    • PROJ_INSTALL_ROOT - The root installation directory.
    • +
    • LEVEL - The relative path from the current directory to the + project's root ($PROJ_OBJ_ROOT).
    • +
  2. +
  3. Include Makefile.config from $(LLVM_OBJ_ROOT).
  4. +
  5. Include Makefile.rules from $(LLVM_SRC_ROOT).
  6. +
+ +

There are two ways that you can set all of these variables:

+
    +
  1. You can write your own Makefiles which hard-code these values.
  2. +
  3. You can use the pre-made LLVM sample project. This sample project + includes Makefiles, a configure script that can be used to configure the + location of LLVM, and the ability to support multiple object directories + from a single source directory.
  4. +
+ +

This document assumes that you will base your project on the LLVM sample +project found in llvm/projects/sample. If you want to devise your own +build system, studying the sample project and LLVM Makefiles will probably +provide enough information on how to write your own Makefiles.

+ +
+ + + + + +
+ +

Follow these simple steps to start your project:

+ +
    +
  1. Copy the llvm/projects/sample directory to any place of your +choosing. You can place it anywhere you like. Rename the directory to match +the name of your project.
  2. + +
  3. +If you downloaded LLVM using Subversion, remove all the directories named .svn +(and all the files therein) from your project's new source tree. This will +keep Subversion from thinking that your project is inside +llvm/trunk/projects/sample.
  4. + +
  5. Add your source code and Makefiles to your source tree.
  6. + +
  7. If you want your project to be configured with the configure script +then you need to edit autoconf/configure.ac as follows: +
      +
    • AC_INIT. Place the name of your project, its version number and + a contact email address for your project as the arguments to this macro
    • +
    • AC_CONFIG_AUX_DIR. If your project isn't in the + llvm/projects directory then you might need to adjust this so that + it specifies a relative path to the llvm/autoconf directory.
    • +
    • LLVM_CONFIG_PROJECT. Just leave this alone.
    • +
    • AC_CONFIG_SRCDIR. Specify a path to a file name that identifies + your project; or just leave it at Makefile.common.in
    • +
    • AC_CONFIG_FILES. Do not change.
    • +
    • AC_CONFIG_MAKEFILE. Use one of these macros for each Makefile + that your project uses. This macro arranges for your makefiles to be copied + from the source directory, unmodified, to the build directory.
    • +
    +
  8. + +
  9. After updating autoconf/configure.ac, regenerate the +configure script with these commands: + +
    +

    % cd autoconf
    + % ./AutoRegen.sh

    +
    + +

    You must be using Autoconf version 2.59 or later and your aclocal version +should be 1.9 or later.

  10. + +
  11. Run configure in the directory in which you want to place +object code. Use the following options to tell your project where it +can find LLVM: + +
    +
    --with-llvmsrc=<directory>
    +
    Tell your project where the LLVM source tree is located.
    +

    --with-llvmobj=<directory>
    +
    Tell your project where the LLVM object tree is located.
    +

    --prefix=<directory>
    +
    Tell your project where it should get installed.
    +
    +
+ +

That's it! Now all you have to do is type gmake (or make +if your on a GNU/Linux system) in the root of your object directory, and your +project should build.

+ +
+ + + + + +
+ +

In order to use the LLVM build system, you will want to organize your +source code so that it can benefit from the build system's features. +Mainly, you want your source tree layout to look similar to the LLVM +source tree layout. The best way to do this is to just copy the +project tree from llvm/projects/sample and modify it to meet +your needs, but you can certainly add to it if you want.

+ +

Underneath your top level directory, you should have the following +directories:

+ +
+
lib +
+ This subdirectory should contain all of your library source + code. For each library that you build, you will have one + directory in lib that will contain that library's source + code. + +

+ Libraries can be object files, archives, or dynamic libraries. + The lib directory is just a convenient place for libraries + as it places them all in a directory from which they can be linked + later. + +

include +
+ This subdirectory should contain any header files that are + global to your project. By global, we mean that they are used + by more than one library or executable of your project. +

+ By placing your header files in include, they will be + found automatically by the LLVM build system. For example, if + you have a file include/jazz/note.h, then your source + files can include it simply with #include "jazz/note.h". + +

tools +
+ This subdirectory should contain all of your source + code for executables. For each program that you build, you + will have one directory in tools that will contain that + program's source code. +

+ +

test +
+ This subdirectory should contain tests that verify that your code + works correctly. Automated tests are especially useful. +

+ Currently, the LLVM build system provides basic support for tests. + The LLVM system provides the following: +

    +
  • + LLVM provides a tcl procedure that is used by Dejagnu to run + tests. It can be found in llvm/lib/llvm-dg.exp. This + test procedure uses RUN lines in the actual test case to determine + how to run the test. See the TestingGuide for more details. You + can easily write Makefile support similar to the Makefiles in + llvm/test to use Dejagnu to run your project's tests.
  • +
  • + LLVM contains an optional package called llvm-test + which provides benchmarks and programs that are known to compile with the + LLVM GCC front ends. You can use these + programs to test your code, gather statistics information, and + compare it to the current LLVM performance statistics. +
    Currently, there is no way to hook your tests directly into the + llvm/test testing harness. You will simply + need to find a way to use the source provided within that directory + on your own. +
+
+ +

Typically, you will want to build your lib directory first followed by +your tools directory.

+ +
+ + + + + +
+ +

The LLVM build system provides a convenient way to build libraries and +executables. Most of your project Makefiles will only need to define a few +variables. Below is a list of the variables one can set and what they can +do:

+ +
+ + + + +
+ +
+
LEVEL +
+ This variable is the relative path from this Makefile to the + top directory of your project's source code. For example, if + your source code is in /tmp/src, then the Makefile in + /tmp/src/jump/high would set LEVEL to "../..". +
+ +
+ + + + +
+ +
+
DIRS +
+ This is a space separated list of subdirectories that should be + built. They will be built, one at a time, in the order + specified. +

+ +

PARALLEL_DIRS +
+ This is a list of directories that can be built in parallel. + These will be built after the directories in DIRS have been + built. +

+ +

OPTIONAL_DIRS +
+ This is a list of directories that can be built if they exist, + but will not cause an error if they do not exist. They are + built serially in the order in which they are listed. +
+ +
+ + + + +
+ +
+
LIBRARYNAME +
+ This variable contains the base name of the library that will + be built. For example, to build a library named + libsample.a, LIBRARYNAME should be set to + sample. +

+ +

BUILD_ARCHIVE +
+ By default, a library is a .o file that is linked + directly into a program. To build an archive (also known as + a static library), set the BUILD_ARCHIVE variable. +

+ +

SHARED_LIBRARY +
+ If SHARED_LIBRARY is defined in your Makefile, a shared + (or dynamic) library will be built. +
+ +
+ + + + +
+ +
+
TOOLNAME +
+ This variable contains the name of the program that will + be built. For example, to build an executable named + sample, TOOLNAME should be set to sample. +

+ +

USEDLIBS +
+ This variable holds a space separated list of libraries that + should be linked into the program. These libraries must either + be LLVM libraries or libraries that come from your lib + directory. The libraries must be specified by their base name. + For example, to link libsample.a, you would set USEDLIBS to + sample. +

+ Note that this works only for statically linked libraries. +

+ +

LIBS +
+ To link dynamic libraries, add -l<library base name> to + the LIBS variable. The LLVM build system will look in the same places + for dynamic libraries as it does for static libraries. +

+ For example, to link libsample.so, you would have the + following line in your Makefile: +

+ + LIBS += -lsample + +

+ +
+ + + + +
+ +
+
ExtraSource +
+ This variable contains a space separated list of extra source + files that need to be built. It is useful for including the + output of Lex and Yacc programs. +

+ +

CFLAGS +
CPPFLAGS +
+ This variable can be used to add options to the C and C++ + compiler, respectively. It is typically used to add options + that tell the compiler the location of additional directories + to search for header files. +

+ It is highly suggested that you append to CFLAGS and CPPFLAGS as + opposed to overwriting them. The master Makefiles may already + have useful options in them that you may not want to overwrite. +

+

+ +
+ + + + + +
+ +

The final location of built libraries and executables will depend upon +whether you do a Debug, Release, or Profile build.

+ +
+
Libraries +
+ All libraries (static and dynamic) will be stored in + PROJ_OBJ_ROOT/<type>/lib, where type is Debug, + Release, or Profile for a debug, optimized, or + profiled build, respectively.

+ +

Executables +
All executables will be stored in + PROJ_OBJ_ROOT/<type>/bin, where type is Debug, + Release, or Profile for a debug, optimized, or profiled + build, respectively. +
+ +
+ + + + + +
+ +

If you have any questions or need any help creating an LLVM project, +the LLVM team would be more than happy to help. You can always post your +questions to the LLVM Developers +Mailing List.

+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 + + John Criswell
+ The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/ReleaseNotes.html b/final/docs/ReleaseNotes.html new file mode 100644 index 00000000000..2f83b9447d1 --- /dev/null +++ b/final/docs/ReleaseNotes.html @@ -0,0 +1,1306 @@ + + + + + + + LLVM 2.8 Release Notes + + + +
LLVM 2.8 Release Notes
+ +LLVM Dragon Logo + +
    +
  1. Introduction
  2. +
  3. Sub-project Status Update
  4. +
  5. External Projects Using LLVM 2.8
  6. +
  7. What's New in LLVM 2.8?
  8. +
  9. Installation Instructions
  10. +
  11. Known Problems
  12. +
  13. Additional Information
  14. +
+ +
+

Written by the LLVM Team

+
+ + + + + + + +
+ +

This document contains the release notes for the LLVM Compiler +Infrastructure, release 2.8. Here we describe the status of LLVM, including +major improvements from the previous release and significant known problems. +All LLVM releases may be downloaded from the LLVM releases web site.

+ +

For more information about LLVM, including information about the latest +release, please check out the main LLVM +web site. If you have questions or comments, the LLVM Developer's +Mailing List is a good place to send them.

+ +

Note that if you are reading this file from a Subversion checkout or the +main LLVM web page, this document applies to the next release, not the +current one. To see the release notes for a specific release, please see the +releases page.

+ +
+ + + + + + + + + + + + + + +
+

+The LLVM 2.8 distribution currently consists of code from the core LLVM +repository (which roughly includes the LLVM optimizers, code generators +and supporting tools), the Clang repository and the llvm-gcc repository. In +addition to this code, the LLVM Project includes other sub-projects that are in +development. Here we include updates on these subprojects. +

+ +
+ + + + + +
+ +

Clang is an LLVM front end for the C, +C++, and Objective-C languages. Clang aims to provide a better user experience +through expressive diagnostics, a high level of conformance to language +standards, fast compilation, and low memory use. Like LLVM, Clang provides a +modular, library-based architecture that makes it suitable for creating or +integrating with other development tools. Clang is considered a +production-quality compiler for C, Objective-C, C++ and Objective-C++ on x86 +(32- and 64-bit), and for darwin-arm targets.

+ +

In the LLVM 2.8 time-frame, the Clang team has made many improvements:

+ +
    +
  • Clang C++ is now feature-complete with respect to the ISO C++ 1998 and 2003 standards.
  • +
  • Added support for Objective-C++.
  • +
  • Clang now uses LLVM-MC to directly generate object code and to parse inline assembly (on Darwin).
  • +
  • Introduced many new warnings, including -Wmissing-field-initializers, -Wshadow, -Wno-protocol, -Wtautological-compare, -Wstrict-selector-match, -Wcast-align, -Wunused improvements, and greatly improved format-string checking.
  • +
  • Introduced the "libclang" library, a C interface to Clang intended to support IDE clients.
  • +
  • Added support for #pragma GCC visibility, #pragma align, and others.
  • +
  • Added support for SSE, AVX, ARM NEON, and AltiVec.
  • +
  • Improved support for many Microsoft extensions.
  • +
  • Implemented support for blocks in C++.
  • +
  • Implemented precompiled headers for C++.
  • +
  • Improved abstract syntax trees to retain more accurate source information.
  • +
  • Added driver support for handling LLVM IR and bitcode files directly.
  • +
  • Major improvements to compiler correctness for exception handling.
  • +
  • Improved generated code quality in some areas: +
      +
    • Good code generation for X86-32 and X86-64 ABI handling.
    • +
    • Improved code generation for bit-fields, although important work remains.
    • +
    +
  • +
+
+ + + + +
+ +

The Clang Static Analyzer + project is an effort to use static source code analysis techniques to + automatically find bugs in C and Objective-C programs (and hopefully C++ in the + future!). The tool is very good at finding bugs that occur on specific + paths through code, such as on error conditions.

+ +

The LLVM 2.8 release fixes a number of bugs and slightly improves precision + over 2.7, but there are no major new features in the release. +

+ +
+ + + + +
+

+DragonEgg is a port of llvm-gcc to +gcc-4.5. Unlike llvm-gcc, dragonegg in theory does not require any gcc-4.5 +modifications whatsoever (currently one small patch is needed) thanks to the +new gcc plugin architecture. +DragonEgg is a gcc plugin that makes gcc-4.5 use the LLVM optimizers and code +generators instead of gcc's, just like with llvm-gcc. +

+ +

+DragonEgg is still a work in progress, but it is able to compile a lot of code, +for example all of gcc, LLVM and clang. Currently Ada, C, C++ and Fortran work +well, while all other languages either don't work at all or only work poorly. +For the moment only the x86-32 and x86-64 targets are supported, and only on +linux and darwin (darwin may need additional gcc patches). +

+ +

+The 2.8 release has the following notable changes: +

    +
  • The plugin loads faster due to exporting fewer symbols.
  • +
  • Additional vector operations such as addps256 are now supported.
  • +
  • Ada global variables with no initial value are no longer zero initialized, +resulting in better optimization.
  • +
  • The '-fplugin-arg-dragonegg-enable-gcc-optzns' flag now runs all gcc +optimizers, rather than just a handful.
  • +
  • Fortran programs using common variables now link correctly.
  • +
  • GNU OMP constructs no longer crash the compiler.
  • +
+ +
+ + + + +
+

+The VMKit project is an implementation of +a Java Virtual Machine (Java VM or JVM) that uses LLVM for static and +just-in-time compilation. As of LLVM 2.8, VMKit now supports copying garbage +collectors, and can be configured to use MMTk's copy mark-sweep garbage +collector. In LLVM 2.8, the VMKit .NET VM is no longer being maintained. +

+
+ + + + +
+

+The new LLVM compiler-rt project +is a simple library that provides an implementation of the low-level +target-specific hooks required by code generation and other runtime components. +For example, when compiling for a 32-bit target, converting a double to a 64-bit +unsigned integer is compiled into a runtime call to the "__fixunsdfdi" +function. The compiler-rt library provides highly optimized implementations of +this and other low-level routines (some are 3x faster than the equivalent +libgcc routines).

+ +

+All of the code in the compiler-rt project is available under the standard LLVM +License, a "BSD-style" license. New in LLVM 2.8, compiler_rt now supports +soft floating point (for targets that don't have a real floating point unit), +and includes an extensive testsuite for the "blocks" language feature and the +blocks runtime included in compiler_rt.

+ +
+ + + + +
+

+LLDB is a brand new member of the LLVM +umbrella of projects. LLDB is a next generation, high-performance debugger. It +is built as a set of reusable components which highly leverage existing +libraries in the larger LLVM Project, such as the Clang expression parser, the +LLVM disassembler and the LLVM JIT.

+ +

+LLDB is in early development and not included as part of the LLVM 2.8 release, +but is mature enough to support basic debugging scenarios on Mac OS X in C, +Objective-C and C++. We'd really like help extending and expanding LLDB to +support new platforms, new languages, new architectures, and new features. +

+ +
+ + + + +
+

+libc++ is another new member of the LLVM +family. It is an implementation of the C++ standard library, written from the +ground up to specifically target the forthcoming C++'0X standard and focus on +delivering great performance.

+ +

+As of the LLVM 2.8 release, libc++ is virtually feature complete, but would +benefit from more testing and better integration with Clang++. It is also +looking forward to the C++ committee finalizing the C++'0x standard. +

+ +
+ + + + + + +
+

+KLEE is a symbolic execution framework for +programs in LLVM bitcode form. KLEE tries to symbolically evaluate "all" paths +through the application and records state transitions that lead to fault +states. This allows it to construct testcases that lead to faults and can even +be used to verify some algorithms. +

+ +

Although KLEE does not have any major new features as of 2.8, we have made +various minor improvements, particular to ease development:

+
    +
  • Added support for LLVM 2.8. KLEE currently maintains compatibility with + LLVM 2.6, 2.7, and 2.8.
  • +
  • Added a buildbot for 2.6, 2.7, and trunk. A 2.8 buildbot will be coming + soon following release.
  • +
  • Fixed many C++ code issues to allow building with Clang++. Mostly + complete, except for the version of MiniSAT which is inside the KLEE STP + version.
  • +
  • Improved support for building with separate source and build + directories.
  • +
  • Added support for "long double" on x86.
  • +
  • Initial work on KLEE support for using 'lit' test runner instead of + DejaGNU.
  • +
  • Added configure support for using an external version of + STP.
  • +
+ +
+ + + + + + +
+ +

An exciting aspect of LLVM is that it is used as an enabling technology for + a lot of other language and tools projects. This section lists some of the + projects that have already been updated to work with LLVM 2.8.

+
+ + + + +
+

+TCE is a toolset for designing +application-specific processors (ASP) based on the Transport triggered +architecture (TTA). The toolset provides a complete co-design flow from C/C++ +programs down to synthesizable VHDL and parallel program binaries. Processor +customization points include the register files, function units, supported +operations, and the interconnection network.

+ +

TCE uses llvm-gcc/Clang and LLVM for C/C++ language support, target +independent optimizations and also for parts of code generation. It generates +new LLVM-based code generators "on the fly" for the designed TTA processors and +loads them in to the compiler backend as runtime libraries to avoid per-target +recompilation of larger parts of the compiler chain.

+ +
+ + + + +
+

+Horizon is a bytecode +language and compiler written on top of LLVM, intended for producing +single-address-space managed code operating systems that +run faster than the equivalent multiple-address-space C systems. +More in-depth blurb is available on the wiki.

+ +
+ + + + +
+

+Clam AntiVirus is an open source (GPL) +anti-virus toolkit for UNIX, designed especially for e-mail scanning on mail +gateways. Since version 0.96 it has bytecode +signatures that allow writing detections for complex malware. It +uses LLVM's JIT to speed up the execution of bytecode on +X86, X86-64, PPC32/64, falling back to its own interpreter otherwise. +The git version was updated to work with LLVM 2.8. +

+ +

The +ClamAV bytecode compiler uses Clang and LLVM to compile a C-like +language, insert runtime checks, and generate ClamAV bytecode.

+ +
+ + +
+Pure +
+ +
+

+Pure +is an algebraic/functional +programming language based on term rewriting. Programs are collections +of equations which are used to evaluate expressions in a symbolic +fashion. Pure offers dynamic typing, eager and lazy evaluation, lexical +closures, a hygienic macro system (also based on term rewriting), +built-in list and matrix support (including list and matrix +comprehensions) and an easy-to-use C interface. The interpreter uses +LLVM as a backend to JIT-compile Pure programs to fast native code.

+ +

Pure versions 0.44 and later have been tested and are known to work with +LLVM 2.8 (and continue to work with older LLVM releases >= 2.5).

+ +
+ + + + +
+

+GHC is an open source, +state-of-the-art programming suite for +Haskell, a standard lazy functional programming language. It includes +an optimizing static compiler generating good code for a variety of +platforms, together with an interactive system for convenient, quick +development.

+ +

In addition to the existing C and native code generators, GHC 7.0 now +supports an LLVM +code generator. GHC supports LLVM 2.7 and later.

+ +
+ + + + +
+

+Clay is a new systems programming +language that is specifically designed for generic programming. It makes +generic programming very concise thanks to whole program type propagation. It +uses LLVM as its backend.

+ +
+ + + + +
+

+llvm-py has been updated to work +with LLVM 2.8. llvm-py provides Python bindings for LLVM, allowing you to write a +compiler backend or a VM in Python.

+ +
+ + + + + +
+

+FAUST is a compiled language for real-time +audio signal processing. The name FAUST stands for Functional AUdio STream. Its +programming model combines two approaches: functional programming and block +diagram composition. In addition with the C, C++, JAVA output formats, the +Faust compiler can now generate LLVM bitcode, and works with LLVM 2.7 and +2.8.

+ +
+ + + + +
+

Jade +(Just-in-time Adaptive Decoder Engine) is a generic video decoder engine using +LLVM for just-in-time compilation of video decoder configurations. Those +configurations are designed by MPEG Reconfigurable Video Coding (RVC) committee. +MPEG RVC standard is built on a stream-based dataflow representation of +decoders. It is composed of a standard library of coding tools written in +RVC-CAL language and a dataflow configuration — block diagram — +of a decoder.

+ +

Jade project is hosted as part of the Open +RVC-CAL Compiler and requires it to translate the RVC-CAL standard library +of video coding tools into an LLVM assembly code.

+ +
+ + + + +
+

Neko LLVM JIT +replaces the standard Neko JIT with an LLVM-based implementation. While not +fully complete, it is already providing a 1.5x speedup on 64-bit systems. +Neko LLVM JIT requires LLVM 2.8 or later.

+ +
+ + + + +
+

+Crack aims to provide +the ease of development of a scripting language with the performance of a +compiled language. The language derives concepts from C++, Java and Python, +incorporating object-oriented programming, operator overloading and strong +typing. Crack 0.2 works with LLVM 2.7, and the forthcoming Crack 0.2.1 release +builds on LLVM 2.8.

+ +
+ + + + +
+

+DTMC provides support for +Transactional Memory, which is an easy-to-use and efficient way to synchronize +accesses to shared memory. Transactions can contain normal C/C++ code (e.g., +__transaction { list.remove(x); x.refCount--; }) and will be executed +virtually atomically and isolated from other transactions.

+ +
+ + + + +
+

+Kai (Japanese 会 for +meeting/gathering) is an experimental interpreter that provides a highly +extensible runtime environment and explicit control over the compilation +process. Programs are defined using nested symbolic expressions, which are all +parsed into first-class values with minimal intrinsic semantics. Kai can +generate optimised code at run-time (using LLVM) in order to exploit the nature +of the underlying hardware and to integrate with external software libraries. +It is a unique exploration into world of dynamic code compilation, and the +interaction between high level and low level semantics.

+ +
+ + + + +
+

+OSL is a shading +language designed for use in physically based renderers and in particular +production rendering. By using LLVM instead of the interpreter, it was able to +meet its performance goals (>= C-code) while retaining the benefits of +runtime specialization and a portable high-level language. +

+ +
+ + + + + + + +
+ +

This release includes a huge number of bug fixes, performance tweaks and +minor improvements. Some of the major improvements and new features are listed +in this section. +

+ +
+ + + + +
+ +

LLVM 2.8 includes several major new capabilities:

+ +
    +
  • As mentioned above, libc++ and LLDB are major new additions to the LLVM collective.
  • +
  • LLVM 2.8 now has pretty decent support for debugging optimized code. You + should be able to reliably get debug info for function arguments, assuming + that the value is actually available where you have stopped.
  • +
  • A new 'llvm-diff' tool is available that does a semantic diff of .ll + files.
  • +
  • The MC subproject has made major progress in this release. + Direct .o file writing support for darwin/x86[-64] is now reliable and + support for other targets and object file formats are in progress.
  • +
+ +
+ + + + +
+

LLVM IR has several new features for better support of new targets and that +expose new optimization opportunities:

+ +
    +
  • The memcpy, memmove, and memset + intrinsics now take address space qualified pointers and a bit to indicate + whether the transfer is "volatile" or not. +
  • +
  • Per-instruction debug info metadata is much faster and uses less memory by + using the new DebugLoc class.
  • +
  • LLVM IR now has a more formalized concept of "trap values", which allow the optimizer + to optimize more aggressively in the presence of undefined behavior, while + still producing predictable results.
  • +
  • LLVM IR now supports two new linkage + types (linker_private_weak and linker_private_weak_def_auto) which map + onto some obscure MachO concepts.
  • +
+ +
+ + + + +
+ +

In addition to a large array of minor performance tweaks and bug fixes, this +release includes a few major enhancements and additions to the optimizers:

+ +
    +
  • As mentioned above, the optimizer now has support for updating debug + information as it goes. A key aspect of this is the new llvm.dbg.value + intrinsic. This intrinsic represents debug info for variables that are + promoted to SSA values (typically by mem2reg or the -scalarrepl passes).
  • + +
  • The JumpThreading pass is now much more aggressive about implied value + relations, allowing it to thread conditions like "a == 4" when a is known to + be 13 in one of the predecessors of a block. It does this in conjunction + with the new LazyValueInfo analysis pass.
  • +
  • The new RegionInfo analysis pass identifies single-entry single-exit regions + in the CFG. You can play with it with the "opt -regions -analyze" or + "opt -view-regions" commands.
  • +
  • The loop optimizer has significantly improved strength reduction and analysis + capabilities. Notably it is able to build on the trap value and signed + integer overflow information to optimize <= and >= loops.
  • +
  • The CallGraphSCCPassManager now has some basic support for iterating within + an SCC when a optimizer devirtualizes a function call. This allows inlining + through indirect call sites that are devirtualized by store-load forwarding + and other optimizations.
  • +
  • The new -loweratomic pass is available + to lower atomic instructions into their non-atomic form. This can be useful + to optimize generic code that expects to run in a single-threaded + environment.
  • +
+ + + +
+ + + + +
+

+The LLVM Machine Code (aka MC) subsystem was created to solve a number +of problems in the realm of assembly, disassembly, object file format handling, +and a number of other related areas that CPU instruction-set level tools work +in.

+ +

The MC subproject has made great leaps in LLVM 2.8. For example, support for + directly writing .o files from LLC (and clang) now works reliably for + darwin/x86[-64] (including inline assembly support) and the integrated + assembler is turned on by default in Clang for these targets. This provides + improved compile times among other things.

+ +
    +
  • The entire compiler has converted over to using the MCStreamer assembler API + instead of writing out a .s file textually.
  • +
  • The "assembler parser" is far more mature than in 2.7, supporting a full + complement of directives, now supports assembler macros, etc.
  • +
  • The "assembler backend" has been completed, including support for relaxation + relocation processing and all the other things that an assembler does.
  • +
  • The MachO file format support is now fully functional and works.
  • +
  • The MC disassembler now fully supports ARM and Thumb. ARM assembler support + is still in early development though.
  • +
  • The X86 MC assembler now supports the X86 AES and AVX instruction set.
  • +
  • Work on ELF and COFF object files and ARM target support is well underway, + but isn't useful yet in LLVM 2.8. Please contact the llvmdev mailing list + if you're interested in this.
  • +
+ +

For more information, please see the Intro to the +LLVM MC Project Blog Post. +

+ +
+ + + + + +
+ +

We have put a significant amount of work into the code generator +infrastructure, which allows us to implement more aggressive algorithms and make +it run faster:

+ +
    +
  • The clang/gcc -momit-leaf-frame-pointer argument is now supported.
  • +
  • The clang/gcc -ffunction-sections and -fdata-sections arguments are now + supported on ELF targets (like GCC).
  • +
  • The MachineCSE pass is now tuned and on by default. It eliminates common + subexpressions that are exposed when lowering to machine instructions.
  • +
  • The "local" register allocator was replaced by a new "fast" register + allocator. This new allocator (which is often used at -O0) is substantially + faster and produces better code than the old local register allocator.
  • +
  • A new LLC "-regalloc=default" option is available, which automatically + chooses a register allocator based on the -O optimization level.
  • +
  • The common code generator code was modified to promote illegal argument and + return value vectors to wider ones when possible instead of scalarizing + them. For example, <3 x float> will now pass in one SSE register + instead of 3 on X86. This generates substantially better code since the + rest of the code generator was already expecting this.
  • +
  • The code generator uses a new "COPY" machine instruction. This speeds up + the code generator and eliminates the need for targets to implement the + isMoveInstr hook. Also, the copyRegToReg hook was renamed to copyPhysReg + and simplified.
  • +
  • The code generator now has a "LocalStackSlotPass", which optimizes stack + slot access for targets (like ARM) that have limited stack displacement + addressing.
  • +
  • A new "PeepholeOptimizer" is available, which eliminates sign and zero + extends, and optimizes away compare instructions when the condition result + is available from a previous instruction.
  • +
  • Atomic operations now get legalized into simpler atomic operations if not + natively supported, easing the implementation burden on targets.
  • +
  • We have added two new bottom-up pre-allocation register pressure aware schedulers: +
      +
    1. The hybrid scheduler schedules aggressively to minimize schedule length when registers are available and avoid overscheduling in high pressure situations.
    2. +
    3. The instruction-level-parallelism scheduler schedules for maximum ILP when registers are available and avoid overscheduling in high pressure situations.
    4. +
  • +
  • The tblgen type inference algorithm was rewritten to be more consistent and + diagnose more target bugs. If you have an out-of-tree backend, you may + find that it finds bugs in your target description. This support also + allows limited support for writing patterns for instructions that return + multiple results (e.g. a virtual register and a flag result). The + 'parallel' modifier in tblgen was removed, you should use the new support + for multiple results instead.
  • +
  • A new (experimental) "-rendermf" pass is available which renders a + MachineFunction into HTML, showing live ranges and other useful + details.
  • +
  • The new SubRegIndex tablegen class allows subregisters to be indexed + symbolically instead of numerically. If your target uses subregisters you + will need to adapt to use SubRegIndex when you upgrade to 2.8.
  • + + +
  • The -fast-isel instruction selection path (used at -O0 on X86) was rewritten + to work bottom-up on basic blocks instead of top down. This makes it + slightly faster (because the MachineDCE pass is not needed any longer) and + allows it to generate better code in some cases.
  • + +
+
+ + + + +
+

New features and major changes in the X86 target include: +

+ +
    +
  • The X86 backend now supports holding X87 floating point stack values + in registers across basic blocks, dramatically improving performance of code + that uses long double, and when targeting CPUs that don't support SSE.
  • + +
  • The X86 backend now uses a SSEDomainFix pass to optimize SSE operations. On + Nehalem ("Core i7") and newer CPUs there is a 2 cycle latency penalty on + using a register in a different domain than where it was defined. This pass + optimizes away these stalls.
  • + +
  • The X86 backend now promotes 16-bit integer operations to 32-bits when + possible. This avoids 0x66 prefixes, which are slow on some + microarchitectures and bloat the code on all of them.
  • + +
  • The X86 backend now supports the Microsoft "thiscall" calling convention, + and a calling convention to support + ghc.
  • + +
  • The X86 backend supports a new "llvm.x86.int" intrinsic, which maps onto + the X86 "int $42" and "int3" instructions.
  • + +
  • At the IR level, the <2 x float> datatype is now promoted and passed + around as a <4 x float> instead of being passed and returned as an MMX + vector. If you have a frontend that uses this, please pass and return a + <2 x i32> instead (using bitcasts).
  • + +
  • When printing .s files in verbose assembly mode (the default for clang -S), + the X86 backend now decodes X86 shuffle instructions and prints human + readable comments after the most inscrutable of them, e.g.: + +
    +  insertps $113, %xmm3, %xmm0 # xmm0 = zero,xmm0[1,2],xmm3[1]
    +  unpcklps %xmm1, %xmm0       # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
    +  pshufd   $1, %xmm1, %xmm1   # xmm1 = xmm1[1,0,0,0]
    +
    +
  • + +
+ +
+ + + + +
+

New features of the ARM target include: +

+ +
    +
  • The ARM backend now optimizes tail calls into jumps.
  • +
  • Scheduling is improved through the new list-hybrid scheduler as well + as through better modeling of structural hazards.
  • +
  • Half float instructions are now + supported.
  • +
  • NEON support has been improved to model instructions which operate onto + multiple consecutive registers more aggressively. This avoids lots of + extraneous register copies.
  • +
  • The ARM backend now uses a new "ARMGlobalMerge" pass, which merges several + global variables into one, saving extra address computation (all the global + variables can be accessed via same base address) and potentially reducing + register pressure.
  • + +
  • The ARM backend has received many minor improvements and tweaks which lead + to substantially better performance in a wide range of different scenarios. +
  • + +
  • The ARM NEON intrinsics have been substantially reworked to reduce + redundancy and improve code generation. Some of the major changes are: +
      +
    1. + All of the NEON load and store intrinsics (llvm.arm.neon.vld* and + llvm.arm.neon.vst*) take an extra parameter to specify the alignment in bytes + of the memory being accessed. +
    2. +
    3. + The llvm.arm.neon.vaba intrinsic (vector absolute difference and + accumulate) has been removed. This operation is now represented using + the llvm.arm.neon.vabd intrinsic (vector absolute difference) followed by a + vector add. +
    4. +
    5. + The llvm.arm.neon.vabdl and llvm.arm.neon.vabal intrinsics (lengthening + vector absolute difference with and without accumulation) have been removed. + They are represented using the llvm.arm.neon.vabd intrinsic (vector absolute + difference) followed by a vector zero-extend operation, and for vabal, + a vector add. +
    6. +
    7. + The llvm.arm.neon.vmovn intrinsic has been removed. Calls of this intrinsic + are now replaced by vector truncate operations. +
    8. +
    9. + The llvm.arm.neon.vmovls and llvm.arm.neon.vmovlu intrinsics have been + removed. They are now represented as vector sign-extend (vmovls) and + zero-extend (vmovlu) operations. +
    10. +
    11. + The llvm.arm.neon.vaddl*, llvm.arm.neon.vaddw*, llvm.arm.neon.vsubl*, and + llvm.arm.neon.vsubw* intrinsics (lengthening vector add and subtract) have + been removed. They are replaced by vector add and vector subtract operations + where one (vaddw, vsubw) or both (vaddl, vsubl) of the operands are either + sign-extended or zero-extended. +
    12. +
    13. + The llvm.arm.neon.vmulls, llvm.arm.neon.vmullu, llvm.arm.neon.vmlal*, and + llvm.arm.neon.vmlsl* intrinsics (lengthening vector multiply with and without + accumulation and subtraction) have been removed. These operations are now + represented as vector multiplications where the operands are either + sign-extended or zero-extended, followed by a vector add for vmlal or a + vector subtract for vmlsl. Note that the polynomial vector multiply + intrinsic, llvm.arm.neon.vmullp, remains unchanged. +
    14. +
    +
  • + +
+
+ + + + + +
+ +

If you're already an LLVM user or developer with out-of-tree changes based +on LLVM 2.7, this section lists some "gotchas" that you may run into upgrading +from the previous release.

+ +
    +
  • The build configuration machinery changed the output directory names. It + wasn't clear to many people that a "Release-Asserts" build was a release build + without asserts. To make this more clear, "Release" does not include + assertions and "Release+Asserts" does (likewise, "Debug" and + "Debug+Asserts").
  • +
  • The MSIL Backend was removed, it was unsupported and broken.
  • +
  • The ABCD, SSI, and SCCVN passes were removed. These were not fully + functional and their behavior has been or will be subsumed by the + LazyValueInfo pass.
  • +
  • The LLVM IR 'Union' feature was removed. While this is a desirable feature + for LLVM IR to support, the existing implementation was half baked and + barely useful. We'd really like anyone interested to resurrect the work and + finish it for a future release.
  • +
  • If you're used to reading .ll files, you'll probably notice that .ll file + dumps don't produce #uses comments anymore. To get them, run a .bc file + through "llvm-dis --show-annotations".
  • +
  • Target triples are now stored in a normalized form, and all inputs from + humans are expected to be normalized by Triple::normalize before being + stored in a module triple or passed to another library.
  • +
+ + + +

In addition, many APIs have changed in this release. Some of the major LLVM +API changes are:

+
    +
  • LLVM 2.8 changes the internal order of operands in InvokeInst + and CallInst. + To be portable across releases, please use the CallSite class and the + high-level accessors, such as getCalledValue and + setUnwindDest. +
  • +
  • + You can no longer pass use_iterators directly to cast<> (and similar), + because these routines tend to perform costly dereference operations more + than once. You have to dereference the iterators yourself and pass them in. +
  • +
  • + llvm.memcpy.*, llvm.memset.*, llvm.memmove.* intrinsics take an extra + parameter now ("i1 isVolatile"), totaling 5 parameters, and the pointer + operands are now address-space qualified. + If you were creating these intrinsic calls and prototypes yourself (as opposed + to using Intrinsic::getDeclaration), you can use + UpgradeIntrinsicFunction/UpgradeIntrinsicCall to be portable across releases. +
  • +
  • + SetCurrentDebugLocation takes a DebugLoc now instead of a MDNode. + Change your code to use + SetCurrentDebugLocation(DebugLoc::getFromDILocation(...)). +
  • +
  • + The RegisterPass and RegisterAnalysisGroup templates are + considered deprecated, but continue to function in LLVM 2.8. Clients are + strongly advised to use the upcoming INITIALIZE_PASS() and + INITIALIZE_AG_PASS() macros instead. +
  • +
  • + The constructor for the Triple class no longer tries to understand odd triple + specifications. Frontends should ensure that they only pass valid triples to + LLVM. The Triple::normalize utility method has been added to help front-ends + deal with funky triples. +
  • +
  • + The signature of the GCMetadataPrinter::finishAssembly virtual + function changed: the raw_ostream and MCAsmInfo arguments + were dropped. GC plugins which compute stack maps must be updated to avoid + having the old definition overload the new signature. +
  • +
  • + The signature of MemoryBuffer::getMemBuffer changed. Unfortunately + calls intended for the old version still compile, but will not work correctly, + leading to a confusing error about an invalid header in the bitcode. +
  • + +
  • + Some APIs were renamed: +
      +
    • llvm_report_error -> report_fatal_error
    • +
    • llvm_install_error_handler -> install_fatal_error_handler
    • +
    • llvm::DwarfExceptionHandling -> llvm::JITExceptionHandling
    • +
    • VISIBILITY_HIDDEN -> LLVM_LIBRARY_VISIBILITY
    • +
    +
  • + +
  • + Some public headers were renamed: +
      +
    • llvm/Assembly/AsmAnnotationWriter.h was renamed + to llvm/Assembly/AssemblyAnnotationWriter.h +
    • +
    +
+ +
+ + + + +
+ +

This section lists changes to the LLVM development infrastructure. This +mostly impacts users who actively work on LLVM or follow development on +mainline, but may also impact users who leverage the LLVM build infrastructure +or are interested in LLVM qualification.

+ +
    +
  • The default for make check is now to use + the lit testing tool, which is + part of LLVM itself. You can use lit directly as well, or use + the llvm-lit tool which is created as part of a Makefile or CMake + build (and knows how to find the appropriate tools). See the lit + documentation and the blog + post, and PR5217 + for more information.
  • + +
  • The LLVM test-suite infrastructure has a new "simple" test format + (make TEST=simple). The new format is intended to require only a + compiler and not a full set of LLVM tools. This makes it useful for testing + released compilers, for running the test suite with other compilers (for + performance comparisons), and makes sure that we are testing the compiler as + users would see it. The new format is also designed to work using reference + outputs instead of comparison to a baseline compiler, which makes it run much + faster and makes it less system dependent.
  • + +
  • Significant progress has been made on a new interface to running the + LLVM test-suite (aka the LLVM "nightly tests") using + the LNT infrastructure. The LNT + interface to the test-suite brings significantly improved reporting + capabilities for monitoring the correctness and generated code quality + produced by LLVM over time.
  • +
+
+ + + + + +
+ +

This section contains significant known problems with the LLVM system, +listed by component. If you run into a problem, please check the LLVM bug database and submit a bug if +there isn't already one.

+ +
+ + + + +
+ +

The following components of this LLVM release are either untested, known to +be broken or unreliable, or are in early development. These components should +not be relied on, and bugs should not be filed against them, but they may be +useful to some people. In particular, if you would like to work on one of these +components, please contact us on the LLVMdev list.

+ +
    +
  • The Alpha, Blackfin, CellSPU, MicroBlaze, MSP430, MIPS, SystemZ + and XCore backends are experimental.
  • +
  • llc "-filetype=obj" is experimental on all targets + other than darwin-i386 and darwin-x86_64.
  • +
+ +
+ + + + +
+ +
    +
  • The X86 backend does not yet support + all inline assembly that uses the X86 + floating point stack. It supports the 'f' and 't' constraints, but not + 'u'.
  • +
  • Win64 code generation wasn't widely tested. Everything should work, but we + expect small issues to happen. Also, llvm-gcc cannot build the mingw64 + runtime currently due to lack of support for the 'u' inline assembly + constraint and for X87 floating point inline assembly.
  • +
  • The X86-64 backend does not yet support the LLVM IR instruction + va_arg. Currently, front-ends support variadic + argument constructs on X86-64 by lowering them manually.
  • +
+ +
+ + + + +
+ +
    +
  • The Linux PPC32/ABI support needs testing for the interpreter and static +compilation, and lacks support for debug information.
  • +
+ +
+ + + + +
+ +
    +
  • Thumb mode works only on ARMv6 or higher processors. On sub-ARMv6 +processors, thumb programs can crash or produce wrong +results (PR1388).
  • +
  • Compilation for ARM Linux OABI (old ABI) is supported but not fully tested. +
  • +
+ +
+ + + + +
+ +
    +
  • The SPARC backend only supports the 32-bit SPARC ABI (-m32); it does not + support the 64-bit SPARC ABI (-m64).
  • +
+ +
+ + + + +
+ +
    +
  • 64-bit MIPS targets are not supported yet.
  • +
+ +
+ + + + +
+ +
    + +
  • On 21164s, some rare FP arithmetic sequences which may trap do not have the +appropriate nops inserted to ensure restartability.
  • + +
+
+ + + + +
+ +

The C backend has numerous problems and is not being actively maintained. +Depending on it for anything serious is not advised.

+ + + +
+ + + + + +
+ +

llvm-gcc is generally very stable for the C family of languages. The only + major language feature of GCC not supported by llvm-gcc is the + __builtin_apply family of builtins. However, some extensions + are only supported on some targets. For example, trampolines are only + supported on some targets (these are used when you take the address of a + nested function).

+ +

Fortran support generally works, but there are still several unresolved bugs + in Bugzilla. Please see the + tools/gfortran component for details. Note that llvm-gcc is missing major + Fortran performance work in the frontend and library that went into GCC after + 4.2. If you are interested in Fortran, we recommend that you consider using + dragonegg instead.

+ +

The llvm-gcc 4.2 Ada compiler has basic functionality, but is no longer being +actively maintained. If you are interested in Ada, we recommend that you +consider using dragonegg instead.

+
+ + + + + +
+ +

A wide variety of additional information is available on the LLVM web page, in particular in the documentation section. The web page also +contains versions of the API documentation which is up-to-date with the +Subversion version of the source code. +You can access versions of these documents specific to this release by going +into the "llvm/doc/" directory in the LLVM tree.

+ +

If you have any questions or comments about LLVM, please feel free to contact +us via the mailing +lists.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/SourceLevelDebugging.html b/final/docs/SourceLevelDebugging.html new file mode 100644 index 00000000000..3f88e2fc391 --- /dev/null +++ b/final/docs/SourceLevelDebugging.html @@ -0,0 +1,1783 @@ + + + + + Source Level Debugging with LLVM + + + + +
Source Level Debugging with LLVM
+ + + + + +
+ + +A leafy and green bug eater +
+ +
+

Written by Chris Lattner + and Jim Laskey

+
+ + + + + + +
+ +

This document is the central repository for all information pertaining to + debug information in LLVM. It describes the actual format + that the LLVM debug information takes, which is useful for those + interested in creating front-ends or dealing directly with the information. + Further, this document provides specific examples of what debug information + for C/C++ looks like.

+ +
+ + + + +
+ +

The idea of the LLVM debugging information is to capture how the important + pieces of the source-language's Abstract Syntax Tree map onto LLVM code. + Several design aspects have shaped the solution that appears here. The + important ones are:

+ +
    +
  • Debugging information should have very little impact on the rest of the + compiler. No transformations, analyses, or code generators should need to + be modified because of debugging information.
  • + +
  • LLVM optimizations should interact in well-defined and + easily described ways with the debugging information.
  • + +
  • Because LLVM is designed to support arbitrary programming languages, + LLVM-to-LLVM tools should not need to know anything about the semantics of + the source-level-language.
  • + +
  • Source-level languages are often widely different from one another. + LLVM should not put any restrictions of the flavor of the source-language, + and the debugging information should work with any language.
  • + +
  • With code generator support, it should be possible to use an LLVM compiler + to compile a program to native machine code and standard debugging + formats. This allows compatibility with traditional machine-code level + debuggers, like GDB or DBX.
  • +
+ +

The approach used by the LLVM implementation is to use a small set + of intrinsic functions to define a + mapping between LLVM program objects and the source-level objects. The + description of the source-level program is maintained in LLVM metadata + in an implementation-defined format + (the C/C++ front-end currently uses working draft 7 of + the DWARF 3 + standard).

+ +

When a program is being debugged, a debugger interacts with the user and + turns the stored debug information into source-language specific information. + As such, a debugger must be aware of the source-language, and is thus tied to + a specific language or family of languages.

+ +
+ + + + +
+ +

The role of debug information is to provide meta information normally + stripped away during the compilation process. This meta information provides + an LLVM user a relationship between generated code and the original program + source code.

+ +

Currently, debug information is consumed by DwarfDebug to produce dwarf + information used by the gdb debugger. Other targets could use the same + information to produce stabs or other debug forms.

+ +

It would also be reasonable to use debug information to feed profiling tools + for analysis of generated code, or, tools for reconstructing the original + source from generated code.

+ +

TODO - expound a bit more.

+ +
+ + + + +
+ +

An extremely high priority of LLVM debugging information is to make it + interact well with optimizations and analysis. In particular, the LLVM debug + information provides the following guarantees:

+ +
    +
  • LLVM debug information always provides information to accurately read + the source-level state of the program, regardless of which LLVM + optimizations have been run, and without any modification to the + optimizations themselves. However, some optimizations may impact the + ability to modify the current state of the program with a debugger, such + as setting program variables, or calling functions that have been + deleted.
  • + +
  • LLVM optimizations gracefully interact with debugging information. If + they are not aware of debug information, they are automatically disabled + as necessary in the cases that would invalidate the debug info. This + retains the LLVM features, making it easy to write new + transformations.
  • + +
  • As desired, LLVM optimizations can be upgraded to be aware of the LLVM + debugging information, allowing them to update the debugging information + as they perform aggressive optimizations. This means that, with effort, + the LLVM optimizers could optimize debug code just as well as non-debug + code.
  • + +
  • LLVM debug information does not prevent many important optimizations from + happening (for example inlining, basic block reordering/merging/cleanup, + tail duplication, etc), further reducing the amount of the compiler that + eventually is "aware" of debugging information.
  • + +
  • LLVM debug information is automatically optimized along with the rest of + the program, using existing facilities. For example, duplicate + information is automatically merged by the linker, and unused information + is automatically removed.
  • +
+ +

Basically, the debug information allows you to compile a program with + "-O0 -g" and get full debug information, allowing you to arbitrarily + modify the program as it executes from a debugger. Compiling a program with + "-O3 -g" gives you full debug information that is always available + and accurate for reading (e.g., you get accurate stack traces despite tail + call elimination and inlining), but you might lose the ability to modify the + program and call functions where were optimized out of the program, or + inlined away completely.

+ +

LLVM test suite provides a + framework to test optimizer's handling of debugging information. It can be + run like this:

+ +
+
+% cd llvm/projects/test-suite/MultiSource/Benchmarks  # or some other level
+% make TEST=dbgopt
+
+
+ +

This will test impact of debugging information on optimization passes. If + debugging information influences optimization passes then it will be reported + as a failure. See TestingGuide for more + information on LLVM test infrastructure and how to run various tests.

+ +
+ + + + + +
+ +

LLVM debugging information has been carefully designed to make it possible + for the optimizer to optimize the program and debugging information without + necessarily having to know anything about debugging information. In + particular, the use of metadata avoids duplicated debugging information from + the beginning, and the global dead code elimination pass automatically + deletes debugging information for a function if it decides to delete the + function.

+ +

To do this, most of the debugging information (descriptors for types, + variables, functions, source files, etc) is inserted by the language + front-end in the form of LLVM metadata.

+ +

Debug information is designed to be agnostic about the target debugger and + debugging information representation (e.g. DWARF/Stabs/etc). It uses a + generic pass to decode the information that represents variables, types, + functions, namespaces, etc: this allows for arbitrary source-language + semantics and type-systems to be used, as long as there is a module + written for the target debugger to interpret the information.

+ +

To provide basic functionality, the LLVM debugger does have to make some + assumptions about the source-level language being debugged, though it keeps + these to a minimum. The only common features that the LLVM debugger assumes + exist are source files, + and program objects. These abstract + objects are used by a debugger to form stack traces, show information about + local variables, etc.

+ +

This section of the documentation first describes the representation aspects + common to any source-language. The next section + describes the data layout conventions used by the C and C++ front-ends.

+ +
+ + + + +
+ +

In consideration of the complexity and volume of debug information, LLVM + provides a specification for well formed debug descriptors.

+ +

Consumers of LLVM debug information expect the descriptors for program + objects to start in a canonical format, but the descriptors can include + additional information appended at the end that is source-language + specific. All LLVM debugging information is versioned, allowing backwards + compatibility in the case that the core structures need to change in some + way. Also, all debugging information objects start with a tag to indicate + what type of object it is. The source-language is allowed to define its own + objects, by using unreserved tag numbers. We recommend using with tags in + the range 0x1000 through 0x2000 (there is a defined enum DW_TAG_user_base = + 0x1000.)

+ +

The fields of debug descriptors used internally by LLVM + are restricted to only the simple data types i32, i1, + float, double, mdstring and mdnode.

+ +
+
+!1 = metadata !{
+  i32,   ;; A tag
+  ...
+}
+
+
+ +

The first field of a descriptor is always an + i32 containing a tag value identifying the content of the + descriptor. The remaining fields are specific to the descriptor. The values + of tags are loosely bound to the tag values of DWARF information entries. + However, that does not restrict the use of the information supplied to DWARF + targets. To facilitate versioning of debug information, the tag is augmented + with the current debug version (LLVMDebugVersion = 8 << 16 or 0x80000 or + 524288.)

+ +

The details of the various descriptors follow.

+ +
+ + + + +
+ +
+
+!0 = metadata !{
+  i32,       ;; Tag = 17 + LLVMDebugVersion 
+             ;; (DW_TAG_compile_unit)
+  i32,       ;; Unused field. 
+  i32,       ;; DWARF language identifier (ex. DW_LANG_C89) 
+  metadata,  ;; Source file name
+  metadata,  ;; Source file directory (includes trailing slash)
+  metadata   ;; Producer (ex. "4.0.1 LLVM (LLVM research group)")
+  i1,        ;; True if this is a main compile unit. 
+  i1,        ;; True if this is optimized.
+  metadata,  ;; Flags
+  i32        ;; Runtime version
+}
+
+
+ +

These descriptors contain a source language ID for the file (we use the DWARF + 3.0 ID numbers, such as DW_LANG_C89, DW_LANG_C_plus_plus, + DW_LANG_Cobol74, etc), three strings describing the filename, + working directory of the compiler, and an identifier string for the compiler + that produced it.

+ +

Compile unit descriptors provide the root context for objects declared in a + specific compilation unit. File descriptors are defined using this context.

+ +
+ + + + +
+ +
+
+!0 = metadata !{
+  i32,       ;; Tag = 41 + LLVMDebugVersion 
+             ;; (DW_TAG_file_type)
+  metadata,  ;; Source file name
+  metadata,  ;; Source file directory (includes trailing slash)
+  metadata   ;; Reference to compile unit where defined
+}
+
+
+ +

These descriptors contain information for a file. Global variables and top + level functions would be defined using this context.k File descriptors also + provide context for source line correspondence.

+ +

Each input file is encoded as a separate file descriptor in LLVM debugging + information output. Each file descriptor would be defined using a + compile unit.

+ +
+ + + + +
+ +
+
+!1 = metadata !{
+  i32,      ;; Tag = 52 + LLVMDebugVersion 
+            ;; (DW_TAG_variable)
+  i32,      ;; Unused field.
+  metadata, ;; Reference to context descriptor
+  metadata, ;; Name
+  metadata, ;; Display name (fully qualified C++ name)
+  metadata, ;; MIPS linkage name (for C++)
+  metadata, ;; Reference to file where defined
+  i32,      ;; Line number where defined
+  metadata, ;; Reference to type descriptor
+  i1,       ;; True if the global is local to compile unit (static)
+  i1,       ;; True if the global is defined in the compile unit (not extern)
+  {}*       ;; Reference to the global variable
+}
+
+
+ +

These descriptors provide debug information about globals variables. The +provide details such as name, type and where the variable is defined.

+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32,      ;; Tag = 46 + LLVMDebugVersion
+            ;; (DW_TAG_subprogram)
+  i32,      ;; Unused field.
+  metadata, ;; Reference to context descriptor
+  metadata, ;; Name
+  metadata, ;; Display name (fully qualified C++ name)
+  metadata, ;; MIPS linkage name (for C++)
+  metadata, ;; Reference to file where defined
+  i32,      ;; Line number where defined
+  metadata, ;; Reference to type descriptor
+  i1,       ;; True if the global is local to compile unit (static)
+  i1        ;; True if the global is defined in the compile unit (not extern)
+  i32       ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual
+  i32       ;; Index into a virtual function
+  metadata, ;; indicates which base type contains the vtable pointer for the 
+            ;; derived class
+  i1        ;; isArtificial
+  i1        ;; isOptimized
+  Function *;; Pointer to LLVM function
+}
+
+
+ +

These descriptors provide debug information about functions, methods and + subprograms. They provide details such as name, return types and the source + location where the subprogram is defined.

+ +
+ + + + +
+ +
+
+!3 = metadata !{
+  i32,     ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block)
+  metadata,;; Reference to context descriptor
+  i32,     ;; Line number
+  i32      ;; Column number
+}
+
+
+ +

These descriptors provide debug information about nested blocks within a + subprogram. The line number and column numbers are used to dinstinguish + two lexical blocks at same depth.

+ +
+ + + + +
+ +
+
+!4 = metadata !{
+  i32,      ;; Tag = 36 + LLVMDebugVersion 
+            ;; (DW_TAG_base_type)
+  metadata, ;; Reference to context (typically a compile unit)
+  metadata, ;; Name (may be "" for anonymous types)
+  metadata, ;; Reference to file where defined (may be NULL)
+  i32,      ;; Line number where defined (may be 0)
+  i64,      ;; Size in bits
+  i64,      ;; Alignment in bits
+  i64,      ;; Offset in bits
+  i32,      ;; Flags
+  i32       ;; DWARF type encoding
+}
+
+
+ +

These descriptors define primitive types used in the code. Example int, bool + and float. The context provides the scope of the type, which is usually the + top level. Since basic types are not usually user defined the compile unit + and line number can be left as NULL and 0. The size, alignment and offset + are expressed in bits and can be 64 bit values. The alignment is used to + round the offset when embedded in a + composite type (example to keep float + doubles on 64 bit boundaries.) The offset is the bit offset if embedded in + a composite type.

+ +

The type encoding provides the details of the type. The values are typically + one of the following:

+ +
+
+DW_ATE_address       = 1
+DW_ATE_boolean       = 2
+DW_ATE_float         = 4
+DW_ATE_signed        = 5
+DW_ATE_signed_char   = 6
+DW_ATE_unsigned      = 7
+DW_ATE_unsigned_char = 8
+
+
+ +
+ + + + +
+ +
+
+!5 = metadata !{
+  i32,      ;; Tag (see below)
+  metadata, ;; Reference to context
+  metadata, ;; Name (may be "" for anonymous types)
+  metadata, ;; Reference to file where defined (may be NULL)
+  i32,      ;; Line number where defined (may be 0)
+  i64,      ;; Size in bits
+  i64,      ;; Alignment in bits
+  i64,      ;; Offset in bits
+  metadata  ;; Reference to type derived from
+}
+
+
+ +

These descriptors are used to define types derived from other types. The +value of the tag varies depending on the meaning. The following are possible +tag values:

+ +
+
+DW_TAG_formal_parameter = 5
+DW_TAG_member           = 13
+DW_TAG_pointer_type     = 15
+DW_TAG_reference_type   = 16
+DW_TAG_typedef          = 22
+DW_TAG_const_type       = 38
+DW_TAG_volatile_type    = 53
+DW_TAG_restrict_type    = 55
+
+
+ +

DW_TAG_member is used to define a member of + a composite type + or subprogram. The type of the member is + the derived + type. DW_TAG_formal_parameter is used to define a member which + is a formal argument of a subprogram.

+ +

DW_TAG_typedef is used to provide a name for the derived type.

+ +

DW_TAG_pointer_type,DW_TAG_reference_type, + DW_TAG_const_type, DW_TAG_volatile_type + and DW_TAG_restrict_type are used to qualify + the derived type.

+ +

Derived type location can be determined + from the compile unit and line number. The size, alignment and offset are + expressed in bits and can be 64 bit values. The alignment is used to round + the offset when embedded in a composite + type (example to keep float doubles on 64 bit boundaries.) The offset is + the bit offset if embedded in a composite + type.

+ +

Note that the void * type is expressed as a type derived from NULL. +

+ +
+ + + + +
+ +
+
+!6 = metadata !{
+  i32,      ;; Tag (see below)
+  metadata, ;; Reference to context
+  metadata, ;; Name (may be "" for anonymous types)
+  metadata, ;; Reference to file where defined (may be NULL)
+  i32,      ;; Line number where defined (may be 0)
+  i64,      ;; Size in bits
+  i64,      ;; Alignment in bits
+  i64,      ;; Offset in bits
+  i32,      ;; Flags
+  metadata, ;; Reference to type derived from
+  metadata, ;; Reference to array of member descriptors
+  i32       ;; Runtime languages
+}
+
+
+ +

These descriptors are used to define types that are composed of 0 or more +elements. The value of the tag varies depending on the meaning. The following +are possible tag values:

+ +
+
+DW_TAG_array_type       = 1
+DW_TAG_enumeration_type = 4
+DW_TAG_structure_type   = 19
+DW_TAG_union_type       = 23
+DW_TAG_vector_type      = 259
+DW_TAG_subroutine_type  = 21
+DW_TAG_inheritance      = 28
+
+
+ +

The vector flag indicates that an array type is a native packed vector.

+ +

The members of array types (tag = DW_TAG_array_type) or vector types + (tag = DW_TAG_vector_type) are subrange + descriptors, each representing the range of subscripts at that level of + indexing.

+ +

The members of enumeration types (tag = DW_TAG_enumeration_type) are + enumerator descriptors, each representing + the definition of enumeration value for the set.

+ +

The members of structure (tag = DW_TAG_structure_type) or union (tag + = DW_TAG_union_type) types are any one of + the basic, + derived + or composite type descriptors, each + representing a field member of the structure or union.

+ +

For C++ classes (tag = DW_TAG_structure_type), member descriptors + provide information about base classes, static members and member + functions. If a member is a derived type + descriptor and has a tag of DW_TAG_inheritance, then the type + represents a base class. If the member of is + a global variable descriptor then it + represents a static member. And, if the member is + a subprogram descriptor then it represents + a member function. For static members and member + functions, getName() returns the members link or the C++ mangled + name. getDisplayName() the simplied version of the name.

+ +

The first member of subroutine (tag = DW_TAG_subroutine_type) type + elements is the return type for the subroutine. The remaining elements are + the formal arguments to the subroutine.

+ +

Composite type location can be + determined from the compile unit and line number. The size, alignment and + offset are expressed in bits and can be 64 bit values. The alignment is used + to round the offset when embedded in + a composite type (as an example, to keep + float doubles on 64 bit boundaries.) The offset is the bit offset if embedded + in a composite type.

+ +
+ + + + +
+ +
+
+!42 = metadata !{
+  i32,    ;; Tag = 33 + LLVMDebugVersion (DW_TAG_subrange_type)
+  i64,    ;; Low value
+  i64     ;; High value
+}
+
+
+ +

These descriptors are used to define ranges of array subscripts for an array + composite type. The low value defines + the lower bounds typically zero for C/C++. The high value is the upper + bounds. Values are 64 bit. High - low + 1 is the size of the array. If low + == high the array will be unbounded.

+ +
+ + + + +
+ +
+
+!6 = metadata !{
+  i32,      ;; Tag = 40 + LLVMDebugVersion 
+            ;; (DW_TAG_enumerator)
+  metadata, ;; Name
+  i64       ;; Value
+}
+
+
+ +

These descriptors are used to define members of an + enumeration composite type, it + associates the name to the value.

+ +
+ + + + +
+ +
+
+!7 = metadata !{
+  i32,      ;; Tag (see below)
+  metadata, ;; Context
+  metadata, ;; Name
+  metadata, ;; Reference to file where defined
+  i32,      ;; Line number where defined
+  metadata  ;; Type descriptor
+}
+
+
+ +

These descriptors are used to define variables local to a sub program. The + value of the tag depends on the usage of the variable:

+ +
+
+DW_TAG_auto_variable   = 256
+DW_TAG_arg_variable    = 257
+DW_TAG_return_variable = 258
+
+
+ +

An auto variable is any variable declared in the body of the function. An + argument variable is any variable that appears as a formal argument to the + function. A return variable is used to track the result of a function and + has no source correspondent.

+ +

The context is either the subprogram or block where the variable is defined. + Name the source variable name. Compile unit and line indicate where the + variable was defined. Type descriptor defines the declared type of the + variable.

+ +
+ + + + +
+ +

LLVM uses several intrinsic functions (name prefixed with "llvm.dbg") to + provide debug information at various points in generated code.

+ +
+ + + + +
+ + + + +
+
+  void %llvm.dbg.value(metadata, i64, metadata)
+
+ +

This intrinsic provides information when a user source variable is set to a + new value. The first argument is the new value (wrapped as metadata). The + second argument is the offset in the user source variable where the new value + is written. The third argument is metadata containing description of the + user source variable.

+
+ + + + +
+

In many languages, the local variables in functions can have their lifetimes + or scopes limited to a subset of a function. In the C family of languages, + for example, variables are only live (readable and writable) within the + source block that they are defined in. In functional languages, values are + only readable after they have been defined. Though this is a very obvious + concept, it is non-trivial to model in LLVM, because it has no notion of + scoping in this sense, and does not want to be tied to a language's scoping + rules.

+ +

In order to handle this, the LLVM debug format uses the metadata attached to + llvm instructions to encode line number and scoping information. Consider + the following C fragment, for example:

+ +
+
+1.  void foo() {
+2.    int X = 21;
+3.    int Y = 22;
+4.    {
+5.      int Z = 23;
+6.      Z = X;
+7.    }
+8.    X = Y;
+9.  }
+
+
+ +

Compiled to LLVM, this function would be represented like this:

+ +
+
+define void @foo() nounwind ssp {
+entry:
+  %X = alloca i32, align 4                        ; <i32*> [#uses=4]
+  %Y = alloca i32, align 4                        ; <i32*> [#uses=4]
+  %Z = alloca i32, align 4                        ; <i32*> [#uses=3]
+  %0 = bitcast i32* %X to {}*                     ; <{}*> [#uses=1]
+  call void @llvm.dbg.declare(metadata !{i32 * %X}, metadata !0), !dbg !7
+  store i32 21, i32* %X, !dbg !8
+  %1 = bitcast i32* %Y to {}*                     ; <{}*> [#uses=1]
+  call void @llvm.dbg.declare(metadata !{i32 * %Y}, metadata !9), !dbg !10
+  store i32 22, i32* %Y, !dbg !11
+  %2 = bitcast i32* %Z to {}*                     ; <{}*> [#uses=1]
+  call void @llvm.dbg.declare(metadata !{i32 * %Z}, metadata !12), !dbg !14
+  store i32 23, i32* %Z, !dbg !15
+  %tmp = load i32* %X, !dbg !16                   ; <i32> [#uses=1]
+  %tmp1 = load i32* %Y, !dbg !16                  ; <i32> [#uses=1]
+  %add = add nsw i32 %tmp, %tmp1, !dbg !16        ; <i32> [#uses=1]
+  store i32 %add, i32* %Z, !dbg !16
+  %tmp2 = load i32* %Y, !dbg !17                  ; <i32> [#uses=1]
+  store i32 %tmp2, i32* %X, !dbg !17
+  ret void, !dbg !18
+}
+
+declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
+
+!0 = metadata !{i32 459008, metadata !1, metadata !"X", 
+                metadata !3, i32 2, metadata !6}; [ DW_TAG_auto_variable ]
+!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", metadata !"foo", 
+               metadata !"foo", metadata !3, i32 1, metadata !4, 
+               i1 false, i1 true}; [DW_TAG_subprogram ]
+!3 = metadata !{i32 458769, i32 0, i32 12, metadata !"foo.c", 
+                metadata !"/private/tmp", metadata !"clang 1.1", i1 true, 
+                i1 false, metadata !"", i32 0}; [DW_TAG_compile_unit ]
+!4 = metadata !{i32 458773, metadata !3, metadata !"", null, i32 0, i64 0, i64 0, 
+                i64 0, i32 0, null, metadata !5, i32 0}; [DW_TAG_subroutine_type ]
+!5 = metadata !{null}
+!6 = metadata !{i32 458788, metadata !3, metadata !"int", metadata !3, i32 0, 
+                i64 32, i64 32, i64 0, i32 0, i32 5}; [DW_TAG_base_type ]
+!7 = metadata !{i32 2, i32 7, metadata !1, null}
+!8 = metadata !{i32 2, i32 3, metadata !1, null}
+!9 = metadata !{i32 459008, metadata !1, metadata !"Y", metadata !3, i32 3, 
+                metadata !6}; [ DW_TAG_auto_variable ]
+!10 = metadata !{i32 3, i32 7, metadata !1, null}
+!11 = metadata !{i32 3, i32 3, metadata !1, null}
+!12 = metadata !{i32 459008, metadata !13, metadata !"Z", metadata !3, i32 5, 
+                 metadata !6}; [ DW_TAG_auto_variable ]
+!13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+!14 = metadata !{i32 5, i32 9, metadata !13, null}
+!15 = metadata !{i32 5, i32 5, metadata !13, null}
+!16 = metadata !{i32 6, i32 5, metadata !13, null}
+!17 = metadata !{i32 8, i32 3, metadata !1, null}
+!18 = metadata !{i32 9, i32 1, metadata !2, null}
+
+
+ +

This example illustrates a few important details about LLVM debugging + information. In particular, it shows how the llvm.dbg.declare + intrinsic and location information, which are attached to an instruction, + are applied together to allow a debugger to analyze the relationship between + statements, variable definitions, and the code used to implement the + function.

+ +
+
+call void @llvm.dbg.declare(metadata, metadata !0), !dbg !7   
+
+
+ +

The first intrinsic + %llvm.dbg.declare + encodes debugging information for the variable X. The metadata + !dbg !7 attached to the intrinsic provides scope information for the + variable X.

+ +
+
+!7 = metadata !{i32 2, i32 7, metadata !1, null}
+!1 = metadata !{i32 458763, metadata !2}; [DW_TAG_lexical_block ]
+!2 = metadata !{i32 458798, i32 0, metadata !3, metadata !"foo", 
+                metadata !"foo", metadata !"foo", metadata !3, i32 1, 
+                metadata !4, i1 false, i1 true}; [DW_TAG_subprogram ]   
+
+
+ +

Here !7 is metadata providing location information. It has four + fields: line number, column number, scope, and original scope. The original + scope represents inline location if this instruction is inlined inside a + caller, and is null otherwise. In this example, scope is encoded by + !1. !1 represents a lexical block inside the scope + !2, where !2 is a + subprogram descriptor. This way the + location information attached to the intrinsics indicates that the + variable X is declared at line number 2 at a function level scope in + function foo.

+ +

Now lets take another example.

+ +
+
+call void @llvm.dbg.declare(metadata, metadata !12), !dbg !14
+
+
+ +

The second intrinsic + %llvm.dbg.declare + encodes debugging information for variable Z. The metadata + !dbg !14 attached to the intrinsic provides scope information for + the variable Z.

+ +
+
+!13 = metadata !{i32 458763, metadata !1}; [DW_TAG_lexical_block ]
+!14 = metadata !{i32 5, i32 9, metadata !13, null}
+
+
+ +

Here !14 indicates that Z is declared at line number 5 and + column number 9 inside of lexical scope !13. The lexical scope + itself resides inside of lexical scope !1 described above.

+ +

The scope information attached with each instruction provides a + straightforward way to find instructions covered by a scope.

+ +
+ + + + + +
+ +

The C and C++ front-ends represent information about the program in a format + that is effectively identical + to DWARF 3.0 in + terms of information content. This allows code generators to trivially + support native debuggers by generating standard dwarf information, and + contains enough information for non-dwarf targets to translate it as + needed.

+ +

This section describes the forms used to represent C and C++ programs. Other + languages could pattern themselves after this (which itself is tuned to + representing programs in the same way that DWARF 3 does), or they could + choose to provide completely different forms if they don't fit into the DWARF + model. As support for debugging information gets added to the various LLVM + source-language front-ends, the information used should be documented + here.

+ +

The following sections provide examples of various C/C++ constructs and the + debug information that would best describe those constructs.

+ +
+ + + + +
+ +

Given the source files MySource.cpp and MyHeader.h located + in the directory /Users/mine/sources, the following code:

+ +
+
+#include "MyHeader.h"
+
+int main(int argc, char *argv[]) {
+  return 0;
+}
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+...
+;;
+;; Define the compile unit for the main source file "/Users/mine/sources/MySource.cpp".
+;;
+!2 = metadata !{
+  i32 524305,    ;; Tag
+  i32 0,         ;; Unused
+  i32 4,         ;; Language Id
+  metadata !"MySource.cpp", 
+  metadata !"/Users/mine/sources", 
+  metadata !"4.2.1 (Based on Apple Inc. build 5649) (LLVM build 00)", 
+  i1 true,       ;; Main Compile Unit
+  i1 false,      ;; Optimized compile unit
+  metadata !"",  ;; Compiler flags
+  i32 0}         ;; Runtime version
+
+;;
+;; Define the file for the file "/Users/mine/sources/MySource.cpp".
+;;
+!1 = metadata !{
+  i32 524329,    ;; Tag
+  metadata !"MySource.cpp", 
+  metadata !"/Users/mine/sources", 
+  metadata !2    ;; Compile unit
+}
+
+;;
+;; Define the file for the file "/Users/mine/sources/Myheader.h"
+;;
+!3 = metadata !{
+  i32 524329,    ;; Tag
+  metadata !"Myheader.h"
+  metadata !"/Users/mine/sources", 
+  metadata !2    ;; Compile unit
+}
+
+...
+
+
+ +

llvm::Instruction provides easy access to metadata attached with an +instruction. One can extract line number information encoded in LLVM IR +using Instruction::getMetadata() and +DILocation::getLineNumber(). +

+ if (MDNode *N = I->getMetadata("dbg")) {  // Here I is an LLVM instruction
+   DILocation Loc(N);                      // DILocation is in DebugInfo.h
+   unsigned Line = Loc.getLineNumber();
+   StringRef File = Loc.getFilename();
+   StringRef Dir = Loc.getDirectory();
+ }
+
+
+ + + + +
+ +

Given an integer global variable declared as follows:

+ +
+
+int MyGlobal = 100;
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+;;
+;; Define the global itself.
+;;
+%MyGlobal = global int 100
+...
+;;
+;; List of debug info of globals
+;;
+!llvm.dbg.gv = !{!0}
+
+;;
+;; Define the global variable descriptor.  Note the reference to the global
+;; variable anchor and the global variable itself.
+;;
+!0 = metadata !{
+  i32 524340,              ;; Tag
+  i32 0,                   ;; Unused
+  metadata !1,             ;; Context
+  metadata !"MyGlobal",    ;; Name
+  metadata !"MyGlobal",    ;; Display Name
+  metadata !"MyGlobal",    ;; Linkage Name
+  metadata !3,             ;; Compile Unit
+  i32 1,                   ;; Line Number
+  metadata !4,             ;; Type
+  i1 false,                ;; Is a local variable
+  i1 true,                 ;; Is this a definition
+  i32* @MyGlobal           ;; The global variable
+}
+
+;;
+;; Define the basic type of 32 bit signed integer.  Note that since int is an
+;; intrinsic type the source file is NULL and line 0.
+;;    
+!4 = metadata !{
+  i32 524324,              ;; Tag
+  metadata !1,             ;; Context
+  metadata !"int",         ;; Name
+  metadata !1,             ;; File
+  i32 0,                   ;; Line number
+  i64 32,                  ;; Size in Bits
+  i64 32,                  ;; Align in Bits
+  i64 0,                   ;; Offset in Bits
+  i32 0,                   ;; Flags
+  i32 5                    ;; Encoding
+}
+
+
+
+ +
+ + + + +
+ +

Given a function declared as follows:

+ +
+
+int main(int argc, char *argv[]) {
+  return 0;
+}
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+;;
+;; Define the anchor for subprograms.  Note that the second field of the
+;; anchor is 46, which is the same as the tag for subprograms
+;; (46 = DW_TAG_subprogram.)
+;;
+!6 = metadata !{
+  i32 524334,        ;; Tag
+  i32 0,             ;; Unused
+  metadata !1,       ;; Context
+  metadata !"main",  ;; Name
+  metadata !"main",  ;; Display name
+  metadata !"main",  ;; Linkage name
+  metadata !1,       ;; File
+  i32 1,             ;; Line number
+  metadata !4,       ;; Type
+  i1 false,          ;; Is local 
+  i1 true            ;; Is definition
+}
+;;
+;; Define the subprogram itself.
+;;
+define i32 @main(i32 %argc, i8** %argv) {
+...
+}
+
+
+ +
+ + + + +
+ +

The following are the basic type descriptors for C/C++ core types:

+ +
+ + +
+ bool +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"bool",  ;; Name
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 8,             ;; Size in Bits
+  i64 8,             ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 2              ;; Encoding
+}
+
+
+ +
+ + +
+ char +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"char",  ;; Name
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 8,             ;; Size in Bits
+  i64 8,             ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 6              ;; Encoding
+}
+
+
+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"unsigned char", 
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 8,             ;; Size in Bits
+  i64 8,             ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 8              ;; Encoding
+}
+
+
+ +
+ + +
+ short +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"short int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 16,            ;; Size in Bits
+  i64 16,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 5              ;; Encoding
+}
+
+
+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"short unsigned int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 16,            ;; Size in Bits
+  i64 16,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 7              ;; Encoding
+}
+
+
+ +
+ + +
+ int +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"int",   ;; Name
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 32,            ;; Size in Bits
+  i64 32,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 5              ;; Encoding
+}
+
+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"unsigned int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 32,            ;; Size in Bits
+  i64 32,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 7              ;; Encoding
+}
+
+
+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"long long int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 64,            ;; Size in Bits
+  i64 64,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 5              ;; Encoding
+}
+
+
+ +
+ + + + +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"long long unsigned int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 64,            ;; Size in Bits
+  i64 64,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 7              ;; Encoding
+}
+
+
+ +
+ + +
+ float +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"float",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 32,            ;; Size in Bits
+  i64 32,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 4              ;; Encoding
+}
+
+
+ +
+ + +
+ double +
+ +
+ +
+
+!2 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"double",;; Name
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 64,            ;; Size in Bits
+  i64 64,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 4              ;; Encoding
+}
+
+
+ +
+ + + + +
+ +

Given the following as an example of C/C++ derived type:

+ +
+
+typedef const int *IntPtr;
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+;;
+;; Define the typedef "IntPtr".
+;;
+!2 = metadata !{
+  i32 524310,          ;; Tag
+  metadata !1,         ;; Context
+  metadata !"IntPtr",  ;; Name
+  metadata !3,         ;; File
+  i32 0,               ;; Line number
+  i64 0,               ;; Size in bits
+  i64 0,               ;; Align in bits
+  i64 0,               ;; Offset in bits
+  i32 0,               ;; Flags
+  metadata !4          ;; Derived From type
+}
+
+;;
+;; Define the pointer type.
+;;
+!4 = metadata !{
+  i32 524303,          ;; Tag
+  metadata !1,         ;; Context
+  metadata !"",        ;; Name
+  metadata !1,         ;; File
+  i32 0,               ;; Line number
+  i64 64,              ;; Size in bits
+  i64 64,              ;; Align in bits
+  i64 0,               ;; Offset in bits
+  i32 0,               ;; Flags
+  metadata !5          ;; Derived From type
+}
+;;
+;; Define the const type.
+;;
+!5 = metadata !{
+  i32 524326,          ;; Tag
+  metadata !1,         ;; Context
+  metadata !"",        ;; Name
+  metadata !1,         ;; File
+  i32 0,               ;; Line number
+  i64 32,              ;; Size in bits
+  i64 32,              ;; Align in bits
+  i64 0,               ;; Offset in bits
+  i32 0,               ;; Flags
+  metadata !6          ;; Derived From type
+}
+;;
+;; Define the int type.
+;;
+!6 = metadata !{
+  i32 524324,          ;; Tag
+  metadata !1,         ;; Context
+  metadata !"int",     ;; Name
+  metadata !1,         ;; File
+  i32 0,               ;; Line number
+  i64 32,              ;; Size in bits
+  i64 32,              ;; Align in bits
+  i64 0,               ;; Offset in bits
+  i32 0,               ;; Flags
+  5                    ;; Encoding
+}
+
+
+ +
+ + + + +
+ +

Given the following as an example of C/C++ struct type:

+ +
+
+struct Color {
+  unsigned Red;
+  unsigned Green;
+  unsigned Blue;
+};
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+;;
+;; Define basic type for unsigned int.
+;;
+!5 = metadata !{
+  i32 524324,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"unsigned int",
+  metadata !1,       ;; File
+  i32 0,             ;; Line number
+  i64 32,            ;; Size in Bits
+  i64 32,            ;; Align in Bits
+  i64 0,             ;; Offset in Bits
+  i32 0,             ;; Flags
+  i32 7              ;; Encoding
+}
+;;
+;; Define composite type for struct Color.
+;;
+!2 = metadata !{
+  i32 524307,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"Color", ;; Name
+  metadata !1,       ;; Compile unit
+  i32 1,             ;; Line number
+  i64 96,            ;; Size in bits
+  i64 32,            ;; Align in bits
+  i64 0,             ;; Offset in bits
+  i32 0,             ;; Flags
+  null,              ;; Derived From
+  metadata !3,       ;; Elements
+  i32 0              ;; Runtime Language
+}
+
+;;
+;; Define the Red field.
+;;
+!4 = metadata !{
+  i32 524301,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"Red",   ;; Name
+  metadata !1,       ;; File
+  i32 2,             ;; Line number
+  i64 32,            ;; Size in bits
+  i64 32,            ;; Align in bits
+  i64 0,             ;; Offset in bits
+  i32 0,             ;; Flags
+  metadata !5        ;; Derived From type
+}
+
+;;
+;; Define the Green field.
+;;
+!6 = metadata !{
+  i32 524301,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"Green", ;; Name
+  metadata !1,       ;; File
+  i32 3,             ;; Line number
+  i64 32,            ;; Size in bits
+  i64 32,            ;; Align in bits
+  i64 32,             ;; Offset in bits
+  i32 0,             ;; Flags
+  metadata !5        ;; Derived From type
+}
+
+;;
+;; Define the Blue field.
+;;
+!7 = metadata !{
+  i32 524301,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"Blue",  ;; Name
+  metadata !1,       ;; File
+  i32 4,             ;; Line number
+  i64 32,            ;; Size in bits
+  i64 32,            ;; Align in bits
+  i64 64,             ;; Offset in bits
+  i32 0,             ;; Flags
+  metadata !5        ;; Derived From type
+}
+
+;;
+;; Define the array of fields used by the composite type Color.
+;;
+!3 = metadata !{metadata !4, metadata !6, metadata !7}
+
+
+ +
+ + + + +
+ +

Given the following as an example of C/C++ enumeration type:

+ +
+
+enum Trees {
+  Spruce = 100,
+  Oak = 200,
+  Maple = 300
+};
+
+
+ +

a C/C++ front-end would generate the following descriptors:

+ +
+
+;;
+;; Define composite type for enum Trees
+;;
+!2 = metadata !{
+  i32 524292,        ;; Tag
+  metadata !1,       ;; Context
+  metadata !"Trees", ;; Name
+  metadata !1,       ;; File
+  i32 1,             ;; Line number
+  i64 32,            ;; Size in bits
+  i64 32,            ;; Align in bits
+  i64 0,             ;; Offset in bits
+  i32 0,             ;; Flags
+  null,              ;; Derived From type
+  metadata !3,       ;; Elements
+  i32 0              ;; Runtime language
+}
+
+;;
+;; Define the array of enumerators used by composite type Trees.
+;;
+!3 = metadata !{metadata !4, metadata !5, metadata !6}
+
+;;
+;; Define Spruce enumerator.
+;;
+!4 = metadata !{i32 524328, metadata !"Spruce", i64 100}
+
+;;
+;; Define Oak enumerator.
+;;
+!5 = metadata !{i32 524328, metadata !"Oak", i64 200}
+
+;;
+;; Define Maple enumerator.
+;;
+!6 = metadata !{i32 524328, metadata !"Maple", i64 300}
+
+
+
+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/SystemLibrary.html b/final/docs/SystemLibrary.html new file mode 100644 index 00000000000..0289a554108 --- /dev/null +++ b/final/docs/SystemLibrary.html @@ -0,0 +1,319 @@ + + + + System Library + + + + +
System Library
+ + +
+

Written by Reid Spencer

+
+ + + + +
+

This document provides some details on LLVM's System Library, located in + the source at lib/System and include/llvm/System. The + library's purpose is to shield LLVM from the differences between operating + systems for the few services LLVM needs from the operating system. Much of + LLVM is written using portability features of standard C++. However, in a few + areas, system dependent facilities are needed and the System Library is the + wrapper around those system calls.

+

By centralizing LLVM's use of operating system interfaces, we make it + possible for the LLVM tool chain and runtime libraries to be more easily + ported to new platforms since (theoretically) only lib/System needs + to be ported. This library also unclutters the rest of LLVM from #ifdef use + and special cases for specific operating systems. Such uses are replaced + with simple calls to the interfaces provided in include/llvm/System. +

+

Note that the System Library is not intended to be a complete operating + system wrapper (such as the Adaptive Communications Environment (ACE) or + Apache Portable Runtime (APR)), but only provides the functionality necessary + to support LLVM. +

The System Library was written by Reid Spencer who formulated the + design based on similar work originating from the eXtensible Programming + System (XPS). Several people helped with the effort; especially, + Jeff Cohen and Henrik Bach on the Win32 port.

+
+ + + +
+

In order to keep LLVM portable, LLVM developers should adhere to a set of + portability rules associated with the System Library. Adherence to these rules + should help the System Library achieve its goal of shielding LLVM from the + variations in operating system interfaces and doing so efficiently. The + following sections define the rules needed to fulfill this objective.

+
+ + + +
+

Except in lib/System, no LLVM source code should directly + #include a system header. Care has been taken to remove all such + #includes from LLVM while lib/System was being + developed. Specifically this means that header files like "unistd.h", + "windows.h", "stdio.h", and "string.h" are forbidden to be included by LLVM + source code outside the implementation of lib/System.

+

To obtain system-dependent functionality, existing interfaces to the system + found in include/llvm/System should be used. If an appropriate + interface is not available, it should be added to include/llvm/System + and implemented in lib/System for all supported platforms.

+
+ + + +
+

The System Library must shield LLVM from all system headers. To + obtain system level functionality, LLVM source must + #include "llvm/System/Thing.h" and nothing else. This means that + Thing.h cannot expose any system header files. This protects LLVM + from accidentally using system specific functionality and only allows it + via the lib/System interface.

+
+ + + +
+

The standard C headers (the ones beginning with "c") are allowed + to be exposed through the lib/System interface. These headers and + the things they declare are considered to be platform agnostic. LLVM source + files may include them directly or obtain their inclusion through + lib/System interfaces.

+
+ + + +
+

The standard C++ headers from the standard C++ library and + standard template library may be exposed through the lib/System + interface. These headers and the things they declare are considered to be + platform agnostic. LLVM source files may include them or obtain their + inclusion through lib/System interfaces.

+
+ + + +
+

The entry points specified in the interface of lib/System must be aimed at + completing some reasonably high level task needed by LLVM. We do not want to + simply wrap each operating system call. It would be preferable to wrap several + operating system calls that are always used in conjunction with one another by + LLVM.

+

For example, consider what is needed to execute a program, wait for it to + complete, and return its result code. On Unix, this involves the following + operating system calls: getenv, fork, execve, and wait. The + correct thing for lib/System to provide is a function, say + ExecuteProgramAndWait, that implements the functionality completely. + what we don't want is wrappers for the operating system calls involved.

+

There must not be a one-to-one relationship between operating + system calls and the System library's interface. Any such interface function + will be suspicious.

+
+ + + +
+

There must be no functionality specified in the interface of lib/System + that isn't actually used by LLVM. We're not writing a general purpose + operating system wrapper here, just enough to satisfy LLVM's needs. And, LLVM + doesn't need much. This design goal aims to keep the lib/System interface + small and understandable which should foster its actual use and adoption.

+
+ + + +
+

The implementation of a function for a given platform must be written + exactly once. This implies that it must be possible to apply a function's + implementation to multiple operating systems if those operating systems can + share the same implementation. This rule applies to the set of operating + systems supported for a given class of operating system (e.g. Unix, Win32). +

+
+ + + +
+

The System Library interfaces can be called quite frequently by LLVM. In + order to make those calls as efficient as possible, we discourage the use of + virtual methods. There is no need to use inheritance for implementation + differences, it just adds complexity. The #include mechanism works + just fine.

+
+ + + +
+

Any functions defined by system libraries (i.e. not defined by lib/System) + must not be exposed through the lib/System interface, even if the header file + for that function is not exposed. This prevents inadvertent use of system + specific functionality.

+

For example, the stat system call is notorious for having + variations in the data it provides. lib/System must not declare + stat nor allow it to be declared. Instead it should provide its own + interface to discovering information about files and directories. Those + interfaces may be implemented in terms of stat but that is strictly + an implementation detail. The interface provided by the System Library must + be implemented on all platforms (even those without stat).

+
+ + + +
+

Any data defined by system libraries (i.e. not defined by lib/System) must + not be exposed through the lib/System interface, even if the header file for + that function is not exposed. As with functions, this prevents inadvertent use + of data that might not exist on all platforms.

+
+ + + +
+

Operating system interfaces will generally provide error results for every + little thing that could go wrong. In almost all cases, you can divide these + error results into two groups: normal/good/soft and abnormal/bad/hard. That + is, some of the errors are simply information like "file not found", + "insufficient privileges", etc. while other errors are much harder like + "out of space", "bad disk sector", or "system call interrupted". We'll call + the first group "soft" errors and the second group "hard" + errors.

+

lib/System must always attempt to minimize soft errors. + This is a design requirement because the + minimization of soft errors can affect the granularity and the nature of the + interface. In general, if you find that you're wanting to throw soft errors, + you must review the granularity of the interface because it is likely you're + trying to implement something that is too low level. The rule of thumb is to + provide interface functions that can't fail, except when faced with + hard errors.

+

For a trivial example, suppose we wanted to add an "OpenFileForWriting" + function. For many operating systems, if the file doesn't exist, attempting + to open the file will produce an error. However, lib/System should not + simply throw that error if it occurs because its a soft error. The problem + is that the interface function, OpenFileForWriting is too low level. It should + be OpenOrCreateFileForWriting. In the case of the soft "doesn't exist" error, + this function would just create it and then open it for writing.

+

This design principle needs to be maintained in lib/System because it + avoids the propagation of soft error handling throughout the rest of LLVM. + Hard errors will generally just cause a termination for an LLVM tool so don't + be bashful about throwing them.

+

Rules of thumb:

+
    +
  1. Don't throw soft errors, only hard errors.
  2. +
  3. If you're tempted to throw a soft error, re-think the interface.
  4. +
  5. Handle internally the most common normal/good/soft error conditions + so the rest of LLVM doesn't have to.
  6. +
+
+ + + +
+

None of the lib/System interface functions may be declared with C++ + throw() specifications on them. This requirement makes sure that the + compiler does not insert additional exception handling code into the interface + functions. This is a performance consideration: lib/System functions are at + the bottom of many call chains and as such can be frequently called. We + need them to be as efficient as possible. However, no routines in the + system library should actually throw exceptions.

+
+ + + +
+

Implementations of the System Library interface are separated by their + general class of operating system. Currently only Unix and Win32 classes are + defined but more could be added for other operating system classifications. + To distinguish which implementation to compile, the code in lib/System uses + the LLVM_ON_UNIX and LLVM_ON_WIN32 #defines provided via configure through the + llvm/Config/config.h file. Each source file in lib/System, after implementing + the generic (operating system independent) functionality needs to include the + correct implementation using a set of #if defined(LLVM_ON_XYZ) + directives. For example, if we had lib/System/File.cpp, we'd expect to see in + that file:

+

+  #if defined(LLVM_ON_UNIX)
+  #include "Unix/File.cpp"
+  #endif
+  #if defined(LLVM_ON_WIN32)
+  #include "Win32/File.cpp"
+  #endif
+  
+

The implementation in lib/System/Unix/File.cpp should handle all Unix + variants. The implementation in lib/System/Win32/File.cpp should handle all + Win32 variants. What this does is quickly differentiate the basic class of + operating system that will provide the implementation. The specific details + for a given platform must still be determined through the use of + #ifdef.

+
+ + + +
+

The implementation of a lib/System interface can vary drastically between + platforms. That's okay as long as the end result of the interface function + is the same. For example, a function to create a directory is pretty straight + forward on all operating system. System V IPC on the other hand isn't even + supported on all platforms. Instead of "supporting" System V IPC, lib/System + should provide an interface to the basic concept of inter-process + communications. The implementations might use System V IPC if that was + available or named pipes, or whatever gets the job done effectively for a + given operating system. In all cases, the interface and the implementation + must be semantically consistent.

+
+ + + +
+

See bug 351 + for further details on the progress of this work

+
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Reid Spencer
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/TableGenFundamentals.html b/final/docs/TableGenFundamentals.html new file mode 100644 index 00000000000..de46a391f36 --- /dev/null +++ b/final/docs/TableGenFundamentals.html @@ -0,0 +1,911 @@ + + + + TableGen Fundamentals + + + + +
TableGen Fundamentals
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

TableGen's purpose is to help a human develop and maintain records of +domain-specific information. Because there may be a large number of these +records, it is specifically designed to allow writing flexible descriptions and +for common features of these records to be factored out. This reduces the +amount of duplication in the description, reduces the chance of error, and +makes it easier to structure domain specific information.

+ +

The core part of TableGen parses a file, instantiates +the declarations, and hands the result off to a domain-specific "TableGen backend" for processing. The current major user +of TableGen is the LLVM code generator.

+ +

Note that if you work on TableGen much, and use emacs or vim, that you can +find an emacs "TableGen mode" and a vim language file in the +llvm/utils/emacs and llvm/utils/vim directories of your LLVM +distribution, respectively.

+ +
+ + + + +
+ +

TableGen files consist of two key parts: 'classes' and 'definitions', both +of which are considered 'records'.

+ +

TableGen records have a unique name, a list of values, and a list of +superclasses. The list of values is the main data that TableGen builds for each +record; it is this that holds the domain specific information for the +application. The interpretation of this data is left to a specific TableGen backend, but the structure and format rules are +taken care of and are fixed by TableGen.

+ +

TableGen definitions are the concrete form of 'records'. These +generally do not have any undefined values, and are marked with the +'def' keyword.

+ +

TableGen classes are abstract records that are used to build and +describe other records. These 'classes' allow the end-user to build +abstractions for either the domain they are targeting (such as "Register", +"RegisterClass", and "Instruction" in the LLVM code generator) or for the +implementor to help factor out common properties of records (such as "FPInst", +which is used to represent floating point instructions in the X86 backend). +TableGen keeps track of all of the classes that are used to build up a +definition, so the backend can find all definitions of a particular class, such +as "Instruction".

+ +

TableGen multiclasses are groups of abstract records that are +instantiated all at once. Each instantiation can result in multiple +TableGen definitions. If a multiclass inherits from another multiclass, +the definitions in the sub-multiclass become part of the current +multiclass, as if they were declared in the current multiclass.

+ +
+ + + + +
+ +

With no other arguments, TableGen parses the specified file and prints out +all of the classes, then all of the definitions. This is a good way to see what +the various definitions expand to fully. Running this on the X86.td +file prints this (at the time of this writing):

+ +
+
+...
+def ADD32rr {   // Instruction X86Inst I
+  string Namespace = "X86";
+  dag OutOperandList = (outs GR32:$dst);
+  dag InOperandList = (ins GR32:$src1, GR32:$src2);
+  string AsmString = "add{l}\t{$src2, $dst|$dst, $src2}";
+  list<dag> Pattern = [(set GR32:$dst, (add GR32:$src1, GR32:$src2))];
+  list<Register> Uses = [];
+  list<Register> Defs = [EFLAGS];
+  list<Predicate> Predicates = [];
+  int CodeSize = 3;
+  int AddedComplexity = 0;
+  bit isReturn = 0;
+  bit isBranch = 0;
+  bit isIndirectBranch = 0;
+  bit isBarrier = 0;
+  bit isCall = 0;
+  bit canFoldAsLoad = 0;
+  bit mayLoad = 0;
+  bit mayStore = 0;
+  bit isImplicitDef = 0;
+  bit isConvertibleToThreeAddress = 1;
+  bit isCommutable = 1;
+  bit isTerminator = 0;
+  bit isReMaterializable = 0;
+  bit isPredicable = 0;
+  bit hasDelaySlot = 0;
+  bit usesCustomInserter = 0;
+  bit hasCtrlDep = 0;
+  bit isNotDuplicable = 0;
+  bit hasSideEffects = 0;
+  bit neverHasSideEffects = 0;
+  InstrItinClass Itinerary = NoItinerary;
+  string Constraints = "";
+  string DisableEncoding = "";
+  bits<8> Opcode = { 0, 0, 0, 0, 0, 0, 0, 1 };
+  Format Form = MRMDestReg;
+  bits<6> FormBits = { 0, 0, 0, 0, 1, 1 };
+  ImmType ImmT = NoImm;
+  bits<3> ImmTypeBits = { 0, 0, 0 };
+  bit hasOpSizePrefix = 0;
+  bit hasAdSizePrefix = 0;
+  bits<4> Prefix = { 0, 0, 0, 0 };
+  bit hasREX_WPrefix = 0;
+  FPFormat FPForm = ?;
+  bits<3> FPFormBits = { 0, 0, 0 };
+}
+...
+
+
+ +

This definition corresponds to a 32-bit register-register add instruction in +the X86. The string after the 'def' string indicates the name of the +record—"ADD32rr" in this case—and the comment at the end of +the line indicates the superclasses of the definition. The body of the record +contains all of the data that TableGen assembled for the record, indicating that +the instruction is part of the "X86" namespace, the pattern indicating how the +the instruction should be emitted into the assembly file, that it is a +two-address instruction, has a particular encoding, etc. The contents and +semantics of the information in the record is specific to the needs of the X86 +backend, and is only shown as an example.

+ +

As you can see, a lot of information is needed for every instruction +supported by the code generator, and specifying it all manually would be +unmaintainable, prone to bugs, and tiring to do in the first place. Because we +are using TableGen, all of the information was derived from the following +definition:

+ +
+
+let Defs = [EFLAGS],
+    isCommutable = 1,                  // X = ADD Y,Z --> X = ADD Z,Y
+    isConvertibleToThreeAddress = 1 in // Can transform into LEA.
+def ADD32rr  : I<0x01, MRMDestReg, (outs GR32:$dst),
+                                   (ins GR32:$src1, GR32:$src2),
+                 "add{l}\t{$src2, $dst|$dst, $src2}",
+                 [(set GR32:$dst, (add GR32:$src1, GR32:$src2))]>;
+
+
+ +

This definition makes use of the custom class I (extended from the +custom class X86Inst), which is defined in the X86-specific TableGen +file, to factor out the common features that instructions of its class share. A +key feature of TableGen is that it allows the end-user to define the +abstractions they prefer to use when describing their information.

+ +
+ + + + +
+ +

TableGen runs just like any other LLVM tool. The first (optional) argument +specifies the file to read. If a filename is not specified, tblgen +reads from standard input.

+ +

To be useful, one of the TableGen backends must be +used. These backends are selectable on the command line (type 'tblgen +-help' for a list). For example, to get a list of all of the definitions +that subclass a particular type (which can be useful for building up an enum +list of these records), use the -print-enums option:

+ +
+
+$ tblgen X86.td -print-enums -class=Register
+AH, AL, AX, BH, BL, BP, BPL, BX, CH, CL, CX, DH, DI, DIL, DL, DX, EAX, EBP, EBX,
+ECX, EDI, EDX, EFLAGS, EIP, ESI, ESP, FP0, FP1, FP2, FP3, FP4, FP5, FP6, IP,
+MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, R10, R10B, R10D, R10W, R11, R11B, R11D,
+R11W, R12, R12B, R12D, R12W, R13, R13B, R13D, R13W, R14, R14B, R14D, R14W, R15,
+R15B, R15D, R15W, R8, R8B, R8D, R8W, R9, R9B, R9D, R9W, RAX, RBP, RBX, RCX, RDI,
+RDX, RIP, RSI, RSP, SI, SIL, SP, SPL, ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7,
+XMM0, XMM1, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM2, XMM3, XMM4, XMM5,
+XMM6, XMM7, XMM8, XMM9,
+
+$ tblgen X86.td -print-enums -class=Instruction 
+ABS_F, ABS_Fp32, ABS_Fp64, ABS_Fp80, ADC32mi, ADC32mi8, ADC32mr, ADC32ri,
+ADC32ri8, ADC32rm, ADC32rr, ADC64mi32, ADC64mi8, ADC64mr, ADC64ri32, ADC64ri8,
+ADC64rm, ADC64rr, ADD16mi, ADD16mi8, ADD16mr, ADD16ri, ADD16ri8, ADD16rm,
+ADD16rr, ADD32mi, ADD32mi8, ADD32mr, ADD32ri, ADD32ri8, ADD32rm, ADD32rr,
+ADD64mi32, ADD64mi8, ADD64mr, ADD64ri32, ...
+
+
+ +

The default backend prints out all of the records, as described above.

+ +

If you plan to use TableGen, you will most likely have to write a backend that extracts the information specific to +what you need and formats it in the appropriate way.

+ +
+ + + + + + +
+ +

TableGen doesn't care about the meaning of data (that is up to the backend to +define), but it does care about syntax, and it enforces a simple type system. +This section describes the syntax and the constructs allowed in a TableGen file. +

+ +
+ + + + + + + +
+ +

TableGen supports BCPL style "//" comments, which run to the end of +the line, and it also supports nestable "/* */" comments.

+ +
+ + + + +
+ +

TableGen files are strongly typed, in a simple (but complete) type-system. +These types are used to perform automatic conversions, check for errors, and to +help interface designers constrain the input that they allow. Every value definition is required to have an associated type. +

+ +

TableGen supports a mixture of very low-level types (such as bit) +and very high-level types (such as dag). This flexibility is what +allows it to describe a wide range of information conveniently and compactly. +The TableGen types are:

+ +
+
bit
+
A 'bit' is a boolean value that can hold either 0 or 1.
+ +
int
+
The 'int' type represents a simple 32-bit integer value, such as 5.
+ +
string
+
The 'string' type represents an ordered sequence of characters of + arbitrary length.
+ +
bits<n>
+
A 'bits' type is an arbitrary, but fixed, size integer that is broken up + into individual bits. This type is useful because it can handle some bits + being defined while others are undefined.
+ +
list<ty>
+
This type represents a list whose elements are some other type. The + contained type is arbitrary: it can even be another list type.
+ +
Class type
+
Specifying a class name in a type context means that the defined value + must be a subclass of the specified class. This is useful in conjunction with + the list type, for example, to constrain the elements of the + list to a common base class (e.g., a list<Register> can + only contain definitions derived from the "Register" class).
+ +
dag
+
This type represents a nestable directed graph of elements.
+ +
code
+
This represents a big hunk of text. This is lexically distinct from + string values because it doesn't require escapeing double quotes and other + common characters that occur in code.
+
+ +

To date, these types have been sufficient for describing things that +TableGen has been used for, but it is straight-forward to extend this list if +needed.

+ +
+ + + + +
+ +

TableGen allows for a pretty reasonable number of different expression forms +when building up values. These forms allow the TableGen file to be written in a +natural syntax and flavor for the application. The current expression forms +supported include:

+ +
+
?
+
uninitialized field
+
0b1001011
+
binary integer value
+
07654321
+
octal integer value (indicated by a leading 0)
+
7
+
decimal integer value
+
0x7F
+
hexadecimal integer value
+
"foo"
+
string value
+
[{ ... }]
+
code fragment
+
[ X, Y, Z ]<type>
+
list value. <type> is the type of the list +element and is usually optional. In rare cases, +TableGen is unable to deduce the element type in +which case the user must specify it explicitly.
+
{ a, b, c }
+
initializer for a "bits<3>" value
+
value
+
value reference
+
value{17}
+
access to one bit of a value
+
value{15-17}
+
access to multiple bits of a value
+
DEF
+
reference to a record definition
+
CLASS<val list>
+
reference to a new anonymous definition of CLASS with the specified + template arguments.
+
X.Y
+
reference to the subfield of a value
+
list[4-7,17,2-3]
+
A slice of the 'list' list, including elements 4,5,6,7,17,2, and 3 from + it. Elements may be included multiple times.
+
(DEF a, b)
+
a dag value. The first element is required to be a record definition, the + remaining elements in the list may be arbitrary other values, including nested + `dag' values.
+
!strconcat(a, b)
+
A string value that is the result of concatenating the 'a' and 'b' + strings.
+
!cast<type>(a)
+
A symbol of type type obtained by looking up the string 'a' in +the symbol table. If the type of 'a' does not match type, TableGen +aborts with an error. !cast<string> is a special case in that the argument must +be an object defined by a 'def' construct.
+
!subst(a, b, c)
+
If 'a' and 'b' are of string type or are symbol references, substitute +'b' for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.
+
!foreach(a, b, c)
+
For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a +dummy variable that should be declared as a member variable of an instantiated +class. This operation is analogous to $(foreach) in GNU make.
+
!head(a)
+
The first element of list 'a.'
+
!tail(a)
+
The 2nd-N elements of list 'a.'
+
!empty(a)
+
An integer {0,1} indicating whether list 'a' is empty.
+
!if(a,b,c)
+
'b' if the result of 'int' or 'bit' operator 'a' is nonzero, + 'c' otherwise.
+
!eq(a,b)
+
'bit 1' if string a is equal to string b, 0 otherwise. This + only operates on string, int and bit objects. Use !cast<string> to + compare other types of objects.
+
+ +

Note that all of the values have rules specifying how they convert to values +for different types. These rules allow you to assign a value like "7" +to a "bits<4>" value, for example.

+ +
+ + + + +
+ +

As mentioned in the intro, classes and definitions +(collectively known as 'records') in TableGen are the main high-level unit of +information that TableGen collects. Records are defined with a def or +class keyword, the record name, and an optional list of "template arguments". If the record has superclasses, +they are specified as a comma separated list that starts with a colon character +(":"). If value definitions or let expressions are needed for the class, they are +enclosed in curly braces ("{}"); otherwise, the record ends with a +semicolon.

+ +

Here is a simple TableGen file:

+ +
+
+class C { bit V = 1; }
+def X : C;
+def Y : C {
+  string Greeting = "hello";
+}
+
+
+ +

This example defines two definitions, X and Y, both of +which derive from the C class. Because of this, they both get the +V bit value. The Y definition also gets the Greeting member +as well.

+ +

In general, classes are useful for collecting together the commonality +between a group of records and isolating it in a single place. Also, classes +permit the specification of default values for their subclasses, allowing the +subclasses to override them as they wish.

+ +
+ + + + +
+ +

Value definitions define named entries in records. A value must be defined +before it can be referred to as the operand for another value definition or +before the value is reset with a let expression. A +value is defined by specifying a TableGen type and a name. +If an initial value is available, it may be specified after the type with an +equal sign. Value definitions require terminating semicolons.

+ +
+ + + + +
+ +

A record-level let expression is used to change the value of a value +definition in a record. This is primarily useful when a superclass defines a +value that a derived class or definition wants to override. Let expressions +consist of the 'let' keyword followed by a value name, an equal sign +("="), and a new value. For example, a new class could be added to the +example above, redefining the V field for all of its subclasses:

+ +
+
+class D : C { let V = 0; }
+def Z : D;
+
+
+ +

In this case, the Z definition will have a zero value for its "V" +value, despite the fact that it derives (indirectly) from the C class, +because the D class overrode its value.

+ +
+ + + + +
+ +

TableGen permits the definition of parameterized classes as well as normal +concrete classes. Parameterized TableGen classes specify a list of variable +bindings (which may optionally have defaults) that are bound when used. Here is +a simple example:

+ +
+
+class FPFormat<bits<3> val> {
+  bits<3> Value = val;
+}
+def NotFP      : FPFormat<0>;
+def ZeroArgFP  : FPFormat<1>;
+def OneArgFP   : FPFormat<2>;
+def OneArgFPRW : FPFormat<3>;
+def TwoArgFP   : FPFormat<4>;
+def CompareFP  : FPFormat<5>;
+def CondMovFP  : FPFormat<6>;
+def SpecialFP  : FPFormat<7>;
+
+
+ +

In this case, template arguments are used as a space efficient way to specify +a list of "enumeration values", each with a "Value" field set to the +specified integer.

+ +

The more esoteric forms of TableGen expressions are +useful in conjunction with template arguments. As an example:

+ +
+
+class ModRefVal<bits<2> val> {
+  bits<2> Value = val;
+}
+
+def None   : ModRefVal<0>;
+def Mod    : ModRefVal<1>;
+def Ref    : ModRefVal<2>;
+def ModRef : ModRefVal<3>;
+
+class Value<ModRefVal MR> {
+  // Decode some information into a more convenient format, while providing
+  // a nice interface to the user of the "Value" class.
+  bit isMod = MR.Value{0};
+  bit isRef = MR.Value{1};
+
+  // other stuff...
+}
+
+// Example uses
+def bork : Value<Mod>;
+def zork : Value<Ref>;
+def hork : Value<ModRef>;
+
+
+ +

This is obviously a contrived example, but it shows how template arguments +can be used to decouple the interface provided to the user of the class from the +actual internal data representation expected by the class. In this case, +running tblgen on the example prints the following definitions:

+ +
+
+def bork {      // Value
+  bit isMod = 1;
+  bit isRef = 0;
+}
+def hork {      // Value
+  bit isMod = 1;
+  bit isRef = 1;
+}
+def zork {      // Value
+  bit isMod = 0;
+  bit isRef = 1;
+}
+
+
+ +

This shows that TableGen was able to dig into the argument and extract a +piece of information that was requested by the designer of the "Value" class. +For more realistic examples, please see existing users of TableGen, such as the +X86 backend.

+ +
+ + + + +
+ +

+While classes with template arguments are a good way to factor commonality +between two instances of a definition, multiclasses allow a convenient notation +for defining multiple definitions at once (instances of implicitly constructed +classes). For example, consider an 3-address instruction set whose instructions +come in two forms: "reg = reg op reg" and "reg = reg op imm" +(e.g. SPARC). In this case, you'd like to specify in one place that this +commonality exists, then in a separate place indicate what all the ops are. +

+ +

+Here is an example TableGen fragment that shows this idea: +

+ +
+
+def ops;
+def GPR;
+def Imm;
+class inst<int opc, string asmstr, dag operandlist>;
+
+multiclass ri_inst<int opc, string asmstr> {
+  def _rr : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
+                 (ops GPR:$dst, GPR:$src1, GPR:$src2)>;
+  def _ri : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
+                 (ops GPR:$dst, GPR:$src1, Imm:$src2)>;
+}
+
+// Instantiations of the ri_inst multiclass.
+defm ADD : ri_inst<0b111, "add">;
+defm SUB : ri_inst<0b101, "sub">;
+defm MUL : ri_inst<0b100, "mul">;
+...
+
+
+ +

The name of the resultant definitions has the multidef fragment names + appended to them, so this defines ADD_rr, ADD_ri, + SUB_rr, etc. A defm may inherit from multiple multiclasses, + instantiating definitions from each multiclass. Using a multiclass + this way is exactly equivalent to instantiating the classes multiple + times yourself, e.g. by writing:

+ +
+
+def ops;
+def GPR;
+def Imm;
+class inst<int opc, string asmstr, dag operandlist>;
+
+class rrinst<int opc, string asmstr>
+  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
+         (ops GPR:$dst, GPR:$src1, GPR:$src2)>;
+
+class riinst<int opc, string asmstr>
+  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
+         (ops GPR:$dst, GPR:$src1, Imm:$src2)>;
+
+// Instantiations of the ri_inst multiclass.
+def ADD_rr : rrinst<0b111, "add">;
+def ADD_ri : riinst<0b111, "add">;
+def SUB_rr : rrinst<0b101, "sub">;
+def SUB_ri : riinst<0b101, "sub">;
+def MUL_rr : rrinst<0b100, "mul">;
+def MUL_ri : riinst<0b100, "mul">;
+...
+
+
+ +

+A defm can also be used inside a multiclass providing several levels of +multiclass instanciations. +

+ +
+
+class Instruction<bits<4> opc, string Name> {
+  bits<4> opcode = opc;
+  string name = Name;
+}
+
+multiclass basic_r<bits<4> opc> {
+  def rr : Instruction<opc, "rr">;
+  def rm : Instruction<opc, "rm">;
+}
+
+multiclass basic_s<bits<4> opc> {
+  defm SS : basic_r<opc>;
+  defm SD : basic_r<opc>;
+  def X : Instruction<opc, "x">;
+}
+
+multiclass basic_p<bits<4> opc> {
+  defm PS : basic_r<opc>;
+  defm PD : basic_r<opc>;
+  def Y : Instruction<opc, "y">;
+}
+
+defm ADD : basic_s<0xf>, basic_p<0xf>;
+...
+
+// Results
+def ADDPDrm { ...
+def ADDPDrr { ...
+def ADDPSrm { ...
+def ADDPSrr { ...
+def ADDSDrm { ...
+def ADDSDrr { ...
+def ADDY { ...
+def ADDX { ...
+
+
+ +

+defm declarations can inherit from classes too, the +rule to follow is that the class list must start after the +last multiclass, and there must be at least one multiclass +before them. +

+ +
+
+class XD { bits<4> Prefix = 11; }
+class XS { bits<4> Prefix = 12; }
+
+class I<bits<4> op> {
+  bits<4> opcode = op;
+}
+
+multiclass R {
+  def rr : I<4>;
+  def rm : I<2>;
+}
+
+multiclass Y {
+  defm SS : R, XD;
+  defm SD : R, XS;
+}
+
+defm Instr : Y;
+
+// Results
+def InstrSDrm {
+  bits<4> opcode = { 0, 0, 1, 0 };
+  bits<4> Prefix = { 1, 1, 0, 0 };
+}
+...
+def InstrSSrr {
+  bits<4> opcode = { 0, 1, 0, 0 };
+  bits<4> Prefix = { 1, 0, 1, 1 };
+}
+
+
+ +
+ + + + + + + +
+

TableGen supports the 'include' token, which textually substitutes +the specified file in place of the include directive. The filename should be +specified as a double quoted string immediately after the 'include' +keyword. Example:

+ +
+
+include "foo.td"
+
+
+ +
+ + + + +
+ +

"Let" expressions at file scope are similar to "let" +expressions within a record, except they can specify a value binding for +multiple records at a time, and may be useful in certain other cases. +File-scope let expressions are really just another way that TableGen allows the +end-user to factor out commonality from the records.

+ +

File-scope "let" expressions take a comma-separated list of bindings to +apply, and one or more records to bind the values in. Here are some +examples:

+ +
+
+let isTerminator = 1, isReturn = 1, isBarrier = 1, hasCtrlDep = 1 in
+  def RET : I<0xC3, RawFrm, (outs), (ins), "ret", [(X86retflag 0)]>;
+
+let isCall = 1 in
+  // All calls clobber the non-callee saved registers...
+  let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, ST0,
+              MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7,
+              XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, EFLAGS] in {
+    def CALLpcrel32 : Ii32<0xE8, RawFrm, (outs), (ins i32imm:$dst,variable_ops),
+                           "call\t${dst:call}", []>;
+    def CALL32r     : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops),
+                        "call\t{*}$dst", [(X86call GR32:$dst)]>;
+    def CALL32m     : I<0xFF, MRM2m, (outs), (ins i32mem:$dst, variable_ops),
+                        "call\t{*}$dst", []>;
+  }
+
+
+ +

File-scope "let" expressions are often useful when a couple of definitions +need to be added to several records, and the records do not otherwise need to be +opened, as in the case with the CALL* instructions above.

+ +

It's also possible to use "let" expressions inside multiclasses, providing +more ways to factor out commonality from the records, specially if using +several levels of multiclass instanciations. This also avoids the need of using +"let" expressions within subsequent records inside a multiclass.

+ +
+multiclass basic_r<bits<4> opc> {
+  let Predicates = [HasSSE2] in {
+    def rr : Instruction<opc, "rr">;
+    def rm : Instruction<opc, "rm">;
+  }
+  let Predicates = [HasSSE3] in
+    def rx : Instruction<opc, "rx">;
+}
+
+multiclass basic_ss<bits<4> opc> {
+  let IsDouble = 0 in
+    defm SS : basic_r<opc>;
+
+  let IsDouble = 1 in
+    defm SD : basic_r<opc>;
+}
+
+defm ADD : basic_ss<0xf>;
+
+
+ + + + + +
+ +

Expressions used by code generator to describe instructions and isel +patterns:

+ +
+
(implicit a)
+
an implicitly defined physical register. This tells the dag instruction + selection emitter the input pattern's extra definitions matches implicit + physical register definitions.
+
+
+ + + + + +
+ +

TODO: How they work, how to write one. This section should not contain +details about any particular backend, except maybe -print-enums as an example. +This should highlight the APIs in TableGen/Record.h.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/TestingGuide.html b/final/docs/TestingGuide.html new file mode 100644 index 00000000000..b048b72485a --- /dev/null +++ b/final/docs/TestingGuide.html @@ -0,0 +1,1196 @@ + + + + LLVM Testing Infrastructure Guide + + + + +
+ LLVM Testing Infrastructure Guide +
+ +
    +
  1. Overview
  2. +
  3. Requirements
  4. +
  5. LLVM testing infrastructure organization + +
  6. +
  7. Quick start + +
  8. +
  9. Regression test structure + +
  10. +
  11. Test suite structure
  12. +
  13. Running the test suite + +
  14. +
+ +
+

Written by John T. Criswell, Daniel Dunbar, Reid Spencer, and Tanya Lattner

+
+ + + + + +
+ +

This document is the reference manual for the LLVM testing infrastructure. It +documents the structure of the LLVM testing infrastructure, the tools needed to +use it, and how to add and run tests.

+ +
+ + + + + +
+ +

In order to use the LLVM testing infrastructure, you will need all of the +software required to build LLVM, as well +as Python 2.4 or later.

+ +
+ + + + + +
+ +

The LLVM testing infrastructure contains two major categories of tests: +regression tests and whole programs. The regression tests are contained inside +the LLVM repository itself under llvm/test and are expected to always +pass -- they should be run before every commit. The whole programs tests are +referred to as the "LLVM test suite" and are in the test-suite module +in subversion. +

+ +
+ + + + + +
+ +

The regression tests are small pieces of code that test a specific feature of +LLVM or trigger a specific bug in LLVM. They are usually written in LLVM +assembly language, but can be written in other languages if the test targets a +particular language front end (and the appropriate --with-llvmgcc +options were used at configure time of the llvm module). These +tests are driven by the 'lit' testing tool, which is part of LLVM.

+ +

These code fragments are not complete programs. The code generated +from them is never executed to determine correct behavior.

+ +

These code fragment tests are located in the llvm/test +directory.

+ +

Typically when a bug is found in LLVM, a regression test containing +just enough code to reproduce the problem should be written and placed +somewhere underneath this directory. In most cases, this will be a small +piece of LLVM assembly language code, often distilled from an actual +application or benchmark.

+ +
+ + + + + +
+ +

The test suite contains whole programs, which are pieces of +code which can be compiled and linked into a stand-alone program that can be +executed. These programs are generally written in high level languages such as +C or C++, but sometimes they are written straight in LLVM assembly.

+ +

These programs are compiled and then executed using several different +methods (native compiler, LLVM C backend, LLVM JIT, LLVM native code generation, +etc). The output of these programs is compared to ensure that LLVM is compiling +the program correctly.

+ +

In addition to compiling and executing programs, whole program tests serve as +a way of benchmarking LLVM performance, both in terms of the efficiency of the +programs generated as well as the speed with which LLVM compiles, optimizes, and +generates code.

+ +

The test-suite is located in the test-suite Subversion module.

+ +
+ + + + + +
+ +

The test suite contains tests to check quality of debugging information. +The test are written in C based languages or in LLVM assembly language.

+ +

These tests are compiled and run under a debugger. The debugger output +is checked to validate of debugging information. See README.txt in the +test suite for more information . This test suite is located in the +debuginfo-tests Subversion module.

+ +
+ + + + + +
+ +

The tests are located in two separate Subversion modules. The regressions + tests are in the main "llvm" module under the directory + llvm/test (so you get these tests for free with the main llvm tree). + The more comprehensive test suite that includes whole +programs in C and C++ is in the test-suite module. This module should +be checked out to the llvm/projects directory (don't use another name +than the default "test-suite", for then the test suite will be run every time +you run make in the main llvm directory). +When you configure the llvm module, +the test-suite directory will be automatically configured. +Alternatively, you can configure the test-suite module manually.

+ + + + +

To run all of the LLVM regression tests, use master Makefile in + the llvm/test directory:

+ +
+
+% gmake -C llvm/test
+
+
+ +

or

+ +
+
+% gmake check
+
+
+ +

If you have Clang checked out and built, +you can run the LLVM and Clang tests simultaneously using:

+ +

or

+ +
+
+% gmake check-all
+
+
+ +

To run the tests with Valgrind (Memcheck by default), just append +VG=1 to the commands above, e.g.:

+ +
+
+% gmake check VG=1
+
+
+ +

To run individual tests or subsets of tests, you can use the 'llvm-lit' +script which is built as part of LLVM. For example, to run the +'Integer/BitCast.ll' test by itself you can run:

+ +
+
+% llvm-lit ~/llvm/test/Integer/BitCast.ll 
+
+
+ +

or to run all of the ARM CodeGen tests:

+ +
+
+% llvm-lit ~/llvm/test/CodeGen/ARM
+
+
+ +

For more information on using the 'lit' tool, see 'llvm-lit --help' or the +'lit' man page.

+ + + + + +

To run the comprehensive test suite (tests that compile and execute whole +programs), first checkout and setup the test-suite module:

+ +
+
+% cd llvm/projects
+% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
+% cd ..
+% ./configure --with-llvmgccdir=$LLVM_GCC_DIR
+
+
+ +

where $LLVM_GCC_DIR is the directory where +you installed llvm-gcc, not its src or obj +dir. The --with-llvmgccdir option assumes that +the llvm-gcc-4.2 module was configured with +--program-prefix=llvm-, and therefore that the C and C++ +compiler drivers are called llvm-gcc and llvm-g++ +respectively. If this is not the case, +use --with-llvmgcc/--with-llvmgxx to specify each +executable's location.

+ +

Then, run the entire test suite by running make in the test-suite +directory:

+ +
+
+% cd projects/test-suite
+% gmake
+
+
+ +

Usually, running the "nightly" set of tests is a good idea, and you can also +let it generate a report by running:

+ +
+
+% cd projects/test-suite
+% gmake TEST=nightly report report.html
+
+
+ +

Any of the above commands can also be run in a subdirectory of +projects/test-suite to run the specified test only on the programs in +that subdirectory.

+ +
+ + + + + +

To run debugging information tests simply checkout the tests inside +clang/test directory.

+ +
+
+%cd clang/test
+% svn co http://llvm.org/svn/llvm-project/debuginfo-tests/trunk debuginfo-tests
+
+
+ +

These tests are already set up to run as part of clang regression tests.

+ + + + + + +
+

The LLVM regression tests are driven by 'lit' and are located in + the llvm/test directory. + +

This directory contains a large array of small tests + that exercise various features of LLVM and to ensure that regressions do not + occur. The directory is broken into several sub-directories, each focused on + a particular area of LLVM. A few of the important ones are:

+ +
    +
  • Analysis: checks Analysis passes.
  • +
  • Archive: checks the Archive library.
  • +
  • Assembler: checks Assembly reader/writer functionality.
  • +
  • Bitcode: checks Bitcode reader/writer functionality.
  • +
  • CodeGen: checks code generation and each target.
  • +
  • Features: checks various features of the LLVM language.
  • +
  • Linker: tests bitcode linking.
  • +
  • Transforms: tests each of the scalar, IPO, and utility + transforms to ensure they make the right transformations.
  • +
  • Verifier: tests the IR verifier.
  • +
+ +
+ + + + +
+

The regression test structure is very simple, but does require some + information to be set. This information is gathered via configure and + is written to a file, lit.site.cfg + in llvm/test. The llvm/test Makefile does this work for + you.

+ +

In order for the regression tests to work, each directory of tests must + have a dg.exp file. Lit looks for this file to determine how to + run the tests. This file is just a Tcl script and it can do anything you want, + but we've standardized it for the LLVM regression tests. If you're adding a + directory of tests, just copy dg.exp from another directory to get + running. The standard dg.exp simply loads a Tcl library + (test/lib/llvm.exp) and calls the llvm_runtests function + defined in that library with a list of file names to run. The names are + obtained by using Tcl's glob command. Any directory that contains only + directories does not need the dg.exp file.

+ +

The llvm-runtests function lookas at each file that is passed to + it and gathers any lines together that match "RUN:". This are the "RUN" lines + that specify how the test is to be run. So, each test script must contain + RUN lines if it is to do anything. If there are no RUN lines, the + llvm-runtests function will issue an error and the test will + fail.

+ +

RUN lines are specified in the comments of the test program using the + keyword RUN followed by a colon, and lastly the command (pipeline) + to execute. Together, these lines form the "script" that + llvm-runtests executes to run the test case. The syntax of the + RUN lines is similar to a shell's syntax for pipelines including I/O + redirection and variable substitution. However, even though these lines + may look like a shell script, they are not. RUN lines are interpreted + directly by the Tcl exec command. They are never executed by a + shell. Consequently the syntax differs from normal shell script syntax in a + few ways. You can specify as many RUN lines as needed.

+ +

lit performs substitution on each RUN line to replace LLVM tool + names with the full paths to the executable built for each tool (in + $(LLVM_OBJ_ROOT)/$(BuildMode)/bin). This ensures that lit does not + invoke any stray LLVM tools in the user's path during testing.

+ +

Each RUN line is executed on its own, distinct from other lines unless + its last character is \. This continuation character causes the RUN + line to be concatenated with the next one. In this way you can build up long + pipelines of commands without making huge line lengths. The lines ending in + \ are concatenated until a RUN line that doesn't end in \ is + found. This concatenated set of RUN lines then constitutes one execution. + Tcl will substitute variables and arrange for the pipeline to be executed. If + any process in the pipeline fails, the entire line (and test case) fails too. +

+ +

Below is an example of legal RUN lines in a .ll file:

+ +
+
+; RUN: llvm-as < %s | llvm-dis > %t1
+; RUN: llvm-dis < %s.bc-13 > %t2
+; RUN: diff %t1 %t2
+
+
+ +

As with a Unix shell, the RUN: lines permit pipelines and I/O redirection + to be used. However, the usage is slightly different than for Bash. To check + what's legal, see the documentation for the + Tcl exec + command and the + tutorial. + The major differences are:

+
    +
  • You can't do 2>&1. That will cause Tcl to write to a + file named &1. Usually this is done to get stderr to go through + a pipe. You can do that in tcl with |& so replace this idiom: + ... 2>&1 | grep with ... |& grep
  • +
  • You can only redirect to a file, not to another descriptor and not from + a here document.
  • +
  • tcl supports redirecting to open files with the @ syntax but you + shouldn't use that here.
  • +
+ +

There are some quoting rules that you must pay attention to when writing + your RUN lines. In general nothing needs to be quoted. Tcl won't strip off any + quote characters so they will get passed to the invoked program. For + example:

+ +
+
+... | grep 'find this string'
+
+
+ +

This will fail because the ' characters are passed to grep. This would + instruction grep to look for 'find in the files this and + string'. To avoid this use curly braces to tell Tcl that it should + treat everything enclosed as one value. So our example would become:

+ +
+
+... | grep {find this string}
+
+
+ +

Additionally, the characters [ and ] are treated + specially by Tcl. They tell Tcl to interpret the content as a command to + execute. Since these characters are often used in regular expressions this can + have disastrous results and cause the entire test run in a directory to fail. + For example, a common idiom is to look for some basicblock number:

+ +
+
+... | grep bb[2-8]
+
+
+ +

This, however, will cause Tcl to fail because its going to try to execute + a program named "2-8". Instead, what you want is this:

+ +
+
+... | grep {bb\[2-8\]}
+
+
+ +

Finally, if you need to pass the \ character down to a program, + then it must be doubled. This is another Tcl special character. So, suppose + you had: + +

+
+... | grep 'i32\*'
+
+
+ +

This will fail to match what you want (a pointer to i32). First, the + ' do not get stripped off. Second, the \ gets stripped off + by Tcl so what grep sees is: 'i32*'. That's not likely to match + anything. To resolve this you must use \\ and the {}, like + this:

+ +
+
+... | grep {i32\\*}
+
+
+ +

If your system includes GNU grep, make sure +that GREP_OPTIONS is not set in your environment. Otherwise, +you may get invalid results (both false positives and false +negatives).

+ +
+ + + + + +
+ +

A powerful feature of the RUN: lines is that it allows any arbitrary commands + to be executed as part of the test harness. While standard (portable) unix + tools like 'grep' work fine on run lines, as you see above, there are a lot + of caveats due to interaction with Tcl syntax, and we want to make sure the + run lines are portable to a wide range of systems. Another major problem is + that grep is not very good at checking to verify that the output of a tools + contains a series of different output in a specific order. The FileCheck + tool was designed to help with these problems.

+ +

FileCheck (whose basic command line arguments are described in the FileCheck man page is + designed to read a file to check from standard input, and the set of things + to verify from a file specified as a command line argument. A simple example + of using FileCheck from a RUN line looks like this:

+ +
+
+; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s
+
+
+ +

This syntax says to pipe the current file ("%s") into llvm-as, pipe that into +llc, then pipe the output of llc into FileCheck. This means that FileCheck will +be verifying its standard input (the llc output) against the filename argument +specified (the original .ll file specified by "%s"). To see how this works, +lets look at the rest of the .ll file (after the RUN line):

+ +
+
+define void @sub1(i32* %p, i32 %v) {
+entry:
+; CHECK: sub1:
+; CHECK: subl
+        %0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
+        ret void
+}
+
+define void @inc4(i64* %p) {
+entry:
+; CHECK: inc4:
+; CHECK: incq
+        %0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
+        ret void
+}
+
+
+ +

Here you can see some "CHECK:" lines specified in comments. Now you can see +how the file is piped into llvm-as, then llc, and the machine code output is +what we are verifying. FileCheck checks the machine code output to verify that +it matches what the "CHECK:" lines specify.

+ +

The syntax of the CHECK: lines is very simple: they are fixed strings that +must occur in order. FileCheck defaults to ignoring horizontal whitespace +differences (e.g. a space is allowed to match a tab) but otherwise, the contents +of the CHECK: line is required to match some thing in the test file exactly.

+ +

One nice thing about FileCheck (compared to grep) is that it allows merging +test cases together into logical groups. For example, because the test above +is checking for the "sub1:" and "inc4:" labels, it will not match unless there +is a "subl" in between those labels. If it existed somewhere else in the file, +that would not count: "grep subl" matches if subl exists anywhere in the +file.

+ +
+ + + + +
+ +

The FileCheck -check-prefix option allows multiple test configurations to be +driven from one .ll file. This is useful in many circumstances, for example, +testing different architectural variants with llc. Here's a simple example:

+ +
+
+; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
+; RUN:              | FileCheck %s -check-prefix=X32
+; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \
+; RUN:              | FileCheck %s -check-prefix=X64
+
+define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
+        %tmp1 = insertelement <4 x i32> %tmp, i32 %s, i32 1
+        ret <4 x i32> %tmp1
+; X32: pinsrd_1:
+; X32:    pinsrd $1, 4(%esp), %xmm0
+
+; X64: pinsrd_1:
+; X64:    pinsrd $1, %edi, %xmm0
+}
+
+
+ +

In this case, we're testing that we get the expected code generation with +both 32-bit and 64-bit code generation.

+ +
+ + + + +
+ +

Sometimes you want to match lines and would like to verify that matches +happen on exactly consecutive lines with no other lines in between them. In +this case, you can use CHECK: and CHECK-NEXT: directives to specify this. If +you specified a custom check prefix, just use "<PREFIX>-NEXT:". For +example, something like this works as you'd expect:

+ +
+
+define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) {
+	%tmp3 = load <2 x double>* %A, align 16
+	%tmp7 = insertelement <2 x double> undef, double %B, i32 0
+	%tmp9 = shufflevector <2 x double> %tmp3,
+                              <2 x double> %tmp7,
+                              <2 x i32> < i32 0, i32 2 >
+	store <2 x double> %tmp9, <2 x double>* %r, align 16
+	ret void
+        
+; CHECK: t2:
+; CHECK: 	movl	8(%esp), %eax
+; CHECK-NEXT: 	movapd	(%eax), %xmm0
+; CHECK-NEXT: 	movhpd	12(%esp), %xmm0
+; CHECK-NEXT: 	movl	4(%esp), %eax
+; CHECK-NEXT: 	movapd	%xmm0, (%eax)
+; CHECK-NEXT: 	ret
+}
+
+
+ +

CHECK-NEXT: directives reject the input unless there is exactly one newline +between it an the previous directive. A CHECK-NEXT cannot be the first +directive in a file.

+ +
+ + + + +
+ +

The CHECK-NOT: directive is used to verify that a string doesn't occur +between two matches (or the first match and the beginning of the file). For +example, to verify that a load is removed by a transformation, a test like this +can be used:

+ +
+
+define i8 @coerce_offset0(i32 %V, i32* %P) {
+  store i32 %V, i32* %P
+   
+  %P2 = bitcast i32* %P to i8*
+  %P3 = getelementptr i8* %P2, i32 2
+
+  %A = load i8* %P3
+  ret i8 %A
+; CHECK: @coerce_offset0
+; CHECK-NOT: load
+; CHECK: ret i8
+}
+
+
+ +
+ + + + +
+ +

The CHECK: and CHECK-NOT: directives both take a pattern to match. For most +uses of FileCheck, fixed string matching is perfectly sufficient. For some +things, a more flexible form of matching is desired. To support this, FileCheck +allows you to specify regular expressions in matching strings, surrounded by +double braces: {{yourregex}}. Because we want to use fixed string +matching for a majority of what we do, FileCheck has been designed to support +mixing and matching fixed string matching with regular expressions. This allows +you to write things like this:

+ +
+
+; CHECK: movhpd	{{[0-9]+}}(%esp), {{%xmm[0-7]}}
+
+
+ +

In this case, any offset from the ESP register will be allowed, and any xmm +register will be allowed.

+ +

Because regular expressions are enclosed with double braces, they are +visually distinct, and you don't need to use escape characters within the double +braces like you would in C. In the rare case that you want to match double +braces explicitly from the input, you can use something ugly like +{{[{][{]}} as your pattern.

+ +
+ + + + +
+ +

It is often useful to match a pattern and then verify that it occurs again +later in the file. For codegen tests, this can be useful to allow any register, +but verify that that register is used consistently later. To do this, FileCheck +allows named variables to be defined and substituted into patterns. Here is a +simple example:

+ +
+
+; CHECK: test5:
+; CHECK:    notw	[[REGISTER:%[a-z]+]]
+; CHECK:    andw	{{.*}}[[REGISTER]]
+
+
+ +

The first check line matches a regex (%[a-z]+) and captures it into +the variables "REGISTER". The second line verifies that whatever is in REGISTER +occurs later in the file after an "andw". FileCheck variable references are +always contained in [[ ]] pairs, are named, and their names can be +formed with the regex "[a-zA-Z][a-zA-Z0-9]*". If a colon follows the +name, then it is a definition of the variable, if not, it is a use.

+ +

FileCheck variables can be defined multiple times, and uses always get the +latest value. Note that variables are all read at the start of a "CHECK" line +and are all defined at the end. This means that if you have something like +"CHECK: [[XYZ:.*]]x[[XYZ]]" that the check line will read the previous +value of the XYZ variable and define a new one after the match is performed. If +you need to do something like this you can probably take advantage of the fact +that FileCheck is not actually line-oriented when it matches, this allows you to +define two separate CHECK lines that match on the same line. +

+ +
+ + + + +
+

With a RUN line there are a number of substitutions that are permitted. In + general, any Tcl variable that is available in the substitute + function (in test/lib/llvm.exp) can be substituted into a RUN line. + To make a substitution just write the variable's name preceded by a $. + Additionally, for compatibility reasons with previous versions of the test + library, certain names can be accessed with an alternate syntax: a % prefix. + These alternates are deprecated and may go away in a future version. +

+

Here are the available variable names. The alternate syntax is listed in + parentheses.

+ +
+
$test (%s)
+
The full path to the test case's source. This is suitable for passing + on the command line as the input to an llvm tool.
+ +
$srcdir
+
The source directory from where the "make check" was run.
+ +
objdir
+
The object directory that corresponds to the $srcdir.
+ +
subdir
+
A partial path from the test directory that contains the + sub-directory that contains the test source being executed.
+ +
srcroot
+
The root directory of the LLVM src tree.
+ +
objroot
+
The root directory of the LLVM object tree. This could be the same + as the srcroot.
+ +
path
+
The path to the directory that contains the test case source. This is + for locating any supporting files that are not generated by the test, but + used by the test.
+ +
tmp
+
The path to a temporary file name that could be used for this test case. + The file name won't conflict with other test cases. You can append to it if + you need multiple temporaries. This is useful as the destination of some + redirected output.
+ +
llvmlibsdir (%llvmlibsdir)
+
The directory where the LLVM libraries are located.
+ +
target_triplet (%target_triplet)
+
The target triplet that corresponds to the current host machine (the one + running the test cases). This should probably be called "host".
+ +
llvmgcc (%llvmgcc)
+
The full path to the llvm-gcc executable as specified in the + configured LLVM environment
+ +
llvmgxx (%llvmgxx)
+
The full path to the llvm-gxx executable as specified in the + configured LLVM environment
+ +
gccpath
+
The full path to the C compiler used to build LLVM. Note that + this might not be gcc.
+ +
gxxpath
+
The full path to the C++ compiler used to build LLVM. Note that + this might not be g++.
+ +
compile_c (%compile_c)
+
The full command line used to compile LLVM C source code. This has all + the configured -I, -D and optimization options.
+ +
compile_cxx (%compile_cxx)
+
The full command used to compile LLVM C++ source code. This has + all the configured -I, -D and optimization options.
+ +
link (%link)
+
This full link command used to link LLVM executables. This has all the + configured -I, -L and -l options.
+ +
shlibext (%shlibext)
+
The suffix for the host platforms share library (dll) files. This + includes the period as the first character.
+
+

To add more variables, two things need to be changed. First, add a line in + the test/Makefile that creates the site.exp file. This will + "set" the variable as a global in the site.exp file. Second, in the + test/lib/llvm.exp file, in the substitute proc, add the variable name + to the list of "global" declarations at the beginning of the proc. That's it, + the variable can then be used in test scripts.

+
+ + + + +
+

To make RUN line writing easier, there are several shell scripts located + in the llvm/test/Scripts directory. This directory is in the PATH + when running tests, so you can just call these scripts using their name. For + example:

+
+
ignore
+
This script runs its arguments and then always returns 0. This is useful + in cases where the test needs to cause a tool to generate an error (e.g. to + check the error output). However, any program in a pipeline that returns a + non-zero result will cause the test to fail. This script overcomes that + issue and nicely documents that the test case is purposefully ignoring the + result code of the tool
+ +
not
+
This script runs its arguments and then inverts the result code from + it. Zero result codes become 1. Non-zero result codes become 0. This is + useful to invert the result of a grep. For example "not grep X" means + succeed only if you don't find X in the input.
+
+ +

Sometimes it is necessary to mark a test case as "expected fail" or XFAIL. + You can easily mark a test as XFAIL just by including XFAIL: on a + line near the top of the file. This signals that the test case should succeed + if the test fails. Such test cases are counted separately by the testing tool. To + specify an expected fail, use the XFAIL keyword in the comments of the test + program followed by a colon and one or more regular expressions (separated by + a comma). The regular expressions allow you to XFAIL the test conditionally by + host platform. The regular expressions following the : are matched against the + target triplet for the host machine. If there is a match, the test is expected + to fail. If not, the test is expected to succeed. To XFAIL everywhere just + specify XFAIL: *. Here is an example of an XFAIL line:

+ +
+
+; XFAIL: darwin,sun
+
+
+ +

To make the output more useful, the llvm_runtest function wil + scan the lines of the test case for ones that contain a pattern that matches + PR[0-9]+. This is the syntax for specifying a PR (Problem Report) number that + is related to the test case. The number after "PR" specifies the LLVM bugzilla + number. When a PR number is specified, it will be used in the pass/fail + reporting. This is useful to quickly get some context when a test fails.

+ +

Finally, any line that contains "END." will cause the special + interpretation of lines to terminate. This is generally done right after the + last RUN: line. This has two side effects: (a) it prevents special + interpretation of lines that are part of the test program, not the + instructions to the test case, and (b) it speeds things up for really big test + cases by avoiding interpretation of the remainder of the file.

+ +
+ + + + + +
+ +

The test-suite module contains a number of programs that can be compiled +with LLVM and executed. These programs are compiled using the native compiler +and various LLVM backends. The output from the program compiled with the +native compiler is assumed correct; the results from the other programs are +compared to the native program output and pass if they match.

+ +

When executing tests, it is usually a good idea to start out with a subset of +the available tests or programs. This makes test run times smaller at first and +later on this is useful to investigate individual test failures. To run some +test only on a subset of programs, simply change directory to the programs you +want tested and run gmake there. Alternatively, you can run a different +test using the TEST variable to change what tests or run on the +selected programs (see below for more info).

+ +

In addition for testing correctness, the test-suite directory also +performs timing tests of various LLVM optimizations. It also records +compilation times for the compilers and the JIT. This information can be +used to compare the effectiveness of LLVM's optimizations and code +generation.

+ +

test-suite tests are divided into three types of tests: MultiSource, +SingleSource, and External.

+ +
    +
  • test-suite/SingleSource +

    The SingleSource directory contains test programs that are only a single +source file in size. These are usually small benchmark programs or small +programs that calculate a particular value. Several such programs are grouped +together in each directory.

  • + +
  • test-suite/MultiSource +

    The MultiSource directory contains subdirectories which contain entire +programs with multiple source files. Large benchmarks and whole applications +go here.

  • + +
  • test-suite/External +

    The External directory contains Makefiles for building code that is external +to (i.e., not distributed with) LLVM. The most prominent members of this +directory are the SPEC 95 and SPEC 2000 benchmark suites. The External +directory does not contain these actual tests, but only the Makefiles that know +how to properly compile these programs from somewhere else. The presence and +location of these external programs is configured by the test-suite +configure script.

  • +
+ +

Each tree is then subdivided into several categories, including applications, +benchmarks, regression tests, code that is strange grammatically, etc. These +organizations should be relatively self explanatory.

+ +

Some tests are known to fail. Some are bugs that we have not fixed yet; +others are features that we haven't added yet (or may never add). In the +regression tests, the result for such tests will be XFAIL (eXpected FAILure). +In this way, you can tell the difference between an expected and unexpected +failure.

+ +

The tests in the test suite have no such feature at this time. If the +test passes, only warnings and other miscellaneous output will be generated. If +a test fails, a large <program> FAILED message will be displayed. This +will help you separate benign warnings from actual test failures.

+ +
+ + + + + +
+ +

First, all tests are executed within the LLVM object directory tree. They +are not executed inside of the LLVM source tree. This is because the +test suite creates temporary files during execution.

+ +

To run the test suite, you need to use the following steps:

+ +
    +
  1. cd into the llvm/projects directory in your source tree. +
  2. + +
  3. Check out the test-suite module with:

    + +
    +
    +% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
    +
    +
    +

    This will get the test suite into llvm/projects/test-suite.

    +
  4. +
  5. Configure and build llvm.

  6. +
  7. Configure and build llvm-gcc.

  8. +
  9. Install llvm-gcc somewhere.

  10. +
  11. Re-configure llvm from the top level of + each build tree (LLVM object directory tree) in which you want + to run the test suite, just as you do before building LLVM.

    +

    During the re-configuration, you must either: (1) + have llvm-gcc you just built in your path, or (2) + specify the directory where your just-built llvm-gcc is + installed using --with-llvmgccdir=$LLVM_GCC_DIR.

    +

    You must also tell the configure machinery that the test suite + is available so it can be configured for your build tree:

    +
    +
    +% cd $LLVM_OBJ_ROOT ; $LLVM_SRC_ROOT/configure [--with-llvmgccdir=$LLVM_GCC_DIR]
    +
    +
    +

    [Remember that $LLVM_GCC_DIR is the directory where you + installed llvm-gcc, not its src or obj directory.]

    +
  12. + +
  13. You can now run the test suite from your build tree as follows:

    +
    +
    +% cd $LLVM_OBJ_ROOT/projects/test-suite
    +% make
    +
    +
    +
  14. +
+

Note that the second and third steps only need to be done once. After you +have the suite checked out and configured, you don't need to do it again (unless +the test code or configure script changes).

+ +
+ + + + + +
+

In order to run the External tests in the test-suite + module, you must specify --with-externals. This + must be done during the re-configuration step (see above), + and the llvm re-configuration must recognize the + previously-built llvm-gcc. If any of these is missing or + neglected, the External tests won't work.

+
+
--with-externals
+
--with-externals=<directory>
+
+ This tells LLVM where to find any external tests. They are expected to be + in specifically named subdirectories of <directory>. + If directory is left unspecified, + configure uses the default value + /home/vadve/shared/benchmarks/speccpu2000/benchspec. + Subdirectory names known to LLVM include: +
+
spec95
+
speccpu2000
+
speccpu2006
+
povray31
+
+ Others are added from time to time, and can be determined from + configure. +
+ + + + +
+

In addition to the regular "whole program" tests, the test-suite +module also provides a mechanism for compiling the programs in different ways. +If the variable TEST is defined on the gmake command line, the test system will +include a Makefile named TEST.<value of TEST variable>.Makefile. +This Makefile can modify build rules to yield different results.

+ +

For example, the LLVM nightly tester uses TEST.nightly.Makefile to +create the nightly test reports. To run the nightly tests, run gmake +TEST=nightly.

+ +

There are several TEST Makefiles available in the tree. Some of them are +designed for internal LLVM research and will not work outside of the LLVM +research group. They may still be valuable, however, as a guide to writing your +own TEST Makefile for any optimization or analysis passes that you develop with +LLVM.

+ +
+ + + + +
+

There are a number of ways to run the tests and generate output. The most + simple one is simply running gmake with no arguments. This will + compile and run all programs in the tree using a number of different methods + and compare results. Any failures are reported in the output, but are likely + drowned in the other output. Passes are not reported explicitely.

+ +

Somewhat better is running gmake TEST=sometest test, which runs + the specified test and usually adds per-program summaries to the output + (depending on which sometest you use). For example, the nightly test + explicitely outputs TEST-PASS or TEST-FAIL for every test after each program. + Though these lines are still drowned in the output, it's easy to grep the + output logs in the Output directories.

+ +

Even better are the report and report.format targets + (where format is one of html, csv, text or + graphs). The exact contents of the report are dependent on which + TEST you are running, but the text results are always shown at the + end of the run and the results are always stored in the + report.<type>.format file (when running with + TEST=<type>). + + The report also generate a file called + report.<type>.raw.out containing the output of the entire test + run. +

+ + + + + +
+ +

Assuming you can run the test suite, (e.g. "gmake TEST=nightly report" +should work), it is really easy to run optimizations or code generator +components against every program in the tree, collecting statistics or running +custom checks for correctness. At base, this is how the nightly tester works, +it's just one example of a general framework.

+ +

Lets say that you have an LLVM optimization pass, and you want to see how +many times it triggers. First thing you should do is add an LLVM +statistic to your pass, which +will tally counts of things you care about.

+ +

Following this, you can set up a test and a report that collects these and +formats them for easy viewing. This consists of two files, a +"test-suite/TEST.XXX.Makefile" fragment (where XXX is the name of your +test) and a "test-suite/TEST.XXX.report" file that indicates how to +format the output into a table. There are many example reports of various +levels of sophistication included with the test suite, and the framework is very +general.

+ +

If you are interested in testing an optimization pass, check out the +"libcalls" test as an example. It can be run like this:

+ +

+
+% cd llvm/projects/test-suite/MultiSource/Benchmarks  # or some other level
+% make TEST=libcalls report
+
+
+ +

This will do a bunch of stuff, then eventually print a table like this:

+ +
+
+Name                                  | total | #exit |
+...
+FreeBench/analyzer/analyzer           | 51    | 6     | 
+FreeBench/fourinarow/fourinarow       | 1     | 1     | 
+FreeBench/neural/neural               | 19    | 9     | 
+FreeBench/pifft/pifft                 | 5     | 3     | 
+MallocBench/cfrac/cfrac               | 1     | *     | 
+MallocBench/espresso/espresso         | 52    | 12    | 
+MallocBench/gs/gs                     | 4     | *     | 
+Prolangs-C/TimberWolfMC/timberwolfmc  | 302   | *     | 
+Prolangs-C/agrep/agrep                | 33    | 12    | 
+Prolangs-C/allroots/allroots          | *     | *     | 
+Prolangs-C/assembler/assembler        | 47    | *     | 
+Prolangs-C/bison/mybison              | 74    | *     | 
+...
+
+
+ +

This basically is grepping the -stats output and displaying it in a table. +You can also use the "TEST=libcalls report.html" target to get the table in HTML +form, similarly for report.csv and report.tex.

+ +

The source for this is in test-suite/TEST.libcalls.*. The format is pretty +simple: the Makefile indicates how to run the test (in this case, +"opt -simplify-libcalls -stats"), and the report contains one line for +each column of the output. The first value is the header for the column and the +second is the regex to grep the output of the command for. There are lots of +example reports that can do fancy stuff.

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + John T. Criswell, Daniel Dunbar, Reid Spencer, and Tanya Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/UsingLibraries.html b/final/docs/UsingLibraries.html new file mode 100644 index 00000000000..e06838b4cdb --- /dev/null +++ b/final/docs/UsingLibraries.html @@ -0,0 +1,443 @@ + + + + Using The LLVM Libraries + + + +
Using The LLVM Libraries
+
    +
  1. Abstract
  2. +
  3. Introduction
  4. +
  5. Library Descriptions
  6. +
  7. Library Dependencies
  8. +
  9. Linkage Rules Of Thumb +
      +
    1. Always link LLVMCore, LLVMSupport, LLVMSystem +
    2. Never link both archive and re-linked +
    +
  10. +
+ +
+

Written by Reid Spencer

+
+ +

Warning: This document is out of date, for more + information please + see llvm-config or, + if you use CMake, the CMake LLVM + guide.

+ + + +
+

Amongst other things, LLVM is a toolkit for building compilers, linkers, + runtime executives, virtual machines, and other program execution related + tools. In addition to the LLVM tool set, the functionality of LLVM is + available through a set of libraries. To use LLVM as a toolkit for + constructing tools, a developer needs to understand what is contained in the + various libraries, what they depend on, and how to use them. Fortunately, + there is a tool, llvm-config to aid with this. This document + describes the contents of the libraries and how to use llvm-config + to generate command line options. +

+
+ + + +
+

If you're writing a compiler, virtual machine, or any other utility based + on LLVM, you'll need to figure out which of the many libraries files you will + need to link with to be successful. An understanding of the contents of these + libraries will be useful in coming up with an optimal specification for the + libraries to link with. The purpose of this document is to reduce some of + the trial and error that the author experienced in using LLVM.

+

LLVM produces two types of libraries: archives (ending in .a) and + objects (ending in .o). However, both are libraries. Libraries ending + in .o are known as re-linked libraries because they contain all the + compilation units of the library linked together as a single .o file. + Furthermore, several of the libraries have both forms of library. The + re-linked libraries are used whenever you want to include all symbols from the + library. The archive libraries are used whenever you want to only resolve + outstanding symbols at that point in the link without including everything in + the library.

+

If you're using the LLVM Makefile system to link your tools,you will use + the LLVMLIBS make variable. + (see the Makefile Guide for + details). This variable specifies which LLVM libraries to link into your tool + and the order in which they will be linked. You specify re-linked libraries by + naming the library without a suffix. You specify archive libraries by naming + the library with a .a suffix but without the lib prefix. The + order in which the libraries appear in the LLVMLIBS variable + definition is the order in which they will be linked. Getting this order + correct for your tool can sometimes be challenging. +

+ +
Library Descriptions
+
+

The table below categorizes each library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LibraryFormsDescription
Core Libraries
LLVMArchive.aLLVM archive reading and writing
LLVMAsmParser.aLLVM assembly parsing
LLVMBCReader.aLLVM bitcode reading
LLVMBCWriter.aLLVM bitcode writing
LLVMCore.aLLVM core intermediate representation
LLVMDebugger.aSource level debugging support
LLVMLinker.aBitcode and archive linking interface
LLVMSupport.aGeneral support utilities
LLVMSystem.aOperating system abstraction layer
LLVMbzip2.aBZip2 compression library
Analysis Libraries
LLVMAnalysis.aVarious analysis passes.
LLVMDataStructure.oData structure analysis passes.
LLVMipa.aInter-procedural analysis passes.
Transformation Libraries
LLVMInstrumentation.aInstrumentation passes.
LLVMipo.aAll inter-procedural optimization passes.
LLVMScalarOpts.aAll scalar optimization passes.
LLVMTransformUtils.aTransformation utilities used by many passes.
Code Generation Libraries
LLVMCodeGen.oNative code generation infrastructure
LLVMSelectionDAG.oAggressive instruction selector for directed acyclic graphs
Target Libraries
LLVMAlpha.oCode generation for Alpha architecture
LLVMARM.oCode generation for ARM architecture
LLVMCBackend.o'C' language code generator.
LLVMPowerPC.oCode generation for PowerPC architecture
LLVMSparc.oCode generation for Sparc architecture
LLVMTarget.aGeneric code generation utilities.
LLVMX86.oCode generation for Intel x86 architecture
Runtime Libraries
LLVMInterpreter.oBitcode Interpreter
LLVMJIT.oBitcode JIT Compiler
LLVMExecutionEngine.oVirtual machine engine
+

+ + +
Using llvm-config
+
+

The llvm-config tool is a perl script that produces on its output + various kinds of information. For example, the source or object directories + used to build LLVM can be accessed by passing options to llvm-config. + For complete details on this tool, please see the + manual page.

+

To understand the relationships between libraries, the llvm-config + can be very useful. If all you know is that you want certain libraries to + be available, you can generate the complete set of libraries to link with + using one of four options, as below:

+
    +
  1. --ldflags. This generates the command line options necessary to + be passed to the ld tool in order to link with LLVM. Most notably, + the -L option is provided to specify a library search directory + that contains the LLVM libraries.
  2. +
  3. --libs. This generates command line options suitable for + use with a gcc-style linker. That is, libraries are given with a -l option + and object files are given with a full path.
  4. +
  5. --libnames. This generates a list of just the library file + names. If you know the directory in which these files reside (see --ldflags) + then you can find the libraries there.
  6. +
  7. --libfiles. This generates the full path names of the + LLVM library files.
  8. +
+

If you wish to delve further into how llvm-config generates the + correct order (based on library dependencies), please see the tool named + GenLibDeps.pl in the utils source directory of LLVM.

+ + + + + + + +

Dependency Relationships Of Libraries

+

This graph shows the dependency of archive libraries on other archive + libraries or objects. Where a library has both archive and object forms, only + the archive form is shown.

+ Library Dependencies +

Dependency Relationships Of Object Files

+

This graph shows the dependency of object files on archive libraries or + other objects. Where a library has both object and archive forms, only the + dependency to the archive form is shown.

+ Object File Dependencies +

The following list shows the dependency relationships between libraries in + textual form. The information is the same as shown on the graphs but arranged + alphabetically.

+
+
libLLVMAnalysis.a
    +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
libLLVMArchive.a
    +
  • libLLVMBCReader.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMAsmParser.a
    +
  • libLLVMCore.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMBCReader.a
    +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMBCWriter.a
    +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMCodeGen.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMScalarOpts.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMTransformUtils.a
  • +
+
libLLVMCore.a
    +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMDebugger.a
    +
  • libLLVMBCReader.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMInstrumentation.a
    +
  • libLLVMCore.a
  • +
  • libLLVMScalarOpts.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMTransformUtils.a
  • +
+
libLLVMLinker.a
    +
  • libLLVMArchive.a
  • +
  • libLLVMBCReader.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMScalarOpts.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMTransformUtils.a
  • +
+
libLLVMSelectionDAG.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMTransformUtils.a
  • +
+
libLLVMSupport.a
    +
  • libLLVMSystem.a
  • +
  • libLLVMbzip2.a
  • +
+
libLLVMSystem.a
    +
+
libLLVMTarget.a
    +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMTransformUtils.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMipa.a
  • +
+
libLLVMbzip2.a
    +
+
libLLVMipa.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
+
libLLVMipo.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMTransformUtils.a
  • +
  • libLLVMipa.a
  • +
+
libLLVMlto.a
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMBCReader.a
  • +
  • libLLVMBCWriter.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMLinker.a
  • +
  • libLLVMScalarOpts.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMipa.a
  • +
  • libLLVMipo.a
  • +
+
LLVMARM.o
    +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSelectionDAG.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMAlpha.o
    +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSelectionDAG.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMCBackend.o
    +
  • libLLVMAnalysis.a
  • +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMScalarOpts.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
  • libLLVMTransformUtils.a
  • +
  • libLLVMipa.a
  • +
+
LLVMExecutionEngine.o
    +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMInterpreter.o
    +
  • LLVMExecutionEngine.o
  • +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMJIT.o
    +
  • LLVMExecutionEngine.o
  • +
  • libLLVMCore.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMPowerPC.o
    +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSelectionDAG.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMSparc.o
    +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSelectionDAG.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
LLVMX86.o
    +
  • libLLVMCodeGen.a
  • +
  • libLLVMCore.a
  • +
  • libLLVMSelectionDAG.a
  • +
  • libLLVMSupport.a
  • +
  • libLLVMSystem.a
  • +
  • libLLVMTarget.a
  • +
+
+
+ + + +
+

This section contains various "rules of thumb" about what files you + should link into your programs.

+
+ + +
+

No matter what you do with LLVM, the last three entries in the value of + your LLVMLIBS make variable should always be: + LLVMCore LLVMSupport.a LLVMSystem.a. There are no LLVM + programs that don't depend on these three.

+
+ + +
+

There is never any point to linking both the re-linked (.o) and + the archive (.a) versions of a library. Since the re-linked version + includes the entire library, the archive version will not resolve any symbols. + You could even end up with link error if you place the archive version before + the re-linked version on the linker's command line.

+
+ +
+ + + + diff --git a/final/docs/WritingAnLLVMBackend.html b/final/docs/WritingAnLLVMBackend.html new file mode 100644 index 00000000000..729023240de --- /dev/null +++ b/final/docs/WritingAnLLVMBackend.html @@ -0,0 +1,2556 @@ + + + + + Writing an LLVM Compiler Backend + + + + + +
+ Writing an LLVM Compiler Backend +
+ +
    +
  1. Introduction + +
  2. Target Machine
  3. +
  4. Target Registration
  5. +
  6. Register Set and Register Classes +
  7. +
  8. Instruction Set +
  9. +
  10. Instruction Selector +
  11. +
  12. Assembly Printer
  13. +
  14. Subtarget Support
  15. +
  16. JIT Support +
  17. +
+ +
+

Written by Mason Woo and + Misha Brukman

+
+ + + + + +
+ +

+This document describes techniques for writing compiler backends that convert +the LLVM Intermediate Representation (IR) to code for a specified machine or +other languages. Code intended for a specific machine can take the form of +either assembly code or binary code (usable for a JIT compiler). +

+ +

+The backend of LLVM features a target-independent code generator that may create +output for several types of target CPUs — including X86, PowerPC, Alpha, +and SPARC. The backend may also be used to generate code targeted at SPUs of the +Cell processor or GPUs to support the execution of compute kernels. +

+ +

+The document focuses on existing examples found in subdirectories +of llvm/lib/Target in a downloaded LLVM release. In particular, this +document focuses on the example of creating a static compiler (one that emits +text assembly) for a SPARC target, because SPARC has fairly standard +characteristics, such as a RISC instruction set and straightforward calling +conventions. +

+ +
+ + + +
+ +

+The audience for this document is anyone who needs to write an LLVM backend to +generate code for a specific hardware or software target. +

+ +
+ + + +
+ +

+These essential documents must be read before reading this document: +

+ +
    +
  • LLVM Language Reference + Manual — a reference manual for the LLVM assembly language.
  • + +
  • The LLVM + Target-Independent Code Generator — a guide to the components + (classes and code generation algorithms) for translating the LLVM internal + representation into machine code for a specified target. Pay particular + attention to the descriptions of code generation stages: Instruction + Selection, Scheduling and Formation, SSA-based Optimization, Register + Allocation, Prolog/Epilog Code Insertion, Late Machine Code Optimizations, + and Code Emission.
  • + +
  • TableGen + Fundamentals —a document that describes the TableGen + (tblgen) application that manages domain-specific information to + support LLVM code generation. TableGen processes input from a target + description file (.td suffix) and generates C++ code that can be + used for code generation.
  • + +
  • Writing an LLVM + Pass — The assembly printer is a FunctionPass, as are + several SelectionDAG processing steps.
  • +
+ +

+To follow the SPARC examples in this document, have a copy of +The SPARC Architecture +Manual, Version 8 for reference. For details about the ARM instruction +set, refer to the ARM Architecture +Reference Manual. For more about the GNU Assembler format +(GAS), see +Using As, +especially for the assembly printer. Using As contains a list of target +machine dependent features. +

+ +
+ + + +
+ +

+To write a compiler backend for LLVM that converts the LLVM IR to code for a +specified target (machine or other language), follow these steps: +

+ +
    +
  • Create a subclass of the TargetMachine class that describes characteristics + of your target machine. Copy existing examples of specific TargetMachine + class and header files; for example, start with + SparcTargetMachine.cpp and SparcTargetMachine.h, but + change the file names for your target. Similarly, change code that + references "Sparc" to reference your target.
  • + +
  • Describe the register set of the target. Use TableGen to generate code for + register definition, register aliases, and register classes from a + target-specific RegisterInfo.td input file. You should also write + additional code for a subclass of the TargetRegisterInfo class that + represents the class register file data used for register allocation and + also describes the interactions between registers.
  • + +
  • Describe the instruction set of the target. Use TableGen to generate code + for target-specific instructions from target-specific versions of + TargetInstrFormats.td and TargetInstrInfo.td. You should + write additional code for a subclass of the TargetInstrInfo class to + represent machine instructions supported by the target machine.
  • + +
  • Describe the selection and conversion of the LLVM IR from a Directed Acyclic + Graph (DAG) representation of instructions to native target-specific + instructions. Use TableGen to generate code that matches patterns and + selects instructions based on additional information in a target-specific + version of TargetInstrInfo.td. Write code + for XXXISelDAGToDAG.cpp, where XXX identifies the specific target, + to perform pattern matching and DAG-to-DAG instruction selection. Also write + code in XXXISelLowering.cpp to replace or remove operations and + data types that are not supported natively in a SelectionDAG.
  • + +
  • Write code for an assembly printer that converts LLVM IR to a GAS format for + your target machine. You should add assembly strings to the instructions + defined in your target-specific version of TargetInstrInfo.td. You + should also write code for a subclass of AsmPrinter that performs the + LLVM-to-assembly conversion and a trivial subclass of TargetAsmInfo.
  • + +
  • Optionally, add support for subtargets (i.e., variants with different + capabilities). You should also write code for a subclass of the + TargetSubtarget class, which allows you to use the -mcpu= + and -mattr= command-line options.
  • + +
  • Optionally, add JIT support and create a machine code emitter (subclass of + TargetJITInfo) that is used to emit binary code directly into memory.
  • +
+ +

+In the .cpp and .h. files, initially stub up these methods and +then implement them later. Initially, you may not know which private members +that the class will need and which components will need to be subclassed. +

+ +
+ + + +
+ +

+To actually create your compiler backend, you need to create and modify a few +files. The absolute minimum is discussed here. But to actually use the LLVM +target-independent code generator, you must perform the steps described in +the LLVM +Target-Independent Code Generator document. +

+ +

+First, you should create a subdirectory under lib/Target to hold all +the files related to your target. If your target is called "Dummy," create the +directory lib/Target/Dummy. +

+ +

+In this new +directory, create a Makefile. It is easiest to copy a +Makefile of another target and modify it. It should at least contain +the LEVEL, LIBRARYNAME and TARGET variables, and then +include $(LEVEL)/Makefile.common. The library can be +named LLVMDummy (for example, see the MIPS target). Alternatively, you +can split the library into LLVMDummyCodeGen +and LLVMDummyAsmPrinter, the latter of which should be implemented in a +subdirectory below lib/Target/Dummy (for example, see the PowerPC +target). +

+ +

+Note that these two naming schemes are hardcoded into llvm-config. +Using any other naming scheme will confuse llvm-config and produce a +lot of (seemingly unrelated) linker errors when linking llc. +

+ +

+To make your target actually do something, you need to implement a subclass of +TargetMachine. This implementation should typically be in the file +lib/Target/DummyTargetMachine.cpp, but any file in +the lib/Target directory will be built and should work. To use LLVM's +target independent code generator, you should do what all current machine +backends do: create a subclass of LLVMTargetMachine. (To create a +target from scratch, create a subclass of TargetMachine.) +

+ +

+To get LLVM to actually build and link your target, you need to add it to +the TARGETS_TO_BUILD variable. To do this, you modify the configure +script to know about your target when parsing the --enable-targets +option. Search the configure script for TARGETS_TO_BUILD, add your +target to the lists there (some creativity required), and then +reconfigure. Alternatively, you can change autotools/configure.ac and +regenerate configure by running ./autoconf/AutoRegen.sh. +

+ +
+ + + + + +
+ +

+LLVMTargetMachine is designed as a base class for targets implemented +with the LLVM target-independent code generator. The LLVMTargetMachine +class should be specialized by a concrete target class that implements the +various virtual methods. LLVMTargetMachine is defined as a subclass of +TargetMachine in include/llvm/Target/TargetMachine.h. The +TargetMachine class implementation (TargetMachine.cpp) also +processes numerous command-line options. +

+ +

+To create a concrete target-specific subclass of LLVMTargetMachine, +start by copying an existing TargetMachine class and header. You +should name the files that you create to reflect your specific target. For +instance, for the SPARC target, name the files SparcTargetMachine.h and +SparcTargetMachine.cpp. +

+ +

+For a target machine XXX, the implementation of +XXXTargetMachine must have access methods to obtain objects that +represent target components. These methods are named get*Info, and are +intended to obtain the instruction set (getInstrInfo), register set +(getRegisterInfo), stack frame layout (getFrameInfo), and +similar information. XXXTargetMachine must also implement the +getTargetData method to access an object with target-specific data +characteristics, such as data type size and alignment requirements. +

+ +

+For instance, for the SPARC target, the header file +SparcTargetMachine.h declares prototypes for several get*Info +and getTargetData methods that simply return a class member. +

+ +
+
+namespace llvm {
+
+class Module;
+
+class SparcTargetMachine : public LLVMTargetMachine {
+  const TargetData DataLayout;       // Calculates type size & alignment
+  SparcSubtarget Subtarget;
+  SparcInstrInfo InstrInfo;
+  TargetFrameInfo FrameInfo;
+  
+protected:
+  virtual const TargetAsmInfo *createTargetAsmInfo() const;
+  
+public:
+  SparcTargetMachine(const Module &M, const std::string &FS);
+
+  virtual const SparcInstrInfo *getInstrInfo() const {return &InstrInfo; }
+  virtual const TargetFrameInfo *getFrameInfo() const {return &FrameInfo; }
+  virtual const TargetSubtarget *getSubtargetImpl() const{return &Subtarget; }
+  virtual const TargetRegisterInfo *getRegisterInfo() const {
+    return &InstrInfo.getRegisterInfo();
+  }
+  virtual const TargetData *getTargetData() const { return &DataLayout; }
+  static unsigned getModuleMatchQuality(const Module &M);
+
+  // Pass Pipeline Configuration
+  virtual bool addInstSelector(PassManagerBase &PM, bool Fast);
+  virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
+};
+
+} // end namespace llvm
+
+
+ +
+ + +
+ +
    +
  • getInstrInfo()
  • +
  • getRegisterInfo()
  • +
  • getFrameInfo()
  • +
  • getTargetData()
  • +
  • getSubtargetImpl()
  • +
+ +

For some targets, you also need to support the following methods:

+ +
    +
  • getTargetLowering()
  • +
  • getJITInfo()
  • +
+ +

+In addition, the XXXTargetMachine constructor should specify a +TargetDescription string that determines the data layout for the target +machine, including characteristics such as pointer size, alignment, and +endianness. For example, the constructor for SparcTargetMachine contains the +following: +

+ +
+
+SparcTargetMachine::SparcTargetMachine(const Module &M, const std::string &FS)
+  : DataLayout("E-p:32:32-f128:128:128"),
+    Subtarget(M, FS), InstrInfo(Subtarget),
+    FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0) {
+}
+
+
+ +
+ +
+ +

Hyphens separate portions of the TargetDescription string.

+ +
    +
  • An upper-case "E" in the string indicates a big-endian target data + model. a lower-case "e" indicates little-endian.
  • + +
  • "p:" is followed by pointer information: size, ABI alignment, and + preferred alignment. If only two figures follow "p:", then the + first value is pointer size, and the second value is both ABI and preferred + alignment.
  • + +
  • Then a letter for numeric type alignment: "i", "f", + "v", or "a" (corresponding to integer, floating point, + vector, or aggregate). "i", "v", or "a" are + followed by ABI alignment and preferred alignment. "f" is followed + by three values: the first indicates the size of a long double, then ABI + alignment, and then ABI preferred alignment.
  • +
+ +
+ + + + + +
+ +

+You must also register your target with the TargetRegistry, which is +what other LLVM tools use to be able to lookup and use your target at +runtime. The TargetRegistry can be used directly, but for most targets +there are helper templates which should take care of the work for you.

+ +

+All targets should declare a global Target object which is used to +represent the target during registration. Then, in the target's TargetInfo +library, the target should define that object and use +the RegisterTarget template to register the target. For example, the Sparc registration code looks like this: +

+ +
+
+Target llvm::TheSparcTarget;
+
+extern "C" void LLVMInitializeSparcTargetInfo() { 
+  RegisterTarget<Triple::sparc, /*HasJIT=*/false>
+    X(TheSparcTarget, "sparc", "Sparc");
+}
+
+
+ +

+This allows the TargetRegistry to look up the target by name or by +target triple. In addition, most targets will also register additional features +which are available in separate libraries. These registration steps are +separate, because some clients may wish to only link in some parts of the target +-- the JIT code generator does not require the use of the assembler printer, for +example. Here is an example of registering the Sparc assembly printer: +

+ +
+
+extern "C" void LLVMInitializeSparcAsmPrinter() { 
+  RegisterAsmPrinter<SparcAsmPrinter> X(TheSparcTarget);
+}
+
+
+ +

+For more information, see +"llvm/Target/TargetRegistry.h". +

+ +
+ + + + + +
+ +

+You should describe a concrete target-specific class that represents the +register file of a target machine. This class is called XXXRegisterInfo +(where XXX identifies the target) and represents the class register +file data that is used for register allocation. It also describes the +interactions between registers. +

+ +

+You also need to define register classes to categorize related registers. A +register class should be added for groups of registers that are all treated the +same way for some instruction. Typical examples are register classes for +integer, floating-point, or vector registers. A register allocator allows an +instruction to use any register in a specified register class to perform the +instruction in a similar manner. Register classes allocate virtual registers to +instructions from these sets, and register classes let the target-independent +register allocator automatically choose the actual registers. +

+ +

+Much of the code for registers, including register definition, register aliases, +and register classes, is generated by TableGen from XXXRegisterInfo.td +input files and placed in XXXGenRegisterInfo.h.inc and +XXXGenRegisterInfo.inc output files. Some of the code in the +implementation of XXXRegisterInfo requires hand-coding. +

+ +
+ + + + +
+ +

+The XXXRegisterInfo.td file typically starts with register definitions +for a target machine. The Register class (specified +in Target.td) is used to define an object for each register. The +specified string n becomes the Name of the register. The +basic Register object does not have any subregisters and does not +specify any aliases. +

+ +
+
+class Register<string n> {
+  string Namespace = "";
+  string AsmName = n;
+  string Name = n;
+  int SpillSize = 0;
+  int SpillAlignment = 0;
+  list<Register> Aliases = [];
+  list<Register> SubRegs = [];
+  list<int> DwarfNumbers = [];
+}
+
+
+ +

+For example, in the X86RegisterInfo.td file, there are register +definitions that utilize the Register class, such as: +

+ +
+
+def AL : Register<"AL">, DwarfRegNum<[0, 0, 0]>;
+
+
+ +

+This defines the register AL and assigns it values (with +DwarfRegNum) that are used by gcc, gdb, or a debug +information writer to identify a register. For register +AL, DwarfRegNum takes an array of 3 values representing 3 +different modes: the first element is for X86-64, the second for exception +handling (EH) on X86-32, and the third is generic. -1 is a special Dwarf number +that indicates the gcc number is undefined, and -2 indicates the register number +is invalid for this mode. +

+ +

+From the previously described line in the X86RegisterInfo.td file, +TableGen generates this code in the X86GenRegisterInfo.inc file: +

+ +
+
+static const unsigned GR8[] = { X86::AL, ... };
+
+const unsigned AL_AliasSet[] = { X86::AX, X86::EAX, X86::RAX, 0 };
+
+const TargetRegisterDesc RegisterDescriptors[] = { 
+  ...
+{ "AL", "AL", AL_AliasSet, Empty_SubRegsSet, Empty_SubRegsSet, AL_SuperRegsSet }, ...
+
+
+ +

+From the register info file, TableGen generates a TargetRegisterDesc +object for each register. TargetRegisterDesc is defined in +include/llvm/Target/TargetRegisterInfo.h with the following fields: +

+ +
+
+struct TargetRegisterDesc {
+  const char     *AsmName;      // Assembly language name for the register
+  const char     *Name;         // Printable name for the reg (for debugging)
+  const unsigned *AliasSet;     // Register Alias Set
+  const unsigned *SubRegs;      // Sub-register set
+  const unsigned *ImmSubRegs;   // Immediate sub-register set
+  const unsigned *SuperRegs;    // Super-register set
+};
+
+ +

+TableGen uses the entire target description file (.td) to determine +text names for the register (in the AsmName and Name fields of +TargetRegisterDesc) and the relationships of other registers to the +defined register (in the other TargetRegisterDesc fields). In this +example, other definitions establish the registers "AX", +"EAX", and "RAX" as aliases for one another, so TableGen +generates a null-terminated array (AL_AliasSet) for this register alias +set. +

+ +

+The Register class is commonly used as a base class for more complex +classes. In Target.td, the Register class is the base for the +RegisterWithSubRegs class that is used to define registers that need to +specify subregisters in the SubRegs list, as shown here: +

+ +
+
+class RegisterWithSubRegs<string n,
+list<Register> subregs> : Register<n> {
+  let SubRegs = subregs;
+}
+
+
+ +

+In SparcRegisterInfo.td, additional register classes are defined for +SPARC: a Register subclass, SparcReg, and further subclasses: Ri, +Rf, and Rd. SPARC registers are identified by 5-bit ID +numbers, which is a feature common to these subclasses. Note the use of +'let' expressions to override values that are initially defined in a +superclass (such as SubRegs field in the Rd class). +

+ +
+
+class SparcReg<string n> : Register<n> {
+  field bits<5> Num;
+  let Namespace = "SP";
+}
+// Ri - 32-bit integer registers
+class Ri<bits<5> num, string n> :
+SparcReg<n> {
+  let Num = num;
+}
+// Rf - 32-bit floating-point registers
+class Rf<bits<5> num, string n> :
+SparcReg<n> {
+  let Num = num;
+}
+// Rd - Slots in the FP register file for 64-bit
+floating-point values.
+class Rd<bits<5> num, string n,
+list<Register> subregs> : SparcReg<n> {
+  let Num = num;
+  let SubRegs = subregs;
+}
+
+
+ +

+In the SparcRegisterInfo.td file, there are register definitions that +utilize these subclasses of Register, such as: +

+ +
+
+def G0 : Ri< 0, "G0">,
+DwarfRegNum<[0]>;
+def G1 : Ri< 1, "G1">, DwarfRegNum<[1]>;
+...
+def F0 : Rf< 0, "F0">,
+DwarfRegNum<[32]>;
+def F1 : Rf< 1, "F1">,
+DwarfRegNum<[33]>;
+...
+def D0 : Rd< 0, "F0", [F0, F1]>,
+DwarfRegNum<[32]>;
+def D1 : Rd< 2, "F2", [F2, F3]>,
+DwarfRegNum<[34]>;
+
+
+ +

+The last two registers shown above (D0 and D1) are +double-precision floating-point registers that are aliases for pairs of +single-precision floating-point sub-registers. In addition to aliases, the +sub-register and super-register relationships of the defined register are in +fields of a register's TargetRegisterDesc. +

+ +
+ + + + +
+ +

+The RegisterClass class (specified in Target.td) is used to +define an object that represents a group of related registers and also defines +the default allocation order of the registers. A target description file +XXXRegisterInfo.td that uses Target.td can construct register +classes using the following class: +

+ +
+
+class RegisterClass<string namespace,
+list<ValueType> regTypes, int alignment,
+                    list<Register> regList> {
+  string Namespace = namespace;
+  list<ValueType> RegTypes = regTypes;
+  int Size = 0;  // spill size, in bits; zero lets tblgen pick the size
+  int Alignment = alignment;
+
+  // CopyCost is the cost of copying a value between two registers
+  // default value 1 means a single instruction
+  // A negative value means copying is extremely expensive or impossible
+  int CopyCost = 1;  
+  list<Register> MemberList = regList;
+  
+  // for register classes that are subregisters of this class
+  list<RegisterClass> SubRegClassList = [];  
+  
+  code MethodProtos = [{}];  // to insert arbitrary code
+  code MethodBodies = [{}];
+}
+
+
+ +

To define a RegisterClass, use the following 4 arguments:

+ +
    +
  • The first argument of the definition is the name of the namespace.
  • + +
  • The second argument is a list of ValueType register type values + that are defined in include/llvm/CodeGen/ValueTypes.td. Defined + values include integer types (such as i16, i32, + and i1 for Boolean), floating-point types + (f32, f64), and vector types (for example, v8i16 + for an 8 x i16 vector). All registers in a RegisterClass + must have the same ValueType, but some registers may store vector + data in different configurations. For example a register that can process a + 128-bit vector may be able to handle 16 8-bit integer elements, 8 16-bit + integers, 4 32-bit integers, and so on.
  • + +
  • The third argument of the RegisterClass definition specifies the + alignment required of the registers when they are stored or loaded to + memory.
  • + +
  • The final argument, regList, specifies which registers are in this + class. If an allocation_order_* method is not specified, + then regList also defines the order of allocation used by the + register allocator.
  • +
+ +

+In SparcRegisterInfo.td, three RegisterClass objects are defined: +FPRegs, DFPRegs, and IntRegs. For all three register +classes, the first argument defines the namespace with the string +'SP'. FPRegs defines a group of 32 single-precision +floating-point registers (F0 to F31); DFPRegs defines +a group of 16 double-precision registers +(D0-D15). For IntRegs, the MethodProtos +and MethodBodies methods are used by TableGen to insert the specified +code into generated output. +

+ +
+
+def FPRegs : RegisterClass<"SP", [f32], 32,
+  [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
+   F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>;
+
+def DFPRegs : RegisterClass<"SP", [f64], 64,
+  [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]>;
+ 
+def IntRegs : RegisterClass<"SP", [i32], 32,
+    [L0, L1, L2, L3, L4, L5, L6, L7,
+     I0, I1, I2, I3, I4, I5,
+     O0, O1, O2, O3, O4, O5, O7,
+     G1,
+     // Non-allocatable regs:
+     G2, G3, G4, 
+     O6,        // stack ptr
+    I6,        // frame ptr
+     I7,        // return address
+     G0,        // constant zero
+     G5, G6, G7 // reserved for kernel
+    ]> {
+  let MethodProtos = [{
+    iterator allocation_order_end(const MachineFunction &MF) const;
+  }];
+  let MethodBodies = [{
+    IntRegsClass::iterator
+    IntRegsClass::allocation_order_end(const MachineFunction &MF) const {
+      return end() - 10  // Don't allocate special registers
+         -1;
+    }
+  }];
+}
+
+
+ +

+Using SparcRegisterInfo.td with TableGen generates several output files +that are intended for inclusion in other source code that you write. +SparcRegisterInfo.td generates SparcGenRegisterInfo.h.inc, +which should be included in the header file for the implementation of the SPARC +register implementation that you write (SparcRegisterInfo.h). In +SparcGenRegisterInfo.h.inc a new structure is defined called +SparcGenRegisterInfo that uses TargetRegisterInfo as its +base. It also specifies types, based upon the defined register +classes: DFPRegsClass, FPRegsClass, and IntRegsClass. +

+ +

+SparcRegisterInfo.td also generates SparcGenRegisterInfo.inc, +which is included at the bottom of SparcRegisterInfo.cpp, the SPARC +register implementation. The code below shows only the generated integer +registers and associated register classes. The order of registers +in IntRegs reflects the order in the definition of IntRegs in +the target description file. Take special note of the use +of MethodBodies in SparcRegisterInfo.td to create code in +SparcGenRegisterInfo.inc. MethodProtos generates similar code +in SparcGenRegisterInfo.h.inc. +

+ +
+
  // IntRegs Register Class...
+  static const unsigned IntRegs[] = {
+    SP::L0, SP::L1, SP::L2, SP::L3, SP::L4, SP::L5,
+    SP::L6, SP::L7, SP::I0, SP::I1, SP::I2, SP::I3,
+    SP::I4, SP::I5, SP::O0, SP::O1, SP::O2, SP::O3,
+    SP::O4, SP::O5, SP::O7, SP::G1, SP::G2, SP::G3,
+    SP::G4, SP::O6, SP::I6, SP::I7, SP::G0, SP::G5,
+    SP::G6, SP::G7, 
+  };
+
+  // IntRegsVTs Register Class Value Types...
+  static const MVT::ValueType IntRegsVTs[] = {
+    MVT::i32, MVT::Other
+  };
+
+namespace SP {   // Register class instances
+  DFPRegsClass    DFPRegsRegClass;
+  FPRegsClass     FPRegsRegClass;
+  IntRegsClass    IntRegsRegClass;
+...
+  // IntRegs Sub-register Classess...
+  static const TargetRegisterClass* const IntRegsSubRegClasses [] = {
+    NULL
+  };
+...
+  // IntRegs Super-register Classess...
+  static const TargetRegisterClass* const IntRegsSuperRegClasses [] = {
+    NULL
+  };
+...
+  // IntRegs Register Class sub-classes...
+  static const TargetRegisterClass* const IntRegsSubclasses [] = {
+    NULL
+  };
+...
+  // IntRegs Register Class super-classes...
+  static const TargetRegisterClass* const IntRegsSuperclasses [] = {
+    NULL
+  };
+...
+  IntRegsClass::iterator
+  IntRegsClass::allocation_order_end(const MachineFunction &MF) const {
+     return end()-10  // Don't allocate special registers
+         -1;
+  }
+  
+  IntRegsClass::IntRegsClass() : TargetRegisterClass(IntRegsRegClassID, 
+    IntRegsVTs, IntRegsSubclasses, IntRegsSuperclasses, IntRegsSubRegClasses, 
+    IntRegsSuperRegClasses, 4, 4, 1, IntRegs, IntRegs + 32) {}
+}
+
+
+ +
+ + + + +
+ +

+The final step is to hand code portions of XXXRegisterInfo, which +implements the interface described in TargetRegisterInfo.h. These +functions return 0, NULL, or false, unless +overridden. Here is a list of functions that are overridden for the SPARC +implementation in SparcRegisterInfo.cpp: +

+ +
    +
  • getCalleeSavedRegs — Returns a list of callee-saved registers + in the order of the desired callee-save stack frame offset.
  • + +
  • getReservedRegs — Returns a bitset indexed by physical + register numbers, indicating if a particular register is unavailable.
  • + +
  • hasFP — Return a Boolean indicating if a function should have + a dedicated frame pointer register.
  • + +
  • eliminateCallFramePseudoInstr — If call frame setup or + destroy pseudo instructions are used, this can be called to eliminate + them.
  • + +
  • eliminateFrameIndex — Eliminate abstract frame indices from + instructions that may use them.
  • + +
  • emitPrologue — Insert prologue code into the function.
  • + +
  • emitEpilogue — Insert epilogue code into the function.
  • +
+ +
+ + + + + +
+ +

+During the early stages of code generation, the LLVM IR code is converted to a +SelectionDAG with nodes that are instances of the SDNode class +containing target instructions. An SDNode has an opcode, operands, type +requirements, and operation properties. For example, is an operation +commutative, does an operation load from memory. The various operation node +types are described in the include/llvm/CodeGen/SelectionDAGNodes.h +file (values of the NodeType enum in the ISD namespace). +

+ +

+TableGen uses the following target description (.td) input files to +generate much of the code for instruction definition: +

+ +
    +
  • Target.td — Where the Instruction, Operand, + InstrInfo, and other fundamental classes are defined.
  • + +
  • TargetSelectionDAG.td— Used by SelectionDAG + instruction selection generators, contains SDTC* classes (selection + DAG type constraint), definitions of SelectionDAG nodes (such as + imm, cond, bb, add, fadd, + sub), and pattern support (Pattern, Pat, + PatFrag, PatLeaf, ComplexPattern.
  • + +
  • XXXInstrFormats.td — Patterns for definitions of + target-specific instructions.
  • + +
  • XXXInstrInfo.td — Target-specific definitions of instruction + templates, condition codes, and instructions of an instruction set. For + architecture modifications, a different file name may be used. For example, + for Pentium with SSE instruction, this file is X86InstrSSE.td, and + for Pentium with MMX, this file is X86InstrMMX.td.
  • +
+ +

+There is also a target-specific XXX.td file, where XXX is the +name of the target. The XXX.td file includes the other .td +input files, but its contents are only directly important for subtargets. +

+ +

+You should describe a concrete target-specific class XXXInstrInfo that +represents machine instructions supported by a target machine. +XXXInstrInfo contains an array of XXXInstrDescriptor objects, +each of which describes one instruction. An instruction descriptor defines:

+ +
    +
  • Opcode mnemonic
  • + +
  • Number of operands
  • + +
  • List of implicit register definitions and uses
  • + +
  • Target-independent properties (such as memory access, is commutable)
  • + +
  • Target-specific flags
  • +
+ +

+The Instruction class (defined in Target.td) is mostly used as a base +for more complex instruction classes. +

+ +
+
class Instruction {
+  string Namespace = "";
+  dag OutOperandList;       // An dag containing the MI def operand list.
+  dag InOperandList;        // An dag containing the MI use operand list.
+  string AsmString = "";    // The .s format to print the instruction with.
+  list<dag> Pattern;  // Set to the DAG pattern for this instruction
+  list<Register> Uses = []; 
+  list<Register> Defs = [];
+  list<Predicate> Predicates = [];  // predicates turned into isel match code
+  ... remainder not shown for space ...
+}
+
+
+ +

+A SelectionDAG node (SDNode) should contain an object +representing a target-specific instruction that is defined +in XXXInstrInfo.td. The instruction objects should represent +instructions from the architecture manual of the target machine (such as the +SPARC Architecture Manual for the SPARC target). +

+ +

+A single instruction from the architecture manual is often modeled as multiple +target instructions, depending upon its operands. For example, a manual might +describe an add instruction that takes a register or an immediate operand. An +LLVM target could model this with two instructions named ADDri and +ADDrr. +

+ +

+You should define a class for each instruction category and define each opcode +as a subclass of the category with appropriate parameters such as the fixed +binary encoding of opcodes and extended opcodes. You should map the register +bits to the bits of the instruction in which they are encoded (for the +JIT). Also you should specify how the instruction should be printed when the +automatic assembly printer is used. +

+ +

+As is described in the SPARC Architecture Manual, Version 8, there are three +major 32-bit formats for instructions. Format 1 is only for the CALL +instruction. Format 2 is for branch on condition codes and SETHI (set +high bits of a register) instructions. Format 3 is for other instructions. +

+ +

+Each of these formats has corresponding classes in SparcInstrFormat.td. +InstSP is a base class for other instruction classes. Additional base +classes are specified for more precise formats: for example +in SparcInstrFormat.td, F2_1 is for SETHI, +and F2_2 is for branches. There are three other base +classes: F3_1 for register/register operations, F3_2 for +register/immediate operations, and F3_3 for floating-point +operations. SparcInstrInfo.td also adds the base class Pseudo for +synthetic SPARC instructions. +

+ +

+SparcInstrInfo.td largely consists of operand and instruction +definitions for the SPARC target. In SparcInstrInfo.td, the following +target description file entry, LDrr, defines the Load Integer +instruction for a Word (the LD SPARC opcode) from a memory address to a +register. The first parameter, the value 3 (112), is the +operation value for this category of operation. The second parameter +(0000002) is the specific operation value +for LD/Load Word. The third parameter is the output destination, which +is a register operand and defined in the Register target description +file (IntRegs). +

+ +
+
def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr),
+                 "ld [$addr], $dst",
+                 [(set IntRegs:$dst, (load ADDRrr:$addr))]>;
+
+
+ +

+The fourth parameter is the input source, which uses the address +operand MEMrr that is defined earlier in SparcInstrInfo.td: +

+ +
+
def MEMrr : Operand<i32> {
+  let PrintMethod = "printMemOperand";
+  let MIOperandInfo = (ops IntRegs, IntRegs);
+}
+
+
+ +

+The fifth parameter is a string that is used by the assembly printer and can be +left as an empty string until the assembly printer interface is implemented. The +sixth and final parameter is the pattern used to match the instruction during +the SelectionDAG Select Phase described in +(The LLVM +Target-Independent Code Generator). This parameter is detailed in the next +section, Instruction Selector. +

+ +

+Instruction class definitions are not overloaded for different operand types, so +separate versions of instructions are needed for register, memory, or immediate +value operands. For example, to perform a Load Integer instruction for a Word +from an immediate operand to a register, the following instruction class is +defined: +

+ +
+
def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr),
+                 "ld [$addr], $dst",
+                 [(set IntRegs:$dst, (load ADDRri:$addr))]>;
+
+
+ +

+Writing these definitions for so many similar instructions can involve a lot of +cut and paste. In td files, the multiclass directive enables the +creation of templates to define several instruction classes at once (using +the defm directive). For example in SparcInstrInfo.td, the +multiclass pattern F3_12 is defined to create 2 instruction +classes each time F3_12 is invoked: +

+ +
+
multiclass F3_12 <string OpcStr, bits<6> Op3Val, SDNode OpNode> {
+  def rr  : F3_1 <2, Op3Val, 
+                 (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
+                 !strconcat(OpcStr, " $b, $c, $dst"),
+                 [(set IntRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>;
+  def ri  : F3_2 <2, Op3Val,
+                 (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
+                 !strconcat(OpcStr, " $b, $c, $dst"),
+                 [(set IntRegs:$dst, (OpNode IntRegs:$b, simm13:$c))]>;
+}
+
+
+ +

+So when the defm directive is used for the XOR +and ADD instructions, as seen below, it creates four instruction +objects: XORrr, XORri, ADDrr, and ADDri. +

+ +
+
+defm XOR   : F3_12<"xor", 0b000011, xor>;
+defm ADD   : F3_12<"add", 0b000000, add>;
+
+
+ +

+SparcInstrInfo.td also includes definitions for condition codes that +are referenced by branch instructions. The following definitions +in SparcInstrInfo.td indicate the bit location of the SPARC condition +code. For example, the 10th bit represents the 'greater than' +condition for integers, and the 22nd bit represents the 'greater +than' condition for floats. +

+ +
+
+def ICC_NE  : ICC_VAL< 9>;  // Not Equal
+def ICC_E   : ICC_VAL< 1>;  // Equal
+def ICC_G   : ICC_VAL<10>;  // Greater
+...
+def FCC_U   : FCC_VAL<23>;  // Unordered
+def FCC_G   : FCC_VAL<22>;  // Greater
+def FCC_UG  : FCC_VAL<21>;  // Unordered or Greater
+...
+
+
+ +

+(Note that Sparc.h also defines enums that correspond to the same SPARC +condition codes. Care must be taken to ensure the values in Sparc.h +correspond to the values in SparcInstrInfo.td. I.e., +SPCC::ICC_NE = 9, SPCC::FCC_U = 23 and so on.) +

+ +
+ + + + +
+ +

+The code generator backend maps instruction operands to fields in the +instruction. Operands are assigned to unbound fields in the instruction in the +order they are defined. Fields are bound when they are assigned a value. For +example, the Sparc target defines the XNORrr instruction as +a F3_1 format instruction having three operands. +

+ +
+
+def XNORrr  : F3_1<2, 0b000111,
+                   (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
+                   "xnor $b, $c, $dst",
+                   [(set IntRegs:$dst, (not (xor IntRegs:$b, IntRegs:$c)))]>;
+
+
+ +

+The instruction templates in SparcInstrFormats.td show the base class +for F3_1 is InstSP. +

+ +
+
+class InstSP<dag outs, dag ins, string asmstr, list<dag> pattern> : Instruction {
+  field bits<32> Inst;
+  let Namespace = "SP";
+  bits<2> op;
+  let Inst{31-30} = op;       
+  dag OutOperandList = outs;
+  dag InOperandList = ins;
+  let AsmString   = asmstr;
+  let Pattern = pattern;
+}
+
+
+ +

InstSP leaves the op field unbound.

+ +
+
+class F3<dag outs, dag ins, string asmstr, list<dag> pattern>
+    : InstSP<outs, ins, asmstr, pattern> {
+  bits<5> rd;
+  bits<6> op3;
+  bits<5> rs1;
+  let op{1} = 1;   // Op = 2 or 3
+  let Inst{29-25} = rd;
+  let Inst{24-19} = op3;
+  let Inst{18-14} = rs1;
+}
+
+
+ +

+F3 binds the op field and defines the rd, +op3, and rs1 fields. F3 format instructions will +bind the operands rd, op3, and rs1 fields. +

+ +
+
+class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
+           string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
+  bits<8> asi = 0; // asi not currently used
+  bits<5> rs2;
+  let op         = opVal;
+  let op3        = op3val;
+  let Inst{13}   = 0;     // i field = 0
+  let Inst{12-5} = asi;   // address space identifier
+  let Inst{4-0}  = rs2;
+}
+
+
+ +

+F3_1 binds the op3 field and defines the rs2 +fields. F3_1 format instructions will bind the operands to the rd, +rs1, and rs2 fields. This results in the XNORrr +instruction binding $dst, $b, and $c operands to +the rd, rs1, and rs2 fields respectively. +

+ +
+ + + + +
+ +

+The final step is to hand code portions of XXXInstrInfo, which +implements the interface described in TargetInstrInfo.h. These +functions return 0 or a Boolean or they assert, unless +overridden. Here's a list of functions that are overridden for the SPARC +implementation in SparcInstrInfo.cpp: +

+ +
    +
  • isLoadFromStackSlot — If the specified machine instruction is + a direct load from a stack slot, return the register number of the + destination and the FrameIndex of the stack slot.
  • + +
  • isStoreToStackSlot — If the specified machine instruction is + a direct store to a stack slot, return the register number of the + destination and the FrameIndex of the stack slot.
  • + +
  • copyPhysReg — Copy values between a pair of physical + registers.
  • + +
  • storeRegToStackSlot — Store a register value to a stack + slot.
  • + +
  • loadRegFromStackSlot — Load a register value from a stack + slot.
  • + +
  • storeRegToAddr — Store a register value to memory.
  • + +
  • loadRegFromAddr — Load a register value from memory.
  • + +
  • foldMemoryOperand — Attempt to combine instructions of any + load or store instruction for the specified operand(s).
  • +
+ +
+ + + +
+ +

+Performance can be improved by combining instructions or by eliminating +instructions that are never reached. The AnalyzeBranch method +in XXXInstrInfo may be implemented to examine conditional instructions +and remove unnecessary instructions. AnalyzeBranch looks at the end of +a machine basic block (MBB) for opportunities for improvement, such as branch +folding and if conversion. The BranchFolder and IfConverter +machine function passes (see the source files BranchFolding.cpp and +IfConversion.cpp in the lib/CodeGen directory) call +AnalyzeBranch to improve the control flow graph that represents the +instructions. +

+ +

+Several implementations of AnalyzeBranch (for ARM, Alpha, and X86) can +be examined as models for your own AnalyzeBranch implementation. Since +SPARC does not implement a useful AnalyzeBranch, the ARM target +implementation is shown below. +

+ +

AnalyzeBranch returns a Boolean value and takes four parameters:

+ +
    +
  • MachineBasicBlock &MBB — The incoming block to be + examined.
  • + +
  • MachineBasicBlock *&TBB — A destination block that is + returned. For a conditional branch that evaluates to true, TBB is + the destination.
  • + +
  • MachineBasicBlock *&FBB — For a conditional branch that + evaluates to false, FBB is returned as the destination.
  • + +
  • std::vector<MachineOperand> &Cond — List of + operands to evaluate a condition for a conditional branch.
  • +
+ +

+In the simplest case, if a block ends without a branch, then it falls through to +the successor block. No destination blocks are specified for either TBB +or FBB, so both parameters return NULL. The start of +the AnalyzeBranch (see code below for the ARM target) shows the +function parameters and the code for the simplest case. +

+ +
+
bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
+        MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,
+        std::vector<MachineOperand> &Cond) const
+{
+  MachineBasicBlock::iterator I = MBB.end();
+  if (I == MBB.begin() || !isUnpredicatedTerminator(--I))
+    return false;
+
+
+ +

+If a block ends with a single unconditional branch instruction, then +AnalyzeBranch (shown below) should return the destination of that +branch in the TBB parameter. +

+ +
+
+  if (LastOpc == ARM::B || LastOpc == ARM::tB) {
+    TBB = LastInst->getOperand(0).getMBB();
+    return false;
+  }
+
+
+ +

+If a block ends with two unconditional branches, then the second branch is never +reached. In that situation, as shown below, remove the last branch instruction +and return the penultimate branch in the TBB parameter. +

+ +
+
+  if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) &&
+      (LastOpc == ARM::B || LastOpc == ARM::tB)) {
+    TBB = SecondLastInst->getOperand(0).getMBB();
+    I = LastInst;
+    I->eraseFromParent();
+    return false;
+  }
+
+
+ +

+A block may end with a single conditional branch instruction that falls through +to successor block if the condition evaluates to false. In that case, +AnalyzeBranch (shown below) should return the destination of that +conditional branch in the TBB parameter and a list of operands in +the Cond parameter to evaluate the condition. +

+ +
+
+  if (LastOpc == ARM::Bcc || LastOpc == ARM::tBcc) {
+    // Block ends with fall-through condbranch.
+    TBB = LastInst->getOperand(0).getMBB();
+    Cond.push_back(LastInst->getOperand(1));
+    Cond.push_back(LastInst->getOperand(2));
+    return false;
+  }
+
+
+ +

+If a block ends with both a conditional branch and an ensuing unconditional +branch, then AnalyzeBranch (shown below) should return the conditional +branch destination (assuming it corresponds to a conditional evaluation of +'true') in the TBB parameter and the unconditional branch +destination in the FBB (corresponding to a conditional evaluation of +'false'). A list of operands to evaluate the condition should be +returned in the Cond parameter. +

+ +
+
+  unsigned SecondLastOpc = SecondLastInst->getOpcode();
+
+  if ((SecondLastOpc == ARM::Bcc && LastOpc == ARM::B) ||
+      (SecondLastOpc == ARM::tBcc && LastOpc == ARM::tB)) {
+    TBB =  SecondLastInst->getOperand(0).getMBB();
+    Cond.push_back(SecondLastInst->getOperand(1));
+    Cond.push_back(SecondLastInst->getOperand(2));
+    FBB = LastInst->getOperand(0).getMBB();
+    return false;
+  }
+
+
+ +

+For the last two cases (ending with a single conditional branch or ending with +one conditional and one unconditional branch), the operands returned in +the Cond parameter can be passed to methods of other instructions to +create new branches or perform other operations. An implementation +of AnalyzeBranch requires the helper methods RemoveBranch +and InsertBranch to manage subsequent operations. +

+ +

+AnalyzeBranch should return false indicating success in most circumstances. +AnalyzeBranch should only return true when the method is stumped about what to +do, for example, if a block has three terminating branches. AnalyzeBranch may +return true if it encounters a terminator it cannot handle, such as an indirect +branch. +

+ +
+ + + + + +
+ +

+LLVM uses a SelectionDAG to represent LLVM IR instructions, and nodes +of the SelectionDAG ideally represent native target +instructions. During code generation, instruction selection passes are performed +to convert non-native DAG instructions into native target-specific +instructions. The pass described in XXXISelDAGToDAG.cpp is used to +match patterns and perform DAG-to-DAG instruction selection. Optionally, a pass +may be defined (in XXXBranchSelector.cpp) to perform similar DAG-to-DAG +operations for branch instructions. Later, the code in +XXXISelLowering.cpp replaces or removes operations and data types not +supported natively (legalizes) in a SelectionDAG. +

+ +

+TableGen generates code for instruction selection using the following target +description input files: +

+ +
    +
  • XXXInstrInfo.td — Contains definitions of instructions in a + target-specific instruction set, generates XXXGenDAGISel.inc, which + is included in XXXISelDAGToDAG.cpp.
  • + +
  • XXXCallingConv.td — Contains the calling and return value + conventions for the target architecture, and it generates + XXXGenCallingConv.inc, which is included in + XXXISelLowering.cpp.
  • +
+ +

+The implementation of an instruction selection pass must include a header that +declares the FunctionPass class or a subclass of FunctionPass. In +XXXTargetMachine.cpp, a Pass Manager (PM) should add each instruction +selection pass into the queue of passes to run. +

+ +

+The LLVM static compiler (llc) is an excellent tool for visualizing the +contents of DAGs. To display the SelectionDAG before or after specific +processing phases, use the command line options for llc, described +at +SelectionDAG Instruction Selection Process. +

+ +

+To describe instruction selector behavior, you should add patterns for lowering +LLVM code into a SelectionDAG as the last parameter of the instruction +definitions in XXXInstrInfo.td. For example, in +SparcInstrInfo.td, this entry defines a register store operation, and +the last parameter describes a pattern with the store DAG operator. +

+ +
+
+def STrr  : F3_1< 3, 0b000100, (outs), (ins MEMrr:$addr, IntRegs:$src),
+                 "st $src, [$addr]", [(store IntRegs:$src, ADDRrr:$addr)]>;
+
+
+ +

+ADDRrr is a memory mode that is also defined in +SparcInstrInfo.td: +

+ +
+
+def ADDRrr : ComplexPattern<i32, 2, "SelectADDRrr", [], []>;
+
+
+ +

+The definition of ADDRrr refers to SelectADDRrr, which is a +function defined in an implementation of the Instructor Selector (such +as SparcISelDAGToDAG.cpp). +

+ +

+In lib/Target/TargetSelectionDAG.td, the DAG operator for store is +defined below: +

+ +
+
+def store : PatFrag<(ops node:$val, node:$ptr),
+                    (st node:$val, node:$ptr), [{
+  if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+    return !ST->isTruncatingStore() && 
+           ST->getAddressingMode() == ISD::UNINDEXED;
+  return false;
+}]>;
+
+
+ +

+XXXInstrInfo.td also generates (in XXXGenDAGISel.inc) the +SelectCode method that is used to call the appropriate processing +method for an instruction. In this example, SelectCode +calls Select_ISD_STORE for the ISD::STORE opcode. +

+ +
+
+SDNode *SelectCode(SDValue N) {
+  ... 
+  MVT::ValueType NVT = N.getNode()->getValueType(0);
+  switch (N.getOpcode()) {
+  case ISD::STORE: {
+    switch (NVT) {
+    default:
+      return Select_ISD_STORE(N);
+      break;
+    }
+    break;
+  }
+  ...
+
+
+ +

+The pattern for STrr is matched, so elsewhere in +XXXGenDAGISel.inc, code for STrr is created for +Select_ISD_STORE. The Emit_22 method is also generated +in XXXGenDAGISel.inc to complete the processing of this +instruction. +

+ +
+
+SDNode *Select_ISD_STORE(const SDValue &N) {
+  SDValue Chain = N.getOperand(0);
+  if (Predicate_store(N.getNode())) {
+    SDValue N1 = N.getOperand(1);
+    SDValue N2 = N.getOperand(2);
+    SDValue CPTmp0;
+    SDValue CPTmp1;
+
+    // Pattern: (st:void IntRegs:i32:$src, 
+    //           ADDRrr:i32:$addr)<<P:Predicate_store>>
+    // Emits: (STrr:void ADDRrr:i32:$addr, IntRegs:i32:$src)
+    // Pattern complexity = 13  cost = 1  size = 0
+    if (SelectADDRrr(N, N2, CPTmp0, CPTmp1) &&
+        N1.getNode()->getValueType(0) == MVT::i32 &&
+        N2.getNode()->getValueType(0) == MVT::i32) {
+      return Emit_22(N, SP::STrr, CPTmp0, CPTmp1);
+    }
+...
+
+
+ +
+ + + + +
+ +

+The Legalize phase converts a DAG to use types and operations that are natively +supported by the target. For natively unsupported types and operations, you need +to add code to the target-specific XXXTargetLowering implementation to convert +unsupported types and operations to supported ones. +

+ +

+In the constructor for the XXXTargetLowering class, first use the +addRegisterClass method to specify which types are supports and which +register classes are associated with them. The code for the register classes are +generated by TableGen from XXXRegisterInfo.td and placed +in XXXGenRegisterInfo.h.inc. For example, the implementation of the +constructor for the SparcTargetLowering class (in +SparcISelLowering.cpp) starts with the following code: +

+ +
+
+addRegisterClass(MVT::i32, SP::IntRegsRegisterClass);
+addRegisterClass(MVT::f32, SP::FPRegsRegisterClass);
+addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass); 
+
+
+ +

+You should examine the node types in the ISD namespace +(include/llvm/CodeGen/SelectionDAGNodes.h) and determine which +operations the target natively supports. For operations that do not have +native support, add a callback to the constructor for the XXXTargetLowering +class, so the instruction selection process knows what to do. The TargetLowering +class callback methods (declared in llvm/Target/TargetLowering.h) are: +

+ +
    +
  • setOperationAction — General operation.
  • + +
  • setLoadExtAction — Load with extension.
  • + +
  • setTruncStoreAction — Truncating store.
  • + +
  • setIndexedLoadAction — Indexed load.
  • + +
  • setIndexedStoreAction — Indexed store.
  • + +
  • setConvertAction — Type conversion.
  • + +
  • setCondCodeAction — Support for a given condition code.
  • +
+ +

+Note: on older releases, setLoadXAction is used instead +of setLoadExtAction. Also, on older releases, +setCondCodeAction may not be supported. Examine your release +to see what methods are specifically supported. +

+ +

+These callbacks are used to determine that an operation does or does not work +with a specified type (or types). And in all cases, the third parameter is +a LegalAction type enum value: Promote, Expand, +Custom, or Legal. SparcISelLowering.cpp +contains examples of all four LegalAction values. +

+ +
+ + +
+ Promote +
+ +
+ +

+For an operation without native support for a given type, the specified type may +be promoted to a larger type that is supported. For example, SPARC does not +support a sign-extending load for Boolean values (i1 type), so +in SparcISelLowering.cpp the third parameter below, Promote, +changes i1 type values to a large type before loading. +

+ +
+
+setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
+
+
+ +
+ + +
+ Expand +
+ +
+ +

+For a type without native support, a value may need to be broken down further, +rather than promoted. For an operation without native support, a combination of +other operations may be used to similar effect. In SPARC, the floating-point +sine and cosine trig operations are supported by expansion to other operations, +as indicated by the third parameter, Expand, to +setOperationAction: +

+ +
+
+setOperationAction(ISD::FSIN, MVT::f32, Expand);
+setOperationAction(ISD::FCOS, MVT::f32, Expand);
+
+
+ +
+ + +
+ Custom +
+ +
+ +

+For some operations, simple type promotion or operation expansion may be +insufficient. In some cases, a special intrinsic function must be implemented. +

+ +

+For example, a constant value may require special treatment, or an operation may +require spilling and restoring registers in the stack and working with register +allocators. +

+ +

+As seen in SparcISelLowering.cpp code below, to perform a type +conversion from a floating point value to a signed integer, first the +setOperationAction should be called with Custom as the third +parameter: +

+ +
+
+setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
+
+
+ +

+In the LowerOperation method, for each Custom operation, a +case statement should be added to indicate what function to call. In the +following code, an FP_TO_SINT opcode will call +the LowerFP_TO_SINT method: +

+ +
+
+SDValue SparcTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
+  switch (Op.getOpcode()) {
+  case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
+  ...
+  }
+}
+
+
+ +

+Finally, the LowerFP_TO_SINT method is implemented, using an FP +register to convert the floating-point value to an integer. +

+ +
+
+static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
+  assert(Op.getValueType() == MVT::i32);
+  Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0));
+  return DAG.getNode(ISD::BITCAST, MVT::i32, Op);
+}
+
+
+ +
+ + +
+ Legal +
+ +
+ +

+The Legal LegalizeAction enum value simply indicates that an +operation is natively supported. Legal represents the default +condition, so it is rarely used. In SparcISelLowering.cpp, the action +for CTPOP (an operation to count the bits set in an integer) is +natively supported only for SPARC v9. The following code enables +the Expand conversion technique for non-v9 SPARC implementations. +

+ +
+
+setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+...
+if (TM.getSubtarget<SparcSubtarget>().isV9())
+  setOperationAction(ISD::CTPOP, MVT::i32, Legal);
+  case ISD::SETULT: return SPCC::ICC_CS;
+  case ISD::SETULE: return SPCC::ICC_LEU;
+  case ISD::SETUGT: return SPCC::ICC_GU;
+  case ISD::SETUGE: return SPCC::ICC_CC;
+  }
+}
+
+
+ +
+ + + + +
+ +

+To support target-specific calling conventions, XXXGenCallingConv.td +uses interfaces (such as CCIfType and CCAssignToReg) that are defined in +lib/Target/TargetCallingConv.td. TableGen can take the target +descriptor file XXXGenCallingConv.td and generate the header +file XXXGenCallingConv.inc, which is typically included +in XXXISelLowering.cpp. You can use the interfaces in +TargetCallingConv.td to specify: +

+ +
    +
  • The order of parameter allocation.
  • + +
  • Where parameters and return values are placed (that is, on the stack or in + registers).
  • + +
  • Which registers may be used.
  • + +
  • Whether the caller or callee unwinds the stack.
  • +
+ +

+The following example demonstrates the use of the CCIfType and +CCAssignToReg interfaces. If the CCIfType predicate is true +(that is, if the current argument is of type f32 or f64), then +the action is performed. In this case, the CCAssignToReg action assigns +the argument value to the first available register: either R0 +or R1. +

+ +
+
+CCIfType<[f32,f64], CCAssignToReg<[R0, R1]>>
+
+
+ +

+SparcCallingConv.td contains definitions for a target-specific +return-value calling convention (RetCC_Sparc32) and a basic 32-bit C calling +convention (CC_Sparc32). The definition of RetCC_Sparc32 +(shown below) indicates which registers are used for specified scalar return +types. A single-precision float is returned to register F0, and a +double-precision float goes to register D0. A 32-bit integer is +returned in register I0 or I1. +

+ +
+
+def RetCC_Sparc32 : CallingConv<[
+  CCIfType<[i32], CCAssignToReg<[I0, I1]>>,
+  CCIfType<[f32], CCAssignToReg<[F0]>>,
+  CCIfType<[f64], CCAssignToReg<[D0]>>
+]>;
+
+
+ +

+The definition of CC_Sparc32 in SparcCallingConv.td introduces +CCAssignToStack, which assigns the value to a stack slot with the +specified size and alignment. In the example below, the first parameter, 4, +indicates the size of the slot, and the second parameter, also 4, indicates the +stack alignment along 4-byte units. (Special cases: if size is zero, then the +ABI size is used; if alignment is zero, then the ABI alignment is used.) +

+ +
+
+def CC_Sparc32 : CallingConv<[
+  // All arguments get passed in integer registers if there is space.
+  CCIfType<[i32, f32, f64], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
+  CCAssignToStack<4, 4>
+]>;
+
+
+ +

+CCDelegateTo is another commonly used interface, which tries to find a +specified sub-calling convention, and, if a match is found, it is invoked. In +the following example (in X86CallingConv.td), the definition of +RetCC_X86_32_C ends with CCDelegateTo. After the current value +is assigned to the register ST0 or ST1, +the RetCC_X86Common is invoked. +

+ +
+
+def RetCC_X86_32_C : CallingConv<[
+  CCIfType<[f32], CCAssignToReg<[ST0, ST1]>>,
+  CCIfType<[f64], CCAssignToReg<[ST0, ST1]>>,
+  CCDelegateTo<RetCC_X86Common>
+]>;
+
+
+ +

+CCIfCC is an interface that attempts to match the given name to the +current calling convention. If the name identifies the current calling +convention, then a specified action is invoked. In the following example (in +X86CallingConv.td), if the Fast calling convention is in use, +then RetCC_X86_32_Fast is invoked. If the SSECall calling +convention is in use, then RetCC_X86_32_SSE is invoked. +

+ +
+
+def RetCC_X86_32 : CallingConv<[
+  CCIfCC<"CallingConv::Fast", CCDelegateTo<RetCC_X86_32_Fast>>,
+  CCIfCC<"CallingConv::X86_SSECall", CCDelegateTo<RetCC_X86_32_SSE>>,
+  CCDelegateTo<RetCC_X86_32_C>
+]>;
+
+
+ +

Other calling convention interfaces include:

+ +
    +
  • CCIf <predicate, action> — If the predicate matches, + apply the action.
  • + +
  • CCIfInReg <action> — If the argument is marked with the + 'inreg' attribute, then apply the action.
  • + +
  • CCIfNest <action> — Inf the argument is marked with the + 'nest' attribute, then apply the action.
  • + +
  • CCIfNotVarArg <action> — If the current function does + not take a variable number of arguments, apply the action.
  • + +
  • CCAssignToRegWithShadow <registerList, shadowList> — + similar to CCAssignToReg, but with a shadow list of registers.
  • + +
  • CCPassByVal <size, align> — Assign value to a stack + slot with the minimum specified size and alignment.
  • + +
  • CCPromoteToType <type> — Promote the current value to + the specified type.
  • + +
  • CallingConv <[actions]> — Define each calling + convention that is supported.
  • +
+ +
+ + + + + +
+ +

+During the code emission stage, the code generator may utilize an LLVM pass to +produce assembly output. To do this, you want to implement the code for a +printer that converts LLVM IR to a GAS-format assembly language for your target +machine, using the following steps: +

+ +
    +
  • Define all the assembly strings for your target, adding them to the + instructions defined in the XXXInstrInfo.td file. + (See Instruction Set.) TableGen will produce + an output file (XXXGenAsmWriter.inc) with an implementation of + the printInstruction method for the XXXAsmPrinter class.
  • + +
  • Write XXXTargetAsmInfo.h, which contains the bare-bones declaration + of the XXXTargetAsmInfo class (a subclass + of TargetAsmInfo).
  • + +
  • Write XXXTargetAsmInfo.cpp, which contains target-specific values + for TargetAsmInfo properties and sometimes new implementations for + methods.
  • + +
  • Write XXXAsmPrinter.cpp, which implements the AsmPrinter + class that performs the LLVM-to-assembly conversion.
  • +
+ +

+The code in XXXTargetAsmInfo.h is usually a trivial declaration of the +XXXTargetAsmInfo class for use in XXXTargetAsmInfo.cpp. +Similarly, XXXTargetAsmInfo.cpp usually has a few declarations of +XXXTargetAsmInfo replacement values that override the default values +in TargetAsmInfo.cpp. For example in SparcTargetAsmInfo.cpp: +

+ +
+
+SparcTargetAsmInfo::SparcTargetAsmInfo(const SparcTargetMachine &TM) {
+  Data16bitsDirective = "\t.half\t";
+  Data32bitsDirective = "\t.word\t";
+  Data64bitsDirective = 0;  // .xword is only supported by V9.
+  ZeroDirective = "\t.skip\t";
+  CommentString = "!";
+  ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
+}
+
+
+ +

+The X86 assembly printer implementation (X86TargetAsmInfo) is an +example where the target specific TargetAsmInfo class uses an +overridden methods: ExpandInlineAsm. +

+ +

+A target-specific implementation of AsmPrinter is written in +XXXAsmPrinter.cpp, which implements the AsmPrinter class that +converts the LLVM to printable assembly. The implementation must include the +following headers that have declarations for the AsmPrinter and +MachineFunctionPass classes. The MachineFunctionPass is a +subclass of FunctionPass. +

+ +
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunctionPass.h" 
+
+
+ +

+As a FunctionPass, AsmPrinter first +calls doInitialization to set up the AsmPrinter. In +SparcAsmPrinter, a Mangler object is instantiated to process +variable names. +

+ +

+In XXXAsmPrinter.cpp, the runOnMachineFunction method +(declared in MachineFunctionPass) must be implemented +for XXXAsmPrinter. In MachineFunctionPass, +the runOnFunction method invokes runOnMachineFunction. +Target-specific implementations of runOnMachineFunction differ, but +generally do the following to process each machine function: +

+ +
    +
  • Call SetupMachineFunction to perform initialization.
  • + +
  • Call EmitConstantPool to print out (to the output stream) constants + which have been spilled to memory.
  • + +
  • Call EmitJumpTableInfo to print out jump tables used by the current + function.
  • + +
  • Print out the label for the current function.
  • + +
  • Print out the code for the function, including basic block labels and the + assembly for the instruction (using printInstruction)
  • +
+ +

+The XXXAsmPrinter implementation must also include the code generated +by TableGen that is output in the XXXGenAsmWriter.inc file. The code +in XXXGenAsmWriter.inc contains an implementation of the +printInstruction method that may call these methods: +

+ +
    +
  • printOperand
  • + +
  • printMemOperand
  • + +
  • printCCOperand (for conditional statements)
  • + +
  • printDataDirective
  • + +
  • printDeclare
  • + +
  • printImplicitDef
  • + +
  • printInlineAsm
  • +
+ +

+The implementations of printDeclare, printImplicitDef, +printInlineAsm, and printLabel in AsmPrinter.cpp are +generally adequate for printing assembly and do not need to be +overridden. +

+ +

+The printOperand method is implemented with a long switch/case +statement for the type of operand: register, immediate, basic block, external +symbol, global address, constant pool index, or jump table index. For an +instruction with a memory address operand, the printMemOperand method +should be implemented to generate the proper output. Similarly, +printCCOperand should be used to print a conditional operand. +

+ +

doFinalization should be overridden in XXXAsmPrinter, and +it should be called to shut down the assembly printer. During +doFinalization, global variables and constants are printed to +output. +

+ +
+ + + + + +
+ +

+Subtarget support is used to inform the code generation process of instruction +set variations for a given chip set. For example, the LLVM SPARC implementation +provided covers three major versions of the SPARC microprocessor architecture: +Version 8 (V8, which is a 32-bit architecture), Version 9 (V9, a 64-bit +architecture), and the UltraSPARC architecture. V8 has 16 double-precision +floating-point registers that are also usable as either 32 single-precision or 8 +quad-precision registers. V8 is also purely big-endian. V9 has 32 +double-precision floating-point registers that are also usable as 16 +quad-precision registers, but cannot be used as single-precision registers. The +UltraSPARC architecture combines V9 with UltraSPARC Visual Instruction Set +extensions. +

+ +

+If subtarget support is needed, you should implement a target-specific +XXXSubtarget class for your architecture. This class should process the +command-line options -mcpu= and -mattr=. +

+ +

+TableGen uses definitions in the Target.td and Sparc.td files +to generate code in SparcGenSubtarget.inc. In Target.td, shown +below, the SubtargetFeature interface is defined. The first 4 string +parameters of the SubtargetFeature interface are a feature name, an +attribute set by the feature, the value of the attribute, and a description of +the feature. (The fifth parameter is a list of features whose presence is +implied, and its default value is an empty array.) +

+ +
+
+class SubtargetFeature<string n, string a,  string v, string d,
+                       list<SubtargetFeature> i = []> {
+  string Name = n;
+  string Attribute = a;
+  string Value = v;
+  string Desc = d;
+  list<SubtargetFeature> Implies = i;
+}
+
+
+ +

+In the Sparc.td file, the SubtargetFeature is used to define the +following features. +

+ +
+
+def FeatureV9 : SubtargetFeature<"v9", "IsV9", "true",
+                     "Enable SPARC-V9 instructions">;
+def FeatureV8Deprecated : SubtargetFeature<"deprecated-v8", 
+                     "V8DeprecatedInsts", "true",
+                     "Enable deprecated V8 instructions in V9 mode">;
+def FeatureVIS : SubtargetFeature<"vis", "IsVIS", "true",
+                     "Enable UltraSPARC Visual Instruction Set extensions">;
+
+
+ +

+Elsewhere in Sparc.td, the Proc class is defined and then is used to +define particular SPARC processor subtypes that may have the previously +described features. +

+ +
+
+class Proc<string Name, list<SubtargetFeature> Features>
+  : Processor<Name, NoItineraries, Features>;
+ 
+def : Proc<"generic",         []>;
+def : Proc<"v8",              []>;
+def : Proc<"supersparc",      []>;
+def : Proc<"sparclite",       []>;
+def : Proc<"f934",            []>;
+def : Proc<"hypersparc",      []>;
+def : Proc<"sparclite86x",    []>;
+def : Proc<"sparclet",        []>;
+def : Proc<"tsc701",          []>;
+def : Proc<"v9",              [FeatureV9]>;
+def : Proc<"ultrasparc",      [FeatureV9, FeatureV8Deprecated]>;
+def : Proc<"ultrasparc3",     [FeatureV9, FeatureV8Deprecated]>;
+def : Proc<"ultrasparc3-vis", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
+
+
+ +

+From Target.td and Sparc.td files, the resulting +SparcGenSubtarget.inc specifies enum values to identify the features, arrays of +constants to represent the CPU features and CPU subtypes, and the +ParseSubtargetFeatures method that parses the features string that sets +specified subtarget options. The generated SparcGenSubtarget.inc file +should be included in the SparcSubtarget.cpp. The target-specific +implementation of the XXXSubtarget method should follow this pseudocode: +

+ +
+
+XXXSubtarget::XXXSubtarget(const Module &M, const std::string &FS) {
+  // Set the default features
+  // Determine default and user specified characteristics of the CPU
+  // Call ParseSubtargetFeatures(FS, CPU) to parse the features string
+  // Perform any additional operations
+}
+
+
+ +
+ + + + + +
+ +

+The implementation of a target machine optionally includes a Just-In-Time (JIT) +code generator that emits machine code and auxiliary structures as binary output +that can be written directly to memory. To do this, implement JIT code +generation by performing the following steps: +

+ +
    +
  • Write an XXXCodeEmitter.cpp file that contains a machine function + pass that transforms target-machine instructions into relocatable machine + code.
  • + +
  • Write an XXXJITInfo.cpp file that implements the JIT interfaces for + target-specific code-generation activities, such as emitting machine code + and stubs.
  • + +
  • Modify XXXTargetMachine so that it provides a + TargetJITInfo object through its getJITInfo method.
  • +
+ +

+There are several different approaches to writing the JIT support code. For +instance, TableGen and target descriptor files may be used for creating a JIT +code generator, but are not mandatory. For the Alpha and PowerPC target +machines, TableGen is used to generate XXXGenCodeEmitter.inc, which +contains the binary coding of machine instructions and the +getBinaryCodeForInstr method to access those codes. Other JIT +implementations do not. +

+ +

+Both XXXJITInfo.cpp and XXXCodeEmitter.cpp must include the +llvm/CodeGen/MachineCodeEmitter.h header file that defines the +MachineCodeEmitter class containing code for several callback functions +that write data (in bytes, words, strings, etc.) to the output stream. +

+ +
+ + + + +
+ +

+In XXXCodeEmitter.cpp, a target-specific of the Emitter class +is implemented as a function pass (subclass +of MachineFunctionPass). The target-specific implementation +of runOnMachineFunction (invoked by +runOnFunction in MachineFunctionPass) iterates through the +MachineBasicBlock calls emitInstruction to process each +instruction and emit binary code. emitInstruction is largely +implemented with case statements on the instruction types defined in +XXXInstrInfo.h. For example, in X86CodeEmitter.cpp, +the emitInstruction method is built around the following switch/case +statements: +

+ +
+
+switch (Desc->TSFlags & X86::FormMask) {
+case X86II::Pseudo:  // for not yet implemented instructions 
+   ...               // or pseudo-instructions
+   break;
+case X86II::RawFrm:  // for instructions with a fixed opcode value
+   ...
+   break;
+case X86II::AddRegFrm: // for instructions that have one register operand 
+   ...                 // added to their opcode
+   break;
+case X86II::MRMDestReg:// for instructions that use the Mod/RM byte
+   ...                 // to specify a destination (register)
+   break;
+case X86II::MRMDestMem:// for instructions that use the Mod/RM byte
+   ...                 // to specify a destination (memory)
+   break;
+case X86II::MRMSrcReg: // for instructions that use the Mod/RM byte
+   ...                 // to specify a source (register)
+   break;
+case X86II::MRMSrcMem: // for instructions that use the Mod/RM byte
+   ...                 // to specify a source (memory)
+   break;
+case X86II::MRM0r: case X86II::MRM1r:  // for instructions that operate on 
+case X86II::MRM2r: case X86II::MRM3r:  // a REGISTER r/m operand and
+case X86II::MRM4r: case X86II::MRM5r:  // use the Mod/RM byte and a field
+case X86II::MRM6r: case X86II::MRM7r:  // to hold extended opcode data
+   ...  
+   break;
+case X86II::MRM0m: case X86II::MRM1m:  // for instructions that operate on
+case X86II::MRM2m: case X86II::MRM3m:  // a MEMORY r/m operand and
+case X86II::MRM4m: case X86II::MRM5m:  // use the Mod/RM byte and a field
+case X86II::MRM6m: case X86II::MRM7m:  // to hold extended opcode data
+   ...  
+   break;
+case X86II::MRMInitReg: // for instructions whose source and
+   ...                  // destination are the same register
+   break;
+}
+
+
+ +

+The implementations of these case statements often first emit the opcode and +then get the operand(s). Then depending upon the operand, helper methods may be +called to process the operand(s). For example, in X86CodeEmitter.cpp, +for the X86II::AddRegFrm case, the first data emitted +(by emitByte) is the opcode added to the register operand. Then an +object representing the machine operand, MO1, is extracted. The helper +methods such as isImmediate, +isGlobalAddress, isExternalSymbol, isConstantPoolIndex, and +isJumpTableIndex determine the operand +type. (X86CodeEmitter.cpp also has private methods such +as emitConstant, emitGlobalAddress, +emitExternalSymbolAddress, emitConstPoolAddress, +and emitJumpTableAddress that emit the data into the output stream.) +

+ +
+
+case X86II::AddRegFrm:
+  MCE.emitByte(BaseOpcode + getX86RegNum(MI.getOperand(CurOp++).getReg()));
+  
+  if (CurOp != NumOps) {
+    const MachineOperand &MO1 = MI.getOperand(CurOp++);
+    unsigned Size = X86InstrInfo::sizeOfImm(Desc);
+    if (MO1.isImmediate())
+      emitConstant(MO1.getImm(), Size);
+    else {
+      unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
+        : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
+      if (Opcode == X86::MOV64ri) 
+        rt = X86::reloc_absolute_dword;  // FIXME: add X86II flag?
+      if (MO1.isGlobalAddress()) {
+        bool NeedStub = isa<Function>(MO1.getGlobal());
+        bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
+        emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
+                          NeedStub, isLazy);
+      } else if (MO1.isExternalSymbol())
+        emitExternalSymbolAddress(MO1.getSymbolName(), rt);
+      else if (MO1.isConstantPoolIndex())
+        emitConstPoolAddress(MO1.getIndex(), rt);
+      else if (MO1.isJumpTableIndex())
+        emitJumpTableAddress(MO1.getIndex(), rt);
+    }
+  }
+  break;
+
+
+ +

+In the previous example, XXXCodeEmitter.cpp uses the +variable rt, which is a RelocationType enum that may be used to +relocate addresses (for example, a global address with a PIC base offset). The +RelocationType enum for that target is defined in the short +target-specific XXXRelocations.h file. The RelocationType is used by +the relocate method defined in XXXJITInfo.cpp to rewrite +addresses for referenced global symbols. +

+ +

+For example, X86Relocations.h specifies the following relocation types +for the X86 addresses. In all four cases, the relocated value is added to the +value already in memory. For reloc_pcrel_word +and reloc_picrel_word, there is an additional initial adjustment. +

+ +
+
+enum RelocationType {
+  reloc_pcrel_word = 0,    // add reloc value after adjusting for the PC loc
+  reloc_picrel_word = 1,   // add reloc value after adjusting for the PIC base
+  reloc_absolute_word = 2, // absolute relocation; no additional adjustment 
+  reloc_absolute_dword = 3 // absolute relocation; no additional adjustment
+};
+
+
+ +
+ + + + +
+ +

+XXXJITInfo.cpp implements the JIT interfaces for target-specific +code-generation activities, such as emitting machine code and stubs. At minimum, +a target-specific version of XXXJITInfo implements the following: +

+ +
    +
  • getLazyResolverFunction — Initializes the JIT, gives the + target a function that is used for compilation.
  • + +
  • emitFunctionStub — Returns a native function with a specified + address for a callback function.
  • + +
  • relocate — Changes the addresses of referenced globals, based + on relocation types.
  • + +
  • Callback function that are wrappers to a function stub that is used when the + real target is not initially known.
  • +
+ +

+getLazyResolverFunction is generally trivial to implement. It makes the +incoming parameter as the global JITCompilerFunction and returns the +callback function that will be used a function wrapper. For the Alpha target +(in AlphaJITInfo.cpp), the getLazyResolverFunction +implementation is simply: +

+ +
+
+TargetJITInfo::LazyResolverFn AlphaJITInfo::getLazyResolverFunction(  
+                                            JITCompilerFn F) {
+  JITCompilerFunction = F;
+  return AlphaCompilationCallback;
+}
+
+
+ +

+For the X86 target, the getLazyResolverFunction implementation is a +little more complication, because it returns a different callback function for +processors with SSE instructions and XMM registers. +

+ +

+The callback function initially saves and later restores the callee register +values, incoming arguments, and frame and return address. The callback function +needs low-level access to the registers or stack, so it is typically implemented +with assembler. +

+ +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + Mason Woo and Misha Brukman
+ The LLVM Compiler Infrastructure +
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/WritingAnLLVMPass.html b/final/docs/WritingAnLLVMPass.html new file mode 100644 index 00000000000..edc8631d0ab --- /dev/null +++ b/final/docs/WritingAnLLVMPass.html @@ -0,0 +1,1928 @@ + + + + + Writing an LLVM Pass + + + + +
+ Writing an LLVM Pass +
+ +
    +
  1. Introduction - What is a pass?
  2. +
  3. Quick Start - Writing hello world +
  4. +
  5. Pass classes and requirements + +
  6. Pass Registration +
  7. +
  8. Specifying interactions between passes +
  9. +
  10. Implementing Analysis Groups +
  11. +
  12. Pass Statistics +
  13. What PassManager does +
  14. +
  15. Registering dynamically loaded passes +
  16. +
  17. Using GDB with dynamically loaded passes +
  18. +
  19. Future extensions planned +
  20. +
+ +
+

Written by Chris Lattner and + Jim Laskey

+
+ + + + + +
+ +

The LLVM Pass Framework is an important part of the LLVM system, because LLVM +passes are where most of the interesting parts of the compiler exist. Passes +perform the transformations and optimizations that make up the compiler, they +build the analysis results that are used by these transformations, and they are, +above all, a structuring technique for compiler code.

+ +

All LLVM passes are subclasses of the Pass +class, which implement functionality by overriding virtual methods inherited +from Pass. Depending on how your pass works, you should inherit from +the ModulePass, CallGraphSCCPass, FunctionPass, or LoopPass, or RegionPass, or BasicBlockPass classes, which gives the system +more information about what your pass does, and how it can be combined with +other passes. One of the main features of the LLVM Pass Framework is that it +schedules passes to run in an efficient way based on the constraints that your +pass meets (which are indicated by which class they derive from).

+ +

We start by showing you how to construct a pass, everything from setting up +the code, to compiling, loading, and executing it. After the basics are down, +more advanced features are discussed.

+ +
+ + + + + +
+ +

Here we describe how to write the "hello world" of passes. The "Hello" pass +is designed to simply print out the name of non-external functions that exist in +the program being compiled. It does not modify the program at all, it just +inspects it. The source code and files for this pass are available in the LLVM +source tree in the lib/Transforms/Hello directory.

+ +
+ + + + +
+ +

First, configure and build LLVM. This needs to be done directly inside the + LLVM source tree rather than in a separate objects directory. + Next, you need to create a new directory somewhere in the LLVM source + base. For this example, we'll assume that you made + lib/Transforms/Hello. Finally, you must set up a build script + (Makefile) that will compile the source code for the new pass. To do this, + copy the following into Makefile:

+
+ +
+# Makefile for hello pass
+
+# Path to top level of LLVM hierarchy
+LEVEL = ../../..
+
+# Name of the library to build
+LIBRARYNAME = Hello
+
+# Make the shared library become a loadable module so the tools can 
+# dlopen/dlsym on the resulting library.
+LOADABLE_MODULE = 1
+
+# Include the makefile implementation stuff
+include $(LEVEL)/Makefile.common
+
+ +

This makefile specifies that all of the .cpp files in the current +directory are to be compiled and linked together into a shared object +$(LEVEL)/Debug+Asserts/lib/Hello.so that can be dynamically loaded by +the opt or bugpoint tools via their -load options. +If your operating system uses a suffix other than .so (such as windows or +Mac OS/X), the appropriate extension will be used.

+ +

Now that we have the build scripts set up, we just need to write the code for +the pass itself.

+ +
+ + + + +
+ +

Now that we have a way to compile our new pass, we just have to write it. +Start out with:

+ +
+#include "llvm/Pass.h"
+#include "llvm/Function.h"
+#include "llvm/Support/raw_ostream.h"
+
+ +

Which are needed because we are writing a Pass, +we are operating on Function's, +and we will be doing some printing.

+ +

Next we have:

+
+using namespace llvm;
+
+

... which is required because the functions from the include files +live in the llvm namespace. +

+ +

Next we have:

+ +
+namespace {
+
+ +

... which starts out an anonymous namespace. Anonymous namespaces are to C++ +what the "static" keyword is to C (at global scope). It makes the +things declared inside of the anonymous namespace only visible to the current +file. If you're not familiar with them, consult a decent C++ book for more +information.

+ +

Next, we declare our pass itself:

+ +
+  struct Hello : public FunctionPass {
+

+ +

This declares a "Hello" class that is a subclass of FunctionPass. +The different builtin pass subclasses are described in detail later, but for now, know that FunctionPass's operate a function at a +time.

+ +
+     static char ID;
+     Hello() : FunctionPass(ID) {}
+

+ +

This declares pass identifier used by LLVM to identify pass. This allows LLVM to +avoid using expensive C++ runtime information.

+ +
+    virtual bool runOnFunction(Function &F) {
+      errs() << "Hello: " << F.getName() << "\n";
+      return false;
+    }
+  };  // end of struct Hello
+
+ +

We declare a "runOnFunction" method, +which overloads an abstract virtual method inherited from FunctionPass. This is where we are supposed +to do our thing, so we just print out our message with the name of each +function.

+ +
+  char Hello::ID = 0;
+
+ +

We initialize pass ID here. LLVM uses ID's address to identify pass so +initialization value is not important.

+ +
+  static RegisterPass X("hello", "Hello World Pass",
+                        false /* Only looks at CFG */,
+                        false /* Analysis Pass */);
+}  // end of anonymous namespace
+
+ +

Lastly, we register our class Hello, +giving it a command line +argument "hello", and a name "Hello World Pass". +Last two arguments describe its behavior. +If a pass walks CFG without modifying it then third argument is set to true. +If a pass is an analysis pass, for example dominator tree pass, then true +is supplied as fourth argument.

+ +

As a whole, the .cpp file looks like:

+ +
+#include "llvm/Pass.h"
+#include "llvm/Function.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+  struct Hello : public FunctionPass {
+    
+    static char ID;
+    Hello() : FunctionPass(ID) {}
+
+    virtual bool runOnFunction(Function &F) {
+      errs() << "Hello: " << F.getName() << "\n";
+      return false;
+    }
+  };
+  
+  char Hello::ID = 0;
+  static RegisterPass X("hello", "Hello World Pass", false, false);
+}
+
+
+ +

Now that it's all together, compile the file with a simple "gmake" +command in the local directory and you should get a new file +"Debug+Asserts/lib/Hello.so" under the top level directory of the LLVM +source tree (not in the local directory). Note that everything in this file is +contained in an anonymous namespace: this reflects the fact that passes are self +contained units that do not need external interfaces (although they can have +them) to be useful.

+ +
+ + + + +
+ +

Now that you have a brand new shiny shared object file, we can use the +opt command to run an LLVM program through your pass. Because you +registered your pass with RegisterPass, you will be able to +use the opt tool to access it, once loaded.

+ +

To test it, follow the example at the end of the Getting Started Guide to compile "Hello World" to +LLVM. We can now run the bitcode file (hello.bc) for the program +through our transformation like this (or course, any bitcode file will +work):

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -hello < hello.bc > /dev/null
+Hello: __main
+Hello: puts
+Hello: main
+
+ +

The '-load' option specifies that 'opt' should load your +pass as a shared object, which makes '-hello' a valid command line +argument (which is one reason you need to register your +pass). Because the hello pass does not modify the program in any +interesting way, we just throw away the result of opt (sending it to +/dev/null).

+ +

To see what happened to the other string you registered, try running +opt with the -help option:

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -help
+OVERVIEW: llvm .bc -> .bc modular optimizer
+
+USAGE: opt [options] <input bitcode>
+
+OPTIONS:
+  Optimizations available:
+...
+    -funcresolve    - Resolve Functions
+    -gcse           - Global Common Subexpression Elimination
+    -globaldce      - Dead Global Elimination
+    -hello          - Hello World Pass
+    -indvars        - Canonicalize Induction Variables
+    -inline         - Function Integration/Inlining
+    -instcombine    - Combine redundant instructions
+...
+
+ +

The pass name get added as the information string for your pass, giving some +documentation to users of opt. Now that you have a working pass, you +would go ahead and make it do the cool transformations you want. Once you get +it all working and tested, it may become useful to find out how fast your pass +is. The PassManager provides a nice command +line option (--time-passes) that allows you to get information about +the execution time of your pass along with the other passes you queue up. For +example:

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -hello -time-passes < hello.bc > /dev/null
+Hello: __main
+Hello: puts
+Hello: main
+===============================================================================
+                      ... Pass execution timing report ...
+===============================================================================
+  Total Execution Time: 0.02 seconds (0.0479059 wall clock)
+
+   ---User Time---   --System Time--   --User+System--   ---Wall Time---  --- Pass Name ---
+   0.0100 (100.0%)   0.0000 (  0.0%)   0.0100 ( 50.0%)   0.0402 ( 84.0%)  Bitcode Writer
+   0.0000 (  0.0%)   0.0100 (100.0%)   0.0100 ( 50.0%)   0.0031 (  6.4%)  Dominator Set Construction
+   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0013 (  2.7%)  Module Verifier
+   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0000 (  0.0%)   0.0033 (  6.9%)  Hello World Pass
+   0.0100 (100.0%)   0.0100 (100.0%)   0.0200 (100.0%)   0.0479 (100.0%)  TOTAL
+
+ +

As you can see, our implementation above is pretty fast :). The additional +passes listed are automatically inserted by the 'opt' tool to verify +that the LLVM emitted by your pass is still valid and well formed LLVM, which +hasn't been broken somehow.

+ +

Now that you have seen the basics of the mechanics behind passes, we can talk +about some more details of how they work and how to use them.

+ +
+ + + + + +
+ +

One of the first things that you should do when designing a new pass is to +decide what class you should subclass for your pass. The Hello World example uses the FunctionPass class for its implementation, but we +did not discuss why or when this should occur. Here we talk about the classes +available, from the most general to the most specific.

+ +

When choosing a superclass for your Pass, you should choose the most +specific class possible, while still being able to meet the requirements +listed. This gives the LLVM Pass Infrastructure information necessary to +optimize how passes are run, so that the resultant compiler isn't unnecessarily +slow.

+ +
+ + + + +
+ +

The most plain and boring type of pass is the "ImmutablePass" +class. This pass type is used for passes that do not have to be run, do not +change state, and never need to be updated. This is not a normal type of +transformation or analysis, but can provide information about the current +compiler configuration.

+ +

Although this pass class is very infrequently used, it is important for +providing information about the current target machine being compiled for, and +other static information that can affect the various transformations.

+ +

ImmutablePasses never invalidate other transformations, are never +invalidated, and are never "run".

+ +
+ + + + +
+ +

The "ModulePass" +class is the most general of all superclasses that you can use. Deriving from +ModulePass indicates that your pass uses the entire program as a unit, +referring to function bodies in no predictable order, or adding and removing +functions. Because nothing is known about the behavior of ModulePass +subclasses, no optimization can be done for their execution.

+ +

A module pass can use function level passes (e.g. dominators) using +the getAnalysis interface +getAnalysis<DominatorTree>(llvm::Function *) to provide the +function to retrieve analysis result for, if the function pass does not require +any module or immutable passes. Note that this can only be done for functions for which the +analysis ran, e.g. in the case of dominators you should only ask for the +DominatorTree for function definitions, not declarations.

+ +

To write a correct ModulePass subclass, derive from +ModulePass and overload the runOnModule method with the +following signature:

+ +
+ + + + +
+ +
+  virtual bool runOnModule(Module &M) = 0;
+
+ +

The runOnModule method performs the interesting work of the pass. +It should return true if the module was modified by the transformation and +false otherwise.

+ +
+ + + + +
+ +

The "CallGraphSCCPass" +is used by passes that need to traverse the program bottom-up on the call graph +(callees before callers). Deriving from CallGraphSCCPass provides some +mechanics for building and traversing the CallGraph, but also allows the system +to optimize execution of CallGraphSCCPass's. If your pass meets the +requirements outlined below, and doesn't meet the requirements of a FunctionPass or BasicBlockPass, you should derive from +CallGraphSCCPass.

+ +

TODO: explain briefly what SCC, Tarjan's algo, and B-U mean.

+ +

To be explicit, CallGraphSCCPass subclasses are:

+ +
    + +
  1. ... not allowed to inspect or modify any Functions other +than those in the current SCC and the direct callers and direct callees of the +SCC.
  2. + +
  3. ... required to preserve the current CallGraph object, updating it +to reflect any changes made to the program.
  4. + +
  5. ... not allowed to add or remove SCC's from the current Module, +though they may change the contents of an SCC.
  6. + +
  7. ... allowed to add or remove global variables from the current +Module.
  8. + +
  9. ... allowed to maintain state across invocations of + runOnSCC (including global data).
  10. +
+ +

Implementing a CallGraphSCCPass is slightly tricky in some cases +because it has to handle SCCs with more than one node in it. All of the virtual +methods described below should return true if they modified the program, or +false if they didn't.

+ +
+ + + + +
+ +
+  virtual bool doInitialization(CallGraph &CG);
+
+ +

The doIninitialize method is allowed to do most of the things that +CallGraphSCCPass's are not allowed to do. They can add and remove +functions, get pointers to functions, etc. The doInitialization method +is designed to do simple initialization type of stuff that does not depend on +the SCCs being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

+ +
+ + + + +
+ +
+  virtual bool runOnSCC(CallGraphSCC &SCC) = 0;
+
+ +

The runOnSCC method performs the interesting work of the pass, and +should return true if the module was modified by the transformation, false +otherwise.

+ +
+ + + + +
+ +
+  virtual bool doFinalization(CallGraph &CG);
+
+ +

The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnFunction for every function in the +program being compiled.

+ +
+ + + + +
+ +

In contrast to ModulePass subclasses, FunctionPass +subclasses do have a predictable, local behavior that can be expected by the +system. All FunctionPass execute on each function in the program +independent of all of the other functions in the program. +FunctionPass's do not require that they are executed in a particular +order, and FunctionPass's do not modify external functions.

+ +

To be explicit, FunctionPass subclasses are not allowed to:

+ +
    +
  1. Modify a Function other than the one currently being processed.
  2. +
  3. Add or remove Function's from the current Module.
  4. +
  5. Add or remove global variables from the current Module.
  6. +
  7. Maintain state across invocations of + runOnFunction (including global data)
  8. +
+ +

Implementing a FunctionPass is usually straightforward (See the Hello World pass for example). FunctionPass's +may overload three virtual methods to do their work. All of these methods +should return true if they modified the program, or false if they didn't.

+ +
+ + + + +
+ +
+  virtual bool doInitialization(Module &M);
+
+ +

The doIninitialize method is allowed to do most of the things that +FunctionPass's are not allowed to do. They can add and remove +functions, get pointers to functions, etc. The doInitialization method +is designed to do simple initialization type of stuff that does not depend on +the functions being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

+ +

A good example of how this method should be used is the LowerAllocations +pass. This pass converts malloc and free instructions into +platform dependent malloc() and free() function calls. It +uses the doInitialization method to get a reference to the malloc and +free functions that it needs, adding prototypes to the module if necessary.

+ +
+ + + + +
+ +
+  virtual bool runOnFunction(Function &F) = 0;
+

+ +

The runOnFunction method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the function is modified.

+ +
+ + + + +
+ +
+  virtual bool doFinalization(Module &M);
+
+ +

The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnFunction for every function in the +program being compiled.

+ +
+ + + + +
+ +

All LoopPass execute on each loop in the function independent of +all of the other loops in the function. LoopPass processes loops in +loop nest order such that outer most loop is processed last.

+ +

LoopPass subclasses are allowed to update loop nest using +LPPassManager interface. Implementing a loop pass is usually +straightforward. Looppass's may overload three virtual methods to +do their work. All these methods should return true if they modified the +program, or false if they didn't.

+
+ + + + +
+ +
+  virtual bool doInitialization(Loop *, LPPassManager &LPM);
+
+ +

The doInitialization method is designed to do simple initialization +type of stuff that does not depend on the functions being processed. The +doInitialization method call is not scheduled to overlap with any +other pass executions (thus it should be very fast). LPPassManager +interface should be used to access Function or Module level analysis +information.

+ +
+ + + + + +
+ +
+  virtual bool runOnLoop(Loop *, LPPassManager &LPM) = 0;
+

+ +

The runOnLoop method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the function is modified. LPPassManager interface +should be used to update loop nest.

+ +
+ + + + +
+ +
+  virtual bool doFinalization();
+
+ +

The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnLoop for every loop in the +program being compiled.

+ +
+ + + + +
+ +

RegionPass is similar to LoopPass, +but executes on each single entry single exit region in the function. +RegionPass processes regions in nested order such that the outer most +region is processed last.

+ +

RegionPass subclasses are allowed to update the region tree by using +the RGPassManager interface. You may overload three virtual methods of +RegionPass to implementing your own region pass is usually. All these +methods should return true if they modified the program, or false if they didn not. +

+
+ + + + +
+ +
+  virtual bool doInitialization(Region *, RGPassManager &RGM);
+
+ +

The doInitialization method is designed to do simple initialization +type of stuff that does not depend on the functions being processed. The +doInitialization method call is not scheduled to overlap with any +other pass executions (thus it should be very fast). RPPassManager +interface should be used to access Function or Module level analysis +information.

+ +
+ + + + + +
+ +
+  virtual bool runOnRegion(Region *, RGPassManager &RGM) = 0;
+

+ +

The runOnRegion method must be implemented by your subclass to do +the transformation or analysis work of your pass. As usual, a true value should +be returned if the region is modified. RGPassManager interface +should be used to update region tree.

+ +
+ + + + +
+ +
+  virtual bool doFinalization();
+
+ +

The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnRegion for every region in the +program being compiled.

+ +
+ + + + + + +
+ +

BasicBlockPass's are just like FunctionPass's, except that they must limit +their scope of inspection and modification to a single basic block at a time. +As such, they are not allowed to do any of the following:

+ +
    +
  1. Modify or inspect any basic blocks outside of the current one
  2. +
  3. Maintain state across invocations of + runOnBasicBlock
  4. +
  5. Modify the control flow graph (by altering terminator instructions)
  6. +
  7. Any of the things forbidden for + FunctionPasses.
  8. +
+ +

BasicBlockPasses are useful for traditional local and "peephole" +optimizations. They may override the same doInitialization(Module &) and doFinalization(Module &) methods that FunctionPass's have, but also have the following virtual methods that may also be implemented:

+ +
+ + + + +
+ +
+  virtual bool doInitialization(Function &F);
+
+ +

The doIninitialize method is allowed to do most of the things that +BasicBlockPass's are not allowed to do, but that +FunctionPass's can. The doInitialization method is designed +to do simple initialization that does not depend on the +BasicBlocks being processed. The doInitialization method call is not +scheduled to overlap with any other pass executions (thus it should be very +fast).

+ +
+ + + + +
+ +
+  virtual bool runOnBasicBlock(BasicBlock &BB) = 0;
+
+ +

Override this function to do the work of the BasicBlockPass. This +function is not allowed to inspect or modify basic blocks other than the +parameter, and are not allowed to modify the CFG. A true value must be returned +if the basic block is modified.

+ +
+ + + + +
+ +
+  virtual bool doFinalization(Function &F);
+
+ +

The doFinalization method is an infrequently used method that is +called when the pass framework has finished calling runOnBasicBlock for every BasicBlock in the +program being compiled. This can be used to perform per-function +finalization.

+ +
+ + + + +
+ +

A MachineFunctionPass is a part of the LLVM code generator that +executes on the machine-dependent representation of each LLVM function in the +program.

+ +

Code generator passes are registered and initialized specially by +TargetMachine::addPassesToEmitFile and similar routines, so they +cannot generally be run from the opt or bugpoint +commands.

+ +

A MachineFunctionPass is also a FunctionPass, so all +the restrictions that apply to a FunctionPass also apply to it. +MachineFunctionPasses also have additional restrictions. In particular, +MachineFunctionPasses are not allowed to do any of the following:

+ +
    +
  1. Modify or create any LLVM IR Instructions, BasicBlocks, Arguments, + Functions, GlobalVariables, GlobalAliases, or Modules.
  2. +
  3. Modify a MachineFunction other than the one currently being processed.
  4. +
  5. Maintain state across invocations of runOnMachineFunction (including global +data)
  6. +
+ +
+ + + + +
+ +
+  virtual bool runOnMachineFunction(MachineFunction &MF) = 0;
+
+ +

runOnMachineFunction can be considered the main entry point of a +MachineFunctionPass; that is, you should override this method to do the +work of your MachineFunctionPass.

+ +

The runOnMachineFunction method is called on every +MachineFunction in a Module, so that the +MachineFunctionPass may perform optimizations on the machine-dependent +representation of the function. If you want to get at the LLVM Function +for the MachineFunction you're working on, use +MachineFunction's getFunction() accessor method -- but +remember, you may not modify the LLVM Function or its contents from a +MachineFunctionPass.

+ +
+ + + + + +
+ +

In the Hello World example pass we illustrated how +pass registration works, and discussed some of the reasons that it is used and +what it does. Here we discuss how and why passes are registered.

+ +

As we saw above, passes are registered with the RegisterPass +template. The template parameter is the name of the pass that is to be used on +the command line to specify that the pass should be added to a program (for +example, with opt or bugpoint). The first argument is the +name of the pass, which is to be used for the -help output of +programs, as +well as for debug output generated by the --debug-pass option.

+ +

If you want your pass to be easily dumpable, you should +implement the virtual print method:

+ +
+ + + + +
+ +
+  virtual void print(std::ostream &O, const Module *M) const;
+
+ +

The print method must be implemented by "analyses" in order to print +a human readable version of the analysis results. This is useful for debugging +an analysis itself, as well as for other people to figure out how an analysis +works. Use the opt -analyze argument to invoke this method.

+ +

The llvm::OStream parameter specifies the stream to write the results on, +and the Module parameter gives a pointer to the top level module of the +program that has been analyzed. Note however that this pointer may be null in +certain circumstances (such as calling the Pass::dump() from a +debugger), so it should only be used to enhance debug output, it should not be +depended on.

+ +
+ + + + + +
+ +

One of the main responsibilities of the PassManager is to make sure +that passes interact with each other correctly. Because PassManager +tries to optimize the execution of passes it must +know how the passes interact with each other and what dependencies exist between +the various passes. To track this, each pass can declare the set of passes that +are required to be executed before the current pass, and the passes which are +invalidated by the current pass.

+ +

Typically this functionality is used to require that analysis results are +computed before your pass is run. Running arbitrary transformation passes can +invalidate the computed analysis results, which is what the invalidation set +specifies. If a pass does not implement the getAnalysisUsage method, it defaults to not +having any prerequisite passes, and invalidating all other passes.

+ +
+ + + + +
+ +
+  virtual void getAnalysisUsage(AnalysisUsage &Info) const;
+
+ +

By implementing the getAnalysisUsage method, the required and +invalidated sets may be specified for your transformation. The implementation +should fill in the AnalysisUsage +object with information about which passes are required and not invalidated. To +do this, a pass may call any of the following methods on the AnalysisUsage +object:

+
+ + + + +
+

+If your pass requires a previous pass to be executed (an analysis for example), +it can use one of these methods to arrange for it to be run before your pass. +LLVM has many different types of analyses and passes that can be required, +spanning the range from DominatorSet to BreakCriticalEdges. +Requiring BreakCriticalEdges, for example, guarantees that there will +be no critical edges in the CFG when your pass has been run. +

+ +

+Some analyses chain to other analyses to do their job. For example, an AliasAnalysis implementation is required to chain to other alias analysis passes. In +cases where analyses chain, the addRequiredTransitive method should be +used instead of the addRequired method. This informs the PassManager +that the transitively required pass should be alive as long as the requiring +pass is. +

+
+ + + + +
+

+One of the jobs of the PassManager is to optimize how and when analyses are run. +In particular, it attempts to avoid recomputing data unless it needs to. For +this reason, passes are allowed to declare that they preserve (i.e., they don't +invalidate) an existing analysis if it's available. For example, a simple +constant folding pass would not modify the CFG, so it can't possibly affect the +results of dominator analysis. By default, all passes are assumed to invalidate +all others. +

+ +

+The AnalysisUsage class provides several methods which are useful in +certain circumstances that are related to addPreserved. In particular, +the setPreservesAll method can be called to indicate that the pass does +not modify the LLVM program at all (which is true for analyses), and the +setPreservesCFG method can be used by transformations that change +instructions in the program but do not modify the CFG or terminator instructions +(note that this property is implicitly set for BasicBlockPass's). +

+ +

+addPreserved is particularly useful for transformations like +BreakCriticalEdges. This pass knows how to update a small set of loop +and dominator related analyses if they exist, so it can preserve them, despite +the fact that it hacks on the CFG. +

+
+ + + + +
+ +
+  // This is an example implementation from an analysis, which does not modify
+  // the program at all, yet has a prerequisite.
+  void PostDominanceFrontier::getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesAll();
+    AU.addRequired<PostDominatorTree>();
+  }
+
+ +

and:

+ +
+  // This example modifies the program, but does not modify the CFG
+  void LICM::getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesCFG();
+    AU.addRequired<LoopInfo>();
+  }
+
+ +
+ + + + +
+ +

The Pass::getAnalysis<> method is automatically inherited by +your class, providing you with access to the passes that you declared that you +required with the getAnalysisUsage +method. It takes a single template argument that specifies which pass class you +want, and returns a reference to that pass. For example:

+ +
+   bool LICM::runOnFunction(Function &F) {
+     LoopInfo &LI = getAnalysis<LoopInfo>();
+     ...
+   }
+
+ +

This method call returns a reference to the pass desired. You may get a +runtime assertion failure if you attempt to get an analysis that you did not +declare as required in your getAnalysisUsage implementation. This +method can be called by your run* method implementation, or by any +other local method invoked by your run* method. + +A module level pass can use function level analysis info using this interface. +For example:

+ +
+   bool ModuleLevelPass::runOnModule(Module &M) {
+     ...
+     DominatorTree &DT = getAnalysis<DominatorTree>(Func);
+     ...
+   }
+
+ +

In above example, runOnFunction for DominatorTree is called by pass manager +before returning a reference to the desired pass.

+ +

+If your pass is capable of updating analyses if they exist (e.g., +BreakCriticalEdges, as described above), you can use the +getAnalysisIfAvailable method, which returns a pointer to the analysis +if it is active. For example:

+ +
+  ...
+  if (DominatorSet *DS = getAnalysisIfAvailable<DominatorSet>()) {
+    // A DominatorSet is active.  This code will update it.
+  }
+  ...
+
+ +
+ + + + + +
+ +

Now that we understand the basics of how passes are defined, how they are +used, and how they are required from other passes, it's time to get a little bit +fancier. All of the pass relationships that we have seen so far are very +simple: one pass depends on one other specific pass to be run before it can run. +For many applications, this is great, for others, more flexibility is +required.

+ +

In particular, some analyses are defined such that there is a single simple +interface to the analysis results, but multiple ways of calculating them. +Consider alias analysis for example. The most trivial alias analysis returns +"may alias" for any alias query. The most sophisticated analysis a +flow-sensitive, context-sensitive interprocedural analysis that can take a +significant amount of time to execute (and obviously, there is a lot of room +between these two extremes for other implementations). To cleanly support +situations like this, the LLVM Pass Infrastructure supports the notion of +Analysis Groups.

+ +
+ + + + +
+ +

An Analysis Group is a single simple interface that may be implemented by +multiple different passes. Analysis Groups can be given human readable names +just like passes, but unlike passes, they need not derive from the Pass +class. An analysis group may have one or more implementations, one of which is +the "default" implementation.

+ +

Analysis groups are used by client passes just like other passes are: the +AnalysisUsage::addRequired() and Pass::getAnalysis() methods. +In order to resolve this requirement, the PassManager +scans the available passes to see if any implementations of the analysis group +are available. If none is available, the default implementation is created for +the pass to use. All standard rules for interaction +between passes still apply.

+ +

Although Pass Registration is optional for normal +passes, all analysis group implementations must be registered, and must use the +INITIALIZE_AG_PASS template to join the +implementation pool. Also, a default implementation of the interface +must be registered with RegisterAnalysisGroup.

+ +

As a concrete example of an Analysis Group in action, consider the AliasAnalysis +analysis group. The default implementation of the alias analysis interface (the +basicaa +pass) just does a few simple checks that don't require significant analysis to +compute (such as: two different globals can never alias each other, etc). +Passes that use the AliasAnalysis +interface (for example the gcse pass), do +not care which implementation of alias analysis is actually provided, they just +use the designated interface.

+ +

From the user's perspective, commands work just like normal. Issuing the +command 'opt -gcse ...' will cause the basicaa class to be +instantiated and added to the pass sequence. Issuing the command 'opt +-somefancyaa -gcse ...' will cause the gcse pass to use the +somefancyaa alias analysis (which doesn't actually exist, it's just a +hypothetical example) instead.

+ +
+ + + + +
+ +

The RegisterAnalysisGroup template is used to register the analysis +group itself, while the INITIALIZE_AG_PASS is used to add pass +implementations to the analysis group. First, +an analysis group should be registered, with a human readable name +provided for it. +Unlike registration of passes, there is no command line argument to be specified +for the Analysis Group Interface itself, because it is "abstract":

+ +
+  static RegisterAnalysisGroup<AliasAnalysis> A("Alias Analysis");
+
+ +

Once the analysis is registered, passes can declare that they are valid +implementations of the interface by using the following code:

+ +
+namespace {
+  // Declare that we implement the AliasAnalysis interface
+  INITIALIZE_AG_PASS(FancyAA, AliasAnalysis, "somefancyaa",
+                     "A more complex alias analysis implementation",
+                     false, // Is CFG Only?
+                     true,  // Is Analysis?
+                     false, // Is default Analysis Group implementation?
+                    );
+}
+
+ +

This just shows a class FancyAA that +uses the INITIALIZE_AG_PASS macro both to register and +to "join" the AliasAnalysis +analysis group. Every implementation of an analysis group should join using +this macro.

+ +
+namespace {
+  // Declare that we implement the AliasAnalysis interface
+  INITIALIZE_AG_PASS(BasicAA, AliasAnalysis, "basicaa",
+                     "Basic Alias Analysis (default AA impl)",
+                     false, // Is CFG Only?
+                     true,  // Is Analysis?
+                     true, // Is default Analysis Group implementation?
+                    );
+}
+
+ +

Here we show how the default implementation is specified (using the final +argument to the INITIALIZE_AG_PASS template). There must be exactly +one default implementation available at all times for an Analysis Group to be +used. Only default implementation can derive from ImmutablePass. +Here we declare that the + BasicAliasAnalysis +pass is the default implementation for the interface.

+ +
+ + + + + +
+

The Statistic +class is designed to be an easy way to expose various success +metrics from passes. These statistics are printed at the end of a +run, when the -stats command line option is enabled on the command +line. See the Statistics section in the Programmer's Manual for details. + +

+ + + + + + +
+ +

The PassManager +class +takes a list of passes, ensures their prerequisites +are set up correctly, and then schedules passes to run efficiently. All of the +LLVM tools that run passes use the PassManager for execution of these +passes.

+ +

The PassManager does two main things to try to reduce the execution +time of a series of passes:

+ +
    +
  1. Share analysis results - The PassManager attempts to avoid +recomputing analysis results as much as possible. This means keeping track of +which analyses are available already, which analyses get invalidated, and which +analyses are needed to be run for a pass. An important part of work is that the +PassManager tracks the exact lifetime of all analysis results, allowing +it to free memory allocated to holding analysis +results as soon as they are no longer needed.
  2. + +
  3. Pipeline the execution of passes on the program - The +PassManager attempts to get better cache and memory usage behavior out +of a series of passes by pipelining the passes together. This means that, given +a series of consecutive FunctionPass's, it +will execute all of the FunctionPass's on +the first function, then all of the FunctionPasses on the second function, +etc... until the entire program has been run through the passes. + +

    This improves the cache behavior of the compiler, because it is only touching +the LLVM program representation for a single function at a time, instead of +traversing the entire program. It reduces the memory consumption of compiler, +because, for example, only one DominatorSet +needs to be calculated at a time. This also makes it possible to implement +some interesting enhancements in the future.

  4. + +
+ +

The effectiveness of the PassManager is influenced directly by how +much information it has about the behaviors of the passes it is scheduling. For +example, the "preserved" set is intentionally conservative in the face of an +unimplemented getAnalysisUsage method. +Not implementing when it should be implemented will have the effect of not +allowing any analysis results to live across the execution of your pass.

+ +

The PassManager class exposes a --debug-pass command line +options that is useful for debugging pass execution, seeing how things work, and +diagnosing when you should be preserving more analyses than you currently are +(To get information about all of the variants of the --debug-pass +option, just type 'opt -help-hidden').

+ +

By using the --debug-pass=Structure option, for example, we can see +how our Hello World pass interacts with other passes. +Lets try it out with the gcse and licm passes:

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -licm --debug-pass=Structure < hello.bc > /dev/null
+Module Pass Manager
+  Function Pass Manager
+    Dominator Set Construction
+    Immediate Dominators Construction
+    Global Common Subexpression Elimination
+--  Immediate Dominators Construction
+--  Global Common Subexpression Elimination
+    Natural Loop Construction
+    Loop Invariant Code Motion
+--  Natural Loop Construction
+--  Loop Invariant Code Motion
+    Module Verifier
+--  Dominator Set Construction
+--  Module Verifier
+  Bitcode Writer
+--Bitcode Writer
+
+ +

This output shows us when passes are constructed and when the analysis +results are known to be dead (prefixed with '--'). Here we see that +GCSE uses dominator and immediate dominator information to do its job. The LICM +pass uses natural loop information, which uses dominator sets, but not immediate +dominators. Because immediate dominators are no longer useful after the GCSE +pass, it is immediately destroyed. The dominator sets are then reused to +compute natural loop information, which is then used by the LICM pass.

+ +

After the LICM pass, the module verifier runs (which is automatically added +by the 'opt' tool), which uses the dominator set to check that the +resultant LLVM code is well formed. After it finishes, the dominator set +information is destroyed, after being computed once, and shared by three +passes.

+ +

Lets see how this changes when we run the Hello +World pass in between the two passes:

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
+Module Pass Manager
+  Function Pass Manager
+    Dominator Set Construction
+    Immediate Dominators Construction
+    Global Common Subexpression Elimination
+--  Dominator Set Construction
+--  Immediate Dominators Construction
+--  Global Common Subexpression Elimination
+    Hello World Pass
+--  Hello World Pass
+    Dominator Set Construction
+    Natural Loop Construction
+    Loop Invariant Code Motion
+--  Natural Loop Construction
+--  Loop Invariant Code Motion
+    Module Verifier
+--  Dominator Set Construction
+--  Module Verifier
+  Bitcode Writer
+--Bitcode Writer
+Hello: __main
+Hello: puts
+Hello: main
+
+ +

Here we see that the Hello World pass has killed the +Dominator Set pass, even though it doesn't modify the code at all! To fix this, +we need to add the following getAnalysisUsage method to our pass:

+ +
+    // We don't modify the program, so we preserve all analyses
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.setPreservesAll();
+    }
+
+ +

Now when we run our pass, we get this output:

+ +
+$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
+Pass Arguments:  -gcse -hello -licm
+Module Pass Manager
+  Function Pass Manager
+    Dominator Set Construction
+    Immediate Dominators Construction
+    Global Common Subexpression Elimination
+--  Immediate Dominators Construction
+--  Global Common Subexpression Elimination
+    Hello World Pass
+--  Hello World Pass
+    Natural Loop Construction
+    Loop Invariant Code Motion
+--  Loop Invariant Code Motion
+--  Natural Loop Construction
+    Module Verifier
+--  Dominator Set Construction
+--  Module Verifier
+  Bitcode Writer
+--Bitcode Writer
+Hello: __main
+Hello: puts
+Hello: main
+
+ +

Which shows that we don't accidentally invalidate dominator information +anymore, and therefore do not have to compute it twice.

+ +
+ + + + +
+ +
+  virtual void releaseMemory();
+
+ +

The PassManager automatically determines when to compute analysis +results, and how long to keep them around for. Because the lifetime of the pass +object itself is effectively the entire duration of the compilation process, we +need some way to free analysis results when they are no longer useful. The +releaseMemory virtual method is the way to do this.

+ +

If you are writing an analysis or any other pass that retains a significant +amount of state (for use by another pass which "requires" your pass and uses the +getAnalysis method) you should implement +releaseMemory to, well, release the memory allocated to maintain this +internal state. This method is called after the run* method for the +class, before the next call of run* in your pass.

+ +
+ + + + + +
+ +

Size matters when constructing production quality tools using llvm, +both for the purposes of distribution, and for regulating the resident code size +when running on the target system. Therefore, it becomes desirable to +selectively use some passes, while omitting others and maintain the flexibility +to change configurations later on. You want to be able to do all this, and, +provide feedback to the user. This is where pass registration comes into +play.

+ +

The fundamental mechanisms for pass registration are the +MachinePassRegistry class and subclasses of +MachinePassRegistryNode.

+ +

An instance of MachinePassRegistry is used to maintain a list of +MachinePassRegistryNode objects. This instance maintains the list and +communicates additions and deletions to the command line interface.

+ +

An instance of MachinePassRegistryNode subclass is used to maintain +information provided about a particular pass. This information includes the +command line name, the command help string and the address of the function used +to create an instance of the pass. A global static constructor of one of these +instances registers with a corresponding MachinePassRegistry, +the static destructor unregisters. Thus a pass that is statically linked +in the tool will be registered at start up. A dynamically loaded pass will +register on load and unregister at unload.

+ +
+ + + + +
+ +

There are predefined registries to track instruction scheduling +(RegisterScheduler) and register allocation (RegisterRegAlloc) +machine passes. Here we will describe how to register a register +allocator machine pass.

+ +

Implement your register allocator machine pass. In your register allocator +.cpp file add the following include;

+ +
+  #include "llvm/CodeGen/RegAllocRegistry.h"
+
+ +

Also in your register allocator .cpp file, define a creator function in the +form;

+ +
+  FunctionPass *createMyRegisterAllocator() {
+    return new MyRegisterAllocator();
+  }
+
+ +

Note that the signature of this function should match the type of +RegisterRegAlloc::FunctionPassCtor. In the same file add the +"installing" declaration, in the form;

+ +
+  static RegisterRegAlloc myRegAlloc("myregalloc",
+    "  my register allocator help string",
+    createMyRegisterAllocator);
+
+ +

Note the two spaces prior to the help string produces a tidy result on the +-help query.

+ +
+$ llc -help
+  ...
+  -regalloc                    - Register allocator to use (default=linearscan)
+    =linearscan                -   linear scan register allocator
+    =local                     -   local register allocator
+    =simple                    -   simple register allocator
+    =myregalloc                -   my register allocator help string
+  ...
+
+ +

And that's it. The user is now free to use -regalloc=myregalloc as +an option. Registering instruction schedulers is similar except use the +RegisterScheduler class. Note that the +RegisterScheduler::FunctionPassCtor is significantly different from +RegisterRegAlloc::FunctionPassCtor.

+ +

To force the load/linking of your register allocator into the llc/lli tools, +add your creator function's global declaration to "Passes.h" and add a "pseudo" +call line to llvm/Codegen/LinkAllCodegenComponents.h.

+ +
+ + + + + +
+ +

The easiest way to get started is to clone one of the existing registries; we +recommend llvm/CodeGen/RegAllocRegistry.h. The key things to modify +are the class name and the FunctionPassCtor type.

+ +

Then you need to declare the registry. Example: if your pass registry is +RegisterMyPasses then define;

+ +
+MachinePassRegistry RegisterMyPasses::Registry;
+
+ +

And finally, declare the command line option for your passes. Example:

+ +
+  cl::opt<RegisterMyPasses::FunctionPassCtor, false,
+          RegisterPassParser<RegisterMyPasses> >
+  MyPassOpt("mypass",
+            cl::init(&createDefaultMyPass),
+            cl::desc("my pass option help")); 
+
+ +

Here the command option is "mypass", with createDefaultMyPass as the default +creator.

+ +
+ + + + + +
+ +

Unfortunately, using GDB with dynamically loaded passes is not as easy as it +should be. First of all, you can't set a breakpoint in a shared object that has +not been loaded yet, and second of all there are problems with inlined functions +in shared objects. Here are some suggestions to debugging your pass with +GDB.

+ +

For sake of discussion, I'm going to assume that you are debugging a +transformation invoked by opt, although nothing described here depends +on that.

+ +
+ + + + +
+ +

First thing you do is start gdb on the opt process:

+ +
+$ gdb opt
+GNU gdb 5.0
+Copyright 2000 Free Software Foundation, Inc.
+GDB is free software, covered by the GNU General Public License, and you are
+welcome to change it and/or distribute copies of it under certain conditions.
+Type "show copying" to see the conditions.
+There is absolutely no warranty for GDB.  Type "show warranty" for details.
+This GDB was configured as "sparc-sun-solaris2.6"...
+(gdb)
+
+ +

Note that opt has a lot of debugging information in it, so it takes +time to load. Be patient. Since we cannot set a breakpoint in our pass yet +(the shared object isn't loaded until runtime), we must execute the process, and +have it stop before it invokes our pass, but after it has loaded the shared +object. The most foolproof way of doing this is to set a breakpoint in +PassManager::run and then run the process with the arguments you +want:

+ +
+(gdb) break llvm::PassManager::run
+Breakpoint 1 at 0x2413bc: file Pass.cpp, line 70.
+(gdb) run test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption]
+Starting program: opt test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption]
+Breakpoint 1, PassManager::run (this=0xffbef174, M=@0x70b298) at Pass.cpp:70
+70      bool PassManager::run(Module &M) { return PM->run(M); }
+(gdb)
+
+ +

Once the opt stops in the PassManager::run method you are +now free to set breakpoints in your pass so that you can trace through execution +or do other standard debugging stuff.

+ +
+ + + + +
+ +

Once you have the basics down, there are a couple of problems that GDB has, +some with solutions, some without.

+ +
    +
  • Inline functions have bogus stack information. In general, GDB does a +pretty good job getting stack traces and stepping through inline functions. +When a pass is dynamically loaded however, it somehow completely loses this +capability. The only solution I know of is to de-inline a function (move it +from the body of a class to a .cpp file).
  • + +
  • Restarting the program breaks breakpoints. After following the information +above, you have succeeded in getting some breakpoints planted in your pass. Nex +thing you know, you restart the program (i.e., you type 'run' again), +and you start getting errors about breakpoints being unsettable. The only way I +have found to "fix" this problem is to delete the breakpoints that are +already set in your pass, run the program, and re-set the breakpoints once +execution stops in PassManager::run.
  • + +
+ +

Hopefully these tips will help with common case debugging situations. If +you'd like to contribute some tips of your own, just contact Chris.

+ +
+ + + + + +
+ +

Although the LLVM Pass Infrastructure is very capable as it stands, and does +some nifty stuff, there are things we'd like to add in the future. Here is +where we are going:

+ +
+ + + + +
+ +

Multiple CPU machines are becoming more common and compilation can never be +fast enough: obviously we should allow for a multithreaded compiler. Because of +the semantics defined for passes above (specifically they cannot maintain state +across invocations of their run* methods), a nice clean way to +implement a multithreaded compiler would be for the PassManager class +to create multiple instances of each pass object, and allow the separate +instances to be hacking on different parts of the program at the same time.

+ +

This implementation would prevent each of the passes from having to implement +multithreaded constructs, requiring only the LLVM core to have locking in a few +places (for global resources). Although this is a simple extension, we simply +haven't had time (or multiprocessor machines, thus a reason) to implement this. +Despite that, we have kept the LLVM passes SMP ready, and you should too.

+ +
+ + +
+
+ Valid CSS + Valid HTML 4.01 + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + + diff --git a/final/docs/doxygen.cfg.in b/final/docs/doxygen.cfg.in new file mode 100644 index 00000000000..45b8f42e5d5 --- /dev/null +++ b/final/docs/doxygen.cfg.in @@ -0,0 +1,1419 @@ +# Doxyfile 1.5.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = LLVM + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = ../.. + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @abs_top_srcdir@/include \ + @abs_top_srcdir@/lib \ + @abs_top_srcdir@/docs/doxygen.intro + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = @abs_top_srcdir@/examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = @abs_top_srcdir@/docs/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 4 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = llvm:: + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hiererachy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../include + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = YES + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = @DOT@ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is enabled by default, which results in a transparent +# background. Warning: Depending on the platform used, enabling this option +# may lead to badly anti-aliased labels on the edges of a graph (i.e. they +# become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/final/docs/doxygen.css b/final/docs/doxygen.css new file mode 100644 index 00000000000..83b049b5f1b --- /dev/null +++ b/final/docs/doxygen.css @@ -0,0 +1,378 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Verdana,Geneva,Arial,Helvetica,sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #eeeeff; + border: 1px solid #b0b0b0; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { + text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: Fixed, monospace; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #eeeeff; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #eeeeff; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #eeeeff; +} +TD.tiny { font-size: 75%; +} +a { + color: #252E78; +} +a:visited { + color: #3D2185; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #b0b0b0; +} +TH.dirtab { background: #eeeeff; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + +/* + * LLVM Modifications. + * Note: Everything above here is generated with "doxygen -w htlm" command. See + * "doxygen --help" for details. What follows are CSS overrides for LLVM + * specific formatting. We want to keep the above so it can be replaced with + * subsequent doxygen upgrades. + */ + +.footer { + font-size: 80%; + font-weight: bold; + text-align: center; + vertical-align: middle; +} +.title { + font-size: 25pt; + color: black; background: url("../img/lines.gif"); + font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} +A:link { + cursor: pointer; + text-decoration: none; + font-weight: bolder; +} +A:visited { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:hover { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; +} +A:active { + cursor: pointer; + text-decoration: underline; + font-weight: bolder; + font-style: italic; +} +H1 { + text-align: center; + font-size: 140%; + font-weight: bold; +} +H2 { + font-size: 120%; + font-style: italic; +} +H3 { + font-size: 100%; +} +A.qindex {} +A.qindexRef {} +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code { text-decoration: none; font-weight: normal; color: #4444ee } +A.codeRef { font-weight: normal; color: #4444ee } diff --git a/final/docs/doxygen.footer b/final/docs/doxygen.footer new file mode 100644 index 00000000000..d75fff5e4cc --- /dev/null +++ b/final/docs/doxygen.footer @@ -0,0 +1,13 @@ +
+ + +
+ + + + diff --git a/final/docs/doxygen.header b/final/docs/doxygen.header new file mode 100644 index 00000000000..a520434d6c2 --- /dev/null +++ b/final/docs/doxygen.header @@ -0,0 +1,9 @@ + + + + + +LLVM: $title + + +

LLVM API Documentation

diff --git a/final/docs/doxygen.intro b/final/docs/doxygen.intro new file mode 100644 index 00000000000..547730cba79 --- /dev/null +++ b/final/docs/doxygen.intro @@ -0,0 +1,18 @@ +/// @mainpage Low Level Virtual Machine +/// +/// @section main_intro Introduction +/// Welcome to the Low Level Virtual Machine (LLVM). +/// +/// This documentation describes the @b internal software that makes +/// up LLVM, not the @b external use of LLVM. There are no instructions +/// here on how to use LLVM, only the APIs that make up the software. For usage +/// instructions, please see the programmer's guide or reference manual. +/// +/// @section main_caveat Caveat +/// This documentation is generated directly from the source code with doxygen. +/// Since LLVM is constantly under active development, what you're about to +/// read is out of date! However, it may still be useful since certain portions +/// of LLVM are very stable. +/// +/// @section main_changelog Change Log +/// - Original content written 12/30/2003 by Reid Spencer diff --git a/final/docs/img/Debugging.gif b/final/docs/img/Debugging.gif new file mode 100644 index 0000000000000000000000000000000000000000..662d35a6735d811a4145592e9514c7cf06e66935 GIT binary patch literal 20390 zcmb4}(c6>5XJBwN7aRtTje|Q}C@8$lD$;@YCCc$4vSXpB;<|cv zLlT0{rNoPb#zMGw8gF#>^q#Cf15Rs0!WeW|ejjIKbWAD-0D>X96p>uMba3tX((>bi z$>_my1!UkcCku;s% zZ>I;~6KUXAI~*hPp2i6nAOB;EBBJk59?@vdk;Q|qIwOla+TEA!ZL#tNS@DzxHqH*_ zsKvfdAGd0?(3B&L;}|h*3r)%9AR>Jmn06j@kbIhAYPbMv2H>eP10SlvXRI5j06H~| zaU3c`QeVEdI_O%5;2;vN!MWfX*c}<1HE@Ul=6A;gMcS!pnZ-Sj3%b5`pLLdUVT}Yv&)a^{!r*qIEe%>%rW{4j zQRzOh6&~2b5VCtcZ}Q&K_JTD5iejBf+~WX7cGi?m9C(UdS$Pm(b|A*DKm4cs*egeF95@ux6S(T=SWDeghwNTI>C^&HEGE?x-fxAuae_3-(y7G1qAz;py5P0HT1JtI$@ z1El(b;A;$UHKxB(MH)}cbTde@z5UoOLj+@6#g*@=NU-Dz% zGueGs2n|(%3`F(7+wJ+Q2ivBGM!W45U-NEtvGs7sff1ir!K<1|!N6|Rsay6?a}u6hw%3WT&gu$zjk-^+G(k&b8=nk+?s~e+cG4chkyV$v=F%x zVRA=5^a^p_#s7GP58+3^7p39#)O!W@>-sXBJ&0NI!M*@*GNF#1aE+V-cR%Y0{Z0ZZ z#blUV`ftUB;09uW*>8f#!KG?sKECCxY20B`8j)fQSg!=}AjfM7Nm(P3$+I$A!zekC z@4AzJ^Mul+#sQHf-4xe5fY!LsrVFXGxC#;bk3AIG=fTB_*tmu~^Nxd@af52r)W6U$Vw`u}tb` zV~yHQ;3B!f=b`_Lu+JSjZtnrfzPZ;vaWISbJ!GW4X@;@OOwN1H z{cFV1`cpJbx9jsr>;Cpv?&ZsXPn0JE&}l~*;T7$8`};;eteRw|`*Lt_r=g>zC8Xh* z`E)+a^`R!?&sGlEW|M|f5bN48)Lrr%^>=e~o?>18Odfc{?K6)??$soP)WS*|4c}Rg z34u#W9UwJ>I(0WMfbX`Q#XnGv{1Wqm2^*;pZgu-lEf<)e&k?cnz zFtbB$G5eeDl5uWwTSRV`c}+c96cWkIHea@5BcSJ4lV3+4s>7>aIU-afw8pIzVlYpO zo+J$k_3s%_4cOm_Tz3XQ3^zs<-g?ywLeSpK%{*vkM>a*qh5> z7^rp(ioG8~y0eF$U@>w9PS%EcRV))D@(3PC=^HKlGqr`)7>Rs!WE8T9Ix}!#F~(uy zmDjLj+ng4|AjY!uc9&D>wwO__Je&^f97tX9jDdBqZ{*{}-reAAD=IX52R}p>@GZ+_ zo_fy3(x1I-=^7HPfZmu5{WEB=UXqAB_7zdB#rLWI<`a)+yC){y#B7!djx(Yj{B?QB z`!^-mX>&8RgbrU4Uq4Pk)!+_Q0B%Q!|F3)ShHoy{UxJ>diW1(+_{UE#LKGKrG&QnEz4V_u27k`1~#w@9Rrq z3imQpFf!)HT-8$zmVQk*D*jYO4buq)SI+_a8#id()?k{q=x5_fOitH?>4nC%%=hGq z<+>DlR`j_wdpGkH^P-bgj>^Dm<;>6ze=9!ct~JlI@Rt6NZ9(PcPnAc8by&}s#P&*>5>ycKrs&-Qj%o97_i#S8v!sr=|wM0qYzdX3#>^`n##)c*s@*txKq(~bGo z^poCvB(=|dUer39YVkM?e5KkRWbA2jOe6*^m3aQh2J4*%0K|^ai4ohB0zA=pstG)RE&=qL*(2yCV}#p!p|O)!Yj=V z4a1@#AzpaMnIRu>bp@4d5MKl6(>KhhI&-T;JY>RK4RAh75H?_KSz92UH6A7=?8uIIPGO!`ZbSD4Mliz6ab?0~8v>5nh$tEIZ=gWA zD|yw4g|lS=G!$xe9lUV7|W_H+>ARF2zA zB21nu&k2zvM^j_F3U)5hZ(-rxQaqo2fKXI{$yWRhe;k3Pw6hr}2}_>CX}FG+R{-F) zzsj{S7>JR?YJg!NTUd93vSQCw>JxV(u%yBi6f%a2cuHw^w6q!#!S!;7#%pCq4v}bAwi*)~p-&j-mVThdY z6{H)oQnqV{46BCUforqTBUdk9^g)UChDIbHj+cWz7{<|l63PcHJJL#i{17QhCr}Ml za@Ns*a0*9-En;`{>N+S6wAi|8I1IapR`EyOF41$!^ckZh-TaFBYgd(zQ%?F7Ew@M> z8x!?cXM(52EP~kIb~P;9*`~>e&h}&cK;Nyc@VzY3FU?E3Y_kJdi)u#L!vTqw98kx* z^N~4?c6w4|7w}tCF0oSX;jPI0d9fJxviDfI)kgNNyWH^Cx?&t3vVweO<^%a1yaty%cpy^oR#Y1Q`8`a}V{J^?`# zPy49HnHb9d_rE0RNHwtpL9?%%%dU=33*3Ffj8JUXVF>v$>eU$5stiipdXe@z`LHkY z=$e*gKP{8TH|xhX?F$WYT+8)|ETMG$svd(-)B$1u%>Gi-cbMF}45kzt7kB_pFV)e| z6+M+nB?VTvw>CU9^Nb+14W9#lA^F7Xn=pu87az+S^104p_S?IR|^WF7rt2)w!OR1l<82;_**bterD6Z0B6i#~eq^?^_e(Y+Tg9u*zFGQEj)4X^9qw0L)bhYO zy-~m)d>vFt*KuC0#EV{bxw>n;vvAChy|_b?g=Mec07rBao1Sb1UX|)r#)OR~yJSY& z{rhcVp~RT}dJN$KKHM9+_g#p+f;v84|B7TW8eLFv9`x*ad%xh&SVx2nhZpN;DK7*o zx3d&fGz!Y|a9kGt0ZY+^Bq%YcYK{W+iM#}ugIrNt`DF9JX)s@pfNk`pr1PL1_U)hr z{yhL~TnnBinf}wYY%mzb*DMz1n7N$4XReOwxV0JvVw{sYiW0eZHkP-GrZ%Es z^LT>N%q8f91i#rc)gPm};%{qE;m3b26bZr5(B+{(%SM)f(qBNx&P2hS*ExvYa3HHK#qA_S;5ttlS_ih9?1M3+RR*0oX73x~%^4tlsFvfS_55 z!rb?ppM}%X?;mro1owP*{E5kW!_O5S?p3_S6=G;pbjt$4k}p`*Ia=ZknYp@Q48HhH z^Y;~yLlwAn5hvLvRkp+5x7h2XKIKlfup2gf>Sw*f3Vza5@?}wbbwW*x+T_jY5R8*S zpRX}#ok-CG^R#j8=o24ftukr!(mrl!+4~*lh(*`QNseg$UWGsq_S*w7lkaGs03ufm zZ>C+Ed5WE60nD=KR7=#zmp8LEU?c9e%m1;3{Xcpi+2^;bCXV7fYNMsA(r}kgymO1_ zM~XXu+k2ayo08Arp!y22>Yt3o(-CC?EjlrCsH_WRTmKn-XI(F~r|3w#S<#3Vla-9( z!e&@CSusSw|Dr|LJ+?}KbtK=x&)YenIIL6D3w zf`p25hqZl0t4IP|v5RpjnPd9J6BcQR?HfVyya@<|mHmmjeAA@KFRC1>MV6)%bcSE7)1!VB9Tj*DAMJ@HrL>Ytv19k0$H2H^v0us;m)254Zdf;|l_eHRDrn>bET z36^cJ7z{yY%!Ex6N2iy}WW%t7L{XClnTWr$@y+PWj8Qk@=5P~kg#c-1i`aLRXa5nb z){Wiz^HL{@CjM=mQpV#Ic-DSOpIcSnXNmeLaa-Ah7bKRz3*%RM7byEx&{x#P0DY+K zwvciv`r~y0@oyzwBZc&xVQqk}qbhih6l|o6;e~PgJbeTIh2zO6y7(8Q&bN7|@r{{y zEtMtkXMCd47IH6#n=giS&29r`sCqQ_N5O41=O$x7xe7k{6}KX&>Jn{4nU2%g;~m~< zFqh@hl8Ttgg;wisT({CwxCq`d(>v_8;$GNZG$n)(?; z`8<|*e^oMh;cG9tk)WGDdGgmo^V=BPtznrTEG+OK-~{fA0p0N1@a)QTmQV0|*vQCN z(^4&})G@mI6Rz^8%AFKKorwA;xnk->DAuOX8<+nARk)M}Fo|aYilo%LgYM-UM41J7 z<+h++-ub+ZQLr&|bE3#&hd!mVd1oIQ+V0Jv{>JY(5_?sp+p?|xd6yo2az&_K4dB~1 zt4l;?JeR1|SpgbY89sF$Qa)RMvshVONFEHbD@Q$?#O zH?Jc20%C%`JwJywy)2)4tyru?DC0T{DKSntL>snA{x%Wq1!fIUk1Jt+bd$}+CwTr+ zVMbqdKs}{OYf$N~8>+tW#oha_?P|p1_pI!{lkGIWoqwbgRkL(=QIBmFtR|dcZ+-Q& z@uPuHozm)+C^E!v6Uvl(Wh570D(CnC)Y|y)lh&rDD7@;8#%AAw#;@J00_7KyDCNf)RhVjpPMebh zs1H)4C+T0>xt$!}t+4qs0eOQmCqNhq=RWqBAo|U5;ij{-OgB@w);YN}Lj^}9W~VqX zm3p#3?$MD!3XQ|50e>)s`LD|ZiY0m4J4gCAw&#FQ2Ym59`kA~cuOOa<+arObBYdlq z+YgGF5CcDBeL&gFaenBPGDXf>4YIYnbZ;RLG&Oe>1I&JAnCc2V?|Q1kZY`lgbok|Vcq+wttFuOT*Cui5r2!AgJnQBb(kk~uF+Y_$Vrh&e~hD1Ld}9YCti8$?UAL= zyX)Nyz)AN$b088;G78WhcJZ){8D~+Ig^?R&!EihLGHB5z^$aSMk7}rYw2ukM4G*HwqdszJywshiA~-4g#yQ^8(F;ZD2psDL|3{PWr)Yg-j8)99 zDLWz#@ofkMc7a7Xf;LM{#sH6MnNqUqpQ)w5xX;~k^7`%0PrUJ_g8;OlioJc=wb}zJ zT}DjDp^(yw14OfTMr5S@IuU_ruD|b$V!jXM1o5aL<`qr|>tmj&2HcEUxxi)jETiNU zCc(1YoxF__ESb?aMpV}|pt=>^99YqH`W(PD?wt^@KexfP1y3C!`{;~-#;0F9XF{vG zJwuiXG_gE9Q&~I6DZ*@KGns)JqjuFUgc~3t$`)nxq3azA0$U#DLFv!JM!9(@z;#VS zAJ<9G|HRSlXd{f7sDXn zF^XoG=q^6G_%7W}q4zer0YHxg->wYT1tH+?g`PlIHcU)k<2ua8?-eF? z;v(txg1R+7+_qKUcfY!oT}&2Q23TGtUT(|9+~!S=3{qgE7dtrsiYT89Jy>kdY?eet z_9tC+X>fxvl>~cFbv`v?7~AMvnL#zg%_A!9+~8SnZ$(`6Ofpy7E$)&(gmHb#1Kn_9 zT@`y~omr>IWi}q83f#O7MFXBT8!&HM4}I4B@&3qra6=MszX2$Ibj6tVqC7`-5-P6n zW|Yr)Ikl?Yobof6nHIh#w!>1E@{FQ_NR)zUvQ_rXos2UF?W}GaIU-D13WbKW-0_;0 zuZHjlSz-&)m4Sf5N(5q-TKVVaIK0DiOObng$VkeL4vlJ(d*wsbIh2c-3vNJ?L6=;b(5LOpM|uLd6Cm>i`OjFg)g1byKUhhe$}gt%C4WZQs1^RS zG57IX$zCgCAG~(H>*x{;=|e5H<7ZH6;A&Pfaq@~Pb(or!ViN>@k5Hx%f!<~Unu zX>uQ5svZ6A3n}(FnWok*!G2bcjURPRISmHKvRHR! zg6SEAXa6$GrNVY}&M}S_yaOc#cbuA$Yds>ppl0aOuZ_nV!LKgvOvsBBDT!~CFz#BD z_!wR$!vEB-y>|lTom-f(`3sP$54w59iM`|E~juz^6i7oazugNzBh zYGQ{%-=$3z=leCE?N-?!`Ej_pqy|tz&Hg6ftPGMjmlU37pZ@EoxyZ>|ZI&UMTP2@& zM!A!w6(%=q&K>z?8RZbpeEs}pt7wj_)bshz&KuNFH#;*~!Ne}H(N_U=Jy(P!v|*VIq~U6$1D8SJh%(&(ERBF-$jrCg`4 zrE{GI7t35mD&a>HuN%L*?=_kj`p&-DKUKv#VTC=Gz|@?D-$`WXp;B7hJG z5hzG_o1=q6UAO$jpj9MT*KQKhOw!YMZSkuAUFEP`6Da{U3;qVmTl9jdJYBWubf>6$ zeAu>~Bk5-K^v5n7R(g3PRHg}0GegaC9<@9frjuh9!azmjH@b6uPVLsP&t=J@j)l^n zgdNNmI&Rw`-pZM9pX+E+y}u^3v<#bU@p4IZlsbRg!07KeV2r@7dEiM(Q&R6*Ij40) zqGTeFQoR({Dpjkdzy?YwM<=%%9@kFn{Bx%JT~v_PEaEHK+CPOJ7t$zsDfeBvs2!Dj z^-3yTCo?6&?EyFZio;+!@1!YP)KAkqRghRUf~yqQ7f4_Bu9x3zZJ8DR{rU9Ivo~WE zS&KoB`@1bV-%_r`u+y)-rx#j}7`cB7dnu0&vr2RqM9s)W2lLO_MpDHt&p8 z*`usK$-+i8;y7;VMA?XNEfZUsOX;zV)Dssya4St2JvQuq3lg-Ldkqpe&6K@ASg>E-1ktPwHKG=J|zBC>%!cPhPH zoL#6&HT~y_ChDi%Ft1E|0r92sR`d)0_in@<&6HQIVhC8ocGnj^1E7f}{&o&n9=yuV zg8u{;y>HEFm8*Da zs=2iwrQovU-Ils%xpB=5`Glv=ofe)+%U-4<4w5ERh>eRLnEb#2Z48z*UiG$=YQXrb zZJGVud(>COxJ4*pRR;V6HjIsn#OzM&=^0w8EDUnn6E08Co8+-H7+zJ$XS}Z zz|_LP_+q(4QW@PpefmlcgGqc!WE$$Bv-LeQWO01b05HX;jpnnRM& za+kd8&)#LQUtD&00bx{)I@nlkaN8q(mVK5yGLE-)$}BZjpyb$QD|T&)MPnYp9|%y` zi#we4!P=aHLk2s}80=(uiA3}Uyzw0wZ;Atbz%9-WPlw{UwBQer?k$cZfb&#oZsg95 zDoY-7qo#zdjrlymB5(d|hbC)UfyZ0y)V8d$bDtCYWWL0^?zFmbzTtC*diYm(9PG=q zq#)M1ATrQBrQRdh@ZqnF;o(dPKqr|vk$H2b{tza{S-qid@n6#Nz&Z28g;X~VpX={3 znq>g$g_)NRlTAH!O1nUg!d+i!*+p&lE-2By7lK}X^bm%!#;wcuUK>eTLX$Z*M1P-X z&`4CpvW*~bJSy5F!<1&`%l^==akOj<3+Ay{aV{1i3n~kIoLL<(x~)K+stzB_tgCey zahYlVI}GtlJstYw`P=82med^Jf zT>e13mpMMpJndg3QQ0<^vUbEA8Jn?ed6iW!NJEg`->Y5Wi36X0upvr1Gms8+ZJaCi z>Lh?RItN-9)1O0?O+(`q3R2RvoW`Fu8ou7V&iAUG{2ZGPz zH2t^klJ!Wb5A-4+4LfpQgE01C!^CVn<6FYSp8(hwSWyhArf7&TttFgS5cptx)ZAiG zp?5Czz{m_Y9q{`h=<^iG;^@oc;Sb3~w_TBSr=5?j*!l}U9|mZx-tQe-5t|Tw0Ti|c zZjfNAQz?aWF33vSAb;EsCH} zK$|hly8NS5NvFu?Jol?}zMLeL>BUN~gagONvzz|SS=(|+DRkFFKR9nJ-P7?2Ez><= zc)B?=KY|jVn9VEyEPq-y<0CpiTOJ8I60-GPgf-PF6PC5)ALms90SZscX#2ww{`k0Rw}1JlPiB31JSz z(UqD!L1)h$NP1NFgc1CkKvb7^f>XCb=9po8TzR3z8>q0!DEQ^W(3?}!)wW@eWDMvU zyaq==v-wfwIjPHs4jFDAE7h~i4}7(JCET8!`n%gaShJi)g%aA0thie4gzSYr5=W(X z-ISV;@tk-`1acchKd5xdI;-sUofLqZb@23KvKyJ|A*Ig%2dP)h@5YR&7Pt2gT4g+F5l%1i@l?f zcfQl1nXYMZ5t2L1X>zUh9laGDBllFaVz;^w0At$BQ++2M_rOTf5VfB^YGc4%?w%Ae z)81nA@UX|uLoxk45iFZDQSsV0F`9tEbM;lse_(T)#n+FqEBSq#I_Ae;FV`o9-#^*; zO;pA_EosbcVr(aMP3mJ5D^oEww;)-BM#SI#`%bx`Jv>i(CAuvxu@bTW!sccxM@Vb< z!YLnj`vIs%f3q3T?ti^f+W_von$q((gg+b;ZC>oyavZ!vo`M`3Da&;u_gHYirb?Mt z?+@GNQgL5K2d@J=-^_45JjZsp#Xa=ED;RvYO+|hlP$O+7^O14)U{9<)Z9n1&cq`rX z^hFom9pm*4<0A(p=&SU&F4CYoJ>x6+xX6Gc*kVC#70(qdWl~*4g~x; zIa~)ZAea!Q54okqwS|n3&5$o8um6eb8>jHXJM<|*IN1=RT;%Zcf6#9~CHu#R65(7@ z=J5TeIqoN)$ZXo^44dQpU?;Q9e_xeMhk&?3J7TJ7F2*9I#=Y zOJnjVbfagQ@SrGzhXrqc&%K_UqN5`-R(%(!TKKG0h8<|*qO>9RASoMOC|=l5kc(3L zVk0T2{qUnGj?Uo*-27gku0Q|ryBY14W?T1H@_Ybitv^$qGYBr*$*zFW1q3HDoVB<( z#v7$>GI3yPl>D|s)|*84)E)S2A197%lzfb~>)*&>i_E5xHBK+vJzy;NlPjqRN`_J~ z9VUpeiJJH!_zj(}t&uInbxh;wrwd={$11<}wK~%Kx=D6HJhS~yBCCYjZ6*04amr{j zj_M#YTOiyPc{Nx-R{VC39zmH(XO#R`AY*G_z*wWEx)-G$<-i%NY(Az%`Ab@36H!qS ziaiWv(N|SKOTLB>v*_Fb+mn|2Ay7?HHJB@NEm+6)ei4kf5eqn=j@xJ=@b8oF2N6~4 ze1Swdhv$JXKPs~~m`p5E7?|9VS}D#p z;sGG{d59o;A%F20p8n6B#_1bJog2NbnFGx+Nb0@D0yyU@;+-Gxy$KdDKxz z^q;~hoIu$wHM{lnO^(*f0KmZii8)8~R_RgTD^mme(oBU9dQ>RmhYjojFA(o+rGtQA zsAnk@PNBYJE{DMTH!d|RIuP#oKrqC--%?c$#}MbCve*z%8UXN$cPT3MA@DlpNl^-M zL=dZC`F@wfHl%!k0^MA{WwSZ<8!;TpywKa;ucyXeqd&Y zy{iIjTt~+6SGKc6SY!4C=w|@Gn2A(U zt%w~Q+g2c$0dT_1q=AfckBYcW5TO%c;7{M6^<^Y$B~Uf~+h_2r8S&r>-7OI&ewvrhh+iSrQ7&R6++?%vs{1V|ATuYG>6jQ{g{ z@c+;Wy)`kN-~0$6qTv`0Z#2AwB}(IdMFO6|Yd2(ca>6zjL= z$&+~2VpzQ((Ap@Q4byV6rAKz}het*t1?G)n51dyz`()c6~dJQbIZ1Sh5y z?SALLUy*j}BD-xnv1{nnr*i@v;l2F{7>3M~H0uYz&D0=jLX5xcEm#fEm=w;-w7Ooh^VB!`wQD0}uvx z+H&>tl{dr)Wkr)3j>UE}n_zEv3j%oko3EIZrT6!c*#McZd9G!fft6nFm))gFv{s1g zJ$}h38Lei5d^2dcgdQms){8o1j403{_ig?uWWvC4nsB&i)c3>829%tIlNNmgYtfuoEZP;OFNK|i<5fA(}<2f9>b<~Zsdald0QHbA@aCv z3cd^0{!WlI?V<(7_Z+)k;Pi84_6a8jkrO-uD3rvBAgg(fkDEY?egcoptijEI8%J2H z$}yn1nc3T)8C=OzY31dNbm?pmJ2D&8zh829DA2aQN*Ic)&d3WJ+BFGchF>agPW}ZuN#^hODYm<(e_7H0C^3EvHR`< zEwo()@f&+ZKM#Brtu<8ZjPv?iWhBjf85RUwOpduJ*!}s8ugFbNS-F%+q(!ttym7!Z z$?FEr*Oz@lLO?oOy+MxmuwJ)v-|oWxKzW2Y#|eeS@@oO3<35TyVtoq4J3ELw9^t#G zWMY{lF}(B7mJlnt=Vn!9y)2OvcCqi;J-sPO3lc3wgkGPR4T>5Iw#Df3KV|P;#>OmG z#h==D+@H+r@+c_&6LS?7Q#PH@u}hK=$1un@4e|0xO}3B7X>vb^5{`gb>V{(%*L;5Q z9Rk8L{~0*bU`rz?aP$~+SonUzqTp1_bw}Md@Vvt{M9|&Eqasmb8_1?2U+b6&_;dTC zQ#lPXukEu<53tUBp1t=B{e7oA=+J+aOh&Q7{juPH$p2PtQxP4%e@h& z*sH>{0B|^u-M2QN&|-MyLpE1jxnJBh+K9_$ypX+Ub@T29I5NFf{^tYB7iZlgMNDfx z+m8!99BhAbuJC(f(HJjGV=5!`1W#DOb$(6tfvy#3KDLz;f*S)H4lNjwzHRh@7KSD{P z`vdWwH@H9C`xbyu2@V@;kr|lei+~UCNA#pz%qNV2kRg03Yzi7{eVBh)mS| zR&h+B{e0dC#A1v0{5s%Qtaz@g-l3+`{+vkr`6aPaQ!okKxqp&rDMrEPV-2rn+K&T|iM$n3U5KJ^)HLat z%5A7AN9SO3^%{Iwq!uKyIlXKFegvRpd+)+#zNv;_0Jj+d3yhP|x+l83FKKRvUa#c2 z=F9Jp>TFMB@JH(O~{_=~`ZzIkn$vSfgZW(9gsBz&elch;6>G_a{i^46ErvhRNccv70K&+=6V;>Go z5Xe|DPM3J@ZZf2%@8cIhJlP%;6K9@+%*JmKJsdVsq7bQEpuTXAGi_?SAy{g&-6^* zc!MvhU`oc-;qvoEUid*qNjmJLGwPj?IK9_!V2^uICRffrr)S<`&Q%J=DAU7$FY_aw z`$P|MB(tN+g0Gh4O7b1oEcRWKRDbN4CYco#Qq{{UJ#jztjZmqGEAj;#HNb-A;ngpe zBs4_Bq?S{aT%dwQXkAR8h0HnLLGgoLq+f_qv5Qp9_n=QidFLViOzu;Q8?_4U{jsb|1 zQybwcV{MqGHG+;NV#B8^#LO#dANCgG;;gFOv?*EK_83GBK)vHJ_f?RymIKJ>mhNtr zi&(Z7n+Z8NUMspT^50&qZd>L?qNi3`%tavd#)$UaB5m((Z8QAYNSdhJ6!_MbaxY(Y z7B)X@*D(=h|JVK03xCFGU6XeJ^P4vzc2H;p)>f7&c#SC7FAM{c0bk-SHNv39ZFLec zmD*aBz=1MSD12fA5Xgr=300!z)=B;r4%k<4aA{0w08nGfBN*Bq-DvE%FusNB2}^T0 z0Cthw`le9|YNqg!A*R5$%VV}A;zq>&7O=K0HucQY!z_l%Gu%fV9ev62e zEjle0-7dL=8;jQJ#Pb(t5>V^86}lAA-0NvC$3JsFU~%cJ)U`%#vPbE6`k9vf9c{CWURKuM**Vuwm!S#oz77`#_0ok`Q$j!m}JQeh~4?b*Uei#ydanMo*&ib^? zMN5Ue;ip7$E`+5woBp_ALQ-6djYXO2nt5DtW}m%hZh z@-xe+l-AT<5Oe`xUvFvI1aM)dT=UL(MzI3o{AJlb4L=%8ZbXNJS7Dlp{yiF$*9-P* z>%`NJQsDI)$5&y#QrKTx&G2LDcifD4WBc0$2v1n>r!It#V5w7opnWqgCw9@=IOa2K z=~@0xPE396LGVQo{!}GCan~)<~di^`;KWYPULFZnkLBldC>U`BBjF2_i0lRSR zwak;M6mSf zY5du) z6)91M3^t!!KDW5P-{l+;yfW$*lk%XANfIp21#wlC;4fUM`?H7}cEi`F`UTPz>RPaf zU9P9MVAOMNoI7B`V~(=kh=Lx8Y#qbbaQiGs*qP4a!fG1+QWp9)ly4EDwSpXT!qh~E zSUiI!dZ<8sZrtCqES`nEt0q|Lfk8={U+x4NG0$9lOz=bWI#s2=TsQ~HA6Hx_$msKW zrrMGlI5@3)_Tg1HgThQ5LDFr_{$2hEP;D8#!>PeTi-r5#By_~sO@0^UPt!=5+bg?= zJloA4QJdkqw`&>5gk3rWZ~qAR-Kc5f(BS2U*I3tzXG1RSYKu?vbZn2mb^WjOLAS!K zCXH-lVLvUWO#QX2vZ)V`^wXw?r{mr-(5NDu(iK#ikp=35#QPe(#p#g*R;zN9tx-U* z(|l*S;mxTXp@Li?MWSW&E=qr~I9Om>Kz(}NI>qOWC?XRN#i=yhi zr}yl{!Jyw@TASTflSN-YaJ%DXJ?#;qVFT%8OhZlGje{aX4(@EM#QEi`?Ta9wav)d1 zd}dGG zQ^I3F`Q?H=Y6+t;iqu)x;iX+azU!>?u|8UY%j}mWurCoIOwM(Th)x$_K9=y@bsfiU&!eN0sxqE=E37 zUnY;m9u}Z}X22G|@i2LMs*P|l~-v{U-6eFkU$PQ}RYDhwPOPKM%Nd=mV(DmIE- zxwvbYR??+>htFQ}?lH+XGW5spZOhi9iE=eLZ+Z#YZj$!9_Z=GA1+gq0KallPosCxY z+V?Lc)6jMq>N8%5qE;pDj|eRmX*=aj2%W<7Z|f=r!76U+iVODk;#;5Y`!C!g?U(-| zM|7_Eypig#6QBE^JI@FAd&l&*)Q?Xc`+osr51jDfFl4QFDg(KEie!L&_evv2WntVq0(Tp1bZt(PApp{d}MFKs++RXi9{YT{FBAK zUhW$&<3{t{n-r)Q5liG!68u7uh-(AZka@BfGCs3vdwGk3f)ECyDf+4f%b6Mq6b+7( z>BL2EU%-iYC2GhkZXN;Uw{3W;!YW8l2&l{P|4%P&G$R90Lm*k2HBZnJG!i4`{S3u{@q5?yL^&V~<u3e-Iw%4T28$H;&>*}U{`l=N3Erx?IztN>Kc5a=^{D*P9`*%L0^Z~@ZexaQ z`1MuppCXDl7ssox!2%WArlmg|(=*9{bd}Ot72!%-;B$8wgS|HQTT`XnGApfqFS8~`ekjF60r00_$x$OM|} zJFgQ4V(}mmi^d}|sa!IfMMf_wjS3D!Cuw2G2^0<_qc9!w1V+UHQ7G6@C&mNd8l3>w z#^VqJ3{*!2KtY`xRv{4r%0STq4&Pk^071Y(!vesB0Y-JKu`lH zm>$|wlmNk|5r`5tfdW7QFDZ%~|L{r}hCn$Ya~PnSxFTeLf4>AIJTU+h0~`ac)X~QR zg@FSL)9sLjAOX07N|z#8Ms$oXCl3;&@>eL&Q)mGcEI44G(Ex%Z^q^=^g+u}r3{33# z)?`p3rb|3xtkg&Vg9HK)+zBuszz|Dy0d-}-K;MChVxlg=5o!!eLJeXSTXMoJ5nw3r z>KdSL*VzVo1I%fKtWq04zzlR9`jkLYxw4gp%*rEXp~E={BoKS`K&o_=_uWmp42n!% zq}#?m;xR|v*+!OO9Aqovfa?ybm4HI2lAMcXBPM(h0CyADQ*b*dKwzQ*nMB&pFajfy zd$pQ?tBUAyXjKQCD6&3`SZE8uCKuA@{S5RL5 zks(SEX`v8Z5s2_c;d4MW2gVLAS$GRVjRXK&W&+q_Um(BW(nRP5nh|%Q>YdQcxbwjMu-U=rw!3(lwsIUb! z%-#ws03XupMiE*1whIBZ%6Tt(L0&nGn7JCfZ8`< zKds1Gv}cN*c`(x!#z6)FLMk!U9tyWv>;Szn+$;jXMSB-~m9w4;od136QMR8Qa)p$OK4lQzEeo%V+Fy9TClZ$O1=cVMY=P=&=-)wM|=I z;XzRt5Z@9D|3sV1jP*o4tTHn10PYCmIKb%vX}E)hGV197vviq9l}EeKIci7h{QXl` zrUnw=8-P(D4h2Sf#g+i-*yZpY==~Ke+Fm5k>Bj?&^g9BFv|s+cYz_#t*>FiHvj<8K zXOl-QqZV;?H|%shK!kgszi<<#6%`a$8hXO!2`V?40i@vo65@e?P%sfhkYEUNSU^<9 zF|xi{=@B&1NLUu&z6Mey2L<>CovuKq4*^02I+Kqi_+SkKGzxq!l+IyvVgRivK@0s@ z3!8Kk0I(UsL8i-4B<95gPRXDE!t&N79jD-?%l z+J^`jvO$;DfQ9Gm$vWN}!0VV$6hevyl>NCi8g`AFaM?*P_3|MW-hp!@ zFc3l%qE3hsHGdCq=u)0kn*s>2gB<0-(hPCSP5Iz}K(R*OhS~&6Ak};!3CR+{a|KI; z6$vnTM_Lf76rctb3BdV~BbD$R)fBa^cFjVp62X@vtS)yPjjAC&iGueCBX@{HjShGS zqJK5P7)dxtStA({4P}O8k+6wYlaS4}!lRl+@PZQDxRtw-wyx(CRczSuRH$Y)GpX1s z5lA`@L<+=-*=P?z|KJz%ZH5R0sEdjAw2?zZv9-=|Ml@NX*2$ohIDF`8X`_3v|EZip z4`d<(4SXD8@RrRP5FSK)ePp(NJ`)hP)q;~DjJGjs6l`(*c2z+NLVKQe1N<}fy-iVwZo zs8<}ClLML5pg$`e!Cz3|3%16137d=(6hyGmRv7{`ft)dz!v{`dec=HGVCD*JxL_Fw zSR2bY?E9oZfHl;QvLrQfqFUgebt$lc1L?s(hT;<0a`&?p+{Xi$RV~Y6VLVA$~@G%H{p3$vpGirOoCoR!CY*#wfpF#>-fDMuiBz#rM7=NOUO z^bwpA)uRF`8$rQ!q=PLLvdEy7L`Vb>XplJ4?D)%ur~^V(TSQ{hB)6>C!Y}giLS8uY zAu-K_m4tLuLLgugA-Uwx`e6v5-uDZ@7B;*sq~@sMFlR{^VdgUQ+d_BFF)0zlUSwjx zigpAKE`A}%ickk|1;zBv(VXt?F0>wyx+-Q$4{ux6X z>e<++49t)C47uP*UozY30|@seRDAulkH|u%j|DfvdHnvj|7!;oUHA+_-7Uc@MS;x? z798+`CjbRDRFUP>!m4P`KHL=Ut-yhy-T!T1o0ve}ogU^?&HSxE?3LgUcnp^r14hZf z1@6P*6_`N8o44UVR?s7!j_V10RG*^gY{Y zDcT%0r5D10M5ZK8?p!n?;#`CT*sPKx ziIlJ;TA#^a?V{m_i^p(okTe6Oa@sswH2>8&)VEo3sZ~UIQSo z1N8M?N-e}*_9bJ6+4-?n20nw0U%Tl z5&%_8Y1ZNJ4$PrL$c21;|-1V8AbiNNJ= zE+-`F1!}fQ%AFuN77r>ir*)#CE8OIC_=N}=VGN<=b%tjeg2qHDMI6i&FJMHmV4rxl zXB5If0anNs$jF@SQY3(dYr3a?f*FTsD`ygjL4UOaTUkLq_~(8es9hPTIgF&0yhE%| VCW1z2P8!DRv4Vn1s0)Pv06T`D|5^Y5 literal 0 HcmV?d00001 diff --git a/final/docs/img/libdeps.gif b/final/docs/img/libdeps.gif new file mode 100644 index 0000000000000000000000000000000000000000..c5c0ed4c403f7c33c261fb7808c65833c63a9e18 GIT binary patch literal 52679 zcma%AQ+p*0uWdV1Yidr-UE7}8?bLR6ZQJhDwr$(pwQbv;cF%dge{gb>o2(=kd7iA5 zNJ>j^^B9SJuYwMNfcW?C9|Qyh_&@hC4FM6srq*Td*LQq8;h#8=Q8wJzJt_z6nVK7q z$r&{8>}~HKomm|JFaG~;r0?G$At0b2=>G@#Urh*TFbPSVDKOWvvexFZ*MWZ4#dg=D z_SWb2Uw^)X6g__Yc(D`6hBt4n+(o8FyKb%8ZSvZyZ?E1%jxlTYtl4YYu50(M-AAEr z^Y*RVZ}#@@zktA?;E>R;@QBE$=$P2J_&*7WNy#axY3Ui6S=l+cdHDr}Ma3nhW#tu> zRn;}Mb@dI6P0cN>ZS5VMUEMvsef=e-Pgg2&L-t2ZG@+0J`J#1w-LK z$Yrvn8VX0EaoMc4#v6*p;z`7!2&Ef~K}j@V)kZfdL^?H-#Vx`_> zYt3ex!{J1ZY+LPim&fD9_GDX~f!%i~L?XHN`u(Axe}LTR^!|jwX!7__o00mXNo9uk z`IwF-#R&&EZz2X&_PpU@)uitXmh~5_xbj@0$X#xtD@m4{J9yKRA%a(3y_4jqDqojHV$ZbO3h%Br>aeKmf*uM?WNdKUY5#zeIUaG^tZi zZls(QSH3?qbGczO1Zx|_x9f@s;V@W|KZg(qG#rP}d&f}7*?6Q` z^9hz9H~AAFT+}~tPm{3Ut+>S*jA1;&PzdZ&hftg<=VX6G260Rv13Je8(gEh07BsRK z=Rj*kC~nLAnQM=;?0+3;CTXe?;RTRL{cEHF$W-+ZP;fElmcF%~3+HA1Hv`nkh=Y=q z&bX{m#gIj0=U3^o&^)wI<=_SUqxe__3w@KcJ-n+nCnQ9YFg4!Itq=ro+F9ldYd?82 zQovd5A8vEms%j#;4JgOHR&(lhh%!<;NEqfzvd~d7U7Bb_-pjq<%pmE4P()&U@)~?9 z9n!9aFYj-5ejWsO0gc4sk9OENUmPs@PtdFy!<)$5iYpJ5CyYXdnA&-i-&H7}S- zS;j6Pg*pcJWnkTF>x%1a4cA)S$o0!M%io^YJz~U}iFF5z+ICdWSD1F}SSCgugoM)| zkG&*|8`0xle*KJnaOUiE2Xn3}i`UujJpGspuHd+jnQCIykHy+P6o;$Hsa%)qR{sfa z_I7GCpWAn2)YzLE4AiFkC1%Bt$B8l+UygA$7T>3|FQS=eA%}QhgB=T1f$d$KIsxAO z+dqEqjyZiZZ&KB>VC{!!)js6cS)q)-5B+_t|2~R{Aubd8@GzMJH1S9TKVSKw$?oW2 zU0}bxzw~$gs`p3vZ2&_jm4Xao8YJ9K0vk#;2%X9dO+;vijD+)bK4Jbu4ovx z-ipvr-z0=livI}xDk4D!#fhu1_{W(R^ZbCv2J3L>8gYyn|j7 z&}nTicW7m`;?w}g+?S6ObUCDxT5!}D^>TT179FvAZgG~$7-nR1Lm=&kMBGt&=otwR zh=(5J-OEpPHC%je`ea=sP zevlF6CTNsnewOxlMmwv2w`lifsw+H_uXy;?l-I_58i6vQ5E`cRYsiE~G^HpuFe<=6 zEV&$vP8!7*u7HV2l!Hu~U@@x@mJI85aVA*-j7>bK%hWgBmd=P2&8T%DWZPE#GK^B$ zIc6^cDCJ1lPgDS_7YiY9iB;O>I1*7(%Cp{pByk908GAQ>0N#jhj<{M^f$xT2DPlbm1HSHN zrzaPwYyBrkc&j#5!p?J=ZG!;~aU2q6hjVg6qH(3FSX-MgSz6t-ao+qt%V2aC=VVh~ zaEhmc@l_|aAne?rYadr^4YIfm`&AoDFDv-0PaD@BS}l9ch-?)f2P;;D^Tw{HnZRh5 zT6{DPZ38|xd_@F^S9T{g{o8V{*;RVzxM^MAx1m2%CnJ!&+LA&E2E6CJ6(`|2x|O3Z ziFW`7A7F+8?V4ILer|)uhv#l^4N?FTo#A1?bWZZMPLN2HLRmxFps6h$8yf%q(R^VA z^5`%+kI(wDo91vFqIqCO)biIx>M*rk1H&%fL7_3$sOOeLOiQo{bN-$GD_KNJ1Bc>2spukYboq^4D?{;IDclDS4x3S@&^%?H~tTsTe6p zj)x__V`}hWW@SMa_E+QkceIhmoHn^r7_b%SvLho&C{>R;To#k>ij7DL++jStvNUJE z_GnUEYPn9tIVDCZ4sP%EwVIHoc{M*t&Fp)nK6Z)1uV~ z-+w>Eb?WAbM|(GOxnbd+9K}7 zYbB;Ruv!{uSu`#0#I{y;;&z8M5(`qsb~-r(pwohdG$bUUZIa``XU7 z*Gw1g$4l2<9`b7sw4lS+i(1Eb(}uzO>yfa&yX}W<>d~&uJ9R|wee78m%b)G{c8-DD zWH|01x;H!9+N~q>SMJtH0;kq6q!uR0dr*q4aPNw4Ed!##jN>^NI=SoPP{^K5-<9X- z3p3}``n&CdY`ujer$D7*xL0I}pev_p3kf>(+q^3Hk@oO$kGHIGrETUp?A0S*qpe|s zdd3X{m2ebWyerX7{?*2Sf0v@yaO>OjtKn>SNBv9%9BiE&@vFdC6dV}2X^0(qawLfGq*gR=N5VYur371kmSkl@WgZgTWIH$oGjCihj5SZCB>WMq)_4gk+bvYSeLQF}V?s`h9k&!-L zsxdqv4pzz)T$I<4WofGtPFg~f35O;|+Ou+MJ7t=iC#%4F0t=q5bx|tCIh@xs!N#(! zyH@&)GGT>zdK4bfrg4CnbTYq~bPKz^qI9b5JInY3Q8fHdQC4El|CUJwX%-J#juz1; zO>#VZ1`~OPHIL!&eKZUfU~G^X-gUTXmwE5T$K9AgfQLgeRfq6if5KE&ypU9;*~+4^rYy zkQ*;#y_1npc0!<`Q*n2aK${d%Z4d`P5dH|wtN^7^m{`1r$kSv*pnj;KeNfW_Xzp0( zk`IU?$Vk#yDKbTAxr`}ep}IKT#!W@GaYFae*04* z21Vv^K^*o#?DkQB=A15Lk>3Glw?X@d*U}1k!cZQ-KjcX>Dw@lCKnx!M02cu86G>fU z=jqufPkbZij*jpYSsdJ^fK&Vy17D#PGI&w$jZ(I zmcY!!;HcC#lX9=O9IXl`R4ak9kMfsy>WM@^xeWQ7cHZA}=1Er4xF`l!RzeVd$!r4s z`XK#8Cm9qJ0}(6L>I3<80Yqs~Rbmvx+C*W|M`F-NRX;wxb*fKZQ}K*Pwb)|06+#8N z3Mo<(<3%DP3^@smSQZZ}>0KaGH-dpSC-eD4%}gNUx5=z*KtB3n);$zS<3W9VVWs*7 zF$rSb)IF2LiKR<9v306qVntokcpVpc7Bm|*0!EJLV987nfE+-YYDI-Q$Wj&5fZoJn zwo!#6-UJ`r1pX>u{z7BnykN#eXPMC=eLknU+0Q1=q$7YLc6wlxkj-J>sS}qe_j-_c z^D<#Z%zFP|F9N1f1Q9#Dw?<`H^~%&eZ&27I%MtvpCZcMxlWo&XQu$5Y9>xdZ=G|tN z)kfLaW{wfVTaj|tW*0um9%8MZBHM;t+D>vFKBCGI&zGJc8-2GL6_U^)9Nd^5-I;~Q z%Z$#NKwhHD3_AH=a9BOJ1s+cK zTy#XOxYGI&S1y)EJzsU5V>cqN`NZGok(b7z%`U2x-xQ~fcw_3rSorHzJ;eh(Tkkyt zp<%DQ;Ec>xMaz1I?Q*rNOY@seygLHxLs{n}SuTX-M48e?^P)Z$vz~;N-hWvF0ukkG z9KFyKeSh98PyR;SYUKaS@EnI87>UL+pzsx<40sJ5s45RUxm2x8=|zfcw%Uu^s=%l8 zi3ki2oxF67el}lw*LzrxfA|;#6Lj734g7vFNhlqH8&94&8S>*&SVrs+;UA(|?kRE{ zlC~+e92)+Ja6CNeQI;Ft^~f-r0+R6$`YDSuYU=7@^cr+ibHa|8hsiVBj9TgrOVAIH zr`M(N4e85`d>eH@0SuAG6vELmi+Cpc*!bH7YXu;U1tFzZN&&4nM-G<<3#!JvKXGip z-Q^_NeS!40$-=r$1Z}P_86rIWu2Z0#DV)5|aSQ35M4v>UTvRv(6^!ba9TaLUXc)*L>_?&YfMlEmtu{V1j3`YWX7+FLwkvisZu7ygOOj==C3cFfFCJC)JvtWpl=)6Hli;efffhbepJ z8~GQ1+AbNZS^nZ)LK_WI5}2`PG3K##|M2M=<3yrJQ!%A7lJ%X6t6q$`!q(Q4xR05U zV;HS!s#Ec`{1HBevbv(4y=)<%rBO4lKV1wGUKWCnXQyA?)m@C*!nU@RkN8>{;$NL$ z7LJ8qL(QIymhCtDIgQnWHJonbYg_Cm-#JUNj?J_9RW+F=knYj55otSr=)RgK&*xub zF+H@QHDZ)hvvB`BnPIz-)R5E*y9rIWk+`WsnPZjoI(urfhMBXGWs4Qc;k7Wm@T~@f zB|fX;IbLo%?Z3J;Q!}bHzwX1Z70|U%a*d3DwBDSvIRCY+ujz~9Z9j9{j7VF;fA=eg~-Z2u{t@d4eL~0kT+1~lm=zrbanqIpi+?3qLqIJhG)y{{PyFJd{BtkMBeYHVb{)XW>hcSITO)WpP7m1o z#WSbyg6C>Btz_GmN&^=ny~p%3i&VN-qx&l696KQW?aS?ncE3yJxMfAs>v)utB=hT~ z$%!fYJ=L2d@m%&>h01-#8wkIH`P_?6qASI?i!;Jw-quqnCf%Z&>)n~FLz;~myW{eZ z^Szzhy~{QEk0spqJ8b_$(cII&J6HJj7mGJ1b;Y-f)?v5uTl=#2DNSuJE7ah&zY4bf%|^)wlc>3 z)7$}N)JF=`CxY2y4yFfj|L5GA$7ye5UH*r#+VThRnJ4!%r{4zM@beSVQ=h`qtu zaIu1uQ}>kduPM7#HR*rV>n=o${>Cdl!|oi?$31Xv{~d`B=-U1`;QAb%9kNP)!(pm! zRID~aL9Igll12TT%sXGndvibe1SdaP&w{^DVn4EoQBD4nzPE2dc_yplUh|53LTK~- zf+-{r5#(B#Wm5Tco1JuMeQfd*9J!Z#yMKj#lr-jq4dgYr^C1LQQmDelLZzw#Qr)MW zx^|ejk#+zUrjF;;YDJ-wZU~Hdi~Eb-J>z~oP2Q`jJL7rrNCk#-qz7asMdWd0`57h@ zyC&KOIwzDCr-Yb0CMCJ6G$)0?nNn)>s!KY0J*y;&!^(v#jeHxMI(tk@{8I)~#;F9y zD%|@zvqv@;7ukn=HUM^uft*`I^Q(IT^E@-FdrMMBB^BG7=U={VntBdnFW$vkLT`Sd z4iDWjU-K)@Nhjt)~44c=Uxro%JpcJ2TDqn%U2k!DONc-f}7U4kXi5js94 zbWb}fA`He-Z`c!A`}v?Bum<8n4&w{4+?Pigv1jy=Oq=_lC|5 z=uA(D^w2uW3!#H*B@Y&Rk|YJ9M{1IDs<=MJ#{J?PE{MOR=Ol=hk~!CtRL(3RwdfhZ zPD+aMJUmWC2zt#*5sqTr*8-NVQf6k1xWJ_Bb7-9;%`efOW;mZ$po;Sj(xB#_IX<7} z>urgW$NAj@O9LV&GAvR%e}t$-#AxG}Ddh5&o(IcH0M24zBW2dguutCC5=>yeQ&ZNs z;l%t&fm$t3Hvre3r`Q**Uyv26@dAnps!@2V9ScnHWvef8(v5=3$u!3+t5~CHoF=G% zca_!^ z4irAs<)9yAF%70>@G&$S;i6wv%-5*RxuESr_bM)eh|G4Znj({F#@cNwEks6~Z| z!JQY`V`-QdQlY(^_RN#y9Y-x$6UECvgJnHhLdX0*jzvD~7OzVJ%|3F{|2tR8ZoFUI z-W3rUe4aE0g9xATw;6rIp}lwb-uGcEJI*LA>ICjaCjo6mdsVkeuGg}%LOgTie*YZ4 z!_?zm1N~@|4DPx$`g$RM5WUOhZEpPHdNQjGye0{Go=f3A;6QSNUD7+nv=D)Pk+5a} zY+FfiQ$pULdJ`PwPq(KDAI<;x4bU}kfji3RQDzR~T1r83hN*)?t_iZwD$tuMDs< zOL+)U_SM-`vfa{YeFK(K0Y+$_zAowDuZsD z@SS{y4mDCX*ES(xl9~KwiCa#^Yc74ra08!_X9DU*DSfiJfGsJb+hM&icr}I+5KY^y zPb-l*;9|zn*8#FoNQ(I6k>OH%6ILr#Nu&QPeJR!sfhIxo;ihjKE}>Dv5h}$rYcsN3;?u{umdxdgsm9WH_w-(9A)G=YnzK(o+?!Mq-WjV z6GBx(cLBte%Z}n4NgdVz4c8addN+;=gku`+b)NYg@NsrwvWeDq1%6|%BD0AAP}jM$ zCphY^+B$S!;AiFhx8oE!xDnGQfSX1qc512**8Dj0+GGcedLELCm5G`5uWo$x2IPrq zDV8vl3b0y@qA8vE-wD;ZDD?DPom~Td1%D!EHMq%_-Z1t|M{?q& zje+uX3rTxp>w=R_m*CA&_-_6U>+|E{n9Pmw!U~~J`yWsi8UC)}n=M!l2CP3Gl zyUL;z_oxbm;-Je|js1bSR#ho~=fq`^|Idu21=ZX-MA}C$j}l=B8;?0THEQ8o5od2@ zKbA!e-wsM1cNi`9ZBzptB@Q3bsQQv)kEM9gPRGtqYqKm6%%i~2WLreKy@`|BHoO0m z(eWE{CWFSwv}bN@U={FG{l_6o>96Nt`7dpi+Zkrfo5)hE5a61VR~+rT%hcU(Wv0iC z_K6p^UnW&nS11I$%W-zevDbK}uNTU39FL~XdPS-xIvb*;8!g+}H*7dML5+Jazn=-N zNmKb24tF@Zc#ba{+Ii*k33UrO*e-c2E`Z!eEPi?Nb|LPg3sX96eL9jhE}0xlW1Asz z9%;4~L+1M+=%;27lp~_5MN8z2g1@NoLhDHTHene!bWHq9A@8esml`8;VBb2?bAoV# z3Z~7+LZ_wEV_22k03>b;=19rX?FKn22NagBk5R3O*vS_)b{iz3h`{V?$>YM$@ zO1;vsHJ%mWGd`EV-pisbY4V3Fs8h0HCg#Bm$eq<*vU`)QmG)1~I{>ABY7 z^;%t3dNxsAGlv&s5>|FB*rVFXf1i76VXhdSi6gnW-26UHZSmlv=rit$;m$JHwUcst z2Nd#;s&&+S(R=0#VwfQc$I!p~L~+k>A9N8U>ID&4Q0-~)0b9ES@49jP_Hnob>#YTL z*&2Q0xEQ=fPhGF0+&X6Fb9T;FQ7#^LbilSkJYLPb_!AZyT}RV58vSp*9roHiyzasJ z%aQ`Ye=Poe0Ds(>tvvYdo?jCkV&Z`tl1;Dj`l==K&{70==I@sEAGGw&L3uaIgnd7; zPEs;W)w1t;h;OF!x@=Yt6AWKR@;EtEpTBbH820SpzXu;joF@F&pW#@>-b)7#r1{=j z1=dC242~~JW+*Jd(jGMOl)jNnn-TFGvi@%@!yk5rYA$=cxcg|VSiSoj-#(U`kPY{7 zvA_{VTFOR=W5pIu6;LOKLZ7N2|uBSHY}LH0Ru{F|Zfy)1F&K1GybpyfX0=mDKXnAdh>m8&Y% z770z5F($_z`2hYmP8kZ`!bG*%>7~4_2K@4#bmq)N$le6vL=p_nLiWVurl&$iC;iCw za7vUzX&)1HHE6CuJvM#uOUm8n;{zUvrK1WHAtw^blUV-2A|gyvlWvo>CGuqE0|D&9 z@0AAZoqL!M`(kcJ{r`Q-n2SYr(nTxL>C9)S(En5%72!4p%P{Eg=16eB9ATjp6ND6R zI2Lb>Q^1fOffypCd5yn=AIQZImW1?82@~VSe-?ATOiAgJyDH}eiOk^c7m!LQVIk~M z=aR}I9REhAv~w7iBqEi+!KK?#4z(Rkko!pzt9E6yXWx9JxIkRM6DF6tufe)0M4F4q zh{mp6#KcIc-bqYWNUjfY^nGJVoytry5mo`bFOo}4xMo56gu6aIaeSaei!pxm1p!e?g}~-066#`hC)mc+%iH9%68FiC;QWchI)WwANUi42_uIJW6J{-?#5%k!ibA) zVVhcG7VPpsqVh0-u>d;@k-PkR@-K{&>b9b*lQA(K;~91^5zcLWYw353@EG0Ah-+ zXQirVhpzXes`rMj@8U9Zw5TgFyRDH9Kf$`@BT=ug$`G*Mh*Dx>OyQ5NmjNZ(r(Qjx zPd~bGnH5Rrh)+7^1aBk?FpWKx(3>ikFpEXI`Ug!<0A-zuF5H6;(L*LYxQbKMPqSiu&Cyt{_Lg;?95JNT%X2GsPMlOBnhj(=xpa-~()2^k+3cd%uHyGY8QLyU1>CG$ zp4v%Q&zu}pQd^Ibov`9aPMw##-E=7e5UHv z>9)JDZWXF-iOOzQqW&G9d9~IK>WC4ly!N{_y<_3|S1WZ<`c?HxY0{18zlF-D#Ej2} z!&e>)55wCfs`|rG`WrIFCHw#+`#VU<%xOdur?R*A3CQnC83=d1cC& zvw=DKH%bMLcwvlKiVl#t5Gc{tP@gQ**!{$(wQGa+-}&l^zdfKZ{l}9IZ=i4ka89d! z8f*|P-)^82ZKf99Pqk1`~f8wpi7@A_JQbxRVLU?Ore|2Kxf}?9Q z8sJoBVH3Oe#j=mQvPi`}jzW7BIZ=^g<4tnn_&3d=0r=2Va5O(+wKf!7!r>me7p!^Q zIc|KGaOVB@IC9Y>q0mT~cS&jg$gi;J2AEsdK z6y@d+d@-qb`&9H**ERAG1c_%FfTob-tm*Emo5X?c*D|+2z2OLCJ$!Whj}>}$t+6q5bBJ5QMy6@ygAXViHc*CMPQ6uX?(hCj_Tsg@lr?@fiB6(@Q5{} zy<(=QMA+1#7q9;Ic81BLs3~kV^ckZCs-h;&bcZxE|SVLgZ|?5`G0=;<*)hwspI>b$n)oI$2~?Q2ezy z+U$LBiss@||7Kf9H9OeGuX;A%7;|}i{Qcy@c_G1$t;PBA$Q}_`9HobVOgE%l%JR;2 z4Ea{P_L@@D`ctMoXon)AaOQr-xVj|IAZ<^T`iJghc<9iua+_16tem)*dWrx}))bRF^Uu zWyQHC=Cz4kl5&w>5NfEDtz{-M%|0F&C86?EE0k7g>nLy9mr((nf(!mBV3tVeWC#I0 z!gO+~?x7Ohd89fxk^pL*HB@~aj|(35>R=9=<99gO5?I=gZwQ4hO*1o%O*|HCeqxo> zGrRI$ZAyXh^LFh8{NCSqAekh$*Ag<1GLa|Oyt=yipEO2vp&Od z#oWb*_%SWdt2V~d19?Ve;BBVig=z4S7Wnt?AEWe5v{3Pn?0hc+HuthFzVE@H%MA7r701M?@mg- zE*sdb5ZEjz@&#p_b~9~ah<;5Nz|46c5pD~7srAhNDl3!j>9C;OA`s|{FUVJUgWpjq z&ikr{c!zb?_gwkC>Fx`3_v{L;+)rE3fQ#B8r|#?0OdC7VR8iHVX^kFaZzPeZSMI79I>dXnrK|g)%^)ET4 zdX^k#*L-VJD^Fh;3U7y{MaQsIm0rPJhat~+d?Q<><;6eNbdk>d2+bU+v>JP}auL_z z^OVB14t=0ST*JeEUPG(|b(}{7byK(GHb%N7ujHore7*D-jw)-!tu-eZA_#C&<$Z6y z>&>LibkRF+{p?d>Orz%ZV2*F$Y~Ia^7{&?Lu5oL)Z55$AR* zFYuv6;Gy6ZCR#H|jhi1cWHeHD(~VXdEgwzS1z>80h0dp#{F2kFC{1&x1DotlZ1k^0_dkwqoR$PLqtG?Ki$aa}dMW1=m!BsD5@)zrIw zX5Y0Vb^#e2pRN8jj1t0l-j~M9bl=;&NlaZwR)u!s&6Yr#Ai8wuA3I~shHg5I7{lwr zfVeMZoTq1D_}S`i8!hzbg_>{_ey?~kq$Jt^kq^r?TTEK~<&xwLmKAgm634*AhZDG) zXuaEe*;ByNqZ=kGE4}%vSK)P9si~GN zdl&1cfM{)ux^}%5>lw70>5}$yE(gU7-zW2I3XCI$!ii$}Gg$Xv z;v8$a<|}EYA*(q)&@*p_U^ckvb}| zVIol|sGdX)7MvHIpXFp?5}G9wGW3W=kgK>Os6lA4-oG?_BRHwZi5z9MzscusJPtZ5 zvjmM(8Kg>5v!Xf04dCo-KH!v+V#c&XRSJlS zoAhuS5T5uG-44<`%{7<%PS%v7?NdUl7s0~H*~H*LFwCIb2JXL1K25FZ_=Df^PGynH z8gK6+#Z)gfQvrI+4%3?8txDk)=vEaBNSen^dy^O5vaoPc{Vo2AC(iPDn^%oQ<9QZ7 zYerUbd8kIkE*7EzRkI)W-93FM7=uy-B)RsLtVO~%EG9i614SSp7VT{rb8ziW`3 z|D#McRf1M?NOM@g*D4u-Xt^}B@USvMJ5}Q+Q*t>Ee6vsTAN@E?xsqf<+2zq083+s}KaL8(9ck>ch&{&zv2s zYi9BU1Y2+wZY?*WH_R!Qv)l}?9r6i`-uG@4U3jl8mM!`ovXjf#P~oMvcZ?3%r6vuPJ5bV1MZ$BYD*I9cbq_bHQ{UsiZANG=Y9}Z3PD`so>*_+)E%(2P+gr_h z)t`RZd1a6%Ys-4ANh5PfokEw)@9<(H9^&@@^c(dMx0wW`zLh!UP<3GQA1Uy*b1e2B z``}F(NGg$K5h^$t*%Kb$oM{db-86XAA(&!=5!PFtmeC)*Rw^#)xg(pMtxB2c=Q9qL zCsViW!#Hd-7-u^sU0`6+ho(p$VcIgldeP{5p+|LkE7OV5EJ>Hrhxi8XGx^g^I;e8m zIUj)GfUt!88YDAfp~bn6*vZVABvuX2`S~Bcb&-?ZhZTbhd^$HQks{X?P5kRJZ8NvI zB0khO&kweSvM#~mU*_D_$DJxYPsNjArv|dx8$B=2CXS8PDQcU;3BOUse(@E;aHdUp z=G+w>8Ba4AWh`u6E7n-(RZ_jmP~^P0SeN{?QX{~#Tts$9`^RIa>#V*W-NdK^?RN)2 z)heP1_)0?D&H!x5+J#a3Jm5DB))ey4thHe;DvgRspP25l;yf#5RZhpMWJ80tbu| zPxFMO(k4yH;==I{lrX$c^@~2UQt{0x46%1LTu0|U8*Zh1?aoBKnrmw*yJH2m#kCgi zmtLH(c-=`-2Y-L=# zE8-$r@!EBm`o{JsXy1IMdRVi3NYT~h3_c~}`YXmD=-psI_!Ktg9w3eCGi5<}uPyV{ zY!G{;E1Elx|1XZj%>UkLbqD;S<3jVy=I?7g+x{3b>oU!S{J2;I-ub0Z)Q@I6TR))h znX=mRwEA(iDRs47P}lboAOG(fW0d3xyN@d7*5N4C2Xf78j|)eJmpXE>oP9c(ZHQF-wt=g&9|P_6jjp6GW(!G8UY-O15SoT$zY#nU#>NGW=)pj1J7<)v&#b) z@R(}Kk$e=6@5O<~6%;8|x#J5Yt5kZ347Zo;nU!D~r&4-|3a-z)xdo49C?{k4-YZY~sPGAMlz-$>qs3EW`y#jzn*+G0gZCp?qb-#lxc_{A zw_tbv^9c*&1UJRupfM<;C0reI-I~R_DkpG;C$L4*;CIBkti;1d8jw`PVsr#jbl3>F zB>sktMvxX@0wv4CC;gyG@_p0A3lF&G4(x1+=3fxyI!^$vCFre-3*#lHlw*Ks^y|2z zrX!O2#OcbIA?)GP9BI>>rPEx2Y3_Jwz0F)TkAe+Se4u3W>J_T3_M|BqhY{QuA!#)k zV8DP_axm}@_L&zjG6g3vEiE!51DN)&H7x^EK*J&>5k57L#sv2%=yT1x%u=KxJ$ddd zJwDPlK{~UxBC7uJrvnheArc}Jl+^>Drr4pHgO@ak^(Ur7h}1Ka9~fB{k!}S{*NwzA z*NO#)@OZh3nwfUMI%q+BtIyfQOWUc)>CAv|@Pt6@&*^wih2P8BtH|K+~i?_UAZ(a*;n$kqmR~Dh8hm}0Qe{5EA8;0Y zK7^b$1OiC`epIoKOi5Xr^L<81vs9k?g;0oE9^fM0n77pZxKN8HPmH#RTr03hE4$4V z;D}J*fl#n7ox7OS-B%!>4u-?(g}grnFI5qrtYJ1#j8B0R3j>i8Cu(`d9*q< zja;e4f7qph3E)%bSv?O=KaEhRK@C@Uk>jFW*?^FSKvJ^*UM7lA{;eOPBeE_GP_j9_Gt-RJbr1;R4bv)gmy-yk8_py0Leed8q8mo=)CeXU3=m3H zU4#S0AbM$AP%a9DVKQ4g{~UM5n~hZ!d)9)~EF+uKuVq^CtD5KQOD8tc+e&_@Uben_ zWi(w>)Us!vrB&haF<**R8R(dt16sQ}qei^)$zB+K>Qtae)!F`SjgHQ6@@|JG;B?Ch zLm?mw+pMnyHZ&u&qiVEXMO9lwx8mS7(7ZHv^tYFJr^R`<0icN?VSgYU1T|o`>Pu^B z>sagZwKrE)jRJ~7tGfIuY5~A11?ldQs?NU6R8N|Ye*B92%tSCtM2BZ|QD0+iPIOW? zUH+~~hYmhaGRe5^vJ@Qds=#UYlH#Yr6-wTn+*>GA^M_j+r9jW*)CkCLdwybQcaH((pav5XE`dCt`Sf=7`1DW(^^9BzvBUV0IDY8s8rX;_w^BRLa?^Y-@)3m26#24gMCvumB55p}vl;1y`f6(K~uHU;E zR%7h6eJ~=MFC@L6OfEVxs>jaHBr+(QDie=XfwI% zM$&jFsVLcd7-dyRS=-g3xl@|nDbpiFI2G&DeN5SzsUzvE8ym|!UGYslV9VaN)o!J` z(*Wezb2a&kzgiSDoXr%)y@tyxzZgMx{L*cPxDkvZ`zDJ z{7rYCnuutbJtA{1%F_6UH2y6Ib?&51CZ?7N3^yzMm%vGGwrg|xPO?aVp9m}V500;S z6Coc*Oa;BC+3)Nya^GNH1`tK-xJXQ)=vLRmRJVbR*BoI8GxCh^GgFjRsq_`rJ5mIk zj}N~Qtsvj=JA+!~=g_OljCydkZsA;Q_fpEq zcnv##7d^Qr z7IKb>q1&~_#|3@qm1DKqVp*dHYoB7p9(p|@(*zA^B_(z#?rRm8Gw^+-vp{}rS+vlI zYr{li!&g^4R$xWFdxM2~y?29$+QuA=3@7CaXBl|4uJn_o>pEd@V$xu`Pm^JwqegKg zw!WsOrQl>6cN%p0xr92n(Net}USqZu>$6f5))Tvl^wXX!ax*K3;@8(kxysIk8kE9(%H>YH^((Y5g11umvFhNwedPCW-X!31w1{Z9LuK#}kTR^10HebHoq?hEc9NTwRFhZlk9WKiV9v+O0 z!-)Mb|2aeRoZ_9g=j3(Vd9G8B4&1E8e0>6hpnKQ$S>W9`;&42S@|NhHs|?nCEPy?d zHV)p1966Le=ohX=%8j*}p4Cze!Ax>|Trwoj$!KZs1tR zEs?C@8L8#tuHtqM(+C}i;m+CgPScQk?(Iz6vR%a$j$XU|&Boq{cs}QSPD5udGkE^R znXz#zNp*tGsQ=FCwtT}5m+Nc(d_~b-(-qNu`j-L&`+Kz**%UllMJi%R8CYYq9UJo9-A--c|NX0a)`l2iZ7Jtfjv5HtFal z|4k4t!#N!FX_91^yd+%CbX!gEs?KzF> zwchw^==M=vXNsTsj8EY5Xr2ES`5YbVjc$-2EXsC`@T2(U3lGao|M~w1j*kuN4vmzD zg!idW*#Z+P`0nfgFPr{>H~NM*`?25o?0fsmocoQ;@Y63!cAt;WKURk_{JN_dIE|~! zl>E$SthArn6_&k&FX`+{{YzfSm zF*xXTd1KAic4iiuaOpO2?(W&?`h6AVSLN|I1ws+>-5l!q7$%k3FeOGxPEsOP#$9$j zCLW1x0>Xic=0q~0u~}vgF{vjTd2}?#!UV@eZl-BDc$D;ZGu57r`)XSh&EqO#)s3OE+ zPBTTdLUY{JvR;R>lzEg-AcnN0Y7LdPtDvwo;ZYrF7AQET-?*lXxOeW|M`IlhPOR#y zCc=xgF)pkZE=9j2BLmJtQLfN8lNEQ)nt3Z_wt_+1f{ghy=+=r}-Q1P;wYJSH-zqI_ z8nUz1{$y*5bggjaQz}FY*7Hp%wPEFJghSur+&1UO?dT?T42^m2>evnU-Wl+D^ml!W zWAu*rBXsUny-qJL9(G)ujlPa|EGMqra-IjqlplKXu{X8( zorWI%2V#Ib);HrkLP&&Pg2tUCA9p@=W~7upBG=$@Hs$1!Zn0^{;cj)=b|WspSvlpA zqG@N5Z(`oSCQ_KdNTZo^F8N)WZ>p(akUav}V0<5P<|dhIl}RTx1{Nyfmuf|5i=g-Z z8ERyWmL1s#Lbn`O5uXqJX~w2?o;G3&kIr~rqED>$D5?JCAW&JWMrvo3B(nOGO=AWc zUU8k~SQ@O2i5kbR1e#i;Sa?EMA`Qn3OJuCkO{xr7io_}Hp8DZfU5JEm^JzxhzW1z! zXsV|ZW`Z_*4m;`gDz0nMT6-m1)zX^HveKYfuB@PJ%5J?>X6r6uqxsh+ddVX?mzRl9m*w71D^0A6mS06U-Zz4KD0~V#dl>4VQ(d*MXX7LI z<&6;xleZr`+^9+azB+q6q;tG)jI#T>`(@LvRk7j2Rld3J+11{<=3zUDxbvZl-m{pc zs|_E|j~^H~#IENG`_k7xFKzTpvfez*60*(W!s*vja*)C=c=b~zeIECSqGeBiqY0o{ ziiN)H958krQI`9bw-*AsYkNmq4_+jPz<}vZTgXG8@*vn2`Oy!0G5+w96^JLZ1?nzq z0%REkVC;R=apy7HK8fKxi7l>Ao0#D!*NHY#5k(=*5I?684e#3OL@7{)uE?~g{j z5GGqh$(MCbjqIDxhsdQvB>v`Mt~#SV`1r{+n9`A7M5Qd-;|}8$l92FABN<0IIPP7M zj$0CAy!2K_EynSch$3Mx_c%+DjZsn0OrkR7NX%y9jxSb}{z~AW*fLeZF(`JNX8H`+ z$4s8Hhihz2AVH{0XjXHbDC8ss#k0+1bW?+&>_@jEiOfbS@egjv<~02W$W(UnUGHR& z{iG?+CkAVVJ-S^H_eaqvSudTG6eu$#ImCn#v|$J(=L6&E%Y9;#Wa1Rn+$KuPlgezB z{`BKVH;SYia_*UbS}1Em`ciiC)RPT$=tI9Xv6jN=r#`hPK!edrb$(KyBuxXR=E=}{ zCbLl{C8|~7X-#_)icgEUs3uR?3|9VAqj;2RRzXsz_V*1v*^aouBCt)S|;t>(3>^mO9>N@EurySxx_7Mu!Uof%Lhk#i2S zDeL?YiCB?BR)vzCY*8^vp39Evw5;vUW+6&b&-(DNa4pzq8;e@g?)Ivw?JOw0`c<9f z@NKaTu5p{f+-s7^u2`#CVOa+#;0{Jb8I4psO=?J(QWm)}T`nnVTTxCyk+Zjzu6b_S z*1G}Ix9pUcTj|7J^)8XCdbMqGkB85p@{w7CCG35f2Sl~D@1F8K*=l7g+~GPFtNPuq zQTt0Jfn?TYf}JTk3)~HkzBh;p#$WFs2U4OzxV{UXFnDEHO!8u-x-CX8g7fD}8PiX< zHU8*0u}e)8lQfzs4smM_>Er3Xb_TG;?Tr34m0tdK*uz!7G%*G(#;xZS`7vYst)ZOcv zrQDt$ly8OMN?vo8WjR~rh`L4mf}pz(`NHv7)aRkreuMVVzsJ6Nlc z2HtV!H5FV&MWUP5RHvbQV@ZelMK~oc&{DO@S(kc{hPH8oYZsg6f6ZWFNeX=c~T zZ`e-N^_6@3=s25?&Z%Z#sL9}MZ)WOeGf!_^hv^M{ZrDu@5 zB&eqKBsqL*cQ+K#9gp^rjZV3pGc4aRy7|-BL55)87JEP62aVyvYIQd*X-KVg>Q3Fh_7nXtLfjhSIPK? zNnP`U-Q#7OR)`+U!JAr{16k>rxzOmXp9A)uYS^Fk`ma-1QH8AV9tRYy)j-53KbXhmH#>6&1e`R98;kU*(vl>>VZ>u#UBweVGlAx2)4@- zcEPu;77~`8GDKni2m0Ca;o!5OAnj%0!-*Kl)Zal7+WdW%l96E@d>`Ok9c}obUCGU| z2??`FU<&5U6?Rx1DxF7(kQaU-7>42K5QQ2>5aOZT#=+nX`rtxY(Y;WS6)vJ%aS6?& z-{nD=j*ZxuOi$WbV)3z@Cf1c2&eibQV#DzufN6r&cnc}gVoIgr1_BuYrkE>oVdMZ@ z@O@wr8etom%_j<>K?Gt7Zd{2aMWzHJA_if^<;uyumR z?BXJ#BQ+LQFODPEnPWI&n#Q@IDk9m~wc-H|QBTC8EZQ12)*>!(m+0l8)lrHPvLo{4 zU_auBb142~rir8QJzqKcV1gMNrCDG^3Zd>iRl>w0c*tG;tqZEyWB1|X!HL6WS!4kI z*E4QpKz1bhTvEWDnn->l#+%3rdVU?Qb8!pm5a zCG+3|6MTwH))_XjWm{?_IpU;Tb{_dGU<_s@A4&>lI$_UE-OH6*OUh;wCK)8%2IWcR zpZ)>oECL2xE<<6$ruu;73ErhsR_09ZP;M$AxtUzig=N*fmQ3}gfB9HxnkHiE2XUH) zaYCclwWeKa<#F1QLA~0VfLwdJ=X=6ud|sICK<8>gk_Dw1#HA#6W~56FCwQt$a9$#L z=9xk6;a1ul!G&Kz3_ycA=z~INgi7dyQfP%*=!H%w3GpRoHe+RMA%XfPcJXKSFdU3+ z)mb_Z-R;);z0)f`7O_Rdwmhf-I4A;O=#Anih0Q-=0yyXaEP$5o=l~?Z{+Av= z0WbiLekp~%X^$4kj{+dDFzJvIX{$+LM^Wh`rj{RU7<%r{lR{~fBIJ~|m(0ONmmYwY zdg-G!CHrwPmnOgh*yxSMsf1=~g?`R3z67t>sgPo1ZcLn$?&Cos z5j(fn=U|`YHFhv00Jn$02}}UeCYxxz?T+) z0(dH=8o&aGshJw<0yJu;VymNiYqmltW16U~cqe(f9-g|Yp1#hHB;HLz7NDXZ!s+LD z;_76YYK&SMZ15@?{Hm6UsR1nOus&!4*ysTWs{+ty0z_-1(kQexXaOYtz?wE_qf)Gv zDu9hLfUu70mX2zKlB<$c8d$ncx~?j#u2^CoDIAsyfX2|Bjwhc|W}>>LB(CQgmV-*f z=gtzqzjCR;I%=1WX_h8Hwr;7W2CcH9sjx<@gH|e+VrrQ(Y=d5_(Q4|qO6Wu8YQHsI zC;$;sRbi1r<;?PA$VSzyZY_EQrDVP)tyZbNl|mcwtjN89&o(H~66}mpYo=zY0pM-K zUh1VHYtw3~0$gn0QtN|mERAyM;%4p6)hCDA=W#5hx|)^PX6MTC<691wyzb2{B~%DX zm!jQlB^u>5t_>L2ZQ%y3gT^Vfo@tgwYn#gMnfh(eLhS(@?g0K!>!&g+vmUL*hUx%Z zBueINK|TkHf^FEcD{z)7;nAV2QYTe$m5bh=dAcnz^eW4qD!6U0gS=-9_^biku9hyq z`Pyg!oNu*atn1!w(;9%W@-E{NE&_O}0i-YR%I~#8Y~P;mvVv^dR^IVqC0k*q1N~s0 z@h5XGX1;3AL|z)9P7N8}7wMXZw27A6iR`!yB3Uj0kAiRrPbis+aDzs0yX0(LP7!D= zZx?px0(WQ1VvDRE@PL}FTK?k`+NbvJ-&n;XopxobWL(dda1n!W(H8Lut4u*KqzD0O znb8m-hRIY4XGL}{1PgG;lqecCo~`n*Nop`uSc>F^G5$Uo@fqW&?j~{eDk2jXXpB8^ zDkzu_)X0M33TL7m zQ%v)=u;%)w71MB_(qi$FE%b(@Rjv(Cj)lo|mm#-9Krr$uukscb!cKYd3eUpbDH0`G zuGV^HaJZ~P!0gI;G7i&h7sqnk8XD@7%@Im&A@&>3GIKLK^Dc&jST1AcNnR6RNHbo-E`%8RsxF>3^Q=^b~I3fbQrp_ zV$NYvPxF1WC`((4GFNAbO|m{<3gAfxknmy--ZXASbpvsAS64OXo~Qr{HTKEu9}Dv^ z10wdQ^<3*+VxMZwer~Xlv8y2_w_uoEb5b-9s{WLvpEl<7iuFJFaj8VI_w}4hZ!q|p zt798ZUVG&{&$NC~HgQxo<6(9k)6Hi7XOc%_L=7v|W5)2i4m3d{MMzo@k$$Y0%^5#ll3DT8;W}^_^mjBVRKLaCU#eob~E`|2NSp1xM6!Z zbN^EHR=G=F*IfO0YL66=?x*131e^>6zjdHa%zbap@9rxVYrFL|5)kDLei z>Et4#n|1MF`$A7AZ8tmA;O5G?NS?cTL|3G4bIp@2dOk?Gz-T7AXgeSdyRyGK@A>j4 zzx86E)u#3 zrkdAd-n{6=b!L#abW#I7;K=;3ds(?luxU#jt&6O)+YY@d#d80ONE4;CAGZk!NHH7W z)4TY$e^?w-i?6RD(GRB#WBsK=inI4;)T>aLk91%E$iwqO*%Npr+mhjJGY(_CQ?+x~ z_WcklIcl2t;cxqC_k2xiy~#J%s;(_c%{|%Qbs5E1fdPKkZ8XiZP(ssf(Bo{(5q0KE zzGTxhzgzxq{x`9%ycMj7eK?DD%Wrsho30Ux`{TcQUZQ@7_I{t@I-p0skTZVqLu7Q* zegb~|-%WUu9=$igeZ6W^Ihl8-Cq6p|f9ek=z^A;vz@NR>H07tVx-+ojxrch^J%np= zlZQI!Q{V4nqN$^>zNvI3$8!UM03ePdL7r%;lIGg3a9qkL@zOYM=XI#cLD4k#dVW61=_PnpkAH9RXncN7 zcYQ>0f-r3WLyU)NiB(igj)R7OF<+6FoSjW>UYItZ`b4U6qt&v!i2=w!d_6nzzxYT)4)&$;#4Z&D!0vSFOn1Y+l?_)8?0( z>0-Rjtn5aa!ay@e@z&?rxVrdzV5G(gOhc_$zInOY4UDz0A)1pERxhf_ohz*##Flle#kPo_$h1S(=+m}v6W8L?j7;Rjvo3!eIG1q3PFe|`)O-Gz z9!bB9Au&rCwy`(Et|UYLYHXcnh-Ed)HWg{@-rYEVbWXi+_}$N(^x*TSyJ{Z3r@^+) z%kl3Gl*M5`2M)BL(%!dm>uk4wY!~^#7t)8w?M9*z5Ii z<`{nJu|(T`;EDAZOym_voqRMkI37>%@kh~XSamcYQ_dtcL^>o%wG>oH31;Dj7?QP} zgAEll6>=z!$XSI2`UZ@I3?hT$F}X>DT`9_mHXkjg<%b$HqLpZ!dv&F_;DIb=w-}R8 zidQ8?G^)3wQfWmAh%4XPeQ~ zX=jsXZjt3qmJNDhal_fz#-fZi>L{Qx%GnDb@r3vZpVis64}byAxu>6h=7(n@l);E) zsFU%?P@b3tV(6g;mU#xFdpL@ucFv`#5vZ4bxMx*wn#5_R+Jr_Rs$(8Ftb&nRIp(X} zEhi|IU8yNttdgD8o0=Zd8YiaA^0r2iOzCIYW||VWY@mI{$SbmbO!+OitkSC?y!YZI zQG93(^{%SBd5DO$^XjUZIf;J6tEG+vB4oPDP#a#dbV6&VixLy}>&B_#t7}}i7Mx?q zg+)80D~r+xB*D#w`!SE?lDL?|`X;FHRm8SivB$~c?32qJt79>6{=2f(GM35>opEj# zb&;~EAtj*}8_$+oZ(1{(8JNxg!K$@WDl5%mkvMR*zoxGYr7R2K71Aoe#2Zy!8ZGb9loJ zPWV!k*C=n~hpr}T?E2nEyVr7!2;GQgKGj?0-Xh#V9f?u_n?~s6?Z@cR#0bS5z0u?r#|hJN?2%P;q9-N|?sD{mEO}dtvX)7&HqS#fn{`VGTEAJT7*SggfNdm(VCGet3~g<052# zVAwtTtV%Xv?A!h72&wR8afqmM2T%GVgurnqdYkGZ_P!{{9)b{K2`nQW7pcf8P6lCW zY-6>wq(ZZJv67a&r6>crgmV#3YH^g5Dt%VH7MA`plG!Q-o?3=EkhOA^^MNIre1S|# zZcmAPk`{xgiOV_S(3)ETf+s&|AsJSqQr>)$DKkj60;&?4@O-8qWhG77$+BNe#3l>1 zxy?uFGI*(Z=fJ#k$=j5Xn8k#jI;+V<*7XsS5Z$9Z2bsM;?sAF#EKel$SxM%&u}cN@ zQ9%ERGCfLEoyS4w85PPrhRz0vb*v{jCrZ-IOj3^1Y9!GnG`E}TG>TWOsX~_t(FbxZ zXEf`Y5IMNO1+6oG`e|KK^EOkOo;0CLy=rNGDn^z(RhiE0C+J2=Ma3|6FDBJ$DfN^* zn;P?eU!`7D1!~c{Ui6t2($Pw#2o9HqwEl#1i5XV0B|KlwlBh*(*a+>KC&RXnv3DKp zbmAJjiXc{E;G?Ql$r{#qy3%M|-6_&6I1yx4W-!%!9%t{S*lucXliytIS@Fj&%Bs$? zQdO%@UAtMxem1h6bwOrxCl|?e_9#?+%S$0Pu+|3iwJ0^DTUja|+cpljk(;V!@7Y`U zL}s|&3t^~eWL-)8E4AA#glV%X+ufP4k$9A@Z2x*(xcZf8A_^KiPTSk?+Htmj-7mhp zJE-%m5uZriZFVTST5-7O-`cCTR%@huGlECR{CjY3dG|-BP;Lm74bDubA6+3B$Cm z;kIML6|LEZj(5YkbZ~Xki!y&M_=d9$R`xo3y43}^fI^Fe8fzKl*Ce>Y87;htzubS&hGwC|Or?r5 zM!QGTxv-fzSzH^P*(nwJXfGRIr?=GVM4>vV5Bx}Z%eCJS4=uaZo?Y@n@1ge&HH|;# z^PiK_zTWm7>wKD%EgD?xiC(zNna*${Lly4tMmCj~e&D3_EQrs@xW-w{cdz>$>_HDa zsGU2{qF@~9a>M@7${{~7B+KvAjyAiJBOf52Br%m{)B4USxy-(Q{_EC2`*^Wf`oE*> zl+9T^>oNN5e7|w=G#|~m8){Qhb%xgG&U~E^Y2Mft-rs;1{jf>Fc-R<*P$&TV%;Ksy0*prIQyB)vK-&(P;{0_%C%XWvv$9CHt+RzEEjWjA%oL&Xh~v3g#s%2 zCq5k5f&PNVVIUZS_{U-?=s#hIS4;+c3YdJGM_f$^gX%XnW+)F(M}@-%UXTV%BXxov z$9O;Jh3f%^1PBrg$W8}$eSs)zOo(Q&hYru@NFOA9xTHC5$7M5-YlvuuUC4)N=7%~6 z60qfMLWpigCp{jhB`?T^_W^}ev0thvN9-YDyB8OvB-KFc_a3Pdix_lD{Si}9Fd6a{DEHE5pLczOtS;n;k_xP}4=bd8owAk#F=aD}XL zey^yJ?X+e|_>P-+Wy3&^0l9%|rD@y3U&kg{yEtiE=#fZ>hqG9Hi~~{?BosKfYD(B~ zNC}GT*L4qRZI$+bPStB8$z4%6SUEY0KG~4asFC96R)t4@u11u~R%)Eqj`_%uFd2eQ zSvjkSD_41zSom?}xO{K9liBEl(b$q7RZOO5gOE}VV;N6nnU#0BN|)$`x|fzh>6SEU z8anwfVO5vHg^|nRcl|r5S*U$(3MYDw0`==V+XK8IrH3mGB3U z!P%2&HfH|CIe@v8-~=ErwUw5*fTsC9%sHN_*=82oI=_~~4f^eBj)H$7&DS3%vbHtKDuQ_Db(VgDO zjr}Ql{|Q`3beZml4$7yO?si?;>7F8$nw9xeNko*IC8768fEB8r45^$Hx1RHpZK9Yf zHhPkTf|nC2W<2%HS6Z!#I429~2bYE}LuR-k<2QR`_+ z=#`?6d7?&oljxb0ys4A*^Nc*1gc%xmwM2>E7+Vu{d$n1L+EkZi8lbfKld?IRYe-(I z6%kIObUy}$wy69(1`lYO@fsNX7$+aRSN^Mi|o0UqM zi0YrG%0FASqs@qr@Asx`362Q|qQo|mj7p>Nxp(i;tC0Gun;5L3I;xvmsx*15S>Z&K{1ZHHih!y2yY8lF-{v7zK)2|II3sEqyc zt{WRvJUXwqO0obeiAd8)7MO{)5~XHU%dC_FD3(8lurkkm%8Z2A2Qv0%w z*_sjSv!9tcr;4##`&9B89~P>DKO43^reb)fj|Z5pBdWB8d4ITxv9w1`bO<}JIgN5l zQhs`=mV3FFo4HQQd;W^AY4}|2>WSQvTMJ~g&bp_<{t2&8y10_7tB0GZol~%e>b6mv zR|9anxSPAWySu#GyT1Foz>B*#%Xyu9u87N2p=+x0QYd9&x|6HAi%GO3Nwl*jKo4TI zEAzEpin`tvyx#l0;0wOP>pCMfzWl0zYdWqOcDzkjL|2-N_&U7}$heU7w%7}zdiu0* zYrKk(y9R)}2oSykJixwdzV1}M{5!SC%br225=={k?t8Mb^SFm}IRhqzvr8InOSL-N zZb_881uy_19Ks;1yCggS2#^4{djJa{!vA}_32?#+umCh{00%(8w>z}`+DqHopzWEy zV*6`ryEi`cz7TuAI@l8%d_r@3v@1nf7GtjdpX&=He8VSvyH_m2xXS=7e7g#u!Ua$O zH#`6aK*BRT#s@IQ1gyj4%fm@qv0TW&qASE#>&Dt>xIK!*#49MRd$yC=!QiKI*NVCg zO8_N2!ZG~9S$xF{zyP;v!y=3T3NQc%fB+=i$hvy~2Cx8-EW!zp!ketZyUWI)Kg_8(>8Gcouo9>8iI6 z+p_03>Zh7bC$h+JdVF#1j3-y9}nU zo5AP1tmJd4U&sg|Z2&5b#WXz7B0SguEW(ov(Dba>&pg;RtjV1G(q3G{j(pHvbV2lE z*1jmPrb&9n=F=vM(=&^P1^ySKt4h~({hn~>&bqA8wb5rIYREV|+q7-j*i4K3pxF({ z*|(*+zWv)<8y7|!q8lxud#ez&{5RVB(|pX@9u1!*wYjWN+tf|l0Gh-dTM|gk%^aOO z)&1SJt)9!~)~x+RdJU0XcDfy1-02*(tqowXO}#$=-t_&w*S*K!HiGQ!X1sk}^$p%i zx1+=juDXlXBT-dYRXU>@edo#P$>L@mDC zK8`9L9>P{E)k8i2T#UP4EW-ax#{JyPP5urxI^ZYX-U)4L>7C#TzTi;FP5Fy(M~K&~ zYjEERm&O89%l)?@>u^Ah$VkrEm~POJTmX_x$(D@8mb?HEu*sbq-U{<{Jg((hGq|V? z&H^Nnsm-TVNyz^<<3U=pI4j>5r{hR@=91pS{teKG?94(=&jGB-(VWc7EbPwg)uuj$ zADZe{jdn*|K9T!-CS#7Y?3;FnC$t1!?b-ckhrZv3t|W{f zywYzD)zzHRD=p9Xp698!@6vAY)DH0Gjz%P}&aw_zw2tTo9O15>UaE!4Jm+}~ujsia z=ruy|Bz)5IeDRH4)ggS<^SsYpE#f#1?Hx|=&)q2xe4N=%OX0rWKz*KG9!~RU^E56@ zW2EcA>KG4S$iFAoMI z>H=Cegs7dX@7=Ax#*x2~A&>h7S@NzeT3IjflOMbC!26ny`Z%9pJ*)k=M;3h>SmJj4 z0+js9U+|0A{Lx=7Hw)JTcKHdvy{A&WM}6&8-#y-u_pUot;lKG%mee2sh$C5=Cz`4& zI}!sN%QIcuH$D(8UlMySC>#cX#3RXw>?xPdq^Nn4GN0CKaY)7bxL(!vd;OVyWS1Ci z4U5@n>h28Kx}Ej;N(nT=)2O>vo)4g3VT&1JqT(WBqod**q2b$PisaMfe{(em@Z1KPYoxEduQjBSBfaq>;=P%w)%wF##ev z1kqecVKAeW<8%{e#f+n%@x126O%stammX8sMT-k3-UNHE)`t2&OrX7TF{xK2T$%bfQ zv})zXycqfN;(L_u2JUQA5@))E6&gJZSq($aewES$@p- zDCx7RhaZ7WnK)*+zvJO98v3~C=O-!F9c@W^aXk&0S>H{&a&w`!*Uh}>yR>G!*pag@ zcD{Z0x3)}^FU-C3`su*&>ol%WPkK2mqZ@cd$wy#)&b5Wqa)7B9Uwa?m}>D&*q>#Lu|(Ebq#08Oh|ux2po`;~D4uW;+E|1f`H^H{TGR~~6ocRG zIHDh74fmmrMaF@k5In9XEnewnb#qPOmdXujS;HCo|A6=4K$5ar%lmHn7Dko z4V74Jg_uD^js&Gt0;+gmmEQ!{6O1tisHK=Sb~$KPY0B8(d}Q9jVUK?P$Bm-XAvU3R0RPI)hz)nGEJgb;$CUSg(vdyQhBBHu+RFceDtq zm3=zuAfPKP$t=8oK(wr@^%l8|tl5qGStIb-x@~qZJu)!8Zhaf<13!#)T*sy|~g`^=HIc~9=U7c}DQ znzjz`-JA4F+_UETBt1>xWnUHZH@|oB>WQ+eZ2tJv#}-L#2xr{0Rir-wIw>SuHO?4Ke;J*^*I{kIYdbhKm!p77T>F#P(|MBKv}s!z!|kiSAP34|8InCoWHghkBaPX85E8fiaCY>|F5r(MEVE=5z;};{<6) zK%04Se(JJe&)&GfFgh(vWJF;Xjo2hpYhxSuEXfiidV#9 z12MJ5OlDA!$s;7na&<^huC0}ySt25}{$`U3cCeJQTBV@yNFP=vQ9~)=CD@!2Lo=S| zYjeAw22Y8~BSBJ0T$C9R7YNNpo^U$4q~=R3Nj^z_Wt+dF<}!^%PFX6^Sp(%8IGI??KcX{`StQRp z;TaBb3e#i%n}^?s^|otzF?uP(8#Xs7(RYAmmfd7sIVptDgtl{`sbeWSqi4{OG7Xs1 zs^dKq`Ol2TD1aXHl95;zQCR|Xq(2RvKetyyZl05tFvXcV*V)lyevzg%S5}fdVp_r1V)>(Taz>X4Rt6eCrV3 zhtkIB^dL#q6;<`BF|T%^tBiHw-Uce!bfPmATp-b(WLm+aWAd>esA^sIee&#jVGK#de7tF0grK(xx#_6Q5k=MEYD$kFC!??l)AV?k9PVQE-s8p-nNu>M8 z`D(W!^qXx=@%vo%cGtT+1+N)x<5=uYml6XWU>nxdMv?K?v?A^0Mb9DM0)KLo)_op@ zrTWxe9Js;FDDCE!1={`&Clt9y9&BLC2aHG1)tIJdkv*^5VT*JFw?YNjK zy`>|0^-Gb0j)b1(yy^8++*E29u*Xb2^2Wvr$Qlb7y9>oIb)8FJ4x2ZiD-P@;RXZke zE;6n+^dTA5*~!8+*P`ouim(V;!z{(~jL*1X0QLEYf95TMD=Z*FOLNHxGL(|%k!njbS;~&y zqn*#YX5zm0v2b?SPmIaxDtndFj*e7b-xNjVkea@RzN}r;w`#jG8n?f0@6PhY>-epx zq&A*!t{F<;_5Svn&(9tZUy+36^c1_Tw?5Q>)2C=>x2>?>j`QK5w(F>DH^Z?8SGHd| z?Ropj*YB=fu$lbXFT2~R(7pEpDSg;|54O?o4vW1_-DEKdjoBm1_opRo>&g22-xKwn zz&}KASIc_jn+`QFmhHw?|JCDw#oDz^t|2jR`{M4P!p&PN=tSkEop`r4K8^PC6pC%L z8}sVo{{8U#*}K|JoU*@%w&n%j(Ahc5_m*3J*oQuj-RUg%b3}vT2)DRQ?o~3`VzwRPMWTK#1a1Zj6{B`o|o+GY40G+YcJukS384;t7@Tmvf*v}gJPX@pAunKfsjlD0$zdt(}adl9G?7Q&qg!`D; zi#Z%>L|T^BN49000XCj@)Z72LjqNd=rSyUBncD6N6(x1r__>5=Js{q>)%CF3M5q<} z$wvb2-v+i{PraW9Is`|J5sQu6_mvz2VqhHHk<&cH>u6vhaRug>1PN9ex6PgUDc}PB zsvzY7RtpkW1g>1NEtmx+pA`AT6KSBxq1_U09R=b}n@NNa<{Zrwp#Y9y6vmhmW?_fC zpy8PniA9$P@{50PgS73FUDzKQh96p_Mhafh7P6in>V-<+TnQdvI>Fl=ei-51o~yICxShq}P$y!d2{K3s-W*bIH< z7ct^t0EV3uV&c=4p*C8KFRq^`DqkV8-84pn8XjXvy%O)02YRR(EM6lo&S3t2`PMkP z2W%vxWi6M^Embbg3@CczH)`S$4dXmQ-crDz1a2RO1ko$nqdUGMn3)jgjiVe^;qysc zl!2osa--D!A}}^&K%U`1o}&L9Bt%Z2Ba$HuQOzm>Bnp}%zx~%VqL$^T%<36p{h?&i zfZk%s904YwIEG|PDq>Hf7r_*zQ642yCZ+zhBR}n8Dt6>U5~EDkO+LjQ38G}(@Vr9dT+9X{@%v?UDX2d}Z7(fglKx4ip4X`F`rsZQ|C7K;(6ISMI?j~%G+h$s$SXQM< z?IaL(rtE=bOa>)MN?sizCJYq706-^n%D{BSKy@NO0>r=pEI@S1<^UwXbSl6CjHd#m zWp&zsc#`K08~|D#)pB~}@xA3pHXU!)=VFf2{kf;=Dd!mCCoh0zXjY_LA!jX$Bs`KF zVC;c)4ghBgU)~g7yx^2XL;5@h}M99 zlAgW*S%69-eZqiux~6^BsEYQ8B+4a!wxoX+pkMywAI27e{vM)%(jtpCr*l52bb_aB zI_P;W00YQqgCanA9smMx=!Y_>0gPvcj_3kp=Yx7Fm=-_+AOMuc00T5Bc$VjtF2DgK zz<7e`46NvpzNBI1rPuwNSt{v+QYVDArkrkPcg6sC4uF|1Kmo)lV`ga#RO51?Ns$6( zT5RQxLgqFGCJ#apVInAVrlt!l=#pw^c{-^Kl&O|J=ZJo%0)%G)AV8FAsGNEzgK{W? z&MK<*sfTi?0!Zj{J}09(W;%A|_3b5G!lZ8YYJ>i%pTYpIQmBP?sD_?rin3*jI_j`k z&5wFzkHSc{4yz_&YH7X*pb4c~@Bygysi~5xc0yoVWw8}t*(&_-* zYp>#}t@bItZfUFn>uYgpeBx=gaNV9tXLK^@zAk7CoT-LRX_a2-vWn?*nrZ?Vz?HIR z#(t@xCMu(f-$~Kwr19P}1`~0TWiSe>E_9?^;K$`9=zACK&c&EV5r*TegWV&e2C9INWr_k~%znba+G-;|P zz^X25iR!A;!hoAD?Ettb*TR7K-Bvy=jd0orx5jLcj^<9f?53*hJ|<`q(5#G(>djK< z0(d8Mu4bsu zHg0r|=e#cOc+zMAoG7~P>z0mZlzy%C!ho3~fW|)P_I7XUGOzR|D#UWHhN>qGbn8&s zY2RkztspGmmM+&isL-<8dwr@i+a0fr!-u~LK4ioSMS1=Ldzy;$#25T^o3TV}auISS2(~c?g z((4r8>b|4t zu^rE55)&)?3hPfEEd1W_T0U;RPAF}%zih-ad{Y9S9W1d^K`*8}hRBPZ|hBYX0o#PNHw@nkp)X6CXk z@A8*)E^0!hEJHFXg|aBuC~nYjbL!y%_vI&BDrC|f9RIKqGqJZIT2%^FGrQQ91laJJP)L-05AVf8efTTTd^^kFjP%ehGM0>99bq;n%XB)9_QS)(;R z3-vqW^bFOb)xx#uShZp&{*YU~)m>vG-ZD>k@%74z>i`3Gv7WSZKz4{Q^i9ly~M&g-U z#Mw5mc%nAzwkxl488Yy8gWMc})}WO(X}@>M!K?(HH+mOJKf6h7!kjKL;1nJ7R;P6V z0^l2auF>H)VMq34mbdX>bB3=sIgz(zPZgx`j$!HF6RNi}4eUX|%rIezg99{#dn2Wi zmQ?%okiws4vo?kPv&+fuvE)1$hzIwcQFK>?UdW;NSD<187T6pD$!SI5Pct)(leKow zBYf|8hbwY;7dB%lTk%HDh!cvDdsajRc||_A7Gc(vqswd`;AzZwEkk*goArLj`HB2y zmJ`!zC-&MXI8fO&er&W%+abq25|=3WSbrjfzxiT$cS~D%a{jkz*EmZwd7i5f+9Yyd z`FXRfiYIThnNNCqLzLv@`1s&;c9Tw{+xa^}x>QQ~q{ljs=N_g153h)rJaRhS%+o9{ zq&KhZsE0~+nL2Gzb^PIQ1N(QY&-tr!`IfUaVnaLVuAJ=5ZAQ&>k(1GDkGYaFIjo2c zu@}3sUj_bsd$y!n*^Nuzn)CUkyI`pe_d{+6O|liX1KKuiJGU#B=UH3DguA#mm0lxz zVOu+{rF-cKIhH>=`-HiD-;-ESixWrntiXG=HzSNL+F2E+g0LtEDxcF`H>>wnZRK}C z!g{-h_`bDw=u)Jugr7UMWK0bmphjey!-X>|E>GV`*^8L zSkcoWX~~w0qPk}#d`kFJ%?I|)BVcCuJ1*i=Kzp0HpSw{DJ@{e0@ZGbWbbP}r-Dk$U!DK5In-KB`=24L2x}94lJR#z z*8V(_+p|rXeKR9IY6g2V3DjRZdyg0VgfF4upFQNyh}|oD)8EwR>*Wp#<_pHXRzv;i zIiSR!5aXx$-Fi^wV|boX)=_)D$s7G)A3bUEwr@QS>kCe|6hFepVCv`mFSpOHs|l_vbwq^ze~$lF1-qQQwEZsho{+GiC z7$`VrXhTS|$kV9jMfJEuxb`)9l1Z1Pd59?&7sm2=SZWH^dCDkATDFn|sLBQ_`5RRy-Rj)PkvO#d)klI=Q8mI_&*zg$yoE{5^D?JkEtq zW+}W3x!dQgj^p`W&r8qVEyW!SWXiu^gJ5jC(kv6dbOGByqLweBCvxf*N;60CnZ$7SyEpVev4MFbBOHYOOO}iDe7mc88S2W}9Zw$|E&BhQmr@^Q}JvqrC27qd(58oBoRZx}Jm z+13tr=(VO@ec2>dUoO&!$KQc9IXGcPuJxf0zCb-dU)l4uyJKUVi>* zs+o)MQ{5Mp0pjO%sQvl5pB-hM%Tl>#e4`YA76~trq2q z={fo0tl$*2pLbp=xCgTh+Um?JS4M_rmy8*Ek&yx^L#?N!BI~WPP$`K~YyjSy?7ZbA z#pty>#+xXJD?L>Vz%vOcFRc3fVV$$*!e`*5>E$}Cwf?1G>gI9=Cmhno^cvIVRQNXB z7QYW}Tw96H^`{m-A9-vq$HmIXn@|pq_X~6%9t&wT7Ek1Evz_ECv%)YlI_4PoRwfy? zk`TSHWAQGe^Iqa2sFz_da|N6oP zrCYQ>Q>boBStr8wbWnqwuhSvgwQI&bk8<{@=nAby;J2#m4Ri>PZ8d;_>aCjOiyP&w zrJO_NBD5ru$gO6U>$fyH<@;TeR{OZM& z3U;#EmH(={Xwt*0aP?$AA747mS3|7wn`ak!{`4kFXwL8COFOOb>aQQM;QI1Dy|jK? zEwp}Til6GuK#oi4rm$mNwyA9CJ$t(y&ccVk$`P+?1+?C%xI(LDx#}2{yPm3cgNVz) zFM*F^5p0syzi=?CaXb^njs_Son|%*!8sngpHpsvf22E~IlHvQlQ?3Ob3QAq+jt;ZL zCKq}zgY}bC2Mvh8-sy0D^ufhlY}lBz;m(LcEZ_*;W;^t;MRbe$;0xig8tdFmMscg6 z76(V#K7j*%xh|L6#8_he*U?`W6BSe@Pwg2VaTux852>l8cjnXnwvU; zG=-+iBs($4Ia78+ob}4)W6b$ccFG1TGhO7eC`zVulG2r6D5ghmanXIov~c94ge*-; zJc0TYsr*?gFGq<}ZN5|tF%|wLR54f672foWjw0cMZW+KdcG3_*MX4}Zl0AL`6s6Mu zlu+4vz=~a!t5TH^Osi@%9aWRABdsC-+P1`bp5?7N+DBP2ibqSe!gYj=Clr5IPlfgh zbRGJlB7r$qyz11bE{&)F^T^kV0#G{I`zkTDa6w;IRXu;Ts#(7&QHjEKir4d9W@Fb^ z%$}2Lh!yEhc`DY34w7SDm7Qyids{K(a4~MhYi~^(TF&OuqOm+_a0&T7SlD)iz6}di zojXzeb@sSxl__o~H%gPSs*znQsmMsX+Uh#cv$$lUeCPXGSVnBSup4isz6)Mt3MilI zlx%_1DzjdGmcAOLW&ZGtB)8sZ_DWpLB4_MdAmFByk=x>LfBOj}00$T*ydrRck=scV zqgRX!W~PHPr(*imaHwh}?@0o=*Bnn*MedEqz!Z$hy8f4;BVJ*NW87l1lD4S2D{gRX zyvgu5?47YWFDDmk$YwrF$nA{ohS!NjmbMhDH34#wHjj*Qmz zVRsX#CG(-kuKo>WYaSkpdc5o)M*)J*55G%s8xm$lO8 z*^<(>mUQ)>{zu0eStELA8eTN0e>*)-IslWlJ^ zy1Ts2em2S;ZEoU=tM8N(T|Swq5pA}IoIogT|VZTD|$~Vk0Z<3 zoj)$ayy=}0IL)Q*rkgvO>l)d4($9|ew5xsXLa%TkvW>U*TDE+!Hjz`wEoyxweC}E| zVa%)k==JM@y-XhSbz=cbo1Pn>=LlfCTs-s64%(4W5biH`X!!o4H?8sCRMKX6X>d-Us-GS;(Bb6~38KC0$C z#2vS_*n_^SOsGB2Zx4OxU;q9+XMpf|t^mJR0MEyB1|WU;-#KhaOuNcmAm8JgWGC zAc%K9v3@}jcs=!u8-im>=Pu2+q%_%>=( zj-HhT?^u9*D33okg}qmZlV^xncmVr2kcpUkdpH1+czwm#j0Vtrl8BJhM|}$D5%*Gt zHHS~)IC1RPJ3Y2is?%L}$4tg!flS44O$n0RBa$QOAE~okFNRK=@Q(i|gvnQgxQCWT zIE2gii}igbTouOSk|{*pma|OOm{w+Ir^8W)AxIf> zj@5B`nN)#@B6dvmky{CV{YH(A;hA34j(1?1!%3W_$!oj;Ay%=JZ^w17sW=fihw4Tz zwK+EwH;%^vn%Ov;7SWPk_mzBX8D<3DKBTAwrI*k%1G7Oq+Cz>@6^&_$VX`LDPjkB|gVu+O&`kygU zbtnp;tG7^zq*DHXFw&${%Nb-37I1H;m8Ar5iV<#c!E#^MGBiq|S1Dx4mZMD}qv+R1 z=fsVcDV3ndqJ;B>7ej}BWTdmE5@Knkh46ZIIEG3iMHRS;g?FPSl%?adrCb_S{V5fB z`hF{iTDwN3_A`pIh@MO*X%>`fZYoM)Ns++mBT92MY05GXg{8VlWJwuseC4MH0;qIl zP^@%GmI_3s7h7Yh6(r|GW9g_T2wgrJS91y}HF}$Mm8qHvWDI(#a0+!Xp=;M>ssz)a zD#2Y{X{vHpsMvTsuWC1(s&ITps~5sj1|y$SwWR)UxT~GlYF?UM!Md#X1+8XUk%w12 z2?~m`=bA+1p1c{Ypo%W4#9z0%R=Jv=d3U6$>8aKiek?{&69%ik$iKn^>l?v;XU>d0T7Od|;WgAL&dls`&U&7NlK!kJ%b`DYwiP;ROKVzIX|ox-8!@Y`RQaoy z8FzyvM8Z&aQ@gNG8X#QrTVUvTe&Dk zfx~k|iPJWHd#>tgv_#W=WXrP(ce;e@VrjFpjN7=X86{g6yOP_a(pk4R%dEFsu?p2% zvuC2)n{h&VP~vKhU01M788B>vv}=^SO}n{ni(MIowdCr%9a&9QYp%3%DYTZY56QPY zK%kDdE;6x{)qxm0+@^j$a9XEbdkoWSzNAIELD3;iYtq}=~AQhOOnl-$0OLP)~RL|9FjPc zWre%7K#NZA_=1QG%QIMjH;9Nkn1_)^iGmo7huI}oJh<*+$++5^7Taky$6QRjz9xvT zu&iOGi#+#-OE`&xScrM30RH#LMahM$^ptQ1N#e`3 z%Nub)YAB%QotcVGKj5Vl?{78)F zoUr)|zrF;}{p_n#gPD^e&l26lbi2%(+HOS4t?k^=+&jt|(shS*xc-!$Z|24Kh>t5- zkGBVu2c47o$cVfwk*h3zsS?ZwyjY|>9+|5XT64V?4NjrlZpebfaC|-8`#F< z>NBZHz9OVKU7P;NO>EcLT+n3-zpe;eI3{J{I~U& z;om~q0{&Z_OGhHMw3s`>n9x0S^8GhhVt*5UbfG)q1c%)X_MgM$#J$>PuvII(TXKZu zCGX9-SS_^3GmDiR+^Vw9o>5kUQPHQ-CP-n@S$-XYQlw^xjXmC}nBCzX{!+m0)LNY5 z7zo=0r=aHjCN4E-8o&3IGLHF6x8I37T~}N;9V)#X&$xZ zJ40s&0lyJ7{p85aL4=Ba)|iymODZZ3+ejun~a z{zH^L)C}jSo}asp>(XB5mXxKCuEjP+)c-9847}l9rs%8QP~<+cT-AlK4$7;l%J_Ze zd>*^nuCqxKa;xjAt;XLh+gZK_-sP*$bIsSqZQM%ZXqK%xr+U^I=@Zf9R)En^$ubT^UTGx!*l%?y>4)JO$ zTOB{o!tRylF7kw-_@-@}?pRocnyXW~^{lDTI>2T=$*S?5s;8V8k5l_?=s41# z9{SWc+jKQ<<2H_O>V?{RBP%_v<8i3)O+S9-JB=`JVDPEoYOlms45}Xg@pVN0mCBwq zK1X~;IN^X#o@39)ggel~Vn0?N;?w)`S8a|dt}Y??_3irYFUs3@zw?XV-SLd>RgsA| z9n;r`0Ad_`!`E|XynM_zbPqV3Oh)#h{##T|cPjtmpw9MBy`aX9O?u1Db5HjYhKOZDF%NX4-@0LAwNS$4<<27 z|F#7>H(O^_Z!>}~g&7u?WhY0Ill4+_7g|EPWRA|zYhEU_#B+|?<1ZjUuz*3Od8IPZ zLZ~VMK!F79(U{`Hn>Ke^hE+6Yaoin>$#{9(C~~B^kR-)aQIqn}7-c7cNi#W3&K{Ip z$_-gFE}f8$>|DO=3GdP-Z9Ji z*7FArVZU(o_SN&+CSpLicRy2yQCwcvjp{)%z_inX?p3=3?3AnE)B@ngOP>5tyFP)U zTrfy*;8y(kC(;|ZtZSE9-Rpwaq=kPH71vE1&$;u)fWa}i3}Ov>aZGiI6v$Cf3-)1{ za)JT&pL5lU zYC%|}a3LDmBX9qyl;?CPB9kNn<0M)r+8CyoW74>Qc?3yzrkK^# zASH(exUxvDV|O-CS*S3nx;NRZ(F z9JVEem1!)$5WNRU$0$W$Ec){eVwP*2lZLV>(*J`_Ot-$U}hm=CTD(;0mZA0$5)p}c4 zI1dX;sk^sfoUz6mbKJ4VCKe3GvZ7l2t$+hlOx&&20-R*XkpfsH$_T?u?Qsf6ShK_> zn(D7vTHYJr%PqG&Fv`#^I$>Hq8%EL46&+19ZMz!zbeD$GoabUjqr@7!n=4*2=dS+GyrpJ^m-ai?xuI;t6ytweRi+=ByrhenQ8@ty< z+v~w!PgC)ONBKOhLki0K`OA;(y84N+uD6?3R*Y}?oOAtoNgO?`b-$C7NgOu7{R!uN zIy)WWOqL)(6-a@uqg#K}mOAeVZhGkwngkITo&G`YPE#|V^bVLoVNB42;#*kf;#Vk= zv<-u(dZ7F)SPmJ&k8m4|oC+D2J?*j2TqjE%07*!ozx^t6Jv821`1V6dAqs~5!66Ol z<~H={@PYzNVF?pgJ=ra>Xdv9$aK6W*k4$WCC)}CH!uZ0q(TQQXLlsD*^~5zcPh^KG z%S5&qMb!nbjCXY7Z}NDeQ~oV*F!);p^dban3B(2#4rp^C9isqA zJwfX7l;{{E`*hSkP90H$I&9-3Ww}2;&M<*hL?sJFL{aVR!7O!&tPf^kqK2OBzd(2hdxwMGi#=YWOL4h z(KD4xqUJ_@2vgvh{!xk;P0;zwiARDq3aGg$sYWjf#fGjkrWu;4NGZltDDLt|L{-^9 ze`L3-T1P;1bZ1rHDbNm!u+=+S%m! zOqYrUDr28$z}iJtvi2e@E?FtWEZ%RO(rGFKtG3y~PLi~Cg_37ciy+maG^G@BZ5k67 zTiJ${vi|I3aBqu3%-(aXqvh>zKlj_4h1Qy6RqAOENf*^#FmQJYFIHQczwbi#u9obr z?!cxx%|Cszd>5F%CxH-Cuk+38(3IToOipFWhg@)3aj|XKxIcz{!F6J3yMp8-F z7Iprno$O~9N^7`{MWy2M^rtbMG&GMIlTMtn+-hhX-K_e$pvqfFgiK(WI1$#x#c(_0 z{A#CBs#eRbrK%aM}RQ=YYVpV`o4-#YpuoE&(5<`_Z)9`Q&}v2OI5jlWSc;V;MgrT{|L@(qyrh8rT%hR z+(MjUO?OPZztPEv`BnGn`ufa-=DNa)2W_%9?4sDdX3M1&a7m)Q#t+Xjnfog4SjS!Q z{)Rf`D{uLWBOA6n=evl!9!>k19pup@eBl+@kz%v%=nY%ivq#>k@2WlZ$7FQ)opI~CSN7|T z?|fmra>u|gT07XSPvUXU#2XJTw9XvN=)V$DW*~#=<9|ih&us3$zkMoopUN;- z_;H&5%}!XTpB-5o(Ij5pan|jwO{Eqpsi6`1umKTogA*j9hiVdYG@#Q z$cPIlKnoOr3P?gfq+kll3q-hpqQzSa8sG~)QVf0*PY_^xB_L91#Fp*g4(dy$b(I;- zpU>@6ktk4`tU(5jASxVTED(ewtO5d1!U2>(CrDv=bixSc0t|S9CX9vwq#z6ggn9fS ze~jIeU||@Zk`+3cCh=HLwOJU|O=58(mr3H!44CmT-yw+~dBGb|%^r3TMGHK}24aE? zY=U@z!h6t20U*E~x`KFYhAzrTD|~`@OocA^na)Mx@%c~zN|`188rb+~Tt4;9@{!T1 znW2vn8P5Hc%l(rZrcW7UpgdHCE6zY@h=4v2g(Q$dR)j|`s-smnp;ZLqSCrz96{8lu zRXAPNq>xEa7~*6+qzfPbW!%UkZVo)T z;8H$FQ-b6J%~*2n;{!emR)Sd(eU;4J-td89HnN`O)l(1TAEwkHrnDLo@rd>TW?Kkm zR1#ES{tx0&8cLQ=1Ultk4dnW%3p5M5r|nAY@Nri*0erEKOE#)@ZtW?)Jt5R#@w zVvks9nlfdKY#g68dY@u8Ut~faSk9Wy-DY)eN=A8E3s$9666byC*7$*(a{`@lqGo(; zjCZMK@Ij{B$qL7eq(L^1ZCa;wHY0DcO&0#V9z#Qi|qL4U}I#s=?i;@`2|EDe9t1O|nQxDAJOM+8uK;99JIXCB`O9 zDyiE&=HIQ}pgI$N{^l@B9IARD1iBr%{!OL7Or;9Bsv6d5oSvqwj%lq1R;KDB`<3dU zaw>;_Dx6XoRb{KGYE3~FXGz*q!C}v`%Ac!}sDcKmwDPH*BI6?I9BjVaw&o{qnIwgR zl&X0gx3V9;xsAUz>s6xbx1K2Tz~@Q5E0}tgyrR*(a*@5>t5t!kzDgj1ifh@Ko{WAE z16Jk0n%dhfEIxjum?|mASgW8`Xv7k#zfvH}W$X;)60jQVh@R=B9-WneEW@(rR${8c zB5bd&s9x*JCZCCxtkxdc&@%0_3hSiw zs?}cOs9Mz5-q^!(n!v8aaGp&5`tfJM;%qWbVAi^8&?=SW$f~FAt+OC)(n1WJrEFP| zDt<<3h3J*tnO9W#DA&R(t&-x_I_{X!E4B_U+Ln#dLM?#38KpjD-qjJpy$y=JDkn0Y zVmj1!MqHRqZu?cPNd4FU6D*nSag)b8%xZcwFf)A}i@cH+%OD}wT_ z{t|5aej@SI=mc*t3}fR+CN9>72<@6}p`Gvwr!eI1Fz>={=_YT(5gX!OFx(Lyv`THB z{%?;tEvxeIo*wXhl5h~S*aE+8&mQkn!SC=W+&?<-#(v2Y=P>ftT4Qps>WwE6kDs>n zFK+-b5_8=U3l_&>@YHr{?Bd$v1#nCXWCOP5@R{EdYfBZ^t+T#R88dPnbMeOICm$D- zBem|PR%`Xj<{P%FAse6!4=Ed8O#EH3q4sI{KBrZ_F2rH(2;Y#F?lHDDE935#<&vB! zL$V{w=60oPgZ@Gn|JpAnUr&FoE*&=m4n@@Sa*3GvrU~0}F?(^WN{An4WsWB7AS*NA zR&((N>bOpF1_Sar6_~dgaQ@7)9tRsHDzPa)wUv!h%i#A+iqx=W9fBEmQIrS|&;Z^;dlFMNj8L zgY*Aw?)f6;IFoaiHLB93bN{U~Mb8;nu-6{U0A<`?P~&C(Md}(GDJt474M$R)FegzN1&rB_6(j9%@1# zrb27iIv%B~Op67Ev!&7YVRo{4o;4+9G{hcp<;GI4SoUq# zOTZ3Nxv1g`up%X7W+ucUF3h4kA_XP<;x9geEp)an7&v~5V~Q-NfnIgeIaqD~ihSe# zofs3YPjfUdkN0~6cYJH%{_(PN-FH!ZV@=+}IF`aC@I!LHz(aQ6K{NzijzVbsLqNzl zi&r5PKXizT@N7Sngx4eArMHiNa{(izz{oay>ohwLb0QHph#7Y|E@W;xWGOI3iEFnX zmcola0#~GyAouckGj=t$br%D9xEw1X@4$$& zrG9&MU*lvg>W5_9Ap>Lvjer6uyaH-4#6xbz9|HJ3(2U_BSQLbfQcLySFf?cvD3z)Wg2==VYdVc<><9DAf zptfJvAsch0Gkd3Zme;y9sfXKQmaKeob#)GwQNfzaO8eO&`;MwyvWqVW zCpkZt`?LQ{w6A%%lIu1n!Lmek(!tZa$IovUm`oqt$ zzpEU@S6Z`gaS?ZVF5~N{6Fm5l0ZXHL$V(`)4J<_G6IP-;ZtF8`i=DWe`^95?155nA z(Y%oVX|kPOLrZ;%1{BNhb86~f&6ji1m-oKEafSDI1EcTK*VHTreg4IkCYony$WEp| zE3YE^Jf?%_Sg+mJ$EuNAeBa7^l$pKOFY|eKFl<+tVWaca|Gb?t*{<@m*T;E=BmEtJ zdd-xp5C!+d*N*^4T77>IOcAr+mucj#d}IrG=eF_`H?!gc)Z{mPe@%VsyS{kiJ+{n@ zjD@l`$~}?e`(!UZYVL`cd;g2nr_0CjV21Cl4f8)vzlIxqzjbfy=Qj3dKiPM2-#1ZK+u!%& ze?~q&leavZtG(@m03eQJX`X1Ru59a~1o6&kOy78}yYfEw{=T4aNF3RUwb&7vI|7-i zCsPWGzIwncU=26KVA#>jQJx&wd7XM;YnvoMK^)K=I~t=iqI(~aKZ-_+dW=U0q|*WK)nikf@TPciBYfs!IuOJ79>cx;6QpvZ=LqUkW_EsHyJ_t3SVsS_vu&uTq`y3&?Ys8JF{udw=g$q3V# z@Uop~rG=ior(N=y**Czz!DYBG9_Ux#a`>DM$&UPdtw#3_-MJqB_KP7)L2O6$wZ5!k{qNkrOP$qNfm8%s0_~P^!dXG z_RQJ@YXF6TlNJq1G<0hFs|XPRf`D-S0hR+-817@xA~(St*~wARIGIaFN)z>T%g{St z-(IP+xx|owex4*R^v-&wyX({{d$q&XXT078WPtT?;dN=}(oKdpf&&2FM}}8@ZS{w4 zgegaZb@*Vy;5OMI#@%!|Jvd<@j9p0KPuBjCqE0*!Dl(pVQ}KWv7V6=o+JIjvQ%6U- zC{Tbv{N2&a82cSSTyPcf;!JRJ0Ei=f2L+~3g6Pe|+%zFBry*%iVg?>8O-89mmEKu7 zSyC1{mDNsIVu=)qC9ZNJJzZ+Hq5<`R5fMx(MdZ*z%*0k>R}meAfPQH#Ame>^F|>dI zG@`NR0Ke_&n|@;rdLVLTJn`L<6^ePDmQ`RXrKD+UO6GH(8nszg&~fA86rp^opqWFZ z*XbqC#478owAT8Jq(5w0h^69%I;O9VoeC_36b`%IQk_)Bl(5>RnrWG=R&^S$KiF#R zwb*7`M^#{Mi50cK8e5vU$EHZGH2&aja_%?|Qp=#Sq@V__HKUm)t-0)KtM9)23X){K zigo#F6zO79@VW#yhp>|q9=x!^_bVX- z>}546i`w!fFF$OuQVY&f@y#=59IlA0rblJWihwNi(6fpR<*{LYxG>NtZ^m>@Pg|z4 z&C^2NZHCN-$Ft7Q8a*XZIEO9v*kqS&_StBcJub$Gxtm?i8BT3Vb#MpkYt*5x6SFLM zZ~b$Xp84H%Xk7#(Z=r&IAu#!jVh~gk}tymHR6LNXaUSs~a!AC>= z@?xT|H~Qq8RIZupFt7f4{?D213@V7A1#Ww$Ubiay;iZG!HdKbg-f)P8KWV&XzoScY zJOAE(wbZ*uUuN&iH=nDjR5yND>Oo~Mo#M$~2fjGshtJdb&80sn_0_L^J>kA2u|05$ZkmX%LJ3u=rMK1Ukt*-uLhG?@D`C%gWsuN?z)-smhS!PeQ# zdf^L)D&kka`L*ga540TjLcu{%a8PS0oF4izn84=IP=BL%2MMD?ydKK$hYE6F3@=2l z$0(0e+I!&)UACnZDiLz5>xAG$HA02~v4laaN7aV7og(HBf+)1#6FcZF?~O5v6?B`@ zuGGXTVhDs-%%ZFQ&X`2ap@NR>dmtWJ*u@)CiHmSt+QB$x3D}{|jb5~uRkjGoCD~Dm zo?5~lo6^WX63~E?ykqfB$GB3sPJt5xA>tN^rc6FgcbbeO8-Hg?Vu3MTe&kLp`N*zA zK5uiBGz=UINy@8KQc6>V;^8jWN?mesmPo){F?A@e1Ag(1HN#~tw-?81_7X+N{3YAw z)k;q;bAL|!=FcdjO$y%4c+RxsuA~V+Y9`Wz*c9iw7D&rTno6E4JY_cTm^*xa!j$_o zC;ki*wNkzDojem6Bg@H7YclU{R$N*V{h5R;G4z&4B;qOh$*uryFM{waJ3XPacY3fky01I9z72rxur=*?!poQH`CrUr) z(Rti-OgSBDC2@tuVJ6d`6ouGS3z<~}ZfcqF;wMv^YNDrVagIhsUm)A5N>Y)lt4g(D zyV9ybCQ@#JB`p~8qUpH?qLr?syP{9e85PRSQ>v6&C}3xjIK)b$qN#KoS*GOxqrJan8Nq+(w&RQtdUhlzk*|<7wOxz0FumD{b&D z+5TO1Lbkj$MD1tmnk<82_q4%$MHm%}UR0GzwyJ}m<;1(8qeiz}5Tag2Sht*08EFBSS>`JOqbMgB8k9f?6hud!{erp&3gY(W}&8k*-NVTdCwX&(YNZ}N2PqGvt6 zPZFDCGBxp;ZJoMN)_B)@?zJ1K2~iE(?U|Y8@v&!UjXl;mqvbH~dr2J{Q^&fYMQw4S zsaR-f_xRQ-_2wmm?J%2wIoY~~bhM?N>R&TgsByzGzfTQsIn&L3+eYw=>xQiOLc8E9 zrkjab={<4|9H0pw#kWrU-)6%Zh94KDz9C-U?@e5ciM#5#+q~+Db}F0SE;Fw{y5wH% z(%k$$s=xI+M3OhlJ1b}Tjwu{->IV5LgNxGy%M=S4$5a?GEcKxNBN}>)wK}1j zmer!ql%HC^`ly|*t`gA`C{Pdk2TcX+i)xynYIkeAYa41=8+B&RuKChMiSwLim+Jey z``)(fcd@4tk6v$3KjV&Pw%WYx3MPAZ(q4EgIIXR8wKeA$FZZ6aIPq3PMASnMc}GuE zzLM`WuPfj5k%2L{NKf~^Sl zzUDJPq;7#K$ycz?SmScs>6;-(bx zCTSZOPENCfu*M-is7Echb3-_FKNN!_SX1ReGH7FiPSJyKcVP~gSnU&pwe)gUm`28A zfi2j9p0jI7SavkmYM>`cH=}$TWoBXcc(iwhLd9@dcuGVldtEp#UkGVy*eqlCPbWBs z)ZvEi#wquehs%e5fVg^G_ZV@wZm!3Lz~zOy1#Okrfea{X1r#|dn0e)wi70n*eF!Gs z#EI=Sh5Dyty;p}P6p7pCca*q8DhE^nMv8M|Z=tn_=Ke#7xFd>eIB!*^i_BMiL%4-6 zI0#@ki6S?Ovr}lFSWZ)dWXq_9uopJ%rBPP)j620Q)AxvWh<&R#a2Y6YW5CQWye{+E&-w30cOk<-X^G1-L5n3OrW zSa5@mhj)q50yzf@8y% z=E;|mL7ma)pBnR;miL~h7oYgxlizv%Rm;g|w?>{4v!6fKN$JU-z$BQb2!H}upc86B zp&6GYmTd+~eh^rZ8wzaW2cVzXkNB320+pD)B$wW~ex)acD9VJR2$dnaRaTgz8dhrKF8eqDYfpYxtuHQHPrS*B;Yq+dFVd0JpK5s&nFG$-k% zQkqj3I;Sc6re20^7`dChi8G%irLY!QBDtn=>V=)As9zGNfZC;+sHxoMW|)YVbSkDO z*r!qWPo_ASeq)4-P^S{csapP(jMWLMW(uDBm!FXdsh)?bsd{fdCZnU_s+qc>hRS_t z`l+`1RhL;tO391sh>**wY(W-sfr>GMIxWWfdvaQze>tsF#u?~0mOvMixGAZ_^J@9T zr5~5AS&CV$g{;*@fqROEMFFl)Xs&q*tJSG=>ng0+idXOIlrLDRM#_x*nyB6Cs}YB; z*EyrB+K7T$o7(E7+-j}t#e4}%qg;Tm3~PTM>ykAEuq3-P#5%B?cCkB|pte`9A?vas ztFaDCWdA3xz}T)7i?Vmuq#c@T0vWTZw6Q>IqC<o*+v9ASnTdQzUX|?YJ$;)r-_TJ z<$AeZin!%jvSGWjTq}s2OIei#wL>?$GFyvP8?#Isl8(E!m5M}9*t1S_gg|&$Fsr$H zH;b$Lv8}tSu=}}HYKCx`hxB#3z}dSm7OJ{it3$g{H7l`8*R@W|P_5XPX^Fbm7*M&} zyot!V!rQi6ON-;QhCnHCuk^dVx>?=py+il1eHFbnD@nzhdHC`jXT+rL%ctSGzuT+4 z*r}Lx;aw!rELz$B<+BT2mF`>DZdc;~6TbgFC+?4;@ojkF88 zKT5&TmW0!Zz>4<4dOL**>;cORH1oi$*{8DFx2x&|_NKwId8kOE!igK7I_$z6cBVeZ zc9-fUHe8$x9Ht#iuOHdNJ`7_Jnmc|-z>_zEQY@OhTg1!hd02e8O#Hp=xvqLP#s5o# z^`^f~?3yy0#HiWD;N_Xpn@?f=FyqlJL#;N(OYP^?hoHrL7yw>C#^5s25 zbI6GN1ud+{GpVeM>~dbYqRE+W*kj0ve90iw$Ie@-TTHfpEMaOIu}xOV;S(QaFejKi z5UCt1n#^gd{=3MJe5=Mdt1{fFVLYTY@el2x%e;&zvC#}}PyqdK7GxkOexe7??cQ7Mo01*)}%-a&neFTEAY|U55m{$C{B1g)Kq06`6BE8HDW$+7PU>sc$BsP)< z$?VSU90+942C>l_ao`dIAP{-b%GTS-v8c@k*Skwt%MQ1FxZDo9ybr>R8~~xuE>Qpm zfe`E*&9|`{DA6c)Q4+$?5(hF8xnRx%;3sqd9D%^k^tzvB4A504wOrM>sb|n`{7(su z7hTaJy?ho9F%}{L2Wa675UtO3@dbAg20qn|&4bUI%~#!SCHKa#TaW7D*YN<>5Ah!4Tn6&-DD|P(t`PCN=+8`F%}9C7`}ZL^O4tk4W{0k(x{zSxG2Py>U8mX+BE>yY+@&G@*dkQ5_Mu5 zZ=%nFLMZ+)-VXp0Bz-6w?I;5BCI>;@zTgpWLd~Q7+(+rd)@|R-YQO9nyA7Fkuf6`t z0)8#a&70cn-1=>!JKNtsijS^c$^#zZwvxvQZeggM-xcns2+6YJYm(WgA`%|rvVvE< zn&DV&;s|cyL?yW{&6YB84gSdF1rD!>yDTO9;xt^4cRb`oPRHe% z;=1e4I;!M;47WZm*#A=9OwPeKzPMA~&ls-aCtkbP>Wb0OcM0yGzI){?ndMqOyJF;m z;yafkN9Iv$s%4quo{Z#Yo{y{~za#vUUR&oj4(GVZ=Zfg&=UPE{zC&mCs)8<-j;gSL z&TVqe#Re+CGi-gu+UTlV;t0Fr|C#7W3R)6uid2Q@nl7!24#JiW-JHI;0{#ZE&xTW# ze(Gz6>E$@;_L=HD&ReW*=9`{?H`M(%_Q?Ho93-xX$BH16m=>%T6d z@h*_+zN;uEoG<dfx%O8n?+9BBIPerM(I49~w* zTjdp>?%j@nJjQeqzev`e@z_kht^GF}-^80J<|gm$6hDb8rCER) zIticQQn~Om|LiYMg;W~xTWK0K|MSV(jwO%u9Ix`IDw#<`ZbrZJ{ujP&9Le;odGvYv zr~bN?0FL#{{f0gd_8A=XlS-)`@8Ew!_M5csW6$UPfuUZ_wUP?(MtGF>i2tmVE#&sH-`8e@4=)B`6RFPSYG!LFZj+$`H?^8GSB(s z=kyC|@QmN4QxE##D)(f%^r)Y&ivMFHTl%>2;jJ&7RsZ>%Z|-;taqf~}L0 zKzy%sPd|GO{NgD7t~~s~&iaz?N$J0|;E&Sx|HM~s>Es{&orR-UAOMJj2oU5+mMh!3 zFC5D=UE4RF>pS23zv%=V5{t$oGO1h=Q_g3KDVN0UzN((VrHl) zV&SOiDQcqRQ)(-fovR<{)L@WpEN<>qnQpJ|ui)w|FtH|VaWJox=Li|{GjtGVGg9H1i8dXfvv+xDxOuwzdN%s{VfQ->r~9{Oy?nl+vVOn6e7kA?;>2V3qLdM4 z2nRBJg|8vRh}!~6Oe5);(v11? zCQfP;bAn9C4aX*qK6%0+FyJWCq)L}EZR+$X)TmOMt|V&pYOkGGXLPJobsoPPL$@lL zYW6JJv}(VSZR<9d&9}|E_F?;Fp$#l@)fh!;04V~sf(H|(y7w^RYFfz(bF;A~ zgG*Xqz~#%9m1-VW z7aoTlHWXP!<#Bb;X7O!yqGtsTAR1{%oz~oIu|*}_TD8GtrgqeSe;N1Wl1VC8+5-E@sFZsidikY4Am)<|ICG7#*?!3(r5$qv zIEPtuM^R_xic;}-R+r?J*rSF#*7sxr7#_FaQT+{B+J$S{H$axqL5F~J&S}e&s0JV$m>M6F_h9_A_jF92UsGvEkskKA?8023> zHpgFn3It{(W=dWLFQZyE884SMjw1&2pGV#U#`WLpn@^ab}`mjYpsRG!hBq;#C|0xUCCfW zshP8FChIb!)h2z^%tzIH5_;^}eYf0O>%BMMc@%Op+Wn#kBft#~teK1~x_KRx58Jn# zyo<&?z}zI&jW_1MRo*xL=bd}510R4JkaN$Bm;Q6mrY(AOrVpnob)kPzO|;BPQm$|2 zxoiG8@4frp#0r<|u9V{IZ7!1V!z-U2DI+Od3rRJ^0~o zEe7>Wxoy1onS7r<`|V?VX8FTo?>=7z(SJYwIDs3#?(^qQkp2EAzyZFaW86F7ObD2j z<|(j&4n#)i*7ra#(Pe@bydWePXaWpo4L2P8APBh@ln_GCB_uo{3b`V|K%|g;dTAjH zA2^ot#PEIC`O>n&=O-jBO4NkMj%dc6#iQy9E117IJ&Qmx_BcU^H_s0 z>JeKeGzT90C`h3!W{^Dj<3Ivw$VDQ7kBsz&9hLaVNn%2clvH0N^>@il#$qy@3_~X0 zqR3B@k`&`9r5q92sj#53l_hax6OYI@R=Tp5{jlT!3n@Nk*s_;5!6nvY=|H^rvY5F+ z;3z49Oj@Fln8tjjww5VPX>L-3(7Yx#vpCIdX0w~#>|FBrSEFx|vz!-055Ta)9(DRA zndW>aJVydJV0Gp*p&3o7T$He;+-XHe%TIUWDbRs_=SFE7oTj$Zoae-8I{P$VQ;eg~ zfD*K#7XB4wxbhjY`m|0}m|+!wB9u?6xh83+*^=Y(bGYVhJrU z36faC=oM9}lC`W8`PjIOnv{PjN?=y&k+VbtP-wwRG`6FeS@Wt_os4R97}}Z6d{$G5 z2?}Sl>Y2%Uwix4F)J Y5-xP3E8Xc*x4PE7E_Smk+7JK$I|6Cq9{>OV literal 0 HcmV?d00001 diff --git a/final/docs/img/lines.gif b/final/docs/img/lines.gif new file mode 100644 index 0000000000000000000000000000000000000000..88f491edc302684624036548ce3910f32cd4514f GIT binary patch literal 91 zcmZ?wbhEHb6kw2JSj4~}!yWbi|Nq;!Zv#mNB%lLggVZoEYe?+6^Uvpm=jsLv^V7@! jMO<%uq861ZHD`s_rm4RV&HHn4>)eNv)_rVZVXy`Ob}}Q< literal 0 HcmV?d00001 diff --git a/final/docs/img/objdeps.gif b/final/docs/img/objdeps.gif new file mode 100644 index 0000000000000000000000000000000000000000..57c3e2e60d4edc6fec37f766f077c6ed3aae4c20 GIT binary patch literal 16201 zcmV-PKeoU}Nk%w1VO{~t1B3to|Ns900092~|Nr{U004+HRl8<>zp}i>f0DtOr^L+A z$V_Ry<>ktZox(p~ymE-ZlA*%@0000000000000000000000000000000000000000 z000000000000000A^8LW00062EC2ui0A2yh0{{j7ARvxpX`X1Ru59bRa4gSsZQppV z?|kq7z@TtQEE41ejE#iaH+%N z6^FXV>Tz$+P5ap#UE6XK*O8y7el0r*?`J4;r#9aBp~dB)fe)J=&d>JD)~|mv7=AMQ zBk<3mtG`%({appv)OX|jM?-*;A^teuS^0@$AZKJD(bW_Df%71CDPiH&O9XZ^A6y$Y zwO|PqZnI#9Y+N>0gVy;FVjL<~7FIUbxz%4w;DLxud4Y*=;}+TJXian|j>bogEKU<# zk48?%W0KLp#$<9;DQM-7d~qivD_3^u<(GO{`BsEg$hPGw1Pq|&nryb|=9_TFDdzyx z35exvWNLPxkFKOS=bwNE+9rraZs${;FD=PuD}D;<=%a2<$y^tO@^l+ocPi2-q?|hX zT&6C@xMF3XBGPC9Y@(_r0tu{nK&u59ux0|P4sbvL45%5a0SmOMtE_6$8YzZfA~=+& zp!qc;qifbWK&=Wau%-dI{uZ!6t^*iQs{sc1swxAuT8pi=k-j)7gaYP->}<-GdS0`s zvblf)126z=0SUCKfUxyaEA6vt9sumK`3|tJvuYm4BchY#IGnqNoEopI2n>+G0lG3E zEdt;Mi?IRp79jGq&1yUV#|YC|R$Y}E;hl4fq6zQJCI1Vs0RjU&zycx{P_e4>!i%%4 zDJv|Yq!!snUCgRTO!KM+RIID51z?Qo0aAn8vB5T9UA4|^8qI{cNw+5+)2W=wEzY~* zY%s3yGT?2t^sajAng~dZs@zi#I;y%O`j{S3m@?bx;ekR1v2E+(`4)+2qp~UDl)s6o zSc`}G-;)GpF39Bmm4}{iepq>Klu2GnXG49<$}IZpqeFgfnP8eGrkRkN4oI=Q_ugYt znP1t~;0&|dpzgx3ZYkM<1tmCZ6(XNJlqF3#S(c>3%%b$cOhshz6fXDP+1sxcS*-qh(*R=gPuy)To z;1#U5IxVrUb>3?l>^8V2h6RpgX3`Sa*0+=S%2u!%7{927t&}zKPeW{-d+hS5 z1$vQ(SA_nS&8YP(l4WaK-MZq$gqSQk*Y>bPbf<_XR&)_eP zj|^j*Dk-#_0j+00>zk@(xvzX#QA%1w7x;kWlqDrGa-(1(9ZwcDc-_isw#pi=W?8R) z&C-mwv`sEg*SI7AZ&bfb<+IjyD{j6mh?q;B&I}>ws2fypd&T$!Z zDE^Efn!^9-W}k%VCxb4kn~bLIfhZLdNnv;>)zKmFYxLQ`5+F zXr~!`#|1TtQ)~Xzg+UeS2u0*B0OFL0@lhU89p|zI8cK!c>(Epo#37KX5UNrA=~iJ% z1goyEr=LryTGxsbiAv>8W+k0LJ#j*gaulmE8>{USy0U481gspft6)K?lem82MFp&0 zF8>NxMGp3{munxTT1Ys)n#ZGP-5n(H_QY3hb5_iJY@8ySR~*Htl&4)Ed-RHu&8jI{ z)2fyk$u&$h9?puR<&#xQSkd88wJn$hsU?KzEIZySkNiT_A1l_)lOe!u&tlad{wc|- zyt%Ep)}`(tRVKL7hHpftNlkEBdsx>7tYVmamdQ{ywNCmmna$Ky$TsOr1xS*U@a5zW zJIFw{Ru!x@3}ttdx(VX0vX3`&WqW05v8d&Z!S79ggZ0+nyis^qy47M+8|%^ER;6>o zt%QNu^jxU{?3nKj?bQaxVEpDRUN3$ce~;%>mZ^)YCG9VHDb*})whdznfZNpgmg2rW zSi;YhCAaFPDkKBz$m_H%cXeCi9%MFwIKFH{cZ?d*z6rOKV_lV-R~v?2b-*09recnMt_(}^&>QwkHywf?@!T&-Q}1vrM=%0YObUH#7vly>D2<3 z!?Xq{nt}O^NnaD5Hr5QLv-s*$q9Y~g+OQ1?_b|B{8#irjXc6Q*mzAE`){Eu_Nf;Yh z0`v2*V+Jv{`)s0K66($XN^`Y&Emta&yE~;TEb6ipYt@FhCU|8xT}|yk%;5X0RlJL%QmCl{Xc*=|u zb;fPV5v?X(-<94vF-`0>WM;BkP2X78+l=|l!+K$cbpyW9Z1BbRm|NY%{Ws$_w}Lg3 z=1cAuw}L46!E?KRZ+F@DzG`i{g1m#7*|yTEj*{IA>_a!ao1Ys6PFGc5Gv(z*9;z?zw zNzW38R2WlMXnt7uXi0>E8RK|E^ImKcWEg{F4~8%*rYqrshHk=41!FQQMu;Ysa9EWg z2?%dX znRt6_<4r*ZPW3W3=EN-zfH5xTWJAa;Mu&P%_$+)Ee1OP-rq^VI)QS-nWp!w0vUr72 zQdtCaO8HlSkir0z$9jT7KpkgRS*IZj$bj!Nd)(-aC|lbDVunUeN4gBWyhs`Of8BwH-lH-_XfZBlk5nR(n6B-{sFrvn5L zw_6tp2_vQ^#>ImMlU)7MM`w4GIjL~|0QVa(aUnnHA{iz}c!-fNd0vy$hbIGuT{%vF zXNJ{Mje8Z9)p2X?$V@yVG8NM`K^BG>W_-w|7=)od>eH5zWqWjl zFeS!`&nQXtf-4BHgO}HOXGw|S<#QkPIMtSKZb_Iw_G7y@WWE?HKSW6OGJKy@d{7y5 z;vqorA(aM+m4!A54tZBNq!G+kcvJ9B3_@tGd5&c=kUc4VZbwt0Vic{3mApv>u?bOV zd6t*hUCmi04oE?t=98c2NQCKr+c=rN_B;#KQoRK};w5dn*$K&cX+;Gbz7}tA*OMC8 ze4|mF-c?{J2|*?ooqR=onsfe5fH{KiiAp(joUrLtw5c#P1#ClUJN#)VcGx}u3Y-5% z7P%pv_L*A4iHF%FBn+t}S-742Btcka5j41PrIn#k@|^XUbvHt3ABA!MS#JM!R``jW zJW*)sH=+l63`a3Ox)~lbT1p*foLLzO^O;zZvZ48=9YPR$qI{@U zSUc39QLu$HqmfYbSrwRyw!$sDf^(3$SKsHHRGOr5XCpgAr&@}FMVBoynRJ5sm|Y}6 zC~Bvj(-YYQsgA&>SN?RAUze0Q2$!a*lX7QoWx#50R)TLDdT`l=UYU2OSX+nME&#Vr zD#vR6mvT+2rxc=ztR$C^cdJhsb+oBv)u(F2S#Y&kkk@&tB*soB)`^!YW#6-Hm5Gj& zsE1Dit#Q|)vigg;=Qg{@dqb9jg=v<`iZsdhXx$o|#7R#=@u|W}6B~p8)?%o0l9m$6 ztRclk0)|Z{8Lcf@u4@Lc&WefCMtv678^xBRikh!u6Q>nqpwWqZjYFV;W{vvEr1WQL z7Sym+0%-xe6>&yqySh{)YNkV)vV5tcg5jYvTCc{lsxDimq2Qy-BboG3K{-n{_(}_{ z29$ZCrvX=){w+H~FG~ug!>EYWpiA4IOhQ_q3bo+{LcfzDDmy7n%Th|pB>~oN^s(hhnKkBqRdyf)JJmV&4ck4WJOS8)t zxUwcTXQ8)kbhwt8r-~~_V~Zw?^tgpvu>fX~OGUl_smGBayueb;CIPY()HL%Q;W3p~M}=#0l%feG=9(v#P_lU(B6WEXKy$vtY7Jux_%(CADqjc6RA z6}`_6oi+pQPbLk!w%EA|x_t4hS{L0kFO9StO>YV<$?h3yH;q}T47EEwXZ|t$wq|_2 zK}}^t?QBIIOh-MON&T~!oVo-D(m$Njk~7tB3(`fb)S|M~P4aHc_ZK2f#9qyoBj=qF zYDBXGVowd#VU1^x%C(+ytEzrtL$s)K#zQk_%Gp2VT+N%884=u{utSC!U+sNJ0qdmmM&64}U+GQQK3Rl+! z=G?4o+#CUsaZTL_%G{+e$m7h#8>h(x46(PZ)A32k;2r`jNi>h+3{_7^G)Bxjmuzt;7xth=cXdddd~^_ZP#bcf2qz2iQa#G zy!Bl+VEw;5Y9!;D&c0>geXu3{%dIuNM9IBaD;;&#eSRJO*b%PF0#4wFx8az`;Lyo5 zxT)f*9l>PHpH9VaBrSguZp=RQt$j^91}d|jjYKWHBK|#nTbkGtbPd+mA6%$2zmYB$a3Ep{ppH~>VI&gxW3mN?b>_Z>!D5v z68GwwUFdnRy{pdSnwwY3J5kKud8%&gv3}!19lMj5Yx5#?v?JNGS#~v{# z&V0OU?&nUwzMfW|=h*b??jSBo@owocTP$lye)JyP)n49cLp-%^6cd@Nz{SStPVLZs zoAA48HNF)GAFhyW-R$1jer4=RGw~|Rj)g6!Y8^SSNA9zMf_~~*Vi>4{T9Xm=wFUR@ zP#N+We?uhy5t15{D`=_ewP!9*V=&L07(cErbj1F)!H1-ZFFj~<2>?#%gfWGbM$z?L z#<-WIE20Z;pZ5O0d;BtdNUQ2)N#DYXM@L`yq>N`+EKkdG;`121F z@b-(lgx^y*=wrGlWB@~Cs&au=6MX5kPO-F%;u!3SA;uq1<(R)jL_YNGeHIY)f*^?X zL#xKDUih*;`x+hhPytcmIFE)W;%D9a`F`DfmX`ay@e>I>J`2Zd&-OB}-w9v)tHbfG z_fO=k{MB#Qg_?_ClmBs`$u%KqY;phiRVgAnLv zT^t}l00b!lCz`4&+qy3t%QIcC=83C1E&3(TCL9urHIwcK3=Wk{BQz?V9#hXJ%r^p3 zyWTHK8{RIbWiUFejwM}K_lQhd)9bJKc!`ge;`TqFR9nj%Vcc0@V%pweAES|@qU2=O zj-ibfBIPDj8`on|Cg&(64_4t#V;?CiCJxdZD3McZZJjAxl@scnp6@Sku<$UkY}TIA zmYJMw^P=Tt5A5pffb}(Yw)Qr6xA*rq?~Yiqu@J3udKYf)44&pWxcoeQ{kFIjIhnE` zv-&?DXwhW6;}Xgq!h{O1;R_Q>{uMt#1_4rRl4@Y3Y32xCD}c?TH3SK+9T-`_z_kP* zPa0S-a-lVrE>jw)i85Qm9DZW)q~a)N#fm}Rh$A<#Nym@Z6fC%AfWd$Q3!n}#urevk zs8|yqxJDHlP%#iUVrmrhY!87fitaobFQ(FK3lt1saI-*ykqT789dKZ-O}bN~9;nIy z0RjVsql(n(x9Nbv-NN!K2NaH5w3;uDX_qkvydzlqT077+!Qui8nj&DZvVc?t2Iw*! zfZ%}a){48Xj!8Ev?75`5QEvOwr@zh0)%x*_8T7tt!$EfJ4OcPBtD`+CK+Lpc0t1M< zIxa8w>%DW(nUU2+Z8?1YcFqmKijH)8w#4MM9w<;)yEU^7P}^!KwZy;yH*Kd4S6*pT zTtPi86A66rafZ=aZ7Flv2p!qf--iRLmJ|ao0XSe_0gm*SHQ^;j8g}drP+Ki?binD*FU#iG?XT8mc&I9mjJw7afgq7jx)Vmrt}~tTXbF*WR@#cc_U5YW zyyfuQuDj2Mn^}?GLc0jI=_cIc!u`HmCBX6eJ1-jb0wS-rxrTyq#u7KY=);-qtMbZV zkgUhLkf5A$E#G3)a;5h+^XVV&XKoAtH#4qbE6 zFW)^$-u_wdP4?P@;thDn4-L+BT1FopG}auOeH74+Bfi$;K5agBSyg8*Me_ldU=gRWE76OoeL#mqUW@xh-5|J~7svZM($U}Nj z{;(HYb0AUBX2T+u?uh0{qS=5OPx2MFQyC{LY2h|Zg05k0X#->uP(cU(pj>2n zSt2vECrb9hk6*Rx7izAl%Kge5_Q=|yK+&zQ%gVF5!03M@_wcIa~j@Y+U9 z&{^}En9Sy|l3C0K#t)Rz2Gpd=OD-zc>aI7*Y3 zAyug%MS8-Qy7Eh93>yTUm^fW(P+s{Ylt5*AL7FPlNdQgg42$B@GocF}AJu74g?dw> zRz^&P@S{a>8O@Vwl6oxU8cWM5)uBdpP(8Wo$Up{1q85o}OJ!yrVmel^;X|8ph3k{3 z6-Q<=%dN$84^`*-)MiS^Q;G;)U>n7YzRvQmmBg!Hk80PDBDNEVP2yJB_f@bWE3r}? ztV(Zoz{3`27JST+U#%5Z&wkdET|C%K(^^-{;ty02qh~{aIM*=J^tJwj*lH9O15RvOsNZZ5Yw z%(InmU$PUcXaueH*2`Y+es{k@N}GH?dR^Aa)Q$MtBnc~<#^0W^ObW%* zfSrq8{9bgCT(mDZB^)>TJQ!MaB^G+g>fA!T&A;MxFJzPU+YW=vyaX;VKxu)|P+(Yq z$Xr)T4Qyg+)Od+H#*Bs4* zUo284!_>+AHKT$vS6WL+Yt2mybeqRYXyENKwzv3m7;6TPNIsQTlya7oGISIe+f9TahJmqcN*iFu?-74$^W%G4{1 z`i)+mGzxJ&+WqdD*D*t@lNQ}C=`~v*#@Z;Wqv>jExABLY6=Sig9b-nr8AGi`_CTSn zHCfvlNaW>ceN^3P|GhiXt)*kYN(@a{;n_?T19!NE2k&|+yUC;mHo+mj6a68)Tznii zxf@ZqI@4un)I__oSlRm+)ho`j ztIJ%dCx<7T)Ef0T!)v@dXB^3~K4^#|;@%Bq7~7#2_Epd4svssedx^qM!_gL2)8*vo zs*dicsvGcS75v-mPEq^abSQ#rH{|?|accuTgo8+`;VbXBUEzqb3+LwF&vKQ}t9D^UcDNUc<%1=eXZ=ToPS8V)+ z{LVKLG5$!WJ{0|(O_n)+2(?wy#LJx&dU9OjK*ZJ{5- z#a7)F)bY7r&|z9`Elp3!o*Zpp*=1do(GBoLPAzTJ{;buTiJj;j-U`lL1iIkkgfzeZ1=Z>epoCeTz_3+PWnd7p)WIlT_VH8>rr!>>&XY-@zLAa(id!uaA=Eh_ z2X^2Ua$61xLxz=5rwNS~&L5PGp~=l3#5`c&0MN%B9Nz`f8&+Yw$su_K-zLVUF_W$oOF=8WrQhK$NBtqWyU6LXa;*9Yj@}W}k zaAGIoAR@LBsc2NX3?ZjEamhq zPf||dkX*>UQ<_nEAt2uQqZ74c zScV@~f{*!N7joU43bN!{DkWaxVw=rlVC5x^F%?t=rd5s}VWya29;TEiCSX=&V`>i^ zlHnJEU>XL+D^?SW?b(STX721|cWE0wdRt}M;2()49YWw{e&b4pUJ4E&W47jK5~gVe z9uyLtim4t0il*m~ChF{FZ+Rqb&R+BdCnE71Q@$mc`In{>;ooiIW_wZR{^hJzHX*0RkW_u#WH4GDI;LX`CRlGKXTe-2MFI|dZYMy(<%M}lwRvRjJU*d*G@a9QRoVkUE%V$sFtA=T%KUYeTm z*-H-P``yWi-i?sf+k%A+t8CCtIwH@xC3N;uLb{h9t)W!L=p+4ThxX_G8KJ#pRCG;b zexe(gE-91RD4C+ogZ`x`j%Ri{W{qMgXA;bo5?U9r<~ObBW8#%hbsLVtpmpJAwE*g! z#vDS)XhP-w)DI3Qx%6J3_9edkjPU`Bq`DBLR_d5i+qRV=$#^NJawwa&DV|E_sdD6d z7G00ZBH>tROfu?@&1G}G8L6tFYI@@ls_slZj=(1|O8C2F}YDiw<0 zwFSK?E7_@R$6}@5h)~G3 z6U+V)Y{7o0P>K$AHm6Jm7%YU+lH?sAttqYiOoOyI zZB9Y$!x~nt>8aIjWSq3C0WBcOmaIX}rn5;|Bnhp-+*+8TZ7Bg@BVLwFW^KwAXk|og zxlJv<+Dpy;OVj2pFQOLTVw=qAY-k~^hFGjObz#!tR+Zpt*@3hM5Ta+U1{ zth?@Q)Se&P#>Z0yFT=7~?#AvRy5nSi-JA-q%bu5nnyk(J2t+Aw%a$$V#;xRz5B{?G zZoD#5hLY|xY%bph;Bz8u^s=Xyx~|?CuJe-9Yf|miz#PKREd7%2!tgE}`mZwv$^M2< zajh@n`kVmwBlK7d|4tnEhHoBBU(b4`n}MbL&hNRwYsXNq`}!qpR8nf&zHabY;F0ePA20NlO~b8a3B7rWm&QYL02%5m=Z6s2_o{?Rc$d0ncN^+9&_@< zE%5&iFs70+PMR@sZq6h>+FKEs0kvAm=rQclaxJ^EC(~;%r{vfWGutGy zT$Jr%*M^r2KkhP*ARGtcGxst9|1FWW6WV=q99uCif*t;La}OcuDbtHl4KX{nvpYW% zJUg?~^>TPVvAVurK2v8W^YfJWbD6$!K=Yp{h%9bk>7<0xX3(8J&o?XgH zFR?nWb4SzIyte3`&a`<-GC!M4`zq+n4lDH(DNoZhQggI&`fRDBwAF?*5PQ=G*RQAX z3;PIlR3EiQ(zC;WH8OjlHT!GW(%DkkG{;WoFiW+4P&J?(b6R_IguqQ(W7%85^#=>r z@btC&05)Fpk6{m==G7ft6LyIGa$?u6PQ_DW)ASwvGBkrTT@7|+M>e})c4q62hjF&Y zI`(5zlVw9HxUi9FZ;xkx_NBu1RH<}bk925T;c?2gbI^8c7tU*U%To9B9VZ`aTQ*52 zwNi8C5i3q{du&Uqa+&=$WtA~iE@@Yrb?v3LOB!S|r?&nm!z-UiH@3-FZ3kj+XV)O6 zWSx*47h3muqj#x&_eWnMWnYbUU$#916&ZI@d)v2k19yI-oo}j7b!qo|!#B0+^?gHL zfwSp>FBv%tHMRouavGz9%QsL5_=1^ekyUu~fbE0Z-Zrmo9?r1EY&DMFH-1OBy-{qT z9fyI3xQHjXmeTFQR@%fOx6%2E>?vW$5*JYixsVIF4zhTt`r(fgg`_OGLj1S)qN`_y zt^;drpD?+V(}R;gxslr{?`aFERk=0%MqONaH=xIsWcfSOcqZzNmzTE{C`D7mh%(TkGP$@B8km&mLx@~(*>?CI!T;HYV<~HoJdvBMpMWJT$n~(#Q8R0 zyLA)*UHCb$yU@X|_eZjasOJEw)454l`bSuYR$zx?zmj-Oix_IEb zV}Ltsj{BI@%MW8MA*4G<2ne%ZgMK7MfBeU!dxe11MuLb4rpw4vI6R;K`-23$z()y& zhWfdKxmJ`qVwgyXu!LeLz=*&_iIB#O{?v$U)WmPpM4r3IO(e*k>-mdtJWkB`v<^JV znfu6-xzT$=xCguC@;FTKbkQF@)c-ut%jv6pTXVZX)Mx##?-rk+HGPW>)@yy#C%u+` zYSn)|@`SzEA3fPCJ=F{S{4lmQ4msV|JyAlqGH=R0?%IQ5xQ-M04#WNb{d8IWJ%!t( z-sdXezf;>MBCQGi;QynFbFjp!aOA61<8$kV7kWnX;pDq?N)LPI_ipBUD8+pKIRg>p zmOczaDZ!2YUKxJE%GS2QK1|EL1(Mc6NeLBGRlzXjJmk$S%bg8zX3Dod09xto9UqdyF) zzl^j0b{}~KHgiq0KIPN@7~8+9$p8BiBnSZFNS0MI;u%3xyk7wIB44HdWe|` zx|ph33i+C=dlxHf1Ni8PwM$%F)@xaJR13L=Yz!TZ^Gx|EmfDO(EzRAHyW8YeYpd*S ze*RnBNrx>wj1C|Fojd;f(q4ZnuP?n#7^r>E559c_bq$>K#2K>}HTo5NSjk};P@k|d zNhA@XMnf5oHDc$;6UL1s!9`@0&?3WzC0n}cNF`QEP9oE}ygBON8J$j?s5}T0r%*CM z`xue)6XnpQ$?)(T#_ZxBrc@Ob-I4JkO{q4kdgb$!NZ3YESF-$y7LmtGNvEZK%j?S6 zKW(SNy^Ch9+bwmw;{8ih%GGNjx!MJc*h)~nYWn(33^@wpo^ma&dK@{k*e*mZBO9za zGquTB17Z!0T5K=SWNDh+n>sdU%#~e_Wi1=AK-{fEzJ{GUcw-a18=5{XJh_@v6OV6F z4t*+VB+j2lzy7W*&qBS$v3s?}tNL>9*tvA?{pI&~^2(jr+1~Fw`<4RPz@I%oHck<^_~Cb; z;Wi?EB~m3~OdWc-B2(R+sM2OJ4)vg5HNtq~P5cd3mTEn^#NRyBZFR|zByD(95kcCh zUg=j4vmMOo04?;QC>h*<8U=$3jWA>CKyGb)i)- zY|+V&owPMZCYyY!6N*FQ=r|~$h2j~gpozXjN_>qv`e>xBY$K;+epcG#rEg41DW?(9 z^Qmim{)xJ%L8Y0x1*%OE^BJh2x(XIFtH~-PtsF&jE32*Q>JK+E;hHP3PSr`5ufH1m zo|_yhD;TrQI%^!Xno673nboGJ#ipWqn;?4Y$c61%^6a)|x8;&ckTTXTyKb~u(vmK_ z@k*wVLiO5vFOO0J#BE^x`U_D-`|>;R9wiwZu)ql`Odm)MBmD4T5fe5s#TCQpBgT4~ zyYZbJ_jjw6*}=#Na7u@r2QE*u1;OA zye``IFg|7y&+=`uuA})~=hQwQ4z=m47A*7ToHH9M=+kymn76hc2#DndrHvHjoR%|Tpv0GMrb3V%N}Ti@ zKWa^6?AP7;m+>c_cK-VB&wu~BoR3H-(kN^Z8Ac_Sr00I-h!~+;$i&2aq6C0R- zEgGPUD*U11;07`K<*bHFMBo<>_{KI4KmkfTpaF7NfCc1m00v-U0roh-I3_Rw2tXhd z8z{&Hnh|v|Bv=O5$VMbeG64&)q8#0bzy;ip0hTO40-~q@EZQ*vfK-4O2cShR!ZDR& zgd+kR07wSZ(US`}04l3E00eB&mJ|eF^*$9LEM4XeO_byf4PeVSe(?Z>OaL$cs6+%X zfQbx1KqYf%fEzB*k4;>n0+b0y1;`SP;cVa{&({VD2{Rv?D5e|_3I0wuj+30ov|=0& zpu{(Z@{@ktrzqQ~M;y+QoN_c}Efwj@?KLuuJ=zcf+{wgjUXq{()MX*bd4K{W^MHFC zr$i4JP&wvtkK81rA-jmgdA@O)2!+Zo2?xxEY6zkTIOGz=m`t306ObuIsU2}T$5T?$ z02W>1P>agMFsc%cThwMv`MA^so)evpirx?-Hq#zzwS|d<;8fY^qVWCgMl^fqR?iAT zOLp+9?xWX0+L{=nnH8;ct?K~TswGB>wL~GZt6$H$NMUHme}pZp{<5bd!zy;MjGZ3} zKDPwK5%aHTy{c8N$~seMk0DH&D`mB6S&mp%udmpw==6p_{%sBbke~fvXbS;X!o}7; zkj)cV)qu%-I&rtTB;yosdc`j)b&D%}Em%yrjOo?Z9`5J@CMgQtg4U6bcnoPD4`@=3 z7WXT|Jg&BKH;1fXa*~yd?iV$=+D?9Qj{gj)4aKO<0zk2*$Yh{#Q)U%?m==hA7_T?^ zxY2H+vYF2ur!={lK#9^ZoXlM9bfx;8+tOCQ%Z;pf$tlT-QjxcCoM#*BDM$BSvZO?P zYD;A#;fZ7kNuq0me@JOgB`f!Rvs{;dt_yKv#h8xcWT@Jo9h>4 zOwb)ucZt^ZBWoGhRd##vq(6;fkG~CYSe5>pM1c9<3SK-^^Ja3B>ILOL$H-dxJ~NlP zv?Z0Tm{EJaJie5?=oiPy$#IIv0ei&*vj7JtD1sfF zM7qm2q#5mM&o@5s_1#TzW#=Q-*%#ei+lM#Cbz(Wv+2Pnf&Tf_H>dNxq#w_up!(d0aPglnvPvg~+TCY9rA3b% z*>HRN<>&tS0l%K?lWExWum56;Up3);devw_fBe;7Tjo(Y@b@Q`R$0PFrho;Q8rm}p71(AM7=98cE9hc>BgjAI;C~+og72aX?YBc5=z!pd zfbB7X#z7n`$Y;pnfiTlJ(so<_@NqWSY|52`RN@^^(i=a>L)ry|K7@lXIE3OiLW$Ev z>t=NA=3DRB_<@uCtV2ibR%U)4p&!#{!p~!a`5F!&V)eJWoi988~*&;8_{=L>tC#X-7{z#&(&=O|$r1bw_;I27_-% z5B#M$WLJ0+g>Z?-V~a;k95qniL{6KCcb_<7<7Nye7=!b1itgeFG-XrymQ$_AQ>z7g zKm}F*v}7?>WxIDtCI)(=h#(j;jlXj_*;Yh{oE!hocskdoCtBxsTM7;v8fg{LMiYg20;SdR%p zI)IWn$&-U2nOL;`mQH7+YtRFdn5L4NGLcT$Q1FM6B*~Gi#*&NpNLzN3V~AOwa|=I7 zVLqu}ISE@r=^odUVmFDD2%(fZ2rw5(m7w-2!;?Bz36)VPl_=1V4*876$AK}K6C?vx z0`Zk0gl$TJIa;Y%W@%Mln3mTTmOWTnZb>TbI1RYtZAv(o=cp(n5ooRk3m8L^NQgvK zD000eMOcVkS+s?I#ed+@m6t`B)xZu-S&d~_Z)a#n)wM_0wL}m1K=Igoff<3Kb(y|! z4Y^o{wI^VBSaR&uhkzted8kXs6mu*md$a^a3vf}0NN)A9HAESBw3ZM<2VjvXMUyz1 zOGiykmqY#ymUNt0V}+zrF?M*unU}ylO*+#3#obohXNVIkegijzfPX@J7 zZfA3u$epE?ZJUCZ|I$4D^NZUFUBZY&HpY0yIAiq2QUS`32Uxg{}UoQ%Rg9Jvff zc8yA=Q?8ec-MD&lgrSl7R96O@cL$imS(!rvo|XwdL@1tg2yXn?f`mdoqjsWHgOLn% zIapC`2@q~{2BRgqC)3l2GGvx4`jYz}uR*^Vbq^D^T_j7AG5v0gNKYLk~ zSsHpnSv0$oqTzX^@WZ8j16xaKDKt1frNA{QLzZ6`rh{@BdUKg(Duk)YC*qJ!I+>p) zX#O#9nh*;mlWkfs3rIkJ8dH5UqjiabGqi{fC8!pNf%~bYjfRT?w=;PdAC zhOqyIM5gq4M2lNVxLWOpMGvb(oGZ02=pfvOPgTUL)>pXkdPE+ko*J7(57$#x#Icbm zQ6O7V^ZB`~K%Rq%@|i%?HCJ<4 zx0@Lj!NJS0po^_C%V_V*w;#+ha-f{`C9uw!c8XhzJ8DcKrCN?VM^`7ghZnE3_+Q7% zz8O-&ojSGZYMvLXx&UTRf5=|^B*5^guCnOF{?)`xe7g-Q8b55pHE6STd0bts4p|CYF5dXe0)KJm-)EK1?eEw zD#`RmM5!9eYzC+(T*(s4C^%Wlv23k$5eA@4wXV!Isw#iRx~t3QxnS9Gn2HlhFoih# zPFDzAk10hM8nq8}Z&RE-!b~LTYK!X2tw=k*eDp<81wrQvrK0ha>IYE>e1|0WuC&Qf zca)wP{J@fjn_An!&>YF+k&5LBi7SkB1Y3zoWlJAro!}IplW3h7=DE219^tGT70Z}J zoSsG;VtQx0llw`c1jg@a0D%}(2ZhMV;Wq{y6ABHC_5Rky#CUX@*R(x*dO2&L9K3n* z%+WwZJ+hq16Jd>6TgTe?di11PbbEPUivZl(p{k^w+-$b$xS8dLSp-SBAmq^};RGz0 z)Jv$NqD)qOnYrQ?)sEcMqF}(f8&ABO%qN>f9+cIKyw!zbblV!fpUH4aOVtRm$!9GK zueq2>WX@}g&If!@aJ$ilBh&SlK`G3$mxQ>_xz7acVIdndL{xb2RBsr&x<}l^60O92 zz1R!WpEx_x0hVDp=d+f5*~Npk@Jq)BFuy&;d*Qghv=^L39ommJXWlH=ukDp<=A!FM n+e8A@xjoFg&D*-&ezX1Ce?8N`ZQRF=+{vxn1u^h2qxx=DWGy@B3^v z*~}!9na$2-_nF;)>;HBE*vj%s@&FiE0Kodc2KaXgz>)Q~a`Fej0N?=tfargsYXGK{ zwX3BKzV7gii(DcijIx`Kfp%E#KOkH zM90I!$H&7XCnF;x|Mb6rK|(^pK*u1)#wI2uz#$<0U&a6L;NKts2N}j4@CXNk1AxVW zfy06MHwyUAL0CAL|L~uq{}%{|aPUa5Fv$PK^FNyZCkFuF;9+190EkG~09Y6}I5=2% zcvu9a|Dr*FfrZ0?M*vXca^WFL(P(nxBU!jh(}okImb7T`3@z?ide9Nxv}${{@p|#` z|A~-kr}rKv5RZSZlv+GXe~V=T6qu&(uSAlWITEQZ358Y{&N%u4hJ9sxSb<&_TgS4@M`Of66|BD zLpJNhAtp~YoqM@KGO&^UV!ah#pwU-V@MNObn)4Us-acWfV3I!U*+I%aUmU z*0{U1g^9?^beG<-_00Y>^p|nfpUk0$&L>z^77E1vu=0dv(Nm{Y)p6EFJ~=>0bGdM# zS=|nBw^-!NUS;ITLYYyh3yJT5%{uNw?xta4UsQnYz zO#37uVO`wFFZc~tztJ|W!SAG#z@N~OhqN$GV$sweVp$ul430H3f%@xa{M0sZq30Hr zne=e&k-)$z#=0RmbWsS9E<~3?(-(ei=2ivc3p(&<9Uf$po4QhqZj89; z%2ud=Bzs+}e_3PG7`Q}q`~$dBBLMv%(@w7wf4YL&L647%tnpNwq9P!}NNgpEGrljF}9XyA3wsvs!3N>GUkspei z|2p$Dr$0$Ktj&0vAGgV%ge25ps?OUR{aL36Hq?jbgGPs)oO(604i^MaYGec&Tb@k| zAXA#iT!D65_TBniJ(CLIIfKo!3B%(OMyL=VBd$M7Y5xKk>mF74~cQ?x6>py@9-~u5!O&zh7y?H|T zKY*?dDW=inGlsJj7M17E%s{7m$875k($hIuD&Dwk_QO<2yi<@#rxtRg!q?80SqRv; z7I{f9p)y)q`mG=O<-oJvZ!_cQTAkP7JMKvmTw_ywudTknR|i{v2FK;hpog6gT^?q6 z(TJ)vqD`1q<#4|7%&5ke5OANjl**nZGOa%U(&)R3v9_Z|s|}&^r>ou5=nVOaNfp{Q z+=*`p2j(tf{A3QSgcD^|4Thy?`QVM6EyFEQoY2o5JrRCQVF!G)sVc0(uLbUBbM1Gl z1BGt~B(O^GpI{R&Bg$`S)4Ef}rBKVe-hn}51#>&6kOnsTHa6ZE!8 z!%8wkItjWJUl)>Z*;mDAMD0jXJi&v#ESqK+`ToD?jhL_3OJ+CN@;q4fbR)}zd< zW{7Vlz63aqljAsV6RWBGxaIHY3#1R3Y^U0=_F86RqkW z8vpsM7bbj5Zd|ke4`AC9U_YU&b@a%zmSB_jd!n+pJ4P%qs*XezX%j8f^w$~?cWT`B#oKnw3-2e6uP;eoP9RM^@Ms8x6Gf=u!lA`$$tNm_S z+T$JRP5oQ{uNi$pJnV;@tFI5Y{=VVrVw|Yl0Xtpqa-PCqSQtg}y?~Y37h@0Gpr+ON z<;}e1Eulg2v`nu10UG`ljmC0i zAN6H)f&ou7JFcdrnxP<}UBs#(YS8?VUDCr3X-(bTePk&&vdTfz8$00O5;)OCft zUTl&KgqP$>#2PJD1=}-IJ2YQvPo}>|Sc@GvWp&(zta`5)R>?il49{sDw-U88D-*dZF12CqX1sFGvrN2R{H4zV{{T?NEfUdePH~ngtwNEw zg3YCJ_Oan2uSPLVVoilnyh<00vpSzvFxO~(6TwMtfixK-_MwZ^KLF+)+NE!?W8}NU zh_YHz5xdB~VwoG@e3&~wxXIHh%5nSxjeeN6`x)BIJD0Z6yv z7~lxvSm*l8?dEXQcDcY9P-?~$MmZ0!=pBV@0tL%6}T8wN#_6Rn)J#YFYb z2wIle@VDK7B$~oJ>4%Kjgrvha=V-Td(SLxeqr!kG<6c2R^vka~<>ro1fVdJXh<4HV z_HJ2%B;WMx#T zmQad}vb0Q3M~#voR4i`W1VS_E_S+S9{2g`blI#^R%10=N;jZFavVy-+cJi@PS`VoE zCgv}zCmELk7omUrg>mt@RiU7*Jp|~M?%hcq5-^4+ApLCRKW+D2?IE3WHY0iBKj&C>%Ss(NsJyd3^hI?+Uy10 zBU2~(d593J($OxR!AkNnwiK(IiLor= z@&qb)R52ETPh5OR%F^ zCcB|BBAai+C%91e!saY@f??wd5f9Z8nK2XZ>z$T2bF2Z?@uSw1r{i>Atib9^hCvr|UEG5wnPs zi7yAQ=#u-nk=V)4oG}(h&0~9pT{4MDDyg^&fmM&L%5M^NlF^M<-MI2r3|_3C>C!rW z|92$HiRGfi7owEEJ~#a3+T|%H7K&j%T06Tr^*Le- z3){JD5c)Len9U)N6Gv2Ikv3AF?v@<$&=woM`Hh5{)M<%)@BP49CFM zmVdLAMEzy%_(rq8MU!-_cnxj0Ut7~##bRs!w5JeA-z%ZHpsoD|xi;dWvYPJ4^|{?I z3{n_g4o%%|I2}D+xUK!A`v=Lzg;5kX0b(I7s@#OV)aX zea_uY=sn~P#c3&?`(&ywUVzh=h(n94hVkHSwq7vahgF-RcBYs&7Knk26cx*jd_RG_-pvpwGqz)HHTB;&YHDX*XIFPiR zWvQMU(1615{m;R&nxKs*aD!t-8T*KXx;>qlrhil;BD#amAo}hNfiIggF=L#H<;wzn zW)aEXm7fEIYpuv9Rv$-9mNHc0>yvjboh!dj8x1~o{bA0J=F5iAH*rqYvauoco%4Ld zVESLtxD6U(lcjmuswm@^^81M>8qLL;rknGw%!xy|3Jag&@?7e-OuxgE>sl{i5-L1O zj2CB%wyK5{&fTtWK}^F0=}KY>g~X{A{@Y?W`Wc5zxtH4$t(sryHaPuu;`~)x5WW-J zjkdK%7y=S2C|Jj4?Hw9KA_`XasP1Lnl72HM8s2zph$Z{AKCFj8$} zS$|P|)w;?O4+JqIpx{IEF#Z9m6maM{l=&Z)pAPkYvwHSq$z_99#koSFMMzibI_vsL zZbx#}Kk$ys-A?+!R_kR_nmkM6hZP?QW?hQ`4Q)+k&PkIy2=ZFIkm zYT`pPx4tFYB19=YwHW>u5G3sJcGqG>Xj?*&PvD*Z zxlN}gUltWv+W!FzqdUY!<+pMLs5k!stbf5gOk36-bA8aQwVI#YGB{j2u=({$uNY+8 z7@|gY=6%Qx+9&q7NhLG}Sjjc}MdLcL@g*2c{>)y7j8~#*!6!vl8~wnR4xEC)-H-Bb zxauD;LNjR&ip&(iRz5_KbIFTzq^POjYb9J)?JWuP$hu>FPLBQ(LAH%uhdqgxR!}&w z%^^&ow;o%q9~HmINg()+Z_t#%6=*RI zPnUY0rc_g^7+(vLA`D|zrR_+Ps2QedWJnet6Szd@ro`r+YrXl|+O4$XqWeQQU}KgV zNLjWu>&_mb`r3a$^i;&0Im-abm33De?`0V7sHR-(;5%zDBHX1VN8D!0n*NsVcglQs z0K$M3j%G~f)LQvyFrk@reA4e9@%slzZZ#pkzA7gAtd7LAjps4%MwWVT%}jGAlIVYt z=<^0af-4^{{UFBQ zpd?h~{mGMaNrwyxJI{K`ijppmxzz8V<7LB)S)}$qPHQF;)z>ldb~%{CTY!u$Qr(w3 znxg<)^n0fHy7f2@X-Y$q7%ov_3Z=_%lV;2P>Pp`-@q#9B{po2=s3O)-eXHIv>pOdF z_?2_HG%F1QrYWP@S z=jyt|_DvtylEo#;C8Q&7!&WCp6&Si$#jY${Fp-`hE5rPmQZ8v=q$$~E!-IP}Z%pj4 z0d;UtgDGP*@qP8IA8SN`xRy8?VPzs@)BFJ1-`7BKXP3Tds)?&h7M51SGWbH_p3V`2 zKyPkC8hF;oX_3lMa>+<5o2j^OAjoHg`sr*9FkQjO^gVW$+kd9b>@%xlnlEP~_QQPN zN*6%|=0{$p&UE&i+@YbUe%x2>Gf{Iq3I9B3%uE`?yr6}8FbZ<8Qe*L+E>5Ce6jH)I zC%oqne3Of91gqO1ZnyyXmqTpH#t50x*i`9y1&pnMnHAikO}$h864;+%qWh%NE_`qfBEQD`NM+PPt+ucSKU9GbXkSd2rqnbae6I$H%LD0>ZwjSod5 z9*#fuzqPiDofzyjor(8s{n+uPle477StkRZwtJ<_yHO0Gj#x5G<^tn!9Gua3!xsKh zzz8qm7aN1Fkzp{7c=oG$Q)kvZ`bRGXvx8@`&PWkkkBx0j(tNMRaVl`_3avNQMfms7 zC!?Fo*i=ac1(~l}Wysz~TEjzt86iazc(PnsjKs>~blAl98he~uP-!)BwS`IP zKf_<#APvUq6kq3MpHyJDYwWpB8=FMmJ8q}0q#?B`2i6Mbot3`$O#tpJeZd_WO$2YN-YX;eFVxIY?a0ap&Dk^=>t6ghBc9 z@+RHPF+C_|6b=MV!=w*!P_#inOJxK9+JgHDv=?xhd!89Wp4qTAI``*rfb%64!s!jl zDA^lSARv&|3YQ--Gg4s7dFgiPJS=1Bx(M=wHk2#U`8Kg`oSUj4!}2vD)Ibhup&1)H z@3iM-e1=xr+CS#}^;4x{N2It%&`aD`l`H7|!?yheHaZ)WN;yAn#OD<%KxOSf)s;f6 ztpy?9iF?4P3_`Qv-sklF{kB`b>`8JK_R*zjHra_{PkZawG8@2UMNhbqYmrj(x<&rWQrv`6NF}$lv zpWB3Dps=()W8d9$1*~D4j%(#EQ`0wI+ceFQY`julSG8O2NNsnv5 z3eK)>a9Cc`03v!RO6IvsyEOZz&n-;J(s19jfx1|ks>$>>)f?joxHG^=87I!4ot(Sr z)6n#;`0A%8lIT#S!2#MY9aEC%=g!$_PnCN3*?blr+%ZT(_)M5TbXc8(L-5yhwPN%_ zXX*Rei2F?7DB>jX$17VW5adk%0X}I+G->pf82!2IRVo+(hwK{%@_R+kR44i&Z#=g# zk>|C;_I?QOGd18I1+(w_J{ixLJQAknhuE09*gZ@T$`SDHKt4>-5R^n#=$?=5PA$`R z0sjDsdXlv)<;-==jQho>r13PD=$IeZ4*72IL<-G9OoUVWfT62vjdt$P0HHGUMpn~# zmW#nJTAhkCU6itP2?B1Cw}M9#%pL#H#^JhRwN}-Q`&HRZU{!|>`T2Y%v6@+iX2TN9 zDupC45+ci1go+3WN3O4EkM?q7KSKPl+YI54^lRuNmR5_{8>K{4&#X!4)+Kh{s|-m2 zYG`DbpgGi0{pTYGTUBq+xkEwY!I*6kF+G>=)Me zlO}C4L&=!CILxr@Bt5U8y|ok$E%N+e4$X!Gf839?2jI%oP5GiT%A@y31L_`-X&+W6 zfH9fxH9OxNxiw;VB(u`HvYBuZ#M({B^*Rf#)bR(br|6cNjSf?$uxNm5f3zW zrc}-%?8M{sSzUy^aFyv*oWi0tcc}1owUq4Q&~{%j_Mz^C#Hrmni5NSl2eYM$;)SzG zQ>jRav*3i+z&b?LE6 zmdu%~C`1q4aoCsaMK%_Aa^l$AsD)rAA*u9}=Sm`ZAB<*%zf2iv>I~%QWi!i5B3V~6 zSp3;B#D&=>x$C9dxQDFQ@HVAO9R^?G!-#qzmZqBd$Ge%ur2SiJvodJWkuW_O@)^}N z?}jy~zZ$p1`p)0tV-CY@!8JPl`U$s?VF5G34yeFk14 z-pl^srQwcBk4Wy`slL-EjNbhdI8NT~Om*#H2-lc2MJ$QT0jdV<>};Qmau&%xVeC zY~dQbbZR1Zvt6~^Imx0@OyeGB^7GPF#(Y@sgIH*lrdM=nzIBux!ei1S zi3i-K?;ai|E>BjjOAl}0s}gOf+8v41utXOowY_*??u`W7$mV}Xj=eb1NH9L$&(p@s z)~5EzCkjmQ;wIvDb-p>oXgld{O_w#`Uc=A{Y6*)9`#DGLXPfOfHLvUf?w0aX zDxV6J;dU2R2$}V)ps5AY?5lg$F!I~`f&ptr*@-yyuCmUgtZyqX`}mNX@g37Jug54HoQLa;c8Jm{HD!zL;rJM0d-Y*8ohv%4g4y<}&4t2&6 zdV7`^;(ZavXf;MHpQCy${S@tgWGq#KPa0UuT2YX<@vg3Y*}pPIY>mydeM|hbNl2i_ zJ#!ED)o;Q3qBHg9En$OVYysSduuca{yE^V4htGzA35ma8@z^jh#j&MqzC(ypYd}Jp zO0M%at4LFC1waVl?o%W?6jB0dtB*Sz(WLBiyKHH^oIR7O545PwNY%U4i(>^D38+t% zNq1?|5X4^LZi(C-xd&JjgoTboGxfT~xn8H|D~4hU^TrS!U~QS*FL7iCjWAn9bw<1w z+s1CB9kdP^22T+@;f#ixj;}l=^#tzo7ESOZB$p%VC%~X4v0igRuJ=2(py#@QC6rq= zW;U{N8QuC-gdt3WsEavg^Ka~HHSW{SBF`+Z^nxdE-zko|5`wpd@=slsj%YDRl9Ft9 zhaw5x`nwiW{sDYzBTZTB`dRhik?%kO9C_l<^VE;r#p9%??yw5^cQLP%9y(e!5_^+w z4V_h=nU-nNDt>#YrW%2MY#ph0g>dL(ty#~ZzTb^0YYqVe=IX&X$2HCL3`m?Ymjxv7 z@GY~wD`6F_O3DoX+2kcrLS*5Wd=euCG~{Z8&^ypq<~X_9o8ef%Pb94yl_mwFubQMZ zhkxo%a}(7oHZRf)VR3=0bkvuu?)pOcRkEC{m2w(O8`}0o=0mZ606b-ag+tPBzlzaT z_neP7nqQ|Ufp1GDlZ7Ho9=-yykny)o-q^T@b%_#G!Hb3U7#tW|p>GA0ta3LypW~=^5i=QX;%&ttVJGkr7$sKZOk8xnGl!3+#^1H4W9V~l_+{QED z;hz5i$_$r#edM+VruK>G$g||iUV@Uu4cK$`Z~H+wCh~sS3{{ahzbLe}Hcm)tx6b^> z-8f?ma-Q{+#R968=S(e^PkT-DEY*D? zf;)I;EMr@adk=}&-e=3=KNfK+ssT|x~vK^~G zg9nJY?S9fB%$0VOX7P~{bW@z$PE`Di{7M6EmQ}R#M=M|IW_>k9q6t{-=kwL& zww{b2a!4>}wDT`4m$$Z5R#2{u`>j52ru{L5^E>hbJIXr)M28ROF|`5>$zCs->Y0dU zvUkmtI@JFVeaIo9WL=~Bk_tl1LO?382*+o0c#ccTTX;%#b`;$^`yyYYR#==R(Si?9Xs_P%F%!s7>6YF=Z)`-6OJ{5+5v(NBN=2nzD>K4#8>D~ zOH}7*!!$0G5tC^^5l7Ej3Cv?LA}IYn!a2tYeoJ~el)LLo5)VwnPx;bw z>JRwt+)U4AThVV4!6B(cml5X_vmSN0B;V*Db@e_#Wk11b)Bqe`0`u6|YIG&Qxw5`QxQW^jSu(EEtx zQMIQde9zA}CzE1=PMF(@YB6@OKl=2ZMYB=;h|tI>h2IssSv>w*l2|K0ydDCg4LHl9 z;U(waZgAw}(3F$nk15GC^`WXG4H5$Od%FYag~&WuCf$Z|sPwc=i>mL=ON&M{z9LAM z?`o;1Te+WQ1bu5AqqvJA6+hsj5kk>A2WPP1C;RL+g6`G;VWrYO70j)o)?I^7+cLD| z!H}A7eozNpT-jLxsv|ZK`cK@cDLhAlFkhX~KSxX}~Y2Tjq1Y2_iC>yzD zxGN6`9c)~>Y^#H#4jTf6A6wF(m_C;iXp3qp0Ee-ks5oVXEWc$Hz@o2Y{#--;^1^K1 z{{Td=%vq@u}B=cK=@E75DGvCL`K|KG>rhqB8m0IV2H3n9%W@WZ%9tO)W!7PpOzC z^sGd)Yv-VaT@rK*ahXgG0PvJg4h$Vm*SNGPQ)*GT@W5{H`cP2>G4 zy!?HxkdPjmM!oZF8%5pO^Y0Q<4&7pG^d=}*gny$|#ye{`K1)pf(r2UqPzm(IJgFZE z927h_O5XauMNSqMU}VyQsQf`ILTEnDcFPq}q!nc?PnDU*&vIe+B6?A{N`}WhHWtGQ zzVwC^>Lf%U$?^cFiJ*!z3MKlDNSCEb=pf5B@LDAo{(6?Slum2vxMIdC#!|fryG%ve z*0!sH4tuBCx)aDb%EQSy`ho?PPprx!i|b=SU6@IemjO?Z#uY}lSN>Ydhta6!xV(96 zAkWrdRU@m97q$BqPjly{7ttSZ+WFh0^H~jp%##K!p<&u>X`EothTuT?KR%e{JX&^9 zlG=J(#VX`Ojv!%CZKJnaHVnb~FhNEarS$jn#b%KAItEvPs;4|%(cFCnNoYo(~Yfu>wdGgk4A^_)P+y^rek;8mICv zQr3Ulq*!B!b#Z}~L^A<3ca0~vhhkC*R=FMh5ukAz5o9;ZBr_ITxyz7AB*EfbC;w8L zk*}4Bd1wq%{K7&)vi|^DN(@_HZd8aa;`-Zu!PBL0s%)D)BGR{cxxXHaW@f66^X-G{Rn(CwduS?eLs*Eevs+IWR5e2u2-?OAjLTw{17xbu(_Iws1I8~ z7L%foz_1)8e(CkCouXP&j8+#0a`8Xs+m8z5_^Tf5^+r@EH6EniO3wtR+E%vpbVQKZ z=3&mSn9m^}AoM7w_Vxz==6;TT2wUy9Zy)9NsUfK$Uk%}Y_ABjDnU)(MPH1bJJq$U*7@_7}H8J{~bPvSfpcrj#ofQ6M!Ak{?u+R;Q|8}X= zR7-vedRmZBS6(yz2OwWe2xmKp5^{Oe`U1mgyaSO!HdHi%fikg3(NvbbdiMchaL{B2 z3y8E#aS==uEBh-oP!&n6C9hd{f;MQQXNe`3hQ8*O~MKpK_T?;(`Ej05&ie zu*MSAHJXA&5q-zops-ga%N#yN*#7$6+r`6$`$5?nDLf5V=T!+^ z`SZv4f@|p7Xta~oxkTvjR?%pz0$=NUY!cfx>e--SFXq8vUaUp{;LA={OQZd7<53Ce z$=>n;4C&sDOl)4STqUwd(3g(8rS5RPQgdchp@hCrcO~i25l3wGlK=Qh&6Ryfh7ht> z*R+teKQ#kNx#iNeUzSBTRndqMA>X5m>n#4t4~t}8@dGqZ*j2jg5=W40HRB&%iNyvd z33f-bs@Urrqlb=#LcvPb+>#MLYi%SH&vYQvBt}C=N5e@OYH4}RlG*ltaep_)DwBlB z)O#x**BVQDADMH2gBes9Rw%ytXfDJn|Aq>gNu6d% zfdwmubW&!KyJMq&9f4!lBhSm7Eb-<^qhBaHa&dl$BR6mcc`Q@MX2AZ2Of`E_VC%b2dHQ_6@6CuXCvl3cx(OgGrc!nfnxe&#tehtL48W z*&2>|`&6XJCfz+6&^2jt$tMn62Knuv@(S z->dtZNOv4U$cM4B{An~;HAl-vZUuX6W$1?g01}xs9xHYE>kabLd@0?dR(}yMz6l{$ z2>5IeQ>Rl^j8Q8#HdsXwvt!|L-!cV5E_jakBqL-&pDRB&R<0=E*-A-OU%iS+a@QI0 zt}9Ohel1t8!(oBrDj0RLl=-UZ{k5&4}2irTHCE4O9bjE&mHe8)8<@p4}N)penyefJe zczXOkn9opoy++Uz7(pr46c3)XxJa48kpt)rsV z1t*(B-+`*?PItFF;RHPZLRP;hT1}}1xDrR+VV?xw51l#x)B0y0!J|J~bY9#e$;h&An=jv8Hcn2jJu+*H57w- zuy(L)l(*=?jTbBA#sy8x%_@tzRmrc9?N4FrhGTRj)+<4&A~1J=zoTG&!dWv5)v_ZS zmcrfy@E_?dlVit0u8^Erj}=UCDJCZ)SaE-xM6a<1 zLtK(NkjAyQeu~szL8lF19_!ihOYvON398FD( z#yjk?uPBj!5HCo9}8@-PmA9Uz2NMe_yUSflpSsWTWkS_tjxWNr+5ORg-ClCz`x12gDb#!8fb8 zriOm!PIZ9i;J=Dai$Ki!kA92 z`WJQ4yM$(3z;WqfByxMQU93XcOn!{f`3@_hrfs2;))jkHEwKTrobZiqZpJ^rjbLKU zMH63L?=b);KXCEIo`0u{QRYe6a5@E=tBKozV8y0U6mw)m@uIJ6{Flg9&K5FBbFuv>CaASW9O8JiTHV!wC8mgD5M^{Hg7T>H}A`7YaFp4^gj18G%MJvrt{m1hkhm(9KJe)RU zRtE>uH!S6DkhpK8x4=is&`q=d1N^XFUFBZY<99czQEs=lVwqtb!tm~@NzgG z!d$t0*EfGQB;`&Up1S>I5?`0g5!oE*`xQ>UPvPnXZZt8eus40U4!a@&1Sk^hjJoKg zmqQDY&|F;IF_K7cQg#^lTsiC>$9S7I^pXT=#g=BmbKjFl>H zw=;csSmk;4KJmXysmYjga@ldGTP}Y~m6ZeD2uR51|zQh9+G9yas=38;u8BY`>M@dX`3HstXBC zAHCRAL09+WFMy?f`7V~6l_6EovQ+HYhULvyk@0;KW8@{t2d(D7m z3I}yAAG0$Cbt81ay}tJp)eOPkWV28R=r&)8(>lyElh*IRf-zE zx3RsaWKnQFBs{XWt*i5L(t_lAbIh%A)I^TCfjColZw9+681p0TD9d@qy-XYE$Mh2j z4Tdi)*Pkdnw+kFi{cTA_==PSN11-;ZmTW2p+^B_B}+aCWYa%nH678o2tFdS`s_Zc>$I^tF2jtj zfu4|%g*!v=9bo8aZ;&q88vv5z+qBIb#M297=;Dw_wH3YfYxbP$Vv`pq4rzRmoNN7Z zF=?eq;U6keQ9Ul z2r*Abf9W?+)baB=OEDEj-I|&0ap@&=>IQc>4&r8D zCIw==mFnKndQM^m!k-A^FFc&QqGcA!s1wW@D|Zmpc=trfS~}{CMQcj)h_L61`p1^+ zxN}99s+v+2h(_(Teli|66Yr;L{{F^f9gfY}zF_R@jp=9vmAF@{Bmepzhh_p^&4xx_ z^tN1qvKn{QI>$=sp)P(Ob~-CTiTN%hM5$ZqJp>cPao>O^IPR_v@MbdB58cRUZJVOu z$_vXmI3hfBKdeHMdK=_lrVCEcsvzQqFnUMxY2o&Y^ly}D9C-sSI`{L# zWyjUL#a22=&j_mSj3$Y^c|2Jm_i#md00Rp5TFyON=Wi+Ny%aWBK&wkf4Oh3+bR_)Np`Q@Q-p1ajDP7eP2`w zchcS#t7%^0&*-+sAYTwQ6(!3bJJ~l=4qz+)`m=rwKL#%E_M7m!7J(L2I;SF&8WFhxfsGBH}# zsrA@5f+eOU*eapmOQA?^win2QX!X9as@ARqeodu)bPilPS@7qen^d>kT@T9a&J*cn zt^`ZpR2UW-mUV;7ldeRn-_*psL@SR?x<(5JKV56#B}X)+fDf+w<{AA9%&s!QIh~{` zC*56f_N!3dYiR0lyjRD5ik1%QbtgOA;k9C|^HiV!1Mh-Vn^~;Q62_%vCrAy=!GnxKK1s|(5 zy!m)vV-TSTyT$Puj|l^7#M3q{CraG2rKRkxk%{`S-vO6=TufUgK@C3Hnz{WJPE^IFC zMd%Mu#`uyFKmF|jPrc8Y!2bbvK#0E{NQ!X^^`02z5CSnRc-b?vk_Sqs_Jc9{&15V_-V5RI9A)vZ4Ob)B!& znf}&l(TMDC{!64@iYw!96a7>dW-Ed@EL3!pb*B*N&0pcye_dpO5FQfh{HO$zRJSTg zEQg4zP|y!Tps_!Y16PRvE6)W|JM(4)_IK?A5=sKw6(pgmn)^!~sy7?!a@E2h2KBlv zMsW@X!3VXn$oWQTZSk?I`p=V@yB1bRNk^VXDp$Gx07j|_>%?i82w4v^7{2ZD-_j%f zTxcpt2s+2L5C#P~T>TU_@#F0+p@J)RB+Uwic}oB)8)Y~xC>tnc zEC%Ql)|-kNS7HI&Z_`wrvIjL2v;cKJM-gIfW45}9C7vW5mm{D2)zRAJvHf+c6xl~yk#7}IA0}~+to|O2S*1o!t710c;S-srTPjZAAVvXi{ikbnv zHrNfdCWzMHWbL>wqjTN^iy|p(uYQj(f(2{n)wncJt4G0sDhOoaO?^hN&G17I@!P$2 zX-!wiV%$MxYjY%b0VQ>2jd&|Y3K3NF+iH(*<*bcd%q5y9aq_yeZwPB8@V-SkGC*od8}N zXyE&Y_YaNc1u zwsJ?kerORS7W_o;@Fe^^H9EbHtzk0 zDBVC~UR@L#pYI>*{B@^p+tp~o+7)+wBbrdDBV{yFY5xGXT{jD9krYP(BH6({ZdC3^ zYeuwE1BbXKv8UpjG>uPy8*7AKf93H>>H)bSY;VPLkGOl8+DRlby~DFRnu^ral1cdd zbzAYu6IX4B#gX%9Z*Uo?1j!x6#jn#^!s^T=dxjA{-l90$nXkiHx@ZfUn92PziRoe% z71??DEE~%FBPWT2WVXi*BkxLZtX%xrFB z5wW-`76*=ia4y_tV!PAuKEEAjYOEQM0cSgLL7Ysa!+J)&n)F;teQ{wVmRU)-G>sb` zfS+#y;)hyx^vwvx+E5!}o;D#EQ`E94M2mYX+ky(al?ZuIDJRp>M!f>Z-nIV#w_Z@U z{yz6`i*%Hnb4TsHwU6zA07Q1U!5>UCF0{0cJ6a5 z%{|S`a@~5%D=A=WPNtOBeYi-{F)hi`nM1h>9uhK!MEm{*~+G0~+QNT*+#ztf;fb*B9#X~lc5`k zCzAO7b1xG`VdQdStr!5<<&2`pP?OGCVt!Ik8he(5(^|hB@;3DJm9k03PuwCvZq<0) zWT%Y#edSoYs35);SJ*)972Kzd%E1Jy!fAw3gl}SR$p;6I!~vt#9+;vBuPTe}NsEpWK^ ztYdUrI|;5P9GCS@02?UlpzCa!N(5#Vz(%~s)duAxhGuSUB#Q4jecZLhW6<2>;^G_F zJ)tdRG-mHeRS_iJ3F<%^&-MnUV6hy!`0T+<1c_n2A>3Sxh*tUrS*`AiGRYAoC{FA6 zajzO3{yGP?VIv6)vX1Sz@xe{Ya*1NE_|(!}-TeXLRL14Z#H>tkc%*(@}^{sfHT{j{l7e<7Z|9vQqwuzjP5AaKZ1ZaI>qqE&9{gU~aEq1gJ3Zk;TnSf8S>F?WeE zRHyNLW$oz7`0idynA4X1jb2m z*DjtW(4oX zRU1=4EaG3%RdZ#Vtdk-$QefbDQYlA##L6nAWO2Pf*jI8t&8@3u8R@}k&QA$2c@Q0D zvD!&B(6)dXrFY|AuM)DUk{{SlhMQ$w{wvovR60i!vfZ<9KX}xtp5+v?Xr*Y!Uf!X9Hg8nJe3u(j; zRTDuFh=70ioI-zD(NgKk440hcCZ;wETZ%}?9?H@)3cGK|kws7lJ8}H9obA{ip^r1* z=+V+jRSoo3E$8#-ubSJtW8Yde#AYA~0Q{}R6@lAwhP(C9Wou0+)->z-ls!(L+4VJe zCwy(gTt>1hO%nmeTVo(E5v>A}0`gP(Tn+tbb>+2|g}D&GjmMAYi25YYLLnWhkO7u( ztG6y@yZm+CJCRy&_ZK3S0QA;|hBu`zEwDq1 zyPRNqIWO9D5L6M(6}<*Kbcn)@_h2#LS#9={pnDgea8r zv0hos>l|i`%+a>(LU*sk@gyC3Egi_*fIX;@lj5|TR&pEcJ*Gi1ws%(2FDWf@F)hLF z#YpbZ2P~=kwIFcWNcpwq^M4ZghAiELINiK=t3upKVx+eFqm{+UYY)=d<1h;%yJK-y z(OUB1R^uxoJGdv?MD6vfHy%SeCnW_Vp10L!)$uLD(j4LNW(3+PqHQ-VA-x z-o*{Q^vJJyXL6?HmR`S45R4Ce75&CPBa)voupT#89J3=eA{cXh``Pz9bHpr}#ft?E z>2@liO1KppiVspnH|eFULEnOMz+i#i%WyzEil{Xqs!c#28g=W_T2>+!ou*6IufULf z+-uALYw+5?p0%vS(~tp6j%ckQn(l4Z0L3{_3Z3@obUW`khz;mByz&qm)m&=5!~Il@ zO~c7n;7~-G9@y0X0Eno^_Q(L5 z4Yt^gdA()dDP`xigp5`t_d`B2o@11|Tghj%ihrcXiGfq}a4!f7$NCnF%Af03t#$1_ zJ4!5Aj5oD-x#Qu9pa4(=id??NUfGow5VUMjU6p}W9EC?9ek;D6Wh62)~a&VbxCxAP}l)}tbJhUpHq>Brh#V1-9 zQ%%KnQ*^|%g-#q1atuMD)_hYtYn{W#b!tP-BUi{{lAPg{$>i{$_elfsEnchZuRSHu0_DRTQ#P$T5ycm``;2kXeN1g^ z8U`jf`O53tZ~7WA9mVt{Q}NJ6mzD{upa{Nq>k5aI`7HRXy`A6k%PW+;gX-YCxNFfl zNxpL+7YiAEzFr2O4H7y~Vn-B>`^IbzXh9 zR{lN#^Lc__C{p2a`RklpWv;%OD|mw=UfraU$s;fKQKaA(aq_6&NB$foPe|mr01&yp z<@rok5{ymS!)(7RMQd*p04Y=LN`)ump-ba*@-Han>3_O~qGGaE>y~MnUN=zS-KQv^ zpnl2?3nN-gNFi-_J1mWti90$&kGHv-w{aSS zB(puR3eZO(_jYY+Vl34!D3#9b?(-VF!Ud0(T$r9@QMk4MQlL{VW#oh8fk|92;sbE1 zii!{q`DvwWK#1bBESew}i8W6%KnV=3wE*d{({|>`_(&!Ds7uSi8{Jx$QMEk<4z=xF z0xnZgya07x{yUk)zAn*TX`GMRRpeh{K%l2e6Qb!^&BBSJU`@iAaaNg2J9M|c#UsZO z01eHdLIBtkG-4)hl=m^xx~rSQ74sQZGA@ew1YSd7;F&Cr2E`IwiZzSMoTrux2LxQ) zM;x4=a5!=VkyFQg2jX=8_59NGMy%WL+q0t*?ab0*R!bD;F)VgIE#i@7dj*o?Av`im zCBa}l@(|0~9cfpuO~*}o`N#oM%FqOw2Uldm;VyF5GiMt98SS>Z!`r-4)zk$L!*y0( zK9oCww_Oa}E#*#s5JlR(CxWqUOAJuhdVXx^ervrlF4&ssEfnA zl;W)tf;iXvG<`+0C}oLYXnHrdG=Os>n{LE&&9X!2ZqnB8n)63{#4j1Ud1%}U*W`p$ zE|<|-F#*GJ{-4RjpbcGkCNH0u7eeeAp?-HINpq{P*-YGR|qMW zD~ZNkT;nZoL6BP5!)_doM~tdV^{p5K^L%$2s5q!e_ueUtx5>1BP-C+($WkJ~=3^R{ zSwkn(lrb>w*bso3|86 z%p_dhg%w&_GdA>9&}Ba}1W3iA7#_X47QH}^HlRYF=Kq({HiF~t_-Zs`4m7;dN4s9*kf8a^#h*%{ysb9elAv}?pq#5 z-Hb^uUPbYKTpVs~wo87<_9cjKOA z4IEvsdrrzeZqOXUo~!`TuIn=}9eta1aYEGI%orxG8M=nz;U{}*x$kokvv}4RF)-QS zY=bJ^T$VpQ%-q|Z33jVijic)HW7`x4ap=Um*ZeHZ!LpejP<-NF4TA46Yb{7upfv@M zue?x=m{+Ab>k2b4rxeYbjFqlI<`jkx{mK(sbo~DSJu?LGk{s64I}s37U<)2citX_~ zXuP^F%c@IZKqlU-$Akv@+x;2mb_Z^f{xt8w>p1Ay{*ZRA^yQ!(WwmJf{wA9$95q)U}|w~{AH z2bD-!6Nms7^rL&X{Ip4j3qr(zpv0!!ZcaPIRasNA0ale)wCa;Mjko^iDkB5&8qd86 zN6a7e+0$Zf92ZZX8TQqsG0S$ZVT@b5h(W)Mte@f0mL?*DlNwYWCbR_U9Zs@FURnkf z=8?aw5Tt5T759k!zkeHt$3K^}mXV|=i~tOhhj(fD9fY09Jw2s;y)++w;Geh&%-e1C zNIk<|FKXf%ITuU>m+e$bzyHkt|ADM9Ip~(S>%Y+ z_V(nw)Nj2PeFTu~Pnh7Hj-o&Yz-`skro=N`+}vlt7K+?p5x^NB?eGJKxk)tQIS}1- zOOygQp_1<>OPNcla(P7-!Jl=8+A&g14-rBBvC-ic43=7!de%=G@ED?oP`6W+TZU;B zdyPuVPIaw9(w_}WRX~%Ko!G+3I?Hy-mhw27ODNnbi67q`V;vWRRD3#W;aIwE@_UaO z`axxOqTm!!3*xCAG4YFD#w1prRG_@BsBS{;dl2!EOYVXjIn(cgb?T zFNzC_xQ(t-I{yGLOJb#^_OJ;Xk;W*-{^9N_O(|U^rWZ&u-ce*st1iWA)5&oc@(gOo zZL&7yTHQcX8z_#UIQ*;vvDgvQM9({ZV^FPfBB9oKd5X=ZUgGlp#LwKB=9&br8I-Xy z_MK`E8v1*etu{1lOd5o|W63pmG;_n1$J^S!ayFH3F!Hh7#UplSiOBY=F3ReCMba+YN2;hUg$~ofx zGO%PVFC>uT&GS~%lQdG>%7&>T&V>vtqz3-2MZyRmhYOf8*km`@+?rxMlqJK%YYc-w zX7UK6R%1lHiO}{W;*I;O`$X|R+LNy_tN4h%Xko+a^z3)3Ldr;RiOJ&Dw-)aM+)Evu z;-Whz6=_lA93zHMUOrP(g0XHW#4$Tisi)9LOiPBth&4czi!xq(+_>+pzMjGfbD91p zA&hr;Vz9>9(mOnJ#R8;*n;>V1NR^5>#Dm_-bgo|l0x~?l`@tAf7Gac~)!Xs60HR+% zXF!u(#DKziz(d=R7vyl%c=z`+^PTHTO=m62jZ|q#qw&)DF~w9a3<0s`+<}c&FSv z8~Im{y2+8@*_P=MT1Fs$g?nyy6DZkakKOR*DXJ1e>mID9db#$`?ft#7{{Y1vK+@Yu z2XZ(gSs;{8314j2C{m$|eAFYIITa1L!PaU8?;!MaZ~G38hKplIM<|+YCa24CA}jff&Hbu}yQ8cRoM-g5r{lMagE+1Y|Dqn8wmHcmpbM*^54 zxK&wGk!o@37QGaoPvKoY$VNz)gFuq`HJdR7AtquD!m)~`{+{Y;!BsMS$?{dYzqiD5 z<8NpLlY+6%re;vU?gI~Q#)nW8L^4piw=+v@WxiK~wxMO>If*l@#2@lxit8_0*^Z7qjxqqb!&Ab2aWC7WJ~Vo-|VO1wDXV z4o87C`H9<5R|S8|Gt*=~-eEHFg_3C==No$~8kBV+P`||*qPpQlK|+Gs`1Q6s!tb)V z2;w)lim_QmF{2`vQ_dv@tsx)KznRoJy1nDmUg9t_JgShrv`=#&;!LQM4loD)>rTz> zuS6WW6{s};6BwLH+qn|j4R31i46k*{Nt_mu&$*e78)DfxkHeM2`#0NbS#u*4PLCHko`-j z$rHIO#+#ph+i?k>1%Dh$sm69S}4T6-`$|+#kv0gn^1VGMb^{e_qUK@t+CfPcNf=oN|48J+@+tj7Qz@2 z7#7>wicK}=C#*j6e%UT!srfE%%Dh=$Gvnp=06of+fHWu^UvjY?Q<7<(*ZFQv=ySV>$y<4)P!u$5-tg=PyOH-F ziK#2=zB)i>ja#>~ZYW0GD5sj6F*_5#O^%bZydi~VF?o4qagDUd%Z&Qa5?SJr;~Yl* z?j>pmS|9Auv~LT+{U(Ukrp~#*Wc*h1BW;JWzq-kse_#tTdxwa#kdC~a)*+{BAc^!JxdQysT=V@i%rvC&mQ zENQIEP?Vxh0C%0SZpUD0JA}}z@62&Gep!sUp7KSTD|E(Db51MIW#FUq#;T!EdJSo4 zb;L->iW02?#g-vH4I<$SO-rSb;kk@~v!ijS+|+(Py7a)faF{WoVZnISt&UD>iDXOI zZO>{TRDxtGIX4qfc-L+8wyNO+EO9E(j`Zi?9yxpe03O>xfV+y!kS_8urPtB0vImT- z#nM=&6{!lS#ZSO)6_&0-)Bfs#(l+|B!CL5qVo4QS7Iys&u(gTVECB4;W69+Pemu#ezxxKG4vGe&>o|_73ctYjr z895RhaE~be0E>yGI$Zgz*>Fgi{{Sh-W^Nj5hvzJavB@b_QdKrpP`wBB>rT~}z%+0{ zl*v@`*w?U;Vv$uGZS5twPzs;vIx6W!ksk@n*kUqsWG>gZA%XiaRD&d@oK!Fm$9?x& zYm^4wgI-<9b$KP+jm}x5X&s8H@@6$8f$i(AP@X(z5iT-3en#ZMWpwPa+nx+&AXIz9 zHy?WX0n@Jfq|4DUY7J6~TuE)7j^`733(PGgX(A28I>zFi$fT+Fk~c%`H0jeq4;rQ= z2+0G7Vt=cI!zg6)DO&E45+?=v)d3^)g?0MoT4h%|1sfd>;1g!x?0m=j6^<4nLZ=$89Zf z&G_&D?fN3a0-?B2v6_&rL%BbP@zDa?uiZ&Jrt@X z+hEs{UGN-DwU?AE*OEg!+XXfW8vRFdc^8~*9A}RrooGhKsM}h1YaUzDt(2!@Yj7o& z*V}P0N4U6(9n3MU3FOt?hUA6lHIJ#%2%PYvAW9EVs4K+rv~sAD-cV9NIx;Zg%Ub$_ zO;Ess;*uUJf`|uz*}fypFRkupmeUN@)5m+6w}-iOwqbk5J4Rx$$35c4ErTAN#vLj( zuW-iYuulD(YLP&08k?RH*WO-Yc}jP10VmT~ z7p<1c0}NZc=ucV(LNP=!R}jgI6``Kl*`%STwTWdQ)7NpOZMH@j{uN{nV7`31#%1qr zr@cfnEUwatc_=IiBrxP_uVC>MPMdO1ID31Gj~TI%Q@bpP#zjy`07=A2O}|Qt(^iuDxH?aW3YY+16=OZW3$-p#_? zbB*d5s0}N=#E*`tJHvX=v?CDZPjBE^X#Hsa?;rN_F`R&9vXitO)E%o}gufNo2IWp45l&ro#HtyGLo*+4ayD`IEgaoS z2`_9EhYC6sJBB}pT|g?rsQ&vf4o)P&tZ`CBpLHNB3i^ek-U7guVzaTPu@-(%M@|A&qg2 z*A}?mD;=3ayktU(MP-xzk%@Eh_+HaG9r%JVs;QL1Vf@bzCDnwHMV_-&?1J9+hZGKvhcC)p2<8JIp z-H$;E@VWtILTIkLMk|O+cR=tl5&N9Z)C<3_!>*4R#MByhEx258>qvqJHt4HHA|xpy z`q2Pk>UfdquN8J)bJBcQnz+Vitw3xdk_NYu2@DEDEt{67Vk6F2)0XrGj-s3HHK}J) zDZzxi@f164zZIim?56?;s4VBsJbD?t&hS{x5?RX}cXtz(CMaHLyPdkIVoQ}KH3Fuf ze08~@zD<~tD}!_v{ZL~PO1Y26;;mqcOm(DxPUR8uH_@!K+ub-4*_oqmP_4Y|v<{=8 zJdIa!6Eo^9$Y4iJ3;nsKA!rS|6W7}A!+AB-H{7GNyvN?Xg}Tvu4q0Qovyf1441?RY z>qb3kpk07&SZW#ehze1I<-^?(N4npeEIUHKHKKcnq29W^WxNfxD{p+9MbGo`M)vDLx#mdC7R+xG9t)AL`hU>Wgrl!2lnm0+GgFcY#?2@ z&b(>t6f~eTKc4&3M6lC$R}nD@KOLNk-L4g9Yl{?7FVsq$MC+?_J|^oCBjj0da3MA@)A* zAGS~BrDb8H;9z`l`X!mzrNM=`Ho^c)#)_&KQ+_H1e+_B>046T`(=xnBW&0r47<^Jn z)o-LH>7x(D2`6D76f|D6{aWZ{xg*aX!jM=xP_#-(7G6xE+uWIZm57scvV&G}P8@gK z5&oS$Bl}zIy4Vkx$-Gv9g!4-qyQnR%ZdGNuA!4|1VxK@H3$#V6wFez%YIO3-@!YmX zqSy##rZ$@@V*3q>;BI?Z?C`e&FaAf6GKVn^ETUe0%T-q5NB8 z+WB9%MfS5Q@#Rim0j0l} zWDqk7@FVVkBUF{-o)h;^I3SE*t{WW6=JMVdq2&`+iq|dfNJwvRQg;n+IR=l}rTA!7K z1XmAul4P$h-0Pe7ouKAt2*= zk$9W}p?l|^8INCPL1eq)t8pc?ZzD*x_b+ycwEqB9P#;?A!UV1|nM!$&x%kH>JY|D4 zWR$JJR2)4xtXmCSL3MYO4)f2hW-KDd+Q$o##T+!g+HM<>0QLB4L_*|S#wEmf{fGQp zpGB7bXx)5o4IdQ}4os~)>V--|4OMHqZ%&of*-*X#b>d!8k;-LfOVEeED@<8ef+3K9 zhN=e@UvITXrlb?wT5E;HDwdaXBy7$#52UClvR$u-eLIDUUyA9 zvUq}H1CKRW-JBys8T&{Vog{-BNGTJy)n^#LNkVhu^EkmZiu8<{yHqW3iQK zEF*x%mg^)l+Fh1cwuVE_=O1?>ikP4LYe}i|kM9%2m+y!S#Pl})U~%FQj#!G0uMx~| ziB4V@J)S$sEFw_SmoANZ^zX_0Fzf9}UAFzg7uDaLH!A zXNS#C&YbTj z_H!&r;tMrs7QWT^Z`WNZl3h^55y=$3y|%?-8vg(*c&Zo%dzWCbJB8dru6aJg^n+jO z)g>I>R;sK`Ru|?TM*dBft%3;Pw&rbQ;zW}&jzo`8c#5e104|%eXh1T(W>_oUIf%B0 zF>M9)%NQ@@y0N&rTCyJbSmT$A{+hbT7*LImrn+;*I~^eb&p*d%8-&bUWAccZM30Q} zEHg_nBY=&{JGov=c#_|l*G}GHM4TjGY8JDD&syd@c6)IYGu&Cqu|sfnG9y$mUB9?~ zbJt#XUn6QjOZRQsg&|i~Jb&$sSz8`3c?1^Ms^O9uV+J>^e{Q^kjke@^9R?pLXK;f7 z5ZlRf+}+4>CL@Yj^L)gGu^R)K-<&ovjtPK*S6|@5L;APPPosgk$qq`%mWi zC0u2!%PhESBqDo)YAY?#ZU__5A~8GeI_nQp{{Uo*N;b!vaj)snff1Em$78%l2;}(Q z3ev-hafa$hg!f3tc6GR)oT~ep6(WOSuRnX_H5WT+i60a~S8e2zv{MQNYd zI7BMmz&#Y5$6rkvEqs>~JjyRFt}MIKyuS2F4AMqqjv`7a zbd49MMFOz8Q%#3S7t~ntBy%|ku zt+@lZ{Zl^M;uJRi9d&-l_}hr2w{AvxZdhA=GN}N`a9sA)YJH_yxl`k|uNk>xM6}_R zJ6e6Z@mxKWH}{wAnw9uSj|5D%Q7HE_FnUWkH1_O+;tg~gy12yU6`th0t|k8fHSzI$ z^Z5;qa?>s@BvpG=Q*U(`VzI`e0yvPPiu+ol;jXu+B(&mUd%JMk6&CI}W@PJg;=l0m z!Fb>8FVdslXD*D25w0eSlKY#Fu~YcFxYwhfRsxlA(Q zygpoV(ZbEn#rcOwz^xQxJb^sfR%@nHmcTRDUFr03A8H@Z26YFBh_we;6&fN@8b?mwq^Df?G4fH2#;p5$*l zkm2LEj?|mXd!k2(b@vxQIV^7Pza-_iGwol?Ny5>&BIl>{@#ckk(Q(00@La6fFE7Lt zkR)w!B_$Lk_(a{sQBzI<)v48mbnLX^5vL_s#AVxV3ip(xlKD;ULJ5p4@hQ-`LdSjj#;U?XfFC=BC zR#!Xn2ch`>8uOZCBXkhrwdha4lP?sJ<(2|`YGuvDl3ZUoYvRrsTH-LPBeN1KRww0O zU2of+Su3c6f_Lvs9tq|CJ^YT(2S%{SCov;&EVoj~?0NSSaCq@rFs9odO<{bW$6cM% zba|q}oEw1e=_Me<;Fwc4f|~K{EG~t`>}c&Ei6magN^jg?l_i)DZGVQ5x$*ZQ4D!K4 zNE)c}$0wb%w!~V<@?#s-C!03* zcJREN#zgEu(McmQ`CVIjttrrJ(!exoR7|;|(tH=~MWv8}_b`cllsse>CZ-qx+;=JS z$@qM~+oZ2*Op8YZNWcn|-{wA1jPVR{d$)@7$t6zZmM|+9V_$5SDy4WtqtlQl)6|Z$ zWS)gdPOA{|Pb%_nD7BL7Es$x}37OK!Mk0v=kC`}tq>hw3f&6szVg?F~mMGNa>DIrF ztg61JW_e_3iq+iviKS1+roL}yOzpv5Hka!5%C#%#LYmipqgod1h~SuwwJ4MmUroTS z^dtPV(Le~96tJ|csuXf^b_1_aMFG?mQxz9^r0!h`_Q_~r*liM;JA8j~K~wkz(z=_X zG0Hcg5Efzg6B{Rx=b^T>wwmsH8)b~Gyl*W8jM4@62HXeOSJzvg4RBf0yvT@@jwB8V zh**YSF=bxg!)>nN{#bjMk1MxNZYumVBH;$=(f2@Vu>3Wr8}42tN*qUpJQa+<=;U9x zZsvgqFW|PivvVc2?ly68abnRQsi2`Qgw<$_yVO#LOwiR*Ky8ZBJXgNh$Dbfgt;DIy zD;JF1J>*iF%Igs=EjRX-<4;Xs>g<6$X-=+NhU|OYC8)MRWmn0(R@P;L@(9hUGWIRX zqO7oh{>ZLkT1Na`kM1V^g`1|UV_hq9F`Y&=-`B;41^SgO#xnAn9xJ%;Nn>o8za_{+ znaEr+MwoSo%83oQE)3n}2_rf51KI~u&<^&v-Dv6F97%9S?#{COlXfFH6Aj4h51#Tl zn&R?rp^Su%J2;{UUL;TuM;fXs#)zs14x3PF*7OmSvrOie*Z`Z2t9G|KGY^g8?O<6F zC6;CP87B?OWZBqHxYdym14wVan9D}NAF1U-AJ%UCu|>YCa(g1UcQvm zP`??@Blpf#=oQDuk62mfd+rL4gw&I{T=#^y{^ET8%Y) z7!fhow%d{H%v=TsZ_{cfkGHmIW9BxNj|5{Y3Qf)z3Q22tSR`xCgz@J@k*MWJQgj(y zl!znJ{{Vls99K&g=-a6(eaf2VPokF}EU#%SNL`QstjY@15NqgvXaaS(oEgi+O_Rx~fpY7jl7f@(i4c4B16mgg9Xjk%(kOp%T&Onto` zTbR<|_djhODJqRw0i=8xOL8YbwPbzu638pa zIuNKp8+T9!4N4kTnji8b3ymruUW-tqt9)!$khR7_(n$LhX|1PY6G(<+QX&S9th?{H z_|vAH%=jgJri+l6yiP)`d6Ee#SajQrprx?Xri|%dr*mc)fx0DiaLcI*q34_HvLdP3;`HSK% zGuKRBdzjUDLehJr;67EYcYn^EX`$S^E0h7FwmW^%01@d^X1s$ndo)(Q8*OtMf>P(n z8WvatP6&`%#>%Er2&jFiN8`&zwO|UAIZ4)kBzGU9whnTN!+mKAMg zxfhpm_bz5g(6Cq#2+?`d+U*$w<^+*LQy?h0!r9VQ3MfMc8+rvEGLX^hkSxJI7J{_!VCAz(k+g{3|8!JVlOw&qx zal4L@s`BT*x`Sb+E$QS-%A7XblQ(5D(Ot~8(nglnHnG{*z!o^;02w=KyjPs9?maj3 z(I;-$b09Y6iyI;pl}e|c&0xGw1rB#EFumyAY5I^8U4kIq;XYhcO>XKZb%wN z7Ov{<2*y9z;_UuBg$DkX4e1%tWd3jGzDeg7$pD5pG3z2eGZADGMT{kTY%W0V%D}Zt za#gAM2E8SX9gRE6AV+LAf1=XT+k_%(j@a$cticD8No0dR1WzrbY}Ppkol_$aM(y^` z8kqroxHjihmbTcJkoQpvc}*kWgWOtVe0RxB?VX+1dU(OOSd;6T-?#yD8?o(&>cM$2 z4f$z|@Vy3b&&9txaa}_l>Dw85k+89c$nPvxH^25Rjms^}z37Dyy?xG}?n9cqJ!stN%fAG_v@RT^F$%6X6?1iV_jkZaD4|qW3=p4CeL&^v2KsW$V;Ffw zJXV+@5n+OIwtIVMl4B(&PzP{Rm1tB{4xhk&8oZ`TT)@b-g!F&9<=FALuM?AZqQs<#T~_?-QCR4T0*sJga$xm;>{FjI&+hv@*o}RXf!xOG32dq zkuez5q)$7$x`)LrJaZUrjn|b-)8tUqrMI!i%39T4L((>ySzFZmC_Wl<85qatk=OQLnm;7t)py>yq@ZF9LGt20yK-B$gl7l9@7u$r zIa__W$Uv!Un|Co^p_8+26=aAg!5u>6e?X|OlBHOghK zt;RA3B`g|qH+{^H!I`69kVnVbK4$n0wBPa!qfAm4t%w>YKfAs;KbKnA#e%wmD+_Zh zc^iwV0#MZ&0;CUrG6|=pHER)K-8(S0Uw=%{DbAoTaofOw6r7LXuGX zN`bik%^BFya3qkr#@qOwS{!J*%u6;wV4$`i#Qu1G+qWUVR}paPl%^w7HbgM{3*B0veRGM+*9 z($@6Jo3Y5>WDGrvh~r@i3Z$V%+%Ci&#`N{m7Oe;djtNWiAkhGe%6{0`-kX~Y9q3L* zkV!G)z>s*FyqY0{;+M{MQ9I=P!yS&jxn=SEWu4-ra<$9ynn#V)cEM!8vhxrd5q=8qAMVhZ!Oh)g~tM&oMMi(Lv=;TmJmjx^C2p6dOQXPMpk zU8URq05r~B+{aE9$;wEB1715I5dpU>@0#*ldt6^mc;c)sly(vjH@TKG?va_jk)sMytU;=fIZOpf6M#lDkKs(bm-HY1!h7DvI)Q!3+(vh9q#bX(WZ#;)2-cjar(Jx0VekK)Yj~&`5<3{&I zZSMAvc|XigBVBqcd2Gko)5V+AcLH%d<;!&i0AXu($x+^Ca&pG@*vO*BV^q10+SNc* z1dd8r)z0f(&aWLMx6MC1_@Aa$W;%5;?;i@?+%;*Z&)K^A2 zh(xyC$imccbbrSh;?88oU*1D_mnh*V9?r$hh|{#iTKR zC?m(S?18AXKqc9>-kNeE+TSLS<1E`7Z($NZkVw)@!cHFMb0MgAA2;J#YbGsllOa-T zx9A528fZLx#niS}0tr~oQ#>#T9$&w^>Z^+(&QR`TL-R zW~ilE75It{y); z03BZ7h=G{h-j8G^7uh>JEK?y+Vq!?xs2i^J98E&^<(Apw z`Z?R`laKbTO5yb%3_?PT0$|n`@6^mm6@`FN9-!i@&nuA%qrgQ zwd<{$I#|NiLTkULsmI?OYO+J4xBgq=xLY+$mS)o8?z|e?9IbNb0{o@dj9YXB9rZuP ziJ-w#+aUz;{Ev_3vl3--__?A>ZVoaR5{Q~fBP+pVi5a;kUByV-b6RM6!R^{DxoB9q zArraikL0|sH7ea%*j+J@sG4rnT%1JA1kl^Lr5oDb-j%2nCrDYDAQ|9J-ATI|Yjh+b z7Cui6i$`;BJ~B0tPDGD1G0vkb0Y_sB9LNdwJ$Jc_YG zpuZ~nRU-r32_OKYWB7W%7>I<8+oo%5`)&62(+gz;*Om}mc?Tga&D_+PZACdGaEkWT z*JAHNLv%Z6Q@Oz}AenQSWVMP&VRaLb%{9X@pyCTOl06T#M&z9Y10`sH7HMss$axk@ z;^x9-gT}DO>hI=|4&==T?(+!0xxq?uRj=p1z{Cg!-cbZzr8Ns_VKKuxg}I%Ru>mTr zMimVsF$*1kNGI_$_3D4&bLYT6Ajs!~wCzA z&4-&9CE@=2##?Kf;3)3#ps0u|aSDsYM&6qAQ@0p3n#)GD6P6fp`7Hc`{5^wptlf^s(EcaNuUhZSlYY&E;Bj!J8heB@8rj?b|o0FSYf z?1mtUay`By=C0ZVu1Ji~%Gi3J{lBUJ4q3zW5PQ>)+xEDN$on|UIDBbrW0qW|b0{9_ z_B8F2>}Tx6jW0!5Biw$XI;*I;6BjoeoEe+yPy4rVS=zYySeGQ4ZTSm`vP$yJE14DV z7_@!OnT)N^iRerE@A(b2pY5J5*ro&k00yG(`Go5MmI}!PCyL7;5*Zk7#x*>LZo5?c z-h!Lx@V8o;?Y6}jL;A5%-p`A@WfMDL?+9l%VH#^fc#_R5Ox?&y^k~e3{XwQ}hDNuV z1;>~vu#b0x#N;xKbsgHqo!c>OH#iNgba~bJB`XXE^y|-xzj`B&J%J;dnffRrN-;ngxEZH~jxeP70SYkX! zk0qb-SIp)h!J?MDv&l30-x-ZEnHlf0L%lyf^LA3*Q`}kvq!HGk5miRFArR?F!G#uG z?FZsI>~vHWs{OdUwwA`_A+gY_G!JLojd~I7Tn2=y8QUv}>~50Z z5e(}DoNr+Yjc}nyaYSm2ua&tQ$?r(IXo1+reQ>##jbVpKnvcW5Q)%yOHIyonCxuylW*TWHGdI zS87lV_OANO*2ZQ)xr~SOsrJbLggeaf)_E(KV*Yb)WrMYjIAD>{knlttQ6dL^EmC*U zbh9x9ft1eOO2!NjJf3&LV3nq|vV7(8M;fi&;}~HABoQburw-wwjgR>>%prDOqnDz+ z2mYSB0%x1wurHXoqei+{GbYZ znYxN<(;#A^*fMaAMJJG2#WjmOFD>Lo7RAGA(loq{Xn<0+=~e0Q(A*N}pb#p{O#5Z_ z+x{7f8|#kQ&dnP=#nIf^g0wJ3eZ!pz4(s^?P0emxbep<4eU`U^BW(k~VXTte+!NYf z2z}1)w*?-g*YMEe7hGtu&nog9kC55P{JuFYuq!+LP4v#o1;-i`4H}MIVCP9fCaSOEhr7ncufyQJ*+t^wTJzYc)U(?&ckV?iszxNcc*n8O?%O_jOENXuoBneOdrRV=nkpsopSRItUIXK{l4c@MiIt8L zty3CDh8LC}Tm%iPQ)+i_*phuyrTpO4&NB7(T)K@Gn$ zts=y=9kplV$fa0@0PoYGI_dmbk$l*fG#$sKSm|RcncUNms;@uYY}~#yFeV@@fMr#v zAS169j8%E?DN54kD*&4!Re)2<9XcBezPozYMaLSCPR|zr4WSX0n+{ zCVQJJDEQ+{ARy`arOUF(i#%8^%GV)B$ zR!OcBHhA%OGCyfr0S7hYAEzmgqSW^r@jL5UA%a5mi?-ytitND@ZcPW~dTPikX7J2p zHoiHZo+yEe2tSvoAQvWBnpx!Ly-0G3qgmJF=WVxlrvYY<1h4lmD ztL^(uU&E~`4MmnYho^tv?w!$UT!>2@$8Em0uCng8BI6r(b7wSUt?neu@!QMFrHVK_ zR#9GF;ZI+{+BU;9fIQVTc1B~wVm~Nd#q`$D+X&fSY>SC*@0p86ph?&>N%F52ky@2B z+e8p@=K+FNGaxdPBWm#Z1-2{5EaINdW{qOVL>wMB3VSS)2T)X2v_B0FGI$w4*M~x+ zj$>60YsIZ`)=ex<>x;T{h~J_tu?dAw)5?+rp4L=lV9H6a<)YiVWxBjSJJe-~P4f7D z3Mkt51!Z*w^r=U&$dptprAd2vm3W>?eRlk`zw!wUF68CASxRH^oOCv}7b^DPtIQ*a zink)gLjmm^Xboz1JqG$&^ObwTv{|-LK1c3s(0Hw+mhy>O8HB*6IU*!YEYXkf)Rn0p z$L7|M4G%Iz5+t^N7scXmY8mA-WE_dXb+<&IZ+ucqzod}kSMrzs{* zVE|Dl^NFnB;-LK2s}jvDhkcPI>8~{@T7@GLW!X+x_Y|19AShd{D0zR~ENphOT4E!| zVsY`iwVanQ8;qG#R5OQ`Rz!YEXbLdtUG=G<(Au0c7>s_~-){A2TXOPPd_GSIf;(v> znWKpU0Wyh_y!T+NYM#yNyVqLY+S;@7MlAcd*X(=K{{V+s$K?2EABtt{@n^L)gE5Nk z+D2w^#F0rY=L%`PQHK&J6^gg-3qa<6rCXZFn#3_8yH!>4KPa+;BKICXZtU-7+W!E) zR1Jp_8!C=05G@B^jdUv-a?EQD-ak}GM1a%t9(!%#v2$~Ac`tVD+G#3%$NIfGX}Cf$ z4G_UK04bO_9b0S^XW`RUOvG|uxBi_(4kF$|{W=FPc4ld)xA_IYxqm${~lgAXr2K)+;4Bub%a z)_z4doZ9wrS1m7{-`l$6a(B!U(!$wKBL$F=O2pDAP|UvO+_O_{Cvw>Y35O5MVY|b5 zS%yB$oSz`Ut6phaIpWc#IvWW5gApE5CNYwijPn&@BM6^M49z3E0)3m7THTNrsHiDem*DB}=B3*M}8yM^L8aYh?_!}#kjDXAEJS8AdoaI8n}5oh!7 zB&%|!Qt^4zotAe1)c#u6homHCT&S@)kE)J2En#^jWO&wBB_ms*?nSDQ!0;coPt4ww z2U95k9HQE^Wl^!)y*PPB8tUE3qkTQbW#anT-Twe#TH&bB#>^B^c(XC6G}~%vYZ4Q$ z?HDHYQgBGbonXrq#Xi##liU!Oz2dnkNH z+hUWI;Sl%~cK60{w^(Sf`5TLO5QjxE#Ogs>H*64ONQwEPc*{rB72rtL8TlNuGltzf ze0hUVx4(-FR4d~cwrhns6F2h?mg?G2IkbQQD#sWkFg}H92{h}X#6~zOP9(@O zPVrk?JZ;WKY*m<@q;j+5n1zns6e3P9&xit)UKbi}R_6zU@76P|uCz0sW#-yg9kd~>v38``+D?U9;$bRxWs{=-i^+l? z&<{hc3wFdp2`-0bV3Wx#ZM>E#q_{9!_V2BQ6x&=OP&lIh0Px$FC8te;Xae|*{kc$_ zIsQ>&5hWfk$E|MSWR_Bdg8bRa@rD{k&TF~nEkFbKYG-te6H(IwHro_R2rpnsVz;?= zw~!d8Y92x-*wuc2m-_U)#AHE`sHo{xmXs}%JD1JdWv;Ew!zHby#IRW@w}?WD8id2% zjs2vr&Fj}*QuW!1F=ERk3M4Nn$=ck(Extg-J;ZULidC|;EgVuxc(-ymmBmV*l>U13 zp9<#LIBY)Yh(NMS$zw6OJT1l5tV#7wT*5*WkcbZBfcbd}?eW&ixu{Tmv&uFy=JG<) zn_H+Qj!w!mcBX|y(8&CK2oAr~q_x^_b_0kzZOLCx5h;LhRFYXFk)(avL(Gst-M!TZ z;l7T*Ef~m|bgK)~@$?$1ZY6v0{@+bXU=Y6mE7yIsF0Gs|IPX)}OMs>W7IN5w@#12?i-+B5_(*l=L8O?3m~ZQkZF z)*EORR9-xUVw|6TJg7Z&Xa|K=WbW%O^DhyLAC$bi$bC?f@@9C}7}7`#lCUMk$&=j? z=j}XeUu$oeKa9(4w zH#4k~7cSHR1!z=*@YOGA;T8-Qgfx(3RJFng*bng=ij!I$tGUuX+zXBhr%eUuySRd0 z9EfQ4Ve9VSai}_INMVW*(eDV8Us~Nm3=MEnTX=zjW>!~?pV~smPfC8DO;*+0wuhQ8 z7vi8^Ht8ip$@8~ZSZ(lM$!_C@;0d9H6OFyWaZug=0DpA?j$2pPrnNMpH^yNvxakVM z@WfRm`F-z|Wvn5(y0`}vt--DB`F3L=j|P>$P}l&?@|~zXbfIiUfd*AUaM;{|x?AfU zrL-53I}_iRgq^{-6mUaxV?oqcu8N>V9d_pM<-!gs+Ojb z{{YR*{>bI&D02A{>qDCJA#Y|L%f&Le6CojD#mRiUNgm-hZd<@OwQ1Z>aMWmRo6izJiWm#g6x;gbCpmH9U zOK4k;Sm2wscREeR`32{VU*xSOvkLPn+up|@RdkXNeWBx`kl(2OuDWD}&dMxQ`HX%| zn$qR$o>cB$qPl|N6v)hC2igEWzr#}~gF>bfF)kP7X{3!Wdm<<-9x{4RV56c-=p*P?ws4r1yY;ySB=JZcktI>cAzXZ~~t1 zd?(A%EG})VqsrJrWgJrD43YN$n3)}s7y(%WDIhUEhtpVAzGF|GQJKjnp<>5{Yu>?U z-PDQ8xhLEBq_(r%8&q_j(8ki6xY{|@rHryfus;@7NmI2W?@EVVj<$v9&MxCA;6Vqk zdYe}BA1Wi2$L1u$ThEeXWh@r5HM~S5f4F649hI#Z2#XIwy=$sK#miT3x<9bOxb5^> zM6p|3WW3)i8E)iF1lH;~Eqi#-(r^cEL`YkIT6}Z~)(kj(Rbaq};*%Q386~ad?Y*V7 z#k@r$F!!Wen`zxijnQLs&V-IzQ2t#hYEy{*Ry<{LR|<6{2+UEC7yjX`;Bb9o$-ELRfCEN8aL zOa>ARvdphVjuxl|oO`HLdeNJe0hUdZAt^bo&QUDBN+iJC&yH(LM!$kLmfN)ptc%aJ zBEc&!f4dWn<0OE-;Z3wSMCPvLdy;6lIPKi4V={6;sCT6RVe7EfF4+=VT5u&03OJeg zL|_BRgX^S@jJmh+L#dv4E;yLjtwm1Y`gQo~g4vELrrC`Zh?RKpVr%Hj)}4A&L6|8! zwnUZNOqv919E3kt1fVQvS(GcGta2ezr6fbTu>Q>{J2JL?%SS02b}Y-+W|{6yO2lo@)TL}6+dN!P zD89?XD7l2B3V^F~sAAM+AKjqVd|rc@Kd>j*<*68eD>0 zRUPsZT(!Ac^5(#pq+`o)tH<5FMygZVO+DL{{kvk}4e`950>D!xhK~M+d0JTkV8&Sa~PfDQ(eZ#LI39{@_LdSki;l7y@_FX2pEK zziLK$J!{fL^{YL?Rcj#ur6g3PkdZJ4)555ypJprGmPApSi+ z(Rj*WQg70&Z{)QAw4(jLWTTY(YYnC|d}nIKqzdJ{ug zn;4PWm74{Ue2UmxBy-MGxp68iNQ+KR?^8eq=hmK@auduQb;H1I&tjZBTfuB?=Z7Ja zpX#kmBxrjt9MY(vSa>o0xJmanyPK}t1FQ{i%nvaHJ^aYM5*0l_Q8aaA8}$SDYg<9{2GpM5G913eH*Z!(C<{Z7 z!1&LS9Mz4?k9m!iT6iUm;1e<>yid%PECNxOQ>W#xNu}4=y&xef@H9M8Wic@5B>Zu= z(R~sKZiGc`@1X%t1{5k70!on8-|^O@pe8F-5Rr*+yP%2@W}kg6j1EFvOC3 zBX(2Hs*Usi0ICSLL;6FY5!>v8vR$H#7IPs%a5d;9CFlTMF`!RV2+JwQp*Lpeg9%Xe zs#3!=FTzA*Z%{=)w?>SCs9K_6)G4hl+6j3NbwCt94OZkc1!+exWWi~Cvc>^z=|fY$ z@&1ix+_c3hJ47oEqBiEORRsJ9`~^;gMqtG&av6nD+)dGv6Kx}^+RVX>g?SyS15i-Z zRQiwW);6Z!w=pQVA!1*&ZA&m&cc1ufL&vkS%LGDPUBsX6ceb@_c6kRg9Bcxz^)yFN zz<2*mLbK;YEExZqJa*^EGsaPSERaL zit;M)y5_4no-D2=Ik4}H7Ba8~>8=kaC~CdVUfs?~MtEnbD#2|$Arzi$Lksbj5S zzsv}lV?CS)XP4L+0SYLpYB_u>)7Muj(GFAHhk;@y#^m#H194%Dx%yD z!13gx;4Aoz0_ET&BAn6LjIIGHprY1koc@56s?+68gZOIn3)cunA&ml>413f(fTFJM zO*fzf0sM7iJ_^P|aPWx+|6=Nsf zyWugRQO-&ZH8kb16&*J!YIR(pONG=8d=#OOkN~2Zl1ETYDX2E#!9J|mFRsxKV5mhabq!2J-Y@R;%X1*_zsllX{(9zQI&Fm zloGF1VOClVy)`9pQ?1R+btl}dQ`dfjYJZm8k@czHM*m zzw9>UOQYL7MMvMc8r{%MP+S+8TU$&2019~{O0im)ZSc7pkkN}+S(~|Ubdo4`xBb@Q z$8_nspKChZCV2bSs(Bh3;u-7Fk4wChl205FoQ@uASnn~{pel(Jq>4i$suxgE)UaR= zs5(y0tQi75TgNrGrq&5aNE(DD?&B+l%G=M2mPl64-UvdiNO2nSH60t9voYJL)}4b3 zk@I3nPg}8W^gQ9oDXB9aHRLvyvH4BBSj+pg?!kWmtxz5bB+-BG=K!NNQpTZRm@%%!zvld&jSt{|ma-b;B(!*Gf~kp|AJDvS?Q zw0Gwj7!CXDPKG`aFZ+Srg83xH1%gD5M)v`|3`8_?CgWy~PkPg)t9~T?=tpR$f*hcY z*@HL$P}G_ai1ntkZh2G*HVCRkAdJx*u?N@i_4LxlLDYxEQ@X-tY#|qSHsk5473YR~ zdC@914q%c_HK(q$XJv*U^cV0{bPq3SkIO;ynJ5jf>*rD#RDyqTumWo5xa#g?rti7Qmu7cu#mf*laY+A z$V+fYx4u6%7X9(L0~}IGFD}csyt0knMkDa)U-Y*bI`nY6o-Y;H#zyN<57QCJ8HW3O z(l^4pQ*9BK3#2Oxf-=O;s!?S2#H@Y61%1w|(!Z9Z1=7E{etbAQVoDy0lGETtclUmM zb!Jf;tMS6dphlewaiu-V8-2F?^$f4?DzAt!qROfog^TDQl4GQTMv#ym5M50{=D((!k_ z3Za?8;&Tx!IcpWj#)-x$Dpuk;9+A2b^xLN6@Y7mdUE2li%O!CAr>pBj%~~@fng?r- zyYZ__dq}3AJ>hY@vfN=<#+UZ}(4t4Qn6DQ#PF=D9K7y^wTJhCe)l1GjyZfX)Cy~Xd z!+sdkDI{)H<4G={wTCH>k1=S%>lHH;yN$NEf>ayFaScl$D^4xAK8IG7+3C->a+BP5 z9$@X-2pZabaS_UKRBkagnLFRBk=bB0YrY_D5()^=dR0JG+ws%z)f;ik#cM-UVGN@Z ztYAFT$nlvOewd-Nl}p`P$|+?O2so-&eU*5q_?@>WO=O6RgI*j}bsryQf(WhtGC^Z-Kr!CJkds3QMNsX7aa1U}P zqMA~iO?LcisFmFH3rpUO!0|;PkXM@$c^${0(pLkdFGbTHIye>umho8IuFfNn#>5YU zj)zz`Po0L|D+5wI%dECa$%Cpi*LH{xYx#mkW?iZjvJxBf1b$jPqVi}GfG0|%9PgX? zE;e3vX)U#dX!Al7nwoW9YUY$8g|<51)BHxBQS*%Q=|4iR7&;XX+zia~NOC#3*6tu~ zEbo<%2W9ssDAZGs_z_P|y<9&VW0imgKW(-{riiwAPvNM@GCXe6Ya zsbT|=itSYr>Idb@H{!2NoCCS@TFY4rMx!0J=%W&`w5VL6RoL(S;nPdNsxldWBZ832 z8#;sp0E+4rk0DdIuc_s}w6xF$pn=z2x+t8r3AH5MVL=Ve+RC$9$2GL7rDD2*>Ptxy zwA=mNi6GOXZKj8l_w_UPmhMc)E*B>$M}q_4w2AVcZ1Pxy{%F@S=1f3~tC)C?s0bE{ z$8T}z*1bBNTHdG%2X@;6Q8fCSlAc>`BiMjk_(z#w@$=V=;naH6$$xa~kAJO<}xZa7ubhOg_ zq#m?RE1Vs|v&VmKz%UWCjY1fYRem%z*bQGWLNK`<%ItWKlRMr5k?Se)KhD{p6rwRu^Uq_Lh_!X@LiBX<<;(zWy;XeQ`Hl&!)f z%=T4jUN?rs_@#~3R!^&W5x|;j3uAF{kC0Ze-q{a%h#mF^uH1dCq_qb)VTXrH(O~QK zQ@`ciwhKG^!C@!d8!TRD#@fRnk+v;qn~Ksy2Pb0BWYI%=*_V{5-Co!X!;LDyS4Ggo zTQcB$e!II8FtB%hmOFMlp9_5^Heq{-ySL!7**TuxRA*4itsC)WBpzKlbk>aGC+ZK= zR5BAUh3EXO^HxcHc{SEIl#*RTB!ir>!5c{H+;4pk9w74kwV$cb*fBmxj)2|@(6%KY z6D`hnFy2pZfX3X8W;kNIxVc)yCJ>pfX+VVW9+cauVWpw*HVj;adzN7A6|9$8EL~hme1~X26>X+;bgLsK-^60#4uJW z)IQ3UWj;+Bokz&t1N|u#6oLJgm|131siXM>#4IgDsf18EPU3t>yogUta4D0(A>g!ur;k3zSmlhm4y#Y zdc8IAcHg%#ng5e{!+lt=xC;;lb>zgk+-i(36nge$npL;8{fs_8{m#PMg2nBL zjbvb|zWE=Mvvnszw-)mn&Q&Loz;y+^r?Mj#BBf7fJk!p$(E~;_B>an0N|R4*JxMza zEq6r|QHrJg6dN`Q{CGU2%+p(0z%J*7ij}o>W^b4*iWs3N#RyiV81&Mj3~~DSKHV!W z<%Y#k>_;p?inxt;Y7(TAzfeIUx~ab?nm3P%tYs)*6zhkzx0xO*Br~B5B&so8tF*E- zgmvDZ)uBsQa$%)9ZMZUGH*Pg#Vu@O2e45&L!JS2qab9a_8SYD%!B9CkMMdA;#8tMb z)Qi@{X!4gZ0PJ#4Xj5wan?SS5XOc6M^9vljQDd@Lh>f|FHN@8J@;HSQo>F%S_XeOq ztSi2c{J9vpqjf(n&GZP`Tk?!d-Kj+mV#n=u<=#E4?ON3&ki_xMrAY0mF7r^j@jXUhSz==9}a%O5CJnhuwb5c$eENlWTE}$?#dESeiK5)+Cvf?7*+Lj^$)K zdUV@Imb8yaYHwH5e5KifNOtYTb#sXOSeIDK%PD5dSX{7E05V9GjyGvaB!DR-CnaFO z8fdfCHZM#=9k;HB$=;p05kfn0L?X!jxAE-F)xDl2vUt1LIW!VRt0GW<{1#w6$T<5y zjdsw#mAqCv`6YE4yVJBMn9!a45NW>W-@SZt-rfi>9L&}^uJgf=vEtPX#d(Hh=AlCR zei}HAXjGhVZ>T$9tqU25xIED~j~>*ikj~4H%G+cPN9wXMz>q#qxgfcAinM7a*}0Vh zp`CJ0QBe)CPJ$Aq{Y|18GxE>b>?Nr2O?V5 z-KtczvEE(SdwbIS&G1v{res>26@^OAytB)rzRO?zDh9UU9i^o8BrJB)2UkExM{1fM zj*Sa!0vx1+T1AtR{?Hv3z3|p2P%@rh zV^0M`Xe01>_l@LGM|32xlz=~RIi-F9*1LXcG>`r&^`h`1UEhxNQ4<^xZzHiu<9Y05 z7Z5VCg9`^z0PEJD*R5?d%QS-&a9ndtzi)hA*5Ae~v#mVEZ?Enmzn&YD40aLNqQ5C4 z_au@^Tv22MFrtCIbe_Ihj#CiLygR>#NH0z)t5zW(=M>9(kjLDl*Aqn)(@0gLmmU(` zR9E*a1q!kEY!!gkQPSLrc$|3CzqI0=x);~QQdX>hty+Wz$0eg11*ztE{8=Ej;gWDp=@Tu8ks*ikMEl*KT zU03-Th7}7FQxTgqa8un~6h-#{pw(3MUHVsjQdb-Vx(}A^ylpdx<3-|@CNf{KdB&wD7RQiF}LeoX&B2nQNEQ92+cQ$6qIc@}Z7f)1*;6}XE zka@!|HjR)DBy>BUf!C`3JVbEZw&7~ni3Dy!F_N%nwP{irMCJ!BYr)K%Dp!7tbxVQR z?q^z=hERAX%yK3x4>Z?U<%L4c20|8rF7Dmop?G3}SQ$_^zG)mU5$!)6DJ#I7u_H6J zXx;l@D$kRsxhYD8)mie^b7HgkTvDSPb-p_+mi?t!B{3?kTU-nHEvJsx#a0$sJM<)M0CbZeQ=T!vbqcq5LH^vx3>7wSAhAXl*5+%K08Wsr4#bTh zjbP_q6Hc||Hy>m}+E~d|T3yp=$r)vr98Uo6#v_3BNRfb1D^}WpLqC&RTjcI>439jP zsMAk#1ZAKKpfkCD?yYEAlqdLBk@%_30$}5~;+K`9E$Y?1{f*-vrgWH8hbmRLpHM(G z8dmO_<+0`rs^&4uyPC=iui9k=rS^`S*W+D9twgPt2L*jC^9ka+@%y1=75+BjM~>UJ z_c)m%RV@wlY^;P6x&!WEL$lXn9o4jM>I9%BG2is($@&!g%_kjv)RT8FB8g`qWaRS0 zBGFNq39kk~;xc+KN_6>joF|e_{!@<-{I~dYCT(Sm!TqNcCn@E)i&(Mv_OTfjx_09L zg+jEgSoSOev-0Z8uqSP7+OSA)a<<+JQ#5R|Q#S=mGhvmvy86!Sb+HBnu~?cYDbKDD8trpgxqXH5z-+9#+SGJ)>}{Q(g>%y#iXv=TBl5xaT#!xCv_$H!jyFX$mJT z&{f%uHm~Qc2wQHInNy0p;@93mn7QrRw0PWd{{V}4P)xx5BUe0Gi5`P*>eBk3YS?)P zB}&sWSbIru7@TrBxb8bT+)j3os})(;P*u4|z*K&nw$Luf$0!(|s;$WvV5)i6YSR(m zcNb7Z*3sUgE(adV%n+q13vmX7eS&G%L<-LxgnaR<7RK z8jyV{u3QaPgX8}IcKoLgo4Yyg^srshJIg-Yaq!>P+0a2Cq1_#K^kwU)5dn3{8DfWJ zaQ-*sQb8|?w2|d59HZc+1PYq5YhpPCUai2fru06Vl>sQ1y0E#H809G>Y|+SLYJyad zMMlgu#Bp4rOPht4xg3nMF{yPV8rHo=xl5IH4CY)i0dnMyoQ-QiO0hrNT~xquRu?2U ztG51Kc#I^K14z51$?bJJP>OW^p1Ps25*u=paq$kmiTg)$oXB9x=I(AT@(i)wCG68k zZVWSWPAu$s9wh*7RrJ;lpg`Q7QONX+dX{#oj6!L@w~=CIU=HS>3jTV+y%GUrxFKX7 zaHk`D(MY9j<56zXFBNAfLx3cuOD8UC@YkvMXb)xg)j4DU6)U_Sl1Ym&O?&kAGS0i=i{5L_kcah^piU$Hrg5LC|2rDtVW!iEF_j2nri zJ>MPbHF;iyBqDJr$5A0f>x{!&USalB;{o`#RwkA3n@(5RvJ8~5j*PFSo_TiIo zJf+$6SGTR6T&UJ+EOpiLUtCXjX@3&NmiHF@xSltShwem$iK$f^2Cq<9jR#MxsbKH5 zaOuYy;-b`u-0F;3wzQgApn?lI?qf0B+`x+*moXjLXI1^0G5OIDDfQ*4o_V%XX}Yb{ z9}Ssagn3YGVhpQjITa$Y!F_MMmr(RlGOgR=2Zpd$W}u=r}x&|I9VE5DB=Phyop zpUYDEJIO8O5-qeQd&z;K#Svhfi<(sObpS0`o`CB@*TiLKRuF;-CzToOc<;%1hniU{Dlu?vhod`ffVjA79vGd7gbf5>7S(Aw;rBssLJq2}Q95F-1 z9>MuPlO?*f<~m#ZHzt=+EheBQrH4k?`hb5OWa@r8%#8?yySotOY$pp#*k)MgqX7Q^ z;rADdb)`7^F!dV3y{42295^9>#Z|PaS9Nt)N25179z>cCj-9^2gE(#rPVJf@o@s4o zZby}@%K15HT@`)M-YW!I6zr|cQc+LUTKr3Y9eB)pCZIk$ScrtTadQ#X<9Qd63*pQZKnzH6^F-ksZbuMGd@pchf8?PSl#MOr)h>xp>=m&Bt|!wdH7SBR4k?LL-UhPDvz% zA_6Ge+6x7z&2JQvU#q**(r?)pmQ}k)cw_({XBfd|tq2sS<}~0^ zF;8ja7&|F#vEC$>;`zW=xRnt{a-3Ne{k_j`%kK9v+u^9nH>nah1y26}Ar0g**k!IQ z3Z7EP43`m09M44~h3dSB;exU4uv!kCbvbw|32_N?#jY+f&vlTowwCK96}yX9i36+* z#3_`D6YWN0u%}PPoZu*o44#gP_}73X?m03!31scctt2o&M?MI|7G@!bRX)+bsE$x1}A)YLDLPF@0$kyk#YjUfxS>%lr zGSZF2{B_g#__;Bo?YD{?>}E~)55Ab|_lnobEPs?4)mk|ea)`&rk&qHguw>i-KLANO zR{sFTNP27Bg*_n{CI0}pSAH>XZT!~HGh=fV+N|RrQ68&BVLd&z&r zXwS7&@5Fp}8=ZXTReW5Zlr%Rw=!OfaG0@(yhDgJ>ei1z=!I=6s+N^IFR29*Yjteo* zWtoz8!`e4txpuEFM|A>@k}YVetfP|h2W@+eE{;)%_Ya$Zr*7S=Nv;^sBs_`D{_ zb=};o);7<(n`u%{7cy3b9_nD*GgYWd>CpnWGM= zC|F$*ENLLB?0K&;{{U^gM=6cQP7QOHHbv(+7C zP^>|JS?rpfw(e2xfNHD7X<=Z@hV0J^A8f9I7yK%PpMQ-Q{u;-Ypx%`tTeTMD=-j|p ztwAtFMw-pym=nrKOR23l>DQGyYCt6An~nvxqF&@A1_({1+)!k0(q!Oz zpp(B!e`eZ#?V~GkY+D|RFF-A4wg}pR8o0(B<`VY|qEIj64{dL3yxL3XLp7LgMzm&j zjMLGptlKxuo1l|NuSWj>q3u}rt>u!=yfI^*;y0c)WwMj8e!*LNEAlNLn*yPGPblMF zy#D~z8ueEN73={bA7`Qsl)+r%jlx_CO>cDev)88}11TF;gjCm71=Vg^F~w80vbnpu zTU#_Y6EQplYDsP&l0cKaeJQNZf)$DK&nUpy%X5pn`inUqnnvo)Ay8H(o!6Hr)X2e9nu65> zq0<@n6e&f+sy|T$!ugSAGbP$9lOg|y2p>{3oG?xBmn z4>Lt{LrEwUZcuy3AD}Vx)P=~FCnbB1zHCNrd$xiE`hTH|gzv$~DlLrMk`Or=1Fpwy zsB5lQjG0c7-&*sxx4e*dJ9A!K#VR?TQBsa2QOmd6WuhL2py(3OcMi0b*m;sg#qH*8 z035Atphh7s-H?co37SWboN^99qoTEcZGqf3UYaRZ zUQaFLGNezPW=qeGy#WEV z8%yNnR=2iti`%+DZWR=TXYQaWKy?nv%;-mw_~v5=EOJcoWpUYLd#rA55M+w(Fu|mF z17pm5HsKEt{(hf3QC_8?{Y)JnAT&A`DBTMhyVjeN9sn|OI05xPwFnK!2 zBf3j<5q83$_9KExUI4Dj%y}Qeo71f|?Z_sswWD_-;kP}CvuS@Np?s~9D9FN(V~ys- zvOAA`*mmO*B1gz6C+0kkj0#Td9=%&~L9w<_Ns?I7;M@ma{-DR*6HDAK6bkZ{eW*`L zwP{rqGVM~A$mN0~V-`N7RO5_^nqhb8nEwMSo=}oo7A!xzSj= zG^(tV%0O!JK%hGv>FG)jDXw#I&gylgWfBciefB)f+yoY89@ER#wW;`uS4Yz7gjgCa zjVz z>+7{g!+*m`&Su5NKk>@F98>~q%n5oW-1wq6$=ssL8x)!%84loy5bQ_*9f+>8HIM-E zJ_#*lq#rk9hw;q5Ya>0hOONs^UUrz&W^@owBFI$F&xh z_UDf7ZkdtK68Qa(+53|0Ns_nm;cEe4(_CAYl}L<7-K!!q5y{Z9SNp2N^3$vx(txIX zr;uZ^R_7CKc#ks9B^H%*w~|=HDI}Hck^?sutv?-SSg|W|GOk|nw`!Q$59L-?#c!f) zK51pLx=KQiC|>=ONZ?V+8vQ(pP)_`7$Zb$-DVt|JDi36-{^7!p(xww)#{{%)GFV)* z-Nh79=3u9Jn~av$Fcm7Wugs3m8Kp&b`D*5&;A3_iVtdmB5L{#35xZ}y4V1^&Ti-!F ztE=K~(93KK26&O3qcO`(mRQK;PlXRdT^89V98&iH2AC;r=eovPS>`d2_9nKuRa}EG zXYa;}?28#@Mo&}h+z_YMwq;ToKj!e5?=rzya|gXc$_|~TF3b8b~d(>2%#h~5%;Mq zso!%eFq!J#xc>k*8V~5y#?X!n1l%$tlrzd~@Hbc~V9MJpwn)^PWFScZZ*O%7{YcEO zQ|VCEU0ekt6@uJ(7Dj9pwib~koD9v$5G;~axhR!~%oLNve{QEJcSK}Y#k^ij^^EdO zJc8cP@VALgKzRozpgS)?`RP4gv{}jz?nSp4oKp{rms~ky@kTM9Z@%UxH^^{TRx36#*Cs7; z7C^}(rOXLgGImz}$z+l^o;EEJt48D4=zX@418(JLN%7u-Uj3-NYTVgeE#5XZ;*O7O zvdDyzLLOjCElmRY^xHxjk--*L0l@9jfm+*OEaNNPHmq6)h8-tWeU@*X&&wgs*Y6NpXb&FpZ>XH z85th$zlt1UO3w2hQG1-fnrzdFuBIU(x~n8`L|VL36a_nCynqW@@443fjWjIBEwPq6 zZQQO4EArdi%NkqH5AG$nyi}_JaS$9y|buIKZxXQF>TXn;lm`ge7HsGK4$2`J{W>OPd?kf&G%i)dfz&;6rWG zO#EIGyVsUo%vK6_G;a*tW zw{js1@jMp1f}URL5C~&YU10pBnA~zHAw^?oN;OVK2nV{_tpgUVxjo6C;(AZAt$!8U zUS@6$Y2bP``z50(K=M(`i-uGJN}8TZ2Ecv|LBH|Q?CVTuwCw7*A<2ih$KH#}601^L zMHME8sNecEsCALM1}XD;H)EDarb5>nD2FF&SZ0_7$XYhUOVgZn`H}kn0ISgYX>GFRhsjQcUpN1H^_Q6smFEk(ahwv<1FhH3kuIl90%=SnLc7z;8`HJ>-zuLluqmVk`trB!!iPmq{dx#P*n|E|meAI&tc1q}NJn zG})d}_4jrC@m4m$902ECx{(R6e`=A>>+_woLn+{^M4y} zA@Znlem-HggD^ywQG+8zZ0%VjxQxm3B#h3~Lqgl_%7TI@wy&6uYp((FTw3|R^1N%5 z@#$@3va&J-?n@*AS*|KK4>KcvJZLp4bpRNdZx7wKbFE)1ZY}LrHWfD2i`sg!QiSbI z#^YR&h)LN~W@WjyokQ4M+o#l9gTxUyp#=2>x`XljwZR-LOUyh<@5e68VEsli;e*=U zl;U=+Ba^QOp{ZKX_0@rOc3KbGY-|4j!n00jd-pOjgVlJdDgOX!y7FH?b+1N0;rgGl z9Obzy{nf_YN8}=S;b98d!t=8FIhP{5fE<%~&~%Eygd9io*Ul>l=4%S%s^*DQ+er$6BT%dKryXtGtif&$;L% zy1bXi{FJjhTS>))u0b8hWg%8@c0IXRN;)gJ)ClFlOUP3Ys-FhWwp=D{txegKO^EU& z?$MP4C`RE*ggjoZIeZ&!3PULXdP;iT$jT;C^$Zfvjb?3c{D$t>Va4>h88}5|KuK7+ zCRb{EQ;cAM=7T+KX2Eos4E@a-+j8m`5qzhwsx}QFJ-v$OwpG5W|7>uvywmB zS%YzY<;gWQJv87H31K%RZ&hqFOKo)-#lWTqG+b0BX(ePJyF8MS)jDnPttq(_?Pd&9 zRy8Ix9-bdmV=-l8p0u^gT1=~I@<(fYphmJp-OY z{QW+zhhlDIvy%HKZEEnmR^lv7C6+@Jmjt+yr=VMS*t;Ht)Y79&M1Zr)$P(1s>58Fi zh`+nFS|f`sq`0{>21jF3!;slkNE`nEwd+j|S0WEIw5fu1$6i{kyuv^CX2#4dojJ-) zP;pW_jLZ_hFQ&5f7UW16<_Wk(;;A>0-`L;Db!|IZ%7eG{An{PHl;ZyY-VMv;KA(Zn zMv@YSSqB?ni5pQgmI<%LJj&lWaF#h3mm7Na&n2r`H6xkfPEI6ATiYQO_OHWjVQc;% z+8OPf(HQ2$b?wknmo(V`klvXwv5brYOkB}lj@Wtlaz~7BUh24B9XWnoHIsJC?Us~e z4{z$D-JEd=3(b6yC1Z}Ul_af2<rm!NKj|WFEP(tJaqF#{a|FsP*-wgs?hhqSdvN8`14ddC(XvX#rbe8M`(GXXep*)hCf<344>8lEgAqbFJsu8~z@)HV8Z+c{u zS_!U5cSw7-(`|iaMpjeYiA$o9MPNlYI#*F+F>$?zK@XN(XlQ@JP^9kr#~%c{mzK)j z+aX~U$h%>E8G=}&iDGzSjzs6|288z(fHe=VL8jv6jucg#gAvVp78>f-&J2t*FVfEm zn}ocTBr!M-1CT(W+^tCEN)L4gh(Z`%W-T*$uPC{2pIMQ=BJq;lTZr$VoP`a#q+zMQ zKs5`b7_B$Qh9?&Vhm7Yk#LFx*3$T*K3rBA3Ia^!FKLl5klNB-%RRk?6nz5jCA~%Go ziNM?7yt655n#rZSI2eqx$!^Od%NsOl8o=?Etd*H62SLlF2?H^7aWcdn47H4(o8oiW zRG$$gE^Z}_-XcH<@*rw4LdvY5fWwyE4!S{-_TgHk*1Sohy10}uNg3gZ&&sK7`&8U} zy{bqWtFmL;Uz#iB$Dggaf-H0t4|jJ#Z*a0J1V&f()ASnrDm`^*#mcFe3isQ%B3})* zmMFfRZk}s|w^Ga_SCOcy&Pz~n+mWxtp1Sb=06Q{uM1M$#?tiKU)ECdZrVIu_XZkp= zFRmjEXDr~-H3Zatntj~TU%RvESEj& zyfvgTTdUj1+@`dS=eE;D9D=_qY~L%+UK5cwVtitHg(2MP(+p0TJ?wtLf$^CYkC)WP=H50$EwhcMd-60QkFU zrZCM9ySnbOcT`BIj318|*!yd~myOGeQ@_T6FO>$npZRtOVk|70*3%&jbL6Bf67KVu zXGA%sYDtAd$)E9TJ>L zs?vg@njEIZrN0Gn7a~y=8rJA49#Y@Nq8iVBJU(=3&umRl~glG#S@m^&?qWsMyk$8c1F8(;u7$ENilfK2V5w=hn%2^=@8S zCy}I|i&j#tMKneuxbrl@P<%%&l{%&N%eKs|XygvOy~@O7`ZQt49?yCtM-N3RsmtYZ ztbNk03s-Mw73jl$+j3J2l~?>80DIH37^D6H=fY>o}Os1#KqwFBY@rrLHVFj}6dy150r> zMebE)@B@7&HW_X3H`Mx&StWTdcaA9;2z~)km{Ethe;q9Wmiejk#B@>q-YXkW1WVP> z3u$7S2;L^|tNTNHd!^M7%F;xv<~0u|6=Sn{d;?@AH2Q%s#~rcYidaPsQq1Bn`L&!e zmax8y{A*(5DyehrYi53`$J^CU$An}n6b(*RZNqNOsu>K$V&aF$3|BdbXZk6*Ts%VJ zPT)l*b*~uQpisfwdQ^?K(Tp4=1lbCQ#-_QLrLFCps&|dr;UXkZkSQrv27}j9$Z4Yu zB3W7{2pe3r<=O1XXKwtL>7Vx>mB3!oab@?B$okY%R%OnZ{C_=^pD#Wa5r|xQwC%@t zG(^l~NRMg|@~{m^mWDNI?53WYq|0Ef2m|UVQ_t|Xub1ZVfpA2EOO=1#`zu~Io;;d#$U-JI|GstITb(WB-JgeD+fe3}lx<)%^ zi-_dpRgULvSquhSZ;V>aY2vt>d46c^A`Y|!0?HiF^y=Q4`OnDDHm2eK01+LO`XJoJ zX8!y)@ z61BXW1(Lw$@v{#dk{{-_*-A2ubt!i zZJoBt-uT7SHHF0FaI?CV7AY8kENE^Rs;_xSXeClniC@s=gqVU|7Tx&(V)R6=G8dN@ z?;XX(wTWhpE~b^xn4^dU9kgZ~%7A^N*ZP*Xrig8^TGwu6pfMd__H=lmS*w~{i5Dei zBJH7u5MJe|tHg658AGt8KfCGv@ejR9b?mGfqQ1YDZt~T_otr_E2wk>R06_(tu z6-O$0G-rrnr($($5GFNNy)hF|g(i;TIMYK(MKF*AY^qVkGvxeE{`N;f=Lk5h*~XZeRV??s?vt45+Wpd zS-)1^c?vp*{ux7z7gqucY;sCOGB{;XtIcRQv8_V&8Ps{QfJyM{N*y#o zV?oe=UXjJypIMxtiy0NIysBY=KAloy7jz@260|@j#zjD+)Rh|p?mDz#S2+E@U71d} zL;;lG0K`5VwjF6qPb9Oek7$iaK(!%43hiIYx-!g)yN^h&rivpc3)$Htx0Muu9Gt*c za~R}nzUrjcQ6j+-IZimOc5ArrFRVO?h0EIC1+d88Tr6QDy@hGPBa9E30HHgcwBEYM z)A=NAo!()N2cIt7R*ix~$81zyRfKtANZ?<3AKa2cMK?PIqZ6>M)Ygr;Wi?tlOYMpg z;8{ytUzNa_HU9wVmx1guQJRt2oNz2a{_9ZwTD|zZQGQ0ujk75Fqfyhi?ZperVV?<~ zyTeIW7Lu5vaBI#YYa0*ENYLRt(REEEgriOyc3`c+k4x_o&)e~oUIw;%BO6i!D!FG# z`iZK_;YZxzCtCA+!7W#`}u9*byT_>T^cqnAaKKOK}s{P>f&e#>rqjy z1&#|~ium2_<@b_7JhHr*4(iJsi_w`lj@bY*s`gQmHC5P71hH;JBw|4q=PJS!Wmeao&DT~t2>d%R|_)+wC+^?@OVx) z8#X)2{B|Z!7xGA!;@SYFmXopx8r`W-0S(Osf4rmQsjZok7~+Cb20rpj8|W_M{{Rx* z!>IVv)7P$w6efIjQz@VF=gHa=j<^x;BnREH_UOcsUR@8StZKL`UU@H=!nW&ue%E#Y zN86QRjt(qMWs~$=p0J!0S^Q%??p`QiGqi}e0izQ}Jw&=@K#Qb&2 ziFYxITP&MdTh5n=sS~WoMHtHx%fwKTQOk`!Blv1aQl*yCJ1a|UjjWO1+sHe23nUVL z#KjNoNz8Do3bGYrUNzd9%$J#a7)`tlB&{8)y2ToTT<}+A;$tiWbt}J9zWS`D z03_}Y*;NbaWVZ^@K&&G`fmEKJ(YOo!TKR>jo04thr6yKO_g>N;_^tk+296v^lHADL z2Q+u~fT_*w0}kP2Q|>A{ z4`J)MrnR#NZR*cfRE|?4C5q#k=2x+YlSOJ|J*6yp9w<#dZT|p0O9ypq#hK`uVe;&5 zZ^Y9D^=bbAG-==36IMM-Fw1}DFaFp04xERf zZ&|`UDEHhC{YwY_7T5m(#iX>piFBU;va}w9(=Qd?BmV$GeZcT3Si(I8?A8>#422cL3FaByBP-3YSn)o06&&xmiB%l24rmR%U1*}>KkXm#>*m&dK`k|(eaZg-)|kKi6u + + + Documentation for the LLVM System at SVN head + + + + +
Documentation for the LLVM System at SVN head
+ +

If you are using a released version of LLVM, +see the download page to find +your documentation.

+ + + +
+

Written by The LLVM Team

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • The +LLVM Announcements List: This is a low volume list that provides important +announcements regarding LLVM. It gets email about once a month.
  • + +
  • The Developer's +List: This list is for people who want to be included in technical +discussions of LLVM. People post to this list when they have questions about +writing code for or using the LLVM tools. It is relatively low volume.
  • + +
  • The Bugs & +Patches Archive: This list gets emailed every time a bug is opened and +closed, and when people submit patches to be included in LLVM. It is higher +volume than the LLVMdev list.
  • + +
  • The Commits +Archive: This list contains all commit messages that are made when LLVM +developers commit code changes to the repository. It is useful for those who +want to stay on the bleeding edge of LLVM development. This list is very high +volume.
  • + +
  • The +Test Results Archive: A message is automatically sent to this list by every +active nightly tester when it completes. As such, this list gets email several +times each day, making it a high volume list.
  • + +
+ + + +
+
+ Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/llvm.css b/final/docs/llvm.css new file mode 100644 index 00000000000..f572b5e5714 --- /dev/null +++ b/final/docs/llvm.css @@ -0,0 +1,100 @@ +/* + * LLVM documentation style sheet + */ + +/* Common styles */ +.body { color: black; background: white; margin: 0 0 0 0 } + +/* No borders on image links */ +a:link img, a:visited img { border-style: none } + +address img { float: right; width: 88px; height: 31px; } +address { clear: right; } + +table { text-align: center; border: 2px solid black; + border-collapse: collapse; margin-top: 1em; margin-left: 1em; + margin-right: 1em; margin-bottom: 1em; } +tr, td { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; } +th { border: 2px solid gray; font-weight: bold; font-size: 105%; + background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; + text-align: center; vertical-align: middle; } +/* + * Documentation + */ +/* Common for title and header */ +.doc_title, .doc_section, .doc_subsection, h1, h2 { + color: black; background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} + +h1, .doc_section { text-align: center; font-size: 22pt; + margin: 20pt 0pt 5pt 0pt; } + +.doc_title, .title { text-align: left; font-size: 25pt } + +h2, .doc_subsection { width: 75%; + text-align: left; font-size: 12pt; + padding: 4pt 4pt 4pt 4pt; + margin: 1.5em 0.5em 0.5em 0.5em } + +h3, .doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em; + font-weight: bold; font-style: oblique; + border-bottom: 1px solid #999999; font-size: 12pt; + width: 75%; } + +.doc_author { text-align: left; font-weight: bold; padding-left: 20pt } +.doc_text { text-align: left; padding-left: 20pt; padding-right: 10pt } + +.doc_footer { text-align: left; padding: 0 0 0 0 } + +.doc_hilite { color: blue; font-weight: bold; } + +.doc_table { text-align: center; width: 90%; + padding: 1px 1px 1px 1px; border: 1px; } + +.doc_warning { color: red; font-weight: bold } + +/*
would use this class, and
adds more padding */ +.doc_code, .literal-block + { border: solid 1px gray; background: #eeeeee; + margin: 0 1em 0 1em; + padding: 0 1em 0 1em; + display: table; + } + +/* It is preferrable to use
 everywhere instead of the
+ * 
...
construct. + * + * Once all docs use
 for code regions, this style can  be merged with the
+ * one above, and we can drop the [pre] qualifier.
+ */
+pre.doc_code, .literal-block { padding: 1em 2em 1em 1em }
+
+.doc_notes      { background: #fafafa; border: 1px solid #cecece;
+                  display: table; padding: 0 1em 0 .1em }
+
+table.layout    { text-align: left; border: none; border-collapse: collapse;
+                  padding: 4px 4px 4px 4px; }
+tr.layout, td.layout, td.left, td.right
+                { border: none; padding: 4pt 4pt 2pt 2pt; vertical-align: top; }
+td.left         { text-align: left }
+td.right        { text-align: right }
+th.layout       { border: none; font-weight: bold; font-size: 105%;
+                  text-align: center; vertical-align: middle; }
+
+/* Left align table cell */
+.td_left        { border: 2px solid gray; text-align: left; }
+
+/* ReST-specific */
+.title { margin-top: 0 }
+.topic-title{ display: none }
+div.contents ul { list-style-type: decimal }
+.toc-backref    { color: black; text-decoration: none; }
diff --git a/final/docs/re_format.7 b/final/docs/re_format.7
new file mode 100644
index 00000000000..0c0928716f4
--- /dev/null
+++ b/final/docs/re_format.7
@@ -0,0 +1,756 @@
+.\"	$OpenBSD: re_format.7,v 1.14 2007/05/31 19:19:30 jmc Exp $
+.\"
+.\" Copyright (c) 1997, Phillip F Knaack. All rights reserved.
+.\"
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"	@(#)re_format.7	8.3 (Berkeley) 3/20/94
+.\"
+.Dd $Mdocdate: May 31 2007 $
+.Dt RE_FORMAT 7
+.Os
+.Sh NAME
+.Nm re_format
+.Nd POSIX regular expressions
+.Sh DESCRIPTION
+Regular expressions (REs),
+as defined in
+.St -p1003.1-2004 ,
+come in two forms:
+basic regular expressions
+(BREs)
+and extended regular expressions
+(EREs).
+Both forms of regular expressions are supported
+by the interfaces described in
+.Xr regex 3 .
+Applications dealing with regular expressions
+may use one or the other form
+(or indeed both).
+For example,
+.Xr ed 1
+uses BREs,
+whilst
+.Xr egrep 1
+talks EREs.
+Consult the manual page for the specific application to find out which
+it uses.
+.Pp
+POSIX leaves some aspects of RE syntax and semantics open;
+.Sq **
+marks decisions on these aspects that
+may not be fully portable to other POSIX implementations.
+.Pp
+This manual page first describes regular expressions in general,
+specifically extended regular expressions,
+and then discusses differences between them and basic regular expressions.
+.Sh EXTENDED REGULAR EXPRESSIONS
+An ERE is one** or more non-empty**
+.Em branches ,
+separated by
+.Sq \*(Ba .
+It matches anything that matches one of the branches.
+.Pp
+A branch is one** or more
+.Em pieces ,
+concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.Pp
+A piece is an
+.Em atom
+possibly followed by a single**
+.Sq * ,
+.Sq + ,
+.Sq ?\& ,
+or
+.Em bound .
+An atom followed by
+.Sq *
+matches a sequence of 0 or more matches of the atom.
+An atom followed by
+.Sq +
+matches a sequence of 1 or more matches of the atom.
+An atom followed by
+.Sq ?\&
+matches a sequence of 0 or 1 matches of the atom.
+.Pp
+A bound is
+.Sq {
+followed by an unsigned decimal integer,
+possibly followed by
+.Sq ,\&
+possibly followed by another unsigned decimal integer,
+always followed by
+.Sq } .
+The integers must lie between 0 and
+.Dv RE_DUP_MAX
+(255**) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer
+.Ar i
+and no comma matches
+a sequence of exactly
+.Ar i
+matches of the atom.
+An atom followed by a bound
+containing one integer
+.Ar i
+and a comma matches
+a sequence of
+.Ar i
+or more matches of the atom.
+An atom followed by a bound
+containing two integers
+.Ar i
+and
+.Ar j
+matches a sequence of
+.Ar i
+through
+.Ar j
+(inclusive) matches of the atom.
+.Pp
+An atom is a regular expression enclosed in
+.Sq ()
+(matching a part of the regular expression),
+an empty set of
+.Sq ()
+(matching the null string)**,
+a
+.Em bracket expression
+(see below),
+.Sq .\&
+(matching any single character),
+.Sq ^
+(matching the null string at the beginning of a line),
+.Sq $
+(matching the null string at the end of a line),
+a
+.Sq \e
+followed by one of the characters
+.Sq ^.[$()|*+?{\e
+(matching that character taken as an ordinary character),
+a
+.Sq \e
+followed by any other character**
+(matching that character taken as an ordinary character,
+as if the
+.Sq \e
+had not been present**),
+or a single character with no other significance (matching that character).
+A
+.Sq {
+followed by a character other than a digit is an ordinary character,
+not the beginning of a bound**.
+It is illegal to end an RE with
+.Sq \e .
+.Pp
+A bracket expression is a list of characters enclosed in
+.Sq [] .
+It normally matches any single character from the list (but see below).
+If the list begins with
+.Sq ^ ,
+it matches any single character
+.Em not
+from the rest of the list
+(but see below).
+If two characters in the list are separated by
+.Sq - ,
+this is shorthand for the full
+.Em range
+of characters between those two (inclusive) in the
+collating sequence, e.g.\&
+.Sq [0-9]
+in ASCII matches any decimal digit.
+It is illegal** for two ranges to share an endpoint, e.g.\&
+.Sq a-c-e .
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.Pp
+To include a literal
+.Sq ]\&
+in the list, make it the first character
+(following a possible
+.Sq ^ ) .
+To include a literal
+.Sq - ,
+make it the first or last character,
+or the second endpoint of a range.
+To use a literal
+.Sq -
+as the first endpoint of a range,
+enclose it in
+.Sq [.
+and
+.Sq .]
+to make it a collating element (see below).
+With the exception of these and some combinations using
+.Sq [
+(see next paragraphs),
+all other special characters, including
+.Sq \e ,
+lose their special significance within a bracket expression.
+.Pp
+Within a bracket expression, a collating element
+(a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in
+.Sq [.
+and
+.Sq .]
+stands for the sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element
+can thus match more than one character,
+e.g. if the collating sequence includes a
+.Sq ch
+collating element,
+then the RE
+.Sq [[.ch.]]*c
+matches the first five characters of
+.Sq chchcc .
+.Pp
+Within a bracket expression, a collating element enclosed in
+.Sq [=
+and
+.Sq =]
+is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were
+.Sq [.
+and
+.Sq .] . )
+For example, if
+.Sq x
+and
+.Sq y
+are the members of an equivalence class,
+then
+.Sq [[=x=]] ,
+.Sq [[=y=]] ,
+and
+.Sq [xy]
+are all synonymous.
+An equivalence class may not** be an endpoint of a range.
+.Pp
+Within a bracket expression, the name of a
+.Em character class
+enclosed
+in
+.Sq [:
+and
+.Sq :]
+stands for the list of all characters belonging to that class.
+Standard character class names are:
+.Bd -literal -offset indent
+alnum	digit	punct
+alpha	graph	space
+blank	lower	upper
+cntrl	print	xdigit
+.Ed
+.Pp
+These stand for the character classes defined in
+.Xr ctype 3 .
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.Pp
+There are two special cases** of bracket expressions:
+the bracket expressions
+.Sq [[:<:]]
+and
+.Sq [[:>:]]
+match the null string at the beginning and end of a word, respectively.
+A word is defined as a sequence of
+characters starting and ending with a word character
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.Em alnum
+character (as defined by
+.Xr ctype 3 )
+or an underscore.
+This is an extension,
+compatible with but not specified by POSIX,
+and should be used with
+caution in software intended to be portable to other systems.
+.Pp
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.Pp
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+.Sq bb*
+matches the three middle characters of
+.Sq abbbc ;
+.Sq (wee|week)(knights|nights)
+matches all ten characters of
+.Sq weeknights ;
+when
+.Sq (.*).*
+is matched against
+.Sq abc ,
+the parenthesized subexpression matches all three characters;
+and when
+.Sq (a*)*
+is matched against
+.Sq bc ,
+both the whole RE and the parenthesized subexpression match the null string.
+.Pp
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+e.g.\&
+.Sq x
+becomes
+.Sq [xX] .
+When it appears inside a bracket expression,
+all case counterparts of it are added to the bracket expression,
+so that, for example,
+.Sq [x]
+becomes
+.Sq [xX]
+and
+.Sq [^x]
+becomes
+.Sq [^xX] .
+.Pp
+No particular limit is imposed on the length of REs**.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.Pp
+The following is a list of extended regular expressions:
+.Bl -tag -width Ds
+.It Ar c
+Any character
+.Ar c
+not listed below matches itself.
+.It \e Ns Ar c
+Any backslash-escaped character
+.Ar c
+matches itself.
+.It \&.
+Matches any single character that is not a newline
+.Pq Sq \en .
+.It Bq Ar char-class
+Matches any single character in
+.Ar char-class .
+To include a
+.Ql \&]
+in
+.Ar char-class ,
+it must be the first character.
+A range of characters may be specified by separating the end characters
+of the range with a
+.Ql - ;
+e.g.\&
+.Ar a-z
+specifies the lower case characters.
+The following literal expressions can also be used in
+.Ar char-class
+to specify sets of characters:
+.Bd -unfilled -offset indent
+[:alnum:] [:cntrl:] [:lower:] [:space:]
+[:alpha:] [:digit:] [:print:] [:upper:]
+[:blank:] [:graph:] [:punct:] [:xdigit:]
+.Ed
+.Pp
+If
+.Ql -
+appears as the first or last character of
+.Ar char-class ,
+then it matches itself.
+All other characters in
+.Ar char-class
+match themselves.
+.Pp
+Patterns in
+.Ar char-class
+of the form
+.Eo [.
+.Ar col-elm
+.Ec .]\&
+or
+.Eo [=
+.Ar col-elm
+.Ec =]\& ,
+where
+.Ar col-elm
+is a collating element, are interpreted according to
+.Xr setlocale 3
+.Pq not currently supported .
+.It Bq ^ Ns Ar char-class
+Matches any single character, other than newline, not in
+.Ar char-class .
+.Ar char-class
+is defined as above.
+.It ^
+If
+.Sq ^
+is the first character of a regular expression, then it
+anchors the regular expression to the beginning of a line.
+Otherwise, it matches itself.
+.It $
+If
+.Sq $
+is the last character of a regular expression,
+it anchors the regular expression to the end of a line.
+Otherwise, it matches itself.
+.It [[:<:]]
+Anchors the single character regular expression or subexpression
+immediately following it to the beginning of a word.
+.It [[:>:]]
+Anchors the single character regular expression or subexpression
+immediately following it to the end of a word.
+.It Pq Ar re
+Defines a subexpression
+.Ar re .
+Any set of characters enclosed in parentheses
+matches whatever the set of characters without parentheses matches
+(that is a long-winded way of saying the constructs
+.Sq (re)
+and
+.Sq re
+match identically).
+.It *
+Matches the single character regular expression or subexpression
+immediately preceding it zero or more times.
+If
+.Sq *
+is the first character of a regular expression or subexpression,
+then it matches itself.
+The
+.Sq *
+operator sometimes yields unexpected results.
+For example, the regular expression
+.Ar b*
+matches the beginning of the string
+.Qq abbb
+(as opposed to the substring
+.Qq bbb ) ,
+since a null match is the only leftmost match.
+.It +
+Matches the singular character regular expression
+or subexpression immediately preceding it
+one or more times.
+.It ?
+Matches the singular character regular expression
+or subexpression immediately preceding it
+0 or 1 times.
+.Sm off
+.It Xo
+.Pf { Ar n , m No }\ \&
+.Pf { Ar n , No }\ \&
+.Pf { Ar n No }
+.Xc
+.Sm on
+Matches the single character regular expression or subexpression
+immediately preceding it at least
+.Ar n
+and at most
+.Ar m
+times.
+If
+.Ar m
+is omitted, then it matches at least
+.Ar n
+times.
+If the comma is also omitted, then it matches exactly
+.Ar n
+times.
+.It \*(Ba
+Used to separate patterns.
+For example,
+the pattern
+.Sq cat\*(Badog
+matches either
+.Sq cat
+or
+.Sq dog .
+.El
+.Sh BASIC REGULAR EXPRESSIONS
+Basic regular expressions differ in several respects:
+.Bl -bullet -offset 3n
+.It
+.Sq \*(Ba ,
+.Sq + ,
+and
+.Sq ?\&
+are ordinary characters and there is no equivalent
+for their functionality.
+.It
+The delimiters for bounds are
+.Sq \e{
+and
+.Sq \e} ,
+with
+.Sq {
+and
+.Sq }
+by themselves ordinary characters.
+.It
+The parentheses for nested subexpressions are
+.Sq \e(
+and
+.Sq \e) ,
+with
+.Sq (
+and
+.Sq )\&
+by themselves ordinary characters.
+.It
+.Sq ^
+is an ordinary character except at the beginning of the
+RE or** the beginning of a parenthesized subexpression.
+.It
+.Sq $
+is an ordinary character except at the end of the
+RE or** the end of a parenthesized subexpression.
+.It
+.Sq *
+is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading
+.Sq ^ ) .
+.It
+Finally, there is one new type of atom, a
+.Em back-reference :
+.Sq \e
+followed by a non-zero decimal digit
+.Ar d
+matches the same sequence of characters matched by the
+.Ar d Ns th
+parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that, for example,
+.Sq \e([bc]\e)\e1
+matches
+.Sq bb\&
+or
+.Sq cc
+but not
+.Sq bc .
+.El
+.Pp
+The following is a list of basic regular expressions:
+.Bl -tag -width Ds
+.It Ar c
+Any character
+.Ar c
+not listed below matches itself.
+.It \e Ns Ar c
+Any backslash-escaped character
+.Ar c ,
+except for
+.Sq { ,
+.Sq } ,
+.Sq \&( ,
+and
+.Sq \&) ,
+matches itself.
+.It \&.
+Matches any single character that is not a newline
+.Pq Sq \en .
+.It Bq Ar char-class
+Matches any single character in
+.Ar char-class .
+To include a
+.Ql \&]
+in
+.Ar char-class ,
+it must be the first character.
+A range of characters may be specified by separating the end characters
+of the range with a
+.Ql - ;
+e.g.\&
+.Ar a-z
+specifies the lower case characters.
+The following literal expressions can also be used in
+.Ar char-class
+to specify sets of characters:
+.Bd -unfilled -offset indent
+[:alnum:] [:cntrl:] [:lower:] [:space:]
+[:alpha:] [:digit:] [:print:] [:upper:]
+[:blank:] [:graph:] [:punct:] [:xdigit:]
+.Ed
+.Pp
+If
+.Ql -
+appears as the first or last character of
+.Ar char-class ,
+then it matches itself.
+All other characters in
+.Ar char-class
+match themselves.
+.Pp
+Patterns in
+.Ar char-class
+of the form
+.Eo [.
+.Ar col-elm
+.Ec .]\&
+or
+.Eo [=
+.Ar col-elm
+.Ec =]\& ,
+where
+.Ar col-elm
+is a collating element, are interpreted according to
+.Xr setlocale 3
+.Pq not currently supported .
+.It Bq ^ Ns Ar char-class
+Matches any single character, other than newline, not in
+.Ar char-class .
+.Ar char-class
+is defined as above.
+.It ^
+If
+.Sq ^
+is the first character of a regular expression, then it
+anchors the regular expression to the beginning of a line.
+Otherwise, it matches itself.
+.It $
+If
+.Sq $
+is the last character of a regular expression,
+it anchors the regular expression to the end of a line.
+Otherwise, it matches itself.
+.It [[:<:]]
+Anchors the single character regular expression or subexpression
+immediately following it to the beginning of a word.
+.It [[:>:]]
+Anchors the single character regular expression or subexpression
+immediately following it to the end of a word.
+.It \e( Ns Ar re Ns \e)
+Defines a subexpression
+.Ar re .
+Subexpressions may be nested.
+A subsequent backreference of the form
+.Pf \e Ns Ar n ,
+where
+.Ar n
+is a number in the range [1,9], expands to the text matched by the
+.Ar n Ns th
+subexpression.
+For example, the regular expression
+.Ar \e(.*\e)\e1
+matches any string consisting of identical adjacent substrings.
+Subexpressions are ordered relative to their left delimiter.
+.It *
+Matches the single character regular expression or subexpression
+immediately preceding it zero or more times.
+If
+.Sq *
+is the first character of a regular expression or subexpression,
+then it matches itself.
+The
+.Sq *
+operator sometimes yields unexpected results.
+For example, the regular expression
+.Ar b*
+matches the beginning of the string
+.Qq abbb
+(as opposed to the substring
+.Qq bbb ) ,
+since a null match is the only leftmost match.
+.Sm off
+.It Xo
+.Pf \e{ Ar n , m No \e}\ \&
+.Pf \e{ Ar n , No \e}\ \&
+.Pf \e{ Ar n No \e}
+.Xc
+.Sm on
+Matches the single character regular expression or subexpression
+immediately preceding it at least
+.Ar n
+and at most
+.Ar m
+times.
+If
+.Ar m
+is omitted, then it matches at least
+.Ar n
+times.
+If the comma is also omitted, then it matches exactly
+.Ar n
+times.
+.El
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr regex 3
+.Sh STANDARDS
+.St -p1003.1-2004 :
+Base Definitions, Chapter 9 (Regular Expressions).
+.Sh BUGS
+Having two kinds of REs is a botch.
+.Pp
+The current POSIX spec says that
+.Sq )\&
+is an ordinary character in the absence of an unmatched
+.Sq ( ;
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.Pp
+Back-references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+.Sq a\e(\e(b\e)*\e2\e)*d
+match
+.Sq abbbd ? ) .
+Avoid using them.
+.Pp
+POSIX's specification of case-independent matching is vague.
+The
+.Dq one case implies all cases
+definition given above
+is the current consensus among implementors as to the right interpretation.
+.Pp
+The syntax for word boundaries is incredibly ugly.
diff --git a/final/docs/tutorial/LangImpl1.html b/final/docs/tutorial/LangImpl1.html
new file mode 100644
index 00000000000..66843db5d3a
--- /dev/null
+++ b/final/docs/tutorial/LangImpl1.html
@@ -0,0 +1,348 @@
+
+
+
+
+  Kaleidoscope: Tutorial Introduction and the Lexer
+  
+  
+  
+
+
+
+
+
Kaleidoscope: Tutorial Introduction and the Lexer
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to the "Implementing a language with LLVM" tutorial. This tutorial +runs through the implementation of a simple language, showing how fun and +easy it can be. This tutorial will get you up and started as well as help to +build a framework you can extend to other languages. The code in this tutorial +can also be used as a playground to hack on other LLVM specific things. +

+ +

+The goal of this tutorial is to progressively unveil our language, describing +how it is built up over time. This will let us cover a fairly broad range of +language design and LLVM-specific usage issues, showing and explaining the code +for it all along the way, without overwhelming you with tons of details up +front.

+ +

It is useful to point out ahead of time that this tutorial is really about +teaching compiler techniques and LLVM specifically, not about teaching +modern and sane software engineering principles. In practice, this means that +we'll take a number of shortcuts to simplify the exposition. For example, the +code leaks memory, uses global variables all over the place, doesn't use nice +design patterns like visitors, etc... but it +is very simple. If you dig in and use the code as a basis for future projects, +fixing these deficiencies shouldn't be hard.

+ +

I've tried to put this tutorial together in a way that makes chapters easy to +skip over if you are already familiar with or are uninterested in the various +pieces. The structure of the tutorial is: +

+ +
    +
  • Chapter #1: Introduction to the Kaleidoscope +language, and the definition of its Lexer - This shows where we are going +and the basic functionality that we want it to do. In order to make this +tutorial maximally understandable and hackable, we choose to implement +everything in C++ instead of using lexer and parser generators. LLVM obviously +works just fine with such tools, feel free to use one if you prefer.
  • +
  • Chapter #2: Implementing a Parser and +AST - With the lexer in place, we can talk about parsing techniques and +basic AST construction. This tutorial describes recursive descent parsing and +operator precedence parsing. Nothing in Chapters 1 or 2 is LLVM-specific, +the code doesn't even link in LLVM at this point. :)
  • +
  • Chapter #3: Code generation to LLVM IR - +With the AST ready, we can show off how easy generation of LLVM IR really +is.
  • +
  • Chapter #4: Adding JIT and Optimizer +Support - Because a lot of people are interested in using LLVM as a JIT, +we'll dive right into it and show you the 3 lines it takes to add JIT support. +LLVM is also useful in many other ways, but this is one simple and "sexy" way +to shows off its power. :)
  • +
  • Chapter #5: Extending the Language: Control +Flow - With the language up and running, we show how to extend it with +control flow operations (if/then/else and a 'for' loop). This gives us a chance +to talk about simple SSA construction and control flow.
  • +
  • Chapter #6: Extending the Language: +User-defined Operators - This is a silly but fun chapter that talks about +extending the language to let the user program define their own arbitrary +unary and binary operators (with assignable precedence!). This lets us build a +significant piece of the "language" as library routines.
  • +
  • Chapter #7: Extending the Language: Mutable +Variables - This chapter talks about adding user-defined local variables +along with an assignment operator. The interesting part about this is how +easy and trivial it is to construct SSA form in LLVM: no, LLVM does not +require your front-end to construct SSA form!
  • +
  • Chapter #8: Conclusion and other useful LLVM +tidbits - This chapter wraps up the series by talking about potential +ways to extend the language, but also includes a bunch of pointers to info about +"special topics" like adding garbage collection support, exceptions, debugging, +support for "spaghetti stacks", and a bunch of other tips and tricks.
  • + +
+ +

By the end of the tutorial, we'll have written a bit less than 700 lines of +non-comment, non-blank, lines of code. With this small amount of code, we'll +have built up a very reasonable compiler for a non-trivial language including +a hand-written lexer, parser, AST, as well as code generation support with a JIT +compiler. While other systems may have interesting "hello world" tutorials, +I think the breadth of this tutorial is a great testament to the strengths of +LLVM and why you should consider it if you're interested in language or compiler +design.

+ +

A note about this tutorial: we expect you to extend the language and play +with it on your own. Take the code and go crazy hacking away at it, compilers +don't need to be scary creatures - it can be a lot of fun to play with +languages!

+ +
+ + + + + +
+ +

This tutorial will be illustrated with a toy language that we'll call +"Kaleidoscope" (derived +from "meaning beautiful, form, and view"). +Kaleidoscope is a procedural language that allows you to define functions, use +conditionals, math, etc. Over the course of the tutorial, we'll extend +Kaleidoscope to support the if/then/else construct, a for loop, user defined +operators, JIT compilation with a simple command line interface, etc.

+ +

Because we want to keep things simple, the only datatype in Kaleidoscope is a +64-bit floating point type (aka 'double' in C parlance). As such, all values +are implicitly double precision and the language doesn't require type +declarations. This gives the language a very nice and simple syntax. For +example, the following simple example computes Fibonacci numbers:

+ +
+
+# Compute the x'th fibonacci number.
+def fib(x)
+  if x < 3 then
+    1
+  else
+    fib(x-1)+fib(x-2)
+
+# This expression will compute the 40th number.
+fib(40)
+
+
+ +

We also allow Kaleidoscope to call into standard library functions (the LLVM +JIT makes this completely trivial). This means that you can use the 'extern' +keyword to define a function before you use it (this is also useful for mutually +recursive functions). For example:

+ +
+
+extern sin(arg);
+extern cos(arg);
+extern atan2(arg1 arg2);
+
+atan2(sin(.4), cos(42))
+
+
+ +

A more interesting example is included in Chapter 6 where we write a little +Kaleidoscope application that displays +a Mandelbrot Set at various levels of magnification.

+ +

Lets dive into the implementation of this language!

+ +
+ + + + + +
+ +

When it comes to implementing a language, the first thing needed is +the ability to process a text file and recognize what it says. The traditional +way to do this is to use a "lexer" (aka 'scanner') +to break the input up into "tokens". Each token returned by the lexer includes +a token code and potentially some metadata (e.g. the numeric value of a number). +First, we define the possibilities: +

+ +
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5,
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+
+ +

Each token returned by our lexer will either be one of the Token enum values +or it will be an 'unknown' character like '+', which is returned as its ASCII +value. If the current token is an identifier, the IdentifierStr +global variable holds the name of the identifier. If the current token is a +numeric literal (like 1.0), NumVal holds its value. Note that we use +global variables for simplicity, this is not the best choice for a real language +implementation :). +

+ +

The actual implementation of the lexer is a single function named +gettok. The gettok function is called to return the next token +from standard input. Its definition starts as:

+ +
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+
+ +

+gettok works by calling the C getchar() function to read +characters one at a time from standard input. It eats them as it recognizes +them and stores the last character read, but not processed, in LastChar. The +first thing that it has to do is ignore whitespace between tokens. This is +accomplished with the loop above.

+ +

The next thing gettok needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with this simple loop:

+ +
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    return tok_identifier;
+  }
+
+
+ +

Note that this code sets the 'IdentifierStr' global whenever it +lexes an identifier. Also, since language keywords are matched by the same +loop, we handle them here inline. Numeric values are similar:

+ +
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+
+ +

This is all pretty straight-forward code for processing input. When reading +a numeric value from input, we use the C strtod function to convert it +to a numeric value that we store in NumVal. Note that this isn't doing +sufficient error checking: it will incorrectly read "1.23.45.67" and handle it as +if you typed in "1.23". Feel free to extend it :). Next we handle comments: +

+ +
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+
+
+ +

We handle comments by skipping to the end of the line and then return the +next token. Finally, if the input doesn't match one of the above cases, it is +either an operator character like '+' or the end of the file. These are handled +with this code:

+ +
+
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+  
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+
+ +

With this, we have the complete lexer for the basic Kaleidoscope language +(the full code listing for the Lexer is +available in the next chapter of the tutorial). +Next we'll build a simple parser that uses this to +build an Abstract Syntax Tree. When we have that, we'll include a driver +so that you can use the lexer and parser together. +

+ +Next: Implementing a Parser and AST +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl2.html b/final/docs/tutorial/LangImpl2.html new file mode 100644 index 00000000000..9c13b486fa8 --- /dev/null +++ b/final/docs/tutorial/LangImpl2.html @@ -0,0 +1,1233 @@ + + + + + Kaleidoscope: Implementing a Parser and AST + + + + + + + +
Kaleidoscope: Implementing a Parser and AST
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 2 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to use the lexer, built in +Chapter 1, to build a full parser for +our Kaleidoscope language. Once we have a parser, we'll define and build an Abstract Syntax +Tree (AST).

+ +

The parser we will build uses a combination of Recursive Descent +Parsing and Operator-Precedence +Parsing to parse the Kaleidoscope language (the latter for +binary expressions and the former for everything else). Before we get to +parsing though, lets talk about the output of the parser: the Abstract Syntax +Tree.

+ +
+ + + + + +
+ +

The AST for a program captures its behavior in such a way that it is easy for +later stages of the compiler (e.g. code generation) to interpret. We basically +want one object for each construct in the language, and the AST should closely +model the language. In Kaleidoscope, we have expressions, a prototype, and a +function object. We'll start with expressions first:

+ +
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+};
+
+
+ +

The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note about +this code is that the NumberExprAST class captures the numeric value of the +literal as an instance variable. This allows later phases of the compiler to +know what the stored numeric value is.

+ +

Right now we only create the AST, so there are no useful accessor methods on +them. It would be very easy to add a virtual method to pretty print the code, +for example. Here are the other expression AST node definitions that we'll use +in the basic form of the Kaleidoscope language: +

+ +
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+};
+
+
+ +

This is all (intentionally) rather straight-forward: variables capture the +variable name, binary operators capture their opcode (e.g. '+'), and calls +capture a function name as well as a list of any argument expressions. One thing +that is nice about our AST is that it captures the language features without +talking about the syntax of the language. Note that there is no discussion about +precedence of binary operators, lexical structure, etc.

+ +

For our basic language, these are all of the expression nodes we'll define. +Because it doesn't have conditional control flow, it isn't Turing-complete; +we'll fix that in a later installment. The two things we need next are a way +to talk about the interface to a function, and a way to talk about functions +themselves:

+ +
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+    : Name(name), Args(args) {}
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+};
+
+
+ +

In Kaleidoscope, functions are typed with just a count of their arguments. +Since all values are double precision floating point, the type of each argument +doesn't need to be stored anywhere. In a more aggressive and realistic +language, the "ExprAST" class would probably have a type field.

+ +

With this scaffolding, we can now talk about parsing expressions and function +bodies in Kaleidoscope.

+ +
+ + + + + +
+ +

Now that we have an AST to build, we need to define the parser code to build +it. The idea here is that we want to parse something like "x+y" (which is +returned as three tokens by the lexer) into an AST that could be generated with +calls like this:

+ +
+
+  ExprAST *X = new VariableExprAST("x");
+  ExprAST *Y = new VariableExprAST("y");
+  ExprAST *Result = new BinaryExprAST('+', X, Y);
+
+
+ +

In order to do this, we'll start by defining some basic helper routines:

+ +
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+
+ +

+This implements a simple token buffer around the lexer. This allows +us to look one token ahead at what the lexer is returning. Every function in +our parser will assume that CurTok is the current token that needs to be +parsed.

+ +
+
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+
+ +

+The Error routines are simple helper routines that our parser will use +to handle errors. The error recovery in our parser will not be the best and +is not particular user-friendly, but it will be enough for our tutorial. These +routines make it easier to handle errors in routines that have various return +types: they always return null.

+ +

With these basic helper functions, we can implement the first +piece of our grammar: numeric literals.

+ +
+ + + + + +
+ +

We start with numeric literals, because they are the simplest to process. +For each production in our grammar, we'll define a function which parses that +production. For numeric literals, we have: +

+ +
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+
+ +

This routine is very simple: it expects to be called when the current token +is a tok_number token. It takes the current number value, creates +a NumberExprAST node, advances the lexer to the next token, and finally +returns.

+ +

There are some interesting aspects to this. The most important one is that +this routine eats all of the tokens that correspond to the production and +returns the lexer buffer with the next token (which is not part of the grammar +production) ready to go. This is a fairly standard way to go for recursive +descent parsers. For a better example, the parenthesis operator is defined like +this:

+ +
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+
+ +

This function illustrates a number of interesting things about the +parser:

+ +

+1) It shows how we use the Error routines. When called, this function expects +that the current token is a '(' token, but after parsing the subexpression, it +is possible that there is no ')' waiting. For example, if the user types in +"(4 x" instead of "(4)", the parser should emit an error. Because errors can +occur, the parser needs a way to indicate that they happened: in our parser, we +return null on an error.

+ +

2) Another interesting aspect of this function is that it uses recursion by +calling ParseExpression (we will soon see that ParseExpression can call +ParseParenExpr). This is powerful because it allows us to handle +recursive grammars, and keeps each production very simple. Note that +parentheses do not cause construction of AST nodes themselves. While we could +do it this way, the most important role of parentheses are to guide the parser +and provide grouping. Once the parser constructs the AST, parentheses are not +needed.

+ +

The next simple production is for handling variable references and function +calls:

+ +
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+
+ +

This routine follows the same style as the other routines. (It expects to be +called if the current token is a tok_identifier token). It also has +recursion and error handling. One interesting aspect of this is that it uses +look-ahead to determine if the current identifier is a stand alone +variable reference or if it is a function call expression. It handles this by +checking to see if the token after the identifier is a '(' token, constructing +either a VariableExprAST or CallExprAST node as appropriate. +

+ +

Now that we have all of our simple expression-parsing logic in place, we can +define a helper function to wrap it together into one entry point. We call this +class of expressions "primary" expressions, for reasons that will become more +clear later in the tutorial. In order to +parse an arbitrary primary expression, we need to determine what sort of +expression it is:

+ +
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  }
+}
+
+
+ +

Now that you see the definition of this function, it is more obvious why we +can assume the state of CurTok in the various functions. This uses look-ahead +to determine which sort of expression is being inspected, and then parses it +with a function call.

+ +

Now that basic expressions are handled, we need to handle binary expressions. +They are a bit more complex.

+ +
+ + + + + +
+ +

Binary expressions are significantly harder to parse because they are often +ambiguous. For example, when given the string "x+y*z", the parser can choose +to parse it as either "(x+y)*z" or "x+(y*z)". With common definitions from +mathematics, we expect the later parse, because "*" (multiplication) has +higher precedence than "+" (addition).

+ +

There are many ways to handle this, but an elegant and efficient way is to +use Operator-Precedence +Parsing. This parsing technique uses the precedence of binary operators to +guide recursion. To start with, we need a table of precedences:

+ +
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+    
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+int main() {
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+  ...
+}
+
+
+ +

For the basic form of Kaleidoscope, we will only support 4 binary operators +(this can obviously be extended by you, our brave and intrepid reader). The +GetTokPrecedence function returns the precedence for the current token, +or -1 if the token is not a binary operator. Having a map makes it easy to add +new operators and makes it clear that the algorithm doesn't depend on the +specific operators involved, but it would be easy enough to eliminate the map +and do the comparisons in the GetTokPrecedence function. (Or just use +a fixed-size array).

+ +

With the helper above defined, we can now start parsing binary expressions. +The basic idea of operator precedence parsing is to break down an expression +with potentially ambiguous binary operators into pieces. Consider ,for example, +the expression "a+b+(c+d)*e*f+g". Operator precedence parsing considers this +as a stream of primary expressions separated by binary operators. As such, +it will first parse the leading primary expression "a", then it will see the +pairs [+, b] [+, (c+d)] [*, e] [*, f] and [+, g]. Note that because parentheses +are primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. +

+ +

+To start, an expression is a primary expression potentially followed by a +sequence of [binop,primaryexpr] pairs:

+ +
+
+/// expression
+///   ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParsePrimary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+
+ +

ParseBinOpRHS is the function that parses the sequence of pairs for +us. It takes a precedence and a pointer to an expression for the part that has been +parsed so far. Note that "x" is a perfectly valid expression: As such, "binoprhs" is +allowed to be empty, in which case it returns the expression that is passed into +it. In our example above, the code passes the expression for "a" into +ParseBinOpRHS and the current token is "+".

+ +

The precedence value passed into ParseBinOpRHS indicates the +minimal operator precedence that the function is allowed to eat. For +example, if the current pair stream is [+, x] and ParseBinOpRHS is +passed in a precedence of 40, it will not consume any tokens (because the +precedence of '+' is only 20). With this in mind, ParseBinOpRHS starts +with:

+ +
+
+/// binoprhs
+///   ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+
+
+ +

This code gets the precedence of the current token and checks to see if if is +too low. Because we defined invalid tokens to have a precedence of -1, this +check implicitly knows that the pair-stream ends when the token stream runs out +of binary operators. If this check succeeds, we know that the token is a binary +operator and that it will be included in this expression:

+ +
+
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the primary expression after the binary operator.
+    ExprAST *RHS = ParsePrimary();
+    if (!RHS) return 0;
+
+
+ +

As such, this code eats (and remembers) the binary operator and then parses +the primary expression that follows. This builds up the whole pair, the first of +which is [+, b] for the running example.

+ +

Now that we parsed the left-hand side of an expression and one pair of the +RHS sequence, we have to decide which way the expression associates. In +particular, we could have "(a+b) binop unparsed" or "a + (b binop unparsed)". +To determine this, we look ahead at "binop" to determine its precedence and +compare it to BinOp's precedence (which is '+' in this case):

+ +
+
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+
+
+ +

If the precedence of the binop to the right of "RHS" is lower or equal to the +precedence of our current operator, then we know that the parentheses associate +as "(a+b) binop ...". In our example, the current operator is "+" and the next +operator is "+", we know that they have the same precedence. In this case we'll +create the AST node for "a+b", and then continue parsing:

+ +
+
+      ... if body omitted ...
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }  // loop around to the top of the while loop.
+}
+
+
+ +

In our example above, this will turn "a+b+" into "(a+b)" and execute the next +iteration of the loop, with "+" as the current token. The code above will eat, +remember, and parse "(c+d)" as the primary expression, which makes the +current pair equal to [+, (c+d)]. It will then evaluate the 'if' conditional above with +"*" as the binop to the right of the primary. In this case, the precedence of "*" is +higher than the precedence of "+" so the if condition will be entered.

+ +

The critical question left here is "how can the if condition parse the right +hand side in full"? In particular, to build the AST correctly for our example, +it needs to get all of "(c+d)*e*f" as the RHS expression variable. The code to +do this is surprisingly simple (code from the above two blocks duplicated for +context):

+ +
+
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }  // loop around to the top of the while loop.
+}
+
+
+ +

At this point, we know that the binary operator to the RHS of our primary +has higher precedence than the binop we are currently parsing. As such, we know +that any sequence of pairs whose operators are all higher precedence than "+" +should be parsed together and returned as "RHS". To do this, we recursively +invoke the ParseBinOpRHS function specifying "TokPrec+1" as the minimum +precedence required for it to continue. In our example above, this will cause +it to return the AST node for "(c+d)*e*f" as RHS, which is then set as the RHS +of the '+' expression.

+ +

Finally, on the next iteration of the while loop, the "+g" piece is parsed +and added to the AST. With this little bit of code (14 non-trivial lines), we +correctly handle fully general binary expression parsing in a very elegant way. +This was a whirlwind tour of this code, and it is somewhat subtle. I recommend +running through it with a few tough examples to see how it works. +

+ +

This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, stopping +at the first token that is not part of the expression. Next up we need to +handle function definitions, etc.

+ +
+ + + + + +
+ +

+The next thing missing is handling of function prototypes. In Kaleidoscope, +these are used both for 'extern' function declarations as well as function body +definitions. The code to do this is straight-forward and not very interesting +(once you've survived expressions): +

+ +
+
+/// prototype
+///   ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+  if (CurTok != tok_identifier)
+    return ErrorP("Expected function name in prototype");
+
+  std::string FnName = IdentifierStr;
+  getNextToken();
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  // Read the list of argument names.
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  return new PrototypeAST(FnName, ArgNames);
+}
+
+
+ +

Given this, a function definition is very simple, just a prototype plus +an expression to implement the body:

+ +
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+
+ +

In addition, we support 'extern' to declare functions like 'sin' and 'cos' as +well as to support forward declaration of user functions. These 'extern's are just +prototypes with no body:

+ +
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+
+ +

Finally, we'll also let the user type in arbitrary top-level expressions and +evaluate them on the fly. We will handle this by defining anonymous nullary +(zero argument) functions for them:

+ +
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+
+ +

Now that we have all the pieces, let's build a little driver that will let us +actually execute this code we've built!

+ +
+ + + + + +
+ +

The driver for this simply invokes all of the parsing pieces with a top-level +dispatch loop. There isn't much interesting here, so I'll just include the +top-level loop. See below for full code in the "Top-Level +Parsing" section.

+ +
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+
+ +

The most interesting part of this is that we ignore top-level semicolons. +Why is this, you ask? The basic reason is that if you type "4 + 5" at the +command line, the parser doesn't know whether that is the end of what you will type +or not. For example, on the next line you could type "def foo..." in which case +4+5 is the end of a top-level expression. Alternatively you could type "* 6", +which would continue the expression. Having top-level semicolons allows you to +type "4+5;", and the parser will know you are done.

+ +
+ + + + + +
+ +

With just under 400 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a lexer, +parser, and AST builder. With this done, the executable will validate +Kaleidoscope code and tell us if it is grammatically invalid. For +example, here is a sample interaction:

+ +
+
+$ ./a.out
+ready> def foo(x y) x+foo(y, 4.0);
+Parsed a function definition.
+ready> def foo(x y) x+y y;
+Parsed a function definition.
+Parsed a top-level expr
+ready> def foo(x y) x+y );
+Parsed a function definition.
+Error: unknown token when expecting an expression
+ready> extern sin(a);
+ready> Parsed an extern
+ready> ^D
+$ 
+
+
+ +

There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the next +installment, we will describe how to generate LLVM Intermediate +Representation (IR) from the AST.

+ +
+ + + + + +
+ +

+Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any external +libraries at all for this. (Besides the C and C++ standard libraries, of +course.) To build this, just compile with:

+ +
+
+   # Compile
+   g++ -g -O3 toy.cpp 
+   # Run
+   ./a.out 
+
+
+ +

Here is the code:

+ +
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+#include <map>
+#include <vector>
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+    : Name(name), Args(args) {}
+  
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  }
+}
+
+/// binoprhs
+///   ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the primary expression after the binary operator.
+    ExprAST *RHS = ParsePrimary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParsePrimary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+  if (CurTok != tok_identifier)
+    return ErrorP("Expected function name in prototype");
+
+  std::string FnName = IdentifierStr;
+  getNextToken();
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing
+//===----------------------------------------------------------------------===//
+
+static void HandleDefinition() {
+  if (ParseDefinition()) {
+    fprintf(stderr, "Parsed a function definition.\n");
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (ParseExtern()) {
+    fprintf(stderr, "Parsed an extern\n");
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (ParseTopLevelExpr()) {
+    fprintf(stderr, "Parsed a top-level expr\n");
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  return 0;
+}
+
+
+Next: Implementing Code Generation to LLVM IR +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl3.html b/final/docs/tutorial/LangImpl3.html new file mode 100644 index 00000000000..fe0917227db --- /dev/null +++ b/final/docs/tutorial/LangImpl3.html @@ -0,0 +1,1269 @@ + + + + + Kaleidoscope: Implementing code generation to LLVM IR + + + + + + + +
Kaleidoscope: Code generation to LLVM IR
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 3 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into LLVM IR. +This will teach you a little bit about how LLVM does things, as well as +demonstrate how easy it is to use. It's much more work to build a lexer and +parser than it is to generate LLVM IR code. :) +

+ +

Please note: the code in this chapter and later require LLVM 2.2 or +later. LLVM 2.1 and before will not work with it. Also note that you need +to use a version of this tutorial that matches your LLVM release: If you are +using an official LLVM release, use the version of the documentation included +with your release or on the llvm.org +releases page.

+ +
+ + + + + +
+ +

+In order to generate LLVM IR, we want some simple setup to get started. First +we define virtual code generation (codegen) methods in each AST class:

+ +
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+...
+
+
+ +

The Codegen() method says to emit IR for that AST node along with all the things it +depends on, and they all return an LLVM Value object. +"Value" is the class used to represent a "Static Single +Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect +of SSA values is that their value is computed as the related instruction +executes, and it does not get a new value until (and if) the instruction +re-executes. In other words, there is no way to "change" an SSA value. For +more information, please read up on Static Single +Assignment - the concepts are really quite natural once you grok them.

+ +

Note that instead of adding virtual methods to the ExprAST class hierarchy, +it could also make sense to use a visitor pattern or some +other way to model this. Again, this tutorial won't dwell on good software +engineering practices: for our purposes, adding a virtual method is +simplest.

+ +

The +second thing we want is an "Error" method like we used for the parser, which will +be used to report errors found during code generation (for example, use of an +undeclared parameter):

+ +
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value*> NamedValues;
+
+
+ +

The static variables will be used during code generation. TheModule +is the LLVM construct that contains all of the functions and global variables in +a chunk of code. In many ways, it is the top-level structure that the LLVM IR +uses to contain code.

+ +

The Builder object is a helper object that makes it easy to generate +LLVM instructions. Instances of the IRBuilder +class template keep track of the current place to insert instructions and has +methods to create new instructions.

+ +

The NamedValues map keeps track of which values are defined in the +current scope and what their LLVM representation is. (In other words, it is a +symbol table for the code). In this form of Kaleidoscope, the only things that +can be referenced are function parameters. As such, function parameters will +be in this map when generating code for their function body.

+ +

+With these basics in place, we can start talking about how to generate code for +each expression. Note that this assumes that the Builder has been set +up to generate code into something. For now, we'll assume that this +has already been done, and we'll just use it to emit code. +

+ +
+ + + + + +
+ +

Generating LLVM code for expression nodes is very straightforward: less +than 45 lines of commented code for all four of our expression nodes. First +we'll do numeric literals:

+ +
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+
+ +

In the LLVM IR, numeric constants are represented with the +ConstantFP class, which holds the numeric value in an APFloat +internally (APFloat has the capability of holding floating point +constants of Arbitrary Precision). This code basically just +creates and returns a ConstantFP. Note that in the LLVM IR +that constants are all uniqued together and shared. For this reason, the API +uses the "foo::get(...)" idiom instead of "new foo(..)" or "foo::Create(..)".

+ +
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  return V ? V : ErrorV("Unknown variable name");
+}
+
+
+ +

References to variables are also quite simple using LLVM. In the simple version +of Kaleidoscope, we assume that the variable has already been emitted somewhere +and its value is available. In practice, the only values that can be in the +NamedValues map are function arguments. This +code simply checks to see that the specified name is in the map (if not, an +unknown variable is being referenced) and returns the value for it. In future +chapters, we'll add support for loop induction +variables in the symbol table, and for local variables.

+ +
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: return ErrorV("invalid binary operator");
+  }
+}
+
+
+ +

Binary operators start to get more interesting. The basic idea here is that +we recursively emit code for the left-hand side of the expression, then the +right-hand side, then we compute the result of the binary expression. In this +code, we do a simple switch on the opcode to create the right LLVM instruction. +

+ +

In the example above, the LLVM builder class is starting to show its value. +IRBuilder knows where to insert the newly created instruction, all you have to +do is specify what instruction to create (e.g. with CreateFAdd), which +operands to use (L and R here) and optionally provide a name +for the generated instruction.

+ +

One nice thing about LLVM is that the name is just a hint. For instance, if +the code above emits multiple "addtmp" variables, LLVM will automatically +provide each one with an increasing, unique numeric suffix. Local value names +for instructions are purely optional, but it makes it much easier to read the +IR dumps.

+ +

LLVM instructions are constrained by +strict rules: for example, the Left and Right operators of +an add instruction must have the same +type, and the result type of the add must match the operand types. Because +all values in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul.

+ +

On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value +(a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with +a uitofp instruction. This instruction +converts its input integer into a floating point value by treating the input +as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' +operator would return 0.0 and -1.0, depending on the input value.

+ +
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+
+ +

Code generation for function calls is quite straightforward with LLVM. The +code above initially does a function name lookup in the LLVM Module's symbol +table. Recall that the LLVM Module is the container that holds all of the +functions we are JIT'ing. By giving each function the same name as what the +user specifies, we can use the LLVM symbol table to resolve function names for +us.

+ +

Once we have the function to call, we recursively codegen each argument that +is to be passed in, and create an LLVM call +instruction. Note that LLVM uses the native C calling conventions by +default, allowing these calls to also call into standard library functions like +"sin" and "cos", with no additional effort.

+ +

This wraps up our handling of the four basic expressions that we have so far +in Kaleidoscope. Feel free to go in and add some more. For example, by +browsing the LLVM language reference you'll find +several other interesting instructions that are really easy to plug into our +basic framework.

+ +
+ + + + + +
+ +

Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, lets +talk about code generation for prototypes: they are used both for function +bodies and external function declarations. The code starts with:

+ +
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+
+
+ +

This code packs a lot of power into a few lines. Note first that this +function returns a "Function*" instead of a "Value*". Because a "prototype" +really talks about the external interface for a function (not the value computed +by an expression), it makes sense for it to return the LLVM Function it +corresponds to when codegen'd.

+ +

The call to FunctionType::get creates +the FunctionType that should be used for a given Prototype. Since all +function arguments in Kaleidoscope are of type double, the first line creates +a vector of "N" LLVM double types. It then uses the Functiontype::get +method to create a function type that takes "N" doubles as arguments, returns +one double as a result, and that is not vararg (the false parameter indicates +this). Note that Types in LLVM are uniqued just like Constants are, so you +don't "new" a type, you "get" it.

+ +

The final line above actually creates the function that the prototype will +correspond to. This indicates the type, linkage and name to use, as well as which +module to insert into. "external linkage" +means that the function may be defined outside the current module and/or that it +is callable by functions outside the module. The Name passed in is the name the +user specified: since "TheModule" is specified, this name is registered +in "TheModule"s symbol table, which is used by the function call code +above.

+ +
+
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+
+
+ +

The Module symbol table works just like the Function symbol table when it +comes to name conflicts: if a new function is created with a name that was previously +added to the symbol table, the new function will get implicitly renamed when added to the +Module. The code above exploits this fact to determine if there was a previous +definition of this function.

+ +

In Kaleidoscope, I choose to allow redefinitions of functions in two cases: +first, we want to allow 'extern'ing a function more than once, as long as the +prototypes for the externs match (since all arguments have the same type, we +just have to check that the number of arguments match). Second, we want to +allow 'extern'ing a function and then defining a body for it. This is useful +when defining mutually recursive functions.

+ +

In order to implement this, the code above first checks to see if there is +a collision on the name of the function. If so, it deletes the function we just +created (by calling eraseFromParent) and then calling +getFunction to get the existing function with the specified name. Note +that many APIs in LLVM have "erase" forms and "remove" forms. The "remove" form +unlinks the object from its parent (e.g. a Function from a Module) and returns +it. The "erase" form unlinks the object and then deletes it.

+ +
+
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+
+
+ +

In order to verify the logic above, we first check to see if the pre-existing +function is "empty". In this case, empty means that it has no basic blocks in +it, which means it has no body. If it has no body, it is a forward +declaration. Since we don't allow anything after a full definition of the +function, the code rejects this case. If the previous reference to a function +was an 'extern', we simply verify that the number of arguments for that +definition and this one match up. If not, we emit an error.

+ +
+
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx) {
+    AI->setName(Args[Idx]);
+    
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = AI;
+  }
+  return F;
+}
+
+
+ +

The last bit of code for prototypes loops over all of the arguments in the +function, setting the name of the LLVM Argument objects to match, and registering +the arguments in the NamedValues map for future use by the +VariableExprAST AST node. Once this is set up, it returns the Function +object to the caller. Note that we don't check for conflicting +argument names here (e.g. "extern foo(a b a)"). Doing so would be very +straight-forward with the mechanics we have already used above.

+ +
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+
+
+ +

Code generation for function definitions starts out simply enough: we just +codegen the prototype (Proto) and verify that it is ok. We then clear out the +NamedValues map to make sure that there isn't anything in it from the +last function we compiled. Code generation of the prototype ensures that there +is an LLVM Function object that is ready to go for us.

+ +
+
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+
+
+ +

Now we get to the point where the Builder is set up. The first +line creates a new basic +block (named "entry"), which is inserted into TheFunction. The +second line then tells the builder that new instructions should be inserted into +the end of the new basic block. Basic blocks in LLVM are an important part +of functions that define the Control Flow Graph. +Since we don't have any control flow, our functions will only contain one +block at this point. We'll fix this in Chapter 5 :).

+ +
+
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    return TheFunction;
+  }
+
+
+ +

Once the insertion point is set up, we call the CodeGen() method for +the root expression of the function. If no error happens, this emits code to +compute the expression into the entry block and returns the value that was +computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. +Once the function is built, we call verifyFunction, which +is provided by LLVM. This function does a variety of consistency checks on the +generated code, to determine if our compiler is doing everything right. Using +this is important: it can catch a lot of bugs. Once the function is finished +and validated, we return it.

+ +
+
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+  return 0;
+}
+
+
+ +

The only piece left here is handling of the error case. For simplicity, we +handle this by merely deleting the function we produced with the +eraseFromParent method. This allows the user to redefine a function +that they incorrectly typed in before: if we didn't delete it, it would live in +the symbol table, with a body, preventing future redefinition.

+ +

This code does have a bug, though. Since the PrototypeAST::Codegen +can return a previously defined forward declaration, our code can actually delete +a forward declaration. There are a number of ways to fix this bug, see what you +can come up with! Here is a testcase:

+ +
+
+extern foo(a b);     # ok, defines foo.
+def foo(a b) c;      # error, 'c' is invalid.
+def bar() foo(1, 2); # error, unknown function "foo"
+
+
+ +
+ + + + + +
+ +

+For now, code generation to LLVM doesn't really get us much, except that we can +look at the pretty IR calls. The sample code inserts calls to Codegen into the +"HandleDefinition", "HandleExtern" etc functions, and then +dumps out the LLVM IR. This gives a nice way to look at the LLVM IR for simple +functions. For example: +

+ +
+
+ready> 4+5;
+Read top-level expression:
+define double @""() {
+entry:
+        ret double 9.000000e+00
+}
+
+
+ +

Note how the parser turns the top-level expression into anonymous functions +for us. This will be handy when we add JIT +support in the next chapter. Also note that the code is very literally +transcribed, no optimizations are being performed except simple constant +folding done by IRBuilder. We will +add optimizations explicitly in +the next chapter.

+ +
+
+ready> def foo(a b) a*a + 2*a*b + b*b;
+Read function definition:
+define double @foo(double %a, double %b) {
+entry:
+        %multmp = fmul double %a, %a
+        %multmp1 = fmul double 2.000000e+00, %a
+        %multmp2 = fmul double %multmp1, %b
+        %addtmp = fadd double %multmp, %multmp2
+        %multmp3 = fmul double %b, %b
+        %addtmp4 = fadd double %addtmp, %multmp3
+        ret double %addtmp4
+}
+
+
+ +

This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions.

+ +
+
+ready> def bar(a) foo(a, 4.0) + bar(31337);
+Read function definition:
+define double @bar(double %a) {
+entry:
+        %calltmp = call double @foo(double %a, double 4.000000e+00)
+        %calltmp1 = call double @bar(double 3.133700e+04)
+        %addtmp = fadd double %calltmp, %calltmp1
+        ret double %addtmp
+}
+
+
+ +

This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional control +flow to actually make recursion useful :).

+ +
+
+ready> extern cos(x);
+Read extern: 
+declare double @cos(double)
+
+ready> cos(1.234);
+Read top-level expression:
+define double @""() {
+entry:
+        %calltmp = call double @cos(double 1.234000e+00)
+        ret double %calltmp
+}
+
+
+ +

This shows an extern for the libm "cos" function, and a call to it.

+ + +
+
+ready> ^D
+; ModuleID = 'my cool jit'
+
+define double @""() {
+entry:
+        %addtmp = fadd double 4.000000e+00, 5.000000e+00
+        ret double %addtmp
+}
+
+define double @foo(double %a, double %b) {
+entry:
+        %multmp = fmul double %a, %a
+        %multmp1 = fmul double 2.000000e+00, %a
+        %multmp2 = fmul double %multmp1, %b
+        %addtmp = fadd double %multmp, %multmp2
+        %multmp3 = fmul double %b, %b
+        %addtmp4 = fadd double %addtmp, %multmp3
+        ret double %addtmp4
+}
+
+define double @bar(double %a) {
+entry:
+        %calltmp = call double @foo(double %a, double 4.000000e+00)
+        %calltmp1 = call double @bar(double 3.133700e+04)
+        %addtmp = fadd double %calltmp, %calltmp1
+        ret double %addtmp
+}
+
+declare double @cos(double)
+
+define double @""() {
+entry:
+        %calltmp = call double @cos(double 1.234000e+00)
+        ret double %calltmp
+}
+
+
+ +

When you quit the current demo, it dumps out the IR for the entire module +generated. Here you can see the big picture with all the functions referencing +each other.

+ +

This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll +describe how to add JIT codegen and optimizer +support to this so we can actually start running code!

+ +
+ + + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +LLVM code generator. Because this uses the LLVM libraries, we need to link +them in. To do this, we use the llvm-config tool to inform +our makefile/command line about which options to use:

+ +
+
+   # Compile
+   g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
+   # Run
+   ./toy
+
+
+ +

Here is the code:

+ +
+
+// To build this:
+// See example below.
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+  virtual Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+  virtual Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+  virtual Value *Codegen();
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+    : Name(name), Args(args) {}
+  
+  Function *Codegen();
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+  Function *Codegen();
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  }
+}
+
+/// binoprhs
+///   ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the primary expression after the binary operator.
+    ExprAST *RHS = ParsePrimary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParsePrimary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+  if (CurTok != tok_identifier)
+    return ErrorP("Expected function name in prototype");
+
+  std::string FnName = IdentifierStr;
+  getNextToken();
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value*> NamedValues;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  return V ? V : ErrorV("Unknown variable name");
+}
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: return ErrorV("invalid binary operator");
+  }
+}
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+  
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+    
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+  
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx) {
+    AI->setName(Args[Idx]);
+    
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = AI;
+  }
+  
+  return F;
+}
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    return TheFunction;
+  }
+  
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+static void HandleDefinition() {
+  if (FunctionAST *F = ParseDefinition()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read function definition:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (PrototypeAST *P = ParseExtern()) {
+    if (Function *F = P->Codegen()) {
+      fprintf(stderr, "Read extern: ");
+      F->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read top-level expression:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  LLVMContext &Context = getGlobalContext();
+
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Make the module, which holds all the code.
+  TheModule = new Module("my cool jit", Context);
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  // Print out all of the generated code.
+  TheModule->dump();
+
+  return 0;
+}
+
+
+Next: Adding JIT and Optimizer Support +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl4.html b/final/docs/tutorial/LangImpl4.html new file mode 100644 index 00000000000..3eb5be4d14b --- /dev/null +++ b/final/docs/tutorial/LangImpl4.html @@ -0,0 +1,1137 @@ + + + + + Kaleidoscope: Adding JIT and Optimizer Support + + + + + + + +
Kaleidoscope: Adding JIT and Optimizer Support
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 4 of the "Implementing a language +with LLVM" tutorial. Chapters 1-3 described the implementation of a simple +language and added support for generating LLVM IR. This chapter describes +two new techniques: adding optimizer support to your language, and adding JIT +compiler support. These additions will demonstrate how to get nice, efficient code +for the Kaleidoscope language.

+ +
+ + + + + +
+ +

+Our demonstration for Chapter 3 is elegant and easy to extend. Unfortunately, +it does not produce wonderful code. The IRBuilder, however, does give us +obvious optimizations when compiling simple code:

+ +
+
+ready> def test(x) 1+2+x;
+Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 3.000000e+00, %x
+        ret double %addtmp
+}
+
+
+ +

This code is not a literal transcription of the AST built by parsing the +input. That would be: + +

+
+ready> def test(x) 1+2+x;
+Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 2.000000e+00, 1.000000e+00
+        %addtmp1 = fadd double %addtmp, %x
+        ret double %addtmp1
+}
+
+
+ +

Constant folding, as seen above, in particular, is a very common and very +important optimization: so much so that many language implementors implement +constant folding support in their AST representation.

+ +

With LLVM, you don't need this support in the AST. Since all calls to build +LLVM IR go through the LLVM IR builder, the builder itself checked to see if +there was a constant folding opportunity when you call it. If so, it just does +the constant fold and return the constant instead of creating an instruction. + +

Well, that was easy :). In practice, we recommend always using +IRBuilder when generating code like this. It has no +"syntactic overhead" for its use (you don't have to uglify your compiler with +constant checks everywhere) and it can dramatically reduce the amount of +LLVM IR that is generated in some cases (particular for languages with a macro +preprocessor or that use a lot of constants).

+ +

On the other hand, the IRBuilder is limited by the fact +that it does all of its analysis inline with the code as it is built. If you +take a slightly more complex example:

+ +
+
+ready> def test(x) (1+2+x)*(x+(1+2));
+ready> Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 3.000000e+00, %x
+        %addtmp1 = fadd double %x, 3.000000e+00
+        %multmp = fmul double %addtmp, %addtmp1
+        ret double %multmp
+}
+
+
+ +

In this case, the LHS and RHS of the multiplication are the same value. We'd +really like to see this generate "tmp = x+3; result = tmp*tmp;" instead +of computing "x+3" twice.

+ +

Unfortunately, no amount of local analysis will be able to detect and correct +this. This requires two transformations: reassociation of expressions (to +make the add's lexically identical) and Common Subexpression Elimination (CSE) +to delete the redundant add instruction. Fortunately, LLVM provides a broad +range of optimizations that you can use, in the form of "passes".

+ +
+ + + + + +
+ +

LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't hold +to the mistaken notion that one set of optimizations is right for all languages +and for all situations. LLVM allows a compiler implementor to make complete +decisions about what optimizations to use, in which order, and in what +situation.

+ +

As a concrete example, LLVM supports both "whole module" passes, which look +across as large of body of code as they can (often a whole file, but if run +at link time, this can be a substantial portion of the whole program). It also +supports and includes "per-function" passes which just operate on a single +function at a time, without looking at other functions. For more information +on passes and how they are run, see the How +to Write a Pass document and the List of LLVM +Passes.

+ +

For Kaleidoscope, we are currently generating functions on the fly, one at +a time, as the user types them in. We aren't shooting for the ultimate +optimization experience in this setting, but we also want to catch the easy and +quick stuff where possible. As such, we will choose to run a few per-function +optimizations as the user types the function in. If we wanted to make a "static +Kaleidoscope compiler", we would use exactly the code we have now, except that +we would defer running the optimizer until the entire file has been parsed.

+ +

In order to get per-function optimizations going, we need to set up a +FunctionPassManager to hold and +organize the LLVM optimizations that we want to run. Once we have that, we can +add a set of optimizations to run. The code looks like this:

+ +
+
+  FunctionPassManager OurFPM(TheModule);
+
+  // Set up the optimizer pipeline.  Start with registering info about how the
+  // target lays out data structures.
+  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+  // Provide basic AliasAnalysis support for GVN.
+  OurFPM.add(createBasicAliasAnalysisPass());
+  // Do simple "peephole" optimizations and bit-twiddling optzns.
+  OurFPM.add(createInstructionCombiningPass());
+  // Reassociate expressions.
+  OurFPM.add(createReassociatePass());
+  // Eliminate Common SubExpressions.
+  OurFPM.add(createGVNPass());
+  // Simplify the control flow graph (deleting unreachable blocks, etc).
+  OurFPM.add(createCFGSimplificationPass());
+
+  OurFPM.doInitialization();
+
+  // Set the global so the code gen can use this.
+  TheFPM = &OurFPM;
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+
+ +

This code defines a FunctionPassManager, "OurFPM". It +requires a pointer to the Module to construct itself. Once it is set +up, we use a series of "add" calls to add a bunch of LLVM passes. The first +pass is basically boilerplate, it adds a pass so that later optimizations know +how the data structures in the program are laid out. The +"TheExecutionEngine" variable is related to the JIT, which we will get +to in the next section.

+ +

In this case, we choose to add 4 optimization passes. The passes we chose +here are a pretty standard set of "cleanup" optimizations that are useful for +a wide variety of code. I won't delve into what they do but, believe me, +they are a good starting place :).

+ +

Once the PassManager is set up, we need to make use of it. We do this by +running it after our newly created function is constructed (in +FunctionAST::Codegen), but before it is returned to the client:

+ +
+
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    // Optimize the function.
+    TheFPM->run(*TheFunction);
+    
+    return TheFunction;
+  }
+
+
+ +

As you can see, this is pretty straightforward. The +FunctionPassManager optimizes and updates the LLVM Function* in place, +improving (hopefully) its body. With this in place, we can try our test above +again:

+ +
+
+ready> def test(x) (1+2+x)*(x+(1+2));
+ready> Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double %x, 3.000000e+00
+        %multmp = fmul double %addtmp, %addtmp
+        ret double %multmp
+}
+
+
+ +

As expected, we now get our nicely optimized code, saving a floating point +add instruction from every execution of this function.

+ +

LLVM provides a wide variety of optimizations that can be used in certain +circumstances. Some documentation about the various +passes is available, but it isn't very complete. Another good source of +ideas can come from looking at the passes that llvm-gcc or +llvm-ld run to get started. The "opt" tool allows you to +experiment with passes from the command line, so you can see if they do +anything.

+ +

Now that we have reasonable code coming out of our front-end, lets talk about +executing it!

+ +
+ + + + + +
+ +

Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did above), +you can dump it out in textual or binary forms, you can compile the code to an +assembly file (.s) for some target, or you can JIT compile it. The nice thing +about the LLVM IR representation is that it is the "common currency" between +many different parts of the compiler. +

+ +

In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter function +bodies as they do now, but immediately evaluate the top-level expressions they +type in. For example, if they type in "1 + 2;", we should evaluate and print +out 3. If they define a function, they should be able to call it from the +command line.

+ +

In order to do this, we first declare and initialize the JIT. This is done +by adding a global variable and a call in main:

+ +
+
+static ExecutionEngine *TheExecutionEngine;
+...
+int main() {
+  ..
+  // Create the JIT.  This takes ownership of the module.
+  TheExecutionEngine = EngineBuilder(TheModule).create();
+  ..
+}
+
+
+ +

This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT compiler +for you if one is available for your platform, otherwise it will fall back to +the interpreter.

+ +

Once the ExecutionEngine is created, the JIT is ready to be used. +There are a variety of APIs that are useful, but the simplest one is the +"getPointerToFunction(F)" method. This method JIT compiles the +specified LLVM Function and returns a function pointer to the generated machine +code. In our case, this means that we can change the code that parses a +top-level expression to look like this:

+ +
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      LF->dump();  // Dump the function for exposition purposes.
+    
+      // JIT the function, returning a function pointer.
+      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+      
+      // Cast it to the right type (takes no arguments, returns a double) so we
+      // can call it as a native function.
+      double (*FP)() = (double (*)())(intptr_t)FPtr;
+      fprintf(stderr, "Evaluated to %f\n", FP());
+    }
+
+
+ +

Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. Because the +LLVM JIT compiler matches the native platform ABI, this means that you can just +cast the result pointer to a function pointer of that type and call it directly. +This means, there is no difference between JIT compiled code and native machine +code that is statically linked into your application.

+ +

With just these two changes, lets see how Kaleidoscope works now!

+ +
+
+ready> 4+5;
+define double @""() {
+entry:
+        ret double 9.000000e+00
+}
+
+Evaluated to 9.000000
+
+
+ +

Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we synthesize +for each top-level expression that is typed in. This demonstrates very basic +functionality, but can we do more?

+ +
+
+ready> def testfunc(x y) x + y*2;  
+Read function definition:
+define double @testfunc(double %x, double %y) {
+entry:
+        %multmp = fmul double %y, 2.000000e+00
+        %addtmp = fadd double %multmp, %x
+        ret double %addtmp
+}
+
+ready> testfunc(4, 10);
+define double @""() {
+entry:
+        %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
+        ret double %calltmp
+}
+
+Evaluated to 24.000000
+
+
+ +

This illustrates that we can now call user code, but there is something a bit +subtle going on here. Note that we only invoke the JIT on the anonymous +functions that call testfunc, but we never invoked it +on testfunc itself. What actually happened here is that the JIT +scanned for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning +from getPointerToFunction().

+ +

The JIT provides a number of other more advanced interfaces for things like +freeing allocated machine code, rejit'ing functions to update them, etc. +However, even with this simple code, we get some surprisingly powerful +capabilities - check this out (I removed the dump of the anonymous functions, +you should get the idea by now :) :

+ +
+
+ready> extern sin(x);
+Read extern: 
+declare double @sin(double)
+
+ready> extern cos(x);
+Read extern: 
+declare double @cos(double)
+
+ready> sin(1.0);
+Evaluated to 0.841471
+
+ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
+Read function definition:
+define double @foo(double %x) {
+entry:
+        %calltmp = call double @sin(double %x)
+        %multmp = fmul double %calltmp, %calltmp
+        %calltmp2 = call double @cos(double %x)
+        %multmp4 = fmul double %calltmp2, %calltmp2
+        %addtmp = fadd double %multmp, %multmp4
+        ret double %addtmp
+}
+
+ready> foo(4.0);
+Evaluated to 1.000000
+
+
+ +

Whoa, how does the JIT know about sin and cos? The answer is surprisingly +simple: in this +example, the JIT started execution of a function and got to a function call. It +realized that the function was not yet JIT compiled and invoked the standard set +of routines to resolve the function. In this case, there is no body defined +for the function, so the JIT ended up calling "dlsym("sin")" on the +Kaleidoscope process itself. +Since "sin" is defined within the JIT's address space, it simply +patches up calls in the module to call the libm version of sin +directly.

+ +

The LLVM JIT provides a number of interfaces (look in the +ExecutionEngine.h file) for controlling how unknown functions get +resolved. It allows you to establish explicit mappings between IR objects and +addresses (useful for LLVM global variables that you want to map to static +tables, for example), allows you to dynamically decide on the fly based on the +function name, and even allows you to have the JIT compile functions lazily the +first time they're called.

+ +

One interesting application of this is that we can now extend the language +by writing arbitrary C++ code to implement operations. For example, if we add: +

+ +
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+
+ +

Now we can produce simple output to the console by using things like: +"extern putchard(x); putchard(120);", which prints a lowercase 'x' on +the console (120 is the ASCII code for 'x'). Similar code could be used to +implement file I/O, console input, and many other capabilities in +Kaleidoscope.

+ +

This completes the JIT and optimizer chapter of the Kaleidoscope tutorial. At +this point, we can compile a non-Turing-complete programming language, optimize +and JIT compile it in a user-driven way. Next up we'll look into extending the language with control flow constructs, +tackling some interesting LLVM IR issues along the way.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +LLVM JIT and optimizer. To build this example, use: +

+ +
+
+   # Compile
+   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+   # Run
+   ./toy
+
+
+ +

+If you are compiling this on Linux, make sure to add the "-rdynamic" option +as well. This makes sure that the external functions are resolved properly +at runtime.

+ +

Here is the code:

+ +
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+  virtual Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+  virtual Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+  virtual Value *Codegen();
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+    : Name(name), Args(args) {}
+  
+  Function *Codegen();
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+  Function *Codegen();
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  }
+}
+
+/// binoprhs
+///   ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the primary expression after the binary operator.
+    ExprAST *RHS = ParsePrimary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParsePrimary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+  if (CurTok != tok_identifier)
+    return ErrorP("Expected function name in prototype");
+
+  std::string FnName = IdentifierStr;
+  getNextToken();
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value*> NamedValues;
+static FunctionPassManager *TheFPM;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  return V ? V : ErrorV("Unknown variable name");
+}
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: return ErrorV("invalid binary operator");
+  }
+}
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+  
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+    
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+  
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx) {
+    AI->setName(Args[Idx]);
+    
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = AI;
+  }
+  
+  return F;
+}
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    // Optimize the function.
+    TheFPM->run(*TheFunction);
+    
+    return TheFunction;
+  }
+  
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+static ExecutionEngine *TheExecutionEngine;
+
+static void HandleDefinition() {
+  if (FunctionAST *F = ParseDefinition()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read function definition:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (PrototypeAST *P = ParseExtern()) {
+    if (Function *F = P->Codegen()) {
+      fprintf(stderr, "Read extern: ");
+      F->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      // JIT the function, returning a function pointer.
+      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+      
+      // Cast it to the right type (takes no arguments, returns a double) so we
+      // can call it as a native function.
+      double (*FP)() = (double (*)())(intptr_t)FPtr;
+      fprintf(stderr, "Evaluated to %f\n", FP());
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  InitializeNativeTarget();
+  LLVMContext &Context = getGlobalContext();
+
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Make the module, which holds all the code.
+  TheModule = new Module("my cool jit", Context);
+
+  // Create the JIT.  This takes ownership of the module.
+  std::string ErrStr;
+  TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
+  if (!TheExecutionEngine) {
+    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
+    exit(1);
+  }
+
+  FunctionPassManager OurFPM(TheModule);
+
+  // Set up the optimizer pipeline.  Start with registering info about how the
+  // target lays out data structures.
+  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+  // Provide basic AliasAnalysis support for GVN.
+  OurFPM.add(createBasicAliasAnalysisPass());
+  // Do simple "peephole" optimizations and bit-twiddling optzns.
+  OurFPM.add(createInstructionCombiningPass());
+  // Reassociate expressions.
+  OurFPM.add(createReassociatePass());
+  // Eliminate Common SubExpressions.
+  OurFPM.add(createGVNPass());
+  // Simplify the control flow graph (deleting unreachable blocks, etc).
+  OurFPM.add(createCFGSimplificationPass());
+
+  OurFPM.doInitialization();
+
+  // Set the global so the code gen can use this.
+  TheFPM = &OurFPM;
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  TheFPM = 0;
+
+  // Print out all of the generated code.
+  TheModule->dump();
+
+  return 0;
+}
+
+
+ +Next: Extending the language: control flow +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl5-cfg.png b/final/docs/tutorial/LangImpl5-cfg.png new file mode 100644 index 0000000000000000000000000000000000000000..cdba92ff6c5c95b142bd928971bcdd560117028c GIT binary patch literal 38586 zcmZ_0cR1F4_y%l7Rzi}!lI(1ic*)xwtzL5Cq&!eb?hgZ@|#}Wt>+>)Acc3HF;~8 zp``{(@`=` zr-mm=jD{WUvU|yM1HQCg-uLaro5qQ&R$@0Z$%+=zGVa}{_x-KuJx$yo_gdATlVPyn zm|zc``p37w$O$|X4^rh1H(r{W{`!w+CQPeDq-s?%Kk=UQ?y!#T z0R;&aGq*>VR{g@?ZUm_lujo$PalOMBFcO|$zm+%3`a5}FK~u!9WlsMPI(DTS#A}?= z{o((5Rs(`)KL$q>{SrK8;>7fcgE&x&RxFW*j!|NI-9g3{7A1c-*V8yOs!|b6qTeSCW8G&%AKblSlRI3 zO|nW~_dPTcB{lN)sMJ(Oi@eV8Mtg^v@=3w=KNtGkj&@%f(h(?&*?&?^jrS#kDmU+~ zZuuQ*TX(kQ_{gds8S!0)f5(|kANDY+RNGk|E18Ks{D%2NDFbcFvmkEHsEC%cTZFu4 zi~lvd8oMB3_IhcV`4SLN((nF9NRWA#iGYBUKwCrADB$km)eDvkBfoyV_Ge79CRHU- z6*8zW;I)s>>nAzCT@*u6`O?&$PO5_;{(!E1g{|iKmMDs73RiteS9@a3{hFGONX`DF zz0dynTvmBmf{;W~;NlC>O`)^PpL~|<3&(uD(;SbnD+H`MOVQ@qG;as+bzLJ%Oe10K z?6+y&sblY{66z7BQXi0P6JvV29k4plf0xi*ubJ@K=1x7k?m$o@dz)C49aGeodiH(n z3Ynr_texJLoU{|NB6Kkt-226psOs3sgLt*+NbKzF`isuZwBX}MV%FAtqU>(f-QY4y zv|~!6QXZyzOrg@{DKEpX9qxJQ<0meQ?c7@M; zUaT?_624wux3qYLV-|+|jH2smvl_f!Rz0>ZA8!iXdH3*?u#k}XyRPpO-wSdLi?{y$ ztMwcgVT@yG5GkjZ8dBb~5dU;n7QhEVPpTq*&*csnUpVLAx7cHSyotnjZ{!VseR-%vi9}8{6=q z*|%|LU-Uw*3v-FiP_u**yMj5pIpxTCx#mY(&p%xiXr9nY77`J8arLi%Q^-Hp4p(j^ zQ{kMLZ;7~Mo@$CRvQP26+KtvW1_pM{&issVq(tG?jE23lbKQlv?4yfzo}P$_&?GH}Lx<*O zXS>|${&&qf#co=cD_@$wot2fP!96!zYEf?8X!|3|NI*(T>Hs+jBO{}knHihBU$fY0 zUOH`Fx_V2Ily3P;^9~m-9ATj7Okiuktvz_aYhp5zz;;}R7l-6s{>go#1S6xm(=FFd zs`m@ju{*?y2nnsPue*=GXfzUN_qNRMZ?@tsKKH{tr@o2!y>P|UwB_KfS;kzdn-ZCCMIR5O?!tz)HHXFyH)jN1|^~=Yn7eCgxjZ~iRB#)5w znouz_JJeI9mfP3S@wIKAa_~yyub1}60(>sKzT-X7Ot|fJ7>Q%Qd1O@FRGpE)#?PO6 zr%s&}NcH#kH!L>dqAL_iP5Ov3>{!XWy;WQ_uxpm%b zxU0*#FGrOwhD36FdfK6Dvh#`rPLGJQuq6&6GZT~6LqiD(2|sJrUj+NtiQB|%1IdMY z1X5qA-=O&-yNnP|>AtSU<)w%>-Apw6+LCXUd(OGe^uQFo3E?Os`DHIPia&%+`BaZ{Qqr!`0oh%5NU|xU*f*i$7dtVsg@FWBwd#r)uBSdsZBb zgQW=zgpZcGXFT4t%XY>!SGL^BI5gd`)4G;(+KYASobzTw*M$hlb(4~gEaF-d7Q?p8 z@^eMP+0}YFZPj(i&W$i7 z{#b5pI<<59qin1PZcfQ+8o1V&^QDC6U*pwI<`ona)IEJ#rSa-a`B?@{S`zog$cmOd z!x?$}jn?J;&R(qPJu?&WE{1+o!DfX6E#LD`oH(&jMoW9Lcwo*sGY!8ybmQ8xpM17? zskDqtX#dg3jfC@Ue+$j!Z1<|BmIogEX?d1`v{F|#q3uT>tLfe5ML`A%F1f#g&nYRF zPMv#^u;OF!GGEF^F`0MBb)!HxOF&TYXzZWa{6rrgpPwt^J7br}H)i|QIcab4%GoxD z$@zZW8sGWH(I)2N;(`NPAG#CL;J;*CYEF8=`#BL|rBKPhT*%J9U(wOgH*Zo!`+9U) zP_@yLR9^fjo#rTW@dLyD{r$-9JFUUvw9c8^3*}8Okc2owHoxR2Dm}_tA@~^dXMHY$ zlu|%I;OElEBXlu2mG$-YKfb*c6%smq`gCyrv}c#B^n*A02`BQ+YFtx`i|6o5Vj`kH zzg9%kdvdR5UdBJXSl{;c#z#kc`TM`=?#__$yqB7KKzE=sk)!F-LYi7`j!V$b#rHV7 z$^4Conz1%s5UN9^j|a`8`l&@4jrbbXJ;j=v2Tw>Ml7>w+TQy8 zgOrq%F6QO%@Niojv9lT{?c!)&IHpGg?|qvR*kgHBygPr4Afh4kj=l z+WGaA{_%-r_x1M<)W9%3IcOSz6fU)#K*^veflI~S*JpK z-AI76a;l5R1r`Wf!A>;Y^@vnv=O;HIGb0PDC zBiFjkjE$d${QFZ>#9wJ@X>H9;OIzX4o&5gEg=-CrPWk!yJp42QsRBGa#71JizP_<} z)#ev9H6!cm<;dN5wGA20p*Fg^-y~1UYSs}+r;Jq7H~6u(HX$Z3aWvW{C!U+2PbWu7 z>^oArrU8TQfS#TnwzzNr$RoPl-n3cOn=wX1KAR?+s?fNEtB|oxEQfhvBZ#UEfu$1I z>CI|-plFrag~<62j+tRG!_mL|aU)nITWtbDicas$f>WnXVXbrJnB$}J_<4AEZs~`0 zs(Ka~3Cx}=HljGotP>S7;94Wp^U485dykHN;}rP{9f_&|L*1gAqV&G$*}A&Az#m^# z;}jGW-rSWND6={~`z-TvN^;g;_2+4x?@Z7=bEfI?%I9C>p&ZQ26gR{2 z_~TE|v$L1=JI{MW7zzCQ@m86ho*wyEwY<8f22i1S0wMf!sdn6dez5rQ<3*I!W}$5a zJPydu*?t}o5fAJF7Z;bew>L_BS63ImsOWw9ORg)Q8xIPbzpQc(4E+5(@CT|g7hMbu zt8CxXix#u2nFV_zOdErwRB4NgiwOw{$Af>w=jL*q9(&elz)Poyo67Qhp{=8%qorkv zbXH!z@;XDJ{;RO5kCDJRC#M4BtvlX8!ev$s(sr%a%~vwBvTPdsKb&YqsiSAM!<+s>Xn8=I%WZJ?#ql_}+RBA$6>ZZ6~Q?u+%% zA;4G9v1h5-+1aV7sdw%$(bMzLk`KCW+&+310XO&UTc@sVYG&p`0+SD|18SY zKWw1}cT!^FTa+^*Vq#>j<5;){4;~yol@^RpMlhoFQIDd^khqZ0)U@-d-WLas2~d%h zRVbxfjEYzryPUhs_o>c1-}l>_{{DWO(0@{GV!64w*!!~urwQ$JONK-&p1vL$y0kXk z?OGG`_MReD8-MDnzP`Te*Gb68$UHqgIXLd4g8iBwqHGh(*84Uw(O2VUl38F!`NX`` zy3(FBVd{SHnzoS0cIjo?dz%+Hz z#nm+kK}xodeSPsgz4PnWuOB~tEF>kB%Bw9Q@g)6fZFRMzjLfgTTy=h#4=YVOpG!^Tdr64uEnlDvOitSK@Z>A+ zYz+(y{FrFDcH!;4F;w}1!ZS!Lb6>yic}EgW#T3=Dt`xNHjJ49_PO=mkuX2n#kslKs z?L1PJtD|HxqUd9_ z3;p7y%Bm`RGwH*JHA{xf&CKu>SFT*SaN*nZ^fWg6JnIwYFMeM<1dVqpLA1ioVt^iHjGZ=?AZawp0vp8*LjZ|xu!~AVy7h~E!`n@ zy41MsQZnzwix&+JmyA8+fA!(RhtW|cpPxB#($dltkwlW-RBg_gjB)K)9i}K3$;|Yi z^gLA6$NKzw_m!ySdeH{p^AizRukS10x4VPvpRGr>(DE{dKK|y-z9X*xL|pf;ydtQU zFS}t+`qI8q=V5GIoW(Og7xZN~6Nl-vjg1)t-dBYFC94ovPDx8E7+G)>Kg54oHsOM! zW6M5UlCDc#iVoK}$sZc-?H3!0Z5I0 z3_Zv^t0s`j%*_1MZG@&bJW7(#K_**I#&1?%tLBUW!-)2ykp(365^Z{9351D+v@|0* z$(uKCqUXHW7)(?1iDerA5;V9~|EUl7;VfcT0Letsd&1}PT}KoXuI-_26+6w(fF|Pd z=fDg9lNhDM#0cDYjAw@SQ$(WJ;8gRIsPJ1dE1mP#eiW3rJj~t=hP{LimW7O z5k(QbCG9Q_1{m7Mp=4=j=(DxyeaC!mZtlQ=13`^S5)uRb{iw4E0q3*`9m?&^o}Rg{ zgp8=It?gR#th$=PdB4XOS&<~In>*BAvR*Z|*zNt+YPnu7qxZAOcsvK}!g&N}*&9JH zyvH$_H^zyR)H5fhrhIp{{~`Am8wor# zJVZ}_?GHVL+|@tTIuE(Y)k=-eG7Obk$OsCS0Fb)Wm}eGnC4S++UidG*7ydG&Pg-`cc$Uk{me~b0(4l>(^<0^scXe}PVP?)uPB!ekoU17s8|)rQD`Nee zsU*|HymYv=HLtQ{eV(8vNJr-t0_6q`8--H2IR`Oikde_Kn6Gf=GRykptgOE+WE@C7 zRt^5b;^Ky-#)!FJKue%@lDi$Ot*t#gJaFNFO$G)AW6v(J$omzQln81X{Qb2eBPKT5 zaCrsU9V8HVf{>*THQ3nHw6uueV>n0H3uKeA#w!QE<^rjvrys0fM~3;_c;(vnp3ctB zk=@t97$2b?Mg|7=Pj$x*A8sETYjhha!zsfBf2go)LjdAZTwPr15p0wPMK*u`?w4!? zY|YEd!^+%O0%n;TxcKqu(x>_#QPeD^X}zyr$@|Ury-F3tRV8W7PETtjJE&*cg1!m< zy>{o$oyEmPvnNjBCWL&+`T0|6!WPNN$;;zS_tVqS;O(Jd9mO6{vq%HdvdVfjkB^70 z&-Npi7Zo|ryh;Vv6h02(2nG7sv17d2?8p6I4-Wbv-9LQz5Ny>8-)|`6O|`YZ+T#wI zlv`i@KB?*J`(vNdCc)72Wp5*X2EbV0*Lx`UPoDh9K7RSB=lEwF)+<;3uCA^ENG7r? zet7kY;<@~8+{VYB6G+9vF&lbTw|gRV6?58r_=Y;GnX(rsqCJ|(+mt2Vo*rwZu` z^i@nu43aHg{Iet^hez2AJn2C{YZ?HWQni_ynldplamL3KxMb^{q}6b7DUONR3&z!s z@|267UP5DIqgpO)Tzk%9dU`sJoSN?hw|4T(%uGi|ht~&Ig$^+)qbSa3zznc^;c7RW zYnQzl$Vs%cI>o477xa0>pZL+q5xNWZE`F$1Ri{#wqjey@XmD&kC7fy=TLRh!Cz zqM{cZ4yaJ|UFsvAI9zV*qyAabuL#Yd4D%h2{#(bWuH|`g))jtU8TP)(L3;t` z7@!gOm#8L4_-xftP8k^!UOF6BE|1SXABMfcd`LnhbBHB7`i|P}s9iSGs}tQkBu1rf zpI|B^jeQ%oXYJ&gy!lszfySEjacq8WWUX~0aR6b^ep9h&U&g^Samv)azQt8lbOP?4 zo{3HjeZ8O45XrHJV)QX6IW9DJT}HQN|x?zdpE|&lfF(U_3r`RYU76X zOJ-hzHg4UYF4QfR=2u=yJl`9~X^eArZ^0^X|H-1`Ikn;Ck`?wfFDM^ZIDNDk+}Q|; zAj?VhQCzG^)@+Ll>fs=5Sw+{jkDB^GT>Au<%cer``%c%-SFIG!c8;ab8@`;e`7+j_ z_N2(+huXqSP$^;a#v$T>vQoMPtSgYnmk1?T}${VHS zwunDfT|*!9Ts0d%AAJ94okW&wLpsCa!>Nrx;svUWV&kRS;k=-pFa5W7`=Oqy3Z86U zZDL~L7!AW4OHrk-Ecfi=Imx0sV7pZ&eUACwlYO1uvLWRD$q|A-hWMx~E*Ky8J4kSd zzOJ_U*9|+SHJ|52Tds!(KROT|(WR6PvdICYYi(eK2|xN+9k`s>9a`{v)mdg zL$?e(Mf}-hX&Jc-gakJa4_D)XKa9EqJ6k^z(J7$^ogk?@m}*mcJxcOW$*UkD?*qp# zFE94xwju4+HHgnQ$KA6tL*2$Zp8_|4gx3G?-`#AbdryBK?!)>$9zuI3bo6Myvn1`; z6DHx0i83>8krGIEJQ2#mX-`ePH1p~}H5*ZwPa`Vi#g3bY0IWg{-n?jTR!MWbBtM1@ z>AKpN!Q!)*7e@)bLn~NFF5Z~%pi$kyv3>TY*VW|75Q^w6S<2R56UX?Uo-Ne7RZ9Lq zv)YB^Dw~tI0AZ?)XNp}CKj=gq9Uyx^)w1DlQd!*>c`S>&RlQgb#3t1X|`$+>Vs3f41La$k&%%&jn!(gc}4=MMgozyO!QA3iV9~V zw{7tD@(TEteYqm^$ee=>-vy4-#HGerX=!`x+^nAYh5s%v5Sy1H+@*c(wu4gHQbZPSlf6%_G0rx-J+Di21cO)wbP;q;Edsk+)Y*C_mX=hi{`Vq;)$WJL_j; zK2z4nvpZMC>(`2nV`XK{N%qXsG#$!o)%|(nRk%g-g}B&QcXxNrygDbR=CtZ>xxe#< zycHkoOn!VG=_=O?tc{{Bx(ONFEC0N&9_%wgw1LJ@MU z)bK4eGv9sUIap*MapBF)#KfkcjYlyt+71rW=tnq|g6llTm27Orp$CiUfvqE^qUp(6XezEbn$=sfW2ISGC=G|QocAw=o7MX`md@Pb&B)9Q0zRRnj051* zIC=7k5DO!tv9JW^+l@>jbDj}mDi&#Xpw*gfnenTGeF~TI)Z80 zw=WSOm-C8QZ*fG^={HIhxA(C~FJdXt4T7c!Y77BJLkZ^N<1;V)iOv)YL%nzJ7pDSW zZ|}L0at`felxENzxHI6%d&e(()I9dz_@mAgRqypBA};O}b`VE97(B!w2`5`7Cr{6v zUK!{((1y6YO$D3EU-s$B+<(GBuX6c4#lwE+aZ*qn@; z=}G61^Lc>u0zHsF^b;D>rygVTi;Jg|r)$SUjyrVS+UOU?~@PS=j|&Fk`&y3apvLwc>#3q${ss% zTVR*x(svx z4!(J_jBv#E;A@wcm-$0k74`<20V?BSTTDBKpSBQ}B-df%1Lxj7L~lb+@_p+!Ocvi{ z`tu?pB5vQl4I<5>O4&n>C>*HJtM&R`P>jmkn>?zt0Lt7+MNUpC?C}Z1T^p;92(E$$ zadQ)7jBAO#VUj&|Wa2@Gx<5x*IjvO-OWHzw)|12@m2hIUH+r&DM2`$4B-ngnI1lV~ zKRs0Sfy?)}L&8)DL#sGoyS=?Vh-nxUa*Rvt1k@_=HM&{S_LX(0O-Mid57}g?A4xTR z<^uuA;gUbASr$VelzdB>M!GvKJ)K9L*SaQ=DUc;clj+ExeH6cce)LpSR74X`6X;mS z5fm>BfSpuZEA!x6kr~bN<)x*oAe1914<;~6%_F=4Inl2C&wUwRa8yaTk;gCVn*$(- z04E*StTAP*Nasms&Ajdx-*%OR`px?rTQED=GYuD>;fPeLgocB{hAgtV8F1#zTi1*^ zknJ}uN%&J@wRq8&(#n*u1qgt7wYTSX_jmD8e&vjZ?*Vo5q z4>hyV(wEv3(+cw^7G9N;`H*cgz8e@o^n#gaYi;#nO}u&YxzCIadN*X=2%1>|e*UmU zCva+L?SKJ3gO1kGiA_m4iz?66Luzu*RqM?QC_LZ=-9J9nEj9`Y3X+$X2ftj7YeM%6 ziOA;aMrviHHciehHKcJg z;nau3H3U-s{P`0R6awKJ+cW1UkM=&9x7Pi=p}D#1`SU5aZcWV1x!BwL%nu$dHEsZ4 zK<^2`qqDnv4h%E@!!hu__mh)}xLm-TfBpK^a__RHZj>Y$N*%W3R<{Gb7fnzVF45N) zfTpMI#y$WuB#jq=Kb&U2?B_W_9@z>$AT2eOnpIYekMAq^%@9=PPh(@)zPNW^!cTFD zi?4z2diwM!noPi^n{jc(ZEon{b5yVK$HFUc`$T?VqpY6qinh)pX>LA3Ps@@fBJ8x8JB3zt?JWjC6oLT z(M~2&RVi0{!{0Y!b0v;*OS9B?M2KwY(94UQ3Q=}-95YUP++8PrEYx@rj2CCjP|w&* z6*OKu(tk`pCW?ea8VQipa7 zgr%BHx=7siNW;pHW`Dj}XIi`w4}KQOaN1D*Tgs7J8)tI$pVu(Pv`?D%s9xlz&MDF9Cr-YTPg}$XMgPCljj})H< zuXeH!eVBQt^Yv8EbWlYj$5RU_|4RW|p_~byB;)^-GInkDP|vuuIJ;Qxqk6Xs-|rkd zACNXONU-0Zs?Fx?!mv%5EuS}@%-DE+-0D5<(?S?)sEdK{^3xXfx{em>T2 z6hQIc)|QX2FW99Z=+-EspIL`Z34WJVSMTauFb#nfD=RA#>T$YoK^fBYTjd>h?W~^` zVwwQ(%U?Y;2-iGVRK#!L_p0uK@)%(z` z2vQ%>9sKN8Q%R*@SANLq*&-LhPVZd((I*$qAp1D*(ovu>7{q3M{(MhnUP`1+gtBYh z#K2%bBjcU|#SrIA(f~6ofo7$5qM6Fx4;6cO?@fLmz6GKzJNw__`zJtIq?C-32p~xY zg%LL&74PRY*5CU5#N0nbfOu6}aUEAP1Tb-Nx zWmiQ!x$xb265Dc?h;C%&(@U7Yr5R2mwC3~7vo({3$_5gW zDGGRY?)Q&xrMy$;&+b_db#$Boygx>D3cB9w*Dtr1CMWvWTY7?Y8HmDn>n>P$22IEy zvI5cfP2wq|MXS8mMdJ1`5A6zn;Lst6hZ>pOK))=KO-Vvr33p#%(e7`Qd8* zGO{ewNHseM=-_Y={pIAGs>Mbh7WvMo6L5b<{IE1|dy+86?|HryZTT+ir>27JD+7Rrc}^xgaCuf)^5b3Dls$)HkmRNL!O>AudioSbC-IY9H+l^?AF+77 z9>r-zo>I1LCdfEFyvS?Tb$Ea|LBPYs^2~pPQO2D+lE*1Y`M;u+fe}2U7*t(SQlggY z9GG>Nc4YU8oto>@(VQuv@5jD?gU+x4Smq?ZV9$5Q!)qc^YE$)==3a3-?!YsX>!mddK8~7HqkYEq6vVJn; z*)S)DElP`5Nl6L*g7T*A$@a#Az4sQRl$fIW=loFncl}4by}emhFNyb&@Gb+S?+Qgg zW&RUV{*3`!lsHok%>_m^=8d5{+kJid(H=AP);~x$B~K)>XJ=++W@q>QmCWSC?R15O zrDA3O#~rv9VNDsP#S0*S?ONvu-BP91Sa?4)ZVBgS2g%xbEF1@#FO>IvrY_52Y%~)C zvOd#VaNCJ4OGzQ?9SbKi23(1vI@Ee!WK^7hO9;@c@yf5S>ZX~Tn{va>DiPM`h#zRD zP*G8BhNY$vP7mBs2o&e94<COx^VfxC4Ed2S|h~Mtr5o++A)YSa__wR8zx$hCyJ;bkC>FDUH z0J4;L;kg6Px6#YT``!4AJ> zJLuy<1w6~w!fVync z8EVSAYWiXBcAS3G6 zf;{5L+}}Yty9N{5vmy|5%+wq&M))V{KU)y#4n!|}k!5FOg!M;xG~{F5fvN8WguhK7 z{8Yf)2Po#(SW$6n#EXS=>-Lo?mAP|90tYNJKrDE9RX}Cnc>0c+phXa(96AzYhyyX( z7mSI@I(vdVITS{&u-KYCEh-`p0j;szBiaNhZhu_+^PCYK0-Z9o+yIMj?!H1;vUfY6Etc?&QO;ck?rdQw>DKuz$<>d_$Erio^4TYy2M8 z&KaNII9Ke-A+YE;Jv4;(Qqy2-^4A9gncqXL8+|8;$T>oPNV$Irvu#9wyQ>}#Jvs+B zaQO&S&e4saC$yk@i>tW~Rok8ev@hlAm2VT1O?aCrwE&3+in41>rlT36(jPW?&L;D} zjAY>nyxp;}vB}AFGBPrQ;x8^)7q*QsYbXQm!>jz44O&2X0^0d`;HUyFo*)G$U0|+NIfOBShsjSmeR>WTE{&f5_LorTtl_U zs%7GT2(;X}VyZ*zN7-d|PqK+$VGL5#`@-Q2X12~;AS_h3d(9LT-f*o@ncb6NwrhVF zgg+F&MV;@?X#sN7>2^$+1=x7)wT^feG?b{jUs8D10*>dn{6PZ<(ip6p%B8IWZT9l8 z^jjO8axmO0qQ2t{{}111Ckg>Yjm3?YD}u=IqOxdF+tBvavG~b;HT{dqvOQJ!2$-c9 zG+Ta3m9@qV<$y7j`qF)q?4W4NhDy^YJlG(wgM)*`sM>a|-B8bPaN$9Vu8!~$PIGh= z&(Pw{b1^R&ia36Vfj&k<&AL5gd*8zDUNViAy?nWmhIGITc2~qWbHnF*S zn3f!tU6}La;aA))y2MUSU9&*g-ZkUH!NCD(R`kVYE40NnG3eJ1Po-~zDFUknxRfqx z16K%;3Y?kNu*?}2Lp0|6kI+Pb_n>frYScBrNWe$jEgUp~GOUT_gc0|QOWlZPcOC-gDi z!buzUB5bM-%DSaUZEfwYJIb{NS49`YD+DV)La6c(kA9p|J!Fg-ix(5uZpF-pJP-&Rmh_n?VmnfjIjjR^T)NU-j(rinXe03yh>7qq5V}JD(`9*ANXF0;ogX!tec>!w6v=fo>TP6!ZrT z=+5tN_hB^|$FCueHK0sD2Kc)^CjkWRTHPu38ZFg6R@r9JGKIRL!|CF?14J0o@c#E_ z1N^15lvE^Vfa&>5@>Y=PQTxbABz56XCO?zwVvaLOLX@rdYw^7VPP@J&e=LM2+p&BX zlnnBteXcbqi#V*clC@&98$qyFfBl-4k>TR#NZMvahN&T8VT`cM!e4fSEG1LXgW3sy;GUBRKxMLv`lS4a9{u+NL~@lVgj@}|8;AN&4Q zts6fPoRINb3w2@m!1LPpqGo8kl~L&j(;-$DLxwK4g9Nc{rN$v`7V#ldtW!+CUWK-V zfXKmkCbtYJ zb%R}qtnnl*iFUHB2iX9jrN%$~8;XRF$c}pTC6Kaq!q^B7i`rD*ZnTr4;T}tJc1&rk zWa}d$;rdTIO;2J>2#g5cygo4$CZPTBT~vU8X0T!?ON(5U@=H5LwM#MkF1w|T-{MoR6zXZcNB&sgBfYhw-QPsT ztyl}5oVfpA3Ai+K-QXgdiXgELYc=>-jPJny0vG`EB7yf=h7ChPGV0K(&zIeX#o$XS z88SZQ`||2NyF2ih0I}-cSF$P`7_vAt+l=83fLjOJ`5aaIymrhOGnv(w6`!cB(fh4eb8(&9Yi};1^ocn6+%=# z>}3Dn8IZjX`EMTL;}UaU7qv*0C4VEy3~E4?7Uh{U8h8>DX0XB;(`n7$2+6nqVsp#+ z(J`H$?GygT1jt+?w_Eoasb>~I2;u78pIoZX#h{6#Cnql-u}XSa<)T4K{iUc@GAbs0 zL&Lm&XS8`n*1UA_ha~n)HXG>n{rHr*u<-|E0~skPqH1^1F?|B&eh6bU7@*=+e88`h z-@mm!a0ZGfz~NObE%Jn^Pv++=O8QM;cY|#T3M)RJ;6D7dFq*=_@$^@d__YA3Fe5`u zX)rK=K9qvZJ6o^NNMIK{z&v-$)s0O@r281v`TwR(D2W}Au9_~%XP?N2ogH}ffo#D3 z#w1o1Wq4DPl6KSN)>d#buUq!V^3&l$Jw7F{sr@QY507rfOabSI+0RbH$Mpy~RNJxatsvI!r!x_OnLpi;lw#%Efke`C72~!V!f@=feFZBleG&S45 z-4BJ*GzK>=rZ}>>Y01eW2xd(3`!S#vZ42TZPAKlA+v({R=H?MXy$_EpCzI2OCs*f2 zF=zs4nSph;$IOs*dFa}7%(ZL8Iv1~>d(Wpbrk+hR2+u4sKH3%mMn;Po^Y|%QhffhC zma7(}#^;&%Qgw2Jk;+X?`BQb^11&0II{8&CFztci(K|E~^f+2Dxxq3@O!LGh zB<%S|)TPHsTkSToj6w<&_4CJ%D_KWRs}x}3M_5DzRW%yyhNL8%weKP0LL%RLjMzQ3 z@!{jgr-c}IZCGzkCiB9a?rvwtmEL2Prg`D6nsVD@Qg${Q9o?>oQ*W6tC96vN-_T7= zyM2IlsqwWp^p~gd?z>(bt22u)Ka`gi+_ki_-q@K)s zj0#hlP|eX2!ERXj^r@bf7T_xE)i%N3HNCvNFd+n@?Az;%HXlQ^R+}h0Xm5DgsY**o zSX9`m;w|9cfj7VPW|tiq|m>~})TGW-HKSLi!;4H^(^b8>RPZSJyqfJh47lP|HbVg4A+ zx(h1;EDqqqNk~b#lB^2{4j(y^uW$;gUR6yEX&^W+f zF1SYkUCzFPmD11WUw6QyT5et=ATQ6{I%ty-U`>cbjHJ=#t-!<6*473yDjV3f9O`f? zLkvwYGJc(($3*faaC4q7et*SZWAj*m4B>x@Js>E5dHJS}`jS18_66C}*XFQqPUzFvas zLWN&y{sds8Ubei%y>sOM=LJB#r#UV>Y{sYim|4^3syr6hH@d4f!m5DN&A=e(^6tTx zwi`IYSK6Ye(I-|`R%%VC%!i+ z!q3!lE8uYj^?FC?>a)1Gp3rXo?*f+l_Pm8T90v!(DhT7(caHU-l}A#=3=9Uo;VX5* za4(7?q=l|7;G6(NGtx0@XHQR$T}dC@R8{DG3Qu@12YcVe@JjDV>3)cXvqKf!x$kLR=i>|4P~8BedkO?cbPi5UxD(OI4FQD16T8ao&CCmUAoB9%OIF38 z+m7!MxR`RGeTl2=!_pvorSKkNV5kNWf%k#yyO+n0xozwpE@5sXh(8dah68~)hb>G4 zLD8X*Ai3k?=eIs$6WS|w+S%C|DgY=?Tbe$}?BwKkjaM#b7KEZ|qS^WI@gs<~zL60V zA;!Xo593+oFiH{`6;)>TWOrJ6eQixZM1*GVUTrNc9QsulZoYqa87X5^rA42PUXUnU zrPMeS3KRYbk2~a);;%Jfs-6P{yQi9efyC7No>ou^m1Y zm~YSy=4r;k!b8u%u)f@|vfKPh>e|$KwY0ZC#5sihO38omPF9vhZ|+O);E85{^{eh9(iIV%SlB=1?*AiV>;onMpuXQL52KBLle^fmEQC& zqp-P=nOV#Wn9*(>TXc3MCq)!KFS1}x+QpxW5^xit^%ue5KLy3JE5AhC&4u~-C(1~Q zwvZ91*yPtil`eg(z2Pl~G;{Ni1Zos04vfOVE3z`)gz?;xK#lM%+muN#ju;HXQwu(( zZIBR!V;Bfq;O$+B5eu0AK}-aKTS9*ilXw$my0JcddY~Yhj)8HC~Q3n_vG#;8*n8H+E z$|hV14AeY%lBY+6yc>Ou?VddTdAKJrdgN38skwOq-08LUK%~jtmNNLaxGF7j39dBI z;0R|g&JN{P73 z7`%F=Ban&+g?xWs&bOed>RorYHa~;TLqlcdCK#w{B?&(=_At<%rUg02|y%U7tU*i$8e(@uOP}T=Y8nov?wOcW{sd zNI@b+kKg(6<6q684)5IuKzuSf1|CHuo%p@XEh0?Z*bGXGy-29DVW zK=py3`S{@jY8uQETjN}6MPBO%3EbHk&)u%3s9`nx1QkWze=%AXE_FRrA@RmG3D96P zg;2?m>nRXaFhHMIB zURFxV0LJSews>Mj5zB3>SS;-TYV3bzruOi#ty^Gr%ZO=c;KK(z-Qt1q9zp}1ihYZv zgylLviJx{24jN%X0xbic+Tn|=&99-3WLHoiFDDl+2GS8q0z6Lt>+|Y&zLiB6&&hq$ zyovlU&w#|`!JOT>qrQ02JZh@8UC}0W!*=G5{3U@c3sF*T6RO%by5U54dI{Ln{QUFA z#=|$@@0&_g#$g^G9K2nyYYS~?Xg~~~KPT<&@tY`o0&ZSJU!=D|$q@eu3P$$h#~a?g zdw0-)NGpBEyZ)-?0G0KD+IF$mAY^uXz>L#yxnSl)g_B=UP(n(Inu0%5X#D_& z&H{fnH!)$!F=G}R6QlZ1lr9E;dytv=84Qre&UajojO@Lq_!o83vfgI~LK$|Pc#U%2 zl(iErBSw6YnjQ?fx@3mnSs$QsW$@SyOjF0kQZ!oM&&a?7Q+8oDD)#|KMxR1PV@I{1 z?XCKh6#A|n&y#)X>rt;?Ae1o5EKm((0AyuuY6?{dtBLUX4lZ}MF-IzOJ4mjh^Dw!L z!rehmZ;vzQq9BYDImX=<`I4y`i4GlbQ;UWJ#GASzS?B~Y6h`loFMm(WM zmsZ2U;ep=nj5Xdc&Rd~@DXD{ zFdcLePnyZenb=jrq@|T${KXSa#2RkjW`HLZR0yWtE{|XRg&m?5I6zBl>)}BY3GXc* z9(sfEIVh69fB!~&VP$veO?*B|lfVB@xZ^M|e*v75x_TQz;xlsd=;$V-Sio`b%a@z* zXd;*ZcZ;9T8kko&oOkV~coq-NDp+}9;%k^LYk&C?j0=P>N?sz~Fu%EXngXf2PsKp< zgE|dwnwFj(A9-s}&nfPt*^NIqJm^ml`9Xn!Fzfo^0|9?giDBs``=juG@Nd6jN zE(c~kTR&@!K1tnOM2}m*&3j-*4FK`Bjw8A)=mPEbmB^gXsHELTy+8{bJzFsP{ykdw zi=Us@S62^qbntO;{XeaJc{G)6|F0?I#?G9~A<3{4lFU;`88RiY%|j}Ql2q7c$(X5R z&YUSl5h6pLiZV7*kx+(Gq~Uz_^RD;&&N}~{wNC3@?|Pmm_TKlsulsv_zn|&qfM^0r zQ(X9`mv?IH<=(*d`wO-zDs}~cR9IN}Dc~(=xFKfDxq&$}#_47(V_OLy@+4*=cp z^zZ;=OSP}nw&SVYU|a^ki0r+0KR(7@{9F^y7&@K_<`pZk{(9`~_yXeMuLh&uEqo?)s7l##5Qkvl;7_bT*fz))W>9;+PCuqBescK4(CdQ*4e2}8iES)d zQC3D{NWAi$EBl6TfM%?-IP-&N&$y5`wl&#v108MfBdlobgUHgdm%HKPP+}FH9Vcl* zHWyQ+oP-CNnLlimcc8d^FF_p`dHxw1yJxAzsUGod zgm|&q7QhN3Gcr6_BE*>Klnq*ZIca7_#q8dxaV+hyU}g|Np8+qO6;G6&mrQ&JP!9I6ACg%)h_D~aCedh4Am}EBH45a#CY0pEr8g@A0MdI=@QMHEiA}r3;p~E zo=m;;RHs}>tFa`Vbjj!(O9VtR&~?T<)lGPWc8-k=p3ktyp8~00BzhVUCR}U2;vYPK z#2g)|0x~fD#j7lO^omb~bnBopXhHTgTK63@CITm8TM&{2ui%88;Sy1Ylw8J|PSey+ zBB(pEpWYHS6zxq2q`M(2ejJP*T6|a6LO2TX2gZ@D;f(efSNhy7E-Kp{<(k}QDV8G$ zXjd62ZPWfm2gMFIx-dpknO>;N4j(=|K|}VU(Y$n6t2^#s_scy4Sc=x*FNCec&$L~wAuF?}GT|kE+h+J{2;n*d_s^fJ zs+c3Q7DTuEB$K~wwD#CdnYP=`#4hv$dvw`%n#?z17DX`4A)>(offSsdwhYd-n+}v( z?hXpHrr%aOE!2_2xIxd& zq_u4fhMhZT;mvPqoWz3V!N1$qY0g|9I{9Ni%}6#TAT8u^N%p~x3-AA^psEei;zcHT zdZ&sfq-4d^{Y^<7N&NB_^9jET=Go-FjJ18b_aeskw@__wj(OqFqUP}TtKj<3O$@l9 z^kB|~L)CG;{UyVh!jYdr0*`z(*X}-HiLlfPU9BxC@dyoVL9Zma+*ujeYNv2J%97l; zb#Ng%iOt^%N^8vUT~7W&3ox-FJ!e#H@zH8c_6{{ka0i*#96+vVQtwQ1$C%Zvf zVSA>8B`HFDxs&RwzkBztYt1&@`O1%uE`k~Q(Np<3k+0eVnxw>btp060^X82gLsnZq|R!a&yn>r}{{eNH*I`#4T9n$WOGUr)};^}M0QP#XREp10tNn@6T; ztHf&O-92@E!#3|8rb-E#))q7o*rk?_oFsAYzOkJCwSz0aZKG5Mhq{RA7Wz|<2Mk^I z$osuAm=ob`I!*n}tGk_Vt=n{Mm)!Tf?CjeVqj+l$R;#@=9n0zZ_xJwpUKL*vFB$}h z@@aNfHnTr*A>~Mj^W**|p@F*9t{H!`-QnlHfuI5VLWLnptggJCXN*@9cu|-jW4?P@ zikL23gRq?}Oy5wofPaTQz789*O{Hx??Q`IKm%$M{(C|}l}m1Ly($f7V z)(A=+`)RPob!dZ9j!2kB1V4UiJp4;HlU~$US+F=FYR@}68b?FqDIg09u}HoOo}Kqt z4ZYiFV<`ns+=^obuQ+h1GqU&>aFuNqQ5JlRCNSdPDu~(s{QGWpq-SAYV&Rs~Hwgo9 ziHVkywvm_jA(@01yoDXzc+4}{ZbQG0WrW^e!{6+0YFMM*tuDPMIkx})e9Cf3*oRme zq3jOUBXX$YfC=+E{d2t&W_}Ye}yZ+YJoq?U1?KGq2+F%hHx^{bx>V$M4~^Mo7lZ7rGypnu_C@r zo5q1f!51OJ6Ti6VpL_%WV3|?TINl7v5*($dgU;60l4$AS0s|xm)7t9KpNNZ8QB*vE zQ3VCv0pK2z1u#l%P3sdI5VBUd4{03BV2DQq)|+>T3G z;n{dGCy?pXhI=FX+oEabi3f-CVRR2Ko`(BKgrX6i@FY2v(LRA z*BTueDYWOb986Vcks$6+SHBD31D2C4wUe%uw$%Xt0fAwnTEUQy4)wx7V^4aXdE$38 zv`O*tIWUbN7-1$b1TB9{F!)j9bS!d$70Wn*!NX*;iq@Fw+CJ}%?-qMK)IR9wfND8ZXFT?V zaPIO$SE|WHOiT>MK3MyJq9DBsqIrO1)aDdYN^kEO%#Rp1a39JL0@m7!{4~7f#!Z{D zb92w53&e94#yWx?B5Chg=S{Fo;TvsgQo}$Fy5b%(rt}7}QKLKd5!rK0S+LyoAheB< zqgxxV0auPQ2*3ymXEGvaeq-PQ!m#U3h_YZJKA(uDIzALMlVCOgdGO*h*5(JX7v)A4|WGk?k znV)woGD<|pAwKEMjfntWs#EW}SS;e1P8rE>-MRBCsu8GI`0DV1@RLf4F-Df6fFj#P6Rm1XzuajZacSzTuDix z?bv}YQi!8xaB$-Xli1WF7S0FF1?XuV0j70#&HycIzjEEG_8qBW2{EE-+nv^!D)B2JV~kpwQidgVCQ%f5rQx3fgy!}ES?(L$r0IWxO- z*i%^fS|x*S#Z7a~dX>q%zxPuktA;UtI3kxoEJ{+qKJyfNHtO6nnTkC#pS%4xANv`DWUh#09*uWez@U*XQGtu?7Ik z&-L}uszay1wc&pWNlDJY@6fG4h=)Rhwha9Zh-z$pVsE1|Gwr}2!&R^}JG}kXxE4RJ zb&lR#v9Ug*#6AeI%OG|oR7-AD31%lAqj{iaEiPO%$b9sBz9GFrwO#=jC1jl%$(q3C za9gKvlTf|cig>D|xLg824|_TLqxu_Zj5qXmcQd+rl;!N3sHXfQX|+nb>lK*<;aApt zrQAwN#XnwlITG8}rI3Q0n8=>Gh2F<(Y)oI#QX~3T;Y7C{k>%BXN(arlm-sVogAj`m zkzTsVnHlB?YipAov(Y;NHeR`6gNsX{4SOYcx1~zzu5IEqBu1KC+`=63&^5e%)7{dc)N&OUrR+pO6}?s-7PIga!}?1M zh7}AUiZ%!0ZF6S%uRbhL z#m8;uMN4e^3{J5eG}LJ=(>PM7ao2o$Dt)h0M{!%WkmL6g{pCNS)>uQ^XA3?}a*BLE zTZZ@a9g*`W_L^7^kz30)-r{R^fCexb=Y5dCeMu+oo+oc#sI@e{H z(>mS3%JvXCcz2kR{erqJk2f%tTaZapwD0u5df5NTltPFmGXwCc1xP||&hSyz>~+3V z8C<#dSwAkXkmHWX@IXN1T1tQLf=+G1YOgg5)~@ST@!~K0Y>94<#Y*Osu0?ZZ?TqcO z&U&VPBSg>2KvawMt8k-$*@ji}kIvU@ln!gf+Tl(zX_(D#1?}?+-C<1vT3?ZMm~f{DCO2rR$Zy-d+iFMrG9bdR>K9ER!pQO`Y4ZY@Y)tUMu6_#!a6CdsKLhC%Ctir;^=06wC*TiBNcK1@#=A>zSaF7$+! zaH=E}K6n~Q0v-uJ533s$S(ZKr%oO0XCDDkoc*hApXxm*kWo0d%gEF|Ql)K=+9g21vO%Q`)oKGLX8Y?;B~Si3_K4kk_Ush6 zWOa|5o#WZ3K%^zf@$K??#_%N(kuJWC!A1+GTu1^K+WKwW<|A?Y-q zD^GW)^?mSHljEDCn5zV8CmI!v&Q%8)aRx9PRTeCw?|3LUan1RU5F!J+BWnkIs1?&^jwl!5}TWb!R z&oKq~sU97Xla-x?MB@*PTczmZF8m4(*J+;$c)LrmhNHdM)MNDBSNajhn$hh%@#ty) zLD(3TVfj8EeyfetZ#f=Rbva#Yq%%}}Vh5g42(5taVndTi@djSYE~q^5b!~CF=JxHU zIbl7lBiv}Uk#3)to_-6t6&S&m*FsgVCJMi-iC(kkZ1cS@ODc0|7>B?ElO5W(1(0G; zAiKG`q8>X`cMtm7(zLupGi@dfGv*8$f|$VKo@%tGZ-~u82vxYz`=1vvlKoBYguq_HE8^) z121&qchFa8h;Y8VC(A4{XQSmkfSCWQ%08G&ToA|#$&~Q!00a{Nu9*L9duZT6l(lSP zLIP--qXYRJpfE6s;y1?qP6u%qSJY3`IoZ%=oH?r@lGX>M#MkfNq5Nn@e}>jtNLct} zupKXhydw`Uue|g9Uw{umU3|p&n!vA6p|-lMLN811t_Y? zP*eiG474Q^EN@G9N?i?CgXF><(G* zD|8bt(LY^OaVR3&Q^P+uCd_>EUv4`l{;$Vycca*Dnj!*HVH7h<`rB{^n|k;-RCKtjf9>GMs5Zgee!fO0VLp>+zzs`6&qbK%*2x>|ok z52M4uVIHVI>rmgE|N3}W@WE=Sh@KD|VV(gmH#cfx3|heAl9Kb#XF>Xb+}nkBtIzVI z*s{$sva)6t7M$(vgVD_bQkdM|$j5p+gpVdDuJiHZW3a+uD&=HmRtsJf`+mAjhP;d@ zCfp^!VSo>SEaAnG9UafFAjdyH=|CV3Fgbn3b4B&TL9z&X269=LW$Br|op(y6+sxd7 z$@K{0JiEJ95wf7@Xs^C1UME?mXM=Mupk)hby^kgrFWOCeK5wIaQ`r7SOyb{v{P^+h zn+A5s1U`9k&jyiqhm`eT_=m!TPQMba>DbTcqtr0&hb|T?0;&}(8eFtU$>yG?zT^4U zW!OH@tb<}lxu=>lu;doyuJeXzI&SaM$XC?VJP%D0^c6#4T9ghlNnnwNSn@7T+VCUg0*vW7mQc@mJyt&q?0bKyihBX=^dYB!r_&7gI3t%K3YseAF zz;Y1Yj9GV^f&##he|8~@8!*5X(+%71REm?AyIhw5QsH~I2b`5+jDJvr^#d6q28M}aF%bx6x?30}h3g;t509nF`3P2@H}%HU5ncalAsO;Sutz!^2e zV1-Kt`hfHuRAK~PkK>}`R-N{@A8N1W_B9>By}c~3Lqbzi`2J7C7U5+)j~->)Opv{E z-I+aW9AX>*UV?j0S9OrZm>+a>OagrX9l5tIc=+>v3t_xWC7Vnt8g8Uf3S?_Uh~W`D zg|jXI_ExI~2qYR^FXjl)P$iLfM^IbMXDB&?o30x>q!xP zn>!&BVfvA@U(!W4+&YXpjmrh<@b29^RHI)IyHGlkb8|Iu?|~$yN>;yly5X%Y((l07 zg4d;RZpJ8!=L5tgO6gKjqqcSt%M~~C0CJ-_I7E;-HGCL8Vrbk^oi0FI4ml(h2Y>nU<->>51xGk+_epH08K*5ZVVVWj9PWSZwFW5HbRpRzq2Bqt)ESY)BX zmtZrl^3xPvop1K8n}0Mz9so!Iy;g?D-q zvb3|!RIzPCNfS6bWKwQjc+z=|&49KwSd^L3?VRqHxt=mDvLl^w?K(>T+`>Xq#s?oM>o-xZq^zfL8xCt04FZI3zk`DlfUePn zhl$1F6cJrgih+bnoqecQUZ48|wVP#Sz1`i>s36&9I1mK}J|lF?__D!cGg1I1D#^+| zdinCI7;~zmieMtBYmRfbNm;WL!;mJD5hbwX{|0@b*f5ZQS`Xs6Y2d3nA@hLb8feV_ zE9i@@5bjpq?Y787;;dC{t*;TFbcCwP1ynI@QA95eT=;G4IlG$C_4Rcy^)DVi^guqB zne-_E&i_KKN29eZX}-Bcd$YtO{zw<4BS zUcdm=fC*Z9Mg|7z%b``oo1;3TIfHNx*LkqqnvpUIB`;LR7y*oHtZPQ~vxPYJ!Z9HD znwoaT%`JbxoQ~3wo@nTxDG&>|=?JPVHaol+Rt!K=ph!O91(dd0ZvzavaeZZ*x0Ra)Y zn~9~%$Y_J6GsT!85Aw5tHpb_SQ$SdHiOfn*urUREu@2BDlWbUu1`#v+pT0bB`GW}z zud!j>XLN=yxswEd5|51V{n=MEi2s<`zp}WfW7*@UdbQ_$_OA>v zW|5@57N?6Ri5`URN44ZiyXYMlFiFSuYBDa=fi;Vqa%f#9yS}ciLl+&{=%9IOxctX? z`&six%|AvAX5;VP;g8Oq_S*LJlbI^Bew~F^q0sG@#T<()iF)JOf9=f_KAdOweq)<= zLE&qFT%Aq%!wk!z^;zfBdqQhPGfrkG4!Km&*?O-`&|)?K4I#!n7Q@yG&pgn4oX=wV zO*%=6p$cU(TxYRk!d-^_fn%@+#*1hVzEz6?i&z5*d*f~QqEV49upLR0G#NM_P8Q_Z z2Tzxp(1EiI_e`iU!{FDDt@GkV;aq^fzs{j5t$lXUJ@j8CGLw`2;qn1qh+}~sx$mtt>6?*f=U0MA2ayxaju&7iLAMnX6GPGcYcE`_ zbUBhQxqk{Ai2Z+#;y}N52Krr03osJuvFXc6Y8d0ajzPVL_mdSOxGM_+L%t7?6C6_K za%&%L##jXkCAF>kv*ppg&F%to;x;_krAVOcN zZC@fZ(D$%z?*13eLx)X*=72r$3ka;PF1f+9RWV$tQ)zW>aP)*tvm-)i5@2{Vmrg^1 zPud@rrNdBygNH&`@vyftjDk>UZ33fsiG46k@Bq_qf5_X1F2vq^SUkSpp$VTj|BZBt zag~bw@H%ln;oBcHXy51O}Mt4Z^#IUc>y&3LBe~}v7Q*8_PF8JdK zeg7WgRA@+Ur3&b%vHhyHkYSF{d6HsP4%PRRzZwqL!PnYPd8J-Pv5-N(KJjB?`dJ10 zU~ujq99%+^j7S}PR7^U=DE%PWgoFg$y==CXjSio&iX4v|5%-IqJ&lN+ zf6od7YO;q*(pWaj&dqm9q!Eapoa>oL@2R9+Jzz zA$@~IJ-Ay?gbv>4N1O2N7T&NuM2CEBD42Ciki5%cLSvL94KS3d;kO^oAhxc*C zt%hnz>fX3A-w>^;xZ+cVx%cl5ZSA+9(w@-GzH+{6vle;*P(sJi3vUhaQdp?4k|T!@ zCo+ZWfcZf#D>7S^y?rCZ@;3vHNR`CPR>*(T_kT)70fsB0-W@I&ANNyTnJ&Ds{pr|% zUY%bh(=KXriOC)zg||yfKjK;SJ9dm}Cc++wa4N7Pph=FjhBRV4#D-&LP89?Gq@F&6 z% Jp?PQm5#`$i=>Wz^Y{@8WFfQO(JBs~re%!vn6V6@^$m-bP+7Fz;Q~{m@N98cT zcE#0T`^7W`NQ;v|h~zA|w^dRSk`5#3v~4``SUt#FeknPTt?qS6!3%5)gDwb4(72w@f@TIfG}gAwtlYur9>qei zuHoPnklxH2-%FaHFx@CA!S^Ak;)_#g(!^pR$ptCx)DpZyLj#9Vy#Zv08^;r8fPbc* z;R9JN(6WnoA7uM{0of~Qa$P-$Rl3D2gX7T!G3^SQ4iRb=bbB~G9(zoZju2~O4t>zs zX_ETuSv9NlH06jURz^=xj8PHDv|2pgV6`|{S?RX0?L3bG2UL)6BQ)>L(4K>vcJEUN z$~|xfcMPR%kGeYE4sJAc%;kuJ8JGuB`Wrr+$!UirRz}|b@BWkD7uS9vqo~)t9*IJb zj3M#uGaz%uqkv%%MtA7W@grttmmI2%jw|MTg3BNBiroPpdVz*O$cO%9A2HIQ`Z^A$ zgRTa4D`XrmqQn6Df$;ENb2FSws#ib1e@{^t(j|fx$8ivVV~*T8o{RG&1qcQvi$9@d zl|FDy4NVm8B@RZY^2-cIaUGur5{Wee?;t=Y>d8J-q|Vfom4o9APHIFA{}8YScQ7Wr zoxVe5Am#A=Z%*t6un#{B(iiUIm<&zLR_ncS{Zs!T(#@`GG=u%Z49*(miU|;RIzBP6 z@y;D;*c&=hcoR1fjBxMDKR06pPHR3OFh2xj4wV}}3hvDgIOP@z31mw(V#U6_uzm~( zqk8U5d@G1%&glMQZ_!4k> z3%d5=L2qj6Y0hsH!m8sEsTrCh^!bNhj*o|bIf>pAOknxwoR6{taFx~2`w0nbW>#Sz zBci|bp7F*3Bu#d>?!G5aAc94g3J{jU3FfWQ+6 zsEBdOMshL{vjJ``$`Q2W=z2ll{>DR(#{rlRaMtPl28!ViU3X-gDP$flGGezFN2noG zJn#I~Kv$xB7W7*#y1n(<25I)#)J%kpfBd=zU$3QFiGsCE;gA{+Dl+vj8 zyqhF?>A-#>gYh#o6<5K(j{B`X@>YhP3!MxqR=k0P>Q!Xn^?z|9Z8a`^jyrlxhGy5$M(6u^g1G>TFbbip* z@U7L~D6Qz5Y(Gf`Wwqn;II0b2pg>PiT3kH;rgd}ZMgK`C(V*(T$UF=tNhzDaTKxPI zN;MEpYAKzJ5&Z+K3miW7evG{OeyrCnhn`VP<8_l#y)GAb9U}$Q^#o>SnzNR-M3A{5 z=ULFWbH-hcZ#&#IXo#_60Qdy$5~wbnHja(HtINPX0g3>qA^0=H9_ zeG6$tF2Vl&pFy3W?hJM!c^JYT02fl3{m^p3*|FTgrmOl6cNz2>YOtiqX$b7ZV$lhf zF+Lj%S^s_v5(VG{Krpd4VgH8r<0gO6%3lAX z*C6-a?@h}ZdN!)3uA!lAZTc$23i=JeQQJdRUfrz|sYJp8cKVyZuu&DMEE-xI+)^w7 znDZf;kz{@cY6GACA{0g_8aggKj_>hK*kRbg5}+qUj|5BMS(H8qmY~W<3(g^`C6{76 z{UjH9ed@K~(LR9mDQ)e%rysXUOJlP}yL$9tJTJD-gv*zy21T%7;6HVVz^ib=7mjAM zuXi`WoPfZ%ZxC>2oAVxg`*nzu>NWzd7_LLY<8bTNE!glelYy*`xTX1Qa29(c*2Vwm zV(?i&O<`L^-ohWu8dPBkB83nYgv-R~2!LY1R#9aj=$^3afCj*$t*WKvq>zb-gqEhJ zReVhd6FB>8wa(-mTB&;bDi~5>g>ymgB~wNCgTN?Y8IVUJW)7846KR3C;gb&`ga86g zja5N2iNDy$a1!tkv~?&`uzVm_0KGcUrO}=qFMvw;JShACFmR+rq%RfHN3*mTQE+)6 zF7;Cd9&YUCp6>4X1wVUk`{Lbj3f_O>5=6MU-%m|7LM{W>B_bJX1}Y|K(Z+y7RYFu4 zzHbjlev?$l!tm6>uMXFUe^3zhW5URcB%-q#*Yon6;SL23#Umg9cfpIhK}Tm|;A;{4PPNpX3HW* zgPR!S7mt(uX~pL!JoN@>UU_0NwXMWGhnW{ldm^9zED8hkaoD(dti@A|Cl34X%Gde# zA+l6e8PlfOd5Gxhsw{~0t=rC8b={#F{Y;331rA^w1#4&N&uFqTvrb;_a2vLGDGraPnlhbNCs~ zBA=Nc)+h-aQqb4OBEl`;_n^1}dlkt9v2kd@M&~RWIvc`5kKy%UY9$g$pe@3}XteU2 zXK!8FxP8Bk0=cQ#fMV?lZUe&>z=RI9MoEDNnwl72k~iBzLxOlQG&{aHC2(LLl@dhk2P{oo}D7+`R` z;Txu@P)2#S{@Wq`TQDIbIzl$B54tgGHgnP=U&h@0p*x#`t|hUCI%~_gNoW0(M9bre zoe-rJI5r->{S^kkM_b0Mf^KQCS>PlXl@sOy?=OjH=6wHh{Pa-BLghb9dDjA**p%Jy zuwr|}`Dnc#zhZWV3({S8t?kU});qE*X-^yL4;fV!;w%uxIipsEuRpKmMcHzx9eHwL z^}gqsz(Bw8`YF_{j)!aW=c{DN_oe+}h1r3GZ@ls+GH-8d|f&!yFB)5ah=yl*hd;_uNvXU4S^KiWh4&@E61xuKi_uUBrFf7CEbSr7&aJgfdQDm9vi;Et&yryiQbqNs{&R&wg zX|qpr_2|gs4?{K$wAzXzHeor zGfhioPQ_|TnYyn)bSP#zZeVM!kcm_-;KqSg%bI#VR0ah-P1m;y>k8;dQPA~j?XeqB zb4@)NTB02-y^HHkFMXV_XOF07d%=6jy}7MRrrOU|bb%O!}5p{#u4dw6tJF=cec_ginFFQ+eoed5~zSI6}r71LC z*tbjCwkuN)OXgzO$iu^MsJ-t|+VFOLnPYg?01TZlGKxM>ddlCQX1fm#j)AaAqb8;! z)JX2-EG^_iI6VTRG7=oe$9Jo$f&i4>x|N@g@A#XRY?*QC4YUV|Z3nIl16#*{6n^YB zrXy@POmTPMb9THRy2uhaELxz9i6?P@>XX9fpL|De9@9O^DPT6-Q?KbLOZb4!r-e{K+@J0J)UQqN~ z7u4ZSCKFJdjcKdv-B$+6s;vudq3B@hB8Y1J!Z=RUTSXg=(etY01wiz9bZ(PScJv9g zn3f=-q-tKamEL+D8Uo^#e{ggc5;?6|*a< z1T%dlnqaijoi~mPCfb6##TWyq3F)vHllgghgD?{V?1AS`S^ zG)*kVn@dVd@4$49fsER>LB5Mj3_ZOEkk+6Ng!}y*)b`kQq2(1xx&w|D3IOV|fVG?_ zBxOoTfB=tY1M*`q0iv5ilqOweCpb7Dy}%r(hyUvS8_9?{_Zh%8JK| zH_z(=rO0Puvlf^E#>T?9kN5_hBi!KX_!)8~uJ1l>1miSCR+%vmez;lb@fyX-m|4f$ z7J|SR4el6t%y&K{SBc;`o;K=m^!~?SJNpIdtHz$$?^WLRP?dwSR%m}|nDW}qdpEc! zYY9?~R{>{{hrMRjS@Z>fp-*jl1xAyVzTnT)#`&@c>!8XQiD?N53E&}hKVmwpH~!l| zWHi0-q_s`zoP?JjllvC=r;l#(FdlrZ`+OwX>Pfu@iLEvSIz2p;ij!xKI2ua$!bX8cn9*dd9sSbrtN%Bl?gXBuD zr7%N_a%&W{!#D!lk5)lWZfI@=SR+nsoy5a|ZLYL*E2X2izyBP@22gTXE9j_p9ea_U zoqY&Mgml^(1kyOI=0opBux#PX#5kPDis;$2?Cf#4!0~LHC#m&&E2CBdLZu3#5DXpA z43j@=|3c*~)KXi={OTH_s z7Ts$jXRkbu?c|+yJg+66N2wT_lwFa+`aNWAHSx|YhBufY%l>rH_QS^ z5x^Z>OU{_JEy~H~#8mk~P76Aqwl-}_2Qw?HphhsM+CXWf>v5?Qf3?9ay3Kp%Xbx-k zGhWBh2s_ZPqq=hnDkD=Zyy&j?U?E^#pch(soFWQWAFB!`CMO+3*#$NBqRuS_nPssj zgHRD9B^f+IwlM4cE0n|_1Zk{D(#J1fZa)7ccH$bO$H8U-fsK!-3|c)VjocTobLv1D`SBCm62izs~18E0R~2h>6l~L zN&|QE^rQ~gxYr220_h7tY;lpB0lq-VMcR&UWy7<0h#{API16<3J4h(0=bW3C)Ze*7 z1(v{kfVXQx4F^G|d-^VViQeT7&jy@+g3_i-d_qot>sq?HAMFYP(I`~jN4pKEI!QA7q8WkF;V;JS~wxp8mYIQjlP@Ld_- z5o!nw9EVT9p26Nr%?W`T7Tv>J2$A9p>LG*!!iw~U=6mkn zzkUIyHK^zQfrM|{71O{Y*yq;~>4GhL4KwzU=71>4K8&h|T-6kASo?p7_n_A=!0^n? zF!}BsUA+B7itdvw0`~wk`ayGtb(Rgwl<_F;P$5(w-aCF^*aY}23NaD%Fl6xvqoR|| zuaNx2mq0!B9%FIO!-u)MPe}udh13f>EpR;O;()9|8q5k!=EcAFVSrW-!ZhAt1gj!m z5Whl2*JAjS$G_;T?N~%vC zM$tw6pXM?{BO@@1SQW4hdO|sf1N5+sPA&z5Hbakqn~b0^PxNLuMHmDmka?&g2ZL}3 zg(Xtg&YeR(JK~lkAYDPGhKdR=UzF_1aW^f_vDrhaq;YK621ElFm&x_?i(nyfpBnJp z;6;H`06&0_65WULXB(iM0OPUJszF`MAjDJnl636tKj``(JEr*o{s7$TC>FF{!NB-< zGxb1+* zJdF(vlq;^vSE6}j+OJ1=Y~6NfZeRz59LSsm>x%2g0SZ8T(6w-9_8-IG0rZ4y&35>_ z0D&>RXxJBt8Tzd^;WPGdch_;+iYtc@Wo8D(XP<%!Q-M>p!wtchlE8)`t{ch^+&dhU z<)b9>q=DlB;VH3}b-C;R zD193a#MZvx2)(y}w0&lnw}E=@@zh2R8=5~lOL6Fi-vW|B1{^e{!2hsLs_yEjiBsVQ zR1m|~oB02Zpp8;&BMbL*E=5@lpDK2F#JKwmx<)_fp&?+v*_^8oHY270Z6r{v?uQSN zm-cab8hs`{sUV*bNIeUg`RAoivCy#*0g?mQAA)s{F^jsFh!J(hVr(k`pPfL8O=kb+ zfdUG&3>{KF@NJvlzJgWP_biDxrGVP{%jWE1>aQwxSqo%C%?RW|Gabf47YE%v^=FwtctW#k}=GZD@Zcp`co_JmJWJ?n|j*& z{g0H_h`ABAT((w5R|d9~MO~ctFGq8_^P@6@NJfu!wj+Oce24ARin4a@^*Ze}*3#9M z^sn<{V>Y6Tk{cK)EET0Pgu~`?0{WjbV5g^n=Em+eb&aWGs*i^u7znvAA1R;5s$3Bn}bL{hfE$X2pdoclj^P;j)?DN_)0d8vHRaJYaBBj~wy8 E01+e^=Kufz literal 0 HcmV?d00001 diff --git a/final/docs/tutorial/LangImpl5.html b/final/docs/tutorial/LangImpl5.html new file mode 100644 index 00000000000..166b74a4dd6 --- /dev/null +++ b/final/docs/tutorial/LangImpl5.html @@ -0,0 +1,1780 @@ + + + + + Kaleidoscope: Extending the Language: Control Flow + + + + + + + +
Kaleidoscope: Extending the Language: Control Flow
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 5 of the "Implementing a language +with LLVM" tutorial. Parts 1-4 described the implementation of the simple +Kaleidoscope language and included support for generating LLVM IR, followed by +optimizations and a JIT compiler. Unfortunately, as presented, Kaleidoscope is +mostly useless: it has no control flow other than call and return. This means +that you can't have conditional branches in the code, significantly limiting its +power. In this episode of "build that compiler", we'll extend Kaleidoscope to +have an if/then/else expression plus a simple 'for' loop.

+ +
+ + + + + +
+ +

+Extending Kaleidoscope to support if/then/else is quite straightforward. It +basically requires adding support for this "new" concept to the lexer, +parser, AST, and LLVM code emitter. This example is nice, because it shows how +easy it is to "grow" a language over time, incrementally extending it as new +ideas are discovered.

+ +

Before we get going on "how" we add this extension, lets talk about "what" we +want. The basic idea is that we want to be able to write this sort of thing: +

+ +
+
+def fib(x)
+  if x < 3 then
+    1
+  else
+    fib(x-1)+fib(x-2);
+
+
+ +

In Kaleidoscope, every construct is an expression: there are no statements. +As such, the if/then/else expression needs to return a value like any other. +Since we're using a mostly functional form, we'll have it evaluate its +conditional, then return the 'then' or 'else' value based on how the condition +was resolved. This is very similar to the C "?:" expression.

+ +

The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. +If the condition is true, the first subexpression is evaluated and returned, if +the condition is false, the second subexpression is evaluated and returned. +Since Kaleidoscope allows side-effects, this behavior is important to nail down. +

+ +

Now that we know what we "want", lets break this down into its constituent +pieces.

+ +
+ + + + + + +
+ +

The lexer extensions are straightforward. First we add new enum values +for the relevant tokens:

+ +
+
+  // control
+  tok_if = -6, tok_then = -7, tok_else = -8,
+
+
+ +

Once we have that, we recognize the new keywords in the lexer. This is pretty simple +stuff:

+ +
+
+    ...
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    if (IdentifierStr == "if") return tok_if;
+    if (IdentifierStr == "then") return tok_then;
+    if (IdentifierStr == "else") return tok_else;
+    return tok_identifier;
+
+
+ +
+ + + + + +
+ +

To represent the new expression we add a new AST node for it:

+ +
+
+/// IfExprAST - Expression class for if/then/else.
+class IfExprAST : public ExprAST {
+  ExprAST *Cond, *Then, *Else;
+public:
+  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
+    : Cond(cond), Then(then), Else(_else) {}
+  virtual Value *Codegen();
+};
+
+
+ +

The AST node just has pointers to the various subexpressions.

+ +
+ + + + + +
+ +

Now that we have the relevant tokens coming from the lexer and we have the +AST node to build, our parsing logic is relatively straightforward. First we +define a new parsing function:

+ +
+
+/// ifexpr ::= 'if' expression 'then' expression 'else' expression
+static ExprAST *ParseIfExpr() {
+  getNextToken();  // eat the if.
+  
+  // condition.
+  ExprAST *Cond = ParseExpression();
+  if (!Cond) return 0;
+  
+  if (CurTok != tok_then)
+    return Error("expected then");
+  getNextToken();  // eat the then
+  
+  ExprAST *Then = ParseExpression();
+  if (Then == 0) return 0;
+  
+  if (CurTok != tok_else)
+    return Error("expected else");
+  
+  getNextToken();
+  
+  ExprAST *Else = ParseExpression();
+  if (!Else) return 0;
+  
+  return new IfExprAST(Cond, Then, Else);
+}
+
+
+ +

Next we hook it up as a primary expression:

+ +
+
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  case tok_if:         return ParseIfExpr();
+  }
+}
+
+
+ +
+ + + + + +
+ +

Now that we have it parsing and building the AST, the final piece is adding +LLVM code generation support. This is the most interesting part of the +if/then/else example, because this is where it starts to introduce new concepts. +All of the code above has been thoroughly described in previous chapters. +

+ +

To motivate the code we want to produce, lets take a look at a simple +example. Consider:

+ +
+
+extern foo();
+extern bar();
+def baz(x) if x then foo() else bar();
+
+
+ +

If you disable optimizations, the code you'll (soon) get from Kaleidoscope +looks like this:

+ +
+
+declare double @foo()
+
+declare double @bar()
+
+define double @baz(double %x) {
+entry:
+	%ifcond = fcmp one double %x, 0.000000e+00
+	br i1 %ifcond, label %then, label %else
+
+then:		; preds = %entry
+	%calltmp = call double @foo()
+	br label %ifcont
+
+else:		; preds = %entry
+	%calltmp1 = call double @bar()
+	br label %ifcont
+
+ifcont:		; preds = %else, %then
+	%iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
+	ret double %iftmp
+}
+
+
+ +

To visualize the control flow graph, you can use a nifty feature of the LLVM +'opt' tool. If you put this LLVM IR +into "t.ll" and run "llvm-as < t.ll | opt -analyze -view-cfg", a window will pop up and you'll +see this graph:

+ +
Example CFG
+ +

Another way to get this is to call "F->viewCFG()" or +"F->viewCFGOnly()" (where F is a "Function*") either by +inserting actual calls into the code and recompiling or by calling these in the +debugger. LLVM has many nice features for visualizing various graphs.

+ +

Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares the +result to 0.0 with the "fcmp one" +instruction ('one' is "Ordered and Not Equal"). Based on the result of this +expression, the code jumps to either the "then" or "else" blocks, which contain +the expressions for the true/false cases.

+ +

Once the then/else blocks are finished executing, they both branch back to the +'ifcont' block to execute the code that happens after the if/then/else. In this +case the only thing left to do is to return to the caller of the function. The +question then becomes: how does the code know which expression to return?

+ +

The answer to this question involves an important SSA operation: the +Phi +operation. If you're not familiar with SSA, the wikipedia +article is a good introduction and there are various other introductions to +it available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block control came +from. The Phi operation takes on the value corresponding to the input control +block. In this case, if control comes in from the "then" block, it gets the +value of "calltmp". If control comes from the "else" block, it gets the value +of "calltmp1".

+ +

At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in order to +use LLVM!". Fortunately, this is not the case, and we strongly advise +not implementing an SSA construction algorithm in your front-end +unless there is an amazingly good reason to do so. In practice, there are two +sorts of values that float around in code written for your average imperative +programming language that might need Phi nodes:

+ +
    +
  1. Code that involves user variables: x = 1; x = x + 1;
  2. +
  3. Values that are implicit in the structure of your AST, such as the Phi node +in this case.
  4. +
+ +

In Chapter 7 of this tutorial ("mutable +variables"), we'll talk about #1 +in depth. For now, just believe me that you don't need SSA construction to +handle this case. For #2, you have the choice of using the techniques that we will +describe for #1, or you can insert Phi nodes directly, if convenient. In this +case, it is really really easy to generate the Phi node, so we choose to do it +directly.

+ +

Okay, enough of the motivation and overview, lets generate code!

+ +
+ + + + + +
+ +

In order to generate code for this, we implement the Codegen method +for IfExprAST:

+ +
+
+Value *IfExprAST::Codegen() {
+  Value *CondV = Cond->Codegen();
+  if (CondV == 0) return 0;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  CondV = Builder.CreateFCmpONE(CondV, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                "ifcond");
+
+
+ +

This code is straightforward and similar to what we saw before. We emit the +expression for the condition, then compare that value to zero to get a truth +value as a 1-bit (bool) value.

+ +
+
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  
+  // Create blocks for the then and else cases.  Insert the 'then' block at the
+  // end of the function.
+  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
+  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
+  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
+
+  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
+
+
+ +

This code creates the basic blocks that are related to the if/then/else +statement, and correspond directly to the blocks in the example above. The +first line gets the current Function object that is being built. It +gets this by asking the builder for the current BasicBlock, and asking that +block for its "parent" (the function it is currently embedded into).

+ +

Once it has that, it creates three blocks. Note that it passes "TheFunction" +into the constructor for the "then" block. This causes the constructor to +automatically insert the new block into the end of the specified function. The +other two blocks are created, but aren't yet inserted into the function.

+ +

Once the blocks are created, we can emit the conditional branch that chooses +between them. Note that creating new blocks does not implicitly affect the +IRBuilder, so it is still inserting into the block that the condition +went into. Also note that it is creating a branch to the "then" block and the +"else" block, even though the "else" block isn't inserted into the function yet. +This is all ok: it is the standard way that LLVM supports forward +references.

+ +
+
+  // Emit then value.
+  Builder.SetInsertPoint(ThenBB);
+  
+  Value *ThenV = Then->Codegen();
+  if (ThenV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
+  ThenBB = Builder.GetInsertBlock();
+
+
+ +

After the conditional branch is inserted, we move the builder to start +inserting into the "then" block. Strictly speaking, this call moves the +insertion point to be at the end of the specified block. However, since the +"then" block is empty, it also starts out by inserting at the beginning of the +block. :)

+ +

Once the insertion point is set, we recursively codegen the "then" expression +from the AST. To finish off the "then" block, we create an unconditional branch +to the merge block. One interesting (and very important) aspect of the LLVM IR +is that it requires all basic blocks +to be "terminated" with a control flow +instruction such as return or branch. This means that all control flow, +including fall throughs must be made explicit in the LLVM IR. If you +violate this rule, the verifier will emit an error.

+ +

The final line here is quite subtle, but is very important. The basic issue +is that when we create the Phi node in the merge block, we need to set up the +block/value pairs that indicate how the Phi will work. Importantly, the Phi +node expects to have an entry for each predecessor of the block in the CFG. Why +then, are we getting the current block when we just set it to ThenBB 5 lines +above? The problem is that the "Then" expression may actually itself change the +block that the Builder is emitting into if, for example, it contains a nested +"if/then/else" expression. Because calling Codegen recursively could +arbitrarily change the notion of the current block, we are required to get an +up-to-date value for code that will set up the Phi node.

+ +
+
+  // Emit else block.
+  TheFunction->getBasicBlockList().push_back(ElseBB);
+  Builder.SetInsertPoint(ElseBB);
+  
+  Value *ElseV = Else->Codegen();
+  if (ElseV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
+  ElseBB = Builder.GetInsertBlock();
+
+
+ +

Code generation for the 'else' block is basically identical to codegen for +the 'then' block. The only significant difference is the first line, which adds +the 'else' block to the function. Recall previously that the 'else' block was +created, but not added to the function. Now that the 'then' and 'else' blocks +are emitted, we can finish up with the merge code:

+ +
+
+  // Emit merge block.
+  TheFunction->getBasicBlockList().push_back(MergeBB);
+  Builder.SetInsertPoint(MergeBB);
+  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+                                  "iftmp");
+  
+  PN->addIncoming(ThenV, ThenBB);
+  PN->addIncoming(ElseV, ElseBB);
+  return PN;
+}
+
+
+ +

The first two lines here are now familiar: the first adds the "merge" block +to the Function object (it was previously floating, like the else block above). +The second block changes the insertion point so that newly created code will go +into the "merge" block. Once that is done, we need to create the PHI node and +set up the block/value pairs for the PHI.

+ +

Finally, the CodeGen function returns the phi node as the value computed by +the if/then/else expression. In our example above, this returned value will +feed into the code for the top-level function, which will create the return +instruction.

+ +

Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete language +that can calculate a wide variety of numeric functions. Next up we'll add +another useful expression that is familiar from non-functional languages...

+ +
+ + + + + +
+ +

Now that we know how to add basic control flow constructs to the language, +we have the tools to add more powerful things. Lets add something more +aggressive, a 'for' expression:

+ +
+
+ extern putchard(char)
+ def printstar(n)
+   for i = 1, i < n, 1.0 in
+     putchard(42);  # ascii 42 = '*'
+     
+ # print 100 '*' characters
+ printstar(100);
+
+
+ +

This expression defines a new variable ("i" in this case) which iterates from +a starting value, while the condition ("i < n" in this case) is true, +incrementing by an optional step value ("1.0" in this case). If the step value +is omitted, it defaults to 1.0. While the loop is true, it executes its +body expression. Because we don't have anything better to return, we'll just +define the loop as always returning 0.0. In the future when we have mutable +variables, it will get more useful.

+ +

As before, lets talk about the changes that we need to Kaleidoscope to +support this.

+ +
+ + + + + +
+ +

The lexer extensions are the same sort of thing as for if/then/else:

+ +
+
+  ... in enum Token ...
+  // control
+  tok_if = -6, tok_then = -7, tok_else = -8,
+  tok_for = -9, tok_in = -10
+
+  ... in gettok ...
+  if (IdentifierStr == "def") return tok_def;
+  if (IdentifierStr == "extern") return tok_extern;
+  if (IdentifierStr == "if") return tok_if;
+  if (IdentifierStr == "then") return tok_then;
+  if (IdentifierStr == "else") return tok_else;
+  if (IdentifierStr == "for") return tok_for;
+  if (IdentifierStr == "in") return tok_in;
+  return tok_identifier;
+
+
+ +
+ + + + + +
+ +

The AST node is just as simple. It basically boils down to capturing +the variable name and the constituent expressions in the node.

+ +
+
+/// ForExprAST - Expression class for for/in.
+class ForExprAST : public ExprAST {
+  std::string VarName;
+  ExprAST *Start, *End, *Step, *Body;
+public:
+  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
+             ExprAST *step, ExprAST *body)
+    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
+  virtual Value *Codegen();
+};
+
+
+ +
+ + + + + +
+ +

The parser code is also fairly standard. The only interesting thing here is +handling of the optional step value. The parser code handles it by checking to +see if the second comma is present. If not, it sets the step value to null in +the AST node:

+ +
+
+/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
+static ExprAST *ParseForExpr() {
+  getNextToken();  // eat the for.
+
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after for");
+  
+  std::string IdName = IdentifierStr;
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '=')
+    return Error("expected '=' after for");
+  getNextToken();  // eat '='.
+  
+  
+  ExprAST *Start = ParseExpression();
+  if (Start == 0) return 0;
+  if (CurTok != ',')
+    return Error("expected ',' after for start value");
+  getNextToken();
+  
+  ExprAST *End = ParseExpression();
+  if (End == 0) return 0;
+  
+  // The step value is optional.
+  ExprAST *Step = 0;
+  if (CurTok == ',') {
+    getNextToken();
+    Step = ParseExpression();
+    if (Step == 0) return 0;
+  }
+  
+  if (CurTok != tok_in)
+    return Error("expected 'in' after for");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+
+  return new ForExprAST(IdName, Start, End, Step, Body);
+}
+
+
+ +
+ + + + + +
+ +

Now we get to the good part: the LLVM IR we want to generate for this thing. +With the simple example above, we get this LLVM IR (note that this dump is +generated with optimizations disabled for clarity): +

+ +
+
+declare double @putchard(double)
+
+define double @printstar(double %n) {
+entry:
+        ; initial value = 1.0 (inlined into phi)
+	br label %loop
+
+loop:		; preds = %loop, %entry
+	%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
+        ; body
+	%calltmp = call double @putchard(double 4.200000e+01)
+        ; increment
+	%nextvar = fadd double %i, 1.000000e+00
+
+        ; termination test
+	%cmptmp = fcmp ult double %i, %n
+	%booltmp = uitofp i1 %cmptmp to double
+	%loopcond = fcmp one double %booltmp, 0.000000e+00
+	br i1 %loopcond, label %loop, label %afterloop
+
+afterloop:		; preds = %loop
+        ; loop always returns 0.0
+	ret double 0.000000e+00
+}
+
+
+ +

This loop contains all the same constructs we saw before: a phi node, several +expressions, and some basic blocks. Lets see how this fits together.

+ +
+ + + + + +
+ +

The first part of Codegen is very simple: we just output the start expression +for the loop value:

+ +
+
+Value *ForExprAST::Codegen() {
+  // Emit the start code first, without 'variable' in scope.
+  Value *StartVal = Start->Codegen();
+  if (StartVal == 0) return 0;
+
+
+ +

With this out of the way, the next step is to set up the LLVM basic block +for the start of the loop body. In the case above, the whole loop body is one +block, but remember that the body code itself could consist of multiple blocks +(e.g. if it contains an if/then/else or a for/in expression).

+ +
+
+  // Make the new basic block for the loop header, inserting after current
+  // block.
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
+  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
+  
+  // Insert an explicit fall through from the current block to the LoopBB.
+  Builder.CreateBr(LoopBB);
+
+
+ +

This code is similar to what we saw for if/then/else. Because we will need +it to create the Phi node, we remember the block that falls through into the +loop. Once we have that, we create the actual block that starts the loop and +create an unconditional branch for the fall-through between the two blocks.

+ +
+
+  // Start insertion in LoopBB.
+  Builder.SetInsertPoint(LoopBB);
+  
+  // Start the PHI node with an entry for Start.
+  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
+  Variable->addIncoming(StartVal, PreheaderBB);
+
+
+ +

Now that the "preheader" for the loop is set up, we switch to emitting code +for the loop body. To begin with, we move the insertion point and create the +PHI node for the loop induction variable. Since we already know the incoming +value for the starting value, we add it to the Phi node. Note that the Phi will +eventually get a second value for the backedge, but we can't set it up yet +(because it doesn't exist!).

+ +
+
+  // Within the loop, the variable is defined equal to the PHI node.  If it
+  // shadows an existing variable, we have to restore it, so save it now.
+  Value *OldVal = NamedValues[VarName];
+  NamedValues[VarName] = Variable;
+  
+  // Emit the body of the loop.  This, like any other expr, can change the
+  // current BB.  Note that we ignore the value computed by the body, but don't
+  // allow an error.
+  if (Body->Codegen() == 0)
+    return 0;
+
+
+ +

Now the code starts to get more interesting. Our 'for' loop introduces a new +variable to the symbol table. This means that our symbol table can now contain +either function arguments or loop variables. To handle this, before we codegen +the body of the loop, we add the loop variable as the current value for its +name. Note that it is possible that there is a variable of the same name in the +outer scope. It would be easy to make this an error (emit an error and return +null if there is already an entry for VarName) but we choose to allow shadowing +of variables. In order to handle this correctly, we remember the Value that +we are potentially shadowing in OldVal (which will be null if there is +no shadowed variable).

+ +

Once the loop variable is set into the symbol table, the code recursively +codegen's the body. This allows the body to use the loop variable: any +references to it will naturally find it in the symbol table.

+ +
+
+  // Emit the step value.
+  Value *StepVal;
+  if (Step) {
+    StepVal = Step->Codegen();
+    if (StepVal == 0) return 0;
+  } else {
+    // If not specified, use 1.0.
+    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
+  }
+  
+  Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
+
+
+ +

Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. 'NextVar' +will be the value of the loop variable on the next iteration of the loop.

+ +
+
+  // Compute the end condition.
+  Value *EndCond = End->Codegen();
+  if (EndCond == 0) return EndCond;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  EndCond = Builder.CreateFCmpONE(EndCond, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                  "loopcond");
+
+
+ +

Finally, we evaluate the exit value of the loop, to determine whether the +loop should exit. This mirrors the condition evaluation for the if/then/else +statement.

+ +
+
+  // Create the "after loop" block and insert it.
+  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
+  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
+  
+  // Insert the conditional branch into the end of LoopEndBB.
+  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
+  
+  // Any new code will be inserted in AfterBB.
+  Builder.SetInsertPoint(AfterBB);
+
+
+ +

With the code for the body of the loop complete, we just need to finish up +the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the +exit condition, it creates a conditional branch that chooses between executing +the loop again and exiting the loop. Any future code is emitted in the +"afterloop" block, so it sets the insertion position to it.

+ +
+
+  // Add a new entry to the PHI node for the backedge.
+  Variable->addIncoming(NextVar, LoopEndBB);
+  
+  // Restore the unshadowed variable.
+  if (OldVal)
+    NamedValues[VarName] = OldVal;
+  else
+    NamedValues.erase(VarName);
+  
+  // for expr always returns 0.0.
+  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
+}
+
+
+ +

The final code handles various cleanups: now that we have the "NextVar" +value, we can add the incoming value to the loop PHI node. After that, we +remove the loop variable from the symbol table, so that it isn't in scope after +the for loop. Finally, code generation of the for loop always returns 0.0, so +that is what we return from ForExprAST::Codegen.

+ +

With this, we conclude the "adding control flow to Kaleidoscope" chapter of +the tutorial. In this chapter we added two control flow constructs, and used them to motivate a couple of aspects of the LLVM IR that are important for front-end implementors +to know. In the next chapter of our saga, we will get a bit crazier and add +user-defined operators to our poor innocent +language.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

+ +
+
+   # Compile
+   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+   # Run
+   ./toy
+
+
+ +

Here is the code:

+ +
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5,
+  
+  // control
+  tok_if = -6, tok_then = -7, tok_else = -8,
+  tok_for = -9, tok_in = -10
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    if (IdentifierStr == "if") return tok_if;
+    if (IdentifierStr == "then") return tok_then;
+    if (IdentifierStr == "else") return tok_else;
+    if (IdentifierStr == "for") return tok_for;
+    if (IdentifierStr == "in") return tok_in;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+  virtual Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+  virtual Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+  virtual Value *Codegen();
+};
+
+/// IfExprAST - Expression class for if/then/else.
+class IfExprAST : public ExprAST {
+  ExprAST *Cond, *Then, *Else;
+public:
+  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
+  : Cond(cond), Then(then), Else(_else) {}
+  virtual Value *Codegen();
+};
+
+/// ForExprAST - Expression class for for/in.
+class ForExprAST : public ExprAST {
+  std::string VarName;
+  ExprAST *Start, *End, *Step, *Body;
+public:
+  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
+             ExprAST *step, ExprAST *body)
+    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
+  virtual Value *Codegen();
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args)
+    : Name(name), Args(args) {}
+  
+  Function *Codegen();
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+  Function *Codegen();
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// ifexpr ::= 'if' expression 'then' expression 'else' expression
+static ExprAST *ParseIfExpr() {
+  getNextToken();  // eat the if.
+  
+  // condition.
+  ExprAST *Cond = ParseExpression();
+  if (!Cond) return 0;
+  
+  if (CurTok != tok_then)
+    return Error("expected then");
+  getNextToken();  // eat the then
+  
+  ExprAST *Then = ParseExpression();
+  if (Then == 0) return 0;
+  
+  if (CurTok != tok_else)
+    return Error("expected else");
+  
+  getNextToken();
+  
+  ExprAST *Else = ParseExpression();
+  if (!Else) return 0;
+  
+  return new IfExprAST(Cond, Then, Else);
+}
+
+/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
+static ExprAST *ParseForExpr() {
+  getNextToken();  // eat the for.
+
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after for");
+  
+  std::string IdName = IdentifierStr;
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '=')
+    return Error("expected '=' after for");
+  getNextToken();  // eat '='.
+  
+  
+  ExprAST *Start = ParseExpression();
+  if (Start == 0) return 0;
+  if (CurTok != ',')
+    return Error("expected ',' after for start value");
+  getNextToken();
+  
+  ExprAST *End = ParseExpression();
+  if (End == 0) return 0;
+  
+  // The step value is optional.
+  ExprAST *Step = 0;
+  if (CurTok == ',') {
+    getNextToken();
+    Step = ParseExpression();
+    if (Step == 0) return 0;
+  }
+  
+  if (CurTok != tok_in)
+    return Error("expected 'in' after for");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+
+  return new ForExprAST(IdName, Start, End, Step, Body);
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+///   ::= ifexpr
+///   ::= forexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  case tok_if:         return ParseIfExpr();
+  case tok_for:        return ParseForExpr();
+  }
+}
+
+/// binoprhs
+///   ::= ('+' primary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the primary expression after the binary operator.
+    ExprAST *RHS = ParsePrimary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= primary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParsePrimary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+static PrototypeAST *ParsePrototype() {
+  if (CurTok != tok_identifier)
+    return ErrorP("Expected function name in prototype");
+
+  std::string FnName = IdentifierStr;
+  getNextToken();
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  return new PrototypeAST(FnName, ArgNames);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value*> NamedValues;
+static FunctionPassManager *TheFPM;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  return V ? V : ErrorV("Unknown variable name");
+}
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: return ErrorV("invalid binary operator");
+  }
+}
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Value *IfExprAST::Codegen() {
+  Value *CondV = Cond->Codegen();
+  if (CondV == 0) return 0;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  CondV = Builder.CreateFCmpONE(CondV, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                "ifcond");
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  
+  // Create blocks for the then and else cases.  Insert the 'then' block at the
+  // end of the function.
+  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
+  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
+  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
+  
+  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
+  
+  // Emit then value.
+  Builder.SetInsertPoint(ThenBB);
+  
+  Value *ThenV = Then->Codegen();
+  if (ThenV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
+  ThenBB = Builder.GetInsertBlock();
+  
+  // Emit else block.
+  TheFunction->getBasicBlockList().push_back(ElseBB);
+  Builder.SetInsertPoint(ElseBB);
+  
+  Value *ElseV = Else->Codegen();
+  if (ElseV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
+  ElseBB = Builder.GetInsertBlock();
+  
+  // Emit merge block.
+  TheFunction->getBasicBlockList().push_back(MergeBB);
+  Builder.SetInsertPoint(MergeBB);
+  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+                                  "iftmp");
+  
+  PN->addIncoming(ThenV, ThenBB);
+  PN->addIncoming(ElseV, ElseBB);
+  return PN;
+}
+
+Value *ForExprAST::Codegen() {
+  // Output this as:
+  //   ...
+  //   start = startexpr
+  //   goto loop
+  // loop: 
+  //   variable = phi [start, loopheader], [nextvariable, loopend]
+  //   ...
+  //   bodyexpr
+  //   ...
+  // loopend:
+  //   step = stepexpr
+  //   nextvariable = variable + step
+  //   endcond = endexpr
+  //   br endcond, loop, endloop
+  // outloop:
+  
+  // Emit the start code first, without 'variable' in scope.
+  Value *StartVal = Start->Codegen();
+  if (StartVal == 0) return 0;
+  
+  // Make the new basic block for the loop header, inserting after current
+  // block.
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
+  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
+  
+  // Insert an explicit fall through from the current block to the LoopBB.
+  Builder.CreateBr(LoopBB);
+
+  // Start insertion in LoopBB.
+  Builder.SetInsertPoint(LoopBB);
+  
+  // Start the PHI node with an entry for Start.
+  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
+  Variable->addIncoming(StartVal, PreheaderBB);
+  
+  // Within the loop, the variable is defined equal to the PHI node.  If it
+  // shadows an existing variable, we have to restore it, so save it now.
+  Value *OldVal = NamedValues[VarName];
+  NamedValues[VarName] = Variable;
+  
+  // Emit the body of the loop.  This, like any other expr, can change the
+  // current BB.  Note that we ignore the value computed by the body, but don't
+  // allow an error.
+  if (Body->Codegen() == 0)
+    return 0;
+  
+  // Emit the step value.
+  Value *StepVal;
+  if (Step) {
+    StepVal = Step->Codegen();
+    if (StepVal == 0) return 0;
+  } else {
+    // If not specified, use 1.0.
+    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
+  }
+  
+  Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
+
+  // Compute the end condition.
+  Value *EndCond = End->Codegen();
+  if (EndCond == 0) return EndCond;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  EndCond = Builder.CreateFCmpONE(EndCond, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                  "loopcond");
+  
+  // Create the "after loop" block and insert it.
+  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
+  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
+  
+  // Insert the conditional branch into the end of LoopEndBB.
+  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
+  
+  // Any new code will be inserted in AfterBB.
+  Builder.SetInsertPoint(AfterBB);
+  
+  // Add a new entry to the PHI node for the backedge.
+  Variable->addIncoming(NextVar, LoopEndBB);
+  
+  // Restore the unshadowed variable.
+  if (OldVal)
+    NamedValues[VarName] = OldVal;
+  else
+    NamedValues.erase(VarName);
+
+  
+  // for expr always returns 0.0.
+  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
+}
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+  
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+    
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+  
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx) {
+    AI->setName(Args[Idx]);
+    
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = AI;
+  }
+  
+  return F;
+}
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    // Optimize the function.
+    TheFPM->run(*TheFunction);
+    
+    return TheFunction;
+  }
+  
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+static ExecutionEngine *TheExecutionEngine;
+
+static void HandleDefinition() {
+  if (FunctionAST *F = ParseDefinition()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read function definition:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (PrototypeAST *P = ParseExtern()) {
+    if (Function *F = P->Codegen()) {
+      fprintf(stderr, "Read extern: ");
+      F->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      // JIT the function, returning a function pointer.
+      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+      
+      // Cast it to the right type (takes no arguments, returns a double) so we
+      // can call it as a native function.
+      double (*FP)() = (double (*)())(intptr_t)FPtr;
+      fprintf(stderr, "Evaluated to %f\n", FP());
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  InitializeNativeTarget();
+  LLVMContext &Context = getGlobalContext();
+
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Make the module, which holds all the code.
+  TheModule = new Module("my cool jit", Context);
+
+  // Create the JIT.  This takes ownership of the module.
+  std::string ErrStr;
+  TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
+  if (!TheExecutionEngine) {
+    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
+    exit(1);
+  }
+
+  FunctionPassManager OurFPM(TheModule);
+
+  // Set up the optimizer pipeline.  Start with registering info about how the
+  // target lays out data structures.
+  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+  // Provide basic AliasAnalysis support for GVN.
+  OurFPM.add(createBasicAliasAnalysisPass());
+  // Do simple "peephole" optimizations and bit-twiddling optzns.
+  OurFPM.add(createInstructionCombiningPass());
+  // Reassociate expressions.
+  OurFPM.add(createReassociatePass());
+  // Eliminate Common SubExpressions.
+  OurFPM.add(createGVNPass());
+  // Simplify the control flow graph (deleting unreachable blocks, etc).
+  OurFPM.add(createCFGSimplificationPass());
+
+  OurFPM.doInitialization();
+
+  // Set the global so the code gen can use this.
+  TheFPM = &OurFPM;
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  TheFPM = 0;
+
+  // Print out all of the generated code.
+  TheModule->dump();
+
+  return 0;
+}
+
+
+ +Next: Extending the language: user-defined operators +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl6.html b/final/docs/tutorial/LangImpl6.html new file mode 100644 index 00000000000..77dd0ee2b12 --- /dev/null +++ b/final/docs/tutorial/LangImpl6.html @@ -0,0 +1,1817 @@ + + + + + Kaleidoscope: Extending the Language: User-defined Operators + + + + + + + +
Kaleidoscope: Extending the Language: User-defined Operators
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 6 of the "Implementing a language +with LLVM" tutorial. At this point in our tutorial, we now have a fully +functional language that is fairly minimal, but also useful. There +is still one big problem with it, however. Our language doesn't have many +useful operators (like division, logical negation, or even any comparisons +besides less-than).

+ +

This chapter of the tutorial takes a wild digression into adding user-defined +operators to the simple and beautiful Kaleidoscope language. This digression now gives +us a simple and ugly language in some ways, but also a powerful one at the same time. +One of the great things about creating your own language is that you get to +decide what is good or bad. In this tutorial we'll assume that it is okay to +use this as a way to show some interesting parsing techniques.

+ +

At the end of this tutorial, we'll run through an example Kaleidoscope +application that renders the Mandelbrot set. This gives +an example of what you can build with Kaleidoscope and its feature set.

+ +
+ + + + + +
+ +

+The "operator overloading" that we will add to Kaleidoscope is more general than +languages like C++. In C++, you are only allowed to redefine existing +operators: you can't programatically change the grammar, introduce new +operators, change precedence levels, etc. In this chapter, we will add this +capability to Kaleidoscope, which will let the user round out the set of +operators that are supported.

+ +

The point of going into user-defined operators in a tutorial like this is to +show the power and flexibility of using a hand-written parser. Thus far, the parser +we have been implementing uses recursive descent for most parts of the grammar and +operator precedence parsing for the expressions. See Chapter 2 for details. Without using operator +precedence parsing, it would be very difficult to allow the programmer to +introduce new operators into the grammar: the grammar is dynamically extensible +as the JIT runs.

+ +

The two specific features we'll add are programmable unary operators (right +now, Kaleidoscope has no unary operators at all) as well as binary operators. +An example of this is:

+ +
+
+# Logical unary not.
+def unary!(v)
+  if v then
+    0
+  else
+    1;
+
+# Define > with the same precedence as <.
+def binary> 10 (LHS RHS)
+  RHS < LHS;
+
+# Binary "logical or", (note that it does not "short circuit")
+def binary| 5 (LHS RHS)
+  if LHS then
+    1
+  else if RHS then
+    1
+  else
+    0;
+
+# Define = with slightly lower precedence than relationals.
+def binary= 9 (LHS RHS)
+  !(LHS < RHS | LHS > RHS);
+
+
+ +

Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement significant +parts of the language in the library!

+ +

We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators.

+ +
+ + + + + +
+ +

Adding support for user-defined binary operators is pretty simple with our +current framework. We'll first add support for the unary/binary keywords:

+ +
+
+enum Token {
+  ...
+  // operators
+  tok_binary = -11, tok_unary = -12
+};
+...
+static int gettok() {
+...
+    if (IdentifierStr == "for") return tok_for;
+    if (IdentifierStr == "in") return tok_in;
+    if (IdentifierStr == "binary") return tok_binary;
+    if (IdentifierStr == "unary") return tok_unary;
+    return tok_identifier;
+
+
+ +

This just adds lexer support for the unary and binary keywords, like we +did in previous chapters. One nice thing +about our current AST, is that we represent binary operators with full generalisation +by using their ASCII code as the opcode. For our extended operators, we'll use this +same representation, so we don't need any new AST or parser support.

+ +

On the other hand, we have to be able to represent the definitions of these +new operators, in the "def binary| 5" part of the function definition. In our +grammar so far, the "name" for the function definition is parsed as the +"prototype" production and into the PrototypeAST AST node. To +represent our new user-defined operators as prototypes, we have to extend +the PrototypeAST AST node like this:

+ +
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its argument names as well as if it is an operator.
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+  bool isOperator;
+  unsigned Precedence;  // Precedence if a binary op.
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
+               bool isoperator = false, unsigned prec = 0)
+  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
+  
+  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
+  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
+  
+  char getOperatorName() const {
+    assert(isUnaryOp() || isBinaryOp());
+    return Name[Name.size()-1];
+  }
+  
+  unsigned getBinaryPrecedence() const { return Precedence; }
+  
+  Function *Codegen();
+};
+
+
+ +

Basically, in addition to knowing a name for the prototype, we now keep track +of whether it was an operator, and if it was, what precedence level the operator +is at. The precedence is only used for binary operators (as you'll see below, +it just doesn't apply for unary operators). Now that we have a way to represent +the prototype for a user-defined operator, we need to parse it:

+ +
+
+/// prototype
+///   ::= id '(' id* ')'
+///   ::= binary LETTER number? (id, id)
+static PrototypeAST *ParsePrototype() {
+  std::string FnName;
+  
+  unsigned Kind = 0;  // 0 = identifier, 1 = unary, 2 = binary.
+  unsigned BinaryPrecedence = 30;
+  
+  switch (CurTok) {
+  default:
+    return ErrorP("Expected function name in prototype");
+  case tok_identifier:
+    FnName = IdentifierStr;
+    Kind = 0;
+    getNextToken();
+    break;
+  case tok_binary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected binary operator");
+    FnName = "binary";
+    FnName += (char)CurTok;
+    Kind = 2;
+    getNextToken();
+    
+    // Read the precedence if present.
+    if (CurTok == tok_number) {
+      if (NumVal < 1 || NumVal > 100)
+        return ErrorP("Invalid precedecnce: must be 1..100");
+      BinaryPrecedence = (unsigned)NumVal;
+      getNextToken();
+    }
+    break;
+  }
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  // Verify right number of names for operator.
+  if (Kind && ArgNames.size() != Kind)
+    return ErrorP("Invalid number of operands for operator");
+  
+  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
+}
+
+
+ +

This is all fairly straightforward parsing code, and we have already seen +a lot of similar code in the past. One interesting part about the code above is +the couple lines that set up FnName for binary operators. This builds names +like "binary@" for a newly defined "@" operator. This then takes advantage of the +fact that symbol names in the LLVM symbol table are allowed to have any character in +them, including embedded nul characters.

+ +

The next interesting thing to add, is codegen support for these binary operators. +Given our current structure, this is a simple addition of a default case for our +existing binary operator node:

+ +
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: break;
+  }
+  
+  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
+  // a call to it.
+  Function *F = TheModule->getFunction(std::string("binary")+Op);
+  assert(F && "binary operator not found!");
+  
+  Value *Ops[] = { L, R };
+  return Builder.CreateCall(F, Ops, Ops+2, "binop");
+}
+
+
+
+ +

As you can see above, the new code is actually really simple. It just does +a lookup for the appropriate operator in the symbol table and generates a +function call to it. Since user-defined operators are just built as normal +functions (because the "prototype" boils down to a function with the right +name) everything falls into place.

+ +

The final piece of code we are missing, is a bit of top-level magic:

+ +
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // If this is an operator, install it.
+  if (Proto->isBinaryOp())
+    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+    ...
+
+
+ +

Basically, before codegening a function, if it is a user-defined operator, we +register it in the precedence table. This allows the binary operator parsing +logic we already have in place to handle it. Since we are working on a fully-general operator precedence parser, this is all we need to do to "extend the grammar".

+ +

Now we have useful user-defined binary operators. This builds a lot +on the previous framework we built for other operators. Adding unary operators +is a bit more challenging, because we don't have any framework for it yet - lets +see what it takes.

+ +
+ + + + + +
+ +

Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added simple +support for the 'unary' keyword to the lexer. In addition to that, we need an +AST node:

+ +
+
+/// UnaryExprAST - Expression class for a unary operator.
+class UnaryExprAST : public ExprAST {
+  char Opcode;
+  ExprAST *Operand;
+public:
+  UnaryExprAST(char opcode, ExprAST *operand) 
+    : Opcode(opcode), Operand(operand) {}
+  virtual Value *Codegen();
+};
+
+
+ +

This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, we +need to add the parsing logic. Parsing a unary operator is pretty simple: we'll +add a new function to do it:

+ +
+
+/// unary
+///   ::= primary
+///   ::= '!' unary
+static ExprAST *ParseUnary() {
+  // If the current token is not an operator, it must be a primary expr.
+  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
+    return ParsePrimary();
+  
+  // If this is a unary operator, read it.
+  int Opc = CurTok;
+  getNextToken();
+  if (ExprAST *Operand = ParseUnary())
+    return new UnaryExprAST(Opc, Operand);
+  return 0;
+}
+
+
+ +

The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a prefix and +parse the remaining piece as another unary operator. This allows us to handle +multiple unary operators (e.g. "!!x"). Note that unary operators can't have +ambiguous parses like binary operators can, so there is no need for precedence +information.

+ +

The problem with this function, is that we need to call ParseUnary from somewhere. +To do this, we change previous callers of ParsePrimary to call ParseUnary +instead:

+ +
+
+/// binoprhs
+///   ::= ('+' unary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  ...
+    // Parse the unary expression after the binary operator.
+    ExprAST *RHS = ParseUnary();
+    if (!RHS) return 0;
+  ...
+}
+/// expression
+///   ::= unary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParseUnary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+
+ +

With these two simple changes, we are now able to parse unary operators and build the +AST for them. Next up, we need to add parser support for prototypes, to parse +the unary operator prototype. We extend the binary operator code above +with:

+ +
+
+/// prototype
+///   ::= id '(' id* ')'
+///   ::= binary LETTER number? (id, id)
+///   ::= unary LETTER (id)
+static PrototypeAST *ParsePrototype() {
+  std::string FnName;
+  
+  unsigned Kind = 0;  // 0 = identifier, 1 = unary, 2 = binary.
+  unsigned BinaryPrecedence = 30;
+  
+  switch (CurTok) {
+  default:
+    return ErrorP("Expected function name in prototype");
+  case tok_identifier:
+    FnName = IdentifierStr;
+    Kind = 0;
+    getNextToken();
+    break;
+  case tok_unary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected unary operator");
+    FnName = "unary";
+    FnName += (char)CurTok;
+    Kind = 1;
+    getNextToken();
+    break;
+  case tok_binary:
+    ...
+
+
+ +

As with binary operators, we name unary operators with a name that includes +the operator character. This assists us at code generation time. Speaking of, +the final piece we need to add is codegen support for unary operators. It looks +like this:

+ +
+
+Value *UnaryExprAST::Codegen() {
+  Value *OperandV = Operand->Codegen();
+  if (OperandV == 0) return 0;
+  
+  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
+  if (F == 0)
+    return ErrorV("Unknown unary operator");
+  
+  return Builder.CreateCall(F, OperandV, "unop");
+}
+
+
+ +

This code is similar to, but simpler than, the code for binary operators. It +is simpler primarily because it doesn't need to handle any predefined operators. +

+ +
+ + + + + +
+ +

It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With this, we +can do a lot of interesting things, including I/O, math, and a bunch of other +things. For example, we can now add a nice sequencing operator (printd is +defined to print out the specified value and a newline):

+ +
+
+ready> extern printd(x);
+Read extern: declare double @printd(double)
+ready> def binary : 1 (x y) 0;  # Low-precedence operator that ignores operands.
+..
+ready> printd(123) : printd(456) : printd(789);
+123.000000
+456.000000
+789.000000
+Evaluated to 0.000000
+
+
+ +

We can also define a bunch of other "primitive" operations, such as:

+ +
+
+# Logical unary not.
+def unary!(v)
+  if v then
+    0
+  else
+    1;
+    
+# Unary negate.
+def unary-(v)
+  0-v;
+
+# Define > with the same precedence as <.
+def binary> 10 (LHS RHS)
+  RHS < LHS;
+
+# Binary logical or, which does not short circuit. 
+def binary| 5 (LHS RHS)
+  if LHS then
+    1
+  else if RHS then
+    1
+  else
+    0;
+
+# Binary logical and, which does not short circuit. 
+def binary& 6 (LHS RHS)
+  if !LHS then
+    0
+  else
+    !!RHS;
+
+# Define = with slightly lower precedence than relationals.
+def binary = 9 (LHS RHS)
+  !(LHS < RHS | LHS > RHS);
+
+
+
+ + +

Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character whose +"density" reflects the value passed in: the lower the value, the denser the +character:

+ +
+
+ready>
+
+extern putchard(char)
+def printdensity(d)
+  if d > 8 then
+    putchard(32)  # ' '
+  else if d > 4 then
+    putchard(46)  # '.'
+  else if d > 2 then
+    putchard(43)  # '+'
+  else
+    putchard(42); # '*'
+...
+ready> printdensity(1): printdensity(2): printdensity(3) : 
+          printdensity(4): printdensity(5): printdensity(9): putchard(10);
+*++.. 
+Evaluated to 0.000000
+
+
+ +

Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves for the +number of iterations it takes a function in the complex plane to +converge:

+ +
+
+# determine whether the specific location diverges.
+# Solve for z = z^2 + c in the complex plane.
+def mandleconverger(real imag iters creal cimag)
+  if iters > 255 | (real*real + imag*imag > 4) then
+    iters
+  else
+    mandleconverger(real*real - imag*imag + creal,
+                    2*real*imag + cimag,
+                    iters+1, creal, cimag);
+
+# return the number of iterations required for the iteration to escape
+def mandleconverge(real imag)
+  mandleconverger(real, imag, 0, real, imag);
+
+
+ +

This "z = z2 + c" function is a beautiful little creature that is the basis +for computation of the Mandelbrot Set. Our +mandelconverge function returns the number of iterations that it takes +for a complex orbit to escape, saturating to 255. This is not a very useful +function by itself, but if you plot its value over a two-dimensional plane, +you can see the Mandelbrot set. Given that we are limited to using putchard +here, our amazing graphical output is limited, but we can whip together +something using the density plotter above:

+ +
+
+# compute and plot the mandlebrot set with the specified 2 dimensional range
+# info.
+def mandelhelp(xmin xmax xstep   ymin ymax ystep)
+  for y = ymin, y < ymax, ystep in (
+    (for x = xmin, x < xmax, xstep in
+       printdensity(mandleconverge(x,y)))
+    : putchard(10)
+  )
+ 
+# mandel - This is a convenient helper function for ploting the mandelbrot set
+# from the specified position with the specified Magnification.
+def mandel(realstart imagstart realmag imagmag) 
+  mandelhelp(realstart, realstart+realmag*78, realmag,
+             imagstart, imagstart+imagmag*40, imagmag);
+
+
+ +

Given this, we can try plotting out the mandlebrot set! Lets try it out:

+ +
+
+ready> mandel(-2.3, -1.3, 0.05, 0.07);
+*******************************+++++++++++*************************************
+*************************+++++++++++++++++++++++*******************************
+**********************+++++++++++++++++++++++++++++****************************
+*******************+++++++++++++++++++++.. ...++++++++*************************
+*****************++++++++++++++++++++++.... ...+++++++++***********************
+***************+++++++++++++++++++++++.....   ...+++++++++*********************
+**************+++++++++++++++++++++++....     ....+++++++++********************
+*************++++++++++++++++++++++......      .....++++++++*******************
+************+++++++++++++++++++++.......       .......+++++++******************
+***********+++++++++++++++++++....                ... .+++++++*****************
+**********+++++++++++++++++.......                     .+++++++****************
+*********++++++++++++++...........                    ...+++++++***************
+********++++++++++++............                      ...++++++++**************
+********++++++++++... ..........                        .++++++++**************
+*******+++++++++.....                                   .+++++++++*************
+*******++++++++......                                  ..+++++++++*************
+*******++++++.......                                   ..+++++++++*************
+*******+++++......                                     ..+++++++++*************
+*******.... ....                                      ...+++++++++*************
+*******.... .                                         ...+++++++++*************
+*******+++++......                                    ...+++++++++*************
+*******++++++.......                                   ..+++++++++*************
+*******++++++++......                                   .+++++++++*************
+*******+++++++++.....                                  ..+++++++++*************
+********++++++++++... ..........                        .++++++++**************
+********++++++++++++............                      ...++++++++**************
+*********++++++++++++++..........                     ...+++++++***************
+**********++++++++++++++++........                     .+++++++****************
+**********++++++++++++++++++++....                ... ..+++++++****************
+***********++++++++++++++++++++++.......       .......++++++++*****************
+************+++++++++++++++++++++++......      ......++++++++******************
+**************+++++++++++++++++++++++....      ....++++++++********************
+***************+++++++++++++++++++++++.....   ...+++++++++*********************
+*****************++++++++++++++++++++++....  ...++++++++***********************
+*******************+++++++++++++++++++++......++++++++*************************
+*********************++++++++++++++++++++++.++++++++***************************
+*************************+++++++++++++++++++++++*******************************
+******************************+++++++++++++************************************
+*******************************************************************************
+*******************************************************************************
+*******************************************************************************
+Evaluated to 0.000000
+ready> mandel(-2, -1, 0.02, 0.04);
+**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
+***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
+*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
+***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
+**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
+************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
+***********++++++++++++++++++++++++++++++++++++++++++++++++++........        . 
+**********++++++++++++++++++++++++++++++++++++++++++++++.............          
+********+++++++++++++++++++++++++++++++++++++++++++..................          
+*******+++++++++++++++++++++++++++++++++++++++.......................          
+******+++++++++++++++++++++++++++++++++++...........................           
+*****++++++++++++++++++++++++++++++++............................              
+*****++++++++++++++++++++++++++++...............................               
+****++++++++++++++++++++++++++......   .........................               
+***++++++++++++++++++++++++.........     ......    ...........                 
+***++++++++++++++++++++++............                                          
+**+++++++++++++++++++++..............                                          
+**+++++++++++++++++++................                                          
+*++++++++++++++++++.................                                           
+*++++++++++++++++............ ...                                              
+*++++++++++++++..............                                                  
+*+++....++++................                                                   
+*..........  ...........                                                       
+*                                                                              
+*..........  ...........                                                       
+*+++....++++................                                                   
+*++++++++++++++..............                                                  
+*++++++++++++++++............ ...                                              
+*++++++++++++++++++.................                                           
+**+++++++++++++++++++................                                          
+**+++++++++++++++++++++..............                                          
+***++++++++++++++++++++++............                                          
+***++++++++++++++++++++++++.........     ......    ...........                 
+****++++++++++++++++++++++++++......   .........................               
+*****++++++++++++++++++++++++++++...............................               
+*****++++++++++++++++++++++++++++++++............................              
+******+++++++++++++++++++++++++++++++++++...........................           
+*******+++++++++++++++++++++++++++++++++++++++.......................          
+********+++++++++++++++++++++++++++++++++++++++++++..................          
+Evaluated to 0.000000
+ready> mandel(-0.9, -1.4, 0.02, 0.03);
+*******************************************************************************
+*******************************************************************************
+*******************************************************************************
+**********+++++++++++++++++++++************************************************
+*+++++++++++++++++++++++++++++++++++++++***************************************
++++++++++++++++++++++++++++++++++++++++++++++**********************************
+++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
++++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
++++++++++++++++++++++++++++++++....   ......+++++++++++++++++++****************
++++++++++++++++++++++++++++++.......  ........+++++++++++++++++++**************
+++++++++++++++++++++++++++++........   ........++++++++++++++++++++************
++++++++++++++++++++++++++++.........     ..  ...+++++++++++++++++++++**********
+++++++++++++++++++++++++++...........        ....++++++++++++++++++++++********
+++++++++++++++++++++++++.............       .......++++++++++++++++++++++******
++++++++++++++++++++++++.............        ........+++++++++++++++++++++++****
+++++++++++++++++++++++...........           ..........++++++++++++++++++++++***
+++++++++++++++++++++...........                .........++++++++++++++++++++++*
+++++++++++++++++++............                  ...........++++++++++++++++++++
+++++++++++++++++...............                 .............++++++++++++++++++
+++++++++++++++.................                 ...............++++++++++++++++
+++++++++++++..................                  .................++++++++++++++
++++++++++..................                      .................+++++++++++++
+++++++........        .                               .........  ..++++++++++++
+++............                                         ......    ....++++++++++
+..............                                                    ...++++++++++
+..............                                                    ....+++++++++
+..............                                                    .....++++++++
+.............                                                    ......++++++++
+...........                                                     .......++++++++
+.........                                                       ........+++++++
+.........                                                       ........+++++++
+.........                                                           ....+++++++
+........                                                             ...+++++++
+.......                                                              ...+++++++
+                                                                    ....+++++++
+                                                                   .....+++++++
+                                                                    ....+++++++
+                                                                    ....+++++++
+                                                                    ....+++++++
+Evaluated to 0.000000
+ready> ^D
+
+
+ +

At this point, you may be starting to realize that Kaleidoscope is a real +and powerful language. It may not be self-similar :), but it can be used to +plot things that are!

+ +

With this, we conclude the "adding user-defined operators" chapter of the +tutorial. We have successfully augmented our language, adding the ability to extend the +language in the library, and we have shown how this can be used to build a simple but +interesting end-user application in Kaleidoscope. At this point, Kaleidoscope +can build a variety of applications that are functional and can call functions +with side-effects, but it can't actually define and mutate a variable itself. +

+ +

Strikingly, variable mutation is an important feature of some +languages, and it is not at all obvious how to add +support for mutable variables without having to add an "SSA construction" +phase to your front-end. In the next chapter, we will describe how you can +add variable mutation without building SSA in your front-end.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

+ +
+
+   # Compile
+   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+   # Run
+   ./toy
+
+
+ +

Here is the code:

+ +
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5,
+  
+  // control
+  tok_if = -6, tok_then = -7, tok_else = -8,
+  tok_for = -9, tok_in = -10,
+  
+  // operators
+  tok_binary = -11, tok_unary = -12
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    if (IdentifierStr == "if") return tok_if;
+    if (IdentifierStr == "then") return tok_then;
+    if (IdentifierStr == "else") return tok_else;
+    if (IdentifierStr == "for") return tok_for;
+    if (IdentifierStr == "in") return tok_in;
+    if (IdentifierStr == "binary") return tok_binary;
+    if (IdentifierStr == "unary") return tok_unary;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+  virtual Value *Codegen();
+};
+
+/// UnaryExprAST - Expression class for a unary operator.
+class UnaryExprAST : public ExprAST {
+  char Opcode;
+  ExprAST *Operand;
+public:
+  UnaryExprAST(char opcode, ExprAST *operand) 
+    : Opcode(opcode), Operand(operand) {}
+  virtual Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+  virtual Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+  virtual Value *Codegen();
+};
+
+/// IfExprAST - Expression class for if/then/else.
+class IfExprAST : public ExprAST {
+  ExprAST *Cond, *Then, *Else;
+public:
+  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
+  : Cond(cond), Then(then), Else(_else) {}
+  virtual Value *Codegen();
+};
+
+/// ForExprAST - Expression class for for/in.
+class ForExprAST : public ExprAST {
+  std::string VarName;
+  ExprAST *Start, *End, *Step, *Body;
+public:
+  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
+             ExprAST *step, ExprAST *body)
+    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
+  virtual Value *Codegen();
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes), as well as if it is an operator.
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+  bool isOperator;
+  unsigned Precedence;  // Precedence if a binary op.
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
+               bool isoperator = false, unsigned prec = 0)
+  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
+  
+  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
+  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
+  
+  char getOperatorName() const {
+    assert(isUnaryOp() || isBinaryOp());
+    return Name[Name.size()-1];
+  }
+  
+  unsigned getBinaryPrecedence() const { return Precedence; }
+  
+  Function *Codegen();
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+  Function *Codegen();
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// ifexpr ::= 'if' expression 'then' expression 'else' expression
+static ExprAST *ParseIfExpr() {
+  getNextToken();  // eat the if.
+  
+  // condition.
+  ExprAST *Cond = ParseExpression();
+  if (!Cond) return 0;
+  
+  if (CurTok != tok_then)
+    return Error("expected then");
+  getNextToken();  // eat the then
+  
+  ExprAST *Then = ParseExpression();
+  if (Then == 0) return 0;
+  
+  if (CurTok != tok_else)
+    return Error("expected else");
+  
+  getNextToken();
+  
+  ExprAST *Else = ParseExpression();
+  if (!Else) return 0;
+  
+  return new IfExprAST(Cond, Then, Else);
+}
+
+/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
+static ExprAST *ParseForExpr() {
+  getNextToken();  // eat the for.
+
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after for");
+  
+  std::string IdName = IdentifierStr;
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '=')
+    return Error("expected '=' after for");
+  getNextToken();  // eat '='.
+  
+  
+  ExprAST *Start = ParseExpression();
+  if (Start == 0) return 0;
+  if (CurTok != ',')
+    return Error("expected ',' after for start value");
+  getNextToken();
+  
+  ExprAST *End = ParseExpression();
+  if (End == 0) return 0;
+  
+  // The step value is optional.
+  ExprAST *Step = 0;
+  if (CurTok == ',') {
+    getNextToken();
+    Step = ParseExpression();
+    if (Step == 0) return 0;
+  }
+  
+  if (CurTok != tok_in)
+    return Error("expected 'in' after for");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+
+  return new ForExprAST(IdName, Start, End, Step, Body);
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+///   ::= ifexpr
+///   ::= forexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  case tok_if:         return ParseIfExpr();
+  case tok_for:        return ParseForExpr();
+  }
+}
+
+/// unary
+///   ::= primary
+///   ::= '!' unary
+static ExprAST *ParseUnary() {
+  // If the current token is not an operator, it must be a primary expr.
+  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
+    return ParsePrimary();
+  
+  // If this is a unary operator, read it.
+  int Opc = CurTok;
+  getNextToken();
+  if (ExprAST *Operand = ParseUnary())
+    return new UnaryExprAST(Opc, Operand);
+  return 0;
+}
+
+/// binoprhs
+///   ::= ('+' unary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the unary expression after the binary operator.
+    ExprAST *RHS = ParseUnary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= unary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParseUnary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+///   ::= binary LETTER number? (id, id)
+///   ::= unary LETTER (id)
+static PrototypeAST *ParsePrototype() {
+  std::string FnName;
+  
+  unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
+  unsigned BinaryPrecedence = 30;
+  
+  switch (CurTok) {
+  default:
+    return ErrorP("Expected function name in prototype");
+  case tok_identifier:
+    FnName = IdentifierStr;
+    Kind = 0;
+    getNextToken();
+    break;
+  case tok_unary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected unary operator");
+    FnName = "unary";
+    FnName += (char)CurTok;
+    Kind = 1;
+    getNextToken();
+    break;
+  case tok_binary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected binary operator");
+    FnName = "binary";
+    FnName += (char)CurTok;
+    Kind = 2;
+    getNextToken();
+    
+    // Read the precedence if present.
+    if (CurTok == tok_number) {
+      if (NumVal < 1 || NumVal > 100)
+        return ErrorP("Invalid precedecnce: must be 1..100");
+      BinaryPrecedence = (unsigned)NumVal;
+      getNextToken();
+    }
+    break;
+  }
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  // Verify right number of names for operator.
+  if (Kind && ArgNames.size() != Kind)
+    return ErrorP("Invalid number of operands for operator");
+  
+  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, Value*> NamedValues;
+static FunctionPassManager *TheFPM;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  return V ? V : ErrorV("Unknown variable name");
+}
+
+Value *UnaryExprAST::Codegen() {
+  Value *OperandV = Operand->Codegen();
+  if (OperandV == 0) return 0;
+  
+  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
+  if (F == 0)
+    return ErrorV("Unknown unary operator");
+  
+  return Builder.CreateCall(F, OperandV, "unop");
+}
+
+Value *BinaryExprAST::Codegen() {
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: break;
+  }
+  
+  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
+  // a call to it.
+  Function *F = TheModule->getFunction(std::string("binary")+Op);
+  assert(F && "binary operator not found!");
+  
+  Value *Ops[] = { L, R };
+  return Builder.CreateCall(F, Ops, Ops+2, "binop");
+}
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Value *IfExprAST::Codegen() {
+  Value *CondV = Cond->Codegen();
+  if (CondV == 0) return 0;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  CondV = Builder.CreateFCmpONE(CondV, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                "ifcond");
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  
+  // Create blocks for the then and else cases.  Insert the 'then' block at the
+  // end of the function.
+  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
+  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
+  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
+  
+  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
+  
+  // Emit then value.
+  Builder.SetInsertPoint(ThenBB);
+  
+  Value *ThenV = Then->Codegen();
+  if (ThenV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
+  ThenBB = Builder.GetInsertBlock();
+  
+  // Emit else block.
+  TheFunction->getBasicBlockList().push_back(ElseBB);
+  Builder.SetInsertPoint(ElseBB);
+  
+  Value *ElseV = Else->Codegen();
+  if (ElseV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
+  ElseBB = Builder.GetInsertBlock();
+  
+  // Emit merge block.
+  TheFunction->getBasicBlockList().push_back(MergeBB);
+  Builder.SetInsertPoint(MergeBB);
+  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+                                  "iftmp");
+  
+  PN->addIncoming(ThenV, ThenBB);
+  PN->addIncoming(ElseV, ElseBB);
+  return PN;
+}
+
+Value *ForExprAST::Codegen() {
+  // Output this as:
+  //   ...
+  //   start = startexpr
+  //   goto loop
+  // loop: 
+  //   variable = phi [start, loopheader], [nextvariable, loopend]
+  //   ...
+  //   bodyexpr
+  //   ...
+  // loopend:
+  //   step = stepexpr
+  //   nextvariable = variable + step
+  //   endcond = endexpr
+  //   br endcond, loop, endloop
+  // outloop:
+  
+  // Emit the start code first, without 'variable' in scope.
+  Value *StartVal = Start->Codegen();
+  if (StartVal == 0) return 0;
+  
+  // Make the new basic block for the loop header, inserting after current
+  // block.
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  BasicBlock *PreheaderBB = Builder.GetInsertBlock();
+  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
+  
+  // Insert an explicit fall through from the current block to the LoopBB.
+  Builder.CreateBr(LoopBB);
+
+  // Start insertion in LoopBB.
+  Builder.SetInsertPoint(LoopBB);
+  
+  // Start the PHI node with an entry for Start.
+  PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str());
+  Variable->addIncoming(StartVal, PreheaderBB);
+  
+  // Within the loop, the variable is defined equal to the PHI node.  If it
+  // shadows an existing variable, we have to restore it, so save it now.
+  Value *OldVal = NamedValues[VarName];
+  NamedValues[VarName] = Variable;
+  
+  // Emit the body of the loop.  This, like any other expr, can change the
+  // current BB.  Note that we ignore the value computed by the body, but don't
+  // allow an error.
+  if (Body->Codegen() == 0)
+    return 0;
+  
+  // Emit the step value.
+  Value *StepVal;
+  if (Step) {
+    StepVal = Step->Codegen();
+    if (StepVal == 0) return 0;
+  } else {
+    // If not specified, use 1.0.
+    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
+  }
+  
+  Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
+
+  // Compute the end condition.
+  Value *EndCond = End->Codegen();
+  if (EndCond == 0) return EndCond;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  EndCond = Builder.CreateFCmpONE(EndCond, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                  "loopcond");
+  
+  // Create the "after loop" block and insert it.
+  BasicBlock *LoopEndBB = Builder.GetInsertBlock();
+  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
+  
+  // Insert the conditional branch into the end of LoopEndBB.
+  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
+  
+  // Any new code will be inserted in AfterBB.
+  Builder.SetInsertPoint(AfterBB);
+  
+  // Add a new entry to the PHI node for the backedge.
+  Variable->addIncoming(NextVar, LoopEndBB);
+  
+  // Restore the unshadowed variable.
+  if (OldVal)
+    NamedValues[VarName] = OldVal;
+  else
+    NamedValues.erase(VarName);
+
+  
+  // for expr always returns 0.0.
+  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
+}
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+  
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+    
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+  
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx) {
+    AI->setName(Args[Idx]);
+    
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = AI;
+  }
+  
+  return F;
+}
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // If this is an operator, install it.
+  if (Proto->isBinaryOp())
+    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    // Optimize the function.
+    TheFPM->run(*TheFunction);
+    
+    return TheFunction;
+  }
+  
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+
+  if (Proto->isBinaryOp())
+    BinopPrecedence.erase(Proto->getOperatorName());
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+static ExecutionEngine *TheExecutionEngine;
+
+static void HandleDefinition() {
+  if (FunctionAST *F = ParseDefinition()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read function definition:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (PrototypeAST *P = ParseExtern()) {
+    if (Function *F = P->Codegen()) {
+      fprintf(stderr, "Read extern: ");
+      F->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      // JIT the function, returning a function pointer.
+      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+      
+      // Cast it to the right type (takes no arguments, returns a double) so we
+      // can call it as a native function.
+      double (*FP)() = (double (*)())(intptr_t)FPtr;
+      fprintf(stderr, "Evaluated to %f\n", FP());
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+/// printd - printf that takes a double prints it as "%f\n", returning 0.
+extern "C" 
+double printd(double X) {
+  printf("%f\n", X);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  InitializeNativeTarget();
+  LLVMContext &Context = getGlobalContext();
+
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Make the module, which holds all the code.
+  TheModule = new Module("my cool jit", Context);
+
+  // Create the JIT.  This takes ownership of the module.
+  std::string ErrStr;
+  TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
+  if (!TheExecutionEngine) {
+    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
+    exit(1);
+  }
+
+  FunctionPassManager OurFPM(TheModule);
+
+  // Set up the optimizer pipeline.  Start with registering info about how the
+  // target lays out data structures.
+  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+  // Provide basic AliasAnalysis support for GVN.
+  OurFPM.add(createBasicAliasAnalysisPass());
+  // Do simple "peephole" optimizations and bit-twiddling optzns.
+  OurFPM.add(createInstructionCombiningPass());
+  // Reassociate expressions.
+  OurFPM.add(createReassociatePass());
+  // Eliminate Common SubExpressions.
+  OurFPM.add(createGVNPass());
+  // Simplify the control flow graph (deleting unreachable blocks, etc).
+  OurFPM.add(createCFGSimplificationPass());
+
+  OurFPM.doInitialization();
+
+  // Set the global so the code gen can use this.
+  TheFPM = &OurFPM;
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  TheFPM = 0;
+
+  // Print out all of the generated code.
+  TheModule->dump();
+
+  return 0;
+}
+
+
+ +Next: Extending the language: mutable variables / SSA construction +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl7.html b/final/docs/tutorial/LangImpl7.html new file mode 100644 index 00000000000..ddddc423209 --- /dev/null +++ b/final/docs/tutorial/LangImpl7.html @@ -0,0 +1,2167 @@ + + + + + Kaleidoscope: Extending the Language: Mutable Variables / SSA + construction + + + + + + + +
Kaleidoscope: Extending the Language: Mutable Variables
+ + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to Chapter 7 of the "Implementing a language +with LLVM" tutorial. In chapters 1 through 6, we've built a very +respectable, albeit simple, functional +programming language. In our journey, we learned some parsing techniques, +how to build and represent an AST, how to build LLVM IR, and how to optimize +the resultant code as well as JIT compile it.

+ +

While Kaleidoscope is interesting as a functional language, the fact that it +is functional makes it "too easy" to generate LLVM IR for it. In particular, a +functional language makes it very easy to build LLVM IR directly in SSA form. +Since LLVM requires that the input code be in SSA form, this is a very nice +property and it is often unclear to newcomers how to generate code for an +imperative language with mutable variables.

+ +

The short (and happy) summary of this chapter is that there is no need for +your front-end to build SSA form: LLVM provides highly tuned and well tested +support for this, though the way it works is a bit unexpected for some.

+ +
+ + + + + +
+ +

+To understand why mutable variables cause complexities in SSA construction, +consider this extremely simple C example: +

+ +
+
+int G, H;
+int test(_Bool Condition) {
+  int X;
+  if (Condition)
+    X = G;
+  else
+    X = H;
+  return X;
+}
+
+
+ +

In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values for X +before the return instruction, a PHI node is inserted to merge the two values. +The LLVM IR that we want for this example looks like this:

+ +
+
+@G = weak global i32 0   ; type of @G is i32*
+@H = weak global i32 0   ; type of @H is i32*
+
+define i32 @test(i1 %Condition) {
+entry:
+	br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+	%X.0 = load i32* @G
+	br label %cond_next
+
+cond_false:
+	%X.1 = load i32* @H
+	br label %cond_next
+
+cond_next:
+	%X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+	ret i32 %X.2
+}
+
+
+ +

In this example, the loads from the G and H global variables are explicit in +the LLVM IR, and they live in the then/else branches of the if statement +(cond_true/cond_false). In order to merge the incoming values, the X.2 phi node +in the cond_next block selects the right value to use based on where control +flow is coming from: if control flow comes from the cond_false block, X.2 gets +the value of X.1. Alternatively, if control flow comes from cond_true, it gets +the value of X.0. The intent of this chapter is not to explain the details of +SSA form. For more information, see one of the many online +references.

+ +

The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +requires that its IR be in SSA form: there is no "non-ssa" mode for it. +However, SSA construction requires non-trivial algorithms and data structures, +so it is inconvenient and wasteful for every front-end to have to reproduce this +logic.

+ +
+ + + + + +
+ +

The 'trick' here is that while LLVM does require all register values to be +in SSA form, it does not require (or permit) memory objects to be in SSA form. +In the example above, note that the loads from G and H are direct accesses to +G and H: they are not renamed or versioned. This differs from some other +compiler systems, which do try to version memory objects. In LLVM, instead of +encoding dataflow analysis of memory into the LLVM IR, it is handled with Analysis Passes which are computed on +demand.

+ +

+With this in mind, the high-level idea is that we want to make a stack variable +(which lives in memory, because it is on the stack) for each mutable object in +a function. To take advantage of this trick, we need to talk about how LLVM +represents stack variables. +

+ +

In LLVM, all memory accesses are explicit with load/store instructions, and +it is carefully designed not to have (or need) an "address-of" operator. Notice +how the type of the @G/@H global variables is actually "i32*" even though the +variable is defined as "i32". What this means is that @G defines space +for an i32 in the global data area, but its name actually refers to the +address for that space. Stack variables work the same way, except that instead of +being declared with global variable definitions, they are declared with the +LLVM alloca instruction:

+ +
+
+define i32 @example() {
+entry:
+	%X = alloca i32           ; type of %X is i32*.
+	...
+	%tmp = load i32* %X       ; load the stack value %X from the stack.
+	%tmp2 = add i32 %tmp, 1   ; increment it
+	store i32 %tmp2, i32* %X  ; store it back
+	...
+
+
+ +

This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca instruction is +fully general: you can pass the address of the stack slot to functions, you can +store it in other variables, etc. In our example above, we could rewrite the +example to use the alloca technique to avoid using a PHI node:

+ +
+
+@G = weak global i32 0   ; type of @G is i32*
+@H = weak global i32 0   ; type of @H is i32*
+
+define i32 @test(i1 %Condition) {
+entry:
+	%X = alloca i32           ; type of %X is i32*.
+	br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+	%X.0 = load i32* @G
+        store i32 %X.0, i32* %X   ; Update X
+	br label %cond_next
+
+cond_false:
+	%X.1 = load i32* @H
+        store i32 %X.1, i32* %X   ; Update X
+	br label %cond_next
+
+cond_next:
+	%X.2 = load i32* %X       ; Read X
+	ret i32 %X.2
+}
+
+
+ +

With this, we have discovered a way to handle arbitrary mutable variables +without the need to create Phi nodes at all:

+ +
    +
  1. Each mutable variable becomes a stack allocation.
  2. +
  3. Each read of the variable becomes a load from the stack.
  4. +
  5. Each update of the variable becomes a store to the stack.
  6. +
  7. Taking the address of a variable just uses the stack address directly.
  8. +
+ +

While this solution has solved our immediate problem, it introduced another +one: we have now apparently introduced a lot of stack traffic for very simple +and common operations, a major performance problem. Fortunately for us, the +LLVM optimizer has a highly-tuned optimization pass named "mem2reg" that handles +this case, promoting allocas like this into SSA registers, inserting Phi nodes +as appropriate. If you run this example through the pass, for example, you'll +get:

+ +
+
+$ llvm-as < example.ll | opt -mem2reg | llvm-dis
+@G = weak global i32 0
+@H = weak global i32 0
+
+define i32 @test(i1 %Condition) {
+entry:
+	br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+	%X.0 = load i32* @G
+	br label %cond_next
+
+cond_false:
+	%X.1 = load i32* @H
+	br label %cond_next
+
+cond_next:
+	%X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+	ret i32 %X.01
+}
+
+
+ +

The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations that speed +up (very common) degenerate cases. The mem2reg optimization pass is the answer to dealing +with mutable variables, and we highly recommend that you depend on it. Note that +mem2reg only works on variables in certain circumstances:

+ +
    +
  1. mem2reg is alloca-driven: it looks for allocas and if it can handle them, it +promotes them. It does not apply to global variables or heap allocations.
  2. + +
  3. mem2reg only looks for alloca instructions in the entry block of the +function. Being in the entry block guarantees that the alloca is only executed +once, which makes analysis simpler.
  4. + +
  5. mem2reg only promotes allocas whose uses are direct loads and stores. If +the address of the stack object is passed to a function, or if any funny pointer +arithmetic is involved, the alloca will not be promoted.
  6. + +
  7. mem2reg only works on allocas of first class +values (such as pointers, scalars and vectors), and only if the array size +of the allocation is 1 (or missing in the .ll file). mem2reg is not capable of +promoting structs or arrays to registers. Note that the "scalarrepl" pass is +more powerful and can promote structs, "unions", and arrays in many cases.
  8. + +
+ +

+All of these properties are easy to satisfy for most imperative languages, and +we'll illustrate it below with Kaleidoscope. The final question you may be +asking is: should I bother with this nonsense for my front-end? Wouldn't it be +better if I just did SSA construction directly, avoiding use of the mem2reg +optimization pass? In short, we strongly recommend that you use this technique +for building SSA form, unless there is an extremely good reason not to. Using +this technique is:

+ +
    +
  • Proven and well tested: llvm-gcc and clang both use this technique for local +mutable variables. As such, the most common clients of LLVM are using this to +handle a bulk of their variables. You can be sure that bugs are found fast and +fixed early.
  • + +
  • Extremely Fast: mem2reg has a number of special cases that make it fast in +common cases as well as fully general. For example, it has fast-paths for +variables that are only used in a single block, variables that only have one +assignment point, good heuristics to avoid insertion of unneeded phi nodes, etc. +
  • + +
  • Needed for debug info generation: +Debug information in LLVM relies on having the address of the variable +exposed so that debug info can be attached to it. This technique dovetails +very naturally with this style of debug info.
  • +
+ +

If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with mutable +variables now! +

+ +
+ + + + + +
+ +

Now that we know the sort of problem we want to tackle, lets see what this +looks like in the context of our little Kaleidoscope language. We're going to +add two features:

+ +
    +
  1. The ability to mutate variables with the '=' operator.
  2. +
  3. The ability to define new variables.
  4. +
+ +

While the first item is really what this is about, we only have variables +for incoming arguments as well as for induction variables, and redefining those only +goes so far :). Also, the ability to define new variables is a +useful thing regardless of whether you will be mutating them. Here's a +motivating example that shows how we could use these:

+ +
+
+# Define ':' for sequencing: as a low-precedence operator that ignores operands
+# and just returns the RHS.
+def binary : 1 (x y) y;
+
+# Recursive fib, we could do this before.
+def fib(x)
+  if (x < 3) then
+    1
+  else
+    fib(x-1)+fib(x-2);
+
+# Iterative fib.
+def fibi(x)
+  var a = 1, b = 1, c in
+  (for i = 3, i < x in 
+     c = a + b :
+     a = b :
+     b = c) :
+  b;
+
+# Call it. 
+fibi(10);
+
+
+ +

+In order to mutate variables, we have to change our existing variables to use +the "alloca trick". Once we have that, we'll add our new operator, then extend +Kaleidoscope to support new variable definitions. +

+ +
+ + + + + +
+ +

+The symbol table in Kaleidoscope is managed at code generation time by the +'NamedValues' map. This map currently keeps track of the LLVM "Value*" +that holds the double value for the named variable. In order to support +mutation, we need to change this slightly, so that it NamedValues holds +the memory location of the variable in question. Note that this +change is a refactoring: it changes the structure of the code, but does not +(by itself) change the behavior of the compiler. All of these changes are +isolated in the Kaleidoscope code generator.

+ +

+At this point in Kaleidoscope's development, it only supports variables for two +things: incoming arguments to functions and the induction variable of 'for' +loops. For consistency, we'll allow mutation of these variables in addition to +other user-defined variables. This means that these will both need memory +locations. +

+ +

To start our transformation of Kaleidoscope, we'll change the NamedValues +map so that it maps to AllocaInst* instead of Value*. Once we do this, the C++ +compiler will tell us what parts of the code we need to update:

+ +
+
+static std::map<std::string, AllocaInst*> NamedValues;
+
+
+ +

Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of the +function:

+ +
+
+/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
+/// the function.  This is used for mutable variables etc.
+static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
+                                          const std::string &VarName) {
+  IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
+                 TheFunction->getEntryBlock().begin());
+  return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
+                           VarName.c_str());
+}
+
+
+ +

This funny looking code creates an IRBuilder object that is pointing at +the first instruction (.begin()) of the entry block. It then creates an alloca +with the expected name and returns it. Because all values in Kaleidoscope are +doubles, there is no need to pass in a type to use.

+ +

With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so code +generating a reference to them actually needs to produce a load from the stack +slot:

+ +
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  if (V == 0) return ErrorV("Unknown variable name");
+
+  // Load the value.
+  return Builder.CreateLoad(V, Name.c_str());
+}
+
+
+ +

As you can see, this is pretty straightforward. Now we need to update the +things that define the variables to set up the alloca. We'll start with +ForExprAST::Codegen (see the full code listing for +the unabridged code):

+ +
+
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+
+  // Create an alloca for the variable in the entry block.
+  AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
+  
+    // Emit the start code first, without 'variable' in scope.
+  Value *StartVal = Start->Codegen();
+  if (StartVal == 0) return 0;
+  
+  // Store the value into the alloca.
+  Builder.CreateStore(StartVal, Alloca);
+  ...
+
+  // Compute the end condition.
+  Value *EndCond = End->Codegen();
+  if (EndCond == 0) return EndCond;
+  
+  // Reload, increment, and restore the alloca.  This handles the case where
+  // the body of the loop mutates the variable.
+  Value *CurVar = Builder.CreateLoad(Alloca);
+  Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
+  Builder.CreateStore(NextVar, Alloca);
+  ...
+
+
+ +

This code is virtually identical to the code before we allowed mutable variables. The +big difference is that we no longer have to construct a PHI node, and we use +load/store to access the variable as needed.

+ +

To support mutable argument variables, we need to also make allocas for them. +The code for this is also pretty simple:

+ +
+
+/// CreateArgumentAllocas - Create an alloca for each argument and register the
+/// argument in the symbol table so that references to it will succeed.
+void PrototypeAST::CreateArgumentAllocas(Function *F) {
+  Function::arg_iterator AI = F->arg_begin();
+  for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
+    // Create an alloca for this variable.
+    AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
+
+    // Store the initial value into the alloca.
+    Builder.CreateStore(AI, Alloca);
+
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = Alloca;
+  }
+}
+
+
+ +

For each argument, we make an alloca, store the input value to the function +into the alloca, and register the alloca as the memory location for the +argument. This method gets invoked by FunctionAST::Codegen right after +it sets up the entry block for the function.

+ +

The final missing piece is adding the mem2reg pass, which allows us to get +good codegen once again:

+ +
+
+    // Set up the optimizer pipeline.  Start with registering info about how the
+    // target lays out data structures.
+    OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+    // Promote allocas to registers.
+    OurFPM.add(createPromoteMemoryToRegisterPass());
+    // Do simple "peephole" optimizations and bit-twiddling optzns.
+    OurFPM.add(createInstructionCombiningPass());
+    // Reassociate expressions.
+    OurFPM.add(createReassociatePass());
+
+
+ +

It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code for our +recursive fib function. Before the optimization:

+ +
+
+define double @fib(double %x) {
+entry:
+	%x1 = alloca double
+	store double %x, double* %x1
+	%x2 = load double* %x1
+	%cmptmp = fcmp ult double %x2, 3.000000e+00
+	%booltmp = uitofp i1 %cmptmp to double
+	%ifcond = fcmp one double %booltmp, 0.000000e+00
+	br i1 %ifcond, label %then, label %else
+
+then:		; preds = %entry
+	br label %ifcont
+
+else:		; preds = %entry
+	%x3 = load double* %x1
+	%subtmp = fsub double %x3, 1.000000e+00
+	%calltmp = call double @fib(double %subtmp)
+	%x4 = load double* %x1
+	%subtmp5 = fsub double %x4, 2.000000e+00
+	%calltmp6 = call double @fib(double %subtmp5)
+	%addtmp = fadd double %calltmp, %calltmp6
+	br label %ifcont
+
+ifcont:		; preds = %else, %then
+	%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+	ret double %iftmp
+}
+
+
+ +

Here there is only one variable (x, the input argument) but you can still +see the extremely simple-minded code generation strategy we are using. In the +entry block, an alloca is created, and the initial input value is stored into +it. Each reference to the variable does a reload from the stack. Also, note +that we didn't modify the if/then/else expression, so it still inserts a PHI +node. While we could make an alloca for it, it is actually easier to create a +PHI node for it, so we still just make the PHI.

+ +

Here is the code after the mem2reg pass runs:

+ +
+
+define double @fib(double %x) {
+entry:
+	%cmptmp = fcmp ult double %x, 3.000000e+00
+	%booltmp = uitofp i1 %cmptmp to double
+	%ifcond = fcmp one double %booltmp, 0.000000e+00
+	br i1 %ifcond, label %then, label %else
+
+then:
+	br label %ifcont
+
+else:
+	%subtmp = fsub double %x, 1.000000e+00
+	%calltmp = call double @fib(double %subtmp)
+	%subtmp5 = fsub double %x, 2.000000e+00
+	%calltmp6 = call double @fib(double %subtmp5)
+	%addtmp = fadd double %calltmp, %calltmp6
+	br label %ifcont
+
+ifcont:		; preds = %else, %then
+	%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+	ret double %iftmp
+}
+
+
+ +

This is a trivial case for mem2reg, since there are no redefinitions of the +variable. The point of showing this is to calm your tension about inserting +such blatent inefficiencies :).

+ +

After the rest of the optimizers run, we get:

+ +
+
+define double @fib(double %x) {
+entry:
+	%cmptmp = fcmp ult double %x, 3.000000e+00
+	%booltmp = uitofp i1 %cmptmp to double
+	%ifcond = fcmp ueq double %booltmp, 0.000000e+00
+	br i1 %ifcond, label %else, label %ifcont
+
+else:
+	%subtmp = fsub double %x, 1.000000e+00
+	%calltmp = call double @fib(double %subtmp)
+	%subtmp5 = fsub double %x, 2.000000e+00
+	%calltmp6 = call double @fib(double %subtmp5)
+	%addtmp = fadd double %calltmp, %calltmp6
+	ret double %addtmp
+
+ifcont:
+	ret double 1.000000e+00
+}
+
+
+ +

Here we see that the simplifycfg pass decided to clone the return instruction +into the end of the 'else' block. This allowed it to eliminate some branches +and the PHI node.

+ +

Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator.

+ +
+ + + + + +
+ +

With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle it +internally (instead of allowing the user to define it). The first step is to +set a precedence:

+ +
+
+ int main() {
+   // Install standard binary operators.
+   // 1 is lowest precedence.
+   BinopPrecedence['='] = 2;
+   BinopPrecedence['<'] = 10;
+   BinopPrecedence['+'] = 20;
+   BinopPrecedence['-'] = 20;
+
+
+ +

Now that the parser knows the precedence of the binary operator, it takes +care of all the parsing and AST generation. We just need to implement codegen +for the assignment operator. This looks like:

+ +
+
+Value *BinaryExprAST::Codegen() {
+  // Special case '=' because we don't want to emit the LHS as an expression.
+  if (Op == '=') {
+    // Assignment requires the LHS to be an identifier.
+    VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS);
+    if (!LHSE)
+      return ErrorV("destination of '=' must be a variable");
+
+
+ +

Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is handled +as a special case before the other binary operators are handled. The other +strange thing is that it requires the LHS to be a variable. It is invalid to +have "(x+1) = expr" - only things like "x = expr" are allowed. +

+ +
+
+    // Codegen the RHS.
+    Value *Val = RHS->Codegen();
+    if (Val == 0) return 0;
+
+    // Look up the name.
+    Value *Variable = NamedValues[LHSE->getName()];
+    if (Variable == 0) return ErrorV("Unknown variable name");
+
+    Builder.CreateStore(Val, Variable);
+    return Val;
+  }
+  ...  
+
+
+ +

Once we have the variable, codegen'ing the assignment is straightforward: +we emit the RHS of the assignment, create a store, and return the computed +value. Returning a value allows for chained assignments like "X = (Y = Z)".

+ +

Now that we have an assignment operator, we can mutate loop variables and +arguments. For example, we can now run code like this:

+ +
+
+# Function to print a double.
+extern printd(x);
+
+# Define ':' for sequencing: as a low-precedence operator that ignores operands
+# and just returns the RHS.
+def binary : 1 (x y) y;
+
+def test(x)
+  printd(x) :
+  x = 4 :
+  printd(x);
+
+test(123);
+
+
+ +

When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our goal: +getting this to work requires SSA construction in the general case. However, +to be really useful, we want the ability to define our own local variables, lets +add this next! +

+ +
+ + + + + +
+ +

Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code generator. +The first step for adding our new 'var/in' construct is to extend the lexer. +As before, this is pretty trivial, the code looks like this:

+ +
+
+enum Token {
+  ...
+  // var definition
+  tok_var = -13
+...
+}
+...
+static int gettok() {
+...
+    if (IdentifierStr == "in") return tok_in;
+    if (IdentifierStr == "binary") return tok_binary;
+    if (IdentifierStr == "unary") return tok_unary;
+    if (IdentifierStr == "var") return tok_var;
+    return tok_identifier;
+...
+
+
+ +

The next step is to define the AST node that we will construct. For var/in, +it looks like this:

+ +
+
+/// VarExprAST - Expression class for var/in
+class VarExprAST : public ExprAST {
+  std::vector<std::pair<std::string, ExprAST*> > VarNames;
+  ExprAST *Body;
+public:
+  VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames,
+             ExprAST *body)
+  : VarNames(varnames), Body(body) {}
+  
+  virtual Value *Codegen();
+};
+
+
+ +

var/in allows a list of names to be defined all at once, and each name can +optionally have an initializer value. As such, we capture this information in +the VarNames vector. Also, var/in has a body, this body is allowed to access +the variables defined by the var/in.

+ +

With this in place, we can define the parser pieces. The first thing we do is add +it as a primary expression:

+ +
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+///   ::= ifexpr
+///   ::= forexpr
+///   ::= varexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  case tok_if:         return ParseIfExpr();
+  case tok_for:        return ParseForExpr();
+  case tok_var:        return ParseVarExpr();
+  }
+}
+
+
+ +

Next we define ParseVarExpr:

+ +
+
+/// varexpr ::= 'var' identifier ('=' expression)? 
+//                    (',' identifier ('=' expression)?)* 'in' expression
+static ExprAST *ParseVarExpr() {
+  getNextToken();  // eat the var.
+
+  std::vector<std::pair<std::string, ExprAST*> > VarNames;
+
+  // At least one variable name is required.
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after var");
+
+
+ +

The first part of this code parses the list of identifier/expr pairs into the +local VarNames vector. + +

+
+  while (1) {
+    std::string Name = IdentifierStr;
+    getNextToken();  // eat identifier.
+
+    // Read the optional initializer.
+    ExprAST *Init = 0;
+    if (CurTok == '=') {
+      getNextToken(); // eat the '='.
+      
+      Init = ParseExpression();
+      if (Init == 0) return 0;
+    }
+    
+    VarNames.push_back(std::make_pair(Name, Init));
+    
+    // End of var list, exit loop.
+    if (CurTok != ',') break;
+    getNextToken(); // eat the ','.
+    
+    if (CurTok != tok_identifier)
+      return Error("expected identifier list after var");
+  }
+
+
+ +

Once all the variables are parsed, we then parse the body and create the +AST node:

+ +
+
+  // At this point, we have to have 'in'.
+  if (CurTok != tok_in)
+    return Error("expected 'in' keyword after 'var'");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+  
+  return new VarExprAST(VarNames, Body);
+}
+
+
+ +

Now that we can parse and represent the code, we need to support emission of +LLVM IR for it. This code starts out with:

+ +
+
+Value *VarExprAST::Codegen() {
+  std::vector<AllocaInst *> OldBindings;
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+
+  // Register all variables and emit their initializer.
+  for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
+    const std::string &VarName = VarNames[i].first;
+    ExprAST *Init = VarNames[i].second;
+
+
+ +

Basically it loops over all the variables, installing them one at a time. +For each variable we put into the symbol table, we remember the previous value +that we replace in OldBindings.

+ +
+
+    // Emit the initializer before adding the variable to scope, this prevents
+    // the initializer from referencing the variable itself, and permits stuff
+    // like this:
+    //  var a = 1 in
+    //    var a = a in ...   # refers to outer 'a'.
+    Value *InitVal;
+    if (Init) {
+      InitVal = Init->Codegen();
+      if (InitVal == 0) return 0;
+    } else { // If not specified, use 0.0.
+      InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
+    }
+    
+    AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
+    Builder.CreateStore(InitVal, Alloca);
+
+    // Remember the old variable binding so that we can restore the binding when
+    // we unrecurse.
+    OldBindings.push_back(NamedValues[VarName]);
+    
+    // Remember this binding.
+    NamedValues[VarName] = Alloca;
+  }
+
+
+ +

There are more comments here than code. The basic idea is that we emit the +initializer, create the alloca, then update the symbol table to point to it. +Once all the variables are installed in the symbol table, we evaluate the body +of the var/in expression:

+ +
+
+  // Codegen the body, now that all vars are in scope.
+  Value *BodyVal = Body->Codegen();
+  if (BodyVal == 0) return 0;
+
+
+ +

Finally, before returning, we restore the previous variable bindings:

+ +
+
+  // Pop all our variables from scope.
+  for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
+    NamedValues[VarNames[i].first] = OldBindings[i];
+
+  // Return the body computation.
+  return BodyVal;
+}
+
+
+ +

The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :).

+ +

With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass optimizes +all of our stack variables into SSA registers, inserting PHI nodes where needed, +and our front-end remains simple: no "iterated dominance frontier" computation +anywhere in sight.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with mutable +variables and var/in support. To build this example, use: +

+ +
+
+   # Compile
+   g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
+   # Run
+   ./toy
+
+
+ +

Here is the code:

+ +
+
+#include "llvm/DerivedTypes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Support/IRBuilder.h"
+#include <cstdio>
+#include <string>
+#include <map>
+#include <vector>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Lexer
+//===----------------------------------------------------------------------===//
+
+// The lexer returns tokens [0-255] if it is an unknown character, otherwise one
+// of these for known things.
+enum Token {
+  tok_eof = -1,
+
+  // commands
+  tok_def = -2, tok_extern = -3,
+
+  // primary
+  tok_identifier = -4, tok_number = -5,
+  
+  // control
+  tok_if = -6, tok_then = -7, tok_else = -8,
+  tok_for = -9, tok_in = -10,
+  
+  // operators
+  tok_binary = -11, tok_unary = -12,
+  
+  // var definition
+  tok_var = -13
+};
+
+static std::string IdentifierStr;  // Filled in if tok_identifier
+static double NumVal;              // Filled in if tok_number
+
+/// gettok - Return the next token from standard input.
+static int gettok() {
+  static int LastChar = ' ';
+
+  // Skip any whitespace.
+  while (isspace(LastChar))
+    LastChar = getchar();
+
+  if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]*
+    IdentifierStr = LastChar;
+    while (isalnum((LastChar = getchar())))
+      IdentifierStr += LastChar;
+
+    if (IdentifierStr == "def") return tok_def;
+    if (IdentifierStr == "extern") return tok_extern;
+    if (IdentifierStr == "if") return tok_if;
+    if (IdentifierStr == "then") return tok_then;
+    if (IdentifierStr == "else") return tok_else;
+    if (IdentifierStr == "for") return tok_for;
+    if (IdentifierStr == "in") return tok_in;
+    if (IdentifierStr == "binary") return tok_binary;
+    if (IdentifierStr == "unary") return tok_unary;
+    if (IdentifierStr == "var") return tok_var;
+    return tok_identifier;
+  }
+
+  if (isdigit(LastChar) || LastChar == '.') {   // Number: [0-9.]+
+    std::string NumStr;
+    do {
+      NumStr += LastChar;
+      LastChar = getchar();
+    } while (isdigit(LastChar) || LastChar == '.');
+
+    NumVal = strtod(NumStr.c_str(), 0);
+    return tok_number;
+  }
+
+  if (LastChar == '#') {
+    // Comment until end of line.
+    do LastChar = getchar();
+    while (LastChar != EOF && LastChar != '\n' && LastChar != '\r');
+    
+    if (LastChar != EOF)
+      return gettok();
+  }
+  
+  // Check for end of file.  Don't eat the EOF.
+  if (LastChar == EOF)
+    return tok_eof;
+
+  // Otherwise, just return the character as its ascii value.
+  int ThisChar = LastChar;
+  LastChar = getchar();
+  return ThisChar;
+}
+
+//===----------------------------------------------------------------------===//
+// Abstract Syntax Tree (aka Parse Tree)
+//===----------------------------------------------------------------------===//
+
+/// ExprAST - Base class for all expression nodes.
+class ExprAST {
+public:
+  virtual ~ExprAST() {}
+  virtual Value *Codegen() = 0;
+};
+
+/// NumberExprAST - Expression class for numeric literals like "1.0".
+class NumberExprAST : public ExprAST {
+  double Val;
+public:
+  NumberExprAST(double val) : Val(val) {}
+  virtual Value *Codegen();
+};
+
+/// VariableExprAST - Expression class for referencing a variable, like "a".
+class VariableExprAST : public ExprAST {
+  std::string Name;
+public:
+  VariableExprAST(const std::string &name) : Name(name) {}
+  const std::string &getName() const { return Name; }
+  virtual Value *Codegen();
+};
+
+/// UnaryExprAST - Expression class for a unary operator.
+class UnaryExprAST : public ExprAST {
+  char Opcode;
+  ExprAST *Operand;
+public:
+  UnaryExprAST(char opcode, ExprAST *operand) 
+    : Opcode(opcode), Operand(operand) {}
+  virtual Value *Codegen();
+};
+
+/// BinaryExprAST - Expression class for a binary operator.
+class BinaryExprAST : public ExprAST {
+  char Op;
+  ExprAST *LHS, *RHS;
+public:
+  BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) 
+    : Op(op), LHS(lhs), RHS(rhs) {}
+  virtual Value *Codegen();
+};
+
+/// CallExprAST - Expression class for function calls.
+class CallExprAST : public ExprAST {
+  std::string Callee;
+  std::vector<ExprAST*> Args;
+public:
+  CallExprAST(const std::string &callee, std::vector<ExprAST*> &args)
+    : Callee(callee), Args(args) {}
+  virtual Value *Codegen();
+};
+
+/// IfExprAST - Expression class for if/then/else.
+class IfExprAST : public ExprAST {
+  ExprAST *Cond, *Then, *Else;
+public:
+  IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else)
+  : Cond(cond), Then(then), Else(_else) {}
+  virtual Value *Codegen();
+};
+
+/// ForExprAST - Expression class for for/in.
+class ForExprAST : public ExprAST {
+  std::string VarName;
+  ExprAST *Start, *End, *Step, *Body;
+public:
+  ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end,
+             ExprAST *step, ExprAST *body)
+    : VarName(varname), Start(start), End(end), Step(step), Body(body) {}
+  virtual Value *Codegen();
+};
+
+/// VarExprAST - Expression class for var/in
+class VarExprAST : public ExprAST {
+  std::vector<std::pair<std::string, ExprAST*> > VarNames;
+  ExprAST *Body;
+public:
+  VarExprAST(const std::vector<std::pair<std::string, ExprAST*> > &varnames,
+             ExprAST *body)
+  : VarNames(varnames), Body(body) {}
+  
+  virtual Value *Codegen();
+};
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes), as well as if it is an operator.
+class PrototypeAST {
+  std::string Name;
+  std::vector<std::string> Args;
+  bool isOperator;
+  unsigned Precedence;  // Precedence if a binary op.
+public:
+  PrototypeAST(const std::string &name, const std::vector<std::string> &args,
+               bool isoperator = false, unsigned prec = 0)
+  : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {}
+  
+  bool isUnaryOp() const { return isOperator && Args.size() == 1; }
+  bool isBinaryOp() const { return isOperator && Args.size() == 2; }
+  
+  char getOperatorName() const {
+    assert(isUnaryOp() || isBinaryOp());
+    return Name[Name.size()-1];
+  }
+  
+  unsigned getBinaryPrecedence() const { return Precedence; }
+  
+  Function *Codegen();
+  
+  void CreateArgumentAllocas(Function *F);
+};
+
+/// FunctionAST - This class represents a function definition itself.
+class FunctionAST {
+  PrototypeAST *Proto;
+  ExprAST *Body;
+public:
+  FunctionAST(PrototypeAST *proto, ExprAST *body)
+    : Proto(proto), Body(body) {}
+  
+  Function *Codegen();
+};
+
+//===----------------------------------------------------------------------===//
+// Parser
+//===----------------------------------------------------------------------===//
+
+/// CurTok/getNextToken - Provide a simple token buffer.  CurTok is the current
+/// token the parser is looking at.  getNextToken reads another token from the
+/// lexer and updates CurTok with its results.
+static int CurTok;
+static int getNextToken() {
+  return CurTok = gettok();
+}
+
+/// BinopPrecedence - This holds the precedence for each binary operator that is
+/// defined.
+static std::map<char, int> BinopPrecedence;
+
+/// GetTokPrecedence - Get the precedence of the pending binary operator token.
+static int GetTokPrecedence() {
+  if (!isascii(CurTok))
+    return -1;
+  
+  // Make sure it's a declared binop.
+  int TokPrec = BinopPrecedence[CurTok];
+  if (TokPrec <= 0) return -1;
+  return TokPrec;
+}
+
+/// Error* - These are little helper functions for error handling.
+ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;}
+PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; }
+FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; }
+
+static ExprAST *ParseExpression();
+
+/// identifierexpr
+///   ::= identifier
+///   ::= identifier '(' expression* ')'
+static ExprAST *ParseIdentifierExpr() {
+  std::string IdName = IdentifierStr;
+  
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '(') // Simple variable ref.
+    return new VariableExprAST(IdName);
+  
+  // Call.
+  getNextToken();  // eat (
+  std::vector<ExprAST*> Args;
+  if (CurTok != ')') {
+    while (1) {
+      ExprAST *Arg = ParseExpression();
+      if (!Arg) return 0;
+      Args.push_back(Arg);
+
+      if (CurTok == ')') break;
+
+      if (CurTok != ',')
+        return Error("Expected ')' or ',' in argument list");
+      getNextToken();
+    }
+  }
+
+  // Eat the ')'.
+  getNextToken();
+  
+  return new CallExprAST(IdName, Args);
+}
+
+/// numberexpr ::= number
+static ExprAST *ParseNumberExpr() {
+  ExprAST *Result = new NumberExprAST(NumVal);
+  getNextToken(); // consume the number
+  return Result;
+}
+
+/// parenexpr ::= '(' expression ')'
+static ExprAST *ParseParenExpr() {
+  getNextToken();  // eat (.
+  ExprAST *V = ParseExpression();
+  if (!V) return 0;
+  
+  if (CurTok != ')')
+    return Error("expected ')'");
+  getNextToken();  // eat ).
+  return V;
+}
+
+/// ifexpr ::= 'if' expression 'then' expression 'else' expression
+static ExprAST *ParseIfExpr() {
+  getNextToken();  // eat the if.
+  
+  // condition.
+  ExprAST *Cond = ParseExpression();
+  if (!Cond) return 0;
+  
+  if (CurTok != tok_then)
+    return Error("expected then");
+  getNextToken();  // eat the then
+  
+  ExprAST *Then = ParseExpression();
+  if (Then == 0) return 0;
+  
+  if (CurTok != tok_else)
+    return Error("expected else");
+  
+  getNextToken();
+  
+  ExprAST *Else = ParseExpression();
+  if (!Else) return 0;
+  
+  return new IfExprAST(Cond, Then, Else);
+}
+
+/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression
+static ExprAST *ParseForExpr() {
+  getNextToken();  // eat the for.
+
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after for");
+  
+  std::string IdName = IdentifierStr;
+  getNextToken();  // eat identifier.
+  
+  if (CurTok != '=')
+    return Error("expected '=' after for");
+  getNextToken();  // eat '='.
+  
+  
+  ExprAST *Start = ParseExpression();
+  if (Start == 0) return 0;
+  if (CurTok != ',')
+    return Error("expected ',' after for start value");
+  getNextToken();
+  
+  ExprAST *End = ParseExpression();
+  if (End == 0) return 0;
+  
+  // The step value is optional.
+  ExprAST *Step = 0;
+  if (CurTok == ',') {
+    getNextToken();
+    Step = ParseExpression();
+    if (Step == 0) return 0;
+  }
+  
+  if (CurTok != tok_in)
+    return Error("expected 'in' after for");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+
+  return new ForExprAST(IdName, Start, End, Step, Body);
+}
+
+/// varexpr ::= 'var' identifier ('=' expression)? 
+//                    (',' identifier ('=' expression)?)* 'in' expression
+static ExprAST *ParseVarExpr() {
+  getNextToken();  // eat the var.
+
+  std::vector<std::pair<std::string, ExprAST*> > VarNames;
+
+  // At least one variable name is required.
+  if (CurTok != tok_identifier)
+    return Error("expected identifier after var");
+  
+  while (1) {
+    std::string Name = IdentifierStr;
+    getNextToken();  // eat identifier.
+
+    // Read the optional initializer.
+    ExprAST *Init = 0;
+    if (CurTok == '=') {
+      getNextToken(); // eat the '='.
+      
+      Init = ParseExpression();
+      if (Init == 0) return 0;
+    }
+    
+    VarNames.push_back(std::make_pair(Name, Init));
+    
+    // End of var list, exit loop.
+    if (CurTok != ',') break;
+    getNextToken(); // eat the ','.
+    
+    if (CurTok != tok_identifier)
+      return Error("expected identifier list after var");
+  }
+  
+  // At this point, we have to have 'in'.
+  if (CurTok != tok_in)
+    return Error("expected 'in' keyword after 'var'");
+  getNextToken();  // eat 'in'.
+  
+  ExprAST *Body = ParseExpression();
+  if (Body == 0) return 0;
+  
+  return new VarExprAST(VarNames, Body);
+}
+
+/// primary
+///   ::= identifierexpr
+///   ::= numberexpr
+///   ::= parenexpr
+///   ::= ifexpr
+///   ::= forexpr
+///   ::= varexpr
+static ExprAST *ParsePrimary() {
+  switch (CurTok) {
+  default: return Error("unknown token when expecting an expression");
+  case tok_identifier: return ParseIdentifierExpr();
+  case tok_number:     return ParseNumberExpr();
+  case '(':            return ParseParenExpr();
+  case tok_if:         return ParseIfExpr();
+  case tok_for:        return ParseForExpr();
+  case tok_var:        return ParseVarExpr();
+  }
+}
+
+/// unary
+///   ::= primary
+///   ::= '!' unary
+static ExprAST *ParseUnary() {
+  // If the current token is not an operator, it must be a primary expr.
+  if (!isascii(CurTok) || CurTok == '(' || CurTok == ',')
+    return ParsePrimary();
+  
+  // If this is a unary operator, read it.
+  int Opc = CurTok;
+  getNextToken();
+  if (ExprAST *Operand = ParseUnary())
+    return new UnaryExprAST(Opc, Operand);
+  return 0;
+}
+
+/// binoprhs
+///   ::= ('+' unary)*
+static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) {
+  // If this is a binop, find its precedence.
+  while (1) {
+    int TokPrec = GetTokPrecedence();
+    
+    // If this is a binop that binds at least as tightly as the current binop,
+    // consume it, otherwise we are done.
+    if (TokPrec < ExprPrec)
+      return LHS;
+    
+    // Okay, we know this is a binop.
+    int BinOp = CurTok;
+    getNextToken();  // eat binop
+    
+    // Parse the unary expression after the binary operator.
+    ExprAST *RHS = ParseUnary();
+    if (!RHS) return 0;
+    
+    // If BinOp binds less tightly with RHS than the operator after RHS, let
+    // the pending operator take RHS as its LHS.
+    int NextPrec = GetTokPrecedence();
+    if (TokPrec < NextPrec) {
+      RHS = ParseBinOpRHS(TokPrec+1, RHS);
+      if (RHS == 0) return 0;
+    }
+    
+    // Merge LHS/RHS.
+    LHS = new BinaryExprAST(BinOp, LHS, RHS);
+  }
+}
+
+/// expression
+///   ::= unary binoprhs
+///
+static ExprAST *ParseExpression() {
+  ExprAST *LHS = ParseUnary();
+  if (!LHS) return 0;
+  
+  return ParseBinOpRHS(0, LHS);
+}
+
+/// prototype
+///   ::= id '(' id* ')'
+///   ::= binary LETTER number? (id, id)
+///   ::= unary LETTER (id)
+static PrototypeAST *ParsePrototype() {
+  std::string FnName;
+  
+  unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary.
+  unsigned BinaryPrecedence = 30;
+  
+  switch (CurTok) {
+  default:
+    return ErrorP("Expected function name in prototype");
+  case tok_identifier:
+    FnName = IdentifierStr;
+    Kind = 0;
+    getNextToken();
+    break;
+  case tok_unary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected unary operator");
+    FnName = "unary";
+    FnName += (char)CurTok;
+    Kind = 1;
+    getNextToken();
+    break;
+  case tok_binary:
+    getNextToken();
+    if (!isascii(CurTok))
+      return ErrorP("Expected binary operator");
+    FnName = "binary";
+    FnName += (char)CurTok;
+    Kind = 2;
+    getNextToken();
+    
+    // Read the precedence if present.
+    if (CurTok == tok_number) {
+      if (NumVal < 1 || NumVal > 100)
+        return ErrorP("Invalid precedecnce: must be 1..100");
+      BinaryPrecedence = (unsigned)NumVal;
+      getNextToken();
+    }
+    break;
+  }
+  
+  if (CurTok != '(')
+    return ErrorP("Expected '(' in prototype");
+  
+  std::vector<std::string> ArgNames;
+  while (getNextToken() == tok_identifier)
+    ArgNames.push_back(IdentifierStr);
+  if (CurTok != ')')
+    return ErrorP("Expected ')' in prototype");
+  
+  // success.
+  getNextToken();  // eat ')'.
+  
+  // Verify right number of names for operator.
+  if (Kind && ArgNames.size() != Kind)
+    return ErrorP("Invalid number of operands for operator");
+  
+  return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence);
+}
+
+/// definition ::= 'def' prototype expression
+static FunctionAST *ParseDefinition() {
+  getNextToken();  // eat def.
+  PrototypeAST *Proto = ParsePrototype();
+  if (Proto == 0) return 0;
+
+  if (ExprAST *E = ParseExpression())
+    return new FunctionAST(Proto, E);
+  return 0;
+}
+
+/// toplevelexpr ::= expression
+static FunctionAST *ParseTopLevelExpr() {
+  if (ExprAST *E = ParseExpression()) {
+    // Make an anonymous proto.
+    PrototypeAST *Proto = new PrototypeAST("", std::vector<std::string>());
+    return new FunctionAST(Proto, E);
+  }
+  return 0;
+}
+
+/// external ::= 'extern' prototype
+static PrototypeAST *ParseExtern() {
+  getNextToken();  // eat extern.
+  return ParsePrototype();
+}
+
+//===----------------------------------------------------------------------===//
+// Code Generation
+//===----------------------------------------------------------------------===//
+
+static Module *TheModule;
+static IRBuilder<> Builder(getGlobalContext());
+static std::map<std::string, AllocaInst*> NamedValues;
+static FunctionPassManager *TheFPM;
+
+Value *ErrorV(const char *Str) { Error(Str); return 0; }
+
+/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of
+/// the function.  This is used for mutable variables etc.
+static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction,
+                                          const std::string &VarName) {
+  IRBuilder<> TmpB(&TheFunction->getEntryBlock(),
+                 TheFunction->getEntryBlock().begin());
+  return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0,
+                           VarName.c_str());
+}
+
+Value *NumberExprAST::Codegen() {
+  return ConstantFP::get(getGlobalContext(), APFloat(Val));
+}
+
+Value *VariableExprAST::Codegen() {
+  // Look this variable up in the function.
+  Value *V = NamedValues[Name];
+  if (V == 0) return ErrorV("Unknown variable name");
+
+  // Load the value.
+  return Builder.CreateLoad(V, Name.c_str());
+}
+
+Value *UnaryExprAST::Codegen() {
+  Value *OperandV = Operand->Codegen();
+  if (OperandV == 0) return 0;
+  
+  Function *F = TheModule->getFunction(std::string("unary")+Opcode);
+  if (F == 0)
+    return ErrorV("Unknown unary operator");
+  
+  return Builder.CreateCall(F, OperandV, "unop");
+}
+
+Value *BinaryExprAST::Codegen() {
+  // Special case '=' because we don't want to emit the LHS as an expression.
+  if (Op == '=') {
+    // Assignment requires the LHS to be an identifier.
+    VariableExprAST *LHSE = dynamic_cast<VariableExprAST*>(LHS);
+    if (!LHSE)
+      return ErrorV("destination of '=' must be a variable");
+    // Codegen the RHS.
+    Value *Val = RHS->Codegen();
+    if (Val == 0) return 0;
+
+    // Look up the name.
+    Value *Variable = NamedValues[LHSE->getName()];
+    if (Variable == 0) return ErrorV("Unknown variable name");
+
+    Builder.CreateStore(Val, Variable);
+    return Val;
+  }
+  
+  Value *L = LHS->Codegen();
+  Value *R = RHS->Codegen();
+  if (L == 0 || R == 0) return 0;
+  
+  switch (Op) {
+  case '+': return Builder.CreateFAdd(L, R, "addtmp");
+  case '-': return Builder.CreateFSub(L, R, "subtmp");
+  case '*': return Builder.CreateFMul(L, R, "multmp");
+  case '<':
+    L = Builder.CreateFCmpULT(L, R, "cmptmp");
+    // Convert bool 0/1 to double 0.0 or 1.0
+    return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()),
+                                "booltmp");
+  default: break;
+  }
+  
+  // If it wasn't a builtin binary operator, it must be a user defined one. Emit
+  // a call to it.
+  Function *F = TheModule->getFunction(std::string("binary")+Op);
+  assert(F && "binary operator not found!");
+  
+  Value *Ops[] = { L, R };
+  return Builder.CreateCall(F, Ops, Ops+2, "binop");
+}
+
+Value *CallExprAST::Codegen() {
+  // Look up the name in the global module table.
+  Function *CalleeF = TheModule->getFunction(Callee);
+  if (CalleeF == 0)
+    return ErrorV("Unknown function referenced");
+  
+  // If argument mismatch error.
+  if (CalleeF->arg_size() != Args.size())
+    return ErrorV("Incorrect # arguments passed");
+
+  std::vector<Value*> ArgsV;
+  for (unsigned i = 0, e = Args.size(); i != e; ++i) {
+    ArgsV.push_back(Args[i]->Codegen());
+    if (ArgsV.back() == 0) return 0;
+  }
+  
+  return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
+}
+
+Value *IfExprAST::Codegen() {
+  Value *CondV = Cond->Codegen();
+  if (CondV == 0) return 0;
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  CondV = Builder.CreateFCmpONE(CondV, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                "ifcond");
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+  
+  // Create blocks for the then and else cases.  Insert the 'then' block at the
+  // end of the function.
+  BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction);
+  BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else");
+  BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont");
+  
+  Builder.CreateCondBr(CondV, ThenBB, ElseBB);
+  
+  // Emit then value.
+  Builder.SetInsertPoint(ThenBB);
+  
+  Value *ThenV = Then->Codegen();
+  if (ThenV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Then' can change the current block, update ThenBB for the PHI.
+  ThenBB = Builder.GetInsertBlock();
+  
+  // Emit else block.
+  TheFunction->getBasicBlockList().push_back(ElseBB);
+  Builder.SetInsertPoint(ElseBB);
+  
+  Value *ElseV = Else->Codegen();
+  if (ElseV == 0) return 0;
+  
+  Builder.CreateBr(MergeBB);
+  // Codegen of 'Else' can change the current block, update ElseBB for the PHI.
+  ElseBB = Builder.GetInsertBlock();
+  
+  // Emit merge block.
+  TheFunction->getBasicBlockList().push_back(MergeBB);
+  Builder.SetInsertPoint(MergeBB);
+  PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()),
+                                  "iftmp");
+  
+  PN->addIncoming(ThenV, ThenBB);
+  PN->addIncoming(ElseV, ElseBB);
+  return PN;
+}
+
+Value *ForExprAST::Codegen() {
+  // Output this as:
+  //   var = alloca double
+  //   ...
+  //   start = startexpr
+  //   store start -> var
+  //   goto loop
+  // loop: 
+  //   ...
+  //   bodyexpr
+  //   ...
+  // loopend:
+  //   step = stepexpr
+  //   endcond = endexpr
+  //
+  //   curvar = load var
+  //   nextvar = curvar + step
+  //   store nextvar -> var
+  //   br endcond, loop, endloop
+  // outloop:
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+
+  // Create an alloca for the variable in the entry block.
+  AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
+  
+  // Emit the start code first, without 'variable' in scope.
+  Value *StartVal = Start->Codegen();
+  if (StartVal == 0) return 0;
+  
+  // Store the value into the alloca.
+  Builder.CreateStore(StartVal, Alloca);
+  
+  // Make the new basic block for the loop header, inserting after current
+  // block.
+  BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction);
+  
+  // Insert an explicit fall through from the current block to the LoopBB.
+  Builder.CreateBr(LoopBB);
+
+  // Start insertion in LoopBB.
+  Builder.SetInsertPoint(LoopBB);
+  
+  // Within the loop, the variable is defined equal to the PHI node.  If it
+  // shadows an existing variable, we have to restore it, so save it now.
+  AllocaInst *OldVal = NamedValues[VarName];
+  NamedValues[VarName] = Alloca;
+  
+  // Emit the body of the loop.  This, like any other expr, can change the
+  // current BB.  Note that we ignore the value computed by the body, but don't
+  // allow an error.
+  if (Body->Codegen() == 0)
+    return 0;
+  
+  // Emit the step value.
+  Value *StepVal;
+  if (Step) {
+    StepVal = Step->Codegen();
+    if (StepVal == 0) return 0;
+  } else {
+    // If not specified, use 1.0.
+    StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
+  }
+  
+  // Compute the end condition.
+  Value *EndCond = End->Codegen();
+  if (EndCond == 0) return EndCond;
+  
+  // Reload, increment, and restore the alloca.  This handles the case where
+  // the body of the loop mutates the variable.
+  Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str());
+  Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
+  Builder.CreateStore(NextVar, Alloca);
+  
+  // Convert condition to a bool by comparing equal to 0.0.
+  EndCond = Builder.CreateFCmpONE(EndCond, 
+                              ConstantFP::get(getGlobalContext(), APFloat(0.0)),
+                                  "loopcond");
+  
+  // Create the "after loop" block and insert it.
+  BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction);
+  
+  // Insert the conditional branch into the end of LoopEndBB.
+  Builder.CreateCondBr(EndCond, LoopBB, AfterBB);
+  
+  // Any new code will be inserted in AfterBB.
+  Builder.SetInsertPoint(AfterBB);
+  
+  // Restore the unshadowed variable.
+  if (OldVal)
+    NamedValues[VarName] = OldVal;
+  else
+    NamedValues.erase(VarName);
+
+  
+  // for expr always returns 0.0.
+  return Constant::getNullValue(Type::getDoubleTy(getGlobalContext()));
+}
+
+Value *VarExprAST::Codegen() {
+  std::vector<AllocaInst *> OldBindings;
+  
+  Function *TheFunction = Builder.GetInsertBlock()->getParent();
+
+  // Register all variables and emit their initializer.
+  for (unsigned i = 0, e = VarNames.size(); i != e; ++i) {
+    const std::string &VarName = VarNames[i].first;
+    ExprAST *Init = VarNames[i].second;
+    
+    // Emit the initializer before adding the variable to scope, this prevents
+    // the initializer from referencing the variable itself, and permits stuff
+    // like this:
+    //  var a = 1 in
+    //    var a = a in ...   # refers to outer 'a'.
+    Value *InitVal;
+    if (Init) {
+      InitVal = Init->Codegen();
+      if (InitVal == 0) return 0;
+    } else { // If not specified, use 0.0.
+      InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0));
+    }
+    
+    AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName);
+    Builder.CreateStore(InitVal, Alloca);
+
+    // Remember the old variable binding so that we can restore the binding when
+    // we unrecurse.
+    OldBindings.push_back(NamedValues[VarName]);
+    
+    // Remember this binding.
+    NamedValues[VarName] = Alloca;
+  }
+  
+  // Codegen the body, now that all vars are in scope.
+  Value *BodyVal = Body->Codegen();
+  if (BodyVal == 0) return 0;
+  
+  // Pop all our variables from scope.
+  for (unsigned i = 0, e = VarNames.size(); i != e; ++i)
+    NamedValues[VarNames[i].first] = OldBindings[i];
+
+  // Return the body computation.
+  return BodyVal;
+}
+
+Function *PrototypeAST::Codegen() {
+  // Make the function type:  double(double,double) etc.
+  std::vector<const Type*> Doubles(Args.size(),
+                                   Type::getDoubleTy(getGlobalContext()));
+  FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
+                                       Doubles, false);
+  
+  Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
+  
+  // If F conflicted, there was already something named 'Name'.  If it has a
+  // body, don't allow redefinition or reextern.
+  if (F->getName() != Name) {
+    // Delete the one we just made and get the existing one.
+    F->eraseFromParent();
+    F = TheModule->getFunction(Name);
+    
+    // If F already has a body, reject this.
+    if (!F->empty()) {
+      ErrorF("redefinition of function");
+      return 0;
+    }
+    
+    // If F took a different number of args, reject.
+    if (F->arg_size() != Args.size()) {
+      ErrorF("redefinition of function with different # args");
+      return 0;
+    }
+  }
+  
+  // Set names for all arguments.
+  unsigned Idx = 0;
+  for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size();
+       ++AI, ++Idx)
+    AI->setName(Args[Idx]);
+    
+  return F;
+}
+
+/// CreateArgumentAllocas - Create an alloca for each argument and register the
+/// argument in the symbol table so that references to it will succeed.
+void PrototypeAST::CreateArgumentAllocas(Function *F) {
+  Function::arg_iterator AI = F->arg_begin();
+  for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) {
+    // Create an alloca for this variable.
+    AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]);
+
+    // Store the initial value into the alloca.
+    Builder.CreateStore(AI, Alloca);
+
+    // Add arguments to variable symbol table.
+    NamedValues[Args[Idx]] = Alloca;
+  }
+}
+
+Function *FunctionAST::Codegen() {
+  NamedValues.clear();
+  
+  Function *TheFunction = Proto->Codegen();
+  if (TheFunction == 0)
+    return 0;
+  
+  // If this is an operator, install it.
+  if (Proto->isBinaryOp())
+    BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence();
+  
+  // Create a new basic block to start insertion into.
+  BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction);
+  Builder.SetInsertPoint(BB);
+  
+  // Add all arguments to the symbol table and create their allocas.
+  Proto->CreateArgumentAllocas(TheFunction);
+
+  if (Value *RetVal = Body->Codegen()) {
+    // Finish off the function.
+    Builder.CreateRet(RetVal);
+
+    // Validate the generated code, checking for consistency.
+    verifyFunction(*TheFunction);
+
+    // Optimize the function.
+    TheFPM->run(*TheFunction);
+    
+    return TheFunction;
+  }
+  
+  // Error reading body, remove function.
+  TheFunction->eraseFromParent();
+
+  if (Proto->isBinaryOp())
+    BinopPrecedence.erase(Proto->getOperatorName());
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Top-Level parsing and JIT Driver
+//===----------------------------------------------------------------------===//
+
+static ExecutionEngine *TheExecutionEngine;
+
+static void HandleDefinition() {
+  if (FunctionAST *F = ParseDefinition()) {
+    if (Function *LF = F->Codegen()) {
+      fprintf(stderr, "Read function definition:");
+      LF->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleExtern() {
+  if (PrototypeAST *P = ParseExtern()) {
+    if (Function *F = P->Codegen()) {
+      fprintf(stderr, "Read extern: ");
+      F->dump();
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+static void HandleTopLevelExpression() {
+  // Evaluate a top-level expression into an anonymous function.
+  if (FunctionAST *F = ParseTopLevelExpr()) {
+    if (Function *LF = F->Codegen()) {
+      // JIT the function, returning a function pointer.
+      void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
+      
+      // Cast it to the right type (takes no arguments, returns a double) so we
+      // can call it as a native function.
+      double (*FP)() = (double (*)())(intptr_t)FPtr;
+      fprintf(stderr, "Evaluated to %f\n", FP());
+    }
+  } else {
+    // Skip token for error recovery.
+    getNextToken();
+  }
+}
+
+/// top ::= definition | external | expression | ';'
+static void MainLoop() {
+  while (1) {
+    fprintf(stderr, "ready> ");
+    switch (CurTok) {
+    case tok_eof:    return;
+    case ';':        getNextToken(); break;  // ignore top-level semicolons.
+    case tok_def:    HandleDefinition(); break;
+    case tok_extern: HandleExtern(); break;
+    default:         HandleTopLevelExpression(); break;
+    }
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// "Library" functions that can be "extern'd" from user code.
+//===----------------------------------------------------------------------===//
+
+/// putchard - putchar that takes a double and returns 0.
+extern "C" 
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+/// printd - printf that takes a double prints it as "%f\n", returning 0.
+extern "C" 
+double printd(double X) {
+  printf("%f\n", X);
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// Main driver code.
+//===----------------------------------------------------------------------===//
+
+int main() {
+  InitializeNativeTarget();
+  LLVMContext &Context = getGlobalContext();
+
+  // Install standard binary operators.
+  // 1 is lowest precedence.
+  BinopPrecedence['='] = 2;
+  BinopPrecedence['<'] = 10;
+  BinopPrecedence['+'] = 20;
+  BinopPrecedence['-'] = 20;
+  BinopPrecedence['*'] = 40;  // highest.
+
+  // Prime the first token.
+  fprintf(stderr, "ready> ");
+  getNextToken();
+
+  // Make the module, which holds all the code.
+  TheModule = new Module("my cool jit", Context);
+
+  // Create the JIT.  This takes ownership of the module.
+  std::string ErrStr;
+  TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
+  if (!TheExecutionEngine) {
+    fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
+    exit(1);
+  }
+
+  FunctionPassManager OurFPM(TheModule);
+
+  // Set up the optimizer pipeline.  Start with registering info about how the
+  // target lays out data structures.
+  OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData()));
+  // Provide basic AliasAnalysis support for GVN.
+  OurFPM.add(createBasicAliasAnalysisPass());
+  // Promote allocas to registers.
+  OurFPM.add(createPromoteMemoryToRegisterPass());
+  // Do simple "peephole" optimizations and bit-twiddling optzns.
+  OurFPM.add(createInstructionCombiningPass());
+  // Reassociate expressions.
+  OurFPM.add(createReassociatePass());
+  // Eliminate Common SubExpressions.
+  OurFPM.add(createGVNPass());
+  // Simplify the control flow graph (deleting unreachable blocks, etc).
+  OurFPM.add(createCFGSimplificationPass());
+
+  OurFPM.doInitialization();
+
+  // Set the global so the code gen can use this.
+  TheFPM = &OurFPM;
+
+  // Run the main "interpreter loop" now.
+  MainLoop();
+
+  TheFPM = 0;
+
+  // Print out all of the generated code.
+  TheModule->dump();
+
+  return 0;
+}
+
+
+ +Next: Conclusion and other useful LLVM tidbits +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/LangImpl8.html b/final/docs/tutorial/LangImpl8.html new file mode 100644 index 00000000000..64a62002c4c --- /dev/null +++ b/final/docs/tutorial/LangImpl8.html @@ -0,0 +1,365 @@ + + + + + Kaleidoscope: Conclusion and other useful LLVM tidbits + + + + + + + +
Kaleidoscope: Conclusion and other useful LLVM + tidbits
+ + + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to the the final chapter of the "Implementing a +language with LLVM" tutorial. In the course of this tutorial, we have grown +our little Kaleidoscope language from being a useless toy, to being a +semi-interesting (but probably still useless) toy. :)

+ +

It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code.

+ +

Our little language supports a couple of interesting features: it supports +user defined binary and unary operators, it uses JIT compilation for immediate +evaluation, and it supports a few control flow constructs with SSA construction. +

+ +

Part of the idea of this tutorial was to show you how easy and fun it can be +to define, build, and play with languages. Building a compiler need not be a +scary or mystical process! Now that you've seen some of the basics, I strongly +encourage you to take the code and hack on it. For example, try adding:

+ +
    +
  • global variables - While global variables have questional value in +modern software engineering, they are often useful when putting together quick +little hacks like the Kaleidoscope compiler itself. Fortunately, our current +setup makes it very easy to add global variables: just have value lookup check +to see if an unresolved variable is in the global variable symbol table before +rejecting it. To create a new global variable, make an instance of the LLVM +GlobalVariable class.
  • + +
  • typed variables - Kaleidoscope currently only supports variables of +type double. This gives the language a very nice elegance, because only +supporting one type means that you never have to specify types. Different +languages have different ways of handling this. The easiest way is to require +the user to specify types for every variable definition, and record the type +of the variable in the symbol table along with its Value*.
  • + +
  • arrays, structs, vectors, etc - Once you add types, you can start +extending the type system in all sorts of interesting ways. Simple arrays are +very easy and are quite useful for many different applications. Adding them is +mostly an exercise in learning how the LLVM getelementptr instruction works: it +is so nifty/unconventional, it has its own FAQ! If you add support +for recursive types (e.g. linked lists), make sure to read the section in the LLVM +Programmer's Manual that describes how to construct them.
  • + +
  • standard runtime - Our current language allows the user to access +arbitrary external functions, and we use it for things like "printd" and +"putchard". As you extend the language to add higher-level constructs, often +these constructs make the most sense if they are lowered to calls into a +language-supplied runtime. For example, if you add hash tables to the language, +it would probably make sense to add the routines to a runtime, instead of +inlining them all the way.
  • + +
  • memory management - Currently we can only access the stack in +Kaleidoscope. It would also be useful to be able to allocate heap memory, +either with calls to the standard libc malloc/free interface or with a garbage +collector. If you would like to use garbage collection, note that LLVM fully +supports Accurate Garbage Collection +including algorithms that move objects and need to scan/update the stack.
  • + +
  • debugger support - LLVM supports generation of DWARF Debug info which is understood by +common debuggers like GDB. Adding support for debug info is fairly +straightforward. The best way to understand it is to compile some C/C++ code +with "llvm-gcc -g -O0" and taking a look at what it produces.
  • + +
  • exception handling support - LLVM supports generation of zero cost exceptions which interoperate +with code compiled in other languages. You could also generate code by +implicitly making every function return an error value and checking it. You +could also make explicit use of setjmp/longjmp. There are many different ways +to go here.
  • + +
  • object orientation, generics, database access, complex numbers, +geometric programming, ... - Really, there is +no end of crazy features that you can add to the language.
  • + +
  • unusual domains - We've been talking about applying LLVM to a domain +that many people are interested in: building a compiler for a specific language. +However, there are many other domains that can use compiler technology that are +not typically considered. For example, LLVM has been used to implement OpenGL +graphics acceleration, translate C++ code to ActionScript, and many other +cute and clever things. Maybe you will be the first to JIT compile a regular +expression interpreter into native code with LLVM?
  • + +
+ +

+Have fun - try doing something crazy and unusual. Building a language like +everyone else always has, is much less fun than trying something a little crazy +or off the wall and seeing how it turns out. If you get stuck or want to talk +about it, feel free to email the llvmdev mailing +list: it has lots of people who are interested in languages and are often +willing to help out. +

+ +

Before we end this tutorial, I want to talk about some "tips and tricks" for generating +LLVM IR. These are some of the more subtle things that may not be obvious, but +are very useful if you want to take advantage of LLVM's capabilities.

+ +
+ + + + + +
+ +

We have a couple common questions about code in the LLVM IR form - lets just +get these out of the way right now, shall we?

+ +
+ + + + + +
+ +

Kaleidoscope is an example of a "portable language": any program written in +Kaleidoscope will work the same way on any target that it runs on. Many other +languages have this property, e.g. lisp, java, haskell, javascript, python, etc +(note that while these languages are portable, not all their libraries are).

+ +

One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a Kaleidoscope-compiled +program and run it on any target that LLVM supports, even emitting C code and +compiling that on targets that LLVM doesn't support natively. You can trivially +tell that the Kaleidoscope compiler generates target-independent code because it +never queries for any target-specific information when generating code.

+ +

The fact that LLVM provides a compact, target-independent, representation for +code gets a lot of people excited. Unfortunately, these people are usually +thinking about C or a language from the C family when they are asking questions +about language portability. I say "unfortunately", because there is really no +way to make (fully general) C code portable, other than shipping the source code +around (and of course, C source code is not actually portable in general +either - ever port a really old application from 32- to 64-bits?).

+ +

The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the preprocessor +often destructively removes target-independence from the code when it processes +the input text:

+ +
+
+#ifdef __i386__
+  int X = 1;
+#else
+  int X = 42;
+#endif
+
+
+ +

While it is possible to engineer more and more complex solutions to problems +like this, it cannot be solved in full generality in a way that is better than shipping +the actual source code.

+ +

That said, there are interesting subsets of C that can be made portable. If +you are willing to fix primitive types to a fixed size (say int = 32-bits, +and long = 64-bits), don't care about ABI compatibility with existing binaries, +and are willing to give up some other minor features, you can have portable +code. This can make sense for specialized domains such as an +in-kernel language.

+ +
+ + + + + +
+ +

Many of the languages above are also "safe" languages: it is impossible for +a program written in Java to corrupt its address space and crash the process +(assuming the JVM has no bugs). +Safety is an interesting property that requires a combination of language +design, runtime support, and often operating system support.

+ +

It is certainly possible to implement a safe language in LLVM, but LLVM IR +does not itself guarantee safety. The LLVM IR allows unsafe pointer casts, +use after free bugs, buffer over-runs, and a variety of other problems. Safety +needs to be implemented as a layer on top of LLVM and, conveniently, several +groups have investigated this. Ask on the llvmdev mailing +list if you are interested in more details.

+ +
+ + + + + +
+ +

One thing about LLVM that turns off many people is that it does not solve all +the world's problems in one system (sorry 'world hunger', someone else will have +to solve you some other day). One specific complaint is that people perceive +LLVM as being incapable of performing high-level language-specific optimization: +LLVM "loses too much information".

+ +

Unfortunately, this is really not the place to give you a full and unified +version of "Chris Lattner's theory of compiler design". Instead, I'll make a +few observations:

+ +

First, you're right that LLVM does lose information. For example, as of this +writing, there is no way to distinguish in the LLVM IR whether an SSA-value came +from a C "int" or a C "long" on an ILP32 machine (other than debug info). Both +get compiled down to an 'i32' value and the information about what it came from +is lost. The more general issue here, is that the LLVM type system uses +"structural equivalence" instead of "name equivalence". Another place this +surprises people is if you have two types in a high-level language that have the +same structure (e.g. two different structs that have a single int field): these +types will compile down into a single LLVM type and it will be impossible to +tell what it came from.

+ +

Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition to +adding new features (LLVM did not always support exceptions or debug info), we +also extend the IR to capture important information for optimization (e.g. +whether an argument is sign or zero extended, information about pointers +aliasing, etc). Many of the enhancements are user-driven: people want LLVM to +include some specific feature, so they go ahead and extend it.

+ +

Third, it is possible and easy to add language-specific +optimizations, and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C family, +there is an optimization pass that "knows" about the standard C library +functions. If you call "exit(0)" in main(), it knows that it is safe to +optimize that into "return 0;" because C specifies what the 'exit' +function does.

+ +

In addition to simple library knowledge, it is possible to embed a variety of +other language-specific information into the LLVM IR. If you have a specific +need and run into a wall, please bring the topic up on the llvmdev list. At the +very worst, you can always treat LLVM as if it were a "dumb code generator" and +implement the high-level optimizations you desire in your front-end, on the +language-specific AST. +

+ +
+ + + + + +
+ +

There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of letting +everyone rediscover them, this section talks about some of these issues.

+ +
+ + + + + +
+ +

One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need to know +the size of some LLVM type or the offset of some field in an llvm structure. +For example, you might need to pass the size of a type into a function that +allocates memory.

+ +

Unfortunately, this can vary widely across targets: for example the width of +a pointer is trivially target-specific. However, there is a clever +way to use the getelementptr instruction that allows you to compute this +in a portable way.

+ +
+ + + + + +
+ +

Some languages want to explicitly manage their stack frames, often so that +they are garbage collected or to allow easy implementation of closures. There +are often better ways to implement these features than explicit stack frames, +but LLVM +does support them, if you want. It requires your front-end to convert the +code into Continuation +Passing Style and the use of tail calls (which LLVM also supports).

+ +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/Makefile b/final/docs/tutorial/Makefile new file mode 100644 index 00000000000..9082ad4d857 --- /dev/null +++ b/final/docs/tutorial/Makefile @@ -0,0 +1,28 @@ +##===- docs/tutorial/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 + +HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) +EXTRA_DIST := $(HTML) index.html +HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/tutorial + +install-local:: $(HTML) + $(Echo) Installing HTML Tutorial Documentation + $(Verb) $(MKDIR) $(HTML_DIR) + $(Verb) $(DataInstall) $(HTML) $(HTML_DIR) + $(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR) + +uninstall-local:: + $(Echo) Uninstalling Tutorial Documentation + $(Verb) $(RM) -rf $(HTML_DIR) + +printvars:: + $(Echo) "HTML : " '$(HTML)' diff --git a/final/docs/tutorial/OCamlLangImpl1.html b/final/docs/tutorial/OCamlLangImpl1.html new file mode 100644 index 00000000000..98c1124cc12 --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl1.html @@ -0,0 +1,365 @@ + + + + + Kaleidoscope: Tutorial Introduction and the Lexer + + + + + + + + +
Kaleidoscope: Tutorial Introduction and the Lexer
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to the "Implementing a language with LLVM" tutorial. This tutorial +runs through the implementation of a simple language, showing how fun and +easy it can be. This tutorial will get you up and started as well as help to +build a framework you can extend to other languages. The code in this tutorial +can also be used as a playground to hack on other LLVM specific things. +

+ +

+The goal of this tutorial is to progressively unveil our language, describing +how it is built up over time. This will let us cover a fairly broad range of +language design and LLVM-specific usage issues, showing and explaining the code +for it all along the way, without overwhelming you with tons of details up +front.

+ +

It is useful to point out ahead of time that this tutorial is really about +teaching compiler techniques and LLVM specifically, not about teaching +modern and sane software engineering principles. In practice, this means that +we'll take a number of shortcuts to simplify the exposition. For example, the +code leaks memory, uses global variables all over the place, doesn't use nice +design patterns like visitors, etc... but it +is very simple. If you dig in and use the code as a basis for future projects, +fixing these deficiencies shouldn't be hard.

+ +

I've tried to put this tutorial together in a way that makes chapters easy to +skip over if you are already familiar with or are uninterested in the various +pieces. The structure of the tutorial is: +

+ +
    +
  • Chapter #1: Introduction to the Kaleidoscope +language, and the definition of its Lexer - This shows where we are going +and the basic functionality that we want it to do. In order to make this +tutorial maximally understandable and hackable, we choose to implement +everything in Objective Caml instead of using lexer and parser generators. +LLVM obviously works just fine with such tools, feel free to use one if you +prefer.
  • +
  • Chapter #2: Implementing a Parser and +AST - With the lexer in place, we can talk about parsing techniques and +basic AST construction. This tutorial describes recursive descent parsing and +operator precedence parsing. Nothing in Chapters 1 or 2 is LLVM-specific, +the code doesn't even link in LLVM at this point. :)
  • +
  • Chapter #3: Code generation to LLVM +IR - With the AST ready, we can show off how easy generation of LLVM IR +really is.
  • +
  • Chapter #4: Adding JIT and Optimizer +Support - Because a lot of people are interested in using LLVM as a JIT, +we'll dive right into it and show you the 3 lines it takes to add JIT support. +LLVM is also useful in many other ways, but this is one simple and "sexy" way +to shows off its power. :)
  • +
  • Chapter #5: Extending the Language: +Control Flow - With the language up and running, we show how to extend it +with control flow operations (if/then/else and a 'for' loop). This gives us a +chance to talk about simple SSA construction and control flow.
  • +
  • Chapter #6: Extending the Language: +User-defined Operators - This is a silly but fun chapter that talks about +extending the language to let the user program define their own arbitrary +unary and binary operators (with assignable precedence!). This lets us build a +significant piece of the "language" as library routines.
  • +
  • Chapter #7: Extending the Language: +Mutable Variables - This chapter talks about adding user-defined local +variables along with an assignment operator. The interesting part about this +is how easy and trivial it is to construct SSA form in LLVM: no, LLVM does +not require your front-end to construct SSA form!
  • +
  • Chapter #8: Conclusion and other +useful LLVM tidbits - This chapter wraps up the series by talking about +potential ways to extend the language, but also includes a bunch of pointers to +info about "special topics" like adding garbage collection support, exceptions, +debugging, support for "spaghetti stacks", and a bunch of other tips and +tricks.
  • + +
+ +

By the end of the tutorial, we'll have written a bit less than 700 lines of +non-comment, non-blank, lines of code. With this small amount of code, we'll +have built up a very reasonable compiler for a non-trivial language including +a hand-written lexer, parser, AST, as well as code generation support with a JIT +compiler. While other systems may have interesting "hello world" tutorials, +I think the breadth of this tutorial is a great testament to the strengths of +LLVM and why you should consider it if you're interested in language or compiler +design.

+ +

A note about this tutorial: we expect you to extend the language and play +with it on your own. Take the code and go crazy hacking away at it, compilers +don't need to be scary creatures - it can be a lot of fun to play with +languages!

+ +
+ + + + + +
+ +

This tutorial will be illustrated with a toy language that we'll call +"Kaleidoscope" (derived +from "meaning beautiful, form, and view"). +Kaleidoscope is a procedural language that allows you to define functions, use +conditionals, math, etc. Over the course of the tutorial, we'll extend +Kaleidoscope to support the if/then/else construct, a for loop, user defined +operators, JIT compilation with a simple command line interface, etc.

+ +

Because we want to keep things simple, the only datatype in Kaleidoscope is a +64-bit floating point type (aka 'float' in O'Caml parlance). As such, all +values are implicitly double precision and the language doesn't require type +declarations. This gives the language a very nice and simple syntax. For +example, the following simple example computes Fibonacci numbers:

+ +
+
+# Compute the x'th fibonacci number.
+def fib(x)
+  if x < 3 then
+    1
+  else
+    fib(x-1)+fib(x-2)
+
+# This expression will compute the 40th number.
+fib(40)
+
+
+ +

We also allow Kaleidoscope to call into standard library functions (the LLVM +JIT makes this completely trivial). This means that you can use the 'extern' +keyword to define a function before you use it (this is also useful for mutually +recursive functions). For example:

+ +
+
+extern sin(arg);
+extern cos(arg);
+extern atan2(arg1 arg2);
+
+atan2(sin(.4), cos(42))
+
+
+ +

A more interesting example is included in Chapter 6 where we write a little +Kaleidoscope application that displays +a Mandelbrot Set at various levels of magnification.

+ +

Lets dive into the implementation of this language!

+ +
+ + + + + +
+ +

When it comes to implementing a language, the first thing needed is +the ability to process a text file and recognize what it says. The traditional +way to do this is to use a "lexer" (aka 'scanner') +to break the input up into "tokens". Each token returned by the lexer includes +a token code and potentially some metadata (e.g. the numeric value of a number). +First, we define the possibilities: +

+ +
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+
+ +

Each token returned by our lexer will be one of the token variant values. +An unknown character like '+' will be returned as Token.Kwd '+'. If +the curr token is an identifier, the value will be Token.Ident s. If +the current token is a numeric literal (like 1.0), the value will be +Token.Number 1.0. +

+ +

The actual implementation of the lexer is a collection of functions driven +by a function named Lexer.lex. The Lexer.lex function is +called to return the next token from standard input. We will use +Camlp4 +to simplify the tokenization of the standard input. Its definition starts +as:

+ +
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+
+ +

+Lexer.lex works by recursing over a char Stream.t to read +characters one at a time from the standard input. It eats them as it recognizes +them and stores them in in a Token.token variant. The first thing that +it has to do is ignore whitespace between tokens. This is accomplished with the +recursive call above.

+ +

The next thing Lexer.lex needs to do is recognize identifiers and +specific keywords like "def". Kaleidoscope does this with a pattern match +and a helper function.

+ +

+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+...
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+
+ +

Numeric values are similar:

+ +
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+...
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+
+ +

This is all pretty straight-forward code for processing input. When reading +a numeric value from input, we use the ocaml float_of_string function +to convert it to a numeric value that we store in Token.Number. Note +that this isn't doing sufficient error checking: it will raise Failure +if the string "1.23.45.67". Feel free to extend it :). Next we handle +comments: +

+ +
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+...
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +

We handle comments by skipping to the end of the line and then return the +next token. Finally, if the input doesn't match one of the above cases, it is +either an operator character like '+' or the end of the file. These are handled +with this code:

+ +
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+
+ +

With this, we have the complete lexer for the basic Kaleidoscope language +(the full code listing for the Lexer is +available in the next chapter of the +tutorial). Next we'll build a simple parser that +uses this to build an Abstract Syntax Tree. When we have that, we'll +include a driver so that you can use the lexer and parser together. +

+ +Next: Implementing a Parser and AST +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl2.html b/final/docs/tutorial/OCamlLangImpl2.html new file mode 100644 index 00000000000..666510979fe --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl2.html @@ -0,0 +1,1045 @@ + + + + + Kaleidoscope: Implementing a Parser and AST + + + + + + + + +
Kaleidoscope: Implementing a Parser and AST
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 2 of the "Implementing a language +with LLVM in Objective Caml" tutorial. This chapter shows you how to use +the lexer, built in Chapter 1, to build a +full parser for our +Kaleidoscope language. Once we have a parser, we'll define and build an Abstract Syntax +Tree (AST).

+ +

The parser we will build uses a combination of Recursive Descent +Parsing and Operator-Precedence +Parsing to parse the Kaleidoscope language (the latter for +binary expressions and the former for everything else). Before we get to +parsing though, lets talk about the output of the parser: the Abstract Syntax +Tree.

+ +
+ + + + + +
+ +

The AST for a program captures its behavior in such a way that it is easy for +later stages of the compiler (e.g. code generation) to interpret. We basically +want one object for each construct in the language, and the AST should closely +model the language. In Kaleidoscope, we have expressions, a prototype, and a +function object. We'll start with expressions first:

+ +
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+
+ +

The code above shows the definition of the base ExprAST class and one +subclass which we use for numeric literals. The important thing to note about +this code is that the Number variant captures the numeric value of the +literal as an instance variable. This allows later phases of the compiler to +know what the stored numeric value is.

+ +

Right now we only create the AST, so there are no useful functions on +them. It would be very easy to add a function to pretty print the code, +for example. Here are the other expression AST node definitions that we'll use +in the basic form of the Kaleidoscope language: +

+ +
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+
+ +

This is all (intentionally) rather straight-forward: variables capture the +variable name, binary operators capture their opcode (e.g. '+'), and calls +capture a function name as well as a list of any argument expressions. One thing +that is nice about our AST is that it captures the language features without +talking about the syntax of the language. Note that there is no discussion about +precedence of binary operators, lexical structure, etc.

+ +

For our basic language, these are all of the expression nodes we'll define. +Because it doesn't have conditional control flow, it isn't Turing-complete; +we'll fix that in a later installment. The two things we need next are a way +to talk about the interface to a function, and a way to talk about functions +themselves:

+ +
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto = Prototype of string * string array
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +

In Kaleidoscope, functions are typed with just a count of their arguments. +Since all values are double precision floating point, the type of each argument +doesn't need to be stored anywhere. In a more aggressive and realistic +language, the "expr" variants would probably have a type field.

+ +

With this scaffolding, we can now talk about parsing expressions and function +bodies in Kaleidoscope.

+ +
+ + + + + +
+ +

Now that we have an AST to build, we need to define the parser code to build +it. The idea here is that we want to parse something like "x+y" (which is +returned as three tokens by the lexer) into an AST that could be generated with +calls like this:

+ +
+
+  let x = Variable "x" in
+  let y = Variable "y" in
+  let result = Binary ('+', x, y) in
+  ...
+
+
+ +

+The error handling routines make use of the builtin Stream.Failure and +Stream.Errors. Stream.Failure is raised when the parser is +unable to find any matching token in the first position of a pattern. +Stream.Error is raised when the first token matches, but the rest do +not. The error recovery in our parser will not be the best and is not +particular user-friendly, but it will be enough for our tutorial. These +exceptions make it easier to handle errors in routines that have various return +types.

+ +

With these basic types and exceptions, we can implement the first +piece of our grammar: numeric literals.

+ +
+ + + + + +
+ +

We start with numeric literals, because they are the simplest to process. +For each production in our grammar, we'll define a function which parses that +production. We call this class of expressions "primary" expressions, for +reasons that will become more clear +later in the tutorial. In order to parse an arbitrary primary expression, +we need to determine what sort of expression it is. For numeric literals, we +have:

+ +
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr *)
+parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+
+ +

This routine is very simple: it expects to be called when the current token +is a Token.Number token. It takes the current number value, creates +a Ast.Number node, advances the lexer to the next token, and finally +returns.

+ +

There are some interesting aspects to this. The most important one is that +this routine eats all of the tokens that correspond to the production and +returns the lexer buffer with the next token (which is not part of the grammar +production) ready to go. This is a fairly standard way to go for recursive +descent parsers. For a better example, the parenthesis operator is defined like +this:

+ +
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+
+ +

This function illustrates a number of interesting things about the +parser:

+ +

+1) It shows how we use the Stream.Error exception. When called, this +function expects that the current token is a '(' token, but after parsing the +subexpression, it is possible that there is no ')' waiting. For example, if +the user types in "(4 x" instead of "(4)", the parser should emit an error. +Because errors can occur, the parser needs a way to indicate that they +happened. In our parser, we use the camlp4 shortcut syntax token ?? "parse +error", where if the token before the ?? does not match, then +Stream.Error "parse error" will be raised.

+ +

2) Another interesting aspect of this function is that it uses recursion by +calling Parser.parse_primary (we will soon see that +Parser.parse_primary can call Parser.parse_primary). This is +powerful because it allows us to handle recursive grammars, and keeps each +production very simple. Note that parentheses do not cause construction of AST +nodes themselves. While we could do it this way, the most important role of +parentheses are to guide the parser and provide grouping. Once the parser +constructs the AST, parentheses are not needed.

+ +

The next simple production is for handling variable references and function +calls:

+ +
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+
+ +

This routine follows the same style as the other routines. (It expects to be +called if the current token is a Token.Ident token). It also has +recursion and error handling. One interesting aspect of this is that it uses +look-ahead to determine if the current identifier is a stand alone +variable reference or if it is a function call expression. It handles this by +checking to see if the token after the identifier is a '(' token, constructing +either a Ast.Variable or Ast.Call node as appropriate. +

+ +

We finish up by raising an exception if we received a token we didn't +expect:

+ +
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+
+ +

Now that basic expressions are handled, we need to handle binary expressions. +They are a bit more complex.

+ +
+ + + + + +
+ +

Binary expressions are significantly harder to parse because they are often +ambiguous. For example, when given the string "x+y*z", the parser can choose +to parse it as either "(x+y)*z" or "x+(y*z)". With common definitions from +mathematics, we expect the later parse, because "*" (multiplication) has +higher precedence than "+" (addition).

+ +

There are many ways to handle this, but an elegant and efficient way is to +use Operator-Precedence +Parsing. This parsing technique uses the precedence of binary operators to +guide recursion. To start with, we need a table of precedences:

+ +
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+...
+
+let main () =
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+  ...
+
+
+ +

For the basic form of Kaleidoscope, we will only support 4 binary operators +(this can obviously be extended by you, our brave and intrepid reader). The +Parser.precedence function returns the precedence for the current +token, or -1 if the token is not a binary operator. Having a Hashtbl.t +makes it easy to add new operators and makes it clear that the algorithm doesn't +depend on the specific operators involved, but it would be easy enough to +eliminate the Hashtbl.t and do the comparisons in the +Parser.precedence function. (Or just use a fixed-size array).

+ +

With the helper above defined, we can now start parsing binary expressions. +The basic idea of operator precedence parsing is to break down an expression +with potentially ambiguous binary operators into pieces. Consider ,for example, +the expression "a+b+(c+d)*e*f+g". Operator precedence parsing considers this +as a stream of primary expressions separated by binary operators. As such, +it will first parse the leading primary expression "a", then it will see the +pairs [+, b] [+, (c+d)] [*, e] [*, f] and [+, g]. Note that because parentheses +are primary expressions, the binary expression parser doesn't need to worry +about nested subexpressions like (c+d) at all. +

+ +

+To start, an expression is a primary expression potentially followed by a +sequence of [binop,primaryexpr] pairs:

+ +
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
+
+
+ +

Parser.parse_bin_rhs is the function that parses the sequence of +pairs for us. It takes a precedence and a pointer to an expression for the part +that has been parsed so far. Note that "x" is a perfectly valid expression: As +such, "binoprhs" is allowed to be empty, in which case it returns the expression +that is passed into it. In our example above, the code passes the expression for +"a" into Parser.parse_bin_rhs and the current token is "+".

+ +

The precedence value passed into Parser.parse_bin_rhs indicates the +minimal operator precedence that the function is allowed to eat. For +example, if the current pair stream is [+, x] and Parser.parse_bin_rhs +is passed in a precedence of 40, it will not consume any tokens (because the +precedence of '+' is only 20). With this in mind, Parser.parse_bin_rhs +starts with:

+ +
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+
+
+ +

This code gets the precedence of the current token and checks to see if if is +too low. Because we defined invalid tokens to have a precedence of -1, this +check implicitly knows that the pair-stream ends when the token stream runs out +of binary operators. If this check succeeds, we know that the token is a binary +operator and that it will be included in this expression:

+ +
+
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+
+
+ +

As such, this code eats (and remembers) the binary operator and then parses +the primary expression that follows. This builds up the whole pair, the first of +which is [+, b] for the running example.

+ +

Now that we parsed the left-hand side of an expression and one pair of the +RHS sequence, we have to decide which way the expression associates. In +particular, we could have "(a+b) binop unparsed" or "a + (b binop unparsed)". +To determine this, we look ahead at "binop" to determine its precedence and +compare it to BinOp's precedence (which is '+' in this case):

+ +
+
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+
+
+ +

If the precedence of the binop to the right of "RHS" is lower or equal to the +precedence of our current operator, then we know that the parentheses associate +as "(a+b) binop ...". In our example, the current operator is "+" and the next +operator is "+", we know that they have the same precedence. In this case we'll +create the AST node for "a+b", and then continue parsing:

+ +
+
+          ... if body omitted ...
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+
+
+ +

In our example above, this will turn "a+b+" into "(a+b)" and execute the next +iteration of the loop, with "+" as the current token. The code above will eat, +remember, and parse "(c+d)" as the primary expression, which makes the +current pair equal to [+, (c+d)]. It will then evaluate the 'if' conditional above with +"*" as the binop to the right of the primary. In this case, the precedence of "*" is +higher than the precedence of "+" so the if condition will be entered.

+ +

The critical question left here is "how can the if condition parse the right +hand side in full"? In particular, to build the AST correctly for our example, +it needs to get all of "(c+d)*e*f" as the RHS expression variable. The code to +do this is surprisingly simple (code from the above two blocks duplicated for +context):

+ +
+
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              if token_prec < precedence c2
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+
+
+ +

At this point, we know that the binary operator to the RHS of our primary +has higher precedence than the binop we are currently parsing. As such, we know +that any sequence of pairs whose operators are all higher precedence than "+" +should be parsed together and returned as "RHS". To do this, we recursively +invoke the Parser.parse_bin_rhs function specifying "token_prec+1" as +the minimum precedence required for it to continue. In our example above, this +will cause it to return the AST node for "(c+d)*e*f" as RHS, which is then set +as the RHS of the '+' expression.

+ +

Finally, on the next iteration of the while loop, the "+g" piece is parsed +and added to the AST. With this little bit of code (14 non-trivial lines), we +correctly handle fully general binary expression parsing in a very elegant way. +This was a whirlwind tour of this code, and it is somewhat subtle. I recommend +running through it with a few tough examples to see how it works. +

+ +

This wraps up handling of expressions. At this point, we can point the +parser at an arbitrary token stream and build an expression from it, stopping +at the first token that is not part of the expression. Next up we need to +handle function definitions, etc.

+ +
+ + + + + +
+ +

+The next thing missing is handling of function prototypes. In Kaleidoscope, +these are used both for 'extern' function declarations as well as function body +definitions. The code to do this is straight-forward and not very interesting +(once you've survived expressions): +

+ +
+
+(* prototype
+ *   ::= id '(' id* ')' *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+
+ +

Given this, a function definition is very simple, just a prototype plus +an expression to implement the body:

+ +
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+
+ +

In addition, we support 'extern' to declare functions like 'sin' and 'cos' as +well as to support forward declaration of user functions. These 'extern's are just +prototypes with no body:

+ +
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +

Finally, we'll also let the user type in arbitrary top-level expressions and +evaluate them on the fly. We will handle this by defining anonymous nullary +(zero argument) functions for them:

+ +
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+
+ +

Now that we have all the pieces, let's build a little driver that will let us +actually execute this code we've built!

+ +
+ + + + + +
+ +

The driver for this simply invokes all of the parsing pieces with a top-level +dispatch loop. There isn't much interesting here, so I'll just include the +top-level loop. See below for full code in the "Top-Level +Parsing" section.

+ +
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            ignore(Parser.parse_definition stream);
+            print_endline "parsed a function definition.";
+        | Token.Extern ->
+            ignore(Parser.parse_extern stream);
+            print_endline "parsed an extern.";
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            ignore(Parser.parse_toplevel stream);
+            print_endline "parsed a top-level expr";
+        with Stream.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop stream
+
+
+ +

The most interesting part of this is that we ignore top-level semicolons. +Why is this, you ask? The basic reason is that if you type "4 + 5" at the +command line, the parser doesn't know whether that is the end of what you will type +or not. For example, on the next line you could type "def foo..." in which case +4+5 is the end of a top-level expression. Alternatively you could type "* 6", +which would continue the expression. Having top-level semicolons allows you to +type "4+5;", and the parser will know you are done.

+ +
+ + + + + +
+ +

With just under 300 lines of commented code (240 lines of non-comment, +non-blank code), we fully defined our minimal language, including a lexer, +parser, and AST builder. With this done, the executable will validate +Kaleidoscope code and tell us if it is grammatically invalid. For +example, here is a sample interaction:

+ +
+
+$ ./toy.byte
+ready> def foo(x y) x+foo(y, 4.0);
+Parsed a function definition.
+ready> def foo(x y) x+y y;
+Parsed a function definition.
+Parsed a top-level expr
+ready> def foo(x y) x+y );
+Parsed a function definition.
+Error: unknown token when expecting an expression
+ready> extern sin(a);
+ready> Parsed an extern
+ready> ^D
+$
+
+
+ +

There is a lot of room for extension here. You can define new AST nodes, +extend the language in many ways, etc. In the +next installment, we will describe how to generate LLVM Intermediate +Representation (IR) from the AST.

+ +
+ + + + + +
+ +

+Here is the complete code listing for this and the previous chapter. +Note that it is fully self-contained: you don't need LLVM or any external +libraries at all for this. (Besides the ocaml standard libraries, of +course.) To build this, just compile with:

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto = Prototype of string * string array
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the primary expression after the binary operator. *)
+        let rhs = parse_primary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')' *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            ignore(Parser.parse_definition stream);
+            print_endline "parsed a function definition.";
+        | Token.Extern ->
+            ignore(Parser.parse_extern stream);
+            print_endline "parsed an extern.";
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            ignore(Parser.parse_toplevel stream);
+            print_endline "parsed a top-level expr";
+        with Stream.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+let main () =
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop stream;
+;;
+
+main ()
+
+
+
+ +Next: Implementing Code Generation to LLVM IR +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner + Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl3.html b/final/docs/tutorial/OCamlLangImpl3.html new file mode 100644 index 00000000000..d55fd0fd0cb --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl3.html @@ -0,0 +1,1093 @@ + + + + + Kaleidoscope: Implementing code generation to LLVM IR + + + + + + + + +
Kaleidoscope: Code generation to LLVM IR
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 3 of the "Implementing a language +with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into +LLVM IR. This will teach you a little bit about how LLVM does things, as well +as demonstrate how easy it is to use. It's much more work to build a lexer and +parser than it is to generate LLVM IR code. :) +

+ +

Please note: the code in this chapter and later require LLVM 2.3 or +LLVM SVN to work. LLVM 2.2 and before will not work with it.

+ +
+ + + + + +
+ +

+In order to generate LLVM IR, we want some simple setup to get started. First +we define virtual code generation (codegen) methods in each AST class:

+ +
+
+let rec codegen_expr = function
+  | Ast.Number n -> ...
+  | Ast.Variable name -> ...
+
+
+ +

The Codegen.codegen_expr function says to emit IR for that AST node +along with all the things it depends on, and they all return an LLVM Value +object. "Value" is the class used to represent a "Static Single +Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect +of SSA values is that their value is computed as the related instruction +executes, and it does not get a new value until (and if) the instruction +re-executes. In other words, there is no way to "change" an SSA value. For +more information, please read up on Static Single +Assignment - the concepts are really quite natural once you grok them.

+ +

The +second thing we want is an "Error" exception like we used for the parser, which +will be used to report errors found during code generation (for example, use of +an undeclared parameter):

+ +
+
+exception Error of string
+
+let the_module = create_module (global_context ()) "my cool jit"
+let builder = builder (global_context ())
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+
+ +

The static variables will be used during code generation. +Codgen.the_module is the LLVM construct that contains all of the +functions and global variables in a chunk of code. In many ways, it is the +top-level structure that the LLVM IR uses to contain code.

+ +

The Codegen.builder object is a helper object that makes it easy to +generate LLVM instructions. Instances of the IRBuilder +class keep track of the current place to insert instructions and has methods to +create new instructions.

+ +

The Codegen.named_values map keeps track of which values are defined +in the current scope and what their LLVM representation is. (In other words, it +is a symbol table for the code). In this form of Kaleidoscope, the only things +that can be referenced are function parameters. As such, function parameters +will be in this map when generating code for their function body.

+ +

+With these basics in place, we can start talking about how to generate code for +each expression. Note that this assumes that the Codgen.builder has +been set up to generate code into something. For now, we'll assume +that this has already been done, and we'll just use it to emit code.

+ +
+ + + + + +
+ +

Generating LLVM code for expression nodes is very straightforward: less +than 30 lines of commented code for all four of our expression nodes. First +we'll do numeric literals:

+ +
+
+  | Ast.Number n -> const_float double_type n
+
+
+ +

In the LLVM IR, numeric constants are represented with the +ConstantFP class, which holds the numeric value in an APFloat +internally (APFloat has the capability of holding floating point +constants of Arbitrary Precision). This code basically just +creates and returns a ConstantFP. Note that in the LLVM IR +that constants are all uniqued together and shared. For this reason, the API +uses "the foo::get(..)" idiom instead of "new foo(..)" or "foo::Create(..)".

+ +
+
+  | Ast.Variable name ->
+      (try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name"))
+
+
+ +

References to variables are also quite simple using LLVM. In the simple +version of Kaleidoscope, we assume that the variable has already been emitted +somewhere and its value is available. In practice, the only values that can be +in the Codegen.named_values map are function arguments. This code +simply checks to see that the specified name is in the map (if not, an unknown +variable is being referenced) and returns the value for it. In future chapters, +we'll add support for loop induction variables +in the symbol table, and for local +variables.

+ +
+
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ -> raise (Error "invalid binary operator")
+      end
+
+
+ +

Binary operators start to get more interesting. The basic idea here is that +we recursively emit code for the left-hand side of the expression, then the +right-hand side, then we compute the result of the binary expression. In this +code, we do a simple switch on the opcode to create the right LLVM instruction. +

+ +

In the example above, the LLVM builder class is starting to show its value. +IRBuilder knows where to insert the newly created instruction, all you have to +do is specify what instruction to create (e.g. with Llvm.create_add), +which operands to use (lhs and rhs here) and optionally +provide a name for the generated instruction.

+ +

One nice thing about LLVM is that the name is just a hint. For instance, if +the code above emits multiple "addtmp" variables, LLVM will automatically +provide each one with an increasing, unique numeric suffix. Local value names +for instructions are purely optional, but it makes it much easier to read the +IR dumps.

+ +

LLVM instructions are constrained by +strict rules: for example, the Left and Right operators of +an add instruction must have the same +type, and the result type of the add must match the operand types. Because +all values in Kaleidoscope are doubles, this makes for very simple code for add, +sub and mul.

+ +

On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value +(a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with +a uitofp instruction. This instruction +converts its input integer into a floating point value by treating the input +as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' +operator would return 0.0 and -1.0, depending on the input value.

+ +
+
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+
+
+ +

Code generation for function calls is quite straightforward with LLVM. The +code above initially does a function name lookup in the LLVM Module's symbol +table. Recall that the LLVM Module is the container that holds all of the +functions we are JIT'ing. By giving each function the same name as what the +user specifies, we can use the LLVM symbol table to resolve function names for +us.

+ +

Once we have the function to call, we recursively codegen each argument that +is to be passed in, and create an LLVM call +instruction. Note that LLVM uses the native C calling conventions by +default, allowing these calls to also call into standard library functions like +"sin" and "cos", with no additional effort.

+ +

This wraps up our handling of the four basic expressions that we have so far +in Kaleidoscope. Feel free to go in and add some more. For example, by +browsing the LLVM language reference you'll find +several other interesting instructions that are really easy to plug into our +basic framework.

+ +
+ + + + + +
+ +

Code generation for prototypes and functions must handle a number of +details, which make their code less beautiful than expression code +generation, but allows us to illustrate some important points. First, lets +talk about code generation for prototypes: they are used both for function +bodies and external function declarations. The code starts with:

+ +
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+
+
+ +

This code packs a lot of power into a few lines. Note first that this +function returns a "Function*" instead of a "Value*" (although at the moment +they both are modeled by llvalue in ocaml). Because a "prototype" +really talks about the external interface for a function (not the value computed +by an expression), it makes sense for it to return the LLVM Function it +corresponds to when codegen'd.

+ +

The call to Llvm.function_type creates the Llvm.llvalue +that should be used for a given Prototype. Since all function arguments in +Kaleidoscope are of type double, the first line creates a vector of "N" LLVM +double types. It then uses the Llvm.function_type method to create a +function type that takes "N" doubles as arguments, returns one double as a +result, and that is not vararg (that uses the function +Llvm.var_arg_function_type). Note that Types in LLVM are uniqued just +like Constants are, so you don't "new" a type, you "get" it.

+ +

The final line above checks if the function has already been defined in +Codegen.the_module. If not, we will create it.

+ +
+
+        | None -> declare_function name ft the_module
+
+
+ +

This indicates the type and name to use, as well as which module to insert +into. By default we assume a function has +Llvm.Linkage.ExternalLinkage. "external +linkage" means that the function may be defined outside the current module +and/or that it is callable by functions outside the module. The "name" +passed in is the name the user specified: this name is registered in +"Codegen.the_module"s symbol table, which is used by the function call +code above.

+ +

In Kaleidoscope, I choose to allow redefinitions of functions in two cases: +first, we want to allow 'extern'ing a function more than once, as long as the +prototypes for the externs match (since all arguments have the same type, we +just have to check that the number of arguments match). Second, we want to +allow 'extern'ing a function and then defining a body for it. This is useful +when defining mutually recursive functions.

+ +
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if Array.length (basic_blocks f) == 0 then () else
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if Array.length (params f) == Array.length args then () else
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+
+ +

In order to verify the logic above, we first check to see if the pre-existing +function is "empty". In this case, empty means that it has no basic blocks in +it, which means it has no body. If it has no body, it is a forward +declaration. Since we don't allow anything after a full definition of the +function, the code rejects this case. If the previous reference to a function +was an 'extern', we simply verify that the number of arguments for that +definition and this one match up. If not, we emit an error.

+ +
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+
+ +

The last bit of code for prototypes loops over all of the arguments in the +function, setting the name of the LLVM Argument objects to match, and registering +the arguments in the Codegen.named_values map for future use by the +Ast.Variable variant. Once this is set up, it returns the Function +object to the caller. Note that we don't check for conflicting +argument names here (e.g. "extern foo(a b a)"). Doing so would be very +straight-forward with the mechanics we have already used above.

+ +
+
+let codegen_func = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+
+ +

Code generation for function definitions starts out simply enough: we just +codegen the prototype (Proto) and verify that it is ok. We then clear out the +Codegen.named_values map to make sure that there isn't anything in it +from the last function we compiled. Code generation of the prototype ensures +that there is an LLVM Function object that is ready to go for us.

+ +
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        let ret_val = codegen_expr body in
+
+
+ +

Now we get to the point where the Codegen.builder is set up. The +first line creates a new +basic block (named +"entry"), which is inserted into the_function. The second line then +tells the builder that new instructions should be inserted into the end of the +new basic block. Basic blocks in LLVM are an important part of functions that +define the Control Flow Graph. +Since we don't have any control flow, our functions will only contain one +block at this point. We'll fix this in Chapter +5 :).

+ +
+
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        the_function
+
+
+ +

Once the insertion point is set up, we call the Codegen.codegen_func +method for the root expression of the function. If no error happens, this emits +code to compute the expression into the entry block and returns the value that +was computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. +Once the function is built, we call +Llvm_analysis.assert_valid_function, which is provided by LLVM. This +function does a variety of consistency checks on the generated code, to +determine if our compiler is doing everything right. Using this is important: +it can catch a lot of bugs. Once the function is finished and validated, we +return it.

+ +
+
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +

The only piece left here is handling of the error case. For simplicity, we +handle this by merely deleting the function we produced with the +Llvm.delete_function method. This allows the user to redefine a +function that they incorrectly typed in before: if we didn't delete it, it +would live in the symbol table, with a body, preventing future redefinition.

+ +

This code does have a bug, though. Since the Codegen.codegen_proto +can return a previously defined forward declaration, our code can actually delete +a forward declaration. There are a number of ways to fix this bug, see what you +can come up with! Here is a testcase:

+ +
+
+extern foo(a b);     # ok, defines foo.
+def foo(a b) c;      # error, 'c' is invalid.
+def bar() foo(1, 2); # error, unknown function "foo"
+
+
+ +
+ + + + + +
+ +

+For now, code generation to LLVM doesn't really get us much, except that we can +look at the pretty IR calls. The sample code inserts calls to Codegen into the +"Toplevel.main_loop", and then dumps out the LLVM IR. This gives a +nice way to look at the LLVM IR for simple functions. For example: +

+ +
+
+ready> 4+5;
+Read top-level expression:
+define double @""() {
+entry:
+        %addtmp = fadd double 4.000000e+00, 5.000000e+00
+        ret double %addtmp
+}
+
+
+ +

Note how the parser turns the top-level expression into anonymous functions +for us. This will be handy when we add JIT +support in the next chapter. Also note that the code is very literally +transcribed, no optimizations are being performed. We will +add optimizations explicitly +in the next chapter.

+ +
+
+ready> def foo(a b) a*a + 2*a*b + b*b;
+Read function definition:
+define double @foo(double %a, double %b) {
+entry:
+        %multmp = fmul double %a, %a
+        %multmp1 = fmul double 2.000000e+00, %a
+        %multmp2 = fmul double %multmp1, %b
+        %addtmp = fadd double %multmp, %multmp2
+        %multmp3 = fmul double %b, %b
+        %addtmp4 = fadd double %addtmp, %multmp3
+        ret double %addtmp4
+}
+
+
+ +

This shows some simple arithmetic. Notice the striking similarity to the +LLVM builder calls that we use to create the instructions.

+ +
+
+ready> def bar(a) foo(a, 4.0) + bar(31337);
+Read function definition:
+define double @bar(double %a) {
+entry:
+        %calltmp = call double @foo(double %a, double 4.000000e+00)
+        %calltmp1 = call double @bar(double 3.133700e+04)
+        %addtmp = fadd double %calltmp, %calltmp1
+        ret double %addtmp
+}
+
+
+ +

This shows some function calls. Note that this function will take a long +time to execute if you call it. In the future we'll add conditional control +flow to actually make recursion useful :).

+ +
+
+ready> extern cos(x);
+Read extern:
+declare double @cos(double)
+
+ready> cos(1.234);
+Read top-level expression:
+define double @""() {
+entry:
+        %calltmp = call double @cos(double 1.234000e+00)
+        ret double %calltmp
+}
+
+
+ +

This shows an extern for the libm "cos" function, and a call to it.

+ + +
+
+ready> ^D
+; ModuleID = 'my cool jit'
+
+define double @""() {
+entry:
+        %addtmp = fadd double 4.000000e+00, 5.000000e+00
+        ret double %addtmp
+}
+
+define double @foo(double %a, double %b) {
+entry:
+        %multmp = fmul double %a, %a
+        %multmp1 = fmul double 2.000000e+00, %a
+        %multmp2 = fmul double %multmp1, %b
+        %addtmp = fadd double %multmp, %multmp2
+        %multmp3 = fmul double %b, %b
+        %addtmp4 = fadd double %addtmp, %multmp3
+        ret double %addtmp4
+}
+
+define double @bar(double %a) {
+entry:
+        %calltmp = call double @foo(double %a, double 4.000000e+00)
+        %calltmp1 = call double @bar(double 3.133700e+04)
+        %addtmp = fadd double %calltmp, %calltmp1
+        ret double %addtmp
+}
+
+declare double @cos(double)
+
+define double @""() {
+entry:
+        %calltmp = call double @cos(double 1.234000e+00)
+        ret double %calltmp
+}
+
+
+ +

When you quit the current demo, it dumps out the IR for the entire module +generated. Here you can see the big picture with all the functions referencing +each other.

+ +

This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll +describe how to add JIT codegen and optimizer +support to this so we can actually start running code!

+ +
+ + + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +LLVM code generator. Because this uses the LLVM libraries, we need to link +them in. To do this, we use the llvm-config tool to inform +our makefile/command line about which options to use:

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
+
+
+ +
myocamlbuild.ml:
+
+
+open Ocamlbuild_plugin;;
+
+ocaml_lib ~extern:true "llvm";;
+ocaml_lib ~extern:true "llvm_analysis";;
+
+flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto = Prototype of string * string array
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the primary expression after the binary operator. *)
+        let rhs = parse_primary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')' *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
codegen.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Code Generation
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+exception Error of string
+
+let context = global_context ()
+let the_module = create_module context "my cool jit"
+let builder = builder context
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+let rec codegen_expr = function
+  | Ast.Number n -> const_float double_type n
+  | Ast.Variable name ->
+      (try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name"))
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ -> raise (Error "invalid binary operator")
+      end
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+        | None -> declare_function name ft the_module
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if block_begin f <> At_end f then
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if element_type (type_of f) <> ft then
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+let codegen_func = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        the_function
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            let e = Parser.parse_definition stream in
+            print_endline "parsed a function definition.";
+            dump_value (Codegen.codegen_func e);
+        | Token.Extern ->
+            let e = Parser.parse_extern stream in
+            print_endline "parsed an extern.";
+            dump_value (Codegen.codegen_proto e);
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            dump_value (Codegen.codegen_func e);
+        with Stream.Error s | Codegen.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+let main () =
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop stream;
+
+  (* Print out all the generated code. *)
+  dump_module Codegen.the_module
+;;
+
+main ()
+
+
+
+ +Next: Adding JIT and Optimizer Support +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl4.html b/final/docs/tutorial/OCamlLangImpl4.html new file mode 100644 index 00000000000..979119afbc1 --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl4.html @@ -0,0 +1,1029 @@ + + + + + Kaleidoscope: Adding JIT and Optimizer Support + + + + + + + + +
Kaleidoscope: Adding JIT and Optimizer Support
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 4 of the "Implementing a language +with LLVM" tutorial. Chapters 1-3 described the implementation of a simple +language and added support for generating LLVM IR. This chapter describes +two new techniques: adding optimizer support to your language, and adding JIT +compiler support. These additions will demonstrate how to get nice, efficient code +for the Kaleidoscope language.

+ +
+ + + + + +
+ +

Note: the default IRBuilder now always includes the constant +folding optimisations below.

+ +

+Our demonstration for Chapter 3 is elegant and easy to extend. Unfortunately, +it does not produce wonderful code. For example, when compiling simple code, +we don't get obvious optimizations:

+ +
+
+ready> def test(x) 1+2+x;
+Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 1.000000e+00, 2.000000e+00
+        %addtmp1 = fadd double %addtmp, %x
+        ret double %addtmp1
+}
+
+
+ +

This code is a very, very literal transcription of the AST built by parsing +the input. As such, this transcription lacks optimizations like constant folding +(we'd like to get "add x, 3.0" in the example above) as well as other +more important optimizations. Constant folding, in particular, is a very common +and very important optimization: so much so that many language implementors +implement constant folding support in their AST representation.

+ +

With LLVM, you don't need this support in the AST. Since all calls to build +LLVM IR go through the LLVM builder, it would be nice if the builder itself +checked to see if there was a constant folding opportunity when you call it. +If so, it could just do the constant fold and return the constant instead of +creating an instruction. This is exactly what the LLVMFoldingBuilder +class does. + +

All we did was switch from LLVMBuilder to +LLVMFoldingBuilder. Though we change no other code, we now have all of our +instructions implicitly constant folded without us having to do anything +about it. For example, the input above now compiles to:

+ +
+
+ready> def test(x) 1+2+x;
+Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 3.000000e+00, %x
+        ret double %addtmp
+}
+
+
+ +

Well, that was easy :). In practice, we recommend always using +LLVMFoldingBuilder when generating code like this. It has no +"syntactic overhead" for its use (you don't have to uglify your compiler with +constant checks everywhere) and it can dramatically reduce the amount of +LLVM IR that is generated in some cases (particular for languages with a macro +preprocessor or that use a lot of constants).

+ +

On the other hand, the LLVMFoldingBuilder is limited by the fact +that it does all of its analysis inline with the code as it is built. If you +take a slightly more complex example:

+ +
+
+ready> def test(x) (1+2+x)*(x+(1+2));
+ready> Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double 3.000000e+00, %x
+        %addtmp1 = fadd double %x, 3.000000e+00
+        %multmp = fmul double %addtmp, %addtmp1
+        ret double %multmp
+}
+
+
+ +

In this case, the LHS and RHS of the multiplication are the same value. We'd +really like to see this generate "tmp = x+3; result = tmp*tmp;" instead +of computing "x*3" twice.

+ +

Unfortunately, no amount of local analysis will be able to detect and correct +this. This requires two transformations: reassociation of expressions (to +make the add's lexically identical) and Common Subexpression Elimination (CSE) +to delete the redundant add instruction. Fortunately, LLVM provides a broad +range of optimizations that you can use, in the form of "passes".

+ +
+ + + + + +
+ +

LLVM provides many optimization passes, which do many different sorts of +things and have different tradeoffs. Unlike other systems, LLVM doesn't hold +to the mistaken notion that one set of optimizations is right for all languages +and for all situations. LLVM allows a compiler implementor to make complete +decisions about what optimizations to use, in which order, and in what +situation.

+ +

As a concrete example, LLVM supports both "whole module" passes, which look +across as large of body of code as they can (often a whole file, but if run +at link time, this can be a substantial portion of the whole program). It also +supports and includes "per-function" passes which just operate on a single +function at a time, without looking at other functions. For more information +on passes and how they are run, see the How +to Write a Pass document and the List of LLVM +Passes.

+ +

For Kaleidoscope, we are currently generating functions on the fly, one at +a time, as the user types them in. We aren't shooting for the ultimate +optimization experience in this setting, but we also want to catch the easy and +quick stuff where possible. As such, we will choose to run a few per-function +optimizations as the user types the function in. If we wanted to make a "static +Kaleidoscope compiler", we would use exactly the code we have now, except that +we would defer running the optimizer until the entire file has been parsed.

+ +

In order to get per-function optimizations going, we need to set up a +Llvm.PassManager to hold and +organize the LLVM optimizations that we want to run. Once we have that, we can +add a set of optimizations to run. The code looks like this:

+ +
+
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combining the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+  (* Eliminate Common SubExpressions. *)
+  add_gvn the_fpm;
+
+  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
+  add_cfg_simplification the_fpm;
+
+  ignore (PassManager.initialize the_fpm);
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop the_fpm the_execution_engine stream;
+
+
+ +

The meat of the matter here, is the definition of "the_fpm". It +requires a pointer to the the_module to construct itself. Once it is +set up, we use a series of "add" calls to add a bunch of LLVM passes. The +first pass is basically boilerplate, it adds a pass so that later optimizations +know how the data structures in the program are laid out. The +"the_execution_engine" variable is related to the JIT, which we will +get to in the next section.

+ +

In this case, we choose to add 4 optimization passes. The passes we chose +here are a pretty standard set of "cleanup" optimizations that are useful for +a wide variety of code. I won't delve into what they do but, believe me, +they are a good starting place :).

+ +

Once the Llvm.PassManager. is set up, we need to make use of it. +We do this by running it after our newly created function is constructed (in +Codegen.codegen_func), but before it is returned to the client:

+ +
+
+let codegen_func the_fpm = function
+      ...
+      try
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        (* Optimize the function. *)
+        let _ = PassManager.run_function the_function the_fpm in
+
+        the_function
+
+
+ +

As you can see, this is pretty straightforward. The the_fpm +optimizes and updates the LLVM Function* in place, improving (hopefully) its +body. With this in place, we can try our test above again:

+ +
+
+ready> def test(x) (1+2+x)*(x+(1+2));
+ready> Read function definition:
+define double @test(double %x) {
+entry:
+        %addtmp = fadd double %x, 3.000000e+00
+        %multmp = fmul double %addtmp, %addtmp
+        ret double %multmp
+}
+
+
+ +

As expected, we now get our nicely optimized code, saving a floating point +add instruction from every execution of this function.

+ +

LLVM provides a wide variety of optimizations that can be used in certain +circumstances. Some documentation about the various +passes is available, but it isn't very complete. Another good source of +ideas can come from looking at the passes that llvm-gcc or +llvm-ld run to get started. The "opt" tool allows you to +experiment with passes from the command line, so you can see if they do +anything.

+ +

Now that we have reasonable code coming out of our front-end, lets talk about +executing it!

+ +
+ + + + + +
+ +

Code that is available in LLVM IR can have a wide variety of tools +applied to it. For example, you can run optimizations on it (as we did above), +you can dump it out in textual or binary forms, you can compile the code to an +assembly file (.s) for some target, or you can JIT compile it. The nice thing +about the LLVM IR representation is that it is the "common currency" between +many different parts of the compiler. +

+ +

In this section, we'll add JIT compiler support to our interpreter. The +basic idea that we want for Kaleidoscope is to have the user enter function +bodies as they do now, but immediately evaluate the top-level expressions they +type in. For example, if they type in "1 + 2;", we should evaluate and print +out 3. If they define a function, they should be able to call it from the +command line.

+ +

In order to do this, we first declare and initialize the JIT. This is done +by adding a global variable and a call in main:

+ +
+
+...
+let main () =
+  ...
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  ...
+
+
+ +

This creates an abstract "Execution Engine" which can be either a JIT +compiler or the LLVM interpreter. LLVM will automatically pick a JIT compiler +for you if one is available for your platform, otherwise it will fall back to +the interpreter.

+ +

Once the Llvm_executionengine.ExecutionEngine.t is created, the JIT +is ready to be used. There are a variety of APIs that are useful, but the +simplest one is the "Llvm_executionengine.ExecutionEngine.run_function" +function. This method JIT compiles the specified LLVM Function and returns a +function pointer to the generated machine code. In our case, this means that we +can change the code that parses a top-level expression to look like this:

+ +
+
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            let the_function = Codegen.codegen_func the_fpm e in
+            dump_value the_function;
+
+            (* JIT the function, returning a function pointer. *)
+            let result = ExecutionEngine.run_function the_function [||]
+              the_execution_engine in
+
+            print_string "Evaluated to ";
+            print_float (GenericValue.as_float Codegen.double_type result);
+            print_newline ();
+
+
+ +

Recall that we compile top-level expressions into a self-contained LLVM +function that takes no arguments and returns the computed double. Because the +LLVM JIT compiler matches the native platform ABI, this means that you can just +cast the result pointer to a function pointer of that type and call it directly. +This means, there is no difference between JIT compiled code and native machine +code that is statically linked into your application.

+ +

With just these two changes, lets see how Kaleidoscope works now!

+ +
+
+ready> 4+5;
+define double @""() {
+entry:
+        ret double 9.000000e+00
+}
+
+Evaluated to 9.000000
+
+
+ +

Well this looks like it is basically working. The dump of the function +shows the "no argument function that always returns double" that we synthesize +for each top level expression that is typed in. This demonstrates very basic +functionality, but can we do more?

+ +
+
+ready> def testfunc(x y) x + y*2; 
+Read function definition:
+define double @testfunc(double %x, double %y) {
+entry:
+        %multmp = fmul double %y, 2.000000e+00
+        %addtmp = fadd double %multmp, %x
+        ret double %addtmp
+}
+
+ready> testfunc(4, 10);
+define double @""() {
+entry:
+        %calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
+        ret double %calltmp
+}
+
+Evaluated to 24.000000
+
+
+ +

This illustrates that we can now call user code, but there is something a bit +subtle going on here. Note that we only invoke the JIT on the anonymous +functions that call testfunc, but we never invoked it +on testfunc itself. What actually happened here is that the JIT +scanned for all non-JIT'd functions transitively called from the anonymous +function and compiled all of them before returning +from run_function.

+ +

The JIT provides a number of other more advanced interfaces for things like +freeing allocated machine code, rejit'ing functions to update them, etc. +However, even with this simple code, we get some surprisingly powerful +capabilities - check this out (I removed the dump of the anonymous functions, +you should get the idea by now :) :

+ +
+
+ready> extern sin(x);
+Read extern:
+declare double @sin(double)
+
+ready> extern cos(x);
+Read extern:
+declare double @cos(double)
+
+ready> sin(1.0);
+Evaluated to 0.841471
+
+ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
+Read function definition:
+define double @foo(double %x) {
+entry:
+        %calltmp = call double @sin(double %x)
+        %multmp = fmul double %calltmp, %calltmp
+        %calltmp2 = call double @cos(double %x)
+        %multmp4 = fmul double %calltmp2, %calltmp2
+        %addtmp = fadd double %multmp, %multmp4
+        ret double %addtmp
+}
+
+ready> foo(4.0);
+Evaluated to 1.000000
+
+
+ +

Whoa, how does the JIT know about sin and cos? The answer is surprisingly +simple: in this example, the JIT started execution of a function and got to a +function call. It realized that the function was not yet JIT compiled and +invoked the standard set of routines to resolve the function. In this case, +there is no body defined for the function, so the JIT ended up calling +"dlsym("sin")" on the Kaleidoscope process itself. Since +"sin" is defined within the JIT's address space, it simply patches up +calls in the module to call the libm version of sin directly.

+ +

The LLVM JIT provides a number of interfaces (look in the +llvm_executionengine.mli file) for controlling how unknown functions +get resolved. It allows you to establish explicit mappings between IR objects +and addresses (useful for LLVM global variables that you want to map to static +tables, for example), allows you to dynamically decide on the fly based on the +function name, and even allows you to have the JIT compile functions lazily the +first time they're called.

+ +

One interesting application of this is that we can now extend the language +by writing arbitrary C code to implement operations. For example, if we add: +

+ +
+
+/* putchard - putchar that takes a double and returns 0. */
+extern "C"
+double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+
+ +

Now we can produce simple output to the console by using things like: +"extern putchard(x); putchard(120);", which prints a lowercase 'x' on +the console (120 is the ASCII code for 'x'). Similar code could be used to +implement file I/O, console input, and many other capabilities in +Kaleidoscope.

+ +

This completes the JIT and optimizer chapter of the Kaleidoscope tutorial. At +this point, we can compile a non-Turing-complete programming language, optimize +and JIT compile it in a user-driven way. Next up we'll look into extending the language with control flow +constructs, tackling some interesting LLVM IR issues along the way.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +LLVM JIT and optimizer. To build this example, use: +

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
+<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
+<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
+
+
+ +
myocamlbuild.ml:
+
+
+open Ocamlbuild_plugin;;
+
+ocaml_lib ~extern:true "llvm";;
+ocaml_lib ~extern:true "llvm_analysis";;
+ocaml_lib ~extern:true "llvm_executionengine";;
+ocaml_lib ~extern:true "llvm_target";;
+ocaml_lib ~extern:true "llvm_scalar_opts";;
+
+flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
+dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto = Prototype of string * string array
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the primary expression after the binary operator. *)
+        let rhs = parse_primary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')' *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
codegen.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Code Generation
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+exception Error of string
+
+let context = global_context ()
+let the_module = create_module context "my cool jit"
+let builder = builder context
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+let rec codegen_expr = function
+  | Ast.Number n -> const_float double_type n
+  | Ast.Variable name ->
+      (try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name"))
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ -> raise (Error "invalid binary operator")
+      end
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+        | None -> declare_function name ft the_module
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if block_begin f <> At_end f then
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if element_type (type_of f) <> ft then
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+let codegen_func the_fpm = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        (* Optimize the function. *)
+        let _ = PassManager.run_function the_function the_fpm in
+
+        the_function
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop the_fpm the_execution_engine stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop the_fpm the_execution_engine stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            let e = Parser.parse_definition stream in
+            print_endline "parsed a function definition.";
+            dump_value (Codegen.codegen_func the_fpm e);
+        | Token.Extern ->
+            let e = Parser.parse_extern stream in
+            print_endline "parsed an extern.";
+            dump_value (Codegen.codegen_proto e);
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            let the_function = Codegen.codegen_func the_fpm e in
+            dump_value the_function;
+
+            (* JIT the function, returning a function pointer. *)
+            let result = ExecutionEngine.run_function the_function [||]
+              the_execution_engine in
+
+            print_string "Evaluated to ";
+            print_float (GenericValue.as_float Codegen.double_type result);
+            print_newline ();
+        with Stream.Error s | Codegen.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop the_fpm the_execution_engine stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+open Llvm_target
+open Llvm_scalar_opts
+
+let main () =
+  ignore (initialize_native_target ());
+
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combination the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+  (* Eliminate Common SubExpressions. *)
+  add_gvn the_fpm;
+
+  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
+  add_cfg_simplification the_fpm;
+
+  ignore (PassManager.initialize the_fpm);
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop the_fpm the_execution_engine stream;
+
+  (* Print out all the generated code. *)
+  dump_module Codegen.the_module
+;;
+
+main ()
+
+
+ +
bindings.c
+
+
+#include <stdio.h>
+
+/* putchard - putchar that takes a double and returns 0. */
+extern double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+
+
+ +Next: Extending the language: control flow +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl5.html b/final/docs/tutorial/OCamlLangImpl5.html new file mode 100644 index 00000000000..7a213952574 --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl5.html @@ -0,0 +1,1569 @@ + + + + + Kaleidoscope: Extending the Language: Control Flow + + + + + + + + +
Kaleidoscope: Extending the Language: Control Flow
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 5 of the "Implementing a language +with LLVM" tutorial. Parts 1-4 described the implementation of the simple +Kaleidoscope language and included support for generating LLVM IR, followed by +optimizations and a JIT compiler. Unfortunately, as presented, Kaleidoscope is +mostly useless: it has no control flow other than call and return. This means +that you can't have conditional branches in the code, significantly limiting its +power. In this episode of "build that compiler", we'll extend Kaleidoscope to +have an if/then/else expression plus a simple 'for' loop.

+ +
+ + + + + +
+ +

+Extending Kaleidoscope to support if/then/else is quite straightforward. It +basically requires adding lexer support for this "new" concept to the lexer, +parser, AST, and LLVM code emitter. This example is nice, because it shows how +easy it is to "grow" a language over time, incrementally extending it as new +ideas are discovered.

+ +

Before we get going on "how" we add this extension, lets talk about "what" we +want. The basic idea is that we want to be able to write this sort of thing: +

+ +
+
+def fib(x)
+  if x < 3 then
+    1
+  else
+    fib(x-1)+fib(x-2);
+
+
+ +

In Kaleidoscope, every construct is an expression: there are no statements. +As such, the if/then/else expression needs to return a value like any other. +Since we're using a mostly functional form, we'll have it evaluate its +conditional, then return the 'then' or 'else' value based on how the condition +was resolved. This is very similar to the C "?:" expression.

+ +

The semantics of the if/then/else expression is that it evaluates the +condition to a boolean equality value: 0.0 is considered to be false and +everything else is considered to be true. +If the condition is true, the first subexpression is evaluated and returned, if +the condition is false, the second subexpression is evaluated and returned. +Since Kaleidoscope allows side-effects, this behavior is important to nail down. +

+ +

Now that we know what we "want", lets break this down into its constituent +pieces.

+ +
+ + + + + + +
+ +

The lexer extensions are straightforward. First we add new variants +for the relevant tokens:

+ +
+
+  (* control *)
+  | If | Then | Else | For | In
+
+
+ +

Once we have that, we recognize the new keywords in the lexer. This is pretty simple +stuff:

+ +
+
+      ...
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | "if" -> [< 'Token.If; stream >]
+      | "then" -> [< 'Token.Then; stream >]
+      | "else" -> [< 'Token.Else; stream >]
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+
+ +
+ + + + + +
+ +

To represent the new expression we add a new AST variant for it:

+ +
+
+type expr =
+  ...
+  (* variant for if/then/else. *)
+  | If of expr * expr * expr
+
+
+ +

The AST variant just has pointers to the various subexpressions.

+ +
+ + + + + +
+ +

Now that we have the relevant tokens coming from the lexer and we have the +AST node to build, our parsing logic is relatively straightforward. First we +define a new parsing function:

+ +
+
+let rec parse_primary = parser
+  ...
+  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
+  | [< 'Token.If; c=parse_expr;
+       'Token.Then ?? "expected 'then'"; t=parse_expr;
+       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
+      Ast.If (c, t, e)
+
+
+ +

Next we hook it up as a primary expression:

+ +
+
+let rec parse_primary = parser
+  ...
+  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
+  | [< 'Token.If; c=parse_expr;
+       'Token.Then ?? "expected 'then'"; t=parse_expr;
+       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
+      Ast.If (c, t, e)
+
+
+ +
+ + + + + +
+ +

Now that we have it parsing and building the AST, the final piece is adding +LLVM code generation support. This is the most interesting part of the +if/then/else example, because this is where it starts to introduce new concepts. +All of the code above has been thoroughly described in previous chapters. +

+ +

To motivate the code we want to produce, lets take a look at a simple +example. Consider:

+ +
+
+extern foo();
+extern bar();
+def baz(x) if x then foo() else bar();
+
+
+ +

If you disable optimizations, the code you'll (soon) get from Kaleidoscope +looks like this:

+ +
+
+declare double @foo()
+
+declare double @bar()
+
+define double @baz(double %x) {
+entry:
+  %ifcond = fcmp one double %x, 0.000000e+00
+  br i1 %ifcond, label %then, label %else
+
+then:    ; preds = %entry
+  %calltmp = call double @foo()
+  br label %ifcont
+
+else:    ; preds = %entry
+  %calltmp1 = call double @bar()
+  br label %ifcont
+
+ifcont:    ; preds = %else, %then
+  %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
+  ret double %iftmp
+}
+
+
+ +

To visualize the control flow graph, you can use a nifty feature of the LLVM +'opt' tool. If you put this LLVM IR +into "t.ll" and run "llvm-as < t.ll | opt -analyze -view-cfg", a window will pop up and you'll +see this graph:

+ +
Example CFG
+ +

Another way to get this is to call "Llvm_analysis.view_function_cfg +f" or "Llvm_analysis.view_function_cfg_only f" (where f +is a "Function") either by inserting actual calls into the code and +recompiling or by calling these in the debugger. LLVM has many nice features +for visualizing various graphs.

+ +

Getting back to the generated code, it is fairly simple: the entry block +evaluates the conditional expression ("x" in our case here) and compares the +result to 0.0 with the "fcmp one" +instruction ('one' is "Ordered and Not Equal"). Based on the result of this +expression, the code jumps to either the "then" or "else" blocks, which contain +the expressions for the true/false cases.

+ +

Once the then/else blocks are finished executing, they both branch back to the +'ifcont' block to execute the code that happens after the if/then/else. In this +case the only thing left to do is to return to the caller of the function. The +question then becomes: how does the code know which expression to return?

+ +

The answer to this question involves an important SSA operation: the +Phi +operation. If you're not familiar with SSA, the wikipedia +article is a good introduction and there are various other introductions to +it available on your favorite search engine. The short version is that +"execution" of the Phi operation requires "remembering" which block control came +from. The Phi operation takes on the value corresponding to the input control +block. In this case, if control comes in from the "then" block, it gets the +value of "calltmp". If control comes from the "else" block, it gets the value +of "calltmp1".

+ +

At this point, you are probably starting to think "Oh no! This means my +simple and elegant front-end will have to start generating SSA form in order to +use LLVM!". Fortunately, this is not the case, and we strongly advise +not implementing an SSA construction algorithm in your front-end +unless there is an amazingly good reason to do so. In practice, there are two +sorts of values that float around in code written for your average imperative +programming language that might need Phi nodes:

+ +
    +
  1. Code that involves user variables: x = 1; x = x + 1;
  2. +
  3. Values that are implicit in the structure of your AST, such as the Phi node +in this case.
  4. +
+ +

In Chapter 7 of this tutorial ("mutable +variables"), we'll talk about #1 +in depth. For now, just believe me that you don't need SSA construction to +handle this case. For #2, you have the choice of using the techniques that we will +describe for #1, or you can insert Phi nodes directly, if convenient. In this +case, it is really really easy to generate the Phi node, so we choose to do it +directly.

+ +

Okay, enough of the motivation and overview, lets generate code!

+ +
+ + + + + +
+ +

In order to generate code for this, we implement the Codegen method +for IfExprAST:

+ +
+
+let rec codegen_expr = function
+  ...
+  | Ast.If (cond, then_, else_) ->
+      let cond = codegen_expr cond in
+
+      (* Convert condition to a bool by comparing equal to 0.0 *)
+      let zero = const_float double_type 0.0 in
+      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
+
+
+ +

This code is straightforward and similar to what we saw before. We emit the +expression for the condition, then compare that value to zero to get a truth +value as a 1-bit (bool) value.

+ +
+
+      (* Grab the first block so that we might later add the conditional branch
+       * to it at the end of the function. *)
+      let start_bb = insertion_block builder in
+      let the_function = block_parent start_bb in
+
+      let then_bb = append_block context "then" the_function in
+      position_at_end then_bb builder;
+
+
+ +

+As opposed to the C++ tutorial, we have to build +our basic blocks bottom up since we can't have dangling BasicBlocks. We start +off by saving a pointer to the first block (which might not be the entry +block), which we'll need to build a conditional branch later. We do this by +asking the builder for the current BasicBlock. The fourth line +gets the current Function object that is being built. It gets this by the +start_bb for its "parent" (the function it is currently embedded +into).

+ +

Once it has that, it creates one block. It is automatically appended into +the function's list of blocks.

+ +
+
+      (* Emit 'then' value. *)
+      position_at_end then_bb builder;
+      let then_val = codegen_expr then_ in
+
+      (* Codegen of 'then' can change the current block, update then_bb for the
+       * phi. We create a new name because one is used for the phi node, and the
+       * other is used for the conditional branch. *)
+      let new_then_bb = insertion_block builder in
+
+
+ +

We move the builder to start inserting into the "then" block. Strictly +speaking, this call moves the insertion point to be at the end of the specified +block. However, since the "then" block is empty, it also starts out by +inserting at the beginning of the block. :)

+ +

Once the insertion point is set, we recursively codegen the "then" expression +from the AST.

+ +

The final line here is quite subtle, but is very important. The basic issue +is that when we create the Phi node in the merge block, we need to set up the +block/value pairs that indicate how the Phi will work. Importantly, the Phi +node expects to have an entry for each predecessor of the block in the CFG. Why +then, are we getting the current block when we just set it to ThenBB 5 lines +above? The problem is that the "Then" expression may actually itself change the +block that the Builder is emitting into if, for example, it contains a nested +"if/then/else" expression. Because calling Codegen recursively could +arbitrarily change the notion of the current block, we are required to get an +up-to-date value for code that will set up the Phi node.

+ +
+
+      (* Emit 'else' value. *)
+      let else_bb = append_block context "else" the_function in
+      position_at_end else_bb builder;
+      let else_val = codegen_expr else_ in
+
+      (* Codegen of 'else' can change the current block, update else_bb for the
+       * phi. *)
+      let new_else_bb = insertion_block builder in
+
+
+ +

Code generation for the 'else' block is basically identical to codegen for +the 'then' block.

+ +
+
+      (* Emit merge block. *)
+      let merge_bb = append_block context "ifcont" the_function in
+      position_at_end merge_bb builder;
+      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
+      let phi = build_phi incoming "iftmp" builder in
+
+
+ +

The first two lines here are now familiar: the first adds the "merge" block +to the Function object. The second block changes the insertion point so that +newly created code will go into the "merge" block. Once that is done, we need +to create the PHI node and set up the block/value pairs for the PHI.

+ +
+
+      (* Return to the start block to add the conditional branch. *)
+      position_at_end start_bb builder;
+      ignore (build_cond_br cond_val then_bb else_bb builder);
+
+
+ +

Once the blocks are created, we can emit the conditional branch that chooses +between them. Note that creating new blocks does not implicitly affect the +IRBuilder, so it is still inserting into the block that the condition +went into. This is why we needed to save the "start" block.

+ +
+
+      (* Set a unconditional branch at the end of the 'then' block and the
+       * 'else' block to the 'merge' block. *)
+      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
+      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
+
+      (* Finally, set the builder to the end of the merge block. *)
+      position_at_end merge_bb builder;
+
+      phi
+
+
+ +

To finish off the blocks, we create an unconditional branch +to the merge block. One interesting (and very important) aspect of the LLVM IR +is that it requires all basic blocks +to be "terminated" with a control flow +instruction such as return or branch. This means that all control flow, +including fall throughs must be made explicit in the LLVM IR. If you +violate this rule, the verifier will emit an error. + +

Finally, the CodeGen function returns the phi node as the value computed by +the if/then/else expression. In our example above, this returned value will +feed into the code for the top-level function, which will create the return +instruction.

+ +

Overall, we now have the ability to execute conditional code in +Kaleidoscope. With this extension, Kaleidoscope is a fairly complete language +that can calculate a wide variety of numeric functions. Next up we'll add +another useful expression that is familiar from non-functional languages...

+ +
+ + + + + +
+ +

Now that we know how to add basic control flow constructs to the language, +we have the tools to add more powerful things. Lets add something more +aggressive, a 'for' expression:

+ +
+
+ extern putchard(char);
+ def printstar(n)
+   for i = 1, i < n, 1.0 in
+     putchard(42);  # ascii 42 = '*'
+
+ # print 100 '*' characters
+ printstar(100);
+
+
+ +

This expression defines a new variable ("i" in this case) which iterates from +a starting value, while the condition ("i < n" in this case) is true, +incrementing by an optional step value ("1.0" in this case). If the step value +is omitted, it defaults to 1.0. While the loop is true, it executes its +body expression. Because we don't have anything better to return, we'll just +define the loop as always returning 0.0. In the future when we have mutable +variables, it will get more useful.

+ +

As before, lets talk about the changes that we need to Kaleidoscope to +support this.

+ +
+ + + + + +
+ +

The lexer extensions are the same sort of thing as for if/then/else:

+ +
+
+  ... in Token.token ...
+  (* control *)
+  | If | Then | Else
+  | For | In
+
+  ... in Lexer.lex_ident...
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | "if" -> [< 'Token.If; stream >]
+      | "then" -> [< 'Token.Then; stream >]
+      | "else" -> [< 'Token.Else; stream >]
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+
+ +
+ + + + + +
+ +

The AST variant is just as simple. It basically boils down to capturing +the variable name and the constituent expressions in the node.

+ +
+
+type expr =
+  ...
+  (* variant for for/in. *)
+  | For of string * expr * expr * expr option * expr
+
+
+ +
+ + + + + +
+ +

The parser code is also fairly standard. The only interesting thing here is +handling of the optional step value. The parser code handles it by checking to +see if the second comma is present. If not, it sets the step value to null in +the AST node:

+ +
+
+let rec parse_primary = parser
+  ...
+  (* forexpr
+        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
+  | [< 'Token.For;
+       'Token.Ident id ?? "expected identifier after for";
+       'Token.Kwd '=' ?? "expected '=' after for";
+       stream >] ->
+      begin parser
+        | [<
+             start=parse_expr;
+             'Token.Kwd ',' ?? "expected ',' after for";
+             end_=parse_expr;
+             stream >] ->
+            let step =
+              begin parser
+              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
+              | [< >] -> None
+              end stream
+            in
+            begin parser
+            | [< 'Token.In; body=parse_expr >] ->
+                Ast.For (id, start, end_, step, body)
+            | [< >] ->
+                raise (Stream.Error "expected 'in' after for")
+            end stream
+        | [< >] ->
+            raise (Stream.Error "expected '=' after for")
+      end stream
+
+
+ +
+ + + + + +
+ +

Now we get to the good part: the LLVM IR we want to generate for this thing. +With the simple example above, we get this LLVM IR (note that this dump is +generated with optimizations disabled for clarity): +

+ +
+
+declare double @putchard(double)
+
+define double @printstar(double %n) {
+entry:
+        ; initial value = 1.0 (inlined into phi)
+  br label %loop
+
+loop:    ; preds = %loop, %entry
+  %i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
+        ; body
+  %calltmp = call double @putchard(double 4.200000e+01)
+        ; increment
+  %nextvar = fadd double %i, 1.000000e+00
+
+        ; termination test
+  %cmptmp = fcmp ult double %i, %n
+  %booltmp = uitofp i1 %cmptmp to double
+  %loopcond = fcmp one double %booltmp, 0.000000e+00
+  br i1 %loopcond, label %loop, label %afterloop
+
+afterloop:    ; preds = %loop
+        ; loop always returns 0.0
+  ret double 0.000000e+00
+}
+
+
+ +

This loop contains all the same constructs we saw before: a phi node, several +expressions, and some basic blocks. Lets see how this fits together.

+ +
+ + + + + +
+ +

The first part of Codegen is very simple: we just output the start expression +for the loop value:

+ +
+
+let rec codegen_expr = function
+  ...
+  | Ast.For (var_name, start, end_, step, body) ->
+      (* Emit the start code first, without 'variable' in scope. *)
+      let start_val = codegen_expr start in
+
+
+ +

With this out of the way, the next step is to set up the LLVM basic block +for the start of the loop body. In the case above, the whole loop body is one +block, but remember that the body code itself could consist of multiple blocks +(e.g. if it contains an if/then/else or a for/in expression).

+ +
+
+      (* Make the new basic block for the loop header, inserting after current
+       * block. *)
+      let preheader_bb = insertion_block builder in
+      let the_function = block_parent preheader_bb in
+      let loop_bb = append_block context "loop" the_function in
+
+      (* Insert an explicit fall through from the current block to the
+       * loop_bb. *)
+      ignore (build_br loop_bb builder);
+
+
+ +

This code is similar to what we saw for if/then/else. Because we will need +it to create the Phi node, we remember the block that falls through into the +loop. Once we have that, we create the actual block that starts the loop and +create an unconditional branch for the fall-through between the two blocks.

+ +
+
+      (* Start insertion in loop_bb. *)
+      position_at_end loop_bb builder;
+
+      (* Start the PHI node with an entry for start. *)
+      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
+
+
+ +

Now that the "preheader" for the loop is set up, we switch to emitting code +for the loop body. To begin with, we move the insertion point and create the +PHI node for the loop induction variable. Since we already know the incoming +value for the starting value, we add it to the Phi node. Note that the Phi will +eventually get a second value for the backedge, but we can't set it up yet +(because it doesn't exist!).

+ +
+
+      (* Within the loop, the variable is defined equal to the PHI node. If it
+       * shadows an existing variable, we have to restore it, so save it
+       * now. *)
+      let old_val =
+        try Some (Hashtbl.find named_values var_name) with Not_found -> None
+      in
+      Hashtbl.add named_values var_name variable;
+
+      (* Emit the body of the loop.  This, like any other expr, can change the
+       * current BB.  Note that we ignore the value computed by the body, but
+       * don't allow an error *)
+      ignore (codegen_expr body);
+
+
+ +

Now the code starts to get more interesting. Our 'for' loop introduces a new +variable to the symbol table. This means that our symbol table can now contain +either function arguments or loop variables. To handle this, before we codegen +the body of the loop, we add the loop variable as the current value for its +name. Note that it is possible that there is a variable of the same name in the +outer scope. It would be easy to make this an error (emit an error and return +null if there is already an entry for VarName) but we choose to allow shadowing +of variables. In order to handle this correctly, we remember the Value that +we are potentially shadowing in old_val (which will be None if there is +no shadowed variable).

+ +

Once the loop variable is set into the symbol table, the code recursively +codegen's the body. This allows the body to use the loop variable: any +references to it will naturally find it in the symbol table.

+ +
+
+      (* Emit the step value. *)
+      let step_val =
+        match step with
+        | Some step -> codegen_expr step
+        (* If not specified, use 1.0. *)
+        | None -> const_float double_type 1.0
+      in
+
+      let next_var = build_add variable step_val "nextvar" builder in
+
+
+ +

Now that the body is emitted, we compute the next value of the iteration +variable by adding the step value, or 1.0 if it isn't present. +'next_var' will be the value of the loop variable on the next iteration +of the loop.

+ +
+
+      (* Compute the end condition. *)
+      let end_cond = codegen_expr end_ in
+
+      (* Convert condition to a bool by comparing equal to 0.0. *)
+      let zero = const_float double_type 0.0 in
+      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
+
+
+ +

Finally, we evaluate the exit value of the loop, to determine whether the +loop should exit. This mirrors the condition evaluation for the if/then/else +statement.

+ +
+
+      (* Create the "after loop" block and insert it. *)
+      let loop_end_bb = insertion_block builder in
+      let after_bb = append_block context "afterloop" the_function in
+
+      (* Insert the conditional branch into the end of loop_end_bb. *)
+      ignore (build_cond_br end_cond loop_bb after_bb builder);
+
+      (* Any new code will be inserted in after_bb. *)
+      position_at_end after_bb builder;
+
+
+ +

With the code for the body of the loop complete, we just need to finish up +the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the +exit condition, it creates a conditional branch that chooses between executing +the loop again and exiting the loop. Any future code is emitted in the +"afterloop" block, so it sets the insertion position to it.

+ +
+
+      (* Add a new entry to the PHI node for the backedge. *)
+      add_incoming (next_var, loop_end_bb) variable;
+
+      (* Restore the unshadowed variable. *)
+      begin match old_val with
+      | Some old_val -> Hashtbl.add named_values var_name old_val
+      | None -> ()
+      end;
+
+      (* for expr always returns 0.0. *)
+      const_null double_type
+
+
+ +

The final code handles various cleanups: now that we have the +"next_var" value, we can add the incoming value to the loop PHI node. +After that, we remove the loop variable from the symbol table, so that it isn't +in scope after the for loop. Finally, code generation of the for loop always +returns 0.0, so that is what we return from Codegen.codegen_expr.

+ +

With this, we conclude the "adding control flow to Kaleidoscope" chapter of +the tutorial. In this chapter we added two control flow constructs, and used +them to motivate a couple of aspects of the LLVM IR that are important for +front-end implementors to know. In the next chapter of our saga, we will get +a bit crazier and add user-defined operators +to our poor innocent language.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
+<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
+<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
+
+
+ +
myocamlbuild.ml:
+
+
+open Ocamlbuild_plugin;;
+
+ocaml_lib ~extern:true "llvm";;
+ocaml_lib ~extern:true "llvm_analysis";;
+ocaml_lib ~extern:true "llvm_executionengine";;
+ocaml_lib ~extern:true "llvm_target";;
+ocaml_lib ~extern:true "llvm_scalar_opts";;
+
+flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
+dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+  (* control *)
+  | If | Then | Else
+  | For | In
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | "if" -> [< 'Token.If; stream >]
+      | "then" -> [< 'Token.Then; stream >]
+      | "else" -> [< 'Token.Else; stream >]
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+  (* variant for if/then/else. *)
+  | If of expr * expr * expr
+
+  (* variant for for/in. *)
+  | For of string * expr * expr * expr option * expr
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto = Prototype of string * string array
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr
+ *   ::= ifexpr
+ *   ::= forexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
+  | [< 'Token.If; c=parse_expr;
+       'Token.Then ?? "expected 'then'"; t=parse_expr;
+       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
+      Ast.If (c, t, e)
+
+  (* forexpr
+        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
+  | [< 'Token.For;
+       'Token.Ident id ?? "expected identifier after for";
+       'Token.Kwd '=' ?? "expected '=' after for";
+       stream >] ->
+      begin parser
+        | [<
+             start=parse_expr;
+             'Token.Kwd ',' ?? "expected ',' after for";
+             end_=parse_expr;
+             stream >] ->
+            let step =
+              begin parser
+              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
+              | [< >] -> None
+              end stream
+            in
+            begin parser
+            | [< 'Token.In; body=parse_expr >] ->
+                Ast.For (id, start, end_, step, body)
+            | [< >] ->
+                raise (Stream.Error "expected 'in' after for")
+            end stream
+        | [< >] ->
+            raise (Stream.Error "expected '=' after for")
+      end stream
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the primary expression after the binary operator. *)
+        let rhs = parse_primary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')' *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
codegen.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Code Generation
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+exception Error of string
+
+let context = global_context ()
+let the_module = create_module context "my cool jit"
+let builder = builder context
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+let rec codegen_expr = function
+  | Ast.Number n -> const_float double_type n
+  | Ast.Variable name ->
+      (try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name"))
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ -> raise (Error "invalid binary operator")
+      end
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+  | Ast.If (cond, then_, else_) ->
+      let cond = codegen_expr cond in
+
+      (* Convert condition to a bool by comparing equal to 0.0 *)
+      let zero = const_float double_type 0.0 in
+      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
+
+      (* Grab the first block so that we might later add the conditional branch
+       * to it at the end of the function. *)
+      let start_bb = insertion_block builder in
+      let the_function = block_parent start_bb in
+
+      let then_bb = append_block context "then" the_function in
+
+      (* Emit 'then' value. *)
+      position_at_end then_bb builder;
+      let then_val = codegen_expr then_ in
+
+      (* Codegen of 'then' can change the current block, update then_bb for the
+       * phi. We create a new name because one is used for the phi node, and the
+       * other is used for the conditional branch. *)
+      let new_then_bb = insertion_block builder in
+
+      (* Emit 'else' value. *)
+      let else_bb = append_block context "else" the_function in
+      position_at_end else_bb builder;
+      let else_val = codegen_expr else_ in
+
+      (* Codegen of 'else' can change the current block, update else_bb for the
+       * phi. *)
+      let new_else_bb = insertion_block builder in
+
+      (* Emit merge block. *)
+      let merge_bb = append_block context "ifcont" the_function in
+      position_at_end merge_bb builder;
+      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
+      let phi = build_phi incoming "iftmp" builder in
+
+      (* Return to the start block to add the conditional branch. *)
+      position_at_end start_bb builder;
+      ignore (build_cond_br cond_val then_bb else_bb builder);
+
+      (* Set a unconditional branch at the end of the 'then' block and the
+       * 'else' block to the 'merge' block. *)
+      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
+      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
+
+      (* Finally, set the builder to the end of the merge block. *)
+      position_at_end merge_bb builder;
+
+      phi
+  | Ast.For (var_name, start, end_, step, body) ->
+      (* Emit the start code first, without 'variable' in scope. *)
+      let start_val = codegen_expr start in
+
+      (* Make the new basic block for the loop header, inserting after current
+       * block. *)
+      let preheader_bb = insertion_block builder in
+      let the_function = block_parent preheader_bb in
+      let loop_bb = append_block context "loop" the_function in
+
+      (* Insert an explicit fall through from the current block to the
+       * loop_bb. *)
+      ignore (build_br loop_bb builder);
+
+      (* Start insertion in loop_bb. *)
+      position_at_end loop_bb builder;
+
+      (* Start the PHI node with an entry for start. *)
+      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
+
+      (* Within the loop, the variable is defined equal to the PHI node. If it
+       * shadows an existing variable, we have to restore it, so save it
+       * now. *)
+      let old_val =
+        try Some (Hashtbl.find named_values var_name) with Not_found -> None
+      in
+      Hashtbl.add named_values var_name variable;
+
+      (* Emit the body of the loop.  This, like any other expr, can change the
+       * current BB.  Note that we ignore the value computed by the body, but
+       * don't allow an error *)
+      ignore (codegen_expr body);
+
+      (* Emit the step value. *)
+      let step_val =
+        match step with
+        | Some step -> codegen_expr step
+        (* If not specified, use 1.0. *)
+        | None -> const_float double_type 1.0
+      in
+
+      let next_var = build_add variable step_val "nextvar" builder in
+
+      (* Compute the end condition. *)
+      let end_cond = codegen_expr end_ in
+
+      (* Convert condition to a bool by comparing equal to 0.0. *)
+      let zero = const_float double_type 0.0 in
+      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
+
+      (* Create the "after loop" block and insert it. *)
+      let loop_end_bb = insertion_block builder in
+      let after_bb = append_block context "afterloop" the_function in
+
+      (* Insert the conditional branch into the end of loop_end_bb. *)
+      ignore (build_cond_br end_cond loop_bb after_bb builder);
+
+      (* Any new code will be inserted in after_bb. *)
+      position_at_end after_bb builder;
+
+      (* Add a new entry to the PHI node for the backedge. *)
+      add_incoming (next_var, loop_end_bb) variable;
+
+      (* Restore the unshadowed variable. *)
+      begin match old_val with
+      | Some old_val -> Hashtbl.add named_values var_name old_val
+      | None -> ()
+      end;
+
+      (* for expr always returns 0.0. *)
+      const_null double_type
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+        | None -> declare_function name ft the_module
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if block_begin f <> At_end f then
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if element_type (type_of f) <> ft then
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+let codegen_func the_fpm = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        (* Optimize the function. *)
+        let _ = PassManager.run_function the_function the_fpm in
+
+        the_function
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop the_fpm the_execution_engine stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop the_fpm the_execution_engine stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            let e = Parser.parse_definition stream in
+            print_endline "parsed a function definition.";
+            dump_value (Codegen.codegen_func the_fpm e);
+        | Token.Extern ->
+            let e = Parser.parse_extern stream in
+            print_endline "parsed an extern.";
+            dump_value (Codegen.codegen_proto e);
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            let the_function = Codegen.codegen_func the_fpm e in
+            dump_value the_function;
+
+            (* JIT the function, returning a function pointer. *)
+            let result = ExecutionEngine.run_function the_function [||]
+              the_execution_engine in
+
+            print_string "Evaluated to ";
+            print_float (GenericValue.as_float Codegen.double_type result);
+            print_newline ();
+        with Stream.Error s | Codegen.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop the_fpm the_execution_engine stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+open Llvm_target
+open Llvm_scalar_opts
+
+let main () =
+  ignore (initialize_native_target ());
+
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combination the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+  (* Eliminate Common SubExpressions. *)
+  add_gvn the_fpm;
+
+  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
+  add_cfg_simplification the_fpm;
+
+  ignore (PassManager.initialize the_fpm);
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop the_fpm the_execution_engine stream;
+
+  (* Print out all the generated code. *)
+  dump_module Codegen.the_module
+;;
+
+main ()
+
+
+ +
bindings.c
+
+
+#include <stdio.h>
+
+/* putchard - putchar that takes a double and returns 0. */
+extern double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+
+
+ +Next: Extending the language: user-defined +operators +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl6.html b/final/docs/tutorial/OCamlLangImpl6.html new file mode 100644 index 00000000000..86210febca2 --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl6.html @@ -0,0 +1,1574 @@ + + + + + Kaleidoscope: Extending the Language: User-defined Operators + + + + + + + + +
Kaleidoscope: Extending the Language: User-defined Operators
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 6 of the "Implementing a language +with LLVM" tutorial. At this point in our tutorial, we now have a fully +functional language that is fairly minimal, but also useful. There +is still one big problem with it, however. Our language doesn't have many +useful operators (like division, logical negation, or even any comparisons +besides less-than).

+ +

This chapter of the tutorial takes a wild digression into adding user-defined +operators to the simple and beautiful Kaleidoscope language. This digression now +gives us a simple and ugly language in some ways, but also a powerful one at the +same time. One of the great things about creating your own language is that you +get to decide what is good or bad. In this tutorial we'll assume that it is +okay to use this as a way to show some interesting parsing techniques.

+ +

At the end of this tutorial, we'll run through an example Kaleidoscope +application that renders the Mandelbrot set. This gives +an example of what you can build with Kaleidoscope and its feature set.

+ +
+ + + + + +
+ +

+The "operator overloading" that we will add to Kaleidoscope is more general than +languages like C++. In C++, you are only allowed to redefine existing +operators: you can't programatically change the grammar, introduce new +operators, change precedence levels, etc. In this chapter, we will add this +capability to Kaleidoscope, which will let the user round out the set of +operators that are supported.

+ +

The point of going into user-defined operators in a tutorial like this is to +show the power and flexibility of using a hand-written parser. Thus far, the parser +we have been implementing uses recursive descent for most parts of the grammar and +operator precedence parsing for the expressions. See Chapter 2 for details. Without using operator +precedence parsing, it would be very difficult to allow the programmer to +introduce new operators into the grammar: the grammar is dynamically extensible +as the JIT runs.

+ +

The two specific features we'll add are programmable unary operators (right +now, Kaleidoscope has no unary operators at all) as well as binary operators. +An example of this is:

+ +
+
+# Logical unary not.
+def unary!(v)
+  if v then
+    0
+  else
+    1;
+
+# Define > with the same precedence as <.
+def binary> 10 (LHS RHS)
+  RHS < LHS;
+
+# Binary "logical or", (note that it does not "short circuit")
+def binary| 5 (LHS RHS)
+  if LHS then
+    1
+  else if RHS then
+    1
+  else
+    0;
+
+# Define = with slightly lower precedence than relationals.
+def binary= 9 (LHS RHS)
+  !(LHS < RHS | LHS > RHS);
+
+
+ +

Many languages aspire to being able to implement their standard runtime +library in the language itself. In Kaleidoscope, we can implement significant +parts of the language in the library!

+ +

We will break down implementation of these features into two parts: +implementing support for user-defined binary operators and adding unary +operators.

+ +
+ + + + + +
+ +

Adding support for user-defined binary operators is pretty simple with our +current framework. We'll first add support for the unary/binary keywords:

+ +
+
+type token =
+  ...
+  (* operators *)
+  | Binary | Unary
+
+...
+
+and lex_ident buffer = parser
+  ...
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | "binary" -> [< 'Token.Binary; stream >]
+      | "unary" -> [< 'Token.Unary; stream >]
+
+
+ +

This just adds lexer support for the unary and binary keywords, like we +did in previous chapters. One nice +thing about our current AST, is that we represent binary operators with full +generalisation by using their ASCII code as the opcode. For our extended +operators, we'll use this same representation, so we don't need any new AST or +parser support.

+ +

On the other hand, we have to be able to represent the definitions of these +new operators, in the "def binary| 5" part of the function definition. In our +grammar so far, the "name" for the function definition is parsed as the +"prototype" production and into the Ast.Prototype AST node. To +represent our new user-defined operators as prototypes, we have to extend +the Ast.Prototype AST node like this:

+ +
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto =
+  | Prototype of string * string array
+  | BinOpPrototype of string * string array * int
+
+
+ +

Basically, in addition to knowing a name for the prototype, we now keep track +of whether it was an operator, and if it was, what precedence level the operator +is at. The precedence is only used for binary operators (as you'll see below, +it just doesn't apply for unary operators). Now that we have a way to represent +the prototype for a user-defined operator, we need to parse it:

+ +
+
+(* prototype
+ *   ::= id '(' id* ')'
+ *   ::= binary LETTER number? (id, id)
+ *   ::= unary LETTER number? (id) *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+  let parse_operator = parser
+    | [< 'Token.Unary >] -> "unary", 1
+    | [< 'Token.Binary >] -> "binary", 2
+  in
+  let parse_binary_precedence = parser
+    | [< 'Token.Number n >] -> int_of_float n
+    | [< >] -> 30
+  in
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+  | [< (prefix, kind)=parse_operator;
+       'Token.Kwd op ?? "expected an operator";
+       (* Read the precedence if present. *)
+       binary_precedence=parse_binary_precedence;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+        args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      let name = prefix ^ (String.make 1 op) in
+      let args = Array.of_list (List.rev args) in
+
+      (* Verify right number of arguments for operator. *)
+      if Array.length args != kind
+      then raise (Stream.Error "invalid number of operands for operator")
+      else
+        if kind == 1 then
+          Ast.Prototype (name, args)
+        else
+          Ast.BinOpPrototype (name, args, binary_precedence)
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+
+ +

This is all fairly straightforward parsing code, and we have already seen +a lot of similar code in the past. One interesting part about the code above is +the couple lines that set up name for binary operators. This builds +names like "binary@" for a newly defined "@" operator. This then takes +advantage of the fact that symbol names in the LLVM symbol table are allowed to +have any character in them, including embedded nul characters.

+ +

The next interesting thing to add, is codegen support for these binary +operators. Given our current structure, this is a simple addition of a default +case for our existing binary operator node:

+ +
+
+let codegen_expr = function
+  ...
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ ->
+            (* If it wasn't a builtin binary operator, it must be a user defined
+             * one. Emit a call to it. *)
+            let callee = "binary" ^ (String.make 1 op) in
+            let callee =
+              match lookup_function callee the_module with
+              | Some callee -> callee
+              | None -> raise (Error "binary operator not found!")
+            in
+            build_call callee [|lhs_val; rhs_val|] "binop" builder
+      end
+
+
+ +

As you can see above, the new code is actually really simple. It just does +a lookup for the appropriate operator in the symbol table and generates a +function call to it. Since user-defined operators are just built as normal +functions (because the "prototype" boils down to a function with the right +name) everything falls into place.

+ +

The final piece of code we are missing, is a bit of top level magic:

+ +
+
+let codegen_func the_fpm = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* If this is an operator, install it. *)
+      begin match proto with
+      | Ast.BinOpPrototype (name, args, prec) ->
+          let op = name.[String.length name - 1] in
+          Hashtbl.add Parser.binop_precedence op prec;
+      | _ -> ()
+      end;
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+      ...
+
+
+ +

Basically, before codegening a function, if it is a user-defined operator, we +register it in the precedence table. This allows the binary operator parsing +logic we already have in place to handle it. Since we are working on a +fully-general operator precedence parser, this is all we need to do to "extend +the grammar".

+ +

Now we have useful user-defined binary operators. This builds a lot +on the previous framework we built for other operators. Adding unary operators +is a bit more challenging, because we don't have any framework for it yet - lets +see what it takes.

+ +
+ + + + + +
+ +

Since we don't currently support unary operators in the Kaleidoscope +language, we'll need to add everything to support them. Above, we added simple +support for the 'unary' keyword to the lexer. In addition to that, we need an +AST node:

+ +
+
+type expr =
+  ...
+  (* variant for a unary operator. *)
+  | Unary of char * expr
+  ...
+
+
+ +

This AST node is very simple and obvious by now. It directly mirrors the +binary operator AST node, except that it only has one child. With this, we +need to add the parsing logic. Parsing a unary operator is pretty simple: we'll +add a new function to do it:

+ +
+
+(* unary
+ *   ::= primary
+ *   ::= '!' unary *)
+and parse_unary = parser
+  (* If this is a unary operator, read it. *)
+  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
+      Ast.Unary (op, operand)
+
+  (* If the current token is not an operator, it must be a primary expr. *)
+  | [< stream >] -> parse_primary stream
+
+
+ +

The grammar we add is pretty straightforward here. If we see a unary +operator when parsing a primary operator, we eat the operator as a prefix and +parse the remaining piece as another unary operator. This allows us to handle +multiple unary operators (e.g. "!!x"). Note that unary operators can't have +ambiguous parses like binary operators can, so there is no need for precedence +information.

+ +

The problem with this function, is that we need to call ParseUnary from +somewhere. To do this, we change previous callers of ParsePrimary to call +parse_unary instead:

+ +
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+        ...
+        (* Parse the unary expression after the binary operator. *)
+        let rhs = parse_unary stream in
+        ...
+
+...
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
+
+
+ +

With these two simple changes, we are now able to parse unary operators and build the +AST for them. Next up, we need to add parser support for prototypes, to parse +the unary operator prototype. We extend the binary operator code above +with:

+ +
+
+(* prototype
+ *   ::= id '(' id* ')'
+ *   ::= binary LETTER number? (id, id)
+ *   ::= unary LETTER number? (id) *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+  let parse_operator = parser
+    | [< 'Token.Unary >] -> "unary", 1
+    | [< 'Token.Binary >] -> "binary", 2
+  in
+  let parse_binary_precedence = parser
+    | [< 'Token.Number n >] -> int_of_float n
+    | [< >] -> 30
+  in
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+  | [< (prefix, kind)=parse_operator;
+       'Token.Kwd op ?? "expected an operator";
+       (* Read the precedence if present. *)
+       binary_precedence=parse_binary_precedence;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+        args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      let name = prefix ^ (String.make 1 op) in
+      let args = Array.of_list (List.rev args) in
+
+      (* Verify right number of arguments for operator. *)
+      if Array.length args != kind
+      then raise (Stream.Error "invalid number of operands for operator")
+      else
+        if kind == 1 then
+          Ast.Prototype (name, args)
+        else
+          Ast.BinOpPrototype (name, args, binary_precedence)
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+
+ +

As with binary operators, we name unary operators with a name that includes +the operator character. This assists us at code generation time. Speaking of, +the final piece we need to add is codegen support for unary operators. It looks +like this:

+ +
+
+let rec codegen_expr = function
+  ...
+  | Ast.Unary (op, operand) ->
+      let operand = codegen_expr operand in
+      let callee = "unary" ^ (String.make 1 op) in
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown unary operator")
+      in
+      build_call callee [|operand|] "unop" builder
+
+
+ +

This code is similar to, but simpler than, the code for binary operators. It +is simpler primarily because it doesn't need to handle any predefined operators. +

+ +
+ + + + + +
+ +

It is somewhat hard to believe, but with a few simple extensions we've +covered in the last chapters, we have grown a real-ish language. With this, we +can do a lot of interesting things, including I/O, math, and a bunch of other +things. For example, we can now add a nice sequencing operator (printd is +defined to print out the specified value and a newline):

+ +
+
+ready> extern printd(x);
+Read extern: declare double @printd(double)
+ready> def binary : 1 (x y) 0;  # Low-precedence operator that ignores operands.
+..
+ready> printd(123) : printd(456) : printd(789);
+123.000000
+456.000000
+789.000000
+Evaluated to 0.000000
+
+
+ +

We can also define a bunch of other "primitive" operations, such as:

+ +
+
+# Logical unary not.
+def unary!(v)
+  if v then
+    0
+  else
+    1;
+
+# Unary negate.
+def unary-(v)
+  0-v;
+
+# Define > with the same precedence as <.
+def binary> 10 (LHS RHS)
+  RHS < LHS;
+
+# Binary logical or, which does not short circuit.
+def binary| 5 (LHS RHS)
+  if LHS then
+    1
+  else if RHS then
+    1
+  else
+    0;
+
+# Binary logical and, which does not short circuit.
+def binary& 6 (LHS RHS)
+  if !LHS then
+    0
+  else
+    !!RHS;
+
+# Define = with slightly lower precedence than relationals.
+def binary = 9 (LHS RHS)
+  !(LHS < RHS | LHS > RHS);
+
+
+
+ + +

Given the previous if/then/else support, we can also define interesting +functions for I/O. For example, the following prints out a character whose +"density" reflects the value passed in: the lower the value, the denser the +character:

+ +
+
+ready>
+
+extern putchard(char)
+def printdensity(d)
+  if d > 8 then
+    putchard(32)  # ' '
+  else if d > 4 then
+    putchard(46)  # '.'
+  else if d > 2 then
+    putchard(43)  # '+'
+  else
+    putchard(42); # '*'
+...
+ready> printdensity(1): printdensity(2): printdensity(3) :
+          printdensity(4): printdensity(5): printdensity(9): putchard(10);
+*++..
+Evaluated to 0.000000
+
+
+ +

Based on these simple primitive operations, we can start to define more +interesting things. For example, here's a little function that solves for the +number of iterations it takes a function in the complex plane to +converge:

+ +
+
+# determine whether the specific location diverges.
+# Solve for z = z^2 + c in the complex plane.
+def mandleconverger(real imag iters creal cimag)
+  if iters > 255 | (real*real + imag*imag > 4) then
+    iters
+  else
+    mandleconverger(real*real - imag*imag + creal,
+                    2*real*imag + cimag,
+                    iters+1, creal, cimag);
+
+# return the number of iterations required for the iteration to escape
+def mandleconverge(real imag)
+  mandleconverger(real, imag, 0, real, imag);
+
+
+ +

This "z = z2 + c" function is a beautiful little creature that is the basis +for computation of the Mandelbrot Set. Our +mandelconverge function returns the number of iterations that it takes +for a complex orbit to escape, saturating to 255. This is not a very useful +function by itself, but if you plot its value over a two-dimensional plane, +you can see the Mandelbrot set. Given that we are limited to using putchard +here, our amazing graphical output is limited, but we can whip together +something using the density plotter above:

+ +
+
+# compute and plot the mandlebrot set with the specified 2 dimensional range
+# info.
+def mandelhelp(xmin xmax xstep   ymin ymax ystep)
+  for y = ymin, y < ymax, ystep in (
+    (for x = xmin, x < xmax, xstep in
+       printdensity(mandleconverge(x,y)))
+    : putchard(10)
+  )
+
+# mandel - This is a convenient helper function for ploting the mandelbrot set
+# from the specified position with the specified Magnification.
+def mandel(realstart imagstart realmag imagmag)
+  mandelhelp(realstart, realstart+realmag*78, realmag,
+             imagstart, imagstart+imagmag*40, imagmag);
+
+
+ +

Given this, we can try plotting out the mandlebrot set! Lets try it out:

+ +
+
+ready> mandel(-2.3, -1.3, 0.05, 0.07);
+*******************************+++++++++++*************************************
+*************************+++++++++++++++++++++++*******************************
+**********************+++++++++++++++++++++++++++++****************************
+*******************+++++++++++++++++++++.. ...++++++++*************************
+*****************++++++++++++++++++++++.... ...+++++++++***********************
+***************+++++++++++++++++++++++.....   ...+++++++++*********************
+**************+++++++++++++++++++++++....     ....+++++++++********************
+*************++++++++++++++++++++++......      .....++++++++*******************
+************+++++++++++++++++++++.......       .......+++++++******************
+***********+++++++++++++++++++....                ... .+++++++*****************
+**********+++++++++++++++++.......                     .+++++++****************
+*********++++++++++++++...........                    ...+++++++***************
+********++++++++++++............                      ...++++++++**************
+********++++++++++... ..........                        .++++++++**************
+*******+++++++++.....                                   .+++++++++*************
+*******++++++++......                                  ..+++++++++*************
+*******++++++.......                                   ..+++++++++*************
+*******+++++......                                     ..+++++++++*************
+*******.... ....                                      ...+++++++++*************
+*******.... .                                         ...+++++++++*************
+*******+++++......                                    ...+++++++++*************
+*******++++++.......                                   ..+++++++++*************
+*******++++++++......                                   .+++++++++*************
+*******+++++++++.....                                  ..+++++++++*************
+********++++++++++... ..........                        .++++++++**************
+********++++++++++++............                      ...++++++++**************
+*********++++++++++++++..........                     ...+++++++***************
+**********++++++++++++++++........                     .+++++++****************
+**********++++++++++++++++++++....                ... ..+++++++****************
+***********++++++++++++++++++++++.......       .......++++++++*****************
+************+++++++++++++++++++++++......      ......++++++++******************
+**************+++++++++++++++++++++++....      ....++++++++********************
+***************+++++++++++++++++++++++.....   ...+++++++++*********************
+*****************++++++++++++++++++++++....  ...++++++++***********************
+*******************+++++++++++++++++++++......++++++++*************************
+*********************++++++++++++++++++++++.++++++++***************************
+*************************+++++++++++++++++++++++*******************************
+******************************+++++++++++++************************************
+*******************************************************************************
+*******************************************************************************
+*******************************************************************************
+Evaluated to 0.000000
+ready> mandel(-2, -1, 0.02, 0.04);
+**************************+++++++++++++++++++++++++++++++++++++++++++++++++++++
+***********************++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*********************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.
+*******************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
+*****************+++++++++++++++++++++++++++++++++++++++++++++++++++++++++.....
+***************++++++++++++++++++++++++++++++++++++++++++++++++++++++++........
+**************++++++++++++++++++++++++++++++++++++++++++++++++++++++...........
+************+++++++++++++++++++++++++++++++++++++++++++++++++++++..............
+***********++++++++++++++++++++++++++++++++++++++++++++++++++........        .
+**********++++++++++++++++++++++++++++++++++++++++++++++.............
+********+++++++++++++++++++++++++++++++++++++++++++..................
+*******+++++++++++++++++++++++++++++++++++++++.......................
+******+++++++++++++++++++++++++++++++++++...........................
+*****++++++++++++++++++++++++++++++++............................
+*****++++++++++++++++++++++++++++...............................
+****++++++++++++++++++++++++++......   .........................
+***++++++++++++++++++++++++.........     ......    ...........
+***++++++++++++++++++++++............
+**+++++++++++++++++++++..............
+**+++++++++++++++++++................
+*++++++++++++++++++.................
+*++++++++++++++++............ ...
+*++++++++++++++..............
+*+++....++++................
+*..........  ...........
+*
+*..........  ...........
+*+++....++++................
+*++++++++++++++..............
+*++++++++++++++++............ ...
+*++++++++++++++++++.................
+**+++++++++++++++++++................
+**+++++++++++++++++++++..............
+***++++++++++++++++++++++............
+***++++++++++++++++++++++++.........     ......    ...........
+****++++++++++++++++++++++++++......   .........................
+*****++++++++++++++++++++++++++++...............................
+*****++++++++++++++++++++++++++++++++............................
+******+++++++++++++++++++++++++++++++++++...........................
+*******+++++++++++++++++++++++++++++++++++++++.......................
+********+++++++++++++++++++++++++++++++++++++++++++..................
+Evaluated to 0.000000
+ready> mandel(-0.9, -1.4, 0.02, 0.03);
+*******************************************************************************
+*******************************************************************************
+*******************************************************************************
+**********+++++++++++++++++++++************************************************
+*+++++++++++++++++++++++++++++++++++++++***************************************
++++++++++++++++++++++++++++++++++++++++++++++**********************************
+++++++++++++++++++++++++++++++++++++++++++++++++++*****************************
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*************************
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**********************
++++++++++++++++++++++++++++++++++.........++++++++++++++++++*******************
++++++++++++++++++++++++++++++++....   ......+++++++++++++++++++****************
++++++++++++++++++++++++++++++.......  ........+++++++++++++++++++**************
+++++++++++++++++++++++++++++........   ........++++++++++++++++++++************
++++++++++++++++++++++++++++.........     ..  ...+++++++++++++++++++++**********
+++++++++++++++++++++++++++...........        ....++++++++++++++++++++++********
+++++++++++++++++++++++++.............       .......++++++++++++++++++++++******
++++++++++++++++++++++++.............        ........+++++++++++++++++++++++****
+++++++++++++++++++++++...........           ..........++++++++++++++++++++++***
+++++++++++++++++++++...........                .........++++++++++++++++++++++*
+++++++++++++++++++............                  ...........++++++++++++++++++++
+++++++++++++++++...............                 .............++++++++++++++++++
+++++++++++++++.................                 ...............++++++++++++++++
+++++++++++++..................                  .................++++++++++++++
++++++++++..................                      .................+++++++++++++
+++++++........        .                               .........  ..++++++++++++
+++............                                         ......    ....++++++++++
+..............                                                    ...++++++++++
+..............                                                    ....+++++++++
+..............                                                    .....++++++++
+.............                                                    ......++++++++
+...........                                                     .......++++++++
+.........                                                       ........+++++++
+.........                                                       ........+++++++
+.........                                                           ....+++++++
+........                                                             ...+++++++
+.......                                                              ...+++++++
+                                                                    ....+++++++
+                                                                   .....+++++++
+                                                                    ....+++++++
+                                                                    ....+++++++
+                                                                    ....+++++++
+Evaluated to 0.000000
+ready> ^D
+
+
+ +

At this point, you may be starting to realize that Kaleidoscope is a real +and powerful language. It may not be self-similar :), but it can be used to +plot things that are!

+ +

With this, we conclude the "adding user-defined operators" chapter of the +tutorial. We have successfully augmented our language, adding the ability to +extend the language in the library, and we have shown how this can be used to +build a simple but interesting end-user application in Kaleidoscope. At this +point, Kaleidoscope can build a variety of applications that are functional and +can call functions with side-effects, but it can't actually define and mutate a +variable itself.

+ +

Strikingly, variable mutation is an important feature of some +languages, and it is not at all obvious how to add +support for mutable variables without having to add an "SSA construction" +phase to your front-end. In the next chapter, we will describe how you can +add variable mutation without building SSA in your front-end.

+ +
+ + + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with the +if/then/else and for expressions.. To build this example, use: +

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
+<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
+<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
+
+
+ +
myocamlbuild.ml:
+
+
+open Ocamlbuild_plugin;;
+
+ocaml_lib ~extern:true "llvm";;
+ocaml_lib ~extern:true "llvm_analysis";;
+ocaml_lib ~extern:true "llvm_executionengine";;
+ocaml_lib ~extern:true "llvm_target";;
+ocaml_lib ~extern:true "llvm_scalar_opts";;
+
+flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
+dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+  (* control *)
+  | If | Then | Else
+  | For | In
+
+  (* operators *)
+  | Binary | Unary
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | "if" -> [< 'Token.If; stream >]
+      | "then" -> [< 'Token.Then; stream >]
+      | "else" -> [< 'Token.Else; stream >]
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | "binary" -> [< 'Token.Binary; stream >]
+      | "unary" -> [< 'Token.Unary; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a unary operator. *)
+  | Unary of char * expr
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+  (* variant for if/then/else. *)
+  | If of expr * expr * expr
+
+  (* variant for for/in. *)
+  | For of string * expr * expr * expr option * expr
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto =
+  | Prototype of string * string array
+  | BinOpPrototype of string * string array * int
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr
+ *   ::= ifexpr
+ *   ::= forexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
+  | [< 'Token.If; c=parse_expr;
+       'Token.Then ?? "expected 'then'"; t=parse_expr;
+       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
+      Ast.If (c, t, e)
+
+  (* forexpr
+        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
+  | [< 'Token.For;
+       'Token.Ident id ?? "expected identifier after for";
+       'Token.Kwd '=' ?? "expected '=' after for";
+       stream >] ->
+      begin parser
+        | [<
+             start=parse_expr;
+             'Token.Kwd ',' ?? "expected ',' after for";
+             end_=parse_expr;
+             stream >] ->
+            let step =
+              begin parser
+              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
+              | [< >] -> None
+              end stream
+            in
+            begin parser
+            | [< 'Token.In; body=parse_expr >] ->
+                Ast.For (id, start, end_, step, body)
+            | [< >] ->
+                raise (Stream.Error "expected 'in' after for")
+            end stream
+        | [< >] ->
+            raise (Stream.Error "expected '=' after for")
+      end stream
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* unary
+ *   ::= primary
+ *   ::= '!' unary *)
+and parse_unary = parser
+  (* If this is a unary operator, read it. *)
+  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
+      Ast.Unary (op, operand)
+
+  (* If the current token is not an operator, it must be a primary expr. *)
+  | [< stream >] -> parse_primary stream
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the unary expression after the binary operator. *)
+        let rhs = parse_unary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')'
+ *   ::= binary LETTER number? (id, id)
+ *   ::= unary LETTER number? (id) *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+  let parse_operator = parser
+    | [< 'Token.Unary >] -> "unary", 1
+    | [< 'Token.Binary >] -> "binary", 2
+  in
+  let parse_binary_precedence = parser
+    | [< 'Token.Number n >] -> int_of_float n
+    | [< >] -> 30
+  in
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+  | [< (prefix, kind)=parse_operator;
+       'Token.Kwd op ?? "expected an operator";
+       (* Read the precedence if present. *)
+       binary_precedence=parse_binary_precedence;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+        args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      let name = prefix ^ (String.make 1 op) in
+      let args = Array.of_list (List.rev args) in
+
+      (* Verify right number of arguments for operator. *)
+      if Array.length args != kind
+      then raise (Stream.Error "invalid number of operands for operator")
+      else
+        if kind == 1 then
+          Ast.Prototype (name, args)
+        else
+          Ast.BinOpPrototype (name, args, binary_precedence)
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
codegen.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Code Generation
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+exception Error of string
+
+let context = global_context ()
+let the_module = create_module context "my cool jit"
+let builder = builder context
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+let rec codegen_expr = function
+  | Ast.Number n -> const_float double_type n
+  | Ast.Variable name ->
+      (try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name"))
+  | Ast.Unary (op, operand) ->
+      let operand = codegen_expr operand in
+      let callee = "unary" ^ (String.make 1 op) in
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown unary operator")
+      in
+      build_call callee [|operand|] "unop" builder
+  | Ast.Binary (op, lhs, rhs) ->
+      let lhs_val = codegen_expr lhs in
+      let rhs_val = codegen_expr rhs in
+      begin
+        match op with
+        | '+' -> build_add lhs_val rhs_val "addtmp" builder
+        | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+        | '*' -> build_mul lhs_val rhs_val "multmp" builder
+        | '<' ->
+            (* Convert bool 0/1 to double 0.0 or 1.0 *)
+            let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+            build_uitofp i double_type "booltmp" builder
+        | _ ->
+            (* If it wasn't a builtin binary operator, it must be a user defined
+             * one. Emit a call to it. *)
+            let callee = "binary" ^ (String.make 1 op) in
+            let callee =
+              match lookup_function callee the_module with
+              | Some callee -> callee
+              | None -> raise (Error "binary operator not found!")
+            in
+            build_call callee [|lhs_val; rhs_val|] "binop" builder
+      end
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+  | Ast.If (cond, then_, else_) ->
+      let cond = codegen_expr cond in
+
+      (* Convert condition to a bool by comparing equal to 0.0 *)
+      let zero = const_float double_type 0.0 in
+      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
+
+      (* Grab the first block so that we might later add the conditional branch
+       * to it at the end of the function. *)
+      let start_bb = insertion_block builder in
+      let the_function = block_parent start_bb in
+
+      let then_bb = append_block context "then" the_function in
+
+      (* Emit 'then' value. *)
+      position_at_end then_bb builder;
+      let then_val = codegen_expr then_ in
+
+      (* Codegen of 'then' can change the current block, update then_bb for the
+       * phi. We create a new name because one is used for the phi node, and the
+       * other is used for the conditional branch. *)
+      let new_then_bb = insertion_block builder in
+
+      (* Emit 'else' value. *)
+      let else_bb = append_block context "else" the_function in
+      position_at_end else_bb builder;
+      let else_val = codegen_expr else_ in
+
+      (* Codegen of 'else' can change the current block, update else_bb for the
+       * phi. *)
+      let new_else_bb = insertion_block builder in
+
+      (* Emit merge block. *)
+      let merge_bb = append_block context "ifcont" the_function in
+      position_at_end merge_bb builder;
+      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
+      let phi = build_phi incoming "iftmp" builder in
+
+      (* Return to the start block to add the conditional branch. *)
+      position_at_end start_bb builder;
+      ignore (build_cond_br cond_val then_bb else_bb builder);
+
+      (* Set a unconditional branch at the end of the 'then' block and the
+       * 'else' block to the 'merge' block. *)
+      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
+      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
+
+      (* Finally, set the builder to the end of the merge block. *)
+      position_at_end merge_bb builder;
+
+      phi
+  | Ast.For (var_name, start, end_, step, body) ->
+      (* Emit the start code first, without 'variable' in scope. *)
+      let start_val = codegen_expr start in
+
+      (* Make the new basic block for the loop header, inserting after current
+       * block. *)
+      let preheader_bb = insertion_block builder in
+      let the_function = block_parent preheader_bb in
+      let loop_bb = append_block context "loop" the_function in
+
+      (* Insert an explicit fall through from the current block to the
+       * loop_bb. *)
+      ignore (build_br loop_bb builder);
+
+      (* Start insertion in loop_bb. *)
+      position_at_end loop_bb builder;
+
+      (* Start the PHI node with an entry for start. *)
+      let variable = build_phi [(start_val, preheader_bb)] var_name builder in
+
+      (* Within the loop, the variable is defined equal to the PHI node. If it
+       * shadows an existing variable, we have to restore it, so save it
+       * now. *)
+      let old_val =
+        try Some (Hashtbl.find named_values var_name) with Not_found -> None
+      in
+      Hashtbl.add named_values var_name variable;
+
+      (* Emit the body of the loop.  This, like any other expr, can change the
+       * current BB.  Note that we ignore the value computed by the body, but
+       * don't allow an error *)
+      ignore (codegen_expr body);
+
+      (* Emit the step value. *)
+      let step_val =
+        match step with
+        | Some step -> codegen_expr step
+        (* If not specified, use 1.0. *)
+        | None -> const_float double_type 1.0
+      in
+
+      let next_var = build_add variable step_val "nextvar" builder in
+
+      (* Compute the end condition. *)
+      let end_cond = codegen_expr end_ in
+
+      (* Convert condition to a bool by comparing equal to 0.0. *)
+      let zero = const_float double_type 0.0 in
+      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
+
+      (* Create the "after loop" block and insert it. *)
+      let loop_end_bb = insertion_block builder in
+      let after_bb = append_block context "afterloop" the_function in
+
+      (* Insert the conditional branch into the end of loop_end_bb. *)
+      ignore (build_cond_br end_cond loop_bb after_bb builder);
+
+      (* Any new code will be inserted in after_bb. *)
+      position_at_end after_bb builder;
+
+      (* Add a new entry to the PHI node for the backedge. *)
+      add_incoming (next_var, loop_end_bb) variable;
+
+      (* Restore the unshadowed variable. *)
+      begin match old_val with
+      | Some old_val -> Hashtbl.add named_values var_name old_val
+      | None -> ()
+      end;
+
+      (* for expr always returns 0.0. *)
+      const_null double_type
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+        | None -> declare_function name ft the_module
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if block_begin f <> At_end f then
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if element_type (type_of f) <> ft then
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+let codegen_func the_fpm = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* If this is an operator, install it. *)
+      begin match proto with
+      | Ast.BinOpPrototype (name, args, prec) ->
+          let op = name.[String.length name - 1] in
+          Hashtbl.add Parser.binop_precedence op prec;
+      | _ -> ()
+      end;
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        (* Optimize the function. *)
+        let _ = PassManager.run_function the_function the_fpm in
+
+        the_function
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop the_fpm the_execution_engine stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop the_fpm the_execution_engine stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            let e = Parser.parse_definition stream in
+            print_endline "parsed a function definition.";
+            dump_value (Codegen.codegen_func the_fpm e);
+        | Token.Extern ->
+            let e = Parser.parse_extern stream in
+            print_endline "parsed an extern.";
+            dump_value (Codegen.codegen_proto e);
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            let the_function = Codegen.codegen_func the_fpm e in
+            dump_value the_function;
+
+            (* JIT the function, returning a function pointer. *)
+            let result = ExecutionEngine.run_function the_function [||]
+              the_execution_engine in
+
+            print_string "Evaluated to ";
+            print_float (GenericValue.as_float Codegen.double_type result);
+            print_newline ();
+        with Stream.Error s | Codegen.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop the_fpm the_execution_engine stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+open Llvm_target
+open Llvm_scalar_opts
+
+let main () =
+  ignore (initialize_native_target ());
+
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combination the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+  (* Eliminate Common SubExpressions. *)
+  add_gvn the_fpm;
+
+  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
+  add_cfg_simplification the_fpm;
+
+  ignore (PassManager.initialize the_fpm);
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop the_fpm the_execution_engine stream;
+
+  (* Print out all the generated code. *)
+  dump_module Codegen.the_module
+;;
+
+main ()
+
+
+ +
bindings.c
+
+
+#include <stdio.h>
+
+/* putchard - putchar that takes a double and returns 0. */
+extern double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+/* printd - printf that takes a double prints it as "%f\n", returning 0. */
+extern double printd(double X) {
+  printf("%f\n", X);
+  return 0;
+}
+
+
+
+ +Next: Extending the language: mutable variables / +SSA construction +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ Erick Tryzelaar
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl7.html b/final/docs/tutorial/OCamlLangImpl7.html new file mode 100644 index 00000000000..7146a5cacde --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl7.html @@ -0,0 +1,1907 @@ + + + + + Kaleidoscope: Extending the Language: Mutable Variables / SSA + construction + + + + + + + + +
Kaleidoscope: Extending the Language: Mutable Variables
+ + + +
+

+ Written by Chris Lattner + and Erick Tryzelaar +

+
+ + + + + +
+ +

Welcome to Chapter 7 of the "Implementing a language +with LLVM" tutorial. In chapters 1 through 6, we've built a very +respectable, albeit simple, functional +programming language. In our journey, we learned some parsing techniques, +how to build and represent an AST, how to build LLVM IR, and how to optimize +the resultant code as well as JIT compile it.

+ +

While Kaleidoscope is interesting as a functional language, the fact that it +is functional makes it "too easy" to generate LLVM IR for it. In particular, a +functional language makes it very easy to build LLVM IR directly in SSA form. +Since LLVM requires that the input code be in SSA form, this is a very nice +property and it is often unclear to newcomers how to generate code for an +imperative language with mutable variables.

+ +

The short (and happy) summary of this chapter is that there is no need for +your front-end to build SSA form: LLVM provides highly tuned and well tested +support for this, though the way it works is a bit unexpected for some.

+ +
+ + + + + +
+ +

+To understand why mutable variables cause complexities in SSA construction, +consider this extremely simple C example: +

+ +
+
+int G, H;
+int test(_Bool Condition) {
+  int X;
+  if (Condition)
+    X = G;
+  else
+    X = H;
+  return X;
+}
+
+
+ +

In this case, we have the variable "X", whose value depends on the path +executed in the program. Because there are two different possible values for X +before the return instruction, a PHI node is inserted to merge the two values. +The LLVM IR that we want for this example looks like this:

+ +
+
+@G = weak global i32 0   ; type of @G is i32*
+@H = weak global i32 0   ; type of @H is i32*
+
+define i32 @test(i1 %Condition) {
+entry:
+  br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+  %X.0 = load i32* @G
+  br label %cond_next
+
+cond_false:
+  %X.1 = load i32* @H
+  br label %cond_next
+
+cond_next:
+  %X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+  ret i32 %X.2
+}
+
+
+ +

In this example, the loads from the G and H global variables are explicit in +the LLVM IR, and they live in the then/else branches of the if statement +(cond_true/cond_false). In order to merge the incoming values, the X.2 phi node +in the cond_next block selects the right value to use based on where control +flow is coming from: if control flow comes from the cond_false block, X.2 gets +the value of X.1. Alternatively, if control flow comes from cond_true, it gets +the value of X.0. The intent of this chapter is not to explain the details of +SSA form. For more information, see one of the many online +references.

+ +

The question for this article is "who places the phi nodes when lowering +assignments to mutable variables?". The issue here is that LLVM +requires that its IR be in SSA form: there is no "non-ssa" mode for it. +However, SSA construction requires non-trivial algorithms and data structures, +so it is inconvenient and wasteful for every front-end to have to reproduce this +logic.

+ +
+ + + + + +
+ +

The 'trick' here is that while LLVM does require all register values to be +in SSA form, it does not require (or permit) memory objects to be in SSA form. +In the example above, note that the loads from G and H are direct accesses to +G and H: they are not renamed or versioned. This differs from some other +compiler systems, which do try to version memory objects. In LLVM, instead of +encoding dataflow analysis of memory into the LLVM IR, it is handled with Analysis Passes which are computed on +demand.

+ +

+With this in mind, the high-level idea is that we want to make a stack variable +(which lives in memory, because it is on the stack) for each mutable object in +a function. To take advantage of this trick, we need to talk about how LLVM +represents stack variables. +

+ +

In LLVM, all memory accesses are explicit with load/store instructions, and +it is carefully designed not to have (or need) an "address-of" operator. Notice +how the type of the @G/@H global variables is actually "i32*" even though the +variable is defined as "i32". What this means is that @G defines space +for an i32 in the global data area, but its name actually refers to the +address for that space. Stack variables work the same way, except that instead of +being declared with global variable definitions, they are declared with the +LLVM alloca instruction:

+ +
+
+define i32 @example() {
+entry:
+  %X = alloca i32           ; type of %X is i32*.
+  ...
+  %tmp = load i32* %X       ; load the stack value %X from the stack.
+  %tmp2 = add i32 %tmp, 1   ; increment it
+  store i32 %tmp2, i32* %X  ; store it back
+  ...
+
+
+ +

This code shows an example of how you can declare and manipulate a stack +variable in the LLVM IR. Stack memory allocated with the alloca instruction is +fully general: you can pass the address of the stack slot to functions, you can +store it in other variables, etc. In our example above, we could rewrite the +example to use the alloca technique to avoid using a PHI node:

+ +
+
+@G = weak global i32 0   ; type of @G is i32*
+@H = weak global i32 0   ; type of @H is i32*
+
+define i32 @test(i1 %Condition) {
+entry:
+  %X = alloca i32           ; type of %X is i32*.
+  br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+  %X.0 = load i32* @G
+        store i32 %X.0, i32* %X   ; Update X
+  br label %cond_next
+
+cond_false:
+  %X.1 = load i32* @H
+        store i32 %X.1, i32* %X   ; Update X
+  br label %cond_next
+
+cond_next:
+  %X.2 = load i32* %X       ; Read X
+  ret i32 %X.2
+}
+
+
+ +

With this, we have discovered a way to handle arbitrary mutable variables +without the need to create Phi nodes at all:

+ +
    +
  1. Each mutable variable becomes a stack allocation.
  2. +
  3. Each read of the variable becomes a load from the stack.
  4. +
  5. Each update of the variable becomes a store to the stack.
  6. +
  7. Taking the address of a variable just uses the stack address directly.
  8. +
+ +

While this solution has solved our immediate problem, it introduced another +one: we have now apparently introduced a lot of stack traffic for very simple +and common operations, a major performance problem. Fortunately for us, the +LLVM optimizer has a highly-tuned optimization pass named "mem2reg" that handles +this case, promoting allocas like this into SSA registers, inserting Phi nodes +as appropriate. If you run this example through the pass, for example, you'll +get:

+ +
+
+$ llvm-as < example.ll | opt -mem2reg | llvm-dis
+@G = weak global i32 0
+@H = weak global i32 0
+
+define i32 @test(i1 %Condition) {
+entry:
+  br i1 %Condition, label %cond_true, label %cond_false
+
+cond_true:
+  %X.0 = load i32* @G
+  br label %cond_next
+
+cond_false:
+  %X.1 = load i32* @H
+  br label %cond_next
+
+cond_next:
+  %X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
+  ret i32 %X.01
+}
+
+
+ +

The mem2reg pass implements the standard "iterated dominance frontier" +algorithm for constructing SSA form and has a number of optimizations that speed +up (very common) degenerate cases. The mem2reg optimization pass is the answer +to dealing with mutable variables, and we highly recommend that you depend on +it. Note that mem2reg only works on variables in certain circumstances:

+ +
    +
  1. mem2reg is alloca-driven: it looks for allocas and if it can handle them, it +promotes them. It does not apply to global variables or heap allocations.
  2. + +
  3. mem2reg only looks for alloca instructions in the entry block of the +function. Being in the entry block guarantees that the alloca is only executed +once, which makes analysis simpler.
  4. + +
  5. mem2reg only promotes allocas whose uses are direct loads and stores. If +the address of the stack object is passed to a function, or if any funny pointer +arithmetic is involved, the alloca will not be promoted.
  6. + +
  7. mem2reg only works on allocas of first class +values (such as pointers, scalars and vectors), and only if the array size +of the allocation is 1 (or missing in the .ll file). mem2reg is not capable of +promoting structs or arrays to registers. Note that the "scalarrepl" pass is +more powerful and can promote structs, "unions", and arrays in many cases.
  8. + +
+ +

+All of these properties are easy to satisfy for most imperative languages, and +we'll illustrate it below with Kaleidoscope. The final question you may be +asking is: should I bother with this nonsense for my front-end? Wouldn't it be +better if I just did SSA construction directly, avoiding use of the mem2reg +optimization pass? In short, we strongly recommend that you use this technique +for building SSA form, unless there is an extremely good reason not to. Using +this technique is:

+ +
    +
  • Proven and well tested: llvm-gcc and clang both use this technique for local +mutable variables. As such, the most common clients of LLVM are using this to +handle a bulk of their variables. You can be sure that bugs are found fast and +fixed early.
  • + +
  • Extremely Fast: mem2reg has a number of special cases that make it fast in +common cases as well as fully general. For example, it has fast-paths for +variables that are only used in a single block, variables that only have one +assignment point, good heuristics to avoid insertion of unneeded phi nodes, etc. +
  • + +
  • Needed for debug info generation: +Debug information in LLVM relies on having the address of the variable +exposed so that debug info can be attached to it. This technique dovetails +very naturally with this style of debug info.
  • +
+ +

If nothing else, this makes it much easier to get your front-end up and +running, and is very simple to implement. Lets extend Kaleidoscope with mutable +variables now! +

+ +
+ + + + + +
+ +

Now that we know the sort of problem we want to tackle, lets see what this +looks like in the context of our little Kaleidoscope language. We're going to +add two features:

+ +
    +
  1. The ability to mutate variables with the '=' operator.
  2. +
  3. The ability to define new variables.
  4. +
+ +

While the first item is really what this is about, we only have variables +for incoming arguments as well as for induction variables, and redefining those only +goes so far :). Also, the ability to define new variables is a +useful thing regardless of whether you will be mutating them. Here's a +motivating example that shows how we could use these:

+ +
+
+# Define ':' for sequencing: as a low-precedence operator that ignores operands
+# and just returns the RHS.
+def binary : 1 (x y) y;
+
+# Recursive fib, we could do this before.
+def fib(x)
+  if (x < 3) then
+    1
+  else
+    fib(x-1)+fib(x-2);
+
+# Iterative fib.
+def fibi(x)
+  var a = 1, b = 1, c in
+  (for i = 3, i < x in
+     c = a + b :
+     a = b :
+     b = c) :
+  b;
+
+# Call it.
+fibi(10);
+
+
+ +

+In order to mutate variables, we have to change our existing variables to use +the "alloca trick". Once we have that, we'll add our new operator, then extend +Kaleidoscope to support new variable definitions. +

+ +
+ + + + + +
+ +

+The symbol table in Kaleidoscope is managed at code generation time by the +'named_values' map. This map currently keeps track of the LLVM +"Value*" that holds the double value for the named variable. In order to +support mutation, we need to change this slightly, so that it +named_values holds the memory location of the variable in +question. Note that this change is a refactoring: it changes the structure of +the code, but does not (by itself) change the behavior of the compiler. All of +these changes are isolated in the Kaleidoscope code generator.

+ +

+At this point in Kaleidoscope's development, it only supports variables for two +things: incoming arguments to functions and the induction variable of 'for' +loops. For consistency, we'll allow mutation of these variables in addition to +other user-defined variables. This means that these will both need memory +locations. +

+ +

To start our transformation of Kaleidoscope, we'll change the +named_values map so that it maps to AllocaInst* instead of Value*. +Once we do this, the C++ compiler will tell us what parts of the code we need to +update:

+ +

Note: the ocaml bindings currently model both Value*s and +AllocInst*s as Llvm.llvalues, but this may change in the +future to be more type safe.

+ +
+
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+
+
+ +

Also, since we will need to create these alloca's, we'll use a helper +function that ensures that the allocas are created in the entry block of the +function:

+ +
+
+(* Create an alloca instruction in the entry block of the function. This
+ * is used for mutable variables etc. *)
+let create_entry_block_alloca the_function var_name =
+  let builder = builder_at (instr_begin (entry_block the_function)) in
+  build_alloca double_type var_name builder
+
+
+ +

This funny looking code creates an Llvm.llbuilder object that is +pointing at the first instruction of the entry block. It then creates an alloca +with the expected name and returns it. Because all values in Kaleidoscope are +doubles, there is no need to pass in a type to use.

+ +

With this in place, the first functionality change we want to make is to +variable references. In our new scheme, variables live on the stack, so code +generating a reference to them actually needs to produce a load from the stack +slot:

+ +
+
+let rec codegen_expr = function
+  ...
+  | Ast.Variable name ->
+      let v = try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name")
+      in
+      (* Load the value. *)
+      build_load v name builder
+
+
+ +

As you can see, this is pretty straightforward. Now we need to update the +things that define the variables to set up the alloca. We'll start with +codegen_expr Ast.For ... (see the full code listing +for the unabridged code):

+ +
+
+  | Ast.For (var_name, start, end_, step, body) ->
+      let the_function = block_parent (insertion_block builder) in
+
+      (* Create an alloca for the variable in the entry block. *)
+      let alloca = create_entry_block_alloca the_function var_name in
+
+      (* Emit the start code first, without 'variable' in scope. *)
+      let start_val = codegen_expr start in
+
+      (* Store the value into the alloca. *)
+      ignore(build_store start_val alloca builder);
+
+      ...
+
+      (* Within the loop, the variable is defined equal to the PHI node. If it
+       * shadows an existing variable, we have to restore it, so save it
+       * now. *)
+      let old_val =
+        try Some (Hashtbl.find named_values var_name) with Not_found -> None
+      in
+      Hashtbl.add named_values var_name alloca;
+
+      ...
+
+      (* Compute the end condition. *)
+      let end_cond = codegen_expr end_ in
+
+      (* Reload, increment, and restore the alloca. This handles the case where
+       * the body of the loop mutates the variable. *)
+      let cur_var = build_load alloca var_name builder in
+      let next_var = build_add cur_var step_val "nextvar" builder in
+      ignore(build_store next_var alloca builder);
+      ...
+
+
+ +

This code is virtually identical to the code before we allowed mutable variables. +The big difference is that we no longer have to construct a PHI node, and we use +load/store to access the variable as needed.

+ +

To support mutable argument variables, we need to also make allocas for them. +The code for this is also pretty simple:

+ +
+
+(* Create an alloca for each argument and register the argument in the symbol
+ * table so that references to it will succeed. *)
+let create_argument_allocas the_function proto =
+  let args = match proto with
+    | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args
+  in
+  Array.iteri (fun i ai ->
+    let var_name = args.(i) in
+    (* Create an alloca for this variable. *)
+    let alloca = create_entry_block_alloca the_function var_name in
+
+    (* Store the initial value into the alloca. *)
+    ignore(build_store ai alloca builder);
+
+    (* Add arguments to variable symbol table. *)
+    Hashtbl.add named_values var_name alloca;
+  ) (params the_function)
+
+
+ +

For each argument, we make an alloca, store the input value to the function +into the alloca, and register the alloca as the memory location for the +argument. This method gets invoked by Codegen.codegen_func right after +it sets up the entry block for the function.

+ +

The final missing piece is adding the mem2reg pass, which allows us to get +good codegen once again:

+ +
+
+let main () =
+  ...
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Promote allocas to registers. *)
+  add_memory_to_register_promotion the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combining the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+
+ +

It is interesting to see what the code looks like before and after the +mem2reg optimization runs. For example, this is the before/after code for our +recursive fib function. Before the optimization:

+ +
+
+define double @fib(double %x) {
+entry:
+  %x1 = alloca double
+  store double %x, double* %x1
+  %x2 = load double* %x1
+  %cmptmp = fcmp ult double %x2, 3.000000e+00
+  %booltmp = uitofp i1 %cmptmp to double
+  %ifcond = fcmp one double %booltmp, 0.000000e+00
+  br i1 %ifcond, label %then, label %else
+
+then:    ; preds = %entry
+  br label %ifcont
+
+else:    ; preds = %entry
+  %x3 = load double* %x1
+  %subtmp = fsub double %x3, 1.000000e+00
+  %calltmp = call double @fib(double %subtmp)
+  %x4 = load double* %x1
+  %subtmp5 = fsub double %x4, 2.000000e+00
+  %calltmp6 = call double @fib(double %subtmp5)
+  %addtmp = fadd double %calltmp, %calltmp6
+  br label %ifcont
+
+ifcont:    ; preds = %else, %then
+  %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+  ret double %iftmp
+}
+
+
+ +

Here there is only one variable (x, the input argument) but you can still +see the extremely simple-minded code generation strategy we are using. In the +entry block, an alloca is created, and the initial input value is stored into +it. Each reference to the variable does a reload from the stack. Also, note +that we didn't modify the if/then/else expression, so it still inserts a PHI +node. While we could make an alloca for it, it is actually easier to create a +PHI node for it, so we still just make the PHI.

+ +

Here is the code after the mem2reg pass runs:

+ +
+
+define double @fib(double %x) {
+entry:
+  %cmptmp = fcmp ult double %x, 3.000000e+00
+  %booltmp = uitofp i1 %cmptmp to double
+  %ifcond = fcmp one double %booltmp, 0.000000e+00
+  br i1 %ifcond, label %then, label %else
+
+then:
+  br label %ifcont
+
+else:
+  %subtmp = fsub double %x, 1.000000e+00
+  %calltmp = call double @fib(double %subtmp)
+  %subtmp5 = fsub double %x, 2.000000e+00
+  %calltmp6 = call double @fib(double %subtmp5)
+  %addtmp = fadd double %calltmp, %calltmp6
+  br label %ifcont
+
+ifcont:    ; preds = %else, %then
+  %iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
+  ret double %iftmp
+}
+
+
+ +

This is a trivial case for mem2reg, since there are no redefinitions of the +variable. The point of showing this is to calm your tension about inserting +such blatent inefficiencies :).

+ +

After the rest of the optimizers run, we get:

+ +
+
+define double @fib(double %x) {
+entry:
+  %cmptmp = fcmp ult double %x, 3.000000e+00
+  %booltmp = uitofp i1 %cmptmp to double
+  %ifcond = fcmp ueq double %booltmp, 0.000000e+00
+  br i1 %ifcond, label %else, label %ifcont
+
+else:
+  %subtmp = fsub double %x, 1.000000e+00
+  %calltmp = call double @fib(double %subtmp)
+  %subtmp5 = fsub double %x, 2.000000e+00
+  %calltmp6 = call double @fib(double %subtmp5)
+  %addtmp = fadd double %calltmp, %calltmp6
+  ret double %addtmp
+
+ifcont:
+  ret double 1.000000e+00
+}
+
+
+ +

Here we see that the simplifycfg pass decided to clone the return instruction +into the end of the 'else' block. This allowed it to eliminate some branches +and the PHI node.

+ +

Now that all symbol table references are updated to use stack variables, +we'll add the assignment operator.

+ +
+ + + + + +
+ +

With our current framework, adding a new assignment operator is really +simple. We will parse it just like any other binary operator, but handle it +internally (instead of allowing the user to define it). The first step is to +set a precedence:

+ +
+
+let main () =
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '=' 2;
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  ...
+
+
+ +

Now that the parser knows the precedence of the binary operator, it takes +care of all the parsing and AST generation. We just need to implement codegen +for the assignment operator. This looks like:

+ +
+
+let rec codegen_expr = function
+      begin match op with
+      | '=' ->
+          (* Special case '=' because we don't want to emit the LHS as an
+           * expression. *)
+          let name =
+            match lhs with
+            | Ast.Variable name -> name
+            | _ -> raise (Error "destination of '=' must be a variable")
+          in
+
+
+ +

Unlike the rest of the binary operators, our assignment operator doesn't +follow the "emit LHS, emit RHS, do computation" model. As such, it is handled +as a special case before the other binary operators are handled. The other +strange thing is that it requires the LHS to be a variable. It is invalid to +have "(x+1) = expr" - only things like "x = expr" are allowed. +

+ + +
+
+          (* Codegen the rhs. *)
+          let val_ = codegen_expr rhs in
+
+          (* Lookup the name. *)
+          let variable = try Hashtbl.find named_values name with
+          | Not_found -> raise (Error "unknown variable name")
+          in
+          ignore(build_store val_ variable builder);
+          val_
+      | _ ->
+			...
+
+
+ +

Once we have the variable, codegen'ing the assignment is straightforward: +we emit the RHS of the assignment, create a store, and return the computed +value. Returning a value allows for chained assignments like "X = (Y = Z)".

+ +

Now that we have an assignment operator, we can mutate loop variables and +arguments. For example, we can now run code like this:

+ +
+
+# Function to print a double.
+extern printd(x);
+
+# Define ':' for sequencing: as a low-precedence operator that ignores operands
+# and just returns the RHS.
+def binary : 1 (x y) y;
+
+def test(x)
+  printd(x) :
+  x = 4 :
+  printd(x);
+
+test(123);
+
+
+ +

When run, this example prints "123" and then "4", showing that we did +actually mutate the value! Okay, we have now officially implemented our goal: +getting this to work requires SSA construction in the general case. However, +to be really useful, we want the ability to define our own local variables, lets +add this next! +

+ +
+ + + + + +
+ +

Adding var/in is just like any other other extensions we made to +Kaleidoscope: we extend the lexer, the parser, the AST and the code generator. +The first step for adding our new 'var/in' construct is to extend the lexer. +As before, this is pretty trivial, the code looks like this:

+ +
+
+type token =
+  ...
+  (* var definition *)
+  | Var
+
+...
+
+and lex_ident buffer = parser
+      ...
+      | "in" -> [< 'Token.In; stream >]
+      | "binary" -> [< 'Token.Binary; stream >]
+      | "unary" -> [< 'Token.Unary; stream >]
+      | "var" -> [< 'Token.Var; stream >]
+      ...
+
+
+ +

The next step is to define the AST node that we will construct. For var/in, +it looks like this:

+ +
+
+type expr =
+  ...
+  (* variant for var/in. *)
+  | Var of (string * expr option) array * expr
+  ...
+
+
+ +

var/in allows a list of names to be defined all at once, and each name can +optionally have an initializer value. As such, we capture this information in +the VarNames vector. Also, var/in has a body, this body is allowed to access +the variables defined by the var/in.

+ +

With this in place, we can define the parser pieces. The first thing we do +is add it as a primary expression:

+ +
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr
+ *   ::= ifexpr
+ *   ::= forexpr
+ *   ::= varexpr *)
+let rec parse_primary = parser
+  ...
+  (* varexpr
+   *   ::= 'var' identifier ('=' expression?
+   *             (',' identifier ('=' expression)?)* 'in' expression *)
+  | [< 'Token.Var;
+       (* At least one variable name is required. *)
+       'Token.Ident id ?? "expected identifier after var";
+       init=parse_var_init;
+       var_names=parse_var_names [(id, init)];
+       (* At this point, we have to have 'in'. *)
+       'Token.In ?? "expected 'in' keyword after 'var'";
+       body=parse_expr >] ->
+      Ast.Var (Array.of_list (List.rev var_names), body)
+
+...
+
+and parse_var_init = parser
+  (* read in the optional initializer. *)
+  | [< 'Token.Kwd '='; e=parse_expr >] -> Some e
+  | [< >] -> None
+
+and parse_var_names accumulator = parser
+  | [< 'Token.Kwd ',';
+       'Token.Ident id ?? "expected identifier list after var";
+       init=parse_var_init;
+       e=parse_var_names ((id, init) :: accumulator) >] -> e
+  | [< >] -> accumulator
+
+
+ +

Now that we can parse and represent the code, we need to support emission of +LLVM IR for it. This code starts out with:

+ +
+
+let rec codegen_expr = function
+  ...
+  | Ast.Var (var_names, body)
+      let old_bindings = ref [] in
+
+      let the_function = block_parent (insertion_block builder) in
+
+      (* Register all variables and emit their initializer. *)
+      Array.iter (fun (var_name, init) ->
+
+
+ +

Basically it loops over all the variables, installing them one at a time. +For each variable we put into the symbol table, we remember the previous value +that we replace in OldBindings.

+ +
+
+        (* Emit the initializer before adding the variable to scope, this
+         * prevents the initializer from referencing the variable itself, and
+         * permits stuff like this:
+         *   var a = 1 in
+         *     var a = a in ...   # refers to outer 'a'. *)
+        let init_val =
+          match init with
+          | Some init -> codegen_expr init
+          (* If not specified, use 0.0. *)
+          | None -> const_float double_type 0.0
+        in
+
+        let alloca = create_entry_block_alloca the_function var_name in
+        ignore(build_store init_val alloca builder);
+
+        (* Remember the old variable binding so that we can restore the binding
+         * when we unrecurse. *)
+
+        begin
+          try
+            let old_value = Hashtbl.find named_values var_name in
+            old_bindings := (var_name, old_value) :: !old_bindings;
+          with Not_found > ()
+        end;
+
+        (* Remember this binding. *)
+        Hashtbl.add named_values var_name alloca;
+      ) var_names;
+
+
+ +

There are more comments here than code. The basic idea is that we emit the +initializer, create the alloca, then update the symbol table to point to it. +Once all the variables are installed in the symbol table, we evaluate the body +of the var/in expression:

+ +
+
+      (* Codegen the body, now that all vars are in scope. *)
+      let body_val = codegen_expr body in
+
+
+ +

Finally, before returning, we restore the previous variable bindings:

+ +
+
+      (* Pop all our variables from scope. *)
+      List.iter (fun (var_name, old_value) ->
+        Hashtbl.add named_values var_name old_value
+      ) !old_bindings;
+
+      (* Return the body computation. *)
+      body_val
+
+
+ +

The end result of all of this is that we get properly scoped variable +definitions, and we even (trivially) allow mutation of them :).

+ +

With this, we completed what we set out to do. Our nice iterative fib +example from the intro compiles and runs just fine. The mem2reg pass optimizes +all of our stack variables into SSA registers, inserting PHI nodes where needed, +and our front-end remains simple: no "iterated dominance frontier" computation +anywhere in sight.

+ +
+ + + + + +
+ +

+Here is the complete code listing for our running example, enhanced with mutable +variables and var/in support. To build this example, use: +

+ +
+
+# Compile
+ocamlbuild toy.byte
+# Run
+./toy.byte
+
+
+ +

Here is the code:

+ +
+
_tags:
+
+
+<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
+<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
+<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
+<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
+
+
+ +
myocamlbuild.ml:
+
+
+open Ocamlbuild_plugin;;
+
+ocaml_lib ~extern:true "llvm";;
+ocaml_lib ~extern:true "llvm_analysis";;
+ocaml_lib ~extern:true "llvm_executionengine";;
+ocaml_lib ~extern:true "llvm_target";;
+ocaml_lib ~extern:true "llvm_scalar_opts";;
+
+flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);;
+dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
+
+
+ +
token.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer Tokens
+ *===----------------------------------------------------------------------===*)
+
+(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
+ * these others for known things. *)
+type token =
+  (* commands *)
+  | Def | Extern
+
+  (* primary *)
+  | Ident of string | Number of float
+
+  (* unknown *)
+  | Kwd of char
+
+  (* control *)
+  | If | Then | Else
+  | For | In
+
+  (* operators *)
+  | Binary | Unary
+
+  (* var definition *)
+  | Var
+
+
+ +
lexer.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Lexer
+ *===----------------------------------------------------------------------===*)
+
+let rec lex = parser
+  (* Skip any whitespace. *)
+  | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
+
+  (* identifier: [a-zA-Z][a-zA-Z0-9] *)
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+
+  (* number: [0-9.]+ *)
+  | [< ' ('0' .. '9' as c); stream >] ->
+      let buffer = Buffer.create 1 in
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+
+  (* Comment until end of line. *)
+  | [< ' ('#'); stream >] ->
+      lex_comment stream
+
+  (* Otherwise, just return the character as its ascii value. *)
+  | [< 'c; stream >] ->
+      [< 'Token.Kwd c; lex stream >]
+
+  (* end of stream. *)
+  | [< >] -> [< >]
+
+and lex_number buffer = parser
+  | [< ' ('0' .. '9' | '.' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_number buffer stream
+  | [< stream=lex >] ->
+      [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
+
+and lex_ident buffer = parser
+  | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
+      Buffer.add_char buffer c;
+      lex_ident buffer stream
+  | [< stream=lex >] ->
+      match Buffer.contents buffer with
+      | "def" -> [< 'Token.Def; stream >]
+      | "extern" -> [< 'Token.Extern; stream >]
+      | "if" -> [< 'Token.If; stream >]
+      | "then" -> [< 'Token.Then; stream >]
+      | "else" -> [< 'Token.Else; stream >]
+      | "for" -> [< 'Token.For; stream >]
+      | "in" -> [< 'Token.In; stream >]
+      | "binary" -> [< 'Token.Binary; stream >]
+      | "unary" -> [< 'Token.Unary; stream >]
+      | "var" -> [< 'Token.Var; stream >]
+      | id -> [< 'Token.Ident id; stream >]
+
+and lex_comment = parser
+  | [< ' ('\n'); stream=lex >] -> stream
+  | [< 'c; e=lex_comment >] -> e
+  | [< >] -> [< >]
+
+
+ +
ast.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Abstract Syntax Tree (aka Parse Tree)
+ *===----------------------------------------------------------------------===*)
+
+(* expr - Base type for all expression nodes. *)
+type expr =
+  (* variant for numeric literals like "1.0". *)
+  | Number of float
+
+  (* variant for referencing a variable, like "a". *)
+  | Variable of string
+
+  (* variant for a unary operator. *)
+  | Unary of char * expr
+
+  (* variant for a binary operator. *)
+  | Binary of char * expr * expr
+
+  (* variant for function calls. *)
+  | Call of string * expr array
+
+  (* variant for if/then/else. *)
+  | If of expr * expr * expr
+
+  (* variant for for/in. *)
+  | For of string * expr * expr * expr option * expr
+
+  (* variant for var/in. *)
+  | Var of (string * expr option) array * expr
+
+(* proto - This type represents the "prototype" for a function, which captures
+ * its name, and its argument names (thus implicitly the number of arguments the
+ * function takes). *)
+type proto =
+  | Prototype of string * string array
+  | BinOpPrototype of string * string array * int
+
+(* func - This type represents a function definition itself. *)
+type func = Function of proto * expr
+
+
+ +
parser.ml:
+
+
+(*===---------------------------------------------------------------------===
+ * Parser
+ *===---------------------------------------------------------------------===*)
+
+(* binop_precedence - This holds the precedence for each binary operator that is
+ * defined *)
+let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
+
+(* precedence - Get the precedence of the pending binary operator token. *)
+let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
+
+(* primary
+ *   ::= identifier
+ *   ::= numberexpr
+ *   ::= parenexpr
+ *   ::= ifexpr
+ *   ::= forexpr
+ *   ::= varexpr *)
+let rec parse_primary = parser
+  (* numberexpr ::= number *)
+  | [< 'Token.Number n >] -> Ast.Number n
+
+  (* parenexpr ::= '(' expression ')' *)
+  | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
+
+  (* identifierexpr
+   *   ::= identifier
+   *   ::= identifier '(' argumentexpr ')' *)
+  | [< 'Token.Ident id; stream >] ->
+      let rec parse_args accumulator = parser
+        | [< e=parse_expr; stream >] ->
+            begin parser
+              | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
+              | [< >] -> e :: accumulator
+            end stream
+        | [< >] -> accumulator
+      in
+      let rec parse_ident id = parser
+        (* Call. *)
+        | [< 'Token.Kwd '(';
+             args=parse_args [];
+             'Token.Kwd ')' ?? "expected ')'">] ->
+            Ast.Call (id, Array.of_list (List.rev args))
+
+        (* Simple variable ref. *)
+        | [< >] -> Ast.Variable id
+      in
+      parse_ident id stream
+
+  (* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
+  | [< 'Token.If; c=parse_expr;
+       'Token.Then ?? "expected 'then'"; t=parse_expr;
+       'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
+      Ast.If (c, t, e)
+
+  (* forexpr
+        ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
+  | [< 'Token.For;
+       'Token.Ident id ?? "expected identifier after for";
+       'Token.Kwd '=' ?? "expected '=' after for";
+       stream >] ->
+      begin parser
+        | [<
+             start=parse_expr;
+             'Token.Kwd ',' ?? "expected ',' after for";
+             end_=parse_expr;
+             stream >] ->
+            let step =
+              begin parser
+              | [< 'Token.Kwd ','; step=parse_expr >] -> Some step
+              | [< >] -> None
+              end stream
+            in
+            begin parser
+            | [< 'Token.In; body=parse_expr >] ->
+                Ast.For (id, start, end_, step, body)
+            | [< >] ->
+                raise (Stream.Error "expected 'in' after for")
+            end stream
+        | [< >] ->
+            raise (Stream.Error "expected '=' after for")
+      end stream
+
+  (* varexpr
+   *   ::= 'var' identifier ('=' expression?
+   *             (',' identifier ('=' expression)?)* 'in' expression *)
+  | [< 'Token.Var;
+       (* At least one variable name is required. *)
+       'Token.Ident id ?? "expected identifier after var";
+       init=parse_var_init;
+       var_names=parse_var_names [(id, init)];
+       (* At this point, we have to have 'in'. *)
+       'Token.In ?? "expected 'in' keyword after 'var'";
+       body=parse_expr >] ->
+      Ast.Var (Array.of_list (List.rev var_names), body)
+
+  | [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
+
+(* unary
+ *   ::= primary
+ *   ::= '!' unary *)
+and parse_unary = parser
+  (* If this is a unary operator, read it. *)
+  | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
+      Ast.Unary (op, operand)
+
+  (* If the current token is not an operator, it must be a primary expr. *)
+  | [< stream >] -> parse_primary stream
+
+(* binoprhs
+ *   ::= ('+' primary)* *)
+and parse_bin_rhs expr_prec lhs stream =
+  match Stream.peek stream with
+  (* If this is a binop, find its precedence. *)
+  | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
+      let token_prec = precedence c in
+
+      (* If this is a binop that binds at least as tightly as the current binop,
+       * consume it, otherwise we are done. *)
+      if token_prec < expr_prec then lhs else begin
+        (* Eat the binop. *)
+        Stream.junk stream;
+
+        (* Parse the primary expression after the binary operator. *)
+        let rhs = parse_unary stream in
+
+        (* Okay, we know this is a binop. *)
+        let rhs =
+          match Stream.peek stream with
+          | Some (Token.Kwd c2) ->
+              (* If BinOp binds less tightly with rhs than the operator after
+               * rhs, let the pending operator take rhs as its lhs. *)
+              let next_prec = precedence c2 in
+              if token_prec < next_prec
+              then parse_bin_rhs (token_prec + 1) rhs stream
+              else rhs
+          | _ -> rhs
+        in
+
+        (* Merge lhs/rhs. *)
+        let lhs = Ast.Binary (c, lhs, rhs) in
+        parse_bin_rhs expr_prec lhs stream
+      end
+  | _ -> lhs
+
+and parse_var_init = parser
+  (* read in the optional initializer. *)
+  | [< 'Token.Kwd '='; e=parse_expr >] -> Some e
+  | [< >] -> None
+
+and parse_var_names accumulator = parser
+  | [< 'Token.Kwd ',';
+       'Token.Ident id ?? "expected identifier list after var";
+       init=parse_var_init;
+       e=parse_var_names ((id, init) :: accumulator) >] -> e
+  | [< >] -> accumulator
+
+(* expression
+ *   ::= primary binoprhs *)
+and parse_expr = parser
+  | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
+
+(* prototype
+ *   ::= id '(' id* ')'
+ *   ::= binary LETTER number? (id, id)
+ *   ::= unary LETTER number? (id) *)
+let parse_prototype =
+  let rec parse_args accumulator = parser
+    | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
+    | [< >] -> accumulator
+  in
+  let parse_operator = parser
+    | [< 'Token.Unary >] -> "unary", 1
+    | [< 'Token.Binary >] -> "binary", 2
+  in
+  let parse_binary_precedence = parser
+    | [< 'Token.Number n >] -> int_of_float n
+    | [< >] -> 30
+  in
+  parser
+  | [< 'Token.Ident id;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+       args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      (* success. *)
+      Ast.Prototype (id, Array.of_list (List.rev args))
+  | [< (prefix, kind)=parse_operator;
+       'Token.Kwd op ?? "expected an operator";
+       (* Read the precedence if present. *)
+       binary_precedence=parse_binary_precedence;
+       'Token.Kwd '(' ?? "expected '(' in prototype";
+        args=parse_args [];
+       'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
+      let name = prefix ^ (String.make 1 op) in
+      let args = Array.of_list (List.rev args) in
+
+      (* Verify right number of arguments for operator. *)
+      if Array.length args != kind
+      then raise (Stream.Error "invalid number of operands for operator")
+      else
+        if kind == 1 then
+          Ast.Prototype (name, args)
+        else
+          Ast.BinOpPrototype (name, args, binary_precedence)
+  | [< >] ->
+      raise (Stream.Error "expected function name in prototype")
+
+(* definition ::= 'def' prototype expression *)
+let parse_definition = parser
+  | [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
+      Ast.Function (p, e)
+
+(* toplevelexpr ::= expression *)
+let parse_toplevel = parser
+  | [< e=parse_expr >] ->
+      (* Make an anonymous proto. *)
+      Ast.Function (Ast.Prototype ("", [||]), e)
+
+(*  external ::= 'extern' prototype *)
+let parse_extern = parser
+  | [< 'Token.Extern; e=parse_prototype >] -> e
+
+
+ +
codegen.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Code Generation
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+
+exception Error of string
+
+let context = global_context ()
+let the_module = create_module context "my cool jit"
+let builder = builder context
+let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
+let double_type = double_type context
+
+(* Create an alloca instruction in the entry block of the function. This
+ * is used for mutable variables etc. *)
+let create_entry_block_alloca the_function var_name =
+  let builder = builder_at context (instr_begin (entry_block the_function)) in
+  build_alloca double_type var_name builder
+
+let rec codegen_expr = function
+  | Ast.Number n -> const_float double_type n
+  | Ast.Variable name ->
+      let v = try Hashtbl.find named_values name with
+        | Not_found -> raise (Error "unknown variable name")
+      in
+      (* Load the value. *)
+      build_load v name builder
+  | Ast.Unary (op, operand) ->
+      let operand = codegen_expr operand in
+      let callee = "unary" ^ (String.make 1 op) in
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown unary operator")
+      in
+      build_call callee [|operand|] "unop" builder
+  | Ast.Binary (op, lhs, rhs) ->
+      begin match op with
+      | '=' ->
+          (* Special case '=' because we don't want to emit the LHS as an
+           * expression. *)
+          let name =
+            match lhs with
+            | Ast.Variable name -> name
+            | _ -> raise (Error "destination of '=' must be a variable")
+          in
+
+          (* Codegen the rhs. *)
+          let val_ = codegen_expr rhs in
+
+          (* Lookup the name. *)
+          let variable = try Hashtbl.find named_values name with
+          | Not_found -> raise (Error "unknown variable name")
+          in
+          ignore(build_store val_ variable builder);
+          val_
+      | _ ->
+          let lhs_val = codegen_expr lhs in
+          let rhs_val = codegen_expr rhs in
+          begin
+            match op with
+            | '+' -> build_add lhs_val rhs_val "addtmp" builder
+            | '-' -> build_sub lhs_val rhs_val "subtmp" builder
+            | '*' -> build_mul lhs_val rhs_val "multmp" builder
+            | '<' ->
+                (* Convert bool 0/1 to double 0.0 or 1.0 *)
+                let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
+                build_uitofp i double_type "booltmp" builder
+            | _ ->
+                (* If it wasn't a builtin binary operator, it must be a user defined
+                 * one. Emit a call to it. *)
+                let callee = "binary" ^ (String.make 1 op) in
+                let callee =
+                  match lookup_function callee the_module with
+                  | Some callee -> callee
+                  | None -> raise (Error "binary operator not found!")
+                in
+                build_call callee [|lhs_val; rhs_val|] "binop" builder
+          end
+      end
+  | Ast.Call (callee, args) ->
+      (* Look up the name in the module table. *)
+      let callee =
+        match lookup_function callee the_module with
+        | Some callee -> callee
+        | None -> raise (Error "unknown function referenced")
+      in
+      let params = params callee in
+
+      (* If argument mismatch error. *)
+      if Array.length params == Array.length args then () else
+        raise (Error "incorrect # arguments passed");
+      let args = Array.map codegen_expr args in
+      build_call callee args "calltmp" builder
+  | Ast.If (cond, then_, else_) ->
+      let cond = codegen_expr cond in
+
+      (* Convert condition to a bool by comparing equal to 0.0 *)
+      let zero = const_float double_type 0.0 in
+      let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
+
+      (* Grab the first block so that we might later add the conditional branch
+       * to it at the end of the function. *)
+      let start_bb = insertion_block builder in
+      let the_function = block_parent start_bb in
+
+      let then_bb = append_block context "then" the_function in
+
+      (* Emit 'then' value. *)
+      position_at_end then_bb builder;
+      let then_val = codegen_expr then_ in
+
+      (* Codegen of 'then' can change the current block, update then_bb for the
+       * phi. We create a new name because one is used for the phi node, and the
+       * other is used for the conditional branch. *)
+      let new_then_bb = insertion_block builder in
+
+      (* Emit 'else' value. *)
+      let else_bb = append_block context "else" the_function in
+      position_at_end else_bb builder;
+      let else_val = codegen_expr else_ in
+
+      (* Codegen of 'else' can change the current block, update else_bb for the
+       * phi. *)
+      let new_else_bb = insertion_block builder in
+
+      (* Emit merge block. *)
+      let merge_bb = append_block context "ifcont" the_function in
+      position_at_end merge_bb builder;
+      let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
+      let phi = build_phi incoming "iftmp" builder in
+
+      (* Return to the start block to add the conditional branch. *)
+      position_at_end start_bb builder;
+      ignore (build_cond_br cond_val then_bb else_bb builder);
+
+      (* Set a unconditional branch at the end of the 'then' block and the
+       * 'else' block to the 'merge' block. *)
+      position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
+      position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
+
+      (* Finally, set the builder to the end of the merge block. *)
+      position_at_end merge_bb builder;
+
+      phi
+  | Ast.For (var_name, start, end_, step, body) ->
+      (* Output this as:
+       *   var = alloca double
+       *   ...
+       *   start = startexpr
+       *   store start -> var
+       *   goto loop
+       * loop:
+       *   ...
+       *   bodyexpr
+       *   ...
+       * loopend:
+       *   step = stepexpr
+       *   endcond = endexpr
+       *
+       *   curvar = load var
+       *   nextvar = curvar + step
+       *   store nextvar -> var
+       *   br endcond, loop, endloop
+       * outloop: *)
+
+      let the_function = block_parent (insertion_block builder) in
+
+      (* Create an alloca for the variable in the entry block. *)
+      let alloca = create_entry_block_alloca the_function var_name in
+
+      (* Emit the start code first, without 'variable' in scope. *)
+      let start_val = codegen_expr start in
+
+      (* Store the value into the alloca. *)
+      ignore(build_store start_val alloca builder);
+
+      (* Make the new basic block for the loop header, inserting after current
+       * block. *)
+      let loop_bb = append_block context "loop" the_function in
+
+      (* Insert an explicit fall through from the current block to the
+       * loop_bb. *)
+      ignore (build_br loop_bb builder);
+
+      (* Start insertion in loop_bb. *)
+      position_at_end loop_bb builder;
+
+      (* Within the loop, the variable is defined equal to the PHI node. If it
+       * shadows an existing variable, we have to restore it, so save it
+       * now. *)
+      let old_val =
+        try Some (Hashtbl.find named_values var_name) with Not_found -> None
+      in
+      Hashtbl.add named_values var_name alloca;
+
+      (* Emit the body of the loop.  This, like any other expr, can change the
+       * current BB.  Note that we ignore the value computed by the body, but
+       * don't allow an error *)
+      ignore (codegen_expr body);
+
+      (* Emit the step value. *)
+      let step_val =
+        match step with
+        | Some step -> codegen_expr step
+        (* If not specified, use 1.0. *)
+        | None -> const_float double_type 1.0
+      in
+
+      (* Compute the end condition. *)
+      let end_cond = codegen_expr end_ in
+
+      (* Reload, increment, and restore the alloca. This handles the case where
+       * the body of the loop mutates the variable. *)
+      let cur_var = build_load alloca var_name builder in
+      let next_var = build_add cur_var step_val "nextvar" builder in
+      ignore(build_store next_var alloca builder);
+
+      (* Convert condition to a bool by comparing equal to 0.0. *)
+      let zero = const_float double_type 0.0 in
+      let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
+
+      (* Create the "after loop" block and insert it. *)
+      let after_bb = append_block context "afterloop" the_function in
+
+      (* Insert the conditional branch into the end of loop_end_bb. *)
+      ignore (build_cond_br end_cond loop_bb after_bb builder);
+
+      (* Any new code will be inserted in after_bb. *)
+      position_at_end after_bb builder;
+
+      (* Restore the unshadowed variable. *)
+      begin match old_val with
+      | Some old_val -> Hashtbl.add named_values var_name old_val
+      | None -> ()
+      end;
+
+      (* for expr always returns 0.0. *)
+      const_null double_type
+  | Ast.Var (var_names, body) ->
+      let old_bindings = ref [] in
+
+      let the_function = block_parent (insertion_block builder) in
+
+      (* Register all variables and emit their initializer. *)
+      Array.iter (fun (var_name, init) ->
+        (* Emit the initializer before adding the variable to scope, this
+         * prevents the initializer from referencing the variable itself, and
+         * permits stuff like this:
+         *   var a = 1 in
+         *     var a = a in ...   # refers to outer 'a'. *)
+        let init_val =
+          match init with
+          | Some init -> codegen_expr init
+          (* If not specified, use 0.0. *)
+          | None -> const_float double_type 0.0
+        in
+
+        let alloca = create_entry_block_alloca the_function var_name in
+        ignore(build_store init_val alloca builder);
+
+        (* Remember the old variable binding so that we can restore the binding
+         * when we unrecurse. *)
+        begin
+          try
+            let old_value = Hashtbl.find named_values var_name in
+            old_bindings := (var_name, old_value) :: !old_bindings;
+          with Not_found -> ()
+        end;
+
+        (* Remember this binding. *)
+        Hashtbl.add named_values var_name alloca;
+      ) var_names;
+
+      (* Codegen the body, now that all vars are in scope. *)
+      let body_val = codegen_expr body in
+
+      (* Pop all our variables from scope. *)
+      List.iter (fun (var_name, old_value) ->
+        Hashtbl.add named_values var_name old_value
+      ) !old_bindings;
+
+      (* Return the body computation. *)
+      body_val
+
+let codegen_proto = function
+  | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
+      (* Make the function type: double(double,double) etc. *)
+      let doubles = Array.make (Array.length args) double_type in
+      let ft = function_type double_type doubles in
+      let f =
+        match lookup_function name the_module with
+        | None -> declare_function name ft the_module
+
+        (* If 'f' conflicted, there was already something named 'name'. If it
+         * has a body, don't allow redefinition or reextern. *)
+        | Some f ->
+            (* If 'f' already has a body, reject this. *)
+            if block_begin f <> At_end f then
+              raise (Error "redefinition of function");
+
+            (* If 'f' took a different number of arguments, reject. *)
+            if element_type (type_of f) <> ft then
+              raise (Error "redefinition of function with different # args");
+            f
+      in
+
+      (* Set names for all arguments. *)
+      Array.iteri (fun i a ->
+        let n = args.(i) in
+        set_value_name n a;
+        Hashtbl.add named_values n a;
+      ) (params f);
+      f
+
+(* Create an alloca for each argument and register the argument in the symbol
+ * table so that references to it will succeed. *)
+let create_argument_allocas the_function proto =
+  let args = match proto with
+    | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args
+  in
+  Array.iteri (fun i ai ->
+    let var_name = args.(i) in
+    (* Create an alloca for this variable. *)
+    let alloca = create_entry_block_alloca the_function var_name in
+
+    (* Store the initial value into the alloca. *)
+    ignore(build_store ai alloca builder);
+
+    (* Add arguments to variable symbol table. *)
+    Hashtbl.add named_values var_name alloca;
+  ) (params the_function)
+
+let codegen_func the_fpm = function
+  | Ast.Function (proto, body) ->
+      Hashtbl.clear named_values;
+      let the_function = codegen_proto proto in
+
+      (* If this is an operator, install it. *)
+      begin match proto with
+      | Ast.BinOpPrototype (name, args, prec) ->
+          let op = name.[String.length name - 1] in
+          Hashtbl.add Parser.binop_precedence op prec;
+      | _ -> ()
+      end;
+
+      (* Create a new basic block to start insertion into. *)
+      let bb = append_block context "entry" the_function in
+      position_at_end bb builder;
+
+      try
+        (* Add all arguments to the symbol table and create their allocas. *)
+        create_argument_allocas the_function proto;
+
+        let ret_val = codegen_expr body in
+
+        (* Finish off the function. *)
+        let _ = build_ret ret_val builder in
+
+        (* Validate the generated code, checking for consistency. *)
+        Llvm_analysis.assert_valid_function the_function;
+
+        (* Optimize the function. *)
+        let _ = PassManager.run_function the_function the_fpm in
+
+        the_function
+      with e ->
+        delete_function the_function;
+        raise e
+
+
+ +
toplevel.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Top-Level parsing and JIT Driver
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+
+(* top ::= definition | external | expression | ';' *)
+let rec main_loop the_fpm the_execution_engine stream =
+  match Stream.peek stream with
+  | None -> ()
+
+  (* ignore top-level semicolons. *)
+  | Some (Token.Kwd ';') ->
+      Stream.junk stream;
+      main_loop the_fpm the_execution_engine stream
+
+  | Some token ->
+      begin
+        try match token with
+        | Token.Def ->
+            let e = Parser.parse_definition stream in
+            print_endline "parsed a function definition.";
+            dump_value (Codegen.codegen_func the_fpm e);
+        | Token.Extern ->
+            let e = Parser.parse_extern stream in
+            print_endline "parsed an extern.";
+            dump_value (Codegen.codegen_proto e);
+        | _ ->
+            (* Evaluate a top-level expression into an anonymous function. *)
+            let e = Parser.parse_toplevel stream in
+            print_endline "parsed a top-level expr";
+            let the_function = Codegen.codegen_func the_fpm e in
+            dump_value the_function;
+
+            (* JIT the function, returning a function pointer. *)
+            let result = ExecutionEngine.run_function the_function [||]
+              the_execution_engine in
+
+            print_string "Evaluated to ";
+            print_float (GenericValue.as_float Codegen.double_type result);
+            print_newline ();
+        with Stream.Error s | Codegen.Error s ->
+          (* Skip token for error recovery. *)
+          Stream.junk stream;
+          print_endline s;
+      end;
+      print_string "ready> "; flush stdout;
+      main_loop the_fpm the_execution_engine stream
+
+
+ +
toy.ml:
+
+
+(*===----------------------------------------------------------------------===
+ * Main driver code.
+ *===----------------------------------------------------------------------===*)
+
+open Llvm
+open Llvm_executionengine
+open Llvm_target
+open Llvm_scalar_opts
+
+let main () =
+  ignore (initialize_native_target ());
+
+  (* Install standard binary operators.
+   * 1 is the lowest precedence. *)
+  Hashtbl.add Parser.binop_precedence '=' 2;
+  Hashtbl.add Parser.binop_precedence '<' 10;
+  Hashtbl.add Parser.binop_precedence '+' 20;
+  Hashtbl.add Parser.binop_precedence '-' 20;
+  Hashtbl.add Parser.binop_precedence '*' 40;    (* highest. *)
+
+  (* Prime the first token. *)
+  print_string "ready> "; flush stdout;
+  let stream = Lexer.lex (Stream.of_channel stdin) in
+
+  (* Create the JIT. *)
+  let the_execution_engine = ExecutionEngine.create Codegen.the_module in
+  let the_fpm = PassManager.create_function Codegen.the_module in
+
+  (* Set up the optimizer pipeline.  Start with registering info about how the
+   * target lays out data structures. *)
+  TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
+
+  (* Promote allocas to registers. *)
+  add_memory_to_register_promotion the_fpm;
+
+  (* Do simple "peephole" optimizations and bit-twiddling optzn. *)
+  add_instruction_combination the_fpm;
+
+  (* reassociate expressions. *)
+  add_reassociation the_fpm;
+
+  (* Eliminate Common SubExpressions. *)
+  add_gvn the_fpm;
+
+  (* Simplify the control flow graph (deleting unreachable blocks, etc). *)
+  add_cfg_simplification the_fpm;
+
+  ignore (PassManager.initialize the_fpm);
+
+  (* Run the main "interpreter loop" now. *)
+  Toplevel.main_loop the_fpm the_execution_engine stream;
+
+  (* Print out all the generated code. *)
+  dump_module Codegen.the_module
+;;
+
+main ()
+
+
+ +
bindings.c
+
+
+#include <stdio.h>
+
+/* putchard - putchar that takes a double and returns 0. */
+extern double putchard(double X) {
+  putchar((char)X);
+  return 0;
+}
+
+/* printd - printf that takes a double prints it as "%f\n", returning 0. */
+extern double printd(double X) {
+  printf("%f\n", X);
+  return 0;
+}
+
+
+
+ +Next: Conclusion and other useful LLVM tidbits +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Erick Tryzelaar
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/OCamlLangImpl8.html b/final/docs/tutorial/OCamlLangImpl8.html new file mode 100644 index 00000000000..64a62002c4c --- /dev/null +++ b/final/docs/tutorial/OCamlLangImpl8.html @@ -0,0 +1,365 @@ + + + + + Kaleidoscope: Conclusion and other useful LLVM tidbits + + + + + + + +
Kaleidoscope: Conclusion and other useful LLVM + tidbits
+ + + + +
+

Written by Chris Lattner

+
+ + + + + +
+ +

Welcome to the the final chapter of the "Implementing a +language with LLVM" tutorial. In the course of this tutorial, we have grown +our little Kaleidoscope language from being a useless toy, to being a +semi-interesting (but probably still useless) toy. :)

+ +

It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code.

+ +

Our little language supports a couple of interesting features: it supports +user defined binary and unary operators, it uses JIT compilation for immediate +evaluation, and it supports a few control flow constructs with SSA construction. +

+ +

Part of the idea of this tutorial was to show you how easy and fun it can be +to define, build, and play with languages. Building a compiler need not be a +scary or mystical process! Now that you've seen some of the basics, I strongly +encourage you to take the code and hack on it. For example, try adding:

+ +
    +
  • global variables - While global variables have questional value in +modern software engineering, they are often useful when putting together quick +little hacks like the Kaleidoscope compiler itself. Fortunately, our current +setup makes it very easy to add global variables: just have value lookup check +to see if an unresolved variable is in the global variable symbol table before +rejecting it. To create a new global variable, make an instance of the LLVM +GlobalVariable class.
  • + +
  • typed variables - Kaleidoscope currently only supports variables of +type double. This gives the language a very nice elegance, because only +supporting one type means that you never have to specify types. Different +languages have different ways of handling this. The easiest way is to require +the user to specify types for every variable definition, and record the type +of the variable in the symbol table along with its Value*.
  • + +
  • arrays, structs, vectors, etc - Once you add types, you can start +extending the type system in all sorts of interesting ways. Simple arrays are +very easy and are quite useful for many different applications. Adding them is +mostly an exercise in learning how the LLVM getelementptr instruction works: it +is so nifty/unconventional, it has its own FAQ! If you add support +for recursive types (e.g. linked lists), make sure to read the section in the LLVM +Programmer's Manual that describes how to construct them.
  • + +
  • standard runtime - Our current language allows the user to access +arbitrary external functions, and we use it for things like "printd" and +"putchard". As you extend the language to add higher-level constructs, often +these constructs make the most sense if they are lowered to calls into a +language-supplied runtime. For example, if you add hash tables to the language, +it would probably make sense to add the routines to a runtime, instead of +inlining them all the way.
  • + +
  • memory management - Currently we can only access the stack in +Kaleidoscope. It would also be useful to be able to allocate heap memory, +either with calls to the standard libc malloc/free interface or with a garbage +collector. If you would like to use garbage collection, note that LLVM fully +supports Accurate Garbage Collection +including algorithms that move objects and need to scan/update the stack.
  • + +
  • debugger support - LLVM supports generation of DWARF Debug info which is understood by +common debuggers like GDB. Adding support for debug info is fairly +straightforward. The best way to understand it is to compile some C/C++ code +with "llvm-gcc -g -O0" and taking a look at what it produces.
  • + +
  • exception handling support - LLVM supports generation of zero cost exceptions which interoperate +with code compiled in other languages. You could also generate code by +implicitly making every function return an error value and checking it. You +could also make explicit use of setjmp/longjmp. There are many different ways +to go here.
  • + +
  • object orientation, generics, database access, complex numbers, +geometric programming, ... - Really, there is +no end of crazy features that you can add to the language.
  • + +
  • unusual domains - We've been talking about applying LLVM to a domain +that many people are interested in: building a compiler for a specific language. +However, there are many other domains that can use compiler technology that are +not typically considered. For example, LLVM has been used to implement OpenGL +graphics acceleration, translate C++ code to ActionScript, and many other +cute and clever things. Maybe you will be the first to JIT compile a regular +expression interpreter into native code with LLVM?
  • + +
+ +

+Have fun - try doing something crazy and unusual. Building a language like +everyone else always has, is much less fun than trying something a little crazy +or off the wall and seeing how it turns out. If you get stuck or want to talk +about it, feel free to email the llvmdev mailing +list: it has lots of people who are interested in languages and are often +willing to help out. +

+ +

Before we end this tutorial, I want to talk about some "tips and tricks" for generating +LLVM IR. These are some of the more subtle things that may not be obvious, but +are very useful if you want to take advantage of LLVM's capabilities.

+ +
+ + + + + +
+ +

We have a couple common questions about code in the LLVM IR form - lets just +get these out of the way right now, shall we?

+ +
+ + + + + +
+ +

Kaleidoscope is an example of a "portable language": any program written in +Kaleidoscope will work the same way on any target that it runs on. Many other +languages have this property, e.g. lisp, java, haskell, javascript, python, etc +(note that while these languages are portable, not all their libraries are).

+ +

One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a Kaleidoscope-compiled +program and run it on any target that LLVM supports, even emitting C code and +compiling that on targets that LLVM doesn't support natively. You can trivially +tell that the Kaleidoscope compiler generates target-independent code because it +never queries for any target-specific information when generating code.

+ +

The fact that LLVM provides a compact, target-independent, representation for +code gets a lot of people excited. Unfortunately, these people are usually +thinking about C or a language from the C family when they are asking questions +about language portability. I say "unfortunately", because there is really no +way to make (fully general) C code portable, other than shipping the source code +around (and of course, C source code is not actually portable in general +either - ever port a really old application from 32- to 64-bits?).

+ +

The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the preprocessor +often destructively removes target-independence from the code when it processes +the input text:

+ +
+
+#ifdef __i386__
+  int X = 1;
+#else
+  int X = 42;
+#endif
+
+
+ +

While it is possible to engineer more and more complex solutions to problems +like this, it cannot be solved in full generality in a way that is better than shipping +the actual source code.

+ +

That said, there are interesting subsets of C that can be made portable. If +you are willing to fix primitive types to a fixed size (say int = 32-bits, +and long = 64-bits), don't care about ABI compatibility with existing binaries, +and are willing to give up some other minor features, you can have portable +code. This can make sense for specialized domains such as an +in-kernel language.

+ +
+ + + + + +
+ +

Many of the languages above are also "safe" languages: it is impossible for +a program written in Java to corrupt its address space and crash the process +(assuming the JVM has no bugs). +Safety is an interesting property that requires a combination of language +design, runtime support, and often operating system support.

+ +

It is certainly possible to implement a safe language in LLVM, but LLVM IR +does not itself guarantee safety. The LLVM IR allows unsafe pointer casts, +use after free bugs, buffer over-runs, and a variety of other problems. Safety +needs to be implemented as a layer on top of LLVM and, conveniently, several +groups have investigated this. Ask on the llvmdev mailing +list if you are interested in more details.

+ +
+ + + + + +
+ +

One thing about LLVM that turns off many people is that it does not solve all +the world's problems in one system (sorry 'world hunger', someone else will have +to solve you some other day). One specific complaint is that people perceive +LLVM as being incapable of performing high-level language-specific optimization: +LLVM "loses too much information".

+ +

Unfortunately, this is really not the place to give you a full and unified +version of "Chris Lattner's theory of compiler design". Instead, I'll make a +few observations:

+ +

First, you're right that LLVM does lose information. For example, as of this +writing, there is no way to distinguish in the LLVM IR whether an SSA-value came +from a C "int" or a C "long" on an ILP32 machine (other than debug info). Both +get compiled down to an 'i32' value and the information about what it came from +is lost. The more general issue here, is that the LLVM type system uses +"structural equivalence" instead of "name equivalence". Another place this +surprises people is if you have two types in a high-level language that have the +same structure (e.g. two different structs that have a single int field): these +types will compile down into a single LLVM type and it will be impossible to +tell what it came from.

+ +

Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition to +adding new features (LLVM did not always support exceptions or debug info), we +also extend the IR to capture important information for optimization (e.g. +whether an argument is sign or zero extended, information about pointers +aliasing, etc). Many of the enhancements are user-driven: people want LLVM to +include some specific feature, so they go ahead and extend it.

+ +

Third, it is possible and easy to add language-specific +optimizations, and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C family, +there is an optimization pass that "knows" about the standard C library +functions. If you call "exit(0)" in main(), it knows that it is safe to +optimize that into "return 0;" because C specifies what the 'exit' +function does.

+ +

In addition to simple library knowledge, it is possible to embed a variety of +other language-specific information into the LLVM IR. If you have a specific +need and run into a wall, please bring the topic up on the llvmdev list. At the +very worst, you can always treat LLVM as if it were a "dumb code generator" and +implement the high-level optimizations you desire in your front-end, on the +language-specific AST. +

+ +
+ + + + + +
+ +

There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of letting +everyone rediscover them, this section talks about some of these issues.

+ +
+ + + + + +
+ +

One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need to know +the size of some LLVM type or the offset of some field in an llvm structure. +For example, you might need to pass the size of a type into a function that +allocates memory.

+ +

Unfortunately, this can vary widely across targets: for example the width of +a pointer is trivially target-specific. However, there is a clever +way to use the getelementptr instruction that allows you to compute this +in a portable way.

+ +
+ + + + + +
+ +

Some languages want to explicitly manage their stack frames, often so that +they are garbage collected or to allow easy implementation of closures. There +are often better ways to implement these features than explicit stack frames, +but LLVM +does support them, if you want. It requires your front-end to convert the +code into Continuation +Passing Style and the use of tail calls (which LLVM also supports).

+ +
+ + +
+
+ Valid CSS! + Valid HTML 4.01! + + Chris Lattner
+ The LLVM Compiler Infrastructure
+ Last modified: $Date$ +
+ + diff --git a/final/docs/tutorial/index.html b/final/docs/tutorial/index.html new file mode 100644 index 00000000000..11dd5e2d732 --- /dev/null +++ b/final/docs/tutorial/index.html @@ -0,0 +1,48 @@ + + + + LLVM Tutorial: Table of Contents + + + + + + + + +
LLVM Tutorial: Table of Contents
+ +
    +
  1. Kaleidoscope: Implementing a Language with LLVM +
      +
    1. Tutorial Introduction and the Lexer
    2. +
    3. Implementing a Parser and AST
    4. +
    5. Implementing Code Generation to LLVM IR
    6. +
    7. Adding JIT and Optimizer Support
    8. +
    9. Extending the language: control flow
    10. +
    11. Extending the language: user-defined operators
    12. +
    13. Extending the language: mutable variables / SSA construction
    14. +
    15. Conclusion and other useful LLVM tidbits
    16. +
  2. +
  3. Kaleidoscope: Implementing a Language with LLVM in Objective Caml +
      +
    1. Tutorial Introduction and the Lexer
    2. +
    3. Implementing a Parser and AST
    4. +
    5. Implementing Code Generation to LLVM IR
    6. +
    7. Adding JIT and Optimizer Support
    8. +
    9. Extending the language: control flow
    10. +
    11. Extending the language: user-defined operators
    12. +
    13. Extending the language: mutable variables / SSA construction
    14. +
    15. Conclusion and other useful LLVM tidbits
    16. +
  4. +
  5. Advanced Topics +
      +
    1. Writing + an Optimization for LLVM
    2. +
  6. +
+ + + diff --git a/final/examples/BrainF/BrainF.cpp b/final/examples/BrainF/BrainF.cpp new file mode 100644 index 00000000000..8536915993e --- /dev/null +++ b/final/examples/BrainF/BrainF.cpp @@ -0,0 +1,468 @@ +//===-- BrainF.cpp - BrainF compiler example ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This class compiles the BrainF language into LLVM assembly. +// +// The BrainF language has 8 commands: +// Command Equivalent C Action +// ------- ------------ ------ +// , *h=getchar(); Read a character from stdin, 255 on EOF +// . putchar(*h); Write a character to stdout +// - --*h; Decrement tape +// + ++*h; Increment tape +// < --h; Move head left +// > ++h; Move head right +// [ while(*h) { Start loop +// ] } End loop +// +//===--------------------------------------------------------------------===// + +#include "BrainF.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +//Set the constants for naming +const char *BrainF::tapereg = "tape"; +const char *BrainF::headreg = "head"; +const char *BrainF::label = "brainf"; +const char *BrainF::testreg = "test"; + +Module *BrainF::parse(std::istream *in1, int mem, CompileFlags cf, + LLVMContext& Context) { + in = in1; + memtotal = mem; + comflag = cf; + + header(Context); + readloop(0, 0, 0, Context); + delete builder; + return module; +} + +void BrainF::header(LLVMContext& C) { + module = new Module("BrainF", C); + + //Function prototypes + + //declare void @llvm.memset.p0i8.i32(i8 *, i8, i32, i32, i1) + const Type *Tys[] = { Type::getInt8PtrTy(C), Type::getInt32Ty(C) }; + Function *memset_func = Intrinsic::getDeclaration(module, Intrinsic::memset, + Tys, 2); + + //declare i32 @getchar() + getchar_func = cast(module-> + getOrInsertFunction("getchar", IntegerType::getInt32Ty(C), NULL)); + + //declare i32 @putchar(i32) + putchar_func = cast(module-> + getOrInsertFunction("putchar", IntegerType::getInt32Ty(C), + IntegerType::getInt32Ty(C), NULL)); + + + //Function header + + //define void @brainf() + brainf_func = cast(module-> + getOrInsertFunction("brainf", Type::getVoidTy(C), NULL)); + + builder = new IRBuilder<>(BasicBlock::Create(C, label, brainf_func)); + + //%arr = malloc i8, i32 %d + ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal)); + BasicBlock* BB = builder->GetInsertBlock(); + const Type* IntPtrTy = IntegerType::getInt32Ty(C); + const Type* Int8Ty = IntegerType::getInt8Ty(C); + Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty); + allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy); + ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem, + NULL, "arr"); + BB->getInstList().push_back(cast(ptr_arr)); + + //call void @llvm.memset.p0i8.i32(i8 *%arr, i8 0, i32 %d, i32 1, i1 0) + { + Value *memset_params[] = { + ptr_arr, + ConstantInt::get(C, APInt(8, 0)), + val_mem, + ConstantInt::get(C, APInt(32, 1)), + ConstantInt::get(C, APInt(1, 0)) + }; + + CallInst *memset_call = builder-> + CreateCall(memset_func, memset_params, array_endof(memset_params)); + memset_call->setTailCall(false); + } + + //%arrmax = getelementptr i8 *%arr, i32 %d + if (comflag & flag_arraybounds) { + ptr_arrmax = builder-> + CreateGEP(ptr_arr, ConstantInt::get(C, APInt(32, memtotal)), "arrmax"); + } + + //%head.%d = getelementptr i8 *%arr, i32 %d + curhead = builder->CreateGEP(ptr_arr, + ConstantInt::get(C, APInt(32, memtotal/2)), + headreg); + + + + //Function footer + + //brainf.end: + endbb = BasicBlock::Create(C, label, brainf_func); + + //call free(i8 *%arr) + endbb->getInstList().push_back(CallInst::CreateFree(ptr_arr, endbb)); + + //ret void + ReturnInst::Create(C, endbb); + + + + //Error block for array out of bounds + if (comflag & flag_arraybounds) + { + //@aberrormsg = internal constant [%d x i8] c"\00" + Constant *msg_0 = + ConstantArray::get(C, "Error: The head has left the tape.", true); + + GlobalVariable *aberrormsg = new GlobalVariable( + *module, + msg_0->getType(), + true, + GlobalValue::InternalLinkage, + msg_0, + "aberrormsg"); + + //declare i32 @puts(i8 *) + Function *puts_func = cast(module-> + getOrInsertFunction("puts", IntegerType::getInt32Ty(C), + PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL)); + + //brainf.aberror: + aberrorbb = BasicBlock::Create(C, label, brainf_func); + + //call i32 @puts(i8 *getelementptr([%d x i8] *@aberrormsg, i32 0, i32 0)) + { + Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C)); + + Constant *gep_params[] = { + zero_32, + zero_32 + }; + + Constant *msgptr = ConstantExpr:: + getGetElementPtr(aberrormsg, gep_params, + array_lengthof(gep_params)); + + Value *puts_params[] = { + msgptr + }; + + CallInst *puts_call = + CallInst::Create(puts_func, + puts_params, array_endof(puts_params), + "", aberrorbb); + puts_call->setTailCall(false); + } + + //br label %brainf.end + BranchInst::Create(endbb, aberrorbb); + } +} + +void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, + LLVMContext &C) { + Symbol cursym = SYM_NONE; + int curvalue = 0; + Symbol nextsym = SYM_NONE; + int nextvalue = 0; + char c; + int loop; + int direction; + + while(cursym != SYM_EOF && cursym != SYM_ENDLOOP) { + // Write out commands + switch(cursym) { + case SYM_NONE: + // Do nothing + break; + + case SYM_READ: + { + //%tape.%d = call i32 @getchar() + CallInst *getchar_call = builder->CreateCall(getchar_func, tapereg); + getchar_call->setTailCall(false); + Value *tape_0 = getchar_call; + + //%tape.%d = trunc i32 %tape.%d to i8 + Value *tape_1 = builder-> + CreateTrunc(tape_0, IntegerType::getInt8Ty(C), tapereg); + + //store i8 %tape.%d, i8 *%head.%d + builder->CreateStore(tape_1, curhead); + } + break; + + case SYM_WRITE: + { + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); + + //%tape.%d = sext i8 %tape.%d to i32 + Value *tape_1 = builder-> + CreateSExt(tape_0, IntegerType::getInt32Ty(C), tapereg); + + //call i32 @putchar(i32 %tape.%d) + Value *putchar_params[] = { + tape_1 + }; + CallInst *putchar_call = builder-> + CreateCall(putchar_func, + putchar_params, array_endof(putchar_params)); + putchar_call->setTailCall(false); + } + break; + + case SYM_MOVE: + { + //%head.%d = getelementptr i8 *%head.%d, i32 %d + curhead = builder-> + CreateGEP(curhead, ConstantInt::get(C, APInt(32, curvalue)), + headreg); + + //Error block for array out of bounds + if (comflag & flag_arraybounds) + { + //%test.%d = icmp uge i8 *%head.%d, %arrmax + Value *test_0 = builder-> + CreateICmpUGE(curhead, ptr_arrmax, testreg); + + //%test.%d = icmp ult i8 *%head.%d, %arr + Value *test_1 = builder-> + CreateICmpULT(curhead, ptr_arr, testreg); + + //%test.%d = or i1 %test.%d, %test.%d + Value *test_2 = builder-> + CreateOr(test_0, test_1, testreg); + + //br i1 %test.%d, label %main.%d, label %main.%d + BasicBlock *nextbb = BasicBlock::Create(C, label, brainf_func); + builder->CreateCondBr(test_2, aberrorbb, nextbb); + + //main.%d: + builder->SetInsertPoint(nextbb); + } + } + break; + + case SYM_CHANGE: + { + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = builder->CreateLoad(curhead, tapereg); + + //%tape.%d = add i8 %tape.%d, %d + Value *tape_1 = builder-> + CreateAdd(tape_0, ConstantInt::get(C, APInt(8, curvalue)), tapereg); + + //store i8 %tape.%d, i8 *%head.%d\n" + builder->CreateStore(tape_1, curhead); + } + break; + + case SYM_LOOP: + { + //br label %main.%d + BasicBlock *testbb = BasicBlock::Create(C, label, brainf_func); + builder->CreateBr(testbb); + + //main.%d: + BasicBlock *bb_0 = builder->GetInsertBlock(); + BasicBlock *bb_1 = BasicBlock::Create(C, label, brainf_func); + builder->SetInsertPoint(bb_1); + + // Make part of PHI instruction now, wait until end of loop to finish + PHINode *phi_0 = + PHINode::Create(PointerType::getUnqual(IntegerType::getInt8Ty(C)), + headreg, testbb); + phi_0->reserveOperandSpace(2); + phi_0->addIncoming(curhead, bb_0); + curhead = phi_0; + + readloop(phi_0, bb_1, testbb, C); + } + break; + + default: + std::cerr << "Error: Unknown symbol.\n"; + abort(); + break; + } + + cursym = nextsym; + curvalue = nextvalue; + nextsym = SYM_NONE; + + // Reading stdin loop + loop = (cursym == SYM_NONE) + || (cursym == SYM_MOVE) + || (cursym == SYM_CHANGE); + while(loop) { + *in>>c; + if (in->eof()) { + if (cursym == SYM_NONE) { + cursym = SYM_EOF; + } else { + nextsym = SYM_EOF; + } + loop = 0; + } else { + direction = 1; + switch(c) { + case '-': + direction = -1; + // Fall through + + case '+': + if (cursym == SYM_CHANGE) { + curvalue += direction; + // loop = 1 + } else { + if (cursym == SYM_NONE) { + cursym = SYM_CHANGE; + curvalue = direction; + // loop = 1 + } else { + nextsym = SYM_CHANGE; + nextvalue = direction; + loop = 0; + } + } + break; + + case '<': + direction = -1; + // Fall through + + case '>': + if (cursym == SYM_MOVE) { + curvalue += direction; + // loop = 1 + } else { + if (cursym == SYM_NONE) { + cursym = SYM_MOVE; + curvalue = direction; + // loop = 1 + } else { + nextsym = SYM_MOVE; + nextvalue = direction; + loop = 0; + } + } + break; + + case ',': + if (cursym == SYM_NONE) { + cursym = SYM_READ; + } else { + nextsym = SYM_READ; + } + loop = 0; + break; + + case '.': + if (cursym == SYM_NONE) { + cursym = SYM_WRITE; + } else { + nextsym = SYM_WRITE; + } + loop = 0; + break; + + case '[': + if (cursym == SYM_NONE) { + cursym = SYM_LOOP; + } else { + nextsym = SYM_LOOP; + } + loop = 0; + break; + + case ']': + if (cursym == SYM_NONE) { + cursym = SYM_ENDLOOP; + } else { + nextsym = SYM_ENDLOOP; + } + loop = 0; + break; + + // Ignore other characters + default: + break; + } + } + } + } + + if (cursym == SYM_ENDLOOP) { + if (!phi) { + std::cerr << "Error: Extra ']'\n"; + abort(); + } + + // Write loop test + { + //br label %main.%d + builder->CreateBr(testbb); + + //main.%d: + + //%head.%d = phi i8 *[%head.%d, %main.%d], [%head.%d, %main.%d] + //Finish phi made at beginning of loop + phi->addIncoming(curhead, builder->GetInsertBlock()); + Value *head_0 = phi; + + //%tape.%d = load i8 *%head.%d + LoadInst *tape_0 = new LoadInst(head_0, tapereg, testbb); + + //%test.%d = icmp eq i8 %tape.%d, 0 + ICmpInst *test_0 = new ICmpInst(*testbb, ICmpInst::ICMP_EQ, tape_0, + ConstantInt::get(C, APInt(8, 0)), testreg); + + //br i1 %test.%d, label %main.%d, label %main.%d + BasicBlock *bb_0 = BasicBlock::Create(C, label, brainf_func); + BranchInst::Create(bb_0, oldbb, test_0, testbb); + + //main.%d: + builder->SetInsertPoint(bb_0); + + //%head.%d = phi i8 *[%head.%d, %main.%d] + PHINode *phi_1 = builder-> + CreatePHI(PointerType::getUnqual(IntegerType::getInt8Ty(C)), headreg); + phi_1->reserveOperandSpace(1); + phi_1->addIncoming(head_0, testbb); + curhead = phi_1; + } + + return; + } + + //End of the program, so go to return block + builder->CreateBr(endbb); + + if (phi) { + std::cerr << "Error: Missing ']'\n"; + abort(); + } +} diff --git a/final/examples/BrainF/BrainF.h b/final/examples/BrainF/BrainF.h new file mode 100644 index 00000000000..add0687d54a --- /dev/null +++ b/final/examples/BrainF/BrainF.h @@ -0,0 +1,94 @@ +//===-- BrainF.h - BrainF compiler class ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This class stores the data for the BrainF compiler so it doesn't have +// to pass all of it around. The main method is parse. +// +//===--------------------------------------------------------------------===// + +#ifndef BRAINF_H +#define BRAINF_H + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" + +using namespace llvm; + +/// This class provides a parser for the BrainF language. +/// The class itself is made to store values during +/// parsing so they don't have to be passed around +/// as much. +class BrainF { + public: + /// Options for how BrainF should compile + enum CompileFlags { + flag_off = 0, + flag_arraybounds = 1 + }; + + /// This is the main method. It parses BrainF from in1 + /// and returns the module with a function + /// void brainf() + /// containing the resulting code. + /// On error, it calls abort. + /// The caller must delete the returned module. + Module *parse(std::istream *in1, int mem, CompileFlags cf, + LLVMContext& C); + + protected: + /// The different symbols in the BrainF language + enum Symbol { + SYM_NONE, + SYM_READ, + SYM_WRITE, + SYM_MOVE, + SYM_CHANGE, + SYM_LOOP, + SYM_ENDLOOP, + SYM_EOF + }; + + /// Names of the different parts of the language. + /// Tape is used for reading and writing the tape. + /// headreg is used for the position of the head. + /// label is used for the labels for the BasicBlocks. + /// testreg is used for testing the loop exit condition. + static const char *tapereg; + static const char *headreg; + static const char *label; + static const char *testreg; + + /// Put the brainf function preamble and other fixed pieces of code + void header(LLVMContext& C); + + /// The main loop for parsing. It calls itself recursively + /// to handle the depth of nesting of "[]". + void readloop(PHINode *phi, BasicBlock *oldbb, + BasicBlock *testbb, LLVMContext &Context); + + /// Constants during parsing + int memtotal; + CompileFlags comflag; + std::istream *in; + Module *module; + Function *brainf_func; + Function *getchar_func; + Function *putchar_func; + Value *ptr_arr; + Value *ptr_arrmax; + BasicBlock *endbb; + BasicBlock *aberrorbb; + + /// Variables + IRBuilder<> *builder; + Value *curhead; +}; + +#endif diff --git a/final/examples/BrainF/BrainFDriver.cpp b/final/examples/BrainF/BrainFDriver.cpp new file mode 100644 index 00000000000..c11a58067e8 --- /dev/null +++ b/final/examples/BrainF/BrainFDriver.cpp @@ -0,0 +1,160 @@ +//===-- BrainFDriver.cpp - BrainF compiler driver -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// This program converts the BrainF language into LLVM assembly, +// which it can then run using the JIT or output as BitCode. +// +// This implementation has a tape of 65536 bytes, +// with the head starting in the middle. +// Range checking is off by default, so be careful. +// It can be enabled with -abc. +// +// Use: +// ./BrainF -jit prog.bf #Run program now +// ./BrainF -jit -abc prog.bf #Run program now safely +// ./BrainF prog.bf #Write as BitCode +// +// lli prog.bf.bc #Run generated BitCode +// llvm-ld -native -o=prog prog.bf.bc #Compile BitCode into native executable +// +//===--------------------------------------------------------------------===// + +#include "BrainF.h" +#include "llvm/Constants.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; + +//Command line options + +static cl::opt +InputFilename(cl::Positional, cl::desc("")); + +static cl::opt +OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); + +static cl::opt +ArrayBoundsChecking("abc", cl::desc("Enable array bounds checking")); + +static cl::opt +JIT("jit", cl::desc("Run program Just-In-Time")); + + +//Add main function so can be fully compiled +void addMainFunction(Module *mod) { + //define i32 @main(i32 %argc, i8 **%argv) + Function *main_func = cast(mod-> + getOrInsertFunction("main", IntegerType::getInt32Ty(mod->getContext()), + IntegerType::getInt32Ty(mod->getContext()), + PointerType::getUnqual(PointerType::getUnqual( + IntegerType::getInt8Ty(mod->getContext()))), NULL)); + { + Function::arg_iterator args = main_func->arg_begin(); + Value *arg_0 = args++; + arg_0->setName("argc"); + Value *arg_1 = args++; + arg_1->setName("argv"); + } + + //main.0: + BasicBlock *bb = BasicBlock::Create(mod->getContext(), "main.0", main_func); + + //call void @brainf() + { + CallInst *brainf_call = CallInst::Create(mod->getFunction("brainf"), + "", bb); + brainf_call->setTailCall(false); + } + + //ret i32 0 + ReturnInst::Create(mod->getContext(), + ConstantInt::get(mod->getContext(), APInt(32, 0)), bb); +} + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " BrainF compiler\n"); + + LLVMContext &Context = getGlobalContext(); + + if (InputFilename == "") { + errs() << "Error: You must specify the filename of the program to " + "be compiled. Use --help to see the options.\n"; + abort(); + } + + //Get the output stream + raw_ostream *out = &outs(); + if (!JIT) { + if (OutputFilename == "") { + std::string base = InputFilename; + if (InputFilename == "-") { base = "a"; } + + // Use default filename. + OutputFilename = base+".bc"; + } + if (OutputFilename != "-") { + std::string ErrInfo; + out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo, + raw_fd_ostream::F_Binary); + } + } + + //Get the input stream + std::istream *in = &std::cin; + if (InputFilename != "-") + in = new std::ifstream(InputFilename.c_str()); + + //Gather the compile flags + BrainF::CompileFlags cf = BrainF::flag_off; + if (ArrayBoundsChecking) + cf = BrainF::CompileFlags(cf | BrainF::flag_arraybounds); + + //Read the BrainF program + BrainF bf; + Module *mod = bf.parse(in, 65536, cf, Context); //64 KiB + if (in != &std::cin) + delete in; + addMainFunction(mod); + + //Verify generated code + if (verifyModule(*mod)) { + errs() << "Error: module failed verification. This shouldn't happen.\n"; + abort(); + } + + //Write it out + if (JIT) { + InitializeNativeTarget(); + + outs() << "------- Running JIT -------\n"; + ExecutionEngine *ee = EngineBuilder(mod).create(); + std::vector args; + Function *brainf_func = mod->getFunction("brainf"); + GenericValue gv = ee->runFunction(brainf_func, args); + } else { + WriteBitcodeToFile(mod, *out); + } + + //Clean up + if (out != &outs()) + delete out; + delete mod; + + llvm_shutdown(); + + return 0; +} diff --git a/final/examples/BrainF/CMakeLists.txt b/final/examples/BrainF/CMakeLists.txt new file mode 100644 index 00000000000..7bec105cdc8 --- /dev/null +++ b/final/examples/BrainF/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS jit bitwriter nativecodegen interpreter) + +add_llvm_example(BrainF + BrainF.cpp + BrainFDriver.cpp + ) diff --git a/final/examples/BrainF/Makefile b/final/examples/BrainF/Makefile new file mode 100644 index 00000000000..2c3e0662523 --- /dev/null +++ b/final/examples/BrainF/Makefile @@ -0,0 +1,15 @@ +##===- examples/BrainF/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 = BrainF +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := jit bitwriter nativecodegen interpreter + +include $(LEVEL)/Makefile.common diff --git a/final/examples/CMakeLists.txt b/final/examples/CMakeLists.txt new file mode 100644 index 00000000000..54ee6cc3a3a --- /dev/null +++ b/final/examples/CMakeLists.txt @@ -0,0 +1,13 @@ +add_subdirectory(BrainF) +add_subdirectory(Fibonacci) +add_subdirectory(HowToUseJIT) +add_subdirectory(Kaleidoscope) +add_subdirectory(ModuleMaker) + +if( NOT WIN32 ) + add_subdirectory(ExceptionDemo) +endif() + +if( HAVE_PTHREAD_H ) + add_subdirectory(ParallelJIT) +endif( HAVE_PTHREAD_H ) diff --git a/final/examples/ExceptionDemo/CMakeLists.txt b/final/examples/ExceptionDemo/CMakeLists.txt new file mode 100644 index 00000000000..88c9ab7c181 --- /dev/null +++ b/final/examples/ExceptionDemo/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS jit nativecodegen) +set(LLVM_REQUIRES_EH 1) + +add_llvm_example(ExceptionDemo + ExceptionDemo.cpp + ) diff --git a/final/examples/ExceptionDemo/ExceptionDemo.cpp b/final/examples/ExceptionDemo/ExceptionDemo.cpp new file mode 100644 index 00000000000..95ccd24a689 --- /dev/null +++ b/final/examples/ExceptionDemo/ExceptionDemo.cpp @@ -0,0 +1,2030 @@ +//===-- examples/ExceptionDemo/ExceptionDemo.cpp - +// An example use of the llvm Exception mechanism --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +// Demo program which implements an example LLVM exception implementation, and +// shows several test cases including the handling of foreign exceptions. +// It is run with type info types arguments to throw. A test will +// be run for each given type info type. While type info types with the value +// of -1 will trigger a foreign C++ exception to be thrown; type info types +// <= 6 and >= 1 will cause the associated generated exceptions to be thrown +// and caught by generated test functions; and type info types > 6 +// will result in exceptions which pass through to the test harness. All other +// type info types are not supported and could cause a crash. In all cases, +// the "finally" blocks of every generated test functions will executed +// regardless of whether or not that test function ignores or catches the +// thrown exception. +// +// examples: +// +// ExceptionDemo +// +// causes a usage to be printed to stderr +// +// ExceptionDemo 2 3 7 -1 +// +// results in the following cases: +// - Value 2 causes an exception with a type info type of 2 to be +// thrown and caught by an inner generated test function. +// - Value 3 causes an exception with a type info type of 3 to be +// thrown and caught by an outer generated test function. +// - Value 7 causes an exception with a type info type of 7 to be +// thrown and NOT be caught by any generated function. +// - Value -1 causes a foreign C++ exception to be thrown and not be +// caught by any generated function +// +// Cases -1 and 7 are caught by a C++ test harness where the validity of +// of a C++ catch(...) clause catching a generated exception with a +// type info type of 7 is questionable. +// +// This code uses code from the llvm compiler-rt project and the llvm +// Kaleidoscope project. +// +//===--------------------------------------------------------------------===// + + +#include "llvm/LLVMContext.h" +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Intrinsics.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/Dwarf.h" + +#include +#include +#include +#include +#include +#include + + +#ifndef USE_GLOBAL_STR_CONSTS +#define USE_GLOBAL_STR_CONSTS true +#endif + +// System C++ ABI unwind types from: +// http://refspecs.freestandards.org/abi-eh-1.21.html + +extern "C" { + +typedef enum { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + +typedef enum { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + _UA_END_OF_STACK = 16 +} _Unwind_Action; + +struct _Unwind_Exception; + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +struct _Unwind_Exception { + uint64_t exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + + uintptr_t private_1; + uintptr_t private_2; + + // @@@ The IA-64 ABI says that this structure must be double-word aligned. + // Taking that literally does not make much sense generically. Instead + // we provide the maximum alignment required by any type for the machine. +} __attribute__((__aligned__)); + +struct _Unwind_Context; +typedef struct _Unwind_Context* _Unwind_Context_t; + +extern const uint8_t* _Unwind_GetLanguageSpecificData (_Unwind_Context_t c); +extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i); +extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n); +extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value); +extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context); +extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context); + +} // extern "C" + +// +// Example types +// + +/// This is our simplistic type info +struct OurExceptionType_t { + /// type info type + int type; +}; + + +/// This is our Exception class which relies on a negative offset to calculate +/// pointers to its instances from pointers to its unwindException member. +/// +/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned +/// on a double word boundary. This is necessary to match the standard: +/// http://refspecs.freestandards.org/abi-eh-1.21.html +struct OurBaseException_t { + struct OurExceptionType_t type; + + // Note: This is properly aligned in unwind.h + struct _Unwind_Exception unwindException; +}; + + +// Note: Not needed since we are C++ +typedef struct OurBaseException_t OurException; +typedef struct _Unwind_Exception OurUnwindException; + +// +// Various globals used to support typeinfo and generatted exceptions in +// general +// + +static std::map namedValues; + +int64_t ourBaseFromUnwindOffset; + +const unsigned char ourBaseExcpClassChars[] = + {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'}; + + +static uint64_t ourBaseExceptionClass = 0; + +static std::vector ourTypeInfoNames; +static std::map ourTypeInfoNamesIndex; + +static llvm::StructType* ourTypeInfoType; +static llvm::StructType* ourExceptionType; +static llvm::StructType* ourUnwindExceptionType; + +static llvm::ConstantInt* ourExceptionNotThrownState; +static llvm::ConstantInt* ourExceptionThrownState; +static llvm::ConstantInt* ourExceptionCaughtState; + +typedef std::vector ArgNames; +typedef std::vector ArgTypes; + +// +// Code Generation Utilities +// + +/// Utility used to create a function, both declarations and definitions +/// @param module for module instance +/// @param retType function return type +/// @param theArgTypes function's ordered argument types +/// @param theArgNames function's ordered arguments needed if use of this +/// function corresponds to a function definition. Use empty +/// aggregate for function declarations. +/// @param functName function name +/// @param linkage function linkage +/// @param declarationOnly for function declarations +/// @param isVarArg function uses vararg arguments +/// @returns function instance +llvm::Function *createFunction(llvm::Module& module, + const llvm::Type* retType, + const ArgTypes& theArgTypes, + const ArgNames& theArgNames, + const std::string& functName, + llvm::GlobalValue::LinkageTypes linkage, + bool declarationOnly, + bool isVarArg) { + llvm::FunctionType* functType = llvm::FunctionType::get(retType, + theArgTypes, + isVarArg); + llvm::Function* ret = llvm::Function::Create(functType, + linkage, + functName, + &module); + if (!ret || declarationOnly) + return(ret); + + namedValues.clear(); + unsigned i = 0; + for (llvm::Function::arg_iterator argIndex = ret->arg_begin(); + i != theArgNames.size(); + ++argIndex, ++i) { + + argIndex->setName(theArgNames[i]); + namedValues[theArgNames[i]] = argIndex; + } + + return(ret); +} + + +/// Create an alloca instruction in the entry block of +/// the parent function. This is used for mutable variables etc. +/// @param function parent instance +/// @param varName stack variable name +/// @param type stack variable type +/// @param initWith optional constant initialization value +/// @returns AllocaInst instance +static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function& function, + const std::string &varName, + const llvm::Type* type, + llvm::Constant* initWith = NULL) { + llvm::BasicBlock& block = function.getEntryBlock(); + llvm::IRBuilder<> tmp(&block, block.begin()); + llvm::AllocaInst* ret = tmp.CreateAlloca(type, 0, varName.c_str()); + + if (initWith) + tmp.CreateStore(initWith, ret); + + return(ret); +} + + +// +// Code Generation Utilities End +// + +// +// Runtime C Library functions +// + +// Note: using an extern "C" block so that static functions can be used +extern "C" { + +// Note: Better ways to decide on bit width +// +/// Prints a 32 bit number, according to the format, to stderr. +/// @param intToPrint integer to print +/// @param format printf like format to use when printing +void print32Int(int intToPrint, const char* format) { + if (format) { + // Note: No NULL check + fprintf(stderr, format, intToPrint); + } + else { + // Note: No NULL check + fprintf(stderr, "::print32Int(...):NULL arg.\n"); + } +} + + +// Note: Better ways to decide on bit width +// +/// Prints a 64 bit number, according to the format, to stderr. +/// @param intToPrint integer to print +/// @param format printf like format to use when printing +void print64Int(long int intToPrint, const char* format) { + if (format) { + // Note: No NULL check + fprintf(stderr, format, intToPrint); + } + else { + // Note: No NULL check + fprintf(stderr, "::print64Int(...):NULL arg.\n"); + } +} + + +/// Prints a C string to stderr +/// @param toPrint string to print +void printStr(char* toPrint) { + if (toPrint) { + fprintf(stderr, "%s", toPrint); + } + else { + fprintf(stderr, "::printStr(...):NULL arg.\n"); + } +} + + +/// Deletes the true previosly allocated exception whose address +/// is calculated from the supplied OurBaseException_t::unwindException +/// member address. Handles (ignores), NULL pointers. +/// @param expToDelete exception to delete +void deleteOurException(OurUnwindException* expToDelete) { +#ifdef DEBUG + fprintf(stderr, + "deleteOurException(...).\n"); +#endif + + if (expToDelete && + (expToDelete->exception_class == ourBaseExceptionClass)) { + + free(((char*) expToDelete) + ourBaseFromUnwindOffset); + } +} + + +/// This function is the struct _Unwind_Exception API mandated delete function +/// used by foreign exception handlers when deleting our exception +/// (OurException), instances. +/// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html +/// @unlink +/// @param expToDelete exception instance to delete +void deleteFromUnwindOurException(_Unwind_Reason_Code reason, + OurUnwindException* expToDelete) { +#ifdef DEBUG + fprintf(stderr, + "deleteFromUnwindOurException(...).\n"); +#endif + + deleteOurException(expToDelete); +} + + +/// Creates (allocates on the heap), an exception (OurException instance), +/// of the supplied type info type. +/// @param type type info type +OurUnwindException* createOurException(int type) { + size_t size = sizeof(OurException); + OurException* ret = (OurException*) memset(malloc(size), 0, size); + (ret->type).type = type; + (ret->unwindException).exception_class = ourBaseExceptionClass; + (ret->unwindException).exception_cleanup = deleteFromUnwindOurException; + + return(&(ret->unwindException)); +} + + +/// Read a uleb128 encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @returns decoded value +static uintptr_t readULEB128(const uint8_t** data) { + uintptr_t result = 0; + uintptr_t shift = 0; + unsigned char byte; + const uint8_t* p = *data; + + do { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *data = p; + + return result; +} + + +/// Read a sleb128 encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @returns decoded value +static uintptr_t readSLEB128(const uint8_t** data) { + uintptr_t result = 0; + uintptr_t shift = 0; + unsigned char byte; + const uint8_t* p = *data; + + do { + byte = *p++; + result |= (byte & 0x7f) << shift; + shift += 7; + } + while (byte & 0x80); + + *data = p; + + if ((byte & 0x40) && (shift < (sizeof(result) << 3))) { + result |= (~0 << shift); + } + + return result; +} + + +/// Read a pointer encoded value and advance pointer +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// @param data reference variable holding memory pointer to decode from +/// @param encoding dwarf encoding type +/// @returns decoded value +static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) { + uintptr_t result = 0; + const uint8_t* p = *data; + + if (encoding == llvm::dwarf::DW_EH_PE_omit) + return(result); + + // first get value + switch (encoding & 0x0F) { + case llvm::dwarf::DW_EH_PE_absptr: + result = *((uintptr_t*)p); + p += sizeof(uintptr_t); + break; + case llvm::dwarf::DW_EH_PE_uleb128: + result = readULEB128(&p); + break; + // Note: This case has not been tested + case llvm::dwarf::DW_EH_PE_sleb128: + result = readSLEB128(&p); + break; + case llvm::dwarf::DW_EH_PE_udata2: + result = *((uint16_t*)p); + p += sizeof(uint16_t); + break; + case llvm::dwarf::DW_EH_PE_udata4: + result = *((uint32_t*)p); + p += sizeof(uint32_t); + break; + case llvm::dwarf::DW_EH_PE_udata8: + result = *((uint64_t*)p); + p += sizeof(uint64_t); + break; + case llvm::dwarf::DW_EH_PE_sdata2: + result = *((int16_t*)p); + p += sizeof(int16_t); + break; + case llvm::dwarf::DW_EH_PE_sdata4: + result = *((int32_t*)p); + p += sizeof(int32_t); + break; + case llvm::dwarf::DW_EH_PE_sdata8: + result = *((int64_t*)p); + p += sizeof(int64_t); + break; + default: + // not supported + abort(); + break; + } + + // then add relative offset + switch (encoding & 0x70) { + case llvm::dwarf::DW_EH_PE_absptr: + // do nothing + break; + case llvm::dwarf::DW_EH_PE_pcrel: + result += (uintptr_t)(*data); + break; + case llvm::dwarf::DW_EH_PE_textrel: + case llvm::dwarf::DW_EH_PE_datarel: + case llvm::dwarf::DW_EH_PE_funcrel: + case llvm::dwarf::DW_EH_PE_aligned: + default: + // not supported + abort(); + break; + } + + // then apply indirection + if (encoding & llvm::dwarf::DW_EH_PE_indirect) { + result = *((uintptr_t*)result); + } + + *data = p; + + return result; +} + + +/// Deals with Dwarf actions matching our type infos +/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted +/// action matches the supplied exception type. If such a match succeeds, +/// the resultAction argument will be set with > 0 index value. Only +/// corresponding llvm.eh.selector type info arguments, cleanup arguments +/// are supported. Filters are not supported. +/// See Variable Length Data in: +/// @link http://dwarfstd.org/Dwarf3.pdf @unlink +/// Also see @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink +/// @param resultAction reference variable which will be set with result +/// @param classInfo our array of type info pointers (to globals) +/// @param actionEntry index into above type info array or 0 (clean up). +/// We do not support filters. +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @returns whether or not a type info was found. False is returned if only +/// a cleanup was found +static bool handleActionValue(int64_t *resultAction, + struct OurExceptionType_t **classInfo, + uintptr_t actionEntry, + uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject) { + bool ret = false; + + if (!resultAction || + !exceptionObject || + (exceptionClass != ourBaseExceptionClass)) + return(ret); + + struct OurBaseException_t* excp = (struct OurBaseException_t*) + (((char*) exceptionObject) + ourBaseFromUnwindOffset); + struct OurExceptionType_t *excpType = &(excp->type); + int type = excpType->type; + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...): exceptionObject = <%p>, " + "excp = <%p>.\n", + exceptionObject, + excp); +#endif + + const uint8_t *actionPos = (uint8_t*) actionEntry, + *tempActionPos; + int64_t typeOffset = 0, + actionOffset; + + for (int i = 0; true; ++i) { + // Each emitted dwarf action corresponds to a 2 tuple of + // type info address offset, and action offset to the next + // emitted action. + typeOffset = readSLEB128(&actionPos); + tempActionPos = actionPos; + actionOffset = readSLEB128(&tempActionPos); + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):typeOffset: <%lld>, " + "actionOffset: <%lld>.\n", + typeOffset, + actionOffset); +#endif + assert((typeOffset >= 0) && + "handleActionValue(...):filters are not supported."); + + // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector + // argument has been matched. + if ((typeOffset > 0) && + (type == (classInfo[-typeOffset])->type)) { +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):actionValue <%d> found.\n", + i); +#endif + *resultAction = i + 1; + ret = true; + break; + } + +#ifdef DEBUG + fprintf(stderr, + "handleActionValue(...):actionValue not found.\n"); +#endif + if (!actionOffset) + break; + + actionPos += actionOffset; + } + + return(ret); +} + + +/// Deals with the Language specific data portion of the emitted dwarf code. +/// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink +/// @param version unsupported (ignored), unwind version +/// @param lsda language specific data area +/// @param _Unwind_Action actions minimally supported unwind stage +/// (forced specifically not supported) +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @param context unwind system context +/// @returns minimally supported unwinding control indicator +static _Unwind_Reason_Code handleLsda(int version, + const uint8_t* lsda, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception* exceptionObject, + _Unwind_Context_t context) { + _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND; + + if (!lsda) + return(ret); + +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...):lsda is non-zero.\n"); +#endif + + // Get the current instruction pointer and offset it before next + // instruction in the current frame which threw the exception. + uintptr_t pc = _Unwind_GetIP(context)-1; + + // Get beginning current frame's code (as defined by the + // emitted dwarf code) + uintptr_t funcStart = _Unwind_GetRegionStart(context); + uintptr_t pcOffset = pc - funcStart; + struct OurExceptionType_t** classInfo = NULL; + + // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding + // dwarf emission + + // Parse LSDA header. + uint8_t lpStartEncoding = *lsda++; + + if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) { + readEncodedPointer(&lsda, lpStartEncoding); + } + + uint8_t ttypeEncoding = *lsda++; + uintptr_t classInfoOffset; + + if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) { + // Calculate type info locations in emitted dwarf code which + // were flagged by type info arguments to llvm.eh.selector + // intrinsic + classInfoOffset = readULEB128(&lsda); + classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset); + } + + // Walk call-site table looking for range that + // includes current PC. + + uint8_t callSiteEncoding = *lsda++; + uint32_t callSiteTableLength = readULEB128(&lsda); + const uint8_t* callSiteTableStart = lsda; + const uint8_t* callSiteTableEnd = callSiteTableStart + + callSiteTableLength; + const uint8_t* actionTableStart = callSiteTableEnd; + const uint8_t* callSitePtr = callSiteTableStart; + + bool foreignException = false; + + while (callSitePtr < callSiteTableEnd) { + uintptr_t start = readEncodedPointer(&callSitePtr, + callSiteEncoding); + uintptr_t length = readEncodedPointer(&callSitePtr, + callSiteEncoding); + uintptr_t landingPad = readEncodedPointer(&callSitePtr, + callSiteEncoding); + + // Note: Action value + uintptr_t actionEntry = readULEB128(&callSitePtr); + + if (exceptionClass != ourBaseExceptionClass) { + // We have been notified of a foreign exception being thrown, + // and we therefore need to execute cleanup landing pads + actionEntry = 0; + foreignException = true; + } + + if (landingPad == 0) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): No landing pad found.\n"); +#endif + + continue; // no landing pad for this entry + } + + if (actionEntry) { + actionEntry += ((uintptr_t) actionTableStart) - 1; + } + else { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...):No action table found.\n"); +#endif + } + + bool exceptionMatched = false; + + if ((start <= pcOffset) && (pcOffset < (start + length))) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): Landing pad found.\n"); +#endif + int64_t actionValue = 0; + + if (actionEntry) { + exceptionMatched = handleActionValue + ( + &actionValue, + classInfo, + actionEntry, + exceptionClass, + exceptionObject + ); + } + + if (!(actions & _UA_SEARCH_PHASE)) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): installed landing pad " + "context.\n"); +#endif + + // Found landing pad for the PC. + // Set Instruction Pointer to so we re-enter function + // at landing pad. The landing pad is created by the + // compiler to take two parameters in registers. + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(0), + (uintptr_t)exceptionObject); + + // Note: this virtual register directly corresponds + // to the return of the llvm.eh.selector intrinsic + if (!actionEntry || !exceptionMatched) { + // We indicate cleanup only + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), + 0); + } + else { + // Matched type info index of llvm.eh.selector intrinsic + // passed here. + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), + actionValue); + } + + // To execute landing pad set here + _Unwind_SetIP(context, funcStart + landingPad); + ret = _URC_INSTALL_CONTEXT; + } + else if (exceptionMatched) { +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): setting handler found.\n"); +#endif + ret = _URC_HANDLER_FOUND; + } + else { + // Note: Only non-clean up handlers are marked as + // found. Otherwise the clean up handlers will be + // re-found and executed during the clean up + // phase. +#ifdef DEBUG + fprintf(stderr, + "handleLsda(...): cleanup handler found.\n"); +#endif + } + + break; + } + } + + return(ret); +} + + +/// This is the personality function which is embedded (dwarf emitted), in the +/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp. +/// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink +/// @param version unsupported (ignored), unwind version +/// @param _Unwind_Action actions minimally supported unwind stage +/// (forced specifically not supported) +/// @param exceptionClass exception class (_Unwind_Exception::exception_class) +/// of thrown exception. +/// @param exceptionObject thrown _Unwind_Exception instance. +/// @param context unwind system context +/// @returns minimally supported unwinding control indicator +_Unwind_Reason_Code ourPersonality(int version, + _Unwind_Action actions, + uint64_t exceptionClass, + struct _Unwind_Exception* exceptionObject, + _Unwind_Context_t context) { +#ifdef DEBUG + fprintf(stderr, + "We are in ourPersonality(...):actions is <%d>.\n", + actions); + + if (actions & _UA_SEARCH_PHASE) { + fprintf(stderr, "ourPersonality(...):In search phase.\n"); + } + else { + fprintf(stderr, "ourPersonality(...):In non-search phase.\n"); + } +#endif + + const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context); + +#ifdef DEBUG + fprintf(stderr, + "ourPersonality(...):lsda = <%p>.\n", + lsda); +#endif + + // The real work of the personality function is captured here + return(handleLsda(version, + lsda, + actions, + exceptionClass, + exceptionObject, + context)); +} + + +/// Generates our _Unwind_Exception class from a given character array. +/// thereby handling arbitrary lengths (not in standard), and handling +/// embedded \0s. +/// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink +/// @param classChars char array to encode. NULL values not checkedf +/// @param classCharsSize number of chars in classChars. Value is not checked. +/// @returns class value +uint64_t genClass(const unsigned char classChars[], size_t classCharsSize) +{ + uint64_t ret = classChars[0]; + + for (unsigned i = 1; i < classCharsSize; ++i) { + ret <<= 8; + ret += classChars[i]; + } + + return(ret); +} + +} // extern "C" + +// +// Runtime C Library functions End +// + +// +// Code generation functions +// + +/// Generates code to print given constant string +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toPrint string to print +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// generated, and is used to hold the constant string. A value of +/// false indicates that the constant string will be stored on the +/// stack. +void generateStringPrint(llvm::LLVMContext& context, + llvm::Module& module, + llvm::IRBuilder<>& builder, + std::string toPrint, + bool useGlobal = true) { + llvm::Function *printFunct = module.getFunction("printStr"); + + llvm::Value *stringVar; + llvm::Constant* stringConstant = + llvm::ConstantArray::get(context, toPrint); + + if (useGlobal) { + // Note: Does not work without allocation + stringVar = + new llvm::GlobalVariable(module, + stringConstant->getType(), + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, + ""); + } + else { + stringVar = builder.CreateAlloca(stringConstant->getType()); + builder.CreateStore(stringConstant, stringVar); + } + + llvm::Value* cast = + builder.CreatePointerCast(stringVar, + builder.getInt8Ty()->getPointerTo()); + builder.CreateCall(printFunct, cast); +} + + +/// Generates code to print given runtime integer according to constant +/// string format, and a given print function. +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param printFunct function used to "print" integer +/// @param toPrint string to print +/// @param format printf like formating string for print +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// generated, and is used to hold the constant string. A value of +/// false indicates that the constant string will be stored on the +/// stack. +void generateIntegerPrint(llvm::LLVMContext& context, + llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::Function& printFunct, + llvm::Value& toPrint, + std::string format, + bool useGlobal = true) { + llvm::Constant *stringConstant = llvm::ConstantArray::get(context, format); + llvm::Value *stringVar; + + if (useGlobal) { + // Note: Does not seem to work without allocation + stringVar = + new llvm::GlobalVariable(module, + stringConstant->getType(), + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, + ""); + } + else { + stringVar = builder.CreateAlloca(stringConstant->getType()); + builder.CreateStore(stringConstant, stringVar); + } + + llvm::Value* cast = + builder.CreateBitCast(stringVar, + builder.getInt8Ty()->getPointerTo()); + builder.CreateCall2(&printFunct, &toPrint, cast); +} + + +/// Generates code to handle finally block type semantics: always runs +/// regardless of whether a thrown exception is passing through or the +/// parent function is simply exiting. In addition to printing some state +/// to stderr, this code will resume the exception handling--runs the +/// unwind resume block, if the exception has not been previously caught +/// by a catch clause, and will otherwise execute the end block (terminator +/// block). In addition this function creates the corresponding function's +/// stack storage for the exception pointer and catch flag status. +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toAddTo parent function to add block to +/// @param blockName block name of new "finally" block. +/// @param functionId output id used for printing +/// @param terminatorBlock terminator "end" block +/// @param unwindResumeBlock unwind resume block +/// @param exceptionCaughtFlag reference exception caught/thrown status storage +/// @param exceptionStorage reference to exception pointer storage +/// @returns newly created block +static llvm::BasicBlock* createFinallyBlock(llvm::LLVMContext& context, + llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::Function& toAddTo, + std::string& blockName, + std::string& functionId, + llvm::BasicBlock& terminatorBlock, + llvm::BasicBlock& unwindResumeBlock, + llvm::Value** exceptionCaughtFlag, + llvm::Value** exceptionStorage) { + assert(exceptionCaughtFlag && + "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag " + "is NULL"); + assert(exceptionStorage && + "ExceptionDemo::createFinallyBlock(...):exceptionStorage " + "is NULL"); + + *exceptionCaughtFlag = + createEntryBlockAlloca(toAddTo, + "exceptionCaught", + ourExceptionNotThrownState->getType(), + ourExceptionNotThrownState); + + const llvm::PointerType* exceptionStorageType = + builder.getInt8Ty()->getPointerTo(); + *exceptionStorage = + createEntryBlockAlloca(toAddTo, + "exceptionStorage", + exceptionStorageType, + llvm::ConstantPointerNull::get( + exceptionStorageType)); + + llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, + blockName, + &toAddTo); + + builder.SetInsertPoint(ret); + + std::ostringstream bufferToPrint; + bufferToPrint << "Gen: Executing finally block " + << blockName + << " in " + << functionId + << std::endl; + generateStringPrint(context, + module, + builder, + bufferToPrint.str(), + USE_GLOBAL_STR_CONSTS); + + llvm::SwitchInst* theSwitch = + builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag), + &terminatorBlock, + 2); + theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); + theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); + + return(ret); +} + + +/// Generates catch block semantics which print a string to indicate type of +/// catch executed, sets an exception caught flag, and executes passed in +/// end block (terminator block). +/// @param context llvm context +/// @param module code for module instance +/// @param builder builder instance +/// @param toAddTo parent function to add block to +/// @param blockName block name of new "catch" block. +/// @param functionId output id used for printing +/// @param terminatorBlock terminator "end" block +/// @param exceptionCaughtFlag exception caught/thrown status +/// @returns newly created block +static llvm::BasicBlock* createCatchBlock(llvm::LLVMContext& context, + llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::Function& toAddTo, + std::string& blockName, + std::string& functionId, + llvm::BasicBlock& terminatorBlock, + llvm::Value& exceptionCaughtFlag) { + + llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, + blockName, + &toAddTo); + + builder.SetInsertPoint(ret); + + std::ostringstream bufferToPrint; + bufferToPrint << "Gen: Executing catch block " + << blockName + << " in " + << functionId + << std::endl; + generateStringPrint(context, + module, + builder, + bufferToPrint.str(), + USE_GLOBAL_STR_CONSTS); + builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag); + builder.CreateBr(&terminatorBlock); + + return(ret); +} + + +/// Generates a function which invokes a function (toInvoke) and, whose +/// unwind block will "catch" the type info types correspondingly held in the +/// exceptionTypesToCatch argument. If the toInvoke function throws an +/// exception which does not match any type info types contained in +/// exceptionTypesToCatch, the generated code will call _Unwind_Resume +/// with the raised exception. On the other hand the generated code will +/// normally exit if the toInvoke function does not throw an exception. +/// The generated "finally" block is always run regardless of the cause of +/// the generated function exit. +/// The generated function is returned after being verified. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param toInvoke inner function to invoke +/// @param ourId id used to printing purposes +/// @param numExceptionsToCatch length of exceptionTypesToCatch array +/// @param exceptionTypesToCatch array of type info types to "catch" +/// @returns generated function +static +llvm::Function* createCatchWrappedInvokeFunction(llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::FunctionPassManager& fpm, + llvm::Function& toInvoke, + std::string ourId, + unsigned numExceptionsToCatch, + unsigned exceptionTypesToCatch[]) { + + llvm::LLVMContext& context = module.getContext(); + llvm::Function *toPrint32Int = module.getFunction("print32Int"); + + ArgTypes argTypes; + argTypes.push_back(builder.getInt32Ty()); + + ArgNames argNames; + argNames.push_back("exceptTypeToThrow"); + + llvm::Function* ret = createFunction(module, + builder.getVoidTy(), + argTypes, + argNames, + ourId, + llvm::Function::ExternalLinkage, + false, + false); + + // Block which calls invoke + llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, + "entry", + ret); + // Normal block for invoke + llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context, + "normal", + ret); + // Unwind block for invoke + llvm::BasicBlock *exceptionBlock = + llvm::BasicBlock::Create(context, "exception", ret); + + // Block which routes exception to correct catch handler block + llvm::BasicBlock *exceptionRouteBlock = + llvm::BasicBlock::Create(context, "exceptionRoute", ret); + + // Foreign exception handler + llvm::BasicBlock *externalExceptionBlock = + llvm::BasicBlock::Create(context, "externalException", ret); + + // Block which calls _Unwind_Resume + llvm::BasicBlock *unwindResumeBlock = + llvm::BasicBlock::Create(context, "unwindResume", ret); + + // Clean up block which delete exception if needed + llvm::BasicBlock *endBlock = + llvm::BasicBlock::Create(context, "end", ret); + + std::string nextName; + std::vector catchBlocks(numExceptionsToCatch); + llvm::Value* exceptionCaughtFlag = NULL; + llvm::Value* exceptionStorage = NULL; + + // Finally block which will branch to unwindResumeBlock if + // exception is not caught. Initializes/allocates stack locations. + llvm::BasicBlock* finallyBlock = createFinallyBlock(context, + module, + builder, + *ret, + nextName = "finally", + ourId, + *endBlock, + *unwindResumeBlock, + &exceptionCaughtFlag, + &exceptionStorage); + + for (unsigned i = 0; i < numExceptionsToCatch; ++i) { + nextName = ourTypeInfoNames[exceptionTypesToCatch[i]]; + + // One catch block per type info to be caught + catchBlocks[i] = createCatchBlock(context, + module, + builder, + *ret, + nextName, + ourId, + *finallyBlock, + *exceptionCaughtFlag); + } + + // Entry Block + + builder.SetInsertPoint(entryBlock); + + std::vector args; + args.push_back(namedValues["exceptTypeToThrow"]); + builder.CreateInvoke(&toInvoke, + normalBlock, + exceptionBlock, + args.begin(), + args.end()); + + // End Block + + builder.SetInsertPoint(endBlock); + + generateStringPrint(context, + module, + builder, + "Gen: In end block: exiting in " + ourId + ".\n", + USE_GLOBAL_STR_CONSTS); + llvm::Function *deleteOurException = + module.getFunction("deleteOurException"); + + // Note: function handles NULL exceptions + builder.CreateCall(deleteOurException, + builder.CreateLoad(exceptionStorage)); + builder.CreateRetVoid(); + + // Normal Block + + builder.SetInsertPoint(normalBlock); + + generateStringPrint(context, + module, + builder, + "Gen: No exception in " + ourId + "!\n", + USE_GLOBAL_STR_CONSTS); + + // Finally block is always called + builder.CreateBr(finallyBlock); + + // Unwind Resume Block + + builder.SetInsertPoint(unwindResumeBlock); + + llvm::Function *resumeOurException = + module.getFunction("_Unwind_Resume"); + builder.CreateCall(resumeOurException, + builder.CreateLoad(exceptionStorage)); + builder.CreateUnreachable(); + + // Exception Block + + builder.SetInsertPoint(exceptionBlock); + + llvm::Function *ehException = module.getFunction("llvm.eh.exception"); + + // Retrieve thrown exception + llvm::Value* unwindException = builder.CreateCall(ehException); + + // Store exception and flag + builder.CreateStore(unwindException, exceptionStorage); + builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag); + llvm::Function *personality = module.getFunction("ourPersonality"); + llvm::Value* functPtr = + builder.CreatePointerCast(personality, + builder.getInt8Ty()->getPointerTo()); + + args.clear(); + args.push_back(unwindException); + args.push_back(functPtr); + + // Note: Skipping index 0 + for (unsigned i = 0; i < numExceptionsToCatch; ++i) { + // Set up type infos to be caught + args.push_back( + module.getGlobalVariable( + ourTypeInfoNames[exceptionTypesToCatch[i]])); + } + + args.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), 0)); + + llvm::Function *ehSelector = module.getFunction("llvm.eh.selector"); + + // Set up this exeption block as the landing pad which will handle + // given type infos. See case Intrinsic::eh_selector in + // SelectionDAGBuilder::visitIntrinsicCall(...) and AddCatchInfo(...) + // implemented in FunctionLoweringInfo.cpp to see how the implementation + // handles this call. This landing pad (this exception block), will be + // called either because it nees to cleanup (call finally) or a type + // info was found which matched the thrown exception. + llvm::Value* retTypeInfoIndex = builder.CreateCall(ehSelector, + args.begin(), + args.end()); + + // Retrieve exception_class member from thrown exception + // (_Unwind_Exception instance). This member tells us whether or not + // the exception is foreign. + llvm::Value* unwindExceptionClass = + builder.CreateLoad( + builder.CreateStructGEP( + builder.CreatePointerCast( + unwindException, + ourUnwindExceptionType->getPointerTo()), + 0)); + + // Branch to the externalExceptionBlock if the exception is foreign or + // to a catch router if not. Either way the finally block will be run. + builder.CreateCondBr( + builder.CreateICmpEQ(unwindExceptionClass, + llvm::ConstantInt::get(builder.getInt64Ty(), + ourBaseExceptionClass)), + exceptionRouteBlock, + externalExceptionBlock); + + // External Exception Block + + builder.SetInsertPoint(externalExceptionBlock); + + generateStringPrint(context, + module, + builder, + "Gen: Foreign exception received.\n", + USE_GLOBAL_STR_CONSTS); + + // Branch to the finally block + builder.CreateBr(finallyBlock); + + // Exception Route Block + + builder.SetInsertPoint(exceptionRouteBlock); + + // Casts exception pointer (_Unwind_Exception instance) to parent + // (OurException instance). + // + // Note: ourBaseFromUnwindOffset is usually negative + llvm::Value* typeInfoThrown = + builder.CreatePointerCast( + builder.CreateConstGEP1_64(unwindException, + ourBaseFromUnwindOffset), + ourExceptionType->getPointerTo()); + + // Retrieve thrown exception type info type + // + // Note: Index is not relative to pointer but instead to structure + // unlike a true getelementptr (GEP) instruction + typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0); + + llvm::Value* typeInfoThrownType = + builder.CreateStructGEP(typeInfoThrown, 0); + + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *(builder.CreateLoad(typeInfoThrownType)), + "Gen: Exception type <%d> received (stack unwound) " + " in " + + ourId + + ".\n", + USE_GLOBAL_STR_CONSTS); + + // Route to matched type info catch block or run cleanup finally block + llvm::SwitchInst* switchToCatchBlock = + builder.CreateSwitch(retTypeInfoIndex, + finallyBlock, + numExceptionsToCatch); + + unsigned nextTypeToCatch; + + for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { + nextTypeToCatch = i - 1; + switchToCatchBlock->addCase(llvm::ConstantInt::get( + llvm::Type::getInt32Ty(context), + i), + catchBlocks[nextTypeToCatch]); + } + + llvm::verifyFunction(*ret); + fpm.run(*ret); + + return(ret); +} + + +/// Generates function which throws either an exception matched to a runtime +/// determined type info type (argument to generated function), or if this +/// runtime value matches nativeThrowType, throws a foreign exception by +/// calling nativeThrowFunct. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param ourId id used to printing purposes +/// @param nativeThrowType a runtime argument of this value results in +/// nativeThrowFunct being called to generate/throw exception. +/// @param nativeThrowFunct function which will throw a foreign exception +/// if the above nativeThrowType matches generated function's arg. +/// @returns generated function +static +llvm::Function* createThrowExceptionFunction(llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::FunctionPassManager& fpm, + std::string ourId, + int32_t nativeThrowType, + llvm::Function& nativeThrowFunct) { + llvm::LLVMContext& context = module.getContext(); + namedValues.clear(); + ArgTypes unwindArgTypes; + unwindArgTypes.push_back(builder.getInt32Ty()); + ArgNames unwindArgNames; + unwindArgNames.push_back("exceptTypeToThrow"); + + llvm::Function *ret = createFunction(module, + builder.getVoidTy(), + unwindArgTypes, + unwindArgNames, + ourId, + llvm::Function::ExternalLinkage, + false, + false); + + // Throws either one of our exception or a native C++ exception depending + // on a runtime argument value containing a type info type. + llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, + "entry", + ret); + // Throws a foreign exception + llvm::BasicBlock *nativeThrowBlock = + llvm::BasicBlock::Create(context, + "nativeThrow", + ret); + // Throws one of our Exceptions + llvm::BasicBlock *generatedThrowBlock = + llvm::BasicBlock::Create(context, + "generatedThrow", + ret); + // Retrieved runtime type info type to throw + llvm::Value* exceptionType = namedValues["exceptTypeToThrow"]; + + // nativeThrowBlock block + + builder.SetInsertPoint(nativeThrowBlock); + + // Throws foreign exception + builder.CreateCall(&nativeThrowFunct, exceptionType); + builder.CreateUnreachable(); + + // entry block + + builder.SetInsertPoint(entryBlock); + + llvm::Function *toPrint32Int = module.getFunction("print32Int"); + generateIntegerPrint(context, + module, + builder, + *toPrint32Int, + *exceptionType, + "\nGen: About to throw exception type <%d> in " + + ourId + + ".\n", + USE_GLOBAL_STR_CONSTS); + + // Switches on runtime type info type value to determine whether or not + // a foreign exception is thrown. Defaults to throwing one of our + // generated exceptions. + llvm::SwitchInst* theSwitch = builder.CreateSwitch(exceptionType, + generatedThrowBlock, + 1); + + theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + nativeThrowType), + nativeThrowBlock); + + // generatedThrow block + + builder.SetInsertPoint(generatedThrowBlock); + + llvm::Function *createOurException = + module.getFunction("createOurException"); + llvm::Function *raiseOurException = + module.getFunction("_Unwind_RaiseException"); + + // Creates exception to throw with runtime type info type. + llvm::Value* exception = + builder.CreateCall(createOurException, + namedValues["exceptTypeToThrow"]); + + // Throw generated Exception + builder.CreateCall(raiseOurException, exception); + builder.CreateUnreachable(); + + llvm::verifyFunction(*ret); + fpm.run(*ret); + + return(ret); +} + +static void createStandardUtilityFunctions(unsigned numTypeInfos, + llvm::Module& module, + llvm::IRBuilder<>& builder); + +/// Creates test code by generating and organizing these functions into the +/// test case. The test case consists of an outer function setup to invoke +/// an inner function within an environment having multiple catch and single +/// finally blocks. This inner function is also setup to invoke a throw +/// function within an evironment similar in nature to the outer function's +/// catch and finally blocks. Each of these two functions catch mutually +/// exclusive subsets (even or odd) of the type info types configured +/// for this this. All generated functions have a runtime argument which +/// holds a type info type to throw that each function takes and passes it +/// to the inner one if such a inner function exists. This type info type is +/// looked at by the generated throw function to see whether or not it should +/// throw a generated exception with the same type info type, or instead call +/// a supplied a function which in turn will throw a foreign exception. +/// @param module code for module instance +/// @param builder builder instance +/// @param fpm a function pass manager holding optional IR to IR +/// transformations +/// @param nativeThrowFunctName name of external function which will throw +/// a foreign exception +/// @returns outermost generated test function. +llvm::Function* createUnwindExceptionTest(llvm::Module& module, + llvm::IRBuilder<>& builder, + llvm::FunctionPassManager& fpm, + std::string nativeThrowFunctName) { + // Number of type infos to generate + unsigned numTypeInfos = 6; + + // Initialze intrisics and external functions to use along with exception + // and type info globals. + createStandardUtilityFunctions(numTypeInfos, + module, + builder); + llvm::Function *nativeThrowFunct = + module.getFunction(nativeThrowFunctName); + + // Create exception throw function using the value ~0 to cause + // foreign exceptions to be thrown. + llvm::Function* throwFunct = + createThrowExceptionFunction(module, + builder, + fpm, + "throwFunct", + ~0, + *nativeThrowFunct); + // Inner function will catch even type infos + unsigned innerExceptionTypesToCatch[] = {6, 2, 4}; + size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) / + sizeof(unsigned); + + // Generate inner function. + llvm::Function* innerCatchFunct = + createCatchWrappedInvokeFunction(module, + builder, + fpm, + *throwFunct, + "innerCatchFunct", + numExceptionTypesToCatch, + innerExceptionTypesToCatch); + + // Outer function will catch odd type infos + unsigned outerExceptionTypesToCatch[] = {3, 1, 5}; + numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) / + sizeof(unsigned); + + // Generate outer function + llvm::Function* outerCatchFunct = + createCatchWrappedInvokeFunction(module, + builder, + fpm, + *innerCatchFunct, + "outerCatchFunct", + numExceptionTypesToCatch, + outerExceptionTypesToCatch); + + // Return outer function to run + return(outerCatchFunct); +} + + +/// Represents our foreign exceptions +class OurCppRunException : public std::runtime_error { +public: + OurCppRunException(const std::string reason) : + std::runtime_error(reason) {} + + OurCppRunException (const OurCppRunException& toCopy) : + std::runtime_error(toCopy) {} + + OurCppRunException& operator = (const OurCppRunException& toCopy) { + return(reinterpret_cast( + std::runtime_error::operator = (toCopy) + )); + } + + ~OurCppRunException (void) throw () {} +}; + + +/// Throws foreign C++ exception. +/// @param ignoreIt unused parameter that allows function to match implied +/// generated function contract. +extern "C" +void throwCppException (int32_t ignoreIt) { + throw(OurCppRunException("thrown by throwCppException(...)")); +} + +typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); + +/// This is a test harness which runs test by executing generated +/// function with a type info type to throw. Harness wraps the excecution +/// of generated function in a C++ try catch clause. +/// @param engine execution engine to use for executing generated function. +/// This demo program expects this to be a JIT instance for demo +/// purposes. +/// @param function generated test function to run +/// @param typeToThrow type info type of generated exception to throw, or +/// indicator to cause foreign exception to be thrown. +static +void runExceptionThrow(llvm::ExecutionEngine* engine, + llvm::Function* function, + int32_t typeToThrow) { + + // Find test's function pointer + OurExceptionThrowFunctType functPtr = + reinterpret_cast( + reinterpret_cast( + engine->getPointerToFunction(function) + ) + ); + + try { + // Run test + (*functPtr)(typeToThrow); + } + catch (OurCppRunException exc) { + // Catch foreign C++ exception + fprintf(stderr, + "\nrunExceptionThrow(...):In C++ catch OurCppRunException " + "with reason: %s.\n", + exc.what()); + } + catch (...) { + // Catch all exceptions including our generated ones. I'm not sure + // why this latter functionality should work, as it seems that + // our exceptions should be foreign to C++ (the _Unwind_Exception:: + // exception_class should be different from the one used by C++), and + // therefore C++ should ignore the generated exceptions. + + fprintf(stderr, + "\nrunExceptionThrow(...):In C++ catch all.\n"); + } +} + +// +// End test functions +// + +/// This initialization routine creates type info globals and +/// adds external function declarations to module. +/// @param numTypeInfos number of linear type info associated type info types +/// to create as GlobalVariable instances, starting with the value 1. +/// @param module code for module instance +/// @param builder builder instance +static void createStandardUtilityFunctions(unsigned numTypeInfos, + llvm::Module& module, + llvm::IRBuilder<>& builder) { + + llvm::LLVMContext& context = module.getContext(); + + // Exception initializations + + // Setup exception catch state + ourExceptionNotThrownState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0), + ourExceptionThrownState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1), + ourExceptionCaughtState = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2), + + + // Create our type info type + ourTypeInfoType = llvm::StructType::get(context, + builder.getInt32Ty(), + NULL); + + // Create OurException type + ourExceptionType = llvm::StructType::get(context, + ourTypeInfoType, + NULL); + + // Create portion of _Unwind_Exception type + // + // Note: Declaring only a portion of the _Unwind_Exception struct. + // Does this cause problems? + ourUnwindExceptionType = llvm::StructType::get(context, + builder.getInt64Ty(), + NULL); + struct OurBaseException_t dummyException; + + // Calculate offset of OurException::unwindException member. + ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) - + ((uintptr_t) &(dummyException.unwindException)); + +#ifdef DEBUG + fprintf(stderr, + "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset " + "= %lld, sizeof(struct OurBaseException_t) - " + "sizeof(struct _Unwind_Exception) = %lu.\n", + ourBaseFromUnwindOffset, + sizeof(struct OurBaseException_t) - + sizeof(struct _Unwind_Exception)); +#endif + + size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char); + + // Create our _Unwind_Exception::exception_class value + ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars); + + // Type infos + + std::string baseStr = "typeInfo", typeInfoName; + std::ostringstream typeInfoNameBuilder; + std::vector structVals; + + llvm::Constant *nextStruct; + llvm::GlobalVariable* nextGlobal = NULL; + + // Generate each type info + // + // Note: First type info is not used. + for (unsigned i = 0; i <= numTypeInfos; ++i) { + structVals.clear(); + structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i)); + nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals); + + typeInfoNameBuilder.str(""); + typeInfoNameBuilder << baseStr << i; + typeInfoName = typeInfoNameBuilder.str(); + + // Note: Does not seem to work without allocation + nextGlobal = + new llvm::GlobalVariable(module, + ourTypeInfoType, + true, + llvm::GlobalValue::ExternalLinkage, + nextStruct, + typeInfoName); + + ourTypeInfoNames.push_back(typeInfoName); + ourTypeInfoNamesIndex[i] = typeInfoName; + } + + ArgNames argNames; + ArgTypes argTypes; + llvm::Function* funct = NULL; + + // print32Int + + const llvm::Type* retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "print32Int", + llvm::Function::ExternalLinkage, + true, + false); + + // print64Int + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt64Ty()); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "print64Int", + llvm::Function::ExternalLinkage, + true, + false); + + // printStr + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "printStr", + llvm::Function::ExternalLinkage, + true, + false); + + // throwCppException + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "throwCppException", + llvm::Function::ExternalLinkage, + true, + false); + + // deleteOurException + + retType = builder.getVoidTy(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "deleteOurException", + llvm::Function::ExternalLinkage, + true, + false); + + // createOurException + + retType = builder.getInt8Ty()->getPointerTo(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "createOurException", + llvm::Function::ExternalLinkage, + true, + false); + + // _Unwind_RaiseException + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_RaiseException", + llvm::Function::ExternalLinkage, + true, + false); + + funct->addFnAttr(llvm::Attribute::NoReturn); + + // _Unwind_Resume + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_Resume", + llvm::Function::ExternalLinkage, + true, + false); + + funct->addFnAttr(llvm::Attribute::NoReturn); + + // ourPersonality + + retType = builder.getInt32Ty(); + + argTypes.clear(); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt32Ty()); + argTypes.push_back(builder.getInt64Ty()); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + argTypes.push_back(builder.getInt8Ty()->getPointerTo()); + + argNames.clear(); + + createFunction(module, + retType, + argTypes, + argNames, + "ourPersonality", + llvm::Function::ExternalLinkage, + true, + false); + + // llvm.eh.selector intrinsic + + getDeclaration(&module, llvm::Intrinsic::eh_selector); + + // llvm.eh.exception intrinsic + + getDeclaration(&module, llvm::Intrinsic::eh_exception); + + // llvm.eh.typeid.for intrinsic + + getDeclaration(&module, llvm::Intrinsic::eh_typeid_for); +} + + +//===---------------------------------------------------------------------===// +// Main test driver code. +//===---------------------------------------------------------------------===// + +/// Demo main routine which takes the type info types to throw. A test will +/// be run for each given type info type. While type info types with the value +/// of -1 will trigger a foreign C++ exception to be thrown; type info types +/// <= 6 and >= 1 will be caught by test functions; and type info types > 6 +/// will result in exceptions which pass through to the test harness. All other +/// type info types are not supported and could cause a crash. +int main(int argc, char* argv[]) { + if (argc == 1) { + fprintf(stderr, + "\nUsage: ExceptionDemo " + "[...].\n" + " Each type must have the value of 1 - 6 for " + "generated exceptions to be caught;\n" + " the value -1 for foreign C++ exceptions to be " + "generated and thrown;\n" + " or the values > 6 for exceptions to be ignored.\n" + "\nTry: ExceptionDemo 2 3 7 -1\n" + " for a full test.\n\n"); + return(0); + } + + // If not set, exception handling will not be turned on + llvm::JITExceptionHandling = true; + + llvm::InitializeNativeTarget(); + llvm::LLVMContext& context = llvm::getGlobalContext(); + llvm::IRBuilder<> theBuilder(context); + + // Make the module, which holds all the code. + llvm::Module* module = new llvm::Module("my cool jit", context); + + // Build engine with JIT + llvm::EngineBuilder factory(module); + factory.setEngineKind(llvm::EngineKind::JIT); + factory.setAllocateGVsWithCode(false); + llvm::ExecutionEngine* executionEngine = factory.create(); + + { + llvm::FunctionPassManager fpm(module); + + // Set up the optimizer pipeline. + // Start with registering info about how the + // target lays out data structures. + fpm.add(new llvm::TargetData(*executionEngine->getTargetData())); + + // Optimizations turned on +#ifdef ADD_OPT_PASSES + + // Basic AliasAnslysis support for GVN. + fpm.add(llvm::createBasicAliasAnalysisPass()); + + // Promote allocas to registers. + fpm.add(llvm::createPromoteMemoryToRegisterPass()); + + // Do simple "peephole" optimizations and bit-twiddling optzns. + fpm.add(llvm::createInstructionCombiningPass()); + + // Reassociate expressions. + fpm.add(llvm::createReassociatePass()); + + // Eliminate Common SubExpressions. + fpm.add(llvm::createGVNPass()); + + // Simplify the control flow graph (deleting unreachable + // blocks, etc). + fpm.add(llvm::createCFGSimplificationPass()); +#endif // ADD_OPT_PASSES + + fpm.doInitialization(); + + // Generate test code using function throwCppException(...) as + // the function which throws foreign exceptions. + llvm::Function* toRun = + createUnwindExceptionTest(*module, + theBuilder, + fpm, + "throwCppException"); + + fprintf(stderr, "\nBegin module dump:\n\n"); + + module->dump(); + + fprintf(stderr, "\nEnd module dump:\n"); + + fprintf(stderr, "\n\nBegin Test:\n"); + + for (int i = 1; i < argc; ++i) { + // Run test for each argument whose value is the exception + // type to throw. + runExceptionThrow(executionEngine, + toRun, + (unsigned) strtoul(argv[i], NULL, 10)); + } + + fprintf(stderr, "\nEnd Test:\n\n"); + } + + delete executionEngine; + + return 0; +} + diff --git a/final/examples/ExceptionDemo/Makefile b/final/examples/ExceptionDemo/Makefile new file mode 100644 index 00000000000..480744730eb --- /dev/null +++ b/final/examples/ExceptionDemo/Makefile @@ -0,0 +1,16 @@ +##===- examples/ExceptionDemo/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 = ExceptionDemo +EXAMPLE_TOOL = 1 +REQUIRES_EH = 1 + +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Fibonacci/CMakeLists.txt b/final/examples/Fibonacci/CMakeLists.txt new file mode 100644 index 00000000000..693761241fc --- /dev/null +++ b/final/examples/Fibonacci/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen) + +add_llvm_example(Fibonacci + fibonacci.cpp + ) diff --git a/final/examples/Fibonacci/Makefile b/final/examples/Fibonacci/Makefile new file mode 100644 index 00000000000..71f6ba0ef52 --- /dev/null +++ b/final/examples/Fibonacci/Makefile @@ -0,0 +1,17 @@ +##===- examples/Fibonacci/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 = Fibonacci +EXAMPLE_TOOL = 1 + +# Link in JIT support +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Fibonacci/fibonacci.cpp b/final/examples/Fibonacci/fibonacci.cpp new file mode 100644 index 00000000000..a7bbf8c7268 --- /dev/null +++ b/final/examples/Fibonacci/fibonacci.cpp @@ -0,0 +1,137 @@ +//===--- examples/Fibonacci/fibonacci.cpp - An example use of the JIT -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This small program provides an example of how to build quickly a small module +// with function Fibonacci and execute it with the JIT. +// +// The goal of this snippet is to create in the memory the LLVM module +// consisting of one function as follow: +// +// int fib(int x) { +// if(x<=2) return 1; +// return fib(x-1)+fib(x-2); +// } +// +// Once we have this, we compile the module via JIT, then execute the `fib' +// function and return result to a driver, i.e. to a "host program". +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetSelect.h" +using namespace llvm; + +static Function *CreateFibFunction(Module *M, LLVMContext &Context) { + // Create the fib function and insert it into module M. This function is said + // to return an int and take an int parameter. + Function *FibF = + cast(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the function. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF); + + // Get pointers to the constants. + Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); + Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); + + // Get pointer to the integer argument of the add1 function... + Argument *ArgX = FibF->arg_begin(); // Get the arg. + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the true_block. + BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF); + // Create an exit block. + BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF); + + // Create the "if (arg <= 2) goto exitbb" + Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); + BranchInst::Create(RetBB, RecurseBB, CondInst, BB); + + // Create: ret int 1 + ReturnInst::Create(Context, One, RetBB); + + // create fib(x-1) + Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); + CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); + CallFibX1->setTailCall(); + + // create fib(x-2) + Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); + CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); + CallFibX2->setTailCall(); + + + // fib(x-1)+fib(x-2) + Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, + "addresult", RecurseBB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(Context, Sum, RecurseBB); + + return FibF; +} + + +int main(int argc, char **argv) { + int n = argc > 1 ? atol(argv[1]) : 24; + + InitializeNativeTarget(); + LLVMContext Context; + + // Create some module to put our function into it. + OwningPtr M(new Module("test", Context)); + + // We are about to create the "fib" function: + Function *FibF = CreateFibFunction(M.get(), Context); + + // Now we going to create JIT + std::string errStr; + ExecutionEngine *EE = + EngineBuilder(M.get()) + .setErrorStr(&errStr) + .setEngineKind(EngineKind::JIT) + .create(); + + if (!EE) { + errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr + << "\n"; + return 1; + } + + errs() << "verifying... "; + if (verifyModule(*M)) { + errs() << argv[0] << ": Error constructing function!\n"; + return 1; + } + + errs() << "OK\n"; + errs() << "We just constructed this LLVM module:\n\n---------\n" << *M; + errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; + + // Call the Fibonacci function with argument n: + std::vector Args(1); + Args[0].IntVal = APInt(32, n); + GenericValue GV = EE->runFunction(FibF, Args); + + // import result of execution + outs() << "Result: " << GV.IntVal << "\n"; + + return 0; +} diff --git a/final/examples/HowToUseJIT/CMakeLists.txt b/final/examples/HowToUseJIT/CMakeLists.txt new file mode 100644 index 00000000000..428b53ffb9b --- /dev/null +++ b/final/examples/HowToUseJIT/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen) + +add_llvm_example(HowToUseJIT + HowToUseJIT.cpp + ) diff --git a/final/examples/HowToUseJIT/HowToUseJIT.cpp b/final/examples/HowToUseJIT/HowToUseJIT.cpp new file mode 100644 index 00000000000..8e3b6dc4a27 --- /dev/null +++ b/final/examples/HowToUseJIT/HowToUseJIT.cpp @@ -0,0 +1,124 @@ +//===-- examples/HowToUseJIT/HowToUseJIT.cpp - An example use of the JIT --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This small program provides an example of how to quickly build a small +// module with two functions and execute it with the JIT. +// +// Goal: +// The goal of this snippet is to create in the memory +// the LLVM module consisting of two functions as follow: +// +// int add1(int x) { +// return x+1; +// } +// +// int foo() { +// return add1(10); +// } +// +// then compile the module via JIT, then execute the `foo' +// function and return result to a driver, i.e. to a "host program". +// +// Some remarks and questions: +// +// - could we invoke some code using noname functions too? +// e.g. evaluate "foo()+foo()" without fears to introduce +// conflict of temporary function name with some real +// existing function name? +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +int main() { + + InitializeNativeTarget(); + + LLVMContext Context; + + // Create some module to put our function into it. + Module *M = new Module("test", Context); + + // Create the add1 function entry and insert this entry into module M. The + // function will have a return type of "int" and take an argument of "int". + // The '0' terminates the list of argument types. + Function *Add1F = + cast(M->getOrInsertFunction("add1", Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the function. As before, it automatically inserts + // because of the last argument. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", Add1F); + + // Get pointers to the constant `1'. + Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); + + // Get pointers to the integer argument of the add1 function... + assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg + Argument *ArgX = Add1F->arg_begin(); // Get the arg + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the add instruction, inserting it into the end of BB. + Instruction *Add = BinaryOperator::CreateAdd(One, ArgX, "addresult", BB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(Context, Add, BB); + + // Now, function add1 is ready. + + + // Now we going to create function `foo', which returns an int and takes no + // arguments. + Function *FooF = + cast(M->getOrInsertFunction("foo", Type::getInt32Ty(Context), + (Type *)0)); + + // Add a basic block to the FooF function. + BB = BasicBlock::Create(Context, "EntryBlock", FooF); + + // Get pointers to the constant `10'. + Value *Ten = ConstantInt::get(Type::getInt32Ty(Context), 10); + + // Pass Ten to the call call: + CallInst *Add1CallRes = CallInst::Create(Add1F, Ten, "add1", BB); + Add1CallRes->setTailCall(true); + + // Create the return instruction and add it to the basic block. + ReturnInst::Create(Context, Add1CallRes, BB); + + // Now we create the JIT. + ExecutionEngine* EE = EngineBuilder(M).create(); + + outs() << "We just constructed this LLVM module:\n\n" << *M; + outs() << "\n\nRunning foo: "; + outs().flush(); + + // Call the `foo' function with no arguments: + std::vector noargs; + GenericValue gv = EE->runFunction(FooF, noargs); + + // Import result of execution: + outs() << "Result: " << gv.IntVal << "\n"; + EE->freeMachineCodeForFunction(FooF); + delete EE; + llvm_shutdown(); + return 0; +} diff --git a/final/examples/HowToUseJIT/Makefile b/final/examples/HowToUseJIT/Makefile new file mode 100644 index 00000000000..c8919db90cc --- /dev/null +++ b/final/examples/HowToUseJIT/Makefile @@ -0,0 +1,15 @@ +##===- examples/HowToUseJIT/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 = HowToUseJIT +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/CMakeLists.txt b/final/examples/Kaleidoscope/CMakeLists.txt new file mode 100644 index 00000000000..8c87ac50b7a --- /dev/null +++ b/final/examples/Kaleidoscope/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(Chapter2) +add_subdirectory(Chapter3) +add_subdirectory(Chapter4) +add_subdirectory(Chapter5) +add_subdirectory(Chapter6) +add_subdirectory(Chapter7) diff --git a/final/examples/Kaleidoscope/Chapter2/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter2/CMakeLists.txt new file mode 100644 index 00000000000..79f2b172d0d --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter2/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_example(Kaleidoscope-Ch2 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter2/Makefile b/final/examples/Kaleidoscope/Chapter2/Makefile new file mode 100644 index 00000000000..1a9b94ce541 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter2/Makefile @@ -0,0 +1,13 @@ +##===- examples/Kaleidoscope/Chapter2/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 = Kaleidoscope-Ch2 +EXAMPLE_TOOL = 1 + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter2/toy.cpp b/final/examples/Kaleidoscope/Chapter2/toy.cpp new file mode 100644 index 00000000000..f4f09d0b351 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter2/toy.cpp @@ -0,0 +1,398 @@ +#include +#include +#include +#include +#include + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (ParseDefinition()) { + fprintf(stderr, "Parsed a function definition.\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (ParseExtern()) { + fprintf(stderr, "Parsed an extern\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (ParseTopLevelExpr()) { + fprintf(stderr, "Parsed a top-level expr\n"); + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Run the main "interpreter loop" now. + MainLoop(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Chapter3/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter3/CMakeLists.txt new file mode 100644 index 00000000000..1af8db00a17 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter3/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core) + +add_llvm_example(Kaleidoscope-Ch3 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter3/Makefile b/final/examples/Kaleidoscope/Chapter3/Makefile new file mode 100644 index 00000000000..4cc6948d803 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter3/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter3/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 = Kaleidoscope-Ch3 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter3/toy.cpp b/final/examples/Kaleidoscope/Chapter3/toy.cpp new file mode 100644 index 00000000000..80d691dd536 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter3/toy.cpp @@ -0,0 +1,563 @@ +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/IRBuilder.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read top-level expression:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Run the main "interpreter loop" now. + MainLoop(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter4/CMakeLists.txt new file mode 100644 index 00000000000..0d1ac533f02 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch4 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter4/Makefile b/final/examples/Kaleidoscope/Chapter4/Makefile new file mode 100644 index 00000000000..30162d94bce --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter4/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter4/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 = Kaleidoscope-Ch4 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter4/toy.cpp b/final/examples/Kaleidoscope/Chapter4/toy.cpp new file mode 100644 index 00000000000..a50d2a43dd2 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter4/toy.cpp @@ -0,0 +1,613 @@ +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/IRBuilder.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter5/CMakeLists.txt new file mode 100644 index 00000000000..2d75ad35923 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch5 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter5/Makefile b/final/examples/Kaleidoscope/Chapter5/Makefile new file mode 100644 index 00000000000..d1f5e2035b4 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter5/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter5/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 = Kaleidoscope-Ch5 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter5/toy.cpp b/final/examples/Kaleidoscope/Chapter5/toy.cpp new file mode 100644 index 00000000000..26b3db66202 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter5/toy.cpp @@ -0,0 +1,858 @@ +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/IRBuilder.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes). +class PrototypeAST { + std::string Name; + std::vector Args; +public: + PrototypeAST(const std::string &name, const std::vector &args) + : Name(name), Args(args) {} + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + } +} + +/// binoprhs +/// ::= ('+' primary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the primary expression after the binary operator. + ExprAST *RHS = ParsePrimary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParsePrimary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +static PrototypeAST *ParsePrototype() { + if (CurTok != tok_identifier) + return ErrorP("Expected function name in prototype"); + + std::string FnName = IdentifierStr; + getNextToken(); + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + return new PrototypeAST(FnName, ArgNames); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: return ErrorV("invalid binary operator"); + } +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // ... + // start = startexpr + // goto loop + // loop: + // variable = phi [start, loopheader], [nextvariable, loopend] + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // nextvariable = variable + step + // endcond = endexpr + // br endcond, loop, endloop + // outloop: + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Make the new basic block for the loop header, inserting after current + // block. + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder.GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Start the PHI node with an entry for Start. + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str()); + Variable->addIncoming(StartVal, PreheaderBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + Value *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Variable; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Add a new entry to the PHI node for the backedge. + Variable->addIncoming(NextVar, LoopEndBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter6/CMakeLists.txt new file mode 100644 index 00000000000..2e15a5f7dfc --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) + +add_llvm_example(Kaleidoscope-Ch6 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter6/Makefile b/final/examples/Kaleidoscope/Chapter6/Makefile new file mode 100644 index 00000000000..a5fbcbdf9b2 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter6/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/Chapter6/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 = Kaleidoscope-Ch6 +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter6/toy.cpp b/final/examples/Kaleidoscope/Chapter6/toy.cpp new file mode 100644 index 00000000000..838125ae77d --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter6/toy.cpp @@ -0,0 +1,976 @@ +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/IRBuilder.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its name, and its argument names (thus implicitly the number +/// of arguments the function takes), as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + return V ? V : ErrorV("Unknown variable name"); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, Ops+2, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // ... + // start = startexpr + // goto loop + // loop: + // variable = phi [start, loopheader], [nextvariable, loopend] + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // nextvariable = variable + step + // endcond = endexpr + // br endcond, loop, endloop + // outloop: + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Make the new basic block for the loop header, inserting after current + // block. + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + BasicBlock *PreheaderBB = Builder.GetInsertBlock(); + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Start the PHI node with an entry for Start. + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), VarName.c_str()); + Variable->addIncoming(StartVal, PreheaderBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + Value *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Variable; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *LoopEndBB = Builder.GetInsertBlock(); + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Add a new entry to the PHI node for the backedge. + Variable->addIncoming(NextVar, LoopEndBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) { + AI->setName(Args[Idx]); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = AI; + } + + return F; +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/final/examples/Kaleidoscope/Chapter7/CMakeLists.txt new file mode 100644 index 00000000000..da3839843bd --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LLVM_LINK_COMPONENTS core jit interpreter native) +set(LLVM_REQUIRES_RTTI 1) + +add_llvm_example(Kaleidoscope-Ch7 + toy.cpp + ) diff --git a/final/examples/Kaleidoscope/Chapter7/Makefile b/final/examples/Kaleidoscope/Chapter7/Makefile new file mode 100644 index 00000000000..6cec323efd4 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter7/Makefile @@ -0,0 +1,16 @@ +##===- examples/Kaleidoscope/Chapter7/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 = Kaleidoscope-Ch7 +EXAMPLE_TOOL = 1 +REQUIRES_RTTI := 1 + +LINK_COMPONENTS := core jit native + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Kaleidoscope/Chapter7/toy.cpp b/final/examples/Kaleidoscope/Chapter7/toy.cpp new file mode 100644 index 00000000000..e63578f57e6 --- /dev/null +++ b/final/examples/Kaleidoscope/Chapter7/toy.cpp @@ -0,0 +1,1142 @@ +#include "llvm/DerivedTypes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/IRBuilder.h" +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, tok_extern = -3, + + // primary + tok_identifier = -4, tok_number = -5, + + // control + tok_if = -6, tok_then = -7, tok_else = -8, + tok_for = -9, tok_in = -10, + + // operators + tok_binary = -11, tok_unary = -12, + + // var definition + tok_var = -13 +}; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = getchar(); + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getchar()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") return tok_def; + if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + if (IdentifierStr == "for") return tok_for; + if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "binary") return tok_binary; + if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "var") return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = getchar(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do LastChar = getchar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = getchar(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// + +/// ExprAST - Base class for all expression nodes. +class ExprAST { +public: + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; +public: + NumberExprAST(double val) : Val(val) {} + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; +public: + VariableExprAST(const std::string &name) : Name(name) {} + const std::string &getName() const { return Name; } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; +public: + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; +public: + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; +public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) + : Cond(cond), Then(then), Else(_else) {} + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. +public: + PrototypeAST(const std::string &name, const std::vector &args, + bool isoperator = false, unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size()-1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) + : Proto(proto), Body(body) {} + + Function *Codegen(); +}; + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { + return CurTok = gettok(); +} + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} +PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } +FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) return 0; + Args.push_back(Arg); + + if (CurTok == ')') break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) return 0; + + return new IfExprAST(Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + + ExprAST *Start = ParseExpression(); + if (Start == 0) return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: return Error("unknown token when expecting an expression"); + case tok_identifier: return ParseIdentifierExpr(); + case tok_number: return ParseNumberExpr(); + case '(': return ParseParenExpr(); + case tok_if: return ParseIfExpr(); + case tok_for: return ParseForExpr(); + case tok_var: return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec+1, RHS); + if (RHS == 0) return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = new PrototypeAST("", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static IRBuilder<> Builder(getGlobalContext()); +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { Error(Str); return 0; } + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) return ErrorV("Unknown variable name"); + + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) return 0; + + Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) return 0; + + switch (Op) { + case '+': return Builder.CreateFAdd(L, R, "addtmp"); + case '-': return Builder.CreateFSub(L, R, "subtmp"); + case '*': return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary")+Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, Ops+2, "binop"); +} + +Value *CallExprAST::Codegen() { + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp"); +} + +Value *IfExprAST::Codegen() { + Value *CondV = Cond->Codegen(); + if (CondV == 0) return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE(CondV, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE(EndCond, + ConstantFP::get(getGlobalContext(), APFloat(0.0)), + "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), + Doubles, false); + + Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (Function *LF = F->Codegen()) { + fprintf(stderr, "Read function definition:"); + LF->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (Function *F = P->Codegen()) { + fprintf(stderr, "Read extern: "); + F->dump(); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (Function *LF = F->Codegen()) { + // JIT the function, returning a function pointer. + void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + + // Cast it to the right type (takes no arguments, returns a double) so we + // can call it as a native function. + double (*FP)() = (double (*)())(intptr_t)FPtr; + fprintf(stderr, "Evaluated to %f\n", FP()); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: return; + case ';': getNextToken(); break; // ignore top-level semicolons. + case tok_def: HandleDefinition(); break; + case tok_extern: HandleExtern(); break; + default: HandleTopLevelExpression(); break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" +double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" +double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + fprintf(stderr, "ready> "); + getNextToken(); + + // Make the module, which holds all the code. + TheModule = new Module("my cool jit", Context); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/final/examples/Kaleidoscope/Makefile b/final/examples/Kaleidoscope/Makefile new file mode 100644 index 00000000000..bd0c252c2c0 --- /dev/null +++ b/final/examples/Kaleidoscope/Makefile @@ -0,0 +1,15 @@ +##===- examples/Kaleidoscope/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 + +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 + +include $(LEVEL)/Makefile.common diff --git a/final/examples/Makefile b/final/examples/Makefile new file mode 100644 index 00000000000..50a6db76aa2 --- /dev/null +++ b/final/examples/Makefile @@ -0,0 +1,32 @@ +##===- examples/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 + +PARALLEL_DIRS:= BrainF Fibonacci HowToUseJIT Kaleidoscope ModuleMaker + +ifeq ($(HAVE_PTHREAD),1) +PARALLEL_DIRS += ParallelJIT +endif + +ifeq ($(LLVM_ON_UNIX),1) + ifeq ($(ARCH),x86) + PARALLEL_DIRS += ExceptionDemo + endif + ifeq ($(ARCH),x86_64) + PARALLEL_DIRS += ExceptionDemo + endif +endif + +ifeq ($(filter $(BINDINGS_TO_BUILD),ocaml),ocaml) + PARALLEL_DIRS += OCaml-Kaleidoscope +endif + +include $(LEVEL)/Makefile.common diff --git a/final/examples/ModuleMaker/CMakeLists.txt b/final/examples/ModuleMaker/CMakeLists.txt new file mode 100644 index 00000000000..81e911560bd --- /dev/null +++ b/final/examples/ModuleMaker/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_LINK_COMPONENTS bitwriter) + +add_llvm_example(ModuleMaker + ModuleMaker.cpp + ) diff --git a/final/examples/ModuleMaker/Makefile b/final/examples/ModuleMaker/Makefile new file mode 100644 index 00000000000..9454cf514dc --- /dev/null +++ b/final/examples/ModuleMaker/Makefile @@ -0,0 +1,14 @@ +##===- examples/ModuleMaker/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=ModuleMaker +EXAMPLE_TOOL = 1 +LINK_COMPONENTS := bitwriter + +include $(LEVEL)/Makefile.common diff --git a/final/examples/ModuleMaker/ModuleMaker.cpp b/final/examples/ModuleMaker/ModuleMaker.cpp new file mode 100644 index 00000000000..6bc52c12a03 --- /dev/null +++ b/final/examples/ModuleMaker/ModuleMaker.cpp @@ -0,0 +1,64 @@ +//===- examples/ModuleMaker/ModuleMaker.cpp - Example project ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This programs is a simple example that creates an LLVM module "from scratch", +// emitting it as a bitcode file to standard out. This is just to show how +// LLVM projects work and to demonstrate some of the LLVM APIs. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +int main() { + LLVMContext Context; + + // Create the "module" or "program" or "translation unit" to hold the + // function + Module *M = new Module("test", Context); + + // Create the main function: first create the type 'int ()' + FunctionType *FT = + FunctionType::get(Type::getInt32Ty(Context), /*not vararg*/false); + + // By passing a module as the last parameter to the Function constructor, + // it automatically gets appended to the Module. + Function *F = Function::Create(FT, Function::ExternalLinkage, "main", M); + + // Add a basic block to the function... again, it automatically inserts + // because of the last argument. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", F); + + // Get pointers to the constant integers... + Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); + Value *Three = ConstantInt::get(Type::getInt32Ty(Context), 3); + + // Create the add instruction... does not insert... + Instruction *Add = BinaryOperator::Create(Instruction::Add, Two, Three, + "addresult"); + + // explicitly insert it into the basic block... + BB->getInstList().push_back(Add); + + // Create the return instruction and add it to the basic block + BB->getInstList().push_back(ReturnInst::Create(Context, Add)); + + // Output the bitcode file to stdout + WriteBitcodeToFile(M, outs()); + + // Delete the module and all of its contents. + delete M; + return 0; +} diff --git a/final/examples/ModuleMaker/README.txt b/final/examples/ModuleMaker/README.txt new file mode 100644 index 00000000000..66a5d3fe0b1 --- /dev/null +++ b/final/examples/ModuleMaker/README.txt @@ -0,0 +1,8 @@ +//===----------------------------------------------------------------------===// +// ModuleMaker Sample project +//===----------------------------------------------------------------------===// + +This project is an extremely simple example of using some simple pieces of the +LLVM API. The actual executable generated by this project simply emits an +LLVM bitcode file to standard output. It is designed to show some basic +usage of LLVM APIs, and how to link to LLVM libraries. diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter2/Makefile new file mode 100644 index 00000000000..8fc03da0fbd --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/Makefile @@ -0,0 +1,22 @@ +##===- examples/OCaml-Kaleidoscope/Chapter2/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 2. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch2 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm + +OCAMLCFLAGS += -pp camlp4of + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/_tags b/final/examples/OCaml-Kaleidoscope/Chapter2/_tags new file mode 100644 index 00000000000..7b9b80b1e94 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/_tags @@ -0,0 +1 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/ast.ml new file mode 100644 index 00000000000..4cc2dea86b7 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/ast.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml new file mode 100644 index 00000000000..22a915552f0 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/lexer.ml @@ -0,0 +1,52 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/parser.ml new file mode 100644 index 00000000000..83d9874a4ab --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/parser.ml @@ -0,0 +1,122 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/token.ml new file mode 100644 index 00000000000..2ca782e1499 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/token.ml @@ -0,0 +1,15 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml new file mode 100644 index 00000000000..01c85bd70d2 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml @@ -0,0 +1,34 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +(* top ::= definition | external | expression | ';' *) +let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + ignore(Parser.parse_definition stream); + print_endline "parsed a function definition."; + | Token.Extern -> + ignore(Parser.parse_extern stream); + print_endline "parsed an extern."; + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + ignore(Parser.parse_toplevel stream); + print_endline "parsed a top-level expr"; + with Stream.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter2/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter2/toy.ml new file mode 100644 index 00000000000..42b19fec001 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter2/toy.ml @@ -0,0 +1,21 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter3/Makefile new file mode 100644 index 00000000000..fdbcd5191f4 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/Makefile @@ -0,0 +1,24 @@ +##===- examples/OCaml-Kaleidoscope/Chapter3/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 3. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch3 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis + +OCAMLCFLAGS += -pp camlp4of + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/_tags b/final/examples/OCaml-Kaleidoscope/Chapter3/_tags new file mode 100644 index 00000000000..990490a5db2 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/_tags @@ -0,0 +1,2 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/ast.ml new file mode 100644 index 00000000000..4cc2dea86b7 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/ast.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml new file mode 100644 index 00000000000..275cd0bee04 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/codegen.ml @@ -0,0 +1,100 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_add lhs_val rhs_val "addtmp" builder + | '-' -> build_sub lhs_val rhs_val "subtmp" builder + | '*' -> build_mul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + +let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +let codegen_func = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + the_function + with e -> + delete_function the_function; + raise e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml new file mode 100644 index 00000000000..22a915552f0 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/lexer.ml @@ -0,0 +1,52 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml new file mode 100644 index 00000000000..b71f5d717ef --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml @@ -0,0 +1,6 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/parser.ml new file mode 100644 index 00000000000..83d9874a4ab --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/parser.ml @@ -0,0 +1,122 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/token.ml new file mode 100644 index 00000000000..2ca782e1499 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/token.ml @@ -0,0 +1,15 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml new file mode 100644 index 00000000000..d1bf5d4c0c6 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml @@ -0,0 +1,39 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm + +(* top ::= definition | external | expression | ';' *) +let rec main_loop stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + dump_value (Codegen.codegen_func e); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter3/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter3/toy.ml new file mode 100644 index 00000000000..73c1a1ec62a --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter3/toy.ml @@ -0,0 +1,26 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm + +let main () = + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter4/Makefile new file mode 100644 index 00000000000..d9c3f49bea6 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/Makefile @@ -0,0 +1,25 @@ +##===- examples/OCaml-Kaleidoscope/Chapter4/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 4. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch4 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ + llvm_scalar_opts + +OCAMLCFLAGS += -pp camlp4of + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/_tags b/final/examples/OCaml-Kaleidoscope/Chapter4/_tags new file mode 100644 index 00000000000..7a03dba6672 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/_tags @@ -0,0 +1,4 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/ast.ml new file mode 100644 index 00000000000..4cc2dea86b7 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/ast.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/bindings.c b/final/examples/OCaml-Kaleidoscope/Chapter4/bindings.c new file mode 100644 index 00000000000..053513bf0c0 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/bindings.c @@ -0,0 +1,7 @@ +#include + +/* putchard - putchar that takes a double and returns 0. */ +extern double putchard(double X) { + putchar((char)X); + return 0; +} diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/codegen.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/codegen.ml new file mode 100644 index 00000000000..8957f4c610f --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/codegen.ml @@ -0,0 +1,103 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_fadd lhs_val rhs_val "addtmp" builder + | '-' -> build_fsub lhs_val rhs_val "subtmp" builder + | '*' -> build_fmul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + +let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/lexer.ml new file mode 100644 index 00000000000..22a915552f0 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/lexer.ml @@ -0,0 +1,52 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml new file mode 100644 index 00000000000..ff42664c43b --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml @@ -0,0 +1,10 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; +ocaml_lib ~extern:true "llvm_executionengine";; +ocaml_lib ~extern:true "llvm_target";; +ocaml_lib ~extern:true "llvm_scalar_opts";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/parser.ml new file mode 100644 index 00000000000..83d9874a4ab --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/parser.ml @@ -0,0 +1,122 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/token.ml new file mode 100644 index 00000000000..2ca782e1499 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/token.ml @@ -0,0 +1,15 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml new file mode 100644 index 00000000000..01d24ede149 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml @@ -0,0 +1,49 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine + +(* top ::= definition | external | expression | ';' *) +let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter4/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter4/toy.ml new file mode 100644 index 00000000000..5f9d912499c --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter4/toy.ml @@ -0,0 +1,53 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine +open Llvm_target +open Llvm_scalar_opts + +let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter5/Makefile new file mode 100644 index 00000000000..f31c10d3c2f --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/Makefile @@ -0,0 +1,25 @@ +##===- examples/OCaml-Kaleidoscope/Chapter5/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 5. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch5 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ + llvm_scalar_opts + +OCAMLCFLAGS += -pp camlp4of + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/_tags b/final/examples/OCaml-Kaleidoscope/Chapter5/_tags new file mode 100644 index 00000000000..7a03dba6672 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/_tags @@ -0,0 +1,4 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/ast.ml new file mode 100644 index 00000000000..8a6703db837 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/ast.ml @@ -0,0 +1,31 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = Prototype of string * string array + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/bindings.c b/final/examples/OCaml-Kaleidoscope/Chapter5/bindings.c new file mode 100644 index 00000000000..053513bf0c0 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/bindings.c @@ -0,0 +1,7 @@ +#include + +/* putchard - putchar that takes a double and returns 0. */ +extern double putchard(double X) { + putchar((char)X); + return 0; +} diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/codegen.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/codegen.ml new file mode 100644 index 00000000000..e4570a65759 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/codegen.ml @@ -0,0 +1,225 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_fadd lhs_val rhs_val "addtmp" builder + | '-' -> build_fsub lhs_val rhs_val "subtmp" builder + | '*' -> build_fmul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> raise (Error "invalid binary operator") + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let preheader_bb = insertion_block builder in + let the_function = block_parent preheader_bb in + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Start the PHI node with an entry for start. *) + let variable = build_phi [(start_val, preheader_bb)] var_name builder in + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name variable; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + let next_var = build_add variable step_val "nextvar" builder in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let loop_end_bb = insertion_block builder in + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Add a new entry to the PHI node for the backedge. *) + add_incoming (next_var, loop_end_bb) variable; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + +let codegen_proto = function + | Ast.Prototype (name, args) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/lexer.ml new file mode 100644 index 00000000000..d8c1d563010 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/lexer.ml @@ -0,0 +1,57 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml new file mode 100644 index 00000000000..ff42664c43b --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml @@ -0,0 +1,10 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; +ocaml_lib ~extern:true "llvm_executionengine";; +ocaml_lib ~extern:true "llvm_target";; +ocaml_lib ~extern:true "llvm_scalar_opts";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);; +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/parser.ml new file mode 100644 index 00000000000..bfb4f168458 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/parser.ml @@ -0,0 +1,158 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_primary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/token.ml new file mode 100644 index 00000000000..5eb502fb894 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/token.ml @@ -0,0 +1,19 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml new file mode 100644 index 00000000000..01d24ede149 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml @@ -0,0 +1,49 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine + +(* top ::= definition | external | expression | ';' *) +let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter5/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter5/toy.ml new file mode 100644 index 00000000000..5f9d912499c --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter5/toy.ml @@ -0,0 +1,53 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine +open Llvm_target +open Llvm_scalar_opts + +let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter6/Makefile new file mode 100644 index 00000000000..21f0c53df4b --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/Makefile @@ -0,0 +1,34 @@ +##===- examples/OCaml-Kaleidoscope/Chapter6/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 6. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch6 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ + llvm_scalar_opts + +OCAMLCFLAGS += -pp camlp4of + +OcamlSources1 = \ + $(PROJ_SRC_DIR)/ast.ml \ + $(PROJ_SRC_DIR)/parser.ml \ + $(PROJ_SRC_DIR)/codegen.ml \ + $(PROJ_SRC_DIR)/lexer.ml \ + $(PROJ_SRC_DIR)/token.ml \ + $(PROJ_SRC_DIR)/toplevel.ml \ + $(PROJ_SRC_DIR)/toy.ml + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/_tags b/final/examples/OCaml-Kaleidoscope/Chapter6/_tags new file mode 100644 index 00000000000..7a03dba6672 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/_tags @@ -0,0 +1,4 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/ast.ml new file mode 100644 index 00000000000..99088cfd2f5 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/ast.ml @@ -0,0 +1,36 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a unary operator. *) + | Unary of char * expr + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = + | Prototype of string * string array + | BinOpPrototype of string * string array * int + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/bindings.c b/final/examples/OCaml-Kaleidoscope/Chapter6/bindings.c new file mode 100644 index 00000000000..90faed15813 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/bindings.c @@ -0,0 +1,13 @@ +#include + +/* putchard - putchar that takes a double and returns 0. */ +extern double putchard(double X) { + putchar((char)X); + return 0; +} + +/* printd - printf that takes a double prints it as "%f\n", returning 0. */ +extern double printd(double X) { + printf("%f\n", X); + return 0; +} diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/codegen.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/codegen.ml new file mode 100644 index 00000000000..96674359440 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/codegen.ml @@ -0,0 +1,251 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + (try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name")) + | Ast.Unary (op, operand) -> + let operand = codegen_expr operand in + let callee = "unary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown unary operator") + in + build_call callee [|operand|] "unop" builder + | Ast.Binary (op, lhs, rhs) -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_fadd lhs_val rhs_val "addtmp" builder + | '-' -> build_fsub lhs_val rhs_val "subtmp" builder + | '*' -> build_fmul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> + (* If it wasn't a builtin binary operator, it must be a user defined + * one. Emit a call to it. *) + let callee = "binary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "binary operator not found!") + in + build_call callee [|lhs_val; rhs_val|] "binop" builder + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let preheader_bb = insertion_block builder in + let the_function = block_parent preheader_bb in + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Start the PHI node with an entry for start. *) + let variable = build_phi [(start_val, preheader_bb)] var_name builder in + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name variable; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + let next_var = build_add variable step_val "nextvar" builder in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let loop_end_bb = insertion_block builder in + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Add a new entry to the PHI node for the backedge. *) + add_incoming (next_var, loop_end_bb) variable; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + +let codegen_proto = function + | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* If this is an operator, install it. *) + begin match proto with + | Ast.BinOpPrototype (name, args, prec) -> + let op = name.[String.length name - 1] in + Hashtbl.add Parser.binop_precedence op prec; + | _ -> () + end; + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/lexer.ml new file mode 100644 index 00000000000..5fe9da4f16c --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/lexer.ml @@ -0,0 +1,59 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml new file mode 100644 index 00000000000..54d3fd97709 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml @@ -0,0 +1,10 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; +ocaml_lib ~extern:true "llvm_executionengine";; +ocaml_lib ~extern:true "llvm_target";; +ocaml_lib ~extern:true "llvm_scalar_opts";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);; +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/parser.ml new file mode 100644 index 00000000000..da443c5bb68 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/parser.ml @@ -0,0 +1,195 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* unary + * ::= primary + * ::= '!' unary *) +and parse_unary = parser + (* If this is a unary operator, read it. *) + | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> + Ast.Unary (op, operand) + + (* If the current token is not an operator, it must be a primary expr. *) + | [< stream >] -> parse_primary stream + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the unary expression after the binary operator. *) + let rhs = parse_unary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/token.ml new file mode 100644 index 00000000000..c7a5f95092d --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/token.ml @@ -0,0 +1,22 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In + + (* operators *) + | Binary | Unary diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml new file mode 100644 index 00000000000..01d24ede149 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml @@ -0,0 +1,49 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine + +(* top ::= definition | external | expression | ';' *) +let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter6/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter6/toy.ml new file mode 100644 index 00000000000..5f9d912499c --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter6/toy.ml @@ -0,0 +1,53 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine +open Llvm_target +open Llvm_scalar_opts + +let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/Makefile b/final/examples/OCaml-Kaleidoscope/Chapter7/Makefile new file mode 100644 index 00000000000..99686e17ea8 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/Makefile @@ -0,0 +1,34 @@ +##===- examples/OCaml-Kaleidoscope/Chapter7/Makefile -------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 7. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../.. +TOOLNAME := OCaml-Kaleidoscope-Ch7 +EXAMPLE_TOOL := 1 +UsedComponents := core +UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \ + llvm_scalar_opts + +OCAMLCFLAGS += -pp camlp4of + +OcamlSources1 = \ + $(PROJ_SRC_DIR)/ast.ml \ + $(PROJ_SRC_DIR)/parser.ml \ + $(PROJ_SRC_DIR)/codegen.ml \ + $(PROJ_SRC_DIR)/lexer.ml \ + $(PROJ_SRC_DIR)/token.ml \ + $(PROJ_SRC_DIR)/toplevel.ml \ + $(PROJ_SRC_DIR)/toy.ml + +ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml + +include $(LEVEL)/bindings/ocaml/Makefile.ocaml diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/_tags b/final/examples/OCaml-Kaleidoscope/Chapter7/_tags new file mode 100644 index 00000000000..7a03dba6672 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/_tags @@ -0,0 +1,4 @@ +<{lexer,parser}.ml>: use_camlp4, pp(camlp4of) +<*.{byte,native}>: g++, use_llvm, use_llvm_analysis +<*.{byte,native}>: use_llvm_executionengine, use_llvm_target +<*.{byte,native}>: use_llvm_scalar_opts, use_bindings diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/ast.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/ast.ml new file mode 100644 index 00000000000..c699e8074a4 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/ast.ml @@ -0,0 +1,39 @@ +(*===----------------------------------------------------------------------=== + * Abstract Syntax Tree (aka Parse Tree) + *===----------------------------------------------------------------------===*) + +(* expr - Base type for all expression nodes. *) +type expr = + (* variant for numeric literals like "1.0". *) + | Number of float + + (* variant for referencing a variable, like "a". *) + | Variable of string + + (* variant for a unary operator. *) + | Unary of char * expr + + (* variant for a binary operator. *) + | Binary of char * expr * expr + + (* variant for function calls. *) + | Call of string * expr array + + (* variant for if/then/else. *) + | If of expr * expr * expr + + (* variant for for/in. *) + | For of string * expr * expr * expr option * expr + + (* variant for var/in. *) + | Var of (string * expr option) array * expr + +(* proto - This type represents the "prototype" for a function, which captures + * its name, and its argument names (thus implicitly the number of arguments the + * function takes). *) +type proto = + | Prototype of string * string array + | BinOpPrototype of string * string array * int + +(* func - This type represents a function definition itself. *) +type func = Function of proto * expr diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/bindings.c b/final/examples/OCaml-Kaleidoscope/Chapter7/bindings.c new file mode 100644 index 00000000000..90faed15813 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/bindings.c @@ -0,0 +1,13 @@ +#include + +/* putchard - putchar that takes a double and returns 0. */ +extern double putchard(double X) { + putchar((char)X); + return 0; +} + +/* printd - printf that takes a double prints it as "%f\n", returning 0. */ +extern double printd(double X) { + printf("%f\n", X); + return 0; +} diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/codegen.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/codegen.ml new file mode 100644 index 00000000000..e66396eb6ac --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/codegen.ml @@ -0,0 +1,370 @@ +(*===----------------------------------------------------------------------=== + * Code Generation + *===----------------------------------------------------------------------===*) + +open Llvm + +exception Error of string + +let context = global_context () +let the_module = create_module context "my cool jit" +let builder = builder context +let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10 +let double_type = double_type context + +(* Create an alloca instruction in the entry block of the function. This + * is used for mutable variables etc. *) +let create_entry_block_alloca the_function var_name = + let builder = builder_at context (instr_begin (entry_block the_function)) in + build_alloca double_type var_name builder + +let rec codegen_expr = function + | Ast.Number n -> const_float double_type n + | Ast.Variable name -> + let v = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + (* Load the value. *) + build_load v name builder + | Ast.Unary (op, operand) -> + let operand = codegen_expr operand in + let callee = "unary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown unary operator") + in + build_call callee [|operand|] "unop" builder + | Ast.Binary (op, lhs, rhs) -> + begin match op with + | '=' -> + (* Special case '=' because we don't want to emit the LHS as an + * expression. *) + let name = + match lhs with + | Ast.Variable name -> name + | _ -> raise (Error "destination of '=' must be a variable") + in + + (* Codegen the rhs. *) + let val_ = codegen_expr rhs in + + (* Lookup the name. *) + let variable = try Hashtbl.find named_values name with + | Not_found -> raise (Error "unknown variable name") + in + ignore(build_store val_ variable builder); + val_ + | _ -> + let lhs_val = codegen_expr lhs in + let rhs_val = codegen_expr rhs in + begin + match op with + | '+' -> build_fadd lhs_val rhs_val "addtmp" builder + | '-' -> build_fsub lhs_val rhs_val "subtmp" builder + | '*' -> build_fmul lhs_val rhs_val "multmp" builder + | '<' -> + (* Convert bool 0/1 to double 0.0 or 1.0 *) + let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in + build_uitofp i double_type "booltmp" builder + | _ -> + (* If it wasn't a builtin binary operator, it must be a user defined + * one. Emit a call to it. *) + let callee = "binary" ^ (String.make 1 op) in + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "binary operator not found!") + in + build_call callee [|lhs_val; rhs_val|] "binop" builder + end + end + | Ast.Call (callee, args) -> + (* Look up the name in the module table. *) + let callee = + match lookup_function callee the_module with + | Some callee -> callee + | None -> raise (Error "unknown function referenced") + in + let params = params callee in + + (* If argument mismatch error. *) + if Array.length params == Array.length args then () else + raise (Error "incorrect # arguments passed"); + let args = Array.map codegen_expr args in + build_call callee args "calltmp" builder + | Ast.If (cond, then_, else_) -> + let cond = codegen_expr cond in + + (* Convert condition to a bool by comparing equal to 0.0 *) + let zero = const_float double_type 0.0 in + let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in + + (* Grab the first block so that we might later add the conditional branch + * to it at the end of the function. *) + let start_bb = insertion_block builder in + let the_function = block_parent start_bb in + + let then_bb = append_block context "then" the_function in + + (* Emit 'then' value. *) + position_at_end then_bb builder; + let then_val = codegen_expr then_ in + + (* Codegen of 'then' can change the current block, update then_bb for the + * phi. We create a new name because one is used for the phi node, and the + * other is used for the conditional branch. *) + let new_then_bb = insertion_block builder in + + (* Emit 'else' value. *) + let else_bb = append_block context "else" the_function in + position_at_end else_bb builder; + let else_val = codegen_expr else_ in + + (* Codegen of 'else' can change the current block, update else_bb for the + * phi. *) + let new_else_bb = insertion_block builder in + + (* Emit merge block. *) + let merge_bb = append_block context "ifcont" the_function in + position_at_end merge_bb builder; + let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in + let phi = build_phi incoming "iftmp" builder in + + (* Return to the start block to add the conditional branch. *) + position_at_end start_bb builder; + ignore (build_cond_br cond_val then_bb else_bb builder); + + (* Set a unconditional branch at the end of the 'then' block and the + * 'else' block to the 'merge' block. *) + position_at_end new_then_bb builder; ignore (build_br merge_bb builder); + position_at_end new_else_bb builder; ignore (build_br merge_bb builder); + + (* Finally, set the builder to the end of the merge block. *) + position_at_end merge_bb builder; + + phi + | Ast.For (var_name, start, end_, step, body) -> + (* Output this as: + * var = alloca double + * ... + * start = startexpr + * store start -> var + * goto loop + * loop: + * ... + * bodyexpr + * ... + * loopend: + * step = stepexpr + * endcond = endexpr + * + * curvar = load var + * nextvar = curvar + step + * store nextvar -> var + * br endcond, loop, endloop + * outloop: *) + + let the_function = block_parent (insertion_block builder) in + + (* Create an alloca for the variable in the entry block. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Emit the start code first, without 'variable' in scope. *) + let start_val = codegen_expr start in + + (* Store the value into the alloca. *) + ignore(build_store start_val alloca builder); + + (* Make the new basic block for the loop header, inserting after current + * block. *) + let loop_bb = append_block context "loop" the_function in + + (* Insert an explicit fall through from the current block to the + * loop_bb. *) + ignore (build_br loop_bb builder); + + (* Start insertion in loop_bb. *) + position_at_end loop_bb builder; + + (* Within the loop, the variable is defined equal to the PHI node. If it + * shadows an existing variable, we have to restore it, so save it + * now. *) + let old_val = + try Some (Hashtbl.find named_values var_name) with Not_found -> None + in + Hashtbl.add named_values var_name alloca; + + (* Emit the body of the loop. This, like any other expr, can change the + * current BB. Note that we ignore the value computed by the body, but + * don't allow an error *) + ignore (codegen_expr body); + + (* Emit the step value. *) + let step_val = + match step with + | Some step -> codegen_expr step + (* If not specified, use 1.0. *) + | None -> const_float double_type 1.0 + in + + (* Compute the end condition. *) + let end_cond = codegen_expr end_ in + + (* Reload, increment, and restore the alloca. This handles the case where + * the body of the loop mutates the variable. *) + let cur_var = build_load alloca var_name builder in + let next_var = build_add cur_var step_val "nextvar" builder in + ignore(build_store next_var alloca builder); + + (* Convert condition to a bool by comparing equal to 0.0. *) + let zero = const_float double_type 0.0 in + let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in + + (* Create the "after loop" block and insert it. *) + let after_bb = append_block context "afterloop" the_function in + + (* Insert the conditional branch into the end of loop_end_bb. *) + ignore (build_cond_br end_cond loop_bb after_bb builder); + + (* Any new code will be inserted in after_bb. *) + position_at_end after_bb builder; + + (* Restore the unshadowed variable. *) + begin match old_val with + | Some old_val -> Hashtbl.add named_values var_name old_val + | None -> () + end; + + (* for expr always returns 0.0. *) + const_null double_type + | Ast.Var (var_names, body) -> + let old_bindings = ref [] in + + let the_function = block_parent (insertion_block builder) in + + (* Register all variables and emit their initializer. *) + Array.iter (fun (var_name, init) -> + (* Emit the initializer before adding the variable to scope, this + * prevents the initializer from referencing the variable itself, and + * permits stuff like this: + * var a = 1 in + * var a = a in ... # refers to outer 'a'. *) + let init_val = + match init with + | Some init -> codegen_expr init + (* If not specified, use 0.0. *) + | None -> const_float double_type 0.0 + in + + let alloca = create_entry_block_alloca the_function var_name in + ignore(build_store init_val alloca builder); + + (* Remember the old variable binding so that we can restore the binding + * when we unrecurse. *) + begin + try + let old_value = Hashtbl.find named_values var_name in + old_bindings := (var_name, old_value) :: !old_bindings; + with Not_found -> () + end; + + (* Remember this binding. *) + Hashtbl.add named_values var_name alloca; + ) var_names; + + (* Codegen the body, now that all vars are in scope. *) + let body_val = codegen_expr body in + + (* Pop all our variables from scope. *) + List.iter (fun (var_name, old_value) -> + Hashtbl.add named_values var_name old_value + ) !old_bindings; + + (* Return the body computation. *) + body_val + +let codegen_proto = function + | Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) -> + (* Make the function type: double(double,double) etc. *) + let doubles = Array.make (Array.length args) double_type in + let ft = function_type double_type doubles in + let f = + match lookup_function name the_module with + | None -> declare_function name ft the_module + + (* If 'f' conflicted, there was already something named 'name'. If it + * has a body, don't allow redefinition or reextern. *) + | Some f -> + (* If 'f' already has a body, reject this. *) + if block_begin f <> At_end f then + raise (Error "redefinition of function"); + + (* If 'f' took a different number of arguments, reject. *) + if element_type (type_of f) <> ft then + raise (Error "redefinition of function with different # args"); + f + in + + (* Set names for all arguments. *) + Array.iteri (fun i a -> + let n = args.(i) in + set_value_name n a; + Hashtbl.add named_values n a; + ) (params f); + f + +(* Create an alloca for each argument and register the argument in the symbol + * table so that references to it will succeed. *) +let create_argument_allocas the_function proto = + let args = match proto with + | Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args + in + Array.iteri (fun i ai -> + let var_name = args.(i) in + (* Create an alloca for this variable. *) + let alloca = create_entry_block_alloca the_function var_name in + + (* Store the initial value into the alloca. *) + ignore(build_store ai alloca builder); + + (* Add arguments to variable symbol table. *) + Hashtbl.add named_values var_name alloca; + ) (params the_function) + +let codegen_func the_fpm = function + | Ast.Function (proto, body) -> + Hashtbl.clear named_values; + let the_function = codegen_proto proto in + + (* If this is an operator, install it. *) + begin match proto with + | Ast.BinOpPrototype (name, args, prec) -> + let op = name.[String.length name - 1] in + Hashtbl.add Parser.binop_precedence op prec; + | _ -> () + end; + + (* Create a new basic block to start insertion into. *) + let bb = append_block context "entry" the_function in + position_at_end bb builder; + + try + (* Add all arguments to the symbol table and create their allocas. *) + create_argument_allocas the_function proto; + + let ret_val = codegen_expr body in + + (* Finish off the function. *) + let _ = build_ret ret_val builder in + + (* Validate the generated code, checking for consistency. *) + Llvm_analysis.assert_valid_function the_function; + + (* Optimize the function. *) + let _ = PassManager.run_function the_function the_fpm in + + the_function + with e -> + delete_function the_function; + raise e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/lexer.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/lexer.ml new file mode 100644 index 00000000000..922cabf0428 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/lexer.ml @@ -0,0 +1,60 @@ +(*===----------------------------------------------------------------------=== + * Lexer + *===----------------------------------------------------------------------===*) + +let rec lex = parser + (* Skip any whitespace. *) + | [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream + + (* identifier: [a-zA-Z][a-zA-Z0-9] *) + | [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_ident buffer stream + + (* number: [0-9.]+ *) + | [< ' ('0' .. '9' as c); stream >] -> + let buffer = Buffer.create 1 in + Buffer.add_char buffer c; + lex_number buffer stream + + (* Comment until end of line. *) + | [< ' ('#'); stream >] -> + lex_comment stream + + (* Otherwise, just return the character as its ascii value. *) + | [< 'c; stream >] -> + [< 'Token.Kwd c; lex stream >] + + (* end of stream. *) + | [< >] -> [< >] + +and lex_number buffer = parser + | [< ' ('0' .. '9' | '.' as c); stream >] -> + Buffer.add_char buffer c; + lex_number buffer stream + | [< stream=lex >] -> + [< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >] + +and lex_ident buffer = parser + | [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] -> + Buffer.add_char buffer c; + lex_ident buffer stream + | [< stream=lex >] -> + match Buffer.contents buffer with + | "def" -> [< 'Token.Def; stream >] + | "extern" -> [< 'Token.Extern; stream >] + | "if" -> [< 'Token.If; stream >] + | "then" -> [< 'Token.Then; stream >] + | "else" -> [< 'Token.Else; stream >] + | "for" -> [< 'Token.For; stream >] + | "in" -> [< 'Token.In; stream >] + | "binary" -> [< 'Token.Binary; stream >] + | "unary" -> [< 'Token.Unary; stream >] + | "var" -> [< 'Token.Var; stream >] + | id -> [< 'Token.Ident id; stream >] + +and lex_comment = parser + | [< ' ('\n'); stream=lex >] -> stream + | [< 'c; e=lex_comment >] -> e + | [< >] -> [< >] diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml new file mode 100644 index 00000000000..54d3fd97709 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml @@ -0,0 +1,10 @@ +open Ocamlbuild_plugin;; + +ocaml_lib ~extern:true "llvm";; +ocaml_lib ~extern:true "llvm_analysis";; +ocaml_lib ~extern:true "llvm_executionengine";; +ocaml_lib ~extern:true "llvm_target";; +ocaml_lib ~extern:true "llvm_scalar_opts";; + +flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"; A"-cclib"; A"-rdynamic"]);; +dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];; diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/parser.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/parser.ml new file mode 100644 index 00000000000..c0e7db8349a --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/parser.ml @@ -0,0 +1,221 @@ +(*===---------------------------------------------------------------------=== + * Parser + *===---------------------------------------------------------------------===*) + +(* binop_precedence - This holds the precedence for each binary operator that is + * defined *) +let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10 + +(* precedence - Get the precedence of the pending binary operator token. *) +let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1 + +(* primary + * ::= identifier + * ::= numberexpr + * ::= parenexpr + * ::= ifexpr + * ::= forexpr + * ::= varexpr *) +let rec parse_primary = parser + (* numberexpr ::= number *) + | [< 'Token.Number n >] -> Ast.Number n + + (* parenexpr ::= '(' expression ')' *) + | [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e + + (* identifierexpr + * ::= identifier + * ::= identifier '(' argumentexpr ')' *) + | [< 'Token.Ident id; stream >] -> + let rec parse_args accumulator = parser + | [< e=parse_expr; stream >] -> + begin parser + | [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e + | [< >] -> e :: accumulator + end stream + | [< >] -> accumulator + in + let rec parse_ident id = parser + (* Call. *) + | [< 'Token.Kwd '('; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')'">] -> + Ast.Call (id, Array.of_list (List.rev args)) + + (* Simple variable ref. *) + | [< >] -> Ast.Variable id + in + parse_ident id stream + + (* ifexpr ::= 'if' expr 'then' expr 'else' expr *) + | [< 'Token.If; c=parse_expr; + 'Token.Then ?? "expected 'then'"; t=parse_expr; + 'Token.Else ?? "expected 'else'"; e=parse_expr >] -> + Ast.If (c, t, e) + + (* forexpr + ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *) + | [< 'Token.For; + 'Token.Ident id ?? "expected identifier after for"; + 'Token.Kwd '=' ?? "expected '=' after for"; + stream >] -> + begin parser + | [< + start=parse_expr; + 'Token.Kwd ',' ?? "expected ',' after for"; + end_=parse_expr; + stream >] -> + let step = + begin parser + | [< 'Token.Kwd ','; step=parse_expr >] -> Some step + | [< >] -> None + end stream + in + begin parser + | [< 'Token.In; body=parse_expr >] -> + Ast.For (id, start, end_, step, body) + | [< >] -> + raise (Stream.Error "expected 'in' after for") + end stream + | [< >] -> + raise (Stream.Error "expected '=' after for") + end stream + + (* varexpr + * ::= 'var' identifier ('=' expression? + * (',' identifier ('=' expression)?)* 'in' expression *) + | [< 'Token.Var; + (* At least one variable name is required. *) + 'Token.Ident id ?? "expected identifier after var"; + init=parse_var_init; + var_names=parse_var_names [(id, init)]; + (* At this point, we have to have 'in'. *) + 'Token.In ?? "expected 'in' keyword after 'var'"; + body=parse_expr >] -> + Ast.Var (Array.of_list (List.rev var_names), body) + + | [< >] -> raise (Stream.Error "unknown token when expecting an expression.") + +(* unary + * ::= primary + * ::= '!' unary *) +and parse_unary = parser + (* If this is a unary operator, read it. *) + | [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] -> + Ast.Unary (op, operand) + + (* If the current token is not an operator, it must be a primary expr. *) + | [< stream >] -> parse_primary stream + +(* binoprhs + * ::= ('+' primary)* *) +and parse_bin_rhs expr_prec lhs stream = + match Stream.peek stream with + (* If this is a binop, find its precedence. *) + | Some (Token.Kwd c) when Hashtbl.mem binop_precedence c -> + let token_prec = precedence c in + + (* If this is a binop that binds at least as tightly as the current binop, + * consume it, otherwise we are done. *) + if token_prec < expr_prec then lhs else begin + (* Eat the binop. *) + Stream.junk stream; + + (* Parse the primary expression after the binary operator. *) + let rhs = parse_unary stream in + + (* Okay, we know this is a binop. *) + let rhs = + match Stream.peek stream with + | Some (Token.Kwd c2) -> + (* If BinOp binds less tightly with rhs than the operator after + * rhs, let the pending operator take rhs as its lhs. *) + let next_prec = precedence c2 in + if token_prec < next_prec + then parse_bin_rhs (token_prec + 1) rhs stream + else rhs + | _ -> rhs + in + + (* Merge lhs/rhs. *) + let lhs = Ast.Binary (c, lhs, rhs) in + parse_bin_rhs expr_prec lhs stream + end + | _ -> lhs + +and parse_var_init = parser + (* read in the optional initializer. *) + | [< 'Token.Kwd '='; e=parse_expr >] -> Some e + | [< >] -> None + +and parse_var_names accumulator = parser + | [< 'Token.Kwd ','; + 'Token.Ident id ?? "expected identifier list after var"; + init=parse_var_init; + e=parse_var_names ((id, init) :: accumulator) >] -> e + | [< >] -> accumulator + +(* expression + * ::= primary binoprhs *) +and parse_expr = parser + | [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream + +(* prototype + * ::= id '(' id* ')' + * ::= binary LETTER number? (id, id) + * ::= unary LETTER number? (id) *) +let parse_prototype = + let rec parse_args accumulator = parser + | [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e + | [< >] -> accumulator + in + let parse_operator = parser + | [< 'Token.Unary >] -> "unary", 1 + | [< 'Token.Binary >] -> "binary", 2 + in + let parse_binary_precedence = parser + | [< 'Token.Number n >] -> int_of_float n + | [< >] -> 30 + in + parser + | [< 'Token.Ident id; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + (* success. *) + Ast.Prototype (id, Array.of_list (List.rev args)) + | [< (prefix, kind)=parse_operator; + 'Token.Kwd op ?? "expected an operator"; + (* Read the precedence if present. *) + binary_precedence=parse_binary_precedence; + 'Token.Kwd '(' ?? "expected '(' in prototype"; + args=parse_args []; + 'Token.Kwd ')' ?? "expected ')' in prototype" >] -> + let name = prefix ^ (String.make 1 op) in + let args = Array.of_list (List.rev args) in + + (* Verify right number of arguments for operator. *) + if Array.length args != kind + then raise (Stream.Error "invalid number of operands for operator") + else + if kind == 1 then + Ast.Prototype (name, args) + else + Ast.BinOpPrototype (name, args, binary_precedence) + | [< >] -> + raise (Stream.Error "expected function name in prototype") + +(* definition ::= 'def' prototype expression *) +let parse_definition = parser + | [< 'Token.Def; p=parse_prototype; e=parse_expr >] -> + Ast.Function (p, e) + +(* toplevelexpr ::= expression *) +let parse_toplevel = parser + | [< e=parse_expr >] -> + (* Make an anonymous proto. *) + Ast.Function (Ast.Prototype ("", [||]), e) + +(* external ::= 'extern' prototype *) +let parse_extern = parser + | [< 'Token.Extern; e=parse_prototype >] -> e diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/token.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/token.ml new file mode 100644 index 00000000000..1489f0b9e79 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/token.ml @@ -0,0 +1,25 @@ +(*===----------------------------------------------------------------------=== + * Lexer Tokens + *===----------------------------------------------------------------------===*) + +(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of + * these others for known things. *) +type token = + (* commands *) + | Def | Extern + + (* primary *) + | Ident of string | Number of float + + (* unknown *) + | Kwd of char + + (* control *) + | If | Then | Else + | For | In + + (* operators *) + | Binary | Unary + + (* var definition *) + | Var diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml new file mode 100644 index 00000000000..01d24ede149 --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml @@ -0,0 +1,49 @@ +(*===----------------------------------------------------------------------=== + * Top-Level parsing and JIT Driver + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine + +(* top ::= definition | external | expression | ';' *) +let rec main_loop the_fpm the_execution_engine stream = + match Stream.peek stream with + | None -> () + + (* ignore top-level semicolons. *) + | Some (Token.Kwd ';') -> + Stream.junk stream; + main_loop the_fpm the_execution_engine stream + + | Some token -> + begin + try match token with + | Token.Def -> + let e = Parser.parse_definition stream in + print_endline "parsed a function definition."; + dump_value (Codegen.codegen_func the_fpm e); + | Token.Extern -> + let e = Parser.parse_extern stream in + print_endline "parsed an extern."; + dump_value (Codegen.codegen_proto e); + | _ -> + (* Evaluate a top-level expression into an anonymous function. *) + let e = Parser.parse_toplevel stream in + print_endline "parsed a top-level expr"; + let the_function = Codegen.codegen_func the_fpm e in + dump_value the_function; + + (* JIT the function, returning a function pointer. *) + let result = ExecutionEngine.run_function the_function [||] + the_execution_engine in + + print_string "Evaluated to "; + print_float (GenericValue.as_float Codegen.double_type result); + print_newline (); + with Stream.Error s | Codegen.Error s -> + (* Skip token for error recovery. *) + Stream.junk stream; + print_endline s; + end; + print_string "ready> "; flush stdout; + main_loop the_fpm the_execution_engine stream diff --git a/final/examples/OCaml-Kaleidoscope/Chapter7/toy.ml b/final/examples/OCaml-Kaleidoscope/Chapter7/toy.ml new file mode 100644 index 00000000000..babab28601d --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Chapter7/toy.ml @@ -0,0 +1,57 @@ +(*===----------------------------------------------------------------------=== + * Main driver code. + *===----------------------------------------------------------------------===*) + +open Llvm +open Llvm_executionengine +open Llvm_target +open Llvm_scalar_opts + +let main () = + ignore (initialize_native_target ()); + + (* Install standard binary operators. + * 1 is the lowest precedence. *) + Hashtbl.add Parser.binop_precedence '=' 2; + Hashtbl.add Parser.binop_precedence '<' 10; + Hashtbl.add Parser.binop_precedence '+' 20; + Hashtbl.add Parser.binop_precedence '-' 20; + Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *) + + (* Prime the first token. *) + print_string "ready> "; flush stdout; + let stream = Lexer.lex (Stream.of_channel stdin) in + + (* Create the JIT. *) + let the_execution_engine = ExecutionEngine.create Codegen.the_module in + let the_fpm = PassManager.create_function Codegen.the_module in + + (* Set up the optimizer pipeline. Start with registering info about how the + * target lays out data structures. *) + TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm; + + (* Promote allocas to registers. *) + add_memory_to_register_promotion the_fpm; + + (* Do simple "peephole" optimizations and bit-twiddling optzn. *) + add_instruction_combination the_fpm; + + (* reassociate expressions. *) + add_reassociation the_fpm; + + (* Eliminate Common SubExpressions. *) + add_gvn the_fpm; + + (* Simplify the control flow graph (deleting unreachable blocks, etc). *) + add_cfg_simplification the_fpm; + + ignore (PassManager.initialize the_fpm); + + (* Run the main "interpreter loop" now. *) + Toplevel.main_loop the_fpm the_execution_engine stream; + + (* Print out all the generated code. *) + dump_module Codegen.the_module +;; + +main () diff --git a/final/examples/OCaml-Kaleidoscope/Makefile b/final/examples/OCaml-Kaleidoscope/Makefile new file mode 100644 index 00000000000..5342b94022a --- /dev/null +++ b/final/examples/OCaml-Kaleidoscope/Makefile @@ -0,0 +1,15 @@ +##===- examples/OCaml-Kaleidoscope/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 + +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 + +include $(LEVEL)/Makefile.common diff --git a/final/examples/ParallelJIT/CMakeLists.txt b/final/examples/ParallelJIT/CMakeLists.txt new file mode 100644 index 00000000000..fbdc6e5fc10 --- /dev/null +++ b/final/examples/ParallelJIT/CMakeLists.txt @@ -0,0 +1,9 @@ +set(LLVM_LINK_COMPONENTS jit interpreter nativecodegen) + +add_llvm_example(ParallelJIT + ParallelJIT.cpp + ) + +if(HAVE_LIBPTHREAD) + target_link_libraries(ParallelJIT pthread) +endif(HAVE_LIBPTHREAD) diff --git a/final/examples/ParallelJIT/Makefile b/final/examples/ParallelJIT/Makefile new file mode 100644 index 00000000000..8a49d427313 --- /dev/null +++ b/final/examples/ParallelJIT/Makefile @@ -0,0 +1,17 @@ +##===- examples/ParallelJIT/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 = ParallelJIT +EXAMPLE_TOOL = 1 + +LINK_COMPONENTS := jit interpreter nativecodegen + +include $(LEVEL)/Makefile.common + +LIBS += -lpthread diff --git a/final/examples/ParallelJIT/ParallelJIT.cpp b/final/examples/ParallelJIT/ParallelJIT.cpp new file mode 100644 index 00000000000..9231abf6e31 --- /dev/null +++ b/final/examples/ParallelJIT/ParallelJIT.cpp @@ -0,0 +1,304 @@ +//===-- examples/ParallelJIT/ParallelJIT.cpp - Exercise threaded-safe JIT -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Parallel JIT +// +// This test program creates two LLVM functions then calls them from three +// separate threads. It requires the pthreads library. +// The three threads are created and then block waiting on a condition variable. +// Once all threads are blocked on the conditional variable, the main thread +// wakes them up. This complicated work is performed so that all three threads +// call into the JIT at the same time (or the best possible approximation of the +// same time). This test had assertion errors until I got the locking right. + +#include +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/Target/TargetSelect.h" +#include +using namespace llvm; + +static Function* createAdd1(Module *M) { + // Create the add1 function entry and insert this entry into module M. The + // function will have a return type of "int" and take an argument of "int". + // The '0' terminates the list of argument types. + Function *Add1F = + cast(M->getOrInsertFunction("add1", + Type::getInt32Ty(M->getContext()), + Type::getInt32Ty(M->getContext()), + (Type *)0)); + + // Add a basic block to the function. As before, it automatically inserts + // because of the last argument. + BasicBlock *BB = BasicBlock::Create(M->getContext(), "EntryBlock", Add1F); + + // Get pointers to the constant `1'. + Value *One = ConstantInt::get(Type::getInt32Ty(M->getContext()), 1); + + // Get pointers to the integer argument of the add1 function... + assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg + Argument *ArgX = Add1F->arg_begin(); // Get the arg + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the add instruction, inserting it into the end of BB. + Instruction *Add = BinaryOperator::CreateAdd(One, ArgX, "addresult", BB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(M->getContext(), Add, BB); + + // Now, function add1 is ready. + return Add1F; +} + +static Function *CreateFibFunction(Module *M) { + // Create the fib function and insert it into module M. This function is said + // to return an int and take an int parameter. + Function *FibF = + cast(M->getOrInsertFunction("fib", + Type::getInt32Ty(M->getContext()), + Type::getInt32Ty(M->getContext()), + (Type *)0)); + + // Add a basic block to the function. + BasicBlock *BB = BasicBlock::Create(M->getContext(), "EntryBlock", FibF); + + // Get pointers to the constants. + Value *One = ConstantInt::get(Type::getInt32Ty(M->getContext()), 1); + Value *Two = ConstantInt::get(Type::getInt32Ty(M->getContext()), 2); + + // Get pointer to the integer argument of the add1 function... + Argument *ArgX = FibF->arg_begin(); // Get the arg. + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. + + // Create the true_block. + BasicBlock *RetBB = BasicBlock::Create(M->getContext(), "return", FibF); + // Create an exit block. + BasicBlock* RecurseBB = BasicBlock::Create(M->getContext(), "recurse", FibF); + + // Create the "if (arg < 2) goto exitbb" + Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); + BranchInst::Create(RetBB, RecurseBB, CondInst, BB); + + // Create: ret int 1 + ReturnInst::Create(M->getContext(), One, RetBB); + + // create fib(x-1) + Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); + Value *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); + + // create fib(x-2) + Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); + Value *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); + + // fib(x-1)+fib(x-2) + Value *Sum = + BinaryOperator::CreateAdd(CallFibX1, CallFibX2, "addresult", RecurseBB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(M->getContext(), Sum, RecurseBB); + + return FibF; +} + +struct threadParams { + ExecutionEngine* EE; + Function* F; + int value; +}; + +// We block the subthreads just before they begin to execute: +// we want all of them to call into the JIT at the same time, +// to verify that the locking is working correctly. +class WaitForThreads +{ +public: + WaitForThreads() + { + n = 0; + waitFor = 0; + + int result = pthread_cond_init( &condition, NULL ); + assert( result == 0 ); + + result = pthread_mutex_init( &mutex, NULL ); + assert( result == 0 ); + } + + ~WaitForThreads() + { + int result = pthread_cond_destroy( &condition ); + assert( result == 0 ); + + result = pthread_mutex_destroy( &mutex ); + assert( result == 0 ); + } + + // All threads will stop here until another thread calls releaseThreads + void block() + { + int result = pthread_mutex_lock( &mutex ); + assert( result == 0 ); + n ++; + //~ std::cout << "block() n " << n << " waitFor " << waitFor << std::endl; + + assert( waitFor == 0 || n <= waitFor ); + if ( waitFor > 0 && n == waitFor ) + { + // There are enough threads blocked that we can release all of them + std::cout << "Unblocking threads from block()" << std::endl; + unblockThreads(); + } + else + { + // We just need to wait until someone unblocks us + result = pthread_cond_wait( &condition, &mutex ); + assert( result == 0 ); + } + + // unlock the mutex before returning + result = pthread_mutex_unlock( &mutex ); + assert( result == 0 ); + } + + // If there are num or more threads blocked, it will signal them all + // Otherwise, this thread blocks until there are enough OTHER threads + // blocked + void releaseThreads( size_t num ) + { + int result = pthread_mutex_lock( &mutex ); + assert( result == 0 ); + + if ( n >= num ) { + std::cout << "Unblocking threads from releaseThreads()" << std::endl; + unblockThreads(); + } + else + { + waitFor = num; + pthread_cond_wait( &condition, &mutex ); + } + + // unlock the mutex before returning + result = pthread_mutex_unlock( &mutex ); + assert( result == 0 ); + } + +private: + void unblockThreads() + { + // Reset the counters to zero: this way, if any new threads + // enter while threads are exiting, they will block instead + // of triggering a new release of threads + n = 0; + + // Reset waitFor to zero: this way, if waitFor threads enter + // while threads are exiting, they will block instead of + // triggering a new release of threads + waitFor = 0; + + int result = pthread_cond_broadcast( &condition ); + assert(result == 0); result=result; + } + + size_t n; + size_t waitFor; + pthread_cond_t condition; + pthread_mutex_t mutex; +}; + +static WaitForThreads synchronize; + +void* callFunc( void* param ) +{ + struct threadParams* p = (struct threadParams*) param; + + // Call the `foo' function with no arguments: + std::vector Args(1); + Args[0].IntVal = APInt(32, p->value); + + synchronize.block(); // wait until other threads are at this point + GenericValue gv = p->EE->runFunction(p->F, Args); + + return (void*)(intptr_t)gv.IntVal.getZExtValue(); +} + +int main() { + InitializeNativeTarget(); + LLVMContext Context; + + // Create some module to put our function into it. + Module *M = new Module("test", Context); + + Function* add1F = createAdd1( M ); + Function* fibF = CreateFibFunction( M ); + + // Now we create the JIT. + ExecutionEngine* EE = EngineBuilder(M).create(); + + //~ std::cout << "We just constructed this LLVM module:\n\n" << *M; + //~ std::cout << "\n\nRunning foo: " << std::flush; + + // Create one thread for add1 and two threads for fib + struct threadParams add1 = { EE, add1F, 1000 }; + struct threadParams fib1 = { EE, fibF, 39 }; + struct threadParams fib2 = { EE, fibF, 42 }; + + pthread_t add1Thread; + int result = pthread_create( &add1Thread, NULL, callFunc, &add1 ); + if ( result != 0 ) { + std::cerr << "Could not create thread" << std::endl; + return 1; + } + + pthread_t fibThread1; + result = pthread_create( &fibThread1, NULL, callFunc, &fib1 ); + if ( result != 0 ) { + std::cerr << "Could not create thread" << std::endl; + return 1; + } + + pthread_t fibThread2; + result = pthread_create( &fibThread2, NULL, callFunc, &fib2 ); + if ( result != 0 ) { + std::cerr << "Could not create thread" << std::endl; + return 1; + } + + synchronize.releaseThreads(3); // wait until other threads are at this point + + void* returnValue; + result = pthread_join( add1Thread, &returnValue ); + if ( result != 0 ) { + std::cerr << "Could not join thread" << std::endl; + return 1; + } + std::cout << "Add1 returned " << intptr_t(returnValue) << std::endl; + + result = pthread_join( fibThread1, &returnValue ); + if ( result != 0 ) { + std::cerr << "Could not join thread" << std::endl; + return 1; + } + std::cout << "Fib1 returned " << intptr_t(returnValue) << std::endl; + + result = pthread_join( fibThread2, &returnValue ); + if ( result != 0 ) { + std::cerr << "Could not join thread" << std::endl; + return 1; + } + std::cout << "Fib2 returned " << intptr_t(returnValue) << std::endl; + + return 0; +} diff --git a/final/include/llvm-c/Analysis.h b/final/include/llvm-c/Analysis.h new file mode 100644 index 00000000000..e1e44872b16 --- /dev/null +++ b/final/include/llvm-c/Analysis.h @@ -0,0 +1,55 @@ +/*===-- llvm-c/Analysis.h - Analysis Library C Interface --------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMAnalysis.a, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ANALYSIS_H +#define LLVM_C_ANALYSIS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef enum { + LLVMAbortProcessAction, /* verifier will print to stderr and abort() */ + LLVMPrintMessageAction, /* verifier will print to stderr and return 1 */ + LLVMReturnStatusAction /* verifier will just return 1 */ +} LLVMVerifierFailureAction; + + +/* Verifies that a module is valid, taking the specified action if not. + Optionally returns a human-readable description of any invalid constructs. + OutMessage must be disposed with LLVMDisposeMessage. */ +LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessage); + +/* Verifies that a single function is valid, taking the specified action. Useful + for debugging. */ +LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action); + +/* Open up a ghostview window that displays the CFG of the current function. + Useful for debugging. */ +void LLVMViewFunctionCFG(LLVMValueRef Fn); +void LLVMViewFunctionCFGOnly(LLVMValueRef Fn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/BitReader.h b/final/include/llvm-c/BitReader.h new file mode 100644 index 00000000000..6db66074b31 --- /dev/null +++ b/final/include/llvm-c/BitReader.h @@ -0,0 +1,66 @@ +/*===-- llvm-c/BitReader.h - BitReader Library C Interface ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMBitReader.a, which *| +|* implements input of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITCODEREADER_H +#define LLVM_C_BITCODEREADER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage); + +LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage); + +/** Reads a module from the specified path, returning via the OutMP parameter + a module provider which performs lazy deserialization. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutM, + char **OutMessage); + +LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage); + + +/** Deprecated: Use LLVMGetBitcodeModuleInContext instead. */ +LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage); + +/** Deprecated: Use LLVMGetBitcodeModule instead. */ +LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/BitWriter.h b/final/include/llvm-c/BitWriter.h new file mode 100644 index 00000000000..bcbfb111492 --- /dev/null +++ b/final/include/llvm-c/BitWriter.h @@ -0,0 +1,46 @@ +/*===-- llvm-c/BitWriter.h - BitWriter Library C Interface ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMBitWriter.a, which *| +|* implements output of the LLVM bitcode format. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_BITCODEWRITER_H +#define LLVM_C_BITCODEWRITER_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/*===-- Operations on modules ---------------------------------------------===*/ + +/** Writes a module to the specified path. Returns 0 on success. */ +int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path); + +/** Writes a module to an open file descriptor. Returns 0 on success. */ +int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, + int Unbuffered); + +/** Deprecated for LLVMWriteBitcodeToFD. Writes a module to an open file + descriptor. Returns 0 on success. Closes the Handle. */ +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/Core.h b/final/include/llvm-c/Core.h new file mode 100644 index 00000000000..39c3cb40117 --- /dev/null +++ b/final/include/llvm-c/Core.h @@ -0,0 +1,1177 @@ +/*===-- llvm-c/Core.h - Core Library C Interface ------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMCore.a, which implements *| +|* the LLVM intermediate representation. *| +|* *| +|* LLVM uses a polymorphic type hierarchy which C cannot represent, therefore *| +|* parameters must be passed as base types. Despite the declared types, most *| +|* of the functions provided operate only on branches of the type hierarchy. *| +|* The declared parameter names are descriptive and specify which type is *| +|* required. Additionally, each type hierarchy is documented along with the *| +|* functions that operate upon it. For more detail, refer to LLVM's C++ code. *| +|* If in doubt, refer to Core.cpp, which performs paramter downcasts in the *| +|* form unwrap(Param). *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +|* When included into a C++ source file, also declares 'wrap' and 'unwrap' *| +|* helpers to perform opaque reference<-->pointer conversions. These helpers *| +|* are shorter and more tightly typed than writing the casts by hand when *| +|* authoring bindings. In assert builds, they will do runtime type checking. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_CORE_H +#define LLVM_C_CORE_H + +#include "llvm/Support/DataTypes.h" + +#ifdef __cplusplus + +/* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' + and 'unwrap' conversion functions. */ +#include "llvm/Module.h" +#include "llvm/PassRegistry.h" +#include "llvm/Support/IRBuilder.h" + +extern "C" { +#endif + + +typedef int LLVMBool; + +/* Opaque types. */ + +/** + * The top-level container for all LLVM global data. See the LLVMContext class. + */ +typedef struct LLVMOpaqueContext *LLVMContextRef; + +/** + * The top-level container for all other LLVM Intermediate Representation (IR) + * objects. See the llvm::Module class. + */ +typedef struct LLVMOpaqueModule *LLVMModuleRef; + +/** + * Each value in the LLVM IR has a type, an LLVMTypeRef. See the llvm::Type + * class. + */ +typedef struct LLVMOpaqueType *LLVMTypeRef; + +/** + * When building recursive types using LLVMRefineType, LLVMTypeRef values may + * become invalid; use LLVMTypeHandleRef to resolve this problem. See the + * llvm::AbstractTypeHolder class. + */ +typedef struct LLVMOpaqueTypeHandle *LLVMTypeHandleRef; + +typedef struct LLVMOpaqueValue *LLVMValueRef; +typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; +typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; + +/* Interface used to provide a module to JIT or interpreter. This is now just a + * synonym for llvm::Module, but we have to keep using the different type to + * keep binary compatibility. + */ +typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef; + +/* Used to provide a module to JIT or interpreter. + * See the llvm::MemoryBuffer class. + */ +typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; + +/** See the llvm::PassManagerBase class. */ +typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; + +/** See the llvm::PassRegistry class. */ +typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; + +/** Used to get the users and usees of a Value. See the llvm::Use class. */ +typedef struct LLVMOpaqueUse *LLVMUseRef; + +typedef enum { + LLVMZExtAttribute = 1<<0, + LLVMSExtAttribute = 1<<1, + LLVMNoReturnAttribute = 1<<2, + LLVMInRegAttribute = 1<<3, + LLVMStructRetAttribute = 1<<4, + LLVMNoUnwindAttribute = 1<<5, + LLVMNoAliasAttribute = 1<<6, + LLVMByValAttribute = 1<<7, + LLVMNestAttribute = 1<<8, + LLVMReadNoneAttribute = 1<<9, + LLVMReadOnlyAttribute = 1<<10, + LLVMNoInlineAttribute = 1<<11, + LLVMAlwaysInlineAttribute = 1<<12, + LLVMOptimizeForSizeAttribute = 1<<13, + LLVMStackProtectAttribute = 1<<14, + LLVMStackProtectReqAttribute = 1<<15, + LLVMAlignment = 31<<16, + LLVMNoCaptureAttribute = 1<<21, + LLVMNoRedZoneAttribute = 1<<22, + LLVMNoImplicitFloatAttribute = 1<<23, + LLVMNakedAttribute = 1<<24, + LLVMInlineHintAttribute = 1<<25, + LLVMStackAlignment = 7<<26 +} LLVMAttribute; + +typedef enum { + /* Terminator Instructions */ + LLVMRet = 1, + LLVMBr = 2, + LLVMSwitch = 3, + LLVMIndirectBr = 4, + LLVMInvoke = 5, + LLVMUnwind = 6, + LLVMUnreachable = 7, + + /* Standard Binary Operators */ + LLVMAdd = 8, + LLVMFAdd = 9, + LLVMSub = 10, + LLVMFSub = 11, + LLVMMul = 12, + LLVMFMul = 13, + LLVMUDiv = 14, + LLVMSDiv = 15, + LLVMFDiv = 16, + LLVMURem = 17, + LLVMSRem = 18, + LLVMFRem = 19, + + /* Logical Operators */ + LLVMShl = 20, + LLVMLShr = 21, + LLVMAShr = 22, + LLVMAnd = 23, + LLVMOr = 24, + LLVMXor = 25, + + /* Memory Operators */ + LLVMAlloca = 26, + LLVMLoad = 27, + LLVMStore = 28, + LLVMGetElementPtr = 29, + + /* Cast Operators */ + LLVMTrunc = 30, + LLVMZExt = 31, + LLVMSExt = 32, + LLVMFPToUI = 33, + LLVMFPToSI = 34, + LLVMUIToFP = 35, + LLVMSIToFP = 36, + LLVMFPTrunc = 37, + LLVMFPExt = 38, + LLVMPtrToInt = 39, + LLVMIntToPtr = 40, + LLVMBitCast = 41, + + /* Other Operators */ + LLVMICmp = 42, + LLVMFCmp = 43, + LLVMPHI = 44, + LLVMCall = 45, + LLVMSelect = 46, + /* UserOp1 */ + /* UserOp2 */ + LLVMVAArg = 49, + LLVMExtractElement = 50, + LLVMInsertElement = 51, + LLVMShuffleVector = 52, + LLVMExtractValue = 53, + LLVMInsertValue = 54 +} LLVMOpcode; + +typedef enum { + LLVMVoidTypeKind, /**< type with no size */ + LLVMFloatTypeKind, /**< 32 bit floating point type */ + LLVMDoubleTypeKind, /**< 64 bit floating point type */ + LLVMX86_FP80TypeKind, /**< 80 bit floating point type (X87) */ + LLVMFP128TypeKind, /**< 128 bit floating point type (112-bit mantissa)*/ + LLVMPPC_FP128TypeKind, /**< 128 bit floating point type (two 64-bits) */ + LLVMLabelTypeKind, /**< Labels */ + LLVMIntegerTypeKind, /**< Arbitrary bit width integers */ + LLVMFunctionTypeKind, /**< Functions */ + LLVMStructTypeKind, /**< Structures */ + LLVMArrayTypeKind, /**< Arrays */ + LLVMPointerTypeKind, /**< Pointers */ + LLVMOpaqueTypeKind, /**< Opaque: type with unknown structure */ + LLVMVectorTypeKind, /**< SIMD 'packed' format, or other vector type */ + LLVMMetadataTypeKind, /**< Metadata */ + LLVMX86_MMXTypeKind /**< X86 MMX */ +} LLVMTypeKind; + +typedef enum { + LLVMExternalLinkage, /**< Externally visible function */ + LLVMAvailableExternallyLinkage, + LLVMLinkOnceAnyLinkage, /**< Keep one copy of function when linking (inline)*/ + LLVMLinkOnceODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMWeakAnyLinkage, /**< Keep one copy of function when linking (weak) */ + LLVMWeakODRLinkage, /**< Same, but only replaced by something + equivalent. */ + LLVMAppendingLinkage, /**< Special purpose, only applies to global arrays */ + LLVMInternalLinkage, /**< Rename collisions when linking (static + functions) */ + LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */ + LLVMDLLImportLinkage, /**< Function to be imported from DLL */ + LLVMDLLExportLinkage, /**< Function to be accessible from DLL */ + LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */ + LLVMGhostLinkage, /**< Obsolete */ + LLVMCommonLinkage, /**< Tentative definitions */ + LLVMLinkerPrivateLinkage, /**< Like Private, but linker removes. */ + LLVMLinkerPrivateWeakLinkage, /**< Like LinkerPrivate, but is weak. */ + LLVMLinkerPrivateWeakDefAutoLinkage /**< Like LinkerPrivateWeak, but possibly + hidden. */ +} LLVMLinkage; + +typedef enum { + LLVMDefaultVisibility, /**< The GV is visible */ + LLVMHiddenVisibility, /**< The GV is hidden */ + LLVMProtectedVisibility /**< The GV is protected */ +} LLVMVisibility; + +typedef enum { + LLVMCCallConv = 0, + LLVMFastCallConv = 8, + LLVMColdCallConv = 9, + LLVMX86StdcallCallConv = 64, + LLVMX86FastcallCallConv = 65 +} LLVMCallConv; + +typedef enum { + LLVMIntEQ = 32, /**< equal */ + LLVMIntNE, /**< not equal */ + LLVMIntUGT, /**< unsigned greater than */ + LLVMIntUGE, /**< unsigned greater or equal */ + LLVMIntULT, /**< unsigned less than */ + LLVMIntULE, /**< unsigned less or equal */ + LLVMIntSGT, /**< signed greater than */ + LLVMIntSGE, /**< signed greater or equal */ + LLVMIntSLT, /**< signed less than */ + LLVMIntSLE /**< signed less or equal */ +} LLVMIntPredicate; + +typedef enum { + LLVMRealPredicateFalse, /**< Always false (always folded) */ + LLVMRealOEQ, /**< True if ordered and equal */ + LLVMRealOGT, /**< True if ordered and greater than */ + LLVMRealOGE, /**< True if ordered and greater than or equal */ + LLVMRealOLT, /**< True if ordered and less than */ + LLVMRealOLE, /**< True if ordered and less than or equal */ + LLVMRealONE, /**< True if ordered and operands are unequal */ + LLVMRealORD, /**< True if ordered (no nans) */ + LLVMRealUNO, /**< True if unordered: isnan(X) | isnan(Y) */ + LLVMRealUEQ, /**< True if unordered or equal */ + LLVMRealUGT, /**< True if unordered or greater than */ + LLVMRealUGE, /**< True if unordered, greater than, or equal */ + LLVMRealULT, /**< True if unordered or less than */ + LLVMRealULE, /**< True if unordered, less than, or equal */ + LLVMRealUNE, /**< True if unordered or not equal */ + LLVMRealPredicateTrue /**< Always true (always folded) */ +} LLVMRealPredicate; + + +/*===-- Error handling ----------------------------------------------------===*/ + +void LLVMDisposeMessage(char *Message); + + +/*===-- Contexts ----------------------------------------------------------===*/ + +/* Create and destroy contexts. */ +LLVMContextRef LLVMContextCreate(void); +LLVMContextRef LLVMGetGlobalContext(void); +void LLVMContextDispose(LLVMContextRef C); + +unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name, + unsigned SLen); +unsigned LLVMGetMDKindID(const char* Name, unsigned SLen); + +/*===-- Modules -----------------------------------------------------------===*/ + +/* Create and destroy modules. */ +/** See llvm::Module::Module. */ +LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); +LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, + LLVMContextRef C); + +/** See llvm::Module::~Module. */ +void LLVMDisposeModule(LLVMModuleRef M); + +/** Data layout. See Module::getDataLayout. */ +const char *LLVMGetDataLayout(LLVMModuleRef M); +void LLVMSetDataLayout(LLVMModuleRef M, const char *Triple); + +/** Target triple. See Module::getTargetTriple. */ +const char *LLVMGetTarget(LLVMModuleRef M); +void LLVMSetTarget(LLVMModuleRef M, const char *Triple); + +/** See Module::addTypeName. */ +LLVMBool LLVMAddTypeName(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty); +void LLVMDeleteTypeName(LLVMModuleRef M, const char *Name); +LLVMTypeRef LLVMGetTypeByName(LLVMModuleRef M, const char *Name); +const char *LLVMGetTypeName(LLVMModuleRef M, LLVMTypeRef Ty); + +/** See Module::dump. */ +void LLVMDumpModule(LLVMModuleRef M); + +/** See Module::setModuleInlineAsm. */ +void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm); + +/** See Module::getContext. */ +LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M); + +/*===-- Types -------------------------------------------------------------===*/ + +/* LLVM types conform to the following hierarchy: + * + * types: + * integer type + * real type + * function type + * sequence types: + * array type + * pointer type + * vector type + * void type + * label type + * opaque type + */ + +/** See llvm::LLVMTypeKind::getTypeID. */ +LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty); + +/** See llvm::LLVMType::getContext. */ +LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); + +/* Operations on integer types */ +LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt8TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt16TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt32TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMInt64TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMIntTypeInContext(LLVMContextRef C, unsigned NumBits); + +LLVMTypeRef LLVMInt1Type(void); +LLVMTypeRef LLVMInt8Type(void); +LLVMTypeRef LLVMInt16Type(void); +LLVMTypeRef LLVMInt32Type(void); +LLVMTypeRef LLVMInt64Type(void); +LLVMTypeRef LLVMIntType(unsigned NumBits); +unsigned LLVMGetIntTypeWidth(LLVMTypeRef IntegerTy); + +/* Operations on real types */ +LLVMTypeRef LLVMFloatTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMDoubleTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMX86FP80TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMFP128TypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C); + +LLVMTypeRef LLVMFloatType(void); +LLVMTypeRef LLVMDoubleType(void); +LLVMTypeRef LLVMX86FP80Type(void); +LLVMTypeRef LLVMFP128Type(void); +LLVMTypeRef LLVMPPCFP128Type(void); + +/* Operations on function types */ +LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, + LLVMTypeRef *ParamTypes, unsigned ParamCount, + LLVMBool IsVarArg); +LLVMBool LLVMIsFunctionVarArg(LLVMTypeRef FunctionTy); +LLVMTypeRef LLVMGetReturnType(LLVMTypeRef FunctionTy); +unsigned LLVMCountParamTypes(LLVMTypeRef FunctionTy); +void LLVMGetParamTypes(LLVMTypeRef FunctionTy, LLVMTypeRef *Dest); + +/* Operations on struct types */ +LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, + unsigned ElementCount, LLVMBool Packed); +LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount, + LLVMBool Packed); +unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy); +void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest); +LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy); + +/* Operations on array, pointer, and vector types (sequence types) */ +LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount); +LLVMTypeRef LLVMPointerType(LLVMTypeRef ElementType, unsigned AddressSpace); +LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount); + +LLVMTypeRef LLVMGetElementType(LLVMTypeRef Ty); +unsigned LLVMGetArrayLength(LLVMTypeRef ArrayTy); +unsigned LLVMGetPointerAddressSpace(LLVMTypeRef PointerTy); +unsigned LLVMGetVectorSize(LLVMTypeRef VectorTy); + +/* Operations on other types */ +LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMOpaqueTypeInContext(LLVMContextRef C); +LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C); + +LLVMTypeRef LLVMVoidType(void); +LLVMTypeRef LLVMLabelType(void); +LLVMTypeRef LLVMOpaqueType(void); +LLVMTypeRef LLVMX86MMXType(void); + +/* Operations on type handles */ +LLVMTypeHandleRef LLVMCreateTypeHandle(LLVMTypeRef PotentiallyAbstractTy); +void LLVMRefineType(LLVMTypeRef AbstractTy, LLVMTypeRef ConcreteTy); +LLVMTypeRef LLVMResolveTypeHandle(LLVMTypeHandleRef TypeHandle); +void LLVMDisposeTypeHandle(LLVMTypeHandleRef TypeHandle); + + +/*===-- Values ------------------------------------------------------------===*/ + +/* The bulk of LLVM's object model consists of values, which comprise a very + * rich type hierarchy. + */ + +#define LLVM_FOR_EACH_VALUE_SUBCLASS(macro) \ + macro(Argument) \ + macro(BasicBlock) \ + macro(InlineAsm) \ + macro(User) \ + macro(Constant) \ + macro(ConstantAggregateZero) \ + macro(ConstantArray) \ + macro(ConstantExpr) \ + macro(ConstantFP) \ + macro(ConstantInt) \ + macro(ConstantPointerNull) \ + macro(ConstantStruct) \ + macro(ConstantVector) \ + macro(GlobalValue) \ + macro(Function) \ + macro(GlobalAlias) \ + macro(GlobalVariable) \ + macro(UndefValue) \ + macro(Instruction) \ + macro(BinaryOperator) \ + macro(CallInst) \ + macro(IntrinsicInst) \ + macro(DbgInfoIntrinsic) \ + macro(DbgDeclareInst) \ + macro(EHSelectorInst) \ + macro(MemIntrinsic) \ + macro(MemCpyInst) \ + macro(MemMoveInst) \ + macro(MemSetInst) \ + macro(CmpInst) \ + macro(FCmpInst) \ + macro(ICmpInst) \ + macro(ExtractElementInst) \ + macro(GetElementPtrInst) \ + macro(InsertElementInst) \ + macro(InsertValueInst) \ + macro(PHINode) \ + macro(SelectInst) \ + macro(ShuffleVectorInst) \ + macro(StoreInst) \ + macro(TerminatorInst) \ + macro(BranchInst) \ + macro(InvokeInst) \ + macro(ReturnInst) \ + macro(SwitchInst) \ + macro(UnreachableInst) \ + macro(UnwindInst) \ + macro(UnaryInstruction) \ + macro(AllocaInst) \ + macro(CastInst) \ + macro(BitCastInst) \ + macro(FPExtInst) \ + macro(FPToSIInst) \ + macro(FPToUIInst) \ + macro(FPTruncInst) \ + macro(IntToPtrInst) \ + macro(PtrToIntInst) \ + macro(SExtInst) \ + macro(SIToFPInst) \ + macro(TruncInst) \ + macro(UIToFPInst) \ + macro(ZExtInst) \ + macro(ExtractValueInst) \ + macro(LoadInst) \ + macro(VAArgInst) + +/* Operations on all values */ +LLVMTypeRef LLVMTypeOf(LLVMValueRef Val); +const char *LLVMGetValueName(LLVMValueRef Val); +void LLVMSetValueName(LLVMValueRef Val, const char *Name); +void LLVMDumpValue(LLVMValueRef Val); +void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal); +int LLVMHasMetadata(LLVMValueRef Val); +LLVMValueRef LLVMGetMetadata(LLVMValueRef Val, unsigned KindID); +void LLVMSetMetadata(LLVMValueRef Val, unsigned KindID, LLVMValueRef Node); + +/* Conversion functions. Return the input value if it is an instance of the + specified class, otherwise NULL. See llvm::dyn_cast_or_null<>. */ +#define LLVM_DECLARE_VALUE_CAST(name) \ + LLVMValueRef LLVMIsA##name(LLVMValueRef Val); +LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) + +/* Operations on Uses */ +LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val); +LLVMUseRef LLVMGetNextUse(LLVMUseRef U); +LLVMValueRef LLVMGetUser(LLVMUseRef U); +LLVMValueRef LLVMGetUsedValue(LLVMUseRef U); + +/* Operations on Users */ +LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index); +void LLVMSetOperand(LLVMValueRef User, unsigned Index, LLVMValueRef Val); +int LLVMGetNumOperands(LLVMValueRef Val); + +/* Operations on constants of any type */ +LLVMValueRef LLVMConstNull(LLVMTypeRef Ty); /* all zeroes */ +LLVMValueRef LLVMConstAllOnes(LLVMTypeRef Ty); /* only for int/vector */ +LLVMValueRef LLVMGetUndef(LLVMTypeRef Ty); +LLVMBool LLVMIsConstant(LLVMValueRef Val); +LLVMBool LLVMIsNull(LLVMValueRef Val); +LLVMBool LLVMIsUndef(LLVMValueRef Val); +LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty); + +/* Operations on metadata */ +LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, + unsigned SLen); +LLVMValueRef LLVMMDString(const char *Str, unsigned SLen); +LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, + unsigned Count); +LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); + +/* Operations on scalar constants */ +LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, + LLVMBool SignExtend); +LLVMValueRef LLVMConstIntOfArbitraryPrecision(LLVMTypeRef IntTy, + unsigned NumWords, + const uint64_t Words[]); +LLVMValueRef LLVMConstIntOfString(LLVMTypeRef IntTy, const char *Text, + uint8_t Radix); +LLVMValueRef LLVMConstIntOfStringAndSize(LLVMTypeRef IntTy, const char *Text, + unsigned SLen, uint8_t Radix); +LLVMValueRef LLVMConstReal(LLVMTypeRef RealTy, double N); +LLVMValueRef LLVMConstRealOfString(LLVMTypeRef RealTy, const char *Text); +LLVMValueRef LLVMConstRealOfStringAndSize(LLVMTypeRef RealTy, const char *Text, + unsigned SLen); +unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal); +long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal); + + +/* Operations on composite constants */ +LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, + unsigned Length, LLVMBool DontNullTerminate); +LLVMValueRef LLVMConstStructInContext(LLVMContextRef C, + LLVMValueRef *ConstantVals, + unsigned Count, LLVMBool Packed); + +LLVMValueRef LLVMConstString(const char *Str, unsigned Length, + LLVMBool DontNullTerminate); +LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, + LLVMValueRef *ConstantVals, unsigned Length); +LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, + LLVMBool Packed); +LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size); + +/* Constant expressions */ +LLVMOpcode LLVMGetConstOpcode(LLVMValueRef ConstantVal); +LLVMValueRef LLVMAlignOf(LLVMTypeRef Ty); +LLVMValueRef LLVMSizeOf(LLVMTypeRef Ty); +LLVMValueRef LLVMConstNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNSWNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstFNeg(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstNot(LLVMValueRef ConstantVal); +LLVMValueRef LLVMConstAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNSWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstNUWMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstUDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstExactSDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFDiv(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstURem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstSRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFRem(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAnd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstOr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstXor(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstICmp(LLVMIntPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstFCmp(LLVMRealPredicate Predicate, + LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstShl(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); +LLVMValueRef LLVMConstGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, unsigned NumIndices); +LLVMValueRef LLVMConstInBoundsGEP(LLVMValueRef ConstantVal, + LLVMValueRef *ConstantIndices, + unsigned NumIndices); +LLVMValueRef LLVMConstTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPTrunc(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPExt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstUIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSIToFP(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToUI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstFPToSI(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstPtrToInt(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntToPtr(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstSExtOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstTruncOrBitCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstPointerCast(LLVMValueRef ConstantVal, + LLVMTypeRef ToType); +LLVMValueRef LLVMConstIntCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType, + LLVMBool isSigned); +LLVMValueRef LLVMConstFPCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType); +LLVMValueRef LLVMConstSelect(LLVMValueRef ConstantCondition, + LLVMValueRef ConstantIfTrue, + LLVMValueRef ConstantIfFalse); +LLVMValueRef LLVMConstExtractElement(LLVMValueRef VectorConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstInsertElement(LLVMValueRef VectorConstant, + LLVMValueRef ElementValueConstant, + LLVMValueRef IndexConstant); +LLVMValueRef LLVMConstShuffleVector(LLVMValueRef VectorAConstant, + LLVMValueRef VectorBConstant, + LLVMValueRef MaskConstant); +LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, + unsigned NumIdx); +LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant, + LLVMValueRef ElementValueConstant, + unsigned *IdxList, unsigned NumIdx); +LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, + const char *AsmString, const char *Constraints, + LLVMBool HasSideEffects, LLVMBool IsAlignStack); +LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB); + +/* Operations on global variables, functions, and aliases (globals) */ +LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global); +LLVMBool LLVMIsDeclaration(LLVMValueRef Global); +LLVMLinkage LLVMGetLinkage(LLVMValueRef Global); +void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage); +const char *LLVMGetSection(LLVMValueRef Global); +void LLVMSetSection(LLVMValueRef Global, const char *Section); +LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); +void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); +unsigned LLVMGetAlignment(LLVMValueRef Global); +void LLVMSetAlignment(LLVMValueRef Global, unsigned Bytes); + +/* Operations on global variables */ +LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMAddGlobalInAddressSpace(LLVMModuleRef M, LLVMTypeRef Ty, + const char *Name, + unsigned AddressSpace); +LLVMValueRef LLVMGetNamedGlobal(LLVMModuleRef M, const char *Name); +LLVMValueRef LLVMGetFirstGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetLastGlobal(LLVMModuleRef M); +LLVMValueRef LLVMGetNextGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetPreviousGlobal(LLVMValueRef GlobalVar); +void LLVMDeleteGlobal(LLVMValueRef GlobalVar); +LLVMValueRef LLVMGetInitializer(LLVMValueRef GlobalVar); +void LLVMSetInitializer(LLVMValueRef GlobalVar, LLVMValueRef ConstantVal); +LLVMBool LLVMIsThreadLocal(LLVMValueRef GlobalVar); +void LLVMSetThreadLocal(LLVMValueRef GlobalVar, LLVMBool IsThreadLocal); +LLVMBool LLVMIsGlobalConstant(LLVMValueRef GlobalVar); +void LLVMSetGlobalConstant(LLVMValueRef GlobalVar, LLVMBool IsConstant); + +/* Operations on aliases */ +LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, + const char *Name); + +/* Operations on functions */ +LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, + LLVMTypeRef FunctionTy); +LLVMValueRef LLVMGetNamedFunction(LLVMModuleRef M, const char *Name); +LLVMValueRef LLVMGetFirstFunction(LLVMModuleRef M); +LLVMValueRef LLVMGetLastFunction(LLVMModuleRef M); +LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn); +LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn); +void LLVMDeleteFunction(LLVMValueRef Fn); +unsigned LLVMGetIntrinsicID(LLVMValueRef Fn); +unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn); +void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC); +const char *LLVMGetGC(LLVMValueRef Fn); +void LLVMSetGC(LLVMValueRef Fn, const char *Name); +void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); +LLVMAttribute LLVMGetFunctionAttr(LLVMValueRef Fn); +void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); + +/* Operations on parameters */ +unsigned LLVMCountParams(LLVMValueRef Fn); +void LLVMGetParams(LLVMValueRef Fn, LLVMValueRef *Params); +LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); +LLVMValueRef LLVMGetParamParent(LLVMValueRef Inst); +LLVMValueRef LLVMGetFirstParam(LLVMValueRef Fn); +LLVMValueRef LLVMGetLastParam(LLVMValueRef Fn); +LLVMValueRef LLVMGetNextParam(LLVMValueRef Arg); +LLVMValueRef LLVMGetPreviousParam(LLVMValueRef Arg); +void LLVMAddAttribute(LLVMValueRef Arg, LLVMAttribute PA); +void LLVMRemoveAttribute(LLVMValueRef Arg, LLVMAttribute PA); +LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg); +void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align); + +/* Operations on basic blocks */ +LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB); +LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); +LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); +LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); +unsigned LLVMCountBasicBlocks(LLVMValueRef Fn); +void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks); +LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn); +LLVMBasicBlockRef LLVMGetLastBasicBlock(LLVMValueRef Fn); +LLVMBasicBlockRef LLVMGetNextBasicBlock(LLVMBasicBlockRef BB); +LLVMBasicBlockRef LLVMGetPreviousBasicBlock(LLVMBasicBlockRef BB); +LLVMBasicBlockRef LLVMGetEntryBasicBlock(LLVMValueRef Fn); + +LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C, + LLVMValueRef Fn, + const char *Name); +LLVMBasicBlockRef LLVMInsertBasicBlockInContext(LLVMContextRef C, + LLVMBasicBlockRef BB, + const char *Name); + +LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name); +LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB, + const char *Name); +void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB); + +void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); +void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); + +/* Operations on instructions */ +LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst); +LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); +LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); +LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); +LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst); + +/* Operations on call sites */ +void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); +unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr); +void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index, LLVMAttribute); +void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index, + LLVMAttribute); +void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, + unsigned align); + +/* Operations on call instructions (only) */ +LLVMBool LLVMIsTailCall(LLVMValueRef CallInst); +void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); + +/* Operations on phi nodes */ +void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, + LLVMBasicBlockRef *IncomingBlocks, unsigned Count); +unsigned LLVMCountIncoming(LLVMValueRef PhiNode); +LLVMValueRef LLVMGetIncomingValue(LLVMValueRef PhiNode, unsigned Index); +LLVMBasicBlockRef LLVMGetIncomingBlock(LLVMValueRef PhiNode, unsigned Index); + +/*===-- Instruction builders ----------------------------------------------===*/ + +/* An instruction builder represents a point within a basic block, and is the + * exclusive means of building instructions using the C interface. + */ + +LLVMBuilderRef LLVMCreateBuilderInContext(LLVMContextRef C); +LLVMBuilderRef LLVMCreateBuilder(void); +void LLVMPositionBuilder(LLVMBuilderRef Builder, LLVMBasicBlockRef Block, + LLVMValueRef Instr); +void LLVMPositionBuilderBefore(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMPositionBuilderAtEnd(LLVMBuilderRef Builder, LLVMBasicBlockRef Block); +LLVMBasicBlockRef LLVMGetInsertBlock(LLVMBuilderRef Builder); +void LLVMClearInsertionPosition(LLVMBuilderRef Builder); +void LLVMInsertIntoBuilder(LLVMBuilderRef Builder, LLVMValueRef Instr); +void LLVMInsertIntoBuilderWithName(LLVMBuilderRef Builder, LLVMValueRef Instr, + const char *Name); +void LLVMDisposeBuilder(LLVMBuilderRef Builder); + +/* Metadata */ +void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L); +LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder); +void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst); + +/* Terminators */ +LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef); +LLVMValueRef LLVMBuildRet(LLVMBuilderRef, LLVMValueRef V); +LLVMValueRef LLVMBuildAggregateRet(LLVMBuilderRef, LLVMValueRef *RetVals, + unsigned N); +LLVMValueRef LLVMBuildBr(LLVMBuilderRef, LLVMBasicBlockRef Dest); +LLVMValueRef LLVMBuildCondBr(LLVMBuilderRef, LLVMValueRef If, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Else); +LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef, LLVMValueRef V, + LLVMBasicBlockRef Else, unsigned NumCases); +LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, + unsigned NumDests); +LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, + const char *Name); +LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef); +LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); + +/* Add a case to the switch instruction */ +void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, + LLVMBasicBlockRef Dest); + +/* Add a destination to the indirectbr instruction */ +void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest); + +/* Arithmetic */ +LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFSub(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNSWMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNUWMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFMul(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildUDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildExactSDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFDiv(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildURem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildSRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFRem(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildShl(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildLShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAShr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildAnd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildOr(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildXor(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildBinOp(LLVMBuilderRef B, LLVMOpcode Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildNSWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name); +LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name); +LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); +LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name); + +/* Memory */ +LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); +LLVMValueRef LLVMBuildAlloca(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildArrayAlloca(LLVMBuilderRef, LLVMTypeRef Ty, + LLVMValueRef Val, const char *Name); +LLVMValueRef LLVMBuildFree(LLVMBuilderRef, LLVMValueRef PointerVal); +LLVMValueRef LLVMBuildLoad(LLVMBuilderRef, LLVMValueRef PointerVal, + const char *Name); +LLVMValueRef LLVMBuildStore(LLVMBuilderRef, LLVMValueRef Val, LLVMValueRef Ptr); +LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildInBoundsGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + LLVMValueRef *Indices, unsigned NumIndices, + const char *Name); +LLVMValueRef LLVMBuildStructGEP(LLVMBuilderRef B, LLVMValueRef Pointer, + unsigned Idx, const char *Name); +LLVMValueRef LLVMBuildGlobalString(LLVMBuilderRef B, const char *Str, + const char *Name); +LLVMValueRef LLVMBuildGlobalStringPtr(LLVMBuilderRef B, const char *Str, + const char *Name); + +/* Casts */ +LLVMValueRef LLVMBuildTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToUI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPToSI(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildUIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSIToFP(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPTrunc(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPExt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPtrToInt(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntToPtr(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildSExtOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildTruncOrBitCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildIntCast(LLVMBuilderRef, LLVMValueRef Val, /*Signed cast!*/ + LLVMTypeRef DestTy, const char *Name); +LLVMValueRef LLVMBuildFPCast(LLVMBuilderRef, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name); + +/* Comparisons */ +LLVMValueRef LLVMBuildICmp(LLVMBuilderRef, LLVMIntPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); +LLVMValueRef LLVMBuildFCmp(LLVMBuilderRef, LLVMRealPredicate Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name); + +/* Miscellaneous instructions */ +LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name); +LLVMValueRef LLVMBuildCall(LLVMBuilderRef, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If, + LLVMValueRef Then, LLVMValueRef Else, + const char *Name); +LLVMValueRef LLVMBuildVAArg(LLVMBuilderRef, LLVMValueRef List, LLVMTypeRef Ty, + const char *Name); +LLVMValueRef LLVMBuildExtractElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef Index, const char *Name); +LLVMValueRef LLVMBuildInsertElement(LLVMBuilderRef, LLVMValueRef VecVal, + LLVMValueRef EltVal, LLVMValueRef Index, + const char *Name); +LLVMValueRef LLVMBuildShuffleVector(LLVMBuilderRef, LLVMValueRef V1, + LLVMValueRef V2, LLVMValueRef Mask, + const char *Name); +LLVMValueRef LLVMBuildExtractValue(LLVMBuilderRef, LLVMValueRef AggVal, + unsigned Index, const char *Name); +LLVMValueRef LLVMBuildInsertValue(LLVMBuilderRef, LLVMValueRef AggVal, + LLVMValueRef EltVal, unsigned Index, + const char *Name); + +LLVMValueRef LLVMBuildIsNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, + const char *Name); +LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, + LLVMValueRef RHS, const char *Name); + + +/*===-- Module providers --------------------------------------------------===*/ + +/* Changes the type of M so it can be passed to FunctionPassManagers and the + * JIT. They take ModuleProviders for historical reasons. + */ +LLVMModuleProviderRef +LLVMCreateModuleProviderForExistingModule(LLVMModuleRef M); + +/* Destroys the module M. + */ +void LLVMDisposeModuleProvider(LLVMModuleProviderRef M); + + +/*===-- Memory buffers ----------------------------------------------------===*/ + +LLVMBool LLVMCreateMemoryBufferWithContentsOfFile(const char *Path, + LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf, + char **OutMessage); +void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); + +/*===-- Pass Registry -----------------------------------------------------===*/ + +/** Return the global pass registry, for use with initialization functions. + See llvm::PassRegistry::getPassRegistry. */ +LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void); + +/*===-- Pass Managers -----------------------------------------------------===*/ + +/** Constructs a new whole-module pass pipeline. This type of pipeline is + suitable for link-time optimization and whole-module transformations. + See llvm::PassManager::PassManager. */ +LLVMPassManagerRef LLVMCreatePassManager(void); + +/** Constructs a new function-by-function pass pipeline over the module + provider. It does not take ownership of the module provider. This type of + pipeline is suitable for code generation and JIT compilation tasks. + See llvm::FunctionPassManager::FunctionPassManager. */ +LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef M); + +/** Deprecated: Use LLVMCreateFunctionPassManagerForModule instead. */ +LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef MP); + +/** Initializes, executes on the provided module, and finalizes all of the + passes scheduled in the pass manager. Returns 1 if any of the passes + modified the module, 0 otherwise. See llvm::PassManager::run(Module&). */ +LLVMBool LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M); + +/** Initializes all of the function passes scheduled in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + See llvm::FunctionPassManager::doInitialization. */ +LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Executes all of the function passes scheduled in the function pass manager + on the provided function. Returns 1 if any of the passes modified the + function, false otherwise. + See llvm::FunctionPassManager::run(Function&). */ +LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F); + +/** Finalizes all of the function passes scheduled in in the function pass + manager. Returns 1 if any of the passes modified the module, 0 otherwise. + See llvm::FunctionPassManager::doFinalization. */ +LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM); + +/** Frees the memory of a pass pipeline. For function pipelines, does not free + the module provider. + See llvm::PassManagerBase::~PassManagerBase. */ +void LLVMDisposePassManager(LLVMPassManagerRef PM); + + +#ifdef __cplusplus +} + +namespace llvm { + class MemoryBuffer; + class PassManagerBase; + + #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast(const_cast(P)); \ + } + + #define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template \ + inline T *unwrap(ref P) { \ + return cast(unwrap(P)); \ + } + + #define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template \ + inline T *unwrap(ref P) { \ + T *Q = (T*)unwrap(P); \ + assert(Q && "Invalid cast!"); \ + return Q; \ + } + + DEFINE_ISA_CONVERSION_FUNCTIONS (Type, LLVMTypeRef ) + DEFINE_ISA_CONVERSION_FUNCTIONS (Value, LLVMValueRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(PATypeHolder, LLVMTypeHandleRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef ) + DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef ) + DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassRegistry, LLVMPassRegistryRef ) + /* LLVMModuleProviderRef exists for historical reasons, but now just holds a + * Module. + */ + inline Module *unwrap(LLVMModuleProviderRef MP) { + return reinterpret_cast(MP); + } + + #undef DEFINE_STDCXX_CONVERSION_FUNCTIONS + #undef DEFINE_ISA_CONVERSION_FUNCTIONS + #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS + + /* Specialized opaque context conversions. + */ + inline LLVMContext **unwrap(LLVMContextRef* Tys) { + return reinterpret_cast(Tys); + } + + inline LLVMContextRef *wrap(const LLVMContext **Tys) { + return reinterpret_cast(const_cast(Tys)); + } + + /* Specialized opaque type conversions. + */ + inline Type **unwrap(LLVMTypeRef* Tys) { + return reinterpret_cast(Tys); + } + + inline LLVMTypeRef *wrap(const Type **Tys) { + return reinterpret_cast(const_cast(Tys)); + } + + /* Specialized opaque value conversions. + */ + inline Value **unwrap(LLVMValueRef *Vals) { + return reinterpret_cast(Vals); + } + + template + inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { + #if DEBUG + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) + cast(*I); + #endif + return reinterpret_cast(Vals); + } + + inline LLVMValueRef *wrap(const Value **Vals) { + return reinterpret_cast(const_cast(Vals)); + } +} + +#endif /* !defined(__cplusplus) */ + +#endif /* !defined(LLVM_C_CORE_H) */ diff --git a/final/include/llvm-c/EnhancedDisassembly.h b/final/include/llvm-c/EnhancedDisassembly.h new file mode 100644 index 00000000000..28ac0ed2ab3 --- /dev/null +++ b/final/include/llvm-c/EnhancedDisassembly.h @@ -0,0 +1,513 @@ +/*===-- llvm-c/EnhancedDisassembly.h - Disassembler C Interface ---*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to EnhancedDisassembly.so, which *| +|* implements a disassembler with the ability to extract operand values and *| +|* individual tokens from assembly instructions. *| +|* *| +|* The header declares additional interfaces if the host compiler supports *| +|* the blocks API. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_ENHANCEDDISASSEMBLY_H +#define LLVM_C_ENHANCEDDISASSEMBLY_H + +#include "llvm/Support/DataTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @typedef EDByteReaderCallback + Interface to memory from which instructions may be read. + @param byte A pointer whose target should be filled in with the data returned. + @param address The address of the byte to be read. + @param arg An anonymous argument for client use. + @result 0 on success; -1 otherwise. + */ +typedef int (*EDByteReaderCallback)(uint8_t *byte, uint64_t address, void *arg); + +/*! + @typedef EDRegisterReaderCallback + Interface to registers from which registers may be read. + @param value A pointer whose target should be filled in with the value of the + register. + @param regID The LLVM register identifier for the register to read. + @param arg An anonymous argument for client use. + @result 0 if the register could be read; -1 otherwise. + */ +typedef int (*EDRegisterReaderCallback)(uint64_t *value, unsigned regID, + void* arg); + +/*! + @typedef EDAssemblySyntax_t + An assembly syntax for use in tokenizing instructions. + */ +enum { +/*! @constant kEDAssemblySyntaxX86Intel Intel syntax for i386 and x86_64. */ + kEDAssemblySyntaxX86Intel = 0, +/*! @constant kEDAssemblySyntaxX86ATT AT&T syntax for i386 and x86_64. */ + kEDAssemblySyntaxX86ATT = 1, + kEDAssemblySyntaxARMUAL = 2 +}; +typedef unsigned EDAssemblySyntax_t; + +/*! + @typedef EDDisassemblerRef + Encapsulates a disassembler for a single CPU architecture. + */ +typedef void *EDDisassemblerRef; + +/*! + @typedef EDInstRef + Encapsulates a single disassembled instruction in one assembly syntax. + */ +typedef void *EDInstRef; + +/*! + @typedef EDTokenRef + Encapsulates a token from the disassembly of an instruction. + */ +typedef void *EDTokenRef; + +/*! + @typedef EDOperandRef + Encapsulates an operand of an instruction. + */ +typedef void *EDOperandRef; + +/*! + @functiongroup Getting a disassembler + */ + +/*! + @function EDGetDisassembler + Gets the disassembler for a given target. + @param disassembler A pointer whose target will be filled in with the + disassembler. + @param triple Identifies the target. Example: "x86_64-apple-darwin10" + @param syntax The assembly syntax to use when decoding instructions. + @result 0 on success; -1 otherwise. + */ +int EDGetDisassembler(EDDisassemblerRef *disassembler, + const char *triple, + EDAssemblySyntax_t syntax); + +/*! + @functiongroup Generic architectural queries + */ + +/*! + @function EDGetRegisterName + Gets the human-readable name for a given register. + @param regName A pointer whose target will be pointed at the name of the + register. The name does not need to be deallocated and will be + @param disassembler The disassembler to query for the name. + @param regID The register identifier, as returned by EDRegisterTokenValue. + @result 0 on success; -1 otherwise. + */ +int EDGetRegisterName(const char** regName, + EDDisassemblerRef disassembler, + unsigned regID); + +/*! + @function EDRegisterIsStackPointer + Determines if a register is one of the platform's stack-pointer registers. + @param disassembler The disassembler to query. + @param regID The register identifier, as returned by EDRegisterTokenValue. + @result 1 if true; 0 otherwise. + */ +int EDRegisterIsStackPointer(EDDisassemblerRef disassembler, + unsigned regID); + +/*! + @function EDRegisterIsProgramCounter + Determines if a register is one of the platform's stack-pointer registers. + @param disassembler The disassembler to query. + @param regID The register identifier, as returned by EDRegisterTokenValue. + @result 1 if true; 0 otherwise. + */ +int EDRegisterIsProgramCounter(EDDisassemblerRef disassembler, + unsigned regID); + +/*! + @functiongroup Creating and querying instructions + */ + +/*! + @function EDCreateInst + Gets a set of contiguous instructions from a disassembler. + @param insts A pointer to an array that will be filled in with the + instructions. Must have at least count entries. Entries not filled in will + be set to NULL. + @param count The maximum number of instructions to fill in. + @param disassembler The disassembler to use when decoding the instructions. + @param byteReader The function to use when reading the instruction's machine + code. + @param address The address of the first byte of the instruction. + @param arg An anonymous argument to be passed to byteReader. + @result The number of instructions read on success; 0 otherwise. + */ +unsigned int EDCreateInsts(EDInstRef *insts, + unsigned int count, + EDDisassemblerRef disassembler, + EDByteReaderCallback byteReader, + uint64_t address, + void *arg); + +/*! + @function EDReleaseInst + Frees the memory for an instruction. The instruction can no longer be accessed + after this call. + @param inst The instruction to be freed. + */ +void EDReleaseInst(EDInstRef inst); + +/*! + @function EDInstByteSize + @param inst The instruction to be queried. + @result The number of bytes in the instruction's machine-code representation. + */ +int EDInstByteSize(EDInstRef inst); + +/*! + @function EDGetInstString + Gets the disassembled text equivalent of the instruction. + @param buf A pointer whose target will be filled in with a pointer to the + string. (The string becomes invalid when the instruction is released.) + @param inst The instruction to be queried. + @result 0 on success; -1 otherwise. + */ +int EDGetInstString(const char **buf, + EDInstRef inst); + +/*! + @function EDInstID + @param instID A pointer whose target will be filled in with the LLVM identifier + for the instruction. + @param inst The instruction to be queried. + @result 0 on success; -1 otherwise. + */ +int EDInstID(unsigned *instID, EDInstRef inst); + +/*! + @function EDInstIsBranch + @param inst The instruction to be queried. + @result 1 if the instruction is a branch instruction; 0 if it is some other + type of instruction; -1 if there was an error. + */ +int EDInstIsBranch(EDInstRef inst); + +/*! + @function EDInstIsMove + @param inst The instruction to be queried. + @result 1 if the instruction is a move instruction; 0 if it is some other + type of instruction; -1 if there was an error. + */ +int EDInstIsMove(EDInstRef inst); + +/*! + @function EDBranchTargetID + @param inst The instruction to be queried. + @result The ID of the branch target operand, suitable for use with + EDCopyOperand. -1 if no such operand exists. + */ +int EDBranchTargetID(EDInstRef inst); + +/*! + @function EDMoveSourceID + @param inst The instruction to be queried. + @result The ID of the move source operand, suitable for use with + EDCopyOperand. -1 if no such operand exists. + */ +int EDMoveSourceID(EDInstRef inst); + +/*! + @function EDMoveTargetID + @param inst The instruction to be queried. + @result The ID of the move source operand, suitable for use with + EDCopyOperand. -1 if no such operand exists. + */ +int EDMoveTargetID(EDInstRef inst); + +/*! + @functiongroup Creating and querying tokens + */ + +/*! + @function EDNumTokens + @param inst The instruction to be queried. + @result The number of tokens in the instruction, or -1 on error. + */ +int EDNumTokens(EDInstRef inst); + +/*! + @function EDGetToken + Retrieves a token from an instruction. The token is valid until the + instruction is released. + @param token A pointer to be filled in with the token. + @param inst The instruction to be queried. + @param index The index of the token in the instruction. + @result 0 on success; -1 otherwise. + */ +int EDGetToken(EDTokenRef *token, + EDInstRef inst, + int index); + +/*! + @function EDGetTokenString + Gets the disassembled text for a token. + @param buf A pointer whose target will be filled in with a pointer to the + string. (The string becomes invalid when the token is released.) + @param token The token to be queried. + @result 0 on success; -1 otherwise. + */ +int EDGetTokenString(const char **buf, + EDTokenRef token); + +/*! + @function EDOperandIndexForToken + Returns the index of the operand to which a token belongs. + @param token The token to be queried. + @result The operand index on success; -1 otherwise + */ +int EDOperandIndexForToken(EDTokenRef token); + +/*! + @function EDTokenIsWhitespace + @param token The token to be queried. + @result 1 if the token is whitespace; 0 if not; -1 on error. + */ +int EDTokenIsWhitespace(EDTokenRef token); + +/*! + @function EDTokenIsPunctuation + @param token The token to be queried. + @result 1 if the token is punctuation; 0 if not; -1 on error. + */ +int EDTokenIsPunctuation(EDTokenRef token); + +/*! + @function EDTokenIsOpcode + @param token The token to be queried. + @result 1 if the token is opcode; 0 if not; -1 on error. + */ +int EDTokenIsOpcode(EDTokenRef token); + +/*! + @function EDTokenIsLiteral + @param token The token to be queried. + @result 1 if the token is a numeric literal; 0 if not; -1 on error. + */ +int EDTokenIsLiteral(EDTokenRef token); + +/*! + @function EDTokenIsRegister + @param token The token to be queried. + @result 1 if the token identifies a register; 0 if not; -1 on error. + */ +int EDTokenIsRegister(EDTokenRef token); + +/*! + @function EDTokenIsNegativeLiteral + @param token The token to be queried. + @result 1 if the token is a negative signed literal; 0 if not; -1 on error. + */ +int EDTokenIsNegativeLiteral(EDTokenRef token); + +/*! + @function EDLiteralTokenAbsoluteValue + @param value A pointer whose target will be filled in with the absolute value + of the literal. + @param token The token to be queried. + @result 0 on success; -1 otherwise. + */ +int EDLiteralTokenAbsoluteValue(uint64_t *value, + EDTokenRef token); + +/*! + @function EDRegisterTokenValue + @param registerID A pointer whose target will be filled in with the LLVM + register identifier for the token. + @param token The token to be queried. + @result 0 on success; -1 otherwise. + */ +int EDRegisterTokenValue(unsigned *registerID, + EDTokenRef token); + +/*! + @functiongroup Creating and querying operands + */ + +/*! + @function EDNumOperands + @param inst The instruction to be queried. + @result The number of operands in the instruction, or -1 on error. + */ +int EDNumOperands(EDInstRef inst); + +/*! + @function EDGetOperand + Retrieves an operand from an instruction. The operand is valid until the + instruction is released. + @param operand A pointer to be filled in with the operand. + @param inst The instruction to be queried. + @param index The index of the operand in the instruction. + @result 0 on success; -1 otherwise. + */ +int EDGetOperand(EDOperandRef *operand, + EDInstRef inst, + int index); + +/*! + @function EDOperandIsRegister + @param operand The operand to be queried. + @result 1 if the operand names a register; 0 if not; -1 on error. + */ +int EDOperandIsRegister(EDOperandRef operand); + +/*! + @function EDOperandIsImmediate + @param operand The operand to be queried. + @result 1 if the operand specifies an immediate value; 0 if not; -1 on error. + */ +int EDOperandIsImmediate(EDOperandRef operand); + +/*! + @function EDOperandIsMemory + @param operand The operand to be queried. + @result 1 if the operand specifies a location in memory; 0 if not; -1 on error. + */ +int EDOperandIsMemory(EDOperandRef operand); + +/*! + @function EDRegisterOperandValue + @param value A pointer whose target will be filled in with the LLVM register ID + of the register named by the operand. + @param operand The operand to be queried. + @result 0 on success; -1 otherwise. + */ +int EDRegisterOperandValue(unsigned *value, + EDOperandRef operand); + +/*! + @function EDImmediateOperandValue + @param value A pointer whose target will be filled in with the value of the + immediate. + @param operand The operand to be queried. + @result 0 on success; -1 otherwise. + */ +int EDImmediateOperandValue(uint64_t *value, + EDOperandRef operand); + +/*! + @function EDEvaluateOperand + Evaluates an operand using a client-supplied register state accessor. Register + operands are evaluated by reading the value of the register; immediate operands + are evaluated by reporting the immediate value; memory operands are evaluated + by computing the target address (with only those relocations applied that were + already applied to the original bytes). + @param result A pointer whose target is to be filled with the result of + evaluating the operand. + @param operand The operand to be evaluated. + @param regReader The function to use when reading registers from the register + state. + @param arg An anonymous argument for client use. + @result 0 if the operand could be evaluated; -1 otherwise. + */ +int EDEvaluateOperand(uint64_t *result, + EDOperandRef operand, + EDRegisterReaderCallback regReader, + void *arg); + +#ifdef __BLOCKS__ + +/*! + @typedef EDByteBlock_t + Block-based interface to memory from which instructions may be read. + @param byte A pointer whose target should be filled in with the data returned. + @param address The address of the byte to be read. + @result 0 on success; -1 otherwise. + */ +typedef int (^EDByteBlock_t)(uint8_t *byte, uint64_t address); + +/*! + @typedef EDRegisterBlock_t + Block-based interface to registers from which registers may be read. + @param value A pointer whose target should be filled in with the value of the + register. + @param regID The LLVM register identifier for the register to read. + @result 0 if the register could be read; -1 otherwise. + */ +typedef int (^EDRegisterBlock_t)(uint64_t *value, unsigned regID); + +/*! + @typedef EDTokenVisitor_t + Block-based handler for individual tokens. + @param token The current token being read. + @result 0 to continue; 1 to stop normally; -1 on error. + */ +typedef int (^EDTokenVisitor_t)(EDTokenRef token); + +/*! @functiongroup Block-based interfaces */ + +/*! + @function EDBlockCreateInsts + Gets a set of contiguous instructions from a disassembler, using a block to + read memory. + @param insts A pointer to an array that will be filled in with the + instructions. Must have at least count entries. Entries not filled in will + be set to NULL. + @param count The maximum number of instructions to fill in. + @param disassembler The disassembler to use when decoding the instructions. + @param byteBlock The block to use when reading the instruction's machine + code. + @param address The address of the first byte of the instruction. + @result The number of instructions read on success; 0 otherwise. + */ +unsigned int EDBlockCreateInsts(EDInstRef *insts, + int count, + EDDisassemblerRef disassembler, + EDByteBlock_t byteBlock, + uint64_t address); + +/*! + @function EDBlockEvaluateOperand + Evaluates an operand using a block to read registers. + @param result A pointer whose target is to be filled with the result of + evaluating the operand. + @param operand The operand to be evaluated. + @param regBlock The block to use when reading registers from the register + state. + @result 0 if the operand could be evaluated; -1 otherwise. + */ +int EDBlockEvaluateOperand(uint64_t *result, + EDOperandRef operand, + EDRegisterBlock_t regBlock); + +/*! + @function EDBlockVisitTokens + Visits every token with a visitor. + @param inst The instruction with the tokens to be visited. + @param visitor The visitor. + @result 0 if the visit ended normally; -1 if the visitor encountered an error + or there was some other error. + */ +int EDBlockVisitTokens(EDInstRef inst, + EDTokenVisitor_t visitor); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/ExecutionEngine.h b/final/include/llvm-c/ExecutionEngine.h new file mode 100644 index 00000000000..f5f40619ef0 --- /dev/null +++ b/final/include/llvm-c/ExecutionEngine.h @@ -0,0 +1,152 @@ +/*===-- llvm-c/ExecutionEngine.h - ExecutionEngine Lib C Iface --*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMExecutionEngine.o, which *| +|* implements various analyses of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_EXECUTIONENGINE_H +#define LLVM_C_EXECUTIONENGINE_H + +#include "llvm-c/Core.h" +#include "llvm-c/Target.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void LLVMLinkInJIT(void); +void LLVMLinkInInterpreter(void); + +typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; +typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; + +/*===-- Operations on generic values --------------------------------------===*/ + +LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, + unsigned long long N, + LLVMBool IsSigned); + +LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P); + +LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef Ty, double N); + +unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef); + +unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenVal, + LLVMBool IsSigned); + +void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal); + +double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal); + +void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal); + +/*===-- Operations on execution engines -----------------------------------===*/ + +LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, + LLVMModuleRef M, + char **OutError); + +LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, + LLVMModuleRef M, + char **OutError); + +LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + unsigned OptLevel, + char **OutError); + +/** Deprecated: Use LLVMCreateExecutionEngineForModule instead. */ +LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, + LLVMModuleProviderRef MP, + char **OutError); + +/** Deprecated: Use LLVMCreateInterpreterForModule instead. */ +LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError); + +/** Deprecated: Use LLVMCreateJITCompilerForModule instead. */ +LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, + LLVMModuleProviderRef MP, + unsigned OptLevel, + char **OutError); + +void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE); + +void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE); + +void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE); + +int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned ArgC, const char * const *ArgV, + const char * const *EnvP); + +LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned NumArgs, + LLVMGenericValueRef *Args); + +void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F); + +void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M); + +/** Deprecated: Use LLVMAddModule instead. */ +void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP); + +LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, + LLVMModuleRef *OutMod, char **OutError); + +/** Deprecated: Use LLVMRemoveModule instead. */ +LLVMBool LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, + LLVMModuleProviderRef MP, + LLVMModuleRef *OutMod, char **OutError); + +LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, + LLVMValueRef *OutFn); + +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn); + +LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr); + +void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); + +#ifdef __cplusplus +} + +namespace llvm { + struct GenericValue; + class ExecutionEngine; + + #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast(const_cast(P)); \ + } + + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef ) + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) + + #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS +} + +#endif /* defined(__cplusplus) */ + +#endif diff --git a/final/include/llvm-c/Initialization.h b/final/include/llvm-c/Initialization.h new file mode 100644 index 00000000000..3b59abbec03 --- /dev/null +++ b/final/include/llvm-c/Initialization.h @@ -0,0 +1,40 @@ +/*===-- llvm-c/Initialization.h - Initialization C Interface ------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to LLVM initialization routines, *| +|* which must be called before you can use the functionality provided by *| +|* the corresponding LLVM library. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_INITIALIZEPASSES_H +#define LLVM_C_INITIALIZEPASSES_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void LLVMInitializeCore(LLVMPassRegistryRef R); +void LLVMInitializeTransformUtils(LLVMPassRegistryRef R); +void LLVMInitializeScalarOpts(LLVMPassRegistryRef R); +void LLVMInitializeInstCombine(LLVMPassRegistryRef R); +void LLVMInitializeIPO(LLVMPassRegistryRef R); +void LLVMInitializeInstrumentation(LLVMPassRegistryRef R); +void LLVMInitializeAnalysis(LLVMPassRegistryRef R); +void LLVMInitializeIPA(LLVMPassRegistryRef R); +void LLVMInitializeCodeGen(LLVMPassRegistryRef R); +void LLVMInitializeTarget(LLVMPassRegistryRef R); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/LinkTimeOptimizer.h b/final/include/llvm-c/LinkTimeOptimizer.h new file mode 100644 index 00000000000..fca394681c7 --- /dev/null +++ b/final/include/llvm-c/LinkTimeOptimizer.h @@ -0,0 +1,58 @@ +//===-- llvm/LinkTimeOptimizer.h - LTO Public C Interface -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header provides a C API to use the LLVM link time optimization +// library. This is intended to be used by linkers which are C-only in +// their implementation for performing LTO. +// +//===----------------------------------------------------------------------===// + +#ifndef __LTO_CAPI_H__ +#define __LTO_CAPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + /// This provides a dummy type for pointers to the LTO object. + typedef void* llvm_lto_t; + + /// This provides a C-visible enumerator to manage status codes. + /// This should map exactly onto the C++ enumerator LTOStatus. + typedef enum llvm_lto_status { + LLVM_LTO_UNKNOWN, + LLVM_LTO_OPT_SUCCESS, + LLVM_LTO_READ_SUCCESS, + LLVM_LTO_READ_FAILURE, + LLVM_LTO_WRITE_FAILURE, + LLVM_LTO_NO_TARGET, + LLVM_LTO_NO_WORK, + LLVM_LTO_MODULE_MERGE_FAILURE, + LLVM_LTO_ASM_FAILURE, + + // Added C-specific error codes + LLVM_LTO_NULL_OBJECT + } llvm_lto_status_t; + + /// This provides C interface to initialize link time optimizer. This allows + /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. + /// extern "C" helps, because dlopen() interface uses name to find the symbol. + extern llvm_lto_t llvm_create_optimizer(void); + extern void llvm_destroy_optimizer(llvm_lto_t lto); + + extern llvm_lto_status_t llvm_read_object_file + (llvm_lto_t lto, const char* input_filename); + extern llvm_lto_status_t llvm_optimize_modules + (llvm_lto_t lto, const char* output_filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/final/include/llvm-c/Target.h b/final/include/llvm-c/Target.h new file mode 100644 index 00000000000..2cd15c3fa30 --- /dev/null +++ b/final/include/llvm-c/Target.h @@ -0,0 +1,172 @@ +/*===-- llvm-c/Target.h - Target Lib C Iface --------------------*- C++ -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ +/* */ +/* This header declares the C interface to libLLVMTarget.a, which */ +/* implements target information. */ +/* */ +/* Many exotic languages can interoperate with C code but have a harder time */ +/* with C++ due to name mangling. So in addition to C, this interface enables */ +/* tools written in such languages. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TARGET_H +#define LLVM_C_TARGET_H + +#include "llvm-c/Core.h" +#include "llvm/Config/llvm-config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; + +typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; +typedef struct LLVMStructLayout *LLVMStructLayoutRef; + +/* Declare all of the target-initialization functions that are available. */ +#define LLVM_TARGET(TargetName) \ + void LLVMInitialize##TargetName##TargetInfo(void); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ + +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(void); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ + +/** LLVMInitializeAllTargetInfos - The main program should call this function if + it wants access to all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargetInfos(void) { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeAllTargets - The main program should call this function if it + wants to link in all available targets that LLVM is configured to + support. */ +static inline void LLVMInitializeAllTargets(void) { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" +#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ +} + +/** LLVMInitializeNativeTarget - The main program should call this function to + initialize the native target corresponding to the host. This is useful + for JIT applications to ensure that the target gets linked in correctly. */ +static inline LLVMBool LLVMInitializeNativeTarget(void) { + /* If we have a native target, initialize it to ensure it is linked in. */ +#ifdef LLVM_NATIVE_TARGET + LLVM_NATIVE_TARGETINFO(); + LLVM_NATIVE_TARGET(); + return 0; +#else + return 1; +#endif +} + +/*===-- Target Data -------------------------------------------------------===*/ + +/** Creates target data from a target layout string. + See the constructor llvm::TargetData::TargetData. */ +LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep); + +/** Adds target data information to a pass manager. This does not take ownership + of the target data. + See the method llvm::PassManagerBase::add. */ +void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); + +/** Converts target data to a target layout string. The string must be disposed + with LLVMDisposeMessage. + See the constructor llvm::TargetData::TargetData. */ +char *LLVMCopyStringRepOfTargetData(LLVMTargetDataRef); + +/** Returns the byte order of a target, either LLVMBigEndian or + LLVMLittleEndian. + See the method llvm::TargetData::isLittleEndian. */ +enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef); + +/** Returns the pointer size in bytes for a target. + See the method llvm::TargetData::getPointerSize. */ +unsigned LLVMPointerSize(LLVMTargetDataRef); + +/** Returns the integer type that is the same size as a pointer on a target. + See the method llvm::TargetData::getIntPtrType. */ +LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef); + +/** Computes the size of a type in bytes for a target. + See the method llvm::TargetData::getTypeSizeInBits. */ +unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the storage size of a type in bytes for a target. + See the method llvm::TargetData::getTypeStoreSize. */ +unsigned long long LLVMStoreSizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI size of a type in bytes for a target. + See the method llvm::TargetData::getTypeAllocSize. */ +unsigned long long LLVMABISizeOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the ABI alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMABIAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the call frame alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMCallFrameAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a type in bytes for a target. + See the method llvm::TargetData::getTypeABISize. */ +unsigned LLVMPreferredAlignmentOfType(LLVMTargetDataRef, LLVMTypeRef); + +/** Computes the preferred alignment of a global variable in bytes for a target. + See the method llvm::TargetData::getPreferredAlignment. */ +unsigned LLVMPreferredAlignmentOfGlobal(LLVMTargetDataRef, + LLVMValueRef GlobalVar); + +/** Computes the structure element that contains the byte offset for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned LLVMElementAtOffset(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned long long Offset); + +/** Computes the byte offset of the indexed struct element for a target. + See the method llvm::StructLayout::getElementContainingOffset. */ +unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy, + unsigned Element); + +/** Struct layouts are speculatively cached. If a TargetDataRef is alive when + types are being refined and removed, this method must be called whenever a + struct type is removed to avoid a dangling pointer in this cache. + See the method llvm::TargetData::InvalidateStructLayoutInfo. */ +void LLVMInvalidateStructLayout(LLVMTargetDataRef, LLVMTypeRef StructTy); + +/** Deallocates a TargetData. + See the destructor llvm::TargetData::~TargetData. */ +void LLVMDisposeTargetData(LLVMTargetDataRef); + + +#ifdef __cplusplus +} + +namespace llvm { + class TargetData; + + inline TargetData *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast(P); + } + + inline LLVMTargetDataRef wrap(const TargetData *P) { + return reinterpret_cast(const_cast(P)); + } +} + +#endif /* defined(__cplusplus) */ + +#endif diff --git a/final/include/llvm-c/Transforms/IPO.h b/final/include/llvm-c/Transforms/IPO.h new file mode 100644 index 00000000000..d16e858bca3 --- /dev/null +++ b/final/include/llvm-c/Transforms/IPO.h @@ -0,0 +1,76 @@ +/*===-- IPO.h - Interprocedural Transformations C Interface -----*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMIPO.a, which implements *| +|* various interprocedural transformations of the LLVM IR. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_IPO_H +#define LLVM_C_TRANSFORMS_IPO_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** See llvm::createArgumentPromotionPass function. */ +void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantMergePass function. */ +void LLVMAddConstantMergePass(LLVMPassManagerRef PM); + +/** See llvm::createDeadArgEliminationPass function. */ +void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadTypeEliminationPass function. */ +void LLVMAddDeadTypeEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionAttrsPass function. */ +void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM); + +/** See llvm::createFunctionInliningPass function. */ +void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalDCEPass function. */ +void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createGlobalOptimizerPass function. */ +void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM); + +/** See llvm::createIPConstantPropagationPass function. */ +void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::createLowerSetJmpPass function. */ +void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM); + +/** See llvm::createPruneEHPass function. */ +void LLVMAddPruneEHPass(LLVMPassManagerRef PM); + +/** See llvm::createIPSCCPPass function. */ +void LLVMAddIPSCCPPass(LLVMPassManagerRef PM); + +/** See llvm::createInternalizePass function. */ +void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain); + +// FIXME: Remove in LLVM 3.0. +void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM); + +/** See llvm::createStripDeadPrototypesPass function. */ +void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM); + +/** See llvm::createStripSymbolsPass function. */ +void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM); + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif diff --git a/final/include/llvm-c/Transforms/Scalar.h b/final/include/llvm-c/Transforms/Scalar.h new file mode 100644 index 00000000000..2ddfb38171c --- /dev/null +++ b/final/include/llvm-c/Transforms/Scalar.h @@ -0,0 +1,102 @@ +/*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMScalarOpts.a, which *| +|* implements various scalar transformations of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_SCALAR_H +#define LLVM_C_TRANSFORMS_SCALAR_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** See llvm::createAggressiveDCEPass function. */ +void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); + +/** See llvm::createCFGSimplificationPass function. */ +void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); + +/** See llvm::createDeadStoreEliminationPass function. */ +void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createGVNPass function. */ +void LLVMAddGVNPass(LLVMPassManagerRef PM); + +/** See llvm::createIndVarSimplifyPass function. */ +void LLVMAddIndVarSimplifyPass(LLVMPassManagerRef PM); + +/** See llvm::createInstructionCombiningPass function. */ +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); + +/** See llvm::createJumpThreadingPass function. */ +void LLVMAddJumpThreadingPass(LLVMPassManagerRef PM); + +/** See llvm::createLICMPass function. */ +void LLVMAddLICMPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopDeletionPass function. */ +void LLVMAddLoopDeletionPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopRotatePass function. */ +void LLVMAddLoopRotatePass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnrollPass function. */ +void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); + +/** See llvm::createLoopUnswitchPass function. */ +void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); + +/** See llvm::createMemCpyOptPass function. */ +void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); + +/** See llvm::createPromoteMemoryToRegisterPass function. */ +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** See llvm::createReassociatePass function. */ +void LLVMAddReassociatePass(LLVMPassManagerRef PM); + +/** See llvm::createSCCPPass function. */ +void LLVMAddSCCPPass(LLVMPassManagerRef PM); + +/** See llvm::createScalarReplAggregatesPass function. */ +void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM); + +/** See llvm::createScalarReplAggregatesPass function. */ +void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM, + int Threshold); + +/** See llvm::createSimplifyLibCallsPass function. */ +void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM); + +/** See llvm::createTailCallEliminationPass function. */ +void LLVMAddTailCallEliminationPass(LLVMPassManagerRef PM); + +/** See llvm::createConstantPropagationPass function. */ +void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM); + +/** See llvm::demotePromoteMemoryToRegisterPass function. */ +void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** See llvm::createVerifierPass function. */ +void LLVMAddVerifierPass(LLVMPassManagerRef PM); + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif diff --git a/final/include/llvm-c/lto.h b/final/include/llvm-c/lto.h new file mode 100644 index 00000000000..1c42ce0cec7 --- /dev/null +++ b/final/include/llvm-c/lto.h @@ -0,0 +1,278 @@ +/*===-- llvm-c/lto.h - LTO Public C Interface ---------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header provides public interface to an abstract link time optimization*| +|* library. LLVM provides an implementation of this interface for use with *| +|* llvm bitcode files. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LTO_H +#define LTO_H 1 + +#include +#include +#include + +#define LTO_API_VERSION 4 + +typedef enum { + LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ + LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, + LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0, + LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0, + LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080, + LTO_SYMBOL_DEFINITION_MASK = 0x00000700, + LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100, + LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200, + LTO_SYMBOL_DEFINITION_WEAK = 0x00000300, + LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400, + LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500, + LTO_SYMBOL_SCOPE_MASK = 0x00003800, + LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800, + LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000, + LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, + LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800, + LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800 +} lto_symbol_attributes; + +typedef enum { + LTO_DEBUG_MODEL_NONE = 0, + LTO_DEBUG_MODEL_DWARF = 1 +} lto_debug_model; + +typedef enum { + LTO_CODEGEN_PIC_MODEL_STATIC = 0, + LTO_CODEGEN_PIC_MODEL_DYNAMIC = 1, + LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2 +} lto_codegen_model; + + +/** opaque reference to a loaded object module */ +typedef struct LTOModule* lto_module_t; + +/** opaque reference to a code generator */ +typedef struct LTOCodeGenerator* lto_code_gen_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Returns a printable string. + */ +extern const char* +lto_get_version(void); + + +/** + * Returns the last error string or NULL if last operation was sucessful. + */ +extern const char* +lto_get_error_message(void); + +/** + * Checks if a file is a loadable object file. + */ +extern bool +lto_module_is_object_file(const char* path); + + +/** + * Checks if a file is a loadable object compiled for requested target. + */ +extern bool +lto_module_is_object_file_for_target(const char* path, + const char* target_triple_prefix); + + +/** + * Checks if a buffer is a loadable object file. + */ +extern bool +lto_module_is_object_file_in_memory(const void* mem, size_t length); + + +/** + * Checks if a buffer is a loadable object compiled for requested target. + */ +extern bool +lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, + const char* target_triple_prefix); + + +/** + * Loads an object file from disk. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create(const char* path); + + +/** + * Loads an object file from memory. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create_from_memory(const void* mem, size_t length); + +/** + * Loads an object file from disk. The seek point of fd is not preserved. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_module_t +lto_module_create_from_fd(int fd, const char *path, off_t size); + + +/** + * Frees all memory internally allocated by the module. + * Upon return the lto_module_t is no longer valid. + */ +extern void +lto_module_dispose(lto_module_t mod); + + +/** + * Returns triple string which the object module was compiled under. + */ +extern const char* +lto_module_get_target_triple(lto_module_t mod); + +/** + * Sets triple string with which the object will be codegened. + */ +extern void +lto_module_set_target_triple(lto_module_t mod, const char *triple); + + +/** + * Returns the number of symbols in the object module. + */ +extern unsigned int +lto_module_get_num_symbols(lto_module_t mod); + + +/** + * Returns the name of the ith symbol in the object module. + */ +extern const char* +lto_module_get_symbol_name(lto_module_t mod, unsigned int index); + + +/** + * Returns the attributes of the ith symbol in the object module. + */ +extern lto_symbol_attributes +lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); + + +/** + * Instantiates a code generator. + * Returns NULL on error (check lto_get_error_message() for details). + */ +extern lto_code_gen_t +lto_codegen_create(void); + + +/** + * Frees all code generator and all memory it internally allocated. + * Upon return the lto_code_gen_t is no longer valid. + */ +extern void +lto_codegen_dispose(lto_code_gen_t); + + + +/** + * Add an object module to the set of modules for which code will be generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); + + + +/** + * Sets if debug info should be generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); + + +/** + * Sets which PIC code model to generated. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); + + +/** + * Sets the cpu to generate code for. + */ +extern void +lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu); + + +/** + * Sets the location of the assembler tool to run. If not set, libLTO + * will use gcc to invoke the assembler. + */ +extern void +lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path); + +/** + * Sets extra arguments that libLTO should pass to the assembler. + */ +extern void +lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, + int nargs); + +/** + * Adds to a list of all global symbols that must exist in the final + * generated code. If a function is not listed, it might be + * inlined into every usage and optimized away. + */ +extern void +lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); + + +/** + * Writes a new object file at the specified path that contains the + * merged contents of all modules added so far. + * Returns true on error (check lto_get_error_message() for details). + */ +extern bool +lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); + + +/** + * Generates code for all added modules into one native object file. + * On sucess returns a pointer to a generated mach-o/ELF buffer and + * length set to the buffer size. The buffer is owned by the + * lto_code_gen_t and will be freed when lto_codegen_dispose() + * is called, or lto_codegen_compile() is called again. + * On failure, returns NULL (check lto_get_error_message() for details). + */ +extern const void* +lto_codegen_compile(lto_code_gen_t cg, size_t* length); + + +/** + * Sets options to help debug codegen bugs. + */ +extern void +lto_codegen_debug_options(lto_code_gen_t cg, const char *); +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/final/include/llvm/ADT/APFloat.h b/final/include/llvm/ADT/APFloat.h new file mode 100644 index 00000000000..ca4138b825a --- /dev/null +++ b/final/include/llvm/ADT/APFloat.h @@ -0,0 +1,452 @@ +//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- 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 a class to represent arbitrary precision floating +// point values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +/* A self-contained host- and target-independent arbitrary-precision + floating-point software implementation. It uses bignum integer + arithmetic as provided by static functions in the APInt class. + The library will work with bignum integers whose parts are any + unsigned type at least 16 bits wide, but 64 bits is recommended. + + Written for clarity rather than speed, in particular with a view + to use in the front-end of a cross compiler so that target + arithmetic can be correctly performed on the host. Performance + should nonetheless be reasonable, particularly for its intended + use. It may be useful as a base implementation for a run-time + library during development of a faster target-specific one. + + All 5 rounding modes in the IEEE-754R draft are handled correctly + for all implemented operations. Currently implemented operations + are add, subtract, multiply, divide, fused-multiply-add, + conversion-to-float, conversion-to-integer and + conversion-from-integer. New rounding modes (e.g. away from zero) + can be added with three or four lines of code. + + Four formats are built-in: IEEE single precision, double + precision, quadruple precision, and x87 80-bit extended double + (when operating with full extended precision). Adding a new + format that obeys IEEE semantics only requires adding two lines of + code: a declaration and definition of the format. + + All operations return the status of that operation as an exception + bit-mask, so multiple operations can be done consecutively with + their results or-ed together. The returned status can be useful + for compiler diagnostics; e.g., inexact, underflow and overflow + can be easily diagnosed on constant folding, and compiler + optimizers can determine what exceptions would be raised by + folding operations and optimize, or perhaps not optimize, + accordingly. + + At present, underflow tininess is detected after rounding; it + should be straight forward to add support for the before-rounding + case too. + + The library reads hexadecimal floating point numbers as per C99, + and correctly rounds if necessary according to the specified + rounding mode. Syntax is required to have been validated by the + caller. It also converts floating point numbers to hexadecimal + text as per the C99 %a and %A conversions. The output precision + (or alternatively the natural minimal precision) can be specified; + if the requested precision is less than the natural precision the + output is correctly rounded for the specified rounding mode. + + It also reads decimal floating point numbers and correctly rounds + according to the specified rounding mode. + + Conversion to decimal text is not currently implemented. + + Non-zero finite numbers are represented internally as a sign bit, + a 16-bit signed exponent, and the significand as an array of + integer parts. After normalization of a number of precision P the + exponent is within the range of the format, and if the number is + not denormal the P-th bit of the significand is set as an explicit + integer bit. For denormals the most significant bit is shifted + right so that the exponent is maintained at the format's minimum, + so that the smallest denormal has just the least significant bit + of the significand set. The sign of zeroes and infinities is + significant; the exponent and significand of such numbers is not + stored, but has a known implicit (deterministic) value: 0 for the + significands, 0 for zero exponent, all 1 bits for infinity + exponent. For NaNs the sign and significand are deterministic, + although not really meaningful, and preserved in non-conversion + operations. The exponent is implicitly all 1 bits. + + TODO + ==== + + Some features that may or may not be worth adding: + + Binary to decimal conversion (hard). + + Optional ability to detect underflow tininess before rounding. + + New formats: x87 in single and double precision mode (IEEE apart + from extended exponent range) (hard). + + New operations: sqrt, IEEE remainder, C90 fmod, nextafter, + nexttoward. +*/ + +#ifndef LLVM_FLOAT_H +#define LLVM_FLOAT_H + +// APInt contains static functions implementing bignum arithmetic. +#include "llvm/ADT/APInt.h" + +namespace llvm { + + /* Exponents are stored as signed numbers. */ + typedef signed short exponent_t; + + struct fltSemantics; + class StringRef; + + /* When bits of a floating point number are truncated, this enum is + used to indicate what fraction of the LSB those bits represented. + It essentially combines the roles of guard and sticky bits. */ + enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero + }; + + class APFloat { + public: + + /* We support the following floating point semantics. */ + static const fltSemantics IEEEhalf; + static const fltSemantics IEEEsingle; + static const fltSemantics IEEEdouble; + static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; + static const fltSemantics x87DoubleExtended; + /* And this pseudo, used to construct APFloats that cannot + conflict with anything real. */ + static const fltSemantics Bogus; + + static unsigned int semanticsPrecision(const fltSemantics &); + + /* Floating point numbers have a four-state comparison relation. */ + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered + }; + + /* IEEE-754R gives five rounding modes. */ + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; + + // Operation status. opUnderflow or opOverflow are always returned + // or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; + + // Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero + }; + + enum uninitializedTag { + uninitialized + }; + + // Constructors. + APFloat(const fltSemantics &); // Default construct to 0.0 + APFloat(const fltSemantics &, StringRef); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, fltCategory, bool negative); + APFloat(const fltSemantics &, uninitializedTag); + explicit APFloat(double d); + explicit APFloat(float f); + explicit APFloat(const APInt &, bool isIEEE = false); + APFloat(const APFloat &); + ~APFloat(); + + // Convenience "constructors" + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcZero, Negative); + } + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcInfinity, Negative); + } + + /// getNaN - Factory for QNaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + if (type) { + APInt fill(64, type); + return getQNaN(Sem, Negative, &fill); + } else { + return getQNaN(Sem, Negative, 0); + } + } + + /// getQNan - Factory for QNaN values. + static APFloat getQNaN(const fltSemantics &Sem, + bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, false, Negative, payload); + } + + /// getSNan - Factory for SNaN values. + static APFloat getSNaN(const fltSemantics &Sem, + bool Negative = false, + const APInt *payload = 0) { + return makeNaN(Sem, true, Negative, payload); + } + + /// getLargest - Returns the largest finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getLargest(const fltSemantics &Sem, bool Negative = false); + + /// getSmallest - Returns the smallest (by magnitude) finite number + /// in the given semantics. Might be denormalized, which implies a + /// relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false); + + /// getSmallestNormalized - Returns the smallest (by magnitude) + /// normalized finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static APFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false); + + /// getAllOnesValue - Returns a float which is bitcasted from + /// an all one value int. + /// + /// \param BitWidth - Select float type + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + + /// Profile - Used to insert APFloat objects, or objects that contain + /// APFloat objects, into FoldingSets. + void Profile(FoldingSetNodeID& NID) const; + + /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer& S) const; + + /// @brief Used by the Bitcode deserializer to deserialize APInts. + static APFloat ReadVal(Deserializer& D); + + /* Arithmetic. */ + opStatus add(const APFloat &, roundingMode); + opStatus subtract(const APFloat &, roundingMode); + opStatus multiply(const APFloat &, roundingMode); + opStatus divide(const APFloat &, roundingMode); + /* IEEE remainder. */ + opStatus remainder(const APFloat &); + /* C fmod, or llvm frem. */ + opStatus mod(const APFloat &, roundingMode); + opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + + /* Sign operations. */ + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /* Conversions. */ + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, + bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromString(StringRef, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /* The definition of equality is not straightforward for floating point, + so we won't use operator==. Use one of the following, or write + whatever it is you really mean. */ + // bool operator==(const APFloat &) const; // DO NOT IMPLEMENT + + /* IEEE comparison with another floating point number (NaNs + compare unordered, 0==-0). */ + cmpResult compare(const APFloat &) const; + + /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */ + bool bitwiseIsEqual(const APFloat &) const; + + /* Write out a hexadecimal representation of the floating point + value to DST, which must be of sufficient size, in the C99 form + [-]0xh.hhhhp[+-]d. Return the number of characters written, + excluding the terminating NUL. */ + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /* Simple queries. */ + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isZero() const { return category == fcZero; } + bool isNonZero() const { return category != fcZero; } + bool isNaN() const { return category == fcNaN; } + bool isInfinity() const { return category == fcInfinity; } + bool isNegative() const { return sign; } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + APFloat& operator=(const APFloat &); + + /* Return an arbitrary integer value usable for hashing. */ + uint32_t getHashValue() const; + + /// Converts this value into a decimal string. + /// + /// \param FormatPrecision The maximum number of digits of + /// precision to output. If there are fewer digits available, + /// zero padding will not be used unless the value is + /// integral and small enough to be expressed in + /// FormatPrecision digits. 0 means to use the natural + /// precision of the number. + /// \param FormatMaxPadding The maximum number of zeros to + /// consider inserting before falling back to scientific + /// notation. 0 means to always use scientific notation. + /// + /// Number Precision MaxPadding Result + /// ------ --------- ---------- ------ + /// 1.01E+4 5 2 10100 + /// 1.01E+4 4 2 1.01E+4 + /// 1.01E+4 5 1 1.01E+4 + /// 1.01E-2 5 2 0.0101 + /// 1.01E-2 4 2 0.0101 + /// 1.01E-2 4 1 1.01E-2 + void toString(SmallVectorImpl &Str, + unsigned FormatPrecision = 0, + unsigned FormatMaxPadding = 3) const; + + private: + + /* Trivial queries. */ + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /* Significand operations. */ + integerPart addSignificand(const APFloat &); + integerPart subtractSignificand(const APFloat &, integerPart); + lostFraction addOrSubtractSignificand(const APFloat &, bool subtract); + lostFraction multiplySignificand(const APFloat &, const APFloat *); + lostFraction divideSignificand(const APFloat &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + + /* Arithmetic on special values. */ + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /* Miscellany. */ + static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill); + void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); + cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + opStatus convertFromHexadecimalString(StringRef, roundingMode); + opStatus convertFromDecimalString(StringRef, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, + int, roundingMode); + + APInt convertHalfAPFloatToAPInt() const; + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertQuadrupleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const APInt& api, bool isIEEE = false); + void initFromHalfAPInt(const APInt& api); + void initFromFloatAPInt(const APInt& api); + void initFromDoubleAPInt(const APInt& api); + void initFromQuadrupleAPInt(const APInt &api); + void initFromF80LongDoubleAPInt(const APInt& api); + void initFromPPCDoubleDoubleAPInt(const APInt& api); + + void assign(const APFloat &); + void copySignificand(const APFloat &); + void freeSignificand(); + + /* What kind of semantics does this value obey? */ + const fltSemantics *semantics; + + /* Significand - the fraction with an explicit integer bit. Must be + at least one bit wider than the target precision. */ + union Significand + { + integerPart part; + integerPart *parts; + } significand; + + /* The exponent - a signed number. */ + exponent_t exponent; + + /* What kind of floating point number this is. */ + /* Only 2 bits are required, but VisualStudio incorrectly sign extends + it. Using the extra bit keeps it from failing under VisualStudio */ + fltCategory category: 3; + + /* The sign bit of this number. */ + unsigned int sign: 1; + + /* For PPCDoubleDouble, we have a second exponent and sign (the second + significand is appended to the first one, although it would be wrong to + regard these as a single number for arithmetic purposes). These fields + are not meaningful for any other type. */ + exponent_t exponent2 : 11; + unsigned int sign2: 1; + }; +} /* namespace llvm */ + +#endif /* LLVM_FLOAT_H */ diff --git a/final/include/llvm/ADT/APInt.h b/final/include/llvm/ADT/APInt.h new file mode 100644 index 00000000000..d1fd3e5034b --- /dev/null +++ b/final/include/llvm/ADT/APInt.h @@ -0,0 +1,1720 @@ +//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integral +// constant values and operations on them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APINT_H +#define LLVM_APINT_H + +#include "llvm/Support/MathExtras.h" +#include +#include +#include +#include + +namespace llvm { + class Serializer; + class Deserializer; + class FoldingSetNodeID; + class raw_ostream; + class StringRef; + + template + class SmallVectorImpl; + + // An unsigned host type used as a single part of a multi-part + // bignum. + typedef uint64_t integerPart; + + const unsigned int host_char_bit = 8; + const unsigned int integerPartWidth = host_char_bit * + static_cast(sizeof(integerPart)); + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// APInt - This class represents arbitrary precision constant integral values. +/// It is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +/// @brief Class for arbitrary precision integers. +class APInt { + unsigned BitWidth; ///< The number of bits in this APInt. + + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + /// This enum is used to hold the constants we needed for APInt. + enum { + /// Bits in a word + APINT_BITS_PER_WORD = static_cast(sizeof(uint64_t)) * + CHAR_BIT, + /// Byte size of a word + APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) + }; + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /// @brief Fast internal constructor + APInt(uint64_t* val, unsigned bits) : BitWidth(bits), pVal(val) { } + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this APInt just has one word to store value. + bool isSingleWord() const { + return BitWidth <= APINT_BITS_PER_WORD; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static unsigned whichWord(unsigned bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// @returns the bit position in a word for the specified bit position + /// in the APInt. + /// @brief Determine which bit in a word a bit is in. + static unsigned whichBit(unsigned bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(unsigned bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + APInt& clearUnusedBits() { + // Compute how many bits are used in the final word + unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shift is the same size as + // the word size (64). + return *this; + + // Mask out the high bits. + uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits); + if (isSingleWord()) + VAL &= mask; + else + pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + uint64_t getWord(unsigned bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// Converts a string into a number. The string must be non-empty + /// and well-formed as a number of the given base. The bit-width + /// must be sufficient to hold the result. + /// + /// This is used by the constructors that take string arguments. + /// + /// StringRef::getAsInteger is superficially similar but (1) does + /// not assume that the string is well-formed and (2) grows the + /// result to hold the input. + /// + /// @param radix 2, 8, 10, or 16 + /// @brief Convert a char array into an APInt + void fromString(unsigned numBits, StringRef str, uint8_t radix); + + /// This is used by the toString method to divide by the radix. It simply + /// provides a more convenient form of divide for internal use since KnuthDiv + /// has specific constraints on its inputs. If those constraints are not met + /// then it provides a simpler form of divide. + /// @brief An internal division function for dividing APInts. + static void divide(const APInt LHS, unsigned lhsWords, + const APInt &RHS, unsigned rhsWords, + APInt *Quotient, APInt *Remainder); + + /// out-of-line slow case for inline constructor + void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt& that); + + /// out-of-line slow case for shl + APInt shlSlowCase(unsigned shiftAmt) const; + + /// out-of-line slow case for operator& + APInt AndSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator| + APInt OrSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator^ + APInt XorSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator= + APInt& AssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator== + bool EqualSlowCase(uint64_t Val) const; + + /// out-of-line slow case for countLeadingZeros + unsigned countLeadingZerosSlowCase() const; + + /// out-of-line slow case for countTrailingOnes + unsigned countTrailingOnesSlowCase() const; + + /// out-of-line slow case for countPopulation + unsigned countPopulationSlowCase() const; + +public: + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed APInt + /// @param val the initial value of the APInt + /// @param isSigned how to treat signedness of val + /// @brief Create a new APInt of numBits width, initialized as val. + APInt(unsigned numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = val; + else + initSlowCase(numBits, val, isSigned); + clearUnusedBits(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed APInt + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the APInt + /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + + /// This constructor interprets the string \arg str in the given radix. The + /// interpretation stops when the first character that is not suitable for the + /// radix is encountered, or the end of the string. Acceptable radix values + /// are 2, 8, 10 and 16. It is an error for the value implied by the string to + /// require more bits than numBits. + /// + /// @param numBits the bit width of the constructed APInt + /// @param str the string to be interpreted + /// @param radix the radix to use for the conversion + /// @brief Construct an APInt from a string representation. + APInt(unsigned numBits, StringRef str, uint8_t radix); + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + APInt(const APInt& that) + : BitWidth(that.BitWidth), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = that.VAL; + else + initSlowCase(that); + } + + /// @brief Destructor. + ~APInt() { + if (!isSingleWord()) + delete [] pVal; + } + + /// Default constructor that creates an uninitialized APInt. This is useful + /// for object deserialization (pair this with the static method Read). + explicit APInt() : BitWidth(1) {} + + /// Profile - Used to insert APInt objects, or objects that contain APInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& id) const; + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this APInt to determine if it is set. + /// @returns true if this APInt is negative, false otherwise + /// @brief Determine sign of this APInt. + bool isNegative() const { + return (*this)[BitWidth - 1]; + } + + /// This tests the high bit of the APInt to determine if it is unset. + /// @brief Determine if this APInt Value is non-negative (>= 0) + bool isNonNegative() const { + return !isNegative(); + } + + /// This tests if the value of this APInt is positive (> 0). Note + /// that 0 is not a positive value. + /// @returns true if this APInt is positive. + /// @brief Determine if this APInt Value is positive. + bool isStrictlyPositive() const { + return isNonNegative() && !!*this; + } + + /// This checks to see if the value has all bits of the APInt are set or not. + /// @brief Determine if all bits are set + bool isAllOnesValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the largest unsigned value. + bool isMaxValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the largest signed value. + bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == BitWidth - 1; + } + + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest unsigned value. + bool isMinValue() const { + return !*this; + } + + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest signed value. + bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2(); + } + + /// @brief Check if this APInt has an N-bits unsigned integer value. + bool isIntN(unsigned N) const { + assert(N && "N == 0 ???"); + if (N >= getBitWidth()) + return true; + + if (isSingleWord()) + return isUIntN(N, VAL); + return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this); + } + + /// @brief Check if this APInt has an N-bits signed integer value. + bool isSignedIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getMinSignedBits() <= N; + } + + /// @returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const { + if (isSingleWord()) + return isPowerOf2_64(VAL); + return countPopulationSlowCase() == 1; + } + + /// isSignBit - Return true if this is the value returned by getSignBit. + bool isSignBit() const { return isMinSignedValue(); } + + /// This converts the APInt to a boolean value as a test against zero. + /// @brief Boolean conversion function. + bool getBoolValue() const { + return !!*this; + } + + /// getLimitedValue - If this value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return (getActiveBits() > 64 || getZExtValue() > Limit) ? + Limit : getZExtValue(); + } + + /// @} + /// @name Value Generators + /// @{ + /// @brief Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(unsigned numBits) { + return getAllOnesValue(numBits); + } + + /// @brief Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(unsigned numBits) { + APInt API = getAllOnesValue(numBits); + API.clearBit(numBits - 1); + return API; + } + + /// @brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// @brief Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(unsigned numBits) { + APInt API(numBits, 0); + API.setBit(numBits - 1); + return API; + } + + /// getSignBit - This is just a wrapper function of getSignedMinValue(), and + /// it helps code readability when we want to get a SignBit. + /// @brief Get the SignBit for a specific bit width. + static APInt getSignBit(unsigned BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// @returns the all-ones value for an APInt of the specified bit-width. + /// @brief Get the all-ones value. + static APInt getAllOnesValue(unsigned numBits) { + return APInt(numBits, -1ULL, true); + } + + /// @returns the '0' value for an APInt of the specified bit-width. + /// @brief Get the '0' value. + static APInt getNullValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// @returns the high "numBits" bits of this APInt. + APInt getHiBits(unsigned numBits) const; + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// @returns the low "numBits" bits of this APInt. + APInt getLoBits(unsigned numBits) const; + + /// getOneBitSet - Return an APInt with exactly one bit set in the result. + static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { + APInt Res(numBits, 0); + Res.setBit(BitNo); + return Res; + } + + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 0, 16) you would get + /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For + /// example, with parameters (32, 28, 4), you would get 0xF000000F. + /// @param numBits the intended bit width of the result + /// @param loBit the index of the lowest bit set. + /// @param hiBit the index of the highest bit set. + /// @returns An APInt value with the requested bits set. + /// @brief Get a value with a block of bits set. + static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(hiBit <= numBits && "hiBit out of range"); + assert(loBit < numBits && "loBit out of range"); + if (hiBit < loBit) + return getLowBitsSet(numBits, hiBit) | + getHighBitsSet(numBits, numBits-loBit); + return getLowBitsSet(numBits, hiBit-loBit).shl(loBit); + } + + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param hiBitsSet the number of high-order bits set in the result. + /// @brief Get a value with high bits set + static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { + assert(hiBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (hiBitsSet == 0) + return APInt(numBits, 0); + unsigned shiftAmt = numBits - hiBitsSet; + // For small values, return quickly + if (numBits <= APINT_BITS_PER_WORD) + return APInt(numBits, ~0ULL << shiftAmt); + return getAllOnesValue(numBits).shl(shiftAmt); + } + + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param loBitsSet the number of low-order bits set in the result. + /// @brief Get a value with low bits set + static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { + assert(loBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (loBitsSet == 0) + return APInt(numBits, 0); + if (loBitsSet == APINT_BITS_PER_WORD) + return APInt(numBits, -1ULL); + // For small values, return quickly. + if (numBits < APINT_BITS_PER_WORD) + return APInt(numBits, (1ULL << loBitsSet) - 1); + return getAllOnesValue(numBits).lshr(numBits - loBitsSet); + } + + /// The hash value is computed as the sum of the words and the bit width. + /// @returns A hash value computed from the sum of the APInt words. + /// @brief Get a hash value based on this APInt + uint64_t getHashValue() const; + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new APInt value representing *this incremented by one + /// @brief Postfix increment operator. + const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + APInt& operator++(); + + /// @returns a new APInt representing *this decremented by one. + /// @brief Postfix decrement operator. + const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + APInt& operator--(); + + /// Performs a bitwise complement operation on this APInt. + /// @returns an APInt that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + APInt operator~() const { + APInt Result(*this); + Result.flipAllBits(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An APInt value representing the negation of *this. + /// @brief Unary negation operator + APInt operator-() const { + return APInt(BitWidth, 0) - (*this); + } + + /// Performs logical negation operation on this APInt. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + bool operator!() const; + + /// @} + /// @name Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + APInt& operator=(const APInt& RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + VAL = RHS.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + return AssignSlowCase(RHS); + } + + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// @returns *this after assignment of RHS value. + /// @brief Assignment operator. + APInt& operator=(uint64_t RHS); + + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after ANDing with RHS. + /// @brief Bitwise AND assignment operator. + APInt& operator&=(const APInt& RHS); + + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// @returns *this after ORing with RHS. + /// @brief Bitwise OR assignment operator. + APInt& operator|=(const APInt& RHS); + + /// Performs a bitwise OR operation on this APInt and RHS. RHS is + /// logically zero-extended or truncated to match the bit-width of + /// the LHS. + /// + /// @brief Bitwise OR assignment operator. + APInt& operator|=(uint64_t RHS) { + if (isSingleWord()) { + VAL |= RHS; + clearUnusedBits(); + } else { + pVal[0] |= RHS; + } + return *this; + } + + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after XORing with RHS. + /// @brief Bitwise XOR assignment operator. + APInt& operator^=(const APInt& RHS); + + /// Multiplies this APInt by RHS and assigns the result to *this. + /// @returns *this + /// @brief Multiplication assignment operator. + APInt& operator*=(const APInt& RHS); + + /// Adds RHS to *this and assigns the result to *this. + /// @returns *this + /// @brief Addition assignment operator. + APInt& operator+=(const APInt& RHS); + + /// Subtracts RHS from *this and assigns the result to *this. + /// @returns *this + /// @brief Subtraction assignment operator. + APInt& operator-=(const APInt& RHS); + + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// @returns *this after shifting left by shiftAmt + /// @brief Left-shift assignment function. + APInt& operator<<=(unsigned shiftAmt) { + *this = shl(shiftAmt); + return *this; + } + + /// @} + /// @name Binary Operators + /// @{ + /// Performs a bitwise AND operation on *this and RHS. + /// @returns An APInt value representing the bitwise AND of *this and RHS. + /// @brief Bitwise AND operator. + APInt operator&(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL & RHS.VAL); + return AndSlowCase(RHS); + } + APInt And(const APInt& RHS) const { + return this->operator&(RHS); + } + + /// Performs a bitwise OR operation on *this and RHS. + /// @returns An APInt value representing the bitwise OR of *this and RHS. + /// @brief Bitwise OR operator. + APInt operator|(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL | RHS.VAL); + return OrSlowCase(RHS); + } + APInt Or(const APInt& RHS) const { + return this->operator|(RHS); + } + + /// Performs a bitwise XOR operation on *this and RHS. + /// @returns An APInt value representing the bitwise XOR of *this and RHS. + /// @brief Bitwise XOR operator. + APInt operator^(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + return XorSlowCase(RHS); + } + APInt Xor(const APInt& RHS) const { + return this->operator^(RHS); + } + + /// Multiplies this APInt by RHS and returns the result. + /// @brief Multiplication operator. + APInt operator*(const APInt& RHS) const; + + /// Adds RHS to this APInt and returns the result. + /// @brief Addition operator. + APInt operator+(const APInt& RHS) const; + APInt operator+(uint64_t RHS) const { + return (*this) + APInt(BitWidth, RHS); + } + + /// Subtracts RHS from this APInt and returns the result. + /// @brief Subtraction operator. + APInt operator-(const APInt& RHS) const; + APInt operator-(uint64_t RHS) const { + return (*this) - APInt(BitWidth, RHS); + } + + APInt operator<<(unsigned Bits) const { + return shl(Bits); + } + + APInt operator<<(const APInt &Bits) const { + return shl(Bits); + } + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(unsigned shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(unsigned shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + return shlSlowCase(shiftAmt); + } + + /// @brief Rotate left by rotateAmt. + APInt rotl(unsigned rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(unsigned rotateAmt) const; + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(const APInt &shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(const APInt &shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(const APInt &shiftAmt) const; + + /// @brief Rotate left by rotateAmt. + APInt rotl(const APInt &rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(const APInt &rotateAmt) const; + + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new APInt value containing the division result + /// @brief Unsigned division operation. + APInt udiv(const APInt &RHS) const; + + /// Signed divide this APInt by APInt RHS. + /// @brief Signed division function for APInt. + APInt sdiv(const APInt &RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new APInt value containing the remainder result + /// @brief Unsigned remainder operation. + APInt urem(const APInt &RHS) const; + + /// Signed remainder operation on APInt. + /// @brief Function for signed remainder operation. + APInt srem(const APInt &RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS.isNegative()) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two APInt values and obtain both the + /// quotient and remainder. This function does both operations in the same + /// computation making it a little more efficient. The pair of input arguments + /// may overlap with the pair of output arguments. It is safe to call + /// udivrem(X, Y, X, Y), for example. + /// @brief Dual division/remainder interface. + static void udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) { + if (LHS.isNegative()) { + if (RHS.isNegative()) + APInt::udivrem(-LHS, -RHS, Quotient, Remainder); + else + APInt::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + APInt::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + APInt::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + + // Operations that return overflow indicators. + APInt sadd_ov(const APInt &RHS, bool &Overflow) const; + APInt uadd_ov(const APInt &RHS, bool &Overflow) const; + APInt ssub_ov(const APInt &RHS, bool &Overflow) const; + APInt usub_ov(const APInt &RHS, bool &Overflow) const; + APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; + APInt smul_ov(const APInt &RHS, bool &Overflow) const; + APInt sshl_ov(unsigned Amt, bool &Overflow) const; + + /// @returns the bit value at bitPosition + /// @brief Array-indexing support. + bool operator[](unsigned bitPosition) const; + + /// @} + /// @name Comparison Operators + /// @{ + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @brief Equality operator. + bool operator==(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return VAL == RHS.VAL; + return EqualSlowCase(RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality operator. + bool operator==(uint64_t Val) const { + if (isSingleWord()) + return VAL == Val; + return EqualSlowCase(Val); + } + + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + bool eq(const APInt &RHS) const { + return (*this) == RHS; + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(const APInt& RHS) const { + return !((*this) == RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + bool ne(const APInt &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + bool ult(const APInt &RHS) const; + + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when considered unsigned. + /// @brief Unsigned less than comparison + bool ult(uint64_t RHS) const { + return ult(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + bool slt(const APInt& RHS) const; + + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when considered signed. + /// @brief Signed less than comparison + bool slt(uint64_t RHS) const { + return slt(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + bool ule(const APInt& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when considered unsigned. + /// @brief Unsigned less or equal comparison + bool ule(uint64_t RHS) const { + return ule(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + bool sle(const APInt& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when considered signed. + /// @brief Signed less or equal comparison + bool sle(uint64_t RHS) const { + return sle(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + bool ugt(const APInt& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when considered unsigned. + /// @brief Unsigned greater than comparison + bool ugt(uint64_t RHS) const { + return ugt(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + bool sgt(const APInt& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when considered signed. + /// @brief Signed greater than comparison + bool sgt(uint64_t RHS) const { + return sgt(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + bool uge(const APInt& RHS) const { + return !ult(RHS); + } + + /// Regards both *this as an unsigned quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when considered unsigned. + /// @brief Unsigned greater or equal comparison + bool uge(uint64_t RHS) const { + return uge(APInt(getBitWidth(), RHS)); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + bool sge(const APInt& RHS) const { + return !slt(RHS); + } + + /// Regards both *this as a signed quantity and compares it with RHS for + /// the validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when considered signed. + /// @brief Signed greater or equal comparison + bool sge(uint64_t RHS) const { + return sge(APInt(getBitWidth(), RHS)); + } + + + + + /// This operation tests if there are any pairs of corresponding bits + /// between this APInt and RHS that are both set. + bool intersects(const APInt &RHS) const { + return (*this & RHS) != 0; + } + + /// @} + /// @name Resizing Operators + /// @{ + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + /// @brief Truncate to new width. + APInt trunc(unsigned width) const; + + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + /// @brief Sign extend to a new width. + APInt sext(unsigned width) const; + + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + /// @brief Zero extend to a new width. + APInt zext(unsigned width) const; + + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + /// @brief Sign extend or truncate to width + APInt sextOrTrunc(unsigned width) const; + + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + /// @brief Zero extend or truncate to width + APInt zextOrTrunc(unsigned width) const; + + /// @} + /// @name Bit Manipulation Operators + /// @{ + /// @brief Set every bit to 1. + void setAllBits() { + if (isSingleWord()) + VAL = -1ULL; + else { + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; + } + // Clear the unused ones + clearUnusedBits(); + } + + /// Set the given bit to 1 whose position is given as "bitPosition". + /// @brief Set a given bit to 1. + void setBit(unsigned bitPosition); + + /// @brief Set every bit to 0. + void clearAllBits() { + if (isSingleWord()) + VAL = 0; + else + memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + void clearBit(unsigned bitPosition); + + /// @brief Toggle every bit to its opposite value. + void flipAllBits() { + if (isSingleWord()) + VAL ^= -1ULL; + else { + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; + } + clearUnusedBits(); + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + void flipBit(unsigned bitPosition); + + /// @} + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + unsigned getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this APInt. + /// @brief Get the number of words. + unsigned getNumWords() const { + return getNumWords(BitWidth); + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value with a + /// given bit width. + /// @brief Get the number of words. + static unsigned getNumWords(unsigned BitWidth) { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + unsigned getActiveBits() const { + return BitWidth - countLeadingZeros(); + } + + /// This function returns the number of active words in the value of this + /// APInt. This is used in conjunction with getActiveData to extract the raw + /// value of the APInt. + unsigned getActiveWords() const { + return whichWord(getActiveBits()-1) + 1; + } + + /// Computes the minimum bit width for this APInt while considering it to be + /// a signed (and probably negative) value. If the value is not negative, + /// this function returns the same value as getActiveBits()+1. Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + /// @brief Get the minimum bit size for this signed APInt + unsigned getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits()+1; + } + + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + uint64_t getZExtValue() const { + if (isSingleWord()) + return VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return pVal[0]; + } + + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + int64_t getSExtValue() const { + if (isSingleWord()) + return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> + (APINT_BITS_PER_WORD - BitWidth); + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \arg str. + /// @brief Get bits required for string value. + static unsigned getBitsNeeded(StringRef str, uint8_t radix); + + /// countLeadingZeros - This function is an APInt version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + unsigned countLeadingZeros() const { + if (isSingleWord()) { + unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; + return CountLeadingZeros_64(VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } + + /// countLeadingOnes - This function is an APInt version of the + /// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number + /// of ones from the most significant bit to the first zero bit. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + unsigned countLeadingOnes() const; + + /// Computes the number of leading bits of this APInt that are equal to its + /// sign bit. + unsigned getNumSignBits() const { + return isNegative() ? countLeadingOnes() : countLeadingZeros(); + } + + /// countTrailingZeros - This function is an APInt version of the + /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + unsigned countTrailingZeros() const; + + /// countTrailingOnes - This function is an APInt version of the + /// countTrailingOnes_{32,64} functions in MathExtras.h. It counts + /// the number of ones from the least significant bit to the first zero bit. + /// @returns BitWidth if the value is all ones. + /// @returns the number of ones from the least significant bit to the first + /// zero bit. + /// @brief Count the number of trailing one bits. + unsigned countTrailingOnes() const { + if (isSingleWord()) + return CountTrailingOnes_64(VAL); + return countTrailingOnesSlowCase(); + } + + /// countPopulation - This function is an APInt version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the APInt value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + unsigned countPopulation() const { + if (isSingleWord()) + return CountPopulation_64(VAL); + return countPopulationSlowCase(); + } + + /// @} + /// @name Conversion Functions + /// @{ + void print(raw_ostream &OS, bool isSigned) const; + + /// toString - Converts an APInt to a string and append it to Str. Str is + /// commonly a SmallString. + void toString(SmallVectorImpl &Str, unsigned Radix, bool Signed) const; + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + void toStringUnsigned(SmallVectorImpl &Str, unsigned Radix = 10) const { + toString(Str, Radix, false); + } + + /// Considers the APInt to be signed and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + void toStringSigned(SmallVectorImpl &Str, unsigned Radix = 10) const { + toString(Str, Radix, true); + } + + /// toString - This returns the APInt as a std::string. Note that this is an + /// inefficient method. It is better to pass in a SmallVector/SmallString + /// to the methods above to avoid thrashing the heap for the string. + std::string toString(unsigned Radix, bool Signed) const; + + + /// @returns a byte-swapped representation of this APInt Value. + APInt byteSwap() const; + + /// @brief Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// @brief Converts this unsigned APInt to a double value. + double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts APInt bits to a double + double bitsToDouble() const { + union { + uint64_t I; + double D; + } T; + T.I = (isSingleWord() ? VAL : pVal[0]); + return T.D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts APInt bits to a double + float bitsToFloat() const { + union { + unsigned I; + float F; + } T; + T.I = unsigned((isSingleWord() ? VAL : pVal[0])); + return T.F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. + /// @brief Converts a double to APInt bits. + static APInt doubleToBits(double V) { + union { + uint64_t I; + double D; + } T; + T.D = V; + return APInt(sizeof T * CHAR_BIT, T.I); + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. + /// @brief Converts a float to APInt bits. + static APInt floatToBits(float V) { + union { + unsigned I; + float F; + } T; + T.F = V; + return APInt(sizeof T * CHAR_BIT, T.I); + } + + /// @} + /// @name Mathematics Operations + /// @{ + + /// @returns the floor log base 2 of this APInt. + unsigned logBase2() const { + return BitWidth - 1 - countLeadingZeros(); + } + + /// @returns the ceil log base 2 of this APInt. + unsigned ceilLogBase2() const { + return BitWidth - (*this - 1).countLeadingZeros(); + } + + /// @returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// @brief Compute the square root + APInt sqrt() const; + + /// If *this is < 0 then return -(*this), otherwise *this; + /// @brief Get the absolute value; + APInt abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + /// @returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt& modulo) const; + + /// @} + /// @name Support for division by constant + /// @{ + + /// Calculate the magic number for signed division by a constant. + struct ms; + ms magic() const; + + /// Calculate the magic number for unsigned division by a constant. + struct mu; + mu magicu() const; + + /// @} + /// @name Building-block Operations for APInt and APFloat + /// @{ + + // These building block operations operate on a representation of + // arbitrary precision, two's-complement, bignum integer values. + // They should be sufficient to implement APInt and APFloat bignum + // requirements. Inputs are generally a pointer to the base of an + // array of integer parts, representing an unsigned bignum, and a + // count of how many parts there are. + + /// Sets the least significant part of a bignum to the input value, + /// and zeroes out higher parts. */ + static void tcSet(integerPart *, integerPart, unsigned int); + + /// Assign one bignum to another. + static void tcAssign(integerPart *, const integerPart *, unsigned int); + + /// Returns true if a bignum is zero, false otherwise. + static bool tcIsZero(const integerPart *, unsigned int); + + /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. + static int tcExtractBit(const integerPart *, unsigned int bit); + + /// Copy the bit vector of width srcBITS from SRC, starting at bit + /// srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB + /// becomes the least significant bit of DST. All high bits above + /// srcBITS in DST are zero-filled. + static void tcExtract(integerPart *, unsigned int dstCount, + const integerPart *, + unsigned int srcBits, unsigned int srcLSB); + + /// Set the given bit of a bignum. Zero-based. + static void tcSetBit(integerPart *, unsigned int bit); + + /// Clear the given bit of a bignum. Zero-based. + static void tcClearBit(integerPart *, unsigned int bit); + + /// Returns the bit number of the least or most significant set bit + /// of a number. If the input number has no bits set -1U is + /// returned. + static unsigned int tcLSB(const integerPart *, unsigned int); + static unsigned int tcMSB(const integerPart *parts, unsigned int n); + + /// Negate a bignum in-place. + static void tcNegate(integerPart *, unsigned int); + + /// DST += RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcAdd(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcSubtract(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false + /// + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + /// they must start at the same point, i.e. DST == SRC. + /// + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is + /// returned. Otherwise DST is filled with the least significant + /// DSTPARTS parts of the result, and if all of the omitted higher + /// parts were zero return zero, otherwise overflow occurred and + /// return one. + static int tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add); + + /// DST = LHS * RHS, where DST has the same width as the operands + /// and is filled with the least significant parts of the result. + /// Returns one if overflow occurred, otherwise zero. DST must be + /// disjoint from both operands. + static int tcMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of + /// the operands. No overflow occurs. DST must be disjoint from + /// both operands. Returns the number of parts required to hold the + /// result. + static unsigned int tcFullMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned, unsigned); + + /// If RHS is zero LHS and REMAINDER are left unchanged, return one. + /// Otherwise set LHS to LHS / RHS with the fractional part + /// discarded, set REMAINDER to the remainder, return zero. i.e. + /// + /// OLD_LHS = RHS * LHS + REMAINDER + /// + /// SCRATCH is a bignum of the same size as the operands and result + /// for use by the routine; its contents need not be initialized + /// and are destroyed. LHS, REMAINDER and SCRATCH must be + /// distinct. + static int tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *scratch, + unsigned int parts); + + /// Shift a bignum left COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftLeft(integerPart *, unsigned int parts, + unsigned int count); + + /// Shift a bignum right COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftRight(integerPart *, unsigned int parts, + unsigned int count); + + /// The obvious AND, OR and XOR and complement operations. + static void tcAnd(integerPart *, const integerPart *, unsigned int); + static void tcOr(integerPart *, const integerPart *, unsigned int); + static void tcXor(integerPart *, const integerPart *, unsigned int); + static void tcComplement(integerPart *, unsigned int); + + /// Comparison (unsigned) of two bignums. + static int tcCompare(const integerPart *, const integerPart *, + unsigned int); + + /// Increment a bignum in-place. Return the carry flag. + static integerPart tcIncrement(integerPart *, unsigned int); + + /// Set the least significant BITS and clear the rest. + static void tcSetLeastSignificantBits(integerPart *, unsigned int, + unsigned int bits); + + /// @brief debug method + void dump() const; + + /// @} +}; + +/// Magic data for optimising signed division by a constant. +struct APInt::ms { + APInt m; ///< magic number + unsigned s; ///< shift amount +}; + +/// Magic data for optimising unsigned division by a constant. +struct APInt::mu { + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount +}; + +inline bool operator==(uint64_t V1, const APInt& V2) { + return V2 == V1; +} + +inline bool operator!=(uint64_t V1, const APInt& V2) { + return V2 != V1; +} + +inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { + I.print(OS, true); + return OS; +} + +namespace APIntOps { + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be signed. +inline APInt smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be unsigned. +inline APInt umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// @brief Check if the specified APInt has a N-bits unsigned integer value. +inline bool isIntN(unsigned N, const APInt& APIVal) { + return APIVal.isIntN(N); +} + +/// @brief Check if the specified APInt has a N-bits signed integer value. +inline bool isSignedIntN(unsigned N, const APInt& APIVal) { + return APIVal.isSignedIntN(N); +} + +/// @returns true if the argument APInt value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +inline bool isMask(unsigned numBits, const APInt& APIVal) { + return numBits <= APIVal.getBitWidth() && + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); +} + +/// @returns true if the argument APInt value contains a sequence of ones +/// with the remainder zero. +inline bool isShiftedMask(unsigned numBits, const APInt& APIVal) { + return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal); +} + +/// @returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt& APIVal) { + return APIVal.byteSwap(); +} + +/// @returns the floor log base 2 of the specified APInt value. +inline unsigned logBase2(const APInt& APIVal) { + return APIVal.logBase2(); +} + +/// GreatestCommonDivisor - This function returns the greatest common +/// divisor of the two APInt values using Euclid's algorithm. +/// @returns the greatest common divisor of Val1 and Val2 +/// @brief Compute GCD of two APInt values. +APInt GreatestCommonDivisor(const APInt& Val1, const APInt& Val2); + +/// Treats the APInt as an unsigned value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundAPIntToDouble(const APInt& APIVal) { + return APIVal.roundToDouble(); +} + +/// Treats the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundSignedAPIntToDouble(const APInt& APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// @brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt& APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// Treast the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a float value. +inline float RoundSignedAPIntToFloat(const APInt& APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// RoundDoubleToAPInt - This function convert a double value to an APInt value. +/// @brief Converts the given double value into a APInt. +APInt RoundDoubleToAPInt(double Double, unsigned width); + +/// RoundFloatToAPInt - Converts a float value into an APInt value. +/// @brief Converts a float value into a APInt. +inline APInt RoundFloatToAPInt(float Float, unsigned width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +inline APInt ashr(const APInt& LHS, unsigned shiftAmt) { + return LHS.ashr(shiftAmt); +} + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +inline APInt lshr(const APInt& LHS, unsigned shiftAmt) { + return LHS.lshr(shiftAmt); +} + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +inline APInt shl(const APInt& LHS, unsigned shiftAmt) { + return LHS.shl(shiftAmt); +} + +/// Signed divide APInt LHS by APInt RHS. +/// @brief Signed division function for APInt. +inline APInt sdiv(const APInt& LHS, const APInt& RHS) { + return LHS.sdiv(RHS); +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +inline APInt udiv(const APInt& LHS, const APInt& RHS) { + return LHS.udiv(RHS); +} + +/// Signed remainder operation on APInt. +/// @brief Function for signed remainder operation. +inline APInt srem(const APInt& LHS, const APInt& RHS) { + return LHS.srem(RHS); +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +inline APInt urem(const APInt& LHS, const APInt& RHS) { + return LHS.urem(RHS); +} + +/// Performs multiplication on APInt values. +/// @brief Function for multiplication operation. +inline APInt mul(const APInt& LHS, const APInt& RHS) { + return LHS * RHS; +} + +/// Performs addition on APInt values. +/// @brief Function for addition operation. +inline APInt add(const APInt& LHS, const APInt& RHS) { + return LHS + RHS; +} + +/// Performs subtraction on APInt values. +/// @brief Function for subtraction operation. +inline APInt sub(const APInt& LHS, const APInt& RHS) { + return LHS - RHS; +} + +/// Performs bitwise AND operation on APInt LHS and +/// APInt RHS. +/// @brief Bitwise AND function for APInt. +inline APInt And(const APInt& LHS, const APInt& RHS) { + return LHS & RHS; +} + +/// Performs bitwise OR operation on APInt LHS and APInt RHS. +/// @brief Bitwise OR function for APInt. +inline APInt Or(const APInt& LHS, const APInt& RHS) { + return LHS | RHS; +} + +/// Performs bitwise XOR operation on APInt. +/// @brief Bitwise XOR function for APInt. +inline APInt Xor(const APInt& LHS, const APInt& RHS) { + return LHS ^ RHS; +} + +/// Performs a bitwise complement operation on APInt. +/// @brief Bitwise complement function. +inline APInt Not(const APInt& APIVal) { + return ~APIVal; +} + +} // End of APIntOps namespace + +} // End of llvm namespace + +#endif diff --git a/final/include/llvm/ADT/APSInt.h b/final/include/llvm/ADT/APSInt.h new file mode 100644 index 00000000000..54a7b601d1f --- /dev/null +++ b/final/include/llvm/ADT/APSInt.h @@ -0,0 +1,266 @@ +//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APSINT_H +#define LLVM_APSINT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + +class APSInt : public APInt { + bool IsUnsigned; +public: + /// Default constructor that creates an uninitialized APInt. + explicit APSInt() {} + + /// APSInt ctor - Create an APSInt with the specified width, default to + /// unsigned. + explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) + : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} + + explicit APSInt(const APInt &I, bool isUnsigned = true) + : APInt(I), IsUnsigned(isUnsigned) {} + + APSInt &operator=(const APSInt &RHS) { + APInt::operator=(RHS); + IsUnsigned = RHS.IsUnsigned; + return *this; + } + + APSInt &operator=(const APInt &RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + APSInt &operator=(uint64_t RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + // Query sign information. + bool isSigned() const { return !IsUnsigned; } + bool isUnsigned() const { return IsUnsigned; } + void setIsUnsigned(bool Val) { IsUnsigned = Val; } + void setIsSigned(bool Val) { IsUnsigned = !Val; } + + /// toString - Append this APSInt to the specified SmallString. + void toString(SmallVectorImpl &Str, unsigned Radix = 10) const { + APInt::toString(Str, Radix, isSigned()); + } + /// toString - Converts an APInt to a std::string. This is an inefficient + /// method, your should prefer passing in a SmallString instead. + std::string toString(unsigned Radix) const { + return APInt::toString(Radix, isSigned()); + } + using APInt::toString; + + APSInt trunc(uint32_t width) const { + return APSInt(APInt::trunc(width), IsUnsigned); + } + + APSInt extend(uint32_t width) const { + if (IsUnsigned) + return APSInt(zext(width), IsUnsigned); + else + return APSInt(sext(width), IsUnsigned); + } + + APSInt extOrTrunc(uint32_t width) const { + if (IsUnsigned) + return APSInt(zextOrTrunc(width), IsUnsigned); + else + return APSInt(sextOrTrunc(width), IsUnsigned); + } + + const APSInt &operator%=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = urem(RHS); + else + *this = srem(RHS); + return *this; + } + const APSInt &operator/=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = udiv(RHS); + else + *this = sdiv(RHS); + return *this; + } + APSInt operator%(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); + } + APSInt operator/(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); + } + + APSInt operator>>(unsigned Amt) const { + return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); + } + APSInt& operator>>=(unsigned Amt) { + *this = *this >> Amt; + return *this; + } + + inline bool operator<(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ult(RHS) : slt(RHS); + } + inline bool operator>(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ugt(RHS) : sgt(RHS); + } + inline bool operator<=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ule(RHS) : sle(RHS); + } + inline bool operator>=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? uge(RHS) : sge(RHS); + } + + // The remaining operators just wrap the logic of APInt, but retain the + // signedness information. + + APSInt operator<<(unsigned Bits) const { + return APSInt(static_cast(*this) << Bits, IsUnsigned); + } + APSInt& operator<<=(unsigned Amt) { + *this = *this << Amt; + return *this; + } + + APSInt& operator++() { + static_cast(*this)++; + return *this; + } + APSInt& operator--() { + static_cast(*this)--; + return *this; + } + APSInt operator++(int) { + return APSInt(++static_cast(*this), IsUnsigned); + } + APSInt operator--(int) { + return APSInt(--static_cast(*this), IsUnsigned); + } + APSInt operator-() const { + return APSInt(-static_cast(*this), IsUnsigned); + } + APSInt& operator+=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) += RHS; + return *this; + } + APSInt& operator-=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) -= RHS; + return *this; + } + APSInt& operator*=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) *= RHS; + return *this; + } + APSInt& operator&=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) &= RHS; + return *this; + } + APSInt& operator|=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) |= RHS; + return *this; + } + APSInt& operator^=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast(*this) ^= RHS; + return *this; + } + + APSInt operator&(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) & RHS, IsUnsigned); + } + APSInt And(const APSInt& RHS) const { + return this->operator&(RHS); + } + + APSInt operator|(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) | RHS, IsUnsigned); + } + APSInt Or(const APSInt& RHS) const { + return this->operator|(RHS); + } + + + APSInt operator^(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) ^ RHS, IsUnsigned); + } + APSInt Xor(const APSInt& RHS) const { + return this->operator^(RHS); + } + + APSInt operator*(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) * RHS, IsUnsigned); + } + APSInt operator+(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) + RHS, IsUnsigned); + } + APSInt operator-(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast(*this) - RHS, IsUnsigned); + } + APSInt operator~() const { + return APSInt(~static_cast(*this), IsUnsigned); + } + + /// getMaxValue - Return the APSInt representing the maximum integer value + /// with the given bit width and signedness. + static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMaxValue(numBits) + : APInt::getSignedMaxValue(numBits), Unsigned); + } + + /// getMinValue - Return the APSInt representing the minimum integer value + /// with the given bit width and signedness. + static APSInt getMinValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMinValue(numBits) + : APInt::getSignedMinValue(numBits), Unsigned); + } + + /// Profile - Used to insert APSInt objects, or objects that contain APSInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& ID) const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { + I.print(OS, I.isSigned()); + return OS; +} + + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/ArrayRef.h b/final/include/llvm/ADT/ArrayRef.h new file mode 100644 index 00000000000..ebddb1287eb --- /dev/null +++ b/final/include/llvm/ADT/ArrayRef.h @@ -0,0 +1,137 @@ +//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ARRAYREF_H +#define LLVM_ADT_ARRAYREF_H + +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + class APInt; + + /// ArrayRef - Represent a constant reference to an array (0 or more elements + /// consecutively in memory), i.e. a start pointer and a length. It allows + /// various APIs to take consecutive elements easily and conveniently. + /// + /// This class does not own the underlying data, it is expected to be used in + /// situations where the data resides in some other buffer, whose lifetime + /// extends past that of the StringRef. For this reason, it is not in general + /// safe to store a ArrayRef. + /// + /// This is intended to be trivially copyable, so it should be passed by + /// value. + template + class ArrayRef { + public: + typedef const T *iterator; + typedef const T *const_iterator; + typedef size_t size_type; + + private: + /// The start of the array, in an external buffer. + const T *Data; + + /// The number of elements. + size_t Length; + + public: + /// @name Constructors + /// @{ + + /// Construct an empty ArrayRef. + /*implicit*/ ArrayRef() : Data(0), Length(0) {} + + /// Construct an ArrayRef from a single element. + /*implicit*/ ArrayRef(const T &OneElt) + : Data(&OneElt), Length(1) {} + + /// Construct an ArrayRef from a pointer and length. + /*implicit*/ ArrayRef(const T *data, size_t length) + : Data(data), Length(length) {} + + /// Construct an ArrayRef from a SmallVector. + /*implicit*/ ArrayRef(const SmallVectorImpl &Vec) + : Data(Vec.data()), Length(Vec.size()) {} + + /// Construct an ArrayRef from a std::vector. + /*implicit*/ ArrayRef(const std::vector &Vec) + : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {} + + /// Construct an ArrayRef from a C array. + template + /*implicit*/ ArrayRef(const T (&Arr)[N]) + : Data(Arr), Length(N) {} + + /// @} + /// @name Simple Operations + /// @{ + + iterator begin() const { return Data; } + iterator end() const { return Data + Length; } + + /// empty - Check if the array is empty. + bool empty() const { return Length == 0; } + + const T *data() const { return Data; } + + /// size - Get the array size. + size_t size() const { return Length; } + + /// front - Get the first element. + const T &front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last element. + const T &back() const { + assert(!empty()); + return Data[Length-1]; + } + + /// slice(n) - Chop off the first N elements of the array. + ArrayRef slice(unsigned N) { + assert(N <= size() && "Invalid specifier"); + return ArrayRef(data()+N, size()-N); + } + + /// slice(n, m) - Chop off the first N elements of the array, and keep M + /// elements in the array. + ArrayRef slice(unsigned N, unsigned M) { + assert(N+M <= size() && "Invalid specifier"); + return ArrayRef(data()+N, M); + } + + /// @} + /// @name Operator Overloads + /// @{ + const T &operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Expensive Operations + /// @{ + std::vector vec() const { + return std::vector(Data, Data+Length); + } + + /// @} + }; + + // ArrayRefs can be treated like a POD type. + template struct isPodLike; + template struct isPodLike > { + static const bool value = true; + }; +} + +#endif diff --git a/final/include/llvm/ADT/BitVector.h b/final/include/llvm/ADT/BitVector.h new file mode 100644 index 00000000000..ac1cf0c79a8 --- /dev/null +++ b/final/include/llvm/ADT/BitVector.h @@ -0,0 +1,433 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/Support/MathExtras.h" +#include +#include +#include +#include +#include + +namespace llvm { + +class BitVector { + typedef unsigned long BitWord; + + enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + + BitWord *Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Size of allocated memory in BitWord. + +public: + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + reference(); // Undefined + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + ~reference() {} + + reference &operator=(reference t) { + *this = bool(t); + return *this; + } + + reference& operator=(bool t) { + if (t) + *WordRef |= 1L << BitPos; + else + *WordRef &= ~(1L << BitPos); + return *this; + } + + operator bool() const { + return ((*WordRef) & (1L << BitPos)) ? true : false; + } + }; + + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0), Capacity(0) { + Bits = 0; + } + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + Capacity = NumBitWords(s); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + init_words(Bits, Capacity, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = 0; + Capacity = 0; + return; + } + + Capacity = NumBitWords(RHS.size()); + Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); + } + + ~BitVector() { + std::free(Bits); + } + + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { return Size == 0; } + + /// size - Returns the number of bits in this bitvector. + unsigned size() const { return Size; } + + /// count - Returns the number of bits which are set. + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// all - Returns true if all bits are set. + bool all() const { + // TODO: Optimize this. + return count() == size(); + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + ++Prev; + if (Prev >= Size) + return -1; + + unsigned WordPos = Prev / BITWORD_SIZE; + unsigned BitPos = Prev % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// clear - Clear all bits. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > Capacity * BITWORD_SIZE) { + unsigned OldCapacity = Capacity; + grow(N); + init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + } + + // Set any old unused bits that are now included in the BitVector. This + // may set bits that are not included in the new vector, but we will clear + // them back out below. + if (N > Size) + set_unused_bits(t); + + // Update the size, and clear out any bits that are now unused + unsigned OldSize = Size; + Size = N; + if (t || N < OldSize) + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > Capacity * BITWORD_SIZE) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, Capacity, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + BitVector &reset() { + init_words(Bits, Capacity, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + // No argument flip. + BitVector operator~() const { + return BitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + assert (Idx < Size && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert (Idx < Size && "Out-of-bounds Bit access."); + BitWord Mask = 1L << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + + // Verify that any extra words are all zeros. + if (i != ThisWords) { + for (; i != ThisWords; ++i) + if (Bits[i]) + return false; + } else if (i != RHSWords) { + for (; i != RHSWords; ++i) + if (RHS.Bits[i]) + return false; + } + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + BitVector &operator&=(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= RHS.Bits[i]; + + // Any bits that are just in this bitvector become zero, because they aren't + // in the RHS bit vector. Any words only in RHS are ignored because they + // are already zero in the LHS. + for (; i != ThisWords; ++i) + Bits[i] = 0; + + return *this; + } + + BitVector &operator|=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector &operator^=(const BitVector &RHS) { + if (size() < RHS.size()) + resize(RHS.size()); + for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= Capacity * BITWORD_SIZE) { + if (Size) + std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord)); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + Capacity = RHSWords; + BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); + std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); + + // Destroy the old bits. + std::free(Bits); + Bits = NewBits; + + return *this; + } + + void swap(BitVector &RHS) { + std::swap(Bits, RHS.Bits); + std::swap(Size, RHS.Size); + std::swap(Capacity, RHS.Capacity); + } + +private: + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Set the unused bits in the high words. + void set_unused_bits(bool t = true) { + // Set high words first. + unsigned UsedWords = NumBitWords(Size); + if (Capacity > UsedWords) + init_words(&Bits[UsedWords], (Capacity-UsedWords), t); + + // Then set any stray high bits of the last used word. + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + Bits[UsedWords-1] &= ~(~0L << ExtraBits); + Bits[UsedWords-1] |= (0 - (BitWord)t) << ExtraBits; + } + } + + // Clear the unused bits in the high words. + void clear_unused_bits() { + set_unused_bits(false); + } + + void grow(unsigned NewSize) { + Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); + + clear_unused_bits(); + } + + void init_words(BitWord *B, unsigned NumWords, bool t) { + memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); + } +}; + +inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::BitVector &LHS, llvm::BitVector &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/final/include/llvm/ADT/DAGDeltaAlgorithm.h b/final/include/llvm/ADT/DAGDeltaAlgorithm.h new file mode 100644 index 00000000000..99ed15c0d60 --- /dev/null +++ b/final/include/llvm/ADT/DAGDeltaAlgorithm.h @@ -0,0 +1,75 @@ +//===--- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DAGDELTAALGORITHM_H +#define LLVM_ADT_DAGDELTAALGORITHM_H + +#include +#include + +namespace llvm { + +/// DAGDeltaAlgorithm - Implements a "delta debugging" algorithm for minimizing +/// directed acyclic graphs using a predicate function. +/// +/// The result of the algorithm is a subset of the input change set which is +/// guaranteed to satisfy the predicate, assuming that the input set did. For +/// well formed predicates, the result set is guaranteed to be such that +/// removing any single element not required by the dependencies on the other +/// elements would falsify the predicate. +/// +/// The DAG should be used to represent dependencies in the changes which are +/// likely to hold across the predicate function. That is, for a particular +/// changeset S and predicate P: +/// +/// P(S) => P(S union pred(S)) +/// +/// The minization algorithm uses this dependency information to attempt to +/// eagerly prune large subsets of changes. As with \see DeltaAlgorithm, the DAG +/// is not required to satisfy this property, but the algorithm will run +/// substantially fewer tests with appropriate dependencies. \see DeltaAlgorithm +/// for more information on the properties which the predicate function itself +/// should satisfy. +class DAGDeltaAlgorithm { +public: + typedef unsigned change_ty; + typedef std::pair edge_ty; + + // FIXME: Use a decent data structure. + typedef std::set changeset_ty; + typedef std::vector changesetlist_ty; + +public: + virtual ~DAGDeltaAlgorithm() {} + + /// Run - Minimize the DAG formed by the \arg Changes vertices and the \arg + /// Dependencies edges by executing \see ExecuteOneTest() on subsets of + /// changes and returning the smallest set which still satisfies the test + /// predicate and the input \arg Dependencies. + /// + /// \param Changes The list of changes. + /// + /// \param Dependencies The list of dependencies amongst changes. For each + /// (x,y) in \arg Dependencies, both x and y must be in \arg Changes. The + /// minimization algorithm guarantees that for each tested changed set S, x + /// \in S implies y \in S. It is an error to have cyclic dependencies. + changeset_ty Run(const changeset_ty &Changes, + const std::vector &Dependencies); + + /// UpdatedSearchState - Callback used when the search state changes. + virtual void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets, + const changeset_ty &Required) {} + + /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + virtual bool ExecuteOneTest(const changeset_ty &S) = 0; +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/DeltaAlgorithm.h b/final/include/llvm/ADT/DeltaAlgorithm.h new file mode 100644 index 00000000000..45ba19891d4 --- /dev/null +++ b/final/include/llvm/ADT/DeltaAlgorithm.h @@ -0,0 +1,91 @@ +//===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DELTAALGORITHM_H +#define LLVM_ADT_DELTAALGORITHM_H + +#include +#include + +namespace llvm { + +/// DeltaAlgorithm - Implements the delta debugging algorithm (A. Zeller '99) +/// for minimizing arbitrary sets using a predicate function. +/// +/// The result of the algorithm is a subset of the input change set which is +/// guaranteed to satisfy the predicate, assuming that the input set did. For +/// well formed predicates, the result set is guaranteed to be such that +/// removing any single element would falsify the predicate. +/// +/// For best results the predicate function *should* (but need not) satisfy +/// certain properties, in particular: +/// (1) The predicate should return false on an empty set and true on the full +/// set. +/// (2) If the predicate returns true for a set of changes, it should return +/// true for all supersets of that set. +/// +/// It is not an error to provide a predicate that does not satisfy these +/// requirements, and the algorithm will generally produce reasonable +/// results. However, it may run substantially more tests than with a good +/// predicate. +class DeltaAlgorithm { +public: + typedef unsigned change_ty; + // FIXME: Use a decent data structure. + typedef std::set changeset_ty; + typedef std::vector changesetlist_ty; + +private: + /// Cache of failed test results. Successful test results are never cached + /// since we always reduce following a success. + std::set FailedTestsCache; + + /// GetTestResult - Get the test result for the \arg Changes from the + /// cache, executing the test if necessary. + /// + /// \param Changes - The change set to test. + /// \return - The test result. + bool GetTestResult(const changeset_ty &Changes); + + /// Split - Partition a set of changes \arg S into one or two subsets. + void Split(const changeset_ty &S, changesetlist_ty &Res); + + /// Delta - Minimize a set of \arg Changes which has been partioned into + /// smaller sets, by attempting to remove individual subsets. + changeset_ty Delta(const changeset_ty &Changes, + const changesetlist_ty &Sets); + + /// Search - Search for a subset (or subsets) in \arg Sets which can be + /// removed from \arg Changes while still satisfying the predicate. + /// + /// \param Res - On success, a subset of Changes which satisfies the + /// predicate. + /// \return - True on success. + bool Search(const changeset_ty &Changes, const changesetlist_ty &Sets, + changeset_ty &Res); + +protected: + /// UpdatedSearchState - Callback used when the search state changes. + virtual void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets) {} + + /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + virtual bool ExecuteOneTest(const changeset_ty &S) = 0; + +public: + virtual ~DeltaAlgorithm(); + + /// Run - Minimize the set \arg Changes by executing \see ExecuteOneTest() on + /// subsets of changes and returning the smallest set which still satisfies + /// the test predicate. + changeset_ty Run(const changeset_ty &Changes); +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/DenseMap.h b/final/include/llvm/ADT/DenseMap.h new file mode 100644 index 00000000000..9d2b11d6b2b --- /dev/null +++ b/final/include/llvm/ADT/DenseMap.h @@ -0,0 +1,533 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- 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 DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include "llvm/ADT/DenseMapInfo.h" +#include +#include +#include +#include +#include +#include +#include + +namespace llvm { + +template, + typename ValueInfoT = DenseMapInfo, bool IsConst = false> +class DenseMapIterator; + +template, + typename ValueInfoT = DenseMapInfo > +class DenseMap { + typedef std::pair BucketT; + unsigned NumBuckets; + BucketT *Buckets; + + unsigned NumEntries; + unsigned NumTombstones; +public: + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef BucketT value_type; + + DenseMap(const DenseMap &other) { + NumBuckets = 0; + CopyFrom(other); + } + + explicit DenseMap(unsigned NumInitBuckets = 0) { + init(NumInitBuckets); + } + + template + DenseMap(const InputIt &I, const InputIt &E) { + init(NextPowerOf2(std::distance(I, E))); + insert(I, E); + } + + ~DenseMap() { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } +#ifndef NDEBUG + if (NumBuckets) + memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); +#endif + operator delete(Buckets); + } + + typedef DenseMapIterator iterator; + typedef DenseMapIterator const_iterator; + inline iterator begin() { + // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). + return empty() ? end() : iterator(Buckets, Buckets+NumBuckets); + } + inline iterator end() { + return iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + inline const_iterator begin() const { + return empty() ? end() : const_iterator(Buckets, Buckets+NumBuckets); + } + inline const_iterator end() const { + return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + + bool empty() const { return NumEntries == 0; } + unsigned size() const { return NumEntries; } + + /// Grow the densemap so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { + if (Size > NumBuckets) + grow(Size); + } + + void clear() { + if (NumEntries == 0 && NumTombstones == 0) return; + + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (NumEntries * 4 < NumBuckets && NumBuckets > 64) { + shrink_and_clear(); + return; + } + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey)) { + if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { + P->second.~ValueT(); + --NumEntries; + } + P->first = EmptyKey; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + NumTombstones = 0; + } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket); + } + + iterator find(const KeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + const_iterator find(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return TheBucket->second; + return ValueT(); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair insert(const std::pair &KV) { + BucketT *TheBucket; + if (LookupBucketFor(KV.first, TheBucket)) + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + true); + } + + /// insert - Range insertion of pairs. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + void erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + } + + void swap(DenseMap& RHS) { + std::swap(NumBuckets, RHS.NumBuckets); + std::swap(Buckets, RHS.Buckets); + std::swap(NumEntries, RHS.NumEntries); + std::swap(NumTombstones, RHS.NumTombstones); + } + + value_type& FindAndConstruct(const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(Key, ValueT(), TheBucket); + } + + ValueT &operator[](const KeyT &Key) { + return FindAndConstruct(Key).second; + } + + DenseMap& operator=(const DenseMap& other) { + CopyFrom(other); + return *this; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the DenseMap's array of buckets (i.e. either to a key or + /// value in the DenseMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Ptr >= Buckets && Ptr < Buckets+NumBuckets; + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the DenseMap to reallocate. + const void *getPointerIntoBucketsArray() const { return Buckets; } + +private: + void CopyFrom(const DenseMap& other) { + if (NumBuckets != 0 && + (!isPodLike::value || !isPodLike::value)) { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } + } + + NumEntries = other.NumEntries; + NumTombstones = other.NumTombstones; + + if (NumBuckets) { +#ifndef NDEBUG + memset(Buckets, 0x5a, sizeof(BucketT)*NumBuckets); +#endif + operator delete(Buckets); + } + + NumBuckets = other.NumBuckets; + + if (NumBuckets == 0) { + Buckets = 0; + return; + } + + Buckets = static_cast(operator new(sizeof(BucketT) * NumBuckets)); + + if (isPodLike::value && isPodLike::value) + memcpy(Buckets, other.Buckets, NumBuckets * sizeof(BucketT)); + else + for (size_t i = 0; i < NumBuckets; ++i) { + new (&Buckets[i].first) KeyT(other.Buckets[i].first); + if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && + !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) + new (&Buckets[i].second) ValueT(other.Buckets[i].second); + } + } + + BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, + BucketT *TheBucket) { + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + ++NumEntries; + if (NumEntries*4 >= NumBuckets*3 || + NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + this->grow(NumBuckets * 2); + LookupBucketFor(Key, TheBucket); + } + + // If we are writing over a tombstone, remember this. + if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) + --NumTombstones; + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(Value); + return TheBucket; + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const { + unsigned BucketNo = getHashValue(Val); + unsigned ProbeAmt = 1; + BucketT *BucketsPtr = Buckets; + + if (NumBuckets == 0) { + FoundBucket = 0; + return false; + } + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + BucketT *FoundTombstone = 0; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(!KeyInfoT::isEqual(Val, EmptyKey) && + !KeyInfoT::isEqual(Val, TombstoneKey) && + "Empty/Tombstone value shouldn't be inserted into map!"); + + while (1) { + BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); + // Found Val's bucket? If so, return it. + if (KeyInfoT::isEqual(ThisBucket->first, Val)) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + if (FoundTombstone) ThisBucket = FoundTombstone; + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + } + } + + void init(unsigned InitBuckets) { + NumEntries = 0; + NumTombstones = 0; + NumBuckets = InitBuckets; + + if (InitBuckets == 0) { + Buckets = 0; + return; + } + + assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && + "# initial buckets must be a power of two!"); + Buckets = static_cast(operator new(sizeof(BucketT)*InitBuckets)); + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0; i != InitBuckets; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + if (NumBuckets < 64) + NumBuckets = 64; + + // Double the number of buckets. + while (NumBuckets < AtLeast) + NumBuckets <<= 1; + NumTombstones = 0; + Buckets = static_cast(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Insert all the old elements. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->first, DestBucket); + (void)FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->first = B->first; + new (&DestBucket->second) ValueT(B->second); + + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + +#ifndef NDEBUG + memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); +#endif + // Free the old table. + operator delete(OldBuckets); + } + + void shrink_and_clear() { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Reduce the number of buckets. + NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1) + : 64; + NumTombstones = 0; + Buckets = static_cast(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Free the old buckets. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + +#ifndef NDEBUG + memset(OldBuckets, 0x5a, sizeof(BucketT)*OldNumBuckets); +#endif + // Free the old table. + operator delete(OldBuckets); + + NumEntries = 0; + } +}; + +template +class DenseMapIterator { + typedef std::pair Bucket; + typedef DenseMapIterator ConstIterator; + friend class DenseMapIterator; +public: + typedef ptrdiff_t difference_type; + typedef typename conditional::type value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef std::forward_iterator_tag iterator_category; +private: + pointer Ptr, End; +public: + DenseMapIterator() : Ptr(0), End(0) {} + + DenseMapIterator(pointer Pos, pointer E) : Ptr(Pos), End(E) { + AdvancePastEmptyBuckets(); + } + + // If IsConst is true this is a converting constructor from iterator to + // const_iterator and the default copy constructor is used. + // Otherwise this is a copy constructor for iterator. + DenseMapIterator(const DenseMapIterator& I) + : Ptr(I.Ptr), End(I.End) {} + + reference operator*() const { + return *Ptr; + } + pointer operator->() const { + return Ptr; + } + + bool operator==(const ConstIterator &RHS) const { + return Ptr == RHS.operator->(); + } + bool operator!=(const ConstIterator &RHS) const { + return Ptr != RHS.operator->(); + } + + inline DenseMapIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && + (KeyInfoT::isEqual(Ptr->first, Empty) || + KeyInfoT::isEqual(Ptr->first, Tombstone))) + ++Ptr; + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/DenseMapInfo.h b/final/include/llvm/ADT/DenseMapInfo.h new file mode 100644 index 00000000000..25e341bf4fd --- /dev/null +++ b/final/include/llvm/ADT/DenseMapInfo.h @@ -0,0 +1,165 @@ +//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- 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 DenseMapInfo traits for DenseMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAPINFO_H +#define LLVM_ADT_DENSEMAPINFO_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { + +template +struct DenseMapInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isEqual(const T &LHS, const T &RHS); +}; + +// Provide DenseMapInfo for all pointers. +template +struct DenseMapInfo { + static inline T* getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return reinterpret_cast(Val); + } + static inline T* getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return reinterpret_cast(Val); + } + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo { + static inline char getEmptyKey() { return ~0; } + static inline char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37; } + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned ints. +template<> struct DenseMapInfo { + static inline unsigned getEmptyKey() { return ~0; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37; } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned longs. +template<> struct DenseMapInfo { + static inline unsigned long getEmptyKey() { return ~0UL; } + static inline unsigned long getTombstoneKey() { return ~0UL - 1L; } + static unsigned getHashValue(const unsigned long& Val) { + return (unsigned)(Val * 37UL); + } + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned long longs. +template<> struct DenseMapInfo { + static inline unsigned long long getEmptyKey() { return ~0ULL; } + static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; } + static unsigned getHashValue(const unsigned long long& Val) { + return (unsigned)(Val * 37ULL); + } + static bool isEqual(const unsigned long long& LHS, + const unsigned long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for ints. +template<> struct DenseMapInfo { + static inline int getEmptyKey() { return 0x7fffffff; } + static inline int getTombstoneKey() { return -0x7fffffff - 1; } + static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37); } + static bool isEqual(const int& LHS, const int& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for longs. +template<> struct DenseMapInfo { + static inline long getEmptyKey() { + return (1UL << (sizeof(long) * 8 - 1)) - 1L; + } + static inline long getTombstoneKey() { return getEmptyKey() - 1L; } + static unsigned getHashValue(const long& Val) { + return (unsigned)(Val * 37L); + } + static bool isEqual(const long& LHS, const long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for long longs. +template<> struct DenseMapInfo { + static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } + static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } + static unsigned getHashValue(const long long& Val) { + return (unsigned)(Val * 37LL); + } + static bool isEqual(const long long& LHS, + const long long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template +struct DenseMapInfo > { + typedef std::pair Pair; + typedef DenseMapInfo FirstInfo; + typedef DenseMapInfo SecondInfo; + + static inline Pair getEmptyKey() { + return std::make_pair(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + static inline Pair getTombstoneKey() { + return std::make_pair(FirstInfo::getTombstoneKey(), + SecondInfo::getEmptyKey()); + } + static unsigned getHashValue(const Pair& PairVal) { + uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 + | (uint64_t)SecondInfo::getHashValue(PairVal.second); + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return (unsigned)key; + } + static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/DenseSet.h b/final/include/llvm/ADT/DenseSet.h new file mode 100644 index 00000000000..67321f53984 --- /dev/null +++ b/final/include/llvm/ADT/DenseSet.h @@ -0,0 +1,129 @@ +//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- 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 DenseSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSESET_H +#define LLVM_ADT_DENSESET_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +/// DenseSet - This implements a dense probed hash-table based set. +/// +/// FIXME: This is currently implemented directly in terms of DenseMap, this +/// should be optimized later if there is a need. +template > +class DenseSet { + typedef DenseMap MapTy; + MapTy TheMap; +public: + DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} + explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {} + + bool empty() const { return TheMap.empty(); } + unsigned size() const { return TheMap.size(); } + + /// Grow the denseset so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { TheMap.resize(Size); } + + void clear() { + TheMap.clear(); + } + + bool count(const ValueT &V) const { + return TheMap.count(V); + } + + bool erase(const ValueT &V) { + return TheMap.erase(V); + } + + void swap(DenseSet& RHS) { + TheMap.swap(RHS.TheMap); + } + + DenseSet &operator=(const DenseSet &RHS) { + TheMap = RHS.TheMap; + return *this; + } + + // Iterators. + + class Iterator { + typename MapTy::iterator I; + friend class DenseSet; + public: + typedef typename MapTy::iterator::difference_type difference_type; + typedef ValueT value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef std::forward_iterator_tag iterator_category; + + Iterator(const typename MapTy::iterator &i) : I(i) {} + + ValueT& operator*() { return I->first; } + ValueT* operator->() { return &I->first; } + + Iterator& operator++() { ++I; return *this; } + bool operator==(const Iterator& X) const { return I == X.I; } + bool operator!=(const Iterator& X) const { return I != X.I; } + }; + + class ConstIterator { + typename MapTy::const_iterator I; + friend class DenseSet; + public: + typedef typename MapTy::const_iterator::difference_type difference_type; + typedef ValueT value_type; + typedef value_type *pointer; + typedef value_type &reference; + typedef std::forward_iterator_tag iterator_category; + + ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} + + const ValueT& operator*() { return I->first; } + const ValueT* operator->() { return &I->first; } + + ConstIterator& operator++() { ++I; return *this; } + bool operator==(const ConstIterator& X) const { return I == X.I; } + bool operator!=(const ConstIterator& X) const { return I != X.I; } + }; + + typedef Iterator iterator; + typedef ConstIterator const_iterator; + + iterator begin() { return Iterator(TheMap.begin()); } + iterator end() { return Iterator(TheMap.end()); } + + const_iterator begin() const { return ConstIterator(TheMap.begin()); } + const_iterator end() const { return ConstIterator(TheMap.end()); } + + iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); } + void erase(Iterator I) { return TheMap.erase(I.I); } + void erase(ConstIterator CI) { return TheMap.erase(CI.I); } + + std::pair insert(const ValueT &V) { + return TheMap.insert(std::make_pair(V, 0)); + } + + // Range insertion of values. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/DepthFirstIterator.h b/final/include/llvm/ADT/DepthFirstIterator.h new file mode 100644 index 00000000000..dd13a2c0205 --- /dev/null +++ b/final/include/llvm/ADT/DepthFirstIterator.h @@ -0,0 +1,268 @@ +//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build generic depth +// first graph iterator. This file exposes the following functions/types: +// +// df_begin/df_end/df_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// +// idf_begin/idf_end/idf_iterator +// * Depth-first iteration on the 'inverse' graph. +// +// df_ext_begin/df_ext_end/df_ext_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +// idf_ext_begin/idf_ext_end/idf_ext_iterator +// * Depth-first iteration on the 'inverse' graph. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H +#define LLVM_ADT_DEPTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include +#include + +namespace llvm { + +// df_iterator_storage - A private class which is used to figure out where to +// store the visited set. +template // Non-external set +class df_iterator_storage { +public: + SetType Visited; +}; + +template +class df_iterator_storage { +public: + df_iterator_storage(SetType &VSet) : Visited(VSet) {} + df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + + +// Generic Depth First Iterator +template::NodeType*, 8>, + bool ExtStorage = false, class GT = GraphTraits > +class df_iterator : public std::iterator, + public df_iterator_storage { + typedef std::iterator super; + + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef PointerIntPair PointerIntTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is node pointer, second is the 'next child' to visit + // if the int in PointerIntTy is 0, the 'next child' to visit is invalid + std::vector > VisitStack; +private: + inline df_iterator(NodeType *Node) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0), + GT::child_begin(Node))); + } + inline df_iterator() { + // End is when stack is empty + } + inline df_iterator(NodeType *Node, SetType &S) + : df_iterator_storage(S) { + if (!S.count(Node)) { + VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0), + GT::child_begin(Node))); + this->Visited.insert(Node); + } + } + inline df_iterator(SetType &S) + : df_iterator_storage(S) { + // End is when stack is empty + } + + inline void toNext() { + do { + std::pair &Top = VisitStack.back(); + NodeType *Node = Top.first.getPointer(); + ChildItTy &It = Top.second; + if (!Top.first.getInt()) { + // now retrieve the real begin of the children before we dive in + It = GT::child_begin(Node); + Top.first.setInt(1); + } + + while (It != GT::child_end(Node)) { + NodeType *Next = *It++; + // Has our next sibling been visited? + if (Next && !this->Visited.count(Next)) { + // No, do it now. + this->Visited.insert(Next); + VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0), + GT::child_begin(Next))); + return; + } + } + + // Oops, ran out of successors... go up a level on the stack. + VisitStack.pop_back(); + } while (!VisitStack.empty()); + } + +public: + typedef typename super::pointer pointer; + typedef df_iterator _Self; + + // Provide static begin and end methods as our public "constructors" + static inline _Self begin(const GraphT& G) { + return _Self(GT::getEntryNode(G)); + } + static inline _Self end(const GraphT& G) { return _Self(); } + + // Static begin and end methods as our public ctors for external iterators + static inline _Self begin(const GraphT& G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.back().first.getPointer(); + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the Node, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + toNext(); + return *this; + } + + // skips all children of the current node and traverses to next node + // + inline _Self& skipChildren() { + VisitStack.pop_back(); + if (!VisitStack.empty()) + toNext(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // nodeVisited - return true if this iterator has already visited the + // specified node. This is public, and will probably be used to iterate over + // nodes that a depth first iteration did not find: ie unreachable nodes. + // + inline bool nodeVisited(NodeType *Node) const { + return this->Visited.count(Node) != 0; + } + + /// getPathLength - Return the length of the path from the entry node to the + /// current node, counting both nodes. + unsigned getPathLength() const { return VisitStack.size(); } + + /// getPath - Return the n'th node in the path from the the entry node to the + /// current node. + NodeType *getPath(unsigned n) const { + return VisitStack[n].first.getPointer(); + } +}; + + +// Provide global constructors that automatically figure out correct types... +// +template +df_iterator df_begin(const T& G) { + return df_iterator::begin(G); +} + +template +df_iterator df_end(const T& G) { + return df_iterator::end(G); +} + +// Provide global definitions of external depth first iterators... +template ::NodeType*> > +struct df_ext_iterator : public df_iterator { + df_ext_iterator(const df_iterator &V) + : df_iterator(V) {} +}; + +template +df_ext_iterator df_ext_begin(const T& G, SetTy &S) { + return df_ext_iterator::begin(G, S); +} + +template +df_ext_iterator df_ext_end(const T& G, SetTy &S) { + return df_ext_iterator::end(G, S); +} + + +// Provide global definitions of inverse depth first iterators... +template ::NodeType*, 8>, + bool External = false> +struct idf_iterator : public df_iterator, SetTy, External> { + idf_iterator(const df_iterator, SetTy, External> &V) + : df_iterator, SetTy, External>(V) {} +}; + +template +idf_iterator idf_begin(const T& G) { + return idf_iterator::begin(Inverse(G)); +} + +template +idf_iterator idf_end(const T& G){ + return idf_iterator::end(Inverse(G)); +} + +// Provide global definitions of external inverse depth first iterators... +template ::NodeType*> > +struct idf_ext_iterator : public idf_iterator { + idf_ext_iterator(const idf_iterator &V) + : idf_iterator(V) {} + idf_ext_iterator(const df_iterator, SetTy, true> &V) + : idf_iterator(V) {} +}; + +template +idf_ext_iterator idf_ext_begin(const T& G, SetTy &S) { + return idf_ext_iterator::begin(Inverse(G), S); +} + +template +idf_ext_iterator idf_ext_end(const T& G, SetTy &S) { + return idf_ext_iterator::end(Inverse(G), S); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/EquivalenceClasses.h b/final/include/llvm/ADT/EquivalenceClasses.h new file mode 100644 index 00000000000..771476c3036 --- /dev/null +++ b/final/include/llvm/ADT/EquivalenceClasses.h @@ -0,0 +1,281 @@ +//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generic implementation of equivalence classes through the use Tarjan's +// efficient union-find algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EQUIVALENCECLASSES_H +#define LLVM_ADT_EQUIVALENCECLASSES_H + +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { + +/// EquivalenceClasses - This represents a collection of equivalence classes and +/// supports three efficient operations: insert an element into a class of its +/// own, union two classes, and find the class for a given element. In +/// addition to these modification methods, it is possible to iterate over all +/// of the equivalence classes and all of the elements in a class. +/// +/// This implementation is an efficient implementation that only stores one copy +/// of the element being indexed per entry in the set, and allows any arbitrary +/// type to be indexed (as long as it can be ordered with operator<). +/// +/// Here is a simple example using integers: +/// +/// EquivalenceClasses EC; +/// EC.unionSets(1, 2); // insert 1, 2 into the same set +/// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets +/// EC.unionSets(5, 1); // merge the set for 1 with 5's set. +/// +/// for (EquivalenceClasses::iterator I = EC.begin(), E = EC.end(); +/// I != E; ++I) { // Iterate over all of the equivalence sets. +/// if (!I->isLeader()) continue; // Ignore non-leader sets. +/// for (EquivalenceClasses::member_iterator MI = EC.member_begin(I); +/// MI != EC.member_end(); ++MI) // Loop over members in this set. +/// cerr << *MI << " "; // Print member. +/// cerr << "\n"; // Finish set. +/// } +/// +/// This example prints: +/// 4 +/// 5 1 2 +/// +template +class EquivalenceClasses { + /// ECValue - The EquivalenceClasses data structure is just a set of these. + /// Each of these represents a relation for a value. First it stores the + /// value itself, which provides the ordering that the set queries. Next, it + /// provides a "next pointer", which is used to enumerate all of the elements + /// in the unioned set. Finally, it defines either a "end of list pointer" or + /// "leader pointer" depending on whether the value itself is a leader. A + /// "leader pointer" points to the node that is the leader for this element, + /// if the node is not a leader. A "end of list pointer" points to the last + /// node in the list of members of this list. Whether or not a node is a + /// leader is determined by a bit stolen from one of the pointers. + class ECValue { + friend class EquivalenceClasses; + mutable const ECValue *Leader, *Next; + ElemTy Data; + // ECValue ctor - Start out with EndOfList pointing to this node, Next is + // Null, isLeader = true. + ECValue(const ElemTy &Elt) + : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {} + + const ECValue *getLeader() const { + if (isLeader()) return this; + if (Leader->isLeader()) return Leader; + // Path compression. + return Leader = Leader->getLeader(); + } + const ECValue *getEndOfList() const { + assert(isLeader() && "Cannot get the end of a list for a non-leader!"); + return Leader; + } + + void setNext(const ECValue *NewNext) const { + assert(getNext() == 0 && "Already has a next pointer!"); + Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); + } + public: + ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), + Data(RHS.Data) { + // Only support copying of singleton nodes. + assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!"); + } + + bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } + + bool isLeader() const { return (intptr_t)Next & 1; } + const ElemTy &getData() const { return Data; } + + const ECValue *getNext() const { + return (ECValue*)((intptr_t)Next & ~(intptr_t)1); + } + + template + bool operator<(const T &Val) const { return Data < Val; } + }; + + /// TheMapping - This implicitly provides a mapping from ElemTy values to the + /// ECValues, it just keeps the key as part of the value. + std::set TheMapping; + +public: + EquivalenceClasses() {} + EquivalenceClasses(const EquivalenceClasses &RHS) { + operator=(RHS); + } + + const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) { + TheMapping.clear(); + for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) + if (I->isLeader()) { + member_iterator MI = RHS.member_begin(I); + member_iterator LeaderIt = member_begin(insert(*MI)); + for (++MI; MI != member_end(); ++MI) + unionSets(LeaderIt, member_begin(insert(*MI))); + } + return *this; + } + + //===--------------------------------------------------------------------===// + // Inspection methods + // + + /// iterator* - Provides a way to iterate over all values in the set. + typedef typename std::set::const_iterator iterator; + iterator begin() const { return TheMapping.begin(); } + iterator end() const { return TheMapping.end(); } + + bool empty() const { return TheMapping.empty(); } + + /// member_* Iterate over the members of an equivalence class. + /// + class member_iterator; + member_iterator member_begin(iterator I) const { + // Only leaders provide anything to iterate over. + return member_iterator(I->isLeader() ? &*I : 0); + } + member_iterator member_end() const { + return member_iterator(0); + } + + /// findValue - Return an iterator to the specified value. If it does not + /// exist, end() is returned. + iterator findValue(const ElemTy &V) const { + return TheMapping.find(V); + } + + /// getLeaderValue - Return the leader for the specified value that is in the + /// set. It is an error to call this method for a value that is not yet in + /// the set. For that, call getOrInsertLeaderValue(V). + const ElemTy &getLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(V); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getOrInsertLeaderValue - Return the leader for the specified value that is + /// in the set. If the member is not in the set, it is inserted, then + /// returned. + const ElemTy &getOrInsertLeaderValue(const ElemTy &V) { + member_iterator MI = findLeader(insert(V)); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getNumClasses - Return the number of equivalence classes in this set. + /// Note that this is a linear time operation. + unsigned getNumClasses() const { + unsigned NC = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->isLeader()) ++NC; + return NC; + } + + + //===--------------------------------------------------------------------===// + // Mutation methods + + /// insert - Insert a new value into the union/find set, ignoring the request + /// if the value already exists. + iterator insert(const ElemTy &Data) { + return TheMapping.insert(ECValue(Data)).first; + } + + /// findLeader - Given a value in the set, return a member iterator for the + /// equivalence class it is in. This does the path-compression part that + /// makes union-find "union findy". This returns an end iterator if the value + /// is not in the equivalence class. + /// + member_iterator findLeader(iterator I) const { + if (I == TheMapping.end()) return member_end(); + return member_iterator(I->getLeader()); + } + member_iterator findLeader(const ElemTy &V) const { + return findLeader(TheMapping.find(V)); + } + + + /// union - Merge the two equivalence sets for the specified values, inserting + /// them if they do not already exist in the equivalence set. + member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) { + iterator V1I = insert(V1), V2I = insert(V2); + return unionSets(findLeader(V1I), findLeader(V2I)); + } + member_iterator unionSets(member_iterator L1, member_iterator L2) { + assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!"); + if (L1 == L2) return L1; // Unifying the same two sets, noop. + + // Otherwise, this is a real union operation. Set the end of the L1 list to + // point to the L2 leader node. + const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node; + L1LV.getEndOfList()->setNext(&L2LV); + + // Update L1LV's end of list pointer. + L1LV.Leader = L2LV.getEndOfList(); + + // Clear L2's leader flag: + L2LV.Next = L2LV.getNext(); + + // L2's leader is now L1. + L2LV.Leader = &L1LV; + return L1; + } + + class member_iterator : public std::iterator { + typedef std::iterator super; + const ECValue *Node; + friend class EquivalenceClasses; + public: + typedef size_t size_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; + + explicit member_iterator() {} + explicit member_iterator(const ECValue *N) : Node(N) {} + member_iterator(const member_iterator &I) : Node(I.Node) {} + + reference operator*() const { + assert(Node != 0 && "Dereferencing end()!"); + return Node->getData(); + } + reference operator->() const { return operator*(); } + + member_iterator &operator++() { + assert(Node != 0 && "++'d off the end of the list!"); + Node = Node->getNext(); + return *this; + } + + member_iterator operator++(int) { // postincrement operators. + member_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const member_iterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const member_iterator &RHS) const { + return Node != RHS.Node; + } + }; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/FoldingSet.h b/final/include/llvm/ADT/FoldingSet.h new file mode 100644 index 00000000000..879dbd05e17 --- /dev/null +++ b/final/include/llvm/ADT/FoldingSet.h @@ -0,0 +1,684 @@ +//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- 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 hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class APFloat; + class APInt; + class BumpPtrAllocator; + +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplify node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) const { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M with be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new +/// node with FindNodeOrInsertPos; +/// +/// InsertNode(N, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = RemoveNode(N); +/// +/// The result indicates whether the node existed in the folding set. + +class FoldingSetNodeID; + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetImpl { +protected: + /// Buckets - Array of bucket chains. + /// + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + +public: + explicit FoldingSetImpl(unsigned Log2InitSize = 6); + virtual ~FoldingSetImpl(); + + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + /// + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; + + public: + + Node() : NextInFoldingSetBucket(0) {} + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// clear - Remove all nodes from the folding set. + void clear(); + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. + void InsertNode(Node *N) { + Node *Inserted = GetOrInsertNode(N); + (void)Inserted; + assert(Inserted == N && "Node already inserted!"); + } + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return NumNodes; } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return NumNodes == 0; } + +private: + + /// GrowHashTable - Double the size of the hash table and rehash everything. + /// + void GrowHashTable(); + +protected: + + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0; + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compare the given node with the given ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const=0; + /// NodeEquals - Instantiations of the FoldingSet template implement + /// this function to compute a hash value for the given node. + virtual unsigned ComputeNodeHash(Node *N, + FoldingSetNodeID &TempID) const = 0; +}; + +//===----------------------------------------------------------------------===// + +template struct FoldingSetTrait; + +/// DefaultFoldingSetTrait - This class provides default implementations +/// for FoldingSetTrait implementations. +/// +template struct DefaultFoldingSetTrait { + static void Profile(const T& X, FoldingSetNodeID& ID) { + X.Profile(ID); + } + static void Profile(T& X, FoldingSetNodeID& ID) { + X.Profile(ID); + } + + // Equals - Test if the profile for X would match ID, using TempID + // to compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular comparison. Implementations + // can override this to provide more efficient implementations. + static inline bool Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID); + + // ComputeHash - Compute a hash value for X, using TempID to + // compute a temporary ID if necessary. The default implementation + // just calls Profile and does a regular hash computation. + // Implementations can override this to provide more efficient + // implementations. + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID); +}; + +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper class, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +template struct FoldingSetTrait + : public DefaultFoldingSetTrait {}; + +template struct ContextualFoldingSetTrait; + +/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but +/// for ContextualFoldingSets. +template +struct DefaultContextualFoldingSetTrait { + static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) { + X.Profile(ID, Context); + } + static inline bool Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID, Ctx Context); + static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID, + Ctx Context); +}; + +/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for +/// ContextualFoldingSets. +template struct ContextualFoldingSetTrait + : public DefaultContextualFoldingSetTrait {}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeIDRef - This class describes a reference to an interned +/// FoldingSetNodeID, which can be a useful to store node id data rather +/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector +/// is often much larger than necessary, and the possibility of heap +/// allocation means it requires a non-trivial destructor call. +class FoldingSetNodeIDRef { + const unsigned* Data; + size_t Size; +public: + FoldingSetNodeIDRef() : Data(0), Size(0) {} + FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, + /// used to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + bool operator==(FoldingSetNodeIDRef) const; + + const unsigned *getData() const { return Data; } + size_t getSize() const { return Size; } +}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeID - This class is used to gather all the unique data bits of +/// a node. When all the bits are gathered this class is used to produce a +/// hash value for the node. +/// +class FoldingSetNodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector Bits; + +public: + FoldingSetNodeID() {} + + FoldingSetNodeID(FoldingSetNodeIDRef Ref) + : Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {} + + /// Add* - Add various data types to Bit data. + /// + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(long I); + void AddInteger(unsigned long I); + void AddInteger(long long I); + void AddInteger(unsigned long long I); + void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } + void AddString(StringRef String); + + template + inline void Add(const T& x) { FoldingSetTrait::Profile(x, *this); } + + /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID + /// object to be used to compute a new profile. + inline void clear() { Bits.clear(); } + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used + /// to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + /// + bool operator==(const FoldingSetNodeID &RHS) const; + bool operator==(const FoldingSetNodeIDRef RHS) const; + + /// Intern - Copy this node's data to a memory region allocated from the + /// given allocator and return a FoldingSetNodeIDRef describing the + /// interned data. + FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const; +}; + +// Convenience type to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +template class FoldingSetIterator; +template class FoldingSetBucketIterator; + +// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which +// require the definition of FoldingSetNodeID. +template +inline bool +DefaultFoldingSetTrait::Equals(T &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) { + FoldingSetTrait::Profile(X, TempID); + return TempID == ID; +} +template +inline unsigned +DefaultFoldingSetTrait::ComputeHash(T &X, FoldingSetNodeID &TempID) { + FoldingSetTrait::Profile(X, TempID); + return TempID.ComputeHash(); +} +template +inline bool +DefaultContextualFoldingSetTrait::Equals(T &X, + const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait::Profile(X, TempID, Context); + return TempID == ID; +} +template +inline unsigned +DefaultContextualFoldingSetTrait::ComputeHash(T &X, + FoldingSetNodeID &TempID, + Ctx Context) { + ContextualFoldingSetTrait::Profile(X, TempID, Context); + return TempID.ComputeHash(); +} + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +template class FoldingSet : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const { + T *TN = static_cast(N); + FoldingSetTrait::Profile(*TN, ID); + } + /// NodeEquals - Instantiations may optionally provide a way to compare a + /// node with a specified ID. + virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const { + T *TN = static_cast(N); + return FoldingSetTrait::Equals(*TN, ID, TempID); + } + /// NodeEquals - Instantiations may optionally provide a way to compute a + /// hash value directly from a node. + virtual unsigned ComputeNodeHash(Node *N, + FoldingSetNodeID &TempID) const { + T *TN = static_cast(N); + return FoldingSetTrait::ComputeHash(*TN, TempID); + } + +public: + explicit FoldingSet(unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize) + {} + + typedef FoldingSetIterator iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// ContextualFoldingSet - This template class is a further refinement +/// of FoldingSet which provides a context argument when calling +/// Profile on its nodes. Currently, that argument is fixed at +/// initialization time. +/// +/// T must be a subclass of FoldingSetNode and implement a Profile +/// function with signature +/// void Profile(llvm::FoldingSetNodeID &, Ctx); +template +class ContextualFoldingSet : public FoldingSetImpl { + // Unfortunately, this can't derive from FoldingSet because the + // construction vtable for FoldingSet requires + // FoldingSet::GetNodeProfile to be instantiated, which in turn + // requires a single-argument T::Profile(). + +private: + Ctx Context; + + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(FoldingSetImpl::Node *N, + FoldingSetNodeID &ID) const { + T *TN = static_cast(N); + ContextualFoldingSetTrait::Profile(*TN, ID, Context); + } + virtual bool NodeEquals(FoldingSetImpl::Node *N, + const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) const { + T *TN = static_cast(N); + return ContextualFoldingSetTrait::Equals(*TN, ID, TempID, Context); + } + virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N, + FoldingSetNodeID &TempID) const { + T *TN = static_cast(N); + return ContextualFoldingSetTrait::ComputeHash(*TN, TempID, Context); + } + +public: + explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize), Context(Context) + {} + + Ctx getContext() const { return Context; } + + + typedef FoldingSetIterator iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' + /// and return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it + /// exists, return it. If not, return the insertion token that will + /// make insertion faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetIteratorImpl - This is the common iterator support shared by all +/// folding sets, which knows how to walk the folding set hash table. +class FoldingSetIteratorImpl { +protected: + FoldingSetNode *NodePtr; + FoldingSetIteratorImpl(void **Bucket); + void advance(); + +public: + bool operator==(const FoldingSetIteratorImpl &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const FoldingSetIteratorImpl &RHS) const { + return NodePtr != RHS.NodePtr; + } +}; + + +template +class FoldingSetIterator : public FoldingSetIteratorImpl { +public: + explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {} + + T &operator*() const { + return *static_cast(NodePtr); + } + + T *operator->() const { + return static_cast(NodePtr); + } + + inline FoldingSetIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetIterator operator++(int) { // Postincrement + FoldingSetIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support +/// shared by all folding sets, which knows how to walk a particular bucket +/// of a folding set hash table. + +class FoldingSetBucketIteratorImpl { +protected: + void *Ptr; + + explicit FoldingSetBucketIteratorImpl(void **Bucket); + + FoldingSetBucketIteratorImpl(void **Bucket, bool) + : Ptr(Bucket) {} + + void advance() { + void *Probe = static_cast(Ptr)->getNextInBucket(); + uintptr_t x = reinterpret_cast(Probe) & ~0x1; + Ptr = reinterpret_cast(x); + } + +public: + bool operator==(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr != RHS.Ptr; + } +}; + + +template +class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { +public: + explicit FoldingSetBucketIterator(void **Bucket) : + FoldingSetBucketIteratorImpl(Bucket) {} + + FoldingSetBucketIterator(void **Bucket, bool) : + FoldingSetBucketIteratorImpl(Bucket, true) {} + + T& operator*() const { return *static_cast(Ptr); } + T* operator->() const { return static_cast(Ptr); } + + inline FoldingSetBucketIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetBucketIterator operator++(int) { // Postincrement + FoldingSetBucketIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; +public: + explicit FoldingSetNodeWrapper(const T& x) : data(x) {} + virtual ~FoldingSetNodeWrapper() {} + + template + explicit FoldingSetNodeWrapper(const A1& a1) + : data(a1) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2) + : data(a1,a2) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3) + : data(a1,a2,a3) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) + : data(a1,a2,a3,a4) {} + + template + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4, const A5& a5) + : data(a1,a2,a3,a4,a5) {} + + + void Profile(FoldingSetNodeID& ID) { FoldingSetTrait::Profile(data, ID); } + + T& getValue() { return data; } + const T& getValue() const { return data; } + + operator T&() { return data; } + operator const T&() const { return data; } +}; + +//===----------------------------------------------------------------------===// +/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores +/// a FoldingSetNodeID value rather than requiring the node to recompute it +/// each time it is needed. This trades space for speed (which can be +/// significant if the ID is long), and it also permits nodes to drop +/// information that would otherwise only be required for recomputing an ID. +class FastFoldingSetNode : public FoldingSetNode { + FoldingSetNodeID FastID; +protected: + explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {} +public: + void Profile(FoldingSetNodeID& ID) const { ID = FastID; } +}; + +//===----------------------------------------------------------------------===// +// Partial specializations of FoldingSetTrait. + +template struct FoldingSetTrait { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +template struct FoldingSetTrait { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +} // End of namespace llvm. + +#endif diff --git a/final/include/llvm/ADT/GraphTraits.h b/final/include/llvm/ADT/GraphTraits.h new file mode 100644 index 00000000000..0fd1f5022af --- /dev/null +++ b/final/include/llvm/ADT/GraphTraits.h @@ -0,0 +1,103 @@ +//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- 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 little GraphTraits template class that should be +// specialized by classes that want to be iteratable by generic graph iterators. +// +// This file also defines the marker class Inverse that is used to iterate over +// graphs in a graph defined, inverse ordering... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_GRAPHTRAITS_H +#define LLVM_ADT_GRAPHTRAITS_H + +namespace llvm { + +// GraphTraits - This class should be specialized by different graph types... +// which is why the default version is empty. +// +template +struct GraphTraits { + // Elements to provide: + + // typedef NodeType - Type of Node in the graph + // typedef ChildIteratorType - Type used to iterate over children in graph + + // static NodeType *getEntryNode(const GraphType &) + // Return the entry node of the graph + + // static ChildIteratorType child_begin(NodeType *) + // static ChildIteratorType child_end (NodeType *) + // Return iterators that point to the beginning and ending of the child + // node list for the specified node. + // + + + // typedef ...iterator nodes_iterator; + // static nodes_iterator nodes_begin(GraphType *G) + // static nodes_iterator nodes_end (GraphType *G) + // + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + + + // If anyone tries to use this class without having an appropriate + // specialization, make an error. If you get this error, it's because you + // need to include the appropriate specialization of GraphTraits<> for your + // graph, or you need to define it for a new graph type. Either that or + // your argument to XXX_begin(...) is unknown or needs to have the proper .h + // file #include'd. + // + typedef typename GraphType::UnknownGraphTypeError NodeType; +}; + + +// Inverse - This class is used as a little marker class to tell the graph +// iterator to iterate over the graph in a graph defined "Inverse" ordering. +// Not all graphs define an inverse ordering, and if they do, it depends on +// the graph exactly what that is. Here's an example of usage with the +// df_iterator: +// +// idf_iterator I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +// Which is equivalent to: +// df_iterator > I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +template +struct Inverse { + const GraphType &Graph; + + inline Inverse(const GraphType &G) : Graph(G) {} +}; + +// Provide a partial specialization of GraphTraits so that the inverse of an +// inverse falls back to the original graph. +template +struct GraphTraits > > { + typedef typename GraphTraits::NodeType NodeType; + typedef typename GraphTraits::ChildIteratorType ChildIteratorType; + + static NodeType *getEntryNode(Inverse > *G) { + return GraphTraits::getEntryNode(G->Graph.Graph); + } + + static ChildIteratorType child_begin(NodeType* N) { + return GraphTraits::child_begin(N); + } + + static ChildIteratorType child_end(NodeType* N) { + return GraphTraits::child_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/ImmutableIntervalMap.h b/final/include/llvm/ADT/ImmutableIntervalMap.h new file mode 100644 index 00000000000..0d8fcf34338 --- /dev/null +++ b/final/include/llvm/ADT/ImmutableIntervalMap.h @@ -0,0 +1,242 @@ +//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- 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 ImmutableIntervalMap class. +// +//===----------------------------------------------------------------------===// +#include "llvm/ADT/ImmutableMap.h" + +namespace llvm { + +class Interval { +private: + int64_t Start; + int64_t End; + +public: + Interval(int64_t S, int64_t E) : Start(S), End(E) {} + + int64_t getStart() const { return Start; } + int64_t getEnd() const { return End; } +}; + +template +struct ImutIntervalInfo { + typedef const std::pair value_type; + typedef const value_type &value_type_ref; + typedef const Interval key_type; + typedef const Interval &key_type_ref; + typedef const T data_type; + typedef const T &data_type_ref; + + static key_type_ref KeyOfValue(value_type_ref V) { + return V.first; + } + + static data_type_ref DataOfValue(value_type_ref V) { + return V.second; + } + + static bool isEqual(key_type_ref L, key_type_ref R) { + return L.getStart() == R.getStart() && L.getEnd() == R.getEnd(); + } + + static bool isDataEqual(data_type_ref L, data_type_ref R) { + return ImutContainerInfo::isEqual(L,R); + } + + static bool isLess(key_type_ref L, key_type_ref R) { + // Assume L and R does not overlap. + if (L.getStart() < R.getStart()) { + assert(L.getEnd() < R.getStart()); + return true; + } else if (L.getStart() == R.getStart()) { + assert(L.getEnd() == R.getEnd()); + return false; + } else { + assert(L.getStart() > R.getEnd()); + return false; + } + } + + static bool isContainedIn(key_type_ref K, key_type_ref L) { + if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd()) + return true; + else + return false; + } + + static void Profile(FoldingSetNodeID &ID, value_type_ref V) { + ID.AddInteger(V.first.getStart()); + ID.AddInteger(V.first.getEnd()); + ImutProfileInfo::Profile(ID, V.second); + } +}; + +template +class ImutIntervalAVLFactory : public ImutAVLFactory { + typedef ImutAVLTree TreeTy; + typedef typename ImutInfo::value_type value_type; + typedef typename ImutInfo::value_type_ref value_type_ref; + typedef typename ImutInfo::key_type key_type; + typedef typename ImutInfo::key_type_ref key_type_ref; + typedef typename ImutInfo::data_type data_type; + typedef typename ImutInfo::data_type_ref data_type_ref; + +public: + ImutIntervalAVLFactory(BumpPtrAllocator &Alloc) + : ImutAVLFactory(Alloc) {} + + TreeTy *Add(TreeTy *T, value_type_ref V) { + T = add_internal(V,T); + this->MarkImmutable(T); + return T; + } + + TreeTy *Find(TreeTy *T, key_type_ref K) { + if (!T) + return NULL; + + key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T)); + + if (ImutInfo::isContainedIn(K, CurrentKey)) + return T; + else if (ImutInfo::isLess(K, CurrentKey)) + return Find(this->getLeft(T), K); + else + return Find(this->getRight(T), K); + } + +private: + TreeTy *add_internal(value_type_ref V, TreeTy *T) { + key_type_ref K = ImutInfo::KeyOfValue(V); + T = removeAllOverlaps(T, K); + if (this->isEmpty(T)) + return this->CreateNode(NULL, V, NULL); + + assert(!T->isMutable()); + + key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T)); + + if (ImutInfo::isLess(K, KCurrent)) + return this->Balance(add_internal(V, this->Left(T)), this->Value(T), + this->Right(T)); + else + return this->Balance(this->Left(T), this->Value(T), + add_internal(V, this->Right(T))); + } + + // Remove all overlaps from T. + TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) { + bool Changed; + do { + Changed = false; + T = removeOverlap(T, K, Changed); + this->markImmutable(T); + } while (Changed); + + return T; + } + + // Remove one overlap from T. + TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) { + if (!T) + return NULL; + Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T)); + + // If current key does not overlap the inserted key. + if (CurrentK.getStart() > K.getEnd()) + return this->Balance(removeOverlap(this->Left(T), K, Changed), + this->Value(T), this->Right(T)); + else if (CurrentK.getEnd() < K.getStart()) + return this->Balance(this->Left(T), this->Value(T), + removeOverlap(this->Right(T), K, Changed)); + + // Current key overlaps with the inserted key. + // Remove the current key. + Changed = true; + data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T)); + T = this->Remove_internal(CurrentK, T); + // Add back the unoverlapped part of the current key. + if (CurrentK.getStart() < K.getStart()) { + if (CurrentK.getEnd() <= K.getEnd()) { + Interval NewK(CurrentK.getStart(), K.getStart()-1); + return add_internal(std::make_pair(NewK, OldData), T); + } else { + Interval NewK1(CurrentK.getStart(), K.getStart()-1); + T = add_internal(std::make_pair(NewK1, OldData), T); + + Interval NewK2(K.getEnd()+1, CurrentK.getEnd()); + return add_internal(std::make_pair(NewK2, OldData), T); + } + } else { + if (CurrentK.getEnd() > K.getEnd()) { + Interval NewK(K.getEnd()+1, CurrentK.getEnd()); + return add_internal(std::make_pair(NewK, OldData), T); + } else + return T; + } + } +}; + +/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals +/// in the map are guaranteed to be disjoint. +template +class ImmutableIntervalMap + : public ImmutableMap > { + + typedef typename ImutIntervalInfo::value_type value_type; + typedef typename ImutIntervalInfo::value_type_ref value_type_ref; + typedef typename ImutIntervalInfo::key_type key_type; + typedef typename ImutIntervalInfo::key_type_ref key_type_ref; + typedef typename ImutIntervalInfo::data_type data_type; + typedef typename ImutIntervalInfo::data_type_ref data_type_ref; + typedef ImutAVLTree > TreeTy; + +public: + explicit ImmutableIntervalMap(TreeTy *R) + : ImmutableMap >(R) {} + + class Factory { + ImutIntervalAVLFactory > F; + + public: + Factory(BumpPtrAllocator& Alloc) : F(Alloc) {} + + ImmutableIntervalMap getEmptyMap() { + return ImmutableIntervalMap(F.getEmptyTree()); + } + + ImmutableIntervalMap add(ImmutableIntervalMap Old, + key_type_ref K, data_type_ref D) { + TreeTy *T = F.add(Old.Root, std::pair(K, D)); + return ImmutableIntervalMap(F.getCanonicalTree(T)); + } + + ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root, K); + return ImmutableIntervalMap(F.getCanonicalTree(T)); + } + + data_type *lookup(ImmutableIntervalMap M, key_type_ref K) { + TreeTy *T = F.Find(M.getRoot(), K); + if (T) + return &T->getValue().second; + else + return 0; + } + }; + +private: + // For ImmutableIntervalMap, the lookup operation has to be done by the + // factory. + data_type* lookup(key_type_ref K) const; +}; + +} // end namespace llvm diff --git a/final/include/llvm/ADT/ImmutableList.h b/final/include/llvm/ADT/ImmutableList.h new file mode 100644 index 00000000000..714355b9513 --- /dev/null +++ b/final/include/llvm/ADT/ImmutableList.h @@ -0,0 +1,222 @@ +//==--- ImmutableList.h - Immutable (functional) list interface --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableList class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMLIST_H +#define LLVM_ADT_IMLIST_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +template class ImmutableListFactory; + +template +class ImmutableListImpl : public FoldingSetNode { + T Head; + const ImmutableListImpl* Tail; + + ImmutableListImpl(const T& head, const ImmutableListImpl* tail = 0) + : Head(head), Tail(tail) {} + + friend class ImmutableListFactory; + + // Do not implement. + void operator=(const ImmutableListImpl&); + ImmutableListImpl(const ImmutableListImpl&); + +public: + const T& getHead() const { return Head; } + const ImmutableListImpl* getTail() const { return Tail; } + + static inline void Profile(FoldingSetNodeID& ID, const T& H, + const ImmutableListImpl* L){ + ID.AddPointer(L); + ID.Add(H); + } + + void Profile(FoldingSetNodeID& ID) { + Profile(ID, Head, Tail); + } +}; + +/// ImmutableList - This class represents an immutable (functional) list. +/// It is implemented as a smart pointer (wraps ImmutableListImpl), so it +/// it is intended to always be copied by value as if it were a pointer. +/// This interface matches ImmutableSet and ImmutableMap. ImmutableList +/// objects should almost never be created directly, and instead should +/// be created by ImmutableListFactory objects that manage the lifetime +/// of a group of lists. When the factory object is reclaimed, all lists +/// created by that factory are released as well. +template +class ImmutableList { +public: + typedef T value_type; + typedef ImmutableListFactory Factory; + +private: + const ImmutableListImpl* X; + +public: + // This constructor should normally only be called by ImmutableListFactory. + // There may be cases, however, when one needs to extract the internal pointer + // and reconstruct a list object from that pointer. + ImmutableList(const ImmutableListImpl* x = 0) : X(x) {} + + const ImmutableListImpl* getInternalPointer() const { + return X; + } + + class iterator { + const ImmutableListImpl* L; + public: + iterator() : L(0) {} + iterator(ImmutableList l) : L(l.getInternalPointer()) {} + + iterator& operator++() { L = L->getTail(); return *this; } + bool operator==(const iterator& I) const { return L == I.L; } + bool operator!=(const iterator& I) const { return L != I.L; } + const value_type& operator*() const { return L->getHead(); } + ImmutableList getList() const { return L; } + }; + + /// begin - Returns an iterator referring to the head of the list, or + /// an iterator denoting the end of the list if the list is empty. + iterator begin() const { return iterator(X); } + + /// end - Returns an iterator denoting the end of the list. This iterator + /// does not refer to a valid list element. + iterator end() const { return iterator(); } + + /// isEmpty - Returns true if the list is empty. + bool isEmpty() const { return !X; } + + /// isEqual - Returns true if two lists are equal. Because all lists created + /// from the same ImmutableListFactory are uniqued, this has O(1) complexity + /// because it the contents of the list do not need to be compared. Note + /// that you should only compare two lists created from the same + /// ImmutableListFactory. + bool isEqual(const ImmutableList& L) const { return X == L.X; } + + bool operator==(const ImmutableList& L) const { return isEqual(L); } + + /// getHead - Returns the head of the list. + const T& getHead() { + assert (!isEmpty() && "Cannot get the head of an empty list."); + return X->getHead(); + } + + /// getTail - Returns the tail of the list, which is another (possibly empty) + /// ImmutableList. + ImmutableList getTail() { + return X ? X->getTail() : 0; + } + + void Profile(FoldingSetNodeID& ID) const { + ID.AddPointer(X); + } +}; + +template +class ImmutableListFactory { + typedef ImmutableListImpl ListTy; + typedef FoldingSet CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast(Allocator & ~0x1); + } + +public: + ImmutableListFactory() + : Allocator(reinterpret_cast(new BumpPtrAllocator())) {} + + ImmutableListFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast(&Alloc) | 0x1) {} + + ~ImmutableListFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + ImmutableList concat(const T& Head, ImmutableList Tail) { + // Profile the new list to see if it already exists in our cache. + FoldingSetNodeID ID; + void* InsertPos; + + const ListTy* TailImpl = Tail.getInternalPointer(); + ListTy::Profile(ID, Head, TailImpl); + ListTy* L = Cache.FindNodeOrInsertPos(ID, InsertPos); + + if (!L) { + // The list does not exist in our cache. Create it. + BumpPtrAllocator& A = getAllocator(); + L = (ListTy*) A.Allocate(); + new (L) ListTy(Head, TailImpl); + + // Insert the new list into the cache. + Cache.InsertNode(L, InsertPos); + } + + return L; + } + + ImmutableList add(const T& D, ImmutableList L) { + return concat(D, L); + } + + ImmutableList getEmptyList() const { + return ImmutableList(0); + } + + ImmutableList create(const T& X) { + return Concat(X, getEmptyList()); + } +}; + +//===----------------------------------------------------------------------===// +// Partially-specialized Traits. +//===----------------------------------------------------------------------===// + +template struct DenseMapInfo; +template struct DenseMapInfo > { + static inline ImmutableList getEmptyKey() { + return reinterpret_cast*>(-1); + } + static inline ImmutableList getTombstoneKey() { + return reinterpret_cast*>(-2); + } + static unsigned getHashValue(ImmutableList X) { + uintptr_t PtrVal = reinterpret_cast(X.getInternalPointer()); + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(ImmutableList X1, ImmutableList X2) { + return X1 == X2; + } +}; + +template struct isPodLike; +template +struct isPodLike > { static const bool value = true; }; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/ADT/ImmutableMap.h b/final/include/llvm/ADT/ImmutableMap.h new file mode 100644 index 00000000000..d6cce7ccfa0 --- /dev/null +++ b/final/include/llvm/ADT/ImmutableMap.h @@ -0,0 +1,261 @@ +//===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMAP_H +#define LLVM_ADT_IMMAP_H + +#include "llvm/ADT/ImmutableSet.h" + +namespace llvm { + +/// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first +/// and second elements in a pair are used to generate profile information, +/// only the first element (the key) is used by isEqual and isLess. +template +struct ImutKeyValueInfo { + typedef const std::pair value_type; + typedef const value_type& value_type_ref; + typedef const T key_type; + typedef const T& key_type_ref; + typedef const S data_type; + typedef const S& data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref V) { + return V.first; + } + + static inline data_type_ref DataOfValue(value_type_ref V) { + return V.second; + } + + static inline bool isEqual(key_type_ref L, key_type_ref R) { + return ImutContainerInfo::isEqual(L,R); + } + static inline bool isLess(key_type_ref L, key_type_ref R) { + return ImutContainerInfo::isLess(L,R); + } + + static inline bool isDataEqual(data_type_ref L, data_type_ref R) { + return ImutContainerInfo::isEqual(L,R); + } + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) { + ImutContainerInfo::Profile(ID, V.first); + ImutContainerInfo::Profile(ID, V.second); + } +}; + + +template > +class ImmutableMap { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef typename ValInfo::key_type key_type; + typedef typename ValInfo::key_type_ref key_type_ref; + typedef typename ValInfo::data_type data_type; + typedef typename ValInfo::data_type_ref data_type_ref; + typedef ImutAVLTree TreeTy; + +protected: + TreeTy* Root; + +public: + /// Constructs a map from a pointer to a tree root. In general one + /// should use a Factory object to create maps instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableMap(const TreeTy* R) : Root(const_cast(R)) { + if (Root) { Root->retain(); } + } + ImmutableMap(const ImmutableMap &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableMap &operator=(const ImmutableMap &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableMap() { + if (Root) { Root->release(); } + } + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) + : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } + + ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + TreeTy *T = F.add(Old.Root, std::pair(K,D)); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); + } + + ImmutableMap remove(ImmutableMap Old, key_type_ref K) { + TreeTy *T = F.remove(Old.Root,K); + return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); + } + + private: + Factory(const Factory& RHS); // DO NOT IMPLEMENT + void operator=(const Factory& RHS); // DO NOT IMPLEMENT + }; + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + bool operator==(const ImmutableMap &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableMap &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy *getRoot() const { + if (Root) { Root->retain(); } + return Root; + } + + TreeTy *getRootWithoutRetain() const { + return Root; + } + + void manualRetain() { + if (Root) Root->retain(); + } + + void manualRelease() { + if (Root) Root->release(); + } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // Foreach - A limited form of map iteration. + //===--------------------------------------------------===// + +private: + template + struct CBWrapper { + Callback C; + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + + template + struct CBWrapperRef { + Callback &C; + CBWrapperRef(Callback& c) : C(c) {} + + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + +public: + template + void foreach(Callback& C) { + if (Root) { + CBWrapperRef CB(C); + Root->foreach(CB); + } + } + + template + void foreach() { + if (Root) { + CBWrapper CB; + Root->foreach(CB); + } + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + + iterator() {} + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableMap; + + public: + value_type_ref operator*() const { return itr->getValue(); } + value_type* operator->() const { return &itr->getValue(); } + + key_type_ref getKey() const { return itr->getValue().first; } + data_type_ref getData() const { return itr->getValue().second; } + + + iterator& operator++() { ++itr; return *this; } + iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + iterator& operator--() { --itr; return *this; } + iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + data_type* lookup(key_type_ref K) const { + if (Root) { + TreeTy* T = Root->find(K); + if (T) return &T->getValue().second; + } + + return 0; + } + + /// getMaxElement - Returns the pair in the ImmutableMap for + /// which key is the highest in the ordering of keys in the map. This + /// method returns NULL if the map is empty. + value_type* getMaxElement() const { + return Root ? &(Root->getMaxElement()->getValue()) : 0; + } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/ImmutableSet.h b/final/include/llvm/ADT/ImmutableSet.h new file mode 100644 index 00000000000..3ca910ce944 --- /dev/null +++ b/final/include/llvm/ADT/ImmutableSet.h @@ -0,0 +1,1084 @@ +//===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImutAVLTree and ImmutableSet classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMSET_H +#define LLVM_ADT_IMSET_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/DataTypes.h" +#include +#include +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Definition. +//===----------------------------------------------------------------------===// + +template class ImutAVLFactory; +template class ImutIntervalAVLFactory; +template class ImutAVLTreeInOrderIterator; +template class ImutAVLTreeGenericIterator; + +template +class ImutAVLTree { +public: + typedef typename ImutInfo::key_type_ref key_type_ref; + typedef typename ImutInfo::value_type value_type; + typedef typename ImutInfo::value_type_ref value_type_ref; + + typedef ImutAVLFactory Factory; + friend class ImutAVLFactory; + friend class ImutIntervalAVLFactory; + + friend class ImutAVLTreeGenericIterator; + + typedef ImutAVLTreeInOrderIterator iterator; + + //===----------------------------------------------------===// + // Public Interface. + //===----------------------------------------------------===// + + /// Return a pointer to the left subtree. This value + /// is NULL if there is no left subtree. + ImutAVLTree *getLeft() const { return left; } + + /// Return a pointer to the right subtree. This value is + /// NULL if there is no right subtree. + ImutAVLTree *getRight() const { return right; } + + /// getHeight - Returns the height of the tree. A tree with no subtrees + /// has a height of 1. + unsigned getHeight() const { return height; } + + /// getValue - Returns the data value associated with the tree node. + const value_type& getValue() const { return value; } + + /// find - Finds the subtree associated with the specified key value. + /// This method returns NULL if no matching subtree is found. + ImutAVLTree* find(key_type_ref K) { + ImutAVLTree *T = this; + while (T) { + key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); + if (ImutInfo::isEqual(K,CurrentKey)) + return T; + else if (ImutInfo::isLess(K,CurrentKey)) + T = T->getLeft(); + else + T = T->getRight(); + } + return NULL; + } + + /// getMaxElement - Find the subtree associated with the highest ranged + /// key value. + ImutAVLTree* getMaxElement() { + ImutAVLTree *T = this; + ImutAVLTree *Right = T->getRight(); + while (Right) { T = right; right = T->getRight(); } + return T; + } + + /// size - Returns the number of nodes in the tree, which includes + /// both leaves and non-leaf nodes. + unsigned size() const { + unsigned n = 1; + if (const ImutAVLTree* L = getLeft()) + n += L->size(); + if (const ImutAVLTree* R = getRight()) + n += R->size(); + return n; + } + + /// begin - Returns an iterator that iterates over the nodes of the tree + /// in an inorder traversal. The returned iterator thus refers to the + /// the tree node with the minimum data element. + iterator begin() const { return iterator(this); } + + /// end - Returns an iterator for the tree that denotes the end of an + /// inorder traversal. + iterator end() const { return iterator(); } + + bool isElementEqual(value_type_ref V) const { + // Compare the keys. + if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(V))) + return false; + + // Also compare the data values. + if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()), + ImutInfo::DataOfValue(V))) + return false; + + return true; + } + + bool isElementEqual(const ImutAVLTree* RHS) const { + return isElementEqual(RHS->getValue()); + } + + /// isEqual - Compares two trees for structural equality and returns true + /// if they are equal. This worst case performance of this operation is + // linear in the sizes of the trees. + bool isEqual(const ImutAVLTree& RHS) const { + if (&RHS == this) + return true; + + iterator LItr = begin(), LEnd = end(); + iterator RItr = RHS.begin(), REnd = RHS.end(); + + while (LItr != LEnd && RItr != REnd) { + if (*LItr == *RItr) { + LItr.skipSubTree(); + RItr.skipSubTree(); + continue; + } + + if (!LItr->isElementEqual(*RItr)) + return false; + + ++LItr; + ++RItr; + } + + return LItr == LEnd && RItr == REnd; + } + + /// isNotEqual - Compares two trees for structural inequality. Performance + /// is the same is isEqual. + bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); } + + /// contains - Returns true if this tree contains a subtree (node) that + /// has an data element that matches the specified key. Complexity + /// is logarithmic in the size of the tree. + bool contains(key_type_ref K) { return (bool) find(K); } + + /// foreach - A member template the accepts invokes operator() on a functor + /// object (specifed by Callback) for every node/subtree in the tree. + /// Nodes are visited using an inorder traversal. + template + void foreach(Callback& C) { + if (ImutAVLTree* L = getLeft()) + L->foreach(C); + + C(value); + + if (ImutAVLTree* R = getRight()) + R->foreach(C); + } + + /// validateTree - A utility method that checks that the balancing and + /// ordering invariants of the tree are satisifed. It is a recursive + /// method that returns the height of the tree, which is then consumed + /// by the enclosing validateTree call. External callers should ignore the + /// return value. An invalid tree will cause an assertion to fire in + /// a debug build. + unsigned validateTree() const { + unsigned HL = getLeft() ? getLeft()->validateTree() : 0; + unsigned HR = getRight() ? getRight()->validateTree() : 0; + (void) HL; + (void) HR; + + assert(getHeight() == ( HL > HR ? HL : HR ) + 1 + && "Height calculation wrong"); + + assert((HL > HR ? HL-HR : HR-HL) <= 2 + && "Balancing invariant violated"); + + assert((!getLeft() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue()))) && + "Value in left child is not less that current value"); + + + assert(!(getRight() || + ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue()))) && + "Current value is not less that value of right child"); + + return getHeight(); + } + + //===----------------------------------------------------===// + // Internal values. + //===----------------------------------------------------===// + +private: + Factory *factory; + ImutAVLTree *left; + ImutAVLTree *right; + ImutAVLTree *prev; + ImutAVLTree *next; + + unsigned height : 28; + unsigned IsMutable : 1; + unsigned IsDigestCached : 1; + unsigned IsCanonicalized : 1; + + value_type value; + uint32_t digest; + uint32_t refCount; + + //===----------------------------------------------------===// + // Internal methods (node manipulation; used by Factory). + //===----------------------------------------------------===// + +private: + /// ImutAVLTree - Internal constructor that is only called by + /// ImutAVLFactory. + ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, + unsigned height) + : factory(f), left(l), right(r), prev(0), next(0), height(height), + IsMutable(true), IsDigestCached(false), IsCanonicalized(0), + value(v), digest(0), refCount(0) + { + if (left) left->retain(); + if (right) right->retain(); + } + + /// isMutable - Returns true if the left and right subtree references + /// (as well as height) can be changed. If this method returns false, + /// the tree is truly immutable. Trees returned from an ImutAVLFactory + /// object should always have this method return true. Further, if this + /// method returns false for an instance of ImutAVLTree, all subtrees + /// will also have this method return false. The converse is not true. + bool isMutable() const { return IsMutable; } + + /// hasCachedDigest - Returns true if the digest for this tree is cached. + /// This can only be true if the tree is immutable. + bool hasCachedDigest() const { return IsDigestCached; } + + //===----------------------------------------------------===// + // Mutating operations. A tree root can be manipulated as + // long as its reference has not "escaped" from internal + // methods of a factory object (see below). When a tree + // pointer is externally viewable by client code, the + // internal "mutable bit" is cleared to mark the tree + // immutable. Note that a tree that still has its mutable + // bit set may have children (subtrees) that are themselves + // immutable. + //===----------------------------------------------------===// + + /// markImmutable - Clears the mutable flag for a tree. After this happens, + /// it is an error to call setLeft(), setRight(), and setHeight(). + void markImmutable() { + assert(isMutable() && "Mutable flag already removed."); + IsMutable = false; + } + + /// markedCachedDigest - Clears the NoCachedDigest flag for a tree. + void markedCachedDigest() { + assert(!hasCachedDigest() && "NoCachedDigest flag already removed."); + IsDigestCached = true; + } + + /// setHeight - Changes the height of the tree. Used internally by + /// ImutAVLFactory. + void setHeight(unsigned h) { + assert(isMutable() && "Only a mutable tree can have its height changed."); + height = h; + } + + static inline + uint32_t computeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + uint32_t digest = 0; + + if (L) + digest += L->computeDigest(); + + // Compute digest of stored data. + FoldingSetNodeID ID; + ImutInfo::Profile(ID,V); + digest += ID.ComputeHash(); + + if (R) + digest += R->computeDigest(); + + return digest; + } + + inline uint32_t computeDigest() { + // Check the lowest bit to determine if digest has actually been + // pre-computed. + if (hasCachedDigest()) + return digest; + + uint32_t X = computeDigest(getLeft(), getRight(), getValue()); + digest = X; + markedCachedDigest(); + return X; + } + + //===----------------------------------------------------===// + // Reference count operations. + //===----------------------------------------------------===// + +public: + void retain() { ++refCount; } + void release() { + assert(refCount > 0); + if (--refCount == 0) + destroy(); + } + void destroy() { + if (left) + left->release(); + if (right) + right->release(); + if (IsCanonicalized) { + if (next) + next->prev = prev; + + if (prev) + prev->next = next; + else + factory->Cache[computeDigest()] = next; + } + + // We need to clear the mutability bit in case we are + // destroying the node as part of a sweep in ImutAVLFactory::recoverNodes(). + IsMutable = false; + factory->freeNodes.push_back(this); + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Factory class. +//===----------------------------------------------------------------------===// + +template +class ImutAVLFactory { + friend class ImutAVLTree; + typedef ImutAVLTree TreeTy; + typedef typename TreeTy::value_type_ref value_type_ref; + typedef typename TreeTy::key_type_ref key_type_ref; + + typedef DenseMap CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + std::vector createdNodes; + std::vector freeNodes; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast(Allocator & ~0x1); + } + + //===--------------------------------------------------===// + // Public interface. + //===--------------------------------------------------===// + +public: + ImutAVLFactory() + : Allocator(reinterpret_cast(new BumpPtrAllocator())) {} + + ImutAVLFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast(&Alloc) | 0x1) {} + + ~ImutAVLFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + TreeTy* add(TreeTy* T, value_type_ref V) { + T = add_internal(V,T); + markImmutable(T); + recoverNodes(); + return T; + } + + TreeTy* remove(TreeTy* T, key_type_ref V) { + T = remove_internal(V,T); + markImmutable(T); + recoverNodes(); + return T; + } + + TreeTy* getEmptyTree() const { return NULL; } + +protected: + + //===--------------------------------------------------===// + // A bunch of quick helper functions used for reasoning + // about the properties of trees and their children. + // These have succinct names so that the balancing code + // is as terse (and readable) as possible. + //===--------------------------------------------------===// + + bool isEmpty(TreeTy* T) const { return !T; } + unsigned getHeight(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* getLeft(TreeTy* T) const { return T->getLeft(); } + TreeTy* getRight(TreeTy* T) const { return T->getRight(); } + value_type_ref getValue(TreeTy* T) const { return T->value; } + + unsigned incrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); + return (hl > hr ? hl : hr) + 1; + } + + static bool compareTreeWithSection(TreeTy* T, + typename TreeTy::iterator& TI, + typename TreeTy::iterator& TE) { + typename TreeTy::iterator I = T->begin(), E = T->end(); + for ( ; I!=E ; ++I, ++TI) { + if (TI == TE || !I->isElementEqual(*TI)) + return false; + } + return true; + } + + //===--------------------------------------------------===// + // "createNode" is used to generate new tree roots that link + // to other trees. The functon may also simply move links + // in an existing root if that root is still marked mutable. + // This is necessary because otherwise our balancing code + // would leak memory as it would create nodes that are + // then discarded later before the finished tree is + // returned to the caller. + //===--------------------------------------------------===// + + TreeTy* createNode(TreeTy* L, value_type_ref V, TreeTy* R) { + BumpPtrAllocator& A = getAllocator(); + TreeTy* T; + if (!freeNodes.empty()) { + T = freeNodes.back(); + freeNodes.pop_back(); + assert(T != L); + assert(T != R); + } + else { + T = (TreeTy*) A.Allocate(); + } + new (T) TreeTy(this, L, R, V, incrementHeight(L,R)); + createdNodes.push_back(T); + return T; + } + + TreeTy* createNode(TreeTy* newLeft, TreeTy* oldTree, TreeTy* newRight) { + return createNode(newLeft, getValue(oldTree), newRight); + } + + void recoverNodes() { + for (unsigned i = 0, n = createdNodes.size(); i < n; ++i) { + TreeTy *N = createdNodes[i]; + if (N->isMutable() && N->refCount == 0) + N->destroy(); + } + createdNodes.clear(); + } + + /// balanceTree - Used by add_internal and remove_internal to + /// balance a newly created tree. + TreeTy* balanceTree(TreeTy* L, value_type_ref V, TreeTy* R) { + unsigned hl = getHeight(L); + unsigned hr = getHeight(R); + + if (hl > hr + 2) { + assert(!isEmpty(L) && "Left tree cannot be empty to have a height >= 2"); + + TreeTy *LL = getLeft(L); + TreeTy *LR = getRight(L); + + if (getHeight(LL) >= getHeight(LR)) + return createNode(LL, L, createNode(LR,V,R)); + + assert(!isEmpty(LR) && "LR cannot be empty because it has a height >= 1"); + + TreeTy *LRL = getLeft(LR); + TreeTy *LRR = getRight(LR); + + return createNode(createNode(LL,L,LRL), LR, createNode(LRR,V,R)); + } + else if (hr > hl + 2) { + assert(!isEmpty(R) && "Right tree cannot be empty to have a height >= 2"); + + TreeTy *RL = getLeft(R); + TreeTy *RR = getRight(R); + + if (getHeight(RR) >= getHeight(RL)) + return createNode(createNode(L,V,RL), R, RR); + + assert(!isEmpty(RL) && "RL cannot be empty because it has a height >= 1"); + + TreeTy *RLL = getLeft(RL); + TreeTy *RLR = getRight(RL); + + return createNode(createNode(L,V,RLL), RL, createNode(RLR,R,RR)); + } + else + return createNode(L,V,R); + } + + /// add_internal - Creates a new tree that includes the specified + /// data and the data from the original tree. If the original tree + /// already contained the data item, the original tree is returned. + TreeTy* add_internal(value_type_ref V, TreeTy* T) { + if (isEmpty(T)) + return createNode(T, V, T); + assert(!T->isMutable()); + + key_type_ref K = ImutInfo::KeyOfValue(V); + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return createNode(getLeft(T), V, getRight(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return balanceTree(add_internal(V, getLeft(T)), getValue(T), getRight(T)); + else + return balanceTree(getLeft(T), getValue(T), add_internal(V, getRight(T))); + } + + /// remove_internal - Creates a new tree that includes all the data + /// from the original tree except the specified data. If the + /// specified data did not exist in the original tree, the original + /// tree is returned. + TreeTy* remove_internal(key_type_ref K, TreeTy* T) { + if (isEmpty(T)) + return T; + + assert(!T->isMutable()); + + key_type_ref KCurrent = ImutInfo::KeyOfValue(getValue(T)); + + if (ImutInfo::isEqual(K,KCurrent)) { + return combineTrees(getLeft(T), getRight(T)); + } else if (ImutInfo::isLess(K,KCurrent)) { + return balanceTree(remove_internal(K, getLeft(T)), + getValue(T), getRight(T)); + } else { + return balanceTree(getLeft(T), getValue(T), + remove_internal(K, getRight(T))); + } + } + + TreeTy* combineTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) + return R; + if (isEmpty(R)) + return L; + TreeTy* OldNode; + TreeTy* newRight = removeMinBinding(R,OldNode); + return balanceTree(L, getValue(OldNode), newRight); + } + + TreeTy* removeMinBinding(TreeTy* T, TreeTy*& Noderemoved) { + assert(!isEmpty(T)); + if (isEmpty(getLeft(T))) { + Noderemoved = T; + return getRight(T); + } + return balanceTree(removeMinBinding(getLeft(T), Noderemoved), + getValue(T), getRight(T)); + } + + /// markImmutable - Clears the mutable bits of a root and all of its + /// descendants. + void markImmutable(TreeTy* T) { + if (!T || !T->isMutable()) + return; + T->markImmutable(); + markImmutable(getLeft(T)); + markImmutable(getRight(T)); + } + +public: + TreeTy *getCanonicalTree(TreeTy *TNew) { + if (!TNew) + return 0; + + if (TNew->IsCanonicalized) + return TNew; + + // Search the hashtable for another tree with the same digest, and + // if find a collision compare those trees by their contents. + unsigned digest = TNew->computeDigest(); + TreeTy *&entry = Cache[digest]; + do { + if (!entry) + break; + for (TreeTy *T = entry ; T != 0; T = T->next) { + // Compare the Contents('T') with Contents('TNew') + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + if (!compareTreeWithSection(TNew, TI, TE)) + continue; + if (TI != TE) + continue; // T has more contents than TNew. + // Trees did match! Return 'T'. + if (TNew->refCount == 0) + TNew->destroy(); + return T; + } + entry->prev = TNew; + TNew->next = entry; + } + while (false); + + entry = TNew; + TNew->IsCanonicalized = true; + return TNew; + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Iterators. +//===----------------------------------------------------------------------===// + +template +class ImutAVLTreeGenericIterator { + SmallVector stack; +public: + enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, + Flags=0x3 }; + + typedef ImutAVLTree TreeTy; + typedef ImutAVLTreeGenericIterator _Self; + + inline ImutAVLTreeGenericIterator() {} + inline ImutAVLTreeGenericIterator(const TreeTy* Root) { + if (Root) stack.push_back(reinterpret_cast(Root)); + } + + TreeTy* operator*() const { + assert(!stack.empty()); + return reinterpret_cast(stack.back() & ~Flags); + } + + uintptr_t getVisitState() { + assert(!stack.empty()); + return stack.back() & Flags; + } + + + bool atEnd() const { return stack.empty(); } + + bool atBeginning() const { + return stack.size() == 1 && getVisitState() == VisitedNone; + } + + void skipToParent() { + assert(!stack.empty()); + stack.pop_back(); + if (stack.empty()) + return; + switch (getVisitState()) { + case VisitedNone: + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + stack.back() |= VisitedRight; + break; + default: + assert(false && "Unreachable."); + } + } + + inline bool operator==(const _Self& x) const { + if (stack.size() != x.stack.size()) + return false; + for (unsigned i = 0 ; i < stack.size(); i++) + if (stack[i] != x.stack[i]) + return false; + return true; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + _Self& operator++() { + assert(!stack.empty()); + TreeTy* Current = reinterpret_cast(stack.back() & ~Flags); + assert(Current); + switch (getVisitState()) { + case VisitedNone: + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast(L)); + else + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast(R)); + else + stack.back() |= VisitedRight; + break; + case VisitedRight: + skipToParent(); + break; + default: + assert(false && "Unreachable."); + } + return *this; + } + + _Self& operator--() { + assert(!stack.empty()); + TreeTy* Current = reinterpret_cast(stack.back() & ~Flags); + assert(Current); + switch (getVisitState()) { + case VisitedNone: + stack.pop_back(); + break; + case VisitedLeft: + stack.back() &= ~Flags; // Set state to "VisitedNone." + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast(L) | VisitedRight); + break; + case VisitedRight: + stack.back() &= ~Flags; + stack.back() |= VisitedLeft; + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast(R) | VisitedRight); + break; + default: + assert(false && "Unreachable."); + } + return *this; + } +}; + +template +class ImutAVLTreeInOrderIterator { + typedef ImutAVLTreeGenericIterator InternalIteratorTy; + InternalIteratorTy InternalItr; + +public: + typedef ImutAVLTree TreeTy; + typedef ImutAVLTreeInOrderIterator _Self; + + ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { + if (Root) operator++(); // Advance to first element. + } + + ImutAVLTreeInOrderIterator() : InternalItr() {} + + inline bool operator==(const _Self& x) const { + return InternalItr == x.InternalItr; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline TreeTy* operator*() const { return *InternalItr; } + inline TreeTy* operator->() const { return *InternalItr; } + + inline _Self& operator++() { + do ++InternalItr; + while (!InternalItr.atEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline _Self& operator--() { + do --InternalItr; + while (!InternalItr.atBeginning() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline void skipSubTree() { + InternalItr.skipToParent(); + + while (!InternalItr.atEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) + ++InternalItr; + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes for Profile information. +//===----------------------------------------------------------------------===// + +/// Generic profile template. The default behavior is to invoke the +/// profile method of an object. Specializations for primitive integers +/// and generic handling of pointers is done below. +template +struct ImutProfileInfo { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + FoldingSetTrait::Profile(X,ID); + } +}; + +/// Profile traits for integers. +template +struct ImutProfileInteger { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddInteger(X); + } +}; + +#define PROFILE_INTEGER_INFO(X)\ +template<> struct ImutProfileInfo : ImutProfileInteger {}; + +PROFILE_INTEGER_INFO(char) +PROFILE_INTEGER_INFO(unsigned char) +PROFILE_INTEGER_INFO(short) +PROFILE_INTEGER_INFO(unsigned short) +PROFILE_INTEGER_INFO(unsigned) +PROFILE_INTEGER_INFO(signed) +PROFILE_INTEGER_INFO(long) +PROFILE_INTEGER_INFO(unsigned long) +PROFILE_INTEGER_INFO(long long) +PROFILE_INTEGER_INFO(unsigned long long) + +#undef PROFILE_INTEGER_INFO + +/// Generic profile trait for pointer types. We treat pointers as +/// references to unique objects. +template +struct ImutProfileInfo { + typedef const T* value_type; + typedef value_type value_type_ref; + + static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddPointer(X); + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes that contain element comparison operators and type +// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These +// inherit from the profile traits (ImutProfileInfo) to include operations +// for element profiling. +//===----------------------------------------------------------------------===// + + +/// ImutContainerInfo - Generic definition of comparison operations for +/// elements of immutable containers that defaults to using +/// std::equal_to<> and std::less<> to perform comparison of elements. +template +struct ImutContainerInfo : public ImutProfileInfo { + typedef typename ImutProfileInfo::value_type value_type; + typedef typename ImutProfileInfo::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return std::equal_to()(LHS,RHS); + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return std::less()(LHS,RHS); + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +/// ImutContainerInfo - Specialization for pointer values to treat pointers +/// as references to unique objects. Pointers are thus compared by +/// their addresses. +template +struct ImutContainerInfo : public ImutProfileInfo { + typedef typename ImutProfileInfo::value_type value_type; + typedef typename ImutProfileInfo::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return LHS == RHS; + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return LHS < RHS; + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Immutable Set +//===----------------------------------------------------------------------===// + +template > +class ImmutableSet { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef ImutAVLTree TreeTy; + +private: + TreeTy *Root; + +public: + /// Constructs a set from a pointer to a tree root. In general one + /// should use a Factory object to create sets instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableSet(TreeTy* R) : Root(R) { + if (Root) { Root->retain(); } + } + ImmutableSet(const ImmutableSet &X) : Root(X.Root) { + if (Root) { Root->retain(); } + } + ImmutableSet &operator=(const ImmutableSet &X) { + if (Root != X.Root) { + if (X.Root) { X.Root->retain(); } + if (Root) { Root->release(); } + Root = X.Root; + } + return *this; + } + ~ImmutableSet() { + if (Root) { Root->release(); } + } + + class Factory { + typename TreeTy::Factory F; + const bool Canonicalize; + + public: + Factory(bool canonicalize = true) + : Canonicalize(canonicalize) {} + + Factory(BumpPtrAllocator& Alloc, bool canonicalize = true) + : F(Alloc), Canonicalize(canonicalize) {} + + /// getEmptySet - Returns an immutable set that contains no elements. + ImmutableSet getEmptySet() { + return ImmutableSet(F.getEmptyTree()); + } + + /// add - Creates a new immutable set that contains all of the values + /// of the original set with the addition of the specified value. If + /// the original set already included the value, then the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet add(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.add(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); + } + + /// remove - Creates a new immutable set that contains all of the values + /// of the original set with the exception of the specified value. If + /// the original set did not contain the value, the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet remove(ImmutableSet Old, value_type_ref V) { + TreeTy *NewT = F.remove(Old.Root, V); + return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); + } + + BumpPtrAllocator& getAllocator() { return F.getAllocator(); } + + private: + Factory(const Factory& RHS); // DO NOT IMPLEMENT + void operator=(const Factory& RHS); // DO NOT IMPLEMENT + }; + + friend class Factory; + + /// Returns true if the set contains the specified value. + bool contains(value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + bool operator==(const ImmutableSet &RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(const ImmutableSet &RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy *getRoot() { + if (Root) { Root->retain(); } + return Root; + } + + /// isEmpty - Return true if the set contains no elements. + bool isEmpty() const { return !Root; } + + /// isSingleton - Return true if the set contains exactly one element. + /// This method runs in constant time. + bool isSingleton() const { return getHeight() == 1; } + + template + void foreach(Callback& C) { if (Root) Root->foreach(C); } + + template + void foreach() { if (Root) { Callback C; Root->foreach(C); } } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableSet; + public: + iterator() {} + inline value_type_ref operator*() const { return itr->getValue(); } + inline iterator& operator++() { ++itr; return *this; } + inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + inline iterator& operator--() { --itr; return *this; } + inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + inline value_type *operator->() const { return &(operator*()); } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) { + ID.AddPointer(S.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void validateTree() const { if (Root) Root->validateTree(); } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/InMemoryStruct.h b/final/include/llvm/ADT/InMemoryStruct.h new file mode 100644 index 00000000000..a56084501a6 --- /dev/null +++ b/final/include/llvm/ADT/InMemoryStruct.h @@ -0,0 +1,77 @@ +//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INMEMORYSTRUCT_H +#define LLVM_ADT_INMEMORYSTRUCT_H + +#include + +namespace llvm { + +/// \brief Helper object for abstracting access to an in-memory structure which +/// may require some kind of temporary storage. +/// +/// This class is designed to be used for accessing file data structures which +/// in the common case can be accessed from a direct pointer to a memory mapped +/// object, but which in some cases may require indirect access to a temporary +/// structure (which, for example, may have undergone endianness translation). +template +class InMemoryStruct { + typedef T value_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef const value_type &const_reference; + typedef const value_type *const_pointer; + + /// \brief The smart pointer target. + value_type *Target; + + /// \brief A temporary object which can be used as a target of the smart + /// pointer. + value_type Contents; + +private: + +public: + InMemoryStruct() : Target(0) {} + InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {} + InMemoryStruct(pointer Value) : Target(Value) {} + InMemoryStruct(const InMemoryStruct &Value) { *this = Value; } + + void operator=(const InMemoryStruct &Value) { + if (Value.Target != &Value.Contents) { + Target = Value.Target; + } else { + Target = &Contents; + Contents = Value.Contents; + } + } + + const_reference operator*() const { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + reference operator*() { + assert(Target && "Cannot dereference null pointer"); + return *Target; + } + + const_pointer operator->() const { + return Target; + } + pointer operator->() { + return Target; + } + + operator bool() const { return Target != 0; } +}; + +} + +#endif diff --git a/final/include/llvm/ADT/IndexedMap.h b/final/include/llvm/ADT/IndexedMap.h new file mode 100644 index 00000000000..87126ea4918 --- /dev/null +++ b/final/include/llvm/ADT/IndexedMap.h @@ -0,0 +1,87 @@ +//===- llvm/ADT/IndexedMap.h - An index map implementation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an indexed map. The index map template takes two +// types. The first is the mapped type and the second is a functor +// that maps its argument to a size_t. On instantiation a "null" value +// can be provided to be used as a "does not exist" indicator in the +// map. A member function grow() is provided that given the value of +// the maximally indexed key (the argument of the functor) makes sure +// the map has enough space for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INDEXEDMAP_H +#define LLVM_ADT_INDEXEDMAP_H + +#include +#include +#include + +namespace llvm { + + struct IdentityFunctor : public std::unary_function { + unsigned operator()(unsigned Index) const { + return Index; + } + }; + + template + class IndexedMap { + typedef typename ToIndexT::argument_type IndexT; + typedef std::vector StorageT; + StorageT storage_; + T nullVal_; + ToIndexT toIndex_; + + public: + IndexedMap() : nullVal_(T()) { } + + explicit IndexedMap(const T& val) : nullVal_(val) { } + + typename StorageT::reference operator[](IndexT n) { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + typename StorageT::const_reference operator[](IndexT n) const { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + void reserve(typename StorageT::size_type s) { + storage_.reserve(s); + } + + void resize(typename StorageT::size_type s) { + storage_.resize(s, nullVal_); + } + + void clear() { + storage_.clear(); + } + + void grow(IndexT n) { + unsigned NewSize = toIndex_(n) + 1; + if (NewSize > storage_.size()) + resize(NewSize); + } + + bool inBounds(IndexT n) const { + return toIndex_(n) < storage_.size(); + } + + typename StorageT::size_type size() const { + return storage_.size(); + } + }; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/IntEqClasses.h b/final/include/llvm/ADT/IntEqClasses.h new file mode 100644 index 00000000000..8e75c48e376 --- /dev/null +++ b/final/include/llvm/ADT/IntEqClasses.h @@ -0,0 +1,88 @@ +//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Equivalence classes for small integers. This is a mapping of the integers +// 0 .. N-1 into M equivalence classes numbered 0 .. M-1. +// +// Initially each integer has its own equivalence class. Classes are joined by +// passing a representative member of each class to join(). +// +// Once the classes are built, compress() will number them 0 .. M-1 and prevent +// further changes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTEQCLASSES_H +#define LLVM_ADT_INTEQCLASSES_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class IntEqClasses { + /// EC - When uncompressed, map each integer to a smaller member of its + /// equivalence class. The class leader is the smallest member and maps to + /// itself. + /// + /// When compressed, EC[i] is the equivalence class of i. + SmallVector EC; + + /// NumClasses - The number of equivalence classes when compressed, or 0 when + /// uncompressed. + unsigned NumClasses; + +public: + /// IntEqClasses - Create an equivalence class mapping for 0 .. N-1. + IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); } + + /// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique + /// equivalence classes. + /// This requires an uncompressed map. + void grow(unsigned N); + + /// clear - Clear all classes so that grow() will assign a unique class to + /// every integer. + void clear() { + EC.clear(); + NumClasses = 0; + } + + /// join - Join the equivalence classes of a and b. After joining classes, + /// findLeader(a) == findLeader(b). + /// This requires an uncompressed map. + void join(unsigned a, unsigned b); + + /// findLeader - Compute the leader of a's equivalence class. This is the + /// smallest member of the class. + /// This requires an uncompressed map. + unsigned findLeader(unsigned a) const; + + /// compress - Compress equivalence classes by numbering them 0 .. M. + /// This makes the equivalence class map immutable. + void compress(); + + /// getNumClasses - Return the number of equivalence classes after compress() + /// was called. + unsigned getNumClasses() const { return NumClasses; } + + /// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1. + /// This requires a compressed map. + unsigned operator[](unsigned a) const { + assert(NumClasses && "operator[] called before compress()"); + return EC[a]; + } + + /// uncompress - Change back to the uncompressed representation that allows + /// editing. + void uncompress(); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/IntervalMap.h b/final/include/llvm/ADT/IntervalMap.h new file mode 100644 index 00000000000..79f24d31c06 --- /dev/null +++ b/final/include/llvm/ADT/IntervalMap.h @@ -0,0 +1,2139 @@ +//===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a coalescing interval map for small objects. +// +// KeyT objects are mapped to ValT objects. Intervals of keys that map to the +// same value are represented in a compressed form. +// +// Iterators provide ordered access to the compressed intervals rather than the +// individual keys, and insert and erase operations use key intervals as well. +// +// Like SmallVector, IntervalMap will store the first N intervals in the map +// object itself without any allocations. When space is exhausted it switches to +// a B+-tree representation with very small overhead for small key and value +// objects. +// +// A Traits class specifies how keys are compared. It also allows IntervalMap to +// work with both closed and half-open intervals. +// +// Keys and values are not stored next to each other in a std::pair, so we don't +// provide such a value_type. Dereferencing iterators only returns the mapped +// value. The interval bounds are accessible through the start() and stop() +// iterator methods. +// +// IntervalMap is optimized for small key and value objects, 4 or 8 bytes each +// is the optimal size. For large objects use std::map instead. +// +//===----------------------------------------------------------------------===// +// +// Synopsis: +// +// template +// class IntervalMap { +// public: +// typedef KeyT key_type; +// typedef ValT mapped_type; +// typedef RecyclingAllocator<...> Allocator; +// class iterator; +// class const_iterator; +// +// explicit IntervalMap(Allocator&); +// ~IntervalMap(): +// +// bool empty() const; +// KeyT start() const; +// KeyT stop() const; +// ValT lookup(KeyT x, Value NotFound = Value()) const; +// +// const_iterator begin() const; +// const_iterator end() const; +// iterator begin(); +// iterator end(); +// const_iterator find(KeyT x) const; +// iterator find(KeyT x); +// +// void insert(KeyT a, KeyT b, ValT y); +// void clear(); +// }; +// +// template +// class IntervalMap::const_iterator : +// public std::iterator { +// public: +// bool operator==(const const_iterator &) const; +// bool operator!=(const const_iterator &) const; +// bool valid() const; +// +// const KeyT &start() const; +// const KeyT &stop() const; +// const ValT &value() const; +// const ValT &operator*() const; +// const ValT *operator->() const; +// +// const_iterator &operator++(); +// const_iterator &operator++(int); +// const_iterator &operator--(); +// const_iterator &operator--(int); +// void goToBegin(); +// void goToEnd(); +// void find(KeyT x); +// void advanceTo(KeyT x); +// }; +// +// template +// class IntervalMap::iterator : public const_iterator { +// public: +// void insert(KeyT a, KeyT b, Value y); +// void erase(); +// }; +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTERVALMAP_H +#define LLVM_ADT_INTERVALMAP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/RecyclingAllocator.h" +#include + +namespace llvm { + + +//===----------------------------------------------------------------------===// +//--- Key traits ---// +//===----------------------------------------------------------------------===// +// +// The IntervalMap works with closed or half-open intervals. +// Adjacent intervals that map to the same value are coalesced. +// +// The IntervalMapInfo traits class is used to determine if a key is contained +// in an interval, and if two intervals are adjacent so they can be coalesced. +// The provided implementation works for closed integer intervals, other keys +// probably need a specialized version. +// +// The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x). +// +// It is assumed that (a;b] half-open intervals are not used, only [a;b) is +// allowed. This is so that stopLess(a, b) can be used to determine if two +// intervals overlap. +// +//===----------------------------------------------------------------------===// + +template +struct IntervalMapInfo { + + /// startLess - Return true if x is not in [a;b]. + /// This is x < a both for closed intervals and for [a;b) half-open intervals. + static inline bool startLess(const T &x, const T &a) { + return x < a; + } + + /// stopLess - Return true if x is not in [a;b]. + /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals. + static inline bool stopLess(const T &b, const T &x) { + return b < x; + } + + /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce. + /// This is a+1 == b for closed intervals, a == b for half-open intervals. + static inline bool adjacent(const T &a, const T &b) { + return a+1 == b; + } + +}; + +/// IntervalMapImpl - Namespace used for IntervalMap implementation details. +/// It should be considered private to the implementation. +namespace IntervalMapImpl { + +// Forward declarations. +template class LeafNode; +template class BranchNode; + +typedef std::pair IdxPair; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeBase ---// +//===----------------------------------------------------------------------===// +// +// Both leaf and branch nodes store vectors of pairs. +// Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT). +// +// Keys and values are stored in separate arrays to avoid padding caused by +// different object alignments. This also helps improve locality of reference +// when searching the keys. +// +// The nodes don't know how many elements they contain - that information is +// stored elsewhere. Omitting the size field prevents padding and allows a node +// to fill the allocated cache lines completely. +// +// These are typical key and value sizes, the node branching factor (N), and +// wasted space when nodes are sized to fit in three cache lines (192 bytes): +// +// T1 T2 N Waste Used by +// 4 4 24 0 Branch<4> (32-bit pointers) +// 8 4 16 0 Leaf<4,4>, Branch<4> +// 8 8 12 0 Leaf<4,8>, Branch<8> +// 16 4 9 12 Leaf<8,4> +// 16 8 8 0 Leaf<8,8> +// +//===----------------------------------------------------------------------===// + +template +class NodeBase { +public: + enum { Capacity = N }; + + T1 first[N]; + T2 second[N]; + + /// copy - Copy elements from another node. + /// @param Other Node elements are copied from. + /// @param i Beginning of the source range in other. + /// @param j Beginning of the destination range in this. + /// @param Count Number of elements to copy. + template + void copy(const NodeBase &Other, unsigned i, + unsigned j, unsigned Count) { + assert(i + Count <= M && "Invalid source range"); + assert(j + Count <= N && "Invalid dest range"); + for (unsigned e = i + Count; i != e; ++i, ++j) { + first[j] = Other.first[i]; + second[j] = Other.second[i]; + } + } + + /// moveLeft - Move elements to the left. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveLeft(unsigned i, unsigned j, unsigned Count) { + assert(j <= i && "Use moveRight shift elements right"); + copy(*this, i, j, Count); + } + + /// moveRight - Move elements to the right. + /// @param i Beginning of the source range. + /// @param j Beginning of the destination range. + /// @param Count Number of elements to copy. + void moveRight(unsigned i, unsigned j, unsigned Count) { + assert(i <= j && "Use moveLeft shift elements left"); + assert(j + Count <= N && "Invalid range"); + while (Count--) { + first[j + Count] = first[i + Count]; + second[j + Count] = second[i + Count]; + } + } + + /// erase - Erase elements [i;j). + /// @param i Beginning of the range to erase. + /// @param j End of the range. (Exclusive). + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned j, unsigned Size) { + moveLeft(j, i, Size - j); + } + + /// erase - Erase element at i. + /// @param i Index of element to erase. + /// @param Size Number of elements in node. + void erase(unsigned i, unsigned Size) { + erase(i, i+1, Size); + } + + /// shift - Shift elements [i;size) 1 position to the right. + /// @param i Beginning of the range to move. + /// @param Size Number of elements in node. + void shift(unsigned i, unsigned Size) { + moveRight(i, i + 1, Size - i); + } + + /// transferToLeftSib - Transfer elements to a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Left sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.copy(*this, 0, SSize, Count); + erase(0, Count, Size); + } + + /// transferToRightSib - Transfer elements to a right sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Count Number of elements to transfer. + void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, + unsigned Count) { + Sib.moveRight(0, Count, SSize); + Sib.copy(*this, Size-Count, 0, Count); + } + + /// adjustFromLeftSib - Adjust the number if elements in this node by moving + /// elements to or from a left sibling node. + /// @param Size Number of elements in this. + /// @param Sib Right sibling node. + /// @param SSize Number of elements in sib. + /// @param Add The number of elements to add to this node, possibly < 0. + /// @return Number of elements added to this node, possibly negative. + int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) { + if (Add > 0) { + // We want to grow, copy from sib. + unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size); + Sib.transferToRightSib(SSize, *this, Size, Count); + return Count; + } else { + // We want to shrink, copy to sib. + unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize); + transferToLeftSib(Size, Sib, SSize, Count); + return -Count; + } + } +}; + +/// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes. +/// @param Node Array of pointers to sibling nodes. +/// @param Nodes Number of nodes. +/// @param CurSize Array of current node sizes, will be overwritten. +/// @param NewSize Array of desired node sizes. +template +void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, + unsigned CurSize[], const unsigned NewSize[]) { + // Move elements right. + for (int n = Nodes - 1; n; --n) { + if (CurSize[n] == NewSize[n]) + continue; + for (int m = n - 1; m != -1; --m) { + int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m], + NewSize[n] - CurSize[n]); + CurSize[m] -= d; + CurSize[n] += d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + + if (Nodes == 0) + return; + + // Move elements left. + for (unsigned n = 0; n != Nodes - 1; ++n) { + if (CurSize[n] == NewSize[n]) + continue; + for (unsigned m = n + 1; m != Nodes; ++m) { + int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n], + CurSize[n] - NewSize[n]); + CurSize[m] += d; + CurSize[n] -= d; + // Keep going if the current node was exhausted. + if (CurSize[n] >= NewSize[n]) + break; + } + } + +#ifndef NDEBUG + for (unsigned n = 0; n != Nodes; n++) + assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle"); +#endif +} + +/// IntervalMapImpl::distribute - Compute a new distribution of node elements +/// after an overflow or underflow. Reserve space for a new element at Position, +/// and compute the node that will hold Position after redistributing node +/// elements. +/// +/// It is required that +/// +/// Elements == sum(CurSize), and +/// Elements + Grow <= Nodes * Capacity. +/// +/// NewSize[] will be filled in such that: +/// +/// sum(NewSize) == Elements, and +/// NewSize[i] <= Capacity. +/// +/// The returned index is the node where Position will go, so: +/// +/// sum(NewSize[0..idx-1]) <= Position +/// sum(NewSize[0..idx]) >= Position +/// +/// The last equality, sum(NewSize[0..idx]) == Position, can only happen when +/// Grow is set and NewSize[idx] == Capacity-1. The index points to the node +/// before the one holding the Position'th element where there is room for an +/// insertion. +/// +/// @param Nodes The number of nodes. +/// @param Elements Total elements in all nodes. +/// @param Capacity The capacity of each node. +/// @param CurSize Array[Nodes] of current node sizes, or NULL. +/// @param NewSize Array[Nodes] to receive the new node sizes. +/// @param Position Insert position. +/// @param Grow Reserve space for a new element at Position. +/// @return (node, offset) for Position. +IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, + const unsigned *CurSize, unsigned NewSize[], + unsigned Position, bool Grow); + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeSizer ---// +//===----------------------------------------------------------------------===// +// +// Compute node sizes from key and value types. +// +// The branching factors are chosen to make nodes fit in three cache lines. +// This may not be possible if keys or values are very large. Such large objects +// are handled correctly, but a std::map would probably give better performance. +// +//===----------------------------------------------------------------------===// + +enum { + // Cache line size. Most architectures have 32 or 64 byte cache lines. + // We use 64 bytes here because it provides good branching factors. + Log2CacheLine = 6, + CacheLineBytes = 1 << Log2CacheLine, + DesiredNodeBytes = 3 * CacheLineBytes +}; + +template +struct NodeSizer { + enum { + // Compute the leaf node branching factor that makes a node fit in three + // cache lines. The branching factor must be at least 3, or some B+-tree + // balancing algorithms won't work. + // LeafSize can't be larger than CacheLineBytes. This is required by the + // PointerIntPair used by NodeRef. + DesiredLeafSize = DesiredNodeBytes / + static_cast(2*sizeof(KeyT)+sizeof(ValT)), + MinLeafSize = 3, + LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize + }; + + typedef NodeBase, ValT, LeafSize> LeafBase; + + enum { + // Now that we have the leaf branching factor, compute the actual allocation + // unit size by rounding up to a whole number of cache lines. + AllocBytes = (sizeof(LeafBase) + CacheLineBytes-1) & ~(CacheLineBytes-1), + + // Determine the branching factor for branch nodes. + BranchSize = AllocBytes / + static_cast(sizeof(KeyT) + sizeof(void*)) + }; + + /// Allocator - The recycling allocator used for both branch and leaf nodes. + /// This typedef is very likely to be identical for all IntervalMaps with + /// reasonably sized entries, so the same allocator can be shared among + /// different kinds of maps. + typedef RecyclingAllocator Allocator; + +}; + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::NodeRef ---// +//===----------------------------------------------------------------------===// +// +// B+-tree nodes can be leaves or branches, so we need a polymorphic node +// pointer that can point to both kinds. +// +// All nodes are cache line aligned and the low 6 bits of a node pointer are +// always 0. These bits are used to store the number of elements in the +// referenced node. Besides saving space, placing node sizes in the parents +// allow tree balancing algorithms to run without faulting cache lines for nodes +// that may not need to be modified. +// +// A NodeRef doesn't know whether it references a leaf node or a branch node. +// It is the responsibility of the caller to use the correct types. +// +// Nodes are never supposed to be empty, and it is invalid to store a node size +// of 0 in a NodeRef. The valid range of sizes is 1-64. +// +//===----------------------------------------------------------------------===// + +class NodeRef { + struct CacheAlignedPointerTraits { + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { NumLowBitsAvailable = Log2CacheLine }; + }; + PointerIntPair pip; + +public: + /// NodeRef - Create a null ref. + NodeRef() {} + + /// operator bool - Detect a null ref. + operator bool() const { return pip.getOpaqueValue(); } + + /// NodeRef - Create a reference to the node p with n elements. + template + NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) { + assert(n <= NodeT::Capacity && "Size too big for node"); + } + + /// size - Return the number of elements in the referenced node. + unsigned size() const { return pip.getInt() + 1; } + + /// setSize - Update the node size. + void setSize(unsigned n) { pip.setInt(n - 1); } + + /// subtree - Access the i'th subtree reference in a branch node. + /// This depends on branch nodes storing the NodeRef array as their first + /// member. + NodeRef &subtree(unsigned i) const { + return reinterpret_cast(pip.getPointer())[i]; + } + + /// get - Dereference as a NodeT reference. + template + NodeT &get() const { + return *reinterpret_cast(pip.getPointer()); + } + + bool operator==(const NodeRef &RHS) const { + if (pip == RHS.pip) + return true; + assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs"); + return false; + } + + bool operator!=(const NodeRef &RHS) const { + return !operator==(RHS); + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::LeafNode ---// +//===----------------------------------------------------------------------===// +// +// Leaf nodes store up to N disjoint intervals with corresponding values. +// +// The intervals are kept sorted and fully coalesced so there are no adjacent +// intervals mapping to the same value. +// +// These constraints are always satisfied: +// +// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals. +// +// - Traits::stopLess(stop(i), start(i + 1) - Sorted. +// +// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1)) +// - Fully coalesced. +// +//===----------------------------------------------------------------------===// + +template +class LeafNode : public NodeBase, ValT, N> { +public: + const KeyT &start(unsigned i) const { return this->first[i].first; } + const KeyT &stop(unsigned i) const { return this->first[i].second; } + const ValT &value(unsigned i) const { return this->second[i]; } + + KeyT &start(unsigned i) { return this->first[i].first; } + KeyT &stop(unsigned i) { return this->first[i].second; } + ValT &value(unsigned i) { return this->second[i]; } + + /// findFrom - Find the first interval after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), or size. + /// This is the first interval that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find an interval that is known to exist. This is the same as + /// findFrom except is it assumed that x is at least within range of the last + /// interval. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i].stop, x), never size. + /// This is the first interval that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Lookup mapped value for a safe key. + /// It is assumed that x is within range of the last entry. + /// @param x Key to search for. + /// @param NotFound Value to return if x is not in any interval. + /// @return The mapped value at x or NotFound. + ValT safeLookup(KeyT x, ValT NotFound) const { + unsigned i = safeFind(0, x); + return Traits::startLess(x, start(i)) ? NotFound : value(i); + } + + unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y); +}; + +/// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as +/// possible. This may cause the node to grow by 1, or it may cause the node +/// to shrink because of coalescing. +/// @param i Starting index = insertFrom(0, size, a) +/// @param Size Number of elements in node. +/// @param a Interval start. +/// @param b Interval stop. +/// @param y Value be mapped. +/// @return (insert position, new size), or (i, Capacity+1) on overflow. +template +unsigned LeafNode:: +insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) { + unsigned i = Pos; + assert(i <= Size && Size <= N && "Invalid index"); + assert(!Traits::stopLess(b, a) && "Invalid interval"); + + // Verify the findFrom invariant. + assert((i == 0 || Traits::stopLess(stop(i - 1), a))); + assert((i == Size || !Traits::stopLess(stop(i), a))); + assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert"); + + // Coalesce with previous interval. + if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) { + Pos = i - 1; + // Also coalesce with next interval? + if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) { + stop(i - 1) = stop(i); + this->erase(i, Size); + return Size - 1; + } + stop(i - 1) = b; + return Size; + } + + // Detect overflow. + if (i == N) + return N + 1; + + // Add new interval at end. + if (i == Size) { + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; + } + + // Try to coalesce with following interval. + if (value(i) == y && Traits::adjacent(b, start(i))) { + start(i) = a; + return Size; + } + + // We must insert before i. Detect overflow. + if (Size == N) + return N + 1; + + // Insert before i. + this->shift(i, Size); + start(i) = a; + stop(i) = b; + value(i) = y; + return Size + 1; +} + + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::BranchNode ---// +//===----------------------------------------------------------------------===// +// +// A branch node stores references to 1--N subtrees all of the same height. +// +// The key array in a branch node holds the rightmost stop key of each subtree. +// It is redundant to store the last stop key since it can be found in the +// parent node, but doing so makes tree balancing a lot simpler. +// +// It is unusual for a branch node to only have one subtree, but it can happen +// in the root node if it is smaller than the normal nodes. +// +// When all of the leaf nodes from all the subtrees are concatenated, they must +// satisfy the same constraints as a single leaf node. They must be sorted, +// sane, and fully coalesced. +// +//===----------------------------------------------------------------------===// + +template +class BranchNode : public NodeBase { +public: + const KeyT &stop(unsigned i) const { return this->second[i]; } + const NodeRef &subtree(unsigned i) const { return this->first[i]; } + + KeyT &stop(unsigned i) { return this->second[i]; } + NodeRef &subtree(unsigned i) { return this->first[i]; } + + /// findFrom - Find the first subtree after i that may contain x. + /// @param i Starting index for the search. + /// @param Size Number of elements in node. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), or size. + /// This is the first subtree that can possibly contain x. + unsigned findFrom(unsigned i, unsigned Size, KeyT x) const { + assert(i <= Size && Size <= N && "Bad indices"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index to findFrom is past the needed point"); + while (i != Size && Traits::stopLess(stop(i), x)) ++i; + return i; + } + + /// safeFind - Find a subtree that is known to exist. This is the same as + /// findFrom except is it assumed that x is in range. + /// @param i Starting index for the search. + /// @param x Key to search for. + /// @return First index with !stopLess(key[i], x), never size. + /// This is the first subtree that can possibly contain x. + unsigned safeFind(unsigned i, KeyT x) const { + assert(i < N && "Bad index"); + assert((i == 0 || Traits::stopLess(stop(i - 1), x)) && + "Index is past the needed point"); + while (Traits::stopLess(stop(i), x)) ++i; + assert(i < N && "Unsafe intervals"); + return i; + } + + /// safeLookup - Get the subtree containing x, Assuming that x is in range. + /// @param x Key to search for. + /// @return Subtree containing x + NodeRef safeLookup(KeyT x) const { + return subtree(safeFind(0, x)); + } + + /// insert - Insert a new (subtree, stop) pair. + /// @param i Insert position, following entries will be shifted. + /// @param Size Number of elements in node. + /// @param Node Subtree to insert. + /// @param Stop Last key in subtree. + void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) { + assert(Size < N && "branch node overflow"); + assert(i <= Size && "Bad insert position"); + this->shift(i, Size); + subtree(i) = Node; + stop(i) = Stop; + } +}; + +//===----------------------------------------------------------------------===// +//--- IntervalMapImpl::Path ---// +//===----------------------------------------------------------------------===// +// +// A Path is used by iterators to represent a position in a B+-tree, and the +// path to get there from the root. +// +// The Path class also constains the tree navigation code that doesn't have to +// be templatized. +// +//===----------------------------------------------------------------------===// + +class Path { + /// Entry - Each step in the path is a node pointer and an offset into that + /// node. + struct Entry { + void *node; + unsigned size; + unsigned offset; + + Entry(void *Node, unsigned Size, unsigned Offset) + : node(Node), size(Size), offset(Offset) {} + + Entry(NodeRef Node, unsigned Offset) + : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {} + + NodeRef &subtree(unsigned i) const { + return reinterpret_cast(node)[i]; + } + }; + + /// path - The path entries, path[0] is the root node, path.back() is a leaf. + SmallVector path; + +public: + // Node accessors. + template NodeT &node(unsigned Level) const { + return *reinterpret_cast(path[Level].node); + } + unsigned size(unsigned Level) const { return path[Level].size; } + unsigned offset(unsigned Level) const { return path[Level].offset; } + unsigned &offset(unsigned Level) { return path[Level].offset; } + + // Leaf accessors. + template NodeT &leaf() const { + return *reinterpret_cast(path.back().node); + } + unsigned leafSize() const { return path.back().size; } + unsigned leafOffset() const { return path.back().offset; } + unsigned &leafOffset() { return path.back().offset; } + + /// valid - Return true if path is at a valid node, not at end(). + bool valid() const { + return !path.empty() && path.front().offset < path.front().size; + } + + /// height - Return the height of the tree corresponding to this path. + /// This matches map->height in a full path. + unsigned height() const { return path.size() - 1; } + + /// subtree - Get the subtree referenced from Level. When the path is + /// consistent, node(Level + 1) == subtree(Level). + /// @param Level 0..height-1. The leaves have no subtrees. + NodeRef &subtree(unsigned Level) const { + return path[Level].subtree(path[Level].offset); + } + + /// reset - Reset cached information about node(Level) from subtree(Level -1). + /// @param Level 1..height. THe node to update after parent node changed. + void reset(unsigned Level) { + path[Level] = Entry(subtree(Level - 1), offset(Level)); + } + + /// push - Add entry to path. + /// @param Node Node to add, should be subtree(path.size()-1). + /// @param Offset Offset into Node. + void push(NodeRef Node, unsigned Offset) { + path.push_back(Entry(Node, Offset)); + } + + /// pop - Remove the last path entry. + void pop() { + path.pop_back(); + } + + /// setSize - Set the size of a node both in the path and in the tree. + /// @param Level 0..height. Note that setting the root size won't change + /// map->rootSize. + /// @param Size New node size. + void setSize(unsigned Level, unsigned Size) { + path[Level].size = Size; + if (Level) + subtree(Level - 1).setSize(Size); + } + + /// setRoot - Clear the path and set a new root node. + /// @param Node New root node. + /// @param Size New root size. + /// @param Offset Offset into root node. + void setRoot(void *Node, unsigned Size, unsigned Offset) { + path.clear(); + path.push_back(Entry(Node, Size, Offset)); + } + + /// replaceRoot - Replace the current root node with two new entries after the + /// tree height has increased. + /// @param Root The new root node. + /// @param Size Number of entries in the new root. + /// @param Offsets Offsets into the root and first branch nodes. + void replaceRoot(void *Root, unsigned Size, IdxPair Offsets); + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sibling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getLeftSibling(unsigned Level) const; + + /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level + /// unaltered. + /// @param Level Move node(Level). + void moveLeft(unsigned Level); + + /// fillLeft - Grow path to Height by taking leftmost branches. + /// @param Height The target height. + void fillLeft(unsigned Height) { + while (height() < Height) + push(subtree(height()), 0); + } + + /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef. + /// @param Level Get the sinbling to node(Level). + /// @return Left sibling, or NodeRef(). + NodeRef getRightSibling(unsigned Level) const; + + /// moveRight - Move path to the left sibling at Level. Leave nodes below + /// Level unaltered. + /// @param Level Move node(Level). + void moveRight(unsigned Level); + + /// atBegin - Return true if path is at begin(). + bool atBegin() const { + for (unsigned i = 0, e = path.size(); i != e; ++i) + if (path[i].offset != 0) + return false; + return true; + } + + /// atLastEntry - Return true if the path is at the last entry of the node at + /// Level. + /// @param Level Node to examine. + bool atLastEntry(unsigned Level) const { + return path[Level].offset == path[Level].size - 1; + } + + /// legalizeForInsert - Prepare the path for an insertion at Level. When the + /// path is at end(), node(Level) may not be a legal node. legalizeForInsert + /// ensures that node(Level) is real by moving back to the last node at Level, + /// and setting offset(Level) to size(Level) if required. + /// @param Level The level where an insertion is about to take place. + void legalizeForInsert(unsigned Level) { + if (valid()) + return; + moveLeft(Level); + ++path[Level].offset; + } +}; + +} // namespace IntervalMapImpl + + +//===----------------------------------------------------------------------===// +//--- IntervalMap ----// +//===----------------------------------------------------------------------===// + +template ::LeafSize, + typename Traits = IntervalMapInfo > +class IntervalMap { + typedef IntervalMapImpl::NodeSizer Sizer; + typedef IntervalMapImpl::LeafNode Leaf; + typedef IntervalMapImpl::BranchNode + Branch; + typedef IntervalMapImpl::LeafNode RootLeaf; + typedef IntervalMapImpl::IdxPair IdxPair; + + // The RootLeaf capacity is given as a template parameter. We must compute the + // corresponding RootBranch capacity. + enum { + DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) / + (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)), + RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1 + }; + + typedef IntervalMapImpl::BranchNode + RootBranch; + + // When branched, we store a global start key as well as the branch node. + struct RootBranchData { + KeyT start; + RootBranch node; + }; + + enum { + RootDataSize = sizeof(RootBranchData) > sizeof(RootLeaf) ? + sizeof(RootBranchData) : sizeof(RootLeaf) + }; + +public: + typedef typename Sizer::Allocator Allocator; + typedef KeyT KeyType; + typedef ValT ValueType; + typedef Traits KeyTraits; + +private: + // The root data is either a RootLeaf or a RootBranchData instance. + // We can't put them in a union since C++03 doesn't allow non-trivial + // constructors in unions. + // Instead, we use a char array with pointer alignment. The alignment is + // ensured by the allocator member in the class, but still verified in the + // constructor. We don't support keys or values that are more aligned than a + // pointer. + char data[RootDataSize]; + + // Tree height. + // 0: Leaves in root. + // 1: Root points to leaf. + // 2: root->branch->leaf ... + unsigned height; + + // Number of entries in the root node. + unsigned rootSize; + + // Allocator used for creating external nodes. + Allocator &allocator; + + /// dataAs - Represent data as a node type without breaking aliasing rules. + template + T &dataAs() const { + union { + const char *d; + T *t; + } u; + u.d = data; + return *u.t; + } + + const RootLeaf &rootLeaf() const { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs(); + } + RootLeaf &rootLeaf() { + assert(!branched() && "Cannot acces leaf data in branched root"); + return dataAs(); + } + RootBranchData &rootBranchData() const { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs(); + } + RootBranchData &rootBranchData() { + assert(branched() && "Cannot access branch data in non-branched root"); + return dataAs(); + } + const RootBranch &rootBranch() const { return rootBranchData().node; } + RootBranch &rootBranch() { return rootBranchData().node; } + KeyT rootBranchStart() const { return rootBranchData().start; } + KeyT &rootBranchStart() { return rootBranchData().start; } + + template NodeT *newNode() { + return new(allocator.template Allocate()) NodeT(); + } + + template void deleteNode(NodeT *P) { + P->~NodeT(); + allocator.Deallocate(P); + } + + IdxPair branchRoot(unsigned Position); + IdxPair splitRoot(unsigned Position); + + void switchRootToBranch() { + rootLeaf().~RootLeaf(); + height = 1; + new (&rootBranchData()) RootBranchData(); + } + + void switchRootToLeaf() { + rootBranchData().~RootBranchData(); + height = 0; + new(&rootLeaf()) RootLeaf(); + } + + bool branched() const { return height > 0; } + + ValT treeSafeLookup(KeyT x, ValT NotFound) const; + void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, + unsigned Level)); + void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level); + +public: + explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) { + assert((uintptr_t(data) & (alignOf() - 1)) == 0 && + "Insufficient alignment"); + new(&rootLeaf()) RootLeaf(); + } + + ~IntervalMap() { + clear(); + rootLeaf().~RootLeaf(); + } + + /// empty - Return true when no intervals are mapped. + bool empty() const { + return rootSize == 0; + } + + /// start - Return the smallest mapped key in a non-empty map. + KeyT start() const { + assert(!empty() && "Empty IntervalMap has no start"); + return !branched() ? rootLeaf().start(0) : rootBranchStart(); + } + + /// stop - Return the largest mapped key in a non-empty map. + KeyT stop() const { + assert(!empty() && "Empty IntervalMap has no stop"); + return !branched() ? rootLeaf().stop(rootSize - 1) : + rootBranch().stop(rootSize - 1); + } + + /// lookup - Return the mapped value at x or NotFound. + ValT lookup(KeyT x, ValT NotFound = ValT()) const { + if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x)) + return NotFound; + return branched() ? treeSafeLookup(x, NotFound) : + rootLeaf().safeLookup(x, NotFound); + } + + /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals. + /// It is assumed that no key in the interval is mapped to another value, but + /// overlapping intervals already mapped to y will be coalesced. + void insert(KeyT a, KeyT b, ValT y) { + if (branched() || rootSize == RootLeaf::Capacity) + return find(a).insert(a, b, y); + + // Easy insert into root leaf. + unsigned p = rootLeaf().findFrom(0, rootSize, a); + rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y); + } + + /// clear - Remove all entries. + void clear(); + + class const_iterator; + class iterator; + friend class const_iterator; + friend class iterator; + + const_iterator begin() const { + const_iterator I(*this); + I.goToBegin(); + return I; + } + + iterator begin() { + iterator I(*this); + I.goToBegin(); + return I; + } + + const_iterator end() const { + const_iterator I(*this); + I.goToEnd(); + return I; + } + + iterator end() { + iterator I(*this); + I.goToEnd(); + return I; + } + + /// find - Return an iterator pointing to the first interval ending at or + /// after x, or end(). + const_iterator find(KeyT x) const { + const_iterator I(*this); + I.find(x); + return I; + } + + iterator find(KeyT x) { + iterator I(*this); + I.find(x); + return I; + } +}; + +/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a +/// branched root. +template +ValT IntervalMap:: +treeSafeLookup(KeyT x, ValT NotFound) const { + assert(branched() && "treeLookup assumes a branched root"); + + IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x); + for (unsigned h = height-1; h; --h) + NR = NR.get().safeLookup(x); + return NR.get().safeLookup(x, NotFound); +} + + +// branchRoot - Switch from a leaf root to a branched root. +// Return the new (root offset, node offset) corresponding to Position. +template +IntervalMapImpl::IdxPair IntervalMap:: +branchRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootLeaf+1? + const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, size, + Position, true); + + // Allocate new nodes. + unsigned pos = 0; + NodeRef node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Leaf *L = newNode(); + L->copy(rootLeaf(), pos, 0, size[n]); + node[n] = NodeRef(L, size[n]); + pos += size[n]; + } + + // Destroy the old leaf node, construct branch node instead. + switchRootToBranch(); + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = node[n].template get().stop(size[n]-1); + rootBranch().subtree(n) = node[n]; + } + rootBranchStart() = node[0].template get().start(0); + rootSize = Nodes; + return NewOffset; +} + +// splitRoot - Split the current BranchRoot into multiple Branch nodes. +// Return the new (root offset, node offset) corresponding to Position. +template +IntervalMapImpl::IdxPair IntervalMap:: +splitRoot(unsigned Position) { + using namespace IntervalMapImpl; + // How many external leaf nodes to hold RootBranch+1? + const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1; + + // Compute element distribution among new nodes. + unsigned Size[Nodes]; + IdxPair NewOffset(0, Position); + + // Is is very common for the root node to be smaller than external nodes. + if (Nodes == 1) + Size[0] = rootSize; + else + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, Size, + Position, true); + + // Allocate new nodes. + unsigned Pos = 0; + NodeRef Node[Nodes]; + for (unsigned n = 0; n != Nodes; ++n) { + Branch *B = newNode(); + B->copy(rootBranch(), Pos, 0, Size[n]); + Node[n] = NodeRef(B, Size[n]); + Pos += Size[n]; + } + + for (unsigned n = 0; n != Nodes; ++n) { + rootBranch().stop(n) = Node[n].template get().stop(Size[n]-1); + rootBranch().subtree(n) = Node[n]; + } + rootSize = Nodes; + ++height; + return NewOffset; +} + +/// visitNodes - Visit each external node. +template +void IntervalMap:: +visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) { + if (!branched()) + return; + SmallVector Refs, NextRefs; + + // Collect level 0 nodes from the root. + for (unsigned i = 0; i != rootSize; ++i) + Refs.push_back(rootBranch().subtree(i)); + + // Visit all branch nodes. + for (unsigned h = height - 1; h; --h) { + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + for (unsigned j = 0, s = Refs[i].size(); j != s; ++j) + NextRefs.push_back(Refs[i].subtree(j)); + (this->*f)(Refs[i], h); + } + Refs.clear(); + Refs.swap(NextRefs); + } + + // Visit all leaf nodes. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + (this->*f)(Refs[i], 0); +} + +template +void IntervalMap:: +deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) { + if (Level) + deleteNode(&Node.get()); + else + deleteNode(&Node.get()); +} + +template +void IntervalMap:: +clear() { + if (branched()) { + visitNodes(&IntervalMap::deleteNode); + switchRootToLeaf(); + } + rootSize = 0; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::const_iterator ----// +//===----------------------------------------------------------------------===// + +template +class IntervalMap::const_iterator : + public std::iterator { +protected: + friend class IntervalMap; + + // The map referred to. + IntervalMap *map; + + // We store a full path from the root to the current position. + // The path may be partially filled, but never between iterator calls. + IntervalMapImpl::Path path; + + explicit const_iterator(const IntervalMap &map) : + map(const_cast(&map)) {} + + bool branched() const { + assert(map && "Invalid iterator"); + return map->branched(); + } + + void setRoot(unsigned Offset) { + if (branched()) + path.setRoot(&map->rootBranch(), map->rootSize, Offset); + else + path.setRoot(&map->rootLeaf(), map->rootSize, Offset); + } + + void pathFillFind(KeyT x); + void treeFind(KeyT x); + void treeAdvanceTo(KeyT x); + + /// unsafeStart - Writable access to start() for iterator. + KeyT &unsafeStart() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf().start(path.leafOffset()) : + path.leaf().start(path.leafOffset()); + } + + /// unsafeStop - Writable access to stop() for iterator. + KeyT &unsafeStop() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf().stop(path.leafOffset()) : + path.leaf().stop(path.leafOffset()); + } + + /// unsafeValue - Writable access to value() for iterator. + ValT &unsafeValue() const { + assert(valid() && "Cannot access invalid iterator"); + return branched() ? path.leaf().value(path.leafOffset()) : + path.leaf().value(path.leafOffset()); + } + +public: + /// const_iterator - Create an iterator that isn't pointing anywhere. + const_iterator() : map(0) {} + + /// valid - Return true if the current position is valid, false for end(). + bool valid() const { return path.valid(); } + + /// start - Return the beginning of the current interval. + const KeyT &start() const { return unsafeStart(); } + + /// stop - Return the end of the current interval. + const KeyT &stop() const { return unsafeStop(); } + + /// value - Return the mapped value at the current interval. + const ValT &value() const { return unsafeValue(); } + + const ValT &operator*() const { return value(); } + + bool operator==(const const_iterator &RHS) const { + assert(map == RHS.map && "Cannot compare iterators from different maps"); + if (!valid()) + return !RHS.valid(); + if (path.leafOffset() != RHS.path.leafOffset()) + return false; + return &path.template leaf() == &RHS.path.template leaf(); + } + + bool operator!=(const const_iterator &RHS) const { + return !operator==(RHS); + } + + /// goToBegin - Move to the first interval in map. + void goToBegin() { + setRoot(0); + if (branched()) + path.fillLeft(map->height); + } + + /// goToEnd - Move beyond the last interval in map. + void goToEnd() { + setRoot(map->rootSize); + } + + /// preincrement - move to the next interval. + const_iterator &operator++() { + assert(valid() && "Cannot increment end()"); + if (++path.leafOffset() == path.leafSize() && branched()) + path.moveRight(map->height); + return *this; + } + + /// postincrement - Dont do that! + const_iterator operator++(int) { + const_iterator tmp = *this; + operator++(); + return tmp; + } + + /// predecrement - move to the previous interval. + const_iterator &operator--() { + if (path.leafOffset() && (valid() || !branched())) + --path.leafOffset(); + else + path.moveLeft(map->height); + return *this; + } + + /// postdecrement - Dont do that! + const_iterator operator--(int) { + const_iterator tmp = *this; + operator--(); + return tmp; + } + + /// find - Move to the first interval with stop >= x, or end(). + /// This is a full search from the root, the current position is ignored. + void find(KeyT x) { + if (branched()) + treeFind(x); + else + setRoot(map->rootLeaf().findFrom(0, map->rootSize, x)); + } + + /// advanceTo - Move to the first interval with stop >= x, or end(). + /// The search is started from the current position, and no earlier positions + /// can be found. This is much faster than find() for small moves. + void advanceTo(KeyT x) { + if (!valid()) + return; + if (branched()) + treeAdvanceTo(x); + else + path.leafOffset() = + map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x); + } + +}; + +/// pathFillFind - Complete path by searching for x. +/// @param x Key to search for. +template +void IntervalMap:: +const_iterator::pathFillFind(KeyT x) { + IntervalMapImpl::NodeRef NR = path.subtree(path.height()); + for (unsigned i = map->height - path.height() - 1; i; --i) { + unsigned p = NR.get().safeFind(0, x); + path.push(NR, p); + NR = NR.subtree(p); + } + path.push(NR, NR.get().safeFind(0, x)); +} + +/// treeFind - Find in a branched tree. +/// @param x Key to search for. +template +void IntervalMap:: +const_iterator::treeFind(KeyT x) { + setRoot(map->rootBranch().findFrom(0, map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +/// treeAdvanceTo - Find position after the current one. +/// @param x Key to search for. +template +void IntervalMap:: +const_iterator::treeAdvanceTo(KeyT x) { + // Can we stay on the same leaf node? + if (!Traits::stopLess(path.leaf().stop(path.leafSize() - 1), x)) { + path.leafOffset() = path.leaf().safeFind(path.leafOffset(), x); + return; + } + + // Drop the current leaf. + path.pop(); + + // Search towards the root for a usable subtree. + if (path.height()) { + for (unsigned l = path.height() - 1; l; --l) { + if (!Traits::stopLess(path.node(l).stop(path.offset(l)), x)) { + // The branch node at l+1 is usable + path.offset(l + 1) = + path.node(l + 1).safeFind(path.offset(l + 1), x); + return pathFillFind(x); + } + path.pop(); + } + // Is the level-1 Branch usable? + if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) { + path.offset(1) = path.node(1).safeFind(path.offset(1), x); + return pathFillFind(x); + } + } + + // We reached the root. + setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x)); + if (valid()) + pathFillFind(x); +} + +//===----------------------------------------------------------------------===// +//--- IntervalMap::iterator ----// +//===----------------------------------------------------------------------===// + +template +class IntervalMap::iterator : public const_iterator { + friend class IntervalMap; + typedef IntervalMapImpl::IdxPair IdxPair; + + explicit iterator(IntervalMap &map) : const_iterator(map) {} + + void setNodeStop(unsigned Level, KeyT Stop); + bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop); + template bool overflow(unsigned Level); + void treeInsert(KeyT a, KeyT b, ValT y); + void eraseNode(unsigned Level); + void treeErase(bool UpdateRoot = true); + bool canCoalesceLeft(KeyT Start, ValT x); + bool canCoalesceRight(KeyT Stop, ValT x); + +public: + /// iterator - Create null iterator. + iterator() {} + + /// setStart - Move the start of the current interval. + /// This may cause coalescing with the previous interval. + /// @param a New start key, must not overlap the previous interval. + void setStart(KeyT a); + + /// setStop - Move the end of the current interval. + /// This may cause coalescing with the following interval. + /// @param b New stop key, must not overlap the following interval. + void setStop(KeyT b); + + /// setValue - Change the mapped value of the current interval. + /// This may cause coalescing with the previous and following intervals. + /// @param x New value. + void setValue(ValT x); + + /// setStartUnchecked - Move the start of the current interval without + /// checking for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param a New start key. + void setStartUnchecked(KeyT a) { this->unsafeStart() = a; } + + /// setStopUnchecked - Move the end of the current interval without checking + /// for coalescing or overlaps. + /// This should only be used when it is known that coalescing is not required. + /// @param b New stop key. + void setStopUnchecked(KeyT b) { + this->unsafeStop() = b; + // Update keys in branch nodes as well. + if (this->path.atLastEntry(this->path.height())) + setNodeStop(this->path.height(), b); + } + + /// setValueUnchecked - Change the mapped value of the current interval + /// without checking for coalescing. + /// @param x New value. + void setValueUnchecked(ValT x) { this->unsafeValue() = x; } + + /// insert - Insert mapping [a;b] -> y before the current position. + void insert(KeyT a, KeyT b, ValT y); + + /// erase - Erase the current interval. + void erase(); + + iterator &operator++() { + const_iterator::operator++(); + return *this; + } + + iterator operator++(int) { + iterator tmp = *this; + operator++(); + return tmp; + } + + iterator &operator--() { + const_iterator::operator--(); + return *this; + } + + iterator operator--(int) { + iterator tmp = *this; + operator--(); + return tmp; + } + +}; + +/// canCoalesceLeft - Can the current interval coalesce to the left after +/// changing start or value? +/// @param Start New start of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template +bool IntervalMap:: +iterator::canCoalesceLeft(KeyT Start, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + if (!this->branched()) { + unsigned i = P.leafOffset(); + RootLeaf &Node = P.leaf(); + return i && Node.value(i-1) == Value && + Traits::adjacent(Node.stop(i-1), Start); + } + // Branched. + if (unsigned i = P.leafOffset()) { + Leaf &Node = P.leaf(); + return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start); + } else if (NodeRef NR = P.getLeftSibling(P.height())) { + unsigned i = NR.size() - 1; + Leaf &Node = NR.get(); + return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start); + } + return false; +} + +/// canCoalesceRight - Can the current interval coalesce to the right after +/// changing stop or value? +/// @param Stop New stop of current interval. +/// @param Value New value for current interval. +/// @return True when updating the current interval would enable coalescing. +template +bool IntervalMap:: +iterator::canCoalesceRight(KeyT Stop, ValT Value) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned i = P.leafOffset() + 1; + if (!this->branched()) { + if (i >= P.leafSize()) + return false; + RootLeaf &Node = P.leaf(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } + // Branched. + if (i < P.leafSize()) { + Leaf &Node = P.leaf(); + return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i)); + } else if (NodeRef NR = P.getRightSibling(P.height())) { + Leaf &Node = NR.get(); + return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0)); + } + return false; +} + +/// setNodeStop - Update the stop key of the current node at level and above. +template +void IntervalMap:: +iterator::setNodeStop(unsigned Level, KeyT Stop) { + // There are no references to the root node, so nothing to update. + if (!Level) + return; + IntervalMapImpl::Path &P = this->path; + // Update nodes pointing to the current node. + while (--Level) { + P.node(Level).stop(P.offset(Level)) = Stop; + if (!P.atLastEntry(Level)) + return; + } + // Update root separately since it has a different layout. + P.node(Level).stop(P.offset(Level)) = Stop; +} + +template +void IntervalMap:: +iterator::setStart(KeyT a) { + assert(Traits::stopLess(a, this->stop()) && "Cannot move start beyond stop"); + KeyT &CurStart = this->unsafeStart(); + if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) { + CurStart = a; + return; + } + // Coalesce with the interval to the left. + --*this; + a = this->start(); + erase(); + setStartUnchecked(a); +} + +template +void IntervalMap:: +iterator::setStop(KeyT b) { + assert(Traits::stopLess(this->start(), b) && "Cannot move stop beyond start"); + if (Traits::startLess(b, this->stop()) || + !canCoalesceRight(b, this->value())) { + setStopUnchecked(b); + return; + } + // Coalesce with interval to the right. + KeyT a = this->start(); + erase(); + setStartUnchecked(a); +} + +template +void IntervalMap:: +iterator::setValue(ValT x) { + setValueUnchecked(x); + if (canCoalesceRight(this->stop(), x)) { + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } + if (canCoalesceLeft(this->start(), x)) { + --*this; + KeyT a = this->start(); + erase(); + setStartUnchecked(a); + } +} + +/// insertNode - insert a node before the current path at level. +/// Leave the current path pointing at the new node. +/// @param Level path index of the node to be inserted. +/// @param Node The node to be inserted. +/// @param Stop The last index in the new node. +/// @return True if the tree height was increased. +template +bool IntervalMap:: +iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) { + assert(Level && "Cannot insert next to the root"); + bool SplitRoot = false; + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (Level == 1) { + // Insert into the root branch node. + if (IM.rootSize < RootBranch::Capacity) { + IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop); + P.setSize(0, ++IM.rootSize); + P.reset(Level); + return SplitRoot; + } + + // We need to split the root while keeping our position. + SplitRoot = true; + IdxPair Offset = IM.splitRoot(P.offset(0)); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Fall through to insert at the new higher level. + ++Level; + } + + // When inserting before end(), make sure we have a valid path. + P.legalizeForInsert(--Level); + + // Insert into the branch node at Level-1. + if (P.size(Level) == Branch::Capacity) { + // Branch node is full, handle handle the overflow. + assert(!SplitRoot && "Cannot overflow after splitting the root"); + SplitRoot = overflow(Level); + Level += SplitRoot; + } + P.node(Level).insert(P.offset(Level), P.size(Level), Node, Stop); + P.setSize(Level, P.size(Level) + 1); + if (P.atLastEntry(Level)) + setNodeStop(Level, Stop); + P.reset(Level + 1); + return SplitRoot; +} + +// insert +template +void IntervalMap:: +iterator::insert(KeyT a, KeyT b, ValT y) { + if (this->branched()) + return treeInsert(a, b, y); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + // Try simple root leaf insert. + unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y); + + // Was the root node insert successful? + if (Size <= RootLeaf::Capacity) { + P.setSize(0, IM.rootSize = Size); + return; + } + + // Root leaf node is full, we must branch. + IdxPair Offset = IM.branchRoot(P.leafOffset()); + P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset); + + // Now it fits in the new leaf. + treeInsert(a, b, y); +} + + +template +void IntervalMap:: +iterator::treeInsert(KeyT a, KeyT b, ValT y) { + using namespace IntervalMapImpl; + Path &P = this->path; + + if (!P.valid()) + P.legalizeForInsert(this->map->height); + + // Check if this insertion will extend the node to the left. + if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf().start(0))) { + // Node is growing to the left, will it affect a left sibling node? + if (NodeRef Sib = P.getLeftSibling(P.height())) { + Leaf &SibLeaf = Sib.get(); + unsigned SibOfs = Sib.size() - 1; + if (SibLeaf.value(SibOfs) == y && + Traits::adjacent(SibLeaf.stop(SibOfs), a)) { + // This insertion will coalesce with the last entry in SibLeaf. We can + // handle it in two ways: + // 1. Extend SibLeaf.stop to b and be done, or + // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue. + // We prefer 1., but need 2 when coalescing to the right as well. + Leaf &CurLeaf = P.leaf(); + P.moveLeft(P.height()); + if (Traits::stopLess(b, CurLeaf.start(0)) && + (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) { + // Easy, just extend SibLeaf and we're done. + setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b); + return; + } else { + // We have both left and right coalescing. Erase the old SibLeaf entry + // and continue inserting the larger interval. + a = SibLeaf.start(SibOfs); + treeErase(/* UpdateRoot= */false); + } + } + } else { + // No left sibling means we are at begin(). Update cached bound. + this->map->rootBranchStart() = a; + } + } + + // When we are inserting at the end of a leaf node, we must update stops. + unsigned Size = P.leafSize(); + bool Grow = P.leafOffset() == Size; + Size = P.leaf().insertFrom(P.leafOffset(), Size, a, b, y); + + // Leaf insertion unsuccessful? Overflow and try again. + if (Size > Leaf::Capacity) { + overflow(P.height()); + Grow = P.leafOffset() == P.leafSize(); + Size = P.leaf().insertFrom(P.leafOffset(), P.leafSize(), a, b, y); + assert(Size <= Leaf::Capacity && "overflow() didn't make room"); + } + + // Inserted, update offset and leaf size. + P.setSize(P.height(), Size); + + // Insert was the last node entry, update stops. + if (Grow) + setNodeStop(P.height(), b); +} + +/// erase - erase the current interval and move to the next position. +template +void IntervalMap:: +iterator::erase() { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + assert(P.valid() && "Cannot erase end()"); + if (this->branched()) + return treeErase(); + IM.rootLeaf().erase(P.leafOffset(), IM.rootSize); + P.setSize(0, --IM.rootSize); +} + +/// treeErase - erase() for a branched tree. +template +void IntervalMap:: +iterator::treeErase(bool UpdateRoot) { + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + Leaf &Node = P.leaf(); + + // Nodes are not allowed to become empty. + if (P.leafSize() == 1) { + IM.deleteNode(&Node); + eraseNode(IM.height); + // Update rootBranchStart if we erased begin(). + if (UpdateRoot && IM.branched() && P.valid() && P.atBegin()) + IM.rootBranchStart() = P.leaf().start(0); + return; + } + + // Erase current entry. + Node.erase(P.leafOffset(), P.leafSize()); + unsigned NewSize = P.leafSize() - 1; + P.setSize(IM.height, NewSize); + // When we erase the last entry, update stop and move to a legal position. + if (P.leafOffset() == NewSize) { + setNodeStop(IM.height, Node.stop(NewSize - 1)); + P.moveRight(IM.height); + } else if (UpdateRoot && P.atBegin()) + IM.rootBranchStart() = P.leaf().start(0); +} + +/// eraseNode - Erase the current node at Level from its parent and move path to +/// the first entry of the next sibling node. +/// The node must be deallocated by the caller. +/// @param Level 1..height, the root node cannot be erased. +template +void IntervalMap:: +iterator::eraseNode(unsigned Level) { + assert(Level && "Cannot erase root node"); + IntervalMap &IM = *this->map; + IntervalMapImpl::Path &P = this->path; + + if (--Level == 0) { + IM.rootBranch().erase(P.offset(0), IM.rootSize); + P.setSize(0, --IM.rootSize); + // If this cleared the root, switch to height=0. + if (IM.empty()) { + IM.switchRootToLeaf(); + this->setRoot(0); + return; + } + } else { + // Remove node ref from branch node at Level. + Branch &Parent = P.node(Level); + if (P.size(Level) == 1) { + // Branch node became empty, remove it recursively. + IM.deleteNode(&Parent); + eraseNode(Level); + } else { + // Branch node won't become empty. + Parent.erase(P.offset(Level), P.size(Level)); + unsigned NewSize = P.size(Level) - 1; + P.setSize(Level, NewSize); + // If we removed the last branch, update stop and move to a legal pos. + if (P.offset(Level) == NewSize) { + setNodeStop(Level, Parent.stop(NewSize - 1)); + P.moveRight(Level); + } + } + } + // Update path cache for the new right sibling position. + if (P.valid()) { + P.reset(Level + 1); + P.offset(Level + 1) = 0; + } +} + +/// overflow - Distribute entries of the current node evenly among +/// its siblings and ensure that the current node is not full. +/// This may require allocating a new node. +/// @param NodeT The type of node at Level (Leaf or Branch). +/// @param Level path index of the overflowing node. +/// @return True when the tree height was changed. +template +template +bool IntervalMap:: +iterator::overflow(unsigned Level) { + using namespace IntervalMapImpl; + Path &P = this->path; + unsigned CurSize[4]; + NodeT *Node[4]; + unsigned Nodes = 0; + unsigned Elements = 0; + unsigned Offset = P.offset(Level); + + // Do we have a left sibling? + NodeRef LeftSib = P.getLeftSibling(Level); + if (LeftSib) { + Offset += Elements = CurSize[Nodes] = LeftSib.size(); + Node[Nodes++] = &LeftSib.get(); + } + + // Current node. + Elements += CurSize[Nodes] = P.size(Level); + Node[Nodes++] = &P.node(Level); + + // Do we have a right sibling? + NodeRef RightSib = P.getRightSibling(Level); + if (RightSib) { + Elements += CurSize[Nodes] = RightSib.size(); + Node[Nodes++] = &RightSib.get(); + } + + // Do we need to allocate a new node? + unsigned NewNode = 0; + if (Elements + 1 > Nodes * NodeT::Capacity) { + // Insert NewNode at the penultimate position, or after a single node. + NewNode = Nodes == 1 ? 1 : Nodes - 1; + CurSize[Nodes] = CurSize[NewNode]; + Node[Nodes] = Node[NewNode]; + CurSize[NewNode] = 0; + Node[NewNode] = this->map->newNode(); + ++Nodes; + } + + // Compute the new element distribution. + unsigned NewSize[4]; + IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity, + CurSize, NewSize, Offset, true); + adjustSiblingSizes(Node, Nodes, CurSize, NewSize); + + // Move current location to the leftmost node. + if (LeftSib) + P.moveLeft(Level); + + // Elements have been rearranged, now update node sizes and stops. + bool SplitRoot = false; + unsigned Pos = 0; + for (;;) { + KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1); + if (NewNode && Pos == NewNode) { + SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop); + Level += SplitRoot; + } else { + P.setSize(Level, NewSize[Pos]); + setNodeStop(Level, Stop); + } + if (Pos + 1 == Nodes) + break; + P.moveRight(Level); + ++Pos; + } + + // Where was I? Find NewOffset. + while(Pos != NewOffset.first) { + P.moveLeft(Level); + --Pos; + } + P.offset(Level) = NewOffset.second; + return SplitRoot; +} + +//===----------------------------------------------------------------------===// +//--- IntervalMapOverlaps ----// +//===----------------------------------------------------------------------===// + +/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two +/// IntervalMaps. The maps may be different, but the KeyT and Traits types +/// should be the same. +/// +/// Typical uses: +/// +/// 1. Test for overlap: +/// bool overlap = IntervalMapOverlaps(a, b).valid(); +/// +/// 2. Enumerate overlaps: +/// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... } +/// +template +class IntervalMapOverlaps { + typedef typename MapA::KeyType KeyType; + typedef typename MapA::KeyTraits Traits; + typename MapA::const_iterator posA; + typename MapB::const_iterator posB; + + /// advance - Move posA and posB forward until reaching an overlap, or until + /// either meets end. + /// Don't move the iterators if they are already overlapping. + void advance() { + if (!valid()) + return; + + if (Traits::stopLess(posA.stop(), posB.start())) { + // A ends before B begins. Catch up. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + } else if (Traits::stopLess(posB.stop(), posA.start())) { + // B ends before A begins. Catch up. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } else + // Already overlapping. + return; + + for (;;) { + // Make a.end > b.start. + posA.advanceTo(posB.start()); + if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start())) + return; + // Make b.end > a.start. + posB.advanceTo(posA.start()); + if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start())) + return; + } + } + +public: + /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b. + IntervalMapOverlaps(const MapA &a, const MapB &b) + : posA(b.empty() ? a.end() : a.find(b.start())), + posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); } + + /// valid - Return true if iterator is at an overlap. + bool valid() const { + return posA.valid() && posB.valid(); + } + + /// a - access the left hand side in the overlap. + const typename MapA::const_iterator &a() const { return posA; } + + /// b - access the right hand side in the overlap. + const typename MapB::const_iterator &b() const { return posB; } + + /// start - Beginning of the overlapping interval. + KeyType start() const { + KeyType ak = a().start(); + KeyType bk = b().start(); + return Traits::startLess(ak, bk) ? bk : ak; + } + + /// stop - End of the overlapping interval. + KeyType stop() const { + KeyType ak = a().stop(); + KeyType bk = b().stop(); + return Traits::startLess(ak, bk) ? ak : bk; + } + + /// skipA - Move to the next overlap that doesn't involve a(). + void skipA() { + ++posA; + advance(); + } + + /// skipB - Move to the next overlap that doesn't involve b(). + void skipB() { + ++posB; + advance(); + } + + /// Preincrement - Move to the next overlap. + IntervalMapOverlaps &operator++() { + // Bump the iterator that ends first. The other one may have more overlaps. + if (Traits::startLess(posB.stop(), posA.stop())) + skipB(); + else + skipA(); + return *this; + } + + /// advanceTo - Move to the first overlapping interval with + /// stopLess(x, stop()). + void advanceTo(KeyType x) { + if (!valid()) + return; + // Make sure advanceTo sees monotonic keys. + if (Traits::stopLess(posA.stop(), x)) + posA.advanceTo(x); + if (Traits::stopLess(posB.stop(), x)) + posB.advanceTo(x); + advance(); + } +}; + +} // namespace llvm + +#endif diff --git a/final/include/llvm/ADT/IntrusiveRefCntPtr.h b/final/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 00000000000..37d4ac9d29d --- /dev/null +++ b/final/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -0,0 +1,230 @@ +//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- 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 IntrusiveRefCntPtr, a template class that +// implements a "smart" pointer for objects that maintain their own +// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two +// generic base classes for objects that wish to have their lifetimes +// managed using reference counting. +// +// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added +// LLVM-style casting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR +#define LLVM_ADT_INTRUSIVE_REF_CNT_PTR + +#include + +#include "llvm/Support/Casting.h" + +namespace llvm { + + template + class IntrusiveRefCntPtr; + +//===----------------------------------------------------------------------===// +/// RefCountedBase - A generic base class for objects that wish to +/// have their lifetimes managed using reference counts. Classes +/// subclass RefCountedBase to obtain such functionality, and are +/// typically handled with IntrusivePtr "smart pointers" (see below) +/// which automatically handle the management of reference counts. +/// Objects that subclass RefCountedBase should not be allocated on +/// the stack, as invoking "delete" (which is called when the +/// reference count hits 0) on such objects is an error. +//===----------------------------------------------------------------------===// + template + class RefCountedBase { + unsigned ref_cnt; + + protected: + RefCountedBase() : ref_cnt(0) {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete static_cast(this); + } + + friend class IntrusiveRefCntPtr; + }; + +//===----------------------------------------------------------------------===// +/// RefCountedBaseVPTR - A class that has the same function as +/// RefCountedBase, but with a virtual destructor. Should be used +/// instead of RefCountedBase for classes that already have virtual +/// methods to enforce dynamic allocation via 'new'. Classes that +/// inherit from RefCountedBaseVPTR can't be allocated on stack - +/// attempting to do this will produce a compile error. +//===----------------------------------------------------------------------===// + template + class RefCountedBaseVPTR { + unsigned ref_cnt; + + protected: + RefCountedBaseVPTR() : ref_cnt(0) {} + virtual ~RefCountedBaseVPTR() {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete this; + } + + friend class IntrusiveRefCntPtr; + }; + +//===----------------------------------------------------------------------===// +/// IntrusiveRefCntPtr - A template class that implements a "smart pointer" +/// that assumes the wrapped object has a reference count associated +/// with it that can be managed via calls to +/// IntrusivePtrAddRef/IntrusivePtrRelease. The smart pointers +/// manage reference counts via the RAII idiom: upon creation of +/// smart pointer the reference count of the wrapped object is +/// incremented and upon destruction of the smart pointer the +/// reference count is decremented. This class also safely handles +/// wrapping NULL pointers. +/// +/// Reference counting is implemented via calls to +/// Obj->Retain()/Obj->Release(). Release() is required to destroy +/// the object when the reference count reaches zero. Inheriting from +/// RefCountedBase/RefCountedBaseVPTR takes care of this +/// automatically. +//===----------------------------------------------------------------------===// + template + class IntrusiveRefCntPtr { + T* Obj; + typedef IntrusiveRefCntPtr this_type; + public: + typedef T element_type; + + explicit IntrusiveRefCntPtr() : Obj(0) {} + + explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) { + retain(); + } + + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { + retain(); + } + + template + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) + : Obj(S.getPtr()) { + retain(); + } + + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { + replace(S.getPtr()); + return *this; + } + + template + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { + replace(S.getPtr()); + return *this; + } + + IntrusiveRefCntPtr& operator=(T * S) { + replace(S); + return *this; + } + + ~IntrusiveRefCntPtr() { release(); } + + T& operator*() const { return *Obj; } + + T* operator->() const { return Obj; } + + T* getPtr() const { return Obj; } + + typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; + operator unspecified_bool_type() const { + return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; + } + + void swap(IntrusiveRefCntPtr& other) { + T* tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + private: + void retain() { if (Obj) Obj->Retain(); } + void release() { if (Obj) Obj->Release(); } + + void replace(T* S) { + this_type(S).swap(*this); + } + }; + + template + inline bool operator==(const IntrusiveRefCntPtr& A, + const IntrusiveRefCntPtr& B) + { + return A.getPtr() == B.getPtr(); + } + + template + inline bool operator!=(const IntrusiveRefCntPtr& A, + const IntrusiveRefCntPtr& B) + { + return A.getPtr() != B.getPtr(); + } + + template + inline bool operator==(const IntrusiveRefCntPtr& A, + U* B) + { + return A.getPtr() == B; + } + + template + inline bool operator!=(const IntrusiveRefCntPtr& A, + U* B) + { + return A.getPtr() != B; + } + + template + inline bool operator==(T* A, + const IntrusiveRefCntPtr& B) + { + return A == B.getPtr(); + } + + template + inline bool operator!=(T* A, + const IntrusiveRefCntPtr& B) + { + return A != B.getPtr(); + } + +//===----------------------------------------------------------------------===// +// LLVM-style downcasting support for IntrusiveRefCntPtr objects +//===----------------------------------------------------------------------===// + + template struct simplify_type > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { + return Val.getPtr(); + } + }; + + template struct simplify_type > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr& Val) { + return Val.getPtr(); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR diff --git a/final/include/llvm/ADT/NullablePtr.h b/final/include/llvm/ADT/NullablePtr.h new file mode 100644 index 00000000000..a9c47a138ec --- /dev/null +++ b/final/include/llvm/ADT/NullablePtr.h @@ -0,0 +1,52 @@ +//===- llvm/ADT/NullablePtr.h - A pointer that allows null ------*- 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 and implements the NullablePtr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_NULLABLE_PTR_H +#define LLVM_ADT_NULLABLE_PTR_H + +#include +#include + +namespace llvm { +/// NullablePtr pointer wrapper - NullablePtr is used for APIs where a +/// potentially-null pointer gets passed around that must be explicitly handled +/// in lots of places. By putting a wrapper around the null pointer, it makes +/// it more likely that the null pointer case will be handled correctly. +template +class NullablePtr { + T *Ptr; +public: + NullablePtr(T *P = 0) : Ptr(P) {} + + bool isNull() const { return Ptr == 0; } + bool isNonNull() const { return Ptr != 0; } + + /// get - Return the pointer if it is non-null. + const T *get() const { + assert(Ptr && "Pointer wasn't checked for null!"); + return Ptr; + } + + /// get - Return the pointer if it is non-null. + T *get() { + assert(Ptr && "Pointer wasn't checked for null!"); + return Ptr; + } + + T *getPtrOrNull() { return Ptr; } + const T *getPtrOrNull() const { return Ptr; } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/Optional.h b/final/include/llvm/ADT/Optional.h new file mode 100644 index 00000000000..ee8b69f3d12 --- /dev/null +++ b/final/include/llvm/ADT/Optional.h @@ -0,0 +1,120 @@ +//===-- Optional.h - Simple variant for passing optional values ---*- 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 Optional, a template class modeled in the spirit of +// OCaml's 'opt' variant. The idea is to strongly type whether or not +// a value can be optional. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OPTIONAL +#define LLVM_ADT_OPTIONAL + +#include + +namespace llvm { + +template +class Optional { + T x; + unsigned hasVal : 1; +public: + explicit Optional() : x(), hasVal(false) {} + Optional(const T &y) : x(y), hasVal(true) {} + + static inline Optional create(const T* y) { + return y ? Optional(*y) : Optional(); + } + + Optional &operator=(const T &y) { + x = y; + hasVal = true; + return *this; + } + + const T* getPointer() const { assert(hasVal); return &x; } + const T& getValue() const { assert(hasVal); return x; } + + operator bool() const { return hasVal; } + bool hasValue() const { return hasVal; } + const T* operator->() const { return getPointer(); } + const T& operator*() const { assert(hasVal); return x; } +}; + +template struct simplify_type; + +template +struct simplify_type > { + typedef const T* SimpleType; + static SimpleType getSimplifiedValue(const Optional &Val) { + return Val.getPointer(); + } +}; + +template +struct simplify_type > + : public simplify_type > {}; + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator==(const Optional &X, const Optional &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator!=(const Optional &X, const Optional &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator<(const Optional &X, const Optional &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator<=(const Optional &X, const Optional &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator>=(const Optional &X, const Optional &Y); + +/// \brief Poison comparison between two \c Optional objects. Clients needs to +/// explicitly compare the underlying values and account for empty \c Optional +/// objects. +/// +/// This routine will never be defined. It returns \c void to help diagnose +/// errors at compile time. +template +void operator>(const Optional &X, const Optional &Y); + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/ADT/OwningPtr.h b/final/include/llvm/ADT/OwningPtr.h new file mode 100644 index 00000000000..6d9c3059778 --- /dev/null +++ b/final/include/llvm/ADT/OwningPtr.h @@ -0,0 +1,133 @@ +//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 and implements the OwningPtr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OWNING_PTR_H +#define LLVM_ADT_OWNING_PTR_H + +#include +#include + +namespace llvm { + +/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it +/// guarantees deletion of the object pointed to, either on destruction of the +/// OwningPtr or via an explicit reset(). Once created, ownership of the +/// pointee object can be taken away from OwningPtr by using the take method. +template +class OwningPtr { + OwningPtr(OwningPtr const &); // DO NOT IMPLEMENT + OwningPtr &operator=(OwningPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningPtr(T *P = 0) : Ptr(P) {} + + ~OwningPtr() { + delete Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator*() const { + assert(Ptr && "Cannot dereference null pointer"); + return *Ptr; + } + + T *operator->() const { return Ptr; } + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template +inline void swap(OwningPtr &a, OwningPtr &b) { + a.swap(b); +} + +/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same +/// functionality as OwningPtr, except that it works for array types. +template +class OwningArrayPtr { + OwningArrayPtr(OwningArrayPtr const &); // DO NOT IMPLEMENT + OwningArrayPtr &operator=(OwningArrayPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} + + ~OwningArrayPtr() { + delete [] Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete [] Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator[](std::ptrdiff_t i) const { + assert(Ptr && "Cannot dereference null pointer"); + return Ptr[i]; + } + + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningArrayPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template +inline void swap(OwningArrayPtr &a, OwningArrayPtr &b) { + a.swap(b); +} + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/PointerIntPair.h b/final/include/llvm/ADT/PointerIntPair.h new file mode 100644 index 00000000000..85dbba2b4a4 --- /dev/null +++ b/final/include/llvm/ADT/PointerIntPair.h @@ -0,0 +1,163 @@ +//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- 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 PointerIntPair class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERINTPAIR_H +#define LLVM_ADT_POINTERINTPAIR_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include + +namespace llvm { + +template +struct DenseMapInfo; + +/// PointerIntPair - This class implements a pair of a pointer and small +/// integer. It is designed to represent this in the space required by one +/// pointer by bitmangling the integer into the low part of the pointer. This +/// can only be done for small integers: typically up to 3 bits, but it depends +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the Int part in the highest bits +/// possible. For example, PointerIntPair will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair, 1, bool> +/// ... and the two bools will land in different bits. +/// +template > +class PointerIntPair { + intptr_t Value; + enum { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1), + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) + }; +public: + PointerIntPair() : Value(0) {} + PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + assert(IntBits <= PtrTraits::NumLowBitsAvailable && + "PointerIntPair formed with integer size too large for pointer"); + setPointer(Ptr); + setInt(Int); + } + + PointerTy getPointer() const { + return PtrTraits::getFromVoidPointer( + reinterpret_cast(Value & PointerBitMask)); + } + + IntType getInt() const { + return (IntType)((Value >> IntShift) & IntMask); + } + + void setPointer(PointerTy Ptr) { + intptr_t PtrVal + = reinterpret_cast(PtrTraits::getAsVoidPointer(Ptr)); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + // Preserve all low bits, just update the pointer. + Value = PtrVal | (Value & ~PointerBitMask); + } + + void setInt(IntType Int) { + intptr_t IntVal = Int; + assert(IntVal < (1 << IntBits) && "Integer too large for field"); + + // Preserve all bits other than the ones we are updating. + Value &= ~ShiftedIntMask; // Remove integer field. + Value |= IntVal << IntShift; // Set new integer. + } + + PointerTy const *getAddrOfPointer() const { + assert(Value == reinterpret_cast(getPointer()) && + "Can only return the address if IntBits is cleared and " + "PtrTraits doesn't change the pointer"); + return reinterpret_cast(&Value); + } + + void *getOpaqueValue() const { return reinterpret_cast(Value); } + void setFromOpaqueValue(void *Val) { Value = reinterpret_cast(Val);} + + static PointerIntPair getFromOpaqueValue(void *V) { + PointerIntPair P; P.setFromOpaqueValue(V); return P; + } + + bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;} + bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;} + bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;} + bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;} + bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;} + bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;} +}; + +template struct isPodLike; +template +struct isPodLike > { + static const bool value = true; +}; + +// Provide specialization of DenseMapInfo for PointerIntPair. +template +struct DenseMapInfo > { + typedef PointerIntPair Ty; + static Ty getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return Ty(reinterpret_cast(Val), IntType((1 << IntBits)-1)); + } + static Ty getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return Ty(reinterpret_cast(Val), IntType(0)); + } + static unsigned getHashValue(Ty V) { + uintptr_t IV = reinterpret_cast(V.getOpaqueValue()); + return unsigned(IV) ^ unsigned(IV >> 9); + } + static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } +}; + +// Teach SmallPtrSet that PointerIntPair is "basically a pointer". +template +class PointerLikeTypeTraits > { +public: + static inline void * + getAsVoidPointer(const PointerIntPair &P) { + return P.getOpaqueValue(); + } + static inline PointerIntPair + getFromVoidPointer(void *P) { + return PointerIntPair::getFromOpaqueValue(P); + } + enum { + NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits + }; +}; + +} // end namespace llvm +#endif diff --git a/final/include/llvm/ADT/PointerUnion.h b/final/include/llvm/ADT/PointerUnion.h new file mode 100644 index 00000000000..13b98cef07a --- /dev/null +++ b/final/include/llvm/ADT/PointerUnion.h @@ -0,0 +1,445 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- 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 PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + + template + struct PointerUnionTypeSelectorReturn { + typedef T Return; + }; + + /// \brief Get a type based on whether two types are the same or not. For: + /// @code + /// typedef typename PointerUnionTypeSelector::Return Ret; + /// @endcode + /// Ret will be EQ type if T1 is same as T2 or NE type otherwise. + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelector { + typedef typename PointerUnionTypeSelectorReturn::Return Return; + }; + + template + struct PointerUnionTypeSelectorReturn< + PointerUnionTypeSelector > { + typedef typename PointerUnionTypeSelector::Return + Return; + }; + + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion + /// for the two template arguments. + template + class PointerUnionUIntTraits { + public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { + PT1BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + PT2BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + }; + }; + + /// PointerUnion - This implements a discriminated union of two pointer types, + /// and keeps the discriminator bit-mangled into the low bits of the pointer. + /// This allows the implementation to be extremely efficient in space, but + /// permits a very natural and type-safe API. + /// + /// Common use patterns would be something like this: + /// PointerUnion P; + /// P = (int*)0; + /// printf("%d %d", P.is(), P.is()); // prints "1 0" + /// X = P.get(); // ok. + /// Y = P.get(); // runtime assertion failure. + /// Z = P.get(); // runtime assertion failure (regardless of tag) + /// P = (float*)0; + /// Y = P.get(); // ok. + /// X = P.get(); // runtime assertion failure. + template + class PointerUnion { + public: + typedef PointerIntPair > ValTy; + private: + ValTy Val; + + struct IsPT1 { + static const int Num = 0; + }; + struct IsPT2 { + static const int Num = 1; + }; + template + struct UNION_DOESNT_CONTAIN_TYPE { }; + + public: + PointerUnion() {} + + PointerUnion(PT1 V) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); + Val.setInt(0); + } + PointerUnion(PT2 V) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(V))); + Val.setInt(1); + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.getPointer() == 0; } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + typedef typename + ::llvm::PointerUnionTypeSelector > >::Return Ty; + int TyNo = Ty::Num; + return static_cast(Val.getInt()) == TyNo; + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + return PointerLikeTypeTraits::getFromVoidPointer(Val.getPointer()); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// \brief If the union is set to the first pointer type we can get an + /// address pointing to it. + template + PT1 const *getAddrOf() const { + assert(is() && "Val is not the first pointer"); + assert(get() == Val.getPointer() && + "Can't get the address because PointerLikeTypeTraits changes the ptr"); + T const *can_only_get_address_of_first_pointer_type + = reinterpret_cast(Val.getAddrOfPointer()); + return can_only_get_address_of_first_pointer_type; + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion &operator=(const PT1 &RHS) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); + Val.setInt(0); + return *this; + } + const PointerUnion &operator=(const PT2 &RHS) { + Val.setPointer( + const_cast(PointerLikeTypeTraits::getAsVoidPointer(RHS))); + Val.setInt(1); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits)-1. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion + getFromVoidPointer(void *P) { + return PointerUnion::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; + + + /// PointerUnion3 - This is a pointer union of three pointer types. See + /// documentation for PointerUnion for usage. + template + class PointerUnion3 { + public: + typedef PointerUnion InnerUnion; + typedef PointerUnion ValTy; + private: + ValTy Val; + + struct IsInnerUnion { + ValTy Val; + IsInnerUnion(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is() && + Val.template get().template is(); + } + template + T get() const { + return Val.template get().template get(); + } + }; + + struct IsPT3 { + ValTy Val; + IsPT3(ValTy val) : Val(val) { } + template + int is() const { + return Val.template is(); + } + template + T get() const { + return Val.template get(); + } + }; + + public: + PointerUnion3() {} + + PointerUnion3(PT1 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT2 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT3 V) { + Val = V; + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.isNull(); } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).is(); + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Ty(Val).get(); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion3 &operator=(const PT1 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT2 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT3 &RHS) { + Val = RHS; + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion3 getFromOpaqueValue(void *VP) { + PointerUnion3 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion3 &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion3 + getFromVoidPointer(void *P) { + return PointerUnion3::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; + + /// PointerUnion4 - This is a pointer union of four pointer types. See + /// documentation for PointerUnion for usage. + template + class PointerUnion4 { + public: + typedef PointerUnion InnerUnion1; + typedef PointerUnion InnerUnion2; + typedef PointerUnion ValTy; + private: + ValTy Val; + public: + PointerUnion4() {} + + PointerUnion4(PT1 V) { + Val = InnerUnion1(V); + } + PointerUnion4(PT2 V) { + Val = InnerUnion1(V); + } + PointerUnion4(PT3 V) { + Val = InnerUnion2(V); + } + PointerUnion4(PT4 V) { + Val = InnerUnion2(V); + } + + /// isNull - Return true if the pointer held in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.isNull(); } + operator bool() const { return !isNull(); } + + /// is() return true if the Union currently holds the type matching T. + template + int is() const { + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template is() && + Val.template get().template is(); + } + + /// get() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template + T get() const { + assert(is() && "Invalid accessor called"); + // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. + typedef typename + ::llvm::PointerUnionTypeSelector + >::Return Ty; + return Val.template get().template get(); + } + + /// dyn_cast() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template + T dyn_cast() const { + if (is()) return get(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion4 &operator=(const PT1 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT2 &RHS) { + Val = InnerUnion1(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT3 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + const PointerUnion4 &operator=(const PT4 &RHS) { + Val = InnerUnion2(RHS); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static inline PointerUnion4 getFromOpaqueValue(void *VP) { + PointerUnion4 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion4 &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion4 + getFromVoidPointer(void *P) { + return PointerUnion4::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::ValTy> + ::NumLowBitsAvailable + }; + }; +} + +#endif diff --git a/final/include/llvm/ADT/PostOrderIterator.h b/final/include/llvm/ADT/PostOrderIterator.h new file mode 100644 index 00000000000..e3b499488d0 --- /dev/null +++ b/final/include/llvm/ADT/PostOrderIterator.h @@ -0,0 +1,230 @@ +//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic graph +// post order iterator. This should work over any graph type that has a +// GraphTraits specialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POSTORDERITERATOR_H +#define LLVM_ADT_POSTORDERITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +#include + +namespace llvm { + +template // Non-external set +class po_iterator_storage { +public: + SetType Visited; +}; + +template +class po_iterator_storage { +public: + po_iterator_storage(SetType &VSet) : Visited(VSet) {} + po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + +template::NodeType*, 8>, + bool ExtStorage = false, + class GT = GraphTraits > +class po_iterator : public std::iterator, + public po_iterator_storage { + typedef std::iterator super; + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector > VisitStack; + + void traverseChild() { + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + NodeType *BB = *VisitStack.back().second++; + if (this->Visited.insert(BB)) { // If the block is not visited... + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + } + } + } + + inline po_iterator(NodeType *BB) { + this->Visited.insert(BB); + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + inline po_iterator() {} // End is when stack is empty. + + inline po_iterator(NodeType *BB, SetType &S) : + po_iterator_storage(S) { + if (this->Visited.insert(BB)) { + VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + } + + inline po_iterator(SetType &S) : + po_iterator_storage(S) { + } // End is when stack is empty. +public: + typedef typename super::pointer pointer; + typedef po_iterator _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT G) { return _Self(); } + + static inline _Self begin(GraphT G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end (GraphT G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.back().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the BasicBlock, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + VisitStack.pop_back(); + if (!VisitStack.empty()) + traverseChild(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +// Provide global constructors that automatically figure out correct types... +// +template +po_iterator po_begin(T G) { return po_iterator::begin(G); } +template +po_iterator po_end (T G) { return po_iterator::end(G); } + +// Provide global definitions of external postorder iterators... +template::NodeType*> > +struct po_ext_iterator : public po_iterator { + po_ext_iterator(const po_iterator &V) : + po_iterator(V) {} +}; + +template +po_ext_iterator po_ext_begin(T G, SetType &S) { + return po_ext_iterator::begin(G, S); +} + +template +po_ext_iterator po_ext_end(T G, SetType &S) { + return po_ext_iterator::end(G, S); +} + +// Provide global definitions of inverse post order iterators... +template ::NodeType*>, + bool External = false> +struct ipo_iterator : public po_iterator, SetType, External > { + ipo_iterator(const po_iterator, SetType, External> &V) : + po_iterator, SetType, External> (V) {} +}; + +template +ipo_iterator ipo_begin(T G, bool Reverse = false) { + return ipo_iterator::begin(G, Reverse); +} + +template +ipo_iterator ipo_end(T G){ + return ipo_iterator::end(G); +} + +//Provide global definitions of external inverse postorder iterators... +template ::NodeType*> > +struct ipo_ext_iterator : public ipo_iterator { + ipo_ext_iterator(const ipo_iterator &V) : + ipo_iterator(&V) {} + ipo_ext_iterator(const po_iterator, SetType, true> &V) : + ipo_iterator(&V) {} +}; + +template +ipo_ext_iterator ipo_ext_begin(T G, SetType &S) { + return ipo_ext_iterator::begin(G, S); +} + +template +ipo_ext_iterator ipo_ext_end(T G, SetType &S) { + return ipo_ext_iterator::end(G, S); +} + +//===--------------------------------------------------------------------===// +// Reverse Post Order CFG iterator code +//===--------------------------------------------------------------------===// +// +// This is used to visit basic blocks in a method in reverse post order. This +// class is awkward to use because I don't know a good incremental algorithm to +// computer RPO from a graph. Because of this, the construction of the +// ReversePostOrderTraversal object is expensive (it must walk the entire graph +// with a postorder iterator to build the data structures). The moral of this +// story is: Don't create more ReversePostOrderTraversal classes than necessary. +// +// This class should be used like this: +// { +// ReversePostOrderTraversal RPOT(FuncPtr); // Expensive to create +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// } +// + +template > +class ReversePostOrderTraversal { + typedef typename GT::NodeType NodeType; + std::vector Blocks; // Block list in normal PO order + inline void Initialize(NodeType *BB) { + copy(po_begin(BB), po_end(BB), back_inserter(Blocks)); + } +public: + typedef typename std::vector::reverse_iterator rpo_iterator; + + inline ReversePostOrderTraversal(GraphT G) { + Initialize(GT::getEntryNode(G)); + } + + // Because we want a reverse post order, use reverse iterators from the vector + inline rpo_iterator begin() { return Blocks.rbegin(); } + inline rpo_iterator end() { return Blocks.rend(); } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/PriorityQueue.h b/final/include/llvm/ADT/PriorityQueue.h new file mode 100644 index 00000000000..bf8a6870816 --- /dev/null +++ b/final/include/llvm/ADT/PriorityQueue.h @@ -0,0 +1,84 @@ +//===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- 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 PriorityQueue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PRIORITY_QUEUE_H +#define LLVM_ADT_PRIORITY_QUEUE_H + +#include +#include + +namespace llvm { + +/// PriorityQueue - This class behaves like std::priority_queue and +/// provides a few additional convenience functions. +/// +template, + class Compare = std::less > +class PriorityQueue : public std::priority_queue { +public: + explicit PriorityQueue(const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(compare, sequence) + {} + + template + PriorityQueue(Iterator begin, Iterator end, + const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(begin, end, compare, sequence) + {} + + /// erase_one - Erase one element from the queue, regardless of its + /// position. This operation performs a linear search to find an element + /// equal to t, but then uses all logarithmic-time algorithms to do + /// the erase operation. + /// + void erase_one(const T &t) { + // Linear-search to find the element. + typename Sequence::size_type i = + std::find(this->c.begin(), this->c.end(), t) - this->c.begin(); + + // Logarithmic-time heap bubble-up. + while (i != 0) { + typename Sequence::size_type parent = (i - 1) / 2; + this->c[i] = this->c[parent]; + i = parent; + } + + // The element we want to remove is now at the root, so we can use + // priority_queue's plain pop to remove it. + this->pop(); + } + + /// reheapify - If an element in the queue has changed in a way that + /// affects its standing in the comparison function, the queue's + /// internal state becomes invalid. Calling reheapify() resets the + /// queue's state, making it valid again. This operation has time + /// complexity proportional to the number of elements in the queue, + /// so don't plan to use it a lot. + /// + void reheapify() { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } + + /// clear - Erase all elements from the queue. + /// + void clear() { + this->c.clear(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/SCCIterator.h b/final/include/llvm/ADT/SCCIterator.h new file mode 100644 index 00000000000..3e93cfe914f --- /dev/null +++ b/final/include/llvm/ADT/SCCIterator.h @@ -0,0 +1,220 @@ +//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected +// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm. +// +// The SCC iterator has the important property that if a node in SCC S1 has an +// edge to a node in SCC S2, then it visits S1 *after* S2. +// +// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. +// (NOTE: This requires some simple wrappers and is not supported yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCCITERATOR_H +#define LLVM_ADT_SCCITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// scc_iterator - Enumerate the SCCs of a directed graph, in +/// reverse topological order of the SCC DAG. +/// +template > +class scc_iterator + : public std::iterator, ptrdiff_t> { + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef std::vector SccTy; + typedef std::iterator, ptrdiff_t> super; + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + // The visit counters used to detect when a complete SCC is on the stack. + // visitNum is the global counter. + // nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + unsigned visitNum; + DenseMap nodeVisitNumbers; + + // SCCNodeStack - Stack holding nodes of the SCC. + std::vector SCCNodeStack; + + // CurrentSCC - The current SCC, retrieved using operator*(). + SccTy CurrentSCC; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector > VisitStack; + + // MinVisitNumStack - Stack holding the "min" values for each node in the DFS. + // This is used to track the minimum uplink values for all children of + // the corresponding node on the VisitStack. + std::vector MinVisitNumStack; + + // A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeType *N) { + ++visitNum; // Global counter for the visit order + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + MinVisitNumStack.push_back(visitNum); + VisitStack.push_back(std::make_pair(N, GT::child_begin(N))); + //dbgs() << "TarjanSCC: Node " << N << + // " : visitNum = " << visitNum << "\n"; + } + + // The stack-based DFS traversal; defined below. + void DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + // TOS has at least one more child so continue DFS + NodeType *childN = *VisitStack.back().second++; + if (!nodeVisitNumbers.count(childN)) { + // this node has never been seen. + DFSVisitOne(childN); + continue; + } + + unsigned childNum = nodeVisitNumbers[childN]; + if (MinVisitNumStack.back() > childNum) + MinVisitNumStack.back() = childNum; + } + } + + // Compute the next SCC using the DFS traversal. + void GetNextSCC() { + assert(VisitStack.size() == MinVisitNumStack.size()); + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first)); + NodeType *visitingN = VisitStack.back().first; + unsigned minVisitNum = MinVisitNumStack.back(); + VisitStack.pop_back(); + MinVisitNumStack.pop_back(); + if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum) + MinVisitNumStack.back() = minVisitNum; + + //dbgs() << "TarjanSCC: Popped node " << visitingN << + // " : minVisitNum = " << minVisitNum << "; Node visit num = " << + // nodeVisitNumbers[visitingN] << "\n"; + + if (minVisitNum != nodeVisitNumbers[visitingN]) + continue; + + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } + } + + inline scc_iterator(NodeType *entryN) : visitNum(0) { + DFSVisitOne(entryN); + GetNextSCC(); + } + inline scc_iterator() { /* End is when DFS stack is empty */ } + +public: + typedef scc_iterator _Self; + + // Provide static "constructors"... + static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));} + static inline _Self end (const GraphT &G) { return _Self(); } + + // Direct loop termination test: I.isAtEnd() is more efficient than I == end() + inline bool isAtEnd() const { + assert(!CurrentSCC.empty() || VisitStack.empty()); + return CurrentSCC.empty(); + } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + // Iterator traversal: forward iteration only + inline _Self& operator++() { // Preincrement + GetNextSCC(); + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a reference to the current SCC + inline const SccTy &operator*() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + inline SccTy &operator*() { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + + // hasLoop() -- Test if the current SCC has a loop. If it has more than one + // node, this is trivially true. If not, it may still contain a loop if the + // node has an edge back to itself. + bool hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) return true; + NodeType *N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI) + if (*CI == N) + return true; + return false; + } + + /// ReplaceNode - This informs the scc_iterator that the specified Old node + /// has been deleted, and New is to be used in its place. + void ReplaceNode(NodeType *Old, NodeType *New) { + assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?"); + nodeVisitNumbers[New] = nodeVisitNumbers[Old]; + nodeVisitNumbers.erase(Old); + } +}; + + +// Global constructor for the SCC iterator. +template +scc_iterator scc_begin(const T &G) { + return scc_iterator::begin(G); +} + +template +scc_iterator scc_end(const T &G) { + return scc_iterator::end(G); +} + +template +scc_iterator > scc_begin(const Inverse &G) { + return scc_iterator >::begin(G); +} + +template +scc_iterator > scc_end(const Inverse &G) { + return scc_iterator >::end(G); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/STLExtras.h b/final/include/llvm/ADT/STLExtras.h new file mode 100644 index 00000000000..0b0346be2cc --- /dev/null +++ b/final/include/llvm/ADT/STLExtras.h @@ -0,0 +1,306 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include // for std::size_t +#include // for qsort +#include +#include +#include // for std::pair + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +template +struct less_ptr : public std::binary_function { + bool operator()(const Ty* left, const Ty* right) const { + return *left < *right; + } +}; + +template +struct greater_ptr : public std::binary_function { + bool operator()(const Ty* left, const Ty* right) const { + return *right < *left; + } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter); +// +template +static inline void deleter(T *Ptr) { + delete Ptr; +} + + + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be dereferenced whenever operator* is invoked on the iterator. +// +template +class mapped_iterator { + RootIt current; + UnaryFunc Fn; +public: + typedef typename std::iterator_traits::iterator_category + iterator_category; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef typename UnaryFunc::result_type value_type; + + typedef void pointer; + //typedef typename UnaryFunc::result_type *pointer; + typedef void reference; // Can't modify value returned by fn + + typedef RootIt iterator_type; + typedef mapped_iterator _Self; + + inline const RootIt &getCurrent() const { return current; } + inline const UnaryFunc &getFunc() const { return Fn; } + + inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) + : current(I), Fn(F) {} + inline mapped_iterator(const mapped_iterator &It) + : current(It.current), Fn(It.Fn) {} + + inline value_type operator*() const { // All this work to do this + return Fn(*current); // little change + } + + _Self& operator++() { ++current; return *this; } + _Self& operator--() { --current; return *this; } + _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } + _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } + _Self operator+ (difference_type n) const { + return _Self(current + n, Fn); + } + _Self& operator+= (difference_type n) { current += n; return *this; } + _Self operator- (difference_type n) const { + return _Self(current - n, Fn); + } + _Self& operator-= (difference_type n) { current -= n; return *this; } + reference operator[](difference_type n) const { return *(*this + n); } + + inline bool operator!=(const _Self &X) const { return !operator==(X); } + inline bool operator==(const _Self &X) const { return current == X.current; } + inline bool operator< (const _Self &X) const { return current < X.current; } + + inline difference_type operator-(const _Self &X) const { + return current - X.current; + } +}; + +template +inline mapped_iterator<_Iterator, Func> +operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, + const mapped_iterator<_Iterator, Func>& X) { + return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); +} + + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +// +template +inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { + return mapped_iterator(I, F); +} + + +// next/prior - These functions unlike std::advance do not modify the +// passed iterator but return a copy. +// +// next(myIt) returns copy of myIt incremented once +// next(myIt, n) returns copy of myIt incremented n times +// prior(myIt) returns copy of myIt decremented once +// prior(myIt, n) returns copy of myIt decremented n times + +template +inline ItTy next(ItTy it, Dist n) +{ + std::advance(it, n); + return it; +} + +template +inline ItTy next(ItTy it) +{ + return ++it; +} + +template +inline ItTy prior(ItTy it, Dist n) +{ + std::advance(it, -n); + return it; +} + +template +inline ItTy prior(ItTy it) +{ + return --it; +} + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +// tie - this function ties two objects and returns a temporary object +// that is assignable from a std::pair. This can be used to make code +// more readable when using values returned from functions bundled in +// a std::pair. Since an example is worth 1000 words: +// +// typedef std::map Int2IntMap; +// +// Int2IntMap myMap; +// Int2IntMap::iterator where; +// bool inserted; +// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); +// +// if (inserted) +// // do stuff +// else +// // do other stuff + +namespace +{ + template + struct tier { + typedef T1 &first_type; + typedef T2 &second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair& p) { + first = p.first; + second = p.second; + return *this; + } + }; +} + +template +inline tier tie(T1& f, T2& s) { + return tier(f, s); +} + +//===----------------------------------------------------------------------===// +// Extra additions for arrays +//===----------------------------------------------------------------------===// + +/// Find where an array ends (for ending iterators) +/// This returns a pointer to the byte immediately +/// after the end of an array. +template +inline T *array_endof(T (&x)[N]) { + return x+N; +} + +/// Find the length of an array. +template +inline size_t array_lengthof(T (&)[N]) { + return N; +} + +/// array_pod_sort_comparator - This is helper function for array_pod_sort, +/// which just uses operator< on T. +template +static inline int array_pod_sort_comparator(const void *P1, const void *P2) { + if (*reinterpret_cast(P1) < *reinterpret_cast(P2)) + return -1; + if (*reinterpret_cast(P2) < *reinterpret_cast(P1)) + return 1; + return 0; +} + +/// get_array_pad_sort_comparator - This is an internal helper function used to +/// get type deduction of T right. +template +static int (*get_array_pad_sort_comparator(const T &)) + (const void*, const void*) { + return array_pod_sort_comparator; +} + + +/// array_pod_sort - This sorts an array with the specified start and end +/// extent. This is just like std::sort, except that it calls qsort instead of +/// using an inlined template. qsort is slightly slower than std::sort, but +/// most sorts are not performance critical in LLVM and std::sort has to be +/// template instantiated for each type, leading to significant measured code +/// bloat. This function should generally be used instead of std::sort where +/// possible. +/// +/// This function assumes that you have simple POD-like types that can be +/// compared with operator< and can be moved with memcpy. If this isn't true, +/// you should use std::sort. +/// +/// NOTE: If qsort_r were portable, we could allow a custom comparator and +/// default to std::less. +template +static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { + // Don't dereference start iterator of empty sequence. + if (Start == End) return; + qsort(&*Start, End-Start, sizeof(*Start), + get_array_pad_sort_comparator(*Start)); +} + +template +static inline void array_pod_sort(IteratorTy Start, IteratorTy End, + int (*Compare)(const void*, const void*)) { + // Don't dereference start iterator of empty sequence. + if (Start == End) return; + qsort(&*Start, End-Start, sizeof(*Start), Compare); +} + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +/// For a container of pointers, deletes the pointers and then clears the +/// container. +template +void DeleteContainerPointers(Container &C) { + for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) + delete *I; + C.clear(); +} + +/// In a container of pairs (usually a map) whose second element is a pointer, +/// deletes the second elements and then clears the container. +template +void DeleteContainerSeconds(Container &C) { + for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I) + delete I->second; + C.clear(); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/ScopedHashTable.h b/final/include/llvm/ADT/ScopedHashTable.h new file mode 100644 index 00000000000..a6803ee0edd --- /dev/null +++ b/final/include/llvm/ADT/ScopedHashTable.h @@ -0,0 +1,256 @@ +//===- ScopedHashTable.h - A simple scoped hash table ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an efficient scoped hash table, which is useful for +// things like dominator-based optimizations. This allows clients to do things +// like this: +// +// ScopedHashTable HT; +// { +// ScopedHashTableScope Scope1(HT); +// HT.insert(0, 0); +// HT.insert(1, 1); +// { +// ScopedHashTableScope Scope2(HT); +// HT.insert(0, 42); +// } +// } +// +// Looking up the value for "0" in the Scope2 block will return 42. Looking +// up the value for 0 before 42 is inserted or after Scope2 is popped will +// return 0. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPEDHASHTABLE_H +#define LLVM_ADT_SCOPEDHASHTABLE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +template , + typename AllocatorTy = MallocAllocator> +class ScopedHashTable; + +template +class ScopedHashTableVal { + ScopedHashTableVal *NextInScope; + ScopedHashTableVal *NextForKey; + K Key; + V Val; + ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {} +public: + + const K &getKey() const { return Key; } + const V &getValue() const { return Val; } + V &getValue() { return Val; } + + ScopedHashTableVal *getNextForKey() { return NextForKey; } + const ScopedHashTableVal *getNextForKey() const { return NextForKey; } + ScopedHashTableVal *getNextInScope() { return NextInScope; } + + template + static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, + const K &key, const V &val, + AllocatorTy &Allocator) { + ScopedHashTableVal *New = Allocator.template Allocate(); + // Set up the value. + new (New) ScopedHashTableVal(key, val); + New->NextInScope = nextInScope; + New->NextForKey = nextForKey; + return New; + } + + template + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~ScopedHashTableVal(); + Allocator.Deallocate(this); + } +}; + +template , + typename AllocatorTy = MallocAllocator> +class ScopedHashTableScope { + /// HT - The hashtable that we are active for. + ScopedHashTable &HT; + + /// PrevScope - This is the scope that we are shadowing in HT. + ScopedHashTableScope *PrevScope; + + /// LastValInScope - This is the last value that was inserted for this scope + /// or null if none have been inserted yet. + ScopedHashTableVal *LastValInScope; + void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT + ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT +public: + ScopedHashTableScope(ScopedHashTable &HT); + ~ScopedHashTableScope(); + + ScopedHashTableScope *getParentScope() { return PrevScope; } + const ScopedHashTableScope *getParentScope() const { return PrevScope; } + +private: + friend class ScopedHashTable; + ScopedHashTableVal *getLastValInScope() { + return LastValInScope; + } + void setLastValInScope(ScopedHashTableVal *Val) { + LastValInScope = Val; + } +}; + + +template > +class ScopedHashTableIterator { + ScopedHashTableVal *Node; +public: + ScopedHashTableIterator(ScopedHashTableVal *node) : Node(node) {} + + V &operator*() const { + assert(Node && "Dereference end()"); + return Node->getValue(); + } + V *operator->() const { + return &Node->getValue(); + } + + bool operator==(const ScopedHashTableIterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const ScopedHashTableIterator &RHS) const { + return Node != RHS.Node; + } + + inline ScopedHashTableIterator& operator++() { // Preincrement + assert(Node && "incrementing past end()"); + Node = Node->getNextForKey(); + return *this; + } + ScopedHashTableIterator operator++(int) { // Postincrement + ScopedHashTableIterator tmp = *this; ++*this; return tmp; + } +}; + + +template +class ScopedHashTable { +public: + /// ScopeTy - This is a helpful typedef that allows clients to get easy access + /// to the name of the scope for this hash table. + typedef ScopedHashTableScope ScopeTy; +private: + typedef ScopedHashTableVal ValTy; + DenseMap TopLevelMap; + ScopeTy *CurScope; + + AllocatorTy Allocator; + + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED + void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED + friend class ScopedHashTableScope; +public: + ScopedHashTable() : CurScope(0) {} + ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} + ~ScopedHashTable() { + assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); + } + + + /// Access to the allocator. + typedef typename ReferenceAdder::result AllocatorRefTy; + typedef typename ReferenceAdder::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } + + bool count(const K &Key) const { + return TopLevelMap.count(Key); + } + + V lookup(const K &Key) { + typename DenseMap::iterator I = TopLevelMap.find(Key); + if (I != TopLevelMap.end()) + return I->second->getValue(); + + return V(); + } + + void insert(const K &Key, const V &Val) { + insertIntoScope(CurScope, Key, Val); + } + + typedef ScopedHashTableIterator iterator; + + iterator end() { return iterator(0); } + + iterator begin(const K &Key) { + typename DenseMap::iterator I = + TopLevelMap.find(Key); + if (I == TopLevelMap.end()) return end(); + return iterator(I->second); + } + + ScopeTy *getCurScope() { return CurScope; } + const ScopeTy *getCurScope() const { return CurScope; } + + /// insertIntoScope - This inserts the specified key/value at the specified + /// (possibly not the current) scope. While it is ok to insert into a scope + /// that isn't the current one, it isn't ok to insert *underneath* an existing + /// value of the specified key. + void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) { + assert(S && "No scope active!"); + ScopedHashTableVal *&KeyEntry = TopLevelMap[Key]; + KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val, + Allocator); + S->setLastValInScope(KeyEntry); + } +}; + +/// ScopedHashTableScope ctor - Install this as the current scope for the hash +/// table. +template +ScopedHashTableScope:: + ScopedHashTableScope(ScopedHashTable &ht) : HT(ht) { + PrevScope = HT.CurScope; + HT.CurScope = this; + LastValInScope = 0; +} + +template +ScopedHashTableScope::~ScopedHashTableScope() { + assert(HT.CurScope == this && "Scope imbalance!"); + HT.CurScope = PrevScope; + + // Pop and delete all values corresponding to this scope. + while (ScopedHashTableVal *ThisEntry = LastValInScope) { + // Pop this value out of the TopLevelMap. + if (ThisEntry->getNextForKey() == 0) { + assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && + "Scope imbalance!"); + HT.TopLevelMap.erase(ThisEntry->getKey()); + } else { + ScopedHashTableVal *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + assert(KeyEntry == ThisEntry && "Scope imbalance!"); + KeyEntry = ThisEntry->getNextForKey(); + } + + // Pop this value out of the scope. + LastValInScope = ThisEntry->getNextInScope(); + + // Delete this entry. + ThisEntry->Destroy(HT.getAllocator()); + } +} + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/SetOperations.h b/final/include/llvm/ADT/SetOperations.h new file mode 100644 index 00000000000..71f5db380f6 --- /dev/null +++ b/final/include/llvm/ADT/SetOperations.h @@ -0,0 +1,71 @@ +//===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- 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 generic set operations that may be used on set's of +// different types, and different element types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETOPERATIONS_H +#define LLVM_ADT_SETOPERATIONS_H + +namespace llvm { + +/// set_union(A, B) - Compute A := A u B, return whether A changed. +/// +template +bool set_union(S1Ty &S1, const S2Ty &S2) { + bool Changed = false; + + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + if (S1.insert(*SI).second) + Changed = true; + + return Changed; +} + +/// set_intersect(A, B) - Compute A := A ^ B +/// Identical to set_intersection, except that it works on set<>'s and +/// is nicer to use. Functionally, this iterates through S1, removing +/// elements that are not contained in S2. +/// +template +void set_intersect(S1Ty &S1, const S2Ty &S2) { + for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) { + const typename S1Ty::key_type &E = *I; + ++I; + if (!S2.count(E)) S1.erase(E); // Erase element if not in S2 + } +} + +/// set_difference(A, B) - Return A - B +/// +template +S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) { + S1Ty Result; + for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); + SI != SE; ++SI) + if (!S2.count(*SI)) // if the element is not in set2 + Result.insert(*SI); + return Result; +} + +/// set_subtract(A, B) - Compute A := A - B +/// +template +void set_subtract(S1Ty &S1, const S2Ty &S2) { + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + S1.erase(*SI); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/SetVector.h b/final/include/llvm/ADT/SetVector.h new file mode 100644 index 00000000000..abe20676d54 --- /dev/null +++ b/final/include/llvm/ADT/SetVector.h @@ -0,0 +1,178 @@ +//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a set that has insertion order iteration +// characteristics. This is useful for keeping a set of things that need to be +// visited later but in a deterministic order (insertion order). The interface +// is purposefully minimal. +// +// This file defines SetVector and SmallSetVector, which performs no allocations +// if the SetVector has less than a certain number of elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETVECTOR_H +#define LLVM_ADT_SETVECTOR_H + +#include "llvm/ADT/SmallSet.h" +#include +#include +#include + +namespace llvm { + +/// This adapter class provides a way to keep a set of things that also has the +/// property of a deterministic iteration order. The order of iteration is the +/// order of insertion. +/// @brief A vector that has set insertion semantics. +template , + typename Set = SmallSet > +class SetVector { +public: + typedef T value_type; + typedef T key_type; + typedef T& reference; + typedef const T& const_reference; + typedef Set set_type; + typedef Vector vector_type; + typedef typename vector_type::const_iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::size_type size_type; + + /// @brief Construct an empty SetVector + SetVector() {} + + /// @brief Initialize a SetVector with a range of elements + template + SetVector(It Start, It End) { + insert(Start, End); + } + + /// @brief Determine if the SetVector is empty or not. + bool empty() const { + return vector_.empty(); + } + + /// @brief Determine the number of elements in the SetVector. + size_type size() const { + return vector_.size(); + } + + /// @brief Get an iterator to the beginning of the SetVector. + iterator begin() { + return vector_.begin(); + } + + /// @brief Get a const_iterator to the beginning of the SetVector. + const_iterator begin() const { + return vector_.begin(); + } + + /// @brief Get an iterator to the end of the SetVector. + iterator end() { + return vector_.end(); + } + + /// @brief Get a const_iterator to the end of the SetVector. + const_iterator end() const { + return vector_.end(); + } + + /// @brief Return the last element of the SetVector. + const T &back() const { + assert(!empty() && "Cannot call back() on empty SetVector!"); + return vector_.back(); + } + + /// @brief Index into the SetVector. + const_reference operator[](size_type n) const { + assert(n < vector_.size() && "SetVector access out of range!"); + return vector_[n]; + } + + /// @returns true iff the element was inserted into the SetVector. + /// @brief Insert a new element into the SetVector. + bool insert(const value_type &X) { + bool result = set_.insert(X); + if (result) + vector_.push_back(X); + return result; + } + + /// @brief Insert a range of elements into the SetVector. + template + void insert(It Start, It End) { + for (; Start != End; ++Start) + if (set_.insert(*Start)) + vector_.push_back(*Start); + } + + /// @brief Remove an item from the set vector. + bool remove(const value_type& X) { + if (set_.erase(X)) { + typename vector_type::iterator I = + std::find(vector_.begin(), vector_.end(), X); + assert(I != vector_.end() && "Corrupted SetVector instances!"); + vector_.erase(I); + return true; + } + return false; + } + + + /// @returns 0 if the element is not in the SetVector, 1 if it is. + /// @brief Count the number of elements of a given key in the SetVector. + size_type count(const key_type &key) const { + return set_.count(key); + } + + /// @brief Completely clear the SetVector + void clear() { + set_.clear(); + vector_.clear(); + } + + /// @brief Remove the last element of the SetVector. + void pop_back() { + assert(!empty() && "Cannot remove an element from an empty SetVector!"); + set_.erase(back()); + vector_.pop_back(); + } + + bool operator==(const SetVector &that) const { + return vector_ == that.vector_; + } + + bool operator!=(const SetVector &that) const { + return vector_ != that.vector_; + } + +private: + set_type set_; ///< The set. + vector_type vector_; ///< The vector. +}; + +/// SmallSetVector - A SetVector that performs no allocations if smaller than +/// a certain size. +template +class SmallSetVector : public SetVector, SmallSet > { +public: + SmallSetVector() {} + + /// @brief Initialize a SmallSetVector with a range of elements + template + SmallSetVector(It Start, It End) { + this->insert(Start, End); + } +}; + +} // End llvm namespace + +// vim: sw=2 ai +#endif diff --git a/final/include/llvm/ADT/SmallBitVector.h b/final/include/llvm/ADT/SmallBitVector.h new file mode 100644 index 00000000000..b15b3ee0418 --- /dev/null +++ b/final/include/llvm/ADT/SmallBitVector.h @@ -0,0 +1,461 @@ +//===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallBitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLBITVECTOR_H +#define LLVM_ADT_SMALLBITVECTOR_H + +#include "llvm/ADT/BitVector.h" +#include "llvm/Support/MathExtras.h" +#include + +namespace llvm { + +/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array), +/// optimized for the case when the array is small. It contains one +/// pointer-sized field, which is directly used as a plain collection of bits +/// when possible, or as a pointer to a larger heap-allocated array when +/// necessary. This allows normal "small" cases to be fast without losing +/// generality for large inputs. +/// +class SmallBitVector { + // TODO: In "large" mode, a pointer to a BitVector is used, leading to an + // unnecessary level of indirection. It would be more efficient to use a + // pointer to memory containing size, allocation size, and the array of bits. + uintptr_t X; + + enum { + // The number of bits in this class. + NumBaseBits = sizeof(uintptr_t) * CHAR_BIT, + + // One bit is used to discriminate between small and large mode. The + // remaining bits are used for the small-mode representation. + SmallNumRawBits = NumBaseBits - 1, + + // A few more bits are used to store the size of the bit set in small mode. + // Theoretically this is a ceil-log2. These bits are encoded in the most + // significant bits of the raw bits. + SmallNumSizeBits = (NumBaseBits == 32 ? 5 : + NumBaseBits == 64 ? 6 : + SmallNumRawBits), + + // The remaining bits are used to store the actual set in small mode. + SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits + }; + +public: + // Encapsulation of a single bit. + class reference { + SmallBitVector &TheVector; + unsigned BitPos; + + public: + reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {} + + reference& operator=(reference t) { + *this = bool(t); + return *this; + } + + reference& operator=(bool t) { + if (t) + TheVector.set(BitPos); + else + TheVector.reset(BitPos); + return *this; + } + + operator bool() const { + return const_cast(TheVector).operator[](BitPos); + } + }; + +private: + bool isSmall() const { + return X & uintptr_t(1); + } + + BitVector *getPointer() const { + assert(!isSmall()); + return reinterpret_cast(X); + } + + void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) { + X = 1; + setSmallSize(NewSize); + setSmallBits(NewSmallBits); + } + + void switchToLarge(BitVector *BV) { + X = reinterpret_cast(BV); + assert(!isSmall() && "Tried to use an unaligned pointer"); + } + + // Return all the bits used for the "small" representation; this includes + // bits for the size as well as the element bits. + uintptr_t getSmallRawBits() const { + assert(isSmall()); + return X >> 1; + } + + void setSmallRawBits(uintptr_t NewRawBits) { + assert(isSmall()); + X = (NewRawBits << 1) | uintptr_t(1); + } + + // Return the size. + size_t getSmallSize() const { + return getSmallRawBits() >> SmallNumDataBits; + } + + void setSmallSize(size_t Size) { + setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); + } + + // Return the element bits. + uintptr_t getSmallBits() const { + return getSmallRawBits() & ~(~uintptr_t(0) << getSmallSize()); + } + + void setSmallBits(uintptr_t NewBits) { + setSmallRawBits((NewBits & ~(~uintptr_t(0) << getSmallSize())) | + (getSmallSize() << SmallNumDataBits)); + } + +public: + /// SmallBitVector default ctor - Creates an empty bitvector. + SmallBitVector() : X(1) {} + + /// SmallBitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit SmallBitVector(unsigned s, bool t = false) { + if (s <= SmallNumDataBits) + switchToSmall(t ? ~uintptr_t(0) : 0, s); + else + switchToLarge(new BitVector(s, t)); + } + + /// SmallBitVector copy ctor. + SmallBitVector(const SmallBitVector &RHS) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.getPointer())); + } + + ~SmallBitVector() { + if (!isSmall()) + delete getPointer(); + } + + /// empty - Tests whether there are no bits in this bitvector. + bool empty() const { + return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); + } + + /// size - Returns the number of bits in this bitvector. + size_t size() const { + return isSmall() ? getSmallSize() : getPointer()->size(); + } + + /// count - Returns the number of bits which are set. + unsigned count() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountPopulation_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountPopulation_64(Bits); + assert(0 && "Unsupported!"); + } + return getPointer()->count(); + } + + /// any - Returns true if any bit is set. + bool any() const { + if (isSmall()) + return getSmallBits() != 0; + return getPointer()->any(); + } + + /// all - Returns true if all bits are set. + bool all() const { + if (isSmall()) + return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1; + return getPointer()->all(); + } + + /// none - Returns true if none of the bits are set. + bool none() const { + if (isSmall()) + return getSmallBits() == 0; + return getPointer()->none(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + if (Bits == 0) + return -1; + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountTrailingZeros_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountTrailingZeros_64(Bits); + assert(0 && "Unsupported!"); + } + return getPointer()->find_first(); + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + if (isSmall()) { + uintptr_t Bits = getSmallBits(); + // Mask off previous bits. + Bits &= ~uintptr_t(0) << (Prev + 1); + if (Bits == 0 || Prev + 1 >= getSmallSize()) + return -1; + if (sizeof(uintptr_t) * CHAR_BIT == 32) + return CountTrailingZeros_32(Bits); + if (sizeof(uintptr_t) * CHAR_BIT == 64) + return CountTrailingZeros_64(Bits); + assert(0 && "Unsupported!"); + } + return getPointer()->find_next(Prev); + } + + /// clear - Clear all bits. + void clear() { + if (!isSmall()) + delete getPointer(); + switchToSmall(0, 0); + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (!isSmall()) { + getPointer()->resize(N, t); + } else if (SmallNumDataBits >= N) { + uintptr_t NewBits = t ? ~uintptr_t(0) << getSmallSize() : 0; + setSmallSize(N); + setSmallBits(NewBits | getSmallBits()); + } else { + BitVector *BV = new BitVector(N, t); + uintptr_t OldBits = getSmallBits(); + for (size_t i = 0, e = getSmallSize(); i != e; ++i) + (*BV)[i] = (OldBits >> i) & 1; + switchToLarge(BV); + } + } + + void reserve(unsigned N) { + if (isSmall()) { + if (N > SmallNumDataBits) { + uintptr_t OldBits = getSmallRawBits(); + size_t SmallSize = getSmallSize(); + BitVector *BV = new BitVector(SmallSize); + for (size_t i = 0; i < SmallSize; ++i) + if ((OldBits >> i) & 1) + BV->set(i); + BV->reserve(N); + switchToLarge(BV); + } + } else { + getPointer()->reserve(N); + } + } + + // Set, reset, flip + SmallBitVector &set() { + if (isSmall()) + setSmallBits(~uintptr_t(0)); + else + getPointer()->set(); + return *this; + } + + SmallBitVector &set(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + else + getPointer()->set(Idx); + return *this; + } + + SmallBitVector &reset() { + if (isSmall()) + setSmallBits(0); + else + getPointer()->reset(); + return *this; + } + + SmallBitVector &reset(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx)); + else + getPointer()->reset(Idx); + return *this; + } + + SmallBitVector &flip() { + if (isSmall()) + setSmallBits(~getSmallBits()); + else + getPointer()->flip(); + return *this; + } + + SmallBitVector &flip(unsigned Idx) { + if (isSmall()) + setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx)); + else + getPointer()->flip(Idx); + return *this; + } + + // No argument flip. + SmallBitVector operator~() const { + return SmallBitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + assert(Idx < size() && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert(Idx < size() && "Out-of-bounds Bit access."); + if (isSmall()) + return ((getSmallBits() >> Idx) & 1) != 0; + return getPointer()->operator[](Idx); + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const SmallBitVector &RHS) const { + if (size() != RHS.size()) + return false; + if (isSmall()) + return getSmallBits() == RHS.getSmallBits(); + else + return *getPointer() == *RHS.getPointer(); + } + + bool operator!=(const SmallBitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + SmallBitVector &operator&=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall()) + setSmallBits(getSmallBits() & RHS.getSmallBits()); + else if (!RHS.isSmall()) + getPointer()->operator&=(*RHS.getPointer()); + else { + SmallBitVector Copy = RHS; + Copy.resize(size()); + getPointer()->operator&=(*Copy.getPointer()); + } + return *this; + } + + SmallBitVector &operator|=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall()) + setSmallBits(getSmallBits() | RHS.getSmallBits()); + else if (!RHS.isSmall()) + getPointer()->operator|=(*RHS.getPointer()); + else { + SmallBitVector Copy = RHS; + Copy.resize(size()); + getPointer()->operator|=(*Copy.getPointer()); + } + return *this; + } + + SmallBitVector &operator^=(const SmallBitVector &RHS) { + resize(std::max(size(), RHS.size())); + if (isSmall()) + setSmallBits(getSmallBits() ^ RHS.getSmallBits()); + else if (!RHS.isSmall()) + getPointer()->operator^=(*RHS.getPointer()); + else { + SmallBitVector Copy = RHS; + Copy.resize(size()); + getPointer()->operator^=(*Copy.getPointer()); + } + return *this; + } + + // Assignment operator. + const SmallBitVector &operator=(const SmallBitVector &RHS) { + if (isSmall()) { + if (RHS.isSmall()) + X = RHS.X; + else + switchToLarge(new BitVector(*RHS.getPointer())); + } else { + if (!RHS.isSmall()) + *getPointer() = *RHS.getPointer(); + else { + delete getPointer(); + X = RHS.X; + } + } + return *this; + } + + void swap(SmallBitVector &RHS) { + std::swap(X, RHS.X); + } +}; + +inline SmallBitVector +operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline SmallBitVector +operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline SmallBitVector +operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { + SmallBitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of BitVector swap. + inline void + swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/final/include/llvm/ADT/SmallPtrSet.h b/final/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 00000000000..ff32ba87a26 --- /dev/null +++ b/final/include/llvm/ADT/SmallPtrSet.h @@ -0,0 +1,294 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- 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 SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImpl for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include +#include +#include +#include +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" + +namespace llvm { + +class SmallPtrSetIteratorImpl; + +/// SmallPtrSetImpl - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImpl { + friend class SmallPtrSetIteratorImpl; +protected: + /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. + const void **SmallArray; + /// CurArray - This is the current set of buckets. If equal to SmallArray, + /// then the set is in 'small mode'. + const void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + /// Note that CurArray points to an array that has CurArraySize+1 elements in + /// it, so that the end iterator actually points to valid memory. + unsigned CurArraySize; + + // If small, this is # elts allocated consecutively + unsigned NumElements; + unsigned NumTombstones; + + // Helper to copy construct a SmallPtrSet. + SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that); + explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) : + SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { + assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && + "Initial size must be a power of two!"); + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[SmallSize] = 0; + clear(); + } + ~SmallPtrSetImpl(); + +public: + bool empty() const { return size() == 0; } + unsigned size() const { return NumElements; } + + void clear() { + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) + return shrink_and_clear(); + + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize*sizeof(void*)); + NumElements = 0; + NumTombstones = 0; + } + +protected: + static void *getTombstoneMarker() { return reinterpret_cast(-2); } + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + return reinterpret_cast(-1); + } + + /// insert_imp - This returns true if the pointer was new to the set, false if + /// it was already in the set. This is hidden from the client so that the + /// derived class can check that the right type of pointer is passed in. + bool insert_imp(const void * Ptr); + + /// erase_imp - If the set contains the specified pointer, remove it and + /// return true, otherwise return false. This is hidden from the client so + /// that the derived class can check that the right type of pointer is passed + /// in. + bool erase_imp(const void * Ptr); + + bool count_imp(const void * Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (const void *const *APtr = SmallArray, + *const *E = SmallArray+NumElements; APtr != E; ++APtr) + if (*APtr == Ptr) + return true; + return false; + } + + // Big set case. + return *FindBucketFor(Ptr) == Ptr; + } + +private: + bool isSmall() const { return CurArray == SmallArray; } + + unsigned Hash(const void *Ptr) const { + return static_cast(((uintptr_t)Ptr >> 4) & (CurArraySize-1)); + } + const void * const *FindBucketFor(const void *Ptr) const; + void shrink_and_clear(); + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(); + + void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. +protected: + void CopyFrom(const SmallPtrSetImpl &RHS); +}; + +/// SmallPtrSetIteratorImpl - This is the common base class shared between all +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + const void *const *Bucket; +public: + explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) { + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + while (*Bucket == SmallPtrSetImpl::getEmptyMarker() || + *Bucket == SmallPtrSetImpl::getTombstoneMarker()) + ++Bucket; + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { + typedef PointerLikeTypeTraits PtrTraits; + +public: + typedef PtrTy value_type; + typedef PtrTy reference; + typedef PtrTy pointer; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + explicit SmallPtrSetIterator(const void *const *BP) + : SmallPtrSetIteratorImpl(BP) {} + + // Most methods provided by baseclass. + + const PtrTy operator*() const { + return PtrTraits::getFromVoidPointer(const_cast(*Bucket)); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; ++*this; return tmp; + } +}; + +/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two (which means N itself if N is already a power of two). +template +struct RoundUpToPowerOfTwo; + +/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a +/// helper template used to implement RoundUpToPowerOfTwo. +template +struct RoundUpToPowerOfTwoH { + enum { Val = N }; +}; +template +struct RoundUpToPowerOfTwoH { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template +struct RoundUpToPowerOfTwo { + enum { Val = RoundUpToPowerOfTwoH::Val }; +}; + + +/// SmallPtrSet - This class implements a set which is optimized for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImpl for details of the algorithm. +template +class SmallPtrSet : public SmallPtrSetImpl { + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = RoundUpToPowerOfTwo::Val }; + /// SmallStorage - Fixed size storage used in 'small mode'. The extra element + /// ensures that the end iterator actually points to valid memory. + const void *SmallStorage[SmallSizePowTwo+1]; + typedef PointerLikeTypeTraits PtrTraits; +public: + SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {} + SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {} + + template + SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) { + insert(I, E); + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(PtrType Ptr) { + return insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(PtrType Ptr) { + return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// count - Return true if the specified pointer is in the set. + bool count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + template + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + typedef SmallPtrSetIterator iterator; + typedef SmallPtrSetIterator const_iterator; + inline iterator begin() const { + return iterator(CurArray); + } + inline iterator end() const { + return iterator(CurArray+CurArraySize); + } + + // Allow assignment from any smallptrset with the same element type even if it + // doesn't have the same smallsize. + const SmallPtrSet& + operator=(const SmallPtrSet &RHS) { + CopyFrom(RHS); + return *this; + } + +}; + +} + +#endif diff --git a/final/include/llvm/ADT/SmallSet.h b/final/include/llvm/ADT/SmallSet.h new file mode 100644 index 00000000000..d03f1bef15b --- /dev/null +++ b/final/include/llvm/ADT/SmallSet.h @@ -0,0 +1,118 @@ +//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- 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 SmallSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSET_H +#define LLVM_ADT_SMALLSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include + +namespace llvm { + +/// SmallSet - This maintains a set of unique values, optimizing for the case +/// when the set is small (less than N). In this case, the set can be +/// maintained with no mallocs. If the set gets large, we expand to using an +/// std::set to maintain reasonable lookup times. +/// +/// Note that this set does not provide a way to iterate over members in the +/// set. +template +class SmallSet { + /// Use a SmallVector to hold the elements here (even though it will never + /// reach its 'large' stage) to avoid calling the default ctors of elements + /// we will never use. + SmallVector Vector; + std::set Set; + typedef typename SmallVector::const_iterator VIterator; + typedef typename SmallVector::iterator mutable_iterator; +public: + SmallSet() {} + + bool empty() const { return Vector.empty() && Set.empty(); } + unsigned size() const { + return isSmall() ? Vector.size() : Set.size(); + } + + /// count - Return true if the element is in the set. + bool count(const T &V) const { + if (isSmall()) { + // Since the collection is small, just do a linear search. + return vfind(V) != Vector.end(); + } else { + return Set.count(V); + } + } + + /// insert - Insert an element into the set if it isn't already there. + bool insert(const T &V) { + if (!isSmall()) + return Set.insert(V).second; + + VIterator I = vfind(V); + if (I != Vector.end()) // Don't reinsert if it already exists. + return false; + if (Vector.size() < N) { + Vector.push_back(V); + return true; + } + + // Otherwise, grow from vector to set. + while (!Vector.empty()) { + Set.insert(Vector.back()); + Vector.pop_back(); + } + Set.insert(V); + return true; + } + + template + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const T &V) { + if (!isSmall()) + return Set.erase(V); + for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) { + Vector.erase(I); + return true; + } + return false; + } + + void clear() { + Vector.clear(); + Set.clear(); + } +private: + bool isSmall() const { return Set.empty(); } + + VIterator vfind(const T &V) const { + for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) + return I; + return Vector.end(); + } +}; + +/// If this set is of pointer values, transparently switch over to using +/// SmallPtrSet for performance. +template +class SmallSet : public SmallPtrSet {}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/SmallString.h b/final/include/llvm/ADT/SmallString.h new file mode 100644 index 00000000000..da264164821 --- /dev/null +++ b/final/include/llvm/ADT/SmallString.h @@ -0,0 +1,72 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- 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 SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template +class SmallString : public SmallVector { +public: + // Default ctor - Initialize to empty. + SmallString() {} + + // Initialize from a StringRef. + SmallString(StringRef S) : SmallVector(S.begin(), S.end()) {} + + // Initialize with a range. + template + SmallString(ItTy S, ItTy E) : SmallVector(S, E) {} + + // Copy ctor. + SmallString(const SmallString &RHS) : SmallVector(RHS) {} + + + // Extra methods. + StringRef str() const { return StringRef(this->begin(), this->size()); } + + // TODO: Make this const, if it's safe... + const char* c_str() { + this->push_back(0); + this->pop_back(); + return this->data(); + } + + // Implicit conversion to StringRef. + operator StringRef() const { return str(); } + + // Extra operators. + const SmallString &operator=(StringRef RHS) { + this->clear(); + return *this += RHS; + } + + SmallString &operator+=(StringRef RHS) { + this->append(RHS.begin(), RHS.end()); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } +}; + +} + +#endif diff --git a/final/include/llvm/ADT/SmallVector.h b/final/include/llvm/ADT/SmallVector.h new file mode 100644 index 00000000000..8b0a13d6ed7 --- /dev/null +++ b/final/include/llvm/ADT/SmallVector.h @@ -0,0 +1,752 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- 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 SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include "llvm/Support/type_traits.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else +// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear +// is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace llvm { + +/// SmallVectorBase - This is all the non-templated stuff common to all +/// SmallVectors. +class SmallVectorBase { +protected: + void *BeginX, *EndX, *CapacityX; + + // Allocate raw space for N elements of type T. If T has a ctor or dtor, we + // don't want it to be automatically run, so we need to represent the space as + // something else. An array of char would work great, but might not be + // aligned sufficiently. Instead we use some number of union instances for + // the space, which guarantee maximal alignment. + union U { + double D; + long double LD; + long long L; + void *P; + } FirstEl; + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. + +protected: + SmallVectorBase(size_t Size) + : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {} + + /// isSmall - Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return BeginX == static_cast(&FirstEl); + } + + /// size_in_bytes - This returns size()*sizeof(T). + size_t size_in_bytes() const { + return size_t((char*)EndX - (char*)BeginX); + } + + /// capacity_in_bytes - This returns capacity()*sizeof(T). + size_t capacity_in_bytes() const { + return size_t((char*)CapacityX - (char*)BeginX); + } + + /// grow_pod - This is an implementation of the grow() method which only works + /// on POD-like data types and is out of line to reduce code duplication. + void grow_pod(size_t MinSizeInBytes, size_t TSize); + +public: + bool empty() const { return BeginX == EndX; } +}; + + +template +class SmallVectorTemplateCommon : public SmallVectorBase { +protected: + void setEnd(T *P) { this->EndX = P; } +public: + SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *iterator; + typedef const T *const_iterator; + + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + typedef T &reference; + typedef const T &const_reference; + typedef T *pointer; + typedef const T *const_pointer; + + // forward iterator creation methods. + iterator begin() { return (iterator)this->BeginX; } + const_iterator begin() const { return (const_iterator)this->BeginX; } + iterator end() { return (iterator)this->EndX; } + const_iterator end() const { return (const_iterator)this->EndX; } +protected: + iterator capacity_ptr() { return (iterator)this->CapacityX; } + const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} +public: + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + size_type size() const { return end()-begin(); } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return capacity_ptr() - begin(); } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { return pointer(begin()); } + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { return const_pointer(begin()); } + + reference operator[](unsigned idx) { + assert(begin() + idx < end()); + return begin()[idx]; + } + const_reference operator[](unsigned idx) const { + assert(begin() + idx < end()); + return begin()[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } +}; + +/// SmallVectorTemplateBase - This is where we put method +/// implementations that are designed to work with non-POD-like T's. +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + + static void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0); +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +void SmallVectorTemplateBase::grow(size_t MinSize) { + size_t CurCapacity = this->capacity(); + size_t CurSize = this->size(); + size_t NewCapacity = 2*CurCapacity + 1; // Always grow, even from zero. + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = static_cast(malloc(NewCapacity*sizeof(T))); + + // Copy the elements over. + this->uninitialized_copy(this->begin(), this->end(), NewElts); + + // Destroy the original elements. + destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + + this->setEnd(NewElts+CurSize); + this->BeginX = NewElts; + this->CapacityX = this->begin()+NewCapacity; +} + + +/// SmallVectorTemplateBase - This is where we put method +/// implementations that are designed to work with POD-like T's. +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + + // No need to do a destroy loop for POD's. + static void destroy_range(T *, T *) {} + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + // Arbitrary iterator types; just use the basic implementation. + std::uninitialized_copy(I, E, Dest); + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { + // Use memcpy for PODs iterated by pointers (which includes SmallVector + // iterators): std::uninitialized_copy optimizes to memmove, but we can + // use memcpy here. + memcpy(Dest, I, (E-I)*sizeof(T)); + } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0) { + this->grow_pod(MinSize*sizeof(T), sizeof(T)); + } +}; + + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template +class SmallVectorImpl : public SmallVectorTemplateBase::value> { + typedef SmallVectorTemplateBase::value > SuperClass; + + SmallVectorImpl(const SmallVectorImpl&); // DISABLED. +public: + typedef typename SuperClass::iterator iterator; + typedef typename SuperClass::size_type size_type; + + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : SmallVectorTemplateBase::value>(N*sizeof(T)) { + } + + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + this->destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + free(this->begin()); + } + + + void clear() { + this->destroy_range(this->begin(), this->end()); + this->EndX = this->BeginX; + } + + void resize(unsigned N) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + this->construct_range(this->end(), this->begin()+N, T()); + this->setEnd(this->begin()+N); + } + } + + void resize(unsigned N, const T &NV) { + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) + this->grow(N); + construct_range(this->end(), this->begin()+N, NV); + this->setEnd(this->begin()+N); + } + } + + void reserve(unsigned N) { + if (this->capacity() < N) + this->grow(N); + } + + void push_back(const T &Elt) { + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(Elt); + this->setEnd(this->end()+1); + return; + } + this->grow(); + goto Retry; + } + + void pop_back() { + this->setEnd(this->end()-1); + this->end()->~T(); + } + + T pop_back_val() { + T Result = this->back(); + pop_back(); + return Result; + } + + void swap(SmallVectorImpl &RHS); + + /// append - Add the specified range to the end of the SmallVector. + /// + template + void append(in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(this->size()+NumInputs); + + // Copy the new elements over. + // TODO: NEED To compile time dispatch on whether in_iter is a random access + // iterator to use the fast uninitialized_copy. + std::uninitialized_copy(in_start, in_end, this->end()); + this->setEnd(this->end() + NumInputs); + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + this->grow(this->size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + this->setEnd(this->end() + NumInputs); + } + + void assign(unsigned NumElts, const T &Elt) { + clear(); + if (this->capacity() < NumElts) + this->grow(NumElts); + this->setEnd(this->begin()+NumElts); + construct_range(this->begin(), this->end(), Elt); + } + + iterator erase(iterator I) { + iterator N = I; + // Shift all elts down one. + std::copy(I+1, this->end(), I); + // Drop the last elt. + pop_back(); + return(N); + } + + iterator erase(iterator S, iterator E) { + iterator N = S; + // Shift all elts down. + iterator I = std::copy(E, this->end(), S); + // Drop the last elts. + this->destroy_range(I, this->end()); + this->setEnd(I); + return(N); + } + + iterator insert(iterator I, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + push_back(Elt); + return this->end()-1; + } + + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(this->back()); + this->setEnd(this->end()+1); + // Push everything else over. + std::copy_backward(I, this->end()-1, this->end()); + *I = Elt; + return I; + } + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + goto Retry; + } + + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + if (I == this->end()) { // Important special case for empty vector. + append(NumToInsert, Elt); + return this->end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(static_cast(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template + iterator insert(iterator I, ItTy From, ItTy To) { + if (I == this->end()) { // Important special case for empty vector. + append(From, To); + return this->end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + // Ensure there is enough space. + reserve(static_cast(this->size() + NumToInsert)); + + // Uninvalidate the iterator. + I = this->begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(this->end()-NumToInsert, this->end()); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = this->end(); + this->setEnd(this->end() + NumToInsert); + size_t NumOverwritten = OldEnd-I; + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + + // Replace the overwritten part. + for (; NumOverwritten > 0; --NumOverwritten) { + *I = *From; + ++I; ++From; + } + + // Insert the non-overwritten middle part. + this->uninitialized_copy(From, To, OldEnd); + return I; + } + + const SmallVectorImpl + &operator=(const SmallVectorImpl &RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (this->size() != RHS.size()) return false; + return std::equal(this->begin(), this->end(), RHS.begin()); + } + bool operator!=(const SmallVectorImpl &RHS) const { + return !(*this == RHS); + } + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(this->begin(), this->end(), + RHS.begin(), RHS.end()); + } + + /// set_size - Set the array size to \arg N, which the current array must have + /// enough capacity for. + /// + /// This does not construct or destroy any elements in the vector. + /// + /// Clients can use this in conjunction with capacity() to write past the end + /// of the buffer when they know that more elements are available, and only + /// update the size later. This avoids the cost of value initializing elements + /// which will only be overwritten. + void set_size(unsigned N) { + assert(N <= this->capacity()); + this->setEnd(this->begin() + N); + } + +private: + static void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } +}; + + +template +void SmallVectorImpl::swap(SmallVectorImpl &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!this->isSmall() && !RHS.isSmall()) { + std::swap(this->BeginX, RHS.BeginX); + std::swap(this->EndX, RHS.EndX); + std::swap(this->CapacityX, RHS.CapacityX); + return; + } + if (RHS.size() > this->capacity()) + this->grow(RHS.size()); + if (this->size() > RHS.capacity()) + RHS.grow(this->size()); + + // Swap the shared elements. + size_t NumShared = this->size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (unsigned i = 0; i != static_cast(NumShared); ++i) + std::swap((*this)[i], RHS[i]); + + // Copy over the extra elts. + if (this->size() > RHS.size()) { + size_t EltDiff = this->size() - RHS.size(); + this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); + RHS.setEnd(RHS.end()+EltDiff); + this->destroy_range(this->begin()+NumShared, this->end()); + this->setEnd(this->begin()+NumShared); + } else if (RHS.size() > this->size()) { + size_t EltDiff = RHS.size() - this->size(); + this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); + this->setEnd(this->end() + EltDiff); + this->destroy_range(RHS.begin()+NumShared, RHS.end()); + RHS.setEnd(RHS.begin()+NumShared); + } +} + +template +const SmallVectorImpl &SmallVectorImpl:: + operator=(const SmallVectorImpl &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + size_t RHSSize = RHS.size(); + size_t CurSize = this->size(); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd; + if (RHSSize) + NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); + else + NewEnd = this->begin(); + + // Destroy excess elements. + this->destroy_range(NewEnd, this->end()); + + // Trim. + this->setEnd(NewEnd); + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + if (this->capacity() < RHSSize) { + // Destroy current elements. + this->destroy_range(this->begin(), this->end()); + this->setEnd(this->begin()); + CurSize = 0; + this->grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); + } + + // Copy construct the new elements in place. + this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); + + // Set end. + this->setEnd(this->begin()+RHSSize); + return *this; +} + + +/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template +class SmallVector : public SmallVectorImpl { + /// InlineElts - These are 'N-1' elements that are stored inline in the body + /// of the vector. The extra '1' element is stored in SmallVectorImpl. + typedef typename SmallVectorImpl::U U; + enum { + // MinUs - The number of U's require to cover N T's. + MinUs = (static_cast(sizeof(T))*N + + static_cast(sizeof(U)) - 1) / + static_cast(sizeof(U)), + + // NumInlineEltsElts - The number of elements actually in this array. There + // is already one in the parent class, and we have to round up to avoid + // having a zero-element array. + NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, + + // NumTsAvailable - The number of T's we actually have space for, which may + // be more than N due to rounding. + NumTsAvailable = (NumInlineEltsElts+1)*static_cast(sizeof(U))/ + static_cast(sizeof(T)) + }; + U InlineElts[NumInlineEltsElts]; +public: + SmallVector() : SmallVectorImpl(NumTsAvailable) { + } + + explicit SmallVector(unsigned Size, const T &Value = T()) + : SmallVectorImpl(NumTsAvailable) { + this->reserve(Size); + while (Size--) + this->push_back(Value); + } + + template + SmallVector(ItTy S, ItTy E) : SmallVectorImpl(NumTsAvailable) { + this->append(S, E); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl(NumTsAvailable) { + if (!RHS.empty()) + SmallVectorImpl::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl::operator=(RHS); + return *this; + } + +}; + +/// Specialize SmallVector at N=0. This specialization guarantees +/// that it can be instantiated at an incomplete T if none of its +/// members are required. +template +class SmallVector : public SmallVectorImpl { +public: + SmallVector() : SmallVectorImpl(0) {} + + explicit SmallVector(unsigned Size, const T &Value = T()) + : SmallVectorImpl(0) { + this->reserve(Size); + while (Size--) + this->push_back(Value); + } + + template + SmallVector(ItTy S, ItTy E) : SmallVectorImpl(0) { + this->append(S, E); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl(0) { + SmallVectorImpl::operator=(RHS); + } + + SmallVector &operator=(const SmallVectorImpl &RHS) { + return SmallVectorImpl::operator=(RHS); + } + +}; + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVectorImpl &LHS, llvm::SmallVectorImpl &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template + inline void + swap(llvm::SmallVector &LHS, llvm::SmallVector &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/final/include/llvm/ADT/SparseBitVector.h b/final/include/llvm/ADT/SparseBitVector.h new file mode 100644 index 00000000000..d977136b2fc --- /dev/null +++ b/final/include/llvm/ADT/SparseBitVector.h @@ -0,0 +1,906 @@ +//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- 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 SparseBitVector class. See the doxygen comment for +// SparseBitVector for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEBITVECTOR_H +#define LLVM_ADT_SPARSEBITVECTOR_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace llvm { + +/// SparseBitVector is an implementation of a bitvector that is sparse by only +/// storing the elements that have non-zero bits set. In order to make this +/// fast for the most common cases, SparseBitVector is implemented as a linked +/// list of SparseBitVectorElements. We maintain a pointer to the last +/// SparseBitVectorElement accessed (in the form of a list iterator), in order +/// to make multiple in-order test/set constant time after the first one is +/// executed. Note that using vectors to store SparseBitVectorElement's does +/// not work out very well because it causes insertion in the middle to take +/// enormous amounts of time with a large amount of bits. Other structures that +/// have better worst cases for insertion in the middle (various balanced trees, +/// etc) do not perform as well in practice as a linked list with this iterator +/// kept up to date. They are also significantly more memory intensive. + + +template +struct SparseBitVectorElement + : public ilist_node > { +public: + typedef unsigned long BitWord; + enum { + BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, + BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, + BITS_PER_ELEMENT = ElementSize + }; + +private: + // Index of Element in terms of where first bit starts. + unsigned ElementIndex; + BitWord Bits[BITWORDS_PER_ELEMENT]; + // Needed for sentinels + friend struct ilist_sentinel_traits; + SparseBitVectorElement() { + ElementIndex = ~0U; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + +public: + explicit SparseBitVectorElement(unsigned Idx) { + ElementIndex = Idx; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + + // Comparison. + bool operator==(const SparseBitVectorElement &RHS) const { + if (ElementIndex != RHS.ElementIndex) + return false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + return true; + } + + bool operator!=(const SparseBitVectorElement &RHS) const { + return !(*this == RHS); + } + + // Return the bits that make up word Idx in our element. + BitWord word(unsigned Idx) const { + assert (Idx < BITWORDS_PER_ELEMENT); + return Bits[Idx]; + } + + unsigned index() const { + return ElementIndex; + } + + bool empty() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i]) + return false; + return true; + } + + void set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + void reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + } + + bool test(unsigned Idx) const { + return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); + } + + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32(Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// find_first - Returns the index of the first set bit. + int find_first() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + assert(0 && "Illegal empty element"); + return 0; // Not reached + } + + /// find_next - Returns the index of the next set bit starting from the + /// "Curr" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Curr) const { + if (Curr >= BITS_PER_ELEMENT) + return -1; + + unsigned WordPos = Curr / BITWORD_SIZE; + unsigned BitPos = Curr % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + assert (WordPos <= BITWORDS_PER_ELEMENT + && "Word Position outside of element"); + + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + // Union this element with RHS and return true if this one changed. + bool unionWith(const SparseBitVectorElement &RHS) { + bool changed = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] |= RHS.Bits[i]; + if (!changed && old != Bits[i]) + changed = true; + } + return changed; + } + + // Return true if we have any bits in common with RHS + bool intersects(const SparseBitVectorElement &RHS) const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + if (RHS.Bits[i] & Bits[i]) + return true; + } + return false; + } + + // Intersect this Element with RHS and return true if this one changed. + // BecameZero is set to true if this element became all-zero bits. + bool intersectWith(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Intersect this Element with the complement of RHS and return true if this + // one changed. BecameZero is set to true if this element became all-zero + // bits. + bool intersectWithComplement(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= ~RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Three argument version of intersectWithComplement that intersects + // RHS1 & ~RHS2 into this element + void intersectWithComplement(const SparseBitVectorElement &RHS1, + const SparseBitVectorElement &RHS2, + bool &BecameZero) { + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; + if (Bits[i] != 0) + allzero = false; + } + BecameZero = allzero; + } + + // Get a hash value for this element; + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + HashVal ^= Bits[i]; + } + return HashVal; + } +}; + +template +class SparseBitVector { + typedef ilist > ElementList; + typedef typename ElementList::iterator ElementListIter; + typedef typename ElementList::const_iterator ElementListConstIter; + enum { + BITWORD_SIZE = SparseBitVectorElement::BITWORD_SIZE + }; + + // Pointer to our current Element. + ElementListIter CurrElementIter; + ElementList Elements; + + // This is like std::lower_bound, except we do linear searching from the + // current position. + ElementListIter FindLowerBound(unsigned ElementIndex) { + + if (Elements.empty()) { + CurrElementIter = Elements.begin(); + return Elements.begin(); + } + + // Make sure our current iterator is valid. + if (CurrElementIter == Elements.end()) + --CurrElementIter; + + // Search from our current iterator, either backwards or forwards, + // depending on what element we are looking for. + ElementListIter ElementIter = CurrElementIter; + if (CurrElementIter->index() == ElementIndex) { + return ElementIter; + } else if (CurrElementIter->index() > ElementIndex) { + while (ElementIter != Elements.begin() + && ElementIter->index() > ElementIndex) + --ElementIter; + } else { + while (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ++ElementIter; + } + CurrElementIter = ElementIter; + return ElementIter; + } + + // Iterator to walk set bits in the bitmap. This iterator is a lot uglier + // than it would be, in order to be efficient. + class SparseBitVectorIterator { + private: + bool AtEnd; + + const SparseBitVector *BitVector; + + // Current element inside of bitmap. + ElementListConstIter Iter; + + // Current bit number inside of our bitmap. + unsigned BitNumber; + + // Current word number inside of our element. + unsigned WordNumber; + + // Current bits from the element. + typename SparseBitVectorElement::BitWord Bits; + + // Move our iterator to the first non-zero bit in the bitmap. + void AdvanceToFirstNonZero() { + if (AtEnd) + return; + if (BitVector->Elements.empty()) { + AtEnd = true; + return; + } + Iter = BitVector->Elements.begin(); + BitNumber = Iter->index() * ElementSize; + unsigned BitPos = Iter->find_first(); + BitNumber += BitPos; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= BitPos % BITWORD_SIZE; + } + + // Move our iterator to the next non-zero bit. + void AdvanceToNextNonZero() { + if (AtEnd) + return; + + while (Bits && !(Bits & 1)) { + Bits >>= 1; + BitNumber += 1; + } + + // See if we ran out of Bits in this word. + if (!Bits) { + int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ; + // If we ran out of set bits in this element, move to next element. + if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) { + ++Iter; + WordNumber = 0; + + // We may run out of elements in the bitmap. + if (Iter == BitVector->Elements.end()) { + AtEnd = true; + return; + } + // Set up for next non zero word in bitmap. + BitNumber = Iter->index() * ElementSize; + NextSetBitNumber = Iter->find_first(); + BitNumber += NextSetBitNumber; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + } else { + WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + BitNumber = Iter->index() * ElementSize; + BitNumber += NextSetBitNumber; + } + } + } + public: + // Preincrement. + inline SparseBitVectorIterator& operator++() { + ++BitNumber; + Bits >>= 1; + AdvanceToNextNonZero(); + return *this; + } + + // Postincrement. + inline SparseBitVectorIterator operator++(int) { + SparseBitVectorIterator tmp = *this; + ++*this; + return tmp; + } + + // Return the current set bit number. + unsigned operator*() const { + return BitNumber; + } + + bool operator==(const SparseBitVectorIterator &RHS) const { + // If they are both at the end, ignore the rest of the fields. + if (AtEnd && RHS.AtEnd) + return true; + // Otherwise they are the same if they have the same bit number and + // bitmap. + return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber; + } + bool operator!=(const SparseBitVectorIterator &RHS) const { + return !(*this == RHS); + } + SparseBitVectorIterator(): BitVector(NULL) { + } + + + SparseBitVectorIterator(const SparseBitVector *RHS, + bool end = false):BitVector(RHS) { + Iter = BitVector->Elements.begin(); + BitNumber = 0; + Bits = 0; + WordNumber = ~0; + AtEnd = end; + AdvanceToFirstNonZero(); + } + }; +public: + typedef SparseBitVectorIterator iterator; + + SparseBitVector () { + CurrElementIter = Elements.begin (); + } + + ~SparseBitVector() { + } + + // SparseBitVector copy ctor. + SparseBitVector(const SparseBitVector &RHS) { + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + } + + // Clear. + void clear() { + Elements.clear(); + } + + // Assignment + SparseBitVector& operator=(const SparseBitVector& RHS) { + Elements.clear(); + + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + + return *this; + } + + // Test, Reset, and Set a bit in the bitmap. + bool test(unsigned Idx) { + if (Elements.empty()) + return false; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return false; + return ElementIter->test(Idx % ElementSize); + } + + void reset(unsigned Idx) { + if (Elements.empty()) + return; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return; + ElementIter->reset(Idx % ElementSize); + + // When the element is zeroed out, delete it. + if (ElementIter->empty()) { + ++CurrElementIter; + Elements.erase(ElementIter); + } + } + + void set(unsigned Idx) { + unsigned ElementIndex = Idx / ElementSize; + SparseBitVectorElement *Element; + ElementListIter ElementIter; + if (Elements.empty()) { + Element = new SparseBitVectorElement(ElementIndex); + ElementIter = Elements.insert(Elements.end(), Element); + + } else { + ElementIter = FindLowerBound(ElementIndex); + + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) { + Element = new SparseBitVectorElement(ElementIndex); + // We may have hit the beginning of our SparseBitVector, in which case, + // we may need to insert right after this element, which requires moving + // the current iterator forward one, because insert does insert before. + if (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ElementIter = Elements.insert(++ElementIter, Element); + else + ElementIter = Elements.insert(ElementIter, Element); + } + } + CurrElementIter = ElementIter; + + ElementIter->set(Idx % ElementSize); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + bool operator!=(const SparseBitVector &RHS) const { + return !(*this == RHS); + } + + bool operator==(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); + ++Iter1, ++Iter2) { + if (*Iter1 != *Iter2) + return false; + } + return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); + } + + // Union our bitmap with the RHS and return true if we changed. + bool operator|=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If RHS is empty, we are done + if (RHS.Elements.empty()) + return false; + + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { + Elements.insert(Iter1, + new SparseBitVectorElement(*Iter2)); + ++Iter2; + changed = true; + } else if (Iter1->index() == Iter2->index()) { + changed |= Iter1->unionWith(*Iter2); + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the RHS and return true if ours changed. + bool operator&=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWith(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } + } + Elements.erase(Iter1, Elements.end()); + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the complement of the RHS and return true + // if ours changed. + bool intersectWithComplement(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If either our bitmap or RHS is empty, we are done + if (Elements.empty() || RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + bool intersectWithComplement(const SparseBitVector *RHS) const { + return intersectWithComplement(*RHS); + } + + + // Three argument version of intersectWithComplement. + // Result of RHS1 & ~RHS2 is stored into this bitmap. + void intersectWithComplement(const SparseBitVector &RHS1, + const SparseBitVector &RHS2) + { + Elements.clear(); + CurrElementIter = Elements.begin(); + ElementListConstIter Iter1 = RHS1.Elements.begin(); + ElementListConstIter Iter2 = RHS2.Elements.begin(); + + // If RHS1 is empty, we are done + // If RHS2 is empty, we still have to copy RHS1 + if (RHS1.Elements.empty()) + return; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS2.Elements.end()) { + if (Iter1 == RHS1.Elements.end()) + return; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero = false; + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(Iter1->index()); + NewElement->intersectWithComplement(*Iter1, *Iter2, BecameZero); + if (!BecameZero) { + Elements.push_back(NewElement); + } + else + delete NewElement; + ++Iter1; + ++Iter2; + } else { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + } + + // copy the remaining elements + while (Iter1 != RHS1.Elements.end()) { + SparseBitVectorElement *NewElement = + new SparseBitVectorElement(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + + return; + } + + void intersectWithComplement(const SparseBitVector *RHS1, + const SparseBitVector *RHS2) { + intersectWithComplement(*RHS1, *RHS2); + } + + bool intersects(const SparseBitVector *RHS) const { + return intersects(*RHS); + } + + // Return true if we share any bits in common with RHS + bool intersects(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting stopping when we hit bits in common. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) + return false; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + if (Iter1->intersects(*Iter2)) + return true; + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + return false; + } + + // Return true iff all bits set in this SparseBitVector are + // also set in RHS. + bool contains(const SparseBitVector &RHS) const { + SparseBitVector Result(*this); + Result &= RHS; + return (Result == RHS); + } + + // Return the first set bit in the bitmap. Return -1 if no bits are set. + int find_first() const { + if (Elements.empty()) + return -1; + const SparseBitVectorElement &First = *(Elements.begin()); + return (First.index() * ElementSize) + First.find_first(); + } + + // Return true if the SparseBitVector is empty + bool empty() const { + return Elements.empty(); + } + + unsigned count() const { + unsigned BitCount = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) + BitCount += Iter->count(); + + return BitCount; + } + iterator begin() const { + return iterator(this); + } + + iterator end() const { + return iterator(this, true); + } + + // Get a hash value for this bitmap. + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) { + HashVal ^= Iter->index(); + HashVal ^= Iter->getHashValue(); + } + return HashVal; + } +}; + +// Convenience functions to allow Or and And without dereferencing in the user +// code. + +template +inline bool operator |=(SparseBitVector &LHS, + const SparseBitVector *RHS) { + return LHS |= *RHS; +} + +template +inline bool operator |=(SparseBitVector *LHS, + const SparseBitVector &RHS) { + return LHS->operator|=(RHS); +} + +template +inline bool operator &=(SparseBitVector *LHS, + const SparseBitVector &RHS) { + return LHS->operator&=(RHS); +} + +template +inline bool operator &=(SparseBitVector &LHS, + const SparseBitVector *RHS) { + return LHS &= *RHS; +} + +// Convenience functions for infix union, intersection, difference operators. + +template +inline SparseBitVector +operator|(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result |= RHS; + return Result; +} + +template +inline SparseBitVector +operator&(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result(LHS); + Result &= RHS; + return Result; +} + +template +inline SparseBitVector +operator-(const SparseBitVector &LHS, + const SparseBitVector &RHS) { + SparseBitVector Result; + Result.intersectWithComplement(LHS, RHS); + return Result; +} + + + + +// Dump a SparseBitVector to a stream +template +void dump(const SparseBitVector &LHS, raw_ostream &out) { + out << "["; + + typename SparseBitVector::iterator bi = LHS.begin(), + be = LHS.end(); + if (bi != be) { + out << *bi; + for (++bi; bi != be; ++bi) { + out << " " << *bi; + } + } + out << "]\n"; +} +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/Statistic.h b/final/include/llvm/ADT/Statistic.h new file mode 100644 index 00000000000..fda99c6edbc --- /dev/null +++ b/final/include/llvm/ADT/Statistic.h @@ -0,0 +1,135 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- 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 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +#include "llvm/Support/Atomic.h" + +namespace llvm { +class raw_ostream; + +class Statistic { +public: + const char *Name; + const char *Desc; + volatile llvm::sys::cas_flag Value; + bool Initialized; + + llvm::sys::cas_flag getValue() const { return Value; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + + /// construct - This should only be called for non-global statistics. + void construct(const char *name, const char *desc) { + Name = name; Desc = desc; + Value = 0; Initialized = 0; + } + + // Allow use of this class as the value itself. + operator unsigned() const { return Value; } + const Statistic &operator=(unsigned Val) { + Value = Val; + return init(); + } + + const Statistic &operator++() { + // FIXME: This function and all those that follow carefully use an + // atomic operation to update the value safely in the presence of + // concurrent accesses, but not to read the return value, so the + // return value is not thread safe. + sys::AtomicIncrement(&Value); + return init(); + } + + unsigned operator++(int) { + init(); + unsigned OldValue = Value; + sys::AtomicIncrement(&Value); + return OldValue; + } + + const Statistic &operator--() { + sys::AtomicDecrement(&Value); + return init(); + } + + unsigned operator--(int) { + init(); + unsigned OldValue = Value; + sys::AtomicDecrement(&Value); + return OldValue; + } + + const Statistic &operator+=(const unsigned &V) { + sys::AtomicAdd(&Value, V); + return init(); + } + + const Statistic &operator-=(const unsigned &V) { + sys::AtomicAdd(&Value, -V); + return init(); + } + + const Statistic &operator*=(const unsigned &V) { + sys::AtomicMul(&Value, V); + return init(); + } + + const Statistic &operator/=(const unsigned &V) { + sys::AtomicDiv(&Value, V); + return init(); + } + +protected: + Statistic &init() { + bool tmp = Initialized; + sys::MemoryFence(); + if (!tmp) RegisterStatistic(); + return *this; + } + void RegisterStatistic(); +}; + +// STATISTIC - A macro to make definition of statistics really simple. This +// automatically passes the DEBUG_TYPE of the file into the statistic. +#define STATISTIC(VARNAME, DESC) \ + static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 } + +/// \brief Enable the collection and printing of statistics. +void EnableStatistics(); + +/// \brief Check if statistics are enabled. +bool AreStatisticsEnabled(); + +/// \brief Print statistics to the file returned by CreateInfoOutputFile(). +void PrintStatistics(); + +/// \brief Print statistics to the given output stream. +void PrintStatistics(raw_ostream &OS); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/StringExtras.h b/final/include/llvm/ADT/StringExtras.h new file mode 100644 index 00000000000..acbed66ef40 --- /dev/null +++ b/final/include/llvm/ADT/StringExtras.h @@ -0,0 +1,171 @@ +//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include +#include + +namespace llvm { +template class SmallVectorImpl; + +/// hexdigit - Return the hexadecimal character for the +/// given number \arg X (which should be less than 16). +static inline char hexdigit(unsigned X, bool LowerCase = false) { + const char HexChar = LowerCase ? 'a' : 'A'; + return X < 10 ? '0' + X : HexChar + X - 10; +} + +/// utohex_buffer - Emit the specified number into the buffer specified by +/// BufferEnd, returning a pointer to the start of the string. This can be used +/// like this: (note that the buffer must be large enough to handle any number): +/// char Buffer[40]; +/// printf("0x%s", utohex_buffer(X, Buffer+40)); +/// +/// This should only be used with unsigned types. +/// +template +static inline char *utohex_buffer(IntTy X, char *BufferEnd) { + char *BufPtr = BufferEnd; + *--BufPtr = 0; // Null terminate buffer. + if (X == 0) { + *--BufPtr = '0'; // Handle special case. + return BufPtr; + } + + while (X) { + unsigned char Mod = static_cast(X) & 15; + *--BufPtr = hexdigit(Mod); + X >>= 4; + } + return BufPtr; +} + +static inline std::string utohexstr(uint64_t X) { + char Buffer[17]; + return utohex_buffer(X, Buffer+17); +} + +static inline std::string utostr_32(uint32_t X, bool isNeg = false) { + char Buffer[11]; + char *BufPtr = Buffer+11; + + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + + return std::string(BufPtr, Buffer+11); +} + +static inline std::string utostr(uint64_t X, bool isNeg = false) { + char Buffer[21]; + char *BufPtr = Buffer+21; + + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr, Buffer+21); +} + + +static inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast(-X), true); + else + return utostr(static_cast(X)); +} + +static inline std::string ftostr(double V) { + char Buffer[200]; + sprintf(Buffer, "%20.6e", V); + char *B = Buffer; + while (*B == ' ') ++B; + return B; +} + +static inline std::string ftostr(const APFloat& V) { + if (&V.getSemantics() == &APFloat::IEEEdouble) + return ftostr(V.convertToDouble()); + else if (&V.getSemantics() == &APFloat::IEEEsingle) + return ftostr((double)V.convertToFloat()); + return ""; // error +} + +static inline std::string LowercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (isupper(result[i])) + result[i] = char(tolower(result[i])); + return result; +} + +static inline std::string UppercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (islower(result[i])) + result[i] = char(toupper(result[i])); + return result; +} + +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2); + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair getToken(StringRef Source, + StringRef Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(StringRef Source, + SmallVectorImpl &OutFragments, + StringRef Delimiters = " \t\n\v\f\r"); + +/// HashString - Hash funtion for strings. +/// +/// This is the Bernstein hash function. +// +// FIXME: Investigate whether a modified bernstein hash function performs +// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx +// X*33+c -> X*33^c +static inline unsigned HashString(StringRef Str, unsigned Result = 0) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) + Result = Result * 33 + Str[i]; + return Result; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/StringMap.h b/final/include/llvm/ADT/StringMap.h new file mode 100644 index 00000000000..bad0e6f5136 --- /dev/null +++ b/final/include/llvm/ADT/StringMap.h @@ -0,0 +1,493 @@ +//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include +#include + +namespace llvm { + template + class StringMapConstIterator; + template + class StringMapIterator; + template + class StringMapEntry; + +/// StringMapEntryInitializer - This datatype can be partially specialized for +/// various datatypes in a stringmap to allow them to be initialized when an +/// entry is default constructed for the map. +template +class StringMapEntryInitializer { +public: + template + static void Initialize(StringMapEntry &T, InitTy InitVal) { + T.second = InitVal; + } +}; + + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + unsigned StrLen; +public: + explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} + + unsigned getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +public: + /// ItemBucket - The hash table consists of an array of these. If Item is + /// non-null, this is an extant entry, otherwise, it is a hole. + struct ItemBucket { + /// FullHashValue - This remembers the full hash value of the key for + /// easy scanning. + unsigned FullHashValue; + + /// Item - This is a pointer to the actual item object. + StringMapEntryBase *Item; + }; + +protected: + ItemBucket *TheTable; + unsigned NumBuckets; + unsigned NumItems; + unsigned NumTombstones; + unsigned ItemSize; +protected: + explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { + // Initialize the map with zero buckets to allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; + } + StringMapImpl(unsigned InitSize, unsigned ItemSize); + void RehashTable(); + + /// ShouldRehash - Return true if the table should be rehashed after a new + /// element was recently inserted. + bool ShouldRehash() const { + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + return NumItems*4 > NumBuckets*3 || + NumBuckets-(NumItems+NumTombstones) < NumBuckets/8; + } + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(StringRef Key); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(StringRef Key) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(StringRef Key); +private: + void init(unsigned Size); +public: + static StringMapEntryBase *getTombstoneVal() { + return (StringMapEntryBase*)-1; + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template +class StringMapEntry : public StringMapEntryBase { +public: + ValueTy second; + + explicit StringMapEntry(unsigned strLen) + : StringMapEntryBase(strLen), second() {} + StringMapEntry(unsigned strLen, const ValueTy &V) + : StringMapEntryBase(strLen), second(V) {} + + StringRef getKey() const { + return StringRef(getKeyData(), getKeyLength()); + } + + const ValueTy &getValue() const { return second; } + ValueTy &getValue() { return second; } + + void setValue(const ValueTy &V) { second = V; } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast(this+1);} + + const char *first() const { return getKeyData(); } + + /// Create - Create a StringMapEntry for the specified key and default + /// construct the value. + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator, + InitType InitVal) { + unsigned KeyLength = static_cast(KeyEnd-KeyStart); + + // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill + // in. Allocate a new item with space for the string at the end and a null + // terminator. + + unsigned AllocSize = static_cast(sizeof(StringMapEntry))+ + KeyLength+1; + unsigned Alignment = alignOf(); + + StringMapEntry *NewItem = + static_cast(Allocator.Allocate(AllocSize,Alignment)); + + // Default construct the value. + new (NewItem) StringMapEntry(KeyLength); + + // Copy the string information. + char *StrBuffer = const_cast(NewItem->getKeyData()); + memcpy(StrBuffer, KeyStart, KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + + // Initialize the value if the client wants to. + StringMapEntryInitializer::Initialize(*NewItem, InitVal); + return NewItem; + } + + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator) { + return Create(KeyStart, KeyEnd, Allocator, 0); + } + + + /// Create - Create a StringMapEntry with normal malloc/free. + template + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + InitType InitVal) { + MallocAllocator A; + return Create(KeyStart, KeyEnd, A, InitVal); + } + + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { + return Create(KeyStart, KeyEnd, ValueTy()); + } + + /// GetStringMapEntryFromValue - Given a value that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { + StringMapEntry *EPtr = 0; + char *Ptr = reinterpret_cast(&V) - + (reinterpret_cast(&EPtr->second) - + reinterpret_cast(EPtr)); + return *reinterpret_cast(Ptr); + } + static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { + return GetStringMapEntryFromValue(const_cast(V)); + } + + /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { + char *Ptr = const_cast(KeyData) - sizeof(StringMapEntry); + return *reinterpret_cast(Ptr); + } + + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~StringMapEntry(); + Allocator.Deallocate(this); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + typedef StringMapEntry MapEntryTy; +public: + StringMap() : StringMapImpl(static_cast(sizeof(MapEntryTy))) {} + explicit StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, static_cast(sizeof(MapEntryTy))) {} + + explicit StringMap(AllocatorTy A) + : StringMapImpl(static_cast(sizeof(MapEntryTy))), Allocator(A) {} + + explicit StringMap(const StringMap &RHS) + : StringMapImpl(static_cast(sizeof(MapEntryTy))) { + assert(RHS.empty() && + "Copy ctor from non-empty stringmap not implemented yet!"); + (void)RHS; + } + void operator=(const StringMap &RHS) { + assert(RHS.empty() && + "assignment from non-empty stringmap not implemented yet!"); + (void)RHS; + clear(); + } + + typedef typename ReferenceAdder::result AllocatorRefTy; + typedef typename ReferenceAdder::result AllocatorCRefTy; + AllocatorRefTy getAllocator() { return Allocator; } + AllocatorCRefTy getAllocator() const { return Allocator; } + + typedef const char* key_type; + typedef ValueTy mapped_type; + typedef StringMapEntry value_type; + typedef size_t size_type; + + typedef StringMapConstIterator const_iterator; + typedef StringMapIterator iterator; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator find(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket); + } + + const_iterator find(StringRef Key) const { + int Bucket = FindKey(Key); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueTy lookup(StringRef Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + return ValueTy(); + } + + ValueTy& operator[](StringRef Key) { + return GetOrCreateValue(Key).getValue(); + } + + size_type count(StringRef Key) const { + return find(Key) == end() ? 0 : 1; + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = LookupBucketFor(KeyValue->getKey()); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + Bucket.Item = KeyValue; + ++NumItems; + + if (ShouldRehash()) + RehashTable(); + return true; + } + + // clear - Empties out the StringMap + void clear() { + if (empty()) return; + + // Zap all values, resetting the keys back to non-present (not tombstone), + // which is safe because we're removing all elements. + for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) { + if (I->Item && I->Item != getTombstoneVal()) { + static_cast(I->Item)->Destroy(Allocator); + I->Item = 0; + } + } + + NumItems = 0; + } + + /// GetOrCreateValue - Look up the specified key in the table. If a value + /// exists, return it. Otherwise, default construct a value, insert it, and + /// return. + template + StringMapEntry &GetOrCreateValue(StringRef Key, + InitTy Val) { + unsigned BucketNo = LookupBucketFor(Key); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return *static_cast(Bucket.Item); + + MapEntryTy *NewItem = + MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val); + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + ++NumItems; + + // Fill in the bucket for the hash table. The FullHashValue was already + // filled in by LookupBucketFor. + Bucket.Item = NewItem; + + if (ShouldRehash()) + RehashTable(); + return *NewItem; + } + + StringMapEntry &GetOrCreateValue(StringRef Key) { + return GetOrCreateValue(Key, ValueTy()); + } + + template + StringMapEntry &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd, + InitTy Val) { + return GetOrCreateValue(StringRef(KeyStart, KeyEnd - KeyStart), Val); + } + + StringMapEntry &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd) { + return GetOrCreateValue(StringRef(KeyStart, KeyEnd - KeyStart)); + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + void erase(iterator I) { + MapEntryTy &V = *I; + remove(&V); + V.Destroy(Allocator); + } + + bool erase(StringRef Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } + + ~StringMap() { + clear(); + free(TheTable); + } +}; + + +template +class StringMapConstIterator { +protected: + StringMapImpl::ItemBucket *Ptr; +public: + typedef StringMapEntry value_type; + + explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + const value_type &operator*() const { + return *static_cast*>(Ptr->Item); + } + const value_type *operator->() const { + return static_cast*>(Ptr->Item); + } + + bool operator==(const StringMapConstIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const StringMapConstIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline StringMapConstIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + StringMapConstIterator operator++(int) { // Postincrement + StringMapConstIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template +class StringMapIterator : public StringMapConstIterator { +public: + explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : StringMapConstIterator(Bucket, NoAdvance) { + } + StringMapEntry &operator*() const { + return *static_cast*>(this->Ptr->Item); + } + StringMapEntry *operator->() const { + return static_cast*>(this->Ptr->Item); + } +}; + +} + +#endif diff --git a/final/include/llvm/ADT/StringRef.h b/final/include/llvm/ADT/StringRef.h new file mode 100644 index 00000000000..1766d2b9f2d --- /dev/null +++ b/final/include/llvm/ADT/StringRef.h @@ -0,0 +1,458 @@ +//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGREF_H +#define LLVM_ADT_STRINGREF_H + +#include +#include +#include +#include + +namespace llvm { + template + class SmallVectorImpl; + class APInt; + + /// StringRef - Represent a constant reference to a string, i.e. a character + /// array and a length, which need not be null terminated. + /// + /// This class does not own the string data, it is expected to be used in + /// situations where the character data resides in some other buffer, whose + /// lifetime extends past that of the StringRef. For this reason, it is not in + /// general safe to store a StringRef. + class StringRef { + public: + typedef const char *iterator; + typedef const char *const_iterator; + static const size_t npos = ~size_t(0); + typedef size_t size_type; + + private: + /// The start of the string, in an external buffer. + const char *Data; + + /// The length of the string. + size_t Length; + + // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min() + // Changing the arg of min to be an integer, instead of a reference to an + // integer works around this bug. + static size_t min(size_t a, size_t b) { return a < b ? a : b; } + static size_t max(size_t a, size_t b) { return a > b ? a : b; } + + public: + /// @name Constructors + /// @{ + + /// Construct an empty string ref. + /*implicit*/ StringRef() : Data(0), Length(0) {} + + /// Construct a string ref from a cstring. + /*implicit*/ StringRef(const char *Str) + : Data(Str), Length(::strlen(Str)) {} + + /// Construct a string ref from a pointer and length. + /*implicit*/ StringRef(const char *data, size_t length) + : Data(data), Length(length) {} + + /// Construct a string ref from an std::string. + /*implicit*/ StringRef(const std::string &Str) + : Data(Str.data()), Length(Str.length()) {} + + /// @} + /// @name Iterators + /// @{ + + iterator begin() const { return Data; } + + iterator end() const { return Data + Length; } + + /// @} + /// @name String Operations + /// @{ + + /// data - Get a pointer to the start of the string (which may not be null + /// terminated). + const char *data() const { return Data; } + + /// empty - Check if the string is empty. + bool empty() const { return Length == 0; } + + /// size - Get the string size. + size_t size() const { return Length; } + + /// front - Get the first character in the string. + char front() const { + assert(!empty()); + return Data[0]; + } + + /// back - Get the last character in the string. + char back() const { + assert(!empty()); + return Data[Length-1]; + } + + /// equals - Check for string equality, this is more efficient than + /// compare() when the relative ordering of inequal strings isn't needed. + bool equals(StringRef RHS) const { + return (Length == RHS.Length && + memcmp(Data, RHS.Data, RHS.Length) == 0); + } + + /// equals_lower - Check for string equality, ignoring case. + bool equals_lower(StringRef RHS) const { + return Length == RHS.Length && compare_lower(RHS) == 0; + } + + /// compare - Compare two strings; the result is -1, 0, or 1 if this string + /// is lexicographically less than, equal to, or greater than the \arg RHS. + int compare(StringRef RHS) const { + // Check the prefix for a mismatch. + if (int Res = memcmp(Data, RHS.Data, min(Length, RHS.Length))) + return Res < 0 ? -1 : 1; + + // Otherwise the prefixes match, so we only need to check the lengths. + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; + } + + /// compare_lower - Compare two strings, ignoring case. + int compare_lower(StringRef RHS) const; + + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const; + + /// \brief Determine the edit distance between this string and another + /// string. + /// + /// \param Other the string to compare this string against. + /// + /// \param AllowReplacements whether to allow character + /// replacements (change one character into another) as a single + /// operation, rather than as two operations (an insertion and a + /// removal). + /// + /// \param MaxEditDistance If non-zero, the maximum edit distance that + /// this routine is allowed to compute. If the edit distance will exceed + /// that maximum, returns \c MaxEditDistance+1. + /// + /// \returns the minimum number of character insertions, removals, + /// or (if \p AllowReplacements is \c true) replacements needed to + /// transform one of the given strings into the other. If zero, + /// the strings are identical. + unsigned edit_distance(StringRef Other, bool AllowReplacements = true, + unsigned MaxEditDistance = 0); + + /// str - Get the contents as an std::string. + std::string str() const { + if (Data == 0) return std::string(); + return std::string(Data, Length); + } + + /// @} + /// @name Operator Overloads + /// @{ + + char operator[](size_t Index) const { + assert(Index < Length && "Invalid index!"); + return Data[Index]; + } + + /// @} + /// @name Type Conversions + /// @{ + + operator std::string() const { + return str(); + } + + /// @} + /// @name String Predicates + /// @{ + + /// startswith - Check if this string starts with the given \arg Prefix. + bool startswith(StringRef Prefix) const { + return Length >= Prefix.Length && + memcmp(Data, Prefix.Data, Prefix.Length) == 0; + } + + /// endswith - Check if this string ends with the given \arg Suffix. + bool endswith(StringRef Suffix) const { + return Length >= Suffix.Length && + memcmp(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0; + } + + /// @} + /// @name String Searching + /// @{ + + /// find - Search for the first character \arg C in the string. + /// + /// \return - The index of the first occurrence of \arg C, or npos if not + /// found. + size_t find(char C, size_t From = 0) const { + for (size_t i = min(From, Length), e = Length; i != e; ++i) + if (Data[i] == C) + return i; + return npos; + } + + /// find - Search for the first string \arg Str in the string. + /// + /// \return - The index of the first occurrence of \arg Str, or npos if not + /// found. + size_t find(StringRef Str, size_t From = 0) const; + + /// rfind - Search for the last character \arg C in the string. + /// + /// \return - The index of the last occurrence of \arg C, or npos if not + /// found. + size_t rfind(char C, size_t From = npos) const { + From = min(From, Length); + size_t i = From; + while (i != 0) { + --i; + if (Data[i] == C) + return i; + } + return npos; + } + + /// rfind - Search for the last string \arg Str in the string. + /// + /// \return - The index of the last occurrence of \arg Str, or npos if not + /// found. + size_t rfind(StringRef Str) const; + + /// find_first_of - Find the first character in the string that is \arg C, + /// or npos if not found. Same as find. + size_type find_first_of(char C, size_t From = 0) const { + return find(C, From); + } + + /// find_first_of - Find the first character in the string that is in \arg + /// Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_first_of(StringRef Chars, size_t From = 0) const; + + /// find_first_not_of - Find the first character in the string that is not + /// \arg C or npos if not found. + size_type find_first_not_of(char C, size_t From = 0) const; + + /// find_first_not_of - Find the first character in the string that is not + /// in the string \arg Chars, or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_first_not_of(StringRef Chars, size_t From = 0) const; + + /// find_last_of - Find the last character in the string that is \arg C, or + /// npos if not found. + size_type find_last_of(char C, size_t From = npos) const { + return rfind(C, From); + } + + /// find_last_of - Find the last character in the string that is in \arg C, + /// or npos if not found. + /// + /// Note: O(size() + Chars.size()) + size_type find_last_of(StringRef Chars, size_t From = npos) const; + + /// @} + /// @name Helpful Algorithms + /// @{ + + /// count - Return the number of occurrences of \arg C in the string. + size_t count(char C) const { + size_t Count = 0; + for (size_t i = 0, e = Length; i != e; ++i) + if (Data[i] == C) + ++Count; + return Count; + } + + /// count - Return the number of non-overlapped occurrences of \arg Str in + /// the string. + size_t count(StringRef Str) const; + + /// getAsInteger - Parse the current string as an integer of the specified + /// radix. If Radix is specified as zero, this does radix autosensing using + /// extended C rules: 0 is octal, 0x is hex, 0b is binary. + /// + /// If the string is invalid or if only a subset of the string is valid, + /// this returns true to signify the error. The string is considered + /// erroneous if empty. + /// + bool getAsInteger(unsigned Radix, long long &Result) const; + bool getAsInteger(unsigned Radix, unsigned long long &Result) const; + bool getAsInteger(unsigned Radix, int &Result) const; + bool getAsInteger(unsigned Radix, unsigned &Result) const; + + // TODO: Provide overloads for int/unsigned that check for overflow. + + /// getAsInteger - Parse the current string as an integer of the + /// specified radix, or of an autosensed radix if the radix given + /// is 0. The current value in Result is discarded, and the + /// storage is changed to be wide enough to store the parsed + /// integer. + /// + /// Returns true if the string does not solely consist of a valid + /// non-empty number in the appropriate base. + /// + /// APInt::fromString is superficially similar but assumes the + /// string is well-formed in the given radix. + bool getAsInteger(unsigned Radix, APInt &Result) const; + + /// @} + /// @name Substring Operations + /// @{ + + /// substr - Return a reference to the substring from [Start, Start + N). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param N - The number of characters to included in the substring. If N + /// exceeds the number of characters remaining in the string, the string + /// suffix (starting with \arg Start) will be returned. + StringRef substr(size_t Start, size_t N = npos) const { + Start = min(Start, Length); + return StringRef(Data + Start, min(N, Length - Start)); + } + + /// slice - Return a reference to the substring from [Start, End). + /// + /// \param Start - The index of the starting character in the substring; if + /// the index is npos or greater than the length of the string then the + /// empty substring will be returned. + /// + /// \param End - The index following the last character to include in the + /// substring. If this is npos, or less than \arg Start, or exceeds the + /// number of characters remaining in the string, the string suffix + /// (starting with \arg Start) will be returned. + StringRef slice(size_t Start, size_t End) const { + Start = min(Start, Length); + End = min(max(Start, End), Length); + return StringRef(Data + Start, End - Start); + } + + /// split - Split into two substrings around the first occurrence of a + /// separator character. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + std::pair split(char Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// split - Split into two substrings around the first occurrence of a + /// separator string. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// maximal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + std::pair split(StringRef Separator) const { + size_t Idx = find(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + + /// split - Split into substrings around the occurrences of a separator + /// string. + /// + /// Each substring is stored in \arg A. If \arg MaxSplit is >= 0, at most + /// \arg MaxSplit splits are done and consequently <= \arg MaxSplit + /// elements are added to A. + /// If \arg KeepEmpty is false, empty strings are not added to \arg A. They + /// still count when considering \arg MaxSplit + /// An useful invariant is that + /// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true + /// + /// \param A - Where to put the substrings. + /// \param Separator - The string to split on. + /// \param MaxSplit - The maximum number of times the string is split. + /// \param KeepEmpty - True if empty substring should be added. + void split(SmallVectorImpl &A, + StringRef Separator, int MaxSplit = -1, + bool KeepEmpty = true) const; + + /// rsplit - Split into two substrings around the last occurrence of a + /// separator character. + /// + /// If \arg Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \arg Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The character to split on. + /// \return - The split substrings. + std::pair rsplit(char Separator) const { + size_t Idx = rfind(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + } + + /// @} + }; + + /// @name StringRef Comparison Operators + /// @{ + + inline bool operator==(StringRef LHS, StringRef RHS) { + return LHS.equals(RHS); + } + + inline bool operator!=(StringRef LHS, StringRef RHS) { + return !(LHS == RHS); + } + + inline bool operator<(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == -1; + } + + inline bool operator<=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != 1; + } + + inline bool operator>(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) == 1; + } + + inline bool operator>=(StringRef LHS, StringRef RHS) { + return LHS.compare(RHS) != -1; + } + + /// @} + + // StringRefs can be treated like a POD type. + template struct isPodLike; + template <> struct isPodLike { static const bool value = true; }; + +} + +#endif diff --git a/final/include/llvm/ADT/StringSet.h b/final/include/llvm/ADT/StringSet.h new file mode 100644 index 00000000000..9c55f6b70e3 --- /dev/null +++ b/final/include/llvm/ADT/StringSet.h @@ -0,0 +1,38 @@ +//===--- StringSet.h - The LLVM Compiler Driver -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// StringSet - A set-like wrapper for the StringMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGSET_H +#define LLVM_ADT_STRINGSET_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { + + /// StringSet - A wrapper for StringMap that provides set-like + /// functionality. Only insert() and count() methods are used by my + /// code. + template + class StringSet : public llvm::StringMap { + typedef llvm::StringMap base; + public: + bool insert(StringRef InLang) { + assert(!InLang.empty()); + const char *KeyStart = InLang.data(); + const char *KeyEnd = KeyStart + InLang.size(); + return base::insert(llvm::StringMapEntry:: + Create(KeyStart, KeyEnd, base::getAllocator(), '+')); + } + }; +} + +#endif // LLVM_ADT_STRINGSET_H diff --git a/final/include/llvm/ADT/StringSwitch.h b/final/include/llvm/ADT/StringSwitch.h new file mode 100644 index 00000000000..74805830d85 --- /dev/null +++ b/final/include/llvm/ADT/StringSwitch.h @@ -0,0 +1,126 @@ +//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/ +// +// 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 StringSwitch template, which mimics a switch() +// statement whose cases are string literals. +// +//===----------------------------------------------------------------------===/ +#ifndef LLVM_ADT_STRINGSWITCH_H +#define LLVM_ADT_STRINGSWITCH_H + +#include "llvm/ADT/StringRef.h" +#include +#include + +namespace llvm { + +/// \brief A switch()-like statement whose cases are string literals. +/// +/// The StringSwitch class is a simple form of a switch() statement that +/// determines whether the given string matches one of the given string +/// literals. The template type parameter \p T is the type of the value that +/// will be returned from the string-switch expression. For example, +/// the following code switches on the name of a color in \c argv[i]: +/// +/// \code +/// Color color = StringSwitch(argv[i]) +/// .Case("red", Red) +/// .Case("orange", Orange) +/// .Case("yellow", Yellow) +/// .Case("green", Green) +/// .Case("blue", Blue) +/// .Case("indigo", Indigo) +/// .Cases("violet", "purple", Violet) +/// .Default(UnknownColor); +/// \endcode +template +class StringSwitch { + /// \brief The string we are matching. + StringRef Str; + + /// \brief The pointer to the result of this switch statement, once known, + /// null before that. + const T *Result; + +public: + explicit StringSwitch(StringRef Str) + : Str(Str), Result(0) { } + + template + StringSwitch& Case(const char (&S)[N], const T& Value) { + if (!Result && N-1 == Str.size() && + (std::memcmp(S, Str.data(), N-1) == 0)) { + Result = &Value; + } + + return *this; + } + + template + StringSwitch& EndsWith(const char (&S)[N], const T &Value) { + if (!Result && Str.size() >= N-1 && + std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) { + Result = &Value; + } + + return *this; + } + + template + StringSwitch& StartsWith(const char (&S)[N], const T &Value) { + if (!Result && Str.size() >= N-1 && + std::memcmp(S, Str.data(), N-1) == 0) { + Result = &Value; + } + + return *this; + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const T& Value) { + return Case(S0, Value).Case(S1, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value); + } + + template + StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1], + const char (&S2)[N2], const char (&S3)[N3], + const char (&S4)[N4], const T& Value) { + return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value) + .Case(S4, Value); + } + + R Default(const T& Value) const { + if (Result) + return *Result; + + return Value; + } + + operator R() const { + assert(Result && "Fell off the end of a string-switch"); + return *Result; + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_STRINGSWITCH_H diff --git a/final/include/llvm/ADT/Trie.h b/final/include/llvm/ADT/Trie.h new file mode 100644 index 00000000000..6b150c8fffa --- /dev/null +++ b/final/include/llvm/ADT/Trie.h @@ -0,0 +1,336 @@ +//===- llvm/ADT/Trie.h ---- Generic trie structure --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines a generic trie structure. The trie structure +// is immutable after creation, but the payload contained within it is not. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIE_H +#define LLVM_ADT_TRIE_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/DOTGraphTraits.h" + +#include +#include + +namespace llvm { + +// FIXME: +// - Labels are usually small, maybe it's better to use SmallString +// - Should we use char* during construction? +// - Should we templatize Empty with traits-like interface? + +template +class Trie { + friend class GraphTraits >; + friend class DOTGraphTraits >; +public: + class Node { + friend class Trie; + + public: + typedef std::vector NodeVectorType; + typedef typename NodeVectorType::iterator iterator; + typedef typename NodeVectorType::const_iterator const_iterator; + + private: + enum QueryResult { + Same = -3, + StringIsPrefix = -2, + LabelIsPrefix = -1, + DontMatch = 0, + HaveCommonPart + }; + + struct NodeCmp { + bool operator() (Node* N1, Node* N2) { + return (N1->Label[0] < N2->Label[0]); + } + bool operator() (Node* N, char Id) { + return (N->Label[0] < Id); + } + }; + + std::string Label; + Payload Data; + NodeVectorType Children; + + // Do not implement + Node(const Node&); + Node& operator=(const Node&); + + inline void addEdge(Node* N) { + if (Children.empty()) + Children.push_back(N); + else { + iterator I = std::lower_bound(Children.begin(), Children.end(), + N, NodeCmp()); + // FIXME: no dups are allowed + Children.insert(I, N); + } + } + + inline void setEdge(Node* N) { + char Id = N->Label[0]; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + assert(I != Children.end() && "Node does not exists!"); + *I = N; + } + + QueryResult query(const std::string& s) const { + unsigned i, l; + unsigned l1 = s.length(); + unsigned l2 = Label.length(); + + // Find the length of common part + l = std::min(l1, l2); + i = 0; + while ((i < l) && (s[i] == Label[i])) + ++i; + + if (i == l) { // One is prefix of another, find who is who + if (l1 == l2) + return Same; + else if (i == l1) + return StringIsPrefix; + else + return LabelIsPrefix; + } else // s and Label have common (possible empty) part, return its length + return (QueryResult)i; + } + + public: + inline explicit Node(const Payload& data, const std::string& label = ""): + Label(label), Data(data) { } + + inline const Payload& data() const { return Data; } + inline void setData(const Payload& data) { Data = data; } + + inline const std::string& label() const { return Label; } + +#if 0 + inline void dump() { + llvm::cerr << "Node: " << this << "\n" + << "Label: " << Label << "\n" + << "Children:\n"; + + for (iterator I = Children.begin(), E = Children.end(); I != E; ++I) + llvm::cerr << (*I)->Label << "\n"; + } +#endif + + inline Node* getEdge(char Id) { + Node* fNode = NULL; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + if (I != Children.end() && (*I)->Label[0] == Id) + fNode = *I; + + return fNode; + } + + inline iterator begin() { return Children.begin(); } + inline const_iterator begin() const { return Children.begin(); } + inline iterator end () { return Children.end(); } + inline const_iterator end () const { return Children.end(); } + + inline size_t size () const { return Children.size(); } + inline bool empty() const { return Children.empty(); } + inline const Node* &front() const { return Children.front(); } + inline Node* &front() { return Children.front(); } + inline const Node* &back() const { return Children.back(); } + inline Node* &back() { return Children.back(); } + + }; + +private: + std::vector Nodes; + Payload Empty; + + inline Node* addNode(const Payload& data, const std::string label = "") { + Node* N = new Node(data, label); + Nodes.push_back(N); + return N; + } + + inline Node* splitEdge(Node* N, char Id, size_t index) { + Node* eNode = N->getEdge(Id); + assert(eNode && "Node doesn't exist"); + + const std::string &l = eNode->Label; + assert(index > 0 && index < l.length() && "Trying to split too far!"); + std::string l1 = l.substr(0, index); + std::string l2 = l.substr(index); + + Node* nNode = addNode(Empty, l1); + N->setEdge(nNode); + + eNode->Label = l2; + nNode->addEdge(eNode); + + return nNode; + } + + // Do not implement + Trie(const Trie&); + Trie& operator=(const Trie&); + +public: + inline explicit Trie(const Payload& empty):Empty(empty) { + addNode(Empty); + } + inline ~Trie() { + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + delete Nodes[i]; + } + + inline Node* getRoot() const { return Nodes[0]; } + + bool addString(const std::string& s, const Payload& data); + const Payload& lookup(const std::string& s) const; + +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +bool Trie::addString(const std::string& s, const Payload& data) { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + case Node::StringIsPrefix: + // Currently we don't allow to have two strings in the trie one + // being a prefix of another. This should be fixed. + assert(0 && "FIXME!"); + return false; + case Node::DontMatch: + assert(0 && "Impossible!"); + return false; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + nNode = splitEdge(cNode, Id, r); + tNode = addNode(data, s1.substr(r)); + nNode->addEdge(tNode); + } + } else { + tNode = addNode(data, s1); + cNode->addEdge(tNode); + } + } + + return true; +} + +template +const Payload& Trie::lookup(const std::string& s) const { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + tNode = nNode; + break; + case Node::StringIsPrefix: + return Empty; + case Node::DontMatch: + assert(0 && "Impossible!"); + return Empty; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + return Empty; + } + } else + return Empty; + } + + return tNode->data(); +} + +template +struct GraphTraits > { + typedef Trie TrieType; + typedef typename TrieType::Node NodeType; + typedef typename NodeType::iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const TrieType& T) { + return T.getRoot(); + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + + typedef typename std::vector::const_iterator nodes_iterator; + + static inline nodes_iterator nodes_begin(const TrieType& G) { + return G.Nodes.begin(); + } + static inline nodes_iterator nodes_end(const TrieType& G) { + return G.Nodes.end(); + } + +}; + +template +struct DOTGraphTraits > : public DefaultDOTGraphTraits { + typedef typename Trie::Node NodeType; + typedef typename GraphTraits >::ChildIteratorType EdgeIter; + + static std::string getGraphName(const Trie& T) { + return "Trie"; + } + + static std::string getNodeLabel(NodeType* Node, const Trie& T) { + if (T.getRoot() == Node) + return ""; + else + return Node->label(); + } + + static std::string getEdgeSourceLabel(NodeType* Node, EdgeIter I) { + NodeType* N = *I; + return N->label().substr(0, 1); + } + + static std::string getNodeAttributes(const NodeType* Node, + const Trie& T) { + if (Node->data() != T.Empty) + return "color=blue"; + + return ""; + } + +}; + +} // end of llvm namespace + +#endif // LLVM_ADT_TRIE_H diff --git a/final/include/llvm/ADT/Triple.h b/final/include/llvm/ADT/Triple.h new file mode 100644 index 00000000000..e6dcc23258f --- /dev/null +++ b/final/include/llvm/ADT/Triple.h @@ -0,0 +1,333 @@ +//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIPLE_H +#define LLVM_ADT_TRIPLE_H + +#include "llvm/ADT/StringRef.h" +#include + +// Some system headers or GCC predefined macros conflict with identifiers in +// this file. Undefine them here. +#undef mips +#undef sparc + +namespace llvm { +class StringRef; +class Twine; + +/// Triple - Helper class for working with target triples. +/// +/// Target triples are strings in the canonical form: +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM +/// or +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT +/// +/// This class is used for clients which want to support arbitrary +/// target triples, but also want to implement certain special +/// behavior for particular targets. This class isolates the mapping +/// from the components of the target triple to well known IDs. +/// +/// At its core the Triple class is designed to be a wrapper for a triple +/// string; the constructor does not change or normalize the triple string. +/// Clients that need to handle the non-canonical triples that users often +/// specify should use the normalize method. +/// +/// See autoconf/config.guess for a glimpse into what triples look like in +/// practice. +class Triple { +public: + enum ArchType { + UnknownArch, + + alpha, // Alpha: alpha + arm, // ARM; arm, armv.*, xscale + bfin, // Blackfin: bfin + cellspu, // CellSPU: spu, cellspu + mips, // MIPS: mips, mipsallegrex + mipsel, // MIPSEL: mipsel, mipsallegrexel, psp + msp430, // MSP430: msp430 + ppc, // PPC: powerpc + ppc64, // PPC64: powerpc64, ppu + sparc, // Sparc: sparc + sparcv9, // Sparcv9: Sparcv9 + systemz, // SystemZ: s390x + tce, // TCE (http://tce.cs.tut.fi/): tce + thumb, // Thumb: thumb, thumbv.* + x86, // X86: i[3-9]86 + x86_64, // X86-64: amd64, x86_64 + xcore, // XCore: xcore + mblaze, // MBlaze: mblaze + ptx, // PTX: ptx + + InvalidArch + }; + enum VendorType { + UnknownVendor, + + Apple, + PC + }; + enum OSType { + UnknownOS, + + AuroraUX, + Cygwin, + Darwin, + DragonFly, + FreeBSD, + Linux, + Lv2, // PS3 + MinGW32, // i*86-pc-mingw32, *-w64-mingw32 + NetBSD, + OpenBSD, + Psp, + Solaris, + Win32, + Haiku, + Minix + }; + enum EnvironmentType { + UnknownEnvironment, + + GNU, + GNUEABI, + EABI, + MachO + }; + +private: + std::string Data; + + /// The parsed arch type (or InvalidArch if uninitialized). + mutable ArchType Arch; + + /// The parsed vendor type. + mutable VendorType Vendor; + + /// The parsed OS type. + mutable OSType OS; + + /// The parsed Environment type. + mutable EnvironmentType Environment; + + bool isInitialized() const { return Arch != InvalidArch; } + static ArchType ParseArch(StringRef ArchName); + static VendorType ParseVendor(StringRef VendorName); + static OSType ParseOS(StringRef OSName); + static EnvironmentType ParseEnvironment(StringRef EnvironmentName); + void Parse() const; + +public: + /// @name Constructors + /// @{ + + Triple() : Data(), Arch(InvalidArch) {} + explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {} + explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + } + + explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr, + StringRef EnvironmentStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + Data += '-'; + Data += EnvironmentStr; + } + + /// @} + /// @name Normalization + /// @{ + + /// normalize - Turn an arbitrary machine specification into the canonical + /// triple form (or something sensible that the Triple class understands if + /// nothing better can reasonably be done). In particular, it handles the + /// common case in which otherwise valid components are in the wrong order. + static std::string normalize(StringRef Str); + + /// @} + /// @name Typed Component Access + /// @{ + + /// getArch - Get the parsed architecture type of this triple. + ArchType getArch() const { + if (!isInitialized()) Parse(); + return Arch; + } + + /// getVendor - Get the parsed vendor type of this triple. + VendorType getVendor() const { + if (!isInitialized()) Parse(); + return Vendor; + } + + /// getOS - Get the parsed operating system type of this triple. + OSType getOS() const { + if (!isInitialized()) Parse(); + return OS; + } + + /// hasEnvironment - Does this triple have the optional environment + /// (fourth) component? + bool hasEnvironment() const { + return getEnvironmentName() != ""; + } + + /// getEnvironment - Get the parsed environment type of this triple. + EnvironmentType getEnvironment() const { + if (!isInitialized()) Parse(); + return Environment; + } + + /// @} + /// @name Direct Component Access + /// @{ + + const std::string &str() const { return Data; } + + const std::string &getTriple() const { return Data; } + + /// getArchName - Get the architecture (first) component of the + /// triple. + StringRef getArchName() const; + + /// getVendorName - Get the vendor (second) component of the triple. + StringRef getVendorName() const; + + /// getOSName - Get the operating system (third) component of the + /// triple. + StringRef getOSName() const; + + /// getEnvironmentName - Get the optional environment (fourth) + /// component of the triple, or "" if empty. + StringRef getEnvironmentName() const; + + /// getOSAndEnvironmentName - Get the operating system and optional + /// environment components as a single string (separated by a '-' + /// if the environment component is present). + StringRef getOSAndEnvironmentName() const; + + + /// getDarwinNumber - Parse the 'darwin number' out of the specific target + /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is + /// not defined, return 0's. This requires that the triple have an OSType of + /// darwin before it is called. + void getDarwinNumber(unsigned &Maj, unsigned &Min, unsigned &Revision) const; + + /// getDarwinMajorNumber - Return just the major version number, this is + /// specialized because it is a common query. + unsigned getDarwinMajorNumber() const { + unsigned Maj, Min, Rev; + getDarwinNumber(Maj, Min, Rev); + return Maj; + } + + /// @} + /// @name Mutators + /// @{ + + /// setArch - Set the architecture (first) component of the triple + /// to a known type. + void setArch(ArchType Kind); + + /// setVendor - Set the vendor (second) component of the triple to a + /// known type. + void setVendor(VendorType Kind); + + /// setOS - Set the operating system (third) component of the triple + /// to a known type. + void setOS(OSType Kind); + + /// setEnvironment - Set the environment (fourth) component of the triple + /// to a known type. + void setEnvironment(EnvironmentType Kind); + + /// setTriple - Set all components to the new triple \arg Str. + void setTriple(const Twine &Str); + + /// setArchName - Set the architecture (first) component of the + /// triple by name. + void setArchName(StringRef Str); + + /// setVendorName - Set the vendor (second) component of the triple + /// by name. + void setVendorName(StringRef Str); + + /// setOSName - Set the operating system (third) component of the + /// triple by name. + void setOSName(StringRef Str); + + /// setEnvironmentName - Set the optional environment (fourth) + /// component of the triple by name. + void setEnvironmentName(StringRef Str); + + /// setOSAndEnvironmentName - Set the operating system and optional + /// environment components with a single string. + void setOSAndEnvironmentName(StringRef Str); + + /// getArchNameForAssembler - Get an architecture name that is understood by + /// the target assembler. + const char *getArchNameForAssembler(); + + /// @} + /// @name Static helpers for IDs. + /// @{ + + /// getArchTypeName - Get the canonical name for the \arg Kind + /// architecture. + static const char *getArchTypeName(ArchType Kind); + + /// getArchTypePrefix - Get the "prefix" canonical name for the \arg Kind + /// architecture. This is the prefix used by the architecture specific + /// builtins, and is suitable for passing to \see + /// Intrinsic::getIntrinsicForGCCBuiltin(). + /// + /// \return - The architecture prefix, or 0 if none is defined. + static const char *getArchTypePrefix(ArchType Kind); + + /// getVendorTypeName - Get the canonical name for the \arg Kind + /// vendor. + static const char *getVendorTypeName(VendorType Kind); + + /// getOSTypeName - Get the canonical name for the \arg Kind operating + /// system. + static const char *getOSTypeName(OSType Kind); + + /// getEnvironmentTypeName - Get the canonical name for the \arg Kind + /// environment. + static const char *getEnvironmentTypeName(EnvironmentType Kind); + + /// @} + /// @name Static helpers for converting alternate architecture names. + /// @{ + + /// getArchTypeForLLVMName - The canonical type for the given LLVM + /// architecture name (e.g., "x86"). + static ArchType getArchTypeForLLVMName(StringRef Str); + + /// getArchTypeForDarwinArchName - Get the architecture type for a "Darwin" + /// architecture name, for example as accepted by "gcc -arch" (see also + /// arch(3)). + static ArchType getArchTypeForDarwinArchName(StringRef Str); + + /// @} +}; + +} // End llvm namespace + + +#endif diff --git a/final/include/llvm/ADT/Twine.h b/final/include/llvm/ADT/Twine.h new file mode 100644 index 00000000000..ab8d3653e33 --- /dev/null +++ b/final/include/llvm/ADT/Twine.h @@ -0,0 +1,465 @@ +//===-- Twine.h - Fast Temporary String Concatenation -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TWINE_H +#define LLVM_ADT_TWINE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { + template + class SmallVectorImpl; + class StringRef; + class raw_ostream; + + /// Twine - A lightweight data structure for efficiently representing the + /// concatenation of temporary values as strings. + /// + /// A Twine is a kind of rope, it represents a concatenated string using a + /// binary-tree, where the string is the preorder of the nodes. Since the + /// Twine can be efficiently rendered into a buffer when its result is used, + /// it avoids the cost of generating temporary values for intermediate string + /// results -- particularly in cases when the Twine result is never + /// required. By explicitly tracking the type of leaf nodes, we can also avoid + /// the creation of temporary strings for conversions operations (such as + /// appending an integer to a string). + /// + /// A Twine is not intended for use directly and should not be stored, its + /// implementation relies on the ability to store pointers to temporary stack + /// objects which may be deallocated at the end of a statement. Twines should + /// only be used accepted as const references in arguments, when an API wishes + /// to accept possibly-concatenated strings. + /// + /// Twines support a special 'null' value, which always concatenates to form + /// itself, and renders as an empty string. This can be returned from APIs to + /// effectively nullify any concatenations performed on the result. + /// + /// \b Implementation \n + /// + /// Given the nature of a Twine, it is not possible for the Twine's + /// concatenation method to construct interior nodes; the result must be + /// represented inside the returned value. For this reason a Twine object + /// actually holds two values, the left- and right-hand sides of a + /// concatenation. We also have nullary Twine objects, which are effectively + /// sentinel values that represent empty strings. + /// + /// Thus, a Twine can effectively have zero, one, or two children. The \see + /// isNullary(), \see isUnary(), and \see isBinary() predicates exist for + /// testing the number of children. + /// + /// We maintain a number of invariants on Twine objects (FIXME: Why): + /// - Nullary twines are always represented with their Kind on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - Unary twines are always represented with the value on the left-hand + /// side, and the Empty kind on the right-hand side. + /// - If a Twine has another Twine as a child, that child should always be + /// binary (otherwise it could have been folded into the parent). + /// + /// These invariants are check by \see isValid(). + /// + /// \b Efficiency Considerations \n + /// + /// The Twine is designed to yield efficient and small code for common + /// situations. For this reason, the concat() method is inlined so that + /// concatenations of leaf nodes can be optimized into stores directly into a + /// single stack allocated object. + /// + /// In practice, not all compilers can be trusted to optimize concat() fully, + /// so we provide two additional methods (and accompanying operator+ + /// overloads) to guarantee that particularly important cases (cstring plus + /// StringRef) codegen as desired. + class Twine { + /// NodeKind - Represent the type of an argument. + enum NodeKind { + /// An empty string; the result of concatenating anything with it is also + /// empty. + NullKind, + + /// The empty string. + EmptyKind, + + /// A pointer to a Twine instance. + TwineKind, + + /// A pointer to a C string instance. + CStringKind, + + /// A pointer to an std::string instance. + StdStringKind, + + /// A pointer to a StringRef instance. + StringRefKind, + + /// An unsigned int value reinterpreted as a pointer, to render as an + /// unsigned decimal integer. + DecUIKind, + + /// An int value reinterpreted as a pointer, to render as a signed + /// decimal integer. + DecIKind, + + /// A pointer to an unsigned long value, to render as an unsigned decimal + /// integer. + DecULKind, + + /// A pointer to a long value, to render as a signed decimal integer. + DecLKind, + + /// A pointer to an unsigned long long value, to render as an unsigned + /// decimal integer. + DecULLKind, + + /// A pointer to a long long value, to render as a signed decimal integer. + DecLLKind, + + /// A pointer to a uint64_t value, to render as an unsigned hexadecimal + /// integer. + UHexKind + }; + + private: + /// LHS - The prefix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + const void *LHS; + /// RHS - The suffix in the concatenation, which may be uninitialized for + /// Null or Empty kinds. + const void *RHS; + /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). + unsigned char LHSKind; + /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). + unsigned char RHSKind; + + private: + /// Construct a nullary twine; the kind must be NullKind or EmptyKind. + explicit Twine(NodeKind Kind) + : LHSKind(Kind), RHSKind(EmptyKind) { + assert(isNullary() && "Invalid kind!"); + } + + /// Construct a binary twine. + explicit Twine(const Twine &_LHS, const Twine &_RHS) + : LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine from explicit values. + explicit Twine(const void *_LHS, NodeKind _LHSKind, + const void *_RHS, NodeKind _RHSKind) + : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { + assert(isValid() && "Invalid twine!"); + } + + /// isNull - Check for the null twine. + bool isNull() const { + return getLHSKind() == NullKind; + } + + /// isEmpty - Check for the empty twine. + bool isEmpty() const { + return getLHSKind() == EmptyKind; + } + + /// isNullary - Check if this is a nullary twine (null or empty). + bool isNullary() const { + return isNull() || isEmpty(); + } + + /// isUnary - Check if this is a unary twine. + bool isUnary() const { + return getRHSKind() == EmptyKind && !isNullary(); + } + + /// isBinary - Check if this is a binary twine. + bool isBinary() const { + return getLHSKind() != NullKind && getRHSKind() != EmptyKind; + } + + /// isValid - Check if this is a valid twine (satisfying the invariants on + /// order and number of arguments). + bool isValid() const { + // Nullary twines always have Empty on the RHS. + if (isNullary() && getRHSKind() != EmptyKind) + return false; + + // Null should never appear on the RHS. + if (getRHSKind() == NullKind) + return false; + + // The RHS cannot be non-empty if the LHS is empty. + if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind) + return false; + + // A twine child should always be binary. + if (getLHSKind() == TwineKind && + !static_cast(LHS)->isBinary()) + return false; + if (getRHSKind() == TwineKind && + !static_cast(RHS)->isBinary()) + return false; + + return true; + } + + /// getLHSKind - Get the NodeKind of the left-hand side. + NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + + /// getRHSKind - Get the NodeKind of the left-hand side. + NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + + /// printOneChild - Print one child from a twine. + void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const; + + /// printOneChildRepr - Print the representation of one child from a twine. + void printOneChildRepr(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const; + + public: + /// @name Constructors + /// @{ + + /// Construct from an empty string. + /*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a C string. + /// + /// We take care here to optimize "" into the empty twine -- this will be + /// optimized out for string constants. This allows Twine arguments have + /// default "" values, without introducing unnecessary string constants. + /*implicit*/ Twine(const char *Str) + : RHSKind(EmptyKind) { + if (Str[0] != '\0') { + LHS = Str; + LHSKind = CStringKind; + } else + LHSKind = EmptyKind; + + assert(isValid() && "Invalid twine!"); + } + + /// Construct from an std::string. + /*implicit*/ Twine(const std::string &Str) + : LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct from a StringRef. + /*implicit*/ Twine(const StringRef &Str) + : LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(unsigned Val) + : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(int Val) + : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(const unsigned long &Val) + : LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(const long &Val) + : LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as an unsigned decimal integer. + explicit Twine(const unsigned long long &Val) + : LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { + } + + /// Construct a twine to print \arg Val as a signed decimal integer. + explicit Twine(const long long &Val) + : LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { + } + + // FIXME: Unfortunately, to make sure this is as efficient as possible we + // need extra binary constructors from particular types. We can't rely on + // the compiler to be smart enough to fold operator+()/concat() down to the + // right thing. Yet. + + /// Construct as the concatenation of a C string and a StringRef. + /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) + : LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Construct as the concatenation of a StringRef and a C string. + /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) + : LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) { + assert(isValid() && "Invalid twine!"); + } + + /// Create a 'null' string, which is an empty string that always + /// concatenates to form another empty string. + static Twine createNull() { + return Twine(NullKind); + } + + /// @} + /// @name Numeric Conversions + /// @{ + + // Construct a twine to print \arg Val as an unsigned hexadecimal integer. + static Twine utohexstr(const uint64_t &Val) { + return Twine(&Val, UHexKind, 0, EmptyKind); + } + + /// @} + /// @name Predicate Operations + /// @{ + + /// isTriviallyEmpty - Check if this twine is trivially empty; a false + /// return value does not necessarily mean the twine is empty. + bool isTriviallyEmpty() const { + return isNullary(); + } + + /// isSingleStringRef - Return true if this twine can be dynamically + /// accessed as a single StringRef value with getSingleStringRef(). + bool isSingleStringRef() const { + if (getRHSKind() != EmptyKind) return false; + + switch (getLHSKind()) { + case EmptyKind: + case CStringKind: + case StdStringKind: + case StringRefKind: + return true; + default: + return false; + } + } + + /// @} + /// @name String Operations + /// @{ + + Twine concat(const Twine &Suffix) const; + + /// @} + /// @name Output & Conversion. + /// @{ + + /// str - Return the twine contents as a std::string. + std::string str() const; + + /// toVector - Write the concatenated string into the given SmallString or + /// SmallVector. + void toVector(SmallVectorImpl &Out) const; + + /// getSingleStringRef - This returns the twine as a single StringRef. This + /// method is only valid if isSingleStringRef() is true. + StringRef getSingleStringRef() const { + assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); + switch (getLHSKind()) { + default: assert(0 && "Out of sync with isSingleStringRef"); + case EmptyKind: return StringRef(); + case CStringKind: return StringRef((const char*)LHS); + case StdStringKind: return StringRef(*(const std::string*)LHS); + case StringRefKind: return *(const StringRef*)LHS; + } + } + + /// toStringRef - This returns the twine as a single StringRef if it can be + /// represented as such. Otherwise the twine is written into the given + /// SmallVector and a StringRef to the SmallVector's data is returned. + StringRef toStringRef(SmallVectorImpl &Out) const; + + /// toNullTerminatedStringRef - This returns the twine as a single null + /// terminated StringRef if it can be represented as such. Otherwise the + /// twine is written into the given SmallVector and a StringRef to the + /// SmallVector's data is returned. + /// + /// The returned StringRef's size does not include the null terminator. + StringRef toNullTerminatedStringRef(SmallVectorImpl &Out) const; + + /// print - Write the concatenated string represented by this twine to the + /// stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Dump the concatenated string represented by this twine to stderr. + void dump() const; + + /// print - Write the representation of this twine to the stream \arg OS. + void printRepr(raw_ostream &OS) const; + + /// dumpRepr - Dump the representation of this twine to stderr. + void dumpRepr() const; + + /// @} + }; + + /// @name Twine Inline Implementations + /// @{ + + inline Twine Twine::concat(const Twine &Suffix) const { + // Concatenation with null is null. + if (isNull() || Suffix.isNull()) + return Twine(NullKind); + + // Concatenation with empty yields the other side. + if (isEmpty()) + return Suffix; + if (Suffix.isEmpty()) + return *this; + + // Otherwise we need to create a new node, taking care to fold in unary + // twines. + const void *NewLHS = this, *NewRHS = &Suffix; + NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; + if (isUnary()) { + NewLHS = LHS; + NewLHSKind = getLHSKind(); + } + if (Suffix.isUnary()) { + NewRHS = Suffix.LHS; + NewRHSKind = Suffix.getLHSKind(); + } + + return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind); + } + + inline Twine operator+(const Twine &LHS, const Twine &RHS) { + return LHS.concat(RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const char *LHS, const StringRef &RHS) { + return Twine(LHS, RHS); + } + + /// Additional overload to guarantee simplified codegen; this is equivalent to + /// concat(). + + inline Twine operator+(const StringRef &LHS, const char *RHS) { + return Twine(LHS, RHS); + } + + inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) { + RHS.print(OS); + return OS; + } + + /// @} +} + +#endif diff --git a/final/include/llvm/ADT/UniqueVector.h b/final/include/llvm/ADT/UniqueVector.h new file mode 100644 index 00000000000..2d02d1ce166 --- /dev/null +++ b/final/include/llvm/ADT/UniqueVector.h @@ -0,0 +1,89 @@ +//===-- llvm/ADT/UniqueVector.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_UNIQUEVECTOR_H +#define LLVM_ADT_UNIQUEVECTOR_H + +#include +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// UniqueVector - This class produces a sequential ID number (base 1) for each +/// unique entry that is added. T is the type of entries in the vector. This +/// class should have an implementation of operator== and of operator<. +/// Entries can be fetched using operator[] with the entry ID. +template class UniqueVector { +private: + // Map - Used to handle the correspondence of entry to ID. + std::map Map; + + // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. + // + std::vector Vector; + +public: + /// insert - Append entry to the vector if it doesn't already exist. Returns + /// the entry's index + 1 to be used as a unique ID. + unsigned insert(const T &Entry) { + // Check if the entry is already in the map. + unsigned &Val = Map[Entry]; + + // See if entry exists, if so return prior ID. + if (Val) return Val; + + // Compute ID for entry. + Val = static_cast(Vector.size()) + 1; + + // Insert in vector. + Vector.push_back(Entry); + return Val; + } + + /// idFor - return the ID for an existing entry. Returns 0 if the entry is + /// not found. + unsigned idFor(const T &Entry) const { + // Search for entry in the map. + typename std::map::const_iterator MI = Map.find(Entry); + + // See if entry exists, if so return ID. + if (MI != Map.end()) return MI->second; + + // No luck. + return 0; + } + + /// operator[] - Returns a reference to the entry with the specified ID. + /// + const T &operator[](unsigned ID) const { + assert(ID-1 < size() && "ID is 0 or out of range!"); + return Vector[ID - 1]; + } + + /// size - Returns the number of entries in the vector. + /// + size_t size() const { return Vector.size(); } + + /// empty - Returns true if the vector is empty. + /// + bool empty() const { return Vector.empty(); } + + /// reset - Clears all the entries. + /// + void reset() { + Map.clear(); + Vector.resize(0, 0); + } +}; + +} // End of namespace llvm + +#endif // LLVM_ADT_UNIQUEVECTOR_H diff --git a/final/include/llvm/ADT/ValueMap.h b/final/include/llvm/ADT/ValueMap.h new file mode 100644 index 00000000000..d1f4e5a0dac --- /dev/null +++ b/final/include/llvm/ADT/ValueMap.h @@ -0,0 +1,368 @@ +//===- llvm/ADT/ValueMap.h - Safe map from Values to data -------*- 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 ValueMap class. ValueMap maps Value* or any subclass +// to an arbitrary other type. It provides the DenseMap interface but updates +// itself to remain safe when keys are RAUWed or deleted. By default, when a +// key is RAUWed from V1 to V2, the old mapping V1->target is removed, and a new +// mapping V2->target is added. If V2 already existed, its old target is +// overwritten. When a key is deleted, its mapping is removed. +// +// You can override a ValueMap's Config parameter to control exactly what +// happens on RAUW and destruction and to get called back on each event. It's +// legal to call back into the ValueMap from a Config's callbacks. Config +// parameters should inherit from ValueMapConfig to get default +// implementations of all the methods ValueMap uses. See ValueMapConfig for +// documentation of the functions you can override. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VALUEMAP_H +#define LLVM_ADT_VALUEMAP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Mutex.h" + +#include + +namespace llvm { + +template +class ValueMapCallbackVH; + +template +class ValueMapIterator; +template +class ValueMapConstIterator; + +/// This class defines the default behavior for configurable aspects of +/// ValueMap<>. User Configs should inherit from this class to be as compatible +/// as possible with future versions of ValueMap. +template +struct ValueMapConfig { + /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's + /// false, the ValueMap will leave the original mapping in place. + enum { FollowRAUW = true }; + + // All methods will be called with a first argument of type ExtraData. The + // default implementations in this class take a templated first argument so + // that users' subclasses can use any type they want without having to + // override all the defaults. + struct ExtraData {}; + + template + static void onRAUW(const ExtraDataT & /*Data*/, KeyT /*Old*/, KeyT /*New*/) {} + template + static void onDelete(const ExtraDataT &/*Data*/, KeyT /*Old*/) {} + + /// Returns a mutex that should be acquired around any changes to the map. + /// This is only acquired from the CallbackVH (and held around calls to onRAUW + /// and onDelete) and not inside other ValueMap methods. NULL means that no + /// mutex is necessary. + template + static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return NULL; } +}; + +/// See the file comment. +template, + typename ValueInfoT = DenseMapInfo > +class ValueMap { + friend class ValueMapCallbackVH; + typedef ValueMapCallbackVH ValueMapCVH; + typedef DenseMap, + ValueInfoT> MapT; + typedef typename Config::ExtraData ExtraData; + MapT Map; + ExtraData Data; + ValueMap(const ValueMap&); // DO NOT IMPLEMENT + ValueMap& operator=(const ValueMap&); // DO NOT IMPLEMENT +public: + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef std::pair value_type; + + explicit ValueMap(unsigned NumInitBuckets = 64) + : Map(NumInitBuckets), Data() {} + explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) + : Map(NumInitBuckets), Data(Data) {} + + ~ValueMap() {} + + typedef ValueMapIterator iterator; + typedef ValueMapConstIterator const_iterator; + inline iterator begin() { return iterator(Map.begin()); } + inline iterator end() { return iterator(Map.end()); } + inline const_iterator begin() const { return const_iterator(Map.begin()); } + inline const_iterator end() const { return const_iterator(Map.end()); } + + bool empty() const { return Map.empty(); } + unsigned size() const { return Map.size(); } + + /// Grow the map so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { Map.resize(Size); } + + void clear() { Map.clear(); } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + return Map.count(Wrap(Val)); + } + + iterator find(const KeyT &Val) { + return iterator(Map.find(Wrap(Val))); + } + const_iterator find(const KeyT &Val) const { + return const_iterator(Map.find(Wrap(Val))); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + return Map.lookup(Wrap(Val)); + } + + // Inserts key,value pair into the map if the key isn't already in the map. + // If the key is already in the map, it returns false and doesn't update the + // value. + std::pair insert(const std::pair &KV) { + std::pair map_result= + Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(map_result.first), map_result.second); + } + + /// insert - Range insertion of pairs. + template + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + + bool erase(const KeyT &Val) { + return Map.erase(Wrap(Val)); + } + void erase(iterator I) { + return Map.erase(I.base()); + } + + value_type& FindAndConstruct(const KeyT &Key) { + return Map.FindAndConstruct(Wrap(Key)); + } + + ValueT &operator[](const KeyT &Key) { + return Map[Wrap(Key)]; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the ValueMap's array of buckets (i.e. either to a key or + /// value in the ValueMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Map.isPointerIntoBucketsArray(Ptr); + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the ValueMap to reallocate. + const void *getPointerIntoBucketsArray() const { + return Map.getPointerIntoBucketsArray(); + } + +private: + // Takes a key being looked up in the map and wraps it into a + // ValueMapCallbackVH, the actual key type of the map. We use a helper + // function because ValueMapCVH is constructed with a second parameter. + ValueMapCVH Wrap(KeyT key) const { + // The only way the resulting CallbackVH could try to modify *this (making + // the const_cast incorrect) is if it gets inserted into the map. But then + // this function must have been called from a non-const method, making the + // const_cast ok. + return ValueMapCVH(key, const_cast(this)); + } +}; + +// This CallbackVH updates its ValueMap when the contained Value changes, +// according to the user's preferences expressed through the Config object. +template +class ValueMapCallbackVH : public CallbackVH { + friend class ValueMap; + friend struct DenseMapInfo; + typedef ValueMap ValueMapT; + typedef typename llvm::remove_pointer::type KeySansPointerT; + + ValueMapT *Map; + + ValueMapCallbackVH(KeyT Key, ValueMapT *Map) + : CallbackVH(const_cast(static_cast(Key))), + Map(Map) {} + +public: + KeyT Unwrap() const { return cast_or_null(getValPtr()); } + + virtual void deleted() { + // Make a copy that won't get changed even when *this is destroyed. + ValueMapCallbackVH Copy(*this); + sys::Mutex *M = Config::getMutex(Copy.Map->Data); + if (M) + M->acquire(); + Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. + Copy.Map->Map.erase(Copy); // Definitely destroys *this. + if (M) + M->release(); + } + virtual void allUsesReplacedWith(Value *new_key) { + assert(isa(new_key) && + "Invalid RAUW on key of ValueMap<>"); + // Make a copy that won't get changed even when *this is destroyed. + ValueMapCallbackVH Copy(*this); + sys::Mutex *M = Config::getMutex(Copy.Map->Data); + if (M) + M->acquire(); + + KeyT typed_new_key = cast(new_key); + // Can destroy *this: + Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key); + if (Config::FollowRAUW) { + typename ValueMapT::MapT::iterator I = Copy.Map->Map.find(Copy); + // I could == Copy.Map->Map.end() if the onRAUW callback already + // removed the old mapping. + if (I != Copy.Map->Map.end()) { + ValueT Target(I->second); + Copy.Map->Map.erase(I); // Definitely destroys *this. + Copy.Map->insert(std::make_pair(typed_new_key, Target)); + } + } + if (M) + M->release(); + } +}; + +template +struct DenseMapInfo > { + typedef ValueMapCallbackVH VH; + typedef DenseMapInfo PointerInfo; + + static inline VH getEmptyKey() { + return VH(PointerInfo::getEmptyKey(), NULL); + } + static inline VH getTombstoneKey() { + return VH(PointerInfo::getTombstoneKey(), NULL); + } + static unsigned getHashValue(const VH &Val) { + return PointerInfo::getHashValue(Val.Unwrap()); + } + static bool isEqual(const VH &LHS, const VH &RHS) { + return LHS == RHS; + } +}; + + +template +class ValueMapIterator : + public std::iterator, + ptrdiff_t> { + typedef typename DenseMapT::iterator BaseT; + typedef typename DenseMapT::mapped_type ValueT; + BaseT I; +public: + ValueMapIterator() : I() {} + + ValueMapIterator(BaseT I) : I(I) {} + + BaseT base() const { return I; } + + struct ValueTypeProxy { + const KeyT first; + ValueT& second; + ValueTypeProxy *operator->() { return this; } + operator std::pair() const { + return std::make_pair(first, second); + } + }; + + ValueTypeProxy operator*() const { + ValueTypeProxy Result = {I->first.Unwrap(), I->second}; + return Result; + } + + ValueTypeProxy operator->() const { + return operator*(); + } + + bool operator==(const ValueMapIterator &RHS) const { + return I == RHS.I; + } + bool operator!=(const ValueMapIterator &RHS) const { + return I != RHS.I; + } + + inline ValueMapIterator& operator++() { // Preincrement + ++I; + return *this; + } + ValueMapIterator operator++(int) { // Postincrement + ValueMapIterator tmp = *this; ++*this; return tmp; + } +}; + +template +class ValueMapConstIterator : + public std::iterator, + ptrdiff_t> { + typedef typename DenseMapT::const_iterator BaseT; + typedef typename DenseMapT::mapped_type ValueT; + BaseT I; +public: + ValueMapConstIterator() : I() {} + ValueMapConstIterator(BaseT I) : I(I) {} + ValueMapConstIterator(ValueMapIterator Other) + : I(Other.base()) {} + + BaseT base() const { return I; } + + struct ValueTypeProxy { + const KeyT first; + const ValueT& second; + ValueTypeProxy *operator->() { return this; } + operator std::pair() const { + return std::make_pair(first, second); + } + }; + + ValueTypeProxy operator*() const { + ValueTypeProxy Result = {I->first.Unwrap(), I->second}; + return Result; + } + + ValueTypeProxy operator->() const { + return operator*(); + } + + bool operator==(const ValueMapConstIterator &RHS) const { + return I == RHS.I; + } + bool operator!=(const ValueMapConstIterator &RHS) const { + return I != RHS.I; + } + + inline ValueMapConstIterator& operator++() { // Preincrement + ++I; + return *this; + } + ValueMapConstIterator operator++(int) { // Postincrement + ValueMapConstIterator tmp = *this; ++*this; return tmp; + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/ADT/VectorExtras.h b/final/include/llvm/ADT/VectorExtras.h new file mode 100644 index 00000000000..e05f585996f --- /dev/null +++ b/final/include/llvm/ADT/VectorExtras.h @@ -0,0 +1,41 @@ +//===-- llvm/ADT/VectorExtras.h - Helpers for std::vector -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains helper functions which are useful for working with the +// std::vector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VECTOREXTRAS_H +#define LLVM_ADT_VECTOREXTRAS_H + +#include +#include + +namespace llvm { + +/// make_vector - Helper function which is useful for building temporary vectors +/// to pass into type construction of CallInst ctors. This turns a null +/// terminated list of pointers (or other value types) into a real live vector. +/// +template +inline std::vector make_vector(T A, ...) { + va_list Args; + va_start(Args, A); + std::vector Result; + Result.push_back(A); + while (T Val = va_arg(Args, T)) + Result.push_back(Val); + va_end(Args); + return Result; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ADT/ilist.h b/final/include/llvm/ADT/ilist.h new file mode 100644 index 00000000000..865fcb3d8aa --- /dev/null +++ b/final/include/llvm/ADT/ilist.h @@ -0,0 +1,708 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- 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 classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist_traits trait class is used to gain access to the next and previous +// fields of the node type that the list is instantiated with. If it is not +// specialized, the list defaults to using the getPrev(), getNext() method calls +// to get the next and previous pointers. +// +// The ilist class itself, should be a plug in replacement for list, assuming +// that the nodes contain next/prev pointers. This list replacement does not +// provide a constant time size() method, so be careful to use empty() when you +// really want to know if it's empty. +// +// The ilist class is implemented by allocating a 'tail' node when the list is +// created (using ilist_traits<>::createSentinel()). This tail node is +// absolutely required because the user must be able to compute end()-1. Because +// of this, users of the direct next/prev links will see an extra link on the +// end of the list, which should be ignored. +// +// Requirements for a user of this list: +// +// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize +// ilist_traits to provide an alternate way of getting and setting next and +// prev links. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_H +#define LLVM_ADT_ILIST_H + +#include +#include +#include +#include + +namespace llvm { + +template class iplist; +template class ilist_iterator; + +/// ilist_nextprev_traits - A fragment for template traits for intrusive list +/// that provides default next/prev implementations for common operations. +/// +template +struct ilist_nextprev_traits { + static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } + static NodeTy *getNext(NodeTy *N) { return N->getNext(); } + static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } + static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } + + static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } + static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } +}; + +template +struct ilist_traits; + +/// ilist_sentinel_traits - A fragment for template traits for intrusive list +/// that provides default sentinel implementations for common operations. +/// +/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation +/// strategy. The sentinel is stored in the prev field of ilist's Head. +/// +template +struct ilist_sentinel_traits { + /// createSentinel - create the dynamic sentinel + static NodeTy *createSentinel() { return new NodeTy(); } + + /// destroySentinel - deallocate the dynamic sentinel + static void destroySentinel(NodeTy *N) { delete N; } + + /// provideInitialHead - when constructing an ilist, provide a starting + /// value for its Head + /// @return null node to indicate that it needs to be allocated later + static NodeTy *provideInitialHead() { return 0; } + + /// ensureHead - make sure that Head is either already + /// initialized or assigned a fresh sentinel + /// @return the sentinel + static NodeTy *ensureHead(NodeTy *&Head) { + if (!Head) { + Head = ilist_traits::createSentinel(); + ilist_traits::noteHead(Head, Head); + ilist_traits::setNext(Head, 0); + return Head; + } + return ilist_traits::getPrev(Head); + } + + /// noteHead - stash the sentinel into its default location + static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) { + ilist_traits::setPrev(NewHead, Sentinel); + } +}; + +/// ilist_node_traits - A fragment for template traits for intrusive list +/// that provides default node related operations. +/// +template +struct ilist_node_traits { + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + static void deleteNode(NodeTy *V) { delete V; } + + void addNodeToList(NodeTy *) {} + void removeNodeFromList(NodeTy *) {} + void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, + ilist_iterator /*first*/, + ilist_iterator /*last*/) {} +}; + +/// ilist_default_traits - Default template traits for intrusive list. +/// By inheriting from this, you can easily use default implementations +/// for all common operations. +/// +template +struct ilist_default_traits : public ilist_nextprev_traits, + public ilist_sentinel_traits, + public ilist_node_traits { +}; + +// Template traits for intrusive list. By specializing this template class, you +// can change what next/prev fields are used to store the links... +template +struct ilist_traits : public ilist_default_traits {}; + +// Const traits are the same as nonconst traits... +template +struct ilist_traits : public ilist_traits {}; + +//===----------------------------------------------------------------------===// +// ilist_iterator - Iterator for intrusive list. +// +template +class ilist_iterator + : public std::iterator { + +public: + typedef ilist_traits Traits; + typedef std::iterator super; + + typedef typename super::value_type value_type; + typedef typename super::difference_type difference_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; +private: + pointer NodePtr; + + // ilist_iterator is not a random-access iterator, but it has an + // implicit conversion to pointer-type, which is. Declare (but + // don't define) these functions as private to help catch + // accidental misuse. + void operator[](difference_type) const; + void operator+(difference_type) const; + void operator-(difference_type) const; + void operator+=(difference_type) const; + void operator-=(difference_type) const; + template void operator<(T) const; + template void operator<=(T) const; + template void operator>(T) const; + template void operator>=(T) const; + template void operator-(T) const; +public: + + ilist_iterator(pointer NP) : NodePtr(NP) {} + ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(0) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template + ilist_iterator(const ilist_iterator &RHS) + : NodePtr(RHS.getNodePtrUnchecked()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template + const ilist_iterator &operator=(const ilist_iterator &RHS) { + NodePtr = RHS.getNodePtrUnchecked(); + return *this; + } + + // Accessors... + operator pointer() const { + return NodePtr; + } + + reference operator*() const { + return *NodePtr; + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + bool operator==(const ilist_iterator &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const ilist_iterator &RHS) const { + return NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { // predecrement - Back up + NodePtr = Traits::getPrev(NodePtr); + assert(NodePtr && "--'d off the beginning of an ilist!"); + return *this; + } + ilist_iterator &operator++() { // preincrement - Advance + NodePtr = Traits::getNext(NodePtr); + return *this; + } + ilist_iterator operator--(int) { // postdecrement operators... + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { // postincrement operators... + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + // Internal interface, do not use... + pointer getNodePtrUnchecked() const { return NodePtr; } +}; + +// do not implement. this is to catch errors when people try to use +// them as random access iterators +template +void operator-(int, ilist_iterator); +template +void operator-(ilist_iterator,int); + +template +void operator+(int, ilist_iterator); +template +void operator+(ilist_iterator,int); + +// operator!=/operator== - Allow mixed comparisons without dereferencing +// the iterator, which could very likely be pointing to end(). +template +bool operator!=(const T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(const T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} +template +bool operator!=(T* LHS, const ilist_iterator &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template +bool operator==(T* LHS, const ilist_iterator &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} + + +// Allow ilist_iterators to convert into pointers to a node automatically when +// used by the dyn_cast, cast, isa mechanisms... + +template struct simplify_type; + +template struct simplify_type > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; +template struct simplify_type > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator &Node) { + return &*Node; + } +}; + + +//===----------------------------------------------------------------------===// +// +/// iplist - The subset of list functionality that can safely be used on nodes +/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is a single +/// pointer to the head of the list. +/// +/// This list can be in one of three interesting states: +/// 1. The list may be completely unconstructed. In this case, the head +/// pointer is null. When in this form, any query for an iterator (e.g. +/// begin() or end()) causes the list to transparently change to state #2. +/// 2. The list may be empty, but contain a sentinel for the end iterator. This +/// sentinel is created by the Traits::createSentinel method and is a link +/// in the list. When the list is empty, the pointer in the iplist points +/// to the sentinel. Once the sentinel is constructed, it +/// is not destroyed until the list is. +/// 3. The list may contain actual objects in it, which are stored as a doubly +/// linked list of nodes. One invariant of the list is that the predecessor +/// of the first node in the list always points to the last node in the list, +/// and the successor pointer for the sentinel (which always stays at the +/// end of the list) is always null. +/// +template > +class iplist : public Traits { + mutable NodeTy *Head; + + // Use the prev node pointer of 'head' as the tail pointer. This is really a + // circularly linked list where we snip the 'next' link from the sentinel node + // back to the first node in the list (to preserve assertions about going off + // the end of the list). + NodeTy *getTail() { return this->ensureHead(Head); } + const NodeTy *getTail() const { return this->ensureHead(Head); } + void setTail(NodeTy *N) const { this->noteHead(Head, N); } + + /// CreateLazySentinel - This method verifies whether the sentinel for the + /// list has been created and lazily makes it if not. + void CreateLazySentinel() const { + this->ensureHead(Head); + } + + static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } + static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } + + // No fundamental reason why iplist can't be copyable, but the default + // copy/copy-assign won't do. + iplist(const iplist &); // do not implement + void operator=(const iplist &); // do not implement + +public: + typedef NodeTy *pointer; + typedef const NodeTy *const_pointer; + typedef NodeTy &reference; + typedef const NodeTy &const_reference; + typedef NodeTy value_type; + typedef ilist_iterator iterator; + typedef ilist_iterator const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + iplist() : Head(this->provideInitialHead()) {} + ~iplist() { + if (!Head) return; + clear(); + Traits::destroySentinel(getTail()); + } + + // Iterator creation methods. + iterator begin() { + CreateLazySentinel(); + return iterator(Head); + } + const_iterator begin() const { + CreateLazySentinel(); + return const_iterator(Head); + } + iterator end() { + CreateLazySentinel(); + return iterator(getTail()); + } + const_iterator end() const { + CreateLazySentinel(); + return const_iterator(getTail()); + } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + bool empty() const { return Head == 0 || Head == getTail(); } + + // Front and back accessor functions... + reference front() { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + const_reference front() const { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + reference back() { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + const_reference back() const { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + + void swap(iplist &RHS) { + assert(0 && "Swap does not use list traits callback correctly yet!"); + std::swap(Head, RHS.Head); + } + + iterator insert(iterator where, NodeTy *New) { + NodeTy *CurNode = where.getNodePtrUnchecked(); + NodeTy *PrevNode = this->getPrev(CurNode); + this->setNext(New, CurNode); + this->setPrev(New, PrevNode); + + if (CurNode != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, New); + else + Head = New; + this->setPrev(CurNode, New); + + this->addNodeToList(New); // Notify traits that we added a node... + return New; + } + + iterator insertAfter(iterator where, NodeTy *New) { + if (empty()) + return insert(begin(), New); + else + return insert(++where, New); + } + + NodeTy *remove(iterator &IT) { + assert(IT != end() && "Cannot remove end of list!"); + NodeTy *Node = &*IT; + NodeTy *NextNode = this->getNext(Node); + NodeTy *PrevNode = this->getPrev(Node); + + if (Node != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, NextNode); + else + Head = NextNode; + this->setPrev(NextNode, PrevNode); + IT = NextNode; + this->removeNodeFromList(Node); // Notify traits that we removed a node... + + // Set the next/prev pointers of the current node to null. This isn't + // strictly required, but this catches errors where a node is removed from + // an ilist (and potentially deleted) with iterators still pointing at it. + // When those iterators are incremented or decremented, they will assert on + // the null next/prev pointer instead of "usually working". + this->setNext(Node, 0); + this->setPrev(Node, 0); + return Node; + } + + NodeTy *remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + this->deleteNode(remove(where)); + return where; + } + + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist &L2, iterator first, iterator last) { + assert(first != last && "Should be checked by callers"); + + if (position != last) { + // Note: we have to be careful about the case when we move the first node + // in the list. This node is the list sentinel node and we can't move it. + NodeTy *ThisSentinel = getTail(); + setTail(0); + NodeTy *L2Sentinel = L2.getTail(); + L2.setTail(0); + + // Remove [first, last) from its old position. + NodeTy *First = &*first, *Prev = this->getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->getPrev(Next); + if (Prev) + this->setNext(Prev, Next); + else + L2.Head = Next; + this->setPrev(Next, Prev); + + // Splice [first, last) into its new position. + NodeTy *PosNext = position.getNodePtrUnchecked(); + NodeTy *PosPrev = this->getPrev(PosNext); + + // Fix head of list... + if (PosPrev) + this->setNext(PosPrev, First); + else + Head = First; + this->setPrev(First, PosPrev); + + // Fix end of list... + this->setNext(Last, PosNext); + this->setPrev(PosNext, Last); + + this->transferNodesFromList(L2, First, PosNext); + + // Now that everything is set, restore the pointers to the list sentinels. + L2.setTail(L2Sentinel); + setTail(ThisSentinel); + } + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + size_type size() const { + if (Head == 0) return 0; // Don't require construction of sentinel if empty. + return std::distance(begin(), end()); + } + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { if (Head) erase(begin(), end()); } + + // Front and back inserters... + void push_front(NodeTy *val) { insert(begin(), val); } + void push_back(NodeTy *val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + + + + //===----------------------------------------------------------------------=== + // High-Level Functionality that shouldn't really be here, but is part of list + // + + // These two functions are actually called remove/remove_if in list<>, but + // they actually do the job of erase, rename them accordingly. + // + void erase(const NodeTy &val) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (*I == val) erase(I); + I = next; + } + } + template void erase_if(Pr1 pred) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (pred(*I)) erase(I); + I = next; + } + } + + template void unique(Pr2 pred) { + if (empty()) return; + for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { + if (pred(*I)) + erase(Next); + else + I = Next; + Next = I; + } + } + void unique() { unique(op_equal); } + + template void merge(iplist &right, Pr3 pred) { + iterator first1 = begin(), last1 = end(); + iterator first2 = right.begin(), last2 = right.end(); + while (first1 != last1 && first2 != last2) + if (pred(*first2, *first1)) { + iterator next = first2; + transfer(first1, right, first2, ++next); + first2 = next; + } else { + ++first1; + } + if (first2 != last2) transfer(last1, right, first2, last2); + } + void merge(iplist &right) { return merge(right, op_less); } + + template void sort(Pr3 pred); + void sort() { sort(op_less); } +}; + + +template +struct ilist : public iplist { + typedef typename iplist::size_type size_type; + typedef typename iplist::iterator iterator; + + ilist() {} + ilist(const ilist &right) { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, NodeTy()); + } + ilist(size_type count, const NodeTy &val) { + insert(this->begin(), count, val); + } + template ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + // bring hidden functions into scope + using iplist::insert; + using iplist::push_front; + using iplist::push_back; + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const NodeTy &val) { + return insert(where, this->createNode(val)); + } + + + // Front and back inserters... + void push_front(const NodeTy &val) { insert(this->begin(), val); } + void push_back(const NodeTy &val) { insert(this->end(), val); } + + // Special forms of insert... + template void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + void insert(iterator where, size_type count, const NodeTy &val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const NodeTy &val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, NodeTy val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, NodeTy()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template + void swap(llvm::iplist &Left, llvm::iplist &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif // LLVM_ADT_ILIST_H diff --git a/final/include/llvm/ADT/ilist_node.h b/final/include/llvm/ADT/ilist_node.h new file mode 100644 index 00000000000..f0080035cb8 --- /dev/null +++ b/final/include/llvm/ADT/ilist_node.h @@ -0,0 +1,106 @@ +//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- 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 ilist_node class template, which is a convenient +// base class for creating classes that can be used with ilists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H + +namespace llvm { + +template +struct ilist_traits; + +/// ilist_half_node - Base class that provides prev services for sentinels. +/// +template +class ilist_half_node { + friend struct ilist_traits; + NodeTy *Prev; +protected: + NodeTy *getPrev() { return Prev; } + const NodeTy *getPrev() const { return Prev; } + void setPrev(NodeTy *P) { Prev = P; } + ilist_half_node() : Prev(0) {} +}; + +template +struct ilist_nextprev_traits; + +/// ilist_node - Base class that provides next/prev services for nodes +/// that use ilist_nextprev_traits or ilist_default_traits. +/// +template +class ilist_node : private ilist_half_node { + friend struct ilist_nextprev_traits; + friend struct ilist_traits; + NodeTy *Next; + NodeTy *getNext() { return Next; } + const NodeTy *getNext() const { return Next; } + void setNext(NodeTy *N) { Next = N; } +protected: + ilist_node() : Next(0) {} + +public: + /// @name Adjacent Node Accessors + /// @{ + + /// \brief Get the previous node, or 0 for the list head. + NodeTy *getPrevNode() { + NodeTy *Prev = this->getPrev(); + + // Check for sentinel. + if (!Prev->getNext()) + return 0; + + return Prev; + } + + /// \brief Get the previous node, or 0 for the list head. + const NodeTy *getPrevNode() const { + const NodeTy *Prev = this->getPrev(); + + // Check for sentinel. + if (!Prev->getNext()) + return 0; + + return Prev; + } + + /// \brief Get the next node, or 0 for the list tail. + NodeTy *getNextNode() { + NodeTy *Next = getNext(); + + // Check for sentinel. + if (!Next->getNext()) + return 0; + + return Next; + } + + /// \brief Get the next node, or 0 for the list tail. + const NodeTy *getNextNode() const { + const NodeTy *Next = getNext(); + + // Check for sentinel. + if (!Next->getNext()) + return 0; + + return Next; + } + + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/AbstractTypeUser.h b/final/include/llvm/AbstractTypeUser.h new file mode 100644 index 00000000000..81f5c5c7680 --- /dev/null +++ b/final/include/llvm/AbstractTypeUser.h @@ -0,0 +1,205 @@ +//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AbstractTypeUser class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ABSTRACT_TYPE_USER_H +#define LLVM_ABSTRACT_TYPE_USER_H + +#if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H) +#error Do not include this file directly. Include Type.h instead. +#error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method +#error PATypeHolder::dropRef() correctly otherwise. +#endif + +// This is the "master" include for Whether this file needs it or not, +// it must always include for the files which include +// llvm/AbstractTypeUser.h +// +// In this way, most every LLVM source file will have access to the assert() +// macro without having to #include directly. +// +#include + +namespace llvm { + +class Value; +class Type; +class DerivedType; +template struct simplify_type; + +/// The AbstractTypeUser class is an interface to be implemented by classes who +/// could possibly use an abstract type. Abstract types are denoted by the +/// isAbstract flag set to true in the Type class. These are classes that +/// contain an Opaque type in their structure somewhere. +/// +/// Classes must implement this interface so that they may be notified when an +/// abstract type is resolved. Abstract types may be resolved into more +/// concrete types through: linking, parsing, and bitcode reading. When this +/// happens, all of the users of the type must be updated to reference the new, +/// more concrete type. They are notified through the AbstractTypeUser +/// interface. +/// +/// In addition to this, AbstractTypeUsers must keep the use list of the +/// potentially abstract type that they reference up-to-date. To do this in a +/// nice, transparent way, the PATypeHandle class is used to hold "Potentially +/// Abstract Types", and keep the use list of the abstract types up-to-date. +/// @brief LLVM Abstract Type User Representation +class AbstractTypeUser { +protected: + virtual ~AbstractTypeUser(); // Derive from me + + /// setType - It's normally not possible to change a Value's type in place, + /// but an AbstractTypeUser subclass that knows what its doing can be + /// permitted to do so with care. + void setType(Value *V, const Type *NewTy); + +public: + + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) = 0; + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on its + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0; + + // for debugging... + virtual void dump() const = 0; +}; + + +/// PATypeHandle - Handle to a Type subclass. This class is used to keep the +/// use list of abstract types up-to-date. +/// +class PATypeHandle { + const Type *Ty; + AbstractTypeUser * const User; + + // These functions are defined at the bottom of Type.h. See the comment there + // for justification. + void addUser(); + void removeUser(); +public: + // ctor - Add use to type if abstract. Note that Ty must not be null + inline PATypeHandle(const Type *ty, AbstractTypeUser *user) + : Ty(ty), User(user) { + addUser(); + } + + // ctor - Add use to type if abstract. + inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) { + addUser(); + } + + // dtor - Remove reference to type... + inline ~PATypeHandle() { removeUser(); } + + // Automatic casting operator so that the handle may be used naturally + inline operator Type *() const { return const_cast(Ty); } + inline Type *get() const { return const_cast(Ty); } + + // operator= - Allow assignment to handle + inline Type *operator=(const Type *ty) { + if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty + removeUser(); + Ty = ty; + addUser(); + } + return get(); + } + + // operator= - Allow assignment to handle + inline const Type *operator=(const PATypeHandle &T) { + return operator=(T.Ty); + } + + inline bool operator==(const Type *ty) { + return Ty == ty; + } + + // operator-> - Allow user to dereference handle naturally... + inline const Type *operator->() const { return Ty; } +}; + + +/// PATypeHolder - Holder class for a potentially abstract type. This uses +/// efficient union-find techniques to handle dynamic type resolution. Unless +/// you need to do custom processing when types are resolved, you should always +/// use PATypeHolders in preference to PATypeHandles. +/// +class PATypeHolder { + mutable const Type *Ty; + void destroy(); +public: + PATypeHolder() : Ty(0) {} + PATypeHolder(const Type *ty) : Ty(ty) { + addRef(); + } + PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) { + addRef(); + } + + ~PATypeHolder() { dropRef(); } + + operator Type *() const { return get(); } + Type *get() const; + + // operator-> - Allow user to dereference handle naturally... + Type *operator->() const { return get(); } + + // operator= - Allow assignment to handle + Type *operator=(const Type *ty) { + if (Ty != ty) { // Don't accidentally drop last ref to Ty. + dropRef(); + Ty = ty; + addRef(); + } + return get(); + } + Type *operator=(const PATypeHolder &H) { + return operator=(H.Ty); + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return Ty; } + +private: + void addRef(); + void dropRef(); + friend class TypeMapBase; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type { + typedef const Type* SimpleType; + static SimpleType getSimplifiedValue(const PATypeHolder &Val) { + return static_cast(Val.get()); + } +}; +template<> struct simplify_type { + typedef const Type* SimpleType; + static SimpleType getSimplifiedValue(const PATypeHolder &Val) { + return static_cast(Val.get()); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/AliasAnalysis.h b/final/include/llvm/Analysis/AliasAnalysis.h new file mode 100644 index 00000000000..71a5982c7d3 --- /dev/null +++ b/final/include/llvm/Analysis/AliasAnalysis.h @@ -0,0 +1,507 @@ +//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic AliasAnalysis interface, which is used as the +// common interface used by all clients of alias analysis information, and +// implemented by all alias analysis implementations. Mod/Ref information is +// also captured by this interface. +// +// Implementations of this interface must implement the various virtual methods, +// which automatically provides functionality for the entire suite of client +// APIs. +// +// This API identifies memory regions with the Location class. The pointer +// component specifies the base memory address of the region. The Size specifies +// the maximum size (in address units) of the memory region, or UnknownSize if +// the size is not known. The TBAA tag identifies the "type" of the memory +// reference; see the TypeBasedAliasAnalysis class for details. +// +// Some non-obvious details include: +// - Pointers that point to two completely different objects in memory never +// alias, regardless of the value of the Size component. +// - NoAlias doesn't imply inequal pointers. The most obvious example of this +// is two pointers to constant memory. Even if they are equal, constant +// memory is never stored to, so there will never be any dependencies. +// In this and other situations, the pointers may be both NoAlias and +// MustAlias at the same time. The current API can only return one result, +// though this is rarely a problem in practice. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H +#define LLVM_ANALYSIS_ALIAS_ANALYSIS_H + +#include "llvm/Support/CallSite.h" +#include + +namespace llvm { + +class LoadInst; +class StoreInst; +class VAArgInst; +class TargetData; +class Pass; +class AnalysisUsage; +class MemTransferInst; +class MemIntrinsic; + +class AliasAnalysis { +protected: + const TargetData *TD; + +private: + AliasAnalysis *AA; // Previous Alias Analysis to chain to. + +protected: + /// InitializeAliasAnalysis - Subclasses must call this method to initialize + /// the AliasAnalysis interface before any other methods are called. This is + /// typically called by the run* methods of these subclasses. This may be + /// called multiple times. + /// + void InitializeAliasAnalysis(Pass *P); + + /// getAnalysisUsage - All alias analysis implementations should invoke this + /// directly (using AliasAnalysis::getAnalysisUsage(AU)). + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +public: + static char ID; // Class identification, replacement for typeinfo + AliasAnalysis() : TD(0), AA(0) {} + virtual ~AliasAnalysis(); // We want to be subclassed + + /// UnknownSize - This is a special value which can be used with the + /// size arguments in alias queries to indicate that the caller does not + /// know the sizes of the potential memory references. + static uint64_t const UnknownSize = ~UINT64_C(0); + + /// getTargetData - Return a pointer to the current TargetData object, or + /// null if no TargetData object is available. + /// + const TargetData *getTargetData() const { return TD; } + + /// getTypeStoreSize - Return the TargetData store size for the given type, + /// if known, or a conservative value otherwise. + /// + uint64_t getTypeStoreSize(const Type *Ty); + + //===--------------------------------------------------------------------===// + /// Alias Queries... + /// + + /// Location - A description of a memory location. + struct Location { + /// Ptr - The address of the start of the location. + const Value *Ptr; + /// Size - The maximum size of the location, in address-units, or + /// UnknownSize if the size is not known. Note that an unknown size does + /// not mean the pointer aliases the entire virtual address space, because + /// there are restrictions on stepping out of one object and into another. + /// See http://llvm.org/docs/LangRef.html#pointeraliasing + uint64_t Size; + /// TBAATag - The metadata node which describes the TBAA type of + /// the location, or null if there is no known unique tag. + const MDNode *TBAATag; + + explicit Location(const Value *P = 0, uint64_t S = UnknownSize, + const MDNode *N = 0) + : Ptr(P), Size(S), TBAATag(N) {} + + Location getWithNewPtr(const Value *NewPtr) const { + Location Copy(*this); + Copy.Ptr = NewPtr; + return Copy; + } + + Location getWithNewSize(uint64_t NewSize) const { + Location Copy(*this); + Copy.Size = NewSize; + return Copy; + } + + Location getWithoutTBAATag() const { + Location Copy(*this); + Copy.TBAATag = 0; + return Copy; + } + }; + + /// getLocation - Fill in Loc with information about the memory reference by + /// the given instruction. + Location getLocation(const LoadInst *LI); + Location getLocation(const StoreInst *SI); + Location getLocation(const VAArgInst *VI); + static Location getLocationForSource(const MemTransferInst *MTI); + static Location getLocationForDest(const MemIntrinsic *MI); + + /// Alias analysis result - Either we know for sure that it does not alias, we + /// know for sure it must alias, or we don't know anything: The two pointers + /// _might_ alias. This enum is designed so you can do things like: + /// if (AA.alias(P1, P2)) { ... } + /// to check to see if two pointers might alias. + /// + /// See docs/AliasAnalysis.html for more information on the specific meanings + /// of these values. + /// + enum AliasResult { + NoAlias = 0, ///< No dependencies. + MayAlias, ///< Anything goes. + PartialAlias, ///< Pointers differ, but pointees overlap. + MustAlias ///< Pointers are equal. + }; + + /// alias - The main low level interface to the alias analysis implementation. + /// Returns an AliasResult indicating whether the two pointers are aliased to + /// each other. This is the interface that must be implemented by specific + /// alias analysis implementations. + virtual AliasResult alias(const Location &LocA, const Location &LocB); + + /// alias - A convenience wrapper. + AliasResult alias(const Value *V1, uint64_t V1Size, + const Value *V2, uint64_t V2Size) { + return alias(Location(V1, V1Size), Location(V2, V2Size)); + } + + /// alias - A convenience wrapper. + AliasResult alias(const Value *V1, const Value *V2) { + return alias(V1, UnknownSize, V2, UnknownSize); + } + + /// isNoAlias - A trivial helper function to check to see if the specified + /// pointers are no-alias. + bool isNoAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == NoAlias; + } + + /// isNoAlias - A convenience wrapper. + bool isNoAlias(const Value *V1, uint64_t V1Size, + const Value *V2, uint64_t V2Size) { + return isNoAlias(Location(V1, V1Size), Location(V2, V2Size)); + } + + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == MustAlias; + } + + /// isMustAlias - A convenience wrapper. + bool isMustAlias(const Value *V1, const Value *V2) { + return alias(V1, 1, V2, 1) == MustAlias; + } + + /// pointsToConstantMemory - If the specified memory location is + /// known to be constant, return true. If OrLocal is true and the + /// specified memory location is known to be "local" (derived from + /// an alloca), return true. Otherwise return false. + virtual bool pointsToConstantMemory(const Location &Loc, + bool OrLocal = false); + + /// pointsToConstantMemory - A convenient wrapper. + bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { + return pointsToConstantMemory(Location(P), OrLocal); + } + + //===--------------------------------------------------------------------===// + /// Simple mod/ref information... + /// + + /// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are + /// bits which may be or'd together. + /// + enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; + + /// These values define additional bits used to define the + /// ModRefBehavior values. + enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees }; + + /// ModRefBehavior - Summary of how a function affects memory in the program. + /// Loads from constant globals are not considered memory accesses for this + /// interface. Also, functions may freely modify stack space local to their + /// invocation without having to report it through these interfaces. + enum ModRefBehavior { + /// DoesNotAccessMemory - This function does not perform any non-local loads + /// or stores to memory. + /// + /// This property corresponds to the GCC 'const' attribute. + /// This property corresponds to the LLVM IR 'readnone' attribute. + /// This property corresponds to the IntrNoMem LLVM intrinsic flag. + DoesNotAccessMemory = Nowhere | NoModRef, + + /// OnlyReadsArgumentPointees - The only memory references in this function + /// (if it has any) are non-volatile loads from objects pointed to by its + /// pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. + OnlyReadsArgumentPointees = ArgumentPointees | Ref, + + /// OnlyAccessesArgumentPointees - The only memory references in this + /// function (if it has any) are non-volatile loads and stores from objects + /// pointed to by its pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag. + OnlyAccessesArgumentPointees = ArgumentPointees | ModRef, + + /// OnlyReadsMemory - This function does not perform any non-local stores or + /// volatile loads, but may read from any memory location. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// This property corresponds to the LLVM IR 'readonly' attribute. + /// This property corresponds to the IntrReadMem LLVM intrinsic flag. + OnlyReadsMemory = Anywhere | Ref, + + /// UnknownModRefBehavior - This indicates that the function could not be + /// classified into one of the behaviors above. + UnknownModRefBehavior = Anywhere | ModRef + }; + + /// getModRefBehavior - Return the behavior when calling the given call site. + virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); + + /// getModRefBehavior - Return the behavior when calling the given function. + /// For use when the call site is not known. + virtual ModRefBehavior getModRefBehavior(const Function *F); + + /// doesNotAccessMemory - If the specified call is known to never read or + /// write memory, return true. If the call only reads from known-constant + /// memory, it is also legal to return true. Calls that unwind the stack + /// are legal for this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// without worrying about aliasing properties, and many calls have this + /// property (e.g. calls to 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. + /// + bool doesNotAccessMemory(ImmutableCallSite CS) { + return getModRefBehavior(CS) == DoesNotAccessMemory; + } + + /// doesNotAccessMemory - If the specified function is known to never read or + /// write memory, return true. For use when the call site is not known. + /// + bool doesNotAccessMemory(const Function *F) { + return getModRefBehavior(F) == DoesNotAccessMemory; + } + + /// onlyReadsMemory - If the specified call is known to only read from + /// non-volatile memory (or not access memory at all), return true. Calls + /// that unwind the stack are legal for this predicate. + /// + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// + bool onlyReadsMemory(ImmutableCallSite CS) { + return onlyReadsMemory(getModRefBehavior(CS)); + } + + /// onlyReadsMemory - If the specified function is known to only read from + /// non-volatile memory (or not access memory at all), return true. For use + /// when the call site is not known. + /// + bool onlyReadsMemory(const Function *F) { + return onlyReadsMemory(getModRefBehavior(F)); + } + + /// onlyReadsMemory - Return true if functions with the specified behavior are + /// known to only read from non-volatile memory (or not access memory at all). + /// + static bool onlyReadsMemory(ModRefBehavior MRB) { + return !(MRB & Mod); + } + + /// onlyAccessesArgPointees - Return true if functions with the specified + /// behavior are known to read and write at most from objects pointed to by + /// their pointer-typed arguments (with arbitrary offsets). + /// + static bool onlyAccessesArgPointees(ModRefBehavior MRB) { + return !(MRB & Anywhere & ~ArgumentPointees); + } + + /// doesAccessArgPointees - Return true if functions with the specified + /// behavior are known to potentially read or write from objects pointed + /// to be their pointer-typed arguments (with arbitrary offsets). + /// + static bool doesAccessArgPointees(ModRefBehavior MRB) { + return (MRB & ModRef) && (MRB & ArgumentPointees); + } + + /// getModRefInfo - Return information about whether or not an instruction may + /// read or write the specified memory location. An instruction + /// that doesn't read or write memory may be trivially LICM'd for example. + ModRefResult getModRefInfo(const Instruction *I, + const Location &Loc) { + switch (I->getOpcode()) { + case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); + case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); + case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); + case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); + case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); + default: return NoModRef; + } + } + + /// getModRefInfo - A convenience wrapper. + ModRefResult getModRefInfo(const Instruction *I, + const Value *P, uint64_t Size) { + return getModRefInfo(I, Location(P, Size)); + } + + /// getModRefInfo (for call sites) - Return whether information about whether + /// a particular call site modifies or reads the specified memory location. + virtual ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + + /// getModRefInfo (for call sites) - A convenience wrapper. + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Value *P, uint64_t Size) { + return getModRefInfo(CS, Location(P, Size)); + } + + /// getModRefInfo (for calls) - Return whether information about whether + /// a particular call modifies or reads the specified memory location. + ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) { + return getModRefInfo(ImmutableCallSite(C), Loc); + } + + /// getModRefInfo (for calls) - A convenience wrapper. + ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) { + return getModRefInfo(C, Location(P, Size)); + } + + /// getModRefInfo (for invokes) - Return whether information about whether + /// a particular invoke modifies or reads the specified memory location. + ModRefResult getModRefInfo(const InvokeInst *I, + const Location &Loc) { + return getModRefInfo(ImmutableCallSite(I), Loc); + } + + /// getModRefInfo (for invokes) - A convenience wrapper. + ModRefResult getModRefInfo(const InvokeInst *I, + const Value *P, uint64_t Size) { + return getModRefInfo(I, Location(P, Size)); + } + + /// getModRefInfo (for loads) - Return whether information about whether + /// a particular load modifies or reads the specified memory location. + ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc); + + /// getModRefInfo (for loads) - A convenience wrapper. + ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) { + return getModRefInfo(L, Location(P, Size)); + } + + /// getModRefInfo (for stores) - Return whether information about whether + /// a particular store modifies or reads the specified memory location. + ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); + + /// getModRefInfo (for stores) - A convenience wrapper. + ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){ + return getModRefInfo(S, Location(P, Size)); + } + + /// getModRefInfo (for va_args) - Return whether information about whether + /// a particular va_arg modifies or reads the specified memory location. + ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); + + /// getModRefInfo (for va_args) - A convenience wrapper. + ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ + return getModRefInfo(I, Location(P, Size)); + } + + /// getModRefInfo - Return information about whether two call sites may refer + /// to the same set of memory locations. See + /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo + /// for details. + virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2); + + //===--------------------------------------------------------------------===// + /// Higher level methods for querying mod/ref information. + /// + + /// canBasicBlockModify - Return true if it is possible for execution of the + /// specified basic block to modify the value pointed to by Ptr. + bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); + + /// canBasicBlockModify - A convenience wrapper. + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){ + return canBasicBlockModify(BB, Location(P, Size)); + } + + /// canInstructionRangeModify - Return true if it is possible for the + /// execution of the specified instructions to modify the value pointed to by + /// Ptr. The instructions to consider are all of the instructions in the + /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Location &Loc); + + /// canInstructionRangeModify - A convenience wrapper. + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Value *Ptr, uint64_t Size) { + return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + } + + //===--------------------------------------------------------------------===// + /// Methods that clients should call when they transform the program to allow + /// alias analyses to update their internal data structures. Note that these + /// methods may be called on any instruction, regardless of whether or not + /// they have pointer-analysis implications. + /// + + /// deleteValue - This method should be called whenever an LLVM Value is + /// deleted from the program, for example when an instruction is found to be + /// redundant and is eliminated. + /// + virtual void deleteValue(Value *V); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that analysis + /// implementations should tolerate clients that use this method to introduce + /// the same value multiple times: if the analysis already knows about a + /// value, it should ignore the request. + /// + virtual void copyValue(Value *From, Value *To); + + /// addEscapingUse - This method should be used whenever an escaping use is + /// added to a pointer value. Analysis implementations may either return + /// conservative responses for that value in the future, or may recompute + /// some or all internal state to continue providing precise responses. + /// + /// Escaping uses are considered by anything _except_ the following: + /// - GEPs or bitcasts of the pointer + /// - Loads through the pointer + /// - Stores through (but not of) the pointer + virtual void addEscapingUse(Use &U); + + /// replaceWithNewValue - This method is the obvious combination of the two + /// above, and it provided as a helper to simplify client code. + /// + void replaceWithNewValue(Value *Old, Value *New) { + copyValue(Old, New); + deleteValue(Old); + } +}; + +/// isNoAliasCall - Return true if this pointer is returned by a noalias +/// function. +bool isNoAliasCall(const Value *V); + +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions (but not Global Aliases) +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// NoAlias returns +/// +bool isIdentifiedObject(const Value *V); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/AliasSetTracker.h b/final/include/llvm/Analysis/AliasSetTracker.h new file mode 100644 index 00000000000..e844d10dda0 --- /dev/null +++ b/final/include/llvm/Analysis/AliasSetTracker.h @@ -0,0 +1,440 @@ +//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- 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 two classes: AliasSetTracker and AliasSet. These interface +// are used to classify a collection of pointer references into a maximal number +// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker +// object refers to memory disjoint from the other sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H +#define LLVM_ANALYSIS_ALIASSETTRACKER_H + +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include + +namespace llvm { + +class AliasAnalysis; +class LoadInst; +class StoreInst; +class VAArgInst; +class AliasSetTracker; +class AliasSet; + +class AliasSet : public ilist_node { + friend class AliasSetTracker; + + class PointerRec { + Value *Val; // The pointer this record corresponds to. + PointerRec **PrevInList, *NextInList; + AliasSet *AS; + uint64_t Size; + const MDNode *TBAAInfo; + public: + PointerRec(Value *V) + : Val(V), PrevInList(0), NextInList(0), AS(0), Size(0), + TBAAInfo(DenseMapInfo::getEmptyKey()) {} + + Value *getValue() const { return Val; } + + PointerRec *getNext() const { return NextInList; } + bool hasAliasSet() const { return AS != 0; } + + PointerRec** setPrevInList(PointerRec **PIL) { + PrevInList = PIL; + return &NextInList; + } + + void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) { + if (NewSize > Size) Size = NewSize; + + if (TBAAInfo == DenseMapInfo::getEmptyKey()) + // We don't have a TBAAInfo yet. Set it to NewTBAAInfo. + TBAAInfo = NewTBAAInfo; + else if (TBAAInfo != NewTBAAInfo) + // NewTBAAInfo conflicts with TBAAInfo. + TBAAInfo = DenseMapInfo::getTombstoneKey(); + } + + uint64_t getSize() const { return Size; } + + /// getTBAAInfo - Return the TBAAInfo, or null if there is no + /// information or conflicting information. + const MDNode *getTBAAInfo() const { + // If we have missing or conflicting TBAAInfo, return null. + if (TBAAInfo == DenseMapInfo::getEmptyKey() || + TBAAInfo == DenseMapInfo::getTombstoneKey()) + return 0; + return TBAAInfo; + } + + AliasSet *getAliasSet(AliasSetTracker &AST) { + assert(AS && "No AliasSet yet!"); + if (AS->Forward) { + AliasSet *OldAS = AS; + AS = OldAS->getForwardedTarget(AST); + AS->addRef(); + OldAS->dropRef(AST); + } + return AS; + } + + void setAliasSet(AliasSet *as) { + assert(AS == 0 && "Already have an alias set!"); + AS = as; + } + + void eraseFromList() { + if (NextInList) NextInList->PrevInList = PrevInList; + *PrevInList = NextInList; + if (AS->PtrListEnd == &NextInList) { + AS->PtrListEnd = PrevInList; + assert(*AS->PtrListEnd == 0 && "List not terminated right!"); + } + delete this; + } + }; + + PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes. + AliasSet *Forward; // Forwarding pointer. + AliasSet *Next, *Prev; // Doubly linked list of AliasSets. + + // All calls & invokes in this alias set. + std::vector > CallSites; + + // RefCount - Number of nodes pointing to this AliasSet plus the number of + // AliasSets forwarding to it. + unsigned RefCount : 28; + + /// AccessType - Keep track of whether this alias set merely refers to the + /// locations of memory, whether it modifies the memory, or whether it does + /// both. The lattice goes from "NoModRef" to either Refs or Mods, then to + /// ModRef as necessary. + /// + enum AccessType { + NoModRef = 0, Refs = 1, // Ref = bit 1 + Mods = 2, ModRef = 3 // Mod = bit 2 + }; + unsigned AccessTy : 2; + + /// AliasType - Keep track the relationships between the pointers in the set. + /// Lattice goes from MustAlias to MayAlias. + /// + enum AliasType { + MustAlias = 0, MayAlias = 1 + }; + unsigned AliasTy : 1; + + // Volatile - True if this alias set contains volatile loads or stores. + bool Volatile : 1; + + void addRef() { ++RefCount; } + void dropRef(AliasSetTracker &AST) { + assert(RefCount >= 1 && "Invalid reference count detected!"); + if (--RefCount == 0) + removeFromTracker(AST); + } + + CallSite getCallSite(unsigned i) const { + assert(i < CallSites.size()); + return CallSite(CallSites[i]); + } + +public: + /// Accessors... + bool isRef() const { return AccessTy & Refs; } + bool isMod() const { return AccessTy & Mods; } + bool isMustAlias() const { return AliasTy == MustAlias; } + bool isMayAlias() const { return AliasTy == MayAlias; } + + // isVolatile - Return true if this alias set contains volatile loads or + // stores. + bool isVolatile() const { return Volatile; } + + /// isForwardingAliasSet - Return true if this alias set should be ignored as + /// part of the AliasSetTracker object. + bool isForwardingAliasSet() const { return Forward; } + + /// mergeSetIn - Merge the specified alias set into this alias set... + /// + void mergeSetIn(AliasSet &AS, AliasSetTracker &AST); + + // Alias Set iteration - Allow access to all of the pointer which are part of + // this alias set... + class iterator; + iterator begin() const { return iterator(PtrList); } + iterator end() const { return iterator(); } + bool empty() const { return PtrList == 0; } + + void print(raw_ostream &OS) const; + void dump() const; + + /// Define an iterator for alias sets... this is just a forward iterator. + class iterator : public std::iterator { + PointerRec *CurNode; + public: + explicit iterator(PointerRec *CN = 0) : CurNode(CN) {} + + bool operator==(const iterator& x) const { + return CurNode == x.CurNode; + } + bool operator!=(const iterator& x) const { return !operator==(x); } + + const iterator &operator=(const iterator &I) { + CurNode = I.CurNode; + return *this; + } + + value_type &operator*() const { + assert(CurNode && "Dereferencing AliasSet.end()!"); + return *CurNode; + } + value_type *operator->() const { return &operator*(); } + + Value *getPointer() const { return CurNode->getValue(); } + uint64_t getSize() const { return CurNode->getSize(); } + const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); } + + iterator& operator++() { // Preincrement + assert(CurNode && "Advancing past AliasSet.end()!"); + CurNode = CurNode->getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; ++*this; return tmp; + } + }; + +private: + // Can only be created by AliasSetTracker. Also, ilist creates one + // to serve as a sentinel. + friend struct ilist_sentinel_traits; + AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0), + AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { + } + + AliasSet(const AliasSet &AS); // do not implement + void operator=(const AliasSet &AS); // do not implement + + PointerRec *getSomePointer() const { + return PtrList; + } + + /// getForwardedTarget - Return the real alias set this represents. If this + /// has been merged with another set and is forwarding, return the ultimate + /// destination set. This also implements the union-find collapsing as well. + AliasSet *getForwardedTarget(AliasSetTracker &AST) { + if (!Forward) return this; + + AliasSet *Dest = Forward->getForwardedTarget(AST); + if (Dest != Forward) { + Dest->addRef(); + Forward->dropRef(AST); + Forward = Dest; + } + return Dest; + } + + void removeFromTracker(AliasSetTracker &AST); + + void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, + const MDNode *TBAAInfo, + bool KnownMustAlias = false); + void addCallSite(CallSite CS, AliasAnalysis &AA); + void removeCallSite(CallSite CS) { + for (size_t i = 0, e = CallSites.size(); i != e; ++i) + if (CallSites[i] == CS.getInstruction()) { + CallSites[i] = CallSites.back(); + CallSites.pop_back(); + } + } + void setVolatile() { Volatile = true; } + + /// aliasesPointer - Return true if the specified pointer "may" (or must) + /// alias one of the members in the set. + /// + bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, + AliasAnalysis &AA) const; + bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { + AS.print(OS); + return OS; +} + + +class AliasSetTracker { + /// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be + /// notified whenever a Value is deleted. + class ASTCallbackVH : public CallbackVH { + AliasSetTracker *AST; + virtual void deleted(); + public: + ASTCallbackVH(Value *V, AliasSetTracker *AST = 0); + ASTCallbackVH &operator=(Value *V); + }; + /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to + /// compare and hash the value handle. + struct ASTCallbackVHDenseMapInfo : public DenseMapInfo {}; + + AliasAnalysis &AA; + ilist AliasSets; + + typedef DenseMap + PointerMapType; + + // Map from pointers to their node + PointerMapType PointerMap; + +public: + /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use + /// the specified alias analysis object to disambiguate load and store + /// addresses. + explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} + ~AliasSetTracker() { clear(); } + + /// add methods - These methods are used to add different types of + /// instructions to the alias sets. Adding a new instruction can result in + /// one of three actions happening: + /// + /// 1. If the instruction doesn't alias any other sets, create a new set. + /// 2. If the instruction aliases exactly one set, add it to the set + /// 3. If the instruction aliases multiple sets, merge the sets, and add + /// the instruction to the result. + /// + /// These methods return true if inserting the instruction resulted in the + /// addition of a new alias set (i.e., the pointer did not alias anything). + /// + bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location + bool add(LoadInst *LI); + bool add(StoreInst *SI); + bool add(VAArgInst *VAAI); + bool add(CallSite CS); // Call/Invoke instructions + bool add(CallInst *CI) { return add(CallSite(CI)); } + bool add(InvokeInst *II) { return add(CallSite(II)); } + bool add(Instruction *I); // Dispatch to one of the other add methods... + void add(BasicBlock &BB); // Add all instructions in basic block + void add(const AliasSetTracker &AST); // Add alias relations from another AST + + /// remove methods - These methods are used to remove all entries that might + /// be aliased by the specified instruction. These methods return true if any + /// alias sets were eliminated. + // Remove a location + bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); + bool remove(LoadInst *LI); + bool remove(StoreInst *SI); + bool remove(VAArgInst *VAAI); + bool remove(CallSite CS); + bool remove(CallInst *CI) { return remove(CallSite(CI)); } + bool remove(InvokeInst *II) { return remove(CallSite(II)); } + bool remove(Instruction *I); + void remove(AliasSet &AS); + + void clear(); + + /// getAliasSets - Return the alias sets that are active. + /// + const ilist &getAliasSets() const { return AliasSets; } + + /// getAliasSetForPointer - Return the alias set that the specified pointer + /// lives in. If the New argument is non-null, this method sets the value to + /// true if a new alias set is created to contain the pointer (because the + /// pointer didn't alias anything). + AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, + const MDNode *TBAAInfo, + bool *New = 0); + + /// getAliasSetForPointerIfExists - Return the alias set containing the + /// location specified if one exists, otherwise return null. + AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, + const MDNode *TBAAInfo) { + return findAliasSetForPointer(P, Size, TBAAInfo); + } + + /// containsPointer - Return true if the specified location is represented by + /// this alias set, false otherwise. This does not modify the AST object or + /// alias sets. + bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const; + + /// getAliasAnalysis - Return the underlying alias analysis object used by + /// this tracker. + AliasAnalysis &getAliasAnalysis() const { return AA; } + + /// deleteValue method - This method is used to remove a pointer value from + /// the AliasSetTracker entirely. It should be used when an instruction is + /// deleted from the program to update the AST. If you don't use this, you + /// would have dangling pointers to deleted instructions. + /// + void deleteValue(Value *PtrVal); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that it is ok + /// for clients that use this method to introduce the same value multiple + /// times: if the tracker already knows about a value, it will ignore the + /// request. + /// + void copyValue(Value *From, Value *To); + + + typedef ilist::iterator iterator; + typedef ilist::const_iterator const_iterator; + + const_iterator begin() const { return AliasSets.begin(); } + const_iterator end() const { return AliasSets.end(); } + + iterator begin() { return AliasSets.begin(); } + iterator end() { return AliasSets.end(); } + + void print(raw_ostream &OS) const; + void dump() const; + +private: + friend class AliasSet; + void removeAliasSet(AliasSet *AS); + + // getEntryFor - Just like operator[] on the map, except that it creates an + // entry for the pointer if it doesn't already exist. + AliasSet::PointerRec &getEntryFor(Value *V) { + AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)]; + if (Entry == 0) + Entry = new AliasSet::PointerRec(V); + return *Entry; + } + + AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, + AliasSet::AccessType E, + bool &NewSet) { + NewSet = false; + AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet); + AS.AccessTy |= E; + return AS; + } + AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, + const MDNode *TBAAInfo); + + AliasSet *findAliasSetForCallSite(CallSite CS); +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { + AST.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/CFGPrinter.h b/final/include/llvm/Analysis/CFGPrinter.h new file mode 100644 index 00000000000..ac8f59602da --- /dev/null +++ b/final/include/llvm/Analysis/CFGPrinter.h @@ -0,0 +1,111 @@ +//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the CFG printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFGPRINTER_H +#define LLVM_ANALYSIS_CFGPRINTER_H + +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/GraphWriter.h" + +namespace llvm { +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(const Function *F) { + return "CFG for '" + F->getNameStr() + "' function"; + } + + static std::string getSimpleNodeLabel(const BasicBlock *Node, + const Function *Graph) { + if (!Node->getName().empty()) + return Node->getNameStr(); + + std::string Str; + raw_string_ostream OS(Str); + + WriteAsOperand(OS, Node, false); + return OS.str(); + } + + static std::string getCompleteNodeLabel(const BasicBlock *Node, + const Function *Graph) { + std::string Str; + raw_string_ostream OS(Str); + + if (Node->getName().empty()) { + WriteAsOperand(OS, Node, false); + OS << ":"; + } + + OS << *Node; + std::string OutStr = OS.str(); + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } else if (OutStr[i] == ';') { // Delete comments! + unsigned Idx = OutStr.find('\n', i+1); // Find end of line + OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); + --i; + } + + return OutStr; + } + + std::string getNodeLabel(const BasicBlock *Node, + const Function *Graph) { + if (isSimple()) + return getSimpleNodeLabel(Node, Graph); + else + return getCompleteNodeLabel(Node, Graph); + } + + static std::string getEdgeSourceLabel(const BasicBlock *Node, + succ_const_iterator I) { + // Label source of conditional branches with "T" or "F" + if (const BranchInst *BI = dyn_cast(Node->getTerminator())) + if (BI->isConditional()) + return (I == succ_begin(Node)) ? "T" : "F"; + + // Label source of switch edges with the associated value. + if (const SwitchInst *SI = dyn_cast(Node->getTerminator())) { + unsigned SuccNo = I.getSuccessorIndex(); + + if (SuccNo == 0) return "def"; + + std::string Str; + raw_string_ostream OS(Str); + OS << SI->getCaseValue(SuccNo)->getValue(); + return OS.str(); + } + return ""; + } +}; +} // End llvm namespace + +namespace llvm { + class FunctionPass; + FunctionPass *createCFGPrinterPass (); + FunctionPass *createCFGOnlyPrinterPass (); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/CallGraph.h b/final/include/llvm/Analysis/CallGraph.h new file mode 100644 index 00000000000..089f322e4a8 --- /dev/null +++ b/final/include/llvm/Analysis/CallGraph.h @@ -0,0 +1,375 @@ +//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This interface is used to build and manipulate a call graph, which is a very +// useful tool for interprocedural optimization. +// +// Every function in a module is represented as a node in the call graph. The +// callgraph node keeps track of which functions the are called by the function +// corresponding to the node. +// +// A call graph may contain nodes where the function that they correspond to is +// null. These 'external' nodes are used to represent control flow that is not +// represented (or analyzable) in the module. In particular, this analysis +// builds one external node such that: +// 1. All functions in the module without internal linkage will have edges +// from this external node, indicating that they could be called by +// functions outside of the module. +// 2. All functions whose address is used for something more than a direct +// call, for example being stored into a memory location will also have an +// edge from this external node. Since they may be called by an unknown +// caller later, they must be tracked as such. +// +// There is a second external node added for calls that leave this module. +// Functions have a call edge to the external node iff: +// 1. The function is external, reflecting the fact that they could call +// anything without internal linkage or that has its address taken. +// 2. The function contains an indirect function call. +// +// As an extension in the future, there may be multiple nodes with a null +// function. These will be used when we can prove (through pointer analysis) +// that an indirect call site can call only a specific set of functions. +// +// Because of these properties, the CallGraph captures a conservative superset +// of all of the caller-callee relationships, which is useful for +// transformations. +// +// The CallGraph class also attempts to figure out what the root of the +// CallGraph is, which it currently does by looking for a function named 'main'. +// If no function named 'main' is found, the external node is used as the entry +// node, reflecting the fact that any function without internal linkage could +// be called into (which is common for libraries). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLGRAPH_H +#define LLVM_ANALYSIS_CALLGRAPH_H + +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/IncludeFile.h" +#include + +namespace llvm { + +class Function; +class Module; +class CallGraphNode; + +//===----------------------------------------------------------------------===// +// CallGraph class definition +// +class CallGraph { +protected: + Module *Mod; // The module this call graph represents + + typedef std::map FunctionMapTy; + FunctionMapTy FunctionMap; // Map from a function to its node + +public: + static char ID; // Class identification, replacement for typeinfo + //===--------------------------------------------------------------------- + // Accessors. + // + typedef FunctionMapTy::iterator iterator; + typedef FunctionMapTy::const_iterator const_iterator; + + /// getModule - Return the module the call graph corresponds to. + /// + Module &getModule() const { return *Mod; } + + inline iterator begin() { return FunctionMap.begin(); } + inline iterator end() { return FunctionMap.end(); } + inline const_iterator begin() const { return FunctionMap.begin(); } + inline const_iterator end() const { return FunctionMap.end(); } + + // Subscripting operators, return the call graph node for the provided + // function + inline const CallGraphNode *operator[](const Function *F) const { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + inline CallGraphNode *operator[](const Function *F) { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + + /// Returns the CallGraphNode which is used to represent undetermined calls + /// into the callgraph. Override this if you want behavioral inheritance. + virtual CallGraphNode* getExternalCallingNode() const { return 0; } + virtual CallGraphNode* getCallsExternalNode() const { return 0; } + + /// Return the root/main method in the module, or some other root node, such + /// as the externalcallingnode. Overload these if you behavioral + /// inheritance. + virtual CallGraphNode* getRoot() { return 0; } + virtual const CallGraphNode* getRoot() const { return 0; } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// removeFunctionFromModule - Unlink the function from this module, returning + /// it. Because this removes the function from the module, the call graph + /// node is destroyed. This is only valid if the function does not call any + /// other functions (ie, there are no edges in it's CGN). The easiest way to + /// do this is to dropAllReferences before calling this. + /// + Function *removeFunctionFromModule(CallGraphNode *CGN); + Function *removeFunctionFromModule(Function *F) { + return removeFunctionFromModule((*this)[F]); + } + + /// getOrInsertFunction - This method is identical to calling operator[], but + /// it will insert a new CallGraphNode for the specified function if one does + /// not already exist. + CallGraphNode *getOrInsertFunction(const Function *F); + + /// spliceFunction - Replace the function represented by this node by another. + /// This does not rescan the body of the function, so it is suitable when + /// splicing the body of one function to another while also updating all + /// callers from the old function to the new. + /// + void spliceFunction(const Function *From, const Function *To); + + //===--------------------------------------------------------------------- + // Pass infrastructure interface glue code. + // +protected: + CallGraph() {} + +public: + virtual ~CallGraph() { destroy(); } + + /// initialize - Call this method before calling other methods, + /// re/initializes the state of the CallGraph. + /// + void initialize(Module &M); + + void print(raw_ostream &o, Module *) const; + void dump() const; +protected: + // destroy - Release memory for the call graph + virtual void destroy(); +}; + +//===----------------------------------------------------------------------===// +// CallGraphNode class definition. +// +class CallGraphNode { + friend class CallGraph; + + AssertingVH F; + + // CallRecord - This is a pair of the calling instruction (a call or invoke) + // and the callgraph node being called. +public: + typedef std::pair CallRecord; +private: + std::vector CalledFunctions; + + /// NumReferences - This is the number of times that this CallGraphNode occurs + /// in the CalledFunctions array of this or other CallGraphNodes. + unsigned NumReferences; + + CallGraphNode(const CallGraphNode &); // DO NOT IMPLEMENT + void operator=(const CallGraphNode &); // DO NOT IMPLEMENT + + void DropRef() { --NumReferences; } + void AddRef() { ++NumReferences; } +public: + typedef std::vector CalledFunctionsVector; + + + // CallGraphNode ctor - Create a node for the specified function. + inline CallGraphNode(Function *f) : F(f), NumReferences(0) {} + ~CallGraphNode() { + assert(NumReferences == 0 && "Node deleted while references remain"); + } + + //===--------------------------------------------------------------------- + // Accessor methods. + // + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + // getFunction - Return the function that this call graph node represents. + Function *getFunction() const { return F; } + + inline iterator begin() { return CalledFunctions.begin(); } + inline iterator end() { return CalledFunctions.end(); } + inline const_iterator begin() const { return CalledFunctions.begin(); } + inline const_iterator end() const { return CalledFunctions.end(); } + inline bool empty() const { return CalledFunctions.empty(); } + inline unsigned size() const { return (unsigned)CalledFunctions.size(); } + + /// getNumReferences - Return the number of other CallGraphNodes in this + /// CallGraph that reference this node in their callee list. + unsigned getNumReferences() const { return NumReferences; } + + // Subscripting operator - Return the i'th called function. + // + CallGraphNode *operator[](unsigned i) const { + assert(i < CalledFunctions.size() && "Invalid index"); + return CalledFunctions[i].second; + } + + /// dump - Print out this call graph node. + /// + void dump() const; + void print(raw_ostream &OS) const; + + //===--------------------------------------------------------------------- + // Methods to keep a call graph up to date with a function that has been + // modified + // + + /// removeAllCalledFunctions - As the name implies, this removes all edges + /// from this CallGraphNode to any functions it calls. + void removeAllCalledFunctions() { + while (!CalledFunctions.empty()) { + CalledFunctions.back().second->DropRef(); + CalledFunctions.pop_back(); + } + } + + /// stealCalledFunctionsFrom - Move all the callee information from N to this + /// node. + void stealCalledFunctionsFrom(CallGraphNode *N) { + assert(CalledFunctions.empty() && + "Cannot steal callsite information if I already have some"); + std::swap(CalledFunctions, N->CalledFunctions); + } + + + /// addCalledFunction - Add a function to the list of functions called by this + /// one. + void addCalledFunction(CallSite CS, CallGraphNode *M) { + CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M)); + M->AddRef(); + } + + void removeCallEdge(iterator I) { + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + } + + + /// removeCallEdgeFor - This method removes the edge in the node for the + /// specified call site. Note that this method takes linear time, so it + /// should be used sparingly. + void removeCallEdgeFor(CallSite CS); + + /// removeAnyCallEdgeTo - This method removes all call edges from this node + /// to the specified callee function. This takes more time to execute than + /// removeCallEdgeTo, so it should not be used unless necessary. + void removeAnyCallEdgeTo(CallGraphNode *Callee); + + /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite + /// from this node to the specified callee function. + void removeOneAbstractEdgeTo(CallGraphNode *Callee); + + /// replaceCallEdge - This method replaces the edge in the node for the + /// specified call site with a new one. Note that this method takes linear + /// time, so it should be used sparingly. + void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode); + + /// allReferencesDropped - This is a special function that should only be + /// used by the CallGraph class. + void allReferencesDropped() { + NumReferences = 0; + } +}; + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for call graphs so that they can be treated as +// graphs by the generic graph algorithms. +// + +// Provide graph traits for tranversing call graphs using standard graph +// traversals. +template <> struct GraphTraits { + typedef CallGraphNode NodeType; + + typedef CallGraphNode::CallRecord CGNPairTy; + typedef std::pointer_to_unary_function CGNDerefFun; + + static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; } + + typedef mapped_iterator ChildIteratorType; + + static inline ChildIteratorType child_begin(NodeType *N) { + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); + } + static inline ChildIteratorType child_end (NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + static CallGraphNode *CGNDeref(CGNPairTy P) { + return P.second; + } + +}; + +template <> struct GraphTraits { + typedef const CallGraphNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } + static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } +}; + +template<> struct GraphTraits : public GraphTraits { + static NodeType *getEntryNode(CallGraph *CGN) { + return CGN->getExternalCallingNode(); // Start at the external node! + } + typedef std::pair PairTy; + typedef std::pointer_to_unary_function DerefFun; + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef mapped_iterator nodes_iterator; + static nodes_iterator nodes_begin(CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end (CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + + static CallGraphNode &CGdereference(PairTy P) { + return *P.second; + } +}; + +template<> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const CallGraph *CGN) { + return CGN->getExternalCallingNode(); + } + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef CallGraph::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); } + static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); } +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in CallGraph.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph) + +#endif diff --git a/final/include/llvm/Analysis/CaptureTracking.h b/final/include/llvm/Analysis/CaptureTracking.h new file mode 100644 index 00000000000..b3390f47d2f --- /dev/null +++ b/final/include/llvm/Analysis/CaptureTracking.h @@ -0,0 +1,33 @@ +//===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help determine which pointers are captured. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H +#define LLVM_ANALYSIS_CAPTURETRACKING_H + +namespace llvm { + class Value; + + /// PointerMayBeCaptured - Return true if this pointer value may be captured + /// by the enclosing function (which is required to exist). This routine can + /// be expensive, so consider caching the results. The boolean ReturnCaptures + /// specifies whether returning the value (or part of it) from the function + /// counts as capturing it or not. The boolean StoreCaptures specified + /// whether storing the value (or part of it) into memory anywhere + /// automatically counts as capturing it or not. + bool PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, + bool StoreCaptures); + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/CodeMetrics.h b/final/include/llvm/Analysis/CodeMetrics.h new file mode 100644 index 00000000000..75edfbbed2e --- /dev/null +++ b/final/include/llvm/Analysis/CodeMetrics.h @@ -0,0 +1,95 @@ +//===- CodeMetrics.h - Measures the weight of a function---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements various weight measurements for code, helping +// the Inliner and other passes decide whether to duplicate its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CODEMETRICS_H +#define LLVM_ANALYSIS_CODEMETRICS_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + // CodeMetrics - Calculate size and a few similar metrics for a set of + // basic blocks. + struct CodeMetrics { + /// NeverInline - True if this callee should never be inlined into a + /// caller. + // bool NeverInline; + + // True if this function contains a call to setjmp or _setjmp + bool callsSetJmp; + + // True if this function calls itself + bool isRecursive; + + // True if this function contains one or more indirect branches + bool containsIndirectBr; + + /// usesDynamicAlloca - True if this function calls alloca (in the C sense). + bool usesDynamicAlloca; + + /// NumInsts, NumBlocks - Keep track of how large each function is, which + /// is used to estimate the code size cost of inlining it. + unsigned NumInsts, NumBlocks; + + /// NumBBInsts - Keeps track of basic block code size estimates. + DenseMap NumBBInsts; + + /// NumCalls - Keep track of the number of calls to 'big' functions. + unsigned NumCalls; + + /// NumInlineCandidates - Keep track of the number of calls to internal + /// functions with only a single caller. These are likely targets for + /// future inlining, likely exposed by interleaved devirtualization. + unsigned NumInlineCandidates; + + /// NumVectorInsts - Keep track of how many instructions produce vector + /// values. The inliner is being more aggressive with inlining vector + /// kernels. + unsigned NumVectorInsts; + + /// NumRets - Keep track of how many Ret instructions the block contains. + unsigned NumRets; + + CodeMetrics() : callsSetJmp(false), isRecursive(false), + containsIndirectBr(false), usesDynamicAlloca(false), + NumInsts(0), NumBlocks(0), NumCalls(0), + NumInlineCandidates(0), NumVectorInsts(0), + NumRets(0) {} + + /// analyzeBasicBlock - Add information about the specified basic block + /// to the current structure. + void analyzeBasicBlock(const BasicBlock *BB); + + /// analyzeFunction - Add information about the specified function + /// to the current structure. + void analyzeFunction(Function *F); + + /// CountCodeReductionForConstant - Figure out an approximation for how + /// many instructions will be constant folded if the specified value is + /// constant. + unsigned CountCodeReductionForConstant(Value *V); + + /// CountBonusForConstant - Figure out an approximation for how much + /// per-call performance boost we can expect if the specified value is + /// constant. + unsigned CountBonusForConstant(Value *V); + + /// CountCodeReductionForAlloca - Figure out an approximation of how much + /// smaller the function will be if it is inlined into a context where an + /// argument becomes an alloca. + /// + unsigned CountCodeReductionForAlloca(Value *V); + }; +} + +#endif diff --git a/final/include/llvm/Analysis/ConstantFolding.h b/final/include/llvm/Analysis/ConstantFolding.h new file mode 100644 index 00000000000..f6b1f5ab991 --- /dev/null +++ b/final/include/llvm/Analysis/ConstantFolding.h @@ -0,0 +1,82 @@ +//===-- ConstantFolding.h - Fold instructions into constants --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into constants when all +// operands are constants, for example "sub i32 1, 0" -> "1". +// +// Also, to supplement the basic VMCore ConstantExpr simplifications, +// this file declares some additional folding routines that can make use of +// TargetData information. These functions cannot go in VMCore due to library +// dependency issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H +#define LLVM_ANALYSIS_CONSTANTFOLDING_H + +namespace llvm { + class Constant; + class ConstantExpr; + class Instruction; + class TargetData; + class Function; + class Type; + +/// ConstantFoldInstruction - Try to constant fold the specified instruction. +/// If successful, the constant result is returned, if not, null is returned. +/// Note that this fails if not all of the operands are constant. Otherwise, +/// this function can only fail when attempting to fold instructions like loads +/// and stores, which have no constant expression form. +Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); + +/// ConstantFoldConstantExpression - Attempt to fold the constant expression +/// using the specified TargetData. If successful, the constant result is +/// result is returned, if not, null is returned. +Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, + const TargetData *TD = 0); + +/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the +/// specified operands. If successful, the constant result is returned, if not, +/// null is returned. Note that this function can fail when attempting to +/// fold instructions like loads and stores, which have no constant expression +/// form. +/// +Constant *ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant *const *Ops, unsigned NumOps, + const TargetData *TD = 0); + +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *ConstantFoldCompareInstOperands(unsigned Predicate, + Constant *LHS, Constant *RHS, + const TargetData *TD = 0); + +/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would +/// produce if it is constant and determinable. If this is not determinable, +/// return null. +Constant *ConstantFoldLoadFromConstPtr(Constant *C, const TargetData *TD = 0); + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE); + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool canConstantFoldCallTo(const Function *F); + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant * +ConstantFoldCall(Function *F, Constant *const *Operands, unsigned NumOperands); +} + +#endif diff --git a/final/include/llvm/Analysis/ConstantsScanner.h b/final/include/llvm/Analysis/ConstantsScanner.h new file mode 100644 index 00000000000..cdaf68d75a6 --- /dev/null +++ b/final/include/llvm/Analysis/ConstantsScanner.h @@ -0,0 +1,93 @@ +//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements an iterator to walk through the constants referenced by +// a method. This is used by the Bitcode & Assembly writers to build constant +// pools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H +#define LLVM_ANALYSIS_CONSTANTSSCANNER_H + +#include "llvm/Support/InstIterator.h" + +namespace llvm { + +class Constant; + +class constant_iterator : public std::iterator { + const_inst_iterator InstI; // Method instruction iterator + unsigned OpIdx; // Operand index + + typedef constant_iterator _Self; + + inline bool isAtConstant() const { + assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() && + "isAtConstant called with invalid arguments!"); + return isa(InstI->getOperand(OpIdx)); + } + +public: + inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) { + // Advance to first constant... if we are not already at constant or end + if (InstI != inst_end(F) && // InstI is valid? + (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant? + operator++(); + } + + inline constant_iterator(const Function *F, bool) // end ctor + : InstI(inst_end(F)), OpIdx(0) { + } + + inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx && + InstI == x.InstI; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(isAtConstant() && "Dereferenced an iterator at the end!"); + return cast(InstI->getOperand(OpIdx)); + } + inline pointer operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement implementation + ++OpIdx; + do { + unsigned NumOperands = InstI->getNumOperands(); + while (OpIdx < NumOperands && !isAtConstant()) { + ++OpIdx; + } + + if (OpIdx < NumOperands) return *this; // Found a constant! + ++InstI; + OpIdx = 0; + } while (!InstI.atEnd()); + + return *this; // At the end of the method + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + inline bool atEnd() const { return InstI.atEnd(); } +}; + +inline constant_iterator constant_begin(const Function *F) { + return constant_iterator(F); +} + +inline constant_iterator constant_end(const Function *F) { + return constant_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/DIBuilder.h b/final/include/llvm/Analysis/DIBuilder.h new file mode 100644 index 00000000000..32a17e4f096 --- /dev/null +++ b/final/include/llvm/Analysis/DIBuilder.h @@ -0,0 +1,464 @@ +//===--- llvm/Analysis/DIBuilder.h - Debug Information Builder --*- 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 DIBuilder that is useful for creating debugging +// information entries in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DIBUILDER_H +#define LLVM_ANALYSIS_DIBUILDER_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class BasicBlock; + class Instruction; + class Function; + class Module; + class Value; + class LLVMContext; + class MDNode; + class StringRef; + class DIDescriptor; + class DIFile; + class DIEnumerator; + class DIType; + class DIArray; + class DIGlobalVariable; + class DINameSpace; + class DIVariable; + class DISubrange; + class DILexicalBlock; + class DISubprogram; + class DITemplateTypeParameter; + class DITemplateValueParameter; + + class DIBuilder { + private: + Module &M; + LLVMContext & VMContext; + MDNode *TheCU; + + Function *DeclareFn; // llvm.dbg.declare + Function *ValueFn; // llvm.dbg.value + + DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT + void operator=(const DIBuilder &); // DO NOT IMPLEMENT + + public: + explicit DIBuilder(Module &M); + const MDNode *getCU() { return TheCU; } + enum ComplexAddrKind { OpPlus=1, OpDeref }; + + /// createCompileUnit - A CompileUnit provides an anchor for all debugging + /// information generated during this instance of compilation. + /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 + /// @param File File name + /// @param Dir Directory + /// @param Producer String identify producer of debugging information. + /// Usuall this is a compiler version string. + /// @param isOptimized A boolean flag which indicates whether optimization + /// is ON or not. + /// @param Flags This string lists command line options. This string is + /// directly embedded in debug info output which may be used + /// by a tool analyzing generated debugging information. + /// @param RV This indicates runtime version for languages like + /// Objective-C. + void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + StringRef Producer, + bool isOptimized, StringRef Flags, unsigned RV); + + /// createFile - Create a file descriptor to hold debugging information + /// for a file. + DIFile createFile(StringRef Filename, StringRef Directory); + + /// createEnumerator - Create a single enumerator value. + DIEnumerator createEnumerator(StringRef Name, uint64_t Val); + + /// createBasicType - Create debugging information entry for a basic + /// type. + /// @param Name Type name. + /// @param SizeInBits Size of the type. + /// @param AlignInBits Type alignment. + /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. + DIType createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding); + + /// createQualifiedType - Create debugging information entry for a qualified + /// type, e.g. 'const int'. + /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type + /// @param FromTy Base Type. + DIType createQualifiedType(unsigned Tag, DIType FromTy); + + /// createPointerType - Create debugging information entry for a pointer. + /// @param PointeeTy Type pointed by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) + /// @param Name Pointer type name. (optional) + DIType createPointerType(DIType PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = StringRef()); + + /// createReferenceType - Create debugging information entry for a c++ + /// style reference. + DIType createReferenceType(DIType RTy); + + /// createTypedef - Create debugging information entry for a typedef. + /// @param Ty Original type. + /// @param Name Typedef name. + /// @param File File where this type is defined. + /// @param LineNo Line number. + DIType createTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo); + + /// createFriend - Create debugging information entry for a 'friend'. + DIType createFriend(DIType Ty, DIType FriendTy); + + /// createInheritance - Create debugging information entry to establish + /// inheritance relationship between two types. + /// @param Ty Original type. + /// @param BaseTy Base type. Ty is inherits from base. + /// @param BaseOffset Base offset. + /// @param Flags Flags to describe inheritance attribute, + /// e.g. private + DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, + unsigned Flags); + + /// createMemberType - Create debugging information entry for a member. + /// @param Name Member name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Ty Parent type. + DIType createMemberType(StringRef Name, DIFile File, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType Ty); + + /// createClassType - Create debugging information entry for a class. + /// @param Scope Scope in which this class is defined. + /// @param Name class name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param OffsetInBits Member offset. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements class members. + /// @param VTableHolder Debug info of the base class that contains vtable + /// for this type. This is used in + /// DW_AT_containing_type. See DWARF documentation + /// for more info. + /// @param TemplateParms Template type parameters. + DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DIType DerivedFrom, + DIArray Elements, MDNode *VTableHolder = 0, + MDNode *TemplateParms = 0); + + /// createStructType - Create debugging information entry for a struct. + /// @param Scope Scope in which this struct is defined. + /// @param Name Struct name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Struct elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// createUnionType - Create debugging information entry for an union. + /// @param Scope Scope in which this union is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Flags Flags to encode member attribute, e.g. private + /// @param Elements Union elements. + /// @param RunTimeLang Optional parameter, Objective-C runtime version. + DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang = 0); + + /// createTemplateTypeParameter - Create debugging information for template + /// type parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Type parameter name. + /// @param Ty Parameter type. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateTypeParameter + createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// createTemplateValueParameter - Create debugging information for template + /// value parameter. + /// @param Scope Scope in which this type is defined. + /// @param Name Value parameter name. + /// @param Ty Parameter type. + /// @param Value Constant parameter value. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + uint64_t Value, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + + /// createArrayType - Create debugging information entry for an array. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// createVectorType - Create debugging information entry for a vector type. + /// @param Size Array size. + /// @param AlignInBits Alignment. + /// @param Ty Element type. + /// @param Subscripts Subscripts. + DIType createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts); + + /// createEnumerationType - Create debugging information entry for an + /// enumeration. + /// @param Scope Scope in which this enumeration is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNo Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Elements Enumeration elements. + DIType createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements); + + /// createSubroutineType - Create subroutine type. + /// @param File File in which this subroutine is defined. + /// @param ParamterTypes An array of subroutine parameter types. This + /// includes return type at 0th index. + DIType createSubroutineType(DIFile File, DIArray ParameterTypes); + + /// createArtificialType - Create a new DIType with "artificial" flag set. + DIType createArtificialType(DIType Ty); + + /// createTemporaryType - Create a temporary forward-declared type. + DIType createTemporaryType(); + DIType createTemporaryType(DIFile F); + + /// retainType - Retain DIType in a module even if it is not referenced + /// through debug info anchors. + void retainType(DIType T); + + /// createUnspecifiedParameter - Create unspeicified type descriptor + /// for a subroutine type. + DIDescriptor createUnspecifiedParameter(); + + /// getOrCreateArray - Get a DIArray, create one if required. + DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements); + + /// getOrCreateSubrange - Create a descriptor for a value range. This + /// implicitly uniques the values returned. + DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi); + + /// createGlobalVariable - Create a new descriptor for the specified global. + /// @param Name Name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// createStaticVariable - Create a new descriptor for the specified + /// variable. + /// @param Conext Variable scope. + /// @param Name Name of the variable. + /// @param LinakgeName Mangled name of the variable. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, llvm::Value *Val); + + + /// createLocalVariable - Create a new descriptor for the specified + /// local variable. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param AlwaysPreserve Boolean. Set to true if debug info for this + /// variable should be preserved in optimized build. + /// @param Flags Flags, e.g. artificial variable. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. + DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, + DIFile File, unsigned LineNo, + DIType Ty, bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); + + + /// createComplexVariable - Create a new descriptor for the specified + /// variable which has a complex address expression for its address. + /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or + /// DW_TAG_arg_variable. + /// @param Scope Variable scope. + /// @param Name Variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type + /// @param Addr A pointer to a vector of complex address operations. + /// @param NumAddr Num of address operations in the vector. + /// @param ArgNo If this variable is an arugment then this argument's + /// number. 1 indicates 1st argument. + DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile F, unsigned LineNo, + DIType Ty, Value *const *Addr, + unsigned NumAddr, unsigned ArgNo = 0); + + /// createFunction - Create a new descriptor for the specified subprogram. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram createFunction(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// createMethod - Create a new descriptor for the specified C++ method. + /// See comments in DISubprogram for descriptions of these fields. + /// @param Scope Function scope. + /// @param Name Function name. + /// @param LinkageName Mangled function name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Function type. + /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isDefinition True if this is a function definition. + /// @param Virtuality Attributes describing virutallness. e.g. pure + /// virtual function. + /// @param VTableIndex Index no of this method in virtual table. + /// @param VTableHolder Type that holds vtable. + /// @param Flags e.g. is this function prototyped or not. + /// This flags are used to emit dwarf attributes. + /// @param isOptimized True if optimization is ON. + /// @param Fn llvm::Function pointer. + DISubprogram createMethod(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned Virtuality = 0, unsigned VTableIndex = 0, + MDNode *VTableHolder = 0, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = 0); + + /// createNameSpace - This creates new descriptor for a namespace + /// with the specified parent scope. + /// @param Scope Namespace scope + /// @param Name Name of this namespace + /// @param File Source file + /// @param LineNo Line number + DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo); + + + /// createLexicalBlock - This creates a descriptor for a lexical block + /// with the specified parent context. + /// @param Scope Parent lexical scope. + /// @param File Source file + /// @param Line Line number + /// @param Col Column number + DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, + unsigned Line, unsigned Col); + + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. + /// @param Storage llvm::Value of the variable + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, + Instruction *InsertBefore); + + + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertAtEnd Location for the new intrinsic. + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + BasicBlock *InsertAtEnd); + + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. + /// @param Val llvm::Value of the variable + /// @param Offset Offset + /// @param VarInfo Variable's debug info descriptor. + /// @param InsertBefore Location for the new intrinsic. + Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, + DIVariable VarInfo, + Instruction *InsertBefore); + + }; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/DOTGraphTraitsPass.h b/final/include/llvm/Analysis/DOTGraphTraitsPass.h new file mode 100644 index 00000000000..30741c4970a --- /dev/null +++ b/final/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -0,0 +1,83 @@ +//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Templates to create dotty viewer and printer passes for GraphTraits graphs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H +#define LLVM_ANALYSIS_DOT_GRAPHTRAITS_PASS_H + +#include "llvm/Pass.h" +#include "llvm/Analysis/CFGPrinter.h" + +namespace llvm { +template +struct DOTGraphTraitsViewer : public FunctionPass { + std::string Name; + + DOTGraphTraitsViewer(std::string GraphName, char &ID) : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + std::string Title, GraphName; + Graph = &getAnalysis(); + GraphName = DOTGraphTraits::getGraphName(Graph); + Title = GraphName + " for '" + F.getNameStr() + "' function"; + ViewGraph(Graph, Name, Simple, Title); + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } +}; + +template +struct DOTGraphTraitsPrinter : public FunctionPass { + + std::string Name; + + DOTGraphTraitsPrinter(std::string GraphName, char &ID) + : FunctionPass(ID) { + Name = GraphName; + } + + virtual bool runOnFunction(Function &F) { + Analysis *Graph; + std::string Filename = Name + "." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + Graph = &getAnalysis(); + + std::string Title, GraphName; + GraphName = DOTGraphTraits::getGraphName(Graph); + Title = GraphName + " for '" + F.getNameStr() + "' function"; + + if (ErrorInfo.empty()) + WriteGraph(File, Graph, Simple, Title); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } +}; +} +#endif diff --git a/final/include/llvm/Analysis/DebugInfo.h b/final/include/llvm/Analysis/DebugInfo.h new file mode 100644 index 00000000000..951fd3cf1f6 --- /dev/null +++ b/final/include/llvm/Analysis/DebugInfo.h @@ -0,0 +1,742 @@ +//===--- llvm/Analysis/DebugInfo.h - Debug Information Helpers --*- 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 bunch of datatypes that are useful for creating and +// walking debug info in LLVM IR form. They essentially provide wrappers around +// the information in the global variables that's needed when constructing the +// DWARF information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DEBUGINFO_H +#define LLVM_ANALYSIS_DEBUGINFO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Dwarf.h" + +namespace llvm { + class BasicBlock; + class Constant; + class Function; + class GlobalVariable; + class Module; + class Type; + class Value; + class DbgDeclareInst; + class Instruction; + class MDNode; + class NamedMDNode; + class LLVMContext; + class raw_ostream; + + class DIFile; + class DISubprogram; + class DILexicalBlock; + class DIVariable; + class DIType; + + /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. + /// This should not be stored in a container, because underly MDNode may + /// change in certain situations. + class DIDescriptor { + public: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4, + FlagVirtual = 1 << 5, + FlagArtificial = 1 << 6, + FlagExplicit = 1 << 7, + FlagPrototyped = 1 << 8 + }; + protected: + const MDNode *DbgNode; + + StringRef getStringField(unsigned Elt) const; + unsigned getUnsignedField(unsigned Elt) const { + return (unsigned)getUInt64Field(Elt); + } + uint64_t getUInt64Field(unsigned Elt) const; + DIDescriptor getDescriptorField(unsigned Elt) const; + + template + DescTy getFieldAs(unsigned Elt) const { + return DescTy(getDescriptorField(Elt)); + } + + GlobalVariable *getGlobalVariableField(unsigned Elt) const; + Constant *getConstantField(unsigned Elt) const; + Function *getFunctionField(unsigned Elt) const; + + public: + explicit DIDescriptor() : DbgNode(0) {} + explicit DIDescriptor(const MDNode *N) : DbgNode(N) {} + explicit DIDescriptor(const DIFile F); + explicit DIDescriptor(const DISubprogram F); + explicit DIDescriptor(const DILexicalBlock F); + explicit DIDescriptor(const DIVariable F); + explicit DIDescriptor(const DIType F); + + bool Verify() const { return DbgNode != 0; } + + operator MDNode *() const { return const_cast(DbgNode); } + MDNode *operator ->() const { return const_cast(DbgNode); } + + unsigned getVersion() const { + return getUnsignedField(0) & LLVMDebugVersionMask; + } + + unsigned getTag() const { + return getUnsignedField(0) & ~LLVMDebugVersionMask; + } + + /// print - print descriptor. + void print(raw_ostream &OS) const; + + /// dump - print descriptor to dbgs() with a newline. + void dump() const; + + bool isDerivedType() const; + bool isCompositeType() const; + bool isBasicType() const; + bool isVariable() const; + bool isSubprogram() const; + bool isGlobalVariable() const; + bool isScope() const; + bool isFile() const; + bool isCompileUnit() const; + bool isNameSpace() const; + bool isLexicalBlock() const; + bool isSubrange() const; + bool isEnumerator() const; + bool isType() const; + bool isGlobal() const; + bool isUnspecifiedParameter() const; + bool isTemplateTypeParameter() const; + bool isTemplateValueParameter() const; + }; + + /// DISubrange - This is used to represent ranges, for array bounds. + class DISubrange : public DIDescriptor { + public: + explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} + + int64_t getLo() const { return (int64_t)getUInt64Field(1); } + int64_t getHi() const { return (int64_t)getUInt64Field(2); } + }; + + /// DIArray - This descriptor holds an array of descriptors. + class DIArray : public DIDescriptor { + public: + explicit DIArray(const MDNode *N = 0) + : DIDescriptor(N) {} + + unsigned getNumElements() const; + DIDescriptor getElement(unsigned Idx) const { + return getDescriptorField(Idx); + } + }; + + /// DIScope - A base class for various scopes. + class DIScope : public DIDescriptor { + public: + explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} + virtual ~DIScope() {} + + StringRef getFilename() const; + StringRef getDirectory() const; + }; + + /// DICompileUnit - A wrapper for a compile unit. + class DICompileUnit : public DIScope { + public: + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} + + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getFilename() const { return getStringField(3); } + StringRef getDirectory() const { return getStringField(4); } + StringRef getProducer() const { return getStringField(5); } + + /// isMain - Each input file is encoded as a separate compile unit in LLVM + /// debugging information output. However, many target specific tool chains + /// prefer to encode only one compile unit in an object file. In this + /// situation, the LLVM code generator will include debugging information + /// entities in the compile unit that is marked as main compile unit. The + /// code generator accepts maximum one main compile unit per module. If a + /// module does not contain any main compile unit then the code generator + /// will emit multiple compile units in the output object file. + + bool isMain() const { return getUnsignedField(6) != 0; } + bool isOptimized() const { return getUnsignedField(7) != 0; } + StringRef getFlags() const { return getStringField(8); } + unsigned getRunTimeVersion() const { return getUnsignedField(9); } + + /// Verify - Verify that a compile unit is well formed. + bool Verify() const; + + /// print - print compile unit. + void print(raw_ostream &OS) const; + + /// dump - print compile unit to dbgs() with a newline. + void dump() const; + }; + + /// DIFile - This is a wrapper for a file. + class DIFile : public DIScope { + public: + explicit DIFile(const MDNode *N = 0) : DIScope(N) { + if (DbgNode && !isFile()) + DbgNode = 0; + } + StringRef getFilename() const { return getStringField(1); } + StringRef getDirectory() const { return getStringField(2); } + DICompileUnit getCompileUnit() const{ return getFieldAs(3); } + }; + + /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). + /// FIXME: it seems strange that this doesn't have either a reference to the + /// type/precision or a file/line pair for location info. + class DIEnumerator : public DIDescriptor { + public: + explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} + + StringRef getName() const { return getStringField(1); } + uint64_t getEnumValue() const { return getUInt64Field(2); } + }; + + /// DIType - This is a wrapper for a type. + /// FIXME: Types should be factored much better so that CV qualifiers and + /// others do not require a huge and empty descriptor full of zeros. + class DIType : public DIScope { + public: + protected: + // This ctor is used when the Tag has already been validated by a derived + // ctor. + DIType(const MDNode *N, bool, bool) : DIScope(N) {} + + public: + + /// Verify - Verify that a type descriptor is well formed. + bool Verify() const; + public: + explicit DIType(const MDNode *N); + explicit DIType() {} + virtual ~DIType() {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs(3); + + return getFieldAs(3).getCompileUnit(); + } + DIFile getFile() const { return getFieldAs(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + uint64_t getSizeInBits() const { return getUInt64Field(5); } + uint64_t getAlignInBits() const { return getUInt64Field(6); } + // FIXME: Offset is only used for DW_TAG_member nodes. Making every type + // carry this is just plain insane. + uint64_t getOffsetInBits() const { return getUInt64Field(7); } + unsigned getFlags() const { return getUnsignedField(8); } + bool isPrivate() const { + return (getFlags() & FlagPrivate) != 0; + } + bool isProtected() const { + return (getFlags() & FlagProtected) != 0; + } + bool isForwardDecl() const { + return (getFlags() & FlagFwdDecl) != 0; + } + // isAppleBlock - Return true if this is the Apple Blocks extension. + bool isAppleBlockExtension() const { + return (getFlags() & FlagAppleBlock) != 0; + } + bool isBlockByrefStruct() const { + return (getFlags() & FlagBlockByrefStruct) != 0; + } + bool isVirtual() const { + return (getFlags() & FlagVirtual) != 0; + } + bool isArtificial() const { + return (getFlags() & FlagArtificial) != 0; + } + bool isValid() const { + return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); + } + StringRef getDirectory() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getDirectory(); + + return getFieldAs(3).getDirectory(); + } + StringRef getFilename() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getFilename(); + + return getFieldAs(3).getFilename(); + } + + /// replaceAllUsesWith - Replace all uses of debug info referenced by + /// this descriptor. + void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(MDNode *D); + + /// print - print type. + void print(raw_ostream &OS) const; + + /// dump - print type to dbgs() with a newline. + void dump() const; + }; + + /// DIBasicType - A basic type, like 'int' or 'float'. + class DIBasicType : public DIType { + public: + explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} + + unsigned getEncoding() const { return getUnsignedField(9); } + + /// Verify - Verify that a basic type descriptor is well formed. + bool Verify() const; + + /// print - print basic type. + void print(raw_ostream &OS) const; + + /// dump - print basic type to dbgs() with a newline. + void dump() const; + }; + + /// DIDerivedType - A simple derived type, like a const qualified type, + /// a typedef, a pointer or reference, etc. + class DIDerivedType : public DIType { + protected: + explicit DIDerivedType(const MDNode *N, bool, bool) + : DIType(N, true, true) {} + public: + explicit DIDerivedType(const MDNode *N = 0) + : DIType(N, true, true) {} + + DIType getTypeDerivedFrom() const { return getFieldAs(9); } + + /// getOriginalTypeSize - If this type is derived from a base type then + /// return base type size. + uint64_t getOriginalTypeSize() const; + + /// Verify - Verify that a derived type descriptor is well formed. + bool Verify() const; + + /// print - print derived type. + void print(raw_ostream &OS) const; + + /// dump - print derived type to dbgs() with a newline. + void dump() const; + }; + + /// DICompositeType - This descriptor holds a type that can refer to multiple + /// other types, like a function or struct. + /// FIXME: Why is this a DIDerivedType?? + class DICompositeType : public DIDerivedType { + public: + explicit DICompositeType(const MDNode *N = 0) + : DIDerivedType(N, true, true) { + if (N && !isCompositeType()) + DbgNode = 0; + } + + DIArray getTypeArray() const { return getFieldAs(10); } + unsigned getRunTimeLang() const { return getUnsignedField(11); } + DICompositeType getContainingType() const { + return getFieldAs(12); + } + DIArray getTemplateParams() const { return getFieldAs(13); } + + /// Verify - Verify that a composite type descriptor is well formed. + bool Verify() const; + + /// print - print composite type. + void print(raw_ostream &OS) const; + + /// dump - print composite type to dbgs() with a newline. + void dump() const; + }; + + /// DITemplateTypeParameter - This is a wrapper for template type parameter. + class DITemplateTypeParameter : public DIDescriptor { + public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs(3); } + StringRef getFilename() const { + return getFieldAs(4).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + }; + + /// DITemplateValueParameter - This is a wrapper for template value parameter. + class DITemplateValueParameter : public DIDescriptor { + public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs(3); } + uint64_t getValue() const { return getUInt64Field(4); } + StringRef getFilename() const { + return getFieldAs(5).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + }; + + /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). + class DISubprogram : public DIScope { + public: + explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} + + DIScope getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs(6); + + return getFieldAs(6).getCompileUnit(); + } + unsigned getLineNumber() const { return getUnsignedField(7); } + DICompositeType getType() const { return getFieldAs(8); } + + /// getReturnTypeName - Subprogram return types are encoded either as + /// DIType or as DICompositeType. + StringRef getReturnTypeName() const { + DICompositeType DCT(getFieldAs(8)); + if (DCT.Verify()) { + DIArray A = DCT.getTypeArray(); + DIType T(A.getElement(0)); + return T.getName(); + } + DIType T(getFieldAs(8)); + return T.getName(); + } + + /// isLocalToUnit - Return true if this subprogram is local to the current + /// compile unit, like 'static' in C. + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + + unsigned getVirtuality() const { return getUnsignedField(11); } + unsigned getVirtualIndex() const { return getUnsignedField(12); } + + DICompositeType getContainingType() const { + return getFieldAs(13); + } + unsigned isArtificial() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return getUnsignedField(14); + return (getUnsignedField(14) & FlagArtificial) != 0; + } + /// isPrivate - Return true if this subprogram has "private" + /// access specifier. + bool isPrivate() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagPrivate) != 0; + } + /// isProtected - Return true if this subprogram has "protected" + /// access specifier. + bool isProtected() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagProtected) != 0; + } + /// isExplicit - Return true if this subprogram is marked as explicit. + bool isExplicit() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagExplicit) != 0; + } + /// isPrototyped - Return true if this subprogram is prototyped. + bool isPrototyped() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(14) & FlagPrototyped) != 0; + } + + unsigned isOptimized() const; + + StringRef getFilename() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getFilename(); + + return getFieldAs(6).getFilename(); + } + + StringRef getDirectory() const { + if (getVersion() == llvm::LLVMDebugVersion7) + return getCompileUnit().getFilename(); + + return getFieldAs(6).getDirectory(); + } + + /// Verify - Verify that a subprogram descriptor is well formed. + bool Verify() const; + + /// print - print subprogram. + void print(raw_ostream &OS) const; + + /// dump - print subprogram to dbgs() with a newline. + void dump() const; + + /// describes - Return true if this subprogram provides debugging + /// information for the function F. + bool describes(const Function *F); + + Function *getFunction() const { return getFunctionField(16); } + }; + + /// DIGlobalVariable - This is a wrapper for a global variable. + class DIGlobalVariable : public DIDescriptor { + public: + explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs(6); + + DIFile F = getFieldAs(6); + return F.getCompileUnit(); + } + + unsigned getLineNumber() const { return getUnsignedField(7); } + DIType getType() const { return getFieldAs(8); } + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } + + GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } + Constant *getConstant() const { return getConstantField(11); } + + /// Verify - Verify that a global variable descriptor is well formed. + bool Verify() const; + + /// print - print global variable. + void print(raw_ostream &OS) const; + + /// dump - print global variable to dbgs() with a newline. + void dump() const; + }; + + /// DIVariable - This is a wrapper for a variable (e.g. parameter, local, + /// global etc). + class DIVariable : public DIDescriptor { + public: + explicit DIVariable(const MDNode *N = 0) + : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs(3); + + DIFile F = getFieldAs(3); + return F.getCompileUnit(); + } + unsigned getLineNumber() const { + return (getUnsignedField(4) << 8) >> 8; + } + unsigned getArgNumber() const { + unsigned L = getUnsignedField(4); + return L >> 24; + } + DIType getType() const { return getFieldAs(5); } + + /// isArtificial - Return true if this variable is marked as "artificial". + bool isArtificial() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return false; + return (getUnsignedField(6) & FlagArtificial) != 0; + } + + + /// Verify - Verify that a variable descriptor is well formed. + bool Verify() const; + + /// HasComplexAddr - Return true if the variable has a complex address. + bool hasComplexAddress() const { + return getNumAddrElements() > 0; + } + + unsigned getNumAddrElements() const; + + uint64_t getAddrElement(unsigned Idx) const { + return getUInt64Field(Idx+6); + } + + /// isBlockByrefVariable - Return true if the variable was declared as + /// a "__block" variable (Apple Blocks). + bool isBlockByrefVariable() const { + return getType().isBlockByrefStruct(); + } + + /// isInlinedFnArgument - Return trule if this variable provides debugging + /// information for an inlined function arguments. + bool isInlinedFnArgument(const Function *CurFn); + + /// print - print variable. + void print(raw_ostream &OS) const; + + /// dump - print variable to dbgs() with a newline. + void dump() const; + }; + + /// DILexicalBlock - This is a wrapper for a lexical block. + class DILexicalBlock : public DIScope { + public: + explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs(1); } + unsigned getLineNumber() const { return getUnsignedField(2); } + unsigned getColumnNumber() const { return getUnsignedField(3); } + StringRef getDirectory() const { + StringRef dir = getFieldAs(4).getDirectory(); + return !dir.empty() ? dir : getContext().getDirectory(); + } + StringRef getFilename() const { + StringRef filename = getFieldAs(4).getFilename(); + return !filename.empty() ? filename : getContext().getFilename(); + } + }; + + /// DINameSpace - A wrapper for a C++ style name space. + class DINameSpace : public DIScope { + public: + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + StringRef getDirectory() const { + return getFieldAs(3).getDirectory(); + } + StringRef getFilename() const { + return getFieldAs(3).getFilename(); + } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs(3); + + return getFieldAs(3).getCompileUnit(); + } + unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; + }; + + /// DILocation - This object holds location information. This object + /// is not associated with any DWARF tag. + class DILocation : public DIDescriptor { + public: + explicit DILocation(const MDNode *N) : DIDescriptor(N) { } + + unsigned getLineNumber() const { return getUnsignedField(0); } + unsigned getColumnNumber() const { return getUnsignedField(1); } + DIScope getScope() const { return getFieldAs(2); } + DILocation getOrigLocation() const { return getFieldAs(3); } + StringRef getFilename() const { return getScope().getFilename(); } + StringRef getDirectory() const { return getScope().getDirectory(); } + bool Verify() const; + }; + + /// getDISubprogram - Find subprogram that is enclosing this scope. + DISubprogram getDISubprogram(const MDNode *Scope); + + /// getDICompositeType - Find underlying composite type. + DICompositeType getDICompositeType(DIType T); + + /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable + /// to hold function specific information. + NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, StringRef Name); + + /// getFnSpecificMDNode - Return a NameMDNode, if available, that is + /// suitable to hold function specific information. + NamedMDNode *getFnSpecificMDNode(const Module &M, StringRef Name); + + class DebugInfoFinder { + public: + /// processModule - Process entire module and collect debug info + /// anchors. + void processModule(Module &M); + + private: + /// processType - Process DIType. + void processType(DIType DT); + + /// processLexicalBlock - Process DILexicalBlock. + void processLexicalBlock(DILexicalBlock LB); + + /// processSubprogram - Process DISubprogram. + void processSubprogram(DISubprogram SP); + + /// processDeclare - Process DbgDeclareInst. + void processDeclare(DbgDeclareInst *DDI); + + /// processLocation - Process DILocation. + void processLocation(DILocation Loc); + + /// addCompileUnit - Add compile unit into CUs. + bool addCompileUnit(DICompileUnit CU); + + /// addGlobalVariable - Add global variable into GVs. + bool addGlobalVariable(DIGlobalVariable DIG); + + // addSubprogram - Add subprgoram into SPs. + bool addSubprogram(DISubprogram SP); + + /// addType - Add type into Tys. + bool addType(DIType DT); + + public: + typedef SmallVector::const_iterator iterator; + iterator compile_unit_begin() const { return CUs.begin(); } + iterator compile_unit_end() const { return CUs.end(); } + iterator subprogram_begin() const { return SPs.begin(); } + iterator subprogram_end() const { return SPs.end(); } + iterator global_variable_begin() const { return GVs.begin(); } + iterator global_variable_end() const { return GVs.end(); } + iterator type_begin() const { return TYs.begin(); } + iterator type_end() const { return TYs.end(); } + + unsigned compile_unit_count() const { return CUs.size(); } + unsigned global_variable_count() const { return GVs.size(); } + unsigned subprogram_count() const { return SPs.size(); } + unsigned type_count() const { return TYs.size(); } + + private: + SmallVector CUs; // Compile Units + SmallVector SPs; // Subprograms + SmallVector GVs; // Global Variables; + SmallVector TYs; // Types + SmallPtrSet NodesSeen; + }; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/DomPrinter.h b/final/include/llvm/Analysis/DomPrinter.h new file mode 100644 index 00000000000..0ed28994995 --- /dev/null +++ b/final/include/llvm/Analysis/DomPrinter.h @@ -0,0 +1,30 @@ +//===-- DomPrinter.h - Dom printer external interface ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the dominance tree printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMPRINTER_H +#define LLVM_ANALYSIS_DOMPRINTER_H + +namespace llvm { + class FunctionPass; + FunctionPass *createDomPrinterPass(); + FunctionPass *createDomOnlyPrinterPass(); + FunctionPass *createDomViewerPass(); + FunctionPass *createDomOnlyViewerPass(); + FunctionPass *createPostDomPrinterPass(); + FunctionPass *createPostDomOnlyPrinterPass(); + FunctionPass *createPostDomViewerPass(); + FunctionPass *createPostDomOnlyViewerPass(); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/DominanceFrontier.h b/final/include/llvm/Analysis/DominanceFrontier.h new file mode 100644 index 00000000000..d7f74af1c65 --- /dev/null +++ b/final/include/llvm/Analysis/DominanceFrontier.h @@ -0,0 +1,189 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- 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 DominanceFrontier class, which calculate and holds the +// dominance frontier for a function. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H + +#include "llvm/Analysis/Dominators.h" +#include +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +class DominanceFrontierBase : public FunctionPass { +public: + typedef std::set DomSetType; // Dom set for a bb + typedef std::map DomSetMapType; // Dom set map +protected: + DomSetMapType Frontiers; + std::vector Roots; + const bool IsPostDominators; + +public: + DominanceFrontierBase(char &ID, bool isPostDom) + : FunctionPass(ID), IsPostDominators(isPostDom) {} + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } + + virtual void releaseMemory() { Frontiers.clear(); } + + // Accessor interface: + typedef DomSetMapType::iterator iterator; + typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + + iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + return Frontiers.insert(std::make_pair(BB, frontier)).first; + } + + /// removeBlock - Remove basic block BB's frontier. + void removeBlock(BasicBlock *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); + } + + void addToFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + I->second.insert(Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); + } + + /// compareDomSet - Return false if two domsets match. Otherwise + /// return true; + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + std::set tmpSet; + for (DomSetType::const_iterator I = DS2.begin(), + E = DS2.end(); I != E; ++I) + tmpSet.insert(*I); + + for (DomSetType::const_iterator I = DS1.begin(), + E = DS1.end(); I != E; ) { + BasicBlock *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but not in DS2. + return true; + } + + if (!tmpSet.empty()) + // There are nodes that are in DS2 but not in DS1. + return true; + + // DS1 and DS2 matches. + return false; + } + + /// compare - Return true if the other dominance frontier base matches + /// this dominance frontier base. Otherwise return false. + bool compare(DominanceFrontierBase &Other) const { + DomSetMapType tmpFrontiers; + for (DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); I != E; ) { + BasicBlock *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; + } + + /// print - Convert to human readable form + /// + virtual void print(raw_ostream &OS, const Module* = 0) const; + + /// dump - Dump the dominance frontier to dbgs(). + void dump() const; +}; + + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +class DominanceFrontier : public DominanceFrontierBase { +public: + static char ID; // Pass ID, replacement for typeid + DominanceFrontier() : + DominanceFrontierBase(ID, false) { + initializeDominanceFrontierPass(*PassRegistry::getPassRegistry()); + } + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + DominatorTree &DT = getAnalysis(); + Roots = DT.getRoots(); + assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); + calculate(DT, DT[Roots[0]]); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + const DomSetType &calculate(const DominatorTree &DT, + const DomTreeNode *Node); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/DominatorInternals.h b/final/include/llvm/Analysis/DominatorInternals.h new file mode 100644 index 00000000000..ae552b05abf --- /dev/null +++ b/final/include/llvm/Analysis/DominatorInternals.h @@ -0,0 +1,289 @@ +//=== llvm/Analysis/DominatorInternals.h - Dominator Calculation -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H +#define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H + +#include "llvm/Analysis/Dominators.h" +#include "llvm/ADT/SmallPtrSet.h" + +//===----------------------------------------------------------------------===// +// +// DominatorTree construction - This pass constructs immediate dominator +// information for a flow-graph based on the algorithm described in this +// document: +// +// A Fast Algorithm for Finding Dominators in a Flowgraph +// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. +// +// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns +// out that the theoretically slower O(n*log(n)) implementation is actually +// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. +// +//===----------------------------------------------------------------------===// + +namespace llvm { + +template +unsigned DFSPass(DominatorTreeBase& DT, + typename GraphT::NodeType* V, unsigned N) { + // This is more understandable as a recursive algorithm, but we can't use the + // recursive algorithm due to stack depth issues. Keep it here for + // documentation purposes. +#if 0 + InfoRec &VInfo = DT.Info[DT.Roots[i]]; + VInfo.DFSNum = VInfo.Semi = ++N; + VInfo.Label = V; + + Vertex.push_back(V); // Vertex[n] = V; + + for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) { + InfoRec &SuccVInfo = DT.Info[*SI]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = V; + N = DTDFSPass(DT, *SI, N); + } + } +#else + bool IsChildOfArtificialExit = (N != 0); + + SmallVector, 32> Worklist; + Worklist.push_back(std::make_pair(V, GraphT::child_begin(V))); + while (!Worklist.empty()) { + typename GraphT::NodeType* BB = Worklist.back().first; + typename GraphT::ChildIteratorType NextSucc = Worklist.back().second; + + typename DominatorTreeBase::InfoRec &BBInfo = + DT.Info[BB]; + + // First time we visited this BB? + if (NextSucc == GraphT::child_begin(BB)) { + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = BB; + + DT.Vertex.push_back(BB); // Vertex[n] = V; + + if (IsChildOfArtificialExit) + BBInfo.Parent = 1; + + IsChildOfArtificialExit = false; + } + + // store the DFS number of the current BB - the reference to BBInfo might + // get invalidated when processing the successors. + unsigned BBDFSNum = BBInfo.DFSNum; + + // If we are done with this block, remove it from the worklist. + if (NextSucc == GraphT::child_end(BB)) { + Worklist.pop_back(); + continue; + } + + // Increment the successor number for the next time we get to it. + ++Worklist.back().second; + + // Visit the successor next, if it isn't already visited. + typename GraphT::NodeType* Succ = *NextSucc; + + typename DominatorTreeBase::InfoRec &SuccVInfo = + DT.Info[Succ]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = BBDFSNum; + Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ))); + } + } +#endif + return N; +} + +template +typename GraphT::NodeType* +Eval(DominatorTreeBase& DT, + typename GraphT::NodeType *VIn, unsigned LastLinked) { + typename DominatorTreeBase::InfoRec &VInInfo = + DT.Info[VIn]; + if (VInInfo.DFSNum < LastLinked) + return VIn; + + SmallVector Work; + SmallPtrSet Visited; + + if (VInInfo.Parent >= LastLinked) + Work.push_back(VIn); + + while (!Work.empty()) { + typename GraphT::NodeType* V = Work.back(); + typename DominatorTreeBase::InfoRec &VInfo = + DT.Info[V]; + typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent]; + + // Process Ancestor first + if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) { + Work.push_back(VAncestor); + continue; + } + Work.pop_back(); + + // Update VInfo based on Ancestor info + if (VInfo.Parent < LastLinked) + continue; + + typename DominatorTreeBase::InfoRec &VAInfo = + DT.Info[VAncestor]; + typename GraphT::NodeType* VAncestorLabel = VAInfo.Label; + typename GraphT::NodeType* VLabel = VInfo.Label; + if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) + VInfo.Label = VAncestorLabel; + VInfo.Parent = VAInfo.Parent; + } + + return VInInfo.Label; +} + +template +void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F) { + typedef GraphTraits GraphT; + + unsigned N = 0; + bool MultipleRoots = (DT.Roots.size() > 1); + if (MultipleRoots) { + typename DominatorTreeBase::InfoRec &BBInfo = + DT.Info[NULL]; + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = NULL; + + DT.Vertex.push_back(NULL); // Vertex[n] = V; + } + + // Step #1: Number blocks in depth-first order and initialize variables used + // in later stages of the algorithm. + for (unsigned i = 0, e = static_cast(DT.Roots.size()); + i != e; ++i) + N = DFSPass(DT, DT.Roots[i], N); + + // it might be that some blocks did not get a DFS number (e.g., blocks of + // infinite loops). In these cases an artificial exit node is required. + MultipleRoots |= (DT.isPostDominator() && N != F.size()); + + // When naively implemented, the Lengauer-Tarjan algorithm requires a separate + // bucket for each vertex. However, this is unnecessary, because each vertex + // is only placed into a single bucket (that of its semidominator), and each + // vertex's bucket is processed before it is added to any bucket itself. + // + // Instead of using a bucket per vertex, we use a single array Buckets that + // has two purposes. Before the vertex V with preorder number i is processed, + // Buckets[i] stores the index of the first element in V's bucket. After V's + // bucket is processed, Buckets[i] stores the index of the next element in the + // bucket containing V, if any. + SmallVector Buckets; + Buckets.resize(N + 1); + for (unsigned i = 1; i <= N; ++i) + Buckets[i] = i; + + for (unsigned i = N; i >= 2; --i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename DominatorTreeBase::InfoRec &WInfo = + DT.Info[W]; + + // Step #2: Implicitly define the immediate dominator of vertices + for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + typename GraphT::NodeType* U = Eval(DT, V, i + 1); + DT.IDoms[V] = DT.Info[U].Semi < i ? U : W; + } + + // Step #3: Calculate the semidominators of all vertices + + // initialize the semi dominator to point to the parent node + WInfo.Semi = WInfo.Parent; + typedef GraphTraits > InvTraits; + for (typename InvTraits::ChildIteratorType CI = + InvTraits::child_begin(W), + E = InvTraits::child_end(W); CI != E; ++CI) { + typename InvTraits::NodeType *N = *CI; + if (DT.Info.count(N)) { // Only if this predecessor is reachable! + unsigned SemiU = DT.Info[Eval(DT, N, i + 1)].Semi; + if (SemiU < WInfo.Semi) + WInfo.Semi = SemiU; + } + } + + // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is + // necessarily parent(V). In this case, set idom(V) here and avoid placing + // V into a bucket. + if (WInfo.Semi == WInfo.Parent) { + DT.IDoms[W] = DT.Vertex[WInfo.Parent]; + } else { + Buckets[i] = Buckets[WInfo.Semi]; + Buckets[WInfo.Semi] = i; + } + } + + if (N >= 1) { + typename GraphT::NodeType* Root = DT.Vertex[1]; + for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + DT.IDoms[V] = Root; + } + } + + // Step #4: Explicitly define the immediate dominator of each vertex + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename GraphT::NodeType*& WIDom = DT.IDoms[W]; + if (WIDom != DT.Vertex[DT.Info[W].Semi]) + WIDom = DT.IDoms[WIDom]; + } + + if (DT.Roots.empty()) return; + + // Add a node for the root. This node might be the actual root, if there is + // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) + // which postdominates all real exits if there are multiple exit blocks, or + // an infinite loop. + typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : 0; + + DT.DomTreeNodes[Root] = DT.RootNode = + new DomTreeNodeBase(Root, 0); + + // Loop over all of the reachable blocks in the function... + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + + DomTreeNodeBase *BBNode = DT.DomTreeNodes[W]; + if (BBNode) continue; // Haven't calculated this node yet? + + typename GraphT::NodeType* ImmDom = DT.getIDom(W); + + assert(ImmDom || DT.DomTreeNodes[NULL]); + + // Get or calculate the node for the immediate dominator + DomTreeNodeBase *IDomNode = + DT.getNodeForBlock(ImmDom); + + // Add a new tree node for this BasicBlock, and link it as a child of + // IDomNode + DomTreeNodeBase *C = + new DomTreeNodeBase(W, IDomNode); + DT.DomTreeNodes[W] = IDomNode->addChild(C); + } + + // Free temporary memory used to construct idom's + DT.IDoms.clear(); + DT.Info.clear(); + std::vector().swap(DT.Vertex); + + DT.updateDFSNumbers(); +} + +} + +#endif diff --git a/final/include/llvm/Analysis/Dominators.h b/final/include/llvm/Analysis/Dominators.h new file mode 100644 index 00000000000..230e83d3012 --- /dev/null +++ b/final/include/llvm/Analysis/Dominators.h @@ -0,0 +1,876 @@ +//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- 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 DominatorTree class, which provides fast and efficient +// dominance queries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINATORS_H +#define LLVM_ANALYSIS_DOMINATORS_H + +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominatorBase - Base class that other, more interesting dominator analyses +/// inherit from. +/// +template +class DominatorBase { +protected: + std::vector Roots; + const bool IsPostDominators; + inline explicit DominatorBase(bool isPostDom) : + Roots(), IsPostDominators(isPostDom) {} +public: + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } +}; + + +//===----------------------------------------------------------------------===// +// DomTreeNode - Dominator Tree Node +template class DominatorTreeBase; +struct PostDominatorTree; +class MachineBasicBlock; + +template +class DomTreeNodeBase { + NodeT *TheBB; + DomTreeNodeBase *IDom; + std::vector *> Children; + int DFSNumIn, DFSNumOut; + + template friend class DominatorTreeBase; + friend struct PostDominatorTree; +public: + typedef typename std::vector *>::iterator iterator; + typedef typename std::vector *>::const_iterator + const_iterator; + + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } + const_iterator begin() const { return Children.begin(); } + const_iterator end() const { return Children.end(); } + + NodeT *getBlock() const { return TheBB; } + DomTreeNodeBase *getIDom() const { return IDom; } + const std::vector*> &getChildren() const { + return Children; + } + + DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom) + : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { } + + DomTreeNodeBase *addChild(DomTreeNodeBase *C) { + Children.push_back(C); + return C; + } + + size_t getNumChildren() const { + return Children.size(); + } + + void clearAllChildren() { + Children.clear(); + } + + bool compare(DomTreeNodeBase *Other) { + if (getNumChildren() != Other->getNumChildren()) + return true; + + SmallPtrSet OtherChildren; + for (iterator I = Other->begin(), E = Other->end(); I != E; ++I) { + NodeT *Nd = (*I)->getBlock(); + OtherChildren.insert(Nd); + } + + for (iterator I = begin(), E = end(); I != E; ++I) { + NodeT *N = (*I)->getBlock(); + if (OtherChildren.count(N) == 0) + return true; + } + return false; + } + + void setIDom(DomTreeNodeBase *NewIDom) { + assert(IDom && "No immediate dominator?"); + if (IDom != NewIDom) { + typename std::vector*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), this); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + + // Switch to new dominator + IDom = NewIDom; + IDom->Children.push_back(this); + } + } + + /// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do + /// not call them. + unsigned getDFSNumIn() const { return DFSNumIn; } + unsigned getDFSNumOut() const { return DFSNumOut; } +private: + // Return true if this node is dominated by other. Use this only if DFS info + // is valid. + bool DominatedBy(const DomTreeNodeBase *other) const { + return this->DFSNumIn >= other->DFSNumIn && + this->DFSNumOut <= other->DFSNumOut; + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); + +template +static raw_ostream &operator<<(raw_ostream &o, + const DomTreeNodeBase *Node) { + if (Node->getBlock()) + WriteAsOperand(o, Node->getBlock(), false); + else + o << " <>"; + + o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}"; + + return o << "\n"; +} + +template +static void PrintDomTree(const DomTreeNodeBase *N, raw_ostream &o, + unsigned Lev) { + o.indent(2*Lev) << "[" << Lev << "] " << N; + for (typename DomTreeNodeBase::const_iterator I = N->begin(), + E = N->end(); I != E; ++I) + PrintDomTree(*I, o, Lev+1); +} + +typedef DomTreeNodeBase DomTreeNode; + +//===----------------------------------------------------------------------===// +/// DominatorTree - Calculate the immediate dominator tree for a function. +/// + +template +void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F); + +template +class DominatorTreeBase : public DominatorBase { +protected: + typedef DenseMap*> DomTreeNodeMapType; + DomTreeNodeMapType DomTreeNodes; + DomTreeNodeBase *RootNode; + + bool DFSInfoValid; + unsigned int SlowQueries; + // Information record used during immediate dominators computation. + struct InfoRec { + unsigned DFSNum; + unsigned Parent; + unsigned Semi; + NodeT *Label; + + InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {} + }; + + DenseMap IDoms; + + // Vertex - Map the DFS number to the BasicBlock* + std::vector Vertex; + + // Info - Collection of information used during the computation of idoms. + DenseMap Info; + + void reset() { + for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), + E = DomTreeNodes.end(); I != E; ++I) + delete I->second; + DomTreeNodes.clear(); + IDoms.clear(); + this->Roots.clear(); + Vertex.clear(); + RootNode = 0; + } + + // NewBB is split and now it has one successor. Update dominator tree to + // reflect this change. + template + void Split(DominatorTreeBase& DT, + typename GraphT::NodeType* NewBB) { + assert(std::distance(GraphT::child_begin(NewBB), + GraphT::child_end(NewBB)) == 1 && + "NewBB should have a single successor!"); + typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB); + + std::vector PredBlocks; + typedef GraphTraits > InvTraits; + for (typename InvTraits::ChildIteratorType PI = + InvTraits::child_begin(NewBB), + PE = InvTraits::child_end(NewBB); PI != PE; ++PI) + PredBlocks.push_back(*PI); + + assert(!PredBlocks.empty() && "No predblocks?"); + + bool NewBBDominatesNewBBSucc = true; + for (typename InvTraits::ChildIteratorType PI = + InvTraits::child_begin(NewBBSucc), + E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) { + typename InvTraits::NodeType *ND = *PI; + if (ND != NewBB && !DT.dominates(NewBBSucc, ND) && + DT.isReachableFromEntry(ND)) { + NewBBDominatesNewBBSucc = false; + break; + } + } + + // Find NewBB's immediate dominator and create new dominator tree node for + // NewBB. + NodeT *NewBBIDom = 0; + unsigned i = 0; + for (i = 0; i < PredBlocks.size(); ++i) + if (DT.isReachableFromEntry(PredBlocks[i])) { + NewBBIDom = PredBlocks[i]; + break; + } + + // It's possible that none of the predecessors of NewBB are reachable; + // in that case, NewBB itself is unreachable, so nothing needs to be + // changed. + if (!NewBBIDom) + return; + + for (i = i + 1; i < PredBlocks.size(); ++i) { + if (DT.isReachableFromEntry(PredBlocks[i])) + NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]); + } + + // Create the new dominator tree node... and set the idom of NewBB. + DomTreeNodeBase *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom); + + // If NewBB strictly dominates other blocks, then it is now the immediate + // dominator of NewBBSucc. Update the dominator tree as appropriate. + if (NewBBDominatesNewBBSucc) { + DomTreeNodeBase *NewBBSuccNode = DT.getNode(NewBBSucc); + DT.changeImmediateDominator(NewBBSuccNode, NewBBNode); + } + } + +public: + explicit DominatorTreeBase(bool isPostDom) + : DominatorBase(isPostDom), DFSInfoValid(false), SlowQueries(0) {} + virtual ~DominatorTreeBase() { reset(); } + + /// compare - Return false if the other dominator tree base matches this + /// dominator tree base. Otherwise return true. + bool compare(DominatorTreeBase &Other) const { + + const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; + if (DomTreeNodes.size() != OtherDomTreeNodes.size()) + return true; + + for (typename DomTreeNodeMapType::const_iterator + I = this->DomTreeNodes.begin(), + E = this->DomTreeNodes.end(); I != E; ++I) { + NodeT *BB = I->first; + typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB); + if (OI == OtherDomTreeNodes.end()) + return true; + + DomTreeNodeBase* MyNd = I->second; + DomTreeNodeBase* OtherNd = OI->second; + + if (MyNd->compare(OtherNd)) + return true; + } + + return false; + } + + virtual void releaseMemory() { reset(); } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNodeBase *getNode(NodeT *BB) const { + typename DomTreeNodeMapType::const_iterator I = DomTreeNodes.find(BB); + return I != DomTreeNodes.end() ? I->second : 0; + } + + /// getRootNode - This returns the entry node for the CFG of the function. If + /// this tree represents the post-dominance relations for a function, however, + /// this root may be a node with the block == NULL. This is the case when + /// there are multiple exit nodes from a particular function. Consumers of + /// post-dominance information must be capable of dealing with this + /// possibility. + /// + DomTreeNodeBase *getRootNode() { return RootNode; } + const DomTreeNodeBase *getRootNode() const { return RootNode; } + + /// properlyDominates - Returns true iff this dominates N and this != N. + /// Note that this is not a constant time operation! + /// + bool properlyDominates(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) const { + if (A == 0 || B == 0) return false; + return dominatedBySlowTreeWalk(A, B); + } + + inline bool properlyDominates(const NodeT *A, const NodeT *B) { + if (A == B) + return false; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return properlyDominates(getNode(const_cast(A)), + getNode(const_cast(B))); + } + + bool dominatedBySlowTreeWalk(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) const { + const DomTreeNodeBase *IDom; + if (A == 0 || B == 0) return false; + while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B) + B = IDom; // Walk up the tree + return IDom != 0; + } + + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + bool isReachableFromEntry(const NodeT* A) { + assert(!this->isPostDominator() && + "This is not implemented for post dominators"); + return dominates(&A->getParent()->front(), A); + } + + /// dominates - Returns true iff A dominates B. Note that this is not a + /// constant time operation! + /// + inline bool dominates(const DomTreeNodeBase *A, + const DomTreeNodeBase *B) { + if (B == A) + return true; // A node trivially dominates itself. + + if (A == 0 || B == 0) + return false; + + // Compare the result of the tree walk and the dfs numbers, if expensive + // checks are enabled. +#ifdef XDEBUG + assert((!DFSInfoValid || + (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) && + "Tree walk disagrees with dfs numbers!"); +#endif + + if (DFSInfoValid) + return B->DominatedBy(A); + + // If we end up with too many slow queries, just update the + // DFS numbers on the theory that we are going to keep querying. + SlowQueries++; + if (SlowQueries > 32) { + updateDFSNumbers(); + return B->DominatedBy(A); + } + + return dominatedBySlowTreeWalk(A, B); + } + + inline bool dominates(const NodeT *A, const NodeT *B) { + if (A == B) + return true; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return dominates(getNode(const_cast(A)), + getNode(const_cast(B))); + } + + NodeT *getRoot() const { + assert(this->Roots.size() == 1 && "Should always have entry node!"); + return this->Roots[0]; + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) { + assert(A->getParent() == B->getParent() && + "Two blocks are not in same function"); + + // If either A or B is a entry block then it is nearest common dominator + // (for forward-dominators). + if (!this->isPostDominator()) { + NodeT &Entry = A->getParent()->front(); + if (A == &Entry || B == &Entry) + return &Entry; + } + + // If B dominates A then B is nearest common dominator. + if (dominates(B, A)) + return B; + + // If A dominates B then A is nearest common dominator. + if (dominates(A, B)) + return A; + + DomTreeNodeBase *NodeA = getNode(A); + DomTreeNodeBase *NodeB = getNode(B); + + // Collect NodeA dominators set. + SmallPtrSet*, 16> NodeADoms; + NodeADoms.insert(NodeA); + DomTreeNodeBase *IDomA = NodeA->getIDom(); + while (IDomA) { + NodeADoms.insert(IDomA); + IDomA = IDomA->getIDom(); + } + + // Walk NodeB immediate dominators chain and find common dominator node. + DomTreeNodeBase *IDomB = NodeB->getIDom(); + while (IDomB) { + if (NodeADoms.count(IDomB) != 0) + return IDomB->getBlock(); + + IDomB = IDomB->getIDom(); + } + + return NULL; + } + + const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) { + // Cast away the const qualifiers here. This is ok since + // const is re-introduced on the return type. + return findNearestCommonDominator(const_cast(A), + const_cast(B)); + } + + //===--------------------------------------------------------------------===// + // API to update (Post)DominatorTree information based on modifications to + // the CFG... + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + DomTreeNodeBase *addNewBlock(NodeT *BB, NodeT *DomBB) { + assert(getNode(BB) == 0 && "Block already in dominator tree!"); + DomTreeNodeBase *IDomNode = getNode(DomBB); + assert(IDomNode && "Not immediate dominator specified for block!"); + DFSInfoValid = false; + return DomTreeNodes[BB] = + IDomNode->addChild(new DomTreeNodeBase(BB, IDomNode)); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + void changeImmediateDominator(DomTreeNodeBase *N, + DomTreeNodeBase *NewIDom) { + assert(N && NewIDom && "Cannot change null node pointers!"); + DFSInfoValid = false; + N->setIDom(NewIDom); + } + + void changeImmediateDominator(NodeT *BB, NodeT *NewBB) { + changeImmediateDominator(getNode(BB), getNode(NewBB)); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + void eraseNode(NodeT *BB) { + DomTreeNodeBase *Node = getNode(BB); + assert(Node && "Removing node that isn't in dominator tree."); + assert(Node->getChildren().empty() && "Node is not a leaf node."); + + // Remove node from immediate dominator's children list. + DomTreeNodeBase *IDom = Node->getIDom(); + if (IDom) { + typename std::vector*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), Node); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + } + + DomTreeNodes.erase(BB); + delete Node; + } + + /// removeNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Invalidates any node pointing to removed + /// block. + void removeNode(NodeT *BB) { + assert(getNode(BB) && "Removing node that isn't in dominator tree."); + DomTreeNodes.erase(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + void splitBlock(NodeT* NewBB) { + if (this->IsPostDominators) + this->Split, GraphTraits > >(*this, NewBB); + else + this->Split >(*this, NewBB); + } + + /// print - Convert to human readable form + /// + void print(raw_ostream &o) const { + o << "=============================--------------------------------\n"; + if (this->isPostDominator()) + o << "Inorder PostDominator Tree: "; + else + o << "Inorder Dominator Tree: "; + if (!this->DFSInfoValid) + o << "DFSNumbers invalid: " << SlowQueries << " slow queries."; + o << "\n"; + + // The postdom tree can have a null root if there are no returns. + if (getRootNode()) + PrintDomTree(getRootNode(), o, 1); + } + +protected: + template + friend typename GraphT::NodeType* Eval( + DominatorTreeBase& DT, + typename GraphT::NodeType* V, + unsigned LastLinked); + + template + friend unsigned DFSPass(DominatorTreeBase& DT, + typename GraphT::NodeType* V, + unsigned N); + + template + friend void Calculate(DominatorTreeBase::NodeType>& DT, + FuncT& F); + + /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking + /// dominator tree in dfs order. + void updateDFSNumbers() { + unsigned DFSNum = 0; + + SmallVector*, + typename DomTreeNodeBase::iterator>, 32> WorkStack; + + DomTreeNodeBase *ThisRoot = getRootNode(); + + if (!ThisRoot) + return; + + // Even in the case of multiple exits that form the post dominator root + // nodes, do not iterate over all exits, but start from the virtual root + // node. Otherwise bbs, that are not post dominated by any exit but by the + // virtual root node, will never be assigned a DFS number. + WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin())); + ThisRoot->DFSNumIn = DFSNum++; + + while (!WorkStack.empty()) { + DomTreeNodeBase *Node = WorkStack.back().first; + typename DomTreeNodeBase::iterator ChildIt = + WorkStack.back().second; + + // If we visited all of the children of this node, "recurse" back up the + // stack setting the DFOutNum. + if (ChildIt == Node->end()) { + Node->DFSNumOut = DFSNum++; + WorkStack.pop_back(); + } else { + // Otherwise, recursively visit this child. + DomTreeNodeBase *Child = *ChildIt; + ++WorkStack.back().second; + + WorkStack.push_back(std::make_pair(Child, Child->begin())); + Child->DFSNumIn = DFSNum++; + } + } + + SlowQueries = 0; + DFSInfoValid = true; + } + + DomTreeNodeBase *getNodeForBlock(NodeT *BB) { + typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.find(BB); + if (I != this->DomTreeNodes.end() && I->second) + return I->second; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[NULL]); + DomTreeNodeBase *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this BasicBlock, and link it as a child of + // IDomNode + DomTreeNodeBase *C = new DomTreeNodeBase(BB, IDomNode); + return this->DomTreeNodes[BB] = IDomNode->addChild(C); + } + + inline NodeT *getIDom(NodeT *BB) const { + typename DenseMap::const_iterator I = IDoms.find(BB); + return I != IDoms.end() ? I->second : 0; + } + + inline void addRoot(NodeT* BB) { + this->Roots.push_back(BB); + } + +public: + /// recalculate - compute a dominator tree for the given function + template + void recalculate(FT& F) { + reset(); + this->Vertex.push_back(0); + + if (!this->IsPostDominators) { + // Initialize root + this->Roots.push_back(&F.front()); + this->IDoms[&F.front()] = 0; + this->DomTreeNodes[&F.front()] = 0; + + Calculate(*this, F); + } else { + // Initialize the roots list + for (typename FT::iterator I = F.begin(), E = F.end(); I != E; ++I) { + if (std::distance(GraphTraits::child_begin(I), + GraphTraits::child_end(I)) == 0) + addRoot(I); + + // Prepopulate maps so that we don't get iterator invalidation issues later. + this->IDoms[I] = 0; + this->DomTreeNodes[I] = 0; + } + + Calculate >(*this, F); + } + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); + +//===------------------------------------- +/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to +/// compute a normal dominator tree. +/// +class DominatorTree : public FunctionPass { +public: + static char ID; // Pass ID, replacement for typeid + DominatorTreeBase* DT; + + DominatorTree() : FunctionPass(ID) { + initializeDominatorTreePass(*PassRegistry::getPassRegistry()); + DT = new DominatorTreeBase(false); + } + + ~DominatorTree() { + delete DT; + } + + DominatorTreeBase& getBase() { return *DT; } + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline BasicBlock *getRoot() const { + return DT->getRoot(); + } + + inline DomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + /// compare - Return false if the other dominator tree matches this + /// dominator tree. Otherwise return true. + inline bool compare(DominatorTree &Other) const { + DomTreeNode *R = getRootNode(); + DomTreeNode *OtherR = Other.getRootNode(); + + if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) + return true; + + if (DT->compare(Other.getBase())) + return true; + + return false; + } + + virtual bool runOnFunction(Function &F); + + virtual void verifyAnalysis() const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(const BasicBlock* A, const BasicBlock* B) const { + return DT->dominates(A, B); + } + + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(const Instruction *A, const Instruction *B) const; + + bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const { + return DT->properlyDominates(A, B); + } + + bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const { + return DT->properlyDominates(A, B); + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A, + const BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return DT->getNode(BB); + } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNode *getNode(BasicBlock *BB) const { + return DT->getNode(BB); + } + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { + return DT->addNewBlock(BB, DomBB); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + inline void eraseNode(BasicBlock *BB) { + DT->eraseNode(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + inline void splitBlock(BasicBlock* NewBB) { + DT->splitBlock(NewBB); + } + + bool isReachableFromEntry(const BasicBlock* A) { + return DT->isReachableFromEntry(A); + } + + + virtual void releaseMemory() { + DT->releaseMemory(); + } + + virtual void print(raw_ostream &OS, const Module* M= 0) const; +}; + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// +template <> struct GraphTraits { + typedef DomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } + + typedef df_iterator nodes_iterator; + + static nodes_iterator nodes_begin(DomTreeNode *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DomTreeNode *N) { + return df_end(getEntryNode(N)); + } +}; + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(DominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(DominatorTree *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/FindUsedTypes.h b/final/include/llvm/Analysis/FindUsedTypes.h new file mode 100644 index 00000000000..fc57e1a0469 --- /dev/null +++ b/final/include/llvm/Analysis/FindUsedTypes.h @@ -0,0 +1,66 @@ +//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to seek out all of the types in use by the program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H +#define LLVM_ANALYSIS_FINDUSEDTYPES_H + +#include "llvm/Pass.h" +#include + +namespace llvm { + +class Type; +class Value; + +class FindUsedTypes : public ModulePass { + std::set UsedTypes; +public: + static char ID; // Pass identification, replacement for typeid + FindUsedTypes() : ModulePass(ID) { + initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); + } + + /// getTypes - After the pass has been run, return the set containing all of + /// the types used in the module. + /// + const std::set &getTypes() const { return UsedTypes; } + + /// Print the types found in the module. If the optional Module parameter is + /// passed in, then the types are printed symbolically if possible, using the + /// symbol table from the module. + /// + void print(raw_ostream &o, const Module *M) const; + +private: + /// IncorporateType - Incorporate one type and all of its subtypes into the + /// collection of used types. + /// + void IncorporateType(const Type *Ty); + + /// IncorporateValue - Incorporate all of the types used by this value. + /// + void IncorporateValue(const Value *V); + +public: + /// run - This incorporates all types used by the specified module + bool runOnModule(Module &M); + + /// getAnalysisUsage - We do not modify anything. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/IVUsers.h b/final/include/llvm/Analysis/IVUsers.h new file mode 100644 index 00000000000..578e6aba833 --- /dev/null +++ b/final/include/llvm/Analysis/IVUsers.h @@ -0,0 +1,175 @@ +//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements bookkeeping for "interesting" users of expressions +// computed from induction variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IVUSERS_H +#define LLVM_ANALYSIS_IVUSERS_H + +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/Support/ValueHandle.h" + +namespace llvm { + +class DominatorTree; +class Instruction; +class Value; +class IVUsers; +class ScalarEvolution; +class SCEV; +class IVUsers; + +/// IVStrideUse - Keep track of one use of a strided induction variable. +/// The Expr member keeps track of the expression, User is the actual user +/// instruction of the operand, and 'OperandValToReplace' is the operand of +/// the User that is the use. +class IVStrideUse : public CallbackVH, public ilist_node { + friend class IVUsers; +public: + IVStrideUse(IVUsers *P, Instruction* U, Value *O) + : CallbackVH(U), Parent(P), OperandValToReplace(O) { + } + + /// getUser - Return the user instruction for this use. + Instruction *getUser() const { + return cast(getValPtr()); + } + + /// setUser - Assign a new user instruction for this use. + void setUser(Instruction *NewUser) { + setValPtr(NewUser); + } + + /// getOperandValToReplace - Return the Value of the operand in the user + /// instruction that this IVStrideUse is representing. + Value *getOperandValToReplace() const { + return OperandValToReplace; + } + + /// setOperandValToReplace - Assign a new Value as the operand value + /// to replace. + void setOperandValToReplace(Value *Op) { + OperandValToReplace = Op; + } + + /// getPostIncLoops - Return the set of loops for which the expression has + /// been adjusted to use post-inc mode. + const PostIncLoopSet &getPostIncLoops() const { + return PostIncLoops; + } + + /// transformToPostInc - Transform the expression to post-inc form for the + /// given loop. + void transformToPostInc(const Loop *L); + +private: + /// Parent - a pointer to the IVUsers that owns this IVStrideUse. + IVUsers *Parent; + + /// OperandValToReplace - The Value of the operand in the user instruction + /// that this IVStrideUse is representing. + WeakVH OperandValToReplace; + + /// PostIncLoops - The set of loops for which Expr has been adjusted to + /// use post-inc mode. This corresponds with SCEVExpander's post-inc concept. + PostIncLoopSet PostIncLoops; + + /// Deleted - Implementation of CallbackVH virtual function to + /// receive notification when the User is deleted. + virtual void deleted(); +}; + +template<> struct ilist_traits + : public ilist_default_traits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + // The sentinel is relative to this instance, so we use a non-static + // method. + IVStrideUse *createSentinel() const { + // since i(p)lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment i(p)list. + // But since the NodeTy is expected to publicly derive from + // ilist_node, there is a legal viable downcast from it + // to NodeTy. We use this trick to superpose i(p)list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node) so no one will ever notice + // the superposition. + return static_cast(&Sentinel); + } + static void destroySentinel(IVStrideUse*) {} + + IVStrideUse *provideInitialHead() const { return createSentinel(); } + IVStrideUse *ensureHead(IVStrideUse*) const { return createSentinel(); } + static void noteHead(IVStrideUse*, IVStrideUse*) {} + +private: + mutable ilist_node Sentinel; +}; + +class IVUsers : public LoopPass { + friend class IVStrideUse; + Loop *L; + LoopInfo *LI; + DominatorTree *DT; + ScalarEvolution *SE; + SmallPtrSet Processed; + + /// IVUses - A list of all tracked IV uses of induction variable expressions + /// we are interested in. + ilist IVUses; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + + virtual void releaseMemory(); + +public: + static char ID; // Pass ID, replacement for typeid + IVUsers(); + + /// AddUsersIfInteresting - Inspect the specified Instruction. If it is a + /// reducible SCEV, recursively add its users to the IVUsesByStride set and + /// return true. Otherwise, return false. + bool AddUsersIfInteresting(Instruction *I); + + IVStrideUse &AddUser(Instruction *User, Value *Operand); + + /// getReplacementExpr - Return a SCEV expression which computes the + /// value of the OperandValToReplace of the given IVStrideUse. + const SCEV *getReplacementExpr(const IVStrideUse &IU) const; + + /// getExpr - Return the expression for the use. + const SCEV *getExpr(const IVStrideUse &IU) const; + + const SCEV *getStride(const IVStrideUse &IU, const Loop *L) const; + + typedef ilist::iterator iterator; + typedef ilist::const_iterator const_iterator; + iterator begin() { return IVUses.begin(); } + iterator end() { return IVUses.end(); } + const_iterator begin() const { return IVUses.begin(); } + const_iterator end() const { return IVUses.end(); } + bool empty() const { return IVUses.empty(); } + + void print(raw_ostream &OS, const Module* = 0) const; + + /// dump - This method is used for debugging. + void dump() const; +}; + +Pass *createIVUsersPass(); + +} + +#endif diff --git a/final/include/llvm/Analysis/InlineCost.h b/final/include/llvm/Analysis/InlineCost.h new file mode 100644 index 00000000000..b08bf57ace9 --- /dev/null +++ b/final/include/llvm/Analysis/InlineCost.h @@ -0,0 +1,182 @@ +//===- InlineCost.h - Cost analysis for inliner -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements heuristics for inlining decisions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INLINECOST_H +#define LLVM_ANALYSIS_INLINECOST_H + +#include +#include +#include +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/Analysis/CodeMetrics.h" + +namespace llvm { + + class Value; + class Function; + class BasicBlock; + class CallSite; + template + class SmallPtrSet; + + namespace InlineConstants { + // Various magic constants used to adjust heuristics. + const int InstrCost = 5; + const int IndirectCallBonus = -100; + const int CallPenalty = 25; + const int LastCallToStaticBonus = -15000; + const int ColdccPenalty = 2000; + const int NoreturnPenalty = 10000; + } + + /// InlineCost - Represent the cost of inlining a function. This + /// supports special values for functions which should "always" or + /// "never" be inlined. Otherwise, the cost represents a unitless + /// amount; smaller values increase the likelyhood of the function + /// being inlined. + class InlineCost { + enum Kind { + Value, + Always, + Never + }; + + // This is a do-it-yourself implementation of + // int Cost : 30; + // unsigned Type : 2; + // We used to use bitfields, but they were sometimes miscompiled (PR3822). + enum { TYPE_BITS = 2 }; + enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS }; + unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS; + + Kind getType() const { + return Kind(TypedCost >> COST_BITS); + } + + int getCost() const { + // Sign-extend the bottom COST_BITS bits. + return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS; + } + + InlineCost(int C, int T) { + TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS); + assert(getCost() == C && "Cost exceeds InlineCost precision"); + } + public: + static InlineCost get(int Cost) { return InlineCost(Cost, Value); } + static InlineCost getAlways() { return InlineCost(0, Always); } + static InlineCost getNever() { return InlineCost(0, Never); } + + bool isVariable() const { return getType() == Value; } + bool isAlways() const { return getType() == Always; } + bool isNever() const { return getType() == Never; } + + /// getValue() - Return a "variable" inline cost's amount. It is + /// an error to call this on an "always" or "never" InlineCost. + int getValue() const { + assert(getType() == Value && "Invalid access of InlineCost"); + return getCost(); + } + }; + + /// InlineCostAnalyzer - Cost analyzer used by inliner. + class InlineCostAnalyzer { + struct ArgInfo { + public: + unsigned ConstantWeight; + unsigned AllocaWeight; + + ArgInfo(unsigned CWeight, unsigned AWeight) + : ConstantWeight(CWeight), AllocaWeight(AWeight) + {} + }; + + struct FunctionInfo { + CodeMetrics Metrics; + + /// ArgumentWeights - Each formal argument of the function is inspected to + /// see if it is used in any contexts where making it a constant or alloca + /// would reduce the code size. If so, we add some value to the argument + /// entry here. + std::vector ArgumentWeights; + + /// analyzeFunction - Add information about the specified function + /// to the current structure. + void analyzeFunction(Function *F); + + /// NeverInline - Returns true if the function should never be + /// inlined into any caller. + bool NeverInline(); + }; + + // The Function* for a function can be changed (by ArgumentPromotion); + // the ValueMap will update itself when this happens. + ValueMap CachedFunctionInfo; + + int CountBonusForConstant(Value *V, Constant *C = NULL); + int ConstantFunctionBonus(CallSite CS, Constant *C); + int getInlineSize(CallSite CS, Function *Callee); + int getInlineBonuses(CallSite CS, Function *Callee); + public: + + /// getInlineCost - The heuristic used to determine if we should inline the + /// function call or not. + /// + InlineCost getInlineCost(CallSite CS, + SmallPtrSet &NeverInline); + /// getCalledFunction - The heuristic used to determine if we should inline + /// the function call or not. The callee is explicitly specified, to allow + /// you to calculate the cost of inlining a function via a pointer. The + /// result assumes that the inlined version will always be used. You should + /// weight it yourself in cases where this callee will not always be called. + InlineCost getInlineCost(CallSite CS, + Function *Callee, + SmallPtrSet &NeverInline); + + /// getSpecializationBonus - The heuristic used to determine the per-call + /// performance boost for using a specialization of Callee with argument + /// SpecializedArgNos replaced by a constant. + int getSpecializationBonus(Function *Callee, + SmallVectorImpl &SpecializedArgNo); + + /// getSpecializationCost - The heuristic used to determine the code-size + /// impact of creating a specialized version of Callee with argument + /// SpecializedArgNo replaced by a constant. + InlineCost getSpecializationCost(Function *Callee, + SmallVectorImpl &SpecializedArgNo); + + /// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a + /// higher threshold to determine if the function call should be inlined. + float getInlineFudgeFactor(CallSite CS); + + /// resetCachedFunctionInfo - erase any cached cost info for this function. + void resetCachedCostInfo(Function* Caller) { + CachedFunctionInfo[Caller] = FunctionInfo(); + } + + /// growCachedCostInfo - update the cached cost info for Caller after Callee + /// has been inlined. If Callee is NULL it means a dead call has been + /// eliminated. + void growCachedCostInfo(Function* Caller, Function* Callee); + + /// clear - empty the cache of inline costs + void clear(); + }; + + /// callIsSmall - If a call is likely to lower to a single target instruction, + /// or is otherwise deemed small return true. + bool callIsSmall(const Function *Callee); +} + +#endif diff --git a/final/include/llvm/Analysis/InstructionSimplify.h b/final/include/llvm/Analysis/InstructionSimplify.h new file mode 100644 index 00000000000..dff1ba2f7be --- /dev/null +++ b/final/include/llvm/Analysis/InstructionSimplify.h @@ -0,0 +1,143 @@ +//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares routines for folding instructions into simpler forms +// that do not require creating new instructions. This does constant folding +// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either +// returning a constant ("and i32 %x, 0" -> "0") or an already existing value +// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction +// then it dominates the original instruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H + +namespace llvm { + class DominatorTree; + class Instruction; + class Value; + class TargetData; + + /// SimplifyAddInst - Given operands for an Add, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifySubInst - Given operands for a Sub, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyMulInst - Given operands for a Mul, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifySDivInst - Given operands for an SDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyUDivInst - Given operands for a UDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyFDivInst - Given operands for an FDiv, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyShlInst - Given operands for a Shl, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyLShrInst - Given operands for a LShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, const DominatorTree *DT=0); + + /// SimplifyAShrInst - Given operands for a AShr, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyAndInst - Given operands for an And, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyOrInst - Given operands for an Or, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyXorInst - Given operands for a Xor, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold + /// the result. If not, this returns null. + Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + + /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + //=== Helper functions for higher up the class hierarchy. + + + /// SimplifyCmpInst - Given operands for a CmpInst, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD = 0, const DominatorTree *DT = 0); + + /// SimplifyInstruction - See if we can compute a simplified version of this + /// instruction. If not, this returns null. + Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0, + const DominatorTree *DT = 0); + + + /// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then + /// delete the From instruction. In addition to a basic RAUW, this does a + /// recursive simplification of the updated instructions. This catches + /// things where one simplification exposes other opportunities. This only + /// simplifies and deletes scalar operations, it does not change the CFG. + /// + void ReplaceAndSimplifyAllUses(Instruction *From, Value *To, + const TargetData *TD = 0, + const DominatorTree *DT = 0); +} // end namespace llvm + +#endif + diff --git a/final/include/llvm/Analysis/Interval.h b/final/include/llvm/Analysis/Interval.h new file mode 100644 index 00000000000..ca8ad73131a --- /dev/null +++ b/final/include/llvm/Analysis/Interval.h @@ -0,0 +1,153 @@ +//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Interval class, which +// represents a set of CFG nodes and is a portion of an interval partition. +// +// Intervals have some interesting and useful properties, including the +// following: +// 1. The header node of an interval dominates all of the elements of the +// interval +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_H +#define LLVM_INTERVAL_H + +#include "llvm/ADT/GraphTraits.h" +#include + +namespace llvm { + +class BasicBlock; +class raw_ostream; + +//===----------------------------------------------------------------------===// +// +/// Interval Class - An Interval is a set of nodes defined such that every node +/// in the interval has all of its predecessors in the interval (except for the +/// header) +/// +class Interval { + /// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this + /// interval. Also, any loops in this interval must go through the HeaderNode. + /// + BasicBlock *HeaderNode; +public: + typedef std::vector::iterator succ_iterator; + typedef std::vector::iterator pred_iterator; + typedef std::vector::iterator node_iterator; + + inline Interval(BasicBlock *Header) : HeaderNode(Header) { + Nodes.push_back(Header); + } + + inline Interval(const Interval &I) // copy ctor + : HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {} + + inline BasicBlock *getHeaderNode() const { return HeaderNode; } + + /// Nodes - The basic blocks in this interval. + /// + std::vector Nodes; + + /// Successors - List of BasicBlocks that are reachable directly from nodes in + /// this interval, but are not in the interval themselves. + /// These nodes necessarily must be header nodes for other intervals. + /// + std::vector Successors; + + /// Predecessors - List of BasicBlocks that have this Interval's header block + /// as one of their successors. + /// + std::vector Predecessors; + + /// contains - Find out if a basic block is in this interval + inline bool contains(BasicBlock *BB) const { + for (unsigned i = 0; i < Nodes.size(); ++i) + if (Nodes[i] == BB) return true; + return false; + // I don't want the dependency on + //return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end(); + } + + /// isSuccessor - find out if a basic block is a successor of this Interval + inline bool isSuccessor(BasicBlock *BB) const { + for (unsigned i = 0; i < Successors.size(); ++i) + if (Successors[i] == BB) return true; + return false; + // I don't want the dependency on + //return find(Successors.begin(), Successors.end(), BB) != Successors.end(); + } + + /// Equality operator. It is only valid to compare two intervals from the + /// same partition, because of this, all we have to check is the header node + /// for equality. + /// + inline bool operator==(const Interval &I) const { + return HeaderNode == I.HeaderNode; + } + + /// isLoop - Find out if there is a back edge in this interval... + bool isLoop() const; + + /// print - Show contents in human readable format... + void print(raw_ostream &O) const; +}; + +/// succ_begin/succ_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator. +/// +inline Interval::succ_iterator succ_begin(Interval *I) { + return I->Successors.begin(); +} +inline Interval::succ_iterator succ_end(Interval *I) { + return I->Successors.end(); +} + +/// pred_begin/pred_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator. +/// +inline Interval::pred_iterator pred_begin(Interval *I) { + return I->Predecessors.begin(); +} +inline Interval::pred_iterator pred_end(Interval *I) { + return I->Predecessors.end(); +} + +template <> struct GraphTraits { + typedef Interval NodeType; + typedef Interval::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(Interval *I) { return I; } + + /// nodes_iterator/begin/end - Allow iteration over all nodes in the graph + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits > { + typedef Interval NodeType; + typedef Interval::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/IntervalIterator.h b/final/include/llvm/Analysis/IntervalIterator.h new file mode 100644 index 00000000000..82b3294cc50 --- /dev/null +++ b/final/include/llvm/Analysis/IntervalIterator.h @@ -0,0 +1,259 @@ +//===- IntervalIterator.h - Interval Iterator Declaration -------*- 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 an iterator that enumerates the intervals in a control flow +// graph of some sort. This iterator is parametric, allowing iterator over the +// following types of graphs: +// +// 1. A Function* object, composed of BasicBlock nodes. +// 2. An IntervalPartition& object, composed of Interval nodes. +// +// This iterator is defined to walk the control flow graph, returning intervals +// in depth first order. These intervals are completely filled in except for +// the predecessor fields (the successor information is filled in however). +// +// By default, the intervals created by this iterator are deleted after they +// are no longer any use to the iterator. This behavior can be changed by +// passing a false value into the intervals_begin() function. This causes the +// IOwnMem member to be set, and the intervals to not be deleted. +// +// It is only safe to use this if all of the intervals are deleted by the caller +// and all of the intervals are processed. However, the user of the iterator is +// not allowed to modify or delete the intervals until after the iterator has +// been used completely. The IntervalPartition class uses this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_ITERATOR_H +#define LLVM_INTERVAL_ITERATOR_H + +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Function.h" +#include "llvm/Support/CFG.h" +#include +#include +#include + +namespace llvm { + +// getNodeHeader - Given a source graph node and the source graph, return the +// BasicBlock that is the header node. This is the opposite of +// getSourceGraphNode. +// +inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; } +inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); } + +// getSourceGraphNode - Given a BasicBlock and the source graph, return the +// source graph node that corresponds to the BasicBlock. This is the opposite +// of getNodeHeader. +// +inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) { + return BB; +} +inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) { + return IP->getBlockInterval(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. +// +inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { + Int->Nodes.push_back(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. In the case of +// an IntervalPartition source graph (Interval case), all of the member +// BasicBlocks are added to the interval. +// +inline void addNodeToInterval(Interval *Int, Interval *I) { + // Add all of the nodes in I as new nodes in Int. + copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); +} + + + + + +template, + class IGT = GraphTraits > > +class IntervalIterator { + std::vector > IntStack; + std::set Visited; + OrigContainer_t *OrigContainer; + bool IOwnMem; // If True, delete intervals when done with them + // See file header for conditions of use +public: + typedef IntervalIterator _Self; + typedef std::forward_iterator_tag iterator_category; + + IntervalIterator() {} // End iterator, empty stack + IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = M; + if (!ProcessInterval(&M->front())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = &IP; + if (!ProcessInterval(IP.getRootInterval())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + inline ~IntervalIterator() { + if (IOwnMem) + while (!IntStack.empty()) { + delete operator*(); + IntStack.pop_back(); + } + } + + inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;} + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline const Interval *operator*() const { return IntStack.back().first; } + inline Interval *operator*() { return IntStack.back().first; } + inline const Interval *operator->() const { return operator*(); } + inline Interval *operator->() { return operator*(); } + + _Self& operator++() { // Preincrement + assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); + do { + // All of the intervals on the stack have been visited. Try visiting + // their successors now. + Interval::succ_iterator &SuccIt = IntStack.back().second, + EndIt = succ_end(IntStack.back().first); + while (SuccIt != EndIt) { // Loop over all interval succs + bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt)); + ++SuccIt; // Increment iterator + if (Done) return *this; // Found a new interval! Use it! + } + + // Free interval memory... if necessary + if (IOwnMem) delete IntStack.back().first; + + // We ran out of successors for this interval... pop off the stack + IntStack.pop_back(); + } while (!IntStack.empty()); + + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + +private: + // ProcessInterval - This method is used during the construction of the + // interval graph. It walks through the source graph, recursively creating + // an interval per invokation until the entire graph is covered. This uses + // the ProcessNode method to add all of the nodes to the interval. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + bool ProcessInterval(NodeTy *Node) { + BasicBlock *Header = getNodeHeader(Node); + if (Visited.count(Header)) return false; + + Interval *Int = new Interval(Header); + Visited.insert(Header); // The header has now been visited! + + // Check all of our successors to see if they are in the interval... + for (typename GT::ChildIteratorType I = GT::child_begin(Node), + E = GT::child_end(Node); I != E; ++I) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *I)); + + IntStack.push_back(std::make_pair(Int, succ_begin(Int))); + return true; + } + + // ProcessNode - This method is called by ProcessInterval to add nodes to the + // interval being constructed, and it is also called recursively as it walks + // the source graph. A node is added to the current interval only if all of + // its predecessors are already in the graph. This also takes care of keeping + // the successor set of an interval up to date. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + void ProcessNode(Interval *Int, NodeTy *Node) { + assert(Int && "Null interval == bad!"); + assert(Node && "Null Node == bad!"); + + BasicBlock *NodeHeader = getNodeHeader(Node); + + if (Visited.count(NodeHeader)) { // Node already been visited? + if (Int->contains(NodeHeader)) { // Already in this interval... + return; + } else { // In other interval, add as successor + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + } + } else { // Otherwise, not in interval yet + for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), + E = IGT::child_end(Node); I != E; ++I) { + if (!Int->contains(*I)) { // If pred not in interval, we can't be + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + return; // See you later + } + } + + // If we get here, then all of the predecessors of BB are in the interval + // already. In this case, we must add BB to the interval! + addNodeToInterval(Int, Node); + Visited.insert(NodeHeader); // The node has now been visited! + + if (Int->isSuccessor(NodeHeader)) { + // If we were in the successor list from before... remove from succ list + Int->Successors.erase(std::remove(Int->Successors.begin(), + Int->Successors.end(), NodeHeader), + Int->Successors.end()); + } + + // Now that we have discovered that Node is in the interval, perhaps some + // of its successors are as well? + for (typename GT::ChildIteratorType It = GT::child_begin(Node), + End = GT::child_end(Node); It != End; ++It) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); + } + } +}; + +typedef IntervalIterator function_interval_iterator; +typedef IntervalIterator + interval_part_interval_iterator; + + +inline function_interval_iterator intervals_begin(Function *F, + bool DeleteInts = true) { + return function_interval_iterator(F, DeleteInts); +} +inline function_interval_iterator intervals_end(Function *) { + return function_interval_iterator(); +} + +inline interval_part_interval_iterator + intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) { + return interval_part_interval_iterator(IP, DeleteIntervals); +} + +inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) { + return interval_part_interval_iterator(); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/IntervalPartition.h b/final/include/llvm/Analysis/IntervalPartition.h new file mode 100644 index 00000000000..df7313f18f3 --- /dev/null +++ b/final/include/llvm/Analysis/IntervalPartition.h @@ -0,0 +1,111 @@ +//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the IntervalPartition class, which +// calculates and represents the interval partition of a function, or a +// preexisting interval partition. +// +// In this way, the interval partition may be used to reduce a flow graph down +// to its degenerate single node interval partition (unless it is irreducible). +// +// TODO: The IntervalPartition class should take a bool parameter that tells +// whether it should add the "tails" of an interval to an interval itself or if +// they should be represented as distinct intervals. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_PARTITION_H +#define LLVM_INTERVAL_PARTITION_H + +#include "llvm/Analysis/Interval.h" +#include "llvm/Pass.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// +// IntervalPartition - This class builds and holds an "interval partition" for +// a function. This partition divides the control flow graph into a set of +// maximal intervals, as defined with the properties above. Intuitively, a +// BasicBlock is a (possibly nonexistent) loop with a "tail" of non looping +// nodes following it. +// +class IntervalPartition : public FunctionPass { + typedef std::map IntervalMapTy; + IntervalMapTy IntervalMap; + + typedef std::vector IntervalListTy; + Interval *RootInterval; + std::vector Intervals; + +public: + static char ID; // Pass identification, replacement for typeid + + IntervalPartition() : FunctionPass(ID), RootInterval(0) { + initializeIntervalPartitionPass(*PassRegistry::getPassRegistry()); + } + + // run - Calculate the interval partition for this function + virtual bool runOnFunction(Function &F); + + // IntervalPartition ctor - Build a reduced interval partition from an + // existing interval graph. This takes an additional boolean parameter to + // distinguish it from a copy constructor. Always pass in false for now. + // + IntervalPartition(IntervalPartition &I, bool); + + // print - Show contents in human readable format... + virtual void print(raw_ostream &O, const Module* = 0) const; + + // getRootInterval() - Return the root interval that contains the starting + // block of the function. + inline Interval *getRootInterval() { return RootInterval; } + + // isDegeneratePartition() - Returns true if the interval partition contains + // a single interval, and thus cannot be simplified anymore. + bool isDegeneratePartition() { return Intervals.size() == 1; } + + // TODO: isIrreducible - look for triangle graph. + + // getBlockInterval - Return the interval that a basic block exists in. + inline Interval *getBlockInterval(BasicBlock *BB) { + IntervalMapTy::iterator I = IntervalMap.find(BB); + return I != IntervalMap.end() ? I->second : 0; + } + + // getAnalysisUsage - Implement the Pass API + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + // Interface to Intervals vector... + const std::vector &getIntervals() const { return Intervals; } + + // releaseMemory - Reset state back to before function was analyzed + void releaseMemory(); + +private: + // addIntervalToPartition - Add an interval to the internal list of intervals, + // and then add mappings from all of the basic blocks in the interval to the + // interval itself (in the IntervalMap). + // + void addIntervalToPartition(Interval *I); + + // updatePredecessors - Interval generation only sets the successor fields of + // the interval data structures. After interval generation is complete, + // run through all of the intervals and propagate successor info as + // predecessor info. + // + void updatePredecessors(Interval *Int); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/LazyValueInfo.h b/final/include/llvm/Analysis/LazyValueInfo.h new file mode 100644 index 00000000000..fc4d0af920e --- /dev/null +++ b/final/include/llvm/Analysis/LazyValueInfo.h @@ -0,0 +1,81 @@ +//===- LazyValueInfo.h - Value constraint analysis --------------*- 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 interface for lazy computation of value constraint +// information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYVALUEINFO_H +#define LLVM_ANALYSIS_LAZYVALUEINFO_H + +#include "llvm/Pass.h" + +namespace llvm { + class Constant; + class TargetData; + class Value; + +/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint +/// information. +class LazyValueInfo : public FunctionPass { + class TargetData *TD; + void *PImpl; + LazyValueInfo(const LazyValueInfo&); // DO NOT IMPLEMENT. + void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT. +public: + static char ID; + LazyValueInfo() : FunctionPass(ID), PImpl(0) { + initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); + } + ~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); } + + /// Tristate - This is used to return true/false/dunno results. + enum Tristate { + Unknown = -1, False = 0, True = 1 + }; + + + // Public query interface. + + /// getPredicateOnEdge - Determine whether the specified value comparison + /// with a constant is known to be true or false on the specified CFG edge. + /// Pred is a CmpInst predicate. + Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, + BasicBlock *FromBB, BasicBlock *ToBB); + + + /// getConstant - Determine whether the specified value is known to be a + /// constant at the end of the specified block. Return null if not. + Constant *getConstant(Value *V, BasicBlock *BB); + + /// getConstantOnEdge - Determine whether the specified value is known to be a + /// constant on the specified edge. Return null if not. + Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB); + + /// threadEdge - Inform the analysis cache that we have threaded an edge from + /// PredBB to OldSucc to be from PredBB to NewSucc instead. + void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); + + /// eraseBlock - Inform the analysis cache that we have erased a block. + void eraseBlock(BasicBlock *BB); + + // Implementation boilerplate. + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + virtual void releaseMemory(); + virtual bool runOnFunction(Function &F); +}; + +} // end namespace llvm + +#endif + diff --git a/final/include/llvm/Analysis/LibCallAliasAnalysis.h b/final/include/llvm/Analysis/LibCallAliasAnalysis.h new file mode 100644 index 00000000000..243234b7563 --- /dev/null +++ b/final/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -0,0 +1,73 @@ +//===- LibCallAliasAnalysis.h - Implement AliasAnalysis for libcalls ------===// +// +// 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 LibCallAliasAnalysis class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIBCALL_AA_H +#define LLVM_ANALYSIS_LIBCALL_AA_H + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Pass.h" + +namespace llvm { + class LibCallInfo; + struct LibCallFunctionInfo; + + /// LibCallAliasAnalysis - Alias analysis driven from LibCallInfo. + struct LibCallAliasAnalysis : public FunctionPass, public AliasAnalysis { + static char ID; // Class identification + + LibCallInfo *LCI; + + explicit LibCallAliasAnalysis(LibCallInfo *LC = 0) + : FunctionPass(ID), LCI(LC) { + initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); + } + explicit LibCallAliasAnalysis(char &ID, LibCallInfo *LC) + : FunctionPass(ID), LCI(LC) { + initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); + } + ~LibCallAliasAnalysis(); + + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + + ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + // TODO: Could compare two direct calls against each other if we cared to. + return AliasAnalysis::getModRefInfo(CS1, CS2); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnFunction(Function &F) { + InitializeAliasAnalysis(this); // set up super class + return false; + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const void *PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + private: + ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, + ImmutableCallSite CS, + const Location &Loc); + }; +} // End of llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/LibCallSemantics.h b/final/include/llvm/Analysis/LibCallSemantics.h new file mode 100644 index 00000000000..f5a9e96cbdd --- /dev/null +++ b/final/include/llvm/Analysis/LibCallSemantics.h @@ -0,0 +1,167 @@ +//===- LibCallSemantics.h - Describe library semantics --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces that can be used to describe language specific +// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H +#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H + +#include "llvm/Analysis/AliasAnalysis.h" + +namespace llvm { + + /// LibCallLocationInfo - This struct describes a set of memory locations that + /// are accessed by libcalls. Identification of a location is doing with a + /// simple callback function. + /// + /// For example, the LibCallInfo may be set up to model the behavior of + /// standard libm functions. The location that they may be interested in is + /// an abstract location that represents errno for the current target. In + /// this case, a location for errno is anything such that the predicate + /// returns true. On Mac OS/X, this predicate would return true if the + /// pointer is the result of a call to "__error()". + /// + /// Locations can also be defined in a constant-sensitive way. For example, + /// it is possible to define a location that returns true iff it is passed + /// into the call as a specific argument. This is useful for modeling things + /// like "printf", which can store to memory, but only through pointers passed + /// with a '%n' constraint. + /// + struct LibCallLocationInfo { + // TODO: Flags: isContextSensitive etc. + + /// isLocation - Return a LocResult if the specified pointer refers to this + /// location for the specified call site. This returns "Yes" if we can tell + /// that the pointer *does definitely* refer to the location, "No" if we can + /// tell that the location *definitely does not* refer to the location, and + /// returns "Unknown" if we cannot tell for certain. + enum LocResult { + Yes, No, Unknown + }; + LocResult (*isLocation)(ImmutableCallSite CS, + const AliasAnalysis::Location &Loc); + }; + + /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs + /// records the behavior of one libcall that is known by the optimizer. This + /// captures things like the side effects of the call. Side effects are + /// modeled both universally (in the readnone/readonly) sense, but also + /// potentially against a set of abstract locations defined by the optimizer. + /// This allows an optimizer to define that some libcall (e.g. sqrt) is + /// side-effect free except that it might modify errno (thus, the call is + /// *not* universally readonly). Or it might say that the side effects + /// are unknown other than to say that errno is not modified. + /// + struct LibCallFunctionInfo { + /// Name - This is the name of the libcall this describes. + const char *Name; + + /// TODO: Constant folding function: Constant* vector -> Constant*. + + /// UniversalBehavior - This captures the absolute mod/ref behavior without + /// any specific context knowledge. For example, if the function is known + /// to be readonly, this would be set to 'ref'. If known to be readnone, + /// this is set to NoModRef. + AliasAnalysis::ModRefResult UniversalBehavior; + + /// LocationMRInfo - This pair captures info about whether a specific + /// location is modified or referenced by a libcall. + struct LocationMRInfo { + /// LocationID - ID # of the accessed location or ~0U for array end. + unsigned LocationID; + /// MRInfo - Mod/Ref info for this location. + AliasAnalysis::ModRefResult MRInfo; + }; + + /// DetailsType - Indicate the sense of the LocationDetails array. This + /// controls how the LocationDetails array is interpreted. + enum { + /// DoesOnly - If DetailsType is set to DoesOnly, then we know that the + /// *only* mod/ref behavior of this function is captured by the + /// LocationDetails array. If we are trying to say that 'sqrt' can only + /// modify errno, we'd have the {errnoloc,mod} in the LocationDetails + /// array and have DetailsType set to DoesOnly. + DoesOnly, + + /// DoesNot - If DetailsType is set to DoesNot, then the sense of the + /// LocationDetails array is completely inverted. This means that we *do + /// not* know everything about the side effects of this libcall, but we do + /// know things that the libcall cannot do. This is useful for complex + /// functions like 'ctime' which have crazy mod/ref behavior, but are + /// known to never read or write errno. In this case, we'd have + /// {errnoloc,modref} in the LocationDetails array and DetailsType would + /// be set to DoesNot, indicating that ctime does not read or write the + /// errno location. + DoesNot + } DetailsType; + + /// LocationDetails - This is a pointer to an array of LocationMRInfo + /// structs which indicates the behavior of the libcall w.r.t. specific + /// locations. For example, if this libcall is known to only modify + /// 'errno', it would have a LocationDetails array with the errno ID and + /// 'mod' in it. See the DetailsType field for how this is interpreted. + /// + /// In the "DoesOnly" case, this information is 'may' information for: there + /// is no guarantee that the specified side effect actually does happen, + /// just that it could. In the "DoesNot" case, this is 'must not' info. + /// + /// If this pointer is null, no details are known. + /// + const LocationMRInfo *LocationDetails; + }; + + + /// LibCallInfo - Abstract interface to query about library call information. + /// Instances of this class return known information about some set of + /// libcalls. + /// + class LibCallInfo { + // Implementation details of this object, private. + mutable void *Impl; + mutable const LibCallLocationInfo *Locations; + mutable unsigned NumLocations; + public: + LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {} + virtual ~LibCallInfo(); + + //===------------------------------------------------------------------===// + // Accessor Methods: Efficient access to contained data. + //===------------------------------------------------------------------===// + + /// getLocationInfo - Return information about the specified LocationID. + const LibCallLocationInfo &getLocationInfo(unsigned LocID) const; + + + /// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to + /// the specified function if we have it. If not, return null. + const LibCallFunctionInfo *getFunctionInfo(const Function *F) const; + + + //===------------------------------------------------------------------===// + // Implementation Methods: Subclasses should implement these. + //===------------------------------------------------------------------===// + + /// getLocationInfo - Return descriptors for the locations referenced by + /// this set of libcalls. + virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const { + return 0; + } + + /// getFunctionInfoArray - Return an array of descriptors that describe the + /// set of libcalls represented by this LibCallInfo object. This array is + /// terminated by an entry with a NULL name. + virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/Lint.h b/final/include/llvm/Analysis/Lint.h new file mode 100644 index 00000000000..eb65d223644 --- /dev/null +++ b/final/include/llvm/Analysis/Lint.h @@ -0,0 +1,51 @@ +//===-- llvm/Analysis/Lint.h - LLVM IR Lint ---------------------*- 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 lint interfaces that can be used for some sanity checking +// of input to the system, and for checking that transformations +// haven't done something bad. In contrast to the Verifier, the Lint checker +// checks for undefined behavior or constructions with likely unintended +// behavior. +// +// To see what specifically is checked, look at Lint.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LINT_H +#define LLVM_ANALYSIS_LINT_H + +#include + +namespace llvm { + +class FunctionPass; +class Module; +class Function; + +/// @brief Create a lint pass. +/// +/// Check a module or function. +FunctionPass *createLintPass(); + +/// @brief Check a module. +/// +/// This should only be used for debugging, because it plays games with +/// PassManagers and stuff. +void lintModule( + const Module &M ///< The module to be checked +); + +// lintFunction - Check a function. +void lintFunction( + const Function &F ///< The function to be checked +); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/Loads.h b/final/include/llvm/Analysis/Loads.h new file mode 100644 index 00000000000..1574262dd6d --- /dev/null +++ b/final/include/llvm/Analysis/Loads.h @@ -0,0 +1,51 @@ +//===- Loads.h - Local load analysis --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares simple local analyses for load instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOADS_H +#define LLVM_ANALYSIS_LOADS_H + +#include "llvm/BasicBlock.h" + +namespace llvm { + +class AliasAnalysis; +class TargetData; + +/// isSafeToLoadUnconditionally - Return true if we know that executing a load +/// from this value cannot trap. If it is not obviously safe to load from the +/// specified pointer, we do a quick local scan of the basic block containing +/// ScanFrom, to determine if the address is already accessed. +bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, + unsigned Align, const TargetData *TD = 0); + +/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at +/// the instruction before ScanFrom) checking to see if we have the value at +/// the memory address *Ptr locally available within a small number of +/// instructions. If the value is available, return it. +/// +/// If not, return the iterator for the last validated instruction that the +/// value would be live through. If we scanned the entire block and didn't +/// find something that invalidates *Ptr or provides it, ScanFrom would be +/// left at begin() and this returns null. ScanFrom could also be left +/// +/// MaxInstsToScan specifies the maximum instructions to scan in the block. +/// If it is set to 0, it will scan the whole block. You can also optionally +/// specify an alias analysis implementation, which makes this more precise. +Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, + BasicBlock::iterator &ScanFrom, + unsigned MaxInstsToScan = 6, + AliasAnalysis *AA = 0); + +} + +#endif diff --git a/final/include/llvm/Analysis/LoopDependenceAnalysis.h b/final/include/llvm/Analysis/LoopDependenceAnalysis.h new file mode 100644 index 00000000000..f195d278241 --- /dev/null +++ b/final/include/llvm/Analysis/LoopDependenceAnalysis.h @@ -0,0 +1,124 @@ +//===- llvm/Analysis/LoopDependenceAnalysis.h --------------- -*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LoopDependenceAnalysis is an LLVM pass that analyses dependences in memory +// accesses in loops. +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// TODO: adapt as interface progresses +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H +#define LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class AliasAnalysis; +class AnalysisUsage; +class ScalarEvolution; +class SCEV; +class Value; +class raw_ostream; + +class LoopDependenceAnalysis : public LoopPass { + AliasAnalysis *AA; + ScalarEvolution *SE; + + /// L - The loop we are currently analysing. + Loop *L; + + /// TODO: doc + enum DependenceResult { Independent = 0, Dependent = 1, Unknown = 2 }; + + /// TODO: doc + struct Subscript { + /// TODO: Add distance, direction, breaking conditions, ... + }; + + /// DependencePair - Represents a data dependence relation between to memory + /// reference instructions. + struct DependencePair : public FastFoldingSetNode { + Value *A; + Value *B; + DependenceResult Result; + SmallVector Subscripts; + + DependencePair(const FoldingSetNodeID &ID, Value *a, Value *b) : + FastFoldingSetNode(ID), A(a), B(b), Result(Unknown), Subscripts() {} + }; + + /// findOrInsertDependencePair - Return true if a DependencePair for the + /// given Values already exists, false if a new DependencePair had to be + /// created. The third argument is set to the pair found or created. + bool findOrInsertDependencePair(Value*, Value*, DependencePair*&); + + /// getLoops - Collect all loops of the loop nest L in which + /// a given SCEV is variant. + void getLoops(const SCEV*, DenseSet*) const; + + /// isLoopInvariant - True if a given SCEV is invariant in all loops of the + /// loop nest starting at the innermost loop L. + bool isLoopInvariant(const SCEV*) const; + + /// isAffine - An SCEV is affine with respect to the loop nest starting at + /// the innermost loop L if it is of the form A+B*X where A, B are invariant + /// in the loop nest and X is a induction variable in the loop nest. + bool isAffine(const SCEV*) const; + + /// TODO: doc + bool isZIVPair(const SCEV*, const SCEV*) const; + bool isSIVPair(const SCEV*, const SCEV*) const; + DependenceResult analyseZIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseSIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseMIV(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analyseSubscript(const SCEV*, const SCEV*, Subscript*) const; + DependenceResult analysePair(DependencePair*) const; + +public: + static char ID; // Class identification, replacement for typeinfo + LoopDependenceAnalysis() : LoopPass(ID) { + initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry()); + } + + /// isDependencePair - Check whether two values can possibly give rise to + /// a data dependence: that is the case if both are instructions accessing + /// memory and at least one of those accesses is a write. + bool isDependencePair(const Value*, const Value*) const; + + /// depends - Return a boolean indicating if there is a data dependence + /// between two instructions. + bool depends(Value*, Value*); + + bool runOnLoop(Loop*, LPPassManager&); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage&) const; + void print(raw_ostream&, const Module* = 0) const; + +private: + FoldingSet Pairs; + BumpPtrAllocator PairAllocator; +}; // class LoopDependenceAnalysis + +// createLoopDependenceAnalysisPass - This creates an instance of the +// LoopDependenceAnalysis pass. +// +LoopPass *createLoopDependenceAnalysisPass(); + +} // namespace llvm + +#endif /* LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H */ diff --git a/final/include/llvm/Analysis/LoopInfo.h b/final/include/llvm/Analysis/LoopInfo.h new file mode 100644 index 00000000000..392bdad5ab0 --- /dev/null +++ b/final/include/llvm/Analysis/LoopInfo.h @@ -0,0 +1,1100 @@ +//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- 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 LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. A natural loop +// has exactly one entry-point, which is called the header. Note that natural +// loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * the trip count +// * etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_INFO_H +#define LLVM_ANALYSIS_LOOP_INFO_H + +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { + +template +static void RemoveFromVector(std::vector &V, T *N) { + typename std::vector::iterator I = std::find(V.begin(), V.end(), N); + assert(I != V.end() && "N is not in this list!"); + V.erase(I); +} + +class DominatorTree; +class LoopInfo; +class Loop; +class PHINode; +template class LoopInfoBase; +template class LoopBase; + +//===----------------------------------------------------------------------===// +/// LoopBase class - Instances of this class are used to represent loops that +/// are detected in the flow graph +/// +template +class LoopBase { + LoopT *ParentLoop; + // SubLoops - Loops contained entirely within this one. + std::vector SubLoops; + + // Blocks - The list of blocks in this loop. First entry is the header node. + std::vector Blocks; + + // DO NOT IMPLEMENT + LoopBase(const LoopBase &); + // DO NOT IMPLEMENT + const LoopBase&operator=(const LoopBase &); +public: + /// Loop ctor - This creates an empty loop. + LoopBase() : ParentLoop(0) {} + ~LoopBase() { + for (size_t i = 0, e = SubLoops.size(); i != e; ++i) + delete SubLoops[i]; + } + + /// getLoopDepth - Return the nesting level of this loop. An outer-most + /// loop has depth 1, for consistency with loop depth values used for basic + /// blocks, where depth 0 is used for blocks not inside any loops. + unsigned getLoopDepth() const { + unsigned D = 1; + for (const LoopT *CurLoop = ParentLoop; CurLoop; + CurLoop = CurLoop->ParentLoop) + ++D; + return D; + } + BlockT *getHeader() const { return Blocks.front(); } + LoopT *getParentLoop() const { return ParentLoop; } + + /// contains - Return true if the specified loop is contained within in + /// this loop. + /// + bool contains(const LoopT *L) const { + if (L == this) return true; + if (L == 0) return false; + return contains(L->getParentLoop()); + } + + /// contains - Return true if the specified basic block is in this loop. + /// + bool contains(const BlockT *BB) const { + return std::find(block_begin(), block_end(), BB) != block_end(); + } + + /// contains - Return true if the specified instruction is in this loop. + /// + template + bool contains(const InstT *Inst) const { + return contains(Inst->getParent()); + } + + /// iterator/begin/end - Return the loops contained entirely within this loop. + /// + const std::vector &getSubLoops() const { return SubLoops; } + typedef typename std::vector::const_iterator iterator; + iterator begin() const { return SubLoops.begin(); } + iterator end() const { return SubLoops.end(); } + bool empty() const { return SubLoops.empty(); } + + /// getBlocks - Get a list of the basic blocks which make up this loop. + /// + const std::vector &getBlocks() const { return Blocks; } + typedef typename std::vector::const_iterator block_iterator; + block_iterator block_begin() const { return Blocks.begin(); } + block_iterator block_end() const { return Blocks.end(); } + + /// isLoopExiting - True if terminator in the block can branch to another + /// block that is outside of the current loop. + /// + bool isLoopExiting(const BlockT *BB) const { + typedef GraphTraits BlockTraits; + for (typename BlockTraits::ChildIteratorType SI = + BlockTraits::child_begin(const_cast(BB)), + SE = BlockTraits::child_end(const_cast(BB)); SI != SE; ++SI) { + if (!contains(*SI)) + return true; + } + return false; + } + + /// getNumBackEdges - Calculate the number of back edges to the loop header + /// + unsigned getNumBackEdges() const { + unsigned NumBackEdges = 0; + BlockT *H = getHeader(); + + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType I = + InvBlockTraits::child_begin(const_cast(H)), + E = InvBlockTraits::child_end(const_cast(H)); I != E; ++I) + if (contains(*I)) + ++NumBackEdges; + + return NumBackEdges; + } + + //===--------------------------------------------------------------------===// + // APIs for simple analysis of the loop. + // + // Note that all of these methods can fail on general loops (ie, there may not + // be a preheader, etc). For best success, the loop simplification and + // induction variable canonicalization pass should be used to normalize loops + // for easy analysis. These methods assume canonical loops. + + /// getExitingBlocks - Return all blocks inside the loop that have successors + /// outside of the loop. These are the blocks _inside of the current loop_ + /// which branch out. The returned list is always unique. + /// + void getExitingBlocks(SmallVectorImpl &ExitingBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) { + // Not in current loop? It must be an exit block. + ExitingBlocks.push_back(*BI); + break; + } + } + + /// getExitingBlock - If getExitingBlocks would return exactly one block, + /// return that block. Otherwise return null. + BlockT *getExitingBlock() const { + SmallVector ExitingBlocks; + getExitingBlocks(ExitingBlocks); + if (ExitingBlocks.size() == 1) + return ExitingBlocks[0]; + return 0; + } + + /// getExitBlocks - Return all of the successor blocks of this loop. These + /// are the blocks _outside of the current loop_ which are branched to. + /// + void getExitBlocks(SmallVectorImpl &ExitBlocks) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitBlocks.push_back(*I); + } + + /// getExitBlock - If getExitBlocks would return exactly one block, + /// return that block. Otherwise return null. + BlockT *getExitBlock() const { + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + if (ExitBlocks.size() == 1) + return ExitBlocks[0]; + return 0; + } + + /// Edge type. + typedef std::pair Edge; + + /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). + template + void getExitEdges(SmallVectorImpl &ExitEdges) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + array_pod_sort(LoopBBs.begin(), LoopBBs.end()); + + typedef GraphTraits BlockTraits; + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) + for (typename BlockTraits::ChildIteratorType I = + BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI); + I != E; ++I) + if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + // Not in current loop? It must be an exit block. + ExitEdges.push_back(EdgeT(*BI, *I)); + } + + /// getLoopPreheader - If there is a preheader for this loop, return it. A + /// loop has a preheader if there is only one edge to the header of the loop + /// from outside of the loop. If this is the case, the block branching to the + /// header of the loop is the preheader node. + /// + /// This method returns null if there is no preheader for the loop. + /// + BlockT *getLoopPreheader() const { + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = getLoopPredecessor(); + if (!Out) return 0; + + // Make sure there is only one exit out of the preheader. + typedef GraphTraits BlockTraits; + typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); + ++SI; + if (SI != BlockTraits::child_end(Out)) + return 0; // Multiple exits from the block, must not be a preheader. + + // The predecessor has exactly one successor, so it is a preheader. + return Out; + } + + /// getLoopPredecessor - If the given loop's header has exactly one unique + /// predecessor outside the loop, return it. Otherwise return null. + /// This is less strict that the loop "preheader" concept, which requires + /// the predecessor to have exactly one successor. + /// + BlockT *getLoopPredecessor() const { + // Keep track of nodes outside the loop branching to the header... + BlockT *Out = 0; + + // Loop over the predecessors of the header node... + BlockT *Header = getHeader(); + typedef GraphTraits BlockTraits; + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header), + PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) { + typename InvBlockTraits::NodeType *N = *PI; + if (!contains(N)) { // If the block is not in the loop... + if (Out && Out != N) + return 0; // Multiple predecessors outside the loop + Out = N; + } + } + + // Make sure there is only one exit out of the preheader. + assert(Out && "Header of loop has no predecessors from outside loop?"); + return Out; + } + + /// getLoopLatch - If there is a single latch block for this loop, return it. + /// A latch block is a block that contains a branch back to the header. + BlockT *getLoopLatch() const { + BlockT *Header = getHeader(); + typedef GraphTraits > InvBlockTraits; + typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(Header); + typename InvBlockTraits::ChildIteratorType PE = + InvBlockTraits::child_end(Header); + BlockT *Latch = 0; + for (; PI != PE; ++PI) { + typename InvBlockTraits::NodeType *N = *PI; + if (contains(N)) { + if (Latch) return 0; + Latch = N; + } + } + + return Latch; + } + + //===--------------------------------------------------------------------===// + // APIs for updating loop information after changing the CFG + // + + /// addBasicBlockToLoop - This method is used by other analyses to update loop + /// information. NewBB is set to be a new member of the current loop. + /// Because of this, it is added as a member of all parent loops, and is added + /// to the specified LoopInfo object as being in the current basic block. It + /// is not valid to replace the loop header with this method. + /// + void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase &LI); + + /// replaceChildLoopWith - This is used when splitting loops up. It replaces + /// the OldChild entry in our children list with NewChild, and updates the + /// parent pointer of OldChild to be null and the NewChild to be this loop. + /// This updates the loop depth of the new child. + void replaceChildLoopWith(LoopT *OldChild, + LoopT *NewChild) { + assert(OldChild->ParentLoop == this && "This loop is already broken!"); + assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + typename std::vector::iterator I = + std::find(SubLoops.begin(), SubLoops.end(), OldChild); + assert(I != SubLoops.end() && "OldChild not in loop!"); + *I = NewChild; + OldChild->ParentLoop = 0; + NewChild->ParentLoop = static_cast(this); + } + + /// addChildLoop - Add the specified loop to be a child of this loop. This + /// updates the loop depth of the new child. + /// + void addChildLoop(LoopT *NewChild) { + assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + NewChild->ParentLoop = static_cast(this); + SubLoops.push_back(NewChild); + } + + /// removeChildLoop - This removes the specified child from being a subloop of + /// this loop. The loop is not deleted, as it will presumably be inserted + /// into another loop. + LoopT *removeChildLoop(iterator I) { + assert(I != SubLoops.end() && "Cannot remove end iterator!"); + LoopT *Child = *I; + assert(Child->ParentLoop == this && "Child is not a child of this loop!"); + SubLoops.erase(SubLoops.begin()+(I-begin())); + Child->ParentLoop = 0; + return Child; + } + + /// addBlockEntry - This adds a basic block directly to the basic block list. + /// This should only be used by transformations that create new loops. Other + /// transformations should use addBasicBlockToLoop. + void addBlockEntry(BlockT *BB) { + Blocks.push_back(BB); + } + + /// moveToHeader - This method is used to move BB (which must be part of this + /// loop) to be the loop header of the loop (the block that dominates all + /// others). + void moveToHeader(BlockT *BB) { + if (Blocks[0] == BB) return; + for (unsigned i = 0; ; ++i) { + assert(i != Blocks.size() && "Loop does not contain BB!"); + if (Blocks[i] == BB) { + Blocks[i] = Blocks[0]; + Blocks[0] = BB; + return; + } + } + } + + /// removeBlockFromLoop - This removes the specified basic block from the + /// current loop, updating the Blocks as appropriate. This does not update + /// the mapping in the LoopInfo class. + void removeBlockFromLoop(BlockT *BB) { + RemoveFromVector(Blocks, BB); + } + + /// verifyLoop - Verify loop structure + void verifyLoop() const { +#ifndef NDEBUG + assert(!Blocks.empty() && "Loop header is missing"); + + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + // Check the individual blocks. + for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) { + BlockT *BB = *I; + bool HasInsideLoopSuccs = false; + bool HasInsideLoopPreds = false; + SmallVector OutsideLoopPreds; + + typedef GraphTraits BlockTraits; + for (typename BlockTraits::ChildIteratorType SI = + BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB); + SI != SE; ++SI) + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) { + HasInsideLoopSuccs = true; + break; + } + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType PI = + InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); + PI != PE; ++PI) { + typename InvBlockTraits::NodeType *N = *PI; + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) + HasInsideLoopPreds = true; + else + OutsideLoopPreds.push_back(N); + } + + if (BB == getHeader()) { + assert(!OutsideLoopPreds.empty() && "Loop is unreachable!"); + } else if (!OutsideLoopPreds.empty()) { + // A non-header loop shouldn't be reachable from outside the loop, + // though it is permitted if the predecessor is not itself actually + // reachable. + BlockT *EntryBB = BB->getParent()->begin(); + for (df_iterator NI = df_begin(EntryBB), + NE = df_end(EntryBB); NI != NE; ++NI) + for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) + assert(*NI != OutsideLoopPreds[i] && + "Loop has multiple entry points!"); + } + assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!"); + assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); + assert(BB != getHeader()->getParent()->begin() && + "Loop contains function entry block!"); + } + + // Check the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + // Each block in each subloop should be contained within this loop. + for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end(); + BI != BE; ++BI) { + assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) && + "Loop does not contain all the blocks of a subloop!"); + } + + // Check the parent loop pointer. + if (ParentLoop) { + assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) != + ParentLoop->end() && + "Loop is not a subloop of its parent!"); + } +#endif + } + + /// verifyLoop - Verify loop structure of this loop and all nested loops. + void verifyLoopNest() const { + // Verify this loop. + verifyLoop(); + // Verify the subloops. + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->verifyLoopNest(); + } + + void print(raw_ostream &OS, unsigned Depth = 0) const { + OS.indent(Depth*2) << "Loop at depth " << getLoopDepth() + << " containing: "; + + for (unsigned i = 0; i < getBlocks().size(); ++i) { + if (i) OS << ","; + BlockT *BB = getBlocks()[i]; + WriteAsOperand(OS, BB, false); + if (BB == getHeader()) OS << "
"; + if (BB == getLoopLatch()) OS << ""; + if (isLoopExiting(BB)) OS << ""; + } + OS << "\n"; + + for (iterator I = begin(), E = end(); I != E; ++I) + (*I)->print(OS, Depth+2); + } + +protected: + friend class LoopInfoBase; + explicit LoopBase(BlockT *BB) : ParentLoop(0) { + Blocks.push_back(BB); + } +}; + +template +raw_ostream& operator<<(raw_ostream &OS, const LoopBase &Loop) { + Loop.print(OS); + return OS; +} + +class Loop : public LoopBase { +public: + Loop() {} + + /// isLoopInvariant - Return true if the specified value is loop invariant + /// + bool isLoopInvariant(Value *V) const; + + /// hasLoopInvariantOperands - Return true if all the operands of the + /// specified instruction are loop invariant. + bool hasLoopInvariantOperands(Instruction *I) const; + + /// makeLoopInvariant - If the given value is an instruction inside of the + /// loop and it can be hoisted, do so to make it trivially loop-invariant. + /// Return true if the value after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + /// + bool makeLoopInvariant(Value *V, bool &Changed, + Instruction *InsertPt = 0) const; + + /// makeLoopInvariant - If the given instruction is inside of the + /// loop and it can be hoisted, do so to make it trivially loop-invariant. + /// Return true if the instruction after any hoisting is loop invariant. This + /// function can be used as a slightly more aggressive replacement for + /// isLoopInvariant. + /// + /// If InsertPt is specified, it is the point to hoist instructions to. + /// If null, the terminator of the loop preheader is used. + /// + bool makeLoopInvariant(Instruction *I, bool &Changed, + Instruction *InsertPt = 0) const; + + /// getCanonicalInductionVariable - Check to see if the loop has a canonical + /// induction variable: an integer recurrence that starts at 0 and increments + /// by one each time through the loop. If so, return the phi node that + /// corresponds to it. + /// + /// The IndVarSimplify pass transforms loops to have a canonical induction + /// variable. + /// + PHINode *getCanonicalInductionVariable() const; + + /// getTripCount - Return a loop-invariant LLVM value indicating the number of + /// times the loop will be executed. Note that this means that the backedge + /// of the loop executes N-1 times. If the trip-count cannot be determined, + /// this returns null. + /// + /// The IndVarSimplify pass transforms loops to have a form that this + /// function easily understands. + /// + Value *getTripCount() const; + + /// getSmallConstantTripCount - Returns the trip count of this loop as a + /// normal unsigned value, if possible. Returns 0 if the trip count is unknown + /// of not constant. Will also return 0 if the trip count is very large + /// (>= 2^32) + /// + /// The IndVarSimplify pass transforms loops to have a form that this + /// function easily understands. + /// + unsigned getSmallConstantTripCount() const; + + /// getSmallConstantTripMultiple - Returns the largest constant divisor of the + /// trip count of this loop as a normal unsigned value, if possible. This + /// means that the actual trip count is always a multiple of the returned + /// value (don't forget the trip count could very well be zero as well!). + /// + /// Returns 1 if the trip count is unknown or not guaranteed to be the + /// multiple of a constant (which is also the case if the trip count is simply + /// constant, use getSmallConstantTripCount for that case), Will also return 1 + /// if the trip count is very large (>= 2^32). + unsigned getSmallConstantTripMultiple() const; + + /// isLCSSAForm - Return true if the Loop is in LCSSA form + bool isLCSSAForm(DominatorTree &DT) const; + + /// isLoopSimplifyForm - Return true if the Loop is in the form that + /// the LoopSimplify form transforms loops to, which is sometimes called + /// normal form. + bool isLoopSimplifyForm() const; + + /// hasDedicatedExits - Return true if no exit block for the loop + /// has a predecessor that is outside the loop. + bool hasDedicatedExits() const; + + /// getUniqueExitBlocks - Return all unique successor blocks of this loop. + /// These are the blocks _outside of the current loop_ which are branched to. + /// This assumes that loop exits are in canonical form. + /// + void getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const; + + /// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one + /// block, return that block. Otherwise return null. + BasicBlock *getUniqueExitBlock() const; + + void dump() const; + +private: + friend class LoopInfoBase; + explicit Loop(BasicBlock *BB) : LoopBase(BB) {} +}; + +//===----------------------------------------------------------------------===// +/// LoopInfo - This class builds and contains all of the top level loop +/// structures in the specified function. +/// + +template +class LoopInfoBase { + // BBMap - Mapping of basic blocks to the inner most loop they occur in + DenseMap BBMap; + std::vector TopLevelLoops; + friend class LoopBase; + + void operator=(const LoopInfoBase &); // do not implement + LoopInfoBase(const LoopInfo &); // do not implement +public: + LoopInfoBase() { } + ~LoopInfoBase() { releaseMemory(); } + + void releaseMemory() { + for (typename std::vector::iterator I = + TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) + delete *I; // Delete all of the loops... + + BBMap.clear(); // Reset internal state of analysis + TopLevelLoops.clear(); + } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef typename std::vector::const_iterator iterator; + iterator begin() const { return TopLevelLoops.begin(); } + iterator end() const { return TopLevelLoops.end(); } + bool empty() const { return TopLevelLoops.empty(); } + + /// getLoopFor - Return the inner most loop that BB lives in. If a basic + /// block is in no loop (for example the entry node), null is returned. + /// + LoopT *getLoopFor(const BlockT *BB) const { + typename DenseMap::const_iterator I= + BBMap.find(const_cast(BB)); + return I != BBMap.end() ? I->second : 0; + } + + /// operator[] - same as getLoopFor... + /// + const LoopT *operator[](const BlockT *BB) const { + return getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block. A + /// depth of 0 means the block is not inside any loop. + /// + unsigned getLoopDepth(const BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L ? L->getLoopDepth() : 0; + } + + // isLoopHeader - True if the block is a loop header node + bool isLoopHeader(BlockT *BB) const { + const LoopT *L = getLoopFor(BB); + return L && L->getHeader() == BB; + } + + /// removeLoop - This removes the specified top-level loop from this loop info + /// object. The loop is not deleted, as it will presumably be inserted into + /// another loop. + LoopT *removeLoop(iterator I) { + assert(I != end() && "Cannot remove end iterator!"); + LoopT *L = *I; + assert(L->getParentLoop() == 0 && "Not a top-level loop!"); + TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin())); + return L; + } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + void changeLoopFor(BlockT *BB, LoopT *L) { + LoopT *&OldLoop = BBMap[BB]; + assert(OldLoop && "Block not in a loop yet!"); + OldLoop = L; + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + void changeTopLevelLoop(LoopT *OldLoop, + LoopT *NewLoop) { + typename std::vector::iterator I = + std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + assert(I != TopLevelLoops.end() && "Old loop not at top level!"); + *I = NewLoop; + assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 && + "Loops already embedded into a subloop!"); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + void addTopLevelLoop(LoopT *New) { + assert(New->getParentLoop() == 0 && "Loop already in subloop!"); + TopLevelLoops.push_back(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BlockT *BB) { + typename DenseMap::iterator I = BBMap.find(BB); + if (I != BBMap.end()) { + for (LoopT *L = I->second; L; L = L->getParentLoop()) + L->removeBlockFromLoop(BB); + + BBMap.erase(I); + } + } + + // Internals + + static bool isNotAlreadyContainedIn(const LoopT *SubLoop, + const LoopT *ParentLoop) { + if (SubLoop == 0) return true; + if (SubLoop == ParentLoop) return false; + return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); + } + + void Calculate(DominatorTreeBase &DT) { + BlockT *RootNode = DT.getRootNode()->getBlock(); + + for (df_iterator NI = df_begin(RootNode), + NE = df_end(RootNode); NI != NE; ++NI) + if (LoopT *L = ConsiderForLoop(*NI, DT)) + TopLevelLoops.push_back(L); + } + + LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase &DT) { + if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node? + + std::vector TodoStack; + + // Scan the predecessors of BB, checking to see if BB dominates any of + // them. This identifies backedges which target this node... + typedef GraphTraits > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType I = + InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB); + I != E; ++I) { + typename InvBlockTraits::NodeType *N = *I; + if (DT.dominates(BB, N)) // If BB dominates its predecessor... + TodoStack.push_back(N); + } + + if (TodoStack.empty()) return 0; // No backedges to this block... + + // Create a new loop to represent this basic block... + LoopT *L = new LoopT(BB); + BBMap[BB] = L; + + BlockT *EntryBlock = BB->getParent()->begin(); + + while (!TodoStack.empty()) { // Process all the nodes in the loop + BlockT *X = TodoStack.back(); + TodoStack.pop_back(); + + if (!L->contains(X) && // As of yet unprocessed?? + DT.dominates(EntryBlock, X)) { // X is reachable from entry block? + // Check to see if this block already belongs to a loop. If this occurs + // then we have a case where a loop that is supposed to be a child of + // the current loop was processed before the current loop. When this + // occurs, this child loop gets added to a part of the current loop, + // making it a sibling to the current loop. We have to reparent this + // loop. + if (LoopT *SubLoop = + const_cast(getLoopFor(X))) + if (SubLoop->getHeader() == X && isNotAlreadyContainedIn(SubLoop, L)){ + // Remove the subloop from its current parent... + assert(SubLoop->ParentLoop && SubLoop->ParentLoop != L); + LoopT *SLP = SubLoop->ParentLoop; // SubLoopParent + typename std::vector::iterator I = + std::find(SLP->SubLoops.begin(), SLP->SubLoops.end(), SubLoop); + assert(I != SLP->SubLoops.end() &&"SubLoop not a child of parent?"); + SLP->SubLoops.erase(I); // Remove from parent... + + // Add the subloop to THIS loop... + SubLoop->ParentLoop = L; + L->SubLoops.push_back(SubLoop); + } + + // Normal case, add the block to our loop... + L->Blocks.push_back(X); + + typedef GraphTraits > InvBlockTraits; + + // Add all of the predecessors of X to the end of the work stack... + TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X), + InvBlockTraits::child_end(X)); + } + } + + // If there are any loops nested within this loop, create them now! + for (typename std::vector::iterator I = L->Blocks.begin(), + E = L->Blocks.end(); I != E; ++I) + if (LoopT *NewLoop = ConsiderForLoop(*I, DT)) { + L->SubLoops.push_back(NewLoop); + NewLoop->ParentLoop = L; + } + + // Add the basic blocks that comprise this loop to the BBMap so that this + // loop can be found for them. + // + for (typename std::vector::iterator I = L->Blocks.begin(), + E = L->Blocks.end(); I != E; ++I) + BBMap.insert(std::make_pair(*I, L)); + + // Now that we have a list of all of the child loops of this loop, check to + // see if any of them should actually be nested inside of each other. We + // can accidentally pull loops our of their parents, so we must make sure to + // organize the loop nests correctly now. + { + std::map ContainingLoops; + for (unsigned i = 0; i != L->SubLoops.size(); ++i) { + LoopT *Child = L->SubLoops[i]; + assert(Child->getParentLoop() == L && "Not proper child loop?"); + + if (LoopT *ContainingLoop = ContainingLoops[Child->getHeader()]) { + // If there is already a loop which contains this loop, move this loop + // into the containing loop. + MoveSiblingLoopInto(Child, ContainingLoop); + --i; // The loop got removed from the SubLoops list. + } else { + // This is currently considered to be a top-level loop. Check to see + // if any of the contained blocks are loop headers for subloops we + // have already processed. + for (unsigned b = 0, e = Child->Blocks.size(); b != e; ++b) { + LoopT *&BlockLoop = ContainingLoops[Child->Blocks[b]]; + if (BlockLoop == 0) { // Child block not processed yet... + BlockLoop = Child; + } else if (BlockLoop != Child) { + LoopT *SubLoop = BlockLoop; + // Reparent all of the blocks which used to belong to BlockLoops + for (unsigned j = 0, f = SubLoop->Blocks.size(); j != f; ++j) + ContainingLoops[SubLoop->Blocks[j]] = Child; + + // There is already a loop which contains this block, that means + // that we should reparent the loop which the block is currently + // considered to belong to to be a child of this loop. + MoveSiblingLoopInto(SubLoop, Child); + --i; // We just shrunk the SubLoops list. + } + } + } + } + } + + return L; + } + + /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside + /// of the NewParent Loop, instead of being a sibling of it. + void MoveSiblingLoopInto(LoopT *NewChild, + LoopT *NewParent) { + LoopT *OldParent = NewChild->getParentLoop(); + assert(OldParent && OldParent == NewParent->getParentLoop() && + NewChild != NewParent && "Not sibling loops!"); + + // Remove NewChild from being a child of OldParent + typename std::vector::iterator I = + std::find(OldParent->SubLoops.begin(), OldParent->SubLoops.end(), + NewChild); + assert(I != OldParent->SubLoops.end() && "Parent fields incorrect??"); + OldParent->SubLoops.erase(I); // Remove from parent's subloops list + NewChild->ParentLoop = 0; + + InsertLoopInto(NewChild, NewParent); + } + + /// InsertLoopInto - This inserts loop L into the specified parent loop. If + /// the parent loop contains a loop which should contain L, the loop gets + /// inserted into L instead. + void InsertLoopInto(LoopT *L, LoopT *Parent) { + BlockT *LHeader = L->getHeader(); + assert(Parent->contains(LHeader) && + "This loop should not be inserted here!"); + + // Check to see if it belongs in a child loop... + for (unsigned i = 0, e = static_cast(Parent->SubLoops.size()); + i != e; ++i) + if (Parent->SubLoops[i]->contains(LHeader)) { + InsertLoopInto(L, Parent->SubLoops[i]); + return; + } + + // If not, insert it here! + Parent->SubLoops.push_back(L); + L->ParentLoop = Parent; + } + + // Debugging + + void print(raw_ostream &OS) const { + for (unsigned i = 0; i < TopLevelLoops.size(); ++i) + TopLevelLoops[i]->print(OS); + #if 0 + for (DenseMap::const_iterator I = BBMap.begin(), + E = BBMap.end(); I != E; ++I) + OS << "BB '" << I->first->getName() << "' level = " + << I->second->getLoopDepth() << "\n"; + #endif + } +}; + +class LoopInfo : public FunctionPass { + LoopInfoBase LI; + friend class LoopBase; + + void operator=(const LoopInfo &); // do not implement + LoopInfo(const LoopInfo &); // do not implement +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfo() : FunctionPass(ID) { + initializeLoopInfoPass(*PassRegistry::getPassRegistry()); + } + + LoopInfoBase& getBase() { return LI; } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef LoopInfoBase::iterator iterator; + inline iterator begin() const { return LI.begin(); } + inline iterator end() const { return LI.end(); } + bool empty() const { return LI.empty(); } + + /// getLoopFor - Return the inner most loop that BB lives in. If a basic + /// block is in no loop (for example the entry node), null is returned. + /// + inline Loop *getLoopFor(const BasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// operator[] - same as getLoopFor... + /// + inline const Loop *operator[](const BasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block. A + /// depth of 0 means the block is not inside any loop. + /// + inline unsigned getLoopDepth(const BasicBlock *BB) const { + return LI.getLoopDepth(BB); + } + + // isLoopHeader - True if the block is a loop header node + inline bool isLoopHeader(BasicBlock *BB) const { + return LI.isLoopHeader(BB); + } + + /// runOnFunction - Calculate the natural loop information. + /// + virtual bool runOnFunction(Function &F); + + virtual void verifyAnalysis() const; + + virtual void releaseMemory() { LI.releaseMemory(); } + + virtual void print(raw_ostream &O, const Module* M = 0) const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// removeLoop - This removes the specified top-level loop from this loop info + /// object. The loop is not deleted, as it will presumably be inserted into + /// another loop. + inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + inline void changeLoopFor(BasicBlock *BB, Loop *L) { + LI.changeLoopFor(BB, L); + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { + LI.changeTopLevelLoop(OldLoop, NewLoop); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + inline void addTopLevelLoop(Loop *New) { + LI.addTopLevelLoop(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BasicBlock *BB) { + LI.removeBlock(BB); + } + + /// replacementPreservesLCSSAForm - Returns true if replacing From with To + /// everywhere is guaranteed to preserve LCSSA form. + bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { + // Preserving LCSSA form is only problematic if the replacing value is an + // instruction. + Instruction *I = dyn_cast(To); + if (!I) return true; + // If both instructions are defined in the same basic block then replacement + // cannot break LCSSA form. + if (I->getParent() == From->getParent()) + return true; + // If the instruction is not defined in a loop then it can safely replace + // anything. + Loop *ToLoop = getLoopFor(I->getParent()); + if (!ToLoop) return true; + // If the replacing instruction is defined in the same loop as the original + // instruction, or in a loop that contains it as an inner loop, then using + // it as a replacement will not break LCSSA form. + return ToLoop->contains(getLoopFor(From->getParent())); + } +}; + + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits { + typedef const Loop NodeType; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(const Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template <> struct GraphTraits { + typedef Loop NodeType; + typedef LoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template +void +LoopBase::addBasicBlockToLoop(BlockT *NewBB, + LoopInfoBase &LIB) { + assert((Blocks.empty() || LIB[getHeader()] == this) && + "Incorrect LI specified for this loop!"); + assert(NewBB && "Cannot add a null basic block to the loop!"); + assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!"); + + LoopT *L = static_cast(this); + + // Add the loop mapping to the LoopInfo object... + LIB.BBMap[NewBB] = L; + + // Add the basic block to this loop and all parent loops... + while (L) { + L->Blocks.push_back(NewBB); + L = L->getParentLoop(); + } +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/LoopPass.h b/final/include/llvm/Analysis/LoopPass.h new file mode 100644 index 00000000000..1603d2ea7a4 --- /dev/null +++ b/final/include/llvm/Analysis/LoopPass.h @@ -0,0 +1,158 @@ +//===- LoopPass.h - LoopPass class ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LoopPass class. All loop optimization +// and transformation passes are derived from LoopPass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LOOP_PASS_H +#define LLVM_LOOP_PASS_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" +#include + +namespace llvm { + +class LPPassManager; +class Function; +class PMStack; + +class LoopPass : public Pass { +public: + explicit LoopPass(char &pid) : Pass(PT_Loop, pid) {} + + /// getPrinterPass - Get a pass to print the function corresponding + /// to a Loop. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + // runOnLoop - This method should be implemented by the subclass to perform + // whatever action is necessary for the specified Loop. + virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0; + + // Initialization and finalization hooks. + virtual bool doInitialization(Loop *L, LPPassManager &LPM) { + return false; + } + + // Finalization hook does not supply Loop because at this time + // loop nest is completely different. + virtual bool doFinalization() { return false; } + + // Check if this pass is suitable for the current LPPassManager, if + // available. This pass P is not suitable for a LPPassManager if P + // is not preserving higher level analysis info used by other + // LPPassManager passes. In such case, pop LPPassManager from the + // stack. This will force assignPassManager() to create new + // LPPassManger as expected. + void preparePassManager(PMStack &PMS); + + /// Assign pass manager to manage this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_LoopPassManager; + } + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// Each loop pass can override these simple analysis hooks to update + /// desired analysis information. + /// cloneBasicBlockAnalysis - Clone analysis info associated with basic block. + virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {} + + /// deleteAnalysisValue - Delete analysis info associated with value V. + virtual void deleteAnalysisValue(Value *V, Loop *L) {} +}; + +class LPPassManager : public FunctionPass, public PMDataManager { +public: + static char ID; + explicit LPPassManager(int Depth); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + // LPPassManager needs LoopInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Loop Pass Manager"; + } + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + /// Print passes managed by this manager + void dumpPassStructure(unsigned Offset); + + LoopPass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + LoopPass *LP = static_cast(PassVector[N]); + return LP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_LoopPassManager; + } + +public: + // Delete loop from the loop queue and loop nest (LoopInfo). + void deleteLoopFromQueue(Loop *L); + + // Insert loop into the loop queue and add it as a child of the + // given parent. + void insertLoop(Loop *L, Loop *ParentLoop); + + // Insert a loop into the loop queue. + void insertLoopIntoQueue(Loop *L); + + // Reoptimize this loop. LPPassManager will re-insert this loop into the + // queue. This allows LoopPass to change loop nest for the loop. This + // utility may send LPPassManager into infinite loops so use caution. + void redoLoop(Loop *L); + + //===--------------------------------------------------------------------===// + /// SimpleAnalysis - Provides simple interface to update analysis info + /// maintained by various passes. Note, if required this interface can + /// be extracted into a separate abstract class but it would require + /// additional use of multiple inheritance in Pass class hierarchy, something + /// we are trying to avoid. + + /// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for + /// all passes that implement simple analysis interface. + void cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L); + + /// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes + /// that implement simple analysis interface. + void deleteSimpleAnalysisValue(Value *V, Loop *L); + +private: + std::deque LQ; + bool skipThisLoop; + bool redoThisLoop; + LoopInfo *LI; + Loop *CurrentLoop; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/MemoryBuiltins.h b/final/include/llvm/Analysis/MemoryBuiltins.h new file mode 100644 index 00000000000..22493f6f8b9 --- /dev/null +++ b/final/include/llvm/Analysis/MemoryBuiltins.h @@ -0,0 +1,84 @@ +//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions identifies calls to builtin functions that allocate +// or free memory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H +#define LLVM_ANALYSIS_MEMORYBUILTINS_H + +namespace llvm { +class CallInst; +class PointerType; +class TargetData; +class Type; +class Value; + +//===----------------------------------------------------------------------===// +// malloc Call Utility Functions. +// + +/// isMalloc - Returns true if the value is either a malloc call or a bitcast of +/// the result of a malloc call +bool isMalloc(const Value *I); + +/// extractMallocCall - Returns the corresponding CallInst if the instruction +/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we +/// ignore InvokeInst here. +const CallInst *extractMallocCall(const Value *I); +CallInst *extractMallocCall(Value *I); + +/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the +/// instruction is a bitcast of the result of a malloc call. +const CallInst *extractMallocCallFromBitCast(const Value *I); +CallInst *extractMallocCallFromBitCast(Value *I); + +/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// is a call to malloc whose array size can be determined and the array size +/// is not constant 1. Otherwise, return NULL. +const CallInst *isArrayMalloc(const Value *I, const TargetData *TD); + +/// getMallocType - Returns the PointerType resulting from the malloc call. +/// The PointerType depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const PointerType *getMallocType(const CallInst *CI); + +/// getMallocAllocatedType - Returns the Type allocated by malloc call. +/// The Type depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const Type *getMallocAllocatedType(const CallInst *CI); + +/// getMallocArraySize - Returns the array size of a malloc call. If the +/// argument passed to malloc is a multiple of the size of the malloced type, +/// then return that multiple. For non-array mallocs, the multiple is +/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be +/// determined. +Value *getMallocArraySize(CallInst *CI, const TargetData *TD, + bool LookThroughSExt = false); + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isFreeCall - Returns non-null if the value is a call to the builtin free() +const CallInst *isFreeCall(const Value *I); + +static inline CallInst *isFreeCall(Value *I) { + return const_cast(isFreeCall((const Value*)I)); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/MemoryDependenceAnalysis.h b/final/include/llvm/Analysis/MemoryDependenceAnalysis.h new file mode 100644 index 00000000000..4d5dd1987f2 --- /dev/null +++ b/final/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -0,0 +1,378 @@ +//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- 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 MemoryDependenceAnalysis analysis pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H +#define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H + +#include "llvm/BasicBlock.h" +#include "llvm/Pass.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class Function; + class FunctionPass; + class Instruction; + class CallSite; + class AliasAnalysis; + class TargetData; + class MemoryDependenceAnalysis; + class PredIteratorCache; + class DominatorTree; + class PHITransAddr; + + /// MemDepResult - A memory dependence query can return one of three different + /// answers, described below. + class MemDepResult { + enum DepType { + /// Invalid - Clients of MemDep never see this. + Invalid = 0, + + /// Clobber - This is a dependence on the specified instruction which + /// clobbers the desired value. The pointer member of the MemDepResult + /// pair holds the instruction that clobbers the memory. For example, + /// this occurs when we see a may-aliased store to the memory location we + /// care about. + /// + /// A dependence query on the first instruction of the entry block will + /// return a clobber(self) result. + Clobber, + + /// Def - This is a dependence on the specified instruction which + /// defines/produces the desired memory location. The pointer member of + /// the MemDepResult pair holds the instruction that defines the memory. + /// Cases of interest: + /// 1. This could be a load or store for dependence queries on + /// load/store. The value loaded or stored is the produced value. + /// Note that the pointer operand may be different than that of the + /// queried pointer due to must aliases and phi translation. Note + /// that the def may not be the same type as the query, the pointers + /// may just be must aliases. + /// 2. For loads and stores, this could be an allocation instruction. In + /// this case, the load is loading an undef value or a store is the + /// first store to (that part of) the allocation. + /// 3. Dependence queries on calls return Def only when they are + /// readonly calls or memory use intrinsics with identical callees + /// and no intervening clobbers. No validation is done that the + /// operands to the calls are the same. + Def, + + /// NonLocal - This marker indicates that the query has no dependency in + /// the specified block. To find out more, the client should query other + /// predecessor blocks. + NonLocal + }; + typedef PointerIntPair PairTy; + PairTy Value; + explicit MemDepResult(PairTy V) : Value(V) {} + public: + MemDepResult() : Value(0, Invalid) {} + + /// get methods: These are static ctor methods for creating various + /// MemDepResult kinds. + static MemDepResult getDef(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Def)); + } + static MemDepResult getClobber(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Clobber)); + } + static MemDepResult getNonLocal() { + return MemDepResult(PairTy(0, NonLocal)); + } + + /// isClobber - Return true if this MemDepResult represents a query that is + /// a instruction clobber dependency. + bool isClobber() const { return Value.getInt() == Clobber; } + + /// isDef - Return true if this MemDepResult represents a query that is + /// a instruction definition dependency. + bool isDef() const { return Value.getInt() == Def; } + + /// isNonLocal - Return true if this MemDepResult represents a query that + /// is transparent to the start of the block, but where a non-local hasn't + /// been done. + bool isNonLocal() const { return Value.getInt() == NonLocal; } + + /// getInst() - If this is a normal dependency, return the instruction that + /// is depended on. Otherwise, return null. + Instruction *getInst() const { return Value.getPointer(); } + + bool operator==(const MemDepResult &M) const { return Value == M.Value; } + bool operator!=(const MemDepResult &M) const { return Value != M.Value; } + bool operator<(const MemDepResult &M) const { return Value < M.Value; } + bool operator>(const MemDepResult &M) const { return Value > M.Value; } + private: + friend class MemoryDependenceAnalysis; + /// Dirty - Entries with this marker occur in a LocalDeps map or + /// NonLocalDeps map when the instruction they previously referenced was + /// removed from MemDep. In either case, the entry may include an + /// instruction pointer. If so, the pointer is an instruction in the + /// block where scanning can start from, saving some work. + /// + /// In a default-constructed MemDepResult object, the type will be Dirty + /// and the instruction pointer will be null. + /// + + /// isDirty - Return true if this is a MemDepResult in its dirty/invalid. + /// state. + bool isDirty() const { return Value.getInt() == Invalid; } + + static MemDepResult getDirty(Instruction *Inst) { + return MemDepResult(PairTy(Inst, Invalid)); + } + }; + + /// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For + /// each BasicBlock (the BB entry) it keeps a MemDepResult. + class NonLocalDepEntry { + BasicBlock *BB; + MemDepResult Result; + public: + NonLocalDepEntry(BasicBlock *bb, MemDepResult result) + : BB(bb), Result(result) {} + + // This is used for searches. + NonLocalDepEntry(BasicBlock *bb) : BB(bb) {} + + // BB is the sort key, it can't be changed. + BasicBlock *getBB() const { return BB; } + + void setResult(const MemDepResult &R) { Result = R; } + + const MemDepResult &getResult() const { return Result; } + + bool operator<(const NonLocalDepEntry &RHS) const { + return BB < RHS.BB; + } + }; + + /// NonLocalDepResult - This is a result from a NonLocal dependence query. + /// For each BasicBlock (the BB entry) it keeps a MemDepResult and the + /// (potentially phi translated) address that was live in the block. + class NonLocalDepResult { + NonLocalDepEntry Entry; + Value *Address; + public: + NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address) + : Entry(bb, result), Address(address) {} + + // BB is the sort key, it can't be changed. + BasicBlock *getBB() const { return Entry.getBB(); } + + void setResult(const MemDepResult &R, Value *Addr) { + Entry.setResult(R); + Address = Addr; + } + + const MemDepResult &getResult() const { return Entry.getResult(); } + + /// getAddress - Return the address of this pointer in this block. This can + /// be different than the address queried for the non-local result because + /// of phi translation. This returns null if the address was not available + /// in a block (i.e. because phi translation failed) or if this is a cached + /// result and that address was deleted. + /// + /// The address is always null for a non-local 'call' dependence. + Value *getAddress() const { return Address; } + }; + + /// MemoryDependenceAnalysis - This is an analysis that determines, for a + /// given memory operation, what preceding memory operations it depends on. + /// It builds on alias analysis information, and tries to provide a lazy, + /// caching interface to a common kind of alias information query. + /// + /// The dependency information returned is somewhat unusual, but is pragmatic. + /// If queried about a store or call that might modify memory, the analysis + /// will return the instruction[s] that may either load from that memory or + /// store to it. If queried with a load or call that can never modify memory, + /// the analysis will return calls and stores that might modify the pointer, + /// but generally does not return loads unless a) they are volatile, or + /// b) they load from *must-aliased* pointers. Returning a dependence on + /// must-alias'd pointers instead of all pointers interacts well with the + /// internal caching mechanism. + /// + class MemoryDependenceAnalysis : public FunctionPass { + // A map from instructions to their dependency. + typedef DenseMap LocalDepMapType; + LocalDepMapType LocalDeps; + + public: + typedef std::vector NonLocalDepInfo; + private: + /// ValueIsLoadPair - This is a pair where the bool is true if + /// the dependence is a read only dependence, false if read/write. + typedef PointerIntPair ValueIsLoadPair; + + /// BBSkipFirstBlockPair - This pair is used when caching information for a + /// block. If the pointer is null, the cache value is not a full query that + /// starts at the specified block. If non-null, the bool indicates whether + /// or not the contents of the block was skipped. + typedef PointerIntPair BBSkipFirstBlockPair; + + /// NonLocalPointerInfo - This record is the information kept for each + /// (value, is load) pair. + struct NonLocalPointerInfo { + /// Pair - The pair of the block and the skip-first-block flag. + BBSkipFirstBlockPair Pair; + /// NonLocalDeps - The results of the query for each relevant block. + NonLocalDepInfo NonLocalDeps; + /// Size - The maximum size of the dereferences of the + /// pointer. May be UnknownSize if the sizes are unknown. + uint64_t Size; + /// TBAATag - The TBAA tag associated with dereferences of the + /// pointer. May be null if there are no tags or conflicting tags. + const MDNode *TBAATag; + + NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {} + }; + + /// CachedNonLocalPointerInfo - This map stores the cached results of doing + /// a pointer lookup at the bottom of a block. The key of this map is the + /// pointer+isload bit, the value is a list of result> mappings. + typedef DenseMap CachedNonLocalPointerInfo; + CachedNonLocalPointerInfo NonLocalPointerDeps; + + // A map from instructions to their non-local pointer dependencies. + typedef DenseMap > ReverseNonLocalPtrDepTy; + ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps; + + + /// PerInstNLInfo - This is the instruction we keep for each cached access + /// that we have for an instruction. The pointer is an owning pointer and + /// the bool indicates whether we have any dirty bits in the set. + typedef std::pair PerInstNLInfo; + + // A map from instructions to their non-local dependencies. + typedef DenseMap NonLocalDepMapType; + + NonLocalDepMapType NonLocalDeps; + + // A reverse mapping from dependencies to the dependees. This is + // used when removing instructions to keep the cache coherent. + typedef DenseMap > ReverseDepMapType; + ReverseDepMapType ReverseLocalDeps; + + // A reverse mapping from dependencies to the non-local dependees. + ReverseDepMapType ReverseNonLocalDeps; + + /// Current AA implementation, just a cache. + AliasAnalysis *AA; + TargetData *TD; + OwningPtr PredCache; + public: + MemoryDependenceAnalysis(); + ~MemoryDependenceAnalysis(); + static char ID; + + /// Pass Implementation stuff. This doesn't do any analysis eagerly. + bool runOnFunction(Function &); + + /// Clean up memory in between runs + void releaseMemory(); + + /// getAnalysisUsage - Does not modify anything. It uses Value Numbering + /// and Alias Analysis. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// getDependency - Return the instruction on which a memory operation + /// depends. See the class comment for more details. It is illegal to call + /// this on non-memory instructions. + MemDepResult getDependency(Instruction *QueryInst); + + /// getNonLocalCallDependency - Perform a full dependency query for the + /// specified call, returning the set of blocks that the value is + /// potentially live across. The returned set of results will include a + /// "NonLocal" result for all blocks where the value is live across. + /// + /// This method assumes the instruction returns a "NonLocal" dependency + /// within its own block. + /// + /// This returns a reference to an internal data structure that may be + /// invalidated on the next non-local query or when an instruction is + /// removed. Clients must copy this data if they want it around longer than + /// that. + const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS); + + + /// getNonLocalPointerDependency - Perform a full dependency query for an + /// access to the specified (non-volatile) memory location, returning the + /// set of instructions that either define or clobber the value. + /// + /// This method assumes the pointer has a "NonLocal" dependency within BB. + void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *BB, + SmallVectorImpl &Result); + + /// removeInstruction - Remove an instruction from the dependence analysis, + /// updating the dependence of instructions that previously depended on it. + void removeInstruction(Instruction *InstToRemove); + + /// invalidateCachedPointerInfo - This method is used to invalidate cached + /// information about the specified pointer, because it may be too + /// conservative in memdep. This is an optional call that can be used when + /// the client detects an equivalence between the pointer and some other + /// value and replaces the other value with ptr. This can make Ptr available + /// in more places that cached info does not necessarily keep. + void invalidateCachedPointerInfo(Value *Ptr); + + /// invalidateCachedPredecessors - Clear the PredIteratorCache info. + /// This needs to be done when the CFG changes, e.g., due to splitting + /// critical edges. + void invalidateCachedPredecessors(); + + /// getPointerDependencyFrom - Return the instruction on which a memory + /// location depends. If isLoad is true, this routine ignores may-aliases + /// with read-only operations. If isLoad is false, this routine ignores + /// may-aliases with reads from read-only locations. + /// + /// Note that this is an uncached query, and thus may be inefficient. + /// + MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, + bool isLoad, + BasicBlock::iterator ScanIt, + BasicBlock *BB); + + private: + MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, + BasicBlock::iterator ScanIt, + BasicBlock *BB); + bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *BB, + SmallVectorImpl &Result, + DenseMap &Visited, + bool SkipFirstBlock = false); + MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *BB, + NonLocalDepInfo *Cache, + unsigned NumSortedEntries); + + void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); + + /// verifyRemoved - Verify that the specified instruction does not occur + /// in our internal data structures. + void verifyRemoved(Instruction *Inst) const; + + }; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/PHITransAddr.h b/final/include/llvm/Analysis/PHITransAddr.h new file mode 100644 index 00000000000..033efba3e74 --- /dev/null +++ b/final/include/llvm/Analysis/PHITransAddr.h @@ -0,0 +1,117 @@ +//===- PHITransAddr.h - PHI Translation for Addresses -----------*- 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 PHITransAddr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PHITRANSADDR_H +#define LLVM_ANALYSIS_PHITRANSADDR_H + +#include "llvm/Instruction.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + class DominatorTree; + class TargetData; + +/// PHITransAddr - An address value which tracks and handles phi translation. +/// As we walk "up" the CFG through predecessors, we need to ensure that the +/// address we're tracking is kept up to date. For example, if we're analyzing +/// an address of "&A[i]" and walk through the definition of 'i' which is a PHI +/// node, we *must* phi translate i to get "&A[j]" or else we will analyze an +/// incorrect pointer in the predecessor block. +/// +/// This is designed to be a relatively small object that lives on the stack and +/// is copyable. +/// +class PHITransAddr { + /// Addr - The actual address we're analyzing. + Value *Addr; + + /// TD - The target data we are playing with if known, otherwise null. + const TargetData *TD; + + /// InstInputs - The inputs for our symbolic address. + SmallVector InstInputs; +public: + PHITransAddr(Value *addr, const TargetData *td) : Addr(addr), TD(td) { + // If the address is an instruction, the whole thing is considered an input. + if (Instruction *I = dyn_cast(Addr)) + InstInputs.push_back(I); + } + + Value *getAddr() const { return Addr; } + + /// NeedsPHITranslationFromBlock - Return true if moving from the specified + /// BasicBlock to its predecessors requires PHI translation. + bool NeedsPHITranslationFromBlock(BasicBlock *BB) const { + // We do need translation if one of our input instructions is defined in + // this block. + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + if (InstInputs[i]->getParent() == BB) + return true; + return false; + } + + /// IsPotentiallyPHITranslatable - If this needs PHI translation, return true + /// if we have some hope of doing it. This should be used as a filter to + /// avoid calling PHITranslateValue in hopeless situations. + bool IsPotentiallyPHITranslatable() const; + + /// PHITranslateValue - PHI translate the current address up the CFG from + /// CurBB to Pred, updating our state to reflect any needed changes. If the + /// dominator tree DT is non-null, the translated value must dominate + /// PredBB. This returns true on failure and sets Addr to null. + bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT); + + /// PHITranslateWithInsertion - PHI translate this value into the specified + /// predecessor block, inserting a computation of the value if it is + /// unavailable. + /// + /// All newly created instructions are added to the NewInsts list. This + /// returns null on failure. + /// + Value *PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree &DT, + SmallVectorImpl &NewInsts); + + void dump() const; + + /// Verify - Check internal consistency of this data structure. If the + /// structure is valid, it returns true. If invalid, it prints errors and + /// returns false. + bool Verify() const; +private: + Value *PHITranslateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT); + + /// InsertPHITranslatedSubExpr - Insert a computation of the PHI translated + /// version of 'V' for the edge PredBB->CurBB into the end of the PredBB + /// block. All newly created instructions are added to the NewInsts list. + /// This returns null on failure. + /// + Value *InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, + BasicBlock *PredBB, const DominatorTree &DT, + SmallVectorImpl &NewInsts); + + /// AddAsInput - If the specified value is an instruction, add it as an input. + Value *AddAsInput(Value *V) { + // If V is an instruction, it is now an input. + if (Instruction *VI = dyn_cast(V)) + InstInputs.push_back(VI); + return V; + } + +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/Passes.h b/final/include/llvm/Analysis/Passes.h new file mode 100644 index 00000000000..0eff75fe2f8 --- /dev/null +++ b/final/include/llvm/Analysis/Passes.h @@ -0,0 +1,198 @@ +//===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the analysis libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PASSES_H +#define LLVM_ANALYSIS_PASSES_H + +namespace llvm { + class FunctionPass; + class ImmutablePass; + class LoopPass; + class ModulePass; + class Pass; + class PassInfo; + class LibCallInfo; + + //===--------------------------------------------------------------------===// + // + // createGlobalsModRefPass - This pass provides alias and mod/ref info for + // global values that do not have their addresses taken. + // + Pass *createGlobalsModRefPass(); + + //===--------------------------------------------------------------------===// + // + // createAliasDebugger - This pass helps debug clients of AA + // + Pass *createAliasDebugger(); + + //===--------------------------------------------------------------------===// + // + // createAliasAnalysisCounterPass - This pass counts alias queries and how the + // alias analysis implementation responds. + // + ModulePass *createAliasAnalysisCounterPass(); + + //===--------------------------------------------------------------------===// + // + // createAAEvalPass - This pass implements a simple N^2 alias analysis + // accuracy evaluator. + // + FunctionPass *createAAEvalPass(); + + //===--------------------------------------------------------------------===// + // + // createNoAAPass - This pass implements a "I don't know" alias analysis. + // + ImmutablePass *createNoAAPass(); + + //===--------------------------------------------------------------------===// + // + // createBasicAliasAnalysisPass - This pass implements the stateless alias + // analysis. + // + ImmutablePass *createBasicAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows + /// about the semantics of a set of libcalls specified by LCI. The newly + /// constructed pass takes ownership of the pointer that is provided. + /// + FunctionPass *createLibCallAliasAnalysisPass(LibCallInfo *LCI); + + //===--------------------------------------------------------------------===// + // + // createScalarEvolutionAliasAnalysisPass - This pass implements a simple + // alias analysis using ScalarEvolution queries. + // + FunctionPass *createScalarEvolutionAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // createTypeBasedAliasAnalysisPass - This pass implements metadata-based + // type-based alias analysis. + // + ImmutablePass *createTypeBasedAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // createProfileLoaderPass - This pass loads information from a profile dump + // file. + // + ModulePass *createProfileLoaderPass(); + extern char &ProfileLoaderPassID; + + //===--------------------------------------------------------------------===// + // + // createNoProfileInfoPass - This pass implements the default "no profile". + // + ImmutablePass *createNoProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createProfileEstimatorPass - This pass estimates profiling information + // instead of loading it from a previous run. + // + FunctionPass *createProfileEstimatorPass(); + extern char &ProfileEstimatorPassID; + + //===--------------------------------------------------------------------===// + // + // createProfileVerifierPass - This pass verifies profiling information. + // + FunctionPass *createProfileVerifierPass(); + + //===--------------------------------------------------------------------===// + // + // createPathProfileLoaderPass - This pass loads information from a path + // profile dump file. + // + ModulePass *createPathProfileLoaderPass(); + extern char &PathProfileLoaderPassID; + + //===--------------------------------------------------------------------===// + // + // createNoPathProfileInfoPass - This pass implements the default + // "no path profile". + // + ImmutablePass *createNoPathProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createPathProfileVerifierPass - This pass verifies path profiling + // information. + // + ModulePass *createPathProfileVerifierPass(); + + //===--------------------------------------------------------------------===// + // + // createDSAAPass - This pass implements simple context sensitive alias + // analysis. + // + ModulePass *createDSAAPass(); + + //===--------------------------------------------------------------------===// + // + // createDSOptPass - This pass uses DSA to do a series of simple + // optimizations. + // + ModulePass *createDSOptPass(); + + //===--------------------------------------------------------------------===// + // + // createSteensgaardPass - This pass uses the data structure graphs to do a + // simple context insensitive alias analysis. + // + ModulePass *createSteensgaardPass(); + + //===--------------------------------------------------------------------===// + // + /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo + /// pass. + FunctionPass *createLazyValueInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createLoopDependenceAnalysisPass - This creates an instance of the + // LoopDependenceAnalysis pass. + // + LoopPass *createLoopDependenceAnalysisPass(); + + // Minor pass prototypes, allowing us to expose them through bugpoint and + // analyze. + FunctionPass *createInstCountPass(); + + // print debug info intrinsics in human readable form + FunctionPass *createDbgInfoPrinterPass(); + + //===--------------------------------------------------------------------===// + // + // createRegionInfoPass - This pass finds all single entry single exit regions + // in a function and builds the region hierarchy. + // + FunctionPass *createRegionInfoPass(); + + // Print module-level debug info metadata in human-readable form. + ModulePass *createModuleDebugInfoPrinterPass(); + + //===--------------------------------------------------------------------===// + // + // createMemDepPrinter - This pass exhaustively collects all memdep + // information and prints it with -analyze. + // + FunctionPass *createMemDepPrinter(); +} + +#endif diff --git a/final/include/llvm/Analysis/PathNumbering.h b/final/include/llvm/Analysis/PathNumbering.h new file mode 100644 index 00000000000..7025e28484c --- /dev/null +++ b/final/include/llvm/Analysis/PathNumbering.h @@ -0,0 +1,304 @@ +//===- PathNumbering.h ----------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Ball-Larus path numbers uniquely identify paths through a directed acyclic +// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony +// edges to obtain a DAG, and thus the unique path numbers [Ball96]. +// +// The purpose of this analysis is to enumerate the edges in a CFG in order +// to obtain paths from path numbers in a convenient manner. As described in +// [Ball96] edges can be enumerated such that given a path number by following +// the CFG and updating the path number, the path is obtained. +// +// [Ball96] +// T. Ball and J. R. Larus. "Efficient Path Profiling." +// International Symposium on Microarchitecture, pages 46-57, 1996. +// http://portal.acm.org/citation.cfm?id=243857 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATH_NUMBERING_H +#define LLVM_PATH_NUMBERING_H + +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include +#include +#include + +namespace llvm { +class BallLarusNode; +class BallLarusEdge; +class BallLarusDag; + +// typedefs for storage/ interators of various DAG components +typedef std::vector BLNodeVector; +typedef std::vector::iterator BLNodeIterator; +typedef std::vector BLEdgeVector; +typedef std::vector::iterator BLEdgeIterator; +typedef std::map BLBlockNodeMap; +typedef std::stack BLNodeStack; + +// Represents a basic block with information necessary for the BallLarus +// algorithms. +class BallLarusNode { +public: + enum NodeColor { WHITE, GRAY, BLACK }; + + // Constructor: Initializes a new Node for the given BasicBlock + BallLarusNode(BasicBlock* BB) : + _basicBlock(BB), _numberPaths(0), _color(WHITE) { + static unsigned nextUID = 0; + _uid = nextUID++; + } + + // Returns the basic block for the BallLarusNode + BasicBlock* getBlock(); + + // Get/set the number of paths to the exit starting at the node. + unsigned getNumberPaths(); + void setNumberPaths(unsigned numberPaths); + + // Get/set the NodeColor used in graph algorithms. + NodeColor getColor(); + void setColor(NodeColor color); + + // Iterator information for predecessor edges. Includes phony and + // backedges. + BLEdgeIterator predBegin(); + BLEdgeIterator predEnd(); + unsigned getNumberPredEdges(); + + // Iterator information for successor edges. Includes phony and + // backedges. + BLEdgeIterator succBegin(); + BLEdgeIterator succEnd(); + unsigned getNumberSuccEdges(); + + // Add an edge to the predecessor list. + void addPredEdge(BallLarusEdge* edge); + + // Remove an edge from the predecessor list. + void removePredEdge(BallLarusEdge* edge); + + // Add an edge to the successor list. + void addSuccEdge(BallLarusEdge* edge); + + // Remove an edge from the successor list. + void removeSuccEdge(BallLarusEdge* edge); + + // Returns the name of the BasicBlock being represented. If BasicBlock + // is null then returns "". If BasicBlock has no name, then + // "" is returned. Intended for use with debug output. + std::string getName(); + +private: + // The corresponding underlying BB. + BasicBlock* _basicBlock; + + // Holds the predecessor edges of this node. + BLEdgeVector _predEdges; + + // Holds the successor edges of this node. + BLEdgeVector _succEdges; + + // The number of paths from the node to the exit. + unsigned _numberPaths; + + // 'Color' used by graph algorithms to mark the node. + NodeColor _color; + + // Unique ID to ensure naming difference with dotgraphs + unsigned _uid; + + // Removes an edge from an edgeVector. Used by removePredEdge and + // removeSuccEdge. + void removeEdge(BLEdgeVector& v, BallLarusEdge* e); +}; + +// Represents an edge in the Dag. For an edge, v -> w, v is the source, and +// w is the target. +class BallLarusEdge { +public: + enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE, + BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY }; + + // Constructor: Initializes an BallLarusEdge with a source and target. + BallLarusEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber) + : _source(source), _target(target), _weight(0), _edgeType(NORMAL), + _realEdge(NULL), _duplicateNumber(duplicateNumber) {} + + // Returns the source/ target node of this edge. + BallLarusNode* getSource() const; + BallLarusNode* getTarget() const; + + // Sets the type of the edge. + EdgeType getType() const; + + // Gets the type of the edge. + void setType(EdgeType type); + + // Returns the weight of this edge. Used to decode path numbers to + // sequences of basic blocks. + unsigned getWeight(); + + // Sets the weight of the edge. Used during path numbering. + void setWeight(unsigned weight); + + // Gets/sets the phony edge originating at the root. + BallLarusEdge* getPhonyRoot(); + void setPhonyRoot(BallLarusEdge* phonyRoot); + + // Gets/sets the phony edge terminating at the exit. + BallLarusEdge* getPhonyExit(); + void setPhonyExit(BallLarusEdge* phonyExit); + + // Gets/sets the associated real edge if this is a phony edge. + BallLarusEdge* getRealEdge(); + void setRealEdge(BallLarusEdge* realEdge); + + // Returns the duplicate number of the edge. + unsigned getDuplicateNumber(); + +protected: + // Source node for this edge. + BallLarusNode* _source; + + // Target node for this edge. + BallLarusNode* _target; + +private: + // Edge weight cooresponding to path number increments before removing + // increments along a spanning tree. The sum over the edge weights gives + // the path number. + unsigned _weight; + + // Type to represent for what this edge is intended + EdgeType _edgeType; + + // For backedges and split-edges, the phony edge which is linked to the + // root node of the DAG. This contains a path number initialization. + BallLarusEdge* _phonyRoot; + + // For backedges and split-edges, the phony edge which is linked to the + // exit node of the DAG. This contains a path counter increment, and + // potentially a path number increment. + BallLarusEdge* _phonyExit; + + // If this is a phony edge, _realEdge is a link to the back or split + // edge. Otherwise, this is null. + BallLarusEdge* _realEdge; + + // An ID to differentiate between those edges which have the same source + // and destination blocks. + unsigned _duplicateNumber; +}; + +// Represents the Ball Larus DAG for a given Function. Can calculate +// various properties required for instrumentation or analysis. E.g. the +// edge weights that determine the path number. +class BallLarusDag { +public: + // Initializes a BallLarusDag from the CFG of a given function. Must + // call init() after creation, since some initialization requires + // virtual functions. + BallLarusDag(Function &F) + : _root(NULL), _exit(NULL), _function(F) {} + + // Initialization that requires virtual functions which are not fully + // functional in the constructor. + void init(); + + // Frees all memory associated with the DAG. + virtual ~BallLarusDag(); + + // Calculate the path numbers by assigning edge increments as prescribed + // in Ball-Larus path profiling. + void calculatePathNumbers(); + + // Returns the number of paths for the DAG. + unsigned getNumberOfPaths(); + + // Returns the root (i.e. entry) node for the DAG. + BallLarusNode* getRoot(); + + // Returns the exit node for the DAG. + BallLarusNode* getExit(); + + // Returns the function for the DAG. + Function& getFunction(); + + // Clears the node colors. + void clearColors(BallLarusNode::NodeColor color); + +protected: + // All nodes in the DAG. + BLNodeVector _nodes; + + // All edges in the DAG. + BLEdgeVector _edges; + + // All backedges in the DAG. + BLEdgeVector _backEdges; + + // Allows subclasses to determine which type of Node is created. + // Override this method to produce subclasses of BallLarusNode if + // necessary. The destructor of BallLarusDag will call free on each pointer + // created. + virtual BallLarusNode* createNode(BasicBlock* BB); + + // Allows subclasses to determine which type of Edge is created. + // Override this method to produce subclasses of BallLarusEdge if + // necessary. Parameters source and target will have been created by + // createNode and can be cast to the subclass of BallLarusNode* + // returned by createNode. The destructor of BallLarusDag will call free + // on each pointer created. + virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode* + target, unsigned duplicateNumber); + + // Proxy to node's constructor. Updates the DAG state. + BallLarusNode* addNode(BasicBlock* BB); + + // Proxy to edge's constructor. Updates the DAG state. + BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateNumber); + +private: + // The root (i.e. entry) node for this DAG. + BallLarusNode* _root; + + // The exit node for this DAG. + BallLarusNode* _exit; + + // The function represented by this DAG. + Function& _function; + + // Processes one node and its imediate edges for building the DAG. + void buildNode(BLBlockNodeMap& inDag, std::stack& dfsStack); + + // Process an edge in the CFG for DAG building. + void buildEdge(BLBlockNodeMap& inDag, std::stack& dfsStack, + BallLarusNode* currentNode, BasicBlock* succBB, + unsigned duplicateNumber); + + // The weight on each edge is the increment required along any path that + // contains that edge. + void calculatePathNumbersFrom(BallLarusNode* node); + + // Adds a backedge with its phony edges. Updates the DAG state. + void addBackedge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateCount); +}; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/PathProfileInfo.h b/final/include/llvm/Analysis/PathProfileInfo.h new file mode 100644 index 00000000000..263763f7a8d --- /dev/null +++ b/final/include/llvm/Analysis/PathProfileInfo.h @@ -0,0 +1,113 @@ +//===- PathProfileInfo.h --------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file outlines the interface used by optimizers to load path profiles. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PATHPROFILEINFO_H +#define LLVM_PATHPROFILEINFO_H + +#include "llvm/BasicBlock.h" +#include "llvm/Analysis/PathNumbering.h" +#include + +namespace llvm { + +class ProfilePath; +class ProfilePathEdge; +class PathProfileInfo; + +typedef std::vector ProfilePathEdgeVector; +typedef std::vector::iterator ProfilePathEdgeIterator; + +typedef std::vector ProfilePathBlockVector; +typedef std::vector::iterator ProfilePathBlockIterator; + +typedef std::map ProfilePathMap; +typedef std::map::iterator ProfilePathIterator; + +typedef std::map FunctionPathCountMap; +typedef std::map FunctionPathMap; +typedef std::map::iterator FunctionPathIterator; + +class ProfilePathEdge { +public: + ProfilePathEdge(BasicBlock* source, BasicBlock* target, + unsigned duplicateNumber); + + inline unsigned getDuplicateNumber() { return _duplicateNumber; } + inline BasicBlock* getSource() { return _source; } + inline BasicBlock* getTarget() { return _target; } + +protected: + BasicBlock* _source; + BasicBlock* _target; + unsigned _duplicateNumber; +}; + +class ProfilePath { +public: + ProfilePath(unsigned int number, unsigned int count, + double countStdDev, PathProfileInfo* ppi); + + double getFrequency() const; + + inline unsigned int getNumber() const { return _number; } + inline unsigned int getCount() const { return _count; } + inline double getCountStdDev() const { return _countStdDev; } + + ProfilePathEdgeVector* getPathEdges() const; + ProfilePathBlockVector* getPathBlocks() const; + + BasicBlock* getFirstBlockInPath() const; + +private: + unsigned int _number; + unsigned int _count; + double _countStdDev; + + // double pointer back to the profiling info + PathProfileInfo* _ppi; +}; + +// TODO: overload [] operator for getting path +// Add: getFunctionCallCount() +class PathProfileInfo { + public: + PathProfileInfo(); + ~PathProfileInfo(); + + void setCurrentFunction(Function* F); + Function* getCurrentFunction() const; + BasicBlock* getCurrentFunctionEntry(); + + ProfilePath* getPath(unsigned int number); + unsigned int getPotentialPathCount(); + + ProfilePathIterator pathBegin(); + ProfilePathIterator pathEnd(); + unsigned int pathsRun(); + + static char ID; // Pass identification + std::string argList; + +protected: + FunctionPathMap _functionPaths; + FunctionPathCountMap _functionPathCounts; + +private: + BallLarusDag* _currentDag; + Function* _currentFunction; + + friend class ProfilePath; +}; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/PostDominators.h b/final/include/llvm/Analysis/PostDominators.h new file mode 100644 index 00000000000..2cd6ae346ee --- /dev/null +++ b/final/include/llvm/Analysis/PostDominators.h @@ -0,0 +1,137 @@ +//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes interfaces to post dominance information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_POST_DOMINATORS_H +#define LLVM_ANALYSIS_POST_DOMINATORS_H + +#include "llvm/Analysis/DominanceFrontier.h" + +namespace llvm { + +/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to +/// compute the a post-dominator tree. +/// +struct PostDominatorTree : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + DominatorTreeBase* DT; + + PostDominatorTree() : FunctionPass(ID) { + initializePostDominatorTreePass(*PassRegistry::getPassRegistry()); + DT = new DominatorTreeBase(true); + } + + ~PostDominatorTree(); + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline DomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return DT->getNode(BB); + } + + inline DomTreeNode *getNode(BasicBlock *BB) const { + return DT->getNode(BB); + } + + inline bool dominates(DomTreeNode* A, DomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(const BasicBlock* A, const BasicBlock* B) const { + return DT->dominates(A, B); + } + + inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const { + return DT->properlyDominates(A, B); + } + + inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const { + return DT->properlyDominates(A, B); + } + + inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + virtual void releaseMemory() { + DT->releaseMemory(); + } + + virtual void print(raw_ostream &OS, const Module*) const; +}; + +FunctionPass* createPostDomTree(); + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(PostDominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(PostDominatorTree *N) { + if (getEntryNode(N)) + return df_begin(getEntryNode(N)); + else + return df_end(getEntryNode(N)); + } + + static nodes_iterator nodes_end(PostDominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + +/// PostDominanceFrontier Class - Concrete subclass of DominanceFrontier that is +/// used to compute the a post-dominance frontier. +/// +struct PostDominanceFrontier : public DominanceFrontierBase { + static char ID; + PostDominanceFrontier() + : DominanceFrontierBase(ID, true) { + initializePostDominanceFrontierPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + PostDominatorTree &DT = getAnalysis(); + Roots = DT.getRoots(); + if (const DomTreeNode *Root = DT.getRootNode()) + calculate(DT, Root); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + +private: + const DomSetType &calculate(const PostDominatorTree &DT, + const DomTreeNode *Node); +}; + +FunctionPass* createPostDomFrontier(); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/ProfileInfo.h b/final/include/llvm/Analysis/ProfileInfo.h new file mode 100644 index 00000000000..300a0279042 --- /dev/null +++ b/final/include/llvm/Analysis/ProfileInfo.h @@ -0,0 +1,248 @@ +//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic ProfileInfo interface, which is used as the +// common interface used by all clients of profiling information, and +// implemented either by making static guestimations, or by actually reading in +// profiling information gathered by running the program. +// +// Note that to be useful, all profile-based optimizations should preserve +// ProfileInfo, which requires that they notify it when changes to the CFG are +// made. (This is not implemented yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFO_H +#define LLVM_ANALYSIS_PROFILEINFO_H + +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include + +namespace llvm { + class Pass; + class raw_ostream; + + class BasicBlock; + class Function; + class MachineBasicBlock; + class MachineFunction; + + // Helper for dumping edges to dbgs(). + raw_ostream& operator<<(raw_ostream &O, std::pair E); + raw_ostream& operator<<(raw_ostream &O, std::pair E); + + raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB); + raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB); + + raw_ostream& operator<<(raw_ostream &O, const Function *F); + raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF); + + /// ProfileInfo Class - This class holds and maintains profiling + /// information for some unit of code. + template + class ProfileInfoT { + public: + // Types for handling profiling information. + typedef std::pair Edge; + typedef std::pair EdgeWeight; + typedef std::map EdgeWeights; + typedef std::map BlockCounts; + typedef std::map Path; + + protected: + // EdgeInformation - Count the number of times a transition between two + // blocks is executed. As a special case, we also hold an edge from the + // null BasicBlock to the entry block to indicate how many times the + // function was entered. + std::map EdgeInformation; + + // BlockInformation - Count the number of times a block is executed. + std::map BlockInformation; + + // FunctionInformation - Count the number of times a function is executed. + std::map FunctionInformation; + + ProfileInfoT *MachineProfile; + public: + static char ID; // Class identification, replacement for typeinfo + ProfileInfoT(); + ~ProfileInfoT(); // We want to be subclassed + + // MissingValue - The value that is returned for execution counts in case + // no value is available. + static const double MissingValue; + + // getFunction() - Returns the Function for an Edge, checking for validity. + static const FType* getFunction(Edge e) { + if (e.first) { + return e.first->getParent(); + } else if (e.second) { + return e.second->getParent(); + } + assert(0 && "Invalid ProfileInfo::Edge"); + return (const FType*)0; + } + + // getEdge() - Creates an Edge from two BasicBlocks. + static Edge getEdge(const BType *Src, const BType *Dest) { + return std::make_pair(Src, Dest); + } + + //===------------------------------------------------------------------===// + /// Profile Information Queries + /// + double getExecutionCount(const FType *F); + + double getExecutionCount(const BType *BB); + + void setExecutionCount(const BType *BB, double w); + + void addExecutionCount(const BType *BB, double w); + + double getEdgeWeight(Edge e) const { + typename std::map::const_iterator J = + EdgeInformation.find(getFunction(e)); + if (J == EdgeInformation.end()) return MissingValue; + + typename EdgeWeights::const_iterator I = J->second.find(e); + if (I == J->second.end()) return MissingValue; + + return I->second; + } + + void setEdgeWeight(Edge e, double w) { + DEBUG_WITH_TYPE("profile-info", + dbgs() << "Creating Edge " << e + << " (weight: " << format("%.20g",w) << ")\n"); + EdgeInformation[getFunction(e)][e] = w; + } + + void addEdgeWeight(Edge e, double w); + + EdgeWeights &getEdgeWeights (const FType *F) { + return EdgeInformation[F]; + } + + //===------------------------------------------------------------------===// + /// Analysis Update Methods + /// + void removeBlock(const BType *BB); + + void removeEdge(Edge e); + + void replaceEdge(const Edge &, const Edge &); + + enum GetPathMode { + GetPathToExit = 1, + GetPathToValue = 2, + GetPathToDest = 4, + GetPathWithNewEdges = 8 + }; + + const BType *GetPath(const BType *Src, const BType *Dest, + Path &P, unsigned Mode); + + void divertFlow(const Edge &, const Edge &); + + void splitEdge(const BType *FirstBB, const BType *SecondBB, + const BType *NewBB, bool MergeIdenticalEdges = false); + + void splitBlock(const BType *Old, const BType* New); + + void splitBlock(const BType *BB, const BType* NewBB, + BType *const *Preds, unsigned NumPreds); + + void replaceAllUses(const BType *RmBB, const BType *DestBB); + + void transfer(const FType *Old, const FType *New); + + void repair(const FType *F); + + void dump(FType *F = 0, bool real = true) { + dbgs() << "**** This is ProfileInfo " << this << " speaking:\n"; + if (!real) { + typename std::set Functions; + + dbgs() << "Functions: \n"; + if (F) { + dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; + Functions.insert(F); + } else { + for (typename std::map::iterator fi = FunctionInformation.begin(), + fe = FunctionInformation.end(); fi != fe; ++fi) { + dbgs() << fi->first << "@" << format("%p",fi->first) << ": " << format("%.20g",fi->second) << "\n"; + Functions.insert(fi->first); + } + } + + for (typename std::set::iterator FI = Functions.begin(), FE = Functions.end(); + FI != FE; ++FI) { + const FType *F = *FI; + typename std::map::iterator bwi = BlockInformation.find(F); + dbgs() << "BasicBlocks for Function " << F << ":\n"; + for (typename BlockCounts::const_iterator bi = bwi->second.begin(), be = bwi->second.end(); bi != be; ++bi) { + dbgs() << bi->first << "@" << format("%p", bi->first) << ": " << format("%.20g",bi->second) << "\n"; + } + } + + for (typename std::set::iterator FI = Functions.begin(), FE = Functions.end(); + FI != FE; ++FI) { + typename std::map::iterator ei = EdgeInformation.find(*FI); + dbgs() << "Edges for Function " << ei->first << ":\n"; + for (typename EdgeWeights::iterator ewi = ei->second.begin(), ewe = ei->second.end(); + ewi != ewe; ++ewi) { + dbgs() << ewi->first << ": " << format("%.20g",ewi->second) << "\n"; + } + } + } else { + assert(F && "No function given, this is not supported!"); + dbgs() << "Functions: \n"; + dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n"; + + dbgs() << "BasicBlocks for Function " << F << ":\n"; + for (typename FType::const_iterator BI = F->begin(), BE = F->end(); + BI != BE; ++BI) { + const BType *BB = &(*BI); + dbgs() << BB << "@" << format("%p", BB) << ": " << format("%.20g",getExecutionCount(BB)) << "\n"; + } + } + dbgs() << "**** ProfileInfo " << this << ", over and out.\n"; + } + + bool CalculateMissingEdge(const BType *BB, Edge &removed, bool assumeEmptyExit = false); + + bool EstimateMissingEdges(const BType *BB); + + ProfileInfoT *MI() { + if (MachineProfile == 0) + MachineProfile = new ProfileInfoT(); + return MachineProfile; + } + + bool hasMI() const { + return (MachineProfile != 0); + } + }; + + typedef ProfileInfoT ProfileInfo; + typedef ProfileInfoT MachineProfileInfo; + + /// createProfileLoaderPass - This function returns a Pass that loads the + /// profiling information for the module from the specified filename, making + /// it available to the optimizers. + Pass *createProfileLoaderPass(const std::string &Filename); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/ProfileInfoLoader.h b/final/include/llvm/Analysis/ProfileInfoLoader.h new file mode 100644 index 00000000000..9e0c393c428 --- /dev/null +++ b/final/include/llvm/Analysis/ProfileInfoLoader.h @@ -0,0 +1,84 @@ +//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ProfileInfoLoader class is used to load and represent profiling +// information read in from the dump file. If conversions between formats are +// needed, it can also do this. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H +#define LLVM_ANALYSIS_PROFILEINFOLOADER_H + +#include +#include +#include + +namespace llvm { + +class Module; +class Function; +class BasicBlock; + +class ProfileInfoLoader { + const std::string &Filename; + Module &M; + std::vector CommandLines; + std::vector FunctionCounts; + std::vector BlockCounts; + std::vector EdgeCounts; + std::vector OptimalEdgeCounts; + std::vector BBTrace; + bool Warned; +public: + // ProfileInfoLoader ctor - Read the specified profiling data file, exiting + // the program if the file is invalid or broken. + ProfileInfoLoader(const char *ToolName, const std::string &Filename, + Module &M); + + static const unsigned Uncounted; + + unsigned getNumExecutions() const { return CommandLines.size(); } + const std::string &getExecution(unsigned i) const { return CommandLines[i]; } + + const std::string &getFileName() const { return Filename; } + + // getRawFunctionCounts - This method is used by consumers of function + // counting information. + // + const std::vector &getRawFunctionCounts() const { + return FunctionCounts; + } + + // getRawBlockCounts - This method is used by consumers of block counting + // information. + // + const std::vector &getRawBlockCounts() const { + return BlockCounts; + } + + // getEdgeCounts - This method is used by consumers of edge counting + // information. + // + const std::vector &getRawEdgeCounts() const { + return EdgeCounts; + } + + // getEdgeOptimalCounts - This method is used by consumers of optimal edge + // counting information. + // + const std::vector &getRawOptimalEdgeCounts() const { + return OptimalEdgeCounts; + } + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/ProfileInfoTypes.h b/final/include/llvm/Analysis/ProfileInfoTypes.h new file mode 100644 index 00000000000..6b4ac85082b --- /dev/null +++ b/final/include/llvm/Analysis/ProfileInfoTypes.h @@ -0,0 +1,60 @@ +/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +|*===----------------------------------------------------------------------===*| +|* +|* This file defines constants shared by the various different profiling +|* runtime libraries and the LLVM C++ profile info loader. It must be a +|* C header because, at present, the profiling runtimes are written in C. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H +#define LLVM_ANALYSIS_PROFILEINFOTYPES_H + +/* Included by libprofile. */ +#if defined(__cplusplus) +extern "C" { +#endif + +/* IDs to distinguish between those path counters stored in hashses vs arrays */ +enum ProfilingStorageType { + ProfilingArray = 1, + ProfilingHash = 2 +}; + +enum ProfilingType { + ArgumentInfo = 1, /* The command line argument block */ + FunctionInfo = 2, /* Function profiling information */ + BlockInfo = 3, /* Block profiling information */ + EdgeInfo = 4, /* Edge profiling information */ + PathInfo = 5, /* Path profiling information */ + BBTraceInfo = 6, /* Basic block trace information */ + OptEdgeInfo = 7 /* Edge profiling information, optimal version */ +}; + +/* + * The header for tables that map path numbers to path counters. + */ +typedef struct { + unsigned fnNumber; /* function number for these counters */ + unsigned numEntries; /* number of entries stored */ +} PathProfileHeader; + +/* + * Describes an entry in a tagged table for path counters. + */ +typedef struct { + unsigned pathNumber; + unsigned pathCounter; +} PathProfileTableEntry; + +#if defined(__cplusplus) +} +#endif + +#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/final/include/llvm/Analysis/RegionInfo.h b/final/include/llvm/Analysis/RegionInfo.h new file mode 100644 index 00000000000..a36ca110d8c --- /dev/null +++ b/final/include/llvm/Analysis/RegionInfo.h @@ -0,0 +1,683 @@ +//===- RegionInfo.h - SESE region analysis ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Calculate a program structure tree built out of single entry single exit +// regions. +// The basic ideas are taken from "The Program Structure Tree - Richard Johnson, +// David Pearson, Keshav Pingali - 1994", however enriched with ideas from "The +// Refined Process Structure Tree - Jussi Vanhatalo, Hagen Voelyer, Jana +// Koehler - 2009". +// The algorithm to calculate these data structures however is completely +// different, as it takes advantage of existing information already available +// in (Post)dominace tree and dominance frontier passes. This leads to a simpler +// and in practice hopefully better performing algorithm. The runtime of the +// algorithms described in the papers above are both linear in graph size, +// O(V+E), whereas this algorithm is not, as the dominance frontier information +// itself is not, but in practice runtime seems to be in the order of magnitude +// of dominance tree calculation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGION_INFO_H +#define LLVM_ANALYSIS_REGION_INFO_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +class Region; +class RegionInfo; +class raw_ostream; +class Loop; +class LoopInfo; + +/// @brief Marker class to iterate over the elements of a Region in flat mode. +/// +/// The class is used to either iterate in Flat mode or by not using it to not +/// iterate in Flat mode. During a Flat mode iteration all Regions are entered +/// and the iteration returns every BasicBlock. If the Flat mode is not +/// selected for SubRegions just one RegionNode containing the subregion is +/// returned. +template +class FlatIt {}; + +/// @brief A RegionNode represents a subregion or a BasicBlock that is part of a +/// Region. +class RegionNode { + // DO NOT IMPLEMENT + RegionNode(const RegionNode &); + // DO NOT IMPLEMENT + const RegionNode &operator=(const RegionNode &); + +protected: + /// This is the entry basic block that starts this region node. If this is a + /// BasicBlock RegionNode, then entry is just the basic block, that this + /// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode. + /// + /// In the BBtoRegionNode map of the parent of this node, BB will always map + /// to this node no matter which kind of node this one is. + /// + /// The node can hold either a Region or a BasicBlock. + /// Use one bit to save, if this RegionNode is a subregion or BasicBlock + /// RegionNode. + PointerIntPair entry; + + /// @brief The parent Region of this RegionNode. + /// @see getParent() + Region* parent; + +public: + /// @brief Create a RegionNode. + /// + /// @param Parent The parent of this RegionNode. + /// @param Entry The entry BasicBlock of the RegionNode. If this + /// RegionNode represents a BasicBlock, this is the + /// BasicBlock itself. If it represents a subregion, this + /// is the entry BasicBlock of the subregion. + /// @param isSubRegion If this RegionNode represents a SubRegion. + inline RegionNode(Region* Parent, BasicBlock* Entry, bool isSubRegion = 0) + : entry(Entry, isSubRegion), parent(Parent) {} + + /// @brief Get the parent Region of this RegionNode. + /// + /// The parent Region is the Region this RegionNode belongs to. If for + /// example a BasicBlock is element of two Regions, there exist two + /// RegionNodes for this BasicBlock. Each with the getParent() function + /// pointing to the Region this RegionNode belongs to. + /// + /// @return Get the parent Region of this RegionNode. + inline Region* getParent() const { return parent; } + + /// @brief Get the entry BasicBlock of this RegionNode. + /// + /// If this RegionNode represents a BasicBlock this is just the BasicBlock + /// itself, otherwise we return the entry BasicBlock of the Subregion + /// + /// @return The entry BasicBlock of this RegionNode. + inline BasicBlock* getEntry() const { return entry.getPointer(); } + + /// @brief Get the content of this RegionNode. + /// + /// This can be either a BasicBlock or a subregion. Before calling getNodeAs() + /// check the type of the content with the isSubRegion() function call. + /// + /// @return The content of this RegionNode. + template + inline T* getNodeAs() const; + + /// @brief Is this RegionNode a subregion? + /// + /// @return True if it contains a subregion. False if it contains a + /// BasicBlock. + inline bool isSubRegion() const { + return entry.getInt(); + } +}; + +/// Print a RegionNode. +inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node); + +template<> +inline BasicBlock* RegionNode::getNodeAs() const { + assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); + return getEntry(); +} + +template<> +inline Region* RegionNode::getNodeAs() const { + assert(isSubRegion() && "This is not a subregion RegionNode!"); + return reinterpret_cast(const_cast(this)); +} + +//===----------------------------------------------------------------------===// +/// @brief A single entry single exit Region. +/// +/// A Region is a connected subgraph of a control flow graph that has exactly +/// two connections to the remaining graph. It can be used to analyze or +/// optimize parts of the control flow graph. +/// +/// A simple Region is connected to the remaing graph by just two +/// edges. One edge entering the Region and another one leaving the Region. +/// +/// An extended Region (or just Region) is a subgraph that can be +/// transform into a simple Region. The transformation is done by adding +/// BasicBlocks that merge several entry or exit edges so that after the merge +/// just one entry and one exit edge exists. +/// +/// The \e Entry of a Region is the first BasicBlock that is passed after +/// entering the Region. It is an element of the Region. The entry BasicBlock +/// dominates all BasicBlocks in the Region. +/// +/// The \e Exit of a Region is the first BasicBlock that is passed after +/// leaving the Region. It is not an element of the Region. The exit BasicBlock, +/// postdominates all BasicBlocks in the Region. +/// +/// A canonical Region cannot be constructed by combining smaller +/// Regions. +/// +/// Region A is the \e parent of Region B, if B is completely contained in A. +/// +/// Two canonical Regions either do not intersect at all or one is +/// the parent of the other. +/// +/// The Program Structure Tree is a graph (V, E) where V is the set of +/// Regions in the control flow graph and E is the \e parent relation of these +/// Regions. +/// +/// Example: +/// +/// \verbatim +/// A simple control flow graph, that contains two regions. +/// +/// 1 +/// / | +/// 2 | +/// / \ 3 +/// 4 5 | +/// | | | +/// 6 7 8 +/// \ | / +/// \ |/ Region A: 1 -> 9 {1,2,3,4,5,6,7,8} +/// 9 Region B: 2 -> 9 {2,4,5,6,7} +/// \endverbatim +/// +/// You can obtain more examples by either calling +/// +/// "opt -regions -analyze anyprogram.ll" +/// or +/// "opt -view-regions-only anyprogram.ll" +/// +/// on any LLVM file you are interested in. +/// +/// The first call returns a textual representation of the program structure +/// tree, the second one creates a graphical representation using graphviz. +class Region : public RegionNode { + friend class RegionInfo; + // DO NOT IMPLEMENT + Region(const Region &); + // DO NOT IMPLEMENT + const Region &operator=(const Region &); + + // Information necessary to manage this Region. + RegionInfo* RI; + DominatorTree *DT; + + // The exit BasicBlock of this region. + // (The entry BasicBlock is part of RegionNode) + BasicBlock *exit; + + typedef std::vector RegionSet; + + // The subregions of this region. + RegionSet children; + + typedef std::map BBNodeMapT; + + // Save the BasicBlock RegionNodes that are element of this Region. + mutable BBNodeMapT BBNodeMap; + + /// verifyBBInRegion - Check if a BB is in this Region. This check also works + /// if the region is incorrectly built. (EXPENSIVE!) + void verifyBBInRegion(BasicBlock* BB) const; + + /// verifyWalk - Walk over all the BBs of the region starting from BB and + /// verify that all reachable basic blocks are elements of the region. + /// (EXPENSIVE!) + void verifyWalk(BasicBlock* BB, std::set* visitedBB) const; + + /// verifyRegionNest - Verify if the region and its children are valid + /// regions (EXPENSIVE!) + void verifyRegionNest() const; + +public: + /// @brief Create a new region. + /// + /// @param Entry The entry basic block of the region. + /// @param Exit The exit basic block of the region. + /// @param RI The region info object that is managing this region. + /// @param DT The dominator tree of the current function. + /// @param Parent The surrounding region or NULL if this is a top level + /// region. + Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RI, + DominatorTree *DT, Region *Parent = 0); + + /// Delete the Region and all its subregions. + ~Region(); + + /// @brief Get the entry BasicBlock of the Region. + /// @return The entry BasicBlock of the region. + BasicBlock *getEntry() const { return RegionNode::getEntry(); } + + /// @brief Replace the entry basic block of the region with the new basic + /// block. + /// + /// @param BB The new entry basic block of the region. + void replaceEntry(BasicBlock *BB); + + /// @brief Replace the exit basic block of the region with the new basic + /// block. + /// + /// @param BB The new exit basic block of the region. + void replaceExit(BasicBlock *BB); + + /// @brief Get the exit BasicBlock of the Region. + /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel + /// Region. + BasicBlock *getExit() const { return exit; } + + /// @brief Get the parent of the Region. + /// @return The parent of the Region or NULL if this is a top level + /// Region. + Region *getParent() const { return RegionNode::getParent(); } + + /// @brief Get the RegionNode representing the current Region. + /// @return The RegionNode representing the current Region. + RegionNode* getNode() const { + return const_cast(reinterpret_cast(this)); + } + + /// @brief Get the nesting level of this Region. + /// + /// An toplevel Region has depth 0. + /// + /// @return The depth of the region. + unsigned getDepth() const; + + /// @brief Check if a Region is the TopLevel region. + /// + /// The toplevel region represents the whole function. + bool isTopLevelRegion() const { return exit == NULL; } + + /// @brief Return a new (non canonical) region, that is obtained by joining + /// this region with its predecessors. + /// + /// @return A region also starting at getEntry(), but reaching to the next + /// basic block that forms with getEntry() a (non canonical) region. + /// NULL if such a basic block does not exist. + Region *getExpandedRegion() const; + + /// @brief Return the first block of this region's single entry edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single entry edge, + /// else NULL. + BasicBlock *getEnteringBlock() const; + + /// @brief Return the first block of this region's single exit edge, + /// if existing. + /// + /// @return The BasicBlock starting this region's single exit edge, + /// else NULL. + BasicBlock *getExitingBlock() const; + + /// @brief Is this a simple region? + /// + /// A region is simple if it has exactly one exit and one entry edge. + /// + /// @return True if the Region is simple. + bool isSimple() const; + + /// @brief Returns the name of the Region. + /// @return The Name of the Region. + std::string getNameStr() const; + + /// @brief Return the RegionInfo object, that belongs to this Region. + RegionInfo *getRegionInfo() const { + return RI; + } + + /// @brief Print the region. + /// + /// @param OS The output stream the Region is printed to. + /// @param printTree Print also the tree of subregions. + /// @param level The indentation level used for printing. + void print(raw_ostream& OS, bool printTree = true, unsigned level = 0) const; + + /// @brief Print the region to stderr. + void dump() const; + + /// @brief Check if the region contains a BasicBlock. + /// + /// @param BB The BasicBlock that might be contained in this Region. + /// @return True if the block is contained in the region otherwise false. + bool contains(const BasicBlock *BB) const; + + /// @brief Check if the region contains another region. + /// + /// @param SubRegion The region that might be contained in this Region. + /// @return True if SubRegion is contained in the region otherwise false. + bool contains(const Region *SubRegion) const { + // Toplevel Region. + if (!getExit()) + return true; + + return contains(SubRegion->getEntry()) + && (contains(SubRegion->getExit()) || SubRegion->getExit() == getExit()); + } + + /// @brief Check if the region contains an Instruction. + /// + /// @param Inst The Instruction that might be contained in this region. + /// @return True if the Instruction is contained in the region otherwise false. + bool contains(const Instruction *Inst) const { + return contains(Inst->getParent()); + } + + /// @brief Check if the region contains a loop. + /// + /// @param L The loop that might be contained in this region. + /// @return True if the loop is contained in the region otherwise false. + /// In case a NULL pointer is passed to this function the result + /// is false, except for the region that describes the whole function. + /// In that case true is returned. + bool contains(const Loop *L) const; + + /// @brief Get the outermost loop in the region that contains a loop. + /// + /// Find for a Loop L the outermost loop OuterL that is a parent loop of L + /// and is itself contained in the region. + /// + /// @param L The loop the lookup is started. + /// @return The outermost loop in the region, NULL if such a loop does not + /// exist or if the region describes the whole function. + Loop *outermostLoopInRegion(Loop *L) const; + + /// @brief Get the outermost loop in the region that contains a basic block. + /// + /// Find for a basic block BB the outermost loop L that contains BB and is + /// itself contained in the region. + /// + /// @param LI A pointer to a LoopInfo analysis. + /// @param BB The basic block surrounded by the loop. + /// @return The outermost loop in the region, NULL if such a loop does not + /// exist or if the region describes the whole function. + Loop *outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const; + + /// @brief Get the subregion that starts at a BasicBlock + /// + /// @param BB The BasicBlock the subregion should start. + /// @return The Subregion if available, otherwise NULL. + Region* getSubRegionNode(BasicBlock *BB) const; + + /// @brief Get the RegionNode for a BasicBlock + /// + /// @param BB The BasicBlock at which the RegionNode should start. + /// @return If available, the RegionNode that represents the subregion + /// starting at BB. If no subregion starts at BB, the RegionNode + /// representing BB. + RegionNode* getNode(BasicBlock *BB) const; + + /// @brief Get the BasicBlock RegionNode for a BasicBlock + /// + /// @param BB The BasicBlock for which the RegionNode is requested. + /// @return The RegionNode representing the BB. + RegionNode* getBBNode(BasicBlock *BB) const; + + /// @brief Add a new subregion to this Region. + /// + /// @param SubRegion The new subregion that will be added. + /// @param moveChildren Move the children of this region, that are also + /// contained in SubRegion into SubRegion. + void addSubRegion(Region *SubRegion, bool moveChildren = false); + + /// @brief Remove a subregion from this Region. + /// + /// The subregion is not deleted, as it will probably be inserted into another + /// region. + /// @param SubRegion The SubRegion that will be removed. + Region *removeSubRegion(Region *SubRegion); + + /// @brief Move all direct child nodes of this Region to another Region. + /// + /// @param To The Region the child nodes will be transfered to. + void transferChildrenTo(Region *To); + + /// @brief Verify if the region is a correct region. + /// + /// Check if this is a correctly build Region. This is an expensive check, as + /// the complete CFG of the Region will be walked. + void verifyRegion() const; + + /// @brief Clear the cache for BB RegionNodes. + /// + /// After calling this function the BasicBlock RegionNodes will be stored at + /// different memory locations. RegionNodes obtained before this function is + /// called are therefore not comparable to RegionNodes abtained afterwords. + void clearNodeCache(); + + /// @name Subregion Iterators + /// + /// These iterators iterator over all subregions of this Region. + //@{ + typedef RegionSet::iterator iterator; + typedef RegionSet::const_iterator const_iterator; + + iterator begin() { return children.begin(); } + iterator end() { return children.end(); } + + const_iterator begin() const { return children.begin(); } + const_iterator end() const { return children.end(); } + //@} + + /// @name BasicBlock Iterators + /// + /// These iterators iterate over all BasicBlock RegionNodes that are + /// contained in this Region. The iterator also iterates over BasicBlocks + /// that are elements of a subregion of this Region. It is therefore called a + /// flat iterator. + //@{ + typedef df_iterator, false, + GraphTraits > > block_iterator; + + typedef df_iterator, + false, GraphTraits > > + const_block_iterator; + + block_iterator block_begin(); + block_iterator block_end(); + + const_block_iterator block_begin() const; + const_block_iterator block_end() const; + //@} + + /// @name Element Iterators + /// + /// These iterators iterate over all BasicBlock and subregion RegionNodes that + /// are direct children of this Region. It does not iterate over any + /// RegionNodes that are also element of a subregion of this Region. + //@{ + typedef df_iterator, false, + GraphTraits > element_iterator; + + typedef df_iterator, + false, GraphTraits > + const_element_iterator; + + element_iterator element_begin(); + element_iterator element_end(); + + const_element_iterator element_begin() const; + const_element_iterator element_end() const; + //@} +}; + +//===----------------------------------------------------------------------===// +/// @brief Analysis that detects all canonical Regions. +/// +/// The RegionInfo pass detects all canonical regions in a function. The Regions +/// are connected using the parent relation. This builds a Program Structure +/// Tree. +class RegionInfo : public FunctionPass { + typedef DenseMap BBtoBBMap; + typedef DenseMap BBtoRegionMap; + typedef SmallPtrSet RegionSet; + + // DO NOT IMPLEMENT + RegionInfo(const RegionInfo &); + // DO NOT IMPLEMENT + const RegionInfo &operator=(const RegionInfo &); + + DominatorTree *DT; + PostDominatorTree *PDT; + DominanceFrontier *DF; + + /// The top level region. + Region *TopLevelRegion; + + /// Map every BB to the smallest region, that contains BB. + BBtoRegionMap BBtoRegion; + + // isCommonDomFrontier - Returns true if BB is in the dominance frontier of + // entry, because it was inherited from exit. In the other case there is an + // edge going from entry to BB without passing exit. + bool isCommonDomFrontier(BasicBlock* BB, BasicBlock* entry, + BasicBlock* exit) const; + + // isRegion - Check if entry and exit surround a valid region, based on + // dominance tree and dominance frontier. + bool isRegion(BasicBlock* entry, BasicBlock* exit) const; + + // insertShortCut - Saves a shortcut pointing from entry to exit. + // This function may extend this shortcut if possible. + void insertShortCut(BasicBlock* entry, BasicBlock* exit, + BBtoBBMap* ShortCut) const; + + // getNextPostDom - Returns the next BB that postdominates N, while skipping + // all post dominators that cannot finish a canonical region. + DomTreeNode *getNextPostDom(DomTreeNode* N, BBtoBBMap *ShortCut) const; + + // isTrivialRegion - A region is trivial, if it contains only one BB. + bool isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const; + + // createRegion - Creates a single entry single exit region. + Region *createRegion(BasicBlock *entry, BasicBlock *exit); + + // findRegionsWithEntry - Detect all regions starting with bb 'entry'. + void findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut); + + // scanForRegions - Detects regions in F. + void scanForRegions(Function &F, BBtoBBMap *ShortCut); + + // getTopMostParent - Get the top most parent with the same entry block. + Region *getTopMostParent(Region *region); + + // buildRegionsTree - build the region hierarchy after all region detected. + void buildRegionsTree(DomTreeNode *N, Region *region); + + // Calculate - detecte all regions in function and build the region tree. + void Calculate(Function& F); + + void releaseMemory(); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(Region *R); + + // isSimple - Check if a region is a simple region with exactly one entry + // edge and exactly one exit edge. + bool isSimple(Region* R) const; + +public: + static char ID; + explicit RegionInfo(); + + ~RegionInfo(); + + /// @name FunctionPass interface + //@{ + virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void print(raw_ostream &OS, const Module *) const; + virtual void verifyAnalysis() const; + //@} + + /// @brief Get the smallest region that contains a BasicBlock. + /// + /// @param BB The basic block. + /// @return The smallest region, that contains BB or NULL, if there is no + /// region containing BB. + Region *getRegionFor(BasicBlock *BB) const; + + /// @brief Set the smallest region that surrounds a basic block. + /// + /// @param BB The basic block surrounded by a region. + /// @param R The smallest region that surrounds BB. + void setRegionFor(BasicBlock *BB, Region *R); + + /// @brief A shortcut for getRegionFor(). + /// + /// @param BB The basic block. + /// @return The smallest region, that contains BB or NULL, if there is no + /// region containing BB. + Region *operator[](BasicBlock *BB) const; + + /// @brief Return the exit of the maximal refined region, that starts at a + /// BasicBlock. + /// + /// @param BB The BasicBlock the refined region starts. + BasicBlock *getMaxRegionExit(BasicBlock *BB) const; + + /// @brief Find the smallest region that contains two regions. + /// + /// @param A The first region. + /// @param B The second region. + /// @return The smallest region containing A and B. + Region *getCommonRegion(Region* A, Region *B) const; + + /// @brief Find the smallest region that contains two basic blocks. + /// + /// @param A The first basic block. + /// @param B The second basic block. + /// @return The smallest region that contains A and B. + Region* getCommonRegion(BasicBlock* A, BasicBlock *B) const { + return getCommonRegion(getRegionFor(A), getRegionFor(B)); + } + + /// @brief Find the smallest region that contains a set of regions. + /// + /// @param Regions A vector of regions. + /// @return The smallest region that contains all regions in Regions. + Region* getCommonRegion(SmallVectorImpl &Regions) const; + + /// @brief Find the smallest region that contains a set of basic blocks. + /// + /// @param BBs A vector of basic blocks. + /// @return The smallest region that contains all basic blocks in BBS. + Region* getCommonRegion(SmallVectorImpl &BBs) const; + + Region *getTopLevelRegion() const { + return TopLevelRegion; + } + + /// @brief Update RegionInfo after a basic block was split. + /// + /// @param NewBB The basic block that was created before OldBB. + /// @param OldBB The old basic block. + void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB); + + /// @brief Clear the Node Cache for all Regions. + /// + /// @see Region::clearNodeCache() + void clearNodeCache() { + if (TopLevelRegion) + TopLevelRegion->clearNodeCache(); + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) { + if (Node.isSubRegion()) + return OS << Node.getNodeAs()->getNameStr(); + else + return OS << Node.getNodeAs()->getNameStr(); +} +} // End llvm namespace +#endif + diff --git a/final/include/llvm/Analysis/RegionIterator.h b/final/include/llvm/Analysis/RegionIterator.h new file mode 100644 index 00000000000..ced5b528cbb --- /dev/null +++ b/final/include/llvm/Analysis/RegionIterator.h @@ -0,0 +1,342 @@ +//===- RegionIterator.h - Iterators to iteratate over Regions ---*- 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 iterators to iterate over the elements of a Region. +//===----------------------------------------------------------------------===// +#ifndef LLVM_ANALYSIS_REGION_ITERATOR_H +#define LLVM_ANALYSIS_REGION_ITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +//===----------------------------------------------------------------------===// +/// @brief Hierachical RegionNode successor iterator. +/// +/// This iterator iterates over all successors of a RegionNode. +/// +/// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of +/// the parent Region. Furthermore for BasicBlocks that start a subregion, a +/// RegionNode representing the subregion is returned. +/// +/// For a subregion RegionNode there is just one successor. The RegionNode +/// representing the exit of the subregion. +template +class RNSuccIterator : public std::iterator +{ + typedef std::iterator super; + // The iterator works in two modes, bb mode or region mode. + enum ItMode{ + // In BB mode it returns all successors of this BasicBlock as its + // successors. + ItBB, + // In region mode there is only one successor, thats the regionnode mapping + // to the exit block of the regionnode + ItRgBegin, // At the beginning of the regionnode successor. + ItRgEnd // At the end of the regionnode successor. + }; + + // Use two bit to represent the mode iterator. + PointerIntPair Node; + + // The block successor iterator. + succ_iterator BItor; + + // advanceRegionSucc - A region node has only one successor. It reaches end + // once we advance it. + void advanceRegionSucc() { + assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!"); + Node.setInt(ItRgEnd); + } + + NodeType* getNode() const{ return Node.getPointer(); } + + // isRegionMode - Is the current iterator in region mode? + bool isRegionMode() const { return Node.getInt() != ItBB; } + + // Get the immediate successor. This function may return a Basic Block + // RegionNode or a subregion RegionNode. + RegionNode* getISucc(BasicBlock* BB) const { + RegionNode *succ; + succ = getNode()->getParent()->getNode(BB); + assert(succ && "BB not in Region or entered subregion!"); + return succ; + } + + // getRegionSucc - Return the successor basic block of a SubRegion RegionNode. + inline BasicBlock* getRegionSucc() const { + assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!"); + return getNode()->template getNodeAs()->getExit(); + } + + // isExit - Is this the exit BB of the Region? + inline bool isExit(BasicBlock* BB) const { + return getNode()->getParent()->getExit() == BB; + } +public: + typedef RNSuccIterator Self; + + typedef typename super::pointer pointer; + + /// @brief Create begin iterator of a RegionNode. + inline RNSuccIterator(NodeType* node) + : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), + BItor(succ_begin(node->getEntry())) { + + + // Skip the exit block + if (!isRegionMode()) + while (succ_end(node->getEntry()) != BItor && isExit(*BItor)) + ++BItor; + + if (isRegionMode() && isExit(getRegionSucc())) + advanceRegionSucc(); + } + + /// @brief Create an end iterator. + inline RNSuccIterator(NodeType* node, bool) + : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), + BItor(succ_end(node->getEntry())) {} + + inline bool operator==(const Self& x) const { + assert(isRegionMode() == x.isRegionMode() && "Broken iterator!"); + if (isRegionMode()) + return Node.getInt() == x.Node.getInt(); + else + return BItor == x.BItor; + } + + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + BasicBlock* BB = isRegionMode() ? getRegionSucc() : *BItor; + assert(!isExit(BB) && "Iterator out of range!"); + return getISucc(BB); + } + + inline Self& operator++() { + if(isRegionMode()) { + // The Region only has 1 successor. + advanceRegionSucc(); + } else { + // Skip the exit. + do + ++BItor; + while (BItor != succ_end(getNode()->getEntry()) + && isExit(*BItor)); + } + return *this; + } + + inline Self operator++(int) { + Self tmp = *this; + ++*this; + return tmp; + } + + inline const Self &operator=(const Self &I) { + if (this != &I) { + assert(getNode()->getParent() == I.getNode()->getParent() + && "Cannot assign iterators of two different regions!"); + Node = I.Node; + BItor = I.BItor; + } + return *this; + } +}; + + +//===----------------------------------------------------------------------===// +/// @brief Flat RegionNode iterator. +/// +/// The Flat Region iterator will iterate over all BasicBlock RegionNodes that +/// are contained in the Region and its subregions. This is close to a virtual +/// control flow graph of the Region. +template +class RNSuccIterator > + : public std::iterator +{ + typedef std::iterator super; + NodeType* Node; + succ_iterator Itor; + +public: + typedef RNSuccIterator > Self; + typedef typename super::pointer pointer; + + /// @brief Create the iterator from a RegionNode. + /// + /// Note that the incoming node must be a bb node, otherwise it will trigger + /// an assertion when we try to get a BasicBlock. + inline RNSuccIterator(NodeType* node) : Node(node), + Itor(succ_begin(node->getEntry())) { + assert(!Node->isSubRegion() + && "Subregion node not allowed in flat iterating mode!"); + assert(Node->getParent() && "A BB node must have a parent!"); + + // Skip the exit block of the iterating region. + while (succ_end(Node->getEntry()) != Itor + && Node->getParent()->getExit() == *Itor) + ++Itor; + } + /// @brief Create an end iterator + inline RNSuccIterator(NodeType* node, bool) : Node(node), + Itor(succ_end(node->getEntry())) { + assert(!Node->isSubRegion() + && "Subregion node not allowed in flat iterating mode!"); + } + + inline bool operator==(const Self& x) const { + assert(Node->getParent() == x.Node->getParent() + && "Cannot compare iterators of different regions!"); + + return Itor == x.Itor && Node == x.Node; + } + + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + BasicBlock* BB = *Itor; + + // Get the iterating region. + Region* Parent = Node->getParent(); + + // The only case that the successor reaches out of the region is it reaches + // the exit of the region. + assert(Parent->getExit() != BB && "iterator out of range!"); + + return Parent->getBBNode(BB); + } + + inline Self& operator++() { + // Skip the exit block of the iterating region. + do + ++Itor; + while (Itor != succ_end(Node->getEntry()) + && Node->getParent()->getExit() == *Itor); + + return *this; + } + + inline Self operator++(int) { + Self tmp = *this; + ++*this; + return tmp; + } + + inline const Self &operator=(const Self &I) { + if (this != &I) { + assert(Node->getParent() == I.Node->getParent() + && "Cannot assign iterators to two different regions!"); + Node = I.Node; + Itor = I.Itor; + } + return *this; + } +}; + +template +inline RNSuccIterator succ_begin(NodeType* Node) { + return RNSuccIterator(Node); +} + +template +inline RNSuccIterator succ_end(NodeType* Node) { + return RNSuccIterator(Node, true); +} + +//===--------------------------------------------------------------------===// +// RegionNode GraphTraits specialization so the bbs in the region can be +// iterate by generic graph iterators. +// +// NodeT can either be region node or const region node, otherwise child_begin +// and child_end fail. + +#define RegionNodeGraphTraits(NodeT) \ + template<> struct GraphTraits { \ + typedef NodeT NodeType; \ + typedef RNSuccIterator ChildIteratorType; \ + static NodeType *getEntryNode(NodeType* N) { return N; } \ + static inline ChildIteratorType child_begin(NodeType *N) { \ + return RNSuccIterator(N); \ + } \ + static inline ChildIteratorType child_end(NodeType *N) { \ + return RNSuccIterator(N, true); \ + } \ +}; \ +template<> struct GraphTraits > { \ + typedef NodeT NodeType; \ + typedef RNSuccIterator > ChildIteratorType; \ + static NodeType *getEntryNode(NodeType* N) { return N; } \ + static inline ChildIteratorType child_begin(NodeType *N) { \ + return RNSuccIterator >(N); \ + } \ + static inline ChildIteratorType child_end(NodeType *N) { \ + return RNSuccIterator >(N, true); \ + } \ +} + +#define RegionGraphTraits(RegionT, NodeT) \ +template<> struct GraphTraits \ + : public GraphTraits { \ + typedef df_iterator nodes_iterator; \ + static NodeType *getEntryNode(RegionT* R) { \ + return R->getNode(R->getEntry()); \ + } \ + static nodes_iterator nodes_begin(RegionT* R) { \ + return nodes_iterator::begin(getEntryNode(R)); \ + } \ + static nodes_iterator nodes_end(RegionT* R) { \ + return nodes_iterator::end(getEntryNode(R)); \ + } \ +}; \ +template<> struct GraphTraits > \ + : public GraphTraits > { \ + typedef df_iterator, false, \ + GraphTraits > > nodes_iterator; \ + static NodeType *getEntryNode(RegionT* R) { \ + return R->getBBNode(R->getEntry()); \ + } \ + static nodes_iterator nodes_begin(RegionT* R) { \ + return nodes_iterator::begin(getEntryNode(R)); \ + } \ + static nodes_iterator nodes_end(RegionT* R) { \ + return nodes_iterator::end(getEntryNode(R)); \ + } \ +} + +RegionNodeGraphTraits(RegionNode); +RegionNodeGraphTraits(const RegionNode); + +RegionGraphTraits(Region, RegionNode); +RegionGraphTraits(const Region, const RegionNode); + +template <> struct GraphTraits + : public GraphTraits > { + typedef df_iterator, false, + GraphTraits > > nodes_iterator; + + static NodeType *getEntryNode(RegionInfo *RI) { + return GraphTraits >::getEntryNode(RI->getTopLevelRegion()); + } + static nodes_iterator nodes_begin(RegionInfo* RI) { + return nodes_iterator::begin(getEntryNode(RI)); + } + static nodes_iterator nodes_end(RegionInfo *RI) { + return nodes_iterator::end(getEntryNode(RI)); + } +}; + +} // End namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/RegionPass.h b/final/include/llvm/Analysis/RegionPass.h new file mode 100644 index 00000000000..aedc06aa6cf --- /dev/null +++ b/final/include/llvm/Analysis/RegionPass.h @@ -0,0 +1,126 @@ +//===- RegionPass.h - RegionPass class ------------------------------------===// +// +// 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 RegionPass class. All region based analysis, +// optimization and transformation passes are derived from RegionPass. +// This class is implemented following the some ideas of the LoopPass.h class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REGION_PASS_H +#define LLVM_REGION_PASS_H + +#include "llvm/Analysis/RegionInfo.h" + +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" + +#include + +namespace llvm { + +class RGPassManager; +class Function; + +//===----------------------------------------------------------------------===// +/// @brief A pass that runs on each Region in a function. +/// +/// RegionPass is managed by RGPassManager. +class RegionPass : public Pass { +public: + explicit RegionPass(char &pid) : Pass(PT_Region, pid) {} + + //===--------------------------------------------------------------------===// + /// @name To be implemented by every RegionPass + /// + //@{ + /// @brief Run the pass on a specific Region + /// + /// Accessing regions not contained in the current region is not allowed. + /// + /// @param R The region this pass is run on. + /// @param RGM The RegionPassManager that manages this Pass. + /// + /// @return True if the pass modifies this Region. + virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0; + + /// @brief Get a pass to print the LLVM IR in the region. + /// + /// @param O The ouput stream to print the Region. + /// @param Banner The banner to seperate different printed passes. + /// + /// @return The pass to print the LLVM IR in the region. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; } + virtual bool doFinalization() { return false; } + //@} + + //===--------------------------------------------------------------------===// + /// @name PassManager API + /// + //@{ + void preparePassManager(PMStack &PMS); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_RegionPassManager); + + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_RegionPassManager; + } + //@} +}; + +/// @brief The pass manager to schedule RegionPasses. +class RGPassManager : public FunctionPass, public PMDataManager { + std::deque RQ; + bool skipThisRegion; + bool redoThisRegion; + RegionInfo *RI; + Region *CurrentRegion; + +public: + static char ID; + explicit RGPassManager(int Depth); + + /// @brief Execute all of the passes scheduled for execution. + /// + /// @return True if any of the passes modifies the function. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + /// RGPassManager needs RegionInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Region Pass Manager"; + } + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + /// @brief Print passes managed by this manager. + void dumpPassStructure(unsigned Offset); + + /// @brief Print passes contained by this manager. + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_RegionPassManager; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/RegionPrinter.h b/final/include/llvm/Analysis/RegionPrinter.h new file mode 100644 index 00000000000..758748aad9e --- /dev/null +++ b/final/include/llvm/Analysis/RegionPrinter.h @@ -0,0 +1,26 @@ +//===-- RegionPrinter.h - Region printer external interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the region printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_REGIONPRINTER_H +#define LLVM_ANALYSIS_REGIONPRINTER_H + +namespace llvm { + class FunctionPass; + FunctionPass *createRegionViewerPass(); + FunctionPass *createRegionOnlyViewerPass(); + FunctionPass *createRegionPrinterPass(); + FunctionPass *createRegionOnlyPrinterPass(); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Analysis/ScalarEvolution.h b/final/include/llvm/Analysis/ScalarEvolution.h new file mode 100644 index 00000000000..d1938061bef --- /dev/null +++ b/final/include/llvm/Analysis/ScalarEvolution.h @@ -0,0 +1,748 @@ +//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ScalarEvolution class is an LLVM pass which can be used to analyze and +// categorize scalar expressions in loops. It specializes in recognizing +// general induction variables, representing them with the abstract and opaque +// SCEV class. Given this analysis, trip counts of loops and other important +// properties can be obtained. +// +// This analysis is primarily useful for induction variable substitution and +// strength reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_H + +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + class APInt; + class Constant; + class ConstantInt; + class DominatorTree; + class Type; + class ScalarEvolution; + class TargetData; + class LLVMContext; + class Loop; + class LoopInfo; + class Operator; + class SCEVUnknown; + class SCEV; + template<> struct FoldingSetTrait; + + /// SCEV - This class represents an analyzed expression in the program. These + /// are opaque objects that the client is not allowed to do much with + /// directly. + /// + class SCEV : public FoldingSetNode { + friend struct FoldingSetTrait; + + /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// The ScalarEvolution's BumpPtrAllocator holds the data. + FoldingSetNodeIDRef FastID; + + // The SCEV baseclass this node corresponds to + const unsigned short SCEVType; + + protected: + /// SubclassData - This field is initialized to zero and may be used in + /// subclasses to store miscellaneous information. + unsigned short SubclassData; + + private: + SCEV(const SCEV &); // DO NOT IMPLEMENT + void operator=(const SCEV &); // DO NOT IMPLEMENT + + public: + explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) : + FastID(ID), SCEVType(SCEVTy), SubclassData(0) {} + + unsigned getSCEVType() const { return SCEVType; } + + /// getType - Return the LLVM type of this SCEV expression. + /// + const Type *getType() const; + + /// isZero - Return true if the expression is a constant zero. + /// + bool isZero() const; + + /// isOne - Return true if the expression is a constant one. + /// + bool isOne() const; + + /// isAllOnesValue - Return true if the expression is a constant + /// all-ones value. + /// + bool isAllOnesValue() const; + + /// print - Print out the internal representation of this scalar to the + /// specified stream. This should really only be used for debugging + /// purposes. + void print(raw_ostream &OS) const; + + /// dump - This method is used for debugging. + /// + void dump() const; + }; + + // Specialize FoldingSetTrait for SCEV to avoid needing to compute + // temporary FoldingSetNodeID values. + template<> struct FoldingSetTrait : DefaultFoldingSetTrait { + static void Profile(const SCEV &X, FoldingSetNodeID& ID) { + ID = X.FastID; + } + static bool Equals(const SCEV &X, const FoldingSetNodeID &ID, + FoldingSetNodeID &TempID) { + return ID == X.FastID; + } + static unsigned ComputeHash(const SCEV &X, FoldingSetNodeID &TempID) { + return X.FastID.ComputeHash(); + } + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) { + S.print(OS); + return OS; + } + + /// SCEVCouldNotCompute - An object of this class is returned by queries that + /// could not be answered. For example, if you ask for the number of + /// iterations of a linked-list traversal loop, you will get one of these. + /// None of the standard SCEV operations are valid on this class, it is just a + /// marker. + struct SCEVCouldNotCompute : public SCEV { + SCEVCouldNotCompute(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCouldNotCompute *S) { return true; } + static bool classof(const SCEV *S); + }; + + /// ScalarEvolution - This class is the main scalar evolution driver. Because + /// client code (intentionally) can't do much with the SCEV objects directly, + /// they must ask this class for services. + /// + class ScalarEvolution : public FunctionPass { + public: + /// LoopDisposition - An enum describing the relationship between a + /// SCEV and a loop. + enum LoopDisposition { + LoopVariant, ///< The SCEV is loop-variant (unknown). + LoopInvariant, ///< The SCEV is loop-invariant. + LoopComputable ///< The SCEV varies predictably with the loop. + }; + + /// BlockDisposition - An enum describing the relationship between a + /// SCEV and a basic block. + enum BlockDisposition { + DoesNotDominateBlock, ///< The SCEV does not dominate the block. + DominatesBlock, ///< The SCEV dominates the block. + ProperlyDominatesBlock ///< The SCEV properly dominates the block. + }; + + private: + /// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be + /// notified whenever a Value is deleted. + class SCEVCallbackVH : public CallbackVH { + ScalarEvolution *SE; + virtual void deleted(); + virtual void allUsesReplacedWith(Value *New); + public: + SCEVCallbackVH(Value *V, ScalarEvolution *SE = 0); + }; + + friend class SCEVCallbackVH; + friend class SCEVExpander; + friend class SCEVUnknown; + + /// F - The function we are analyzing. + /// + Function *F; + + /// LI - The loop information for the function we are currently analyzing. + /// + LoopInfo *LI; + + /// TD - The target data information for the target we are targeting. + /// + TargetData *TD; + + /// DT - The dominator tree. + /// + DominatorTree *DT; + + /// CouldNotCompute - This SCEV is used to represent unknown trip + /// counts and things. + SCEVCouldNotCompute CouldNotCompute; + + /// ValueExprMapType - The typedef for ValueExprMap. + /// + typedef DenseMap > + ValueExprMapType; + + /// ValueExprMap - This is a cache of the values we have analyzed so far. + /// + ValueExprMapType ValueExprMap; + + /// BackedgeTakenInfo - Information about the backedge-taken count + /// of a loop. This currently includes an exact count and a maximum count. + /// + struct BackedgeTakenInfo { + /// Exact - An expression indicating the exact backedge-taken count of + /// the loop if it is known, or a SCEVCouldNotCompute otherwise. + const SCEV *Exact; + + /// Max - An expression indicating the least maximum backedge-taken + /// count of the loop that is known, or a SCEVCouldNotCompute. + const SCEV *Max; + + /*implicit*/ BackedgeTakenInfo(const SCEV *exact) : + Exact(exact), Max(exact) {} + + BackedgeTakenInfo(const SCEV *exact, const SCEV *max) : + Exact(exact), Max(max) {} + + /// hasAnyInfo - Test whether this BackedgeTakenInfo contains any + /// computed information, or whether it's all SCEVCouldNotCompute + /// values. + bool hasAnyInfo() const { + return !isa(Exact) || + !isa(Max); + } + }; + + /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for + /// this function as they are computed. + std::map BackedgeTakenCounts; + + /// ConstantEvolutionLoopExitValue - This map contains entries for all of + /// the PHI instructions that we attempt to compute constant evolutions for. + /// This allows us to avoid potentially expensive recomputation of these + /// properties. An instruction maps to null if we are unable to compute its + /// exit value. + std::map ConstantEvolutionLoopExitValue; + + /// ValuesAtScopes - This map contains entries for all the expressions + /// that we attempt to compute getSCEVAtScope information for, which can + /// be expensive in extreme cases. + std::map > ValuesAtScopes; + + /// LoopDispositions - Memoized computeLoopDisposition results. + std::map > LoopDispositions; + + /// computeLoopDisposition - Compute a LoopDisposition value. + LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); + + /// BlockDispositions - Memoized computeBlockDisposition results. + std::map > BlockDispositions; + + /// computeBlockDisposition - Compute a BlockDisposition value. + BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// UnsignedRanges - Memoized results from getUnsignedRange + DenseMap UnsignedRanges; + + /// SignedRanges - Memoized results from getSignedRange + DenseMap SignedRanges; + + /// setUnsignedRange - Set the memoized unsigned range for the given SCEV. + const ConstantRange &setUnsignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair::iterator, bool> Pair = + UnsignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + + /// setUnsignedRange - Set the memoized signed range for the given SCEV. + const ConstantRange &setSignedRange(const SCEV *S, + const ConstantRange &CR) { + std::pair::iterator, bool> Pair = + SignedRanges.insert(std::make_pair(S, CR)); + if (!Pair.second) + Pair.first->second = CR; + return Pair.first->second; + } + + /// createSCEV - We know that there is no SCEV for the specified value. + /// Analyze the expression. + const SCEV *createSCEV(Value *V); + + /// createNodeForPHI - Provide the special handling we need to analyze PHI + /// SCEVs. + const SCEV *createNodeForPHI(PHINode *PN); + + /// createNodeForGEP - Provide the special handling we need to analyze GEP + /// SCEVs. + const SCEV *createNodeForGEP(GEPOperator *GEP); + + /// computeSCEVAtScope - Implementation code for getSCEVAtScope; called + /// at most once for each SCEV+Loop pair. + /// + const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L); + + /// ForgetSymbolicValue - This looks up computed SCEV values for all + /// instructions that depend on the given instruction and removes them from + /// the ValueExprMap map if they reference SymName. This is used during PHI + /// resolution. + void ForgetSymbolicName(Instruction *I, const SCEV *SymName); + + /// getBECount - Subtract the end and start values and divide by the step, + /// rounding up, to get the number of times the backedge is executed. Return + /// CouldNotCompute if an intermediate computation overflows. + const SCEV *getBECount(const SCEV *Start, + const SCEV *End, + const SCEV *Step, + bool NoWrap); + + /// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given + /// loop, lazily computing new values if the loop hasn't been analyzed + /// yet. + const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L); + + /// ComputeBackedgeTakenCount - Compute the number of times the specified + /// loop will iterate. + BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L); + + /// ComputeBackedgeTakenCountFromExit - Compute the number of times the + /// backedge of the specified loop will execute if it exits via the + /// specified block. + BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L, + BasicBlock *ExitingBlock); + + /// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the + /// backedge of the specified loop will execute if its exit condition + /// were a conditional branch of ExitCond, TBB, and FBB. + BackedgeTakenInfo + ComputeBackedgeTakenCountFromExitCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of + /// times the backedge of the specified loop will execute if its exit + /// condition were a conditional branch of the ICmpInst ExitCond, TBB, + /// and FBB. + BackedgeTakenInfo + ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB); + + /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition + /// of 'icmp op load X, cst', try to see if we can compute the + /// backedge-taken count. + BackedgeTakenInfo + ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate p); + + /// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute + /// a constant number of times (the condition evolves only from constants), + /// try to evaluate a few iterations of the loop until we get the exit + /// condition gets a value of ExitWhen (true or false). If we cannot + /// evaluate the backedge-taken count of the loop, return CouldNotCompute. + const SCEV *ComputeBackedgeTakenCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen); + + /// HowFarToZero - Return the number of times a backedge comparing the + /// specified value to zero will execute. If not computable, return + /// CouldNotCompute. + BackedgeTakenInfo HowFarToZero(const SCEV *V, const Loop *L); + + /// HowFarToNonZero - Return the number of times a backedge checking the + /// specified value for nonzero will execute. If not computable, return + /// CouldNotCompute. + BackedgeTakenInfo HowFarToNonZero(const SCEV *V, const Loop *L); + + /// HowManyLessThans - Return the number of times a backedge containing the + /// specified less-than comparison will execute. If not computable, return + /// CouldNotCompute. isSigned specifies whether the less-than is signed. + BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned); + + /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB + /// (which may not be an immediate predecessor) which has exactly one + /// successor from which BB is reachable, or null if no such block is + /// found. + std::pair + getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB); + + /// isImpliedCond - Test whether the condition described by Pred, LHS, and + /// RHS is true whenever the given FoundCondValue value evaluates to true. + bool isImpliedCond(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + Value *FoundCondValue, + bool Inverse); + + /// isImpliedCondOperands - Test whether the condition described by Pred, + /// LHS, and RHS is true whenever the condition described by Pred, FoundLHS, + /// and FoundRHS is true. + bool isImpliedCondOperands(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS); + + /// isImpliedCondOperandsHelper - Test whether the condition described by + /// Pred, LHS, and RHS is true whenever the condition described by Pred, + /// FoundLHS, and FoundRHS is true. + bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS); + + /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is + /// in the header of its containing loop, we know the loop executes a + /// constant number of times, and the PHI node is just a recurrence + /// involving constants, fold it. + Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs, + const Loop *L); + + /// isKnownPredicateWithRanges - Test if the given expression is known to + /// satisfy the condition described by Pred and the known constant ranges + /// of LHS and RHS. + /// + bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// forgetMemoizedResults - Drop memoized information computed for S. + void forgetMemoizedResults(const SCEV *S); + + public: + static char ID; // Pass identification, replacement for typeid + ScalarEvolution(); + + LLVMContext &getContext() const { return F->getContext(); } + + /// isSCEVable - Test if values of the given type are analyzable within + /// the SCEV framework. This primarily includes integer types, and it + /// can optionally include pointer types if the ScalarEvolution class + /// has access to target-specific information. + bool isSCEVable(const Type *Ty) const; + + /// getTypeSizeInBits - Return the size in bits of the specified type, + /// for which isSCEVable must return true. + uint64_t getTypeSizeInBits(const Type *Ty) const; + + /// getEffectiveSCEVType - Return a type with the same bitwidth as + /// the given type and which represents how SCEV will treat the given + /// type, for which isSCEVable must return true. For pointer types, + /// this is the pointer-sized integer type. + const Type *getEffectiveSCEVType(const Type *Ty) const; + + /// getSCEV - Return a SCEV expression for the full generality of the + /// specified expression. + const SCEV *getSCEV(Value *V); + + const SCEV *getConstant(ConstantInt *V); + const SCEV *getConstant(const APInt& Val); + const SCEV *getConstant(const Type *Ty, uint64_t V, bool isSigned = false); + const SCEV *getTruncateExpr(const SCEV *Op, const Type *Ty); + const SCEV *getZeroExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getSignExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getAnyExtendExpr(const SCEV *Op, const Type *Ty); + const SCEV *getAddExpr(SmallVectorImpl &Ops, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getAddExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, + const SCEV *Op2, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(Op0); + Ops.push_back(Op1); + Ops.push_back(Op2); + return getAddExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getMulExpr(SmallVectorImpl &Ops, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getMulExpr(Ops, HasNUW, HasNSW); + } + const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, + const Loop *L, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddRecExpr(SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW = false, bool HasNSW = false); + const SCEV *getAddRecExpr(const SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW = false, bool HasNSW = false) { + SmallVector NewOp(Operands.begin(), Operands.end()); + return getAddRecExpr(NewOp, L, HasNUW, HasNSW); + } + const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMaxExpr(SmallVectorImpl &Operands); + const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMaxExpr(SmallVectorImpl &Operands); + const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUnknown(Value *V); + const SCEV *getCouldNotCompute(); + + /// getSizeOfExpr - Return an expression for sizeof on the given type. + /// + const SCEV *getSizeOfExpr(const Type *AllocTy); + + /// getAlignOfExpr - Return an expression for alignof on the given type. + /// + const SCEV *getAlignOfExpr(const Type *AllocTy); + + /// getOffsetOfExpr - Return an expression for offsetof on the given field. + /// + const SCEV *getOffsetOfExpr(const StructType *STy, unsigned FieldNo); + + /// getOffsetOfExpr - Return an expression for offsetof on the given field. + /// + const SCEV *getOffsetOfExpr(const Type *CTy, Constant *FieldNo); + + /// getNegativeSCEV - Return the SCEV object corresponding to -V. + /// + const SCEV *getNegativeSCEV(const SCEV *V); + + /// getNotSCEV - Return the SCEV object corresponding to ~V. + /// + const SCEV *getNotSCEV(const SCEV *V); + + /// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, + /// and thus the HasNUW and HasNSW bits apply to the resultant add, not + /// whether the sub would have overflowed. + const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS, + bool HasNUW = false, bool HasNSW = false); + + /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion + /// of the input value to the specified type. If the type must be + /// extended, it is zero extended. + const SCEV *getTruncateOrZeroExtend(const SCEV *V, const Type *Ty); + + /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion + /// of the input value to the specified type. If the type must be + /// extended, it is sign extended. + const SCEV *getTruncateOrSignExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is zero extended. The conversion must not be narrowing. + const SCEV *getNoopOrZeroExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is sign extended. The conversion must not be narrowing. + const SCEV *getNoopOrSignExtend(const SCEV *V, const Type *Ty); + + /// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of + /// the input value to the specified type. If the type must be extended, + /// it is extended with unspecified bits. The conversion must not be + /// narrowing. + const SCEV *getNoopOrAnyExtend(const SCEV *V, const Type *Ty); + + /// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the + /// input value to the specified type. The conversion must not be + /// widening. + const SCEV *getTruncateOrNoop(const SCEV *V, const Type *Ty); + + /// getUMaxFromMismatchedTypes - Promote the operands to the wider of + /// the types using zero-extension, and then perform a umax operation + /// with them. + const SCEV *getUMaxFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS); + + /// getUMinFromMismatchedTypes - Promote the operands to the wider of + /// the types using zero-extension, and then perform a umin operation + /// with them. + const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS); + + /// getSCEVAtScope - Return a SCEV expression for the specified value + /// at the specified scope in the program. The L value specifies a loop + /// nest to evaluate the expression at, where null is the top-level or a + /// specified loop is immediately inside of the loop. + /// + /// This method can be used to compute the exit value for a variable defined + /// in a loop by querying what the value will hold in the parent loop. + /// + /// In the case that a relevant loop exit value cannot be computed, the + /// original value V is returned. + const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L); + + /// getSCEVAtScope - This is a convenience function which does + /// getSCEVAtScope(getSCEV(V), L). + const SCEV *getSCEVAtScope(Value *V, const Loop *L); + + /// isLoopEntryGuardedByCond - Test whether entry to the loop is protected + /// by a conditional between LHS and RHS. This is used to help avoid max + /// expressions in loop trip counts, and to eliminate casts. + bool isLoopEntryGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is + /// protected by a conditional between LHS and RHS. This is used to + /// to eliminate casts. + bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// getBackedgeTakenCount - If the specified loop has a predictable + /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute + /// object. The backedge-taken count is the number of times the loop header + /// will be branched to from within the loop. This is one less than the + /// trip count of the loop, since it doesn't count the first iteration, + /// when the header is branched to from outside the loop. + /// + /// Note that it is not valid to call this method on a loop without a + /// loop-invariant backedge-taken count (see + /// hasLoopInvariantBackedgeTakenCount). + /// + const SCEV *getBackedgeTakenCount(const Loop *L); + + /// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except + /// return the least SCEV value that is known never to be less than the + /// actual backedge taken count. + const SCEV *getMaxBackedgeTakenCount(const Loop *L); + + /// hasLoopInvariantBackedgeTakenCount - Return true if the specified loop + /// has an analyzable loop-invariant backedge-taken count. + bool hasLoopInvariantBackedgeTakenCount(const Loop *L); + + /// forgetLoop - This method should be called by the client when it has + /// changed a loop in a way that may effect ScalarEvolution's ability to + /// compute a trip count, or if the loop is deleted. + void forgetLoop(const Loop *L); + + /// forgetValue - This method should be called by the client when it has + /// changed a value in a way that may effect its value, or which may + /// disconnect it from a def-use chain linking it to a loop. + void forgetValue(Value *V); + + /// GetMinTrailingZeros - Determine the minimum number of zero bits that S + /// is guaranteed to end in (at every loop iteration). It is, at the same + /// time, the minimum number of times S is divisible by 2. For example, + /// given {4,+,8} it returns 2. If S is guaranteed to be 0, it returns the + /// bitwidth of S. + uint32_t GetMinTrailingZeros(const SCEV *S); + + /// getUnsignedRange - Determine the unsigned range for a particular SCEV. + /// + ConstantRange getUnsignedRange(const SCEV *S); + + /// getSignedRange - Determine the signed range for a particular SCEV. + /// + ConstantRange getSignedRange(const SCEV *S); + + /// isKnownNegative - Test if the given expression is known to be negative. + /// + bool isKnownNegative(const SCEV *S); + + /// isKnownPositive - Test if the given expression is known to be positive. + /// + bool isKnownPositive(const SCEV *S); + + /// isKnownNonNegative - Test if the given expression is known to be + /// non-negative. + /// + bool isKnownNonNegative(const SCEV *S); + + /// isKnownNonPositive - Test if the given expression is known to be + /// non-positive. + /// + bool isKnownNonPositive(const SCEV *S); + + /// isKnownNonZero - Test if the given expression is known to be + /// non-zero. + /// + bool isKnownNonZero(const SCEV *S); + + /// isKnownPredicate - Test if the given expression is known to satisfy + /// the condition described by Pred, LHS, and RHS. + /// + bool isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); + + /// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with + /// predicate Pred. Return true iff any changes were made. If the + /// operands are provably equal or inequal, LHS and RHS are set to + /// the same value and Pred is set to either ICMP_EQ or ICMP_NE. + /// + bool SimplifyICmpOperands(ICmpInst::Predicate &Pred, + const SCEV *&LHS, + const SCEV *&RHS); + + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given loop. + LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L); + + /// isLoopInvariant - Return true if the value of the given SCEV is + /// unchanging in the specified loop. + bool isLoopInvariant(const SCEV *S, const Loop *L); + + /// hasComputableLoopEvolution - Return true if the given SCEV changes value + /// in a known way in the specified loop. This property being true implies + /// that the value is variant in the loop AND that we can emit an expression + /// to compute the value of the expression at any particular loop iteration. + bool hasComputableLoopEvolution(const SCEV *S, const Loop *L); + + /// getLoopDisposition - Return the "disposition" of the given SCEV with + /// respect to the given block. + BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB); + + /// dominates - Return true if elements that makes up the given SCEV + /// dominate the specified basic block. + bool dominates(const SCEV *S, const BasicBlock *BB); + + /// properlyDominates - Return true if elements that makes up the given SCEV + /// properly dominate the specified basic block. + bool properlyDominates(const SCEV *S, const BasicBlock *BB); + + /// hasOperand - Test whether the given SCEV has Op as a direct or + /// indirect operand. + bool hasOperand(const SCEV *S, const SCEV *Op) const; + + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void print(raw_ostream &OS, const Module* = 0) const; + + private: + FoldingSet UniqueSCEVs; + BumpPtrAllocator SCEVAllocator; + + /// FirstUnknown - The head of a linked list of all SCEVUnknown + /// values that have been allocated. This is used by releaseMemory + /// to locate them all and call their destructors. + SCEVUnknown *FirstUnknown; + }; +} + +#endif diff --git a/final/include/llvm/Analysis/ScalarEvolutionExpander.h b/final/include/llvm/Analysis/ScalarEvolutionExpander.h new file mode 100644 index 00000000000..39d378ed9be --- /dev/null +++ b/final/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -0,0 +1,215 @@ +//===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- 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 classes used to generate code from scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H + +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/TargetFolder.h" +#include "llvm/Support/ValueHandle.h" +#include + +namespace llvm { + /// SCEVExpander - This class uses information about analyze scalars to + /// rewrite expressions in canonical form. + /// + /// Clients should create an instance of this class when rewriting is needed, + /// and destroy it when finished to allow the release of the associated + /// memory. + class SCEVExpander : public SCEVVisitor { + ScalarEvolution &SE; + std::map, AssertingVH > + InsertedExpressions; + std::set > InsertedValues; + std::set > InsertedPostIncValues; + + /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + DenseMap RelevantLoops; + + /// PostIncLoops - Addrecs referring to any of the given loops are expanded + /// in post-inc mode. For example, expanding {1,+,1} in post-inc mode + /// returns the add instruction that adds one to the phi for {0,+,1}, + /// as opposed to a new phi starting at 1. This is only supported in + /// non-canonical mode. + PostIncLoopSet PostIncLoops; + + /// IVIncInsertPos - When this is non-null, addrecs expanded in the + /// loop it indicates should be inserted with increments at + /// IVIncInsertPos. + const Loop *IVIncInsertLoop; + + /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop, + /// insert the IV increment at this position. + Instruction *IVIncInsertPos; + + /// CanonicalMode - When true, expressions are expanded in "canonical" + /// form. In particular, addrecs are expanded as arithmetic based on + /// a canonical induction variable. When false, expression are expanded + /// in a more literal form. + bool CanonicalMode; + + typedef IRBuilder BuilderType; + BuilderType Builder; + + friend struct SCEVVisitor; + + public: + /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. + explicit SCEVExpander(ScalarEvolution &se) + : SE(se), IVIncInsertLoop(0), CanonicalMode(true), + Builder(se.getContext(), TargetFolder(se.TD)) {} + + /// clear - Erase the contents of the InsertedExpressions map so that users + /// trying to expand the same expression into multiple BasicBlocks or + /// different places within the same BasicBlock can do so. + void clear() { + InsertedExpressions.clear(); + InsertedValues.clear(); + InsertedPostIncValues.clear(); + } + + /// getOrInsertCanonicalInductionVariable - This method returns the + /// canonical induction variable of the specified type for the specified + /// loop (inserting one if there is none). A canonical induction variable + /// starts at zero and steps by one on each iteration. + PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, + const Type *Ty); + + /// expandCodeFor - Insert code to directly compute the specified SCEV + /// expression into the program. The inserted code is inserted into the + /// specified block. + Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I); + + /// setIVIncInsertPos - Set the current IV increment loop and position. + void setIVIncInsertPos(const Loop *L, Instruction *Pos) { + assert(!CanonicalMode && + "IV increment positions are not supported in CanonicalMode"); + IVIncInsertLoop = L; + IVIncInsertPos = Pos; + } + + /// setPostInc - Enable post-inc expansion for addrecs referring to the + /// given loops. Post-inc expansion is only supported in non-canonical + /// mode. + void setPostInc(const PostIncLoopSet &L) { + assert(!CanonicalMode && + "Post-inc expansion is not supported in CanonicalMode"); + PostIncLoops = L; + } + + /// clearPostInc - Disable all post-inc expansion. + void clearPostInc() { + PostIncLoops.clear(); + + // When we change the post-inc loop set, cached expansions may no + // longer be valid. + InsertedPostIncValues.clear(); + } + + /// disableCanonicalMode - Disable the behavior of expanding expressions in + /// canonical form rather than in a more literal form. Non-canonical mode + /// is useful for late optimization passes. + void disableCanonicalMode() { CanonicalMode = false; } + + /// clearInsertPoint - Clear the current insertion point. This is useful + /// if the instruction that had been serving as the insertion point may + /// have been deleted. + void clearInsertPoint() { + Builder.ClearInsertionPoint(); + } + + private: + LLVMContext &getContext() const { return SE.getContext(); } + + /// InsertBinop - Insert the specified binary operator, doing a small amount + /// of work to avoid inserting an obviously redundant operation. + Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); + + /// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP, + /// reusing an existing cast if a suitable one exists, moving an existing + /// cast if a suitable one exists but isn't in the right place, or + /// or creating a new one. + Value *ReuseOrCreateCast(Value *V, const Type *Ty, + Instruction::CastOps Op, + BasicBlock::iterator IP); + + /// InsertNoopCastOfTo - Insert a cast of V to the specified type, + /// which must be possible with a noop cast, doing what we can to + /// share the casts. + Value *InsertNoopCastOfTo(Value *V, const Type *Ty); + + /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP + /// instead of using ptrtoint+arithmetic+inttoptr. + Value *expandAddToGEP(const SCEV *const *op_begin, + const SCEV *const *op_end, + const PointerType *PTy, const Type *Ty, Value *V); + + Value *expand(const SCEV *S); + + /// expandCodeFor - Insert code to directly compute the specified SCEV + /// expression into the program. The inserted code is inserted into the + /// SCEVExpander's current insertion point. If a type is specified, the + /// result will be expanded to have that type, with a cast if necessary. + Value *expandCodeFor(const SCEV *SH, const Type *Ty = 0); + + /// isInsertedInstruction - Return true if the specified instruction was + /// inserted by the code rewriter. If so, the client should not modify the + /// instruction. + bool isInsertedInstruction(Instruction *I) const { + return InsertedValues.count(I) || InsertedPostIncValues.count(I); + } + + /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + const Loop *getRelevantLoop(const SCEV *); + + Value *visitConstant(const SCEVConstant *S) { + return S->getValue(); + } + + Value *visitTruncateExpr(const SCEVTruncateExpr *S); + + Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S); + + Value *visitSignExtendExpr(const SCEVSignExtendExpr *S); + + Value *visitAddExpr(const SCEVAddExpr *S); + + Value *visitMulExpr(const SCEVMulExpr *S); + + Value *visitUDivExpr(const SCEVUDivExpr *S); + + Value *visitAddRecExpr(const SCEVAddRecExpr *S); + + Value *visitSMaxExpr(const SCEVSMaxExpr *S); + + Value *visitUMaxExpr(const SCEVUMaxExpr *S); + + Value *visitUnknown(const SCEVUnknown *S) { + return S->getValue(); + } + + void rememberInstruction(Value *I); + + void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I); + + Value *expandAddRecExprLiterally(const SCEVAddRecExpr *); + PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, + const Loop *L, + const Type *ExpandTy, + const Type *IntTy); + }; +} + +#endif diff --git a/final/include/llvm/Analysis/ScalarEvolutionExpressions.h b/final/include/llvm/Analysis/ScalarEvolutionExpressions.h new file mode 100644 index 00000000000..db432c8173d --- /dev/null +++ b/final/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -0,0 +1,491 @@ +//===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- 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 classes used to represent and build scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H + +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + class ConstantInt; + class ConstantRange; + class DominatorTree; + + enum SCEVTypes { + // These should be ordered in terms of increasing complexity to make the + // folders simpler. + scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, + scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, + scUnknown, scCouldNotCompute + }; + + //===--------------------------------------------------------------------===// + /// SCEVConstant - This class represents a constant integer value. + /// + class SCEVConstant : public SCEV { + friend class ScalarEvolution; + + ConstantInt *V; + SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) : + SCEV(ID, scConstant), V(v) {} + public: + ConstantInt *getValue() const { return V; } + + const Type *getType() const { return V->getType(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVConstant *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scConstant; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVCastExpr - This is the base class for unary cast operator classes. + /// + class SCEVCastExpr : public SCEV { + protected: + const SCEV *Op; + const Type *Ty; + + SCEVCastExpr(const FoldingSetNodeIDRef ID, + unsigned SCEVTy, const SCEV *op, const Type *ty); + + public: + const SCEV *getOperand() const { return Op; } + const Type *getType() const { return Ty; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCastExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate || + S->getSCEVType() == scZeroExtend || + S->getSCEVType() == scSignExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVTruncateExpr - This class represents a truncation of an integer value + /// to a smaller integer value. + /// + class SCEVTruncateExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVTruncateExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVTruncateExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVZeroExtendExpr - This class represents a zero extension of a small + /// integer value to a larger integer value. + /// + class SCEVZeroExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scZeroExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVSignExtendExpr - This class represents a sign extension of a small + /// integer value to a larger integer value. + /// + class SCEVSignExtendExpr : public SCEVCastExpr { + friend class ScalarEvolution; + + SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty); + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSignExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSignExtend; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVNAryExpr - This node is a base class providing common + /// functionality for n'ary operators. + /// + class SCEVNAryExpr : public SCEV { + protected: + // Since SCEVs are immutable, ScalarEvolution allocates operand + // arrays with its SCEVAllocator, so this class just needs a simple + // pointer rather than a more elaborate vector-like data structure. + // This also avoids the need for a non-trivial destructor. + const SCEV *const *Operands; + size_t NumOperands; + + SCEVNAryExpr(const FoldingSetNodeIDRef ID, + enum SCEVTypes T, const SCEV *const *O, size_t N) + : SCEV(ID, T), Operands(O), NumOperands(N) {} + + public: + size_t getNumOperands() const { return NumOperands; } + const SCEV *getOperand(unsigned i) const { + assert(i < NumOperands && "Operand index out of range!"); + return Operands[i]; + } + + typedef const SCEV *const *op_iterator; + op_iterator op_begin() const { return Operands; } + op_iterator op_end() const { return Operands + NumOperands; } + + const Type *getType() const { return getOperand(0)->getType(); } + + bool hasNoUnsignedWrap() const { return SubclassData & (1 << 0); } + void setHasNoUnsignedWrap(bool B) { + SubclassData = (SubclassData & ~(1 << 0)) | (B << 0); + } + bool hasNoSignedWrap() const { return SubclassData & (1 << 1); } + void setHasNoSignedWrap(bool B) { + SubclassData = (SubclassData & ~(1 << 1)) | (B << 1); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVNAryExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || + S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || + S->getSCEVType() == scUMaxExpr || + S->getSCEVType() == scAddRecExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVCommutativeExpr - This node is the base class for n'ary commutative + /// operators. + /// + class SCEVCommutativeExpr : public SCEVNAryExpr { + protected: + SCEVCommutativeExpr(const FoldingSetNodeIDRef ID, + enum SCEVTypes T, const SCEV *const *O, size_t N) + : SCEVNAryExpr(ID, T, O, N) {} + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCommutativeExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || + S->getSCEVType() == scMulExpr || + S->getSCEVType() == scSMaxExpr || + S->getSCEVType() == scUMaxExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddExpr - This node represents an addition of some number of SCEVs. + /// + class SCEVAddExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVAddExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scAddExpr, O, N) { + } + + public: + const Type *getType() const { + // Use the type of the last operand, which is likely to be a pointer + // type, if there is one. This doesn't usually matter, but it can help + // reduce casts when the expressions are expanded. + return getOperand(getNumOperands() - 1)->getType(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVMulExpr - This node represents multiplication of some number of SCEVs. + /// + class SCEVMulExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVMulExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scMulExpr, O, N) { + } + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVMulExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scMulExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVUDivExpr - This class represents a binary unsigned division operation. + /// + class SCEVUDivExpr : public SCEV { + friend class ScalarEvolution; + + const SCEV *LHS; + const SCEV *RHS; + SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs) + : SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {} + + public: + const SCEV *getLHS() const { return LHS; } + const SCEV *getRHS() const { return RHS; } + + const Type *getType() const { + // In most cases the types of LHS and RHS will be the same, but in some + // crazy cases one or the other may be a pointer. ScalarEvolution doesn't + // depend on the type for correctness, but handling types carefully can + // avoid extra casts in the SCEVExpander. The LHS is more likely to be + // a pointer type than the RHS, so use the RHS' type here. + return getRHS()->getType(); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUDivExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUDivExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip + /// count of the specified loop. This is the primary focus of the + /// ScalarEvolution framework; all the other SCEV subclasses are mostly just + /// supporting infrastructure to allow SCEVAddRecExpr expressions to be + /// created and analyzed. + /// + /// All operands of an AddRec are required to be loop invariant. + /// + class SCEVAddRecExpr : public SCEVNAryExpr { + friend class ScalarEvolution; + + const Loop *L; + + SCEVAddRecExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N, const Loop *l) + : SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {} + + public: + const SCEV *getStart() const { return Operands[0]; } + const Loop *getLoop() const { return L; } + + /// getStepRecurrence - This method constructs and returns the recurrence + /// indicating how much this expression steps by. If this is a polynomial + /// of degree N, it returns a chrec of degree N-1. + const SCEV *getStepRecurrence(ScalarEvolution &SE) const { + if (isAffine()) return getOperand(1); + return SE.getAddRecExpr(SmallVector(op_begin()+1, + op_end()), + getLoop()); + } + + /// isAffine - Return true if this is an affine AddRec (i.e., it represents + /// an expressions A+B*x where A and B are loop invariant values. + bool isAffine() const { + // We know that the start value is invariant. This expression is thus + // affine iff the step is also invariant. + return getNumOperands() == 2; + } + + /// isQuadratic - Return true if this is an quadratic AddRec (i.e., it + /// represents an expressions A+B*x+C*x^2 where A, B and C are loop + /// invariant values. This corresponds to an addrec of the form {L,+,M,+,N} + bool isQuadratic() const { + return getNumOperands() == 3; + } + + /// evaluateAtIteration - Return the value of this chain of recurrences at + /// the specified iteration number. + const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const; + + /// getNumIterationsInRange - Return the number of iterations of this loop + /// that produce values in the specified constant range. Another way of + /// looking at this is that it returns the first iteration number where the + /// value is not in the condition, thus computing the exit count. If the + /// iteration count can't be computed, an instance of SCEVCouldNotCompute is + /// returned. + const SCEV *getNumIterationsInRange(ConstantRange Range, + ScalarEvolution &SE) const; + + /// getPostIncExpr - Return an expression representing the value of + /// this expression one iteration of the loop ahead. + const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const { + return cast(SE.getAddExpr(this, getStepRecurrence(SE))); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddRecExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddRecExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVSMaxExpr - This class represents a signed maximum selection. + /// + class SCEVSMaxExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVSMaxExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scSMaxExpr, O, N) { + // Max never overflows. + setHasNoUnsignedWrap(true); + setHasNoSignedWrap(true); + } + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSMaxExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSMaxExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVUMaxExpr - This class represents an unsigned maximum selection. + /// + class SCEVUMaxExpr : public SCEVCommutativeExpr { + friend class ScalarEvolution; + + SCEVUMaxExpr(const FoldingSetNodeIDRef ID, + const SCEV *const *O, size_t N) + : SCEVCommutativeExpr(ID, scUMaxExpr, O, N) { + // Max never overflows. + setHasNoUnsignedWrap(true); + setHasNoSignedWrap(true); + } + + public: + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUMaxExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUMaxExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV + /// value, and only represent it as its LLVM Value. This is the "bottom" + /// value for the analysis. + /// + class SCEVUnknown : public SCEV, private CallbackVH { + friend class ScalarEvolution; + + // Implement CallbackVH. + virtual void deleted(); + virtual void allUsesReplacedWith(Value *New); + + /// SE - The parent ScalarEvolution value. This is used to update + /// the parent's maps when the value associated with a SCEVUnknown + /// is deleted or RAUW'd. + ScalarEvolution *SE; + + /// Next - The next pointer in the linked list of all + /// SCEVUnknown instances owned by a ScalarEvolution. + SCEVUnknown *Next; + + SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V, + ScalarEvolution *se, SCEVUnknown *next) : + SCEV(ID, scUnknown), CallbackVH(V), SE(se), Next(next) {} + + public: + Value *getValue() const { return getValPtr(); } + + /// isSizeOf, isAlignOf, isOffsetOf - Test whether this is a special + /// constant representing a type size, alignment, or field offset in + /// a target-independent manner, and hasn't happened to have been + /// folded with other operations into something unrecognizable. This + /// is mainly only useful for pretty-printing and other situations + /// where it isn't absolutely required for these to succeed. + bool isSizeOf(const Type *&AllocTy) const; + bool isAlignOf(const Type *&AllocTy) const; + bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const; + + const Type *getType() const { return getValPtr()->getType(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUnknown *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUnknown; + } + }; + + /// SCEVVisitor - This class defines a simple visitor class that may be used + /// for various SCEV analysis purposes. + template + struct SCEVVisitor { + RetVal visit(const SCEV *S) { + switch (S->getSCEVType()) { + case scConstant: + return ((SC*)this)->visitConstant((const SCEVConstant*)S); + case scTruncate: + return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S); + case scZeroExtend: + return ((SC*)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr*)S); + case scSignExtend: + return ((SC*)this)->visitSignExtendExpr((const SCEVSignExtendExpr*)S); + case scAddExpr: + return ((SC*)this)->visitAddExpr((const SCEVAddExpr*)S); + case scMulExpr: + return ((SC*)this)->visitMulExpr((const SCEVMulExpr*)S); + case scUDivExpr: + return ((SC*)this)->visitUDivExpr((const SCEVUDivExpr*)S); + case scAddRecExpr: + return ((SC*)this)->visitAddRecExpr((const SCEVAddRecExpr*)S); + case scSMaxExpr: + return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S); + case scUMaxExpr: + return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S); + case scUnknown: + return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); + case scCouldNotCompute: + return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S); + default: + llvm_unreachable("Unknown SCEV type!"); + } + } + + RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) { + llvm_unreachable("Invalid use of SCEVCouldNotCompute!"); + return RetVal(); + } + }; +} + +#endif diff --git a/final/include/llvm/Analysis/ScalarEvolutionNormalization.h b/final/include/llvm/Analysis/ScalarEvolutionNormalization.h new file mode 100644 index 00000000000..342e5937891 --- /dev/null +++ b/final/include/llvm/Analysis/ScalarEvolutionNormalization.h @@ -0,0 +1,78 @@ +//===- llvm/Analysis/ScalarEvolutionNormalization.h - See below -*- 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 utilities for working with "normalized" ScalarEvolution +// expressions. +// +// The following example illustrates post-increment uses and how normalized +// expressions help. +// +// for (i=0; i!=n; ++i) { +// ... +// } +// use(i); +// +// While the expression for most uses of i inside the loop is {0,+,1}<%L>, the +// expression for the use of i outside the loop is {1,+,1}<%L>, since i is +// incremented at the end of the loop body. This is inconveient, since it +// suggests that we need two different induction variables, one that starts +// at 0 and one that starts at 1. We'd prefer to be able to think of these as +// the same induction variable, with uses inside the loop using the +// "pre-incremented" value, and uses after the loop using the +// "post-incremented" value. +// +// Expressions for post-incremented uses are represented as an expression +// paired with a set of loops for which the expression is in "post-increment" +// mode (there may be multiple loops). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_NORMALIZATION_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_NORMALIZATION_H + +#include "llvm/ADT/SmallPtrSet.h" + +namespace llvm { + +class Instruction; +class DominatorTree; +class Loop; +class ScalarEvolution; +class SCEV; +class Value; + +/// TransformKind - Different types of transformations that +/// TransformForPostIncUse can do. +enum TransformKind { + /// Normalize - Normalize according to the given loops. + Normalize, + /// NormalizeAutodetect - Detect post-inc opportunities on new expressions, + /// update the given loop set, and normalize. + NormalizeAutodetect, + /// Denormalize - Perform the inverse transform on the expression with the + /// given loop set. + Denormalize +}; + +/// PostIncLoopSet - A set of loops. +typedef SmallPtrSet PostIncLoopSet; + +/// TransformForPostIncUse - Transform the given expression according to the +/// given transformation kind. +const SCEV *TransformForPostIncUse(TransformKind Kind, + const SCEV *S, + Instruction *User, + Value *OperandValToReplace, + PostIncLoopSet &Loops, + ScalarEvolution &SE, + DominatorTree &DT); + +} + +#endif diff --git a/final/include/llvm/Analysis/SparsePropagation.h b/final/include/llvm/Analysis/SparsePropagation.h new file mode 100644 index 00000000000..c3c2f4b0668 --- /dev/null +++ b/final/include/llvm/Analysis/SparsePropagation.h @@ -0,0 +1,206 @@ +//===- SparsePropagation.h - Sparse Conditional Property Propagation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an abstract sparse conditional propagation algorithm, +// modeled after SCCP, but with a customizable lattice function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SPARSE_PROPAGATION_H +#define LLVM_ANALYSIS_SPARSE_PROPAGATION_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +#include + +namespace llvm { + class Value; + class Constant; + class Argument; + class Instruction; + class PHINode; + class TerminatorInst; + class BasicBlock; + class Function; + class SparseSolver; + class raw_ostream; + + template class SmallVectorImpl; + +/// AbstractLatticeFunction - This class is implemented by the dataflow instance +/// to specify what the lattice values are and how they handle merges etc. +/// This gives the client the power to compute lattice values from instructions, +/// constants, etc. The requirement is that lattice values must all fit into +/// a void*. If a void* is not sufficient, the implementation should use this +/// pointer to be a pointer into a uniquing set or something. +/// +class AbstractLatticeFunction { +public: + typedef void *LatticeVal; +private: + LatticeVal UndefVal, OverdefinedVal, UntrackedVal; +public: + AbstractLatticeFunction(LatticeVal undefVal, LatticeVal overdefinedVal, + LatticeVal untrackedVal) { + UndefVal = undefVal; + OverdefinedVal = overdefinedVal; + UntrackedVal = untrackedVal; + } + virtual ~AbstractLatticeFunction(); + + LatticeVal getUndefVal() const { return UndefVal; } + LatticeVal getOverdefinedVal() const { return OverdefinedVal; } + LatticeVal getUntrackedVal() const { return UntrackedVal; } + + /// IsUntrackedValue - If the specified Value is something that is obviously + /// uninteresting to the analysis (and would always return UntrackedVal), + /// this function can return true to avoid pointless work. + virtual bool IsUntrackedValue(Value *V) { + return false; + } + + /// ComputeConstant - Given a constant value, compute and return a lattice + /// value corresponding to the specified constant. + virtual LatticeVal ComputeConstant(Constant *C) { + return getOverdefinedVal(); // always safe + } + + /// IsSpecialCasedPHI - Given a PHI node, determine whether this PHI node is + /// one that the we want to handle through ComputeInstructionState. + virtual bool IsSpecialCasedPHI(PHINode *PN) { + return false; + } + + /// GetConstant - If the specified lattice value is representable as an LLVM + /// constant value, return it. Otherwise return null. The returned value + /// must be in the same LLVM type as Val. + virtual Constant *GetConstant(LatticeVal LV, Value *Val, SparseSolver &SS) { + return 0; + } + + /// ComputeArgument - Given a formal argument value, compute and return a + /// lattice value corresponding to the specified argument. + virtual LatticeVal ComputeArgument(Argument *I) { + return getOverdefinedVal(); // always safe + } + + /// MergeValues - Compute and return the merge of the two specified lattice + /// values. Merging should only move one direction down the lattice to + /// guarantee convergence (toward overdefined). + virtual LatticeVal MergeValues(LatticeVal X, LatticeVal Y) { + return getOverdefinedVal(); // always safe, never useful. + } + + /// ComputeInstructionState - Given an instruction and a vector of its operand + /// values, compute the result value of the instruction. + virtual LatticeVal ComputeInstructionState(Instruction &I, SparseSolver &SS) { + return getOverdefinedVal(); // always safe, never useful. + } + + /// PrintValue - Render the specified lattice value to the specified stream. + virtual void PrintValue(LatticeVal V, raw_ostream &OS); +}; + + +/// SparseSolver - This class is a general purpose solver for Sparse Conditional +/// Propagation with a programmable lattice function. +/// +class SparseSolver { + typedef AbstractLatticeFunction::LatticeVal LatticeVal; + + /// LatticeFunc - This is the object that knows the lattice and how to do + /// compute transfer functions. + AbstractLatticeFunction *LatticeFunc; + + DenseMap ValueState; // The state each value is in. + SmallPtrSet BBExecutable; // The bbs that are executable. + + std::vector InstWorkList; // Worklist of insts to process. + + std::vector BBWorkList; // The BasicBlock work list + + /// KnownFeasibleEdges - Entries in this set are edges which have already had + /// PHI nodes retriggered. + typedef std::pair Edge; + std::set KnownFeasibleEdges; + + SparseSolver(const SparseSolver&); // DO NOT IMPLEMENT + void operator=(const SparseSolver&); // DO NOT IMPLEMENT +public: + explicit SparseSolver(AbstractLatticeFunction *Lattice) + : LatticeFunc(Lattice) {} + ~SparseSolver() { + delete LatticeFunc; + } + + /// Solve - Solve for constants and executable blocks. + /// + void Solve(Function &F); + + void Print(Function &F, raw_ostream &OS) const; + + /// getLatticeState - Return the LatticeVal object that corresponds to the + /// value. If an value is not in the map, it is returned as untracked, + /// unlike the getOrInitValueState method. + LatticeVal getLatticeState(Value *V) const { + DenseMap::const_iterator I = ValueState.find(V); + return I != ValueState.end() ? I->second : LatticeFunc->getUntrackedVal(); + } + + /// getOrInitValueState - Return the LatticeVal object that corresponds to the + /// value, initializing the value's state if it hasn't been entered into the + /// map yet. This function is necessary because not all values should start + /// out in the underdefined state... Arguments should be overdefined, and + /// constants should be marked as constants. + /// + LatticeVal getOrInitValueState(Value *V); + + /// isEdgeFeasible - Return true if the control flow edge from the 'From' + /// basic block to the 'To' basic block is currently feasible. If + /// AggressiveUndef is true, then this treats values with unknown lattice + /// values as undefined. This is generally only useful when solving the + /// lattice, not when querying it. + bool isEdgeFeasible(BasicBlock *From, BasicBlock *To, + bool AggressiveUndef = false); + + /// isBlockExecutable - Return true if there are any known feasible + /// edges into the basic block. This is generally only useful when + /// querying the lattice. + bool isBlockExecutable(BasicBlock *BB) const { + return BBExecutable.count(BB); + } + +private: + /// UpdateState - When the state for some instruction is potentially updated, + /// this function notices and adds I to the worklist if needed. + void UpdateState(Instruction &Inst, LatticeVal V); + + /// MarkBlockExecutable - This method can be used by clients to mark all of + /// the blocks that are known to be intrinsically live in the processed unit. + void MarkBlockExecutable(BasicBlock *BB); + + /// markEdgeExecutable - Mark a basic block as executable, adding it to the BB + /// work list if it is not already executable. + void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest); + + /// getFeasibleSuccessors - Return a vector of booleans to indicate which + /// successors are reachable from a given terminator instruction. + void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl &Succs, + bool AggressiveUndef); + + void visitInst(Instruction &I); + void visitPHINode(PHINode &I); + void visitTerminatorInst(TerminatorInst &TI); + +}; + +} // end namespace llvm + +#endif // LLVM_ANALYSIS_SPARSE_PROPAGATION_H diff --git a/final/include/llvm/Analysis/Trace.h b/final/include/llvm/Analysis/Trace.h new file mode 100644 index 00000000000..99651e192d3 --- /dev/null +++ b/final/include/llvm/Analysis/Trace.h @@ -0,0 +1,119 @@ +//===- llvm/Analysis/Trace.h - Represent one trace of LLVM code -*- 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 a single trace of LLVM basic blocks. A trace is a +// single entry, multiple exit, region of code that is often hot. Trace-based +// optimizations treat traces almost like they are a large, strange, basic +// block: because the trace path is assumed to be hot, optimizations for the +// fall-through path are made at the expense of the non-fall-through paths. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TRACE_H +#define LLVM_ANALYSIS_TRACE_H + +#include +#include + +namespace llvm { + class BasicBlock; + class Function; + class Module; + class raw_ostream; + +class Trace { + typedef std::vector BasicBlockListType; + BasicBlockListType BasicBlocks; + +public: + /// Trace ctor - Make a new trace from a vector of basic blocks, + /// residing in the function which is the parent of the first + /// basic block in the vector. + /// + Trace(const std::vector &vBB) : BasicBlocks (vBB) {} + + /// getEntryBasicBlock - Return the entry basic block (first block) + /// of the trace. + /// + BasicBlock *getEntryBasicBlock () const { return BasicBlocks[0]; } + + /// operator[]/getBlock - Return basic block N in the trace. + /// + BasicBlock *operator[](unsigned i) const { return BasicBlocks[i]; } + BasicBlock *getBlock(unsigned i) const { return BasicBlocks[i]; } + + /// getFunction - Return this trace's parent function. + /// + Function *getFunction () const; + + /// getModule - Return this Module that contains this trace's parent + /// function. + /// + Module *getModule () const; + + /// getBlockIndex - Return the index of the specified basic block in the + /// trace, or -1 if it is not in the trace. + int getBlockIndex(const BasicBlock *X) const { + for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i) + if (BasicBlocks[i] == X) + return i; + return -1; + } + + /// contains - Returns true if this trace contains the given basic + /// block. + /// + bool contains(const BasicBlock *X) const { + return getBlockIndex(X) != -1; + } + + /// Returns true if B1 occurs before B2 in the trace, or if it is the same + /// block as B2.. Both blocks must be in the trace. + /// + bool dominates(const BasicBlock *B1, const BasicBlock *B2) const { + int B1Idx = getBlockIndex(B1), B2Idx = getBlockIndex(B2); + assert(B1Idx != -1 && B2Idx != -1 && "Block is not in the trace!"); + return B1Idx <= B2Idx; + } + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + + iterator erase(iterator q) { return BasicBlocks.erase (q); } + iterator erase(iterator q1, iterator q2) { return BasicBlocks.erase (q1, q2); } + + /// print - Write trace to output stream. + /// + void print(raw_ostream &O) const; + + /// dump - Debugger convenience method; writes trace to standard error + /// output stream. + /// + void dump() const; +}; + +} // end namespace llvm + +#endif // TRACE_H diff --git a/final/include/llvm/Analysis/ValueTracking.h b/final/include/llvm/Analysis/ValueTracking.h new file mode 100644 index 00000000000..6df1693c78e --- /dev/null +++ b/final/include/llvm/Analysis/ValueTracking.h @@ -0,0 +1,163 @@ +//===- llvm/Analysis/ValueTracking.h - Walk computations --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help analyze properties that chains of +// computations have. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VALUETRACKING_H +#define LLVM_ANALYSIS_VALUETRACKING_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + template class SmallVectorImpl; + class Value; + class Instruction; + class APInt; + class TargetData; + + /// ComputeMaskedBits - Determine which of the bits specified in Mask are + /// known to be either zero or one and return them in the KnownZero/KnownOne + /// bit sets. This code only analyzes bits in Mask, in order to short-circuit + /// processing. + /// + /// This function is defined on values with integer type, values with pointer + /// type (but only if TD is non-null), and vectors of integers. In the case + /// where V is a vector, the mask, known zero, and known one values are the + /// same width as the vector element, and the bit is set only if it is true + /// for all of the elements in the vector. + void ComputeMaskedBits(Value *V, const APInt &Mask, APInt &KnownZero, + APInt &KnownOne, const TargetData *TD = 0, + unsigned Depth = 0); + + /// ComputeSignBit - Determine whether the sign bit is known to be zero or + /// one. Convenience wrapper around ComputeMaskedBits. + void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, + const TargetData *TD = 0, unsigned Depth = 0); + + /// isPowerOfTwo - Return true if the given value is known to have exactly one + /// bit set when defined. For vectors return true if every element is known to + /// be a power of two when defined. Supports values with integer or pointer + /// type and vectors of integers. + bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + + /// isKnownNonZero - Return true if the given value is known to be non-zero + /// when defined. For vectors return true if every element is known to be + /// non-zero when defined. Supports values with integer or pointer type and + /// vectors of integers. + bool isKnownNonZero(Value *V, const TargetData *TD = 0, unsigned Depth = 0); + + /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use + /// this predicate to simplify operations downstream. Mask is known to be + /// zero for bits that V cannot have. + /// + /// This function is defined on values with integer type, values with pointer + /// type (but only if TD is non-null), and vectors of integers. In the case + /// where V is a vector, the mask, known zero, and known one values are the + /// same width as the vector element, and the bit is set only if it is true + /// for all of the elements in the vector. + bool MaskedValueIsZero(Value *V, const APInt &Mask, + const TargetData *TD = 0, unsigned Depth = 0); + + + /// ComputeNumSignBits - Return the number of times the sign bit of the + /// register is replicated into the other bits. We know that at least 1 bit + /// is always equal to the sign bit (itself), but other cases can give us + /// information. For example, immediately after an "ashr X, 2", we know that + /// the top 3 bits are all equal to each other, so we return 3. + /// + /// 'Op' must have a scalar integer type. + /// + unsigned ComputeNumSignBits(Value *Op, const TargetData *TD = 0, + unsigned Depth = 0); + + /// ComputeMultiple - This function computes the integer multiple of Base that + /// equals V. If successful, it returns true and returns the multiple in + /// Multiple. If unsuccessful, it returns false. Also, if V can be + /// simplified to an integer, then the simplified V is returned in Val. Look + /// through sext only if LookThroughSExt=true. + bool ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, + bool LookThroughSExt = false, + unsigned Depth = 0); + + /// CannotBeNegativeZero - Return true if we can prove that the specified FP + /// value is never equal to -0.0. + /// + bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + + /// isBytewiseValue - If the specified value can be set by repeating the same + /// byte in memory, return the i8 value that it is represented with. This is + /// true for all i8 values obviously, but is also true for i32 0, i32 -1, + /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated + /// byte store (e.g. i16 0x1234), return null. + Value *isBytewiseValue(Value *V); + + /// FindInsertedValue - Given an aggregrate and an sequence of indices, see if + /// the scalar value indexed is already around as a register, for example if + /// it were inserted directly into the aggregrate. + /// + /// If InsertBefore is not null, this function will duplicate (modified) + /// insertvalues when a part of a nested struct is extracted. + Value *FindInsertedValue(Value *V, + const unsigned *idx_begin, + const unsigned *idx_end, + Instruction *InsertBefore = 0); + + /// This is a convenience wrapper for finding values indexed by a single index + /// only. + inline Value *FindInsertedValue(Value *V, const unsigned Idx, + Instruction *InsertBefore = 0) { + const unsigned Idxs[1] = { Idx }; + return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); + } + + /// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if + /// it can be expressed as a base pointer plus a constant offset. Return the + /// base and offset to the caller. + Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const TargetData &TD); + static inline const Value * + GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, + const TargetData &TD) { + return GetPointerBaseWithConstantOffset(const_cast(Ptr), Offset,TD); + } + + /// GetConstantStringInfo - This function computes the length of a + /// null-terminated C string pointed to by V. If successful, it returns true + /// and returns the string in Str. If unsuccessful, it returns false. If + /// StopAtNul is set to true (the default), the returned string is truncated + /// by a nul character in the global. If StopAtNul is false, the nul + /// character is included in the result string. + bool GetConstantStringInfo(const Value *V, std::string &Str, + uint64_t Offset = 0, + bool StopAtNul = true); + + /// GetStringLength - If we can compute the length of the string pointed to by + /// the specified pointer, return 'len+1'. If we can't, return 0. + uint64_t GetStringLength(Value *V); + + /// GetUnderlyingObject - This method strips off any GEP address adjustments + /// and pointer casts from the specified value, returning the original object + /// being addressed. Note that the returned value has pointer type if the + /// specified value does. If the MaxLookup value is non-zero, it limits the + /// number of instructions to be stripped off. + Value *GetUnderlyingObject(Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6); + static inline const Value * + GetUnderlyingObject(const Value *V, const TargetData *TD = 0, + unsigned MaxLookup = 6) { + return GetUnderlyingObject(const_cast(V), TD, MaxLookup); + } + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Analysis/Verifier.h b/final/include/llvm/Analysis/Verifier.h new file mode 100644 index 00000000000..ce8aeef0764 --- /dev/null +++ b/final/include/llvm/Analysis/Verifier.h @@ -0,0 +1,75 @@ +//===-- llvm/Analysis/Verifier.h - LLVM IR Verifier -------------*- 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 function verifier interface, that can be used for some +// sanity checking of input to the system, and for checking that transformations +// haven't done something bad. +// +// Note that this does not provide full 'java style' security and verifications, +// instead it just tries to ensure that code is well formed. +// +// To see what specifically is checked, look at the top of Verifier.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VERIFIER_H +#define LLVM_ANALYSIS_VERIFIER_H + +#include + +namespace llvm { + +class FunctionPass; +class Module; +class Function; + +/// @brief An enumeration to specify the action to be taken if errors found. +/// +/// This enumeration is used in the functions below to indicate what should +/// happen if the verifier finds errors. Each of the functions that uses +/// this enumeration as an argument provides a default value for it. The +/// actions are listed below. +enum VerifierFailureAction { + AbortProcessAction, ///< verifyModule will print to stderr and abort() + PrintMessageAction, ///< verifyModule will print to stderr and return true + ReturnStatusAction ///< verifyModule will just return true +}; + +/// @brief Create a verifier pass. +/// +/// Check a module or function for validity. When the pass is used, the +/// action indicated by the \p action argument will be used if errors are +/// found. +FunctionPass *createVerifierPass( + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +/// @brief Check a module for errors. +/// +/// If there are no errors, the function returns false. If an error is found, +/// the action taken depends on the \p action parameter. +/// This should only be used for debugging, because it plays games with +/// PassManagers and stuff. + +bool verifyModule( + const Module &M, ///< The module to be verified + VerifierFailureAction action = AbortProcessAction, ///< Action to take + std::string *ErrorInfo = 0 ///< Information about failures. +); + +// verifyFunction - Check a function for errors, useful for use when debugging a +// pass. +bool verifyFunction( + const Function &F, ///< The function to be verified + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Argument.h b/final/include/llvm/Argument.h new file mode 100644 index 00000000000..71c001fbe18 --- /dev/null +++ b/final/include/llvm/Argument.h @@ -0,0 +1,88 @@ +//===-- llvm/Argument.h - Definition of the Argument class ------*- 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 Argument class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ARGUMENT_H +#define LLVM_ARGUMENT_H + +#include "llvm/Value.h" +#include "llvm/Attributes.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/Twine.h" + +namespace llvm { + +template + class SymbolTableListTraits; + +/// A class to represent an incoming formal argument to a Function. An argument +/// is a very simple Value. It is essentially a named (optional) type. When used +/// in the body of a function, it represents the value of the actual argument +/// the function was called with. +/// @brief LLVM Argument representation +class Argument : public Value, public ilist_node { + Function *Parent; + + friend class SymbolTableListTraits; + void setParent(Function *parent); + +public: + /// Argument ctor - If Function argument is specified, this argument is + /// inserted at the end of the argument list for the function. + /// + explicit Argument(const Type *Ty, const Twine &Name = "", Function *F = 0); + + inline const Function *getParent() const { return Parent; } + inline Function *getParent() { return Parent; } + + /// getArgNo - Return the index of this formal argument in its containing + /// function. For example in "void foo(int a, float b)" a is 0 and b is 1. + unsigned getArgNo() const; + + /// hasByValAttr - Return true if this argument has the byval attribute on it + /// in its containing function. + bool hasByValAttr() const; + + /// hasNestAttr - Return true if this argument has the nest attribute on + /// it in its containing function. + bool hasNestAttr() const; + + /// hasNoAliasAttr - Return true if this argument has the noalias attribute on + /// it in its containing function. + bool hasNoAliasAttr() const; + + /// hasNoCaptureAttr - Return true if this argument has the nocapture + /// attribute on it in its containing function. + bool hasNoCaptureAttr() const; + + /// hasSRetAttr - Return true if this argument has the sret attribute on it in + /// its containing function. + bool hasStructRetAttr() const; + + /// addAttr - Add a Attribute to an argument + void addAttr(Attributes); + + /// removeAttr - Remove a Attribute from an argument + void removeAttr(Attributes); + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const Argument *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ArgumentVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Assembly/AssemblyAnnotationWriter.h b/final/include/llvm/Assembly/AssemblyAnnotationWriter.h new file mode 100644 index 00000000000..3a65f97a5b5 --- /dev/null +++ b/final/include/llvm/Assembly/AssemblyAnnotationWriter.h @@ -0,0 +1,63 @@ +//===-- AssemblyAnnotationWriter.h - Annotation .ll files -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Clients of the assembly writer can use this interface to add their own +// special-purpose annotations to LLVM assembly language printouts. Note that +// the assembly parser won't be able to parse these, in general, so +// implementations are advised to print stuff as LLVM comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H +#define LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H + +namespace llvm { + +class Function; +class BasicBlock; +class Instruction; +class raw_ostream; +class formatted_raw_ostream; + +class AssemblyAnnotationWriter { +public: + + virtual ~AssemblyAnnotationWriter(); + + /// emitFunctionAnnot - This may be implemented to emit a string right before + /// the start of a function. + virtual void emitFunctionAnnot(const Function *F, + formatted_raw_ostream &OS) {} + + /// emitBasicBlockStartAnnot - This may be implemented to emit a string right + /// after the basic block label, but before the first instruction in the + /// block. + virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, + formatted_raw_ostream &OS) { + } + + /// emitBasicBlockEndAnnot - This may be implemented to emit a string right + /// after the basic block. + virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, + formatted_raw_ostream &OS) { + } + + /// emitInstructionAnnot - This may be implemented to emit a string right + /// before an instruction is emitted. + virtual void emitInstructionAnnot(const Instruction *I, + formatted_raw_ostream &OS) {} + + /// printInfoComment - This may be implemented to emit a comment to the + /// right of an instruction or global value. + virtual void printInfoComment(const Value &V, formatted_raw_ostream &OS) {} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Assembly/Parser.h b/final/include/llvm/Assembly/Parser.h new file mode 100644 index 00000000000..82ec6d81367 --- /dev/null +++ b/final/include/llvm/Assembly/Parser.h @@ -0,0 +1,65 @@ +//===-- llvm/Assembly/Parser.h - Parser for VM assembly files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes are implemented by the lib/AsmParser library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PARSER_H +#define LLVM_ASSEMBLY_PARSER_H + +#include + +namespace llvm { + +class Module; +class MemoryBuffer; +class SMDiagnostic; +class raw_ostream; +class LLVMContext; + +/// This function is the main interface to the LLVM Assembly Parser. It parses +/// an ASCII file that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a file +Module *ParseAssemblyFile( + const std::string &Filename, ///< The name of the file to parse + SMDiagnostic &Error, ///< Error result info. + LLVMContext &Context ///< Context in which to allocate globals info. +); + +/// The function is a secondary interface to the LLVM Assembly Parser. It parses +/// an ASCII string that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a string +Module *ParseAssemblyString( + const char *AsmString, ///< The string containing assembly + Module *M, ///< A module to add the assembly too. + SMDiagnostic &Error, ///< Error result info. + LLVMContext &Context +); + +/// This function is the low-level interface to the LLVM Assembly Parser. +/// ParseAssemblyFile and ParseAssemblyString are wrappers around this function. +/// @brief Parse LLVM Assembly from a MemoryBuffer. This function *always* +/// takes ownership of the MemoryBuffer. +Module *ParseAssembly( + MemoryBuffer *F, ///< The MemoryBuffer containing assembly + Module *M, ///< A module to add the assembly too. + SMDiagnostic &Err, ///< Error result info. + LLVMContext &Context +); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Assembly/PrintModulePass.h b/final/include/llvm/Assembly/PrintModulePass.h new file mode 100644 index 00000000000..239fbcc0c8c --- /dev/null +++ b/final/include/llvm/Assembly/PrintModulePass.h @@ -0,0 +1,42 @@ +//===- llvm/Assembly/PrintModulePass.h - Printing Pass ----------*- 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 two passes to print out a module. The PrintModulePass pass +// simply prints out the entire module when it is executed. The +// PrintFunctionPass class is designed to be pipelined with other +// FunctionPass's, and prints out the functions of the module as they are +// processed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PRINTMODULEPASS_H +#define LLVM_ASSEMBLY_PRINTMODULEPASS_H + +#include + +namespace llvm { + class FunctionPass; + class ModulePass; + class raw_ostream; + + /// createPrintModulePass - Create and return a pass that writes the + /// module to the specified raw_ostream. + ModulePass *createPrintModulePass(raw_ostream *OS, + bool DeleteStream=false, + const std::string &Banner = ""); + + /// createPrintFunctionPass - Create and return a pass that prints + /// functions to the specified raw_ostream as they are processed. + FunctionPass *createPrintFunctionPass(const std::string &Banner, + raw_ostream *OS, + bool DeleteStream=false); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Assembly/Writer.h b/final/include/llvm/Assembly/Writer.h new file mode 100644 index 00000000000..c5b239079a0 --- /dev/null +++ b/final/include/llvm/Assembly/Writer.h @@ -0,0 +1,78 @@ +//===-- llvm/Assembly/Writer.h - Printer for LLVM assembly files --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This functionality is implemented by lib/VMCore/AsmWriter.cpp. +// This library is used to print LLVM assembly language files to an iostream. It +// can print LLVM code at a variety of granularities, including Modules, +// BasicBlocks, and Instructions. This makes it useful for debugging. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_WRITER_H +#define LLVM_ASSEMBLY_WRITER_H + +#include + +namespace llvm { + +class Type; +class Module; +class Value; +class raw_ostream; +template class SmallVectorImpl; + +/// TypePrinting - Type printing machinery. +class TypePrinting { + void *TypeNames; // A map to remember type names. + TypePrinting(const TypePrinting &); // DO NOT IMPLEMENT + void operator=(const TypePrinting&); // DO NOT IMPLEMENT +public: + TypePrinting(); + ~TypePrinting(); + + void clear(); + + void print(const Type *Ty, raw_ostream &OS, bool IgnoreTopLevelName = false); + + void printAtLeastOneLevel(const Type *Ty, raw_ostream &OS) { + print(Ty, OS, true); + } + + /// hasTypeName - Return true if the type has a name in TypeNames, false + /// otherwise. + bool hasTypeName(const Type *Ty) const; + + /// addTypeName - Add a name for the specified type if it doesn't already have + /// one. This name will be printed instead of the structural version of the + /// type in order to make the output more concise. + void addTypeName(const Type *Ty, const std::string &N); + +private: + void CalcTypeName(const Type *Ty, SmallVectorImpl &TypeStack, + raw_ostream &OS, bool IgnoreTopLevelName = false); +}; + +// WriteTypeSymbolic - This attempts to write the specified type as a symbolic +// type, if there is an entry in the Module's symbol table for the specified +// type or one of its component types. +// +void WriteTypeSymbolic(raw_ostream &, const Type *, const Module *M); + +// WriteAsOperand - Write the name of the specified value out to the specified +// ostream. This can be useful when you just want to print int %reg126, not the +// whole instruction that generated it. If you specify a Module for context, +// then even constants get pretty-printed; for example, the type of a null +// pointer is printed symbolically. +// +void WriteAsOperand(raw_ostream &, const Value *, bool PrintTy = true, + const Module *Context = 0); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Attributes.h b/final/include/llvm/Attributes.h new file mode 100644 index 00000000000..da6188b1a8e --- /dev/null +++ b/final/include/llvm/Attributes.h @@ -0,0 +1,290 @@ +//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the simple types necessary to represent the +// attributes associated with functions and their calls. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ATTRIBUTES_H +#define LLVM_ATTRIBUTES_H + +#include "llvm/Support/MathExtras.h" +#include +#include + +namespace llvm { +class Type; + +/// Attributes - A bitset of attributes. +typedef unsigned Attributes; + +namespace Attribute { + +/// Function parameters and results can have attributes to indicate how they +/// should be treated by optimizations and code generation. This enumeration +/// lists the attributes that can be associated with parameters, function +/// results or the function itself. +/// @brief Function attributes. + +const Attributes None = 0; ///< No attributes have been set +const Attributes ZExt = 1<<0; ///< Zero extended before/after call +const Attributes SExt = 1<<1; ///< Sign extended before/after call +const Attributes NoReturn = 1<<2; ///< Mark the function as not returning +const Attributes InReg = 1<<3; ///< Force argument to be passed in register +const Attributes StructRet = 1<<4; ///< Hidden pointer to structure to return +const Attributes NoUnwind = 1<<5; ///< Function doesn't unwind stack +const Attributes NoAlias = 1<<6; ///< Considered to not alias after call +const Attributes ByVal = 1<<7; ///< Pass structure by value +const Attributes Nest = 1<<8; ///< Nested function static chain +const Attributes ReadNone = 1<<9; ///< Function does not access memory +const Attributes ReadOnly = 1<<10; ///< Function only reads from memory +const Attributes NoInline = 1<<11; ///< inline=never +const Attributes AlwaysInline = 1<<12; ///< inline=always +const Attributes OptimizeForSize = 1<<13; ///< opt_size +const Attributes StackProtect = 1<<14; ///< Stack protection. +const Attributes StackProtectReq = 1<<15; ///< Stack protection required. +const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits) + // stored as log2 of alignment with +1 bias + // 0 means unaligned different from align 1 +const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer +const Attributes NoRedZone = 1<<22; /// disable redzone +const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point + /// instructions. +const Attributes Naked = 1<<24; ///< Naked function +const Attributes InlineHint = 1<<25; ///< source said inlining was + ///desirable +const Attributes StackAlignment = 7<<26; ///< Alignment of stack for + ///function (3 bits) stored as log2 + ///of alignment with +1 bias + ///0 means unaligned (different from + ///alignstack(1)) +const Attributes Hotpatch = 1<<29; ///< Function should have special + ///'hotpatch' sequence in prologue + +/// @brief Attributes that only apply to function parameters. +const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; + +/// @brief Attributes that may be applied to the function itself. These cannot +/// be used on return values or function parameters. +const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | + NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | + NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | + Hotpatch; + +/// @brief Parameter attributes that do not apply to vararg call arguments. +const Attributes VarArgsIncompatible = StructRet; + +/// @brief Attributes that are mutually incompatible. +const Attributes MutuallyIncompatible[4] = { + ByVal | InReg | Nest | StructRet, + ZExt | SExt, + ReadNone | ReadOnly, + NoInline | AlwaysInline +}; + +/// @brief Which attributes cannot be applied to a type. +Attributes typeIncompatible(const Type *Ty); + +/// This turns an int alignment (a power of 2, normally) into the +/// form used internally in Attributes. +inline Attributes constructAlignmentFromInt(unsigned i) { + // Default alignment, allow the target to define how to align it. + if (i == 0) + return 0; + + assert(isPowerOf2_32(i) && "Alignment must be a power of two."); + assert(i <= 0x40000000 && "Alignment too large."); + return (Log2_32(i)+1) << 16; +} + +/// This returns the alignment field of an attribute as a byte alignment value. +inline unsigned getAlignmentFromAttrs(Attributes A) { + Attributes Align = A & Attribute::Alignment; + if (Align == 0) + return 0; + + return 1U << ((Align >> 16) - 1); +} + +/// This turns an int stack alignment (which must be a power of 2) into +/// the form used internally in Attributes. +inline Attributes constructStackAlignmentFromInt(unsigned i) { + // Default alignment, allow the target to define how to align it. + if (i == 0) + return 0; + + assert(isPowerOf2_32(i) && "Alignment must be a power of two."); + assert(i <= 0x100 && "Alignment too large."); + return (Log2_32(i)+1) << 26; +} + +/// This returns the stack alignment field of an attribute as a byte alignment +/// value. +inline unsigned getStackAlignmentFromAttrs(Attributes A) { + Attributes StackAlign = A & Attribute::StackAlignment; + if (StackAlign == 0) + return 0; + + return 1U << ((StackAlign >> 26) - 1); +} + + +/// The set of Attributes set in Attributes is converted to a +/// string of equivalent mnemonics. This is, presumably, for writing out +/// the mnemonics for the assembly writer. +/// @brief Convert attribute bits to text +std::string getAsString(Attributes Attrs); +} // end namespace Attribute + +/// This is just a pair of values to associate a set of attributes +/// with an index. +struct AttributeWithIndex { + Attributes Attrs; ///< The attributes that are set, or'd together. + unsigned Index; ///< Index of the parameter for which the attributes apply. + ///< Index 0 is used for return value attributes. + ///< Index ~0U is used for function attributes. + + static AttributeWithIndex get(unsigned Idx, Attributes Attrs) { + AttributeWithIndex P; + P.Index = Idx; + P.Attrs = Attrs; + return P; + } +}; + +//===----------------------------------------------------------------------===// +// AttrListPtr Smart Pointer +//===----------------------------------------------------------------------===// + +class AttributeListImpl; + +/// AttrListPtr - This class manages the ref count for the opaque +/// AttributeListImpl object and provides accessors for it. +class AttrListPtr { + /// AttrList - The attributes that we are managing. This can be null + /// to represent the empty attributes list. + AttributeListImpl *AttrList; +public: + AttrListPtr() : AttrList(0) {} + AttrListPtr(const AttrListPtr &P); + const AttrListPtr &operator=(const AttrListPtr &RHS); + ~AttrListPtr(); + + //===--------------------------------------------------------------------===// + // Attribute List Construction and Mutation + //===--------------------------------------------------------------------===// + + /// get - Return a Attributes list with the specified parameter in it. + static AttrListPtr get(const AttributeWithIndex *Attr, unsigned NumAttrs); + + /// get - Return a Attribute list with the parameters specified by the + /// consecutive random access iterator range. + template + static AttrListPtr get(const Iter &I, const Iter &E) { + if (I == E) return AttrListPtr(); // Empty list. + return get(&*I, static_cast(E-I)); + } + + /// addAttr - Add the specified attribute at the specified index to this + /// attribute list. Since attribute lists are immutable, this + /// returns the new list. + AttrListPtr addAttr(unsigned Idx, Attributes Attrs) const; + + /// removeAttr - Remove the specified attribute at the specified index from + /// this attribute list. Since attribute lists are immutable, this + /// returns the new list. + AttrListPtr removeAttr(unsigned Idx, Attributes Attrs) const; + + //===--------------------------------------------------------------------===// + // Attribute List Accessors + //===--------------------------------------------------------------------===// + /// getParamAttributes - The attributes for the specified index are + /// returned. + Attributes getParamAttributes(unsigned Idx) const { + assert (Idx && Idx != ~0U && "Invalid parameter index!"); + return getAttributes(Idx); + } + + /// getRetAttributes - The attributes for the ret value are + /// returned. + Attributes getRetAttributes() const { + return getAttributes(0); + } + + /// getFnAttributes - The function attributes are returned. + Attributes getFnAttributes() const { + return getAttributes(~0U); + } + + /// paramHasAttr - Return true if the specified parameter index has the + /// specified attribute set. + bool paramHasAttr(unsigned Idx, Attributes Attr) const { + return (getAttributes(Idx) & Attr) != 0; + } + + /// getParamAlignment - Return the alignment for the specified function + /// parameter. + unsigned getParamAlignment(unsigned Idx) const { + return Attribute::getAlignmentFromAttrs(getAttributes(Idx)); + } + + /// hasAttrSomewhere - Return true if the specified attribute is set for at + /// least one parameter or for the return value. + bool hasAttrSomewhere(Attributes Attr) const; + + /// operator==/!= - Provide equality predicates. + bool operator==(const AttrListPtr &RHS) const + { return AttrList == RHS.AttrList; } + bool operator!=(const AttrListPtr &RHS) const + { return AttrList != RHS.AttrList; } + + void dump() const; + + //===--------------------------------------------------------------------===// + // Attribute List Introspection + //===--------------------------------------------------------------------===// + + /// getRawPointer - Return a raw pointer that uniquely identifies this + /// attribute list. + void *getRawPointer() const { + return AttrList; + } + + // Attributes are stored as a dense set of slots, where there is one + // slot for each argument that has an attribute. This allows walking over the + // dense set instead of walking the sparse list of attributes. + + /// isEmpty - Return true if there are no attributes. + /// + bool isEmpty() const { + return AttrList == 0; + } + + /// getNumSlots - Return the number of slots used in this attribute list. + /// This is the number of arguments that have an attribute set on them + /// (including the function itself). + unsigned getNumSlots() const; + + /// getSlot - Return the AttributeWithIndex at the specified slot. This + /// holds a index number plus a set of attributes. + const AttributeWithIndex &getSlot(unsigned Slot) const; + +private: + explicit AttrListPtr(AttributeListImpl *L); + + /// getAttributes - The attributes for the specified index are + /// returned. Attributes for the result are denoted with Idx = 0. + Attributes getAttributes(unsigned Idx) const; + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/AutoUpgrade.h b/final/include/llvm/AutoUpgrade.h new file mode 100644 index 00000000000..5ce20b69e2f --- /dev/null +++ b/final/include/llvm/AutoUpgrade.h @@ -0,0 +1,48 @@ +//===-- llvm/AutoUpgrade.h - AutoUpgrade Helpers ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These functions are implemented by lib/VMCore/AutoUpgrade.cpp. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_AUTOUPGRADE_H +#define LLVM_AUTOUPGRADE_H + +namespace llvm { + class Module; + class GlobalVariable; + class Function; + class CallInst; + + /// This is a more granular function that simply checks an intrinsic function + /// for upgrading, and returns true if it requires upgrading. It may return + /// null in NewFn if the all calls to the original intrinsic function + /// should be transformed to non-function-call instructions. + bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); + + /// This is the complement to the above, replacing a specific call to an + /// intrinsic function with a call to the specified new function. + void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); + + /// This is an auto-upgrade hook for any old intrinsic function syntaxes + /// which need to have both the function updated as well as all calls updated + /// to the new function. This should only be run in a post-processing fashion + /// so that it can update all calls to the old function. + void UpgradeCallsToIntrinsic(Function* F); + + /// This checks for global variables which should be upgraded. It returns true + /// if it requires upgrading. + bool UpgradeGlobalVariable(GlobalVariable *GV); + + /// This function checks debug info intrinsics. If an intrinsic is invalid + /// then this function simply removes the intrinsic. + void CheckDebugInfoIntrinsics(Module *M); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/BasicBlock.h b/final/include/llvm/BasicBlock.h new file mode 100644 index 00000000000..7e7c9e76943 --- /dev/null +++ b/final/include/llvm/BasicBlock.h @@ -0,0 +1,269 @@ +//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the BasicBlock class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BASICBLOCK_H +#define LLVM_BASICBLOCK_H + +#include "llvm/Instruction.h" +#include "llvm/SymbolTableListTraits.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class TerminatorInst; +class LLVMContext; +class BlockAddress; + +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + // The sentinel is relative to this instance, so we use a non-static + // method. + Instruction *createSentinel() const { + // since i(p)lists always publicly derive from the corresponding + // traits, placing a data member in this class will augment i(p)list. + // But since the NodeTy is expected to publicly derive from + // ilist_node, there is a legal viable downcast from it + // to NodeTy. We use this trick to superpose i(p)list with a "ghostly" + // NodeTy, which becomes the sentinel. Dereferencing the sentinel is + // forbidden (save the ilist_node) so no one will ever notice + // the superposition. + return static_cast(&Sentinel); + } + static void destroySentinel(Instruction*) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction*) const { return createSentinel(); } + static void noteHead(Instruction*, Instruction*) {} +private: + mutable ilist_half_node Sentinel; +}; + +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// terminate the blocks. The BasicBlock class allows malformed basic blocks to +/// occur because it may be useful in the intermediate stage of constructing or +/// modifying a program. However, the verifier will ensure that basic blocks +/// are "well formed". +/// @brief LLVM Basic Block Representation +class BasicBlock : public Value, // Basic blocks are data objects also + public ilist_node { + friend class BlockAddress; +public: + typedef iplist InstListType; +private: + InstListType InstList; + Function *Parent; + + void setParent(Function *parent); + friend class SymbolTableListTraits; + + BasicBlock(const BasicBlock &); // Do not implement + void operator=(const BasicBlock &); // Do not implement + + /// BasicBlock ctor - If the function parameter is specified, the basic block + /// is automatically inserted at either the end of the function (if + /// InsertBefore is null), or before the specified basic block. + /// + explicit BasicBlock(LLVMContext &C, const Twine &Name = "", + Function *Parent = 0, BasicBlock *InsertBefore = 0); +public: + /// getContext - Get the context in which this basic block lives. + LLVMContext &getContext() const; + + /// Instruction iterators... + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + + /// Create - Creates a new BasicBlock. If the Parent parameter is specified, + /// the basic block is automatically inserted at either the end of the + /// function (if InsertBefore is 0), or before the specified basic block. + static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", + Function *Parent = 0,BasicBlock *InsertBefore = 0) { + return new BasicBlock(Context, Name, Parent, InsertBefore); + } + ~BasicBlock(); + + /// getParent - Return the enclosing method, or null if none + /// + const Function *getParent() const { return Parent; } + Function *getParent() { return Parent; } + + /// use_back - Specialize the methods defined in Value, as we know that an + /// BasicBlock can only be used by Users (specifically PHI nodes, terminators, + /// and BlockAddress's). + User *use_back() { return cast(*use_begin());} + const User *use_back() const { return cast(*use_begin());} + + /// getTerminator() - If this is a well formed basic block, then this returns + /// a pointer to the terminator instruction. If it is not, then you get a + /// null pointer back. + /// + TerminatorInst *getTerminator(); + const TerminatorInst *getTerminator() const; + + /// Returns a pointer to the first instructon in this block that is not a + /// PHINode instruction. When adding instruction to the beginning of the + /// basic block, they should be added before the returned value, not before + /// the first instruction, which might be PHI. + /// Returns 0 is there's no non-PHI instruction. + Instruction* getFirstNonPHI(); + const Instruction* getFirstNonPHI() const { + return const_cast(this)->getFirstNonPHI(); + } + + // Same as above, but also skip debug intrinsics. + Instruction* getFirstNonPHIOrDbg(); + const Instruction* getFirstNonPHIOrDbg() const { + return const_cast(this)->getFirstNonPHIOrDbg(); + } + + /// removeFromParent - This method unlinks 'this' from the containing + /// function, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing function + /// and deletes it. + /// + void eraseFromParent(); + + /// moveBefore - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right before MovePos. + void moveBefore(BasicBlock *MovePos); + + /// moveAfter - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right after MovePos. + void moveAfter(BasicBlock *MovePos); + + + /// getSinglePredecessor - If this basic block has a single predecessor block, + /// return the block, otherwise return a null pointer. + BasicBlock *getSinglePredecessor(); + const BasicBlock *getSinglePredecessor() const { + return const_cast(this)->getSinglePredecessor(); + } + + /// getUniquePredecessor - If this basic block has a unique predecessor block, + /// return the block, otherwise return a null pointer. + /// Note that unique predecessor doesn't mean single edge, there can be + /// multiple edges from the unique predecessor to this block (for example + /// a switch statement with multiple cases having the same destination). + BasicBlock *getUniquePredecessor(); + const BasicBlock *getUniquePredecessor() const { + return const_cast(this)->getUniquePredecessor(); + } + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline size_t size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const Instruction &front() const { return InstList.front(); } + inline Instruction &front() { return InstList.front(); } + inline const Instruction &back() const { return InstList.back(); } + inline Instruction &back() { return InstList.back(); } + + /// getInstList() - Return the underlying instruction list container. You + /// need to access it directly if you want to modify it currently. + /// + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + + /// getSublistAccess() - returns pointer to member of instruction list + static iplist BasicBlock::*getSublistAccess(Instruction*) { + return &BasicBlock::InstList; + } + + /// getValueSymbolTable() - returns pointer to symbol table (if any) + ValueSymbolTable *getValueSymbolTable(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BasicBlock *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::BasicBlockVal; + } + + /// dropAllReferences() - This function causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole class at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is delete'd for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + void dropAllReferences(); + + /// removePredecessor - This method is used to notify a BasicBlock that the + /// specified Predecessor of the block is no longer able to reach it. This is + /// actually not used to update the Predecessor list, but is actually used to + /// update the PHI nodes that reside in the block. Note that this should be + /// called while the predecessor still refers to this block. + /// + void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + + /// splitBasicBlock - This splits a basic block into two at the specified + /// instruction. Note that all instructions BEFORE the specified iterator + /// stay as part of the original basic block, an unconditional branch is added + /// to the original BB, and the rest of the instructions in the BB are moved + /// to the new BB, including the old terminator. The newly formed BasicBlock + /// is returned. This function invalidates the specified iterator. + /// + /// Note that this only works on well formed basic blocks (must have a + /// terminator), and 'I' must not be the end of instruction list (which would + /// cause a degenerate basic block to be formed, having a terminator inside of + /// the basic block). + /// + /// Also note that this doesn't preserve any passes. To split blocks while + /// keeping loop information consistent, use the SplitBlock utility function. + /// + BasicBlock *splitBasicBlock(iterator I, const Twine &BBName = ""); + + /// hasAddressTaken - returns true if there are any uses of this basic block + /// other than direct branches, switches, etc. to it. + bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } + +private: + /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress + /// objects using it. This is almost always 0, sometimes one, possibly but + /// almost never 2, and inconceivably 3 or more. + void AdjustBlockAddressRefCount(int Amt) { + setValueSubclassData(getSubclassDataFromValue()+Amt); + assert((int)(signed char)getSubclassDataFromValue() >= 0 && + "Refcount wrap-around"); + } + // Shadow Value::setValueSubclassData with a private forwarding method so that + // any future subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/Archive.h b/final/include/llvm/Bitcode/Archive.h new file mode 100644 index 00000000000..4abfa6e8442 --- /dev/null +++ b/final/include/llvm/Bitcode/Archive.h @@ -0,0 +1,546 @@ +//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the Archive and ArchiveMember classes that provide +// manipulation of LLVM Archive files. The implementation is provided by the +// lib/Bitcode/Archive library. This library is used to read and write +// archive (*.a) files that contain LLVM bitcode files (or others). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_ARCHIVE_H +#define LLVM_BITCODE_ARCHIVE_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/Path.h" +#include +#include + +namespace llvm { + class MemoryBuffer; + +// Forward declare classes +class Module; // From VMCore +class Archive; // Declared below +class ArchiveMemberHeader; // Internal implementation class +class LLVMContext; // Global data + +/// This class is the main class manipulated by users of the Archive class. It +/// holds information about one member of the Archive. It is also the element +/// stored by the Archive's ilist, the Archive's main abstraction. Because of +/// the special requirements of archive files, users are not permitted to +/// construct ArchiveMember instances. You should obtain them from the methods +/// of the Archive class instead. +/// @brief This class represents a single archive member. +class ArchiveMember : public ilist_node { + /// @name Types + /// @{ + public: + /// These flags are used internally by the archive member to specify various + /// characteristics of the member. The various "is" methods below provide + /// access to the flags. The flags are not user settable. + enum Flags { + CompressedFlag = 1, ///< Member is a normal compressed file + SVR4SymbolTableFlag = 2, ///< Member is a SVR4 symbol table + BSD4SymbolTableFlag = 4, ///< Member is a BSD4 symbol table + LLVMSymbolTableFlag = 8, ///< Member is an LLVM symbol table + BitcodeFlag = 16, ///< Member is bitcode + HasPathFlag = 64, ///< Member has a full or partial path + HasLongFilenameFlag = 128, ///< Member uses the long filename syntax + StringTableFlag = 256 ///< Member is an ar(1) format string table + }; + + /// @} + /// @name Accessors + /// @{ + public: + /// @returns the parent Archive instance + /// @brief Get the archive associated with this member + Archive* getArchive() const { return parent; } + + /// @returns the path to the Archive's file + /// @brief Get the path to the archive member + const sys::Path& getPath() const { return path; } + + /// The "user" is the owner of the file per Unix security. This may not + /// have any applicability on non-Unix systems but is a required component + /// of the "ar" file format. + /// @brief Get the user associated with this archive member. + unsigned getUser() const { return info.getUser(); } + + /// The "group" is the owning group of the file per Unix security. This + /// may not have any applicability on non-Unix systems but is a required + /// component of the "ar" file format. + /// @brief Get the group associated with this archive member. + unsigned getGroup() const { return info.getGroup(); } + + /// The "mode" specifies the access permissions for the file per Unix + /// security. This may not have any applicability on non-Unix systems but is + /// a required component of the "ar" file format. + /// @brief Get the permission mode associated with this archive member. + unsigned getMode() const { return info.getMode(); } + + /// This method returns the time at which the archive member was last + /// modified when it was not in the archive. + /// @brief Get the time of last modification of the archive member. + sys::TimeValue getModTime() const { return info.getTimestamp(); } + + /// @returns the size of the archive member in bytes. + /// @brief Get the size of the archive member. + uint64_t getSize() const { return info.getSize(); } + + /// This method returns the total size of the archive member as it + /// appears on disk. This includes the file content, the header, the + /// long file name if any, and the padding. + /// @brief Get total on-disk member size. + unsigned getMemberSize() const; + + /// This method will return a pointer to the in-memory content of the + /// archive member, if it is available. If the data has not been loaded + /// into memory, the return value will be null. + /// @returns a pointer to the member's data. + /// @brief Get the data content of the archive member + const char* getData() const { return data; } + + /// This method determines if the member is a regular compressed file. + /// @returns true iff the archive member is a compressed regular file. + /// @brief Determine if the member is a compressed regular file. + bool isCompressed() const { return flags&CompressedFlag; } + + /// @returns true iff the member is a SVR4 (non-LLVM) symbol table + /// @brief Determine if this member is a SVR4 symbol table. + bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; } + + /// @returns true iff the member is a BSD4.4 (non-LLVM) symbol table + /// @brief Determine if this member is a BSD4.4 symbol table. + bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; } + + /// @returns true iff the archive member is the LLVM symbol table + /// @brief Determine if this member is the LLVM symbol table. + bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; } + + /// @returns true iff the archive member is the ar(1) string table + /// @brief Determine if this member is the ar(1) string table. + bool isStringTable() const { return flags&StringTableFlag; } + + /// @returns true iff the archive member is a bitcode file. + /// @brief Determine if this member is a bitcode file. + bool isBitcode() const { return flags&BitcodeFlag; } + + /// @returns true iff the file name contains a path (directory) component. + /// @brief Determine if the member has a path + bool hasPath() const { return flags&HasPathFlag; } + + /// Long filenames are an artifact of the ar(1) file format which allows + /// up to sixteen characters in its header and doesn't allow a path + /// separator character (/). To avoid this, a "long format" member name is + /// allowed that doesn't have this restriction. This method determines if + /// that "long format" is used for this member. + /// @returns true iff the file name uses the long form + /// @brief Determine if the member has a long file name + bool hasLongFilename() const { return flags&HasLongFilenameFlag; } + + /// This method returns the status info (like Unix stat(2)) for the archive + /// member. The status info provides the file's size, permissions, and + /// modification time. The contents of the Path::StatusInfo structure, other + /// than the size and modification time, may not have utility on non-Unix + /// systems. + /// @returns the status info for the archive member + /// @brief Obtain the status info for the archive member + const sys::FileStatus &getFileStatus() const { return info; } + + /// This method causes the archive member to be replaced with the contents + /// of the file specified by \p File. The contents of \p this will be + /// updated to reflect the new data from \p File. The \p File must exist and + /// be readable on entry to this method. + /// @returns true if an error occurred, false otherwise + /// @brief Replace contents of archive member with a new file. + bool replaceWith(const sys::Path &aFile, std::string* ErrMsg); + + /// @} + /// @name Data + /// @{ + private: + Archive* parent; ///< Pointer to parent archive + sys::PathWithStatus path; ///< Path of file containing the member + sys::FileStatus info; ///< Status info (size,mode,date) + unsigned flags; ///< Flags about the archive member + const char* data; ///< Data for the member + + /// @} + /// @name Constructors + /// @{ + public: + /// The default constructor is only used by the Archive's iplist when it + /// constructs the list's sentry node. + ArchiveMember(); + + private: + /// Used internally by the Archive class to construct an ArchiveMember. + /// The contents of the ArchiveMember are filled out by the Archive class. + explicit ArchiveMember(Archive *PAR); + + // So Archive can construct an ArchiveMember + friend class llvm::Archive; + /// @} +}; + +/// This class defines the interface to LLVM Archive files. The Archive class +/// presents the archive file as an ilist of ArchiveMember objects. The members +/// can be rearranged in any fashion either by directly editing the ilist or by +/// using editing methods on the Archive class (recommended). The Archive +/// class also provides several ways of accessing the archive file for various +/// purposes such as editing and linking. Full symbol table support is provided +/// for loading only those files that resolve symbols. Note that read +/// performance of this library is _crucial_ for performance of JIT type +/// applications and the linkers. Consequently, the implementation of the class +/// is optimized for reading. +class Archive { + + /// @name Types + /// @{ + public: + /// This is the ilist type over which users may iterate to examine + /// the contents of the archive + /// @brief The ilist type of ArchiveMembers that Archive contains. + typedef iplist MembersList; + + /// @brief Forward mutable iterator over ArchiveMember + typedef MembersList::iterator iterator; + + /// @brief Forward immutable iterator over ArchiveMember + typedef MembersList::const_iterator const_iterator; + + /// @brief Reverse mutable iterator over ArchiveMember + typedef std::reverse_iterator reverse_iterator; + + /// @brief Reverse immutable iterator over ArchiveMember + typedef std::reverse_iterator const_reverse_iterator; + + /// @brief The in-memory version of the symbol table + typedef std::map SymTabType; + + /// @} + /// @name ilist accessor methods + /// @{ + public: + inline iterator begin() { return members.begin(); } + inline const_iterator begin() const { return members.begin(); } + inline iterator end () { return members.end(); } + inline const_iterator end () const { return members.end(); } + + inline reverse_iterator rbegin() { return members.rbegin(); } + inline const_reverse_iterator rbegin() const { return members.rbegin(); } + inline reverse_iterator rend () { return members.rend(); } + inline const_reverse_iterator rend () const { return members.rend(); } + + inline size_t size() const { return members.size(); } + inline bool empty() const { return members.empty(); } + inline const ArchiveMember& front() const { return members.front(); } + inline ArchiveMember& front() { return members.front(); } + inline const ArchiveMember& back() const { return members.back(); } + inline ArchiveMember& back() { return members.back(); } + + /// @} + /// @name ilist mutator methods + /// @{ + public: + /// This method splices a \p src member from an archive (possibly \p this), + /// to a position just before the member given by \p dest in \p this. When + /// the archive is written, \p src will be written in its new location. + /// @brief Move a member to a new location + inline void splice(iterator dest, Archive& arch, iterator src) + { return members.splice(dest,arch.members,src); } + + /// This method erases a \p target member from the archive. When the + /// archive is written, it will no longer contain \p target. The associated + /// ArchiveMember is deleted. + /// @brief Erase a member. + inline iterator erase(iterator target) { return members.erase(target); } + + /// @} + /// @name Constructors + /// @{ + public: + /// Create an empty archive file and associate it with the \p Filename. This + /// method does not actually create the archive disk file. It creates an + /// empty Archive object. If the writeToDisk method is called, the archive + /// file \p Filename will be created at that point, with whatever content + /// the returned Archive object has at that time. + /// @returns An Archive* that represents the new archive file. + /// @brief Create an empty Archive. + static Archive* CreateEmpty( + const sys::Path& Filename,///< Name of the archive to (eventually) create. + LLVMContext& C ///< Context to use for global information + ); + + /// Open an existing archive and load its contents in preparation for + /// editing. After this call, the member ilist is completely populated based + /// on the contents of the archive file. You should use this form of open if + /// you intend to modify the archive or traverse its contents (e.g. for + /// printing). + /// @brief Open and load an archive file + static Archive* OpenAndLoad( + const sys::Path& filePath, ///< The file path to open and load + LLVMContext& C, ///< The context to use for global information + std::string* ErrorMessage ///< An optional error string + ); + + /// This method opens an existing archive file from \p Filename and reads in + /// its symbol table without reading in any of the archive's members. This + /// reduces both I/O and cpu time in opening the archive if it is to be used + /// solely for symbol lookup (e.g. during linking). The \p Filename must + /// exist and be an archive file or an error will be returned. This form + /// of opening the archive is intended for read-only operations that need to + /// locate members via the symbol table for link editing. Since the archve + /// members are not read by this method, the archive will appear empty upon + /// return. If editing operations are performed on the archive, they will + /// completely replace the contents of the archive! It is recommended that + /// if this form of opening the archive is used that only the symbol table + /// lookup methods (getSymbolTable, findModuleDefiningSymbol, and + /// findModulesDefiningSymbols) be used. + /// @returns an Archive* that represents the archive file, or null on error. + /// @brief Open an existing archive and load its symbols. + static Archive* OpenAndLoadSymbols( + const sys::Path& Filename, ///< Name of the archive file to open + LLVMContext& C, ///< The context to use for global info + std::string* ErrorMessage=0 ///< An optional error string + ); + + /// This destructor cleans up the Archive object, releases all memory, and + /// closes files. It does nothing with the archive file on disk. If you + /// haven't used the writeToDisk method by the time the destructor is + /// called, all changes to the archive will be lost. + /// @brief Destruct in-memory archive + ~Archive(); + + /// @} + /// @name Accessors + /// @{ + public: + /// @returns the path to the archive file. + /// @brief Get the archive path. + const sys::Path& getPath() { return archPath; } + + /// This method is provided so that editing methods can be invoked directly + /// on the Archive's iplist of ArchiveMember. However, it is recommended + /// that the usual STL style iterator interface be used instead. + /// @returns the iplist of ArchiveMember + /// @brief Get the iplist of the members + MembersList& getMembers() { return members; } + + /// This method allows direct query of the Archive's symbol table. The + /// symbol table is a std::map of std::string (the symbol) to unsigned (the + /// file offset). Note that for efficiency reasons, the offset stored in + /// the symbol table is not the actual offset. It is the offset from the + /// beginning of the first "real" file member (after the symbol table). Use + /// the getFirstFileOffset() to obtain that offset and add this value to the + /// offset in the symbol table to obtain the real file offset. Note that + /// there is purposefully no interface provided by Archive to look up + /// members by their offset. Use the findModulesDefiningSymbols and + /// findModuleDefiningSymbol methods instead. + /// @returns the Archive's symbol table. + /// @brief Get the archive's symbol table + const SymTabType& getSymbolTable() { return symTab; } + + /// This method returns the offset in the archive file to the first "real" + /// file member. Archive files, on disk, have a signature and might have a + /// symbol table that precedes the first actual file member. This method + /// allows you to determine what the size of those fields are. + /// @returns the offset to the first "real" file member in the archive. + /// @brief Get the offset to the first "real" file member in the archive. + unsigned getFirstFileOffset() { return firstFileOffset; } + + /// This method will scan the archive for bitcode modules, interpret them + /// and return a vector of the instantiated modules in \p Modules. If an + /// error occurs, this method will return true. If \p ErrMessage is not null + /// and an error occurs, \p *ErrMessage will be set to a string explaining + /// the error that occurred. + /// @returns true if an error occurred + /// @brief Instantiate all the bitcode modules located in the archive + bool getAllModules(std::vector& Modules, std::string* ErrMessage); + + /// This accessor looks up the \p symbol in the archive's symbol table and + /// returns the associated module that defines that symbol. This method can + /// be called as many times as necessary. This is handy for linking the + /// archive into another module based on unresolved symbols. Note that the + /// Module returned by this accessor should not be deleted by the caller. It + /// is managed internally by the Archive class. It is possible that multiple + /// calls to this accessor will return the same Module instance because the + /// associated module defines multiple symbols. + /// @returns The Module* found or null if the archive does not contain a + /// module that defines the \p symbol. + /// @brief Look up a module by symbol name. + Module* findModuleDefiningSymbol( + const std::string& symbol, ///< Symbol to be sought + std::string* ErrMessage ///< Error message storage, if non-zero + ); + + /// This method is similar to findModuleDefiningSymbol but allows lookup of + /// more than one symbol at a time. If \p symbols contains a list of + /// undefined symbols in some module, then calling this method is like + /// making one complete pass through the archive to resolve symbols but is + /// more efficient than looking at the individual members. Note that on + /// exit, the symbols resolved by this method will be removed from \p + /// symbols to ensure they are not re-searched on a subsequent call. If + /// you need to retain the list of symbols, make a copy. + /// @brief Look up multiple symbols in the archive. + bool findModulesDefiningSymbols( + std::set& symbols, ///< Symbols to be sought + std::set& modules, ///< The modules matching \p symbols + std::string* ErrMessage ///< Error msg storage, if non-zero + ); + + /// This method determines whether the archive is a properly formed llvm + /// bitcode archive. It first makes sure the symbol table has been loaded + /// and has a non-zero size. If it does, then it is an archive. If not, + /// then it tries to load all the bitcode modules of the archive. Finally, + /// it returns whether it was successful. + /// @returns true if the archive is a proper llvm bitcode archive + /// @brief Determine whether the archive is a proper llvm bitcode archive. + bool isBitcodeArchive(); + + /// @} + /// @name Mutators + /// @{ + public: + /// This method is the only way to get the archive written to disk. It + /// creates or overwrites the file specified when \p this was created + /// or opened. The arguments provide options for writing the archive. If + /// \p CreateSymbolTable is true, the archive is scanned for bitcode files + /// and a symbol table of the externally visible function and global + /// variable names is created. If \p TruncateNames is true, the names of the + /// archive members will have their path component stripped and the file + /// name will be truncated at 15 characters. If \p Compress is specified, + /// all archive members will be compressed before being written. If + /// \p PrintSymTab is true, the symbol table will be printed to std::cout. + /// @returns true if an error occurred, \p error set to error message + /// @returns false if the writing succeeded. + /// @brief Write (possibly modified) archive contents to disk + bool writeToDisk( + bool CreateSymbolTable=false, ///< Create Symbol table + bool TruncateNames=false, ///< Truncate the filename to 15 chars + bool Compress=false, ///< Compress files + std::string* ErrMessage=0 ///< If non-null, where error msg is set + ); + + /// This method adds a new file to the archive. The \p filename is examined + /// to determine just enough information to create an ArchiveMember object + /// which is then inserted into the Archive object's ilist at the location + /// given by \p where. + /// @returns true if an error occured, false otherwise + /// @brief Add a file to the archive. + bool addFileBefore( + const sys::Path& filename, ///< The file to be added + iterator where, ///< Insertion point + std::string* ErrMsg ///< Optional error message location + ); + + /// @} + /// @name Implementation + /// @{ + protected: + /// @brief Construct an Archive for \p filename and optionally map it + /// into memory. + explicit Archive(const sys::Path& filename, LLVMContext& C); + + /// @param data The symbol table data to be parsed + /// @param len The length of the symbol table data + /// @param error Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Parse the symbol table at \p data. + bool parseSymbolTable(const void* data,unsigned len,std::string* error); + + /// @returns A fully populated ArchiveMember or 0 if an error occurred. + /// @brief Parse the header of a member starting at \p At + ArchiveMember* parseMemberHeader( + const char*&At, ///< The pointer to the location we're parsing + const char*End, ///< The pointer to the end of the archive + std::string* error ///< Optional error message catcher + ); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Check that the archive signature is correct + bool checkSignature(std::string* ErrMessage); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Load the entire archive. + bool loadArchive(std::string* ErrMessage); + + /// @param ErrMessage Set to address of a std::string to get error messages + /// @returns false on error + /// @brief Load just the symbol table. + bool loadSymbolTable(std::string* ErrMessage); + + /// @brief Write the symbol table to an ofstream. + void writeSymbolTable(std::ofstream& ARFile); + + /// Writes one ArchiveMember to an ofstream. If an error occurs, returns + /// false, otherwise true. If an error occurs and error is non-null then + /// it will be set to an error message. + /// @returns false Writing member succeeded + /// @returns true Writing member failed, \p error set to error message + bool writeMember( + const ArchiveMember& member, ///< The member to be written + std::ofstream& ARFile, ///< The file to write member onto + bool CreateSymbolTable, ///< Should symbol table be created? + bool TruncateNames, ///< Should names be truncated to 11 chars? + bool ShouldCompress, ///< Should the member be compressed? + std::string* ErrMessage ///< If non-null, place were error msg is set + ); + + /// @brief Fill in an ArchiveMemberHeader from ArchiveMember. + bool fillHeader(const ArchiveMember&mbr, + ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const; + + /// @brief Maps archive into memory + bool mapToMemory(std::string* ErrMsg); + + /// @brief Frees all the members and unmaps the archive file. + void cleanUpMemory(); + + /// This type is used to keep track of bitcode modules loaded from the + /// symbol table. It maps the file offset to a pair that consists of the + /// associated ArchiveMember and the Module. + /// @brief Module mapping type + typedef std::map > + ModuleMap; + + + /// @} + /// @name Data + /// @{ + protected: + sys::Path archPath; ///< Path to the archive file we read/write + MembersList members; ///< The ilist of ArchiveMember + MemoryBuffer *mapfile; ///< Raw Archive contents mapped into memory + const char* base; ///< Base of the memory mapped file data + SymTabType symTab; ///< The symbol table + std::string strtab; ///< The string table for long file names + unsigned symTabSize; ///< Size in bytes of symbol table + unsigned firstFileOffset; ///< Offset to first normal file. + ModuleMap modules; ///< The modules loaded via symbol lookup. + ArchiveMember* foreignST; ///< This holds the foreign symbol table. + LLVMContext& Context; ///< This holds global data. + /// @} + /// @name Hidden + /// @{ + private: + Archive(); ///< Do not implement + Archive(const Archive&); ///< Do not implement + Archive& operator=(const Archive&); ///< Do not implement + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/BitCodes.h b/final/include/llvm/Bitcode/BitCodes.h new file mode 100644 index 00000000000..449dc35d7de --- /dev/null +++ b/final/include/llvm/Bitcode/BitCodes.h @@ -0,0 +1,185 @@ +//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header Bitcode enum values. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODES_H +#define LLVM_BITCODE_BITCODES_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +namespace bitc { + enum StandardWidths { + BlockIDWidth = 8, // We use VBR-8 for block IDs. + CodeLenWidth = 4, // Codelen are VBR-4. + BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 16GB per block. + }; + + // The standard abbrev namespace always has a way to exit a block, enter a + // nested block, define abbrevs, and define an unabbreviated record. + enum FixedAbbrevIDs { + END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode. + ENTER_SUBBLOCK = 1, + + /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists + /// of a vbr5 for # operand infos. Each operand info is emitted with a + /// single bit to indicate if it is a literal encoding. If so, the value is + /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed + /// by the info value as a vbr5 if needed. + DEFINE_ABBREV = 2, + + // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by + // a vbr6 for the # operands, followed by vbr6's for each operand. + UNABBREV_RECORD = 3, + + // This is not a code, this is a marker for the first abbrev assignment. + FIRST_APPLICATION_ABBREV = 4 + }; + + /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO + /// block, which contains metadata about other blocks in the file. + enum StandardBlockIDs { + /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example, + /// standard abbrevs that should be available to all blocks of a specified + /// ID. + BLOCKINFO_BLOCK_ID = 0, + + // Block IDs 1-7 are reserved for future expansion. + FIRST_APPLICATION_BLOCKID = 8 + }; + + /// BlockInfoCodes - The blockinfo block contains metadata about user-defined + /// blocks. + enum BlockInfoCodes { + // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd + // block, instead of the BlockInfo block. + + BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] + BLOCKINFO_CODE_BLOCKNAME = 2, // BLOCKNAME: [name] + BLOCKINFO_CODE_SETRECORDNAME = 3 // BLOCKINFO_CODE_SETRECORDNAME: [id, name] + }; + +} // End bitc namespace + +/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation. +/// This is actually a union of two different things: +/// 1. It could be a literal integer value ("the operand is always 17"). +/// 2. It could be an encoding specification ("this operand encoded like so"). +/// +class BitCodeAbbrevOp { + uint64_t Val; // A literal value or data for an encoding. + bool IsLiteral : 1; // Indicate whether this is a literal value or not. + unsigned Enc : 3; // The encoding to use. +public: + enum Encoding { + Fixed = 1, // A fixed width field, Val specifies number of bits. + VBR = 2, // A VBR field where Val specifies the width of each chunk. + Array = 3, // A sequence of fields, next field species elt encoding. + Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._]. + Blob = 5 // 32-bit aligned array of 8-bit characters. + }; + + explicit BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} + explicit BitCodeAbbrevOp(Encoding E, uint64_t Data = 0) + : Val(Data), IsLiteral(false), Enc(E) {} + + bool isLiteral() const { return IsLiteral; } + bool isEncoding() const { return !IsLiteral; } + + // Accessors for literals. + uint64_t getLiteralValue() const { assert(isLiteral()); return Val; } + + // Accessors for encoding info. + Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; } + uint64_t getEncodingData() const { + assert(isEncoding() && hasEncodingData()); + return Val; + } + + bool hasEncodingData() const { return hasEncodingData(getEncoding()); } + static bool hasEncodingData(Encoding E) { + switch (E) { + default: assert(0 && "Unknown encoding"); + case Fixed: + case VBR: + return true; + case Array: + case Char6: + case Blob: + return false; + } + } + + /// isChar6 - Return true if this character is legal in the Char6 encoding. + static bool isChar6(char C) { + if (C >= 'a' && C <= 'z') return true; + if (C >= 'A' && C <= 'Z') return true; + if (C >= '0' && C <= '9') return true; + if (C == '.' || C == '_') return true; + return false; + } + static unsigned EncodeChar6(char C) { + if (C >= 'a' && C <= 'z') return C-'a'; + if (C >= 'A' && C <= 'Z') return C-'A'+26; + if (C >= '0' && C <= '9') return C-'0'+26+26; + if (C == '.') return 62; + if (C == '_') return 63; + assert(0 && "Not a value Char6 character!"); + return 0; + } + + static char DecodeChar6(unsigned V) { + assert((V & ~63) == 0 && "Not a Char6 encoded character!"); + if (V < 26) return V+'a'; + if (V < 26+26) return V-26+'A'; + if (V < 26+26+10) return V-26-26+'0'; + if (V == 62) return '.'; + if (V == 63) return '_'; + assert(0 && "Not a value Char6 character!"); + return ' '; + } + +}; + +/// BitCodeAbbrev - This class represents an abbreviation record. An +/// abbreviation allows a complex record that has redundancy to be stored in a +/// specialized format instead of the fully-general, fully-vbr, format. +class BitCodeAbbrev { + SmallVector OperandList; + unsigned char RefCount; // Number of things using this. + ~BitCodeAbbrev() {} +public: + BitCodeAbbrev() : RefCount(1) {} + + void addRef() { ++RefCount; } + void dropRef() { if (--RefCount == 0) delete this; } + + unsigned getNumOperandInfos() const { + return static_cast(OperandList.size()); + } + const BitCodeAbbrevOp &getOperandInfo(unsigned N) const { + return OperandList[N]; + } + + void Add(const BitCodeAbbrevOp &OpInfo) { + OperandList.push_back(OpInfo); + } +}; +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/BitstreamReader.h b/final/include/llvm/Bitcode/BitstreamReader.h new file mode 100644 index 00000000000..779ef5fa2d8 --- /dev/null +++ b/final/include/llvm/Bitcode/BitstreamReader.h @@ -0,0 +1,642 @@ +//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitstreamReader class. This class can be used to +// read an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_READER_H +#define BITSTREAM_READER_H + +#include "llvm/Bitcode/BitCodes.h" +#include +#include +#include + +namespace llvm { + + class Deserializer; + +class BitstreamReader { +public: + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector Abbrevs; + std::string Name; + + std::vector > RecordNames; + }; +private: + /// FirstChar/LastChar - This remembers the first and last bytes of the + /// stream. + const unsigned char *FirstChar, *LastChar; + + std::vector BlockInfoRecords; + + /// IgnoreBlockInfoNames - This is set to true if we don't care about the + /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer + /// uses this. + bool IgnoreBlockInfoNames; + + BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED + void operator=(const BitstreamReader&); // NOT IMPLEMENTED +public: + BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) { + } + + BitstreamReader(const unsigned char *Start, const unsigned char *End) { + IgnoreBlockInfoNames = true; + init(Start, End); + } + + void init(const unsigned char *Start, const unsigned char *End) { + FirstChar = Start; + LastChar = End; + assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); + } + + ~BitstreamReader() { + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); + i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + const unsigned char *getFirstChar() const { return FirstChar; } + const unsigned char *getLastChar() const { return LastChar; } + + /// CollectBlockInfoNames - This is called by clients that want block/record + /// name information. + void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } + bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// hasBlockInfoRecords - Return true if we've already read and processed the + /// block info block for this Bitstream. We only process it for the first + /// cursor that walks over it. + bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + const BlockInfo *getBlockInfo(unsigned BlockID) const { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); + i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (const BlockInfo *BI = getBlockInfo(BlockID)) + return *const_cast(BI); + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +}; + +class BitstreamCursor { + friend class Deserializer; + BitstreamReader *BitStream; + const unsigned char *NextChar; + + /// CurWord - This is the current data we have pulled from the stream but have + /// not returned to the client. + uint32_t CurWord; + + /// BitsInCurWord - This is the number of bits in CurWord that are valid. This + /// is always from [0...31] inclusive. + unsigned BitsInCurWord; + + // CurCodeSize - This is the declared size of code values used for the current + // block, in bits. + unsigned CurCodeSize; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + std::vector PrevAbbrevs; + explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} + }; + + /// BlockScope - This tracks the codesize of parent blocks. + SmallVector BlockScope; + +public: + BitstreamCursor() : BitStream(0), NextChar(0) { + } + BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { + operator=(RHS); + } + + explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 2; + } + + void init(BitstreamReader &R) { + freeState(); + + BitStream = &R; + NextChar = R.getFirstChar(); + assert(NextChar && "Bitstream not initialized yet"); + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 2; + } + + ~BitstreamCursor() { + freeState(); + } + + void operator=(const BitstreamCursor &RHS) { + freeState(); + + BitStream = RHS.BitStream; + NextChar = RHS.NextChar; + CurWord = RHS.CurWord; + BitsInCurWord = RHS.BitsInCurWord; + CurCodeSize = RHS.CurCodeSize; + + // Copy abbreviations, and bump ref counts. + CurAbbrevs = RHS.CurAbbrevs; + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->addRef(); + + // Copy block scope and bump ref counts. + for (unsigned S = 0, e = static_cast(BlockScope.size()); + S != e; ++S) { + std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = static_cast(Abbrevs.size()); + i != e; ++i) + Abbrevs[i]->addRef(); + } + } + + void freeState() { + // Free all the Abbrevs. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + CurAbbrevs.clear(); + + // Free all the Abbrevs in the block scope. + for (unsigned S = 0, e = static_cast(BlockScope.size()); + S != e; ++S) { + std::vector &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = static_cast(Abbrevs.size()); + i != e; ++i) + Abbrevs[i]->dropRef(); + } + BlockScope.clear(); + } + + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned GetAbbrevIDWidth() const { return CurCodeSize; } + + bool AtEndOfStream() const { + return NextChar == BitStream->getLastChar() && BitsInCurWord == 0; + } + + /// GetCurrentBitNo - Return the bit # of the bit we are reading. + uint64_t GetCurrentBitNo() const { + return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord; + } + + BitstreamReader *getBitStreamReader() { + return BitStream; + } + const BitstreamReader *getBitStreamReader() const { + return BitStream; + } + + + /// JumpToBit - Reset the stream to the specified bit number. + void JumpToBit(uint64_t BitNo) { + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; + uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()- + BitStream->getFirstChar()) && + "Invalid location"); + + // Move the cursor to the right word. + NextChar = BitStream->getFirstChar()+ByteNo; + BitsInCurWord = 0; + CurWord = 0; + + // Skip over any bits that are already consumed. + if (WordBitNo) + Read(static_cast(WordBitNo)); + } + + + uint32_t Read(unsigned NumBits) { + assert(NumBits <= 32 && "Cannot return more than 32 bits!"); + // If the field is fully contained by CurWord, return it quickly. + if (BitsInCurWord >= NumBits) { + uint32_t R = CurWord & ((1U << NumBits)-1); + CurWord >>= NumBits; + BitsInCurWord -= NumBits; + return R; + } + + // If we run out of data, stop at the end of the stream. + if (NextChar == BitStream->getLastChar()) { + CurWord = 0; + BitsInCurWord = 0; + return 0; + } + + unsigned R = CurWord; + + // Read the next word from the stream. + CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) | + (NextChar[2] << 16) | (NextChar[3] << 24); + NextChar += 4; + + // Extract NumBits-BitsInCurWord from what we just read. + unsigned BitsLeft = NumBits-BitsInCurWord; + + // Be careful here, BitsLeft is in the range [1..32] inclusive. + R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + + // BitsLeft bits have just been used up from CurWord. + if (BitsLeft != 32) + CurWord >>= BitsLeft; + else + CurWord = 0; + BitsInCurWord = 32-BitsLeft; + return R; + } + + uint64_t Read64(unsigned NumBits) { + if (NumBits <= 32) return Read(NumBits); + + uint64_t V = Read(32); + return V | (uint64_t)Read(NumBits-32) << 32; + } + + uint32_t ReadVBR(unsigned NumBits) { + uint32_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return Piece; + + uint32_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The + // chunk size of the VBR must still be <= 32 bits though. + uint64_t ReadVBR64(unsigned NumBits) { + uint32_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return uint64_t(Piece); + + uint64_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + void SkipToWord() { + BitsInCurWord = 0; + CurWord = 0; + } + + unsigned ReadCode() { + return Read(CurCodeSize); + } + + + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] + + /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for + /// the block. + unsigned ReadSubBlockID() { + return ReadVBR(bitc::BlockIDWidth); + } + + /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip + /// over the body of this block. If the block record is malformed, return + /// true. + bool SkipBlock() { + // Read and ignore the codelen value. Since we are skipping this block, we + // don't care what code widths are used inside of it. + ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + + // Check that the block wasn't partially defined, and that the offset isn't + // bogus. + if (AtEndOfStream() || NextChar+NumWords*4 > BitStream->getLastChar()) + return true; + + NextChar += NumWords*4; + return false; + } + + /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter + /// the block, and return true if the block is valid. + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) { + // Save the current block's state on BlockScope. + BlockScope.push_back(Block(CurCodeSize)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // Add the abbrevs specific to this block to the CurAbbrevs list. + if (const BitstreamReader::BlockInfo *Info = + BitStream->getBlockInfo(BlockID)) { + for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); + i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + CurAbbrevs.back()->addRef(); + } + } + + // Get the codesize of this block. + CurCodeSize = ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + if (NumWordsP) *NumWordsP = NumWords; + + // Validate that this block is sane. + if (CurCodeSize == 0 || AtEndOfStream() || + NextChar+NumWords*4 > BitStream->getLastChar()) + return true; + + return false; + } + + bool ReadBlockEnd() { + if (BlockScope.empty()) return true; + + // Block tail: + // [END_BLOCK, ] + SkipToWord(); + + PopBlockScope(); + return false; + } + +private: + void PopBlockScope() { + CurCodeSize = BlockScope.back().PrevCodeSize; + + // Delete abbrevs from popped scope. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + } + + //===--------------------------------------------------------------------===// + // Record Processing + //===--------------------------------------------------------------------===// + +private: + void ReadAbbreviatedLiteral(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals) { + assert(Op.isLiteral() && "Not a literal"); + // If the abbrev specifies the literal value to use, use it. + Vals.push_back(Op.getLiteralValue()); + } + + void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl &Vals) { + assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!"); + + // Decode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + Vals.push_back(Read((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::VBR: + Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::Char6: + Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); + break; + } + } +public: + + /// getAbbrev - Return the abbreviation for the specified AbbrevId. + const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { + unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + return CurAbbrevs[AbbrevNo]; + } + + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, + const char **BlobStart = 0, unsigned *BlobLen = 0) { + if (AbbrevID == bitc::UNABBREV_RECORD) { + unsigned Code = ReadVBR(6); + unsigned NumElts = ReadVBR(6); + for (unsigned i = 0; i != NumElts; ++i) + Vals.push_back(ReadVBR64(6)); + return Code; + } + + const BitCodeAbbrev *Abbv = getAbbrev(AbbrevID); + + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral()) { + ReadAbbreviatedLiteral(Op, Vals); + } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { + // Array case. Read the number of elements as a vbr6. + unsigned NumElts = ReadVBR(6); + + // Get the element encoding. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // Read all the elements. + for (; NumElts; --NumElts) + ReadAbbreviatedField(EltEnc, Vals); + } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { + // Blob case. Read the number of bytes as a vbr6. + unsigned NumElts = ReadVBR(6); + SkipToWord(); // 32-bit alignment + + // Figure out where the end of this blob will be including tail padding. + const unsigned char *NewEnd = NextChar+((NumElts+3)&~3); + + // If this would read off the end of the bitcode file, just set the + // record to empty and return. + if (NewEnd > BitStream->getLastChar()) { + Vals.append(NumElts, 0); + NextChar = BitStream->getLastChar(); + break; + } + + // Otherwise, read the number of bytes. If we can return a reference to + // the data, do so to avoid copying it. + if (BlobStart) { + *BlobStart = (const char*)NextChar; + *BlobLen = NumElts; + } else { + for (; NumElts; ++NextChar, --NumElts) + Vals.push_back(*NextChar); + } + // Skip over tail padding. + NextChar = NewEnd; + } else { + ReadAbbreviatedField(Op, Vals); + } + } + + unsigned Code = (unsigned)Vals[0]; + Vals.erase(Vals.begin()); + return Code; + } + + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl &Vals, + const char *&BlobStart, unsigned &BlobLen) { + return ReadRecord(AbbrevID, Vals, &BlobStart, &BlobLen); + } + + + //===--------------------------------------------------------------------===// + // Abbrev Processing + //===--------------------------------------------------------------------===// + + void ReadAbbrevRecord() { + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + unsigned NumOpInfo = ReadVBR(5); + for (unsigned i = 0; i != NumOpInfo; ++i) { + bool IsLiteral = Read(1) ? true : false; + if (IsLiteral) { + Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); + continue; + } + + BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); + if (BitCodeAbbrevOp::hasEncodingData(E)) + Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); + else + Abbv->Add(BitCodeAbbrevOp(E)); + } + CurAbbrevs.push_back(Abbv); + } + +public: + + bool ReadBlockInfoBlock() { + // If this is the second stream to get to the block info block, skip it. + if (BitStream->hasBlockInfoRecords()) + return SkipBlock(); + + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; + + SmallVector Record; + BitstreamReader::BlockInfo *CurBlockInfo = 0; + + // Read all the records for this module. + while (1) { + unsigned Code = ReadCode(); + if (Code == bitc::END_BLOCK) + return ReadBlockEnd(); + if (Code == bitc::ENTER_SUBBLOCK) { + ReadSubBlockID(); + if (SkipBlock()) return true; + continue; + } + + // Read abbrev records, associate them with CurBID. + if (Code == bitc::DEFINE_ABBREV) { + if (!CurBlockInfo) return true; + ReadAbbrevRecord(); + + // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the + // appropriate BlockInfo. + BitCodeAbbrev *Abbv = CurAbbrevs.back(); + CurAbbrevs.pop_back(); + CurBlockInfo->Abbrevs.push_back(Abbv); + continue; + } + + // Read a record. + Record.clear(); + switch (ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::BLOCKINFO_CODE_SETBID: + if (Record.size() < 1) return true; + CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]); + break; + case bitc::BLOCKINFO_CODE_BLOCKNAME: { + if (!CurBlockInfo) return true; + if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. + std::string Name; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->Name = Name; + break; + } + case bitc::BLOCKINFO_CODE_SETRECORDNAME: { + if (!CurBlockInfo) return true; + if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name. + std::string Name; + for (unsigned i = 1, e = Record.size(); i != e; ++i) + Name += (char)Record[i]; + CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0], + Name)); + break; + } + } + } + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/BitstreamWriter.h b/final/include/llvm/Bitcode/BitstreamWriter.h new file mode 100644 index 00000000000..bfb3a4e49c5 --- /dev/null +++ b/final/include/llvm/Bitcode/BitstreamWriter.h @@ -0,0 +1,533 @@ +//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitstreamWriter class. This class can be used to +// write an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_WRITER_H +#define BITSTREAM_WRITER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitCodes.h" +#include + +namespace llvm { + +class BitstreamWriter { + std::vector &Out; + + /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. + unsigned CurBit; + + /// CurValue - The current value. Only bits < CurBit are valid. + uint32_t CurValue; + + /// CurCodeSize - This is the declared size of code values used for the + /// current block, in bits. + unsigned CurCodeSize; + + /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently + /// selected BLOCK ID. + unsigned BlockInfoCurBID; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + unsigned StartSizeWord; + std::vector PrevAbbrevs; + Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} + }; + + /// BlockScope - This tracks the current blocks that we have entered. + std::vector BlockScope; + + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector Abbrevs; + }; + std::vector BlockInfoRecords; + +public: + explicit BitstreamWriter(std::vector &O) + : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} + + ~BitstreamWriter() { + assert(CurBit == 0 && "Unflused data remaining"); + assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); + + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); + i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + std::vector &getBuffer() { return Out; } + + /// \brief Retrieve the current position in the stream, in bits. + uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; } + + //===--------------------------------------------------------------------===// + // Basic Primitives for emitting bits to the stream. + //===--------------------------------------------------------------------===// + + void Emit(uint32_t Val, unsigned NumBits) { + assert(NumBits && NumBits <= 32 && "Invalid value size!"); + assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!"); + CurValue |= Val << CurBit; + if (CurBit + NumBits < 32) { + CurBit += NumBits; + return; + } + + // Add the current word. + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + + if (CurBit) + CurValue = Val >> (32-CurBit); + else + CurValue = 0; + CurBit = (CurBit+NumBits) & 31; + } + + void Emit64(uint64_t Val, unsigned NumBits) { + if (NumBits <= 32) + Emit((uint32_t)Val, NumBits); + else { + Emit((uint32_t)Val, 32); + Emit((uint32_t)(Val >> 32), NumBits-32); + } + } + + void FlushToWord() { + if (CurBit) { + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + CurBit = 0; + CurValue = 0; + } + } + + void EmitVBR(uint32_t Val, unsigned NumBits) { + uint32_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit(Val, NumBits); + } + + void EmitVBR64(uint64_t Val, unsigned NumBits) { + if ((uint32_t)Val == Val) + return EmitVBR((uint32_t)Val, NumBits); + + uint64_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | + (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit((uint32_t)Val, NumBits); + } + + /// EmitCode - Emit the specified code. + void EmitCode(unsigned Val) { + Emit(Val, CurCodeSize); + } + + // BackpatchWord - Backpatch a 32-bit word in the output with the specified + // value. + void BackpatchWord(unsigned ByteNo, unsigned NewWord) { + Out[ByteNo++] = (unsigned char)(NewWord >> 0); + Out[ByteNo++] = (unsigned char)(NewWord >> 8); + Out[ByteNo++] = (unsigned char)(NewWord >> 16); + Out[ByteNo ] = (unsigned char)(NewWord >> 24); + } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + BlockInfo *getBlockInfo(unsigned BlockID) { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); + i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + + void EnterSubblock(unsigned BlockID, unsigned CodeLen) { + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] + EmitCode(bitc::ENTER_SUBBLOCK); + EmitVBR(BlockID, bitc::BlockIDWidth); + EmitVBR(CodeLen, bitc::CodeLenWidth); + FlushToWord(); + + unsigned BlockSizeWordLoc = static_cast(Out.size()); + unsigned OldCodeSize = CurCodeSize; + + // Emit a placeholder, which will be replaced when the block is popped. + Emit(0, bitc::BlockSizeWidth); + + CurCodeSize = CodeLen; + + // Push the outer block's abbrev set onto the stack, start out with an + // empty abbrev set. + BlockScope.push_back(Block(OldCodeSize, BlockSizeWordLoc/4)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // If there is a blockinfo for this BlockID, add all the predefined abbrevs + // to the abbrev list. + if (BlockInfo *Info = getBlockInfo(BlockID)) { + for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); + i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + Info->Abbrevs[i]->addRef(); + } + } + } + + void ExitBlock() { + assert(!BlockScope.empty() && "Block scope imbalance!"); + + // Delete all abbrevs. + for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); + i != e; ++i) + CurAbbrevs[i]->dropRef(); + + const Block &B = BlockScope.back(); + + // Block tail: + // [END_BLOCK, ] + EmitCode(bitc::END_BLOCK); + FlushToWord(); + + // Compute the size of the block, in words, not counting the size field. + unsigned SizeInWords= static_cast(Out.size())/4-B.StartSizeWord-1; + unsigned ByteNo = B.StartSizeWord*4; + + // Update the block size field in the header of this sub-block. + BackpatchWord(ByteNo, SizeInWords); + + // Restore the inner block's code size and abbrev table. + CurCodeSize = B.PrevCodeSize; + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + } + + //===--------------------------------------------------------------------===// + // Record Emission + //===--------------------------------------------------------------------===// + +private: + /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev + /// record. This is a no-op, since the abbrev specifies the literal to use. + template + void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { + assert(Op.isLiteral() && "Not a literal"); + // If the abbrev specifies the literal value to use, don't emit + // anything. + assert(V == Op.getLiteralValue() && + "Invalid abbrev for record!"); + } + + /// EmitAbbreviatedField - Emit a single scalar field value with the specified + /// encoding. + template + void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { + assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); + + // Encode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + if (Op.getEncodingData()) + Emit((unsigned)V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::VBR: + if (Op.getEncodingData()) + EmitVBR64(V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::Char6: + Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); + break; + } + } + + /// EmitRecordWithAbbrevImpl - This is the core implementation of the record + /// emission code. If BlobData is non-null, then it specifies an array of + /// data that should be emitted as part of the Blob or Array operand that is + /// known to exist at the end of the record. + template + void EmitRecordWithAbbrevImpl(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + const char *BlobData = Blob.data(); + unsigned BlobLen = (unsigned) Blob.size(); + unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + + EmitCode(Abbrev); + + unsigned RecordIdx = 0; + for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); + i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral()) { + assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); + EmitAbbreviatedLiteral(Op, Vals[RecordIdx]); + ++RecordIdx; + } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { + // Array case. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // If this record has blob data, emit it, otherwise we must have record + // entries to encode this way. + if (BlobData) { + assert(RecordIdx == Vals.size() && + "Blob data and record entries specified for array!"); + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(static_cast(BlobLen), 6); + + // Emit each field. + for (unsigned i = 0; i != BlobLen; ++i) + EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); + + // Know that blob data is consumed for assertion below. + BlobData = 0; + } else { + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(static_cast(Vals.size()-RecordIdx), 6); + + // Emit each field. + for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) + EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); + } + } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { + // If this record has blob data, emit it, otherwise we must have record + // entries to encode this way. + + // Emit a vbr6 to indicate the number of elements present. + if (BlobData) { + EmitVBR(static_cast(BlobLen), 6); + assert(RecordIdx == Vals.size() && + "Blob data and record entries specified for blob operand!"); + } else { + EmitVBR(static_cast(Vals.size()-RecordIdx), 6); + } + + // Flush to a 32-bit alignment boundary. + FlushToWord(); + assert((Out.size() & 3) == 0 && "Not 32-bit aligned"); + + // Emit each field as a literal byte. + if (BlobData) { + for (unsigned i = 0; i != BlobLen; ++i) + Out.push_back((unsigned char)BlobData[i]); + + // Know that blob data is consumed for assertion below. + BlobData = 0; + } else { + for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { + assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob"); + Out.push_back((unsigned char)Vals[RecordIdx]); + } + } + // Align end to 32-bits. + while (Out.size() & 3) + Out.push_back(0); + + } else { // Single scalar field. + assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); + EmitAbbreviatedField(Op, Vals[RecordIdx]); + ++RecordIdx; + } + } + assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); + assert(BlobData == 0 && + "Blob data specified for record that doesn't use it!"); + } + +public: + + /// EmitRecord - Emit the specified record to the stream, using an abbrev if + /// we have one to compress the output. + template + void EmitRecord(unsigned Code, SmallVectorImpl &Vals, + unsigned Abbrev = 0) { + if (!Abbrev) { + // If we don't have an abbrev to use, emit this in its fully unabbreviated + // form. + EmitCode(bitc::UNABBREV_RECORD); + EmitVBR(Code, 6); + EmitVBR(static_cast(Vals.size()), 6); + for (unsigned i = 0, e = static_cast(Vals.size()); i != e; ++i) + EmitVBR64(Vals[i], 6); + return; + } + + // Insert the code into Vals to treat it uniformly. + Vals.insert(Vals.begin(), Code); + + EmitRecordWithAbbrev(Abbrev, Vals); + } + + /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. + /// Unlike EmitRecord, the code for the record should be included in Vals as + /// the first entry. + template + void EmitRecordWithAbbrev(unsigned Abbrev, SmallVectorImpl &Vals) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef()); + } + + /// EmitRecordWithBlob - Emit the specified record to the stream, using an + /// abbrev that includes a blob at the end. The blob data to emit is + /// specified by the pointer and length specified at the end. In contrast to + /// EmitRecord, this routine expects that the first entry in Vals is the code + /// of the record. + template + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Blob) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Blob); + } + template + void EmitRecordWithBlob(unsigned Abbrev, SmallVectorImpl &Vals, + const char *BlobData, unsigned BlobLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(BlobData, BlobLen)); + } + + /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records + /// that end with an array. + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + StringRef Array) { + EmitRecordWithAbbrevImpl(Abbrev, Vals, Array); + } + template + void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl &Vals, + const char *ArrayData, unsigned ArrayLen) { + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, + ArrayLen)); + } + + //===--------------------------------------------------------------------===// + // Abbrev Emission + //===--------------------------------------------------------------------===// + +private: + // Emit the abbreviation as a DEFINE_ABBREV record. + void EncodeAbbrev(BitCodeAbbrev *Abbv) { + EmitCode(bitc::DEFINE_ABBREV); + EmitVBR(Abbv->getNumOperandInfos(), 5); + for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); + i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + Emit(Op.isLiteral(), 1); + if (Op.isLiteral()) { + EmitVBR64(Op.getLiteralValue(), 8); + } else { + Emit(Op.getEncoding(), 3); + if (Op.hasEncodingData()) + EmitVBR64(Op.getEncodingData(), 5); + } + } + } +public: + + /// EmitAbbrev - This emits an abbreviation to the stream. Note that this + /// method takes ownership of the specified abbrev. + unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + // Emit the abbreviation as a record. + EncodeAbbrev(Abbv); + CurAbbrevs.push_back(Abbv); + return static_cast(CurAbbrevs.size())-1 + + bitc::FIRST_APPLICATION_ABBREV; + } + + //===--------------------------------------------------------------------===// + // BlockInfo Block Emission + //===--------------------------------------------------------------------===// + + /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. + void EnterBlockInfoBlock(unsigned CodeWidth) { + EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); + BlockInfoCurBID = -1U; + } +private: + /// SwitchToBlockID - If we aren't already talking about the specified block + /// ID, emit a BLOCKINFO_CODE_SETBID record. + void SwitchToBlockID(unsigned BlockID) { + if (BlockInfoCurBID == BlockID) return; + SmallVector V; + V.push_back(BlockID); + EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); + BlockInfoCurBID = BlockID; + } + + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (BlockInfo *BI = getBlockInfo(BlockID)) + return *BI; + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +public: + + /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified + /// BlockID. + unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) { + SwitchToBlockID(BlockID); + EncodeAbbrev(Abbv); + + // Add the abbrev to the specified block record. + BlockInfo &Info = getOrCreateBlockInfo(BlockID); + Info.Abbrevs.push_back(Abbv); + + return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; + } +}; + + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/LLVMBitCodes.h b/final/include/llvm/Bitcode/LLVMBitCodes.h new file mode 100644 index 00000000000..7692bd28720 --- /dev/null +++ b/final/include/llvm/Bitcode/LLVMBitCodes.h @@ -0,0 +1,266 @@ +//===- LLVMBitCodes.h - Enum values for the LLVM bitcode format -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines Bitcode enum values for LLVM IR bitcode files. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_LLVMBITCODES_H +#define LLVM_BITCODE_LLVMBITCODES_H + +#include "llvm/Bitcode/BitCodes.h" + +namespace llvm { +namespace bitc { + // The only top-level block type defined is for a module. + enum BlockIDs { + // Blocks + MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID, + + // Module sub-block id's. + PARAMATTR_BLOCK_ID, + TYPE_BLOCK_ID, + CONSTANTS_BLOCK_ID, + FUNCTION_BLOCK_ID, + TYPE_SYMTAB_BLOCK_ID, + VALUE_SYMTAB_BLOCK_ID, + METADATA_BLOCK_ID, + METADATA_ATTACHMENT_ID + }; + + + /// MODULE blocks have a number of optional fields and subblocks. + enum ModuleCodes { + MODULE_CODE_VERSION = 1, // VERSION: [version#] + MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N] + MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N] + MODULE_CODE_ASM = 4, // ASM: [strchr x N] + MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N] + MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N] + + // GLOBALVAR: [pointer type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal] + MODULE_CODE_GLOBALVAR = 7, + + // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, + // section, visibility] + MODULE_CODE_FUNCTION = 8, + + // ALIAS: [alias type, aliasee val#, linkage] + MODULE_CODE_ALIAS = 9, + + /// MODULE_CODE_PURGEVALS: [numvals] + MODULE_CODE_PURGEVALS = 10, + + MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] + }; + + /// PARAMATTR blocks have code for defining a parameter attribute set. + enum AttributeCodes { + PARAMATTR_CODE_ENTRY = 1 // ENTRY: [paramidx0, attr0, paramidx1, attr1...] + }; + + /// TYPE blocks have codes for each type primitive they use. + enum TypeCodes { + TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries] + + // Type Codes + TYPE_CODE_VOID = 2, // VOID + TYPE_CODE_FLOAT = 3, // FLOAT + TYPE_CODE_DOUBLE = 4, // DOUBLE + TYPE_CODE_LABEL = 5, // LABEL + TYPE_CODE_OPAQUE = 6, // OPAQUE + TYPE_CODE_INTEGER = 7, // INTEGER: [width] + TYPE_CODE_POINTER = 8, // POINTER: [pointee type] + TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N] + TYPE_CODE_STRUCT = 10, // STRUCT: [ispacked, eltty x N] + TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty] + TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty] + + // These are not with the other floating point types because they're + // a late addition, and putting them in the right place breaks + // binary compatibility. + TYPE_CODE_X86_FP80 = 13, // X86 LONG DOUBLE + TYPE_CODE_FP128 = 14, // LONG DOUBLE (112 bit mantissa) + TYPE_CODE_PPC_FP128= 15, // PPC LONG DOUBLE (2 doubles) + + TYPE_CODE_METADATA = 16, // METADATA + + TYPE_CODE_X86_MMX = 17 // X86 MMX + }; + + // The type symbol table only has one code (TST_ENTRY_CODE). + enum TypeSymtabCodes { + TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N] + }; + + // The value symbol table only has one code (VST_ENTRY_CODE). + enum ValueSymtabCodes { + VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N] + VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N] + }; + + enum MetadataCodes { + METADATA_STRING = 1, // MDSTRING: [values] + // FIXME: Remove NODE in favor of NODE2 in LLVM 3.0 + METADATA_NODE = 2, // NODE with potentially invalid metadata + // FIXME: Remove FN_NODE in favor of FN_NODE2 in LLVM 3.0 + METADATA_FN_NODE = 3, // FN_NODE with potentially invalid metadata + METADATA_NAME = 4, // STRING: [values] + // FIXME: Remove NAMED_NODE in favor of NAMED_NODE2 in LLVM 3.0 + METADATA_NAMED_NODE = 5, // NAMED_NODE with potentially invalid metadata + METADATA_KIND = 6, // [n x [id, name]] + // FIXME: Remove ATTACHMENT in favor of ATTACHMENT2 in LLVM 3.0 + METADATA_ATTACHMENT = 7, // ATTACHMENT with potentially invalid metadata + METADATA_NODE2 = 8, // NODE2: [n x (type num, value num)] + METADATA_FN_NODE2 = 9, // FN_NODE2: [n x (type num, value num)] + METADATA_NAMED_NODE2 = 10, // NAMED_NODE2: [n x mdnodes] + METADATA_ATTACHMENT2 = 11 // [m x [value, [n x [id, mdnode]]] + }; + // The constants block (CONSTANTS_BLOCK_ID) describes emission for each + // constant and maintains an implicit current type value. + enum ConstantsCodes { + CST_CODE_SETTYPE = 1, // SETTYPE: [typeid] + CST_CODE_NULL = 2, // NULL + CST_CODE_UNDEF = 3, // UNDEF + CST_CODE_INTEGER = 4, // INTEGER: [intval] + CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval] + CST_CODE_FLOAT = 6, // FLOAT: [fpval] + CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number] + CST_CODE_STRING = 8, // STRING: [values] + CST_CODE_CSTRING = 9, // CSTRING: [values] + CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval] + CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval] + CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands] + CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval] + CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval] + CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval] + CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval] + CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred] + CST_CODE_INLINEASM = 18, // INLINEASM: [sideeffect,asmstr,conststr] + CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval] + CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands] + CST_CODE_BLOCKADDRESS = 21 // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#] + }; + + /// CastOpcodes - These are values used in the bitcode files to encode which + /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum CastOpcodes { + CAST_TRUNC = 0, + CAST_ZEXT = 1, + CAST_SEXT = 2, + CAST_FPTOUI = 3, + CAST_FPTOSI = 4, + CAST_UITOFP = 5, + CAST_SITOFP = 6, + CAST_FPTRUNC = 7, + CAST_FPEXT = 8, + CAST_PTRTOINT = 9, + CAST_INTTOPTR = 10, + CAST_BITCAST = 11 + }; + + /// BinaryOpcodes - These are values used in the bitcode files to encode which + /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum BinaryOpcodes { + BINOP_ADD = 0, + BINOP_SUB = 1, + BINOP_MUL = 2, + BINOP_UDIV = 3, + BINOP_SDIV = 4, // overloaded for FP + BINOP_UREM = 5, + BINOP_SREM = 6, // overloaded for FP + BINOP_SHL = 7, + BINOP_LSHR = 8, + BINOP_ASHR = 9, + BINOP_AND = 10, + BINOP_OR = 11, + BINOP_XOR = 12 + }; + + /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing + /// OverflowingBinaryOperator's SubclassOptionalData contents. + enum OverflowingBinaryOperatorOptionalFlags { + OBO_NO_UNSIGNED_WRAP = 0, + OBO_NO_SIGNED_WRAP = 1 + }; + + /// PossiblyExactOperatorOptionalFlags - Flags for serializing + /// PossiblyExactOperator's SubclassOptionalData contents. + enum PossiblyExactOperatorOptionalFlags { + PEO_EXACT = 0 + }; + + // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It + // can contain a constant block (CONSTANTS_BLOCK_ID). + enum FunctionCodes { + FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n] + + FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] + FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] + FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] + FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] + FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] + FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval] + FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred] + + FUNC_CODE_INST_RET = 10, // RET: [opty,opval] + FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#] + FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...] + FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...] + FUNC_CODE_INST_UNWIND = 14, // UNWIND + FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE + + FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] + FUNC_CODE_INST_MALLOC = 17, // MALLOC: [instty, op, align] + FUNC_CODE_INST_FREE = 18, // FREE: [opty, op] + FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align] + FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol] + // FIXME: Remove STORE in favor of STORE2 in LLVM 3.0 + FUNC_CODE_INST_STORE = 21, // STORE: [valty,val,ptr, align, vol] + // FIXME: Remove CALL in favor of CALL2 in LLVM 3.0 + FUNC_CODE_INST_CALL = 22, // CALL with potentially invalid metadata + FUNC_CODE_INST_VAARG = 23, // VAARG: [valistty, valist, instty] + // This store code encodes the pointer type, rather than the value type + // this is so information only available in the pointer type (e.g. address + // spaces) is retained. + FUNC_CODE_INST_STORE2 = 24, // STORE: [ptrty,ptr,val, align, vol] + // FIXME: Remove GETRESULT in favor of EXTRACTVAL in LLVM 3.0 + FUNC_CODE_INST_GETRESULT = 25, // GETRESULT: [ty, opval, n] + FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands] + FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands] + // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to + // support legacy vicmp/vfcmp instructions. + FUNC_CODE_INST_CMP2 = 28, // CMP2: [opty, opval, opval, pred] + // new select on i1 or [N x i1] + FUNC_CODE_INST_VSELECT = 29, // VSELECT: [ty,opval,opval,predty,pred] + FUNC_CODE_INST_INBOUNDS_GEP= 30, // INBOUNDS_GEP: [n x operands] + FUNC_CODE_INST_INDIRECTBR = 31, // INDIRECTBR: [opty, op0, op1, ...] + + // FIXME: Remove DEBUG_LOC in favor of DEBUG_LOC2 in LLVM 3.0 + FUNC_CODE_DEBUG_LOC = 32, // DEBUG_LOC with potentially invalid metadata + FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN + + FUNC_CODE_INST_CALL2 = 34, // CALL2: [attr, fnty, fnid, args...] + + FUNC_CODE_DEBUG_LOC2 = 35 // DEBUG_LOC2: [Line,Col,ScopeVal, IAVal] + }; +} // End bitc namespace +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Bitcode/ReaderWriter.h b/final/include/llvm/Bitcode/ReaderWriter.h new file mode 100644 index 00000000000..fa754c01462 --- /dev/null +++ b/final/include/llvm/Bitcode/ReaderWriter.h @@ -0,0 +1,145 @@ +//===-- llvm/Bitcode/ReaderWriter.h - Bitcode reader/writers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines interfaces to read and write LLVM bitcode files/streams. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_H +#define LLVM_BITCODE_H + +#include + +namespace llvm { + class Module; + class MemoryBuffer; + class ModulePass; + class BitstreamWriter; + class LLVMContext; + class raw_ostream; + + /// getLazyBitcodeModule - Read the header of the specified bitcode buffer + /// and prepare for lazy deserialization of function bodies. If successful, + /// this takes ownership of 'buffer' and returns a non-null pointer. On + /// error, this returns null, *does not* take ownership of Buffer, and fills + /// in *ErrMsg with an error description if ErrMsg is non-null. + Module *getLazyBitcodeModule(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg = 0); + + /// getBitcodeTargetTriple - Read the header of the specified bitcode + /// buffer and extract just the triple information. If successful, + /// this returns a string and *does not* take ownership + /// of 'buffer'. On error, this returns "", and fills in *ErrMsg + /// if ErrMsg is non-null. + std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg = 0); + + /// ParseBitcodeFile - Read the specified bitcode file, returning the module. + /// If an error occurs, this returns null and fills in *ErrMsg if it is + /// non-null. This method *never* takes ownership of Buffer. + Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context, + std::string *ErrMsg = 0); + + /// WriteBitcodeToFile - Write the specified module to the specified + /// raw output stream. For streams where it matters, the given stream + /// should be in "binary" mode. + void WriteBitcodeToFile(const Module *M, raw_ostream &Out); + + /// WriteBitcodeToStream - Write the specified module to the specified + /// raw output stream. + void WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream); + + /// createBitcodeWriterPass - Create and return a pass that writes the module + /// to the specified ostream. + ModulePass *createBitcodeWriterPass(raw_ostream &Str); + + + /// isBitcodeWrapper - Return true if the given bytes are the magic bytes + /// for an LLVM IR bitcode wrapper. + /// + static inline bool isBitcodeWrapper(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + // See if you can find the hidden message in the magic bytes :-). + // (Hint: it's a little-endian encoding.) + return BufPtr != BufEnd && + BufPtr[0] == 0xDE && + BufPtr[1] == 0xC0 && + BufPtr[2] == 0x17 && + BufPtr[3] == 0x0B; + } + + /// isRawBitcode - Return true if the given bytes are the magic bytes for + /// raw LLVM IR bitcode (without a wrapper). + /// + static inline bool isRawBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + // These bytes sort of have a hidden message, but it's not in + // little-endian this time, and it's a little redundant. + return BufPtr != BufEnd && + BufPtr[0] == 'B' && + BufPtr[1] == 'C' && + BufPtr[2] == 0xc0 && + BufPtr[3] == 0xde; + } + + /// isBitcode - Return true if the given bytes are the magic bytes for + /// LLVM IR bitcode, either with or without a wrapper. + /// + static bool inline isBitcode(const unsigned char *BufPtr, + const unsigned char *BufEnd) { + return isBitcodeWrapper(BufPtr, BufEnd) || + isRawBitcode(BufPtr, BufEnd); + } + + /// SkipBitcodeWrapperHeader - Some systems wrap bc files with a special + /// header for padding or other reasons. The format of this header is: + /// + /// struct bc_header { + /// uint32_t Magic; // 0x0B17C0DE + /// uint32_t Version; // Version, currently always 0. + /// uint32_t BitcodeOffset; // Offset to traditional bitcode file. + /// uint32_t BitcodeSize; // Size of traditional bitcode file. + /// ... potentially other gunk ... + /// }; + /// + /// This function is called when we find a file with a matching magic number. + /// In this case, skip down to the subsection of the file that is actually a + /// BC file. + static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr, + unsigned char *&BufEnd) { + enum { + KnownHeaderSize = 4*4, // Size of header we read. + OffsetField = 2*4, // Offset in bytes to Offset field. + SizeField = 3*4 // Offset in bytes to Size field. + }; + + // Must contain the header! + if (BufEnd-BufPtr < KnownHeaderSize) return true; + + unsigned Offset = ( BufPtr[OffsetField ] | + (BufPtr[OffsetField+1] << 8) | + (BufPtr[OffsetField+2] << 16) | + (BufPtr[OffsetField+3] << 24)); + unsigned Size = ( BufPtr[SizeField ] | + (BufPtr[SizeField +1] << 8) | + (BufPtr[SizeField +2] << 16) | + (BufPtr[SizeField +3] << 24)); + + // Verify that Offset+Size fits in the file. + if (Offset+Size > unsigned(BufEnd-BufPtr)) + return true; + BufPtr += Offset; + BufEnd = BufPtr+Size; + return false; + } +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CMakeLists.txt b/final/include/llvm/CMakeLists.txt new file mode 100644 index 00000000000..0c3ca1cd0c5 --- /dev/null +++ b/final/include/llvm/CMakeLists.txt @@ -0,0 +1,21 @@ +set(LLVM_TARGET_DEFINITIONS Intrinsics.td) + +tablegen(Intrinsics.gen -gen-intrinsic) + +add_custom_target(intrinsics_gen ALL + DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen) +set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") + +set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} intrinsics_gen PARENT_SCOPE) + +if( MSVC_IDE OR XCODE ) + # Creates a dummy target containing all headers for the benefit of + # Visual Studio users. + file(GLOB_RECURSE headers *.h) + add_td_sources(headers) + add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL + # We need at least one source file: + ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp + ${headers}) + set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc") +endif() diff --git a/final/include/llvm/CallGraphSCCPass.h b/final/include/llvm/CallGraphSCCPass.h new file mode 100644 index 00000000000..7154aa3259d --- /dev/null +++ b/final/include/llvm/CallGraphSCCPass.h @@ -0,0 +1,104 @@ +//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- 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 CallGraphSCCPass class, which is used for passes which +// are implemented as bottom-up traversals on the call graph. Because there may +// be cycles in the call graph, passes of this type operate on the call-graph in +// SCC order: that is, they process function bottom-up, except for recursive +// functions, which they process all at once. +// +// These passes are inherently interprocedural, and are required to keep the +// call graph up-to-date if they do anything which could modify it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALL_GRAPH_SCC_PASS_H +#define LLVM_CALL_GRAPH_SCC_PASS_H + +#include "llvm/Pass.h" +#include "llvm/Analysis/CallGraph.h" + +namespace llvm { + +class CallGraphNode; +class CallGraph; +class PMStack; +class CallGraphSCC; + +class CallGraphSCCPass : public Pass { +public: + explicit CallGraphSCCPass(char &pid) : Pass(PT_CallGraphSCC, pid) {} + + /// createPrinterPass - Get a pass that prints the Module + /// corresponding to a CallGraph. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + /// doInitialization - This method is called before the SCC's of the program + /// has been processed, allowing the pass to do initialization as necessary. + virtual bool doInitialization(CallGraph &CG) { + return false; + } + + /// runOnSCC - This method should be implemented by the subclass to perform + /// whatever action is necessary for the specified SCC. Note that + /// non-recursive (or only self-recursive) functions will have an SCC size of + /// 1, where recursive portions of the call graph will have SCC size > 1. + /// + /// SCC passes that add or delete functions to the SCC are required to update + /// the SCC list, otherwise stale pointers may be dereferenced. + /// + virtual bool runOnSCC(CallGraphSCC &SCC) = 0; + + /// doFinalization - This method is called after the SCC's of the program has + /// been processed, allowing the pass to do final cleanup as necessary. + virtual bool doFinalization(CallGraph &CG) { + return false; + } + + /// Assign pass manager to manager this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_CallGraphPassManager; + } + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; +}; + +/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on. +class CallGraphSCC { + void *Context; // The CGPassManager object that is vending this. + std::vector Nodes; +public: + CallGraphSCC(void *context) : Context(context) {} + + void initialize(CallGraphNode*const*I, CallGraphNode*const*E) { + Nodes.assign(I, E); + } + + bool isSingular() const { return Nodes.size() == 1; } + unsigned size() const { return Nodes.size(); } + + /// ReplaceNode - This informs the SCC and the pass manager that the specified + /// Old node has been deleted, and New is to be used in its place. + void ReplaceNode(CallGraphNode *Old, CallGraphNode *New); + + typedef std::vector::const_iterator iterator; + iterator begin() const { return Nodes.begin(); } + iterator end() const { return Nodes.end(); } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CallingConv.h b/final/include/llvm/CallingConv.h new file mode 100644 index 00000000000..4c5ee626709 --- /dev/null +++ b/final/include/llvm/CallingConv.h @@ -0,0 +1,103 @@ +//===-- llvm/CallingConv.h - LLVM 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 file defines LLVM's set of calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALLINGCONV_H +#define LLVM_CALLINGCONV_H + +namespace llvm { + +/// CallingConv Namespace - This namespace contains an enum with a value for +/// the well-known calling conventions. +/// +namespace CallingConv { + /// A set of enums which specify the assigned numeric values for known llvm + /// calling conventions. + /// @brief LLVM Calling Convention Representation + enum ID { + /// C - The default llvm calling convention, compatible with C. This + /// convention is the only calling convention that supports varargs calls. + /// As with typical C calling conventions, the callee/caller have to + /// tolerate certain amounts of prototype mismatch. + C = 0, + + // Generic LLVM calling conventions. None of these calling conventions + // support varargs calls, and all assume that the caller and callee + // prototype exactly match. + + /// Fast - This calling convention attempts to make calls as fast as + /// possible (e.g. by passing things in registers). + Fast = 8, + + // Cold - This calling convention attempts to make code in the caller as + // efficient as possible under the assumption that the call is not commonly + // executed. As such, these calls often preserve all registers so that the + // call does not break any live ranges in the caller side. + Cold = 9, + + // GHC - Calling convention used by the Glasgow Haskell Compiler (GHC). + GHC = 10, + + // Target - This is the start of the target-specific calling conventions, + // e.g. fastcall and thiscall on X86. + FirstTargetCC = 64, + + /// X86_StdCall - stdcall is the calling conventions mostly used by the + /// Win32 API. It is basically the same as the C convention with the + /// difference in that the callee is responsible for popping the arguments + /// from the stack. + X86_StdCall = 64, + + /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments + /// in ECX:EDX registers, others - via stack. Callee is responsible for + /// stack cleaning. + X86_FastCall = 65, + + /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete, + /// but still used on some targets). + ARM_APCS = 66, + + /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling + /// convention (aka EABI). Soft float variant. + ARM_AAPCS = 67, + + /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI. + ARM_AAPCS_VFP = 68, + + /// MSP430_INTR - Calling convention used for MSP430 interrupt routines. + MSP430_INTR = 69, + + /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, + /// others via stack. Callee is responsible for stack cleaning. MSVC uses + /// this by default for methods in its ABI. + X86_ThisCall = 70, + + /// PTX_Kernel - Call to a PTX kernel. + /// Passes all arguments in parameter space. + PTX_Kernel = 71, + + /// PTX_Device - Call to a PTX device function. + /// Passes all arguments in register or parameter space. + PTX_Device = 72, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. + MBLAZE_INTR = 73, + + /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support + /// routines (i.e. GCC's save_volatiles attribute). + MBLAZE_SVOL = 74 + }; +} // End CallingConv namespace + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/Analysis.h b/final/include/llvm/CodeGen/Analysis.h new file mode 100644 index 00000000000..78bf9fc11aa --- /dev/null +++ b/final/include/llvm/CodeGen/Analysis.h @@ -0,0 +1,85 @@ +//===- CodeGen/Analysis.h - CodeGen LLVM IR Analysis Utilities --*- 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 several CodeGen-specific LLVM IR analysis utilties. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ANALYSIS_H +#define LLVM_CODEGEN_ANALYSIS_H + +#include "llvm/Instructions.h" +#include "llvm/InlineAsm.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/Support/CallSite.h" + +namespace llvm { + +class GlobalVariable; +class TargetLowering; +class SDNode; +class SelectionDAG; + +/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence +/// of insertvalue or extractvalue indices that identify a member, return +/// the linearized index of the start of the member. +/// +unsigned ComputeLinearIndex(const Type *Ty, + const unsigned *Indices, + const unsigned *IndicesEnd, + unsigned CurIndex = 0); + +/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of +/// EVTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// If Offsets is non-null, it points to a vector to be filled in +/// with the in-memory offsets of each of the individual values. +/// +void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, + SmallVectorImpl &ValueVTs, + SmallVectorImpl *Offsets = 0, + uint64_t StartingOffset = 0); + +/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. +GlobalVariable *ExtractTypeInfo(Value *V); + +/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being +/// processed uses a memory 'm' constraint. +bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, + const TargetLowering &TLI); + +/// getFCmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR floating-point condition code. This includes +/// consideration of global floating-point math flags. +/// +ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred); + +/// getICmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR integer condition code. +/// +ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); + +/// Test if the given instruction is in a position to be optimized +/// with a tail-call. This roughly means that it's in a block with +/// a return and there's nothing that needs to be scheduled +/// between it and the return. +/// +/// This function only tests target-independent requirements. +bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, + const TargetLowering &TLI); + +bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, + const TargetLowering &TLI); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/AsmPrinter.h b/final/include/llvm/CodeGen/AsmPrinter.h new file mode 100644 index 00000000000..a071febb102 --- /dev/null +++ b/final/include/llvm/CodeGen/AsmPrinter.h @@ -0,0 +1,462 @@ +//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class to be used as the base class for target specific +// asm writers. This class primarily handles common functionality used by +// all asm writers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ASMPRINTER_H +#define LLVM_CODEGEN_ASMPRINTER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class BlockAddress; + class GCStrategy; + class Constant; + class ConstantArray; + class ConstantFP; + class ConstantInt; + class ConstantStruct; + class ConstantVector; + class GCMetadataPrinter; + class GlobalValue; + class GlobalVariable; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class MachineLocation; + class MachineLoopInfo; + class MachineLoop; + class MachineConstantPool; + class MachineConstantPoolEntry; + class MachineConstantPoolValue; + class MachineJumpTableInfo; + class MachineModuleInfo; + class MachineMove; + class MCAsmInfo; + class MCInst; + class MCContext; + class MCSection; + class MCStreamer; + class MCSymbol; + class MDNode; + class DwarfDebug; + class DwarfException; + class Mangler; + class TargetLoweringObjectFile; + class TargetData; + class TargetMachine; + class Twine; + class Type; + + /// AsmPrinter - This class is intended to be used as a driving class for all + /// asm writers. + class AsmPrinter : public MachineFunctionPass { + public: + /// Target machine description. + /// + TargetMachine &TM; + + /// Target Asm Printer information. + /// + const MCAsmInfo *MAI; + + /// OutContext - This is the context for the output file that we are + /// streaming. This owns all of the global MC-related objects for the + /// generated translation unit. + MCContext &OutContext; + + /// OutStreamer - This is the MCStreamer object for the file we are + /// generating. This contains the transient state for the current + /// translation unit that we are generating (such as the current section + /// etc). + MCStreamer &OutStreamer; + + /// The current machine function. + const MachineFunction *MF; + + /// MMI - This is a pointer to the current MachineModuleInfo. + MachineModuleInfo *MMI; + + /// Name-mangler for global names. + /// + Mangler *Mang; + + /// The symbol for the current function. This is recalculated at the + /// beginning of each call to runOnMachineFunction(). + /// + MCSymbol *CurrentFnSym; + + private: + // GCMetadataPrinters - The garbage collection metadata printer table. + void *GCMetadataPrinters; // Really a DenseMap. + + /// VerboseAsm - Emit comments in assembly output if this is true. + /// + bool VerboseAsm; + static char ID; + + /// If VerboseAsm is set, a pointer to the loop info for this + /// function. + MachineLoopInfo *LI; + + /// DD - If the target supports dwarf debug info, this pointer is non-null. + DwarfDebug *DD; + + /// DE - If the target supports dwarf exception info, this pointer is + /// non-null. + DwarfException *DE; + + protected: + explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); + + public: + virtual ~AsmPrinter(); + + /// isVerbose - Return true if assembly output should contain comments. + /// + bool isVerbose() const { return VerboseAsm; } + + /// getFunctionNumber - Return a unique ID for the current function. + /// + unsigned getFunctionNumber() const; + + /// getObjFileLowering - Return information about object file lowering. + const TargetLoweringObjectFile &getObjFileLowering() const; + + /// getTargetData - Return information about data layout. + const TargetData &getTargetData() const; + + /// getCurrentSection() - Return the current section we are emitting to. + const MCSection *getCurrentSection() const; + + + //===------------------------------------------------------------------===// + // MachineFunctionPass Implementation. + //===------------------------------------------------------------------===// + + /// getAnalysisUsage - Record analysis usage. + /// + void getAnalysisUsage(AnalysisUsage &AU) const; + + /// doInitialization - Set up the AsmPrinter when we are working on a new + /// module. If your pass overrides this, it must make sure to explicitly + /// call this implementation. + bool doInitialization(Module &M); + + /// doFinalization - Shut down the asmprinter. If you override this in your + /// pass, you must make sure to call it explicitly. + bool doFinalization(Module &M); + + /// runOnMachineFunction - Emit the specified function out to the + /// OutStreamer. + virtual bool runOnMachineFunction(MachineFunction &MF) { + SetupMachineFunction(MF); + EmitFunctionHeader(); + EmitFunctionBody(); + return false; + } + + //===------------------------------------------------------------------===// + // Coarse grained IR lowering routines. + //===------------------------------------------------------------------===// + + /// SetupMachineFunction - This should be called when a new MachineFunction + /// is being processed from runOnMachineFunction. + void SetupMachineFunction(MachineFunction &MF); + + /// EmitFunctionHeader - This method emits the header for the current + /// function. + void EmitFunctionHeader(); + + /// EmitFunctionBody - This method emits the body and trailer for a + /// function. + void EmitFunctionBody(); + + /// EmitConstantPool - Print to the current output stream assembly + /// representations of the constants in the constant pool MCP. This is + /// used to print out constants which have been "spilled to memory" by + /// the code generator. + /// + virtual void EmitConstantPool(); + + /// EmitJumpTableInfo - Print assembly representations of the jump tables + /// used by the current function to the current output stream. + /// + void EmitJumpTableInfo(); + + /// EmitGlobalVariable - Emit the specified global variable to the .s file. + virtual void EmitGlobalVariable(const GlobalVariable *GV); + + /// EmitSpecialLLVMGlobal - Check to see if the specified global is a + /// special global used by LLVM. If so, emit it and return true, otherwise + /// do nothing and return false. + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + + /// EmitAlignment - Emit an alignment directive to the specified power of + /// two boundary. For example, if you pass in 3 here, you will get an 8 + /// byte alignment. If a global value is specified, and if that global has + /// an explicit alignment requested, it will override the alignment request + /// if required for correctness. + /// + void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const; + + /// EmitBasicBlockStart - This method prints the label for the specified + /// MachineBasicBlock, an alignment (if present) and a comment describing + /// it if appropriate. + void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; + + /// EmitGlobalConstant - Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0); + + + //===------------------------------------------------------------------===// + // Overridable Hooks + //===------------------------------------------------------------------===// + + // Targets can, or in the case of EmitInstruction, must implement these to + // customize output. + + /// EmitStartOfAsmFile - This virtual method can be overridden by targets + /// that want to emit something at the start of their file. + virtual void EmitStartOfAsmFile(Module &) {} + + /// EmitEndOfAsmFile - This virtual method can be overridden by targets that + /// want to emit something at the end of their file. + virtual void EmitEndOfAsmFile(Module &) {} + + /// EmitFunctionBodyStart - Targets can override this to emit stuff before + /// the first basic block in the function. + virtual void EmitFunctionBodyStart() {} + + /// EmitFunctionBodyEnd - Targets can override this to emit stuff after + /// the last basic block in the function. + virtual void EmitFunctionBodyEnd() {} + + /// EmitInstruction - Targets should implement this to emit instructions. + virtual void EmitInstruction(const MachineInstr *) { + assert(0 && "EmitInstruction not implemented"); + } + + virtual void EmitFunctionEntryLabel(); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + /// isBlockOnlyReachableByFallthough - Return true if the basic block has + /// exactly one predecessor and the control transfer mechanism between + /// the predecessor and this block is a fall-through. + virtual bool + isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + + //===------------------------------------------------------------------===// + // Symbol Lowering Routines. + //===------------------------------------------------------------------===// + public: + + /// GetTempSymbol - Return the MCSymbol corresponding to the assembler + /// temporary label with the specified stem and unique ID. + MCSymbol *GetTempSymbol(StringRef Name, unsigned ID) const; + + /// GetTempSymbol - Return an assembler temporary label with the specified + /// stem. + MCSymbol *GetTempSymbol(StringRef Name) const; + + + /// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with + /// global value name as its base, with the specified suffix, and where the + /// symbol is forced to have private linkage if ForcePrivate is true. + MCSymbol *GetSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix, + bool ForcePrivate = true) const; + + /// GetExternalSymbolSymbol - Return the MCSymbol for the specified + /// ExternalSymbol. + MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const; + + /// GetCPISymbol - Return the symbol for the specified constant pool entry. + MCSymbol *GetCPISymbol(unsigned CPID) const; + + /// GetJTISymbol - Return the symbol for the specified jump table entry. + MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const; + + /// GetJTSetSymbol - Return the symbol for the specified jump table .set + /// FIXME: privatize to AsmPrinter. + MCSymbol *GetJTSetSymbol(unsigned UID, unsigned MBBID) const; + + /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress + /// uses of the specified basic block. + MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; + MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const; + + //===------------------------------------------------------------------===// + // Emission Helper Routines. + //===------------------------------------------------------------------===// + public: + /// printOffset - This is just convenient handler for printing offsets. + void printOffset(int64_t Offset, raw_ostream &OS) const; + + /// EmitInt8 - Emit a byte directive and value. + /// + void EmitInt8(int Value) const; + + /// EmitInt16 - Emit a short directive and value. + /// + void EmitInt16(int Value) const; + + /// EmitInt32 - Emit a long directive and value. + /// + void EmitInt32(int Value) const; + + /// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size + /// in bytes of the directive is specified by Size and Hi/Lo specify the + /// labels. This implicitly uses .set if it is available. + void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) const; + + /// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo" + /// where the size in bytes of the directive is specified by Size and Hi/Lo + /// specify the labels. This implicitly uses .set if it is available. + void EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, + const MCSymbol *Lo, unsigned Size) const; + + /// EmitLabelPlusOffset - Emit something like ".long Label+Offset" + /// where the size in bytes of the directive is specified by Size and Label + /// specifies the label. This implicitly uses .set if it is available. + void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, + unsigned Size) const; + + //===------------------------------------------------------------------===// + // Dwarf Emission Helper Routines + //===------------------------------------------------------------------===// + + /// EmitSLEB128 - emit the specified signed leb128 value. + void EmitSLEB128(int Value, const char *Desc = 0) const; + + /// EmitULEB128 - emit the specified unsigned leb128 value. + void EmitULEB128(unsigned Value, const char *Desc = 0, + unsigned PadTo = 0) const; + + /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. + void EmitCFAByte(unsigned Val) const; + + /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an + /// encoding. If verbose assembly output is enabled, we output comments + /// describing the encoding. Desc is a string saying what the encoding is + /// specifying (e.g. "LSDA"). + void EmitEncodingByte(unsigned Val, const char *Desc = 0) const; + + /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned GetSizeOfEncodedValue(unsigned Encoding) const; + + /// EmitReference - Emit a reference to a label with a specified encoding. + /// + void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; + void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + + /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of + /// its section. This can be done with a special directive if the target + /// supports it (e.g. cygwin) or by emitting it as an offset from a label at + /// the start of the section. + /// + /// SectionLabel is a temporary label emitted at the start of the section + /// that Label lives in. + void EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const; + + /// getDebugValueLocation - Get location information encoded by DBG_VALUE + /// operands. + virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + + /// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa + /// encoding specified. + virtual unsigned getISAEncoding() { return 0; } + + //===------------------------------------------------------------------===// + // Dwarf Lowering Routines + //===------------------------------------------------------------------===// + + /// EmitFrameMoves - Emit frame instructions to describe the layout of the + /// frame. + void EmitFrameMoves(const std::vector &Moves, + MCSymbol *BaseLabel, bool isEH) const; + void EmitCFIFrameMoves(const std::vector &Moves) const; + + //===------------------------------------------------------------------===// + // Inline Asm Support + //===------------------------------------------------------------------===// + public: + // These are hooks that targets can override to implement inline asm + // support. These should probably be moved out of AsmPrinter someday. + + /// PrintSpecial - Print information related to the specified machine instr + /// that is independent of the operand, and may be independent of the instr + /// itself. This can be useful for portably encoding the comment character + /// or other bits of target-specific knowledge into the asmstrings. The + /// syntax used is ${:comment}. Targets can override this to add support + /// for their own strange codes. + virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, + const char *Code) const; + + /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant. Targets should + /// override this to format as appropriate. This method can return true if + /// the operand is erroneous. + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant as an address. + /// Targets should override this to format as appropriate. This method can + /// return true if the operand is erroneous. + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &OS); + + private: + /// Private state for PrintSpecial() + // Assign a unique ID to this machine instruction. + mutable const MachineInstr *LastMI; + mutable unsigned LastFn; + mutable unsigned Counter; + mutable unsigned SetCounter; + + /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. + void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0) const; + + /// EmitInlineAsm - This method formats and emits the specified machine + /// instruction that is an inline asm. + void EmitInlineAsm(const MachineInstr *MI) const; + + //===------------------------------------------------------------------===// + // Internal Implementation Details + //===------------------------------------------------------------------===// + + /// EmitVisibility - This emits visibility information about symbol, if + /// this is suported by the target. + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; + + void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const; + + void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned uid) const; + void EmitLLVMUsedList(Constant *List); + void EmitXXStructorList(Constant *List); + GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); + }; +} + +#endif diff --git a/final/include/llvm/CodeGen/BinaryObject.h b/final/include/llvm/CodeGen/BinaryObject.h new file mode 100644 index 00000000000..8c1431ffbee --- /dev/null +++ b/final/include/llvm/CodeGen/BinaryObject.h @@ -0,0 +1,353 @@ +//===-- llvm/CodeGen/BinaryObject.h - Binary Object. -----------*- 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 Binary Object Aka. "blob" for holding data from code +// generators, ready for data to the object module code writters. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BINARYOBJECT_H +#define LLVM_CODEGEN_BINARYOBJECT_H + +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/Support/DataTypes.h" + +#include +#include + +namespace llvm { + +typedef std::vector BinaryData; + +class BinaryObject { +protected: + std::string Name; + bool IsLittleEndian; + bool Is64Bit; + BinaryData Data; + std::vector Relocations; + +public: + /// Constructors and destructor + BinaryObject() {} + + BinaryObject(bool isLittleEndian, bool is64Bit) + : IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} + + BinaryObject(const std::string &name, bool isLittleEndian, bool is64Bit) + : Name(name), IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {} + + ~BinaryObject() {} + + /// getName - get name of BinaryObject + inline std::string getName() const { return Name; } + + /// get size of binary data + size_t size() const { + return Data.size(); + } + + /// get binary data + BinaryData& getData() { + return Data; + } + + /// get machine relocations + const std::vector& getRelocations() const { + return Relocations; + } + + /// hasRelocations - Return true if 'Relocations' is not empty + bool hasRelocations() const { + return !Relocations.empty(); + } + + /// emitZeros - This callback is invoked to emit a arbitrary number + /// of zero bytes to the data stream. + inline void emitZeros(unsigned Size) { + for (unsigned i=0; i < Size; ++i) + emitByte(0); + } + + /// emitByte - This callback is invoked when a byte needs to be + /// written to the data stream. + inline void emitByte(uint8_t B) { + Data.push_back(B); + } + + /// emitWord16 - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16(uint16_t W) { + if (IsLittleEndian) + emitWord16LE(W); + else + emitWord16BE(W); + } + + /// emitWord16LE - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16LE(uint16_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + } + + /// emitWord16BE - This callback is invoked when a 16-bit word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord16BE(uint16_t W) { + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// emitWord - This callback is invoked when a word needs to be + /// written to the data stream in correct endian format and correct size. + inline void emitWord(uint64_t W) { + if (!Is64Bit) + emitWord32(W); + else + emitWord64(W); + } + + /// emitWord32 - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in correct endian format. + inline void emitWord32(uint32_t W) { + if (IsLittleEndian) + emitWordLE(W); + else + emitWordBE(W); + } + + /// emitWord64 - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in correct endian format. + inline void emitWord64(uint64_t W) { + if (IsLittleEndian) + emitDWordLE(W); + else + emitDWordBE(W); + } + + /// emitWord64 - This callback is invoked when a x86_fp80 needs to be + /// written to the data stream in correct endian format. + inline void emitWordFP80(const uint64_t *W, unsigned PadSize) { + if (IsLittleEndian) { + emitWord64(W[0]); + emitWord16(W[1]); + } else { + emitWord16(W[1]); + emitWord64(W[0]); + } + emitZeros(PadSize); + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in little-endian format. + inline void emitWordLE(uint32_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in big-endian format. + /// + inline void emitWordBE(uint32_t W) { + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in little-endian format. + inline void emitDWordLE(uint64_t W) { + Data.push_back((uint8_t)(W >> 0)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 56)); + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in big-endian format. + inline void emitDWordBE(uint64_t W) { + Data.push_back((uint8_t)(W >> 56)); + Data.push_back((uint8_t)(W >> 48)); + Data.push_back((uint8_t)(W >> 40)); + Data.push_back((uint8_t)(W >> 32)); + Data.push_back((uint8_t)(W >> 24)); + Data.push_back((uint8_t)(W >> 16)); + Data.push_back((uint8_t)(W >> 8)); + Data.push_back((uint8_t)(W >> 0)); + } + + /// fixByte - This callback is invoked when a byte needs to be + /// fixup the buffer. + inline void fixByte(uint8_t B, uint32_t offset) { + Data[offset] = B; + } + + /// fixWord16 - This callback is invoked when a 16-bit word needs to + /// fixup the data stream in correct endian format. + inline void fixWord16(uint16_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord16LE(W, offset); + else + fixWord16BE(W, offset); + } + + /// emitWord16LE - This callback is invoked when a 16-bit word needs to + /// fixup the data stream in little endian format. + inline void fixWord16LE(uint16_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + } + + /// fixWord16BE - This callback is invoked when a 16-bit word needs to + /// fixup data stream in big endian format. + inline void fixWord16BE(uint16_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// emitWord - This callback is invoked when a word needs to + /// fixup the data in correct endian format and correct size. + inline void fixWord(uint64_t W, uint32_t offset) { + if (!Is64Bit) + fixWord32(W, offset); + else + fixWord64(W, offset); + } + + /// fixWord32 - This callback is invoked when a 32-bit word needs to + /// fixup the data in correct endian format. + inline void fixWord32(uint32_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord32LE(W, offset); + else + fixWord32BE(W, offset); + } + + /// fixWord32LE - This callback is invoked when a 32-bit word needs to + /// fixup the data in little endian format. + inline void fixWord32LE(uint32_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); + } + + /// fixWord32BE - This callback is invoked when a 32-bit word needs to + /// fixup the data in big endian format. + inline void fixWord32BE(uint32_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// fixWord64 - This callback is invoked when a 64-bit word needs to + /// fixup the data in correct endian format. + inline void fixWord64(uint64_t W, uint32_t offset) { + if (IsLittleEndian) + fixWord64LE(W, offset); + else + fixWord64BE(W, offset); + } + + /// fixWord64BE - This callback is invoked when a 64-bit word needs to + /// fixup the data in little endian format. + inline void fixWord64LE(uint64_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 0); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 56); + } + + /// fixWord64BE - This callback is invoked when a 64-bit word needs to + /// fixup the data in big endian format. + inline void fixWord64BE(uint64_t W, uint32_t offset) { + Data[offset] = (uint8_t)(W >> 56); + Data[++offset] = (uint8_t)(W >> 48); + Data[++offset] = (uint8_t)(W >> 40); + Data[++offset] = (uint8_t)(W >> 32); + Data[++offset] = (uint8_t)(W >> 24); + Data[++offset] = (uint8_t)(W >> 16); + Data[++offset] = (uint8_t)(W >> 8); + Data[++offset] = (uint8_t)(W >> 0); + } + + /// emitAlignment - Pad the data to the specified alignment. + void emitAlignment(unsigned Alignment, uint8_t fill = 0) { + if (Alignment <= 1) return; + unsigned PadSize = -Data.size() & (Alignment-1); + for (unsigned i = 0; i>= 7; + if (Value) Byte |= 0x80; + emitByte(Byte); + } while (Value); + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the data stream. + void emitSLEB128Bytes(int64_t Value) { + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = (uint8_t)(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the data stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); i hint_; + public: + VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, + const MachineLoopInfo &loops) : + mf_(mf), lis_(lis), loops_(loops) {} + + /// CalculateRegClass - recompute the register class for reg from its uses. + /// Since the register class can affect the allocation hint, this function + /// should be called before CalculateWeightAndHint if both are called. + void CalculateRegClass(unsigned reg); + + /// CalculateWeightAndHint - (re)compute li's spill weight and allocation + /// hint. + void CalculateWeightAndHint(LiveInterval &li); + }; + + /// CalculateSpillWeights - Compute spill weights for all virtual register + /// live intervals. + class CalculateSpillWeights : public MachineFunctionPass { + public: + static char ID; + + CalculateSpillWeights() : MachineFunctionPass(ID) { + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + + private: + /// Returns true if the given live interval is zero length. + bool isZeroLengthInterval(LiveInterval *li) const; + }; + +} + +#endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H diff --git a/final/include/llvm/CodeGen/CallingConvLower.h b/final/include/llvm/CodeGen/CallingConvLower.h new file mode 100644 index 00000000000..2a9bbdfb7ce --- /dev/null +++ b/final/include/llvm/CodeGen/CallingConvLower.h @@ -0,0 +1,300 @@ +//===-- llvm/CallingConvLower.h - 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 file declares the CCState and CCValAssign classes, used for lowering +// and implementing calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H +#define LLVM_CODEGEN_CALLINGCONVLOWER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Target/TargetCallingConv.h" +#include "llvm/CallingConv.h" + +namespace llvm { + class TargetRegisterInfo; + class TargetMachine; + class CCState; + +/// CCValAssign - Represent assignment of one arg/retval to a location. +class CCValAssign { +public: + enum LocInfo { + Full, // The value fills the full location. + SExt, // The value is sign extended in the location. + ZExt, // The value is zero extended in the location. + AExt, // The value is extended with undefined upper bits. + BCvt, // The value is bit-converted in the location. + VExt, // The value is vector-widened in the location. + // FIXME: Not implemented yet. Code that uses AExt to mean + // vector-widen should be fixed to use VExt instead. + Indirect // The location contains pointer to the value. + // TODO: a subset of the value is in the location. + }; +private: + /// ValNo - This is the value number begin assigned (e.g. an argument number). + unsigned ValNo; + + /// Loc is either a stack offset or a register number. + unsigned Loc; + + /// isMem - True if this is a memory loc, false if it is a register loc. + bool isMem : 1; + + /// isCustom - True if this arg/retval requires special handling. + bool isCustom : 1; + + /// Information about how the value is assigned. + LocInfo HTP : 6; + + /// ValVT - The type of the value being assigned. + MVT ValVT; + + /// LocVT - The type of the location being assigned to. + MVT LocVT; +public: + + static CCValAssign getReg(unsigned ValNo, MVT ValVT, + unsigned RegNo, MVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = RegNo; + Ret.isMem = false; + Ret.isCustom = false; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + + static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, + unsigned RegNo, MVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); + Ret.isCustom = true; + return Ret; + } + + static CCValAssign getMem(unsigned ValNo, MVT ValVT, + unsigned Offset, MVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = Offset; + Ret.isMem = true; + Ret.isCustom = false; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + + static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, + unsigned Offset, MVT LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); + Ret.isCustom = true; + return Ret; + } + + unsigned getValNo() const { return ValNo; } + MVT getValVT() const { return ValVT; } + + bool isRegLoc() const { return !isMem; } + bool isMemLoc() const { return isMem; } + + bool needsCustom() const { return isCustom; } + + unsigned getLocReg() const { assert(isRegLoc()); return Loc; } + unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + MVT getLocVT() const { return LocVT; } + + LocInfo getLocInfo() const { return HTP; } + bool isExtInLoc() const { + return (HTP == AExt || HTP == SExt || HTP == ZExt); + } + +}; + +/// CCAssignFn - This function assigns a location for Val, updating State to +/// reflect the change. It returns 'true' if it failed to handle Val. +typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); + +/// CCCustomFn - This function assigns a location for Val, possibly updating +/// all args to reflect changes and indicates if it handled it. It must set +/// isCustom if it handles the arg and returns true. +typedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT, + MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State); + +/// CCState - This class holds information needed while lowering arguments and +/// return values. It captures which registers are already assigned and which +/// stack slots are used. It provides accessors to allocate these values. +class CCState { + CallingConv::ID CallingConv; + bool IsVarArg; + const TargetMachine &TM; + const TargetRegisterInfo &TRI; + SmallVector &Locs; + LLVMContext &Context; + + unsigned StackOffset; + SmallVector UsedRegs; +public: + CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, + SmallVector &locs, LLVMContext &C); + + void addLoc(const CCValAssign &V) { + Locs.push_back(V); + } + + LLVMContext &getContext() const { return Context; } + const TargetMachine &getTarget() const { return TM; } + CallingConv::ID getCallingConv() const { return CallingConv; } + bool isVarArg() const { return IsVarArg; } + + unsigned getNextStackOffset() const { return StackOffset; } + + /// isAllocated - Return true if the specified register (or an alias) is + /// allocated. + bool isAllocated(unsigned Reg) const { + return UsedRegs[Reg/32] & (1 << (Reg&31)); + } + + /// AnalyzeFormalArguments - Analyze an array of argument values, + /// incorporating info about the formals into this state. + void AnalyzeFormalArguments(const SmallVectorImpl &Ins, + CCAssignFn Fn); + + /// AnalyzeReturn - Analyze the returned values of a return, + /// incorporating info about the result values into this state. + void AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn); + + /// CheckReturn - Analyze the return values of a function, returning + /// true if the return can be performed without sret-demotion, and + /// false otherwise. + bool CheckReturn(const SmallVectorImpl &ArgsFlags, + CCAssignFn Fn); + + /// AnalyzeCallOperands - Analyze the outgoing arguments to a call, + /// incorporating info about the passed values into this state. + void AnalyzeCallOperands(const SmallVectorImpl &Outs, + CCAssignFn Fn); + + /// AnalyzeCallOperands - Same as above except it takes vectors of types + /// and argument flags. + void AnalyzeCallOperands(SmallVectorImpl &ArgVTs, + SmallVectorImpl &Flags, + CCAssignFn Fn); + + /// AnalyzeCallResult - Analyze the return values of a call, + /// incorporating info about the passed values into this state. + void AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn); + + /// AnalyzeCallResult - Same as above except it's specialized for calls which + /// produce a single value. + void AnalyzeCallResult(MVT VT, CCAssignFn Fn); + + /// getFirstUnallocated - Return the first unallocated register in the set, or + /// NumRegs if they are all allocated. + unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const { + for (unsigned i = 0; i != NumRegs; ++i) + if (!isAllocated(Regs[i])) + return i; + return NumRegs; + } + + /// AllocateReg - Attempt to allocate one register. If it is not available, + /// return zero. Otherwise, return the register, marking it and any aliases + /// as allocated. + unsigned AllocateReg(unsigned Reg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with extra register to be shadowed. + unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateReg - Attempt to allocate one of the specified registers. If none + /// are available, return zero. Otherwise, return the first one available, + /// marking it and any aliases as allocated. + unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc]; + MarkAllocated(Reg); + return Reg; + } + + /// Version of AllocateReg with list of registers to be shadowed. + unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs, + unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc]; + MarkAllocated(Reg); + MarkAllocated(ShadowReg); + return Reg; + } + + /// AllocateStack - Allocate a chunk of stack space with the specified size + /// and alignment. + unsigned AllocateStack(unsigned Size, unsigned Align) { + assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + unsigned Result = StackOffset; + StackOffset += Size; + return Result; + } + + /// Version of AllocateStack with extra register to be shadowed. + unsigned AllocateStack(unsigned Size, unsigned Align, unsigned ShadowReg) { + MarkAllocated(ShadowReg); + return AllocateStack(Size, Align); + } + + // HandleByVal - Allocate a stack slot large enough to pass an argument by + // value. The size and alignment information of the argument is encoded in its + // parameter attribute. + void HandleByVal(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); + +private: + /// MarkAllocated - Mark a register and all of its aliases as allocated. + void MarkAllocated(unsigned Reg); +}; + + + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/EdgeBundles.h b/final/include/llvm/CodeGen/EdgeBundles.h new file mode 100644 index 00000000000..2c5215a7927 --- /dev/null +++ b/final/include/llvm/CodeGen/EdgeBundles.h @@ -0,0 +1,61 @@ +//===-------- EdgeBundles.h - Bundles of CFG edges --------------*- c++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The EdgeBundles analysis forms equivalence classes of CFG edges such that all +// edges leaving a machine basic block are in the same bundle, and all edges +// leaving a basic block are in the same bundle. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_EDGEBUNDLES_H +#define LLVM_CODEGEN_EDGEBUNDLES_H + +#include "llvm/ADT/IntEqClasses.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class EdgeBundles : public MachineFunctionPass { + const MachineFunction *MF; + + /// EC - Each edge bundle is an equivalence class. The keys are: + /// 2*BB->getNumber() -> Ingoing bundle. + /// 2*BB->getNumber()+1 -> Outgoing bundle. + IntEqClasses EC; + +public: + static char ID; + EdgeBundles() : MachineFunctionPass(ID) {} + + /// getBundle - Return the ingoing (Out = false) or outgoing (Out = true) + /// bundle number for basic block #N + unsigned getBundle(unsigned N, bool Out) const { return EC[2 * N + Out]; } + + /// getNumBundles - Return the total number of bundles in the CFG. + unsigned getNumBundles() const { return EC.getNumClasses(); } + + /// getMachineFunction - Return the last machine function computed. + const MachineFunction *getMachineFunction() const { return MF; } + + /// view - Visualize the annotated bipartite CFG with Graphviz. + void view() const; + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + +/// Specialize WriteGraph, the standard implementation won't work. +raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G, + bool ShortNames = false, + const std::string &Title = ""); + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/FastISel.h b/final/include/llvm/CodeGen/FastISel.h new file mode 100644 index 00000000000..fbb12005444 --- /dev/null +++ b/final/include/llvm/CodeGen/FastISel.h @@ -0,0 +1,348 @@ +//===-- FastISel.h - Definition of the FastISel class ---------------------===// +// +// 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 FastISel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FASTISEL_H +#define LLVM_CODEGEN_FASTISEL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" + +namespace llvm { + +class AllocaInst; +class ConstantFP; +class FunctionLoweringInfo; +class Instruction; +class MachineBasicBlock; +class MachineConstantPool; +class MachineFunction; +class MachineInstr; +class MachineFrameInfo; +class MachineRegisterInfo; +class TargetData; +class TargetInstrInfo; +class TargetLowering; +class TargetMachine; +class TargetRegisterClass; +class TargetRegisterInfo; +class LoadInst; + +/// FastISel - This is a fast-path instruction selection class that +/// generates poor code and doesn't support illegal types or non-trivial +/// lowering, but runs quickly. +class FastISel { +protected: + DenseMap LocalValueMap; + FunctionLoweringInfo &FuncInfo; + MachineRegisterInfo &MRI; + MachineFrameInfo &MFI; + MachineConstantPool &MCP; + DebugLoc DL; + const TargetMachine &TM; + const TargetData &TD; + const TargetInstrInfo &TII; + const TargetLowering &TLI; + const TargetRegisterInfo &TRI; + MachineInstr *LastLocalValue; + +public: + /// getLastLocalValue - Return the position of the last instruction + /// emitted for materializing constants for use in the current block. + MachineInstr *getLastLocalValue() { return LastLocalValue; } + + /// setLastLocalValue - Update the position of the last instruction + /// emitted for materializing constants for use in the current block. + void setLastLocalValue(MachineInstr *I) { LastLocalValue = I; } + + /// startNewBlock - Set the current block to which generated machine + /// instructions will be appended, and clear the local CSE map. + /// + void startNewBlock(); + + /// getCurDebugLoc() - Return current debug location information. + DebugLoc getCurDebugLoc() const { return DL; } + + /// SelectInstruction - Do "fast" instruction selection for the given + /// LLVM IR instruction, and append generated machine instructions to + /// the current block. Return true if selection was successful. + /// + bool SelectInstruction(const Instruction *I); + + /// SelectOperator - Do "fast" instruction selection for the given + /// LLVM IR operator (Instruction or ConstantExpr), and append + /// generated machine instructions to the current block. Return true + /// if selection was successful. + /// + bool SelectOperator(const User *I, unsigned Opcode); + + /// getRegForValue - Create a virtual register and arrange for it to + /// be assigned the value for the given LLVM value. + unsigned getRegForValue(const Value *V); + + /// lookUpRegForValue - Look up the value to see if its value is already + /// cached in a register. It may be defined by instructions across blocks or + /// defined locally. + unsigned lookUpRegForValue(const Value *V); + + /// getRegForGEPIndex - This is a wrapper around getRegForValue that also + /// takes care of truncating or sign-extending the given getelementptr + /// index value. + std::pair getRegForGEPIndex(const Value *V); + + /// TryToFoldLoad - The specified machine instr operand is a vreg, and that + /// vreg is being provided by the specified load instruction. If possible, + /// try to fold the load as an operand to the instruction, returning true if + /// possible. + virtual bool TryToFoldLoad(MachineInstr * /*MI*/, unsigned /*OpNo*/, + const LoadInst * /*LI*/) { + return false; + } + + /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions + /// into the current block. + void recomputeInsertPt(); + + struct SavePoint { + MachineBasicBlock::iterator InsertPt; + DebugLoc DL; + }; + + /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions + /// into the local value area and return the old insert position. + SavePoint enterLocalValueArea(); + + /// leaveLocalValueArea - Reset InsertPt to the given old insert position. + void leaveLocalValueArea(SavePoint Old); + + virtual ~FastISel(); + +protected: + explicit FastISel(FunctionLoweringInfo &funcInfo); + + /// TargetSelectInstruction - This method is called by target-independent + /// code when the normal FastISel process fails to select an instruction. + /// This gives targets a chance to emit code for anything that doesn't + /// fit into FastISel's framework. It returns true if it was successful. + /// + virtual bool + TargetSelectInstruction(const Instruction *I) = 0; + + /// FastEmit_r - This method is called by target-independent code + /// to request that an instruction with the given type and opcode + /// be emitted. + virtual unsigned FastEmit_(MVT VT, + MVT RetVT, + unsigned Opcode); + + /// FastEmit_r - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register operand be emitted. + /// + virtual unsigned FastEmit_r(MVT VT, + MVT RetVT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill); + + /// FastEmit_rr - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register operands be emitted. + /// + virtual unsigned FastEmit_rr(MVT VT, + MVT RetVT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); + + /// FastEmit_ri - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and immediate operands be emitted. + /// + virtual unsigned FastEmit_ri(MVT VT, + MVT RetVT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + uint64_t Imm); + + /// FastEmit_rf - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and floating-point immediate operands be emitted. + /// + virtual unsigned FastEmit_rf(MVT VT, + MVT RetVT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm); + + /// FastEmit_rri - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// register and immediate operands be emitted. + /// + virtual unsigned FastEmit_rri(MVT VT, + MVT RetVT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm); + + /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries + /// to emit an instruction with an immediate operand using FastEmit_ri. + /// If that fails, it materializes the immediate into a register and try + /// FastEmit_rr instead. + unsigned FastEmit_ri_(MVT VT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + uint64_t Imm, MVT ImmType); + + /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries + /// to emit an instruction with an immediate operand using FastEmit_rf. + /// If that fails, it materializes the immediate into a register and try + /// FastEmit_rr instead. + unsigned FastEmit_rf_(MVT VT, + unsigned Opcode, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm, MVT ImmType); + + /// FastEmit_i - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// immediate operand be emitted. + virtual unsigned FastEmit_i(MVT VT, + MVT RetVT, + unsigned Opcode, + uint64_t Imm); + + /// FastEmit_f - This method is called by target-independent code + /// to request that an instruction with the given type, opcode, and + /// floating-point immediate operand be emitted. + virtual unsigned FastEmit_f(MVT VT, + MVT RetVT, + unsigned Opcode, + const ConstantFP *FPImm); + + /// FastEmitInst_ - Emit a MachineInstr with no operands and a + /// result register in the given register class. + /// + unsigned FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass *RC); + + /// FastEmitInst_r - Emit a MachineInstr with one register operand + /// and a result register in the given register class. + /// + unsigned FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill); + + /// FastEmitInst_rr - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); + + /// FastEmitInst_ri - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm); + + /// FastEmitInst_rf - Emit a MachineInstr with two register operands + /// and a result register in the given register class. + /// + unsigned FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm); + + /// FastEmitInst_rri - Emit a MachineInstr with two register operands, + /// an immediate, and a result register in the given register class. + /// + unsigned FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm); + + /// FastEmitInst_i - Emit a MachineInstr with a single immediate + /// operand, and a result register in the given register class. + unsigned FastEmitInst_i(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, + uint64_t Imm); + + /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg + /// from a specified index of a superregister to a specified type. + unsigned FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, bool Op0IsKill, + uint32_t Idx); + + /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op + /// with all but the least significant bit set to zero. + unsigned FastEmitZExtFromI1(MVT VT, + unsigned Op0, bool Op0IsKill); + + /// FastEmitBranch - Emit an unconditional branch to the given block, + /// unless it is the immediate (fall-through) successor, and update + /// the CFG. + void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); + + unsigned UpdateValueMap(const Value* I, unsigned Reg); + + unsigned createResultReg(const TargetRegisterClass *RC); + + /// TargetMaterializeConstant - Emit a constant in a register using + /// target-specific logic, such as constant pool loads. + virtual unsigned TargetMaterializeConstant(const Constant* C) { + return 0; + } + + /// TargetMaterializeAlloca - Emit an alloca address in a register using + /// target-specific logic. + virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { + return 0; + } + +private: + bool SelectBinaryOp(const User *I, unsigned ISDOpcode); + + bool SelectFNeg(const User *I); + + bool SelectGetElementPtr(const User *I); + + bool SelectCall(const User *I); + + bool SelectBitCast(const User *I); + + bool SelectCast(const User *I, unsigned Opcode); + + /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. + /// Emit code to ensure constants are copied into registers when needed. + /// Remember the virtual registers that need to be added to the Machine PHI + /// nodes as input. We cannot just directly add them, because expansion + /// might result in multiple MBB's for one BB. As such, the start of the + /// BB might correspond to a different MBB than the end. + bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + + /// materializeRegForValue - Helper for getRegForVale. This function is + /// called when the value isn't already available in a register and must + /// be materialized with new instructions. + unsigned materializeRegForValue(const Value *V, MVT VT); + + /// hasTrivialKill - Test whether the given value has exactly one use. + bool hasTrivialKill(const Value *V) const; +}; + +} + +#endif diff --git a/final/include/llvm/CodeGen/FunctionLoweringInfo.h b/final/include/llvm/CodeGen/FunctionLoweringInfo.h new file mode 100644 index 00000000000..4421cc02d1c --- /dev/null +++ b/final/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -0,0 +1,224 @@ +//===-- FunctionLoweringInfo.h - Lower functions from LLVM IR to CodeGen --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating functions from LLVM IR into +// Machine IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H +#define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H + +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" +#ifndef NDEBUG +#include "llvm/ADT/SmallSet.h" +#endif +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include + +namespace llvm { + +class AllocaInst; +class BasicBlock; +class CallInst; +class Function; +class GlobalVariable; +class Instruction; +class MachineInstr; +class MachineBasicBlock; +class MachineFunction; +class MachineModuleInfo; +class MachineRegisterInfo; +class TargetLowering; +class Value; + +//===--------------------------------------------------------------------===// +/// FunctionLoweringInfo - This contains information that is global to a +/// function that is used when lowering a region of the function. +/// +class FunctionLoweringInfo { +public: + const TargetLowering &TLI; + const Function *Fn; + MachineFunction *MF; + MachineRegisterInfo *RegInfo; + + /// CanLowerReturn - true iff the function's return value can be lowered to + /// registers. + bool CanLowerReturn; + + /// DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg + /// allocated to hold a pointer to the hidden sret parameter. + unsigned DemoteRegister; + + /// MBBMap - A mapping from LLVM basic blocks to their machine code entry. + DenseMap MBBMap; + + /// ValueMap - Since we emit code for the function a basic block at a time, + /// we must remember which virtual registers hold the values for + /// cross-basic-block values. + DenseMap ValueMap; + + /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in + /// the entry block. This allows the allocas to be efficiently referenced + /// anywhere in the function. + DenseMap StaticAllocaMap; + + /// ByValArgFrameIndexMap - Keep track of frame indices for byval arguments. + DenseMap ByValArgFrameIndexMap; + + /// ArgDbgValues - A list of DBG_VALUE instructions created during isel for + /// function arguments that are inserted after scheduling is completed. + SmallVector ArgDbgValues; + + /// RegFixups - Registers which need to be replaced after isel is done. + DenseMap RegFixups; + + /// MBB - The current block. + MachineBasicBlock *MBB; + + /// MBB - The current insert position inside the current block. + MachineBasicBlock::iterator InsertPt; + +#ifndef NDEBUG + SmallSet CatchInfoLost; + SmallSet CatchInfoFound; +#endif + + struct LiveOutInfo { + unsigned NumSignBits : 31; + bool IsValid : 1; + APInt KnownOne, KnownZero; + LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0), + KnownZero(1, 0) {} + }; + + /// VisitedBBs - The set of basic blocks visited thus far by instruction + /// selection. + DenseSet VisitedBBs; + + /// PHINodesToUpdate - A list of phi instructions whose operand list will + /// be updated after processing the current basic block. + /// TODO: This isn't per-function state, it's per-basic-block state. But + /// there's no other convenient place for it to live right now. + std::vector > PHINodesToUpdate; + + explicit FunctionLoweringInfo(const TargetLowering &TLI); + + /// set - Initialize this FunctionLoweringInfo with the given Function + /// and its associated MachineFunction. + /// + void set(const Function &Fn, MachineFunction &MF); + + /// clear - Clear out all the function-specific state. This returns this + /// FunctionLoweringInfo to an empty state, ready to be used for a + /// different function. + void clear(); + + /// isExportedInst - Return true if the specified value is an instruction + /// exported from its block. + bool isExportedInst(const Value *V) { + return ValueMap.count(V); + } + + unsigned CreateReg(EVT VT); + + unsigned CreateRegs(const Type *Ty); + + unsigned InitializeRegForValue(const Value *V) { + unsigned &R = ValueMap[V]; + assert(R == 0 && "Already initialized this value register!"); + return R = CreateRegs(V->getType()); + } + + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) { + if (!LiveOutRegInfo.inBounds(Reg)) + return NULL; + + const LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; + if (!LOI->IsValid) + return NULL; + + return LOI; + } + + /// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the + /// register is a PHI destination and the PHI's LiveOutInfo is not valid. If + /// the register's LiveOutInfo is for a smaller bit width, it is extended to + /// the larger bit width by zero extension. The bit width must be no smaller + /// than the LiveOutInfo's existing bit width. + const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth); + + /// AddLiveOutRegInfo - Adds LiveOutInfo for a register. + void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits, + const APInt &KnownZero, const APInt &KnownOne) { + // Only install this information if it tells us something. + if (NumSignBits == 1 && KnownZero == 0 && KnownOne == 0) + return; + + LiveOutRegInfo.grow(Reg); + LiveOutInfo &LOI = LiveOutRegInfo[Reg]; + LOI.NumSignBits = NumSignBits; + LOI.KnownOne = KnownOne; + LOI.KnownZero = KnownZero; + } + + /// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination + /// register based on the LiveOutInfo of its operands. + void ComputePHILiveOutRegInfo(const PHINode*); + + /// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be + /// called when a block is visited before all of its predecessors. + void InvalidatePHILiveOutRegInfo(const PHINode *PN) { + // PHIs with no uses have no ValueMap entry. + DenseMap::const_iterator It = ValueMap.find(PN); + if (It == ValueMap.end()) + return; + + unsigned Reg = It->second; + LiveOutRegInfo.grow(Reg); + LiveOutRegInfo[Reg].IsValid = false; + } + + /// setByValArgumentFrameIndex - Record frame index for the byval + /// argument. + void setByValArgumentFrameIndex(const Argument *A, int FI); + + /// getByValArgumentFrameIndex - Get frame index for the byval argument. + int getByValArgumentFrameIndex(const Argument *A); + +private: + /// LiveOutRegInfo - Information about live out vregs. + IndexedMap LiveOutRegInfo; +}; + +/// AddCatchInfo - Extract the personality and type infos from an eh.selector +/// call, and add them to the specified machine basic block. +void AddCatchInfo(const CallInst &I, + MachineModuleInfo *MMI, MachineBasicBlock *MBB); + +/// CopyCatchInfo - Copy catch information from SuccBB (or one of its +/// successors) to LPad. +void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, + MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/GCMetadata.h b/final/include/llvm/CodeGen/GCMetadata.h new file mode 100644 index 00000000000..45469ed7de8 --- /dev/null +++ b/final/include/llvm/CodeGen/GCMetadata.h @@ -0,0 +1,193 @@ +//===-- GCMetadata.h - Garbage collector metadata ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the GCFunctionInfo and GCModuleInfo classes, which are +// used as a communication channel from the target code generator to the target +// garbage collectors. This interface allows code generators and garbage +// collectors to be developed independently. +// +// The GCFunctionInfo class logs the data necessary to build a type accurate +// stack map. The code generator outputs: +// +// - Safe points as specified by the GCStrategy's NeededSafePoints. +// - Stack offsets for GC roots, as specified by calls to llvm.gcroot +// +// As a refinement, liveness analysis calculates the set of live roots at each +// safe point. Liveness analysis is not presently performed by the code +// generator, so all roots are assumed live. +// +// GCModuleInfo simply collects GCFunctionInfo instances for each Function as +// they are compiled. This accretion is necessary for collectors which must emit +// a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo +// outlives the MachineFunction from which it is derived and must not refer to +// any code generator data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCMETADATA_H +#define LLVM_CODEGEN_GCMETADATA_H + +#include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + class AsmPrinter; + class GCStrategy; + class Constant; + class MCSymbol; + + namespace GC { + /// PointKind - The type of a collector-safe point. + /// + enum PointKind { + Loop, //< Instr is a loop (backwards branch). + Return, //< Instr is a return instruction. + PreCall, //< Instr is a call instruction. + PostCall //< Instr is the return address of a call. + }; + } + + /// GCPoint - Metadata for a collector-safe point in machine code. + /// + struct GCPoint { + GC::PointKind Kind; //< The kind of the safe point. + MCSymbol *Label; //< A label. + DebugLoc Loc; + + GCPoint(GC::PointKind K, MCSymbol *L, DebugLoc DL) + : Kind(K), Label(L), Loc(DL) {} + }; + + /// GCRoot - Metadata for a pointer to an object managed by the garbage + /// collector. + struct GCRoot { + int Num; //< Usually a frame index. + int StackOffset; //< Offset from the stack pointer. + const Constant *Metadata;//< Metadata straight from the call to llvm.gcroot. + + GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {} + }; + + + /// GCFunctionInfo - Garbage collection metadata for a single function. + /// + class GCFunctionInfo { + public: + typedef std::vector::iterator iterator; + typedef std::vector::iterator roots_iterator; + typedef std::vector::const_iterator live_iterator; + + private: + const Function &F; + GCStrategy &S; + uint64_t FrameSize; + std::vector Roots; + std::vector SafePoints; + + // FIXME: Liveness. A 2D BitVector, perhaps? + // + // BitVector Liveness; + // + // bool islive(int point, int root) = + // Liveness[point * SafePoints.size() + root] + // + // The bit vector is the more compact representation where >3.2% of roots + // are live per safe point (1.5% on 64-bit hosts). + + public: + GCFunctionInfo(const Function &F, GCStrategy &S); + ~GCFunctionInfo(); + + /// getFunction - Return the function to which this metadata applies. + /// + const Function &getFunction() const { return F; } + + /// getStrategy - Return the GC strategy for the function. + /// + GCStrategy &getStrategy() { return S; } + + /// addStackRoot - Registers a root that lives on the stack. Num is the + /// stack object ID for the alloca (if the code generator is + // using MachineFrameInfo). + void addStackRoot(int Num, const Constant *Metadata) { + Roots.push_back(GCRoot(Num, Metadata)); + } + + /// addSafePoint - Notes the existence of a safe point. Num is the ID of the + /// label just prior to the safe point (if the code generator is using + /// MachineModuleInfo). + void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { + SafePoints.push_back(GCPoint(Kind, Label, DL)); + } + + /// getFrameSize/setFrameSize - Records the function's frame size. + /// + uint64_t getFrameSize() const { return FrameSize; } + void setFrameSize(uint64_t S) { FrameSize = S; } + + /// begin/end - Iterators for safe points. + /// + iterator begin() { return SafePoints.begin(); } + iterator end() { return SafePoints.end(); } + size_t size() const { return SafePoints.size(); } + + /// roots_begin/roots_end - Iterators for all roots in the function. + /// + roots_iterator roots_begin() { return Roots.begin(); } + roots_iterator roots_end () { return Roots.end(); } + size_t roots_size() const { return Roots.size(); } + + /// live_begin/live_end - Iterators for live roots at a given safe point. + /// + live_iterator live_begin(const iterator &p) { return roots_begin(); } + live_iterator live_end (const iterator &p) { return roots_end(); } + size_t live_size(const iterator &p) const { return roots_size(); } + }; + + + /// GCModuleInfo - Garbage collection metadata for a whole module. + /// + class GCModuleInfo : public ImmutablePass { + typedef StringMap strategy_map_type; + typedef std::vector list_type; + typedef DenseMap finfo_map_type; + + strategy_map_type StrategyMap; + list_type StrategyList; + finfo_map_type FInfoMap; + + GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); + + public: + typedef list_type::const_iterator iterator; + + static char ID; + + GCModuleInfo(); + ~GCModuleInfo(); + + /// clear - Resets the pass. The metadata deleter pass calls this. + /// + void clear(); + + /// begin/end - Iterators for used strategies. + /// + iterator begin() const { return StrategyList.begin(); } + iterator end() const { return StrategyList.end(); } + + /// get - Look up function metadata. + /// + GCFunctionInfo &getFunctionInfo(const Function &F); + }; + +} + +#endif diff --git a/final/include/llvm/CodeGen/GCMetadataPrinter.h b/final/include/llvm/CodeGen/GCMetadataPrinter.h new file mode 100644 index 00000000000..17a26530000 --- /dev/null +++ b/final/include/llvm/CodeGen/GCMetadataPrinter.h @@ -0,0 +1,73 @@ +//===-- llvm/CodeGen/GCMetadataPrinter.h - Prints asm GC tables -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The abstract base class GCMetadataPrinter supports writing GC metadata tables +// as assembly code. This is a separate class from GCStrategy in order to allow +// users of the LLVM JIT to avoid linking with the AsmWriter. +// +// Subclasses of GCMetadataPrinter must be registered using the +// GCMetadataPrinterRegistry. This is separate from the GCStrategy itself +// because these subclasses are logically plugins for the AsmWriter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCMETADATAPRINTER_H +#define LLVM_CODEGEN_GCMETADATAPRINTER_H + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/Support/Registry.h" + +namespace llvm { + + class GCMetadataPrinter; + + /// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the + /// defaults from Registry. + typedef Registry GCMetadataPrinterRegistry; + + /// GCMetadataPrinter - Emits GC metadata as assembly code. + /// + class GCMetadataPrinter { + public: + typedef GCStrategy::list_type list_type; + typedef GCStrategy::iterator iterator; + + private: + GCStrategy *S; + + friend class AsmPrinter; + + protected: + // May only be subclassed. + GCMetadataPrinter(); + + // Do not implement. + GCMetadataPrinter(const GCMetadataPrinter &); + GCMetadataPrinter &operator=(const GCMetadataPrinter &); + + public: + GCStrategy &getStrategy() { return *S; } + const Module &getModule() const { return S->getModule(); } + + /// begin/end - Iterate over the collected function metadata. + iterator begin() { return S->begin(); } + iterator end() { return S->end(); } + + /// beginAssembly/finishAssembly - Emit module metadata as assembly code. + virtual void beginAssembly(AsmPrinter &AP); + + virtual void finishAssembly(AsmPrinter &AP); + + virtual ~GCMetadataPrinter(); + }; + +} + +#endif diff --git a/final/include/llvm/CodeGen/GCStrategy.h b/final/include/llvm/CodeGen/GCStrategy.h new file mode 100644 index 00000000000..cd760dba92a --- /dev/null +++ b/final/include/llvm/CodeGen/GCStrategy.h @@ -0,0 +1,142 @@ +//===-- llvm/CodeGen/GCStrategy.h - Garbage collection ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// GCStrategy coordinates code generation algorithms and implements some itself +// in order to generate code compatible with a target code generator as +// specified in a function's 'gc' attribute. Algorithms are enabled by setting +// flags in a subclass's constructor, and some virtual methods can be +// overridden. +// +// When requested, the GCStrategy will be populated with data about each +// function which uses it. Specifically: +// +// - Safe points +// Garbage collection is generally only possible at certain points in code. +// GCStrategy can request that the collector insert such points: +// +// - At and after any call to a subroutine +// - Before returning from the current function +// - Before backwards branches (loops) +// +// - Roots +// When a reference to a GC-allocated object exists on the stack, it must be +// stored in an alloca registered with llvm.gcoot. +// +// This information can used to emit the metadata tables which are required by +// the target garbage collector runtime. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCSTRATEGY_H +#define LLVM_CODEGEN_GCSTRATEGY_H + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/Support/Registry.h" +#include + +namespace llvm { + + class GCStrategy; + + /// The GC strategy registry uses all the defaults from Registry. + /// + typedef Registry GCRegistry; + + /// GCStrategy describes a garbage collector algorithm's code generation + /// requirements, and provides overridable hooks for those needs which cannot + /// be abstractly described. + class GCStrategy { + public: + typedef std::vector list_type; + typedef list_type::iterator iterator; + + private: + friend class GCModuleInfo; + const Module *M; + std::string Name; + + list_type Functions; + + protected: + unsigned NeededSafePoints; //< Bitmask of required safe points. + bool CustomReadBarriers; //< Default is to insert loads. + bool CustomWriteBarriers; //< Default is to insert stores. + bool CustomRoots; //< Default is to pass through to backend. + bool InitRoots; //< If set, roots are nulled during lowering. + bool UsesMetadata; //< If set, backend must emit metadata tables. + + public: + GCStrategy(); + + virtual ~GCStrategy(); + + + /// getName - The name of the GC strategy, for debugging. + /// + const std::string &getName() const { return Name; } + + /// getModule - The module within which the GC strategy is operating. + /// + const Module &getModule() const { return *M; } + + /// needsSafePoitns - True if safe points of any kind are required. By + // default, none are recorded. + bool needsSafePoints() const { return NeededSafePoints != 0; } + + /// needsSafePoint(Kind) - True if the given kind of safe point is + // required. By default, none are recorded. + bool needsSafePoint(GC::PointKind Kind) const { + return (NeededSafePoints & 1 << Kind) != 0; + } + + /// customWriteBarrier - By default, write barriers are replaced with simple + /// store instructions. If true, then + /// performCustomLowering must instead lower them. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// customReadBarrier - By default, read barriers are replaced with simple + /// load instructions. If true, then + /// performCustomLowering must instead lower them. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// customRoots - By default, roots are left for the code generator so it + /// can generate a stack map. If true, then + // performCustomLowering must delete them. + bool customRoots() const { return CustomRoots; } + + /// initializeRoots - If set, gcroot intrinsics should initialize their + // allocas to null before the first use. This is + // necessary for most GCs and is enabled by default. + bool initializeRoots() const { return InitRoots; } + + /// usesMetadata - If set, appropriate metadata tables must be emitted by + /// the back-end (assembler, JIT, or otherwise). + bool usesMetadata() const { return UsesMetadata; } + + /// begin/end - Iterators for function metadata. + /// + iterator begin() { return Functions.begin(); } + iterator end() { return Functions.end(); } + + /// insertFunctionMetadata - Creates metadata for a function. + /// + GCFunctionInfo *insertFunctionInfo(const Function &F); + + /// initializeCustomLowering/performCustomLowering - If any of the actions + /// are set to custom, performCustomLowering must be overriden to transform + /// the corresponding actions to LLVM IR. initializeCustomLowering is + /// optional to override. These are the only GCStrategy methods through + /// which the LLVM IR can be modified. + virtual bool initializeCustomLowering(Module &F); + virtual bool performCustomLowering(Function &F); + }; + +} + +#endif diff --git a/final/include/llvm/CodeGen/GCs.h b/final/include/llvm/CodeGen/GCs.h new file mode 100644 index 00000000000..c407b616748 --- /dev/null +++ b/final/include/llvm/CodeGen/GCs.h @@ -0,0 +1,35 @@ +//===-- GCs.h - Garbage collector linkage hacks ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains hack functions to force linking in the GC components. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GCS_H +#define LLVM_CODEGEN_GCS_H + +namespace llvm { + class GCStrategy; + class GCMetadataPrinter; + + /// FIXME: Collector instances are not useful on their own. These no longer + /// serve any purpose except to link in the plugins. + + /// Creates an ocaml-compatible garbage collector. + void linkOcamlGC(); + + /// Creates an ocaml-compatible metadata printer. + void linkOcamlGCPrinter(); + + /// Creates a shadow stack garbage collector. This collector requires no code + /// generator support. + void linkShadowStackGC(); +} + +#endif diff --git a/final/include/llvm/CodeGen/ISDOpcodes.h b/final/include/llvm/CodeGen/ISDOpcodes.h new file mode 100644 index 00000000000..3da11c4a0e0 --- /dev/null +++ b/final/include/llvm/CodeGen/ISDOpcodes.h @@ -0,0 +1,799 @@ +//===-- llvm/CodeGen/ISDOpcodes.h - CodeGen opcodes -------------*- 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 codegen opcodes and related utilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ISDOPCODES_H +#define LLVM_CODEGEN_ISDOPCODES_H + +namespace llvm { + +/// ISD namespace - This namespace contains an enum which represents all of the +/// SelectionDAG node types and value types. +/// +namespace ISD { + + //===--------------------------------------------------------------------===// + /// ISD::NodeType enum - This enum defines the target-independent operators + /// for a SelectionDAG. + /// + /// Targets may also define target-dependent operator codes for SDNodes. For + /// example, on x86, these are the enum values in the X86ISD namespace. + /// Targets should aim to use target-independent operators to model their + /// instruction sets as much as possible, and only use target-dependent + /// operators when they have special requirements. + /// + /// Finally, during and after selection proper, SNodes may use special + /// operator codes that correspond directly with MachineInstr opcodes. These + /// are used to represent selected instructions. See the isMachineOpcode() + /// and getMachineOpcode() member functions of SDNode. + /// + enum NodeType { + // DELETED_NODE - This is an illegal value that is used to catch + // errors. This opcode is not a legal opcode for any node. + DELETED_NODE, + + // EntryToken - This is the marker used to indicate the start of the region. + EntryToken, + + // TokenFactor - This node takes multiple tokens as input and produces a + // single token result. This is used to represent the fact that the operand + // operators are independent of each other. + TokenFactor, + + // AssertSext, AssertZext - These nodes record if a register contains a + // value that has already been zero or sign extended from a narrower type. + // These nodes take two operands. The first is the node that has already + // been extended, and the second is a value type node indicating the width + // of the extension + AssertSext, AssertZext, + + // Various leaf nodes. + BasicBlock, VALUETYPE, CONDCODE, Register, + Constant, ConstantFP, + GlobalAddress, GlobalTLSAddress, FrameIndex, + JumpTable, ConstantPool, ExternalSymbol, BlockAddress, + + // The address of the GOT + GLOBAL_OFFSET_TABLE, + + // FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and + // llvm.returnaddress on the DAG. These nodes take one operand, the index + // of the frame or return address to return. An index of zero corresponds + // to the current function's frame or return address, an index of one to the + // parent's frame or return address, and so on. + FRAMEADDR, RETURNADDR, + + // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to + // first (possible) on-stack argument. This is needed for correct stack + // adjustment during unwind. + FRAME_TO_ARGS_OFFSET, + + // RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the + // address of the exception block on entry to an landing pad block. + EXCEPTIONADDR, + + // RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the + // address of the Language Specific Data Area for the enclosing function. + LSDAADDR, + + // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents + // the selection index of the exception thrown. + EHSELECTION, + + // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents + // 'eh_return' gcc dwarf builtin, which is used to return from + // exception. The general meaning is: adjust stack by OFFSET and pass + // execution to HANDLER. Many platform-related details also :) + EH_RETURN, + + // OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) + // This corresponds to the eh.sjlj.setjmp intrinsic. + // It takes an input chain and a pointer to the jump buffer as inputs + // and returns an outchain. + EH_SJLJ_SETJMP, + + // OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) + // This corresponds to the eh.sjlj.longjmp intrinsic. + // It takes an input chain and a pointer to the jump buffer as inputs + // and returns an outchain. + EH_SJLJ_LONGJMP, + + // OUTCHAIN = EH_SJLJ_DISPATCHSETUP(INCHAIN, context) + // This corresponds to the eh.sjlj.dispatchsetup intrinsic. It takes an + // input chain and a pointer to the sjlj function context as inputs and + // returns an outchain. By default, this does nothing. Targets can lower + // this to unwind setup code if needed. + EH_SJLJ_DISPATCHSETUP, + + // TargetConstant* - Like Constant*, but the DAG does not do any folding, + // simplification, or lowering of the constant. They are used for constants + // which are known to fit in the immediate fields of their users, or for + // carrying magic numbers which are not values which need to be materialized + // in registers. + TargetConstant, + TargetConstantFP, + + // TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or + // anything else with this node, and this is valid in the target-specific + // dag, turning into a GlobalAddress operand. + TargetGlobalAddress, + TargetGlobalTLSAddress, + TargetFrameIndex, + TargetJumpTable, + TargetConstantPool, + TargetExternalSymbol, + TargetBlockAddress, + + /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with no side effects. + /// The first operand is the ID number of the intrinsic from the + /// llvm::Intrinsic namespace. The operands to the intrinsic follow. The + /// node returns the result of the intrinsic. + INTRINSIC_WO_CHAIN, + + /// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) + /// This node represents a target intrinsic function with side effects that + /// returns a result. The first operand is a chain pointer. The second is + /// the ID number of the intrinsic from the llvm::Intrinsic namespace. The + /// operands to the intrinsic follow. The node has two results, the result + /// of the intrinsic and an output chain. + INTRINSIC_W_CHAIN, + + /// OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with side effects that + /// does not return a result. The first operand is a chain pointer. The + /// second is the ID number of the intrinsic from the llvm::Intrinsic + /// namespace. The operands to the intrinsic follow. + INTRINSIC_VOID, + + // CopyToReg - This node has three operands: a chain, a register number to + // set to this value, and a value. + CopyToReg, + + // CopyFromReg - This node indicates that the input value is a virtual or + // physical register that is defined outside of the scope of this + // SelectionDAG. The register is available from the RegisterSDNode object. + CopyFromReg, + + // UNDEF - An undefined node + UNDEF, + + // EXTRACT_ELEMENT - This is used to get the lower or upper (determined by + // a Constant, which is required to be operand #1) half of the integer or + // float value specified as operand #0. This is only for use before + // legalization, for values that will be broken into multiple registers. + EXTRACT_ELEMENT, + + // BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given + // two values of the same integer value type, this produces a value twice as + // big. Like EXTRACT_ELEMENT, this can only be used before legalization. + BUILD_PAIR, + + // MERGE_VALUES - This node takes multiple discrete operands and returns + // them all as its individual results. This nodes has exactly the same + // number of inputs and outputs. This node is useful for some pieces of the + // code generator that want to think about a single node with multiple + // results, not multiple nodes. + MERGE_VALUES, + + // Simple integer binary arithmetic operators. + ADD, SUB, MUL, SDIV, UDIV, SREM, UREM, + + // SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing + // a signed/unsigned value of type i[2*N], and return the full value as + // two results, each of type iN. + SMUL_LOHI, UMUL_LOHI, + + // SDIVREM/UDIVREM - Divide two integers and produce both a quotient and + // remainder result. + SDIVREM, UDIVREM, + + // CARRY_FALSE - This node is used when folding other nodes, + // like ADDC/SUBC, which indicate the carry result is always false. + CARRY_FALSE, + + // Carry-setting nodes for multiple precision addition and subtraction. + // These nodes take two operands of the same value type, and produce two + // results. The first result is the normal add or sub result, the second + // result is the carry flag result. + ADDC, SUBC, + + // Carry-using nodes for multiple precision addition and subtraction. These + // nodes take three operands: The first two are the normal lhs and rhs to + // the add or sub, and the third is the input carry flag. These nodes + // produce two results; the normal result of the add or sub, and the output + // carry flag. These nodes both read and write a carry flag to allow them + // to them to be chained together for add and sub of arbitrarily large + // values. + ADDE, SUBE, + + // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. + // These nodes take two operands: the normal LHS and RHS to the add. They + // produce two results: the normal result of the add, and a boolean that + // indicates if an overflow occured (*not* a flag, because it may be stored + // to memory, etc.). If the type of the boolean is not i1 then the high + // bits conform to getBooleanContents. + // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. + SADDO, UADDO, + + // Same for subtraction + SSUBO, USUBO, + + // Same for multiplication + SMULO, UMULO, + + // Simple binary floating point operators. + FADD, FSUB, FMUL, FDIV, FREM, + + // FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This + // DAG node does not require that X and Y have the same type, just that they + // are both floating point. X and the result must have the same type. + // FCOPYSIGN(f32, f64) is allowed. + FCOPYSIGN, + + // INT = FGETSIGN(FP) - Return the sign bit of the specified floating point + // value as an integer 0/1 value. + FGETSIGN, + + /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the + /// specified, possibly variable, elements. The number of elements is + /// required to be a power of two. The types of the operands must all be + /// the same and must match the vector element type, except that integer + /// types are allowed to be larger than the element type, in which case + /// the operands are implicitly truncated. + BUILD_VECTOR, + + /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element + /// at IDX replaced with VAL. If the type of VAL is larger than the vector + /// element type then VAL is truncated before replacement. + INSERT_VECTOR_ELT, + + /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR + /// identified by the (potentially variable) element number IDX. If the + /// return type is an integer type larger than the element type of the + /// vector, the result is extended to the width of the return type. + EXTRACT_VECTOR_ELT, + + /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of + /// vector type with the same length and element type, this produces a + /// concatenated vector result value, with length equal to the sum of the + /// lengths of the input vectors. + CONCAT_VECTORS, + + /// INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector + /// with VECTOR2 inserted into VECTOR1 at the (potentially + /// variable) element number IDX, which must be a multiple of the + /// VECTOR2 vector length. The elements of VECTOR1 starting at + /// IDX are overwritten with VECTOR2. Elements IDX through + /// vector_length(VECTOR2) must be valid VECTOR1 indices. + INSERT_SUBVECTOR, + + /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an + /// vector value) starting with the element number IDX, which must be a + /// constant multiple of the result vector length. + EXTRACT_SUBVECTOR, + + /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as + /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int + /// values that indicate which value (or undef) each result element will + /// get. These constant ints are accessible through the + /// ShuffleVectorSDNode class. This is quite similar to the Altivec + /// 'vperm' instruction, except that the indices must be constants and are + /// in terms of the element size of VEC1/VEC2, not in terms of bytes. + VECTOR_SHUFFLE, + + /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a + /// scalar value into element 0 of the resultant vector type. The top + /// elements 1 to N-1 of the N-element vector are undefined. The type + /// of the operand must match the vector element type, except when they + /// are integer types. In this case the operand is allowed to be wider + /// than the vector element type, and is implicitly truncated to it. + SCALAR_TO_VECTOR, + + // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing + // an unsigned/signed value of type i[2*N], then return the top part. + MULHU, MULHS, + + /// Bitwise operators - logical and, logical or, logical xor. + AND, OR, XOR, + + /// Shift and rotation operations. After legalization, the type of the + /// shift amount is known to be TLI.getShiftAmountTy(). Before legalization + /// the shift amount can be any type, but care must be taken to ensure it is + /// large enough. TLI.getShiftAmountTy() is i8 on some targets, but before + /// legalization, types like i1024 can occur and i8 doesn't have enough bits + /// to represent the shift amount. By convention, DAGCombine and + /// SelectionDAGBuilder forces these shift amounts to i32 for simplicity. + /// + SHL, SRA, SRL, ROTL, ROTR, + + /// Byte Swap and Counting operators. + BSWAP, CTTZ, CTLZ, CTPOP, + + // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not + // i1 then the high bits must conform to getBooleanContents. + SELECT, + + // Select with condition operator - This selects between a true value and + // a false value (ops #2 and #3) based on the boolean result of comparing + // the lhs and rhs (ops #0 and #1) of a conditional expression with the + // condition code in op #4, a CondCodeSDNode. + SELECT_CC, + + // SetCC operator - This evaluates to a true value iff the condition is + // true. If the result value type is not i1 then the high bits conform + // to getBooleanContents. The operands to this are the left and right + // operands to compare (ops #0, and #1) and the condition code to compare + // them with (op #2) as a CondCodeSDNode. + SETCC, + + // RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of + // integer elements with all bits of the result elements set to true if the + // comparison is true or all cleared if the comparison is false. The + // operands to this are the left and right operands to compare (LHS/RHS) and + // the condition code to compare them with (COND) as a CondCodeSDNode. + VSETCC, + + // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded + // integer shift operations, just like ADD/SUB_PARTS. The operation + // ordering is: + // [Lo,Hi] = op [LoLHS,HiLHS], Amt + SHL_PARTS, SRA_PARTS, SRL_PARTS, + + // Conversion operators. These are all single input single output + // operations. For all of these, the result type must be strictly + // wider or narrower (depending on the operation) than the source + // type. + + // SIGN_EXTEND - Used for integer types, replicating the sign bit + // into new bits. + SIGN_EXTEND, + + // ZERO_EXTEND - Used for integer types, zeroing the new bits. + ZERO_EXTEND, + + // ANY_EXTEND - Used for integer types. The high bits are undefined. + ANY_EXTEND, + + // TRUNCATE - Completely drop the high bits. + TRUNCATE, + + // [SU]INT_TO_FP - These operators convert integers (whose interpreted sign + // depends on the first letter) to floating point. + SINT_TO_FP, + UINT_TO_FP, + + // SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to + // sign extend a small value in a large integer register (e.g. sign + // extending the low 8 bits of a 32-bit register to fill the top 24 bits + // with the 7th bit). The size of the smaller type is indicated by the 1th + // operand, a ValueType node. + SIGN_EXTEND_INREG, + + /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned + /// integer. + FP_TO_SINT, + FP_TO_UINT, + + /// X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type + /// down to the precision of the destination VT. TRUNC is a flag, which is + /// always an integer that is zero or one. If TRUNC is 0, this is a + /// normal rounding, if it is 1, this FP_ROUND is known to not change the + /// value of Y. + /// + /// The TRUNC = 1 case is used in cases where we know that the value will + /// not be modified by the node, because Y is not using any of the extra + /// precision of source type. This allows certain transformations like + /// FP_EXTEND(FP_ROUND(X,1)) -> X which are not safe for + /// FP_EXTEND(FP_ROUND(X,0)) because the extra bits aren't removed. + FP_ROUND, + + // FLT_ROUNDS_ - Returns current rounding mode: + // -1 Undefined + // 0 Round to 0 + // 1 Round to nearest + // 2 Round to +inf + // 3 Round to -inf + FLT_ROUNDS_, + + /// X = FP_ROUND_INREG(Y, VT) - This operator takes an FP register, and + /// rounds it to a floating point value. It then promotes it and returns it + /// in a register of the same size. This operation effectively just + /// discards excess precision. The type to round down to is specified by + /// the VT operand, a VTSDNode. + FP_ROUND_INREG, + + /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. + FP_EXTEND, + + // BITCAST - This operator converts between integer, vector and FP + // values, as if the value was stored to memory with one type and loaded + // from the same address with the other type (or equivalently for vector + // format conversions, etc). The source and result are required to have + // the same bit size (e.g. f32 <-> i32). This can also be used for + // int-to-int or fp-to-fp conversions, but that is a noop, deleted by + // getNode(). + BITCAST, + + // CONVERT_RNDSAT - This operator is used to support various conversions + // between various types (float, signed, unsigned and vectors of those + // types) with rounding and saturation. NOTE: Avoid using this operator as + // most target don't support it and the operator might be removed in the + // future. It takes the following arguments: + // 0) value + // 1) dest type (type to convert to) + // 2) src type (type to convert from) + // 3) rounding imm + // 4) saturation imm + // 5) ISD::CvtCode indicating the type of conversion to do + CONVERT_RNDSAT, + + // FP16_TO_FP32, FP32_TO_FP16 - These operators are used to perform + // promotions and truncation for half-precision (16 bit) floating + // numbers. We need special nodes since FP16 is a storage-only type with + // special semantics of operations. + FP16_TO_FP32, FP32_TO_FP16, + + // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + // FLOG, FLOG2, FLOG10, FEXP, FEXP2, + // FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary floating + // point operations. These are inspired by libm. + FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, + FLOG, FLOG2, FLOG10, FEXP, FEXP2, + FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR, + + // LOAD and STORE have token chains as their first operand, then the same + // operands as an LLVM load/store instruction, then an offset node that + // is added / subtracted from the base pointer to form the address (for + // indexed memory ops). + LOAD, STORE, + + // DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned + // to a specified boundary. This node always has two return values: a new + // stack pointer value and a chain. The first operand is the token chain, + // the second is the number of bytes to allocate, and the third is the + // alignment boundary. The size is guaranteed to be a multiple of the stack + // alignment, and the alignment is guaranteed to be bigger than the stack + // alignment (if required) or 0 to get standard stack alignment. + DYNAMIC_STACKALLOC, + + // Control flow instructions. These all have token chains. + + // BR - Unconditional branch. The first operand is the chain + // operand, the second is the MBB to branch to. + BR, + + // BRIND - Indirect branch. The first operand is the chain, the second + // is the value to branch to, which must be of the same type as the target's + // pointer type. + BRIND, + + // BR_JT - Jumptable branch. The first operand is the chain, the second + // is the jumptable index, the last one is the jumptable entry index. + BR_JT, + + // BRCOND - Conditional branch. The first operand is the chain, the + // second is the condition, the third is the block to branch to if the + // condition is true. If the type of the condition is not i1, then the + // high bits must conform to getBooleanContents. + BRCOND, + + // BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in + // that the condition is represented as condition code, and two nodes to + // compare, rather than as a combined SetCC node. The operands in order are + // chain, cc, lhs, rhs, block to branch to if condition is true. + BR_CC, + + // INLINEASM - Represents an inline asm block. This node always has two + // return values: a chain and a flag result. The inputs are as follows: + // Operand #0 : Input chain. + // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. + // Operand #2 : a MDNodeSDNode with the !srcloc metadata. + // Operand #3 : HasSideEffect, IsAlignStack bits. + // After this, it is followed by a list of operands with this format: + // ConstantSDNode: Flags that encode whether it is a mem or not, the + // of operands that follow, etc. See InlineAsm.h. + // ... however many operands ... + // Operand #last: Optional, an incoming flag. + // + // The variable width operands are required to represent target addressing + // modes as a single "operand", even though they may have multiple + // SDOperands. + INLINEASM, + + // EH_LABEL - Represents a label in mid basic block used to track + // locations needed for debug and exception handling tables. These nodes + // take a chain as input and return a chain. + EH_LABEL, + + // STACKSAVE - STACKSAVE has one operand, an input chain. It produces a + // value, the same type as the pointer type for the system, and an output + // chain. + STACKSAVE, + + // STACKRESTORE has two operands, an input chain and a pointer to restore to + // it returns an output chain. + STACKRESTORE, + + // CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of + // a call sequence, and carry arbitrary information that target might want + // to know. The first operand is a chain, the rest are specified by the + // target and not touched by the DAG optimizers. + // CALLSEQ_START..CALLSEQ_END pairs may not be nested. + CALLSEQ_START, // Beginning of a call sequence + CALLSEQ_END, // End of a call sequence + + // VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, + // and the alignment. It returns a pair of values: the vaarg value and a + // new chain. + VAARG, + + // VACOPY - VACOPY has five operands: an input chain, a destination pointer, + // a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the + // source. + VACOPY, + + // VAEND, VASTART - VAEND and VASTART have three operands: an input chain, a + // pointer, and a SRCVALUE. + VAEND, VASTART, + + // SRCVALUE - This is a node type that holds a Value* that is used to + // make reference to a value in the LLVM IR. + SRCVALUE, + + // MDNODE_SDNODE - This is a node that holdes an MDNode*, which is used to + // reference metadata in the IR. + MDNODE_SDNODE, + + // PCMARKER - This corresponds to the pcmarker intrinsic. + PCMARKER, + + // READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. + // The only operand is a chain and a value and a chain are produced. The + // value is the contents of the architecture specific cycle counter like + // register (or other high accuracy low latency clock source) + READCYCLECOUNTER, + + // HANDLENODE node - Used as a handle for various purposes. + HANDLENODE, + + // TRAMPOLINE - This corresponds to the init_trampoline intrinsic. + // It takes as input a token chain, the pointer to the trampoline, + // the pointer to the nested function, the pointer to pass for the + // 'nest' parameter, a SRCVALUE for the trampoline and another for + // the nested function (allowing targets to access the original + // Function*). It produces the result of the intrinsic and a token + // chain as output. + TRAMPOLINE, + + // TRAP - Trapping instruction + TRAP, + + // PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are + // their first operand. The other operands are the address to prefetch, + // read / write specifier, and locality specifier. + PREFETCH, + + // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, + // store-store, device) + // This corresponds to the memory.barrier intrinsic. + // it takes an input chain, 4 operands to specify the type of barrier, an + // operand specifying if the barrier applies to device and uncached memory + // and produces an output chain. + MEMBARRIER, + + // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) + // this corresponds to the atomic.lcs intrinsic. + // cmp is compared to *ptr, and if equal, swap is stored in *ptr. + // the return is always the original value in *ptr + ATOMIC_CMP_SWAP, + + // Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) + // this corresponds to the atomic.swap intrinsic. + // amt is stored to *ptr atomically. + // the return is always the original value in *ptr + ATOMIC_SWAP, + + // Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) + // this corresponds to the atomic.load.[OpName] intrinsic. + // op(*ptr, amt) is stored to *ptr atomically. + // the return is always the original value in *ptr + ATOMIC_LOAD_ADD, + ATOMIC_LOAD_SUB, + ATOMIC_LOAD_AND, + ATOMIC_LOAD_OR, + ATOMIC_LOAD_XOR, + ATOMIC_LOAD_NAND, + ATOMIC_LOAD_MIN, + ATOMIC_LOAD_MAX, + ATOMIC_LOAD_UMIN, + ATOMIC_LOAD_UMAX, + + /// BUILTIN_OP_END - This must be the last enum value in this list. + /// The target-specific pre-isel opcode values start here. + BUILTIN_OP_END + }; + + /// FIRST_TARGET_MEMORY_OPCODE - Target-specific pre-isel operations + /// which do not reference a specific memory location should be less than + /// this value. Those that do must not be less than this value, and can + /// be used with SelectionDAG::getMemIntrinsicNode. + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+150; + + //===--------------------------------------------------------------------===// + /// MemIndexedMode enum - This enum defines the load / store indexed + /// addressing modes. + /// + /// UNINDEXED "Normal" load / store. The effective address is already + /// computed and is available in the base pointer. The offset + /// operand is always undefined. In addition to producing a + /// chain, an unindexed load produces one value (result of the + /// load); an unindexed store does not produce a value. + /// + /// PRE_INC Similar to the unindexed mode where the effective address is + /// PRE_DEC the value of the base pointer add / subtract the offset. + /// It considers the computation as being folded into the load / + /// store operation (i.e. the load / store does the address + /// computation as well as performing the memory transaction). + /// The base operand is always undefined. In addition to + /// producing a chain, pre-indexed load produces two values + /// (result of the load and the result of the address + /// computation); a pre-indexed store produces one value (result + /// of the address computation). + /// + /// POST_INC The effective address is the value of the base pointer. The + /// POST_DEC value of the offset operand is then added to / subtracted + /// from the base after memory transaction. In addition to + /// producing a chain, post-indexed load produces two values + /// (the result of the load and the result of the base +/- offset + /// computation); a post-indexed store produces one value (the + /// the result of the base +/- offset computation). + enum MemIndexedMode { + UNINDEXED = 0, + PRE_INC, + PRE_DEC, + POST_INC, + POST_DEC, + LAST_INDEXED_MODE + }; + + //===--------------------------------------------------------------------===// + /// LoadExtType enum - This enum defines the three variants of LOADEXT + /// (load with extension). + /// + /// SEXTLOAD loads the integer operand and sign extends it to a larger + /// integer result type. + /// ZEXTLOAD loads the integer operand and zero extends it to a larger + /// integer result type. + /// EXTLOAD is used for two things: floating point extending loads and + /// integer extending loads [the top bits are undefined]. + enum LoadExtType { + NON_EXTLOAD = 0, + EXTLOAD, + SEXTLOAD, + ZEXTLOAD, + LAST_LOADEXT_TYPE + }; + + //===--------------------------------------------------------------------===// + /// ISD::CondCode enum - These are ordered carefully to make the bitfields + /// below work out, when considering SETFALSE (something that never exists + /// dynamically) as 0. "U" -> Unsigned (for integer operands) or Unordered + /// (for floating point), "L" -> Less than, "G" -> Greater than, "E" -> Equal + /// to. If the "N" column is 1, the result of the comparison is undefined if + /// the input is a NAN. + /// + /// All of these (except for the 'always folded ops') should be handled for + /// floating point. For integer, only the SETEQ,SETNE,SETLT,SETLE,SETGT, + /// SETGE,SETULT,SETULE,SETUGT, and SETUGE opcodes are used. + /// + /// Note that these are laid out in a specific order to allow bit-twiddling + /// to transform conditions. + enum CondCode { + // Opcode N U L G E Intuitive operation + SETFALSE, // 0 0 0 0 Always false (always folded) + SETOEQ, // 0 0 0 1 True if ordered and equal + SETOGT, // 0 0 1 0 True if ordered and greater than + SETOGE, // 0 0 1 1 True if ordered and greater than or equal + SETOLT, // 0 1 0 0 True if ordered and less than + SETOLE, // 0 1 0 1 True if ordered and less than or equal + SETONE, // 0 1 1 0 True if ordered and operands are unequal + SETO, // 0 1 1 1 True if ordered (no nans) + SETUO, // 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + SETUEQ, // 1 0 0 1 True if unordered or equal + SETUGT, // 1 0 1 0 True if unordered or greater than + SETUGE, // 1 0 1 1 True if unordered, greater than, or equal + SETULT, // 1 1 0 0 True if unordered or less than + SETULE, // 1 1 0 1 True if unordered, less than, or equal + SETUNE, // 1 1 1 0 True if unordered or not equal + SETTRUE, // 1 1 1 1 Always true (always folded) + // Don't care operations: undefined if the input is a nan. + SETFALSE2, // 1 X 0 0 0 Always false (always folded) + SETEQ, // 1 X 0 0 1 True if equal + SETGT, // 1 X 0 1 0 True if greater than + SETGE, // 1 X 0 1 1 True if greater than or equal + SETLT, // 1 X 1 0 0 True if less than + SETLE, // 1 X 1 0 1 True if less than or equal + SETNE, // 1 X 1 1 0 True if not equal + SETTRUE2, // 1 X 1 1 1 Always true (always folded) + + SETCC_INVALID // Marker value. + }; + + /// isSignedIntSetCC - Return true if this is a setcc instruction that + /// performs a signed comparison when used with integer operands. + inline bool isSignedIntSetCC(CondCode Code) { + return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE; + } + + /// isUnsignedIntSetCC - Return true if this is a setcc instruction that + /// performs an unsigned comparison when used with integer operands. + inline bool isUnsignedIntSetCC(CondCode Code) { + return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; + } + + /// isTrueWhenEqual - Return true if the specified condition returns true if + /// the two operands to the condition are equal. Note that if one of the two + /// operands is a NaN, this value is meaningless. + inline bool isTrueWhenEqual(CondCode Cond) { + return ((int)Cond & 1) != 0; + } + + /// getUnorderedFlavor - This function returns 0 if the condition is always + /// false if an operand is a NaN, 1 if the condition is always true if the + /// operand is a NaN, and 2 if the condition is undefined if the operand is a + /// NaN. + inline unsigned getUnorderedFlavor(CondCode Cond) { + return ((int)Cond >> 3) & 3; + } + + /// getSetCCInverse - Return the operation corresponding to !(X op Y), where + /// 'op' is a valid SetCC operation. + CondCode getSetCCInverse(CondCode Operation, bool isInteger); + + /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) + /// when given the operation for (X op Y). + CondCode getSetCCSwappedOperands(CondCode Operation); + + /// getSetCCOrOperation - Return the result of a logical OR between different + /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger); + + /// getSetCCAndOperation - Return the result of a logical AND between + /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger); + + //===--------------------------------------------------------------------===// + /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT + /// supports. + enum CvtCode { + CVT_FF, // Float from Float + CVT_FS, // Float from Signed + CVT_FU, // Float from Unsigned + CVT_SF, // Signed from Float + CVT_UF, // Unsigned from Float + CVT_SS, // Signed from Signed + CVT_SU, // Signed from Unsigned + CVT_US, // Unsigned from Signed + CVT_UU, // Unsigned from Unsigned + CVT_INVALID // Marker - Invalid opcode + }; + +} // end llvm::ISD namespace + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/IntrinsicLowering.h b/final/include/llvm/CodeGen/IntrinsicLowering.h new file mode 100644 index 00000000000..767b6662254 --- /dev/null +++ b/final/include/llvm/CodeGen/IntrinsicLowering.h @@ -0,0 +1,59 @@ +//===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- 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 IntrinsicLowering interface. This interface allows +// addition of domain-specific or front-end specific intrinsics to LLVM without +// having to modify all of the C backend or interpreter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_INTRINSICLOWERING_H +#define LLVM_CODEGEN_INTRINSICLOWERING_H + +#include "llvm/Intrinsics.h" + +namespace llvm { + class CallInst; + class Module; + class TargetData; + + class IntrinsicLowering { + const TargetData& TD; + + + bool Warned; + public: + explicit IntrinsicLowering(const TargetData &td) : + TD(td), Warned(false) {} + + /// AddPrototypes - This method, if called, causes all of the prototypes + /// that might be needed by an intrinsic lowering implementation to be + /// inserted into the module specified. + void AddPrototypes(Module &M); + + /// LowerIntrinsicCall - This method replaces a call with the LLVM function + /// which should be used to implement the specified intrinsic function call. + /// If an intrinsic function must be implemented by the code generator + /// (such as va_start), this function should print a message and abort. + /// + /// Otherwise, if an intrinsic function call can be lowered, the code to + /// implement it (often a call to a non-intrinsic function) is inserted + /// _after_ the call instruction and the call is deleted. The caller must + /// be capable of handling this kind of change. + /// + void LowerIntrinsicCall(CallInst *CI); + + /// LowerToByteSwap - Replace a call instruction into a call to bswap + /// intrinsic. Return false if it has determined the call is not a + /// simple integer bswap. + static bool LowerToByteSwap(CallInst *CI); + }; +} + +#endif diff --git a/final/include/llvm/CodeGen/JITCodeEmitter.h b/final/include/llvm/CodeGen/JITCodeEmitter.h new file mode 100644 index 00000000000..fea85230515 --- /dev/null +++ b/final/include/llvm/CodeGen/JITCodeEmitter.h @@ -0,0 +1,343 @@ +//===-- llvm/CodeGen/JITCodeEmitter.h - Code emission ----------*- 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 an abstract interface that is used by the machine code +// emission framework to output the code. This allows machine code emission to +// be separated from concerns such as resolution of call targets, and where the +// machine code will be written (memory or disk, f.e.). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_JITCODEEMITTER_H +#define LLVM_CODEGEN_JITCODEEMITTER_H + +#include +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/ADT/DenseMap.h" + +using namespace std; + +namespace llvm { + +class MachineBasicBlock; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineFunction; +class MachineModuleInfo; +class MachineRelocation; +class Value; +class GlobalValue; +class Function; + +/// JITCodeEmitter - This class defines two sorts of methods: those for +/// emitting the actual bytes of machine code, and those for emitting auxillary +/// structures, such as jump tables, relocations, etc. +/// +/// Emission of machine code is complicated by the fact that we don't (in +/// general) know the size of the machine code that we're about to emit before +/// we emit it. As such, we preallocate a certain amount of memory, and set the +/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we +/// emit machine instructions, we advance the CurBufferPtr to indicate the +/// location of the next byte to emit. In the case of a buffer overflow (we +/// need to emit more machine code than we have allocated space for), the +/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire +/// function has been emitted, the overflow condition is checked, and if it has +/// occurred, more memory is allocated, and we reemit the code into it. +/// +class JITCodeEmitter : public MachineCodeEmitter { +public: + virtual ~JITCodeEmitter() {} + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + /// + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + /// + virtual bool finishFunction(MachineFunction &F) = 0; + + /// allocIndirectGV - Allocates and fills storage for an indirect + /// GlobalValue, and returns the address. + virtual void *allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment) = 0; + + /// emitByte - This callback is invoked when a byte needs to be written to the + /// output stream. + /// + void emitByte(uint8_t B) { + if (CurBufferPtr != BufferEnd) + *CurBufferPtr++ = B; + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitWordLE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitWordBE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitDWordLE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 56); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitDWordBE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitAlignment - Move the CurBufferPtr pointer up to the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + CurBufferPtr = std::min(NewPtr, BufferEnd); + } + + /// emitAlignmentWithFill - Similar to emitAlignment, except that the + /// extra bytes are filled with the provided byte. + void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) { + if (Alignment == 0) Alignment = 1; + uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, + Alignment); + // Fail if we don't have room. + if (NewPtr > BufferEnd) { + CurBufferPtr = BufferEnd; + return; + } + while (CurBufferPtr < NewPtr) { + *CurBufferPtr++ = Fill; + } + } + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the output stream. + void emitULEB128Bytes(uint64_t Value, unsigned PadTo = 0) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value || PadTo != 0) Byte |= 0x80; + emitByte(Byte); + } while (Value); + + if (PadTo) { + do { + uint8_t Byte = (PadTo > 1) ? 0x80 : 0x0; + emitByte(Byte); + } while (--PadTo); + } + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the output stream. + void emitSLEB128Bytes(int64_t Value) { + int32_t Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the output stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); + i < N; ++i) { + uint8_t C = String[i]; + emitByte(C); + } + emitByte(0); + } + + /// emitInt32 - Emit a int32 directive. + void emitInt32(uint32_t Value) { + if (4 <= BufferEnd-CurBufferPtr) { + *((uint32_t*)CurBufferPtr) = Value; + CurBufferPtr += 4; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt64 - Emit a int64 directive. + void emitInt64(uint64_t Value) { + if (8 <= BufferEnd-CurBufferPtr) { + *((uint64_t*)CurBufferPtr) = Value; + CurBufferPtr += 8; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt32At - Emit the Int32 Value in Addr. + void emitInt32At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint32_t*)Addr) = (uint32_t)Value; + } + + /// emitInt64At - Emit the Int64 Value in Addr. + void emitInt64At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint64_t*)Addr) = (uint64_t)Value; + } + + + /// emitLabel - Emits a label + virtual void emitLabel(MCSymbol *Label) = 0; + + /// allocateSpace - Allocate a block of space in the current output buffer, + /// returning null (and setting conditions to indicate buffer overflow) on + /// failure. Alignment is the alignment in bytes of the buffer desired. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { + emitAlignment(Alignment); + void *Result; + + // Check for buffer overflow. + if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { + CurBufferPtr = BufferEnd; + Result = 0; + } else { + // Allocate the space. + Result = CurBufferPtr; + CurBufferPtr += Size; + } + + return Result; + } + + /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, + /// this method does not allocate memory in the current output buffer, + /// because a global may live longer than the current function. + virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + /// + virtual uintptr_t getCurrentPCValue() const { + return (uintptr_t)CurBufferPtr; + } + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + uintptr_t getCurrentPCOffset() const { + return CurBufferPtr-BufferBegin; + } + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return true; } + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + virtual void addRelocation(const MachineRelocation &MR) = 0; + + /// FIXME: These should all be handled with relocations! + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + /// + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + /// + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + /// + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; + + /// getLabelAddress - Return the address of the specified Label, only usable + /// after the Label has been emitted. + /// + virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; + + /// getLabelLocations - Return the label locations map of the label IDs to + /// their address. + virtual DenseMap *getLabelLocations() { return 0; } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/LatencyPriorityQueue.h b/final/include/llvm/CodeGen/LatencyPriorityQueue.h new file mode 100644 index 00000000000..1ed2547ca6c --- /dev/null +++ b/final/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -0,0 +1,100 @@ +//===---- LatencyPriorityQueue.h - A latency-oriented priority queue ------===// +// +// 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 LatencyPriorityQueue class, which is a +// SchedulingPriorityQueue that schedules using latency information to +// reduce the length of the critical path through the basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LATENCY_PRIORITY_QUEUE_H +#define LATENCY_PRIORITY_QUEUE_H + +#include "llvm/CodeGen/ScheduleDAG.h" + +namespace llvm { + class LatencyPriorityQueue; + + /// Sorting functions for the Available queue. + struct latency_sort : public std::binary_function { + LatencyPriorityQueue *PQ; + explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} + + bool operator()(const SUnit* left, const SUnit* right) const; + }; + + class LatencyPriorityQueue : public SchedulingPriorityQueue { + // SUnits - The SUnits for the current graph. + std::vector *SUnits; + + /// NumNodesSolelyBlocking - This vector contains, for every node in the + /// Queue, the number of nodes that the node is the sole unscheduled + /// predecessor for. This is used as a tie-breaker heuristic for better + /// mobility. + std::vector NumNodesSolelyBlocking; + + /// Queue - The queue. + std::vector Queue; + latency_sort Picker; + + public: + LatencyPriorityQueue() : Picker(this) { + } + + bool isBottomUp() const { return false; } + + void initNodes(std::vector &sunits) { + SUnits = &sunits; + NumNodesSolelyBlocking.resize(SUnits->size(), 0); + } + + void addNode(const SUnit *SU) { + NumNodesSolelyBlocking.resize(SUnits->size(), 0); + } + + void updateNode(const SUnit *SU) { + } + + void releaseState() { + SUnits = 0; + } + + unsigned getLatency(unsigned NodeNum) const { + assert(NodeNum < (*SUnits).size()); + return (*SUnits)[NodeNum].getHeight(); + } + + unsigned getNumSolelyBlockNodes(unsigned NodeNum) const { + assert(NodeNum < NumNodesSolelyBlocking.size()); + return NumNodesSolelyBlocking[NodeNum]; + } + + bool empty() const { return Queue.empty(); } + + virtual void push(SUnit *U); + + virtual SUnit *pop(); + + virtual void remove(SUnit *SU); + + virtual void dump(ScheduleDAG* DAG) const; + + // ScheduledNode - As nodes are scheduled, we look to see if there are any + // successor nodes that have a single unscheduled predecessor. If so, that + // single predecessor has a higher priority, since scheduling it will make + // the node available. + void ScheduledNode(SUnit *Node); + +private: + void AdjustPriorityOfUnscheduledPreds(SUnit *SU); + SUnit *getSingleUnscheduledPred(SUnit *SU); + }; +} + +#endif diff --git a/final/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/final/include/llvm/CodeGen/LinkAllAsmWriterComponents.h new file mode 100644 index 00000000000..7d1b1fe477a --- /dev/null +++ b/final/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -0,0 +1,37 @@ +//===- llvm/Codegen/LinkAllAsmWriterComponents.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all assembler writer related passes for tools like +// llc that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H +#define LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H + +#include "llvm/CodeGen/GCs.h" +#include + +namespace { + struct ForceAsmWriterLinking { + ForceAsmWriterLinking() { + // We must reference the plug-ins in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + llvm::linkOcamlGCPrinter(); + + } + } ForceAsmWriterLinking; // Force link by creating a global definition. +} + +#endif // LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H diff --git a/final/include/llvm/CodeGen/LinkAllCodegenComponents.h b/final/include/llvm/CodeGen/LinkAllCodegenComponents.h new file mode 100644 index 00000000000..c931261f633 --- /dev/null +++ b/final/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -0,0 +1,59 @@ +//===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all codegen related passes for tools like lli and +// llc that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H +#define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/GCs.h" +#include "llvm/Target/TargetMachine.h" +#include + +namespace { + struct ForceCodegenLinking { + ForceCodegenLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createDeadMachineInstructionElimPass(); + + (void) llvm::createFastRegisterAllocator(); + (void) llvm::createBasicRegisterAllocator(); + (void) llvm::createLinearScanRegisterAllocator(); + (void) llvm::createGreedyRegisterAllocator(); + (void) llvm::createDefaultPBQPRegisterAllocator(); + + (void) llvm::createSimpleRegisterCoalescer(); + + llvm::linkOcamlGC(); + llvm::linkShadowStackGC(); + + (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createTDRRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createSourceListDAGScheduler(NULL,llvm::CodeGenOpt::Default); + (void) llvm::createHybridListDAGScheduler(NULL,llvm::CodeGenOpt::Default); + (void) llvm::createTDListDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default); + + } + } ForceCodegenLinking; // Force link by creating a global definition. +} + +#endif diff --git a/final/include/llvm/CodeGen/LiveInterval.h b/final/include/llvm/CodeGen/LiveInterval.h new file mode 100644 index 00000000000..427af879609 --- /dev/null +++ b/final/include/llvm/CodeGen/LiveInterval.h @@ -0,0 +1,578 @@ +//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveRange and LiveInterval classes. Given some +// numbering of each the machine instructions an interval [i, j) is said to be a +// live interval for register v if there is no instruction with number j' >= j +// such that v is live at j' and there is no instruction with number i' < i such +// that v is live at i'. In this implementation intervals can have holes, +// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each +// individual range is represented as an instance of LiveRange, and the whole +// interval is represented as an instance of LiveInterval. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_H +#define LLVM_CODEGEN_LIVEINTERVAL_H + +#include "llvm/ADT/IntEqClasses.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include +#include + +namespace llvm { + class LiveIntervals; + class MachineInstr; + class MachineRegisterInfo; + class TargetRegisterInfo; + class raw_ostream; + + /// VNInfo - Value Number Information. + /// This class holds information about a machine level values, including + /// definition and use points. + /// + class VNInfo { + private: + enum { + HAS_PHI_KILL = 1, + REDEF_BY_EC = 1 << 1, + IS_PHI_DEF = 1 << 2, + IS_UNUSED = 1 << 3 + }; + + MachineInstr *copy; + unsigned char flags; + + public: + typedef BumpPtrAllocator Allocator; + + /// The ID number of this value. + unsigned id; + + /// The index of the defining instruction (if isDefAccurate() returns true). + SlotIndex def; + + /// VNInfo constructor. + VNInfo(unsigned i, SlotIndex d, MachineInstr *c) + : copy(c), flags(0), id(i), def(d) + { } + + /// VNInfo construtor, copies values from orig, except for the value number. + VNInfo(unsigned i, const VNInfo &orig) + : copy(orig.copy), flags(orig.flags), id(i), def(orig.def) + { } + + /// Copy from the parameter into this VNInfo. + void copyFrom(VNInfo &src) { + flags = src.flags; + copy = src.copy; + def = src.def; + } + + /// Used for copying value number info. + unsigned getFlags() const { return flags; } + void setFlags(unsigned flags) { this->flags = flags; } + + /// Merge flags from another VNInfo + void mergeFlags(const VNInfo *VNI) { + flags = (flags | VNI->flags) & ~IS_UNUSED; + } + + /// For a register interval, if this VN was definied by a copy instr + /// getCopy() returns a pointer to it, otherwise returns 0. + /// For a stack interval the behaviour of this method is undefined. + MachineInstr* getCopy() const { return copy; } + /// For a register interval, set the copy member. + /// This method should not be called on stack intervals as it may lead to + /// undefined behavior. + void setCopy(MachineInstr *c) { copy = c; } + + /// isDefByCopy - Return true when this value was defined by a copy-like + /// instruction as determined by MachineInstr::isCopyLike. + bool isDefByCopy() const { return copy != 0; } + + /// Returns true if one or more kills are PHI nodes. + bool hasPHIKill() const { return flags & HAS_PHI_KILL; } + /// Set the PHI kill flag on this value. + void setHasPHIKill(bool hasKill) { + if (hasKill) + flags |= HAS_PHI_KILL; + else + flags &= ~HAS_PHI_KILL; + } + + /// Returns true if this value is re-defined by an early clobber somewhere + /// during the live range. + bool hasRedefByEC() const { return flags & REDEF_BY_EC; } + /// Set the "redef by early clobber" flag on this value. + void setHasRedefByEC(bool hasRedef) { + if (hasRedef) + flags |= REDEF_BY_EC; + else + flags &= ~REDEF_BY_EC; + } + + /// Returns true if this value is defined by a PHI instruction (or was, + /// PHI instrucions may have been eliminated). + bool isPHIDef() const { return flags & IS_PHI_DEF; } + /// Set the "phi def" flag on this value. + void setIsPHIDef(bool phiDef) { + if (phiDef) + flags |= IS_PHI_DEF; + else + flags &= ~IS_PHI_DEF; + } + + /// Returns true if this value is unused. + bool isUnused() const { return flags & IS_UNUSED; } + /// Set the "is unused" flag on this value. + void setIsUnused(bool unused) { + if (unused) + flags |= IS_UNUSED; + else + flags &= ~IS_UNUSED; + } + }; + + /// LiveRange structure - This represents a simple register range in the + /// program, with an inclusive start point and an exclusive end point. + /// These ranges are rendered as [start,end). + struct LiveRange { + SlotIndex start; // Start point of the interval (inclusive) + SlotIndex end; // End point of the interval (exclusive) + VNInfo *valno; // identifier for the value contained in this interval. + + LiveRange(SlotIndex S, SlotIndex E, VNInfo *V) + : start(S), end(E), valno(V) { + + assert(S < E && "Cannot create empty or backwards range"); + } + + /// contains - Return true if the index is covered by this range. + /// + bool contains(SlotIndex I) const { + return start <= I && I < end; + } + + /// containsRange - Return true if the given range, [S, E), is covered by + /// this range. + bool containsRange(SlotIndex S, SlotIndex E) const { + assert((S < E) && "Backwards interval?"); + return (start <= S && S < end) && (start < E && E <= end); + } + + bool operator<(const LiveRange &LR) const { + return start < LR.start || (start == LR.start && end < LR.end); + } + bool operator==(const LiveRange &LR) const { + return start == LR.start && end == LR.end; + } + + void dump() const; + void print(raw_ostream &os) const; + + private: + LiveRange(); // DO NOT IMPLEMENT + }; + + template <> struct isPodLike { static const bool value = true; }; + + raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR); + + + inline bool operator<(SlotIndex V, const LiveRange &LR) { + return V < LR.start; + } + + inline bool operator<(const LiveRange &LR, SlotIndex V) { + return LR.start < V; + } + + /// LiveInterval - This class represents some number of live ranges for a + /// register or value. This class also contains a bit of register allocator + /// state. + class LiveInterval { + public: + + typedef SmallVector Ranges; + typedef SmallVector VNInfoList; + + const unsigned reg; // the register or stack slot of this interval. + float weight; // weight of this interval + Ranges ranges; // the ranges in which this register is live + VNInfoList valnos; // value#'s + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + + }; + + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), weight(Weight) {} + + typedef Ranges::iterator iterator; + iterator begin() { return ranges.begin(); } + iterator end() { return ranges.end(); } + + typedef Ranges::const_iterator const_iterator; + const_iterator begin() const { return ranges.begin(); } + const_iterator end() const { return ranges.end(); } + + typedef VNInfoList::iterator vni_iterator; + vni_iterator vni_begin() { return valnos.begin(); } + vni_iterator vni_end() { return valnos.end(); } + + typedef VNInfoList::const_iterator const_vni_iterator; + const_vni_iterator vni_begin() const { return valnos.begin(); } + const_vni_iterator vni_end() const { return valnos.end(); } + + /// advanceTo - Advance the specified iterator to point to the LiveRange + /// containing the specified position, or end() if the position is past the + /// end of the interval. If no LiveRange contains this position, but the + /// position is in a hole, this method returns an iterator pointing to the + /// LiveRange immediately after the hole. + iterator advanceTo(iterator I, SlotIndex Pos) { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + + /// find - Return an iterator pointing to the first range that ends after + /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster + /// when searching large intervals. + /// + /// If Pos is contained in a LiveRange, that range is returned. + /// If Pos is in a hole, the following LiveRange is returned. + /// If Pos is beyond endIndex, end() is returned. + iterator find(SlotIndex Pos); + + const_iterator find(SlotIndex Pos) const { + return const_cast(this)->find(Pos); + } + + void clear() { + valnos.clear(); + ranges.clear(); + } + + bool hasAtLeastOneValue() const { return !valnos.empty(); } + + bool containsOneValue() const { return valnos.size() == 1; } + + unsigned getNumValNums() const { return (unsigned)valnos.size(); } + + /// getValNumInfo - Returns pointer to the specified val#. + /// + inline VNInfo *getValNumInfo(unsigned ValNo) { + return valnos[ValNo]; + } + inline const VNInfo *getValNumInfo(unsigned ValNo) const { + return valnos[ValNo]; + } + + /// getNextValue - Create a new value number and return it. MIIdx specifies + /// the instruction that defines the value number. + VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI, + VNInfo::Allocator &VNInfoAllocator) { + VNInfo *VNI = + new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), def, CopyMI); + valnos.push_back(VNI); + return VNI; + } + + /// Create a copy of the given value. The new value will be identical except + /// for the Value number. + VNInfo *createValueCopy(const VNInfo *orig, + VNInfo::Allocator &VNInfoAllocator) { + VNInfo *VNI = + new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), *orig); + valnos.push_back(VNI); + return VNI; + } + + /// RenumberValues - Renumber all values in order of appearance and remove + /// unused values. + /// Recalculate phi-kill flags in case any phi-def values were removed. + void RenumberValues(LiveIntervals &lis); + + /// isOnlyLROfValNo - Return true if the specified live range is the only + /// one defined by the its val#. + bool isOnlyLROfValNo(const LiveRange *LR) { + for (const_iterator I = begin(), E = end(); I != E; ++I) { + const LiveRange *Tmp = I; + if (Tmp != LR && Tmp->valno == LR->valno) + return false; + } + return true; + } + + /// MergeValueNumberInto - This method is called when two value nubmers + /// are found to be equivalent. This eliminates V1, replacing all + /// LiveRanges with the V1 value number with the V2 value number. This can + /// cause merging of V1/V2 values numbers and compaction of the value space. + VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2); + + /// MergeValueInAsValue - Merge all of the live ranges of a specific val# + /// in RHS into this live interval as the specified value number. + /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the + /// current interval, it will replace the value numbers of the overlaped + /// live ranges with the specified value number. + void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the live ranges of a specific val# + /// in RHS into this live interval as the specified value number. + /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the + /// current interval, but only if the overlapping LiveRanges have the + /// specified value number. + void MergeValueInAsValue(const LiveInterval &RHS, + const VNInfo *RHSValNo, VNInfo *LHSValNo); + + /// Copy - Copy the specified live interval. This copies all the fields + /// except for the register of the interval. + void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI, + VNInfo::Allocator &VNInfoAllocator); + + bool empty() const { return ranges.empty(); } + + /// beginIndex - Return the lowest numbered slot covered by interval. + SlotIndex beginIndex() const { + assert(!empty() && "Call to beginIndex() on empty interval."); + return ranges.front().start; + } + + /// endNumber - return the maximum point of the interval of the whole, + /// exclusive. + SlotIndex endIndex() const { + assert(!empty() && "Call to endIndex() on empty interval."); + return ranges.back().end; + } + + bool expiredAt(SlotIndex index) const { + return index >= endIndex(); + } + + bool liveAt(SlotIndex index) const { + const_iterator r = find(index); + return r != end() && r->start <= index; + } + + /// killedAt - Return true if a live range ends at index. Note that the kill + /// point is not contained in the half-open live range. It is usually the + /// getDefIndex() slot following its last use. + bool killedAt(SlotIndex index) const { + const_iterator r = find(index.getUseIndex()); + return r != end() && r->end == index; + } + + /// killedInRange - Return true if the interval has kills in [Start,End). + /// Note that the kill point is considered the end of a live range, so it is + /// not contained in the live range. If a live range ends at End, it won't + /// be counted as a kill by this method. + bool killedInRange(SlotIndex Start, SlotIndex End) const; + + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + const LiveRange *getLiveRangeContaining(SlotIndex Idx) const { + const_iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + LiveRange *getLiveRangeContaining(SlotIndex Idx) { + iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + + /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. + VNInfo *getVNInfoAt(SlotIndex Idx) const { + const_iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : I->valno; + } + + /// FindLiveRangeContaining - Return an iterator to the live range that + /// contains the specified index, or end() if there is none. + iterator FindLiveRangeContaining(SlotIndex Idx) { + iterator I = find(Idx); + return I != end() && I->start <= Idx ? I : end(); + } + + const_iterator FindLiveRangeContaining(SlotIndex Idx) const { + const_iterator I = find(Idx); + return I != end() && I->start <= Idx ? I : end(); + } + + /// findDefinedVNInfo - Find the by the specified + /// index (register interval) or defined + VNInfo *findDefinedVNInfoForRegInt(SlotIndex Idx) const; + + + /// overlaps - Return true if the intersection of the two live intervals is + /// not empty. + bool overlaps(const LiveInterval& other) const { + if (other.empty()) + return false; + return overlapsFrom(other, other.begin()); + } + + /// overlaps - Return true if the live interval overlaps a range specified + /// by [Start, End). + bool overlaps(SlotIndex Start, SlotIndex End) const; + + /// overlapsFrom - Return true if the intersection of the two live intervals + /// is not empty. The specified iterator is a hint that we can begin + /// scanning the Other interval starting at I. + bool overlapsFrom(const LiveInterval& other, const_iterator I) const; + + /// addRange - Add the specified LiveRange to this interval, merging + /// intervals as appropriate. This returns an iterator to the inserted live + /// range (which may have grown since it was inserted. + void addRange(LiveRange LR) { + addRangeFrom(LR, ranges.begin()); + } + + /// extendInBlock - If this interval is live before UseIdx in the basic + /// block that starts at StartIdx, extend it to be live at UseIdx and return + /// the value. If there is no live range before UseIdx, return NULL. + VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx); + + /// join - Join two live intervals (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS intervals as specified. If + /// the intervals are not joinable, this aborts. + void join(LiveInterval &Other, + const int *ValNoAssignments, + const int *RHSValNoAssignments, + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI); + + /// isInOneLiveRange - Return true if the range specified is entirely in the + /// a single LiveRange of the live interval. + bool isInOneLiveRange(SlotIndex Start, SlotIndex End) const { + const_iterator r = find(Start); + return r != end() && r->containsRange(Start, End); + } + + /// removeRange - Remove the specified range from this interval. Note that + /// the range must be a single LiveRange in its entirety. + void removeRange(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo = false); + + void removeRange(LiveRange LR, bool RemoveDeadValNo = false) { + removeRange(LR.start, LR.end, RemoveDeadValNo); + } + + /// removeValNo - Remove all the ranges defined by the specified value#. + /// Also remove the value# from value# list. + void removeValNo(VNInfo *ValNo); + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + /// Returns true if the live interval is zero length, i.e. no live ranges + /// span instructions. It doesn't pay to spill such an interval. + bool isZeroLength() const { + for (const_iterator i = begin(), e = end(); i != e; ++i) + if (i->end.getPrevIndex() > i->start) + return false; + return true; + } + + /// isSpillable - Can this interval be spilled? + bool isSpillable() const { + return weight != HUGE_VALF; + } + + /// markNotSpillable - Mark interval as not spillable + void markNotSpillable() { + weight = HUGE_VALF; + } + + /// ComputeJoinedWeight - Set the weight of a live interval after + /// Other has been merged into it. + void ComputeJoinedWeight(const LiveInterval &Other); + + bool operator<(const LiveInterval& other) const { + const SlotIndex &thisIndex = beginIndex(); + const SlotIndex &otherIndex = other.beginIndex(); + return (thisIndex < otherIndex || + (thisIndex == otherIndex && reg < other.reg)); + } + + void print(raw_ostream &OS, const TargetRegisterInfo *TRI = 0) const; + void dump() const; + + private: + + Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); + void extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd); + Ranges::iterator extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStr); + void markValNoForDeletion(VNInfo *V); + + LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT + + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { + LI.print(OS); + return OS; + } + + /// ConnectedVNInfoEqClasses - Helper class that can divide VNInfos in a + /// LiveInterval into equivalence clases of connected components. A + /// LiveInterval that has multiple connected components can be broken into + /// multiple LiveIntervals. + /// + /// Given a LiveInterval that may have multiple connected components, run: + /// + /// unsigned numComps = ConEQ.Classify(LI); + /// if (numComps > 1) { + /// // allocate numComps-1 new LiveIntervals into LIS[1..] + /// ConEQ.Distribute(LIS); + /// } + + class ConnectedVNInfoEqClasses { + LiveIntervals &lis_; + IntEqClasses eqClass_; + + // Note that values a and b are connected. + void Connect(unsigned a, unsigned b); + + unsigned Renumber(); + + public: + explicit ConnectedVNInfoEqClasses(LiveIntervals &lis) : lis_(lis) {} + + /// Classify - Classify the values in LI into connected components. + /// Return the number of connected components. + unsigned Classify(const LiveInterval *LI); + + /// getEqClass - Classify creates equivalence classes numbered 0..N. Return + /// the equivalence class assigned the VNI. + unsigned getEqClass(const VNInfo *VNI) const { return eqClass_[VNI->id]; } + + /// Distribute - Distribute values in LIV[0] into a separate LiveInterval + /// for each connected component. LIV must have a LiveInterval for each + /// connected component. The LiveIntervals in Liv[1..] must be empty. + void Distribute(LiveInterval *LIV[]); + + }; + +} +#endif diff --git a/final/include/llvm/CodeGen/LiveIntervalAnalysis.h b/final/include/llvm/CodeGen/LiveIntervalAnalysis.h new file mode 100644 index 00000000000..1391f0f95be --- /dev/null +++ b/final/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -0,0 +1,465 @@ +//===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveInterval analysis pass. Given some numbering of +// each the machine instructions (in this implemention depth-first order) an +// interval [i, j) is said to be a live interval for register v if there is no +// instruction with number j' > j such that v is live at j' and there is no +// instruction with number i' < i such that v is live at i'. In this +// implementation intervals can have holes, i.e. an interval might look like +// [1,20), [50,65), [1000,1001). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include +#include + +namespace llvm { + + class AliasAnalysis; + class LiveVariables; + class MachineLoopInfo; + class TargetRegisterInfo; + class MachineRegisterInfo; + class TargetInstrInfo; + class TargetRegisterClass; + class VirtRegMap; + + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + AliasAnalysis *aa_; + LiveVariables* lv_; + SlotIndexes* indexes_; + + /// Special pool allocator for VNInfo's (LiveInterval val#). + /// + VNInfo::Allocator VNInfoAllocator; + + typedef DenseMap Reg2IntervalMap; + Reg2IntervalMap r2iMap_; + + /// allocatableRegs_ - A bit vector of allocatable registers. + BitVector allocatableRegs_; + + /// CloneMIs - A list of clones as result of re-materialization. + std::vector CloneMIs; + + public: + static char ID; // Pass identification, replacement for typeid + LiveIntervals() : MachineFunctionPass(ID) { + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + } + + // Calculate the spill weight to assign to a single instruction. + static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); + + typedef Reg2IntervalMap::iterator iterator; + typedef Reg2IntervalMap::const_iterator const_iterator; + const_iterator begin() const { return r2iMap_.begin(); } + const_iterator end() const { return r2iMap_.end(); } + iterator begin() { return r2iMap_.begin(); } + iterator end() { return r2iMap_.end(); } + unsigned getNumIntervals() const { return (unsigned)r2iMap_.size(); } + + LiveInterval &getInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return *I->second; + } + + const LiveInterval &getInterval(unsigned reg) const { + Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return *I->second; + } + + bool hasInterval(unsigned reg) const { + return r2iMap_.count(reg); + } + + /// isAllocatable - is the physical register reg allocatable in the current + /// function? + bool isAllocatable(unsigned reg) const { + return allocatableRegs_.test(reg); + } + + /// getScaledIntervalSize - get the size of an interval in "units," + /// where every function is composed of one thousand units. This + /// measure scales properly with empty index slots in the function. + double getScaledIntervalSize(LiveInterval& I) { + return (1000.0 * I.getSize()) / indexes_->getIndexesLength(); + } + + /// getFuncInstructionCount - Return the number of instructions in the + /// current function. + unsigned getFuncInstructionCount() { + return indexes_->getFunctionSize(); + } + + /// getApproximateInstructionCount - computes an estimate of the number + /// of instructions in a given LiveInterval. + unsigned getApproximateInstructionCount(LiveInterval& I) { + double IntervalPercentage = getScaledIntervalSize(I) / 1000.0; + return (unsigned)(IntervalPercentage * indexes_->getFunctionSize()); + } + + /// conflictsWithPhysReg - Returns true if the specified register is used or + /// defined during the duration of the specified interval. Copies to and + /// from li.reg are allowed. This method is only able to analyze simple + /// ranges that stay within a single basic block. Anything else is + /// considered a conflict. + bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm, + unsigned reg); + + /// conflictsWithAliasRef - Similar to conflictsWithPhysRegRef except + /// it checks for alias uses and defs. + bool conflictsWithAliasRef(LiveInterval &li, unsigned Reg, + SmallPtrSet &JoinedCopies); + + // Interval creation + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(std::make_pair(reg, createInterval(reg))).first; + return *I->second; + } + + /// dupInterval - Duplicate a live interval. The caller is responsible for + /// managing the allocated memory. + LiveInterval *dupInterval(LiveInterval *li); + + /// addLiveRangeToEndOfBlock - Given a register and an instruction, + /// adds a live range from that instruction to the end of its MBB. + LiveRange addLiveRangeToEndOfBlock(unsigned reg, + MachineInstr* startInst); + + /// shrinkToUses - After removing some uses of a register, shrink its live + /// range to just the remaining uses. This method does not compute reaching + /// defs for new uses, and it doesn't remove dead defs. + /// Dead PHIDef values are marked as unused. + /// New dead machine instructions are added to the dead vector. + void shrinkToUses(LiveInterval *li, + SmallVectorImpl *dead = 0); + + // Interval removal + + void removeInterval(unsigned Reg) { + DenseMap::iterator I = r2iMap_.find(Reg); + delete I->second; + r2iMap_.erase(I); + } + + SlotIndexes *getSlotIndexes() const { + return indexes_; + } + + SlotIndex getZeroIndex() const { + return indexes_->getZeroIndex(); + } + + SlotIndex getInvalidIndex() const { + return indexes_->getInvalidIndex(); + } + + /// isNotInMIMap - returns true if the specified machine instr has been + /// removed or was never entered in the map. + bool isNotInMIMap(const MachineInstr* Instr) const { + return !indexes_->hasIndex(Instr); + } + + /// Returns the base index of the given instruction. + SlotIndex getInstructionIndex(const MachineInstr *instr) const { + return indexes_->getInstructionIndex(instr); + } + + /// Returns the instruction associated with the given index. + MachineInstr* getInstructionFromIndex(SlotIndex index) const { + return indexes_->getInstructionFromIndex(index); + } + + /// Return the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + return indexes_->getMBBStartIdx(mbb); + } + + /// Return the last index in the given basic block. + SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { + return indexes_->getMBBEndIdx(mbb); + } + + bool isLiveInToMBB(const LiveInterval &li, + const MachineBasicBlock *mbb) const { + return li.liveAt(getMBBStartIdx(mbb)); + } + + LiveRange* findEnteringRange(LiveInterval &li, + const MachineBasicBlock *mbb) { + return li.getLiveRangeContaining(getMBBStartIdx(mbb)); + } + + bool isLiveOutOfMBB(const LiveInterval &li, + const MachineBasicBlock *mbb) const { + return li.liveAt(getMBBEndIdx(mbb).getPrevSlot()); + } + + LiveRange* findExitingRange(LiveInterval &li, + const MachineBasicBlock *mbb) { + return li.getLiveRangeContaining(getMBBEndIdx(mbb).getPrevSlot()); + } + + MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { + return indexes_->getMBBFromIndex(index); + } + + SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) { + return indexes_->insertMachineInstrInMaps(MI); + } + + void RemoveMachineInstrFromMaps(MachineInstr *MI) { + indexes_->removeMachineInstrFromMaps(MI); + } + + void ReplaceMachineInstrInMaps(MachineInstr *MI, MachineInstr *NewMI) { + indexes_->replaceMachineInstrInMaps(MI, NewMI); + } + + void InsertMBBInMaps(MachineBasicBlock *MBB) { + indexes_->insertMBBInMaps(MBB); + } + + bool findLiveInMBBs(SlotIndex Start, SlotIndex End, + SmallVectorImpl &MBBs) const { + return indexes_->findLiveInMBBs(Start, End, MBBs); + } + + void renumber() { + indexes_->renumberIndexes(); + } + + VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + + /// addIntervalsForSpills - Create new intervals for spilled defs / uses of + /// the given interval. FIXME: It also returns the weight of the spill slot + /// (if any is created) by reference. This is temporary. + std::vector + addIntervalsForSpills(const LiveInterval& i, + const SmallVectorImpl &SpillIs, + const MachineLoopInfo *loopInfo, VirtRegMap& vrm); + + /// spillPhysRegAroundRegDefsUses - Spill the specified physical register + /// around all defs and uses of the specified interval. Return true if it + /// was able to cut its interval. + bool spillPhysRegAroundRegDefsUses(const LiveInterval &li, + unsigned PhysReg, VirtRegMap &vrm); + + /// isReMaterializable - Returns true if every definition of MI of every + /// val# of the specified interval is re-materializable. Also returns true + /// by reference if all of the defs are load instructions. + bool isReMaterializable(const LiveInterval &li, + const SmallVectorImpl &SpillIs, + bool &isLoad); + + /// isReMaterializable - Returns true if the definition MI of the specified + /// val# of the specified interval is re-materializable. + bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, + MachineInstr *MI); + + /// getRepresentativeReg - Find the largest super register of the specified + /// physical register. + unsigned getRepresentativeReg(unsigned Reg) const; + + /// getNumConflictsWithPhysReg - Return the number of uses and defs of the + /// specified interval that conflicts with the specified physical register. + unsigned getNumConflictsWithPhysReg(const LiveInterval &li, + unsigned PhysReg) const; + + /// intervalIsInOneMBB - Returns true if the specified interval is entirely + /// within a single basic block. + bool intervalIsInOneMBB(const LiveInterval &li) const; + + /// getLastSplitPoint - Return the last possible insertion point in mbb for + /// spilling and splitting code. This is the first terminator, or the call + /// instruction if li is live into a landing pad successor. + MachineBasicBlock::iterator getLastSplitPoint(const LiveInterval &li, + MachineBasicBlock *mbb) const; + + /// addKillFlags - Add kill flags to any instruction that kills a virtual + /// register. + void addKillFlags(); + + private: + /// computeIntervals - Compute live intervals. + void computeIntervals(); + + /// handleRegisterDef - update intervals for a register def + /// (calls handlePhysicalRegisterDef and + /// handleVirtualRegisterDef) + void handleRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, + MachineOperand& MO, unsigned MOIdx); + + /// isPartialRedef - Return true if the specified def at the specific index + /// is partially re-defining the specified live interval. A common case of + /// this is a definition of the sub-register. + bool isPartialRedef(SlotIndex MIIdx, MachineOperand &MO, + LiveInterval &interval); + + /// handleVirtualRegisterDef - update intervals for a virtual + /// register def + void handleVirtualRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, MachineOperand& MO, + unsigned MOIdx, + LiveInterval& interval); + + /// handlePhysicalRegisterDef - update intervals for a physical register + /// def. + void handlePhysicalRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, MachineOperand& MO, + LiveInterval &interval, + MachineInstr *CopyMI); + + /// handleLiveInRegister - Create interval for a livein register. + void handleLiveInRegister(MachineBasicBlock* mbb, + SlotIndex MIIdx, + LiveInterval &interval, bool isAlias = false); + + /// getReMatImplicitUse - If the remat definition MI has one (for now, we + /// only allow one) virtual register operand, then its uses are implicitly + /// using the register. Returns the virtual register. + unsigned getReMatImplicitUse(const LiveInterval &li, + MachineInstr *MI) const; + + /// isValNoAvailableAt - Return true if the val# of the specified interval + /// which reaches the given instruction also reaches the specified use + /// index. + bool isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, + SlotIndex UseIdx) const; + + /// isReMaterializable - Returns true if the definition MI of the specified + /// val# of the specified interval is re-materializable. Also returns true + /// by reference if the def is a load. + bool isReMaterializable(const LiveInterval &li, const VNInfo *ValNo, + MachineInstr *MI, + const SmallVectorImpl &SpillIs, + bool &isLoad); + + /// tryFoldMemoryOperand - Attempts to fold either a spill / restore from + /// slot / to reg or any rematerialized load into ith operand of specified + /// MI. If it is successul, MI is updated with the newly created MI and + /// returns true. + bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, + MachineInstr *DefMI, SlotIndex InstrIdx, + SmallVector &Ops, + bool isSS, int FrameIndex, unsigned Reg); + + /// canFoldMemoryOperand - Return true if the specified load / store + /// folding is possible. + bool canFoldMemoryOperand(MachineInstr *MI, + SmallVector &Ops, + bool ReMatLoadSS) const; + + /// anyKillInMBBAfterIdx - Returns true if there is a kill of the specified + /// VNInfo that's after the specified index but is within the basic block. + bool anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI, + MachineBasicBlock *MBB, + SlotIndex Idx) const; + + /// hasAllocatableSuperReg - Return true if the specified physical register + /// has any super register that's allocatable. + bool hasAllocatableSuperReg(unsigned Reg) const; + + /// SRInfo - Spill / restore info. + struct SRInfo { + SlotIndex index; + unsigned vreg; + bool canFold; + SRInfo(SlotIndex i, unsigned vr, bool f) + : index(i), vreg(vr), canFold(f) {} + }; + + bool alsoFoldARestore(int Id, SlotIndex index, unsigned vr, + BitVector &RestoreMBBs, + DenseMap >&RestoreIdxes); + void eraseRestoreInfo(int Id, SlotIndex index, unsigned vr, + BitVector &RestoreMBBs, + DenseMap >&RestoreIdxes); + + /// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being + /// spilled and create empty intervals for their uses. + void handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, + const TargetRegisterClass* rc, + std::vector &NewLIs); + + /// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of + /// interval on to-be re-materialized operands of MI) with new register. + void rewriteImplicitOps(const LiveInterval &li, + MachineInstr *MI, unsigned NewVReg, VirtRegMap &vrm); + + /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper + /// functions for addIntervalsForSpills to rewrite uses / defs for the given + /// live range. + bool rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, + bool TrySplit, SlotIndex index, SlotIndex end, + MachineInstr *MI, MachineInstr *OrigDefMI, MachineInstr *DefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, const TargetRegisterClass* rc, + SmallVector &ReMatIds, const MachineLoopInfo *loopInfo, + unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse, + DenseMap &MBBVRegsMap, + std::vector &NewLIs); + void rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, + LiveInterval::Ranges::const_iterator &I, + MachineInstr *OrigDefMI, MachineInstr *DefMI, unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, const TargetRegisterClass* rc, + SmallVector &ReMatIds, const MachineLoopInfo *loopInfo, + BitVector &SpillMBBs, + DenseMap > &SpillIdxes, + BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes, + DenseMap &MBBVRegsMap, + std::vector &NewLIs); + + static LiveInterval* createInterval(unsigned Reg); + + void printInstrs(raw_ostream &O) const; + void dumpInstrs() const; + }; +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/LiveStackAnalysis.h b/final/include/llvm/CodeGen/LiveStackAnalysis.h new file mode 100644 index 00000000000..8a8dcaf5728 --- /dev/null +++ b/final/include/llvm/CodeGen/LiveStackAnalysis.h @@ -0,0 +1,97 @@ +//===-- LiveStackAnalysis.h - Live Stack Slot Analysis ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the live stack slot analysis pass. It is analogous to +// live interval analysis except it's analyzing liveness of stack slots rather +// than registers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVESTACK_ANALYSIS_H +#define LLVM_CODEGEN_LIVESTACK_ANALYSIS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Allocator.h" +#include + +namespace llvm { + + class LiveStacks : public MachineFunctionPass { + /// Special pool allocator for VNInfo's (LiveInterval val#). + /// + VNInfo::Allocator VNInfoAllocator; + + /// S2IMap - Stack slot indices to live interval mapping. + /// + typedef std::map SS2IntervalMap; + SS2IntervalMap S2IMap; + + /// S2RCMap - Stack slot indices to register class mapping. + std::map S2RCMap; + + public: + static char ID; // Pass identification, replacement for typeid + LiveStacks() : MachineFunctionPass(ID) { + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + } + + typedef SS2IntervalMap::iterator iterator; + typedef SS2IntervalMap::const_iterator const_iterator; + const_iterator begin() const { return S2IMap.begin(); } + const_iterator end() const { return S2IMap.end(); } + iterator begin() { return S2IMap.begin(); } + iterator end() { return S2IMap.end(); } + + unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } + + LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC); + + LiveInterval &getInterval(int Slot) { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::iterator I = S2IMap.find(Slot); + assert(I != S2IMap.end() && "Interval does not exist for stack slot"); + return I->second; + } + + const LiveInterval &getInterval(int Slot) const { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::const_iterator I = S2IMap.find(Slot); + assert(I != S2IMap.end() && "Interval does not exist for stack slot"); + return I->second; + } + + bool hasInterval(int Slot) const { + return S2IMap.count(Slot); + } + + const TargetRegisterClass *getIntervalRegClass(int Slot) const { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + std::map::const_iterator + I = S2RCMap.find(Slot); + assert(I != S2RCMap.end() && + "Register class info does not exist for stack slot"); + return I->second; + } + + VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + }; +} + +#endif /* LLVM_CODEGEN_LIVESTACK_ANALYSIS_H */ diff --git a/final/include/llvm/CodeGen/LiveVariables.h b/final/include/llvm/CodeGen/LiveVariables.h new file mode 100644 index 00000000000..f9b81b1ea7d --- /dev/null +++ b/final/include/llvm/CodeGen/LiveVariables.h @@ -0,0 +1,316 @@ +//===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveVariables analysis pass. For each machine +// instruction in the function, this pass calculates the set of registers that +// are immediately dead after the instruction (i.e., the instruction calculates +// the value, but it is never used) and the set of registers that are used by +// the instruction, but are never used after the instruction (i.e., they are +// killed). +// +// This class computes live variables using a sparse implementation based on +// the machine code SSA form. This class computes live variable information for +// each virtual and _register allocatable_ physical register in a function. It +// uses the dominance properties of SSA form to efficiently compute live +// variables for virtual registers, and assumes that physical registers are only +// live within a single basic block (allowing it to do a single local analysis +// to resolve physical register lifetimes in each basic block). If a physical +// register is not register allocatable, it is not tracked. This is useful for +// things like the stack pointer and condition codes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEVARIABLES_H +#define LLVM_CODEGEN_LIVEVARIABLES_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SparseBitVector.h" + +namespace llvm { + +class MachineRegisterInfo; +class TargetRegisterInfo; + +class LiveVariables : public MachineFunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + LiveVariables() : MachineFunctionPass(ID) { + initializeLiveVariablesPass(*PassRegistry::getPassRegistry()); + } + + /// VarInfo - This represents the regions where a virtual register is live in + /// the program. We represent this with three different pieces of + /// information: the set of blocks in which the instruction is live + /// throughout, the set of blocks in which the instruction is actually used, + /// and the set of non-phi instructions that are the last users of the value. + /// + /// In the common case where a value is defined and killed in the same block, + /// There is one killing instruction, and AliveBlocks is empty. + /// + /// Otherwise, the value is live out of the block. If the value is live + /// throughout any blocks, these blocks are listed in AliveBlocks. Blocks + /// where the liveness range ends are not included in AliveBlocks, instead + /// being captured by the Kills set. In these blocks, the value is live into + /// the block (unless the value is defined and killed in the same block) and + /// lives until the specified instruction. Note that there cannot ever be a + /// value whose Kills set contains two instructions from the same basic block. + /// + /// PHI nodes complicate things a bit. If a PHI node is the last user of a + /// value in one of its predecessor blocks, it is not listed in the kills set, + /// but does include the predecessor block in the AliveBlocks set (unless that + /// block also defines the value). This leads to the (perfectly sensical) + /// situation where a value is defined in a block, and the last use is a phi + /// node in the successor. In this case, AliveBlocks is empty (the value is + /// not live across any blocks) and Kills is empty (phi nodes are not + /// included). This is sensical because the value must be live to the end of + /// the block, but is not live in any successor blocks. + struct VarInfo { + /// AliveBlocks - Set of blocks in which this value is alive completely + /// through. This is a bit set which uses the basic block number as an + /// index. + /// + SparseBitVector<> AliveBlocks; + + /// NumUses - Number of uses of this register across the entire function. + /// + unsigned NumUses; + + /// Kills - List of MachineInstruction's which are the last use of this + /// virtual register (kill it) in their basic block. + /// + std::vector Kills; + + VarInfo() : NumUses(0) {} + + /// removeKill - Delete a kill corresponding to the specified + /// machine instruction. Returns true if there was a kill + /// corresponding to this instruction, false otherwise. + bool removeKill(MachineInstr *MI) { + std::vector::iterator + I = std::find(Kills.begin(), Kills.end(), MI); + if (I == Kills.end()) + return false; + Kills.erase(I); + return true; + } + + /// findKill - Find a kill instruction in MBB. Return NULL if none is found. + MachineInstr *findKill(const MachineBasicBlock *MBB) const; + + /// isLiveIn - Is Reg live in to MBB? This means that Reg is live through + /// MBB, or it is killed in MBB. If Reg is only used by PHI instructions in + /// MBB, it is not considered live in. + bool isLiveIn(const MachineBasicBlock &MBB, + unsigned Reg, + MachineRegisterInfo &MRI); + + void dump() const; + }; + +private: + /// VirtRegInfo - This list is a mapping from virtual register number to + /// variable information. + /// + IndexedMap VirtRegInfo; + + /// PHIJoins - list of virtual registers that are PHI joins. These registers + /// may have multiple definitions, and they require special handling when + /// building live intervals. + SparseBitVector<> PHIJoins; + + /// ReservedRegisters - This vector keeps track of which registers + /// are reserved register which are not allocatable by the target machine. + /// We can not track liveness for values that are in this set. + /// + BitVector ReservedRegisters; + +private: // Intermediate data structures + MachineFunction *MF; + + MachineRegisterInfo* MRI; + + const TargetRegisterInfo *TRI; + + // PhysRegInfo - Keep track of which instruction was the last def of a + // physical register. This is a purely local property, because all physical + // register references are presumed dead across basic blocks. + MachineInstr **PhysRegDef; + + // PhysRegInfo - Keep track of which instruction was the last use of a + // physical register. This is a purely local property, because all physical + // register references are presumed dead across basic blocks. + MachineInstr **PhysRegUse; + + SmallVector *PHIVarInfo; + + // DistanceMap - Keep track the distance of a MI from the start of the + // current basic block. + DenseMap DistanceMap; + + /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the + /// uses. Pay special attention to the sub-register uses which may come below + /// the last use of the whole register. + bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); + + void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); + void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVector &Defs); + + /// FindLastRefOrPartRef - Return the last reference or partial reference of + /// the specified register. + MachineInstr *FindLastRefOrPartRef(unsigned Reg); + + /// FindLastPartialDef - Return the last partial def of the specified + /// register. Also returns the sub-registers that're defined by the + /// instruction. + MachineInstr *FindLastPartialDef(unsigned Reg, + SmallSet &PartDefRegs); + + /// analyzePHINodes - Gather information about the PHI nodes in here. In + /// particular, we want to map the variable information of a virtual + /// register which is used in a PHI node. We map that to the BB the vreg + /// is coming from. + void analyzePHINodes(const MachineFunction& Fn); +public: + + virtual bool runOnMachineFunction(MachineFunction &MF); + + /// RegisterDefIsDead - Return true if the specified instruction defines the + /// specified register, but that definition is dead. + bool RegisterDefIsDead(MachineInstr *MI, unsigned Reg) const; + + //===--------------------------------------------------------------------===// + // API to update live variable information + + /// replaceKillInstruction - Update register kill info by replacing a kill + /// instruction with a new one. + void replaceKillInstruction(unsigned Reg, MachineInstr *OldMI, + MachineInstr *NewMI); + + /// addVirtualRegisterKilled - Add information about the fact that the + /// specified register is killed after being used by the specified + /// instruction. If AddIfNotFound is true, add a implicit operand if it's + /// not found. + void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (MI->addRegisterKilled(IncomingReg, TRI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterKilled - Remove the specified kill of the virtual + /// register from the live variable information. Returns true if the + /// variable was marked as killed by the specified instruction, + /// false otherwise. + bool removeVirtualRegisterKilled(unsigned reg, MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isKill() && MO.getReg() == reg) { + MO.setIsKill(false); + Removed = true; + break; + } + } + + assert(Removed && "Register is not used by this instruction!"); + return true; + } + + /// removeVirtualRegistersKilled - Remove all killed info for the specified + /// instruction. + void removeVirtualRegistersKilled(MachineInstr *MI); + + /// addVirtualRegisterDead - Add information about the fact that the specified + /// register is dead after being used by the specified instruction. If + /// AddIfNotFound is true, add a implicit operand if it's not found. + void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (MI->addRegisterDead(IncomingReg, TRI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterDead - Remove the specified kill of the virtual + /// register from the live variable information. Returns true if the + /// variable was marked dead at the specified instruction, false + /// otherwise. + bool removeVirtualRegisterDead(unsigned reg, MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.getReg() == reg) { + MO.setIsDead(false); + Removed = true; + break; + } + } + assert(Removed && "Register is not defined by this instruction!"); + return true; + } + + void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory() { + VirtRegInfo.clear(); + } + + /// getVarInfo - Return the VarInfo structure for the specified VIRTUAL + /// register. + VarInfo &getVarInfo(unsigned RegIdx); + + void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, + MachineBasicBlock *BB); + void MarkVirtRegAliveInBlock(VarInfo& VRInfo, MachineBasicBlock* DefBlock, + MachineBasicBlock *BB, + std::vector &WorkList); + void HandleVirtRegDef(unsigned reg, MachineInstr *MI); + void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, + MachineInstr *MI); + + bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB) { + return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI); + } + + /// isLiveOut - Determine if Reg is live out from MBB, when not considering + /// PHI nodes. This means that Reg is either killed by a successor block or + /// passed through one. + bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB); + + /// addNewBlock - Add a new basic block BB between DomBB and SuccBB. All + /// variables that are live out of DomBB and live into SuccBB will be marked + /// as passing live through BB. This method assumes that the machine code is + /// still in SSA form. + void addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB, + MachineBasicBlock *SuccBB); + + /// isPHIJoin - Return true if Reg is a phi join register. + bool isPHIJoin(unsigned Reg) { return PHIJoins.test(Reg); } + + /// setPHIJoin - Mark Reg as a phi join register. + void setPHIJoin(unsigned Reg) { PHIJoins.set(Reg); } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachORelocation.h b/final/include/llvm/CodeGen/MachORelocation.h new file mode 100644 index 00000000000..21fe74f8e1c --- /dev/null +++ b/final/include/llvm/CodeGen/MachORelocation.h @@ -0,0 +1,56 @@ +//=== MachORelocation.h - Mach-O Relocation 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 the MachORelocation class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHO_RELOCATION_H +#define LLVM_CODEGEN_MACHO_RELOCATION_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + + /// MachORelocation - This struct contains information about each relocation + /// that needs to be emitted to the file. + /// see + class MachORelocation { + uint32_t r_address; // offset in the section to what is being relocated + uint32_t r_symbolnum; // symbol index if r_extern == 1 else section index + bool r_pcrel; // was relocated pc-relative already + uint8_t r_length; // length = 2 ^ r_length + bool r_extern; // + uint8_t r_type; // if not 0, machine-specific relocation type. + bool r_scattered; // 1 = scattered, 0 = non-scattered + int32_t r_value; // the value the item to be relocated is referring + // to. + public: + uint32_t getPackedFields() const { + if (r_scattered) + return (1 << 31) | (r_pcrel << 30) | ((r_length & 3) << 28) | + ((r_type & 15) << 24) | (r_address & 0x00FFFFFF); + else + return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | + (r_extern << 4) | (r_type & 15); + } + uint32_t getAddress() const { return r_scattered ? r_value : r_address; } + uint32_t getRawAddress() const { return r_address; } + + MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len, + bool ext, uint8_t type, bool scattered = false, + int32_t value = 0) : + r_address(addr), r_symbolnum(index), r_pcrel(pcrel), r_length(len), + r_extern(ext), r_type(type), r_scattered(scattered), r_value(value) {} + }; + +} // end llvm namespace + +#endif // LLVM_CODEGEN_MACHO_RELOCATION_H diff --git a/final/include/llvm/CodeGen/MachineBasicBlock.h b/final/include/llvm/CodeGen/MachineBasicBlock.h new file mode 100644 index 00000000000..19060933888 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineBasicBlock.h @@ -0,0 +1,493 @@ +//===-- llvm/CodeGen/MachineBasicBlock.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the sequence of machine instructions for a basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H +#define LLVM_CODEGEN_MACHINEBASICBLOCK_H + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/ADT/GraphTraits.h" +#include + +namespace llvm { + +class Pass; +class BasicBlock; +class MachineFunction; +class MCSymbol; +class SlotIndexes; +class StringRef; +class raw_ostream; + +template <> +struct ilist_traits : public ilist_default_traits { +private: + mutable ilist_half_node Sentinel; + + // this is only set by the MachineBasicBlock owning the LiveList + friend class MachineBasicBlock; + MachineBasicBlock* Parent; + +public: + MachineInstr *createSentinel() const { + return static_cast(&Sentinel); + } + void destroySentinel(MachineInstr *) const {} + + MachineInstr *provideInitialHead() const { return createSentinel(); } + MachineInstr *ensureHead(MachineInstr*) const { return createSentinel(); } + static void noteHead(MachineInstr*, MachineInstr*) {} + + void addNodeToList(MachineInstr* N); + void removeNodeFromList(MachineInstr* N); + void transferNodesFromList(ilist_traits &SrcTraits, + ilist_iterator first, + ilist_iterator last); + void deleteNode(MachineInstr *N); +private: + void createNode(const MachineInstr &); +}; + +class MachineBasicBlock : public ilist_node { + typedef ilist Instructions; + Instructions Insts; + const BasicBlock *BB; + int Number; + MachineFunction *xParent; + + /// Predecessors/Successors - Keep track of the predecessor / successor + /// basicblocks. + std::vector Predecessors; + std::vector Successors; + + /// LiveIns - Keep track of the physical registers that are livein of + /// the basicblock. + std::vector LiveIns; + + /// Alignment - Alignment of the basic block. Zero if the basic block does + /// not need to be aligned. + unsigned Alignment; + + /// IsLandingPad - Indicate that this basic block is entered via an + /// exception handler. + bool IsLandingPad; + + /// AddressTaken - Indicate that this basic block is potentially the + /// target of an indirect branch. + bool AddressTaken; + + // Intrusive list support + MachineBasicBlock() {} + + explicit MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb); + + ~MachineBasicBlock(); + + // MachineBasicBlocks are allocated and owned by MachineFunction. + friend class MachineFunction; + +public: + /// getBasicBlock - Return the LLVM basic block that this instance + /// corresponded to originally. Note that this may be NULL if this instance + /// does not correspond directly to an LLVM basic block. + /// + const BasicBlock *getBasicBlock() const { return BB; } + + /// getName - Return the name of the corresponding LLVM basic block, or + /// "(null)". + StringRef getName() const; + + /// hasAddressTaken - Test whether this block is potentially the target + /// of an indirect branch. + bool hasAddressTaken() const { return AddressTaken; } + + /// setHasAddressTaken - Set this block to reflect that it potentially + /// is the target of an indirect branch. + void setHasAddressTaken() { AddressTaken = true; } + + /// getParent - Return the MachineFunction containing this basic block. + /// + const MachineFunction *getParent() const { return xParent; } + MachineFunction *getParent() { return xParent; } + + typedef Instructions::iterator iterator; + typedef Instructions::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + unsigned size() const { return (unsigned)Insts.size(); } + bool empty() const { return Insts.empty(); } + + MachineInstr& front() { return Insts.front(); } + MachineInstr& back() { return Insts.back(); } + const MachineInstr& front() const { return Insts.front(); } + const MachineInstr& back() const { return Insts.back(); } + + iterator begin() { return Insts.begin(); } + const_iterator begin() const { return Insts.begin(); } + iterator end() { return Insts.end(); } + const_iterator end() const { return Insts.end(); } + reverse_iterator rbegin() { return Insts.rbegin(); } + const_reverse_iterator rbegin() const { return Insts.rbegin(); } + reverse_iterator rend () { return Insts.rend(); } + const_reverse_iterator rend () const { return Insts.rend(); } + + // Machine-CFG iterators + typedef std::vector::iterator pred_iterator; + typedef std::vector::const_iterator const_pred_iterator; + typedef std::vector::iterator succ_iterator; + typedef std::vector::const_iterator const_succ_iterator; + typedef std::vector::reverse_iterator + pred_reverse_iterator; + typedef std::vector::const_reverse_iterator + const_pred_reverse_iterator; + typedef std::vector::reverse_iterator + succ_reverse_iterator; + typedef std::vector::const_reverse_iterator + const_succ_reverse_iterator; + + pred_iterator pred_begin() { return Predecessors.begin(); } + const_pred_iterator pred_begin() const { return Predecessors.begin(); } + pred_iterator pred_end() { return Predecessors.end(); } + const_pred_iterator pred_end() const { return Predecessors.end(); } + pred_reverse_iterator pred_rbegin() + { return Predecessors.rbegin();} + const_pred_reverse_iterator pred_rbegin() const + { return Predecessors.rbegin();} + pred_reverse_iterator pred_rend() + { return Predecessors.rend(); } + const_pred_reverse_iterator pred_rend() const + { return Predecessors.rend(); } + unsigned pred_size() const { + return (unsigned)Predecessors.size(); + } + bool pred_empty() const { return Predecessors.empty(); } + succ_iterator succ_begin() { return Successors.begin(); } + const_succ_iterator succ_begin() const { return Successors.begin(); } + succ_iterator succ_end() { return Successors.end(); } + const_succ_iterator succ_end() const { return Successors.end(); } + succ_reverse_iterator succ_rbegin() + { return Successors.rbegin(); } + const_succ_reverse_iterator succ_rbegin() const + { return Successors.rbegin(); } + succ_reverse_iterator succ_rend() + { return Successors.rend(); } + const_succ_reverse_iterator succ_rend() const + { return Successors.rend(); } + unsigned succ_size() const { + return (unsigned)Successors.size(); + } + bool succ_empty() const { return Successors.empty(); } + + // LiveIn management methods. + + /// addLiveIn - Add the specified register as a live in. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + + /// removeLiveIn - Remove the specified register from the live in set. + /// + void removeLiveIn(unsigned Reg); + + /// isLiveIn - Return true if the specified register is in the live in set. + /// + bool isLiveIn(unsigned Reg) const; + + // Iteration support for live in sets. These sets are kept in sorted + // order by their register number. + typedef std::vector::const_iterator livein_iterator; + livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + + /// getAlignment - Return alignment of the basic block. + /// + unsigned getAlignment() const { return Alignment; } + + /// setAlignment - Set alignment of the basic block. + /// + void setAlignment(unsigned Align) { Alignment = Align; } + + /// isLandingPad - Returns true if the block is a landing pad. That is + /// this basic block is entered via an exception handler. + bool isLandingPad() const { return IsLandingPad; } + + /// setIsLandingPad - Indicates the block is a landing pad. That is + /// this basic block is entered via an exception handler. + void setIsLandingPad() { IsLandingPad = true; } + + /// getLandingPadSuccessor - If this block has a successor that is a landing + /// pad, return it. Otherwise return NULL. + const MachineBasicBlock *getLandingPadSuccessor() const; + + // Code Layout methods. + + /// moveBefore/moveAfter - move 'this' block before or after the specified + /// block. This only moves the block, it does not modify the CFG or adjust + /// potential fall-throughs at the end of the block. + void moveBefore(MachineBasicBlock *NewAfter); + void moveAfter(MachineBasicBlock *NewBefore); + + /// updateTerminator - Update the terminator instructions in block to account + /// for changes to the layout. If the block previously used a fallthrough, + /// it may now need a branch, and if it previously used branching it may now + /// be able to use a fallthrough. + void updateTerminator(); + + // Machine-CFG mutators + + /// addSuccessor - Add succ as a successor of this MachineBasicBlock. + /// The Predecessors list of succ is automatically updated. + /// + void addSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove successor from the successors list of this + /// MachineBasicBlock. The Predecessors list of succ is automatically updated. + /// + void removeSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove specified successor from the successors list of + /// this MachineBasicBlock. The Predecessors list of succ is automatically + /// updated. Return the iterator to the element after the one removed. + /// + succ_iterator removeSuccessor(succ_iterator I); + + /// transferSuccessors - Transfers all the successors from MBB to this + /// machine basic block (i.e., copies all the successors fromMBB and + /// remove all the successors from fromMBB). + void transferSuccessors(MachineBasicBlock *fromMBB); + + /// transferSuccessorsAndUpdatePHIs - Transfers all the successors, as + /// in transferSuccessors, and update PHI operands in the successor blocks + /// which refer to fromMBB to refer to this. + void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB); + + /// isSuccessor - Return true if the specified MBB is a successor of this + /// block. + bool isSuccessor(const MachineBasicBlock *MBB) const; + + /// isLayoutSuccessor - Return true if the specified MBB will be emitted + /// immediately after this block, such that if this block exits by + /// falling through, control will transfer to the specified MBB. Note + /// that MBB need not be a successor at all, for example if this block + /// ends with an unconditional branch to some other block. + bool isLayoutSuccessor(const MachineBasicBlock *MBB) const; + + /// canFallThrough - Return true if the block can implicitly transfer + /// control to the block after it by falling off the end of it. This should + /// return false if it can reach the block after it, but it uses an explicit + /// branch to do so (e.g., a table jump). True is a conservative answer. + bool canFallThrough(); + + /// Returns a pointer to the first instructon in this block that is not a + /// PHINode instruction. When adding instruction to the beginning of the + /// basic block, they should be added before the returned value, not before + /// the first instruction, which might be PHI. + /// Returns end() is there's no non-PHI instruction. + iterator getFirstNonPHI(); + + /// SkipPHIsAndLabels - Return the first instruction in MBB after I that is + /// not a PHI or a label. This is the correct point to insert copies at the + /// beginning of a basic block. + iterator SkipPHIsAndLabels(iterator I); + + /// getFirstTerminator - returns an iterator to the first terminator + /// instruction of this basic block. If a terminator does not exist, + /// it returns end() + iterator getFirstTerminator(); + + /// getLastNonDebugInstr - returns an iterator to the last non-debug + /// instruction in the basic block, or end() + iterator getLastNonDebugInstr(); + + /// SplitCriticalEdge - Split the critical edge from this block to the + /// given successor block, and return the newly created block, or null + /// if splitting is not possible. + /// + /// This function updates LiveVariables, MachineDominatorTree, and + /// MachineLoopInfo, as applicable. + MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P); + + void pop_front() { Insts.pop_front(); } + void pop_back() { Insts.pop_back(); } + void push_back(MachineInstr *MI) { Insts.push_back(MI); } + template + void insert(iterator I, IT S, IT E) { Insts.insert(I, S, E); } + iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); } + iterator insertAfter(iterator I, MachineInstr *M) { + return Insts.insertAfter(I, M); + } + + // erase - Remove the specified element or range from the instruction list. + // These functions delete any instructions removed. + // + iterator erase(iterator I) { return Insts.erase(I); } + iterator erase(iterator I, iterator E) { return Insts.erase(I, E); } + MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); } + void clear() { Insts.clear(); } + + /// splice - Take an instruction from MBB 'Other' at the position From, + /// and insert it into this MBB right before 'where'. + void splice(iterator where, MachineBasicBlock *Other, iterator From) { + Insts.splice(where, Other->Insts, From); + } + + /// splice - Take a block of instructions from MBB 'Other' in the range [From, + /// To), and insert them into this MBB right before 'where'. + void splice(iterator where, MachineBasicBlock *Other, iterator From, + iterator To) { + Insts.splice(where, Other->Insts, From, To); + } + + /// removeFromParent - This method unlinks 'this' from the containing + /// function, and returns it, but does not delete it. + MachineBasicBlock *removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing + /// function and deletes it. + void eraseFromParent(); + + /// ReplaceUsesOfBlockWith - Given a machine basic block that branched to + /// 'Old', change the code and CFG so that it branches to 'New' instead. + void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in + /// the CFG to be inserted. If we have proven that MBB can only branch to + /// DestA and DestB, remove any other MBB successors from the CFG. DestA and + /// DestB can be null. Besides DestA and DestB, retain other edges leading + /// to LandingPads (currently there can be only one; we don't check or require + /// that here). Note it is possible that DestA and/or DestB are LandingPads. + bool CorrectExtraCFGEdges(MachineBasicBlock *DestA, + MachineBasicBlock *DestB, + bool isCond); + + /// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping + /// any DBG_VALUE instructions. Return UnknownLoc if there is none. + DebugLoc findDebugLoc(MachineBasicBlock::iterator &MBBI); + + // Debugging methods. + void dump() const; + void print(raw_ostream &OS, SlotIndexes* = 0) const; + + /// getNumber - MachineBasicBlocks are uniquely numbered at the function + /// level, unless they're not in a MachineFunction yet, in which case this + /// will return -1. + /// + int getNumber() const { return Number; } + void setNumber(int N) { Number = N; } + + /// getSymbol - Return the MCSymbol for this basic block. + /// + MCSymbol *getSymbol() const; + +private: // Methods used to maintain doubly linked list of blocks... + friend struct ilist_traits; + + // Machine-CFG mutators + + /// addPredecessor - Remove pred as a predecessor of this MachineBasicBlock. + /// Don't do this unless you know what you're doing, because it doesn't + /// update pred's successors list. Use pred->addSuccessor instead. + /// + void addPredecessor(MachineBasicBlock *pred); + + /// removePredecessor - Remove pred as a predecessor of this + /// MachineBasicBlock. Don't do this unless you know what you're + /// doing, because it doesn't update pred's successors list. Use + /// pred->removeSuccessor instead. + /// + void removePredecessor(MachineBasicBlock *pred); +}; + +raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); + +void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t); + +// This is useful when building IndexedMaps keyed on basic block pointers. +struct MBB2NumberFunctor : + public std::unary_function { + unsigned operator()(const MachineBasicBlock *MBB) const { + return MBB->getNumber(); + } +}; + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for machine basic block graphs (machine-CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... +// + +template <> struct GraphTraits { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +template <> struct GraphTraits { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(const MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... and to walk it +// in inverse order. Inverse order for a function is considered +// to be when traversing the predecessor edges of a MBB +// instead of the successor edges. +// +template <> struct GraphTraits > { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +template <> struct GraphTraits > { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineCodeEmitter.h b/final/include/llvm/CodeGen/MachineCodeEmitter.h new file mode 100644 index 00000000000..8fc80adf7fb --- /dev/null +++ b/final/include/llvm/CodeGen/MachineCodeEmitter.h @@ -0,0 +1,332 @@ +//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- 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 an abstract interface that is used by the machine code +// emission framework to output the code. This allows machine code emission to +// be separated from concerns such as resolution of call targets, and where the +// machine code will be written (memory or disk, f.e.). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H +#define LLVM_CODEGEN_MACHINECODEEMITTER_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineFunction; +class MachineModuleInfo; +class MachineRelocation; +class Value; +class GlobalValue; +class Function; +class MCSymbol; + +/// MachineCodeEmitter - This class defines two sorts of methods: those for +/// emitting the actual bytes of machine code, and those for emitting auxillary +/// structures, such as jump tables, relocations, etc. +/// +/// Emission of machine code is complicated by the fact that we don't (in +/// general) know the size of the machine code that we're about to emit before +/// we emit it. As such, we preallocate a certain amount of memory, and set the +/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we +/// emit machine instructions, we advance the CurBufferPtr to indicate the +/// location of the next byte to emit. In the case of a buffer overflow (we +/// need to emit more machine code than we have allocated space for), the +/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire +/// function has been emitted, the overflow condition is checked, and if it has +/// occurred, more memory is allocated, and we reemit the code into it. +/// +class MachineCodeEmitter { +protected: + /// BufferBegin/BufferEnd - Pointers to the start and end of the memory + /// allocated for this code buffer. + uint8_t *BufferBegin, *BufferEnd; + /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting + /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// this pointer is at BufferEnd, it will never move due to code emission, and + /// all code emission requests will be ignored (this is the buffer overflow + /// condition). + uint8_t *CurBufferPtr; + +public: + virtual ~MachineCodeEmitter() {} + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + /// + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + /// + virtual bool finishFunction(MachineFunction &F) = 0; + + /// emitByte - This callback is invoked when a byte needs to be written to the + /// output stream. + /// + void emitByte(uint8_t B) { + if (CurBufferPtr != BufferEnd) + *CurBufferPtr++ = B; + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitWordLE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + emitWordLEInto(CurBufferPtr, W); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be + /// written to an arbitrary buffer in little-endian format. Buf must have at + /// least 4 bytes of available space. + /// + static void emitWordLEInto(uint8_t *&Buf, uint32_t W) { + *Buf++ = (uint8_t)(W >> 0); + *Buf++ = (uint8_t)(W >> 8); + *Buf++ = (uint8_t)(W >> 16); + *Buf++ = (uint8_t)(W >> 24); + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitWordBE(uint32_t W) { + if (4 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitDWordLE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 0); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 56); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitDWordBE(uint64_t W) { + if (8 <= BufferEnd-CurBufferPtr) { + *CurBufferPtr++ = (uint8_t)(W >> 56); + *CurBufferPtr++ = (uint8_t)(W >> 48); + *CurBufferPtr++ = (uint8_t)(W >> 40); + *CurBufferPtr++ = (uint8_t)(W >> 32); + *CurBufferPtr++ = (uint8_t)(W >> 24); + *CurBufferPtr++ = (uint8_t)(W >> 16); + *CurBufferPtr++ = (uint8_t)(W >> 8); + *CurBufferPtr++ = (uint8_t)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitAlignment - Move the CurBufferPtr pointer up to the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + + if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { + // Move the current buffer ptr up to the specified alignment. + CurBufferPtr = + (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & + ~(uintptr_t)(Alignment-1)); + } else { + CurBufferPtr = BufferEnd; + } + } + + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the output stream. + void emitULEB128Bytes(uint64_t Value) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value) Byte |= 0x80; + emitByte(Byte); + } while (Value); + } + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the output stream. + void emitSLEB128Bytes(uint64_t Value) { + uint64_t Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + emitByte(Byte); + } while (IsMore); + } + + /// emitString - This callback is invoked when a String needs to be + /// written to the output stream. + void emitString(const std::string &String) { + for (unsigned i = 0, N = static_cast(String.size()); + i < N; ++i) { + uint8_t C = String[i]; + emitByte(C); + } + emitByte(0); + } + + /// emitInt32 - Emit a int32 directive. + void emitInt32(int32_t Value) { + if (4 <= BufferEnd-CurBufferPtr) { + *((uint32_t*)CurBufferPtr) = Value; + CurBufferPtr += 4; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt64 - Emit a int64 directive. + void emitInt64(uint64_t Value) { + if (8 <= BufferEnd-CurBufferPtr) { + *((uint64_t*)CurBufferPtr) = Value; + CurBufferPtr += 8; + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitInt32At - Emit the Int32 Value in Addr. + void emitInt32At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint32_t*)Addr) = (uint32_t)Value; + } + + /// emitInt64At - Emit the Int64 Value in Addr. + void emitInt64At(uintptr_t *Addr, uintptr_t Value) { + if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) + (*(uint64_t*)Addr) = (uint64_t)Value; + } + + /// processDebugLoc - Records debug location information about a + /// MachineInstruction. This is called before emitting any bytes associated + /// with the instruction. Even if successive instructions have the same debug + /// location, this method will be called for each one. + virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {} + + /// emitLabel - Emits a label + virtual void emitLabel(MCSymbol *Label) = 0; + + /// allocateSpace - Allocate a block of space in the current output buffer, + /// returning null (and setting conditions to indicate buffer overflow) on + /// failure. Alignment is the alignment in bytes of the buffer desired. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { + emitAlignment(Alignment); + void *Result; + + // Check for buffer overflow. + if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { + CurBufferPtr = BufferEnd; + Result = 0; + } else { + // Allocate the space. + Result = CurBufferPtr; + CurBufferPtr += Size; + } + + return Result; + } + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + /// + virtual uintptr_t getCurrentPCValue() const { + return (uintptr_t)CurBufferPtr; + } + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + virtual uintptr_t getCurrentPCOffset() const { + return CurBufferPtr-BufferBegin; + } + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + virtual bool earlyResolveAddresses() const = 0; + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + virtual void addRelocation(const MachineRelocation &MR) = 0; + + /// FIXME: These should all be handled with relocations! + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + /// + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + /// + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + /// + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; + + /// getLabelAddress - Return the address of the specified Label, only usable + /// after the LabelID has been emitted. + /// + virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineCodeInfo.h b/final/include/llvm/CodeGen/MachineCodeInfo.h new file mode 100644 index 00000000000..c5c0c445045 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineCodeInfo.h @@ -0,0 +1,53 @@ +//===-- MachineCodeInfo.h - Class used to report JIT 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 MachineCodeInfo, a class used by the JIT ExecutionEngine +// to report information about the generated machine code. +// +// See JIT::runJITOnFunction for usage. +// +//===----------------------------------------------------------------------===// + +#ifndef EE_MACHINE_CODE_INFO_H +#define EE_MACHINE_CODE_INFO_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MachineCodeInfo { +private: + size_t Size; // Number of bytes in memory used + void *Address; // The address of the function in memory + +public: + MachineCodeInfo() : Size(0), Address(0) {} + + void setSize(size_t s) { + Size = s; + } + + void setAddress(void *a) { + Address = a; + } + + size_t size() const { + return Size; + } + + void *address() const { + return Address; + } + +}; + +} + +#endif + diff --git a/final/include/llvm/CodeGen/MachineConstantPool.h b/final/include/llvm/CodeGen/MachineConstantPool.h new file mode 100644 index 00000000000..5727321a0da --- /dev/null +++ b/final/include/llvm/CodeGen/MachineConstantPool.h @@ -0,0 +1,170 @@ +//===-- CodeGen/MachineConstantPool.h - Abstract Constant Pool --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file declares the MachineConstantPool class which is an abstract +/// constant pool to keep track of constants referenced by a function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H +#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H + +#include "llvm/ADT/DenseSet.h" +#include +#include +#include + +namespace llvm { + +class Constant; +class FoldingSetNodeID; +class TargetData; +class TargetMachine; +class Type; +class MachineConstantPool; +class raw_ostream; + +/// Abstract base class for all machine specific constantpool value subclasses. +/// +class MachineConstantPoolValue { + const Type *Ty; + +public: + explicit MachineConstantPoolValue(const Type *ty) : Ty(ty) {} + virtual ~MachineConstantPoolValue() {} + + /// getType - get type of this MachineConstantPoolValue. + /// + const Type *getType() const { return Ty; } + + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are the same as Constant::getRelocationInfo(). + virtual unsigned getRelocationInfo() const = 0; + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) = 0; + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; + + /// print - Implement operator<< + virtual void print(raw_ostream &O) const = 0; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, + const MachineConstantPoolValue &V) { + V.print(OS); + return OS; +} + + +/// This class is a data container for one entry in a MachineConstantPool. +/// It contains a pointer to the value and an offset from the start of +/// the constant pool. +/// @brief An entry in a MachineConstantPool +class MachineConstantPoolEntry { +public: + /// The constant itself. + union { + const Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + + /// The required alignment for this entry. The top bit is set when Val is + /// a MachineConstantPoolValue. + unsigned Alignment; + + MachineConstantPoolEntry(const Constant *V, unsigned A) + : Alignment(A) { + Val.ConstVal = V; + } + MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned A) + : Alignment(A) { + Val.MachineCPVal = V; + Alignment |= 1U << (sizeof(unsigned)*CHAR_BIT-1); + } + + bool isMachineConstantPoolEntry() const { + return (int)Alignment < 0; + } + + int getAlignment() const { + return Alignment & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); + } + + const Type *getType() const; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// 0: This constant pool entry is guaranteed to never have a relocation + /// applied to it (because it holds a simple constant like '4'). + /// 1: This entry has relocations, but the entries are guaranteed to be + /// resolvable by the static linker, so the dynamic linker will never see + /// them. + /// 2: This entry may have arbitrary relocations. + unsigned getRelocationInfo() const; +}; + +/// The MachineConstantPool class keeps track of constants referenced by a +/// function which must be spilled to memory. This is used for constants which +/// are unable to be used directly as operands to instructions, which typically +/// include floating point and large integer constants. +/// +/// Instructions reference the address of these constant pool constants through +/// the use of MO_ConstantPoolIndex values. When emitting assembly or machine +/// code, these virtual address references are converted to refer to the +/// address of the function constant pool values. +/// @brief The machine constant pool. +class MachineConstantPool { + const TargetData *TD; ///< The machine's TargetData. + unsigned PoolAlignment; ///< The alignment for the pool. + std::vector Constants; ///< The pool of constants. + /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. + DenseSet MachineCPVsSharingEntries; +public: + /// @brief The only constructor. + explicit MachineConstantPool(const TargetData *td) + : TD(td), PoolAlignment(1) {} + ~MachineConstantPool(); + + /// getConstantPoolAlignment - Return the alignment required by + /// the whole constant pool, of which the first element must be aligned. + unsigned getConstantPoolAlignment() const { return PoolAlignment; } + + /// getConstantPoolIndex - Create a new entry in the constant pool or return + /// an existing one. User must specify the minimum required alignment for + /// the object. + unsigned getConstantPoolIndex(const Constant *C, unsigned Alignment); + unsigned getConstantPoolIndex(MachineConstantPoolValue *V,unsigned Alignment); + + /// isEmpty - Return true if this constant pool contains no constants. + bool isEmpty() const { return Constants.empty(); } + + const std::vector &getConstants() const { + return Constants; + } + + /// print - Used by the MachineFunction printer to print information about + /// constant pool objects. Implemented in MachineFunction.cpp + /// + void print(raw_ostream &OS) const; + + /// dump - Call print(cerr) to be called from the debugger. + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineDominators.h b/final/include/llvm/CodeGen/MachineDominators.h new file mode 100644 index 00000000000..ab944a2335f --- /dev/null +++ b/final/include/llvm/CodeGen/MachineDominators.h @@ -0,0 +1,202 @@ +//=- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation --*- 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 classes mirroring those in llvm/Analysis/Dominators.h, +// but for target-specific code rather than target-independent IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H +#define LLVM_CODEGEN_MACHINEDOMINATORS_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/DominatorInternals.h" + +namespace llvm { + +template<> +inline void DominatorTreeBase::addRoot(MachineBasicBlock* MBB) { + this->Roots.push_back(MBB); +} + +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); + +typedef DomTreeNodeBase MachineDomTreeNode; + +//===------------------------------------- +/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to +/// compute a normal dominator tree. +/// +class MachineDominatorTree : public MachineFunctionPass { +public: + static char ID; // Pass ID, replacement for typeid + DominatorTreeBase* DT; + + MachineDominatorTree(); + + ~MachineDominatorTree(); + + DominatorTreeBase& getBase() { return *DT; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector &getRoots() const { + return DT->getRoots(); + } + + inline MachineBasicBlock *getRoot() const { + return DT->getRoot(); + } + + inline MachineDomTreeNode *getRootNode() const { + return DT->getRootNode(); + } + + virtual bool runOnMachineFunction(MachineFunction &F); + + inline bool dominates(MachineDomTreeNode* A, MachineDomTreeNode* B) const { + return DT->dominates(A, B); + } + + inline bool dominates(MachineBasicBlock* A, MachineBasicBlock* B) const { + return DT->dominates(A, B); + } + + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(MachineInstr *A, MachineInstr *B) const { + MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); + if (BBA != BBB) return DT->dominates(BBA, BBB); + + // Loop through the basic block until we find A or B. + MachineBasicBlock::iterator I = BBA->begin(); + for (; &*I != A && &*I != B; ++I) /*empty*/; + + //if(!DT.IsPostDominators) { + // A dominates B if it is found first in the basic block. + return &*I == A; + //} else { + // // A post-dominates B if B is found first in the basic block. + // return &*I == B; + //} + } + + inline bool properlyDominates(const MachineDomTreeNode* A, + MachineDomTreeNode* B) const { + return DT->properlyDominates(A, B); + } + + inline bool properlyDominates(MachineBasicBlock* A, + MachineBasicBlock* B) const { + return DT->properlyDominates(A, B); + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, + MachineBasicBlock *B) { + return DT->findNearestCommonDominator(A, B); + } + + inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { + return DT->getNode(BB); + } + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB) { + return DT->addNewBlock(BB, DomBB); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + inline void changeImmediateDominator(MachineBasicBlock *N, + MachineBasicBlock* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + inline void changeImmediateDominator(MachineDomTreeNode *N, + MachineDomTreeNode* NewIDom) { + DT->changeImmediateDominator(N, NewIDom); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + inline void eraseNode(MachineBasicBlock *BB) { + DT->eraseNode(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + inline void splitBlock(MachineBasicBlock* NewBB) { + DT->splitBlock(NewBB); + } + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + bool isReachableFromEntry(MachineBasicBlock *A) { + return DT->isReachableFromEntry(A); + } + + virtual void releaseMemory(); + + virtual void print(raw_ostream &OS, const Module*) const; +}; + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// + +template struct GraphTraits; + +template <> struct GraphTraits { + typedef MachineDomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType* N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType* N) { + return N->end(); + } +}; + +template <> struct GraphTraits + : public GraphTraits { + static NodeType *getEntryNode(MachineDominatorTree *DT) { + return DT->getRootNode(); + } +}; + +} + +#endif diff --git a/final/include/llvm/CodeGen/MachineFrameInfo.h b/final/include/llvm/CodeGen/MachineFrameInfo.h new file mode 100644 index 00000000000..4ea6aa3396a --- /dev/null +++ b/final/include/llvm/CodeGen/MachineFrameInfo.h @@ -0,0 +1,551 @@ +//===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The file defines the MachineFrameInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H +#define LLVM_CODEGEN_MACHINEFRAMEINFO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { +class raw_ostream; +class TargetData; +class TargetRegisterClass; +class Type; +class MachineFunction; +class MachineBasicBlock; +class TargetFrameLowering; +class BitVector; + +/// The CalleeSavedInfo class tracks the information need to locate where a +/// callee saved register is in the current frame. +class CalleeSavedInfo { + unsigned Reg; + int FrameIdx; + +public: + explicit CalleeSavedInfo(unsigned R, int FI = 0) + : Reg(R), FrameIdx(FI) {} + + // Accessors. + unsigned getReg() const { return Reg; } + int getFrameIdx() const { return FrameIdx; } + void setFrameIdx(int FI) { FrameIdx = FI; } +}; + +/// The MachineFrameInfo class represents an abstract stack frame until +/// prolog/epilog code is inserted. This class is key to allowing stack frame +/// representation optimizations, such as frame pointer elimination. It also +/// allows more mundane (but still important) optimizations, such as reordering +/// of abstract objects on the stack frame. +/// +/// To support this, the class assigns unique integer identifiers to stack +/// objects requested clients. These identifiers are negative integers for +/// fixed stack objects (such as arguments passed on the stack) or nonnegative +/// for objects that may be reordered. Instructions which refer to stack +/// objects use a special MO_FrameIndex operand to represent these frame +/// indexes. +/// +/// Because this class keeps track of all references to the stack frame, it +/// knows when a variable sized object is allocated on the stack. This is the +/// sole condition which prevents frame pointer elimination, which is an +/// important optimization on register-poor architectures. Because original +/// variable sized alloca's in the source program are the only source of +/// variable sized stack objects, it is safe to decide whether there will be +/// any variable sized objects before all stack objects are known (for +/// example, register allocator spill code never needs variable sized +/// objects). +/// +/// When prolog/epilog code emission is performed, the final stack frame is +/// built and the machine instructions are modified to refer to the actual +/// stack offsets of the object, eliminating all MO_FrameIndex operands from +/// the program. +/// +/// @brief Abstract Stack Frame Information +class MachineFrameInfo { + + // StackObject - Represent a single object allocated on the stack. + struct StackObject { + // SPOffset - The offset of this object from the stack pointer on entry to + // the function. This field has no meaning for a variable sized element. + int64_t SPOffset; + + // The size of this object on the stack. 0 means a variable sized object, + // ~0ULL means a dead object. + uint64_t Size; + + // Alignment - The required alignment of this stack slot. + unsigned Alignment; + + // isImmutable - If true, the value of the stack object is set before + // entering the function and is not modified inside the function. By + // default, fixed objects are immutable unless marked otherwise. + bool isImmutable; + + // isSpillSlot - If true the stack object is used as spill slot. It + // cannot alias any other memory objects. + bool isSpillSlot; + + // MayNeedSP - If true the stack object triggered the creation of the stack + // protector. We should allocate this object right after the stack + // protector. + bool MayNeedSP; + + // PreAllocated - If true, the object was mapped into the local frame + // block and doesn't need additional handling for allocation beyond that. + bool PreAllocated; + + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, + bool isSS, bool NSP) + : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), + isSpillSlot(isSS), MayNeedSP(NSP), PreAllocated(false) {} + }; + + /// Objects - The list of stack objects allocated... + /// + std::vector Objects; + + /// NumFixedObjects - This contains the number of fixed objects contained on + /// the stack. Because fixed objects are stored at a negative index in the + /// Objects list, this is also the index to the 0th object in the list. + /// + unsigned NumFixedObjects; + + /// HasVarSizedObjects - This boolean keeps track of whether any variable + /// sized objects have been allocated yet. + /// + bool HasVarSizedObjects; + + /// FrameAddressTaken - This boolean keeps track of whether there is a call + /// to builtin \@llvm.frameaddress. + bool FrameAddressTaken; + + /// ReturnAddressTaken - This boolean keeps track of whether there is a call + /// to builtin \@llvm.returnaddress. + bool ReturnAddressTaken; + + /// StackSize - The prolog/epilog code inserter calculates the final stack + /// offsets for all of the fixed size objects, updating the Objects list + /// above. It then updates StackSize to contain the number of bytes that need + /// to be allocated on entry to the function. + /// + uint64_t StackSize; + + /// OffsetAdjustment - The amount that a frame offset needs to be adjusted to + /// have the actual offset from the stack/frame pointer. The exact usage of + /// this is target-dependent, but it is typically used to adjust between + /// SP-relative and FP-relative offsets. E.G., if objects are accessed via + /// SP then OffsetAdjustment is zero; if FP is used, OffsetAdjustment is set + /// to the distance between the initial SP and the value in FP. For many + /// targets, this value is only used when generating debug info (via + /// TargetRegisterInfo::getFrameIndexOffset); when generating code, the + /// corresponding adjustments are performed directly. + int OffsetAdjustment; + + /// MaxAlignment - The prolog/epilog code inserter may process objects + /// that require greater alignment than the default alignment the target + /// provides. To handle this, MaxAlignment is set to the maximum alignment + /// needed by the objects on the current frame. If this is greater than the + /// native alignment maintained by the compiler, dynamic alignment code will + /// be needed. + /// + unsigned MaxAlignment; + + /// AdjustsStack - Set to true if this function adjusts the stack -- e.g., + /// when calling another function. This is only valid during and after + /// prolog/epilog code insertion. + bool AdjustsStack; + + /// HasCalls - Set to true if this function has any function calls. + bool HasCalls; + + /// StackProtectorIdx - The frame index for the stack protector. + int StackProtectorIdx; + + /// MaxCallFrameSize - This contains the size of the largest call frame if the + /// target uses frame setup/destroy pseudo instructions (as defined in the + /// TargetFrameInfo class). This information is important for frame pointer + /// elimination. If is only valid during and after prolog/epilog code + /// insertion. + /// + unsigned MaxCallFrameSize; + + /// CSInfo - The prolog/epilog code inserter fills in this vector with each + /// callee saved register saved in the frame. Beyond its use by the prolog/ + /// epilog code inserter, this data used for debug info and exception + /// handling. + std::vector CSInfo; + + /// CSIValid - Has CSInfo been set yet? + bool CSIValid; + + /// TargetFrameLowering - Target information about frame layout. + /// + const TargetFrameLowering &TFI; + + /// LocalFrameObjects - References to frame indices which are mapped + /// into the local frame allocation block. + SmallVector, 32> LocalFrameObjects; + + /// LocalFrameSize - Size of the pre-allocated local frame block. + int64_t LocalFrameSize; + + /// Required alignment of the local object blob, which is the strictest + /// alignment of any object in it. + unsigned LocalFrameMaxAlign; + + /// Whether the local object blob needs to be allocated together. If not, + /// PEI should ignore the isPreAllocated flags on the stack objects and + /// just allocate them normally. + bool UseLocalStackAllocationBlock; + +public: + explicit MachineFrameInfo(const TargetFrameLowering &tfi) : TFI(tfi) { + StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; + HasVarSizedObjects = false; + FrameAddressTaken = false; + ReturnAddressTaken = false; + AdjustsStack = false; + HasCalls = false; + StackProtectorIdx = -1; + MaxCallFrameSize = 0; + CSIValid = false; + LocalFrameSize = 0; + LocalFrameMaxAlign = 0; + UseLocalStackAllocationBlock = false; + } + + /// hasStackObjects - Return true if there are any stack objects in this + /// function. + /// + bool hasStackObjects() const { return !Objects.empty(); } + + /// hasVarSizedObjects - This method may be called any time after instruction + /// selection is complete to determine if the stack frame for this function + /// contains any variable sized objects. + /// + bool hasVarSizedObjects() const { return HasVarSizedObjects; } + + /// getStackProtectorIndex/setStackProtectorIndex - Return the index for the + /// stack protector object. + /// + int getStackProtectorIndex() const { return StackProtectorIdx; } + void setStackProtectorIndex(int I) { StackProtectorIdx = I; } + + /// isFrameAddressTaken - This method may be called any time after instruction + /// selection is complete to determine if there is a call to + /// \@llvm.frameaddress in this function. + bool isFrameAddressTaken() const { return FrameAddressTaken; } + void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } + + /// isReturnAddressTaken - This method may be called any time after + /// instruction selection is complete to determine if there is a call to + /// \@llvm.returnaddress in this function. + bool isReturnAddressTaken() const { return ReturnAddressTaken; } + void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } + + /// getObjectIndexBegin - Return the minimum frame object index. + /// + int getObjectIndexBegin() const { return -NumFixedObjects; } + + /// getObjectIndexEnd - Return one past the maximum frame object index. + /// + int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; } + + /// getNumFixedObjects - Return the number of fixed objects. + unsigned getNumFixedObjects() const { return NumFixedObjects; } + + /// getNumObjects - Return the number of objects. + /// + unsigned getNumObjects() const { return Objects.size(); } + + /// mapLocalFrameObject - Map a frame index into the local object block + void mapLocalFrameObject(int ObjectIndex, int64_t Offset) { + LocalFrameObjects.push_back(std::pair(ObjectIndex, Offset)); + Objects[ObjectIndex + NumFixedObjects].PreAllocated = true; + } + + /// getLocalFrameObjectMap - Get the local offset mapping for a for an object + std::pair getLocalFrameObjectMap(int i) { + assert (i >= 0 && (unsigned)i < LocalFrameObjects.size() && + "Invalid local object reference!"); + return LocalFrameObjects[i]; + } + + /// getLocalFrameObjectCount - Return the number of objects allocated into + /// the local object block. + int64_t getLocalFrameObjectCount() { return LocalFrameObjects.size(); } + + /// setLocalFrameSize - Set the size of the local object blob. + void setLocalFrameSize(int64_t sz) { LocalFrameSize = sz; } + + /// getLocalFrameSize - Get the size of the local object blob. + int64_t getLocalFrameSize() const { return LocalFrameSize; } + + /// setLocalFrameMaxAlign - Required alignment of the local object blob, + /// which is the strictest alignment of any object in it. + void setLocalFrameMaxAlign(unsigned Align) { LocalFrameMaxAlign = Align; } + + /// getLocalFrameMaxAlign - Return the required alignment of the local + /// object blob. + unsigned getLocalFrameMaxAlign() const { return LocalFrameMaxAlign; } + + /// getUseLocalStackAllocationBlock - Get whether the local allocation blob + /// should be allocated together or let PEI allocate the locals in it + /// directly. + bool getUseLocalStackAllocationBlock() {return UseLocalStackAllocationBlock;} + + /// setUseLocalStackAllocationBlock - Set whether the local allocation blob + /// should be allocated together or let PEI allocate the locals in it + /// directly. + void setUseLocalStackAllocationBlock(bool v) { + UseLocalStackAllocationBlock = v; + } + + /// isObjectPreAllocated - Return true if the object was pre-allocated into + /// the local block. + bool isObjectPreAllocated(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].PreAllocated; + } + + /// getObjectSize - Return the size of the specified object. + /// + int64_t getObjectSize(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Size; + } + + /// setObjectSize - Change the size of the specified stack object. + void setObjectSize(int ObjectIdx, int64_t Size) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].Size = Size; + } + + /// getObjectAlignment - Return the alignment of the specified stack object. + unsigned getObjectAlignment(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Alignment; + } + + /// setObjectAlignment - Change the alignment of the specified stack object. + void setObjectAlignment(int ObjectIdx, unsigned Align) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].Alignment = Align; + MaxAlignment = std::max(MaxAlignment, Align); + } + + /// NeedsStackProtector - Returns true if the object may need stack + /// protectors. + bool MayNeedStackProtector(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].MayNeedSP; + } + + /// getObjectOffset - Return the assigned stack offset of the specified object + /// from the incoming stack pointer. + /// + int64_t getObjectOffset(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Getting frame offset for a dead object?"); + return Objects[ObjectIdx+NumFixedObjects].SPOffset; + } + + /// setObjectOffset - Set the stack frame offset of the specified object. The + /// offset is relative to the stack pointer on entry to the function. + /// + void setObjectOffset(int ObjectIdx, int64_t SPOffset) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Setting frame offset for a dead object?"); + Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; + } + + /// getStackSize - Return the number of bytes that must be allocated to hold + /// all of the fixed size frame objects. This is only valid after + /// Prolog/Epilog code insertion has finalized the stack frame layout. + /// + uint64_t getStackSize() const { return StackSize; } + + /// setStackSize - Set the size of the stack... + /// + void setStackSize(uint64_t Size) { StackSize = Size; } + + /// getOffsetAdjustment - Return the correction for frame offsets. + /// + int getOffsetAdjustment() const { return OffsetAdjustment; } + + /// setOffsetAdjustment - Set the correction for frame offsets. + /// + void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } + + /// getMaxAlignment - Return the alignment in bytes that this function must be + /// aligned to, which is greater than the default stack alignment provided by + /// the target. + /// + unsigned getMaxAlignment() const { return MaxAlignment; } + + /// setMaxAlignment - Set the preferred alignment. + /// + void setMaxAlignment(unsigned Align) { MaxAlignment = Align; } + + /// AdjustsStack - Return true if this function adjusts the stack -- e.g., + /// when calling another function. This is only valid during and after + /// prolog/epilog code insertion. + bool adjustsStack() const { return AdjustsStack; } + void setAdjustsStack(bool V) { AdjustsStack = V; } + + /// hasCalls - Return true if the current function has any function calls. + bool hasCalls() const { return HasCalls; } + void setHasCalls(bool V) { HasCalls = V; } + + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be + /// allocated for an outgoing function call. This is only available if + /// CallFrameSetup/Destroy pseudo instructions are used by the target, and + /// then only during or after prolog/epilog code insertion. + /// + unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } + void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } + + /// CreateFixedObject - Create a new object at a fixed location on the stack. + /// All fixed objects should be created before other objects are created for + /// efficiency. By default, fixed objects are immutable. This returns an + /// index with a negative value. + /// + int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable); + + + /// isFixedObjectIndex - Returns true if the specified index corresponds to a + /// fixed stack object. + bool isFixedObjectIndex(int ObjectIdx) const { + return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); + } + + /// isImmutableObjectIndex - Returns true if the specified index corresponds + /// to an immutable object. + bool isImmutableObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isImmutable; + } + + /// isSpillSlotObjectIndex - Returns true if the specified index corresponds + /// to a spill slot.. + bool isSpillSlotObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isSpillSlot;; + } + + /// isDeadObjectIndex - Returns true if the specified index corresponds to + /// a dead object. + bool isDeadObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; + } + + /// CreateStackObject - Create a new statically sized stack object, returning + /// a nonnegative identifier to represent it. + /// + int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, + bool MayNeedSP = false) { + assert(Size != 0 && "Cannot allocate zero size stack objects!"); + Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP)); + int Index = (int)Objects.size() - NumFixedObjects - 1; + assert(Index >= 0 && "Bad frame index!"); + MaxAlignment = std::max(MaxAlignment, Alignment); + return Index; + } + + /// CreateSpillStackObject - Create a new statically sized stack object that + /// represents a spill slot, returning a nonnegative identifier to represent + /// it. + /// + int CreateSpillStackObject(uint64_t Size, unsigned Alignment) { + CreateStackObject(Size, Alignment, true, false); + int Index = (int)Objects.size() - NumFixedObjects - 1; + MaxAlignment = std::max(MaxAlignment, Alignment); + return Index; + } + + /// RemoveStackObject - Remove or mark dead a statically sized stack object. + /// + void RemoveStackObject(int ObjectIdx) { + // Mark it dead. + Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL; + } + + /// CreateVariableSizedObject - Notify the MachineFrameInfo object that a + /// variable sized object has been created. This must be created whenever a + /// variable sized object is created, whether or not the index returned is + /// actually used. + /// + int CreateVariableSizedObject(unsigned Alignment) { + HasVarSizedObjects = true; + Objects.push_back(StackObject(0, Alignment, 0, false, false, true)); + MaxAlignment = std::max(MaxAlignment, Alignment); + return (int)Objects.size()-NumFixedObjects-1; + } + + /// getCalleeSavedInfo - Returns a reference to call saved info vector for the + /// current function. + const std::vector &getCalleeSavedInfo() const { + return CSInfo; + } + + /// setCalleeSavedInfo - Used by prolog/epilog inserter to set the function's + /// callee saved information. + void setCalleeSavedInfo(const std::vector &CSI) { + CSInfo = CSI; + } + + /// isCalleeSavedInfoValid - Has the callee saved info been calculated yet? + bool isCalleeSavedInfoValid() const { return CSIValid; } + + void setCalleeSavedInfoValid(bool v) { CSIValid = v; } + + /// getPristineRegs - Return a set of physical registers that are pristine on + /// entry to the MBB. + /// + /// Pristine registers hold a value that is useless to the current function, + /// but that must be preserved - they are callee saved registers that have not + /// been saved yet. + /// + /// Before the PrologueEpilogueInserter has placed the CSR spill code, this + /// method always returns an empty set. + BitVector getPristineRegs(const MachineBasicBlock *MBB) const; + + /// print - Used by the MachineFunction printer to print information about + /// stack objects. Implemented in MachineFunction.cpp + /// + void print(const MachineFunction &MF, raw_ostream &OS) const; + + /// dump - Print the function to stderr. + void dump(const MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineFunction.h b/final/include/llvm/CodeGen/MachineFunction.h new file mode 100644 index 00000000000..f56c053e470 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineFunction.h @@ -0,0 +1,478 @@ +//===-- llvm/CodeGen/MachineFunction.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect native machine code for a function. This class contains a list of +// MachineBasicBlock instances that make up the current compiled function. +// +// This class also contains pointers to various classes which hold +// target-specific information about the generated code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H +#define LLVM_CODEGEN_MACHINEFUNCTION_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/ilist.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Recycler.h" + +namespace llvm { + +class Value; +class Function; +class GCModuleInfo; +class MachineRegisterInfo; +class MachineFrameInfo; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineModuleInfo; +class MCContext; +class Pass; +class TargetMachine; +class TargetRegisterClass; +struct MachinePointerInfo; + +template <> +struct ilist_traits + : public ilist_default_traits { + mutable ilist_half_node Sentinel; +public: + MachineBasicBlock *createSentinel() const { + return static_cast(&Sentinel); + } + void destroySentinel(MachineBasicBlock *) const {} + + MachineBasicBlock *provideInitialHead() const { return createSentinel(); } + MachineBasicBlock *ensureHead(MachineBasicBlock*) const { + return createSentinel(); + } + static void noteHead(MachineBasicBlock*, MachineBasicBlock*) {} + + void addNodeToList(MachineBasicBlock* MBB); + void removeNodeFromList(MachineBasicBlock* MBB); + void deleteNode(MachineBasicBlock *MBB); +private: + void createNode(const MachineBasicBlock &); +}; + +/// MachineFunctionInfo - This class can be derived from and used by targets to +/// hold private target-specific information for each MachineFunction. Objects +/// of type are accessed/created with MF::getInfo and destroyed when the +/// MachineFunction is destroyed. +struct MachineFunctionInfo { + virtual ~MachineFunctionInfo(); +}; + +class MachineFunction { + const Function *Fn; + const TargetMachine &Target; + MCContext &Ctx; + MachineModuleInfo &MMI; + GCModuleInfo *GMI; + + // RegInfo - Information about each register in use in the function. + MachineRegisterInfo *RegInfo; + + // Used to keep track of target-specific per-machine function information for + // the target implementation. + MachineFunctionInfo *MFInfo; + + // Keep track of objects allocated on the stack. + MachineFrameInfo *FrameInfo; + + // Keep track of constants which are spilled to memory + MachineConstantPool *ConstantPool; + + // Keep track of jump tables for switch instructions + MachineJumpTableInfo *JumpTableInfo; + + // Function-level unique numbering for MachineBasicBlocks. When a + // MachineBasicBlock is inserted into a MachineFunction is it automatically + // numbered and this vector keeps track of the mapping from ID's to MBB's. + std::vector MBBNumbering; + + // Pool-allocate MachineFunction-lifetime and IR objects. + BumpPtrAllocator Allocator; + + // Allocation management for instructions in function. + Recycler InstructionRecycler; + + // Allocation management for basic blocks in function. + Recycler BasicBlockRecycler; + + // List of machine basic blocks in function + typedef ilist BasicBlockListType; + BasicBlockListType BasicBlocks; + + /// FunctionNumber - This provides a unique ID for each function emitted in + /// this translation unit. + /// + unsigned FunctionNumber; + + /// Alignment - The alignment of the function. + unsigned Alignment; + + /// CallsSetJmp - True if the function calls setjmp or sigsetjmp. This is used + /// to limit optimizations which cannot reason about the control flow of + /// setjmp. + bool CallsSetJmp; + + MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT + void operator=(const MachineFunction&); // DO NOT IMPLEMENT +public: + MachineFunction(const Function *Fn, const TargetMachine &TM, + unsigned FunctionNum, MachineModuleInfo &MMI, + GCModuleInfo* GMI); + ~MachineFunction(); + + MachineModuleInfo &getMMI() const { return MMI; } + GCModuleInfo *getGMI() const { return GMI; } + MCContext &getContext() const { return Ctx; } + + /// getFunction - Return the LLVM function that this machine code represents + /// + const Function *getFunction() const { return Fn; } + + /// getFunctionNumber - Return a unique ID for the current function. + /// + unsigned getFunctionNumber() const { return FunctionNumber; } + + /// getTarget - Return the target machine this machine code is compiled with + /// + const TargetMachine &getTarget() const { return Target; } + + /// getRegInfo - Return information about the registers currently in use. + /// + MachineRegisterInfo &getRegInfo() { return *RegInfo; } + const MachineRegisterInfo &getRegInfo() const { return *RegInfo; } + + /// getFrameInfo - Return the frame info object for the current function. + /// This object contains information about objects allocated on the stack + /// frame of the current function in an abstract way. + /// + MachineFrameInfo *getFrameInfo() { return FrameInfo; } + const MachineFrameInfo *getFrameInfo() const { return FrameInfo; } + + /// getJumpTableInfo - Return the jump table info object for the current + /// function. This object contains information about jump tables in the + /// current function. If the current function has no jump tables, this will + /// return null. + const MachineJumpTableInfo *getJumpTableInfo() const { return JumpTableInfo; } + MachineJumpTableInfo *getJumpTableInfo() { return JumpTableInfo; } + + /// getOrCreateJumpTableInfo - Get the JumpTableInfo for this function, if it + /// does already exist, allocate one. + MachineJumpTableInfo *getOrCreateJumpTableInfo(unsigned JTEntryKind); + + + /// getConstantPool - Return the constant pool object for the current + /// function. + /// + MachineConstantPool *getConstantPool() { return ConstantPool; } + const MachineConstantPool *getConstantPool() const { return ConstantPool; } + + /// getAlignment - Return the alignment (log2, not bytes) of the function. + /// + unsigned getAlignment() const { return Alignment; } + + /// setAlignment - Set the alignment (log2, not bytes) of the function. + /// + void setAlignment(unsigned A) { Alignment = A; } + + /// EnsureAlignment - Make sure the function is at least 'A' bits aligned. + void EnsureAlignment(unsigned A) { + if (Alignment < A) Alignment = A; + } + + /// callsSetJmp - Returns true if the function calls setjmp or sigsetjmp. + bool callsSetJmp() const { + return CallsSetJmp; + } + + /// setCallsSetJmp - Set a flag that indicates if there's a call to setjmp or + /// sigsetjmp. + void setCallsSetJmp(bool B) { + CallsSetJmp = B; + } + + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. + /// + template + Ty *getInfo() { + if (!MFInfo) { + // This should be just `new (Allocator.Allocate()) Ty(*this)', but + // that apparently breaks GCC 3.3. + Ty *Loc = static_cast(Allocator.Allocate(sizeof(Ty), + AlignOf::Alignment)); + MFInfo = new (Loc) Ty(*this); + } + return static_cast(MFInfo); + } + + template + const Ty *getInfo() const { + return const_cast(this)->getInfo(); + } + + /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they + /// are inserted into the machine function. The block number for a machine + /// basic block can be found by using the MBB::getBlockNumber method, this + /// method provides the inverse mapping. + /// + MachineBasicBlock *getBlockNumbered(unsigned N) const { + assert(N < MBBNumbering.size() && "Illegal block number"); + assert(MBBNumbering[N] && "Block was removed from the machine function!"); + return MBBNumbering[N]; + } + + /// getNumBlockIDs - Return the number of MBB ID's allocated. + /// + unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); } + + /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and + /// recomputes them. This guarantees that the MBB numbers are sequential, + /// dense, and match the ordering of the blocks within the function. If a + /// specific MachineBasicBlock is specified, only that block and those after + /// it are renumbered. + void RenumberBlocks(MachineBasicBlock *MBBFrom = 0); + + /// print - Print out the MachineFunction in a format suitable for debugging + /// to the specified stream. + /// + void print(raw_ostream &OS, SlotIndexes* = 0) const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// dump - Print the current MachineFunction to cerr, useful for debugger use. + /// + void dump() const; + + /// verify - Run the current MachineFunction through the machine code + /// verifier, useful for debugger use. + void verify(Pass *p = NULL, const char *Banner = NULL) const; + + // Provide accessors for the MachineBasicBlock list... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + /// addLiveIn - Add the specified physical register as a live-in value and + /// create a corresponding virtual register for it. + unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC); + + //===--------------------------------------------------------------------===// + // BasicBlock accessor functions. + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return (unsigned)BasicBlocks.size();} + bool empty() const { return BasicBlocks.empty(); } + const MachineBasicBlock &front() const { return BasicBlocks.front(); } + MachineBasicBlock &front() { return BasicBlocks.front(); } + const MachineBasicBlock & back() const { return BasicBlocks.back(); } + MachineBasicBlock & back() { return BasicBlocks.back(); } + + void push_back (MachineBasicBlock *MBB) { BasicBlocks.push_back (MBB); } + void push_front(MachineBasicBlock *MBB) { BasicBlocks.push_front(MBB); } + void insert(iterator MBBI, MachineBasicBlock *MBB) { + BasicBlocks.insert(MBBI, MBB); + } + void splice(iterator InsertPt, iterator MBBI) { + BasicBlocks.splice(InsertPt, BasicBlocks, MBBI); + } + void splice(iterator InsertPt, iterator MBBI, iterator MBBE) { + BasicBlocks.splice(InsertPt, BasicBlocks, MBBI, MBBE); + } + + void remove(iterator MBBI) { + BasicBlocks.remove(MBBI); + } + void erase(iterator MBBI) { + BasicBlocks.erase(MBBI); + } + + //===--------------------------------------------------------------------===// + // Internal functions used to automatically number MachineBasicBlocks + // + + /// getNextMBBNumber - Returns the next unique number to be assigned + /// to a MachineBasicBlock in this MachineFunction. + /// + unsigned addToMBBNumbering(MachineBasicBlock *MBB) { + MBBNumbering.push_back(MBB); + return (unsigned)MBBNumbering.size()-1; + } + + /// removeFromMBBNumbering - Remove the specific machine basic block from our + /// tracker, this is only really to be used by the MachineBasicBlock + /// implementation. + void removeFromMBBNumbering(unsigned N) { + assert(N < MBBNumbering.size() && "Illegal basic block #"); + MBBNumbering[N] = 0; + } + + /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead + /// of `new MachineInstr'. + /// + MachineInstr *CreateMachineInstr(const TargetInstrDesc &TID, + DebugLoc DL, + bool NoImp = false); + + /// CloneMachineInstr - Create a new MachineInstr which is a copy of the + /// 'Orig' instruction, identical in all ways except the instruction + /// has no parent, prev, or next. + /// + /// See also TargetInstrInfo::duplicate() for target-specific fixes to cloned + /// instructions. + MachineInstr *CloneMachineInstr(const MachineInstr *Orig); + + /// DeleteMachineInstr - Delete the given MachineInstr. + /// + void DeleteMachineInstr(MachineInstr *MI); + + /// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this + /// instead of `new MachineBasicBlock'. + /// + MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = 0); + + /// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. + /// + void DeleteMachineBasicBlock(MachineBasicBlock *MBB); + + /// getMachineMemOperand - Allocate a new MachineMemOperand. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, + unsigned f, uint64_t s, + unsigned base_alignment, + const MDNode *TBAAInfo = 0); + + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, adjusting by an offset and using the given size. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size); + + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand + /// pointers. This array is owned by the MachineFunction. + MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); + + /// extractLoadMemRefs - Allocate an array and populate it with just the + /// load information from the given MachineMemOperand sequence. + std::pair + extractLoadMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + + /// extractStoreMemRefs - Allocate an array and populate it with just the + /// store information from the given MachineMemOperand sequence. + std::pair + extractStoreMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End); + + //===--------------------------------------------------------------------===// + // Label Manipulation. + // + + /// getJTISymbol - Return the MCSymbol for the specified non-empty jump table. + /// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a + /// normal 'L' label is returned. + MCSymbol *getJTISymbol(unsigned JTI, MCContext &Ctx, + bool isLinkerPrivate = false) const; + + /// getPICBaseSymbol - Return a function-local symbol to represent the PIC + /// base. + MCSymbol *getPICBaseSymbol() const; +}; + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// machine function as a graph of machine basic blocks... these are +// the same as the machine basic block iterators, except that the root +// node is implicitly the first node of the function. +// +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::iterator nodes_iterator; + static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); } + static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); } +}; +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const MachineFunction *F) { + return F->begin(); + } + static nodes_iterator nodes_end (const MachineFunction *F) { + return F->end(); + } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->front(); + } +}; +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->front(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineFunctionAnalysis.h b/final/include/llvm/CodeGen/MachineFunctionAnalysis.h new file mode 100644 index 00000000000..50676ad4ad4 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -0,0 +1,54 @@ +//===-- MachineFunctionAnalysis.h - Owner of MachineFunctions ----*-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 MachineFunctionAnalysis class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_ANALYSIS_H + +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class MachineFunction; + +/// MachineFunctionAnalysis - This class is a Pass that manages a +/// MachineFunction object. +struct MachineFunctionAnalysis : public FunctionPass { +private: + const TargetMachine &TM; + CodeGenOpt::Level OptLevel; + MachineFunction *MF; + unsigned NextFnNum; +public: + static char ID; + explicit MachineFunctionAnalysis(const TargetMachine &tm, + CodeGenOpt::Level OL = CodeGenOpt::Default); + ~MachineFunctionAnalysis(); + + MachineFunction &getMF() const { return *MF; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } + + virtual const char* getPassName() const { + return "Machine Function Analysis"; + } + +private: + virtual bool doInitialization(Module &M); + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineFunctionPass.h b/final/include/llvm/CodeGen/MachineFunctionPass.h new file mode 100644 index 00000000000..b7bf0a36c44 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineFunctionPass.h @@ -0,0 +1,59 @@ +//===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-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 MachineFunctionPass class. MachineFunctionPass's are +// just FunctionPass's, except they operate on machine code as part of a code +// generator. Because they operate on machine code, not the LLVM +// representation, MachineFunctionPass's are not allowed to modify the LLVM +// representation. Due to this limitation, the MachineFunctionPass class takes +// care of declaring that no LLVM passes are invalidated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H + +#include "llvm/Pass.h" + +namespace llvm { + +class MachineFunction; + +/// MachineFunctionPass - This class adapts the FunctionPass interface to +/// allow convenient creation of passes that operate on the MachineFunction +/// representation. Instead of overriding runOnFunction, subclasses +/// override runOnMachineFunction. +class MachineFunctionPass : public FunctionPass { +protected: + explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {} + + /// runOnMachineFunction - This method must be overloaded to perform the + /// desired machine code transformation or analysis. + /// + virtual bool runOnMachineFunction(MachineFunction &MF) = 0; + + /// getAnalysisUsage - Subclasses that override getAnalysisUsage + /// must call this. + /// + /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that + /// the pass does not modify the MachineBasicBlock CFG. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +private: + /// createPrinterPass - Get a machine function printer pass. + virtual Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const; + + virtual bool runOnFunction(Function &F); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineInstr.h b/final/include/llvm/CodeGen/MachineInstr.h new file mode 100644 index 00000000000..0f69a7789cf --- /dev/null +++ b/final/include/llvm/CodeGen/MachineInstr.h @@ -0,0 +1,578 @@ +//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineInstr class, which is the +// basic representation for all target dependent machine instructions used by +// the back end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTR_H +#define LLVM_CODEGEN_MACHINEINSTR_H + +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Target/TargetOpcodes.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/DebugLoc.h" +#include + +namespace llvm { + +template class SmallVectorImpl; +class AliasAnalysis; +class TargetInstrDesc; +class TargetInstrInfo; +class TargetRegisterInfo; +class MachineFunction; +class MachineMemOperand; + +//===----------------------------------------------------------------------===// +/// MachineInstr - Representation of each machine instruction. +/// +class MachineInstr : public ilist_node { +public: + typedef MachineMemOperand **mmo_iterator; + + /// Flags to specify different kinds of comments to output in + /// assembly code. These flags carry semantic information not + /// otherwise easily derivable from the IR text. + /// + enum CommentFlag { + ReloadReuse = 0x1 + }; + + enum MIFlag { + NoFlags = 0, + FrameSetup = 1 << 0 // Instruction is used as a part of + // function frame setup code. + }; +private: + const TargetInstrDesc *TID; // Instruction descriptor. + uint16_t NumImplicitOps; // Number of implicit operands (which + // are determined at construction time). + + uint8_t Flags; // Various bits of additional + // information about machine + // instruction. + + uint8_t AsmPrinterFlags; // Various bits of information used by + // the AsmPrinter to emit helpful + // comments. This is *not* semantic + // information. Do not use this for + // anything other than to convey comment + // information to AsmPrinter. + + std::vector Operands; // the operands + mmo_iterator MemRefs; // information on memory references + mmo_iterator MemRefsEnd; + MachineBasicBlock *Parent; // Pointer to the owning basic block. + DebugLoc debugLoc; // Source line information. + + // OperandComplete - Return true if it's illegal to add a new operand + bool OperandsComplete() const; + + MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT + void operator=(const MachineInstr&); // DO NOT IMPLEMENT + + // Intrusive list support + friend struct ilist_traits; + friend struct ilist_traits; + void setParent(MachineBasicBlock *P) { Parent = P; } + + /// MachineInstr ctor - This constructor creates a copy of the given + /// MachineInstr in the given MachineFunction. + MachineInstr(MachineFunction &, const MachineInstr &); + + /// MachineInstr ctor - This constructor creates a dummy MachineInstr with + /// TID NULL and no operands. + MachineInstr(); + + // The next two constructors have DebugLoc and non-DebugLoc versions; + // over time, the non-DebugLoc versions should be phased out and eventually + // removed. + + /// MachineInstr ctor - This constructor creates a MachineInstr and adds the + /// implicit operands. It reserves space for the number of operands specified + /// by the TargetInstrDesc. The version with a DebugLoc should be preferred. + explicit MachineInstr(const TargetInstrDesc &TID, bool NoImp = false); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. The version with a DebugLoc should be preferred. + MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &TID); + + /// MachineInstr ctor - This constructor create a MachineInstr and add the + /// implicit operands. It reserves space for number of operands specified by + /// TargetInstrDesc. An explicit DebugLoc is supplied. + explicit MachineInstr(const TargetInstrDesc &TID, const DebugLoc dl, + bool NoImp = false); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. + MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, + const TargetInstrDesc &TID); + + ~MachineInstr(); + + // MachineInstrs are pool-allocated and owned by MachineFunction. + friend class MachineFunction; + +public: + const MachineBasicBlock* getParent() const { return Parent; } + MachineBasicBlock* getParent() { return Parent; } + + /// getAsmPrinterFlags - Return the asm printer flags bitvector. + /// + uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } + + /// clearAsmPrinterFlags - clear the AsmPrinter bitvector + /// + void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } + + /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. + /// + bool getAsmPrinterFlag(CommentFlag Flag) const { + return AsmPrinterFlags & Flag; + } + + /// setAsmPrinterFlag - Set a flag for the AsmPrinter. + /// + void setAsmPrinterFlag(CommentFlag Flag) { + AsmPrinterFlags |= (uint8_t)Flag; + } + + /// getFlags - Return the MI flags bitvector. + uint8_t getFlags() const { + return Flags; + } + + /// getFlag - Return whether an MI flag is set. + bool getFlag(MIFlag Flag) const { + return Flags & Flag; + } + + /// setFlag - Set a MI flag. + void setFlag(MIFlag Flag) { + Flags |= (uint8_t)Flag; + } + + void setFlags(unsigned flags) { + Flags = flags; + } + + /// clearAsmPrinterFlag - clear specific AsmPrinter flags + /// + void clearAsmPrinterFlag(CommentFlag Flag) { + AsmPrinterFlags &= ~Flag; + } + + /// getDebugLoc - Returns the debug location id of this MachineInstr. + /// + DebugLoc getDebugLoc() const { return debugLoc; } + + /// getDesc - Returns the target instruction descriptor of this + /// MachineInstr. + const TargetInstrDesc &getDesc() const { return *TID; } + + /// getOpcode - Returns the opcode of this MachineInstr. + /// + int getOpcode() const { return TID->Opcode; } + + /// Access to explicit operands of the instruction. + /// + unsigned getNumOperands() const { return (unsigned)Operands.size(); } + + const MachineOperand& getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + MachineOperand& getOperand(unsigned i) { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + + /// getNumExplicitOperands - Returns the number of non-implicit operands. + /// + unsigned getNumExplicitOperands() const; + + /// iterator/begin/end - Iterate over all operands of a machine instruction. + typedef std::vector::iterator mop_iterator; + typedef std::vector::const_iterator const_mop_iterator; + + mop_iterator operands_begin() { return Operands.begin(); } + mop_iterator operands_end() { return Operands.end(); } + + const_mop_iterator operands_begin() const { return Operands.begin(); } + const_mop_iterator operands_end() const { return Operands.end(); } + + /// Access to memory operands of the instruction + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// hasOneMemOperand - Return true if this instruction has exactly one + /// MachineMemOperand. + bool hasOneMemOperand() const { + return MemRefsEnd - MemRefs == 1; + } + + enum MICheckType { + CheckDefs, // Check all operands for equality + IgnoreDefs, // Ignore all definitions + IgnoreVRegDefs // Ignore virtual register definitions + }; + + /// isIdenticalTo - Return true if this instruction is identical to (same + /// opcode and same operands as) the specified instruction. + bool isIdenticalTo(const MachineInstr *Other, + MICheckType Check = CheckDefs) const; + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, and returns it, but does not delete it. + MachineInstr *removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + void eraseFromParent(); + + /// isLabel - Returns true if the MachineInstr represents a label. + /// + bool isLabel() const { + return getOpcode() == TargetOpcode::PROLOG_LABEL || + getOpcode() == TargetOpcode::EH_LABEL || + getOpcode() == TargetOpcode::GC_LABEL; + } + + bool isPrologLabel() const { + return getOpcode() == TargetOpcode::PROLOG_LABEL; + } + bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } + bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } + bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } + + bool isPHI() const { return getOpcode() == TargetOpcode::PHI; } + bool isKill() const { return getOpcode() == TargetOpcode::KILL; } + bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; } + bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; } + bool isStackAligningInlineAsm() const; + bool isInsertSubreg() const { + return getOpcode() == TargetOpcode::INSERT_SUBREG; + } + bool isSubregToReg() const { + return getOpcode() == TargetOpcode::SUBREG_TO_REG; + } + bool isRegSequence() const { + return getOpcode() == TargetOpcode::REG_SEQUENCE; + } + bool isCopy() const { + return getOpcode() == TargetOpcode::COPY; + } + + /// isCopyLike - Return true if the instruction behaves like a copy. + /// This does not include native copy instructions. + bool isCopyLike() const { + return isCopy() || isSubregToReg(); + } + + /// isIdentityCopy - Return true is the instruction is an identity copy. + bool isIdentityCopy() const { + return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() && + getOperand(0).getSubReg() == getOperand(1).getSubReg(); + } + + /// readsRegister - Return true if the MachineInstr reads the specified + /// register. If TargetRegisterInfo is passed, then it also checks if there + /// is a read of a super-register. + /// This does not count partial redefines of virtual registers as reads: + /// %reg1024:6 = OP. + bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + return findRegisterUseOperandIdx(Reg, false, TRI) != -1; + } + + /// readsVirtualRegister - Return true if the MachineInstr reads the specified + /// virtual register. Take into account that a partial define is a + /// read-modify-write operation. + bool readsVirtualRegister(unsigned Reg) const { + return readsWritesVirtualRegister(Reg).first; + } + + /// readsWritesVirtualRegister - Return a pair of bools (reads, writes) + /// indicating if this instruction reads or writes Reg. This also considers + /// partial defines. + /// If Ops is not null, all operand indices for Reg are added. + std::pair readsWritesVirtualRegister(unsigned Reg, + SmallVectorImpl *Ops = 0) const; + + /// killsRegister - Return true if the MachineInstr kills the specified + /// register. If TargetRegisterInfo is passed, then it also checks if there is + /// a kill of a super-register. + bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + return findRegisterUseOperandIdx(Reg, true, TRI) != -1; + } + + /// definesRegister - Return true if the MachineInstr fully defines the + /// specified register. If TargetRegisterInfo is passed, then it also checks + /// if there is a def of a super-register. + /// NOTE: It's ignoring subreg indices on virtual registers. + bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=NULL) const { + return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; + } + + /// modifiesRegister - Return true if the MachineInstr modifies (fully define + /// or partially define) the specified register. + /// NOTE: It's ignoring subreg indices on virtual registers. + bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const { + return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; + } + + /// registerDefIsDead - Returns true if the register is dead in this machine + /// instruction. If TargetRegisterInfo is passed, then it also checks + /// if there is a dead def of a super-register. + bool registerDefIsDead(unsigned Reg, + const TargetRegisterInfo *TRI = NULL) const { + return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; + } + + /// findRegisterUseOperandIdx() - Returns the operand index that is a use of + /// the specific register or -1 if it is not found. It further tightens + /// the search criteria to a use that kills the register if isKill is true. + int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, + const TargetRegisterInfo *TRI = NULL) const; + + /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns + /// a pointer to the MachineOperand rather than an index. + MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false, + const TargetRegisterInfo *TRI = NULL) { + int Idx = findRegisterUseOperandIdx(Reg, isKill, TRI); + return (Idx == -1) ? NULL : &getOperand(Idx); + } + + /// findRegisterDefOperandIdx() - Returns the operand index that is a def of + /// the specified register or -1 if it is not found. If isDead is true, defs + /// that are not dead are skipped. If Overlap is true, then it also looks for + /// defs that merely overlap the specified register. If TargetRegisterInfo is + /// non-null, then it also checks if there is a def of a super-register. + int findRegisterDefOperandIdx(unsigned Reg, + bool isDead = false, bool Overlap = false, + const TargetRegisterInfo *TRI = NULL) const; + + /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns + /// a pointer to the MachineOperand rather than an index. + MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, + const TargetRegisterInfo *TRI = NULL) { + int Idx = findRegisterDefOperandIdx(Reg, isDead, false, TRI); + return (Idx == -1) ? NULL : &getOperand(Idx); + } + + /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// operand list that is used to represent the predicate. It returns -1 if + /// none is found. + int findFirstPredOperandIdx() const; + + /// isRegTiedToUseOperand - Given the index of a register def operand, + /// check if the register def is tied to a source operand, due to either + /// two-address elimination or inline assembly constraints. Returns the + /// first tied use operand index by reference is UseOpIdx is not null. + bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx = 0) const; + + /// isRegTiedToDefOperand - Return true if the use operand of the specified + /// index is tied to an def operand. It also returns the def operand index by + /// reference if DefOpIdx is not null. + bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const; + + /// clearKillInfo - Clears kill flags on all operands. + /// + void clearKillInfo(); + + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. + /// + void copyKillDeadInfo(const MachineInstr *MI); + + /// copyPredicates - Copies predicate operand(s) from MI. + void copyPredicates(const MachineInstr *MI); + + /// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx, + /// properly composing subreg indices where necessary. + void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx, + const TargetRegisterInfo &RegInfo); + + /// addRegisterKilled - We have determined MI kills a register. Look for the + /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, + /// add a implicit operand if it's not found. Returns true if the operand + /// exists / is added. + bool addRegisterKilled(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound = false); + + /// addRegisterDead - We have determined MI defined a register without a use. + /// Look for the operand that defines it and mark it as IsDead. If + /// AddIfNotFound is true, add a implicit operand if it's not found. Returns + /// true if the operand exists / is added. + bool addRegisterDead(unsigned IncomingReg, const TargetRegisterInfo *RegInfo, + bool AddIfNotFound = false); + + /// addRegisterDefined - We have determined MI defines a register. Make sure + /// there is an operand defining Reg. + void addRegisterDefined(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo = 0); + + /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as dead + /// except those in the UsedRegs list. + void setPhysRegsDeadExcept(const SmallVectorImpl &UsedRegs, + const TargetRegisterInfo &TRI); + + /// isSafeToMove - Return true if it is safe to move this instruction. If + /// SawStore is set to true, it means that there is a store (or call) between + /// the instruction's location and its intended destination. + bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, + bool &SawStore) const; + + /// isSafeToReMat - Return true if it's safe to rematerialize the specified + /// instruction which defined the specified register instead of copying it. + bool isSafeToReMat(const TargetInstrInfo *TII, AliasAnalysis *AA, + unsigned DstReg) const; + + /// hasVolatileMemoryRef - Return true if this instruction may have a + /// volatile memory reference, or if the information describing the + /// memory reference is not available. Return false if it is known to + /// have no volatile memory references. + bool hasVolatileMemoryRef() const; + + /// isInvariantLoad - Return true if this instruction is loading from a + /// location whose value is invariant across the function. For example, + /// loading a value from the constant pool or from the argument area of + /// a function if it does not change. This should only return true of *all* + /// loads the instruction does are invariant (if it does multiple loads). + bool isInvariantLoad(AliasAnalysis *AA) const; + + /// isConstantValuePHI - If the specified instruction is a PHI that always + /// merges together the same virtual register, return the register, otherwise + /// return 0. + unsigned isConstantValuePHI() const; + + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by mayLoad / mayStore, etc. + /// For all instructions, the property is encoded in TargetInstrDesc::Flags + /// (see TargetInstrDesc::hasUnmodeledSideEffects(). The only exception is + /// INLINEASM instruction, in which case the side effect property is encoded + /// in one of its operands (see InlineAsm::Extra_HasSideEffect). + /// + bool hasUnmodeledSideEffects() const; + + /// allDefsAreDead - Return true if all the defs of this instruction are dead. + /// + bool allDefsAreDead() const; + + /// copyImplicitOps - Copy implicit register operands from specified + /// instruction to this instruction. + void copyImplicitOps(const MachineInstr *MI); + + // + // Debugging support + // + void print(raw_ostream &OS, const TargetMachine *TM = 0) const; + void dump() const; + + //===--------------------------------------------------------------------===// + // Accessors used to build up machine instructions. + + /// addOperand - Add the specified operand to the instruction. If it is an + /// implicit operand, it is added to the end of the operand list. If it is + /// an explicit operand it is added at the end of the explicit operand list + /// (before the first implicit operand). + void addOperand(const MachineOperand &Op); + + /// setDesc - Replace the instruction descriptor (thus opcode) of + /// the current instruction with a new one. + /// + void setDesc(const TargetInstrDesc &tid) { TID = &tid; } + + /// setDebugLoc - Replace current source information with new such. + /// Avoid using this, the constructor argument is preferable. + /// + void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + + /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// fewer operand than it started with. + /// + void RemoveOperand(unsigned i); + + /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// This function should be used only occasionally. The setMemRefs function + /// is the primary method for setting up a MachineInstr's MemRefs list. + void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); + + /// setMemRefs - Assign this MachineInstr's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + +private: + /// getRegInfo - If this instruction is embedded into a MachineFunction, + /// return the MachineRegisterInfo object for the current function, otherwise + /// return null. + MachineRegisterInfo *getRegInfo(); + + /// addImplicitDefUseOperands - Add all implicit def and use operands to + /// this instruction. + void addImplicitDefUseOperands(); + + /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in + /// this instruction from their respective use lists. This requires that the + /// operands already be on their use lists. + void RemoveRegOperandsFromUseLists(); + + /// AddRegOperandsToUseLists - Add all of the register operands in + /// this instruction from their respective use lists. This requires that the + /// operands not be on their use lists yet. + void AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo); +}; + +/// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare +/// MachineInstr* by *value* of the instruction rather than by pointer value. +/// The hashing and equality testing functions ignore definitions so this is +/// useful for CSE, etc. +struct MachineInstrExpressionTrait : DenseMapInfo { + static inline MachineInstr *getEmptyKey() { + return 0; + } + + static inline MachineInstr *getTombstoneKey() { + return reinterpret_cast(-1); + } + + static unsigned getHashValue(const MachineInstr* const &MI); + + static bool isEqual(const MachineInstr* const &LHS, + const MachineInstr* const &RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey() || + LHS == getEmptyKey() || LHS == getTombstoneKey()) + return LHS == RHS; + return LHS->isIdenticalTo(RHS, MachineInstr::IgnoreVRegDefs); + } +}; + +//===----------------------------------------------------------------------===// +// Debugging Support + +inline raw_ostream& operator<<(raw_ostream &OS, const MachineInstr &MI) { + MI.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineInstrBuilder.h b/final/include/llvm/CodeGen/MachineInstrBuilder.h new file mode 100644 index 00000000000..f04dee2b4b0 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineInstrBuilder.h @@ -0,0 +1,258 @@ +//===-- CodeGen/MachineInstBuilder.h - Simplify creation of MIs -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes a function named BuildMI, which is useful for dramatically +// simplifying how MachineInstr's are created. It allows use of code like this: +// +// M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H +#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +class TargetInstrDesc; +class MDNode; + +namespace RegState { + enum { + Define = 0x2, + Implicit = 0x4, + Kill = 0x8, + Dead = 0x10, + Undef = 0x20, + EarlyClobber = 0x40, + Debug = 0x80, + ImplicitDefine = Implicit | Define, + ImplicitKill = Implicit | Kill + }; +} + +class MachineInstrBuilder { + MachineInstr *MI; +public: + MachineInstrBuilder() : MI(0) {} + explicit MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} + + /// Allow automatic conversion to the machine instruction we are working on. + /// + operator MachineInstr*() const { return MI; } + operator MachineBasicBlock::iterator() const { return MI; } + + /// addReg - Add a new virtual register operand... + /// + const + MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, + unsigned SubReg = 0) const { + assert((flags & 0x1) == 0 && + "Passing in 'true' to addReg is forbidden! Use enums instead."); + MI->addOperand(MachineOperand::CreateReg(RegNo, + flags & RegState::Define, + flags & RegState::Implicit, + flags & RegState::Kill, + flags & RegState::Dead, + flags & RegState::Undef, + flags & RegState::EarlyClobber, + SubReg, + flags & RegState::Debug)); + return *this; + } + + /// addImm - Add a new immediate operand. + /// + const MachineInstrBuilder &addImm(int64_t Val) const { + MI->addOperand(MachineOperand::CreateImm(Val)); + return *this; + } + + const MachineInstrBuilder &addFPImm(const ConstantFP *Val) const { + MI->addOperand(MachineOperand::CreateFPImm(Val)); + return *this; + } + + const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateMBB(MBB, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addFrameIndex(unsigned Idx) const { + MI->addOperand(MachineOperand::CreateFI(Idx)); + return *this; + } + + const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, + int Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateCPI(Idx, Offset, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addJumpTableIndex(unsigned Idx, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateJTI(Idx, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addGlobalAddress(const GlobalValue *GV, + int64_t Offset = 0, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateGA(GV, Offset, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addExternalSymbol(const char *FnName, + unsigned char TargetFlags = 0) const { + MI->addOperand(MachineOperand::CreateES(FnName, TargetFlags)); + return *this; + } + + const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { + MI->addMemOperand(*MI->getParent()->getParent(), MMO); + return *this; + } + + const MachineInstrBuilder &setMemRefs(MachineInstr::mmo_iterator b, + MachineInstr::mmo_iterator e) const { + MI->setMemRefs(b, e); + return *this; + } + + + const MachineInstrBuilder &addOperand(const MachineOperand &MO) const { + MI->addOperand(MO); + return *this; + } + + const MachineInstrBuilder &addMetadata(const MDNode *MD) const { + MI->addOperand(MachineOperand::CreateMetadata(MD)); + return *this; + } + + const MachineInstrBuilder &addSym(MCSymbol *Sym) const { + MI->addOperand(MachineOperand::CreateMCSymbol(Sym)); + return *this; + } + + const MachineInstrBuilder &setMIFlags(unsigned Flags) const { + MI->setFlags(Flags); + return *this; + } + + const MachineInstrBuilder &setMIFlag(MachineInstr::MIFlag Flag) const { + MI->setFlag(Flag); + return *this; + } + + // Add a displacement from an existing MachineOperand with an added offset. + const MachineInstrBuilder &addDisp(const MachineOperand &Disp, + int64_t off) const { + switch (Disp.getType()) { + default: + llvm_unreachable("Unhandled operand type in addDisp()"); + case MachineOperand::MO_Immediate: + return addImm(Disp.getImm() + off); + case MachineOperand::MO_GlobalAddress: + return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off); + } + } +}; + +/// BuildMI - Builder interface. Specify how to create the initial instruction +/// itself. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const TargetInstrDesc &TID) { + return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)); +} + +/// BuildMI - This version of the builder sets up the first operand as a +/// destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + return MachineInstrBuilder(MF.CreateMachineInstr(TID, DL)) + .addReg(DestReg, RegState::Define); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// sets up the first operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + BB.insert(I, MI); + return MachineInstrBuilder(MI).addReg(DestReg, RegState::Define); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// does NOT take a destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const TargetInstrDesc &TID) { + MachineInstr *MI = BB.getParent()->CreateMachineInstr(TID, DL); + BB.insert(I, MI); + return MachineInstrBuilder(MI); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and does NOT take a +/// destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const TargetInstrDesc &TID) { + return BuildMI(*BB, BB->end(), DL, TID); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and sets up the first +/// operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + DebugLoc DL, + const TargetInstrDesc &TID, + unsigned DestReg) { + return BuildMI(*BB, BB->end(), DL, TID, DestReg); +} + +inline unsigned getDefRegState(bool B) { + return B ? RegState::Define : 0; +} +inline unsigned getImplRegState(bool B) { + return B ? RegState::Implicit : 0; +} +inline unsigned getKillRegState(bool B) { + return B ? RegState::Kill : 0; +} +inline unsigned getDeadRegState(bool B) { + return B ? RegState::Dead : 0; +} +inline unsigned getUndefRegState(bool B) { + return B ? RegState::Undef : 0; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineJumpTableInfo.h b/final/include/llvm/CodeGen/MachineJumpTableInfo.h new file mode 100644 index 00000000000..62643497655 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -0,0 +1,125 @@ +//===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The MachineJumpTableInfo class keeps track of jump tables referenced by +// lowered switch instructions in the MachineFunction. +// +// Instructions reference the address of these jump tables through the use of +// MO_JumpTableIndex values. When emitting assembly or machine code, these +// virtual address references are converted to refer to the address of the +// function jump tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H +#define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H + +#include +#include + +namespace llvm { + +class MachineBasicBlock; +class TargetData; +class raw_ostream; + +/// MachineJumpTableEntry - One jump table in the jump table info. +/// +struct MachineJumpTableEntry { + /// MBBs - The vector of basic blocks from which to create the jump table. + std::vector MBBs; + + explicit MachineJumpTableEntry(const std::vector &M) + : MBBs(M) {} +}; + +class MachineJumpTableInfo { +public: + /// JTEntryKind - This enum indicates how each entry of the jump table is + /// represented and emitted. + enum JTEntryKind { + /// EK_BlockAddress - Each entry is a plain address of block, e.g.: + /// .word LBB123 + EK_BlockAddress, + + /// EK_GPRel32BlockAddress - Each entry is an address of block, encoded + /// with a relocation as gp-relative, e.g.: + /// .gprel32 LBB123 + EK_GPRel32BlockAddress, + + /// EK_LabelDifference32 - Each entry is the address of the block minus + /// the address of the jump table. This is used for PIC jump tables where + /// gprel32 is not supported. e.g.: + /// .word LBB123 - LJTI1_2 + /// If the .set directive is supported, this is emitted as: + /// .set L4_5_set_123, LBB123 - LJTI1_2 + /// .word L4_5_set_123 + EK_LabelDifference32, + + /// EK_Inline - Jump table entries are emitted inline at their point of + /// use. It is the responsibility of the target to emit the entries. + EK_Inline, + + /// EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the + /// TargetLowering::LowerCustomJumpTableEntry hook. + EK_Custom32 + }; +private: + JTEntryKind EntryKind; + std::vector JumpTables; +public: + explicit MachineJumpTableInfo(JTEntryKind Kind): EntryKind(Kind) {} + + JTEntryKind getEntryKind() const { return EntryKind; } + + /// getEntrySize - Return the size of each entry in the jump table. + unsigned getEntrySize(const TargetData &TD) const; + /// getEntryAlignment - Return the alignment of each entry in the jump table. + unsigned getEntryAlignment(const TargetData &TD) const; + + /// createJumpTableIndex - Create a new jump table. + /// + unsigned createJumpTableIndex(const std::vector &DestBBs); + + /// isEmpty - Return true if there are no jump tables. + /// + bool isEmpty() const { return JumpTables.empty(); } + + const std::vector &getJumpTables() const { + return JumpTables; + } + + /// RemoveJumpTable - Mark the specific index as being dead. This will + /// prevent it from being emitted. + void RemoveJumpTable(unsigned Idx) { + JumpTables[Idx].MBBs.clear(); + } + + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update + /// the jump tables to branch to New instead. + bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update + /// the jump table to branch to New instead. + bool ReplaceMBBInJumpTable(unsigned Idx, MachineBasicBlock *Old, + MachineBasicBlock *New); + + /// print - Used by the MachineFunction printer to print information about + /// jump tables. Implemented in MachineFunction.cpp + /// + void print(raw_ostream &OS) const; + + /// dump - Call to stderr. + /// + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineLocation.h b/final/include/llvm/CodeGen/MachineLocation.h new file mode 100644 index 00000000000..21951b6680b --- /dev/null +++ b/final/include/llvm/CodeGen/MachineLocation.h @@ -0,0 +1,98 @@ +//===-- llvm/CodeGen/MachineLocation.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// The MachineLocation class is used to represent a simple location in a machine +// frame. Locations will be one of two forms; a register or an address formed +// from a base address plus an offset. Register indirection can be specified by +// using an offset of zero. +// +// The MachineMove class is used to represent abstract move operations in the +// prolog/epilog of a compiled function. A collection of these objects can be +// used by a debug consumer to track the location of values when unwinding stack +// frames. +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHINELOCATION_H +#define LLVM_CODEGEN_MACHINELOCATION_H + +namespace llvm { + class MCSymbol; + +class MachineLocation { +private: + bool IsRegister; // True if location is a register. + unsigned Register; // gcc/gdb register number. + int Offset; // Displacement if not register. +public: + enum { + // The target register number for an abstract frame pointer. The value is + // an arbitrary value that doesn't collide with any real target register. + VirtualFP = ~0U + }; + MachineLocation() + : IsRegister(false), Register(0), Offset(0) {} + explicit MachineLocation(unsigned R) + : IsRegister(true), Register(R), Offset(0) {} + MachineLocation(unsigned R, int O) + : IsRegister(false), Register(R), Offset(O) {} + + bool operator==(const MachineLocation &Other) const { + return IsRegister == Other.IsRegister && Register == Other.Register && + Offset == Other.Offset; + } + + // Accessors + bool isReg() const { return IsRegister; } + unsigned getReg() const { return Register; } + int getOffset() const { return Offset; } + void setIsRegister(bool Is) { IsRegister = Is; } + void setRegister(unsigned R) { Register = R; } + void setOffset(int O) { Offset = O; } + void set(unsigned R) { + IsRegister = true; + Register = R; + Offset = 0; + } + void set(unsigned R, int O) { + IsRegister = false; + Register = R; + Offset = O; + } + +#ifndef NDEBUG + void dump(); +#endif +}; + +/// MachineMove - This class represents the save or restore of a callee saved +/// register that exception or debug info needs to know about. +class MachineMove { +private: + /// Label - Symbol for post-instruction address when result of move takes + /// effect. + MCSymbol *Label; + + // Move to & from location. + MachineLocation Destination, Source; +public: + MachineMove() : Label(0) {} + + MachineMove(MCSymbol *label, const MachineLocation &D, + const MachineLocation &S) + : Label(label), Destination(D), Source(S) {} + + // Accessors + MCSymbol *getLabel() const { return Label; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineLoopInfo.h b/final/include/llvm/CodeGen/MachineLoopInfo.h new file mode 100644 index 00000000000..6dd9440500b --- /dev/null +++ b/final/include/llvm/CodeGen/MachineLoopInfo.h @@ -0,0 +1,178 @@ +//===- llvm/CodeGen/MachineLoopInfo.h - Natural Loop Calculator -*- 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 MachineLoopInfo class that is used to identify natural +// loops and determine the loop depth of various nodes of the CFG. Note that +// natural loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * the trip count +// * etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_LOOP_INFO_H +#define LLVM_CODEGEN_MACHINE_LOOP_INFO_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Analysis/LoopInfo.h" + +namespace llvm { + +class MachineLoop : public LoopBase { +public: + MachineLoop(); + + /// getTopBlock - Return the "top" block in the loop, which is the first + /// block in the linear layout, ignoring any parts of the loop not + /// contiguous with the part the contains the header. + MachineBasicBlock *getTopBlock(); + + /// getBottomBlock - Return the "bottom" block in the loop, which is the last + /// block in the linear layout, ignoring any parts of the loop not + /// contiguous with the part the contains the header. + MachineBasicBlock *getBottomBlock(); + + void dump() const; + +private: + friend class LoopInfoBase; + explicit MachineLoop(MachineBasicBlock *MBB) + : LoopBase(MBB) {} +}; + +class MachineLoopInfo : public MachineFunctionPass { + LoopInfoBase LI; + friend class LoopBase; + + void operator=(const MachineLoopInfo &); // do not implement + MachineLoopInfo(const MachineLoopInfo &); // do not implement + +public: + static char ID; // Pass identification, replacement for typeid + + MachineLoopInfo() : MachineFunctionPass(ID) { + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + } + + LoopInfoBase& getBase() { return LI; } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef LoopInfoBase::iterator iterator; + inline iterator begin() const { return LI.begin(); } + inline iterator end() const { return LI.end(); } + bool empty() const { return LI.empty(); } + + /// getLoopFor - Return the inner most loop that BB lives in. If a basic + /// block is in no loop (for example the entry node), null is returned. + /// + inline MachineLoop *getLoopFor(const MachineBasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// operator[] - same as getLoopFor... + /// + inline const MachineLoop *operator[](const MachineBasicBlock *BB) const { + return LI.getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block... + /// + inline unsigned getLoopDepth(const MachineBasicBlock *BB) const { + return LI.getLoopDepth(BB); + } + + // isLoopHeader - True if the block is a loop header node + inline bool isLoopHeader(MachineBasicBlock *BB) const { + return LI.isLoopHeader(BB); + } + + /// runOnFunction - Calculate the natural loop information. + /// + virtual bool runOnMachineFunction(MachineFunction &F); + + virtual void releaseMemory() { LI.releaseMemory(); } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// removeLoop - This removes the specified top-level loop from this loop info + /// object. The loop is not deleted, as it will presumably be inserted into + /// another loop. + inline MachineLoop *removeLoop(iterator I) { return LI.removeLoop(I); } + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + inline void changeLoopFor(MachineBasicBlock *BB, MachineLoop *L) { + LI.changeLoopFor(BB, L); + } + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + inline void changeTopLevelLoop(MachineLoop *OldLoop, MachineLoop *NewLoop) { + LI.changeTopLevelLoop(OldLoop, NewLoop); + } + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + inline void addTopLevelLoop(MachineLoop *New) { + LI.addTopLevelLoop(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// MachineBasicBlocks to loops. + void removeBlock(MachineBasicBlock *BB) { + LI.removeBlock(BB); + } +}; + + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits { + typedef const MachineLoop NodeType; + typedef MachineLoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(const MachineLoop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template <> struct GraphTraits { + typedef MachineLoop NodeType; + typedef MachineLoopInfo::iterator ChildIteratorType; + + static NodeType *getEntryNode(MachineLoop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineLoopRanges.h b/final/include/llvm/CodeGen/MachineLoopRanges.h new file mode 100644 index 00000000000..6a30e8b53c0 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineLoopRanges.h @@ -0,0 +1,112 @@ +//===- MachineLoopRanges.h - Ranges of machine loops -----------*- 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 the interface to the MachineLoopRanges analysis. +// +// Provide on-demand information about the ranges of machine instructions +// covered by a loop. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINELOOPRANGES_H +#define LLVM_CODEGEN_MACHINELOOPRANGES_H + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/SlotIndexes.h" + +namespace llvm { + +class MachineLoop; +class MachineLoopInfo; +class raw_ostream; + +/// MachineLoopRange - Range information for a single loop. +class MachineLoopRange { + friend class MachineLoopRanges; + +public: + typedef IntervalMap Map; + typedef Map::Allocator Allocator; + +private: + /// The mapped loop. + const MachineLoop *const Loop; + + /// Map intervals to a bit mask. + /// Bit 0 = inside loop block. + Map Intervals; + + /// Loop area as measured by SlotIndex::distance. + unsigned Area; + + /// Create a MachineLoopRange, only accessible to MachineLoopRanges. + MachineLoopRange(const MachineLoop*, Allocator&, SlotIndexes&); + +public: + /// getLoop - Return the mapped machine loop. + const MachineLoop *getLoop() const { return Loop; } + + /// overlaps - Return true if this loop overlaps the given range of machine + /// inteructions. + bool overlaps(SlotIndex Start, SlotIndex Stop); + + /// getNumber - Return the loop number. This is the same as the number of the + /// header block. + unsigned getNumber() const; + + /// getArea - Return the loop area. This number is approximately proportional + /// to the number of instructions in the loop. + unsigned getArea() const { return Area; } + + /// getMap - Allow public read-only access for IntervalMapOverlaps. + const Map &getMap() { return Intervals; } + + /// print - Print loop ranges on OS. + void print(raw_ostream&) const; + + /// byNumber - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by number. + static int byNumber(const void*, const void*); + + /// byAreaDesc - Comparator for array_pod_sort that sorts a list of + /// MachineLoopRange pointers by descending area, then by number. + static int byAreaDesc(const void*, const void*); +}; + +raw_ostream &operator<<(raw_ostream&, const MachineLoopRange&); + +/// MachineLoopRanges - Analysis pass that provides on-demand per-loop range +/// information. +class MachineLoopRanges : public MachineFunctionPass { + typedef DenseMap CacheMap; + typedef MachineLoopRange::Allocator MapAllocator; + + MapAllocator Allocator; + SlotIndexes *Indexes; + CacheMap Cache; + +public: + static char ID; // Pass identification, replacement for typeid + + MachineLoopRanges() : MachineFunctionPass(ID), Indexes(0) {} + ~MachineLoopRanges() { releaseMemory(); } + + /// getLoopRange - Return the range of loop. + MachineLoopRange *getLoopRange(const MachineLoop *Loop); + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage&) const; +}; + + +} // end namespace llvm + +#endif // LLVM_CODEGEN_MACHINELOOPRANGES_H diff --git a/final/include/llvm/CodeGen/MachineMemOperand.h b/final/include/llvm/CodeGen/MachineMemOperand.h new file mode 100644 index 00000000000..768ce47f8b3 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineMemOperand.h @@ -0,0 +1,165 @@ +//==- llvm/CodeGen/MachineMemOperand.h - MachineMemOperand class -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineMemOperand class, which is a +// description of a memory reference. It is used to help track dependencies +// in the backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H +#define LLVM_CODEGEN_MACHINEMEMOPERAND_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +class FoldingSetNodeID; +class raw_ostream; + +/// MachinePointerInfo - This class contains a discriminated union of +/// information about pointers in memory operands, relating them back to LLVM IR +/// or to virtual locations (such as frame indices) that are exposed during +/// codegen. +struct MachinePointerInfo { + /// V - This is the IR pointer value for the access, or it is null if unknown. + /// If this is null, then the access is to a pointer in the default address + /// space. + const Value *V; + + /// Offset - This is an offset from the base Value*. + int64_t Offset; + + explicit MachinePointerInfo(const Value *v = 0, int64_t offset = 0) + : V(v), Offset(offset) {} + + MachinePointerInfo getWithOffset(int64_t O) const { + if (V == 0) return MachinePointerInfo(0, 0); + return MachinePointerInfo(V, Offset+O); + } + + /// getAddrSpace - Return the LLVM IR address space number that this pointer + /// points into. + unsigned getAddrSpace() const; + + /// getConstantPool - Return a MachinePointerInfo record that refers to the + /// constant pool. + static MachinePointerInfo getConstantPool(); + + /// getFixedStack - Return a MachinePointerInfo record that refers to the + /// the specified FrameIndex. + static MachinePointerInfo getFixedStack(int FI, int64_t offset = 0); + + /// getJumpTable - Return a MachinePointerInfo record that refers to a + /// jump table entry. + static MachinePointerInfo getJumpTable(); + + /// getGOT - Return a MachinePointerInfo record that refers to a + /// GOT entry. + static MachinePointerInfo getGOT(); + + /// getStack - stack pointer relative access. + static MachinePointerInfo getStack(int64_t Offset); +}; + + +//===----------------------------------------------------------------------===// +/// MachineMemOperand - A description of a memory reference used in the backend. +/// Instead of holding a StoreInst or LoadInst, this class holds the address +/// Value of the reference along with a byte size and offset. This allows it +/// to describe lowered loads and stores. Also, the special PseudoSourceValue +/// objects can be used to represent loads and stores to memory locations +/// that aren't explicit in the regular LLVM IR. +/// +class MachineMemOperand { + MachinePointerInfo PtrInfo; + uint64_t Size; + unsigned Flags; + const MDNode *TBAAInfo; + +public: + /// Flags values. These may be or'd together. + enum MemOperandFlags { + /// The memory access reads data. + MOLoad = 1, + /// The memory access writes data. + MOStore = 2, + /// The memory access is volatile. + MOVolatile = 4, + /// The memory access is non-temporal. + MONonTemporal = 8, + // This is the number of bits we need to represent flags. + MOMaxBits = 4 + }; + + /// MachineMemOperand - Construct an MachineMemOperand object with the + /// specified PtrInfo, flags, size, and base alignment. + MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, + unsigned base_alignment, const MDNode *TBAAInfo = 0); + + const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } + + /// getValue - Return the base address of the memory access. This may either + /// be a normal LLVM IR Value, or one of the special values used in CodeGen. + /// Special values are those obtained via + /// PseudoSourceValue::getFixedStack(int), PseudoSourceValue::getStack, and + /// other PseudoSourceValue member functions which return objects which stand + /// for frame/stack pointer relative references and other special references + /// which are not representable in the high-level IR. + const Value *getValue() const { return PtrInfo.V; } + + /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. + unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); } + + /// getOffset - For normal values, this is a byte offset added to the base + /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex + /// number. + int64_t getOffset() const { return PtrInfo.Offset; } + + /// getSize - Return the size in bytes of the memory reference. + uint64_t getSize() const { return Size; } + + /// getAlignment - Return the minimum known alignment in bytes of the + /// actual memory reference. + uint64_t getAlignment() const; + + /// getBaseAlignment - Return the minimum known alignment in bytes of the + /// base address, without the offset. + uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; } + + /// getTBAAInfo - Return the TBAA tag for the memory reference. + const MDNode *getTBAAInfo() const { return TBAAInfo; } + + bool isLoad() const { return Flags & MOLoad; } + bool isStore() const { return Flags & MOStore; } + bool isVolatile() const { return Flags & MOVolatile; } + bool isNonTemporal() const { return Flags & MONonTemporal; } + + /// refineAlignment - Update this MachineMemOperand to reflect the alignment + /// of MMO, if it has a greater alignment. This must only be used when the + /// new alignment applies to all users of this MachineMemOperand. + void refineAlignment(const MachineMemOperand *MMO); + + /// setValue - Change the SourceValue for this MachineMemOperand. This + /// should only be used when an object is being relocated and all references + /// to it are being updated. + void setValue(const Value *NewSV) { PtrInfo.V = NewSV; } + void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; } + + /// Profile - Gather unique data for the object. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineModuleInfo.h b/final/include/llvm/CodeGen/MachineModuleInfo.h new file mode 100644 index 00000000000..6bc80b099fd --- /dev/null +++ b/final/include/llvm/CodeGen/MachineModuleInfo.h @@ -0,0 +1,366 @@ +//===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect meta information for a module. This information should be in a +// neutral form that can be used by different debugging and exception handling +// schemes. +// +// The organization of information is primarily clustered around the source +// compile units. The main exception is source line correspondence where +// inlining may interleave code from various compile units. +// +// The following information can be retrieved from the MachineModuleInfo. +// +// -- Source directories - Directories are uniqued based on their canonical +// string and assigned a sequential numeric ID (base 1.) +// -- Source files - Files are also uniqued based on their name and directory +// ID. A file ID is sequential number (base 1.) +// -- Source line correspondence - A vector of file ID, line#, column# triples. +// A DEBUG_LOCATION instruction is generated by the DAG Legalizer +// corresponding to each entry in the source line list. This allows a debug +// emitter to generate labels referenced by debug information tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H +#define LLVM_CODEGEN_MACHINEMODULEINFO_H + +#include "llvm/Pass.h" +#include "llvm/GlobalValue.h" +#include "llvm/Metadata.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Forward declarations. +class Constant; +class GlobalVariable; +class MDNode; +class MachineBasicBlock; +class MachineFunction; +class Module; +class PointerType; +class StructType; + +/// MachineModuleInfoImpl - This class can be derived from and used by targets +/// to hold private target-specific information for each Module. Objects of +/// type are accessed/created with MMI::getInfo and destroyed when the +/// MachineModuleInfo is destroyed. +class MachineModuleInfoImpl { +public: + typedef PointerIntPair StubValueTy; + virtual ~MachineModuleInfoImpl(); + typedef std::vector > SymbolListTy; +protected: + static SymbolListTy GetSortedStubs(const DenseMap&); +}; + + + +//===----------------------------------------------------------------------===// +/// LandingPadInfo - This structure is used to retain landing pad info for +/// the current function. +/// +struct LandingPadInfo { + MachineBasicBlock *LandingPadBlock; // Landing pad block. + SmallVector BeginLabels; // Labels prior to invoke. + SmallVector EndLabels; // Labels after invoke. + MCSymbol *LandingPadLabel; // Label at beginning of landing pad. + const Function *Personality; // Personality function. + std::vector TypeIds; // List of type ids (filters negative) + + explicit LandingPadInfo(MachineBasicBlock *MBB) + : LandingPadBlock(MBB), LandingPadLabel(0), Personality(0) {} +}; + +class MMIAddrLabelMap; + +//===----------------------------------------------------------------------===// +/// MachineModuleInfo - This class contains meta information specific to a +/// module. Queries can be made by different debugging and exception handling +/// schemes and reformated for specific use. +/// +class MachineModuleInfo : public ImmutablePass { + /// Context - This is the MCContext used for the entire code generator. + MCContext Context; + + /// TheModule - This is the LLVM Module being worked on. + const Module *TheModule; + + /// ObjFileMMI - This is the object-file-format-specific implementation of + /// MachineModuleInfoImpl, which lets targets accumulate whatever info they + /// want. + MachineModuleInfoImpl *ObjFileMMI; + + // FrameMoves - List of moves done by a function's prolog. Used to construct + // frame maps by debug and exception handling consumers. + std::vector FrameMoves; + + // LandingPads - List of LandingPadInfo describing the landing pad information + // in the current function. + std::vector LandingPads; + + // Map of invoke call site index values to associated begin EH_LABEL for + // the current function. + DenseMap CallSiteMap; + + // The current call site index being processed, if any. 0 if none. + unsigned CurCallSite; + + // TypeInfos - List of C++ TypeInfo used in the current function. + // + std::vector TypeInfos; + + // FilterIds - List of typeids encoding filters used in the current function. + // + std::vector FilterIds; + + // FilterEnds - List of the indices in FilterIds corresponding to filter + // terminators. + // + std::vector FilterEnds; + + // Personalities - Vector of all personality functions ever seen. Used to emit + // common EH frames. + std::vector Personalities; + + /// UsedFunctions - The functions in the @llvm.used list in a more easily + /// searchable format. This does not include the functions in + /// llvm.compiler.used. + SmallPtrSet UsedFunctions; + + + /// AddrLabelSymbols - This map keeps track of which symbol is being used for + /// the specified basic block's address of label. + MMIAddrLabelMap *AddrLabelSymbols; + + bool CallsEHReturn; + bool CallsUnwindInit; + + /// DbgInfoAvailable - True if debugging information is available + /// in this module. + bool DbgInfoAvailable; + + /// True if this module calls VarArg function with floating point arguments. + /// This is used to emit an undefined reference to fltused on Windows targets. + bool CallsExternalVAFunctionWithFloatingPointArguments; + +public: + static char ID; // Pass identification, replacement for typeid + + typedef std::pair UnsignedDebugLocPair; + typedef SmallVector, UnsignedDebugLocPair>, 4> + VariableDbgInfoMapTy; + VariableDbgInfoMapTy VariableDbgInfo; + + MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. + // Real constructor. + MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); + ~MachineModuleInfo(); + + bool doInitialization(); + bool doFinalization(); + + /// EndFunction - Discard function meta information. + /// + void EndFunction(); + + const MCContext &getContext() const { return Context; } + MCContext &getContext() { return Context; } + + void setModule(const Module *M) { TheModule = M; } + const Module *getModule() const { return TheModule; } + + /// getInfo - Keep track of various per-function pieces of information for + /// backends that would like to do so. + /// + template + Ty &getObjFileInfo() { + if (ObjFileMMI == 0) + ObjFileMMI = new Ty(*this); + return *static_cast(ObjFileMMI); + } + + template + const Ty &getObjFileInfo() const { + return const_cast(this)->getObjFileInfo(); + } + + /// AnalyzeModule - Scan the module for global debug information. + /// + void AnalyzeModule(const Module &M); + + /// hasDebugInfo - Returns true if valid debug info is present. + /// + bool hasDebugInfo() const { return DbgInfoAvailable; } + void setDebugInfoAvailability(bool avail) { DbgInfoAvailable = avail; } + + bool callsEHReturn() const { return CallsEHReturn; } + void setCallsEHReturn(bool b) { CallsEHReturn = b; } + + bool callsUnwindInit() const { return CallsUnwindInit; } + void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } + + bool callsExternalVAFunctionWithFloatingPointArguments() const { + return CallsExternalVAFunctionWithFloatingPointArguments; + } + + void setCallsExternalVAFunctionWithFloatingPointArguments(bool b) { + CallsExternalVAFunctionWithFloatingPointArguments = b; + } + + /// getFrameMoves - Returns a reference to a list of moves done in the current + /// function's prologue. Used to construct frame maps for debug and exception + /// handling comsumers. + std::vector &getFrameMoves() { return FrameMoves; } + + /// getAddrLabelSymbol - Return the symbol to be used for the specified basic + /// block when its address is taken. This cannot be its normal LBB label + /// because the block may be accessed outside its containing function. + MCSymbol *getAddrLabelSymbol(const BasicBlock *BB); + + /// getAddrLabelSymbolToEmit - Return the symbol to be used for the specified + /// basic block when its address is taken. If other blocks were RAUW'd to + /// this one, we may have to emit them as well, return the whole set. + std::vector getAddrLabelSymbolToEmit(const BasicBlock *BB); + + /// takeDeletedSymbolsForFunction - If the specified function has had any + /// references to address-taken blocks generated, but the block got deleted, + /// return the symbol now so we can emit it. This prevents emitting a + /// reference to a symbol that has no definition. + void takeDeletedSymbolsForFunction(const Function *F, + std::vector &Result); + + + //===- EH ---------------------------------------------------------------===// + + /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the + /// specified MachineBasicBlock. + LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); + + /// addInvoke - Provide the begin and end labels of an invoke style call and + /// associate it with a try landing pad block. + void addInvoke(MachineBasicBlock *LandingPad, + MCSymbol *BeginLabel, MCSymbol *EndLabel); + + /// addLandingPad - Add a new panding pad. Returns the label ID for the + /// landing pad entry. + MCSymbol *addLandingPad(MachineBasicBlock *LandingPad); + + /// addPersonality - Provide the personality function for the exception + /// information. + void addPersonality(MachineBasicBlock *LandingPad, + const Function *Personality); + + /// getPersonalityIndex - Get index of the current personality function inside + /// Personalitites array + unsigned getPersonalityIndex() const; + + /// getPersonalities - Return array of personality functions ever seen. + const std::vector& getPersonalities() const { + return Personalities; + } + + /// isUsedFunction - Return true if the functions in the llvm.used list. This + /// does not return true for things in llvm.compiler.used unless they are also + /// in llvm.used. + bool isUsedFunction(const Function *F) { + return UsedFunctions.count(F); + } + + /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. + /// + void addCatchTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo); + + /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. + /// + void addFilterTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo); + + /// addCleanup - Add a cleanup action for a landing pad. + /// + void addCleanup(MachineBasicBlock *LandingPad); + + /// getTypeIDFor - Return the type id for the specified typeinfo. This is + /// function wide. + unsigned getTypeIDFor(const GlobalVariable *TI); + + /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is + /// function wide. + int getFilterIDFor(std::vector &TyIds); + + /// TidyLandingPads - Remap landing pad labels and remove any deleted landing + /// pads. + void TidyLandingPads(DenseMap *LPMap = 0); + + /// getLandingPads - Return a reference to the landing pad info for the + /// current function. + const std::vector &getLandingPads() const { + return LandingPads; + } + + /// setCallSiteBeginLabel - Map the begin label for a call site + void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) { + CallSiteMap[BeginLabel] = Site; + } + + /// getCallSiteBeginLabel - Get the call site number for a begin label + unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) { + assert(CallSiteMap.count(BeginLabel) && + "Missing call site number for EH_LABEL!"); + return CallSiteMap[BeginLabel]; + } + + /// setCurrentCallSite - Set the call site currently being processed. + void setCurrentCallSite(unsigned Site) { CurCallSite = Site; } + + /// getCurrentCallSite - Get the call site currently being processed, if any. + /// return zero if none. + unsigned getCurrentCallSite(void) { return CurCallSite; } + + /// getTypeInfos - Return a reference to the C++ typeinfo for the current + /// function. + const std::vector &getTypeInfos() const { + return TypeInfos; + } + + /// getFilterIds - Return a reference to the typeids encoding filters used in + /// the current function. + const std::vector &getFilterIds() const { + return FilterIds; + } + + /// getPersonality - Return a personality function if available. The presence + /// of one is required to emit exception handling info. + const Function *getPersonality() const; + + /// setVariableDbgInfo - Collect information used to emit debugging + /// information of a variable. + void setVariableDbgInfo(MDNode *N, unsigned Slot, DebugLoc Loc) { + VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Loc))); + } + + VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; } + +}; // End class MachineModuleInfo + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineModuleInfoImpls.h b/final/include/llvm/CodeGen/MachineModuleInfoImpls.h new file mode 100644 index 00000000000..9401ffd199d --- /dev/null +++ b/final/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -0,0 +1,97 @@ +//===-- llvm/CodeGen/MachineModuleInfoImpls.h -------------------*- 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 object-file format specific implementations of +// MachineModuleInfoImpl. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H +#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H + +#include "llvm/CodeGen/MachineModuleInfo.h" + +namespace llvm { + class MCSymbol; + + /// MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation + /// for MachO targets. + class MachineModuleInfoMachO : public MachineModuleInfoImpl { + /// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub", + /// the value is something like "_foo". + DenseMap FnStubs; + + /// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra bit + /// is true if this GV is external. + DenseMap GVStubs; + + /// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like + /// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs + /// these are for things with hidden visibility. The extra bit is true if + /// this GV is external. + DenseMap HiddenGVStubs; + + virtual void Anchor(); // Out of line virtual method. + public: + MachineModuleInfoMachO(const MachineModuleInfo &) {} + + StubValueTy &getFnStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return FnStubs[Sym]; + } + + StubValueTy &getGVStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return GVStubs[Sym]; + } + + StubValueTy &getHiddenGVStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return HiddenGVStubs[Sym]; + } + + /// Accessor methods to return the set of stubs in sorted order. + SymbolListTy GetFnStubList() const { + return GetSortedStubs(FnStubs); + } + SymbolListTy GetGVStubList() const { + return GetSortedStubs(GVStubs); + } + SymbolListTy GetHiddenGVStubList() const { + return GetSortedStubs(HiddenGVStubs); + } + }; + + /// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation + /// for ELF targets. + class MachineModuleInfoELF : public MachineModuleInfoImpl { + /// GVStubs - These stubs are used to materialize global addresses in PIC + /// mode. + DenseMap GVStubs; + + virtual void Anchor(); // Out of line virtual method. + public: + MachineModuleInfoELF(const MachineModuleInfo &) {} + + StubValueTy &getGVStubEntry(MCSymbol *Sym) { + assert(Sym && "Key cannot be null"); + return GVStubs[Sym]; + } + + /// Accessor methods to return the set of stubs in sorted order. + + SymbolListTy GetGVStubList() const { + return GetSortedStubs(GVStubs); + } + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/MachineOperand.h b/final/include/llvm/CodeGen/MachineOperand.h new file mode 100644 index 00000000000..8acc9490d8d --- /dev/null +++ b/final/include/llvm/CodeGen/MachineOperand.h @@ -0,0 +1,564 @@ +//===-- llvm/CodeGen/MachineOperand.h - MachineOperand class ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineOperand class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEOPERAND_H +#define LLVM_CODEGEN_MACHINEOPERAND_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class BlockAddress; +class ConstantFP; +class GlobalValue; +class MachineBasicBlock; +class MachineInstr; +class MachineRegisterInfo; +class MDNode; +class TargetMachine; +class TargetRegisterInfo; +class raw_ostream; +class MCSymbol; + +/// MachineOperand class - Representation of each machine instruction operand. +/// +class MachineOperand { +public: + enum MachineOperandType { + MO_Register, ///< Register operand. + MO_Immediate, ///< Immediate operand + MO_FPImmediate, ///< Floating-point immediate operand + MO_MachineBasicBlock, ///< MachineBasicBlock reference + MO_FrameIndex, ///< Abstract Stack Frame Index + MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool + MO_JumpTableIndex, ///< Address of indexed Jump Table for switch + MO_ExternalSymbol, ///< Name of external global symbol + MO_GlobalAddress, ///< Address of a global value + MO_BlockAddress, ///< Address of a basic block + MO_Metadata, ///< Metadata reference (for debug info) + MO_MCSymbol ///< MCSymbol reference (for debug/eh info) + }; + +private: + /// OpKind - Specify what kind of operand this is. This discriminates the + /// union. + unsigned char OpKind; // MachineOperandType + + /// SubReg - Subregister number, only valid for MO_Register. A value of 0 + /// indicates the MO_Register has no subReg. + unsigned char SubReg; + + /// TargetFlags - This is a set of target-specific operand flags. + unsigned char TargetFlags; + + /// IsDef/IsImp/IsKill/IsDead flags - These are only valid for MO_Register + /// operands. + + /// IsDef - True if this is a def, false if this is a use of the register. + /// + bool IsDef : 1; + + /// IsImp - True if this is an implicit def or use, false if it is explicit. + /// + bool IsImp : 1; + + /// IsKill - True if this instruction is the last use of the register on this + /// path through the function. This is only valid on uses of registers. + bool IsKill : 1; + + /// IsDead - True if this register is never used by a subsequent instruction. + /// This is only valid on definitions of registers. + bool IsDead : 1; + + /// IsUndef - True if this is a register def / use of "undef", i.e. register + /// defined by an IMPLICIT_DEF. This is only valid on registers. + bool IsUndef : 1; + + /// IsEarlyClobber - True if this MO_Register 'def' operand is written to + /// by the MachineInstr before all input registers are read. This is used to + /// model the GCC inline asm '&' constraint modifier. + bool IsEarlyClobber : 1; + + /// IsDebug - True if this MO_Register 'use' operand is in a debug pseudo, + /// not a real instruction. Such uses should be ignored during codegen. + bool IsDebug : 1; + + /// SmallContents - Thisreally should be part of the Contents union, but lives + /// out here so we can get a better packed struct. + /// MO_Register: Register number. + /// OffsetedInfo: Low bits of offset. + union { + unsigned RegNo; // For MO_Register. + unsigned OffsetLo; // Matches Contents.OffsetedInfo.OffsetHi. + } SmallContents; + + /// ParentMI - This is the instruction that this operand is embedded into. + /// This is valid for all operand types, when the operand is in an instr. + MachineInstr *ParentMI; + + /// Contents union - This contains the payload for the various operand types. + union { + MachineBasicBlock *MBB; // For MO_MachineBasicBlock. + const ConstantFP *CFP; // For MO_FPImmediate. + int64_t ImmVal; // For MO_Immediate. + const MDNode *MD; // For MO_Metadata. + MCSymbol *Sym; // For MO_MCSymbol + + struct { // For MO_Register. + // Register number is in SmallContents.RegNo. + MachineOperand **Prev; // Access list for register. + MachineOperand *Next; + } Reg; + + /// OffsetedInfo - This struct contains the offset and an object identifier. + /// this represent the object as with an optional offset from it. + struct { + union { + int Index; // For MO_*Index - The index itself. + const char *SymbolName; // For MO_ExternalSymbol. + const GlobalValue *GV; // For MO_GlobalAddress. + const BlockAddress *BA; // For MO_BlockAddress. + } Val; + // Low bits of offset are in SmallContents.OffsetLo. + int OffsetHi; // An offset from the object, high 32 bits. + } OffsetedInfo; + } Contents; + + explicit MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) { + TargetFlags = 0; + } +public: + /// getType - Returns the MachineOperandType for this operand. + /// + MachineOperandType getType() const { return (MachineOperandType)OpKind; } + + unsigned char getTargetFlags() const { return TargetFlags; } + void setTargetFlags(unsigned char F) { TargetFlags = F; } + void addTargetFlag(unsigned char F) { TargetFlags |= F; } + + + /// getParent - Return the instruction that this operand belongs to. + /// + MachineInstr *getParent() { return ParentMI; } + const MachineInstr *getParent() const { return ParentMI; } + + /// clearParent - Reset the parent pointer. + /// + /// The MachineOperand copy constructor also copies ParentMI, expecting the + /// original to be deleted. If a MachineOperand is ever stored outside a + /// MachineInstr, the parent pointer must be cleared. + /// + /// Never call clearParent() on an operand in a MachineInstr. + /// + void clearParent() { ParentMI = 0; } + + void print(raw_ostream &os, const TargetMachine *TM = 0) const; + + //===--------------------------------------------------------------------===// + // Accessors that tell you what kind of MachineOperand you're looking at. + //===--------------------------------------------------------------------===// + + /// isReg - Tests if this is a MO_Register operand. + bool isReg() const { return OpKind == MO_Register; } + /// isImm - Tests if this is a MO_Immediate operand. + bool isImm() const { return OpKind == MO_Immediate; } + /// isFPImm - Tests if this is a MO_FPImmediate operand. + bool isFPImm() const { return OpKind == MO_FPImmediate; } + /// isMBB - Tests if this is a MO_MachineBasicBlock operand. + bool isMBB() const { return OpKind == MO_MachineBasicBlock; } + /// isFI - Tests if this is a MO_FrameIndex operand. + bool isFI() const { return OpKind == MO_FrameIndex; } + /// isCPI - Tests if this is a MO_ConstantPoolIndex operand. + bool isCPI() const { return OpKind == MO_ConstantPoolIndex; } + /// isJTI - Tests if this is a MO_JumpTableIndex operand. + bool isJTI() const { return OpKind == MO_JumpTableIndex; } + /// isGlobal - Tests if this is a MO_GlobalAddress operand. + bool isGlobal() const { return OpKind == MO_GlobalAddress; } + /// isSymbol - Tests if this is a MO_ExternalSymbol operand. + bool isSymbol() const { return OpKind == MO_ExternalSymbol; } + /// isBlockAddress - Tests if this is a MO_BlockAddress operand. + bool isBlockAddress() const { return OpKind == MO_BlockAddress; } + /// isMetadata - Tests if this is a MO_Metadata operand. + bool isMetadata() const { return OpKind == MO_Metadata; } + bool isMCSymbol() const { return OpKind == MO_MCSymbol; } + + //===--------------------------------------------------------------------===// + // Accessors for Register Operands + //===--------------------------------------------------------------------===// + + /// getReg - Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return SmallContents.RegNo; + } + + unsigned getSubReg() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return (unsigned)SubReg; + } + + bool isUse() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return !IsDef; + } + + bool isDef() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsDef; + } + + bool isImplicit() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsImp; + } + + bool isDead() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsDead; + } + + bool isKill() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsKill; + } + + bool isUndef() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsUndef; + } + + bool isEarlyClobber() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsEarlyClobber; + } + + bool isDebug() const { + assert(isReg() && "Wrong MachineOperand accessor"); + return IsDebug; + } + + /// getNextOperandForReg - Return the next MachineOperand in the function that + /// uses or defines this register. + MachineOperand *getNextOperandForReg() const { + assert(isReg() && "This is not a register operand!"); + return Contents.Reg.Next; + } + + //===--------------------------------------------------------------------===// + // Mutators for Register Operands + //===--------------------------------------------------------------------===// + + /// Change the register this operand corresponds to. + /// + void setReg(unsigned Reg); + + void setSubReg(unsigned subReg) { + assert(isReg() && "Wrong MachineOperand accessor"); + SubReg = (unsigned char)subReg; + } + + /// substVirtReg - Substitute the current register with the virtual + /// subregister Reg:SubReg. Take any existing SubReg index into account, + /// using TargetRegisterInfo to compose the subreg indices if necessary. + /// Reg must be a virtual register, SubIdx can be 0. + /// + void substVirtReg(unsigned Reg, unsigned SubIdx, const TargetRegisterInfo&); + + /// substPhysReg - Substitute the current register with the physical register + /// Reg, taking any existing SubReg into account. For instance, + /// substPhysReg(%EAX) will change %reg1024:sub_8bit to %AL. + /// + void substPhysReg(unsigned Reg, const TargetRegisterInfo&); + + void setIsUse(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + assert((Val || !isDebug()) && "Marking a debug operation as def"); + IsDef = !Val; + } + + void setIsDef(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + assert((!Val || !isDebug()) && "Marking a debug operation as def"); + IsDef = Val; + } + + void setImplicit(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsImp = Val; + } + + void setIsKill(bool Val = true) { + assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); + assert((!Val || !isDebug()) && "Marking a debug operation as kill"); + IsKill = Val; + } + + void setIsDead(bool Val = true) { + assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + IsDead = Val; + } + + void setIsUndef(bool Val = true) { + assert(isReg() && "Wrong MachineOperand accessor"); + IsUndef = Val; + } + + void setIsEarlyClobber(bool Val = true) { + assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + IsEarlyClobber = Val; + } + + void setIsDebug(bool Val = true) { + assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + IsDebug = Val; + } + + //===--------------------------------------------------------------------===// + // Accessors for various operand types. + //===--------------------------------------------------------------------===// + + int64_t getImm() const { + assert(isImm() && "Wrong MachineOperand accessor"); + return Contents.ImmVal; + } + + const ConstantFP *getFPImm() const { + assert(isFPImm() && "Wrong MachineOperand accessor"); + return Contents.CFP; + } + + MachineBasicBlock *getMBB() const { + assert(isMBB() && "Wrong MachineOperand accessor"); + return Contents.MBB; + } + + int getIndex() const { + assert((isFI() || isCPI() || isJTI()) && + "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.Index; + } + + const GlobalValue *getGlobal() const { + assert(isGlobal() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.GV; + } + + const BlockAddress *getBlockAddress() const { + assert(isBlockAddress() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.BA; + } + + MCSymbol *getMCSymbol() const { + assert(isMCSymbol() && "Wrong MachineOperand accessor"); + return Contents.Sym; + } + + /// getOffset - Return the offset from the symbol in this operand. This always + /// returns 0 for ExternalSymbol operands. + int64_t getOffset() const { + assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && + "Wrong MachineOperand accessor"); + return (int64_t(Contents.OffsetedInfo.OffsetHi) << 32) | + SmallContents.OffsetLo; + } + + const char *getSymbolName() const { + assert(isSymbol() && "Wrong MachineOperand accessor"); + return Contents.OffsetedInfo.Val.SymbolName; + } + + const MDNode *getMetadata() const { + assert(isMetadata() && "Wrong MachineOperand accessor"); + return Contents.MD; + } + + //===--------------------------------------------------------------------===// + // Mutators for various operand types. + //===--------------------------------------------------------------------===// + + void setImm(int64_t immVal) { + assert(isImm() && "Wrong MachineOperand mutator"); + Contents.ImmVal = immVal; + } + + void setOffset(int64_t Offset) { + assert((isGlobal() || isSymbol() || isCPI() || isBlockAddress()) && + "Wrong MachineOperand accessor"); + SmallContents.OffsetLo = unsigned(Offset); + Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); + } + + void setIndex(int Idx) { + assert((isFI() || isCPI() || isJTI()) && + "Wrong MachineOperand accessor"); + Contents.OffsetedInfo.Val.Index = Idx; + } + + void setMBB(MachineBasicBlock *MBB) { + assert(isMBB() && "Wrong MachineOperand accessor"); + Contents.MBB = MBB; + } + + //===--------------------------------------------------------------------===// + // Other methods. + //===--------------------------------------------------------------------===// + + /// isIdenticalTo - Return true if this operand is identical to the specified + /// operand. Note: This method ignores isKill and isDead properties. + bool isIdenticalTo(const MachineOperand &Other) const; + + /// ChangeToImmediate - Replace this operand with a new immediate operand of + /// the specified value. If an operand is known to be an immediate already, + /// the setImm method should be used. + void ChangeToImmediate(int64_t ImmVal); + + /// ChangeToRegister - Replace this operand with a new register operand of + /// the specified value. If an operand is known to be an register already, + /// the setReg method should be used. + void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false, + bool isKill = false, bool isDead = false, + bool isUndef = false, bool isDebug = false); + + //===--------------------------------------------------------------------===// + // Construction methods. + //===--------------------------------------------------------------------===// + + static MachineOperand CreateImm(int64_t Val) { + MachineOperand Op(MachineOperand::MO_Immediate); + Op.setImm(Val); + return Op; + } + + static MachineOperand CreateFPImm(const ConstantFP *CFP) { + MachineOperand Op(MachineOperand::MO_FPImmediate); + Op.Contents.CFP = CFP; + return Op; + } + + static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp = false, + bool isKill = false, bool isDead = false, + bool isUndef = false, + bool isEarlyClobber = false, + unsigned SubReg = 0, + bool isDebug = false) { + MachineOperand Op(MachineOperand::MO_Register); + Op.IsDef = isDef; + Op.IsImp = isImp; + Op.IsKill = isKill; + Op.IsDead = isDead; + Op.IsUndef = isUndef; + Op.IsEarlyClobber = isEarlyClobber; + Op.IsDebug = isDebug; + Op.SmallContents.RegNo = Reg; + Op.Contents.Reg.Prev = 0; + Op.Contents.Reg.Next = 0; + Op.SubReg = SubReg; + return Op; + } + static MachineOperand CreateMBB(MachineBasicBlock *MBB, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_MachineBasicBlock); + Op.setMBB(MBB); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateFI(unsigned Idx) { + MachineOperand Op(MachineOperand::MO_FrameIndex); + Op.setIndex(Idx); + return Op; + } + static MachineOperand CreateCPI(unsigned Idx, int Offset, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_ConstantPoolIndex); + Op.setIndex(Idx); + Op.setOffset(Offset); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateJTI(unsigned Idx, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_JumpTableIndex); + Op.setIndex(Idx); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_GlobalAddress); + Op.Contents.OffsetedInfo.Val.GV = GV; + Op.setOffset(Offset); + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateES(const char *SymName, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_ExternalSymbol); + Op.Contents.OffsetedInfo.Val.SymbolName = SymName; + Op.setOffset(0); // Offset is always 0. + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateBA(const BlockAddress *BA, + unsigned char TargetFlags = 0) { + MachineOperand Op(MachineOperand::MO_BlockAddress); + Op.Contents.OffsetedInfo.Val.BA = BA; + Op.setOffset(0); // Offset is always 0. + Op.setTargetFlags(TargetFlags); + return Op; + } + static MachineOperand CreateMetadata(const MDNode *Meta) { + MachineOperand Op(MachineOperand::MO_Metadata); + Op.Contents.MD = Meta; + return Op; + } + + static MachineOperand CreateMCSymbol(MCSymbol *Sym) { + MachineOperand Op(MachineOperand::MO_MCSymbol); + Op.Contents.Sym = Sym; + return Op; + } + + friend class MachineInstr; + friend class MachineRegisterInfo; +private: + //===--------------------------------------------------------------------===// + // Methods for handling register use/def lists. + //===--------------------------------------------------------------------===// + + /// isOnRegUseList - Return true if this operand is on a register use/def list + /// or false if not. This can only be called for register operands that are + /// part of a machine instruction. + bool isOnRegUseList() const { + assert(isReg() && "Can only add reg operand to use lists"); + return Contents.Reg.Prev != 0; + } + + /// AddRegOperandToRegInfo - Add this register operand to the specified + /// MachineRegisterInfo. If it is null, then the next/prev fields should be + /// explicitly nulled out. + void AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo); + + /// RemoveRegOperandFromRegInfo - Remove this register operand from the + /// MachineRegisterInfo it is linked with. + void RemoveRegOperandFromRegInfo(); +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { + MO.print(OS, 0); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachinePassRegistry.h b/final/include/llvm/CodeGen/MachinePassRegistry.h new file mode 100644 index 00000000000..6ee2e90a9f5 --- /dev/null +++ b/final/include/llvm/CodeGen/MachinePassRegistry.h @@ -0,0 +1,156 @@ +//===-- llvm/CodeGen/MachinePassRegistry.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the mechanics for machine function pass registries. A +// function pass registry (MachinePassRegistry) is auto filled by the static +// constructors of MachinePassRegistryNode. Further there is a command line +// parser (RegisterPassParser) which listens to each registry for additions +// and deletions, so that the appropriate command option is updated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H +#define LLVM_CODEGEN_MACHINEPASSREGISTRY_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +typedef void *(*MachinePassCtor)(); + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryListener - Listener to adds and removals of nodes in +/// registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryListener { +public: + MachinePassRegistryListener() {} + virtual ~MachinePassRegistryListener() {} + virtual void NotifyAdd(const char *N, MachinePassCtor C, const char *D) = 0; + virtual void NotifyRemove(const char *N) = 0; +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryNode - Machine pass node stored in registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryNode { + +private: + + MachinePassRegistryNode *Next; // Next function pass in list. + const char *Name; // Name of function pass. + const char *Description; // Description string. + MachinePassCtor Ctor; // Function pass creator. + +public: + + MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) + : Next(NULL) + , Name(N) + , Description(D) + , Ctor(C) + {} + + // Accessors + MachinePassRegistryNode *getNext() const { return Next; } + MachinePassRegistryNode **getNextAddress() { return &Next; } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } + MachinePassCtor getCtor() const { return Ctor; } + void setNext(MachinePassRegistryNode *N) { Next = N; } + +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistry - Track the registration of machine passes. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistry { + +private: + + MachinePassRegistryNode *List; // List of registry nodes. + MachinePassCtor Default; // Default function pass creator. + MachinePassRegistryListener* Listener;// Listener for list adds are removes. + +public: + + // NO CONSTRUCTOR - we don't want static constructor ordering to mess + // with the registry. + + // Accessors. + // + MachinePassRegistryNode *getList() { return List; } + MachinePassCtor getDefault() { return Default; } + void setDefault(MachinePassCtor C) { Default = C; } + void setListener(MachinePassRegistryListener *L) { Listener = L; } + + /// Add - Adds a function pass to the registration list. + /// + void Add(MachinePassRegistryNode *Node); + + /// Remove - Removes a function pass from the registration list. + /// + void Remove(MachinePassRegistryNode *Node); + +}; + + +//===----------------------------------------------------------------------===// +/// +/// RegisterPassParser class - Handle the addition of new machine passes. +/// +//===----------------------------------------------------------------------===// +template +class RegisterPassParser : public MachinePassRegistryListener, + public cl::parser { +public: + RegisterPassParser() {} + ~RegisterPassParser() { RegistryClass::setListener(NULL); } + + void initialize(cl::Option &O) { + cl::parser::initialize(O); + + // Add existing passes to option. + for (RegistryClass *Node = RegistryClass::getList(); + Node; Node = Node->getNext()) { + this->addLiteralOption(Node->getName(), + (typename RegistryClass::FunctionPassCtor)Node->getCtor(), + Node->getDescription()); + } + + // Make sure we listen for list changes. + RegistryClass::setListener(this); + } + + // Implement the MachinePassRegistryListener callbacks. + // + virtual void NotifyAdd(const char *N, + MachinePassCtor C, + const char *D) { + this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D); + } + virtual void NotifyRemove(const char *N) { + this->removeLiteralOption(N); + } +}; + + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/MachineRegisterInfo.h b/final/include/llvm/CodeGen/MachineRegisterInfo.h new file mode 100644 index 00000000000..74df8da20ed --- /dev/null +++ b/final/include/llvm/CodeGen/MachineRegisterInfo.h @@ -0,0 +1,404 @@ +//===-- llvm/CodeGen/MachineRegisterInfo.h ----------------------*- 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 MachineRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEREGISTERINFO_H +#define LLVM_CODEGEN_MACHINEREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" +#include + +namespace llvm { + +/// MachineRegisterInfo - Keep track of information for virtual and physical +/// registers, including vreg register classes, use/def chains for registers, +/// etc. +class MachineRegisterInfo { + /// VRegInfo - Information we keep for each virtual register. + /// + /// Each element in this list contains the register class of the vreg and the + /// start of the use/def list for the register. + IndexedMap, + VirtReg2IndexFunctor> VRegInfo; + + /// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to + /// virtual registers. For each target register class, it keeps a list of + /// virtual registers belonging to the class. + std::vector *RegClass2VRegMap; + + /// RegAllocHints - This vector records register allocation hints for virtual + /// registers. For each virtual register, it keeps a register and hint type + /// pair making up the allocation hint. Hint type is target specific except + /// for the value 0 which means the second value of the pair is the preferred + /// register for allocation. For example, if the hint is <0, 1024>, it means + /// the allocator should prefer the physical register allocated to the virtual + /// register of the hint. + IndexedMap, VirtReg2IndexFunctor> RegAllocHints; + + /// PhysRegUseDefLists - This is an array of the head of the use/def list for + /// physical registers. + MachineOperand **PhysRegUseDefLists; + + /// UsedPhysRegs - This is a bit vector that is computed and set by the + /// register allocator, and must be kept up to date by passes that run after + /// register allocation (though most don't modify this). This is used + /// so that the code generator knows which callee save registers to save and + /// for other target specific uses. + BitVector UsedPhysRegs; + + /// LiveIns/LiveOuts - Keep track of the physical registers that are + /// livein/liveout of the function. Live in values are typically arguments in + /// registers, live out values are typically return values in registers. + /// LiveIn values are allowed to have virtual registers associated with them, + /// stored in the second element. + std::vector > LiveIns; + std::vector LiveOuts; + + MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT + void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT +public: + explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); + ~MachineRegisterInfo(); + + //===--------------------------------------------------------------------===// + // Register Info + //===--------------------------------------------------------------------===// + + /// reg_begin/reg_end - Provide iteration support to walk over all definitions + /// and uses of a register within the MachineFunction that corresponds to this + /// MachineRegisterInfo object. + template + class defusechain_iterator; + + /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified + /// register. + typedef defusechain_iterator reg_iterator; + reg_iterator reg_begin(unsigned RegNo) const { + return reg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_iterator reg_end() { return reg_iterator(0); } + + /// reg_empty - Return true if there are no instructions using or defining the + /// specified register (it may be live-in). + bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); } + + /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses + /// of the specified register, skipping those marked as Debug. + typedef defusechain_iterator reg_nodbg_iterator; + reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const { + return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_nodbg_iterator reg_nodbg_end() { return reg_nodbg_iterator(0); } + + /// reg_nodbg_empty - Return true if the only instructions using or defining + /// Reg are Debug instructions. + bool reg_nodbg_empty(unsigned RegNo) const { + return reg_nodbg_begin(RegNo) == reg_nodbg_end(); + } + + /// def_iterator/def_begin/def_end - Walk all defs of the specified register. + typedef defusechain_iterator def_iterator; + def_iterator def_begin(unsigned RegNo) const { + return def_iterator(getRegUseDefListHead(RegNo)); + } + static def_iterator def_end() { return def_iterator(0); } + + /// def_empty - Return true if there are no instructions defining the + /// specified register (it may be live-in). + bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } + + /// use_iterator/use_begin/use_end - Walk all uses of the specified register. + typedef defusechain_iterator use_iterator; + use_iterator use_begin(unsigned RegNo) const { + return use_iterator(getRegUseDefListHead(RegNo)); + } + static use_iterator use_end() { return use_iterator(0); } + + /// use_empty - Return true if there are no instructions using the specified + /// register. + bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); } + + /// hasOneUse - Return true if there is exactly one instruction using the + /// specified register. + bool hasOneUse(unsigned RegNo) const; + + /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the + /// specified register, skipping those marked as Debug. + typedef defusechain_iterator use_nodbg_iterator; + use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const { + return use_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static use_nodbg_iterator use_nodbg_end() { return use_nodbg_iterator(0); } + + /// use_nodbg_empty - Return true if there are no non-Debug instructions + /// using the specified register. + bool use_nodbg_empty(unsigned RegNo) const { + return use_nodbg_begin(RegNo) == use_nodbg_end(); + } + + /// hasOneNonDBGUse - Return true if there is exactly one non-Debug + /// instruction using the specified register. + bool hasOneNonDBGUse(unsigned RegNo) const; + + /// replaceRegWith - Replace all instances of FromReg with ToReg in the + /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), + /// except that it also changes any definitions of the register as well. + void replaceRegWith(unsigned FromReg, unsigned ToReg); + + /// getRegUseDefListHead - Return the head pointer for the register use/def + /// list for the specified virtual or physical register. + MachineOperand *&getRegUseDefListHead(unsigned RegNo) { + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; + } + + MachineOperand *getRegUseDefListHead(unsigned RegNo) const { + if (TargetRegisterInfo::isVirtualRegister(RegNo)) + return VRegInfo[RegNo].second; + return PhysRegUseDefLists[RegNo]; + } + + /// getVRegDef - Return the machine instr that defines the specified virtual + /// register or null if none is found. This assumes that the code is in SSA + /// form, so there should only be one definition. + MachineInstr *getVRegDef(unsigned Reg) const; + + /// clearKillFlags - Iterate over all the uses of the given register and + /// clear the kill flag from the MachineOperand. This function is used by + /// optimization passes which extend register lifetimes and need only + /// preserve conservative kill flag information. + void clearKillFlags(unsigned Reg) const; + +#ifndef NDEBUG + void dumpUses(unsigned RegNo) const; +#endif + + //===--------------------------------------------------------------------===// + // Virtual Register Info + //===--------------------------------------------------------------------===// + + /// getRegClass - Return the register class of the specified virtual register. + /// + const TargetRegisterClass *getRegClass(unsigned Reg) const { + return VRegInfo[Reg].first; + } + + /// setRegClass - Set the register class of the specified virtual register. + /// + void setRegClass(unsigned Reg, const TargetRegisterClass *RC); + + /// constrainRegClass - Constrain the register class of the specified virtual + /// register to be a common subclass of RC and the current register class. + /// Return the new register class, or NULL if no such class exists. + /// This should only be used when the constraint is known to be trivial, like + /// GR32 -> GR32_NOSP. Beware of increasing register pressure. + const TargetRegisterClass *constrainRegClass(unsigned Reg, + const TargetRegisterClass *RC); + + /// createVirtualRegister - Create and return a new virtual register in the + /// function with the specified register class. + /// + unsigned createVirtualRegister(const TargetRegisterClass *RegClass); + + /// getNumVirtRegs - Return the number of virtual registers created. + /// + unsigned getNumVirtRegs() const { return VRegInfo.size(); } + + /// getRegClassVirtRegs - Return the list of virtual registers of the given + /// target register class. + const std::vector & + getRegClassVirtRegs(const TargetRegisterClass *RC) const { + return RegClass2VRegMap[RC->getID()]; + } + + /// setRegAllocationHint - Specify a register allocation hint for the + /// specified virtual register. + void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { + RegAllocHints[Reg].first = Type; + RegAllocHints[Reg].second = PrefReg; + } + + /// getRegAllocationHint - Return the register allocation hint for the + /// specified virtual register. + std::pair + getRegAllocationHint(unsigned Reg) const { + return RegAllocHints[Reg]; + } + + //===--------------------------------------------------------------------===// + // Physical Register Use Info + //===--------------------------------------------------------------------===// + + /// isPhysRegUsed - Return true if the specified register is used in this + /// function. This only works after register allocation. + bool isPhysRegUsed(unsigned Reg) const { return UsedPhysRegs[Reg]; } + + /// setPhysRegUsed - Mark the specified register used in this function. + /// This should only be called during and after register allocation. + void setPhysRegUsed(unsigned Reg) { UsedPhysRegs[Reg] = true; } + + /// addPhysRegsUsed - Mark the specified registers used in this function. + /// This should only be called during and after register allocation. + void addPhysRegsUsed(const BitVector &Regs) { UsedPhysRegs |= Regs; } + + /// setPhysRegUnused - Mark the specified register unused in this function. + /// This should only be called during and after register allocation. + void setPhysRegUnused(unsigned Reg) { UsedPhysRegs[Reg] = false; } + + /// closePhysRegsUsed - Expand UsedPhysRegs to its transitive closure over + /// subregisters. That means that if R is used, so are all subregisters. + void closePhysRegsUsed(const TargetRegisterInfo&); + + //===--------------------------------------------------------------------===// + // LiveIn/LiveOut Management + //===--------------------------------------------------------------------===// + + /// addLiveIn/Out - Add the specified register as a live in/out. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg, unsigned vreg = 0) { + LiveIns.push_back(std::make_pair(Reg, vreg)); + } + void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } + + // Iteration support for live in/out sets. These sets are kept in sorted + // order by their register number. + typedef std::vector >::const_iterator + livein_iterator; + typedef std::vector::const_iterator liveout_iterator; + livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + liveout_iterator liveout_begin() const { return LiveOuts.begin(); } + liveout_iterator liveout_end() const { return LiveOuts.end(); } + bool liveout_empty() const { return LiveOuts.empty(); } + + bool isLiveIn(unsigned Reg) const; + bool isLiveOut(unsigned Reg) const; + + /// getLiveInPhysReg - If VReg is a live-in virtual register, return the + /// corresponding live-in physical register. + unsigned getLiveInPhysReg(unsigned VReg) const; + + /// getLiveInVirtReg - If PReg is a live-in physical register, return the + /// corresponding live-in physical register. + unsigned getLiveInVirtReg(unsigned PReg) const; + + /// EmitLiveInCopies - Emit copies to initialize livein virtual registers + /// into the given entry block. + void EmitLiveInCopies(MachineBasicBlock *EntryMBB, + const TargetRegisterInfo &TRI, + const TargetInstrInfo &TII); + +private: + void HandleVRegListReallocation(); + +public: + /// defusechain_iterator - This class provides iterator support for machine + /// operands in the function that use or define a specific register. If + /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it + /// returns defs. If neither are true then you are silly and it always + /// returns end(). If SkipDebug is true it skips uses marked Debug + /// when incrementing. + template + class defusechain_iterator + : public std::iterator { + MachineOperand *Op; + explicit defusechain_iterator(MachineOperand *op) : Op(op) { + // If the first node isn't one we're interested in, advance to one that + // we are interested in. + if (op) { + if ((!ReturnUses && op->isUse()) || + (!ReturnDefs && op->isDef()) || + (SkipDebug && op->isDebug())) + ++*this; + } + } + friend class MachineRegisterInfo; + public: + typedef std::iterator::reference reference; + typedef std::iterator::pointer pointer; + + defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {} + defusechain_iterator() : Op(0) {} + + bool operator==(const defusechain_iterator &x) const { + return Op == x.Op; + } + bool operator!=(const defusechain_iterator &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is equal to reg_end() on the value. + bool atEnd() const { return Op == 0; } + + // Iterator traversal: forward iteration only + defusechain_iterator &operator++() { // Preincrement + assert(Op && "Cannot increment end iterator!"); + Op = Op->getNextOperandForReg(); + + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnUses && Op->isUse()) || + (!ReturnDefs && Op->isDef()) || + (SkipDebug && Op->isDebug()))) + Op = Op->getNextOperandForReg(); + + return *this; + } + defusechain_iterator operator++(int) { // Postincrement + defusechain_iterator tmp = *this; ++*this; return tmp; + } + + /// skipInstruction - move forward until reaching a different instruction. + /// Return the skipped instruction that is no longer pointed to, or NULL if + /// already pointing to end(). + MachineInstr *skipInstruction() { + if (!Op) return 0; + MachineInstr *MI = Op->getParent(); + do ++*this; + while (Op && Op->getParent() == MI); + return MI; + } + + MachineOperand &getOperand() const { + assert(Op && "Cannot dereference end iterator!"); + return *Op; + } + + /// getOperandNo - Return the operand # of this MachineOperand in its + /// MachineInstr. + unsigned getOperandNo() const { + assert(Op && "Cannot dereference end iterator!"); + return Op - &Op->getParent()->getOperand(0); + } + + // Retrieve a reference to the current operand. + MachineInstr &operator*() const { + assert(Op && "Cannot dereference end iterator!"); + return *Op->getParent(); + } + + MachineInstr *operator->() const { + assert(Op && "Cannot dereference end iterator!"); + return Op->getParent(); + } + }; + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/MachineRelocation.h b/final/include/llvm/CodeGen/MachineRelocation.h new file mode 100644 index 00000000000..244b466e172 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineRelocation.h @@ -0,0 +1,342 @@ +//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- 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 MachineRelocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINERELOCATION_H +#define LLVM_CODEGEN_MACHINERELOCATION_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +class GlobalValue; +class MachineBasicBlock; + +/// MachineRelocation - This represents a target-specific relocation value, +/// produced by the code emitter. This relocation is resolved after the has +/// been emitted, either to an object file or to memory, when the target of the +/// relocation can be resolved. +/// +/// A relocation is made up of the following logical portions: +/// 1. An offset in the machine code buffer, the location to modify. +/// 2. A target specific relocation type (a number from 0 to 63). +/// 3. A symbol being referenced, either as a GlobalValue* or as a string. +/// 4. An optional constant value to be added to the reference. +/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is +/// not needed for the relocation. +/// 6. An index into the GOT, if the target uses a GOT +/// +class MachineRelocation { + enum AddressType { + isResult, // Relocation has be transformed into its result pointer. + isGV, // The Target.GV field is valid. + isIndirectSym, // Relocation of an indirect symbol. + isBB, // Relocation of BB address. + isExtSym, // The Target.ExtSym field is valid. + isConstPool, // Relocation of constant pool address. + isJumpTable, // Relocation of jump table address. + isGOTIndex // The Target.GOTIndex field is valid. + }; + + /// Offset - This is the offset from the start of the code buffer of the + /// relocation to perform. + uintptr_t Offset; + + /// ConstantVal - A field that may be used by the target relocation type. + intptr_t ConstantVal; + + union { + void *Result; // If this has been resolved to a resolved pointer + GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. + MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB + const char *ExtSym; // If this is a pointer to a named symbol + unsigned Index; // Constant pool / jump table index + unsigned GOTIndex; // Index in the GOT of this symbol/global + } Target; + + unsigned TargetReloType : 6; // The target relocation ID + AddressType AddrType : 4; // The field of Target to use + bool MayNeedFarStub : 1; // True if this relocation may require a far-stub + bool GOTRelative : 1; // Should this relocation be relative to the GOT? + bool TargetResolve : 1; // True if target should resolve the address + +public: + // Relocation types used in a generic implementation. Currently, relocation + // entries for all things use the generic VANILLA type until they are refined + // into target relocation types. + enum RelocationType { + VANILLA + }; + + /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue. + /// + static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType, + GlobalValue *GV, intptr_t cst = 0, + bool MayNeedFarStub = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isGV; + Result.MayNeedFarStub = MayNeedFarStub; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.GV = GV; + return Result; + } + + /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an + /// indirect symbol. + static MachineRelocation getIndirectSymbol(uintptr_t offset, + unsigned RelocationType, + GlobalValue *GV, intptr_t cst = 0, + bool MayNeedFarStub = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isIndirectSym; + Result.MayNeedFarStub = MayNeedFarStub; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.GV = GV; + return Result; + } + + /// MachineRelocation::getBB - Return a relocation entry for a BB. + /// + static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType, + MachineBasicBlock *MBB, intptr_t cst = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isBB; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = false; + Result.Target.MBB = MBB; + return Result; + } + + /// MachineRelocation::getExtSym - Return a relocation entry for an external + /// symbol, like "free". + /// + static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType, + const char *ES, intptr_t cst = 0, + bool GOTrelative = 0, + bool NeedStub = true) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isExtSym; + Result.MayNeedFarStub = NeedStub; + Result.GOTRelative = GOTrelative; + Result.TargetResolve = false; + Result.Target.ExtSym = ES; + return Result; + } + + /// MachineRelocation::getConstPool - Return a relocation entry for a constant + /// pool entry. + /// + static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType, + unsigned CPI, intptr_t cst = 0, + bool letTargetResolve = false) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isConstPool; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = letTargetResolve; + Result.Target.Index = CPI; + return Result; + } + + /// MachineRelocation::getJumpTable - Return a relocation entry for a jump + /// table entry. + /// + static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType, + unsigned JTI, intptr_t cst = 0, + bool letTargetResolve = false) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isJumpTable; + Result.MayNeedFarStub = false; + Result.GOTRelative = false; + Result.TargetResolve = letTargetResolve; + Result.Target.Index = JTI; + return Result; + } + + /// getMachineCodeOffset - Return the offset into the code buffer that the + /// relocation should be performed. + intptr_t getMachineCodeOffset() const { + return Offset; + } + + /// getRelocationType - Return the target-specific relocation ID for this + /// relocation. + unsigned getRelocationType() const { + return TargetReloType; + } + + /// getConstantVal - Get the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + intptr_t getConstantVal() const { + return ConstantVal; + } + + /// setConstantVal - Set the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + void setConstantVal(intptr_t val) { + ConstantVal = val; + } + + /// isGlobalValue - Return true if this relocation is a GlobalValue, as + /// opposed to a constant string. + bool isGlobalValue() const { + return AddrType == isGV; + } + + /// isIndirectSymbol - Return true if this relocation is the address an + /// indirect symbol + bool isIndirectSymbol() const { + return AddrType == isIndirectSym; + } + + /// isBasicBlock - Return true if this relocation is a basic block reference. + /// + bool isBasicBlock() const { + return AddrType == isBB; + } + + /// isExternalSymbol - Return true if this is a constant string. + /// + bool isExternalSymbol() const { + return AddrType == isExtSym; + } + + /// isConstantPoolIndex - Return true if this is a constant pool reference. + /// + bool isConstantPoolIndex() const { + return AddrType == isConstPool; + } + + /// isJumpTableIndex - Return true if this is a jump table reference. + /// + bool isJumpTableIndex() const { + return AddrType == isJumpTable; + } + + /// isGOTRelative - Return true the target wants the index into the GOT of + /// the symbol rather than the address of the symbol. + bool isGOTRelative() const { + return GOTRelative; + } + + /// mayNeedFarStub - This function returns true if the JIT for this target may + /// need either a stub function or an indirect global-variable load to handle + /// the relocated GlobalValue reference. For example, the x86-64 call + /// instruction can only call functions within +/-2GB of the call site. + /// Anything farther away needs a longer mov+call sequence, which can't just + /// be written on top of the existing call. + bool mayNeedFarStub() const { + return MayNeedFarStub; + } + + /// letTargetResolve - Return true if the target JITInfo is usually + /// responsible for resolving the address of this relocation. + bool letTargetResolve() const { + return TargetResolve; + } + + /// getGlobalValue - If this is a global value reference, return the + /// referenced global. + GlobalValue *getGlobalValue() const { + assert((isGlobalValue() || isIndirectSymbol()) && + "This is not a global value reference!"); + return Target.GV; + } + + MachineBasicBlock *getBasicBlock() const { + assert(isBasicBlock() && "This is not a basic block reference!"); + return Target.MBB; + } + + /// getString - If this is a string value, return the string reference. + /// + const char *getExternalSymbol() const { + assert(isExternalSymbol() && "This is not an external symbol reference!"); + return Target.ExtSym; + } + + /// getConstantPoolIndex - If this is a const pool reference, return + /// the index into the constant pool. + unsigned getConstantPoolIndex() const { + assert(isConstantPoolIndex() && "This is not a constant pool reference!"); + return Target.Index; + } + + /// getJumpTableIndex - If this is a jump table reference, return + /// the index into the jump table. + unsigned getJumpTableIndex() const { + assert(isJumpTableIndex() && "This is not a jump table reference!"); + return Target.Index; + } + + /// getResultPointer - Once this has been resolved to point to an actual + /// address, this returns the pointer. + void *getResultPointer() const { + assert(AddrType == isResult && "Result pointer isn't set yet!"); + return Target.Result; + } + + /// setResultPointer - Set the result to the specified pointer value. + /// + void setResultPointer(void *Ptr) { + Target.Result = Ptr; + AddrType = isResult; + } + + /// setGOTIndex - Set the GOT index to a specific value. + void setGOTIndex(unsigned idx) { + AddrType = isGOTIndex; + Target.GOTIndex = idx; + } + + /// getGOTIndex - Once this has been resolved to an entry in the GOT, + /// this returns that index. The index is from the lowest address entry + /// in the GOT. + unsigned getGOTIndex() const { + assert(AddrType == isGOTIndex); + return Target.GOTIndex; + } +}; +} + +#endif diff --git a/final/include/llvm/CodeGen/MachineSSAUpdater.h b/final/include/llvm/CodeGen/MachineSSAUpdater.h new file mode 100644 index 00000000000..cbb45a71275 --- /dev/null +++ b/final/include/llvm/CodeGen/MachineSSAUpdater.h @@ -0,0 +1,115 @@ +//===-- MachineSSAUpdater.h - Unstructured SSA Update Tool ------*- 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 MachineSSAUpdater class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H +#define LLVM_CODEGEN_MACHINESSAUPDATER_H + +namespace llvm { + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class MachineOperand; + class MachineRegisterInfo; + class TargetInstrInfo; + class TargetRegisterClass; + template class SmallVectorImpl; + template class SSAUpdaterTraits; + class BumpPtrAllocator; + +/// MachineSSAUpdater - This class updates SSA form for a set of virtual +/// registers defined in multiple blocks. This is used when code duplication +/// or another unstructured transformation wants to rewrite a set of uses of one +/// vreg with uses of a set of vregs. +class MachineSSAUpdater { + friend class SSAUpdaterTraits; + +private: + /// AvailableVals - This keeps track of which value to use on a per-block + /// basis. When we insert PHI nodes, we keep track of them here. + //typedef DenseMap AvailableValsTy; + void *AV; + + /// VR - Current virtual register whose uses are being updated. + unsigned VR; + + /// VRC - Register class of the current virtual register. + const TargetRegisterClass *VRC; + + /// InsertedPHIs - If this is non-null, the MachineSSAUpdater adds all PHI + /// nodes that it creates to the vector. + SmallVectorImpl *InsertedPHIs; + + const TargetInstrInfo *TII; + MachineRegisterInfo *MRI; +public: + /// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be + /// filled in with all PHI Nodes created by rewriting. + explicit MachineSSAUpdater(MachineFunction &MF, + SmallVectorImpl *InsertedPHIs = 0); + ~MachineSSAUpdater(); + + /// Initialize - Reset this object to get ready for a new set of SSA + /// updates. + void Initialize(unsigned V); + + /// AddAvailableValue - Indicate that a rewritten value is available at the + /// end of the specified block with the specified value. + void AddAvailableValue(MachineBasicBlock *BB, unsigned V); + + /// HasValueForBlock - Return true if the MachineSSAUpdater already has a + /// value for the specified block. + bool HasValueForBlock(MachineBasicBlock *BB) const; + + /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is + /// live at the end of the specified block. + unsigned GetValueAtEndOfBlock(MachineBasicBlock *BB); + + /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that + /// is live in the middle of the specified block. + /// + /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one + /// important case: if there is a definition of the rewritten value after the + /// 'use' in BB. Consider code like this: + /// + /// X1 = ... + /// SomeBB: + /// use(X) + /// X2 = ... + /// br Cond, SomeBB, OutBB + /// + /// In this case, there are two values (X1 and X2) added to the AvailableVals + /// set by the client of the rewriter, and those values are both live out of + /// their respective blocks. However, the use of X happens in the *middle* of + /// a block. Because of this, we need to insert a new PHI node in SomeBB to + /// merge the appropriate values, and this value isn't live out of the block. + /// + unsigned GetValueInMiddleOfBlock(MachineBasicBlock *BB); + + /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, + /// which use their value in the corresponding predecessor. Note that this + /// will not work if the use is supposed to be rewritten to a value defined in + /// the same block as the use, but above it. Any 'AddAvailableValue's added + /// for the use's block will be considered to be below it. + void RewriteUse(MachineOperand &U); + +private: + void ReplaceRegWith(unsigned OldReg, unsigned NewReg); + unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); + + void operator=(const MachineSSAUpdater&); // DO NOT IMPLEMENT + MachineSSAUpdater(const MachineSSAUpdater&); // DO NOT IMPLEMENT +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/ObjectCodeEmitter.h b/final/include/llvm/CodeGen/ObjectCodeEmitter.h new file mode 100644 index 00000000000..d46628caae7 --- /dev/null +++ b/final/include/llvm/CodeGen/ObjectCodeEmitter.h @@ -0,0 +1,171 @@ +//===-- llvm/CodeGen/ObjectCodeEmitter.h - Object Code Emitter -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generalized Object Code Emitter, works with ObjectModule and BinaryObject. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_OBJECTCODEEMITTER_H +#define LLVM_CODEGEN_OBJECTCODEEMITTER_H + +#include "llvm/CodeGen/MachineCodeEmitter.h" + +namespace llvm { + +class BinaryObject; +class MachineBasicBlock; +class MachineCodeEmitter; +class MachineFunction; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineModuleInfo; + +class ObjectCodeEmitter : public MachineCodeEmitter { +protected: + + /// Binary Object (Section or Segment) we are emitting to. + BinaryObject *BO; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector MBBLocations; + + /// LabelLocations - This vector is a mapping from Label ID's to their + /// address. + std::vector LabelLocations; + + /// CPLocations - This is a map of constant pool indices to offsets from the + /// start of the section for that constant pool index. + std::vector CPLocations; + + /// CPSections - This is a map of constant pool indices to the Section + /// containing the constant pool entry for that index. + std::vector CPSections; + + /// JTLocations - This is a map of jump table indices to offsets from the + /// start of the section for that jump table index. + std::vector JTLocations; + +public: + ObjectCodeEmitter(); + ObjectCodeEmitter(BinaryObject *bo); + virtual ~ObjectCodeEmitter(); + + /// setBinaryObject - set the BinaryObject we are writting to + void setBinaryObject(BinaryObject *bo); + + /// emitByte - This callback is invoked when a byte needs to be + /// written to the data stream, without buffer overflow testing. + void emitByte(uint8_t B); + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in little-endian format. + void emitWordLE(uint32_t W); + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the data stream in big-endian format. + void emitWordBE(uint32_t W); + + /// emitDWordLE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in little-endian format. + void emitDWordLE(uint64_t W); + + /// emitDWordBE - This callback is invoked when a 64-bit word needs to be + /// written to the data stream in big-endian format. + void emitDWordBE(uint64_t W); + + /// emitAlignment - Move the CurBufferPtr pointer up to the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment = 0, uint8_t fill = 0); + + /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be + /// written to the data stream. + void emitULEB128Bytes(uint64_t Value); + + /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be + /// written to the data stream. + void emitSLEB128Bytes(uint64_t Value); + + /// emitString - This callback is invoked when a String needs to be + /// written to the data stream. + void emitString(const std::string &String); + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + uintptr_t getCurrentPCValue() const; + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + uintptr_t getCurrentPCOffset() const; + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + void addRelocation(const MachineRelocation& relocation); + + /// earlyResolveAddresses - True if the code emitter can use symbol addresses + /// during code emission time. The JIT is capable of doing this because it + /// creates jump tables or constant pools in memory on the fly while the + /// object code emitters rely on a linker to have real addresses and should + /// use relocations instead. + bool earlyResolveAddresses() const { return false; } + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + virtual bool finishFunction(MachineFunction &F) = 0; + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB); + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const; + + /// emitJumpTables - Emit all the jump tables for a given jump table info + /// record to the appropriate section. + virtual void emitJumpTables(MachineJumpTableInfo *MJTI) = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const; + + /// emitConstantPool - For each constant pool entry, figure out which section + /// the constant should live in, allocate space for it, and emit it to the + /// Section data buffer. + virtual void emitConstantPool(MachineConstantPool *MCP) = 0; + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const; + + /// getConstantPoolEntrySection - Return the section of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + virtual uintptr_t getConstantPoolEntrySection(unsigned Index) const; + + /// Specifies the MachineModuleInfo object. This is used for exception handling + /// purposes. + virtual void setModuleInfo(MachineModuleInfo* Info) = 0; + // to be implemented or depreciated with MachineModuleInfo + +}; // end class ObjectCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/final/include/llvm/CodeGen/PBQP/Graph.h b/final/include/llvm/CodeGen/PBQP/Graph.h new file mode 100644 index 00000000000..b2224cb051d --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/Graph.h @@ -0,0 +1,425 @@ +//===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// PBQP Graph class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PBQP_GRAPH_H +#define LLVM_CODEGEN_PBQP_GRAPH_H + +#include "Math.h" + +#include +#include +#include + +namespace PBQP { + + /// PBQP Graph class. + /// Instances of this class describe PBQP problems. + class Graph { + private: + + // ----- TYPEDEFS ----- + class NodeEntry; + class EdgeEntry; + + typedef std::list NodeList; + typedef std::list EdgeList; + + public: + + typedef NodeList::iterator NodeItr; + typedef NodeList::const_iterator ConstNodeItr; + + typedef EdgeList::iterator EdgeItr; + typedef EdgeList::const_iterator ConstEdgeItr; + + private: + + typedef std::list AdjEdgeList; + + public: + + typedef AdjEdgeList::iterator AdjEdgeItr; + + private: + + class NodeEntry { + private: + Vector costs; + AdjEdgeList adjEdges; + unsigned degree; + void *data; + public: + NodeEntry(const Vector &costs) : costs(costs), degree(0) {} + Vector& getCosts() { return costs; } + const Vector& getCosts() const { return costs; } + unsigned getDegree() const { return degree; } + AdjEdgeItr edgesBegin() { return adjEdges.begin(); } + AdjEdgeItr edgesEnd() { return adjEdges.end(); } + AdjEdgeItr addEdge(EdgeItr e) { + ++degree; + return adjEdges.insert(adjEdges.end(), e); + } + void removeEdge(AdjEdgeItr ae) { + --degree; + adjEdges.erase(ae); + } + void setData(void *data) { this->data = data; } + void* getData() { return data; } + }; + + class EdgeEntry { + private: + NodeItr node1, node2; + Matrix costs; + AdjEdgeItr node1AEItr, node2AEItr; + void *data; + public: + EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs) + : node1(node1), node2(node2), costs(costs) {} + NodeItr getNode1() const { return node1; } + NodeItr getNode2() const { return node2; } + Matrix& getCosts() { return costs; } + const Matrix& getCosts() const { return costs; } + void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } + AdjEdgeItr getNode1AEItr() { return node1AEItr; } + void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; } + AdjEdgeItr getNode2AEItr() { return node2AEItr; } + void setData(void *data) { this->data = data; } + void *getData() { return data; } + }; + + // ----- MEMBERS ----- + + NodeList nodes; + unsigned numNodes; + + EdgeList edges; + unsigned numEdges; + + // ----- INTERNAL METHODS ----- + + NodeEntry& getNode(NodeItr nItr) { return *nItr; } + const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; } + + EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; } + const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; } + + NodeItr addConstructedNode(const NodeEntry &n) { + ++numNodes; + return nodes.insert(nodes.end(), n); + } + + EdgeItr addConstructedEdge(const EdgeEntry &e) { + assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() && + "Attempt to add duplicate edge."); + ++numEdges; + EdgeItr edgeItr = edges.insert(edges.end(), e); + EdgeEntry &ne = getEdge(edgeItr); + NodeEntry &n1 = getNode(ne.getNode1()); + NodeEntry &n2 = getNode(ne.getNode2()); + // Sanity check on matrix dimensions: + assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && + (n2.getCosts().getLength() == ne.getCosts().getCols()) && + "Edge cost dimensions do not match node costs dimensions."); + ne.setNode1AEItr(n1.addEdge(edgeItr)); + ne.setNode2AEItr(n2.addEdge(edgeItr)); + return edgeItr; + } + + inline void copyFrom(const Graph &other); + public: + + /// \brief Construct an empty PBQP graph. + Graph() : numNodes(0), numEdges(0) {} + + /// \brief Copy construct this graph from "other". Note: Does not copy node + /// and edge data, only graph structure and costs. + /// @param other Source graph to copy from. + Graph(const Graph &other) : numNodes(0), numEdges(0) { + copyFrom(other); + } + + /// \brief Make this graph a copy of "other". Note: Does not copy node and + /// edge data, only graph structure and costs. + /// @param other The graph to copy from. + /// @return A reference to this graph. + /// + /// This will clear the current graph, erasing any nodes and edges added, + /// before copying from other. + Graph& operator=(const Graph &other) { + clear(); + copyFrom(other); + return *this; + } + + /// \brief Add a node with the given costs. + /// @param costs Cost vector for the new node. + /// @return Node iterator for the added node. + NodeItr addNode(const Vector &costs) { + return addConstructedNode(NodeEntry(costs)); + } + + /// \brief Add an edge between the given nodes with the given costs. + /// @param n1Itr First node. + /// @param n2Itr Second node. + /// @return Edge iterator for the added edge. + EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr, + const Matrix &costs) { + assert(getNodeCosts(n1Itr).getLength() == costs.getRows() && + getNodeCosts(n2Itr).getLength() == costs.getCols() && + "Matrix dimensions mismatch."); + return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs)); + } + + /// \brief Get the number of nodes in the graph. + /// @return Number of nodes in the graph. + unsigned getNumNodes() const { return numNodes; } + + /// \brief Get the number of edges in the graph. + /// @return Number of edges in the graph. + unsigned getNumEdges() const { return numEdges; } + + /// \brief Get a node's cost vector. + /// @param nItr Node iterator. + /// @return Node cost vector. + Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); } + + /// \brief Get a node's cost vector (const version). + /// @param nItr Node iterator. + /// @return Node cost vector. + const Vector& getNodeCosts(ConstNodeItr nItr) const { + return getNode(nItr).getCosts(); + } + + /// \brief Set a node's data pointer. + /// @param nItr Node iterator. + /// @param data Pointer to node data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); } + + /// \brief Get the node's data pointer. + /// @param nItr Node iterator. + /// @return Pointer to node data. + void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); } + + /// \brief Get an edge's cost matrix. + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); } + + /// \brief Get an edge's cost matrix (const version). + /// @param eItr Edge iterator. + /// @return Edge cost matrix. + const Matrix& getEdgeCosts(ConstEdgeItr eItr) const { + return getEdge(eItr).getCosts(); + } + + /// \brief Set an edge's data pointer. + /// @param eItr Edge iterator. + /// @param data Pointer to edge data. + /// + /// Typically used by a PBQP solver to attach data to aid in solution. + void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); } + + /// \brief Get an edge's data pointer. + /// @param eItr Edge iterator. + /// @return Pointer to edge data. + void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); } + + /// \brief Get a node's degree. + /// @param nItr Node iterator. + /// @return The degree of the node. + unsigned getNodeDegree(NodeItr nItr) const { + return getNode(nItr).getDegree(); + } + + /// \brief Begin iterator for node set. + NodeItr nodesBegin() { return nodes.begin(); } + + /// \brief Begin const iterator for node set. + ConstNodeItr nodesBegin() const { return nodes.begin(); } + + /// \brief End iterator for node set. + NodeItr nodesEnd() { return nodes.end(); } + + /// \brief End const iterator for node set. + ConstNodeItr nodesEnd() const { return nodes.end(); } + + /// \brief Begin iterator for edge set. + EdgeItr edgesBegin() { return edges.begin(); } + + /// \brief End iterator for edge set. + EdgeItr edgesEnd() { return edges.end(); } + + /// \brief Get begin iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesBegin(NodeItr nItr) { + return getNode(nItr).edgesBegin(); + } + + /// \brief Get end iterator for adjacent edge set. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges connected to the given node. + AdjEdgeItr adjEdgesEnd(NodeItr nItr) { + return getNode(nItr).edgesEnd(); + } + + /// \brief Get the first node connected to this edge. + /// @param eItr Edge iterator. + /// @return The first node connected to the given edge. + NodeItr getEdgeNode1(EdgeItr eItr) { + return getEdge(eItr).getNode1(); + } + + /// \brief Get the second node connected to this edge. + /// @param eItr Edge iterator. + /// @return The second node connected to the given edge. + NodeItr getEdgeNode2(EdgeItr eItr) { + return getEdge(eItr).getNode2(); + } + + /// \brief Get the "other" node connected to this edge. + /// @param eItr Edge iterator. + /// @param nItr Node iterator for the "given" node. + /// @return The iterator for the "other" node connected to this edge. + NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) { + EdgeEntry &e = getEdge(eItr); + if (e.getNode1() == nItr) { + return e.getNode2(); + } // else + return e.getNode1(); + } + + /// \brief Get the edge connecting two nodes. + /// @param n1Itr First node iterator. + /// @param n2Itr Second node iterator. + /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists, + /// otherwise returns edgesEnd(). + EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) { + for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr); + aeItr != aeEnd; ++aeItr) { + if ((getEdgeNode1(*aeItr) == n2Itr) || + (getEdgeNode2(*aeItr) == n2Itr)) { + return *aeItr; + } + } + return edges.end(); + } + + /// \brief Remove a node from the graph. + /// @param nItr Node iterator. + void removeNode(NodeItr nItr) { + NodeEntry &n = getNode(nItr); + for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) { + EdgeItr eItr = *itr; + ++itr; + removeEdge(eItr); + } + nodes.erase(nItr); + --numNodes; + } + + /// \brief Remove an edge from the graph. + /// @param eItr Edge iterator. + void removeEdge(EdgeItr eItr) { + EdgeEntry &e = getEdge(eItr); + NodeEntry &n1 = getNode(e.getNode1()); + NodeEntry &n2 = getNode(e.getNode2()); + n1.removeEdge(e.getNode1AEItr()); + n2.removeEdge(e.getNode2AEItr()); + edges.erase(eItr); + --numEdges; + } + + /// \brief Remove all nodes and edges from the graph. + void clear() { + nodes.clear(); + edges.clear(); + numNodes = numEdges = 0; + } + + /// \brief Print a representation of this graph in DOT format. + /// @param os Output stream to print on. + template + void printDot(OStream &os) { + + os << "graph {\n"; + + for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); + nodeItr != nodeEnd; ++nodeItr) { + + os << " node" << nodeItr << " [ label=\"" + << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n"; + } + + os << " edge [ len=" << getNumNodes() << " ]\n"; + + for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); + edgeItr != edgeEnd; ++edgeItr) { + + os << " node" << getEdgeNode1(edgeItr) + << " -- node" << getEdgeNode2(edgeItr) + << " [ label=\""; + + const Matrix &edgeCosts = getEdgeCosts(edgeItr); + + for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { + os << edgeCosts.getRowAsVector(i) << "\\n"; + } + os << "\" ]\n"; + } + os << "}\n"; + } + + }; + + class NodeItrComparator { + public: + bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const { + return &*n1 < &*n2; + } + + bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const { + return &*n1 < &*n2; + } + }; + + class EdgeItrCompartor { + public: + bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const { + return &*e1 < &*e2; + } + + bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const { + return &*e1 < &*e2; + } + }; + + void Graph::copyFrom(const Graph &other) { + std::map nodeMap; + + for (Graph::ConstNodeItr nItr = other.nodesBegin(), + nEnd = other.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); + } + + } + +} + +#endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/final/include/llvm/CodeGen/PBQP/HeuristicBase.h b/final/include/llvm/CodeGen/PBQP/HeuristicBase.h new file mode 100644 index 00000000000..791c227f0d0 --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/HeuristicBase.h @@ -0,0 +1,246 @@ +//===-- HeuristcBase.h --- Heuristic base class for PBQP --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICBASE_H +#define LLVM_CODEGEN_PBQP_HEURISTICBASE_H + +#include "HeuristicSolver.h" + +namespace PBQP { + + /// \brief Abstract base class for heuristic implementations. + /// + /// This class provides a handy base for heuristic implementations with common + /// solver behaviour implemented for a number of methods. + /// + /// To implement your own heuristic using this class as a base you'll have to + /// implement, as a minimum, the following methods: + ///
    + ///
  • void addToHeuristicList(Graph::NodeItr) : Add a node to the + /// heuristic reduction list. + ///
  • void heuristicReduce() : Perform a single heuristic reduction. + ///
  • void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) + /// change to the cost matrix on the given edge (by R2). + ///
  • void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new + /// costs on the given edge. + ///
  • void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new + /// edge into the PBQP graph (by R2). + ///
  • void handleRemoveEdge(Graph::EdgeItr, Graph::NodeItr) : Handle the + /// disconnection of the given edge from the given node. + ///
  • A constructor for your derived class : to pass back a reference to + /// the solver which is using this heuristic. + ///
+ /// + /// These methods are implemented in this class for documentation purposes, + /// but will assert if called. + /// + /// Note that this class uses the curiously recursive template idiom to + /// forward calls to the derived class. These methods need not be made + /// virtual, and indeed probably shouldn't for performance reasons. + /// + /// You'll also need to provide NodeData and EdgeData structs in your class. + /// These can be used to attach data relevant to your heuristic to each + /// node/edge in the PBQP graph. + + template + class HeuristicBase { + private: + + typedef std::list OptimalList; + + HeuristicSolverImpl &s; + Graph &g; + OptimalList optimalList; + + // Return a reference to the derived heuristic. + HImpl& impl() { return static_cast(*this); } + + // Add the given node to the optimal reductions list. Keep an iterator to + // its location for fast removal. + void addToOptimalReductionList(Graph::NodeItr nItr) { + optimalList.insert(optimalList.end(), nItr); + } + + public: + + /// \brief Construct an instance with a reference to the given solver. + /// @param solver The solver which is using this heuristic instance. + HeuristicBase(HeuristicSolverImpl &solver) + : s(solver), g(s.getGraph()) { } + + /// \brief Get the solver which is using this heuristic instance. + /// @return The solver which is using this heuristic instance. + /// + /// You can use this method to get access to the solver in your derived + /// heuristic implementation. + HeuristicSolverImpl& getSolver() { return s; } + + /// \brief Get the graph representing the problem to be solved. + /// @return The graph representing the problem to be solved. + Graph& getGraph() { return g; } + + /// \brief Tell the solver to simplify the graph before the reduction phase. + /// @return Whether or not the solver should run a simplification phase + /// prior to the main setup and reduction. + /// + /// HeuristicBase returns true from this method as it's a sensible default, + /// however you can over-ride it in your derived class if you want different + /// behaviour. + bool solverRunSimplify() const { return true; } + + /// \brief Decide whether a node should be optimally or heuristically + /// reduced. + /// @return Whether or not the given node should be listed for optimal + /// reduction (via R0, R1 or R2). + /// + /// HeuristicBase returns true for any node with degree less than 3. This is + /// sane and sensible for many situations, but not all. You can over-ride + /// this method in your derived class if you want a different selection + /// criteria. Note however that your criteria for selecting optimal nodes + /// should be at least as strong as this. I.e. Nodes of degree 3 or + /// higher should not be selected under any circumstances. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (g.getNodeDegree(nItr) < 3) + return true; + // else + return false; + } + + /// \brief Add the given node to the list of nodes to be optimally reduced. + /// @return nItr Node iterator to be added. + /// + /// You probably don't want to over-ride this, except perhaps to record + /// statistics before calling this implementation. HeuristicBase relies on + /// its behaviour. + void addToOptimalReduceList(Graph::NodeItr nItr) { + optimalList.push_back(nItr); + } + + /// \brief Initialise the heuristic. + /// + /// HeuristicBase iterates over all nodes in the problem and adds them to + /// the appropriate list using addToOptimalReduceList or + /// addToHeuristicReduceList based on the result of shouldOptimallyReduce. + /// + /// This behaviour should be fine for most situations. + void setup() { + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + if (impl().shouldOptimallyReduce(nItr)) { + addToOptimalReduceList(nItr); + } else { + impl().addToHeuristicReduceList(nItr); + } + } + } + + /// \brief Optimally reduce one of the nodes in the optimal reduce list. + /// @return True if a reduction takes place, false if the optimal reduce + /// list is empty. + /// + /// Selects a node from the optimal reduce list and removes it, applying + /// R0, R1 or R2 as appropriate based on the selected node's degree. + bool optimalReduce() { + if (optimalList.empty()) + return false; + + Graph::NodeItr nItr = optimalList.front(); + optimalList.pop_front(); + + switch (s.getSolverDegree(nItr)) { + case 0: s.applyR0(nItr); break; + case 1: s.applyR1(nItr); break; + case 2: s.applyR2(nItr); break; + default: assert(false && + "Optimal reductions of degree > 2 nodes is invalid."); + } + + return true; + } + + /// \brief Perform the PBQP reduction process. + /// + /// Reduces the problem to the empty graph by repeated application of the + /// reduction rules R0, R1, R2 and RN. + /// R0, R1 or R2 are always applied if possible before RN is used. + void reduce() { + bool finished = false; + + while (!finished) { + if (!optimalReduce()) { + if (impl().heuristicReduce()) { + getSolver().recordRN(); + } else { + finished = true; + } + } + } + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicList(Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + void heuristicReduce() { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCostts(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + void handleAddEdge(Graph::EdgeItr eItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Edges are frequently removed due to the removal of a node. This + /// method allows for the effect to be computed only for the remaining + /// node in the graph. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + assert(false && "Must be implemented in derived class."); + } + + /// \brief Clean up any structures used by HeuristicBase. + /// + /// At present this just performs a sanity check: that the optimal reduce + /// list is empty now that reduction has completed. + /// + /// If your derived class has more complex structures which need tearing + /// down you should over-ride this method but include a call back to this + /// implementation. + void cleanup() { + assert(optimalList.empty() && "Nodes left over in optimal reduce list?"); + } + + }; + +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICBASE_H diff --git a/final/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/final/include/llvm/CodeGen/PBQP/HeuristicSolver.h new file mode 100644 index 00000000000..35514f96747 --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/HeuristicSolver.h @@ -0,0 +1,616 @@ +//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Heuristic PBQP solver. This solver is able to perform optimal reductions for +// nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is +// used to select a node for reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H +#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H + +#include "Graph.h" +#include "Solution.h" +#include +#include + +namespace PBQP { + + /// \brief Heuristic PBQP solver implementation. + /// + /// This class should usually be created (and destroyed) indirectly via a call + /// to HeuristicSolver::solve(Graph&). + /// See the comments for HeuristicSolver. + /// + /// HeuristicSolverImpl provides the R0, R1 and R2 reduction rules, + /// backpropagation phase, and maintains the internal copy of the graph on + /// which the reduction is carried out (the original being kept to facilitate + /// backpropagation). + template + class HeuristicSolverImpl { + private: + + typedef typename HImpl::NodeData HeuristicNodeData; + typedef typename HImpl::EdgeData HeuristicEdgeData; + + typedef std::list SolverEdges; + + public: + + /// \brief Iterator type for edges in the solver graph. + typedef SolverEdges::iterator SolverEdgeItr; + + private: + + class NodeData { + public: + NodeData() : solverDegree(0) {} + + HeuristicNodeData& getHeuristicData() { return hData; } + + SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) { + ++solverDegree; + return solverEdges.insert(solverEdges.end(), eItr); + } + + void removeSolverEdge(SolverEdgeItr seItr) { + --solverDegree; + solverEdges.erase(seItr); + } + + SolverEdgeItr solverEdgesBegin() { return solverEdges.begin(); } + SolverEdgeItr solverEdgesEnd() { return solverEdges.end(); } + unsigned getSolverDegree() const { return solverDegree; } + void clearSolverEdges() { + solverDegree = 0; + solverEdges.clear(); + } + + private: + HeuristicNodeData hData; + unsigned solverDegree; + SolverEdges solverEdges; + }; + + class EdgeData { + public: + HeuristicEdgeData& getHeuristicData() { return hData; } + + void setN1SolverEdgeItr(SolverEdgeItr n1SolverEdgeItr) { + this->n1SolverEdgeItr = n1SolverEdgeItr; + } + + SolverEdgeItr getN1SolverEdgeItr() { return n1SolverEdgeItr; } + + void setN2SolverEdgeItr(SolverEdgeItr n2SolverEdgeItr){ + this->n2SolverEdgeItr = n2SolverEdgeItr; + } + + SolverEdgeItr getN2SolverEdgeItr() { return n2SolverEdgeItr; } + + private: + + HeuristicEdgeData hData; + SolverEdgeItr n1SolverEdgeItr, n2SolverEdgeItr; + }; + + Graph &g; + HImpl h; + Solution s; + std::vector stack; + + typedef std::list NodeDataList; + NodeDataList nodeDataList; + + typedef std::list EdgeDataList; + EdgeDataList edgeDataList; + + public: + + /// \brief Construct a heuristic solver implementation to solve the given + /// graph. + /// @param g The graph representing the problem instance to be solved. + HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} + + /// \brief Get the graph being solved by this solver. + /// @return The graph representing the problem instance being solved by this + /// solver. + Graph& getGraph() { return g; } + + /// \brief Get the heuristic data attached to the given node. + /// @param nItr Node iterator. + /// @return The heuristic data attached to the given node. + HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getHeuristicData(); + } + + /// \brief Get the heuristic data attached to the given edge. + /// @param eItr Edge iterator. + /// @return The heuristic data attached to the given node. + HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolverEdgeData(eItr).getHeuristicData(); + } + + /// \brief Begin iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return Begin iterator for the set of edges adjacent to the given node + /// in the solver graph. + SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesBegin(); + } + + /// \brief End iterator for the set of edges adjacent to the given node in + /// the solver graph. + /// @param nItr Node iterator. + /// @return End iterator for the set of edges adjacent to the given node in + /// the solver graph. + SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).solverEdgesEnd(); + } + + /// \brief Remove a node from the solver graph. + /// @param eItr Edge iterator for edge to be removed. + /// + /// Does not notify the heuristic of the removal. That should be + /// done manually if necessary. + void removeSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + + n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); + n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); + } + + /// \brief Compute a solution to the PBQP problem instance with which this + /// heuristic solver was constructed. + /// @return A solution to the PBQP problem. + /// + /// Performs the full PBQP heuristic solver algorithm, including setup, + /// calls to the heuristic (which will call back to the reduction rules in + /// this class), and cleanup. + Solution computeSolution() { + setup(); + h.setup(); + h.reduce(); + backpropagate(); + h.cleanup(); + cleanup(); + return s; + } + + /// \brief Add to the end of the stack. + /// @param nItr Node iterator to add to the reduction stack. + void pushToStack(Graph::NodeItr nItr) { + getSolverNodeData(nItr).clearSolverEdges(); + stack.push_back(nItr); + } + + /// \brief Returns the solver degree of the given node. + /// @param nItr Node iterator for which degree is requested. + /// @return Node degree in the solver graph (not the original graph). + unsigned getSolverDegree(Graph::NodeItr nItr) { + return getSolverNodeData(nItr).getSolverDegree(); + } + + /// \brief Set the solution of the given node. + /// @param nItr Node iterator to set solution for. + /// @param selection Selection for node. + void setSolution(const Graph::NodeItr &nItr, unsigned selection) { + s.setSelection(nItr, selection); + + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + Graph::EdgeItr eItr(*aeItr); + Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr)); + getSolverNodeData(anItr).addSolverEdge(eItr); + } + } + + /// \brief Apply rule R0. + /// @param nItr Node iterator for node to apply R0 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR0(Graph::NodeItr nItr) { + assert(getSolverNodeData(nItr).getSolverDegree() == 0 && + "R0 applied to node with degree != 0."); + + // Nothing to do. Just push the node onto the reduction stack. + pushToStack(nItr); + + s.recordR0(); + } + + /// \brief Apply rule R1. + /// @param xnItr Node iterator for node to apply R1 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR1(Graph::NodeItr xnItr) { + NodeData &nd = getSolverNodeData(xnItr); + assert(nd.getSolverDegree() == 1 && + "R1 applied to node with degree != 1."); + + Graph::EdgeItr eItr = *nd.solverEdgesBegin(); + + const Matrix &eCosts = g.getEdgeCosts(eItr); + const Vector &xCosts = g.getNodeCosts(xnItr); + + // Duplicate a little to avoid transposing matrices. + if (xnItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr ynItr = g.getEdgeNode2(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned j = 0; j < yCosts.getLength(); ++j) { + PBQPNum min = eCosts[0][j] + xCosts[0]; + for (unsigned i = 1; i < xCosts.getLength(); ++i) { + PBQPNum c = eCosts[i][j] + xCosts[i]; + if (c < min) + min = c; + } + yCosts[j] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } else { + Graph::NodeItr ynItr = g.getEdgeNode1(eItr); + Vector &yCosts = g.getNodeCosts(ynItr); + for (unsigned i = 0; i < yCosts.getLength(); ++i) { + PBQPNum min = eCosts[i][0] + xCosts[0]; + for (unsigned j = 1; j < xCosts.getLength(); ++j) { + PBQPNum c = eCosts[i][j] + xCosts[j]; + if (c < min) + min = c; + } + yCosts[i] += min; + } + h.handleRemoveEdge(eItr, ynItr); + } + removeSolverEdge(eItr); + assert(nd.getSolverDegree() == 0 && + "Degree 1 with edge removed should be 0."); + pushToStack(xnItr); + s.recordR1(); + } + + /// \brief Apply rule R2. + /// @param xnItr Node iterator for node to apply R2 to. + /// + /// Node will be automatically pushed to the solver stack. + void applyR2(Graph::NodeItr xnItr) { + assert(getSolverNodeData(xnItr).getSolverDegree() == 2 && + "R2 applied to node with degree != 2."); + + NodeData &nd = getSolverNodeData(xnItr); + const Vector &xCosts = g.getNodeCosts(xnItr); + + SolverEdgeItr aeItr = nd.solverEdgesBegin(); + Graph::EdgeItr yxeItr = *aeItr, + zxeItr = *(++aeItr); + + Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr), + znItr = g.getEdgeOtherNode(zxeItr, xnItr); + + bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr), + flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr); + + const Matrix *yxeCosts = flipEdge1 ? + new Matrix(g.getEdgeCosts(yxeItr).transpose()) : + &g.getEdgeCosts(yxeItr); + + const Matrix *zxeCosts = flipEdge2 ? + new Matrix(g.getEdgeCosts(zxeItr).transpose()) : + &g.getEdgeCosts(zxeItr); + + unsigned xLen = xCosts.getLength(), + yLen = yxeCosts->getRows(), + zLen = zxeCosts->getRows(); + + Matrix delta(yLen, zLen); + + for (unsigned i = 0; i < yLen; ++i) { + for (unsigned j = 0; j < zLen; ++j) { + PBQPNum min = (*yxeCosts)[i][0] + (*zxeCosts)[j][0] + xCosts[0]; + for (unsigned k = 1; k < xLen; ++k) { + PBQPNum c = (*yxeCosts)[i][k] + (*zxeCosts)[j][k] + xCosts[k]; + if (c < min) { + min = c; + } + } + delta[i][j] = min; + } + } + + if (flipEdge1) + delete yxeCosts; + + if (flipEdge2) + delete zxeCosts; + + Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr); + bool addedEdge = false; + + if (yzeItr == g.edgesEnd()) { + yzeItr = g.addEdge(ynItr, znItr, delta); + addedEdge = true; + } else { + Matrix &yzeCosts = g.getEdgeCosts(yzeItr); + h.preUpdateEdgeCosts(yzeItr); + if (ynItr == g.getEdgeNode1(yzeItr)) { + yzeCosts += delta; + } else { + yzeCosts += delta.transpose(); + } + } + + bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr); + + if (!addedEdge) { + // If we modified the edge costs let the heuristic know. + h.postUpdateEdgeCosts(yzeItr); + } + + if (nullCostEdge) { + // If this edge ended up null remove it. + if (!addedEdge) { + // We didn't just add it, so we need to notify the heuristic + // and remove it from the solver. + h.handleRemoveEdge(yzeItr, ynItr); + h.handleRemoveEdge(yzeItr, znItr); + removeSolverEdge(yzeItr); + } + g.removeEdge(yzeItr); + } else if (addedEdge) { + // If the edge was added, and non-null, finish setting it up, add it to + // the solver & notify heuristic. + edgeDataList.push_back(EdgeData()); + g.setEdgeData(yzeItr, &edgeDataList.back()); + addSolverEdge(yzeItr); + h.handleAddEdge(yzeItr); + } + + h.handleRemoveEdge(yxeItr, ynItr); + removeSolverEdge(yxeItr); + h.handleRemoveEdge(zxeItr, znItr); + removeSolverEdge(zxeItr); + + pushToStack(xnItr); + s.recordR2(); + } + + /// \brief Record an application of the RN rule. + /// + /// For use by the HeuristicBase. + void recordRN() { s.recordRN(); } + + private: + + NodeData& getSolverNodeData(Graph::NodeItr nItr) { + return *static_cast(g.getNodeData(nItr)); + } + + EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) { + return *static_cast(g.getEdgeData(eItr)); + } + + void addSolverEdge(Graph::EdgeItr eItr) { + EdgeData &eData = getSolverEdgeData(eItr); + NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)), + &n2Data = getSolverNodeData(g.getEdgeNode2(eItr)); + + eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr)); + eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr)); + } + + void setup() { + if (h.solverRunSimplify()) { + simplify(); + } + + // Create node data objects. + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + nodeDataList.push_back(NodeData()); + g.setNodeData(nItr, &nodeDataList.back()); + } + + // Create edge data objects. + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgeDataList.push_back(EdgeData()); + g.setEdgeData(eItr, &edgeDataList.back()); + addSolverEdge(eItr); + } + } + + void simplify() { + disconnectTrivialNodes(); + eliminateIndependentEdges(); + } + + // Eliminate trivial nodes. + void disconnectTrivialNodes() { + unsigned numDisconnected = 0; + + for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); + nItr != nEnd; ++nItr) { + + if (g.getNodeCosts(nItr).getLength() == 1) { + + std::vector edgesToRemove; + + for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr), + aeEnd = g.adjEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + + Graph::EdgeItr eItr = *aeItr; + + if (g.getEdgeNode1(eItr) == nItr) { + Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getRowAsVector(0); + } + else { + Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr); + g.getNodeCosts(otherNodeItr) += + g.getEdgeCosts(eItr).getColAsVector(0); + } + + edgesToRemove.push_back(eItr); + } + + if (!edgesToRemove.empty()) + ++numDisconnected; + + while (!edgesToRemove.empty()) { + g.removeEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + } + } + + void eliminateIndependentEdges() { + std::vector edgesToProcess; + unsigned numEliminated = 0; + + for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); + eItr != eEnd; ++eItr) { + edgesToProcess.push_back(eItr); + } + + while (!edgesToProcess.empty()) { + if (tryToEliminateEdge(edgesToProcess.back())) + ++numEliminated; + edgesToProcess.pop_back(); + } + } + + bool tryToEliminateEdge(Graph::EdgeItr eItr) { + if (tryNormaliseEdgeMatrix(eItr)) { + g.removeEdge(eItr); + return true; + } + return false; + } + + bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + + const PBQPNum infinity = std::numeric_limits::infinity(); + + Matrix &edgeCosts = g.getEdgeCosts(eItr); + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), + &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + PBQPNum rowMin = infinity; + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + if (vCosts[c] != infinity && edgeCosts[r][c] < rowMin) + rowMin = edgeCosts[r][c]; + } + + uCosts[r] += rowMin; + + if (rowMin != infinity) { + edgeCosts.subFromRow(r, rowMin); + } + else { + edgeCosts.setRow(r, 0); + } + } + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + PBQPNum colMin = infinity; + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + if (uCosts[r] != infinity && edgeCosts[r][c] < colMin) + colMin = edgeCosts[r][c]; + } + + vCosts[c] += colMin; + + if (colMin != infinity) { + edgeCosts.subFromCol(c, colMin); + } + else { + edgeCosts.setCol(c, 0); + } + } + + return edgeCosts.isZero(); + } + + void backpropagate() { + while (!stack.empty()) { + computeSolution(stack.back()); + stack.pop_back(); + } + } + + void computeSolution(Graph::NodeItr nItr) { + + NodeData &nodeData = getSolverNodeData(nItr); + + Vector v(g.getNodeCosts(nItr)); + + // Solve based on existing solved edges. + for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), + solvedEdgeEnd = nodeData.solverEdgesEnd(); + solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { + + Graph::EdgeItr eItr(*solvedEdgeItr); + Matrix &edgeCosts = g.getEdgeCosts(eItr); + + if (nItr == g.getEdgeNode1(eItr)) { + Graph::NodeItr adjNode(g.getEdgeNode2(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getColAsVector(adjSolution); + } + else { + Graph::NodeItr adjNode(g.getEdgeNode1(eItr)); + unsigned adjSolution = s.getSelection(adjNode); + v += edgeCosts.getRowAsVector(adjSolution); + } + + } + + setSolution(nItr, v.minIndex()); + } + + void cleanup() { + h.cleanup(); + nodeDataList.clear(); + edgeDataList.clear(); + } + }; + + /// \brief PBQP heuristic solver class. + /// + /// Given a PBQP Graph g representing a PBQP problem, you can find a solution + /// by calling + /// Solution s = HeuristicSolver::solve(g); + /// + /// The choice of heuristic for the H parameter will affect both the solver + /// speed and solution quality. The heuristic should be chosen based on the + /// nature of the problem being solved. + /// Currently the only solver included with LLVM is the Briggs heuristic for + /// register allocation. + template + class HeuristicSolver { + public: + static Solution solve(Graph &g) { + HeuristicSolverImpl hs(g); + return hs.computeSolution(); + } + }; + +} + +#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H diff --git a/final/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/final/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h new file mode 100644 index 00000000000..47a287ccf2f --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h @@ -0,0 +1,464 @@ +//===-- Briggs.h --- Briggs Heuristic for PBQP ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the Briggs test for "allocability" of nodes in a +// PBQP graph representing a register allocation problem. Nodes which can be +// proven allocable (by a safe and relatively accurate test) are removed from +// the PBQP graph first. If no provably allocable node is present in the graph +// then the node with the minimal spill-cost to degree ratio is removed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H +#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H + +#include "../HeuristicSolver.h" +#include "../HeuristicBase.h" + +#include +#include + +namespace PBQP { + namespace Heuristics { + + /// \brief PBQP Heuristic which applies an allocability test based on + /// Briggs. + /// + /// This heuristic assumes that the elements of cost vectors in the PBQP + /// problem represent storage options, with the first being the spill + /// option and subsequent elements representing legal registers for the + /// corresponding node. Edge cost matrices are likewise assumed to represent + /// register constraints. + /// If one or more nodes can be proven allocable by this heuristic (by + /// inspection of their constraint matrices) then the allocable node of + /// highest degree is selected for the next reduction and pushed to the + /// solver stack. If no nodes can be proven allocable then the node with + /// the lowest estimated spill cost is selected and push to the solver stack + /// instead. + /// + /// This implementation is built on top of HeuristicBase. + class Briggs : public HeuristicBase { + private: + + class LinkDegreeComparator { + public: + LinkDegreeComparator(HeuristicSolverImpl &s) : s(&s) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr)) + return true; + return false; + } + private: + HeuristicSolverImpl *s; + }; + + class SpillCostComparator { + public: + SpillCostComparator(HeuristicSolverImpl &s) + : s(&s), g(&s.getGraph()) {} + bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const { + const PBQP::Vector &cv1 = g->getNodeCosts(n1Itr); + const PBQP::Vector &cv2 = g->getNodeCosts(n2Itr); + + PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr); + PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr); + + if (cost1 < cost2) + return true; + return false; + } + + private: + HeuristicSolverImpl *s; + Graph *g; + }; + + typedef std::list RNAllocableList; + typedef RNAllocableList::iterator RNAllocableListItr; + + typedef std::list RNUnallocableList; + typedef RNUnallocableList::iterator RNUnallocableListItr; + + public: + + struct NodeData { + typedef std::vector UnsafeDegreesArray; + bool isHeuristic, isAllocable, isInitialized; + unsigned numDenied, numSafe; + UnsafeDegreesArray unsafeDegrees; + RNAllocableListItr rnaItr; + RNUnallocableListItr rnuItr; + + NodeData() + : isHeuristic(false), isAllocable(false), isInitialized(false), + numDenied(0), numSafe(0) { } + }; + + struct EdgeData { + typedef std::vector UnsafeArray; + unsigned worst, reverseWorst; + UnsafeArray unsafe, reverseUnsafe; + bool isUpToDate; + + EdgeData() : worst(0), reverseWorst(0), isUpToDate(false) {} + }; + + /// \brief Construct an instance of the Briggs heuristic. + /// @param solver A reference to the solver which is using this heuristic. + Briggs(HeuristicSolverImpl &solver) : + HeuristicBase(solver) {} + + /// \brief Determine whether a node should be reduced using optimal + /// reduction. + /// @param nItr Node iterator to be considered. + /// @return True if the given node should be optimally reduced, false + /// otherwise. + /// + /// Selects nodes of degree 0, 1 or 2 for optimal reduction, with one + /// exception. Nodes whose spill cost (element 0 of their cost vector) is + /// infinite are checked for allocability first. Allocable nodes may be + /// optimally reduced, but nodes whose allocability cannot be proven are + /// selected for heuristic reduction instead. + bool shouldOptimallyReduce(Graph::NodeItr nItr) { + if (getSolver().getSolverDegree(nItr) < 3) { + return true; + } + // else + return false; + } + + /// \brief Add a node to the heuristic reduce list. + /// @param nItr Node iterator to add to the heuristic reduce list. + void addToHeuristicReduceList(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + initializeNode(nItr); + nd.isHeuristic = true; + if (nd.isAllocable) { + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } else { + nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr); + } + } + + /// \brief Heuristically reduce one of the nodes in the heuristic + /// reduce list. + /// @return True if a reduction takes place, false if the heuristic reduce + /// list is empty. + /// + /// If the list of allocable nodes is non-empty a node is selected + /// from it and pushed to the stack. Otherwise if the non-allocable list + /// is non-empty a node is selected from it and pushed to the stack. + /// If both lists are empty the method simply returns false with no action + /// taken. + bool heuristicReduce() { + if (!rnAllocableList.empty()) { + RNAllocableListItr rnaItr = + min_element(rnAllocableList.begin(), rnAllocableList.end(), + LinkDegreeComparator(getSolver())); + Graph::NodeItr nItr = *rnaItr; + rnAllocableList.erase(rnaItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; + } else if (!rnUnallocableList.empty()) { + RNUnallocableListItr rnuItr = + min_element(rnUnallocableList.begin(), rnUnallocableList.end(), + SpillCostComparator(getSolver())); + Graph::NodeItr nItr = *rnuItr; + rnUnallocableList.erase(rnuItr); + handleRemoveNode(nItr); + getSolver().pushToStack(nItr); + return true; + } + // else + return false; + } + + /// \brief Prepare a change in the costs on the given edge. + /// @param eItr Edge iterator. + void preUpdateEdgeCosts(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + if (n1.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr)); + if (n2.isHeuristic) + subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr)); + + EdgeData &ed = getHeuristicEdgeData(eItr); + ed.isUpToDate = false; + } + + /// \brief Handle the change in the costs on the given edge. + /// @param eItr Edge iterator. + void postUpdateEdgeCosts(Graph::EdgeItr eItr) { + // This is effectively the same as adding a new edge now, since + // we've factored out the costs of the old one. + handleAddEdge(eItr); + } + + /// \brief Handle the addition of a new edge into the PBQP graph. + /// @param eItr Edge iterator for the added edge. + /// + /// Updates allocability of any nodes connected by this edge which are + /// being managed by the heuristic. If allocability changes they are + /// moved to the appropriate list. + void handleAddEdge(Graph::EdgeItr eItr) { + Graph &g = getGraph(); + Graph::NodeItr n1Itr = g.getEdgeNode1(eItr), + n2Itr = g.getEdgeNode2(eItr); + NodeData &n1 = getHeuristicNodeData(n1Itr), + &n2 = getHeuristicNodeData(n2Itr); + + // If neither node is managed by the heuristic there's nothing to be + // done. + if (!n1.isHeuristic && !n2.isHeuristic) + return; + + // Ok - we need to update at least one node. + computeEdgeContributions(eItr); + + // Update node 1 if it's managed by the heuristic. + if (n1.isHeuristic) { + bool n1WasAllocable = n1.isAllocable; + addEdgeContributions(eItr, n1Itr); + updateAllocability(n1Itr); + if (n1WasAllocable && !n1.isAllocable) { + rnAllocableList.erase(n1.rnaItr); + n1.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n1Itr); + } + } + + // Likewise for node 2. + if (n2.isHeuristic) { + bool n2WasAllocable = n2.isAllocable; + addEdgeContributions(eItr, n2Itr); + updateAllocability(n2Itr); + if (n2WasAllocable && !n2.isAllocable) { + rnAllocableList.erase(n2.rnaItr); + n2.rnuItr = + rnUnallocableList.insert(rnUnallocableList.end(), n2Itr); + } + } + } + + /// \brief Handle disconnection of an edge from a node. + /// @param eItr Edge iterator for edge being disconnected. + /// @param nItr Node iterator for the node being disconnected from. + /// + /// Updates allocability of the given node and, if appropriate, moves the + /// node to a new list. + void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + + // If the node is not managed by the heuristic there's nothing to be + // done. + if (!nd.isHeuristic) + return; + + EdgeData &ed = getHeuristicEdgeData(eItr); + (void)ed; + assert(ed.isUpToDate && "Edge data is not up to date."); + + // Update node. + bool ndWasAllocable = nd.isAllocable; + subtractEdgeContributions(eItr, nItr); + updateAllocability(nItr); + + // If the node has gone optimal... + if (shouldOptimallyReduce(nItr)) { + nd.isHeuristic = false; + addToOptimalReduceList(nItr); + if (ndWasAllocable) { + rnAllocableList.erase(nd.rnaItr); + } else { + rnUnallocableList.erase(nd.rnuItr); + } + } else { + // Node didn't go optimal, but we might have to move it + // from "unallocable" to "allocable". + if (!ndWasAllocable && nd.isAllocable) { + rnUnallocableList.erase(nd.rnuItr); + nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr); + } + } + } + + private: + + NodeData& getHeuristicNodeData(Graph::NodeItr nItr) { + return getSolver().getHeuristicNodeData(nItr); + } + + EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) { + return getSolver().getHeuristicEdgeData(eItr); + } + + // Work out what this edge will contribute to the allocability of the + // nodes connected to it. + void computeEdgeContributions(Graph::EdgeItr eItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + if (ed.isUpToDate) + return; // Edge data is already up to date. + + Matrix &eCosts = getGraph().getEdgeCosts(eItr); + + unsigned numRegs = eCosts.getRows() - 1, + numReverseRegs = eCosts.getCols() - 1; + + std::vector rowInfCounts(numRegs, 0), + colInfCounts(numReverseRegs, 0); + + ed.worst = 0; + ed.reverseWorst = 0; + ed.unsafe.clear(); + ed.unsafe.resize(numRegs, 0); + ed.reverseUnsafe.clear(); + ed.reverseUnsafe.resize(numReverseRegs, 0); + + for (unsigned i = 0; i < numRegs; ++i) { + for (unsigned j = 0; j < numReverseRegs; ++j) { + if (eCosts[i + 1][j + 1] == + std::numeric_limits::infinity()) { + ed.unsafe[i] = 1; + ed.reverseUnsafe[j] = 1; + ++rowInfCounts[i]; + ++colInfCounts[j]; + + if (colInfCounts[j] > ed.worst) { + ed.worst = colInfCounts[j]; + } + + if (rowInfCounts[i] > ed.reverseWorst) { + ed.reverseWorst = rowInfCounts[i]; + } + } + } + } + + ed.isUpToDate = true; + } + + // Add the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r]==0) { + --nd.numSafe; + } + ++nd.unsafeDegrees[r]; + } + } + } + + // Subtract the contributions of the given edge to the given node's + // numDenied and safe members. No action is taken other than to update + // these member values. Once updated these numbers can be used by clients + // to update the node's allocability. + void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) { + EdgeData &ed = getHeuristicEdgeData(eItr); + + assert(ed.isUpToDate && "Using out-of-date edge numbers."); + + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr); + EdgeData::UnsafeArray &unsafe = + nIsNode1 ? ed.unsafe : ed.reverseUnsafe; + nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; + + for (unsigned r = 0; r < numRegs; ++r) { + if (unsafe[r]) { + if (nd.unsafeDegrees[r] == 1) { + ++nd.numSafe; + } + --nd.unsafeDegrees[r]; + } + } + } + + void updateAllocability(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; + } + + void initializeNode(Graph::NodeItr nItr) { + NodeData &nd = getHeuristicNodeData(nItr); + + if (nd.isInitialized) + return; // Node data is already up to date. + + unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1; + + nd.numDenied = 0; + nd.numSafe = numRegs; + nd.unsafeDegrees.resize(numRegs, 0); + + typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; + + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr), + aeEnd = getSolver().solverEdgesEnd(nItr); + aeItr != aeEnd; ++aeItr) { + + Graph::EdgeItr eItr = *aeItr; + computeEdgeContributions(eItr); + addEdgeContributions(eItr, nItr); + } + + updateAllocability(nItr); + nd.isInitialized = true; + } + + void handleRemoveNode(Graph::NodeItr xnItr) { + typedef HeuristicSolverImpl::SolverEdgeItr SolverEdgeItr; + std::vector edgesToRemove; + for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr), + aeEnd = getSolver().solverEdgesEnd(xnItr); + aeItr != aeEnd; ++aeItr) { + Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr); + handleRemoveEdge(*aeItr, ynItr); + edgesToRemove.push_back(*aeItr); + } + while (!edgesToRemove.empty()) { + getSolver().removeSolverEdge(edgesToRemove.back()); + edgesToRemove.pop_back(); + } + } + + RNAllocableList rnAllocableList; + RNUnallocableList rnUnallocableList; + }; + + } +} + + +#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H diff --git a/final/include/llvm/CodeGen/PBQP/Math.h b/final/include/llvm/CodeGen/PBQP/Math.h new file mode 100644 index 00000000000..e7598bf3e3f --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/Math.h @@ -0,0 +1,288 @@ +//===------ Math.h - PBQP Vector and Matrix classes -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_MATH_H +#define LLVM_CODEGEN_PBQP_MATH_H + +#include +#include +#include + +namespace PBQP { + +typedef float PBQPNum; + +/// \brief PBQP Vector class. +class Vector { + public: + + /// \brief Construct a PBQP vector of the given size. + explicit Vector(unsigned length) : + length(length), data(new PBQPNum[length]) { + } + + /// \brief Construct a PBQP vector with initializer. + Vector(unsigned length, PBQPNum initVal) : + length(length), data(new PBQPNum[length]) { + std::fill(data, data + length, initVal); + } + + /// \brief Copy construct a PBQP vector. + Vector(const Vector &v) : + length(v.length), data(new PBQPNum[length]) { + std::copy(v.data, v.data + length, data); + } + + /// \brief Destroy this vector, return its memory. + ~Vector() { delete[] data; } + + /// \brief Assignment operator. + Vector& operator=(const Vector &v) { + delete[] data; + length = v.length; + data = new PBQPNum[length]; + std::copy(v.data, v.data + length, data); + return *this; + } + + /// \brief Return the length of the vector + unsigned getLength() const { + return length; + } + + /// \brief Element access. + PBQPNum& operator[](unsigned index) { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Const element access. + const PBQPNum& operator[](unsigned index) const { + assert(index < length && "Vector element access out of bounds."); + return data[index]; + } + + /// \brief Add another vector to this one. + Vector& operator+=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::plus()); + return *this; + } + + /// \brief Subtract another vector from this one. + Vector& operator-=(const Vector &v) { + assert(length == v.length && "Vector length mismatch."); + std::transform(data, data + length, v.data, data, std::minus()); + return *this; + } + + /// \brief Returns the index of the minimum value in this vector + unsigned minIndex() const { + return std::min_element(data, data + length) - data; + } + + private: + unsigned length; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given vector on the given +/// output stream. +template +OStream& operator<<(OStream &os, const Vector &v) { + assert((v.getLength() != 0) && "Zero-length vector badness."); + + os << "[ " << v[0]; + for (unsigned i = 1; i < v.getLength(); ++i) { + os << ", " << v[i]; + } + os << " ]"; + + return os; +} + + +/// \brief PBQP Matrix class +class Matrix { + public: + + /// \brief Construct a PBQP Matrix with the given dimensions. + Matrix(unsigned rows, unsigned cols) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + } + + /// \brief Construct a PBQP Matrix with the given dimensions and initial + /// value. + Matrix(unsigned rows, unsigned cols, PBQPNum initVal) : + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { + std::fill(data, data + (rows * cols), initVal); + } + + /// \brief Copy construct a PBQP matrix. + Matrix(const Matrix &m) : + rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) { + std::copy(m.data, m.data + (rows * cols), data); + } + + /// \brief Destroy this matrix, return its memory. + ~Matrix() { delete[] data; } + + /// \brief Assignment operator. + Matrix& operator=(const Matrix &m) { + delete[] data; + rows = m.rows; cols = m.cols; + data = new PBQPNum[rows * cols]; + std::copy(m.data, m.data + (rows * cols), data); + return *this; + } + + /// \brief Return the number of rows in this matrix. + unsigned getRows() const { return rows; } + + /// \brief Return the number of cols in this matrix. + unsigned getCols() const { return cols; } + + /// \brief Matrix element access. + PBQPNum* operator[](unsigned r) { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Matrix element access. + const PBQPNum* operator[](unsigned r) const { + assert(r < rows && "Row out of bounds."); + return data + (r * cols); + } + + /// \brief Returns the given row as a vector. + Vector getRowAsVector(unsigned r) const { + Vector v(cols); + for (unsigned c = 0; c < cols; ++c) + v[c] = (*this)[r][c]; + return v; + } + + /// \brief Returns the given column as a vector. + Vector getColAsVector(unsigned c) const { + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][c]; + return v; + } + + /// \brief Reset the matrix to the given value. + Matrix& reset(PBQPNum val = 0) { + std::fill(data, data + (rows * cols), val); + return *this; + } + + /// \brief Set a single row of this matrix to the given value. + Matrix& setRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds."); + std::fill(data + (r * cols), data + ((r + 1) * cols), val); + return *this; + } + + /// \brief Set a single column of this matrix to the given value. + Matrix& setCol(unsigned c, PBQPNum val) { + assert(c < cols && "Column out of bounds."); + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] = val; + return *this; + } + + /// \brief Matrix transpose. + Matrix transpose() const { + Matrix m(cols, rows); + for (unsigned r = 0; r < rows; ++r) + for (unsigned c = 0; c < cols; ++c) + m[c][r] = (*this)[r][c]; + return m; + } + + /// \brief Returns the diagonal of the matrix as a vector. + /// + /// Matrix must be square. + Vector diagonalize() const { + assert(rows == cols && "Attempt to diagonalize non-square matrix."); + + Vector v(rows); + for (unsigned r = 0; r < rows; ++r) + v[r] = (*this)[r][r]; + return v; + } + + /// \brief Add the given matrix to this one. + Matrix& operator+=(const Matrix &m) { + assert(rows == m.rows && cols == m.cols && + "Matrix dimensions mismatch."); + std::transform(data, data + (rows * cols), m.data, data, + std::plus()); + return *this; + } + + /// \brief Returns the minimum of the given row + PBQPNum getRowMin(unsigned r) const { + assert(r < rows && "Row out of bounds"); + return *std::min_element(data + (r * cols), data + ((r + 1) * cols)); + } + + /// \brief Returns the minimum of the given column + PBQPNum getColMin(unsigned c) const { + PBQPNum minElem = (*this)[0][c]; + for (unsigned r = 1; r < rows; ++r) + if ((*this)[r][c] < minElem) minElem = (*this)[r][c]; + return minElem; + } + + /// \brief Subtracts the given scalar from the elements of the given row. + Matrix& subFromRow(unsigned r, PBQPNum val) { + assert(r < rows && "Row out of bounds"); + std::transform(data + (r * cols), data + ((r + 1) * cols), + data + (r * cols), + std::bind2nd(std::minus(), val)); + return *this; + } + + /// \brief Subtracts the given scalar from the elements of the given column. + Matrix& subFromCol(unsigned c, PBQPNum val) { + for (unsigned r = 0; r < rows; ++r) + (*this)[r][c] -= val; + return *this; + } + + /// \brief Returns true if this is a zero matrix. + bool isZero() const { + return find_if(data, data + (rows * cols), + std::bind2nd(std::not_equal_to(), 0)) == + data + (rows * cols); + } + + private: + unsigned rows, cols; + PBQPNum *data; +}; + +/// \brief Output a textual representation of the given matrix on the given +/// output stream. +template +OStream& operator<<(OStream &os, const Matrix &m) { + + assert((m.getRows() != 0) && "Zero-row matrix badness."); + + for (unsigned i = 0; i < m.getRows(); ++i) { + os << m.getRowAsVector(i); + } + + return os; +} + +} + +#endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/final/include/llvm/CodeGen/PBQP/Solution.h b/final/include/llvm/CodeGen/PBQP/Solution.h new file mode 100644 index 00000000000..57d9b95fc3b --- /dev/null +++ b/final/include/llvm/CodeGen/PBQP/Solution.h @@ -0,0 +1,94 @@ +//===-- Solution.h ------- PBQP Solution ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// PBQP Solution class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H +#define LLVM_CODEGEN_PBQP_SOLUTION_H + +#include "Math.h" +#include "Graph.h" + +#include + +namespace PBQP { + + /// \brief Represents a solution to a PBQP problem. + /// + /// To get the selection for each node in the problem use the getSelection method. + class Solution { + private: + + typedef std::map SelectionsMap; + SelectionsMap selections; + + unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; + + public: + + /// \brief Initialise an empty solution. + Solution() + : r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions(0) {} + + /// \brief Number of nodes for which selections have been made. + /// @return Number of nodes for which selections have been made. + unsigned numNodes() const { return selections.size(); } + + /// \brief Records a reduction via the R0 rule. Should be called from the + /// solver only. + void recordR0() { ++r0Reductions; } + + /// \brief Returns the number of R0 reductions applied to solve the problem. + unsigned numR0Reductions() const { return r0Reductions; } + + /// \brief Records a reduction via the R1 rule. Should be called from the + /// solver only. + void recordR1() { ++r1Reductions; } + + /// \brief Returns the number of R1 reductions applied to solve the problem. + unsigned numR1Reductions() const { return r1Reductions; } + + /// \brief Records a reduction via the R2 rule. Should be called from the + /// solver only. + void recordR2() { ++r2Reductions; } + + /// \brief Returns the number of R2 reductions applied to solve the problem. + unsigned numR2Reductions() const { return r2Reductions; } + + /// \brief Records a reduction via the RN rule. Should be called from the + /// solver only. + void recordRN() { ++ rNReductions; } + + /// \brief Returns the number of RN reductions applied to solve the problem. + unsigned numRNReductions() const { return rNReductions; } + + /// \brief Set the selection for a given node. + /// @param nItr Node iterator. + /// @param selection Selection for nItr. + void setSelection(Graph::NodeItr nItr, unsigned selection) { + selections[nItr] = selection; + } + + /// \brief Get a node's selection. + /// @param nItr Node iterator. + /// @return The selection for nItr; + unsigned getSelection(Graph::ConstNodeItr nItr) const { + SelectionsMap::const_iterator sItr = selections.find(nItr); + assert(sItr != selections.end() && "No selection for node."); + return sItr->second; + } + + }; + +} + +#endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/final/include/llvm/CodeGen/Passes.h b/final/include/llvm/CodeGen/Passes.h new file mode 100644 index 00000000000..53aee7a9c9f --- /dev/null +++ b/final/include/llvm/CodeGen/Passes.h @@ -0,0 +1,241 @@ +//===-- Passes.h - Target independent code generation passes ----*- 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 interfaces to access the target independent code generation +// passes provided by the LLVM backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PASSES_H +#define LLVM_CODEGEN_PASSES_H + +#include "llvm/Target/TargetMachine.h" +#include + +namespace llvm { + + class FunctionPass; + class MachineFunctionPass; + class PassInfo; + class TargetLowering; + class RegisterCoalescer; + class raw_ostream; + + /// createUnreachableBlockEliminationPass - The LLVM code generator does not + /// work well with unreachable basic blocks (what live ranges make sense for a + /// block that cannot be reached?). As such, a code generator should either + /// not instruction select unreachable blocks, or run this pass as its + /// last LLVM modifying pass to clean up blocks that are not reachable from + /// the entry block. + FunctionPass *createUnreachableBlockEliminationPass(); + + /// MachineFunctionPrinter pass - This pass prints out the machine function to + /// the given stream as a debugging tool. + MachineFunctionPass * + createMachineFunctionPrinterPass(raw_ostream &OS, + const std::string &Banner =""); + + /// MachineLoopInfo pass - This pass is a loop analysis pass. + /// + extern char &MachineLoopInfoID; + + /// MachineLoopRanges pass - This pass is an on-demand loop coverage + /// analysis pass. + /// + extern char &MachineLoopRangesID; + + /// MachineDominators pass - This pass is a machine dominators analysis pass. + /// + extern char &MachineDominatorsID; + + /// EdgeBundles analysis - Bundle machine CFG edges. + /// + extern char &EdgeBundlesID; + + /// PHIElimination pass - This pass eliminates machine instruction PHI nodes + /// by inserting copy instructions. This destroys SSA information, but is the + /// desired input for some register allocators. This pass is "required" by + /// these register allocator like this: AU.addRequiredID(PHIEliminationID); + /// + extern char &PHIEliminationID; + + /// StrongPHIElimination pass - This pass eliminates machine instruction PHI + /// nodes by inserting copy instructions. This destroys SSA information, but + /// is the desired input for some register allocators. This pass is + /// "required" by these register allocator like this: + /// AU.addRequiredID(PHIEliminationID); + /// This pass is still in development + extern char &StrongPHIEliminationID; + + extern char &PreAllocSplittingID; + + /// LiveStacks pass. An analysis keeping track of the liveness of stack slots. + extern char &LiveStacksID; + + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register + /// copy it can. + /// + extern char &SimpleRegisterCoalescingID; + + /// TwoAddressInstruction pass - This pass reduces two-address instructions to + /// use two operands. This destroys SSA information but it is desired by + /// register allocators. + extern char &TwoAddressInstructionPassID; + + /// SpillPlacement analysis. Suggest optimal placement of spill code between + /// basic blocks. + /// + extern char &SpillPlacementID; + + /// UnreachableMachineBlockElimination pass - This pass removes unreachable + /// machine basic blocks. + extern char &UnreachableMachineBlockElimID; + + /// DeadMachineInstructionElim pass - This pass removes dead machine + /// instructions. + /// + FunctionPass *createDeadMachineInstructionElimPass(); + + /// Creates a register allocator as the user specified on the command line, or + /// picks one that matches OptLevel. + /// + FunctionPass *createRegisterAllocator(CodeGenOpt::Level OptLevel); + + /// FastRegisterAllocation Pass - This pass register allocates as fast as + /// possible. It is best suited for debug code where live ranges are short. + /// + FunctionPass *createFastRegisterAllocator(); + + /// BasicRegisterAllocation Pass - This pass implements a degenerate global + /// register allocator using the basic regalloc framework. + /// + FunctionPass *createBasicRegisterAllocator(); + + /// Greedy register allocation pass - This pass implements a global register + /// allocator for optimized builds. + /// + FunctionPass *createGreedyRegisterAllocator(); + + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan + /// register allocation algorithm, a global register allocator. + /// + FunctionPass *createLinearScanRegisterAllocator(); + + /// PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean + /// Quadratic Prograaming (PBQP) based register allocator. + /// + FunctionPass *createDefaultPBQPRegisterAllocator(); + + /// SimpleRegisterCoalescing Pass - Coalesce all copies possible. Can run + /// independently of the register allocator. + /// + RegisterCoalescer *createSimpleRegisterCoalescer(); + + /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, + /// and eliminates abstract frame references. + /// + FunctionPass *createPrologEpilogCodeInserter(); + + /// LowerSubregs Pass - This pass lowers subregs to register-register copies + /// which yields suboptimal, but correct code if the register allocator + /// cannot coalesce all subreg operations during allocation. + /// + FunctionPass *createLowerSubregsPass(); + + /// createPostRAScheduler - This pass performs post register allocation + /// scheduling. + FunctionPass *createPostRAScheduler(CodeGenOpt::Level OptLevel); + + /// BranchFolding Pass - This pass performs machine code CFG based + /// optimizations to delete branches to branches, eliminate branches to + /// successor blocks (creating fall throughs), and eliminating branches over + /// branches. + FunctionPass *createBranchFoldingPass(bool DefaultEnableTailMerge); + + /// TailDuplicate Pass - Duplicate blocks with unconditional branches + /// into tails of their predecessors. + FunctionPass *createTailDuplicatePass(bool PreRegAlloc = false); + + /// IfConverter Pass - This pass performs machine code if conversion. + FunctionPass *createIfConverterPass(); + + /// Code Placement Pass - This pass optimize code placement and aligns loop + /// headers to target specific alignment boundary. + FunctionPass *createCodePlacementOptPass(); + + /// IntrinsicLowering Pass - Performs target-independent LLVM IR + /// transformations for highly portable strategies. + FunctionPass *createGCLoweringPass(); + + /// MachineCodeAnalysis Pass - Target-independent pass to mark safe points in + /// machine code. Must be added very late during code generation, just prior + /// to output, and importantly after all CFG transformations (such as branch + /// folding). + FunctionPass *createGCMachineCodeAnalysisPass(); + + /// Deleter Pass - Releases GC metadata. + /// + FunctionPass *createGCInfoDeleter(); + + /// Creates a pass to print GC metadata. + /// + FunctionPass *createGCInfoPrinter(raw_ostream &OS); + + /// createMachineCSEPass - This pass performs global CSE on machine + /// instructions. + FunctionPass *createMachineCSEPass(); + + /// createMachineLICMPass - This pass performs LICM on machine instructions. + /// + FunctionPass *createMachineLICMPass(bool PreRegAlloc = true); + + /// createMachineSinkingPass - This pass performs sinking on machine + /// instructions. + FunctionPass *createMachineSinkingPass(); + + /// createPeepholeOptimizerPass - This pass performs peephole optimizations - + /// like extension and comparison eliminations. + FunctionPass *createPeepholeOptimizerPass(); + + /// createOptimizePHIsPass - This pass optimizes machine instruction PHIs + /// to take advantage of opportunities created during DAG legalization. + FunctionPass *createOptimizePHIsPass(); + + /// createStackSlotColoringPass - This pass performs stack slot coloring. + FunctionPass *createStackSlotColoringPass(bool); + + /// createStackProtectorPass - This pass adds stack protectors to functions. + FunctionPass *createStackProtectorPass(const TargetLowering *tli); + + /// createMachineVerifierPass - This pass verifies cenerated machine code + /// instructions for correctness. + FunctionPass *createMachineVerifierPass(const char *Banner = 0); + + /// createDwarfEHPass - This pass mulches exception handling code into a form + /// adapted to code generation. Required if using dwarf exception handling. + FunctionPass *createDwarfEHPass(const TargetMachine *tm); + + /// createSjLjEHPass - This pass adapts exception handling code to use + /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. + FunctionPass *createSjLjEHPass(const TargetLowering *tli); + + /// createLocalStackSlotAllocationPass - This pass assigns local frame + /// indices to stack slots relative to one another and allocates + /// base registers to access them when it is estimated by the target to + /// be out of range of normal frame pointer or stack pointer index + /// addressing. + FunctionPass *createLocalStackSlotAllocationPass(); + + /// createExpandISelPseudosPass - This pass expands pseudo-instructions. + /// + FunctionPass *createExpandISelPseudosPass(); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/ProcessImplicitDefs.h b/final/include/llvm/CodeGen/ProcessImplicitDefs.h new file mode 100644 index 00000000000..e2ab899f183 --- /dev/null +++ b/final/include/llvm/CodeGen/ProcessImplicitDefs.h @@ -0,0 +1,45 @@ +//===-------------- llvm/CodeGen/ProcessImplicitDefs.h ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_PROCESSIMPLICITDEFS_H +#define LLVM_CODEGEN_PROCESSIMPLICITDEFS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/SmallSet.h" + +namespace llvm { + + class MachineInstr; + class TargetInstrInfo; + + /// Process IMPLICIT_DEF instructions and make sure there is one implicit_def + /// for each use. Add isUndef marker to implicit_def defs and their uses. + class ProcessImplicitDefs : public MachineFunctionPass { + private: + + bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg, + unsigned OpIdx, const TargetInstrInfo *tii_, + SmallSet &ImpDefRegs); + + public: + static char ID; + + ProcessImplicitDefs() : MachineFunctionPass(ID) { + initializeProcessImplicitDefsPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + }; + +} + +#endif // LLVM_CODEGEN_PROCESSIMPLICITDEFS_H diff --git a/final/include/llvm/CodeGen/PseudoSourceValue.h b/final/include/llvm/CodeGen/PseudoSourceValue.h new file mode 100644 index 00000000000..bace631ab95 --- /dev/null +++ b/final/include/llvm/CodeGen/PseudoSourceValue.h @@ -0,0 +1,112 @@ +//===-- llvm/CodeGen/PseudoSourceValue.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the PseudoSourceValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PSEUDOSOURCEVALUE_H +#define LLVM_CODEGEN_PSEUDOSOURCEVALUE_H + +#include "llvm/Value.h" + +namespace llvm { + class MachineFrameInfo; + class raw_ostream; + + /// PseudoSourceValue - Special value supplied for machine level alias + /// analysis. It indicates that the a memory access references the functions + /// stack frame (e.g., a spill slot), below the stack frame (e.g., argument + /// space), or constant pool. + class PseudoSourceValue : public Value { + private: + /// printCustom - Implement printing for PseudoSourceValue. This is called + /// from Value::print or Value's operator<<. + /// + virtual void printCustom(raw_ostream &O) const; + + public: + explicit PseudoSourceValue(enum ValueTy Subclass = PseudoSourceValueVal); + + /// isConstant - Test whether the memory pointed to by this + /// PseudoSourceValue has a constant value. + /// + virtual bool isConstant(const MachineFrameInfo *) const; + + /// isAliased - Test whether the memory pointed to by this + /// PseudoSourceValue may also be pointed to by an LLVM IR Value. + virtual bool isAliased(const MachineFrameInfo *) const; + + /// mayAlias - Return true if the memory pointed to by this + /// PseudoSourceValue can ever alias a LLVM IR Value. + virtual bool mayAlias(const MachineFrameInfo *) const; + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const PseudoSourceValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == PseudoSourceValueVal || + V->getValueID() == FixedStackPseudoSourceValueVal; + } + + /// A pseudo source value referencing a fixed stack frame entry, + /// e.g., a spill slot. + static const PseudoSourceValue *getFixedStack(int FI); + + /// A pseudo source value referencing the area below the stack frame of + /// a function, e.g., the argument space. + static const PseudoSourceValue *getStack(); + + /// A pseudo source value referencing the global offset table + /// (or something the like). + static const PseudoSourceValue *getGOT(); + + /// A pseudo source value referencing the constant pool. Since constant + /// pools are constant, this doesn't need to identify a specific constant + /// pool entry. + static const PseudoSourceValue *getConstantPool(); + + /// A pseudo source value referencing a jump table. Since jump tables are + /// constant, this doesn't need to identify a specific jump table. + static const PseudoSourceValue *getJumpTable(); + }; + + /// FixedStackPseudoSourceValue - A specialized PseudoSourceValue + /// for holding FixedStack values, which must include a frame + /// index. + class FixedStackPseudoSourceValue : public PseudoSourceValue { + const int FI; + public: + explicit FixedStackPseudoSourceValue(int fi) : + PseudoSourceValue(FixedStackPseudoSourceValueVal), FI(fi) {} + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const FixedStackPseudoSourceValue *) { + return true; + } + static inline bool classof(const Value *V) { + return V->getValueID() == FixedStackPseudoSourceValueVal; + } + + virtual bool isConstant(const MachineFrameInfo *MFI) const; + + virtual bool isAliased(const MachineFrameInfo *MFI) const; + + virtual bool mayAlias(const MachineFrameInfo *) const; + + virtual void printCustom(raw_ostream &OS) const; + + int getFrameIndex() const { return FI; } + }; +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/RegAllocPBQP.h b/final/include/llvm/CodeGen/RegAllocPBQP.h new file mode 100644 index 00000000000..7e8745eddef --- /dev/null +++ b/final/include/llvm/CodeGen/RegAllocPBQP.h @@ -0,0 +1,167 @@ +//===-- RegAllocPBQP.h ------------------------------------------*- 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 PBQPBuilder interface, for classes which build PBQP +// instances to represent register allocation problems, and the RegAllocPBQP +// interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCPBQP_H +#define LLVM_CODEGEN_REGALLOCPBQP_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/PBQP/Graph.h" +#include "llvm/CodeGen/PBQP/Solution.h" + +#include +#include + +namespace llvm { + + class LiveIntervals; + class MachineFunction; + class MachineLoopInfo; + + /// This class wraps up a PBQP instance representing a register allocation + /// problem, plus the structures necessary to map back from the PBQP solution + /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map, + /// and the PBQP option <--> storage location map). + + class PBQPRAProblem { + public: + + typedef SmallVector AllowedSet; + + PBQP::Graph& getGraph() { return graph; } + + const PBQP::Graph& getGraph() const { return graph; } + + /// Record the mapping between the given virtual register and PBQP node, + /// and the set of allowed pregs for the vreg. + /// + /// If you are extending + /// PBQPBuilder you are unlikely to need this: Nodes and options for all + /// vregs will already have been set up for you by the base class. + template + void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node, + AllowedRegsItr arBegin, AllowedRegsItr arEnd) { + assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node."); + assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); + assert(allowedSets[vreg].empty() && "vreg already has pregs."); + + node2VReg[node] = vreg; + vreg2Node[vreg] = node; + std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); + } + + /// Get the virtual register corresponding to the given PBQP node. + unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const; + + /// Get the PBQP node corresponding to the given virtual register. + PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const; + + /// Returns true if the given PBQP option represents a physical register, + /// false otherwise. + bool isPRegOption(unsigned vreg, unsigned option) const { + // At present we only have spills or pregs, so anything that's not a + // spill is a preg. (This might be extended one day to support remat). + return !isSpillOption(vreg, option); + } + + /// Returns true if the given PBQP option represents spilling, false + /// otherwise. + bool isSpillOption(unsigned vreg, unsigned option) const { + // We hardcode option zero as the spill option. + return option == 0; + } + + /// Returns the allowed set for the given virtual register. + const AllowedSet& getAllowedSet(unsigned vreg) const; + + /// Get PReg for option. + unsigned getPRegForOption(unsigned vreg, unsigned option) const; + + private: + + typedef std::map Node2VReg; + typedef DenseMap VReg2Node; + typedef std::map AllowedSetMap; + + PBQP::Graph graph; + Node2VReg node2VReg; + VReg2Node vreg2Node; + + AllowedSetMap allowedSets; + + }; + + /// Builds PBQP instances to represent register allocation problems. Includes + /// spill, interference and coalescing costs by default. You can extend this + /// class to support additional constraints for your architecture. + class PBQPBuilder { + private: + PBQPBuilder(const PBQPBuilder&) {} + void operator=(const PBQPBuilder&) {} + public: + + typedef std::set RegSet; + + /// Default constructor. + PBQPBuilder() {} + + /// Clean up a PBQPBuilder. + virtual ~PBQPBuilder() {} + + /// Build a PBQP instance to represent the register allocation problem for + /// the given MachineFunction. + virtual std::auto_ptr build( + MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); + private: + + void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost); + + void addInterferenceCosts(PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + const TargetRegisterInfo *tri); + }; + + /// Extended builder which adds coalescing constraints to a problem. + class PBQPBuilderWithCoalescing : public PBQPBuilder { + public: + + /// Build a PBQP instance to represent the register allocation problem for + /// the given MachineFunction. + virtual std::auto_ptr build( + MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); + + private: + + void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption, + PBQP::PBQPNum benefit); + + void addVirtRegCoalesce(PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + PBQP::PBQPNum benefit); + }; + + FunctionPass* createPBQPRegisterAllocator(std::auto_ptr builder); +} + +#endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/final/include/llvm/CodeGen/RegAllocRegistry.h b/final/include/llvm/CodeGen/RegAllocRegistry.h new file mode 100644 index 00000000000..100e357654f --- /dev/null +++ b/final/include/llvm/CodeGen/RegAllocRegistry.h @@ -0,0 +1,66 @@ +//===-- llvm/CodeGen/RegAllocRegistry.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for register allocator function +// pass registry (RegisterRegAlloc). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENREGALLOCREGISTRY_H +#define LLVM_CODEGENREGALLOCREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterRegAlloc class - Track the registration of register allocators. +/// +//===----------------------------------------------------------------------===// +class RegisterRegAlloc : public MachinePassRegistryNode { + +public: + + typedef FunctionPass *(*FunctionPassCtor)(); + + static MachinePassRegistry Registry; + + RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { + Registry.Add(this); + } + ~RegisterRegAlloc() { Registry.Remove(this); } + + + // Accessors. + // + RegisterRegAlloc *getNext() const { + return (RegisterRegAlloc *)MachinePassRegistryNode::getNext(); + } + static RegisterRegAlloc *getList() { + return (RegisterRegAlloc *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } + +}; + +} // end namespace llvm + + +#endif diff --git a/final/include/llvm/CodeGen/RegisterCoalescer.h b/final/include/llvm/CodeGen/RegisterCoalescer.h new file mode 100644 index 00000000000..af0b3946912 --- /dev/null +++ b/final/include/llvm/CodeGen/RegisterCoalescer.h @@ -0,0 +1,244 @@ +//===-- RegisterCoalescer.h - Register Coalescing Interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the abstract interface for register coalescers, +// allowing them to interact with and query register allocators. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/IncludeFile.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/SmallPtrSet.h" + +#ifndef LLVM_CODEGEN_REGISTER_COALESCER_H +#define LLVM_CODEGEN_REGISTER_COALESCER_H + +namespace llvm { + + class MachineFunction; + class RegallocQuery; + class AnalysisUsage; + class MachineInstr; + class TargetRegisterInfo; + class TargetRegisterClass; + class TargetInstrInfo; + + /// An abstract interface for register coalescers. Coalescers must + /// implement this interface to be part of the coalescer analysis + /// group. + class RegisterCoalescer { + public: + static char ID; // Class identification, replacement for typeinfo + RegisterCoalescer() {} + virtual ~RegisterCoalescer(); // We want to be subclassed + + /// Run the coalescer on this function, providing interference + /// data to query. Return whether we removed any copies. + virtual bool coalesceFunction(MachineFunction &mf, + RegallocQuery &ifd) = 0; + + /// Reset state. Can be used to allow a coalescer run by + /// PassManager to be run again by the register allocator. + virtual void reset(MachineFunction &mf) {} + + /// Register allocators must call this from their own + /// getAnalysisUsage to cover the case where the coalescer is not + /// a Pass in the proper sense and isn't managed by PassManager. + /// PassManager needs to know which analyses to make available and + /// which to invalidate when running the register allocator or any + /// pass that might call coalescing. The long-term solution is to + /// allow hierarchies of PassManagers. + virtual void getAnalysisUsage(AnalysisUsage &AU) const {} + }; + + /// An abstract interface for register allocators to interact with + /// coalescers + /// + /// Example: + /// + /// This is simply an example of how to use the RegallocQuery + /// interface. It is not meant to be used in production. + /// + /// class LinearScanRegallocQuery : public RegallocQuery { + /// private: + /// const LiveIntervals \&li; + /// + /// public: + /// LinearScanRegallocQuery(LiveIntervals &intervals) + /// : li(intervals) {} + /// + /// /// This is pretty slow and conservative, but since linear scan + /// /// allocation doesn't pre-compute interference information it's + /// /// the best we can do. Coalescers are always free to ignore this + /// /// and implement their own discovery strategy. See + /// /// SimpleRegisterCoalescing for an example. + /// void getInterferences(IntervalSet &interferences, + /// const LiveInterval &a) const { + /// for(LiveIntervals::const_iterator iv = li.begin(), + /// ivend = li.end(); + /// iv != ivend; + /// ++iv) { + /// if (interfere(a, iv->second)) { + /// interferences.insert(&iv->second); + /// } + /// } + /// } + /// + /// /// This is *really* slow and stupid. See above. + /// int getNumberOfInterferences(const LiveInterval &a) const { + /// IntervalSet intervals; + /// getInterferences(intervals, a); + /// return intervals.size(); + /// } + /// }; + /// + /// In the allocator: + /// + /// RegisterCoalescer &coalescer = getAnalysis(); + /// + /// // We don't reset the coalescer so if it's already been run this + /// // takes almost no time. + /// LinearScanRegallocQuery ifd(*li_); + /// coalescer.coalesceFunction(fn, ifd); + /// + class RegallocQuery { + public: + typedef SmallPtrSet IntervalSet; + + virtual ~RegallocQuery() {} + + /// Return whether two live ranges interfere. + virtual bool interfere(const LiveInterval &a, + const LiveInterval &b) const { + // A naive test + return a.overlaps(b); + } + + /// Return the set of intervals that interfere with this one. + virtual void getInterferences(IntervalSet &interferences, + const LiveInterval &a) const = 0; + + /// This can often be cheaper than actually returning the + /// interferences. + virtual int getNumberOfInterferences(const LiveInterval &a) const = 0; + + /// Make any data structure updates necessary to reflect + /// coalescing or other modifications. + virtual void updateDataForMerge(const LiveInterval &a, + const LiveInterval &b, + const MachineInstr ©) {} + + /// Allow the register allocator to communicate when it doesn't + /// want a copy coalesced. This may be due to assumptions made by + /// the allocator about various invariants and so this question is + /// a matter of legality, not performance. Performance decisions + /// about which copies to coalesce should be made by the + /// coalescer. + virtual bool isLegalToCoalesce(const MachineInstr &inst) const { + return true; + } + }; + + + /// CoalescerPair - A helper class for register coalescers. When deciding if + /// two registers can be coalesced, CoalescerPair can determine if a copy + /// instruction would become an identity copy after coalescing. + class CoalescerPair { + const TargetInstrInfo &tii_; + const TargetRegisterInfo &tri_; + + /// dstReg_ - The register that will be left after coalescing. It can be a + /// virtual or physical register. + unsigned dstReg_; + + /// srcReg_ - the virtual register that will be coalesced into dstReg. + unsigned srcReg_; + + /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the + /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a + /// virtual register. + unsigned subIdx_; + + /// partial_ - True when the original copy was a partial subregister copy. + bool partial_; + + /// crossClass_ - True when both regs are virtual, and newRC is constrained. + bool crossClass_; + + /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy + /// instruction. + bool flipped_; + + /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ + /// is a physreg. + const TargetRegisterClass *newRC_; + + /// compose - Compose subreg indices a and b, either may be 0. + unsigned compose(unsigned, unsigned) const; + + /// isMoveInstr - Return true if MI is a move or subreg instruction. + bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst, + unsigned &SrcSub, unsigned &DstSub) const; + + public: + CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) + : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), + partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} + + /// setRegisters - set registers to match the copy instruction MI. Return + /// false if MI is not a coalescable copy instruction. + bool setRegisters(const MachineInstr*); + + /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible + /// because dstReg_ is a physical register, or subIdx_ is set. + bool flip(); + + /// isCoalescable - Return true if MI is a copy instruction that will become + /// an identity copy after coalescing. + bool isCoalescable(const MachineInstr*) const; + + /// isPhys - Return true if DstReg is a physical register. + bool isPhys() const { return !newRC_; } + + /// isPartial - Return true if the original copy instruction did not copy the + /// full register, but was a subreg operation. + bool isPartial() const { return partial_; } + + /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. + bool isCrossClass() const { return crossClass_; } + + /// isFlipped - Return true when getSrcReg is the register being defined by + /// the original copy instruction. + bool isFlipped() const { return flipped_; } + + /// getDstReg - Return the register (virtual or physical) that will remain + /// after coalescing. + unsigned getDstReg() const { return dstReg_; } + + /// getSrcReg - Return the virtual register that will be coalesced away. + unsigned getSrcReg() const { return srcReg_; } + + /// getSubIdx - Return the subregister index in DstReg that SrcReg will be + /// coalesced into, or 0. + unsigned getSubIdx() const { return subIdx_; } + + /// getNewRC - Return the register class of the coalesced register. + const TargetRegisterClass *getNewRC() const { return newRC_; } + }; +} + +// Because of the way .a files work, we must force the SimpleRC +// implementation to be pulled in if the RegisterCoalescing header is +// included. Otherwise we run the risk of RegisterCoalescing being +// used, but the default implementation not being linked into the tool +// that uses it. +FORCE_DEFINING_FILE_TO_BE_LINKED(RegisterCoalescer) +FORCE_DEFINING_FILE_TO_BE_LINKED(SimpleRegisterCoalescing) + +#endif diff --git a/final/include/llvm/CodeGen/RegisterScavenging.h b/final/include/llvm/CodeGen/RegisterScavenging.h new file mode 100644 index 00000000000..26b6773c053 --- /dev/null +++ b/final/include/llvm/CodeGen/RegisterScavenging.h @@ -0,0 +1,168 @@ +//===-- RegisterScavenging.h - Machine register scavenging ------*- 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 machine register scavenger class. It can provide +// information such as unused register at any point in a machine basic block. +// It also provides a mechanism to make registers availbale by evicting them +// to spill slots. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTER_SCAVENGING_H +#define LLVM_CODEGEN_REGISTER_SCAVENGING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + +class MachineRegisterInfo; +class TargetRegisterInfo; +class TargetInstrInfo; +class TargetRegisterClass; + +class RegScavenger { + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + MachineRegisterInfo* MRI; + MachineBasicBlock *MBB; + MachineBasicBlock::iterator MBBI; + unsigned NumPhysRegs; + + /// Tracking - True if RegScavenger is currently tracking the liveness of + /// registers. + bool Tracking; + + /// ScavengingFrameIndex - Special spill slot used for scavenging a register + /// post register allocation. + int ScavengingFrameIndex; + + /// ScavengedReg - If none zero, the specific register is currently being + /// scavenged. That is, it is spilled to the special scavenging stack slot. + unsigned ScavengedReg; + + /// ScavengedRC - Register class of the scavenged register. + /// + const TargetRegisterClass *ScavengedRC; + + /// ScavengeRestore - Instruction that restores the scavenged register from + /// stack. + const MachineInstr *ScavengeRestore; + + /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. + /// + BitVector CalleeSavedRegs; + + /// ReservedRegs - A bitvector of reserved registers. + /// + BitVector ReservedRegs; + + /// RegsAvailable - The current state of all the physical registers immediately + /// before MBBI. One bit per physical register. If bit is set that means it's + /// available, unset means the register is currently being used. + BitVector RegsAvailable; + +public: + RegScavenger() + : MBB(NULL), NumPhysRegs(0), Tracking(false), + ScavengingFrameIndex(-1), ScavengedReg(0), ScavengedRC(NULL) {} + + /// enterBasicBlock - Start tracking liveness from the begin of the specific + /// basic block. + void enterBasicBlock(MachineBasicBlock *mbb); + + /// initRegState - allow resetting register state info for multiple + /// passes over/within the same function. + void initRegState(); + + /// forward - Move the internal MBB iterator and update register states. + void forward(); + + /// forward - Move the internal MBB iterator and update register states until + /// it has processed the specific iterator. + void forward(MachineBasicBlock::iterator I) { + if (!Tracking && MBB->begin() != I) forward(); + while (MBBI != I) forward(); + } + + /// skipTo - Move the internal MBB iterator but do not update register states. + /// + void skipTo(MachineBasicBlock::iterator I) { MBBI = I; } + + /// getRegsUsed - return all registers currently in use in used. + void getRegsUsed(BitVector &used, bool includeReserved); + + /// getRegsAvailable - Return all available registers in the register class + /// in Mask. + BitVector getRegsAvailable(const TargetRegisterClass *RC); + + /// FindUnusedReg - Find a unused register of the specified register class. + /// Return 0 if none is found. + unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; + + /// setScavengingFrameIndex / getScavengingFrameIndex - accessor and setter of + /// ScavengingFrameIndex. + void setScavengingFrameIndex(int FI) { ScavengingFrameIndex = FI; } + int getScavengingFrameIndex() const { return ScavengingFrameIndex; } + + /// scavengeRegister - Make a register of the specific register class + /// available and do the appropriate bookkeeping. SPAdj is the stack + /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). + /// Returns the scavenged register. + unsigned scavengeRegister(const TargetRegisterClass *RegClass, + MachineBasicBlock::iterator I, int SPAdj); + unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { + return scavengeRegister(RegClass, MBBI, SPAdj); + } + + /// setUsed - Tell the scavenger a register is used. + /// + void setUsed(unsigned Reg); +private: + /// isReserved - Returns true if a register is reserved. It is never "unused". + bool isReserved(unsigned Reg) const { return ReservedRegs.test(Reg); } + + /// isUsed / isUnused - Test if a register is currently being used. + /// + bool isUsed(unsigned Reg) const { return !RegsAvailable.test(Reg); } + bool isUnused(unsigned Reg) const { return RegsAvailable.test(Reg); } + + /// isAliasUsed - Is Reg or an alias currently in use? + bool isAliasUsed(unsigned Reg) const; + + /// setUsed / setUnused - Mark the state of one or a number of registers. + /// + void setUsed(BitVector &Regs) { + RegsAvailable &= ~Regs; + } + void setUnused(BitVector &Regs) { + RegsAvailable |= Regs; + } + + /// Add Reg and all its sub-registers to BV. + void addRegWithSubRegs(BitVector &BV, unsigned Reg); + + /// Add Reg and its aliases to BV. + void addRegWithAliases(BitVector &BV, unsigned Reg); + + /// findSurvivorReg - Return the candidate register that is unused for the + /// longest after StartMI. UseMI is set to the instruction where the search + /// stopped. + /// + /// No more than InstrLimit instructions are inspected. + unsigned findSurvivorReg(MachineBasicBlock::iterator StartMI, + BitVector &Candidates, + unsigned InstrLimit, + MachineBasicBlock::iterator &UseMI); + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/RuntimeLibcalls.h b/final/include/llvm/CodeGen/RuntimeLibcalls.h new file mode 100644 index 00000000000..a51e82a6404 --- /dev/null +++ b/final/include/llvm/CodeGen/RuntimeLibcalls.h @@ -0,0 +1,313 @@ +//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- 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 enum representing the list of runtime library calls +// the backend may emit during code generation, and also some helper functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H +#define LLVM_CODEGEN_RUNTIMELIBCALLS_H + +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { +namespace RTLIB { + /// RTLIB::Libcall enum - This enum defines all of the runtime library calls + /// the backend can emit. The various long double types cannot be merged, + /// because 80-bit library functions use "xf" and 128-bit use "tf". + /// + /// When adding PPCF128 functions here, note that their names generally need + /// to be overridden for Darwin with the xxx$LDBL128 form. See + /// PPCISelLowering.cpp. + /// + enum Libcall { + // Integer + SHL_I16, + SHL_I32, + SHL_I64, + SHL_I128, + SRL_I16, + SRL_I32, + SRL_I64, + SRL_I128, + SRA_I16, + SRA_I32, + SRA_I64, + SRA_I128, + MUL_I8, + MUL_I16, + MUL_I32, + MUL_I64, + MUL_I128, + SDIV_I8, + SDIV_I16, + SDIV_I32, + SDIV_I64, + SDIV_I128, + UDIV_I8, + UDIV_I16, + UDIV_I32, + UDIV_I64, + UDIV_I128, + SREM_I8, + SREM_I16, + SREM_I32, + SREM_I64, + SREM_I128, + UREM_I8, + UREM_I16, + UREM_I32, + UREM_I64, + UREM_I128, + NEG_I32, + NEG_I64, + + // FLOATING POINT + ADD_F32, + ADD_F64, + ADD_F80, + ADD_PPCF128, + SUB_F32, + SUB_F64, + SUB_F80, + SUB_PPCF128, + MUL_F32, + MUL_F64, + MUL_F80, + MUL_PPCF128, + DIV_F32, + DIV_F64, + DIV_F80, + DIV_PPCF128, + REM_F32, + REM_F64, + REM_F80, + REM_PPCF128, + POWI_F32, + POWI_F64, + POWI_F80, + POWI_PPCF128, + SQRT_F32, + SQRT_F64, + SQRT_F80, + SQRT_PPCF128, + LOG_F32, + LOG_F64, + LOG_F80, + LOG_PPCF128, + LOG2_F32, + LOG2_F64, + LOG2_F80, + LOG2_PPCF128, + LOG10_F32, + LOG10_F64, + LOG10_F80, + LOG10_PPCF128, + EXP_F32, + EXP_F64, + EXP_F80, + EXP_PPCF128, + EXP2_F32, + EXP2_F64, + EXP2_F80, + EXP2_PPCF128, + SIN_F32, + SIN_F64, + SIN_F80, + SIN_PPCF128, + COS_F32, + COS_F64, + COS_F80, + COS_PPCF128, + POW_F32, + POW_F64, + POW_F80, + POW_PPCF128, + CEIL_F32, + CEIL_F64, + CEIL_F80, + CEIL_PPCF128, + TRUNC_F32, + TRUNC_F64, + TRUNC_F80, + TRUNC_PPCF128, + RINT_F32, + RINT_F64, + RINT_F80, + RINT_PPCF128, + NEARBYINT_F32, + NEARBYINT_F64, + NEARBYINT_F80, + NEARBYINT_PPCF128, + FLOOR_F32, + FLOOR_F64, + FLOOR_F80, + FLOOR_PPCF128, + COPYSIGN_F32, + COPYSIGN_F64, + COPYSIGN_F80, + COPYSIGN_PPCF128, + + // CONVERSION + FPEXT_F32_F64, + FPEXT_F16_F32, + FPROUND_F32_F16, + FPROUND_F64_F32, + FPROUND_F80_F32, + FPROUND_PPCF128_F32, + FPROUND_F80_F64, + FPROUND_PPCF128_F64, + FPTOSINT_F32_I8, + FPTOSINT_F32_I16, + FPTOSINT_F32_I32, + FPTOSINT_F32_I64, + FPTOSINT_F32_I128, + FPTOSINT_F64_I8, + FPTOSINT_F64_I16, + FPTOSINT_F64_I32, + FPTOSINT_F64_I64, + FPTOSINT_F64_I128, + FPTOSINT_F80_I32, + FPTOSINT_F80_I64, + FPTOSINT_F80_I128, + FPTOSINT_PPCF128_I32, + FPTOSINT_PPCF128_I64, + FPTOSINT_PPCF128_I128, + FPTOUINT_F32_I8, + FPTOUINT_F32_I16, + FPTOUINT_F32_I32, + FPTOUINT_F32_I64, + FPTOUINT_F32_I128, + FPTOUINT_F64_I8, + FPTOUINT_F64_I16, + FPTOUINT_F64_I32, + FPTOUINT_F64_I64, + FPTOUINT_F64_I128, + FPTOUINT_F80_I32, + FPTOUINT_F80_I64, + FPTOUINT_F80_I128, + FPTOUINT_PPCF128_I32, + FPTOUINT_PPCF128_I64, + FPTOUINT_PPCF128_I128, + SINTTOFP_I32_F32, + SINTTOFP_I32_F64, + SINTTOFP_I32_F80, + SINTTOFP_I32_PPCF128, + SINTTOFP_I64_F32, + SINTTOFP_I64_F64, + SINTTOFP_I64_F80, + SINTTOFP_I64_PPCF128, + SINTTOFP_I128_F32, + SINTTOFP_I128_F64, + SINTTOFP_I128_F80, + SINTTOFP_I128_PPCF128, + UINTTOFP_I32_F32, + UINTTOFP_I32_F64, + UINTTOFP_I32_F80, + UINTTOFP_I32_PPCF128, + UINTTOFP_I64_F32, + UINTTOFP_I64_F64, + UINTTOFP_I64_F80, + UINTTOFP_I64_PPCF128, + UINTTOFP_I128_F32, + UINTTOFP_I128_F64, + UINTTOFP_I128_F80, + UINTTOFP_I128_PPCF128, + + // COMPARISON + OEQ_F32, + OEQ_F64, + UNE_F32, + UNE_F64, + OGE_F32, + OGE_F64, + OLT_F32, + OLT_F64, + OLE_F32, + OLE_F64, + OGT_F32, + OGT_F64, + UO_F32, + UO_F64, + O_F32, + O_F64, + + // MEMORY + MEMCPY, + MEMSET, + MEMMOVE, + + // EXCEPTION HANDLING + UNWIND_RESUME, + + // Family ATOMICs + SYNC_VAL_COMPARE_AND_SWAP_1, + SYNC_VAL_COMPARE_AND_SWAP_2, + SYNC_VAL_COMPARE_AND_SWAP_4, + SYNC_VAL_COMPARE_AND_SWAP_8, + SYNC_LOCK_TEST_AND_SET_1, + SYNC_LOCK_TEST_AND_SET_2, + SYNC_LOCK_TEST_AND_SET_4, + SYNC_LOCK_TEST_AND_SET_8, + SYNC_FETCH_AND_ADD_1, + SYNC_FETCH_AND_ADD_2, + SYNC_FETCH_AND_ADD_4, + SYNC_FETCH_AND_ADD_8, + SYNC_FETCH_AND_SUB_1, + SYNC_FETCH_AND_SUB_2, + SYNC_FETCH_AND_SUB_4, + SYNC_FETCH_AND_SUB_8, + SYNC_FETCH_AND_AND_1, + SYNC_FETCH_AND_AND_2, + SYNC_FETCH_AND_AND_4, + SYNC_FETCH_AND_AND_8, + SYNC_FETCH_AND_OR_1, + SYNC_FETCH_AND_OR_2, + SYNC_FETCH_AND_OR_4, + SYNC_FETCH_AND_OR_8, + SYNC_FETCH_AND_XOR_1, + SYNC_FETCH_AND_XOR_2, + SYNC_FETCH_AND_XOR_4, + SYNC_FETCH_AND_XOR_8, + SYNC_FETCH_AND_NAND_1, + SYNC_FETCH_AND_NAND_2, + SYNC_FETCH_AND_NAND_4, + SYNC_FETCH_AND_NAND_8, + + UNKNOWN_LIBCALL + }; + + /// getFPEXT - Return the FPEXT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPEXT(EVT OpVT, EVT RetVT); + + /// getFPROUND - Return the FPROUND_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPROUND(EVT OpVT, EVT RetVT); + + /// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPTOSINT(EVT OpVT, EVT RetVT); + + /// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getFPTOUINT(EVT OpVT, EVT RetVT); + + /// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getSINTTOFP(EVT OpVT, EVT RetVT); + + /// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or + /// UNKNOWN_LIBCALL if there is none. + Libcall getUINTTOFP(EVT OpVT, EVT RetVT); +} +} + +#endif diff --git a/final/include/llvm/CodeGen/ScheduleDAG.h b/final/include/llvm/CodeGen/ScheduleDAG.h new file mode 100644 index 00000000000..a303dbbec0f --- /dev/null +++ b/final/include/llvm/CodeGen/ScheduleDAG.h @@ -0,0 +1,718 @@ +//===------- llvm/CodeGen/ScheduleDAG.h - Common Base Class------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScheduleDAG class, which is used as the common +// base class for instruction schedulers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEDAG_H +#define LLVM_CODEGEN_SCHEDULEDAG_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + class AliasAnalysis; + class SUnit; + class MachineConstantPool; + class MachineFunction; + class MachineRegisterInfo; + class MachineInstr; + class TargetRegisterInfo; + class ScheduleDAG; + class SDNode; + class TargetInstrInfo; + class TargetInstrDesc; + class TargetMachine; + class TargetRegisterClass; + template class GraphWriter; + + /// SDep - Scheduling dependency. This represents one direction of an + /// edge in the scheduling DAG. + class SDep { + public: + /// Kind - These are the different kinds of scheduling dependencies. + enum Kind { + Data, ///< Regular data dependence (aka true-dependence). + Anti, ///< A register anti-dependedence (aka WAR). + Output, ///< A register output-dependence (aka WAW). + Order ///< Any other ordering dependency. + }; + + private: + /// Dep - A pointer to the depending/depended-on SUnit, and an enum + /// indicating the kind of the dependency. + PointerIntPair Dep; + + /// Contents - A union discriminated by the dependence kind. + union { + /// Reg - For Data, Anti, and Output dependencies, the associated + /// register. For Data dependencies that don't currently have a register + /// assigned, this is set to zero. + unsigned Reg; + + /// Order - Additional information about Order dependencies. + struct { + /// isNormalMemory - True if both sides of the dependence + /// access memory in non-volatile and fully modeled ways. + bool isNormalMemory : 1; + + /// isMustAlias - True if both sides of the dependence are known to + /// access the same memory. + bool isMustAlias : 1; + + /// isArtificial - True if this is an artificial dependency, meaning + /// it is not necessary for program correctness, and may be safely + /// deleted if necessary. + bool isArtificial : 1; + } Order; + } Contents; + + /// Latency - The time associated with this edge. Often this is just + /// the value of the Latency field of the predecessor, however advanced + /// models may provide additional information about specific edges. + unsigned Latency; + + public: + /// SDep - Construct a null SDep. This is only for use by container + /// classes which require default constructors. SUnits may not + /// have null SDep edges. + SDep() : Dep(0, Data) {} + + /// SDep - Construct an SDep with the specified values. + SDep(SUnit *S, Kind kind, unsigned latency = 1, unsigned Reg = 0, + bool isNormalMemory = false, bool isMustAlias = false, + bool isArtificial = false) + : Dep(S, kind), Contents(), Latency(latency) { + switch (kind) { + case Anti: + case Output: + assert(Reg != 0 && + "SDep::Anti and SDep::Output must use a non-zero Reg!"); + // fall through + case Data: + assert(!isMustAlias && "isMustAlias only applies with SDep::Order!"); + assert(!isArtificial && "isArtificial only applies with SDep::Order!"); + Contents.Reg = Reg; + break; + case Order: + assert(Reg == 0 && "Reg given for non-register dependence!"); + Contents.Order.isNormalMemory = isNormalMemory; + Contents.Order.isMustAlias = isMustAlias; + Contents.Order.isArtificial = isArtificial; + break; + } + } + + bool operator==(const SDep &Other) const { + if (Dep != Other.Dep || Latency != Other.Latency) return false; + switch (Dep.getInt()) { + case Data: + case Anti: + case Output: + return Contents.Reg == Other.Contents.Reg; + case Order: + return Contents.Order.isNormalMemory == + Other.Contents.Order.isNormalMemory && + Contents.Order.isMustAlias == Other.Contents.Order.isMustAlias && + Contents.Order.isArtificial == Other.Contents.Order.isArtificial; + } + assert(0 && "Invalid dependency kind!"); + return false; + } + + bool operator!=(const SDep &Other) const { + return !operator==(Other); + } + + /// getLatency - Return the latency value for this edge, which roughly + /// means the minimum number of cycles that must elapse between the + /// predecessor and the successor, given that they have this edge + /// between them. + unsigned getLatency() const { + return Latency; + } + + /// setLatency - Set the latency for this edge. + void setLatency(unsigned Lat) { + Latency = Lat; + } + + //// getSUnit - Return the SUnit to which this edge points. + SUnit *getSUnit() const { + return Dep.getPointer(); + } + + //// setSUnit - Assign the SUnit to which this edge points. + void setSUnit(SUnit *SU) { + Dep.setPointer(SU); + } + + /// getKind - Return an enum value representing the kind of the dependence. + Kind getKind() const { + return Dep.getInt(); + } + + /// isCtrl - Shorthand for getKind() != SDep::Data. + bool isCtrl() const { + return getKind() != Data; + } + + /// isNormalMemory - Test if this is an Order dependence between two + /// memory accesses where both sides of the dependence access memory + /// in non-volatile and fully modeled ways. + bool isNormalMemory() const { + return getKind() == Order && Contents.Order.isNormalMemory; + } + + /// isMustAlias - Test if this is an Order dependence that is marked + /// as "must alias", meaning that the SUnits at either end of the edge + /// have a memory dependence on a known memory location. + bool isMustAlias() const { + return getKind() == Order && Contents.Order.isMustAlias; + } + + /// isArtificial - Test if this is an Order dependence that is marked + /// as "artificial", meaning it isn't necessary for correctness. + bool isArtificial() const { + return getKind() == Order && Contents.Order.isArtificial; + } + + /// isAssignedRegDep - Test if this is a Data dependence that is + /// associated with a register. + bool isAssignedRegDep() const { + return getKind() == Data && Contents.Reg != 0; + } + + /// getReg - Return the register associated with this edge. This is + /// only valid on Data, Anti, and Output edges. On Data edges, this + /// value may be zero, meaning there is no associated register. + unsigned getReg() const { + assert((getKind() == Data || getKind() == Anti || getKind() == Output) && + "getReg called on non-register dependence edge!"); + return Contents.Reg; + } + + /// setReg - Assign the associated register for this edge. This is + /// only valid on Data, Anti, and Output edges. On Anti and Output + /// edges, this value must not be zero. On Data edges, the value may + /// be zero, which would mean that no specific register is associated + /// with this edge. + void setReg(unsigned Reg) { + assert((getKind() == Data || getKind() == Anti || getKind() == Output) && + "setReg called on non-register dependence edge!"); + assert((getKind() != Anti || Reg != 0) && + "SDep::Anti edge cannot use the zero register!"); + assert((getKind() != Output || Reg != 0) && + "SDep::Output edge cannot use the zero register!"); + Contents.Reg = Reg; + } + }; + + template <> + struct isPodLike { static const bool value = true; }; + + /// SUnit - Scheduling unit. This is a node in the scheduling DAG. + class SUnit { + private: + SDNode *Node; // Representative node. + MachineInstr *Instr; // Alternatively, a MachineInstr. + public: + SUnit *OrigNode; // If not this, the node from which + // this node was cloned. + + // Preds/Succs - The SUnits before/after us in the graph. + SmallVector Preds; // All sunit predecessors. + SmallVector Succs; // All sunit successors. + + typedef SmallVector::iterator pred_iterator; + typedef SmallVector::iterator succ_iterator; + typedef SmallVector::const_iterator const_pred_iterator; + typedef SmallVector::const_iterator const_succ_iterator; + + unsigned NodeNum; // Entry # of node in the node vector. + unsigned NodeQueueId; // Queue id of node. + unsigned NumPreds; // # of SDep::Data preds. + unsigned NumSuccs; // # of SDep::Data sucss. + unsigned NumPredsLeft; // # of preds not scheduled. + unsigned NumSuccsLeft; // # of succs not scheduled. + unsigned short NumRegDefsLeft; // # of reg defs with no scheduled use. + unsigned short Latency; // Node latency. + bool isCall : 1; // Is a function call. + bool isTwoAddress : 1; // Is a two-address instruction. + bool isCommutable : 1; // Is a commutable instruction. + bool hasPhysRegDefs : 1; // Has physreg defs that are being used. + bool hasPhysRegClobbers : 1; // Has any physreg defs, used or not. + bool isPending : 1; // True once pending. + bool isAvailable : 1; // True once available. + bool isScheduled : 1; // True once scheduled. + bool isScheduleHigh : 1; // True if preferable to schedule high. + bool isCloned : 1; // True if this node has been cloned. + Sched::Preference SchedulingPref; // Scheduling preference. + + SmallVector DbgInstrList; // dbg_values referencing this. + private: + bool isDepthCurrent : 1; // True if Depth is current. + bool isHeightCurrent : 1; // True if Height is current. + unsigned Depth; // Node depth. + unsigned Height; // Node height. + public: + const TargetRegisterClass *CopyDstRC; // Is a special copy node if not null. + const TargetRegisterClass *CopySrcRC; + + /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent + /// an SDNode and any nodes flagged to it. + SUnit(SDNode *node, unsigned nodenum) + : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// SUnit - Construct an SUnit for post-regalloc scheduling to represent + /// a MachineInstr. + SUnit(MachineInstr *instr, unsigned nodenum) + : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// SUnit - Construct a placeholder SUnit. + SUnit() + : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), + NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), + NumSuccsLeft(0), NumRegDefsLeft(0), Latency(0), + isCall(false), isTwoAddress(false), isCommutable(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), + isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), + CopyDstRC(NULL), CopySrcRC(NULL) {} + + /// setNode - Assign the representative SDNode for this SUnit. + /// This may be used during pre-regalloc scheduling. + void setNode(SDNode *N) { + assert(!Instr && "Setting SDNode of SUnit with MachineInstr!"); + Node = N; + } + + /// getNode - Return the representative SDNode for this SUnit. + /// This may be used during pre-regalloc scheduling. + SDNode *getNode() const { + assert(!Instr && "Reading SDNode of SUnit with MachineInstr!"); + return Node; + } + + /// isInstr - Return true if this SUnit refers to a machine instruction as + /// opposed to an SDNode. + bool isInstr() const { return Instr; } + + /// setInstr - Assign the instruction for the SUnit. + /// This may be used during post-regalloc scheduling. + void setInstr(MachineInstr *MI) { + assert(!Node && "Setting MachineInstr of SUnit with SDNode!"); + Instr = MI; + } + + /// getInstr - Return the representative MachineInstr for this SUnit. + /// This may be used during post-regalloc scheduling. + MachineInstr *getInstr() const { + assert(!Node && "Reading MachineInstr of SUnit with SDNode!"); + return Instr; + } + + /// addPred - This adds the specified edge as a pred of the current node if + /// not already. It also adds the current node as a successor of the + /// specified node. + bool addPred(const SDep &D); + + /// removePred - This removes the specified edge as a pred of the current + /// node if it exists. It also removes the current node as a successor of + /// the specified node. + void removePred(const SDep &D); + + /// getDepth - Return the depth of this node, which is the length of the + /// maximum path up to any node which has no predecessors. + unsigned getDepth() const { + if (!isDepthCurrent) + const_cast(this)->ComputeDepth(); + return Depth; + } + + /// getHeight - Return the height of this node, which is the length of the + /// maximum path down to any node which has no successors. + unsigned getHeight() const { + if (!isHeightCurrent) + const_cast(this)->ComputeHeight(); + return Height; + } + + /// setDepthToAtLeast - If NewDepth is greater than this node's + /// depth value, set it to be the new depth value. This also + /// recursively marks successor nodes dirty. + void setDepthToAtLeast(unsigned NewDepth); + + /// setDepthToAtLeast - If NewDepth is greater than this node's + /// depth value, set it to be the new height value. This also + /// recursively marks predecessor nodes dirty. + void setHeightToAtLeast(unsigned NewHeight); + + /// setDepthDirty - Set a flag in this node to indicate that its + /// stored Depth value will require recomputation the next time + /// getDepth() is called. + void setDepthDirty(); + + /// setHeightDirty - Set a flag in this node to indicate that its + /// stored Height value will require recomputation the next time + /// getHeight() is called. + void setHeightDirty(); + + /// isPred - Test if node N is a predecessor of this node. + bool isPred(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) + if (Preds[i].getSUnit() == N) + return true; + return false; + } + + /// isSucc - Test if node N is a successor of this node. + bool isSucc(SUnit *N) { + for (unsigned i = 0, e = (unsigned)Succs.size(); i != e; ++i) + if (Succs[i].getSUnit() == N) + return true; + return false; + } + + void dump(const ScheduleDAG *G) const; + void dumpAll(const ScheduleDAG *G) const; + void print(raw_ostream &O, const ScheduleDAG *G) const; + + private: + void ComputeDepth(); + void ComputeHeight(); + }; + + //===--------------------------------------------------------------------===// + /// SchedulingPriorityQueue - This interface is used to plug different + /// priorities computation algorithms into the list scheduler. It implements + /// the interface of a standard priority queue, where nodes are inserted in + /// arbitrary order and returned in priority order. The computation of the + /// priority and the representation of the queue are totally up to the + /// implementation to decide. + /// + class SchedulingPriorityQueue { + unsigned CurCycle; + bool HasReadyFilter; + public: + SchedulingPriorityQueue(bool rf = false): + CurCycle(0), HasReadyFilter(rf) {} + virtual ~SchedulingPriorityQueue() {} + + virtual bool isBottomUp() const = 0; + + virtual void initNodes(std::vector &SUnits) = 0; + virtual void addNode(const SUnit *SU) = 0; + virtual void updateNode(const SUnit *SU) = 0; + virtual void releaseState() = 0; + + virtual bool empty() const = 0; + + bool hasReadyFilter() const { return HasReadyFilter; } + + virtual bool tracksRegPressure() const { return false; } + + virtual bool isReady(SUnit *) const { + assert(!HasReadyFilter && "The ready filter must override isReady()"); + return true; + } + virtual void push(SUnit *U) = 0; + + void push_all(const std::vector &Nodes) { + for (std::vector::const_iterator I = Nodes.begin(), + E = Nodes.end(); I != E; ++I) + push(*I); + } + + virtual SUnit *pop() = 0; + + virtual void remove(SUnit *SU) = 0; + + virtual void dump(ScheduleDAG *) const {} + + /// ScheduledNode - As each node is scheduled, this method is invoked. This + /// allows the priority function to adjust the priority of related + /// unscheduled nodes, for example. + /// + virtual void ScheduledNode(SUnit *) {} + + virtual void UnscheduledNode(SUnit *) {} + + void setCurCycle(unsigned Cycle) { + CurCycle = Cycle; + } + + unsigned getCurCycle() const { + return CurCycle; + } + }; + + class ScheduleDAG { + public: + MachineBasicBlock *BB; // The block in which to insert instructions + MachineBasicBlock::iterator InsertPos;// The position to insert instructions + const TargetMachine &TM; // Target processor + const TargetInstrInfo *TII; // Target instruction information + const TargetRegisterInfo *TRI; // Target processor register info + MachineFunction &MF; // Machine function + MachineRegisterInfo &MRI; // Virtual/real register map + std::vector Sequence; // The schedule. Null SUnit*'s + // represent noop instructions. + std::vector SUnits; // The scheduling units. + SUnit EntrySU; // Special node for the region entry. + SUnit ExitSU; // Special node for the region exit. + + explicit ScheduleDAG(MachineFunction &mf); + + virtual ~ScheduleDAG(); + + /// getInstrDesc - Return the TargetInstrDesc of this SUnit. + /// Return NULL for SDNodes without a machine opcode. + const TargetInstrDesc *getInstrDesc(const SUnit *SU) const { + if (SU->isInstr()) return &SU->getInstr()->getDesc(); + return getNodeDesc(SU->getNode()); + } + + /// viewGraph - Pop up a GraphViz/gv window with the ScheduleDAG rendered + /// using 'dot'. + /// + void viewGraph(); + + /// EmitSchedule - Insert MachineInstrs into the MachineBasicBlock + /// according to the order specified in Sequence. + /// + virtual MachineBasicBlock *EmitSchedule() = 0; + + void dumpSchedule() const; + + virtual void dumpNode(const SUnit *SU) const = 0; + + /// getGraphNodeLabel - Return a label for an SUnit node in a visualization + /// of the ScheduleDAG. + virtual std::string getGraphNodeLabel(const SUnit *SU) const = 0; + + /// addCustomGraphFeatures - Add custom features for a visualization of + /// the ScheduleDAG. + virtual void addCustomGraphFeatures(GraphWriter &) const {} + +#ifndef NDEBUG + /// VerifySchedule - Verify that all SUnits were scheduled and that + /// their state is consistent. + void VerifySchedule(bool isBottomUp); +#endif + + protected: + /// Run - perform scheduling. + /// + void Run(MachineBasicBlock *bb, MachineBasicBlock::iterator insertPos); + + /// BuildSchedGraph - Build SUnits and set up their Preds and Succs + /// to form the scheduling dependency graph. + /// + virtual void BuildSchedGraph(AliasAnalysis *AA) = 0; + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU) = 0; + + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *, SUnit *, + SDep&) const { } + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + /// ForceUnitLatencies - Return true if all scheduling edges should be given + /// a latency value of one. The default is to return false; schedulers may + /// override this as needed. + virtual bool ForceUnitLatencies() const { return false; } + + /// EmitNoop - Emit a noop instruction. + /// + void EmitNoop(); + + void EmitPhysRegCopy(SUnit *SU, DenseMap &VRBaseMap); + + private: + // Return the TargetInstrDesc of this SDNode or NULL. + const TargetInstrDesc *getNodeDesc(const SDNode *Node) const; + }; + + class SUnitIterator : public std::iterator { + SUnit *Node; + unsigned Operand; + + SUnitIterator(SUnit *N, unsigned Op) : Node(N), Operand(Op) {} + public: + bool operator==(const SUnitIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SUnitIterator& x) const { return !operator==(x); } + + const SUnitIterator &operator=(const SUnitIterator &I) { + assert(I.Node==Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->Preds[Operand].getSUnit(); + } + pointer operator->() const { return operator*(); } + + SUnitIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SUnitIterator operator++(int) { // Postincrement + SUnitIterator tmp = *this; ++*this; return tmp; + } + + static SUnitIterator begin(SUnit *N) { return SUnitIterator(N, 0); } + static SUnitIterator end (SUnit *N) { + return SUnitIterator(N, (unsigned)N->Preds.size()); + } + + unsigned getOperand() const { return Operand; } + const SUnit *getNode() const { return Node; } + /// isCtrlDep - Test if this is not an SDep::Data dependence. + bool isCtrlDep() const { + return getSDep().isCtrl(); + } + bool isArtificialDep() const { + return getSDep().isArtificial(); + } + const SDep &getSDep() const { + return Node->Preds[Operand]; + } + }; + + template <> struct GraphTraits { + typedef SUnit NodeType; + typedef SUnitIterator ChildIteratorType; + static inline NodeType *getEntryNode(SUnit *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SUnitIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SUnitIterator::end(N); + } + }; + + template <> struct GraphTraits : public GraphTraits { + typedef std::vector::iterator nodes_iterator; + static nodes_iterator nodes_begin(ScheduleDAG *G) { + return G->SUnits.begin(); + } + static nodes_iterator nodes_end(ScheduleDAG *G) { + return G->SUnits.end(); + } + }; + + /// ScheduleDAGTopologicalSort is a class that computes a topological + /// ordering for SUnits and provides methods for dynamically updating + /// the ordering as new edges are added. + /// + /// This allows a very fast implementation of IsReachable, for example. + /// + class ScheduleDAGTopologicalSort { + /// SUnits - A reference to the ScheduleDAG's SUnits. + std::vector &SUnits; + + /// Index2Node - Maps topological index to the node number. + std::vector Index2Node; + /// Node2Index - Maps the node number to its topological index. + std::vector Node2Index; + /// Visited - a set of nodes visited during a DFS traversal. + BitVector Visited; + + /// DFS - make a DFS traversal and mark all nodes affected by the + /// edge insertion. These nodes will later get new topological indexes + /// by means of the Shift method. + void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); + + /// Shift - reassign topological indexes for the nodes in the DAG + /// to preserve the topological ordering. + void Shift(BitVector& Visited, int LowerBound, int UpperBound); + + /// Allocate - assign the topological index to the node n. + void Allocate(int n, int index); + + public: + explicit ScheduleDAGTopologicalSort(std::vector &SUnits); + + /// InitDAGTopologicalSorting - create the initial topological + /// ordering from the DAG to be scheduled. + void InitDAGTopologicalSorting(); + + /// IsReachable - Checks if SU is reachable from TargetSU. + bool IsReachable(const SUnit *SU, const SUnit *TargetSU); + + /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU + /// will create a cycle. + bool WillCreateCycle(SUnit *SU, SUnit *TargetSU); + + /// AddPred - Updates the topological ordering to accomodate an edge + /// to be added from SUnit X to SUnit Y. + void AddPred(SUnit *Y, SUnit *X); + + /// RemovePred - Updates the topological ordering to accomodate an + /// an edge to be removed from the specified node N from the predecessors + /// of the current node M. + void RemovePred(SUnit *M, SUnit *N); + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + iterator begin() { return Index2Node.begin(); } + const_iterator begin() const { return Index2Node.begin(); } + iterator end() { return Index2Node.end(); } + const_iterator end() const { return Index2Node.end(); } + + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::const_reverse_iterator const_reverse_iterator; + reverse_iterator rbegin() { return Index2Node.rbegin(); } + const_reverse_iterator rbegin() const { return Index2Node.rbegin(); } + reverse_iterator rend() { return Index2Node.rend(); } + const_reverse_iterator rend() const { return Index2Node.rend(); } + }; +} + +#endif diff --git a/final/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/final/include/llvm/CodeGen/ScheduleHazardRecognizer.h new file mode 100644 index 00000000000..2f53baa1c7e --- /dev/null +++ b/final/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -0,0 +1,93 @@ +//=- llvm/CodeGen/ScheduleHazardRecognizer.h - Scheduling Support -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScheduleHazardRecognizer class, which implements +// hazard-avoidance heuristics for scheduling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SCHEDULEHAZARDRECOGNIZER_H + +namespace llvm { + +class SUnit; + +/// HazardRecognizer - This determines whether or not an instruction can be +/// issued this cycle, and whether or not a noop needs to be inserted to handle +/// the hazard. +class ScheduleHazardRecognizer { +protected: + /// MaxLookAhead - Indicate the number of cycles in the scoreboard + /// state. Important to restore the state after backtracking. Additionally, + /// MaxLookAhead=0 identifies a fake recognizer, allowing the client to + /// bypass virtual calls. Currently the PostRA scheduler ignores it. + unsigned MaxLookAhead; + +public: + ScheduleHazardRecognizer(): MaxLookAhead(0) {} + virtual ~ScheduleHazardRecognizer(); + + enum HazardType { + NoHazard, // This instruction can be emitted at this cycle. + Hazard, // This instruction can't be emitted at this cycle. + NoopHazard // This instruction can't be emitted, and needs noops. + }; + + unsigned getMaxLookAhead() const { return MaxLookAhead; } + + bool isEnabled() const { return MaxLookAhead != 0; } + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const { return false; } + + /// getHazardType - Return the hazard type of emitting this node. There are + /// three possible results. Either: + /// * NoHazard: it is legal to issue this instruction on this cycle. + /// * Hazard: issuing this instruction would stall the machine. If some + /// other instruction is available, issue it first. + /// * NoopHazard: issuing this instruction would break the program. If + /// some other instruction can be issued, do so, otherwise issue a noop. + virtual HazardType getHazardType(SUnit *m, int Stalls) { + return NoHazard; + } + + /// Reset - This callback is invoked when a new block of + /// instructions is about to be schedule. The hazard state should be + /// set to an initialized state. + virtual void Reset() {} + + /// EmitInstruction - This callback is invoked when an instruction is + /// emitted, to advance the hazard state. + virtual void EmitInstruction(SUnit *) {} + + /// AdvanceCycle - This callback is invoked whenever the next top-down + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. This should increment the + /// internal state of the hazard recognizer so that previously "Hazard" + /// instructions will now not be hazards. + virtual void AdvanceCycle() {} + + /// RecedeCycle - This callback is invoked whenever the next bottom-up + /// instruction to be scheduled cannot issue in the current cycle, either + /// because of latency or resource conflicts. + virtual void RecedeCycle() {} + + /// EmitNoop - This callback is invoked when a noop was added to the + /// instruction stream. + virtual void EmitNoop() { + // Default implementation: count it as a cycle. + AdvanceCycle(); + } +}; + +} + +#endif diff --git a/final/include/llvm/CodeGen/SchedulerRegistry.h b/final/include/llvm/CodeGen/SchedulerRegistry.h new file mode 100644 index 00000000000..96573dd5d8b --- /dev/null +++ b/final/include/llvm/CodeGen/SchedulerRegistry.h @@ -0,0 +1,111 @@ +//===-- llvm/CodeGen/SchedulerRegistry.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for instruction scheduler function +// pass registry (RegisterScheduler). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENSCHEDULERREGISTRY_H +#define LLVM_CODEGENSCHEDULERREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterScheduler class - Track the registration of instruction schedulers. +/// +//===----------------------------------------------------------------------===// + +class SelectionDAGISel; +class ScheduleDAGSDNodes; +class SelectionDAG; +class MachineBasicBlock; + +class RegisterScheduler : public MachinePassRegistryNode { +public: + typedef ScheduleDAGSDNodes *(*FunctionPassCtor)(SelectionDAGISel*, + CodeGenOpt::Level); + + static MachinePassRegistry Registry; + + RegisterScheduler(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { Registry.Add(this); } + ~RegisterScheduler() { Registry.Remove(this); } + + + // Accessors. + // + RegisterScheduler *getNext() const { + return (RegisterScheduler *)MachinePassRegistryNode::getNext(); + } + static RegisterScheduler *getList() { + return (RegisterScheduler *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } +}; + +/// createBURRListDAGScheduler - This creates a bottom up register usage +/// reduction list scheduler. +ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createTDRRListDAGScheduler - This creates a top down register usage +/// reduction list scheduler. +ScheduleDAGSDNodes *createTDRRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createBURRListDAGScheduler - This creates a bottom up list scheduler that +/// schedules nodes in source code order when possible. +ScheduleDAGSDNodes *createSourceListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createHybridListDAGScheduler - This creates a bottom up register pressure +/// aware list scheduler that make use of latency information to avoid stalls +/// for long latency instructions in low register pressure mode. In high +/// register pressure mode it schedules to reduce register pressure. +ScheduleDAGSDNodes *createHybridListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level); + +/// createILPListDAGScheduler - This creates a bottom up register pressure +/// aware list scheduler that tries to increase instruction level parallelism +/// in low register pressure mode. In high register pressure mode it schedules +/// to reduce register pressure. +ScheduleDAGSDNodes *createILPListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level); +/// createTDListDAGScheduler - This creates a top-down list scheduler with +/// a hazard recognizer. +ScheduleDAGSDNodes *createTDListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createFastDAGScheduler - This creates a "fast" scheduler. +/// +ScheduleDAGSDNodes *createFastDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +/// createDefaultScheduler - This creates an instruction scheduler appropriate +/// for the target. +ScheduleDAGSDNodes *createDefaultScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel); + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/final/include/llvm/CodeGen/ScoreboardHazardRecognizer.h new file mode 100644 index 00000000000..8850006df84 --- /dev/null +++ b/final/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -0,0 +1,129 @@ +//=- llvm/CodeGen/ScoreboardHazardRecognizer.h - Schedule Support -*- 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 ScoreboardHazardRecognizer class, which +// encapsulates hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H +#define LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Support/DataTypes.h" + +#include +#include +#include + +namespace llvm { + +class InstrItineraryData; +class TargetInstrDesc; +class ScheduleDAG; +class SUnit; + +class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { + // Scoreboard to track function unit usage. Scoreboard[0] is a + // mask of the FUs in use in the cycle currently being + // schedule. Scoreboard[1] is a mask for the next cycle. The + // Scoreboard is used as a circular buffer with the current cycle + // indicated by Head. + // + // Scoreboard always counts cycles in forward execution order. If used by a + // bottom-up scheduler, then the scoreboard cycles are the inverse of the + // scheduler's cycles. + class Scoreboard { + unsigned *Data; + + // The maximum number of cycles monitored by the Scoreboard. This + // value is determined based on the target itineraries to ensure + // that all hazards can be tracked. + size_t Depth; + // Indices into the Scoreboard that represent the current cycle. + size_t Head; + public: + Scoreboard():Data(NULL), Depth(0), Head(0) { } + ~Scoreboard() { + delete[] Data; + } + + size_t getDepth() const { return Depth; } + unsigned& operator[](size_t idx) const { + // Depth is expected to be a power-of-2. + assert(Depth && !(Depth & (Depth - 1)) && + "Scoreboard was not initialized properly!"); + + return Data[(Head + idx) & (Depth-1)]; + } + + void reset(size_t d = 1) { + if (Data == NULL) { + Depth = d; + Data = new unsigned[Depth]; + } + + memset(Data, 0, Depth * sizeof(Data[0])); + Head = 0; + } + + void advance() { + Head = (Head + 1) & (Depth-1); + } + + void recede() { + Head = (Head - 1) & (Depth-1); + } + + // Print the scoreboard. + void dump() const; + }; + +#ifndef NDEBUG + // Support for tracing ScoreboardHazardRecognizer as a component within + // another module. Follows the current thread-unsafe model of tracing. + static const char *DebugType; +#endif + + // Itinerary data for the target. + const InstrItineraryData *ItinData; + + const ScheduleDAG *DAG; + + /// IssueWidth - Max issue per cycle. 0=Unknown. + unsigned IssueWidth; + + /// IssueCount - Count instructions issued in this cycle. + unsigned IssueCount; + + Scoreboard ReservedScoreboard; + Scoreboard RequiredScoreboard; + +public: + ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, + const ScheduleDAG *DAG, + const char *ParentDebugType = ""); + + /// atIssueLimit - Return true if no more instructions may be issued in this + /// cycle. + virtual bool atIssueLimit() const; + + // Stalls provides an cycle offset at which SU will be scheduled. It will be + // negative for bottom-up scheduling. + virtual HazardType getHazardType(SUnit *SU, int Stalls); + virtual void Reset(); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + virtual void RecedeCycle(); +}; + +} + +#endif //!LLVM_CODEGEN_SCOREBOARDHAZARDRECOGNIZER_H diff --git a/final/include/llvm/CodeGen/SelectionDAG.h b/final/include/llvm/CodeGen/SelectionDAG.h new file mode 100644 index 00000000000..b537a77a76a --- /dev/null +++ b/final/include/llvm/CodeGen/SelectionDAG.h @@ -0,0 +1,1051 @@ +//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- 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 SelectionDAG class, and transitively defines the +// SDNode class and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_H +#define LLVM_CODEGEN_SELECTIONDAG_H + +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/RecyclingAllocator.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include +#include + +namespace llvm { + +class AliasAnalysis; +class MachineConstantPoolValue; +class MachineFunction; +class MDNode; +class SDNodeOrdering; +class SDDbgValue; +class TargetLowering; +class TargetSelectionDAGInfo; + +template<> struct ilist_traits : public ilist_default_traits { +private: + mutable ilist_half_node Sentinel; +public: + SDNode *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(SDNode *) {} + + SDNode *provideInitialHead() const { return createSentinel(); } + SDNode *ensureHead(SDNode*) const { return createSentinel(); } + static void noteHead(SDNode*, SDNode*) {} + + static void deleteNode(SDNode *) { + assert(0 && "ilist_traits shouldn't see a deleteNode call!"); + } +private: + static void createNode(const SDNode &); +}; + +/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do +/// not build SDNodes for these so as not to perturb the generated code; +/// instead the info is kept off to the side in this structure. Each SDNode may +/// have one or more associated dbg_value entries. This information is kept in +/// DbgValMap. +/// Byval parameters are handled separately because they don't use alloca's, +/// which busts the normal mechanism. There is good reason for handling all +/// parameters separately: they may not have code generated for them, they +/// should always go at the beginning of the function regardless of other code +/// motion, and debug info for them is potentially useful even if the parameter +/// is unused. Right now only byval parameters are handled separately. +class SDDbgInfo { + SmallVector DbgValues; + SmallVector ByvalParmDbgValues; + DenseMap > DbgValMap; + + void operator=(const SDDbgInfo&); // Do not implement. + SDDbgInfo(const SDDbgInfo&); // Do not implement. +public: + SDDbgInfo() {} + + void add(SDDbgValue *V, const SDNode *Node, bool isParameter) { + if (isParameter) { + ByvalParmDbgValues.push_back(V); + } else DbgValues.push_back(V); + if (Node) + DbgValMap[Node].push_back(V); + } + + void clear() { + DbgValMap.clear(); + DbgValues.clear(); + ByvalParmDbgValues.clear(); + } + + bool empty() const { + return DbgValues.empty() && ByvalParmDbgValues.empty(); + } + + SmallVector &getSDDbgValues(const SDNode *Node) { + return DbgValMap[Node]; + } + + typedef SmallVector::iterator DbgIterator; + DbgIterator DbgBegin() { return DbgValues.begin(); } + DbgIterator DbgEnd() { return DbgValues.end(); } + DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } + DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); } +}; + +enum CombineLevel { + Unrestricted, // Combine may create illegal operations and illegal types. + NoIllegalTypes, // Combine may create illegal operations but no illegal types. + NoIllegalOperations // Combine may only create legal operations and types. +}; + +class SelectionDAG; +void checkForCycles(const SDNode *N); +void checkForCycles(const SelectionDAG *DAG); + +/// SelectionDAG class - This is used to represent a portion of an LLVM function +/// in a low-level Data Dependence DAG representation suitable for instruction +/// selection. This DAG is constructed as the first step of instruction +/// selection in order to allow implementation of machine specific optimizations +/// and code simplifications. +/// +/// The representation used by the SelectionDAG is a target-independent +/// representation, which has some similarities to the GCC RTL representation, +/// but is significantly more simple, powerful, and is a graph form instead of a +/// linear form. +/// +class SelectionDAG { + const TargetMachine &TM; + const TargetLowering &TLI; + const TargetSelectionDAGInfo &TSI; + MachineFunction *MF; + LLVMContext *Context; + + /// EntryNode - The starting token. + SDNode EntryNode; + + /// Root - The root of the entire DAG. + SDValue Root; + + /// AllNodes - A linked list of nodes in the current DAG. + ilist AllNodes; + + /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use + /// pool allocation with recycling. + typedef RecyclingAllocator::Alignment> + NodeAllocatorType; + + /// NodeAllocator - Pool allocation for nodes. + NodeAllocatorType NodeAllocator; + + /// CSEMap - This structure is used to memoize nodes, automatically performing + /// CSE with existing nodes when a duplicate is requested. + FoldingSet CSEMap; + + /// OperandAllocator - Pool allocation for machine-opcode SDNode operands. + BumpPtrAllocator OperandAllocator; + + /// Allocator - Pool allocation for misc. objects that are created once per + /// SelectionDAG. + BumpPtrAllocator Allocator; + + /// SDNodeOrdering - The ordering of the SDNodes. It roughly corresponds to + /// the ordering of the original LLVM instructions. + SDNodeOrdering *Ordering; + + /// DbgInfo - Tracks dbg_value information through SDISel. + SDDbgInfo *DbgInfo; + + /// setGraphColorHelper - Implementation of setSubgraphColor. + /// Return whether we had to truncate the search. + /// + bool setSubgraphColorHelper(SDNode *N, const char *Color, + DenseSet &visited, + int level, bool &printed); + + void operator=(const SelectionDAG&); // Do not implement. + SelectionDAG(const SelectionDAG&); // Do not implement. + +public: + explicit SelectionDAG(const TargetMachine &TM); + ~SelectionDAG(); + + /// init - Prepare this SelectionDAG to process code in the given + /// MachineFunction. + /// + void init(MachineFunction &mf); + + /// clear - Clear state and free memory necessary to make this + /// SelectionDAG ready to process a new block. + /// + void clear(); + + MachineFunction &getMachineFunction() const { return *MF; } + const TargetMachine &getTarget() const { return TM; } + const TargetLowering &getTargetLoweringInfo() const { return TLI; } + const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } + LLVMContext *getContext() const {return Context; } + + /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. + /// + void viewGraph(const std::string &Title); + void viewGraph(); + +#ifndef NDEBUG + std::map NodeGraphAttrs; +#endif + + /// clearGraphAttrs - Clear all previously defined node graph attributes. + /// Intended to be used from a debugging tool (eg. gdb). + void clearGraphAttrs(); + + /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) + /// + void setGraphAttrs(const SDNode *N, const char *Attrs); + + /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) + /// Used from getNodeAttributes. + const std::string getGraphAttrs(const SDNode *N) const; + + /// setGraphColor - Convenience for setting node color attribute. + /// + void setGraphColor(const SDNode *N, const char *Color); + + /// setGraphColor - Convenience for setting subgraph color attribute. + /// + void setSubgraphColor(SDNode *N, const char *Color); + + typedef ilist::const_iterator allnodes_const_iterator; + allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); } + allnodes_const_iterator allnodes_end() const { return AllNodes.end(); } + typedef ilist::iterator allnodes_iterator; + allnodes_iterator allnodes_begin() { return AllNodes.begin(); } + allnodes_iterator allnodes_end() { return AllNodes.end(); } + ilist::size_type allnodes_size() const { + return AllNodes.size(); + } + + /// getRoot - Return the root tag of the SelectionDAG. + /// + const SDValue &getRoot() const { return Root; } + + /// getEntryNode - Return the token chain corresponding to the entry of the + /// function. + SDValue getEntryNode() const { + return SDValue(const_cast(&EntryNode), 0); + } + + /// setRoot - Set the current root tag of the SelectionDAG. + /// + const SDValue &setRoot(SDValue N) { + assert((!N.getNode() || N.getValueType() == MVT::Other) && + "DAG root value is not a chain!"); + if (N.getNode()) + checkForCycles(N.getNode()); + Root = N; + if (N.getNode()) + checkForCycles(this); + return Root; + } + + /// Combine - This iterates over the nodes in the SelectionDAG, folding + /// certain types of nodes together, or eliminating superfluous nodes. The + /// Level argument controls whether Combine is allowed to produce nodes and + /// types that are illegal on the target. + void Combine(CombineLevel Level, AliasAnalysis &AA, + CodeGenOpt::Level OptLevel); + + /// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that + /// only uses types natively supported by the target. Returns "true" if it + /// made any changes. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + bool LegalizeTypes(); + + /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is + /// compatible with the target instruction selector, as indicated by the + /// TargetLowering object. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + void Legalize(CodeGenOpt::Level OptLevel); + + /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG + /// that only uses vector math operations supported by the target. This is + /// necessary as a separate step from Legalize because unrolling a vector + /// operation can introduce illegal types, which requires running + /// LegalizeTypes again. + /// + /// This returns true if it made any changes; in that case, LegalizeTypes + /// is called again before Legalize. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + bool LegalizeVectors(); + + /// RemoveDeadNodes - This method deletes all unreachable nodes in the + /// SelectionDAG. + void RemoveDeadNodes(); + + /// DeleteNode - Remove the specified node from the system. This node must + /// have no referrers. + void DeleteNode(SDNode *N); + + /// getVTList - Return an SDVTList that represents the list of values + /// specified. + SDVTList getVTList(EVT VT); + SDVTList getVTList(EVT VT1, EVT VT2); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); + SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4); + SDVTList getVTList(const EVT *VTs, unsigned NumVTs); + + //===--------------------------------------------------------------------===// + // Node creation methods. + // + SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false); + SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false); + SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false); + SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); + SDValue getTargetConstant(uint64_t Val, EVT VT) { + return getConstant(Val, VT, true); + } + SDValue getTargetConstant(const APInt &Val, EVT VT) { + return getConstant(Val, VT, true); + } + SDValue getTargetConstant(const ConstantInt &Val, EVT VT) { + return getConstant(Val, VT, true); + } + // The forms below that take a double should only be used for simple + // constants that can be exactly represented in VT. No checks are made. + SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); + SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); + SDValue getTargetConstantFP(double Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getTargetConstantFP(const APFloat& Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { + return getConstantFP(Val, VT, true); + } + SDValue getGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + int64_t offset = 0, bool isTargetGA = false, + unsigned char TargetFlags = 0); + SDValue getTargetGlobalAddress(const GlobalValue *GV, DebugLoc DL, EVT VT, + int64_t offset = 0, + unsigned char TargetFlags = 0) { + return getGlobalAddress(GV, DL, VT, offset, true, TargetFlags); + } + SDValue getFrameIndex(int FI, EVT VT, bool isTarget = false); + SDValue getTargetFrameIndex(int FI, EVT VT) { + return getFrameIndex(FI, VT, true); + } + SDValue getJumpTable(int JTI, EVT VT, bool isTarget = false, + unsigned char TargetFlags = 0); + SDValue getTargetJumpTable(int JTI, EVT VT, unsigned char TargetFlags = 0) { + return getJumpTable(JTI, VT, true, TargetFlags); + } + SDValue getConstantPool(const Constant *C, EVT VT, + unsigned Align = 0, int Offs = 0, bool isT=false, + unsigned char TargetFlags = 0); + SDValue getTargetConstantPool(const Constant *C, EVT VT, + unsigned Align = 0, int Offset = 0, + unsigned char TargetFlags = 0) { + return getConstantPool(C, VT, Align, Offset, true, TargetFlags); + } + SDValue getConstantPool(MachineConstantPoolValue *C, EVT VT, + unsigned Align = 0, int Offs = 0, bool isT=false, + unsigned char TargetFlags = 0); + SDValue getTargetConstantPool(MachineConstantPoolValue *C, + EVT VT, unsigned Align = 0, + int Offset = 0, unsigned char TargetFlags=0) { + return getConstantPool(C, VT, Align, Offset, true, TargetFlags); + } + // When generating a branch to a BB, we don't in general know enough + // to provide debug info for the BB at that time, so keep this one around. + SDValue getBasicBlock(MachineBasicBlock *MBB); + SDValue getBasicBlock(MachineBasicBlock *MBB, DebugLoc dl); + SDValue getExternalSymbol(const char *Sym, EVT VT); + SDValue getExternalSymbol(const char *Sym, DebugLoc dl, EVT VT); + SDValue getTargetExternalSymbol(const char *Sym, EVT VT, + unsigned char TargetFlags = 0); + SDValue getValueType(EVT); + SDValue getRegister(unsigned Reg, EVT VT); + SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label); + SDValue getBlockAddress(const BlockAddress *BA, EVT VT, + bool isTarget = false, unsigned char TargetFlags = 0); + + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N) { + return getNode(ISD::CopyToReg, dl, MVT::Other, Chain, + getRegister(Reg, N.getValueType()), N); + } + + // This version of the getCopyToReg method takes an extra operand, which + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, unsigned Reg, SDValue N, + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); + } + + // Similar to last getCopyToReg() except parameter Reg is a SDValue + SDValue getCopyToReg(SDValue Chain, DebugLoc dl, SDValue Reg, SDValue N, + SDValue Glue) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, Reg, N, Glue }; + return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); + } + + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT) { + SDVTList VTs = getVTList(VT, MVT::Other); + SDValue Ops[] = { Chain, getRegister(Reg, VT) }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, 2); + } + + // This version of the getCopyFromReg method takes an extra operand, which + // indicates that there is potentially an incoming glue value (if Glue is not + // null) and that there should be a glue result. + SDValue getCopyFromReg(SDValue Chain, DebugLoc dl, unsigned Reg, EVT VT, + SDValue Glue) { + SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; + return getNode(ISD::CopyFromReg, dl, VTs, Ops, Glue.getNode() ? 3 : 2); + } + + SDValue getCondCode(ISD::CondCode Cond); + + /// Returns the ConvertRndSat Note: Avoid using this node because it may + /// disappear in the future and most targets don't support it. + SDValue getConvertRndSat(EVT VT, DebugLoc dl, SDValue Val, SDValue DTy, + SDValue STy, + SDValue Rnd, SDValue Sat, ISD::CvtCode Code); + + /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of + /// elements in VT, which must be a vector type, must match the number of + /// mask elements NumElts. A integer mask element equal to -1 is treated as + /// undefined. + SDValue getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *MaskElts); + + /// getSExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either sign-extending or truncating it. + SDValue getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + + /// getZExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by either zero-extending or truncating it. + SDValue getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT); + + /// getZeroExtendInReg - Return the expression required to zero extend the Op + /// value assuming it was the smaller SrcTy value. + SDValue getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT SrcTy); + + /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). + SDValue getNOT(DebugLoc DL, SDValue Val, EVT VT); + + /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have + /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a + /// useful DebugLoc. + SDValue getCALLSEQ_START(SDValue Chain, SDValue Op) { + SDVTList VTs = getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, Op }; + return getNode(ISD::CALLSEQ_START, DebugLoc(), VTs, Ops, 2); + } + + /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a + /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have + /// a useful DebugLoc. + SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, + SDValue InGlue) { + SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Op1); + Ops.push_back(Op2); + Ops.push_back(InGlue); + return getNode(ISD::CALLSEQ_END, DebugLoc(), NodeTys, &Ops[0], + (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); + } + + /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful DebugLoc. + SDValue getUNDEF(EVT VT) { + return getNode(ISD::UNDEF, DebugLoc(), VT); + } + + /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does + /// not have a useful DebugLoc. + SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { + return getNode(ISD::GLOBAL_OFFSET_TABLE, DebugLoc(), VT); + } + + /// getNode - Gets or creates the specified node. + /// + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, SDValue N4, + SDValue N5); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDUse *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, SDValue N); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, SDValue N3, SDValue N4, + SDValue N5); + + /// getStackArgumentTokenFactor - Compute a TokenFactor to force all + /// the incoming stack arguments to be loaded from the stack. This is + /// used in tail call lowering to protect stack arguments from being + /// clobbered. + SDValue getStackArgumentTokenFactor(SDValue Chain); + + SDValue getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); + + SDValue getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, bool isVol, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); + + SDValue getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, SDValue Src, + SDValue Size, unsigned Align, bool isVol, + MachinePointerInfo DstPtrInfo); + + /// getSetCC - Helper function to make it easier to build SetCC's if you just + /// have an ISD::CondCode instead of an SDValue. + /// + SDValue getSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, + ISD::CondCode Cond) { + return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); + } + + /// getVSetCC - Helper function to make it easier to build VSetCC's nodes + /// if you just have an ISD::CondCode instead of an SDValue. + /// + SDValue getVSetCC(DebugLoc DL, EVT VT, SDValue LHS, SDValue RHS, + ISD::CondCode Cond) { + return getNode(ISD::VSETCC, DL, VT, LHS, RHS, getCondCode(Cond)); + } + + /// getSelectCC - Helper function to make it easier to build SelectCC's if you + /// just have an ISD::CondCode instead of an SDValue. + /// + SDValue getSelectCC(DebugLoc DL, SDValue LHS, SDValue RHS, + SDValue True, SDValue False, ISD::CondCode Cond) { + return getNode(ISD::SELECT_CC, DL, True.getValueType(), + LHS, RHS, True, False, getCondCode(Cond)); + } + + /// getVAArg - VAArg produces a result and token chain, and takes a pointer + /// and a source value as input. + SDValue getVAArg(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + SDValue SV, unsigned Align); + + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes 3 operands + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachinePointerInfo PtrInfo, unsigned Alignment=0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO); + + /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// takes 2 operands. + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, const Value* PtrVal, + unsigned Alignment = 0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO); + + /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a + /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, + /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not + /// less than FIRST_TARGET_MEMORY_OPCODE. + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachinePointerInfo PtrInfo, + unsigned Align = 0, bool Vol = false, + bool ReadMem = true, bool WriteMem = true); + + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachinePointerInfo PtrInfo, + unsigned Align = 0, bool Vol = false, + bool ReadMem = true, bool WriteMem = true); + + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO); + + /// getMergeValues - Create a MERGE_VALUES node from the given operands. + SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); + + /// getLoad - Loads are not normal binary operators: their result type is not + /// determined by their operands, and they produce a value AND a token chain. + /// + SDValue getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, + MachinePointerInfo PtrInfo, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, + EVT MemVT, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM); + SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, + EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, SDValue Offset, + MachinePointerInfo PtrInfo, EVT MemVT, + bool isVolatile, bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, + EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, SDValue Offset, + EVT MemVT, MachineMemOperand *MMO); + + /// getStore - Helper function to build ISD::STORE nodes. + /// + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachinePointerInfo PtrInfo, bool isVolatile, + bool isNonTemporal, unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachineMemOperand *MMO); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachinePointerInfo PtrInfo, EVT TVT, + bool isNonTemporal, bool isVolatile, + unsigned Alignment, + const MDNode *TBAAInfo = 0); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + EVT TVT, MachineMemOperand *MMO); + SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM); + + /// getSrcValue - Construct a node to track a Value* through the backend. + SDValue getSrcValue(const Value *v); + + /// getMDNode - Return an MDNodeSDNode which holds an MDNode. + SDValue getMDNode(const MDNode *MD); + + /// getShiftAmountOperand - Return the specified value casted to + /// the target's desired shift amount type. + SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); + + /// UpdateNodeOperands - *Mutate* the specified node in-place to have the + /// specified operands. If the resultant node already exists in the DAG, + /// this does not modify the specified node, instead it returns the node that + /// already exists. If the resultant node does not exist in the DAG, the + /// input node is returned. As a degenerate case, if you specify the same + /// input operands as the node already has, the input node is returned. + SDNode *UpdateNodeOperands(SDNode *N, SDValue Op); + SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2); + SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, + SDValue Op3); + SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4); + SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4, SDValue Op5); + SDNode *UpdateNodeOperands(SDNode *N, + const SDValue *Ops, unsigned NumOps); + + /// SelectNodeTo - These are used for target selectors to *mutate* the + /// specified node to have the specified return type, Target opcode, and + /// operands. Note that target opcodes are stored as + /// ~TargetOpcode in the node opcode field. The resultant node is returned. + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDValue Op1, SDValue Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, + EVT VT2, EVT VT3, EVT VT4, const SDValue *Ops, + unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// MorphNodeTo - This *mutates* the specified node to have the specified + /// return type, opcode, and operands. + SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getMachineNode - These are used for target selectors to create a new node + /// with specified return type(s), MachineInstr opcode, and operands. + /// + /// Note that getMachineNode returns the resultant node. If there is already + /// a node of the specified opcode and operands, it returns that node instead + /// of the current one. + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, + const std::vector &ResultTys, const SDValue *Ops, + unsigned NumOps); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getTargetExtractSubreg - A convenience function for creating + /// TargetInstrInfo::EXTRACT_SUBREG nodes. + SDValue getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand); + + /// getTargetInsertSubreg - A convenience function for creating + /// TargetInstrInfo::INSERT_SUBREG nodes. + SDValue getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand, SDValue Subreg); + + /// getNodeIfExists - Get the specified node if it's already available, or + /// else return NULL. + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); + + /// getDbgValue - Creates a SDDbgValue node. + /// + SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, uint64_t Off, + DebugLoc DL, unsigned O); + SDDbgValue *getDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, + DebugLoc DL, unsigned O); + SDDbgValue *getDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, + DebugLoc DL, unsigned O); + + /// DAGUpdateListener - Clients of various APIs that cause global effects on + /// the DAG can optionally implement this interface. This allows the clients + /// to handle the various sorts of updates that happen. + class DAGUpdateListener { + public: + virtual ~DAGUpdateListener(); + + /// NodeDeleted - The node N that was deleted and, if E is not null, an + /// equivalent node E that replaced it. + virtual void NodeDeleted(SDNode *N, SDNode *E) = 0; + + /// NodeUpdated - The node N that was updated. + virtual void NodeUpdated(SDNode *N) = 0; + }; + + /// RemoveDeadNode - Remove the specified node from the system. If any of its + /// operands then becomes dead, remove them as well. Inform UpdateListener + /// for each node deleted. + void RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener = 0); + + /// RemoveDeadNodes - This method deletes the unreachable nodes in the + /// given list, and any nodes that become unreachable as a result. + void RemoveDeadNodes(SmallVectorImpl &DeadNodes, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. + /// This can cause recursive merging of nodes in the DAG. Use the first + /// version if 'From' is known to have a single result, use the second + /// if you have two nodes with identical results (or if 'To' has a superset + /// of the results of 'From'), use the third otherwise. + /// + /// These methods all take an optional UpdateListener, which (if not null) is + /// informed about nodes that are deleted and modified due to recursive + /// changes in the dag. + /// + /// These functions only replace all existing uses. It's possible that as + /// these replacements are being performed, CSE may cause the From node + /// to be given new uses. These new uses of From are left in place, and + /// not automatically transfered to To. + /// + void ReplaceAllUsesWith(SDValue From, SDValue Op, + DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesWith(SDNode *From, SDNode *To, + DAGUpdateListener *UpdateListener = 0); + void ReplaceAllUsesWith(SDNode *From, const SDValue *To, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving + /// uses of other values produced by From.Val alone. + void ReplaceAllUsesOfValueWith(SDValue From, SDValue To, + DAGUpdateListener *UpdateListener = 0); + + /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but + /// for multiple values at once. This correctly handles the case where + /// there is an overlap between the From values and the To values. + void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, + unsigned Num, + DAGUpdateListener *UpdateListener = 0); + + /// AssignTopologicalOrder - Topological-sort the AllNodes list and a + /// assign a unique node id for each node in the DAG based on their + /// topological order. Returns the number of nodes. + unsigned AssignTopologicalOrder(); + + /// RepositionNode - Move node N in the AllNodes list to be immediately + /// before the given iterator Position. This may be used to update the + /// topological ordering when the list of nodes is modified. + void RepositionNode(allnodes_iterator Position, SDNode *N) { + AllNodes.insert(Position, AllNodes.remove(N)); + } + + /// isCommutativeBinOp - Returns true if the opcode is a commutative binary + /// operation. + static bool isCommutativeBinOp(unsigned Opcode) { + // FIXME: This should get its info from the td file, so that we can include + // target info. + switch (Opcode) { + case ISD::ADD: + case ISD::MUL: + case ISD::MULHU: + case ISD::MULHS: + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: + case ISD::FADD: + case ISD::FMUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SADDO: + case ISD::UADDO: + case ISD::ADDC: + case ISD::ADDE: return true; + default: return false; + } + } + + /// AssignOrdering - Assign an order to the SDNode. + void AssignOrdering(const SDNode *SD, unsigned Order); + + /// GetOrdering - Get the order for the SDNode. + unsigned GetOrdering(const SDNode *SD) const; + + /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the + /// value is produced by SD. + void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); + + /// GetDbgValues - Get the debug values which reference the given SDNode. + SmallVector &GetDbgValues(const SDNode* SD) { + return DbgInfo->getSDDbgValues(SD); + } + + /// TransferDbgValues - Transfer SDDbgValues. + void TransferDbgValues(SDValue From, SDValue To); + + /// hasDebugValues - Return true if there are any SDDbgValue nodes associated + /// with this SelectionDAG. + bool hasDebugValues() const { return !DbgInfo->empty(); } + + SDDbgInfo::DbgIterator DbgBegin() { return DbgInfo->DbgBegin(); } + SDDbgInfo::DbgIterator DbgEnd() { return DbgInfo->DbgEnd(); } + SDDbgInfo::DbgIterator ByvalParmDbgBegin() { + return DbgInfo->ByvalParmDbgBegin(); + } + SDDbgInfo::DbgIterator ByvalParmDbgEnd() { + return DbgInfo->ByvalParmDbgEnd(); + } + + void dump() const; + + /// CreateStackTemporary - Create a stack temporary, suitable for holding the + /// specified value type. If minAlign is specified, the slot size will have + /// at least that alignment. + SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); + + /// CreateStackTemporary - Create a stack temporary suitable for holding + /// either of the specified value types. + SDValue CreateStackTemporary(EVT VT1, EVT VT2); + + /// FoldConstantArithmetic - + SDValue FoldConstantArithmetic(unsigned Opcode, + EVT VT, + ConstantSDNode *Cst1, + ConstantSDNode *Cst2); + + /// FoldSetCC - Constant fold a setcc to true or false. + SDValue FoldSetCC(EVT VT, SDValue N1, + SDValue N2, ISD::CondCode Cond, DebugLoc dl); + + /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We + /// use this predicate to simplify operations downstream. + bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const; + + /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We + /// use this predicate to simplify operations downstream. Op and Mask are + /// known to be the same type. + bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) + const; + + /// ComputeMaskedBits - Determine which of the bits specified in Mask are + /// known to be either zero or one and return them in the KnownZero/KnownOne + /// bitsets. This code only analyzes bits in Mask, in order to short-circuit + /// processing. Targets can implement the computeMaskedBitsForTargetNode + /// method in the TargetLowering class to allow target nodes to be understood. + void ComputeMaskedBits(SDValue Op, const APInt &Mask, APInt &KnownZero, + APInt &KnownOne, unsigned Depth = 0) const; + + /// ComputeNumSignBits - Return the number of times the sign bit of the + /// register is replicated into the other bits. We know that at least 1 bit + /// is always equal to the sign bit (itself), but other cases can give us + /// information. For example, immediately after an "SRA X, 2", we know that + /// the top 3 bits are all equal to each other, so we return 3. Targets can + /// implement the ComputeNumSignBitsForTarget method in the TargetLowering + /// class to allow target nodes to be understood. + unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; + + /// isBaseWithConstantOffset - Return true if the specified operand is an + /// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an + /// ISD::OR with a ConstantSDNode that is guaranteed to have the same + /// semantics as an ADD. This handles the equivalence: + /// X|Cst == X+Cst iff X&Cst = 0. + bool isBaseWithConstantOffset(SDValue Op) const; + + /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. + bool isKnownNeverNaN(SDValue Op) const; + + /// isKnownNeverZero - Test whether the given SDValue is known to never be + /// positive or negative Zero. + bool isKnownNeverZero(SDValue Op) const; + + /// isEqualTo - Test whether two SDValues are known to compare equal. This + /// is true if they are the same value, or if one is negative zero and the + /// other positive zero. + bool isEqualTo(SDValue A, SDValue B) const; + + /// isVerifiedDebugInfoDesc - Returns true if the specified SDValue has + /// been verified as a debug information descriptor. + bool isVerifiedDebugInfoDesc(SDValue Op) const; + + /// UnrollVectorOp - Utility function used by legalize and lowering to + /// "unroll" a vector operation by splitting out the scalars and operating + /// on each element individually. If the ResNE is 0, fully unroll the vector + /// op. If ResNE is less than the width of the vector op, unroll up to ResNE. + /// If the ResNE is greater than the width of the vector op, unroll the + /// vector op and fill the end of the resulting vector with UNDEFS. + SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); + + /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a + /// location that is 'Dist' units away from the location that the 'Base' load + /// is loading from. + bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, + unsigned Bytes, int Dist) const; + + /// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if + /// it cannot be inferred. + unsigned InferPtrAlignment(SDValue Ptr) const; + +private: + bool RemoveNodeFromCSEMaps(SDNode *N); + void AddModifiedNodeToCSEMaps(SDNode *N, DAGUpdateListener *UpdateListener); + SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2, + void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps, + void *&InsertPos); + + void DeleteNodeNotInCSEMaps(SDNode *N); + void DeallocateNode(SDNode *N); + + unsigned getEVTAlignment(EVT MemoryVT) const; + + void allnodes_clear(); + + /// VTList - List of non-single value types. + std::vector VTList; + + /// CondCodeNodes - Maps to auto-CSE operations. + std::vector CondCodeNodes; + + std::vector ValueTypeNodes; + std::map ExtendedValueTypeNodes; + StringMap ExternalSymbols; + + std::map,SDNode*> TargetExternalSymbols; +}; + +template <> struct GraphTraits : public GraphTraits { + typedef SelectionDAG::allnodes_iterator nodes_iterator; + static nodes_iterator nodes_begin(SelectionDAG *G) { + return G->allnodes_begin(); + } + static nodes_iterator nodes_end(SelectionDAG *G) { + return G->allnodes_end(); + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/SelectionDAGISel.h b/final/include/llvm/CodeGen/SelectionDAGISel.h new file mode 100644 index 00000000000..54576794ded --- /dev/null +++ b/final/include/llvm/CodeGen/SelectionDAGISel.h @@ -0,0 +1,313 @@ +//===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SelectionDAGISel class, which is used as the common +// base class for SelectionDAG-based instruction selectors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H +#define LLVM_CODEGEN_SELECTIONDAG_ISEL_H + +#include "llvm/BasicBlock.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + class FastISel; + class SelectionDAGBuilder; + class SDValue; + class MachineRegisterInfo; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class TargetLowering; + class TargetInstrInfo; + class FunctionLoweringInfo; + class ScheduleHazardRecognizer; + class GCFunctionInfo; + class ScheduleDAGSDNodes; + class LoadInst; + +/// SelectionDAGISel - This is the common base class used for SelectionDAG-based +/// pattern-matching instruction selectors. +class SelectionDAGISel : public MachineFunctionPass { +public: + const TargetMachine &TM; + const TargetLowering &TLI; + FunctionLoweringInfo *FuncInfo; + MachineFunction *MF; + MachineRegisterInfo *RegInfo; + SelectionDAG *CurDAG; + SelectionDAGBuilder *SDB; + AliasAnalysis *AA; + GCFunctionInfo *GFI; + CodeGenOpt::Level OptLevel; + static char ID; + + explicit SelectionDAGISel(const TargetMachine &tm, + CodeGenOpt::Level OL = CodeGenOpt::Default); + virtual ~SelectionDAGISel(); + + const TargetLowering &getTargetLowering() { return TLI; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void EmitFunctionEntryCode() {} + + /// PreprocessISelDAG - This hook allows targets to hack on the graph before + /// instruction selection starts. + virtual void PreprocessISelDAG() {} + + /// PostprocessISelDAG() - This hook allows the target to hack on the graph + /// right after selection. + virtual void PostprocessISelDAG() {} + + /// Select - Main hook targets implement to select a node. + virtual SDNode *Select(SDNode *N) = 0; + + /// SelectInlineAsmMemoryOperand - Select the specified address as a target + /// addressing mode, according to the specified constraint code. If this does + /// not match or is not implemented, return true. The resultant operands + /// (which will appear in the machine instruction) should be added to the + /// OutOps vector. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps) { + return true; + } + + /// IsProfitableToFold - Returns true if it's profitable to fold the specific + /// operand node N of U during instruction selection that starts at Root. + virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const; + + /// IsLegalToFold - Returns true if the specific operand node N of + /// U can be folded during instruction selection that starts at Root. + /// FIXME: This is a static member function because the MSP430/SystemZ/X86 + /// targets, which uses it during isel. This could become a proper member. + static bool IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, + CodeGenOpt::Level OptLevel, + bool IgnoreChains = false); + + // Opcodes used by the DAG state machine: + enum BuiltinOpcodes { + OPC_Scope, + OPC_RecordNode, + OPC_RecordChild0, OPC_RecordChild1, OPC_RecordChild2, OPC_RecordChild3, + OPC_RecordChild4, OPC_RecordChild5, OPC_RecordChild6, OPC_RecordChild7, + OPC_RecordMemRef, + OPC_CaptureGlueInput, + OPC_MoveChild, + OPC_MoveParent, + OPC_CheckSame, + OPC_CheckPatternPredicate, + OPC_CheckPredicate, + OPC_CheckOpcode, + OPC_SwitchOpcode, + OPC_CheckType, + OPC_SwitchType, + OPC_CheckChild0Type, OPC_CheckChild1Type, OPC_CheckChild2Type, + OPC_CheckChild3Type, OPC_CheckChild4Type, OPC_CheckChild5Type, + OPC_CheckChild6Type, OPC_CheckChild7Type, + OPC_CheckInteger, + OPC_CheckCondCode, + OPC_CheckValueType, + OPC_CheckComplexPat, + OPC_CheckAndImm, OPC_CheckOrImm, + OPC_CheckFoldableChainNode, + + OPC_EmitInteger, + OPC_EmitRegister, + OPC_EmitRegister2, + OPC_EmitConvertToTarget, + OPC_EmitMergeInputChains, + OPC_EmitMergeInputChains1_0, + OPC_EmitMergeInputChains1_1, + OPC_EmitCopyToReg, + OPC_EmitNodeXForm, + OPC_EmitNode, + OPC_MorphNodeTo, + OPC_MarkGlueResults, + OPC_CompleteMatch + }; + + enum { + OPFL_None = 0, // Node has no chain or glue input and isn't variadic. + OPFL_Chain = 1, // Node has a chain input. + OPFL_GlueInput = 2, // Node has a glue input. + OPFL_GlueOutput = 4, // Node has a glue output. + OPFL_MemRefs = 8, // Node gets accumulated MemRefs. + OPFL_Variadic0 = 1<<4, // Node is variadic, root has 0 fixed inputs. + OPFL_Variadic1 = 2<<4, // Node is variadic, root has 1 fixed inputs. + OPFL_Variadic2 = 3<<4, // Node is variadic, root has 2 fixed inputs. + OPFL_Variadic3 = 4<<4, // Node is variadic, root has 3 fixed inputs. + OPFL_Variadic4 = 5<<4, // Node is variadic, root has 4 fixed inputs. + OPFL_Variadic5 = 6<<4, // Node is variadic, root has 5 fixed inputs. + OPFL_Variadic6 = 7<<4, // Node is variadic, root has 6 fixed inputs. + + OPFL_VariadicInfo = OPFL_Variadic6 + }; + + /// getNumFixedFromVariadicInfo - Transform an EmitNode flags word into the + /// number of fixed arity values that should be skipped when copying from the + /// root. + static inline int getNumFixedFromVariadicInfo(unsigned Flags) { + return ((Flags&OPFL_VariadicInfo) >> 4)-1; + } + + +protected: + /// DAGSize - Size of DAG being instruction selected. + /// + unsigned DAGSize; + + /// ISelPosition - Node iterator marking the current position of + /// instruction selection as it procedes through the topologically-sorted + /// node list. + SelectionDAG::allnodes_iterator ISelPosition; + + + /// ISelUpdater - helper class to handle updates of the + /// instruction selection graph. + class ISelUpdater : public SelectionDAG::DAGUpdateListener { + SelectionDAG::allnodes_iterator &ISelPosition; + public: + explicit ISelUpdater(SelectionDAG::allnodes_iterator &isp) + : ISelPosition(isp) {} + + /// NodeDeleted - Handle nodes deleted from the graph. If the + /// node being deleted is the current ISelPosition node, update + /// ISelPosition. + /// + virtual void NodeDeleted(SDNode *N, SDNode *E) { + if (ISelPosition == SelectionDAG::allnodes_iterator(N)) + ++ISelPosition; + } + + /// NodeUpdated - Ignore updates for now. + virtual void NodeUpdated(SDNode *N) {} + }; + + /// ReplaceUses - replace all uses of the old node F with the use + /// of the new node T. + void ReplaceUses(SDValue F, SDValue T) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesOfValueWith(F, T, &ISU); + } + + /// ReplaceUses - replace all uses of the old nodes F with the use + /// of the new nodes T. + void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISU); + } + + /// ReplaceUses - replace all uses of the old node F with the use + /// of the new node T. + void ReplaceUses(SDNode *F, SDNode *T) { + ISelUpdater ISU(ISelPosition); + CurDAG->ReplaceAllUsesWith(F, T, &ISU); + } + + + /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated + /// by tblgen. Others should not call it. + void SelectInlineAsmMemoryOperands(std::vector &Ops); + + +public: + // Calls to these predicates are generated by tblgen. + bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const; + bool CheckOrMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const; + + + /// CheckPatternPredicate - This function is generated by tblgen in the + /// target. It runs the specified pattern predicate and returns true if it + /// succeeds or false if it fails. The number is a private implementation + /// detail to the code tblgen produces. + virtual bool CheckPatternPredicate(unsigned PredNo) const { + assert(0 && "Tblgen should generate the implementation of this!"); + return 0; + } + + /// CheckNodePredicate - This function is generated by tblgen in the target. + /// It runs node predicate number PredNo and returns true if it succeeds or + /// false if it fails. The number is a private implementation + /// detail to the code tblgen produces. + virtual bool CheckNodePredicate(SDNode *N, unsigned PredNo) const { + assert(0 && "Tblgen should generate the implementation of this!"); + return 0; + } + + virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N, + unsigned PatternNo, + SmallVectorImpl > &Result) { + assert(0 && "Tblgen should generate the implementation of this!"); + return false; + } + + virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { + assert(0 && "Tblgen shoudl generate this!"); + return SDValue(); + } + + SDNode *SelectCodeCommon(SDNode *NodeToMatch, + const unsigned char *MatcherTable, + unsigned TableSize); + +private: + + // Calls to these functions are generated by tblgen. + SDNode *Select_INLINEASM(SDNode *N); + SDNode *Select_UNDEF(SDNode *N); + void CannotYetSelect(SDNode *N); + +private: + void DoInstructionSelection(); + SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo); + + void PrepareEHLandingPad(); + void SelectAllBasicBlocks(const Function &Fn); + bool TryToFoldFastISelLoad(const LoadInst *LI, FastISel *FastIS); + void FinishBasicBlock(); + + void SelectBasicBlock(BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End, + bool &HadTailCall); + void CodeGenAndEmitDAG(); + void LowerArguments(const BasicBlock *BB); + + void ComputeLiveOutVRegInfo(); + + /// Create the scheduler. If a specific scheduler was specified + /// via the SchedulerRegistry, use it, otherwise select the + /// one preferred by the target. + /// + ScheduleDAGSDNodes *CreateScheduler(); + + /// OpcodeOffset - This is a cache used to dispatch efficiently into isel + /// state machines that start with a OPC_SwitchOpcode node. + std::vector OpcodeOffset; + + void UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain, + const SmallVectorImpl &ChainNodesMatched, + SDValue InputGlue, const SmallVectorImpl &F, + bool isMorphNodeTo); + +}; + +} + +#endif /* LLVM_CODEGEN_SELECTIONDAG_ISEL_H */ diff --git a/final/include/llvm/CodeGen/SelectionDAGNodes.h b/final/include/llvm/CodeGen/SelectionDAGNodes.h new file mode 100644 index 00000000000..64546394ce9 --- /dev/null +++ b/final/include/llvm/CodeGen/SelectionDAGNodes.h @@ -0,0 +1,1781 @@ +//===-- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ---*- 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 SDNode class and derived classes, which are used to +// represent the nodes and operations present in a SelectionDAG. These nodes +// and operations are machine code level operations, with some similarities to +// the GCC RTL representation. +// +// Clients should include the SelectionDAG.h file instead of this file directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H +#define LLVM_CODEGEN_SELECTIONDAGNODES_H + +#include "llvm/Constants.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" +#include + +namespace llvm { + +class SelectionDAG; +class GlobalValue; +class MachineBasicBlock; +class MachineConstantPoolValue; +class SDNode; +class Value; +class MCSymbol; +template struct DenseMapInfo; +template struct simplify_type; +template struct ilist_traits; + +void checkForCycles(const SDNode *N); + +/// SDVTList - This represents a list of ValueType's that has been intern'd by +/// a SelectionDAG. Instances of this simple value class are returned by +/// SelectionDAG::getVTList(...). +/// +struct SDVTList { + const EVT *VTs; + unsigned int NumVTs; +}; + +namespace ISD { + /// Node predicates + + /// isBuildVectorAllOnes - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are ~0 or undef. + bool isBuildVectorAllOnes(const SDNode *N); + + /// isBuildVectorAllZeros - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are 0 or undef. + bool isBuildVectorAllZeros(const SDNode *N); + + /// isScalarToVector - Return true if the specified node is a + /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low + /// element is not an undef. + bool isScalarToVector(const SDNode *N); +} // end llvm:ISD namespace + +//===----------------------------------------------------------------------===// +/// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple +/// values as the result of a computation. Many nodes return multiple values, +/// from loads (which define a token and a return value) to ADDC (which returns +/// a result and a carry value), to calls (which may return an arbitrary number +/// of values). +/// +/// As such, each use of a SelectionDAG computation must indicate the node that +/// computes it as well as which return value to use from that node. This pair +/// of information is represented with the SDValue value type. +/// +class SDValue { + SDNode *Node; // The node defining the value we are using. + unsigned ResNo; // Which return value of the node we are using. +public: + SDValue() : Node(0), ResNo(0) {} + SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {} + + /// get the index which selects a specific result in the SDNode + unsigned getResNo() const { return ResNo; } + + /// get the SDNode which holds the desired result + SDNode *getNode() const { return Node; } + + /// set the SDNode + void setNode(SDNode *N) { Node = N; } + + inline SDNode *operator->() const { return Node; } + + bool operator==(const SDValue &O) const { + return Node == O.Node && ResNo == O.ResNo; + } + bool operator!=(const SDValue &O) const { + return !operator==(O); + } + bool operator<(const SDValue &O) const { + return Node < O.Node || (Node == O.Node && ResNo < O.ResNo); + } + + SDValue getValue(unsigned R) const { + return SDValue(Node, R); + } + + // isOperandOf - Return true if this node is an operand of N. + bool isOperandOf(SDNode *N) const; + + /// getValueType - Return the ValueType of the referenced return value. + /// + inline EVT getValueType() const; + + /// getValueSizeInBits - Returns the size of the value in bits. + /// + unsigned getValueSizeInBits() const { + return getValueType().getSizeInBits(); + } + + // Forwarding methods - These forward to the corresponding methods in SDNode. + inline unsigned getOpcode() const; + inline unsigned getNumOperands() const; + inline const SDValue &getOperand(unsigned i) const; + inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetMemoryOpcode() const; + inline bool isTargetOpcode() const; + inline bool isMachineOpcode() const; + inline unsigned getMachineOpcode() const; + inline const DebugLoc getDebugLoc() const; + + + /// reachesChainWithoutSideEffects - Return true if this operand (which must + /// be a chain) reaches the specified operand without crossing any + /// side-effecting instructions. In practice, this looks through token + /// factors and non-volatile loads. In order to remain efficient, this only + /// looks a couple of nodes in, it does not do an exhaustive search. + bool reachesChainWithoutSideEffects(SDValue Dest, + unsigned Depth = 2) const; + + /// use_empty - Return true if there are no nodes using value ResNo + /// of Node. + /// + inline bool use_empty() const; + + /// hasOneUse - Return true if there is exactly one node using value + /// ResNo of Node. + /// + inline bool hasOneUse() const; +}; + + +template<> struct DenseMapInfo { + static inline SDValue getEmptyKey() { + return SDValue((SDNode*)-1, -1U); + } + static inline SDValue getTombstoneKey() { + return SDValue((SDNode*)-1, 0); + } + static unsigned getHashValue(const SDValue &Val) { + return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ + (unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo(); + } + static bool isEqual(const SDValue &LHS, const SDValue &RHS) { + return LHS == RHS; + } +}; +template <> struct isPodLike { static const bool value = true; }; + + +/// simplify_type specializations - Allow casting operators to work directly on +/// SDValues as if they were SDNode*'s. +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDValue &Val) { + return static_cast(Val.getNode()); + } +}; +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDValue &Val) { + return static_cast(Val.getNode()); + } +}; + +/// SDUse - Represents a use of a SDNode. This class holds an SDValue, +/// which records the SDNode being used and the result number, a +/// pointer to the SDNode using the value, and Next and Prev pointers, +/// which link together all the uses of an SDNode. +/// +class SDUse { + /// Val - The value being used. + SDValue Val; + /// User - The user of this value. + SDNode *User; + /// Prev, Next - Pointers to the uses list of the SDNode referred by + /// this operand. + SDUse **Prev, *Next; + + SDUse(const SDUse &U); // Do not implement + void operator=(const SDUse &U); // Do not implement + +public: + SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {} + + /// Normally SDUse will just implicitly convert to an SDValue that it holds. + operator const SDValue&() const { return Val; } + + /// If implicit conversion to SDValue doesn't work, the get() method returns + /// the SDValue. + const SDValue &get() const { return Val; } + + /// getUser - This returns the SDNode that contains this Use. + SDNode *getUser() { return User; } + + /// getNext - Get the next SDUse in the use list. + SDUse *getNext() const { return Next; } + + /// getNode - Convenience function for get().getNode(). + SDNode *getNode() const { return Val.getNode(); } + /// getResNo - Convenience function for get().getResNo(). + unsigned getResNo() const { return Val.getResNo(); } + /// getValueType - Convenience function for get().getValueType(). + EVT getValueType() const { return Val.getValueType(); } + + /// operator== - Convenience function for get().operator== + bool operator==(const SDValue &V) const { + return Val == V; + } + + /// operator!= - Convenience function for get().operator!= + bool operator!=(const SDValue &V) const { + return Val != V; + } + + /// operator< - Convenience function for get().operator< + bool operator<(const SDValue &V) const { + return Val < V; + } + +private: + friend class SelectionDAG; + friend class SDNode; + + void setUser(SDNode *p) { User = p; } + + /// set - Remove this use from its existing use list, assign it the + /// given value, and add it to the new value's node's use list. + inline void set(const SDValue &V); + /// setInitial - like set, but only supports initializing a newly-allocated + /// SDUse with a non-null value. + inline void setInitial(const SDValue &V); + /// setNode - like set, but only sets the Node portion of the value, + /// leaving the ResNo portion unmodified. + inline void setNode(SDNode *N); + + void addToList(SDUse **List) { + Next = *List; + if (Next) Next->Prev = &Next; + Prev = List; + *List = this; + } + + void removeFromList() { + *Prev = Next; + if (Next) Next->Prev = Prev; + } +}; + +/// simplify_type specializations - Allow casting operators to work directly on +/// SDValues as if they were SDNode*'s. +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDUse &Val) { + return static_cast(Val.getNode()); + } +}; +template<> struct simplify_type { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDUse &Val) { + return static_cast(Val.getNode()); + } +}; + + +/// SDNode - Represents one node in the SelectionDAG. +/// +class SDNode : public FoldingSetNode, public ilist_node { +private: + /// NodeType - The operation that this node performs. + /// + int16_t NodeType; + + /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, + /// then they will be delete[]'d when the node is destroyed. + uint16_t OperandsNeedDelete : 1; + + /// HasDebugValue - This tracks whether this node has one or more dbg_value + /// nodes corresponding to it. + uint16_t HasDebugValue : 1; + +protected: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + uint16_t SubclassData : 14; + +private: + /// NodeId - Unique id per SDNode in the DAG. + int NodeId; + + /// OperandList - The values that are used by this operation. + /// + SDUse *OperandList; + + /// ValueList - The types of the values this node defines. SDNode's may + /// define multiple values simultaneously. + const EVT *ValueList; + + /// UseList - List of uses for this SDNode. + SDUse *UseList; + + /// NumOperands/NumValues - The number of entries in the Operand/Value list. + unsigned short NumOperands, NumValues; + + /// debugLoc - source line information. + DebugLoc debugLoc; + + /// getValueTypeList - Return a pointer to the specified value type. + static const EVT *getValueTypeList(EVT VT); + + friend class SelectionDAG; + friend struct ilist_traits; + +public: + //===--------------------------------------------------------------------===// + // Accessors + // + + /// getOpcode - Return the SelectionDAG opcode value for this node. For + /// pre-isel nodes (those for which isMachineOpcode returns false), these + /// are the opcode values in the ISD and ISD namespaces. For + /// post-isel opcodes, see getMachineOpcode. + unsigned getOpcode() const { return (unsigned short)NodeType; } + + /// isTargetOpcode - Test if this node has a target-specific opcode (in the + /// \ISD namespace). + bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + + /// isTargetMemoryOpcode - Test if this node has a target-specific + /// memory-referencing opcode (in the \ISD namespace and + /// greater than FIRST_TARGET_MEMORY_OPCODE). + bool isTargetMemoryOpcode() const { + return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; + } + + /// isMachineOpcode - Test if this node has a post-isel opcode, directly + /// corresponding to a MachineInstr opcode. + bool isMachineOpcode() const { return NodeType < 0; } + + /// getMachineOpcode - This may only be called if isMachineOpcode returns + /// true. It returns the MachineInstr opcode value that the node's opcode + /// corresponds to. + unsigned getMachineOpcode() const { + assert(isMachineOpcode() && "Not a MachineInstr opcode!"); + return ~NodeType; + } + + /// getHasDebugValue - get this bit. + bool getHasDebugValue() const { return HasDebugValue; } + + /// setHasDebugValue - set this bit. + void setHasDebugValue(bool b) { HasDebugValue = b; } + + /// use_empty - Return true if there are no uses of this node. + /// + bool use_empty() const { return UseList == NULL; } + + /// hasOneUse - Return true if there is exactly one use of this node. + /// + bool hasOneUse() const { + return !use_empty() && llvm::next(use_begin()) == use_end(); + } + + /// use_size - Return the number of uses of this node. This method takes + /// time proportional to the number of uses. + /// + size_t use_size() const { return std::distance(use_begin(), use_end()); } + + /// getNodeId - Return the unique node id. + /// + int getNodeId() const { return NodeId; } + + /// setNodeId - Set unique node id. + void setNodeId(int Id) { NodeId = Id; } + + /// getDebugLoc - Return the source location info. + const DebugLoc getDebugLoc() const { return debugLoc; } + + /// setDebugLoc - Set source location info. Try to avoid this, putting + /// it in the constructor is preferable. + void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + + /// use_iterator - This class provides iterator support for SDUse + /// operands that use a specific SDNode. + class use_iterator + : public std::iterator { + SDUse *Op; + explicit use_iterator(SDUse *op) : Op(op) { + } + friend class SDNode; + public: + typedef std::iterator::reference reference; + typedef std::iterator::pointer pointer; + + use_iterator(const use_iterator &I) : Op(I.Op) {} + use_iterator() : Op(0) {} + + bool operator==(const use_iterator &x) const { + return Op == x.Op; + } + bool operator!=(const use_iterator &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is at the end of uses list. + bool atEnd() const { return Op == 0; } + + // Iterator traversal: forward iteration only. + use_iterator &operator++() { // Preincrement + assert(Op && "Cannot increment end iterator!"); + Op = Op->getNext(); + return *this; + } + + use_iterator operator++(int) { // Postincrement + use_iterator tmp = *this; ++*this; return tmp; + } + + /// Retrieve a pointer to the current user node. + SDNode *operator*() const { + assert(Op && "Cannot dereference end iterator!"); + return Op->getUser(); + } + + SDNode *operator->() const { return operator*(); } + + SDUse &getUse() const { return *Op; } + + /// getOperandNo - Retrieve the operand # of this use in its user. + /// + unsigned getOperandNo() const { + assert(Op && "Cannot dereference end iterator!"); + return (unsigned)(Op - Op->getUser()->OperandList); + } + }; + + /// use_begin/use_end - Provide iteration support to walk over all uses + /// of an SDNode. + + use_iterator use_begin() const { + return use_iterator(UseList); + } + + static use_iterator use_end() { return use_iterator(0); } + + + /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the + /// indicated value. This method ignores uses of other values defined by this + /// operation. + bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; + + /// hasAnyUseOfValue - Return true if there are any use of the indicated + /// value. This method ignores uses of other values defined by this operation. + bool hasAnyUseOfValue(unsigned Value) const; + + /// isOnlyUserOf - Return true if this node is the only use of N. + /// + bool isOnlyUserOf(SDNode *N) const; + + /// isOperandOf - Return true if this node is an operand of N. + /// + bool isOperandOf(SDNode *N) const; + + /// isPredecessorOf - Return true if this node is a predecessor of N. This + /// node is either an operand of N or it can be reached by recursively + /// traversing up the operands. + /// NOTE: this is an expensive method. Use it carefully. + bool isPredecessorOf(SDNode *N) const; + + /// getNumOperands - Return the number of values used by this operation. + /// + unsigned getNumOperands() const { return NumOperands; } + + /// getConstantOperandVal - Helper method returns the integer value of a + /// ConstantSDNode operand. + uint64_t getConstantOperandVal(unsigned Num) const; + + const SDValue &getOperand(unsigned Num) const { + assert(Num < NumOperands && "Invalid child # of SDNode!"); + return OperandList[Num]; + } + + typedef SDUse* op_iterator; + op_iterator op_begin() const { return OperandList; } + op_iterator op_end() const { return OperandList+NumOperands; } + + SDVTList getVTList() const { + SDVTList X = { ValueList, NumValues }; + return X; + } + + /// getGluedNode - If this node has a glue operand, return the node + /// to which the glue operand points. Otherwise return NULL. + SDNode *getGluedNode() const { + if (getNumOperands() != 0 && + getOperand(getNumOperands()-1).getValueType() == MVT::Glue) + return getOperand(getNumOperands()-1).getNode(); + return 0; + } + + // If this is a pseudo op, like copyfromreg, look to see if there is a + // real target node glued to it. If so, return the target node. + const SDNode *getGluedMachineNode() const { + const SDNode *FoundNode = this; + + // Climb up glue edges until a machine-opcode node is found, or the + // end of the chain is reached. + while (!FoundNode->isMachineOpcode()) { + const SDNode *N = FoundNode->getGluedNode(); + if (!N) break; + FoundNode = N; + } + + return FoundNode; + } + + /// getGluedUser - If this node has a glue value with a user, return + /// the user (there is at most one). Otherwise return NULL. + SDNode *getGluedUser() const { + for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) + if (UI.getUse().get().getValueType() == MVT::Glue) + return *UI; + return 0; + } + + /// getNumValues - Return the number of values defined/returned by this + /// operator. + /// + unsigned getNumValues() const { return NumValues; } + + /// getValueType - Return the type of a specified result. + /// + EVT getValueType(unsigned ResNo) const { + assert(ResNo < NumValues && "Illegal result number!"); + return ValueList[ResNo]; + } + + /// getValueSizeInBits - Returns MVT::getSizeInBits(getValueType(ResNo)). + /// + unsigned getValueSizeInBits(unsigned ResNo) const { + return getValueType(ResNo).getSizeInBits(); + } + + typedef const EVT* value_iterator; + value_iterator value_begin() const { return ValueList; } + value_iterator value_end() const { return ValueList+NumValues; } + + /// getOperationName - Return the opcode of this operation for printing. + /// + std::string getOperationName(const SelectionDAG *G = 0) const; + static const char* getIndexedModeName(ISD::MemIndexedMode AM); + void print_types(raw_ostream &OS, const SelectionDAG *G) const; + void print_details(raw_ostream &OS, const SelectionDAG *G) const; + void print(raw_ostream &OS, const SelectionDAG *G = 0) const; + void printr(raw_ostream &OS, const SelectionDAG *G = 0) const; + + /// printrFull - Print a SelectionDAG node and all children down to + /// the leaves. The given SelectionDAG allows target-specific nodes + /// to be printed in human-readable form. Unlike printr, this will + /// print the whole DAG, including children that appear multiple + /// times. + /// + void printrFull(raw_ostream &O, const SelectionDAG *G = 0) const; + + /// printrWithDepth - Print a SelectionDAG node and children up to + /// depth "depth." The given SelectionDAG allows target-specific + /// nodes to be printed in human-readable form. Unlike printr, this + /// will print children that appear multiple times wherever they are + /// used. + /// + void printrWithDepth(raw_ostream &O, const SelectionDAG *G = 0, + unsigned depth = 100) const; + + + /// dump - Dump this node, for debugging. + void dump() const; + + /// dumpr - Dump (recursively) this node and its use-def subgraph. + void dumpr() const; + + /// dump - Dump this node, for debugging. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. + void dump(const SelectionDAG *G) const; + + /// dumpr - Dump (recursively) this node and its use-def subgraph. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. + void dumpr(const SelectionDAG *G) const; + + /// dumprFull - printrFull to dbgs(). The given SelectionDAG allows + /// target-specific nodes to be printed in human-readable form. + /// Unlike dumpr, this will print the whole DAG, including children + /// that appear multiple times. + /// + void dumprFull(const SelectionDAG *G = 0) const; + + /// dumprWithDepth - printrWithDepth to dbgs(). The given + /// SelectionDAG allows target-specific nodes to be printed in + /// human-readable form. Unlike dumpr, this will print children + /// that appear multiple times wherever they are used. + /// + void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const; + + + static bool classof(const SDNode *) { return true; } + + /// Profile - Gather unique data for the node. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// addUse - This method should only be used by the SDUse class. + /// + void addUse(SDUse &U) { U.addToList(&UseList); } + +protected: + static SDVTList getSDVTList(EVT VT) { + SDVTList Ret = { getValueTypeList(VT), 1 }; + return Ret; + } + + SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops, + unsigned NumOps) + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), + OperandList(NumOps ? new SDUse[NumOps] : 0), + ValueList(VTs.VTs), UseList(NULL), + NumOperands(NumOps), NumValues(VTs.NumVTs), + debugLoc(dl) { + for (unsigned i = 0; i != NumOps; ++i) { + OperandList[i].setUser(this); + OperandList[i].setInitial(Ops[i]); + } + checkForCycles(this); + } + + /// This constructor adds no operands itself; operands can be + /// set later with InitOperands. + SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs) + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(0), ValueList(VTs.VTs), + UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs), + debugLoc(dl) {} + + /// InitOperands - Initialize the operands list of this with 1 operand. + void InitOperands(SDUse *Ops, const SDValue &Op0) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + NumOperands = 1; + OperandList = Ops; + checkForCycles(this); + } + + /// InitOperands - Initialize the operands list of this with 2 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + NumOperands = 2; + OperandList = Ops; + checkForCycles(this); + } + + /// InitOperands - Initialize the operands list of this with 3 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + NumOperands = 3; + OperandList = Ops; + checkForCycles(this); + } + + /// InitOperands - Initialize the operands list of this with 4 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2, const SDValue &Op3) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + Ops[3].setUser(this); + Ops[3].setInitial(Op3); + NumOperands = 4; + OperandList = Ops; + checkForCycles(this); + } + + /// InitOperands - Initialize the operands list of this with N operands. + void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) { + for (unsigned i = 0; i != N; ++i) { + Ops[i].setUser(this); + Ops[i].setInitial(Vals[i]); + } + NumOperands = N; + OperandList = Ops; + checkForCycles(this); + } + + /// DropOperands - Release the operands and set this node to have + /// zero operands. + void DropOperands(); +}; + + +// Define inline functions from the SDValue class. + +inline unsigned SDValue::getOpcode() const { + return Node->getOpcode(); +} +inline EVT SDValue::getValueType() const { + return Node->getValueType(ResNo); +} +inline unsigned SDValue::getNumOperands() const { + return Node->getNumOperands(); +} +inline const SDValue &SDValue::getOperand(unsigned i) const { + return Node->getOperand(i); +} +inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { + return Node->getConstantOperandVal(i); +} +inline bool SDValue::isTargetOpcode() const { + return Node->isTargetOpcode(); +} +inline bool SDValue::isTargetMemoryOpcode() const { + return Node->isTargetMemoryOpcode(); +} +inline bool SDValue::isMachineOpcode() const { + return Node->isMachineOpcode(); +} +inline unsigned SDValue::getMachineOpcode() const { + return Node->getMachineOpcode(); +} +inline bool SDValue::use_empty() const { + return !Node->hasAnyUseOfValue(ResNo); +} +inline bool SDValue::hasOneUse() const { + return Node->hasNUsesOfValue(1, ResNo); +} +inline const DebugLoc SDValue::getDebugLoc() const { + return Node->getDebugLoc(); +} + +// Define inline functions from the SDUse class. + +inline void SDUse::set(const SDValue &V) { + if (Val.getNode()) removeFromList(); + Val = V; + if (V.getNode()) V.getNode()->addUse(*this); +} + +inline void SDUse::setInitial(const SDValue &V) { + Val = V; + V.getNode()->addUse(*this); +} + +inline void SDUse::setNode(SDNode *N) { + if (Val.getNode()) removeFromList(); + Val.setNode(N); + if (N) N->addUse(*this); +} + +/// UnarySDNode - This class is used for single-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class UnarySDNode : public SDNode { + SDUse Op; +public: + UnarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X) + : SDNode(Opc, dl, VTs) { + InitOperands(&Op, X); + } +}; + +/// BinarySDNode - This class is used for two-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class BinarySDNode : public SDNode { + SDUse Ops[2]; +public: + BinarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y) + : SDNode(Opc, dl, VTs) { + InitOperands(Ops, X, Y); + } +}; + +/// TernarySDNode - This class is used for three-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class TernarySDNode : public SDNode { + SDUse Ops[3]; +public: + TernarySDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, SDValue X, SDValue Y, + SDValue Z) + : SDNode(Opc, dl, VTs) { + InitOperands(Ops, X, Y, Z); + } +}; + + +/// HandleSDNode - This class is used to form a handle around another node that +/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// operand. This node should be directly created by end-users and not added to +/// the AllNodes list. +class HandleSDNode : public SDNode { + SDUse Op; +public: + // FIXME: Remove the "noinline" attribute once is + // fixed. +#if __GNUC__==4 && __GNUC_MINOR__==2 && defined(__APPLE__) && !defined(__llvm__) + explicit __attribute__((__noinline__)) HandleSDNode(SDValue X) +#else + explicit HandleSDNode(SDValue X) +#endif + : SDNode(ISD::HANDLENODE, DebugLoc(), getSDVTList(MVT::Other)) { + InitOperands(&Op, X); + } + ~HandleSDNode(); + const SDValue &getValue() const { return Op; } +}; + +/// Abstact virtual class for operations for memory operations +class MemSDNode : public SDNode { +private: + // MemoryVT - VT of in-memory value. + EVT MemoryVT; + +protected: + /// MMO - Memory reference information. + MachineMemOperand *MMO; + +public: + MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, + MachineMemOperand *MMO); + + MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, + unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + + bool readMem() const { return MMO->isLoad(); } + bool writeMem() const { return MMO->isStore(); } + + /// Returns alignment and volatility of the memory access + unsigned getOriginalAlignment() const { + return MMO->getBaseAlignment(); + } + unsigned getAlignment() const { + return MMO->getAlignment(); + } + + /// getRawSubclassData - Return the SubclassData value, which contains an + /// encoding of the volatile flag, as well as bits used by subclasses. This + /// function should only be used to compute a FoldingSetNodeID value. + unsigned getRawSubclassData() const { + return SubclassData; + } + + // We access subclass data here so that we can check consistency + // with MachineMemOperand information. + bool isVolatile() const { return (SubclassData >> 5) & 1; } + bool isNonTemporal() const { return (SubclassData >> 6) & 1; } + + /// Returns the SrcValue and offset that describes the location of the access + const Value *getSrcValue() const { return MMO->getValue(); } + int64_t getSrcValueOffset() const { return MMO->getOffset(); } + + /// Returns the TBAAInfo that describes the dereference. + const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); } + + /// getMemoryVT - Return the type of the in-memory value. + EVT getMemoryVT() const { return MemoryVT; } + + /// getMemOperand - Return a MachineMemOperand object describing the memory + /// reference performed by operation. + MachineMemOperand *getMemOperand() const { return MMO; } + + const MachinePointerInfo &getPointerInfo() const { + return MMO->getPointerInfo(); + } + + /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// to reflect the alignment of NewMMO, if it has a greater alignment. + /// This must only be used when the new alignment applies to all users of + /// this MachineMemOperand. + void refineAlignment(const MachineMemOperand *NewMMO) { + MMO->refineAlignment(NewMMO); + } + + const SDValue &getChain() const { return getOperand(0); } + const SDValue &getBasePtr() const { + return getOperand(getOpcode() == ISD::STORE ? 2 : 1); + } + + // Methods to support isa and dyn_cast + static bool classof(const MemSDNode *) { return true; } + static bool classof(const SDNode *N) { + // For some targets, we lower some target intrinsics to a MemIntrinsicNode + // with either an intrinsic or a target opcode. + return N->getOpcode() == ISD::LOAD || + N->getOpcode() == ISD::STORE || + N->getOpcode() == ISD::PREFETCH || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_SWAP || + N->getOpcode() == ISD::ATOMIC_LOAD_ADD || + N->getOpcode() == ISD::ATOMIC_LOAD_SUB || + N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_OR || + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || + N->getOpcode() == ISD::ATOMIC_LOAD_NAND || + N->getOpcode() == ISD::ATOMIC_LOAD_MIN || + N->getOpcode() == ISD::ATOMIC_LOAD_MAX || + N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || + N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || + N->isTargetMemoryOpcode(); + } +}; + +/// AtomicSDNode - A SDNode reprenting atomic operations. +/// +class AtomicSDNode : public MemSDNode { + SDUse Ops[4]; + +public: + // Opc: opcode for atomic + // VTL: value type list + // Chain: memory chain for operaand + // Ptr: address to update as a SDValue + // Cmp: compare value + // Swp: swap value + // SrcVal: address to update as a Value (used for MemOperand) + // Align: alignment of memory + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue Chain, SDValue Ptr, + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitOperands(Ops, Chain, Ptr, Cmp, Swp); + } + AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, + SDValue Chain, SDValue Ptr, + SDValue Val, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); + InitOperands(Ops, Chain, Ptr, Val); + } + + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getVal() const { return getOperand(2); } + + bool isCompareAndSwap() const { + unsigned Op = getOpcode(); + return Op == ISD::ATOMIC_CMP_SWAP; + } + + // Methods to support isa and dyn_cast + static bool classof(const AtomicSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_SWAP || + N->getOpcode() == ISD::ATOMIC_LOAD_ADD || + N->getOpcode() == ISD::ATOMIC_LOAD_SUB || + N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_OR || + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || + N->getOpcode() == ISD::ATOMIC_LOAD_NAND || + N->getOpcode() == ISD::ATOMIC_LOAD_MIN || + N->getOpcode() == ISD::ATOMIC_LOAD_MAX || + N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || + N->getOpcode() == ISD::ATOMIC_LOAD_UMAX; + } +}; + +/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// memory and need an associated MachineMemOperand. Its opcode may be +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode +/// with a value not less than FIRST_TARGET_MEMORY_OPCODE. +class MemIntrinsicSDNode : public MemSDNode { +public: + MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, + EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { + } + + // Methods to support isa and dyn_cast + static bool classof(const MemIntrinsicSDNode *) { return true; } + static bool classof(const SDNode *N) { + // We lower some target intrinsics to their target opcode + // early a node with a target opcode can be of this class + return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || + N->getOpcode() == ISD::INTRINSIC_VOID || + N->getOpcode() == ISD::PREFETCH || + N->isTargetMemoryOpcode(); + } +}; + +/// ShuffleVectorSDNode - This SDNode is used to implement the code generator +/// support for the llvm IR shufflevector instruction. It combines elements +/// from two input vectors into a new input vector, with the selection and +/// ordering of elements determined by an array of integers, referred to as +/// the shuffle mask. For input vectors of width N, mask indices of 0..N-1 +/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS. +/// An index of -1 is treated as undef, such that the code generator may put +/// any value in the corresponding element of the result. +class ShuffleVectorSDNode : public SDNode { + SDUse Ops[2]; + + // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and + // is freed when the SelectionDAG object is destroyed. + const int *Mask; +protected: + friend class SelectionDAG; + ShuffleVectorSDNode(EVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *M) + : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { + InitOperands(Ops, N1, N2); + } +public: + + void getMask(SmallVectorImpl &M) const { + EVT VT = getValueType(0); + M.clear(); + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) + M.push_back(Mask[i]); + } + int getMaskElt(unsigned Idx) const { + assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); + return Mask[Idx]; + } + + bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } + int getSplatIndex() const { + assert(isSplat() && "Cannot get splat index for non-splat!"); + EVT VT = getValueType(0); + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + if (Mask[i] != -1) + return Mask[i]; + } + return -1; + } + static bool isSplatMask(const int *Mask, EVT VT); + + static bool classof(const ShuffleVectorSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VECTOR_SHUFFLE; + } +}; + +class ConstantSDNode : public SDNode { + const ConstantInt *Value; + friend class SelectionDAG; + ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, + DebugLoc(), getSDVTList(VT)), Value(val) { + } +public: + + const ConstantInt *getConstantIntValue() const { return Value; } + const APInt &getAPIntValue() const { return Value->getValue(); } + uint64_t getZExtValue() const { return Value->getZExtValue(); } + int64_t getSExtValue() const { return Value->getSExtValue(); } + + bool isOne() const { return Value->isOne(); } + bool isNullValue() const { return Value->isNullValue(); } + bool isAllOnesValue() const { return Value->isAllOnesValue(); } + + static bool classof(const ConstantSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Constant || + N->getOpcode() == ISD::TargetConstant; + } +}; + +class ConstantFPSDNode : public SDNode { + const ConstantFP *Value; + friend class SelectionDAG; + ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, + DebugLoc(), getSDVTList(VT)), Value(val) { + } +public: + + const APFloat& getValueAPF() const { return Value->getValueAPF(); } + const ConstantFP *getConstantFPValue() const { return Value; } + + /// isZero - Return true if the value is positive or negative zero. + bool isZero() const { return Value->isZero(); } + + /// isNaN - Return true if the value is a NaN. + bool isNaN() const { return Value->isNaN(); } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. + + /// We leave the version with the double argument here because it's just so + /// convenient to write "2.0" and the like. Without this function we'd + /// have to duplicate its logic everywhere it's called. + bool isExactlyValue(double V) const { + bool ignored; + // convert is not supported on this type + if (&Value->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble) + return false; + APFloat Tmp(V); + Tmp.convert(Value->getValueAPF().getSemantics(), + APFloat::rmNearestTiesToEven, &ignored); + return isExactlyValue(Tmp); + } + bool isExactlyValue(const APFloat& V) const; + + static bool isValueValidForType(EVT VT, const APFloat& Val); + + static bool classof(const ConstantFPSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantFP || + N->getOpcode() == ISD::TargetConstantFP; + } +}; + +class GlobalAddressSDNode : public SDNode { + const GlobalValue *TheGlobal; + int64_t Offset; + unsigned char TargetFlags; + friend class SelectionDAG; + GlobalAddressSDNode(unsigned Opc, DebugLoc DL, const GlobalValue *GA, EVT VT, + int64_t o, unsigned char TargetFlags); +public: + + const GlobalValue *getGlobal() const { return TheGlobal; } + int64_t getOffset() const { return Offset; } + unsigned char getTargetFlags() const { return TargetFlags; } + // Return the address space this GlobalAddress belongs to. + unsigned getAddressSpace() const; + + static bool classof(const GlobalAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::GlobalAddress || + N->getOpcode() == ISD::TargetGlobalAddress || + N->getOpcode() == ISD::GlobalTLSAddress || + N->getOpcode() == ISD::TargetGlobalTLSAddress; + } +}; + +class FrameIndexSDNode : public SDNode { + int FI; + friend class SelectionDAG; + FrameIndexSDNode(int fi, EVT VT, bool isTarg) + : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, + DebugLoc(), getSDVTList(VT)), FI(fi) { + } +public: + + int getIndex() const { return FI; } + + static bool classof(const FrameIndexSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::FrameIndex || + N->getOpcode() == ISD::TargetFrameIndex; + } +}; + +class JumpTableSDNode : public SDNode { + int JTI; + unsigned char TargetFlags; + friend class SelectionDAG; + JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) + : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, + DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { + } +public: + + int getIndex() const { return JTI; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const JumpTableSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::JumpTable || + N->getOpcode() == ISD::TargetJumpTable; + } +}; + +class ConstantPoolSDNode : public SDNode { + union { + const Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + int Offset; // It's a MachineConstantPoolValue if top bit is set. + unsigned Alignment; // Minimum alignment requirement of CP (not log2 value). + unsigned char TargetFlags; + friend class SelectionDAG; + ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, + unsigned Align, unsigned char TF) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + DebugLoc(), + getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.ConstVal = c; + } + ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, + EVT VT, int o, unsigned Align, unsigned char TF) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + DebugLoc(), + getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.MachineCPVal = v; + Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1); + } +public: + + + bool isMachineConstantPoolEntry() const { + return (int)Offset < 0; + } + + const Constant *getConstVal() const { + assert(!isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.ConstVal; + } + + MachineConstantPoolValue *getMachineCPVal() const { + assert(isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.MachineCPVal; + } + + int getOffset() const { + return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); + } + + // Return the alignment of this constant pool object, which is either 0 (for + // default alignment) or the desired value. + unsigned getAlignment() const { return Alignment; } + unsigned char getTargetFlags() const { return TargetFlags; } + + const Type *getType() const; + + static bool classof(const ConstantPoolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantPool || + N->getOpcode() == ISD::TargetConstantPool; + } +}; + +class BasicBlockSDNode : public SDNode { + MachineBasicBlock *MBB; + friend class SelectionDAG; + /// Debug info is meaningful and potentially useful here, but we create + /// blocks out of order when they're jumped to, which makes it a bit + /// harder. Let's see if we need it first. + explicit BasicBlockSDNode(MachineBasicBlock *mbb) + : SDNode(ISD::BasicBlock, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) { + } +public: + + MachineBasicBlock *getBasicBlock() const { return MBB; } + + static bool classof(const BasicBlockSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BasicBlock; + } +}; + +/// BuildVectorSDNode - A "pseudo-class" with methods for operating on +/// BUILD_VECTORs. +class BuildVectorSDNode : public SDNode { + // These are constructed as SDNodes and then cast to BuildVectorSDNodes. + explicit BuildVectorSDNode(); // Do not implement +public: + /// isConstantSplat - Check if this is a constant splat, and if so, find the + /// smallest element size that splats the vector. If MinSplatBits is + /// nonzero, the element size must be at least that large. Note that the + /// splat element may be the entire vector (i.e., a one element vector). + /// Returns the splat element value in SplatValue. Any undefined bits in + /// that value are zero, and the corresponding bits in the SplatUndef mask + /// are set. The SplatBitSize value is set to the splat element size in + /// bits. HasAnyUndefs is set to true if any bits in the vector are + /// undefined. isBigEndian describes the endianness of the target. + bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, + unsigned &SplatBitSize, bool &HasAnyUndefs, + unsigned MinSplatBits = 0, bool isBigEndian = false); + + static inline bool classof(const BuildVectorSDNode *) { return true; } + static inline bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BUILD_VECTOR; + } +}; + +/// SrcValueSDNode - An SDNode that holds an arbitrary LLVM IR Value. This is +/// used when the SelectionDAG needs to make a simple reference to something +/// in the LLVM IR representation. +/// +class SrcValueSDNode : public SDNode { + const Value *V; + friend class SelectionDAG; + /// Create a SrcValue for a general value. + explicit SrcValueSDNode(const Value *v) + : SDNode(ISD::SRCVALUE, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} + +public: + /// getValue - return the contained Value. + const Value *getValue() const { return V; } + + static bool classof(const SrcValueSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::SRCVALUE; + } +}; + +class MDNodeSDNode : public SDNode { + const MDNode *MD; + friend class SelectionDAG; + explicit MDNodeSDNode(const MDNode *md) + : SDNode(ISD::MDNODE_SDNODE, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {} +public: + + const MDNode *getMD() const { return MD; } + + static bool classof(const MDNodeSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MDNODE_SDNODE; + } +}; + + +class RegisterSDNode : public SDNode { + unsigned Reg; + friend class SelectionDAG; + RegisterSDNode(unsigned reg, EVT VT) + : SDNode(ISD::Register, DebugLoc(), getSDVTList(VT)), Reg(reg) { + } +public: + + unsigned getReg() const { return Reg; } + + static bool classof(const RegisterSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Register; + } +}; + +class BlockAddressSDNode : public SDNode { + const BlockAddress *BA; + unsigned char TargetFlags; + friend class SelectionDAG; + BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, + unsigned char Flags) + : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), + BA(ba), TargetFlags(Flags) { + } +public: + const BlockAddress *getBlockAddress() const { return BA; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const BlockAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BlockAddress || + N->getOpcode() == ISD::TargetBlockAddress; + } +}; + +class EHLabelSDNode : public SDNode { + SDUse Chain; + MCSymbol *Label; + friend class SelectionDAG; + EHLabelSDNode(DebugLoc dl, SDValue ch, MCSymbol *L) + : SDNode(ISD::EH_LABEL, dl, getSDVTList(MVT::Other)), Label(L) { + InitOperands(&Chain, ch); + } +public: + MCSymbol *getLabel() const { return Label; } + + static bool classof(const EHLabelSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::EH_LABEL; + } +}; + +class ExternalSymbolSDNode : public SDNode { + const char *Symbol; + unsigned char TargetFlags; + + friend class SelectionDAG; + ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) + : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, + DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { + } +public: + + const char *getSymbol() const { return Symbol; } + unsigned char getTargetFlags() const { return TargetFlags; } + + static bool classof(const ExternalSymbolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ExternalSymbol || + N->getOpcode() == ISD::TargetExternalSymbol; + } +}; + +class CondCodeSDNode : public SDNode { + ISD::CondCode Condition; + friend class SelectionDAG; + explicit CondCodeSDNode(ISD::CondCode Cond) + : SDNode(ISD::CONDCODE, DebugLoc(), getSDVTList(MVT::Other)), + Condition(Cond) { + } +public: + + ISD::CondCode get() const { return Condition; } + + static bool classof(const CondCodeSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::CONDCODE; + } +}; + +/// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the +/// future and most targets don't support it. +class CvtRndSatSDNode : public SDNode { + ISD::CvtCode CvtCode; + friend class SelectionDAG; + explicit CvtRndSatSDNode(EVT VT, DebugLoc dl, const SDValue *Ops, + unsigned NumOps, ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps), + CvtCode(Code) { + assert(NumOps == 5 && "wrong number of operations"); + } +public: + ISD::CvtCode getCvtCode() const { return CvtCode; } + + static bool classof(const CvtRndSatSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::CONVERT_RNDSAT; + } +}; + +/// VTSDNode - This class is used to represent EVT's, which are used +/// to parameterize some operations. +class VTSDNode : public SDNode { + EVT ValueType; + friend class SelectionDAG; + explicit VTSDNode(EVT VT) + : SDNode(ISD::VALUETYPE, DebugLoc(), getSDVTList(MVT::Other)), + ValueType(VT) { + } +public: + + EVT getVT() const { return ValueType; } + + static bool classof(const VTSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VALUETYPE; + } +}; + +/// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode +/// +class LSBaseSDNode : public MemSDNode { + //! Operand array for load and store + /*! + \note Moving this array to the base class captures more + common functionality shared between LoadSDNode and + StoreSDNode + */ + SDUse Ops[4]; +public: + LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, + unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, + EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { + SubclassData |= AM << 2; + assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); + InitOperands(Ops, Operands, numOperands); + assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) && + "Only indexed loads and stores have a non-undef offset operand"); + } + + const SDValue &getOffset() const { + return getOperand(getOpcode() == ISD::LOAD ? 2 : 3); + } + + /// getAddressingMode - Return the addressing mode for this load or store: + /// unindexed, pre-inc, pre-dec, post-inc, or post-dec. + ISD::MemIndexedMode getAddressingMode() const { + return ISD::MemIndexedMode((SubclassData >> 2) & 7); + } + + /// isIndexed - Return true if this is a pre/post inc/dec load/store. + bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; } + + /// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store. + bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; } + + static bool classof(const LSBaseSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LOAD || + N->getOpcode() == ISD::STORE; + } +}; + +/// LoadSDNode - This class is used to represent ISD::LOAD nodes. +/// +class LoadSDNode : public LSBaseSDNode { + friend class SelectionDAG; + LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, + MachineMemOperand *MMO) + : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, + VTs, AM, MemVT, MMO) { + SubclassData |= (unsigned short)ETy; + assert(getExtensionType() == ETy && "LoadExtType encoding error!"); + assert(readMem() && "Load MachineMemOperand is not a load!"); + assert(!writeMem() && "Load MachineMemOperand is a store!"); + } +public: + + /// getExtensionType - Return whether this is a plain node, + /// or one of the varieties of value-extending loads. + ISD::LoadExtType getExtensionType() const { + return ISD::LoadExtType(SubclassData & 3); + } + + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getOffset() const { return getOperand(2); } + + static bool classof(const LoadSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LOAD; + } +}; + +/// StoreSDNode - This class is used to represent ISD::STORE nodes. +/// +class StoreSDNode : public LSBaseSDNode { + friend class SelectionDAG; + StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) + : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, + VTs, AM, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; + assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); + assert(!readMem() && "Store MachineMemOperand is a load!"); + assert(writeMem() && "Store MachineMemOperand is not a store!"); + } +public: + + /// isTruncatingStore - Return true if the op does a truncation before store. + /// For integers this is the same as doing a TRUNCATE and storing the result. + /// For floats, it is the same as doing an FP_ROUND and storing the result. + bool isTruncatingStore() const { return SubclassData & 1; } + + const SDValue &getValue() const { return getOperand(1); } + const SDValue &getBasePtr() const { return getOperand(2); } + const SDValue &getOffset() const { return getOperand(3); } + + static bool classof(const StoreSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::STORE; + } +}; + +/// MachineSDNode - An SDNode that represents everything that will be needed +/// to construct a MachineInstr. These nodes are created during the +/// instruction selection proper phase. +/// +class MachineSDNode : public SDNode { +public: + typedef MachineMemOperand **mmo_iterator; + +private: + friend class SelectionDAG; + MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + + /// LocalOperands - Operands for this instruction, if they fit here. If + /// they don't, this field is unused. + SDUse LocalOperands[4]; + + /// MemRefs - Memory reference descriptions for this instruction. + mmo_iterator MemRefs; + mmo_iterator MemRefsEnd; + +public: + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + + static bool classof(const MachineSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->isMachineOpcode(); + } +}; + +class SDNodeIterator : public std::iterator { + SDNode *Node; + unsigned Operand; + + SDNodeIterator(SDNode *N, unsigned Op) : Node(N), Operand(Op) {} +public: + bool operator==(const SDNodeIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } + + const SDNodeIterator &operator=(const SDNodeIterator &I) { + assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->getOperand(Operand).getNode(); + } + pointer operator->() const { return operator*(); } + + SDNodeIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SDNodeIterator operator++(int) { // Postincrement + SDNodeIterator tmp = *this; ++*this; return tmp; + } + size_t operator-(SDNodeIterator Other) const { + assert(Node == Other.Node && + "Cannot compare iterators of two different nodes!"); + return Operand - Other.Operand; + } + + static SDNodeIterator begin(SDNode *N) { return SDNodeIterator(N, 0); } + static SDNodeIterator end (SDNode *N) { + return SDNodeIterator(N, N->getNumOperands()); + } + + unsigned getOperand() const { return Operand; } + const SDNode *getNode() const { return Node; } +}; + +template <> struct GraphTraits { + typedef SDNode NodeType; + typedef SDNodeIterator ChildIteratorType; + static inline NodeType *getEntryNode(SDNode *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SDNodeIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SDNodeIterator::end(N); + } +}; + +/// LargestSDNode - The largest SDNode class. +/// +typedef LoadSDNode LargestSDNode; + +/// MostAlignedSDNode - The SDNode class with the greatest alignment +/// requirement. +/// +typedef GlobalAddressSDNode MostAlignedSDNode; + +namespace ISD { + /// isNormalLoad - Returns true if the specified node is a non-extending + /// and unindexed load. + inline bool isNormalLoad(const SDNode *N) { + const LoadSDNode *Ld = dyn_cast(N); + return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && + Ld->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNON_EXTLoad - Returns true if the specified node is a non-extending + /// load. + inline bool isNON_EXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::NON_EXTLOAD; + } + + /// isEXTLoad - Returns true if the specified node is a EXTLOAD. + /// + inline bool isEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::EXTLOAD; + } + + /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD. + /// + inline bool isSEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::SEXTLOAD; + } + + /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD. + /// + inline bool isZEXTLoad(const SDNode *N) { + return isa(N) && + cast(N)->getExtensionType() == ISD::ZEXTLOAD; + } + + /// isUNINDEXEDLoad - Returns true if the specified node is an unindexed load. + /// + inline bool isUNINDEXEDLoad(const SDNode *N) { + return isa(N) && + cast(N)->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNormalStore - Returns true if the specified node is a non-truncating + /// and unindexed store. + inline bool isNormalStore(const SDNode *N) { + const StoreSDNode *St = dyn_cast(N); + return St && !St->isTruncatingStore() && + St->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating + /// store. + inline bool isNON_TRUNCStore(const SDNode *N) { + return isa(N) && !cast(N)->isTruncatingStore(); + } + + /// isTRUNCStore - Returns true if the specified node is a truncating + /// store. + inline bool isTRUNCStore(const SDNode *N) { + return isa(N) && cast(N)->isTruncatingStore(); + } + + /// isUNINDEXEDStore - Returns true if the specified node is an + /// unindexed store. + inline bool isUNINDEXEDStore(const SDNode *N) { + return isa(N) && + cast(N)->getAddressingMode() == ISD::UNINDEXED; + } +} + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/SlotIndexes.h b/final/include/llvm/CodeGen/SlotIndexes.h new file mode 100644 index 00000000000..0e2adb58977 --- /dev/null +++ b/final/include/llvm/CodeGen/SlotIndexes.h @@ -0,0 +1,728 @@ +//===- llvm/CodeGen/SlotIndexes.h - Slot indexes representation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements SlotIndex and related classes. The purpuse of SlotIndex +// is to describe a position at which a register can become live, or cease to +// be live. +// +// SlotIndex is mostly a proxy for entries of the SlotIndexList, a class which +// is held is LiveIntervals and provides the real numbering. This allows +// LiveIntervals to perform largely transparent renumbering. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SLOTINDEXES_H +#define LLVM_CODEGEN_SLOTINDEXES_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + + /// This class represents an entry in the slot index list held in the + /// SlotIndexes pass. It should not be used directly. See the + /// SlotIndex & SlotIndexes classes for the public interface to this + /// information. + class IndexListEntry { + IndexListEntry *next, *prev; + MachineInstr *mi; + unsigned index; + + public: + + IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {} + + MachineInstr* getInstr() const { return mi; } + void setInstr(MachineInstr *mi) { + this->mi = mi; + } + + unsigned getIndex() const { return index; } + void setIndex(unsigned index) { + this->index = index; + } + + IndexListEntry* getNext() { return next; } + const IndexListEntry* getNext() const { return next; } + void setNext(IndexListEntry *next) { + this->next = next; + } + + IndexListEntry* getPrev() { return prev; } + const IndexListEntry* getPrev() const { return prev; } + void setPrev(IndexListEntry *prev) { + this->prev = prev; + } + }; + + // Specialize PointerLikeTypeTraits for IndexListEntry. + template <> + class PointerLikeTypeTraits { + public: + static inline void* getAsVoidPointer(IndexListEntry *p) { + return p; + } + static inline IndexListEntry* getFromVoidPointer(void *p) { + return static_cast(p); + } + enum { NumLowBitsAvailable = 3 }; + }; + + /// SlotIndex - An opaque wrapper around machine indexes. + class SlotIndex { + friend class SlotIndexes; + friend struct DenseMapInfo; + + enum Slot { LOAD, USE, DEF, STORE, NUM }; + + PointerIntPair lie; + + SlotIndex(IndexListEntry *entry, unsigned slot) + : lie(entry, slot) {} + + IndexListEntry& entry() const { + assert(isValid() && "Attempt to compare reserved index."); + return *lie.getPointer(); + } + + int getIndex() const { + return entry().getIndex() | getSlot(); + } + + /// Returns the slot for this SlotIndex. + Slot getSlot() const { + return static_cast(lie.getInt()); + } + + static inline unsigned getHashValue(const SlotIndex &v) { + void *ptrVal = v.lie.getOpaqueValue(); + return (unsigned((intptr_t)ptrVal)) ^ (unsigned((intptr_t)ptrVal) >> 9); + } + + public: + enum { + /// The default distance between instructions as returned by distance(). + /// This may vary as instructions are inserted and removed. + InstrDist = 4*NUM + }; + + static inline SlotIndex getEmptyKey() { + return SlotIndex(0, 1); + } + + static inline SlotIndex getTombstoneKey() { + return SlotIndex(0, 2); + } + + /// Construct an invalid index. + SlotIndex() : lie(0, 0) {} + + // Construct a new slot index from the given one, and set the slot. + SlotIndex(const SlotIndex &li, Slot s) + : lie(&li.entry(), unsigned(s)) { + assert(lie.getPointer() != 0 && + "Attempt to construct index with 0 pointer."); + } + + /// Returns true if this is a valid index. Invalid indicies do + /// not point into an index table, and cannot be compared. + bool isValid() const { + return lie.getPointer(); + } + + /// Print this index to the given raw_ostream. + void print(raw_ostream &os) const; + + /// Dump this index to stderr. + void dump() const; + + /// Compare two SlotIndex objects for equality. + bool operator==(SlotIndex other) const { + return lie == other.lie; + } + /// Compare two SlotIndex objects for inequality. + bool operator!=(SlotIndex other) const { + return lie != other.lie; + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is strictly lower than the second. + bool operator<(SlotIndex other) const { + return getIndex() < other.getIndex(); + } + /// Compare two SlotIndex objects. Return true if the first index + /// is lower than, or equal to, the second. + bool operator<=(SlotIndex other) const { + return getIndex() <= other.getIndex(); + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is greater than the second. + bool operator>(SlotIndex other) const { + return getIndex() > other.getIndex(); + } + + /// Compare two SlotIndex objects. Return true if the first index + /// is greater than, or equal to, the second. + bool operator>=(SlotIndex other) const { + return getIndex() >= other.getIndex(); + } + + /// Return the distance from this index to the given one. + int distance(SlotIndex other) const { + return other.getIndex() - getIndex(); + } + + /// isLoad - Return true if this is a LOAD slot. + bool isLoad() const { + return getSlot() == LOAD; + } + + /// isDef - Return true if this is a DEF slot. + bool isDef() const { + return getSlot() == DEF; + } + + /// isUse - Return true if this is a USE slot. + bool isUse() const { + return getSlot() == USE; + } + + /// isStore - Return true if this is a STORE slot. + bool isStore() const { + return getSlot() == STORE; + } + + /// Returns the base index for associated with this index. The base index + /// is the one associated with the LOAD slot for the instruction pointed to + /// by this index. + SlotIndex getBaseIndex() const { + return getLoadIndex(); + } + + /// Returns the boundary index for associated with this index. The boundary + /// index is the one associated with the LOAD slot for the instruction + /// pointed to by this index. + SlotIndex getBoundaryIndex() const { + return getStoreIndex(); + } + + /// Returns the index of the LOAD slot for the instruction pointed to by + /// this index. + SlotIndex getLoadIndex() const { + return SlotIndex(&entry(), SlotIndex::LOAD); + } + + /// Returns the index of the USE slot for the instruction pointed to by + /// this index. + SlotIndex getUseIndex() const { + return SlotIndex(&entry(), SlotIndex::USE); + } + + /// Returns the index of the DEF slot for the instruction pointed to by + /// this index. + SlotIndex getDefIndex() const { + return SlotIndex(&entry(), SlotIndex::DEF); + } + + /// Returns the index of the STORE slot for the instruction pointed to by + /// this index. + SlotIndex getStoreIndex() const { + return SlotIndex(&entry(), SlotIndex::STORE); + } + + /// Returns the next slot in the index list. This could be either the + /// next slot for the instruction pointed to by this index or, if this + /// index is a STORE, the first slot for the next instruction. + /// WARNING: This method is considerably more expensive than the methods + /// that return specific slots (getUseIndex(), etc). If you can - please + /// use one of those methods. + SlotIndex getNextSlot() const { + Slot s = getSlot(); + if (s == SlotIndex::STORE) { + return SlotIndex(entry().getNext(), SlotIndex::LOAD); + } + return SlotIndex(&entry(), s + 1); + } + + /// Returns the next index. This is the index corresponding to the this + /// index's slot, but for the next instruction. + SlotIndex getNextIndex() const { + return SlotIndex(entry().getNext(), getSlot()); + } + + /// Returns the previous slot in the index list. This could be either the + /// previous slot for the instruction pointed to by this index or, if this + /// index is a LOAD, the last slot for the previous instruction. + /// WARNING: This method is considerably more expensive than the methods + /// that return specific slots (getUseIndex(), etc). If you can - please + /// use one of those methods. + SlotIndex getPrevSlot() const { + Slot s = getSlot(); + if (s == SlotIndex::LOAD) { + return SlotIndex(entry().getPrev(), SlotIndex::STORE); + } + return SlotIndex(&entry(), s - 1); + } + + /// Returns the previous index. This is the index corresponding to this + /// index's slot, but for the previous instruction. + SlotIndex getPrevIndex() const { + return SlotIndex(entry().getPrev(), getSlot()); + } + + }; + + /// DenseMapInfo specialization for SlotIndex. + template <> + struct DenseMapInfo { + static inline SlotIndex getEmptyKey() { + return SlotIndex::getEmptyKey(); + } + static inline SlotIndex getTombstoneKey() { + return SlotIndex::getTombstoneKey(); + } + static inline unsigned getHashValue(const SlotIndex &v) { + return SlotIndex::getHashValue(v); + } + static inline bool isEqual(const SlotIndex &LHS, const SlotIndex &RHS) { + return (LHS == RHS); + } + }; + + template <> struct isPodLike { static const bool value = true; }; + + + inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { + li.print(os); + return os; + } + + typedef std::pair IdxMBBPair; + + inline bool operator<(SlotIndex V, const IdxMBBPair &IM) { + return V < IM.first; + } + + inline bool operator<(const IdxMBBPair &IM, SlotIndex V) { + return IM.first < V; + } + + struct Idx2MBBCompare { + bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const { + return LHS.first < RHS.first; + } + }; + + /// SlotIndexes pass. + /// + /// This pass assigns indexes to each instruction. + class SlotIndexes : public MachineFunctionPass { + private: + + MachineFunction *mf; + IndexListEntry *indexListHead; + unsigned functionSize; + + typedef DenseMap Mi2IndexMap; + Mi2IndexMap mi2iMap; + + /// MBB2IdxMap - The indexes of the first and last instructions in the + /// specified basic block. + typedef DenseMap > MBB2IdxMap; + MBB2IdxMap mbb2IdxMap; + + /// Idx2MBBMap - Sorted list of pairs of index of first instruction + /// and MBB id. + std::vector idx2MBBMap; + + // IndexListEntry allocator. + BumpPtrAllocator ileAllocator; + + IndexListEntry* createEntry(MachineInstr *mi, unsigned index) { + IndexListEntry *entry = + static_cast( + ileAllocator.Allocate(sizeof(IndexListEntry), + alignOf())); + + new (entry) IndexListEntry(mi, index); + + return entry; + } + + void initList() { + assert(indexListHead == 0 && "Zero entry non-null at initialisation."); + indexListHead = createEntry(0, ~0U); + indexListHead->setNext(0); + indexListHead->setPrev(indexListHead); + } + + void clearList() { + indexListHead = 0; + ileAllocator.Reset(); + } + + IndexListEntry* getTail() { + assert(indexListHead != 0 && "Call to getTail on uninitialized list."); + return indexListHead->getPrev(); + } + + const IndexListEntry* getTail() const { + assert(indexListHead != 0 && "Call to getTail on uninitialized list."); + return indexListHead->getPrev(); + } + + // Returns true if the index list is empty. + bool empty() const { return (indexListHead == getTail()); } + + IndexListEntry* front() { + assert(!empty() && "front() called on empty index list."); + return indexListHead; + } + + const IndexListEntry* front() const { + assert(!empty() && "front() called on empty index list."); + return indexListHead; + } + + IndexListEntry* back() { + assert(!empty() && "back() called on empty index list."); + return getTail()->getPrev(); + } + + const IndexListEntry* back() const { + assert(!empty() && "back() called on empty index list."); + return getTail()->getPrev(); + } + + /// Insert a new entry before itr. + void insert(IndexListEntry *itr, IndexListEntry *val) { + assert(itr != 0 && "itr should not be null."); + IndexListEntry *prev = itr->getPrev(); + val->setNext(itr); + val->setPrev(prev); + + if (itr != indexListHead) { + prev->setNext(val); + } + else { + indexListHead = val; + } + itr->setPrev(val); + } + + /// Push a new entry on to the end of the list. + void push_back(IndexListEntry *val) { + insert(getTail(), val); + } + + /// Renumber locally after inserting newEntry. + void renumberIndexes(IndexListEntry *newEntry); + + public: + static char ID; + + SlotIndexes() : MachineFunctionPass(ID), indexListHead(0) { + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + virtual void releaseMemory(); + + virtual bool runOnMachineFunction(MachineFunction &fn); + + /// Dump the indexes. + void dump() const; + + /// Renumber the index list, providing space for new instructions. + void renumberIndexes(); + + /// Returns the zero index for this analysis. + SlotIndex getZeroIndex() { + assert(front()->getIndex() == 0 && "First index is not 0?"); + return SlotIndex(front(), 0); + } + + /// Returns the base index of the last slot in this analysis. + SlotIndex getLastIndex() { + return SlotIndex(back(), 0); + } + + /// Returns the invalid index marker for this analysis. + SlotIndex getInvalidIndex() { + return getZeroIndex(); + } + + /// Returns the distance between the highest and lowest indexes allocated + /// so far. + unsigned getIndexesLength() const { + assert(front()->getIndex() == 0 && + "Initial index isn't zero?"); + + return back()->getIndex(); + } + + /// Returns the number of instructions in the function. + unsigned getFunctionSize() const { + return functionSize; + } + + /// Returns true if the given machine instr is mapped to an index, + /// otherwise returns false. + bool hasIndex(const MachineInstr *instr) const { + return (mi2iMap.find(instr) != mi2iMap.end()); + } + + /// Returns the base index for the given instruction. + SlotIndex getInstructionIndex(const MachineInstr *instr) const { + Mi2IndexMap::const_iterator itr = mi2iMap.find(instr); + assert(itr != mi2iMap.end() && "Instruction not found in maps."); + return itr->second; + } + + /// Returns the instruction for the given index, or null if the given + /// index has no instruction associated with it. + MachineInstr* getInstructionFromIndex(SlotIndex index) const { + return index.isValid() ? index.entry().getInstr() : 0; + } + + /// Returns the next non-null index. + SlotIndex getNextNonNullIndex(SlotIndex index) { + SlotIndex nextNonNull = index.getNextIndex(); + + while (&nextNonNull.entry() != getTail() && + getInstructionFromIndex(nextNonNull) == 0) { + nextNonNull = nextNonNull.getNextIndex(); + } + + return nextNonNull; + } + + /// Return the (start,end) range of the given basic block. + const std::pair & + getMBBRange(const MachineBasicBlock *mbb) const { + MBB2IdxMap::const_iterator itr = mbb2IdxMap.find(mbb); + assert(itr != mbb2IdxMap.end() && "MBB not found in maps."); + return itr->second; + } + + /// Returns the first index in the given basic block. + SlotIndex getMBBStartIdx(const MachineBasicBlock *mbb) const { + return getMBBRange(mbb).first; + } + + /// Returns the last index in the given basic block. + SlotIndex getMBBEndIdx(const MachineBasicBlock *mbb) const { + return getMBBRange(mbb).second; + } + + /// Returns the basic block which the given index falls in. + MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { + std::vector::const_iterator I = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != idx2MBBMap.end() && I->first > index) || + (I == idx2MBBMap.end() && idx2MBBMap.size()>0)) ? (I-1): I; + + assert(J != idx2MBBMap.end() && J->first <= index && + index < getMBBEndIdx(J->second) && + "index does not correspond to an MBB"); + return J->second; + } + + bool findLiveInMBBs(SlotIndex start, SlotIndex end, + SmallVectorImpl &mbbs) const { + std::vector::const_iterator itr = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); + bool resVal = false; + + while (itr != idx2MBBMap.end()) { + if (itr->first >= end) + break; + mbbs.push_back(itr->second); + resVal = true; + ++itr; + } + return resVal; + } + + /// Returns the MBB covering the given range, or null if the range covers + /// more than one basic block. + MachineBasicBlock* getMBBCoveringRange(SlotIndex start, SlotIndex end) const { + + assert(start < end && "Backwards ranges not allowed."); + + std::vector::const_iterator itr = + std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); + + if (itr == idx2MBBMap.end()) { + itr = prior(itr); + return itr->second; + } + + // Check that we don't cross the boundary into this block. + if (itr->first < end) + return 0; + + itr = prior(itr); + + if (itr->first <= start) + return itr->second; + + return 0; + } + + /// Insert the given machine instruction into the mapping. Returns the + /// assigned index. + SlotIndex insertMachineInstrInMaps(MachineInstr *mi) { + assert(mi2iMap.find(mi) == mi2iMap.end() && "Instr already indexed."); + // Numbering DBG_VALUE instructions could cause code generation to be + // affected by debug information. + assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions."); + + MachineBasicBlock *mbb = mi->getParent(); + + assert(mbb != 0 && "Instr must be added to function."); + + MBB2IdxMap::iterator mbbRangeItr = mbb2IdxMap.find(mbb); + + assert(mbbRangeItr != mbb2IdxMap.end() && + "Instruction's parent MBB has not been added to SlotIndexes."); + + MachineBasicBlock::iterator miItr(mi); + IndexListEntry *newEntry; + // Get previous index, considering that not all instructions are indexed. + IndexListEntry *prevEntry; + for (;;) { + // If mi is at the mbb beginning, get the prev index from the mbb. + if (miItr == mbb->begin()) { + prevEntry = &mbbRangeItr->second.first.entry(); + break; + } + // Otherwise rewind until we find a mapped instruction. + Mi2IndexMap::const_iterator itr = mi2iMap.find(--miItr); + if (itr != mi2iMap.end()) { + prevEntry = &itr->second.entry(); + break; + } + } + + // Get next entry from previous entry. + IndexListEntry *nextEntry = prevEntry->getNext(); + + // Get a number for the new instr, or 0 if there's no room currently. + // In the latter case we'll force a renumber later. + unsigned dist = ((nextEntry->getIndex() - prevEntry->getIndex())/2) & ~3u; + unsigned newNumber = prevEntry->getIndex() + dist; + + // Insert a new list entry for mi. + newEntry = createEntry(mi, newNumber); + insert(nextEntry, newEntry); + + // Renumber locally if we need to. + if (dist == 0) + renumberIndexes(newEntry); + + SlotIndex newIndex(newEntry, SlotIndex::LOAD); + mi2iMap.insert(std::make_pair(mi, newIndex)); + return newIndex; + } + + /// Remove the given machine instruction from the mapping. + void removeMachineInstrFromMaps(MachineInstr *mi) { + // remove index -> MachineInstr and + // MachineInstr -> index mappings + Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi); + if (mi2iItr != mi2iMap.end()) { + IndexListEntry *miEntry(&mi2iItr->second.entry()); + assert(miEntry->getInstr() == mi && "Instruction indexes broken."); + // FIXME: Eventually we want to actually delete these indexes. + miEntry->setInstr(0); + mi2iMap.erase(mi2iItr); + } + } + + /// ReplaceMachineInstrInMaps - Replacing a machine instr with a new one in + /// maps used by register allocator. + void replaceMachineInstrInMaps(MachineInstr *mi, MachineInstr *newMI) { + Mi2IndexMap::iterator mi2iItr = mi2iMap.find(mi); + if (mi2iItr == mi2iMap.end()) + return; + SlotIndex replaceBaseIndex = mi2iItr->second; + IndexListEntry *miEntry(&replaceBaseIndex.entry()); + assert(miEntry->getInstr() == mi && + "Mismatched instruction in index tables."); + miEntry->setInstr(newMI); + mi2iMap.erase(mi2iItr); + mi2iMap.insert(std::make_pair(newMI, replaceBaseIndex)); + } + + /// Add the given MachineBasicBlock into the maps. + void insertMBBInMaps(MachineBasicBlock *mbb) { + MachineFunction::iterator nextMBB = + llvm::next(MachineFunction::iterator(mbb)); + IndexListEntry *startEntry = createEntry(0, 0); + IndexListEntry *stopEntry = createEntry(0, 0); + IndexListEntry *nextEntry = 0; + + if (nextMBB == mbb->getParent()->end()) { + nextEntry = getTail(); + } else { + nextEntry = &getMBBStartIdx(nextMBB).entry(); + } + + insert(nextEntry, startEntry); + insert(nextEntry, stopEntry); + + SlotIndex startIdx(startEntry, SlotIndex::LOAD); + SlotIndex endIdx(nextEntry, SlotIndex::LOAD); + + mbb2IdxMap.insert( + std::make_pair(mbb, std::make_pair(startIdx, endIdx))); + + idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); + + if (MachineFunction::iterator(mbb) != mbb->getParent()->begin()) { + // Have to update the end index of the previous block. + MachineBasicBlock *priorMBB = + llvm::prior(MachineFunction::iterator(mbb)); + mbb2IdxMap[priorMBB].second = startIdx; + } + + renumberIndexes(); + std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); + + } + + }; + + + // Specialize IntervalMapInfo for half-open slot index intervals. + template struct IntervalMapInfo; + template <> struct IntervalMapInfo { + static inline bool startLess(const SlotIndex &x, const SlotIndex &a) { + return x < a; + } + static inline bool stopLess(const SlotIndex &b, const SlotIndex &x) { + return b <= x; + } + static inline bool adjacent(const SlotIndex &a, const SlotIndex &b) { + return a == b; + } + }; + +} + +#endif // LLVM_CODEGEN_LIVEINDEX_H diff --git a/final/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/final/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h new file mode 100644 index 00000000000..fba3e48c475 --- /dev/null +++ b/final/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -0,0 +1,206 @@ +//==-- llvm/CodeGen/TargetLoweringObjectFileImpl.h - Object 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 implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H +#define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { + class MachineModuleInfo; + class Mangler; + class MCAsmInfo; + class MCExpr; + class MCSection; + class MCSectionMachO; + class MCSymbol; + class MCContext; + class GlobalValue; + class TargetMachine; + + +class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { +protected: + /// TLSDataSection - Section directive for Thread Local data. + /// + const MCSection *TLSDataSection; // Defaults to ".tdata". + + /// TLSBSSSection - Section directive for Thread Local uninitialized data. + /// Null if this target doesn't support a BSS section. + /// + const MCSection *TLSBSSSection; // Defaults to ".tbss". + + const MCSection *DataRelSection; + const MCSection *DataRelLocalSection; + const MCSection *DataRelROSection; + const MCSection *DataRelROLocalSection; + + const MCSection *MergeableConst4Section; + const MCSection *MergeableConst8Section; + const MCSection *MergeableConst16Section; +public: + TargetLoweringObjectFileELF() {} + ~TargetLoweringObjectFileELF() {} + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection *getEHFrameSection() const; + + const MCSection *getDataRelSection() const { return DataRelSection; } + + /// getSectionForConstant - Given a constant with the SectionKind, return a + /// section that it should be placed in. + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + /// getExprForDwarfGlobalReference - Return an MCExpr to use for a reference + /// to the specified global variable from exception handling information. + /// + virtual const MCExpr * + getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; +}; + + + +class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { + /// TLSDataSection - Section for thread local data. + /// + const MCSection *TLSDataSection; // Defaults to ".tdata". + + /// TLSBSSSection - Section for thread local uninitialized data. + /// + const MCSection *TLSBSSSection; // Defaults to ".tbss". + + /// TLSTLVSection - Section for thread local structure infomation. + /// Contains the source code name of the variable, visibility and a pointer + /// to the initial value (.tdata or .tbss). + const MCSection *TLSTLVSection; // Defaults to ".tlv". + + /// TLSThreadInitSection - Section for thread local data initialization + /// functions. + const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". + + const MCSection *CStringSection; + const MCSection *UStringSection; + const MCSection *TextCoalSection; + const MCSection *ConstTextCoalSection; + const MCSection *ConstDataSection; + const MCSection *DataCoalSection; + const MCSection *DataCommonSection; + const MCSection *DataBSSSection; + const MCSection *FourByteConstantSection; + const MCSection *EightByteConstantSection; + const MCSection *SixteenByteConstantSection; + + const MCSection *LazySymbolPointerSection; + const MCSection *NonLazySymbolPointerSection; +public: + TargetLoweringObjectFileMachO() {} + ~TargetLoweringObjectFileMachO() {} + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection *getEHFrameSection() const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively + /// decide not to emit the UsedDirective for some symbols in llvm.used. + /// FIXME: REMOVE this (rdar://7071300) + virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, + Mangler *) const; + + /// getTextCoalSection - Return the "__TEXT,__textcoal_nt" section we put weak + /// text symbols into. + const MCSection *getTextCoalSection() const { + return TextCoalSection; + } + + /// getConstTextCoalSection - Return the "__TEXT,__const_coal" section + /// we put weak read-only symbols into. + const MCSection *getConstTextCoalSection() const { + return ConstTextCoalSection; + } + + /// getLazySymbolPointerSection - Return the section corresponding to + /// the .lazy_symbol_pointer directive. + const MCSection *getLazySymbolPointerSection() const { + return LazySymbolPointerSection; + } + + /// getNonLazySymbolPointerSection - Return the section corresponding to + /// the .non_lazy_symbol_pointer directive. + const MCSection *getNonLazySymbolPointerSection() const { + return NonLazySymbolPointerSection; + } + + /// getExprForDwarfGlobalReference - The mach-o version of this method + /// defaults to returning a stub reference. + virtual const MCExpr * + getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; + + virtual unsigned getPersonalityEncoding() const; + virtual unsigned getLSDAEncoding() const; + virtual unsigned getFDEEncoding() const; + virtual unsigned getTTypeEncoding() const; +}; + + + +class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { + const MCSection *DrectveSection; +public: + TargetLoweringObjectFileCOFF() {} + ~TargetLoweringObjectFileCOFF() {} + + virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + + virtual const MCSection *getEHFrameSection() const; + + virtual const MCSection *getDrectveSection() const { return DrectveSection; } + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/CodeGen/ValueTypes.h b/final/include/llvm/CodeGen/ValueTypes.h new file mode 100644 index 00000000000..22d16222078 --- /dev/null +++ b/final/include/llvm/CodeGen/ValueTypes.h @@ -0,0 +1,690 @@ +//===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- 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 set of low-level target independent types which various +// values in the code generator are. This allows the target specific behavior +// of instructions to be described to target independent passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VALUETYPES_H +#define LLVM_CODEGEN_VALUETYPES_H + +#include +#include +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + class Type; + class LLVMContext; + struct EVT; + + /// MVT - Machine Value Type. Every type that is supported natively by some + /// processor targeted by LLVM occurs here. This means that any legal value + /// type can be represented by a MVT. + class MVT { + public: + enum SimpleValueType { + // If you change this numbering, you must change the values in + // ValueTypes.td as well! + Other = 0, // This is a non-standard value + i1 = 1, // This is a 1 bit integer value + i8 = 2, // This is an 8 bit integer value + i16 = 3, // This is a 16 bit integer value + i32 = 4, // This is a 32 bit integer value + i64 = 5, // This is a 64 bit integer value + i128 = 6, // This is a 128 bit integer value + + FIRST_INTEGER_VALUETYPE = i1, + LAST_INTEGER_VALUETYPE = i128, + + f32 = 7, // This is a 32 bit floating point value + f64 = 8, // This is a 64 bit floating point value + f80 = 9, // This is a 80 bit floating point value + f128 = 10, // This is a 128 bit floating point value + ppcf128 = 11, // This is a PPC 128-bit floating point value + + v2i8 = 12, // 2 x i8 + v4i8 = 13, // 4 x i8 + v8i8 = 14, // 8 x i8 + v16i8 = 15, // 16 x i8 + v32i8 = 16, // 32 x i8 + v2i16 = 17, // 2 x i16 + v4i16 = 18, // 4 x i16 + v8i16 = 19, // 8 x i16 + v16i16 = 20, // 16 x i16 + v2i32 = 21, // 2 x i32 + v4i32 = 22, // 4 x i32 + v8i32 = 23, // 8 x i32 + v1i64 = 24, // 1 x i64 + v2i64 = 25, // 2 x i64 + v4i64 = 26, // 4 x i64 + v8i64 = 27, // 8 x i64 + + v2f32 = 28, // 2 x f32 + v4f32 = 29, // 4 x f32 + v8f32 = 30, // 8 x f32 + v2f64 = 31, // 2 x f64 + v4f64 = 32, // 4 x f64 + + FIRST_VECTOR_VALUETYPE = v2i8, + LAST_VECTOR_VALUETYPE = v4f64, + + x86mmx = 33, // This is an X86 MMX value + + Glue = 34, // This glues nodes together during pre-RA sched + + isVoid = 35, // This has no value + + LAST_VALUETYPE = 36, // This always remains at the end of the list. + + // This is the current maximum for LAST_VALUETYPE. + // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // This value must be a multiple of 32. + MAX_ALLOWED_VALUETYPE = 64, + + // Metadata - This is MDNode or MDString. + Metadata = 250, + + // iPTRAny - An int value the size of the pointer of the current + // target to any address space. This must only be used internal to + // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. + iPTRAny = 251, + + // vAny - A vector with any length and element size. This is used + // for intrinsics that have overloadings based on vector types. + // This is only for tblgen's consumption! + vAny = 252, + + // fAny - Any floating-point or vector floating-point value. This is used + // for intrinsics that have overloadings based on floating-point types. + // This is only for tblgen's consumption! + fAny = 253, + + // iAny - An integer or vector integer value of any bit width. This is + // used for intrinsics that have overloadings based on integer bit widths. + // This is only for tblgen's consumption! + iAny = 254, + + // iPTR - An int value the size of the pointer of the current + // target. This should only be used internal to tblgen! + iPTR = 255, + + // LastSimpleValueType - The greatest valid SimpleValueType value. + LastSimpleValueType = 255, + + // INVALID_SIMPLE_VALUE_TYPE - Simple value types greater than or equal + // to this are considered extended value types. + INVALID_SIMPLE_VALUE_TYPE = LastSimpleValueType + 1 + }; + + SimpleValueType SimpleTy; + + MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} + MVT(SimpleValueType SVT) : SimpleTy(SVT) { } + + bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } + bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } + bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } + bool operator!=(const MVT& S) const { return SimpleTy != S.SimpleTy; } + bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } + bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return ((SimpleTy >= MVT::f32 && SimpleTy <= MVT::ppcf128) || + (SimpleTy >= MVT::v2f32 && SimpleTy <= MVT::v4f64)); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || + (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v8i64)); + } + + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); + } + + /// isPow2VectorType - Returns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); + } + + /// getPow2VectorType - Widens the length of the given vector MVT up to + /// the nearest power of 2 and returns that type. + MVT getPow2VectorType() const { + if (isPow2VectorType()) + return *this; + + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return MVT::getVectorVT(getVectorElementType(), Pow2NElts); + } + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return this. + MVT getScalarType() const { + return isVector() ? getVectorElementType() : *this; + } + + MVT getVectorElementType() const { + switch (SimpleTy) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case v2i8 : + case v4i8 : + case v8i8 : + case v16i8: + case v32i8: return i8; + case v2i16: + case v4i16: + case v8i16: + case v16i16: return i16; + case v2i32: + case v4i32: + case v8i32: return i32; + case v1i64: + case v2i64: + case v4i64: + case v8i64: return i64; + case v2f32: + case v4f32: + case v8f32: return f32; + case v2f64: + case v4f64: return f64; + } + } + + unsigned getVectorNumElements() const { + switch (SimpleTy) { + default: + return ~0U; + case v32i8: return 32; + case v16i8: + case v16i16: return 16; + case v8i8 : + case v8i16: + case v8i32: + case v8i64: + case v8f32: return 8; + case v4i8: + case v4i16: + case v4i32: + case v4i64: + case v4f32: + case v4f64: return 4; + case v2i8: + case v2i16: + case v2i32: + case v2i64: + case v2f32: + case v2f64: return 2; + case v1i64: return 1; + } + } + + unsigned getSizeInBits() const { + switch (SimpleTy) { + case iPTR: + assert(0 && "Value type size is target-dependent. Ask TLI."); + case iPTRAny: + case iAny: + case fAny: + assert(0 && "Value type is overloaded."); + default: + assert(0 && "getSizeInBits called on extended MVT."); + case i1 : return 1; + case i8 : return 8; + case i16 : + case v2i8: return 16; + case f32 : + case i32 : + case v4i8: + case v2i16: return 32; + case x86mmx: + case f64 : + case i64 : + case v8i8: + case v4i16: + case v2i32: + case v1i64: + case v2f32: return 64; + case f80 : return 80; + case f128: + case ppcf128: + case i128: + case v16i8: + case v8i16: + case v4i32: + case v2i64: + case v4f32: + case v2f64: return 128; + case v32i8: + case v16i16: + case v8i32: + case v4i64: + case v8f32: + case v4f64: return 256; + case v8i64: return 512; + } + } + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; + } + + /// getStoreSizeInBits - Return the number of bits overwritten by a store + /// of the specified value type. + unsigned getStoreSizeInBits() const { + return getStoreSize() * 8; + } + + static MVT getFloatingPointVT(unsigned BitWidth) { + switch (BitWidth) { + default: + assert(false && "Bad bit width!"); + case 32: + return MVT::f32; + case 64: + return MVT::f64; + case 80: + return MVT::f80; + case 128: + return MVT::f128; + } + } + + static MVT getIntegerVT(unsigned BitWidth) { + switch (BitWidth) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case 1: + return MVT::i1; + case 8: + return MVT::i8; + case 16: + return MVT::i16; + case 32: + return MVT::i32; + case 64: + return MVT::i64; + case 128: + return MVT::i128; + } + } + + static MVT getVectorVT(MVT VT, unsigned NumElements) { + switch (VT.SimpleTy) { + default: + break; + case MVT::i8: + if (NumElements == 2) return MVT::v2i8; + if (NumElements == 4) return MVT::v4i8; + if (NumElements == 8) return MVT::v8i8; + if (NumElements == 16) return MVT::v16i8; + if (NumElements == 32) return MVT::v32i8; + break; + case MVT::i16: + if (NumElements == 2) return MVT::v2i16; + if (NumElements == 4) return MVT::v4i16; + if (NumElements == 8) return MVT::v8i16; + if (NumElements == 16) return MVT::v16i16; + break; + case MVT::i32: + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 4) return MVT::v4i32; + if (NumElements == 8) return MVT::v8i32; + break; + case MVT::i64: + if (NumElements == 1) return MVT::v1i64; + if (NumElements == 2) return MVT::v2i64; + if (NumElements == 4) return MVT::v4i64; + if (NumElements == 8) return MVT::v8i64; + break; + case MVT::f32: + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 4) return MVT::v4f32; + if (NumElements == 8) return MVT::v8f32; + break; + case MVT::f64: + if (NumElements == 2) return MVT::v2f64; + if (NumElements == 4) return MVT::v4f64; + break; + } + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + } + }; + + + /// EVT - Extended Value Type. Capable of holding value types which are not + /// native for any processor (such as the i12345 type), as well as the types + /// a MVT can represent. + struct EVT { + private: + MVT V; + const Type *LLVMTy; + + public: + EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), + LLVMTy(0) {} + EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(0) { } + EVT(MVT S) : V(S), LLVMTy(0) {} + + bool operator==(EVT VT) const { + return !(*this != VT); + } + bool operator!=(EVT VT) const { + if (V.SimpleTy != VT.V.SimpleTy) + return true; + if (V.SimpleTy == MVT::INVALID_SIMPLE_VALUE_TYPE) + return LLVMTy != VT.LLVMTy; + return false; + } + + /// getFloatingPointVT - Returns the EVT that represents a floating point + /// type with the given number of bits. There are two floating point types + /// with 128 bits - this returns f128 rather than ppcf128. + static EVT getFloatingPointVT(unsigned BitWidth) { + return MVT::getFloatingPointVT(BitWidth); + } + + /// getIntegerVT - Returns the EVT that represents an integer with the given + /// number of bits. + static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth) { + MVT M = MVT::getIntegerVT(BitWidth); + if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) + return M; + return getExtendedIntegerVT(Context, BitWidth); + } + + /// getVectorVT - Returns the EVT that represents a vector NumElements in + /// length, where each element is of type VT. + static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements) { + MVT M = MVT::getVectorVT(VT.V, NumElements); + if (M.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE) + return M; + return getExtendedVectorVT(Context, VT, NumElements); + } + + /// getIntVectorWithNumElements - Return any integer vector type that has + /// the specified number of elements. + static EVT getIntVectorWithNumElements(LLVMContext &C, unsigned NumElts) { + switch (NumElts) { + default: return getVectorVT(C, MVT::i8, NumElts); + case 1: return MVT::v1i64; + case 2: return MVT::v2i32; + case 4: return MVT::v4i16; + case 8: return MVT::v8i8; + case 16: return MVT::v16i8; + } + return MVT::INVALID_SIMPLE_VALUE_TYPE; + } + + /// isSimple - Test if the given EVT is simple (as opposed to being + /// extended). + bool isSimple() const { + return V.SimpleTy <= MVT::LastSimpleValueType; + } + + /// isExtended - Test if the given EVT is extended (as opposed to + /// being simple). + bool isExtended() const { + return !isSimple(); + } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return isSimple() ? V.isFloatingPoint() : isExtendedFloatingPoint(); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return isSimple() ? V.isInteger() : isExtendedInteger(); + } + + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return isSimple() ? V.isVector() : isExtendedVector(); + } + + /// is64BitVector - Return true if this is a 64-bit vector type. + bool is64BitVector() const { + if (!isSimple()) + return isExtended64BitVector(); + + return (V == MVT::v8i8 || V==MVT::v4i16 || V==MVT::v2i32 || + V == MVT::v1i64 || V==MVT::v2f32); + } + + /// is128BitVector - Return true if this is a 128-bit vector type. + bool is128BitVector() const { + if (!isSimple()) + return isExtended128BitVector(); + return (V==MVT::v16i8 || V==MVT::v8i16 || V==MVT::v4i32 || + V==MVT::v2i64 || V==MVT::v4f32 || V==MVT::v2f64); + } + + /// is256BitVector - Return true if this is a 256-bit vector type. + inline bool is256BitVector() const { + if (!isSimple()) + return isExtended256BitVector(); + return (V == MVT::v8f32 || V == MVT::v4f64 || V == MVT::v32i8 || + V == MVT::v16i16 || V == MVT::v8i32 || V == MVT::v4i64); + } + + /// is512BitVector - Return true if this is a 512-bit vector type. + inline bool is512BitVector() const { + return isSimple() ? (V == MVT::v8i64) : isExtended512BitVector(); + } + + /// isOverloaded - Return true if this is an overloaded type for TableGen. + bool isOverloaded() const { + return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); + } + + /// isByteSized - Return true if the bit size is a multiple of 8. + bool isByteSized() const { + return (getSizeInBits() & 7) == 0; + } + + /// isRound - Return true if the size is a power-of-two number of bytes. + bool isRound() const { + unsigned BitSize = getSizeInBits(); + return BitSize >= 8 && !(BitSize & (BitSize - 1)); + } + + /// bitsEq - Return true if this has the same number of bits as VT. + bool bitsEq(EVT VT) const { + if (EVT::operator==(VT)) return true; + return getSizeInBits() == VT.getSizeInBits(); + } + + /// bitsGT - Return true if this has more bits than VT. + bool bitsGT(EVT VT) const { + if (EVT::operator==(VT)) return false; + return getSizeInBits() > VT.getSizeInBits(); + } + + /// bitsGE - Return true if this has no less bits than VT. + bool bitsGE(EVT VT) const { + if (EVT::operator==(VT)) return true; + return getSizeInBits() >= VT.getSizeInBits(); + } + + /// bitsLT - Return true if this has less bits than VT. + bool bitsLT(EVT VT) const { + if (EVT::operator==(VT)) return false; + return getSizeInBits() < VT.getSizeInBits(); + } + + /// bitsLE - Return true if this has no more bits than VT. + bool bitsLE(EVT VT) const { + if (EVT::operator==(VT)) return true; + return getSizeInBits() <= VT.getSizeInBits(); + } + + + /// getSimpleVT - Return the SimpleValueType held in the specified + /// simple EVT. + MVT getSimpleVT() const { + assert(isSimple() && "Expected a SimpleValueType!"); + return V; + } + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return this. + EVT getScalarType() const { + return isVector() ? getVectorElementType() : *this; + } + + /// getVectorElementType - Given a vector type, return the type of + /// each element. + EVT getVectorElementType() const { + assert(isVector() && "Invalid vector type!"); + if (isSimple()) + return V.getVectorElementType(); + return getExtendedVectorElementType(); + } + + /// getVectorNumElements - Given a vector type, return the number of + /// elements it contains. + unsigned getVectorNumElements() const { + assert(isVector() && "Invalid vector type!"); + if (isSimple()) + return V.getVectorNumElements(); + return getExtendedVectorNumElements(); + } + + /// getSizeInBits - Return the size of the specified value type in bits. + unsigned getSizeInBits() const { + if (isSimple()) + return V.getSizeInBits(); + return getExtendedSizeInBits(); + } + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; + } + + /// getStoreSizeInBits - Return the number of bits overwritten by a store + /// of the specified value type. + unsigned getStoreSizeInBits() const { + return getStoreSize() * 8; + } + + /// getRoundIntegerType - Rounds the bit-width of the given integer EVT up + /// to the nearest power of two (and at least to eight), and returns the + /// integer EVT with that number of bits. + EVT getRoundIntegerType(LLVMContext &Context) const { + assert(isInteger() && !isVector() && "Invalid integer type!"); + unsigned BitWidth = getSizeInBits(); + if (BitWidth <= 8) + return EVT(MVT::i8); + return getIntegerVT(Context, 1 << Log2_32_Ceil(BitWidth)); + } + + /// getHalfSizedIntegerVT - Finds the smallest simple value type that is + /// greater than or equal to half the width of this EVT. If no simple + /// value type can be found, an extended integer value type of half the + /// size (rounded up) is returned. + EVT getHalfSizedIntegerVT(LLVMContext &Context) const { + assert(isInteger() && !isVector() && "Invalid integer type!"); + unsigned EVTSize = getSizeInBits(); + for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE; + IntVT <= MVT::LAST_INTEGER_VALUETYPE; ++IntVT) { + EVT HalfVT = EVT((MVT::SimpleValueType)IntVT); + if (HalfVT.getSizeInBits() * 2 >= EVTSize) + return HalfVT; + } + return getIntegerVT(Context, (EVTSize + 1) / 2); + } + + /// isPow2VectorType - Returns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); + } + + /// getPow2VectorType - Widens the length of the given vector EVT up to + /// the nearest power of 2 and returns that type. + EVT getPow2VectorType(LLVMContext &Context) const { + if (!isPow2VectorType()) { + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return EVT::getVectorVT(Context, getVectorElementType(), Pow2NElts); + } + else { + return *this; + } + } + + /// getEVTString - This function returns value type as a string, + /// e.g. "i32". + std::string getEVTString() const; + + /// getTypeForEVT - This method returns an LLVM type corresponding to the + /// specified EVT. For integer types, this returns an unsigned type. Note + /// that this will abort for types that cannot be represented. + const Type *getTypeForEVT(LLVMContext &Context) const; + + /// getEVT - Return the value type corresponding to the specified type. + /// This returns all pointers as iPTR. If HandleUnknown is true, unknown + /// types are returned as Other, otherwise they are invalid. + static EVT getEVT(const Type *Ty, bool HandleUnknown = false); + + intptr_t getRawBits() { + if (isSimple()) + return V.SimpleTy; + else + return (intptr_t)(LLVMTy); + } + + /// compareRawBits - A meaningless but well-behaved order, useful for + /// constructing containers. + struct compareRawBits { + bool operator()(EVT L, EVT R) const { + if (L.V.SimpleTy == R.V.SimpleTy) + return L.LLVMTy < R.LLVMTy; + else + return L.V.SimpleTy < R.V.SimpleTy; + } + }; + + private: + // Methods for handling the Extended-type case in functions above. + // These are all out-of-line to prevent users of this header file + // from having a dependency on Type.h. + static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); + static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, + unsigned NumElements); + bool isExtendedFloatingPoint() const; + bool isExtendedInteger() const; + bool isExtendedVector() const; + bool isExtended64BitVector() const; + bool isExtended128BitVector() const; + bool isExtended256BitVector() const; + bool isExtended512BitVector() const; + EVT getExtendedVectorElementType() const; + unsigned getExtendedVectorNumElements() const; + unsigned getExtendedSizeInBits() const; + }; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/CodeGen/ValueTypes.td b/final/include/llvm/CodeGen/ValueTypes.td new file mode 100644 index 00000000000..a1163f7a2f9 --- /dev/null +++ b/final/include/llvm/CodeGen/ValueTypes.td @@ -0,0 +1,78 @@ +//===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Value types - These values correspond to the register types defined in the +// ValueTypes.h file. If you update anything here, you must update it there as +// well! +// +//===----------------------------------------------------------------------===// + +class ValueType { + string Namespace = "MVT"; + int Size = size; + int Value = value; +} + +def OtherVT: ValueType<0 , 0>; // "Other" value +def i1 : ValueType<1 , 1>; // One bit boolean value +def i8 : ValueType<8 , 2>; // 8-bit integer value +def i16 : ValueType<16 , 3>; // 16-bit integer value +def i32 : ValueType<32 , 4>; // 32-bit integer value +def i64 : ValueType<64 , 5>; // 64-bit integer value +def i128 : ValueType<128, 6>; // 128-bit integer value +def f32 : ValueType<32 , 7>; // 32-bit floating point value +def f64 : ValueType<64 , 8>; // 64-bit floating point value +def f80 : ValueType<80 , 9>; // 80-bit floating point value +def f128 : ValueType<128, 10>; // 128-bit floating point value +def ppcf128: ValueType<128, 11>; // PPC 128-bit floating point value + +def v2i8 : ValueType<16 , 12>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 13>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 14>; // 8 x i8 vector value +def v16i8 : ValueType<128, 15>; // 16 x i8 vector value +def v32i8 : ValueType<256, 16>; // 32 x i8 vector value +def v2i16 : ValueType<32 , 17>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 18>; // 4 x i16 vector value +def v8i16 : ValueType<128, 19>; // 8 x i16 vector value +def v16i16 : ValueType<256, 20>; // 16 x i16 vector value +def v2i32 : ValueType<64 , 21>; // 2 x i32 vector value +def v4i32 : ValueType<128, 22>; // 4 x i32 vector value +def v8i32 : ValueType<256, 23>; // 8 x i32 vector value +def v1i64 : ValueType<64 , 24>; // 1 x i64 vector value +def v2i64 : ValueType<128, 25>; // 2 x i64 vector value +def v4i64 : ValueType<256, 26>; // 4 x i64 vector value +def v8i64 : ValueType<512, 27>; // 8 x i64 vector value + +def v2f32 : ValueType<64 , 28>; // 2 x f32 vector value +def v4f32 : ValueType<128, 29>; // 4 x f32 vector value +def v8f32 : ValueType<256, 30>; // 8 x f32 vector value +def v2f64 : ValueType<128, 31>; // 2 x f64 vector value +def v4f64 : ValueType<256, 32>; // 4 x f64 vector value + +def x86mmx : ValueType<64 , 33>; // X86 MMX value +def FlagVT : ValueType<0 , 34>; // Pre-RA sched glue +def isVoid : ValueType<0 , 35>; // Produces no value + +def MetadataVT: ValueType<0, 250>; // Metadata + +// Pseudo valuetype mapped to the current pointer size to any address space. +// Should only be used in TableGen. +def iPTRAny : ValueType<0, 251>; + +// Pseudo valuetype to represent "vector of any size" +def vAny : ValueType<0 , 252>; + +// Pseudo valuetype to represent "float of any format" +def fAny : ValueType<0 , 253>; + +// Pseudo valuetype to represent "integer of any bit width" +def iAny : ValueType<0 , 254>; + +// Pseudo valuetype mapped to the current pointer size. +def iPTR : ValueType<0 , 255>; diff --git a/final/include/llvm/CompilerDriver/Action.h b/final/include/llvm/CompilerDriver/Action.h new file mode 100644 index 00000000000..f2b79655f60 --- /dev/null +++ b/final/include/llvm/CompilerDriver/Action.h @@ -0,0 +1,54 @@ +//===--- Action.h - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Action - encapsulates a single shell command. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H +#define LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H + +#include +#include + +namespace llvmc { + + typedef std::vector StrVector; + + /// Action - A class that encapsulates a single shell command. + class Action { + /// Command_ - The actual command (for example, 'ls'). + std::string Command_; + /// Args_ - Command arguments. Stdout redirection ("> file") is allowed. + std::vector Args_; + /// StopCompilation_ - Should we stop compilation after executing + /// this action? + bool StopCompilation_; + /// OutFile_ - The output file name. + std::string OutFile_; + + public: + void Construct (const std::string& C, const StrVector& A, + bool S, const std::string& O) { + Command_ = C; + Args_ = A; + StopCompilation_ = S; + OutFile_ = O; + } + bool IsConstructed () { return (Command_.size() != 0);} + + /// Execute - Executes the command. Returns -1 on error. + int Execute () const; + bool StopCompilation () const { return StopCompilation_; } + const std::string& OutFile() { return OutFile_; } + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H diff --git a/final/include/llvm/CompilerDriver/AutoGenerated.h b/final/include/llvm/CompilerDriver/AutoGenerated.h new file mode 100644 index 00000000000..7b926c622c9 --- /dev/null +++ b/final/include/llvm/CompilerDriver/AutoGenerated.h @@ -0,0 +1,40 @@ +//===--- AutoGenerated.h - The LLVM Compiler Driver -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to the autogenerated driver code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H +#define LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H + +namespace llvmc { + class LanguageMap; + class CompilationGraph; + + namespace autogenerated { + + int PreprocessOptions(); + int PopulateLanguageMap(LanguageMap& langMap); + int PopulateCompilationGraph(CompilationGraph& graph); + + inline int RunInitialization (LanguageMap& M, CompilationGraph& G) { + if (int ret = PreprocessOptions()) + return ret; + if (int ret = PopulateLanguageMap(M)) + return ret; + if (int ret = PopulateCompilationGraph(G)) + return ret; + + return 0; + } + } +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H diff --git a/final/include/llvm/CompilerDriver/BuiltinOptions.h b/final/include/llvm/CompilerDriver/BuiltinOptions.h new file mode 100644 index 00000000000..7b9c15c52f7 --- /dev/null +++ b/final/include/llvm/CompilerDriver/BuiltinOptions.h @@ -0,0 +1,39 @@ +//===--- BuiltinOptions.h - The LLVM Compiler Driver ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declarations of all global command-line option variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H +#define LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H + +#include "llvm/Support/CommandLine.h" + +#include + +namespace llvmc { + +namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; } + +extern llvm::cl::list InputFilenames; +extern llvm::cl::opt OutputFilename; +extern llvm::cl::opt TempDirname; +extern llvm::cl::list Languages; +extern llvm::cl::opt DryRun; +extern llvm::cl::opt Time; +extern llvm::cl::opt VerboseMode; +extern llvm::cl::opt CheckGraph; +extern llvm::cl::opt ViewGraph; +extern llvm::cl::opt WriteGraph; +extern llvm::cl::opt SaveTemps; + +} // End namespace llvmc. + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H diff --git a/final/include/llvm/CompilerDriver/Common.td b/final/include/llvm/CompilerDriver/Common.td new file mode 100644 index 00000000000..84e8783d20a --- /dev/null +++ b/final/include/llvm/CompilerDriver/Common.td @@ -0,0 +1,124 @@ +//===- Common.td - Common definitions for LLVMC2 ----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains common definitions used in llvmc tool description files. +// +//===----------------------------------------------------------------------===// + +class Tool l> { + list properties = l; +} + +// Possible Tool properties. + +def in_language; +def out_language; +def output_suffix; +def command; +def out_file_option; +def in_file_option; +def join; +def sink; +def works_on_empty; +def actions; + +// Possible option types. + +def alias_option; +def switch_option; +def switch_list_option; +def parameter_option; +def parameter_list_option; +def prefix_option; +def prefix_list_option; + +// Possible option properties. + +def help; +def hidden; +def init; +def multi_val; +def one_or_more; +def zero_or_more; +def optional; +def really_hidden; +def required; +def comma_separated; +def forward_not_split; + +// The 'case' construct. +def case; + +// Boolean constants. +def true; +def false; + +// Boolean operators. +def and; +def or; +def not; + +// Primitive tests. +def switch_on; +def parameter_equals; +def element_in_list; +def input_languages_contain; +def empty; +def not_empty; +def default; +def single_input_file; +def multiple_input_files; +def any_switch_on; +def any_not_empty; +def any_empty; + +// Possible actions. + +def append_cmd; +def forward; +def forward_as; +def forward_value; +def forward_transformed_value; +def stop_compilation; +def no_out_file; +def unpack_values; +def warning; +def error; +def set_option; +def unset_option; + +// Increase the edge weight. +def inc_weight; + +// Option list - a single place to specify options. +class OptionList l> { + list options = l; +} + +// Option preprocessor - actions taken during plugin loading. +class OptionPreprocessor { + dag preprocessor = d; +} + +// Map from suffixes to language names + +def lang_to_suffixes; + +class LanguageMap l> { + list map = l; +} + +// Compilation graph + +def edge; +def optional_edge; + +class CompilationGraph l> { + list edges = l; +} diff --git a/final/include/llvm/CompilerDriver/CompilationGraph.h b/final/include/llvm/CompilerDriver/CompilationGraph.h new file mode 100644 index 00000000000..e1eea325e34 --- /dev/null +++ b/final/include/llvm/CompilerDriver/CompilationGraph.h @@ -0,0 +1,330 @@ +//===--- CompilationGraph.h - The LLVM Compiler Driver ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Compilation graph - definition. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H +#define LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H + +#include "llvm/CompilerDriver/Tool.h" + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Path.h" + +#include +#include + +namespace llvmc { + + class CompilationGraph; + typedef llvm::StringSet<> InputLanguagesSet; + + /// LanguageMap - Maps from extensions to language names. + class LanguageMap : public llvm::StringMap { + public: + + /// GetLanguage - Find the language name corresponding to a given file. + const std::string* GetLanguage(const llvm::sys::Path&) const; + }; + + /// Edge - Represents an edge of the compilation graph. + class Edge : public llvm::RefCountedBaseVPTR { + public: + Edge(const std::string& T) : ToolName_(T) {} + virtual ~Edge() {} + + const std::string& ToolName() const { return ToolName_; } + virtual int Weight(const InputLanguagesSet& InLangs) const = 0; + private: + std::string ToolName_; + }; + + /// SimpleEdge - An edge that has no properties. + class SimpleEdge : public Edge { + public: + SimpleEdge(const std::string& T) : Edge(T) {} + int Weight(const InputLanguagesSet&) const { return 1; } + }; + + /// Node - A node (vertex) of the compilation graph. + struct Node { + // A Node holds a list of the outward edges. + typedef llvm::SmallVector, 3> container_type; + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; + + Node() : OwningGraph(0), InEdges(0) {} + Node(CompilationGraph* G) : OwningGraph(G), InEdges(0) {} + Node(CompilationGraph* G, Tool* T) : + OwningGraph(G), ToolPtr(T), InEdges(0) {} + + bool HasChildren() const { return !OutEdges.empty(); } + const std::string Name() const + { return ToolPtr ? ToolPtr->Name() : "root"; } + + // Iteration. + iterator EdgesBegin() { return OutEdges.begin(); } + const_iterator EdgesBegin() const { return OutEdges.begin(); } + iterator EdgesEnd() { return OutEdges.end(); } + const_iterator EdgesEnd() const { return OutEdges.end(); } + + /// AddEdge - Add an outward edge. Takes ownership of the provided + /// Edge object. + void AddEdge(Edge* E); + + // Inward edge counter. Used to implement topological sort. + void IncrInEdges() { ++InEdges; } + void DecrInEdges() { --InEdges; } + bool HasNoInEdges() const { return InEdges == 0; } + + // Needed to implement NodeChildIterator/GraphTraits + CompilationGraph* OwningGraph; + // The corresponding Tool. + // WARNING: ToolPtr can be NULL (for the root node). + llvm::IntrusiveRefCntPtr ToolPtr; + // Links to children. + container_type OutEdges; + // Inward edge counter. Updated in + // CompilationGraph::insertEdge(). Used for topological sorting. + unsigned InEdges; + }; + + class NodesIterator; + + /// CompilationGraph - The compilation graph itself. + class CompilationGraph { + /// nodes_map_type - The main data structure. + typedef llvm::StringMap nodes_map_type; + /// tools_vector_type, tools_map_type - Data structures used to + /// map from language names to tools. (We can have several tools + /// associated with each language name, hence the need for a + /// vector.) + typedef + llvm::SmallVector, 3> tools_vector_type; + typedef llvm::StringMap tools_map_type; + + /// ToolsMap - Map from language names to lists of tool names. + tools_map_type ToolsMap; + /// NodesMap - Map from tool names to Tool objects. + nodes_map_type NodesMap; + + public: + + typedef nodes_map_type::iterator nodes_iterator; + typedef nodes_map_type::const_iterator const_nodes_iterator; + + CompilationGraph(); + + /// insertNode - Insert a new node into the graph. Takes + /// ownership of the object. + void insertNode(Tool* T); + + /// insertEdge - Insert a new edge into the graph. Takes ownership + /// of the Edge object. Returns non-zero value on error. + int insertEdge(const std::string& A, Edge* E); + + /// Build - Build target(s) from the input file set. Command-line options + /// are passed implicitly as global variables. Returns non-zero value on + /// error (usually the failed program's exit code). + int Build(llvm::sys::Path const& TempDir, const LanguageMap& LangMap); + + /// Check - Check the compilation graph for common errors like cycles, + /// input/output language mismatch and multiple default edges. Prints error + /// messages and in case it finds any errors. + int Check(); + + /// getNode - Return a reference to the node corresponding to the given tool + /// name. Returns 0 on error. + Node* getNode(const std::string& ToolName); + const Node* getNode(const std::string& ToolName) const; + + /// viewGraph - This function is meant for use from the debugger. You can + /// just say 'call G->viewGraph()' and a ghostview window should pop up from + /// the program, displaying the compilation graph. This depends on there + /// being a 'dot' and 'gv' program in your path. + void viewGraph(); + + /// writeGraph - Write Graphviz .dot source file to the current direcotry. + int writeGraph(const std::string& OutputFilename); + + // GraphTraits support. + friend NodesIterator GraphBegin(CompilationGraph*); + friend NodesIterator GraphEnd(CompilationGraph*); + + private: + // Helper functions. + + /// getToolsVector - Return a reference to the list of tool names + /// corresponding to the given language name. Returns 0 on error. + const tools_vector_type* getToolsVector(const std::string& LangName) const; + + /// PassThroughGraph - Pass the input file through the toolchain starting at + /// StartNode. + int PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode, + const InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap) const; + + /// FindToolChain - Find head of the toolchain corresponding to + /// the given file. + const Node* FindToolChain(const llvm::sys::Path& In, + const std::string* ForceLanguage, + InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const; + + /// BuildInitial - Traverse the initial parts of the toolchains. Returns + /// non-zero value on error. + int BuildInitial(InputLanguagesSet& InLangs, + const llvm::sys::Path& TempDir, + const LanguageMap& LangMap); + + /// TopologicalSort - Sort the nodes in topological order. Returns non-zero + /// value on error. + int TopologicalSort(std::vector& Out); + /// TopologicalSortFilterJoinNodes - Call TopologicalSort and filter the + /// resulting list to include only Join nodes. Returns non-zero value on + /// error. + int TopologicalSortFilterJoinNodes(std::vector& Out); + + // Functions used to implement Check(). + + /// CheckLanguageNames - Check that output/input language names match for + /// all nodes. Returns non-zero value on error (number of errors + /// encountered). + int CheckLanguageNames() const; + /// CheckMultipleDefaultEdges - check that there are no multiple default + /// default edges. Returns non-zero value on error (number of errors + /// encountered). + int CheckMultipleDefaultEdges() const; + /// CheckCycles - Check that there are no cycles in the graph. Returns + /// non-zero value on error (number of errors encountered). + int CheckCycles(); + + }; + + // GraphTraits support code. + + /// NodesIterator - Auxiliary class needed to implement GraphTraits + /// support. Can be generalised to something like value_iterator + /// for map-like containers. + class NodesIterator : public CompilationGraph::nodes_iterator { + typedef CompilationGraph::nodes_iterator super; + typedef NodesIterator ThisType; + typedef Node* pointer; + typedef Node& reference; + + public: + NodesIterator(super I) : super(I) {} + + inline reference operator*() const { + return super::operator->()->second; + } + inline pointer operator->() const { + return &super::operator->()->second; + } + }; + + inline NodesIterator GraphBegin(CompilationGraph* G) { + return NodesIterator(G->NodesMap.begin()); + } + + inline NodesIterator GraphEnd(CompilationGraph* G) { + return NodesIterator(G->NodesMap.end()); + } + + + /// NodeChildIterator - Another auxiliary class needed by GraphTraits. + class NodeChildIterator : public + std::iterator { + typedef NodeChildIterator ThisType; + typedef Node::container_type::iterator iterator; + + CompilationGraph* OwningGraph; + iterator EdgeIter; + public: + typedef Node* pointer; + typedef Node& reference; + + NodeChildIterator(Node* N, iterator I) : + OwningGraph(N->OwningGraph), EdgeIter(I) {} + + const ThisType& operator=(const ThisType& I) { + assert(OwningGraph == I.OwningGraph); + EdgeIter = I.EdgeIter; + return *this; + } + + inline bool operator==(const ThisType& I) const { + assert(OwningGraph == I.OwningGraph); + return EdgeIter == I.EdgeIter; + } + inline bool operator!=(const ThisType& I) const { + return !this->operator==(I); + } + + inline pointer operator*() const { + return OwningGraph->getNode((*EdgeIter)->ToolName()); + } + inline pointer operator->() const { + return this->operator*(); + } + + ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement + ThisType operator++(int) { // Postincrement + ThisType tmp = *this; + ++*this; + return tmp; + } + + inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement + inline ThisType operator--(int) { // Postdecrement + ThisType tmp = *this; + --*this; + return tmp; + } + + }; +} + +namespace llvm { + template <> + struct GraphTraits { + typedef llvmc::CompilationGraph GraphType; + typedef llvmc::Node NodeType; + typedef llvmc::NodeChildIterator ChildIteratorType; + + static NodeType* getEntryNode(GraphType* G) { + return G->getNode("root"); + } + + static ChildIteratorType child_begin(NodeType* N) { + return ChildIteratorType(N, N->OutEdges.begin()); + } + static ChildIteratorType child_end(NodeType* N) { + return ChildIteratorType(N, N->OutEdges.end()); + } + + typedef llvmc::NodesIterator nodes_iterator; + static nodes_iterator nodes_begin(GraphType *G) { + return GraphBegin(G); + } + static nodes_iterator nodes_end(GraphType *G) { + return GraphEnd(G); + } + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H diff --git a/final/include/llvm/CompilerDriver/Error.h b/final/include/llvm/CompilerDriver/Error.h new file mode 100644 index 00000000000..013094e5dd7 --- /dev/null +++ b/final/include/llvm/CompilerDriver/Error.h @@ -0,0 +1,29 @@ +//===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Error handling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H +#define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvmc { + + inline void PrintError(llvm::StringRef Err) { + extern const char* ProgramName; + llvm::errs() << ProgramName << ": " << Err << '\n'; + } + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H diff --git a/final/include/llvm/CompilerDriver/Main.h b/final/include/llvm/CompilerDriver/Main.h new file mode 100644 index 00000000000..d136a5d2fa1 --- /dev/null +++ b/final/include/llvm/CompilerDriver/Main.h @@ -0,0 +1,21 @@ +//===--- Main.h - The LLVM Compiler Driver ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Entry point for the driver executable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H +#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H + +namespace llvmc { + int Main(int argc, char** argv); +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H diff --git a/final/include/llvm/CompilerDriver/Main.inc b/final/include/llvm/CompilerDriver/Main.inc new file mode 100644 index 00000000000..41640437de8 --- /dev/null +++ b/final/include/llvm/CompilerDriver/Main.inc @@ -0,0 +1,23 @@ +//===--- Main.inc - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Default main() for the driver executable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC +#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC + +#include "llvm/CompilerDriver/Main.h" + +int main(int argc, char** argv) { + return llvmc::Main(argc, argv); +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC diff --git a/final/include/llvm/CompilerDriver/Tool.h b/final/include/llvm/CompilerDriver/Tool.h new file mode 100644 index 00000000000..d0926ba9831 --- /dev/null +++ b/final/include/llvm/CompilerDriver/Tool.h @@ -0,0 +1,100 @@ +//===--- Tool.h - The LLVM Compiler Driver ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tool abstract base class - an interface to tool descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H +#define LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H + +#include "llvm/CompilerDriver/Action.h" + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Path.h" + +#include +#include +#include + +namespace llvmc { + + class LanguageMap; + typedef std::vector > ArgsVector; + typedef std::vector PathVector; + typedef std::vector StrVector; + typedef llvm::StringSet<> InputLanguagesSet; + + /// Tool - Represents a single tool. + class Tool : public llvm::RefCountedBaseVPTR { + public: + + virtual ~Tool() {} + + /// GenerateAction - Generate an Action given particular command-line + /// options. Returns non-zero value on error. + virtual int GenerateAction (Action& Out, + const PathVector& inFiles, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; + + /// GenerateAction - Generate an Action given particular command-line + /// options. Returns non-zero value on error. + virtual int GenerateAction (Action& Out, + const llvm::sys::Path& inFile, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const = 0; + + virtual const char* Name() const = 0; + virtual const char** InputLanguages() const = 0; + virtual const char** OutputLanguages() const = 0; + + virtual bool IsJoin() const = 0; + virtual bool WorksOnEmpty() const = 0; + + protected: + /// OutFileName - Generate the output file name. + llvm::sys::Path OutFilename(const llvm::sys::Path& In, + const llvm::sys::Path& TempDir, + bool StopCompilation, + const char* OutputSuffix) const; + + StrVector SortArgs(ArgsVector& Args) const; + }; + + /// JoinTool - A Tool that has an associated input file list. + class JoinTool : public Tool { + public: + void AddToJoinList(const llvm::sys::Path& P) { JoinList_.push_back(P); } + void ClearJoinList() { JoinList_.clear(); } + bool JoinListEmpty() const { return JoinList_.empty(); } + + int GenerateAction(Action& Out, + const bool HasChildren, + const llvm::sys::Path& TempDir, + const InputLanguagesSet& InLangs, + const LanguageMap& LangMap) const { + return GenerateAction(Out, JoinList_, HasChildren, TempDir, InLangs, + LangMap); + } + // We shouldn't shadow base class's version of GenerateAction. + using Tool::GenerateAction; + + private: + PathVector JoinList_; + }; + +} + +#endif // LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H diff --git a/final/include/llvm/Config/AsmParsers.def.in b/final/include/llvm/Config/AsmParsers.def.in new file mode 100644 index 00000000000..041af837541 --- /dev/null +++ b/final/include/llvm/Config/AsmParsers.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmParsers.def - LLVM Assembly Parsers -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PARSER +# error Please define the macro LLVM_ASM_PARSER(TargetName) +#endif + +@LLVM_ENUM_ASM_PARSERS@ + +#undef LLVM_ASM_PARSER diff --git a/final/include/llvm/Config/AsmPrinters.def.in b/final/include/llvm/Config/AsmPrinters.def.in new file mode 100644 index 00000000000..9729bd75eb4 --- /dev/null +++ b/final/include/llvm/Config/AsmPrinters.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmPrinters.def - LLVM Assembly Printers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language printers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PRINTER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly printers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PRINTER +# error Please define the macro LLVM_ASM_PRINTER(TargetName) +#endif + +@LLVM_ENUM_ASM_PRINTERS@ + +#undef LLVM_ASM_PRINTER diff --git a/final/include/llvm/Config/Disassemblers.def.in b/final/include/llvm/Config/Disassemblers.def.in new file mode 100644 index 00000000000..1b136570933 --- /dev/null +++ b/final/include/llvm/Config/Disassemblers.def.in @@ -0,0 +1,29 @@ +//===- llvm/Config/Disassemblers.def - LLVM Assembly Parsers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DISASSEMBLER +# error Please define the macro LLVM_DISASSEMBLER(TargetName) +#endif + +@LLVM_ENUM_DISASSEMBLERS@ + +#undef LLVM_DISASSEMBLER diff --git a/final/include/llvm/Config/Targets.def.in b/final/include/llvm/Config/Targets.def.in new file mode 100644 index 00000000000..d589ecee12c --- /dev/null +++ b/final/include/llvm/Config/Targets.def.in @@ -0,0 +1,28 @@ +/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file enumerates all of the target architectures supported by *| +|* this build of LLVM. Clients of this file should define the *| +|* LLVM_TARGET macro to be a function-like macro with a single *| +|* parameter (the name of the target); including this file will then *| +|* enumerate all of the targets. *| +|* *| +|* The set of targets supported by LLVM is generated at configuration *| +|* time, at which point this header is generated. Do not modify this *| +|* header directly. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_TARGET +# error Please define the macro LLVM_TARGET(TargetName) +#endif + +@LLVM_ENUM_TARGETS@ + +#undef LLVM_TARGET diff --git a/final/include/llvm/Config/config.h.cmake b/final/include/llvm/Config/config.h.cmake new file mode 100644 index 00000000000..b2deb1dccf5 --- /dev/null +++ b/final/include/llvm/Config/config.h.cmake @@ -0,0 +1,737 @@ +/************************************** +** Created by Kevin from config.h.in ** +***************************************/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* Define if CBE is enabled for printf %a output */ +#cmakedefine ENABLE_CBE_PRINTF_A ${ENABLE_CBE_PRINTF_A} + +/* Define if position independent code is enabled */ +#cmakedefine ENABLE_PIC + +/* Define if threads enabled */ +#cmakedefine ENABLE_THREADS ${ENABLE_THREADS} + +/* Define if timestamp information (e.g., __DATE___) is allowed */ +#cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS} + +/* Define to 1 if you have the `argz_append' function. */ +#cmakedefine HAVE_ARGZ_APPEND ${HAVE_ARGZ_APPEND} + +/* Define to 1 if you have the `argz_create_sep' function. */ +#cmakedefine HAVE_ARGZ_CREATE_SEP ${HAVE_ARGZ_CREATE_SEP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ARGZ_H ${HAVE_ARGZ_H} + +/* Define to 1 if you have the `argz_insert' function. */ +#cmakedefine HAVE_ARGZ_INSERT ${HAVE_ARGZ_INSERT} + +/* Define to 1 if you have the `argz_next' function. */ +#cmakedefine HAVE_ARGZ_NEXT ${HAVE_ARGZ_NEXT} + +/* Define to 1 if you have the `argz_stringify' function. */ +#cmakedefine HAVE_ARGZ_STRINGIFY ${HAVE_ARGZ_STRINGIFY} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Define to 1 if you have the `ceilf' function. */ +#cmakedefine HAVE_CEILF ${HAVE_CEILF} + +/* Define if the neat program is available */ +#cmakedefine HAVE_CIRCO ${HAVE_CIRCO} + +/* Define to 1 if you have the `closedir' function. */ +#cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRASHREPORTERCLIENT_H + +/* Define if __crashreporter_info__ exists. */ +#undef HAVE_CRASHREPORTER_INFO + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CTYPE_H ${HAVE_CTYPE_H} + +/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you + don't. */ +#cmakedefine01 HAVE_DECL_STRERROR_S + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_DIRENT_H ${HAVE_DIRENT_H} + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLD_H ${HAVE_DLD_H} + +/* Define to 1 if you have the `dlerror' function. */ +#cmakedefine HAVE_DLERROR ${HAVE_DLERROR} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H ${HAVE_DLFCN_H} + +/* Define if dlopen() is available on this platform. */ +#cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DL_H ${HAVE_DL_H} + +/* Define if the dot program is available */ +#cmakedefine HAVE_DOT ${HAVE_DOT} + +/* Define if the dotty program is available */ +#cmakedefine HAVE_DOTTY ${HAVE_DOTTY} + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} + +/* Define to 1 if the system has the type `error_t'. */ +#cmakedefine HAVE_ERROR_T ${HAVE_ERROR_T} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_EXECINFO_H ${HAVE_EXECINFO_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} + +/* Define if the neat program is available */ +#cmakedefine HAVE_FDP ${HAVE_FDP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FENV_H ${HAVE_FENV_H} + +/* Define if libffi is available on this platform. */ +#cmakedefine HAVE_FFI_CALL ${HAVE_FFI_CALL} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FFI_FFI_H ${HAVE_FFI_FFI_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FFI_H ${HAVE_FFI_H} + +/* Set to 1 if the finite function is found in */ +#cmakedefine HAVE_FINITE_IN_IEEEFP_H ${HAVE_FINITE_IN_IEEEFP_H} + +/* Define to 1 if you have the `floorf' function. */ +#cmakedefine HAVE_FLOORF ${HAVE_FLOORF} + +/* Define to 1 if you have the `fmodf' function. */ +#cmakedefine HAVE_FMODF ${HAVE_FMODF} + +/* Define to 1 if you have the `getcwd' function. */ +#cmakedefine HAVE_GETCWD ${HAVE_GETCWD} + +/* Define to 1 if you have the `getpagesize' function. */ +#cmakedefine HAVE_GETPAGESIZE ${HAVE_GETPAGESIZE} + +/* Define to 1 if you have the `getrlimit' function. */ +#cmakedefine HAVE_GETRLIMIT ${HAVE_GETRLIMIT} + +/* Define to 1 if you have the `getrusage' function. */ +#cmakedefine HAVE_GETRUSAGE ${HAVE_GETRUSAGE} + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} + +/* Define if the Graphviz program is available */ +#undef HAVE_GRAPHVIZ + +/* Define if the gv program is available */ +#cmakedefine HAVE_GV ${HAVE_GV} + +/* Define to 1 if you have the `index' function. */ +#cmakedefine HAVE_INDEX ${HAVE_INDEX} + +/* Define to 1 if the system has the type `int64_t'. */ +#cmakedefine HAVE_INT64_T ${HAVE_INT64_T} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} + +/* Define to 1 if you have the `isatty' function. */ +#cmakedefine HAVE_ISATTY 1 + +/* Set to 1 if the isinf function is found in */ +#cmakedefine HAVE_ISINF_IN_CMATH ${HAVE_ISINF_IN_CMATH} + +/* Set to 1 if the isinf function is found in */ +#cmakedefine HAVE_ISINF_IN_MATH_H ${HAVE_ISINF_IN_MATH_H} + +/* Set to 1 if the isnan function is found in */ +#cmakedefine HAVE_ISNAN_IN_CMATH ${HAVE_ISNAN_IN_CMATH} + +/* Set to 1 if the isnan function is found in */ +#cmakedefine HAVE_ISNAN_IN_MATH_H ${HAVE_ISNAN_IN_MATH_H} + +/* Define if you have the libdl library or equivalent. */ +#cmakedefine HAVE_LIBDL ${HAVE_LIBDL} + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +#cmakedefine HAVE_LIBIMAGEHLP ${HAVE_LIBIMAGEHLP} + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +#cmakedefine HAVE_LIBPSAPI ${HAVE_LIBPSAPI} + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine HAVE_LIBPTHREAD ${HAVE_LIBPTHREAD} + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +#undef HAVE_LIBUDIS86 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} + +/* Define if you can use -Wl,-export-dynamic. */ +#define HAVE_LINK_EXPORT_DYNAMIC 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINK_H ${HAVE_LINK_H} + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add + the current directory to the dynamic linker search path. */ +#undef HAVE_LINK_R + +/* Define to 1 if you have the `longjmp' function. */ +#cmakedefine HAVE_LONGJMP ${HAVE_LONGJMP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MACH_MACH_H ${HAVE_MACH_MACH_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MACH_O_DYLD_H ${HAVE_MACH_O_DYLD_H} + +/* Define if mallinfo() is available on this platform. */ +#cmakedefine HAVE_MALLINFO ${HAVE_MALLINFO} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_H ${HAVE_MALLOC_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_MALLOC_H ${HAVE_MALLOC_MALLOC_H} + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +#cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} + +/* Define to 1 if you have the `memcpy' function. */ +#cmakedefine HAVE_MEMCPY ${HAVE_MEMCPY} + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE ${HAVE_MEMMOVE} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} + +/* Define to 1 if you have the `mkdtemp' function. */ +#cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} + +/* Define to 1 if you have the `mkstemp' function. */ +#cmakedefine HAVE_MKSTEMP ${HAVE_MKSTEMP} + +/* Define to 1 if you have the `mktemp' function. */ +#cmakedefine HAVE_MKTEMP ${HAVE_MKTEMP} + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} + +/* Define to 1 if you have the `nearbyintf' function. */ +#cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF} + +/* Define if the neat program is available */ +#cmakedefine HAVE_NEATO ${HAVE_NEATO} + +/* Define to 1 if you have the `opendir' function. */ +#cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR} + +/* Define to 1 if you have the `posix_spawn' function. */ +#cmakedefine HAVE_POSIX_SPAWN ${HAVE_POSIX_SPAWN} + +/* Define to 1 if you have the `powf' function. */ +#cmakedefine HAVE_POWF ${HAVE_POWF} + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread_getspecific */ +#cmakedefine HAVE_PTHREAD_GETSPECIFIC ${HAVE_PTHREAD_GETSPECIFIC} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_PTHREAD_H ${HAVE_PTHREAD_H} + +/* Have pthread_mutex_lock */ +#cmakedefine HAVE_PTHREAD_MUTEX_LOCK ${HAVE_PTHREAD_MUTEX_LOCK} + +/* Have pthread_rwlock_init */ +#cmakedefine HAVE_PTHREAD_RWLOCK_INIT ${HAVE_PTHREAD_RWLOCK_INIT} + +/* Define to 1 if srand48/lrand48/drand48 exist in */ +#cmakedefine HAVE_RAND48 ${HAVE_RAND48} + +/* Define to 1 if you have the `readdir' function. */ +#cmakedefine HAVE_READDIR ${HAVE_READDIR} + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `rindex' function. */ +#cmakedefine HAVE_RINDEX ${HAVE_RINDEX} + +/* Define to 1 if you have the `rintf' function. */ +#undef HAVE_RINTF + +/* Define to 1 if you have the `round' function. */ +#cmakedefine HAVE_ROUND ${HAVE_ROUND} + +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + +/* Define to 1 if you have the `sbrk' function. */ +#cmakedefine HAVE_SBRK ${HAVE_SBRK} + +/* Define to 1 if you have the `setenv' function. */ +#cmakedefine HAVE_SETENV ${HAVE_SETENV} + +/* Define to 1 if you have the `setjmp' function. */ +#cmakedefine HAVE_SETJMP ${HAVE_SETJMP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} + +/* Define to 1 if you have the `setrlimit' function. */ +#cmakedefine HAVE_SETRLIMIT ${HAVE_SETRLIMIT} + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +#cmakedefine HAVE_SIGLONGJMP ${HAVE_SIGLONGJMP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H ${HAVE_SIGNAL_H} + +/* Define to 1 if you have the `sigsetjmp' function. */ +#cmakedefine HAVE_SIGSETJMP ${HAVE_SIGSETJMP} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} + +/* Set to 1 if the std::isinf function is found in */ +#undef HAVE_STD_ISINF_IN_CMATH + +/* Set to 1 if the std::isnan function is found in */ +#undef HAVE_STD_ISNAN_IN_CMATH + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR ${HAVE_STRCHR} + +/* Define to 1 if you have the `strcmp' function. */ +#cmakedefine HAVE_STRCMP ${HAVE_STRCMP} + +/* Define to 1 if you have the `strdup' function. */ +#cmakedefine HAVE_STRDUP ${HAVE_STRDUP} + +/* Define to 1 if you have the `strerror' function. */ +#cmakedefine HAVE_STRERROR ${HAVE_STRERROR} + +/* Define to 1 if you have the `strerror_r' function. */ +#cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR ${HAVE_STRRCHR} + +/* Define to 1 if you have the `strtof' function. */ +#cmakedefine HAVE_STRTOF ${HAVE_STRTOF} + +/* Define to 1 if you have the `strtoll' function. */ +#cmakedefine HAVE_STRTOLL ${HAVE_STRTOLL} + +/* Define to 1 if you have the `strtoq' function. */ +#cmakedefine HAVE_STRTOQ ${HAVE_STRTOQ} + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_DIR_H ${HAVE_SYS_DIR_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_DL_H ${HAVE_SYS_DL_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_MMAN_H ${} + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#cmakedefine HAVE_SYS_NDIR_H ${HAVE_SYS_NDIR_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_PARAM_H ${HAVE_SYS_PARAM_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_RESOURCE_H ${HAVE_SYS_RESOURCE_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H ${HAVE_SYS_STAT_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H ${HAVE_SYS_TIME_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_UIO_H ${HAVE_SYS_UIO_H} + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H ${HAVE_UNISTD_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UTIME_H ${HAVE_UTIME_H} + +/* Define to 1 if the system has the type `u_int64_t'. */ +#cmakedefine HAVE_U_INT64_T ${HAVE_U_INT64_T} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_VALGRIND_VALGRIND_H ${HAVE_VALGRIND_VALGRIND_H} + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H} + +/* Define to 1 if you have the `writev' function. */ +#cmakedefine HAVE_WRITEV ${HAVE_WRITEV} + +/* Define if the xdot.py program is available */ +#cmakedefine HAVE_XDOT_PY ${HAVE_XDOT_PY} + +/* Have host's _alloca */ +#cmakedefine HAVE__ALLOCA ${HAVE__ALLOCA} + +/* Have host's __alloca */ +#cmakedefine HAVE___ALLOCA ${HAVE___ALLOCA} + +/* Have host's __ashldi3 */ +#cmakedefine HAVE___ASHLDI3 ${HAVE___ASHLDI3} + +/* Have host's __ashrdi3 */ +#cmakedefine HAVE___ASHRDI3 ${HAVE___ASHRDI3} + +/* Have host's __chkstk */ +#cmakedefine HAVE___CHKSTK ${HAVE___CHKSTK} + +/* Have host's __cmpdi2 */ +#cmakedefine HAVE___CMPDI2 ${HAVE___CMPDI2} + +/* Have host's __divdi3 */ +#cmakedefine HAVE___DIVDI3 ${HAVE___DIVDI3} + +/* Define to 1 if you have the `__dso_handle' function. */ +#undef HAVE___DSO_HANDLE + +/* Have host's __fixdfdi */ +#cmakedefine HAVE___FIXDFDI ${HAVE___FIXDFDI} + +/* Have host's __fixsfdi */ +#cmakedefine HAVE___FIXSFDI ${HAVE___FIXSFDI} + +/* Have host's __floatdidf */ +#cmakedefine HAVE___FLOATDIDF ${HAVE___FLOATDIDF} + +/* Have host's __lshrdi3 */ +#cmakedefine HAVE___LSHRDI3 ${HAVE___LSHRDI3} + +/* Have host's __main */ +#cmakedefine HAVE___MAIN ${HAVE___MAIN} + +/* Have host's __moddi3 */ +#cmakedefine HAVE___MODDI3 ${HAVE___MODDI3} + +/* Have host's __udivdi3 */ +#cmakedefine HAVE___UDIVDI3 ${HAVE___UDIVDI3} + +/* Have host's __umoddi3 */ +#cmakedefine HAVE___UMODDI3 ${HAVE___UMODDI3} + +/* Have host's ___chkstk */ +#cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} + +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for documentation */ +#undef LLVM_DATADIR + +/* Installation directory for documentation */ +#undef LLVM_DOCSDIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Host triple we were built on */ +#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}" + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Build multithreading support into LLVM */ +#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED} + +/* LLVM architecture name for the native architecture, if available */ +#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} + +/* LLVM name for the native AsmPrinter init function, if available */ +#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter + +/* LLVM name for the native Target init function, if available */ +#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target + +/* LLVM name for the native TargetInfo init function, if available */ +#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo + +/* Define if this is Unixish platform */ +#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} + +/* Define if this is Win32ish platform */ +#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" + +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}" + +/* Installation prefix directory */ +#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#cmakedefine LTDL_DLOPEN_DEPLIBS ${LTDL_DLOPEN_DEPLIBS} + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#cmakedefine LTDL_SHLIBPATH_VAR "${LTDL_SHLIBPATH_VAR}" + +/* Define to the extension used for shared libraries, say, ".so". */ +#cmakedefine LTDL_SHLIB_EXT "${LTDL_SHLIB_EXT}" + +/* Define to the system default library search path. */ +#cmakedefine LTDL_SYSSEARCHPATH "${LTDL_SYSSEARCHPATH}" + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME "${PACKAGE_NAME}" + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING "${PACKAGE_STRING}" + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION "${PACKAGE_VERSION}" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#cmakedefine RETSIGTYPE ${RETSIGTYPE} + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if we have the oprofile JIT-support library */ +#undef USE_OPROFILE + +/* Define if use udis86 library */ +#undef USE_UDIS86 + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +#cmakedefine error_t ${error_t} + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define if the neat program is available */ +#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} + +/* Define to 1 if the system has the type `uint64_t'. */ +#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* Define to a type to use for `mode_t' if it is not otherwise available. */ +#cmakedefine mode_t ${mode_t} + +/* Define to a function replacing strtoll */ +#cmakedefine strtoll ${strtoll} + +/* Define to a function implementing strtoull */ +#cmakedefine strtoull ${strtoull} + +/* Define to a function implementing stricmp */ +#cmakedefine stricmp ${stricmp} + +/* Define to a function implementing strdup */ +#cmakedefine strdup ${strdup} + +/* Define to 1 if you have the `_chsize_s' function. */ +#cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} + +/* define if the compiler implements namespaces */ +#undef HAVE_NAMESPACES + +/* Does not have std namespace iterator */ +#undef HAVE_STD_ITERATOR + +/* Does not have forward iterator */ +#undef HAVE_FWD_ITERATOR + +/* Does not have bi-directional iterator */ +#undef HAVE_BI_ITERATOR + +/* Does not have */ +#undef HAVE_GLOBAL_HASH_MAP + +/* Does not have hash_set in global namespace */ +#undef HAVE_GLOBAL_HASH_SET + +/* Does not have ext/hash_map */ +#undef HAVE_GNU_EXT_HASH_MAP + +/* Does not have hash_set in gnu namespace */ +#undef HAVE_GNU_EXT_HASH_SET + +/* Does not have ext/hash_map> */ +#undef HAVE_STD_EXT_HASH_MAP + +/* Does not have hash_set in std namespace */ +#undef HAVE_STD_EXT_HASH_SET + +/* Added by Kevin -- Maximum path length */ +#cmakedefine MAXPATHLEN ${MAXPATHLEN} + +#endif diff --git a/final/include/llvm/Config/config.h.in b/final/include/llvm/Config/config.h.in new file mode 100644 index 00000000000..14c44b4b1e2 --- /dev/null +++ b/final/include/llvm/Config/config.h.in @@ -0,0 +1,687 @@ +/* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */ + +#ifndef CONFIG_H +#define CONFIG_H + +/* Relative directory for resource files */ +#undef CLANG_RESOURCE_DIR + +/* 32 bit multilib directory. */ +#undef CXX_INCLUDE_32BIT_DIR + +/* 64 bit multilib directory. */ +#undef CXX_INCLUDE_64BIT_DIR + +/* Arch the libstdc++ headers. */ +#undef CXX_INCLUDE_ARCH + +/* Directory with the libstdc++ headers. */ +#undef CXX_INCLUDE_ROOT + +/* Directories clang will search for headers */ +#undef C_INCLUDE_DIRS + +/* Define if CBE is enabled for printf %a output */ +#undef ENABLE_CBE_PRINTF_A + +/* Define if position independent code is enabled */ +#undef ENABLE_PIC + +/* Define if threads enabled */ +#undef ENABLE_THREADS + +/* Define if timestamp information (e.g., __DATE___) is allowed */ +#undef ENABLE_TIMESTAMPS + +/* Define to 1 if you have the `argz_append' function. */ +#undef HAVE_ARGZ_APPEND + +/* Define to 1 if you have the `argz_create_sep' function. */ +#undef HAVE_ARGZ_CREATE_SEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define to 1 if you have the `argz_insert' function. */ +#undef HAVE_ARGZ_INSERT + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* Define to 1 if you have the `argz_stringify' function. */ +#undef HAVE_ARGZ_STRINGIFY + +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `bcopy' function. */ +#undef HAVE_BCOPY + +/* Define to 1 if you have the `ceilf' function. */ +#undef HAVE_CEILF + +/* Define if the neat program is available */ +#undef HAVE_CIRCO + +/* Define to 1 if you have the `closedir' function. */ +#undef HAVE_CLOSEDIR + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRASHREPORTERCLIENT_H + +/* Define if __crashreporter_info__ exists. */ +#undef HAVE_CRASHREPORTER_INFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the declaration of `strerror_s', and to 0 if you + don't. */ +#undef HAVE_DECL_STRERROR_S + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define if you have the GNU dld library. */ +#undef HAVE_DLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLD_H + +/* Define to 1 if you have the `dlerror' function. */ +#undef HAVE_DLERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if dlopen() is available on this platform. */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_DL_H + +/* Define if the dot program is available */ +#undef HAVE_DOT + +/* Define if the dotty program is available */ +#undef HAVE_DOTTY + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if the system has the type `error_t'. */ +#undef HAVE_ERROR_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if the neat program is available */ +#undef HAVE_FDP + +/* Define to 1 if you have the header file. */ +#undef HAVE_FENV_H + +/* Define if libffi is available on this platform. */ +#undef HAVE_FFI_CALL + +/* Define to 1 if you have the header file. */ +#undef HAVE_FFI_FFI_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FFI_H + +/* Set to 1 if the finite function is found in */ +#undef HAVE_FINITE_IN_IEEEFP_H + +/* Define to 1 if you have the `floorf' function. */ +#undef HAVE_FLOORF + +/* Define to 1 if you have the `fmodf' function. */ +#undef HAVE_FMODF + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if the Graphviz program is available */ +#undef HAVE_GRAPHVIZ + +/* Define if the gv program is available */ +#undef HAVE_GV + +/* Define to 1 if you have the `index' function. */ +#undef HAVE_INDEX + +/* Define to 1 if the system has the type `int64_t'. */ +#undef HAVE_INT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isatty' function. */ +#undef HAVE_ISATTY + +/* Set to 1 if the isinf function is found in */ +#undef HAVE_ISINF_IN_CMATH + +/* Set to 1 if the isinf function is found in */ +#undef HAVE_ISINF_IN_MATH_H + +/* Set to 1 if the isnan function is found in */ +#undef HAVE_ISNAN_IN_CMATH + +/* Set to 1 if the isnan function is found in */ +#undef HAVE_ISNAN_IN_MATH_H + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +#undef HAVE_LIBIMAGEHLP + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +#undef HAVE_LIBPSAPI + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +#undef HAVE_LIBUDIS86 + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you can use -Wl,-export-dynamic. */ +#undef HAVE_LINK_EXPORT_DYNAMIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINK_H + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add + the current directory to the dynamic linker search path. */ +#undef HAVE_LINK_R + +/* Define to 1 if you have the `longjmp' function. */ +#undef HAVE_LONGJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_MACH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_O_DYLD_H + +/* Define if mallinfo() is available on this platform. */ +#undef HAVE_MALLINFO + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_MALLOC_H + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +#undef HAVE_MALLOC_ZONE_STATISTICS + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `nearbyintf' function. */ +#undef HAVE_NEARBYINTF + +/* Define if the neat program is available */ +#undef HAVE_NEATO + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define to 1 if you have the `posix_spawn' function. */ +#undef HAVE_POSIX_SPAWN + +/* Define to 1 if you have the `powf' function. */ +#undef HAVE_POWF + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread_getspecific */ +#undef HAVE_PTHREAD_GETSPECIFIC + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Have pthread_mutex_lock */ +#undef HAVE_PTHREAD_MUTEX_LOCK + +/* Have pthread_rwlock_init */ +#undef HAVE_PTHREAD_RWLOCK_INIT + +/* Define to 1 if srand48/lrand48/drand48 exist in */ +#undef HAVE_RAND48 + +/* Define to 1 if you have the `readdir' function. */ +#undef HAVE_READDIR + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `rindex' function. */ +#undef HAVE_RINDEX + +/* Define to 1 if you have the `rintf' function. */ +#undef HAVE_RINTF + +/* Define to 1 if you have the `round' function. */ +#undef HAVE_ROUND + +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `setjmp' function. */ +#undef HAVE_SETJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +#undef HAVE_SIGLONGJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `sigsetjmp' function. */ +#undef HAVE_SIGSETJMP + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Set to 1 if the std::isinf function is found in */ +#undef HAVE_STD_ISINF_IN_CMATH + +/* Set to 1 if the std::isnan function is found in */ +#undef HAVE_STD_ISNAN_IN_CMATH + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcmp' function. */ +#undef HAVE_STRCMP + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strerror_r' function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtof' function. */ +#undef HAVE_STRTOF + +/* Define to 1 if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define to 1 if you have the `strtoq' function. */ +#undef HAVE_STRTOQ + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if the neat program is available */ +#undef HAVE_TWOPI + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if the system has the type `u_int64_t'. */ +#undef HAVE_U_INT64_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_VALGRIND_VALGRIND_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_WINDOWS_H + +/* Define to 1 if you have the `writev' function. */ +#undef HAVE_WRITEV + +/* Define if the xdot.py program is available */ +#undef HAVE_XDOT_PY + +/* Have host's _alloca */ +#undef HAVE__ALLOCA + +/* Have host's __alloca */ +#undef HAVE___ALLOCA + +/* Have host's __ashldi3 */ +#undef HAVE___ASHLDI3 + +/* Have host's __ashrdi3 */ +#undef HAVE___ASHRDI3 + +/* Have host's __chkstk */ +#undef HAVE___CHKSTK + +/* Have host's __cmpdi2 */ +#undef HAVE___CMPDI2 + +/* Have host's __divdi3 */ +#undef HAVE___DIVDI3 + +/* Define to 1 if you have the `__dso_handle' function. */ +#undef HAVE___DSO_HANDLE + +/* Have host's __fixdfdi */ +#undef HAVE___FIXDFDI + +/* Have host's __fixsfdi */ +#undef HAVE___FIXSFDI + +/* Have host's __floatdidf */ +#undef HAVE___FLOATDIDF + +/* Have host's __lshrdi3 */ +#undef HAVE___LSHRDI3 + +/* Have host's __main */ +#undef HAVE___MAIN + +/* Have host's __moddi3 */ +#undef HAVE___MODDI3 + +/* Have host's __udivdi3 */ +#undef HAVE___UDIVDI3 + +/* Have host's __umoddi3 */ +#undef HAVE___UMODDI3 + +/* Have host's ___chkstk */ +#undef HAVE____CHKSTK + +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for data files */ +#undef LLVM_DATADIR + +/* Installation directory for documentation */ +#undef LLVM_DOCSDIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Host triple we were built on */ +#undef LLVM_HOSTTRIPLE + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Build multithreading support into LLVM */ +#undef LLVM_MULTITHREADED + +/* LLVM architecture name for the native architecture, if available */ +#undef LLVM_NATIVE_ARCH + +/* LLVM name for the native AsmPrinter init function, if available */ +#undef LLVM_NATIVE_ASMPRINTER + +/* LLVM name for the native Target init function, if available */ +#undef LLVM_NATIVE_TARGET + +/* LLVM name for the native TargetInfo init function, if available */ +#undef LLVM_NATIVE_TARGETINFO + +/* Define if this is Unixish platform */ +#undef LLVM_ON_UNIX + +/* Define if this is Win32ish platform */ +#undef LLVM_ON_WIN32 + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#undef LLVM_PATH_CIRCO + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#undef LLVM_PATH_DOT + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#undef LLVM_PATH_DOTTY + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#undef LLVM_PATH_FDP + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#undef LLVM_PATH_GV + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#undef LLVM_PATH_NEATO + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#undef LLVM_PATH_TWOPI + +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +#undef LLVM_PATH_XDOT_PY + +/* Installation prefix directory */ +#undef LLVM_PREFIX + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#undef LTDL_DLOPEN_DEPLIBS + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#undef LTDL_SHLIBPATH_VAR + +/* Define to the extension used for shared libraries, say, ".so". */ +#undef LTDL_SHLIB_EXT + +/* Define to the system default library search path. */ +#undef LTDL_SYSSEARCHPATH + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if we have the oprofile JIT-support library */ +#undef USE_OPROFILE + +/* Define if use udis86 library */ +#undef USE_UDIS86 + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +#undef error_t + +/* Define to `int' if does not define. */ +#undef pid_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +#endif diff --git a/final/include/llvm/Config/llvm-config.h.cmake b/final/include/llvm/Config/llvm-config.h.cmake new file mode 100644 index 00000000000..33a40350d5c --- /dev/null +++ b/final/include/llvm/Config/llvm-config.h.cmake @@ -0,0 +1,100 @@ +/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +/* This file enumerates all of the llvm variables from configure so that + they can be in exported headers and won't override package specific + directives. This is a C file so we can include it in the llvm-c headers. */ + +/* To avoid multiple inclusions of these variables when we include the exported + headers and config.h, conditionally include these. */ +/* TODO: This is a bit of a hack. */ +#ifndef CONFIG_H + +/* Installation directory for binary executables */ +#cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" + +/* Time at which LLVM was configured */ +#cmakedefine LLVM_CONFIGTIME "${LLVM_CONFIGTIME}" + +/* Installation directory for data files */ +#cmakedefine LLVM_DATADIR "${LLVM_DATADIR}" + +/* Installation directory for documentation */ +#cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" + +/* Installation directory for config files */ +#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" + +/* Host triple we were built on */ +#cmakedefine LLVM_HOSTTRIPLE "${LLVM_HOSTTRIPLE}" + +/* Installation directory for include files */ +#cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" + +/* Installation directory for .info files */ +#cmakedefine LLVM_INFODIR "${LLVM_INFODIR}" + +/* Installation directory for libraries */ +#cmakedefine LLVM_LIBDIR "${LLVM_LIBDIR}" + +/* Installation directory for man pages */ +#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}" + +/* Build multithreading support into LLVM */ +#cmakedefine LLVM_MULTITHREADED ${LLVM_MULTITHREADED} + +/* LLVM architecture name for the native architecture, if available */ +#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} + +/* LLVM name for the native Target init function, if available */ +#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target + +/* LLVM name for the native TargetInfo init function, if available */ +#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo + +/* LLVM name for the native AsmPrinter init function, if available */ +#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter + +/* Define if this is Unixish platform */ +#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} + +/* Define if this is Win32ish platform */ +#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}" + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" + +/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ +#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT.PY}" + +/* Installation prefix directory */ +#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" + +#endif diff --git a/final/include/llvm/Config/llvm-config.h.in b/final/include/llvm/Config/llvm-config.h.in new file mode 100644 index 00000000000..e7a04ee91bb --- /dev/null +++ b/final/include/llvm/Config/llvm-config.h.in @@ -0,0 +1,97 @@ +/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/* */ +/* The LLVM Compiler Infrastructure */ +/* */ +/* This file is distributed under the University of Illinois Open Source */ +/* License. See LICENSE.TXT for details. */ +/* */ +/*===----------------------------------------------------------------------===*/ + +/* This file enumerates all of the llvm variables from configure so that + they can be in exported headers and won't override package specific + directives. This is a C file so we can include it in the llvm-c headers. */ + +/* To avoid multiple inclusions of these variables when we include the exported + headers and config.h, conditionally include these. */ +/* TODO: This is a bit of a hack. */ +#ifndef CONFIG_H + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for data files */ +#undef LLVM_DATADIR + +/* Installation directory for documentation */ +#undef LLVM_DOCSDIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Host triple we were built on */ +#undef LLVM_HOSTTRIPLE + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Build multithreading support into LLVM */ +#undef LLVM_MULTITHREADED + +/* LLVM architecture name for the native architecture, if available */ +#undef LLVM_NATIVE_ARCH + +/* LLVM name for the native Target init function, if available */ +#undef LLVM_NATIVE_TARGET + +/* LLVM name for the native TargetInfo init function, if available */ +#undef LLVM_NATIVE_TARGETINFO + +/* LLVM name for the native AsmPrinter init function, if available */ +#undef LLVM_NATIVE_ASMPRINTER + +/* Define if this is Unixish platform */ +#undef LLVM_ON_UNIX + +/* Define if this is Win32ish platform */ +#undef LLVM_ON_WIN32 + +/* Define to path to circo program if found or 'echo circo' otherwise */ +#undef LLVM_PATH_CIRCO + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#undef LLVM_PATH_DOT + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#undef LLVM_PATH_DOTTY + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +#undef LLVM_PATH_FDP + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#undef LLVM_PATH_GV + +/* Define to path to neato program if found or 'echo neato' otherwise */ +#undef LLVM_PATH_NEATO + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +#undef LLVM_PATH_TWOPI + +/* Installation prefix directory */ +#undef LLVM_PREFIX + +#endif diff --git a/final/include/llvm/Constant.h b/final/include/llvm/Constant.h new file mode 100644 index 00000000000..38045fc0c1d --- /dev/null +++ b/final/include/llvm/Constant.h @@ -0,0 +1,164 @@ +//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Constant class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANT_H +#define LLVM_CONSTANT_H + +#include "llvm/User.h" + +namespace llvm { + class APInt; + + template class SmallVectorImpl; + +/// This is an important base class in LLVM. It provides the common facilities +/// of all constant values in an LLVM program. A constant is a value that is +/// immutable at runtime. Functions are constants because their address is +/// immutable. Same with global variables. +/// +/// All constants share the capabilities provided in this class. All constants +/// can have a null value. They can have an operand list. Constants can be +/// simple (integer and floating point values), complex (arrays and structures), +/// or expression based (computations yielding a constant value composed of +/// only certain operators and other constant values). +/// +/// Note that Constants are immutable (once created they never change) +/// and are fully shared by structural equivalence. This means that two +/// structurally equivalent constants will always have the same address. +/// Constants are created on demand as needed and never deleted: thus clients +/// don't have to worry about the lifetime of the objects. +/// @brief LLVM Constant Representation +class Constant : public User { + void operator=(const Constant &); // Do not implement + Constant(const Constant &); // Do not implement + +protected: + Constant(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) + : User(ty, vty, Ops, NumOps) {} + + void destroyConstantImpl(); + + void setOperand(unsigned i, Value *V) { + User::setOperand(i, V); + } +public: + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const = 0; + + /// isNegativeZeroValue - Return true if the value is what would be returned + /// by getZeroValueForNegation. + virtual bool isNegativeZeroValue() const { return isNullValue(); } + + /// canTrap - Return true if evaluation of this constant could trap. This is + /// true for things like constant expressions that could divide by zero. + bool canTrap() const; + + /// isConstantUsed - Return true if the constant has users other than constant + /// exprs and other dangling things. + bool isConstantUsed() const; + + enum PossibleRelocationsTy { + NoRelocation = 0, + LocalRelocation = 1, + GlobalRelocations = 2 + }; + + /// getRelocationInfo - This method classifies the entry according to + /// whether or not it may generate a relocation entry. This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. The return values are: + /// + /// NoRelocation: This constant pool entry is guaranteed to never have a + /// relocation applied to it (because it holds a simple constant like + /// '4'). + /// LocalRelocation: This entry has relocations, but the entries are + /// guaranteed to be resolvable by the static linker, so the dynamic + /// linker will never see them. + /// GlobalRelocations: This entry may have arbitrary relocations. + /// + /// FIXME: This really should not be in VMCore. + PossibleRelocationsTy getRelocationInfo() const; + + // Specialize get/setOperand for Users as their operands are always + // constants or BasicBlocks as well. + User *getOperand(unsigned i) { + return static_cast(User::getOperand(i)); + } + const User *getOperand(unsigned i) const { + return static_cast(User::getOperand(i)); + } + + /// getVectorElements - This method, which is only valid on constant of vector + /// type, returns the elements of the vector in the specified smallvector. + /// This handles breaking down a vector undef into undef elements, etc. For + /// constant exprs and other cases we can't handle, we return an empty vector. + void getVectorElements(SmallVectorImpl &Elts) const; + + /// destroyConstant - Called if some element of this constant is no longer + /// valid. At this point only other constants may be on the use_list for this + /// constant. Any constants on our Use list must also be destroy'd. The + /// implementation must be sure to remove the constant from the list of + /// available cached constants. Implementations should call + /// destroyConstantImpl as the last thing they do, to destroy all users and + /// delete this. + virtual void destroyConstant() { assert(0 && "Not reached!"); } + + //// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Constant *) { return true; } + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= ConstantFirstVal && + V->getValueID() <= ConstantLastVal; + } + + /// replaceUsesOfWithOnConstant - This method is a special form of + /// User::replaceUsesOfWith (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) { + // Provide a default implementation for constants (like integers) that + // cannot use any other values. This cannot be called at runtime, but needs + // to be here to avoid link errors. + assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " + "implemented for all constants that have operands!"); + assert(0 && "Constants that do not have operands cannot be using 'From'!"); + } + + static Constant *getNullValue(const Type* Ty); + + /// @returns the value for an integer constant of the given type that has all + /// its bits set to true. + /// @brief Get the all ones value + static Constant *getAllOnesValue(const Type* Ty); + + /// getIntegerValue - Return the value for an integer or pointer constant, + /// or a vector thereof, with the given scalar value. + static Constant *getIntegerValue(const Type* Ty, const APInt &V); + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this constant, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers() const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Constants.h b/final/include/llvm/Constants.h new file mode 100644 index 00000000000..c12b33fae71 --- /dev/null +++ b/final/include/llvm/Constants.h @@ -0,0 +1,971 @@ +//===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for the subclasses of Constant, +/// which represent the different flavors of constant values that live in LLVM. +/// Note that Constants are immutable (once created they never change) and are +/// fully shared by structural equivalence. This means that two structurally +/// equivalent constants will always have the same address. Constant's are +/// created on demand as needed and never deleted: thus clients don't have to +/// worry about the lifetime of the objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANTS_H +#define LLVM_CONSTANTS_H + +#include "llvm/Constant.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/ArrayRef.h" + +namespace llvm { + +class ArrayType; +class IntegerType; +class StructType; +class PointerType; +class VectorType; + +template +struct ConstantCreator; +template +struct ConvertConstantType; + +//===----------------------------------------------------------------------===// +/// This is the shared class of boolean and integer constants. This class +/// represents both boolean and integral constants. +/// @brief Class for constant integers. +class ConstantInt : public Constant { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT + ConstantInt(const IntegerType *Ty, const APInt& V); + APInt Val; +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantInt *getTrue(LLVMContext &Context); + static ConstantInt *getFalse(LLVMContext &Context); + static Constant *getTrue(const Type *Ty); + static Constant *getFalse(const Type *Ty); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(const Type *Ty, uint64_t V, bool isSigned = false); + + /// Return a ConstantInt with the specified integer value for the specified + /// type. If the type is wider than 64 bits, the value will be zero-extended + /// to fit the type, unless isSigned is true, in which case the value will + /// be interpreted as a 64-bit signed integer and sign-extended to fit + /// the type. + /// @brief Get a ConstantInt for a specific value. + static ConstantInt *get(const IntegerType *Ty, uint64_t V, + bool isSigned = false); + + /// Return a ConstantInt with the specified value for the specified type. The + /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// either getSExtValue() or getZExtValue() will yield a correctly sized and + /// signed value for the type Ty. + /// @brief Get a ConstantInt for a specific signed value. + static ConstantInt *getSigned(const IntegerType *Ty, int64_t V); + static Constant *getSigned(const Type *Ty, int64_t V); + + /// Return a ConstantInt with the specified value and an implied Type. The + /// type is the integer type that corresponds to the bit width of the value. + static ConstantInt *get(LLVMContext &Context, const APInt &V); + + /// Return a ConstantInt constructed from the string strStart with the given + /// radix. + static ConstantInt *get(const IntegerType *Ty, StringRef Str, + uint8_t radix); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantInt for the given value. + static Constant *get(const Type* Ty, const APInt& V); + + /// Return the constant as an APInt value reference. This allows clients to + /// obtain a copy of the value, with all its precision in tact. + /// @brief Return the constant's value. + inline const APInt &getValue() const { + return Val; + } + + /// getBitWidth - Return the bitwidth of this constant. + unsigned getBitWidth() const { return Val.getBitWidth(); } + + /// Return the constant as a 64-bit unsigned integer value after it + /// has been zero extended as appropriate for the type of this constant. Note + /// that this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the zero extended value. + inline uint64_t getZExtValue() const { + return Val.getZExtValue(); + } + + /// Return the constant as a 64-bit integer value after it has been sign + /// extended as appropriate for the type of this constant. Note that + /// this method can assert if the value does not fit in 64 bits. + /// @deprecated + /// @brief Return the sign extended value. + inline int64_t getSExtValue() const { + return Val.getSExtValue(); + } + + /// A helper method that can be used to determine if the constant contained + /// within is equal to a constant. This only works for very small values, + /// because this is all that can be represented with all types. + /// @brief Determine if this constant's value is same as an unsigned char. + bool equalsInt(uint64_t V) const { + return Val == V; + } + + /// getType - Specialize the getType() method to always return an IntegerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const IntegerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// This static method returns true if the type Ty is big enough to + /// represent the value V. This can be used to avoid having the get method + /// assert when V is larger than Ty can represent. Note that there are two + /// versions of this method, one for unsigned and one for signed integers. + /// Although ConstantInt canonicalizes everything to an unsigned integer, + /// the signed version avoids callers having to convert a signed quantity + /// to the appropriate unsigned type before calling the method. + /// @returns true if V is a valid value for type Ty + /// @brief Determine if the value is in range for the given type. + static bool isValueValidForType(const Type *Ty, uint64_t V); + static bool isValueValidForType(const Type *Ty, int64_t V); + + /// This function will return true iff this constant represents the "null" + /// value that would be returned by the getNullValue method. + /// @returns true if this is the null integer value. + /// @brief Determine if the value is null. + virtual bool isNullValue() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common code. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + bool isZero() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common case. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + /// @brief Determine if the value is one. + bool isOne() const { + return Val == 1; + } + + /// This function will return true iff every bit in this constant is set + /// to true. + /// @returns true iff this constant's bits are all set to true. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const { + return Val.isAllOnesValue(); + } + + /// This function will return true iff this constant represents the largest + /// value that may be represented by the constant's type. + /// @returns true iff this is the largest value that may be represented + /// by this type. + /// @brief Determine if the value is maximal. + bool isMaxValue(bool isSigned) const { + if (isSigned) + return Val.isMaxSignedValue(); + else + return Val.isMaxValue(); + } + + /// This function will return true iff this constant represents the smallest + /// value that may be represented by this constant's type. + /// @returns true if this is the smallest value that may be represented by + /// this type. + /// @brief Determine if the value is minimal. + bool isMinValue(bool isSigned) const { + if (isSigned) + return Val.isMinSignedValue(); + else + return Val.isMinValue(); + } + + /// This function will return true iff this constant represents a value with + /// active bits bigger than 64 bits or a value greater than the given uint64_t + /// value. + /// @returns true iff this constant is greater or equal to the given number. + /// @brief Determine if the value is greater or equal to the given number. + bool uge(uint64_t Num) { + return Val.getActiveBits() > 64 || Val.getZExtValue() >= Num; + } + + /// getLimitedValue - If the value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + /// @returns the min of the value of the constant and the specified value + /// @brief Get the constant's value with a saturation limit + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return Val.getLimitedValue(Limit); + } + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const ConstantInt *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantIntVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantFP - Floating Point Values [float, double] +/// +class ConstantFP : public Constant { + APFloat Val; + void *operator new(size_t, unsigned);// DO NOT IMPLEMENT + ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT + friend class LLVMContextImpl; +protected: + ConstantFP(const Type *Ty, const APFloat& V); +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// Floating point negation must be implemented with f(x) = -0.0 - x. This + /// method returns the negative zero constant for floating point or vector + /// floating point types; for all other types, it returns the null value. + static Constant *getZeroValueForNegation(const Type *Ty); + + /// get() - This returns a ConstantFP, or a vector containing a splat of a + /// ConstantFP, for the specified value in the specified type. This should + /// only be used for simple constant values like 2.0/1.0 etc, that are + /// known-valid both as host double and as the target format. + static Constant *get(const Type* Ty, double V); + static Constant *get(const Type* Ty, StringRef Str); + static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static ConstantFP *getNegativeZero(const Type* Ty); + static ConstantFP *getInfinity(const Type *Ty, bool Negative = false); + + /// isValueValidForType - return true if Ty is big enough to represent V. + static bool isValueValidForType(const Type *Ty, const APFloat &V); + inline const APFloat& getValueAPF() const { return Val; } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. For ConstantFP, this is +0.0, but not -0.0. To handle the + /// two the same, use isZero(). + virtual bool isNullValue() const; + + /// isNegativeZeroValue - Return true if the value is what would be returned + /// by getZeroValueForNegation. + virtual bool isNegativeZeroValue() const { + return Val.isZero() && Val.isNegative(); + } + + /// isZero - Return true if the value is positive or negative zero. + bool isZero() const { return Val.isZero(); } + + /// isNaN - Return true if the value is a NaN. + bool isNaN() const { return Val.isNaN(); } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. The version with a double operand is retained + /// because it's so convenient to write isExactlyValue(2.0), but please use + /// it only for simple constants. + bool isExactlyValue(const APFloat &V) const; + + bool isExactlyValue(double V) const { + bool ignored; + // convert is not supported on this type + if (&Val.getSemantics() == &APFloat::PPCDoubleDouble) + return false; + APFloat FV(V); + FV.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &ignored); + return isExactlyValue(FV); + } + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantFP *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantFPVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantAggregateZero - All zero aggregate value +/// +class ConstantAggregateZero : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT +protected: + explicit ConstantAggregateZero(const Type *ty) + : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + static ConstantAggregateZero* get(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantAggregateZero *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantAggregateZeroVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantArray - Constant Array Declarations +/// +class ConstantArray : public Constant { + friend struct ConstantCreator >; + ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT +protected: + ConstantArray(const ArrayType *T, const std::vector &Val); +public: + // ConstantArray accessors + static Constant *get(const ArrayType *T, const std::vector &V); + static Constant *get(const ArrayType *T, Constant *const *Vals, + unsigned NumVals); + + /// This method constructs a ConstantArray and initializes it with a text + /// string. The default behavior (AddNull==true) causes a null terminator to + /// be placed at the end of the array. This effectively increases the length + /// of the array by one (you've been warned). However, in some situations + /// this is not desired so if AddNull==false then the string is copied without + /// null termination. + static Constant *get(LLVMContext &Context, StringRef Initializer, + bool AddNull = true); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const ArrayType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isString - This method returns true if the array is an array of i8 and + /// the elements of the array are all ConstantInt's. + bool isString() const; + + /// isCString - This method returns true if the array is a string (see + /// @verbatim + /// isString) and it ends in a null byte \0 and does not contains any other + /// @endverbatim + /// null bytes except its terminator. + bool isCString() const; + + /// getAsString - If this array is isString(), then this method converts the + /// array to an std::string and returns it. Otherwise, it asserts out. + /// + std::string getAsString() const; + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero arrays are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantArray *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantArrayVal; + } +}; + +template <> +struct OperandTraits : + public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantArray, Constant) + +//===----------------------------------------------------------------------===// +// ConstantStruct - Constant Struct Declarations +// +class ConstantStruct : public Constant { + friend struct ConstantCreator >; + ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT +protected: + ConstantStruct(const StructType *T, const std::vector &Val); +public: + // ConstantStruct accessors + static Constant *get(const StructType *T, const std::vector &V); + static Constant *get(LLVMContext &Context, + const std::vector &V, bool Packed); + static Constant *get(LLVMContext &Context, + Constant *const *Vals, unsigned NumVals, bool Packed); + static Constant *get(LLVMContext &Context, bool Packed, + Constant * Val, ...) END_WITH_NULL; + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType() specialization - Reduce amount of casting... + /// + inline const StructType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero structs are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { + return false; + } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantStruct *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantStructVal; + } +}; + +template <> +struct OperandTraits : + public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantStruct, Constant) + + +//===----------------------------------------------------------------------===// +/// ConstantVector - Constant Vector Declarations +/// +class ConstantVector : public Constant { + friend struct ConstantCreator >; + ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT +protected: + ConstantVector(const VectorType *T, const std::vector &Val); +public: + // ConstantVector accessors + static Constant *get(ArrayRef V); + // FIXME: Eliminate this constructor form. + static Constant *get(const VectorType *T, const std::vector &V); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const VectorType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero vectors are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + /// This function will return true iff every element in this vector constant + /// is set to all ones. + /// @returns true iff this constant's emements are all set to all ones. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const; + + /// getSplatValue - If this is a splat constant, meaning that all of the + /// elements have the same value, return that value. Otherwise return NULL. + Constant *getSplatValue() const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantVector *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantVectorVal; + } +}; + +template <> +struct OperandTraits : + public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantVector, Constant) + +//===----------------------------------------------------------------------===// +/// ConstantPointerNull - a constant pointer value that points to null +/// +class ConstantPointerNull : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT +protected: + explicit ConstantPointerNull(const PointerType *T) + : Constant(reinterpret_cast(T), + Value::ConstantPointerNullVal, 0, 0) {} + +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return objects of the specified value + static ConstantPointerNull *get(const PointerType *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// getType - Specialize the getType() method to always return an PointerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const PointerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantPointerNull *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantPointerNullVal; + } +}; + +/// BlockAddress - The address of a basic block. +/// +class BlockAddress : public Constant { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void *operator new(size_t s) { return User::operator new(s, 2); } + BlockAddress(Function *F, BasicBlock *BB); +public: + /// get - Return a BlockAddress for the specified function and basic block. + static BlockAddress *get(Function *F, BasicBlock *BB); + + /// get - Return a BlockAddress for the specified basic block. The basic + /// block must be embedded into a function. + static BlockAddress *get(BasicBlock *BB); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + Function *getFunction() const { return (Function*)Op<0>().get(); } + BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BlockAddress *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == BlockAddressVal; + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(BlockAddress, Value) + + +//===----------------------------------------------------------------------===// +/// ConstantExpr - a constant value that is initialized with an expression using +/// other constant values. +/// +/// This class uses the standard Instruction opcodes to define the various +/// constant expressions. The Opcode field for the ConstantExpr class is +/// maintained in the Value::SubclassData field. +class ConstantExpr : public Constant { + friend struct ConstantCreator > >; + friend struct ConvertConstantType; + +protected: + ConstantExpr(const Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) + : Constant(ty, ConstantExprVal, Ops, NumOps) { + // Operation type (an Instruction opcode) is stored as the SubclassData. + setValueSubclassData(Opcode); + } + + // These private methods are used by the type resolution code to create + // ConstantExprs in intermediate forms. + static Constant *getTy(const Type *Ty, unsigned Opcode, + Constant *C1, Constant *C2, + unsigned Flags = 0); + static Constant *getCompareTy(unsigned short pred, Constant *C1, + Constant *C2); + static Constant *getSelectTy(const Type *Ty, + Constant *C1, Constant *C2, Constant *C3); + template + static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, + IndexTy const *Idxs, unsigned NumIdxs, + bool InBounds); + static Constant *getExtractElementTy(const Type *Ty, Constant *Val, + Constant *Idx); + static Constant *getInsertElementTy(const Type *Ty, Constant *Val, + Constant *Elt, Constant *Idx); + static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1, + Constant *V2, Constant *Mask); + static Constant *getExtractValueTy(const Type *Ty, Constant *Agg, + const unsigned *Idxs, unsigned NumIdxs); + static Constant *getInsertValueTy(const Type *Ty, Constant *Agg, + Constant *Val, + const unsigned *Idxs, unsigned NumIdxs); + template + static Constant *getGetElementPtrImpl(Constant *C, + IndexTy const *IdxList, + unsigned NumIdx, bool InBounds); + +public: + // Static methods to construct a ConstantExpr of different kinds. Note that + // these methods may return a object that is not an instance of the + // ConstantExpr class, because they will attempt to fold the constant + // expression into something simpler if possible. + + /// getAlignOf constant expr - computes the alignment of a type in a target + /// independent way (Note: the return type is an i64). + static Constant *getAlignOf(const Type *Ty); + + /// getSizeOf constant expr - computes the (alloc) size of a type (in + /// address-units, not bits) in a target independent way (Note: the return + /// type is an i64). + /// + static Constant *getSizeOf(const Type *Ty); + + /// getOffsetOf constant expr - computes the offset of a struct field in a + /// target independent way (Note: the return type is an i64). + /// + static Constant *getOffsetOf(const StructType *STy, unsigned FieldNo); + + /// getOffsetOf constant expr - This is a generalized form of getOffsetOf, + /// which supports any aggregate type, and any Constant index. + /// + static Constant *getOffsetOf(const Type *Ty, Constant *FieldNo); + + static Constant *getNeg(Constant *C, bool HasNUW = false, bool HasNSW =false); + static Constant *getFNeg(Constant *C); + static Constant *getNot(Constant *C); + static Constant *getAdd(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFAdd(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFSub(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getFMul(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getSDiv(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getFDiv(Constant *C1, Constant *C2); + static Constant *getURem(Constant *C1, Constant *C2); + static Constant *getSRem(Constant *C1, Constant *C2); + static Constant *getFRem(Constant *C1, Constant *C2); + static Constant *getAnd(Constant *C1, Constant *C2); + static Constant *getOr(Constant *C1, Constant *C2); + static Constant *getXor(Constant *C1, Constant *C2); + static Constant *getShl(Constant *C1, Constant *C2, + bool HasNUW = false, bool HasNSW = false); + static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); + static Constant *getTrunc (Constant *C, const Type *Ty); + static Constant *getSExt (Constant *C, const Type *Ty); + static Constant *getZExt (Constant *C, const Type *Ty); + static Constant *getFPTrunc (Constant *C, const Type *Ty); + static Constant *getFPExtend(Constant *C, const Type *Ty); + static Constant *getUIToFP (Constant *C, const Type *Ty); + static Constant *getSIToFP (Constant *C, const Type *Ty); + static Constant *getFPToUI (Constant *C, const Type *Ty); + static Constant *getFPToSI (Constant *C, const Type *Ty); + static Constant *getPtrToInt(Constant *C, const Type *Ty); + static Constant *getIntToPtr(Constant *C, const Type *Ty); + static Constant *getBitCast (Constant *C, const Type *Ty); + + static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } + static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } + static Constant *getNSWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, false, true); + } + static Constant *getNUWAdd(Constant *C1, Constant *C2) { + return getAdd(C1, C2, true, false); + } + static Constant *getNSWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, false, true); + } + static Constant *getNUWSub(Constant *C1, Constant *C2) { + return getSub(C1, C2, true, false); + } + static Constant *getNSWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, false, true); + } + static Constant *getNUWMul(Constant *C1, Constant *C2) { + return getMul(C1, C2, true, false); + } + static Constant *getNSWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, false, true); + } + static Constant *getNUWShl(Constant *C1, Constant *C2) { + return getShl(C1, C2, true, false); + } + static Constant *getExactSDiv(Constant *C1, Constant *C2) { + return getSDiv(C1, C2, true); + } + static Constant *getExactUDiv(Constant *C1, Constant *C2) { + return getUDiv(C1, C2, true); + } + static Constant *getExactAShr(Constant *C1, Constant *C2) { + return getAShr(C1, C2, true); + } + static Constant *getExactLShr(Constant *C1, Constant *C2) { + return getLShr(C1, C2, true); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); + + // @brief Convenience function for getting one of the casting operations + // using a CastOps opcode. + static Constant *getCast( + unsigned ops, ///< The opcode for the conversion + Constant *C, ///< The constant to be converted + const Type *Ty ///< The type to which the constant is converted + ); + + // @brief Create a ZExt or BitCast cast constant expression + static Constant *getZExtOrBitCast( + Constant *C, ///< The constant to zext or bitcast + const Type *Ty ///< The type to zext or bitcast C to + ); + + // @brief Create a SExt or BitCast cast constant expression + static Constant *getSExtOrBitCast( + Constant *C, ///< The constant to sext or bitcast + const Type *Ty ///< The type to sext or bitcast C to + ); + + // @brief Create a Trunc or BitCast cast constant expression + static Constant *getTruncOrBitCast( + Constant *C, ///< The constant to trunc or bitcast + const Type *Ty ///< The type to trunc or bitcast C to + ); + + /// @brief Create a BitCast or a PtrToInt cast constant expression + static Constant *getPointerCast( + Constant *C, ///< The pointer value to be casted (operand 0) + const Type *Ty ///< The type to which cast should be made + ); + + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts + static Constant *getIntegerCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty, ///< The integer type to cast to + bool isSigned ///< Whether C should be treated as signed or not + ); + + /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts + static Constant *getFPCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty ///< The integer type to cast to + ); + + /// @brief Return true if this is a convert constant expression + bool isCast() const; + + /// @brief Return true if this is a compare constant expression + bool isCompare() const; + + /// @brief Return true if this is an insertvalue or extractvalue expression, + /// and the getIndices() method may be used. + bool hasIndices() const; + + /// @brief Return true if this is a getelementptr expression and all + /// the index operands are compile-time known integers within the + /// corresponding notional static array extents. Note that this is + /// not equivalant to, a subset of, or a superset of the "inbounds" + /// property. + bool isGEPWithNoNotionalOverIndexing() const; + + /// Select constant expr + /// + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) { + return getSelectTy(V1->getType(), C, V1, V2); + } + + /// get - Return a binary or shift operator constant expression, + /// folding if possible. + /// + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, + unsigned Flags = 0); + + /// @brief Return an ICmp or FCmp comparison operator constant expression. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + + /// get* - Return some common constants without having to + /// specify the full Instruction::OPCODE identifier. + /// + static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); + static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); + + /// Getelementptr form. std::vector is only accepted for convenience: + /// all elements must be Constant's. + /// + static Constant *getGetElementPtr(Constant *C, + Constant *const *IdxList, unsigned NumIdx, + bool InBounds = false); + static Constant *getGetElementPtr(Constant *C, + Value *const *IdxList, unsigned NumIdx, + bool InBounds = false); + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + static Constant *getInBoundsGetElementPtr(Constant *C, + Constant *const *IdxList, + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } + static Constant *getInBoundsGetElementPtr(Constant *C, + Value* const *IdxList, + unsigned NumIdx) { + return getGetElementPtr(C, IdxList, NumIdx, true); + } + + static Constant *getExtractElement(Constant *Vec, Constant *Idx); + static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); + static Constant *getExtractValue(Constant *Agg, + const unsigned *IdxList, unsigned NumIdx); + static Constant *getInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + /// getOpcode - Return the opcode at the root of this constant expression + unsigned getOpcode() const { return getSubclassDataFromValue(); } + + /// getPredicate - Return the ICMP or FCMP predicate value. Assert if this is + /// not an ICMP or FCMP constant expression. + unsigned getPredicate() const; + + /// getIndices - Assert that this is an insertvalue or exactvalue + /// expression and return the list of indices. + const SmallVector &getIndices() const; + + /// getOpcodeName - Return a string representation for an opcode. + const char *getOpcodeName() const; + + /// getWithOperandReplaced - Return a constant expression identical to this + /// one, but with the specified operand set to the specified value. + Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const; + + /// getWithOperands - This returns the current constant expression with the + /// operands replaced with the specified values. The specified operands must + /// match count and type with the existing ones. + Constant *getWithOperands(const std::vector &Ops) const { + return getWithOperands(&Ops[0], (unsigned)Ops.size()); + } + Constant *getWithOperands(Constant *const *Ops, unsigned NumOps) const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ConstantExprVal; + } + +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +template <> +struct OperandTraits : + public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) + +//===----------------------------------------------------------------------===// +/// UndefValue - 'undef' values are things that do not have specified contents. +/// These are used for a variety of purposes, including global variable +/// initializers and operands to instructions. 'undef' values can occur with +/// any first-class type. +/// +/// Undef values aren't exactly constants; if they have multiple uses, they +/// can appear to have different bit patterns at each use. See +/// LangRef.html#undefvalues for details. +/// +class UndefValue : public Constant { + friend struct ConstantCreator; + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + UndefValue(const UndefValue &); // DO NOT IMPLEMENT +protected: + explicit UndefValue(const Type *T) : Constant(T, UndefValueVal, 0, 0) {} +protected: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } +public: + /// get() - Static factory methods - Return an 'undef' object of the specified + /// type. + /// + static UndefValue *get(const Type *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UndefValue *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == UndefValueVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/DerivedTypes.h b/final/include/llvm/DerivedTypes.h new file mode 100644 index 00000000000..56d1e3e237d --- /dev/null +++ b/final/include/llvm/DerivedTypes.h @@ -0,0 +1,513 @@ +//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of classes that represent "derived +// types". These are things like "arrays of x" or "structure of x, y, z" or +// "function returning x taking (y,z) as parameters", etc... +// +// The implementations of these classes live in the Type.cpp file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DERIVED_TYPES_H +#define LLVM_DERIVED_TYPES_H + +#include "llvm/Type.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +template class TypeMap; +class FunctionValType; +class ArrayValType; +class StructValType; +class PointerValType; +class VectorValType; +class IntegerValType; +class APInt; +class LLVMContext; + +class DerivedType : public Type { + friend class Type; + +protected: + explicit DerivedType(LLVMContext &C, TypeID id) : Type(C, id) {} + + /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type + /// that the current type has transitioned from being abstract to being + /// concrete. + /// + void notifyUsesThatTypeBecameConcrete(); + + /// dropAllTypeUses - When this (abstract) type is resolved to be equal to + /// another (more concrete) type, we must eliminate all references to other + /// types, to avoid some circular reference problems. + /// + void dropAllTypeUses(); + +public: + + //===--------------------------------------------------------------------===// + // Abstract Type handling methods - These types have special lifetimes, which + // are managed by (add|remove)AbstractTypeUser. See comments in + // AbstractTypeUser.h for more information. + + /// refineAbstractTypeTo - This function is used to when it is discovered that + /// the 'this' abstract type is actually equivalent to the NewType specified. + /// This causes all users of 'this' to switch to reference the more concrete + /// type NewType and for 'this' to be deleted. + /// + void refineAbstractTypeTo(const Type *NewType); + + void dump() const { Type::dump(); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DerivedType *) { return true; } + static inline bool classof(const Type *T) { + return T->isDerivedType(); + } +}; + +/// Class to represent integer types. Note that this class is also used to +/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and +/// Int64Ty. +/// @brief Integer representation type +class IntegerType : public DerivedType { + friend class LLVMContextImpl; + +protected: + explicit IntegerType(LLVMContext &C, unsigned NumBits) : + DerivedType(C, IntegerTyID) { + setSubclassData(NumBits); + } + friend class TypeMap; +public: + /// This enum is just used to hold constants we need for IntegerType. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that bit width is stored in the Type classes SubclassData field + ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits. + }; + + /// This static method is the primary way of constructing an IntegerType. + /// If an IntegerType with the same NumBits value was previously instantiated, + /// that instance will be returned. Otherwise a new one will be created. Only + /// one instance with a given NumBits value is ever created. + /// @brief Get or create an IntegerType instance. + static const IntegerType* get(LLVMContext &C, unsigned NumBits); + + /// @brief Get the number of bits in this IntegerType + unsigned getBitWidth() const { return getSubclassData(); } + + /// getBitMask - Return a bitmask with ones set for all of the bits + /// that can be set by an unsigned version of this type. This is 0xFF for + /// i8, 0xFFFF for i16, etc. + uint64_t getBitMask() const { + return ~uint64_t(0UL) >> (64-getBitWidth()); + } + + /// getSignBit - Return a uint64_t with just the most significant bit set (the + /// sign bit, if the value is treated as a signed number). + uint64_t getSignBit() const { + return 1ULL << (getBitWidth()-1); + } + + /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. + /// @returns a bit mask with ones set for all the bits of this type. + /// @brief Get a bit mask for this type. + APInt getMask() const; + + /// This method determines if the width of this IntegerType is a power-of-2 + /// in terms of 8 bit bytes. + /// @returns true if this is a power-of-2 byte width. + /// @brief Is this a power-of-2 byte-width IntegerType ? + bool isPowerOf2ByteWidth() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntegerType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == IntegerTyID; + } +}; + + +/// FunctionType - Class to represent function types +/// +class FunctionType : public DerivedType { + friend class TypeMap; + bool isVarArgs; + + FunctionType(const FunctionType &); // Do not implement + const FunctionType &operator=(const FunctionType &); // Do not implement + FunctionType(const Type *Result, const std::vector &Params, + bool IsVarArgs); + +public: + /// FunctionType::get - This static method is the primary way of constructing + /// a FunctionType. + /// + static FunctionType *get( + const Type *Result, ///< The result type + const std::vector &Params, ///< The types of the parameters + bool isVarArg ///< Whether this is a variable argument length function + ); + + /// FunctionType::get - Create a FunctionType taking no parameters. + /// + static FunctionType *get( + const Type *Result, ///< The result type + bool isVarArg ///< Whether this is a variable argument length function + ) { + return get(Result, std::vector(), isVarArg); + } + + /// isValidReturnType - Return true if the specified type is valid as a return + /// type. + static bool isValidReturnType(const Type *RetTy); + + /// isValidArgumentType - Return true if the specified type is valid as an + /// argument type. + static bool isValidArgumentType(const Type *ArgTy); + + inline bool isVarArg() const { return isVarArgs; } + inline const Type *getReturnType() const { return ContainedTys[0]; } + + typedef Type::subtype_iterator param_iterator; + param_iterator param_begin() const { return ContainedTys + 1; } + param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + + // Parameter type accessors... + const Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } + + /// getNumParams - Return the number of fixed parameters this function type + /// requires. This does not consider varargs. + /// + unsigned getNumParams() const { return NumContainedTys - 1; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FunctionType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == FunctionTyID; + } +}; + + +/// CompositeType - Common super class of ArrayType, StructType, PointerType +/// and VectorType +class CompositeType : public DerivedType { +protected: + inline explicit CompositeType(LLVMContext &C, TypeID id) : + DerivedType(C, id) { } +public: + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. + /// + virtual const Type *getTypeAtIndex(const Value *V) const = 0; + virtual const Type *getTypeAtIndex(unsigned Idx) const = 0; + virtual bool indexValid(const Value *V) const = 0; + virtual bool indexValid(unsigned Idx) const = 0; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CompositeType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == StructTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// StructType - Class to represent struct types +/// +class StructType : public CompositeType { + friend class TypeMap; + StructType(const StructType &); // Do not implement + const StructType &operator=(const StructType &); // Do not implement + StructType(LLVMContext &C, + const std::vector &Types, bool isPacked); +public: + /// StructType::get - This static method is the primary way to create a + /// StructType. + /// + static StructType *get(LLVMContext &Context, + const std::vector &Params, + bool isPacked=false); + + /// StructType::get - Create an empty structure type. + /// + static StructType *get(LLVMContext &Context, bool isPacked=false) { + return get(Context, std::vector(), isPacked); + } + + /// StructType::get - This static method is a convenience method for + /// creating structure types by specifying the elements as arguments. + /// Note that this method always returns a non-packed struct. To get + /// an empty struct, pass NULL, NULL. + static StructType *get(LLVMContext &Context, + const Type *type, ...) END_WITH_NULL; + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + // Iterator access to the elements + typedef Type::subtype_iterator element_iterator; + element_iterator element_begin() const { return ContainedTys; } + element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + + // Random access to the elements + unsigned getNumElements() const { return NumContainedTys; } + const Type *getElementType(unsigned N) const { + assert(N < NumContainedTys && "Element number out of range!"); + return ContainedTys[N]; + } + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For a structure type, this must be a constant value... + /// + virtual const Type *getTypeAtIndex(const Value *V) const; + virtual const Type *getTypeAtIndex(unsigned Idx) const; + virtual bool indexValid(const Value *V) const; + virtual bool indexValid(unsigned Idx) const; + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StructType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == StructTyID; + } + + bool isPacked() const { return (0 != getSubclassData()) ? true : false; } +}; + +/// SequentialType - This is the superclass of the array, pointer and vector +/// type classes. All of these represent "arrays" in memory. The array type +/// represents a specifically sized array, pointer types are unsized/unknown +/// size arrays, vector types represent specifically sized arrays that +/// allow for use of SIMD instructions. SequentialType holds the common +/// features of all, which stem from the fact that all three lay their +/// components out in memory identically. +/// +class SequentialType : public CompositeType { + PATypeHandle ContainedType; ///< Storage for the single contained type + SequentialType(const SequentialType &); // Do not implement! + const SequentialType &operator=(const SequentialType &); // Do not implement! + + // avoiding warning: 'this' : used in base member initializer list + SequentialType* this_() { return this; } +protected: + SequentialType(TypeID TID, const Type *ElType) + : CompositeType(ElType->getContext(), TID), ContainedType(ElType, this_()) { + ContainedTys = &ContainedType; + NumContainedTys = 1; + } + +public: + inline const Type *getElementType() const { return ContainedTys[0]; } + + virtual bool indexValid(const Value *V) const; + virtual bool indexValid(unsigned) const { + return true; + } + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For sequential types, there is only one subtype... + /// + virtual const Type *getTypeAtIndex(const Value *) const { + return ContainedTys[0]; + } + virtual const Type *getTypeAtIndex(unsigned) const { + return ContainedTys[0]; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SequentialType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// ArrayType - Class to represent array types +/// +class ArrayType : public SequentialType { + friend class TypeMap; + uint64_t NumElements; + + ArrayType(const ArrayType &); // Do not implement + const ArrayType &operator=(const ArrayType &); // Do not implement + ArrayType(const Type *ElType, uint64_t NumEl); +public: + /// ArrayType::get - This static method is the primary way to construct an + /// ArrayType + /// + static ArrayType *get(const Type *ElementType, uint64_t NumElements); + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + inline uint64_t getNumElements() const { return NumElements; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ArrayType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID; + } +}; + +/// VectorType - Class to represent vector types +/// +class VectorType : public SequentialType { + friend class TypeMap; + unsigned NumElements; + + VectorType(const VectorType &); // Do not implement + const VectorType &operator=(const VectorType &); // Do not implement + VectorType(const Type *ElType, unsigned NumEl); +public: + /// VectorType::get - This static method is the primary way to construct an + /// VectorType + /// + static VectorType *get(const Type *ElementType, unsigned NumElements); + + /// VectorType::getInteger - This static method gets a VectorType with the + /// same number of elements as the input type, and the element type is an + /// integer type of the same width as the input element type. + /// + static VectorType *getInteger(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getExtendedElementVectorType - This static method is like + /// getInteger except that the element types are twice as wide as the + /// elements in the input type. + /// + static VectorType *getExtendedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits * 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// VectorType::getTruncatedElementVectorType - This static method is like + /// getInteger except that the element types are half as wide as the + /// elements in the input type. + /// + static VectorType *getTruncatedElementVectorType(const VectorType *VTy) { + unsigned EltBits = VTy->getElementType()->getPrimitiveSizeInBits(); + assert((EltBits & 1) == 0 && + "Cannot truncate vector element with odd bit-width"); + const Type *EltTy = IntegerType::get(VTy->getContext(), EltBits / 2); + return VectorType::get(EltTy, VTy->getNumElements()); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + /// @brief Return the number of elements in the Vector type. + inline unsigned getNumElements() const { return NumElements; } + + /// @brief Return the number of bits in the Vector type. + inline unsigned getBitWidth() const { + return NumElements * getElementType()->getPrimitiveSizeInBits(); + } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VectorType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == VectorTyID; + } +}; + + +/// PointerType - Class to represent pointers +/// +class PointerType : public SequentialType { + friend class TypeMap; + unsigned AddressSpace; + + PointerType(const PointerType &); // Do not implement + const PointerType &operator=(const PointerType &); // Do not implement + explicit PointerType(const Type *ElType, unsigned AddrSpace); +public: + /// PointerType::get - This constructs a pointer to an object of the specified + /// type in a numbered address space. + static PointerType *get(const Type *ElementType, unsigned AddressSpace); + + /// PointerType::getUnqual - This constructs a pointer to an object of the + /// specified type in the generic address space (address space zero). + static PointerType *getUnqual(const Type *ElementType) { + return PointerType::get(ElementType, 0); + } + + /// isValidElementType - Return true if the specified type is valid as a + /// element type. + static bool isValidElementType(const Type *ElemTy); + + /// @brief Return the address space of the Pointer type. + inline unsigned getAddressSpace() const { return AddressSpace; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Implement support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PointerType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == PointerTyID; + } +}; + + +/// OpaqueType - Class to represent abstract types +/// +class OpaqueType : public DerivedType { + friend class LLVMContextImpl; + OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT + const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT + OpaqueType(LLVMContext &C); +public: + /// OpaqueType::get - Static factory method for the OpaqueType class... + /// + static OpaqueType *get(LLVMContext &C); + + // Implement support for type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const OpaqueType *) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == OpaqueTyID; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ExecutionEngine/ExecutionEngine.h b/final/include/llvm/ExecutionEngine/ExecutionEngine.h new file mode 100644 index 00000000000..dcc9743d697 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -0,0 +1,574 @@ +//===- ExecutionEngine.h - Abstract Execution Engine Interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract interface that implements execution support +// for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_H +#define LLVM_EXECUTION_ENGINE_H + +#include +#include +#include +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +struct GenericValue; +class Constant; +class ExecutionEngine; +class Function; +class GlobalVariable; +class GlobalValue; +class JITEventListener; +class JITMemoryManager; +class MachineCodeInfo; +class Module; +class MutexGuard; +class TargetData; +class Type; + +/// \brief Helper class for helping synchronize access to the global address map +/// table. +class ExecutionEngineState { +public: + struct AddressMapConfig : public ValueMapConfig { + typedef ExecutionEngineState *ExtraData; + static sys::Mutex *getMutex(ExecutionEngineState *EES); + static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old); + static void onRAUW(ExecutionEngineState *, const GlobalValue *, + const GlobalValue *); + }; + + typedef ValueMap + GlobalAddressMapTy; + +private: + ExecutionEngine &EE; + + /// GlobalAddressMap - A mapping between LLVM global values and their + /// actualized version... + GlobalAddressMapTy GlobalAddressMap; + + /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, + /// used to convert raw addresses into the LLVM global value that is emitted + /// at the address. This map is not computed unless getGlobalValueAtAddress + /// is called at some point. + std::map > GlobalAddressReverseMap; + +public: + ExecutionEngineState(ExecutionEngine &EE); + + GlobalAddressMapTy &getGlobalAddressMap(const MutexGuard &) { + return GlobalAddressMap; + } + + std::map > & + getGlobalAddressReverseMap(const MutexGuard &) { + return GlobalAddressReverseMap; + } + + /// \brief Erase an entry from the mapping table. + /// + /// \returns The address that \arg ToUnmap was happed to. + void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); +}; + +/// \brief Abstract interface for implementation execution of LLVM modules, +/// designed to support both interpreter and just-in-time (JIT) compiler +/// implementations. +class ExecutionEngine { + /// The state object holding the global address mapping, which must be + /// accessed synchronously. + // + // FIXME: There is no particular need the entire map needs to be + // synchronized. Wouldn't a reader-writer design be better here? + ExecutionEngineState EEState; + + /// The target data for the platform for which execution is being performed. + const TargetData *TD; + + /// Whether lazy JIT compilation is enabled. + bool CompilingLazily; + + /// Whether JIT compilation of external global variables is allowed. + bool GVCompilationDisabled; + + /// Whether the JIT should perform lookups of external symbols (e.g., + /// using dlsym). + bool SymbolSearchingDisabled; + + friend class EngineBuilder; // To allow access to JITCtor and InterpCtor. + +protected: + /// The list of Modules that we are JIT'ing from. We use a SmallVector to + /// optimize for the case where there is only one module. + SmallVector Modules; + + void setTargetData(const TargetData *td) { + TD = td; + } + + /// getMemoryforGV - Allocate memory for a global variable. + virtual char *getMemoryForGV(const GlobalVariable *GV); + + // To avoid having libexecutionengine depend on the JIT and interpreter + // libraries, the execution engine implementations set these functions to ctor + // pointers at startup time if they are linked in. + static ExecutionEngine *(*JITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs); + static ExecutionEngine *(*MCJITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs); + static ExecutionEngine *(*InterpCtor)(Module *M, + std::string *ErrorStr); + + /// LazyFunctionCreator - If an unknown function is needed, this function + /// pointer is invoked to create it. If this returns null, the JIT will + /// abort. + void *(*LazyFunctionCreator)(const std::string &); + + /// ExceptionTableRegister - If Exception Handling is set, the JIT will + /// register dwarf tables with this function. + typedef void (*EERegisterFn)(void*); + EERegisterFn ExceptionTableRegister; + EERegisterFn ExceptionTableDeregister; + /// This maps functions to their exception tables frames. + DenseMap AllExceptionTables; + + +public: + /// lock - This lock protects the ExecutionEngine, JIT, JITResolver and + /// JITEmitter classes. It must be held while changing the internal state of + /// any of those classes. + sys::Mutex lock; + + //===--------------------------------------------------------------------===// + // ExecutionEngine Startup + //===--------------------------------------------------------------------===// + + virtual ~ExecutionEngine(); + + /// create - This is the factory method for creating an execution engine which + /// is appropriate for the current machine. This takes ownership of the + /// module. + /// + /// \param GVsWithCode - Allocating globals with code breaks + /// freeMachineCodeForFunction and is probably unsafe and bad for performance. + /// However, we have clients who depend on this behavior, so we must support + /// it. Eventually, when we're willing to break some backwards compatability, + /// this flag should be flipped to false, so that by default + /// freeMachineCodeForFunction works. + static ExecutionEngine *create(Module *M, + bool ForceInterpreter = false, + std::string *ErrorStr = 0, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true); + + /// createJIT - This is the factory method for creating a JIT for the current + /// machine, it does not fall back to the interpreter. This takes ownership + /// of the Module and JITMemoryManager if successful. + /// + /// Clients should make sure to initialize targets prior to calling this + /// function. + static ExecutionEngine *createJIT(Module *M, + std::string *ErrorStr = 0, + JITMemoryManager *JMM = 0, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true, + CodeModel::Model CMM = + CodeModel::Default); + + /// addModule - Add a Module to the list of modules that we can JIT from. + /// Note that this takes ownership of the Module: when the ExecutionEngine is + /// destroyed, it destroys the Module as well. + virtual void addModule(Module *M) { + Modules.push_back(M); + } + + //===--------------------------------------------------------------------===// + + const TargetData *getTargetData() const { return TD; } + + /// removeModule - Remove a Module from the list of modules. Returns true if + /// M is found. + virtual bool removeModule(Module *M); + + /// FindFunctionNamed - Search all of the active modules to find the one that + /// defines FnName. This is very slow operation and shouldn't be used for + /// general code. + Function *FindFunctionNamed(const char *FnName); + + /// runFunction - Execute the specified function with the specified arguments, + /// and return the result. + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues) = 0; + + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a program. + /// + /// \param isDtors - Run the destructors instead of constructors. + void runStaticConstructorsDestructors(bool isDtors); + + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a particular module. + /// + /// \param isDtors - Run the destructors instead of constructors. + void runStaticConstructorsDestructors(Module *module, bool isDtors); + + + /// runFunctionAsMain - This is a helper function which wraps runFunction to + /// handle the common task of starting up main with the specified argc, argv, + /// and envp parameters. + int runFunctionAsMain(Function *Fn, const std::vector &argv, + const char * const * envp); + + + /// addGlobalMapping - Tell the execution engine that the specified global is + /// at the specified location. This is used internally as functions are JIT'd + /// and as global variables are laid out in memory. It can and should also be + /// used by clients of the EE that want to have an LLVM global overlay + /// existing data in memory. Mappings are automatically removed when their + /// GlobalValue is destroyed. + void addGlobalMapping(const GlobalValue *GV, void *Addr); + + /// clearAllGlobalMappings - Clear all global mappings and start over again, + /// for use in dynamic compilation scenarios to move globals. + void clearAllGlobalMappings(); + + /// clearGlobalMappingsFromModule - Clear all global mappings that came from a + /// particular module, because it has been removed from the JIT. + void clearGlobalMappingsFromModule(Module *M); + + /// updateGlobalMapping - Replace an existing mapping for GV with a new + /// address. This updates both maps as required. If "Addr" is null, the + /// entry for the global is removed from the mappings. This returns the old + /// value of the pointer, or null if it was not in the map. + void *updateGlobalMapping(const GlobalValue *GV, void *Addr); + + /// getPointerToGlobalIfAvailable - This returns the address of the specified + /// global value if it is has already been codegen'd, otherwise it returns + /// null. + void *getPointerToGlobalIfAvailable(const GlobalValue *GV); + + /// getPointerToGlobal - This returns the address of the specified global + /// value. This may involve code generation if it's a function. + void *getPointerToGlobal(const GlobalValue *GV); + + /// getPointerToFunction - The different EE's represent function bodies in + /// different ways. They should each implement this to say what a function + /// pointer should look like. When F is destroyed, the ExecutionEngine will + /// remove its global mapping and free any machine code. Be sure no threads + /// are running inside F when that happens. + virtual void *getPointerToFunction(Function *F) = 0; + + /// getPointerToBasicBlock - The different EE's represent basic blocks in + /// different ways. Return the representation for a blockaddress of the + /// specified block. + virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; + + /// getPointerToFunctionOrStub - If the specified function has been + /// code-gen'd, return a pointer to the function. If not, compile it, or use + /// a stub to implement lazy compilation if available. See + /// getPointerToFunction for the requirements on destroying F. + virtual void *getPointerToFunctionOrStub(Function *F) { + // Default implementation, just codegen the function. + return getPointerToFunction(F); + } + + // The JIT overrides a version that actually does this. + virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } + + /// getGlobalValueAtAddress - Return the LLVM global value object that starts + /// at the specified address. + /// + const GlobalValue *getGlobalValueAtAddress(void *Addr); + + /// StoreValueToMemory - Stores the data in Val of type Ty at address Ptr. + /// Ptr is the address of the memory at which to store Val, cast to + /// GenericValue *. It is not a pointer to a GenericValue containing the + /// address at which to store Val. + void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, + const Type *Ty); + + void InitializeMemory(const Constant *Init, void *Addr); + + /// recompileAndRelinkFunction - This method is used to force a function which + /// has already been compiled to be compiled again, possibly after it has been + /// modified. Then the entry to the old copy is overwritten with a branch to + /// the new copy. If there was no old copy, this acts just like + /// VM::getPointerToFunction(). + virtual void *recompileAndRelinkFunction(Function *F) = 0; + + /// freeMachineCodeForFunction - Release memory in the ExecutionEngine + /// corresponding to the machine code emitted to execute this function, useful + /// for garbage-collecting generated code. + virtual void freeMachineCodeForFunction(Function *F) = 0; + + /// getOrEmitGlobalVariable - Return the address of the specified global + /// variable, possibly emitting it to memory if needed. This is used by the + /// Emitter. + virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { + return getPointerToGlobal((GlobalValue*)GV); + } + + /// Registers a listener to be called back on various events within + /// the JIT. See JITEventListener.h for more details. Does not + /// take ownership of the argument. The argument may be NULL, in + /// which case these functions do nothing. + virtual void RegisterJITEventListener(JITEventListener *) {} + virtual void UnregisterJITEventListener(JITEventListener *) {} + + /// DisableLazyCompilation - When lazy compilation is off (the default), the + /// JIT will eagerly compile every function reachable from the argument to + /// getPointerToFunction. If lazy compilation is turned on, the JIT will only + /// compile the one function and emit stubs to compile the rest when they're + /// first called. If lazy compilation is turned off again while some lazy + /// stubs are still around, and one of those stubs is called, the program will + /// abort. + /// + /// In order to safely compile lazily in a threaded program, the user must + /// ensure that 1) only one thread at a time can call any particular lazy + /// stub, and 2) any thread modifying LLVM IR must hold the JIT's lock + /// (ExecutionEngine::lock) or otherwise ensure that no other thread calls a + /// lazy stub. See http://llvm.org/PR5184 for details. + void DisableLazyCompilation(bool Disabled = true) { + CompilingLazily = !Disabled; + } + bool isCompilingLazily() const { + return CompilingLazily; + } + // Deprecated in favor of isCompilingLazily (to reduce double-negatives). + // Remove this in LLVM 2.8. + bool isLazyCompilationDisabled() const { + return !CompilingLazily; + } + + /// DisableGVCompilation - If called, the JIT will abort if it's asked to + /// allocate space and populate a GlobalVariable that is not internal to + /// the module. + void DisableGVCompilation(bool Disabled = true) { + GVCompilationDisabled = Disabled; + } + bool isGVCompilationDisabled() const { + return GVCompilationDisabled; + } + + /// DisableSymbolSearching - If called, the JIT will not try to lookup unknown + /// symbols with dlsym. A client can still use InstallLazyFunctionCreator to + /// resolve symbols in a custom way. + void DisableSymbolSearching(bool Disabled = true) { + SymbolSearchingDisabled = Disabled; + } + bool isSymbolSearchingDisabled() const { + return SymbolSearchingDisabled; + } + + /// InstallLazyFunctionCreator - If an unknown function is needed, the + /// specified function pointer is invoked to create it. If it returns null, + /// the JIT will abort. + void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { + LazyFunctionCreator = P; + } + + /// InstallExceptionTableRegister - The JIT will use the given function + /// to register the exception tables it generates. + void InstallExceptionTableRegister(EERegisterFn F) { + ExceptionTableRegister = F; + } + void InstallExceptionTableDeregister(EERegisterFn F) { + ExceptionTableDeregister = F; + } + + /// RegisterTable - Registers the given pointer as an exception table. It + /// uses the ExceptionTableRegister function. + void RegisterTable(const Function *fn, void* res) { + if (ExceptionTableRegister) { + ExceptionTableRegister(res); + AllExceptionTables[fn] = res; + } + } + + /// DeregisterTable - Deregisters the exception frame previously registered for the given function. + void DeregisterTable(const Function *Fn) { + if (ExceptionTableDeregister) { + DenseMap::iterator frame = AllExceptionTables.find(Fn); + if(frame != AllExceptionTables.end()) { + ExceptionTableDeregister(frame->second); + AllExceptionTables.erase(frame); + } + } + } + + /// DeregisterAllTables - Deregisters all previously registered pointers to an + /// exception tables. It uses the ExceptionTableoDeregister function. + void DeregisterAllTables(); + +protected: + explicit ExecutionEngine(Module *M); + + void emitGlobals(); + + void EmitGlobalVariable(const GlobalVariable *GV); + + GenericValue getConstantValue(const Constant *C); + void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, + const Type *Ty); +}; + +namespace EngineKind { + // These are actually bitmasks that get or-ed together. + enum Kind { + JIT = 0x1, + Interpreter = 0x2 + }; + const static Kind Either = (Kind)(JIT | Interpreter); +} + +/// EngineBuilder - Builder class for ExecutionEngines. Use this by +/// stack-allocating a builder, chaining the various set* methods, and +/// terminating it with a .create() call. +class EngineBuilder { +private: + Module *M; + EngineKind::Kind WhichEngine; + std::string *ErrorStr; + CodeGenOpt::Level OptLevel; + JITMemoryManager *JMM; + bool AllocateGVsWithCode; + CodeModel::Model CMModel; + std::string MArch; + std::string MCPU; + SmallVector MAttrs; + bool UseMCJIT; + + /// InitEngine - Does the common initialization of default options. + void InitEngine() { + WhichEngine = EngineKind::Either; + ErrorStr = NULL; + OptLevel = CodeGenOpt::Default; + JMM = NULL; + AllocateGVsWithCode = false; + CMModel = CodeModel::Default; + UseMCJIT = false; + } + +public: + /// EngineBuilder - Constructor for EngineBuilder. If create() is called and + /// is successful, the created engine takes ownership of the module. + EngineBuilder(Module *m) : M(m) { + InitEngine(); + } + + /// setEngineKind - Controls whether the user wants the interpreter, the JIT, + /// or whichever engine works. This option defaults to EngineKind::Either. + EngineBuilder &setEngineKind(EngineKind::Kind w) { + WhichEngine = w; + return *this; + } + + /// setJITMemoryManager - Sets the memory manager to use. This allows + /// clients to customize their memory allocation policies. If create() is + /// called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. + EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + JMM = jmm; + return *this; + } + + /// setErrorStr - Set the error string to write to on error. This option + /// defaults to NULL. + EngineBuilder &setErrorStr(std::string *e) { + ErrorStr = e; + return *this; + } + + /// setOptLevel - Set the optimization level for the JIT. This option + /// defaults to CodeGenOpt::Default. + EngineBuilder &setOptLevel(CodeGenOpt::Level l) { + OptLevel = l; + return *this; + } + + /// setCodeModel - Set the CodeModel that the ExecutionEngine target + /// data is using. Defaults to target specific default "CodeModel::Default". + EngineBuilder &setCodeModel(CodeModel::Model M) { + CMModel = M; + return *this; + } + + /// setAllocateGVsWithCode - Sets whether global values should be allocated + /// into the same buffer as code. For most applications this should be set + /// to false. Allocating globals with code breaks freeMachineCodeForFunction + /// and is probably unsafe and bad for performance. However, we have clients + /// who depend on this behavior, so we must support it. This option defaults + /// to false so that users of the new API can safely use the new memory + /// manager and free machine code. + EngineBuilder &setAllocateGVsWithCode(bool a) { + AllocateGVsWithCode = a; + return *this; + } + + /// setMArch - Override the architecture set by the Module's triple. + EngineBuilder &setMArch(StringRef march) { + MArch.assign(march.begin(), march.end()); + return *this; + } + + /// setMCPU - Target a specific cpu type. + EngineBuilder &setMCPU(StringRef mcpu) { + MCPU.assign(mcpu.begin(), mcpu.end()); + return *this; + } + + /// setUseMCJIT - Set whether the MC-JIT implementation should be used + /// (experimental). + void setUseMCJIT(bool Value) { + UseMCJIT = Value; + } + + /// setMAttrs - Set cpu-specific attributes. + template + EngineBuilder &setMAttrs(const StringSequence &mattrs) { + MAttrs.clear(); + MAttrs.append(mattrs.begin(), mattrs.end()); + return *this; + } + + ExecutionEngine *create(); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ExecutionEngine/GenericValue.h b/final/include/llvm/ExecutionEngine/GenericValue.h new file mode 100644 index 00000000000..a2fed98c150 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/GenericValue.h @@ -0,0 +1,44 @@ +//===-- GenericValue.h - Represent any type of LLVM value -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The GenericValue class is used to represent an LLVM value of arbitrary type. +// +//===----------------------------------------------------------------------===// + + +#ifndef GENERIC_VALUE_H +#define GENERIC_VALUE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +typedef void* PointerTy; +class APInt; + +struct GenericValue { + union { + double DoubleVal; + float FloatVal; + PointerTy PointerVal; + struct { unsigned int first; unsigned int second; } UIntPairVal; + unsigned char Untyped[8]; + }; + APInt IntVal; // also used for long doubles + + GenericValue() : DoubleVal(0.0), IntVal(1,0) {} + explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { } +}; + +inline GenericValue PTOGV(void *P) { return GenericValue(P); } +inline void* GVTOP(const GenericValue &GV) { return GV.PointerVal; } + +} // End llvm namespace +#endif diff --git a/final/include/llvm/ExecutionEngine/Interpreter.h b/final/include/llvm/ExecutionEngine/Interpreter.h new file mode 100644 index 00000000000..7425cdbcfda --- /dev/null +++ b/final/include/llvm/ExecutionEngine/Interpreter.h @@ -0,0 +1,38 @@ +//===-- Interpreter.h - Abstract Execution Engine Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the interpreter to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef EXECUTION_ENGINE_INTERPRETER_H +#define EXECUTION_ENGINE_INTERPRETER_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInInterpreter(); + +namespace { + struct ForceInterpreterLinking { + ForceInterpreterLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInInterpreter(); + } + } ForceInterpreterLinking; +} + +#endif diff --git a/final/include/llvm/ExecutionEngine/JIT.h b/final/include/llvm/ExecutionEngine/JIT.h new file mode 100644 index 00000000000..6013db48ce6 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/JIT.h @@ -0,0 +1,38 @@ +//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the JIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_H +#define LLVM_EXECUTION_ENGINE_JIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInJIT(); + +namespace { + struct ForceJITLinking { + ForceJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInJIT(); + } + } ForceJITLinking; +} + +#endif diff --git a/final/include/llvm/ExecutionEngine/JITEventListener.h b/final/include/llvm/ExecutionEngine/JITEventListener.h new file mode 100644 index 00000000000..abc063b0703 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/JITEventListener.h @@ -0,0 +1,82 @@ +//===- JITEventListener.h - Exposes events from JIT compilation -*- 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 JITEventListener interface, which lets users get +// callbacks when significant events happen during the JIT compilation process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H +#define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" + +#include + +namespace llvm { +class Function; +class MachineFunction; + +/// JITEvent_EmittedFunctionDetails - Helper struct for containing information +/// about a generated machine code function. +struct JITEvent_EmittedFunctionDetails { + struct LineStart { + /// The address at which the current line changes. + uintptr_t Address; + + /// The new location information. These can be translated to DebugLocTuples + /// using MF->getDebugLocTuple(). + DebugLoc Loc; + }; + + /// The machine function the struct contains information for. + const MachineFunction *MF; + + /// The list of line boundary information, sorted by address. + std::vector LineStarts; +}; + +/// JITEventListener - Abstract interface for use by the JIT to notify clients +/// about significant events during compilation. For example, to notify +/// profilers and debuggers that need to know where functions have been emitted. +/// +/// The default implementation of each method does nothing. +class JITEventListener { +public: + typedef JITEvent_EmittedFunctionDetails EmittedFunctionDetails; + +public: + JITEventListener() {} + virtual ~JITEventListener(); + + /// NotifyFunctionEmitted - Called after a function has been successfully + /// emitted to memory. The function still has its MachineFunction attached, + /// if you should happen to need that. + virtual void NotifyFunctionEmitted(const Function &F, + void *Code, size_t Size, + const EmittedFunctionDetails &Details) {} + + /// NotifyFreeingMachineCode - Called from freeMachineCodeForFunction(), after + /// the global mapping is removed, but before the machine code is returned to + /// the allocator. + /// + /// OldPtr is the address of the machine code and will be the same as the Code + /// parameter to a previous NotifyFunctionEmitted call. The Function passed + /// to NotifyFunctionEmitted may have been destroyed by the time of the + /// matching NotifyFreeingMachineCode call. + virtual void NotifyFreeingMachineCode(void *OldPtr) {} +}; + +// This returns NULL if support isn't available. +JITEventListener *createOProfileJITEventListener(); + +} // end namespace llvm. + +#endif diff --git a/final/include/llvm/ExecutionEngine/JITMemoryManager.h b/final/include/llvm/ExecutionEngine/JITMemoryManager.h new file mode 100644 index 00000000000..38414180166 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -0,0 +1,179 @@ +//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H +#define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + + class Function; + class GlobalValue; + +/// JITMemoryManager - This interface is used by the JIT to allocate and manage +/// memory for the code generated by the JIT. This can be reimplemented by +/// clients that have a strong desire to control how the layout of JIT'd memory +/// works. +class JITMemoryManager { +protected: + bool HasGOT; + +public: + JITMemoryManager() : HasGOT(false) {} + virtual ~JITMemoryManager(); + + /// CreateDefaultMemManager - This is used to create the default + /// JIT Memory Manager if the client does not provide one to the JIT. + static JITMemoryManager *CreateDefaultMemManager(); + + /// setMemoryWritable - When code generation is in progress, + /// the code pages may need permissions changed. + virtual void setMemoryWritable() = 0; + + /// setMemoryExecutable - When code generation is done and we're ready to + /// start execution, the code pages may need permissions changed. + virtual void setMemoryExecutable() = 0; + + /// setPoisonMemory - Setting this flag to true makes the memory manager + /// garbage values over freed memory. This is useful for testing and + /// debugging, and may be turned on by default in debug mode. + virtual void setPoisonMemory(bool poison) = 0; + + //===--------------------------------------------------------------------===// + // Global Offset Table Management + //===--------------------------------------------------------------------===// + + /// AllocateGOT - If the current table requires a Global Offset Table, this + /// method is invoked to allocate it. This method is required to set HasGOT + /// to true. + virtual void AllocateGOT() = 0; + + /// isManagingGOT - Return true if the AllocateGOT method is called. + bool isManagingGOT() const { + return HasGOT; + } + + /// getGOTBase - If this is managing a Global Offset Table, this method should + /// return a pointer to its base. + virtual uint8_t *getGOTBase() const = 0; + + //===--------------------------------------------------------------------===// + // Main Allocation Functions + //===--------------------------------------------------------------------===// + + /// startFunctionBody - When we start JITing a function, the JIT calls this + /// method to allocate a block of free RWX memory, which returns a pointer to + /// it. If the JIT wants to request a block of memory of at least a certain + /// size, it passes that value as ActualSize, and this method returns a block + /// with at least that much space. If the JIT doesn't know ahead of time how + /// much space it will need to emit the function, it passes 0 for the + /// ActualSize. In either case, this method is required to pass back the size + /// of the allocated block through ActualSize. The JIT will be careful to + /// not write more than the returned ActualSize bytes of memory. + virtual uint8_t *startFunctionBody(const Function *F, + uintptr_t &ActualSize) = 0; + + /// allocateStub - This method is called by the JIT to allocate space for a + /// function stub (used to handle limited branch displacements) while it is + /// JIT compiling a function. For example, if foo calls bar, and if bar + /// either needs to be lazily compiled or is a native function that exists too + /// far away from the call site to work, this method will be used to make a + /// thunk for it. The stub should be "close" to the current function body, + /// but should not be included in the 'actualsize' returned by + /// startFunctionBody. + virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) = 0; + + /// endFunctionBody - This method is called when the JIT is done codegen'ing + /// the specified function. At this point we know the size of the JIT + /// compiled function. This passes in FunctionStart (which was returned by + /// the startFunctionBody method) and FunctionEnd which is a pointer to the + /// actual end of the function. This method should mark the space allocated + /// and remember where it is in case the client wants to deallocate it. + virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) = 0; + + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. + virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; + + /// allocateGlobal - Allocate memory for a global. + virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + + /// deallocateFunctionBody - Free the specified function body. The argument + /// must be the return value from a call to startFunctionBody() that hasn't + /// been deallocated yet. This is never called when the JIT is currently + /// emitting a function. + virtual void deallocateFunctionBody(void *Body) = 0; + + /// startExceptionTable - When we finished JITing the function, if exception + /// handling is set, we emit the exception table. + virtual uint8_t* startExceptionTable(const Function* F, + uintptr_t &ActualSize) = 0; + + /// endExceptionTable - This method is called when the JIT is done emitting + /// the exception table. + virtual void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister) = 0; + + /// deallocateExceptionTable - Free the specified exception table's memory. + /// The argument must be the return value from a call to startExceptionTable() + /// that hasn't been deallocated yet. This is never called when the JIT is + /// currently emitting an exception table. + virtual void deallocateExceptionTable(void *ET) = 0; + + /// CheckInvariants - For testing only. Return true if all internal + /// invariants are preserved, or return false and set ErrorStr to a helpful + /// error message. + virtual bool CheckInvariants(std::string &) { + return true; + } + + /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultCodeSlabSize() { + return 0; + } + + /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultDataSlabSize() { + return 0; + } + + /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultStubSlabSize() { + return 0; + } + + /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for code. + virtual unsigned GetNumCodeSlabs() { + return 0; + } + + /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for data. + virtual unsigned GetNumDataSlabs() { + return 0; + } + + /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for function stubs. + virtual unsigned GetNumStubSlabs() { + return 0; + } +}; + +} // end namespace llvm. + +#endif diff --git a/final/include/llvm/ExecutionEngine/MCJIT.h b/final/include/llvm/ExecutionEngine/MCJIT.h new file mode 100644 index 00000000000..f956a5029b1 --- /dev/null +++ b/final/include/llvm/ExecutionEngine/MCJIT.h @@ -0,0 +1,38 @@ +//===-- MCJIT.h - MC-Based Just-In-Time Execution Engine --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the MCJIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_MCJIT_H +#define LLVM_EXECUTION_ENGINE_MCJIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include + +extern "C" void LLVMLinkInMCJIT(); + +namespace { + struct ForceMCJITLinking { + ForceMCJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + LLVMLinkInMCJIT(); + } + } ForceMCJITLinking; +} + +#endif diff --git a/final/include/llvm/Function.h b/final/include/llvm/Function.h new file mode 100644 index 00000000000..9a0825ab4a9 --- /dev/null +++ b/final/include/llvm/Function.h @@ -0,0 +1,437 @@ +//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Function class, which represents a +// single function/procedure in LLVM. +// +// A function basically consists of a list of basic blocks, a list of arguments, +// and a symbol table. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUNCTION_H +#define LLVM_FUNCTION_H + +#include "llvm/GlobalValue.h" +#include "llvm/CallingConv.h" +#include "llvm/BasicBlock.h" +#include "llvm/Argument.h" +#include "llvm/Attributes.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class FunctionType; +class LLVMContext; + +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits + : public SymbolTableListTraits { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits) + BasicBlock *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(BasicBlock*) {} + + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node Sentinel; +}; + +template<> struct ilist_traits + : public SymbolTableListTraits { + + Argument *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(Argument*) {} + + Argument *provideInitialHead() const { return createSentinel(); } + Argument *ensureHead(Argument*) const { return createSentinel(); } + static void noteHead(Argument*, Argument*) {} + + static ValueSymbolTable *getSymTab(Function *ItemParent); +private: + mutable ilist_half_node Sentinel; +}; + +class Function : public GlobalValue, + public ilist_node { +public: + typedef iplist ArgumentListType; + typedef iplist BasicBlockListType; + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + + typedef ArgumentListType::iterator arg_iterator; + typedef ArgumentListType::const_iterator const_arg_iterator; + +private: + // Important things that make up a function! + BasicBlockListType BasicBlocks; ///< The basic blocks + mutable ArgumentListType ArgumentList; ///< The formal arguments + ValueSymbolTable *SymTab; ///< Symbol table of args/instructions + AttrListPtr AttributeList; ///< Parameter attributes + + // HasLazyArguments is stored in Value::SubclassData. + /*bool HasLazyArguments;*/ + + // The Calling Convention is stored in Value::SubclassData. + /*CallingConv::ID CallingConvention;*/ + + friend class SymbolTableListTraits; + + void setParent(Module *parent); + + /// hasLazyArguments/CheckLazyArguments - The argument list of a function is + /// built on demand, so that the list isn't allocated until the first client + /// needs it. The hasLazyArguments predicate returns true if the arg list + /// hasn't been set up yet. + bool hasLazyArguments() const { + return getSubclassDataFromValue() & 1; + } + void CheckLazyArguments() const { + if (hasLazyArguments()) + BuildLazyArguments(); + } + void BuildLazyArguments() const; + + Function(const Function&); // DO NOT IMPLEMENT + void operator=(const Function&); // DO NOT IMPLEMENT + + /// Function ctor - If the (optional) Module argument is specified, the + /// function is automatically inserted into the end of the function list for + /// the module. + /// + Function(const FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0); + +public: + static Function *Create(const FunctionType *Ty, LinkageTypes Linkage, + const Twine &N = "", Module *M = 0) { + return new(0) Function(Ty, Linkage, N, M); + } + + ~Function(); + + const Type *getReturnType() const; // Return the type of the ret val + const FunctionType *getFunctionType() const; // Return the FunctionType for me + + /// getContext - Return a pointer to the LLVMContext associated with this + /// function, or NULL if this function is not bound to a context yet. + LLVMContext &getContext() const; + + /// isVarArg - Return true if this function takes a variable number of + /// arguments. + bool isVarArg() const; + + /// isDeclaration - Is the body of this function unknown? (The basic block + /// list is empty if so.) This is true for function declarations, but not + /// true for function definitions. + /// + virtual bool isDeclaration() const { return BasicBlocks.empty(); } + + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or Intrinsic::not_intrinsic if the function is not an + /// instrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. + /// + unsigned getIntrinsicID() const LLVM_ATTRIBUTE_READONLY; + bool isIntrinsic() const { return getIntrinsicID() != 0; } + + /// getCallingConv()/setCallingConv(CC) - These method get and set the + /// calling convention of this function. The enum values for the known + /// calling conventions are defined in CallingConv.h. + CallingConv::ID getCallingConv() const { + return static_cast(getSubclassDataFromValue() >> 1); + } + void setCallingConv(CallingConv::ID CC) { + setValueSubclassData((getSubclassDataFromValue() & 1) | + (static_cast(CC) << 1)); + } + + /// getAttributes - Return the attribute list for this Function. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the attribute list for this Function. + /// + void setAttributes(const AttrListPtr &attrs) { AttributeList = attrs; } + + /// hasFnAttr - Return true if this function has the given attribute. + bool hasFnAttr(Attributes N) const { + // Function Attributes are stored at ~0 index + return AttributeList.paramHasAttr(~0U, N); + } + + /// addFnAttr - Add function attributes to this function. + /// + void addFnAttr(Attributes N) { + // Function Attributes are stored at ~0 index + addAttribute(~0U, N); + } + + /// removeFnAttr - Remove function attributes from this function. + /// + void removeFnAttr(Attributes N) { + // Function Attributes are stored at ~0 index + removeAttribute(~0U, N); + } + + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm + /// to use during code generation. + bool hasGC() const; + const char *getGC() const; + void setGC(const char *Str); + void clearGC(); + + /// @brief Determine whether the function has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const { + return AttributeList.paramHasAttr(i, attr); + } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Determine if the function does not access memory. + bool doesNotAccessMemory() const { + return hasFnAttr(Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool DoesNotAccessMemory = true) { + if (DoesNotAccessMemory) addFnAttr(Attribute::ReadNone); + else removeFnAttr(Attribute::ReadNone); + } + + /// @brief Determine if the function does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addFnAttr(Attribute::ReadOnly); + else removeFnAttr(Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the function cannot return. + bool doesNotReturn() const { + return hasFnAttr(Attribute::NoReturn); + } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addFnAttr(Attribute::NoReturn); + else removeFnAttr(Attribute::NoReturn); + } + + /// @brief Determine if the function cannot unwind. + bool doesNotThrow() const { + return hasFnAttr(Attribute::NoUnwind); + } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addFnAttr(Attribute::NoUnwind); + else removeFnAttr(Attribute::NoUnwind); + } + + /// @brief Determine if the function returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if the parameter does not alias other parameters. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotAlias(unsigned n) const { + return paramHasAttr(n, Attribute::NoAlias); + } + void setDoesNotAlias(unsigned n, bool DoesNotAlias = true) { + if (DoesNotAlias) addAttribute(n, Attribute::NoAlias); + else removeAttribute(n, Attribute::NoAlias); + } + + /// @brief Determine if the parameter can be captured. + /// @param n The parameter to check. 1 is the first parameter, 0 is the return + bool doesNotCapture(unsigned n) const { + return paramHasAttr(n, Attribute::NoCapture); + } + void setDoesNotCapture(unsigned n, bool DoesNotCapture = true) { + if (DoesNotCapture) addAttribute(n, Attribute::NoCapture); + else removeAttribute(n, Attribute::NoCapture); + } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a Function) from the Function Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// deleteBody - This method deletes the body of the function, and converts + /// the linkage to external. + /// + void deleteBody() { + dropAllReferences(); + setLinkage(ExternalLinkage); + } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. + /// + const ArgumentListType &getArgumentList() const { + CheckLazyArguments(); + return ArgumentList; + } + ArgumentListType &getArgumentList() { + CheckLazyArguments(); + return ArgumentList; + } + static iplist Function::*getSublistAccess(Argument*) { + return &Function::ArgumentList; + } + + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + static iplist Function::*getSublistAccess(BasicBlock*) { + return &Function::BasicBlocks; + } + + const BasicBlock &getEntryBlock() const { return front(); } + BasicBlock &getEntryBlock() { return front(); } + + //===--------------------------------------------------------------------===// + // Symbol Table Accessing functions... + + /// getSymbolTable() - Return the symbol table... + /// + inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } + inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } + + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + size_t size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const BasicBlock &front() const { return BasicBlocks.front(); } + BasicBlock &front() { return BasicBlocks.front(); } + const BasicBlock &back() const { return BasicBlocks.back(); } + BasicBlock &back() { return BasicBlocks.back(); } + + //===--------------------------------------------------------------------===// + // Argument iterator forwarding functions + // + arg_iterator arg_begin() { + CheckLazyArguments(); + return ArgumentList.begin(); + } + const_arg_iterator arg_begin() const { + CheckLazyArguments(); + return ArgumentList.begin(); + } + arg_iterator arg_end() { + CheckLazyArguments(); + return ArgumentList.end(); + } + const_arg_iterator arg_end() const { + CheckLazyArguments(); + return ArgumentList.end(); + } + + size_t arg_size() const; + bool arg_empty() const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Function *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal; + } + + /// dropAllReferences() - This method causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole module at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is deleted for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + /// Since no other object in the module can have references into the body of a + /// function, dropping all references deletes the entire body of the function, + /// including any contained basic blocks. + /// + void dropAllReferences(); + + /// hasAddressTaken - returns true if there are any uses of this function + /// other than direct calls or invokes to it. Optionally passes back the + /// offending user for diagnostic purposes. + /// + bool hasAddressTaken(const User** = 0) const; + +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +inline ValueSymbolTable * +ilist_traits::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/GVMaterializer.h b/final/include/llvm/GVMaterializer.h new file mode 100644 index 00000000000..c1435523886 --- /dev/null +++ b/final/include/llvm/GVMaterializer.h @@ -0,0 +1,66 @@ +//===-- llvm/GVMaterializer.h - Interface for GV materializers --*- 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 an abstract interface for loading a module from some +// place. This interface allows incremental or random access loading of +// functions from the file. This is useful for applications like JIT compilers +// or interprocedural optimizers that do not need the entire program in memory +// at the same time. +// +//===----------------------------------------------------------------------===// + +#ifndef GVMATERIALIZER_H +#define GVMATERIALIZER_H + +#include + +namespace llvm { + +class Function; +class GlobalValue; +class Module; + +class GVMaterializer { +protected: + GVMaterializer() {} + +public: + virtual ~GVMaterializer(); + + /// isMaterializable - True if GV can be materialized from whatever backing + /// store this GVMaterializer uses and has not been materialized yet. + virtual bool isMaterializable(const GlobalValue *GV) const = 0; + + /// isDematerializable - True if GV has been materialized and can be + /// dematerialized back to whatever backing store this GVMaterializer uses. + virtual bool isDematerializable(const GlobalValue *GV) const = 0; + + /// Materialize - make sure the given GlobalValue is fully read. If the + /// module is corrupt, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + /// + virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0) = 0; + + /// Dematerialize - If the given GlobalValue is read in, and if the + /// GVMaterializer supports it, release the memory for the GV, and set it up + /// to be materialized lazily. If the Materializer doesn't support this + /// capability, this method is a noop. + /// + virtual void Dematerialize(GlobalValue *) {} + + /// MaterializeModule - make sure the entire Module has been completely read. + /// On error, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + /// + virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0) = 0; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/GlobalAlias.h b/final/include/llvm/GlobalAlias.h new file mode 100644 index 00000000000..f4af5b1202c --- /dev/null +++ b/final/include/llvm/GlobalAlias.h @@ -0,0 +1,100 @@ +//===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalAlias class, which +// represents a single function or variable alias in the IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_ALIAS_H +#define LLVM_GLOBAL_ALIAS_H + +#include "llvm/GlobalValue.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/Twine.h" + +namespace llvm { + +class Module; +class Constant; +template + class SymbolTableListTraits; + +class GlobalAlias : public GlobalValue, public ilist_node { + friend class SymbolTableListTraits; + void operator=(const GlobalAlias &); // Do not implement + GlobalAlias(const GlobalAlias &); // Do not implement + + void setParent(Module *parent); + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + /// GlobalAlias ctor - If a parent module is specified, the alias is + /// automatically inserted into the end of the specified module's alias list. + GlobalAlias(const Type *Ty, LinkageTypes Linkage, const Twine &Name = "", + Constant* Aliasee = 0, Module *Parent = 0); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// set/getAliasee - These methods retrive and set alias target. + void setAliasee(Constant* GV); + const Constant* getAliasee() const { + return cast_or_null(getOperand(0)); + } + Constant* getAliasee() { + return cast_or_null(getOperand(0)); + } + /// getAliasedGlobal() - Aliasee can be either global or bitcast of + /// global. This method retrives the global for both aliasee flavours. + const GlobalValue* getAliasedGlobal() const; + + /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias + /// by going through the aliasing chain and trying to find the very last + /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then + /// the whole chain aliasing chain is traversed, otherwise - only strong + /// aliases. + const GlobalValue* resolveAliasedGlobal(bool stopOnWeak = true) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalAlias *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalAliasVal; + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalAlias, Value) + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/GlobalValue.h b/final/include/llvm/GlobalValue.h new file mode 100644 index 00000000000..b184b8e4497 --- /dev/null +++ b/final/include/llvm/GlobalValue.h @@ -0,0 +1,296 @@ +//===-- llvm/GlobalValue.h - Class to represent a global value --*- 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 a common base class of all globally definable objects. As such, +// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is +// used because you can do certain things with these global objects that you +// can't do to anything else. For example, use the address of one as a +// constant. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBALVALUE_H +#define LLVM_GLOBALVALUE_H + +#include "llvm/Constant.h" + +namespace llvm { + +class PointerType; +class Module; + +class GlobalValue : public Constant { + GlobalValue(const GlobalValue &); // do not implement +public: + /// @brief An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + AvailableExternallyLinkage, ///< Available for inspection, not emission. + LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) + LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. + WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) + WeakODRLinkage, ///< Same, but only replaced by something equivalent. + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions). + PrivateLinkage, ///< Like Internal, but omit from symbol table. + LinkerPrivateLinkage, ///< Like Private, but linker removes. + LinkerPrivateWeakLinkage, ///< Like LinkerPrivate, but weak. + LinkerPrivateWeakDefAutoLinkage, ///< Like LinkerPrivateWeak, but possibly + /// hidden. + DLLImportLinkage, ///< Function to be imported from DLL + DLLExportLinkage, ///< Function to be accessible from DLL. + ExternalWeakLinkage,///< ExternalWeak linkage description. + CommonLinkage ///< Tentative definitions. + }; + + /// @brief An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + +protected: + GlobalValue(const Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, + LinkageTypes linkage, const Twine &Name) + : Constant(ty, vty, Ops, NumOps), Parent(0), + Linkage(linkage), Visibility(DefaultVisibility), Alignment(0), + UnnamedAddr(0) { + setName(Name); + } + + Module *Parent; + // Note: VC++ treats enums as signed, so an extra bit is required to prevent + // Linkage and Visibility from turning into negative values. + LinkageTypes Linkage : 5; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned Alignment : 16; // Alignment of this symbol, must be power of two + unsigned UnnamedAddr : 1; // This value's address is not significant + std::string Section; // Section to emit this into, empty mean default +public: + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + unsigned getAlignment() const { + return (1u << Alignment) >> 1; + } + void setAlignment(unsigned Align); + + bool hasUnnamedAddr() const { return UnnamedAddr; } + void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } + bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { Visibility = V; } + + bool hasSection() const { return !Section.empty(); } + const std::string &getSection() const { return Section; } + void setSection(StringRef S) { Section = S; } + + /// If the usage is empty (except transitively dead constants), then this + /// global value can be safely deleted since the destructor will + /// delete the dead constants as well. + /// @brief Determine if the usage of this global value is empty except + /// for transitively dead constants. + bool use_empty_except_constants(); + + /// getType - Global values are always pointers. + inline const PointerType *getType() const { + return reinterpret_cast(User::getType()); + } + + static LinkageTypes getLinkOnceLinkage(bool ODR) { + return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; + } + static LinkageTypes getWeakLinkage(bool ODR) { + return ODR ? WeakODRLinkage : WeakAnyLinkage; + } + + static bool isExternalLinkage(LinkageTypes Linkage) { + return Linkage == ExternalLinkage; + } + static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage; + } + static bool isLinkOnceLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; + } + static bool isWeakLinkage(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; + } + static bool isAppendingLinkage(LinkageTypes Linkage) { + return Linkage == AppendingLinkage; + } + static bool isInternalLinkage(LinkageTypes Linkage) { + return Linkage == InternalLinkage; + } + static bool isPrivateLinkage(LinkageTypes Linkage) { + return Linkage == PrivateLinkage; + } + static bool isLinkerPrivateLinkage(LinkageTypes Linkage) { + return Linkage == LinkerPrivateLinkage; + } + static bool isLinkerPrivateWeakLinkage(LinkageTypes Linkage) { + return Linkage == LinkerPrivateWeakLinkage; + } + static bool isLinkerPrivateWeakDefAutoLinkage(LinkageTypes Linkage) { + return Linkage == LinkerPrivateWeakDefAutoLinkage; + } + static bool isLocalLinkage(LinkageTypes Linkage) { + return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage) || + isLinkerPrivateLinkage(Linkage) || isLinkerPrivateWeakLinkage(Linkage) || + isLinkerPrivateWeakDefAutoLinkage(Linkage); + } + static bool isDLLImportLinkage(LinkageTypes Linkage) { + return Linkage == DLLImportLinkage; + } + static bool isDLLExportLinkage(LinkageTypes Linkage) { + return Linkage == DLLExportLinkage; + } + static bool isExternalWeakLinkage(LinkageTypes Linkage) { + return Linkage == ExternalWeakLinkage; + } + static bool isCommonLinkage(LinkageTypes Linkage) { + return Linkage == CommonLinkage; + } + + /// mayBeOverridden - Whether the definition of this global may be replaced + /// by something non-equivalent at link time. For example, if a function has + /// weak linkage then the code defining it may be replaced by different code. + static bool mayBeOverridden(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage || + Linkage == LinkerPrivateWeakLinkage || + Linkage == LinkerPrivateWeakDefAutoLinkage; + } + + /// isWeakForLinker - Whether the definition of this global may be replaced at + /// link time. NB: Using this method outside of the code generators is almost + /// always a mistake: when working at the IR level use mayBeOverridden instead + /// as it knows about ODR semantics. + static bool isWeakForLinker(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage || + Linkage == WeakAnyLinkage || + Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || + Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage || + Linkage == LinkerPrivateWeakLinkage || + Linkage == LinkerPrivateWeakDefAutoLinkage; + } + + bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } + bool hasAvailableExternallyLinkage() const { + return isAvailableExternallyLinkage(Linkage); + } + bool hasLinkOnceLinkage() const { + return isLinkOnceLinkage(Linkage); + } + bool hasWeakLinkage() const { + return isWeakLinkage(Linkage); + } + bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); } + bool hasInternalLinkage() const { return isInternalLinkage(Linkage); } + bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); } + bool hasLinkerPrivateLinkage() const { return isLinkerPrivateLinkage(Linkage); } + bool hasLinkerPrivateWeakLinkage() const { + return isLinkerPrivateWeakLinkage(Linkage); + } + bool hasLinkerPrivateWeakDefAutoLinkage() const { + return isLinkerPrivateWeakDefAutoLinkage(Linkage); + } + bool hasLocalLinkage() const { return isLocalLinkage(Linkage); } + bool hasDLLImportLinkage() const { return isDLLImportLinkage(Linkage); } + bool hasDLLExportLinkage() const { return isDLLExportLinkage(Linkage); } + bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); } + bool hasCommonLinkage() const { return isCommonLinkage(Linkage); } + + void setLinkage(LinkageTypes LT) { Linkage = LT; } + LinkageTypes getLinkage() const { return Linkage; } + + bool mayBeOverridden() const { return mayBeOverridden(Linkage); } + + bool isWeakForLinker() const { return isWeakForLinker(Linkage); } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalValue) from the GlobalValue Src to this one. + virtual void copyAttributesFrom(const GlobalValue *Src); + +/// @name Materialization +/// Materialization is used to construct functions only as they're needed. This +/// is useful to reduce memory usage in LLVM or parsing work done by the +/// BitcodeReader to load the Module. +/// @{ + + /// isMaterializable - If this function's Module is being lazily streamed in + /// functions from disk or some other source, this method can be used to check + /// to see if the function has been read in yet or not. + bool isMaterializable() const; + + /// isDematerializable - Returns true if this function was loaded from a + /// GVMaterializer that's still attached to its Module and that knows how to + /// dematerialize the function. + bool isDematerializable() const; + + /// Materialize - make sure this GlobalValue is fully read. If the module is + /// corrupt, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + bool Materialize(std::string *ErrInfo = 0); + + /// Dematerialize - If this GlobalValue is read in, and if the GVMaterializer + /// supports it, release the memory for the function, and set it up to be + /// materialized lazily. If !isDematerializable(), this method is a noop. + void Dematerialize(); + +/// @} + + /// Override from Constant class. No GlobalValue's are null values so this + /// always returns false. + virtual bool isNullValue() const { return false; } + + /// Override from Constant class. + virtual void destroyConstant(); + + /// isDeclaration - Return true if the primary definition of this global + /// value is outside of the current translation unit... + virtual bool isDeclaration() const = 0; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + virtual void removeFromParent() = 0; + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + virtual void eraseFromParent() = 0; + + /// getParent - Get the module that this global value is contained inside + /// of... + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/GlobalVariable.h b/final/include/llvm/GlobalVariable.h new file mode 100644 index 00000000000..1769c665d06 --- /dev/null +++ b/final/include/llvm/GlobalVariable.h @@ -0,0 +1,180 @@ +//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalVariable class, which +// represents a single global variable (or constant) in the VM. +// +// Global variables are constant pointers that refer to hunks of space that are +// allocated by either the VM, or by the linker in a static compiler. A global +// variable may have an intial value, which is copied into the executables .data +// area. Global Constants are required to have initializers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_VARIABLE_H +#define LLVM_GLOBAL_VARIABLE_H + +#include "llvm/GlobalValue.h" +#include "llvm/OperandTraits.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/Twine.h" + +namespace llvm { + +class Module; +class Constant; +template + class SymbolTableListTraits; + +class GlobalVariable : public GlobalValue, public ilist_node { + friend class SymbolTableListTraits; + void *operator new(size_t, unsigned); // Do not implement + void operator=(const GlobalVariable &); // Do not implement + GlobalVariable(const GlobalVariable &); // Do not implement + + void setParent(Module *parent); + + bool isConstantGlobal : 1; // Is this a global constant? + bool isThreadLocalSymbol : 1; // Is this symbol "Thread Local"? + +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + /// GlobalVariable ctor - If a parent module is specified, the global is + /// automatically inserted into the end of the specified modules global list. + GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, + Constant *Initializer = 0, const Twine &Name = "", + bool ThreadLocal = false, unsigned AddressSpace = 0); + /// GlobalVariable ctor - This creates a global and inserts it before the + /// specified other global. + GlobalVariable(Module &M, const Type *Ty, bool isConstant, + LinkageTypes Linkage, Constant *Initializer, + const Twine &Name, + GlobalVariable *InsertBefore = 0, bool ThreadLocal = false, + unsigned AddressSpace = 0); + + ~GlobalVariable() { + NumOperands = 1; // FIXME: needed by operator delete + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const { return getNumOperands() == 0; } + + /// hasInitializer - Unless a global variable isExternal(), it has an + /// initializer. The initializer for the global variable/constant is held by + /// Initializer if an initializer is specified. + /// + inline bool hasInitializer() const { return !isDeclaration(); } + + /// hasDefinitiveInitializer - Whether the global variable has an initializer, + /// and any other instances of the global (this can happen due to weak + /// linkage) are guaranteed to have the same initializer. + /// + /// Note that if you want to transform a global, you must use + /// hasUniqueInitializer() instead, because of the *_odr linkage type. + /// + /// Example: + /// + /// @a = global SomeType* null - Initializer is both definitive and unique. + /// + /// @b = global weak SomeType* null - Initializer is neither definitive nor + /// unique. + /// + /// @c = global weak_odr SomeType* null - Initializer is definitive, but not + /// unique. + inline bool hasDefinitiveInitializer() const { + return hasInitializer() && + // The initializer of a global variable with weak linkage may change at + // link time. + !mayBeOverridden(); + } + + /// hasUniqueInitializer - Whether the global variable has an initializer, and + /// any changes made to the initializer will turn up in the final executable. + inline bool hasUniqueInitializer() const { + return hasInitializer() && + // It's not safe to modify initializers of global variables with weak + // linkage, because the linker might choose to discard the initializer and + // use the initializer from another instance of the global variable + // instead. It is wrong to modify the initializer of a global variable + // with *_odr linkage because then different instances of the global may + // have different initializers, breaking the One Definition Rule. + !isWeakForLinker(); + } + + /// getInitializer - Return the initializer for this global variable. It is + /// illegal to call this method if the global is external, because we cannot + /// tell what the value is initialized to! + /// + inline /*const FIXME*/ Constant *getInitializer() const { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast(Op<0>().get()); + } + inline Constant *getInitializer() { + assert(hasInitializer() && "GV doesn't have initializer!"); + return static_cast(Op<0>().get()); + } + /// setInitializer - Sets the initializer for this global variable, removing + /// any existing initializer if InitVal==NULL. If this GV has type T*, the + /// initializer must have type T. + void setInitializer(Constant *InitVal); + + /// If the value is a global constant, its value is immutable throughout the + /// runtime execution of the program. Assigning a value into the constant + /// leads to undefined behavior. + /// + bool isConstant() const { return isConstantGlobal; } + void setConstant(bool Val) { isConstantGlobal = Val; } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return isThreadLocalSymbol; } + void setThreadLocal(bool Val) { isThreadLocalSymbol = Val; } + + /// copyAttributesFrom - copy all additional attributes (those not needed to + /// create a GlobalVariable) from the GlobalVariable Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + virtual void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + virtual void eraseFromParent(); + + /// Override Constant's implementation of this method so we can + /// replace constant initializers. + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalVariable *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalVariableVal; + } +}; + +template <> +struct OperandTraits : + public OptionalOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/InitializePasses.h b/final/include/llvm/InitializePasses.h new file mode 100644 index 00000000000..2758b299ecc --- /dev/null +++ b/final/include/llvm/InitializePasses.h @@ -0,0 +1,232 @@ +//===- llvm/InitializePasses.h -------- Initialize All Passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations for the pass initialization routines +// for the entire LLVM project. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INITIALIZEPASSES_H +#define LLVM_INITIALIZEPASSES_H + +namespace llvm { + +class PassRegistry; + +/// initializeCore - Initialize all passes linked into the +/// TransformUtils library. +void initializeCore(PassRegistry&); + +/// initializeTransformUtils - Initialize all passes linked into the +/// TransformUtils library. +void initializeTransformUtils(PassRegistry&); + +/// initializeScalarOpts - Initialize all passes linked into the +/// ScalarOpts library. +void initializeScalarOpts(PassRegistry&); + +/// initializeInstCombine - Initialize all passes linked into the +/// ScalarOpts library. +void initializeInstCombine(PassRegistry&); + +/// initializeIPO - Initialize all passes linked into the IPO library. +void initializeIPO(PassRegistry&); + +/// initializeInstrumentation - Initialize all passes linked into the +/// Instrumentation library. +void initializeInstrumentation(PassRegistry&); + +/// initializeAnalysis - Initialize all passes linked into the Analysis library. +void initializeAnalysis(PassRegistry&); + +/// initializeIPA - Initialize all passes linked into the IPA library. +void initializeIPA(PassRegistry&); + +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. +void initializeCodeGen(PassRegistry&); + +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. +void initializeTarget(PassRegistry&); + +void initializeAAEvalPass(PassRegistry&); +void initializeADCEPass(PassRegistry&); +void initializeAliasAnalysisAnalysisGroup(PassRegistry&); +void initializeAliasAnalysisCounterPass(PassRegistry&); +void initializeAliasDebuggerPass(PassRegistry&); +void initializeAliasSetPrinterPass(PassRegistry&); +void initializeAlwaysInlinerPass(PassRegistry&); +void initializeArgPromotionPass(PassRegistry&); +void initializeBasicAliasAnalysisPass(PassRegistry&); +void initializeBasicCallGraphPass(PassRegistry&); +void initializeBlockExtractorPassPass(PassRegistry&); +void initializeBlockPlacementPass(PassRegistry&); +void initializeBreakCriticalEdgesPass(PassRegistry&); +void initializeCFGOnlyPrinterPass(PassRegistry&); +void initializeCFGOnlyViewerPass(PassRegistry&); +void initializeCFGPrinterPass(PassRegistry&); +void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeCFGViewerPass(PassRegistry&); +void initializeCalculateSpillWeightsPass(PassRegistry&); +void initializeCallGraphAnalysisGroup(PassRegistry&); +void initializeCodeGenPreparePass(PassRegistry&); +void initializeConstantMergePass(PassRegistry&); +void initializeConstantPropagationPass(PassRegistry&); +void initializeCorrelatedValuePropagationPass(PassRegistry&); +void initializeDAEPass(PassRegistry&); +void initializeDAHPass(PassRegistry&); +void initializeDCEPass(PassRegistry&); +void initializeDSEPass(PassRegistry&); +void initializeDTEPass(PassRegistry&); +void initializeDeadInstEliminationPass(PassRegistry&); +void initializeDeadMachineInstructionElimPass(PassRegistry&); +void initializeDomOnlyPrinterPass(PassRegistry&); +void initializeDomOnlyViewerPass(PassRegistry&); +void initializeDomPrinterPass(PassRegistry&); +void initializeDomViewerPass(PassRegistry&); +void initializeDominanceFrontierPass(PassRegistry&); +void initializeDominatorTreePass(PassRegistry&); +void initializeEdgeBundlesPass(PassRegistry&); +void initializeEdgeProfilerPass(PassRegistry&); +void initializePathProfilerPass(PassRegistry&); +void initializeEarlyCSEPass(PassRegistry&); +void initializeExpandISelPseudosPass(PassRegistry&); +void initializeFindUsedTypesPass(PassRegistry&); +void initializeFunctionAttrsPass(PassRegistry&); +void initializeGCModuleInfoPass(PassRegistry&); +void initializeGVNPass(PassRegistry&); +void initializeGlobalDCEPass(PassRegistry&); +void initializeGlobalOptPass(PassRegistry&); +void initializeGlobalsModRefPass(PassRegistry&); +void initializeIPCPPass(PassRegistry&); +void initializeIPSCCPPass(PassRegistry&); +void initializeIVUsersPass(PassRegistry&); +void initializeIfConverterPass(PassRegistry&); +void initializeIndVarSimplifyPass(PassRegistry&); +void initializeInstCombinerPass(PassRegistry&); +void initializeInstCountPass(PassRegistry&); +void initializeInstNamerPass(PassRegistry&); +void initializeInternalizePassPass(PassRegistry&); +void initializeIntervalPartitionPass(PassRegistry&); +void initializeJumpThreadingPass(PassRegistry&); +void initializeLCSSAPass(PassRegistry&); +void initializeLICMPass(PassRegistry&); +void initializeLazyValueInfoPass(PassRegistry&); +void initializeLibCallAliasAnalysisPass(PassRegistry&); +void initializeLintPass(PassRegistry&); +void initializeLiveDebugVariablesPass(PassRegistry&); +void initializeLiveIntervalsPass(PassRegistry&); +void initializeLiveStacksPass(PassRegistry&); +void initializeLiveVariablesPass(PassRegistry&); +void initializeLoaderPassPass(PassRegistry&); +void initializePathProfileLoaderPassPass(PassRegistry&); +void initializeLoopDeletionPass(PassRegistry&); +void initializeLoopDependenceAnalysisPass(PassRegistry&); +void initializeLoopExtractorPass(PassRegistry&); +void initializeLoopInfoPass(PassRegistry&); +void initializeLoopInstSimplifyPass(PassRegistry&); +void initializeLoopRotatePass(PassRegistry&); +void initializeLoopSimplifyPass(PassRegistry&); +void initializeLoopSplitterPass(PassRegistry&); +void initializeLoopStrengthReducePass(PassRegistry&); +void initializeLoopUnrollPass(PassRegistry&); +void initializeLoopUnswitchPass(PassRegistry&); +void initializeLoopIdiomRecognizePass(PassRegistry&); +void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerIntrinsicsPass(PassRegistry&); +void initializeLowerInvokePass(PassRegistry&); +void initializeLowerSetJmpPass(PassRegistry&); +void initializeLowerSwitchPass(PassRegistry&); +void initializeMachineCSEPass(PassRegistry&); +void initializeMachineDominatorTreePass(PassRegistry&); +void initializeMachineLICMPass(PassRegistry&); +void initializeMachineLoopInfoPass(PassRegistry&); +void initializeMachineLoopRangesPass(PassRegistry&); +void initializeMachineModuleInfoPass(PassRegistry&); +void initializeMachineSinkingPass(PassRegistry&); +void initializeMachineVerifierPassPass(PassRegistry&); +void initializeMemCpyOptPass(PassRegistry&); +void initializeMemDepPrinterPass(PassRegistry&); +void initializeMemoryDependenceAnalysisPass(PassRegistry&); +void initializeMergeFunctionsPass(PassRegistry&); +void initializeModuleDebugInfoPrinterPass(PassRegistry&); +void initializeNoAAPass(PassRegistry&); +void initializeNoProfileInfoPass(PassRegistry&); +void initializeNoPathProfileInfoPass(PassRegistry&); +void initializeOptimalEdgeProfilerPass(PassRegistry&); +void initializeOptimizePHIsPass(PassRegistry&); +void initializePEIPass(PassRegistry&); +void initializePHIEliminationPass(PassRegistry&); +void initializePartialInlinerPass(PassRegistry&); +void initializePeepholeOptimizerPass(PassRegistry&); +void initializePostDomOnlyPrinterPass(PassRegistry&); +void initializePostDomOnlyViewerPass(PassRegistry&); +void initializePostDomPrinterPass(PassRegistry&); +void initializePostDomViewerPass(PassRegistry&); +void initializePostDominanceFrontierPass(PassRegistry&); +void initializePostDominatorTreePass(PassRegistry&); +void initializePreAllocSplittingPass(PassRegistry&); +void initializePreVerifierPass(PassRegistry&); +void initializePrintDbgInfoPass(PassRegistry&); +void initializePrintFunctionPassPass(PassRegistry&); +void initializePrintModulePassPass(PassRegistry&); +void initializeProcessImplicitDefsPass(PassRegistry&); +void initializeProfileEstimatorPassPass(PassRegistry&); +void initializeProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileInfoAnalysisGroup(PassRegistry&); +void initializePathProfileVerifierPass(PassRegistry&); +void initializeProfileVerifierPassPass(PassRegistry&); +void initializePromotePassPass(PassRegistry&); +void initializePruneEHPass(PassRegistry&); +void initializeRALinScanPass(PassRegistry&); +void initializeReassociatePass(PassRegistry&); +void initializeRegToMemPass(PassRegistry&); +void initializeRegionInfoPass(PassRegistry&); +void initializeRegionOnlyPrinterPass(PassRegistry&); +void initializeRegionOnlyViewerPass(PassRegistry&); +void initializeRegionPrinterPass(PassRegistry&); +void initializeRegionViewerPass(PassRegistry&); +void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); +void initializeRenderMachineFunctionPass(PassRegistry&); +void initializeSCCPPass(PassRegistry&); +void initializeSRETPromotionPass(PassRegistry&); +void initializeSROA_DTPass(PassRegistry&); +void initializeSROA_SSAUpPass(PassRegistry&); +void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); +void initializeScalarEvolutionPass(PassRegistry&); +void initializeSimpleInlinerPass(PassRegistry&); +void initializeSimpleRegisterCoalescingPass(PassRegistry&); +void initializeSimplifyLibCallsPass(PassRegistry&); +void initializeSingleLoopExtractorPass(PassRegistry&); +void initializeSinkingPass(PassRegistry&); +void initializeSlotIndexesPass(PassRegistry&); +void initializeSpillPlacementPass(PassRegistry&); +void initializeStackProtectorPass(PassRegistry&); +void initializeStackSlotColoringPass(PassRegistry&); +void initializeStripDeadDebugInfoPass(PassRegistry&); +void initializeStripDeadPrototypesPassPass(PassRegistry&); +void initializeStripDebugDeclarePass(PassRegistry&); +void initializeStripNonDebugSymbolsPass(PassRegistry&); +void initializeStripSymbolsPass(PassRegistry&); +void initializeStrongPHIEliminationPass(PassRegistry&); +void initializeTailCallElimPass(PassRegistry&); +void initializeTailDupPass(PassRegistry&); +void initializeTargetDataPass(PassRegistry&); +void initializeTargetLibraryInfoPass(PassRegistry&); +void initializeTwoAddressInstructionPassPass(PassRegistry&); +void initializeTypeBasedAliasAnalysisPass(PassRegistry&); +void initializeUnifyFunctionExitNodesPass(PassRegistry&); +void initializeUnreachableBlockElimPass(PassRegistry&); +void initializeUnreachableMachineBlockElimPass(PassRegistry&); +void initializeVerifierPass(PassRegistry&); +void initializeVirtRegMapPass(PassRegistry&); +void initializeInstSimplifierPass(PassRegistry&); + +} + +#endif diff --git a/final/include/llvm/InlineAsm.h b/final/include/llvm/InlineAsm.h new file mode 100644 index 00000000000..ed8f0f7f615 --- /dev/null +++ b/final/include/llvm/InlineAsm.h @@ -0,0 +1,256 @@ +//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- 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 inline asm strings, which are Value*'s that are +// used as the callee operand of call instructions. InlineAsm's are uniqued +// like constants, and created via InlineAsm::get(...). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INLINEASM_H +#define LLVM_INLINEASM_H + +#include "llvm/Value.h" +#include + +namespace llvm { + +class PointerType; +class FunctionType; +class Module; +struct InlineAsmKeyType; +template +class ConstantUniqueMap; +template +struct ConstantCreator; + +class InlineAsm : public Value { + friend struct ConstantCreator; + friend class ConstantUniqueMap; + + InlineAsm(const InlineAsm &); // do not implement + void operator=(const InlineAsm&); // do not implement + + std::string AsmString, Constraints; + bool HasSideEffects; + bool IsAlignStack; + + InlineAsm(const PointerType *Ty, const std::string &AsmString, + const std::string &Constraints, bool hasSideEffects, + bool isAlignStack); + virtual ~InlineAsm(); + + /// When the ConstantUniqueMap merges two types and makes two InlineAsms + /// identical, it destroys one of them with this method. + void destroyConstant(); +public: + + /// InlineAsm::get - Return the specified uniqued inline asm string. + /// + static InlineAsm *get(const FunctionType *Ty, StringRef AsmString, + StringRef Constraints, bool hasSideEffects, + bool isAlignStack = false); + + bool hasSideEffects() const { return HasSideEffects; } + bool isAlignStack() const { return IsAlignStack; } + + /// getType - InlineAsm's are always pointers. + /// + const PointerType *getType() const { + return reinterpret_cast(Value::getType()); + } + + /// getFunctionType - InlineAsm's are always pointers to functions. + /// + const FunctionType *getFunctionType() const; + + const std::string &getAsmString() const { return AsmString; } + const std::string &getConstraintString() const { return Constraints; } + + /// Verify - This static method can be used by the parser to check to see if + /// the specified constraint string is legal for the type. This returns true + /// if legal, false if not. + /// + static bool Verify(const FunctionType *Ty, StringRef Constraints); + + // Constraint String Parsing + enum ConstraintPrefix { + isInput, // 'x' + isOutput, // '=x' + isClobber // '~x' + }; + + typedef std::vector ConstraintCodeVector; + + struct SubConstraintInfo { + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + ConstraintCodeVector Codes; + /// Default constructor. + SubConstraintInfo() : MatchingInput(-1) {} + }; + + typedef std::vector SubConstraintInfoVector; + struct ConstraintInfo; + typedef std::vector ConstraintInfoVector; + + struct ConstraintInfo { + /// Type - The basic type of the constraint: input/output/clobber + /// + ConstraintPrefix Type; + + /// isEarlyClobber - "&": output operand writes result before inputs are all + /// read. This is only ever set for an output operand. + bool isEarlyClobber; + + /// MatchingInput - If this is not -1, this is an output constraint where an + /// input constraint is required to match it (e.g. "0"). The value is the + /// constraint number that matches this one (for example, if this is + /// constraint #0 and constraint #4 has the value "0", this will be 4). + signed char MatchingInput; + + /// hasMatchingInput - Return true if this is an output constraint that has + /// a matching input constraint. + bool hasMatchingInput() const { return MatchingInput != -1; } + + /// isCommutative - This is set to true for a constraint that is commutative + /// with the next operand. + bool isCommutative; + + /// isIndirect - True if this operand is an indirect operand. This means + /// that the address of the source or destination is present in the call + /// instruction, instead of it being returned or passed in explicitly. This + /// is represented with a '*' in the asm string. + bool isIndirect; + + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + ConstraintCodeVector Codes; + + /// isMultipleAlternative - '|': has multiple-alternative constraints. + bool isMultipleAlternative; + + /// multipleAlternatives - If there are multiple alternative constraints, + /// this array will contain them. Otherwise it will be empty. + SubConstraintInfoVector multipleAlternatives; + + /// The currently selected alternative constraint index. + unsigned currentAlternativeIndex; + + ///Default constructor. + ConstraintInfo(); + + /// Copy constructor. + ConstraintInfo(const ConstraintInfo &other); + + /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the + /// fields in this structure. If the constraint string is not understood, + /// return true, otherwise return false. + bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); + + /// selectAlternative - Point this constraint to the alternative constraint + /// indicated by the index. + void selectAlternative(unsigned index); + }; + + /// ParseConstraints - Split up the constraint string into the specific + /// constraints and their prefixes. If this returns an empty vector, and if + /// the constraint string itself isn't empty, there was an error parsing. + static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); + + /// ParseConstraints - Parse the constraints of this inlineasm object, + /// returning them the same way that ParseConstraints(str) does. + ConstraintInfoVector ParseConstraints() const { + return ParseConstraints(Constraints); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InlineAsm *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::InlineAsmVal; + } + + + // These are helper methods for dealing with flags in the INLINEASM SDNode + // in the backend. + + enum { + Op_InputChain = 0, + Op_AsmString = 1, + Op_MDNode = 2, + Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack + Op_FirstOperand = 4, + + MIOp_AsmString = 0, + MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack + MIOp_FirstOperand = 2, + + Extra_HasSideEffects = 1, + Extra_IsAlignStack = 2, + + Kind_RegUse = 1, + Kind_RegDef = 2, + Kind_Imm = 3, + Kind_Mem = 4, + Kind_RegDefEarlyClobber = 6, + + Flag_MatchingOperand = 0x80000000 + }; + + static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { + assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); + return Kind | (NumOps << 3); + } + + /// getFlagWordForMatchingOp - Augment an existing flag word returned by + /// getFlagWord with information indicating that this input operand is tied + /// to a previous output operand. + static unsigned getFlagWordForMatchingOp(unsigned InputFlag, + unsigned MatchedOperandNo) { + return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); + } + + static unsigned getKind(unsigned Flags) { + return Flags & 7; + } + + static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} + static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } + static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } + static bool isRegDefEarlyClobberKind(unsigned Flag) { + return getKind(Flag) == Kind_RegDefEarlyClobber; + } + + /// getNumOperandRegisters - Extract the number of registers field from the + /// inline asm operand flag. + static unsigned getNumOperandRegisters(unsigned Flag) { + return (Flag & 0xffff) >> 3; + } + + /// isUseOperandTiedToDef - Return true if the flag of the inline asm + /// operand indicates it is an use operand that's matched to a def operand. + static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { + if ((Flag & Flag_MatchingOperand) == 0) + return false; + Idx = (Flag & ~Flag_MatchingOperand) >> 16; + return true; + } + + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/InstrTypes.h b/final/include/llvm/InstrTypes.h new file mode 100644 index 00000000000..a166956e1a6 --- /dev/null +++ b/final/include/llvm/InstrTypes.h @@ -0,0 +1,854 @@ +//===-- llvm/InstrTypes.h - Important Instruction subclasses ----*- 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 various meta classes of instructions that exist in the VM +// representation. Specific concrete subclasses of these may be found in the +// i*.h files... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_TYPES_H +#define LLVM_INSTRUCTION_TYPES_H + +#include "llvm/Instruction.h" +#include "llvm/OperandTraits.h" +#include "llvm/Operator.h" +#include "llvm/DerivedTypes.h" +#include "llvm/ADT/Twine.h" + +namespace llvm { + +class LLVMContext; + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +/// TerminatorInst - Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. +/// +class TerminatorInst : public Instruction { +protected: + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0) + : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} + + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) + : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} + + // Out of line virtual method, so the vtable, etc has a home. + ~TerminatorInst(); + + /// Virtual methods - Terminators should overload these and provide inline + /// overrides of non-V methods. + virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; + virtual unsigned getNumSuccessorsV() const = 0; + virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; + virtual TerminatorInst *clone_impl() const = 0; +public: + + /// getNumSuccessors - Return the number of successors that this terminator + /// has. + unsigned getNumSuccessors() const { + return getNumSuccessorsV(); + } + + /// getSuccessor - Return the specified successor. + /// + BasicBlock *getSuccessor(unsigned idx) const { + return getSuccessorV(idx); + } + + /// setSuccessor - Update the specified successor to point at the provided + /// block. + void setSuccessor(unsigned idx, BasicBlock *B) { + setSuccessorV(idx, B); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TerminatorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isTerminator(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// UnaryInstruction Class +//===----------------------------------------------------------------------===// + +class UnaryInstruction : public Instruction { + void *operator new(size_t, unsigned); // Do not implement + +protected: + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, + Instruction *IB = 0) + : Instruction(Ty, iType, &Op<0>(), 1, IB) { + Op<0>() = V; + } + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) + : Instruction(Ty, iType, &Op<0>(), 1, IAE) { + Op<0>() = V; + } +public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + + // Out of line virtual method, so the vtable, etc has a home. + ~UnaryInstruction(); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnaryInstruction *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Alloca || + I->getOpcode() == Instruction::Load || + I->getOpcode() == Instruction::VAArg || + I->getOpcode() == Instruction::ExtractValue || + (I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryInstruction, Value) + +//===----------------------------------------------------------------------===// +// BinaryOperator Class +//===----------------------------------------------------------------------===// + +class BinaryOperator : public Instruction { + void *operator new(size_t, unsigned); // Do not implement +protected: + void init(BinaryOps iType); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const Twine &Name, Instruction *InsertBefore); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const Twine &Name, BasicBlock *InsertAtEnd); + virtual BinaryOperator *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Optionally (if InstBefore is specified) insert the instruction + /// into a BasicBlock right before the specified instruction. The specified + /// Instruction is allowed to be a dereferenced end iterator. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name = Twine(), + Instruction *InsertBefore = 0); + + /// Create() - Construct a binary instruction, given the opcode and the two + /// operands. Also automatically insert this instruction to the end of the + /// BasicBlock specified. + /// + static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, + const Twine &Name, BasicBlock *InsertAtEnd); + + /// Create* - These methods just forward to Create, and are useful when you + /// statically know what type of instruction you're going to create. These + /// helpers just save some typing. +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name = "") {\ + return Create(Instruction::OPC, V1, V2, Name);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, BasicBlock *BB) {\ + return Create(Instruction::OPC, V1, V2, Name, BB);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *Create##OPC(Value *V1, Value *V2, \ + const Twine &Name, Instruction *I) {\ + return Create(Instruction::OPC, V1, V2, Name, I);\ + } +#include "llvm/Instruction.def" + + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setHasNoSignedWrap(true); + return BO; + } + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setHasNoSignedWrap(true); + return BO; + } + + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setHasNoUnsignedWrap(true); + return BO; + } + static BinaryOperator *CreateNUW(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setHasNoUnsignedWrap(true); + return BO; + } + + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name = "") { + BinaryOperator *BO = Create(Opc, V1, V2, Name); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, BasicBlock *BB) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, BB); + BO->setIsExact(true); + return BO; + } + static BinaryOperator *CreateExact(BinaryOps Opc, Value *V1, Value *V2, + const Twine &Name, Instruction *I) { + BinaryOperator *BO = Create(Opc, V1, V2, Name, I); + BO->setIsExact(true); + return BO; + } + +#define DEFINE_HELPERS(OPC, NUWNSWEXACT) \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name = "") { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, BB); \ + } \ + static BinaryOperator *Create ## NUWNSWEXACT ## OPC \ + (Value *V1, Value *V2, const Twine &Name, Instruction *I) { \ + return Create ## NUWNSWEXACT(Instruction::OPC, V1, V2, Name, I); \ + } + + DEFINE_HELPERS(Add, NSW) // CreateNSWAdd + DEFINE_HELPERS(Add, NUW) // CreateNUWAdd + DEFINE_HELPERS(Sub, NSW) // CreateNSWSub + DEFINE_HELPERS(Sub, NUW) // CreateNUWSub + DEFINE_HELPERS(Mul, NSW) // CreateNSWMul + DEFINE_HELPERS(Mul, NUW) // CreateNUWMul + DEFINE_HELPERS(Shl, NSW) // CreateNSWShl + DEFINE_HELPERS(Shl, NUW) // CreateNUWShl + + DEFINE_HELPERS(SDiv, Exact) // CreateExactSDiv + DEFINE_HELPERS(UDiv, Exact) // CreateExactUDiv + DEFINE_HELPERS(AShr, Exact) // CreateExactAShr + DEFINE_HELPERS(LShr, Exact) // CreateExactLShr + +#undef DEFINE_HELPERS + + /// Helper functions to construct and inspect unary operations (NEG and NOT) + /// via binary operators SUB and XOR: + /// + /// CreateNeg, CreateNot - Create the NEG and NOT + /// instructions out of SUB and XOR instructions. + /// + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *CreateNot(Value *Op, const Twine &Name, + BasicBlock *InsertAtEnd); + + /// isNeg, isFNeg, isNot - Check if the given Value is a + /// NEG, FNeg, or NOT instruction. + /// + static bool isNeg(const Value *V); + static bool isFNeg(const Value *V); + static bool isNot(const Value *V); + + /// getNegArgument, getNotArgument - Helper functions to extract the + /// unary argument of a NEG, FNEG or NOT operation implemented via + /// Sub, FSub, or Xor. + /// + static const Value *getNegArgument(const Value *BinOp); + static Value *getNegArgument( Value *BinOp); + static const Value *getFNegArgument(const Value *BinOp); + static Value *getFNegArgument( Value *BinOp); + static const Value *getNotArgument(const Value *BinOp); + static Value *getNotArgument( Value *BinOp); + + BinaryOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + /// swapOperands - Exchange the two operands to this instruction. + /// This instruction is safe to use on any binary instruction and + /// does not modify the semantics of the instruction. If the instruction + /// cannot be reversed (ie, it's a Div), then return true. + /// + bool swapOperands(); + + /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoUnsignedWrap(bool b = true); + + /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setHasNoSignedWrap(bool b = true); + + /// setIsExact - Set or clear the exact flag on this instruction, + /// which must be an operator which supports this flag. See LangRef.html + /// for the meaning of this flag. + void setIsExact(bool b = true); + + /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set. + bool hasNoUnsignedWrap() const; + + /// hasNoSignedWrap - Determine whether the no signed wrap flag is set. + bool hasNoSignedWrap() const; + + /// isExact - Determine whether the exact flag is set. + bool isExact() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BinaryOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isBinaryOp(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) + +//===----------------------------------------------------------------------===// +// CastInst Class +//===----------------------------------------------------------------------===// + +/// CastInst - This is the base class for all instructions that perform data +/// casts. It is simply provided so that instruction category testing +/// can be performed with code like: +/// +/// if (isa(Instr)) { ... } +/// @brief Base class of casting instructions. +class CastInst : public UnaryInstruction { +protected: + /// @brief Constructor with insert-before-instruction semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const Twine &NameStr = "", Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + setName(NameStr); + } + /// @brief Constructor with insert-at-end-of-block semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + setName(NameStr); + } +public: + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category (Instruction::isCast(opcode) returns true). This + /// constructor has insert-before-instruction semantics to automatically + /// insert the new CastInst before InsertBefore (if it is non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode of the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category. This constructor has insert-at-end-of-block semantics + /// to automatically insert the new CastInst at the end of InsertAtEnd (if + /// its non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *Create( + Instruction::CastOps, ///< The opcode for the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *CreateZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *CreateSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *CreatePointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *CreateIntegerCast( + Value *S, ///< The integer value to be casted (operand 0) + const Type *Ty, ///< The integer type to which operand is casted + bool isSigned, ///< Whether to regard S as signed or not + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *CreateFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *CreateTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Check whether it is valid to call getCastOpcode for these types. + static bool isCastable( + const Type *SrcTy, ///< The Type from which the value should be cast. + const Type *DestTy ///< The Type to which the value should be cast. + ); + + /// Returns the opcode necessary to cast Val into Ty using usual casting + /// rules. + /// @brief Infer the opcode for cast operand and type + static Instruction::CastOps getCastOpcode( + const Value *Val, ///< The value to cast + bool SrcIsSigned, ///< Whether to treat the source as signed + const Type *Ty, ///< The Type to which the value should be casted + bool DstIsSigned ///< Whether to treate the dest. as signed + ); + + /// There are several places where we need to know if a cast instruction + /// only deals with integer source and destination types. To simplify that + /// logic, this method is provided. + /// @returns true iff the cast has only integral typed operand and dest type. + /// @brief Determine if this is an integer-only cast. + bool isIntegerCast() const; + + /// A lossless cast is one that does not alter the basic value. It implies + /// a no-op cast but is more stringent, preventing things like int->float, + /// long->double, or int->ptr. + /// @returns true iff the cast is lossless. + /// @brief Determine if this is a lossless cast. + bool isLosslessCast() const; + + /// A no-op cast is one that can be effected without changing any bits. + /// It implies that the source and destination types are the same size. The + /// IntPtrTy argument is used to make accurate determinations for casts + /// involving Integer and Pointer types. They are no-op casts if the integer + /// is the same size as the pointer. However, pointer size varies with + /// platform. Generally, the result of TargetData::getIntPtrType() should be + /// passed in. If that's not available, use Type::Int64Ty, which will make + /// the isNoopCast call conservative. + /// @brief Determine if the described cast is a no-op cast. + static bool isNoopCast( + Instruction::CastOps Opcode, ///< Opcode of cast + const Type *SrcTy, ///< SrcTy of cast + const Type *DstTy, ///< DstTy of cast + const Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + ); + + /// @brief Determine if this cast is a no-op cast. + bool isNoopCast( + const Type *IntPtrTy ///< Integer type corresponding to pointer + ) const; + + /// Determine how a pair of casts can be eliminated, if they can be at all. + /// This is a helper function for both CastInst and ConstantExpr. + /// @returns 0 if the CastInst pair can't be eliminated + /// @returns Instruction::CastOps value for a cast that can replace + /// the pair, casting SrcTy to DstTy. + /// @brief Determine if a cast pair is eliminable + static unsigned isEliminableCastPair( + Instruction::CastOps firstOpcode, ///< Opcode of first cast + Instruction::CastOps secondOpcode, ///< Opcode of second cast + const Type *SrcTy, ///< SrcTy of 1st cast + const Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast + const Type *DstTy, ///< DstTy of 2nd cast + const Type *IntPtrTy ///< Integer type corresponding to Ptr types, or null + ); + + /// @brief Return the opcode of this CastInst + Instruction::CastOps getOpcode() const { + return Instruction::CastOps(Instruction::getOpcode()); + } + + /// @brief Return the source type, as a convenience + const Type* getSrcTy() const { return getOperand(0)->getType(); } + /// @brief Return the destination type, as a convenience + const Type* getDestTy() const { return getType(); } + + /// This method can be used to determine if a cast from S to DstTy using + /// Opcode op is valid or not. + /// @returns true iff the proposed cast is valid. + /// @brief Determine if a cast is valid without creating one. + static bool castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->isCast(); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CmpInst Class +//===----------------------------------------------------------------------===// + +/// This class is the base class for the comparison instructions. +/// @brief Abstract base class of comparison instructions. +class CmpInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + CmpInst(); // do not implement +protected: + CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name = "", + Instruction *InsertBefore = 0); + + CmpInst(const Type *ty, Instruction::OtherOps op, unsigned short pred, + Value *LHS, Value *RHS, const Twine &Name, + BasicBlock *InsertAtEnd); + + virtual void Anchor() const; // Out of line virtual method. +public: + /// This enumeration lists the possible predicates for CmpInst subclasses. + /// Values in the range 0-31 are reserved for FCmpInst, while values in the + /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the + /// predicate values are not overlapping between the classes. + enum Predicate { + // Opcode U L G E Intuitive operation + FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) + FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal + FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than + FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal + FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than + FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal + FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal + FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) + FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal + FCMP_UGT = 10, ///< 1 0 1 0 True if unordered or greater than + FCMP_UGE = 11, ///< 1 0 1 1 True if unordered, greater than, or equal + FCMP_ULT = 12, ///< 1 1 0 0 True if unordered or less than + FCMP_ULE = 13, ///< 1 1 0 1 True if unordered, less than, or equal + FCMP_UNE = 14, ///< 1 1 1 0 True if unordered or not equal + FCMP_TRUE = 15, ///< 1 1 1 1 Always true (always folded) + FIRST_FCMP_PREDICATE = FCMP_FALSE, + LAST_FCMP_PREDICATE = FCMP_TRUE, + BAD_FCMP_PREDICATE = FCMP_TRUE + 1, + ICMP_EQ = 32, ///< equal + ICMP_NE = 33, ///< not equal + ICMP_UGT = 34, ///< unsigned greater than + ICMP_UGE = 35, ///< unsigned greater or equal + ICMP_ULT = 36, ///< unsigned less than + ICMP_ULE = 37, ///< unsigned less or equal + ICMP_SGT = 38, ///< signed greater than + ICMP_SGE = 39, ///< signed greater or equal + ICMP_SLT = 40, ///< signed less than + ICMP_SLE = 41, ///< signed less or equal + FIRST_ICMP_PREDICATE = ICMP_EQ, + LAST_ICMP_PREDICATE = ICMP_SLE, + BAD_ICMP_PREDICATE = ICMP_SLE + 1 + }; + + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + /// Construct a compare instruction, given the opcode, the predicate and + /// the two operands. Optionally (if InstBefore is specified) insert the + /// instruction into a BasicBlock right before the specified instruction. + /// The specified Instruction is allowed to be a dereferenced end iterator. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, + unsigned short predicate, Value *S1, + Value *S2, const Twine &Name = "", + Instruction *InsertBefore = 0); + + /// Construct a compare instruction, given the opcode, the predicate and the + /// two operands. Also automatically insert this instruction to the end of + /// the BasicBlock specified. + /// @brief Create a CmpInst + static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); + + /// @brief Get the opcode casted to the right type + OtherOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { + return Predicate(getSubclassDataFromInstruction()); + } + + /// @brief Set the predicate for this instruction to the specified value. + void setPredicate(Predicate P) { setInstructionSubclassData(P); } + + static bool isFPPredicate(Predicate P) { + return P >= FIRST_FCMP_PREDICATE && P <= LAST_FCMP_PREDICATE; + } + + static bool isIntPredicate(Predicate P) { + return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; + } + + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } + bool isIntPredicate() const { return isIntPredicate(getPredicate()); } + + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for the instruction's current predicate. + /// @brief Return the inverse of the instruction's predicate. + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, + /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for predicate provided in \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SGE, ULT->UGT, + /// OEQ->OEQ, ULE->UGE, OLT->OGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the CmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate pred); + + /// @brief Provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Swap the operands and adjust predicate accordingly to retain + /// the same comparison. + void swapOperands(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this CmpInst is commutative. + bool isCommutative() const; + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this is an equals/not equals predicate. + bool isEquality() const; + + /// @returns true if the comparison is signed, false otherwise. + /// @brief Determine if this instruction is using a signed comparison. + bool isSigned() const { + return isSigned(getPredicate()); + } + + /// @returns true if the comparison is unsigned, false otherwise. + /// @brief Determine if this instruction is using an unsigned comparison. + bool isUnsigned() const { + return isUnsigned(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is true when both operands are the same. + bool isTrueWhenEqual() const { + return isTrueWhenEqual(getPredicate()); + } + + /// This is just a convenience. + /// @brief Determine if this is false when both operands are the same. + bool isFalseWhenEqual() const { + return isFalseWhenEqual(getPredicate()); + } + + /// @returns true if the predicate is unsigned, false otherwise. + /// @brief Determine if the predicate is an unsigned operation. + static bool isUnsigned(unsigned short predicate); + + /// @returns true if the predicate is signed, false otherwise. + /// @brief Determine if the predicate is an signed operation. + static bool isSigned(unsigned short predicate); + + /// @brief Determine if the predicate is an ordered operation. + static bool isOrdered(unsigned short predicate); + + /// @brief Determine if the predicate is an unordered operation. + static bool isUnordered(unsigned short predicate); + + /// Determine if the predicate is true when comparing a value with itself. + static bool isTrueWhenEqual(unsigned short predicate); + + /// Determine if the predicate is false when comparing a value with itself. + static bool isFalseWhenEqual(unsigned short predicate); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp || + I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + /// @brief Create a result type for fcmp/icmp + static const Type* makeCmpResultType(const Type* opnd_type) { + if (const VectorType* vt = dyn_cast(opnd_type)) { + return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), + vt->getNumElements()); + } + return Type::getInt1Ty(opnd_type->getContext()); + } +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + + +// FIXME: these are redundant if CmpInst < BinaryOperator +template <> +struct OperandTraits : public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CmpInst, Value) + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Instruction.def b/final/include/llvm/Instruction.def new file mode 100644 index 00000000000..205f30313e7 --- /dev/null +++ b/final/include/llvm/Instruction.def @@ -0,0 +1,196 @@ +//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM instructions. This is +// used as a central place for enumerating the different instructions and +// should eventually be the place to put comments about the instructions. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#ifndef FIRST_TERM_INST +#define FIRST_TERM_INST(num) +#endif +#ifndef HANDLE_TERM_INST +#ifndef HANDLE_INST +#define HANDLE_TERM_INST(num, opcode, Class) +#else +#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_TERM_INST +#define LAST_TERM_INST(num) +#endif + +#ifndef FIRST_BINARY_INST +#define FIRST_BINARY_INST(num) +#endif +#ifndef HANDLE_BINARY_INST +#ifndef HANDLE_INST +#define HANDLE_BINARY_INST(num, opcode, instclass) +#else +#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_BINARY_INST +#define LAST_BINARY_INST(num) +#endif + +#ifndef FIRST_MEMORY_INST +#define FIRST_MEMORY_INST(num) +#endif +#ifndef HANDLE_MEMORY_INST +#ifndef HANDLE_INST +#define HANDLE_MEMORY_INST(num, opcode, Class) +#else +#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_MEMORY_INST +#define LAST_MEMORY_INST(num) +#endif + +#ifndef FIRST_CAST_INST +#define FIRST_CAST_INST(num) +#endif +#ifndef HANDLE_CAST_INST +#ifndef HANDLE_INST +#define HANDLE_CAST_INST(num, opcode, Class) +#else +#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_CAST_INST +#define LAST_CAST_INST(num) +#endif + +#ifndef FIRST_OTHER_INST +#define FIRST_OTHER_INST(num) +#endif +#ifndef HANDLE_OTHER_INST +#ifndef HANDLE_INST +#define HANDLE_OTHER_INST(num, opcode, Class) +#else +#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_OTHER_INST +#define LAST_OTHER_INST(num) +#endif + + +// Terminator Instructions - These instructions are used to terminate a basic +// block of the program. Every basic block must end with one of these +// instructions for it to be a well formed basic block. +// + FIRST_TERM_INST ( 1) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Unwind , UnwindInst) +HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) + LAST_TERM_INST ( 7) + +// Standard binary operators... + FIRST_BINARY_INST( 8) +HANDLE_BINARY_INST( 8, Add , BinaryOperator) +HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) +HANDLE_BINARY_INST(10, Sub , BinaryOperator) +HANDLE_BINARY_INST(11, FSub , BinaryOperator) +HANDLE_BINARY_INST(12, Mul , BinaryOperator) +HANDLE_BINARY_INST(13, FMul , BinaryOperator) +HANDLE_BINARY_INST(14, UDiv , BinaryOperator) +HANDLE_BINARY_INST(15, SDiv , BinaryOperator) +HANDLE_BINARY_INST(16, FDiv , BinaryOperator) +HANDLE_BINARY_INST(17, URem , BinaryOperator) +HANDLE_BINARY_INST(18, SRem , BinaryOperator) +HANDLE_BINARY_INST(19, FRem , BinaryOperator) + +// Logical operators (integer operands) +HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(23, And , BinaryOperator) +HANDLE_BINARY_INST(24, Or , BinaryOperator) +HANDLE_BINARY_INST(25, Xor , BinaryOperator) + LAST_BINARY_INST(25) + +// Memory operators... + FIRST_MEMORY_INST(26) +HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(28, Store , StoreInst ) +HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) + LAST_MEMORY_INST(29) + +// Cast operators ... +// NOTE: The order matters here because CastInst::isEliminableCastPair +// NOTE: (see Instructions.cpp) encodes a table based on this ordering. + FIRST_CAST_INST(30) +HANDLE_CAST_INST(30, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(31, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(32, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(33, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(34, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(35, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(36, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(37, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(38, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(39, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(40, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(41, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(41) + +// Other operators... + FIRST_OTHER_INST(42) +HANDLE_OTHER_INST(42, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(43, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(44, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(45, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(46, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(47, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(48, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(49, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(50, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(51, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(52, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(53, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(54, InsertValue, InsertValueInst) // insert into aggregate + + LAST_OTHER_INST(54) + +#undef FIRST_TERM_INST +#undef HANDLE_TERM_INST +#undef LAST_TERM_INST + +#undef FIRST_BINARY_INST +#undef HANDLE_BINARY_INST +#undef LAST_BINARY_INST + +#undef FIRST_MEMORY_INST +#undef HANDLE_MEMORY_INST +#undef LAST_MEMORY_INST + +#undef FIRST_CAST_INST +#undef HANDLE_CAST_INST +#undef LAST_CAST_INST + +#undef FIRST_OTHER_INST +#undef HANDLE_OTHER_INST +#undef LAST_OTHER_INST + +#ifdef HANDLE_INST +#undef HANDLE_INST +#endif diff --git a/final/include/llvm/Instruction.h b/final/include/llvm/Instruction.h new file mode 100644 index 00000000000..89bb9fdf423 --- /dev/null +++ b/final/include/llvm/Instruction.h @@ -0,0 +1,390 @@ +//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Instruction class, which is the +// base class for all of the LLVM instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_H +#define LLVM_INSTRUCTION_H + +#include "llvm/User.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class LLVMContext; +class MDNode; + +template + class SymbolTableListTraits; + +class Instruction : public User, public ilist_node { + void operator=(const Instruction &); // Do not implement + Instruction(const Instruction &); // Do not implement + + BasicBlock *Parent; + DebugLoc DbgLoc; // 'dbg' Metadata cache. + + enum { + /// HasMetadataBit - This is a bit stored in the SubClassData field which + /// indicates whether this instruction has metadata attached to it or not. + HasMetadataBit = 1 << 15 + }; +public: + // Out of line virtual method, so the vtable, etc has a home. + ~Instruction(); + + /// use_back - Specialize the methods defined in Value, as we know that an + /// instruction can only be used by other instructions. + Instruction *use_back() { return cast(*use_begin());} + const Instruction *use_back() const { return cast(*use_begin());} + + inline const BasicBlock *getParent() const { return Parent; } + inline BasicBlock *getParent() { return Parent; } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + /// + void eraseFromParent(); + + /// insertBefore - Insert an unlinked instructions into a basic block + /// immediately before the specified instruction. + void insertBefore(Instruction *InsertPos); + + /// insertAfter - Insert an unlinked instructions into a basic block + /// immediately after the specified instruction. + void insertAfter(Instruction *InsertPos); + + /// moveBefore - Unlink this instruction from its current basic block and + /// insert it into the basic block that MovePos lives in, right before + /// MovePos. + void moveBefore(Instruction *MovePos); + + //===--------------------------------------------------------------------===// + // Subclass classification. + //===--------------------------------------------------------------------===// + + /// getOpcode() returns a member of one of the enums like Instruction::Add. + unsigned getOpcode() const { return getValueID() - InstructionVal; } + + const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } + bool isTerminator() const { return isTerminator(getOpcode()); } + bool isBinaryOp() const { return isBinaryOp(getOpcode()); } + bool isShift() { return isShift(getOpcode()); } + bool isCast() const { return isCast(getOpcode()); } + + static const char* getOpcodeName(unsigned OpCode); + + static inline bool isTerminator(unsigned OpCode) { + return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; + } + + static inline bool isBinaryOp(unsigned Opcode) { + return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; + } + + /// @brief Determine if the Opcode is one of the shift instructions. + static inline bool isShift(unsigned Opcode) { + return Opcode >= Shl && Opcode <= AShr; + } + + /// isLogicalShift - Return true if this is a logical shift left or a logical + /// shift right. + inline bool isLogicalShift() const { + return getOpcode() == Shl || getOpcode() == LShr; + } + + /// isArithmeticShift - Return true if this is an arithmetic shift right. + inline bool isArithmeticShift() const { + return getOpcode() == AShr; + } + + /// @brief Determine if the OpCode is one of the CastInst instructions. + static inline bool isCast(unsigned OpCode) { + return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; + } + + //===--------------------------------------------------------------------===// + // Metadata manipulation. + //===--------------------------------------------------------------------===// + + /// hasMetadata() - Return true if this instruction has any metadata attached + /// to it. + bool hasMetadata() const { + return !DbgLoc.isUnknown() || hasMetadataHashEntry(); + } + + /// hasMetadataOtherThanDebugLoc - Return true if this instruction has + /// metadata attached to it other than a debug location. + bool hasMetadataOtherThanDebugLoc() const { + return hasMetadataHashEntry(); + } + + /// getMetadata - Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(unsigned KindID) const { + if (!hasMetadata()) return 0; + return getMetadataImpl(KindID); + } + + /// getMetadata - Get the metadata of given kind attached to this Instruction. + /// If the metadata is not found then return null. + MDNode *getMetadata(const char *Kind) const { + if (!hasMetadata()) return 0; + return getMetadataImpl(Kind); + } + + /// getAllMetadata - Get all metadata attached to this Instruction. The first + /// element of each pair returned is the KindID, the second element is the + /// metadata value. This list is returned sorted by the KindID. + void getAllMetadata(SmallVectorImpl > &MDs)const{ + if (hasMetadata()) + getAllMetadataImpl(MDs); + } + + /// getAllMetadataOtherThanDebugLoc - This does the same thing as + /// getAllMetadata, except that it filters out the debug location. + void getAllMetadataOtherThanDebugLoc(SmallVectorImpl > &MDs) const { + if (hasMetadataOtherThanDebugLoc()) + getAllMetadataOtherThanDebugLocImpl(MDs); + } + + /// setMetadata - Set the metadata of the specified kind to the specified + /// node. This updates/replaces metadata if already present, or removes it if + /// Node is null. + void setMetadata(unsigned KindID, MDNode *Node); + void setMetadata(const char *Kind, MDNode *Node); + + /// setDebugLoc - Set the debug location information for this instruction. + void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } + + /// getDebugLoc - Return the debug location for this node as a DebugLoc. + const DebugLoc &getDebugLoc() const { return DbgLoc; } + +private: + /// hasMetadataHashEntry - Return true if we have an entry in the on-the-side + /// metadata hash. + bool hasMetadataHashEntry() const { + return (getSubclassDataFromValue() & HasMetadataBit) != 0; + } + + // These are all implemented in Metadata.cpp. + MDNode *getMetadataImpl(unsigned KindID) const; + MDNode *getMetadataImpl(const char *Kind) const; + void getAllMetadataImpl(SmallVectorImpl > &)const; + void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl > &) const; + void clearMetadataHashEntries(); +public: + //===--------------------------------------------------------------------===// + // Predicates and helper methods. + //===--------------------------------------------------------------------===// + + + /// isAssociative - Return true if the instruction is associative: + /// + /// Associative operators satisfy: x op (y op z) === (x op y) op z + /// + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative. + /// + bool isAssociative() const { return isAssociative(getOpcode()); } + static bool isAssociative(unsigned op); + + /// isCommutative - Return true if the instruction is commutative: + /// + /// Commutative operators satisfy: (x op y) === (y op x) + /// + /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when + /// applied to any type. + /// + bool isCommutative() const { return isCommutative(getOpcode()); } + static bool isCommutative(unsigned op); + + /// mayWriteToMemory - Return true if this instruction may modify memory. + /// + bool mayWriteToMemory() const; + + /// mayReadFromMemory - Return true if this instruction may read memory. + /// + bool mayReadFromMemory() const; + + /// mayThrow - Return true if this instruction may throw an exception. + /// + bool mayThrow() const; + + /// mayHaveSideEffects - Return true if the instruction may have side effects. + /// + /// Note that this does not consider malloc and alloca to have side + /// effects because the newly allocated memory is completely invisible to + /// instructions which don't used the returned value. For cases where this + /// matters, isSafeToSpeculativelyExecute may be more appropriate. + bool mayHaveSideEffects() const { + return mayWriteToMemory() || mayThrow(); + } + + /// isSafeToSpeculativelyExecute - Return true if the instruction does not + /// have any effects besides calculating the result and does not have + /// undefined behavior. + /// + /// This method never returns true for an instruction that returns true for + /// mayHaveSideEffects; however, this method also does some other checks in + /// addition. It checks for undefined behavior, like dividing by zero or + /// loading from an invalid pointer (but not for undefined results, like a + /// shift with a shift amount larger than the width of the result). It checks + /// for malloc and alloca because speculatively executing them might cause a + /// memory leak. It also returns false for instructions related to control + /// flow, specifically terminators and PHI nodes. + /// + /// This method only looks at the instruction itself and its operands, so if + /// this method returns true, it is safe to move the instruction as long as + /// the correct dominance relationships for the operands and users hold. + /// However, this method can return true for instructions that read memory; + /// for such instructions, moving them may change the resulting value. + bool isSafeToSpeculativelyExecute() const; + + /// clone() - Create a copy of 'this' instruction that is identical in all + /// ways except the following: + /// * The instruction has no parent + /// * The instruction has no name + /// + Instruction *clone() const; + + /// isIdenticalTo - Return true if the specified instruction is exactly + /// identical to the current one. This means that all operands match and any + /// extra information (e.g. load is volatile) agree. + bool isIdenticalTo(const Instruction *I) const; + + /// isIdenticalToWhenDefined - This is like isIdenticalTo, except that it + /// ignores the SubclassOptionalData flags, which specify conditions + /// under which the instruction's result is undefined. + bool isIdenticalToWhenDefined(const Instruction *I) const; + + /// This function determines if the specified instruction executes the same + /// operation as the current one. This means that the opcodes, type, operand + /// types and any other factors affecting the operation must be the same. This + /// is similar to isIdenticalTo except the operands themselves don't have to + /// be identical. + /// @returns true if the specified instruction is the same operation as + /// the current one. + /// @brief Determine if one instruction is the same operation as another. + bool isSameOperationAs(const Instruction *I) const; + + /// isUsedOutsideOfBlock - Return true if there are any uses of this + /// instruction in blocks other than the specified block. Note that PHI nodes + /// are considered to evaluate their operands in the corresponding predecessor + /// block. + bool isUsedOutsideOfBlock(const BasicBlock *BB) const; + + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= Value::InstructionVal; + } + + //---------------------------------------------------------------------- + // Exported enumerations. + // + enum TermOps { // These terminate basic blocks +#define FIRST_TERM_INST(N) TermOpsBegin = N, +#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, +#define LAST_TERM_INST(N) TermOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum BinaryOps { +#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, +#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, +#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum MemoryOps { +#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, +#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, +#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum CastOps { +#define FIRST_CAST_INST(N) CastOpsBegin = N, +#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, +#define LAST_CAST_INST(N) CastOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum OtherOps { +#define FIRST_OTHER_INST(N) OtherOpsBegin = N, +#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, +#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 +#include "llvm/Instruction.def" + }; +private: + // Shadow Value::setValueSubclassData with a private forwarding method so that + // subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } + unsigned short getSubclassDataFromValue() const { + return Value::getSubclassDataFromValue(); + } + + void setHasMetadataHashEntry(bool V) { + setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) | + (V ? HasMetadataBit : 0)); + } + + friend class SymbolTableListTraits; + void setParent(BasicBlock *P); +protected: + // Instruction subclasses can stick up to 15 bits of stuff into the + // SubclassData field of instruction with these members. + + // Verify that only the low 15 bits are used. + void setInstructionSubclassData(unsigned short D) { + assert((D & HasMetadataBit) == 0 && "Out of range value put into field"); + setValueSubclassData((getSubclassDataFromValue() & HasMetadataBit) | D); + } + + unsigned getSubclassDataFromInstruction() const { + return getSubclassDataFromValue() & ~HasMetadataBit; + } + + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0); + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + BasicBlock *InsertAtEnd); + virtual Instruction *clone_impl() const = 0; + +}; + +// Instruction* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { + typedef Instruction* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Instructions.h b/final/include/llvm/Instructions.h new file mode 100644 index 00000000000..17ff763c52b --- /dev/null +++ b/final/include/llvm/Instructions.h @@ -0,0 +1,3186 @@ +//===-- llvm/Instructions.h - Instruction subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the class definitions of all of the subclasses of the +// Instruction class. This is meant to be an easy way to get access to all +// instruction subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTIONS_H +#define LLVM_INSTRUCTIONS_H + +#include "llvm/InstrTypes.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Attributes.h" +#include "llvm/CallingConv.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +class ConstantInt; +class ConstantRange; +class APInt; +class LLVMContext; + +//===----------------------------------------------------------------------===// +// AllocaInst Class +//===----------------------------------------------------------------------===// + +/// AllocaInst - an instruction to allocate memory on the stack +/// +class AllocaInst : public UnaryInstruction { +protected: + virtual AllocaInst *clone_impl() const; +public: + explicit AllocaInst(const Type *Ty, Value *ArraySize = 0, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, Value *ArraySize, + const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(const Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); + + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name = "", Instruction *InsertBefore = 0); + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const Twine &Name, BasicBlock *InsertAtEnd); + + // Out of line virtual method, so the vtable, etc. has a home. + virtual ~AllocaInst(); + + /// isArrayAllocation - Return true if there is an allocation size parameter + /// to the allocation instruction that is not 1. + /// + bool isArrayAllocation() const; + + /// getArraySize - Get the number of elements allocated. For a simple + /// allocation of a single element, this will return a constant 1 value. + /// + const Value *getArraySize() const { return getOperand(0); } + Value *getArraySize() { return getOperand(0); } + + /// getType - Overload to return most specific pointer type + /// + const PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// getAllocatedType - Return the type that is being allocated by the + /// instruction. + /// + const Type *getAllocatedType() const; + + /// getAlignment - Return the alignment of the memory that is being allocated + /// by the instruction. + /// + unsigned getAlignment() const { + return (1u << getSubclassDataFromInstruction()) >> 1; + } + void setAlignment(unsigned Align); + + /// isStaticAlloca - Return true if this alloca is in the entry block of the + /// function and is a constant size. If so, the code generator will fold it + /// into the prolog/epilog code, so it is basically free. + bool isStaticAlloca() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AllocaInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Alloca); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + + +//===----------------------------------------------------------------------===// +// LoadInst Class +//===----------------------------------------------------------------------===// + +/// LoadInst - an instruction for reading from memory. This uses the +/// SubclassData field in Value to store whether or not the load is volatile. +/// +class LoadInst : public UnaryInstruction { + void AssertOK(); +protected: + virtual LoadInst *clone_impl() const; +public: + LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + + LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); + LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + explicit LoadInst(Value *Ptr, const char *NameStr = 0, + bool isVolatile = false, Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1; + } + + void setAlignment(unsigned Align); + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const LoadInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Load; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + + +//===----------------------------------------------------------------------===// +// StoreInst Class +//===----------------------------------------------------------------------===// + +/// StoreInst - an instruction for storing to memory +/// +class StoreInst : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + void AssertOK(); +protected: + virtual StoreInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); + StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, BasicBlock *InsertAtEnd); + + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return getSubclassDataFromInstruction() & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + (V ? 1 : 0)); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1; + } + + void setAlignment(unsigned Align); + + Value *getValueOperand() { return getOperand(0); } + const Value *getValueOperand() const { return getOperand(0); } + + Value *getPointerOperand() { return getOperand(1); } + const Value *getPointerOperand() const { return getOperand(1); } + static unsigned getPointerOperandIndex() { return 1U; } + + unsigned getPointerAddressSpace() const { + return cast(getPointerOperand()->getType())->getAddressSpace(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StoreInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Store; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value) + +//===----------------------------------------------------------------------===// +// GetElementPtrInst Class +//===----------------------------------------------------------------------===// + +// checkType - Simple wrapper function to give a better assertion failure +// message on bad indexes for a gep instruction. +// +static inline const Type *checkType(const Type *Ty) { + assert(Ty && "Invalid GetElementPtrInst indices for type!"); + return Ty; +} + +/// GetElementPtrInst - an instruction for type-safe pointer arithmetic to +/// access elements of arrays and structs +/// +class GetElementPtrInst : public Instruction { + GetElementPtrInst(const GetElementPtrInst &GEPI); + void init(Value *Ptr, Value* const *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(Value *Ptr, Value *Idx, const Twine &NameStr); + + template + void init(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) { + // This requires that the iterator points to contiguous memory. + init(Ptr, &*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + else { + init(Ptr, 0, NumIdx, NameStr); + } + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + // This argument ensures that we + // have an iterator we can do + // arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) + // This requires that the iterator points to contiguous memory. + return getIndexedType(Ptr, &*IdxBegin, NumIdx); + else + return getIndexedType(Ptr, (Value *const*)0, NumIdx); + } + + /// Constructors - Create a getelementptr instruction with a base pointer an + /// list of indices. The first ctor can optionally insert before an existing + /// instruction, the second appends the new instruction to the specified + /// BasicBlock. + template + inline GetElementPtrInst(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline GetElementPtrInst(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index getelementptr instructions are so common. + GetElementPtrInst(Value *Ptr, Value *Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + GetElementPtrInst(Value *Ptr, Value *Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual GetElementPtrInst *clone_impl() const; +public: + template + static GetElementPtrInst *Create(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + typename std::iterator_traits::difference_type + Values = 1 + std::distance(IdxBegin, IdxEnd); + return new(Values) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertBefore); + } + template + static GetElementPtrInst *Create(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + typename std::iterator_traits::difference_type + Values = 1 + std::distance(IdxBegin, IdxEnd); + return new(Values) + GetElementPtrInst(Ptr, IdxBegin, IdxEnd, Values, NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index getelementptr instructions are so common. + static GetElementPtrInst *Create(Value *Ptr, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertBefore); + } + static GetElementPtrInst *Create(Value *Ptr, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) GetElementPtrInst(Ptr, Idx, NameStr, InsertAtEnd); + } + + /// Create an "inbounds" getelementptr. See the documentation for the + /// "inbounds" flag in LangRef.html for details. + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertBefore); + GEP->setIsInBounds(true); + return GEP; + } + template + static GetElementPtrInst *CreateInBounds(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, + NameStr, InsertAtEnd); + GEP->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore); + GEP->setIsInBounds(true); + return GEP; + } + static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd); + GEP->setIsInBounds(true); + return GEP; + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // getType - Overload to return most specific pointer type... + const PointerType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified + /// pointer type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd) { + return getIndexedType(Ptr, IdxBegin, IdxEnd, + typename std::iterator_traits:: + iterator_category()); + } + + static const Type *getIndexedType(const Type *Ptr, + Value* const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, + Constant* const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, + uint64_t const *Idx, unsigned NumIdx); + + static const Type *getIndexedType(const Type *Ptr, Value *Idx); + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + unsigned getPointerAddressSpace() const { + return cast(getType())->getAddressSpace(); + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + const PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); + } + + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const; + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const; + + /// setIsInBounds - Set or clear the inbounds flag on this GEP instruction. + /// See LangRef.html for the meaning of inbounds on a getelementptr. + void setIsInBounds(bool b = true); + + /// isInBounds - Determine whether the GEP has the inbounds flag. + bool isInBounds() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GetElementPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::GetElementPtr); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public VariadicOperandTraits { +}; + +template +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd)), + cast(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { + init(Ptr, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} +template +GetElementPtrInst::GetElementPtrInst(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + unsigned Values, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(PointerType::get(checkType( + getIndexedType(Ptr->getType(), + IdxBegin, IdxEnd)), + cast(Ptr->getType()) + ->getAddressSpace()), + GetElementPtr, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { + init(Ptr, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value) + + +//===----------------------------------------------------------------------===// +// ICmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on integers or pointers. The operands +/// must be identical types. +/// @brief Represent an integer comparison operator. +class ICmpInst: public CmpInst { +protected: + /// @brief Clone an indentical ICmpInst + virtual ICmpInst *clone_impl() const; +public: + /// @brief Constructor with insert-before-instruction semantics. + ICmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// @brief Constructor with insert-at-end semantics. + ICmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// @brief Constructor with no-insertion semantics + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::ICmp, pred, LHS, RHS, NameStr) { + assert(pred >= CmpInst::FIRST_ICMP_PREDICATE && + pred <= CmpInst::LAST_ICMP_PREDICATE && + "Invalid ICmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to ICmp instruction are not of the same type!"); + // Check that the operands are the right type + assert((getOperand(0)->getType()->isIntOrIntVectorTy() || + getOperand(0)->getType()->isPointerTy()) && + "Invalid operand types for ICmp instruction"); + } + + /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as signed. + /// @brief Return the signed version of the predicate + Predicate getSignedPredicate() const { + return getSignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// @brief Return the signed version of the predicate. + static Predicate getSignedPredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->ULE, UGT->UGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as unsigned. + /// @brief Return the unsigned version of the predicate + Predicate getUnsignedPredicate() const { + return getUnsignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// @brief Return the unsigned version of the predicate. + static Predicate getUnsignedPredicate(Predicate pred); + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + static bool isEquality(Predicate P) { + return P == ICMP_EQ || P == ICMP_NE; + } + + /// isEquality - Return true if this predicate is either EQ or NE. This also + /// tests for commutativity. + bool isEquality() const { + return isEquality(getPredicate()); + } + + /// @returns true if the predicate of this ICmpInst is commutative + /// @brief Determine if this relation is commutative. + bool isCommutative() const { return isEquality(); } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + bool isRelational() const { + return !isEquality(); + } + + /// isRelational - Return true if the predicate is relational (not EQ or NE). + /// + static bool isRelational(Predicate P) { + return !isEquality(P); + } + + /// Initialize a set of values that all satisfy the predicate with C. + /// @brief Make a ConstantRange for a relation with a constant value. + static ConstantRange makeConstantRange(Predicate pred, const APInt &C); + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + setPredicate(getSwappedPredicate()); + Op<0>().swap(Op<1>()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ICmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +}; + +//===----------------------------------------------------------------------===// +// FCmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on floating point values or packed +/// vectors of floating point values. The operands must be identical types. +/// @brief Represents a floating point comparison operator. +class FCmpInst: public CmpInst { +protected: + /// @brief Clone an indentical FCmpInst + virtual FCmpInst *clone_impl() const; +public: + /// @brief Constructor with insert-before-instruction semantics. + FCmpInst( + Instruction *InsertBefore, ///< Where to insert + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + InsertBefore) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// @brief Constructor with insert-at-end semantics. + FCmpInst( + BasicBlock &InsertAtEnd, ///< Block to insert into. + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr, + &InsertAtEnd) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// @brief Constructor with no-insertion semantics + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const Twine &NameStr = "" ///< Name of the instruction + ) : CmpInst(makeCmpResultType(LHS->getType()), + Instruction::FCmp, pred, LHS, RHS, NameStr) { + assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && + "Invalid FCmp predicate value"); + assert(getOperand(0)->getType() == getOperand(1)->getType() && + "Both operands to FCmp instruction are not of the same type!"); + // Check that the operands are the right type + assert(getOperand(0)->getType()->isFPOrFPVectorTy() && + "Invalid operand types for FCmp instruction"); + } + + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return getPredicate() == FCMP_OEQ || getPredicate() == FCMP_ONE || + getPredicate() == FCMP_UEQ || getPredicate() == FCMP_UNE; + } + + /// @returns true if the predicate of this instruction is commutative. + /// @brief Determine if this is a commutative predicate. + bool isCommutative() const { + return isEquality() || + getPredicate() == FCMP_FALSE || + getPredicate() == FCMP_TRUE || + getPredicate() == FCMP_ORD || + getPredicate() == FCMP_UNO; + } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { return !isEquality(); } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + setPredicate(getSwappedPredicate()); + Op<0>().swap(Op<1>()); + } + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FCmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +/// CallInst - This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// field to indicate whether or not this is a tail call. The rest of the bits +/// hold the calling convention of the call. +/// +class CallInst : public Instruction { + AttrListPtr AttributeList; ///< parameter attributes for call + CallInst(const CallInst &CI); + void init(Value *Func, Value* const *Params, unsigned NumParams); + void init(Value *Func, Value *Actual1, Value *Actual2); + void init(Value *Func, Value *Actual); + void init(Value *Func); + + template + void init(Value *Func, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumArgs = (unsigned)std::distance(ArgBegin, ArgEnd); + + // This requires that the iterator points to contiguous memory. + init(Func, NumArgs ? &*ArgBegin : 0, NumArgs); + setName(NameStr); + } + + /// Construct a CallInst given a range of arguments. RandomAccessIterator + /// must be a random-access iterator pointing to contiguous storage + /// (e.g. a std::vector<>::iterator). Checks are made for + /// random-accessness but not for contiguous storage as that would + /// incur runtime overhead. + /// @brief Construct a CallInst from a range of arguments + template + CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct a CallInst given a range of arguments. RandomAccessIterator + /// must be a random-access iterator pointing to contiguous storage + /// (e.g. a std::vector<>::iterator). Checks are made for + /// random-accessness but not for contiguous storage as that would + /// incur runtime overhead. + /// @brief Construct a CallInst from a range of arguments + template + inline CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + CallInst(Value *F, Value *Actual, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, Value *Actual, const Twine &NameStr, + BasicBlock *InsertAtEnd); + explicit CallInst(Value *F, const Twine &NameStr, + Instruction *InsertBefore); + CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual CallInst *clone_impl() const; +public: + template + static CallInst *Create(Value *Func, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(unsigned(ArgEnd - ArgBegin + 1)) + CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertBefore); + } + template + static CallInst *Create(Value *Func, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new(unsigned(ArgEnd - ArgBegin + 1)) + CallInst(Func, ArgBegin, ArgEnd, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *F, Value *Actual, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) CallInst(F, Actual, NameStr, InsertBefore); + } + static CallInst *Create(Value *F, Value *Actual, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) CallInst(F, Actual, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *F, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(1) CallInst(F, NameStr, InsertBefore); + } + static CallInst *Create(Value *F, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(1) CallInst(F, NameStr, InsertAtEnd); + } + /// CreateMalloc - Generate the IR for a call to malloc: + /// 1. Compute the malloc call's argument as the specified type's size, + /// possibly multiplied by the array size if the array size is not + /// constant 1. + /// 2. Call malloc with that argument. + /// 3. Bitcast the result of the malloc call to the specified type. + static Instruction *CreateMalloc(Instruction *InsertBefore, + const Type *IntPtrTy, const Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + Function* MallocF = 0, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, + const Type *IntPtrTy, const Type *AllocTy, + Value *AllocSize, Value *ArraySize = 0, + Function* MallocF = 0, + const Twine &Name = ""); + /// CreateFree - Generate the IR for a call to the builtin free function. + static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); + static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); + + ~CallInst(); + + bool isTailCall() const { return getSubclassDataFromInstruction() & 1; } + void setTailCall(bool isTC = true) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | + unsigned(isTC)); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumArgOperands - Return the number of call arguments. + /// + unsigned getNumArgOperands() const { return getNumOperands() - 1; } + + /// getArgOperand/setArgOperand - Return/set the i-th call argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast(getSubclassDataFromInstruction() >> 1); + } + void setCallingConv(CallingConv::ID CC) { + setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | + (static_cast(CC) << 1)); + } + + /// getAttributes - Return the parameter attributes for this call. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this call. + /// + void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Determine whether the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Return true if the call should not be inlined. + bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); } + void setIsNoInline(bool Value = true) { + if (Value) addAttribute(~0, Attribute::NoInline); + else removeAttribute(~0, Attribute::NoInline); + } + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(~0, Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool NotAccessMemory = true) { + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const { return paramHasAttr(~0, Attribute::NoReturn); } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); + } + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const { return paramHasAttr(~0, Attribute::NoUnwind); } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); + } + + /// @brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast(Op<-1>()); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction. + const Value *getCalledValue() const { return Op<-1>(); } + Value *getCalledValue() { return Op<-1>(); } + + /// setCalledFunction - Set the function called. + void setCalledFunction(Value* Fn) { + Op<-1>() = Fn; + } + + /// isInlineAsm - Check if this call is an inline asm statement. + bool isInlineAsm() const { + return isa(Op<-1>()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CallInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits { +}; + +template +CallInst::CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits::op_end(this) - (ArgEnd - ArgBegin + 1), + unsigned(ArgEnd - ArgBegin + 1), InsertAtEnd) { + init(Func, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + +template +CallInst::CallInst(Value *Func, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + const Twine &NameStr, Instruction *InsertBefore) + : Instruction(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Call, + OperandTraits::op_end(this) - (ArgEnd - ArgBegin + 1), + unsigned(ArgEnd - ArgBegin + 1), InsertBefore) { + init(Func, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + + +// Note: if you get compile errors about private methods then +// please update your code to use the high-level operand +// interfaces. See line 943 above. +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) + +//===----------------------------------------------------------------------===// +// SelectInst Class +//===----------------------------------------------------------------------===// + +/// SelectInst - This class represents the LLVM 'select' instruction. +/// +class SelectInst : public Instruction { + void init(Value *C, Value *S1, Value *S2) { + assert(!areInvalidOperands(C, S1, S2) && "Invalid operands for select"); + Op<0>() = C; + Op<1>() = S1; + Op<2>() = S2; + } + + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertBefore) { + init(C, S1, S2); + setName(NameStr); + } + SelectInst(Value *C, Value *S1, Value *S2, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(S1->getType(), Instruction::Select, + &Op<0>(), 3, InsertAtEnd) { + init(C, S1, S2); + setName(NameStr); + } +protected: + virtual SelectInst *clone_impl() const; +public: + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertBefore); + } + static SelectInst *Create(Value *C, Value *S1, Value *S2, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) SelectInst(C, S1, S2, NameStr, InsertAtEnd); + } + + const Value *getCondition() const { return Op<0>(); } + const Value *getTrueValue() const { return Op<1>(); } + const Value *getFalseValue() const { return Op<2>(); } + Value *getCondition() { return Op<0>(); } + Value *getTrueValue() { return Op<1>(); } + Value *getFalseValue() { return Op<2>(); } + + /// areInvalidOperands - Return a string if the specified operands are invalid + /// for a select operation, otherwise return null. + static const char *areInvalidOperands(Value *Cond, Value *True, Value *False); + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + OtherOps getOpcode() const { + return static_cast(Instruction::getOpcode()); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SelectInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Select; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) + +//===----------------------------------------------------------------------===// +// VAArgInst Class +//===----------------------------------------------------------------------===// + +/// VAArgInst - This class represents the va_arg llvm instruction, which returns +/// an argument of the specified type given a va_list and increments that list +/// +class VAArgInst : public UnaryInstruction { +protected: + virtual VAArgInst *clone_impl() const; + +public: + VAArgInst(Value *List, const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, VAArg, List, InsertBefore) { + setName(NameStr); + } + VAArgInst(Value *List, const Type *Ty, const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { + setName(NameStr); + } + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VAArgInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == VAArg; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ExtractElementInst Class +//===----------------------------------------------------------------------===// + +/// ExtractElementInst - This instruction extracts a single (scalar) +/// element from a VectorType value +/// +class ExtractElementInst : public Instruction { + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, + BasicBlock *InsertAtEnd); +protected: + virtual ExtractElementInst *clone_impl() const; + +public: + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertBefore); + } + static ExtractElementInst *Create(Value *Vec, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an extractelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *Idx); + + Value *getVectorOperand() { return Op<0>(); } + Value *getIndexOperand() { return Op<1>(); } + const Value *getVectorOperand() const { return Op<0>(); } + const Value *getIndexOperand() const { return Op<1>(); } + + const VectorType *getVectorOperandType() const { + return reinterpret_cast(getVectorOperand()->getType()); + } + + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ExtractElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractElement; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) + +//===----------------------------------------------------------------------===// +// InsertElementInst Class +//===----------------------------------------------------------------------===// + +/// InsertElementInst - This instruction inserts a single (scalar) +/// element into a VectorType value +/// +class InsertElementInst : public Instruction { + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertElementInst *clone_impl() const; + +public: + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertBefore); + } + static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertAtEnd); + } + + /// isValidOperands - Return true if an insertelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *NewElt, + const Value *Idx); + + /// getType - Overload to return most specific vector type. + /// + const VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InsertElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertElement; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) + +//===----------------------------------------------------------------------===// +// ShuffleVectorInst Class +//===----------------------------------------------------------------------===// + +/// ShuffleVectorInst - This instruction constructs a fixed permutation of two +/// input vectors. +/// +class ShuffleVectorInst : public Instruction { +protected: + virtual ShuffleVectorInst *clone_impl() const; + +public: + // allocate space for exactly three operands + void *operator new(size_t s) { + return User::operator new(s, 3); + } + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr = "", + Instruction *InsertBefor = 0); + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if a shufflevector instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *V1, const Value *V2, + const Value *Mask); + + /// getType - Overload to return most specific vector type. + /// + const VectorType *getType() const { + return reinterpret_cast(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getMaskValue - Return the index from the shuffle mask for the specified + /// output result. This is either -1 if the element is undef or a number less + /// than 2*numelements. + int getMaskValue(unsigned i) const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ShuffleVectorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ShuffleVector; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorInst, Value) + +//===----------------------------------------------------------------------===// +// ExtractValueInst Class +//===----------------------------------------------------------------------===// + +/// ExtractValueInst - This instruction extracts a struct member or array +/// element value from an aggregate value. +/// +class ExtractValueInst : public UnaryInstruction { + SmallVector Indices; + + ExtractValueInst(const ExtractValueInst &EVI); + void init(const unsigned *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(unsigned Idx, const Twine &NameStr); + + template + void init(RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + // There's no fundamental reason why we require at least one index + // (other than weirdness with &*IdxBegin being invalid; see + // getelementptr's init routine for example). But there's no + // present need to support it. + assert(NumIdx > 0 && "ExtractValueInst must have at least one index"); + + // This requires that the iterator points to contiguous memory. + init(&*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + + /// getIndexedType - Returns the type of the element that would be extracted + /// with an extractvalue instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified type. + /// + static const Type *getIndexedType(const Type *Agg, + const unsigned *Idx, unsigned NumIdx); + + template + static const Type *getIndexedType(const Type *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + // This argument ensures that we + // have an iterator we can do + // arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + if (NumIdx > 0) + // This requires that the iterator points to contiguous memory. + return getIndexedType(Ptr, &*IdxBegin, NumIdx); + else + return getIndexedType(Ptr, (const unsigned *)0, NumIdx); + } + + /// Constructors - Create a extractvalue instruction with a base aggregate + /// value and a list of indices. The first ctor can optionally insert before + /// an existing instruction, the second appends the new instruction to the + /// specified BasicBlock. + template + inline ExtractValueInst(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline ExtractValueInst(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } +protected: + virtual ExtractValueInst *clone_impl() const; + +public: + template + static ExtractValueInst *Create(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new + ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertBefore); + } + template + static ExtractValueInst *Create(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new ExtractValueInst(Agg, IdxBegin, IdxEnd, NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index extractvalue instructions are much more common than those with + /// more than one. + static ExtractValueInst *Create(Value *Agg, unsigned Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Idxs[1] = { Idx }; + return new ExtractValueInst(Agg, Idxs, Idxs + 1, NameStr, InsertBefore); + } + static ExtractValueInst *Create(Value *Agg, unsigned Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Idxs[1] = { Idx }; + return new ExtractValueInst(Agg, Idxs, Idxs + 1, NameStr, InsertAtEnd); + } + + /// getIndexedType - Returns the type of the element that would be extracted + /// with an extractvalue instruction with the specified parameters. + /// + /// Null is returned if the indices are invalid for the specified type. + /// + template + static const Type *getIndexedType(const Type *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd) { + return getIndexedType(Ptr, IdxBegin, IdxEnd, + typename std::iterator_traits:: + iterator_category()); + } + static const Type *getIndexedType(const Type *Ptr, unsigned Idx); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + unsigned getNumIndices() const { // Note: always non-negative + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ExtractValueInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractValue; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template +ExtractValueInst::ExtractValueInst(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore) + : UnaryInstruction(checkType(getIndexedType(Agg->getType(), + IdxBegin, IdxEnd)), + ExtractValue, Agg, InsertBefore) { + init(IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} +template +ExtractValueInst::ExtractValueInst(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : UnaryInstruction(checkType(getIndexedType(Agg->getType(), + IdxBegin, IdxEnd)), + ExtractValue, Agg, InsertAtEnd) { + init(IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + + +//===----------------------------------------------------------------------===// +// InsertValueInst Class +//===----------------------------------------------------------------------===// + +/// InsertValueInst - This instruction inserts a struct field of array element +/// value into an aggregate value. +/// +class InsertValueInst : public Instruction { + SmallVector Indices; + + void *operator new(size_t, unsigned); // Do not implement + InsertValueInst(const InsertValueInst &IVI); + void init(Value *Agg, Value *Val, const unsigned *Idx, unsigned NumIdx, + const Twine &NameStr); + void init(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr); + + template + void init(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, RandomAccessIterator IdxEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumIdx = static_cast(std::distance(IdxBegin, IdxEnd)); + + // There's no fundamental reason why we require at least one index + // (other than weirdness with &*IdxBegin being invalid; see + // getelementptr's init routine for example). But there's no + // present need to support it. + assert(NumIdx > 0 && "InsertValueInst must have at least one index"); + + // This requires that the iterator points to contiguous memory. + init(Agg, Val, &*IdxBegin, NumIdx, NameStr); // FIXME: for the general case + // we have to build an array here + } + + /// Constructors - Create a insertvalue instruction with a base aggregate + /// value, a value to insert, and a list of indices. The first ctor can + /// optionally insert before an existing instruction, the second appends + /// the new instruction to the specified BasicBlock. + template + inline InsertValueInst(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore); + template + inline InsertValueInst(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index insertvalue instructions are so common. + InsertValueInst(Value *Agg, Value *Val, + unsigned Idx, const Twine &NameStr = "", + Instruction *InsertBefore = 0); + InsertValueInst(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InsertValueInst *clone_impl() const; +public: + // allocate space for exactly two operands + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + template + static InsertValueInst *Create(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, + NameStr, InsertBefore); + } + template + static InsertValueInst *Create(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new InsertValueInst(Agg, Val, IdxBegin, IdxEnd, + NameStr, InsertAtEnd); + } + + /// Constructors - These two creators are convenience methods because one + /// index insertvalue instructions are much more common than those with + /// more than one. + static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new InsertValueInst(Agg, Val, Idx, NameStr, InsertBefore); + } + static InsertValueInst *Create(Value *Agg, Value *Val, unsigned Idx, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new InsertValueInst(Agg, Val, Idx, NameStr, InsertAtEnd); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } + + Value *getAggregateOperand() { + return getOperand(0); + } + const Value *getAggregateOperand() const { + return getOperand(0); + } + static unsigned getAggregateOperandIndex() { + return 0U; // get index for modifying correct operand + } + + Value *getInsertedValueOperand() { + return getOperand(1); + } + const Value *getInsertedValueOperand() const { + return getOperand(1); + } + static unsigned getInsertedValueOperandIndex() { + return 1U; // get index for modifying correct operand + } + + unsigned getNumIndices() const { // Note: always non-negative + return (unsigned)Indices.size(); + } + + bool hasIndices() const { + return true; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InsertValueInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertValue; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; + +template +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + Instruction *InsertBefore) + : Instruction(Agg->getType(), InsertValue, + OperandTraits::op_begin(this), + 2, InsertBefore) { + init(Agg, Val, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} +template +InsertValueInst::InsertValueInst(Value *Agg, + Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) + : Instruction(Agg->getType(), InsertValue, + OperandTraits::op_begin(this), + 2, InsertAtEnd) { + init(Agg, Val, IdxBegin, IdxEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueInst, Value) + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +// PHINode - The PHINode class is used to represent the magical mystical PHI +// node, that can not exist in nature, but can be synthesized in a computer +// scientist's overactive imagination. +// +class PHINode : public Instruction { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + PHINode(const PHINode &PN); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit PHINode(const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), + ReservedSpace(0) { + setName(NameStr); + } + + PHINode(const Type *Ty, const Twine &NameStr, BasicBlock *InsertAtEnd) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), + ReservedSpace(0) { + setName(NameStr); + } +protected: + virtual PHINode *clone_impl() const; +public: + static PHINode *Create(const Type *Ty, const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + return new PHINode(Ty, NameStr, InsertBefore); + } + static PHINode *Create(const Type *Ty, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new PHINode(Ty, NameStr, InsertAtEnd); + } + ~PHINode(); + + /// reserveOperandSpace - This method can be used to avoid repeated + /// reallocation of PHI operand lists by reserving space for the correct + /// number of operands before adding them. Unlike normal vector reserves, + /// this method can also be used to trim the operand space. + void reserveOperandSpace(unsigned NumValues) { + resizeOperands(NumValues*2); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumIncomingValues - Return the number of incoming edges + /// + unsigned getNumIncomingValues() const { return getNumOperands()/2; } + + /// getIncomingValue - Return incoming value number x + /// + Value *getIncomingValue(unsigned i) const { + assert(i*2 < getNumOperands() && "Invalid value number!"); + return getOperand(i*2); + } + void setIncomingValue(unsigned i, Value *V) { + assert(i*2 < getNumOperands() && "Invalid value number!"); + setOperand(i*2, V); + } + static unsigned getOperandNumForIncomingValue(unsigned i) { + return i*2; + } + static unsigned getIncomingValueNumForOperand(unsigned i) { + assert(i % 2 == 0 && "Invalid incoming-value operand index!"); + return i/2; + } + + /// getIncomingBlock - Return incoming basic block number @p i. + /// + BasicBlock *getIncomingBlock(unsigned i) const { + return cast(getOperand(i*2+1)); + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to an operand of the PHI. + /// + BasicBlock *getIncomingBlock(const Use &U) const { + assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); + return cast((&U + 1)->get()); + } + + /// getIncomingBlock - Return incoming basic block corresponding + /// to value use iterator. + /// + template + BasicBlock *getIncomingBlock(value_use_iterator I) const { + return getIncomingBlock(I.getUse()); + } + + + void setIncomingBlock(unsigned i, BasicBlock *BB) { + setOperand(i*2+1, (Value*)BB); + } + static unsigned getOperandNumForIncomingBlock(unsigned i) { + return i*2+1; + } + static unsigned getIncomingBlockNumForOperand(unsigned i) { + assert(i % 2 == 1 && "Invalid incoming-block operand index!"); + return i/2; + } + + /// addIncoming - Add an incoming value to the end of the PHI list + /// + void addIncoming(Value *V, BasicBlock *BB) { + assert(V && "PHI node got a null value!"); + assert(BB && "PHI node got a null basic block!"); + assert(getType() == V->getType() && + "All operands to PHI node must be the same type as the PHI node!"); + unsigned OpNo = NumOperands; + if (OpNo+2 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + NumOperands = OpNo+2; + OperandList[OpNo] = V; + OperandList[OpNo+1] = (Value*)BB; + } + + /// removeIncomingValue - Remove an incoming value. This is useful if a + /// predecessor basic block is deleted. The value removed is returned. + /// + /// If the last incoming value for a PHI node is removed (and DeletePHIIfEmpty + /// is true), the PHI node is destroyed and any uses of it are replaced with + /// dummy values. The only time there should be zero incoming values to a PHI + /// node is when the block is dead, so this strategy is sound. + /// + Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); + + Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty=true) { + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument to remove!"); + return removeIncomingValue(Idx, DeletePHIIfEmpty); + } + + /// getBasicBlockIndex - Return the first index of the specified basic + /// block in the value list for this PHI. Returns -1 if no instance. + /// + int getBasicBlockIndex(const BasicBlock *BB) const { + Use *OL = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) + if (OL[i+1].get() == (const Value*)BB) return i/2; + return -1; + } + + Value *getIncomingValueForBlock(const BasicBlock *BB) const { + return getIncomingValue(getBasicBlockIndex(BB)); + } + + /// hasConstantValue - If the specified PHI node always merges together the + /// same value, return the value, otherwise return null. + Value *hasConstantValue() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PHINode *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::PHI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + private: + void resizeOperands(unsigned NumOperands); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(PHINode, Value) + + +//===----------------------------------------------------------------------===// +// ReturnInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ReturnInst - Return a value (possibly void), from a function. Execution +/// does not continue in this function any longer. +/// +class ReturnInst : public TerminatorInst { + ReturnInst(const ReturnInst &RI); + +private: + // ReturnInst constructors: + // ReturnInst() - 'ret void' instruction + // ReturnInst( null) - 'ret void' instruction + // ReturnInst(Value* X) - 'ret X' instruction + // ReturnInst( null, Inst *I) - 'ret void' instruction, insert before I + // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I + // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of B + // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of B + // + // NOTE: If the Value* passed is of type void then the constructor behaves as + // if it was passed NULL. + explicit ReturnInst(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0); + ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); + explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); +protected: + virtual ReturnInst *clone_impl() const; +public: + static ReturnInst* Create(LLVMContext &C, Value *retVal = 0, + Instruction *InsertBefore = 0) { + return new(!!retVal) ReturnInst(C, retVal, InsertBefore); + } + static ReturnInst* Create(LLVMContext &C, Value *retVal, + BasicBlock *InsertAtEnd) { + return new(!!retVal) ReturnInst(C, retVal, InsertAtEnd); + } + static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { + return new(0) ReturnInst(C, InsertAtEnd); + } + virtual ~ReturnInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessor. Returns null if there is no return value. + Value *getReturnValue() const { + return getNumOperands() != 0 ? getOperand(0) : 0; + } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ReturnInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Ret); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value) + +//===----------------------------------------------------------------------===// +// BranchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// BranchInst - Conditional or Unconditional Branch instruction. +/// +class BranchInst : public TerminatorInst { + /// Ops list - Branches are strange. The operands are ordered: + /// [Cond, FalseDest,] TrueDest. This makes some accessors faster because + /// they don't have to check for cond/uncond branchness. These are mostly + /// accessed relative from op_end(). + BranchInst(const BranchInst &BI); + void AssertOK(); + // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): + // BranchInst(BB *B) - 'br B' + // BranchInst(BB* T, BB *F, Value *C) - 'br C, T, F' + // BranchInst(BB* B, Inst *I) - 'br B' insert before I + // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I + // BranchInst(BB* B, BB *I) - 'br B' insert at end + // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end + explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + BasicBlock *InsertAtEnd); +protected: + virtual BranchInst *clone_impl() const; +public: + static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { + return new(1) BranchInst(IfTrue, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, Instruction *InsertBefore = 0) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { + return new(1) BranchInst(IfTrue, InsertAtEnd); + } + static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, + Value *Cond, BasicBlock *InsertAtEnd) { + return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertAtEnd); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool isUnconditional() const { return getNumOperands() == 1; } + bool isConditional() const { return getNumOperands() == 3; } + + Value *getCondition() const { + assert(isConditional() && "Cannot get condition of an uncond branch!"); + return Op<-3>(); + } + + void setCondition(Value *V) { + assert(isConditional() && "Cannot set condition of unconditional branch!"); + Op<-3>() = V; + } + + unsigned getNumSuccessors() const { return 1+isConditional(); } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); + return cast_or_null((&Op<-1>() - i)->get()); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); + *(&Op<-1>() - idx) = (Value*)NewSucc; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BranchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Br); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public VariadicOperandTraits { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BranchInst, Value) + +//===----------------------------------------------------------------------===// +// SwitchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// SwitchInst - Multiway switch +/// +class SwitchInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + SwitchInst(const SwitchInst &SI); + void init(Value *Value, BasicBlock *Default, unsigned NumReserved); + void resizeOperands(unsigned No); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor can also autoinsert before another instruction. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + Instruction *InsertBefore); + + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor also autoinserts at the end of the specified BasicBlock. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + BasicBlock *InsertAtEnd); +protected: + virtual SwitchInst *clone_impl() const; +public: + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, Instruction *InsertBefore = 0) { + return new SwitchInst(Value, Default, NumCases, InsertBefore); + } + static SwitchInst *Create(Value *Value, BasicBlock *Default, + unsigned NumCases, BasicBlock *InsertAtEnd) { + return new SwitchInst(Value, Default, NumCases, InsertAtEnd); + } + ~SwitchInst(); + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for Switch stmt + Value *getCondition() const { return getOperand(0); } + void setCondition(Value *V) { setOperand(0, V); } + + BasicBlock *getDefaultDest() const { + return cast(getOperand(1)); + } + + /// getNumCases - return the number of 'cases' in this switch instruction. + /// Note that case #0 is always the default case. + unsigned getNumCases() const { + return getNumOperands()/2; + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + ConstantInt *getCaseValue(unsigned i) { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + const ConstantInt *getCaseValue(unsigned i) const { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// findCaseValue - Search all of the case values for the specified constant. + /// If it is explicitly handled, return the case number of it, otherwise + /// return 0 to indicate that it is handled by the default handler. + unsigned findCaseValue(const ConstantInt *C) const { + for (unsigned i = 1, e = getNumCases(); i != e; ++i) + if (getCaseValue(i) == C) + return i; + return 0; + } + + /// findCaseDest - Finds the unique case value for a given successor. Returns + /// null if the successor is not found, not unique, or is the default case. + ConstantInt *findCaseDest(BasicBlock *BB) { + if (BB == getDefaultDest()) return NULL; + + ConstantInt *CI = NULL; + for (unsigned i = 1, e = getNumCases(); i != e; ++i) { + if (getSuccessor(i) == BB) { + if (CI) return NULL; // Multiple cases lead to BB. + else CI = getCaseValue(i); + } + } + return CI; + } + + /// addCase - Add an entry to the switch instruction... + /// + void addCase(ConstantInt *OnVal, BasicBlock *Dest); + + /// removeCase - This method removes the specified successor from the switch + /// instruction. Note that this cannot be used to remove the default + /// destination (successor #0). Also note that this operation may reorder the + /// remaining cases at index idx and above. + /// + void removeCase(unsigned idx); + + unsigned getNumSuccessors() const { return getNumOperands()/2; } + BasicBlock *getSuccessor(unsigned idx) const { + assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); + return cast(getOperand(idx*2+1)); + } + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); + setOperand(idx*2+1, (Value*)NewSucc); + } + + // getSuccessorValue - Return the value associated with the specified + // successor. + ConstantInt *getSuccessorValue(unsigned idx) const { + assert(idx < getNumSuccessors() && "Successor # out of range!"); + return reinterpret_cast(getOperand(idx*2)); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SwitchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Switch; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<2> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SwitchInst, Value) + + +//===----------------------------------------------------------------------===// +// IndirectBrInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// IndirectBrInst - Indirect Branch Instruction. +/// +class IndirectBrInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + IndirectBrInst(const IndirectBrInst &IBI); + void init(Value *Address, unsigned NumDests); + void resizeOperands(unsigned No); + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor can also + /// autoinsert before another instruction. + IndirectBrInst(Value *Address, unsigned NumDests, Instruction *InsertBefore); + + /// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an + /// Address to jump to. The number of expected destinations can be specified + /// here to make memory allocation more efficient. This constructor also + /// autoinserts at the end of the specified BasicBlock. + IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); +protected: + virtual IndirectBrInst *clone_impl() const; +public: + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + Instruction *InsertBefore = 0) { + return new IndirectBrInst(Address, NumDests, InsertBefore); + } + static IndirectBrInst *Create(Value *Address, unsigned NumDests, + BasicBlock *InsertAtEnd) { + return new IndirectBrInst(Address, NumDests, InsertAtEnd); + } + ~IndirectBrInst(); + + /// Provide fast operand accessors. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Accessor Methods for IndirectBrInst instruction. + Value *getAddress() { return getOperand(0); } + const Value *getAddress() const { return getOperand(0); } + void setAddress(Value *V) { setOperand(0, V); } + + + /// getNumDestinations - return the number of possible destinations in this + /// indirectbr instruction. + unsigned getNumDestinations() const { return getNumOperands()-1; } + + /// getDestination - Return the specified destination. + BasicBlock *getDestination(unsigned i) { return getSuccessor(i); } + const BasicBlock *getDestination(unsigned i) const { return getSuccessor(i); } + + /// addDestination - Add a destination. + /// + void addDestination(BasicBlock *Dest); + + /// removeDestination - This method removes the specified successor from the + /// indirectbr instruction. + void removeDestination(unsigned i); + + unsigned getNumSuccessors() const { return getNumOperands()-1; } + BasicBlock *getSuccessor(unsigned i) const { + return cast(getOperand(i+1)); + } + void setSuccessor(unsigned i, BasicBlock *NewSucc) { + setOperand(i+1, (Value*)NewSucc); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IndirectBrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::IndirectBr; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +template <> +struct OperandTraits : public HungoffOperandTraits<1> { +}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) + + +//===----------------------------------------------------------------------===// +// InvokeInst Class +//===----------------------------------------------------------------------===// + +/// InvokeInst - Invoke instruction. The SubclassData field is used to hold the +/// calling convention of the call. +/// +class InvokeInst : public TerminatorInst { + AttrListPtr AttributeList; + InvokeInst(const InvokeInst &BI); + void init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + Value* const *Args, unsigned NumArgs); + + template + void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + const Twine &NameStr, + // This argument ensures that we have an iterator we can + // do arithmetic on in constant time + std::random_access_iterator_tag) { + unsigned NumArgs = (unsigned)std::distance(ArgBegin, ArgEnd); + + // This requires that the iterator points to contiguous memory. + init(Func, IfNormal, IfException, NumArgs ? &*ArgBegin : 0, NumArgs); + setName(NameStr); + } + + /// Construct an InvokeInst given a range of arguments. + /// RandomAccessIterator must be a random-access iterator pointing to + /// contiguous storage (e.g. a std::vector<>::iterator). Checks are + /// made for random-accessness but not for contiguous storage as + /// that would incur runtime overhead. + /// + /// @brief Construct an InvokeInst from a range of arguments + template + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + + /// Construct an InvokeInst given a range of arguments. + /// RandomAccessIterator must be a random-access iterator pointing to + /// contiguous storage (e.g. a std::vector<>::iterator). Checks are + /// made for random-accessness but not for contiguous storage as + /// that would incur runtime overhead. + /// + /// @brief Construct an InvokeInst from a range of arguments + template + inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, RandomAccessIterator ArgEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); +protected: + virtual InvokeInst *clone_impl() const; +public: + template + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &NameStr = "", + Instruction *InsertBefore = 0) { + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, NameStr, InsertBefore); + } + template + static InvokeInst *Create(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values(ArgEnd - ArgBegin + 3); + return new(Values) InvokeInst(Func, IfNormal, IfException, ArgBegin, ArgEnd, + Values, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumArgOperands - Return the number of invoke arguments. + /// + unsigned getNumArgOperands() const { return getNumOperands() - 3; } + + /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + CallingConv::ID getCallingConv() const { + return static_cast(getSubclassDataFromInstruction()); + } + void setCallingConv(CallingConv::ID CC) { + setInstructionSubclassData(static_cast(CC)); + } + + /// getAttributes - Return the parameter attributes for this invoke. + /// + const AttrListPtr &getAttributes() const { return AttributeList; } + + /// setAttributes - Set the parameter attributes for this invoke. + /// + void setAttributes(const AttrListPtr &Attrs) { AttributeList = Attrs; } + + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, Attributes attr); + + /// removeAttribute - removes the attribute from the list of attributes. + void removeAttribute(unsigned i, Attributes attr); + + /// @brief Determine whether the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attributes attr) const; + + /// @brief Extract the alignment for a call or parameter (0=unknown). + unsigned getParamAlignment(unsigned i) const { + return AttributeList.getParamAlignment(i); + } + + /// @brief Return true if the call should not be inlined. + bool isNoInline() const { return paramHasAttr(~0, Attribute::NoInline); } + void setIsNoInline(bool Value = true) { + if (Value) addAttribute(~0, Attribute::NoInline); + else removeAttribute(~0, Attribute::NoInline); + } + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + return paramHasAttr(~0, Attribute::ReadNone); + } + void setDoesNotAccessMemory(bool NotAccessMemory = true) { + if (NotAccessMemory) addAttribute(~0, Attribute::ReadNone); + else removeAttribute(~0, Attribute::ReadNone); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(~0, Attribute::ReadOnly); + } + void setOnlyReadsMemory(bool OnlyReadsMemory = true) { + if (OnlyReadsMemory) addAttribute(~0, Attribute::ReadOnly); + else removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone); + } + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const { return paramHasAttr(~0, Attribute::NoReturn); } + void setDoesNotReturn(bool DoesNotReturn = true) { + if (DoesNotReturn) addAttribute(~0, Attribute::NoReturn); + else removeAttribute(~0, Attribute::NoReturn); + } + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const { return paramHasAttr(~0, Attribute::NoUnwind); } + void setDoesNotThrow(bool DoesNotThrow = true) { + if (DoesNotThrow) addAttribute(~0, Attribute::NoUnwind); + else removeAttribute(~0, Attribute::NoUnwind); + } + + /// @brief Determine if the call returns a structure through first + /// pointer argument. + bool hasStructRetAttr() const { + // Be friendly and also check the callee. + return paramHasAttr(1, Attribute::StructRet); + } + + /// @brief Determine if any call argument is an aggregate passed by value. + bool hasByValArgument() const { + return AttributeList.hasAttrSomewhere(Attribute::ByVal); + } + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast(Op<-3>()); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction + const Value *getCalledValue() const { return Op<-3>(); } + Value *getCalledValue() { return Op<-3>(); } + + /// setCalledFunction - Set the function called. + void setCalledFunction(Value* Fn) { + Op<-3>() = Fn; + } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getNormalDest() const { + return cast(Op<-2>()); + } + BasicBlock *getUnwindDest() const { + return cast(Op<-1>()); + } + void setNormalDest(BasicBlock *B) { + Op<-2>() = reinterpret_cast(B); + } + void setUnwindDest(BasicBlock *B) { + Op<-1>() = reinterpret_cast(B); + } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < 2 && "Successor # out of range for invoke!"); + return i == 0 ? getNormalDest() : getUnwindDest(); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < 2 && "Successor # out of range for invoke!"); + *(&Op<-2>() + idx) = reinterpret_cast(NewSucc); + } + + unsigned getNumSuccessors() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InvokeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Invoke); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); + + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits : public VariadicOperandTraits { +}; + +template +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + unsigned Values, + const Twine &NameStr, Instruction *InsertBefore) + : TerminatorInst(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits::op_end(this) - Values, + Values, InsertBefore) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} +template +InvokeInst::InvokeInst(Value *Func, + BasicBlock *IfNormal, BasicBlock *IfException, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd) + : TerminatorInst(cast(cast(Func->getType()) + ->getElementType())->getReturnType(), + Instruction::Invoke, + OperandTraits::op_end(this) - Values, + Values, InsertAtEnd) { + init(Func, IfNormal, IfException, ArgBegin, ArgEnd, NameStr, + typename std::iterator_traits + ::iterator_category()); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) + +//===----------------------------------------------------------------------===// +// UnwindInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnwindInst - Immediately exit the current function, unwinding the stack +/// until an invoke instruction is found. +/// +class UnwindInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT +protected: + virtual UnwindInst *clone_impl() const; +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit UnwindInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnwindInst(LLVMContext &C, BasicBlock *InsertAtEnd); + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnwindInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unwind; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// UnreachableInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnreachableInst - This function has undefined behavior. In particular, the +/// presence of this instruction indicates some higher level knowledge that the +/// end of the block cannot be reached. +/// +class UnreachableInst : public TerminatorInst { + void *operator new(size_t, unsigned); // DO NOT IMPLEMENT +protected: + virtual UnreachableInst *clone_impl() const; + +public: + // allocate space for exactly zero operands + void *operator new(size_t s) { + return User::operator new(s, 0); + } + explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnreachableInst(LLVMContext &C, BasicBlock *InsertAtEnd); + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnreachableInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unreachable; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// TruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of integer types. +class TruncInst : public CastInst { +protected: + /// @brief Clone an identical TruncInst + virtual TruncInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Trunc; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ZExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents zero extension of integer types. +class ZExtInst : public CastInst { +protected: + /// @brief Clone an identical ZExtInst + virtual ZExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end semantics. + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ZExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == ZExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a sign extension of integer types. +class SExtInst : public CastInst { +protected: + /// @brief Clone an identical SExtInst + virtual SExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPTruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of floating point types. +class FPTruncInst : public CastInst { +protected: + /// @brief Clone an identical FPTruncInst + virtual FPTruncInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPTruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPTrunc; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents an extension of floating point types. +class FPExtInst : public CastInst { +protected: + /// @brief Clone an identical FPExtInst + virtual FPExtInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPExt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// UIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast unsigned integer to floating point. +class UIToFPInst : public CastInst { +protected: + /// @brief Clone an identical UIToFPInst + virtual UIToFPInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == UIToFP; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from signed integer to floating point. +class SIToFPInst : public CastInst { +protected: + /// @brief Clone an identical SIToFPInst + virtual SIToFPInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SIToFP; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToUIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to unsigned integer +class FPToUIInst : public CastInst { +protected: + /// @brief Clone an identical FPToUIInst + virtual FPToUIInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< Where to insert the new instruction + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToUIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToUI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToSIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to signed integer. +class FPToSIInst : public CastInst { +protected: + /// @brief Clone an identical FPToSIInst + virtual FPToSIInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToSIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToSI; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// IntToPtrInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from an integer to a pointer. +class IntToPtrInst : public CastInst { +public: + /// @brief Constructor with insert-before-instruction semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical IntToPtrInst + virtual IntToPtrInst *clone_impl() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntToPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == IntToPtr; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// PtrToIntInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from a pointer to an integer +class PtrToIntInst : public CastInst { +protected: + /// @brief Clone an identical PtrToIntInst + virtual PtrToIntInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PtrToIntInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == PtrToInt; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +//===----------------------------------------------------------------------===// +// BitCastInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a no-op cast from one type to another. +class BitCastInst : public CastInst { +protected: + /// @brief Clone an identical BitCastInst + virtual BitCastInst *clone_impl() const; + +public: + /// @brief Constructor with insert-before-instruction semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const Twine &NameStr, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BitCastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == BitCast; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/IntrinsicInst.h b/final/include/llvm/IntrinsicInst.h new file mode 100644 index 00000000000..74c30fbddd7 --- /dev/null +++ b/final/include/llvm/IntrinsicInst.h @@ -0,0 +1,306 @@ +//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- 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 classes that make it really easy to deal with intrinsic +// functions with the isa/dyncast family of functions. In particular, this +// allows you to do things like: +// +// if (MemCpyInst *MCI = dyn_cast(Inst)) +// ... MCI->getDest() ... MCI->getSource() ... +// +// All intrinsic function calls are instances of the call instruction, so these +// are all subclasses of the CallInst class. Note that none of these classes +// has state or virtual methods, which is an important part of this gross/neat +// hack working. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICINST_H +#define LLVM_INTRINSICINST_H + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" + +namespace llvm { + /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic + /// functions. This allows the standard isa/dyncast/cast functionality to + /// work with calls to intrinsic functions. + class IntrinsicInst : public CallInst { + IntrinsicInst(); // DO NOT IMPLEMENT + IntrinsicInst(const IntrinsicInst&); // DO NOT IMPLEMENT + void operator=(const IntrinsicInst&); // DO NOT IMPLEMENT + public: + /// getIntrinsicID - Return the intrinsic ID of this intrinsic. + /// + Intrinsic::ID getIntrinsicID() const { + return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *) { return true; } + static inline bool classof(const CallInst *I) { + if (const Function *CF = I->getCalledFunction()) + return CF->getIntrinsicID() != 0; + return false; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics + /// + class DbgInfoIntrinsic : public IntrinsicInst { + public: + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgInfoIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + static Value *StripCast(Value *C); + }; + + /// DbgDeclareInst - This represents the llvm.dbg.declare instruction. + /// + class DbgDeclareInst : public DbgInfoIntrinsic { + public: + Value *getAddress() const; + MDNode *getVariable() const { return cast(getArgOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgDeclareInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_declare; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// DbgValueInst - This represents the llvm.dbg.value instruction. + /// + class DbgValueInst : public DbgInfoIntrinsic { + public: + const Value *getValue() const; + Value *getValue(); + uint64_t getOffset() const { + return cast( + const_cast(getArgOperand(1)))->getZExtValue(); + } + MDNode *getVariable() const { return cast(getArgOperand(2)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgValueInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_value; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemIntrinsic - This is the common base class for memset/memcpy/memmove. + /// + class MemIntrinsic : public IntrinsicInst { + public: + Value *getRawDest() const { return const_cast(getArgOperand(0)); } + + Value *getLength() const { return const_cast(getArgOperand(2)); } + ConstantInt *getAlignmentCst() const { + return cast(const_cast(getArgOperand(3))); + } + + unsigned getAlignment() const { + return getAlignmentCst()->getZExtValue(); + } + + ConstantInt *getVolatileCst() const { + return cast(const_cast(getArgOperand(4))); + } + bool isVolatile() const { + return !getVolatileCst()->isZero(); + } + + unsigned getAddressSpace() const { + return cast(getRawDest()->getType())->getAddressSpace(); + } + + /// getDest - This is just like getRawDest, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getDest() const { return getRawDest()->stripPointerCasts(); } + + /// set* - Set the specified arguments of the instruction. + /// + void setDest(Value *Ptr) { + assert(getRawDest()->getType() == Ptr->getType() && + "setDest called with pointer of wrong type!"); + setArgOperand(0, Ptr); + } + + void setLength(Value *L) { + assert(getLength()->getType() == L->getType() && + "setLength called with value of wrong type!"); + setArgOperand(2, L); + } + + void setAlignment(Constant* A) { + setArgOperand(3, A); + } + + void setVolatile(Constant* V) { + setArgOperand(4, V); + } + + const Type *getAlignmentType() const { + return getArgOperand(3)->getType(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy: + case Intrinsic::memmove: + case Intrinsic::memset: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemSetInst - This class wraps the llvm.memset intrinsic. + /// + class MemSetInst : public MemIntrinsic { + public: + /// get* - Return the arguments to the instruction. + /// + Value *getValue() const { return const_cast(getArgOperand(1)); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setValue called with value of wrong type!"); + setArgOperand(1, Val); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemSetInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memset; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemTransferInst - This class wraps the llvm.memcpy/memmove intrinsics. + /// + class MemTransferInst : public MemIntrinsic { + public: + /// get* - Return the arguments to the instruction. + /// + Value *getRawSource() const { return const_cast(getArgOperand(1)); } + + /// getSource - This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return getRawSource()->stripPointerCasts(); } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setArgOperand(1, Ptr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemTransferInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy || + I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + + /// MemCpyInst - This class wraps the llvm.memcpy intrinsic. + /// + class MemCpyInst : public MemTransferInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemCpyInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// MemMoveInst - This class wraps the llvm.memmove intrinsic. + /// + class MemMoveInst : public MemTransferInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemMoveInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memmove; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// EHExceptionInst - This represents the llvm.eh.exception instruction. + /// + class EHExceptionInst : public IntrinsicInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const EHExceptionInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::eh_exception; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + + /// EHSelectorInst - This represents the llvm.eh.selector instruction. + /// + class EHSelectorInst : public IntrinsicInst { + public: + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const EHSelectorInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::eh_selector; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + }; + +} + +#endif diff --git a/final/include/llvm/Intrinsics.h b/final/include/llvm/Intrinsics.h new file mode 100644 index 00000000000..5cfe55181f5 --- /dev/null +++ b/final/include/llvm/Intrinsics.h @@ -0,0 +1,80 @@ +//===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- 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 set of enums which allow processing of intrinsic +// functions. Values of these enum types are returned by +// Function::getIntrinsicID. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICS_H +#define LLVM_INTRINSICS_H + +#include + +namespace llvm { + +class Type; +class FunctionType; +class Function; +class LLVMContext; +class Module; +class AttrListPtr; + +/// Intrinsic Namespace - This namespace contains an enum with a value for +/// every intrinsic/builtin function known by LLVM. These enum values are +/// returned by Function::getIntrinsicID(). +/// +namespace Intrinsic { + enum ID { + not_intrinsic = 0, // Must be zero + + // Get the intrinsic enums generated from Intrinsics.td +#define GET_INTRINSIC_ENUM_VALUES +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_ENUM_VALUES + , num_intrinsics + }; + + /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as + /// "llvm.ppc.altivec.lvx". + std::string getName(ID id, const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::getType(ID) - Return the function type for an intrinsic. + /// + const FunctionType *getType(LLVMContext &Context, ID id, + const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be + /// overloaded. + bool isOverloaded(ID id); + + /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. + /// + AttrListPtr getAttributes(ID id); + + /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function + /// declaration for an intrinsic, and return it. + /// + /// The Tys and numTys parameters are for intrinsics with overloaded types + /// (e.g., those using iAny, fAny, vAny, or iPTRAny). For a declaration for an + /// overloaded intrinsic, Tys should point to an array of numTys pointers to + /// Type, and must provide exactly one type for each overloaded type in the + /// intrinsic. + Function *getDeclaration(Module *M, ID id, const Type **Tys = 0, + unsigned numTys = 0); + + /// Map a GCC builtin name to an intrinsic ID. + ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + +} // End Intrinsic namespace + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Intrinsics.td b/final/include/llvm/Intrinsics.td new file mode 100644 index 00000000000..ba66555c4e0 --- /dev/null +++ b/final/include/llvm/Intrinsics.td @@ -0,0 +1,493 @@ +//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines properties of all LLVM intrinsics. +// +//===----------------------------------------------------------------------===// + +include "llvm/CodeGen/ValueTypes.td" + +//===----------------------------------------------------------------------===// +// Properties we keep track of for intrinsics. +//===----------------------------------------------------------------------===// + +class IntrinsicProperty; + +// Intr*Mem - Memory properties. An intrinsic is allowed to have at most one of +// these properties set. They are listed from the most aggressive (best to use +// if correct) to the least aggressive. If no property is set, the worst case +// is assumed (it may read and write any memory it can get access to and it may +// have other side effects). + +// IntrNoMem - The intrinsic does not access memory or have any other side +// effects. It may be CSE'd deleted if dead, etc. +def IntrNoMem : IntrinsicProperty; + +// IntrReadArgMem - This intrinsic reads only from memory that one of its +// arguments points to, but may read an unspecified amount. +def IntrReadArgMem : IntrinsicProperty; + +// IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be +// moved across stores. However, it can be reordered otherwise and can be +// deleted if dead. +def IntrReadMem : IntrinsicProperty; + +// IntrReadWriteArgMem - This intrinsic reads and writes only from memory that +// one of its arguments points to, but may access an unspecified amount. The +// reads and writes may be volatile, but except for this it has no other side +// effects. +def IntrReadWriteArgMem : IntrinsicProperty; + +// Commutative - This intrinsic is commutative: X op Y == Y op X. +def Commutative : IntrinsicProperty; + +// NoCapture - The specified argument pointer is not captured by the intrinsic. +class NoCapture : IntrinsicProperty { + int ArgNo = argNo; +} + +//===----------------------------------------------------------------------===// +// Types used by intrinsics. +//===----------------------------------------------------------------------===// + +class LLVMType { + ValueType VT = vt; +} + +class LLVMPointerType + : LLVMType{ + LLVMType ElTy = elty; +} + +class LLVMAnyPointerType + : LLVMType{ + LLVMType ElTy = elty; +} + +// Match the type of another intrinsic parameter. Number is an index into the +// list of overloaded types for the intrinsic, excluding all the fixed types. +// The Number value must refer to a previously listed type. For example: +// Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> +// has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> +// refers to the first overloaded type, which is the 2nd argument. +class LLVMMatchType + : LLVMType{ + int Number = num; +} + +// Match the type of another intrinsic parameter that is expected to be +// an integral vector type, but change the element size to be twice as wide +// or half as wide as the other type. This is only useful when the intrinsic +// is overloaded, so the matched type should be declared as iAny. +class LLVMExtendedElementVectorType : LLVMMatchType; +class LLVMTruncatedElementVectorType : LLVMMatchType; + +def llvm_void_ty : LLVMType; +def llvm_anyint_ty : LLVMType; +def llvm_anyfloat_ty : LLVMType; +def llvm_anyvector_ty : LLVMType; +def llvm_i1_ty : LLVMType; +def llvm_i8_ty : LLVMType; +def llvm_i16_ty : LLVMType; +def llvm_i32_ty : LLVMType; +def llvm_i64_ty : LLVMType; +def llvm_float_ty : LLVMType; +def llvm_double_ty : LLVMType; +def llvm_f80_ty : LLVMType; +def llvm_f128_ty : LLVMType; +def llvm_ppcf128_ty : LLVMType; +def llvm_ptr_ty : LLVMPointerType; // i8* +def llvm_ptrptr_ty : LLVMPointerType; // i8** +def llvm_anyptr_ty : LLVMAnyPointerType; // (space)i8* +def llvm_empty_ty : LLVMType; // { } +def llvm_descriptor_ty : LLVMPointerType; // { }* +def llvm_metadata_ty : LLVMType; // !{...} + +def llvm_x86mmx_ty : LLVMType; +def llvm_ptrx86mmx_ty : LLVMPointerType; // <1 x i64>* + +def llvm_v2i8_ty : LLVMType; // 2 x i8 +def llvm_v4i8_ty : LLVMType; // 4 x i8 +def llvm_v8i8_ty : LLVMType; // 8 x i8 +def llvm_v16i8_ty : LLVMType; // 16 x i8 +def llvm_v32i8_ty : LLVMType; // 32 x i8 +def llvm_v2i16_ty : LLVMType; // 2 x i16 +def llvm_v4i16_ty : LLVMType; // 4 x i16 +def llvm_v8i16_ty : LLVMType; // 8 x i16 +def llvm_v16i16_ty : LLVMType; // 16 x i16 +def llvm_v2i32_ty : LLVMType; // 2 x i32 +def llvm_v4i32_ty : LLVMType; // 4 x i32 +def llvm_v8i32_ty : LLVMType; // 8 x i32 +def llvm_v1i64_ty : LLVMType; // 1 x i64 +def llvm_v2i64_ty : LLVMType; // 2 x i64 +def llvm_v4i64_ty : LLVMType; // 4 x i64 + +def llvm_v2f32_ty : LLVMType; // 2 x float +def llvm_v4f32_ty : LLVMType; // 4 x float +def llvm_v8f32_ty : LLVMType; // 8 x float +def llvm_v2f64_ty : LLVMType; // 2 x double +def llvm_v4f64_ty : LLVMType; // 4 x double + +def llvm_vararg_ty : LLVMType; // this means vararg here + + +//===----------------------------------------------------------------------===// +// Intrinsic Definitions. +//===----------------------------------------------------------------------===// + +// Intrinsic class - This is used to define one LLVM intrinsic. The name of the +// intrinsic definition should start with "int_", then match the LLVM intrinsic +// name with the "llvm." prefix removed, and all "."s turned into "_"s. For +// example, llvm.bswap.i16 -> int_bswap_i16. +// +// * RetTypes is a list containing the return types expected for the +// intrinsic. +// * ParamTypes is a list containing the parameter types expected for the +// intrinsic. +// * Properties can be set to describe the behavior of the intrinsic. +// +class Intrinsic ret_types, + list param_types = [], + list properties = [], + string name = ""> { + string LLVMName = name; + string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. + list RetTypes = ret_types; + list ParamTypes = param_types; + list Properties = properties; + + bit isTarget = 0; +} + +/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this +/// specifies the name of the builtin. This provides automatic CBE and CFE +/// support. +class GCCBuiltin { + string GCCBuiltinName = name; +} + + +//===--------------- Variable Argument Handling Intrinsics ----------------===// +// + +def int_vastart : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; +def int_vacopy : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], + "llvm.va_copy">; +def int_vaend : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; + +//===------------------- Garbage Collection Intrinsics --------------------===// +// +def int_gcroot : Intrinsic<[], + [llvm_ptrptr_ty, llvm_ptr_ty]>; +def int_gcread : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadArgMem]>; +def int_gcwrite : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadWriteArgMem, NoCapture<1>, NoCapture<2>]>; + +//===--------------------- Code Generator Intrinsics ----------------------===// +// +def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; + +// Note: we treat stacksave/stackrestore as writemem because we don't otherwise +// model their dependencies on allocas. +def int_stacksave : Intrinsic<[llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_save">; +def int_stackrestore : Intrinsic<[], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_restore">; + +// IntrReadWriteArgMem is more pessimistic than strictly necessary for prefetch, +// however it does conveniently prevent the prefetch from being reordered +// with respect to nearby accesses to the same memory. +def int_prefetch : Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; +def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; + +def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; + +// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack +// guard to the correct place on the stack frame. +def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; + +//===------------------- Standard C Library Intrinsics --------------------===// +// + +def int_memcpy : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memmove : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; +def int_memset : Intrinsic<[], + [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, + llvm_i32_ty, llvm_i1_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; + +// These functions do not actually read memory, but they are sensitive to the +// rounding mode. This needs to be modelled separately; in the meantime +// declaring them as reading memory is conservatively correct. +let Properties = [IntrReadMem] in { + def int_sqrt : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_powi : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty]>; + def int_sin : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_cos : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_pow : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_log : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log10: Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; +} + +// NOTE: these are internal interfaces. +def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>; +def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; +def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty]>; + +// Internal interface for object size checking +def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_ptr_ty, llvm_i1_ty], + [IntrNoMem]>, + GCCBuiltin<"__builtin_object_size">; + +//===-------------------- Bit Manipulation Intrinsics ---------------------===// +// + +// None of these intrinsics accesses memory at all. +let Properties = [IntrNoMem] in { + def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; +} + +//===------------------------ Debugger Intrinsics -------------------------===// +// + +// None of these intrinsics accesses memory at all...but that doesn't mean the +// optimizers can change them aggressively. Special handling needed in a few +// places. +let Properties = [IntrNoMem] in { + def int_dbg_declare : Intrinsic<[], + [llvm_metadata_ty, llvm_metadata_ty]>; + def int_dbg_value : Intrinsic<[], + [llvm_metadata_ty, llvm_i64_ty, + llvm_metadata_ty]>; +} + +//===------------------ Exception Handling Intrinsics----------------------===// +// +def int_eh_exception : Intrinsic<[llvm_ptr_ty], [], [IntrReadMem]>; +def int_eh_selector : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty]>; + +def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; + +def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; +def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; + +def int_eh_unwind_init: Intrinsic<[]>, + GCCBuiltin<"__builtin_unwind_init">; + +def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; + +let Properties = [IntrNoMem] in { + def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; + def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>; +} +def int_eh_sjlj_dispatch_setup : Intrinsic<[], [llvm_ptr_ty]>; +def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; + +//===---------------- Generic Variable Attribute Intrinsics----------------===// +// +def int_var_annotation : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.var.annotation">; +def int_ptr_annotation : Intrinsic<[LLVMAnyPointerType], + [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [], "llvm.ptr.annotation">; +def int_annotation : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.annotation">; + +//===------------------------ Trampoline Intrinsics -----------------------===// +// +def int_init_trampoline : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>, + GCCBuiltin<"__builtin_init_trampoline">; + +//===------------------------ Overflow Intrinsics -------------------------===// +// + +// Expose the carry flag from add operations on two integrals. +def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; +def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +//===------------------------- Atomic Intrinsics --------------------------===// +// +def int_memory_barrier : Intrinsic<[], + [llvm_i1_ty, llvm_i1_ty, + llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], []>, + GCCBuiltin<"__builtin_llvm_memory_barrier">; + +def int_atomic_cmp_swap : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>, LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_val_compare_and_swap">; +def int_atomic_load_add : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_add">; +def int_atomic_swap : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_lock_test_and_set">; +def int_atomic_load_sub : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_sub">; +def int_atomic_load_and : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_and">; +def int_atomic_load_or : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_or">; +def int_atomic_load_xor : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_xor">; +def int_atomic_load_nand : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_nand">; +def int_atomic_load_min : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_min">; +def int_atomic_load_max : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_max">; +def int_atomic_load_umin : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_umin">; +def int_atomic_load_umax : Intrinsic<[llvm_anyint_ty], + [LLVMAnyPointerType>, + LLVMMatchType<0>], + [IntrReadWriteArgMem, NoCapture<0>]>, + GCCBuiltin<"__sync_fetch_and_umax">; + +//===------------------------- Memory Use Markers -------------------------===// +// +def int_lifetime_start : Intrinsic<[], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_lifetime_end : Intrinsic<[], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_invariant_start : Intrinsic<[llvm_descriptor_ty], + [llvm_i64_ty, llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<1>]>; +def int_invariant_end : Intrinsic<[], + [llvm_descriptor_ty, llvm_i64_ty, + llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<2>]>; + +//===-------------------------- Other Intrinsics --------------------------===// +// +def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, + GCCBuiltin<"__builtin_flt_rounds">; +def int_trap : Intrinsic<[]>, + GCCBuiltin<"__builtin_trap">; + +// Intrisics to support half precision floating point format +let Properties = [IntrNoMem] in { +def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_float_ty]>, + GCCBuiltin<"__gnu_f2h_ieee">; +def int_convert_from_fp16 : Intrinsic<[llvm_float_ty], [llvm_i16_ty]>, + GCCBuiltin<"__gnu_h2f_ieee">; +} + +// These convert intrinsics are to support various conversions between +// various types with rounding and saturation. NOTE: avoid using these +// intrinsics as they might be removed sometime in the future and +// most targets don't support them. +def int_convertff : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfsi : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertfui : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuif : Intrinsic<[llvm_anyint_ty], + [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertss : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertsu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertus : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +def int_convertuu : Intrinsic<[llvm_anyint_ty], + [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// +// Target-specific intrinsics +//===----------------------------------------------------------------------===// + +include "llvm/IntrinsicsPowerPC.td" +include "llvm/IntrinsicsX86.td" +include "llvm/IntrinsicsARM.td" +include "llvm/IntrinsicsCellSPU.td" +include "llvm/IntrinsicsAlpha.td" +include "llvm/IntrinsicsXCore.td" +include "llvm/IntrinsicsPTX.td" diff --git a/final/include/llvm/IntrinsicsARM.td b/final/include/llvm/IntrinsicsARM.td new file mode 100644 index 00000000000..823f095dbdc --- /dev/null +++ b/final/include/llvm/IntrinsicsARM.td @@ -0,0 +1,391 @@ +//===- IntrinsicsARM.td - Defines ARM intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the ARM-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// TLS + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// Saturating Arithmentic + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_arm_qsub : GCCBuiltin<"__builtin_arm_qsub">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_arm_ssat : GCCBuiltin<"__builtin_arm_ssat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// VFP + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">, + Intrinsic<[], [llvm_i32_ty], []>; + def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; + def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". + + // The following classes do not correspond directly to GCC builtins. + class Neon_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class Neon_1Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; + class Neon_2Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class Neon_2Arg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedElementVectorType<0>, + LLVMExtendedElementVectorType<0>], + [IntrNoMem]>; + class Neon_2Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; + class Neon_3Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class Neon_3Arg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, + LLVMTruncatedElementVectorType<0>, + LLVMTruncatedElementVectorType<0>], + [IntrNoMem]>; + class Neon_CvtFxToFP_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; + class Neon_CvtFPToFx_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + + // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. + // Besides the table, VTBL has one other v8i8 argument and VTBX has two. + // Overall, the classes range from 2 to 6 v8i8 arguments. + class Neon_Tbl2Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl3Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl4Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty], + [IntrNoMem]>; + class Neon_Tbl5Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + class Neon_Tbl6Arg_Intrinsic + : Intrinsic<[llvm_v8i8_ty], + [llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty, llvm_v8i8_ty], [IntrNoMem]>; +} + +// Arithmetic ops + +let Properties = [IntrNoMem, Commutative] in { + + // Vector Add. + def int_arm_neon_vhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vrhaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vqadds : Neon_2Arg_Intrinsic; + def int_arm_neon_vqaddu : Neon_2Arg_Intrinsic; + def int_arm_neon_vaddhn : Neon_2Arg_Narrow_Intrinsic; + def int_arm_neon_vraddhn : Neon_2Arg_Narrow_Intrinsic; + + // Vector Multiply. + def int_arm_neon_vmulp : Neon_2Arg_Intrinsic; + def int_arm_neon_vqdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vqrdmulh : Neon_2Arg_Intrinsic; + def int_arm_neon_vmullp : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vqdmull : Neon_2Arg_Long_Intrinsic; + def int_arm_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; + def int_arm_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; + + // Vector Maximum. + def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; + def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; + + // Vector Minimum. + def int_arm_neon_vmins : Neon_2Arg_Intrinsic; + def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Step. + def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; + + // Vector Reciprocal Square Root Step. + def int_arm_neon_vrsqrts : Neon_2Arg_Intrinsic; +} + +// Vector Subtract. +def int_arm_neon_vhsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vhsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubs : Neon_2Arg_Intrinsic; +def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; +def int_arm_neon_vsubhn : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Absolute Compare. +let TargetPrefix = "arm" in { + def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], + [llvm_v2f32_ty, llvm_v2f32_ty], + [IntrNoMem]>; + def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +} + +// Vector Absolute Differences. +def int_arm_neon_vabds : Neon_2Arg_Intrinsic; +def int_arm_neon_vabdu : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add. +def int_arm_neon_vpadd : Neon_2Arg_Intrinsic; + +// Vector Pairwise Add Long. +// Note: This is different than the other "long" NEON intrinsics because +// the result vector has half as many elements as the source vector. +// The source and destination vector types must be specified separately. +let TargetPrefix = "arm" in { + def int_arm_neon_vpaddls : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; + def int_arm_neon_vpaddlu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], + [IntrNoMem]>; +} + +// Vector Pairwise Add and Accumulate Long. +// Note: This is similar to vpaddl but the destination vector also appears +// as the first argument. +let TargetPrefix = "arm" in { + def int_arm_neon_vpadals : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; + def int_arm_neon_vpadalu : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +} + +// Vector Pairwise Maximum and Minimum. +def int_arm_neon_vpmaxs : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmaxu : Neon_2Arg_Intrinsic; +def int_arm_neon_vpmins : Neon_2Arg_Intrinsic; +def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; + +// Vector Shifts: +// +// The various saturating and rounding vector shift operations need to be +// represented by intrinsics in LLVM, and even the basic VSHL variable shift +// operation cannot be safely translated to LLVM's shift operators. VSHL can +// be used for both left and right shifts, or even combinations of the two, +// depending on the signs of the shift amounts. It also has well-defined +// behavior for shift amounts that LLVM leaves undefined. Only basic shifts +// by constants can be represented with LLVM's shift operators. +// +// The shift counts for these intrinsics are always vectors, even for constant +// shifts, where the constant is replicated. For consistency with VSHL (and +// other variable shift instructions), left shifts have positive shift counts +// and right shifts have negative shift counts. This convention is also used +// for constant right shift intrinsics, and to help preserve sanity, the +// intrinsic names use "shift" instead of either "shl" or "shr". Where +// applicable, signed and unsigned versions of the intrinsics are +// distinguished with "s" and "u" suffixes. A few NEON shift instructions, +// such as VQSHLU, take signed operands but produce unsigned results; these +// use a "su" suffix. + +// Vector Shift. +def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; +def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Rounding Shift. +def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vrshiftn : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Shift. +def int_arm_neon_vqshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftsu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Saturating Rounding Shift. +def int_arm_neon_vqrshifts : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftu : Neon_2Arg_Intrinsic; +def int_arm_neon_vqrshiftns : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnu : Neon_2Arg_Narrow_Intrinsic; +def int_arm_neon_vqrshiftnsu : Neon_2Arg_Narrow_Intrinsic; + +// Vector Shift and Insert. +def int_arm_neon_vshiftins : Neon_3Arg_Intrinsic; + +// Vector Absolute Value and Saturating Absolute Value. +def int_arm_neon_vabs : Neon_1Arg_Intrinsic; +def int_arm_neon_vqabs : Neon_1Arg_Intrinsic; + +// Vector Saturating Negate. +def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; + +// Vector Count Leading Sign/Zero Bits. +def int_arm_neon_vcls : Neon_1Arg_Intrinsic; +def int_arm_neon_vclz : Neon_1Arg_Intrinsic; + +// Vector Count One Bits. +def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Estimate. +def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; + +// Vector Reciprocal Square Root Estimate. +def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; + +// Vector Conversions Between Floating-point and Fixed-point. +def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; +def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic; +def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic; + +// Vector Conversions Between Half-Precision and Single-Precision. +def int_arm_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_arm_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + +// Narrowing Saturating Vector Moves. +def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic; +def int_arm_neon_vqmovnsu : Neon_1Arg_Narrow_Intrinsic; + +// Vector Table Lookup. +// The first 1-4 arguments are the table. +def int_arm_neon_vtbl1 : Neon_Tbl2Arg_Intrinsic; +def int_arm_neon_vtbl2 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbl3 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbl4 : Neon_Tbl5Arg_Intrinsic; + +// Vector Table Extension. +// Some elements of the destination vector may not be updated, so the original +// value of that vector is passed as the first argument. The next 1-4 +// arguments after that are the table. +def int_arm_neon_vtbx1 : Neon_Tbl3Arg_Intrinsic; +def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; +def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; +def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; + +let TargetPrefix = "arm" in { + + // De-interleaving vector loads from N-element structures. + // Source operands are the address and alignment. + def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_arm_neon_vld2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_arm_neon_vld3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + // Vector load N-element structure to one lane. + // Source operands are: the address, the N input vectors (since only one + // lane is assigned), the lane number, and the alignment. + def int_arm_neon_vld2lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; + def int_arm_neon_vld3lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadArgMem]>; + def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_ptr_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadArgMem]>; + + // Interleaving vector stores from N-element structures. + // Source operands are: the address, the N vectors, and the alignment. + def int_arm_neon_vst1 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_arm_neon_vst2 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_arm_neon_vst3 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_arm_neon_vst4 : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + // Vector store N-element structure from one lane. + // Source operands are: the address, the N vectors, the lane number, and + // the alignment. + def int_arm_neon_vst2lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_arm_neon_vst3lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_arm_neon_vst4lane : Intrinsic<[], + [llvm_ptr_ty, llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, llvm_i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; +} diff --git a/final/include/llvm/IntrinsicsAlpha.td b/final/include/llvm/IntrinsicsAlpha.td new file mode 100644 index 00000000000..59865cf8a3e --- /dev/null +++ b/final/include/llvm/IntrinsicsAlpha.td @@ -0,0 +1,18 @@ +//===- IntrinsicsAlpha.td - Defines Alpha intrinsics -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the Alpha-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +let TargetPrefix = "alpha" in { // All intrinsics start with "llvm.alpha.". + def int_alpha_umulh : GCCBuiltin<"__builtin_alpha_umulh">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; +} diff --git a/final/include/llvm/IntrinsicsCellSPU.td b/final/include/llvm/IntrinsicsCellSPU.td new file mode 100644 index 00000000000..1e311bbecbc --- /dev/null +++ b/final/include/llvm/IntrinsicsCellSPU.td @@ -0,0 +1,242 @@ +//==- IntrinsicsCellSPU.td - Cell SDK intrinsics -*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// Department at The Aerospace Corporation and is distributed under the +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Cell SPU Instructions: +//===----------------------------------------------------------------------===// +// TODO Items (not urgent today, but would be nice, low priority) +// +// ANDBI, ORBI: SPU constructs a 4-byte constant for these instructions by +// concatenating the byte argument b as "bbbb". Could recognize this bit pattern +// in 16-bit and 32-bit constants and reduce instruction count. +//===----------------------------------------------------------------------===// + +// 7-bit integer type, used as an immediate: +def cell_i7_ty: LLVMType; +def cell_i8_ty: LLVMType; + +// Keep this here until it's actually supported: +def llvm_i128_ty : LLVMType; + +class v16i8_u7imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, cell_i7_ty], + [IntrNoMem]>; + +class v16i8_u8imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + +class v16i8_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v16i8_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v16i8_rr : + GCCBuiltin, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +class v8i16_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v8i16_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v8i16_rr : + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + +class v4i32_rr : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + +class v4i32_u7imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, cell_i7_ty], + [IntrNoMem]>; + +class v4i32_s10imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v4i32_u16imm : + GCCBuiltin, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i16_ty], + [IntrNoMem]>; + +class v4f32_rr : + GCCBuiltin, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +class v4f32_rrr : + GCCBuiltin, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +class v2f64_rr : + GCCBuiltin, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +// All Cell SPU intrinsics start with "llvm.spu.". +let TargetPrefix = "spu" in { + def int_spu_si_fsmbi : v8i16_u16imm<"fsmbi">; + def int_spu_si_ah : v8i16_rr<"ah">; + def int_spu_si_ahi : v8i16_s10imm<"ahi">; + def int_spu_si_a : v4i32_rr<"a">; + def int_spu_si_ai : v4i32_s10imm<"ai">; + def int_spu_si_sfh : v8i16_rr<"sfh">; + def int_spu_si_sfhi : v8i16_s10imm<"sfhi">; + def int_spu_si_sf : v4i32_rr<"sf">; + def int_spu_si_sfi : v4i32_s10imm<"sfi">; + def int_spu_si_addx : v4i32_rr<"addx">; + def int_spu_si_cg : v4i32_rr<"cg">; + def int_spu_si_cgx : v4i32_rr<"cgx">; + def int_spu_si_sfx : v4i32_rr<"sfx">; + def int_spu_si_bg : v4i32_rr<"bg">; + def int_spu_si_bgx : v4i32_rr<"bgx">; + def int_spu_si_mpy : // This is special: + GCCBuiltin<"__builtin_si_mpy">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyu : // This is special: + GCCBuiltin<"__builtin_si_mpyu">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyi : // This is special: + GCCBuiltin<"__builtin_si_mpyi">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyui : // This is special: + GCCBuiltin<"__builtin_si_mpyui">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_spu_si_mpya : // This is special: + GCCBuiltin<"__builtin_si_mpya">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyh : // This is special: + GCCBuiltin<"__builtin_si_mpyh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpys : // This is special: + GCCBuiltin<"__builtin_si_mpys">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhh : // This is special: + GCCBuiltin<"__builtin_si_mpyhh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhha : // This is special: + GCCBuiltin<"__builtin_si_mpyhha">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhhu : // This is special: + GCCBuiltin<"__builtin_si_mpyhhu">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_spu_si_mpyhhau : // This is special: + GCCBuiltin<"__builtin_si_mpyhhau">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_spu_si_shli: v4i32_u7imm<"shli">; + + def int_spu_si_shlqbi: + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_spu_si_shlqbii: v16i8_u7imm<"shlqbii">; + def int_spu_si_shlqby: + GCCBuiltin, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_spu_si_shlqbyi: v16i8_u7imm<"shlqbyi">; + + def int_spu_si_ceq: v4i32_rr<"ceq">; + def int_spu_si_ceqi: v4i32_s10imm<"ceqi">; + def int_spu_si_ceqb: v16i8_rr<"ceqb">; + def int_spu_si_ceqbi: v16i8_u8imm<"ceqbi">; + def int_spu_si_ceqh: v8i16_rr<"ceqh">; + def int_spu_si_ceqhi: v8i16_s10imm<"ceqhi">; + def int_spu_si_cgt: v4i32_rr<"cgt">; + def int_spu_si_cgti: v4i32_s10imm<"cgti">; + def int_spu_si_cgtb: v16i8_rr<"cgtb">; + def int_spu_si_cgtbi: v16i8_u8imm<"cgtbi">; + def int_spu_si_cgth: v8i16_rr<"cgth">; + def int_spu_si_cgthi: v8i16_s10imm<"cgthi">; + def int_spu_si_clgtb: v16i8_rr<"clgtb">; + def int_spu_si_clgtbi: v16i8_u8imm<"clgtbi">; + def int_spu_si_clgth: v8i16_rr<"clgth">; + def int_spu_si_clgthi: v8i16_s10imm<"clgthi">; + def int_spu_si_clgt: v4i32_rr<"clgt">; + def int_spu_si_clgti: v4i32_s10imm<"clgti">; + + def int_spu_si_and: v4i32_rr<"and">; + def int_spu_si_andbi: v16i8_u8imm<"andbi">; + def int_spu_si_andc: v4i32_rr<"andc">; + def int_spu_si_andhi: v8i16_s10imm<"andhi">; + def int_spu_si_andi: v4i32_s10imm<"andi">; + + def int_spu_si_or: v4i32_rr<"or">; + def int_spu_si_orbi: v16i8_u8imm<"orbi">; + def int_spu_si_orc: v4i32_rr<"orc">; + def int_spu_si_orhi: v8i16_s10imm<"orhi">; + def int_spu_si_ori: v4i32_s10imm<"ori">; + + def int_spu_si_xor: v4i32_rr<"xor">; + def int_spu_si_xorbi: v16i8_u8imm<"xorbi">; + def int_spu_si_xorhi: v8i16_s10imm<"xorhi">; + def int_spu_si_xori: v4i32_s10imm<"xori">; + + def int_spu_si_nor: v4i32_rr<"nor">; + def int_spu_si_nand: v4i32_rr<"nand">; + + def int_spu_si_fa: v4f32_rr<"fa">; + def int_spu_si_fs: v4f32_rr<"fs">; + def int_spu_si_fm: v4f32_rr<"fm">; + + def int_spu_si_fceq: v4f32_rr<"fceq">; + def int_spu_si_fcmeq: v4f32_rr<"fcmeq">; + def int_spu_si_fcgt: v4f32_rr<"fcgt">; + def int_spu_si_fcmgt: v4f32_rr<"fcmgt">; + + def int_spu_si_fma: v4f32_rrr<"fma">; + def int_spu_si_fnms: v4f32_rrr<"fnms">; + def int_spu_si_fms: v4f32_rrr<"fms">; + + def int_spu_si_dfa: v2f64_rr<"dfa">; + def int_spu_si_dfs: v2f64_rr<"dfs">; + def int_spu_si_dfm: v2f64_rr<"dfm">; + +//def int_spu_si_dfceq: v2f64_rr<"dfceq">; +//def int_spu_si_dfcmeq: v2f64_rr<"dfcmeq">; +//def int_spu_si_dfcgt: v2f64_rr<"dfcgt">; +//def int_spu_si_dfcmgt: v2f64_rr<"dfcmgt">; + + def int_spu_si_dfnma: v2f64_rr<"dfnma">; + def int_spu_si_dfma: v2f64_rr<"dfma">; + def int_spu_si_dfnms: v2f64_rr<"dfnms">; + def int_spu_si_dfms: v2f64_rr<"dfms">; +} diff --git a/final/include/llvm/IntrinsicsPTX.td b/final/include/llvm/IntrinsicsPTX.td new file mode 100644 index 00000000000..ec291e467ec --- /dev/null +++ b/final/include/llvm/IntrinsicsPTX.td @@ -0,0 +1,32 @@ +//===- IntrinsicsPTX.td - Defines PTX intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PTX-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "ptx" in { + multiclass PTXReadSpecialRegisterIntrinsic { + def _r64 : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; + def _v4i16 : Intrinsic<[llvm_v4i16_ty], [], [IntrNoMem]>; + } + + multiclass PTXReadSpecialSubRegisterIntrinsic { + def _x : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _y : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _z : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + def _w : Intrinsic<[llvm_i16_ty], [], [IntrNoMem]>; + } +} + +defm int_ptx_read_tid : PTXReadSpecialRegisterIntrinsic; +defm int_ptx_read_tid : PTXReadSpecialSubRegisterIntrinsic; + +let TargetPrefix = "ptx" in + def int_ptx_bar_sync : Intrinsic<[], [llvm_i32_ty], []>; diff --git a/final/include/llvm/IntrinsicsPowerPC.td b/final/include/llvm/IntrinsicsPowerPC.td new file mode 100644 index 00000000000..da85bfba863 --- /dev/null +++ b/final/include/llvm/IntrinsicsPowerPC.td @@ -0,0 +1,465 @@ +//===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PowerPC-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all PowerPC intrinsics. +// + +// Non-altivec intrinsics. +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. + def int_ppc_dcba : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbf : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbi : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; + + // sync instruction + def int_ppc_sync : Intrinsic<[], [], []>; +} + + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. + class PowerPC_Vec_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; +} + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Class Definitions. +// + +/// PowerPC_Vec_FF_Intrinsic - A PowerPC intrinsic that takes one v4f32 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FF_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FFF_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_BBB_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_HHH_Intrinsic - A PowerPC intrinsic that takes two v8i16 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_HHH_Intrinsic + : PowerPC_Vec_Intrinsic; + +/// PowerPC_Vec_WWW_Intrinsic - A PowerPC intrinsic that takes two v4i32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_WWW_Intrinsic + : PowerPC_Vec_Intrinsic; + + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Data Stream Control. + def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">, + Intrinsic<[], [llvm_i32_ty], []>; + def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">, + Intrinsic<[], [], []>; + def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + []>; + + // VSCR access. + def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">, + Intrinsic<[llvm_v8i16_ty], [], [IntrReadMem]>; + def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">, + Intrinsic<[], [llvm_v4i32_ty], []>; + + + // Loads. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_lvx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvxl : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvebx : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvehx : + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvewx : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + + // Stores. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_stvx : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvxl : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvebx : + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvehx : + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty], []>; + def int_ppc_altivec_stvewx : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + + // Comparisons setting a vector. + def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp : GCCBuiltin<"__builtin_altivec_vcmpeqfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp : GCCBuiltin<"__builtin_altivec_vcmpgefp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw : GCCBuiltin<"__builtin_altivec_vcmpgtsw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw : GCCBuiltin<"__builtin_altivec_vcmpgtuw">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh : GCCBuiltin<"__builtin_altivec_vcmpequh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh : GCCBuiltin<"__builtin_altivec_vcmpgtsh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh : GCCBuiltin<"__builtin_altivec_vcmpgtuh">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb : GCCBuiltin<"__builtin_altivec_vcmpequb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb : GCCBuiltin<"__builtin_altivec_vcmpgtsb">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub : GCCBuiltin<"__builtin_altivec_vcmpgtub">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + // Predicate Comparisons. The first operand specifies interpretation of CR6. + def int_ppc_altivec_vcmpbfp_p : GCCBuiltin<"__builtin_altivec_vcmpbfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp_p : GCCBuiltin<"__builtin_altivec_vcmpeqfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp_p : GCCBuiltin<"__builtin_altivec_vcmpgefp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw_p : GCCBuiltin<"__builtin_altivec_vcmpgtsw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw_p : GCCBuiltin<"__builtin_altivec_vcmpgtuw_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh_p : GCCBuiltin<"__builtin_altivec_vcmpequh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh_p : GCCBuiltin<"__builtin_altivec_vcmpgtsh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh_p : GCCBuiltin<"__builtin_altivec_vcmpgtuh_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb_p : GCCBuiltin<"__builtin_altivec_vcmpequb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb_p : GCCBuiltin<"__builtin_altivec_vcmpgtsb_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub_p : GCCBuiltin<"__builtin_altivec_vcmpgtub_p">, + Intrinsic<[llvm_i32_ty],[llvm_i32_ty,llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; +} + +// Vector average. +def int_ppc_altivec_vavgsb : PowerPC_Vec_BBB_Intrinsic<"vavgsb">; +def int_ppc_altivec_vavgsh : PowerPC_Vec_HHH_Intrinsic<"vavgsh">; +def int_ppc_altivec_vavgsw : PowerPC_Vec_WWW_Intrinsic<"vavgsw">; +def int_ppc_altivec_vavgub : PowerPC_Vec_BBB_Intrinsic<"vavgub">; +def int_ppc_altivec_vavguh : PowerPC_Vec_HHH_Intrinsic<"vavguh">; +def int_ppc_altivec_vavguw : PowerPC_Vec_WWW_Intrinsic<"vavguw">; + +// Vector maximum. +def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; +def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; +def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; +def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; +def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; +def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; + +// Vector minimum. +def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; +def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; +def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; +def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; +def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; +def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; + +// Saturating adds. +def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; +def int_ppc_altivec_vaddsbs : PowerPC_Vec_BBB_Intrinsic<"vaddsbs">; +def int_ppc_altivec_vadduhs : PowerPC_Vec_HHH_Intrinsic<"vadduhs">; +def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; +def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; +def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; +def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; + +// Saturating subs. +def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; +def int_ppc_altivec_vsubsbs : PowerPC_Vec_BBB_Intrinsic<"vsubsbs">; +def int_ppc_altivec_vsubuhs : PowerPC_Vec_HHH_Intrinsic<"vsubuhs">; +def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; +def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; +def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; +def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Saturating multiply-adds. + def int_ppc_altivec_vmhaddshs : GCCBuiltin<"__builtin_altivec_vmhaddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmhraddshs : GCCBuiltin<"__builtin_altivec_vmhraddshs">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + + def int_ppc_altivec_vmaddfp : GCCBuiltin<"__builtin_altivec_vmaddfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vnmsubfp : GCCBuiltin<"__builtin_altivec_vnmsubfp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + + // Vector Multiply Sum Intructions. + def int_ppc_altivec_vmsummbm : GCCBuiltin<"__builtin_altivec_vmsummbm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshm : GCCBuiltin<"__builtin_altivec_vmsumshm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshs : GCCBuiltin<"__builtin_altivec_vmsumshs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumubm : GCCBuiltin<"__builtin_altivec_vmsumubm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhm : GCCBuiltin<"__builtin_altivec_vmsumuhm">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhs : GCCBuiltin<"__builtin_altivec_vmsumuhs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + // Vector Multiply Intructions. + def int_ppc_altivec_vmulesb : GCCBuiltin<"__builtin_altivec_vmulesb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + // Vector Sum Intructions. + def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum2sws : GCCBuiltin<"__builtin_altivec_vsum2sws">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4sbs : GCCBuiltin<"__builtin_altivec_vsum4sbs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4shs : GCCBuiltin<"__builtin_altivec_vsum4shs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4ubs : GCCBuiltin<"__builtin_altivec_vsum4ubs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Other multiplies. + def int_ppc_altivec_vmladduhm : GCCBuiltin<"__builtin_altivec_vmladduhm">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + // Packs. + def int_ppc_altivec_vpkpx : GCCBuiltin<"__builtin_altivec_vpkpx">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshss : GCCBuiltin<"__builtin_altivec_vpkshss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshus : GCCBuiltin<"__builtin_altivec_vpkshus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, + Intrinsic<[llvm_v16i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + // vpkuhum is lowered to a shuffle. + def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + // vpkuwum is lowered to a shuffle. + def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Unpacks. + def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsb : GCCBuiltin<"__builtin_altivec_vupkhsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + + // FP <-> integer conversion. + def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfin : GCCBuiltin<"__builtin_altivec_vrfin">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfip : GCCBuiltin<"__builtin_altivec_vrfip">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; +def int_ppc_altivec_vslo : PowerPC_Vec_WWW_Intrinsic<"vslo">; + +def int_ppc_altivec_vslb : PowerPC_Vec_BBB_Intrinsic<"vslb">; +def int_ppc_altivec_vslh : PowerPC_Vec_HHH_Intrinsic<"vslh">; +def int_ppc_altivec_vslw : PowerPC_Vec_WWW_Intrinsic<"vslw">; + +// Right Shifts. +def int_ppc_altivec_vsr : PowerPC_Vec_WWW_Intrinsic<"vsr">; +def int_ppc_altivec_vsro : PowerPC_Vec_WWW_Intrinsic<"vsro">; + +def int_ppc_altivec_vsrb : PowerPC_Vec_BBB_Intrinsic<"vsrb">; +def int_ppc_altivec_vsrh : PowerPC_Vec_HHH_Intrinsic<"vsrh">; +def int_ppc_altivec_vsrw : PowerPC_Vec_WWW_Intrinsic<"vsrw">; +def int_ppc_altivec_vsrab : PowerPC_Vec_BBB_Intrinsic<"vsrab">; +def int_ppc_altivec_vsrah : PowerPC_Vec_HHH_Intrinsic<"vsrah">; +def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; + +// Rotates. +def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; +def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; +def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Miscellaneous. + def int_ppc_altivec_lvsl : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + def int_ppc_altivec_lvsr : + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrNoMem]>; + + def int_ppc_altivec_vperm : GCCBuiltin<"__builtin_altivec_vperm_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; +def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; +def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; +def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; diff --git a/final/include/llvm/IntrinsicsX86.td b/final/include/llvm/IntrinsicsX86.td new file mode 100644 index 00000000000..49462200f09 --- /dev/null +++ b/final/include/llvm/IntrinsicsX86.td @@ -0,0 +1,1584 @@ +//===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the X86-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Interrupt traps +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_int : Intrinsic<[], [llvm_i8_ty]>; +} + +//===----------------------------------------------------------------------===// +// SSE1 + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ps : GCCBuiltin<"__builtin_ia32_rcpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ss : GCCBuiltin<"__builtin_ia32_rsqrtss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ps : GCCBuiltin<"__builtin_ia32_rsqrtps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_min_ss : GCCBuiltin<"__builtin_ia32_minss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_min_ps : GCCBuiltin<"__builtin_ia32_minps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ss : GCCBuiltin<"__builtin_ia32_maxss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ps : GCCBuiltin<"__builtin_ia32_maxps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + +// Comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cmp_ss : + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_cmp_ps : + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comilt_ss : GCCBuiltin<"__builtin_ia32_comilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comile_ss : GCCBuiltin<"__builtin_ia32_comile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comigt_ss : GCCBuiltin<"__builtin_ia32_comigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comige_ss : GCCBuiltin<"__builtin_ia32_comige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comineq_ss : GCCBuiltin<"__builtin_ia32_comineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomieq_ss : GCCBuiltin<"__builtin_ia32_ucomieq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomilt_ss : GCCBuiltin<"__builtin_ia32_ucomilt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomile_ss : GCCBuiltin<"__builtin_ia32_ucomile">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomigt_ss : GCCBuiltin<"__builtin_ia32_ucomigt">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomige_ss : GCCBuiltin<"__builtin_ia32_ucomige">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomineq_ss : GCCBuiltin<"__builtin_ia32_ucomineq">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cvtss2si : GCCBuiltin<"__builtin_ia32_cvtss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtss2si64 : GCCBuiltin<"__builtin_ia32_cvtss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si : GCCBuiltin<"__builtin_ia32_cvttss2si">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi2ss : GCCBuiltin<"__builtin_ia32_cvtsi2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi642ss : GCCBuiltin<"__builtin_ia32_cvtsi642ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttps2pi: GCCBuiltin<"__builtin_ia32_cvttps2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2ps : GCCBuiltin<"__builtin_ia32_cvtpi2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f32_ty], []>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movnt_ps : GCCBuiltin<"__builtin_ia32_movntps">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f32_ty], []>; + def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">, + Intrinsic<[], [], []>; +} + +// Control register. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_stmxcsr : + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_sse_ldmxcsr : + Intrinsic<[], [llvm_ptr_ty], []>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movmsk_ps : GCCBuiltin<"__builtin_ia32_movmskps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE2 + +// FP arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_min_pd : GCCBuiltin<"__builtin_ia32_minpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_sd : GCCBuiltin<"__builtin_ia32_maxsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_pd : GCCBuiltin<"__builtin_ia32_maxpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// FP comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cmp_sd : + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_cmp_pd : + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comilt_sd : GCCBuiltin<"__builtin_ia32_comisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comile_sd : GCCBuiltin<"__builtin_ia32_comisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comigt_sd : GCCBuiltin<"__builtin_ia32_comisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comige_sd : GCCBuiltin<"__builtin_ia32_comisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comineq_sd : GCCBuiltin<"__builtin_ia32_comisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomieq_sd : GCCBuiltin<"__builtin_ia32_ucomisdeq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomilt_sd : GCCBuiltin<"__builtin_ia32_ucomisdlt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomile_sd : GCCBuiltin<"__builtin_ia32_ucomisdle">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomigt_sd : GCCBuiltin<"__builtin_ia32_ucomisdgt">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomige_sd : GCCBuiltin<"__builtin_ia32_ucomisdge">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomineq_sd : GCCBuiltin<"__builtin_ia32_ucomisdneq">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; + def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_psll_w : GCCBuiltin<"__builtin_ia32_psllw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psll_d : GCCBuiltin<"__builtin_ia32_pslld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_q : GCCBuiltin<"__builtin_ia32_psllq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_d : GCCBuiltin<"__builtin_ia32_psrld128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_psra_w : GCCBuiltin<"__builtin_ia32_psraw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psra_d : GCCBuiltin<"__builtin_ia32_psrad128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_sse2_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrai_d : GCCBuiltin<"__builtin_ia32_psradi128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_dq_bs : GCCBuiltin<"__builtin_ia32_pslldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi128_byteshift">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cvtdq2pd : GCCBuiltin<"__builtin_ia32_cvtdq2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2pd : GCCBuiltin<"__builtin_ia32_cvtps2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si64 : GCCBuiltin<"__builtin_ia32_cvtsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si : GCCBuiltin<"__builtin_ia32_cvttsd2si">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">, + Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi2sd : GCCBuiltin<"__builtin_ia32_cvtsi2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi642sd : GCCBuiltin<"__builtin_ia32_cvtsi642sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtss2sd : GCCBuiltin<"__builtin_ia32_cvtss2sd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse_cvtpi2pd : GCCBuiltin<"__builtin_ia32_cvtpi2pd">, + Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2f64_ty], []>; + def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v16i8_ty], []>; + def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4i32_ty], []>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_movnt_dq : GCCBuiltin<"__builtin_ia32_movntdq">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2i64_ty], []>; + def int_x86_sse2_movnt_pd : GCCBuiltin<"__builtin_ia32_movntpd">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2f64_ty], []>; + def int_x86_sse2_movnt_i : GCCBuiltin<"__builtin_ia32_movnti">, + Intrinsic<[], [llvm_ptr_ty, + llvm_i32_ty], []>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">, + Intrinsic<[], [llvm_v16i8_ty, + llvm_v16i8_ty, llvm_ptr_ty], []>; + def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">, + Intrinsic<[], [], []>; + def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, + Intrinsic<[], [], []>; +} + +//===----------------------------------------------------------------------===// +// SSE3 + +// Addition / subtraction ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_addsub_ps : GCCBuiltin<"__builtin_ia32_addsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_addsub_pd : GCCBuiltin<"__builtin_ia32_addsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Horizontal ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_hadd_ps : GCCBuiltin<"__builtin_ia32_haddps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hadd_pd : GCCBuiltin<"__builtin_ia32_haddpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_ps : GCCBuiltin<"__builtin_ia32_hsubps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_pd : GCCBuiltin<"__builtin_ia32_hsubpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Specialized unaligned load. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_ldu_dq : GCCBuiltin<"__builtin_ia32_lddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Thread synchronization ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">, + Intrinsic<[], [llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">, + Intrinsic<[], [llvm_i32_ty, + llvm_i32_ty], []>; +} + +//===----------------------------------------------------------------------===// +// SSSE3 + +// Horizontal arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_w_128 : GCCBuiltin<"__builtin_ia32_phsubw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_d : GCCBuiltin<"__builtin_ia32_phsubd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_d_128 : GCCBuiltin<"__builtin_ia32_phsubd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_ssse3_phsub_sw : GCCBuiltin<"__builtin_ia32_phsubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_phsub_sw_128 : GCCBuiltin<"__builtin_ia32_phsubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; +} + +// Packed multiply high with round and scale +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem, Commutative]>; +} + +// Shuffle ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pshuf_b : GCCBuiltin<"__builtin_ia32_pshufb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], + [IntrNoMem]>; +} + +// Sign ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_psign_b : GCCBuiltin<"__builtin_ia32_psignb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_b_128 : GCCBuiltin<"__builtin_ia32_psignb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_w : GCCBuiltin<"__builtin_ia32_psignw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_w_128 : GCCBuiltin<"__builtin_ia32_psignw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_psign_d : GCCBuiltin<"__builtin_ia32_psignd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_psign_d_128 : GCCBuiltin<"__builtin_ia32_psignd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Absolute value ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pabs_b : GCCBuiltin<"__builtin_ia32_pabsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_b_128 : GCCBuiltin<"__builtin_ia32_pabsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_w : GCCBuiltin<"__builtin_ia32_pabsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_w_128 : GCCBuiltin<"__builtin_ia32_pabsw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], [IntrNoMem]>; + + def int_x86_ssse3_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_ssse3_pabs_d_128 : GCCBuiltin<"__builtin_ia32_pabsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.1 + +// FP rounding ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_round_ss : GCCBuiltin<"__builtin_ia32_roundss">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_ps : GCCBuiltin<"__builtin_ia32_roundps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_sd : GCCBuiltin<"__builtin_ia32_roundsd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse41_round_pd : GCCBuiltin<"__builtin_ia32_roundpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Vector sign and zero extend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], + [IntrNoMem]>; + def int_x86_sse41_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector min element +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty], + [IntrNoMem]>; +} + +// Vector compare, min, max +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pcmpeqq : GCCBuiltin<"__builtin_ia32_pcmpeqq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse42_pcmpgtq : GCCBuiltin<"__builtin_ia32_pcmpgtq">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_sse41_pmaxsb : GCCBuiltin<"__builtin_ia32_pmaxsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxsd : GCCBuiltin<"__builtin_ia32_pmaxsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxud : GCCBuiltin<"__builtin_ia32_pmaxud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pmaxuw : GCCBuiltin<"__builtin_ia32_pmaxuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsb : GCCBuiltin<"__builtin_ia32_pminsb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminsd : GCCBuiltin<"__builtin_ia32_pminsd128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminud : GCCBuiltin<"__builtin_ia32_pminud128">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_pminuw : GCCBuiltin<"__builtin_ia32_pminuw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; +} + +// Advanced Encryption Standard (AES) Instructions +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_aesni_aesimc : GCCBuiltin<"__builtin_ia32_aesimc128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesenc : GCCBuiltin<"__builtin_ia32_aesenc128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesenclast : GCCBuiltin<"__builtin_ia32_aesenclast128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesdec : GCCBuiltin<"__builtin_ia32_aesdec128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aesdeclast : GCCBuiltin<"__builtin_ia32_aesdeclast128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_x86_aesni_aeskeygenassist : + GCCBuiltin<"__builtin_ia32_aeskeygenassist128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; +} + +// Vector pack +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +} + +// Vector multiply +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector extract +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pextrb : + Intrinsic<[llvm_i32_ty], [llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrd : + Intrinsic<[llvm_i32_ty], [llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_pextrq : + Intrinsic<[llvm_i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_extractps : GCCBuiltin<"__builtin_ia32_extractps128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse41_blendvps : GCCBuiltin<"__builtin_ia32_blendvps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; +} + +// Vector dot product +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; + def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Vector sum of absolute differences +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty], + [IntrNoMem, Commutative]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// Test instruction with bitwise comparison. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestc : GCCBuiltin<"__builtin_ia32_ptestc128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse41_ptestnzc : GCCBuiltin<"__builtin_ia32_ptestnzc128">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE4.2 + +// Miscellaneous +// CRC Instruction +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_crc32_8 : GCCBuiltin<"__builtin_ia32_crc32qi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_16 : GCCBuiltin<"__builtin_ia32_crc32hi">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_sse42_crc32_32 : GCCBuiltin<"__builtin_ia32_crc32si">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_sse42_crc64_8 : + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_crc64_64 : GCCBuiltin<"__builtin_ia32_crc32di">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; +} + +// String/text processing ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// AVX + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_addsub_pd_256 : GCCBuiltin<"__builtin_ia32_addsubpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_addsub_ps_256 : GCCBuiltin<"__builtin_ia32_addsubps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_rsqrt_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrtps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_rcp_ps_256 : GCCBuiltin<"__builtin_ia32_rcpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + + def int_x86_avx_round_pd_256 : GCCBuiltin<"__builtin_ia32_roundpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_round_ps_256 : GCCBuiltin<"__builtin_ia32_roundps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Horizontal ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_hadd_pd_256 : GCCBuiltin<"__builtin_ia32_haddpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_hsub_ps_256 : GCCBuiltin<"__builtin_ia32_hsubps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_hsub_pd_256 : GCCBuiltin<"__builtin_ia32_hsubpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_hadd_ps_256 : GCCBuiltin<"__builtin_ia32_haddps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector permutation +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vpermilvar_pd : GCCBuiltin<"__builtin_ia32_vpermilvarpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx_vpermilvar_ps : GCCBuiltin<"__builtin_ia32_vpermilvarps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + def int_x86_avx_vpermilvar_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermilvarpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_vpermilvar_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermilvarps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx_vperm2f128_pd_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vperm2f128_ps_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vperm2f128_si_256 : + GCCBuiltin<"__builtin_ia32_vperm2f128_si256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx_vpermil_pd : GCCBuiltin<"__builtin_ia32_vpermilpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vpermil_ps : GCCBuiltin<"__builtin_ia32_vpermilps">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx_vpermil_pd_256 : GCCBuiltin<"__builtin_ia32_vpermilpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vpermil_ps_256 : GCCBuiltin<"__builtin_ia32_vpermilps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; +} + +// Vector blend +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_blendv_ps_256 : GCCBuiltin<"__builtin_ia32_blendvps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector dot product +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; +} + +// Vector compare +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_cmp_pd_256 : GCCBuiltin<"__builtin_ia32_cmppd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_cmp_ps_256 : GCCBuiltin<"__builtin_ia32_cmpps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector extract and insert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vextractf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_pd256">, + Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vextractf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_ps256">, + Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vextractf128_si_256 : + GCCBuiltin<"__builtin_ia32_vextractf128_si256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx_vinsertf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vinsertf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx_vinsertf128_si_256 : + GCCBuiltin<"__builtin_ia32_vinsertf128_si256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; +} + +// Vector convert +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_cvtdq2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtdq2pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx_cvtdq2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtdq2ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_cvt_ps2_pd_256 : GCCBuiltin<"__builtin_ia32_cvtps2pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_cvtt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvttpd2dq256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvt_pd2dq_256 : GCCBuiltin<"__builtin_ia32_cvtpd2dq256">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_cvtt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvttps2dq256">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector bit test +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vtestz_pd : GCCBuiltin<"__builtin_ia32_vtestzpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_pd : GCCBuiltin<"__builtin_ia32_vtestcpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_pd : GCCBuiltin<"__builtin_ia32_vtestnzcpd">, + Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_ps : GCCBuiltin<"__builtin_ia32_vtestzps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_ps : GCCBuiltin<"__builtin_ia32_vtestcps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_ps : GCCBuiltin<"__builtin_ia32_vtestnzcps">, + Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_pd_256 : GCCBuiltin<"__builtin_ia32_vtestzpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestcpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_pd_256 : GCCBuiltin<"__builtin_ia32_vtestnzcpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty, + llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_vtestz_ps_256 : GCCBuiltin<"__builtin_ia32_vtestzps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestcps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_vtestnzc_ps_256 : GCCBuiltin<"__builtin_ia32_vtestnzcps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty, + llvm_v8f32_ty], [IntrNoMem]>; + def int_x86_avx_ptestz_256 : GCCBuiltin<"__builtin_ia32_ptestz256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_ptestc_256 : GCCBuiltin<"__builtin_ia32_ptestc256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx_ptestnzc_256 : GCCBuiltin<"__builtin_ia32_ptestnzc256">, + Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, + llvm_v4i64_ty], [IntrNoMem]>; +} + +// Vector extract sign mask +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_movmsk_pd_256 : GCCBuiltin<"__builtin_ia32_movmskpd256">, + Intrinsic<[llvm_i32_ty], [llvm_v4f64_ty], [IntrNoMem]>; + def int_x86_avx_movmsk_ps_256 : GCCBuiltin<"__builtin_ia32_movmskps256">, + Intrinsic<[llvm_i32_ty], [llvm_v8f32_ty], [IntrNoMem]>; +} + +// Vector zero +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vzeroall : GCCBuiltin<"__builtin_ia32_vzeroall">, + Intrinsic<[], [], []>; + def int_x86_avx_vzeroupper : GCCBuiltin<"__builtin_ia32_vzeroupper">, + Intrinsic<[], [], []>; +} + +// Vector load with broadcast +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_vbroadcastss : + GCCBuiltin<"__builtin_ia32_vbroadcastss">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_vbroadcast_sd_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastsd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_vbroadcastss_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastss256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_vbroadcastf128_pd_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastf128_pd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_vbroadcastf128_ps_256 : + GCCBuiltin<"__builtin_ia32_vbroadcastf128_ps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_loadu_pd_256 : GCCBuiltin<"__builtin_ia32_loadupd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_loadu_ps_256 : GCCBuiltin<"__builtin_ia32_loadups256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_loadu_dq_256 : GCCBuiltin<"__builtin_ia32_loaddqu256">, + Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx_ldu_dq_256 : GCCBuiltin<"__builtin_ia32_lddqu256">, + Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_storeu_pd_256 : GCCBuiltin<"__builtin_ia32_storeupd256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty], []>; + def int_x86_avx_storeu_ps_256 : GCCBuiltin<"__builtin_ia32_storeups256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty], []>; + def int_x86_avx_storeu_dq_256 : GCCBuiltin<"__builtin_ia32_storedqu256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty], []>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_movnt_dq_256 : GCCBuiltin<"__builtin_ia32_movntdq256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty], []>; + def int_x86_avx_movnt_pd_256 : GCCBuiltin<"__builtin_ia32_movntpd256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty], []>; + def int_x86_avx_movnt_ps_256 : GCCBuiltin<"__builtin_ia32_movntps256">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty], []>; +} + +// Conditional load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_maskload_pd : GCCBuiltin<"__builtin_ia32_maskloadpd">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty], [IntrReadMem]>; + def int_x86_avx_maskload_ps : GCCBuiltin<"__builtin_ia32_maskloadps">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty], [IntrReadMem]>; + def int_x86_avx_maskload_pd_256 : GCCBuiltin<"__builtin_ia32_maskloadpd256">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty], [IntrReadMem]>; + def int_x86_avx_maskload_ps_256 : GCCBuiltin<"__builtin_ia32_maskloadps256">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty], [IntrReadMem]>; +} + +// Conditional store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx_maskstore_pd : GCCBuiltin<"__builtin_ia32_maskstorepd">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v2f64_ty, llvm_v2f64_ty], []>; + def int_x86_avx_maskstore_ps : GCCBuiltin<"__builtin_ia32_maskstoreps">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f32_ty, llvm_v4f32_ty], []>; + def int_x86_avx_maskstore_pd_256 : + GCCBuiltin<"__builtin_ia32_maskstorepd256">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v4f64_ty, llvm_v4f64_ty], []>; + def int_x86_avx_maskstore_ps_256 : + GCCBuiltin<"__builtin_ia32_maskstoreps256">, + Intrinsic<[], [llvm_ptr_ty, + llvm_v8f32_ty, llvm_v8f32_ty], []>; +} + +//===----------------------------------------------------------------------===// +// MMX + +// Empty MMX state op. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">, + Intrinsic<[], [], []>; + def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">, + Intrinsic<[], [], []>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Addition + def int_x86_mmx_padd_b : GCCBuiltin<"__builtin_ia32_paddb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_w : GCCBuiltin<"__builtin_ia32_paddw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_d : GCCBuiltin<"__builtin_ia32_paddd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_padd_q : GCCBuiltin<"__builtin_ia32_paddq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Subtraction + def int_x86_mmx_psub_b : GCCBuiltin<"__builtin_ia32_psubb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_w : GCCBuiltin<"__builtin_ia32_psubw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_d : GCCBuiltin<"__builtin_ia32_psubd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_psub_q : GCCBuiltin<"__builtin_ia32_psubq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + // Multiplication + def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmull_w : GCCBuiltin<"__builtin_ia32_pmullw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Bitwise operations + def int_x86_mmx_pand : GCCBuiltin<"__builtin_ia32_pand">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_pandn : GCCBuiltin<"__builtin_ia32_pandn">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_por : GCCBuiltin<"__builtin_ia32_por">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_pxor : GCCBuiltin<"__builtin_ia32_pxor">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + + // Averages + def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Maximum + def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Minimum + def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; + + // Packed sum of absolute differences + def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem, Commutative]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Shift left logical + def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_pslli_w : GCCBuiltin<"__builtin_ia32_psllwi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrli_w : GCCBuiltin<"__builtin_ia32_psrlwi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrai_w : GCCBuiltin<"__builtin_ia32_psrawi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrai_d : GCCBuiltin<"__builtin_ia32_psradi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// Unpacking ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_punpckhbw : GCCBuiltin<"__builtin_ia32_punpckhbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckhwd : GCCBuiltin<"__builtin_ia32_punpckhwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckhdq : GCCBuiltin<"__builtin_ia32_punpckhdq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpcklbw : GCCBuiltin<"__builtin_ia32_punpcklbw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpcklwd : GCCBuiltin<"__builtin_ia32_punpcklwd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_mmx_punpckldq : GCCBuiltin<"__builtin_ia32_punpckldq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty], [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, + Intrinsic<[], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_ptr_ty], []>; + + def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + + def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, + Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; + + def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; +} diff --git a/final/include/llvm/IntrinsicsXCore.td b/final/include/llvm/IntrinsicsXCore.td new file mode 100644 index 00000000000..944120fc8c6 --- /dev/null +++ b/final/include/llvm/IntrinsicsXCore.td @@ -0,0 +1,55 @@ +//==- IntrinsicsXCore.td - XCore intrinsics -*- tablegen -*-==// +// +// Copyright (C) 2008 XMOS +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the XCore-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; + + // Resource instructions. + def int_xcore_getr : Intrinsic<[llvm_anyptr_ty],[llvm_i32_ty]>; + def int_xcore_freer : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_in : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],[NoCapture<0>]>; + def int_xcore_int : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_inct : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_out : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_chkct : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setd : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; + def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], + [NoCapture<0>]>; + def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], + [NoCapture<0>]>; + def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + + // Intrinsics for events. + def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>; + def int_xcore_clre : Intrinsic<[],[],[]>; +} diff --git a/final/include/llvm/LLVMContext.h b/final/include/llvm/LLVMContext.h new file mode 100644 index 00000000000..3502ff73c19 --- /dev/null +++ b/final/include/llvm/LLVMContext.h @@ -0,0 +1,107 @@ +//===-- llvm/LLVMContext.h - Class for managing "global" state --*- 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 LLVMContext, a container of "global" state in LLVM, such +// as the global type and constant uniquing tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LLVMCONTEXT_H +#define LLVM_LLVMCONTEXT_H + +namespace llvm { + +class LLVMContextImpl; +class StringRef; +class Instruction; +class Module; +class SMDiagnostic; +template class SmallVectorImpl; + +/// This is an important class for using LLVM in a threaded context. It +/// (opaquely) owns and manages the core "global" data of LLVM's core +/// infrastructure, including the type and constant uniquing tables. +/// LLVMContext itself provides no locking guarantees, so you should be careful +/// to have one context per thread. +class LLVMContext { +public: + LLVMContextImpl *const pImpl; + LLVMContext(); + ~LLVMContext(); + + // Pinned metadata names, which always have the same value. This is a + // compile-time performance optimization, not a correctness optimization. + enum { + MD_dbg = 0, // "dbg" + MD_tbaa = 1 // "tbaa" + }; + + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. + /// This ID is uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// getMDKindNames - Populate client supplied SmallVector with the name for + /// custom metadata IDs registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl &Result) const; + + + typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, + unsigned LocCookie); + + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked + /// when problems with inline asm are detected by the backend. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. + /// + /// LLVMContext doesn't take ownership or interpret either of these + /// pointers. + void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, + void *DiagContext = 0); + + /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by + /// setInlineAsmDiagnosticHandler. + InlineAsmDiagHandlerTy getInlineAsmDiagnosticHandler() const; + + /// getInlineAsmDiagnosticContext - Return the diagnostic context set by + /// setInlineAsmDiagnosticHandler. + void *getInlineAsmDiagnosticContext() const; + + + /// emitError - Emit an error message to the currently installed error handler + /// with optional location information. This function returns, so code should + /// be prepared to drop the erroneous construct on the floor and "not crash". + /// The generated code need not be correct. The error message will be + /// implicitly prefixed with "error: " and should not end with a ".". + void emitError(unsigned LocCookie, StringRef ErrorStr); + void emitError(const Instruction *I, StringRef ErrorStr); + void emitError(StringRef ErrorStr); + +private: + // DO NOT IMPLEMENT + LLVMContext(LLVMContext&); + void operator=(LLVMContext&); + + /// addModule - Register a module as being instantiated in this context. If + /// the context is deleted, the module will be deleted as well. + void addModule(Module*); + + /// removeModule - Unregister a module from this context. + void removeModule(Module*); + + // Module needs access to the add/removeModule methods. + friend class Module; +}; + +/// getGlobalContext - Returns a global context. This is for LLVM clients that +/// only care about operating on a single thread. +extern LLVMContext &getGlobalContext(); + +} + +#endif diff --git a/final/include/llvm/LinkAllPasses.h b/final/include/llvm/LinkAllPasses.h new file mode 100644 index 00000000000..1769ba1ef4e --- /dev/null +++ b/final/include/llvm/LinkAllPasses.h @@ -0,0 +1,165 @@ +//===- llvm/LinkAllPasses.h ------------ Reference All Passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all transformation and analysis passes for tools +// like opt and bugpoint that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLPASSES_H +#define LLVM_LINKALLPASSES_H + +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/DomPrinter.h" +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/RegionPrinter.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/Lint.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include + +namespace { + struct ForcePassLinking { + ForcePassLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createAAEvalPass(); + (void) llvm::createAggressiveDCEPass(); + (void) llvm::createAliasAnalysisCounterPass(); + (void) llvm::createAliasDebugger(); + (void) llvm::createArgumentPromotionPass(); + (void) llvm::createStructRetPromotionPass(); + (void) llvm::createBasicAliasAnalysisPass(); + (void) llvm::createLibCallAliasAnalysisPass(0); + (void) llvm::createScalarEvolutionAliasAnalysisPass(); + (void) llvm::createTypeBasedAliasAnalysisPass(); + (void) llvm::createBlockPlacementPass(); + (void) llvm::createBreakCriticalEdgesPass(); + (void) llvm::createCFGSimplificationPass(); + (void) llvm::createConstantMergePass(); + (void) llvm::createConstantPropagationPass(); + (void) llvm::createDeadArgEliminationPass(); + (void) llvm::createDeadCodeEliminationPass(); + (void) llvm::createDeadInstEliminationPass(); + (void) llvm::createDeadStoreEliminationPass(); + (void) llvm::createDeadTypeEliminationPass(); + (void) llvm::createDomOnlyPrinterPass(); + (void) llvm::createDomPrinterPass(); + (void) llvm::createDomOnlyViewerPass(); + (void) llvm::createDomViewerPass(); + (void) llvm::createEdgeProfilerPass(); + (void) llvm::createOptimalEdgeProfilerPass(); + (void) llvm::createPathProfilerPass(); + (void) llvm::createFunctionInliningPass(); + (void) llvm::createAlwaysInlinerPass(); + (void) llvm::createGlobalDCEPass(); + (void) llvm::createGlobalOptimizerPass(); + (void) llvm::createGlobalsModRefPass(); + (void) llvm::createIPConstantPropagationPass(); + (void) llvm::createIPSCCPPass(); + (void) llvm::createIndVarSimplifyPass(); + (void) llvm::createInstructionCombiningPass(); + (void) llvm::createInternalizePass(false); + (void) llvm::createLCSSAPass(); + (void) llvm::createLICMPass(); + (void) llvm::createLazyValueInfoPass(); + (void) llvm::createLoopDependenceAnalysisPass(); + (void) llvm::createLoopExtractorPass(); + (void) llvm::createLoopSimplifyPass(); + (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopUnrollPass(); + (void) llvm::createLoopUnswitchPass(); + (void) llvm::createLoopIdiomPass(); + (void) llvm::createLoopRotatePass(); + (void) llvm::createLowerInvokePass(); + (void) llvm::createLowerSetJmpPass(); + (void) llvm::createLowerSwitchPass(); + (void) llvm::createNoAAPass(); + (void) llvm::createNoProfileInfoPass(); + (void) llvm::createProfileEstimatorPass(); + (void) llvm::createProfileVerifierPass(); + (void) llvm::createPathProfileVerifierPass(); + (void) llvm::createProfileLoaderPass(); + (void) llvm::createPathProfileLoaderPass(); + (void) llvm::createPromoteMemoryToRegisterPass(); + (void) llvm::createDemoteRegisterToMemoryPass(); + (void) llvm::createPruneEHPass(); + (void) llvm::createPostDomOnlyPrinterPass(); + (void) llvm::createPostDomPrinterPass(); + (void) llvm::createPostDomOnlyViewerPass(); + (void) llvm::createPostDomViewerPass(); + (void) llvm::createReassociatePass(); + (void) llvm::createRegionInfoPass(); + (void) llvm::createRegionOnlyPrinterPass(); + (void) llvm::createRegionOnlyViewerPass(); + (void) llvm::createRegionPrinterPass(); + (void) llvm::createRegionViewerPass(); + (void) llvm::createSCCPPass(); + (void) llvm::createScalarReplAggregatesPass(); + (void) llvm::createSimplifyLibCallsPass(); + (void) llvm::createSingleLoopExtractorPass(); + (void) llvm::createStripSymbolsPass(); + (void) llvm::createStripNonDebugSymbolsPass(); + (void) llvm::createStripDeadDebugInfoPass(); + (void) llvm::createStripDeadPrototypesPass(); + (void) llvm::createTailCallEliminationPass(); + (void) llvm::createTailDuplicationPass(); + (void) llvm::createJumpThreadingPass(); + (void) llvm::createUnifyFunctionExitNodesPass(); + (void) llvm::createInstCountPass(); + (void) llvm::createCodeGenPreparePass(); + (void) llvm::createEarlyCSEPass(); + (void) llvm::createGVNPass(); + (void) llvm::createMemCpyOptPass(); + (void) llvm::createLoopDeletionPass(); + (void) llvm::createPostDomTree(); + (void) llvm::createPostDomFrontier(); + (void) llvm::createInstructionNamerPass(); + (void) llvm::createFunctionAttrsPass(); + (void) llvm::createMergeFunctionsPass(); + (void) llvm::createPrintModulePass(0); + (void) llvm::createPrintFunctionPass("", 0); + (void) llvm::createDbgInfoPrinterPass(); + (void) llvm::createModuleDebugInfoPrinterPass(); + (void) llvm::createPartialInliningPass(); + (void) llvm::createLintPass(); + (void) llvm::createSinkingPass(); + (void) llvm::createLowerAtomicPass(); + (void) llvm::createCorrelatedValuePropagationPass(); + (void) llvm::createMemDepPrinter(); + (void) llvm::createInstructionSimplifierPass(); + + (void)new llvm::IntervalPartition(); + (void)new llvm::FindUsedTypes(); + (void)new llvm::ScalarEvolution(); + ((llvm::Function*)0)->viewCFGOnly(); + llvm::RGPassManager RGM(0); + ((llvm::RegionPass*)0)->runOnRegion((llvm::Region*)0, RGM); + llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); + X.add((llvm::Value*)0, 0, 0); // for -print-alias-sets + } + } ForcePassLinking; // Force link by creating a global definition. +} + +#endif diff --git a/final/include/llvm/LinkAllVMCore.h b/final/include/llvm/LinkAllVMCore.h new file mode 100644 index 00000000000..83684c0fb65 --- /dev/null +++ b/final/include/llvm/LinkAllVMCore.h @@ -0,0 +1,53 @@ +//===- LinkAllVMCore.h - Reference All VMCore Code --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all the object modules of the VMCore library so +// that tools like llc, opt, and lli can ensure they are linked with all symbols +// from libVMCore.a It should only be used from a tool's main program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLVMCORE_H +#define LLVM_LINKALLVMCORE_H + +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/InlineAsm.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Memory.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TimeValue.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/MathExtras.h" +#include + +namespace { + struct ForceVMCoreLinking { + ForceVMCoreLinking() { + // We must reference VMCore in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + (void)new llvm::Module("", llvm::getGlobalContext()); + (void)new llvm::UnreachableInst(llvm::getGlobalContext()); + (void) llvm::createVerifierPass(); + } + } ForceVMCoreLinking; +} + +#endif diff --git a/final/include/llvm/Linker.h b/final/include/llvm/Linker.h new file mode 100644 index 00000000000..b402a6090e2 --- /dev/null +++ b/final/include/llvm/Linker.h @@ -0,0 +1,299 @@ +//===- llvm/Linker.h - Module Linker Interface ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface to the module/file/archive linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKER_H +#define LLVM_LINKER_H + +#include +#include +#include "llvm/ADT/StringRef.h" + +namespace llvm { + namespace sys { class Path; } + +class Module; +class LLVMContext; + +/// This class provides the core functionality of linking in LLVM. It retains a +/// Module object which is the composite of the modules and libraries linked +/// into it. The composite Module can be retrieved via the getModule() method. +/// In this case the Linker still retains ownership of the Module. If the +/// releaseModule() method is used, the ownership of the Module is transferred +/// to the caller and the Linker object is only suitable for destruction. +/// The Linker can link Modules from memory, bitcode files, or bitcode +/// archives. It retains a set of search paths in which to find any libraries +/// presented to it. By default, the linker will generate error and warning +/// messages to stderr but this capability can be turned off with the +/// QuietWarnings and QuietErrors flags. It can also be instructed to verbosely +/// print out the linking actions it is taking with the Verbose flag. +/// @brief The LLVM Linker. +class Linker { + + /// @name Types + /// @{ + public: + /// This type is used to pass the linkage items (libraries and files) to + /// the LinkItems function. It is composed of string/bool pairs. The string + /// provides the name of the file or library (as with the -l option). The + /// bool should be true for libraries and false for files, signifying + /// "isLibrary". + /// @brief A list of linkage items + typedef std::vector > ItemList; + + /// This enumeration is used to control various optional features of the + /// linker. + enum ControlFlags { + Verbose = 1, ///< Print to stderr what steps the linker is taking + QuietWarnings = 2, ///< Don't print warnings to stderr. + QuietErrors = 4 ///< Don't print errors to stderr. + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Construct the Linker with an empty module which will be given the + /// name \p progname. \p progname will also be used for error messages. + /// @brief Construct with empty module + Linker(StringRef progname, ///< name of tool running linker + StringRef modulename, ///< name of linker's end-result module + LLVMContext &C, ///< Context for global info + unsigned Flags = 0 ///< ControlFlags (one or more |'d together) + ); + + /// Construct the Linker with a previously defined module, \p aModule. Use + /// \p progname for the name of the program in error messages. + /// @brief Construct with existing module + Linker(StringRef progname, Module* aModule, unsigned Flags = 0); + + /// Destruct the Linker. + /// @brief Destructor + ~Linker(); + + /// @} + /// @name Accessors + /// @{ + public: + /// This method gets the composite module into which linking is being + /// done. The Composite module starts out empty and accumulates modules + /// linked into it via the various LinkIn* methods. This method does not + /// release the Module to the caller. The Linker retains ownership and will + /// destruct the Module when the Linker is destructed. + /// @see releaseModule + /// @brief Get the linked/composite module. + Module* getModule() const { return Composite; } + + /// This method releases the composite Module into which linking is being + /// done. Ownership of the composite Module is transferred to the caller who + /// must arrange for its destruct. After this method is called, the Linker + /// terminates the linking session for the returned Module. It will no + /// longer utilize the returned Module but instead resets itself for + /// subsequent linking as if the constructor had been called. The Linker's + /// LibPaths and flags to be reset, and memory will be released. + /// @brief Release the linked/composite module. + Module* releaseModule(); + + /// This method gets the list of libraries that form the path that the + /// Linker will search when it is presented with a library name. + /// @brief Get the Linkers library path + const std::vector& getLibPaths() const { return LibPaths; } + + /// This method returns an error string suitable for printing to the user. + /// The return value will be empty unless an error occurred in one of the + /// LinkIn* methods. In those cases, the LinkIn* methods will have returned + /// true, indicating an error occurred. At most one error is retained so + /// this function always returns the last error that occurred. Note that if + /// the Quiet control flag is not set, the error string will have already + /// been printed to stderr. + /// @brief Get the text of the last error that occurred. + const std::string &getLastError() const { return Error; } + + /// @} + /// @name Mutators + /// @{ + public: + /// Add a path to the list of paths that the Linker will search. The Linker + /// accumulates the set of libraries added + /// library paths for the target platform. The standard libraries will + /// always be searched last. The added libraries will be searched in the + /// order added. + /// @brief Add a path. + void addPath(const sys::Path& path); + + /// Add a set of paths to the list of paths that the linker will search. The + /// Linker accumulates the set of libraries added. The \p paths will be + /// added to the end of the Linker's list. Order will be retained. + /// @brief Add a set of paths. + void addPaths(const std::vector& paths); + + /// This method augments the Linker's list of library paths with the system + /// paths of the host operating system, include LLVM_LIB_SEARCH_PATH. + /// @brief Add the system paths. + void addSystemPaths(); + + /// Control optional linker behavior by setting a group of flags. The flags + /// are defined in the ControlFlags enumeration. + /// @see ControlFlags + /// @brief Set control flags. + void setFlags(unsigned flags) { Flags = flags; } + + /// This method is the main interface to the linker. It can be used to + /// link a set of linkage items into a module. A linkage item is either a + /// file name with fully qualified path, or a library for which the Linker's + /// LibraryPath will be utilized to locate the library. The bool value in + /// the LinkItemKind should be set to true for libraries. This function + /// allows linking to preserve the order of specification associated with + /// the command line, or for other purposes. Each item will be linked in + /// turn as it occurs in \p Items. + /// @returns true if an error occurred, false otherwise + /// @see LinkItemKind + /// @see getLastError + bool LinkInItems ( + const ItemList& Items, ///< Set of libraries/files to link in + ItemList& NativeItems ///< Output list of native files/libs + ); + + /// This function links the bitcode \p Files into the composite module. + /// Note that this does not do any linking of unresolved symbols. The \p + /// Files are all completely linked into \p HeadModule regardless of + /// unresolved symbols. This function just loads each bitcode file and + /// calls LinkInModule on them. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in multiple files. + bool LinkInFiles ( + const std::vector & Files ///< Files to link in + ); + + /// This function links a single bitcode file, \p File, into the composite + /// module. Note that this does not attempt to resolve symbols. This method + /// just loads the bitcode file and calls LinkInModule on it. If an error + /// occurs, the Linker's error string is set. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in a single file. + bool LinkInFile( + const sys::Path& File, ///< File to link in. + bool &is_native ///< Indicates if the file is native object file + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in libraries, based on the unresolved symbols in the composite + /// module. Each item in \p Libraries should be the base name of a library, + /// as if given with the -l option of a linker tool. The Linker's LibPaths + /// are searched for the \p Libraries and any found will be linked in with + /// LinkInArchive. If an error occurs, the Linker's error string is set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link libraries into the module + bool LinkInLibraries ( + const std::vector & Libraries ///< Libraries to link in + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in one library, based on the unresolved symbols in the composite + /// module.The \p Library should be the base name of a library, as if given + /// with the -l option of a linker tool. The Linker's LibPaths are searched + /// for the \p Library and if found, it will be linked in with via the + /// LinkInArchive method. If an error occurs, the Linker's error string is + /// set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link one library into the module + bool LinkInLibrary ( + StringRef Library, ///< The library to link in + bool& is_native ///< Indicates if lib a native library + ); + + /// This function links one bitcode archive, \p Filename, into the module. + /// The archive is searched to resolve outstanding symbols. Any modules in + /// the archive that resolve outstanding symbols will be linked in. The + /// library is searched repeatedly until no more modules that resolve + /// symbols can be found. If an error occurs, the error string is set. + /// To speed up this function, ensure the archive has been processed + /// llvm-ranlib or the S option was given to llvm-ar when the archive was + /// created. These tools add a symbol table to the archive which makes the + /// search for undefined symbols much faster. + /// @see getLastError + /// @returns true if an error occurs, otherwise false. + /// @brief Link in one archive. + bool LinkInArchive( + const sys::Path& Filename, ///< Filename of the archive to link + bool& is_native ///< Indicates if archive is a native archive + ); + + /// This method links the \p Src module into the Linker's Composite module + /// by calling LinkModules. All the other LinkIn* methods eventually + /// result in calling this method to link a Module into the Linker's + /// composite. + /// @see LinkModules + /// @returns True if an error occurs, false otherwise. + /// @brief Link in a module. + bool LinkInModule( + Module* Src, ///< Module linked into \p Dest + std::string* ErrorMsg = 0 /// Error/diagnostic string + ) { + return LinkModules(Composite, Src, ErrorMsg ); + } + + /// This is the heart of the linker. This method will take unconditional + /// control of the \p Src module and link it into the \p Dest module. The + /// \p Src module will be destructed or subsumed by this method. In either + /// case it is not usable by the caller after this method is invoked. Only + /// the \p Dest module will remain. The \p Src module is linked into the + /// Linker's composite module such that types, global variables, functions, + /// and etc. are matched and resolved. If an error occurs, this function + /// returns true and ErrorMsg is set to a descriptive message about the + /// error. + /// @returns True if an error occurs, false otherwise. + /// @brief Generically link two modules together. + static bool LinkModules(Module* Dest, Module* Src, std::string* ErrorMsg); + + /// This function looks through the Linker's LibPaths to find a library with + /// the name \p Filename. If the library cannot be found, the returned path + /// will be empty (i.e. sys::Path::isEmpty() will return true). + /// @returns A sys::Path to the found library + /// @brief Find a library from its short name. + sys::Path FindLib(StringRef Filename); + + /// @} + /// @name Implementation + /// @{ + private: + /// Read in and parse the bitcode file named by FN and return the + /// Module it contains (wrapped in an auto_ptr), or 0 if an error occurs. + std::auto_ptr LoadObject(const sys::Path& FN); + + bool warning(StringRef message); + bool error(StringRef message); + void verbose(StringRef message); + + /// @} + /// @name Data + /// @{ + private: + LLVMContext& Context; ///< The context for global information + Module* Composite; ///< The composite module linked together + std::vector LibPaths; ///< The library search paths + unsigned Flags; ///< Flags to control optional behavior. + std::string Error; ///< Text of error that occurred. + std::string ProgramName; ///< Name of the program being linked + /// @} + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/EDInstInfo.h b/final/include/llvm/MC/EDInstInfo.h new file mode 100644 index 00000000000..83d9e780feb --- /dev/null +++ b/final/include/llvm/MC/EDInstInfo.h @@ -0,0 +1,29 @@ +//===-- llvm/MC/EDInstInfo.h - EDis instruction info ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef EDINSTINFO_H +#define EDINSTINFO_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +#define EDIS_MAX_OPERANDS 13 +#define EDIS_MAX_SYNTAXES 2 + +struct EDInstInfo { + uint8_t instructionType; + uint8_t numOperands; + uint8_t operandTypes[EDIS_MAX_OPERANDS]; + uint8_t operandFlags[EDIS_MAX_OPERANDS]; + const char operandOrders[EDIS_MAX_SYNTAXES][EDIS_MAX_OPERANDS]; +}; + +} // namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCAsmInfo.h b/final/include/llvm/MC/MCAsmInfo.h new file mode 100644 index 00000000000..7e24a3d1d3b --- /dev/null +++ b/final/include/llvm/MC/MCAsmInfo.h @@ -0,0 +1,479 @@ +//===-- llvm/MC/MCAsmInfo.h - Asm 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 contains a class to be used as the basis for target specific +// asm writers. This class primarily takes care of global printing constants, +// which are used in very similar ways across all targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ASM_INFO_H +#define LLVM_TARGET_ASM_INFO_H + +#include "llvm/MC/MCDirectives.h" +#include + +namespace llvm { + class MCSection; + class MCContext; + + /// MCAsmInfo - This class is intended to be used as a base class for asm + /// properties and features specific to the target. + namespace ExceptionHandling { + enum ExceptionsType { None, DwarfTable, DwarfCFI, SjLj, ARM }; + } + + class MCAsmInfo { + protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// HasSubsectionsViaSymbols - True if this target has the MachO + /// .subsections_via_symbols directive. + bool HasSubsectionsViaSymbols; // Default is false. + + /// HasMachoZeroFillDirective - True if this is a MachO target that supports + /// the macho-specific .zerofill directive for emitting BSS Symbols. + bool HasMachoZeroFillDirective; // Default is false. + + /// HasMachoTBSSDirective - True if this is a MachO target that supports + /// the macho-specific .tbss directive for emitting thread local BSS Symbols + bool HasMachoTBSSDirective; // Default is false. + + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should + /// emit a ".reference .constructors_used" or ".reference .destructors_used" + /// directive after the a static ctor/dtor list. This directive is only + /// emitted in Static relocation model. + bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. + + /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and + /// requires that the debug_line section be of a minimum size. In practice + /// such a linker requires a non empty line sequence if a file is present. + bool LinkerRequiresNonEmptyDwarfLines; // Default to false. + + /// MaxInstLength - This is the maximum possible length of an instruction, + /// which is needed to compute the size of an inline asm. + unsigned MaxInstLength; // Defaults to 4. + + /// PCSymbol - The symbol used to represent the current PC. Used in PC + /// relative expressions. + const char *PCSymbol; // Defaults to "$". + + /// SeparatorChar - This character, if specified, is used to separate + /// instructions from each other when on the same line. This is used to + /// measure inline asm instructions. + char SeparatorChar; // Defaults to ';' + + /// CommentColumn - This indicates the comment num (zero-based) at + /// which asm comments should be printed. + unsigned CommentColumn; // Defaults to 40 + + /// CommentString - This indicates the comment character used by the + /// assembler. + const char *CommentString; // Defaults to "#" + + /// LabelSuffix - This is appended to emitted labels. + const char *LabelSuffix; // Defaults to ":" + + /// GlobalPrefix - If this is set to a non-empty string, it is prepended + /// onto all global symbols. This is often used for "_" or ".". + const char *GlobalPrefix; // Defaults to "" + + /// PrivateGlobalPrefix - This prefix is used for globals like constant + /// pool entries that are completely private to the .s file and should not + /// have names in the .o file. This is often "." or "L". + const char *PrivateGlobalPrefix; // Defaults to "." + + /// LinkerPrivateGlobalPrefix - This prefix is used for symbols that should + /// be passed through the assembler but be removed by the linker. This + /// is "l" on Darwin, currently used for some ObjC metadata. + const char *LinkerPrivateGlobalPrefix; // Defaults to "" + + /// InlineAsmStart/End - If these are nonempty, they contain a directive to + /// emit before and after an inline assembly statement. + const char *InlineAsmStart; // Defaults to "#APP\n" + const char *InlineAsmEnd; // Defaults to "#NO_APP\n" + + /// AssemblerDialect - Which dialect of an assembler variant to use. + unsigned AssemblerDialect; // Defaults to 0 + + /// AllowQuotesInName - This is true if the assembler allows for complex + /// symbol names to be surrounded in quotes. This defaults to false. + bool AllowQuotesInName; + + /// AllowNameToStartWithDigit - This is true if the assembler allows symbol + /// names to start with a digit (e.g., "0x0021"). This defaults to false. + bool AllowNameToStartWithDigit; + + /// AllowPeriodsInName - This is true if the assembler allows periods in + /// symbol names. This defaults to true. + bool AllowPeriodsInName; + + //===--- Data Emission Directives -------------------------------------===// + + /// ZeroDirective - this should be set to the directive used to get some + /// number of zero bytes emitted to the current section. Common cases are + /// "\t.zero\t" and "\t.space\t". If this is set to null, the + /// Data*bitsDirective's will be used to emit zero bytes. + const char *ZeroDirective; // Defaults to "\t.zero\t" + + /// AsciiDirective - This directive allows emission of an ascii string with + /// the standard C escape characters embedded into it. + const char *AsciiDirective; // Defaults to "\t.ascii\t" + + /// AscizDirective - If not null, this allows for special handling of + /// zero terminated strings on this target. This is commonly supported as + /// ".asciz". If a target doesn't support this, it can be set to null. + const char *AscizDirective; // Defaults to "\t.asciz\t" + + /// DataDirectives - These directives are used to output some unit of + /// integer data to the current section. If a data directive is set to + /// null, smaller data directives will be used to emit the large sizes. + const char *Data8bitsDirective; // Defaults to "\t.byte\t" + const char *Data16bitsDirective; // Defaults to "\t.short\t" + const char *Data32bitsDirective; // Defaults to "\t.long\t" + const char *Data64bitsDirective; // Defaults to "\t.quad\t" + + /// GPRel32Directive - if non-null, a directive that is used to emit a word + /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword + /// on Mips or .gprel32 on Alpha. + const char *GPRel32Directive; // Defaults to NULL. + + /// getDataASDirective - Return the directive that should be used to emit + /// data of the specified size to the specified numeric address space. + virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { + assert(AS != 0 && "Don't know the directives for default addr space"); + return 0; + } + + /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun + /// Style" syntax for section switching ("#alloc,#write" etc) instead of the + /// normal ELF syntax (,"a,w") in .section directives. + bool SunStyleELFSectionSwitchSyntax; // Defaults to false. + + /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF + /// '.section' directive before the '.bss' one. It's used for PPC/Linux + /// which doesn't support the '.bss' directive only. + bool UsesELFSectionDirectiveForBSS; // Defaults to false. + + /// HasMicrosoftFastStdCallMangling - True if this target uses microsoft + /// style mangling for functions with X86_StdCall/X86_FastCall calling + /// convention. + bool HasMicrosoftFastStdCallMangling; // Defaults to false. + + //===--- Alignment Information ----------------------------------------===// + + /// AlignDirective - The directive used to emit round up to an alignment + /// boundary. + /// + const char *AlignDirective; // Defaults to "\t.align\t" + + /// AlignmentIsInBytes - If this is true (the default) then the asmprinter + /// emits ".align N" directives, where N is the number of bytes to align to. + /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte + /// boundary. + bool AlignmentIsInBytes; // Defaults to true + + /// TextAlignFillValue - If non-zero, this is used to fill the executable + /// space created as the result of a alignment directive. + unsigned TextAlignFillValue; // Defaults to 0 + + //===--- Global Variable Emission Directives --------------------------===// + + /// GlobalDirective - This is the directive used to declare a global entity. + /// + const char *GlobalDirective; // Defaults to NULL. + + /// ExternDirective - This is the directive used to declare external + /// globals. + /// + const char *ExternDirective; // Defaults to NULL. + + /// HasSetDirective - True if the assembler supports the .set directive. + bool HasSetDirective; // Defaults to true. + + /// HasAggressiveSymbolFolding - False if the assembler requires that we use + /// Lc = a - b + /// .long Lc + /// instead of + /// .long a - b + bool HasAggressiveSymbolFolding; // Defaults to true. + + /// HasLCOMMDirective - This is true if the target supports the .lcomm + /// directive. + bool HasLCOMMDirective; // Defaults to false. + + /// COMMDirectiveAlignmentIsInBytes - True is COMMDirective's optional + /// alignment is to be specified in bytes instead of log2(n). + bool COMMDirectiveAlignmentIsInBytes; // Defaults to true; + + /// HasDotTypeDotSizeDirective - True if the target has .type and .size + /// directives, this is true for most ELF targets. + bool HasDotTypeDotSizeDirective; // Defaults to true. + + /// HasSingleParameterDotFile - True if the target has a single parameter + /// .file directive, this is true for ELF targets. + bool HasSingleParameterDotFile; // Defaults to true. + + /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip + /// directive. + bool HasNoDeadStrip; // Defaults to false. + + /// HasSymbolResolver - True if this target supports the MachO + /// .symbol_resolver directive. + bool HasSymbolResolver; // Defaults to false. + + /// WeakRefDirective - This directive, if non-null, is used to declare a + /// global as being a weak undefined symbol. + const char *WeakRefDirective; // Defaults to NULL. + + /// WeakDefDirective - This directive, if non-null, is used to declare a + /// global as being a weak defined symbol. + const char *WeakDefDirective; // Defaults to NULL. + + /// LinkOnceDirective - This directive, if non-null is used to declare a + /// global as being a weak defined symbol. This is used on cygwin/mingw. + const char *LinkOnceDirective; // Defaults to NULL. + + /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to + /// declare a symbol as having hidden visibility. + MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. + + /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid, + /// is used to declare an undefined symbol as having hidden visibility. + MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden. + + + /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used + /// to declare a symbol as having protected visibility. + MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// HasLEB128 - True if target asm supports leb128 directives. + bool HasLEB128; // Defaults to false. + + /// SupportsDebugInformation - True if target supports emission of debugging + /// information. + bool SupportsDebugInformation; // Defaults to false. + + /// SupportsExceptionHandling - True if target supports exception handling. + ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None + + /// RequiresFrameSection - true if the Dwarf2 output needs a frame section + bool DwarfRequiresFrameSection; // Defaults to true. + + /// DwarfUsesInlineInfoSection - True if DwarfDebugInlineSection is used to + /// encode inline subroutine information. + bool DwarfUsesInlineInfoSection; // Defaults to false. + + /// DwarfSectionOffsetDirective - Special section offset directive. + const char* DwarfSectionOffsetDirective; // Defaults to NULL + + /// DwarfUsesAbsoluteLabelForStmtList - True if DW_AT_stmt_list needs + /// absolute label instead of offset. + bool DwarfUsesAbsoluteLabelForStmtList; // Defaults to true; + + // DwarfUsesLabelOffsetDifference - True if Dwarf2 output can + // use EmitLabelOffsetDifference. + bool DwarfUsesLabelOffsetForRanges; + + //===--- CBE Asm Translation Table -----------------------------------===// + + const char *const *AsmTransCBE; // Defaults to empty + + public: + explicit MCAsmInfo(); + virtual ~MCAsmInfo(); + + // FIXME: move these methods to DwarfPrinter when the JIT stops using them. + static unsigned getSLEB128Size(int Value); + static unsigned getULEB128Size(unsigned Value); + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } + + // Data directive accessors. + // + const char *getData8bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + } + const char *getData16bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + } + const char *getData32bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + } + const char *getData64bitsDirective(unsigned AS = 0) const { + return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + } + const char *getGPRel32Directive() const { return GPRel32Directive; } + + /// getNonexecutableStackSection - Targets can implement this method to + /// specify a section to switch to if the translation unit doesn't have any + /// trampolines that require an executable stack. + virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const{ + return 0; + } + + bool usesSunStyleELFSectionSwitchSyntax() const { + return SunStyleELFSectionSwitchSyntax; + } + + bool usesELFSectionDirectiveForBSS() const { + return UsesELFSectionDirectiveForBSS; + } + + bool hasMicrosoftFastStdCallMangling() const { + return HasMicrosoftFastStdCallMangling; + } + + // Accessors. + // + bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + bool hasStaticCtorDtorReferenceInStaticMode() const { + return HasStaticCtorDtorReferenceInStaticMode; + } + bool getLinkerRequiresNonEmptyDwarfLines() const { + return LinkerRequiresNonEmptyDwarfLines; + } + unsigned getMaxInstLength() const { + return MaxInstLength; + } + const char *getPCSymbol() const { + return PCSymbol; + } + char getSeparatorChar() const { + return SeparatorChar; + } + unsigned getCommentColumn() const { + return CommentColumn; + } + const char *getCommentString() const { + return CommentString; + } + const char *getLabelSuffix() const { + return LabelSuffix; + } + const char *getGlobalPrefix() const { + return GlobalPrefix; + } + const char *getPrivateGlobalPrefix() const { + return PrivateGlobalPrefix; + } + const char *getLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix; + } + const char *getInlineAsmStart() const { + return InlineAsmStart; + } + const char *getInlineAsmEnd() const { + return InlineAsmEnd; + } + unsigned getAssemblerDialect() const { + return AssemblerDialect; + } + bool doesAllowQuotesInName() const { + return AllowQuotesInName; + } + bool doesAllowNameToStartWithDigit() const { + return AllowNameToStartWithDigit; + } + bool doesAllowPeriodsInName() const { + return AllowPeriodsInName; + } + const char *getZeroDirective() const { + return ZeroDirective; + } + const char *getAsciiDirective() const { + return AsciiDirective; + } + const char *getAscizDirective() const { + return AscizDirective; + } + const char *getAlignDirective() const { + return AlignDirective; + } + bool getAlignmentIsInBytes() const { + return AlignmentIsInBytes; + } + unsigned getTextAlignFillValue() const { + return TextAlignFillValue; + } + const char *getGlobalDirective() const { + return GlobalDirective; + } + const char *getExternDirective() const { + return ExternDirective; + } + bool hasSetDirective() const { return HasSetDirective; } + bool hasAggressiveSymbolFolding() const { + return HasAggressiveSymbolFolding; + } + bool hasLCOMMDirective() const { return HasLCOMMDirective; } + bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} + bool getCOMMDirectiveAlignmentIsInBytes() const { + return COMMDirectiveAlignmentIsInBytes; + } + bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasNoDeadStrip() const { return HasNoDeadStrip; } + bool hasSymbolResolver() const { return HasSymbolResolver; } + const char *getWeakRefDirective() const { return WeakRefDirective; } + const char *getWeakDefDirective() const { return WeakDefDirective; } + const char *getLinkOnceDirective() const { return LinkOnceDirective; } + + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } + MCSymbolAttr getProtectedVisibilityAttr() const { + return ProtectedVisibilityAttr; + } + bool hasLEB128() const { + return HasLEB128; + } + bool doesSupportDebugInformation() const { + return SupportsDebugInformation; + } + bool doesSupportExceptionHandling() const { + return ExceptionsType != ExceptionHandling::None; + } + ExceptionHandling::ExceptionsType getExceptionHandlingType() const { + return ExceptionsType; + } + bool isExceptionHandlingDwarf() const { + return + (ExceptionsType == ExceptionHandling::DwarfTable || + ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM); + } + + bool doesDwarfRequireFrameSection() const { + return DwarfRequiresFrameSection; + } + bool doesDwarfUsesInlineInfoSection() const { + return DwarfUsesInlineInfoSection; + } + const char *getDwarfSectionOffsetDirective() const { + return DwarfSectionOffsetDirective; + } + bool doesDwarfUsesAbsoluteLabelForStmtList() const { + return DwarfUsesAbsoluteLabelForStmtList; + } + bool doesDwarfUsesLabelOffsetForRanges() const { + return DwarfUsesLabelOffsetForRanges; + } + const char *const *getAsmCBE() const { + return AsmTransCBE; + } + }; +} + +#endif diff --git a/final/include/llvm/MC/MCAsmInfoCOFF.h b/final/include/llvm/MC/MCAsmInfoCOFF.h new file mode 100644 index 00000000000..a3ee1593c3a --- /dev/null +++ b/final/include/llvm/MC/MCAsmInfoCOFF.h @@ -0,0 +1,24 @@ +//===-- MCAsmInfoCOFF.h - COFF asm properties -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COFF_TARGET_ASM_INFO_H +#define LLVM_COFF_TARGET_ASM_INFO_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class MCAsmInfoCOFF : public MCAsmInfo { + protected: + explicit MCAsmInfoCOFF(); + + }; +} + + +#endif // LLVM_COFF_TARGET_ASM_INFO_H diff --git a/final/include/llvm/MC/MCAsmInfoDarwin.h b/final/include/llvm/MC/MCAsmInfoDarwin.h new file mode 100644 index 00000000000..c85aa3da957 --- /dev/null +++ b/final/include/llvm/MC/MCAsmInfoDarwin.h @@ -0,0 +1,32 @@ +//===---- MCAsmInfoDarwin.h - Darwin asm properties -------------*- 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 target asm properties related what form asm statements +// should take in general on Darwin-based targets +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DARWIN_TARGET_ASM_INFO_H +#define LLVM_DARWIN_TARGET_ASM_INFO_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class GlobalValue; + class GlobalVariable; + class Type; + class Mangler; + + struct MCAsmInfoDarwin : public MCAsmInfo { + explicit MCAsmInfoDarwin(); + }; +} + + +#endif // LLVM_DARWIN_TARGET_ASM_INFO_H diff --git a/final/include/llvm/MC/MCAsmLayout.h b/final/include/llvm/MC/MCAsmLayout.h new file mode 100644 index 00000000000..01cb0006b36 --- /dev/null +++ b/final/include/llvm/MC/MCAsmLayout.h @@ -0,0 +1,104 @@ +//===- MCAsmLayout.h - Assembly Layout Object -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMLAYOUT_H +#define LLVM_MC_MCASMLAYOUT_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { +class MCAssembler; +class MCFragment; +class MCSectionData; +class MCSymbolData; + +/// Encapsulates the layout of an assembly file at a particular point in time. +/// +/// Assembly may requiring compute multiple layouts for a particular assembly +/// file as part of the relaxation process. This class encapsulates the layout +/// at a single point in time in such a way that it is always possible to +/// efficiently compute the exact addresses of any symbol in the assembly file, +/// even during the relaxation process. +class MCAsmLayout { +public: + typedef llvm::SmallVectorImpl::const_iterator const_iterator; + typedef llvm::SmallVectorImpl::iterator iterator; + +private: + MCAssembler &Assembler; + + /// List of sections in layout order. + llvm::SmallVector SectionOrder; + + /// The last fragment which was layed out, or 0 if nothing has been layed + /// out. Fragments are always layed out in order, so all fragments with a + /// lower ordinal will be up to date. + mutable DenseMap LastValidFragment; + + /// \brief Make sure that the layout for the given fragment is valid, lazily + /// computing it if necessary. + void EnsureValid(const MCFragment *F) const; + + bool isFragmentUpToDate(const MCFragment *F) const; + +public: + MCAsmLayout(MCAssembler &_Assembler); + + /// Get the assembler object this is a layout for. + MCAssembler &getAssembler() const { return Assembler; } + + /// \brief Invalidate all following fragments because a fragment has been + /// resized. The fragments size should have already been updated. + void Invalidate(MCFragment *F); + + /// \brief Perform layout for a single fragment, assuming that the previous + /// fragment has already been layed out correctly, and the parent section has + /// been initialized. + void LayoutFragment(MCFragment *Fragment); + + /// @name Section Access (in layout order) + /// @{ + + llvm::SmallVectorImpl &getSectionOrder() { + return SectionOrder; + } + const llvm::SmallVectorImpl &getSectionOrder() const { + return SectionOrder; + } + + /// @} + /// @name Fragment Layout Data + /// @{ + + /// \brief Get the offset of the given fragment inside its containing section. + uint64_t getFragmentOffset(const MCFragment *F) const; + + /// @} + /// @name Utility Functions + /// @{ + + /// \brief Get the address space size of the given section, as it effects + /// layout. This may differ from the size reported by \see getSectionSize() by + /// not including section tail padding. + uint64_t getSectionAddressSize(const MCSectionData *SD) const; + + /// \brief Get the data size of the given section, as emitted to the object + /// file. This may include additional padding, or be 0 for virtual sections. + uint64_t getSectionFileSize(const MCSectionData *SD) const; + + /// \brief Get the offset of the given symbol, as computed in the current + /// layout. + uint64_t getSymbolOffset(const MCSymbolData *SD) const; + + /// @} +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCAssembler.h b/final/include/llvm/MC/MCAssembler.h new file mode 100644 index 00000000000..30971c62a97 --- /dev/null +++ b/final/include/llvm/MC/MCAssembler.h @@ -0,0 +1,916 @@ +//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASSEMBLER_H +#define LLVM_MC_MCASSEMBLER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" +#include "llvm/Support/Casting.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/DataTypes.h" +#include // FIXME: Shouldn't be needed. + +namespace llvm { +class raw_ostream; +class MCAsmLayout; +class MCAssembler; +class MCBinaryExpr; +class MCContext; +class MCCodeEmitter; +class MCExpr; +class MCFragment; +class MCObjectWriter; +class MCSection; +class MCSectionData; +class MCSymbol; +class MCSymbolData; +class MCValue; +class TargetAsmBackend; + +class MCFragment : public ilist_node { + friend class MCAsmLayout; + + MCFragment(const MCFragment&); // DO NOT IMPLEMENT + void operator=(const MCFragment&); // DO NOT IMPLEMENT + +public: + enum FragmentType { + FT_Align, + FT_Data, + FT_Fill, + FT_Inst, + FT_Org, + FT_Dwarf, + FT_DwarfFrame, + FT_LEB + }; + +private: + FragmentType Kind; + + /// Parent - The data for the section this fragment is in. + MCSectionData *Parent; + + /// Atom - The atom this fragment is in, as represented by it's defining + /// symbol. Atom's are only used by backends which set + /// \see MCAsmBackend::hasReliableSymbolDifference(). + MCSymbolData *Atom; + + /// @name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// Offset - The offset of this fragment in its section. This is ~0 until + /// initialized. + uint64_t Offset; + + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; + + /// @} + +protected: + MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0); + +public: + // Only for sentinel. + MCFragment(); + virtual ~MCFragment(); + + FragmentType getKind() const { return Kind; } + + MCSectionData *getParent() const { return Parent; } + void setParent(MCSectionData *Value) { Parent = Value; } + + MCSymbolData *getAtom() const { return Atom; } + void setAtom(MCSymbolData *Value) { Atom = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + static bool classof(const MCFragment *O) { return true; } + + void dump(); +}; + +class MCDataFragment : public MCFragment { + SmallString<32> Contents; + + /// Fixups - The list of fixups in this fragment. + std::vector Fixups; + +public: + typedef std::vector::const_iterator const_fixup_iterator; + typedef std::vector::iterator fixup_iterator; + +public: + MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} + + /// @name Accessors + /// @{ + + SmallString<32> &getContents() { return Contents; } + const SmallString<32> &getContents() const { return Contents; } + + /// @} + /// @name Fixup Access + /// @{ + + void addFixup(MCFixup Fixup) { + // Enforce invariant that fixups are in offset order. + assert((Fixups.empty() || Fixup.getOffset() > Fixups.back().getOffset()) && + "Fixups must be added in order!"); + Fixups.push_back(Fixup); + } + + std::vector &getFixups() { return Fixups; } + const std::vector &getFixups() const { return Fixups; } + + fixup_iterator fixup_begin() { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + + fixup_iterator fixup_end() {return Fixups.end();} + const_fixup_iterator fixup_end() const {return Fixups.end();} + + size_t fixup_size() const { return Fixups.size(); } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Data; + } + static bool classof(const MCDataFragment *) { return true; } +}; + +// FIXME: This current incarnation of MCInstFragment doesn't make much sense, as +// it is almost entirely a duplicate of MCDataFragment. If we decide to stick +// with this approach (as opposed to making MCInstFragment a very light weight +// object with just the MCInst and a code size, then we should just change +// MCDataFragment to have an optional MCInst at its end. +class MCInstFragment : public MCFragment { + /// Inst - The instruction this is a fragment for. + MCInst Inst; + + /// Code - Binary data for the currently encoded instruction. + SmallString<8> Code; + + /// Fixups - The list of fixups in this fragment. + SmallVector Fixups; + +public: + typedef SmallVectorImpl::const_iterator const_fixup_iterator; + typedef SmallVectorImpl::iterator fixup_iterator; + +public: + MCInstFragment(MCInst _Inst, MCSectionData *SD = 0) + : MCFragment(FT_Inst, SD), Inst(_Inst) { + } + + /// @name Accessors + /// @{ + + SmallVectorImpl &getCode() { return Code; } + const SmallVectorImpl &getCode() const { return Code; } + + unsigned getInstSize() const { return Code.size(); } + + MCInst &getInst() { return Inst; } + const MCInst &getInst() const { return Inst; } + + void setInst(MCInst Value) { Inst = Value; } + + /// @} + /// @name Fixup Access + /// @{ + + SmallVectorImpl &getFixups() { return Fixups; } + const SmallVectorImpl &getFixups() const { return Fixups; } + + fixup_iterator fixup_begin() { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + + fixup_iterator fixup_end() {return Fixups.end();} + const_fixup_iterator fixup_end() const {return Fixups.end();} + + size_t fixup_size() const { return Fixups.size(); } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Inst; + } + static bool classof(const MCInstFragment *) { return true; } +}; + +class MCAlignFragment : public MCFragment { + /// Alignment - The alignment to ensure, in bytes. + unsigned Alignment; + + /// Value - Value to use for filling padding bytes. + int64_t Value; + + /// ValueSize - The size of the integer (in bytes) of \arg Value. + unsigned ValueSize; + + /// MaxBytesToEmit - The maximum number of bytes to emit; if the alignment + /// cannot be satisfied in this width then this fragment is ignored. + unsigned MaxBytesToEmit; + + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// of using the provided value. The exact interpretation of this flag is + /// target dependent. + bool EmitNops : 1; + +public: + MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) + : MCFragment(FT_Align, SD), Alignment(_Alignment), + Value(_Value),ValueSize(_ValueSize), + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} + + /// @name Accessors + /// @{ + + unsigned getAlignment() const { return Alignment; } + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } + + bool hasEmitNops() const { return EmitNops; } + void setEmitNops(bool Value) { EmitNops = Value; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Align; + } + static bool classof(const MCAlignFragment *) { return true; } +}; + +class MCFillFragment : public MCFragment { + /// Value - Value to use for filling bytes. + int64_t Value; + + /// ValueSize - The size (in bytes) of \arg Value to use when filling, or 0 if + /// this is a virtual fill fragment. + unsigned ValueSize; + + /// Size - The number of bytes to insert. + uint64_t Size; + +public: + MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, + MCSectionData *SD = 0) + : MCFragment(FT_Fill, SD), + Value(_Value), ValueSize(_ValueSize), Size(_Size) { + assert((!ValueSize || (Size % ValueSize) == 0) && + "Fill size must be a multiple of the value size!"); + } + + /// @name Accessors + /// @{ + + int64_t getValue() const { return Value; } + + unsigned getValueSize() const { return ValueSize; } + + uint64_t getSize() const { return Size; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Fill; + } + static bool classof(const MCFillFragment *) { return true; } +}; + +class MCOrgFragment : public MCFragment { + /// Offset - The offset this fragment should start at. + const MCExpr *Offset; + + /// Value - Value to use for filling bytes. + int8_t Value; + +public: + MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) + : MCFragment(FT_Org, SD), + Offset(&_Offset), Value(_Value) {} + + /// @name Accessors + /// @{ + + const MCExpr &getOffset() const { return *Offset; } + + uint8_t getValue() const { return Value; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Org; + } + static bool classof(const MCOrgFragment *) { return true; } +}; + +class MCLEBFragment : public MCFragment { + /// Value - The value this fragment should contain. + const MCExpr *Value; + + /// IsSigned - True if this is a sleb128, false if uleb128. + bool IsSigned; + + SmallString<8> Contents; +public: + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) + : MCFragment(FT_LEB, SD), + Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + const MCExpr &getValue() const { return *Value; } + + bool isSigned() const { return IsSigned; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_LEB; + } + static bool classof(const MCLEBFragment *) { return true; } +}; + +class MCDwarfLineAddrFragment : public MCFragment { + /// LineDelta - the value of the difference between the two line numbers + /// between two .loc dwarf directives. + int64_t LineDelta; + + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .loc dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, + MCSectionData *SD) + : MCFragment(FT_Dwarf, SD), + LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + int64_t getLineDelta() const { return LineDelta; } + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_Dwarf; + } + static bool classof(const MCDwarfLineAddrFragment *) { return true; } +}; + +class MCDwarfCallFrameFragment : public MCFragment { + /// AddrDelta - The expression for the difference of the two symbols that + /// make up the address delta between two .cfi_* dwarf directives. + const MCExpr *AddrDelta; + + SmallString<8> Contents; + +public: + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD) + : MCFragment(FT_DwarfFrame, SD), + AddrDelta(&_AddrDelta) { Contents.push_back(0); } + + /// @name Accessors + /// @{ + + const MCExpr &getAddrDelta() const { return *AddrDelta; } + + SmallString<8> &getContents() { return Contents; } + const SmallString<8> &getContents() const { return Contents; } + + /// @} + + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_DwarfFrame; + } + static bool classof(const MCDwarfCallFrameFragment *) { return true; } +}; + +// FIXME: Should this be a separate class, or just merged into MCSection? Since +// we anticipate the fast path being through an MCAssembler, the only reason to +// keep it out is for API abstraction. +class MCSectionData : public ilist_node { + friend class MCAsmLayout; + + MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT + void operator=(const MCSectionData&); // DO NOT IMPLEMENT + +public: + typedef iplist FragmentListType; + + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + + typedef FragmentListType::const_reverse_iterator const_reverse_iterator; + typedef FragmentListType::reverse_iterator reverse_iterator; + +private: + FragmentListType Fragments; + const MCSection *Section; + + /// Ordinal - The section index in the assemblers section list. + unsigned Ordinal; + + /// LayoutOrder - The index of this section in the layout order. + unsigned LayoutOrder; + + /// Alignment - The maximum alignment seen in this section. + unsigned Alignment; + + /// @name Assembler Backend Data + /// @{ + // + // FIXME: This could all be kept private to the assembler implementation. + + /// HasInstructions - Whether this section has had instructions emitted into + /// it. + unsigned HasInstructions : 1; + + /// @} + +public: + // Only for use as sentinel. + MCSectionData(); + MCSectionData(const MCSection &Section, MCAssembler *A = 0); + + const MCSection &getSection() const { return *Section; } + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + /// @name Fragment Access + /// @{ + + const FragmentListType &getFragmentList() const { return Fragments; } + FragmentListType &getFragmentList() { return Fragments; } + + iterator begin() { return Fragments.begin(); } + const_iterator begin() const { return Fragments.begin(); } + + iterator end() { return Fragments.end(); } + const_iterator end() const { return Fragments.end(); } + + reverse_iterator rbegin() { return Fragments.rbegin(); } + const_reverse_iterator rbegin() const { return Fragments.rbegin(); } + + reverse_iterator rend() { return Fragments.rend(); } + const_reverse_iterator rend() const { return Fragments.rend(); } + + size_t size() const { return Fragments.size(); } + + bool empty() const { return Fragments.empty(); } + + void dump(); + + /// @} +}; + +// FIXME: Same concerns as with SectionData. +class MCSymbolData : public ilist_node { +public: + const MCSymbol *Symbol; + + /// Fragment - The fragment this symbol's value is relative to, if any. + MCFragment *Fragment; + + /// Offset - The offset to apply to the fragment address to form this symbol's + /// value. + uint64_t Offset; + + /// IsExternal - True if this symbol is visible outside this translation + /// unit. + unsigned IsExternal : 1; + + /// IsPrivateExtern - True if this symbol is private extern. + unsigned IsPrivateExtern : 1; + + /// CommonSize - The size of the symbol, if it is 'common', or 0. + // + // FIXME: Pack this in with other fields? We could put it in offset, since a + // common symbol can never get a definition. + uint64_t CommonSize; + + /// SymbolSize - An expression describing how to calculate the size of + /// a symbol. If a symbol has no size this field will be NULL. + const MCExpr *SymbolSize; + + /// CommonAlign - The alignment of the symbol, if it is 'common'. + // + // FIXME: Pack this in with other fields? + unsigned CommonAlign; + + /// Flags - The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + uint32_t Flags; + + /// Index - Index field, for use by the object file implementation. + uint64_t Index; + +public: + // Only for use as sentinel. + MCSymbolData(); + MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, + MCAssembler *A = 0); + + /// @name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + MCFragment *getFragment() const { return Fragment; } + void setFragment(MCFragment *Value) { Fragment = Value; } + + uint64_t getOffset() const { return Offset; } + void setOffset(uint64_t Value) { Offset = Value; } + + /// @} + /// @name Symbol Attributes + /// @{ + + bool isExternal() const { return IsExternal; } + void setExternal(bool Value) { IsExternal = Value; } + + bool isPrivateExtern() const { return IsPrivateExtern; } + void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + + /// isCommon - Is this a 'common' symbol. + bool isCommon() const { return CommonSize != 0; } + + /// setCommon - Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + CommonSize = Size; + CommonAlign = Align; + } + + /// getCommonSize - Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } + + void setSize(const MCExpr *SS) { + SymbolSize = SS; + } + + const MCExpr *getSize() const { + return SymbolSize; + } + + + /// getCommonAlignment - Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlign; + } + + /// getFlags - Get the (implementation defined) symbol flags. + uint32_t getFlags() const { return Flags; } + + /// setFlags - Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) { Flags = Value; } + + /// modifyFlags - Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) { + Flags = (Flags & ~Mask) | Value; + } + + /// getIndex - Get the (implementation defined) index. + uint64_t getIndex() const { return Index; } + + /// setIndex - Set the (implementation defined) index. + void setIndex(uint64_t Value) { Index = Value; } + + /// @} + + void dump(); +}; + +// FIXME: This really doesn't belong here. See comments below. +struct IndirectSymbolData { + MCSymbol *Symbol; + MCSectionData *SectionData; +}; + +class MCAssembler { + friend class MCAsmLayout; + +public: + typedef iplist SectionDataListType; + typedef iplist SymbolDataListType; + + typedef SectionDataListType::const_iterator const_iterator; + typedef SectionDataListType::iterator iterator; + + typedef SymbolDataListType::const_iterator const_symbol_iterator; + typedef SymbolDataListType::iterator symbol_iterator; + + typedef std::vector::const_iterator + const_indirect_symbol_iterator; + typedef std::vector::iterator indirect_symbol_iterator; + +private: + MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT + void operator=(const MCAssembler&); // DO NOT IMPLEMENT + + MCContext &Context; + + TargetAsmBackend &Backend; + + MCCodeEmitter &Emitter; + + MCObjectWriter &Writer; + + raw_ostream &OS; + + iplist Sections; + + iplist Symbols; + + /// The map of sections to their associated assembler backend data. + // + // FIXME: Avoid this indirection? + DenseMap SectionMap; + + /// The map of symbols to their associated assembler backend data. + // + // FIXME: Avoid this indirection? + DenseMap SymbolMap; + + std::vector IndirectSymbols; + + /// The set of function symbols for which a .thumb_func directive has + /// been seen. + // + // FIXME: We really would like this in target specific code rather than + // here. Maybe when the relocation stuff moves to target specific, + // this can go with it? The streamer would need some target specific + // refactoring too. + SmallPtrSet ThumbFuncs; + + unsigned RelaxAll : 1; + unsigned NoExecStack : 1; + unsigned SubsectionsViaSymbols : 1; + +private: + /// Evaluate a fixup to a relocatable expression and the value which should be + /// placed into the fixup. + /// + /// \param Layout The layout to use for evaluation. + /// \param Fixup The fixup to evaluate. + /// \param DF The fragment the fixup is inside. + /// \param Target [out] On return, the relocatable expression the fixup + /// evaluates to. + /// \param Value [out] On return, the value of the fixup as currently layed + /// out. + /// \return Whether the fixup value was fully resolved. This is true if the + /// \arg Value result is fixed, otherwise the value may change due to + /// relocation. + bool EvaluateFixup(const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value) const; + + /// Check whether a fixup can be satisfied, or whether it needs to be relaxed + /// (increased in size, in order to hold its value correctly). + bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, + const MCAsmLayout &Layout) const; + + /// Check whether the given fragment needs relaxation. + bool FragmentNeedsRelaxation(const MCInstFragment *IF, + const MCAsmLayout &Layout) const; + + /// LayoutOnce - Perform one layout iteration and return true if any offsets + /// were adjusted. + bool LayoutOnce(MCAsmLayout &Layout); + + bool LayoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + + bool RelaxInstruction(MCAsmLayout &Layout, MCInstFragment &IF); + + bool RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &IF); + + bool RelaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF); + bool RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &DF); + + /// FinishLayout - Finalize a layout, including fragment lowering. + void FinishLayout(MCAsmLayout &Layout); + + uint64_t HandleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); + +public: + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(const MCAsmLayout &Layout, const MCFragment &F) const; + + /// Find the symbol which defines the atom containing the given symbol, or + /// null if there is no such symbol. + const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; + + /// Check whether a particular symbol is visible to the linker and is required + /// in the symbol table, or whether it can be discarded by the assembler. This + /// also effects whether the assembler treats the label as potentially + /// defining a separate atom. + bool isSymbolLinkerVisible(const MCSymbol &SD) const; + + /// Emit the section contents using the given object writer. + void WriteSectionData(const MCSectionData *Section, + const MCAsmLayout &Layout) const; + + /// Check whether a given symbol has been flagged with .thumb_func. + bool isThumbFunc(const MCSymbol *Func) const { + return ThumbFuncs.count(Func); + } + + /// Flag a function symbol as the target of a .thumb_func directive. + void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } + +public: + /// Construct a new assembler instance. + /// + /// \arg OS - The stream to output to. + // + // FIXME: How are we going to parameterize this? Two obvious options are stay + // concrete and require clients to pass in a target like object. The other + // option is to make this abstract, and have targets provide concrete + // implementations as we do with AsmParser. + MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, + raw_ostream &OS); + ~MCAssembler(); + + MCContext &getContext() const { return Context; } + + TargetAsmBackend &getBackend() const { return Backend; } + + MCCodeEmitter &getEmitter() const { return Emitter; } + + MCObjectWriter &getWriter() const { return Writer; } + + /// Finish - Do final processing and write the object to the output stream. + /// \arg Writer is used for custom object writer (as the MCJIT does), + /// if not specified it is automatically created from backend. + void Finish(); + + // FIXME: This does not belong here. + bool getSubsectionsViaSymbols() const { + return SubsectionsViaSymbols; + } + void setSubsectionsViaSymbols(bool Value) { + SubsectionsViaSymbols = Value; + } + + bool getRelaxAll() const { return RelaxAll; } + void setRelaxAll(bool Value) { RelaxAll = Value; } + + bool getNoExecStack() const { return NoExecStack; } + void setNoExecStack(bool Value) { NoExecStack = Value; } + + /// @name Section List Access + /// @{ + + const SectionDataListType &getSectionList() const { return Sections; } + SectionDataListType &getSectionList() { return Sections; } + + iterator begin() { return Sections.begin(); } + const_iterator begin() const { return Sections.begin(); } + + iterator end() { return Sections.end(); } + const_iterator end() const { return Sections.end(); } + + size_t size() const { return Sections.size(); } + + /// @} + /// @name Symbol List Access + /// @{ + + const SymbolDataListType &getSymbolList() const { return Symbols; } + SymbolDataListType &getSymbolList() { return Symbols; } + + symbol_iterator symbol_begin() { return Symbols.begin(); } + const_symbol_iterator symbol_begin() const { return Symbols.begin(); } + + symbol_iterator symbol_end() { return Symbols.end(); } + const_symbol_iterator symbol_end() const { return Symbols.end(); } + + size_t symbol_size() const { return Symbols.size(); } + + /// @} + /// @name Indirect Symbol List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + std::vector &getIndirectSymbols() { + return IndirectSymbols; + } + + indirect_symbol_iterator indirect_symbol_begin() { + return IndirectSymbols.begin(); + } + const_indirect_symbol_iterator indirect_symbol_begin() const { + return IndirectSymbols.begin(); + } + + indirect_symbol_iterator indirect_symbol_end() { + return IndirectSymbols.end(); + } + const_indirect_symbol_iterator indirect_symbol_end() const { + return IndirectSymbols.end(); + } + + size_t indirect_symbol_size() const { return IndirectSymbols.size(); } + + /// @} + /// @name Backend Data Access + /// @{ + + MCSectionData &getSectionData(const MCSection &Section) const { + MCSectionData *Entry = SectionMap.lookup(&Section); + assert(Entry && "Missing section data!"); + return *Entry; + } + + MCSectionData &getOrCreateSectionData(const MCSection &Section, + bool *Created = 0) { + MCSectionData *&Entry = SectionMap[&Section]; + + if (Created) *Created = !Entry; + if (!Entry) + Entry = new MCSectionData(Section, this); + + return *Entry; + } + + MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { + MCSymbolData *Entry = SymbolMap.lookup(&Symbol); + assert(Entry && "Missing symbol data!"); + return *Entry; + } + + MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, + bool *Created = 0) { + MCSymbolData *&Entry = SymbolMap[&Symbol]; + + if (Created) *Created = !Entry; + if (!Entry) + Entry = new MCSymbolData(Symbol, 0, 0, this); + + return *Entry; + } + + /// @} + + void dump(); +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCCodeEmitter.h b/final/include/llvm/MC/MCCodeEmitter.h new file mode 100644 index 00000000000..bc63241bece --- /dev/null +++ b/final/include/llvm/MC/MCCodeEmitter.h @@ -0,0 +1,42 @@ +//===-- llvm/MC/MCCodeEmitter.h - Instruction Encoding ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCODEEMITTER_H +#define LLVM_MC_MCCODEEMITTER_H + +#include "llvm/MC/MCFixup.h" + +#include + +namespace llvm { +class MCExpr; +class MCInst; +class raw_ostream; +template class SmallVectorImpl; + +/// MCCodeEmitter - Generic instruction encoding interface. +class MCCodeEmitter { +private: + MCCodeEmitter(const MCCodeEmitter &); // DO NOT IMPLEMENT + void operator=(const MCCodeEmitter &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + MCCodeEmitter(); + +public: + virtual ~MCCodeEmitter(); + + /// EncodeInstruction - Encode the given \arg Inst to bytes on the output + /// stream \arg OS. + virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, + SmallVectorImpl &Fixups) const = 0; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCContext.h b/final/include/llvm/MC/MCContext.h new file mode 100644 index 00000000000..7b26d549377 --- /dev/null +++ b/final/include/llvm/MC/MCContext.h @@ -0,0 +1,322 @@ +//===- MCContext.h - Machine Code Context -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCCONTEXT_H +#define LLVM_MC_MCCONTEXT_H + +#include "llvm/MC/SectionKind.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include // FIXME: Shouldn't be needed. + +namespace llvm { + class MCAsmInfo; + class MCExpr; + class MCSection; + class MCSymbol; + class MCLabel; + class MCDwarfFile; + class MCDwarfLoc; + class MCLineSection; + class StringRef; + class Twine; + class TargetAsmInfo; + class MCSectionMachO; + class MCSectionELF; + + /// MCContext - Context object for machine code objects. This class owns all + /// of the sections that it creates. + /// + class MCContext { + MCContext(const MCContext&); // DO NOT IMPLEMENT + MCContext &operator=(const MCContext&); // DO NOT IMPLEMENT + + /// The MCAsmInfo for this target. + const MCAsmInfo &MAI; + + const TargetAsmInfo *TAI; + + /// Symbols - Bindings of names to symbols. + StringMap Symbols; + + /// UsedNames - Keeps tracks of names that were used both for used declared + /// and artificial symbols. + StringMap UsedNames; + + /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary + /// symbol. + unsigned NextUniqueID; + + /// Instances of directional local labels. + DenseMap Instances; + /// NextInstance() creates the next instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned NextInstance(int64_t LocalLabelVal); + /// GetInstance() gets the current instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned GetInstance(int64_t LocalLabelVal); + + /// The file name of the log file from the environment variable + /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique + /// directive is used or it is an error. + char *SecureLogFile; + /// The stream that gets written to for the .secure_log_unique directive. + raw_ostream *SecureLog; + /// Boolean toggled when .secure_log_unique / .secure_log_reset is seen to + /// catch errors if .secure_log_unique appears twice without + /// .secure_log_reset appearing between them. + bool SecureLogUsed; + + /// The dwarf file and directory tables from the dwarf .file directive. + std::vector MCDwarfFiles; + std::vector MCDwarfDirs; + + /// The current dwarf line information from the last dwarf .loc directive. + MCDwarfLoc CurrentDwarfLoc; + bool DwarfLocSeen; + + /// The dwarf line information from the .loc directives for the sections + /// with assembled machine instructions have after seeing .loc directives. + DenseMap MCLineSections; + /// We need a deterministic iteration order, so we remember the order + /// the elements were added. + std::vector MCLineSectionOrder; + + /// Allocator - Allocator object used for creating machine code objects. + /// + /// We use a bump pointer allocator to avoid the need to track all allocated + /// objects. + BumpPtrAllocator Allocator; + + void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; + + MCSymbol *CreateSymbol(StringRef Name); + + public: + explicit MCContext(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); + ~MCContext(); + + const MCAsmInfo &getAsmInfo() const { return MAI; } + + const TargetAsmInfo &getTargetAsmInfo() const { return *TAI; } + + /// @name Symbol Management + /// @{ + + /// CreateTempSymbol - Create and return a new assembler temporary symbol + /// with a unique but unspecified name. + MCSymbol *CreateTempSymbol(); + + /// CreateDirectionalLocalSymbol - Create the definition of a directional + /// local symbol for numbered label (used for "1:" definitions). + MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); + + /// GetDirectionalLocalSymbol - Create and return a directional local + /// symbol for numbered label (used for "1b" or 1f" references). + MCSymbol *GetDirectionalLocalSymbol(int64_t LocalLabelVal, int bORf); + + /// GetOrCreateSymbol - Lookup the symbol inside with the specified + /// @p Name. If it exists, return it. If not, create a forward + /// reference and return it. + /// + /// @param Name - The symbol name, which must be unique across all symbols. + MCSymbol *GetOrCreateSymbol(StringRef Name); + MCSymbol *GetOrCreateSymbol(const Twine &Name); + + /// LookupSymbol - Get the symbol for \p Name, or null. + MCSymbol *LookupSymbol(StringRef Name) const; + + /// @} + + /// @name Section Management + /// @{ + + /// getMachOSection - Return the MCSection for the specified mach-o section. + /// This requires the operands to be valid. + const MCSectionMachO *getMachOSection(StringRef Segment, + StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, + SectionKind K); + const MCSectionMachO *getMachOSection(StringRef Segment, + StringRef Section, + unsigned TypeAndAttributes, + SectionKind K) { + return getMachOSection(Segment, Section, TypeAndAttributes, 0, K); + } + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind); + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind, + unsigned EntrySize, StringRef Group); + + const MCSectionELF *CreateELFGroupSection(); + + const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, + int Selection, SectionKind Kind); + + const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind) { + return getCOFFSection (Section, Characteristics, 0, Kind); + } + + + /// @} + + /// @name Dwarf Management + /// @{ + + /// GetDwarfFile - creates an entry in the dwarf file and directory tables. + unsigned GetDwarfFile(StringRef FileName, unsigned FileNumber); + + bool isValidDwarfFileNumber(unsigned FileNumber); + + bool hasDwarfFiles() const { + return !MCDwarfFiles.empty(); + } + + const std::vector &getMCDwarfFiles() { + return MCDwarfFiles; + } + const std::vector &getMCDwarfDirs() { + return MCDwarfDirs; + } + + const DenseMap + &getMCLineSections() const { + return MCLineSections; + } + const std::vector &getMCLineSectionOrder() const { + return MCLineSectionOrder; + } + void addMCLineSection(const MCSection *Sec, MCLineSection *Line) { + MCLineSections[Sec] = Line; + MCLineSectionOrder.push_back(Sec); + } + + /// setCurrentDwarfLoc - saves the information from the currently parsed + /// dwarf .loc directive and sets DwarfLocSeen. When the next instruction + /// is assembled an entry in the line number table with this information and + /// the address of the instruction will be created. + void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column, + unsigned Flags, unsigned Isa, + unsigned Discriminator) { + CurrentDwarfLoc.setFileNum(FileNum); + CurrentDwarfLoc.setLine(Line); + CurrentDwarfLoc.setColumn(Column); + CurrentDwarfLoc.setFlags(Flags); + CurrentDwarfLoc.setIsa(Isa); + CurrentDwarfLoc.setDiscriminator(Discriminator); + DwarfLocSeen = true; + } + void ClearDwarfLocSeen() { DwarfLocSeen = false; } + + bool getDwarfLocSeen() { return DwarfLocSeen; } + const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } + + /// @} + + char *getSecureLogFile() { return SecureLogFile; } + raw_ostream *getSecureLog() { return SecureLog; } + bool getSecureLogUsed() { return SecureLogUsed; } + void setSecureLog(raw_ostream *Value) { + SecureLog = Value; + } + void setSecureLogUsed(bool Value) { + SecureLogUsed = Value; + } + + void *Allocate(unsigned Size, unsigned Align = 8) { + return Allocator.Allocate(Size, Align); + } + void Deallocate(void *Ptr) { + } + }; + +} // end namespace llvm + +// operator new and delete aren't allowed inside namespaces. +// The throw specifications are mandated by the standard. +/// @brief Placement new for using the MCContext's allocator. +/// +/// This placement form of operator new uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new, which means that it returns +/// null on error. (If that is what the allocator does. The current does, so if +/// this ever changes, this operator will have to be changed, too.) +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); +/// // Specific alignment +/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The MCContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new(size_t Bytes, llvm::MCContext &C, + size_t Alignment = 16) throw () { + return C.Allocate(Bytes, Alignment); +} +/// @brief Placement delete companion to the new above. +/// +/// This operator is just a companion to the new above. There is no way of +/// invoking it directly; see the new operator for more details. This operator +/// is called implicitly by the compiler if a placement new expression using +/// the MCContext throws in the object constructor. +inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) + throw () { + C.Deallocate(Ptr); +} + +/// This placement form of operator new[] uses the MCContext's allocator for +/// obtaining memory. It is a non-throwing new[], which means that it returns +/// null on error. +/// Usage looks like this (assuming there's an MCContext 'Context' in scope): +/// @code +/// // Default alignment (16) +/// char *data = new (Context) char[10]; +/// // Specific alignment +/// char *data = new (Context, 8) char[10]; +/// @endcode +/// Please note that you cannot use delete on the pointer; it must be +/// deallocated using an explicit destructor call followed by +/// @c Context.Deallocate(Ptr). +/// +/// @param Bytes The number of bytes to allocate. Calculated by the compiler. +/// @param C The MCContext that provides the allocator. +/// @param Alignment The alignment of the allocated memory (if the underlying +/// allocator supports it). +/// @return The allocated memory. Could be NULL. +inline void *operator new[](size_t Bytes, llvm::MCContext& C, + size_t Alignment = 16) throw () { + return C.Allocate(Bytes, Alignment); +} + +/// @brief Placement delete[] companion to the new[] above. +/// +/// This operator is just a companion to the new[] above. There is no way of +/// invoking it directly; see the new[] operator for more details. This operator +/// is called implicitly by the compiler if a placement new[] expression using +/// the MCContext throws in the object constructor. +inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () { + C.Deallocate(Ptr); +} + +#endif diff --git a/final/include/llvm/MC/MCDirectives.h b/final/include/llvm/MC/MCDirectives.h new file mode 100644 index 00000000000..1df55dc252e --- /dev/null +++ b/final/include/llvm/MC/MCDirectives.h @@ -0,0 +1,56 @@ +//===- MCDirectives.h - Enums for directives on various targets -*- 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 various enums that represent target-specific directives. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDIRECTIVES_H +#define LLVM_MC_MCDIRECTIVES_H + +namespace llvm { + +enum MCSymbolAttr { + MCSA_Invalid = 0, ///< Not a valid directive. + + // Various directives in alphabetical order. + MCSA_ELF_TypeFunction, ///< .type _foo, STT_FUNC # aka @function + MCSA_ELF_TypeIndFunction, ///< .type _foo, STT_GNU_IFUNC + MCSA_ELF_TypeObject, ///< .type _foo, STT_OBJECT # aka @object + MCSA_ELF_TypeTLS, ///< .type _foo, STT_TLS # aka @tls_object + MCSA_ELF_TypeCommon, ///< .type _foo, STT_COMMON # aka @common + MCSA_ELF_TypeNoType, ///< .type _foo, STT_NOTYPE # aka @notype + MCSA_ELF_TypeGnuUniqueObject, /// .type _foo, @gnu_unique_object + MCSA_Global, ///< .globl + MCSA_Hidden, ///< .hidden (ELF) + MCSA_IndirectSymbol, ///< .indirect_symbol (MachO) + MCSA_Internal, ///< .internal (ELF) + MCSA_LazyReference, ///< .lazy_reference (MachO) + MCSA_Local, ///< .local (ELF) + MCSA_NoDeadStrip, ///< .no_dead_strip (MachO) + MCSA_SymbolResolver, ///< .symbol_resolver (MachO) + MCSA_PrivateExtern, ///< .private_extern (MachO) + MCSA_Protected, ///< .protected (ELF) + MCSA_Reference, ///< .reference (MachO) + MCSA_Weak, ///< .weak + MCSA_WeakDefinition, ///< .weak_definition (MachO) + MCSA_WeakReference, ///< .weak_reference (MachO) + MCSA_WeakDefAutoPrivate ///< .weak_def_can_be_hidden (MachO) +}; + +enum MCAssemblerFlag { + MCAF_SyntaxUnified, ///< .syntax (ARM/ELF) + MCAF_SubsectionsViaSymbols, ///< .subsections_via_symbols (MachO) + MCAF_Code16, ///< .code 16 + MCAF_Code32 ///< .code 32 +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCDisassembler.h b/final/include/llvm/MC/MCDisassembler.h new file mode 100644 index 00000000000..c9e42eb6c79 --- /dev/null +++ b/final/include/llvm/MC/MCDisassembler.h @@ -0,0 +1,60 @@ +//===-- llvm/MC/MCDisassembler.h - Disassembler interface -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef MCDISASSEMBLER_H +#define MCDISASSEMBLER_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCInst; +class MemoryObject; +class raw_ostream; + +struct EDInstInfo; + +/// MCDisassembler - Superclass for all disassemblers. Consumes a memory region +/// and provides an array of assembly instructions. +class MCDisassembler { +public: + /// Constructor - Performs initial setup for the disassembler. + MCDisassembler() {} + + virtual ~MCDisassembler(); + + /// getInstruction - Returns the disassembly of a single instruction. + /// + /// @param instr - An MCInst to populate with the contents of the + /// instruction. + /// @param size - A value to populate with the size of the instruction, or + /// the number of bytes consumed while attempting to decode + /// an invalid instruction. + /// @param region - The memory object to use as a source for machine code. + /// @param address - The address, in the memory space of region, of the first + /// byte of the instruction. + /// @param vStream - The stream to print warnings and diagnostic messages on. + /// @return - True if the instruction is valid; false otherwise. + virtual bool getInstruction(MCInst& instr, + uint64_t& size, + const MemoryObject ®ion, + uint64_t address, + raw_ostream &vStream) const = 0; + + /// getEDInfo - Returns the enhanced insturction information corresponding to + /// the disassembler. + /// + /// @return - An array of instruction information, with one entry for + /// each MCInst opcode this disassembler returns. + /// NULL if there is no info for this target. + virtual EDInstInfo *getEDInfo() const { return (EDInstInfo*)0; } +}; + +} // namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCDwarf.h b/final/include/llvm/MC/MCDwarf.h new file mode 100644 index 00000000000..07a7bad15b1 --- /dev/null +++ b/final/include/llvm/MC/MCDwarf.h @@ -0,0 +1,279 @@ +//===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCDwarfFile to support the dwarf +// .file directive and the .loc directive. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCDWARF_H +#define LLVM_MC_MCDWARF_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineLocation.h" // FIXME +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { + class MachineMove; + class MCContext; + class MCExpr; + class MCSection; + class MCSectionData; + class MCStreamer; + class MCSymbol; + class MCObjectStreamer; + class raw_ostream; + + /// MCDwarfFile - Instances of this class represent the name of the dwarf + /// .file directive and its associated dwarf file number in the MC file, + /// and MCDwarfFile's are created and unique'd by the MCContext class where + /// the file number for each is its index into the vector of DwarfFiles (note + /// index 0 is not used and not a valid dwarf file number). + class MCDwarfFile { + // Name - the base name of the file without its directory path. + // The StringRef references memory allocated in the MCContext. + StringRef Name; + + // DirIndex - the index into the list of directory names for this file name. + unsigned DirIndex; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCDwarfFile(StringRef name, unsigned dirIndex) + : Name(name), DirIndex(dirIndex) {} + + MCDwarfFile(const MCDwarfFile&); // DO NOT IMPLEMENT + void operator=(const MCDwarfFile&); // DO NOT IMPLEMENT + public: + /// getName - Get the base name of this MCDwarfFile. + StringRef getName() const { return Name; } + + /// getDirIndex - Get the dirIndex of this MCDwarfFile. + unsigned getDirIndex() const { return DirIndex; } + + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ + DwarfFile.print(OS); + return OS; + } + + /// MCDwarfLoc - Instances of this class represent the information from a + /// dwarf .loc directive. + class MCDwarfLoc { + // FileNum - the file number. + unsigned FileNum; + // Line - the line number. + unsigned Line; + // Column - the column position. + unsigned Column; + // Flags (see #define's below) + unsigned Flags; + // Isa + unsigned Isa; + // Discriminator + unsigned Discriminator; + +// Flag that indicates the initial value of the is_stmt_start flag. +#define DWARF2_LINE_DEFAULT_IS_STMT 1 + +#define DWARF2_FLAG_IS_STMT (1 << 0) +#define DWARF2_FLAG_BASIC_BLOCK (1 << 1) +#define DWARF2_FLAG_PROLOGUE_END (1 << 2) +#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) + + private: // MCContext manages these + friend class MCContext; + friend class MCLineEntry; + MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, + unsigned isa, unsigned discriminator) + : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), + Discriminator(discriminator) {} + + // Allow the default copy constructor and assignment operator to be used + // for an MCDwarfLoc object. + + public: + /// getFileNum - Get the FileNum of this MCDwarfLoc. + unsigned getFileNum() const { return FileNum; } + + /// getLine - Get the Line of this MCDwarfLoc. + unsigned getLine() const { return Line; } + + /// getColumn - Get the Column of this MCDwarfLoc. + unsigned getColumn() const { return Column; } + + /// getFlags - Get the Flags of this MCDwarfLoc. + unsigned getFlags() const { return Flags; } + + /// getIsa - Get the Isa of this MCDwarfLoc. + unsigned getIsa() const { return Isa; } + + /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + unsigned getDiscriminator() const { return Discriminator; } + + /// setFileNum - Set the FileNum of this MCDwarfLoc. + void setFileNum(unsigned fileNum) { FileNum = fileNum; } + + /// setLine - Set the Line of this MCDwarfLoc. + void setLine(unsigned line) { Line = line; } + + /// setColumn - Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { Column = column; } + + /// setFlags - Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { Flags = flags; } + + /// setIsa - Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { Isa = isa; } + + /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + void setDiscriminator(unsigned discriminator) { + Discriminator = discriminator; + } + }; + + /// MCLineEntry - Instances of this class represent the line information for + /// the dwarf line table entries. Which is created after a machine + /// instruction is assembled and uses an address from a temporary label + /// created at the current address in the current section and the info from + /// the last .loc directive seen as stored in the context. + class MCLineEntry : public MCDwarfLoc { + MCSymbol *Label; + + private: + // Allow the default copy constructor and assignment operator to be used + // for an MCLineEntry object. + + public: + // Constructor to create an MCLineEntry given a symbol and the dwarf loc. + MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), + Label(label) {} + + MCSymbol *getLabel() const { return Label; } + + // This is called when an instruction is assembled into the specified + // section and if there is information from the last .loc directive that + // has yet to have a line entry made for it is made. + static void Make(MCStreamer *MCOS, const MCSection *Section); + }; + + /// MCLineSection - Instances of this class represent the line information + /// for a section where machine instructions have been assembled after seeing + /// .loc directives. This is the information used to build the dwarf line + /// table for a section. + class MCLineSection { + + private: + MCLineSection(const MCLineSection&); // DO NOT IMPLEMENT + void operator=(const MCLineSection&); // DO NOT IMPLEMENT + + public: + // Constructor to create an MCLineSection with an empty MCLineEntries + // vector. + MCLineSection() {} + + // addLineEntry - adds an entry to this MCLineSection's line entries + void addLineEntry(const MCLineEntry &LineEntry) { + MCLineEntries.push_back(LineEntry); + } + + typedef std::vector MCLineEntryCollection; + typedef MCLineEntryCollection::iterator iterator; + typedef MCLineEntryCollection::const_iterator const_iterator; + + private: + MCLineEntryCollection MCLineEntries; + + public: + const MCLineEntryCollection *getMCLineEntries() const { + return &MCLineEntries; + } + }; + + class MCDwarfFileTable { + public: + // + // This emits the Dwarf file and the line tables. + // + static void Emit(MCStreamer *MCOS); + }; + + class MCDwarfLineAddr { + public: + /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. + static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); + + /// Utility function to emit the encoding to a streamer. + static void Emit(MCStreamer *MCOS, + int64_t LineDelta,uint64_t AddrDelta); + + /// Utility function to write the encoding to an object writer. + static void Write(MCObjectWriter *OW, + int64_t LineDelta, uint64_t AddrDelta); + }; + + class MCCFIInstruction { + public: + enum OpType { Remember, Restore, Move }; + private: + OpType Operation; + MCSymbol *Label; + // Move to & from location. + MachineLocation Destination; + MachineLocation Source; + public: + MCCFIInstruction(OpType Op, MCSymbol *L) + : Operation(Op), Label(L) { + assert(Op == Remember || Op == Restore); + } + MCCFIInstruction(MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Move), Label(L), Destination(D), Source(S) { + } + OpType getOperation() const { return Operation; } + MCSymbol *getLabel() const { return Label; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } + }; + + struct MCDwarfFrameInfo { + MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), + Instructions(), PersonalityEncoding(0), + LsdaEncoding(0) {} + MCSymbol *Begin; + MCSymbol *End; + const MCSymbol *Personality; + const MCSymbol *Lsda; + std::vector Instructions; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + }; + + class MCDwarfFrameEmitter { + public: + // + // This emits the frame info section. + // + static void Emit(MCStreamer &streamer); + static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); + }; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCELFObjectWriter.h b/final/include/llvm/MC/MCELFObjectWriter.h new file mode 100644 index 00000000000..3c150dca9e6 --- /dev/null +++ b/final/include/llvm/MC/MCELFObjectWriter.h @@ -0,0 +1,47 @@ +//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFOBJECTWRITER_H +#define LLVM_MC_MCELFOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCELFObjectTargetWriter { + const Triple::OSType OSType; + const uint16_t EMachine; + const unsigned HasRelocationAddend : 1; + const unsigned Is64Bit : 1; +protected: + MCELFObjectTargetWriter(bool Is64Bit_, Triple::OSType OSType_, + uint16_t EMachine_, bool HasRelocationAddend_); + +public: + virtual ~MCELFObjectTargetWriter(); + + /// @name Accessors + /// @{ + Triple::OSType getOSType() { return OSType; } + uint16_t getEMachine() { return EMachine; } + bool hasRelocationAddend() { return HasRelocationAddend; } + bool is64Bit() { return Is64Bit; } + /// @} +}; + +/// \brief Construct a new ELF writer instance. +/// +/// \param MOTW - The target specific ELF writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCELFSymbolFlags.h b/final/include/llvm/MC/MCELFSymbolFlags.h new file mode 100644 index 00000000000..d798fb07727 --- /dev/null +++ b/final/include/llvm/MC/MCELFSymbolFlags.h @@ -0,0 +1,57 @@ +//===- MCELFSymbolFlags.h - ELF Symbol Flags ----------------*- 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 SymbolFlags used for the ELF target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSYMBOLFLAGS_H +#define LLVM_MC_MCELFSYMBOLFLAGS_H + +#include "llvm/Support/ELF.h" + +// Because all the symbol flags need to be stored in the MCSymbolData +// 'flags' variable we need to provide shift constants per flag type. + +namespace llvm { + enum { + ELF_STT_Shift = 0, // Shift value for STT_* flags. + ELF_STB_Shift = 4, // Shift value for STB_* flags. + ELF_STV_Shift = 8, // Shift value for STV_* flags. + ELF_Other_Shift = 10 // Shift value for other flags. + }; + + enum SymbolFlags { + ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift), + ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift), + ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift), + ELF_STB_Loproc = (ELF::STB_LOPROC << ELF_STB_Shift), + ELF_STB_Hiproc = (ELF::STB_HIPROC << ELF_STB_Shift), + + ELF_STT_Notype = (ELF::STT_NOTYPE << ELF_STT_Shift), + ELF_STT_Object = (ELF::STT_OBJECT << ELF_STT_Shift), + ELF_STT_Func = (ELF::STT_FUNC << ELF_STT_Shift), + ELF_STT_Section = (ELF::STT_SECTION << ELF_STT_Shift), + ELF_STT_File = (ELF::STT_FILE << ELF_STT_Shift), + ELF_STT_Common = (ELF::STT_COMMON << ELF_STT_Shift), + ELF_STT_Tls = (ELF::STT_TLS << ELF_STT_Shift), + ELF_STT_Loproc = (ELF::STT_LOPROC << ELF_STT_Shift), + ELF_STT_Hiproc = (ELF::STT_HIPROC << ELF_STT_Shift), + + ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift), + ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift), + ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift), + ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift), + + ELF_Other_Weakref = (1 << ELF_Other_Shift) + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCExpr.h b/final/include/llvm/MC/MCExpr.h new file mode 100644 index 00000000000..fea5249eaba --- /dev/null +++ b/final/include/llvm/MC/MCExpr.h @@ -0,0 +1,432 @@ +//===- MCExpr.h - Assembly Level Expressions --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCEXPR_H +#define LLVM_MC_MCEXPR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCAsmInfo; +class MCAsmLayout; +class MCAssembler; +class MCContext; +class MCSectionData; +class MCSymbol; +class MCValue; +class raw_ostream; +class StringRef; +typedef DenseMap SectionAddrMap; + +/// MCExpr - Base class for the full range of assembler expressions which are +/// needed for parsing. +class MCExpr { +public: + enum ExprKind { + Binary, ///< Binary expressions. + Constant, ///< Constant expressions. + SymbolRef, ///< References to labels and assigned expressions. + Unary, ///< Unary expressions. + Target ///< Target specific expression. + }; + +private: + ExprKind Kind; + + MCExpr(const MCExpr&); // DO NOT IMPLEMENT + void operator=(const MCExpr&); // DO NOT IMPLEMENT + + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const; +protected: + explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} + + bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, + bool InSet) const; +public: + /// @name Accessors + /// @{ + + ExprKind getKind() const { return Kind; } + + /// @} + /// @name Utility Methods + /// @{ + + void print(raw_ostream &OS) const; + void dump() const; + + /// @} + /// @name Expression Evaluation + /// @{ + + /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// + /// @param Res - The absolute value, if evaluation succeeds. + /// @param Layout - The assembler layout object to use for evaluating symbol + /// values. If not given, then only non-symbolic expressions will be + /// evaluated. + /// @result - True on success. + bool EvaluateAsAbsolute(int64_t &Res) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const; + + /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable + /// value, i.e. an expression of the fixed form (a - b + constant). + /// + /// @param Res - The relocatable value, if evaluation succeeds. + /// @param Layout - The assembler layout object to use for evaluating values. + /// @result - True on success. + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout &Layout) const; + + /// @} + + static bool classof(const MCExpr *) { return true; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { + E.print(OS); + return OS; +} + +//// MCConstantExpr - Represent a constant integer expression. +class MCConstantExpr : public MCExpr { + int64_t Value; + + explicit MCConstantExpr(int64_t _Value) + : MCExpr(MCExpr::Constant), Value(_Value) {} + +public: + /// @name Construction + /// @{ + + static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); + + /// @} + /// @name Accessors + /// @{ + + int64_t getValue() const { return Value; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Constant; + } + static bool classof(const MCConstantExpr *) { return true; } +}; + +/// MCSymbolRefExpr - Represent a reference to a symbol from inside an +/// expression. +/// +/// A symbol reference in an expression may be a use of a label, a use of an +/// assembler variable (defined constant), or constitute an implicit definition +/// of the symbol as external. +class MCSymbolRefExpr : public MCExpr { +public: + enum VariantKind { + VK_None, + VK_Invalid, + + VK_GOT, + VK_GOTOFF, + VK_GOTPCREL, + VK_GOTTPOFF, + VK_INDNTPOFF, + VK_NTPOFF, + VK_GOTNTPOFF, + VK_PLT, + VK_TLSGD, + VK_TLSLD, + VK_TLSLDM, + VK_TPOFF, + VK_DTPOFF, + VK_TLVP, // Mach-O thread local variable relocation + // FIXME: We'd really like to use the generic Kinds listed above for these. + VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT + VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF + VK_ARM_GOT, + VK_ARM_GOTOFF, + VK_ARM_TPOFF, + VK_ARM_GOTTPOFF, + + VK_PPC_TOC, + VK_PPC_HA16, // ha16(symbol) + VK_PPC_LO16 // lo16(symbol) + }; + +private: + /// The symbol being referenced. + const MCSymbol *Symbol; + + /// The symbol reference modifier. + const VariantKind Kind; + + explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind) + : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind) {} + +public: + /// @name Construction + /// @{ + + static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) { + return MCSymbolRefExpr::Create(Symbol, VK_None, Ctx); + } + + static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, VariantKind Kind, + MCContext &Ctx); + static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind, + MCContext &Ctx); + + /// @} + /// @name Accessors + /// @{ + + const MCSymbol &getSymbol() const { return *Symbol; } + + VariantKind getKind() const { return Kind; } + + /// @} + /// @name Static Utility Functions + /// @{ + + static StringRef getVariantKindName(VariantKind Kind); + + static VariantKind getVariantKindForName(StringRef Name); + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::SymbolRef; + } + static bool classof(const MCSymbolRefExpr *) { return true; } +}; + +/// MCUnaryExpr - Unary assembler expressions. +class MCUnaryExpr : public MCExpr { +public: + enum Opcode { + LNot, ///< Logical negation. + Minus, ///< Unary minus. + Not, ///< Bitwise negation. + Plus ///< Unary plus. + }; + +private: + Opcode Op; + const MCExpr *Expr; + + MCUnaryExpr(Opcode _Op, const MCExpr *_Expr) + : MCExpr(MCExpr::Unary), Op(_Op), Expr(_Expr) {} + +public: + /// @name Construction + /// @{ + + static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, + MCContext &Ctx); + static const MCUnaryExpr *CreateLNot(const MCExpr *Expr, MCContext &Ctx) { + return Create(LNot, Expr, Ctx); + } + static const MCUnaryExpr *CreateMinus(const MCExpr *Expr, MCContext &Ctx) { + return Create(Minus, Expr, Ctx); + } + static const MCUnaryExpr *CreateNot(const MCExpr *Expr, MCContext &Ctx) { + return Create(Not, Expr, Ctx); + } + static const MCUnaryExpr *CreatePlus(const MCExpr *Expr, MCContext &Ctx) { + return Create(Plus, Expr, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this unary expression. + Opcode getOpcode() const { return Op; } + + /// getSubExpr - Get the child of this unary expression. + const MCExpr *getSubExpr() const { return Expr; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Unary; + } + static bool classof(const MCUnaryExpr *) { return true; } +}; + +/// MCBinaryExpr - Binary assembler expressions. +class MCBinaryExpr : public MCExpr { +public: + enum Opcode { + Add, ///< Addition. + And, ///< Bitwise and. + Div, ///< Signed division. + EQ, ///< Equality comparison. + GT, ///< Signed greater than comparison (result is either 0 or some + ///< target-specific non-zero value) + GTE, ///< Signed greater than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + LAnd, ///< Logical and. + LOr, ///< Logical or. + LT, ///< Signed less than comparison (result is either 0 or + ///< some target-specific non-zero value). + LTE, ///< Signed less than or equal comparison (result is either 0 or + ///< some target-specific non-zero value). + Mod, ///< Signed remainder. + Mul, ///< Multiplication. + NE, ///< Inequality comparison. + Or, ///< Bitwise or. + Shl, ///< Shift left. + Shr, ///< Shift right (arithmetic or logical, depending on target) + Sub, ///< Subtraction. + Xor ///< Bitwise exclusive or. + }; + +private: + Opcode Op; + const MCExpr *LHS, *RHS; + + MCBinaryExpr(Opcode _Op, const MCExpr *_LHS, const MCExpr *_RHS) + : MCExpr(MCExpr::Binary), Op(_Op), LHS(_LHS), RHS(_RHS) {} + +public: + /// @name Construction + /// @{ + + static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx); + static const MCBinaryExpr *CreateAdd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Add, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(And, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateDiv(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Div, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateEQ(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(EQ, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateGT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(GT, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateGTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(GTE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLAnd(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LAnd, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LOr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLT(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LT, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateLTE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(LTE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateMod(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Mod, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateMul(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Mul, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateNE(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(NE, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateOr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Or, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateShl(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Shl, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Shr, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Sub, LHS, RHS, Ctx); + } + static const MCBinaryExpr *CreateXor(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return Create(Xor, LHS, RHS, Ctx); + } + + /// @} + /// @name Accessors + /// @{ + + /// getOpcode - Get the kind of this binary expression. + Opcode getOpcode() const { return Op; } + + /// getLHS - Get the left-hand side expression of the binary operator. + const MCExpr *getLHS() const { return LHS; } + + /// getRHS - Get the right-hand side expression of the binary operator. + const MCExpr *getRHS() const { return RHS; } + + /// @} + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Binary; + } + static bool classof(const MCBinaryExpr *) { return true; } +}; + +/// MCTargetExpr - This is an extension point for target-specific MCExpr +/// subclasses to implement. +/// +/// NOTE: All subclasses are required to have trivial destructors because +/// MCExprs are bump pointer allocated and not destructed. +class MCTargetExpr : public MCExpr { + virtual void Anchor(); +protected: + MCTargetExpr() : MCExpr(Target) {} + virtual ~MCTargetExpr() {} +public: + + virtual void PrintImpl(raw_ostream &OS) const = 0; + virtual bool EvaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout) const = 0; + virtual void AddValueSymbols(MCAssembler *) const = 0; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + static bool classof(const MCTargetExpr *) { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCFixup.h b/final/include/llvm/MC/MCFixup.h new file mode 100644 index 00000000000..6fde797e40f --- /dev/null +++ b/final/include/llvm/MC/MCFixup.h @@ -0,0 +1,97 @@ +//===-- llvm/MC/MCFixup.h - Instruction Relocation and Patching -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUP_H +#define LLVM_MC_MCFIXUP_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +class MCExpr; + +/// MCFixupKind - Extensible enumeration to represent the type of a fixup. +enum MCFixupKind { + FK_Data_1 = 0, ///< A one-byte fixup. + FK_Data_2, ///< A two-byte fixup. + FK_Data_4, ///< A four-byte fixup. + FK_Data_8, ///< A eight-byte fixup. + FK_PCRel_1, ///< A one-byte pc relative fixup. + FK_PCRel_2, ///< A two-byte pc relative fixup. + FK_PCRel_4, ///< A four-byte pc relative fixup. + FK_PCRel_8, ///< A eight-byte pc relative fixup. + + FirstTargetFixupKind = 128, + + // Limit range of target fixups, in case we want to pack more efficiently + // later. + MaxTargetFixupKind = (1 << 8) +}; + +/// MCFixup - Encode information on a single operation to perform on a byte +/// sequence (e.g., an encoded instruction) which requires assemble- or run- +/// time patching. +/// +/// Fixups are used any time the target instruction encoder needs to represent +/// some value in an instruction which is not yet concrete. The encoder will +/// encode the instruction assuming the value is 0, and emit a fixup which +/// communicates to the assembler backend how it should rewrite the encoded +/// value. +/// +/// During the process of relaxation, the assembler will apply fixups as +/// symbolic values become concrete. When relaxation is complete, any remaining +/// fixups become relocations in the object file (or errors, if the fixup cannot +/// be encoded on the target). +class MCFixup { + /// The value to put into the fixup location. The exact interpretation of the + /// expression is target dependent, usually it will be one of the operands to + /// an instruction or an assembler directive. + const MCExpr *Value; + + /// The byte index of start of the relocation inside the encoded instruction. + uint32_t Offset; + + /// The target dependent kind of fixup item this is. The kind is used to + /// determine how the operand value should be encoded into the instruction. + unsigned Kind; + +public: + static MCFixup Create(uint32_t Offset, const MCExpr *Value, + MCFixupKind Kind) { + assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); + MCFixup FI; + FI.Value = Value; + FI.Offset = Offset; + FI.Kind = unsigned(Kind); + return FI; + } + + MCFixupKind getKind() const { return MCFixupKind(Kind); } + + uint32_t getOffset() const { return Offset; } + void setOffset(uint32_t Value) { Offset = Value; } + + const MCExpr *getValue() const { return Value; } + + /// getKindForSize - Return the generic fixup kind for a value with the given + /// size. It is an error to pass an unsupported size. + static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { + switch (Size) { + default: assert(0 && "Invalid generic fixup size!"); + case 1: return isPCRel ? FK_PCRel_1 : FK_Data_1; + case 2: return isPCRel ? FK_PCRel_2 : FK_Data_2; + case 4: return isPCRel ? FK_PCRel_4 : FK_Data_4; + case 8: return isPCRel ? FK_PCRel_8 : FK_Data_8; + } + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCFixupKindInfo.h b/final/include/llvm/MC/MCFixupKindInfo.h new file mode 100644 index 00000000000..1961687146a --- /dev/null +++ b/final/include/llvm/MC/MCFixupKindInfo.h @@ -0,0 +1,43 @@ +//===-- llvm/MC/MCFixupKindInfo.h - Fixup Descriptors -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCFIXUPKINDINFO_H +#define LLVM_MC_MCFIXUPKINDINFO_H + +namespace llvm { + +/// MCFixupKindInfo - Target independent information on a fixup kind. +struct MCFixupKindInfo { + enum FixupKindFlags { + /// Is this fixup kind PCrelative? This is used by the assembler backend to + /// evaluate fixup values in a target independent manner when possible. + FKF_IsPCRel = (1 << 0), + + /// Should this fixup kind force a 4-byte aligned effective PC value? + FKF_IsAlignedDownTo32Bits = (1 << 1) + }; + + /// A target specific name for the fixup kind. The names will be unique for + /// distinct kinds on any given target. + const char *Name; + + /// The bit offset to write the relocation into. + unsigned TargetOffset; + + /// The number of bits written by this fixup. The bits are assumed to be + /// contiguous. + unsigned TargetSize; + + /// Flags describing additional information on this fixup kind. + unsigned Flags; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCInst.h b/final/include/llvm/MC/MCInst.h new file mode 100644 index 00000000000..d6ef7b4c33c --- /dev/null +++ b/final/include/llvm/MC/MCInst.h @@ -0,0 +1,170 @@ +//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCInst and MCOperand classes, which +// is the basic representation used to represent low-level machine code +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINST_H +#define LLVM_MC_MCINST_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class raw_ostream; +class MCAsmInfo; +class MCInstPrinter; +class MCExpr; + +/// MCOperand - Instances of this class represent operands of the MCInst class. +/// This is a simple discriminated union. +class MCOperand { + enum MachineOperandType { + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kFPImmediate, ///< Floating-point immediate operand. + kExpr ///< Relocatable immediate operand. + }; + unsigned char Kind; + + union { + unsigned RegVal; + int64_t ImmVal; + double FPImmVal; + const MCExpr *ExprVal; + }; +public: + + MCOperand() : Kind(kInvalid), FPImmVal(0.0) {} + + bool isValid() const { return Kind != kInvalid; } + bool isReg() const { return Kind == kRegister; } + bool isImm() const { return Kind == kImmediate; } + bool isFPImm() const { return Kind == kFPImmediate; } + bool isExpr() const { return Kind == kExpr; } + + /// getReg - Returns the register number. + unsigned getReg() const { + assert(isReg() && "This is not a register operand!"); + return RegVal; + } + + /// setReg - Set the register number. + void setReg(unsigned Reg) { + assert(isReg() && "This is not a register operand!"); + RegVal = Reg; + } + + int64_t getImm() const { + assert(isImm() && "This is not an immediate"); + return ImmVal; + } + void setImm(int64_t Val) { + assert(isImm() && "This is not an immediate"); + ImmVal = Val; + } + + double getFPImm() const { + assert(isFPImm() && "This is not an FP immediate"); + return FPImmVal; + } + + void setFPImm(double Val) { + assert(isFPImm() && "This is not an FP immediate"); + FPImmVal = Val; + } + + const MCExpr *getExpr() const { + assert(isExpr() && "This is not an expression"); + return ExprVal; + } + void setExpr(const MCExpr *Val) { + assert(isExpr() && "This is not an expression"); + ExprVal = Val; + } + + static MCOperand CreateReg(unsigned Reg) { + MCOperand Op; + Op.Kind = kRegister; + Op.RegVal = Reg; + return Op; + } + static MCOperand CreateImm(int64_t Val) { + MCOperand Op; + Op.Kind = kImmediate; + Op.ImmVal = Val; + return Op; + } + static MCOperand CreateFPImm(double Val) { + MCOperand Op; + Op.Kind = kFPImmediate; + Op.FPImmVal = Val; + return Op; + } + static MCOperand CreateExpr(const MCExpr *Val) { + MCOperand Op; + Op.Kind = kExpr; + Op.ExprVal = Val; + return Op; + } + + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void dump() const; +}; + + +/// MCInst - Instances of this class represent a single low-level machine +/// instruction. +class MCInst { + unsigned Opcode; + SmallVector Operands; +public: + MCInst() : Opcode(0) {} + + void setOpcode(unsigned Op) { Opcode = Op; } + + unsigned getOpcode() const { return Opcode; } + + const MCOperand &getOperand(unsigned i) const { return Operands[i]; } + MCOperand &getOperand(unsigned i) { return Operands[i]; } + unsigned getNumOperands() const { return Operands.size(); } + + void addOperand(const MCOperand &Op) { + Operands.push_back(Op); + } + + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + void dump() const; + + /// \brief Dump the MCInst as prettily as possible using the additional MC + /// structures, if given. Operators are separated by the \arg Separator + /// string. + void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = 0, + const MCInstPrinter *Printer = 0, + StringRef Separator = " ") const; +}; + +inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { + MO.print(OS, 0); + return OS; +} + +inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { + MI.print(OS, 0); + return OS; +} + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCInstPrinter.h b/final/include/llvm/MC/MCInstPrinter.h new file mode 100644 index 00000000000..92f06ed09c6 --- /dev/null +++ b/final/include/llvm/MC/MCInstPrinter.h @@ -0,0 +1,51 @@ +//===-- MCInstPrinter.h - Convert an MCInst to target assembly syntax -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCINSTPRINTER_H +#define LLVM_MC_MCINSTPRINTER_H + +namespace llvm { +class MCInst; +class raw_ostream; +class MCAsmInfo; +class StringRef; + +/// MCInstPrinter - This is an instance of a target assembly language printer +/// that converts an MCInst to valid target assembly syntax. +class MCInstPrinter { +protected: + /// CommentStream - a stream that comments can be emitted to if desired. + /// Each comment must end with a newline. This will be null if verbose + /// assembly emission is disable. + raw_ostream *CommentStream; + const MCAsmInfo &MAI; +public: + MCInstPrinter(const MCAsmInfo &mai) + : CommentStream(0), MAI(mai) {} + + virtual ~MCInstPrinter(); + + /// setCommentStream - Specify a stream to emit comments to. + void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } + + /// printInst - Print the specified MCInst to the specified raw_ostream. + /// + virtual void printInst(const MCInst *MI, raw_ostream &OS) = 0; + + /// getOpcodeName - Return the name of the specified opcode enum (e.g. + /// "MOV32ri") or empty if we can't resolve it. + virtual StringRef getOpcodeName(unsigned Opcode) const; + + /// getRegName - Return the assembler register name. + virtual StringRef getRegName(unsigned RegNo) const; +}; + +} // namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCLabel.h b/final/include/llvm/MC/MCLabel.h new file mode 100644 index 00000000000..727520d4af9 --- /dev/null +++ b/final/include/llvm/MC/MCLabel.h @@ -0,0 +1,56 @@ +//===- MCLabel.h - Machine Code Directional Local Labels --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCLabel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLABEL_H +#define LLVM_MC_MCLABEL_H + +namespace llvm { + class MCContext; + class raw_ostream; + + /// MCLabel - Instances of this class represent a label name in the MC file, + /// and MCLabel are created and unique'd by the MCContext class. MCLabel + /// should only be constructed for valid instances in the object file. + class MCLabel { + // Instance - the instance number of this Directional Local Label + unsigned Instance; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCLabel(unsigned instance) + : Instance(instance) {} + + MCLabel(const MCLabel&); // DO NOT IMPLEMENT + void operator=(const MCLabel&); // DO NOT IMPLEMENT + public: + /// getInstance - Get the current instance of this Directional Local Label. + unsigned getInstance() const { return Instance; } + + /// incInstance - Increment the current instance of this Directional Local + /// Label. + unsigned incInstance() { return ++Instance; } + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { + Label.print(OS); + return OS; + } +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCMachOSymbolFlags.h b/final/include/llvm/MC/MCMachOSymbolFlags.h new file mode 100644 index 00000000000..696436dffa6 --- /dev/null +++ b/final/include/llvm/MC/MCMachOSymbolFlags.h @@ -0,0 +1,46 @@ +//===- MCMachOSymbolFlags.h - MachO Symbol Flags ----------------*- 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 SymbolFlags used for the MachO target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOSYMBOLFLAGS_H +#define LLVM_MC_MCMACHOSYMBOLFLAGS_H + +// These flags are mostly used in MCMachOStreamer.cpp but also needed in +// MachObjectWriter.cpp to test for Weak Definitions of symbols to emit +// the correct relocation information. + +namespace llvm { + /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest + /// 16 bits of the implementation defined flags. + enum SymbolFlags { // See . + SF_DescFlagsMask = 0xFFFF, + + // Reference type flags. + SF_ReferenceTypeMask = 0x0007, + SF_ReferenceTypeUndefinedNonLazy = 0x0000, + SF_ReferenceTypeUndefinedLazy = 0x0001, + SF_ReferenceTypeDefined = 0x0002, + SF_ReferenceTypePrivateDefined = 0x0003, + SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, + SF_ReferenceTypePrivateUndefinedLazy = 0x0005, + + // Other 'desc' flags. + SF_ThumbFunc = 0x0008, + SF_NoDeadStrip = 0x0020, + SF_WeakReference = 0x0040, + SF_WeakDefinition = 0x0080, + SF_SymbolResolver = 0x0100 + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCMachObjectWriter.h b/final/include/llvm/MC/MCMachObjectWriter.h new file mode 100644 index 00000000000..ec51031d0bb --- /dev/null +++ b/final/include/llvm/MC/MCMachObjectWriter.h @@ -0,0 +1,65 @@ +//===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOBJECTWRITER_H +#define LLVM_MC_MCMACHOBJECTWRITER_H + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MCMachObjectTargetWriter { + const unsigned Is64Bit : 1; + const uint32_t CPUType; + const uint32_t CPUSubtype; + // FIXME: Remove this, we should just always use it once we no longer care + // about Darwin 'as' compatibility. + const unsigned UseAggressiveSymbolFolding : 1; + unsigned LocalDifference_RIT; + +protected: + MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, + uint32_t CPUSubtype_, + bool UseAggressiveSymbolFolding_ = false); + + void setLocalDifferenceRelocationType(unsigned Type) { + LocalDifference_RIT = Type; + } + +public: + virtual ~MCMachObjectTargetWriter(); + + /// @name Accessors + /// @{ + + bool is64Bit() const { return Is64Bit; } + bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; } + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubtype() const { return CPUSubtype; } + unsigned getLocalDifferenceRelocationType() const { + return LocalDifference_RIT; + } + + /// @} +}; + +/// \brief Construct a new Mach-O writer instance. +/// +/// This routine takes ownership of the target writer subclass. +/// +/// \param MOTW - The target specific Mach-O writer subclass. +/// \param OS - The stream to write to. +/// \returns The constructed object writer. +MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, + raw_ostream &OS, bool IsLittleEndian); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCObjectStreamer.h b/final/include/llvm/MC/MCObjectStreamer.h new file mode 100644 index 00000000000..833341eb97f --- /dev/null +++ b/final/include/llvm/MC/MCObjectStreamer.h @@ -0,0 +1,83 @@ +//===- MCObjectStreamer.h - MCStreamer Object File Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTSTREAMER_H +#define LLVM_MC_MCOBJECTSTREAMER_H + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class MCAssembler; +class MCCodeEmitter; +class MCSectionData; +class MCExpr; +class MCFragment; +class MCDataFragment; +class TargetAsmBackend; +class raw_ostream; + +/// \brief Streaming object file generation interface. +/// +/// This class provides an implementation of the MCStreamer interface which is +/// suitable for use with the assembler backend. Specific object file formats +/// are expected to subclass this interface to implement directives specific +/// to that file format or custom semantics expected by the object writer +/// implementation. +class MCObjectStreamer : public MCStreamer { + MCAssembler *Assembler; + MCSectionData *CurSectionData; + + virtual void EmitInstToData(const MCInst &Inst) = 0; + +protected: + MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &_OS, MCCodeEmitter *_Emitter); + ~MCObjectStreamer(); + + MCSectionData *getCurrentSectionData() const { + return CurSectionData; + } + + MCFragment *getCurrentFragment() const; + + /// Get a data fragment to write into, creating a new one if the current + /// fragment is not a data fragment. + MCDataFragment *getOrCreateDataFragment() const; + + const MCExpr *AddValueSymbols(const MCExpr *Value); + +public: + MCAssembler &getAssembler() { return *Assembler; } + + /// @name MCStreamer Interface + /// @{ + + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); + virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitInstruction(const MCInst &Inst); + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label); + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); + virtual void Finish(); + + /// @} +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCObjectWriter.h b/final/include/llvm/MC/MCObjectWriter.h new file mode 100644 index 00000000000..782d844598b --- /dev/null +++ b/final/include/llvm/MC/MCObjectWriter.h @@ -0,0 +1,198 @@ +//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCOBJECTWRITER_H +#define LLVM_MC_MCOBJECTWRITER_H + +#include "llvm/ADT/Triple.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +class MCAsmLayout; +class MCAssembler; +class MCFixup; +class MCFragment; +class MCSymbol; +class MCSymbolData; +class MCSymbolRefExpr; +class MCValue; +class raw_ostream; + +/// MCObjectWriter - Defines the object file and target independent interfaces +/// used by the assembler backend to write native file format object files. +/// +/// The object writer contains a few callbacks used by the assembler to allow +/// the object writer to modify the assembler data structures at appropriate +/// points. Once assembly is complete, the object writer is given the +/// MCAssembler instance, which contains all the symbol and section data which +/// should be emitted as part of WriteObject(). +/// +/// The object writer also contains a number of helper methods for writing +/// binary data to the output stream. +class MCObjectWriter { + MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT + void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT + +protected: + raw_ostream &OS; + + unsigned IsLittleEndian : 1; + +protected: // Can only create subclasses. + MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian) + : OS(_OS), IsLittleEndian(_IsLittleEndian) {} + +public: + virtual ~MCObjectWriter(); + + bool isLittleEndian() const { return IsLittleEndian; } + + raw_ostream &getStream() { return OS; } + + /// @name High-Level API + /// @{ + + /// Perform any late binding of symbols (for example, to assign symbol indices + /// for use when generating relocations). + /// + /// This routine is called by the assembler after layout and relaxation is + /// complete. + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; + + /// Record a relocation entry. + /// + /// This routine is called by the assembler after layout and relaxation, and + /// post layout binding. The implementation is responsible for storing + /// information about the relocation so that it can be emitted during + /// WriteObject(). + virtual void RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) = 0; + + /// \brief Check whether the difference (A - B) between two symbol + /// references is fully resolved. + /// + /// Clients are not required to answer precisely and may conservatively return + /// false, even when a difference is fully resolved. + bool + IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const; + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + + /// Write the object file. + /// + /// This routine is called by the assembler after layout and relaxation is + /// complete, fixups have been evaluated and applied, and relocations + /// generated. + virtual void WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) = 0; + + /// @} + /// @name Binary Output + /// @{ + + void Write8(uint8_t Value) { + OS << char(Value); + } + + void WriteLE16(uint16_t Value) { + Write8(uint8_t(Value >> 0)); + Write8(uint8_t(Value >> 8)); + } + + void WriteLE32(uint32_t Value) { + WriteLE16(uint16_t(Value >> 0)); + WriteLE16(uint16_t(Value >> 16)); + } + + void WriteLE64(uint64_t Value) { + WriteLE32(uint32_t(Value >> 0)); + WriteLE32(uint32_t(Value >> 32)); + } + + void WriteBE16(uint16_t Value) { + Write8(uint8_t(Value >> 8)); + Write8(uint8_t(Value >> 0)); + } + + void WriteBE32(uint32_t Value) { + WriteBE16(uint16_t(Value >> 16)); + WriteBE16(uint16_t(Value >> 0)); + } + + void WriteBE64(uint64_t Value) { + WriteBE32(uint32_t(Value >> 32)); + WriteBE32(uint32_t(Value >> 0)); + } + + void Write16(uint16_t Value) { + if (IsLittleEndian) + WriteLE16(Value); + else + WriteBE16(Value); + } + + void Write32(uint32_t Value) { + if (IsLittleEndian) + WriteLE32(Value); + else + WriteBE32(Value); + } + + void Write64(uint64_t Value) { + if (IsLittleEndian) + WriteLE64(Value); + else + WriteBE64(Value); + } + + void WriteZeros(unsigned N) { + const char Zeros[16] = { 0 }; + + for (unsigned i = 0, e = N / 16; i != e; ++i) + OS << StringRef(Zeros, 16); + + OS << StringRef(Zeros, N % 16); + } + + void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { + assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && + "data size greater than fill size, unexpected large write will occur"); + OS << Str; + if (ZeroFillSize) + WriteZeros(ZeroFillSize - Str.size()); + } + + /// @} + + /// Utility function to encode a SLEB128 value. + static void EncodeSLEB128(int64_t Value, raw_ostream &OS); + /// Utility function to encode a ULEB128 value. + static void EncodeULEB128(uint64_t Value, raw_ostream &OS); +}; + +MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCParser/AsmCond.h b/final/include/llvm/MC/MCParser/AsmCond.h new file mode 100644 index 00000000000..92a115eb803 --- /dev/null +++ b/final/include/llvm/MC/MCParser/AsmCond.h @@ -0,0 +1,40 @@ +//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMCOND_H +#define ASMCOND_H + +namespace llvm { + +/// AsmCond - Class to support conditional assembly +/// +/// The conditional assembly feature (.if, .else, .elseif and .endif) is +/// implemented with AsmCond that tells us what we are in the middle of +/// processing. Ignore can be either true or false. When true we are ignoring +/// the block of code in the middle of a conditional. + +class AsmCond { +public: + enum ConditionalAssemblyType { + NoCond, // no conditional is being processed + IfCond, // inside if conditional + ElseIfCond, // inside elseif conditional + ElseCond // inside else conditional + }; + + ConditionalAssemblyType TheCond; + bool CondMet; + bool Ignore; + + AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {} +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCParser/AsmLexer.h b/final/include/llvm/MC/MCParser/AsmLexer.h new file mode 100644 index 00000000000..252696bec31 --- /dev/null +++ b/final/include/llvm/MC/MCParser/AsmLexer.h @@ -0,0 +1,70 @@ +//===- AsmLexer.h - Lexer for Assembly 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 declares the lexer for assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMLEXER_H +#define ASMLEXER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { +class MemoryBuffer; +class SMLoc; +class MCAsmInfo; + +/// AsmLexer - Lexer class for assembly files. +class AsmLexer : public MCAsmLexer { + const MCAsmInfo &MAI; + + const char *CurPtr; + const MemoryBuffer *CurBuf; + + void operator=(const AsmLexer&); // DO NOT IMPLEMENT + AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT + +protected: + /// LexToken - Read the next token and return its code. + virtual AsmToken LexToken(); + +public: + AsmLexer(const MCAsmInfo &MAI); + ~AsmLexer(); + + void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); + + virtual StringRef LexUntilEndOfStatement(); + + bool isAtStartOfComment(char Char); + + const MCAsmInfo &getMAI() const { return MAI; } + +private: + int getNextChar(); + AsmToken ReturnError(const char *Loc, const std::string &Msg); + + AsmToken LexIdentifier(); + AsmToken LexSlash(); + AsmToken LexLineComment(); + AsmToken LexDigit(); + AsmToken LexSingleQuote(); + AsmToken LexQuote(); + AsmToken LexFloatLiteral(); +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCParser/MCAsmLexer.h b/final/include/llvm/MC/MCParser/MCAsmLexer.h new file mode 100644 index 00000000000..606725a9851 --- /dev/null +++ b/final/include/llvm/MC/MCParser/MCAsmLexer.h @@ -0,0 +1,181 @@ +//===-- llvm/MC/MCAsmLexer.h - Abstract Asm Lexer Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMLEXER_H +#define LLVM_MC_MCASMLEXER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/SMLoc.h" + +namespace llvm { +class MCAsmLexer; +class MCInst; +class Target; + +/// AsmToken - Target independent representation for an assembler token. +class AsmToken { +public: + enum TokenKind { + // Markers + Eof, Error, + + // String values. + Identifier, + String, + + // Integer values. + Integer, + + // Real values. + Real, + + // Register values (stored in IntVal). Only used by TargetAsmLexer. + Register, + + // No-value. + EndOfStatement, + Colon, + Plus, Minus, Tilde, + Slash, // '/' + LParen, RParen, LBrac, RBrac, LCurly, RCurly, + Star, Dot, Comma, Dollar, Equal, EqualEqual, + + Pipe, PipePipe, Caret, + Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, + Less, LessEqual, LessLess, LessGreater, + Greater, GreaterEqual, GreaterGreater, At + }; + + TokenKind Kind; + + /// A reference to the entire token contents; this is always a pointer into + /// a memory buffer owned by the source manager. + StringRef Str; + + int64_t IntVal; + +public: + AsmToken() {} + AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) + : Kind(_Kind), Str(_Str), IntVal(_IntVal) {} + + TokenKind getKind() const { return Kind; } + bool is(TokenKind K) const { return Kind == K; } + bool isNot(TokenKind K) const { return Kind != K; } + + SMLoc getLoc() const; + + /// getStringContents - Get the contents of a string token (without quotes). + StringRef getStringContents() const { + assert(Kind == String && "This token isn't a string!"); + return Str.slice(1, Str.size() - 1); + } + + /// getIdentifier - Get the identifier string for the current token, which + /// should be an identifier or a string. This gets the portion of the string + /// which should be used as the identifier, e.g., it does not include the + /// quotes on strings. + StringRef getIdentifier() const { + if (Kind == Identifier) + return getString(); + return getStringContents(); + } + + /// getString - Get the string for the current token, this includes all + /// characters (for example, the quotes on strings) in the token. + /// + /// The returned StringRef points into the source manager's memory buffer, and + /// is safe to store across calls to Lex(). + StringRef getString() const { return Str; } + + // FIXME: Don't compute this in advance, it makes every token larger, and is + // also not generally what we want (it is nicer for recovery etc. to lex 123br + // as a single token, then diagnose as an invalid number). + int64_t getIntVal() const { + assert(Kind == Integer && "This token isn't an integer!"); + return IntVal; + } + + /// getRegVal - Get the register number for the current token, which should + /// be a register. + unsigned getRegVal() const { + assert(Kind == Register && "This token isn't a register!"); + return static_cast(IntVal); + } +}; + +/// MCAsmLexer - Generic assembler lexer interface, for use by target specific +/// assembly lexers. +class MCAsmLexer { + /// The current token, stored in the base class for faster access. + AsmToken CurTok; + + /// The location and description of the current error + SMLoc ErrLoc; + std::string Err; + + MCAsmLexer(const MCAsmLexer &); // DO NOT IMPLEMENT + void operator=(const MCAsmLexer &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + const char *TokStart; + + MCAsmLexer(); + + virtual AsmToken LexToken() = 0; + + void SetError(const SMLoc &errLoc, const std::string &err) { + ErrLoc = errLoc; + Err = err; + } + +public: + virtual ~MCAsmLexer(); + + /// Lex - Consume the next token from the input stream and return it. + /// + /// The lexer will continuosly return the end-of-file token once the end of + /// the main input file has been reached. + const AsmToken &Lex() { + return CurTok = LexToken(); + } + + virtual StringRef LexUntilEndOfStatement() = 0; + + /// getLoc - Get the current source location. + SMLoc getLoc() const; + + /// getTok - Get the current (last) lexed token. + const AsmToken &getTok() { + return CurTok; + } + + /// getErrLoc - Get the current error location + const SMLoc &getErrLoc() { + return ErrLoc; + } + + /// getErr - Get the current error string + const std::string &getErr() { + return Err; + } + + /// getKind - Get the kind of current token. + AsmToken::TokenKind getKind() const { return CurTok.getKind(); } + + /// is - Check if the current token has kind \arg K. + bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } + + /// isNot - Check if the current token has kind \arg K. + bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCParser/MCAsmParser.h b/final/include/llvm/MC/MCParser/MCAsmParser.h new file mode 100644 index 00000000000..54979d977db --- /dev/null +++ b/final/include/llvm/MC/MCParser/MCAsmParser.h @@ -0,0 +1,137 @@ +//===-- llvm/MC/MCAsmParser.h - Abstract Asm Parser Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMPARSER_H +#define LLVM_MC_MCASMPARSER_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class AsmToken; +class MCAsmInfo; +class MCAsmLexer; +class MCAsmParserExtension; +class MCContext; +class MCExpr; +class MCStreamer; +class SMLoc; +class SourceMgr; +class StringRef; +class Target; +class TargetAsmParser; +class Twine; + +/// MCAsmParser - Generic assembler parser interface, for use by target specific +/// assembly parsers. +class MCAsmParser { +public: + typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); + +private: + MCAsmParser(const MCAsmParser &); // DO NOT IMPLEMENT + void operator=(const MCAsmParser &); // DO NOT IMPLEMENT + + TargetAsmParser *TargetParser; + + unsigned ShowParsedOperands : 1; + +protected: // Can only create subclasses. + MCAsmParser(); + +public: + virtual ~MCAsmParser(); + + virtual void AddDirectiveHandler(MCAsmParserExtension *Object, + StringRef Directive, + DirectiveHandler Handler) = 0; + + virtual SourceMgr &getSourceManager() = 0; + + virtual MCAsmLexer &getLexer() = 0; + + virtual MCContext &getContext() = 0; + + /// getStreamer - Return the output streamer for the assembler. + virtual MCStreamer &getStreamer() = 0; + + TargetAsmParser &getTargetParser() const { return *TargetParser; } + void setTargetParser(TargetAsmParser &P); + + bool getShowParsedOperands() const { return ShowParsedOperands; } + void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } + + /// Run - Run the parser on the input source buffer. + virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; + + /// Warning - Emit a warning at the location \arg L, with the message \arg + /// Msg. + virtual void Warning(SMLoc L, const Twine &Msg) = 0; + + /// Error - Emit an error at the location \arg L, with the message \arg + /// Msg. + /// + /// \return The return value is always true, as an idiomatic convenience to + /// clients. + virtual bool Error(SMLoc L, const Twine &Msg) = 0; + + /// Lex - Get the next AsmToken in the stream, possibly handling file + /// inclusion first. + virtual const AsmToken &Lex() = 0; + + /// getTok - Get the current AsmToken from the stream. + const AsmToken &getTok(); + + /// \brief Report an error at the current lexer location. + bool TokError(const Twine &Msg); + + /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) + /// and set \arg Res to the identifier contents. + virtual bool ParseIdentifier(StringRef &Res) = 0; + + /// \brief Parse up to the end of statement and return the contents from the + /// current token until the end of the statement; the current token on exit + /// will be either the EndOfStatement or EOF. + virtual StringRef ParseStringToEndOfStatement() = 0; + + /// EatToEndOfStatement - Skip to the end of the current statement, for error + /// recovery. + virtual void EatToEndOfStatement() = 0; + + /// ParseExpression - Parse an arbitrary expression. + /// + /// @param Res - The value of the expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + bool ParseExpression(const MCExpr *&Res); + + /// ParseParenExpression - Parse an arbitrary expression, assuming that an + /// initial '(' has already been consumed. + /// + /// @param Res - The value of the expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; + + /// ParseAbsoluteExpression - Parse an expression which must evaluate to an + /// absolute value. + /// + /// @param Res - The value of the absolute expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool ParseAbsoluteExpression(int64_t &Res) = 0; +}; + +/// \brief Create an MCAsmParser instance. +MCAsmParser *createMCAsmParser(const Target &, SourceMgr &, MCContext &, + MCStreamer &, const MCAsmInfo &); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCParser/MCAsmParserExtension.h b/final/include/llvm/MC/MCParser/MCAsmParserExtension.h new file mode 100644 index 00000000000..ceb57f57e9e --- /dev/null +++ b/final/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -0,0 +1,80 @@ +//===-- llvm/MC/MCAsmParserExtension.h - Asm Parser Hooks -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMPARSEREXTENSION_H +#define LLVM_MC_MCASMPARSEREXTENSION_H + +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" + +namespace llvm { +class Twine; + +/// \brief Generic interface for extending the MCAsmParser, +/// which is implemented by target and object file assembly parser +/// implementations. +class MCAsmParserExtension { + MCAsmParserExtension(const MCAsmParserExtension &); // DO NOT IMPLEMENT + void operator=(const MCAsmParserExtension &); // DO NOT IMPLEMENT + + MCAsmParser *Parser; + +protected: + MCAsmParserExtension(); + + // Helper template for implementing static dispatch functions. + template + static bool HandleDirective(MCAsmParserExtension *Target, + StringRef Directive, + SMLoc DirectiveLoc) { + T *Obj = static_cast(Target); + return (Obj->*Handler)(Directive, DirectiveLoc); + } + + bool BracketExpressionsSupported; + +public: + virtual ~MCAsmParserExtension(); + + /// \brief Initialize the extension for parsing using the given \arg + /// Parser. The extension should use the AsmParser interfaces to register its + /// parsing routines. + virtual void Initialize(MCAsmParser &Parser); + + /// @name MCAsmParser Proxy Interfaces + /// @{ + + MCContext &getContext() { return getParser().getContext(); } + MCAsmLexer &getLexer() { return getParser().getLexer(); } + MCAsmParser &getParser() { return *Parser; } + SourceMgr &getSourceManager() { return getParser().getSourceManager(); } + MCStreamer &getStreamer() { return getParser().getStreamer(); } + void Warning(SMLoc L, const Twine &Msg) { + return getParser().Warning(L, Msg); + } + bool Error(SMLoc L, const Twine &Msg) { + return getParser().Error(L, Msg); + } + bool TokError(const Twine &Msg) { + return getParser().TokError(Msg); + } + + const AsmToken &Lex() { return getParser().Lex(); } + + const AsmToken &getTok() { return getParser().getTok(); } + + bool HasBracketExpressions() const { return BracketExpressionsSupported; } + + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/final/include/llvm/MC/MCParser/MCParsedAsmOperand.h new file mode 100644 index 00000000000..91f5773b8df --- /dev/null +++ b/final/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -0,0 +1,37 @@ +//===-- llvm/MC/MCParsedAsmOperand.h - Asm Parser Operand -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCASMOPERAND_H +#define LLVM_MC_MCASMOPERAND_H + +namespace llvm { +class SMLoc; +class raw_ostream; + +/// MCParsedAsmOperand - This abstract class represents a source-level assembly +/// instruction operand. It should be subclassed by target-specific code. This +/// base class is used by target-independent clients and is the interface +/// between parsing an asm instruction and recognizing it. +class MCParsedAsmOperand { +public: + MCParsedAsmOperand() {} + virtual ~MCParsedAsmOperand() {} + + /// getStartLoc - Get the location of the first token of this operand. + virtual SMLoc getStartLoc() const = 0; + /// getEndLoc - Get the location of the last token of this operand. + virtual SMLoc getEndLoc() const = 0; + + /// dump - Print a debug representation of the operand to the given stream. + virtual void dump(raw_ostream &OS) const = 0; +}; + +} // end namespace llvm. + +#endif diff --git a/final/include/llvm/MC/MCSection.h b/final/include/llvm/MC/MCSection.h new file mode 100644 index 00000000000..1c01b2f8f3c --- /dev/null +++ b/final/include/llvm/MC/MCSection.h @@ -0,0 +1,76 @@ +//===- MCSection.h - Machine Code Sections ----------------------*- 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 MCSection class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTION_H +#define LLVM_MC_MCSECTION_H + +#include +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + class MCContext; + class MCAsmInfo; + class raw_ostream; + + /// MCSection - Instances of this class represent a uniqued identifier for a + /// section in the current translation unit. The MCContext class uniques and + /// creates these. + class MCSection { + public: + enum SectionVariant { + SV_COFF = 0, + SV_ELF, + SV_MachO + }; + + private: + MCSection(const MCSection&); // DO NOT IMPLEMENT + void operator=(const MCSection&); // DO NOT IMPLEMENT + protected: + MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} + SectionVariant Variant; + SectionKind Kind; + public: + virtual ~MCSection(); + + SectionKind getKind() const { return Kind; } + + SectionVariant getVariant() const { return Variant; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const = 0; + + /// isBaseAddressKnownZero - Return true if we know that this section will + /// get a base address of zero. In cases where we know that this is true we + /// can emit section offsets as direct references to avoid a subtraction + /// from the base of the section, saving a relocation. + virtual bool isBaseAddressKnownZero() const { + return false; + } + + // UseCodeAlign - Return true if a .align directive should use + // "optimized nops" to fill instead of 0s. + virtual bool UseCodeAlign() const = 0; + + /// isVirtualSection - Check whether this section is "virtual", that is + /// has no actual object file contents. + virtual bool isVirtualSection() const = 0; + + static bool classof(const MCSection *) { return true; } + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCSectionCOFF.h b/final/include/llvm/MC/MCSectionCOFF.h new file mode 100644 index 00000000000..b154cf59d10 --- /dev/null +++ b/final/include/llvm/MC/MCSectionCOFF.h @@ -0,0 +1,69 @@ +//===- MCSectionCOFF.h - COFF Machine Code Sections -------------*- 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 MCSectionCOFF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONCOFF_H +#define LLVM_MC_MCSECTIONCOFF_H + +#include "llvm/MC/MCSection.h" + +#include "llvm/Support/COFF.h" + +namespace llvm { + +/// MCSectionCOFF - This represents a section on Windows + class MCSectionCOFF : public MCSection { + // The memory for this string is stored in the same MCContext as *this. + StringRef SectionName; + + /// Characteristics - This is the Characteristics field of a section, + // drawn from the enums below. + unsigned Characteristics; + + /// Selection - This is the Selection field for the section symbol, if + /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 + int Selection; + + private: + friend class MCContext; + MCSectionCOFF(StringRef Section, unsigned Characteristics, + int Selection, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), Selection (Selection) { + assert ((Characteristics & 0x00F00000) == 0 && + "alignment must not be set upon section creation"); + } + ~MCSectionCOFF(); + + public: + /// ShouldOmitSectionDirective - Decides whether a '.section' directive + /// should be printed before the section name + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + StringRef getSectionName() const { return SectionName; } + unsigned getCharacteristics() const { return Characteristics; } + int getSelection () const { return Selection; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_COFF; + } + static bool classof(const MCSectionCOFF *) { return true; } + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCSectionELF.h b/final/include/llvm/MC/MCSectionELF.h new file mode 100644 index 00000000000..c82de712820 --- /dev/null +++ b/final/include/llvm/MC/MCSectionELF.h @@ -0,0 +1,87 @@ +//===- MCSectionELF.h - ELF Machine Code Sections ---------------*- 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 MCSectionELF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONELF_H +#define LLVM_MC_MCSECTIONELF_H + +#include "llvm/MC/MCSection.h" +#include "llvm/Support/ELF.h" + +namespace llvm { + +class MCSymbol; + +/// MCSectionELF - This represents a section on linux, lots of unix variants +/// and some bare metal systems. +class MCSectionELF : public MCSection { + /// SectionName - This is the name of the section. The referenced memory is + /// owned by TargetLoweringObjectFileELF's ELFUniqueMap. + StringRef SectionName; + + /// Type - This is the sh_type field of a section, drawn from the enums below. + unsigned Type; + + /// Flags - This is the sh_flags field of a section, drawn from the enums. + /// below. + unsigned Flags; + + /// EntrySize - The size of each entry in this section. This size only + /// makes sense for sections that contain fixed-sized entries. If a + /// section does not contain fixed-sized entries 'EntrySize' will be 0. + unsigned EntrySize; + + const MCSymbol *Group; + +private: + friend class MCContext; + MCSectionELF(StringRef Section, unsigned type, unsigned flags, + SectionKind K, unsigned entrySize, const MCSymbol *group) + : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), + EntrySize(entrySize), Group(group) {} + ~MCSectionELF(); +public: + + /// ShouldOmitSectionDirective - Decides whether a '.section' directive + /// should be printed before the section name + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + StringRef getSectionName() const { return SectionName; } + unsigned getType() const { return Type; } + unsigned getFlags() const { return Flags; } + unsigned getEntrySize() const { return EntrySize; } + const MCSymbol *getGroup() const { return Group; } + + void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; + + /// isBaseAddressKnownZero - We know that non-allocatable sections (like + /// debug info) have a base of zero. + virtual bool isBaseAddressKnownZero() const { + return (getFlags() & ELF::SHF_ALLOC) == 0; + } + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_ELF; + } + static bool classof(const MCSectionELF *) { return true; } + + // Return the entry size for sections with fixed-width data. + static unsigned DetermineEntrySize(SectionKind Kind); + +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCSectionMachO.h b/final/include/llvm/MC/MCSectionMachO.h new file mode 100644 index 00000000000..7633515f274 --- /dev/null +++ b/final/include/llvm/MC/MCSectionMachO.h @@ -0,0 +1,179 @@ +//===- MCSectionMachO.h - MachO Machine Code Sections -----------*- 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 MCSectionMachO class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONMACHO_H +#define LLVM_MC_MCSECTIONMACHO_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// MCSectionMachO - This represents a section on a Mach-O system (used by +/// Mac OS X). On a Mac system, these are also described in +/// /usr/include/mach-o/loader.h. +class MCSectionMachO : public MCSection { + char SegmentName[16]; // Not necessarily null terminated! + char SectionName[16]; // Not necessarily null terminated! + + /// TypeAndAttributes - This is the SECTION_TYPE and SECTION_ATTRIBUTES + /// field of a section, drawn from the enums below. + unsigned TypeAndAttributes; + + /// Reserved2 - The 'reserved2' field of a section, used to represent the + /// size of stubs, for example. + unsigned Reserved2; + + MCSectionMachO(StringRef Segment, StringRef Section, + unsigned TAA, unsigned reserved2, SectionKind K); + friend class MCContext; +public: + + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum { + // TypeAndAttributes bitmasks. + SECTION_TYPE = 0x000000FFU, + SECTION_ATTRIBUTES = 0xFFFFFF00U, + + // Valid section types. + + /// S_REGULAR - Regular section. + S_REGULAR = 0x00U, + /// S_ZEROFILL - Zero fill on demand section. + S_ZEROFILL = 0x01U, + /// S_CSTRING_LITERALS - Section with literal C strings. + S_CSTRING_LITERALS = 0x02U, + /// S_4BYTE_LITERALS - Section with 4 byte literals. + S_4BYTE_LITERALS = 0x03U, + /// S_8BYTE_LITERALS - Section with 8 byte literals. + S_8BYTE_LITERALS = 0x04U, + /// S_LITERAL_POINTERS - Section with pointers to literals. + S_LITERAL_POINTERS = 0x05U, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. + S_NON_LAZY_SYMBOL_POINTERS = 0x06U, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. + S_LAZY_SYMBOL_POINTERS = 0x07U, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. + S_SYMBOL_STUBS = 0x08U, + /// S_SYMBOL_STUBS - Section with only function pointers for + /// initialization. + S_MOD_INIT_FUNC_POINTERS = 0x09U, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// termination. + S_MOD_TERM_FUNC_POINTERS = 0x0AU, + /// S_COALESCED - Section contains symbols that are to be coalesced. + S_COALESCED = 0x0BU, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). + S_GB_ZEROFILL = 0x0CU, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. + S_INTERPOSING = 0x0DU, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. + S_16BYTE_LITERALS = 0x0EU, + /// S_DTRACE_DOF - Section contains DTrace Object Format. + S_DTRACE_DOF = 0x0FU, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. + S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10U, + /// S_THREAD_LOCAL_REGULAR - Section with .... + S_THREAD_LOCAL_REGULAR = 0x11U, + /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. + S_THREAD_LOCAL_ZEROFILL = 0x12U, + /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable structure + /// data. + S_THREAD_LOCAL_VARIABLES = 0x13U, + /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with .... + S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14U, + /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local + /// variable initialization pointers to functions. + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15U, + + LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, + + + // Valid section attributes. + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. + S_ATTR_PURE_INSTRUCTIONS = 1U << 31, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. + S_ATTR_NO_TOC = 1U << 30, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. + S_ATTR_STRIP_STATIC_SYMS = 1U << 29, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. + S_ATTR_NO_DEAD_STRIP = 1U << 28, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. + S_ATTR_LIVE_SUPPORT = 1U << 27, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. + S_ATTR_SELF_MODIFYING_CODE = 1U << 26, + /// S_ATTR_DEBUG - A debug section. + S_ATTR_DEBUG = 1U << 25, + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. + S_ATTR_SOME_INSTRUCTIONS = 1U << 10, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. + S_ATTR_EXT_RELOC = 1U << 9, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. + S_ATTR_LOC_RELOC = 1U << 8 + }; + + StringRef getSegmentName() const { + // SegmentName is not necessarily null terminated! + if (SegmentName[15]) + return StringRef(SegmentName, 16); + return StringRef(SegmentName); + } + StringRef getSectionName() const { + // SectionName is not necessarily null terminated! + if (SectionName[15]) + return StringRef(SectionName, 16); + return StringRef(SectionName); + } + + unsigned getTypeAndAttributes() const { return TypeAndAttributes; } + unsigned getStubSize() const { return Reserved2; } + + unsigned getType() const { return TypeAndAttributes & SECTION_TYPE; } + bool hasAttribute(unsigned Value) const { + return (TypeAndAttributes & Value) != 0; + } + + /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". + /// This is a string that can appear after a .section directive in a mach-o + /// flavored .s file. If successful, this fills in the specified Out + /// parameters and returns an empty string. When an invalid section + /// specifier is present, this returns a string indicating the problem. + static std::string ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize); // Out. + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + virtual bool UseCodeAlign() const; + virtual bool isVirtualSection() const; + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_MachO; + } + static bool classof(const MCSectionMachO *) { return true; } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCStreamer.h b/final/include/llvm/MC/MCStreamer.h new file mode 100644 index 00000000000..4fdbc44b25e --- /dev/null +++ b/final/include/llvm/MC/MCStreamer.h @@ -0,0 +1,544 @@ +//===- MCStreamer.h - High-level Streaming Machine Code Output --*- 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 MCStreamer class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSTREAMER_H +#define LLVM_MC_MCSTREAMER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" + +namespace llvm { + class MCAsmInfo; + class MCCodeEmitter; + class MCContext; + class MCExpr; + class MCInst; + class MCInstPrinter; + class MCSection; + class MCSymbol; + class StringRef; + class TargetAsmBackend; + class TargetLoweringObjectFile; + class Twine; + class raw_ostream; + class formatted_raw_ostream; + + /// MCStreamer - Streaming machine code generation interface. This interface + /// is intended to provide a programatic interface that is very similar to the + /// level that an assembler .s file provides. It has callbacks to emit bytes, + /// handle directives, etc. The implementation of this interface retains + /// state to know what the current section is etc. + /// + /// There are multiple implementations of this interface: one for writing out + /// a .s file, and implementations that write out .o files of various formats. + /// + class MCStreamer { + MCContext &Context; + + MCStreamer(const MCStreamer&); // DO NOT IMPLEMENT + MCStreamer &operator=(const MCStreamer&); // DO NOT IMPLEMENT + + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace); + + std::vector FrameInfos; + MCDwarfFrameInfo *getCurrentFrameInfo(); + void EnsureValidFrame(); + + /// SectionStack - This is stack of current and previous section + /// values saved by PushSection. + SmallVector, 4> SectionStack; + + protected: + MCStreamer(MCContext &Ctx); + + public: + virtual ~MCStreamer(); + + MCContext &getContext() const { return Context; } + + unsigned getNumFrameInfos() { + return FrameInfos.size(); + } + + const MCDwarfFrameInfo &getFrameInfo(unsigned i) { + return FrameInfos[i]; + } + + /// @name Assembly File Formatting. + /// @{ + + /// isVerboseAsm - Return true if this streamer supports verbose assembly + /// and if it is enabled. + virtual bool isVerboseAsm() const { return false; } + + /// hasRawTextSupport - Return true if this asm streamer supports emitting + /// unformatted text to the .s file with EmitRawText. + virtual bool hasRawTextSupport() const { return false; } + + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + /// + /// If the comment includes embedded \n's, they will each get the comment + /// prefix as appropriate. The added comment should not end with a \n. + virtual void AddComment(const Twine &T) {} + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS(); + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() {} + + /// @} + + /// @name Symbol & Section Management + /// @{ + + /// getCurrentSection - Return the current section that the streamer is + /// emitting code to. + const MCSection *getCurrentSection() const { + if (!SectionStack.empty()) + return SectionStack.back().first; + return NULL; + } + + /// getPreviousSection - Return the previous section that the streamer is + /// emitting code to. + const MCSection *getPreviousSection() const { + if (!SectionStack.empty()) + return SectionStack.back().second; + return NULL; + } + + /// ChangeSection - Update streamer for a new active section. + /// + /// This is called by PopSection and SwitchSection, if the current + /// section changes. + virtual void ChangeSection(const MCSection *) = 0; + + /// pushSection - Save the current and previous section on the + /// section stack. + void PushSection() { + SectionStack.push_back(std::make_pair(getCurrentSection(), + getPreviousSection())); + } + + /// popSection - Restore the current and previous section from + /// the section stack. Calls ChangeSection as needed. + /// + /// Returns false if the stack was empty. + bool PopSection() { + if (SectionStack.size() <= 1) + return false; + const MCSection *oldSection = SectionStack.pop_back_val().first; + const MCSection *curSection = SectionStack.back().first; + + if (oldSection != curSection) + ChangeSection(curSection); + return true; + } + + /// SwitchSection - Set the current section where code is being emitted to + /// @p Section. This is required to update CurSection. + /// + /// This corresponds to assembler directives like .section, .text, etc. + void SwitchSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + const MCSection *curSection = SectionStack.back().first; + SectionStack.back().second = curSection; + if (Section != curSection) { + SectionStack.back().first = Section; + ChangeSection(Section); + } + } + + /// InitSections - Create the default sections and set the initial one. + virtual void InitSections() = 0; + + /// EmitLabel - Emit a label for @p Symbol into the current section. + /// + /// This corresponds to an assembler statement such as: + /// foo: + /// + /// @param Symbol - The symbol to emit. A given symbol should only be + /// emitted as a label once, and symbols emitted as a label should never be + /// used in an assignment. + virtual void EmitLabel(MCSymbol *Symbol) = 0; + + /// EmitAssemblerFlag - Note in the output the specified @p Flag + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + + /// EmitThumbFunc - Note in the output that the specified @p Func is + /// a Thumb mode function (ARM target only). + virtual void EmitThumbFunc(MCSymbol *Func) = 0; + + /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// symbol = value + /// + /// The assignment generates no code, but has the side effect of binding the + /// value in the current context. For the assembly streamer, this prints the + /// binding into the .s file. + /// + /// @param Symbol - The symbol being assigned to. + /// @param Value - The value for the symbol. + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// + /// This corresponds to an assembler statement such as: + /// .weakref alias, symbol + /// + /// @param Alias - The alias that is being created. + /// @param Symbol - The symbol being aliased. + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + + /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + virtual void EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) = 0; + + /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// + /// @param Symbol - The symbol to have its n_desc field set. + /// @param DescValue - The value to set into the n_desc field. + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + + /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// + /// @param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + + /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// + /// @param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; + + /// EmitCOFFSymbolType - Emit the type of the symbol. + /// + /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type) = 0; + + /// EndCOFFSymbolDef - Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef() = 0; + + /// EmitELFSize - Emit an ELF .size directive. + /// + /// This corresponds to an assembler statement such as: + /// .size symbol, expression + /// + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + + /// EmitCommonSymbol - Emit a common symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + /// @param ByteAlignment - The alignment of the symbol if + /// non-zero. This must be a power of 2. + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) = 0; + + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0; + + /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param ByteAlignment - The alignment of the zerofill symbol if + /// non-zero. This must be a power of 2 on some targets. + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0,unsigned ByteAlignment = 0) = 0; + + /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// + /// @param Section - The thread local common section. + /// @param Symbol - The thread local common symbol to emit. + /// @param Size - The size of the symbol. + /// @param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) = 0; + /// @} + /// @name Generating Data + /// @{ + + /// EmitBytes - Emit the bytes in \arg Data into the output. + /// + /// This is used to implement assembler directives such as .byte, .ascii, + /// etc. + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) = 0; + + /// EmitValue - Emit the expression @p Value into the output as a native + /// integer of the given @p Size bytes. + /// + /// This is used to implement assembler directives such as .word, .quad, + /// etc. + /// + /// @param Value - The value to emit. + /// @param Size - The size of the integer (in bytes) to emit. This must + /// match a native machine width. + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) = 0; + + void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); + + void EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); + + /// EmitIntValue - Special case of EmitValue that avoids the client having + /// to pass in a MCExpr for constant integers. + virtual void EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace = 0); + + /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO + /// this is done by producing + /// foo = value + /// .long foo + void EmitAbsValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace = 0); + + virtual void EmitULEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) = 0; + + virtual void EmitSLEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) = 0; + + /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace = 0); + + /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the + /// client having to pass in a MCExpr for constant integers. + void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); + + /// EmitSymbolValue - Special case of EmitValue that avoids the client + /// having to pass in a MCExpr for MCSymbols. + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + + void EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace = 0); + + /// EmitGPRel32Value - Emit the expression @p Value into the output as a + /// gprel32 (32-bit GP relative) value. + /// + /// This is used to implement assembler directives such as .gprel32 on + /// targets that support them. + virtual void EmitGPRel32Value(const MCExpr *Value); + + /// EmitFill - Emit NumBytes bytes worth of the value specified by + /// FillValue. This implements directives such as '.space'. + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace); + + /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience + /// function that just wraps EmitFill. + void EmitZeros(uint64_t NumBytes, unsigned AddrSpace) { + EmitFill(NumBytes, 0, AddrSpace); + } + + + /// EmitValueToAlignment - Emit some number of copies of @p Value until + /// the byte alignment @p ByteAlignment is reached. + /// + /// If the number of bytes need to emit for the alignment is not a multiple + /// of @p ValueSize, then the contents of the emitted fill bytes is + /// undefined. + /// + /// This used to implement the .align assembler directive. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param Value - The value to use when filling bytes. + /// @param ValueSize - The size of the integer (in bytes) to emit for + /// @p Value. This must match a native machine width. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment + /// is reached. + /// + /// This used to align code where the alignment bytes may be executed. This + /// can emit different bytes for different sizes to optimize execution. + /// + /// @param ByteAlignment - The alignment to reach. This must be a power of + /// two on some targets. + /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// the alignment cannot be reached in this many bytes, no bytes are + /// emitted. + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) = 0; + + /// EmitValueToOffset - Emit some number of copies of @p Value until the + /// byte offset @p Offset is reached. + /// + /// This is used to implement assembler directives such as .org. + /// + /// @param Offset - The offset to reach. This may be an expression, but the + /// expression must be associated with the current section. + /// @param Value - The value to use when filling bytes. + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) = 0; + + /// @} + + /// EmitFileDirective - Switch to a new logical file. This is used to + /// implement the '.file "foo.c"' assembler directive. + virtual void EmitFileDirective(StringRef Filename) = 0; + + /// EmitDwarfFileDirective - Associate a filename with a specified logical + /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler + /// directive. + virtual bool EmitDwarfFileDirective(unsigned FileNo,StringRef Filename); + + /// EmitDwarfLocDirective - This implements the DWARF2 + // '.loc fileno lineno ...' assembler directive. + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator); + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) = 0; + + virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) { + } + + void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, + int PointerSize); + + virtual bool EmitCFIStartProc(); + virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual bool EmitCFIDefCfaOffset(int64_t Offset); + virtual bool EmitCFIDefCfaRegister(int64_t Register); + virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); + virtual bool EmitCFIPersonality(const MCSymbol *Sym, + unsigned Encoding); + virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual bool EmitCFIRememberState(); + virtual bool EmitCFIRestoreState(); + + /// EmitInstruction - Emit the given @p Instruction into the current + /// section. + virtual void EmitInstruction(const MCInst &Inst) = 0; + + /// EmitRawText - If this file is backed by a assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. By default this aborts. + virtual void EmitRawText(StringRef String); + void EmitRawText(const Twine &String); + + /// ARM-related methods. + /// FIXME: Eventually we should have some "target MC streamer" and move + /// these methods there. + virtual void EmitFnStart(); + virtual void EmitFnEnd(); + virtual void EmitCantUnwind(); + virtual void EmitPersonality(const MCSymbol *Personality); + virtual void EmitHandlerData(); + virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); + virtual void EmitPad(int64_t Offset); + virtual void EmitRegSave(const SmallVectorImpl &RegList, + bool isVector); + + /// Finish - Finish emission of machine code. + virtual void Finish() = 0; + }; + + /// createNullStreamer - Create a dummy machine code streamer, which does + /// nothing. This is useful for timing the assembler front end. + MCStreamer *createNullStreamer(MCContext &Ctx); + + /// createAsmStreamer - Create a machine code streamer which will print out + /// assembly for the native target, suitable for compiling with a native + /// assembler. + /// + /// \param InstPrint - If given, the instruction printer to use. If not given + /// the MCInst representation will be printed. This method takes ownership of + /// InstPrint. + /// + /// \param CE - If given, a code emitter to use to show the instruction + /// encoding inline with the assembly. This method takes ownership of \arg CE. + /// + /// \param TAB - If given, a target asm backend to use to show the fixup + /// information in conjunction with encoding information. This method takes + /// ownership of \arg TAB. + /// + /// \param ShowInst - Whether to show the MCInst representation inline with + /// the assembly. + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint = 0, + MCCodeEmitter *CE = 0, + TargetAsmBackend *TAB = 0, + bool ShowInst = false); + + /// createMachOStreamer - Create a machine code streamer which will generate + /// Mach-O format object files. + /// + /// Takes ownership of \arg TAB and \arg CE. + MCStreamer *createMachOStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll = false); + + /// createWinCOFFStreamer - Create a machine code streamer which will + /// generate Microsoft COFF format object files. + /// + /// Takes ownership of \arg TAB and \arg CE. + MCStreamer *createWinCOFFStreamer(MCContext &Ctx, + TargetAsmBackend &TAB, + MCCodeEmitter &CE, raw_ostream &OS, + bool RelaxAll = false); + + /// createELFStreamer - Create a machine code streamer which will generate + /// ELF format object files. + MCStreamer *createELFStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack); + + /// createLoggingStreamer - Create a machine code streamer which just logs the + /// API calls and then dispatches to another streamer. + /// + /// The new streamer takes ownership of the \arg Child. + MCStreamer *createLoggingStreamer(MCStreamer *Child, raw_ostream &OS); + + /// createPureStreamer - Create a machine code streamer which will generate + /// "pure" MC object files, for use with MC-JIT and testing tools. + /// + /// Takes ownership of \arg TAB and \arg CE. + MCStreamer *createPureStreamer(MCContext &Ctx, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE); + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCSymbol.h b/final/include/llvm/MC/MCSymbol.h new file mode 100644 index 00000000000..7da4d7c15e3 --- /dev/null +++ b/final/include/llvm/MC/MCSymbol.h @@ -0,0 +1,163 @@ +//===- MCSymbol.h - Machine Code Symbols ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCSymbol class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSYMBOL_H +#define LLVM_MC_MCSYMBOL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class MCExpr; + class MCSection; + class MCContext; + class raw_ostream; + + /// MCSymbol - Instances of this class represent a symbol name in the MC file, + /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols + /// should only be constructed with valid names for the object file. + /// + /// If the symbol is defined/emitted into the current translation unit, the + /// Section member is set to indicate what section it lives in. Otherwise, if + /// it is a reference to an external entity, it has a null section. + class MCSymbol { + // Special sentinal value for the absolute pseudo section. + // + // FIXME: Use a PointerInt wrapper for this? + static const MCSection *AbsolutePseudoSection; + + /// Name - The name of the symbol. The referred-to string data is actually + /// held by the StringMap that lives in MCContext. + StringRef Name; + + /// Section - The section the symbol is defined in. This is null for + /// undefined symbols, and the special AbsolutePseudoSection value for + /// absolute symbols. + const MCSection *Section; + + /// Value - If non-null, the value for a variable symbol. + const MCExpr *Value; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCSymbol(StringRef name, bool isTemporary) + : Name(name), Section(0), Value(0), + IsTemporary(isTemporary), IsUsed(false) {} + + MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT + void operator=(const MCSymbol&); // DO NOT IMPLEMENT + public: + /// getName - Get the symbol name. + StringRef getName() const { return Name; } + + /// @name Accessors + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { return IsTemporary; } + + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + void setUsed(bool Value) const { IsUsed = Value; } + + /// @} + /// @name Associated Sections + /// @{ + + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { + return Section != 0; + } + + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { + return isDefined() && !isAbsolute(); + } + + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined() const { + return !isDefined(); + } + + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { + return Section == AbsolutePseudoSection; + } + + /// getSection - Get the section associated with a defined, non-absolute + /// symbol. + const MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *Section; + } + + /// setSection - Mark the symbol as defined in the section \arg S. + void setSection(const MCSection &S) { Section = &S; } + + /// setUndefined - Mark the symbol as undefined. + void setUndefined() { + Section = 0; + } + + /// setAbsolute - Mark the symbol as absolute. + void setAbsolute() { Section = AbsolutePseudoSection; } + + /// @} + /// @name Variable Symbols + /// @{ + + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { + return Value != 0; + } + + /// getValue() - Get the value for variable symbols. + const MCExpr *getVariableValue() const { + assert(isVariable() && "Invalid accessor!"); + IsUsed = true; + return Value; + } + + // AliasedSymbol() - If this is an alias (a = b), return the symbol + // we ultimately point to. For a non alias, this just returns the symbol + // itself. + const MCSymbol &AliasedSymbol() const; + + void setVariableValue(const MCExpr *Value); + + /// @} + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS); + return OS; + } +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/MCValue.h b/final/include/llvm/MC/MCValue.h new file mode 100644 index 00000000000..df8dbd930bf --- /dev/null +++ b/final/include/llvm/MC/MCValue.h @@ -0,0 +1,87 @@ +//===-- llvm/MC/MCValue.h - MCValue class -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCVALUE_H +#define LLVM_MC_MCVALUE_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/MC/MCSymbol.h" +#include + +namespace llvm { +class MCAsmInfo; +class MCSymbol; +class MCSymbolRefExpr; +class raw_ostream; + +/// MCValue - This represents an "assembler immediate". In its most general +/// form, this can hold "SymbolA - SymbolB + imm64". Not all targets supports +/// relocations of this general form, but we need to represent this anyway. +/// +/// In the general form, SymbolB can only be defined if SymbolA is, and both +/// must be in the same (non-external) section. The latter constraint is not +/// enforced, since a symbol's section may not be known at construction. +/// +/// Note that this class must remain a simple POD value class, because we need +/// it to live in unions etc. +class MCValue { + const MCSymbolRefExpr *SymA, *SymB; + int64_t Cst; +public: + + int64_t getConstant() const { return Cst; } + const MCSymbolRefExpr *getSymA() const { return SymA; } + const MCSymbolRefExpr *getSymB() const { return SymB; } + + /// isAbsolute - Is this an absolute (as opposed to relocatable) value. + bool isAbsolute() const { return !SymA && !SymB; } + + /// getAssociatedSection - For relocatable values, return the section the + /// value is associated with. + /// + /// @result - The value's associated section, or null for external or constant + /// values. + // + // FIXME: Switch to a tagged section, so this can return the tagged section + // value. + const MCSection *getAssociatedSection() const; + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; + + /// dump - Print the value to stderr. + void dump() const; + + static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=0, + int64_t Val = 0) { + MCValue R; + assert((!SymB || SymA) && "Invalid relocatable MCValue!"); + R.Cst = Val; + R.SymA = SymA; + R.SymB = SymB; + return R; + } + + static MCValue get(int64_t Val) { + MCValue R; + R.Cst = Val; + R.SymA = 0; + R.SymB = 0; + return R; + } + +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/MC/SectionKind.h b/final/include/llvm/MC/SectionKind.h new file mode 100644 index 00000000000..85a91c6b169 --- /dev/null +++ b/final/include/llvm/MC/SectionKind.h @@ -0,0 +1,240 @@ +//===-- llvm/Target/TargetLoweringObjectFile.h - Object 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 implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_SECTIONKIND_H +#define LLVM_MC_SECTIONKIND_H + +namespace llvm { + +/// SectionKind - This is a simple POD value that classifies the properties of +/// a section. A section is classified into the deepest possible +/// classification, and then the target maps them onto their sections based on +/// what capabilities they have. +/// +/// The comments below describe these as if they were an inheritance hierarchy +/// in order to explain the predicates below. +/// +class SectionKind { + enum Kind { + /// Metadata - Debug info sections or other metadata. + Metadata, + + /// Text - Text section, used for functions and other executable code. + Text, + + /// ReadOnly - Data that is never written to at program runtime by the + /// program or the dynamic linker. Things in the top-level readonly + /// SectionKind are not mergeable. + ReadOnly, + + /// MergableCString - Any null-terminated string which allows merging. + /// These values are known to end in a nul value of the specified size, + /// not otherwise contain a nul value, and be mergable. This allows the + /// linker to unique the strings if it so desires. + + /// Mergeable1ByteCString - 1 byte mergable, null terminated, string. + Mergeable1ByteCString, + + /// Mergeable2ByteCString - 2 byte mergable, null terminated, string. + Mergeable2ByteCString, + + /// Mergeable4ByteCString - 4 byte mergable, null terminated, string. + Mergeable4ByteCString, + + /// MergeableConst - These are sections for merging fixed-length + /// constants together. For example, this can be used to unique + /// constant pool entries etc. + MergeableConst, + + /// MergeableConst4 - This is a section used by 4-byte constants, + /// for example, floats. + MergeableConst4, + + /// MergeableConst8 - This is a section used by 8-byte constants, + /// for example, doubles. + MergeableConst8, + + /// MergeableConst16 - This is a section used by 16-byte constants, + /// for example, vectors. + MergeableConst16, + + /// Writeable - This is the base of all segments that need to be written + /// to during program runtime. + + /// ThreadLocal - This is the base of all TLS segments. All TLS + /// objects must be writeable, otherwise there is no reason for them to + /// be thread local! + + /// ThreadBSS - Zero-initialized TLS data objects. + ThreadBSS, + + /// ThreadData - Initialized TLS data objects. + ThreadData, + + /// GlobalWriteableData - Writeable data that is global (not thread + /// local). + + /// BSS - Zero initialized writeable data. + BSS, + + /// BSSLocal - This is BSS (zero initialized and writable) data + /// which has local linkage. + BSSLocal, + + /// BSSExtern - This is BSS data with normal external linkage. + BSSExtern, + + /// Common - Data with common linkage. These represent tentative + /// definitions, which always have a zero initializer and are never + /// marked 'constant'. + Common, + + /// DataRel - This is the most general form of data that is written + /// to by the program, it can have random relocations to arbitrary + /// globals. + DataRel, + + /// DataRelLocal - This is writeable data that has a non-zero + /// initializer and has relocations in it, but all of the + /// relocations are known to be within the final linked image + /// the global is linked into. + DataRelLocal, + + /// DataNoRel - This is writeable data that has a non-zero + /// initializer, but whose initializer is known to have no + /// relocations. + DataNoRel, + + /// ReadOnlyWithRel - These are global variables that are never + /// written to by the program, but that have relocations, so they + /// must be stuck in a writeable section so that the dynamic linker + /// can write to them. If it chooses to, the dynamic linker can + /// mark the pages these globals end up on as read-only after it is + /// done with its relocation phase. + ReadOnlyWithRel, + + /// ReadOnlyWithRelLocal - This is data that is readonly by the + /// program, but must be writeable so that the dynamic linker + /// can perform relocations in it. This is used when we know + /// that all the relocations are to globals in this final + /// linked image. + ReadOnlyWithRelLocal + + } K : 8; +public: + + bool isMetadata() const { return K == Metadata; } + bool isText() const { return K == Text; } + + bool isReadOnly() const { + return K == ReadOnly || isMergeableCString() || + isMergeableConst(); + } + + bool isMergeableCString() const { + return K == Mergeable1ByteCString || K == Mergeable2ByteCString || + K == Mergeable4ByteCString; + } + bool isMergeable1ByteCString() const { return K == Mergeable1ByteCString; } + bool isMergeable2ByteCString() const { return K == Mergeable2ByteCString; } + bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } + + bool isMergeableConst() const { + return K == MergeableConst || K == MergeableConst4 || + K == MergeableConst8 || K == MergeableConst16; + } + bool isMergeableConst4() const { return K == MergeableConst4; } + bool isMergeableConst8() const { return K == MergeableConst8; } + bool isMergeableConst16() const { return K == MergeableConst16; } + + bool isWriteable() const { + return isThreadLocal() || isGlobalWriteableData(); + } + + bool isThreadLocal() const { + return K == ThreadData || K == ThreadBSS; + } + + bool isThreadBSS() const { return K == ThreadBSS; } + bool isThreadData() const { return K == ThreadData; } + + bool isGlobalWriteableData() const { + return isBSS() || isCommon() || isDataRel() || isReadOnlyWithRel(); + } + + bool isBSS() const { return K == BSS || K == BSSLocal || K == BSSExtern; } + bool isBSSLocal() const { return K == BSSLocal; } + bool isBSSExtern() const { return K == BSSExtern; } + + bool isCommon() const { return K == Common; } + + bool isDataRel() const { + return K == DataRel || K == DataRelLocal || K == DataNoRel; + } + + bool isDataRelLocal() const { + return K == DataRelLocal || K == DataNoRel; + } + + bool isDataNoRel() const { return K == DataNoRel; } + + bool isReadOnlyWithRel() const { + return K == ReadOnlyWithRel || K == ReadOnlyWithRelLocal; + } + + bool isReadOnlyWithRelLocal() const { + return K == ReadOnlyWithRelLocal; + } +private: + static SectionKind get(Kind K) { + SectionKind Res; + Res.K = K; + return Res; + } +public: + + static SectionKind getMetadata() { return get(Metadata); } + static SectionKind getText() { return get(Text); } + static SectionKind getReadOnly() { return get(ReadOnly); } + static SectionKind getMergeable1ByteCString() { + return get(Mergeable1ByteCString); + } + static SectionKind getMergeable2ByteCString() { + return get(Mergeable2ByteCString); + } + static SectionKind getMergeable4ByteCString() { + return get(Mergeable4ByteCString); + } + static SectionKind getMergeableConst() { return get(MergeableConst); } + static SectionKind getMergeableConst4() { return get(MergeableConst4); } + static SectionKind getMergeableConst8() { return get(MergeableConst8); } + static SectionKind getMergeableConst16() { return get(MergeableConst16); } + static SectionKind getThreadBSS() { return get(ThreadBSS); } + static SectionKind getThreadData() { return get(ThreadData); } + static SectionKind getBSS() { return get(BSS); } + static SectionKind getBSSLocal() { return get(BSSLocal); } + static SectionKind getBSSExtern() { return get(BSSExtern); } + static SectionKind getCommon() { return get(Common); } + static SectionKind getDataRel() { return get(DataRel); } + static SectionKind getDataRelLocal() { return get(DataRelLocal); } + static SectionKind getDataNoRel() { return get(DataNoRel); } + static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); } + static SectionKind getReadOnlyWithRelLocal(){ + return get(ReadOnlyWithRelLocal); + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Metadata.h b/final/include/llvm/Metadata.h new file mode 100644 index 00000000000..6a61996ff76 --- /dev/null +++ b/final/include/llvm/Metadata.h @@ -0,0 +1,237 @@ +//===-- llvm/Metadata.h - Metadata definitions ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declarations for metadata subclasses. +/// They represent the different flavors of metadata that live in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_METADATA_H +#define LLVM_METADATA_H + +#include "llvm/Value.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ilist_node.h" + +namespace llvm { +class Constant; +class Instruction; +class LLVMContext; +class Module; +template class SmallVectorImpl; +template + class SymbolTableListTraits; + + +//===----------------------------------------------------------------------===// +/// MDString - a single uniqued string. +/// These are used to efficiently contain a byte sequence for metadata. +/// MDString is always unnamd. +class MDString : public Value { + MDString(const MDString &); // DO NOT IMPLEMENT + + StringRef Str; + explicit MDString(LLVMContext &C, StringRef S); + +public: + static MDString *get(LLVMContext &Context, StringRef Str); + static MDString *get(LLVMContext &Context, const char *Str) { + return get(Context, Str ? StringRef(Str) : StringRef()); + } + + StringRef getString() const { return Str; } + + unsigned getLength() const { return (unsigned)Str.size(); } + + typedef StringRef::iterator iterator; + + /// begin() - Pointer to the first byte of the string. + /// + iterator begin() const { return Str.begin(); } + + /// end() - Pointer to one byte past the end of the string. + /// + iterator end() const { return Str.end(); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MDString *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == MDStringVal; + } +}; + + +class MDNodeOperand; + +//===----------------------------------------------------------------------===// +/// MDNode - a tuple of other values. +class MDNode : public Value, public FoldingSetNode { + MDNode(const MDNode &); // DO NOT IMPLEMENT + void operator=(const MDNode &); // DO NOT IMPLEMENT + friend class MDNodeOperand; + friend class LLVMContextImpl; + + /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the + /// end of this MDNode. + unsigned NumOperands; + + // Subclass data enums. + enum { + /// FunctionLocalBit - This bit is set if this MDNode is function local. + /// This is true when it (potentially transitively) contains a reference to + /// something in a function, like an argument, basicblock, or instruction. + FunctionLocalBit = 1 << 0, + + /// NotUniquedBit - This is set on MDNodes that are not uniqued because they + /// have a null operand. + NotUniquedBit = 1 << 1, + + /// DestroyFlag - This bit is set by destroy() so the destructor can assert + /// that the node isn't being destroyed with a plain 'delete'. + DestroyFlag = 1 << 2 + }; + + // FunctionLocal enums. + enum FunctionLocalness { + FL_Unknown = -1, + FL_No = 0, + FL_Yes = 1 + }; + + /// replaceOperand - Replace each instance of F from the operand list of this + /// node with T. + void replaceOperand(MDNodeOperand *Op, Value *NewVal); + ~MDNode(); + + MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, + bool isFunctionLocal); + + static MDNode *getMDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, + FunctionLocalness FL, bool Insert = true); +public: + // Constructors and destructors. + static MDNode *get(LLVMContext &Context, ArrayRef V); + // FIXME: Eliminate this constructor form. + static MDNode *get(LLVMContext &Context, Value *const *Vals, + unsigned NumVals); + // getWhenValsUnresolved - Construct MDNode determining function-localness + // from isFunctionLocal argument, not by analyzing Vals. + static MDNode *getWhenValsUnresolved(LLVMContext &Context, Value *const *Vals, + unsigned NumVals, bool isFunctionLocal); + + static MDNode *getIfExists(LLVMContext &Context, Value *const *Vals, + unsigned NumVals); + + /// getTemporary - Return a temporary MDNode, for use in constructing + /// cyclic MDNode structures. A temporary MDNode is not uniqued, + /// may be RAUW'd, and must be manually deleted with deleteTemporary. + static MDNode *getTemporary(LLVMContext &Context, Value *const *Vals, + unsigned NumVals); + + /// deleteTemporary - Deallocate a node created by getTemporary. The + /// node must not have any users. + static void deleteTemporary(MDNode *N); + + /// getOperand - Return specified operand. + Value *getOperand(unsigned i) const; + + /// getNumOperands - Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } + + /// isFunctionLocal - Return whether MDNode is local to a function. + bool isFunctionLocal() const { + return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + } + + // getFunction - If this metadata is function-local and recursively has a + // function-local operand, return the first such operand's parent function. + // Otherwise, return null. getFunction() should not be used for performance- + // critical code because it recursively visits all the MDNode's operands. + const Function *getFunction() const; + + /// Profile - calculate a unique identifier for this MDNode to collapse + /// duplicates + void Profile(FoldingSetNodeID &ID) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MDNode *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == MDNodeVal; + } +private: + // destroy - Delete this node. Only when there are no uses. + void destroy(); + + bool isNotUniqued() const { + return (getSubclassDataFromValue() & NotUniquedBit) != 0; + } + void setIsNotUniqued(); + + // Shadow Value::setValueSubclassData with a private forwarding method so that + // any future subclasses cannot accidentally use it. + void setValueSubclassData(unsigned short D) { + Value::setValueSubclassData(D); + } +}; + +//===----------------------------------------------------------------------===// +/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't +/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain +/// lists of MDNodes. +class NamedMDNode : public ilist_node { + friend class SymbolTableListTraits; + friend struct ilist_traits; + friend class LLVMContextImpl; + friend class Module; + NamedMDNode(const NamedMDNode &); // DO NOT IMPLEMENT + + std::string Name; + Module *Parent; + void *Operands; // SmallVector, 4> + + void setParent(Module *M) { Parent = M; } + + explicit NamedMDNode(const Twine &N); + +public: + /// eraseFromParent - Drop all references and remove the node from parent + /// module. + void eraseFromParent(); + + /// dropAllReferences - Remove all uses and clear node vector. + void dropAllReferences(); + + /// ~NamedMDNode - Destroy NamedMDNode. + ~NamedMDNode(); + + /// getParent - Get the module that holds this named metadata collection. + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + /// getOperand - Return specified operand. + MDNode *getOperand(unsigned i) const; + + /// getNumOperands - Return the number of NamedMDNode operands. + unsigned getNumOperands() const; + + /// addOperand - Add metadata operand. + void addOperand(MDNode *M); + + /// getName - Return a constant reference to this named metadata's name. + StringRef getName() const; + + /// print - Implement operator<< on NamedMDNode. + void print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW = 0) const; +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Module.h b/final/include/llvm/Module.h new file mode 100644 index 00000000000..c7063f5e1c4 --- /dev/null +++ b/final/include/llvm/Module.h @@ -0,0 +1,556 @@ +//===-- llvm/Module.h - C++ class to represent a VM module ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// Module.h This file contains the declarations for the Module class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MODULE_H +#define LLVM_MODULE_H + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Metadata.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class FunctionType; +class GVMaterializer; +class LLVMContext; + +template<> struct ilist_traits + : public SymbolTableListTraits { + + // createSentinel is used to get hold of the node that marks the end of the + // list... (same trick used here as in ilist_traits) + Function *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(Function*) {} + + Function *provideInitialHead() const { return createSentinel(); } + Function *ensureHead(Function*) const { return createSentinel(); } + static void noteHead(Function*, Function*) {} + +private: + mutable ilist_node Sentinel; +}; +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to create a node that marks the end of the list. + static GlobalVariable *createSentinel(); + static void destroySentinel(GlobalVariable *GV) { delete GV; } +}; +template<> struct ilist_traits + : public SymbolTableListTraits { + // createSentinel is used to create a node that marks the end of the list. + static GlobalAlias *createSentinel(); + static void destroySentinel(GlobalAlias *GA) { delete GA; } +}; + +template<> struct ilist_traits + : public ilist_default_traits { + // createSentinel is used to get hold of a node that marks the end of + // the list... + NamedMDNode *createSentinel() const { + return static_cast(&Sentinel); + } + static void destroySentinel(NamedMDNode*) {} + + NamedMDNode *provideInitialHead() const { return createSentinel(); } + NamedMDNode *ensureHead(NamedMDNode*) const { return createSentinel(); } + static void noteHead(NamedMDNode*, NamedMDNode*) {} + void addNodeToList(NamedMDNode *) {} + void removeNodeFromList(NamedMDNode *) {} +private: + mutable ilist_node Sentinel; +}; + +/// A Module instance is used to store all the information related to an +/// LLVM module. Modules are the top level container of all other LLVM +/// Intermediate Representation (IR) objects. Each module directly contains a +/// list of globals variables, a list of functions, a list of libraries (or +/// other modules) this module depends on, a symbol table, and various data +/// about the target's characteristics. +/// +/// A module maintains a GlobalValRefMap object that is used to hold all +/// constant references to global variables in the module. When a global +/// variable is destroyed, it should have no entries in the GlobalValueRefMap. +/// @brief The main container class for the LLVM Intermediate Representation. +class Module { +/// @name Types And Enumerations +/// @{ +public: + /// The type for the list of global variables. + typedef iplist GlobalListType; + /// The type for the list of functions. + typedef iplist FunctionListType; + /// The type for the list of aliases. + typedef iplist AliasListType; + /// The type for the list of named metadata. + typedef ilist NamedMDListType; + + /// The type for the list of dependent libraries. + typedef std::vector LibraryListType; + + /// The Global Variable iterator. + typedef GlobalListType::iterator global_iterator; + /// The Global Variable constant iterator. + typedef GlobalListType::const_iterator const_global_iterator; + + /// The Function iterators. + typedef FunctionListType::iterator iterator; + /// The Function constant iterator + typedef FunctionListType::const_iterator const_iterator; + + /// The Global Alias iterators. + typedef AliasListType::iterator alias_iterator; + /// The Global Alias constant iterator + typedef AliasListType::const_iterator const_alias_iterator; + + /// The named metadata iterators. + typedef NamedMDListType::iterator named_metadata_iterator; + /// The named metadata constant interators. + typedef NamedMDListType::const_iterator const_named_metadata_iterator; + /// The Library list iterator. + typedef LibraryListType::const_iterator lib_iterator; + + /// An enumeration for describing the endianess of the target machine. + enum Endianness { AnyEndianness, LittleEndian, BigEndian }; + + /// An enumeration for describing the size of a pointer on the target machine. + enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; + +/// @} +/// @name Member Variables +/// @{ +private: + LLVMContext &Context; ///< The LLVMContext from which types and + ///< constants are allocated. + GlobalListType GlobalList; ///< The Global Variables in the module + FunctionListType FunctionList; ///< The Functions in the module + AliasListType AliasList; ///< The Aliases in the module + LibraryListType LibraryList; ///< The Libraries needed by the module + NamedMDListType NamedMDList; ///< The named metadata in the module + std::string GlobalScopeAsm; ///< Inline Asm at global scope. + ValueSymbolTable *ValSymTab; ///< Symbol table for values + TypeSymbolTable *TypeSymTab; ///< Symbol table for types + OwningPtr Materializer; ///< Used to materialize GlobalValues + std::string ModuleID; ///< Human readable identifier for the module + std::string TargetTriple; ///< Platform target triple Module compiled on + std::string DataLayout; ///< Target data description + void *NamedMDSymTab; ///< NamedMDNode names. + + friend class Constant; + +/// @} +/// @name Constructors +/// @{ +public: + /// The Module constructor. Note that there is no default constructor. You + /// must provide a name for the module upon construction. + explicit Module(StringRef ModuleID, LLVMContext& C); + /// The module destructor. This will dropAllReferences. + ~Module(); + +/// @} +/// @name Module Level Accessors +/// @{ + + /// Get the module identifier which is, essentially, the name of the module. + /// @returns the module identifier as a string + const std::string &getModuleIdentifier() const { return ModuleID; } + + /// Get the data layout string for the module's target platform. This encodes + /// the type sizes and alignments expected by this module. + /// @returns the data layout as a string + const std::string &getDataLayout() const { return DataLayout; } + + /// Get the target triple which is a string describing the target host. + /// @returns a string containing the target triple. + const std::string &getTargetTriple() const { return TargetTriple; } + + /// Get the target endian information. + /// @returns Endianess - an enumeration for the endianess of the target + Endianness getEndianness() const; + + /// Get the target pointer size. + /// @returns PointerSize - an enumeration for the size of the target's pointer + PointerSize getPointerSize() const; + + /// Get the global data context. + /// @returns LLVMContext - a container for LLVM's global information + LLVMContext &getContext() const { return Context; } + + /// Get any module-scope inline assembly blocks. + /// @returns a string containing the module-scope inline assembly blocks. + const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } + +/// @} +/// @name Module Level Mutators +/// @{ + + /// Set the module identifier. + void setModuleIdentifier(StringRef ID) { ModuleID = ID; } + + /// Set the data layout + void setDataLayout(StringRef DL) { DataLayout = DL; } + + /// Set the target triple. + void setTargetTriple(StringRef T) { TargetTriple = T; } + + /// Set the module-scope inline assembly blocks. + void setModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm = Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } + + /// Append to the module-scope inline assembly blocks, automatically inserting + /// a separating newline if necessary. + void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; + if (!GlobalScopeAsm.empty() && + GlobalScopeAsm[GlobalScopeAsm.size()-1] != '\n') + GlobalScopeAsm += '\n'; + } + +/// @} +/// @name Generic Value Accessors +/// @{ + + /// getNamedValue - Return the first global value in the module with + /// the specified name, of arbitrary type. This method returns null + /// if a global with the specified name is not found. + GlobalValue *getNamedValue(StringRef Name) const; + + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. + /// This ID is uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// getMDKindNames - Populate client supplied SmallVector with the name for + /// custom metadata IDs registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl &Result) const; + +/// @} +/// @name Function Accessors +/// @{ + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. Four possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. If it exists, and has a local linkage, the existing function is + /// renamed and a new one is inserted. + /// 3. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 4. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + Constant *getOrInsertFunction(StringRef Name, const FunctionType *T, + AttrListPtr AttributeList); + + Constant *getOrInsertFunction(StringRef Name, const FunctionType *T); + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. If it does not exist, add a prototype for the function and return + /// it. This function guarantees to return a constant of pointer to the + /// specified function type or a ConstantExpr BitCast of that type if the + /// named function has a different type. This version of the method takes a + /// null terminated list of function arguments, which makes it easier for + /// clients to use. + Constant *getOrInsertFunction(StringRef Name, + AttrListPtr AttributeList, + const Type *RetTy, ...) END_WITH_NULL; + + /// getOrInsertFunction - Same as above, but without the attributes. + Constant *getOrInsertFunction(StringRef Name, const Type *RetTy, ...) + END_WITH_NULL; + + Constant *getOrInsertTargetIntrinsic(StringRef Name, + const FunctionType *Ty, + AttrListPtr AttributeList); + + /// getFunction - Look up the specified function in the module symbol table. + /// If it does not exist, return null. + Function *getFunction(StringRef Name) const; + +/// @} +/// @name Global Variable Accessors +/// @{ + + /// getGlobalVariable - Look up the specified global variable in the module + /// symbol table. If it does not exist, return null. If AllowInternal is set + /// to true, this function will return types that have InternalLinkage. By + /// default, these types are not returned. + GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const; + + /// getNamedGlobal - Return the first global variable in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalVariable *getNamedGlobal(StringRef Name) const { + return getGlobalVariable(Name, true); + } + + /// getOrInsertGlobal - Look up the specified global in the module symbol + /// table. + /// 1. If it does not exist, add a declaration of the global and return it. + /// 2. Else, the global exists but has the wrong type: return the function + /// with a constantexpr cast to the right type. + /// 3. Finally, if the existing global is the correct delclaration, return + /// the existing global. + Constant *getOrInsertGlobal(StringRef Name, const Type *Ty); + +/// @} +/// @name Global Alias Accessors +/// @{ + + /// getNamedAlias - Return the first global alias in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalAlias *getNamedAlias(StringRef Name) const; + +/// @} +/// @name Named Metadata Accessors +/// @{ + + /// getNamedMetadata - Return the first NamedMDNode in the module with the + /// specified name. This method returns null if a NamedMDNode with the + /// specified name is not found. + NamedMDNode *getNamedMetadata(const Twine &Name) const; + + /// getOrInsertNamedMetadata - Return the first named MDNode in the module + /// with the specified name. This method returns a new NamedMDNode if a + /// NamedMDNode with the specified name is not found. + NamedMDNode *getOrInsertNamedMetadata(StringRef Name); + + /// eraseNamedMetadata - Remove the given NamedMDNode from this module + /// and delete it. + void eraseNamedMetadata(NamedMDNode *NMD); + +/// @} +/// @name Type Accessors +/// @{ + + /// addTypeName - Insert an entry in the symbol table mapping Str to Type. If + /// there is already an entry for this name, true is returned and the symbol + /// table is not modified. + bool addTypeName(StringRef Name, const Type *Ty); + + /// getTypeName - If there is at least one entry in the symbol table for the + /// specified type, return it. + std::string getTypeName(const Type *Ty) const; + + /// getTypeByName - Return the type with the specified name in this module, or + /// null if there is none by that name. + const Type *getTypeByName(StringRef Name) const; + +/// @} +/// @name Materialization +/// @{ + + /// setMaterializer - Sets the GVMaterializer to GVM. This module must not + /// yet have a Materializer. To reset the materializer for a module that + /// already has one, call MaterializeAllPermanently first. Destroying this + /// module will destroy its materializer without materializing any more + /// GlobalValues. Without destroying the Module, there is no way to detach or + /// destroy a materializer without materializing all the GVs it controls, to + /// avoid leaving orphan unmaterialized GVs. + void setMaterializer(GVMaterializer *GVM); + /// getMaterializer - Retrieves the GVMaterializer, if any, for this Module. + GVMaterializer *getMaterializer() const { return Materializer.get(); } + + /// isMaterializable - True if the definition of GV has yet to be materialized + /// from the GVMaterializer. + bool isMaterializable(const GlobalValue *GV) const; + /// isDematerializable - Returns true if this GV was loaded from this Module's + /// GVMaterializer and the GVMaterializer knows how to dematerialize the GV. + bool isDematerializable(const GlobalValue *GV) const; + + /// Materialize - Make sure the GlobalValue is fully read. If the module is + /// corrupt, this returns true and fills in the optional string with + /// information about the problem. If successful, this returns false. + bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0); + /// Dematerialize - If the GlobalValue is read in, and if the GVMaterializer + /// supports it, release the memory for the function, and set it up to be + /// materialized lazily. If !isDematerializable(), this method is a noop. + void Dematerialize(GlobalValue *GV); + + /// MaterializeAll - Make sure all GlobalValues in this Module are fully read. + /// If the module is corrupt, this returns true and fills in the optional + /// string with information about the problem. If successful, this returns + /// false. + bool MaterializeAll(std::string *ErrInfo = 0); + + /// MaterializeAllPermanently - Make sure all GlobalValues in this Module are + /// fully read and clear the Materializer. If the module is corrupt, this + /// returns true, fills in the optional string with information about the + /// problem, and DOES NOT clear the old Materializer. If successful, this + /// returns false. + bool MaterializeAllPermanently(std::string *ErrInfo = 0); + +/// @} +/// @name Direct access to the globals list, functions list, and symbol table +/// @{ + + /// Get the Module's list of global variables (constant). + const GlobalListType &getGlobalList() const { return GlobalList; } + /// Get the Module's list of global variables. + GlobalListType &getGlobalList() { return GlobalList; } + static iplist Module::*getSublistAccess(GlobalVariable*) { + return &Module::GlobalList; + } + /// Get the Module's list of functions (constant). + const FunctionListType &getFunctionList() const { return FunctionList; } + /// Get the Module's list of functions. + FunctionListType &getFunctionList() { return FunctionList; } + static iplist Module::*getSublistAccess(Function*) { + return &Module::FunctionList; + } + /// Get the Module's list of aliases (constant). + const AliasListType &getAliasList() const { return AliasList; } + /// Get the Module's list of aliases. + AliasListType &getAliasList() { return AliasList; } + static iplist Module::*getSublistAccess(GlobalAlias*) { + return &Module::AliasList; + } + /// Get the symbol table of global variable and function identifiers + const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } + /// Get the Module's symbol table of global variable and function identifiers. + ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + /// Get the symbol table of types + const TypeSymbolTable &getTypeSymbolTable() const { return *TypeSymTab; } + /// Get the Module's symbol table of types + TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; } + +/// @} +/// @name Global Variable Iteration +/// @{ + + /// Get an iterator to the first global variable + global_iterator global_begin() { return GlobalList.begin(); } + /// Get a constant iterator to the first global variable + const_global_iterator global_begin() const { return GlobalList.begin(); } + /// Get an iterator to the last global variable + global_iterator global_end () { return GlobalList.end(); } + /// Get a constant iterator to the last global variable + const_global_iterator global_end () const { return GlobalList.end(); } + /// Determine if the list of globals is empty. + bool global_empty() const { return GlobalList.empty(); } + +/// @} +/// @name Function Iteration +/// @{ + + /// Get an iterator to the first function. + iterator begin() { return FunctionList.begin(); } + /// Get a constant iterator to the first function. + const_iterator begin() const { return FunctionList.begin(); } + /// Get an iterator to the last function. + iterator end () { return FunctionList.end(); } + /// Get a constant iterator to the last function. + const_iterator end () const { return FunctionList.end(); } + /// Determine how many functions are in the Module's list of functions. + size_t size() const { return FunctionList.size(); } + /// Determine if the list of functions is empty. + bool empty() const { return FunctionList.empty(); } + +/// @} +/// @name Dependent Library Iteration +/// @{ + + /// @brief Get a constant iterator to beginning of dependent library list. + inline lib_iterator lib_begin() const { return LibraryList.begin(); } + /// @brief Get a constant iterator to end of dependent library list. + inline lib_iterator lib_end() const { return LibraryList.end(); } + /// @brief Returns the number of items in the list of libraries. + inline size_t lib_size() const { return LibraryList.size(); } + /// @brief Add a library to the list of dependent libraries + void addLibrary(StringRef Lib); + /// @brief Remove a library from the list of dependent libraries + void removeLibrary(StringRef Lib); + /// @brief Get all the libraries + inline const LibraryListType& getLibraries() const { return LibraryList; } + +/// @} +/// @name Alias Iteration +/// @{ + + /// Get an iterator to the first alias. + alias_iterator alias_begin() { return AliasList.begin(); } + /// Get a constant iterator to the first alias. + const_alias_iterator alias_begin() const { return AliasList.begin(); } + /// Get an iterator to the last alias. + alias_iterator alias_end () { return AliasList.end(); } + /// Get a constant iterator to the last alias. + const_alias_iterator alias_end () const { return AliasList.end(); } + /// Determine how many aliases are in the Module's list of aliases. + size_t alias_size () const { return AliasList.size(); } + /// Determine if the list of aliases is empty. + bool alias_empty() const { return AliasList.empty(); } + + +/// @} +/// @name Named Metadata Iteration +/// @{ + + /// Get an iterator to the first named metadata. + named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); } + /// Get a constant iterator to the first named metadata. + const_named_metadata_iterator named_metadata_begin() const { + return NamedMDList.begin(); + } + + /// Get an iterator to the last named metadata. + named_metadata_iterator named_metadata_end() { return NamedMDList.end(); } + /// Get a constant iterator to the last named metadata. + const_named_metadata_iterator named_metadata_end() const { + return NamedMDList.end(); + } + + /// Determine how many NamedMDNodes are in the Module's list of named + /// metadata. + size_t named_metadata_size() const { return NamedMDList.size(); } + /// Determine if the list of named metadata is empty. + bool named_metadata_empty() const { return NamedMDList.empty(); } + + +/// @} +/// @name Utility functions for printing and dumping Module objects +/// @{ + + /// Print the module to an output stream with AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Dump the module to stderr (for debugging). + void dump() const; + /// This function causes all the subinstructions to "let go" of all references + /// that they are maintaining. This allows one to 'delete' a whole class at + /// a time, even though there may be circular references... first all + /// references are dropped, and all use counts go to zero. Then everything + /// is delete'd for real. Note that no operations are valid on an object + /// that has "dropped all references", except operator delete. + void dropAllReferences(); +/// @} +}; + +/// An raw_ostream inserter for modules. +inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { + M.print(O, 0); + return O; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Object/MachOFormat.h b/final/include/llvm/Object/MachOFormat.h new file mode 100644 index 00000000000..31cd523ea21 --- /dev/null +++ b/final/include/llvm/Object/MachOFormat.h @@ -0,0 +1,367 @@ +//===- MachOFormat.h - Mach-O Format Structures And Constants ---*- 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 various structures and constants which are platform +// independent and can be shared by any client which wishes to interact with +// Mach object files. +// +// The definitions here are purposely chosen to match the LLVM style as opposed +// to following the platform specific definition of the format. +// +// On a Mach system, see the includes for more information, in +// particular . +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOFORMAT_H +#define LLVM_OBJECT_MACHOFORMAT_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +namespace object { + +/// General Mach platform information. +namespace mach { + /// @name CPU Type and Subtype Information + /// { + + /// \brief Capability bits used in CPU type encoding. + enum CPUTypeFlagsMask { + CTFM_ArchMask = 0xFF000000, + CTFM_ArchABI64 = 0x01000000 + }; + + /// \brief Machine type IDs used in CPU type encoding. + enum CPUTypeMachine { + CTM_i386 = 7, + CTM_x86_64 = CTM_i386 | CTFM_ArchABI64, + CTM_ARM = 12, + CTM_SPARC = 14, + CTM_PowerPC = 18, + CTM_PowerPC64 = CTM_PowerPC | CTFM_ArchABI64 + }; + + /// \brief Capability bits used in CPU subtype encoding. + enum CPUSubtypeFlagsMask { + CSFM_SubtypeMask = 0xFF000000, + CSFM_SubtypeLib64 = 0x80000000 + }; + + /// \brief ARM Machine Subtypes. + enum CPUSubtypeARM { + CSARM_ALL = 0, + CSARM_V4T = 5, + CSARM_V6 = 6, + CSARM_V5TEJ = 7, + CSARM_XSCALE = 8, + CSARM_V7 = 9 + }; + + /// \brief PowerPC Machine Subtypes. + enum CPUSubtypePowerPC { + CSPPC_ALL = 0 + }; + + /// \brief SPARC Machine Subtypes. + enum CPUSubtypeSPARC { + CSSPARC_ALL = 0 + }; + + /// \brief x86 Machine Subtypes. + enum CPUSubtypeX86 { + CSX86_ALL = 3 + }; + + /// @} + +} // end namespace mach + +/// Format information for Mach object files. +namespace macho { + /// \brief Constants for structure sizes. + enum StructureSizes { + Header32Size = 28, + Header64Size = 32, + SegmentLoadCommand32Size = 56, + SegmentLoadCommand64Size = 72, + Section32Size = 68, + Section64Size = 80, + SymtabLoadCommandSize = 24, + DysymtabLoadCommandSize = 80, + Nlist32Size = 12, + Nlist64Size = 16, + RelocationInfoSize = 8 + }; + + /// \brief Constants for header magic field. + enum HeaderMagic { + HM_Object32 = 0xFEEDFACE, ///< 32-bit mach object file + HM_Object64 = 0xFEEDFACF, ///< 64-bit mach object file + HM_Universal = 0xCAFEBABE ///< Universal object file + }; + + /// \brief Header common to all Mach object files. + struct Header { + uint32_t Magic; + uint32_t CPUType; + uint32_t CPUSubtype; + uint32_t FileType; + uint32_t NumLoadCommands; + uint32_t SizeOfLoadCommands; + uint32_t Flags; + }; + + /// \brief Extended header for 64-bit object files. + struct Header64Ext { + uint32_t Reserved; + }; + + // See . + enum HeaderFileType { + HFT_Object = 0x1 + }; + + enum HeaderFlags { + HF_SubsectionsViaSymbols = 0x2000 + }; + + enum LoadCommandType { + LCT_Segment = 0x1, + LCT_Symtab = 0x2, + LCT_Dysymtab = 0xb, + LCT_Segment64 = 0x19, + LCT_UUID = 0x1b + }; + + /// \brief Load command structure. + struct LoadCommand { + uint32_t Type; + uint32_t Size; + }; + + /// @name Load Command Structures + /// @{ + + struct SegmentLoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint32_t VMAddress; + uint32_t VMSize; + uint32_t FileOffset; + uint32_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct Segment64LoadCommand { + uint32_t Type; + uint32_t Size; + char Name[16]; + uint64_t VMAddress; + uint64_t VMSize; + uint64_t FileOffset; + uint64_t FileSize; + uint32_t MaxVMProtection; + uint32_t InitialVMProtection; + uint32_t NumSections; + uint32_t Flags; + }; + + struct SymtabLoadCommand { + uint32_t Type; + uint32_t Size; + uint32_t SymbolTableOffset; + uint32_t NumSymbolTableEntries; + uint32_t StringTableOffset; + uint32_t StringTableSize; + }; + + struct DysymtabLoadCommand { + uint32_t Type; + uint32_t Size; + + uint32_t LocalSymbolsIndex; + uint32_t NumLocalSymbols; + + uint32_t ExternalSymbolsIndex; + uint32_t NumExternalSymbols; + + uint32_t UndefinedSymbolsIndex; + uint32_t NumUndefinedSymbols; + + uint32_t TOCOffset; + uint32_t NumTOCEntries; + + uint32_t ModuleTableOffset; + uint32_t NumModuleTableEntries; + + uint32_t ReferenceSymbolTableOffset; + uint32_t NumReferencedSymbolTableEntries; + + uint32_t IndirectSymbolTableOffset; + uint32_t NumIndirectSymbolTableEntries; + + uint32_t ExternalRelocationTableOffset; + uint32_t NumExternalRelocationTableEntries; + + uint32_t LocalRelocationTableOffset; + uint32_t NumLocalRelocationTableEntries; + }; + + /// @} + /// @name Section Data + /// @{ + + struct Section { + char Name[16]; + char SegmentName[16]; + uint32_t Address; + uint32_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + }; + struct Section64 { + char Name[16]; + char SegmentName[16]; + uint64_t Address; + uint64_t Size; + uint32_t Offset; + uint32_t Align; + uint32_t RelocationTableOffset; + uint32_t NumRelocationTableEntries; + uint32_t Flags; + uint32_t Reserved1; + uint32_t Reserved2; + uint32_t Reserved3; + }; + + /// @} + /// @name Symbol Table Entries + /// @{ + + struct SymbolTableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint32_t Value; + }; + struct Symbol64TableEntry { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; + uint64_t Value; + }; + + /// @} + /// @name Indirect Symbol Table + /// @{ + + struct IndirectSymbolTableEntry { + uint32_t Index; + }; + + /// @} + /// @name Relocation Data + /// @{ + + struct RelocationEntry { + uint32_t Word0; + uint32_t Word1; + }; + + /// @} + + // See . + enum SymbolTypeType { + STT_Undefined = 0x00, + STT_Absolute = 0x02, + STT_Section = 0x0e + }; + + enum SymbolTypeFlags { + // If any of these bits are set, then the entry is a stab entry number (see + // . Otherwise the other masks apply. + STF_StabsEntryMask = 0xe0, + + STF_TypeMask = 0x0e, + STF_External = 0x01, + STF_PrivateExtern = 0x10 + }; + + /// IndirectSymbolFlags - Flags for encoding special values in the indirect + /// symbol entry. + enum IndirectSymbolFlags { + ISF_Local = 0x80000000, + ISF_Absolute = 0x40000000 + }; + + /// RelocationFlags - Special flags for addresses. + enum RelocationFlags { + RF_Scattered = 0x80000000 + }; + + /// Common relocation info types. + enum RelocationInfoType { + RIT_Vanilla = 0, + RIT_Pair = 1, + RIT_Difference = 2 + }; + + /// Generic relocation info types, which are shared by some (but not all) + /// platforms. + enum RelocationInfoType_Generic { + RIT_Generic_PreboundLazyPointer = 3, + RIT_Generic_LocalDifference = 4, + RIT_Generic_TLV = 5 + }; + + /// X86_64 uses its own relocation types. + enum RelocationInfoTypeX86_64 { + // Note that x86_64 doesn't even share the common relocation types. + RIT_X86_64_Unsigned = 0, + RIT_X86_64_Signed = 1, + RIT_X86_64_Branch = 2, + RIT_X86_64_GOTLoad = 3, + RIT_X86_64_GOT = 4, + RIT_X86_64_Subtractor = 5, + RIT_X86_64_Signed1 = 6, + RIT_X86_64_Signed2 = 7, + RIT_X86_64_Signed4 = 8, + RIT_X86_64_TLV = 9 + }; + + /// ARM uses its own relocation types. + enum RelocationInfoTypeARM { + RIT_ARM_LocalDifference = 3, + RIT_ARM_PreboundLazyPointer = 4, + RIT_ARM_Branch24Bit = 5, + RIT_ARM_ThumbBranch22Bit = 6, + RIT_ARM_ThumbBranch32Bit = 7, + RIT_ARM_Half = 8, + RIT_ARM_HalfDifference = 9 + + }; + +} // end namespace macho + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Object/MachOObject.h b/final/include/llvm/Object/MachOObject.h new file mode 100644 index 00000000000..03d9c147b41 --- /dev/null +++ b/final/include/llvm/Object/MachOObject.h @@ -0,0 +1,180 @@ +//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOOBJECT_H +#define LLVM_OBJECT_MACHOOBJECT_H + +#include +#include "llvm/ADT/InMemoryStruct.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/MachOFormat.h" + +namespace llvm { + +class MemoryBuffer; + +namespace object { + +/// \brief Wrapper object for manipulating Mach-O object files. +/// +/// This class is designed to implement a full-featured, efficient, portable, +/// and robust Mach-O interface to Mach-O object files. It does not attempt to +/// smooth over rough edges in the Mach-O format or generalize access to object +/// independent features. +/// +/// The class is designed around accessing the Mach-O object which is expected +/// to be fully loaded into memory. +/// +/// This class is *not* suitable for concurrent use. For efficient operation, +/// the class uses APIs which rely on the ability to cache the results of +/// certain calls in internal objects which are not safe for concurrent +/// access. This allows the API to be zero-copy on the common paths. +// +// FIXME: It would be cool if we supported a "paged" MemoryBuffer +// implementation. This would allow us to implement a more sensible version of +// MemoryObject which can work like a MemoryBuffer, but be more efficient for +// objects which are in the current address space. +class MachOObject { +public: + struct LoadCommandInfo { + /// The load command information. + macho::LoadCommand Command; + + /// The offset to the start of the load command in memory. + uint64_t Offset; + }; + +private: + OwningPtr Buffer; + + /// Whether the object is little endian. + bool IsLittleEndian; + /// Whether the object is 64-bit. + bool Is64Bit; + /// Whether the object is swapped endianness from the host. + bool IsSwappedEndian; + /// Whether the string table has been registered. + bool HasStringTable; + + /// The cached information on the load commands. + LoadCommandInfo *LoadCommands; + mutable unsigned NumLoadedCommands; + + /// The cached copy of the header. + macho::Header Header; + macho::Header64Ext Header64Ext; + + /// Cache string table information. + StringRef StringTable; + +private: + MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); + +public: + ~MachOObject(); + + /// \brief Load a Mach-O object from a MemoryBuffer object. + /// + /// \param Buffer - The buffer to load the object from. This routine takes + /// exclusive ownership of the buffer (which is passed to the returned object + /// on success). + /// \param ErrorStr [out] - If given, will be set to a user readable error + /// message on failure. + /// \returns The loaded object, or null on error. + static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, + std::string *ErrorStr = 0); + + /// @name File Information + /// @{ + + bool isLittleEndian() const { return IsLittleEndian; } + bool isSwappedEndian() const { return IsSwappedEndian; } + bool is64Bit() const { return Is64Bit; } + + unsigned getHeaderSize() const { + return Is64Bit ? macho::Header64Size : macho::Header32Size; + } + + StringRef getData(size_t Offset, size_t Size) const; + + /// @} + /// @name String Table Data + /// @{ + + StringRef getStringTableData() const { + assert(HasStringTable && "String table has not been registered!"); + return StringTable; + } + + StringRef getStringAtIndex(unsigned Index) const { + size_t End = getStringTableData().find('\0', Index); + return getStringTableData().slice(Index, End); + } + + void RegisterStringTable(macho::SymtabLoadCommand &SLC); + + /// @} + /// @name Object Header Access + /// @{ + + const macho::Header &getHeader() const { return Header; } + const macho::Header64Ext &getHeader64Ext() const { + assert(is64Bit() && "Invalid access!"); + return Header64Ext; + } + + /// @} + /// @name Object Structure Access + /// @{ + + /// \brief Retrieve the information for the given load command. + const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; + + void ReadSegmentLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct &Res) const; + void ReadSegment64LoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct &Res) const; + void ReadSymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct &Res) const; + void ReadDysymtabLoadCommand( + const LoadCommandInfo &LCI, + InMemoryStruct &Res) const; + void ReadIndirectSymbolTableEntry( + const macho::DysymtabLoadCommand &DLC, + unsigned Index, + InMemoryStruct &Res) const; + void ReadSection( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const; + void ReadSection64( + const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const; + void ReadRelocationEntry( + uint64_t RelocationTableOffset, unsigned Index, + InMemoryStruct &Res) const; + void ReadSymbolTableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct &Res) const; + void ReadSymbol64TableEntry( + uint64_t SymbolTableOffset, unsigned Index, + InMemoryStruct &Res) const; + + /// @} +}; + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Object/ObjectFile.h b/final/include/llvm/Object/ObjectFile.h new file mode 100644 index 00000000000..eee9d447cdd --- /dev/null +++ b/final/include/llvm/Object/ObjectFile.h @@ -0,0 +1,262 @@ +//===- ObjectFile.h - File format independent object 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 a file format independent ObjectFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_OBJECT_FILE_H +#define LLVM_OBJECT_OBJECT_FILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class MemoryBuffer; +class StringRef; + +namespace object { + +class ObjectFile; + +union DataRefImpl { + struct { + uint32_t a, b; + } d; + intptr_t p; +}; + +static bool operator ==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +/// SymbolRef - This is a value type class that represents a single symbol in +/// the list of symbols in the object file. +class SymbolRef { + DataRefImpl SymbolPimpl; + const ObjectFile *OwningObject; + +public: + SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); + + bool operator==(const SymbolRef &Other) const; + + SymbolRef getNext() const; + + StringRef getName() const; + uint64_t getAddress() const; + uint64_t getSize() const; + + /// Returns the ascii char that should be displayed in a symbol table dump via + /// nm for this symbol. + char getNMTypeChar() const; + + /// Returns true for symbols that are internal to the object file format such + /// as section symbols. + bool isInternal() const; +}; + +/// SectionRef - This is a value type class that represents a single section in +/// the list of sections in the object file. +class SectionRef { + DataRefImpl SectionPimpl; + const ObjectFile *OwningObject; + +public: + SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); + + bool operator==(const SectionRef &Other) const; + + SectionRef getNext() const; + + StringRef getName() const; + uint64_t getAddress() const; + uint64_t getSize() const; + StringRef getContents() const; + + // FIXME: Move to the normalization layer when it's created. + bool isText() const; +}; + +const uint64_t UnknownAddressOrSize = ~0ULL; + +/// ObjectFile - This class is the base class for all object file types. +/// Concrete instances of this object are created by createObjectFile, which +/// figure out which type to create. +class ObjectFile { +private: + ObjectFile(); // = delete + ObjectFile(const ObjectFile &other); // = delete + +protected: + MemoryBuffer *MapFile; + const uint8_t *base; + + ObjectFile(MemoryBuffer *Object); + + // These functions are for SymbolRef to call internally. The main goal of + // this is to allow SymbolRef::SymbolPimpl to point directly to the symbol + // entry in the memory mapped object file. SymbolPimpl cannot contain any + // virtual functions because then it could not point into the memory mapped + // file. + friend class SymbolRef; + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const = 0; + virtual StringRef getSymbolName(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const = 0; + virtual bool isSymbolInternal(DataRefImpl Symb) const = 0; + + // Same as above for SectionRef. + friend class SectionRef; + virtual SectionRef getSectionNext(DataRefImpl Sec) const = 0; + virtual StringRef getSectionName(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; + virtual StringRef getSectionContents(DataRefImpl Sec) const = 0; + virtual bool isSectionText(DataRefImpl Sec) const = 0; + + +public: + template + class content_iterator { + content_type Current; + public: + content_iterator(content_type symb) + : Current(symb) {} + + const content_type* operator->() const { + return &Current; + } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator& operator++() { // Preincrement + Current = Current.getNext(); + return *this; + } + }; + + typedef content_iterator symbol_iterator; + typedef content_iterator section_iterator; + + virtual ~ObjectFile(); + + virtual symbol_iterator begin_symbols() const = 0; + virtual symbol_iterator end_symbols() const = 0; + + virtual section_iterator begin_sections() const = 0; + virtual section_iterator end_sections() const = 0; + + /// @brief The number of bytes used to represent an address in this object + /// file format. + virtual uint8_t getBytesInAddress() const = 0; + + virtual StringRef getFileFormatName() const = 0; + virtual /* Triple::ArchType */ unsigned getArch() const = 0; + + StringRef getFilename() const; + + /// @returns Pointer to ObjectFile subclass to handle this type of object. + /// @param ObjectPath The path to the object file. ObjectPath.isObject must + /// return true. + /// @brief Create ObjectFile from path. + static ObjectFile *createObjectFile(StringRef ObjectPath); + static ObjectFile *createObjectFile(MemoryBuffer *Object); + +private: + static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); + static ObjectFile *createELFObjectFile(MemoryBuffer *Object); + static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); + static ObjectFile *createArchiveObjectFile(MemoryBuffer *Object); + static ObjectFile *createLibObjectFile(MemoryBuffer *Object); +}; + +// Inline function definitions. +inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) + : SymbolPimpl(SymbolP) + , OwningObject(Owner) {} + +inline bool SymbolRef::operator==(const SymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline SymbolRef SymbolRef::getNext() const { + return OwningObject->getSymbolNext(SymbolPimpl); +} + +inline StringRef SymbolRef::getName() const { + return OwningObject->getSymbolName(SymbolPimpl); +} + +inline uint64_t SymbolRef::getAddress() const { + return OwningObject->getSymbolAddress(SymbolPimpl); +} + +inline uint64_t SymbolRef::getSize() const { + return OwningObject->getSymbolSize(SymbolPimpl); +} + +inline char SymbolRef::getNMTypeChar() const { + return OwningObject->getSymbolNMTypeChar(SymbolPimpl); +} + +inline bool SymbolRef::isInternal() const { + return OwningObject->isSymbolInternal(SymbolPimpl); +} + + +/// SectionRef +inline SectionRef::SectionRef(DataRefImpl SectionP, + const ObjectFile *Owner) + : SectionPimpl(SectionP) + , OwningObject(Owner) {} + +inline bool SectionRef::operator==(const SectionRef &Other) const { + return SectionPimpl == Other.SectionPimpl; +} + +inline SectionRef SectionRef::getNext() const { + return OwningObject->getSectionNext(SectionPimpl); +} + +inline StringRef SectionRef::getName() const { + return OwningObject->getSectionName(SectionPimpl); +} + +inline uint64_t SectionRef::getAddress() const { + return OwningObject->getSectionAddress(SectionPimpl); +} + +inline uint64_t SectionRef::getSize() const { + return OwningObject->getSectionSize(SectionPimpl); +} + +inline StringRef SectionRef::getContents() const { + return OwningObject->getSectionContents(SectionPimpl); +} + +inline bool SectionRef::isText() const { + return OwningObject->isSectionText(SectionPimpl); +} + +} // end namespace object +} // end namespace llvm + +#endif diff --git a/final/include/llvm/OperandTraits.h b/final/include/llvm/OperandTraits.h new file mode 100644 index 00000000000..f0df5fa9bde --- /dev/null +++ b/final/include/llvm/OperandTraits.h @@ -0,0 +1,197 @@ +//===-- llvm/OperandTraits.h - OperandTraits class definition ---*- 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 traits classes that are handy for enforcing the correct +// layout of various User subclasses. It also provides the means for accessing +// the operands in the most efficient manner. +// + +#ifndef LLVM_OPERAND_TRAITS_H +#define LLVM_OPERAND_TRAITS_H + +#include "llvm/User.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// FixedNumOperand Trait Class +//===----------------------------------------------------------------------===// + +/// FixedNumOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// known at compile time. + +template +struct FixedNumOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast(U) - ARITY; + } + static Use *op_end(SubClass* U) { + return reinterpret_cast(U); + } + static unsigned operands(const User*) { + return ARITY; + } +}; + +//===----------------------------------------------------------------------===// +// OptionalOperand Trait Class +//===----------------------------------------------------------------------===// + +/// OptionalOperandTraits - when the number of operands may change at runtime. +/// Naturally it may only decrease, because the allocations may not change. + +template +struct OptionalOperandTraits : public FixedNumOperandTraits { + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// VariadicOperand Trait Class +//===----------------------------------------------------------------------===// + +/// VariadicOperandTraits - determine the allocation regime of the Use array +/// when it is a prefix to the User object, and the number of Use objects is +/// only known at allocation time. + +template +struct VariadicOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast(U) - static_cast(U)->getNumOperands(); + } + static Use *op_end(SubClass* U) { + return reinterpret_cast(U); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +//===----------------------------------------------------------------------===// +// HungoffOperand Trait Class +//===----------------------------------------------------------------------===// + +/// HungoffOperandTraits - determine the allocation regime of the Use array +/// when it is not a prefix to the User object, but allocated at an unrelated +/// heap address. +/// Assumes that the User subclass that is determined by this traits class +/// has an OperandList member of type User::op_iterator. [Note: this is now +/// trivially satisfied, because User has that member for historic reasons.] +/// +/// This is the traits class that is needed when the Use array must be +/// resizable. + +template +struct HungoffOperandTraits { + static Use *op_begin(User* U) { + return U->OperandList; + } + static Use *op_end(User* U) { + return U->OperandList + U->getNumOperands(); + } + static unsigned operands(const User *U) { + return U->getNumOperands(); + } +}; + +/// Macro for generating in-class operand accessor declarations. +/// It should only be called in the public section of the interface. +/// +#define DECLARE_TRANSPARENT_OPERAND_ACCESSORS(VALUECLASS) \ + public: \ + inline VALUECLASS *getOperand(unsigned) const; \ + inline void setOperand(unsigned, VALUECLASS*); \ + inline op_iterator op_begin(); \ + inline const_op_iterator op_begin() const; \ + inline op_iterator op_end(); \ + inline const_op_iterator op_end() const; \ + protected: \ + template inline Use &Op(); \ + template inline const Use &Op() const; \ + public: \ + inline unsigned getNumOperands() const + +/// Macro for generating out-of-class operand accessor definitions +#define DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits::op_begin(const_cast(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits::op_end(const_cast(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "getOperand() out of range!"); \ + return static_cast( \ + OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits::operands(this); \ +} \ +template Use &CLASS::Op() { \ + return this->OpFrom(this); \ +} \ +template const Use &CLASS::Op() const { \ + return this->OpFrom(this); \ +} + + +/// Macro for generating out-of-class operand accessor +/// definitions with casted result +#define DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(CLASS, VALUECLASS) \ +CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits::op_begin(const_cast(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits::op_end(const_cast(this)); \ +} \ +VALUECLASS *CLASS::getOperand(unsigned i_nocapture) const { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "getOperand() out of range!"); \ + return cast( \ + OperandTraits::op_begin(const_cast(this))[i_nocapture]); \ +} \ +void CLASS::setOperand(unsigned i_nocapture, VALUECLASS *Val_nocapture) { \ + assert(i_nocapture < OperandTraits::operands(this) \ + && "setOperand() out of range!"); \ + OperandTraits::op_begin(this)[i_nocapture] = Val_nocapture; \ +} \ +unsigned CLASS::getNumOperands() const { \ + return OperandTraits::operands(this); \ +} \ +template Use &CLASS::Op() { \ + return this->OpFrom(this); \ +} \ +template const Use &CLASS::Op() const { \ + return this->OpFrom(this); \ +} + + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Operator.h b/final/include/llvm/Operator.h new file mode 100644 index 00000000000..ff2a0ad5e4e --- /dev/null +++ b/final/include/llvm/Operator.h @@ -0,0 +1,285 @@ +//===-- llvm/Operator.h - Operator utility subclass -------------*- 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 various classes for working with Instructions and +// ConstantExprs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OPERATOR_H +#define LLVM_OPERATOR_H + +#include "llvm/Instruction.h" +#include "llvm/Constants.h" + +namespace llvm { + +class GetElementPtrInst; +class BinaryOperator; +class ConstantExpr; + +/// Operator - This is a utility class that provides an abstraction for the +/// common functionality between Instructions and ConstantExprs. +/// +class Operator : public User { +private: + // Do not implement any of these. The Operator class is intended to be used + // as a utility, and is never itself instantiated. + void *operator new(size_t, unsigned); + void *operator new(size_t s); + Operator(); + ~Operator(); + +public: + /// getOpcode - Return the opcode for this Instruction or ConstantExpr. + /// + unsigned getOpcode() const { + if (const Instruction *I = dyn_cast(this)) + return I->getOpcode(); + return cast(this)->getOpcode(); + } + + /// getOpcode - If V is an Instruction or ConstantExpr, return its + /// opcode. Otherwise return UserOp1. + /// + static unsigned getOpcode(const Value *V) { + if (const Instruction *I = dyn_cast(V)) + return I->getOpcode(); + if (const ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode(); + return Instruction::UserOp1; + } + + static inline bool classof(const Operator *) { return true; } + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return isa(V) || isa(V); + } +}; + +/// OverflowingBinaryOperator - Utility class for integer arithmetic operators +/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv, +/// despite that operator having the potential for overflow. +/// +class OverflowingBinaryOperator : public Operator { +public: + enum { + NoUnsignedWrap = (1 << 0), + NoSignedWrap = (1 << 1) + }; + +private: + ~OverflowingBinaryOperator(); // do not implement + + friend class BinaryOperator; + friend class ConstantExpr; + void setHasNoUnsignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); + } + void setHasNoSignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); + } + +public: + /// hasNoUnsignedWrap - Test whether this operation is known to never + /// undergo unsigned overflow, aka the nuw property. + bool hasNoUnsignedWrap() const { + return SubclassOptionalData & NoUnsignedWrap; + } + + /// hasNoSignedWrap - Test whether this operation is known to never + /// undergo signed overflow, aka the nsw property. + bool hasNoSignedWrap() const { + return (SubclassOptionalData & NoSignedWrap) != 0; + } + + static inline bool classof(const OverflowingBinaryOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Add || + I->getOpcode() == Instruction::Sub || + I->getOpcode() == Instruction::Mul || + I->getOpcode() == Instruction::Shl; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::Add || + CE->getOpcode() == Instruction::Sub || + CE->getOpcode() == Instruction::Mul || + CE->getOpcode() == Instruction::Shl; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as +/// "exact", indicating that no bits are destroyed. +class PossiblyExactOperator : public Operator { +public: + enum { + IsExact = (1 << 0) + }; + + friend class BinaryOperator; + friend class ConstantExpr; + void setIsExact(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); + } + +private: + ~PossiblyExactOperator(); // do not implement +public: + /// isExact - Test whether this division is known to be exact, with + /// zero remainder. + bool isExact() const { + return SubclassOptionalData & IsExact; + } + + static bool isPossiblyExactOpcode(unsigned OpC) { + return OpC == Instruction::SDiv || + OpC == Instruction::UDiv || + OpC == Instruction::AShr || + OpC == Instruction::LShr; + } + static inline bool classof(const ConstantExpr *CE) { + return isPossiblyExactOpcode(CE->getOpcode()); + } + static inline bool classof(const Instruction *I) { + return isPossiblyExactOpcode(I->getOpcode()); + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + + + +/// ConcreteOperator - A helper template for defining operators for individual +/// opcodes. +template +class ConcreteOperator : public SuperClass { + ~ConcreteOperator(); // DO NOT IMPLEMENT +public: + static inline bool classof(const ConcreteOperator *) { + return true; + } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Opc; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Opc; + } + static inline bool classof(const Value *V) { + return (isa(V) && classof(cast(V))) || + (isa(V) && classof(cast(V))); + } +}; + +class AddOperator + : public ConcreteOperator {}; +class SubOperator + : public ConcreteOperator {}; +class MulOperator + : public ConcreteOperator {}; +class ShlOperator + : public ConcreteOperator {}; + + +class SDivOperator + : public ConcreteOperator {}; +class UDivOperator + : public ConcreteOperator {}; +class AShrOperator + : public ConcreteOperator {}; +class LShrOperator + : public ConcreteOperator {}; + + + +class GEPOperator + : public ConcreteOperator { + enum { + IsInBounds = (1 << 0) + }; + + friend class GetElementPtrInst; + friend class ConstantExpr; + void setIsInBounds(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); + } + +public: + /// isInBounds - Test whether this is an inbounds GEP, as defined + /// by LangRef.html. + bool isInBounds() const { + return SubclassOptionalData & IsInBounds; + } + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + const PointerType *getPointerOperandType() const { + return reinterpret_cast(getPointerOperand()->getType()); + } + + unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (ConstantInt *C = dyn_cast(I)) + if (C->isZero()) + continue; + return false; + } + return true; + } + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const { + for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { + if (!isa(I)) + return false; + } + return true; + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Pass.h b/final/include/llvm/Pass.h new file mode 100644 index 00000000000..ed0fb39f5d6 --- /dev/null +++ b/final/include/llvm/Pass.h @@ -0,0 +1,371 @@ +//===- llvm/Pass.h - Base class for Passes ----------------------*- 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 base class that indicates that a specified class is a +// transformation pass implementation. +// +// Passes are designed this way so that it is possible to run passes in a cache +// and organizationally optimal order without having to specify it at the front +// end. This allows arbitrary passes to be strung together and have them +// executed as effeciently as possible. +// +// Passes should extend one of the classes below, depending on the guarantees +// that it can make about what will be modified as it is run. For example, most +// global optimizations should derive from FunctionPass, because they do not add +// or delete functions, they operate on the internals of the function. +// +// Note that this file #includes PassSupport.h and PassAnalysisSupport.h (at the +// bottom), so the APIs exposed by these files are also automatically available +// to all users of this file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_H +#define LLVM_PASS_H + +#include + +namespace llvm { + +class BasicBlock; +class Function; +class Module; +class AnalysisUsage; +class PassInfo; +class ImmutablePass; +class PMStack; +class AnalysisResolver; +class PMDataManager; +class raw_ostream; +class StringRef; + +// AnalysisID - Use the PassInfo to identify a pass... +typedef const void* AnalysisID; + +/// Different types of internal pass managers. External pass managers +/// (PassManager and FunctionPassManager) are not represented here. +/// Ordering of pass manager types is important here. +enum PassManagerType { + PMT_Unknown = 0, + PMT_ModulePassManager = 1, ///< MPPassManager + PMT_CallGraphPassManager, ///< CGPassManager + PMT_FunctionPassManager, ///< FPPassManager + PMT_LoopPassManager, ///< LPPassManager + PMT_RegionPassManager, ///< RGPassManager + PMT_BasicBlockPassManager, ///< BBPassManager + PMT_Last +}; + +// Different types of passes. +enum PassKind { + PT_BasicBlock, + PT_Region, + PT_Loop, + PT_Function, + PT_CallGraphSCC, + PT_Module, + PT_PassManager +}; + +//===----------------------------------------------------------------------===// +/// Pass interface - Implemented by all 'passes'. Subclass this if you are an +/// interprocedural optimization or you do not fit into any of the more +/// constrained passes described below. +/// +class Pass { + AnalysisResolver *Resolver; // Used to resolve analysis + const void *PassID; + PassKind Kind; + void operator=(const Pass&); // DO NOT IMPLEMENT + Pass(const Pass &); // DO NOT IMPLEMENT + +public: + explicit Pass(PassKind K, char &pid); + virtual ~Pass(); + + + PassKind getPassKind() const { return Kind; } + + /// getPassName - Return a nice clean name for a pass. This usually + /// implemented in terms of the name that is registered by one of the + /// Registration templates, but can be overloaded directly. + /// + virtual const char *getPassName() const; + + /// getPassID - Return the PassID number that corresponds to this pass. + virtual AnalysisID getPassID() const { + return PassID; + } + + /// print - Print out the internal state of the pass. This is called by + /// Analyze to print out the contents of an analysis. Otherwise it is not + /// necessary to implement this method. Beware that the module pointer MAY be + /// null. This automatically forwards to a virtual function that does not + /// provide the Module* in case the analysis doesn't need it it can just be + /// ignored. + /// + virtual void print(raw_ostream &O, const Module *M) const; + void dump() const; // dump - Print to stderr. + + /// createPrinterPass - Get a Pass appropriate to print the IR this + /// pass operates one (Module, Function or MachineFunction). + virtual Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const = 0; + + /// Each pass is responsible for assigning a pass manager to itself. + /// PMS is the stack of available pass manager. + virtual void assignPassManager(PMStack &, + PassManagerType) {} + /// Check if available pass managers are suitable for this pass or not. + virtual void preparePassManager(PMStack &); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const; + + // Access AnalysisResolver + void setResolver(AnalysisResolver *AR); + AnalysisResolver *getResolver() const { return Resolver; } + + /// getAnalysisUsage - This function should be overriden by passes that need + /// analysis information to do their job. If a pass specifies that it uses a + /// particular analysis result to this function, it can then use the + /// getAnalysis() function, below. + /// + virtual void getAnalysisUsage(AnalysisUsage &) const; + + /// releaseMemory() - This member can be implemented by a pass if it wants to + /// be able to release its memory when it is no longer needed. The default + /// behavior of passes is to hold onto memory for the entire duration of their + /// lifetime (which is the entire compile time). For pipelined passes, this + /// is not a big deal because that memory gets recycled every time the pass is + /// invoked on another program unit. For IP passes, it is more important to + /// free memory when it is unused. + /// + /// Optionally implement this function to release pass memory when it is no + /// longer used. + /// + virtual void releaseMemory(); + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(AnalysisID ID); + virtual ImmutablePass *getAsImmutablePass(); + virtual PMDataManager *getAsPMDataManager(); + + /// verifyAnalysis() - This member can be implemented by a analysis pass to + /// check state of analysis information. + virtual void verifyAnalysis() const; + + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual void dumpPassStructure(unsigned Offset = 0); + + // lookupPassInfo - Return the pass info object for the specified pass class, + // or null if it is not known. + static const PassInfo *lookupPassInfo(const void *TI); + + // lookupPassInfo - Return the pass info object for the pass with the given + // argument string, or null if it is not known. + static const PassInfo *lookupPassInfo(StringRef Arg); + + /// getAnalysisIfAvailable() - Subclasses use this function to + /// get analysis information that might be around, for example to update it. + /// This is different than getAnalysis in that it can fail (if the analysis + /// results haven't been computed), so should only be used if you can handle + /// the case when the analysis is not available. This method is often used by + /// transformation APIs to update analysis results for a pass automatically as + /// the transform is performed. + /// + template AnalysisType * + getAnalysisIfAvailable() const; // Defined in PassAnalysisSupport.h + + /// mustPreserveAnalysisID - This method serves the same function as + /// getAnalysisIfAvailable, but works if you just have an AnalysisID. This + /// obviously cannot give you a properly typed instance of the class if you + /// don't have the class name available (use getAnalysisIfAvailable if you + /// do), but it can tell you if you need to preserve the pass at least. + /// + bool mustPreserveAnalysisID(char &AID) const; + + /// getAnalysis() - This function is used by subclasses to get + /// to the analysis information that they claim to use by overriding the + /// getAnalysisUsage function. + /// + template + AnalysisType &getAnalysis() const; // Defined in PassAnalysisSupport.h + + template + AnalysisType &getAnalysis(Function &F); // Defined in PassAnalysisSupport.h + + template + AnalysisType &getAnalysisID(AnalysisID PI) const; + + template + AnalysisType &getAnalysisID(AnalysisID PI, Function &F); +}; + + +//===----------------------------------------------------------------------===// +/// ModulePass class - This class is used to implement unstructured +/// interprocedural optimizations and analyses. ModulePasses may do anything +/// they want to the program. +/// +class ModulePass : public Pass { +public: + /// createPrinterPass - Get a module printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + /// runOnModule - Virtual method overriden by subclasses to process the module + /// being operated on. + virtual bool runOnModule(Module &M) = 0; + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const; + + explicit ModulePass(char &pid) : Pass(PT_Module, pid) {} + // Force out-of-line virtual method. + virtual ~ModulePass(); +}; + + +//===----------------------------------------------------------------------===// +/// ImmutablePass class - This class is used to provide information that does +/// not need to be run. This is useful for things like target information and +/// "basic" versions of AnalysisGroups. +/// +class ImmutablePass : public ModulePass { +public: + /// initializePass - This method may be overriden by immutable passes to allow + /// them to perform various initialization actions they require. This is + /// primarily because an ImmutablePass can "require" another ImmutablePass, + /// and if it does, the overloaded version of initializePass may get access to + /// these passes with getAnalysis<>. + /// + virtual void initializePass(); + + virtual ImmutablePass *getAsImmutablePass() { return this; } + + /// ImmutablePasses are never run. + /// + bool runOnModule(Module &) { return false; } + + explicit ImmutablePass(char &pid) + : ModulePass(pid) {} + + // Force out-of-line virtual method. + virtual ~ImmutablePass(); +}; + +//===----------------------------------------------------------------------===// +/// FunctionPass class - This class is used to implement most global +/// optimizations. Optimizations should subclass this class if they meet the +/// following constraints: +/// +/// 1. Optimizations are organized globally, i.e., a function at a time +/// 2. Optimizing a function does not cause the addition or removal of any +/// functions in the module +/// +class FunctionPass : public Pass { +public: + explicit FunctionPass(char &pid) : Pass(PT_Function, pid) {} + + /// createPrinterPass - Get a function printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &); + + /// runOnFunction - Virtual method overriden by subclasses to do the + /// per-function processing of the pass. + /// + virtual bool runOnFunction(Function &F) = 0; + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const; +}; + + + +//===----------------------------------------------------------------------===// +/// BasicBlockPass class - This class is used to implement most local +/// optimizations. Optimizations should subclass this class if they +/// meet the following constraints: +/// 1. Optimizations are local, operating on either a basic block or +/// instruction at a time. +/// 2. Optimizations do not modify the CFG of the contained function, or any +/// other basic block in the function. +/// 3. Optimizations conform to all of the constraints of FunctionPasses. +/// +class BasicBlockPass : public Pass { +public: + explicit BasicBlockPass(char &pid) : Pass(PT_BasicBlock, pid) {} + + /// createPrinterPass - Get a function printer pass. + Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &); + + /// doInitialization - Virtual method overridden by BasicBlockPass subclasses + /// to do any necessary per-function initialization. + /// + virtual bool doInitialization(Function &); + + /// runOnBasicBlock - Virtual method overriden by subclasses to do the + /// per-basicblock processing of the pass. + /// + virtual bool runOnBasicBlock(BasicBlock &BB) = 0; + + /// doFinalization - Virtual method overriden by BasicBlockPass subclasses to + /// do any post processing needed after all passes have run. + /// + virtual bool doFinalization(Function &); + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const; +}; + +/// If the user specifies the -time-passes argument on an LLVM tool command line +/// then the value of this boolean will be true, otherwise false. +/// @brief This is the storage for the -time-passes option. +extern bool TimePassesIsEnabled; + +} // End llvm namespace + +// Include support files that contain important APIs commonly used by Passes, +// but that we want to separate out to make it easier to read the header files. +// +#include "llvm/PassSupport.h" +#include "llvm/PassAnalysisSupport.h" + +#endif diff --git a/final/include/llvm/PassAnalysisSupport.h b/final/include/llvm/PassAnalysisSupport.h new file mode 100644 index 00000000000..a3342d51386 --- /dev/null +++ b/final/include/llvm/PassAnalysisSupport.h @@ -0,0 +1,250 @@ +//===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- 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 stuff that is used to define and "use" Analysis Passes. +// This file is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_ANALYSIS_SUPPORT_H +#define LLVM_PASS_ANALYSIS_SUPPORT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// AnalysisUsage - Represent the analysis usage information of a pass. This +// tracks analyses that the pass REQUIRES (must be available when the pass +// runs), REQUIRES TRANSITIVE (must be available throughout the lifetime of the +// pass), and analyses that the pass PRESERVES (the pass does not invalidate the +// results of these analyses). This information is provided by a pass to the +// Pass infrastructure through the getAnalysisUsage virtual function. +// +class AnalysisUsage { +public: + typedef SmallVector VectorType; + +private: + // Sets of analyses required and preserved by a pass + VectorType Required, RequiredTransitive, Preserved; + bool PreservesAll; + +public: + AnalysisUsage() : PreservesAll(false) {} + + // addRequired - Add the specified ID to the required set of the usage info + // for a pass. + // + AnalysisUsage &addRequiredID(const void *ID); + AnalysisUsage &addRequiredID(char &ID); + template + AnalysisUsage &addRequired() { + return addRequiredID(PassClass::ID); + } + + AnalysisUsage &addRequiredTransitiveID(char &ID); + template + AnalysisUsage &addRequiredTransitive() { + return addRequiredTransitiveID(PassClass::ID); + } + + // addPreserved - Add the specified ID to the set of analyses preserved by + // this pass + // + AnalysisUsage &addPreservedID(const void *ID) { + Preserved.push_back(ID); + return *this; + } + AnalysisUsage &addPreservedID(char &ID) { + Preserved.push_back(&ID); + return *this; + } + + // addPreserved - Add the specified Pass class to the set of analyses + // preserved by this pass. + // + template + AnalysisUsage &addPreserved() { + Preserved.push_back(&PassClass::ID); + return *this; + } + + // addPreserved - Add the Pass with the specified argument string to the set + // of analyses preserved by this pass. If no such Pass exists, do nothing. + // This can be useful when a pass is trivially preserved, but may not be + // linked in. Be careful about spelling! + // + AnalysisUsage &addPreserved(StringRef Arg); + + // setPreservesAll - Set by analyses that do not transform their input at all + void setPreservesAll() { PreservesAll = true; } + bool getPreservesAll() const { return PreservesAll; } + + /// setPreservesCFG - This function should be called by the pass, iff they do + /// not: + /// + /// 1. Add or remove basic blocks from the function + /// 2. Modify terminator instructions in any way. + /// + /// This function annotates the AnalysisUsage info object to say that analyses + /// that only depend on the CFG are preserved by this pass. + /// + void setPreservesCFG(); + + const VectorType &getRequiredSet() const { return Required; } + const VectorType &getRequiredTransitiveSet() const { + return RequiredTransitive; + } + const VectorType &getPreservedSet() const { return Preserved; } +}; + +//===----------------------------------------------------------------------===// +// AnalysisResolver - Simple interface used by Pass objects to pull all +// analysis information out of pass manager that is responsible to manage +// the pass. +// +class PMDataManager; +class AnalysisResolver { +private: + AnalysisResolver(); // DO NOT IMPLEMENT + +public: + explicit AnalysisResolver(PMDataManager &P) : PM(P) { } + + inline PMDataManager &getPMDataManager() { return PM; } + + // Find pass that is implementing PI. + Pass *findImplPass(AnalysisID PI) { + Pass *ResultPass = 0; + for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) { + if (AnalysisImpls[i].first == PI) { + ResultPass = AnalysisImpls[i].second; + break; + } + } + return ResultPass; + } + + // Find pass that is implementing PI. Initialize pass for Function F. + Pass *findImplPass(Pass *P, AnalysisID PI, Function &F); + + void addAnalysisImplsPair(AnalysisID PI, Pass *P) { + std::pair pir = std::make_pair(PI,P); + AnalysisImpls.push_back(pir); + } + + /// clearAnalysisImpls - Clear cache that is used to connect a pass to the + /// the analysis (PassInfo). + void clearAnalysisImpls() { + AnalysisImpls.clear(); + } + + // getAnalysisIfAvailable - Return analysis result or null if it doesn't exist + Pass *getAnalysisIfAvailable(AnalysisID ID, bool Direction) const; + +private: + // AnalysisImpls - This keeps track of which passes implements the interfaces + // that are required by the current pass (to implement getAnalysis()). + std::vector > AnalysisImpls; + + // PassManager that is used to resolve analysis info + PMDataManager &PM; +}; + +/// getAnalysisIfAvailable() - Subclasses use this function to +/// get analysis information that might be around, for example to update it. +/// This is different than getAnalysis in that it can fail (if the analysis +/// results haven't been computed), so should only be used if you can handle +/// the case when the analysis is not available. This method is often used by +/// transformation APIs to update analysis results for a pass automatically as +/// the transform is performed. +/// +template +AnalysisType *Pass::getAnalysisIfAvailable() const { + assert(Resolver && "Pass not resident in a PassManager object!"); + + const void *PI = &AnalysisType::ID; + + Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI, true); + if (ResultPass == 0) return 0; + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return (AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +/// getAnalysis() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template +AnalysisType &Pass::getAnalysis() const { + assert(Resolver && "Pass has not been inserted into a PassManager object!"); + return getAnalysisID(&AnalysisType::ID); +} + +template +AnalysisType &Pass::getAnalysisID(AnalysisID PI) const { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver&&"Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(PI); + assert (ResultPass && + "getAnalysis*() called on an analysis that was not " + "'required' by pass!"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +/// getAnalysis() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template +AnalysisType &Pass::getAnalysis(Function &F) { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID(&AnalysisType::ID, F); +} + +template +AnalysisType &Pass::getAnalysisID(AnalysisID PI, Function &F) { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver && "Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(this, PI, F); + assert(ResultPass && "Unable to find requested analysis info"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/PassManager.h b/final/include/llvm/PassManager.h new file mode 100644 index 00000000000..c8b5dcaf0f2 --- /dev/null +++ b/final/include/llvm/PassManager.h @@ -0,0 +1,111 @@ +//===- llvm/PassManager.h - Container for Passes ----------------*- 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 PassManager class. This class is used to hold, +// maintain, and optimize execution of Passes. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGER_H +#define LLVM_PASSMANAGER_H + +#include "llvm/Pass.h" + +namespace llvm { + +class Pass; +class Module; + +class PassManagerImpl; +class FunctionPassManagerImpl; + +/// PassManagerBase - An abstract interface to allow code to add passes to +/// a pass manager without having to hard-code what kind of pass manager +/// it is. +class PassManagerBase { +public: + virtual ~PassManagerBase(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + virtual void add(Pass *P) = 0; +}; + +/// PassManager manages ModulePassManagers +class PassManager : public PassManagerBase { +public: + + PassManager(); + ~PassManager(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool run(Module &M); + +private: + /// addImpl - Add a pass to the queue of passes to run, without + /// checking whether to add a printer pass. + void addImpl(Pass *P); + + /// PassManagerImpl_New is the actual class. PassManager is just the + /// wraper to publish simple pass manager interface + PassManagerImpl *PM; +}; + +/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. +class FunctionPassManager : public PassManagerBase { +public: + /// FunctionPassManager ctor - This initializes the pass manager. It needs, + /// but does not take ownership of, the specified Module. + explicit FunctionPassManager(Module *M); + ~FunctionPassManager(); + + /// add - Add a pass to the queue of passes to run. This passes + /// ownership of the Pass to the PassManager. When the + /// PassManager_X is destroyed, the pass will be destroyed as well, so + /// there is no need to delete the pass. (TODO delete passes.) + /// This implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep + /// track of whether any of the passes modifies the function, and if + /// so, return true. + /// + bool run(Function &F); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(); + +private: + /// addImpl - Add a pass to the queue of passes to run, without + /// checking whether to add a printer pass. + void addImpl(Pass *P); + + FunctionPassManagerImpl *FPM; + Module *M; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/PassManagers.h b/final/include/llvm/PassManagers.h new file mode 100644 index 00000000000..c4f409ef525 --- /dev/null +++ b/final/include/llvm/PassManagers.h @@ -0,0 +1,460 @@ +//===- llvm/PassManagers.h - Pass Infrastructure classes -------*- 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 LLVM Pass Manager infrastructure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGERS_H +#define LLVM_PASSMANAGERS_H + +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include +#include + +//===----------------------------------------------------------------------===// +// Overview: +// The Pass Manager Infrastructure manages passes. It's responsibilities are: +// +// o Manage optimization pass execution order +// o Make required Analysis information available before pass P is run +// o Release memory occupied by dead passes +// o If Analysis information is dirtied by a pass then regenerate Analysis +// information before it is consumed by another pass. +// +// Pass Manager Infrastructure uses multiple pass managers. They are +// PassManager, FunctionPassManager, MPPassManager, FPPassManager, BBPassManager. +// This class hierarchy uses multiple inheritance but pass managers do not +// derive from another pass manager. +// +// PassManager and FunctionPassManager are two top-level pass manager that +// represents the external interface of this entire pass manager infrastucture. +// +// Important classes : +// +// [o] class PMTopLevelManager; +// +// Two top level managers, PassManager and FunctionPassManager, derive from +// PMTopLevelManager. PMTopLevelManager manages information used by top level +// managers such as last user info. +// +// [o] class PMDataManager; +// +// PMDataManager manages information, e.g. list of available analysis info, +// used by a pass manager to manage execution order of passes. It also provides +// a place to implement common pass manager APIs. All pass managers derive from +// PMDataManager. +// +// [o] class BBPassManager : public FunctionPass, public PMDataManager; +// +// BBPassManager manages BasicBlockPasses. +// +// [o] class FunctionPassManager; +// +// This is a external interface used by JIT to manage FunctionPasses. This +// interface relies on FunctionPassManagerImpl to do all the tasks. +// +// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, +// public PMTopLevelManager; +// +// FunctionPassManagerImpl is a top level manager. It manages FPPassManagers +// +// [o] class FPPassManager : public ModulePass, public PMDataManager; +// +// FPPassManager manages FunctionPasses and BBPassManagers +// +// [o] class MPPassManager : public Pass, public PMDataManager; +// +// MPPassManager manages ModulePasses and FPPassManagers +// +// [o] class PassManager; +// +// This is a external interface used by various tools to manages passes. It +// relies on PassManagerImpl to do all the tasks. +// +// [o] class PassManagerImpl : public Pass, public PMDataManager, +// public PMDTopLevelManager +// +// PassManagerImpl is a top level pass manager responsible for managing +// MPPassManagers. +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PrettyStackTrace.h" + +namespace llvm { + class Module; + class Pass; + class StringRef; + class Value; + class Timer; + class PMDataManager; + +// enums for debugging strings +enum PassDebuggingString { + EXECUTION_MSG, // "Executing Pass '" + MODIFICATION_MSG, // "' Made Modification '" + FREEING_MSG, // " Freeing Pass '" + ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" + ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" + ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" + ON_REGION_MSG, // " 'on Region ...\n'" + ON_LOOP_MSG, // " 'on Loop ...\n'" + ON_CG_MSG // "' on Call Graph ...\n'" +}; + +/// PassManagerPrettyStackEntry - This is used to print informative information +/// about what pass is running when/if a stack trace is generated. +class PassManagerPrettyStackEntry : public PrettyStackTraceEntry { + Pass *P; + Value *V; + Module *M; +public: + explicit PassManagerPrettyStackEntry(Pass *p) + : P(p), V(0), M(0) {} // When P is releaseMemory'd. + PassManagerPrettyStackEntry(Pass *p, Value &v) + : P(p), V(&v), M(0) {} // When P is run on V + PassManagerPrettyStackEntry(Pass *p, Module &m) + : P(p), V(0), M(&m) {} // When P is run on M + + /// print - Emit information about this stack frame to OS. + virtual void print(raw_ostream &OS) const; +}; + + +//===----------------------------------------------------------------------===// +// PMStack +// +/// PMStack - This class implements a stack data structure of PMDataManager +/// pointers. +/// +/// Top level pass managers (see PassManager.cpp) maintain active Pass Managers +/// using PMStack. Each Pass implements assignPassManager() to connect itself +/// with appropriate manager. assignPassManager() walks PMStack to find +/// suitable manager. +class PMStack { +public: + typedef std::vector::const_reverse_iterator iterator; + iterator begin() const { return S.rbegin(); } + iterator end() const { return S.rend(); } + + void pop(); + PMDataManager *top() const { return S.back(); } + void push(PMDataManager *PM); + bool empty() const { return S.empty(); } + + void dump() const; + +private: + std::vector S; +}; + + +//===----------------------------------------------------------------------===// +// PMTopLevelManager +// +/// PMTopLevelManager manages LastUser info and collects common APIs used by +/// top level pass managers. +class PMTopLevelManager { +protected: + explicit PMTopLevelManager(PMDataManager *PMDM); + + virtual unsigned getNumContainedManagers() const { + return (unsigned)PassManagers.size(); + } + + void initializeAllAnalysisInfo(); + +private: + /// This is implemented by top level pass manager and used by + /// schedulePass() to add analysis info passes that are not available. + virtual void addTopLevelPass(Pass *P) = 0; + +public: + /// Schedule pass P for execution. Make sure that passes required by + /// P are run before P is run. Update analysis info maintained by + /// the manager. Remove dead passes. This is a recursive function. + void schedulePass(Pass *P); + + /// Set pass P as the last user of the given analysis passes. + void setLastUser(const SmallVectorImpl &AnalysisPasses, Pass *P); + + /// Collect passes whose last user is P + void collectLastUses(SmallVectorImpl &LastUses, Pass *P); + + /// Find the pass that implements Analysis AID. Search immutable + /// passes and all pass managers. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID); + + /// Find analysis usage information for the pass P. + AnalysisUsage *findAnalysisUsage(Pass *P); + + virtual ~PMTopLevelManager(); + + /// Add immutable pass and initialize it. + inline void addImmutablePass(ImmutablePass *P) { + P->initializePass(); + ImmutablePasses.push_back(P); + } + + inline SmallVectorImpl& getImmutablePasses() { + return ImmutablePasses; + } + + void addPassManager(PMDataManager *Manager) { + PassManagers.push_back(Manager); + } + + // Add Manager into the list of managers that are not directly + // maintained by this top level pass manager + inline void addIndirectPassManager(PMDataManager *Manager) { + IndirectPassManagers.push_back(Manager); + } + + // Print passes managed by this top level manager. + void dumpPasses() const; + void dumpArguments() const; + + // Active Pass Managers + PMStack activeStack; + +protected: + + /// Collection of pass managers + SmallVector PassManagers; + +private: + + /// Collection of pass managers that are not directly maintained + /// by this pass manager + SmallVector IndirectPassManagers; + + // Map to keep track of last user of the analysis pass. + // LastUser->second is the last user of Lastuser->first. + DenseMap LastUser; + + // Map to keep track of passes that are last used by a pass. + // This inverse map is initialized at PM->run() based on + // LastUser map. + DenseMap > InversedLastUser; + + /// Immutable passes are managed by top level manager. + SmallVector ImmutablePasses; + + DenseMap AnUsageMap; +}; + + + +//===----------------------------------------------------------------------===// +// PMDataManager + +/// PMDataManager provides the common place to manage the analysis data +/// used by pass managers. +class PMDataManager { +public: + + explicit PMDataManager(int Depth) : TPM(NULL), Depth(Depth) { + initializeAnalysisInfo(); + } + + virtual ~PMDataManager(); + + virtual Pass *getAsPass() = 0; + + /// Augment AvailableAnalysis by adding analysis made available by pass P. + void recordAvailableAnalysis(Pass *P); + + /// verifyPreservedAnalysis -- Verify analysis presreved by pass P. + void verifyPreservedAnalysis(Pass *P); + + /// Remove Analysis that is not preserved by the pass + void removeNotPreservedAnalysis(Pass *P); + + /// Remove dead passes used by P. + void removeDeadPasses(Pass *P, StringRef Msg, + enum PassDebuggingString); + + /// Remove P. + void freePass(Pass *P, StringRef Msg, + enum PassDebuggingString); + + /// Add pass P into the PassVector. Update + /// AvailableAnalysis appropriately if ProcessAnalysis is true. + void add(Pass *P, bool ProcessAnalysis = true); + + /// Add RequiredPass into list of lower level passes required by pass P. + /// RequiredPass is run on the fly by Pass Manager when P requests it + /// through getAnalysis interface. + virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass); + + virtual Pass *getOnTheFlyPass(Pass *P, AnalysisID PI, Function &F); + + /// Initialize available analysis information. + void initializeAnalysisInfo() { + AvailableAnalysis.clear(); + for (unsigned i = 0; i < PMT_Last; ++i) + InheritedAnalysis[i] = NULL; + } + + // Return true if P preserves high level analysis used by other + // passes that are managed by this manager. + bool preserveHigherLevelAnalysis(Pass *P); + + + /// Populate RequiredPasses with analysis pass that are required by + /// pass P and are available. Populate ReqPassNotAvailable with analysis + /// pass that are required by pass P but are not available. + void collectRequiredAnalysis(SmallVectorImpl &RequiredPasses, + SmallVectorImpl &ReqPassNotAvailable, + Pass *P); + + /// All Required analyses should be available to the pass as it runs! Here + /// we fill in the AnalysisImpls member of the pass so that it can + /// successfully use the getAnalysis() method to retrieve the + /// implementations it needs. + void initializeAnalysisImpl(Pass *P); + + /// Find the pass that implements Analysis AID. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID, bool Direction); + + // Access toplevel manager + PMTopLevelManager *getTopLevelManager() { return TPM; } + void setTopLevelManager(PMTopLevelManager *T) { TPM = T; } + + unsigned getDepth() const { return Depth; } + + // Print routines used by debug-pass + void dumpLastUses(Pass *P, unsigned Offset) const; + void dumpPassArguments() const; + void dumpPassInfo(Pass *P, enum PassDebuggingString S1, + enum PassDebuggingString S2, StringRef Msg); + void dumpRequiredSet(const Pass *P) const; + void dumpPreservedSet(const Pass *P) const; + + virtual unsigned getNumContainedPasses() const { + return (unsigned)PassVector.size(); + } + + virtual PassManagerType getPassManagerType() const { + assert ( 0 && "Invalid use of getPassManagerType"); + return PMT_Unknown; + } + + std::map *getAvailableAnalysis() { + return &AvailableAnalysis; + } + + // Collect AvailableAnalysis from all the active Pass Managers. + void populateInheritedAnalysis(PMStack &PMS) { + unsigned Index = 0; + for (PMStack::iterator I = PMS.begin(), E = PMS.end(); + I != E; ++I) + InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis(); + } + +protected: + + // Top level manager. + PMTopLevelManager *TPM; + + // Collection of pass that are managed by this manager + SmallVector PassVector; + + // Collection of Analysis provided by Parent pass manager and + // used by current pass manager. At at time there can not be more + // then PMT_Last active pass mangers. + std::map *InheritedAnalysis[PMT_Last]; + + + /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions + /// or higher is specified. + bool isPassDebuggingExecutionsOrMore() const; + +private: + void dumpAnalysisUsage(StringRef Msg, const Pass *P, + const AnalysisUsage::VectorType &Set) const; + + // Set of available Analysis. This information is used while scheduling + // pass. If a pass requires an analysis which is not available then + // the required analysis pass is scheduled to run before the pass itself is + // scheduled to run. + std::map AvailableAnalysis; + + // Collection of higher level analysis used by the pass managed by + // this manager. + SmallVector HigherLevelAnalysis; + + unsigned Depth; +}; + +//===----------------------------------------------------------------------===// +// FPPassManager +// +/// FPPassManager manages BBPassManagers and FunctionPasses. +/// It batches all function passes and basic block pass managers together and +/// sequence them to process one function at a time before processing next +/// function. +class FPPassManager : public ModulePass, public PMDataManager { +public: + static char ID; + explicit FPPassManager(int Depth) + : ModulePass(ID), PMDataManager(Depth) { } + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnFunction(Function &F); + bool runOnModule(Module &M); + + /// cleanup - After running all passes, clean up pass manager cache. + void cleanup(); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(Module &M); + + /// doFinalization - Run all of the finalizers for the function passes. + /// + bool doFinalization(Module &M); + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + /// Pass Manager itself does not invalidate any analysis info. + void getAnalysisUsage(AnalysisUsage &Info) const { + Info.setPreservesAll(); + } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset); + + virtual const char *getPassName() const { + return "Function Pass Manager"; + } + + FunctionPass *getContainedPass(unsigned N) { + assert ( N < PassVector.size() && "Pass number out of range!"); + FunctionPass *FP = static_cast(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_FunctionPassManager; + } +}; + +Timer *getPassTimer(Pass *); + +} + +#endif diff --git a/final/include/llvm/PassRegistry.h b/final/include/llvm/PassRegistry.h new file mode 100644 index 00000000000..5d89c492218 --- /dev/null +++ b/final/include/llvm/PassRegistry.h @@ -0,0 +1,84 @@ +//===- llvm/PassRegistry.h - Pass Information Registry ----------*- 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 PassRegistry, a class that is used in the initialization +// and registration of passes. At application startup, passes are registered +// with the PassRegistry, which is later provided to the PassManager for +// dependency resolution and similar tasks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSREGISTRY_H +#define LLVM_PASSREGISTRY_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +class PassInfo; +struct PassRegistrationListener; + +/// PassRegistry - This class manages the registration and intitialization of +/// the pass subsystem as application startup, and assists the PassManager +/// in resolving pass dependencies. +/// NOTE: PassRegistry is NOT thread-safe. If you want to use LLVM on multiple +/// threads simultaneously, you will need to use a separate PassRegistry on +/// each thread. +class PassRegistry { + mutable void *pImpl; + void *getImpl() const; + +public: + PassRegistry() : pImpl(0) { } + ~PassRegistry(); + + /// getPassRegistry - Access the global registry object, which is + /// automatically initialized at application launch and destroyed by + /// llvm_shutdown. + static PassRegistry *getPassRegistry(); + + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' + /// type identifier (&MyPass::ID). + const PassInfo *getPassInfo(const void *TI) const; + + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' + /// argument string. + const PassInfo *getPassInfo(StringRef Arg) const; + + /// registerPass - Register a pass (by means of its PassInfo) with the + /// registry. Required in order to use the pass with a PassManager. + void registerPass(const PassInfo &PI, bool ShouldFree = false); + + /// registerPass - Unregister a pass (by means of its PassInfo) with the + /// registry. + void unregisterPass(const PassInfo &PI); + + /// registerAnalysisGroup - Register an analysis group (or a pass implementing + // an analysis group) with the registry. Like registerPass, this is required + // in order for a PassManager to be able to use this group/pass. + void registerAnalysisGroup(const void *InterfaceID, const void *PassID, + PassInfo& Registeree, bool isDefault, + bool ShouldFree = false); + + /// enumerateWith - Enumerate the registered passes, calling the provided + /// PassRegistrationListener's passEnumerate() callback on each of them. + void enumerateWith(PassRegistrationListener *L); + + /// addRegistrationListener - Register the given PassRegistrationListener + /// to receive passRegistered() callbacks whenever a new pass is registered. + void addRegistrationListener(PassRegistrationListener *L); + + /// removeRegistrationListener - Unregister a PassRegistrationListener so that + /// it no longer receives passRegistered() callbacks. + void removeRegistrationListener(PassRegistrationListener *L); +}; + +} + +#endif diff --git a/final/include/llvm/PassSupport.h b/final/include/llvm/PassSupport.h new file mode 100644 index 00000000000..082790956c4 --- /dev/null +++ b/final/include/llvm/PassSupport.h @@ -0,0 +1,336 @@ +//===- llvm/PassSupport.h - Pass Support code -------------------*- 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 stuff that is used to define and "use" Passes. This file +// is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h. +// +// This file defines Pass registration code and classes used for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_SUPPORT_H +#define LLVM_PASS_SUPPORT_H + +#include "Pass.h" +#include "llvm/PassRegistry.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/Atomic.h" +#include + +namespace llvm { + +//===--------------------------------------------------------------------------- +/// PassInfo class - An instance of this class exists for every pass known by +/// the system, and can be obtained from a live Pass by calling its +/// getPassInfo() method. These objects are set up by the RegisterPass<> +/// template, defined below. +/// +class PassInfo { +public: + typedef Pass* (*NormalCtor_t)(); + +private: + const char *const PassName; // Nice name for Pass + const char *const PassArgument; // Command Line argument to run this pass + const void *PassID; + const bool IsCFGOnlyPass; // Pass only looks at the CFG. + const bool IsAnalysis; // True if an analysis pass. + const bool IsAnalysisGroup; // True if an analysis group. + std::vector ItfImpl;// Interfaces implemented by this pass + + NormalCtor_t NormalCtor; + +public: + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. + PassInfo(const char *name, const char *arg, const void *pi, + NormalCtor_t normal, bool isCFGOnly, bool is_analysis) + : PassName(name), PassArgument(arg), PassID(pi), + IsCFGOnlyPass(isCFGOnly), + IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { } + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. This version is for use by analysis groups; it + /// does not auto-register the pass. + PassInfo(const char *name, const void *pi) + : PassName(name), PassArgument(""), PassID(pi), + IsCFGOnlyPass(false), + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0) { } + + /// getPassName - Return the friendly name for the pass, never returns null + /// + const char *getPassName() const { return PassName; } + + /// getPassArgument - Return the command line option that may be passed to + /// 'opt' that will cause this pass to be run. This will return null if there + /// is no argument. + /// + const char *getPassArgument() const { return PassArgument; } + + /// getTypeInfo - Return the id object for the pass... + /// TODO : Rename + const void *getTypeInfo() const { return PassID; } + + /// Return true if this PassID implements the specified ID pointer. + bool isPassID(const void *IDPtr) const { + return PassID == IDPtr; + } + + /// isAnalysisGroup - Return true if this is an analysis group, not a normal + /// pass. + /// + bool isAnalysisGroup() const { return IsAnalysisGroup; } + bool isAnalysis() const { return IsAnalysis; } + + /// isCFGOnlyPass - return true if this pass only looks at the CFG for the + /// function. + bool isCFGOnlyPass() const { return IsCFGOnlyPass; } + + /// getNormalCtor - Return a pointer to a function, that when called, creates + /// an instance of the pass and returns it. This pointer may be null if there + /// is no default constructor for the pass. + /// + NormalCtor_t getNormalCtor() const { + return NormalCtor; + } + void setNormalCtor(NormalCtor_t Ctor) { + NormalCtor = Ctor; + } + + /// createPass() - Use this method to create an instance of this pass. + Pass *createPass() const; + + /// addInterfaceImplemented - This method is called when this pass is + /// registered as a member of an analysis group with the RegisterAnalysisGroup + /// template. + /// + void addInterfaceImplemented(const PassInfo *ItfPI) { + ItfImpl.push_back(ItfPI); + } + + /// getInterfacesImplemented - Return a list of all of the analysis group + /// interfaces implemented by this pass. + /// + const std::vector &getInterfacesImplemented() const { + return ItfImpl; + } + +private: + void operator=(const PassInfo &); // do not implement + PassInfo(const PassInfo &); // do not implement +}; + +#define CALL_ONCE_INITIALIZATION(function) \ + static volatile sys::cas_flag initialized = 0; \ + sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); \ + if (old_val == 0) { \ + function(Registry); \ + sys::MemoryFence(); \ + initialized = 2; \ + } else { \ + sys::cas_flag tmp = initialized; \ + sys::MemoryFence(); \ + while (tmp != 2) { \ + tmp = initialized; \ + sys::MemoryFence(); \ + } \ + } + +#define INITIALIZE_PASS(passName, arg, name, cfg, analysis) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + +#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { + +#define INITIALIZE_PASS_DEPENDENCY(depName) \ + initialize##depName##Pass(Registry); +#define INITIALIZE_AG_DEPENDENCY(depName) \ + initialize##depName##AnalysisGroup(Registry); + +#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis) \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + +template +Pass *callDefaultCtor() { return new PassName(); } + +//===--------------------------------------------------------------------------- +/// RegisterPass template - This template class is used to notify the system +/// that a Pass is available for use, and registers it into the internal +/// database maintained by the PassManager. Unless this template is used, opt, +/// for example will not be able to see the pass and attempts to create the pass +/// will fail. This template is used in the follow manner (at global scope, in +/// your .cpp file): +/// +/// static RegisterPass tmp("passopt", "My Pass Name"); +/// +/// This statement will cause your pass to be created by calling the default +/// constructor exposed by the pass. If you have a different constructor that +/// must be called, create a global constructor function (which takes the +/// arguments you need and returns a Pass*) and register your pass like this: +/// +/// static RegisterPass tmp("passopt", "My Name"); +/// +template +struct RegisterPass : public PassInfo { + + // Register Pass using default constructor... + RegisterPass(const char *PassArg, const char *Name, bool CFGOnly = false, + bool is_analysis = false) + : PassInfo(Name, PassArg, &passName::ID, + PassInfo::NormalCtor_t(callDefaultCtor), + CFGOnly, is_analysis) { + PassRegistry::getPassRegistry()->registerPass(*this); + } +}; + + +/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_. +/// Analysis groups are used to define an interface (which need not derive from +/// Pass) that is required by passes to do their job. Analysis Groups differ +/// from normal analyses because any available implementation of the group will +/// be used if it is available. +/// +/// If no analysis implementing the interface is available, a default +/// implementation is created and added. A pass registers itself as the default +/// implementation by specifying 'true' as the second template argument of this +/// class. +/// +/// In addition to registering itself as an analysis group member, a pass must +/// register itself normally as well. Passes may be members of multiple groups +/// and may still be "required" specifically by name. +/// +/// The actual interface may also be registered as well (by not specifying the +/// second template argument). The interface should be registered to associate +/// a nice name with the interface. +/// +class RegisterAGBase : public PassInfo { +public: + RegisterAGBase(const char *Name, + const void *InterfaceID, + const void *PassID = 0, + bool isDefault = false); +}; + +template +struct RegisterAnalysisGroup : public RegisterAGBase { + explicit RegisterAnalysisGroup(PassInfo &RPB) + : RegisterAGBase(RPB.getPassName(), + &Interface::ID, RPB.getTypeInfo(), + Default) { + } + + explicit RegisterAnalysisGroup(const char *Name) + : RegisterAGBase(Name, &Interface::ID) { + } +}; + +#define INITIALIZE_ANALYSIS_GROUP(agName, name, defaultPass) \ + static void* initialize##agName##AnalysisGroupOnce(PassRegistry &Registry) { \ + initialize##defaultPass##Pass(Registry); \ + PassInfo *AI = new PassInfo(name, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, 0, *AI, false, true); \ + return AI; \ + } \ + void llvm::initialize##agName##AnalysisGroup(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##agName##AnalysisGroupOnce) \ + } + + +#define INITIALIZE_AG_PASS(passName, agName, arg, name, cfg, analysis, def) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + if (!def) initialize##agName##AnalysisGroup(Registry); \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + \ + PassInfo *AI = new PassInfo(name, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \ + *AI, def, true); \ + return AI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + + +#define INITIALIZE_AG_PASS_BEGIN(passName, agName, arg, n, cfg, analysis, def) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + if (!def) initialize##agName##AnalysisGroup(Registry); + +#define INITIALIZE_AG_PASS_END(passName, agName, arg, n, cfg, analysis, def) \ + PassInfo *PI = new PassInfo(n, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis); \ + Registry.registerPass(*PI, true); \ + \ + PassInfo *AI = new PassInfo(n, & agName :: ID); \ + Registry.registerAnalysisGroup(& agName ::ID, & passName ::ID, \ + *AI, def, true); \ + return AI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + +//===--------------------------------------------------------------------------- +/// PassRegistrationListener class - This class is meant to be derived from by +/// clients that are interested in which passes get registered and unregistered +/// at runtime (which can be because of the RegisterPass constructors being run +/// as the program starts up, or may be because a shared object just got +/// loaded). Deriving from the PassRegistationListener class automatically +/// registers your object to receive callbacks indicating when passes are loaded +/// and removed. +/// +struct PassRegistrationListener { + + /// PassRegistrationListener ctor - Add the current object to the list of + /// PassRegistrationListeners... + PassRegistrationListener(); + + /// dtor - Remove object from list of listeners... + /// + virtual ~PassRegistrationListener(); + + /// Callback functions - These functions are invoked whenever a pass is loaded + /// or removed from the current executable. + /// + virtual void passRegistered(const PassInfo *) {} + + /// enumeratePasses - Iterate over the registered passes, calling the + /// passEnumerate callback on each PassInfo object. + /// + void enumeratePasses(); + + /// passEnumerate - Callback function invoked when someone calls + /// enumeratePasses on this PassRegistrationListener object. + /// + virtual void passEnumerate(const PassInfo *) {} +}; + + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/AIXDataTypesFix.h b/final/include/llvm/Support/AIXDataTypesFix.h new file mode 100644 index 00000000000..a9a9147de29 --- /dev/null +++ b/final/include/llvm/Support/AIXDataTypesFix.h @@ -0,0 +1,25 @@ +//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file overrides default system-defined types and limits which cannot be +// done in DataTypes.h.in because it is processed by autoheader first, which +// comments out any #undef statement +// +//===----------------------------------------------------------------------===// + +// No include guards desired! + +#ifndef SUPPORT_DATATYPES_H +#error "AIXDataTypesFix.h must only be included via DataTypes.h!" +#endif + +// GCC is strict about defining large constants: they must have LL modifier. +// These will be defined properly at the end of DataTypes.h +#undef INT64_MAX +#undef INT64_MIN diff --git a/final/include/llvm/Support/AlignOf.h b/final/include/llvm/Support/AlignOf.h new file mode 100644 index 00000000000..cebfa7982d6 --- /dev/null +++ b/final/include/llvm/Support/AlignOf.h @@ -0,0 +1,60 @@ +//===--- AlignOf.h - Portable calculation of type alignment -----*- 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 AlignOf function that computes alignments for +// arbitrary types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALIGNOF_H +#define LLVM_SUPPORT_ALIGNOF_H + +namespace llvm { + +template +struct AlignmentCalcImpl { + char x; + T t; +private: + AlignmentCalcImpl() {} // Never instantiate. +}; + +/// AlignOf - A templated class that contains an enum value representing +/// the alignment of the template argument. For example, +/// AlignOf::Alignment represents the alignment of type "int". The +/// alignment calculated is the minimum alignment, and not necessarily +/// the "desired" alignment returned by GCC's __alignof__ (for example). Note +/// that because the alignment is an enum value, it can be used as a +/// compile-time constant (e.g., for template instantiation). +template +struct AlignOf { + enum { Alignment = + static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; + + enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; + enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; + enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; + enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 }; + + enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 }; + enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; + enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; + enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; + +}; + +/// alignOf - A templated function that returns the minimum alignment of +/// of a type. This provides no extra functionality beyond the AlignOf +/// class besides some cosmetic cleanliness. Example usage: +/// alignOf() returns the alignment of an int. +template +static inline unsigned alignOf() { return AlignOf::Alignment; } + +} // end namespace llvm +#endif diff --git a/final/include/llvm/Support/Allocator.h b/final/include/llvm/Support/Allocator.h new file mode 100644 index 00000000000..c6807099f85 --- /dev/null +++ b/final/include/llvm/Support/Allocator.h @@ -0,0 +1,239 @@ +//===--- Allocator.h - Simple memory allocation abstraction -----*- 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 MallocAllocator and BumpPtrAllocator interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALLOCATOR_H +#define LLVM_SUPPORT_ALLOCATOR_H + +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/DataTypes.h" +#include +#include +#include +#include + +namespace llvm { +template struct ReferenceAdder { typedef T& result; }; +template struct ReferenceAdder { typedef T result; }; + +class MallocAllocator { +public: + MallocAllocator() {} + ~MallocAllocator() {} + + void Reset() {} + + void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } + + template + T *Allocate() { return static_cast(malloc(sizeof(T))); } + + template + T *Allocate(size_t Num) { + return static_cast(malloc(sizeof(T)*Num)); + } + + void Deallocate(const void *Ptr) { free(const_cast(Ptr)); } + + void PrintStats() const {} +}; + +/// MemSlab - This structure lives at the beginning of every slab allocated by +/// the bump allocator. +class MemSlab { +public: + size_t Size; + MemSlab *NextPtr; +}; + +/// SlabAllocator - This class can be used to parameterize the underlying +/// allocation strategy for the bump allocator. In particular, this is used +/// by the JIT to allocate contiguous swathes of executable memory. The +/// interface uses MemSlab's instead of void *'s so that the allocator +/// doesn't have to remember the size of the pointer it allocated. +class SlabAllocator { +public: + virtual ~SlabAllocator(); + virtual MemSlab *Allocate(size_t Size) = 0; + virtual void Deallocate(MemSlab *Slab) = 0; +}; + +/// MallocSlabAllocator - The default slab allocator for the bump allocator +/// is an adapter class for MallocAllocator that just forwards the method +/// calls and translates the arguments. +class MallocSlabAllocator : public SlabAllocator { + /// Allocator - The underlying allocator that we forward to. + /// + MallocAllocator Allocator; + +public: + MallocSlabAllocator() : Allocator() { } + virtual ~MallocSlabAllocator(); + virtual MemSlab *Allocate(size_t Size); + virtual void Deallocate(MemSlab *Slab); +}; + +/// BumpPtrAllocator - This allocator is useful for containers that need +/// very simple memory allocation strategies. In particular, this just keeps +/// allocating memory, and never deletes it until the entire block is dead. This +/// makes allocation speedy, but must only be used when the trade-off is ok. +class BumpPtrAllocator { + BumpPtrAllocator(const BumpPtrAllocator &); // do not implement + void operator=(const BumpPtrAllocator &); // do not implement + + /// SlabSize - Allocate data into slabs of this size unless we get an + /// allocation above SizeThreshold. + size_t SlabSize; + + /// SizeThreshold - For any allocation larger than this threshold, we should + /// allocate a separate slab. + size_t SizeThreshold; + + /// Allocator - The underlying allocator we use to get slabs of memory. This + /// defaults to MallocSlabAllocator, which wraps malloc, but it could be + /// changed to use a custom allocator. + SlabAllocator &Allocator; + + /// CurSlab - The slab that we are currently allocating into. + /// + MemSlab *CurSlab; + + /// CurPtr - The current pointer into the current slab. This points to the + /// next free byte in the slab. + char *CurPtr; + + /// End - The end of the current slab. + /// + char *End; + + /// BytesAllocated - This field tracks how many bytes we've allocated, so + /// that we can compute how much space was wasted. + size_t BytesAllocated; + + /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should + /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and + /// AlignPtr(8, 4) == 8. + static char *AlignPtr(char *Ptr, size_t Alignment); + + /// StartNewSlab - Allocate a new slab and move the bump pointers over into + /// the new slab. Modifies CurPtr and End. + void StartNewSlab(); + + /// DeallocateSlabs - Deallocate all memory slabs after and including this + /// one. + void DeallocateSlabs(MemSlab *Slab); + + static MallocSlabAllocator DefaultSlabAllocator; + + template friend class SpecificBumpPtrAllocator; +public: + BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = DefaultSlabAllocator); + ~BumpPtrAllocator(); + + /// Reset - Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. + void Reset(); + + /// Allocate - Allocate space at the specified alignment. + /// + void *Allocate(size_t Size, size_t Alignment); + + /// Allocate space, but do not construct, one object. + /// + template + T *Allocate() { + return static_cast(Allocate(sizeof(T),AlignOf::Alignment)); + } + + /// Allocate space for an array of objects. This does not construct the + /// objects though. + template + T *Allocate(size_t Num) { + return static_cast(Allocate(Num * sizeof(T), AlignOf::Alignment)); + } + + /// Allocate space for a specific count of elements and with a specified + /// alignment. + template + T *Allocate(size_t Num, size_t Alignment) { + // Round EltSize up to the specified alignment. + size_t EltSize = (sizeof(T)+Alignment-1)&(-Alignment); + return static_cast(Allocate(Num * EltSize, Alignment)); + } + + void Deallocate(const void * /*Ptr*/) {} + + unsigned GetNumSlabs() const; + + void PrintStats() const; +}; + +/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only +/// elements of one type to be allocated. This allows calling the destructor +/// in DestroyAll() and when the allocator is destroyed. +template +class SpecificBumpPtrAllocator { + BumpPtrAllocator Allocator; +public: + SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096, + SlabAllocator &allocator = BumpPtrAllocator::DefaultSlabAllocator) + : Allocator(size, threshold, allocator) {} + + ~SpecificBumpPtrAllocator() { + DestroyAll(); + } + + /// Call the destructor of each allocated object and deallocate all but the + /// current slab and reset the current pointer to the beginning of it, freeing + /// all memory allocated so far. + void DestroyAll() { + MemSlab *Slab = Allocator.CurSlab; + while (Slab) { + char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : + (char *)Slab + Slab->Size; + for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { + Ptr = Allocator.AlignPtr(Ptr, alignOf()); + if (Ptr + sizeof(T) <= End) + reinterpret_cast(Ptr)->~T(); + } + Slab = Slab->NextPtr; + } + Allocator.Reset(); + } + + /// Allocate space for a specific count of elements. + T *Allocate(size_t num = 1) { + return Allocator.Allocate(num); + } +}; + +} // end namespace llvm + +inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { + struct S { + char c; + union { + double D; + long double LD; + long long L; + void *P; + } x; + }; + return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), + offsetof(S, x))); +} + +inline void operator delete(void *, llvm::BumpPtrAllocator &) {} + +#endif // LLVM_SUPPORT_ALLOCATOR_H diff --git a/final/include/llvm/Support/Atomic.h b/final/include/llvm/Support/Atomic.h new file mode 100644 index 00000000000..1a6c606aa5f --- /dev/null +++ b/final/include/llvm/Support/Atomic.h @@ -0,0 +1,39 @@ +//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- 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 llvm::sys atomic operations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ATOMIC_H +#define LLVM_SYSTEM_ATOMIC_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + namespace sys { + void MemoryFence(); + +#ifdef _MSC_VER + typedef long cas_flag; +#else + typedef uint32_t cas_flag; +#endif + cas_flag CompareAndSwap(volatile cas_flag* ptr, + cas_flag new_value, + cas_flag old_value); + cas_flag AtomicIncrement(volatile cas_flag* ptr); + cas_flag AtomicDecrement(volatile cas_flag* ptr); + cas_flag AtomicAdd(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicMul(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicDiv(volatile cas_flag* ptr, cas_flag val); + } +} + +#endif diff --git a/final/include/llvm/Support/CFG.h b/final/include/llvm/Support/CFG.h new file mode 100644 index 00000000000..d2ea12364e9 --- /dev/null +++ b/final/include/llvm/Support/CFG.h @@ -0,0 +1,341 @@ +//===-- llvm/Support/CFG.h - Process LLVM structures as graphs --*- 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 specializations of GraphTraits that allow Function and +// BasicBlock graphs to be treated as proper graphs for generic algorithms. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CFG_H +#define LLVM_SUPPORT_CFG_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Function.h" +#include "llvm/InstrTypes.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// BasicBlock pred_iterator definition +//===----------------------------------------------------------------------===// + +template // Predecessor Iterator +class PredIterator : public std::iterator { + typedef std::iterator super; + typedef PredIterator Self; + USE_iterator It; + + inline void advancePastNonTerminators() { + // Loop to ignore non terminator uses (for example PHI nodes). + while (!It.atEnd() && !isa(*It)) + ++It; + } + +public: + typedef typename super::pointer pointer; + + PredIterator() {} + explicit inline PredIterator(Ptr *bb) : It(bb->use_begin()) { + advancePastNonTerminators(); + } + inline PredIterator(Ptr *bb, bool) : It(bb->use_end()) {} + + inline bool operator==(const Self& x) const { return It == x.It; } + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(!It.atEnd() && "pred_iterator out of range!"); + return cast(*It)->getParent(); + } + inline pointer *operator->() const { return &operator*(); } + + inline Self& operator++() { // Preincrement + assert(!It.atEnd() && "pred_iterator out of range!"); + ++It; advancePastNonTerminators(); + return *this; + } + + inline Self operator++(int) { // Postincrement + Self tmp = *this; ++*this; return tmp; + } + + /// getOperandNo - Return the operand number in the predecessor's + /// terminator of the successor. + unsigned getOperandNo() const { + return It.getOperandNo(); + } +}; + +typedef PredIterator pred_iterator; +typedef PredIterator const_pred_iterator; + +inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } +inline const_pred_iterator pred_begin(const BasicBlock *BB) { + return const_pred_iterator(BB); +} +inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} +inline const_pred_iterator pred_end(const BasicBlock *BB) { + return const_pred_iterator(BB, true); +} + + + +//===----------------------------------------------------------------------===// +// BasicBlock succ_iterator definition +//===----------------------------------------------------------------------===// + +template // Successor Iterator +class SuccIterator : public std::iterator { + const Term_ Term; + unsigned idx; + typedef std::iterator super; + typedef SuccIterator Self; + + inline bool index_is_valid(int idx) { + return idx >= 0 && (unsigned) idx < Term->getNumSuccessors(); + } + +public: + typedef typename super::pointer pointer; + // TODO: This can be random access iterator, only operator[] missing. + + explicit inline SuccIterator(Term_ T) : Term(T), idx(0) {// begin iterator + assert(T && "getTerminator returned null!"); + } + inline SuccIterator(Term_ T, bool) // end iterator + : Term(T), idx(Term->getNumSuccessors()) { + assert(T && "getTerminator returned null!"); + } + + inline const Self &operator=(const Self &I) { + assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); + idx = I.idx; + return *this; + } + + /// getSuccessorIndex - This is used to interface between code that wants to + /// operate on terminator instructions directly. + unsigned getSuccessorIndex() const { return idx; } + + inline bool operator==(const Self& x) const { return idx == x.idx; } + inline bool operator!=(const Self& x) const { return !operator==(x); } + + inline pointer operator*() const { return Term->getSuccessor(idx); } + inline pointer operator->() const { return operator*(); } + + inline Self& operator++() { ++idx; return *this; } // Preincrement + + inline Self operator++(int) { // Postincrement + Self tmp = *this; ++*this; return tmp; + } + + inline Self& operator--() { --idx; return *this; } // Predecrement + inline Self operator--(int) { // Postdecrement + Self tmp = *this; --*this; return tmp; + } + + inline bool operator<(const Self& x) const { + assert(Term == x.Term && "Cannot compare iterators of different blocks!"); + return idx < x.idx; + } + + inline bool operator<=(const Self& x) const { + assert(Term == x.Term && "Cannot compare iterators of different blocks!"); + return idx <= x.idx; + } + inline bool operator>=(const Self& x) const { + assert(Term == x.Term && "Cannot compare iterators of different blocks!"); + return idx >= x.idx; + } + + inline bool operator>(const Self& x) const { + assert(Term == x.Term && "Cannot compare iterators of different blocks!"); + return idx > x.idx; + } + + inline Self& operator+=(int Right) { + unsigned new_idx = idx + Right; + assert(index_is_valid(new_idx) && "Iterator index out of bound"); + idx = new_idx; + return *this; + } + + inline Self operator+(int Right) { + Self tmp = *this; + tmp += Right; + return tmp; + } + + inline Self& operator-=(int Right) { + return operator+=(-Right); + } + + inline Self operator-(int Right) { + return operator+(-Right); + } + + inline int operator-(const Self& x) { + assert(Term == x.Term && "Cannot work on iterators of different blocks!"); + int distance = idx - x.idx; + return distance; + } + + // This works for read access, however write access is difficult as changes + // to Term are only possible with Term->setSuccessor(idx). Pointers that can + // be modified are not available. + // + // inline pointer operator[](int offset) { + // Self tmp = *this; + // tmp += offset; + // return tmp.operator*(); + // } + + /// Get the source BB of this iterator. + inline BB_ *getSource() { + return Term->getParent(); + } +}; + +typedef SuccIterator succ_iterator; +typedef SuccIterator succ_const_iterator; + +inline succ_iterator succ_begin(BasicBlock *BB) { + return succ_iterator(BB->getTerminator()); +} +inline succ_const_iterator succ_begin(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator()); +} +inline succ_iterator succ_end(BasicBlock *BB) { + return succ_iterator(BB->getTerminator(), true); +} +inline succ_const_iterator succ_end(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator(), true); +} + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... + +template <> struct GraphTraits { + typedef BasicBlock NodeType; + typedef succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(BasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits { + typedef const BasicBlock NodeType; + typedef succ_const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const BasicBlock *BB) { return BB; } + + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > { + typedef BasicBlock NodeType; + typedef pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +template <> struct GraphTraits > { + typedef const BasicBlock NodeType; + typedef const_pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... these are the same as the basic block iterators, +// except that the root node is implicitly the first node of the function. +// +template <> struct GraphTraits : public GraphTraits { + static NodeType *getEntryNode(Function *F) { return &F->getEntryBlock(); } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef Function::iterator nodes_iterator; + static nodes_iterator nodes_begin(Function *F) { return F->begin(); } + static nodes_iterator nodes_end (Function *F) { return F->end(); } +}; +template <> struct GraphTraits : + public GraphTraits { + static NodeType *getEntryNode(const Function *F) {return &F->getEntryBlock();} + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef Function::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const Function *F) { return F->begin(); } + static nodes_iterator nodes_end (const Function *F) { return F->end(); } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->getEntryBlock(); + } +}; +template <> struct GraphTraits > : + public GraphTraits > { + static NodeType *getEntryNode(Inverse G) { + return &G.Graph->getEntryBlock(); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/COFF.h b/final/include/llvm/Support/COFF.h new file mode 100644 index 00000000000..673925593e6 --- /dev/null +++ b/final/include/llvm/Support/COFF.h @@ -0,0 +1,298 @@ +//===-- llvm/Support/COFF.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an definitions used in Windows COFF Files. +// +// Structures and enums defined within this file where created using +// information from Microsoft's publicly available PE/COFF format document: +// +// Microsoft Portable Executable and Common Object File Format Specification +// Revision 8.1 - February 15, 2008 +// +// As of 5/2/2010, hosted by Microsoft at: +// http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WIN_COFF_H +#define LLVM_SUPPORT_WIN_COFF_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +namespace COFF { + + // Sizes in bytes of various things in the COFF format. + enum { + HeaderSize = 20, + NameSize = 8, + SymbolSize = 18, + SectionSize = 40, + RelocationSize = 10 + }; + + struct header { + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; + }; + + enum MachineTypes { + IMAGE_FILE_MACHINE_I386 = 0x14C, + IMAGE_FILE_MACHINE_AMD64 = 0x8664 + }; + + struct symbol { + char Name[NameSize]; + uint32_t Value; + uint16_t Type; + uint8_t StorageClass; + uint16_t SectionNumber; + uint8_t NumberOfAuxSymbols; + }; + + enum SymbolFlags { + SF_TypeMask = 0x0000FFFF, + SF_TypeShift = 0, + + SF_ClassMask = 0x00FF0000, + SF_ClassShift = 16, + + SF_WeakExternal = 0x01000000 + }; + + enum SymbolSectionNumber { + IMAGE_SYM_DEBUG = -2, + IMAGE_SYM_ABSOLUTE = -1, + IMAGE_SYM_UNDEFINED = 0 + }; + + /// Storage class tells where and what the symbol represents + enum SymbolStorageClass { + IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function + IMAGE_SYM_CLASS_NULL = 0, ///< No symbol + IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable + IMAGE_SYM_CLASS_EXTERNAL = 2, ///< External symbol + IMAGE_SYM_CLASS_STATIC = 3, ///< Static + IMAGE_SYM_CLASS_REGISTER = 4, ///< Register variable + IMAGE_SYM_CLASS_EXTERNAL_DEF = 5, ///< External definition + IMAGE_SYM_CLASS_LABEL = 6, ///< Label + IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7, ///< Undefined label + IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8, ///< Member of structure + IMAGE_SYM_CLASS_ARGUMENT = 9, ///< Function argument + IMAGE_SYM_CLASS_STRUCT_TAG = 10, ///< Structure tag + IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11, ///< Member of union + IMAGE_SYM_CLASS_UNION_TAG = 12, ///< Union tag + IMAGE_SYM_CLASS_TYPE_DEFINITION = 13, ///< Type definition + IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14, ///< Undefined static + IMAGE_SYM_CLASS_ENUM_TAG = 15, ///< Enumeration tag + IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16, ///< Member of enumeration + IMAGE_SYM_CLASS_REGISTER_PARAM = 17, ///< Register parameter + IMAGE_SYM_CLASS_BIT_FIELD = 18, ///< Bit field + /// ".bb" or ".eb" - beginning or end of block + IMAGE_SYM_CLASS_BLOCK = 100, + /// ".bf" or ".ef" - beginning or end of function + IMAGE_SYM_CLASS_FUNCTION = 101, + IMAGE_SYM_CLASS_END_OF_STRUCT = 102, ///< End of structure + IMAGE_SYM_CLASS_FILE = 103, ///< File name + /// Line number, reformatted as symbol + IMAGE_SYM_CLASS_SECTION = 104, + IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105, ///< Duplicate tag + /// External symbol in dmert public lib + IMAGE_SYM_CLASS_CLR_TOKEN = 107 + }; + + enum SymbolBaseType { + IMAGE_SYM_TYPE_NULL = 0, ///< No type information or unknown base type. + IMAGE_SYM_TYPE_VOID = 1, ///< Used with void pointers and functions. + IMAGE_SYM_TYPE_CHAR = 2, ///< A character (signed byte). + IMAGE_SYM_TYPE_SHORT = 3, ///< A 2-byte signed integer. + IMAGE_SYM_TYPE_INT = 4, ///< A natural integer type on the target. + IMAGE_SYM_TYPE_LONG = 5, ///< A 4-byte signed integer. + IMAGE_SYM_TYPE_FLOAT = 6, ///< A 4-byte floating-point number. + IMAGE_SYM_TYPE_DOUBLE = 7, ///< An 8-byte floating-point number. + IMAGE_SYM_TYPE_STRUCT = 8, ///< A structure. + IMAGE_SYM_TYPE_UNION = 9, ///< An union. + IMAGE_SYM_TYPE_ENUM = 10, ///< An enumerated type. + IMAGE_SYM_TYPE_MOE = 11, ///< A member of enumeration (a specific value). + IMAGE_SYM_TYPE_BYTE = 12, ///< A byte; unsigned 1-byte integer. + IMAGE_SYM_TYPE_WORD = 13, ///< A word; unsigned 2-byte integer. + IMAGE_SYM_TYPE_UINT = 14, ///< An unsigned integer of natural size. + IMAGE_SYM_TYPE_DWORD = 15 ///< An unsigned 4-byte integer. + }; + + enum SymbolComplexType { + IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. + IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type. + IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type. + IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type. + + /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT)) + SCT_COMPLEX_TYPE_SHIFT = 4 + }; + + struct section { + char Name[NameSize]; + uint32_t VirtualSize; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLineNumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLineNumbers; + uint32_t Characteristics; + }; + + enum SectionCharacteristics { + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, + IMAGE_SCN_CNT_CODE = 0x00000020, + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, + IMAGE_SCN_LNK_OTHER = 0x00000100, + IMAGE_SCN_LNK_INFO = 0x00000200, + IMAGE_SCN_LNK_REMOVE = 0x00000800, + IMAGE_SCN_LNK_COMDAT = 0x00001000, + IMAGE_SCN_GPREL = 0x00008000, + IMAGE_SCN_MEM_PURGEABLE = 0x00020000, + IMAGE_SCN_MEM_16BIT = 0x00020000, + IMAGE_SCN_MEM_LOCKED = 0x00040000, + IMAGE_SCN_MEM_PRELOAD = 0x00080000, + IMAGE_SCN_ALIGN_1BYTES = 0x00100000, + IMAGE_SCN_ALIGN_2BYTES = 0x00200000, + IMAGE_SCN_ALIGN_4BYTES = 0x00300000, + IMAGE_SCN_ALIGN_8BYTES = 0x00400000, + IMAGE_SCN_ALIGN_16BYTES = 0x00500000, + IMAGE_SCN_ALIGN_32BYTES = 0x00600000, + IMAGE_SCN_ALIGN_64BYTES = 0x00700000, + IMAGE_SCN_ALIGN_128BYTES = 0x00800000, + IMAGE_SCN_ALIGN_256BYTES = 0x00900000, + IMAGE_SCN_ALIGN_512BYTES = 0x00A00000, + IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000, + IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, + IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, + IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, + IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, + IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, + IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, + IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, + IMAGE_SCN_MEM_SHARED = 0x10000000, + IMAGE_SCN_MEM_EXECUTE = 0x20000000, + IMAGE_SCN_MEM_READ = 0x40000000, + IMAGE_SCN_MEM_WRITE = 0x80000000 + }; + + struct relocation { + uint32_t VirtualAddress; + uint32_t SymbolTableIndex; + uint16_t Type; + }; + + enum RelocationTypeX86 { + IMAGE_REL_I386_ABSOLUTE = 0x0000, + IMAGE_REL_I386_DIR16 = 0x0001, + IMAGE_REL_I386_REL16 = 0x0002, + IMAGE_REL_I386_DIR32 = 0x0006, + IMAGE_REL_I386_DIR32NB = 0x0007, + IMAGE_REL_I386_SEG12 = 0x0009, + IMAGE_REL_I386_SECTION = 0x000A, + IMAGE_REL_I386_SECREL = 0x000B, + IMAGE_REL_I386_TOKEN = 0x000C, + IMAGE_REL_I386_SECREL7 = 0x000D, + IMAGE_REL_I386_REL32 = 0x0014, + + IMAGE_REL_AMD64_ABSOLUTE = 0x0000, + IMAGE_REL_AMD64_ADDR64 = 0x0001, + IMAGE_REL_AMD64_ADDR32 = 0x0002, + IMAGE_REL_AMD64_ADDR32NB = 0x0003, + IMAGE_REL_AMD64_REL32 = 0x0004, + IMAGE_REL_AMD64_REL32_1 = 0x0005, + IMAGE_REL_AMD64_REL32_2 = 0x0006, + IMAGE_REL_AMD64_REL32_3 = 0x0007, + IMAGE_REL_AMD64_REL32_4 = 0x0008, + IMAGE_REL_AMD64_REL32_5 = 0x0009, + IMAGE_REL_AMD64_SECTION = 0x000A, + IMAGE_REL_AMD64_SECREL = 0x000B, + IMAGE_REL_AMD64_SECREL7 = 0x000C, + IMAGE_REL_AMD64_TOKEN = 0x000D, + IMAGE_REL_AMD64_SREL32 = 0x000E, + IMAGE_REL_AMD64_PAIR = 0x000F, + IMAGE_REL_AMD64_SSPAN32 = 0x0010 + }; + + enum COMDATType { + IMAGE_COMDAT_SELECT_NODUPLICATES = 1, + IMAGE_COMDAT_SELECT_ANY, + IMAGE_COMDAT_SELECT_SAME_SIZE, + IMAGE_COMDAT_SELECT_EXACT_MATCH, + IMAGE_COMDAT_SELECT_ASSOCIATIVE, + IMAGE_COMDAT_SELECT_LARGEST + }; + + // Auxiliary Symbol Formats + struct AuxiliaryFunctionDefinition { + uint32_t TagIndex; + uint32_t TotalSize; + uint32_t PointerToLinenumber; + uint32_t PointerToNextFunction; + uint8_t unused[2]; + }; + + struct AuxiliarybfAndefSymbol { + uint8_t unused1[4]; + uint16_t Linenumber; + uint8_t unused2[6]; + uint32_t PointerToNextFunction; + uint8_t unused3[2]; + }; + + struct AuxiliaryWeakExternal { + uint32_t TagIndex; + uint32_t Characteristics; + uint8_t unused[10]; + }; + + /// These are not documented in the spec, but are located in WinNT.h. + enum WeakExternalCharacteristics { + IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1, + IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2, + IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 + }; + + struct AuxiliaryFile { + uint8_t FileName[18]; + }; + + struct AuxiliarySectionDefinition { + uint32_t Length; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t CheckSum; + uint16_t Number; + uint8_t Selection; + uint8_t unused[3]; + }; + + union Auxiliary { + AuxiliaryFunctionDefinition FunctionDefinition; + AuxiliarybfAndefSymbol bfAndefSymbol; + AuxiliaryWeakExternal WeakExternal; + AuxiliaryFile File; + AuxiliarySectionDefinition SectionDefinition; + }; + +} // End namespace llvm. +} // End namespace COFF. + +#endif diff --git a/final/include/llvm/Support/CallSite.h b/final/include/llvm/Support/CallSite.h new file mode 100644 index 00000000000..8a998a8cd0d --- /dev/null +++ b/final/include/llvm/Support/CallSite.h @@ -0,0 +1,301 @@ +//===-- llvm/Support/CallSite.h - Abstract Call & Invoke instrs -*- 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 CallSite class, which is a handy wrapper for code that +// wants to treat Call and Invoke instructions in a generic way. When in non- +// mutation context (e.g. an analysis) ImmutableCallSite should be used. +// Finally, when some degree of customization is necessary between these two +// extremes, CallSiteBase<> can be supplied with fine-tuned parameters. +// +// NOTE: These classes are supposed to have "value semantics". So they should be +// passed by value, not by reference; they should not be "new"ed or "delete"d. +// They are efficiently copyable, assignable and constructable, with cost +// equivalent to copying a pointer (notice that they have only a single data +// member). The internal representation carries a flag which indicates which of +// the two variants is enclosed. This allows for cheaper checks when various +// accessors of CallSite are employed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CALLSITE_H +#define LLVM_SUPPORT_CALLSITE_H + +#include "llvm/Attributes.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/BasicBlock.h" +#include "llvm/CallingConv.h" +#include "llvm/Instructions.h" + +namespace llvm { + +class CallInst; +class InvokeInst; + +template +class CallSiteBase { +protected: + PointerIntPair I; +public: + CallSiteBase() : I(0, false) {} + CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } + CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } + CallSiteBase(ValTy *II) { *this = get(II); } +protected: + /// CallSiteBase::get - This static method is sort of like a constructor. It + /// will create an appropriate call site for a Call or Invoke instruction, but + /// it can also create a null initialized CallSiteBase object for something + /// which is NOT a call site. + /// + static CallSiteBase get(ValTy *V) { + if (InstrTy *II = dyn_cast(V)) { + if (II->getOpcode() == Instruction::Call) + return CallSiteBase(static_cast(II)); + else if (II->getOpcode() == Instruction::Invoke) + return CallSiteBase(static_cast(II)); + } + return CallSiteBase(); + } +public: + /// isCall - true if a CallInst is enclosed. + /// Note that !isCall() does not mean it is an InvokeInst enclosed, + /// it also could signify a NULL Instruction pointer. + bool isCall() const { return I.getInt(); } + + /// isInvoke - true if a InvokeInst is enclosed. + /// + bool isInvoke() const { return getInstruction() && !I.getInt(); } + + InstrTy *getInstruction() const { return I.getPointer(); } + InstrTy *operator->() const { return I.getPointer(); } + operator bool() const { return I.getPointer(); } + + /// getCalledValue - Return the pointer to function that is being called... + /// + ValTy *getCalledValue() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + return *getCallee(); + } + + /// getCalledFunction - Return the function being called if this is a direct + /// call, otherwise return null (if it's an indirect call). + /// + FunTy *getCalledFunction() const { + return dyn_cast(getCalledValue()); + } + + /// setCalledFunction - Set the callee to the specified value... + /// + void setCalledFunction(Value *V) { + assert(getInstruction() && "Not a call or invoke instruction!"); + *getCallee() = V; + } + + /// isCallee - Determine whether the passed iterator points to the + /// callee operand's Use. + /// + bool isCallee(value_use_iterator UI) const { + return getCallee() == &UI.getUse(); + } + + ValTy *getArgument(unsigned ArgNo) const { + assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); + return *(arg_begin() + ArgNo); + } + + void setArgument(unsigned ArgNo, Value* newVal) { + assert(getInstruction() && "Not a call or invoke instruction!"); + assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); + getInstruction()->setOperand(ArgNo, newVal); + } + + /// Given a value use iterator, returns the argument that corresponds to it. + /// Iterator must actually correspond to an argument. + unsigned getArgumentNo(value_use_iterator I) const { + assert(getInstruction() && "Not a call or invoke instruction!"); + assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end() + && "Argument # out of range!"); + return &I.getUse() - arg_begin(); + } + + /// arg_iterator - The type of iterator to use when looping over actual + /// arguments at this call site... + typedef IterTy arg_iterator; + + /// arg_begin/arg_end - Return iterators corresponding to the actual argument + /// list for a call site. + IterTy arg_begin() const { + assert(getInstruction() && "Not a call or invoke instruction!"); + // Skip non-arguments + return (*this)->op_begin(); + } + + IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } + bool arg_empty() const { return arg_end() == arg_begin(); } + unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } + + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType() const { return (*this)->getType(); } + + /// getCaller - Return the caller function for this call site + /// + FunTy *getCaller() const { return (*this)->getParent()->getParent(); } + +#define CALLSITE_DELEGATE_GETTER(METHOD) \ + InstrTy *II = getInstruction(); \ + return isCall() \ + ? cast(II)->METHOD \ + : cast(II)->METHOD + +#define CALLSITE_DELEGATE_SETTER(METHOD) \ + InstrTy *II = getInstruction(); \ + if (isCall()) \ + cast(II)->METHOD; \ + else \ + cast(II)->METHOD + + /// getCallingConv/setCallingConv - get or set the calling convention of the + /// call. + CallingConv::ID getCallingConv() const { + CALLSITE_DELEGATE_GETTER(getCallingConv()); + } + void setCallingConv(CallingConv::ID CC) { + CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); + } + + /// getAttributes/setAttributes - get or set the parameter attributes of + /// the call. + const AttrListPtr &getAttributes() const { + CALLSITE_DELEGATE_GETTER(getAttributes()); + } + void setAttributes(const AttrListPtr &PAL) { + CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); + } + + /// paramHasAttr - whether the call or the callee has the given attribute. + bool paramHasAttr(uint16_t i, Attributes attr) const { + CALLSITE_DELEGATE_GETTER(paramHasAttr(i, attr)); + } + + /// @brief Extract the alignment for a call or parameter (0=unknown). + uint16_t getParamAlignment(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); + } + + /// @brief Return true if the call should not be inlined. + bool isNoInline() const { + CALLSITE_DELEGATE_GETTER(isNoInline()); + } + void setIsNoInline(bool Value = true) { + CALLSITE_DELEGATE_SETTER(setIsNoInline(Value)); + } + + /// @brief Determine if the call does not access memory. + bool doesNotAccessMemory() const { + CALLSITE_DELEGATE_GETTER(doesNotAccessMemory()); + } + void setDoesNotAccessMemory(bool doesNotAccessMemory = true) { + CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory(doesNotAccessMemory)); + } + + /// @brief Determine if the call does not access or only reads memory. + bool onlyReadsMemory() const { + CALLSITE_DELEGATE_GETTER(onlyReadsMemory()); + } + void setOnlyReadsMemory(bool onlyReadsMemory = true) { + CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory(onlyReadsMemory)); + } + + /// @brief Determine if the call cannot return. + bool doesNotReturn() const { + CALLSITE_DELEGATE_GETTER(doesNotReturn()); + } + void setDoesNotReturn(bool doesNotReturn = true) { + CALLSITE_DELEGATE_SETTER(setDoesNotReturn(doesNotReturn)); + } + + /// @brief Determine if the call cannot unwind. + bool doesNotThrow() const { + CALLSITE_DELEGATE_GETTER(doesNotThrow()); + } + void setDoesNotThrow(bool doesNotThrow = true) { + CALLSITE_DELEGATE_SETTER(setDoesNotThrow(doesNotThrow)); + } + +#undef CALLSITE_DELEGATE_GETTER +#undef CALLSITE_DELEGATE_SETTER + + /// hasArgument - Returns true if this CallSite passes the given Value* as an + /// argument to the called function. + bool hasArgument(const Value *Arg) const { + for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E; + ++AI) + if (AI->get() == Arg) + return true; + return false; + } + +private: + unsigned getArgumentEndOffset() const { + if (isCall()) + return 1; // Skip Callee + else + return 3; // Skip BB, BB, Callee + } + + IterTy getCallee() const { + if (isCall()) // Skip Callee + return cast(getInstruction())->op_end() - 1; + else // Skip BB, BB, Callee + return cast(getInstruction())->op_end() - 3; + } +}; + +class CallSite : public CallSiteBase { + typedef CallSiteBase Base; +public: + CallSite() {} + CallSite(Base B) : Base(B) {} + CallSite(Value* V) : Base(V) {} + CallSite(CallInst *CI) : Base(CI) {} + CallSite(InvokeInst *II) : Base(II) {} + CallSite(Instruction *II) : Base(II) {} + + bool operator==(const CallSite &CS) const { return I == CS.I; } + bool operator!=(const CallSite &CS) const { return I != CS.I; } + bool operator<(const CallSite &CS) const { + return getInstruction() < CS.getInstruction(); + } + +private: + User::op_iterator getCallee() const; +}; + +/// ImmutableCallSite - establish a view to a call site for examination +class ImmutableCallSite : public CallSiteBase<> { + typedef CallSiteBase<> Base; +public: + ImmutableCallSite(const Value* V) : Base(V) {} + ImmutableCallSite(const CallInst *CI) : Base(CI) {} + ImmutableCallSite(const InvokeInst *II) : Base(II) {} + ImmutableCallSite(const Instruction *II) : Base(II) {} + ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Casting.h b/final/include/llvm/Support/Casting.h new file mode 100644 index 00000000000..6bb98064382 --- /dev/null +++ b/final/include/llvm/Support/Casting.h @@ -0,0 +1,241 @@ +//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- 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 isa(), cast(), dyn_cast(), cast_or_null(), +// and dyn_cast_or_null() templates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CASTING_H +#define LLVM_SUPPORT_CASTING_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// isa Support Templates +//===----------------------------------------------------------------------===// + +template struct isa_impl_cl; + +// Define a template that can be specialized by smart pointers to reflect the +// fact that they are automatically dereferenced, and are not involved with the +// template selection process... the default implementation is a noop. +// +template struct simplify_type { + typedef From SimpleType; // The real type this represents... + + // An accessor to get the real value... + static SimpleType &getSimplifiedValue(From &Val) { return Val; } +}; + +template struct simplify_type { + typedef const From SimpleType; + static SimpleType &getSimplifiedValue(const From &Val) { + return simplify_type::getSimplifiedValue(static_cast(Val)); + } +}; + + +// isa - Return true if the parameter to the template is an instance of the +// template type argument. Used like this: +// +// if (isa(myVal)) { ... } +// +template +struct isa_impl { + static inline bool doit(const From &Val) { + return To::classof(&Val); + } +}; + +template +struct isa_impl_wrap { + // When From != SimplifiedType, we can simplify the type some more by using + // the simplify_type template. + static bool doit(const From &Val) { + return isa_impl_cl::template + isa(simplify_type::getSimplifiedValue(Val)); + } +}; + +template +struct isa_impl_wrap { + // When From == SimpleType, we are as simple as we are going to get. + static bool doit(const FromTy &Val) { + return isa_impl::doit(Val); + } +}; + +// isa_impl_cl - Use class partial specialization to transform types to a single +// canonical form for isa_impl. +// +template +struct isa_impl_cl { + template + static bool isa(const FromCl &Val) { + return isa_impl_wrap::SimpleType>::doit(Val); + } +}; + +// Specialization used to strip const qualifiers off of the FromCl type... +template +struct isa_impl_cl { + template + static bool isa(const FromCl &Val) { + return isa_impl_cl::template isa(Val); + } +}; + +// Define pointer traits in terms of base traits... +template +struct isa_impl_cl { + template + static bool isa(FromCl *Val) { + return isa_impl_cl::template isa(*Val); + } +}; + +// Define reference traits in terms of base traits... +template +struct isa_impl_cl { + template + static bool isa(FromCl &Val) { + return isa_impl_cl::template isa(&Val); + } +}; + +template +inline bool isa(const Y &Val) { + return isa_impl_cl::template isa(Val); +} + +//===----------------------------------------------------------------------===// +// cast Support Templates +//===----------------------------------------------------------------------===// + +template struct cast_retty; + + +// Calculate what type the 'cast' function should return, based on a requested +// type of To and a source type of From. +template struct cast_retty_impl { + typedef To& ret_type; // Normal case, return Ty& +}; +template struct cast_retty_impl { + typedef const To &ret_type; // Normal case, return Ty& +}; + +template struct cast_retty_impl { + typedef To* ret_type; // Pointer arg case, return Ty* +}; + +template struct cast_retty_impl { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + +template struct cast_retty_impl { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + + +template +struct cast_retty_wrap { + // When the simplified type and the from type are not the same, use the type + // simplifier to reduce the type, then reuse cast_retty_impl to get the + // resultant type. + typedef typename cast_retty::ret_type ret_type; +}; + +template +struct cast_retty_wrap { + // When the simplified type is equal to the from type, use it directly. + typedef typename cast_retty_impl::ret_type ret_type; +}; + +template +struct cast_retty { + typedef typename cast_retty_wrap::SimpleType>::ret_type ret_type; +}; + +// Ensure the non-simple values are converted using the simplify_type template +// that may be specialized by smart pointers... +// +template struct cast_convert_val { + // This is not a simple type, use the template to simplify it... + static typename cast_retty::ret_type doit(const From &Val) { + return cast_convert_val::SimpleType>::doit( + simplify_type::getSimplifiedValue(Val)); + } +}; + +template struct cast_convert_val { + // This _is_ a simple type, just cast it. + static typename cast_retty::ret_type doit(const FromTy &Val) { + typename cast_retty::ret_type Res2 + = (typename cast_retty::ret_type)const_cast(Val); + return Res2; + } +}; + + + +// cast - Return the argument parameter cast to the specified type. This +// casting operator asserts that the type is correct, so it does not return null +// on failure. But it will correctly return NULL when the input is NULL. +// Used Like this: +// +// cast(myVal)->getParent() +// +template +inline typename cast_retty::ret_type cast(const Y &Val) { + assert(isa(Val) && "cast() argument of incompatible type!"); + return cast_convert_val::SimpleType>::doit(Val); +} + +// cast_or_null - Functionally identical to cast, except that a null value is +// accepted. +// +template +inline typename cast_retty::ret_type cast_or_null(Y *Val) { + if (Val == 0) return 0; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + + +// dyn_cast - Return the argument parameter cast to the specified type. This +// casting operator returns null if the argument is of the wrong type, so it can +// be used to test for a type as well as cast if successful. This should be +// used in the context of an if statement like this: +// +// if (const Instruction *I = dyn_cast(myVal)) { ... } +// + +template +inline typename cast_retty::ret_type dyn_cast(const Y &Val) { + return isa(Val) ? cast(Val) : 0; +} + +// dyn_cast_or_null - Functionally identical to dyn_cast, except that a null +// value is accepted. +// +template +inline typename cast_retty::ret_type dyn_cast_or_null(Y *Val) { + return (Val && isa(Val)) ? cast(Val) : 0; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/CommandLine.h b/final/include/llvm/Support/CommandLine.h new file mode 100644 index 00000000000..9ae3d6af32e --- /dev/null +++ b/final/include/llvm/Support/CommandLine.h @@ -0,0 +1,1391 @@ +//===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you should +// read the library documentation located in docs/CommandLine.html or looks at +// the many example usages in tools/*/*.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMMANDLINE_H +#define LLVM_SUPPORT_COMMANDLINE_H + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include +#include +#include +#include +#include + +namespace llvm { + +/// cl Namespace - This namespace contains all of the command line option +/// processing machinery. It is intentionally a short name to make qualified +/// usage concise. +namespace cl { + +//===----------------------------------------------------------------------===// +// ParseCommandLineOptions - Command line option processing entry point. +// +void ParseCommandLineOptions(int argc, char **argv, + const char *Overview = 0, + bool ReadResponseFiles = false); + +//===----------------------------------------------------------------------===// +// ParseEnvironmentOptions - Environment variable option processing alternate +// entry point. +// +void ParseEnvironmentOptions(const char *progName, const char *envvar, + const char *Overview = 0, + bool ReadResponseFiles = false); + +///===---------------------------------------------------------------------===// +/// SetVersionPrinter - Override the default (LLVM specific) version printer +/// used to print out the version when --version is given +/// on the command line. This allows other systems using the +/// CommandLine utilities to print their own version string. +void SetVersionPrinter(void (*func)()); + + +// MarkOptionsChanged - Internal helper function. +void MarkOptionsChanged(); + +//===----------------------------------------------------------------------===// +// Flags permitted to be passed to command line arguments +// + +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x01, // Zero or One occurrence + ZeroOrMore = 0x02, // Zero or more occurrences allowed + Required = 0x03, // One occurrence required + OneOrMore = 0x04, // One or more occurrences required + + // ConsumeAfter - Indicates that this option is fed anything that follows the + // last positional argument required by the application (it is an error if + // there are zero positional arguments, and a ConsumeAfter option is used). + // Thus, for example, all arguments to LLI are processed until a filename is + // found. Once a filename is found, all of the succeeding arguments are + // passed, unprocessed, to the ConsumeAfter option. + // + ConsumeAfter = 0x05, + + OccurrencesMask = 0x07 +}; + +enum ValueExpected { // Is a value required for the option? + ValueOptional = 0x08, // The value can appear... or not + ValueRequired = 0x10, // The value is required to appear! + ValueDisallowed = 0x18, // A value may not be specified (for flags) + ValueMask = 0x18 +}; + +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x20, // Option included in -help & -help-hidden + Hidden = 0x40, // -help doesn't, but -help-hidden does + ReallyHidden = 0x60, // Neither -help nor -help-hidden show this arg + HiddenMask = 0x60 +}; + +// Formatting flags - This controls special features that the option might have +// that cause it to be parsed differently... +// +// Prefix - This option allows arguments that are otherwise unrecognized to be +// matched by options that are a prefix of the actual value. This is useful for +// cases like a linker, where options are typically of the form '-lfoo' or +// '-L../../include' where -l or -L are the actual flags. When prefix is +// enabled, and used, the value for the flag comes from the suffix of the +// argument. +// +// Grouping - With this option enabled, multiple letter options are allowed to +// bunch together with only a single hyphen for the whole group. This allows +// emulation of the behavior that ls uses for example: ls -la === ls -l -a +// + +enum FormattingFlags { + NormalFormatting = 0x000, // Nothing special + Positional = 0x080, // Is a positional argument, no '-' required + Prefix = 0x100, // Can this option directly prefix its value? + Grouping = 0x180, // Can this option group with other options? + FormattingMask = 0x180 // Union of the above flags. +}; + +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x200, // Should this cl::list split between commas? + PositionalEatsArgs = 0x400, // Should this positional cl::list eat -args? + Sink = 0x800, // Should this cl::list eat all unknown options? + MiscMask = 0xE00 // Union of the above flags. +}; + + + +//===----------------------------------------------------------------------===// +// Option Base class +// +class alias; +class Option { + friend class alias; + + // handleOccurrences - Overriden by subclasses to handle the value passed into + // an argument. Should return true if there was an error processing the + // argument and the program should exit. + // + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) = 0; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // Out of line virtual function to provide home for the class. + virtual void anchor(); + + int NumOccurrences; // The number of times specified + int Flags; // Flags for the argument + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals;// Greater than 0 for multi-valued option. + Option *NextRegistered; // Singly linked list of registered options. +public: + const char *ArgStr; // The argument string itself (ex: "help", "o") + const char *HelpStr; // The descriptive text message for -help + const char *ValueStr; // String describing what the value of this option is + + inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { + return static_cast(Flags & OccurrencesMask); + } + inline enum ValueExpected getValueExpectedFlag() const { + int VE = Flags & ValueMask; + return VE ? static_cast(VE) + : getValueExpectedFlagDefault(); + } + inline enum OptionHidden getOptionHiddenFlag() const { + return static_cast(Flags & HiddenMask); + } + inline enum FormattingFlags getFormattingFlag() const { + return static_cast(Flags & FormattingMask); + } + inline unsigned getMiscFlags() const { + return Flags & MiscMask; + } + inline unsigned getPosition() const { return Position; } + inline unsigned getNumAdditionalVals() const { return AdditionalVals; } + + // hasArgStr - Return true if the argstr != "" + bool hasArgStr() const { return ArgStr[0] != 0; } + + //-------------------------------------------------------------------------=== + // Accessor functions set by OptionModifiers + // + void setArgStr(const char *S) { ArgStr = S; } + void setDescription(const char *S) { HelpStr = S; } + void setValueStr(const char *S) { ValueStr = S; } + + void setFlag(unsigned Flag, unsigned FlagMask) { + Flags &= ~FlagMask; + Flags |= Flag; + } + + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { + setFlag(Val, OccurrencesMask); + } + void setValueExpectedFlag(enum ValueExpected Val) { setFlag(Val, ValueMask); } + void setHiddenFlag(enum OptionHidden Val) { setFlag(Val, HiddenMask); } + void setFormattingFlag(enum FormattingFlags V) { setFlag(V, FormattingMask); } + void setMiscFlag(enum MiscFlags M) { setFlag(M, M); } + void setPosition(unsigned pos) { Position = pos; } +protected: + explicit Option(unsigned DefaultFlags) + : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0), + AdditionalVals(0), NextRegistered(0), + ArgStr(""), HelpStr(""), ValueStr("") { + assert(getNumOccurrencesFlag() != 0 && + getOptionHiddenFlag() != 0 && "Not all default flags specified!"); + } + + inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } +public: + // addArgument - Register this argument with the commandline system. + // + void addArgument(); + + Option *getNextRegisteredOption() const { return NextRegistered; } + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth() const = 0; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(size_t GlobalWidth) const = 0; + + virtual void getExtraOptionNames(SmallVectorImpl &) {} + + // addOccurrence - Wrapper around handleOccurrence that enforces Flags. + // + bool addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg = false); + + // Prints option name followed by message. Always returns true. + bool error(const Twine &Message, StringRef ArgName = StringRef()); + +public: + inline int getNumOccurrences() const { return NumOccurrences; } + virtual ~Option() {} +}; + + +//===----------------------------------------------------------------------===// +// Command line option modifiers that can be used to modify the behavior of +// command line option parsers... +// + +// desc - Modifier to set the description shown in the -help output... +struct desc { + const char *Desc; + desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setDescription(Desc); } +}; + +// value_desc - Modifier to set the value description shown in the -help +// output... +struct value_desc { + const char *Desc; + value_desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setValueStr(Desc); } +}; + +// init - Specify a default (initial) value for the command line argument, if +// the default constructor for the argument type does not give you what you +// want. This is only valid on "opt" arguments, not on "list" arguments. +// +template +struct initializer { + const Ty &Init; + initializer(const Ty &Val) : Init(Val) {} + + template + void apply(Opt &O) const { O.setInitialValue(Init); } +}; + +template +initializer init(const Ty &Val) { + return initializer(Val); +} + + +// location - Allow the user to specify which external variable they want to +// store the results of the command line argument processing into, if they don't +// want to store it in the option itself. +// +template +struct LocationClass { + Ty &Loc; + LocationClass(Ty &L) : Loc(L) {} + + template + void apply(Opt &O) const { O.setLocation(O, Loc); } +}; + +template +LocationClass location(Ty &L) { return LocationClass(L); } + + +//===----------------------------------------------------------------------===// +// Enum valued command line option +// +#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC +#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC +#define clEnumValEnd (reinterpret_cast(0)) + +// values - For custom data types, allow specifying a group of values together +// as the values that go into the mapping that the option handler uses. Note +// that the values list must always have a 0 at the end of the list to indicate +// that the list has ended. +// +template +class ValuesClass { + // Use a vector instead of a map, because the lists should be short, + // the overhead is less, and most importantly, it keeps them in the order + // inserted so we can print our option out nicely. + SmallVector >,4> Values; + void processValues(va_list Vals); +public: + ValuesClass(const char *EnumName, DataType Val, const char *Desc, + va_list ValueArgs) { + // Insert the first value, which is required. + Values.push_back(std::make_pair(EnumName, std::make_pair(Val, Desc))); + + // Process the varargs portion of the values... + while (const char *enumName = va_arg(ValueArgs, const char *)) { + DataType EnumVal = static_cast(va_arg(ValueArgs, int)); + const char *EnumDesc = va_arg(ValueArgs, const char *); + Values.push_back(std::make_pair(enumName, // Add value to value map + std::make_pair(EnumVal, EnumDesc))); + } + } + + template + void apply(Opt &O) const { + for (unsigned i = 0, e = static_cast(Values.size()); + i != e; ++i) + O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, + Values[i].second.second); + } +}; + +template +ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, + const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; +} + + +//===----------------------------------------------------------------------===// +// parser class - Parameterizable parser for different data types. By default, +// known data types (string, int, bool) have specialized parsers, that do what +// you would expect. The default parser, used for data types that are not +// built-in, uses a mapping table to map specific options to values, which is +// used, among other things, to handle enum types. + +//-------------------------------------------------- +// generic_parser_base - This class holds all the non-generic code that we do +// not need replicated for every instance of the generic parser. This also +// allows us to put stuff into CommandLine.cpp +// +struct generic_parser_base { + virtual ~generic_parser_base() {} // Base class should have virtual-dtor + + // getNumOptions - Virtual function implemented by generic subclass to + // indicate how many entries are in Values. + // + virtual unsigned getNumOptions() const = 0; + + // getOption - Return option name N. + virtual const char *getOption(unsigned N) const = 0; + + // getDescription - Return description N + virtual const char *getDescription(unsigned N) const = 0; + + // Return the width of the option tag for printing... + virtual size_t getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + void initialize(Option &O) { + // All of the modifiers for the option have been processed by now, so the + // argstr field should be stable, copy it down now. + // + hasArgStr = O.hasArgStr(); + } + + void getExtraOptionNames(SmallVectorImpl &OptionNames) { + // If there has been no argstr specified, that means that we need to add an + // argument for every possible option. This ensures that our options are + // vectored to us. + if (!hasArgStr) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + OptionNames.push_back(getOption(i)); + } + + + enum ValueExpected getValueExpectedFlagDefault() const { + // If there is an ArgStr specified, then we are of the form: + // + // -opt=O2 or -opt O2 or -optO2 + // + // In which case, the value is required. Otherwise if an arg str has not + // been specified, we are of the form: + // + // -O2 or O2 or -la (where -l and -a are separate options) + // + // If this is the case, we cannot allow a value. + // + if (hasArgStr) + return ValueRequired; + else + return ValueDisallowed; + } + + // findOption - Return the option number corresponding to the specified + // argument string. If the option is not found, getNumOptions() is returned. + // + unsigned findOption(const char *Name); + +protected: + bool hasArgStr; +}; + +// Default parser implementation - This implementation depends on having a +// mapping of recognized options to values of some sort. In addition to this, +// each entry in the mapping also tracks a help message that is printed with the +// command line option for -help. Because this is a simple mapping parser, the +// data type can be any unsupported type. +// +template +class parser : public generic_parser_base { +protected: + class OptionInfo { + public: + OptionInfo(const char *name, DataType v, const char *helpStr) : + Name(name), V(v), HelpStr(helpStr) {} + const char *Name; + DataType V; + const char *HelpStr; + }; + SmallVector Values; +public: + typedef DataType parser_data_type; + + // Implement virtual functions needed by generic_parser_base + unsigned getNumOptions() const { return unsigned(Values.size()); } + const char *getOption(unsigned N) const { return Values[N].Name; } + const char *getDescription(unsigned N) const { + return Values[N].HelpStr; + } + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { + StringRef ArgVal; + if (hasArgStr) + ArgVal = Arg; + else + ArgVal = ArgName; + + for (unsigned i = 0, e = static_cast(Values.size()); + i != e; ++i) + if (Values[i].Name == ArgVal) { + V = Values[i].V; + return false; + } + + return O.error("Cannot find option named '" + ArgVal + "'!"); + } + + /// addLiteralOption - Add an entry to the mapping table. + /// + template + void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) { + assert(findOption(Name) == Values.size() && "Option already exists!"); + OptionInfo X(Name, static_cast(V), HelpStr); + Values.push_back(X); + MarkOptionsChanged(); + } + + /// removeLiteralOption - Remove the specified option. + /// + void removeLiteralOption(const char *Name) { + unsigned N = findOption(Name); + assert(N != Values.size() && "Option not found!"); + Values.erase(Values.begin()+N); + } +}; + +//-------------------------------------------------- +// basic_parser - Super class of parsers to provide boilerplate code +// +class basic_parser_impl { // non-template implementation of basic_parser +public: + virtual ~basic_parser_impl() {} + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueRequired; + } + + void getExtraOptionNames(SmallVectorImpl &) {} + + void initialize(Option &) {} + + // Return the width of the option tag for printing... + size_t getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + void printOptionInfo(const Option &O, size_t GlobalWidth) const; + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "value"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +// basic_parser - The real basic parser is just a template wrapper that provides +// a typedef for the provided data type. +// +template +class basic_parser : public basic_parser_impl { +public: + typedef DataType parser_data_type; +}; + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { + const char *ArgStr; +public: + + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); + + template + void initialize(Opt &O) { + ArgStr = O.ArgStr; + } + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print = at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print = at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "int"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "uint"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { + Value = Arg.str(); + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "string"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//-------------------------------------------------- +// parser +// +template<> +class parser : public basic_parser { +public: + // parse - Return true on error. + bool parse(Option &, StringRef, StringRef Arg, char &Value) { + Value = Arg[0]; + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "char"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); + +//===----------------------------------------------------------------------===// +// applicator class - This class is used because we must use partial +// specialization to handle literal string arguments specially (const char* does +// not correctly respond to the apply method). Because the syntax to use this +// is a pain, we have the 'apply' method below to handle the nastiness... +// +template struct applicator { + template + static void opt(const Mod &M, Opt &O) { M.apply(O); } +}; + +// Handle const char* as a special case... +template struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template<> struct applicator { + template + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; + +template<> struct applicator { + static void opt(NumOccurrencesFlag NO, Option &O) { + O.setNumOccurrencesFlag(NO); + } +}; +template<> struct applicator { + static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } +}; +template<> struct applicator { + static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } +}; +template<> struct applicator { + static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } +}; +template<> struct applicator { + static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } +}; + +// apply method - Apply a modifier to an option in a type safe way. +template +void apply(const Mod &M, Opt *O) { + applicator::opt(M, *O); +} + + +//===----------------------------------------------------------------------===// +// opt_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class opt_storage { + DataType *Location; // Where to store the object... + + void check() const { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage, " + "or cl::init specified before cl::location()!!"); + } +public: + opt_storage() : Location(0) {} + + bool setLocation(Option &O, DataType &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void setValue(const T &V) { + check(); + *Location = V; + } + + DataType &getValue() { check(); return *Location; } + const DataType &getValue() const { check(); return *Location; } + + operator DataType() const { return this->getValue(); } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template +class opt_storage : public DataType { +public: + template + void setValue(const T &V) { DataType::operator=(V); } + + DataType &getValue() { return *this; } + const DataType &getValue() const { return *this; } +}; + +// Define a partial specialization to handle things we cannot inherit from. In +// this case, we store an instance through containment, and overload operators +// to get at the value. +// +template +class opt_storage { +public: + DataType Value; + + // Make sure we initialize the value with the default constructor for the + // type. + opt_storage() : Value(DataType()) {} + + template + void setValue(const T &V) { Value = V; } + DataType &getValue() { return Value; } + DataType getValue() const { return Value; } + + operator DataType() const { return getValue(); } + + // If the datatype is a pointer, support -> on it. + DataType operator->() const { return Value; } +}; + + +//===----------------------------------------------------------------------===// +// opt - A scalar command line option. +// +template > +class opt : public Option, + public opt_storage::value> { + ParserClass Parser; + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse error! + this->setValue(Val); + this->setPosition(pos); + return false; + } + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + // setInitialValue - Used by the cl::init modifier... + void setInitialValue(const DataType &V) { this->setValue(V); } + + ParserClass &getParser() { return Parser; } + + template + DataType &operator=(const T &Val) { + this->setValue(Val); + return this->getValue(); + } + + // One option... + template + explicit opt(const M0t &M0) : Option(Optional | NotHidden) { + apply(M0, this); + done(); + } + + // Two options... + template + opt(const M0t &M0, const M1t &M1) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + + // Three options... + template + opt(const M0t &M0, const M1t &M1, + const M2t &M2) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, + const M3t &M3) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, + const M6t &M6) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); +EXTERN_TEMPLATE_INSTANTIATION(class opt); + +//===----------------------------------------------------------------------===// +// list_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class list_storage { + StorageClass *Location; // Where to store the object... + +public: + list_storage() : Location(0) {} + + bool setLocation(Option &O, StorageClass &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + Location->push_back(V); + } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template +class list_storage : public std::vector { +public: + template + void addValue(const T &V) { std::vector::push_back(V); } +}; + + +//===----------------------------------------------------------------------===// +// list - A list of command line options. +// +template > +class list : public Option, public list_storage { + std::vector Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + list_storage::addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + void setNumAdditionalVals(unsigned n) { + Option::setNumAdditionalVals(n); + } + + // One option... + template + explicit list(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template + list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +// multi_val - Modifier to set the number of additional values. +struct multi_val { + unsigned AdditionalVals; + explicit multi_val(unsigned N) : AdditionalVals(N) {} + + template + void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } +}; + + +//===----------------------------------------------------------------------===// +// bits_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template +class bits_storage { + unsigned *Location; // Where to store the bits... + + template + static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast(V); + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + bits_storage() : Location(0) {} + + bool setLocation(Option &O, unsigned &L) { + if (Location) + return O.error("cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + *Location |= Bit(V); + } + + unsigned getBits() { return *Location; } + + template + bool isSet(const T &V) { + return (*Location & Bit(V)) != 0; + } +}; + + +// Define how to hold bits. Since we can inherit from a class, we do so. +// This makes us exactly compatible with the bits in all cases that it is used. +// +template +class bits_storage { + unsigned Bits; // Where to store the bits... + + template + static unsigned Bit(const T &V) { + unsigned BitPos = (unsigned)V; + assert(BitPos < sizeof(unsigned) * CHAR_BIT && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + template + void addValue(const T &V) { + Bits |= Bit(V); + } + + unsigned getBits() { return Bits; } + + template + bool isSet(const T &V) { + return (Bits & Bit(V)) != 0; + } +}; + + +//===----------------------------------------------------------------------===// +// bits - A bit vector of command options. +// +template > +class bits : public Option, public bits_storage { + std::vector Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(SmallVectorImpl &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(size_t GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + // One option... + template + explicit bits(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template + bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +//===----------------------------------------------------------------------===// +// Aliased command line option (alias this name to a preexisting name) +// + +class alias : public Option { + Option *AliasFor; + virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) { + return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); + } + // Handle printing stuff... + virtual size_t getOptionWidth() const; + virtual void printOptionInfo(size_t GlobalWidth) const; + + void done() { + if (!hasArgStr()) + error("cl::alias must have argument name specified!"); + if (AliasFor == 0) + error("cl::alias must have an cl::aliasopt(option) specified!"); + addArgument(); + } +public: + void setAliasFor(Option &O) { + if (AliasFor) + error("cl::alias must only have one cl::aliasopt(...) specified!"); + AliasFor = &O; + } + + // One option... + template + explicit alias(const M0t &M0) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); + done(); + } + // Two options... + template + alias(const M0t &M0, const M1t &M1) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template + alias(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template + alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } +}; + +// aliasfor - Modifier to set the option an alias aliases. +struct aliasopt { + Option &Opt; + explicit aliasopt(Option &O) : Opt(O) {} + void apply(alias &A) const { A.setAliasFor(Opt); } +}; + +// extrahelp - provide additional help at the end of the normal help +// output. All occurrences of cl::extrahelp will be accumulated and +// printed to stderr at the end of the regular help, just before +// exit is called. +struct extrahelp { + const char * morehelp; + explicit extrahelp(const char* help); +}; + +void PrintVersionMessage(); +// This function just prints the help message, exactly the same way as if the +// -help option had been given on the command line. +// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! +void PrintHelpMessage(); + +} // End namespace cl + +} // End namespace llvm + +#endif diff --git a/final/include/llvm/Support/Compiler.h b/final/include/llvm/Support/Compiler.h new file mode 100644 index 00000000000..67f0fd7e0dc --- /dev/null +++ b/final/include/llvm/Support/Compiler.h @@ -0,0 +1,129 @@ +//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- 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 several macros, based on the current compiler. This allows +// use of compiler-specific features in a way that remains portable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPILER_H +#define LLVM_SUPPORT_COMPILER_H + +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked +/// into a shared library, then the class should be private to the library and +/// not accessible from outside it. Can also be used to mark variables and +/// functions, making them private to any shared library they are linked into. +#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) +#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) +#else +#define LLVM_LIBRARY_VISIBILITY +#endif + +#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) +#else +#define LLVM_ATTRIBUTE_USED +#endif + +// Some compilers warn about unused functions. When a function is sometimes +// used or not depending on build settings (e.g. a function only called from +// within "assert"), this attribute can be used to suppress such warnings. +// +// However, it shouldn't be used for unused *variables*, as those have a much +// more portable solution: +// (void)unused_var_name; +// Prefer cast-to-void wherever it is sufficient. +#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define LLVM_ATTRIBUTE_UNUSED +#endif + +#ifdef __GNUC__ // aka 'ATTRIBUTE_CONST' but following LLVM Conventions. +#define LLVM_ATTRIBUTE_READNONE __attribute__((__const__)) +#else +#define LLVM_ATTRIBUTE_READNONE +#endif + +#ifdef __GNUC__ // aka 'ATTRIBUTE_PURE' but following LLVM Conventions. +#define LLVM_ATTRIBUTE_READONLY __attribute__((__pure__)) +#else +#define LLVM_ATTRIBUTE_READONLY +#endif + +#if (__GNUC__ >= 4) +#define BUILTIN_EXPECT(EXPR, VALUE) __builtin_expect((EXPR), (VALUE)) +#else +#define BUILTIN_EXPECT(EXPR, VALUE) (EXPR) +#endif + +// C++ doesn't support 'extern template' of template specializations. GCC does, +// but requires __extension__ before it. In the header, use this: +// EXTERN_TEMPLATE_INSTANTIATION(class foo); +// in the .cpp file, use this: +// TEMPLATE_INSTANTIATION(class foo); +#ifdef __GNUC__ +#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X +#define TEMPLATE_INSTANTIATION(X) template X +#else +#define EXTERN_TEMPLATE_INSTANTIATION(X) +#define TEMPLATE_INSTANTIATION(X) +#endif + +// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +// mark a method "not for inlining". +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +#define LLVM_ATTRIBUTE_NOINLINE +#endif + +// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +// so, mark a method "always inline" because it is performance sensitive. GCC +// 3.4 supported this but is buggy in various cases and produces unimplemented +// errors, just use it in GCC 4.0 and later. +#if __GNUC__ > 3 +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline +#else +#define LLVM_ATTRIBUTE_ALWAYS_INLINE +#endif + + +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define LLVM_ATTRIBUTE_NORETURN +#endif + +// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") +#if __has_feature(attribute_deprecated_with_message) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated(message))) +#elif defined(__GNUC__) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated)) +#elif defined(_MSC_VER) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + __declspec(deprecated(message)) decl +#else +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl +#endif + +#endif diff --git a/final/include/llvm/Support/ConstantFolder.h b/final/include/llvm/Support/ConstantFolder.h new file mode 100644 index 00000000000..bd3765d592d --- /dev/null +++ b/final/include/llvm/Support/ConstantFolder.h @@ -0,0 +1,228 @@ +//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- 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 ConstantFolder class, a helper for IRBuilder. +// It provides IRBuilder with a set of methods for creating constants +// with minimal folding. For general constant creation and folding, +// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H +#define LLVM_SUPPORT_CONSTANTFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/InstrTypes.h" + +namespace llvm { + +class LLVMContext; + +/// ConstantFolder - Create constants with minimum, target independent, folding. +class ConstantFolder { +public: + explicit ConstantFolder(LLVMContext &) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); + } + Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFAdd(LHS, RHS); + } + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); + } + Constant *CreateFSub(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFSub(LHS, RHS); + } + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); + } + Constant *CreateFMul(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFMul(LHS, RHS); + } + Constant *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getUDiv(LHS, RHS, isExact); + } + Constant *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getSDiv(LHS, RHS, isExact); + } + Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFDiv(LHS, RHS); + } + Constant *CreateURem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getURem(LHS, RHS); + } + Constant *CreateSRem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getSRem(LHS, RHS); + } + Constant *CreateFRem(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getFRem(LHS, RHS); + } + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); + } + Constant *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getLShr(LHS, RHS, isExact); + } + Constant *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getAShr(LHS, RHS, isExact); + } + Constant *CreateAnd(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getAnd(LHS, RHS); + } + Constant *CreateOr(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getOr(LHS, RHS); + } + Constant *CreateXor(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getXor(LHS, RHS); + } + + Constant *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return ConstantExpr::get(Opc, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getNeg(C, HasNUW, HasNSW); + } + Constant *CreateFNeg(Constant *C) const { + return ConstantExpr::getFNeg(C); + } + Constant *CreateNot(Constant *C) const { + return ConstantExpr::getNot(C); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Constant *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + return ConstantExpr::getCast(Op, C, DestTy); + } + Constant *CreatePointerCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getPointerCast(C, DestTy); + } + Constant *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + return ConstantExpr::getIntegerCast(C, DestTy, isSigned); + } + Constant *CreateFPCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getFPCast(C, DestTy); + } + + Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getZExtOrBitCast(C, DestTy); + } + Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getSExtOrBitCast(C, DestTy); + } + + Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getTruncOrBitCast(C, DestTy); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return ConstantExpr::getCompare(P, LHS, RHS); + } + Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return ConstantExpr::getCompare(P, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return ConstantExpr::getSelect(C, True, False); + } + + Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return ConstantExpr::getExtractElement(Vec, Idx); + } + + Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return ConstantExpr::getInsertElement(Vec, NewElt, Idx); + } + + Constant *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return ConstantExpr::getShuffleVector(V1, V2, Mask); + } + + Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getExtractValue(Agg, IdxList, NumIdx); + } + + Constant *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx) const { + return ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx); + } +}; + +} + +#endif diff --git a/final/include/llvm/Support/ConstantRange.h b/final/include/llvm/Support/ConstantRange.h new file mode 100644 index 00000000000..ced3a2cf2db --- /dev/null +++ b/final/include/llvm/Support/ConstantRange.h @@ -0,0 +1,265 @@ +//===-- llvm/Support/ConstantRange.h - Represent a range --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges: : +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +// The other integral ranges use min/max values for special range values. For +// example, for 8-bit types, it uses: +// [0, 0) = {} = Empty set +// [255, 255) = {0..255} = Full Set +// +// Note that ConstantRange can be used to represent either signed or +// unsigned ranges. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H +#define LLVM_SUPPORT_CONSTANT_RANGE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// ConstantRange - This class represents an range of values. +/// +class ConstantRange { + APInt Lower, Upper; + +public: + /// Initialize a full (the default) or empty set for the specified bit width. + /// + explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true); + + /// Initialize a range to hold the single specified value. + /// + ConstantRange(const APInt &Value); + + /// @brief Initialize a range of values explicitly. This will assert out if + /// Lower==Upper and Lower != Min or Max value for its type. It will also + /// assert out if the two APInt's are not the same bit width. + ConstantRange(const APInt &Lower, const APInt &Upper); + + /// makeICmpRegion - Produce the smallest range that contains all values that + /// might satisfy the comparison specified by Pred when compared to any value + /// contained within Other. + /// + /// Solves for range X in 'for all x in X, there exists a y in Y such that + /// icmp op x, y is true'. Every value that might make the comparison true + /// is included in the resulting range. + static ConstantRange makeICmpRegion(unsigned Pred, + const ConstantRange &Other); + + /// getLower - Return the lower value for this range... + /// + const APInt &getLower() const { return Lower; } + + /// getUpper - Return the upper value for this range... + /// + const APInt &getUpper() const { return Upper; } + + /// getBitWidth - get the bit width of this ConstantRange + /// + uint32_t getBitWidth() const { return Lower.getBitWidth(); } + + /// isFullSet - Return true if this set contains all of the elements possible + /// for this data-type + /// + bool isFullSet() const; + + /// isEmptySet - Return true if this set contains no members. + /// + bool isEmptySet() const; + + /// isWrappedSet - Return true if this set wraps around the top of the range, + /// for example: [100, 8) + /// + bool isWrappedSet() const; + + /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of + /// its bitwidth, for example: i8 [120, 140). + /// + bool isSignWrappedSet() const; + + /// contains - Return true if the specified value is in the set. + /// + bool contains(const APInt &Val) const; + + /// contains - Return true if the other range is a subset of this one. + /// + bool contains(const ConstantRange &CR) const; + + /// getSingleElement - If this set contains a single element, return it, + /// otherwise return null. + /// + const APInt *getSingleElement() const { + if (Upper == Lower + 1) + return &Lower; + return 0; + } + + /// isSingleElement - Return true if this set contains exactly one member. + /// + bool isSingleElement() const { return getSingleElement() != 0; } + + /// getSetSize - Return the number of elements in this set. + /// + APInt getSetSize() const; + + /// getUnsignedMax - Return the largest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMax() const; + + /// getUnsignedMin - Return the smallest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMin() const; + + /// getSignedMax - Return the largest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMax() const; + + /// getSignedMin - Return the smallest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMin() const; + + /// operator== - Return true if this range is equal to another range. + /// + bool operator==(const ConstantRange &CR) const { + return Lower == CR.Lower && Upper == CR.Upper; + } + bool operator!=(const ConstantRange &CR) const { + return !operator==(CR); + } + + /// subtract - Subtract the specified constant from the endpoints of this + /// constant range. + ConstantRange subtract(const APInt &CI) const; + + /// intersectWith - Return the range that results from the intersection of + /// this range with another range. The resultant range is guaranteed to + /// include all elements contained in both input ranges, and to have the + /// smallest possible set size that does so. Because there may be two + /// intersections with the same set size, A.intersectWith(B) might not + /// be equal to B.intersectWith(A). + /// + ConstantRange intersectWith(const ConstantRange &CR) const; + + /// unionWith - Return the range that results from the union of this range + /// with another range. The resultant range is guaranteed to include the + /// elements of both sets, but may contain more. For example, [3, 9) union + /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included + /// in either set before. + /// + ConstantRange unionWith(const ConstantRange &CR) const; + + /// zeroExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// zero extended to BitWidth. + ConstantRange zeroExtend(uint32_t BitWidth) const; + + /// signExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// sign extended to BitWidth. + ConstantRange signExtend(uint32_t BitWidth) const; + + /// truncate - Return a new range in the specified integer type, which must be + /// strictly smaller than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// truncated to the specified type. + ConstantRange truncate(uint32_t BitWidth) const; + + /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// value is zero extended, truncated, or left alone to make it that width. + ConstantRange zextOrTrunc(uint32_t BitWidth) const; + + /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// value is sign extended, truncated, or left alone to make it that width. + ConstantRange sextOrTrunc(uint32_t BitWidth) const; + + /// add - Return a new range representing the possible values resulting + /// from an addition of a value in this range and a value in \p Other. + ConstantRange add(const ConstantRange &Other) const; + + /// sub - Return a new range representing the possible values resulting + /// from a subtraction of a value in this range and a value in \p Other. + ConstantRange sub(const ConstantRange &Other) const; + + /// multiply - Return a new range representing the possible values resulting + /// from a multiplication of a value in this range and a value in \p Other. + /// TODO: This isn't fully implemented yet. + ConstantRange multiply(const ConstantRange &Other) const; + + /// smax - Return a new range representing the possible values resulting + /// from a signed maximum of a value in this range and a value in \p Other. + ConstantRange smax(const ConstantRange &Other) const; + + /// umax - Return a new range representing the possible values resulting + /// from an unsigned maximum of a value in this range and a value in \p Other. + ConstantRange umax(const ConstantRange &Other) const; + + /// udiv - Return a new range representing the possible values resulting + /// from an unsigned division of a value in this range and a value in + /// \p Other. + ConstantRange udiv(const ConstantRange &Other) const; + + /// binaryAnd - return a new range representing the possible values resulting + /// from a binary-and of a value in this range by a value in \p Other. + ConstantRange binaryAnd(const ConstantRange &Other) const; + + /// binaryOr - return a new range representing the possible values resulting + /// from a binary-or of a value in this range by a value in \p Other. + ConstantRange binaryOr(const ConstantRange &Other) const; + + /// shl - Return a new range representing the possible values resulting + /// from a left shift of a value in this range by a value in \p Other. + /// TODO: This isn't fully implemented yet. + ConstantRange shl(const ConstantRange &Other) const; + + /// lshr - Return a new range representing the possible values resulting + /// from a logical right shift of a value in this range and a value in + /// \p Other. + ConstantRange lshr(const ConstantRange &Other) const; + + /// inverse - Return a new range that is the logical not of the current set. + /// + ConstantRange inverse() const; + + /// print - Print out the bounds to a stream... + /// + void print(raw_ostream &OS) const; + + /// dump - Allow printing from a debugger easily... + /// + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) { + CR.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/CrashRecoveryContext.h b/final/include/llvm/Support/CrashRecoveryContext.h new file mode 100644 index 00000000000..2e9b5d4aa54 --- /dev/null +++ b/final/include/llvm/Support/CrashRecoveryContext.h @@ -0,0 +1,92 @@ +//===--- CrashRecoveryContext.h - Crash Recovery ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H +#define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H + +#include + +namespace llvm { +class StringRef; + +/// \brief Crash recovery helper object. +/// +/// This class implements support for running operations in a safe context so +/// that crashes (memory errors, stack overflow, assertion violations) can be +/// detected and control restored to the crashing thread. Crash detection is +/// purely "best effort", the exact set of failures which can be recovered from +/// is platform dependent. +/// +/// Clients make use of this code by first calling +/// CrashRecoveryContext::Enable(), and then executing unsafe operations via a +/// CrashRecoveryContext object. For example: +/// +/// void actual_work(void *); +/// +/// void foo() { +/// CrashRecoveryContext CRC; +/// +/// if (!CRC.RunSafely(actual_work, 0)) { +/// ... a crash was detected, report error to user ... +/// } +/// +/// ... no crash was detected ... +/// } +/// +/// Crash recovery contexts may not be nested. +class CrashRecoveryContext { + void *Impl; + +public: + CrashRecoveryContext() : Impl(0) {} + ~CrashRecoveryContext(); + + /// \brief Enable crash recovery. + static void Enable(); + + /// \brief Disable crash recovery. + static void Disable(); + + /// \brief Return the active context, if the code is currently executing in a + /// thread which is in a protected context. + static CrashRecoveryContext *GetCurrent(); + + /// \brief Execute the provide callback function (with the given arguments) in + /// a protected context. + /// + /// \return True if the function completed successfully, and false if the + /// function crashed (or HandleCrash was called explicitly). Clients should + /// make as little assumptions as possible about the program state when + /// RunSafely has returned false. Clients can use getBacktrace() to retrieve + /// the backtrace of the crash on failures. + bool RunSafely(void (*Fn)(void*), void *UserData); + + /// \brief Execute the provide callback function (with the given arguments) in + /// a protected context which is run in another thread (optionally with a + /// requested stack size). + /// + /// See RunSafely() and llvm_execute_on_thread(). + bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize = 0); + + /// \brief Explicitly trigger a crash recovery in the current process, and + /// return failure from RunSafely(). This function does not return. + void HandleCrash(); + + /// \brief Return a string containing the backtrace where the crash was + /// detected; or empty if the backtrace wasn't recovered. + /// + /// This function is only valid when a crash has been detected (i.e., + /// RunSafely() has returned false. + const std::string &getBacktrace() const; +}; + +} + +#endif diff --git a/final/include/llvm/Support/DOTGraphTraits.h b/final/include/llvm/Support/DOTGraphTraits.h new file mode 100644 index 00000000000..3cb8164c3c3 --- /dev/null +++ b/final/include/llvm/Support/DOTGraphTraits.h @@ -0,0 +1,161 @@ +//===-- llvm/Support/DotGraphTraits.h - Customize .dot output ---*- 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 template class that can be used to customize dot output +// graphs generated by the GraphWriter.h file. The default implementation of +// this file will produce a simple, but not very polished graph. By +// specializing this template, lots of customization opportunities are possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DOTGRAPHTRAITS_H +#define LLVM_SUPPORT_DOTGRAPHTRAITS_H + +#include + +namespace llvm { + +/// DefaultDOTGraphTraits - This class provides the default implementations of +/// all of the DOTGraphTraits methods. If a specialization does not need to +/// override all methods here it should inherit so that it can get the default +/// implementations. +/// +struct DefaultDOTGraphTraits { +private: + bool IsSimple; + +protected: + bool isSimple() { + return IsSimple; + } + +public: + explicit DefaultDOTGraphTraits(bool simple=false) : IsSimple (simple) {} + + /// getGraphName - Return the label for the graph as a whole. Printed at the + /// top of the graph. + /// + template + static std::string getGraphName(const GraphType& Graph) { return ""; } + + /// getGraphProperties - Return any custom properties that should be included + /// in the top level graph structure for dot. + /// + template + static std::string getGraphProperties(const GraphType& Graph) { + return ""; + } + + /// renderGraphFromBottomUp - If this function returns true, the graph is + /// emitted bottom-up instead of top-down. This requires graphviz 2.0 to work + /// though. + static bool renderGraphFromBottomUp() { + return false; + } + + /// isNodeHidden - If the function returns true, the given node is not + /// displayed in the graph. + static bool isNodeHidden(const void *Node) { + return false; + } + + /// getNodeLabel - Given a node and a pointer to the top level graph, return + /// the label to print in the node. + template + std::string getNodeLabel(const void *Node, const GraphType& Graph) { + return ""; + } + + /// hasNodeAddressLabel - If this method returns true, the address of the node + /// is added to the label of the node. + template + static bool hasNodeAddressLabel(const void *Node, const GraphType& Graph) { + return false; + } + + /// If you want to specify custom node attributes, this is the place to do so + /// + template + static std::string getNodeAttributes(const void *Node, + const GraphType& Graph) { + return ""; + } + + /// If you want to override the dot attributes printed for a particular edge, + /// override this method. + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI, + const GraphType& Graph) { + return ""; + } + + /// getEdgeSourceLabel - If you want to label the edge source itself, + /// implement this method. + template + static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { + return ""; + } + + /// edgeTargetsEdgeSource - This method returns true if this outgoing edge + /// should actually target another edge source, not a node. If this method is + /// implemented, getEdgeTarget should be implemented. + template + static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { + return false; + } + + /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is + /// called to determine which outgoing edge of Node is the target of this + /// edge. + template + static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { + return I; + } + + /// hasEdgeDestLabels - If this function returns true, the graph is able + /// to provide labels for edge destinations. + static bool hasEdgeDestLabels() { + return false; + } + + /// numEdgeDestLabels - If hasEdgeDestLabels, this function returns the + /// number of incoming edge labels the given node has. + static unsigned numEdgeDestLabels(const void *Node) { + return 0; + } + + /// getEdgeDestLabel - If hasEdgeDestLabels, this function returns the + /// incoming edge label with the given index in the given node. + static std::string getEdgeDestLabel(const void *Node, unsigned i) { + return ""; + } + + /// addCustomGraphFeatures - If a graph is made up of more than just + /// straight-forward nodes and edges, this is the place to put all of the + /// custom stuff necessary. The GraphWriter object, instantiated with your + /// GraphType is passed in as an argument. You may call arbitrary methods on + /// it to add things to the output graph. + /// + template + static void addCustomGraphFeatures(const GraphType& Graph, GraphWriter &GW) {} +}; + + +/// DOTGraphTraits - Template class that can be specialized to customize how +/// graphs are converted to 'dot' graphs. When specializing, you may inherit +/// from DefaultDOTGraphTraits if you don't need to override everything. +/// +template +struct DOTGraphTraits : public DefaultDOTGraphTraits { + DOTGraphTraits (bool simple=false) : DefaultDOTGraphTraits (simple) {} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/DataFlow.h b/final/include/llvm/Support/DataFlow.h new file mode 100644 index 00000000000..355c402f542 --- /dev/null +++ b/final/include/llvm/Support/DataFlow.h @@ -0,0 +1,103 @@ +//===-- llvm/Support/DataFlow.h - dataflow as graphs ------------*- 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 specializations of GraphTraits that allows Use-Def and +// Def-Use relations to be treated as proper graphs for generic algorithms. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DATAFLOW_H +#define LLVM_SUPPORT_DATAFLOW_H + +#include "llvm/User.h" +#include "llvm/ADT/GraphTraits.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat def-use/use-def +// chains as graphs + +template <> struct GraphTraits { + typedef const Value NodeType; + typedef Value::const_use_iterator ChildIteratorType; + + static NodeType *getEntryNode(const Value *G) { + return G; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->use_begin(); + } + + static inline ChildIteratorType child_end(NodeType *N) { + return N->use_end(); + } +}; + +template <> struct GraphTraits { + typedef Value NodeType; + typedef Value::use_iterator ChildIteratorType; + + static NodeType *getEntryNode(Value *G) { + return G; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->use_begin(); + } + + static inline ChildIteratorType child_end(NodeType *N) { + return N->use_end(); + } +}; + +template <> struct GraphTraits > { + typedef const Value NodeType; + typedef User::const_op_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + if (const User *U = dyn_cast(N)) + return U->op_begin(); + return NULL; + } + + static inline ChildIteratorType child_end(NodeType *N) { + if(const User *U = dyn_cast(N)) + return U->op_end(); + return NULL; + } +}; + +template <> struct GraphTraits > { + typedef Value NodeType; + typedef User::op_iterator ChildIteratorType; + + static NodeType *getEntryNode(Inverse G) { + return G.Graph; + } + + static inline ChildIteratorType child_begin(NodeType *N) { + if (User *U = dyn_cast(N)) + return U->op_begin(); + return NULL; + } + + static inline ChildIteratorType child_end(NodeType *N) { + if (User *U = dyn_cast(N)) + return U->op_end(); + return NULL; + } +}; + +} +#endif diff --git a/final/include/llvm/Support/DataTypes.h.cmake b/final/include/llvm/Support/DataTypes.h.cmake new file mode 100644 index 00000000000..72c451873c0 --- /dev/null +++ b/final/include/llvm/Support/DataTypes.h.cmake @@ -0,0 +1,189 @@ +/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functinons. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} +#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} +#cmakedefine HAVE_U_INT64_T ${HAVE_U_INT64_T} + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifndef _MSC_VER + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including Support/DataTypes.h" +#endif + +/* Note that includes , if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include +#include +#include +#ifdef __cplusplus +#include +#else +#include +#endif +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#ifndef INT8_MAX +# define INT8_MAX 127 +#endif +#ifndef INT8_MIN +# define INT8_MIN -128 +#endif +#ifndef UINT8_MAX +# define UINT8_MAX 255 +#endif +#ifndef INT16_MAX +# define INT16_MAX 32767 +#endif +#ifndef INT16_MIN +# define INT16_MIN -32768 +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif +#ifndef INT32_MAX +# define INT32_MAX 2147483647 +#endif +#ifndef INT32_MIN +# define INT32_MIN -2147483648 +#endif +#ifndef UINT32_MAX +# define UINT32_MAX 4294967295U +#endif +/* Certain compatibility updates to VC++ introduce the `cstdint' + * header, which defines the INT*_C macros. On default installs they + * are absent. */ +#ifndef INT8_C +# define INT8_C(C) C##i8 +#endif +#ifndef UINT8_C +# define UINT8_C(C) C##ui8 +#endif +#ifndef INT16_C +# define INT16_C(C) C##i16 +#endif +#ifndef UINT16_C +# define UINT16_C(C) C##ui16 +#endif +#ifndef INT32_C +# define INT32_C(C) C##i32 +#endif +#ifndef UINT32_C +# define UINT32_C(C) C##ui32 +#endif +#ifndef INT64_C +# define INT64_C(C) C##i64 +#endif +#ifndef UINT64_C +# define UINT64_C(C) C##ui64 +#endif +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/final/include/llvm/Support/DataTypes.h.in b/final/include/llvm/Support/DataTypes.h.in new file mode 100644 index 00000000000..5965e8c0b2a --- /dev/null +++ b/final/include/llvm/Support/DataTypes.h.in @@ -0,0 +1,111 @@ +/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#undef HAVE_SYS_TYPES_H +#undef HAVE_INTTYPES_H +#undef HAVE_STDINT_H +#undef HAVE_UINT64_T +#undef HAVE_U_INT64_T + +#ifdef __cplusplus +#include +#else +#include +#endif + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including System/DataTypes.h" +#endif + +/* Note that includes , if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/final/include/llvm/Support/Debug.h b/final/include/llvm/Support/Debug.h new file mode 100644 index 00000000000..8651fc1abea --- /dev/null +++ b/final/include/llvm/Support/Debug.h @@ -0,0 +1,101 @@ +//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handy way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling without assertions, the -debug-* options and all code in +// DEBUG() statements disappears, so it does not effect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DEBUG_H +#define LLVM_SUPPORT_DEBUG_H + +namespace llvm { + +class raw_ostream; + +/// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes +/// all of their DEBUG statements to be activatable with -debug-only=thatstring. +#ifndef DEBUG_TYPE +#define DEBUG_TYPE "" +#endif + +#ifndef NDEBUG +/// DebugFlag - This boolean is set to true if the '-debug' command line option +/// is specified. This should probably not be referenced directly, instead, use +/// the DEBUG macro below. +/// +extern bool DebugFlag; + +/// isCurrentDebugType - Return true if the specified string is the debug type +/// specified on the command line, or if none was specified on the command line +/// with the -debug-only=X option. +/// +bool isCurrentDebugType(const char *Type); + +/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void SetCurrentDebugType(const char *Type); + +/// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug +/// information. In the '-debug' option is specified on the commandline, and if +/// this is a debug build, then the code specified as the option to the macro +/// will be executed. Otherwise it will not be. Example: +/// +/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n"); +/// +/// This will emit the debug information if -debug is present, and -debug-only +/// is not specified, or is specified as "bitset". +#define DEBUG_WITH_TYPE(TYPE, X) \ + do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \ + } while (0) + +#else +#define isCurrentDebugType(X) (false) +#define SetCurrentDebugType(X) +#define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) +#endif + +/// EnableDebugBuffering - This defaults to false. If true, the debug +/// stream will install signal handlers to dump any buffered debug +/// output. It allows clients to selectively allow the debug stream +/// to install signal handlers if they are certain there will be no +/// conflict. +/// +extern bool EnableDebugBuffering; + +/// dbgs() - This returns a reference to a raw_ostream for debugging +/// messages. If debugging is disabled it returns errs(). Use it +/// like: dbgs() << "foo" << "bar"; +raw_ostream &dbgs(); + +// DEBUG macro - This macro should be used by passes to emit debug information. +// In the '-debug' option is specified on the commandline, and if this is a +// debug build, then the code specified as the option to the macro will be +// executed. Otherwise it will not be. Example: +// +// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); +// +#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/DebugLoc.h b/final/include/llvm/Support/DebugLoc.h new file mode 100644 index 00000000000..ccc34461291 --- /dev/null +++ b/final/include/llvm/Support/DebugLoc.h @@ -0,0 +1,80 @@ +//===---- llvm/Support/DebugLoc.h - Debug Location Information --*- 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 number of light weight data structures used +// to describe and track debug location information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DEBUGLOC_H +#define LLVM_SUPPORT_DEBUGLOC_H + +namespace llvm { + class MDNode; + class LLVMContext; + + /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, + /// and MachineInstr to compactly encode file/line/scope information for an + /// operation. + class DebugLoc { + /// LineCol - This 32-bit value encodes the line and column number for the + /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 + /// for either means unknown. + unsigned LineCol; + + /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, + /// decoded by LLVMContext. 0 is unknown. + int ScopeIdx; + public: + DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + + /// get - Get a new DebugLoc that corresponds to the specified line/col + /// scope/inline location. + static DebugLoc get(unsigned Line, unsigned Col, + MDNode *Scope, MDNode *InlinedAt = 0); + + /// getFromDILocation - Translate the DILocation quad into a DebugLoc. + static DebugLoc getFromDILocation(MDNode *N); + + /// isUnknown - Return true if this is an unknown location. + bool isUnknown() const { return ScopeIdx == 0; } + + unsigned getLine() const { + return (LineCol << 8) >> 8; // Mask out column. + } + + unsigned getCol() const { + return LineCol >> 24; + } + + /// getScope - This returns the scope pointer for this DebugLoc, or null if + /// invalid. + MDNode *getScope(const LLVMContext &Ctx) const; + + /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or + /// null if invalid or not present. + MDNode *getInlinedAt(const LLVMContext &Ctx) const; + + /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, + const LLVMContext &Ctx) const; + + + /// getAsMDNode - This method converts the compressed DebugLoc node into a + /// DILocation compatible MDNode. + MDNode *getAsMDNode(const LLVMContext &Ctx) const; + + bool operator==(const DebugLoc &DL) const { + return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; + } + bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + }; +} // end namespace llvm + +#endif /* LLVM_DEBUGLOC_H */ diff --git a/final/include/llvm/Support/Disassembler.h b/final/include/llvm/Support/Disassembler.h new file mode 100644 index 00000000000..6d1cc0fdcb5 --- /dev/null +++ b/final/include/llvm/Support/Disassembler.h @@ -0,0 +1,35 @@ +//===- llvm/Support/Disassembler.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DISASSEMBLER_H +#define LLVM_SYSTEM_DISASSEMBLER_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +namespace sys { + +/// This function returns true, if there is possible to use some external +/// disassembler library. False otherwise. +bool hasDisassembler(); + +/// This function provides some "glue" code to call external disassembler +/// libraries. +std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); + +} +} + +#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/final/include/llvm/Support/Dwarf.h b/final/include/llvm/Support/Dwarf.h new file mode 100644 index 00000000000..5d0b5a943d5 --- /dev/null +++ b/final/include/llvm/Support/Dwarf.h @@ -0,0 +1,677 @@ +//===-- llvm/Support/Dwarf.h ---Dwarf Constants------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains constants used for implementing Dwarf debug support. For +// Details on the Dwarf 3 specfication see DWARF Debugging Information Format +// V.3 reference manual http://dwarf.freestandards.org , +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DWARF_H +#define LLVM_SUPPORT_DWARF_H + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Debug info constants. + +enum { + LLVMDebugVersion = (9 << 16), // Current version of debug information. + LLVMDebugVersion8 = (8 << 16), // Cconstant for version 8. + LLVMDebugVersion7 = (7 << 16), // Constant for version 7. + LLVMDebugVersion6 = (6 << 16), // Constant for version 6. + LLVMDebugVersion5 = (5 << 16), // Constant for version 5. + LLVMDebugVersion4 = (4 << 16), // Constant for version 4. + LLVMDebugVersionMask = 0xffff0000 // Mask for version number. +}; + +namespace dwarf { + +//===----------------------------------------------------------------------===// +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 +// reference manual http://dwarf.freestandards.org . +// + +// Do not mix the following two enumerations sets. DW_TAG_invalid changes the +// enumeration base type. + +enum llvm_dwarf_constants { + // llvm mock tags + DW_TAG_invalid = ~0U, // Tag for invalid results. + + DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. + DW_TAG_arg_variable = 0x101, // Tag for argument variables. + DW_TAG_return_variable = 0x102, // Tag for return variables. + DW_TAG_vector_type = 0x103, // Tag for vector types. + + DW_TAG_user_base = 0x1000, // Recommended base for user tags. + + DW_CIE_VERSION = 1, // Common frame information version. + DW_CIE_ID = 0xffffffff // Common frame information mark. +}; + +enum dwarf_constants { + DWARF_VERSION = 2, + + // Tags + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_rvalue_reference_type = 0x41, + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff, + + // Children flag + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01, + + // Attributes + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + + // Apple extensions. + DW_AT_APPLE_optimized = 0x3fe1, + DW_AT_APPLE_flags = 0x3fe2, + DW_AT_APPLE_isa = 0x3fe3, + DW_AT_APPLE_block = 0x3fe4, + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6, + DW_AT_APPLE_omit_frame_ptr = 0x3fe7, + + // Attribute form encodings + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + + // Operation encodings + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2f, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3a, + DW_OP_lit11 = 0x3b, + DW_OP_lit12 = 0x3c, + DW_OP_lit13 = 0x3d, + DW_OP_lit14 = 0x3e, + DW_OP_lit15 = 0x3f, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4a, + DW_OP_lit27 = 0x4b, + DW_OP_lit28 = 0x4c, + DW_OP_lit29 = 0x4d, + DW_OP_lit30 = 0x4e, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5a, + DW_OP_reg11 = 0x5b, + DW_OP_reg12 = 0x5c, + DW_OP_reg13 = 0x5d, + DW_OP_reg14 = 0x5e, + DW_OP_reg15 = 0x5f, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6a, + DW_OP_reg27 = 0x6b, + DW_OP_reg28 = 0x6c, + DW_OP_reg29 = 0x6d, + DW_OP_reg30 = 0x6e, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7a, + DW_OP_breg11 = 0x7b, + DW_OP_breg12 = 0x7c, + DW_OP_breg13 = 0x7d, + DW_OP_breg14 = 0x7e, + DW_OP_breg15 = 0x7f, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8a, + DW_OP_breg27 = 0x8b, + DW_OP_breg28 = 0x8c, + DW_OP_breg29 = 0x8d, + DW_OP_breg30 = 0x8e, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b, + DW_OP_call_frame_cfa = 0x9c, + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff, + + // Encoding attribute values + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f, + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff, + + // Decimal sign attribute values + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05, + + // Endianity attribute values + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff, + + // Accessibility codes + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03, + + // Visibility codes + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03, + + // Virtuality codes + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02, + + // Language names + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff, + + // Identifier case codes + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03, + + // Calling convention codes + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff, + + // Inline codes + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03, + + // Array ordering + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01, + + // Discriminant descriptor values + DW_DSC_label = 0x00, + DW_DSC_range = 0x01, + + // Line Number Standard Opcode Encodings + DW_LNS_extended_op = 0x00, + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c, + + // Line Number Extended Opcode Encodings + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff, + + // Macinfo Type Encodings + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff, + + // Call frame instruction encodings + DW_CFA_extended = 0x00, + DW_CFA_nop = 0x00, + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_signed = 0x08, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80 +}; + +/// TagString - Return the string for the specified tag. +/// +const char *TagString(unsigned Tag); + +/// ChildrenString - Return the string for the specified children flag. +/// +const char *ChildrenString(unsigned Children); + +/// AttributeString - Return the string for the specified attribute. +/// +const char *AttributeString(unsigned Attribute); + +/// FormEncodingString - Return the string for the specified form encoding. +/// +const char *FormEncodingString(unsigned Encoding); + +/// OperationEncodingString - Return the string for the specified operation +/// encoding. +const char *OperationEncodingString(unsigned Encoding); + +/// AttributeEncodingString - Return the string for the specified attribute +/// encoding. +const char *AttributeEncodingString(unsigned Encoding); + +/// DecimalSignString - Return the string for the specified decimal sign +/// attribute. +const char *DecimalSignString(unsigned Sign); + +/// EndianityString - Return the string for the specified endianity. +/// +const char *EndianityString(unsigned Endian); + +/// AccessibilityString - Return the string for the specified accessibility. +/// +const char *AccessibilityString(unsigned Access); + +/// VisibilityString - Return the string for the specified visibility. +/// +const char *VisibilityString(unsigned Visibility); + +/// VirtualityString - Return the string for the specified virtuality. +/// +const char *VirtualityString(unsigned Virtuality); + +/// LanguageString - Return the string for the specified language. +/// +const char *LanguageString(unsigned Language); + +/// CaseString - Return the string for the specified identifier case. +/// +const char *CaseString(unsigned Case); + +/// ConventionString - Return the string for the specified calling convention. +/// +const char *ConventionString(unsigned Convention); + +/// InlineCodeString - Return the string for the specified inline code. +/// +const char *InlineCodeString(unsigned Code); + +/// ArrayOrderString - Return the string for the specified array order. +/// +const char *ArrayOrderString(unsigned Order); + +/// DiscriminantString - Return the string for the specified discriminant +/// descriptor. +const char *DiscriminantString(unsigned Discriminant); + +/// LNStandardString - Return the string for the specified line number standard. +/// +const char *LNStandardString(unsigned Standard); + +/// LNExtendedString - Return the string for the specified line number extended +/// opcode encodings. +const char *LNExtendedString(unsigned Encoding); + +/// MacinfoString - Return the string for the specified macinfo type encodings. +/// +const char *MacinfoString(unsigned Encoding); + +/// CallFrameString - Return the string for the specified call frame instruction +/// encodings. +const char *CallFrameString(unsigned Encoding); +} // End of namespace dwarf + +} // End of namespace llvm + +#endif diff --git a/final/include/llvm/Support/DynamicLibrary.h b/final/include/llvm/Support/DynamicLibrary.h new file mode 100644 index 00000000000..e6d9ff57ae8 --- /dev/null +++ b/final/include/llvm/Support/DynamicLibrary.h @@ -0,0 +1,86 @@ +//===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- 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 sys::DynamicLibrary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H + +#include + +namespace llvm { +namespace sys { + + /// This class provides a portable interface to dynamic libraries which also + /// might be known as shared libraries, shared objects, dynamic shared + /// objects, or dynamic link libraries. Regardless of the terminology or the + /// operating system interface, this class provides a portable interface that + /// allows dynamic libraries to be loaded and searched for externally + /// defined symbols. This is typically used to provide "plug-in" support. + /// It also allows for symbols to be defined which don't live in any library, + /// but rather the main program itself, useful on Windows where the main + /// executable cannot be searched. + class DynamicLibrary { + DynamicLibrary(); // DO NOT IMPLEMENT + public: + /// This function allows a library to be loaded without instantiating a + /// DynamicLibrary object. Consequently, it is marked as being permanent + /// and will only be unloaded when the program terminates. This returns + /// false on success or returns true and fills in *ErrMsg on failure. + /// @brief Open a dynamic library permanently. + /// + /// NOTE: This function is not thread safe. + /// + static bool LoadLibraryPermanently(const char *filename, + std::string *ErrMsg = 0); + + /// This function will search through all previously loaded dynamic + /// libraries for the symbol \p symbolName. If it is found, the addressof + /// that symbol is returned. If not, null is returned. Note that this will + /// search permanently loaded libraries (LoadLibraryPermanently) as well + /// as ephemerally loaded libraries (constructors). + /// @throws std::string on error. + /// @brief Search through libraries for address of a symbol + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const char *symbolName); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const std::string &symbolName) { + return SearchForAddressOfSymbol(symbolName.c_str()); + } + + /// This functions permanently adds the symbol \p symbolName with the + /// value \p symbolValue. These symbols are searched before any + /// libraries. + /// @brief Add searchable symbol/value pair. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const char *symbolName, void *symbolValue); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const std::string &symbolName, void *symbolValue) { + AddSymbol(symbolName.c_str(), symbolValue); + } + }; + +} // End sys namespace +} // End llvm namespace + +#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H diff --git a/final/include/llvm/Support/ELF.h b/final/include/llvm/Support/ELF.h new file mode 100644 index 00000000000..cc72bd59cb7 --- /dev/null +++ b/final/include/llvm/Support/ELF.h @@ -0,0 +1,824 @@ +//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on the Tool +// Interface Standard (TIS) Executable and Linking Format (ELF) Specification +// Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format +// Version 1.5, Draft 2, May 1998 as well as OpenBSD header files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ELF_H +#define LLVM_SUPPORT_ELF_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +namespace ELF { + +typedef uint32_t Elf32_Addr; // Program address +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; // File offset +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Shalf; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; +typedef uint32_t Elf64_Half; +typedef uint16_t Elf64_Quarter; + +// Object file magic string. +static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; + +// e_ident size and indices. +enum { + EI_MAG0 = 0, // File identification index. + EI_MAG1 = 1, // File identification index. + EI_MAG2 = 2, // File identification index. + EI_MAG3 = 3, // File identification index. + EI_CLASS = 4, // File class. + EI_DATA = 5, // Data encoding. + EI_VERSION = 6, // File version. + EI_OSABI = 7, // OS/ABI identification. + EI_ABIVERSION = 8, // ABI version. + EI_PAD = 9, // Start of padding bytes. + EI_NIDENT = 16 // Number of bytes in e_ident. +}; + +struct Elf32_Ehdr { + unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes + Elf32_Half e_type; // Type of file (see ET_* below) + Elf32_Half e_machine; // Required architecture for this file (see EM_*) + Elf32_Word e_version; // Must be equal to 1 + Elf32_Addr e_entry; // Address to jump to in order to start program + Elf32_Off e_phoff; // Program header table's file offset, in bytes + Elf32_Off e_shoff; // Section header table's file offset, in bytes + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // Size of ELF header, in bytes + Elf32_Half e_phentsize; // Size of an entry in the program header table + Elf32_Half e_phnum; // Number of entries in the program header table + Elf32_Half e_shentsize; // Size of an entry in the section header table + Elf32_Half e_shnum; // Number of entries in the section header table + Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } +}; + +// 64-bit ELF header. Fields are the same as for ELF32, but with different +// types (see above). +struct Elf64_Ehdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Quarter e_type; + Elf64_Quarter e_machine; + Elf64_Half e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Half e_flags; + Elf64_Quarter e_ehsize; + Elf64_Quarter e_phentsize; + Elf64_Quarter e_phnum; + Elf64_Quarter e_shentsize; + Elf64_Quarter e_shnum; + Elf64_Quarter e_shstrndx; + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } +}; + +// File types +enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific +}; + +// Versioning +enum { + EV_NONE = 0, + EV_CURRENT = 1 +}; + +// Machine architectures +enum { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62, // AMD64 + EM_MBLAZE = 47787 // Xilinx MicroBlaze +}; + +// Object file classes. +enum { + ELFCLASSNONE = 0, + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file +}; + +// Object file byte orderings. +enum { + ELFDATANONE = 0, // Invalid data encoding. + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file +}; + +// OS ABI identification. +enum { + ELFOSABI_NONE = 0, // UNIX System V ABI + ELFOSABI_HPUX = 1, // HP-UX operating system + ELFOSABI_NETBSD = 2, // NetBSD + ELFOSABI_LINUX = 3, // GNU/Linux + ELFOSABI_HURD = 4, // GNU/Hurd + ELFOSABI_SOLARIS = 6, // Solaris + ELFOSABI_AIX = 7, // AIX + ELFOSABI_IRIX = 8, // IRIX + ELFOSABI_FREEBSD = 9, // FreeBSD + ELFOSABI_TRU64 = 10, // TRU64 UNIX + ELFOSABI_MODESTO = 11, // Novell Modesto + ELFOSABI_OPENBSD = 12, // OpenBSD + ELFOSABI_OPENVMS = 13, // OpenVMS + ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel + ELFOSABI_AROS = 15, // AROS + ELFOSABI_FENIXOS = 16, // FenixOS + ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 + ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 + ELFOSABI_ARM = 97, // ARM + ELFOSABI_STANDALONE = 255 // Standalone (embedded) application +}; + +// X86_64 relocations. +enum { + R_X86_64_NONE = 0, + R_X86_64_64 = 1, + R_X86_64_PC32 = 2, + R_X86_64_GOT32 = 3, + R_X86_64_PLT32 = 4, + R_X86_64_COPY = 5, + R_X86_64_GLOB_DAT = 6, + R_X86_64_JUMP_SLOT = 7, + R_X86_64_RELATIVE = 8, + R_X86_64_GOTPCREL = 9, + R_X86_64_32 = 10, + R_X86_64_32S = 11, + R_X86_64_16 = 12, + R_X86_64_PC16 = 13, + R_X86_64_8 = 14, + R_X86_64_PC8 = 15, + R_X86_64_DTPMOD64 = 16, + R_X86_64_DTPOFF64 = 17, + R_X86_64_TPOFF64 = 18, + R_X86_64_TLSGD = 19, + R_X86_64_TLSLD = 20, + R_X86_64_DTPOFF32 = 21, + R_X86_64_GOTTPOFF = 22, + R_X86_64_TPOFF32 = 23, + R_X86_64_PC64 = 24, + R_X86_64_GOTOFF64 = 25, + R_X86_64_GOTPC32 = 26, + R_X86_64_SIZE32 = 32, + R_X86_64_SIZE64 = 33, + R_X86_64_GOTPC32_TLSDESC = 34, + R_X86_64_TLSDESC_CALL = 35, + R_X86_64_TLSDESC = 36 +}; + +// i386 relocations. +// TODO: this is just a subset +enum { + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2, + R_386_GOT32 = 3, + R_386_PLT32 = 4, + R_386_COPY = 5, + R_386_GLOB_DAT = 6, + R_386_JUMP_SLOT = 7, + R_386_RELATIVE = 8, + R_386_GOTOFF = 9, + R_386_GOTPC = 10, + R_386_32PLT = 11, + R_386_TLS_TPOFF = 14, + R_386_TLS_IE = 15, + R_386_TLS_GOTIE = 16, + R_386_TLS_LE = 17, + R_386_TLS_GD = 18, + R_386_TLS_LDM = 19, + R_386_16 = 20, + R_386_PC16 = 21, + R_386_8 = 22, + R_386_PC8 = 23, + R_386_TLS_GD_32 = 24, + R_386_TLS_GD_PUSH = 25, + R_386_TLS_GD_CALL = 26, + R_386_TLS_GD_POP = 27, + R_386_TLS_LDM_32 = 28, + R_386_TLS_LDM_PUSH = 29, + R_386_TLS_LDM_CALL = 30, + R_386_TLS_LDM_POP = 31, + R_386_TLS_LDO_32 = 32, + R_386_TLS_IE_32 = 33, + R_386_TLS_LE_32 = 34, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_TPOFF32 = 37, + R_386_TLS_GOTDESC = 39, + R_386_TLS_DESC_CALL = 40, + R_386_TLS_DESC = 41, + R_386_IRELATIVE = 42, + R_386_NUM = 43 +}; + +// MBlaze relocations. +enum { + R_MICROBLAZE_NONE = 0, + R_MICROBLAZE_32 = 1, + R_MICROBLAZE_32_PCREL = 2, + R_MICROBLAZE_64_PCREL = 3, + R_MICROBLAZE_32_PCREL_LO = 4, + R_MICROBLAZE_64 = 5, + R_MICROBLAZE_32_LO = 6, + R_MICROBLAZE_SRO32 = 7, + R_MICROBLAZE_SRW32 = 8, + R_MICROBLAZE_64_NONE = 9, + R_MICROBLAZE_32_SYM_OP_SYM = 10, + R_MICROBLAZE_GNU_VTINHERIT = 11, + R_MICROBLAZE_GNU_VTENTRY = 12, + R_MICROBLAZE_GOTPC_64 = 13, + R_MICROBLAZE_GOT_64 = 14, + R_MICROBLAZE_PLT_64 = 15, + R_MICROBLAZE_REL = 16, + R_MICROBLAZE_JUMP_SLOT = 17, + R_MICROBLAZE_GLOB_DAT = 18, + R_MICROBLAZE_GOTOFF_64 = 19, + R_MICROBLAZE_GOTOFF_32 = 20, + R_MICROBLAZE_COPY = 21 +}; + + +// ARM Specific e_flags +enum { EF_ARM_EABIMASK = 0xFF000000U }; + +// ELF Relocation types for ARM +// Meets 2.08 ABI Specs. + +enum { + R_ARM_NONE = 0x00, + R_ARM_PC24 = 0x01, + R_ARM_ABS32 = 0x02, + R_ARM_REL32 = 0x03, + R_ARM_LDR_PC_G0 = 0x04, + R_ARM_ABS16 = 0x05, + R_ARM_ABS12 = 0x06, + R_ARM_THM_ABS5 = 0x07, + R_ARM_ABS8 = 0x08, + R_ARM_SBREL32 = 0x09, + R_ARM_THM_CALL = 0x0a, + R_ARM_THM_PC8 = 0x0b, + R_ARM_BREL_ADJ = 0x0c, + R_ARM_TLS_DESC = 0x0d, + R_ARM_THM_SWI8 = 0x0e, + R_ARM_XPC25 = 0x0f, + R_ARM_THM_XPC22 = 0x10, + R_ARM_TLS_DTPMOD32 = 0x11, + R_ARM_TLS_DTPOFF32 = 0x12, + R_ARM_TLS_TPOFF32 = 0x13, + R_ARM_COPY = 0x14, + R_ARM_GLOB_DAT = 0x15, + R_ARM_JUMP_SLOT = 0x16, + R_ARM_RELATIVE = 0x17, + R_ARM_GOTOFF32 = 0x18, + R_ARM_BASE_PREL = 0x19, + R_ARM_GOT_BREL = 0x1a, + R_ARM_PLT32 = 0x1b, + R_ARM_CALL = 0x1c, + R_ARM_JUMP24 = 0x1d, + R_ARM_THM_JUMP24 = 0x1e, + R_ARM_BASE_ABS = 0x1f, + R_ARM_ALU_PCREL_7_0 = 0x20, + R_ARM_ALU_PCREL_15_8 = 0x21, + R_ARM_ALU_PCREL_23_15 = 0x22, + R_ARM_LDR_SBREL_11_0_NC = 0x23, + R_ARM_ALU_SBREL_19_12_NC = 0x24, + R_ARM_ALU_SBREL_27_20_CK = 0x25, + R_ARM_TARGET1 = 0x26, + R_ARM_SBREL31 = 0x27, + R_ARM_V4BX = 0x28, + R_ARM_TARGET2 = 0x29, + R_ARM_PREL31 = 0x2a, + R_ARM_MOVW_ABS_NC = 0x2b, + R_ARM_MOVT_ABS = 0x2c, + R_ARM_MOVW_PREL_NC = 0x2d, + R_ARM_MOVT_PREL = 0x2e, + R_ARM_THM_MOVW_ABS_NC = 0x2f, + R_ARM_THM_MOVT_ABS = 0x30, + R_ARM_THM_MOVW_PREL_NC = 0x31, + R_ARM_THM_MOVT_PREL = 0x32, + R_ARM_THM_JUMP19 = 0x33, + R_ARM_THM_JUMP6 = 0x34, + R_ARM_THM_ALU_PREL_11_0 = 0x35, + R_ARM_THM_PC12 = 0x36, + R_ARM_ABS32_NOI = 0x37, + R_ARM_REL32_NOI = 0x38, + R_ARM_ALU_PC_G0_NC = 0x39, + R_ARM_ALU_PC_G0 = 0x3a, + R_ARM_ALU_PC_G1_NC = 0x3b, + R_ARM_ALU_PC_G1 = 0x3c, + R_ARM_ALU_PC_G2 = 0x3d, + R_ARM_LDR_PC_G1 = 0x3e, + R_ARM_LDR_PC_G2 = 0x3f, + R_ARM_LDRS_PC_G0 = 0x40, + R_ARM_LDRS_PC_G1 = 0x41, + R_ARM_LDRS_PC_G2 = 0x42, + R_ARM_LDC_PC_G0 = 0x43, + R_ARM_LDC_PC_G1 = 0x44, + R_ARM_LDC_PC_G2 = 0x45, + R_ARM_ALU_SB_G0_NC = 0x46, + R_ARM_ALU_SB_G0 = 0x47, + R_ARM_ALU_SB_G1_NC = 0x48, + R_ARM_ALU_SB_G1 = 0x49, + R_ARM_ALU_SB_G2 = 0x4a, + R_ARM_LDR_SB_G0 = 0x4b, + R_ARM_LDR_SB_G1 = 0x4c, + R_ARM_LDR_SB_G2 = 0x4d, + R_ARM_LDRS_SB_G0 = 0x4e, + R_ARM_LDRS_SB_G1 = 0x4f, + R_ARM_LDRS_SB_G2 = 0x50, + R_ARM_LDC_SB_G0 = 0x51, + R_ARM_LDC_SB_G1 = 0x52, + R_ARM_LDC_SB_G2 = 0x53, + R_ARM_MOVW_BREL_NC = 0x54, + R_ARM_MOVT_BREL = 0x55, + R_ARM_MOVW_BREL = 0x56, + R_ARM_THM_MOVW_BREL_NC = 0x57, + R_ARM_THM_MOVT_BREL = 0x58, + R_ARM_THM_MOVW_BREL = 0x59, + R_ARM_TLS_GOTDESC = 0x5a, + R_ARM_TLS_CALL = 0x5b, + R_ARM_TLS_DESCSEQ = 0x5c, + R_ARM_THM_TLS_CALL = 0x5d, + R_ARM_PLT32_ABS = 0x5e, + R_ARM_GOT_ABS = 0x5f, + R_ARM_GOT_PREL = 0x60, + R_ARM_GOT_BREL12 = 0x61, + R_ARM_GOTOFF12 = 0x62, + R_ARM_GOTRELAX = 0x63, + R_ARM_GNU_VTENTRY = 0x64, + R_ARM_GNU_VTINHERIT = 0x65, + R_ARM_THM_JUMP11 = 0x66, + R_ARM_THM_JUMP8 = 0x67, + R_ARM_TLS_GD32 = 0x68, + R_ARM_TLS_LDM32 = 0x69, + R_ARM_TLS_LDO32 = 0x6a, + R_ARM_TLS_IE32 = 0x6b, + R_ARM_TLS_LE32 = 0x6c, + R_ARM_TLS_LDO12 = 0x6d, + R_ARM_TLS_LE12 = 0x6e, + R_ARM_TLS_IE12GP = 0x6f, + R_ARM_PRIVATE_0 = 0x70, + R_ARM_PRIVATE_1 = 0x71, + R_ARM_PRIVATE_2 = 0x72, + R_ARM_PRIVATE_3 = 0x73, + R_ARM_PRIVATE_4 = 0x74, + R_ARM_PRIVATE_5 = 0x75, + R_ARM_PRIVATE_6 = 0x76, + R_ARM_PRIVATE_7 = 0x77, + R_ARM_PRIVATE_8 = 0x78, + R_ARM_PRIVATE_9 = 0x79, + R_ARM_PRIVATE_10 = 0x7a, + R_ARM_PRIVATE_11 = 0x7b, + R_ARM_PRIVATE_12 = 0x7c, + R_ARM_PRIVATE_13 = 0x7d, + R_ARM_PRIVATE_14 = 0x7e, + R_ARM_PRIVATE_15 = 0x7f, + R_ARM_ME_TOO = 0x80, + R_ARM_THM_TLS_DESCSEQ16 = 0x81, + R_ARM_THM_TLS_DESCSEQ32 = 0x82 +}; + + + +// Section header. +struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) + Elf32_Word sh_type; // Section type (SHT_*) + Elf32_Word sh_flags; // Section flags (SHF_*) + Elf32_Addr sh_addr; // Address where section is to be loaded + Elf32_Off sh_offset; // File offset of section data, in bytes + Elf32_Word sh_size; // Size of section, in bytes + Elf32_Word sh_link; // Section type-specific header table index link + Elf32_Word sh_info; // Section type-specific extra information + Elf32_Word sh_addralign; // Section address alignment + Elf32_Word sh_entsize; // Size of records contained within the section +}; + +// Section header for ELF64 - same fields as ELF32, different types. +struct Elf64_Shdr { + Elf64_Half sh_name; + Elf64_Half sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Half sh_link; + Elf64_Half sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + +// Special section indices. +enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE + SHN_HIRESERVE = 0xffff // Highest reserved index +}; + +// Section types. +enum { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_INIT_ARRAY = 14, // Pointers to initialisation functions. + SHT_FINI_ARRAY = 15, // Pointers to termination functions. + SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. + SHT_GROUP = 17, // Section group. + SHT_SYMTAB_SHNDX = 18, // Indicies for SHN_XINDEX entries. + SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. +}; + +// Section flags. +enum { + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000 +}; + +// Section Group Flags +enum { + GRP_COMDAT = 0x1, + GRP_MASKOS = 0x0ff00000, + GRP_MASKPROC = 0xf0000000 +}; + +// Symbol table entries for ELF32. +struct Elf32_Sym { + Elf32_Word st_name; // Symbol name (index into string table) + Elf32_Addr st_value; // Value or address associated with the symbol + Elf32_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf32_Half st_shndx; // Which section (header table index) it's defined in + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// Symbol table entries for ELF64. +struct Elf64_Sym { + Elf64_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf64_Half st_shndx; // Which section (header table index) it's defined in + Elf64_Addr st_value; // Value or address associated with the symbol + Elf64_Xword st_size; // Size of the symbol + + // These accessors and mutators are identical to those defined for ELF32 + // symbol table entries. + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// The size (in bytes) of symbol table entries. +enum { + SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size + SYMENTRY_SIZE64 = 24 // 64-bit symbol entry size. +}; + +// Symbol bindings. +enum { + STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def + STB_GLOBAL = 1, // Global symbol, visible to all object files being combined + STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_LOPROC = 13, // Lowest processor-specific binding type + STB_HIPROC = 15 // Highest processor-specific binding type +}; + +// Symbol types. +enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4, // Local, absolute symbol that refers to a file + STT_COMMON = 5, // An uninitialised common block + STT_TLS = 6, // Thread local data object + STT_LOPROC = 13, // Lowest processor-specific symbol type + STT_HIPROC = 15 // Highest processor-specific symbol type +}; + +enum { + STV_DEFAULT = 0, // Visibility is specified by binding type + STV_INTERNAL = 1, // Defined by processor supplements + STV_HIDDEN = 2, // Not visible to other components + STV_PROTECTED = 3 // Visible in other components but not preemptable +}; + +// Relocation entry, without explicit addend. +struct Elf32_Rel { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry with explicit addend. +struct Elf32_Rela { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + Elf32_Sword r_addend; // Compute value for relocatable field by adding this + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry, without explicit addend. +struct Elf64_Rel { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Xword getSymbol() const { return (r_info >> 32); } + unsigned char getType() const { + return (unsigned char) (r_info & 0xffffffffL); + } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Xword s, unsigned char t) { + r_info = (s << 32) + (t&0xffffffffL); + } +}; + +// Relocation entry with explicit addend. +struct Elf64_Rela { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + Elf64_Sxword r_addend; // Compute value for relocatable field by adding this. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Xword getSymbol() const { return (r_info >> 32); } + unsigned char getType() const { + return (unsigned char) (r_info & 0xffffffffL); + } + void setSymbol(Elf64_Xword s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Xword s, unsigned char t) { + r_info = (s << 32) + (t&0xffffffffL); + } +}; + +// Program header for ELF32. +struct Elf32_Phdr { + Elf32_Word p_type; // Type of segment + Elf32_Off p_offset; // File offset where segment is located, in bytes + Elf32_Addr p_vaddr; // Virtual address of beginning of segment + Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Segment alignment constraint +}; + +// Program header for ELF64. +struct Elf64_Phdr { + Elf64_Word p_type; // Type of segment + Elf64_Word p_flags; // Segment flags + Elf64_Off p_offset; // File offset where segment is located, in bytes + Elf64_Addr p_vaddr; // Virtual address of beginning of segment + Elf64_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf64_Xword p_align; // Segment alignment constraint +}; + +// Segment types. +enum { + PT_NULL = 0, // Unused segment. + PT_LOAD = 1, // Loadable segment. + PT_DYNAMIC = 2, // Dynamic linking information. + PT_INTERP = 3, // Interpreter pathname. + PT_NOTE = 4, // Auxiliary information. + PT_SHLIB = 5, // Reserved. + PT_PHDR = 6, // The program header table itself. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. +}; + +// Segment flag bits. +enum { + PF_X = 1, // Execute + PF_W = 2, // Write + PF_R = 4, // Read + PF_MASKPROC = 0xf0000000 // Unspecified +}; + +// Dynamic table entry for ELF32. +struct Elf32_Dyn +{ + Elf32_Sword d_tag; // Type of dynamic table entry. + union + { + Elf32_Word d_val; // Integer value of entry. + Elf32_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry for ELF64. +struct Elf64_Dyn +{ + Elf64_Sxword d_tag; // Type of dynamic table entry. + union + { + Elf64_Xword d_val; // Integer value of entry. + Elf64_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry tags. +enum { + DT_NULL = 0, // Marks end of dynamic array. + DT_NEEDED = 1, // String table offset of needed library. + DT_PLTRELSZ = 2, // Size of relocation entries in PLT. + DT_PLTGOT = 3, // Address associated with linkage table. + DT_HASH = 4, // Address of symbolic hash table. + DT_STRTAB = 5, // Address of dynamic string table. + DT_SYMTAB = 6, // Address of dynamic symbol table. + DT_RELA = 7, // Address of relocation table (Rela entries). + DT_RELASZ = 8, // Size of Rela relocation table. + DT_RELAENT = 9, // Size of a Rela relocation entry. + DT_STRSZ = 10, // Total size of the string table. + DT_SYMENT = 11, // Size of a symbol table entry. + DT_INIT = 12, // Address of initialization function. + DT_FINI = 13, // Address of termination function. + DT_SONAME = 14, // String table offset of a shared objects name. + DT_RPATH = 15, // String table offset of library search path. + DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. + DT_REL = 17, // Address of relocation table (Rel entries). + DT_RELSZ = 18, // Size of Rel relocation table. + DT_RELENT = 19, // Size of a Rel relocation entry. + DT_PLTREL = 20, // Type of relocation entry used for linking. + DT_DEBUG = 21, // Reserved for debugger. + DT_TEXTREL = 22, // Relocations exist for non-writable segements. + DT_JMPREL = 23, // Address of relocations associated with PLT. + DT_BIND_NOW = 24, // Process all relocations before execution. + DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. + DT_FINI_ARRAY = 26, // Pointer to array of termination functions. + DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. + DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. + DT_LOOS = 0x60000000, // Start of environment specific tags. + DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. + DT_LOPROC = 0x70000000, // Start of processor specific tags. + DT_HIPROC = 0x7FFFFFFF // End of processor specific tags. +}; + +} // end namespace ELF + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/Endian.h b/final/include/llvm/Support/Endian.h new file mode 100644 index 00000000000..f62eab0702b --- /dev/null +++ b/final/include/llvm/Support/Endian.h @@ -0,0 +1,213 @@ +//===- Endian.h - Utilities for IO with endian specific data ----*- 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 generic functions to read and write endian specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ENDIAN_H +#define LLVM_SUPPORT_ENDIAN_H + +#include "llvm/Config/config.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/type_traits.h" + +namespace llvm { +namespace support { + +enum endianness {big, little}; +enum alignment {unaligned, aligned}; + +namespace detail { + +template +struct alignment_access_helper; + +template +struct alignment_access_helper +{ + value_type val; +}; + +// Provides unaligned loads and stores. +#pragma pack(push) +#pragma pack(1) +template +struct alignment_access_helper +{ + value_type val; +}; +#pragma pack(pop) + +} // end namespace detail + +namespace endian { + template + static value_type read_le(const void *memory) { + value_type t = + reinterpret_cast *>(memory)->val; + if (sys::isBigEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template + static void write_le(void *memory, value_type value) { + if (sys::isBigEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast *> + (memory)->val = value; + } + + template + static value_type read_be(const void *memory) { + value_type t = + reinterpret_cast *>(memory)->val; + if (sys::isLittleEndianHost()) + return sys::SwapByteOrder(t); + return t; + } + + template + static void write_be(void *memory, value_type value) { + if (sys::isLittleEndianHost()) + value = sys::SwapByteOrder(value); + reinterpret_cast *> + (memory)->val = value; + } +} + +namespace detail { + +template +class packed_endian_specific_integral; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_le(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_be(Value); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_le(&Value); + } +private: + value_type Value; +}; + +template +class packed_endian_specific_integral { +public: + operator value_type() const { + return endian::read_be(&Value); + } +private: + value_type Value; +}; + +} // end namespace detail + +typedef detail::packed_endian_specific_integral + ulittle8_t; +typedef detail::packed_endian_specific_integral + ulittle16_t; +typedef detail::packed_endian_specific_integral + ulittle32_t; +typedef detail::packed_endian_specific_integral + ulittle64_t; + +typedef detail::packed_endian_specific_integral + little8_t; +typedef detail::packed_endian_specific_integral + little16_t; +typedef detail::packed_endian_specific_integral + little32_t; +typedef detail::packed_endian_specific_integral + little64_t; + +typedef detail::packed_endian_specific_integral + aligned_ulittle8_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle16_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle32_t; +typedef detail::packed_endian_specific_integral + aligned_ulittle64_t; + +typedef detail::packed_endian_specific_integral + aligned_little8_t; +typedef detail::packed_endian_specific_integral + aligned_little16_t; +typedef detail::packed_endian_specific_integral + aligned_little32_t; +typedef detail::packed_endian_specific_integral + aligned_little64_t; + +typedef detail::packed_endian_specific_integral + ubig8_t; +typedef detail::packed_endian_specific_integral + ubig16_t; +typedef detail::packed_endian_specific_integral + ubig32_t; +typedef detail::packed_endian_specific_integral + ubig64_t; + +typedef detail::packed_endian_specific_integral + big8_t; +typedef detail::packed_endian_specific_integral + big16_t; +typedef detail::packed_endian_specific_integral + big32_t; +typedef detail::packed_endian_specific_integral + big64_t; + +typedef detail::packed_endian_specific_integral + aligned_ubig8_t; +typedef detail::packed_endian_specific_integral + aligned_ubig16_t; +typedef detail::packed_endian_specific_integral + aligned_ubig32_t; +typedef detail::packed_endian_specific_integral + aligned_ubig64_t; + +typedef detail::packed_endian_specific_integral + aligned_big8_t; +typedef detail::packed_endian_specific_integral + aligned_big16_t; +typedef detail::packed_endian_specific_integral + aligned_big32_t; +typedef detail::packed_endian_specific_integral + aligned_big64_t; + +} // end namespace llvm +} // end namespace support + +#endif diff --git a/final/include/llvm/Support/Errno.h b/final/include/llvm/Support/Errno.h new file mode 100644 index 00000000000..150bdb70162 --- /dev/null +++ b/final/include/llvm/Support/Errno.h @@ -0,0 +1,34 @@ +//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- 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 some portable and convenient functions to deal with errno. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ERRNO_H +#define LLVM_SYSTEM_ERRNO_H + +#include + +namespace llvm { +namespace sys { + +/// Returns a string representation of the errno value, using whatever +/// thread-safe variant of strerror() is available. Be sure to call this +/// immediately after the function that set errno, or errno may have been +/// overwritten by an intervening call. +std::string StrError(); + +/// Like the no-argument version above, but uses \p errnum instead of errno. +std::string StrError(int errnum); + +} // namespace sys +} // namespace llvm + +#endif // LLVM_SYSTEM_ERRNO_H diff --git a/final/include/llvm/Support/ErrorHandling.h b/final/include/llvm/Support/ErrorHandling.h new file mode 100644 index 00000000000..5eca438d8b4 --- /dev/null +++ b/final/include/llvm/Support/ErrorHandling.h @@ -0,0 +1,103 @@ +//===- llvm/Support/ErrorHandling.h - Fatal error handling ------*- 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 an API used to indicate fatal error conditions. Non-fatal +// errors (most of them) should be handled through LLVMContext. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRORHANDLING_H +#define LLVM_SUPPORT_ERRORHANDLING_H + +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/StringRef.h" +#include + +namespace llvm { + class Twine; + + /// An error handler callback. + typedef void (*fatal_error_handler_t)(void *user_data, + const std::string& reason); + + /// install_fatal_error_handler - Installs a new error handler to be used + /// whenever a serious (non-recoverable) error is encountered by LLVM. + /// + /// If you are using llvm_start_multithreaded, you should register the handler + /// before doing that. + /// + /// If no error handler is installed the default is to print the error message + /// to stderr, and call exit(1). If an error handler is installed then it is + /// the handler's responsibility to log the message, it will no longer be + /// printed to stderr. If the error handler returns, then exit(1) will be + /// called. + /// + /// It is dangerous to naively use an error handler which throws an exception. + /// Even though some applications desire to gracefully recover from arbitrary + /// faults, blindly throwing exceptions through unfamiliar code isn't a way to + /// achieve this. + /// + /// \param user_data - An argument which will be passed to the install error + /// handler. + void install_fatal_error_handler(fatal_error_handler_t handler, + void *user_data = 0); + + /// Restores default error handling behaviour. + /// This must not be called between llvm_start_multithreaded() and + /// llvm_stop_multithreaded(). + void remove_fatal_error_handler(); + + /// ScopedFatalErrorHandler - This is a simple helper class which just + /// calls install_fatal_error_handler in its constructor and + /// remove_fatal_error_handler in its destructor. + struct ScopedFatalErrorHandler { + explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, + void *user_data = 0) { + install_fatal_error_handler(handler, user_data); + } + + ~ScopedFatalErrorHandler() { remove_fatal_error_handler(); } + }; + + /// Reports a serious error, calling any installed error handler. These + /// functions are intended to be used for error conditions which are outside + /// the control of the compiler (I/O errors, invalid user input, etc.) + /// + /// If no error handler is installed the default is to print the message to + /// standard error, followed by a newline. + /// After the error handler is called this function will call exit(1), it + /// does not return. + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason); + + /// This function calls abort(), and prints the optional message to stderr. + /// Use the llvm_unreachable macro (that adds location info), instead of + /// calling this function directly. + LLVM_ATTRIBUTE_NORETURN void llvm_unreachable_internal(const char *msg=0, + const char *file=0, + unsigned line=0); +} + +/// Prints the message and location info to stderr in !NDEBUG builds. +/// This is intended to be used for "impossible" situations that imply +/// a bug in the compiler. +/// +/// In NDEBUG mode it only prints "UNREACHABLE executed". +/// Use this instead of assert(0), so that the compiler knows this path +/// is not reachable even for NDEBUG builds. +#ifndef NDEBUG +#define llvm_unreachable(msg) \ + ::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__) +#else +#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal() +#endif + +#endif diff --git a/final/include/llvm/Support/FEnv.h b/final/include/llvm/Support/FEnv.h new file mode 100644 index 00000000000..f6f43337bd2 --- /dev/null +++ b/final/include/llvm/Support/FEnv.h @@ -0,0 +1,56 @@ +//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- 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 an operating system independent interface to +// floating-point exception interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_FENV_H +#define LLVM_SYSTEM_FENV_H + +#include "llvm/Config/config.h" +#include +#ifdef HAVE_FENV_H +#include +#endif + +// FIXME: Clang's #include handling apparently doesn't work for libstdc++'s +// fenv.h; see PR6907 for details. +#if defined(__clang__) && defined(_GLIBCXX_FENV_H) +#undef HAVE_FENV_H +#endif + +namespace llvm { +namespace sys { + +/// llvm_fenv_clearexcept - Clear the floating-point exception state. +static inline void llvm_fenv_clearexcept() { +#ifdef HAVE_FENV_H + feclearexcept(FE_ALL_EXCEPT); +#endif + errno = 0; +} + +/// llvm_fenv_testexcept - Test if a floating-point exception was raised. +static inline bool llvm_fenv_testexcept() { + int errno_val = errno; + if (errno_val == ERANGE || errno_val == EDOM) + return true; +#ifdef HAVE_FENV_H + if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) + return true; +#endif + return false; +} + +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/FileSystem.h b/final/include/llvm/Support/FileSystem.h new file mode 100644 index 00000000000..4f013f89e86 --- /dev/null +++ b/final/include/llvm/Support/FileSystem.h @@ -0,0 +1,690 @@ +//===- llvm/Support/FileSystem.h - File System OS Concept -------*- 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 llvm::sys::fs namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +// All functions return an error_code and their actual work via the last out +// argument. The out argument is defined if and only if errc::success is +// returned. A function may return any error code in the generic or system +// category. However, they shall be equivalent to any error conditions listed +// in each functions respective documentation if the condition applies. [ note: +// this does not guarantee that error_code will be in the set of explicitly +// listed codes, but it does guarantee that if any of the explicitly listed +// errors occur, the correct error_code will be used ]. All functions may +// return errc::not_enough_memory if there is not enough memory to complete the +// operation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILE_SYSTEM_H +#define LLVM_SUPPORT_FILE_SYSTEM_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PathV1.h" +#include "llvm/Support/system_error.h" +#include +#include +#include + +namespace llvm { +namespace sys { +namespace fs { + +/// file_type - An "enum class" enumeration for the file system's view of the +/// type. +struct file_type { + enum _ { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown + }; + + file_type(_ v) : v_(v) {} + explicit file_type(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// copy_option - An "enum class" enumeration of copy semantics for copy +/// operations. +struct copy_option { + enum _ { + fail_if_exists, + overwrite_if_exists + }; + + copy_option(_ v) : v_(v) {} + explicit copy_option(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// space_info - Self explanatory. +struct space_info { + uint64_t capacity; + uint64_t free; + uint64_t available; +}; + +/// file_status - Represents the result of a call to stat and friends. It has +/// a platform specific member to store the result. +class file_status +{ + // implementation defined status field. + file_type Type; +public: + explicit file_status(file_type v=file_type::status_error) + : Type(v) {} + + file_type type() const { return Type; } + void type(file_type v) { Type = v; } +}; + +/// @} +/// @name Physical Operators +/// @{ + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the current directory if it is not already. An +/// empty \a path will result in the current directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => /relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform specific error_code. +error_code make_absolute(SmallVectorImpl &path); + +/// @brief Copy the file at \a from to the path \a to. +/// +/// @param from The path to copy the file from. +/// @param to The path to copy the file to. +/// @param copt Behavior if \a to already exists. +/// @returns errc::success if the file has been successfully copied. +/// errc::file_exists if \a to already exists and \a copt == +/// copy_option::fail_if_exists. Otherwise a platform specific +/// error_code. +error_code copy_file(const Twine &from, const Twine &to, + copy_option copt = copy_option::fail_if_exists); + +/// @brief Create all the non-existent directories in path. +/// +/// @param path Directories to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directories(const Twine &path, bool &existed); + +/// @brief Create the directory in path. +/// +/// @param path Directory to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directory(const Twine &path, bool &existed); + +/// @brief Create a hard link from \a from to \a to. +/// +/// @param to The path to hard link to. +/// @param from The path to hard link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) +/// , otherwise a platform specific error_code. +error_code create_hard_link(const Twine &to, const Twine &from); + +/// @brief Create a symbolic link from \a from to \a to. +/// +/// @param to The path to symbolically link to. +/// @param from The path to symbolically link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), +/// otherwise a platform specific error_code. +error_code create_symlink(const Twine &to, const Twine &from); + +/// @brief Get the current path. +/// +/// @param result Holds the current path on return. +/// @results errc::success if the current path has been stored in result, +/// otherwise a platform specific error_code. +error_code current_path(SmallVectorImpl &result); + +/// @brief Remove path. Equivalent to POSIX remove(). +/// +/// @param path Input path. +/// @param existed Set to true if \a path existed, false if it did not. +/// undefined otherwise. +/// @results errc::success if path has been removed and existed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove(const Twine &path, bool &existed); + +/// @brief Recursively remove all files below \a path, then \a path. Files are +/// removed as if by POSIX remove(). +/// +/// @param path Input path. +/// @param num_removed Number of files removed. +/// @results errc::success if path has been removed and num_removed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove_all(const Twine &path, uint32_t &num_removed); + +/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). +/// +/// @param from The path to rename from. +/// @param to The path to rename to. This is created. +error_code rename(const Twine &from, const Twine &to); + +/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// +/// @param path Input path. +/// @param size Size to resize to. +/// @returns errc::success if \a path has been resized to \a size, otherwise a +/// platform specific error_code. +error_code resize_file(const Twine &path, uint64_t size); + +/// @brief Make file readable. +/// +/// @param path Input path. +/// @param value If true, make readable, else, make unreadable. +/// @results errc::success if readability has been successfully set, otherwise a +/// platform specific error_code. +error_code set_read(const Twine &path, bool value); + +/// @brief Make file writeable. +/// +/// @param path Input path. +/// @param value If true, make writeable, else, make unwriteable. +/// @results errc::success if writeability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_write(const Twine &path, bool value); + +/// @brief Make file executable. +/// +/// @param path Input path. +/// @param value If true, make executable, else, make unexecutable. +/// @results errc::success if executability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_execute(const Twine &path, bool value); + +/// @} +/// @name Physical Observers +/// @{ + +/// @brief Does file exist? +/// +/// @param status A file_status previously returned from stat. +/// @results True if the file represented by status exists, false if it does +/// not. +bool exists(file_status status); + +/// @brief Does file exist? +/// +/// @param path Input path. +/// @param result Set to true if the file represented by status exists, false if +/// it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code exists(const Twine &path, bool &result); + +/// @brief Do file_status's represent the same thing? +/// +/// @param A Input file_status. +/// @param B Input file_status. +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @results True if A and B both represent the same file system entity, false +/// otherwise. +bool equivalent(file_status A, file_status B); + +/// @brief Do paths represent the same thing? +/// +/// @param A Input path A. +/// @param B Input path B. +/// @param result Set to true if stat(A) and stat(B) have the same device and +/// inode (or equivalent). +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code equivalent(const Twine &A, const Twine &B, bool &result); + +/// @brief Get file size. +/// +/// @param path Input path. +/// @param result Set to the size of the file in \a path. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code file_size(const Twine &path, uint64_t &result); + +/// @brief Does status represent a directory? +/// +/// @param status A file_status previously returned from status. +/// @results status.type() == file_type::directory_file. +bool is_directory(file_status status); + +/// @brief Is path a directory? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a directory, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_directory(const Twine &path, bool &result); + +/// @brief Is path an empty file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a an empty file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_empty(const Twine &path, bool &result); + +/// @brief Does status represent a regular file? +/// +/// @param status A file_status previously returned from status. +/// @results status_known(status) && status.type() == file_type::regular_file. +bool is_regular_file(file_status status); + +/// @brief Is path a regular file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a regular file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_regular_file(const Twine &path, bool &result); + +/// @brief Does this status represent something that exists but is not a +/// directory, regular file, or symlink? +/// +/// @param status A file_status previously returned from status. +/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && +/// !is_symlink(s) +bool is_other(file_status status); + +/// @brief Is path something that exists but is not a directory, +/// regular file, or symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path exists, but is not a directory, regular +/// file, or a symlink, false if it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_other(const Twine &path, bool &result); + +/// @brief Does status represent a symlink? +/// +/// @param status A file_status previously returned from stat. +/// @param result status.type() == symlink_file. +bool is_symlink(file_status status); + +/// @brief Is path a symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a symlink, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_symlink(const Twine &path, bool &result); + +/// @brief Get last write time without changing it. +/// +/// @param path Input path. +/// @param result Set to the last write time (UNIX time) of \a path if it +/// exists. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code last_write_time(const Twine &path, std::time_t &result); + +/// @brief Set last write time. +/// +/// @param path Input path. +/// @param value Time to set (UNIX time) \a path's last write time to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code set_last_write_time(const Twine &path, std::time_t value); + +/// @brief Read a symlink's value. +/// +/// @param path Input path. +/// @param result Set to the value of the symbolic link \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code read_symlink(const Twine &path, SmallVectorImpl &result); + +/// @brief Get disk space usage information. +/// +/// @param path Input path. +/// @param result Set to the capacity, free, and available space on the device +/// \a path is on. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code disk_space(const Twine &path, space_info &result); + +/// @brief Get file status as if by POSIX stat(). +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status(const Twine &path, file_status &result); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @results True if status() != status_error. +bool status_known(file_status s); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @param result Set to true if status() != status_error. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status_known(const Twine &path, bool &result); + +/// @brief Get file status as if by POSIX lstat(). +/// +/// Does not resolve symlinks. +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code symlink_status(const Twine &path, file_status &result); + +/// @brief Generate a unique path and open it as a file. +/// +/// Generates a unique path suitable for a temporary file and then opens it as a +/// file. The name is based on \a model with '%' replaced by a random char in +/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary +/// directory will be prepended. +/// +/// This is an atomic operation. Either the file is created and opened, or the +/// file system is left untouched. +/// +/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s +/// +/// @param model Name to base unique path off of. +/// @param result_fs Set to the opened file's file descriptor. +/// @param result_path Set to the opened file's absolute path. +/// @results errc::success if result_{fd,path} have been successfully set, +/// otherwise a platform specific error_code. +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl &result_path); + +/// @brief Canonicalize path. +/// +/// Sets result to the file system's idea of what path is. The result is always +/// absolute and has the same capitalization as the file system. +/// +/// @param path Input path. +/// @param result Set to the canonicalized version of \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code canonicalize(const Twine &path, SmallVectorImpl &result); + +/// @brief Are \a path's first bytes \a magic? +/// +/// @param path Input path. +/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code has_magic(const Twine &path, const Twine &magic, bool &result); + +/// @brief Get \a path's first \a len bytes. +/// +/// @param path Input path. +/// @param len Number of magic bytes to get. +/// @param result Set to the first \a len bytes in the file pointed to by +/// \a path. Or the entire file if file_size(path) < len, in which +/// case result.size() returns the size of the file. +/// @results errc::success if result has been successfully set, +/// errc::value_too_large if len is larger then the file pointed to by +/// \a path, otherwise a platform specific error_code. +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl &result); + +/// @brief Get and identify \a path's type based on its content. +/// +/// @param path Input path. +/// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code identify_magic(const Twine &path, LLVMFileType &result); + +/// @brief Is file bitcode? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a bitcode file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_bitcode(const Twine &path, bool &result); + +/// @brief Is file a dynamic library? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a dynamic library, false if it is +/// not, undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_dynamic_library(const Twine &path, bool &result); + +/// @brief Is an object file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is an object file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_object_file(const Twine &path, bool &result); + +/// @brief Can file be read? +/// +/// @param path Input path. +/// @param result Set to true if \a path is readable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_read(const Twine &path, bool &result); + +/// @brief Can file be written? +/// +/// @param path Input path. +/// @param result Set to true if \a path is writeable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_write(const Twine &path, bool &result); + +/// @brief Can file be executed? +/// +/// @param path Input path. +/// @param result Set to true if \a path is executable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_execute(const Twine &path, bool &result); + +/// @brief Get library paths the system linker uses. +/// +/// @param result Set to the list of system library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetSystemLibraryPaths(SmallVectorImpl &result); + +/// @brief Get bitcode library paths the system linker uses +/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. +/// +/// @param result Set to the list of bitcode library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetBitcodeLibraryPaths(SmallVectorImpl &result); + +/// @brief Find a library. +/// +/// Find the path to a library using its short name. Use the system +/// dependent library paths to locate the library. +/// +/// c => /usr/lib/libc.so +/// +/// @param short_name Library name one would give to the system linker. +/// @param result Set to the absolute path \a short_name represents. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code FindLibrary(const Twine &short_name, SmallVectorImpl &result); + +/// @brief Get absolute path of main executable. +/// +/// @param argv0 The program name as it was spelled on the command line. +/// @param MainAddr Address of some symbol in the executable (not in a library). +/// @param result Set to the absolute path of the current executable. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetMainExecutable(const char *argv0, void *MainAddr, + SmallVectorImpl &result); + +/// @} +/// @name Iterators +/// @{ + +/// directory_entry - A single entry in a directory. Caches the status either +/// from the result of the iteration syscall, or the first time status or +/// symlink_status is called. +class directory_entry { + std::string Path; + mutable file_status Status; + mutable file_status SymlinkStatus; + +public: + explicit directory_entry(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) + : Path(path.str()) + , Status(st) + , SymlinkStatus(symlink_st) {} + + directory_entry() {} + + void assign(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) { + Path = path.str(); + Status = st; + SymlinkStatus = symlink_st; + } + + void replace_filename(const Twine &filename, file_status st = file_status(), + file_status symlink_st = file_status()); + + const std::string &path() const { return Path; } + error_code status(file_status &result) const; + error_code symlink_status(file_status &result) const; + + bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } + bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } + bool operator< (const directory_entry& rhs) const; + bool operator<=(const directory_entry& rhs) const; + bool operator> (const directory_entry& rhs) const; + bool operator>=(const directory_entry& rhs) const; +}; + +/// directory_iterator - Iterates through the entries in path. There is no +/// operator++ because we need an error_code. If it's really needed we can make +/// it call report_fatal_error on error. +class directory_iterator { + intptr_t IterationHandle; + directory_entry CurrentEntry; + + // Platform implementations implement these functions to handle iteration. + friend error_code directory_iterator_construct(directory_iterator &it, + StringRef path); + friend error_code directory_iterator_increment(directory_iterator &it); + friend error_code directory_iterator_destruct(directory_iterator &it); + +public: + explicit directory_iterator(const Twine &path, error_code &ec) + : IterationHandle(0) { + SmallString<128> path_storage; + ec = directory_iterator_construct(*this, path.toStringRef(path_storage)); + } + + /// Construct end iterator. + directory_iterator() : IterationHandle(0) {} + + ~directory_iterator() { + directory_iterator_destruct(*this); + } + + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec) { + ec = directory_iterator_increment(*this); + return *this; + } + + const directory_entry &operator*() const { return CurrentEntry; } + const directory_entry *operator->() const { return &CurrentEntry; } + + bool operator!=(const directory_iterator &RHS) const { + return CurrentEntry != RHS.CurrentEntry; + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// recursive_directory_iterator - Same as directory_iterator except for it +/// recurses down into child directories. +class recursive_directory_iterator { + uint16_t Level; + bool HasNoPushRequest; + // implementation directory iterator status + +public: + explicit recursive_directory_iterator(const Twine &path, error_code &ec); + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec); + + const directory_entry &operator*() const; + const directory_entry *operator->() const; + + // observers + /// Gets the current level. path is at level 0. + int level() const; + /// Returns true if no_push has been called for this directory_entry. + bool no_push_request() const; + + // modifiers + /// Goes up one level if Level > 0. + void pop(); + /// Does not go down into the current directory_entry. + void no_push(); + + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// @} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/FileUtilities.h b/final/include/llvm/Support/FileUtilities.h new file mode 100644 index 00000000000..748ce7cea7b --- /dev/null +++ b/final/include/llvm/Support/FileUtilities.h @@ -0,0 +1,72 @@ +//===- llvm/Support/FileUtilities.h - File System Utilities -----*- 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 family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEUTILITIES_H +#define LLVM_SUPPORT_FILEUTILITIES_H + +#include "llvm/Support/Path.h" + +namespace llvm { + + /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if + /// the files match, 1 if they are different, and 2 if there is a file error. + /// This function allows you to specify an absolete and relative FP error that + /// is allowed to exist. If you specify a string to fill in for the error + /// option, it will set the string to an error message if an error occurs, or + /// if the files are different. + /// + int DiffFilesWithTolerance(const sys::PathWithStatus &FileA, + const sys::PathWithStatus &FileB, + double AbsTol, double RelTol, + std::string *Error = 0); + + + /// FileRemover - This class is a simple object meant to be stack allocated. + /// If an exception is thrown from a region, the object removes the filename + /// specified (if deleteIt is true). + /// + class FileRemover { + sys::Path Filename; + bool DeleteIt; + public: + FileRemover() : DeleteIt(false) {} + + explicit FileRemover(const sys::Path &filename, bool deleteIt = true) + : Filename(filename), DeleteIt(deleteIt) {} + + ~FileRemover() { + if (DeleteIt) { + // Ignore problems deleting the file. + Filename.eraseFromDisk(); + } + } + + /// setFile - Give ownership of the file to the FileRemover so it will + /// be removed when the object is destroyed. If the FileRemover already + /// had ownership of a file, remove it first. + void setFile(const sys::Path &filename, bool deleteIt = true) { + if (DeleteIt) + Filename.eraseFromDisk(); + + Filename = filename; + DeleteIt = deleteIt; + } + + /// releaseFile - Take ownership of the file away from the FileRemover so it + /// will not be removed when the object is destroyed. + void releaseFile() { DeleteIt = false; } + }; +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Format.h b/final/include/llvm/Support/Format.h new file mode 100644 index 00000000000..f64e3db7d65 --- /dev/null +++ b/final/include/llvm/Support/Format.h @@ -0,0 +1,154 @@ +//===- Format.h - Efficient printf-style formatting for streams -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the format() function, which can be used with other +// LLVM subsystems to provide printf-style formatting. This gives all the power +// and risk of printf. This can be used like this (with raw_ostreams as an +// example): +// +// OS << "mynumber: " << format("%4.5f", 1234.412) << '\n'; +// +// Or if you prefer: +// +// OS << format("mynumber: %4.5f\n", 1234.412); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FORMAT_H +#define LLVM_SUPPORT_FORMAT_H + +#include +#include +#ifdef _MSC_VER +// FIXME: This define is wrong: +// - _snprintf does not guarantee that trailing null is always added - if +// there is no space for null, it does not report any error. +// - According to C++ standard, snprintf should be visible in the 'std' +// namespace - this define makes this impossible. +#define snprintf _snprintf +#endif + +namespace llvm { + +/// format_object_base - This is a helper class used for handling formatted +/// output. It is the abstract base class of a templated derived class. +class format_object_base { +protected: + const char *Fmt; + virtual void home(); // Out of line virtual method. + + /// snprint - Call snprintf() for this object, on the given buffer and size. + virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; + +public: + format_object_base(const char *fmt) : Fmt(fmt) {} + virtual ~format_object_base() {} + + /// print - Format the object into the specified buffer. On success, this + /// returns the length of the formatted string. If the buffer is too small, + /// this returns a length to retry with, which will be larger than BufferSize. + unsigned print(char *Buffer, unsigned BufferSize) const { + assert(BufferSize && "Invalid buffer size!"); + + // Print the string, leaving room for the terminating null. + int N = snprint(Buffer, BufferSize); + + // VC++ and old GlibC return negative on overflow, just double the size. + if (N < 0) + return BufferSize*2; + + // Other impls yield number of bytes needed, not including the final '\0'. + if (unsigned(N) >= BufferSize) + return N+1; + + // Otherwise N is the length of output (not including the final '\0'). + return N; + } +}; + +/// format_object1 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object1 : public format_object_base { + T Val; +public: + format_object1(const char *fmt, const T &val) + : format_object_base(fmt), Val(val) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val); + } +}; + +/// format_object2 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object2 : public format_object_base { + T1 Val1; + T2 Val2; +public: + format_object2(const char *fmt, const T1 &val1, const T2 &val2) + : format_object_base(fmt), Val1(val1), Val2(val2) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); + } +}; + +/// format_object3 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object3 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; +public: + format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); + } +}; + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object1 format(const char *Fmt, const T &Val) { + return format_object1(Fmt, Val); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object2 format(const char *Fmt, const T1 &Val1, + const T2 &Val2) { + return format_object2(Fmt, Val1, Val2); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template + inline format_object3 format(const char *Fmt, const T1 &Val1, + const T2 &Val2, const T3 &Val3) { + return format_object3(Fmt, Val1, Val2, Val3); +} + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/FormattedStream.h b/final/include/llvm/Support/FormattedStream.h new file mode 100644 index 00000000000..58a18851687 --- /dev/null +++ b/final/include/llvm/Support/FormattedStream.h @@ -0,0 +1,154 @@ +//===-- llvm/Support/FormattedStream.h - Formatted streams ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains raw_ostream implementations for streams to do +// things like pretty-print comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H +#define LLVM_SUPPORT_FORMATTEDSTREAM_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm +{ + /// formatted_raw_ostream - Formatted raw_fd_ostream to handle + /// asm-specific constructs. + /// + class formatted_raw_ostream : public raw_ostream { + public: + /// DELETE_STREAM - Tell the destructor to delete the held stream. + /// + static const bool DELETE_STREAM = true; + + /// PRESERVE_STREAM - Tell the destructor to not delete the held + /// stream. + /// + static const bool PRESERVE_STREAM = false; + + private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; + + /// DeleteStream - Do we need to delete TheStream in the + /// destructor? + /// + bool DeleteStream; + + /// ColumnScanned - The current output column of the data that's + /// been flushed and the portion of the buffer that's been + /// scanned. The column scheme is zero-based. + /// + unsigned ColumnScanned; + + /// Scanned - This points to one past the last character in the + /// buffer we've scanned. + /// + const char *Scanned; + + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + virtual uint64_t current_pos() const { + // This has the same effect as calling TheStream.current_pos(), + // but that interface is private. + return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + } + + /// ComputeColumn - Examine the given output buffer and figure out which + /// column we end up in after output. + /// + void ComputeColumn(const char *Ptr, size_t size); + + public: + /// formatted_raw_ostream - Open the specified file for + /// writing. If an error occurs, information about the error is + /// put into ErrorInfo, and the stream should be immediately + /// destroyed; the string will be empty if no error occurred. + /// + /// As a side effect, the given Stream is set to be Unbuffered. + /// This is because formatted_raw_ostream does its own buffering, + /// so it doesn't want another layer of buffering to be happening + /// underneath it. + /// + formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + setStream(Stream, Delete); + } + explicit formatted_raw_ostream() + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + Scanned = 0; + } + + ~formatted_raw_ostream() { + flush(); + releaseStream(); + } + + void setStream(raw_ostream &Stream, bool Delete = false) { + releaseStream(); + + TheStream = &Stream; + DeleteStream = Delete; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = 0; + } + + /// PadToColumn - Align the output to some column number. If the current + /// column is already equal to or more than NewCol, PadToColumn inserts one + /// space. + /// + /// \param NewCol - The column to move to. + formatted_raw_ostream &PadToColumn(unsigned NewCol); + + private: + void releaseStream() { + // Delete the stream if needed. Otherwise, transfer the buffer + // settings from this raw_ostream back to the underlying stream. + if (!TheStream) + return; + if (DeleteStream) + delete TheStream; + else if (size_t BufferSize = GetBufferSize()) + TheStream->SetBufferSize(BufferSize); + else + TheStream->SetUnbuffered(); + } + }; + +/// fouts() - This returns a reference to a formatted_raw_ostream for +/// standard output. Use it like: fouts() << "foo" << "bar"; +formatted_raw_ostream &fouts(); + +/// ferrs() - This returns a reference to a formatted_raw_ostream for +/// standard error. Use it like: ferrs() << "foo" << "bar"; +formatted_raw_ostream &ferrs(); + +/// fdbgs() - This returns a reference to a formatted_raw_ostream for +/// debug output. Use it like: fdbgs() << "foo" << "bar"; +formatted_raw_ostream &fdbgs(); + +} // end llvm namespace + + +#endif diff --git a/final/include/llvm/Support/GetElementPtrTypeIterator.h b/final/include/llvm/Support/GetElementPtrTypeIterator.h new file mode 100644 index 00000000000..e5e7fc74095 --- /dev/null +++ b/final/include/llvm/Support/GetElementPtrTypeIterator.h @@ -0,0 +1,113 @@ +//===- llvm/Support/GetElementPtrTypeIterator.h -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an iterator for walking through the types indexed by +// getelementptr instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H +#define LLVM_SUPPORT_GETELEMENTPTRTYPE_H + +#include "llvm/User.h" +#include "llvm/DerivedTypes.h" + +namespace llvm { + template + class generic_gep_type_iterator + : public std::iterator { + typedef std::iterator super; + + ItTy OpIt; + const Type *CurTy; + generic_gep_type_iterator() {} + public: + + static generic_gep_type_iterator begin(const Type *Ty, ItTy It) { + generic_gep_type_iterator I; + I.CurTy = Ty; + I.OpIt = It; + return I; + } + static generic_gep_type_iterator end(ItTy It) { + generic_gep_type_iterator I; + I.CurTy = 0; + I.OpIt = It; + return I; + } + + bool operator==(const generic_gep_type_iterator& x) const { + return OpIt == x.OpIt; + } + bool operator!=(const generic_gep_type_iterator& x) const { + return !operator==(x); + } + + const Type *operator*() const { + return CurTy; + } + + const Type *getIndexedType() const { + const CompositeType *CT = cast(CurTy); + return CT->getTypeAtIndex(getOperand()); + } + + // This is a non-standard operator->. It allows you to call methods on the + // current type directly. + const Type *operator->() const { return operator*(); } + + Value *getOperand() const { return *OpIt; } + + generic_gep_type_iterator& operator++() { // Preincrement + if (const CompositeType *CT = dyn_cast(CurTy)) { + CurTy = CT->getTypeAtIndex(getOperand()); + } else { + CurTy = 0; + } + ++OpIt; + return *this; + } + + generic_gep_type_iterator operator++(int) { // Postincrement + generic_gep_type_iterator tmp = *this; ++*this; return tmp; + } + }; + + typedef generic_gep_type_iterator<> gep_type_iterator; + + inline gep_type_iterator gep_type_begin(const User *GEP) { + return gep_type_iterator::begin(GEP->getOperand(0)->getType(), + GEP->op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User *GEP) { + return gep_type_iterator::end(GEP->op_end()); + } + inline gep_type_iterator gep_type_begin(const User &GEP) { + return gep_type_iterator::begin(GEP.getOperand(0)->getType(), + GEP.op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User &GEP) { + return gep_type_iterator::end(GEP.op_end()); + } + + template + inline generic_gep_type_iterator + gep_type_begin(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator::begin(Op0, I); + } + + template + inline generic_gep_type_iterator + gep_type_end(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator::end(E); + } +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/GraphWriter.h b/final/include/llvm/Support/GraphWriter.h new file mode 100644 index 00000000000..a5165f44d54 --- /dev/null +++ b/final/include/llvm/Support/GraphWriter.h @@ -0,0 +1,357 @@ +//===-- llvm/Support/GraphWriter.h - Write graph to a .dot 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 defines a simple interface that can be used to print out generic +// LLVM graphs to ".dot" files. "dot" is a tool that is part of the AT&T +// graphviz package (http://www.research.att.com/sw/tools/graphviz/) which can +// be used to turn the files output by this interface into a variety of +// different graphics formats. +// +// Graphs do not need to implement any interface past what is already required +// by the GraphTraits template, but they can choose to implement specializations +// of the DOTGraphTraits template if they want to customize the graphs output in +// any way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GRAPHWRITER_H +#define LLVM_SUPPORT_GRAPHWRITER_H + +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/Path.h" +#include +#include + +namespace llvm { + +namespace DOT { // Private functions... + std::string EscapeString(const std::string &Label); +} + +namespace GraphProgram { + enum Name { + DOT, + FDP, + NEATO, + TWOPI, + CIRCO + }; +} + +void DisplayGraph(const sys::Path& Filename, bool wait=true, GraphProgram::Name program = GraphProgram::DOT); + +template +class GraphWriter { + raw_ostream &O; + const GraphType &G; + + typedef DOTGraphTraits DOTTraits; + typedef GraphTraits GTraits; + typedef typename GTraits::NodeType NodeType; + typedef typename GTraits::nodes_iterator node_iterator; + typedef typename GTraits::ChildIteratorType child_iterator; + DOTTraits DTraits; + + // Writes the edge labels of the node to O and returns true if there are any + // edge labels not equal to the empty string "". + bool getEdgeSourceLabels(raw_ostream &O, NodeType *Node) { + child_iterator EI = GTraits::child_begin(Node); + child_iterator EE = GTraits::child_end(Node); + bool hasEdgeSourceLabels = false; + + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { + std::string label = DTraits.getEdgeSourceLabel(Node, EI); + + if (label.empty()) + continue; + + hasEdgeSourceLabels = true; + + if (i) + O << "|"; + + O << "" << DOT::EscapeString(label); + } + + if (EI != EE && hasEdgeSourceLabels) + O << "|truncated..."; + + return hasEdgeSourceLabels; + } + +public: + GraphWriter(raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) { + DTraits = DOTTraits(SN); + } + + void writeGraph(const std::string &Title = "") { + // Output the header for the graph... + writeHeader(Title); + + // Emit all of the nodes in the graph... + writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits::addCustomGraphFeatures(G, *this); + + // Output the end of the graph + writeFooter(); + } + + void writeHeader(const std::string &Title) { + std::string GraphName = DTraits.getGraphName(G); + + if (!Title.empty()) + O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n"; + else if (!GraphName.empty()) + O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; + else + O << "digraph unnamed {\n"; + + if (DTraits.renderGraphFromBottomUp()) + O << "\trankdir=\"BT\";\n"; + + if (!Title.empty()) + O << "\tlabel=\"" << DOT::EscapeString(Title) << "\";\n"; + else if (!GraphName.empty()) + O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; + O << DTraits.getGraphProperties(G); + O << "\n"; + } + + void writeFooter() { + // Finish off the graph + O << "}\n"; + } + + void writeNodes() { + // Loop over the graph, printing it out... + for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); + I != E; ++I) + if (!isNodeHidden(*I)) + writeNode(*I); + } + + bool isNodeHidden(NodeType &Node) { + return isNodeHidden(&Node); + } + + bool isNodeHidden(NodeType *const *Node) { + return isNodeHidden(*Node); + } + + bool isNodeHidden(NodeType *Node) { + return DTraits.isNodeHidden(Node); + } + + void writeNode(NodeType& Node) { + writeNode(&Node); + } + + void writeNode(NodeType *const *Node) { + writeNode(*Node); + } + + void writeNode(NodeType *Node) { + std::string NodeAttributes = DTraits.getNodeAttributes(Node, G); + + O << "\tNode" << static_cast(Node) << " [shape=record,"; + if (!NodeAttributes.empty()) O << NodeAttributes << ","; + O << "label=\"{"; + + if (!DTraits.renderGraphFromBottomUp()) { + O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); + + // If we should include the address of the node in the label, do so now. + if (DTraits.hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + std::string edgeSourceLabels; + raw_string_ostream EdgeSourceLabels(edgeSourceLabels); + bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node); + + if (hasEdgeSourceLabels) { + if (!DTraits.renderGraphFromBottomUp()) O << "|"; + + O << "{" << EdgeSourceLabels.str() << "}"; + + if (DTraits.renderGraphFromBottomUp()) O << "|"; + } + + if (DTraits.renderGraphFromBottomUp()) { + O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); + + // If we should include the address of the node in the label, do so now. + if (DTraits.hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + if (DTraits.hasEdgeDestLabels()) { + O << "|{"; + + unsigned i = 0, e = DTraits.numEdgeDestLabels(Node); + for (; i != e && i != 64; ++i) { + if (i) O << "|"; + O << "" + << DOT::EscapeString(DTraits.getEdgeDestLabel(Node, i)); + } + + if (i != e) + O << "|truncated..."; + O << "}"; + } + + O << "}\"];\n"; // Finish printing the "node" line + + // Output all of the edges now + child_iterator EI = GTraits::child_begin(Node); + child_iterator EE = GTraits::child_end(Node); + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) + if (!DTraits.isNodeHidden(*EI)) + writeEdge(Node, i, EI); + for (; EI != EE; ++EI) + if (!DTraits.isNodeHidden(*EI)) + writeEdge(Node, 64, EI); + } + + void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { + if (NodeType *TargetNode = *EI) { + int DestPort = -1; + if (DTraits.edgeTargetsEdgeSource(Node, EI)) { + child_iterator TargetIt = DTraits.getEdgeTarget(Node, EI); + + // Figure out which edge this targets... + unsigned Offset = + (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); + DestPort = static_cast(Offset); + } + + if (DTraits.getEdgeSourceLabel(Node, EI).empty()) + edgeidx = -1; + + emitEdge(static_cast(Node), edgeidx, + static_cast(TargetNode), DestPort, + DTraits.getEdgeAttributes(Node, EI, G)); + } + } + + /// emitSimpleNode - Outputs a simple (non-record) node + void emitSimpleNode(const void *ID, const std::string &Attr, + const std::string &Label, unsigned NumEdgeSources = 0, + const std::vector *EdgeSourceLabels = 0) { + O << "\tNode" << ID << "[ "; + if (!Attr.empty()) + O << Attr << ","; + O << " label =\""; + if (NumEdgeSources) O << "{"; + O << DOT::EscapeString(Label); + if (NumEdgeSources) { + O << "|{"; + + for (unsigned i = 0; i != NumEdgeSources; ++i) { + if (i) O << "|"; + O << ""; + if (EdgeSourceLabels) O << DOT::EscapeString((*EdgeSourceLabels)[i]); + } + O << "}}"; + } + O << "\"];\n"; + } + + /// emitEdge - Output an edge from a simple node into the graph... + void emitEdge(const void *SrcNodeID, int SrcNodePort, + const void *DestNodeID, int DestNodePort, + const std::string &Attrs) { + if (SrcNodePort > 64) return; // Eminating from truncated part? + if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? + + O << "\tNode" << SrcNodeID; + if (SrcNodePort >= 0) + O << ":s" << SrcNodePort; + O << " -> Node" << DestNodeID; + if (DestNodePort >= 0 && DTraits.hasEdgeDestLabels()) + O << ":d" << DestNodePort; + + if (!Attrs.empty()) + O << "[" << Attrs << "]"; + O << ";\n"; + } + + /// getOStream - Get the raw output stream into the graph file. Useful to + /// write fancy things using addCustomGraphFeatures(). + raw_ostream &getOStream() { + return O; + } +}; + +template +raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, + bool ShortNames = false, + const std::string &Title = "") { + // Start the graph emission process... + GraphWriter W(O, G, ShortNames); + + // Emit the graph. + W.writeGraph(Title); + + return O; +} + +template +sys::Path WriteGraph(const GraphType &G, const std::string &Name, + bool ShortNames = false, const std::string &Title = "") { + std::string ErrMsg; + sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); + if (Filename.isEmpty()) { + errs() << "Error: " << ErrMsg << "\n"; + return Filename; + } + Filename.appendComponent(Name + ".dot"); + if (Filename.makeUnique(true,&ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + return sys::Path(); + } + + errs() << "Writing '" << Filename.str() << "'... "; + + std::string ErrorInfo; + raw_fd_ostream O(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) { + llvm::WriteGraph(O, G, ShortNames, Title); + errs() << " done. \n"; + } else { + errs() << "error opening file '" << Filename.str() << "' for writing!\n"; + Filename.clear(); + } + + return Filename; +} + +/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, +/// then cleanup. For use from the debugger. +/// +template +void ViewGraph(const GraphType &G, const std::string &Name, + bool ShortNames = false, const std::string &Title = "", + GraphProgram::Name Program = GraphProgram::DOT) { + sys::Path Filename = llvm::WriteGraph(G, Name, ShortNames, Title); + + if (Filename.isEmpty()) + return; + + DisplayGraph(Filename, true, Program); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Host.h b/final/include/llvm/Support/Host.h new file mode 100644 index 00000000000..f77d4c1182b --- /dev/null +++ b/final/include/llvm/Support/Host.h @@ -0,0 +1,66 @@ +//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for querying the nature of the host machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_HOST_H +#define LLVM_SYSTEM_HOST_H + +#include "llvm/ADT/StringMap.h" +#include + +namespace llvm { +namespace sys { + + inline bool isLittleEndianHost() { + union { + int i; + char c; + }; + i = 1; + return c; + } + + inline bool isBigEndianHost() { + return !isLittleEndianHost(); + } + + /// getHostTriple() - Return the target triple of the running + /// system. + /// + /// The target triple is a string in the format of: + /// CPU_TYPE-VENDOR-OPERATING_SYSTEM + /// or + /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM + std::string getHostTriple(); + + /// getHostCPUName - Get the LLVM name for the host CPU. The particular format + /// of the name is target dependent, and suitable for passing as -mcpu to the + /// target which matches the host. + /// + /// \return - The host CPU name, or empty if the CPU could not be determined. + std::string getHostCPUName(); + + /// getHostCPUFeatures - Get the LLVM names for the host CPU features. + /// The particular format of the names are target dependent, and suitable for + /// passing as -mattr to the target which matches the host. + /// + /// \param Features - A string mapping feature names to either + /// true (if enabled) or false (if disabled). This routine makes no guarantees + /// about exactly which features may appear in this map, except that they are + /// all valid LLVM feature names. + /// + /// \return - True on success. + bool getHostCPUFeatures(StringMap &Features); +} +} + +#endif diff --git a/final/include/llvm/Support/IRBuilder.h b/final/include/llvm/Support/IRBuilder.h new file mode 100644 index 00000000000..2394a59c09c --- /dev/null +++ b/final/include/llvm/Support/IRBuilder.h @@ -0,0 +1,1224 @@ +//===---- llvm/Support/IRBuilder.h - Builder for LLVM Instrs ----*- 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 IRBuilder class, which is used as a convenient way +// to create LLVM instructions with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_IRBUILDER_H +#define LLVM_SUPPORT_IRBUILDER_H + +#include "llvm/Instructions.h" +#include "llvm/BasicBlock.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ConstantFolder.h" + +namespace llvm { + class MDNode; + +/// IRBuilderDefaultInserter - This provides the default implementation of the +/// IRBuilder 'InsertHelper' method that is called whenever an instruction is +/// created by IRBuilder and needs to be inserted. By default, this inserts the +/// instruction at the insertion point. +template +class IRBuilderDefaultInserter { +protected: + void InsertHelper(Instruction *I, const Twine &Name, + BasicBlock *BB, BasicBlock::iterator InsertPt) const { + if (BB) BB->getInstList().insert(InsertPt, I); + if (preserveNames) + I->setName(Name); + } +}; + +/// IRBuilderBase - Common base class shared among various IRBuilders. +class IRBuilderBase { + DebugLoc CurDbgLocation; +protected: + BasicBlock *BB; + BasicBlock::iterator InsertPt; + LLVMContext &Context; +public: + + IRBuilderBase(LLVMContext &context) + : Context(context) { + ClearInsertionPoint(); + } + + //===--------------------------------------------------------------------===// + // Builder configuration methods + //===--------------------------------------------------------------------===// + + /// ClearInsertionPoint - Clear the insertion point: created instructions will + /// not be inserted into a block. + void ClearInsertionPoint() { + BB = 0; + } + + BasicBlock *GetInsertBlock() const { return BB; } + BasicBlock::iterator GetInsertPoint() const { return InsertPt; } + LLVMContext &getContext() const { return Context; } + + /// SetInsertPoint - This specifies that created instructions should be + /// appended to the end of the specified block. + void SetInsertPoint(BasicBlock *TheBB) { + BB = TheBB; + InsertPt = BB->end(); + } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted before the specified instruction. + void SetInsertPoint(Instruction *I) { + BB = I->getParent(); + InsertPt = I; + } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted at the specified point. + void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { + BB = TheBB; + InsertPt = IP; + } + + /// SetCurrentDebugLocation - Set location information used by debugging + /// information. + void SetCurrentDebugLocation(const DebugLoc &L) { + CurDbgLocation = L; + } + + /// getCurrentDebugLocation - Get location information used by debugging + /// information. + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } + + /// SetInstDebugLocation - If this builder has a current debug location, set + /// it on the specified instruction. + void SetInstDebugLocation(Instruction *I) const { + if (!CurDbgLocation.isUnknown()) + I->setDebugLoc(CurDbgLocation); + } + + /// InsertPoint - A saved insertion point. + class InsertPoint { + BasicBlock *Block; + BasicBlock::iterator Point; + + public: + /// Creates a new insertion point which doesn't point to anything. + InsertPoint() : Block(0) {} + + /// Creates a new insertion point at the given location. + InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) + : Block(InsertBlock), Point(InsertPoint) {} + + /// isSet - Returns true if this insert point is set. + bool isSet() const { return (Block != 0); } + + llvm::BasicBlock *getBlock() const { return Block; } + llvm::BasicBlock::iterator getPoint() const { return Point; } + }; + + /// saveIP - Returns the current insert point. + InsertPoint saveIP() const { + return InsertPoint(GetInsertBlock(), GetInsertPoint()); + } + + /// saveAndClearIP - Returns the current insert point, clearing it + /// in the process. + InsertPoint saveAndClearIP() { + InsertPoint IP(GetInsertBlock(), GetInsertPoint()); + ClearInsertionPoint(); + return IP; + } + + /// restoreIP - Sets the current insert point to a previously-saved + /// location. + void restoreIP(InsertPoint IP) { + if (IP.isSet()) + SetInsertPoint(IP.getBlock(), IP.getPoint()); + else + ClearInsertionPoint(); + } + + //===--------------------------------------------------------------------===// + // Miscellaneous creation methods. + //===--------------------------------------------------------------------===// + + /// CreateGlobalString - Make a new global variable with an initializer that + /// has array of i8 type filled in with the nul terminated string value + /// specified. If Name is specified, it is the name of the global variable + /// created. + Value *CreateGlobalString(const char *Str = "", const Twine &Name = ""); + + /// getInt1 - Get a constant value representing either true or false. + ConstantInt *getInt1(bool V) { + return ConstantInt::get(getInt1Ty(), V); + } + + /// getTrue - Get the constant value for i1 true. + ConstantInt *getTrue() { + return ConstantInt::getTrue(Context); + } + + /// getFalse - Get the constant value for i1 false. + ConstantInt *getFalse() { + return ConstantInt::getFalse(Context); + } + + /// getInt8 - Get a constant 8-bit value. + ConstantInt *getInt8(uint8_t C) { + return ConstantInt::get(getInt8Ty(), C); + } + + /// getInt16 - Get a constant 16-bit value. + ConstantInt *getInt16(uint16_t C) { + return ConstantInt::get(getInt16Ty(), C); + } + + /// getInt32 - Get a constant 32-bit value. + ConstantInt *getInt32(uint32_t C) { + return ConstantInt::get(getInt32Ty(), C); + } + + /// getInt64 - Get a constant 64-bit value. + ConstantInt *getInt64(uint64_t C) { + return ConstantInt::get(getInt64Ty(), C); + } + + //===--------------------------------------------------------------------===// + // Type creation methods + //===--------------------------------------------------------------------===// + + /// getInt1Ty - Fetch the type representing a single bit + const IntegerType *getInt1Ty() { + return Type::getInt1Ty(Context); + } + + /// getInt8Ty - Fetch the type representing an 8-bit integer. + const IntegerType *getInt8Ty() { + return Type::getInt8Ty(Context); + } + + /// getInt16Ty - Fetch the type representing a 16-bit integer. + const IntegerType *getInt16Ty() { + return Type::getInt16Ty(Context); + } + + /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. + const IntegerType *getInt32Ty() { + return Type::getInt32Ty(Context); + } + + /// getInt64Ty - Fetch the type representing a 64-bit integer. + const IntegerType *getInt64Ty() { + return Type::getInt64Ty(Context); + } + + /// getFloatTy - Fetch the type representing a 32-bit floating point value. + const Type *getFloatTy() { + return Type::getFloatTy(Context); + } + + /// getDoubleTy - Fetch the type representing a 64-bit floating point value. + const Type *getDoubleTy() { + return Type::getDoubleTy(Context); + } + + /// getVoidTy - Fetch the type representing void. + const Type *getVoidTy() { + return Type::getVoidTy(Context); + } + + const PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { + return Type::getInt8PtrTy(Context, AddrSpace); + } + + /// getCurrentFunctionReturnType - Get the return type of the current function + /// that we're emitting into. + const Type *getCurrentFunctionReturnType() const; + + /// CreateMemSet - Create and insert a memset to the specified pointer and the + /// specified value. If the pointer isn't an i8*, it will be converted. If a + /// TBAA tag is specified, it will be added to the instruction. + CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemMove - Create and insert a memmove between the specified + /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA + /// tag is specified, it will be added to the instruction. + CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); +private: + Value *getCastedInt8PtrValue(Value *Ptr); +}; + +/// IRBuilder - This provides a uniform API for creating instructions and +/// inserting them into a basic block: either at the end of a BasicBlock, or +/// at a specific iterator location in a block. +/// +/// Note that the builder does not expose the full generality of LLVM +/// instructions. For access to extra instruction properties, use the mutators +/// (e.g. setVolatile) on the instructions after they have been created. +/// The first template argument handles whether or not to preserve names in the +/// final instruction output. This defaults to on. The second template argument +/// specifies a class to use for creating constants. This defaults to creating +/// minimally folded constants. The fourth template argument allows clients to +/// specify custom insertion hooks that are called on every newly created +/// insertion. +template > +class IRBuilder : public IRBuilderBase, public Inserter { + T Folder; +public: + IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) + : IRBuilderBase(C), Inserter(I), Folder(F) { + } + + explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder(C) { + } + + explicit IRBuilder(BasicBlock *TheBB, const T &F) + : IRBuilderBase(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(BasicBlock *TheBB) + : IRBuilderBase(TheBB->getContext()), Folder(Context) { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(Instruction *IP) + : IRBuilderBase(IP->getContext()), Folder(Context) { + SetInsertPoint(IP); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) + : IRBuilderBase(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB, IP); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) + : IRBuilderBase(TheBB->getContext()), Folder(Context) { + SetInsertPoint(TheBB, IP); + } + + /// getFolder - Get the constant folder being used. + const T &getFolder() { return Folder; } + + /// isNamePreserving - Return true if this builder is configured to actually + /// add the requested names to IR created through it. + bool isNamePreserving() const { return preserveNames; } + + /// Insert - Insert and return the specified instruction. + template + InstTy *Insert(InstTy *I, const Twine &Name = "") const { + this->InsertHelper(I, Name, BB, InsertPt); + if (!getCurrentDebugLocation().isUnknown()) + this->SetInstDebugLocation(I); + return I; + } + + /// Insert - No-op overload to handle constants. + Constant *Insert(Constant *C, const Twine& = "") const { + return C; + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Terminators + //===--------------------------------------------------------------------===// + + /// CreateRetVoid - Create a 'ret void' instruction. + ReturnInst *CreateRetVoid() { + return Insert(ReturnInst::Create(Context)); + } + + /// @verbatim + /// CreateRet - Create a 'ret ' instruction. + /// @endverbatim + ReturnInst *CreateRet(Value *V) { + return Insert(ReturnInst::Create(Context, V)); + } + + /// CreateAggregateRet - Create a sequence of N insertvalue instructions, + /// with one Value from the retVals array each, that build a aggregate + /// return value one value at a time, and a ret instruction to return + /// the resulting aggregate value. This is a convenience function for + /// code that uses aggregate return values as a vehicle for having + /// multiple return values. + /// + ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { + Value *V = UndefValue::get(getCurrentFunctionReturnType()); + for (unsigned i = 0; i != N; ++i) + V = CreateInsertValue(V, retVals[i], i, "mrv"); + return Insert(ReturnInst::Create(Context, V)); + } + + /// CreateBr - Create an unconditional 'br label X' instruction. + BranchInst *CreateBr(BasicBlock *Dest) { + return Insert(BranchInst::Create(Dest)); + } + + /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' + /// instruction. + BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False) { + return Insert(BranchInst::Create(True, False, Cond)); + } + + /// CreateSwitch - Create a switch instruction with the specified value, + /// default dest, and with a hint for the number of cases that will be added + /// (for efficient allocation). + SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10) { + return Insert(SwitchInst::Create(V, Dest, NumCases)); + } + + /// CreateIndirectBr - Create an indirect branch instruction with the + /// specified address operand, with an optional hint for the number of + /// destinations that will be added (for efficient allocation). + IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { + return Insert(IndirectBrInst::Create(Addr, NumDests)); + } + + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, const Twine &Name = "") { + Value *Args[] = { 0 }; + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args, + Args), Name); + } + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, Value *Arg1, + const Twine &Name = "") { + Value *Args[] = { Arg1 }; + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args, + Args+1), Name); + } + InvokeInst *CreateInvoke3(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, Value *Arg1, + Value *Arg2, Value *Arg3, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3 }; + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args, + Args+3), Name); + } + /// CreateInvoke - Create an invoke instruction. + template + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &Name = "") { + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, + ArgBegin, ArgEnd), Name); + } + + UnwindInst *CreateUnwind() { + return Insert(new UnwindInst(Context)); + } + + UnreachableInst *CreateUnreachable() { + return Insert(new UnreachableInst(Context)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Binary Operators + //===--------------------------------------------------------------------===// +private: + BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, + Value *LHS, Value *RHS, + const Twine &Name, + bool HasNUW, bool HasNSW) { + BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } +public: + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateAdd(LHS, RHS, Name, false, true); + } + Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateAdd(LHS, RHS, Name, true, false); + } + Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFAdd(LC, RC), Name); + return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name); + } + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateSub(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSub(LHS, RHS, Name, false, true); + } + Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSub(LHS, RHS, Name, true, false); + } + Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFSub(LC, RC), Name); + return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name); + } + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateMul(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateMul(LHS, RHS, Name, false, true); + } + Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateMul(LHS, RHS, Name, true, false); + } + Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFMul(LC, RC), Name); + return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name); + } + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); + } + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateUDiv(LHS, RHS, Name, true); + } + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); + } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSDiv(LHS, RHS, Name, true); + } + Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFDiv(LC, RC), Name); + return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name); + } + Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateURem(LC, RC), Name); + return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); + } + Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateSRem(LC, RC), Name); + return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); + } + Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFRem(LC, RC), Name); + return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name); + } + + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, + HasNUW, HasNSW); + } + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); + } + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); + } + + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateLShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); + } + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateAShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); + } + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); + } + + Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast(RHS)) { + if (isa(RC) && cast(RC)->isAllOnesValue()) + return LHS; // LHS & -1 -> LHS + if (Constant *LC = dyn_cast(LHS)) + return Insert(Folder.CreateAnd(LC, RC), Name); + } + return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); + } + Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *RC = dyn_cast(RHS)) { + if (RC->isNullValue()) + return LHS; // LHS | 0 -> LHS + if (Constant *LC = dyn_cast(LHS)) + return Insert(Folder.CreateOr(LC, RC), Name); + } + return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); + } + Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateXor(LC, RC), Name); + return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); + } + Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); + } + + Value *CreateBinOp(Instruction::BinaryOps Opc, + Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); + return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + } + + Value *CreateNeg(Value *V, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); + BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Value *CreateNSWNeg(Value *V, const Twine &Name = "") { + return CreateNeg(V, Name, false, true); + } + Value *CreateNUWNeg(Value *V, const Twine &Name = "") { + return CreateNeg(V, Name, true, false); + } + Value *CreateFNeg(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateFNeg(VC), Name); + return Insert(BinaryOperator::CreateFNeg(V), Name); + } + Value *CreateNot(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateNot(VC), Name); + return Insert(BinaryOperator::CreateNot(V), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Memory Instructions + //===--------------------------------------------------------------------===// + + AllocaInst *CreateAlloca(const Type *Ty, Value *ArraySize = 0, + const Twine &Name = "") { + return Insert(new AllocaInst(Ty, ArraySize), Name); + } + // Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + // converting the string to 'bool' for the isVolatile parameter. + LoadInst *CreateLoad(Value *Ptr, const char *Name) { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ptr), Name); + } + LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { + return Insert(new LoadInst(Ptr, 0, isVolatile), Name); + } + StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { + return Insert(new StoreInst(Val, Ptr, isVolatile)); + } + template + Value *CreateGEP(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) { + // Every index must be constant. + RandomAccessIterator i; + for (i = IdxBegin; i < IdxEnd; ++i) + if (!isa(*i)) + break; + if (i == IdxEnd) + return Insert(Folder.CreateGetElementPtr(PC, &IdxBegin[0], + IdxEnd - IdxBegin), + Name); + } + return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); + } + template + Value *CreateInBoundsGEP(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) { + // Every index must be constant. + RandomAccessIterator i; + for (i = IdxBegin; i < IdxEnd; ++i) + if (!isa(*i)) + break; + if (i == IdxEnd) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin), + Name); + } + return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), + Name); + } + Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) + if (Constant *IC = dyn_cast(Idx)) + return Insert(Folder.CreateGetElementPtr(PC, &IC, 1), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + } + Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + if (Constant *PC = dyn_cast(Ptr)) + if (Constant *IC = dyn_cast(Idx)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &IC, 1), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + } + Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); + + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt32Ty(Context), Idx0), + ConstantInt::get(Type::getInt32Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); + + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, + const Twine &Name = "") { + Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); + } + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); + + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, + const Twine &Name = "") { + Value *Idxs[] = { + ConstantInt::get(Type::getInt64Ty(Context), Idx0), + ConstantInt::get(Type::getInt64Ty(Context), Idx1) + }; + + if (Constant *PC = dyn_cast(Ptr)) + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); + + return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); + } + Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + } + + /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer + /// with "i8*" type instead of a pointer to array of i8. + Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { + Value *gv = CreateGlobalString(Str, Name); + Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Value *Args[] = { zero, zero }; + return CreateInBoundsGEP(gv, Args, Args+2, Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Value *CreateTrunc(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::Trunc, V, DestTy, Name); + } + Value *CreateZExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::ZExt, V, DestTy, Name); + } + Value *CreateSExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::SExt, V, DestTy, Name); + } + Value *CreateFPToUI(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToUI, V, DestTy, Name); + } + Value *CreateFPToSI(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::FPToSI, V, DestTy, Name); + } + Value *CreateUIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::UIToFP, V, DestTy, Name); + } + Value *CreateSIToFP(Value *V, const Type *DestTy, const Twine &Name = ""){ + return CreateCast(Instruction::SIToFP, V, DestTy, Name); + } + Value *CreateFPTrunc(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::FPTrunc, V, DestTy, Name); + } + Value *CreateFPExt(Value *V, const Type *DestTy, const Twine &Name = "") { + return CreateCast(Instruction::FPExt, V, DestTy, Name); + } + Value *CreatePtrToInt(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::PtrToInt, V, DestTy, Name); + } + Value *CreateIntToPtr(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::IntToPtr, V, DestTy, Name); + } + Value *CreateBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::BitCast, V, DestTy, Name); + } + Value *CreateZExtOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); + } + Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); + } + Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); + return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); + } + Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateCast(Op, VC, DestTy), Name); + return Insert(CastInst::Create(Op, V, DestTy), Name); + } + Value *CreatePointerCast(Value *V, const Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreatePointerCast(VC, DestTy), Name); + return Insert(CastInst::CreatePointerCast(V, DestTy), Name); + } + Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); + return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); + } +private: + // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time + // error, instead of converting the string to bool for the isSigned parameter. + Value *CreateIntCast(Value *, const Type *, const char *); // DO NOT IMPLEMENT +public: + Value *CreateFPCast(Value *V, const Type *DestTy, const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (Constant *VC = dyn_cast(V)) + return Insert(Folder.CreateFPCast(VC, DestTy), Name); + return Insert(CastInst::CreateFPCast(V, DestTy), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Compare Instructions + //===--------------------------------------------------------------------===// + + Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); + } + Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); + } + Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); + } + Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); + } + Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); + } + Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); + } + Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); + } + Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); + } + Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); + } + Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); + } + + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + } + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + } + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + } + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + } + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + } + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + } + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + } + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + } + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + } + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + } + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + } + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + } + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + } + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + } + + Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateICmp(P, LC, RC), Name); + return Insert(new ICmpInst(P, LHS, RHS), Name); + } + Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, + const Twine &Name = "") { + if (Constant *LC = dyn_cast(LHS)) + if (Constant *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFCmp(P, LC, RC), Name); + return Insert(new FCmpInst(P, LHS, RHS), Name); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Other Instructions + //===--------------------------------------------------------------------===// + + PHINode *CreatePHI(const Type *Ty, const Twine &Name = "") { + return Insert(PHINode::Create(Ty), Name); + } + + CallInst *CreateCall(Value *Callee, const Twine &Name = "") { + return Insert(CallInst::Create(Callee), Name); + } + CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { + return Insert(CallInst::Create(Callee, Arg), Name); + } + CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2 }; + return Insert(CallInst::Create(Callee, Args, Args+2), Name); + } + CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3 }; + return Insert(CallInst::Create(Callee, Args, Args+3), Name); + } + CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + return Insert(CallInst::Create(Callee, Args, Args+4), Name); + } + CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, + Value *Arg4, Value *Arg5, const Twine &Name = "") { + Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; + return Insert(CallInst::Create(Callee, Args, Args+5), Name); + } + + template + CallInst *CreateCall(Value *Callee, RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &Name = "") { + return Insert(CallInst::Create(Callee, ArgBegin, ArgEnd), Name); + } + + Value *CreateSelect(Value *C, Value *True, Value *False, + const Twine &Name = "") { + if (Constant *CC = dyn_cast(C)) + if (Constant *TC = dyn_cast(True)) + if (Constant *FC = dyn_cast(False)) + return Insert(Folder.CreateSelect(CC, TC, FC), Name); + return Insert(SelectInst::Create(C, True, False), Name); + } + + VAArgInst *CreateVAArg(Value *List, const Type *Ty, const Twine &Name = "") { + return Insert(new VAArgInst(List, Ty), Name); + } + + Value *CreateExtractElement(Value *Vec, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast(Vec)) + if (Constant *IC = dyn_cast(Idx)) + return Insert(Folder.CreateExtractElement(VC, IC), Name); + return Insert(ExtractElementInst::Create(Vec, Idx), Name); + } + + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, + const Twine &Name = "") { + if (Constant *VC = dyn_cast(Vec)) + if (Constant *NC = dyn_cast(NewElt)) + if (Constant *IC = dyn_cast(Idx)) + return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); + return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); + } + + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, + const Twine &Name = "") { + if (Constant *V1C = dyn_cast(V1)) + if (Constant *V2C = dyn_cast(V2)) + if (Constant *MC = dyn_cast(Mask)) + return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); + return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); + } + + Value *CreateExtractValue(Value *Agg, unsigned Idx, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + return Insert(Folder.CreateExtractValue(AggC, &Idx, 1), Name); + return Insert(ExtractValueInst::Create(Agg, Idx), Name); + } + + template + Value *CreateExtractValue(Value *Agg, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + return Insert(Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd-IdxBegin), + Name); + return Insert(ExtractValueInst::Create(Agg, IdxBegin, IdxEnd), Name); + } + + Value *CreateInsertValue(Value *Agg, Value *Val, unsigned Idx, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + if (Constant *ValC = dyn_cast(Val)) + return Insert(Folder.CreateInsertValue(AggC, ValC, &Idx, 1), Name); + return Insert(InsertValueInst::Create(Agg, Val, Idx), Name); + } + + template + Value *CreateInsertValue(Value *Agg, Value *Val, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { + if (Constant *AggC = dyn_cast(Agg)) + if (Constant *ValC = dyn_cast(Val)) + return Insert(Folder.CreateInsertValue(AggC, ValC, IdxBegin, + IdxEnd - IdxBegin), + Name); + return Insert(InsertValueInst::Create(Agg, Val, IdxBegin, IdxEnd), Name); + } + + //===--------------------------------------------------------------------===// + // Utility creation methods + //===--------------------------------------------------------------------===// + + /// CreateIsNull - Return an i1 value testing if \arg Arg is null. + Value *CreateIsNull(Value *Arg, const Twine &Name = "") { + return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// CreateIsNotNull - Return an i1 value testing if \arg Arg is not null. + Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { + return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), + Name); + } + + /// CreatePtrDiff - Return the i64 difference between two pointer values, + /// dividing out the size of the pointed-to objects. This is intended to + /// implement C-style pointer subtraction. As such, the pointers must be + /// appropriately aligned for their element types and pointing into the + /// same object. + Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { + assert(LHS->getType() == RHS->getType() && + "Pointer subtraction operand types must match!"); + const PointerType *ArgType = cast(LHS->getType()); + Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); + Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); + Value *Difference = CreateSub(LHS_int, RHS_int); + return CreateExactSDiv(Difference, + ConstantExpr::getSizeOf(ArgType->getElementType()), + Name); + } +}; + +} + +#endif diff --git a/final/include/llvm/Support/IRReader.h b/final/include/llvm/Support/IRReader.h new file mode 100644 index 00000000000..292c001e09f --- /dev/null +++ b/final/include/llvm/Support/IRReader.h @@ -0,0 +1,110 @@ +//===---- llvm/Support/IRReader.h - Reader for LLVM IR files ----*- 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 functions for reading LLVM IR. They support both +// Bitcode and Assembly, automatically detecting the input format. +// +// These functions must be defined in a header file in order to avoid +// library dependencies, since they reference both Bitcode and Assembly +// functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_IRREADER_H +#define LLVM_SUPPORT_IRREADER_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Assembly/Parser.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/system_error.h" + +namespace llvm { + + /// If the given MemoryBuffer holds a bitcode image, return a Module for it + /// which does lazy deserialization of function bodies. Otherwise, attempt to + /// parse it as LLVM Assembly and return a fully populated Module. This + /// function *always* takes ownership of the given MemoryBuffer. + inline Module *getLazyIRModule(MemoryBuffer *Buffer, + SMDiagnostic &Err, + LLVMContext &Context) { + if (isBitcode((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd())) { + std::string ErrMsg; + Module *M = getLazyBitcodeModule(Buffer, Context, &ErrMsg); + if (M == 0) { + Err = SMDiagnostic(Buffer->getBufferIdentifier(), ErrMsg); + // ParseBitcodeFile does not take ownership of the Buffer in the + // case of an error. + delete Buffer; + } + return M; + } + + return ParseAssembly(Buffer, 0, Err, Context); + } + + /// If the given file holds a bitcode image, return a Module + /// for it which does lazy deserialization of function bodies. Otherwise, + /// attempt to parse it as LLVM Assembly and return a fully populated + /// Module. + inline Module *getLazyIRFileModule(const std::string &Filename, + SMDiagnostic &Err, + LLVMContext &Context) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); + return 0; + } + + return getLazyIRModule(File.take(), Err, Context); + } + + /// If the given MemoryBuffer holds a bitcode image, return a Module + /// for it. Otherwise, attempt to parse it as LLVM Assembly and return + /// a Module for it. This function *always* takes ownership of the given + /// MemoryBuffer. + inline Module *ParseIR(MemoryBuffer *Buffer, + SMDiagnostic &Err, + LLVMContext &Context) { + if (isBitcode((const unsigned char *)Buffer->getBufferStart(), + (const unsigned char *)Buffer->getBufferEnd())) { + std::string ErrMsg; + Module *M = ParseBitcodeFile(Buffer, Context, &ErrMsg); + if (M == 0) + Err = SMDiagnostic(Buffer->getBufferIdentifier(), ErrMsg); + // ParseBitcodeFile does not take ownership of the Buffer. + delete Buffer; + return M; + } + + return ParseAssembly(Buffer, 0, Err, Context); + } + + /// If the given file holds a bitcode image, return a Module for it. + /// Otherwise, attempt to parse it as LLVM Assembly and return a Module + /// for it. + inline Module *ParseIRFile(const std::string &Filename, + SMDiagnostic &Err, + LLVMContext &Context) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); + return 0; + } + + return ParseIR(File.take(), Err, Context); + } + +} + +#endif diff --git a/final/include/llvm/Support/IncludeFile.h b/final/include/llvm/Support/IncludeFile.h new file mode 100644 index 00000000000..a9319725d47 --- /dev/null +++ b/final/include/llvm/Support/IncludeFile.h @@ -0,0 +1,79 @@ +//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- 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 FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR +// macros. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_INCLUDEFILE_H +#define LLVM_SYSTEM_INCLUDEFILE_H + +/// This macro is the public interface that IncludeFile.h exports. This gives +/// us the option to implement the "link the definition" capability in any +/// manner that we choose. All header files that depend on a specific .cpp +/// file being linked at run time should use this macro instead of the +/// IncludeFile class directly. +/// +/// For example, foo.h would use:
+/// FORCE_DEFINING_FILE_TO_BE_LINKED(foo)
+/// +/// And, foo.cp would use:
+/// DEFINING_FILE_FOR(foo)
+#ifdef __GNUC__ +// If the `used' attribute is available, use it to create a variable +// with an initializer that will force the linking of the defining file. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + __attribute__((used)) static const char *const name ## LinkObj = \ + &name ## LinkVar; \ + } +#else +// Otherwise use a constructor call. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ + } +#endif + +/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should +/// be used in a .cpp file to define the name referenced in a header file that +/// will cause linkage of the .cpp file. It should only be used at extern level. +#define DEFINING_FILE_FOR(name) \ + namespace llvm { const char name ## LinkVar = 0; } + +namespace llvm { + +/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation +/// of compilation units we need. This is commonly an issue with the various +/// Passes but also occurs elsewhere in LLVM. We like to use .a files because +/// they link faster and provide the smallest executables. However, sometimes +/// those executables are too small, if the program doesn't reference something +/// that might be needed, especially by a loaded share object. This little class +/// helps to resolve that problem. The basic strategy is to use this class in +/// a header file and pass the address of a variable to the constructor. If the +/// variable is defined in the header file's corresponding .cpp file then all +/// tools/libraries that \#include the header file will require the .cpp as +/// well. +/// For example:
+/// extern int LinkMyCodeStub;
+/// static IncludeFile LinkMyModule(&LinkMyCodeStub);
+/// @brief Class to ensure linking of corresponding object file. +struct IncludeFile { + explicit IncludeFile(const void *); +}; + +} + +#endif diff --git a/final/include/llvm/Support/InstIterator.h b/final/include/llvm/Support/InstIterator.h new file mode 100644 index 00000000000..7d3f8835098 --- /dev/null +++ b/final/include/llvm/Support/InstIterator.h @@ -0,0 +1,147 @@ +//===- llvm/Support/InstIterator.h - Classes for inst iteration -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions of two iterators for iterating over the +// instructions in a function. This is effectively a wrapper around a two level +// iterator that can probably be genericized later. +// +// Note that this iterator gets invalidated any time that basic blocks or +// instructions are moved around. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_INSTITERATOR_H +#define LLVM_SUPPORT_INSTITERATOR_H + +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" + +namespace llvm { + +// This class implements inst_begin() & inst_end() for +// inst_iterator and const_inst_iterator's. +// +template +class InstIterator { + typedef _BB_t BBty; + typedef _BB_i_t BBIty; + typedef _BI_t BIty; + typedef _II_t IIty; + _BB_t *BBs; // BasicBlocksType + _BB_i_t BB; // BasicBlocksType::iterator + _BI_t BI; // BasicBlock::iterator +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef IIty value_type; + typedef signed difference_type; + typedef IIty* pointer; + typedef IIty& reference; + + // Default constructor + InstIterator() {} + + // Copy constructor... + template + InstIterator(const InstIterator &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template + InstIterator(InstIterator &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template InstIterator(M &m) + : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor + if (BB != BBs->end()) { + BI = BB->begin(); + advanceToNextBB(); + } + } + + template InstIterator(M &m, bool) + : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor + } + + // Accessors to get at the underlying iterators... + inline BBIty &getBasicBlockIterator() { return BB; } + inline BIty &getInstructionIterator() { return BI; } + + inline reference operator*() const { return *BI; } + inline pointer operator->() const { return &operator*(); } + + inline bool operator==(const InstIterator &y) const { + return BB == y.BB && (BB == BBs->end() || BI == y.BI); + } + inline bool operator!=(const InstIterator& y) const { + return !operator==(y); + } + + InstIterator& operator++() { + ++BI; + advanceToNextBB(); + return *this; + } + inline InstIterator operator++(int) { + InstIterator tmp = *this; ++*this; return tmp; + } + + InstIterator& operator--() { + while (BB == BBs->end() || BI == BB->begin()) { + --BB; + BI = BB->end(); + } + --BI; + return *this; + } + inline InstIterator operator--(int) { + InstIterator tmp = *this; --*this; return tmp; + } + + inline bool atEnd() const { return BB == BBs->end(); } + +private: + inline void advanceToNextBB() { + // The only way that the II could be broken is if it is now pointing to + // the end() of the current BasicBlock and there are successor BBs. + while (BI == BB->end()) { + ++BB; + if (BB == BBs->end()) break; + BI = BB->begin(); + } + } +}; + + +typedef InstIterator, + Function::iterator, BasicBlock::iterator, + Instruction> inst_iterator; +typedef InstIterator, + Function::const_iterator, + BasicBlock::const_iterator, + const Instruction> const_inst_iterator; + +inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } +inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline const_inst_iterator inst_begin(const Function *F) { + return const_inst_iterator(*F); +} +inline const_inst_iterator inst_end(const Function *F) { + return const_inst_iterator(*F, true); +} +inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } +inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline const_inst_iterator inst_begin(const Function &F) { + return const_inst_iterator(F); +} +inline const_inst_iterator inst_end(const Function &F) { + return const_inst_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/InstVisitor.h b/final/include/llvm/Support/InstVisitor.h new file mode 100644 index 00000000000..b2e5d58b7c3 --- /dev/null +++ b/final/include/llvm/Support/InstVisitor.h @@ -0,0 +1,217 @@ +//===- llvm/Support/InstVisitor.h - Define instruction visitors -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_SUPPORT_INSTVISITOR_H +#define LLVM_SUPPORT_INSTVISITOR_H + +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +// We operate on opaque instruction classes, so forward declare all instruction +// types now... +// +#define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; +#include "llvm/Instruction.def" + +#define DELEGATE(CLASS_TO_VISIT) \ + return static_cast(this)-> \ + visit##CLASS_TO_VISIT(static_cast(I)) + + +/// @brief Base class for instruction visitors +/// +/// Instruction visitors are used when you want to perform different actions +/// for different kinds of instructions without having to use lots of casts +/// and a big switch statement (in your code, that is). +/// +/// To define your own visitor, inherit from this class, specifying your +/// new type for the 'SubClass' template parameter, and "override" visitXXX +/// functions in your class. I say "override" because this class is defined +/// in terms of statically resolved overloading, not virtual functions. +/// +/// For example, here is a visitor that counts the number of malloc +/// instructions processed: +/// +/// /// Declare the class. Note that we derive from InstVisitor instantiated +/// /// with _our new subclasses_ type. +/// /// +/// struct CountAllocaVisitor : public InstVisitor { +/// unsigned Count; +/// CountAllocaVisitor() : Count(0) {} +/// +/// void visitAllocaInst(AllocaInst &AI) { ++Count; } +/// }; +/// +/// And this class would be used like this: +/// CountAllocaVisitor CAV; +/// CAV.visit(function); +/// NumAllocas = CAV.Count; +/// +/// The defined has 'visit' methods for Instruction, and also for BasicBlock, +/// Function, and Module, which recursively process all contained instructions. +/// +/// Note that if you don't implement visitXXX for some instruction type, +/// the visitXXX method for instruction superclass will be invoked. So +/// if instructions are added in the future, they will be automatically +/// supported, if you handle one of their superclasses. +/// +/// The optional second template argument specifies the type that instruction +/// visitation functions should return. If you specify this, you *MUST* provide +/// an implementation of visitInstruction though!. +/// +/// Note that this class is specifically designed as a template to avoid +/// virtual function call overhead. Defining and using an InstVisitor is just +/// as efficient as having your own switch statement over the instruction +/// opcode. +template +class InstVisitor { + //===--------------------------------------------------------------------===// + // Interface code - This is the public interface of the InstVisitor that you + // use to visit instructions... + // + +public: + // Generic visit method - Allow visitation to all instructions in a range + template + void visit(Iterator Start, Iterator End) { + while (Start != End) + static_cast(this)->visit(*Start++); + } + + // Define visitors for functions and basic blocks... + // + void visit(Module &M) { + static_cast(this)->visitModule(M); + visit(M.begin(), M.end()); + } + void visit(Function &F) { + static_cast(this)->visitFunction(F); + visit(F.begin(), F.end()); + } + void visit(BasicBlock &BB) { + static_cast(this)->visitBasicBlock(BB); + visit(BB.begin(), BB.end()); + } + + // Forwarding functions so that the user can visit with pointers AND refs. + void visit(Module *M) { visit(*M); } + void visit(Function *F) { visit(*F); } + void visit(BasicBlock *BB) { visit(*BB); } + RetTy visit(Instruction *I) { return visit(*I); } + + // visit - Finally, code to visit an instruction... + // + RetTy visit(Instruction &I) { + switch (I.getOpcode()) { + default: llvm_unreachable("Unknown instruction type encountered!"); + // Build the switch statement using the Instruction.def file... +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: return \ + static_cast(this)-> \ + visit##OPCODE(static_cast(I)); +#include "llvm/Instruction.def" + } + } + + //===--------------------------------------------------------------------===// + // Visitation functions... these functions provide default fallbacks in case + // the user does not specify what to do for a particular instruction type. + // The default behavior is to generalize the instruction type to its subtype + // and try visiting the subtype. All of this should be inlined perfectly, + // because there are no virtual functions to get in the way. + // + + // When visiting a module, function or basic block directly, these methods get + // called to indicate when transitioning into a new unit. + // + void visitModule (Module &M) {} + void visitFunction (Function &F) {} + void visitBasicBlock(BasicBlock &BB) {} + + // Define instruction specific visitor functions that can be overridden to + // handle SPECIFIC instructions. These functions automatically define + // visitMul to proxy to visitBinaryOperator for instance in case the user does + // not need this generality. + // + // The one problem case we have to handle here though is that the PHINode + // class and opcode name are the exact same. Because of this, we cannot + // define visitPHINode (the inst version) to forward to visitPHINode (the + // generic version) without multiply defined symbols and recursion. To handle + // this, we do not autoexpand "Other" instructions, we do it manually. + // +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); } +#include "llvm/Instruction.def" + + // Specific Instruction type classes... note that all of the casts are + // necessary because we use the instruction classes as opaque types... + // + RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);} + RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} + RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} + RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} + RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} + RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(Instruction); } + RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } + RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } + RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction); } + RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } + RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst); } + RetTy visitZExtInst(ZExtInst &I) { DELEGATE(CastInst); } + RetTy visitSExtInst(SExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPTruncInst(FPTruncInst &I) { DELEGATE(CastInst); } + RetTy visitFPExtInst(FPExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPToUIInst(FPToUIInst &I) { DELEGATE(CastInst); } + RetTy visitFPToSIInst(FPToSIInst &I) { DELEGATE(CastInst); } + RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst); } + RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst); } + RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst); } + RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction); } + RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); } + RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(Instruction); } + RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} + RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); } + RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } + RetTy visitExtractValueInst(ExtractValueInst &I) { DELEGATE(Instruction);} + RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } + + // Next level propagators: If the user does not overload a specific + // instruction type, they can overload one of these to get the whole class + // of instructions... + // + RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction); } + RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction); } + RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction); } + RetTy visitCastInst(CastInst &I) { DELEGATE(Instruction); } + + // If the user wants a 'default' case, they can choose to override this + // function. If this function is not overloaded in the user's subclass, then + // this instruction just gets ignored. + // + // Note that you MUST override this function if your return type is not void. + // + void visitInstruction(Instruction &I) {} // Ignore unhandled instructions +}; + +#undef DELEGATE + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/LICENSE.TXT b/final/include/llvm/Support/LICENSE.TXT new file mode 100644 index 00000000000..3479b3fd74d --- /dev/null +++ b/final/include/llvm/Support/LICENSE.TXT @@ -0,0 +1,6 @@ +LLVM System Interface Library +------------------------------------------------------------------------------- +The LLVM System Interface Library is licensed under the Illinois Open Source +License and has the following additional copyright: + +Copyright (C) 2004 eXtensible Systems, Inc. diff --git a/final/include/llvm/Support/LeakDetector.h b/final/include/llvm/Support/LeakDetector.h new file mode 100644 index 00000000000..501a9db72c1 --- /dev/null +++ b/final/include/llvm/Support/LeakDetector.h @@ -0,0 +1,92 @@ +//===-- llvm/Support/LeakDetector.h - Provide leak detection ----*- 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 class that can be used to provide very simple memory leak +// checks for an API. Basically LLVM uses this to make sure that Instructions, +// for example, are deleted when they are supposed to be, and not leaked away. +// +// When compiling with NDEBUG (Release build), this class does nothing, thus +// adding no checking overhead to release builds. Note that this class is +// implemented in a very simple way, requiring completely manual manipulation +// and checking for garbage, but this is intentional: users should not be using +// this API, only other APIs should. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LEAKDETECTOR_H +#define LLVM_SUPPORT_LEAKDETECTOR_H + +#include + +namespace llvm { + +class LLVMContext; +class Value; + +struct LeakDetector { + /// addGarbageObject - Add a pointer to the internal set of "garbage" object + /// pointers. This should be called when objects are created, or if they are + /// taken out of an owning collection. + /// + static void addGarbageObject(void *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + + /// removeGarbageObject - Remove a pointer from our internal representation of + /// our "garbage" objects. This should be called when an object is added to + /// an "owning" collection. + /// + static void removeGarbageObject(void *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + + /// checkForGarbage - Traverse the internal representation of garbage + /// pointers. If there are any pointers that have been add'ed, but not + /// remove'd, big obnoxious warnings about memory leaks are issued. + /// + /// The specified message will be printed indicating when the check was + /// performed. + /// + static void checkForGarbage(LLVMContext &C, const std::string &Message) { +#ifndef NDEBUG + checkForGarbageImpl(C, Message); +#endif + } + + /// Overload the normal methods to work better with Value*'s because they are + /// by far the most common in LLVM. This does not affect the actual + /// functioning of this class, it just makes the warning messages nicer. + /// + static void addGarbageObject(const Value *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + static void removeGarbageObject(const Value *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + +private: + // If we are debugging, the actual implementations will be called... + static void addGarbageObjectImpl(const Value *Object); + static void removeGarbageObjectImpl(const Value *Object); + static void addGarbageObjectImpl(void *Object); + static void removeGarbageObjectImpl(void *Object); + static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/MachO.h b/final/include/llvm/Support/MachO.h new file mode 100644 index 00000000000..6841a0f1fc1 --- /dev/null +++ b/final/include/llvm/Support/MachO.h @@ -0,0 +1,696 @@ +//===-- llvm/Support/MachO.h - The MachO file format ------------*- 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 manifest constants for the MachO object file format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MACHO_H +#define LLVM_SUPPORT_MACHO_H + +#include "llvm/Support/DataTypes.h" + +// NOTE: The enums in this file are intentially named to be different than those +// in the headers in /usr/include/mach (on darwin systems) to avoid conflicts +// with those macros. +namespace llvm { + namespace MachO { + // Enums from + enum { + // Constants for the "magic" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + HeaderMagic32 = 0xFEEDFACEu, // MH_MAGIC + HeaderMagic32Swapped = 0xCEFAEDFEu, // MH_CIGAM + HeaderMagic64 = 0xFEEDFACFu, // MH_MAGIC_64 + HeaderMagic64Swapped = 0xCFFAEDFEu, // MH_CIGAM_64 + UniversalMagic = 0xCAFEBABEu, // FAT_MAGIC + UniversalMagicSwapped = 0xBEBAFECAu, // FAT_CIGAM + + // Constants for the "filetype" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + HeaderFileTypeObject = 0x1u, // MH_OBJECT + HeaderFileTypeExecutable = 0x2u, // MH_EXECUTE + HeaderFileTypeFixedVMShlib = 0x3u, // MH_FVMLIB + HeaderFileTypeCore = 0x4u, // MH_CORE + HeaderFileTypePreloadedExecutable = 0x5u, // MH_PRELOAD + HeaderFileTypeDynamicShlib = 0x6u, // MH_DYLIB + HeaderFileTypeDynamicLinkEditor = 0x7u, // MH_DYLINKER + HeaderFileTypeBundle = 0x8u, // MH_BUNDLE + HeaderFileTypeDynamicShlibStub = 0x9u, // MH_DYLIB_STUB + HeaderFileTypeDSYM = 0xAu, // MH_DSYM + HeaderFileTypeKextBundle = 0xBu, // MH_KEXT_BUNDLE + + // Constant bits for the "flags" field in llvm::MachO::mach_header and + // llvm::MachO::mach_header_64 + HeaderFlagBitNoUndefinedSymbols = 0x00000001u, // MH_NOUNDEFS + HeaderFlagBitIsIncrementalLinkObject= 0x00000002u, // MH_INCRLINK + HeaderFlagBitIsDynamicLinkObject = 0x00000004u, // MH_DYLDLINK + HeaderFlagBitBindAtLoad = 0x00000008u, // MH_BINDATLOAD + HeaderFlagBitPrebound = 0x00000010u, // MH_PREBOUND + HeaderFlagBitSplitSegments = 0x00000020u, // MH_SPLIT_SEGS + HeaderFlagBitLazyInit = 0x00000040u, // MH_LAZY_INIT + HeaderFlagBitTwoLevelNamespace = 0x00000080u, // MH_TWOLEVEL + HeaderFlagBitForceFlatNamespace = 0x00000100u, // MH_FORCE_FLAT + HeaderFlagBitNoMultipleDefintions = 0x00000200u, // MH_NOMULTIDEFS + HeaderFlagBitNoFixPrebinding = 0x00000400u, // MH_NOFIXPREBINDING + HeaderFlagBitPrebindable = 0x00000800u, // MH_PREBINDABLE + HeaderFlagBitAllModulesBound = 0x00001000u, // MH_ALLMODSBOUND + HeaderFlagBitSubsectionsViaSymbols = 0x00002000u, // MH_SUBSECTIONS_VIA_SYMBOLS + HeaderFlagBitCanonical = 0x00004000u, // MH_CANONICAL + HeaderFlagBitWeakDefines = 0x00008000u, // MH_WEAK_DEFINES + HeaderFlagBitBindsToWeak = 0x00010000u, // MH_BINDS_TO_WEAK + HeaderFlagBitAllowStackExecution = 0x00020000u, // MH_ALLOW_STACK_EXECUTION + HeaderFlagBitRootSafe = 0x00040000u, // MH_ROOT_SAFE + HeaderFlagBitSetUIDSafe = 0x00080000u, // MH_SETUID_SAFE + HeaderFlagBitNoReexportedDylibs = 0x00100000u, // MH_NO_REEXPORTED_DYLIBS + HeaderFlagBitPIE = 0x00200000u, // MH_PIE + HeaderFlagBitDeadStrippableDylib = 0x00400000u, // MH_DEAD_STRIPPABLE_DYLIB + + // Constants for the "cmd" field in llvm::MachO::load_command + LoadCommandDynamicLinkerRequired = 0x80000000u, // LC_REQ_DYLD + LoadCommandSegment32 = 0x00000001u, // LC_SEGMENT + LoadCommandSymtab = 0x00000002u, // LC_SYMTAB + LoadCommandSymSeg = 0x00000003u, // LC_SYMSEG + LoadCommandThread = 0x00000004u, // LC_THREAD + LoadCommandUnixThread = 0x00000005u, // LC_UNIXTHREAD + LoadCommandFixedVMShlibLoad = 0x00000006u, // LC_LOADFVMLIB + LoadCommandFixedVMShlibIdent = 0x00000007u, // LC_IDFVMLIB + LoadCommandIdent = 0x00000008u, // LC_IDENT + LoadCommandFixedVMFileInclusion = 0x00000009u, // LC_FVMFILE + LoadCommandPrePage = 0x0000000Au, // LC_PREPAGE + LoadCommandDynamicSymtabInfo = 0x0000000Bu, // LC_DYSYMTAB + LoadCommandDylibLoad = 0x0000000Cu, // LC_LOAD_DYLIB + LoadCommandDylibIdent = 0x0000000Du, // LC_ID_DYLIB + LoadCommandDynamicLinkerLoad = 0x0000000Eu, // LC_LOAD_DYLINKER + LoadCommandDynamicLinkerIdent = 0x0000000Fu, // LC_ID_DYLINKER + LoadCommandDylibPrebound = 0x00000010u, // LC_PREBOUND_DYLIB + LoadCommandRoutines32 = 0x00000011u, // LC_ROUTINES + LoadCommandSubFramework = 0x00000012u, // LC_SUB_FRAMEWORK + LoadCommandSubUmbrella = 0x00000013u, // LC_SUB_UMBRELLA + LoadCommandSubClient = 0x00000014u, // LC_SUB_CLIENT + LoadCommandSubLibrary = 0x00000015u, // LC_SUB_LIBRARY + LoadCommandTwoLevelHints = 0x00000016u, // LC_TWOLEVEL_HINTS + LoadCommandPreBindChecksum = 0x00000017u, // LC_PREBIND_CKSUM + LoadCommandDylibLoadWeak = 0x80000018u, // LC_LOAD_WEAK_DYLIB + LoadCommandSegment64 = 0x00000019u, // LC_SEGMENT_64 + LoadCommandRoutines64 = 0x0000001Au, // LC_ROUTINES_64 + LoadCommandUUID = 0x0000001Bu, // LC_UUID + LoadCommandRunpath = 0x8000001Cu, // LC_RPATH + LoadCommandCodeSignature = 0x0000001Du, // LC_CODE_SIGNATURE + LoadCommandSegmentSplitInfo = 0x0000001Eu, // LC_SEGMENT_SPLIT_INFO + LoadCommandDylibReexport = 0x8000001Fu, // LC_REEXPORT_DYLIB + LoadCommandDylibLazyLoad = 0x00000020u, // LC_LAZY_LOAD_DYLIB + LoadCommandEncryptionInfo = 0x00000021u, // LC_ENCRYPTION_INFO + LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO + LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY + LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB + + // Constant bits for the "flags" field in llvm::MachO::segment_command + SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM + SegmentCommandFlagBitFixedVMLibrary = 0x2u, // SG_FVMLIB + SegmentCommandFlagBitNoRelocations = 0x4u, // SG_NORELOC + SegmentCommandFlagBitProtectedVersion1 = 0x8u, // SG_PROTECTED_VERSION_1 + + + // Constant masks for the "flags" field in llvm::MachO::section and + // llvm::MachO::section_64 + SectionFlagMaskSectionType = 0x000000ffu, // SECTION_TYPE + SectionFlagMaskAllAttributes = 0xffffff00u, // SECTION_ATTRIBUTES + SectionFlagMaskUserAttributes = 0xff000000u, // SECTION_ATTRIBUTES_USR + SectionFlagMaskSystemAttributes = 0x00ffff00u, // SECTION_ATTRIBUTES_SYS + + // Constant masks for the "flags[7:0]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE) + SectionTypeRegular = 0x00u, // S_REGULAR + SectionTypeZeroFill = 0x01u, // S_ZEROFILL + SectionTypeCStringLiterals = 0x02u, // S_CSTRING_LITERALS + SectionType4ByteLiterals = 0x03u, // S_4BYTE_LITERALS + SectionType8ByteLiterals = 0x04u, // S_8BYTE_LITERALS + SectionTypeLiteralPointers = 0x05u, // S_LITERAL_POINTERS + SectionTypeNonLazySymbolPointers = 0x06u, // S_NON_LAZY_SYMBOL_POINTERS + SectionTypeLazySymbolPointers = 0x07u, // S_LAZY_SYMBOL_POINTERS + SectionTypeSymbolStubs = 0x08u, // S_SYMBOL_STUBS + SectionTypeModuleInitFunctionPointers = 0x09u, // S_MOD_INIT_FUNC_POINTERS + SectionTypeModuleTermFunctionPointers = 0x0au, // S_MOD_TERM_FUNC_POINTERS + SectionTypeCoalesced = 0x0bu, // S_COALESCED + SectionTypeZeroFillLarge = 0x0cu, // S_GB_ZEROFILL + SectionTypeInterposing = 0x0du, // S_INTERPOSING + SectionType16ByteLiterals = 0x0eu, // S_16BYTE_LITERALS + SectionTypeDTraceObjectFormat = 0x0fu, // S_DTRACE_DOF + SectionTypeLazyDylibSymbolPointers = 0x10u, // S_LAZY_DYLIB_SYMBOL_POINTERS + + // Constant masks for the "flags[31:24]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) + SectionAttrUserPureInstructions = 0x80000000u, // S_ATTR_PURE_INSTRUCTIONS + SectionAttrUserNoTableOfContents = 0x40000000u, // S_ATTR_NO_TOC + SectionAttrUserCanStripStaticSymbols = 0x20000000u, // S_ATTR_STRIP_STATIC_SYMS + SectionAttrUserNoDeadStrip = 0x10000000u, // S_ATTR_NO_DEAD_STRIP + SectionAttrUserLiveSupport = 0x08000000u, // S_ATTR_LIVE_SUPPORT + SectionAttrUserSelfModifyingCode = 0x04000000u, // S_ATTR_SELF_MODIFYING_CODE + SectionAttrUserDebug = 0x02000000u, // S_ATTR_DEBUG + + // Constant masks for the "flags[23:8]" field in llvm::MachO::section and + // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS) + SectionAttrSytemSomeInstructions = 0x00000400u, // S_ATTR_SOME_INSTRUCTIONS + SectionAttrSytemHasExternalRelocations= 0x00000200u, // S_ATTR_EXT_RELOC + SectionAttrSytemHasLocalRelocations = 0x00000100u, // S_ATTR_LOC_RELOC + + IndirectSymbolLocal = 0x80000000u, // INDIRECT_SYMBOL_LOCAL + IndirectSymbolAbsolute = 0x40000000u, // INDIRECT_SYMBOL_ABS + + RebaseTypePointer = 1u, // REBASE_TYPE_POINTER + RebaseTypeTextAbsolute32 = 2u, // REBASE_TYPE_TEXT_ABSOLUTE32 + RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 + + RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK + RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK + RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE + RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM + RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + RebaseOpcodeAddAddressULEB = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB + RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED + RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES + RebaseOpcodeDoRebaseULEBTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES + RebaseOpcodeDoRebaseAddAddressULEB = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + RebaseOpcodeDoRebaseULEBTimesSkippingULEB = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + + + BindTypePointer = 1u, // BIND_TYPE_POINTER + BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 + BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 + + BindSpecialDylibSelf = 0u, // BIND_SPECIAL_DYLIB_SELF + BindSpecialDylibMainExecutable = -1u, // BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE + BindSpecialDylibFlatLookup = -2u, // BIND_SPECIAL_DYLIB_FLAT_LOOKUP + + BindSymbolFlagsWeakImport = 0x1u, // BIND_SYMBOL_FLAGS_WEAK_IMPORT + BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION + + BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK + BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK + BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE + BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB + BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM + BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM + BindOpcodeSetAppendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB + BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB + BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND + BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED + BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB + + ExportSymbolFlagsKindMask = 0x03u, // EXPORT_SYMBOL_FLAGS_KIND_MASK + ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR + ExportSymbolFlagsKindThreadLocal = 0x01u, // EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL + ExportSymbolFlagsWeakDefinition = 0x04u, // EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION + ExportSymbolFlagsIndirectDefinition = 0x08u, // EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION + ExportSymbolFlagsHasSpecializations = 0x10u, // EXPORT_SYMBOL_FLAGS_HAS_SPECIALIZATIONS + + + // Constant masks for the "n_type" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + NlistMaskStab = 0xe0, // N_STAB + NlistMaskPrivateExternal = 0x10, // N_PEXT + NlistMaskType = 0x0e, // N_TYPE + NlistMaskExternal = 0x01, // N_EXT + + // Constants for the "n_type & N_TYPE" llvm::MachO::nlist and + // llvm::MachO::nlist_64 + NListTypeUndefined = 0x0u, // N_UNDF + NListTypeAbsolute = 0x2u, // N_ABS + NListTypeSection = 0xeu, // N_SECT + NListTypePreboundUndefined = 0xcu, // N_PBUD + NListTypeIndirect = 0xau, // N_INDR + + // Constant masks for the "n_sect" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 + NListSectionNoSection = 0u, // NO_SECT + NListSectionMaxSection = 0xffu, // MAX_SECT + + // Constant values for the "n_type" field in llvm::MachO::nlist and + // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" + StabGlobalSymbol = 0x20u, // N_GSYM + StabFunctionName = 0x22u, // N_FNAME + StabFunction = 0x24u, // N_FUN + StabStaticSymbol = 0x26u, // N_STSYM + StabLocalCommon = 0x28u, // N_LCSYM + StabBeginSymbol = 0x2Eu, // N_BNSYM + StabSourceFileOptions = 0x3Cu, // N_OPT + StabRegisterSymbol = 0x40u, // N_RSYM + StabSourceLine = 0x44u, // N_SLINE + StabEndSymbol = 0x4Eu, // N_ENSYM + StabStructureType = 0x60u, // N_SSYM + StabSourceFileName = 0x64u, // N_SO + StabObjectFileName = 0x66u, // N_OSO + StabLocalSymbol = 0x80u, // N_LSYM + StabBeginIncludeFileName = 0x82u, // N_BINCL + StabIncludeFileName = 0x84u, // N_SOL + StabCompilerParameters = 0x86u, // N_PARAMS + StabCompilerVersion = 0x88u, // N_VERSION + StabCompilerOptLevel = 0x8Au, // N_OLEVEL + StabParameter = 0xA0u, // N_PSYM + StabEndIncludeFile = 0xA2u, // N_EINCL + StabAlternateEntry = 0xA4u, // N_ENTRY + StabLeftBracket = 0xC0u, // N_LBRAC + StabDeletedIncludeFile = 0xC2u, // N_EXCL + StabRightBracket = 0xE0u, // N_RBRAC + StabBeginCommon = 0xE2u, // N_BCOMM + StabEndCommon = 0xE4u, // N_ECOMM + StabEndCommonLocal = 0xE8u, // N_ECOML + StabLength = 0xFEu // N_LENG + + }; + + // Structs from + + struct mach_header { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + }; + + struct mach_header_64 { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + uint32_t reserved; + }; + + struct load_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct segment_command { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t fileoff; + uint32_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct segment_command_64 { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct section { + char sectname[16]; + char segname[16]; + uint32_t addr; + uint32_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + }; + + struct section_64 { + char sectname[16]; + char segname[16]; + uint64_t addr; + uint64_t size; + uint32_t offset; + uint32_t align; + uint32_t reloff; + uint32_t nreloc; + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + }; + + struct fvmlib { + uint32_t name; + uint32_t minor_version; + uint32_t header_addr; + }; + + struct fvmlib_command { + uint32_t cmd; + uint32_t cmdsize; + struct fvmlib fvmlib; + }; + + struct dylib { + uint32_t name; + uint32_t timestamp; + uint32_t current_version; + uint32_t compatibility_version; + }; + + struct dylib_command { + uint32_t cmd; + uint32_t cmdsize; + struct dylib dylib; + }; + + struct sub_framework_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t umbrella; + }; + + struct sub_client_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t client; + }; + + struct sub_umbrella_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t sub_umbrella; + }; + + struct sub_library_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t sub_library; + }; + + struct prebound_dylib_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + uint32_t nmodules; + uint32_t linked_modules; + }; + + struct dylinker_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + }; + + struct thread_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct routines_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t init_address; + uint32_t init_module; + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + }; + + struct routines_command_64 { + uint32_t cmd; + uint32_t cmdsize; + uint64_t init_address; + uint64_t init_module; + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; + uint64_t reserved4; + uint64_t reserved5; + uint64_t reserved6; + }; + + struct symtab_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t symoff; + uint32_t nsyms; + uint32_t stroff; + uint32_t strsize; + }; + + struct dysymtab_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t iundefsym; + uint32_t nundefsym; + uint32_t tocoff; + uint32_t ntoc; + uint32_t modtaboff; + uint32_t nmodtab; + uint32_t extrefsymoff; + uint32_t nextrefsyms; + uint32_t indirectsymoff; + uint32_t nindirectsyms; + uint32_t extreloff; + uint32_t nextrel; + uint32_t locreloff; + uint32_t nlocrel; + }; + + struct dylib_table_of_contents { + uint32_t symbol_index; + uint32_t module_index; + }; + + struct dylib_module { + uint32_t module_name; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t irefsym; + uint32_t nrefsym; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextrel; + uint32_t nextrel; + uint32_t iinit_iterm; + uint32_t ninit_nterm; + uint32_t objc_module_info_addr; + uint32_t objc_module_info_size; + }; + + struct dylib_module_64 { + uint32_t module_name; + uint32_t iextdefsym; + uint32_t nextdefsym; + uint32_t irefsym; + uint32_t nrefsym; + uint32_t ilocalsym; + uint32_t nlocalsym; + uint32_t iextrel; + uint32_t nextrel; + uint32_t iinit_iterm; + uint32_t ninit_nterm; + uint32_t objc_module_info_size; + uint64_t objc_module_info_addr; + }; + + struct dylib_reference { + uint32_t isym:24, + flags:8; + }; + + + struct twolevel_hints_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t offset; + uint32_t nhints; + }; + + struct twolevel_hint { + uint32_t isub_image:8, + itoc:24; + }; + + struct prebind_cksum_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cksum; + }; + + struct uuid_command { + uint32_t cmd; + uint32_t cmdsize; + uint8_t uuid[16]; + }; + + struct rpath_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t path; + }; + + struct linkedit_data_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t dataoff; + uint32_t datasize; + }; + + struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; + }; + + struct dyld_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t rebase_off; + uint32_t rebase_size; + uint32_t bind_off; + uint32_t bind_size; + uint32_t weak_bind_off; + uint32_t weak_bind_size; + uint32_t lazy_bind_off; + uint32_t lazy_bind_size; + uint32_t export_off; + uint32_t export_size; + }; + + struct symseg_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t offset; + uint32_t size; + }; + + struct ident_command { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct fvmfile_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t name; + uint32_t header_addr; + }; + + + // Structs from + struct fat_header { + uint32_t magic; + uint32_t nfat_arch; + }; + + struct fat_arch { + uint32_t cputype; + uint32_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t align; + }; + + // Structs from + struct nlist { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + int16_t n_desc; + uint32_t n_value; + }; + + struct nlist_64 { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + uint64_t n_value; + }; + + // Get/Set functions from + + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) + { + return (((n_desc) >> 8u) & 0xffu); + } + + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) + { + n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); + } + + static inline uint8_t GET_COMM_ALIGN (uint16_t n_desc) + { + return (n_desc >> 8u) & 0x0fu; + } + + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) + { + n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); + } + + // Enums from + enum { + // Capability bits used in the definition of cpu_type. + CPUArchMask = 0xff000000, // Mask for architecture bits + CPUArchABI64 = 0x01000000, // 64 bit ABI + + // Constants for the cputype field. + CPUTypeI386 = 7, + CPUTypeX86_64 = CPUTypeI386 | CPUArchABI64, + CPUTypeARM = 12, + CPUTypeSPARC = 14, + CPUTypePowerPC = 18, + CPUTypePowerPC64 = CPUTypePowerPC | CPUArchABI64, + + + // Constants for the cpusubtype field. + + // X86 + CPUSubType_I386_ALL = 3, + CPUSubType_X86_64_ALL = 3, + + // ARM + CPUSubType_ARM_ALL = 0, + CPUSubType_ARM_V4T = 5, + CPUSubType_ARM_V5 = 7, + CPUSubType_ARM_V6 = 6, + CPUSubType_ARM_V7 = 9, + + // PowerPC + CPUSubType_POWERPC_ALL = 0, + + CPUSubType_SPARC_ALL = 0 + }; + } // end namespace MachO +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/ManagedStatic.h b/final/include/llvm/Support/ManagedStatic.h new file mode 100644 index 00000000000..53e73ad35f4 --- /dev/null +++ b/final/include/llvm/Support/ManagedStatic.h @@ -0,0 +1,110 @@ +//===-- llvm/Support/ManagedStatic.h - Static Global 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 the ManagedStatic class and the llvm_shutdown() function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANAGED_STATIC_H +#define LLVM_SUPPORT_MANAGED_STATIC_H + +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Threading.h" + +namespace llvm { + +/// object_creator - Helper method for ManagedStatic. +template +void* object_creator() { + return new C(); +} + +/// object_deleter - Helper method for ManagedStatic. +/// +template struct object_deleter { + static void call(void * Ptr) { delete (T*)Ptr; } +}; +template struct object_deleter { + static void call(void * Ptr) { delete[] (T*)Ptr; } +}; + +/// ManagedStaticBase - Common base class for ManagedStatic instances. +class ManagedStaticBase { +protected: + // This should only be used as a static variable, which guarantees that this + // will be zero initialized. + mutable void *Ptr; + mutable void (*DeleterFn)(void*); + mutable const ManagedStaticBase *Next; + + void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; +public: + /// isConstructed - Return true if this object has not been created yet. + bool isConstructed() const { return Ptr != 0; } + + void destroy() const; +}; + +/// ManagedStatic - This transparently changes the behavior of global statics to +/// be lazily constructed on demand (good for reducing startup times of dynamic +/// libraries that link in LLVM components) and for making destruction be +/// explicit through the llvm_shutdown() function call. +/// +template +class ManagedStatic : public ManagedStaticBase { +public: + + // Accessors. + C &operator*() { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return *static_cast(Ptr); + } + C *operator->() { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return static_cast(Ptr); + } + const C &operator*() const { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return *static_cast(Ptr); + } + const C *operator->() const { + void* tmp = Ptr; + if (llvm_is_multithreaded()) sys::MemoryFence(); + if (!tmp) RegisterManagedStatic(object_creator, object_deleter::call); + + return static_cast(Ptr); + } +}; + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm_shutdown(); + + +/// llvm_shutdown_obj - This is a simple helper class that calls +/// llvm_shutdown() when it is destroyed. +struct llvm_shutdown_obj { + llvm_shutdown_obj() { } + explicit llvm_shutdown_obj(bool multithreaded) { + if (multithreaded) llvm_start_multithreaded(); + } + ~llvm_shutdown_obj() { llvm_shutdown(); } +}; + +} + +#endif diff --git a/final/include/llvm/Support/MathExtras.h b/final/include/llvm/Support/MathExtras.h new file mode 100644 index 00000000000..4627557f7f1 --- /dev/null +++ b/final/include/llvm/Support/MathExtras.h @@ -0,0 +1,460 @@ +//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful for math stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#include "llvm/Support/SwapByteOrder.h" + +namespace llvm { + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +inline uint32_t Hi_32(uint64_t Value) { + return static_cast(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +inline uint32_t Lo_32(uint64_t Value) { + return static_cast(Value); +} + +/// isInt - Checks if an integer fits into the given bit width. +template +inline bool isInt(int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} +// Template specializations to get better code for common cases. +template<> +inline bool isInt<8>(int64_t x) { + return static_cast(x) == x; +} +template<> +inline bool isInt<16>(int64_t x) { + return static_cast(x) == x; +} +template<> +inline bool isInt<32>(int64_t x) { + return static_cast(x) == x; +} + +/// isUInt - Checks if an unsigned integer fits into the given bit width. +template +inline bool isUInt(uint64_t x) { + return N >= 64 || x < (UINT64_C(1)< +inline bool isUInt<8>(uint64_t x) { + return static_cast(x) == x; +} +template<> +inline bool isUInt<16>(uint64_t x) { + return static_cast(x) == x; +} +template<> +inline bool isUInt<32>(uint64_t x) { + return static_cast(x) == x; +} + +/// isUIntN - Checks if an unsigned integer fits into the given (dynamic) +/// bit width. +inline bool isUIntN(unsigned N, uint64_t x) { + return x == (x & (~0ULL >> (64 - N))); +} + +/// isIntN - Checks if an signed integer fits into the given (dynamic) +/// bit width. +inline bool isIntN(unsigned N, int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} + +/// isMask_32 - This function returns true if the argument is a sequence of ones +/// starting at the least significant bit with the remainder zero (32 bit +/// version). Ex. isMask_32(0x0000FFFFU) == true. +inline bool isMask_32(uint32_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isMask_64 - This function returns true if the argument is a sequence of ones +/// starting at the least significant bit with the remainder zero (64 bit +/// version). +inline bool isMask_64(uint64_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isShiftedMask_32 - This function returns true if the argument contains a +/// sequence of ones with the remainder zero (32 bit version.) +/// Ex. isShiftedMask_32(0x0000FF00U) == true. +inline bool isShiftedMask_32(uint32_t Value) { + return isMask_32((Value - 1) | Value); +} + +/// isShiftedMask_64 - This function returns true if the argument contains a +/// sequence of ones with the remainder zero (64 bit version.) +inline bool isShiftedMask_64(uint64_t Value) { + return isMask_64((Value - 1) | Value); +} + +/// isPowerOf2_32 - This function returns true if the argument is a power of +/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) +inline bool isPowerOf2_32(uint32_t Value) { + return Value && !(Value & (Value - 1)); +} + +/// isPowerOf2_64 - This function returns true if the argument is a power of two +/// > 0 (64 bit edition.) +inline bool isPowerOf2_64(uint64_t Value) { + return Value && !(Value & (Value - int64_t(1L))); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +inline uint16_t ByteSwap_16(uint16_t Value) { + return sys::SwapByteOrder_16(Value); +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +inline uint32_t ByteSwap_32(uint32_t Value) { + return sys::SwapByteOrder_32(Value); +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +inline uint64_t ByteSwap_64(uint64_t Value) { + return sys::SwapByteOrder_64(Value); +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (!Value) return 32; + Count = 0; + // bisection method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingOnes_32 - this function performs the operation of +/// counting the number of ones from the most significant bit to the first zero +/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8. +/// Returns 32 if the word is all ones. +inline unsigned CountLeadingOnes_32(uint32_t Value) { + return CountLeadingZeros_32(~Value); +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisection method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountLeadingOnes_64 - This function performs the operation +/// of counting the number of ones from the most significant bit to the first +/// zero bit (64 bit edition.) +/// Returns 64 if the word is all ones. +inline unsigned CountLeadingOnes_64(uint64_t Value) { + return CountLeadingZeros_64(~Value); +} + +/// CountTrailingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the least significant bit to the first one +/// bit. Ex. CountTrailingZeros_32(0xFF00FF00) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountTrailingZeros_32(uint32_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctz(Value) : 32; +#else + static const unsigned Mod37BitPosition[] = { + 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, + 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, + 5, 20, 8, 19, 18 + }; + return Mod37BitPosition[(-Value & Value) % 37]; +#endif +} + +/// CountTrailingOnes_32 - this function performs the operation of +/// counting the number of ones from the least significant bit to the first zero +/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8. +/// Returns 32 if the word is all ones. +inline unsigned CountTrailingOnes_32(uint32_t Value) { + return CountTrailingZeros_32(~Value); +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(-Value & Value) % 67]; +#endif +} + +/// CountTrailingOnes_64 - This function performs the operation +/// of counting the number of ones from the least significant bit to the first +/// zero bit (64 bit edition.) +/// Returns 64 if the word is all ones. +inline unsigned CountTrailingOnes_64(uint64_t Value) { + return CountTrailingZeros_64(~Value); +} + +/// CountPopulation_32 - this function counts the number of set bits in a value. +/// Ex. CountPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +inline unsigned CountPopulation_32(uint32_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value - ((Value >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +inline unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +/// Log2_32 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (32 bit edition.) +/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 +inline unsigned Log2_32(uint32_t Value) { + return 31 - CountLeadingZeros_32(Value); +} + +/// Log2_64 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (64 bit edition.) +inline unsigned Log2_64(uint64_t Value) { + return 63 - CountLeadingZeros_64(Value); +} + +/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified +/// value, 32 if the value is zero. (32 bit edition). +/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 +inline unsigned Log2_32_Ceil(uint32_t Value) { + return 32-CountLeadingZeros_32(Value-1); +} + +/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified +/// value, 64 if the value is zero. (64 bit edition.) +inline unsigned Log2_64_Ceil(uint64_t Value) { + return 64-CountLeadingZeros_64(Value-1); +} + +/// GreatestCommonDivisor64 - Return the greatest common divisor of the two +/// values using Euclid's algorithm. +inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { + while (B) { + uint64_t T = B; + B = A % B; + A = T; + } + return A; +} + +/// BitsToDouble - This function takes a 64-bit integer and returns the bit +/// equivalent double. +inline double BitsToDouble(uint64_t Bits) { + union { + uint64_t L; + double D; + } T; + T.L = Bits; + return T.D; +} + +/// BitsToFloat - This function takes a 32-bit integer and returns the bit +/// equivalent float. +inline float BitsToFloat(uint32_t Bits) { + union { + uint32_t I; + float F; + } T; + T.I = Bits; + return T.F; +} + +/// DoubleToBits - This function takes a double and returns the bit +/// equivalent 64-bit integer. Note that copying doubles around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint64_t DoubleToBits(double Double) { + union { + uint64_t L; + double D; + } T; + T.D = Double; + return T.L; +} + +/// FloatToBits - This function takes a float and returns the bit +/// equivalent 32-bit integer. Note that copying floats around +/// changes the bits of NaNs on some hosts, notably x86, so this +/// routine cannot be used if these bits are needed. +inline uint32_t FloatToBits(float Float) { + union { + uint32_t I; + float F; + } T; + T.F = Float; + return T.I; +} + +/// Platform-independent wrappers for the C99 isnan() function. +int IsNAN(float f); +int IsNAN(double d); + +/// Platform-independent wrappers for the C99 isinf() function. +int IsInf(float f); +int IsInf(double d); + +/// MinAlign - A and B are either alignments or offsets. Return the minimum +/// alignment that may be assumed after adding the two together. +static inline uint64_t MinAlign(uint64_t A, uint64_t B) { + // The largest power of 2 that divides both A and B. + return (A | B) & -(A | B); +} + +/// NextPowerOf2 - Returns the next power of two (in 64-bits) +/// that is strictly greater than A. Returns zero on overflow. +static inline uint64_t NextPowerOf2(uint64_t A) { + A |= (A >> 1); + A |= (A >> 2); + A |= (A >> 4); + A |= (A >> 8); + A |= (A >> 16); + A |= (A >> 32); + return A + 1; +} + +/// RoundUpToAlignment - Returns the next integer (mod 2**64) that is +/// greater than or equal to \arg Value and is a multiple of \arg +/// Align. Align must be non-zero. +/// +/// Examples: +/// RoundUpToAlignment(5, 8) = 8 +/// RoundUpToAlignment(17, 8) = 24 +/// RoundUpToAlignment(~0LL, 8) = 0 +inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) { + return ((Value + Align - 1) / Align) * Align; +} + +/// OffsetToAlignment - Return the offset to the next integer (mod 2**64) that +/// is greater than or equal to \arg Value and is a multiple of \arg +/// Align. Align must be non-zero. +inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { + return RoundUpToAlignment(Value, Align) - Value; +} + +/// abs64 - absolute value of a 64-bit int. Not all environments support +/// "abs" on whatever their name for the 64-bit int type is. The absolute +/// value of the largest negative number is undefined, as with "abs". +inline int64_t abs64(int64_t x) { + return (x < 0) ? -x : x; +} + +/// SignExtend32 - Sign extend B-bit number x to 32-bit int. +/// Usage int32_t r = SignExtend32<5>(x); +template inline int32_t SignExtend32(uint32_t x) { + return int32_t(x << (32 - B)) >> (32 - B); +} + +/// SignExtend64 - Sign extend B-bit number x to 64-bit int. +/// Usage int64_t r = SignExtend64<5>(x); +template inline int64_t SignExtend64(uint64_t x) { + return int64_t(x << (64 - B)) >> (64 - B); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Memory.h b/final/include/llvm/Support/Memory.h new file mode 100644 index 00000000000..9c3f85b958b --- /dev/null +++ b/final/include/llvm/Support/Memory.h @@ -0,0 +1,96 @@ +//===- llvm/Support/Memory.h - Memory Support --------------------*- 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 llvm::sys::Memory class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MEMORY_H +#define LLVM_SYSTEM_MEMORY_H + +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +namespace sys { + + /// This class encapsulates the notion of a memory block which has an address + /// and a size. It is used by the Memory class (a friend) as the result of + /// various memory allocation operations. + /// @see Memory + /// @brief Memory block abstraction. + class MemoryBlock { + public: + MemoryBlock() : Address(0), Size(0) { } + MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } + void *base() const { return Address; } + size_t size() const { return Size; } + private: + void *Address; ///< Address of first byte of memory area + size_t Size; ///< Size, in bytes of the memory area + friend class Memory; + }; + + /// This class provides various memory handling functions that manipulate + /// MemoryBlock instances. + /// @since 1.4 + /// @brief An abstraction for memory operations. + class Memory { + public: + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = 0); + + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + + + /// InvalidateInstructionCache - Before the JIT can run a block of code + /// that has been emitted it must invalidate the instruction cache on some + /// platforms. + static void InvalidateInstructionCache(const void *Addr, size_t Len); + + /// setExecutable - Before the JIT can run a block of code, it has to be + /// given read and executable privilege. Return true if it is already r-x + /// or the system is able to change its previlege. + static bool setExecutable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setWritable - When adding to a block of code, the JIT may need + /// to mark a block of code as RW since the protections are on page + /// boundaries, and the JIT internal allocations are not page aligned. + static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setRangeExecutable - Mark the page containing a range of addresses + /// as executable. + static bool setRangeExecutable(const void *Addr, size_t Size); + + /// setRangeWritable - Mark the page containing a range of addresses + /// as writable. + static bool setRangeWritable(const void *Addr, size_t Size); + }; +} +} + +#endif diff --git a/final/include/llvm/Support/MemoryBuffer.h b/final/include/llvm/Support/MemoryBuffer.h new file mode 100644 index 00000000000..b6243b7b10d --- /dev/null +++ b/final/include/llvm/Support/MemoryBuffer.h @@ -0,0 +1,119 @@ +//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORYBUFFER_H +#define LLVM_SUPPORT_MEMORYBUFFER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class error_code; +template class OwningPtr; + +/// MemoryBuffer - This interface provides simple read-only access to a block +/// of memory, and provides simple methods for reading files and standard input +/// into a memory buffer. In addition to basic access to the characters in the +/// file, this interface guarantees you can read one character past the end of +/// the file, and that this character will read as '\0'. +/// +/// The '\0' guarantee is needed to support an optimization -- it's intended to +/// be more efficient for clients which are reading all the data to stop +/// reading when they encounter a '\0' than to continually check the file +/// position to see if it has reached the end of the file. +class MemoryBuffer { + const char *BufferStart; // Start of the buffer. + const char *BufferEnd; // End of the buffer. + + MemoryBuffer(const MemoryBuffer &); // DO NOT IMPLEMENT + MemoryBuffer &operator=(const MemoryBuffer &); // DO NOT IMPLEMENT +protected: + MemoryBuffer() {} + void init(const char *BufStart, const char *BufEnd); +public: + virtual ~MemoryBuffer(); + + const char *getBufferStart() const { return BufferStart; } + const char *getBufferEnd() const { return BufferEnd; } + size_t getBufferSize() const { return BufferEnd-BufferStart; } + + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); + } + + /// getBufferIdentifier - Return an identifier for this buffer, typically the + /// filename it was read from. + virtual const char *getBufferIdentifier() const { + return "Unknown buffer"; + } + + /// getFile - Open the specified file as a MemoryBuffer, returning a new + /// MemoryBuffer if successful, otherwise returning null. If FileSize is + /// specified, this means that the client knows that the file exists and that + /// it has the specified size. + static error_code getFile(StringRef Filename, OwningPtr &result, + int64_t FileSize = -1); + static error_code getFile(const char *Filename, + OwningPtr &result, + int64_t FileSize = -1); + + /// getOpenFile - Given an already-open file descriptor, read the file and + /// return a MemoryBuffer. + static error_code getOpenFile(int FD, const char *Filename, + OwningPtr &result, + int64_t FileSize = -1); + + /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note + /// that InputData must be null terminated. + static MemoryBuffer *getMemBuffer(StringRef InputData, + StringRef BufferName = ""); + + /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, + /// copying the contents and taking ownership of it. InputData does not + /// have to be null terminated. + static MemoryBuffer *getMemBufferCopy(StringRef InputData, + StringRef BufferName = ""); + + /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that + /// is completely initialized to zeros. Note that the caller should + /// initialize the memory allocated by this method. The memory is owned by + /// the MemoryBuffer object. + static MemoryBuffer *getNewMemBuffer(size_t Size, StringRef BufferName = ""); + + /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size + /// that is not initialized. Note that the caller should initialize the + /// memory allocated by this method. The memory is owned by the MemoryBuffer + /// object. + static MemoryBuffer *getNewUninitMemBuffer(size_t Size, + StringRef BufferName = ""); + + /// getSTDIN - Read all of stdin into a file buffer, and return it. + /// If an error occurs, this returns null and sets ec. + static error_code getSTDIN(OwningPtr &result); + + + /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin + /// if the Filename is "-". If an error occurs, this returns null and sets + /// ec. + static error_code getFileOrSTDIN(StringRef Filename, + OwningPtr &result, + int64_t FileSize = -1); + static error_code getFileOrSTDIN(const char *Filename, + OwningPtr &result, + int64_t FileSize = -1); +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/MemoryObject.h b/final/include/llvm/Support/MemoryObject.h new file mode 100644 index 00000000000..dec0f134b30 --- /dev/null +++ b/final/include/llvm/Support/MemoryObject.h @@ -0,0 +1,70 @@ +//===- MemoryObject.h - Abstract memory interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MEMORYOBJECT_H +#define MEMORYOBJECT_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// MemoryObject - Abstract base class for contiguous addressable memory. +/// Necessary for cases in which the memory is in another process, in a +/// file, or on a remote machine. +/// All size and offset parameters are uint64_ts, to allow 32-bit processes +/// access to 64-bit address spaces. +class MemoryObject { +public: + /// Destructor - Override as necessary. + virtual ~MemoryObject(); + + /// getBase - Returns the lowest valid address in the region. + /// + /// @result - The lowest valid address. + virtual uint64_t getBase() const = 0; + + /// getExtent - Returns the size of the region in bytes. (The region is + /// contiguous, so the highest valid address of the region + /// is getBase() + getExtent() - 1). + /// + /// @result - The size of the region. + virtual uint64_t getExtent() const = 0; + + /// readByte - Tries to read a single byte from the region. + /// + /// @param address - The address of the byte, in the same space as getBase(). + /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. + /// @result - 0 if successful; -1 if not. Failure may be due to a + /// bounds violation or an implementation-specific error. + virtual int readByte(uint64_t address, uint8_t* ptr) const = 0; + + /// readBytes - Tries to read a contiguous range of bytes from the + /// region, up to the end of the region. + /// You should override this function if there is a quicker + /// way than going back and forth with individual bytes. + /// + /// @param address - The address of the first byte, in the same space as + /// getBase(). + /// @param size - The maximum number of bytes to copy. + /// @param buf - A pointer to a buffer to be filled in. Must be non-NULL + /// and large enough to hold size bytes. + /// @param copied - A pointer to a nunber that is filled in with the number + /// of bytes actually read. May be NULL. + /// @result - 0 if successful; -1 if not. Failure may be due to a + /// bounds violation or an implementation-specific error. + virtual int readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const; +}; + +} + +#endif + diff --git a/final/include/llvm/Support/Mutex.h b/final/include/llvm/Support/Mutex.h new file mode 100644 index 00000000000..42ea63060f6 --- /dev/null +++ b/final/include/llvm/Support/Mutex.h @@ -0,0 +1,154 @@ +//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- 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 llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MUTEX_H +#define LLVM_SYSTEM_MUTEX_H + +#include "llvm/Support/Threading.h" +#include + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class MutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. if \p recursive is set + /// to false, the lock will not be recursive which makes it cheaper but + /// also more likely to deadlock (same thread can't acquire more than + /// once). + /// @brief Default Constructor. + explicit MutexImpl(bool recursive = true); + + /// Releases and removes the lock + /// @brief Destructor + ~MutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock. If the lock is held by + /// another thread, this method will wait until it can acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock. + bool acquire(); + + /// Attempts to release the lock. If the lock is held by the current + /// thread, the lock is released allowing other threads to acquire the + /// lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock. + bool release(); + + /// Attempts to acquire the lock without blocking. If the lock is not + /// available, this function returns false quickly (without blocking). If + /// the lock is available, it is acquired. + /// @returns false if any kind of error occurs or the lock is not + /// available, true otherwise. + /// @brief Try to acquire the lock. + bool tryacquire(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + MutexImpl(const MutexImpl & original); + void operator=(const MutexImpl &); + /// @} + }; + + + /// SmartMutex - A mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template + class SmartMutex : public MutexImpl { + unsigned acquired; + bool recursive; + public: + explicit SmartMutex(bool rec = true) : + MutexImpl(rec), acquired(0), recursive(rec) { } + + bool acquire() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::acquire(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert((recursive || acquired == 0) && "Lock already acquired!!"); + ++acquired; + return true; + } + } + + bool release() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::release(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert(((recursive && acquired) || (acquired == 1)) && + "Lock not acquired before release!"); + --acquired; + return true; + } + } + + bool tryacquire() { + if (!mt_only || llvm_is_multithreaded()) + return MutexImpl::tryacquire(); + else return true; + } + + private: + SmartMutex(const SmartMutex & original); + void operator=(const SmartMutex &); + }; + + /// Mutex - A standard, always enforced mutex. + typedef SmartMutex Mutex; + + template + class SmartScopedLock { + SmartMutex& mtx; + + public: + SmartScopedLock(SmartMutex& m) : mtx(m) { + mtx.acquire(); + } + + ~SmartScopedLock() { + mtx.release(); + } + }; + + typedef SmartScopedLock ScopedLock; + } +} + +#endif diff --git a/final/include/llvm/Support/MutexGuard.h b/final/include/llvm/Support/MutexGuard.h new file mode 100644 index 00000000000..cd13bfe6eeb --- /dev/null +++ b/final/include/llvm/Support/MutexGuard.h @@ -0,0 +1,41 @@ +//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- 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 guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MUTEXGUARD_H +#define LLVM_SUPPORT_MUTEXGUARD_H + +#include "llvm/Support/Mutex.h" + +namespace llvm { + /// Instances of this class acquire a given Mutex Lock when constructed and + /// hold that lock until destruction. The intention is to instantiate one of + /// these on the stack at the top of some scope to be assured that C++ + /// destruction of the object will always release the Mutex and thus avoid + /// a host of nasty multi-threading problems in the face of exceptions, etc. + /// @brief Guard a section of code with a Mutex. + class MutexGuard { + sys::Mutex &M; + MutexGuard(const MutexGuard &); // DO NOT IMPLEMENT + void operator=(const MutexGuard &); // DO NOT IMPLEMENT + public: + MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } + ~MutexGuard() { M.release(); } + /// holds - Returns true if this locker instance holds the specified lock. + /// This is mostly used in assertions to validate that the correct mutex + /// is held. + bool holds(const sys::Mutex& lock) const { return &M == &lock; } + }; +} + +#endif // LLVM_SUPPORT_MUTEXGUARD_H diff --git a/final/include/llvm/Support/NoFolder.h b/final/include/llvm/Support/NoFolder.h new file mode 100644 index 00000000000..92a9fd695e5 --- /dev/null +++ b/final/include/llvm/Support/NoFolder.h @@ -0,0 +1,288 @@ +//======-- llvm/Support/NoFolder.h - Constant folding helper -*- 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 NoFolder class, a helper for IRBuilder. It provides +// IRBuilder with a set of methods for creating unfolded constants. This is +// useful for learners trying to understand how LLVM IR works, and who don't +// want details to be hidden by the constant folder. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. +// +// Note: since it is not actually possible to create unfolded constants, this +// class returns instructions rather than constants. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_NOFOLDER_H +#define LLVM_SUPPORT_NOFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +namespace llvm { + +class LLVMContext; + +/// NoFolder - Create "constants" (actually, instructions) with no folding. +class NoFolder { +public: + explicit NoFolder(LLVMContext &) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Instruction *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWAdd(LHS, RHS); + } + Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNUWAdd(LHS, RHS); + } + Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFAdd(LHS, RHS); + } + Instruction *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWSub(LHS, RHS); + } + Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNUWSub(LHS, RHS); + } + Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFSub(LHS, RHS); + } + Instruction *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWMul(LHS, RHS); + } + Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNUWMul(LHS, RHS); + } + Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFMul(LHS, RHS); + } + Instruction *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateUDiv(LHS, RHS); + return BinaryOperator::CreateExactUDiv(LHS, RHS); + } + Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactUDiv(LHS, RHS); + } + Instruction *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateSDiv(LHS, RHS); + return BinaryOperator::CreateExactSDiv(LHS, RHS); + } + Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactSDiv(LHS, RHS); + } + Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFDiv(LHS, RHS); + } + Instruction *CreateURem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateURem(LHS, RHS); + } + Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateSRem(LHS, RHS); + } + Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateFRem(LHS, RHS); + } + Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, + bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateLShr(LHS, RHS); + return BinaryOperator::CreateExactLShr(LHS, RHS); + } + Instruction *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + if (!isExact) + return BinaryOperator::CreateAShr(LHS, RHS); + return BinaryOperator::CreateExactAShr(LHS, RHS); + } + Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateAnd(LHS, RHS); + } + Instruction *CreateOr(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateOr(LHS, RHS); + } + Instruction *CreateXor(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateXor(LHS, RHS); + } + + Instruction *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return BinaryOperator::Create(Opc, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Instruction *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + BinaryOperator *BO = BinaryOperator::CreateNeg(C); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } + Instruction *CreateNSWNeg(Constant *C) const { + return BinaryOperator::CreateNSWNeg(C); + } + Instruction *CreateNUWNeg(Constant *C) const { + return BinaryOperator::CreateNUWNeg(C); + } + Instruction *CreateFNeg(Constant *C) const { + return BinaryOperator::CreateFNeg(C); + } + Instruction *CreateNot(Constant *C) const { + return BinaryOperator::CreateNot(C); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); + } + Instruction *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); + } + Instruction *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Instruction *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + return CastInst::Create(Op, C, DestTy); + } + Instruction *CreatePointerCast(Constant *C, const Type *DestTy) const { + return CastInst::CreatePointerCast(C, DestTy); + } + Instruction *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + return CastInst::CreateIntegerCast(C, DestTy, isSigned); + } + Instruction *CreateFPCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateFPCast(C, DestTy); + } + + Instruction *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Instruction *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Instruction *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Instruction *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateZExtOrBitCast(C, DestTy); + } + Instruction *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateSExtOrBitCast(C, DestTy); + } + + Instruction *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateTruncOrBitCast(C, DestTy); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Instruction *CreateICmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { + return new ICmpInst(P, LHS, RHS); + } + Instruction *CreateFCmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { + return new FCmpInst(P, LHS, RHS); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Instruction *CreateSelect(Constant *C, + Constant *True, Constant *False) const { + return SelectInst::Create(C, True, False); + } + + Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return ExtractElementInst::Create(Vec, Idx); + } + + Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return InsertElementInst::Create(Vec, NewElt, Idx); + } + + Instruction *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return new ShuffleVectorInst(V1, V2, Mask); + } + + Instruction *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return ExtractValueInst::Create(Agg, IdxList, IdxList+NumIdx); + } + + Instruction *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, + unsigned NumIdx) const { + return InsertValueInst::Create(Agg, Val, IdxList, IdxList+NumIdx); + } +}; + +} + +#endif diff --git a/final/include/llvm/Support/OutputBuffer.h b/final/include/llvm/Support/OutputBuffer.h new file mode 100644 index 00000000000..6b98e99e28e --- /dev/null +++ b/final/include/llvm/Support/OutputBuffer.h @@ -0,0 +1,166 @@ +//=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods to output values to a data buffer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OUTPUTBUFFER_H +#define LLVM_SUPPORT_OUTPUTBUFFER_H + +#include +#include +#include + +namespace llvm { + + class OutputBuffer { + /// Output buffer. + std::vector &Output; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + public: + OutputBuffer(std::vector &Out, + bool is64bit, bool le) + : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} + + // align - Emit padding into the file until the current output position is + // aligned to the specified power of two boundary. + void align(unsigned Boundary) { + assert(Boundary && (Boundary & (Boundary - 1)) == 0 && + "Must align to 2^k boundary"); + size_t Size = Output.size(); + + if (Size & (Boundary - 1)) { + // Add padding to get alignment to the correct place. + size_t Pad = Boundary - (Size & (Boundary - 1)); + Output.resize(Size + Pad); + } + } + + //===------------------------------------------------------------------===// + // Out Functions - Output the specified value to the data buffer. + + void outbyte(unsigned char X) { + Output.push_back(X); + } + void outhalf(unsigned short X) { + if (isLittleEndian) { + Output.push_back(X & 255); + Output.push_back(X >> 8); + } else { + Output.push_back(X >> 8); + Output.push_back(X & 255); + } + } + void outword(unsigned X) { + if (isLittleEndian) { + Output.push_back((X >> 0) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 24) & 255); + } else { + Output.push_back((X >> 24) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 0) & 255); + } + } + void outxword(uint64_t X) { + if (isLittleEndian) { + Output.push_back(unsigned(X >> 0) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 56) & 255); + } else { + Output.push_back(unsigned(X >> 56) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 0) & 255); + } + } + void outaddr32(unsigned X) { + outword(X); + } + void outaddr64(uint64_t X) { + outxword(X); + } + void outaddr(uint64_t X) { + if (!is64Bit) + outword((unsigned)X); + else + outxword(X); + } + void outstring(const std::string &S, unsigned Length) { + unsigned len_to_copy = static_cast(S.length()) < Length + ? static_cast(S.length()) : Length; + unsigned len_to_fill = static_cast(S.length()) < Length + ? Length - static_cast(S.length()) : 0; + + for (unsigned i = 0; i < len_to_copy; ++i) + outbyte(S[i]); + + for (unsigned i = 0; i < len_to_fill; ++i) + outbyte(0); + } + + //===------------------------------------------------------------------===// + // Fix Functions - Replace an existing entry at an offset. + + void fixhalf(unsigned short X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; + } + void fixword(unsigned X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; + } + void fixxword(uint64_t X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 56)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 48)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 40)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 32)) & 255; + P[4] = (X >> (isLittleEndian ? 32 : 24)) & 255; + P[5] = (X >> (isLittleEndian ? 40 : 16)) & 255; + P[6] = (X >> (isLittleEndian ? 48 : 8)) & 255; + P[7] = (X >> (isLittleEndian ? 56 : 0)) & 255; + } + void fixaddr(uint64_t X, unsigned Offset) { + if (!is64Bit) + fixword((unsigned)X, Offset); + else + fixxword(X, Offset); + } + + unsigned char &operator[](unsigned Index) { + return Output[Index]; + } + const unsigned char &operator[](unsigned Index) const { + return Output[Index]; + } + }; + +} // end llvm namespace + +#endif // LLVM_SUPPORT_OUTPUTBUFFER_H diff --git a/final/include/llvm/Support/PassNameParser.h b/final/include/llvm/Support/PassNameParser.h new file mode 100644 index 00000000000..a24a6f0c5e9 --- /dev/null +++ b/final/include/llvm/Support/PassNameParser.h @@ -0,0 +1,137 @@ +//===- llvm/Support/PassNameParser.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file the PassNameParser and FilteredPassNameParser<> classes, which are +// used to add command line arguments to a utility for all of the passes that +// have been registered into the system. +// +// The PassNameParser class adds ALL passes linked into the system (that are +// creatable) as command line arguments to the tool (when instantiated with the +// appropriate command line option template). The FilteredPassNameParser<> +// template is used for the same purposes as PassNameParser, except that it only +// includes passes that have a PassType that are compatible with the filter +// (which is the template argument). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H +#define LLVM_SUPPORT_PASS_NAME_PARSER_H + +#include "llvm/Pass.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +// PassNameParser class - Make use of the pass registration mechanism to +// automatically add a command line argument to opt for each pass. +// +class PassNameParser : public PassRegistrationListener, + public cl::parser { + cl::Option *Opt; +public: + PassNameParser() : Opt(0) {} + virtual ~PassNameParser(); + + void initialize(cl::Option &O) { + Opt = &O; + cl::parser::initialize(O); + + // Add all of the passes to the map that got initialized before 'this' did. + enumeratePasses(); + } + + // ignorablePassImpl - Can be overriden in subclasses to refine the list of + // which passes we want to include. + // + virtual bool ignorablePassImpl(const PassInfo *P) const { return false; } + + inline bool ignorablePass(const PassInfo *P) const { + // Ignore non-selectable and non-constructible passes! Ignore + // non-optimizations. + return P->getPassArgument() == 0 || *P->getPassArgument() == 0 || + P->getNormalCtor() == 0 || ignorablePassImpl(P); + } + + // Implement the PassRegistrationListener callbacks used to populate our map + // + virtual void passRegistered(const PassInfo *P) { + if (ignorablePass(P) || !Opt) return; + if (findOption(P->getPassArgument()) != getNumOptions()) { + errs() << "Two passes with the same argument (-" + << P->getPassArgument() << ") attempted to be registered!\n"; + llvm_unreachable(0); + } + addLiteralOption(P->getPassArgument(), P, P->getPassName()); + } + virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } + + // printOptionInfo - Print out information about this option. Override the + // default implementation to sort the table before we print... + virtual void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const { + PassNameParser *PNP = const_cast(this); + array_pod_sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); + cl::parser::printOptionInfo(O, GlobalWidth); + } + +private: + // ValLessThan - Provide a sorting comparator for Values elements... + static int ValLessThan(const void *VT1, const void *VT2) { + typedef PassNameParser::OptionInfo ValType; + return std::strcmp(static_cast(VT1)->Name, + static_cast(VT2)->Name); + } +}; + +///===----------------------------------------------------------------------===// +/// FilteredPassNameParser class - Make use of the pass registration +/// mechanism to automatically add a command line argument to opt for +/// each pass that satisfies a filter criteria. Filter should return +/// true for passes to be registered as command-line options. +/// +template +class FilteredPassNameParser : public PassNameParser { +private: + Filter filter; + +public: + bool ignorablePassImpl(const PassInfo *P) const { return !filter(*P); } +}; + +///===----------------------------------------------------------------------===// +/// PassArgFilter - A filter for use with PassNameFilterParser that only +/// accepts a Pass whose Arg matches certain strings. +/// +/// Use like this: +/// +/// extern const char AllowedPassArgs[] = "-anders_aa -dse"; +/// +/// static cl::list< +/// const PassInfo*, +/// bool, +/// FilteredPassNameParser > > +/// PassList(cl::desc("Passes available:")); +/// +/// Only the -anders_aa and -dse options will be available to the user. +/// +template +class PassArgFilter { +public: + bool operator()(const PassInfo &P) const { + return(std::strstr(Args, P.getPassArgument())); + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Path.h b/final/include/llvm/Support/Path.h new file mode 100644 index 00000000000..196eecce818 --- /dev/null +++ b/final/include/llvm/Support/Path.h @@ -0,0 +1,16 @@ +//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file currently includes both PathV1 and PathV2 to facilitate moving +// clients over to the new interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PathV1.h" +#include "llvm/Support/PathV2.h" diff --git a/final/include/llvm/Support/PathV1.h b/final/include/llvm/Support/PathV1.h new file mode 100644 index 00000000000..d7753a3e71e --- /dev/null +++ b/final/include/llvm/Support/PathV1.h @@ -0,0 +1,755 @@ +//===- llvm/Support/PathV1.h - Path Operating System Concept ----*- 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 llvm::sys::Path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PATH_H +#define LLVM_SYSTEM_PATH_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TimeValue.h" +#include +#include +#include + +#define LLVM_PATH_DEPRECATED_MSG(replacement) \ + "PathV1 has been deprecated and will be removed as soon as all LLVM and" \ + " Clang clients have been moved over to PathV2. Please use `" #replacement \ + "` from PathV2 instead." + +namespace llvm { +namespace sys { + + /// This structure provides basic file system information about a file. It + /// is patterned after the stat(2) Unix operating system call but made + /// platform independent and eliminates many of the unix-specific fields. + /// However, to support llvm-ar, the mode, user, and group fields are + /// retained. These pertain to unix security and may not have a meaningful + /// value on non-Unix platforms. However, the other fields should + /// always be applicable on all platforms. The structure is filled in by + /// the PathWithStatus class. + /// @brief File status structure + class FileStatus { + public: + uint64_t fileSize; ///< Size of the file in bytes + TimeValue modTime; ///< Time of file's modification + uint32_t mode; ///< Mode of the file, if applicable + uint32_t user; ///< User ID of owner, if applicable + uint32_t group; ///< Group ID of owner, if applicable + uint64_t uniqueID; ///< A number to uniquely ID this file + bool isDir : 1; ///< True if this is a directory. + bool isFile : 1; ///< True if this is a file. + + FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999), + group(999), uniqueID(0), isDir(false), isFile(false) { } + + TimeValue getTimestamp() const { return modTime; } + uint64_t getSize() const { return fileSize; } + uint32_t getMode() const { return mode; } + uint32_t getUser() const { return user; } + uint32_t getGroup() const { return group; } + uint64_t getUniqueID() const { return uniqueID; } + }; + + /// This class provides an abstraction for the path to a file or directory + /// in the operating system's filesystem and provides various basic operations + /// on it. Note that this class only represents the name of a path to a file + /// or directory which may or may not be valid for a given machine's file + /// system. The class is patterned after the java.io.File class with various + /// extensions and several omissions (not relevant to LLVM). A Path object + /// ensures that the path it encapsulates is syntactically valid for the + /// operating system it is running on but does not ensure correctness for + /// any particular file system. That is, a syntactically valid path might + /// specify path components that do not exist in the file system and using + /// such a Path to act on the file system could produce errors. There is one + /// invalid Path value which is permitted: the empty path. The class should + /// never allow a syntactically invalid non-empty path name to be assigned. + /// Empty paths are required in order to indicate an error result in some + /// situations. If the path is empty, the isValid operation will return + /// false. All operations will fail if isValid is false. Operations that + /// change the path will either return false if it would cause a syntactically + /// invalid path name (in which case the Path object is left unchanged) or + /// throw an std::string exception indicating the error. The methods are + /// grouped into four basic categories: Path Accessors (provide information + /// about the path without accessing disk), Disk Accessors (provide + /// information about the underlying file or directory), Path Mutators + /// (change the path information, not the disk), and Disk Mutators (change + /// the disk file/directory referenced by the path). The Disk Mutator methods + /// all have the word "disk" embedded in their method name to reinforce the + /// notion that the operation modifies the file system. + /// @since 1.4 + /// @brief An abstraction for operating system paths. + class Path { + /// @name Constructors + /// @{ + public: + /// Construct a path to the root directory of the file system. The root + /// directory is a top level directory above which there are no more + /// directories. For example, on UNIX, the root directory is /. On Windows + /// it is file:///. Other operating systems may have different notions of + /// what the root directory is or none at all. In that case, a consistent + /// default root directory will be used. + LLVM_ATTRIBUTE_DEPRECATED(static Path GetRootDirectory(), + LLVM_PATH_DEPRECATED_MSG(NOTHING)); + + /// Construct a path to a unique temporary directory that is created in + /// a "standard" place for the operating system. The directory is + /// guaranteed to be created on exit from this function. If the directory + /// cannot be created, the function will throw an exception. + /// @returns an invalid path (empty) on error + /// @param ErrMsg Optional place for an error message if an error occurs + /// @brief Construct a path to an new, unique, existing temporary + /// directory. + static Path GetTemporaryDirectory(std::string* ErrMsg = 0); + + /// Construct a vector of sys::Path that contains the "standard" system + /// library paths suitable for linking into programs. + /// @brief Construct a path to the system library directory + static void GetSystemLibraryPaths(std::vector& Paths); + + /// Construct a vector of sys::Path that contains the "standard" bitcode + /// library paths suitable for linking into an llvm program. This function + /// *must* return the value of LLVM_LIB_SEARCH_PATH as well as the value + /// of LLVM_LIBDIR. It also must provide the System library paths as + /// returned by GetSystemLibraryPaths. + /// @see GetSystemLibraryPaths + /// @brief Construct a list of directories in which bitcode could be + /// found. + static void GetBitcodeLibraryPaths(std::vector& Paths); + + /// Find the path to a library using its short name. Use the system + /// dependent library paths to locate the library. + /// @brief Find a library. + static Path FindLibrary(std::string& short_name); + + /// Construct a path to the default LLVM configuration directory. The + /// implementation must ensure that this is a well-known (same on many + /// systems) directory in which llvm configuration files exist. For + /// example, on Unix, the /etc/llvm directory has been selected. + /// @brief Construct a path to the default LLVM configuration directory + static Path GetLLVMDefaultConfigDir(); + + /// Construct a path to the LLVM installed configuration directory. The + /// implementation must ensure that this refers to the "etc" directory of + /// the LLVM installation. This is the location where configuration files + /// will be located for a particular installation of LLVM on a machine. + /// @brief Construct a path to the LLVM installed configuration directory + static Path GetLLVMConfigDir(); + + /// Construct a path to the current user's home directory. The + /// implementation must use an operating system specific mechanism for + /// determining the user's home directory. For example, the environment + /// variable "HOME" could be used on Unix. If a given operating system + /// does not have the concept of a user's home directory, this static + /// constructor must provide the same result as GetRootDirectory. + /// @brief Construct a path to the current user's "home" directory + static Path GetUserHomeDirectory(); + + /// Construct a path to the current directory for the current process. + /// @returns The current working directory. + /// @brief Returns the current working directory. + static Path GetCurrentDirectory(); + + /// Return the suffix commonly used on file names that contain an + /// executable. + /// @returns The executable file suffix for the current platform. + /// @brief Return the executable file suffix. + static StringRef GetEXESuffix(); + + /// Return the suffix commonly used on file names that contain a shared + /// object, shared archive, or dynamic link library. Such files are + /// linked at runtime into a process and their code images are shared + /// between processes. + /// @returns The dynamic link library suffix for the current platform. + /// @brief Return the dynamic link library suffix. + static StringRef GetDLLSuffix(); + + /// GetMainExecutable - Return the path to the main executable, given the + /// value of argv[0] from program startup and the address of main itself. + /// In extremis, this function may fail and return an empty path. + static Path GetMainExecutable(const char *argv0, void *MainAddr); + + /// This is one of the very few ways in which a path can be constructed + /// with a syntactically invalid name. The only *legal* invalid name is an + /// empty one. Other invalid names are not permitted. Empty paths are + /// provided so that they can be used to indicate null or error results in + /// other lib/System functionality. + /// @brief Construct an empty (and invalid) path. + Path() : path() {} + Path(const Path &that) : path(that.path) {} + + /// This constructor will accept a char* or std::string as a path. No + /// checking is done on this path to determine if it is valid. To + /// determine validity of the path, use the isValid method. + /// @param p The path to assign. + /// @brief Construct a Path from a string. + explicit Path(StringRef p); + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @param StrStart A pointer to the first character of the path name + /// @param StrLen The length of the path name at StrStart + /// @brief Construct a Path from a string. + Path(const char *StrStart, unsigned StrLen); + + /// @} + /// @name Operators + /// @{ + public: + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(const Path &that) { + path = that.path; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @param that A StringRef denoting the path + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(StringRef that); + + /// Compares \p this Path with \p that Path for equality. + /// @returns true if \p this and \p that refer to the same thing. + /// @brief Equality Operator + bool operator==(const Path &that) const; + + /// Compares \p this Path with \p that Path for inequality. + /// @returns true if \p this and \p that refer to different things. + /// @brief Inequality Operator + bool operator!=(const Path &that) const { return !(*this == that); } + + /// Determines if \p this Path is less than \p that Path. This is required + /// so that Path objects can be placed into ordered collections (e.g. + /// std::map). The comparison is done lexicographically as defined by + /// the std::string::compare method. + /// @returns true if \p this path is lexicographically less than \p that. + /// @brief Less Than Operator + bool operator<(const Path& that) const; + + /// @} + /// @name Path Accessors + /// @{ + public: + /// This function will use an operating system specific algorithm to + /// determine if the current value of \p this is a syntactically valid + /// path name for the operating system. The path name does not need to + /// exist, validity is simply syntactical. Empty paths are always invalid. + /// @returns true iff the path name is syntactically legal for the + /// host operating system. + /// @brief Determine if a path is syntactically valid or not. + bool isValid() const; + + /// This function determines if the contents of the path name are empty. + /// That is, the path name has a zero length. This does NOT determine if + /// if the file is empty. To get the length of the file itself, Use the + /// PathWithStatus::getFileStatus() method and then the getSize() method + /// on the returned FileStatus object. + /// @returns true iff the path is empty. + /// @brief Determines if the path name is empty (invalid). + bool isEmpty() const { return path.empty(); } + + /// This function returns the last component of the path name. The last + /// component is the file or directory name occurring after the last + /// directory separator. If no directory separator is present, the entire + /// path name is returned (i.e. same as toString). + /// @returns StringRef containing the last component of the path name. + /// @brief Returns the last component of the path name. + LLVM_ATTRIBUTE_DEPRECATED( + StringRef getLast() const, + LLVM_PATH_DEPRECATED_MSG(path::filename)); + + /// This function strips off the path and suffix of the file or directory + /// name and returns just the basename. For example /a/foo.bar would cause + /// this function to return "foo". + /// @returns StringRef containing the basename of the path + /// @brief Get the base name of the path + LLVM_ATTRIBUTE_DEPRECATED(StringRef getBasename() const, + LLVM_PATH_DEPRECATED_MSG(path::stem)); + + /// This function strips off the suffix of the path beginning with the + /// path separator ('/' on Unix, '\' on Windows) and returns the result. + LLVM_ATTRIBUTE_DEPRECATED(StringRef getDirname() const, + LLVM_PATH_DEPRECATED_MSG(path::parent_path)); + + /// This function strips off the path and basename(up to and + /// including the last dot) of the file or directory name and + /// returns just the suffix. For example /a/foo.bar would cause + /// this function to return "bar". + /// @returns StringRef containing the suffix of the path + /// @brief Get the suffix of the path + LLVM_ATTRIBUTE_DEPRECATED(StringRef getSuffix() const, + LLVM_PATH_DEPRECATED_MSG(path::extension)); + + /// Obtain a 'C' string for the path name. + /// @returns a 'C' string containing the path name. + /// @brief Returns the path as a C string. + const char *c_str() const { return path.c_str(); } + const std::string &str() const { return path; } + + + /// size - Return the length in bytes of this path name. + size_t size() const { return path.size(); } + + /// empty - Returns true if the path is empty. + unsigned empty() const { return path.empty(); } + + /// @} + /// @name Disk Accessors + /// @{ + public: + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. + LLVM_ATTRIBUTE_DEPRECATED( + bool isAbsolute() const, + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); + + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. + LLVM_ATTRIBUTE_DEPRECATED( + static bool isAbsolute(const char *NameStart, unsigned NameLen), + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); + + /// This function opens the file associated with the path name provided by + /// the Path object and reads its magic number. If the magic number at the + /// start of the file matches \p magic, true is returned. In all other + /// cases (file not found, file not accessible, etc.) it returns false. + /// @returns true if the magic number of the file matches \p magic. + /// @brief Determine if file has a specific magic number + LLVM_ATTRIBUTE_DEPRECATED(bool hasMagicNumber(StringRef magic) const, + LLVM_PATH_DEPRECATED_MSG(fs::has_magic)); + + /// This function retrieves the first \p len bytes of the file associated + /// with \p this. These bytes are returned as the "magic number" in the + /// \p Magic parameter. + /// @returns true if the Path is a file and the magic number is retrieved, + /// false otherwise. + /// @brief Get the file's magic number. + bool getMagicNumber(std::string& Magic, unsigned len) const; + + /// This function determines if the path name in the object references an + /// archive file by looking at its magic number. + /// @returns true if the file starts with the magic number for an archive + /// file. + /// @brief Determine if the path references an archive file. + bool isArchive() const; + + /// This function determines if the path name in the object references an + /// LLVM Bitcode file by looking at its magic number. + /// @returns true if the file starts with the magic number for LLVM + /// bitcode files. + /// @brief Determine if the path references a bitcode file. + bool isBitcodeFile() const; + + /// This function determines if the path name in the object references a + /// native Dynamic Library (shared library, shared object) by looking at + /// the file's magic number. The Path object must reference a file, not a + /// directory. + /// @returns true if the file starts with the magic number for a native + /// shared library. + /// @brief Determine if the path references a dynamic library. + bool isDynamicLibrary() const; + + /// This function determines if the path name in the object references a + /// native object file by looking at it's magic number. The term object + /// file is defined as "an organized collection of separate, named + /// sequences of binary data." This covers the obvious file formats such + /// as COFF and ELF, but it also includes llvm ir bitcode, archives, + /// libraries, etc... + /// @returns true if the file starts with the magic number for an object + /// file. + /// @brief Determine if the path references an object file. + bool isObjectFile() const; + + /// This function determines if the path name references an existing file + /// or directory in the file system. + /// @returns true if the pathname references an existing file or + /// directory. + /// @brief Determines if the path is a file or directory in + /// the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool exists() const, + LLVM_PATH_DEPRECATED_MSG(fs::exists)); + + /// This function determines if the path name references an + /// existing directory. + /// @returns true if the pathname references an existing directory. + /// @brief Determines if the path is a directory in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isDirectory() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_directory)); + + /// This function determines if the path name references an + /// existing symbolic link. + /// @returns true if the pathname references an existing symlink. + /// @brief Determines if the path is a symlink in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isSymLink() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_symlink)); + + /// This function determines if the path name references a readable file + /// or directory in the file system. This function checks for + /// the existence and readability (by the current program) of the file + /// or directory. + /// @returns true if the pathname references a readable file. + /// @brief Determines if the path is a readable file or directory + /// in the file system. + bool canRead() const; + + /// This function determines if the path name references a writable file + /// or directory in the file system. This function checks for the + /// existence and writability (by the current program) of the file or + /// directory. + /// @returns true if the pathname references a writable file. + /// @brief Determines if the path is a writable file or directory + /// in the file system. + bool canWrite() const; + + /// This function checks that what we're trying to work only on a regular + /// file. Check for things like /dev/null, any block special file, or + /// other things that aren't "regular" regular files. + /// @returns true if the file is S_ISREG. + /// @brief Determines if the file is a regular file + bool isRegularFile() const; + + /// This function determines if the path name references an executable + /// file in the file system. This function checks for the existence and + /// executability (by the current program) of the file. + /// @returns true if the pathname references an executable file. + /// @brief Determines if the path is an executable file in the file + /// system. + bool canExecute() const; + + /// This function builds a list of paths that are the names of the + /// files and directories in a directory. + /// @returns true if an error occurs, true otherwise + /// @brief Build a list of directory's contents. + bool getDirectoryContents( + std::set &paths, ///< The resulting list of file & directory names + std::string* ErrMsg ///< Optional place to return an error message. + ) const; + + /// @} + /// @name Path Mutators + /// @{ + public: + /// The path name is cleared and becomes empty. This is an invalid + /// path name but is the *only* invalid path name. This is provided + /// so that path objects can be used to indicate the lack of a + /// valid path being found. + /// @brief Make the path empty. + void clear() { path.clear(); } + + /// This method sets the Path object to \p unverified_path. This can fail + /// if the \p unverified_path does not pass the syntactic checks of the + /// isValid() method. If verification fails, the Path object remains + /// unchanged and false is returned. Otherwise true is returned and the + /// Path object takes on the path value of \p unverified_path + /// @returns true if the path was set, false otherwise. + /// @param unverified_path The path to be set in Path object. + /// @brief Set a full path from a StringRef + bool set(StringRef unverified_path); + + /// One path component is removed from the Path. If only one component is + /// present in the path, the Path object becomes empty. If the Path object + /// is empty, no change is made. + /// @returns false if the path component could not be removed. + /// @brief Removes the last directory component of the Path. + bool eraseComponent(); + + /// The \p component is added to the end of the Path if it is a legal + /// name for the operating system. A directory separator will be added if + /// needed. + /// @returns false if the path component could not be added. + /// @brief Appends one path component to the Path. + bool appendComponent(StringRef component); + + /// A period and the \p suffix are appended to the end of the pathname. + /// When the \p suffix is empty, no action is performed. + /// @brief Adds a period and the \p suffix to the end of the pathname. + void appendSuffix(StringRef suffix); + + /// The suffix of the filename is erased. The suffix begins with and + /// includes the last . character in the filename after the last directory + /// separator and extends until the end of the name. If no . character is + /// after the last directory separator, then the file name is left + /// unchanged (i.e. it was already without a suffix) but the function + /// returns false. + /// @returns false if there was no suffix to remove, true otherwise. + /// @brief Remove the suffix from a path name. + bool eraseSuffix(); + + /// The current Path name is made unique in the file system. Upon return, + /// the Path will have been changed to make a unique file in the file + /// system or it will not have been changed if the current path name is + /// already unique. + /// @throws std::string if an unrecoverable error occurs. + /// @brief Make the current path name unique in the file system. + bool makeUnique( bool reuse_current /*= true*/, std::string* ErrMsg ); + + /// The current Path name is made absolute by prepending the + /// current working directory if necessary. + LLVM_ATTRIBUTE_DEPRECATED( + void makeAbsolute(), + LLVM_PATH_DEPRECATED_MSG(fs::make_absolute)); + + /// @} + /// @name Disk Mutators + /// @{ + public: + /// This method attempts to make the file referenced by the Path object + /// available for reading so that the canRead() method will return true. + /// @brief Make the file readable; + bool makeReadableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for writing so that the canWrite() method will return true. + /// @brief Make the file writable; + bool makeWriteableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for execution so that the canExecute() method will return + /// true. + /// @brief Make the file readable; + bool makeExecutableOnDisk(std::string* ErrMsg = 0); + + /// This method allows the last modified time stamp and permission bits + /// to be set on the disk object referenced by the Path. + /// @throws std::string if an error occurs. + /// @returns true on error. + /// @brief Set the status information. + bool setStatusInfoOnDisk(const FileStatus &SI, + std::string *ErrStr = 0) const; + + /// This method attempts to create a directory in the file system with the + /// same name as the Path object. The \p create_parents parameter controls + /// whether intermediate directories are created or not. if \p + /// create_parents is true, then an attempt will be made to create all + /// intermediate directories, as needed. If \p create_parents is false, + /// then only the final directory component of the Path name will be + /// created. The created directory will have no entries. + /// @returns true if the directory could not be created, false otherwise + /// @brief Create the directory this Path refers to. + bool createDirectoryOnDisk( + bool create_parents = false, ///< Determines whether non-existent + ///< directory components other than the last one (the "parents") + ///< are created or not. + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This method attempts to create a file in the file system with the same + /// name as the Path object. The intermediate directories must all exist + /// at the time this method is called. Use createDirectoriesOnDisk to + /// accomplish that. The created file will be empty upon return from this + /// function. + /// @returns true if the file could not be created, false otherwise. + /// @brief Create the file this Path refers to. + bool createFileOnDisk( + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This is like createFile except that it creates a temporary file. A + /// unique temporary file name is generated based on the contents of + /// \p this before the call. The new name is assigned to \p this and the + /// file is created. Note that this will both change the Path object + /// *and* create the corresponding file. This function will ensure that + /// the newly generated temporary file name is unique in the file system. + /// @returns true if the file couldn't be created, false otherwise. + /// @brief Create a unique temporary file + bool createTemporaryFileOnDisk( + bool reuse_current = false, ///< When set to true, this parameter + ///< indicates that if the current file name does not exist then + ///< it will be used without modification. + std::string* ErrMsg = 0 ///< Optional place to put error messages + ); + + /// This method renames the file referenced by \p this as \p newName. The + /// file referenced by \p this must exist. The file referenced by + /// \p newName does not need to exist. + /// @returns true on error, false otherwise + /// @brief Rename one file as another. + bool renamePathOnDisk(const Path& newName, std::string* ErrMsg); + + /// This method attempts to destroy the file or directory named by the + /// last component of the Path. If the Path refers to a directory and the + /// \p destroy_contents is false, an attempt will be made to remove just + /// the directory (the final Path component). If \p destroy_contents is + /// true, an attempt will be made to remove the entire contents of the + /// directory, recursively. If the Path refers to a file, the + /// \p destroy_contents parameter is ignored. + /// @param destroy_contents Indicates whether the contents of a destroyed + /// @param Err An optional string to receive an error message. + /// directory should also be destroyed (recursively). + /// @returns false if the file/directory was destroyed, true on error. + /// @brief Removes the file or directory from the filesystem. + bool eraseFromDisk(bool destroy_contents = false, + std::string *Err = 0) const; + + + /// MapInFilePages - This is a low level system API to map in the file + /// that is currently opened as FD into the current processes' address + /// space for read only access. This function may return null on failure + /// or if the system cannot provide the following constraints: + /// 1) The pages must be valid after the FD is closed, until + /// UnMapFilePages is called. + /// 2) Any padding after the end of the file must be zero filled, if + /// present. + /// 3) The pages must be contiguous. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static const char *MapInFilePages(int FD, uint64_t FileSize); + + /// UnMapFilePages - Free pages mapped into the current process by + /// MapInFilePages. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static void UnMapFilePages(const char *Base, uint64_t FileSize); + + /// @} + /// @name Data + /// @{ + protected: + // Our win32 implementation relies on this string being mutable. + mutable std::string path; ///< Storage for the path name. + + + /// @} + }; + + /// This class is identical to Path class except it allows you to obtain the + /// file status of the Path as well. The reason for the distinction is one of + /// efficiency. First, the file status requires additional space and the space + /// is incorporated directly into PathWithStatus without an additional malloc. + /// Second, obtaining status information is an expensive operation on most + /// operating systems so we want to be careful and explicit about where we + /// allow this operation in LLVM. + /// @brief Path with file status class. + class PathWithStatus : public Path { + /// @name Constructors + /// @{ + public: + /// @brief Default constructor + PathWithStatus() : Path(), status(), fsIsValid(false) {} + + /// @brief Copy constructor + PathWithStatus(const PathWithStatus &that) + : Path(static_cast(that)), status(that.status), + fsIsValid(that.fsIsValid) {} + + /// This constructor allows construction from a Path object + /// @brief Path constructor + PathWithStatus(const Path &other) + : Path(other), status(), fsIsValid(false) {} + + /// This constructor will accept a char* or std::string as a path. No + /// checking is done on this path to determine if it is valid. To + /// determine validity of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + StringRef p ///< The path to assign. + ) : Path(p), status(), fsIsValid(false) {} + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + const char *StrStart, ///< Pointer to the first character of the path + unsigned StrLen ///< Length of the path. + ) : Path(StrStart, StrLen), status(), fsIsValid(false) {} + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const PathWithStatus &that) { + static_cast(*this) = static_cast(that); + status = that.status; + fsIsValid = that.fsIsValid; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const Path &that) { + static_cast(*this) = static_cast(that); + fsIsValid = false; + return *this; + } + + /// @} + /// @name Methods + /// @{ + public: + /// This function returns status information about the file. The type of + /// path (file or directory) is updated to reflect the actual contents + /// of the file system. + /// @returns 0 on failure, with Error explaining why (if non-zero) + /// @returns a pointer to a FileStatus structure on success. + /// @brief Get file status. + const FileStatus *getFileStatus( + bool forceUpdate = false, ///< Force an update from the file system + std::string *Error = 0 ///< Optional place to return an error msg. + ) const; + + /// @} + /// @name Data + /// @{ + private: + mutable FileStatus status; ///< Status information. + mutable bool fsIsValid; ///< Whether we've obtained it or not + + /// @} + }; + + /// This enumeration delineates the kinds of files that LLVM knows about. + enum LLVMFileType { + Unknown_FileType = 0, ///< Unrecognized file + Bitcode_FileType, ///< Bitcode file + Archive_FileType, ///< ar style archive file + ELF_Relocatable_FileType, ///< ELF Relocatable object file + ELF_Executable_FileType, ///< ELF Executable image + ELF_SharedObject_FileType, ///< ELF dynamically linked shared lib + ELF_Core_FileType, ///< ELF core image + Mach_O_Object_FileType, ///< Mach-O Object file + Mach_O_Executable_FileType, ///< Mach-O Executable + Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM + Mach_O_Core_FileType, ///< Mach-O Core File + Mach_O_PreloadExecutable_FileType, ///< Mach-O Preloaded Executable + Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib + Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker + Mach_O_Bundle_FileType, ///< Mach-O Bundle file + Mach_O_DynamicallyLinkedSharedLibStub_FileType, ///< Mach-O Shared lib stub + COFF_FileType ///< COFF object file or lib + }; + + /// This utility function allows any memory block to be examined in order + /// to determine its file type. + LLVMFileType IdentifyFileType(const char*magic, unsigned length); + + /// This function can be used to copy the file specified by Src to the + /// file specified by Dest. If an error occurs, Dest is removed. + /// @returns true if an error occurs, false otherwise + /// @brief Copy one file to another. + bool CopyFile(const Path& Dest, const Path& Src, std::string* ErrMsg); + + /// This is the OS-specific path separator: a colon on Unix or a semicolon + /// on Windows. + extern const char PathSeparator; +} + +} + +#endif diff --git a/final/include/llvm/Support/PathV2.h b/final/include/llvm/Support/PathV2.h new file mode 100644 index 00000000000..251563398fb --- /dev/null +++ b/final/include/llvm/Support/PathV2.h @@ -0,0 +1,347 @@ +//===- llvm/Support/PathV2.h - Path Operating System Concept ----*- 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 llvm::sys::path namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATHV2_H +#define LLVM_SUPPORT_PATHV2_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +namespace sys { +namespace path { + +/// @name Lexical Component Iterator +/// @{ + +/// @brief Path iterator. +/// +/// This is a bidirectional iterator that iterates over the individual +/// components in \a path. The forward traversal order is as follows: +/// * The root-name element, if present. +/// * The root-directory element, if present. +/// * Each successive filename element, if present. +/// * Dot, if one or more trailing non-root slash characters are present. +/// The backwards traversal order is the reverse of forward traversal. +/// +/// Iteration examples. Each component is separated by ',': +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// +class const_iterator { + StringRef Path; //< The entire path. + StringRef Component; //< The current component. Not necessarily in Path. + size_t Position; //< The iterators current position within Path. + + // An end iterator has Position = Path.size() + 1. + friend const_iterator begin(StringRef path); + friend const_iterator end(StringRef path); + +public: + typedef const StringRef value_type; + typedef ptrdiff_t difference_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + const_iterator &operator++(); // preincrement + const_iterator &operator++(int); // postincrement + const_iterator &operator--(); // predecrement + const_iterator &operator--(int); // postdecrement + bool operator==(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const; + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const const_iterator &RHS) const; +}; + +typedef std::reverse_iterator reverse_iterator; + +/// @brief Get begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first component of \a path. +const_iterator begin(StringRef path); + +/// @brief Get end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the end of \a path. +const_iterator end(StringRef path); + +/// @brief Get reverse begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first reverse component of \a path. +inline reverse_iterator rbegin(StringRef path) { + return reverse_iterator(end(path)); +} + +/// @brief Get reverse end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the reverse end of \a path. +inline reverse_iterator rend(StringRef path) { + return reverse_iterator(begin(path)); +} + +/// @} +/// @name Lexical Modifiers +/// @{ + +/// @brief Remove the last component from \a path unless it is the root dir. +/// +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// / => / +/// +/// @param path A path that is modified to not have a file component. +void remove_filename(SmallVectorImpl &path); + +/// @brief Replace the file extension of \a path with \a extension. +/// +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// +/// @param path A path that has its extension replaced with \a extension. +/// @param extension The extension to be added. It may be empty. It may also +/// optionally start with a '.', if it does not, one will be +/// prepended. +void replace_extension(SmallVectorImpl &path, const Twine &extension); + +/// @brief Append to path. +/// +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// +/// @param path Set to \a path + \a component. +/// @param component The component to be appended to \a path. +void append(SmallVectorImpl &path, const Twine &a, + const Twine &b = "", + const Twine &c = "", + const Twine &d = ""); + +/// @brief Append to path. +/// +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// +/// @param path Set to \a path + [\a begin, \a end). +/// @param begin Start of components to append. +/// @param end One past the end of components to append. +void append(SmallVectorImpl &path, + const_iterator begin, const_iterator end); + +/// @} +/// @name Transforms (or some other better name) +/// @{ + +/// Convert path to the native form. This is used to give paths to users and +/// operating system calls in the platform's normal way. For example, on Windows +/// all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +/// @param result Holds the result of the transformation. +void native(const Twine &path, SmallVectorImpl &result); + +/// @} +/// @name Lexical Observers +/// @{ + +/// @brief Get root name. +/// +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => +/// +/// @param path Input path. +/// @result The root name of \a path if it has one, otherwise "". +const StringRef root_name(StringRef path); + +/// @brief Get root directory. +/// +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => +/// +/// @param path Input path. +/// @result The root directory of \a path if it has one, otherwise +/// "". +const StringRef root_directory(StringRef path); + +/// @brief Get root path. +/// +/// Equivalent to root_name + root_directory. +/// +/// @param path Input path. +/// @result The root path of \a path if it has one, otherwise "". +const StringRef root_path(StringRef path); + +/// @brief Get relative path. +/// +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// +/// @param path Input path. +/// @result The path starting after root_path if one exists, otherwise "". +const StringRef relative_path(StringRef path); + +/// @brief Get parent path. +/// +/// / => +/// /foo => / +/// foo/../bar => foo/.. +/// +/// @param path Input path. +/// @result The parent path of \a path if one exists, otherwise "". +const StringRef parent_path(StringRef path); + +/// @brief Get filename. +/// +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// +/// @param path Input path. +/// @result The filename part of \a path. This is defined as the last component +/// of \a path. +const StringRef filename(StringRef path); + +/// @brief Get stem. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename ending at (but not including) the last dot. Otherwise +/// it is filename. +/// +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => +/// /foo/. => . +/// /foo/.. => .. +/// +/// @param path Input path. +/// @result The stem of \a path. +const StringRef stem(StringRef path); + +/// @brief Get extension. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename starting at (and including) the last dot, and ending +/// at the end of \a path. Otherwise "". +/// +/// /foo/bar.txt => .txt +/// /foo/bar => +/// /foo/.txt => .txt +/// +/// @param path Input path. +/// @result The extension of \a path. +const StringRef extension(StringRef path); + +/// @brief Check whether the given char is a path separator on the host OS. +/// +/// @param value a character +/// @result true if \a value is a path separator character on the host OS +bool is_separator(char value); + +/// @brief Has root name? +/// +/// root_name != "" +/// +/// @param path Input path. +/// @result True if the path has a root name, false otherwise. +bool has_root_name(const Twine &path); + +/// @brief Has root directory? +/// +/// root_directory != "" +/// +/// @param path Input path. +/// @result True if the path has a root directory, false otherwise. +bool has_root_directory(const Twine &path); + +/// @brief Has root path? +/// +/// root_path != "" +/// +/// @param path Input path. +/// @result True if the path has a root path, false otherwise. +bool has_root_path(const Twine &path); + +/// @brief Has relative path? +/// +/// relative_path != "" +/// +/// @param path Input path. +/// @result True if the path has a relative path, false otherwise. +bool has_relative_path(const Twine &path); + +/// @brief Has parent path? +/// +/// parent_path != "" +/// +/// @param path Input path. +/// @result True if the path has a parent path, false otherwise. +bool has_parent_path(const Twine &path); + +/// @brief Has filename? +/// +/// filename != "" +/// +/// @param path Input path. +/// @result True if the path has a filename, false otherwise. +bool has_filename(const Twine &path); + +/// @brief Has stem? +/// +/// stem != "" +/// +/// @param path Input path. +/// @result True if the path has a stem, false otherwise. +bool has_stem(const Twine &path); + +/// @brief Has extension? +/// +/// extension != "" +/// +/// @param path Input path. +/// @result True if the path has a extension, false otherwise. +bool has_extension(const Twine &path); + +/// @brief Is path absolute? +/// +/// @param path Input path. +/// @result True if the path is absolute, false if it is not. +bool is_absolute(const Twine &path); + +/// @brief Is path relative? +/// +/// @param path Input path. +/// @result True if the path is relative, false if it is not. +bool is_relative(const Twine &path); + +} // end namespace path +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/PatternMatch.h b/final/include/llvm/Support/PatternMatch.h new file mode 100644 index 00000000000..948ae5176ee --- /dev/null +++ b/final/include/llvm/Support/PatternMatch.h @@ -0,0 +1,665 @@ +//===-- llvm/Support/PatternMatch.h - Match on the LLVM IR ------*- 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 a simple and efficient mechanism for performing general +// tree-based pattern matches on the LLVM IR. The power of these routines is +// that it allows you to write concise patterns that are expressive and easy to +// understand. The other major advantage of this is that it allows you to +// trivially capture/bind elements in the pattern to variables. For example, +// you can do something like this: +// +// Value *Exp = ... +// Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) +// if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), +// m_And(m_Value(Y), m_ConstantInt(C2))))) { +// ... Pattern is matched and variables are bound ... +// } +// +// This is primarily useful to things like the instruction combiner, but can +// also be useful for static analysis tools or code generators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATTERNMATCH_H +#define LLVM_SUPPORT_PATTERNMATCH_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +namespace llvm { +namespace PatternMatch { + +template +bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); +} + +template +struct class_match { + template + bool match(ITy *V) { return isa(V); } +}; + +/// m_Value() - Match an arbitrary value and ignore it. +inline class_match m_Value() { return class_match(); } +/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. +inline class_match m_ConstantInt() { + return class_match(); +} +/// m_Undef() - Match an arbitrary undef constant. +inline class_match m_Undef() { return class_match(); } + +inline class_match m_Constant() { return class_match(); } + +struct match_zero { + template + bool match(ITy *V) { + if (const Constant *C = dyn_cast(V)) + return C->isNullValue(); + return false; + } +}; + +/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. +inline match_zero m_Zero() { return match_zero(); } + + +struct apint_match { + const APInt *&Res; + apint_match(const APInt *&R) : Res(R) {} + template + bool match(ITy *V) { + if (ConstantInt *CI = dyn_cast(V)) { + Res = &CI->getValue(); + return true; + } + if (ConstantVector *CV = dyn_cast(V)) + if (ConstantInt *CI = + dyn_cast_or_null(CV->getSplatValue())) { + Res = &CI->getValue(); + return true; + } + return false; + } +}; + +/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// specified pointer to the contained APInt. +inline apint_match m_APInt(const APInt *&Res) { return Res; } + + +template +struct constantint_match { + template + bool match(ITy *V) { + if (const ConstantInt *CI = dyn_cast(V)) { + const APInt &CIV = CI->getValue(); + if (Val >= 0) + return CIV == static_cast(Val); + // If Val is negative, and CI is shorter than it, truncate to the right + // number of bits. If it is larger, then we have to sign extend. Just + // compare their negated values. + return -CIV == -Val; + } + return false; + } +}; + +/// m_ConstantInt - Match a ConstantInt with a specific value. +template +inline constantint_match m_ConstantInt() { + return constantint_match(); +} + +/// cst_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate. +template +struct cst_pred_ty : public Predicate { + template + bool match(ITy *V) { + if (const ConstantInt *CI = dyn_cast(V)) + return this->isValue(CI->getValue()); + if (const ConstantVector *CV = dyn_cast(V)) + if (ConstantInt *CI = dyn_cast_or_null(CV->getSplatValue())) + return this->isValue(CI->getValue()); + return false; + } +}; + +/// api_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate, and bind them to an APInt. +template +struct api_pred_ty : public Predicate { + const APInt *&Res; + api_pred_ty(const APInt *&R) : Res(R) {} + template + bool match(ITy *V) { + if (const ConstantInt *CI = dyn_cast(V)) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + if (const ConstantVector *CV = dyn_cast(V)) + if (ConstantInt *CI = dyn_cast_or_null(CV->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + return false; + } +}; + + +struct is_one { + bool isValue(const APInt &C) { return C == 1; } +}; + +/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +inline cst_pred_ty m_One() { return cst_pred_ty(); } +inline api_pred_ty m_One(const APInt *&V) { return V; } + +struct is_all_ones { + bool isValue(const APInt &C) { return C.isAllOnesValue(); } +}; + +/// m_AllOnes() - Match an integer or vector with all bits set to true. +inline cst_pred_ty m_AllOnes() {return cst_pred_ty();} +inline api_pred_ty m_AllOnes(const APInt *&V) { return V; } + +struct is_sign_bit { + bool isValue(const APInt &C) { return C.isSignBit(); } +}; + +/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty m_SignBit() {return cst_pred_ty();} +inline api_pred_ty m_SignBit(const APInt *&V) { return V; } + +struct is_power2 { + bool isValue(const APInt &C) { return C.isPowerOf2(); } +}; + +/// m_Power2() - Match an integer or vector power of 2. +inline cst_pred_ty m_Power2() { return cst_pred_ty(); } +inline api_pred_ty m_Power2(const APInt *&V) { return V; } + +template +struct bind_ty { + Class *&VR; + bind_ty(Class *&V) : VR(V) {} + + template + bool match(ITy *V) { + if (Class *CV = dyn_cast(V)) { + VR = CV; + return true; + } + return false; + } +}; + +/// m_Value - Match a value, capturing it if we match. +inline bind_ty m_Value(Value *&V) { return V; } + +/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } + +/// m_Constant - Match a Constant, capturing the value if we match. +inline bind_ty m_Constant(Constant *&C) { return C; } + +/// specificval_ty - Match a specified Value*. +struct specificval_ty { + const Value *Val; + specificval_ty(const Value *V) : Val(V) {} + + template + bool match(ITy *V) { + return V == Val; + } +}; + +/// m_Specific - Match if we have a specific specified value. +inline specificval_ty m_Specific(const Value *V) { return V; } + + +//===----------------------------------------------------------------------===// +// Matchers for specific binary operators. +// + +template +struct BinaryOp_match { + LHS_t L; + RHS_t R; + + BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Opcode) { + BinaryOperator *I = cast(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template +inline BinaryOp_match +m_Add(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_FAdd(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_Sub(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_FSub(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_Mul(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_FMul(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_UDiv(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_SDiv(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_FDiv(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_URem(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_SRem(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_FRem(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_And(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_Or(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_Xor(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_Shl(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_LShr(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +template +inline BinaryOp_match +m_AShr(const LHS &L, const RHS &R) { + return BinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Class that matches two different binary ops. +// +template +struct BinOp2_match { + LHS_t L; + RHS_t R; + + BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Opc1 || + V->getValueID() == Value::InstructionVal + Opc2) { + BinaryOperator *I = cast(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast(V)) + return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && + L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); + return false; + } +}; + +/// m_Shr - Matches LShr or AShr. +template +inline BinOp2_match +m_Shr(const LHS &L, const RHS &R) { + return BinOp2_match(L, R); +} + +/// m_LogicalShift - Matches LShr or Shl. +template +inline BinOp2_match +m_LogicalShift(const LHS &L, const RHS &R) { + return BinOp2_match(L, R); +} + +/// m_IDiv - Matches UDiv and SDiv. +template +inline BinOp2_match +m_IDiv(const LHS &L, const RHS &R) { + return BinOp2_match(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for CmpInst classes +// + +template +struct CmpClass_match { + PredicateTy &Predicate; + LHS_t L; + RHS_t R; + + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) + : Predicate(Pred), L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (Class *I = dyn_cast(V)) + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { + Predicate = I->getPredicate(); + return true; + } + return false; + } +}; + +template +inline CmpClass_match +m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template +inline CmpClass_match +m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for SelectInst classes +// + +template +struct SelectClass_match { + Cond_t C; + LHS_t L; + RHS_t R; + + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, + const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} + + template + bool match(OpTy *V) { + if (SelectInst *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && + L.match(I->getOperand(1)) && + R.match(I->getOperand(2)); + return false; + } +}; + +template +inline SelectClass_match +m_Select(const Cond &C, const LHS &L, const RHS &R) { + return SelectClass_match(C, L, R); +} + +/// m_SelectCst - This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template +inline SelectClass_match, constantint_match > +m_SelectCst(const Cond &C) { + return m_Select(C, m_ConstantInt(), m_ConstantInt()); +} + + +//===----------------------------------------------------------------------===// +// Matchers for CastInst classes +// + +template +struct CastClass_match { + Op_t Op; + + CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} + + template + bool match(OpTy *V) { + if (CastInst *I = dyn_cast(V)) + return I->getOpcode() == Opcode && Op.match(I->getOperand(0)); + if (ConstantExpr *CE = dyn_cast(V)) + return CE->getOpcode() == Opcode && Op.match(CE->getOperand(0)); + return false; + } +}; + +/// m_BitCast +template +inline CastClass_match +m_BitCast(const OpTy &Op) { + return CastClass_match(Op); +} + +/// m_PtrToInt +template +inline CastClass_match +m_PtrToInt(const OpTy &Op) { + return CastClass_match(Op); +} + +/// m_Trunc +template +inline CastClass_match +m_Trunc(const OpTy &Op) { + return CastClass_match(Op); +} + +/// m_SExt +template +inline CastClass_match +m_SExt(const OpTy &Op) { + return CastClass_match(Op); +} + +/// m_ZExt +template +inline CastClass_match +m_ZExt(const OpTy &Op) { + return CastClass_match(Op); +} + + +//===----------------------------------------------------------------------===// +// Matchers for unary operators +// + +template +struct not_match { + LHS_t L; + + not_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Xor) + return matchIfNot(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Xor) + return matchIfNot(CE->getOperand(0), CE->getOperand(1)); + return false; + } +private: + bool matchIfNot(Value *LHS, Value *RHS) { + if (ConstantInt *CI = dyn_cast(RHS)) + return CI->isAllOnesValue() && L.match(LHS); + if (ConstantVector *CV = dyn_cast(RHS)) + return CV->isAllOnesValue() && L.match(LHS); + return false; + } +}; + +template +inline not_match m_Not(const LHS &L) { return L; } + + +template +struct neg_match { + LHS_t L; + + neg_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::Sub) + return matchIfNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::Sub) + return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); + return false; + } +private: + bool matchIfNeg(Value *LHS, Value *RHS) { + if (ConstantInt *C = dyn_cast(LHS)) + return C->isZero() && L.match(RHS); + return false; + } +}; + +/// m_Neg - Match an integer negate. +template +inline neg_match m_Neg(const LHS &L) { return L; } + + +template +struct fneg_match { + LHS_t L; + + fneg_match(const LHS_t &LHS) : L(LHS) {} + + template + bool match(OpTy *V) { + if (Instruction *I = dyn_cast(V)) + if (I->getOpcode() == Instruction::FSub) + return matchIfFNeg(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::FSub) + return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); + return false; + } +private: + bool matchIfFNeg(Value *LHS, Value *RHS) { + if (ConstantFP *C = dyn_cast(LHS)) + return C->isNegativeZeroValue() && L.match(RHS); + return false; + } +}; + +/// m_FNeg - Match a floating point negate. +template +inline fneg_match m_FNeg(const LHS &L) { return L; } + + +//===----------------------------------------------------------------------===// +// Matchers for control flow. +// + +template +struct brc_match { + Cond_t Cond; + BasicBlock *&T, *&F; + brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) + : Cond(C), T(t), F(f) { + } + + template + bool match(OpTy *V) { + if (BranchInst *BI = dyn_cast(V)) + if (BI->isConditional() && Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; + } + return false; + } +}; + +template +inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { + return brc_match(C, T, F); +} + +} // end namespace PatternMatch +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/PluginLoader.h b/final/include/llvm/Support/PluginLoader.h new file mode 100644 index 00000000000..bdbb134b28e --- /dev/null +++ b/final/include/llvm/Support/PluginLoader.h @@ -0,0 +1,37 @@ +//===-- llvm/Support/PluginLoader.h - Plugin Loader for Tools ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A tool can #include this file to get a -load option that allows the user to +// load arbitrary shared objects into the tool's address space. Note that this +// header can only be included by a program ONCE, so it should never to used by +// library authors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PLUGINLOADER_H +#define LLVM_SUPPORT_PLUGINLOADER_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + struct PluginLoader { + void operator=(const std::string &Filename); + static unsigned getNumPlugins(); + static std::string& getPlugin(unsigned num); + }; + +#ifndef DONT_GET_PLUGIN_LOADER_OPTION + // This causes operator= above to be invoked for every -load option. + static cl::opt > + LoadOpt("load", cl::ZeroOrMore, cl::value_desc("pluginfilename"), + cl::desc("Load the specified plugin")); +#endif +} + +#endif diff --git a/final/include/llvm/Support/PointerLikeTypeTraits.h b/final/include/llvm/Support/PointerLikeTypeTraits.h new file mode 100644 index 00000000000..83708213921 --- /dev/null +++ b/final/include/llvm/Support/PointerLikeTypeTraits.h @@ -0,0 +1,81 @@ +//===- llvm/Support/PointerLikeTypeTraits.h - Pointer Traits ----*- 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 PointerLikeTypeTraits class. This allows data +// structures to reason about pointers and other things that are pointer sized. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H +#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// PointerLikeTypeTraits - This is a traits object that is used to handle +/// pointer types and things that are just wrappers for pointers as a uniform +/// entity. +template +class PointerLikeTypeTraits { + // getAsVoidPointer + // getFromVoidPointer + // getNumLowBitsAvailable +}; + +// Provide PointerLikeTypeTraits for non-cvr pointers. +template +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(T* P) { return P; } + static inline T *getFromVoidPointer(void *P) { + return static_cast(P); + } + + /// Note, we assume here that malloc returns objects at least 4-byte aligned. + /// However, this may be wrong, or pointers may be from something other than + /// malloc. In this case, you should specialize this template to reduce this. + /// + /// All clients should use assertions to do a run-time check to ensure that + /// this is actually true. + enum { NumLowBitsAvailable = 2 }; +}; + +// Provide PointerLikeTypeTraits for const pointers. +template +class PointerLikeTypeTraits { + typedef PointerLikeTypeTraits NonConst; + +public: + static inline const void *getAsVoidPointer(const T* P) { + return NonConst::getAsVoidPointer(const_cast(P)); + } + static inline const T *getFromVoidPointer(const void *P) { + return NonConst::getFromVoidPointer(const_cast(P)); + } + enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable }; +}; + +// Provide PointerLikeTypeTraits for uintptr_t. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(uintptr_t P) { + return reinterpret_cast(P); + } + static inline uintptr_t getFromVoidPointer(void *P) { + return reinterpret_cast(P); + } + // No bits are available! + enum { NumLowBitsAvailable = 0 }; +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/PredIteratorCache.h b/final/include/llvm/Support/PredIteratorCache.h new file mode 100644 index 00000000000..bb66a8ed58b --- /dev/null +++ b/final/include/llvm/Support/PredIteratorCache.h @@ -0,0 +1,70 @@ +//===- llvm/Support/PredIteratorCache.h - pred_iterator Cache ---*- 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 PredIteratorCache class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CFG.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" + +#ifndef LLVM_SUPPORT_PREDITERATORCACHE_H +#define LLVM_SUPPORT_PREDITERATORCACHE_H + +namespace llvm { + + /// PredIteratorCache - This class is an extremely trivial cache for + /// predecessor iterator queries. This is useful for code that repeatedly + /// wants the predecessor list for the same blocks. + class PredIteratorCache { + /// BlockToPredsMap - Pointer to null-terminated list. + DenseMap BlockToPredsMap; + DenseMap BlockToPredCountMap; + + /// Memory - This is the space that holds cached preds. + BumpPtrAllocator Memory; + public: + + /// GetPreds - Get a cached list for the null-terminated predecessor list of + /// the specified block. This can be used in a loop like this: + /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) + /// use(*PI); + /// instead of: + /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + BasicBlock **GetPreds(BasicBlock *BB) { + BasicBlock **&Entry = BlockToPredsMap[BB]; + if (Entry) return Entry; + + SmallVector PredCache(pred_begin(BB), pred_end(BB)); + PredCache.push_back(0); // null terminator. + + BlockToPredCountMap[BB] = PredCache.size()-1; + + Entry = Memory.Allocate(PredCache.size()); + std::copy(PredCache.begin(), PredCache.end(), Entry); + return Entry; + } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } + + /// clear - Remove all information. + void clear() { + BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); + Memory.Reset(); + } + }; +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/PrettyStackTrace.h b/final/include/llvm/Support/PrettyStackTrace.h new file mode 100644 index 00000000000..6dbce393b97 --- /dev/null +++ b/final/include/llvm/Support/PrettyStackTrace.h @@ -0,0 +1,71 @@ +//===- llvm/Support/PrettyStackTrace.h - Pretty Crash Handling --*- 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 PrettyStackTraceEntry class, which is used to make +// crashes give more contextual information about what the program was doing +// when it crashed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PRETTYSTACKTRACE_H +#define LLVM_SUPPORT_PRETTYSTACKTRACE_H + +namespace llvm { + class raw_ostream; + + /// DisablePrettyStackTrace - Set this to true to disable this module. This + /// might be neccessary if the host application installs its own signal + /// handlers which conflict with the ones installed by this module. + /// Defaults to false. + extern bool DisablePrettyStackTrace; + + /// PrettyStackTraceEntry - This class is used to represent a frame of the + /// "pretty" stack trace that is dumped when a program crashes. You can define + /// subclasses of this and declare them on the program stack: when they are + /// constructed and destructed, they will add their symbolic frames to a + /// virtual stack trace. This gets dumped out if the program crashes. + class PrettyStackTraceEntry { + const PrettyStackTraceEntry *NextEntry; + PrettyStackTraceEntry(const PrettyStackTraceEntry &); // DO NOT IMPLEMENT + void operator=(const PrettyStackTraceEntry&); // DO NOT IMPLEMENT + public: + PrettyStackTraceEntry(); + virtual ~PrettyStackTraceEntry(); + + /// print - Emit information about this stack frame to OS. + virtual void print(raw_ostream &OS) const = 0; + + /// getNextEntry - Return the next entry in the list of frames. + const PrettyStackTraceEntry *getNextEntry() const { return NextEntry; } + }; + + /// PrettyStackTraceString - This object prints a specified string (which + /// should not contain newlines) to the stream as the stack trace when a crash + /// occurs. + class PrettyStackTraceString : public PrettyStackTraceEntry { + const char *Str; + public: + PrettyStackTraceString(const char *str) : Str(str) {} + virtual void print(raw_ostream &OS) const; + }; + + /// PrettyStackTraceProgram - This object prints a specified program arguments + /// to the stream as the stack trace when a crash occurs. + class PrettyStackTraceProgram : public PrettyStackTraceEntry { + int ArgC; + const char *const *ArgV; + public: + PrettyStackTraceProgram(int argc, const char * const*argv) + : ArgC(argc), ArgV(argv) {} + virtual void print(raw_ostream &OS) const; + }; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/Process.h b/final/include/llvm/Support/Process.h new file mode 100644 index 00000000000..33799229ff3 --- /dev/null +++ b/final/include/llvm/Support/Process.h @@ -0,0 +1,146 @@ +//===- llvm/Support/Process.h ------------------------------------*- 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 llvm::sys::Process class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROCESS_H +#define LLVM_SYSTEM_PROCESS_H + +#include "llvm/Support/TimeValue.h" + +namespace llvm { +namespace sys { + + /// This class provides an abstraction for getting information about the + /// currently executing process. + /// @since 1.4 + /// @brief An abstraction for operating system processes. + class Process { + /// @name Accessors + /// @{ + public: + /// This static function will return the operating system's virtual memory + /// page size. + /// @returns The number of bytes in a virtual memory page. + /// @brief Get the virtual memory page size + static unsigned GetPageSize(); + + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + /// @brief Return process memory usage. + static size_t GetMallocUsage(); + + /// This static function will return the total memory usage of the + /// process. This includes code, data, stack and mapped pages usage. Notei + /// that the value returned here is not necessarily the Running Set Size, + /// it is the total virtual memory usage, regardless of mapped state of + /// that memory. + static size_t GetTotalMemoryUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + static void GetTimeUsage( + TimeValue& elapsed, + ///< Returns the TimeValue::now() giving current time + TimeValue& user_time, + ///< Returns the current amount of user time for the process + TimeValue& sys_time + ///< Returns the current amount of system time for the process + ); + + /// This static function will return the process' current user id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentUserId(); + + /// This static function will return the process' current group id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentGroupId(); + + /// This function makes the necessary calls to the operating system to + /// prevent core files or any other kind of large memory dumps that can + /// occur when a program fails. + /// @brief Prevent core file generation. + static void PreventCoreFiles(); + + /// This function determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// This function determines if the given file descriptor is connected to + /// a "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool FileDescriptorIsDisplayed(int fd); + + /// This function determines the number of columns in the window + /// if standard output is connected to a "tty" or "console" + /// window. If standard output is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardOutColumns(); + + /// This function determines the number of columns in the window + /// if standard error is connected to a "tty" or "console" + /// window. If standard error is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardErrColumns(); + + /// This function determines whether the terminal connected to standard + /// output supports colors. If standard output is not connected to a + /// terminal, this function returns false. + static bool StandardOutHasColors(); + + /// This function determines whether the terminal connected to standard + /// error supports colors. If standard error is not connected to a + /// terminal, this function returns false. + static bool StandardErrHasColors(); + + /// Whether changing colors requires the output to be flushed. + /// This is needed on systems that don't support escape sequences for + /// changing colors. + static bool ColorNeedsFlush(); + + /// This function returns the colorcode escape sequences. + /// If ColorNeedsFlush() is true then this function will change the colors + /// and return an empty escape sequence. In that case it is the + /// responsibility of the client to flush the output stream prior to + /// calling this function. + static const char *OutputColor(char c, bool bold, bool bg); + + /// Same as OutputColor, but only enables the bold attribute. + static const char *OutputBold(bool bg); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + /// @} + }; +} +} + +#endif diff --git a/final/include/llvm/Support/Program.h b/final/include/llvm/Support/Program.h new file mode 100644 index 00000000000..78a495ef210 --- /dev/null +++ b/final/include/llvm/Support/Program.h @@ -0,0 +1,157 @@ +//===- llvm/Support/Program.h ------------------------------------*- 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 llvm::sys::Program class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROGRAM_H +#define LLVM_SYSTEM_PROGRAM_H + +#include "llvm/Support/Path.h" + +namespace llvm { +namespace sys { + + // TODO: Add operations to communicate with the process, redirect its I/O, + // etc. + + /// This class provides an abstraction for programs that are executable by the + /// operating system. It provides a platform generic way to find executable + /// programs from the path and to execute them in various ways. The sys::Path + /// class is used to specify the location of the Program. + /// @since 1.4 + /// @brief An abstraction for finding and executing programs. + class Program { + /// Opaque handle for target specific data. + void *Data_; + + // Noncopyable. + Program(const Program& other); + Program& operator=(const Program& other); + + /// @name Methods + /// @{ + public: + + Program(); + ~Program(); + + /// Return process ID of this program. + unsigned GetPid() const; + + /// This function executes the program using the \p arguments provided. The + /// invoked program will inherit the stdin, stdout, and stderr file + /// descriptors, the environment and other configuration settings of the + /// invoking program. If Path::executable() does not return true when this + /// function is called then a std::string is thrown. + /// @returns false in case of error, true otherwise. + /// @see FindProgramByName + /// @brief Executes the program with the given set of \p args. + bool Execute + ( const Path& path, ///< sys::Path object providing the path of the + ///< program to be executed. It is presumed this is the result of + ///< the FindProgramByName method. + const char** args, ///< A vector of strings that are passed to the + ///< program. The first element should be the name of the program. + ///< The list *must* be terminated by a null char* entry. + const char ** env = 0, ///< An optional vector of strings to use for + ///< the program's environment. If not provided, the current program's + ///< environment will be used. + const sys::Path** redirects = 0, ///< An optional array of pointers to + ///< Paths. If the array is null, no redirection is done. The array + ///< should have a size of at least three. If the pointer in the array + ///< are not null, then the inferior process's stdin(0), stdout(1), + ///< and stderr(2) will be redirected to the corresponding Paths. + ///< When an empty Path is passed in, the corresponding file + ///< descriptor will be disconnected (ie, /dev/null'd) in a portable + ///< way. + unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount + ///< of memory can be allocated by process. If memory usage will be + ///< higher limit, the child is killed and this call returns. If zero + ///< - no memory limit. + std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while invoking the + ///< program. + ); + + /// This function waits for the program to exit. This function will block + /// the current program until the invoked program exits. + /// @returns an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. A + /// negative value is the signal number on which it terminated. + /// @see Execute + /// @brief Waits for the program to exit. + int Wait + ( const Path& path, ///< The path to the child process executable. + unsigned secondsToWait, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. + std::string* ErrMsg ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while waiting. + ); + + /// This function terminates the program. + /// @returns true if an error occured. + /// @see Execute + /// @brief Terminates the program. + bool Kill + ( std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while killing the + ///< program. + ); + + /// This static constructor (factory) will attempt to locate a program in + /// the operating system's file system using some pre-determined set of + /// locations to search (e.g. the PATH on Unix). Paths with slashes are + /// returned unmodified. + /// @returns A Path object initialized to the path of the program or a + /// Path object that is empty (invalid) if the program could not be found. + /// @brief Construct a Program by finding it by name. + static Path FindProgramByName(const std::string& name); + + // These methods change the specified standard stream (stdin, + // stdout, or stderr) to binary mode. They return true if an error + // occurred + static bool ChangeStdinToBinary(); + static bool ChangeStdoutToBinary(); + static bool ChangeStderrToBinary(); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// prg.Wait(..); + /// @see Execute, Wait + static int ExecuteAndWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned secondsToWait = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// @see Execute + static void ExecuteNoWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// @} + + }; +} +} + +#endif diff --git a/final/include/llvm/Support/RWMutex.h b/final/include/llvm/Support/RWMutex.h new file mode 100644 index 00000000000..0d4cb81de39 --- /dev/null +++ b/final/include/llvm/Support/RWMutex.h @@ -0,0 +1,173 @@ +//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- 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 llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_RWMUTEX_H +#define LLVM_SYSTEM_RWMUTEX_H + +#include "llvm/Support/Threading.h" +#include + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic RWMutex class. + class RWMutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. + /// @brief Default Constructor. + explicit RWMutexImpl(); + + /// Releases and removes the lock + /// @brief Destructor + ~RWMutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by a writer, this method will wait until it can acquire + /// the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in reader mode. + bool reader_acquire(); + + /// Attempts to release the lock in reader mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in reader mode. + bool reader_release(); + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by any readers, this method will wait until it can + /// acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in writer mode. + bool writer_acquire(); + + /// Attempts to release the lock in writer mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in write mode. + bool writer_release(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + RWMutexImpl(const RWMutexImpl & original); + void operator=(const RWMutexImpl &); + /// @} + }; + + /// SmartMutex - An R/W mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template + class SmartRWMutex : public RWMutexImpl { + unsigned readers, writers; + public: + explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } + + bool reader_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + ++readers; + return true; + } + + bool reader_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(readers > 0 && "Reader lock not acquired before release!"); + --readers; + return true; + } + + bool writer_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 0 && "Writer lock already acquired!"); + ++writers; + return true; + } + + bool writer_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 1 && "Writer lock not acquired before release!"); + --writers; + return true; + } + + private: + SmartRWMutex(const SmartRWMutex & original); + void operator=(const SmartRWMutex &); + }; + typedef SmartRWMutex RWMutex; + + /// ScopedReader - RAII acquisition of a reader lock + template + struct SmartScopedReader { + SmartRWMutex& mutex; + + explicit SmartScopedReader(SmartRWMutex& m) : mutex(m) { + mutex.reader_acquire(); + } + + ~SmartScopedReader() { + mutex.reader_release(); + } + }; + typedef SmartScopedReader ScopedReader; + + /// ScopedWriter - RAII acquisition of a writer lock + template + struct SmartScopedWriter { + SmartRWMutex& mutex; + + explicit SmartScopedWriter(SmartRWMutex& m) : mutex(m) { + mutex.writer_acquire(); + } + + ~SmartScopedWriter() { + mutex.writer_release(); + } + }; + typedef SmartScopedWriter ScopedWriter; + } +} + +#endif diff --git a/final/include/llvm/Support/Recycler.h b/final/include/llvm/Support/Recycler.h new file mode 100644 index 00000000000..d8f8c789414 --- /dev/null +++ b/final/include/llvm/Support/Recycler.h @@ -0,0 +1,117 @@ +//==- llvm/Support/Recycler.h - Recycling Allocator --------------*- 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 Recycler class template. See the doxygen comment for +// Recycler for more details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RECYCLER_H +#define LLVM_SUPPORT_RECYCLER_H + +#include "llvm/ADT/ilist.h" +#include "llvm/Support/AlignOf.h" +#include + +namespace llvm { + +/// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for +/// printing statistics. +/// +void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize); + +/// RecyclerStruct - Implementation detail for Recycler. This is a +/// class that the recycler imposes on free'd memory to carve out +/// next/prev pointers. +struct RecyclerStruct { + RecyclerStruct *Prev, *Next; +}; + +template<> +struct ilist_traits : + public ilist_default_traits { + static RecyclerStruct *getPrev(const RecyclerStruct *t) { return t->Prev; } + static RecyclerStruct *getNext(const RecyclerStruct *t) { return t->Next; } + static void setPrev(RecyclerStruct *t, RecyclerStruct *p) { t->Prev = p; } + static void setNext(RecyclerStruct *t, RecyclerStruct *n) { t->Next = n; } + + mutable RecyclerStruct Sentinel; + RecyclerStruct *createSentinel() const { + return &Sentinel; + } + static void destroySentinel(RecyclerStruct *) {} + + RecyclerStruct *provideInitialHead() const { return createSentinel(); } + RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); } + static void noteHead(RecyclerStruct*, RecyclerStruct*) {} + + static void deleteNode(RecyclerStruct *) { + assert(0 && "Recycler's ilist_traits shouldn't see a deleteNode call!"); + } +}; + +/// Recycler - This class manages a linked-list of deallocated nodes +/// and facilitates reusing deallocated memory in place of allocating +/// new memory. +/// +template::Alignment> +class Recycler { + /// FreeList - Doubly-linked list of nodes that have deleted contents and + /// are not in active use. + /// + iplist FreeList; + +public: + ~Recycler() { + // If this fails, either the callee has lost track of some allocation, + // or the callee isn't tracking allocations and should just call + // clear() before deleting the Recycler. + assert(FreeList.empty() && "Non-empty recycler deleted!"); + } + + /// clear - Release all the tracked allocations to the allocator. The + /// recycler must be free of any tracked allocations before being + /// deleted; calling clear is one way to ensure this. + template + void clear(AllocatorType &Allocator) { + while (!FreeList.empty()) { + T *t = reinterpret_cast(FreeList.remove(FreeList.begin())); + Allocator.Deallocate(t); + } + } + + template + SubClass *Allocate(AllocatorType &Allocator) { + assert(sizeof(SubClass) <= Size && + "Recycler allocation size is less than object size!"); + assert(AlignOf::Alignment <= Align && + "Recycler allocation alignment is less than object alignment!"); + return !FreeList.empty() ? + reinterpret_cast(FreeList.remove(FreeList.begin())) : + static_cast(Allocator.Allocate(Size, Align)); + } + + template + T *Allocate(AllocatorType &Allocator) { + return Allocate(Allocator); + } + + template + void Deallocate(AllocatorType & /*Allocator*/, SubClass* Element) { + FreeList.push_front(reinterpret_cast(Element)); + } + + void PrintStats() { + PrintRecyclerStats(Size, Align, FreeList.size()); + } +}; + +} + +#endif diff --git a/final/include/llvm/Support/RecyclingAllocator.h b/final/include/llvm/Support/RecyclingAllocator.h new file mode 100644 index 00000000000..34ab874778c --- /dev/null +++ b/final/include/llvm/Support/RecyclingAllocator.h @@ -0,0 +1,73 @@ +//==- llvm/Support/RecyclingAllocator.h - Recycling Allocator ----*- 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 RecyclingAllocator class. See the doxygen comment for +// RecyclingAllocator for more details on the implementation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RECYCLINGALLOCATOR_H +#define LLVM_SUPPORT_RECYCLINGALLOCATOR_H + +#include "llvm/Support/Recycler.h" + +namespace llvm { + +/// RecyclingAllocator - This class wraps an Allocator, adding the +/// functionality of recycling deleted objects. +/// +template::Alignment> +class RecyclingAllocator { +private: + /// Base - Implementation details. + /// + Recycler Base; + + /// Allocator - The wrapped allocator. + /// + AllocatorType Allocator; + +public: + ~RecyclingAllocator() { Base.clear(Allocator); } + + /// Allocate - Return a pointer to storage for an object of type + /// SubClass. The storage may be either newly allocated or recycled. + /// + template + SubClass *Allocate() { return Base.template Allocate(Allocator); } + + T *Allocate() { return Base.Allocate(Allocator); } + + /// Deallocate - Release storage for the pointed-to object. The + /// storage will be kept track of and may be recycled. + /// + template + void Deallocate(SubClass* E) { return Base.Deallocate(Allocator, E); } + + void PrintStats() { Base.PrintStats(); } +}; + +} + +template +inline void *operator new(size_t, + llvm::RecyclingAllocator &Allocator) { + return Allocator.Allocate(); +} + +template +inline void operator delete(void *E, + llvm::RecyclingAllocator &A) { + A.Deallocate(E); +} + +#endif diff --git a/final/include/llvm/Support/Regex.h b/final/include/llvm/Support/Regex.h new file mode 100644 index 00000000000..b46a66889e9 --- /dev/null +++ b/final/include/llvm/Support/Regex.h @@ -0,0 +1,81 @@ +//===-- Regex.h - Regular Expression matcher implementation -*- C++ -*-----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a POSIX regular expression matcher. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGEX_H +#define LLVM_SUPPORT_REGEX_H + +#include + +struct llvm_regex; + +namespace llvm { + class StringRef; + template class SmallVectorImpl; + + class Regex { + public: + enum { + NoFlags=0, + /// Compile for matching that ignores upper/lower case distinctions. + IgnoreCase=1, + /// Compile for newline-sensitive matching. With this flag '[^' bracket + /// expressions and '.' never match newline. A ^ anchor matches the + /// null string after any newline in the string in addition to its normal + /// function, and the $ anchor matches the null string before any + /// newline in the string in addition to its normal function. + Newline=2 + }; + + /// Compiles the given POSIX Extended Regular Expression \arg Regex. + /// This implementation supports regexes and matching strings with embedded + /// NUL characters. + Regex(StringRef Regex, unsigned Flags = NoFlags); + ~Regex(); + + /// isValid - returns the error encountered during regex compilation, or + /// matching, if any. + bool isValid(std::string &Error); + + /// getNumMatches - In a valid regex, return the number of parenthesized + /// matches it contains. The number filled in by match will include this + /// many entries plus one for the whole regex (as element 0). + unsigned getNumMatches() const; + + /// matches - Match the regex against a given \arg String. + /// + /// \param Matches - If given, on a succesful match this will be filled in + /// with references to the matched group expressions (inside \arg String), + /// the first group is always the entire pattern. + /// + /// This returns true on a successful match. + bool match(StringRef String, SmallVectorImpl *Matches = 0); + + /// sub - Return the result of replacing the first match of the regex in + /// \arg String with the \arg Repl string. Backreferences like "\0" in the + /// replacement string are replaced with the appropriate match substring. + /// + /// Note that the replacement string has backslash escaping performed on + /// it. Invalid backreferences are ignored (replaced by empty strings). + /// + /// \param Error If non-null, any errors in the substitution (invalid + /// backreferences, trailing backslashes) will be recorded as a non-empty + /// string. + std::string sub(StringRef Repl, StringRef String, std::string *Error = 0); + + private: + struct llvm_regex *preg; + int error; + }; +} + +#endif // LLVM_SUPPORT_REGEX_H diff --git a/final/include/llvm/Support/Registry.h b/final/include/llvm/Support/Registry.h new file mode 100644 index 00000000000..d0375bedd9f --- /dev/null +++ b/final/include/llvm/Support/Registry.h @@ -0,0 +1,223 @@ +//=== Registry.h - Linker-supported plugin registries -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a registry template for discovering pluggable modules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGISTRY_H +#define LLVM_SUPPORT_REGISTRY_H + +namespace llvm { + /// A simple registry entry which provides only a name, description, and + /// no-argument constructor. + template + class SimpleRegistryEntry { + const char *Name, *Desc; + T *(*Ctor)(); + + public: + SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) + : Name(N), Desc(D), Ctor(C) + {} + + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + T *instantiate() const { return Ctor(); } + }; + + + /// Traits for registry entries. If using other than SimpleRegistryEntry, it + /// is necessary to define an alternate traits class. + template + class RegistryTraits { + RegistryTraits(); // Do not implement. + + public: + typedef SimpleRegistryEntry entry; + + /// nameof/descof - Accessors for name and description of entries. These are + // used to generate help for command-line options. + static const char *nameof(const entry &Entry) { return Entry.getName(); } + static const char *descof(const entry &Entry) { return Entry.getDesc(); } + }; + + + /// A global registry used in conjunction with static constructors to make + /// pluggable components (like targets or garbage collectors) "just work" when + /// linked with an executable. + template > + class Registry { + public: + typedef U traits; + typedef typename U::entry entry; + + class node; + class listener; + class iterator; + + private: + Registry(); // Do not implement. + + static void Announce(const entry &E) { + for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) + Cur->registered(E); + } + + friend class node; + static node *Head, *Tail; + + friend class listener; + static listener *ListenerHead, *ListenerTail; + + public: + /// Node in linked list of entries. + /// + class node { + friend class iterator; + + node *Next; + const entry& Val; + + public: + node(const entry& V) : Next(0), Val(V) { + if (Tail) + Tail->Next = this; + else + Head = this; + Tail = this; + + Announce(V); + } + }; + + + /// Iterators for registry entries. + /// + class iterator { + const node *Cur; + + public: + explicit iterator(const node *N) : Cur(N) {} + + bool operator==(const iterator &That) const { return Cur == That.Cur; } + bool operator!=(const iterator &That) const { return Cur != That.Cur; } + iterator &operator++() { Cur = Cur->Next; return *this; } + const entry &operator*() const { return Cur->Val; } + const entry *operator->() const { return &Cur->Val; } + }; + + static iterator begin() { return iterator(Head); } + static iterator end() { return iterator(0); } + + + /// Abstract base class for registry listeners, which are informed when new + /// entries are added to the registry. Simply subclass and instantiate: + /// + /// class CollectorPrinter : public Registry::listener { + /// protected: + /// void registered(const Registry::entry &e) { + /// cerr << "collector now available: " << e->getName() << "\n"; + /// } + /// + /// public: + /// CollectorPrinter() { init(); } // Print those already registered. + /// }; + /// + /// CollectorPrinter Printer; + /// + class listener { + listener *Prev, *Next; + + friend void Registry::Announce(const entry &E); + + protected: + /// Called when an entry is added to the registry. + /// + virtual void registered(const entry &) = 0; + + /// Calls 'registered' for each pre-existing entry. + /// + void init() { + for (iterator I = begin(), E = end(); I != E; ++I) + registered(*I); + } + + public: + listener() : Prev(ListenerTail), Next(0) { + if (Prev) + Prev->Next = this; + else + ListenerHead = this; + ListenerTail = this; + } + + virtual ~listener() { + if (Next) + Next->Prev = Prev; + else + ListenerTail = Prev; + if (Prev) + Prev->Next = Next; + else + ListenerHead = Next; + } + }; + + + /// A static registration template. Use like such: + /// + /// Registry::Add + /// X("fancy-gc", "Newfangled garbage collector."); + /// + /// Use of this template requires that: + /// + /// 1. The registered subclass has a default constructor. + // + /// 2. The registry entry type has a constructor compatible with this + /// signature: + /// + /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); + /// + /// If you have more elaborate requirements, then copy and modify. + /// + template + class Add { + entry Entry; + node Node; + + static T *CtorFn() { return new V(); } + + public: + Add(const char *Name, const char *Desc) + : Entry(Name, Desc, CtorFn), Node(Entry) {} + }; + + /// Registry::Parser now lives in llvm/Support/RegistryParser.h. + + }; + + // Since these are defined in a header file, plugins must be sure to export + // these symbols. + + template + typename Registry::node *Registry::Head; + + template + typename Registry::node *Registry::Tail; + + template + typename Registry::listener *Registry::ListenerHead; + + template + typename Registry::listener *Registry::ListenerTail; + +} + +#endif diff --git a/final/include/llvm/Support/RegistryParser.h b/final/include/llvm/Support/RegistryParser.h new file mode 100644 index 00000000000..2cc578370fe --- /dev/null +++ b/final/include/llvm/Support/RegistryParser.h @@ -0,0 +1,55 @@ +//=== RegistryParser.h - Linker-supported plugin registries -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a command-line parser for a registry. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_REGISTRY_PARSER_H +#define LLVM_SUPPORT_REGISTRY_PARSER_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Registry.h" + +namespace llvm { + + /// A command-line parser for a registry. Use like such: + /// + /// static cl::opt::entry, false, + /// RegistryParser > + /// GCOpt("gc", cl::desc("Garbage collector to use."), + /// cl::value_desc()); + /// + /// To make use of the value: + /// + /// Collector *TheCollector = GCOpt->instantiate(); + /// + template > + class RegistryParser : + public cl::parser, + public Registry::listener { + typedef U traits; + typedef typename U::entry entry; + typedef typename Registry::listener listener; + + protected: + void registered(const entry &E) { + addLiteralOption(traits::nameof(E), &E, traits::descof(E)); + } + + public: + void initialize(cl::Option &O) { + listener::init(); + cl::parser::initialize(O); + } + }; + +} + +#endif // LLVM_SUPPORT_REGISTRY_PARSER_H diff --git a/final/include/llvm/Support/SMLoc.h b/final/include/llvm/Support/SMLoc.h new file mode 100644 index 00000000000..967bf1432c6 --- /dev/null +++ b/final/include/llvm/Support/SMLoc.h @@ -0,0 +1,44 @@ +//===- SMLoc.h - Source location for use with diagnostics -------*- 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 SMLoc class. This class encapsulates a location in +// source code for use in diagnostics. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_SMLOC_H +#define SUPPORT_SMLOC_H + +namespace llvm { + +// SMLoc - Represents a location in source code. +class SMLoc { + const char *Ptr; +public: + SMLoc() : Ptr(0) {} + SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} + + bool isValid() const { return Ptr != 0; } + + bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } + bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } + + const char *getPointer() const { return Ptr; } + + static SMLoc getFromPointer(const char *Ptr) { + SMLoc L; + L.Ptr = Ptr; + return L; + } +}; + +} + +#endif + diff --git a/final/include/llvm/Support/Signals.h b/final/include/llvm/Support/Signals.h new file mode 100644 index 00000000000..9a84df68ddb --- /dev/null +++ b/final/include/llvm/Support/Signals.h @@ -0,0 +1,59 @@ +//===- llvm/Support/Signals.h - Signal Handling support ----------*- 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 some helpful functions for dealing with the possibility of +// unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SIGNALS_H +#define LLVM_SYSTEM_SIGNALS_H + +#include "llvm/Support/Path.h" + +namespace llvm { +namespace sys { + + /// This function runs all the registered interrupt handlers, including the + /// removal of files registered by RemoveFileOnSignal. + void RunInterruptHandlers(); + + /// This function registers signal handlers to ensure that if a signal gets + /// delivered that the named file is removed. + /// @brief Remove a file if a fatal signal occurs. + bool RemoveFileOnSignal(const Path &Filename, std::string* ErrMsg = 0); + + /// This function removes a file from the list of files to be removed on + /// signal delivery. + void DontRemoveFileOnSignal(const Path &Filename); + + /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// process, print a stack trace and then exit. + /// @brief Print a stack trace if a fatal signal occurs. + void PrintStackTraceOnErrorSignal(); + + /// AddSignalHandler - Add a function to be called when an abort/kill signal + /// is delivered to the process. The handler can have a cookie passed to it + /// to identify what instance of the handler it is. + void AddSignalHandler(void (*FnPtr)(void *), void *Cookie); + + /// This function registers a function to be called when the user "interrupts" + /// the program (typically by pressing ctrl-c). When the user interrupts the + /// program, the specified interrupt function is called instead of the program + /// being killed, and the interrupt function automatically disabled. Note + /// that interrupt functions are not allowed to call any non-reentrant + /// functions. An null interrupt function pointer disables the current + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. + /// @brief Register a function to be called when ctrl-c is pressed. + void SetInterruptFunction(void (*IF)()); +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/Solaris.h b/final/include/llvm/Support/Solaris.h new file mode 100644 index 00000000000..57eee2cb497 --- /dev/null +++ b/final/include/llvm/Support/Solaris.h @@ -0,0 +1,40 @@ +/*===- llvm/Support/Solaris.h ------------------------------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file contains portability fixes for Solaris hosts. + * + *===----------------------------------------------------------------------===*/ + +#ifndef LLVM_SYSTEM_SOLARIS_H +#define LLVM_SYSTEM_SOLARIS_H + +#include +#include + +#undef CS +#undef DS +#undef ES +#undef FS +#undef GS +#undef SS +#undef EAX +#undef ECX +#undef EDX +#undef EBX +#undef ESP +#undef EBP +#undef ESI +#undef EDI +#undef EIP +#undef UESP +#undef EFL +#undef ERR +#undef TRAPNO + +#endif diff --git a/final/include/llvm/Support/SourceMgr.h b/final/include/llvm/Support/SourceMgr.h new file mode 100644 index 00000000000..2a712e44bd1 --- /dev/null +++ b/final/include/llvm/Support/SourceMgr.h @@ -0,0 +1,185 @@ +//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- 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 SMDiagnostic and SourceMgr classes. This +// provides a simple substrate for diagnostics, #include handling, and other low +// level things for simple parsers. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_SOURCEMGR_H +#define SUPPORT_SOURCEMGR_H + +#include "llvm/Support/SMLoc.h" + +#include +#include +#include + +namespace llvm { + class MemoryBuffer; + class SourceMgr; + class SMDiagnostic; + class Twine; + class raw_ostream; + +/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// and handles diagnostic wrangling. +class SourceMgr { +public: + /// DiagHandlerTy - Clients that want to handle their own diagnostics in a + /// custom way can register a function pointer+context as a diagnostic + /// handler. It gets called each time PrintMessage is invoked. + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context); +private: + struct SrcBuffer { + /// Buffer - The memory buffer for the file. + MemoryBuffer *Buffer; + + /// IncludeLoc - This is the location of the parent include, or null if at + /// the top level. + SMLoc IncludeLoc; + }; + + /// Buffers - This is all of the buffers that we are reading from. + std::vector Buffers; + + // IncludeDirectories - This is the list of directories we should search for + // include files in. + std::vector IncludeDirectories; + + /// LineNoCache - This is a cache for line number queries, its implementation + /// is really private to SourceMgr.cpp. + mutable void *LineNoCache; + + DiagHandlerTy DiagHandler; + void *DiagContext; + + SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT + void operator=(const SourceMgr&); // DO NOT IMPLEMENT +public: + SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} + ~SourceMgr(); + + void setIncludeDirs(const std::vector &Dirs) { + IncludeDirectories = Dirs; + } + + /// setDiagHandler - Specify a diagnostic handler to be invoked every time + /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { + DiagHandler = DH; + DiagContext = Ctx; + } + + const SrcBuffer &getBufferInfo(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i]; + } + + const MemoryBuffer *getMemoryBuffer(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i].Buffer; + } + + SMLoc getParentIncludeLoc(unsigned i) const { + assert(i < Buffers.size() && "Invalid Buffer ID!"); + return Buffers[i].IncludeLoc; + } + + /// AddNewSourceBuffer - Add a new source buffer to this source manager. This + /// takes ownership of the memory buffer. + unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + SrcBuffer NB; + NB.Buffer = F; + NB.IncludeLoc = IncludeLoc; + Buffers.push_back(NB); + return Buffers.size()-1; + } + + /// AddIncludeFile - Search for a file with the specified name in the current + /// directory or in one of the IncludeDirs. If no file is found, this returns + /// ~0, otherwise it returns the buffer ID of the stacked file. + unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc); + + /// FindBufferContainingLoc - Return the ID of the buffer containing the + /// specified location, returning -1 if not found. + int FindBufferContainingLoc(SMLoc Loc) const; + + /// FindLineNumber - Find the line number for the specified location in the + /// specified file. This is not a fast method. + unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const; + + /// PrintMessage - Emit a message about the specified location with the + /// specified string. + /// + /// @param Type - If non-null, the kind of message (e.g., "error") which is + /// prefixed to the message. + /// @param ShowLine - Should the diagnostic show the source line. + void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type, + bool ShowLine = true) const; + + + /// GetMessage - Return an SMDiagnostic at the specified location with the + /// specified string. + /// + /// @param Type - If non-null, the kind of message (e.g., "error") which is + /// prefixed to the message. + /// @param ShowLine - Should the diagnostic show the source line. + SMDiagnostic GetMessage(SMLoc Loc, + const Twine &Msg, const char *Type, + bool ShowLine = true) const; + + +private: + void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; +}; + + +/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, +/// allowing printing to a raw_ostream as a caret diagnostic. +class SMDiagnostic { + const SourceMgr *SM; + SMLoc Loc; + std::string Filename; + int LineNo, ColumnNo; + std::string Message, LineContents; + unsigned ShowLine : 1; + +public: + // Null diagnostic. + SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), ShowLine(0) {} + // Diagnostic with no location (e.g. file not found, command line arg error). + SMDiagnostic(const std::string &filename, const std::string &Msg) + : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), + Message(Msg), ShowLine(false) {} + + // Diagnostic with a location. + SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN, + int Line, int Col, + const std::string &Msg, const std::string &LineStr, + bool showline = true) + : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), + LineContents(LineStr), ShowLine(showline) {} + + const SourceMgr *getSourceMgr() const { return SM; } + SMLoc getLoc() const { return Loc; } + const std::string &getFilename() const { return Filename; } + int getLineNo() const { return LineNo; } + int getColumnNo() const { return ColumnNo; } + const std::string &getMessage() const { return Message; } + const std::string &getLineContents() const { return LineContents; } + bool getShowLine() const { return ShowLine; } + + void Print(const char *ProgName, raw_ostream &S) const; +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Support/StandardPasses.h b/final/include/llvm/Support/StandardPasses.h new file mode 100644 index 00000000000..d774faf3864 --- /dev/null +++ b/final/include/llvm/Support/StandardPasses.h @@ -0,0 +1,242 @@ +//===-- llvm/Support/StandardPasses.h - Standard pass lists -----*- 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 utility functions for creating a "standard" set of +// optimization passes, so that compilers and tools which use optimization +// passes use the same set of standard passes. +// +// These are implemented as inline functions so that we do not have to worry +// about link issues. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STANDARDPASSES_H +#define LLVM_SUPPORT_STANDARDPASSES_H + +#include "llvm/PassManager.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" + +namespace llvm { + + static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) { + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that + // BasicAliasAnalysis wins if they disagree. This is intended to help + // support "obvious" type-punning idioms. + PM->add(createTypeBasedAliasAnalysisPass()); + PM->add(createBasicAliasAnalysisPass()); + } + + /// createStandardFunctionPasses - Add the standard list of function passes to + /// the provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + static inline void createStandardFunctionPasses(PassManagerBase *PM, + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + createStandardAliasAnalysisPasses(PM); + PM->add(createCFGSimplificationPass()); + PM->add(createScalarReplAggregatesPass()); + PM->add(createEarlyCSEPass()); + } + } + + /// createStandardModulePasses - Add the standard list of module passes to the + /// provided pass manager. + /// + /// \arg OptimizationLevel - The optimization level, corresponding to -O0, + /// -O1, etc. + /// \arg OptimizeSize - Whether the transformations should optimize for size. + /// \arg UnitAtATime - Allow passes which may make global module changes. + /// \arg UnrollLoops - Allow loop unrolling. + /// \arg SimplifyLibCalls - Allow library calls to be simplified. + /// \arg HaveExceptions - Whether the module may have code using exceptions. + /// \arg InliningPass - The inlining pass to use, if any, or null. This will + /// always be added, even at -O0.a + static inline void createStandardModulePasses(PassManagerBase *PM, + unsigned OptimizationLevel, + bool OptimizeSize, + bool UnitAtATime, + bool UnrollLoops, + bool SimplifyLibCalls, + bool HaveExceptions, + Pass *InliningPass) { + createStandardAliasAnalysisPasses(PM); + + if (OptimizationLevel == 0) { + if (InliningPass) + PM->add(InliningPass); + return; + } + + if (UnitAtATime) { + PM->add(createGlobalOptimizerPass()); // Optimize out global vars + + PM->add(createIPSCCPPass()); // IP SCCP + PM->add(createDeadArgEliminationPass()); // Dead argument elimination + } + PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE + PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE + + // Start of CallGraph SCC passes. + if (UnitAtATime && HaveExceptions) + PM->add(createPruneEHPass()); // Remove dead EH info + if (InliningPass) + PM->add(InliningPass); + if (UnitAtATime) + PM->add(createFunctionAttrsPass()); // Set readonly/readnone attrs + if (OptimizationLevel > 2) + PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args + + // Start of function pass. + // Break up aggregate allocas, using SSAUpdater. + PM->add(createScalarReplAggregatesPass(-1, false)); + PM->add(createEarlyCSEPass()); // Catch trivial redundancies + if (SimplifyLibCalls) + PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations + PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCorrelatedValuePropagationPass()); // Propagate conditionals + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createInstructionCombiningPass()); // Combine silly seq's + + PM->add(createTailCallEliminationPass()); // Eliminate tail calls + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createReassociatePass()); // Reassociate expressions + PM->add(createLoopRotatePass()); // Rotate Loop + PM->add(createLICMPass()); // Hoist loop invariants + PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3)); + PM->add(createInstructionCombiningPass()); + PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopIdiomPass()); // Recognize idioms like memset. + PM->add(createLoopDeletionPass()); // Delete dead loops + if (UnrollLoops) + PM->add(createLoopUnrollPass()); // Unroll small loops + PM->add(createInstructionCombiningPass()); // Clean up after the unroller + if (OptimizationLevel > 1) + PM->add(createGVNPass()); // Remove redundancies + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset + PM->add(createSCCPPass()); // Constant prop with SCCP + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + PM->add(createInstructionCombiningPass()); + PM->add(createJumpThreadingPass()); // Thread jumps + PM->add(createCorrelatedValuePropagationPass()); + PM->add(createDeadStoreEliminationPass()); // Delete dead stores + PM->add(createAggressiveDCEPass()); // Delete dead instructions + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + + if (UnitAtATime) { + PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes + PM->add(createDeadTypeEliminationPass()); // Eliminate dead types + + // GlobalOpt already deletes dead functions and globals, at -O3 try a + // late pass of GlobalDCE. It is capable of deleting dead cycles. + if (OptimizationLevel > 2) + PM->add(createGlobalDCEPass()); // Remove dead fns and globals. + + if (OptimizationLevel > 1) + PM->add(createConstantMergePass()); // Merge dup global constants + } + } + + static inline void addOnePass(PassManagerBase *PM, Pass *P, bool AndVerify) { + PM->add(P); + + if (AndVerify) + PM->add(createVerifierPass()); + } + + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// VerifyEach - Run the verifier after each pass. + static inline void createStandardLTOPasses(PassManagerBase *PM, + bool Internalize, + bool RunInliner, + bool VerifyEach) { + // Provide AliasAnalysis services for optimizations. + createStandardAliasAnalysisPasses(PM); + + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (Internalize) + addOnePass(PM, createInternalizePass(true), VerifyEach); + + // Propagate constants at call sites into the functions they call. This + // opens opportunities for globalopt (and inlining) by substituting function + // pointers passed as arguments to direct uses of functions. + addOnePass(PM, createIPSCCPPass(), VerifyEach); + + // Now that we internalized some globals, see if we can hack on them! + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + + // Linking modules together can lead to duplicated global constants, only + // keep one copy of each constant... + addOnePass(PM, createConstantMergePass(), VerifyEach); + + // Remove unused arguments from functions... + addOnePass(PM, createDeadArgEliminationPass(), VerifyEach); + + // Reduce the code after globalopt and ipsccp. Both can open up significant + // simplification opportunities, and both can propagate functions through + // function pointers. When this happens, we often have to resolve varargs + // calls, etc, so let instcombine do this. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + // Inline small functions + if (RunInliner) + addOnePass(PM, createFunctionInliningPass(), VerifyEach); + + addOnePass(PM, createPruneEHPass(), VerifyEach); // Remove dead EH info. + // Optimize globals again if we ran the inliner. + if (RunInliner) + addOnePass(PM, createGlobalOptimizerPass(), VerifyEach); + addOnePass(PM, createGlobalDCEPass(), VerifyEach); // Remove dead functions. + + // If we didn't decide to inline a function, check to see if we can + // transform it to pass arguments by value instead of by reference. + addOnePass(PM, createArgumentPromotionPass(), VerifyEach); + + // The IPO passes may leave cruft around. Clean up after them. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + // Break up allocas + addOnePass(PM, createScalarReplAggregatesPass(), VerifyEach); + + // Run a few AA driven optimizations here and now, to cleanup the code. + addOnePass(PM, createFunctionAttrsPass(), VerifyEach); // Add nocapture. + addOnePass(PM, createGlobalsModRefPass(), VerifyEach); // IP alias analysis. + + addOnePass(PM, createLICMPass(), VerifyEach); // Hoist loop invariants. + addOnePass(PM, createGVNPass(), VerifyEach); // Remove redundancies. + addOnePass(PM, createMemCpyOptPass(), VerifyEach); // Remove dead memcpys. + // Nuke dead stores. + addOnePass(PM, createDeadStoreEliminationPass(), VerifyEach); + + // Cleanup and simplify the code after the scalar optimizations. + addOnePass(PM, createInstructionCombiningPass(), VerifyEach); + + addOnePass(PM, createJumpThreadingPass(), VerifyEach); + + // Delete basic blocks, which optimization passes may have killed. + addOnePass(PM, createCFGSimplificationPass(), VerifyEach); + + // Now that we have optimized the program, discard unreachable functions. + addOnePass(PM, createGlobalDCEPass(), VerifyEach); + } +} + +#endif diff --git a/final/include/llvm/Support/StringPool.h b/final/include/llvm/Support/StringPool.h new file mode 100644 index 00000000000..de05e0b547a --- /dev/null +++ b/final/include/llvm/Support/StringPool.h @@ -0,0 +1,139 @@ +//===-- StringPool.h - Interned string pool ---------------------*- 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 an interned string pool, which helps reduce the cost of +// strings by using the same storage for identical strings. +// +// To intern a string: +// +// StringPool Pool; +// PooledStringPtr Str = Pool.intern("wakka wakka"); +// +// To use the value of an interned string, use operator bool and operator*: +// +// if (Str) +// cerr << "the string is" << *Str << "\n"; +// +// Pooled strings are immutable, but you can change a PooledStringPtr to point +// to another instance. So that interned strings can eventually be freed, +// strings in the string pool are reference-counted (automatically). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STRINGPOOL_H +#define LLVM_SUPPORT_STRINGPOOL_H + +#include "llvm/ADT/StringMap.h" +#include +#include + +namespace llvm { + + class PooledStringPtr; + + /// StringPool - An interned string pool. Use the intern method to add a + /// string. Strings are removed automatically as PooledStringPtrs are + /// destroyed. + class StringPool { + /// PooledString - This is the value of an entry in the pool's interning + /// table. + struct PooledString { + StringPool *Pool; ///< So the string can remove itself. + unsigned Refcount; ///< Number of referencing PooledStringPtrs. + + public: + PooledString() : Pool(0), Refcount(0) { } + }; + + friend class PooledStringPtr; + + typedef StringMap table_t; + typedef StringMapEntry entry_t; + table_t InternTable; + + public: + StringPool(); + ~StringPool(); + + /// intern - Adds a string to the pool and returns a reference-counted + /// pointer to it. No additional memory is allocated if the string already + /// exists in the pool. + PooledStringPtr intern(StringRef Str); + + /// empty - Checks whether the pool is empty. Returns true if so. + /// + inline bool empty() const { return InternTable.empty(); } + }; + + /// PooledStringPtr - A pointer to an interned string. Use operator bool to + /// test whether the pointer is valid, and operator * to get the string if so. + /// This is a lightweight value class with storage requirements equivalent to + /// a single pointer, but it does have reference-counting overhead when + /// copied. + class PooledStringPtr { + typedef StringPool::entry_t entry_t; + entry_t *S; + + public: + PooledStringPtr() : S(0) {} + + explicit PooledStringPtr(entry_t *E) : S(E) { + if (S) ++S->getValue().Refcount; + } + + PooledStringPtr(const PooledStringPtr &That) : S(That.S) { + if (S) ++S->getValue().Refcount; + } + + PooledStringPtr &operator=(const PooledStringPtr &That) { + if (S != That.S) { + clear(); + S = That.S; + if (S) ++S->getValue().Refcount; + } + return *this; + } + + void clear() { + if (!S) + return; + if (--S->getValue().Refcount == 0) { + S->getValue().Pool->InternTable.remove(S); + S->Destroy(); + } + S = 0; + } + + ~PooledStringPtr() { clear(); } + + inline const char *begin() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyData(); + } + + inline const char *end() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyData() + S->getKeyLength(); + } + + inline unsigned size() const { + assert(*this && "Attempt to dereference empty PooledStringPtr!"); + return S->getKeyLength(); + } + + inline const char *operator*() const { return begin(); } + inline operator bool() const { return S != 0; } + + inline bool operator==(const PooledStringPtr &That) { return S == That.S; } + inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } + }; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/SwapByteOrder.h b/final/include/llvm/Support/SwapByteOrder.h new file mode 100644 index 00000000000..6c0592c05ad --- /dev/null +++ b/final/include/llvm/Support/SwapByteOrder.h @@ -0,0 +1,101 @@ +//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- 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 generic and optimized functions to swap the byte order of +// an integral type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H + +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { +namespace sys { + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +/// SwapByteOrder_32 - This function returns a byte-swapped representation of +/// the 32-bit argument. +inline uint32_t SwapByteOrder_32(uint32_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap32(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(value); +#else + uint32_t Byte0 = value & 0x000000FF; + uint32_t Byte1 = value & 0x0000FF00; + uint32_t Byte2 = value & 0x00FF0000; + uint32_t Byte3 = value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// SwapByteOrder_64 - This function returns a byte-swapped representation of +/// the 64-bit argument. +inline uint64_t SwapByteOrder_64(uint64_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap64(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(value); +#else + uint64_t Hi = SwapByteOrder_32(uint32_t(value)); + uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +inline unsigned char SwapByteOrder(unsigned char C) { return C; } +inline signed char SwapByteOrder(signed char C) { return C; } +inline char SwapByteOrder(char C) { return C; } + +inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } + +inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } + +#if __LONG_MAX__ == __INT_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +#elif __LONG_MAX__ == __LONG_LONG_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +#else +#error "Unknown long size!" +#endif + +inline unsigned long long SwapByteOrder(unsigned long long C) { + return SwapByteOrder_64(C); +} +inline signed long long SwapByteOrder(signed long long C) { + return SwapByteOrder_64(C); +} + +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/SystemUtils.h b/final/include/llvm/Support/SystemUtils.h new file mode 100644 index 00000000000..399aee51eb7 --- /dev/null +++ b/final/include/llvm/Support/SystemUtils.h @@ -0,0 +1,44 @@ +//===- SystemUtils.h - Utilities to do low-level system stuff ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions used to do a variety of low-level, often +// system-specific, tasks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SYSTEMUTILS_H +#define LLVM_SUPPORT_SYSTEMUTILS_H + +#include + +namespace llvm { + class raw_ostream; + namespace sys { class Path; } + +/// Determine if the raw_ostream provided is connected to a terminal. If so, +/// generate a warning message to errs() advising against display of bitcode +/// and return true. Otherwise just return false. +/// @brief Check for output written to a console +bool CheckBitcodeOutputToConsole( + raw_ostream &stream_to_check, ///< The stream to be checked + bool print_warning = true ///< Control whether warnings are printed +); + +/// PrependMainExecutablePath - Prepend the path to the program being executed +/// to \p ExeName, given the value of argv[0] and the address of main() +/// itself. This allows us to find another LLVM tool if it is built in the same +/// directory. An empty string is returned on error; note that this function +/// just mainpulates the path and doesn't check for executability. +/// @brief Find a named executable. +sys::Path PrependMainExecutablePath(const std::string &ExeName, + const char *Argv0, void *MainAddr); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/TargetFolder.h b/final/include/llvm/Support/TargetFolder.h new file mode 100644 index 00000000000..20ca5571ffa --- /dev/null +++ b/final/include/llvm/Support/TargetFolder.h @@ -0,0 +1,242 @@ +//====-- llvm/Support/TargetFolder.h - Constant folding helper -*- 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 TargetFolder class, a helper for IRBuilder. +// It provides IRBuilder with a set of methods for creating constants with +// target dependent folding, in addition to the same target-independent +// folding that the ConstantFolder class provides. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TARGETFOLDER_H +#define LLVM_SUPPORT_TARGETFOLDER_H + +#include "llvm/Constants.h" +#include "llvm/InstrTypes.h" +#include "llvm/Analysis/ConstantFolding.h" + +namespace llvm { + +class TargetData; + +/// TargetFolder - Create constants with target dependent folding. +class TargetFolder { + const TargetData *TD; + + /// Fold - Fold the constant using target specific information. + Constant *Fold(Constant *C) const { + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *CF = ConstantFoldConstantExpression(CE, TD)) + return CF; + return C; + } + +public: + explicit TargetFolder(const TargetData *TheTD) : TD(TheTD) {} + + //===--------------------------------------------------------------------===// + // Binary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFAdd(LHS, RHS)); + } + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFSub(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFSub(LHS, RHS)); + } + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateFMul(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFMul(LHS, RHS)); + } + Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); + } + Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); + } + Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFDiv(LHS, RHS)); + } + Constant *CreateURem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getURem(LHS, RHS)); + } + Constant *CreateSRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getSRem(LHS, RHS)); + } + Constant *CreateFRem(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getFRem(LHS, RHS)); + } + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); + } + Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); + } + Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); + } + Constant *CreateAnd(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getAnd(LHS, RHS)); + } + Constant *CreateOr(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getOr(LHS, RHS)); + } + Constant *CreateXor(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getXor(LHS, RHS)); + } + + Constant *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::get(Opc, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Unary Operators + //===--------------------------------------------------------------------===// + + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); + } + Constant *CreateFNeg(Constant *C) const { + return Fold(ConstantExpr::getFNeg(C)); + } + Constant *CreateNot(Constant *C) const { + return Fold(ConstantExpr::getNot(C)); + } + + //===--------------------------------------------------------------------===// + // Memory Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + } + Constant *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getGetElementPtr(C, IdxList, NumIdx)); + } + + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + Constant *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx)); + } + + //===--------------------------------------------------------------------===// + // Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + Constant *CreateCast(Instruction::CastOps Op, Constant *C, + const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getCast(Op, C, DestTy)); + } + Constant *CreateIntCast(Constant *C, const Type *DestTy, + bool isSigned) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); + } + Constant *CreatePointerCast(Constant *C, const Type *DestTy) const { + return ConstantExpr::getPointerCast(C, DestTy); + } + Constant *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Constant *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Constant *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Constant *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); + } + Constant *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); + } + Constant *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); + } + + //===--------------------------------------------------------------------===// + // Compare Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, + Constant *RHS) const { + return Fold(ConstantExpr::getCompare(P, LHS, RHS)); + } + + //===--------------------------------------------------------------------===// + // Other Instructions + //===--------------------------------------------------------------------===// + + Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { + return Fold(ConstantExpr::getSelect(C, True, False)); + } + + Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { + return Fold(ConstantExpr::getExtractElement(Vec, Idx)); + } + + Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { + return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); + } + + Constant *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { + return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); + } + + Constant *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { + return Fold(ConstantExpr::getExtractValue(Agg, IdxList, NumIdx)); + } + + Constant *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, unsigned NumIdx) const { + return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList, NumIdx)); + } +}; + +} + +#endif diff --git a/final/include/llvm/Support/ThreadLocal.h b/final/include/llvm/Support/ThreadLocal.h new file mode 100644 index 00000000000..15350a7afff --- /dev/null +++ b/final/include/llvm/Support/ThreadLocal.h @@ -0,0 +1,54 @@ +//===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- 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 llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREAD_LOCAL_H +#define LLVM_SYSTEM_THREAD_LOCAL_H + +#include "llvm/Support/Threading.h" +#include + +namespace llvm { + namespace sys { + // ThreadLocalImpl - Common base class of all ThreadLocal instantiations. + // YOU SHOULD NEVER USE THIS DIRECTLY. + class ThreadLocalImpl { + void* data; + public: + ThreadLocalImpl(); + virtual ~ThreadLocalImpl(); + void setInstance(const void* d); + const void* getInstance(); + void removeInstance(); + }; + + /// ThreadLocal - A class used to abstract thread-local storage. It holds, + /// for each thread, a pointer a single object of type T. + template + class ThreadLocal : public ThreadLocalImpl { + public: + ThreadLocal() : ThreadLocalImpl() { } + + /// get - Fetches a pointer to the object associated with the current + /// thread. If no object has yet been associated, it returns NULL; + T* get() { return static_cast(getInstance()); } + + // set - Associates a pointer to an object with the current thread. + void set(T* d) { setInstance(d); } + + // erase - Removes the pointer associated with the current thread. + void erase() { removeInstance(); } + }; + } +} + +#endif diff --git a/final/include/llvm/Support/Threading.h b/final/include/llvm/Support/Threading.h new file mode 100644 index 00000000000..c0e842c2fe7 --- /dev/null +++ b/final/include/llvm/Support/Threading.h @@ -0,0 +1,59 @@ +//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TThis file defines llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREADING_H +#define LLVM_SYSTEM_THREADING_H + +namespace llvm { + /// llvm_start_multithreaded - Allocate and initialize structures needed to + /// make LLVM safe for multithreading. The return value indicates whether + /// multithreaded initialization succeeded. LLVM will still be operational + /// on "failed" return, and will still be safe for hosting threading + /// applications in the JIT, but will not be safe for concurrent calls to the + /// LLVM APIs. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + bool llvm_start_multithreaded(); + + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM + /// safe for multithreading. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + void llvm_stop_multithreaded(); + + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe + /// mode or not. + bool llvm_is_multithreaded(); + + /// acquire_global_lock - Acquire the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_acquire_global_lock(); + + /// release_global_lock - Release the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_release_global_lock(); + + /// llvm_execute_on_thread - Execute the given \arg UserFn on a separate + /// thread, passing it the provided \arg UserData. + /// + /// This function does not guarantee that the code will actually be executed + /// on a separate thread or honoring the requested stack size, but tries to do + /// so where system support is available. + /// + /// \param UserFn - The callback to execute. + /// \param UserData - An argument to pass to the callback function. + /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for + /// the thread stack. + void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData, + unsigned RequestedStackSize = 0); +} + +#endif diff --git a/final/include/llvm/Support/TimeValue.h b/final/include/llvm/Support/TimeValue.h new file mode 100644 index 00000000000..e1227118c22 --- /dev/null +++ b/final/include/llvm/Support/TimeValue.h @@ -0,0 +1,382 @@ +//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/DataTypes.h" +#include + +#ifndef LLVM_SYSTEM_TIMEVALUE_H +#define LLVM_SYSTEM_TIMEVALUE_H + +namespace llvm { +namespace sys { + /// This class is used where a precise fixed point in time is required. The + /// range of TimeValue spans many hundreds of billions of years both past and + /// present. The precision of TimeValue is to the nanosecond. However, the + /// actual precision of its values will be determined by the resolution of + /// the system clock. The TimeValue class is used in conjunction with several + /// other lib/System interfaces to specify the time at which a call should + /// timeout, etc. + /// @since 1.4 + /// @brief Provides an abstraction for a fixed point in time. + class TimeValue { + + /// @name Constants + /// @{ + public: + + /// A constant TimeValue representing the smallest time + /// value permissable by the class. MinTime is some point + /// in the distant past, about 300 billion years BCE. + /// @brief The smallest possible time value. + static const TimeValue MinTime; + + /// A constant TimeValue representing the largest time + /// value permissable by the class. MaxTime is some point + /// in the distant future, about 300 billion years AD. + /// @brief The largest possible time value. + static const TimeValue MaxTime; + + /// A constant TimeValue representing the base time, + /// or zero time of 00:00:00 (midnight) January 1st, 2000. + /// @brief 00:00:00 Jan 1, 2000 UTC. + static const TimeValue ZeroTime; + + /// A constant TimeValue for the Posix base time which is + /// 00:00:00 (midnight) January 1st, 1970. + /// @brief 00:00:00 Jan 1, 1970 UTC. + static const TimeValue PosixZeroTime; + + /// A constant TimeValue for the Win32 base time which is + /// 00:00:00 (midnight) January 1st, 1601. + /// @brief 00:00:00 Jan 1, 1601 UTC. + static const TimeValue Win32ZeroTime; + + /// @} + /// @name Types + /// @{ + public: + typedef int64_t SecondsType; ///< Type used for representing seconds. + typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. + + enum TimeConversions { + NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion + MICROSECONDS_PER_SECOND = 1000000, ///< One Million + MILLISECONDS_PER_SECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million + NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Caller provides the exact value in seconds and nanoseconds. The + /// \p nanos argument defaults to zero for convenience. + /// @brief Explicit constructor + explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) + : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } + + /// Caller provides the exact value as a double in seconds with the + /// fractional part representing nanoseconds. + /// @brief Double Constructor. + explicit TimeValue( double new_time ) + : seconds_( 0 ) , nanos_ ( 0 ) { + SecondsType integer_part = static_cast( new_time ); + seconds_ = integer_part; + nanos_ = static_cast( (new_time - + static_cast(integer_part)) * NANOSECONDS_PER_SECOND ); + this->normalize(); + } + + /// This is a static constructor that returns a TimeValue that represents + /// the current time. + /// @brief Creates a TimeValue with the current time (UTC). + static TimeValue now(); + + /// @} + /// @name Operators + /// @{ + public: + /// Add \p that to \p this. + /// @returns this + /// @brief Incrementing assignment operator. + TimeValue& operator += (const TimeValue& that ) { + this->seconds_ += that.seconds_ ; + this->nanos_ += that.nanos_ ; + this->normalize(); + return *this; + } + + /// Subtract \p that from \p this. + /// @returns this + /// @brief Decrementing assignment operator. + TimeValue& operator -= (const TimeValue &that ) { + this->seconds_ -= that.seconds_ ; + this->nanos_ -= that.nanos_ ; + this->normalize(); + return *this; + } + + /// Determine if \p this is less than \p that. + /// @returns True iff *this < that. + /// @brief True if this < that. + int operator < (const TimeValue &that) const { return that > *this; } + + /// Determine if \p this is greather than \p that. + /// @returns True iff *this > that. + /// @brief True if this > that. + int operator > (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ > that.nanos_ ) return 1; + } + return 0; + } + + /// Determine if \p this is less than or equal to \p that. + /// @returns True iff *this <= that. + /// @brief True if this <= that. + int operator <= (const TimeValue &that) const { return that >= *this; } + + /// Determine if \p this is greater than or equal to \p that. + /// @returns True iff *this >= that. + /// @brief True if this >= that. + int operator >= (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ >= that.nanos_ ) return 1; + } + return 0; + } + + /// Determines if two TimeValue objects represent the same moment in time. + /// @brief True iff *this == that. + /// @brief True if this == that. + int operator == (const TimeValue &that) const { + return (this->seconds_ == that.seconds_) && + (this->nanos_ == that.nanos_); + } + + /// Determines if two TimeValue objects represent times that are not the + /// same. + /// @return True iff *this != that. + /// @brief True if this != that. + int operator != (const TimeValue &that) const { return !(*this == that); } + + /// Adds two TimeValue objects together. + /// @returns The sum of the two operands as a new TimeValue + /// @brief Addition operator. + friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); + + /// Subtracts two TimeValue objects. + /// @returns The difference of the two operands as a new TimeValue + /// @brief Subtraction operator. + friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); + + /// @} + /// @name Accessors + /// @{ + public: + + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + SecondsType seconds() const { return seconds_; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + NanoSecondsType nanoseconds() const { return nanos_; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return nanos_ / NANOSECONDS_PER_MICROSECOND; + } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the fractional part as milliseconds; + uint32_t milliseconds() const { + return nanos_ / NANOSECONDS_PER_MILLISECOND; + } + + /// Returns the TimeValue as a number of microseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of microseconds (can overflow) + uint64_t usec() const { + return seconds_ * MICROSECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MICROSECOND ); + } + + /// Returns the TimeValue as a number of milliseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of milliseconds (can overflow) + uint64_t msec() const { + return seconds_ * MILLISECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MILLISECOND ); + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Posix, correcting for the difference in Posix zero time. + /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) + uint64_t toPosixTime() const { + uint64_t result = seconds_ - PosixZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_POSIX_TICK; + return result; + } + + /// Converts the TimeValue into the corresponding number of seconds + /// since the epoch (00:00:00 Jan 1,1970). + uint64_t toEpochTime() const { + return seconds_ - PosixZeroTime.seconds_; + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Win32 platforms, correcting for the difference in Win32 zero time. + /// @brief Convert to windows time (seconds since 12:00:00a Jan 1, 1601) + uint64_t toWin32Time() const { + uint64_t result = seconds_ - Win32ZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_WIN32_TICK; + return result; + } + + /// Provides the seconds and nanoseconds as results in its arguments after + /// correction for the Posix zero time. + /// @brief Convert to timespec time (ala POSIX.1b) + void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { + seconds = seconds_ - PosixZeroTime.seconds_; + nanos = nanos_; + } + + /// Provides conversion of the TimeValue into a readable time & date. + /// @returns std::string containing the readable time value + /// @brief Convert time to a string. + std::string str() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// The seconds component of the TimeValue is set to \p sec without + /// modifying the nanoseconds part. This is useful for whole second + /// arithmetic. + /// @brief Set the seconds component. + void seconds (SecondsType sec ) { + this->seconds_ = sec; + this->normalize(); + } + + /// The nanoseconds component of the TimeValue is set to \p nanos without + /// modifying the seconds part. This is useful for basic computations + /// involving just the nanoseconds portion. Note that the TimeValue will be + /// normalized after this call so that the fractional (nanoseconds) portion + /// will have the smallest equivalent value. + /// @brief Set the nanoseconds component using a number of nanoseconds. + void nanoseconds ( NanoSecondsType nanos ) { + this->nanos_ = nanos; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of microseconds. + void microseconds ( int32_t micros ) { + this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of milliseconds. + void milliseconds ( int32_t millis ) { + this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// @brief Converts from microsecond format to TimeValue format + void usec( int64_t microseconds ) { + this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * + NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// @brief Converts from millisecond format to TimeValue format + void msec( int64_t milliseconds ) { + this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// Converts the \p seconds argument from PosixTime to the corresponding + /// TimeValue and assigns that value to \p this. + /// @brief Convert seconds form PosixTime to TimeValue + void fromEpochTime( SecondsType seconds ) { + seconds_ = seconds + PosixZeroTime.seconds_; + nanos_ = 0; + this->normalize(); + } + + /// Converts the \p win32Time argument from Windows FILETIME to the + /// corresponding TimeValue and assigns that value to \p this. + /// @brief Convert seconds form Windows FILETIME to TimeValue + void fromWin32Time( uint64_t win32Time ) { + this->seconds_ = win32Time / 10000000 + Win32ZeroTime.seconds_; + this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; + } + + /// @} + /// @name Implementation + /// @{ + private: + /// This causes the values to be represented so that the fractional + /// part is minimized, possibly incrementing the seconds part. + /// @brief Normalize to canonical form. + void normalize(); + + /// @} + /// @name Data + /// @{ + private: + /// Store the values as a . + SecondsType seconds_;///< Stores the seconds part of the TimeVal + NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + /// @} + + }; + +inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); + sum.normalize (); + return sum; +} + +inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); + difference.normalize (); + return difference; +} + +} +} + +#endif diff --git a/final/include/llvm/Support/Timer.h b/final/include/llvm/Support/Timer.h new file mode 100644 index 00000000000..404cb6d6c8b --- /dev/null +++ b/final/include/llvm/Support/Timer.h @@ -0,0 +1,194 @@ +//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- 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 three classes: Timer, TimeRegion, and TimerGroup, +// documented below. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TIMER_H +#define LLVM_SUPPORT_TIMER_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include +#include + +namespace llvm { + +class Timer; +class TimerGroup; +class raw_ostream; + +class TimeRecord { + double WallTime; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + ssize_t MemUsed; // Memory allocated (in bytes) +public: + TimeRecord() : WallTime(0), UserTime(0), SystemTime(0), MemUsed(0) {} + + /// getCurrentTime - Get the current time and memory usage. If Start is true + /// we get the memory usage before the time, otherwise we get time before + /// memory usage. This matters if the time to get the memory usage is + /// significant and shouldn't be counted as part of a duration. + static TimeRecord getCurrentTime(bool Start = true); + + double getProcessTime() const { return UserTime+SystemTime; } + double getUserTime() const { return UserTime; } + double getSystemTime() const { return SystemTime; } + double getWallTime() const { return WallTime; } + ssize_t getMemUsed() const { return MemUsed; } + + + // operator< - Allow sorting. + bool operator<(const TimeRecord &T) const { + // Sort by Wall Time elapsed, as it is the only thing really accurate + return WallTime < T.WallTime; + } + + void operator+=(const TimeRecord &RHS) { + WallTime += RHS.WallTime; + UserTime += RHS.UserTime; + SystemTime += RHS.SystemTime; + MemUsed += RHS.MemUsed; + } + void operator-=(const TimeRecord &RHS) { + WallTime -= RHS.WallTime; + UserTime -= RHS.UserTime; + SystemTime -= RHS.SystemTime; + MemUsed -= RHS.MemUsed; + } + + /// print - Print the current timer to standard error, and reset the "Started" + /// flag. + void print(const TimeRecord &Total, raw_ostream &OS) const; +}; + +/// Timer - This class is used to track the amount of time spent between +/// invocations of its startTimer()/stopTimer() methods. Given appropriate OS +/// support it can also keep track of the RSS of the program at various points. +/// By default, the Timer will print the amount of time it has captured to +/// standard error when the laster timer is destroyed, otherwise it is printed +/// when its TimerGroup is destroyed. Timers do not print their information +/// if they are never started. +/// +class Timer { + TimeRecord Time; + std::string Name; // The name of this time variable. + bool Started; // Has this time variable ever been started? + TimerGroup *TG; // The TimerGroup this Timer is in. + + Timer **Prev, *Next; // Doubly linked list of timers in the group. +public: + explicit Timer(StringRef N) : TG(0) { init(N); } + Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); } + Timer(const Timer &RHS) : TG(0) { + assert(RHS.TG == 0 && "Can only copy uninitialized timers"); + } + const Timer &operator=(const Timer &T) { + assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers"); + return *this; + } + ~Timer(); + + // Create an uninitialized timer, client must use 'init'. + explicit Timer() : TG(0) {} + void init(StringRef N); + void init(StringRef N, TimerGroup &tg); + + const std::string &getName() const { return Name; } + bool isInitialized() const { return TG != 0; } + + /// startTimer - Start the timer running. Time between calls to + /// startTimer/stopTimer is counted by the Timer class. Note that these calls + /// must be correctly paired. + /// + void startTimer(); + + /// stopTimer - Stop the timer. + /// + void stopTimer(); + +private: + friend class TimerGroup; +}; + + +/// The TimeRegion class is used as a helper class to call the startTimer() and +/// stopTimer() methods of the Timer class. When the object is constructed, it +/// starts the timer specified as it's argument. When it is destroyed, it stops +/// the relevant timer. This makes it easy to time a region of code. +/// +class TimeRegion { + Timer *T; + TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT +public: + explicit TimeRegion(Timer &t) : T(&t) { + T->startTimer(); + } + explicit TimeRegion(Timer *t) : T(t) { + if (T) T->startTimer(); + } + ~TimeRegion() { + if (T) T->stopTimer(); + } +}; + + +/// NamedRegionTimer - This class is basically a combination of TimeRegion and +/// Timer. It allows you to declare a new timer, AND specify the region to +/// time, all in one statement. All timers with the same name are merged. This +/// is primarily used for debugging and for hunting performance problems. +/// +struct NamedRegionTimer : public TimeRegion { + explicit NamedRegionTimer(StringRef Name, + bool Enabled = true); + explicit NamedRegionTimer(StringRef Name, StringRef GroupName, + bool Enabled = true); +}; + + +/// The TimerGroup class is used to group together related timers into a single +/// report that is printed when the TimerGroup is destroyed. It is illegal to +/// destroy a TimerGroup object before all of the Timers in it are gone. A +/// TimerGroup can be specified for a newly created timer in its constructor. +/// +class TimerGroup { + std::string Name; + Timer *FirstTimer; // First timer in the group. + std::vector > TimersToPrint; + + TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. + TimerGroup(const TimerGroup &TG); // DO NOT IMPLEMENT + void operator=(const TimerGroup &TG); // DO NOT IMPLEMENT +public: + explicit TimerGroup(StringRef name); + ~TimerGroup(); + + void setName(StringRef name) { Name.assign(name.begin(), name.end()); } + + /// print - Print any started timers in this group and zero them. + void print(raw_ostream &OS); + + /// printAll - This static method prints all timers and clears them all out. + static void printAll(raw_ostream &OS); + +private: + friend class Timer; + void addTimer(Timer &T); + void removeTimer(Timer &T); + void PrintQueuedTimers(raw_ostream &OS); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/ToolOutputFile.h b/final/include/llvm/Support/ToolOutputFile.h new file mode 100644 index 00000000000..65b182a2453 --- /dev/null +++ b/final/include/llvm/Support/ToolOutputFile.h @@ -0,0 +1,62 @@ +//===- ToolOutputFile.h - Output files for compiler-like tools -----------===// +// +// 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 tool_output_file class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TOOL_OUTPUT_FILE_H +#define LLVM_SUPPORT_TOOL_OUTPUT_FILE_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// tool_output_file - This class contains a raw_fd_ostream and adds a +/// few extra features commonly needed for compiler-like tool output files: +/// - The file is automatically deleted if the process is killed. +/// - The file is automatically deleted when the tool_output_file +/// object is destroyed unless the client calls keep(). +class tool_output_file { + /// Installer - This class is declared before the raw_fd_ostream so that + /// it is constructed before the raw_fd_ostream is constructed and + /// destructed after the raw_fd_ostream is destructed. It installs + /// cleanups in its constructor and uninstalls them in its destructor. + class CleanupInstaller { + /// Filename - The name of the file. + std::string Filename; + public: + /// Keep - The flag which indicates whether we should not delete the file. + bool Keep; + + explicit CleanupInstaller(const char *filename); + ~CleanupInstaller(); + } Installer; + + /// OS - The contained stream. This is intentionally declared after + /// Installer. + raw_fd_ostream OS; + +public: + /// tool_output_file - This constructor's arguments are passed to + /// to raw_fd_ostream's constructor. + tool_output_file(const char *filename, std::string &ErrorInfo, + unsigned Flags = 0); + + /// os - Return the contained raw_fd_ostream. + raw_fd_ostream &os() { return OS; } + + /// keep - Indicate that the tool's job wrt this output file has been + /// successful and the file should not be deleted. + void keep() { Installer.Keep = true; } +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Support/TypeBuilder.h b/final/include/llvm/Support/TypeBuilder.h new file mode 100644 index 00000000000..ea63da00edc --- /dev/null +++ b/final/include/llvm/Support/TypeBuilder.h @@ -0,0 +1,399 @@ +//===---- llvm/Support/TypeBuilder.h - Builder for LLVM types ---*- 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 TypeBuilder class, which is used as a convenient way to +// create LLVM types with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPEBUILDER_H +#define LLVM_SUPPORT_TYPEBUILDER_H + +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include + +namespace llvm { + +/// TypeBuilder - This provides a uniform API for looking up types +/// known at compile time. To support cross-compilation, we define a +/// series of tag types in the llvm::types namespace, like i, +/// ieee_float, ppc_fp128, etc. TypeBuilder allows T to be +/// any of these, a native C type (whose size may depend on the host +/// compiler), or a pointer, function, or struct type built out of +/// these. TypeBuilder removes native C types from this set +/// to guarantee that its result is suitable for cross-compilation. +/// We define the primitive types, pointer types, and functions up to +/// 5 arguments here, but to use this class with your own types, +/// you'll need to specialize it. For example, say you want to call a +/// function defined externally as: +/// +/// struct MyType { +/// int32 a; +/// int32 *b; +/// void *array[1]; // Intended as a flexible array. +/// }; +/// int8 AFunction(struct MyType *value); +/// +/// You'll want to use +/// Function::Create(TypeBuilder(MyType*), true>::get(), ...) +/// to declare the function, but when you first try this, your compiler will +/// complain that TypeBuilder::get() doesn't exist. To fix this, +/// write: +/// +/// namespace llvm { +/// template class TypeBuilder { +/// public: +/// static const StructType *get(LLVMContext &Context) { +/// // If you cache this result, be sure to cache it separately +/// // for each LLVMContext. +/// return StructType::get( +/// TypeBuilder, xcompile>::get(Context), +/// TypeBuilder*, xcompile>::get(Context), +/// TypeBuilder*[], xcompile>::get(Context), +/// NULL); +/// } +/// +/// // You may find this a convenient place to put some constants +/// // to help with getelementptr. They don't have any effect on +/// // the operation of TypeBuilder. +/// enum Fields { +/// FIELD_A, +/// FIELD_B, +/// FIELD_ARRAY +/// }; +/// } +/// } // namespace llvm +/// +/// TypeBuilder cannot handle recursive types or types you only know at runtime. +/// If you try to give it a recursive type, it will deadlock, infinitely +/// recurse, or do something similarly undesirable. +template class TypeBuilder {}; + +// Types for use with cross-compilable TypeBuilders. These correspond +// exactly with an LLVM-native type. +namespace types { +/// i corresponds to the LLVM IntegerType with N bits. +template class i {}; + +// The following classes represent the LLVM floating types. +class ieee_float {}; +class ieee_double {}; +class x86_fp80 {}; +class fp128 {}; +class ppc_fp128 {}; +// X86 MMX. +class x86_mmx {}; +} // namespace types + +// LLVM doesn't have const or volatile types. +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; +template class TypeBuilder + : public TypeBuilder {}; + +// Pointers +template class TypeBuilder { +public: + static const PointerType *get(LLVMContext &Context) { + return PointerType::getUnqual(TypeBuilder::get(Context)); + } +}; + +/// There is no support for references +template class TypeBuilder {}; + +// Arrays +template class TypeBuilder { +public: + static const ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder::get(Context), N); + } +}; +/// LLVM uses an array of length 0 to represent an unknown-length array. +template class TypeBuilder { +public: + static const ArrayType *get(LLVMContext &Context) { + return ArrayType::get(TypeBuilder::get(Context), 0); + } +}; + +// Define the C integral types only for TypeBuilder. +// +// C integral types do not have a defined size. It would be nice to use the +// stdint.h-defined typedefs that do have defined sizes, but we'd run into the +// following problem: +// +// On an ILP32 machine, stdint.h might define: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef long size_t; +// +// If we defined TypeBuilder and TypeBuilder, then any use of +// TypeBuilder would fail. We couldn't define TypeBuilder in +// addition to the defined-size types because we'd get duplicate definitions on +// platforms where stdint.h instead defines: +// +// typedef int int32_t; +// typedef long long int64_t; +// typedef int size_t; +// +// So we define all the primitive C types and nothing else. +#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ +template<> class TypeBuilder { \ +public: \ + static const IntegerType *get(LLVMContext &Context) { \ + return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ + } \ +}; \ +template<> class TypeBuilder { \ + /* We provide a definition here so users don't accidentally */ \ + /* define these types to work. */ \ +} +DEFINE_INTEGRAL_TYPEBUILDER(char); +DEFINE_INTEGRAL_TYPEBUILDER(signed char); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); +DEFINE_INTEGRAL_TYPEBUILDER(short); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); +DEFINE_INTEGRAL_TYPEBUILDER(int); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); +DEFINE_INTEGRAL_TYPEBUILDER(long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); +#ifdef _MSC_VER +DEFINE_INTEGRAL_TYPEBUILDER(__int64); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); +#else /* _MSC_VER */ +DEFINE_INTEGRAL_TYPEBUILDER(long long); +DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); +#endif /* _MSC_VER */ +#undef DEFINE_INTEGRAL_TYPEBUILDER + +template +class TypeBuilder, cross> { +public: + static const IntegerType *get(LLVMContext &C) { + return IntegerType::get(C, num_bits); + } +}; + +template<> class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { + return Type::getFloatTy(C); + } +}; +template<> class TypeBuilder {}; + +template<> class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { + return Type::getDoubleTy(C); + } +}; +template<> class TypeBuilder {}; + +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getFloatTy(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } +}; +template class TypeBuilder { +public: + static const Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } +}; + +template class TypeBuilder { +public: + static const Type *get(LLVMContext &C) { + return Type::getVoidTy(C); + } +}; + +/// void* is disallowed in LLVM types, but it occurs often enough in C code that +/// we special case it. +template<> class TypeBuilder + : public TypeBuilder*, false> {}; +template<> class TypeBuilder + : public TypeBuilder*, false> {}; +template<> class TypeBuilder + : public TypeBuilder*, false> {}; +template<> class TypeBuilder + : public TypeBuilder*, false> {}; + +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder::get(Context), false); + } +}; +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, false); + } +}; + +template class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + return FunctionType::get(TypeBuilder::get(Context), true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(1); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(2); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(3); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(4); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +template +class TypeBuilder { +public: + static const FunctionType *get(LLVMContext &Context) { + std::vector params; + params.reserve(5); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + params.push_back(TypeBuilder::get(Context)); + return FunctionType::get(TypeBuilder::get(Context), + params, true); + } +}; + +} // namespace llvm + +#endif diff --git a/final/include/llvm/Support/Valgrind.h b/final/include/llvm/Support/Valgrind.h new file mode 100644 index 00000000000..7662eaaff5a --- /dev/null +++ b/final/include/llvm/Support/Valgrind.h @@ -0,0 +1,32 @@ +//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for communicating with a valgrind instance this program is running +// under. These are all no-ops unless LLVM was configured on a system with the +// valgrind headers installed and valgrind is controlling this process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_VALGRIND_H +#define LLVM_SYSTEM_VALGRIND_H + +#include + +namespace llvm { +namespace sys { + // True if Valgrind is controlling this process. + bool RunningOnValgrind(); + + // Discard valgrind's translation of code in the range [Addr .. Addr + Len). + // Otherwise valgrind may continue to execute the old version of the code. + void ValgrindDiscardTranslations(const void *Addr, size_t Len); +} +} + +#endif diff --git a/final/include/llvm/Support/ValueHandle.h b/final/include/llvm/Support/ValueHandle.h new file mode 100644 index 00000000000..c0cdc35e99b --- /dev/null +++ b/final/include/llvm/Support/ValueHandle.h @@ -0,0 +1,408 @@ +//===- llvm/Support/ValueHandle.h - Value Smart Pointer classes -*- 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 ValueHandle class and its sub-classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_VALUEHANDLE_H +#define LLVM_SUPPORT_VALUEHANDLE_H + +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Value.h" + +namespace llvm { +class ValueHandleBase; + +// ValueHandleBase** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(ValueHandleBase** P) { return P; } + static inline ValueHandleBase **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +/// ValueHandleBase - This is the common base class of value handles. +/// ValueHandle's are smart pointers to Value's that have special behavior when +/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles +/// below for details. +/// +class ValueHandleBase { + friend class Value; +protected: + /// HandleBaseKind - This indicates what sub class the handle actually is. + /// This is to avoid having a vtable for the light-weight handle pointers. The + /// fully general Callback version does have a vtable. + enum HandleBaseKind { + Assert, + Callback, + Tracking, + Weak + }; +private: + + PointerIntPair PrevPair; + ValueHandleBase *Next; + Value *VP; + + explicit ValueHandleBase(const ValueHandleBase&); // DO NOT IMPLEMENT. +public: + explicit ValueHandleBase(HandleBaseKind Kind) + : PrevPair(0, Kind), Next(0), VP(0) {} + ValueHandleBase(HandleBaseKind Kind, Value *V) + : PrevPair(0, Kind), Next(0), VP(V) { + if (isValid(VP)) + AddToUseList(); + } + ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) + : PrevPair(0, Kind), Next(0), VP(RHS.VP) { + if (isValid(VP)) + AddToExistingUseList(RHS.getPrevPtr()); + } + ~ValueHandleBase() { + if (isValid(VP)) + RemoveFromUseList(); + } + + Value *operator=(Value *RHS) { + if (VP == RHS) return RHS; + if (isValid(VP)) RemoveFromUseList(); + VP = RHS; + if (isValid(VP)) AddToUseList(); + return RHS; + } + + Value *operator=(const ValueHandleBase &RHS) { + if (VP == RHS.VP) return RHS.VP; + if (isValid(VP)) RemoveFromUseList(); + VP = RHS.VP; + if (isValid(VP)) AddToExistingUseList(RHS.getPrevPtr()); + return VP; + } + + Value *operator->() const { return getValPtr(); } + Value &operator*() const { return *getValPtr(); } + +protected: + Value *getValPtr() const { return VP; } + static bool isValid(Value *V) { + return V && + V != DenseMapInfo::getEmptyKey() && + V != DenseMapInfo::getTombstoneKey(); + } + +private: + // Callbacks made from Value. + static void ValueIsDeleted(Value *V); + static void ValueIsRAUWd(Value *Old, Value *New); + + // Internal implementation details. + ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } + HandleBaseKind getKind() const { return PrevPair.getInt(); } + void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } + + /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where + /// List is the address of either the head of the list or a Next node within + /// the existing use list. + void AddToExistingUseList(ValueHandleBase **List); + + /// AddToExistingUseListAfter - Add this ValueHandle to the use list after + /// Node. + void AddToExistingUseListAfter(ValueHandleBase *Node); + + /// AddToUseList - Add this ValueHandle to the use list for VP. + void AddToUseList(); + /// RemoveFromUseList - Remove this ValueHandle from its current use list. + void RemoveFromUseList(); +}; + +/// WeakVH - This is a value handle that tries hard to point to a Value, even +/// across RAUW operations, but will null itself out if the value is destroyed. +/// this is useful for advisory sorts of information, but should not be used as +/// the key of a map (since the map would have to rearrange itself when the +/// pointer changes). +class WeakVH : public ValueHandleBase { +public: + WeakVH() : ValueHandleBase(Weak) {} + WeakVH(Value *P) : ValueHandleBase(Weak, P) {} + WeakVH(const WeakVH &RHS) + : ValueHandleBase(Weak, RHS) {} + + Value *operator=(Value *RHS) { + return ValueHandleBase::operator=(RHS); + } + Value *operator=(const ValueHandleBase &RHS) { + return ValueHandleBase::operator=(RHS); + } + + operator Value*() const { + return getValPtr(); + } +}; + +// Specialize simplify_type to allow WeakVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { + return static_cast(WVH); + } +}; +template<> struct simplify_type : public simplify_type {}; + +/// AssertingVH - This is a Value Handle that points to a value and asserts out +/// if the value is destroyed while the handle is still live. This is very +/// useful for catching dangling pointer bugs and other things which can be +/// non-obvious. One particularly useful place to use this is as the Key of a +/// map. Dangling pointer bugs often lead to really subtle bugs that only occur +/// if another object happens to get allocated to the same address as the old +/// one. Using an AssertingVH ensures that an assert is triggered as soon as +/// the bad delete occurs. +/// +/// Note that an AssertingVH handle does *not* follow values across RAUW +/// operations. This means that RAUW's need to explicitly update the +/// AssertingVH's as it moves. This is required because in non-assert mode this +/// class turns into a trivial wrapper around a pointer. +template +class AssertingVH +#ifndef NDEBUG + : public ValueHandleBase +#endif + { + +#ifndef NDEBUG + ValueTy *getValPtr() const { + return static_cast(ValueHandleBase::getValPtr()); + } + void setValPtr(ValueTy *P) { + ValueHandleBase::operator=(GetAsValue(P)); + } +#else + ValueTy *ThePtr; + ValueTy *getValPtr() const { return ThePtr; } + void setValPtr(ValueTy *P) { ThePtr = P; } +#endif + + // Convert a ValueTy*, which may be const, to the type the base + // class expects. + static Value *GetAsValue(Value *V) { return V; } + static Value *GetAsValue(const Value *V) { return const_cast(V); } + +public: +#ifndef NDEBUG + AssertingVH() : ValueHandleBase(Assert) {} + AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} + AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} +#else + AssertingVH() : ThePtr(0) {} + AssertingVH(ValueTy *P) : ThePtr(P) {} +#endif + + operator ValueTy*() const { + return getValPtr(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const AssertingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); + } + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow AssertingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const AssertingVH &AVH) { + return static_cast(AVH); + } +}; +template<> struct simplify_type > + : public simplify_type > {}; + +// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. +template +struct DenseMapInfo > { + typedef DenseMapInfo PointerInfo; + static inline AssertingVH getEmptyKey() { + return AssertingVH(PointerInfo::getEmptyKey()); + } + static inline T* getTombstoneKey() { + return AssertingVH(PointerInfo::getTombstoneKey()); + } + static unsigned getHashValue(const AssertingVH &Val) { + return PointerInfo::getHashValue(Val); + } + static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { + return LHS == RHS; + } +}; + +template +struct isPodLike > { +#ifdef NDEBUG + static const bool value = true; +#else + static const bool value = false; +#endif +}; + + +/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), +/// even across RAUW operations. +/// +/// TrackingVH is designed for situations where a client needs to hold a handle +/// to a Value (or subclass) across some operations which may move that value, +/// but should never destroy it or replace it with some unacceptable type. +/// +/// It is an error to do anything with a TrackingVH whose value has been +/// destroyed, except to destruct it. +/// +/// It is an error to attempt to replace a value with one of a type which is +/// incompatible with any of its outstanding TrackingVHs. +template +class TrackingVH : public ValueHandleBase { + void CheckValidity() const { + Value *VP = ValueHandleBase::getValPtr(); + + // Null is always ok. + if (!VP) return; + + // Check that this value is valid (i.e., it hasn't been deleted). We + // explicitly delay this check until access to avoid requiring clients to be + // unnecessarily careful w.r.t. destruction. + assert(ValueHandleBase::isValid(VP) && "Tracked Value was deleted!"); + + // Check that the value is a member of the correct subclass. We would like + // to check this property on assignment for better debugging, but we don't + // want to require a virtual interface on this VH. Instead we allow RAUW to + // replace this value with a value of an invalid type, and check it here. + assert(isa(VP) && + "Tracked Value was replaced by one with an invalid type!"); + } + + ValueTy *getValPtr() const { + CheckValidity(); + return (ValueTy*)ValueHandleBase::getValPtr(); + } + void setValPtr(ValueTy *P) { + CheckValidity(); + ValueHandleBase::operator=(GetAsValue(P)); + } + + // Convert a ValueTy*, which may be const, to the type the base + // class expects. + static Value *GetAsValue(Value *V) { return V; } + static Value *GetAsValue(const Value *V) { return const_cast(V); } + +public: + TrackingVH() : ValueHandleBase(Tracking) {} + TrackingVH(ValueTy *P) : ValueHandleBase(Tracking, GetAsValue(P)) {} + TrackingVH(const TrackingVH &RHS) : ValueHandleBase(Tracking, RHS) {} + + operator ValueTy*() const { + return getValPtr(); + } + + ValueTy *operator=(ValueTy *RHS) { + setValPtr(RHS); + return getValPtr(); + } + ValueTy *operator=(const TrackingVH &RHS) { + setValPtr(RHS.getValPtr()); + return getValPtr(); + } + + ValueTy *operator->() const { return getValPtr(); } + ValueTy &operator*() const { return *getValPtr(); } +}; + +// Specialize simplify_type to allow TrackingVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type > { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const TrackingVH &AVH) { + return static_cast(AVH); + } +}; +template<> struct simplify_type > + : public simplify_type > {}; + +/// CallbackVH - This is a value handle that allows subclasses to define +/// callbacks that run when the underlying Value has RAUW called on it or is +/// destroyed. This class can be used as the key of a map, as long as the user +/// takes it out of the map before calling setValPtr() (since the map has to +/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this +/// class has a vtable and a virtual destructor. +class CallbackVH : public ValueHandleBase { +protected: + CallbackVH(const CallbackVH &RHS) + : ValueHandleBase(Callback, RHS) {} + + virtual ~CallbackVH(); + + void setValPtr(Value *P) { + ValueHandleBase::operator=(P); + } + +public: + CallbackVH() : ValueHandleBase(Callback) {} + CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} + + operator Value*() const { + return getValPtr(); + } + + /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may + /// call any non-virtual Value method on getValPtr(), but no subclass methods. + /// If WeakVH were implemented as a CallbackVH, it would use this method to + /// call setValPtr(NULL). AssertingVH would use this method to cause an + /// assertion failure. + /// + /// All implementations must remove the reference from this object to the + /// Value that's being destroyed. + virtual void deleted() { + setValPtr(NULL); + } + + /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, + /// _before_ any of the uses have actually been replaced. If WeakVH were + /// implemented as a CallbackVH, it would use this method to call + /// setValPtr(new_value). AssertingVH would do nothing in this method. + virtual void allUsesReplacedWith(Value *) {} +}; + +// Specialize simplify_type to allow CallbackVH to participate in +// dyn_cast, isa, etc. +template struct simplify_type; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const CallbackVH &CVH) { + return static_cast(CVH); + } +}; +template<> struct simplify_type + : public simplify_type {}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Support/circular_raw_ostream.h b/final/include/llvm/Support/circular_raw_ostream.h new file mode 100644 index 00000000000..2b3c329b586 --- /dev/null +++ b/final/include/llvm/Support/circular_raw_ostream.h @@ -0,0 +1,171 @@ +//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains raw_ostream implementations for streams to do circular +// buffering of their output. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H +#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm +{ + /// circular_raw_ostream - A raw_ostream which *can* save its data + /// to a circular buffer, or can pass it through directly to an + /// underlying stream if specified with a buffer of zero. + /// + class circular_raw_ostream : public raw_ostream { + public: + /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying + /// stream and is responsible for cleanup, memory management + /// issues, etc. + /// + static const bool TAKE_OWNERSHIP = true; + + /// REFERENCE_ONLY - Tell this stream it should not manage the + /// held stream. + /// + static const bool REFERENCE_ONLY = false; + + private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; + + /// OwnsStream - Are we responsible for managing the underlying + /// stream? + /// + bool OwnsStream; + + /// BufferSize - The size of the buffer in bytes. + /// + size_t BufferSize; + + /// BufferArray - The actual buffer storage. + /// + char *BufferArray; + + /// Cur - Pointer to the current output point in BufferArray. + /// + char *Cur; + + /// Filled - Indicate whether the buffer has been completely + /// filled. This helps avoid garbage output. + /// + bool Filled; + + /// Banner - A pointer to a banner to print before dumping the + /// log. + /// + const char *Banner; + + /// flushBuffer - Dump the contents of the buffer to Stream. + /// + void flushBuffer(void) { + if (Filled) + // Write the older portion of the buffer. + TheStream->write(Cur, BufferArray + BufferSize - Cur); + // Write the newer portion of the buffer. + TheStream->write(BufferArray, Cur - BufferArray); + Cur = BufferArray; + Filled = false; + } + + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + /// + virtual uint64_t current_pos() const { + // This has the same effect as calling TheStream.current_pos(), + // but that interface is private. + return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + } + + public: + /// circular_raw_ostream - Construct an optionally + /// circular-buffered stream, handing it an underlying stream to + /// do the "real" output. + /// + /// As a side effect, if BuffSize is nonzero, the given Stream is + /// set to be Unbuffered. This is because circular_raw_ostream + /// does its own buffering, so it doesn't want another layer of + /// buffering to be happening underneath it. + /// + /// "Owns" tells the circular_raw_ostream whether it is + /// responsible for managing the held stream, doing memory + /// management of it, etc. + /// + circular_raw_ostream(raw_ostream &Stream, const char *Header, + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/true), + TheStream(0), + OwnsStream(Owns), + BufferSize(BuffSize), + BufferArray(0), + Filled(false), + Banner(Header) { + if (BufferSize != 0) + BufferArray = new char[BufferSize]; + Cur = BufferArray; + setStream(Stream, Owns); + } + explicit circular_raw_ostream() + : raw_ostream(/*unbuffered*/true), + TheStream(0), + OwnsStream(REFERENCE_ONLY), + BufferArray(0), + Filled(false), + Banner("") { + Cur = BufferArray; + } + + ~circular_raw_ostream() { + flush(); + flushBufferWithBanner(); + releaseStream(); + delete[] BufferArray; + } + + /// setStream - Tell the circular_raw_ostream to output a + /// different stream. "Owns" tells circular_raw_ostream whether + /// it should take responsibility for managing the underlying + /// stream. + /// + void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { + releaseStream(); + TheStream = &Stream; + OwnsStream = Owns; + } + + /// flushBufferWithBanner - Force output of the buffer along with + /// a small header. + /// + void flushBufferWithBanner(void); + + private: + /// releaseStream - Delete the held stream if needed. Otherwise, + /// transfer the buffer settings from this circular_raw_ostream + /// back to the underlying stream. + /// + void releaseStream() { + if (!TheStream) + return; + if (OwnsStream) + delete TheStream; + } + }; +} // end llvm namespace + + +#endif diff --git a/final/include/llvm/Support/raw_os_ostream.h b/final/include/llvm/Support/raw_os_ostream.h new file mode 100644 index 00000000000..4f5d3612da1 --- /dev/null +++ b/final/include/llvm/Support/raw_os_ostream.h @@ -0,0 +1,42 @@ +//===- raw_os_ostream.h - std::ostream adaptor for raw_ostream --*- 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 raw_os_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OS_OSTREAM_H +#define LLVM_SUPPORT_RAW_OS_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +/// raw_os_ostream - A raw_ostream that writes to an std::ostream. This is a +/// simple adaptor class. It does not check for output errors; clients should +/// use the underlying stream to detect errors. +class raw_os_ostream : public raw_ostream { + std::ostream &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const; + +public: + raw_os_ostream(std::ostream &O) : OS(O) {} + ~raw_os_ostream(); +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Support/raw_ostream.h b/final/include/llvm/Support/raw_ostream.h new file mode 100644 index 00000000000..6bfae5e2982 --- /dev/null +++ b/final/include/llvm/Support/raw_ostream.h @@ -0,0 +1,491 @@ +//===--- raw_ostream.h - Raw output stream ----------------------*- 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 raw_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_OSTREAM_H +#define LLVM_SUPPORT_RAW_OSTREAM_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class format_object_base; + template + class SmallVectorImpl; + +/// raw_ostream - This class implements an extremely fast bulk output stream +/// that can *only* output to a stream. It does not support seeking, reopening, +/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs +/// a chunk at a time. +class raw_ostream { +private: + // Do not implement. raw_ostream is noncopyable. + void operator=(const raw_ostream &); + raw_ostream(const raw_ostream &); + + /// The buffer is handled in such a way that the buffer is + /// uninitialized, unbuffered, or out of space when OutBufCur >= + /// OutBufEnd. Thus a single comparison suffices to determine if we + /// need to take the slow path to write a single character. + /// + /// The buffer is in one of three states: + /// 1. Unbuffered (BufferMode == Unbuffered) + /// 1. Uninitialized (BufferMode != Unbuffered && OutBufStart == 0). + /// 2. Buffered (BufferMode != Unbuffered && OutBufStart != 0 && + /// OutBufEnd - OutBufStart >= 1). + /// + /// If buffered, then the raw_ostream owns the buffer if (BufferMode == + /// InternalBuffer); otherwise the buffer has been set via SetBuffer and is + /// managed by the subclass. + /// + /// If a subclass installs an external buffer using SetBuffer then it can wait + /// for a \see write_impl() call to handle the data which has been put into + /// this buffer. + char *OutBufStart, *OutBufEnd, *OutBufCur; + + enum BufferKind { + Unbuffered = 0, + InternalBuffer, + ExternalBuffer + } BufferMode; + +public: + // color order matches ANSI escape sequence, don't change + enum Colors { + BLACK=0, + RED, + GREEN, + YELLOW, + BLUE, + MAGENTA, + CYAN, + WHITE, + SAVEDCOLOR + }; + + explicit raw_ostream(bool unbuffered=false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { + // Start out ready to flush. + OutBufStart = OutBufEnd = OutBufCur = 0; + } + + virtual ~raw_ostream(); + + /// tell - Return the current offset with the file. + uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } + + //===--------------------------------------------------------------------===// + // Configuration Interface + //===--------------------------------------------------------------------===// + + /// SetBuffered - Set the stream to be buffered, with an automatically + /// determined buffer size. + void SetBuffered(); + + /// SetBufferSize - Set the stream to be buffered, using the + /// specified buffer size. + void SetBufferSize(size_t Size) { + flush(); + SetBufferAndMode(new char[Size], Size, InternalBuffer); + } + + size_t GetBufferSize() const { + // If we're supposed to be buffered but haven't actually gotten around + // to allocating the buffer yet, return the value that would be used. + if (BufferMode != Unbuffered && OutBufStart == 0) + return preferred_buffer_size(); + + // Otherwise just return the size of the allocated buffer. + return OutBufEnd - OutBufStart; + } + + /// SetUnbuffered - Set the stream to be unbuffered. When + /// unbuffered, the stream will flush after every write. This routine + /// will also flush the buffer immediately when the stream is being + /// set to unbuffered. + void SetUnbuffered() { + flush(); + SetBufferAndMode(0, 0, Unbuffered); + } + + size_t GetNumBytesInBuffer() const { + return OutBufCur - OutBufStart; + } + + //===--------------------------------------------------------------------===// + // Data Output Interface + //===--------------------------------------------------------------------===// + + void flush() { + if (OutBufCur != OutBufStart) + flush_nonempty(); + } + + raw_ostream &operator<<(char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(unsigned char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(signed char C) { + if (OutBufCur >= OutBufEnd) + return write(C); + *OutBufCur++ = C; + return *this; + } + + raw_ostream &operator<<(StringRef Str) { + // Inline fast path, particularly for strings with a known length. + size_t Size = Str.size(); + + // Make sure we can use the fast path. + if (OutBufCur+Size > OutBufEnd) + return write(Str.data(), Size); + + memcpy(OutBufCur, Str.data(), Size); + OutBufCur += Size; + return *this; + } + + raw_ostream &operator<<(const char *Str) { + // Inline fast path, particularly for constant strings where a sufficiently + // smart compiler will simplify strlen. + + return this->operator<<(StringRef(Str)); + } + + raw_ostream &operator<<(const std::string &Str) { + // Avoid the fast path, it would only increase code size for a marginal win. + return write(Str.data(), Str.length()); + } + + raw_ostream &operator<<(unsigned long N); + raw_ostream &operator<<(long N); + raw_ostream &operator<<(unsigned long long N); + raw_ostream &operator<<(long long N); + raw_ostream &operator<<(const void *P); + raw_ostream &operator<<(unsigned int N) { + return this->operator<<(static_cast(N)); + } + + raw_ostream &operator<<(int N) { + return this->operator<<(static_cast(N)); + } + + raw_ostream &operator<<(double N); + + /// write_hex - Output \arg N in hexadecimal, without any prefix or padding. + raw_ostream &write_hex(unsigned long long N); + + /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and + /// anything that doesn't satisfy std::isprint into an escape sequence. + raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); + + raw_ostream &write(unsigned char C); + raw_ostream &write(const char *Ptr, size_t Size); + + // Formatted output, see the format() function in Support/Format.h. + raw_ostream &operator<<(const format_object_base &Fmt); + + /// indent - Insert 'NumSpaces' spaces. + raw_ostream &indent(unsigned NumSpaces); + + + /// Changes the foreground color of text that will be output from this point + /// forward. + /// @param colors ANSI color to use, the special SAVEDCOLOR can be used to + /// change only the bold attribute, and keep colors untouched + /// @param bold bold/brighter text, default false + /// @param bg if true change the background, default: change foreground + /// @returns itself so it can be used within << invocations + virtual raw_ostream &changeColor(enum Colors, bool = false, bool = false) { + return *this; } + + /// Resets the colors to terminal defaults. Call this when you are done + /// outputting colored text, or before program exit. + virtual raw_ostream &resetColor() { return *this; } + + /// This function determines if this stream is connected to a "tty" or + /// "console" window. That is, the output would be displayed to the user + /// rather than being put on a pipe or stored in a file. + virtual bool is_displayed() const { return false; } + + //===--------------------------------------------------------------------===// + // Subclass Interface + //===--------------------------------------------------------------------===// + +private: + /// write_impl - The is the piece of the class that is implemented + /// by subclasses. This writes the \args Size bytes starting at + /// \arg Ptr to the underlying stream. + /// + /// This function is guaranteed to only be called at a point at which it is + /// safe for the subclass to install a new buffer via SetBuffer. + /// + /// \arg Ptr - The start of the data to be written. For buffered streams this + /// is guaranteed to be the start of the buffer. + /// \arg Size - The number of bytes to be written. + /// + /// \invariant { Size > 0 } + virtual void write_impl(const char *Ptr, size_t Size) = 0; + + // An out of line virtual method to provide a home for the class vtable. + virtual void handle(); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const = 0; + +protected: + /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is + /// intended for use only by subclasses which can arrange for the output to go + /// directly into the desired output buffer, instead of being copied on each + /// flush. + void SetBuffer(char *BufferStart, size_t Size) { + SetBufferAndMode(BufferStart, Size, ExternalBuffer); + } + + /// preferred_buffer_size - Return an efficient buffer size for the + /// underlying output mechanism. + virtual size_t preferred_buffer_size() const; + + /// getBufferStart - Return the beginning of the current stream buffer, or 0 + /// if the stream is unbuffered. + const char *getBufferStart() const { return OutBufStart; } + + //===--------------------------------------------------------------------===// + // Private Interface + //===--------------------------------------------------------------------===// +private: + /// SetBufferAndMode - Install the given buffer and mode. + void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); + + /// flush_nonempty - Flush the current buffer, which is known to be + /// non-empty. This outputs the currently buffered data and resets + /// the buffer to empty. + void flush_nonempty(); + + /// copy_to_buffer - Copy data into the buffer. Size must not be + /// greater than the number of unused bytes in the buffer. + void copy_to_buffer(const char *Ptr, size_t Size); +}; + +//===----------------------------------------------------------------------===// +// File Output Streams +//===----------------------------------------------------------------------===// + +/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. +/// +class raw_fd_ostream : public raw_ostream { + int FD; + bool ShouldClose; + + /// Error This flag is true if an error of any kind has been detected. + /// + bool Error; + + /// Controls whether the stream should attempt to use atomic writes, when + /// possible. + bool UseAtomicWrites; + + uint64_t pos; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const { return pos; } + + /// preferred_buffer_size - Determine an efficient buffer size. + virtual size_t preferred_buffer_size() const; + + /// error_detected - Set the flag indicating that an output error has + /// been encountered. + void error_detected() { Error = true; } + +public: + + enum { + /// F_Excl - When opening a file, this flag makes raw_fd_ostream + /// report an error if the file already exists. + F_Excl = 1, + + /// F_Append - When opening a file, if it already exists append to the + /// existing file instead of returning an error. This may not be specified + /// with F_Excl. + F_Append = 2, + + /// F_Binary - The file should be opened in binary mode on platforms that + /// make this distinction. + F_Binary = 4 + }; + + /// raw_fd_ostream - Open the specified file for writing. If an error occurs, + /// information about the error is put into ErrorInfo, and the stream should + /// be immediately destroyed; the string will be empty if no error occurred. + /// This allows optional flags to control how the file will be opened. + /// + /// As a special case, if Filename is "-", then the stream will use + /// STDOUT_FILENO instead of opening a file. Note that it will still consider + /// itself to own the file descriptor. In particular, it will close the + /// file descriptor when it is done (this is necessary to detect + /// output errors). + raw_fd_ostream(const char *Filename, std::string &ErrorInfo, + unsigned Flags = 0); + + /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If + /// ShouldClose is true, this closes the file when the stream is destroyed. + raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); + + ~raw_fd_ostream(); + + /// close - Manually flush the stream and close the file. + /// Note that this does not call fsync. + void close(); + + /// seek - Flushes the stream and repositions the underlying file descriptor + /// position to the offset specified from the beginning of the file. + uint64_t seek(uint64_t off); + + /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for + /// individual output routines where possible. + /// + /// Note that because raw_ostream's are typically buffered, this flag is only + /// sensible when used on unbuffered streams which will flush their output + /// immediately. + void SetUseAtomicWrites(bool Value) { + UseAtomicWrites = Value; + } + + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, + bool bg=false); + virtual raw_ostream &resetColor(); + + virtual bool is_displayed() const; + + /// has_error - Return the value of the flag in this raw_fd_ostream indicating + /// whether an output error has been encountered. + /// This doesn't implicitly flush any pending output. Also, it doesn't + /// guarantee to detect all errors unless the the stream has been closed. + bool has_error() const { + return Error; + } + + /// clear_error - Set the flag read by has_error() to false. If the error + /// flag is set at the time when this raw_ostream's destructor is called, + /// report_fatal_error is called to report the error. Use clear_error() + /// after handling the error to avoid this behavior. + /// + /// "Errors should never pass silently. + /// Unless explicitly silenced." + /// - from The Zen of Python, by Tim Peters + /// + void clear_error() { + Error = false; + } +}; + +/// outs() - This returns a reference to a raw_ostream for standard output. +/// Use it like: outs() << "foo" << "bar"; +raw_ostream &outs(); + +/// errs() - This returns a reference to a raw_ostream for standard error. +/// Use it like: errs() << "foo" << "bar"; +raw_ostream &errs(); + +/// nulls() - This returns a reference to a raw_ostream which simply discards +/// output. +raw_ostream &nulls(); + +//===----------------------------------------------------------------------===// +// Output Stream Adaptors +//===----------------------------------------------------------------------===// + +/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a +/// simple adaptor class. This class does not encounter output errors. +class raw_string_ostream : public raw_ostream { + std::string &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const { return OS.size(); } +public: + explicit raw_string_ostream(std::string &O) : OS(O) {} + ~raw_string_ostream(); + + /// str - Flushes the stream contents to the target string and returns + /// the string's reference. + std::string& str() { + flush(); + return OS; + } +}; + +/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or +/// SmallString. This is a simple adaptor class. This class does not +/// encounter output errors. +class raw_svector_ostream : public raw_ostream { + SmallVectorImpl &OS; + + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const; +public: + /// Construct a new raw_svector_ostream. + /// + /// \arg O - The vector to write to; this should generally have at least 128 + /// bytes free to avoid any extraneous memory overhead. + explicit raw_svector_ostream(SmallVectorImpl &O); + ~raw_svector_ostream(); + + /// resync - This is called when the SmallVector we're appending to is changed + /// outside of the raw_svector_ostream's control. It is only safe to do this + /// if the raw_svector_ostream has previously been flushed. + void resync(); + + /// str - Flushes the stream contents to the target vector and return a + /// StringRef for the vector contents. + StringRef str(); +}; + +/// raw_null_ostream - A raw_ostream that discards all output. +class raw_null_ostream : public raw_ostream { + /// write_impl - See raw_ostream::write_impl. + virtual void write_impl(const char *Ptr, size_t size); + + /// current_pos - Return the current position within the stream, not + /// counting the bytes currently in the buffer. + virtual uint64_t current_pos() const; + +public: + explicit raw_null_ostream() {} + ~raw_null_ostream(); +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Support/system_error.h b/final/include/llvm/Support/system_error.h new file mode 100644 index 00000000000..e5306ecfb35 --- /dev/null +++ b/final/include/llvm/Support/system_error.h @@ -0,0 +1,910 @@ +//===---------------------------- system_error ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This was lifted from libc++ and modified for C++03. This is called +// system_error even though it does not define that class because that's what +// it's called in C++0x. We don't define system_error because it is only used +// for exception handling, which we don't use in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H +#define LLVM_SYSTEM_SYSTEM_ERROR_H + +/* + system_error synopsis + +namespace std +{ + +class error_category +{ +public: + virtual ~error_category(); + + error_category(const error_category&) = delete; + error_category& operator=(const error_category&) = delete; + + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int ev) const; + virtual bool equivalent(int code, const error_condition& condition) const; + virtual bool equivalent(const error_code& code, int condition) const; + virtual std::string message(int ev) const = 0; + + bool operator==(const error_category& rhs) const; + bool operator!=(const error_category& rhs) const; + bool operator<(const error_category& rhs) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +template struct is_error_code_enum + : public false_type {}; + +template struct is_error_condition_enum + : public false_type {}; + +class error_code +{ +public: + // constructors: + error_code(); + error_code(int val, const error_category& cat); + template + error_code(ErrorCodeEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template + error_code& operator=(ErrorCodeEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + error_condition default_error_condition() const; + std::string message() const; + explicit operator bool() const; +}; + +// non-member functions: +bool operator<(const error_code& lhs, const error_code& rhs); +template + basic_ostream& + operator<<(basic_ostream& os, const error_code& ec); + +class error_condition +{ +public: + // constructors: + error_condition(); + error_condition(int val, const error_category& cat); + template + error_condition(ErrorConditionEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template + error_condition& operator=(ErrorConditionEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + std::string message() const; + explicit operator bool() const; +}; + +bool operator<(const error_condition& lhs, const error_condition& rhs); + +class system_error + : public runtime_error +{ +public: + system_error(error_code ec, const std::string& what_arg); + system_error(error_code ec, const char* what_arg); + system_error(error_code ec); + system_error(int ev, const error_category& ecat, const std::string& what_arg); + system_error(int ev, const error_category& ecat, const char* what_arg); + system_error(int ev, const error_category& ecat); + + const error_code& code() const throw(); + const char* what() const throw(); +}; + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +template <> struct is_error_condition_enum : true_type { } + +error_code make_error_code(errc e); +error_condition make_error_condition(errc e); + +// Comparison operators: +bool operator==(const error_code& lhs, const error_code& rhs); +bool operator==(const error_code& lhs, const error_condition& rhs); +bool operator==(const error_condition& lhs, const error_code& rhs); +bool operator==(const error_condition& lhs, const error_condition& rhs); +bool operator!=(const error_code& lhs, const error_code& rhs); +bool operator!=(const error_code& lhs, const error_condition& rhs); +bool operator!=(const error_condition& lhs, const error_code& rhs); +bool operator!=(const error_condition& lhs, const error_condition& rhs); + +template <> struct hash; + +} // std + +*/ + +#include "llvm/Config/config.h" +#include "llvm/Support/type_traits.h" +#include +#include + +// This must be here instead of a .inc file because it is used in the definition +// of the enum values below. +#ifdef LLVM_ON_WIN32 + + // The following numbers were taken from VS2010. +# ifndef EAFNOSUPPORT +# define EAFNOSUPPORT 102 +# endif +# ifndef EADDRINUSE +# define EADDRINUSE 100 +# endif +# ifndef EADDRNOTAVAIL +# define EADDRNOTAVAIL 101 +# endif +# ifndef EISCONN +# define EISCONN 113 +# endif +# ifndef E2BIG +# define E2BIG 7 +# endif +# ifndef EDOM +# define EDOM 33 +# endif +# ifndef EFAULT +# define EFAULT 14 +# endif +# ifndef EBADF +# define EBADF 9 +# endif +# ifndef EBADMSG +# define EBADMSG 104 +# endif +# ifndef EPIPE +# define EPIPE 32 +# endif +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# endif +# ifndef EALREADY +# define EALREADY 103 +# endif +# ifndef ECONNREFUSED +# define ECONNREFUSED 107 +# endif +# ifndef ECONNRESET +# define ECONNRESET 108 +# endif +# ifndef EXDEV +# define EXDEV 18 +# endif +# ifndef EDESTADDRREQ +# define EDESTADDRREQ 109 +# endif +# ifndef EBUSY +# define EBUSY 16 +# endif +# ifndef ENOTEMPTY +# define ENOTEMPTY 41 +# endif +# ifndef ENOEXEC +# define ENOEXEC 8 +# endif +# ifndef EEXIST +# define EEXIST 17 +# endif +# ifndef EFBIG +# define EFBIG 27 +# endif +# ifndef ENAMETOOLONG +# define ENAMETOOLONG 38 +# endif +# ifndef ENOSYS +# define ENOSYS 40 +# endif +# ifndef EHOSTUNREACH +# define EHOSTUNREACH 110 +# endif +# ifndef EIDRM +# define EIDRM 111 +# endif +# ifndef EILSEQ +# define EILSEQ 42 +# endif +# ifndef ENOTTY +# define ENOTTY 25 +# endif +# ifndef EINTR +# define EINTR 4 +# endif +# ifndef EINVAL +# define EINVAL 22 +# endif +# ifndef ESPIPE +# define ESPIPE 29 +# endif +# ifndef EIO +# define EIO 5 +# endif +# ifndef EISDIR +# define EISDIR 21 +# endif +# ifndef EMSGSIZE +# define EMSGSIZE 115 +# endif +# ifndef ENETDOWN +# define ENETDOWN 116 +# endif +# ifndef ENETRESET +# define ENETRESET 117 +# endif +# ifndef ENETUNREACH +# define ENETUNREACH 118 +# endif +# ifndef ENOBUFS +# define ENOBUFS 119 +# endif +# ifndef ECHILD +# define ECHILD 10 +# endif +# ifndef ENOLINK +# define ENOLINK 121 +# endif +# ifndef ENOLCK +# define ENOLCK 39 +# endif +# ifndef ENODATA +# define ENODATA 120 +# endif +# ifndef ENOMSG +# define ENOMSG 122 +# endif +# ifndef ENOPROTOOPT +# define ENOPROTOOPT 123 +# endif +# ifndef ENOSPC +# define ENOSPC 28 +# endif +# ifndef ENOSR +# define ENOSR 124 +# endif +# ifndef ENXIO +# define ENXIO 6 +# endif +# ifndef ENODEV +# define ENODEV 19 +# endif +# ifndef ENOENT +# define ENOENT 2 +# endif +# ifndef ESRCH +# define ESRCH 3 +# endif +# ifndef ENOTDIR +# define ENOTDIR 20 +# endif +# ifndef ENOTSOCK +# define ENOTSOCK 128 +# endif +# ifndef ENOSTR +# define ENOSTR 125 +# endif +# ifndef ENOTCONN +# define ENOTCONN 126 +# endif +# ifndef ENOMEM +# define ENOMEM 12 +# endif +# ifndef ENOTSUP +# define ENOTSUP 129 +# endif +# ifndef ECANCELED +# define ECANCELED 105 +# endif +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# endif +# ifndef EPERM +# define EPERM 1 +# endif +# ifndef EOPNOTSUPP +# define EOPNOTSUPP 130 +# endif +# ifndef EWOULDBLOCK +# define EWOULDBLOCK 140 +# endif +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# endif +# ifndef EACCES +# define EACCES 13 +# endif +# ifndef EPROTO +# define EPROTO 134 +# endif +# ifndef EPROTONOSUPPORT +# define EPROTONOSUPPORT 135 +# endif +# ifndef EROFS +# define EROFS 30 +# endif +# ifndef EDEADLK +# define EDEADLK 36 +# endif +# ifndef EAGAIN +# define EAGAIN 11 +# endif +# ifndef ERANGE +# define ERANGE 34 +# endif +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# endif +# ifndef ETIME +# define ETIME 137 +# endif +# ifndef ETXTBSY +# define ETXTBSY 139 +# endif +# ifndef ETIMEDOUT +# define ETIMEDOUT 138 +# endif +# ifndef ENFILE +# define ENFILE 23 +# endif +# ifndef EMFILE +# define EMFILE 24 +# endif +# ifndef EMLINK +# define EMLINK 31 +# endif +# ifndef ELOOP +# define ELOOP 114 +# endif +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# endif +# ifndef EPROTOTYPE +# define EPROTOTYPE 136 +# endif +#endif + +namespace llvm { + +template +struct integral_constant { + typedef T value_type; + static const value_type value = v; + typedef integral_constant type; + operator value_type() { return value; } +}; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +// is_error_code_enum + +template struct is_error_code_enum : public false_type {}; + +// is_error_condition_enum + +template struct is_error_condition_enum : public false_type {}; + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +struct errc { +enum _ { + success = 0, + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, +#ifdef EBADMSG + bad_message = EBADMSG, +#else + bad_message = EINVAL, +#endif + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, +#ifdef ENOLINK + no_link = ENOLINK, +#else + no_link = EINVAL, +#endif + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, +#ifdef ECANCELED + operation_canceled = ECANCELED, +#else + operation_canceled = EINVAL, +#endif + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#else + owner_dead = EINVAL, +#endif + permission_denied = EACCES, +#ifdef EPROTO + protocol_error = EPROTO, +#else + protocol_error = EINVAL, +#endif + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#else + state_not_recoverable = EINVAL, +#endif +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; + + _ v_; + + errc(_ v) : v_(v) {} + operator int() const {return v_;} +}; + +template <> struct is_error_condition_enum : true_type { }; + +template <> struct is_error_condition_enum : true_type { }; + +class error_condition; +class error_code; + +// class error_category + +class _do_message; + +class error_category +{ +public: + virtual ~error_category(); + +private: + error_category(); + error_category(const error_category&);// = delete; + error_category& operator=(const error_category&);// = delete; + +public: + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int _ev) const; + virtual bool equivalent(int _code, const error_condition& _condition) const; + virtual bool equivalent(const error_code& _code, int _condition) const; + virtual std::string message(int _ev) const = 0; + + bool operator==(const error_category& _rhs) const {return this == &_rhs;} + + bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} + + bool operator< (const error_category& _rhs) const {return this < &_rhs;} + + friend class _do_message; +}; + +class _do_message : public error_category +{ +public: + virtual std::string message(int ev) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +/// Get the error_category used for errno values from POSIX functions. This is +/// the same as the system_category on POISIX systems, but is the same as the +/// generic_category on Windows. +const error_category& posix_category(); + +class error_condition +{ + int _val_; + const error_category* _cat_; +public: + error_condition() : _val_(0), _cat_(&generic_category()) {} + + error_condition(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template + error_condition(E _e, typename enable_if_c< + is_error_condition_enum::value + >::type* = 0) + {*this = make_error_condition(_e);} + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template + typename enable_if_c + < + is_error_condition_enum::value, + error_condition& + >::type + operator=(E _e) + {*this = make_error_condition(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &generic_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_condition make_error_condition(errc _e) { + return error_condition(static_cast(_e), generic_category()); +} + +inline bool operator<(const error_condition& _x, const error_condition& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +// error_code + +class error_code { + int _val_; + const error_category* _cat_; +public: + error_code() : _val_(0), _cat_(&system_category()) {} + + error_code(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template + error_code(E _e, typename enable_if_c< + is_error_code_enum::value + >::type* = 0) { + *this = make_error_code(_e); + } + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template + typename enable_if_c + < + is_error_code_enum::value, + error_code& + >::type + operator=(E _e) + {*this = make_error_code(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &system_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + + error_condition default_error_condition() const + {return _cat_->default_error_condition(_val_);} + + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_code make_error_code(errc _e) { + return error_code(static_cast(_e), generic_category()); +} + +inline bool operator<(const error_code& _x, const error_code& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +inline bool operator==(const error_code& _x, const error_code& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator==(const error_code& _x, const error_condition& _y) { + return _x.category().equivalent(_x.value(), _y) + || _y.category().equivalent(_x, _y.value()); +} + +inline bool operator==(const error_condition& _x, const error_code& _y) { + return _y == _x; +} + +inline bool operator==(const error_condition& _x, const error_condition& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator!=(const error_code& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_code& _x, const error_condition& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_condition& _y) { + return !(_x == _y); +} + +// Windows errors. + +// To construct an error_code after an API error: +// +// error_code( ::GetLastError(), system_category() ) +struct windows_error { +enum _ { + success = 0, + // These names and values are based on Windows WinError.h + // This is not a complete list. Add to this list if you need to explicitly + // check for it. + invalid_function = 1, // ERROR_INVALID_FUNCTION, + file_not_found = 2, // ERROR_FILE_NOT_FOUND, + path_not_found = 3, // ERROR_PATH_NOT_FOUND, + too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, + access_denied = 5, // ERROR_ACCESS_DENIED, + invalid_handle = 6, // ERROR_INVALID_HANDLE, + arena_trashed = 7, // ERROR_ARENA_TRASHED, + not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, + invalid_block = 9, // ERROR_INVALID_BLOCK, + bad_environment = 10, // ERROR_BAD_ENVIRONMENT, + bad_format = 11, // ERROR_BAD_FORMAT, + invalid_access = 12, // ERROR_INVALID_ACCESS, + outofmemory = 14, // ERROR_OUTOFMEMORY, + invalid_drive = 15, // ERROR_INVALID_DRIVE, + current_directory = 16, // ERROR_CURRENT_DIRECTORY, + not_same_device = 17, // ERROR_NOT_SAME_DEVICE, + no_more_files = 18, // ERROR_NO_MORE_FILES, + write_protect = 19, // ERROR_WRITE_PROTECT, + bad_unit = 20, // ERROR_BAD_UNIT, + not_ready = 21, // ERROR_NOT_READY, + bad_command = 22, // ERROR_BAD_COMMAND, + crc = 23, // ERROR_CRC, + bad_length = 24, // ERROR_BAD_LENGTH, + seek = 25, // ERROR_SEEK, + not_dos_disk = 26, // ERROR_NOT_DOS_DISK, + sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, + out_of_paper = 28, // ERROR_OUT_OF_PAPER, + write_fault = 29, // ERROR_WRITE_FAULT, + read_fault = 30, // ERROR_READ_FAULT, + gen_failure = 31, // ERROR_GEN_FAILURE, + sharing_violation = 32, // ERROR_SHARING_VIOLATION, + lock_violation = 33, // ERROR_LOCK_VIOLATION, + wrong_disk = 34, // ERROR_WRONG_DISK, + sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, + handle_eof = 38, // ERROR_HANDLE_EOF, + handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, + rem_not_list = 51, // ERROR_REM_NOT_LIST, + dup_name = 52, // ERROR_DUP_NAME, + bad_net_path = 53, // ERROR_BAD_NETPATH, + network_busy = 54, // ERROR_NETWORK_BUSY, + file_exists = 80, // ERROR_FILE_EXISTS, + cannot_make = 82, // ERROR_CANNOT_MAKE, + broken_pipe = 109, // ERROR_BROKEN_PIPE, + open_failed = 110, // ERROR_OPEN_FAILED, + buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, + disk_full = 112, // ERROR_DISK_FULL, + insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, + lock_failed = 167, // ERROR_LOCK_FAILED, + busy = 170, // ERROR_BUSY, + cancel_violation = 173, // ERROR_CANCEL_VIOLATION, + already_exists = 183 // ERROR_ALREADY_EXISTS +}; + _ v_; + + windows_error(_ v) : v_(v) {} + explicit windows_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + + +template <> struct is_error_code_enum : true_type { }; + +template <> struct is_error_code_enum : true_type { }; + +inline error_code make_error_code(windows_error e) { + return error_code(static_cast(e), system_category()); +} + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Support/type_traits.h b/final/include/llvm/Support/type_traits.h new file mode 100644 index 00000000000..515295bdd66 --- /dev/null +++ b/final/include/llvm/Support/type_traits.h @@ -0,0 +1,126 @@ +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- 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 a template class that determines if a type is a class or +// not. The basic mechanism, based on using the pointer to member function of +// a zero argument to a function was "boosted" from the boost type_traits +// library. See http://www.boost.org/ for all the gory details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPE_TRAITS_H +#define LLVM_SUPPORT_TYPE_TRAITS_H + +#include + +// This is actually the conforming implementation which works with abstract +// classes. However, enough compilers have trouble with it that most will use +// the one in boost/type_traits/object_traits.hpp. This implementation actually +// works with VC7.0, but other interactions seem to fail when we use it. + +namespace llvm { + +namespace dont_use +{ + // These two functions should never be used. They are helpers to + // the is_class template below. They cannot be located inside + // is_class because doing so causes at least GCC to think that + // the value of the "value" enumerator is not constant. Placing + // them out here (for some strange reason) allows the sizeof + // operator against them to magically be constant. This is + // important to make the is_class::value idiom zero cost. it + // evaluates to a constant 1 or 0 depending on whether the + // parameter T is a class or not (respectively). + template char is_class_helper(void(T::*)()); + template double is_class_helper(...); +} + +template +struct is_class +{ + // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For + // more details: + // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 + public: + enum { value = sizeof(char) == sizeof(dont_use::is_class_helper(0)) }; +}; + + +/// isPodLike - This is a type trait that is used to determine whether a given +/// type can be copied around with memcpy instead of running ctors etc. +template +struct isPodLike { + // If we don't know anything else, we can (at least) assume that all non-class + // types are PODs. + static const bool value = !is_class::value; +}; + +// std::pair's are pod-like if their elements are. +template +struct isPodLike > { + static const bool value = isPodLike::value & isPodLike::value; +}; + + +/// \brief Metafunction that determines whether the two given types are +/// equivalent. +template +struct is_same { + static const bool value = false; +}; + +template +struct is_same { + static const bool value = true; +}; + +// enable_if_c - Enable/disable a template based on a metafunction +template +struct enable_if_c { + typedef T type; +}; + +template struct enable_if_c { }; + +// enable_if - Enable/disable a template based on a metafunction +template +struct enable_if : public enable_if_c { }; + +namespace dont_use { + template char base_of_helper(const volatile Base*); + template double base_of_helper(...); +} + +/// is_base_of - Metafunction to determine whether one type is a base class of +/// (or identical to) another type. +template +struct is_base_of { + static const bool value + = is_class::value && is_class::value && + sizeof(char) == sizeof(dont_use::base_of_helper((Derived*)0)); +}; + +// remove_pointer - Metafunction to turn Foo* into Foo. Defined in +// C++0x [meta.trans.ptr]. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + typedef T type; }; + +template +struct conditional { typedef T type; }; + +template +struct conditional { typedef F type; }; + +} + +#endif diff --git a/final/include/llvm/SymbolTableListTraits.h b/final/include/llvm/SymbolTableListTraits.h new file mode 100644 index 00000000000..91a4eb99ff0 --- /dev/null +++ b/final/include/llvm/SymbolTableListTraits.h @@ -0,0 +1,79 @@ +//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- 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 generic class that is used to implement the automatic +// symbol table manipulation that occurs when you put (for example) a named +// instruction into a basic block. +// +// The way that this is implemented is by using a special traits class with the +// intrusive list that makes up the list of instructions in a basic block. When +// a new element is added to the list of instructions, the traits class is +// notified, allowing the symbol table to be updated. +// +// This generic class implements the traits class. It must be generic so that +// it can work for all uses it, which include lists of instructions, basic +// blocks, arguments, functions, global variables, etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYMBOLTABLELISTTRAITS_H +#define LLVM_SYMBOLTABLELISTTRAITS_H + +#include "llvm/ADT/ilist.h" + +namespace llvm { +class ValueSymbolTable; + +template class ilist_iterator; +template class iplist; +template struct ilist_traits; + +// ValueSubClass - The type of objects that I hold, e.g. Instruction. +// ItemParentClass - The type of object that owns the list, e.g. BasicBlock. +// +template +class SymbolTableListTraits : public ilist_default_traits { + typedef ilist_traits TraitsClass; +public: + SymbolTableListTraits() {} + + /// getListOwner - Return the object that owns this list. If this is a list + /// of instructions, it returns the BasicBlock that owns them. + ItemParentClass *getListOwner() { + typedef iplist ItemParentClass::*Sublist; + size_t Offset(size_t(&((ItemParentClass*)0->*ItemParentClass:: + getSublistAccess(static_cast(0))))); + iplist* Anchor(static_cast*>(this)); + return reinterpret_cast(reinterpret_cast(Anchor)- + Offset); + } + + static iplist &getList(ItemParentClass *Par) { + return Par->*(Par->getSublistAccess((ValueSubClass*)0)); + } + + static ValueSymbolTable *getSymTab(ItemParentClass *Par) { + return Par ? toPtr(Par->getValueSymbolTable()) : 0; + } + + void addNodeToList(ValueSubClass *V); + void removeNodeFromList(ValueSubClass *V); + void transferNodesFromList(ilist_traits &L2, + ilist_iterator first, + ilist_iterator last); +//private: + template + void setSymTabObject(TPtr *, TPtr); + static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; } + static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/Mangler.h b/final/include/llvm/Target/Mangler.h new file mode 100644 index 00000000000..c1c118b08ca --- /dev/null +++ b/final/include/llvm/Target/Mangler.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/Mangler.h - Self-contained name mangler -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for various backends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANGLER_H +#define LLVM_SUPPORT_MANGLER_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { +class StringRef; +class Twine; +class Value; +class GlobalValue; +template class SmallVectorImpl; +class MCContext; +class MCSymbol; +class TargetData; + +class Mangler { +public: + enum ManglerPrefixTy { + Default, ///< Emit default string before each symbol. + Private, ///< Emit "private" prefix before each symbol. + LinkerPrivate ///< Emit "linker private" prefix before each symbol. + }; + +private: + MCContext &Context; + const TargetData &TD; + + /// AnonGlobalIDs - We need to give global values the same name every time + /// they are mangled. This keeps track of the number we give to anonymous + /// ones. + /// + DenseMap AnonGlobalIDs; + + /// NextAnonGlobalID - This simple counter is used to unique value names. + /// + unsigned NextAnonGlobalID; + +public: + Mangler(MCContext &context, const TargetData &td) + : Context(context), TD(td), NextAnonGlobalID(1) {} + + /// getSymbol - Return the MCSymbol for the specified global value. This + /// symbol is the main label that is the address of the global. + MCSymbol *getSymbol(const GlobalValue *GV); + + + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix + /// and the specified global variable's name. If the global variable doesn't + /// have a name, this fills in a unique name for the global. + void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, + bool isImplicitlyPrivate); + + /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix + /// and the specified name as the global variable name. GVName must not be + /// empty. + void getNameWithPrefix(SmallVectorImpl &OutName, const Twine &GVName, + ManglerPrefixTy PrefixTy = Mangler::Default); +}; + +} // End llvm namespace + +#endif // LLVM_SUPPORT_MANGLER_H diff --git a/final/include/llvm/Target/SubtargetFeature.h b/final/include/llvm/Target/SubtargetFeature.h new file mode 100644 index 00000000000..6c21ae9583e --- /dev/null +++ b/final/include/llvm/Target/SubtargetFeature.h @@ -0,0 +1,119 @@ +//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- 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 and manages user or tool specified CPU characteristics. +// The intent is to be able to package specific features that should or should +// not be used on a specific target processor. A tool, such as llc, could, as +// as example, gather chip info from the command line, a long with features +// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_SUBTARGETFEATURE_H +#define LLVM_TARGET_SUBTARGETFEATURE_H + +#include +#include +#include +#include "llvm/ADT/Triple.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class raw_ostream; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatureKV - Used to provide key value pairs for feature and +/// CPU bit flags. +// +struct SubtargetFeatureKV { + const char *Key; // K-V key string + const char *Desc; // Help descriptor + uint32_t Value; // K-V integer value + uint32_t Implies; // K-V bit mask + + // Compare routine for std binary search + bool operator<(const SubtargetFeatureKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary +/// pointers. +// +struct SubtargetInfoKV { + const char *Key; // K-V key string + void *Value; // K-V pointer value + + // Compare routine for std binary search + bool operator<(const SubtargetInfoKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// specific features. Features are encoded as a string of the form +/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU +/// value is "generic" then the CPU subtype should be generic for the target. +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +/// + +class SubtargetFeatures { + std::vector Features; // Subtarget features as a vector +public: + explicit SubtargetFeatures(const std::string &Initial = std::string()); + + /// Features string accessors. + std::string getString() const; + void setString(const std::string &Initial); + + /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. + void setCPU(const std::string &String); + + /// Setting CPU string only if no string is set. + void setCPUIfNone(const std::string &String); + + /// Returns current CPU string. + const std::string & getCPU() const; + + /// Adding Features. + void AddFeature(const std::string &String, bool IsEnabled = true); + + /// Get feature bits. + uint32_t getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); + + /// Get info pointer + void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + + /// Print feature string. + void print(raw_ostream &OS) const; + + // Dump feature info. + void dump() const; + + /// Retrieve a formatted string of the default features for the specified + /// target triple. + void getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple); +}; + +} // End namespace llvm + +#endif diff --git a/final/include/llvm/Target/Target.td b/final/include/llvm/Target/Target.td new file mode 100644 index 00000000000..0f7e6aaaf2f --- /dev/null +++ b/final/include/llvm/Target/Target.td @@ -0,0 +1,711 @@ +//===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// +// +// 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 target-independent interfaces which should be +// implemented by each target which is using a TableGen based code generator. +// +//===----------------------------------------------------------------------===// + +// Include all information about LLVM intrinsics. +include "llvm/Intrinsics.td" + +//===----------------------------------------------------------------------===// +// Register file description - These classes are used to fill in the target +// description classes. + +class RegisterClass; // Forward def + +// SubRegIndex - Use instances of SubRegIndex to identify subregisters. +class SubRegIndex { + string Namespace = ""; +} + +// Register - You should define one instance of this class for each register +// in the target machine. String n will become the "name" of the register. +class Register { + string Namespace = ""; + string AsmName = n; + + // SpillSize - If this value is set to a non-zero value, it is the size in + // bits of the spill slot required to hold this register. If this value is + // set to zero, the information is inferred from any register classes the + // register belongs to. + int SpillSize = 0; + + // SpillAlignment - This value is used to specify the alignment required for + // spilling the register. Like SpillSize, this should only be explicitly + // specified if the register is not in a register class. + int SpillAlignment = 0; + + // Aliases - A list of registers that this register overlaps with. A read or + // modification of this register can potentially read or modify the aliased + // registers. + list Aliases = []; + + // SubRegs - A list of registers that are parts of this register. Note these + // are "immediate" sub-registers and the registers within the list do not + // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], + // not [AX, AH, AL]. + list SubRegs = []; + + // SubRegIndices - For each register in SubRegs, specify the SubRegIndex used + // to address it. Sub-sub-register indices are automatically inherited from + // SubRegs. + list SubRegIndices = []; + + // CompositeIndices - Specify subreg indices that don't correspond directly to + // a register in SubRegs and are not inherited. The following formats are + // supported: + // + // (a) Identity - Reg:a == Reg + // (a b) Alias - Reg:a == Reg:b + // (a b,c) Composite - Reg:a == (Reg:b):c + // + // This can be used to disambiguate a sub-sub-register that exists in more + // than one subregister and other weird stuff. + list CompositeIndices = []; + + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the .h file in the + // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. + list DwarfNumbers = []; +} + +// RegisterWithSubRegs - This can be used to define instances of Register which +// need to specify sub-registers. +// List "subregs" specifies which registers are sub-registers to this one. This +// is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. +// This allows the code generator to be careful not to put two values with +// overlapping live ranges into registers which alias. +class RegisterWithSubRegs subregs> : Register { + let SubRegs = subregs; +} + +// RegisterClass - Now that all of the registers are defined, and aliases +// between registers are defined, specify which registers belong to which +// register classes. This also defines the default allocation order of +// registers by register allocators. +// +class RegisterClass regTypes, int alignment, + list regList> { + string Namespace = namespace; + + // RegType - Specify the list ValueType of the registers in this register + // class. Note that all registers in a register class must have the same + // ValueTypes. This is a list because some targets permit storing different + // types in same register, for example vector values with 128-bit total size, + // but different count/size of items, like SSE on x86. + // + list RegTypes = regTypes; + + // Size - Specify the spill size in bits of the registers. A default value of + // zero lets tablgen pick an appropriate size. + int Size = 0; + + // Alignment - Specify the alignment required of the registers when they are + // stored or loaded to memory. + // + int Alignment = alignment; + + // CopyCost - This value is used to specify the cost of copying a value + // between two registers in this register class. The default value is one + // meaning it takes a single instruction to perform the copying. A negative + // value means copying is extremely expensive or impossible. + int CopyCost = 1; + + // MemberList - Specify which registers are in this class. If the + // allocation_order_* method are not specified, this also defines the order of + // allocation used by the register allocator. + // + list MemberList = regList; + + // SubRegClasses - Specify the register class of subregisters as a list of + // dags: (RegClass SubRegIndex, SubRegindex, ...) + list SubRegClasses = []; + + // MethodProtos/MethodBodies - These members can be used to insert arbitrary + // code into a generated register class. The normal usage of this is to + // overload virtual methods. + code MethodProtos = [{}]; + code MethodBodies = [{}]; +} + + +//===----------------------------------------------------------------------===// +// DwarfRegNum - This class provides a mapping of the llvm register enumeration +// to the register numbering used by gcc and gdb. These values are used by a +// debug information writer to describe where values may be located during +// execution. +class DwarfRegNum Numbers> { + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the .h file in the + // directory llvmgcc/gcc/config// and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. + list DwarfNumbers = Numbers; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for scheduling +// +include "llvm/Target/TargetSchedule.td" + +class Predicate; // Forward def + +//===----------------------------------------------------------------------===// +// Instruction set description - These classes correspond to the C++ classes in +// the Target/TargetInstrInfo.h file. +// +class Instruction { + string Namespace = ""; + + dag OutOperandList; // An dag containing the MI def operand list. + dag InOperandList; // An dag containing the MI use operand list. + string AsmString = ""; // The .s format to print the instruction with. + + // Pattern - Set to the DAG pattern for this instruction, if we know of one, + // otherwise, uninitialized. + list Pattern; + + // The follow state will eventually be inferred automatically from the + // instruction pattern. + + list Uses = []; // Default to using no non-operand registers + list Defs = []; // Default to modifying no non-operand registers + + // Predicates - List of predicates which will be turned into isel matching + // code. + list Predicates = []; + + // Code size. + int CodeSize = 0; + + // Added complexity passed onto matching pattern. + int AddedComplexity = 0; + + // These bits capture information about the high-level semantics of the + // instruction. + bit isReturn = 0; // Is this instruction a return instruction? + bit isBranch = 0; // Is this instruction a branch instruction? + bit isIndirectBranch = 0; // Is this instruction an indirect branch? + bit isCompare = 0; // Is this instruction a comparison instruction? + bit isMoveImm = 0; // Is this instruction a move immediate instruction? + bit isBarrier = 0; // Can control flow fall through this instruction? + bit isCall = 0; // Is this instruction a call instruction? + bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? + bit mayLoad = 0; // Is it possible for this inst to read memory? + bit mayStore = 0; // Is it possible for this inst to write memory? + bit isConvertibleToThreeAddress = 0; // Can this 2-addr instruction promote? + bit isCommutable = 0; // Is this 3 operand instruction commutable? + bit isTerminator = 0; // Is this part of the terminator for a basic block? + bit isReMaterializable = 0; // Is this instruction re-materializable? + bit isPredicable = 0; // Is this instruction predicable? + bit hasDelaySlot = 0; // Does this instruction have an delay slot? + bit usesCustomInserter = 0; // Pseudo instr needing special help. + bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? + bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? + bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. + bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? + bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? + + // Side effect flags - When set, the flags have these meanings: + // + // hasSideEffects - The instruction has side effects that are not + // captured by any operands of the instruction or other flags. + // + // neverHasSideEffects - Set on an instruction with no pattern if it has no + // side effects. + bit hasSideEffects = 0; + bit neverHasSideEffects = 0; + + // Is this instruction a "real" instruction (with a distinct machine + // encoding), or is it a pseudo instruction used for codegen modeling + // purposes. + bit isCodeGenOnly = 0; + + // Is this instruction a pseudo instruction for use by the assembler parser. + bit isAsmParserOnly = 0; + + InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. + + string Constraints = ""; // OperandConstraint, e.g. $src = $dst. + + /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not + /// be encoded into the output machineinstr. + string DisableEncoding = ""; + + string PostEncoderMethod = ""; + string DecoderMethod = ""; + + /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. + bits<64> TSFlags = 0; + + ///@name Assembler Parser Support + ///@{ + + string AsmMatchConverter = ""; + + ///@} +} + +/// Predicates - These are extra conditionals which are turned into instruction +/// selector matching code. Currently each predicate is just a string. +class Predicate { + string CondString = cond; + + /// AssemblerMatcherPredicate - If this feature can be used by the assembler + /// matcher, this is true. Targets should set this by inheriting their + /// feature from the AssemblerPredicate class in addition to Predicate. + bit AssemblerMatcherPredicate = 0; +} + +/// NoHonorSignDependentRounding - This predicate is true if support for +/// sign-dependent-rounding is not enabled. +def NoHonorSignDependentRounding + : Predicate<"!HonorSignDependentRoundingFPMath()">; + +class Requires preds> { + list Predicates = preds; +} + +/// ops definition - This is just a simple marker used to identify the operand +/// list for an instruction. outs and ins are identical both syntactically and +/// semanticallyr; they are used to define def operands and use operands to +/// improve readibility. This should be used like this: +/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. +def ops; +def outs; +def ins; + +/// variable_ops definition - Mark this instruction as taking a variable number +/// of operands. +def variable_ops; + + +/// PointerLikeRegClass - Values that are designed to have pointer width are +/// derived from this. TableGen treats the register class as having a symbolic +/// type that it doesn't know, and resolves the actual regclass to use by using +/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time. +class PointerLikeRegClass { + int RegClassKind = Kind; +} + + +/// ptr_rc definition - Mark this operand as being a pointer value whose +/// register class is resolved dynamically via a callback to TargetInstrInfo. +/// FIXME: We should probably change this to a class which contain a list of +/// flags. But currently we have but one flag. +def ptr_rc : PointerLikeRegClass<0>; + +/// unknown definition - Mark this operand as being of unknown type, causing +/// it to be resolved by inference in the context it is used. +def unknown; + +/// AsmOperandClass - Representation for the kinds of operands which the target +/// specific parser can create and the assembly matcher may need to distinguish. +/// +/// Operand classes are used to define the order in which instructions are +/// matched, to ensure that the instruction which gets matched for any +/// particular list of operands is deterministic. +/// +/// The target specific parser must be able to classify a parsed operand into a +/// unique class which does not partially overlap with any other classes. It can +/// match a subset of some other class, in which case the super class field +/// should be defined. +class AsmOperandClass { + /// The name to use for this class, which should be usable as an enum value. + string Name = ?; + + /// The super classes of this operand. + list SuperClasses = []; + + /// The name of the method on the target specific operand to call to test + /// whether the operand is an instance of this class. If not set, this will + /// default to "isFoo", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// bool isFoo() const; + string PredicateMethod = ?; + + /// The name of the method on the target specific operand to call to add the + /// target specific operand to an MCInst. If not set, this will default to + /// "addFooOperands", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// void addFooOperands(MCInst &Inst, unsigned N) const; + string RenderMethod = ?; + + /// The name of the method on the target specific operand to call to custom + /// handle the operand parsing. This is useful when the operands do not relate + /// to immediates or registers and are very instruction specific (as flags to + /// set in a processor register, coprocessor number, ...). + string ParserMethod = ?; +} + +def ImmAsmOperand : AsmOperandClass { + let Name = "Imm"; +} + +/// Operand Types - These provide the built-in operand types that may be used +/// by a target. Targets can optionally provide their own operand types as +/// needed, though this should not be needed for RISC targets. +class Operand { + ValueType Type = ty; + string PrintMethod = "printOperand"; + string EncoderMethod = ""; + string DecoderMethod = ""; + string AsmOperandLowerMethod = ?; + dag MIOperandInfo = (ops); + + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. + AsmOperandClass ParserMatchClass = ImmAsmOperand; +} + +def i1imm : Operand; +def i8imm : Operand; +def i16imm : Operand; +def i32imm : Operand; +def i64imm : Operand; + +def f32imm : Operand; +def f64imm : Operand; + +/// zero_reg definition - Special node to stand for the zero register. +/// +def zero_reg; + +/// PredicateOperand - This can be used to define a predicate operand for an +/// instruction. OpTypes specifies the MIOperandInfo for the operand, and +/// AlwaysVal specifies the value of this predicate when set to "always +/// execute". +class PredicateOperand + : Operand { + let MIOperandInfo = OpTypes; + dag DefaultOps = AlwaysVal; +} + +/// OptionalDefOperand - This is used to define a optional definition operand +/// for an instruction. DefaultOps is the register the operand represents if +/// none is supplied, e.g. zero_reg. +class OptionalDefOperand + : Operand { + let MIOperandInfo = OpTypes; + dag DefaultOps = defaultops; +} + + +// InstrInfo - This class should only be instantiated once to provide parameters +// which are global to the target machine. +// +class InstrInfo { + // Target can specify its instructions in either big or little-endian formats. + // For instance, while both Sparc and PowerPC are big-endian platforms, the + // Sparc manual specifies its instructions in the format [31..0] (big), while + // PowerPC specifies them using the format [0..31] (little). + bit isLittleEndianEncoding = 0; +} + +// Standard Pseudo Instructions. +// This list must match TargetOpcodes.h and CodeGenTarget.cpp. +// Only these instructions are allowed in the TargetOpcode namespace. +let isCodeGenOnly = 1, Namespace = "TargetOpcode" in { +def PHI : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "PHINODE"; +} +def INLINEASM : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let neverHasSideEffects = 1; // Note side effect is encoded in an operand. +} +def PROLOG_LABEL : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def EH_LABEL : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def GC_LABEL : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let isNotDuplicable = 1; +} +def KILL : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let neverHasSideEffects = 1; +} +def EXTRACT_SUBREG : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$supersrc, i32imm:$subidx); + let AsmString = ""; + let neverHasSideEffects = 1; +} +def INSERT_SUBREG : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let neverHasSideEffects = 1; + let Constraints = "$supersrc = $dst"; +} +def IMPLICIT_DEF : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins); + let AsmString = ""; + let neverHasSideEffects = 1; + let isReMaterializable = 1; + let isAsCheapAsAMove = 1; +} +def SUBREG_TO_REG : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let neverHasSideEffects = 1; +} +def COPY_TO_REGCLASS : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$src, i32imm:$regclass); + let AsmString = ""; + let neverHasSideEffects = 1; + let isAsCheapAsAMove = 1; +} +def DBG_VALUE : Instruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "DBG_VALUE"; + let neverHasSideEffects = 1; +} +def REG_SEQUENCE : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let neverHasSideEffects = 1; + let isAsCheapAsAMove = 1; +} +def COPY : Instruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$src); + let AsmString = ""; + let neverHasSideEffects = 1; + let isAsCheapAsAMove = 1; +} +} + +//===----------------------------------------------------------------------===// +// AsmParser - This class can be implemented by targets that wish to implement +// .s file parsing. +// +// Subtargets can have multiple different assembly parsers (e.g. AT&T vs Intel +// syntax on X86 for example). +// +class AsmParser { + // AsmParserClassName - This specifies the suffix to use for the asmparser + // class. Generated AsmParser classes are always prefixed with the target + // name. + string AsmParserClassName = "AsmParser"; + + // AsmParserInstCleanup - If non-empty, this is the name of a custom member + // function of the AsmParser class to call on every matched instruction. + // This can be used to perform target specific instruction post-processing. + string AsmParserInstCleanup = ""; + + // Variant - AsmParsers can be of multiple different variants. Variants are + // used to support targets that need to parser multiple formats for the + // assembly language. + int Variant = 0; + + // CommentDelimiter - If given, the delimiter string used to recognize + // comments which are hard coded in the .td assembler strings for individual + // instructions. + string CommentDelimiter = ""; + + // RegisterPrefix - If given, the token prefix which indicates a register + // token. This is used by the matcher to automatically recognize hard coded + // register tokens as constrained registers, instead of tokens, for the + // purposes of matching. + string RegisterPrefix = ""; +} +def DefaultAsmParser : AsmParser; + +/// AssemblerPredicate - This is a Predicate that can be used when the assembler +/// matches instructions and aliases. +class AssemblerPredicate { + bit AssemblerMatcherPredicate = 1; +} + + + +/// MnemonicAlias - This class allows targets to define assembler mnemonic +/// aliases. This should be used when all forms of one mnemonic are accepted +/// with a different mnemonic. For example, X86 allows: +/// sal %al, 1 -> shl %al, 1 +/// sal %ax, %cl -> shl %ax, %cl +/// sal %eax, %cl -> shl %eax, %cl +/// etc. Though "sal" is accepted with many forms, all of them are directly +/// translated to a shl, so it can be handled with (in the case of X86, it +/// actually has one for each suffix as well): +/// def : MnemonicAlias<"sal", "shl">; +/// +/// Mnemonic aliases are mapped before any other translation in the match phase, +/// and do allow Requires predicates, e.g.: +/// +/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; +/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; +/// +class MnemonicAlias { + string FromMnemonic = From; + string ToMnemonic = To; + + // Predicates - Predicates that must be true for this remapping to happen. + list Predicates = []; +} + +/// InstAlias - This defines an alternate assembly syntax that is allowed to +/// match an instruction that has a different (more canonical) assembly +/// representation. +class InstAlias { + string AsmString = Asm; // The .s format to match the instruction with. + dag ResultInst = Result; // The MCInst to generate. + + // Predicates - Predicates that must be true for this to match. + list Predicates = []; +} + +//===----------------------------------------------------------------------===// +// AsmWriter - This class can be implemented by targets that need to customize +// the format of the .s file writer. +// +// Subtargets can have multiple different asmwriters (e.g. AT&T vs Intel syntax +// on X86 for example). +// +class AsmWriter { + // AsmWriterClassName - This specifies the suffix to use for the asmwriter + // class. Generated AsmWriter classes are always prefixed with the target + // name. + string AsmWriterClassName = "AsmPrinter"; + + // Variant - AsmWriters can be of multiple different variants. Variants are + // used to support targets that need to emit assembly code in ways that are + // mostly the same for different targets, but have minor differences in + // syntax. If the asmstring contains {|} characters in them, this integer + // will specify which alternative to use. For example "{x|y|z}" with Variant + // == 1, will expand to "y". + int Variant = 0; + + + // FirstOperandColumn/OperandSpacing - If the assembler syntax uses a columnar + // layout, the asmwriter can actually generate output in this columns (in + // verbose-asm mode). These two values indicate the width of the first column + // (the "opcode" area) and the width to reserve for subsequent operands. When + // verbose asm mode is enabled, operands will be indented to respect this. + int FirstOperandColumn = -1; + + // OperandSpacing - Space between operand columns. + int OperandSpacing = -1; + + // isMCAsmWriter - Is this assembly writer for an MC emitter? This controls + // generation of the printInstruction() method. For MC printers, it takes + // an MCInstr* operand, otherwise it takes a MachineInstr*. + bit isMCAsmWriter = 0; +} +def DefaultAsmWriter : AsmWriter; + + +//===----------------------------------------------------------------------===// +// Target - This class contains the "global" target information +// +class Target { + // InstructionSet - Instruction set description for this target. + InstrInfo InstructionSet; + + // AssemblyParsers - The AsmParser instances available for this target. + list AssemblyParsers = [DefaultAsmParser]; + + // AssemblyWriters - The AsmWriter instances available for this target. + list AssemblyWriters = [DefaultAsmWriter]; +} + +//===----------------------------------------------------------------------===// +// SubtargetFeature - A characteristic of the chip set. +// +class SubtargetFeature i = []> { + // Name - Feature name. Used by command line (-mattr=) to determine the + // appropriate target chip. + // + string Name = n; + + // Attribute - Attribute to be set by feature. + // + string Attribute = a; + + // Value - Value the attribute to be set to by feature. + // + string Value = v; + + // Desc - Feature description. Used by command line (-mattr=) to display help + // information. + // + string Desc = d; + + // Implies - Features that this feature implies are present. If one of those + // features isn't set, then this one shouldn't be set either. + // + list Implies = i; +} + +//===----------------------------------------------------------------------===// +// Processor chip sets - These values represent each of the chip sets supported +// by the scheduler. Each Processor definition requires corresponding +// instruction itineraries. +// +class Processor f> { + // Name - Chip set name. Used by command line (-mcpu=) to determine the + // appropriate target chip. + // + string Name = n; + + // ProcItin - The scheduling information for the target processor. + // + ProcessorItineraries ProcItin = pi; + + // Features - list of + list Features = f; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for calling conventions. +// +include "llvm/Target/TargetCallingConv.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for DAG isel generation. +// +include "llvm/Target/TargetSelectionDAG.td" diff --git a/final/include/llvm/Target/TargetAsmBackend.h b/final/include/llvm/Target/TargetAsmBackend.h new file mode 100644 index 00000000000..7527298efa9 --- /dev/null +++ b/final/include/llvm/Target/TargetAsmBackend.h @@ -0,0 +1,123 @@ +//===-- llvm/Target/TargetAsmBackend.h - Target Asm Backend -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMBACKEND_H +#define LLVM_TARGET_TARGETASMBACKEND_H + +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCFixup; +class MCInst; +class MCObjectWriter; +class MCSection; +template +class SmallVectorImpl; +class raw_ostream; + +/// TargetAsmBackend - Generic interface to target specific assembler backends. +class TargetAsmBackend { + TargetAsmBackend(const TargetAsmBackend &); // DO NOT IMPLEMENT + void operator=(const TargetAsmBackend &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetAsmBackend(); + + unsigned HasReliableSymbolDifference : 1; + +public: + virtual ~TargetAsmBackend(); + + /// createObjectWriter - Create a new MCObjectWriter instance for use by the + /// assembler backend to emit the final object file. + virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; + + /// hasReliableSymbolDifference - Check whether this target implements + /// accurate relocations for differences between symbols. If not, differences + /// between symbols will always be relocatable expressions and any references + /// to temporary symbols will be assumed to be in the same atom, unless they + /// reside in a different section. + /// + /// This should always be true (since it results in fewer relocations with no + /// loss of functionality), but is currently supported as a way to maintain + /// exact object compatibility with Darwin 'as' (on non-x86_64). It should + /// eventually should be eliminated. + bool hasReliableSymbolDifference() const { + return HasReliableSymbolDifference; + } + + /// doesSectionRequireSymbols - Check whether the given section requires that + /// all symbols (even temporaries) have symbol table entries. + virtual bool doesSectionRequireSymbols(const MCSection &Section) const { + return false; + } + + /// isSectionAtomizable - Check whether the given section can be split into + /// atoms. + /// + /// \see MCAssembler::isSymbolLinkerVisible(). + virtual bool isSectionAtomizable(const MCSection &Section) const { + return true; + } + + /// @name Target Fixup Interfaces + /// @{ + + /// getNumFixupKinds - Get the number of target specific fixup kinds. + virtual unsigned getNumFixupKinds() const = 0; + + /// getFixupKindInfo - Get information on a fixup kind. + virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; + + /// @} + + /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided + /// data fragment, at the offset specified by the fixup and following the + /// fixup kind as appropriate. + virtual void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const = 0; + + /// @} + + /// @name Target Relaxation Interfaces + /// @{ + + /// MayNeedRelaxation - Check whether the given instruction may need + /// relaxation. + /// + /// \param Inst - The instruction to test. + virtual bool MayNeedRelaxation(const MCInst &Inst) const = 0; + + /// RelaxInstruction - Relax the instruction in the given fragment to the next + /// wider instruction. + /// + /// \param Inst - The instruction to relax, which may be the same as the + /// output. + /// \parm Res [output] - On return, the relaxed instruction. + virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0; + + /// @} + + /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given + /// output. If the target cannot generate such a sequence, it should return an + /// error. + /// + /// \return - True on success. + virtual bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const = 0; + + /// HandleAssemblerFlag - Handle any target-specific assembler flags. + /// By default, do nothing. + virtual void HandleAssemblerFlag(MCAssemblerFlag Flag) {} +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetAsmInfo.h b/final/include/llvm/Target/TargetAsmInfo.h new file mode 100644 index 00000000000..98aab142b8e --- /dev/null +++ b/final/include/llvm/Target/TargetAsmInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetAsmInfo.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to provide the information necessary for producing assembly files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMINFO_H +#define LLVM_TARGET_TARGETASMINFO_H + +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class MCSection; + class MCContext; + class TargetMachine; + class TargetLoweringObjectFile; + +class TargetAsmInfo { + unsigned PointerSize; + bool IsLittleEndian; + TargetFrameLowering::StackDirection StackDir; + const TargetRegisterInfo *TRI; + std::vector InitialFrameState; + const TargetLoweringObjectFile *TLOF; + +public: + explicit TargetAsmInfo(const TargetMachine &TM); + + /// getPointerSize - Get the pointer size in bytes. + unsigned getPointerSize() const { + return PointerSize; + } + + /// islittleendian - True if the target is little endian. + bool isLittleEndian() const { + return IsLittleEndian; + } + + TargetFrameLowering::StackDirection getStackGrowthDirection() const { + return StackDir; + } + + const MCSection *getDwarfLineSection() const { + return TLOF->getDwarfLineSection(); + } + + const MCSection *getEHFrameSection() const { + return TLOF->getEHFrameSection(); + } + + unsigned getDwarfRARegNum(bool isEH) const { + return TRI->getDwarfRegNum(TRI->getRARegister(), isEH); + } + + const std::vector &getInitialFrameState() const { + return InitialFrameState; + } + + int getDwarfRegNum(unsigned RegNum, bool isEH) const { + return TRI->getDwarfRegNum(RegNum, isEH); + } +}; + +} +#endif diff --git a/final/include/llvm/Target/TargetAsmLexer.h b/final/include/llvm/Target/TargetAsmLexer.h new file mode 100644 index 00000000000..9fcf449a86c --- /dev/null +++ b/final/include/llvm/Target/TargetAsmLexer.h @@ -0,0 +1,89 @@ +//===-- llvm/Target/TargetAsmLexer.h - Target Assembly Lexer ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETASMLEXER_H +#define LLVM_TARGET_TARGETASMLEXER_H + +#include "llvm/MC/MCParser/MCAsmLexer.h" + +namespace llvm { +class Target; + +/// TargetAsmLexer - Generic interface to target specific assembly lexers. +class TargetAsmLexer { + /// The current token + AsmToken CurTok; + + /// The location and description of the current error + SMLoc ErrLoc; + std::string Err; + + TargetAsmLexer(const TargetAsmLexer &); // DO NOT IMPLEMENT + void operator=(const TargetAsmLexer &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetAsmLexer(const Target &); + + virtual AsmToken LexToken() = 0; + + void SetError(const SMLoc &errLoc, const std::string &err) { + ErrLoc = errLoc; + Err = err; + } + + /// TheTarget - The Target that this machine was created for. + const Target &TheTarget; + MCAsmLexer *Lexer; + +public: + virtual ~TargetAsmLexer(); + + const Target &getTarget() const { return TheTarget; } + + /// InstallLexer - Set the lexer to get tokens from lower-level lexer \arg L. + void InstallLexer(MCAsmLexer &L) { + Lexer = &L; + } + + MCAsmLexer *getLexer() { + return Lexer; + } + + /// Lex - Consume the next token from the input stream and return it. + const AsmToken &Lex() { + return CurTok = LexToken(); + } + + /// getTok - Get the current (last) lexed token. + const AsmToken &getTok() { + return CurTok; + } + + /// getErrLoc - Get the current error location + const SMLoc &getErrLoc() { + return ErrLoc; + } + + /// getErr - Get the current error string + const std::string &getErr() { + return Err; + } + + /// getKind - Get the kind of current token. + AsmToken::TokenKind getKind() const { return CurTok.getKind(); } + + /// is - Check if the current token has kind \arg K. + bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } + + /// isNot - Check if the current token has kind \arg K. + bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetAsmParser.h b/final/include/llvm/Target/TargetAsmParser.h new file mode 100644 index 00000000000..9ff50cb275b --- /dev/null +++ b/final/include/llvm/Target/TargetAsmParser.h @@ -0,0 +1,90 @@ +//===-- llvm/Target/TargetAsmParser.h - Target Assembly Parser --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETPARSER_H +#define LLVM_TARGET_TARGETPARSER_H + +#include "llvm/MC/MCParser/MCAsmParserExtension.h" + +namespace llvm { +class MCStreamer; +class StringRef; +class Target; +class SMLoc; +class AsmToken; +class MCParsedAsmOperand; +template class SmallVectorImpl; + +/// TargetAsmParser - Generic interface to target specific assembly parsers. +class TargetAsmParser : public MCAsmParserExtension { + TargetAsmParser(const TargetAsmParser &); // DO NOT IMPLEMENT + void operator=(const TargetAsmParser &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetAsmParser(const Target &); + + /// The Target that this machine was created for. + const Target &TheTarget; + + /// The current set of available features. + unsigned AvailableFeatures; + +public: + virtual ~TargetAsmParser(); + + const Target &getTarget() const { return TheTarget; } + + unsigned getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + + /// ParseInstruction - Parse one assembly instruction. + /// + /// The parser is positioned following the instruction name. The target + /// specific instruction parser should parse the entire instruction and + /// construct the appropriate MCInst, or emit an error. On success, the entire + /// line should be parsed up to and including the end-of-statement token. On + /// failure, the parser is not required to read to the end of the line. + // + /// \param Name - The instruction name. + /// \param NameLoc - The source location of the name. + /// \param Operands [out] - The list of parsed operands, this returns + /// ownership of them to the caller. + /// \return True on failure. + virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc, + SmallVectorImpl &Operands) = 0; + + /// ParseDirective - Parse a target specific assembler directive + /// + /// The parser is positioned following the directive name. The target + /// specific directive parser should parse the entire directive doing or + /// recording any target specific work, or return true and do nothing if the + /// directive is not target specific. If the directive is specific for + /// the target, the entire line is parsed up to and including the + /// end-of-statement token and false is returned. + /// + /// \param DirectiveID - the identifier token of the directive. + virtual bool ParseDirective(AsmToken DirectiveID) = 0; + + /// MatchAndEmitInstruction - Recognize a series of operands of a parsed + /// instruction as an actual MCInst and emit it to the specified MCStreamer. + /// This returns false on success and returns true on failure to match. + /// + /// On failure, the target parser is responsible for emitting a diagnostic + /// explaining the match failure. + virtual bool + MatchAndEmitInstruction(SMLoc IDLoc, + SmallVectorImpl &Operands, + MCStreamer &Out) = 0; + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetCallingConv.h b/final/include/llvm/Target/TargetCallingConv.h new file mode 100644 index 00000000000..275957e0153 --- /dev/null +++ b/final/include/llvm/Target/TargetCallingConv.h @@ -0,0 +1,140 @@ +//===-- llvm/Target/TargetCallingConv.h - Calling Convention ----*- 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 types for working with calling-convention information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETCALLINGCONV_H +#define LLVM_TARGET_TARGETCALLINGCONV_H + +namespace llvm { + +namespace ISD { + struct ArgFlagsTy { + private: + static const uint64_t NoFlagSet = 0ULL; + static const uint64_t ZExt = 1ULL<<0; ///< Zero extended + static const uint64_t ZExtOffs = 0; + static const uint64_t SExt = 1ULL<<1; ///< Sign extended + static const uint64_t SExtOffs = 1; + static const uint64_t InReg = 1ULL<<2; ///< Passed in register + static const uint64_t InRegOffs = 2; + static const uint64_t SRet = 1ULL<<3; ///< Hidden struct-ret ptr + static const uint64_t SRetOffs = 3; + static const uint64_t ByVal = 1ULL<<4; ///< Struct passed by value + static const uint64_t ByValOffs = 4; + static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain + static const uint64_t NestOffs = 5; + static const uint64_t ByValAlign = 0xFULL << 6; //< Struct alignment + static const uint64_t ByValAlignOffs = 6; + static const uint64_t Split = 1ULL << 10; + static const uint64_t SplitOffs = 10; + static const uint64_t OrigAlign = 0x1FULL<<27; + static const uint64_t OrigAlignOffs = 27; + static const uint64_t ByValSize = 0xffffffffULL << 32; //< Struct size + static const uint64_t ByValSizeOffs = 32; + + static const uint64_t One = 1ULL; //< 1 of this type, for shifts + + uint64_t Flags; + public: + ArgFlagsTy() : Flags(0) { } + + bool isZExt() const { return Flags & ZExt; } + void setZExt() { Flags |= One << ZExtOffs; } + + bool isSExt() const { return Flags & SExt; } + void setSExt() { Flags |= One << SExtOffs; } + + bool isInReg() const { return Flags & InReg; } + void setInReg() { Flags |= One << InRegOffs; } + + bool isSRet() const { return Flags & SRet; } + void setSRet() { Flags |= One << SRetOffs; } + + bool isByVal() const { return Flags & ByVal; } + void setByVal() { Flags |= One << ByValOffs; } + + bool isNest() const { return Flags & Nest; } + void setNest() { Flags |= One << NestOffs; } + + unsigned getByValAlign() const { + return (unsigned) + ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2); + } + void setByValAlign(unsigned A) { + Flags = (Flags & ~ByValAlign) | + (uint64_t(Log2_32(A) + 1) << ByValAlignOffs); + } + + bool isSplit() const { return Flags & Split; } + void setSplit() { Flags |= One << SplitOffs; } + + unsigned getOrigAlign() const { + return (unsigned) + ((One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2); + } + void setOrigAlign(unsigned A) { + Flags = (Flags & ~OrigAlign) | + (uint64_t(Log2_32(A) + 1) << OrigAlignOffs); + } + + unsigned getByValSize() const { + return (unsigned)((Flags & ByValSize) >> ByValSizeOffs); + } + void setByValSize(unsigned S) { + Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs); + } + + /// getArgFlagsString - Returns the flags as a string, eg: "zext align:4". + std::string getArgFlagsString(); + + /// getRawBits - Represent the flags as a bunch of bits. + uint64_t getRawBits() const { return Flags; } + }; + + /// InputArg - This struct carries flags and type information about a + /// single incoming (formal) argument or incoming (from the perspective + /// of the caller) return value virtual register. + /// + struct InputArg { + ArgFlagsTy Flags; + MVT VT; + bool Used; + + InputArg() : VT(MVT::Other), Used(false) {} + InputArg(ArgFlagsTy flags, EVT vt, bool used) + : Flags(flags), Used(used) { + VT = vt.getSimpleVT(); + } + }; + + /// OutputArg - This struct carries flags and a value for a + /// single outgoing (actual) argument or outgoing (from the perspective + /// of the caller) return value virtual register. + /// + struct OutputArg { + ArgFlagsTy Flags; + MVT VT; + + /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...". + bool IsFixed; + + OutputArg() : IsFixed(false) {} + OutputArg(ArgFlagsTy flags, EVT vt, bool isfixed) + : Flags(flags), IsFixed(isfixed) { + VT = vt.getSimpleVT(); + } + }; +} + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetCallingConv.td b/final/include/llvm/Target/TargetCallingConv.td new file mode 100644 index 00000000000..6da3ba13bb3 --- /dev/null +++ b/final/include/llvm/Target/TargetCallingConv.td @@ -0,0 +1,135 @@ +//===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===// +// +// 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 target-independent interfaces with which targets +// describe their calling conventions. +// +//===----------------------------------------------------------------------===// + +class CCAction; +class CallingConv; + +/// CCCustom - Calls a custom arg handling function. +class CCCustom : CCAction { + string FuncName = fn; +} + +/// CCPredicateAction - Instances of this class check some predicate, then +/// delegate to another action if the predicate is true. +class CCPredicateAction : CCAction { + CCAction SubAction = A; +} + +/// CCIfType - If the current argument is one of the specified types, apply +/// Action A. +class CCIfType vts, CCAction A> : CCPredicateAction { + list VTs = vts; +} + +/// CCIf - If the predicate matches, apply A. +class CCIf : CCPredicateAction { + string Predicate = predicate; +} + +/// CCIfByVal - If the current argument has ByVal parameter attribute, apply +/// Action A. +class CCIfByVal : CCIf<"ArgFlags.isByVal()", A> { +} + +/// CCIfCC - Match if the current calling convention is 'CC'. +class CCIfCC + : CCIf {} + +/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply +/// the specified action. +class CCIfInReg : CCIf<"ArgFlags.isInReg()", A> {} + +/// CCIfNest - If this argument is marked with the 'nest' attribute, apply +/// the specified action. +class CCIfNest : CCIf<"ArgFlags.isNest()", A> {} + +/// CCIfSplit - If this argument is marked with the 'split' attribute, apply +/// the specified action. +class CCIfSplit : CCIf<"ArgFlags.isSplit()", A> {} + +/// CCIfSRet - If this argument is marked with the 'sret' attribute, apply +/// the specified action. +class CCIfSRet : CCIf<"ArgFlags.isSRet()", A> {} + +/// CCIfNotVarArg - If the current function is not vararg - apply the action +class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} + +/// CCAssignToReg - This action matches if there is a register in the specified +/// list that is still available. If so, it assigns the value to the first +/// available register and succeeds. +class CCAssignToReg regList> : CCAction { + list RegList = regList; +} + +/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers +/// which became shadowed, when some register is used. +class CCAssignToRegWithShadow regList, + list shadowList> : CCAction { + list RegList = regList; + list ShadowRegList = shadowList; +} + +/// CCAssignToStack - This action always matches: it assigns the value to a +/// stack slot of the specified size and alignment on the stack. If size is +/// zero then the ABI size is used; if align is zero then the ABI alignment +/// is used - these may depend on the target or subtarget. +class CCAssignToStack : CCAction { + int Size = size; + int Align = align; +} + +/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a register +/// to be shadowed. +class CCAssignToStackWithShadow : + CCAssignToStack { + Register ShadowReg = reg; +} + +/// CCPassByVal - This action always matches: it assigns the value to a stack +/// slot to implement ByVal aggregate parameter passing. Size and alignment +/// specify the minimum size and alignment for the stack slot. +class CCPassByVal : CCAction { + int Size = size; + int Align = align; +} + +/// CCPromoteToType - If applied, this promotes the specified current value to +/// the specified type. +class CCPromoteToType : CCAction { + ValueType DestTy = destTy; +} + +/// CCBitConvertToType - If applied, this bitconverts the specified current +/// value to the specified type. +class CCBitConvertToType : CCAction { + ValueType DestTy = destTy; +} + +/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer +/// as normal argument. +class CCPassIndirect : CCAction { + ValueType DestTy = destTy; +} + +/// CCDelegateTo - This action invokes the specified sub-calling-convention. It +/// is successful if the specified CC matches. +class CCDelegateTo : CCAction { + CallingConv CC = cc; +} + +/// CallingConv - An instance of this is used to define each calling convention +/// that the target supports. +class CallingConv actions> { + list Actions = actions; +} diff --git a/final/include/llvm/Target/TargetData.h b/final/include/llvm/Target/TargetData.h new file mode 100644 index 00000000000..25065d30bb6 --- /dev/null +++ b/final/include/llvm/Target/TargetData.h @@ -0,0 +1,336 @@ +//===-- llvm/Target/TargetData.h - Data size & alignment 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 target properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETDATA_H +#define LLVM_TARGET_TARGETDATA_H + +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class Value; +class Type; +class IntegerType; +class StructType; +class StructLayout; +class GlobalVariable; +class LLVMContext; + +/// Enum used to categorize the alignment types stored by TargetAlignElem +enum AlignTypeEnum { + INTEGER_ALIGN = 'i', ///< Integer type alignment + VECTOR_ALIGN = 'v', ///< Vector type alignment + FLOAT_ALIGN = 'f', ///< Floating point type alignment + AGGREGATE_ALIGN = 'a', ///< Aggregate alignment + STACK_ALIGN = 's' ///< Stack objects alignment +}; +/// Target alignment element. +/// +/// Stores the alignment data associated with a given alignment type (pointer, +/// integer, vector, float) and type bit width. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct TargetAlignElem { + AlignTypeEnum AlignType : 8; //< Alignment type (AlignTypeEnum) + unsigned ABIAlign; //< ABI alignment for this type/bitw + unsigned PrefAlign; //< Pref. alignment for this type/bitw + uint32_t TypeBitWidth; //< Type bit width + + /// Initializer + static TargetAlignElem get(AlignTypeEnum align_type, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const TargetAlignElem &rhs) const; +}; + +class TargetData : public ImmutablePass { +private: + bool LittleEndian; ///< Defaults to false + unsigned PointerMemSize; ///< Pointer size in bytes + unsigned PointerABIAlign; ///< Pointer ABI alignment + unsigned PointerPrefAlign; ///< Pointer preferred alignment + + SmallVector LegalIntWidths; ///< Legal Integers. + + /// Alignments- Where the primitive type alignment data is stored. + /// + /// @sa init(). + /// @note Could support multiple size pointer alignments, e.g., 32-bit + /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now, + /// we don't. + SmallVector Alignments; + + /// InvalidAlignmentElem - This member is a signal that a requested alignment + /// type and bit width were not found in the SmallVector. + static const TargetAlignElem InvalidAlignmentElem; + + // The StructType -> StructLayout map. + mutable void *LayoutMap; + + //! Set/initialize target alignments + void setAlignment(AlignTypeEnum align_type, unsigned abi_align, + unsigned pref_align, uint32_t bit_width); + unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, + bool ABIAlign, const Type *Ty) const; + //! Internal helper method that returns requested alignment for type. + unsigned getAlignment(const Type *Ty, bool abi_or_pref) const; + + /// Valid alignment predicate. + /// + /// Predicate that tests a TargetAlignElem reference returned by get() against + /// InvalidAlignmentElem. + bool validAlignment(const TargetAlignElem &align) const { + return &align != &InvalidAlignmentElem; + } + +public: + /// Default ctor. + /// + /// @note This has to exist, because this is a pass, but it should never be + /// used. + TargetData(); + + /// Constructs a TargetData from a specification string. See init(). + explicit TargetData(StringRef TargetDescription) + : ImmutablePass(ID) { + init(TargetDescription); + } + + /// Initialize target data from properties stored in the module. + explicit TargetData(const Module *M); + + TargetData(const TargetData &TD) : + ImmutablePass(ID), + LittleEndian(TD.isLittleEndian()), + PointerMemSize(TD.PointerMemSize), + PointerABIAlign(TD.PointerABIAlign), + PointerPrefAlign(TD.PointerPrefAlign), + LegalIntWidths(TD.LegalIntWidths), + Alignments(TD.Alignments), + LayoutMap(0) + { } + + ~TargetData(); // Not virtual, do not subclass this class + + //! Parse a target data layout string and initialize TargetData alignments. + void init(StringRef TargetDescription); + + /// Target endianness... + bool isLittleEndian() const { return LittleEndian; } + bool isBigEndian() const { return !LittleEndian; } + + /// getStringRepresentation - Return the string representation of the + /// TargetData. This representation is in the same format accepted by the + /// string constructor above. + std::string getStringRepresentation() const; + + /// isLegalInteger - This function returns true if the specified type is + /// known to be a native integer type supported by the CPU. For example, + /// i64 is not native on most 32-bit CPUs and i37 is not native on any known + /// one. This returns false if the integer width is not legal. + /// + /// The width is specified in bits. + /// + bool isLegalInteger(unsigned Width) const { + for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) + if (LegalIntWidths[i] == Width) + return true; + return false; + } + + bool isIllegalInteger(unsigned Width) const { + return !isLegalInteger(Width); + } + + /// Target pointer alignment + unsigned getPointerABIAlignment() const { return PointerABIAlign; } + /// Return target's alignment for stack-based pointers + unsigned getPointerPrefAlignment() const { return PointerPrefAlign; } + /// Target pointer size + unsigned getPointerSize() const { return PointerMemSize; } + /// Target pointer size, in bits + unsigned getPointerSizeInBits() const { return 8*PointerMemSize; } + + /// Size examples: + /// + /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] + /// ---- ---------- --------------- --------------- + /// i1 1 8 8 + /// i8 8 8 8 + /// i19 19 24 32 + /// i32 32 32 32 + /// i100 100 104 128 + /// i128 128 128 128 + /// Float 32 32 32 + /// Double 64 64 64 + /// X86_FP80 80 80 96 + /// + /// [*] The alloc size depends on the alignment, and thus on the target. + /// These values are for x86-32 linux. + + /// getTypeSizeInBits - Return the number of bits necessary to hold the + /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. + uint64_t getTypeSizeInBits(const Type* Ty) const; + + /// getTypeStoreSize - Return the maximum number of bytes that may be + /// overwritten by storing the specified type. For example, returns 5 + /// for i36 and 10 for x86_fp80. + uint64_t getTypeStoreSize(const Type *Ty) const { + return (getTypeSizeInBits(Ty)+7)/8; + } + + /// getTypeStoreSizeInBits - Return the maximum number of bits that may be + /// overwritten by storing the specified type; always a multiple of 8. For + /// example, returns 40 for i36 and 80 for x86_fp80. + uint64_t getTypeStoreSizeInBits(const Type *Ty) const { + return 8*getTypeStoreSize(Ty); + } + + /// getTypeAllocSize - Return the offset in bytes between successive objects + /// of the specified type, including alignment padding. This is the amount + /// that alloca reserves for this type. For example, returns 12 or 16 for + /// x86_fp80, depending on alignment. + uint64_t getTypeAllocSize(const Type* Ty) const { + // Round up to the next alignment boundary. + return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); + } + + /// getTypeAllocSizeInBits - Return the offset in bits between successive + /// objects of the specified type, including alignment padding; always a + /// multiple of 8. This is the amount that alloca reserves for this type. + /// For example, returns 96 or 128 for x86_fp80, depending on alignment. + uint64_t getTypeAllocSizeInBits(const Type* Ty) const { + return 8*getTypeAllocSize(Ty); + } + + /// getABITypeAlignment - Return the minimum ABI-required alignment for the + /// specified type. + unsigned getABITypeAlignment(const Type *Ty) const; + + /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for + /// an integer type of the specified bitwidth. + unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; + + + /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment + /// for the specified type when it is part of a call frame. + unsigned getCallFrameTypeAlignment(const Type *Ty) const; + + + /// getPrefTypeAlignment - Return the preferred stack/global alignment for + /// the specified type. This is always at least as good as the ABI alignment. + unsigned getPrefTypeAlignment(const Type *Ty) const; + + /// getPreferredTypeAlignmentShift - Return the preferred alignment for the + /// specified type, returned as log2 of the value (a shift amount). + /// + unsigned getPreferredTypeAlignmentShift(const Type *Ty) const; + + /// getIntPtrType - Return an unsigned integer type that is the same size or + /// greater to the host pointer size. + /// + const IntegerType *getIntPtrType(LLVMContext &C) const; + + /// getIndexedOffset - return the offset from the beginning of the type for + /// the specified indices. This is used to implement getelementptr. + /// + uint64_t getIndexedOffset(const Type *Ty, + Value* const* Indices, unsigned NumIndices) const; + + /// getStructLayout - Return a StructLayout object, indicating the alignment + /// of the struct, its size, and the offsets of its fields. Note that this + /// information is lazily cached. + const StructLayout *getStructLayout(const StructType *Ty) const; + + /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout + /// objects. If a TargetData object is alive when types are being refined and + /// removed, this method must be called whenever a StructType is removed to + /// avoid a dangling pointer in this cache. + void InvalidateStructLayoutInfo(const StructType *Ty) const; + + /// getPreferredAlignment - Return the preferred alignment of the specified + /// global. This includes an explicitly requested alignment (if the global + /// has one). + unsigned getPreferredAlignment(const GlobalVariable *GV) const; + + /// getPreferredAlignmentLog - Return the preferred alignment of the + /// specified global, returned in log form. This includes an explicitly + /// requested alignment (if the global has one). + unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; + + /// RoundUpAlignment - Round the specified value up to the next alignment + /// boundary specified by Alignment. For example, 7 rounded up to an + /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4 + /// is 8 because it is already aligned. + template + static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) { + assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); + return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); + } + + static char ID; // Pass identification, replacement for typeid +}; + +/// StructLayout - used to lazily calculate structure layout information for a +/// target machine, based on the TargetData structure. +/// +class StructLayout { + uint64_t StructSize; + unsigned StructAlignment; + unsigned NumElements; + uint64_t MemberOffsets[1]; // variable sized array! +public: + + uint64_t getSizeInBytes() const { + return StructSize; + } + + uint64_t getSizeInBits() const { + return 8*StructSize; + } + + unsigned getAlignment() const { + return StructAlignment; + } + + /// getElementContainingOffset - Given a valid byte offset into the structure, + /// return the structure index that contains it. + /// + unsigned getElementContainingOffset(uint64_t Offset) const; + + uint64_t getElementOffset(unsigned Idx) const { + assert(Idx < NumElements && "Invalid element idx!"); + return MemberOffsets[Idx]; + } + + uint64_t getElementOffsetInBits(unsigned Idx) const { + return getElementOffset(Idx)*8; + } + +private: + friend class TargetData; // Only TargetData can create this class + StructLayout(const StructType *ST, const TargetData &TD); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetELFWriterInfo.h b/final/include/llvm/Target/TargetELFWriterInfo.h new file mode 100644 index 00000000000..b97f3e2f4d0 --- /dev/null +++ b/final/include/llvm/Target/TargetELFWriterInfo.h @@ -0,0 +1,123 @@ +//===-- llvm/Target/TargetELFWriterInfo.h - ELF Writer 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 the TargetELFWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETELFWRITERINFO_H +#define LLVM_TARGET_TARGETELFWRITERINFO_H + +namespace llvm { + class Function; + class TargetData; + class TargetMachine; + + //===--------------------------------------------------------------------===// + // TargetELFWriterInfo + //===--------------------------------------------------------------------===// + + class TargetELFWriterInfo { + protected: + // EMachine - This field is the target specific value to emit as the + // e_machine member of the ELF header. + unsigned short EMachine; + bool is64Bit, isLittleEndian; + public: + + // Machine architectures + enum MachineType { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62 // AMD64 + }; + + // ELF File classes + enum { + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file + }; + + // ELF Endianess + enum { + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file + }; + + explicit TargetELFWriterInfo(bool is64Bit_, bool isLittleEndian_); + virtual ~TargetELFWriterInfo(); + + unsigned short getEMachine() const { return EMachine; } + unsigned getEFlags() const { return 0; } + unsigned getEIClass() const { return is64Bit ? ELFCLASS64 : ELFCLASS32; } + unsigned getEIData() const { + return isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; + } + + /// ELF Header and ELF Section Header Info + unsigned getHdrSize() const { return is64Bit ? 64 : 52; } + unsigned getSHdrSize() const { return is64Bit ? 64 : 40; } + + /// Symbol Table Info + unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; } + + /// getPrefELFAlignment - Returns the preferred alignment for ELF. This + /// is used to align some sections. + unsigned getPrefELFAlignment() const { return is64Bit ? 8 : 4; } + + /// getRelocationEntrySize - Entry size used in the relocation section + unsigned getRelocationEntrySize() const { + return is64Bit ? (hasRelocationAddend() ? 24 : 16) + : (hasRelocationAddend() ? 12 : 8); + } + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const = 0; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const = 0; + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const = 0; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const = 0; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const = 0; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const = 0; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const = 0; + }; + +} // end llvm namespace + +#endif // LLVM_TARGET_TARGETELFWRITERINFO_H diff --git a/final/include/llvm/Target/TargetFrameLowering.h b/final/include/llvm/Target/TargetFrameLowering.h new file mode 100644 index 00000000000..e104b1663fd --- /dev/null +++ b/final/include/llvm/Target/TargetFrameLowering.h @@ -0,0 +1,196 @@ +//===-- llvm/Target/TargetFrameLowering.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to describe the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETFRAMELOWERING_H +#define LLVM_TARGET_TARGETFRAMELOWERING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" + +#include +#include + +namespace llvm { + class CalleeSavedInfo; + class MachineFunction; + class MachineBasicBlock; + class MachineMove; + class RegScavenger; + +/// Information about stack frame layout on the target. It holds the direction +/// of stack growth, the known stack alignment on entry to each function, and +/// the offset to the locals area. +/// +/// The offset to the local area is the offset from the stack pointer on +/// function entry to the first location where function data (local variables, +/// spill locations) can be stored. +class TargetFrameLowering { +public: + enum StackDirection { + StackGrowsUp, // Adding to the stack increases the stack address + StackGrowsDown // Adding to the stack decreases the stack address + }; + + // Maps a callee saved register to a stack slot with a fixed offset. + struct SpillSlot { + unsigned Reg; + int Offset; // Offset relative to stack pointer on function entry. + }; +private: + StackDirection StackDir; + unsigned StackAlignment; + unsigned TransientStackAlignment; + int LocalAreaOffset; +public: + TargetFrameLowering(StackDirection D, unsigned StackAl, int LAO, + unsigned TransAl = 1) + : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), + LocalAreaOffset(LAO) {} + + virtual ~TargetFrameLowering(); + + // These methods return information that describes the abstract stack layout + // of the target machine. + + /// getStackGrowthDirection - Return the direction the stack grows + /// + StackDirection getStackGrowthDirection() const { return StackDir; } + + /// getStackAlignment - This method returns the number of bytes to which the + /// stack pointer must be aligned on entry to a function. Typically, this + /// is the largest alignment for any data object in the target. + /// + unsigned getStackAlignment() const { return StackAlignment; } + + /// getTransientStackAlignment - This method returns the number of bytes to + /// which the stack pointer must be aligned at all times, even between + /// calls. + /// + unsigned getTransientStackAlignment() const { + return TransientStackAlignment; + } + + /// getOffsetOfLocalArea - This method returns the offset of the local area + /// from the stack pointer on entrance to a function. + /// + int getOffsetOfLocalArea() const { return LocalAreaOffset; } + + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of + /// pairs, that contains an entry for each callee saved register that must be + /// spilled to a particular stack location if it is spilled. + /// + /// Each entry in this array contains a pair, indicating the + /// fixed offset from the incoming stack pointer that each register should be + /// spilled at. If a register is not listed here, the code generator is + /// allowed to spill it anywhere it chooses. + /// + virtual const SpillSlot * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + NumEntries = 0; + return 0; + } + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + virtual bool targetHandlesStackFrameRounding() const { + return false; + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; + + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of store instructions via + /// storeRegToStackSlot(). Returns false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + return false; + } + + /// hasFP - Return true if the specified function should have a dedicated + /// frame pointer register. For most targets this is true only if the function + /// has variable sized allocas or if frame pointer elimination is disabled. + virtual bool hasFP(const MachineFunction &MF) const = 0; + + /// hasReservedCallFrame - Under normal circumstances, when a frame pointer is + /// not required, we reserve argument space for call sites in the function + /// immediately on entry to the current function. This eliminates the need for + /// add/sub sp brackets around call sites. Returns true if the call frame is + /// included as part of the stack frame. + virtual bool hasReservedCallFrame(const MachineFunction &MF) const { + return !hasFP(MF); + } + + /// canSimplifyCallFramePseudos - When possible, it's best to simplify the + /// call frame pseudo ops before doing frame index elimination. This is + /// possible only when frame index references between the pseudos won't + /// need adjusting for the call frame adjustments. Normally, that's true + /// if the function has a reserved call frame or a frame pointer. Some + /// targets (Thumb2, for example) may have more complicated criteria, + /// however, and can override this behavior. + virtual bool canSimplifyCallFramePseudos(const MachineFunction &MF) const { + return hasReservedCallFrame(MF) || hasFP(MF); + } + + /// getInitialFrameState - Returns a list of machine moves that are assumed + /// on entry to all functions. Note that LabelID is ignored (assumed to be + /// the beginning of the function.) + virtual void getInitialFrameState(std::vector &Moves) const; + + /// getFrameIndexOffset - Returns the displacement from the frame register to + /// the stack frame of the specified index. + virtual int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + /// getFrameIndexReference - This method should return the base register + /// and offset used to reference a frame index location. The offset is + /// returned directly, and the base register is returned via FrameReg. + virtual int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const; + + /// processFunctionBeforeCalleeSavedScan - This method is called immediately + /// before PrologEpilogInserter scans the physical registers used to determine + /// what callee saved registers should be spilled. This method is optional. + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const { + + } + + /// processFunctionBeforeFrameFinalized - This method is called immediately + /// before the specified function's frame layout (MF.getFrameInfo()) is + /// finalized. Once the frame is finalized, MO_FrameIndex operands are + /// replaced with direct constants. This method is optional. + /// + virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetInstrDesc.h b/final/include/llvm/Target/TargetInstrDesc.h new file mode 100644 index 00000000000..8823d5a4d17 --- /dev/null +++ b/final/include/llvm/Target/TargetInstrDesc.h @@ -0,0 +1,513 @@ +//===-- llvm/Target/TargetInstrDesc.h - Instruction Descriptors -*- 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 TargetOperandInfo and TargetInstrDesc classes, which +// are used to describe target instructions and their operands. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRDESC_H +#define LLVM_TARGET_TARGETINSTRDESC_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class TargetRegisterClass; +class TargetRegisterInfo; + +//===----------------------------------------------------------------------===// +// Machine Operand Flags and Description +//===----------------------------------------------------------------------===// + +namespace TOI { + // Operand constraints + enum OperandConstraint { + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand + }; + + /// OperandFlags - These are flags set on operands, but should be considered + /// private, all access should go through the TargetOperandInfo accessors. + /// See the accessors for a description of what these are. + enum OperandFlags { + LookupPtrRegClass = 0, + Predicate, + OptionalDef + }; +} + +/// TargetOperandInfo - This holds information about one operand of a machine +/// instruction, indicating the register class for register operands, etc. +/// +class TargetOperandInfo { +public: + /// RegClass - This specifies the register class enumeration of the operand + /// if the operand is a register. If isLookupPtrRegClass is set, then this is + /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to + /// get a dynamic register class. + /// + /// NOTE: This member should be considered to be private, all access should go + /// through "getRegClass(TRI)" below. + short RegClass; + + /// Flags - These are flags from the TOI::OperandFlags enum. + unsigned short Flags; + + /// Lower 16 bits are used to specify which constraints are set. The higher 16 + /// bits are used to specify the value of constraints (4 bits each). + unsigned Constraints; + /// Currently no other information. + + /// getRegClass - Get the register class for the operand, handling resolution + /// of "symbolic" pointer register classes etc. If this is not a register + /// operand, this returns null. + const TargetRegisterClass *getRegClass(const TargetRegisterInfo *TRI) const; + + + /// isLookupPtrRegClass - Set if this operand is a pointer value and it + /// requires a callback to look up its register class. + bool isLookupPtrRegClass() const { return Flags&(1 <> Pos) & 0xf; + } + return -1; + } + + /// getRegClass - Returns the register class constraint for OpNum, or NULL. + const TargetRegisterClass *getRegClass(unsigned OpNum, + const TargetRegisterInfo *TRI) const { + return OpNum < NumOperands ? OpInfo[OpNum].getRegClass(TRI) : 0; + } + + /// getOpcode - Return the opcode number for this descriptor. + unsigned getOpcode() const { + return Opcode; + } + + /// getName - Return the name of the record in the .td file for this + /// instruction, for example "ADD8ri". + const char *getName() const { + return Name; + } + + /// getNumOperands - Return the number of declared MachineOperands for this + /// MachineInstruction. Note that variadic (isVariadic() returns true) + /// instructions may have additional operands at the end of the list, and note + /// that the machine instruction may include implicit register def/uses as + /// well. + unsigned getNumOperands() const { + return NumOperands; + } + + /// getNumDefs - Return the number of MachineOperands that are register + /// definitions. Register definitions always occur at the start of the + /// machine operand list. This is the number of "outs" in the .td file, + /// and does not include implicit defs. + unsigned getNumDefs() const { + return NumDefs; + } + + /// isVariadic - Return true if this instruction can have a variable number of + /// operands. In this case, the variable operands will be after the normal + /// operands but before the implicit definitions and uses (if any are + /// present). + bool isVariadic() const { + return Flags & (1 << TID::Variadic); + } + + /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// ARM instructions which can set condition code if 's' bit is set. + bool hasOptionalDef() const { + return Flags & (1 << TID::HasOptionalDef); + } + + /// getImplicitUses - Return a list of registers that are potentially + /// read by any instance of this machine instruction. For example, on X86, + /// the "adc" instruction adds two register operands and adds the carry bit in + /// from the flags register. In this case, the instruction is marked as + /// implicitly reading the flags. Likewise, the variable shift instruction on + /// X86 is marked as implicitly reading the 'CL' register, which it always + /// does. + /// + /// This method returns null if the instruction has no implicit uses. + const unsigned *getImplicitUses() const { + return ImplicitUses; + } + + /// getNumImplicitUses - Return the number of implicit uses this instruction + /// has. + unsigned getNumImplicitUses() const { + if (ImplicitUses == 0) return 0; + unsigned i = 0; + for (; ImplicitUses[i]; ++i) /*empty*/; + return i; + } + + + /// getImplicitDefs - Return a list of registers that are potentially + /// written by any instance of this machine instruction. For example, on X86, + /// many instructions implicitly set the flags register. In this case, they + /// are marked as setting the FLAGS. Likewise, many instructions always + /// deposit their result in a physical register. For example, the X86 divide + /// instruction always deposits the quotient and remainder in the EAX/EDX + /// registers. For that instruction, this will return a list containing the + /// EAX/EDX/EFLAGS registers. + /// + /// This method returns null if the instruction has no implicit defs. + const unsigned *getImplicitDefs() const { + return ImplicitDefs; + } + + /// getNumImplicitDefs - Return the number of implicit defs this instruction + /// has. + unsigned getNumImplicitDefs() const { + if (ImplicitDefs == 0) return 0; + unsigned i = 0; + for (; ImplicitDefs[i]; ++i) /*empty*/; + return i; + } + + /// hasImplicitUseOfPhysReg - Return true if this instruction implicitly + /// uses the specified physical register. + bool hasImplicitUseOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpUses = ImplicitUses) + for (; *ImpUses; ++ImpUses) + if (*ImpUses == Reg) return true; + return false; + } + + /// hasImplicitDefOfPhysReg - Return true if this instruction implicitly + /// defines the specified physical register. + bool hasImplicitDefOfPhysReg(unsigned Reg) const { + if (const unsigned *ImpDefs = ImplicitDefs) + for (; *ImpDefs; ++ImpDefs) + if (*ImpDefs == Reg) return true; + return false; + } + + /// getRegClassBarriers - Return a list of register classes that are + /// completely clobbered by this machine instruction. For example, on X86 + /// the call instructions will completely clobber all the registers in the + /// fp stack and XMM classes. + /// + /// This method returns null if the instruction doesn't completely clobber + /// any register class. + const TargetRegisterClass **getRegClassBarriers() const { + return RCBarriers; + } + + /// getSchedClass - Return the scheduling class for this instruction. The + /// scheduling class is an index into the InstrItineraryData table. This + /// returns zero if there is no known scheduling information for the + /// instruction. + /// + unsigned getSchedClass() const { + return SchedClass; + } + + bool isReturn() const { + return Flags & (1 << TID::Return); + } + + bool isCall() const { + return Flags & (1 << TID::Call); + } + + /// isBarrier - Returns true if the specified instruction stops control flow + /// from executing the instruction immediately following it. Examples include + /// unconditional branches and return instructions. + bool isBarrier() const { + return Flags & (1 << TID::Barrier); + } + + /// isTerminator - Returns true if this instruction part of the terminator for + /// a basic block. Typically this is things like return and branch + /// instructions. + /// + /// Various passes use this to insert code into the bottom of a basic block, + /// but before control flow occurs. + bool isTerminator() const { + return Flags & (1 << TID::Terminator); + } + + /// isBranch - Returns true if this is a conditional, unconditional, or + /// indirect branch. Predicates below can be used to discriminate between + /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to + /// get more information. + bool isBranch() const { + return Flags & (1 << TID::Branch); + } + + /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// branch through a register. + bool isIndirectBranch() const { + return Flags & (1 << TID::IndirectBranch); + } + + /// isConditionalBranch - Return true if this is a branch which may fall + /// through to the next instruction or may transfer control flow to some other + /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more + /// information about this branch. + bool isConditionalBranch() const { + return isBranch() & !isBarrier() & !isIndirectBranch(); + } + + /// isUnconditionalBranch - Return true if this is a branch which always + /// transfers control flow to some other block. The + /// TargetInstrInfo::AnalyzeBranch method can be used to get more information + /// about this branch. + bool isUnconditionalBranch() const { + return isBranch() & isBarrier() & !isIndirectBranch(); + } + + // isPredicable - Return true if this instruction has a predicate operand that + // controls execution. It may be set to 'always', or may be set to other + /// values. There are various methods in TargetInstrInfo that can be used to + /// control and modify the predicate in this instruction. + bool isPredicable() const { + return Flags & (1 << TID::Predicable); + } + + /// isCompare - Return true if this instruction is a comparison. + bool isCompare() const { + return Flags & (1 << TID::Compare); + } + + /// isMoveImmediate - Return true if this instruction is a move immediate + /// (including conditional moves) instruction. + bool isMoveImmediate() const { + return Flags & (1 << TID::MoveImm); + } + + /// isNotDuplicable - Return true if this instruction cannot be safely + /// duplicated. For example, if the instruction has a unique labels attached + /// to it, duplicating it would cause multiple definition errors. + bool isNotDuplicable() const { + return Flags & (1 << TID::NotDuplicable); + } + + /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// which must be filled by the code generator. + bool hasDelaySlot() const { + return Flags & (1 << TID::DelaySlot); + } + + /// canFoldAsLoad - Return true for instructions that can be folded as + /// memory operands in other instructions. The most common use for this + /// is instructions that are simple loads from memory that don't modify + /// the loaded value in any way, but it can also be used for instructions + /// that can be expressed as constant-pool loads, such as V_SETALLONES + /// on x86, to allow them to be folded when it is beneficial. + /// This should only be set on instructions that return a value in their + /// only virtual register definition. + bool canFoldAsLoad() const { + return Flags & (1 << TID::FoldableAsLoad); + } + + //===--------------------------------------------------------------------===// + // Side Effect Analysis + //===--------------------------------------------------------------------===// + + /// mayLoad - Return true if this instruction could possibly read memory. + /// Instructions with this flag set are not necessarily simple load + /// instructions, they may load a value and modify it, for example. + bool mayLoad() const { + return Flags & (1 << TID::MayLoad); + } + + + /// mayStore - Return true if this instruction could possibly modify memory. + /// Instructions with this flag set are not necessarily simple store + /// instructions, they may store a modified value based on their operands, or + /// may not actually modify anything, for example. + bool mayStore() const { + return Flags & (1 << TID::MayStore); + } + + /// hasUnmodeledSideEffects - Return true if this instruction has side + /// effects that are not modeled by other flags. This does not return true + /// for instructions whose effects are captured by: + /// + /// 1. Their operand list and implicit definition/use list. Register use/def + /// info is explicit for instructions. + /// 2. Memory accesses. Use mayLoad/mayStore. + /// 3. Calling, branching, returning: use isCall/isReturn/isBranch. + /// + /// Examples of side effects would be modifying 'invisible' machine state like + /// a control register, flushing a cache, modifying a register invisible to + /// LLVM, etc. + /// + bool hasUnmodeledSideEffects() const { + return Flags & (1 << TID::UnmodeledSideEffects); + } + + //===--------------------------------------------------------------------===// + // Flags that indicate whether an instruction can be modified by a method. + //===--------------------------------------------------------------------===// + + /// isCommutable - Return true if this may be a 2- or 3-address + /// instruction (of the form "X = op Y, Z, ..."), which produces the same + /// result if Y and Z are exchanged. If this flag is set, then the + /// TargetInstrInfo::commuteInstruction method may be used to hack on the + /// instruction. + /// + /// Note that this flag may be set on instructions that are only commutable + /// sometimes. In these cases, the call to commuteInstruction will fail. + /// Also note that some instructions require non-trivial modification to + /// commute them. + bool isCommutable() const { + return Flags & (1 << TID::Commutable); + } + + /// isConvertibleTo3Addr - Return true if this is a 2-address instruction + /// which can be changed into a 3-address instruction if needed. Doing this + /// transformation can be profitable in the register allocator, because it + /// means that the instruction can use a 2-address form if possible, but + /// degrade into a less efficient form if the source and dest register cannot + /// be assigned to the same register. For example, this allows the x86 + /// backend to turn a "shl reg, 3" instruction into an LEA instruction, which + /// is the same speed as the shift but has bigger code size. + /// + /// If this returns true, then the target must implement the + /// TargetInstrInfo::convertToThreeAddress method for this instruction, which + /// is allowed to fail if the transformation isn't valid for this specific + /// instruction (e.g. shl reg, 4 on x86). + /// + bool isConvertibleTo3Addr() const { + return Flags & (1 << TID::ConvertibleTo3Addr); + } + + /// usesCustomInsertionHook - Return true if this instruction requires + /// custom insertion support when the DAG scheduler is inserting it into a + /// machine basic block. If this is true for the instruction, it basically + /// means that it is a pseudo instruction used at SelectionDAG time that is + /// expanded out into magic code by the target when MachineInstrs are formed. + /// + /// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method + /// is used to insert this into the MachineBasicBlock. + bool usesCustomInsertionHook() const { + return Flags & (1 << TID::UsesCustomInserter); + } + + /// isRematerializable - Returns true if this instruction is a candidate for + /// remat. This flag is deprecated, please don't use it anymore. If this + /// flag is set, the isReallyTriviallyReMaterializable() method is called to + /// verify the instruction is really rematable. + bool isRematerializable() const { + return Flags & (1 << TID::Rematerializable); + } + + /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or + /// less) than a move instruction. This is useful during certain types of + /// optimizations (e.g., remat during two-address conversion or machine licm) + /// where we would like to remat or hoist the instruction, but not if it costs + /// more than moving the instruction into the appropriate register. Note, we + /// are not marking copies from and to the same register class with this flag. + bool isAsCheapAsAMove() const { + return Flags & (1 << TID::CheapAsAMove); + } + + /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::STRD's two source registers must be an + /// even / odd pair, ARM::STM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for sources of instructions with this flag. + bool hasExtraSrcRegAllocReq() const { + return Flags & (1 << TID::ExtraSrcRegAllocReq); + } + + /// hasExtraDefRegAllocReq - Returns true if this instruction def operands + /// have special register allocation requirements that are not captured by the + /// operand register classes. e.g. ARM::LDRD's two def registers must be an + /// even / odd pair, ARM::LDM registers have to be in ascending order. + /// Post-register allocation passes should not attempt to change allocations + /// for definitions of instructions with this flag. + bool hasExtraDefRegAllocReq() const { + return Flags & (1 << TID::ExtraDefRegAllocReq); + } +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Target/TargetInstrInfo.h b/final/include/llvm/Target/TargetInstrInfo.h new file mode 100644 index 00000000000..c903f3153e1 --- /dev/null +++ b/final/include/llvm/Target/TargetInstrInfo.h @@ -0,0 +1,713 @@ +//===-- llvm/Target/TargetInstrInfo.h - Instruction 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 describes the target machine instruction set to the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRINFO_H +#define LLVM_TARGET_TARGETINSTRINFO_H + +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +class InstrItineraryData; +class LiveVariables; +class MCAsmInfo; +class MachineMemOperand; +class MachineRegisterInfo; +class MDNode; +class MCInst; +class SDNode; +class ScheduleHazardRecognizer; +class SelectionDAG; +class ScheduleDAG; +class TargetRegisterClass; +class TargetRegisterInfo; + +template class SmallVectorImpl; + + +//--------------------------------------------------------------------------- +/// +/// TargetInstrInfo - Interface to description of machine instruction set +/// +class TargetInstrInfo { + const TargetInstrDesc *Descriptors; // Raw array to allow static init'n + unsigned NumOpcodes; // Number of entries in the desc array + + TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT + void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT +public: + TargetInstrInfo(const TargetInstrDesc *desc, unsigned NumOpcodes); + virtual ~TargetInstrInfo(); + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// get - Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + /// + const TargetInstrDesc &get(unsigned Opcode) const { + assert(Opcode < NumOpcodes && "Invalid opcode!"); + return Descriptors[Opcode]; + } + + /// isTriviallyReMaterializable - Return true if the instruction is trivially + /// rematerializable, meaning it has no side effects and requires no operands + /// that aren't always available. + bool isTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA = 0) const { + return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF || + (MI->getDesc().isRematerializable() && + (isReallyTriviallyReMaterializable(MI, AA) || + isReallyTriviallyReMaterializableGeneric(MI, AA))); + } + +protected: + /// isReallyTriviallyReMaterializable - For instructions with opcodes for + /// which the M_REMATERIALIZABLE flag is set, this hook lets the target + /// specify whether the instruction is actually trivially rematerializable, + /// taking into consideration its operands. This predicate must return false + /// if the instruction has any side effects other than producing a value, or + /// if it requres any address registers that are not always available. + virtual bool isReallyTriviallyReMaterializable(const MachineInstr *MI, + AliasAnalysis *AA) const { + return false; + } + +private: + /// isReallyTriviallyReMaterializableGeneric - For instructions with opcodes + /// for which the M_REMATERIALIZABLE flag is set and the target hook + /// isReallyTriviallyReMaterializable returns false, this function does + /// target-independent tests to determine if the instruction is really + /// trivially rematerializable. + bool isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, + AliasAnalysis *AA) const; + +public: + /// isCoalescableExtInstr - Return true if the instruction is a "coalescable" + /// extension instruction. That is, it's like a copy where it's legal for the + /// source to overlap the destination. e.g. X86::MOVSX64rr32. If this returns + /// true, then it's expected the pre-extension value is available as a subreg + /// of the result register. This also returns the sub-register index in + /// SubIdx. + virtual bool isCoalescableExtInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SubIdx) const { + return false; + } + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// isLoadFromStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// hasLoadFromStackSlot - If the specified machine instruction has + /// a load from a stack slot, return true along with the FrameIndex + /// of the loaded stack slot and the machine mem operand containing + /// the reference. If not, return false. Unlike + /// isLoadFromStackSlot, this returns true for any instructions that + /// loads from the stack. This is just a hint, as some cases may be + /// missed. + virtual bool hasLoadFromStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + return 0; + } + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination + /// stack locations as well. This uses a heuristic so it isn't + /// reliable for correctness. + virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + return 0; + } + + /// hasStoreToStackSlot - If the specified machine instruction has a + /// store to a stack slot, return true along with the FrameIndex of + /// the loaded stack slot and the machine mem operand containing the + /// reference. If not, return false. Unlike isStoreToStackSlot, + /// this returns true for any instructions that stores to the + /// stack. This is just a hint, as some cases may be missed. + virtual bool hasStoreToStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + return 0; + } + + /// reMaterialize - Re-issue the specified 'original' instruction at the + /// specific location targeting a new destination register. + /// The register in Orig->getOperand(0).getReg() will be substituted by + /// DestReg:SubIdx. Any existing subreg index is preserved or composed with + /// SubIdx. + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo &TRI) const = 0; + + /// scheduleTwoAddrSource - Schedule the copy / re-mat of the source of the + /// two-addrss instruction inserted by two-address pass. + virtual void scheduleTwoAddrSource(MachineInstr *SrcMI, + MachineInstr *UseMI, + const TargetRegisterInfo &TRI) const { + // Do nothing. + } + + /// duplicate - Create a duplicate of the Orig instruction in MF. This is like + /// MachineFunction::CloneMachineInstr(), but the target may update operands + /// that are required to be unique. + /// + /// The instruction must be duplicable as indicated by isNotDuplicable(). + virtual MachineInstr *duplicate(MachineInstr *Orig, + MachineFunction &MF) const = 0; + + /// convertToThreeAddress - This method must be implemented by targets that + /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target + /// may be able to convert a two-address instruction into one or more true + /// three-address instructions on demand. This allows the X86 target (for + /// example) to convert ADD and SHL instructions into LEA instructions if they + /// would require register copies due to two-addressness. + /// + /// This method returns a null pointer if the transformation cannot be + /// performed, otherwise it returns the last new instruction. + /// + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const { + return 0; + } + + /// commuteInstruction - If a target has any instructions that are + /// commutable but require converting to different instructions or making + /// non-trivial changes to commute them, this method can overloaded to do + /// that. The default implementation simply swaps the commutable operands. + /// If NewMI is false, MI is modified in place and returned; otherwise, a + /// new machine instruction is created and returned. Do not call this + /// method for a non-commutable instruction, but there may be some cases + /// where this method fails and returns null. + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const = 0; + + /// findCommutedOpIndices - If specified MI is commutable, return the two + /// operand indices that would swap value. Return false if the instruction + /// is not in a form which this routine understands. + virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const = 0; + + /// produceSameValue - Return true if two machine instructions would produce + /// identical values. By default, this is only true when the two instructions + /// are deemed identical except for defs. If this function is called when the + /// IR is still in SSA form, the caller can pass the MachineRegisterInfo for + /// aggressive checks. + virtual bool produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI = 0) const = 0; + + /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning + /// true if it cannot be understood (e.g. it's a switch dispatch or isn't + /// implemented for a target). Upon success, this returns false and returns + /// with the following information in various cases: + /// + /// 1. If this block ends with no branches (it just falls through to its succ) + /// just return false, leaving TBB/FBB null. + /// 2. If this block ends with only an unconditional branch, it sets TBB to be + /// the destination block. + /// 3. If this block ends with a conditional branch and it falls through to a + /// successor block, it sets TBB to be the branch destination block and a + /// list of operands that evaluate the condition. These operands can be + /// passed to other TargetInstrInfo methods to create new branches. + /// 4. If this block ends with a conditional branch followed by an + /// unconditional branch, it returns the 'true' destination in TBB, the + /// 'false' destination in FBB, and a list of operands that evaluate the + /// condition. These operands can be passed to other TargetInstrInfo + /// methods to create new branches. + /// + /// Note that RemoveBranch and InsertBranch must be implemented to support + /// cases where this method returns success. + /// + /// If AllowModify is true, then this routine is allowed to modify the basic + /// block (e.g. delete instructions after the unconditional branch). + /// + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify = false) const { + return true; + } + + /// RemoveBranch - Remove the branching code at the end of the specific MBB. + /// This is only invoked in cases where AnalyzeBranch returns success. It + /// returns the number of instructions that were removed. + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + return 0; + } + + /// InsertBranch - Insert branch code into the end of the specified + /// MachineBasicBlock. The operands to this method are the same as those + /// returned by AnalyzeBranch. This is only invoked in cases where + /// AnalyzeBranch returns success. It returns the number of instructions + /// inserted. + /// + /// It is also invoked by tail merging to add unconditional branches in + /// cases where AnalyzeBranch doesn't apply because there was no original + /// branch to analyze. At least this much must be implemented, else tail + /// merging needs to be disabled. + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const { + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + return 0; + } + + /// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything + /// after it, replacing it with an unconditional branch to NewDest. This is + /// used by the tail merging pass. + virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, + MachineBasicBlock *NewDest) const = 0; + + /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic + /// block at the specified instruction (i.e. instruction would be the start + /// of a new basic block). + virtual bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI) const { + return true; + } + + /// isProfitableToIfCvt - Return true if it's profitable to predicate + /// instructions with accumulated instruction latency of "NumCycles" + /// of the specified basic block, where the probability of the instructions + /// being executed is given by Probability, and Confidence is a measure + /// of our confidence that it will be properly predicted. + virtual + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + unsigned ExtraPredCycles, + float Probability, float Confidence) const { + return false; + } + + /// isProfitableToIfCvt - Second variant of isProfitableToIfCvt, this one + /// checks for the case where two basic blocks from true and false path + /// of a if-then-else (diamond) are predicated on mutally exclusive + /// predicates, where the probability of the true path being taken is given + /// by Probability, and Confidence is a measure of our confidence that it + /// will be properly predicted. + virtual bool + isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumTCycles, unsigned ExtraTCycles, + MachineBasicBlock &FMBB, + unsigned NumFCycles, unsigned ExtraFCycles, + float Probability, float Confidence) const { + return false; + } + + /// isProfitableToDupForIfCvt - Return true if it's profitable for + /// if-converter to duplicate instructions of specified accumulated + /// instruction latencies in the specified MBB to enable if-conversion. + /// The probability of the instructions being executed is given by + /// Probability, and Confidence is a measure of our confidence that it + /// will be properly predicted. + virtual bool + isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCyles, + float Probability, float Confidence) const { + return false; + } + + /// copyPhysReg - Emit instructions to copy a pair of physical registers. + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + assert(0 && "Target didn't implement TargetInstrInfo::copyPhysReg!"); + } + + /// storeRegToStackSlot - Store the specified register of the given register + /// class to the specified stack frame index. The store instruction is to be + /// added to the given machine basic block before the specified machine + /// instruction. If isKill is true, the register operand is the last use and + /// must be marked kill. + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!"); + } + + /// loadRegFromStackSlot - Load the specified register of the given register + /// class from the specified stack frame index. The load instruction is to be + /// added to the given machine basic block before the specified machine + /// instruction. + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); + } + + /// emitFrameIndexDebugValue - Emit a target-dependent form of + /// DBG_VALUE encoding the address of a frame index. Addresses would + /// normally be lowered the same way as other addresses on the target, + /// e.g. in load instructions. For targets that do not support this + /// the debug info is simply lost. + /// If you add this for a target you should handle this DBG_VALUE in the + /// target-specific AsmPrinter code as well; you will probably get invalid + /// assembly output if you don't. + virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, + uint64_t Offset, + const MDNode *MDPtr, + DebugLoc dl) const { + return 0; + } + + /// foldMemoryOperand - Attempt to fold a load or store of the specified stack + /// slot into the specified machine instruction for the specified operand(s). + /// If this is possible, a new instruction is returned with the specified + /// operand folded, otherwise NULL is returned. + /// The new instruction is inserted before MI, and the client is responsible + /// for removing the old instruction. + MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + /// foldMemoryOperand - Same as the previous version except it allows folding + /// of any load and store from / to any address, not just from a specific + /// stack slot. + MachineInstr* foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const; + +protected: + /// foldMemoryOperandImpl - Target-dependent implementation for + /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// take care of adding a MachineMemOperand to the newly created instruction. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const { + return 0; + } + + /// foldMemoryOperandImpl - Target-dependent implementation for + /// foldMemoryOperand. Target-independent code in foldMemoryOperand will + /// take care of adding a MachineMemOperand to the newly created instruction. + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + return 0; + } + +public: + /// canFoldMemoryOperand - Returns true for the specified load / store if + /// folding is possible. + virtual + bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const =0; + + /// unfoldMemoryOperand - Separate a single instruction which folded a load or + /// a store or a load and a store into two or more instruction. If this is + /// possible, returns true as well as the new instructions by reference. + virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr *MI, + unsigned Reg, bool UnfoldLoad, bool UnfoldStore, + SmallVectorImpl &NewMIs) const{ + return false; + } + + virtual bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N, + SmallVectorImpl &NewNodes) const { + return false; + } + + /// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new + /// instruction after load / store are unfolded from an instruction of the + /// specified opcode. It returns zero if the specified unfolding is not + /// possible. If LoadRegIndex is non-null, it is filled in with the operand + /// index of the operand which will hold the register holding the loaded + /// value. + virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, + bool UnfoldLoad, bool UnfoldStore, + unsigned *LoadRegIndex = 0) const { + return 0; + } + + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler + /// to determine if two loads are loading from the same base address. It + /// should only return true if the base pointers are the same and the + /// only differences between the two addresses are the offset. It also returns + /// the offsets by reference. + virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2) const { + return false; + } + + /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to + /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// be scheduled togther. On some targets if two loads are loading from + /// addresses in the same cache line, it's better if they are scheduled + /// together. This function takes two integers that represent the load offsets + /// from the common base address. It returns true if it decides it's desirable + /// to schedule the two loads together. "NumLoads" is the number of loads that + /// have already been scheduled after Load1. + virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const { + return false; + } + + /// ReverseBranchCondition - Reverses the branch condition of the specified + /// condition list, returning false on success and true if it cannot be + /// reversed. + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const { + return true; + } + + /// insertNoop - Insert a noop into the instruction stream at the specified + /// point. + virtual void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + + + /// getNoopForMachoTarget - Return the noop instruction to use for a noop. + virtual void getNoopForMachoTarget(MCInst &NopInst) const { + // Default to just using 'nop' string. + } + + + /// isPredicated - Returns true if the instruction is already predicated. + /// + virtual bool isPredicated(const MachineInstr *MI) const { + return false; + } + + /// isUnpredicatedTerminator - Returns true if the instruction is a + /// terminator instruction that has not been predicated. + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; + + /// PredicateInstruction - Convert the instruction into a predicated + /// instruction. It returns true if the operation was successful. + virtual + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const = 0; + + /// SubsumesPredicate - Returns true if the first specified predicate + /// subsumes the second, e.g. GE subsumes GT. + virtual + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { + return false; + } + + /// DefinesPredicate - If the specified instruction defines any predicate + /// or condition code register(s) used for predication, returns true as well + /// as the definition predicate(s) by reference. + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + return false; + } + + /// isPredicable - Return true if the specified instruction can be predicated. + /// By default, this returns true for every instruction with a + /// PredicateOperand. + virtual bool isPredicable(MachineInstr *MI) const { + return MI->getDesc().isPredicable(); + } + + /// isSafeToMoveRegClassDefs - Return true if it's safe to move a machine + /// instruction that defines the specified register class. + virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const { + return true; + } + + /// isSchedulingBoundary - Test if the given instruction should be + /// considered a scheduling boundary. This primarily includes labels and + /// terminators. + virtual bool isSchedulingBoundary(const MachineInstr *MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const = 0; + + /// Measure the specified inline asm to determine an approximation of its + /// length. + virtual unsigned getInlineAsmLength(const char *Str, + const MCAsmInfo &MAI) const; + + /// CreateTargetHazardRecognizer - Allocate and return a hazard recognizer to + /// use for this target when scheduling the machine instructions before + /// register allocation. + virtual ScheduleHazardRecognizer* + CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const = 0; + + /// CreateTargetPostRAHazardRecognizer - Allocate and return a hazard + /// recognizer to use for this target when scheduling the machine instructions + /// after register allocation. + virtual ScheduleHazardRecognizer* + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG *DAG) const = 0; + + /// AnalyzeCompare - For a comparison instruction, return the source register + /// in SrcReg and the value it compares against in CmpValue. Return true if + /// the comparison instruction can be analyzed. + virtual bool AnalyzeCompare(const MachineInstr *MI, + unsigned &SrcReg, int &Mask, int &Value) const { + return false; + } + + /// OptimizeCompareInstr - See if the comparison instruction can be converted + /// into something more efficient. E.g., on ARM most instructions can set the + /// flags register, obviating the need for a separate CMP. + virtual bool OptimizeCompareInstr(MachineInstr *CmpInstr, + unsigned SrcReg, int Mask, int Value, + const MachineRegisterInfo *MRI) const { + return false; + } + + /// FoldImmediate - 'Reg' is known to be defined by a move immediate + /// instruction, try to fold the immediate into the use instruction. + virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, + unsigned Reg, MachineRegisterInfo *MRI) const { + return false; + } + + /// getNumMicroOps - Return the number of u-operations the given machine + /// instruction will be decoded to on the target cpu. + virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, + const MachineInstr *MI) const; + + /// isZeroCost - Return true for pseudo instructions that don't consume any + /// machine resources in their current form. These are common cases that the + /// scheduler should consider free, rather than conservatively handling them + /// as instructions with no itinerary. + bool isZeroCost(unsigned Opcode) const { + return Opcode <= TargetOpcode::COPY; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// pair of def and use. + /// In most cases, the static scheduling itinerary was enough to determine the + /// operand latency. But it may not be possible for instructions with variable + /// number of defs / uses. + virtual int getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const; + + virtual int getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, unsigned UseIdx) const; + + /// getInstrLatency - Compute the instruction latency of a given instruction. + /// If the instruction has higher cost when predicated, it's returned via + /// PredCost. + virtual int getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, + unsigned *PredCost = 0) const; + + virtual int getInstrLatency(const InstrItineraryData *ItinData, + SDNode *Node) const; + + /// isHighLatencyDef - Return true if this opcode has high latency to its + /// result. + virtual bool isHighLatencyDef(int opc) const { return false; } + + /// hasHighOperandLatency - Compute operand latency between a def of 'Reg' + /// and an use in the current loop, return true if the target considered + /// it 'high'. This is used by optimization passes such as machine LICM to + /// determine whether it makes sense to hoist an instruction out even in + /// high register pressure situation. + virtual + bool hasHighOperandLatency(const InstrItineraryData *ItinData, + const MachineRegisterInfo *MRI, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const { + return false; + } + + /// hasLowDefLatency - Compute operand latency of a def of 'Reg', return true + /// if the target considered it 'low'. + virtual + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; +}; + +/// TargetInstrInfoImpl - This is the default implementation of +/// TargetInstrInfo, which just provides a couple of default implementations +/// for various methods. This separated out because it is implemented in +/// libcodegen, not in libtarget. +class TargetInstrInfoImpl : public TargetInstrInfo { +protected: + TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) + : TargetInstrInfo(desc, NumOpcodes) {} +public: + virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, + MachineBasicBlock *NewDest) const; + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const; + virtual bool findCommutedOpIndices(MachineInstr *MI, unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const; + virtual bool canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const; + virtual bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const; + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubReg, + const MachineInstr *Orig, + const TargetRegisterInfo &TRI) const; + virtual MachineInstr *duplicate(MachineInstr *Orig, + MachineFunction &MF) const; + virtual bool produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const; + virtual bool isSchedulingBoundary(const MachineInstr *MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const; + + bool usePreRAHazardRecognizer() const; + + virtual ScheduleHazardRecognizer * + CreateTargetHazardRecognizer(const TargetMachine*, const ScheduleDAG*) const; + + virtual ScheduleHazardRecognizer * + CreateTargetPostRAHazardRecognizer(const InstrItineraryData*, + const ScheduleDAG*) const; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetInstrItineraries.h b/final/include/llvm/Target/TargetInstrItineraries.h new file mode 100644 index 00000000000..a95b70f6b99 --- /dev/null +++ b/final/include/llvm/Target/TargetInstrItineraries.h @@ -0,0 +1,248 @@ +//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction +// itineraries, stages, and operand reads/writes. This is used by +// schedulers to determine instruction stages and latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H +#define LLVM_TARGET_TARGETINSTRITINERARIES_H + +#include + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// Instruction stage - These values represent a non-pipelined step in +/// the execution of an instruction. Cycles represents the number of +/// discrete time slots needed to complete the stage. Units represent +/// the choice of functional units that can be used to complete the +/// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +/// cycles should elapse from the start of this stage to the start of +/// the next stage in the itinerary. A value of -1 indicates that the +/// next stage should start immediately after the current one. +/// For example: +/// +/// { 1, x, -1 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts immediately after this one. +/// +/// { 2, x|y, 1 } +/// indicates that the stage occupies either FU x or FU y for 2 +/// consecuative cycles and that the next stage starts one cycle +/// after this stage starts. That is, the stage requirements +/// overlap in time. +/// +/// { 1, x, 0 } +/// indicates that the stage occupies FU x for 1 cycle and that +/// the next stage starts in this same cycle. This can be used to +/// indicate that the instruction requires multiple stages at the +/// same time. +/// +/// FU reservation can be of two different kinds: +/// - FUs which instruction actually requires +/// - FUs which instruction just reserves. Reserved unit is not available for +/// execution of other instruction. However, several instructions can reserve +/// the same unit several times. +/// Such two types of units reservation is used to model instruction domain +/// change stalls, FUs using the same resource (e.g. same register file), etc. + +struct InstrStage { + enum ReservationKinds { + Required = 0, + Reserved = 1 + }; + + unsigned Cycles_; ///< Length of stage in machine cycles + unsigned Units_; ///< Choice of functional units + int NextCycles_; ///< Number of machine cycles to next stage + ReservationKinds Kind_; ///< Kind of the FU reservation + + /// getCycles - returns the number of cycles the stage is occupied + unsigned getCycles() const { + return Cycles_; + } + + /// getUnits - returns the choice of FUs + unsigned getUnits() const { + return Units_; + } + + ReservationKinds getReservationKind() const { + return Kind_; + } + + /// getNextCycles - returns the number of cycles from the start of + /// this stage to the start of the next stage in the itinerary + unsigned getNextCycles() const { + return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; + } +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary - An itinerary represents the scheduling +/// information for an instruction. This includes a set of stages +/// occupies by the instruction, and the pipeline cycle in which +/// operands are read and written. +/// +struct InstrItinerary { + unsigned NumMicroOps; ///< # of micro-ops, 0 means it's variable + unsigned FirstStage; ///< Index of first stage in itinerary + unsigned LastStage; ///< Index of last + 1 stage in itinerary + unsigned FirstOperandCycle; ///< Index of first operand rd/wr + unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr +}; + + +//===----------------------------------------------------------------------===// +/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be +/// used by a target. +/// +class InstrItineraryData { +public: + const InstrStage *Stages; ///< Array of stages selected + const unsigned *OperandCycles; ///< Array of operand cycles selected + const unsigned *Forwardings; ///< Array of pipeline forwarding pathes + const InstrItinerary *Itineraries; ///< Array of itineraries selected + unsigned IssueWidth; ///< Max issue per cycle. 0=Unknown. + + /// Ctors. + /// + InstrItineraryData() : Stages(0), OperandCycles(0), Forwardings(0), + Itineraries(0), IssueWidth(0) {} + + InstrItineraryData(const InstrStage *S, const unsigned *OS, + const unsigned *F, const InstrItinerary *I) + : Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(I) {} + + /// isEmpty - Returns true if there are no itineraries. + /// + bool isEmpty() const { return Itineraries == 0; } + + /// isEndMarker - Returns true if the index is for the end marker + /// itinerary. + /// + bool isEndMarker(unsigned ItinClassIndx) const { + return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && + (Itineraries[ItinClassIndx].LastStage == ~0U)); + } + + /// beginStage - Return the first stage of the itinerary. + /// + const InstrStage *beginStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; + return Stages + StageIdx; + } + + /// endStage - Return the last+1 stage of the itinerary. + /// + const InstrStage *endStage(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; + return Stages + StageIdx; + } + + /// getStageLatency - Return the total stage latency of the given + /// class. The latency is the maximum completion time for any stage + /// in the itinerary. + /// + unsigned getStageLatency(unsigned ItinClassIndx) const { + // If the target doesn't provide itinerary information, use a + // simple non-zero default value for all instructions. + if (isEmpty()) + return 1; + + // Calculate the maximum completion time for any stage. + unsigned Latency = 0, StartCycle = 0; + for (const InstrStage *IS = beginStage(ItinClassIndx), + *E = endStage(ItinClassIndx); IS != E; ++IS) { + Latency = std::max(Latency, StartCycle + IS->getCycles()); + StartCycle += IS->getNextCycles(); + } + + return Latency; + } + + /// getOperandCycle - Return the cycle for the given class and + /// operand. Return -1 if no cycle is specified for the operand. + /// + int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { + if (isEmpty()) + return -1; + + unsigned FirstIdx = Itineraries[ItinClassIndx].FirstOperandCycle; + unsigned LastIdx = Itineraries[ItinClassIndx].LastOperandCycle; + if ((FirstIdx + OperandIdx) >= LastIdx) + return -1; + + return (int)OperandCycles[FirstIdx + OperandIdx]; + } + + /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// between instructions of itinerary classes DefClass and UseClasses so that + /// value produced by an instruction of itinerary class DefClass, operand + /// index DefIdx can be bypassed when it's read by an instruction of + /// itinerary class UseClass, operand index UseIdx. + bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; + unsigned LastDefIdx = Itineraries[DefClass].LastOperandCycle; + if ((FirstDefIdx + DefIdx) >= LastDefIdx) + return false; + if (Forwardings[FirstDefIdx + DefIdx] == 0) + return false; + + unsigned FirstUseIdx = Itineraries[UseClass].FirstOperandCycle; + unsigned LastUseIdx = Itineraries[UseClass].LastOperandCycle; + if ((FirstUseIdx + UseIdx) >= LastUseIdx) + return false; + + return Forwardings[FirstDefIdx + DefIdx] == + Forwardings[FirstUseIdx + UseIdx]; + } + + /// getOperandLatency - Compute and return the use operand latency of a given + /// itinerary class and operand index if the value is produced by an + /// instruction of the specified itinerary class and def operand index. + int getOperandLatency(unsigned DefClass, unsigned DefIdx, + unsigned UseClass, unsigned UseIdx) const { + if (isEmpty()) + return -1; + + int DefCycle = getOperandCycle(DefClass, DefIdx); + if (DefCycle == -1) + return -1; + + int UseCycle = getOperandCycle(UseClass, UseIdx); + if (UseCycle == -1) + return -1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0 && + hasPipelineForwarding(DefClass, DefIdx, UseClass, UseIdx)) + // FIXME: This assumes one cycle benefit for every pipeline forwarding. + --UseCycle; + return UseCycle; + } + + /// isMicroCoded - Return true if the instructions in the given class decode + /// to more than one micro-ops. + bool isMicroCoded(unsigned ItinClassIndx) const { + if (isEmpty()) + return false; + return Itineraries[ItinClassIndx].NumMicroOps != 1; + } +}; + + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetIntrinsicInfo.h b/final/include/llvm/Target/TargetIntrinsicInfo.h new file mode 100644 index 00000000000..ad8ac925e93 --- /dev/null +++ b/final/include/llvm/Target/TargetIntrinsicInfo.h @@ -0,0 +1,64 @@ +//===-- llvm/Target/TargetIntrinsicInfo.h - Instruction 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 describes the target intrinsic instructions to the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H +#define LLVM_TARGET_TARGETINTRINSICINFO_H + +#include + +namespace llvm { + +class Function; +class Module; +class Type; + +//--------------------------------------------------------------------------- +/// +/// TargetIntrinsicInfo - Interface to description of machine instruction set +/// +class TargetIntrinsicInfo { + TargetIntrinsicInfo(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT + void operator=(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT +public: + TargetIntrinsicInfo(); + virtual ~TargetIntrinsicInfo(); + + /// Return the name of a target intrinsic, e.g. "llvm.bfin.ssync". + /// The Tys and numTys parameters are for intrinsics with overloaded types + /// (e.g., those using iAny or fAny). For a declaration for an overloaded + /// intrinsic, Tys should point to an array of numTys pointers to Type, + /// and must provide exactly one type for each overloaded type in the + /// intrinsic. + virtual std::string getName(unsigned IID, const Type **Tys = 0, + unsigned numTys = 0) const = 0; + + /// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown + /// names. + virtual unsigned lookupName(const char *Name, unsigned Len) const =0; + + /// Return the target intrinsic ID of a function, or 0. + virtual unsigned getIntrinsicID(Function *F) const; + + /// Returns true if the intrinsic can be overloaded. + virtual bool isOverloaded(unsigned IID) const = 0; + + /// Create or insert an LLVM Function declaration for an intrinsic, + /// and return it. The Tys and numTys are for intrinsics with overloaded + /// types. See above for more information. + virtual Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0, + unsigned numTys = 0) const = 0; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetJITInfo.h b/final/include/llvm/Target/TargetJITInfo.h new file mode 100644 index 00000000000..b198eb62f0c --- /dev/null +++ b/final/include/llvm/Target/TargetJITInfo.h @@ -0,0 +1,142 @@ +//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an abstract interface used by the Just-In-Time code +// generator to perform target-specific activities, such as emitting stubs. If +// a TargetMachine supports JIT code generation, it should provide one of these +// objects through the getJITInfo() method. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETJITINFO_H +#define LLVM_TARGET_TARGETJITINFO_H + +#include +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class Function; + class GlobalValue; + class JITCodeEmitter; + class MachineRelocation; + + /// TargetJITInfo - Target specific information required by the Just-In-Time + /// code generator. + class TargetJITInfo { + public: + virtual ~TargetJITInfo() {} + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0; + + /// emitGlobalValueIndirectSym - Use the specified JITCodeEmitter object + /// to emit an indirect symbol which contains the address of the specified + /// ptr. + virtual void *emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, + JITCodeEmitter &JCE) { + assert(0 && "This target doesn't implement emitGlobalValueIndirectSym!"); + return 0; + } + + /// Records the required size and alignment for a call stub in bytes. + struct StubLayout { + size_t Size; + size_t Alignment; + }; + /// Returns the maximum size and alignment for a call stub on this target. + virtual StubLayout getStubLayout() { + llvm_unreachable("This target doesn't implement getStubLayout!"); + StubLayout Result = {0, 0}; + return Result; + } + + /// emitFunctionStub - Use the specified JITCodeEmitter object to emit a + /// small native function that simply calls the function at the specified + /// address. The JITCodeEmitter must already have storage allocated for the + /// stub. Return the address of the resultant function, which may have been + /// aligned from the address the JCE was set up to emit at. + virtual void *emitFunctionStub(const Function* F, void *Target, + JITCodeEmitter &JCE) { + assert(0 && "This target doesn't implement emitFunctionStub!"); + return 0; + } + + /// getPICJumpTableEntry - Returns the value of the jumptable entry for the + /// specific basic block. + virtual uintptr_t getPICJumpTableEntry(uintptr_t BB, uintptr_t JTBase) { + assert(0 && "This target doesn't implement getPICJumpTableEntry!"); + return 0; + } + + /// LazyResolverFn - This typedef is used to represent the function that + /// unresolved call points should invoke. This is a target specific + /// function that knows how to walk the stack and find out which stub the + /// call is coming from. + typedef void (*LazyResolverFn)(); + + /// JITCompilerFn - This typedef is used to represent the JIT function that + /// lazily compiles the function corresponding to a stub. The JIT keeps + /// track of the mapping between stubs and LLVM Functions, the target + /// provides the ability to figure out the address of a stub that is called + /// by the LazyResolverFn. + typedef void* (*JITCompilerFn)(void *); + + /// getLazyResolverFunction - This method is used to initialize the JIT, + /// giving the target the function that should be used to compile a + /// function, and giving the JIT the target function used to do the lazy + /// resolving. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) { + assert(0 && "Not implemented for this target!"); + return 0; + } + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// it must rewrite the code to contain the actual addresses of any + /// referenced global symbols. + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + assert(NumRelocs == 0 && "This target does not have relocations!"); + } + + + /// allocateThreadLocalMemory - Each target has its own way of + /// handling thread local variables. This method returns a value only + /// meaningful to the target. + virtual char* allocateThreadLocalMemory(size_t size) { + assert(0 && "This target does not implement thread local storage!"); + return 0; + } + + /// needsGOT - Allows a target to specify that it would like the + /// JIT to manage a GOT for it. + bool needsGOT() const { return useGOT; } + + /// hasCustomConstantPool - Allows a target to specify that constant + /// pool address resolution is handled by the target. + virtual bool hasCustomConstantPool() const { return false; } + + /// hasCustomJumpTables - Allows a target to specify that jumptables + /// are emitted by the target. + virtual bool hasCustomJumpTables() const { return false; } + + /// allocateSeparateGVMemory - If true, globals should be placed in + /// separately allocated heap memory rather than in the same + /// code memory allocated by JITCodeEmitter. + virtual bool allocateSeparateGVMemory() const { return false; } + protected: + bool useGOT; + }; +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetLibraryInfo.h b/final/include/llvm/Target/TargetLibraryInfo.h new file mode 100644 index 00000000000..1847a3725e6 --- /dev/null +++ b/final/include/llvm/Target/TargetLibraryInfo.h @@ -0,0 +1,75 @@ +//===-- llvm/Target/TargetLibraryInfo.h - Library information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLIBRARYINFO_H +#define LLVM_TARGET_TARGETLIBRARYINFO_H + +#include "llvm/Pass.h" + +namespace llvm { + class Triple; + + namespace LibFunc { + enum Func { + /// void *memset(void *b, int c, size_t len); + memset, + + // void *memcpy(void *s1, const void *s2, size_t n); + memcpy, + + /// void memset_pattern16(void *b, const void *pattern16, size_t len); + memset_pattern16, + + /// int iprintf(const char *format, ...); + iprintf, + + /// int siprintf(char *str, const char *format, ...); + siprintf, + + /// int fiprintf(FILE *stream, const char *format, ...); + fiprintf, + + NumLibFuncs + }; + } + +/// TargetLibraryInfo - This immutable pass captures information about what +/// library functions are available for the current target, and allows a +/// frontend to disable optimizations through -fno-builtin etc. +class TargetLibraryInfo : public ImmutablePass { + unsigned char AvailableArray[(LibFunc::NumLibFuncs+7)/8]; +public: + static char ID; + TargetLibraryInfo(); + TargetLibraryInfo(const Triple &T); + + /// has - This function is used by optimizations that want to match on or form + /// a given library function. + bool has(LibFunc::Func F) const { + return (AvailableArray[F/8] & (1 << (F&7))) != 0; + } + + /// setUnavailable - this can be used by whatever sets up TargetLibraryInfo to + /// ban use of specific library functions. + void setUnavailable(LibFunc::Func F) { + AvailableArray[F/8] &= ~(1 << (F&7)); + } + + void setAvailable(LibFunc::Func F) { + AvailableArray[F/8] |= 1 << (F&7); + } + + /// disableAllFunctions - This disables all builtins, which is used for + /// options like -fno-builtin. + void disableAllFunctions(); +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Target/TargetLowering.h b/final/include/llvm/Target/TargetLowering.h new file mode 100644 index 00000000000..63bf8a2aa0c --- /dev/null +++ b/final/include/llvm/Target/TargetLowering.h @@ -0,0 +1,1864 @@ +//===-- llvm/Target/TargetLowering.h - Target Lowering 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 describes how to lower LLVM code to machine code. This has two +// main components: +// +// 1. Which ValueTypes are natively supported by the target. +// 2. Which operations are supported for supported ValueTypes. +// 3. Cost thresholds for alternative implementations of certain operations. +// +// In addition it has a few other components, like information about FP +// immediates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLOWERING_H +#define LLVM_TARGET_TARGETLOWERING_H + +#include "llvm/CallingConv.h" +#include "llvm/InlineAsm.h" +#include "llvm/Attributes.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Target/TargetCallingConv.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include + +namespace llvm { + class AllocaInst; + class APFloat; + class CallInst; + class CCState; + class Function; + class FastISel; + class FunctionLoweringInfo; + class ImmutableCallSite; + class MachineBasicBlock; + class MachineFunction; + class MachineFrameInfo; + class MachineInstr; + class MachineJumpTableInfo; + class MCContext; + class MCExpr; + class SDNode; + class SDValue; + class SelectionDAG; + template class SmallVectorImpl; + class TargetData; + class TargetMachine; + class TargetRegisterClass; + class TargetLoweringObjectFile; + class Value; + + // FIXME: should this be here? + namespace TLSModel { + enum Model { + GeneralDynamic, + LocalDynamic, + InitialExec, + LocalExec + }; + } + TLSModel::Model getTLSModel(const GlobalValue *GV, Reloc::Model reloc); + + +//===----------------------------------------------------------------------===// +/// TargetLowering - This class defines information used to lower LLVM code to +/// legal SelectionDAG operators that the target instruction selector can accept +/// natively. +/// +/// This class also defines callbacks that targets must implement to lower +/// target-specific constructs to SelectionDAG operators. +/// +class TargetLowering { + TargetLowering(const TargetLowering&); // DO NOT IMPLEMENT + void operator=(const TargetLowering&); // DO NOT IMPLEMENT +public: + /// LegalizeAction - This enum indicates whether operations are valid for a + /// target, and if not, what action should be used to make them valid. + enum LegalizeAction { + Legal, // The target natively supports this operation. + Promote, // This operation should be executed in a larger type. + Expand, // Try to expand this to other ops, otherwise use a libcall. + Custom // Use the LowerOperation hook to implement custom lowering. + }; + + enum BooleanContent { // How the target represents true/false values. + UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage. + ZeroOrOneBooleanContent, // All bits zero except for bit 0. + ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. + }; + + /// NOTE: The constructor takes ownership of TLOF. + explicit TargetLowering(const TargetMachine &TM, + const TargetLoweringObjectFile *TLOF); + virtual ~TargetLowering(); + + const TargetMachine &getTargetMachine() const { return TM; } + const TargetData *getTargetData() const { return TD; } + const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } + + bool isBigEndian() const { return !IsLittleEndian; } + bool isLittleEndian() const { return IsLittleEndian; } + MVT getPointerTy() const { return PointerTy; } + virtual MVT getShiftAmountTy(EVT LHSTy) const; + + /// isSelectExpensive - Return true if the select operation is expensive for + /// this target. + bool isSelectExpensive() const { return SelectIsExpensive; } + + /// isIntDivCheap() - Return true if integer divide is usually cheaper than + /// a sequence of several shifts, adds, and multiplies for this target. + bool isIntDivCheap() const { return IntDivIsCheap; } + + /// isPow2DivCheap() - Return true if pow2 div is cheaper than a chain of + /// srl/add/sra. + bool isPow2DivCheap() const { return Pow2DivIsCheap; } + + /// isJumpExpensive() - Return true if Flow Control is an expensive operation + /// that should be avoided. + bool isJumpExpensive() const { return JumpIsExpensive; } + + /// getSetCCResultType - Return the ValueType of the result of SETCC + /// operations. Also used to obtain the target's preferred type for + /// the condition operand of SELECT and BRCOND nodes. In the case of + /// BRCOND the argument passed is MVT::Other since there are no other + /// operands to get a type hint from. + virtual + MVT::SimpleValueType getSetCCResultType(EVT VT) const; + + /// getCmpLibcallReturnType - Return the ValueType for comparison + /// libcalls. Comparions libcalls include floating point comparion calls, + /// and Ordered/Unordered check calls on floating point numbers. + virtual + MVT::SimpleValueType getCmpLibcallReturnType() const; + + /// getBooleanContents - For targets without i1 registers, this gives the + /// nature of the high-bits of boolean values held in types wider than i1. + /// "Boolean values" are special true/false values produced by nodes like + /// SETCC and consumed (as the condition) by nodes like SELECT and BRCOND. + /// Not to be confused with general values promoted from i1. + BooleanContent getBooleanContents() const { return BooleanContents;} + + /// getSchedulingPreference - Return target scheduling preference. + Sched::Preference getSchedulingPreference() const { + return SchedPreferenceInfo; + } + + /// getSchedulingPreference - Some scheduler, e.g. hybrid, can switch to + /// different scheduling heuristics for different nodes. This function returns + /// the preference (or none) for the given node. + virtual Sched::Preference getSchedulingPreference(SDNode *N) const { + return Sched::None; + } + + /// getRegClassFor - Return the register class that should be used for the + /// specified value type. + virtual TargetRegisterClass *getRegClassFor(EVT VT) const { + assert(VT.isSimple() && "getRegClassFor called on illegal type!"); + TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT().SimpleTy]; + assert(RC && "This value type is not natively supported!"); + return RC; + } + + /// getRepRegClassFor - Return the 'representative' register class for the + /// specified value type. The 'representative' register class is the largest + /// legal super-reg register class for the register class of the value type. + /// For example, on i386 the rep register class for i8, i16, and i32 are GR32; + /// while the rep register class is GR64 on x86_64. + virtual const TargetRegisterClass *getRepRegClassFor(EVT VT) const { + assert(VT.isSimple() && "getRepRegClassFor called on illegal type!"); + const TargetRegisterClass *RC = RepRegClassForVT[VT.getSimpleVT().SimpleTy]; + return RC; + } + + /// getRepRegClassCostFor - Return the cost of the 'representative' register + /// class for the specified value type. + virtual uint8_t getRepRegClassCostFor(EVT VT) const { + assert(VT.isSimple() && "getRepRegClassCostFor called on illegal type!"); + return RepRegClassCostForVT[VT.getSimpleVT().SimpleTy]; + } + + /// isTypeLegal - Return true if the target has native support for the + /// specified value type. This means that it has a register that directly + /// holds it without promotions or expansions. + bool isTypeLegal(EVT VT) const { + assert(!VT.isSimple() || + (unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); + return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != 0; + } + + class ValueTypeActionImpl { + /// ValueTypeActions - For each value type, keep a LegalizeAction enum + /// that indicates how instruction selection should deal with the type. + uint8_t ValueTypeActions[MVT::LAST_VALUETYPE]; + + LegalizeAction getExtendedTypeAction(EVT VT) const { + // Handle non-vector integers. + if (!VT.isVector()) { + assert(VT.isInteger() && "Unsupported extended type!"); + unsigned BitSize = VT.getSizeInBits(); + // First promote to a power-of-two size, then expand if necessary. + if (BitSize < 8 || !isPowerOf2_32(BitSize)) + return Promote; + return Expand; + } + + // Vectors with only one element are always scalarized. + if (VT.getVectorNumElements() == 1) + return Expand; + + // Vectors with a number of elements that is not a power of two are always + // widened, for example <3 x float> -> <4 x float>. + if (!VT.isPow2VectorType()) + return Promote; + + // Vectors with a crazy element type are always expanded, for example + // <4 x i2> is expanded into two vectors of type <2 x i2>. + if (!VT.getVectorElementType().isSimple()) + return Expand; + + // If this type is smaller than a legal vector type then widen it, + // otherwise expand it. E.g. <2 x float> -> <4 x float>. + MVT EltType = VT.getVectorElementType().getSimpleVT(); + unsigned NumElts = VT.getVectorNumElements(); + while (1) { + // Round up to the next power of 2. + NumElts = (unsigned)NextPowerOf2(NumElts); + + // If there is no simple vector type with this many elements then there + // cannot be a larger legal vector type. Note that this assumes that + // there are no skipped intermediate vector types in the simple types. + MVT LargerVector = MVT::getVectorVT(EltType, NumElts); + if (LargerVector == MVT()) + return Expand; + + // If this type is legal then widen the vector. + if (getTypeAction(LargerVector) == Legal) + return Promote; + } + } + public: + ValueTypeActionImpl() { + std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0); + } + + LegalizeAction getTypeAction(EVT VT) const { + if (!VT.isExtended()) + return getTypeAction(VT.getSimpleVT()); + return getExtendedTypeAction(VT); + } + + LegalizeAction getTypeAction(MVT VT) const { + return (LegalizeAction)ValueTypeActions[VT.SimpleTy]; + } + + void setTypeAction(EVT VT, LegalizeAction Action) { + unsigned I = VT.getSimpleVT().SimpleTy; + ValueTypeActions[I] = Action; + } + }; + + const ValueTypeActionImpl &getValueTypeActions() const { + return ValueTypeActions; + } + + /// getTypeAction - Return how we should legalize values of this type, either + /// it is already legal (return 'Legal') or we need to promote it to a larger + /// type (return 'Promote'), or we need to expand it into multiple registers + /// of smaller integer type (return 'Expand'). 'Custom' is not an option. + LegalizeAction getTypeAction(EVT VT) const { + return ValueTypeActions.getTypeAction(VT); + } + LegalizeAction getTypeAction(MVT VT) const { + return ValueTypeActions.getTypeAction(VT); + } + + /// getTypeToTransformTo - For types supported by the target, this is an + /// identity function. For types that must be promoted to larger types, this + /// returns the larger type to promote to. For integer types that are larger + /// than the largest integer register, this contains one step in the expansion + /// to get to the smaller register. For illegal floating point types, this + /// returns the integer type to transform to. + EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(TransformToType)); + EVT NVT = TransformToType[VT.getSimpleVT().SimpleTy]; + assert(getTypeAction(NVT) != Promote && + "Promote may not follow Expand or Promote"); + return NVT; + } + + if (VT.isVector()) { + EVT NVT = VT.getPow2VectorType(Context); + if (NVT == VT) { + // Vector length is a power of 2 - split to half the size. + unsigned NumElts = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + return (NumElts == 1) ? + EltVT : EVT::getVectorVT(Context, EltVT, NumElts / 2); + } + // Promote to a power of two size, avoiding multi-step promotion. + return getTypeAction(NVT) == Promote ? + getTypeToTransformTo(Context, NVT) : NVT; + } else if (VT.isInteger()) { + EVT NVT = VT.getRoundIntegerType(Context); + if (NVT == VT) // Size is a power of two - expand to half the size. + return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2); + + // Promote to a power of two size, avoiding multi-step promotion. + return getTypeAction(NVT) == Promote ? + getTypeToTransformTo(Context, NVT) : NVT; + } + assert(0 && "Unsupported extended type!"); + return MVT(MVT::Other); // Not reached + } + + /// getTypeToExpandTo - For types supported by the target, this is an + /// identity function. For types that must be expanded (i.e. integer types + /// that are larger than the largest integer register or illegal floating + /// point types), this returns the largest legal type it will be expanded to. + EVT getTypeToExpandTo(LLVMContext &Context, EVT VT) const { + assert(!VT.isVector()); + while (true) { + switch (getTypeAction(VT)) { + case Legal: + return VT; + case Expand: + VT = getTypeToTransformTo(Context, VT); + break; + default: + assert(false && "Type is not legal nor is it to be expanded!"); + return VT; + } + } + return VT; + } + + /// getVectorTypeBreakdown - Vector types are broken down into some number of + /// legal first class types. For example, EVT::v8f32 maps to 2 EVT::v4f32 + /// with Altivec or SSE1, or 8 promoted EVT::f64 values with the X86 FP stack. + /// Similarly, EVT::v2i64 turns into 4 EVT::i32 values with both PPC and X86. + /// + /// This method returns the number of registers needed, and the VT for each + /// register. It also returns the VT and quantity of the intermediate values + /// before they are promoted/expanded. + /// + unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT, + EVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT) const; + + /// getTgtMemIntrinsic: Given an intrinsic, checks if on the target the + /// intrinsic will need to map to a MemIntrinsicNode (touches memory). If + /// this is the case, it returns true and store the intrinsic + /// information into the IntrinsicInfo that was passed to the function. + struct IntrinsicInfo { + unsigned opc; // target opcode + EVT memVT; // memory VT + const Value* ptrVal; // value representing memory location + int offset; // offset off of ptrVal + unsigned align; // alignment + bool vol; // is volatile? + bool readMem; // reads memory? + bool writeMem; // writes memory? + }; + + virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info, + const CallInst &I, unsigned Intrinsic) const { + return false; + } + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will materialize + /// the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const { + return false; + } + + /// isShuffleMaskLegal - Targets can use this to indicate that they only + /// support *some* VECTOR_SHUFFLE operations, those with specific masks. + /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values + /// are assumed to be legal. + virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const { + return true; + } + + /// canOpTrap - Returns true if the operation can trap for the value type. + /// VT must be a legal type. By default, we optimistically assume most + /// operations don't trap except for divide and remainder. + virtual bool canOpTrap(unsigned Op, EVT VT) const; + + /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is + /// used by Targets can use this to indicate if there is a suitable + /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant + /// pool entry. + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, + EVT VT) const { + return false; + } + + /// getOperationAction - Return how this operation should be treated: either + /// it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction getOperationAction(unsigned Op, EVT VT) const { + if (VT.isExtended()) return Expand; + assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); + unsigned I = (unsigned) VT.getSimpleVT().SimpleTy; + return (LegalizeAction)OpActions[I][Op]; + } + + /// isOperationLegalOrCustom - Return true if the specified operation is + /// legal on this target or can be made legal with custom lowering. This + /// is used to help guide high-level lowering decisions. + bool isOperationLegalOrCustom(unsigned Op, EVT VT) const { + return (VT == MVT::Other || isTypeLegal(VT)) && + (getOperationAction(Op, VT) == Legal || + getOperationAction(Op, VT) == Custom); + } + + /// isOperationLegal - Return true if the specified operation is legal on this + /// target. + bool isOperationLegal(unsigned Op, EVT VT) const { + return (VT == MVT::Other || isTypeLegal(VT)) && + getOperationAction(Op, VT) == Legal; + } + + /// getLoadExtAction - Return how this load with extension should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + return (LegalizeAction)LoadExtActions[VT.getSimpleVT().SimpleTy][ExtType]; + } + + /// isLoadExtLegal - Return true if the specified load with extension is legal + /// on this target. + bool isLoadExtLegal(unsigned ExtType, EVT VT) const { + return VT.isSimple() && + (getLoadExtAction(ExtType, VT) == Legal || + getLoadExtAction(ExtType, VT) == Custom); + } + + /// getTruncStoreAction - Return how this store with truncation should be + /// treated: either it is legal, needs to be promoted to a larger size, needs + /// to be expanded to some other code sequence, or the target has a custom + /// expander for it. + LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { + assert(ValVT.getSimpleVT() < MVT::LAST_VALUETYPE && + MemVT.getSimpleVT() < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + return (LegalizeAction)TruncStoreActions[ValVT.getSimpleVT().SimpleTy] + [MemVT.getSimpleVT().SimpleTy]; + } + + /// isTruncStoreLegal - Return true if the specified store with truncation is + /// legal on this target. + bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { + return isTypeLegal(ValVT) && MemVT.isSimple() && + (getTruncStoreAction(ValVT, MemVT) == Legal || + getTruncStoreAction(ValVT, MemVT) == Custom); + } + + /// getIndexedLoadAction - Return how the indexed load should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction + getIndexedLoadAction(unsigned IdxMode, EVT VT) const { + assert(IdxMode < ISD::LAST_INDEXED_MODE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); + } + + /// isIndexedLoadLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const { + return VT.isSimple() && + (getIndexedLoadAction(IdxMode, VT) == Legal || + getIndexedLoadAction(IdxMode, VT) == Custom); + } + + /// getIndexedStoreAction - Return how the indexed store should be treated: + /// either it is legal, needs to be promoted to a larger size, needs to be + /// expanded to some other code sequence, or the target has a custom expander + /// for it. + LegalizeAction + getIndexedStoreAction(unsigned IdxMode, EVT VT) const { + assert(IdxMode < ISD::LAST_INDEXED_MODE && + VT.getSimpleVT() < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); + } + + /// isIndexedStoreLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const { + return VT.isSimple() && + (getIndexedStoreAction(IdxMode, VT) == Legal || + getIndexedStoreAction(IdxMode, VT) == Custom); + } + + /// getCondCodeAction - Return how the condition code should be treated: + /// either it is legal, needs to be expanded to some other code sequence, + /// or the target has a custom expander for it. + LegalizeAction + getCondCodeAction(ISD::CondCode CC, EVT VT) const { + assert((unsigned)CC < array_lengthof(CondCodeActions) && + (unsigned)VT.getSimpleVT().SimpleTy < sizeof(CondCodeActions[0])*4 && + "Table isn't big enough!"); + LegalizeAction Action = (LegalizeAction) + ((CondCodeActions[CC] >> (2*VT.getSimpleVT().SimpleTy)) & 3); + assert(Action != Promote && "Can't promote condition code!"); + return Action; + } + + /// isCondCodeLegal - Return true if the specified condition code is legal + /// on this target. + bool isCondCodeLegal(ISD::CondCode CC, EVT VT) const { + return getCondCodeAction(CC, VT) == Legal || + getCondCodeAction(CC, VT) == Custom; + } + + + /// getTypeToPromoteTo - If the action for this operation is to promote, this + /// method returns the ValueType to promote to. + EVT getTypeToPromoteTo(unsigned Op, EVT VT) const { + assert(getOperationAction(Op, VT) == Promote && + "This operation isn't promoted!"); + + // See if this has an explicit type specified. + std::map, + MVT::SimpleValueType>::const_iterator PTTI = + PromoteToType.find(std::make_pair(Op, VT.getSimpleVT().SimpleTy)); + if (PTTI != PromoteToType.end()) return PTTI->second; + + assert((VT.isInteger() || VT.isFloatingPoint()) && + "Cannot autopromote this type, add it with AddPromotedToType."); + + EVT NVT = VT; + do { + NVT = (MVT::SimpleValueType)(NVT.getSimpleVT().SimpleTy+1); + assert(NVT.isInteger() == VT.isInteger() && NVT != MVT::isVoid && + "Didn't find type to promote to!"); + } while (!isTypeLegal(NVT) || + getOperationAction(Op, NVT) == Promote); + return NVT; + } + + /// getValueType - Return the EVT corresponding to this LLVM type. + /// This is fixed by the LLVM operations except for the pointer size. If + /// AllowUnknown is true, this will return MVT::Other for types with no EVT + /// counterpart (e.g. structs), otherwise it will assert. + EVT getValueType(const Type *Ty, bool AllowUnknown = false) const { + EVT VT = EVT::getEVT(Ty, AllowUnknown); + return VT == MVT::iPTR ? PointerTy : VT; + } + + /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate + /// function arguments in the caller parameter area. This is the actual + /// alignment, not its logarithm. + virtual unsigned getByValTypeAlignment(const Type *Ty) const; + + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + EVT getRegisterType(MVT VT) const { + assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT)); + return RegisterTypeForVT[VT.SimpleTy]; + } + + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + EVT getRegisterType(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(RegisterTypeForVT)); + return RegisterTypeForVT[VT.getSimpleVT().SimpleTy]; + } + if (VT.isVector()) { + EVT VT1, RegisterVT; + unsigned NumIntermediates; + (void)getVectorTypeBreakdown(Context, VT, VT1, + NumIntermediates, RegisterVT); + return RegisterVT; + } + if (VT.isInteger()) { + return getRegisterType(Context, getTypeToTransformTo(Context, VT)); + } + assert(0 && "Unsupported extended type!"); + return EVT(MVT::Other); // Not reached + } + + /// getNumRegisters - Return the number of registers that this ValueType will + /// eventually require. This is one for any types promoted to live in larger + /// registers, but may be more than one for types (like i64) that are split + /// into pieces. For types like i140, which are first promoted then expanded, + /// it is the number of registers needed to hold all the bits of the original + /// type. For an i140 on a 32 bit machine this means 5 registers. + unsigned getNumRegisters(LLVMContext &Context, EVT VT) const { + if (VT.isSimple()) { + assert((unsigned)VT.getSimpleVT().SimpleTy < + array_lengthof(NumRegistersForVT)); + return NumRegistersForVT[VT.getSimpleVT().SimpleTy]; + } + if (VT.isVector()) { + EVT VT1, VT2; + unsigned NumIntermediates; + return getVectorTypeBreakdown(Context, VT, VT1, NumIntermediates, VT2); + } + if (VT.isInteger()) { + unsigned BitWidth = VT.getSizeInBits(); + unsigned RegWidth = getRegisterType(Context, VT).getSizeInBits(); + return (BitWidth + RegWidth - 1) / RegWidth; + } + assert(0 && "Unsupported extended type!"); + return 0; // Not reached + } + + /// ShouldShrinkFPConstant - If true, then instruction selection should + /// seek to shrink the FP constant of the specified type to a smaller type + /// in order to save space and / or reduce runtime. + virtual bool ShouldShrinkFPConstant(EVT VT) const { return true; } + + /// hasTargetDAGCombine - If true, the target has custom DAG combine + /// transformations that it can perform for the specified node. + bool hasTargetDAGCombine(ISD::NodeType NT) const { + assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); + return TargetDAGCombineArray[NT >> 3] & (1 << (NT&7)); + } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memset. The value is set by the target at the + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. + /// @brief Get maximum # of store operations permitted for llvm.memset + unsigned getMaxStoresPerMemset(bool OptSize) const { + return OptSize ? maxStoresPerMemsetOptSize : maxStoresPerMemset; + } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memcpy. The value is set by the target at the + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. + /// @brief Get maximum # of store operations permitted for llvm.memcpy + unsigned getMaxStoresPerMemcpy(bool OptSize) const { + return OptSize ? maxStoresPerMemcpyOptSize : maxStoresPerMemcpy; + } + + /// This function returns the maximum number of store operations permitted + /// to replace a call to llvm.memmove. The value is set by the target at the + /// performance threshold for such a replacement. If OptSize is true, + /// return the limit for functions that have OptSize attribute. + /// @brief Get maximum # of store operations permitted for llvm.memmove + unsigned getMaxStoresPerMemmove(bool OptSize) const { + return OptSize ? maxStoresPerMemmoveOptSize : maxStoresPerMemmove; + } + + /// This function returns true if the target allows unaligned memory accesses. + /// of the specified type. This is used, for example, in situations where an + /// array copy/move/set is converted to a sequence of store operations. It's + /// use helps to ensure that such replacements don't generate code that causes + /// an alignment error (trap) on the target machine. + /// @brief Determine if the target supports unaligned memory accesses. + virtual bool allowsUnalignedMemoryAccesses(EVT VT) const { + return false; + } + + /// This function returns true if the target would benefit from code placement + /// optimization. + /// @brief Determine if the target should perform code placement optimization. + bool shouldOptimizeCodePlacement() const { + return benefitFromCodePlacementOpt; + } + + /// getOptimalMemOpType - Returns the target specific optimal type for load + /// and store operations as a result of memset, memcpy, and memmove + /// lowering. If DstAlign is zero that means it's safe to destination + /// alignment can satisfy any constraint. Similarly if SrcAlign is zero it + /// means there isn't a need to check it against alignment requirement, + /// probably because the source does not need to be loaded. If + /// 'NonScalarIntSafe' is true, that means it's safe to return a + /// non-scalar-integer type, e.g. empty string source, constant, or loaded + /// from memory. 'MemcpyStrSrc' indicates whether the memcpy source is + /// constant so it does not need to be loaded. + /// It returns EVT::Other if the type should be determined using generic + /// target-independent logic. + virtual EVT getOptimalMemOpType(uint64_t Size, + unsigned DstAlign, unsigned SrcAlign, + bool NonScalarIntSafe, bool MemcpyStrSrc, + MachineFunction &MF) const { + return MVT::Other; + } + + /// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp + /// to implement llvm.setjmp. + bool usesUnderscoreSetJmp() const { + return UseUnderscoreSetJmp; + } + + /// usesUnderscoreLongJmp - Determine if we should use _longjmp or longjmp + /// to implement llvm.longjmp. + bool usesUnderscoreLongJmp() const { + return UseUnderscoreLongJmp; + } + + /// getStackPointerRegisterToSaveRestore - If a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + unsigned getStackPointerRegisterToSaveRestore() const { + return StackPointerRegisterToSaveRestore; + } + + /// getExceptionAddressRegister - If a physical register, this returns + /// the register that receives the exception address on entry to a landing + /// pad. + unsigned getExceptionAddressRegister() const { + return ExceptionPointerRegister; + } + + /// getExceptionSelectorRegister - If a physical register, this returns + /// the register that receives the exception typeid on entry to a landing + /// pad. + unsigned getExceptionSelectorRegister() const { + return ExceptionSelectorRegister; + } + + /// getJumpBufSize - returns the target's jmp_buf size in bytes (if never + /// set, the default is 200) + unsigned getJumpBufSize() const { + return JumpBufSize; + } + + /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes + /// (if never set, the default is 0) + unsigned getJumpBufAlignment() const { + return JumpBufAlignment; + } + + /// getMinStackArgumentAlignment - return the minimum stack alignment of an + /// argument. + unsigned getMinStackArgumentAlignment() const { + return MinStackArgumentAlignment; + } + + /// getPrefLoopAlignment - return the preferred loop alignment. + /// + unsigned getPrefLoopAlignment() const { + return PrefLoopAlignment; + } + + /// getShouldFoldAtomicFences - return whether the combiner should fold + /// fence MEMBARRIER instructions into the atomic intrinsic instructions. + /// + bool getShouldFoldAtomicFences() const { + return ShouldFoldAtomicFences; + } + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + return false; + } + + /// getPostIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if this node can be + /// combined with a load / store to form a post-indexed load / store. + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + return false; + } + + /// getJumpTableEncoding - Return the entry encoding for a jump table in the + /// current function. The returned value is a member of the + /// MachineJumpTableInfo::JTEntryKind enum. + virtual unsigned getJumpTableEncoding() const; + + virtual const MCExpr * + LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, unsigned uid, + MCContext &Ctx) const { + assert(0 && "Need to implement this hook if target has custom JTIs"); + return 0; + } + + /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC + /// jumptable. + virtual SDValue getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const; + + /// getPICJumpTableRelocBaseExpr - This returns the relocation base for the + /// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an + /// MCExpr. + virtual const MCExpr * + getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI, MCContext &Ctx) const; + + /// isOffsetFoldingLegal - Return true if folding a constant offset + /// with the given GlobalAddress is legal. It is frequently not legal in + /// PIC relocation models. + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *) const = 0; + + /// getStackCookieLocation - Return true if the target stores stack + /// protector cookies at a fixed offset in some non-standard address + /// space, and populates the address space and offset as + /// appropriate. + virtual bool getStackCookieLocation(unsigned &AddressSpace, unsigned &Offset) const { + return false; + } + + /// getMaximalGlobalOffset - Returns the maximal possible offset which can be + /// used for loads / stores from the global. + virtual unsigned getMaximalGlobalOffset() const { + return 0; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Optimization Methods + // + + /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two + /// SDValues for returning information from TargetLowering to its clients + /// that want to combine + struct TargetLoweringOpt { + SelectionDAG &DAG; + bool LegalTys; + bool LegalOps; + SDValue Old; + SDValue New; + + explicit TargetLoweringOpt(SelectionDAG &InDAG, + bool LT, bool LO) : + DAG(InDAG), LegalTys(LT), LegalOps(LO) {} + + bool LegalTypes() const { return LegalTys; } + bool LegalOperations() const { return LegalOps; } + + bool CombineTo(SDValue O, SDValue N) { + Old = O; + New = N; + return true; + } + + /// ShrinkDemandedConstant - Check to see if the specified operand of the + /// specified instruction is a constant integer. If so, check to see if + /// there are any bits set in the constant that are not demanded. If so, + /// shrink the constant and return true. + bool ShrinkDemandedConstant(SDValue Op, const APInt &Demanded); + + /// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the + /// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening + /// cast, but it could be generalized for targets with other types of + /// implicit widening casts. + bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, + DebugLoc dl); + }; + + /// SimplifyDemandedBits - Look at Op. At this point, we know that only the + /// DemandedMask bits of the result of Op are ever used downstream. If we can + /// use this information to simplify Op, create a new simplified DAG node and + /// return true, returning the original and new nodes in Old and New. + /// Otherwise, analyze the expression and return a mask of KnownOne and + /// KnownZero bits for the expression (used to simplify the caller). + /// The KnownZero/One bits may only be accurate for those bits in the + /// DemandedMask. + bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, + APInt &KnownZero, APInt &KnownOne, + TargetLoweringOpt &TLO, unsigned Depth = 0) const; + + /// computeMaskedBitsForTargetNode - Determine which of the bits specified in + /// Mask are known to be either zero or one and return them in the + /// KnownZero/KnownOne bitsets. + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; + + /// ComputeNumSignBitsForTargetNode - This method can be implemented by + /// targets that want to expose additional information about sign bits to the + /// DAG Combiner. + virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, + unsigned Depth = 0) const; + + struct DAGCombinerInfo { + void *DC; // The DAG Combiner object. + bool BeforeLegalize; + bool BeforeLegalizeOps; + bool CalledByLegalizer; + public: + SelectionDAG &DAG; + + DAGCombinerInfo(SelectionDAG &dag, bool bl, bool blo, bool cl, void *dc) + : DC(dc), BeforeLegalize(bl), BeforeLegalizeOps(blo), + CalledByLegalizer(cl), DAG(dag) {} + + bool isBeforeLegalize() const { return BeforeLegalize; } + bool isBeforeLegalizeOps() const { return BeforeLegalizeOps; } + bool isCalledByLegalizer() const { return CalledByLegalizer; } + + void AddToWorklist(SDNode *N); + SDValue CombineTo(SDNode *N, const std::vector &To, + bool AddTo = true); + SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true); + SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo = true); + + void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); + }; + + /// SimplifySetCC - Try to simplify a setcc built with the specified operands + /// and cc. If it is unable to simplify it, return a null SDValue. + SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI, DebugLoc dl) const; + + /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the + /// node is a GlobalAddress + offset. + virtual bool + isGAPlusOffset(SDNode *N, const GlobalValue* &GA, int64_t &Offset) const; + + /// PerformDAGCombine - This method will be invoked for all target nodes and + /// for any target-independent nodes that the target has registered with + /// invoke it for. + /// + /// The semantics are as follows: + /// Return Value: + /// SDValue.Val == 0 - No change was made + /// SDValue.Val == N - N was replaced, is dead, and is already handled. + /// otherwise - N should be replaced by the returned Operand. + /// + /// In addition, methods provided by DAGCombinerInfo may be used to perform + /// more complex transformations. + /// + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + /// isTypeDesirableForOp - Return true if the target has native support for + /// the specified value type and it is 'desirable' to use the type for the + /// given node type. e.g. On x86 i16 is legal, but undesirable since i16 + /// instruction encodings are longer and some i16 instructions are slow. + virtual bool isTypeDesirableForOp(unsigned Opc, EVT VT) const { + // By default, assume all legal types are desirable. + return isTypeLegal(VT); + } + + /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner + /// to transform a floating point op of specified opcode to a equivalent op of + /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. + virtual bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const { + return false; + } + + /// IsDesirableToPromoteOp - This method query the target whether it is + /// beneficial for dag combiner to promote the specified node. If true, it + /// should return the desired promotion type by reference. + virtual bool IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const { + return false; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Configuration Methods - These methods should be invoked by + // the derived class constructor to configure this object for the target. + // + +protected: + /// setBooleanContents - Specify how the target extends the result of a + /// boolean value from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } + + /// setSchedulingPreference - Specify the target scheduling preference. + void setSchedulingPreference(Sched::Preference Pref) { + SchedPreferenceInfo = Pref; + } + + /// setUseUnderscoreSetJmp - Indicate whether this target prefers to + /// use _setjmp to implement llvm.setjmp or the non _ version. + /// Defaults to false. + void setUseUnderscoreSetJmp(bool Val) { + UseUnderscoreSetJmp = Val; + } + + /// setUseUnderscoreLongJmp - Indicate whether this target prefers to + /// use _longjmp to implement llvm.longjmp or the non _ version. + /// Defaults to false. + void setUseUnderscoreLongJmp(bool Val) { + UseUnderscoreLongJmp = Val; + } + + /// setStackPointerRegisterToSaveRestore - If set to a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + void setStackPointerRegisterToSaveRestore(unsigned R) { + StackPointerRegisterToSaveRestore = R; + } + + /// setExceptionPointerRegister - If set to a physical register, this sets + /// the register that receives the exception address on entry to a landing + /// pad. + void setExceptionPointerRegister(unsigned R) { + ExceptionPointerRegister = R; + } + + /// setExceptionSelectorRegister - If set to a physical register, this sets + /// the register that receives the exception typeid on entry to a landing + /// pad. + void setExceptionSelectorRegister(unsigned R) { + ExceptionSelectorRegister = R; + } + + /// SelectIsExpensive - Tells the code generator not to expand operations + /// into sequences that use the select operations if possible. + void setSelectIsExpensive(bool isExpensive = true) { + SelectIsExpensive = isExpensive; + } + + /// JumpIsExpensive - Tells the code generator not to expand sequence of + /// operations into a seperate sequences that increases the amount of + /// flow control. + void setJumpIsExpensive(bool isExpensive = true) { + JumpIsExpensive = isExpensive; + } + + /// setIntDivIsCheap - Tells the code generator that integer divide is + /// expensive, and if possible, should be replaced by an alternate sequence + /// of instructions not containing an integer divide. + void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } + + /// setPow2DivIsCheap - Tells the code generator that it shouldn't generate + /// srl/add/sra for a signed divide by power of two, and let the target handle + /// it. + void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; } + + /// addRegisterClass - Add the specified register class as an available + /// regclass for the specified value type. This indicates the selector can + /// handle values of that class natively. + void addRegisterClass(EVT VT, TargetRegisterClass *RC) { + assert((unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); + AvailableRegClasses.push_back(std::make_pair(VT, RC)); + RegClassForVT[VT.getSimpleVT().SimpleTy] = RC; + } + + /// findRepresentativeClass - Return the largest legal super-reg register class + /// of the register class for the specified type and its associated "cost". + virtual std::pair + findRepresentativeClass(EVT VT) const; + + /// computeRegisterProperties - Once all of the register classes are added, + /// this allows us to compute derived properties we expose. + void computeRegisterProperties(); + + /// setOperationAction - Indicate that the specified operation does not work + /// with the specified type and indicate what to do about it. + void setOperationAction(unsigned Op, MVT VT, + LegalizeAction Action) { + assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); + OpActions[(unsigned)VT.SimpleTy][Op] = (uint8_t)Action; + } + + /// setLoadExtAction - Indicate that the specified load with extension does + /// not work with the specified type and indicate what to do about it. + void setLoadExtAction(unsigned ExtType, MVT VT, + LegalizeAction Action) { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action; + } + + /// setTruncStoreAction - Indicate that the specified truncating store does + /// not work with the specified type and indicate what to do about it. + void setTruncStoreAction(MVT ValVT, MVT MemVT, + LegalizeAction Action) { + assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && + "Table isn't big enough!"); + TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action; + } + + /// setIndexedLoadAction - Indicate that the specified indexed load does or + /// does not work with the specified type and indicate what to do abort + /// it. NOTE: All indexed mode loads are initialized to Expand in + /// TargetLowering.cpp + void setIndexedLoadAction(unsigned IdxMode, MVT VT, + LegalizeAction Action) { + assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); + // Load action are kept in the upper half. + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0; + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action) <<4; + } + + /// setIndexedStoreAction - Indicate that the specified indexed store does or + /// does not work with the specified type and indicate what to do about + /// it. NOTE: All indexed mode stores are initialized to Expand in + /// TargetLowering.cpp + void setIndexedStoreAction(unsigned IdxMode, MVT VT, + LegalizeAction Action) { + assert(VT < MVT::LAST_VALUETYPE && IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); + // Store action are kept in the lower half. + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f; + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action); + } + + /// setCondCodeAction - Indicate that the specified condition code is or isn't + /// supported on the target and indicate what to do about it. + void setCondCodeAction(ISD::CondCode CC, MVT VT, + LegalizeAction Action) { + assert(VT < MVT::LAST_VALUETYPE && + (unsigned)CC < array_lengthof(CondCodeActions) && + "Table isn't big enough!"); + CondCodeActions[(unsigned)CC] &= ~(uint64_t(3UL) << VT.SimpleTy*2); + CondCodeActions[(unsigned)CC] |= (uint64_t)Action << VT.SimpleTy*2; + } + + /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the + /// promotion code defaults to trying a larger integer/fp until it can find + /// one that works. If that default is insufficient, this method can be used + /// by the target to override the default. + void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) { + PromoteToType[std::make_pair(Opc, OrigVT.SimpleTy)] = DestVT.SimpleTy; + } + + /// setTargetDAGCombine - Targets should invoke this method for each target + /// independent node that they want to provide a custom DAG combiner for by + /// implementing the PerformDAGCombine virtual method. + void setTargetDAGCombine(ISD::NodeType NT) { + assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); + TargetDAGCombineArray[NT >> 3] |= 1 << (NT&7); + } + + /// setJumpBufSize - Set the target's required jmp_buf buffer size (in + /// bytes); default is 200 + void setJumpBufSize(unsigned Size) { + JumpBufSize = Size; + } + + /// setJumpBufAlignment - Set the target's required jmp_buf buffer + /// alignment (in bytes); default is 0 + void setJumpBufAlignment(unsigned Align) { + JumpBufAlignment = Align; + } + + /// setPrefLoopAlignment - Set the target's preferred loop alignment. Default + /// alignment is zero, it means the target does not care about loop alignment. + void setPrefLoopAlignment(unsigned Align) { + PrefLoopAlignment = Align; + } + + /// setMinStackArgumentAlignment - Set the minimum stack alignment of an + /// argument. + void setMinStackArgumentAlignment(unsigned Align) { + MinStackArgumentAlignment = Align; + } + + /// setShouldFoldAtomicFences - Set if the target's implementation of the + /// atomic operation intrinsics includes locking. Default is false. + void setShouldFoldAtomicFences(bool fold) { + ShouldFoldAtomicFences = fold; + } + +public: + //===--------------------------------------------------------------------===// + // Lowering methods - These methods must be implemented by targets so that + // the SelectionDAGLowering code knows how to lower these. + // + + /// LowerFormalArguments - This hook must be implemented to lower the + /// incoming (formal) arguments, described by the Ins array, into the + /// specified DAG. The implementation should fill in the InVals array + /// with legal-type argument values, and return the resulting token + /// chain value. + /// + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// LowerCallTo - This function lowers an abstract call to a function into an + /// actual call. This returns a pair of operands. The first element is the + /// return value for the function (if RetTy is not VoidTy). The second + /// element is the outgoing token chain. It calls LowerCall to do the actual + /// lowering. + struct ArgListEntry { + SDValue Node; + const Type* Ty; + bool isSExt : 1; + bool isZExt : 1; + bool isInReg : 1; + bool isSRet : 1; + bool isNest : 1; + bool isByVal : 1; + uint16_t Alignment; + + ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), + isSRet(false), isNest(false), isByVal(false), Alignment(0) { } + }; + typedef std::vector ArgListTy; + std::pair + LowerCallTo(SDValue Chain, const Type *RetTy, bool RetSExt, bool RetZExt, + bool isVarArg, bool isInreg, unsigned NumFixedArgs, + CallingConv::ID CallConv, bool isTailCall, + bool isReturnValueUsed, SDValue Callee, ArgListTy &Args, + SelectionDAG &DAG, DebugLoc dl) const; + + /// LowerCall - This hook must be implemented to lower calls into the + /// the specified DAG. The outgoing arguments to the call are described + /// by the Outs array, and the values to be returned by the call are + /// described by the Ins array. The implementation should fill in the + /// InVals array with legal-type return values from the call, and return + /// the resulting token chain value. + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// HandleByVal - Target-specific cleanup for formal ByVal parameters. + virtual void HandleByVal(CCState *) const {} + + /// CanLowerReturn - This hook should be implemented to check whether the + /// return values described by the Outs array can fit into the return + /// registers. If false is returned, an sret-demotion is performed. + /// + virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + LLVMContext &Context) const + { + // Return true by default to get preexisting behavior. + return true; + } + + /// LowerReturn - This hook must be implemented to lower outgoing + /// return values, described by the Outs array, into the specified + /// DAG. The implementation should return the resulting token chain + /// value. + /// + virtual SDValue + LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + assert(0 && "Not Implemented"); + return SDValue(); // this is here to silence compiler errors + } + + /// isUsedByReturnOnly - Return true if result of the specified node is used + /// by a return node only. This is used to determine whether it is possible + /// to codegen a libcall as tail call at legalization time. + virtual bool isUsedByReturnOnly(SDNode *N) const { + return false; + } + + /// mayBeEmittedAsTailCall - Return true if the target may be able emit the + /// call instruction as a tail call. This is used by optimization passes to + /// determine if it's profitable to duplicate return instructions to enable + /// tailcall optimization. + virtual bool mayBeEmittedAsTailCall(CallInst *CI) const { + return false; + } + + /// LowerOperationWrapper - This callback is invoked by the type legalizer + /// to legalize nodes with an illegal operand type but legal result types. + /// It replaces the LowerOperation callback in the type Legalizer. + /// The reason we can not do away with LowerOperation entirely is that + /// LegalizeDAG isn't yet ready to use this callback. + /// TODO: Consider merging with ReplaceNodeResults. + + /// The target places new result values for the node in Results (their number + /// and types must exactly match those of the original return values of + /// the node), or leaves Results empty, which indicates that the node is not + /// to be custom lowered after all. + /// The default implementation calls LowerOperation. + virtual void LowerOperationWrapper(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG) const; + + /// LowerOperation - This callback is invoked for operations that are + /// unsupported by the target, which are registered to use 'custom' lowering, + /// and whose defined values are all legal. + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation of this aborts. + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + /// ReplaceNodeResults - This callback is invoked when a node result type is + /// illegal for the target, and the operation was registered to use 'custom' + /// lowering for that result type. The target places new result values for + /// the node in Results (their number and types must exactly match those of + /// the original return values of the node), or leaves Results empty, which + /// indicates that the node is not to be custom lowered after all. + /// + /// If the target has no operations that require custom lowering, it need not + /// implement this. The default implementation aborts. + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, + SelectionDAG &DAG) const { + assert(0 && "ReplaceNodeResults not implemented for this target!"); + } + + /// getTargetNodeName() - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// createFastISel - This method returns a target specific FastISel object, + /// or null if the target does not support "fast" ISel. + virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo) const { + return 0; + } + + //===--------------------------------------------------------------------===// + // Inline Asm Support hooks + // + + /// ExpandInlineAsm - This hook allows the target to expand an inline asm + /// call to be explicit llvm code if it wants to. This is useful for + /// turning simple inline asms into LLVM intrinsics, which gives the + /// compiler more information about the behavior of the code. + virtual bool ExpandInlineAsm(CallInst *CI) const { + return false; + } + + enum ConstraintType { + C_Register, // Constraint represents specific register(s). + C_RegisterClass, // Constraint represents any of register(s) in class. + C_Memory, // Memory constraint. + C_Other, // Something else. + C_Unknown // Unsupported constraint. + }; + + enum ConstraintWeight { + // Generic weights. + CW_Invalid = -1, // No match. + CW_Okay = 0, // Acceptable. + CW_Good = 1, // Good weight. + CW_Better = 2, // Better weight. + CW_Best = 3, // Best weight. + + // Well-known weights. + CW_SpecificReg = CW_Okay, // Specific register operands. + CW_Register = CW_Good, // Register operands. + CW_Memory = CW_Better, // Memory operands. + CW_Constant = CW_Best, // Constant operand. + CW_Default = CW_Okay // Default or don't know type. + }; + + /// AsmOperandInfo - This contains information for each constraint that we are + /// lowering. + struct AsmOperandInfo : public InlineAsm::ConstraintInfo { + /// ConstraintCode - This contains the actual string for the code, like "m". + /// TargetLowering picks the 'best' code from ConstraintInfo::Codes that + /// most closely matches the operand. + std::string ConstraintCode; + + /// ConstraintType - Information about the constraint code, e.g. Register, + /// RegisterClass, Memory, Other, Unknown. + TargetLowering::ConstraintType ConstraintType; + + /// CallOperandval - If this is the result output operand or a + /// clobber, this is null, otherwise it is the incoming operand to the + /// CallInst. This gets modified as the asm is processed. + Value *CallOperandVal; + + /// ConstraintVT - The ValueType for the operand value. + EVT ConstraintVT; + + /// isMatchingInputConstraint - Return true of this is an input operand that + /// is a matching constraint like "4". + bool isMatchingInputConstraint() const; + + /// getMatchedOperand - If this is an input matching constraint, this method + /// returns the output operand it matches. + unsigned getMatchedOperand() const; + + /// Copy constructor for copying from an AsmOperandInfo. + AsmOperandInfo(const AsmOperandInfo &info) + : InlineAsm::ConstraintInfo(info), + ConstraintCode(info.ConstraintCode), + ConstraintType(info.ConstraintType), + CallOperandVal(info.CallOperandVal), + ConstraintVT(info.ConstraintVT) { + } + + /// Copy constructor for copying from a ConstraintInfo. + AsmOperandInfo(const InlineAsm::ConstraintInfo &info) + : InlineAsm::ConstraintInfo(info), + ConstraintType(TargetLowering::C_Unknown), + CallOperandVal(0), ConstraintVT(MVT::Other) { + } + }; + + typedef std::vector AsmOperandInfoVector; + + /// ParseConstraints - Split up the constraint string from the inline + /// assembly value into the specific constraints and their prefixes, + /// and also tie in the associated operand values. + /// If this returns an empty vector, and if the constraint string itself + /// isn't empty, there was an error parsing. + virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; + + /// Examine constraint type and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + virtual ConstraintWeight getMultipleConstraintMatchWeight( + AsmOperandInfo &info, int maIndex) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + virtual ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + + /// ComputeConstraintToUse - Determines the constraint code and constraint + /// type to use for the specific AsmOperandInfo, setting + /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand + /// being passed in is available, it can be passed in as Op, otherwise an + /// empty SDValue can be passed. + virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, + SDValue Op, + SelectionDAG *DAG = 0) const; + + /// getConstraintType - Given a constraint, return the type of constraint it + /// is for this target. + virtual ConstraintType getConstraintType(const std::string &Constraint) const; + + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), + /// return a list of registers that can be used to satisfy the constraint. + /// This should only be used for C_RegisterClass constraints. + virtual std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. + /// {edx}), return the register number and the register class for the + /// register. + /// + /// Given a register class constraint, like 'r', if this corresponds directly + /// to an LLVM register class, return a register of 0 and the register class + /// pointer. + /// + /// This should only be used for C_Register constraints. On error, + /// this returns a register number of 0 and a null register class pointer.. + virtual std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// LowerXConstraint - try to replace an X constraint, which matches anything, + /// with another that has more specific requirements based on the type of the + /// corresponding operand. This returns null if there is no replacement to + /// make. + virtual const char *LowerXConstraint(EVT ConstraintVT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. + virtual void LowerAsmOperandForConstraint(SDValue Op, char ConstraintLetter, + std::vector &Ops, + SelectionDAG &DAG) const; + + //===--------------------------------------------------------------------===// + // Instruction Emitting Hooks + // + + // EmitInstrWithCustomInserter - This method should be implemented by targets + // that mark instructions with the 'usesCustomInserter' flag. These + // instructions are special in various ways, which require special support to + // insert. The specified MachineInstr is created but not inserted into any + // basic blocks, and this method is called to expand it into a sequence of + // instructions, potentially also creating new basic blocks and control flow. + virtual MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; + + //===--------------------------------------------------------------------===// + // Addressing mode description hooks (used by LSR etc). + // + + /// AddrMode - This represents an addressing mode of: + /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + /// If BaseGV is null, there is no BaseGV. + /// If BaseOffs is zero, there is no base offset. + /// If HasBaseReg is false, there is no base register. + /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with + /// no scale. + /// + struct AddrMode { + GlobalValue *BaseGV; + int64_t BaseOffs; + bool HasBaseReg; + int64_t Scale; + AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {} + }; + + /// isLegalAddressingMode - Return true if the addressing mode represented by + /// AM is legal for this target, for a load/store of the specified type. + /// The type may be VoidTy, in which case only return true if the addressing + /// mode is legal for a load/store of any legal type. + /// TODO: Handle pre/postinc as well. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; + + /// isTruncateFree - Return true if it's free to truncate a value of + /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in + /// register EAX to i16 by referencing its sub-register AX. + virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const { + return false; + } + + virtual bool isTruncateFree(EVT VT1, EVT VT2) const { + return false; + } + + /// isZExtFree - Return true if any actual instruction that defines a + /// value of type Ty1 implicitly zero-extends the value to Ty2 in the result + /// register. This does not necessarily include registers defined in + /// unknown ways, such as incoming arguments, or copies from unknown + /// virtual registers. Also, if isTruncateFree(Ty2, Ty1) is true, this + /// does not necessarily apply to truncate instructions. e.g. on x86-64, + /// all instructions that define 32-bit values implicit zero-extend the + /// result out to 64 bits. + virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const { + return false; + } + + virtual bool isZExtFree(EVT VT1, EVT VT2) const { + return false; + } + + /// isNarrowingProfitable - Return true if it's profitable to narrow + /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow + /// from i32 to i8 but not from i32 to i16. + virtual bool isNarrowingProfitable(EVT VT1, EVT VT2) const { + return false; + } + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can compare + /// a register against the immediate without having to materialize the + /// immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const { + return true; + } + + //===--------------------------------------------------------------------===// + // Div utility functions + // + SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const; + SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const; + + + //===--------------------------------------------------------------------===// + // Runtime Library hooks + // + + /// setLibcallName - Rename the default libcall routine name for the specified + /// libcall. + void setLibcallName(RTLIB::Libcall Call, const char *Name) { + LibcallRoutineNames[Call] = Name; + } + + /// getLibcallName - Get the libcall routine name for the specified libcall. + /// + const char *getLibcallName(RTLIB::Libcall Call) const { + return LibcallRoutineNames[Call]; + } + + /// setCmpLibcallCC - Override the default CondCode to be used to test the + /// result of the comparison libcall against zero. + void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { + CmpLibcallCCs[Call] = CC; + } + + /// getCmpLibcallCC - Get the CondCode that's to be used to test the result of + /// the comparison libcall against zero. + ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { + return CmpLibcallCCs[Call]; + } + + /// setLibcallCallingConv - Set the CallingConv that should be used for the + /// specified libcall. + void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { + LibcallCallingConvs[Call] = CC; + } + + /// getLibcallCallingConv - Get the CallingConv that should be used for the + /// specified libcall. + CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { + return LibcallCallingConvs[Call]; + } + +private: + const TargetMachine &TM; + const TargetData *TD; + const TargetLoweringObjectFile &TLOF; + + /// PointerTy - The type to use for pointers, usually i32 or i64. + /// + MVT PointerTy; + + /// IsLittleEndian - True if this is a little endian target. + /// + bool IsLittleEndian; + + /// SelectIsExpensive - Tells the code generator not to expand operations + /// into sequences that use the select operations if possible. + bool SelectIsExpensive; + + /// IntDivIsCheap - Tells the code generator not to expand integer divides by + /// constants into a sequence of muls, adds, and shifts. This is a hack until + /// a real cost model is in place. If we ever optimize for size, this will be + /// set to true unconditionally. + bool IntDivIsCheap; + + /// Pow2DivIsCheap - Tells the code generator that it shouldn't generate + /// srl/add/sra for a signed divide by power of two, and let the target handle + /// it. + bool Pow2DivIsCheap; + + /// JumpIsExpensive - Tells the code generator that it shouldn't generate + /// extra flow control instructions and should attempt to combine flow + /// control instructions via predication. + bool JumpIsExpensive; + + /// UseUnderscoreSetJmp - This target prefers to use _setjmp to implement + /// llvm.setjmp. Defaults to false. + bool UseUnderscoreSetJmp; + + /// UseUnderscoreLongJmp - This target prefers to use _longjmp to implement + /// llvm.longjmp. Defaults to false. + bool UseUnderscoreLongJmp; + + /// BooleanContents - Information about the contents of the high-bits in + /// boolean values held in a type wider than i1. See getBooleanContents. + BooleanContent BooleanContents; + + /// SchedPreferenceInfo - The target scheduling preference: shortest possible + /// total cycles or lowest register usage. + Sched::Preference SchedPreferenceInfo; + + /// JumpBufSize - The size, in bytes, of the target's jmp_buf buffers + unsigned JumpBufSize; + + /// JumpBufAlignment - The alignment, in bytes, of the target's jmp_buf + /// buffers + unsigned JumpBufAlignment; + + /// MinStackArgumentAlignment - The minimum alignment that any argument + /// on the stack needs to have. + /// + unsigned MinStackArgumentAlignment; + + /// PrefLoopAlignment - The perferred loop alignment. + /// + unsigned PrefLoopAlignment; + + /// ShouldFoldAtomicFences - Whether fencing MEMBARRIER instructions should + /// be folded into the enclosed atomic intrinsic instruction by the + /// combiner. + bool ShouldFoldAtomicFences; + + /// StackPointerRegisterToSaveRestore - If set to a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + unsigned StackPointerRegisterToSaveRestore; + + /// ExceptionPointerRegister - If set to a physical register, this specifies + /// the register that receives the exception address on entry to a landing + /// pad. + unsigned ExceptionPointerRegister; + + /// ExceptionSelectorRegister - If set to a physical register, this specifies + /// the register that receives the exception typeid on entry to a landing + /// pad. + unsigned ExceptionSelectorRegister; + + /// RegClassForVT - This indicates the default register class to use for + /// each ValueType the target supports natively. + TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; + unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; + EVT RegisterTypeForVT[MVT::LAST_VALUETYPE]; + + /// RepRegClassForVT - This indicates the "representative" register class to + /// use for each ValueType the target supports natively. This information is + /// used by the scheduler to track register pressure. By default, the + /// representative register class is the largest legal super-reg register + /// class of the register class of the specified type. e.g. On x86, i8, i16, + /// and i32's representative class would be GR32. + const TargetRegisterClass *RepRegClassForVT[MVT::LAST_VALUETYPE]; + + /// RepRegClassCostForVT - This indicates the "cost" of the "representative" + /// register class for each ValueType. The cost is used by the scheduler to + /// approximate register pressure. + uint8_t RepRegClassCostForVT[MVT::LAST_VALUETYPE]; + + /// TransformToType - For any value types we are promoting or expanding, this + /// contains the value type that we are changing to. For Expanded types, this + /// contains one step of the expand (e.g. i64 -> i32), even if there are + /// multiple steps required (e.g. i64 -> i16). For types natively supported + /// by the system, this holds the same type (e.g. i32 -> i32). + EVT TransformToType[MVT::LAST_VALUETYPE]; + + /// OpActions - For each operation and each value type, keep a LegalizeAction + /// that indicates how instruction selection should deal with the operation. + /// Most operations are Legal (aka, supported natively by the target), but + /// operations that are not should be described. Note that operations on + /// non-legal value types are not described here. + uint8_t OpActions[MVT::LAST_VALUETYPE][ISD::BUILTIN_OP_END]; + + /// LoadExtActions - For each load extension type and each value type, + /// keep a LegalizeAction that indicates how instruction selection should deal + /// with a load of a specific value type and extension type. + uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE]; + + /// TruncStoreActions - For each value type pair keep a LegalizeAction that + /// indicates whether a truncating store of a specific value type and + /// truncating type is legal. + uint8_t TruncStoreActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]; + + /// IndexedModeActions - For each indexed mode and each value type, + /// keep a pair of LegalizeAction that indicates how instruction + /// selection should deal with the load / store. The first dimension is the + /// value_type for the reference. The second dimension represents the various + /// modes for load store. + uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][ISD::LAST_INDEXED_MODE]; + + /// CondCodeActions - For each condition code (ISD::CondCode) keep a + /// LegalizeAction that indicates how instruction selection should + /// deal with the condition code. + uint64_t CondCodeActions[ISD::SETCC_INVALID]; + + ValueTypeActionImpl ValueTypeActions; + + std::vector > AvailableRegClasses; + + /// TargetDAGCombineArray - Targets can specify ISD nodes that they would + /// like PerformDAGCombine callbacks for by calling setTargetDAGCombine(), + /// which sets a bit in this array. + unsigned char + TargetDAGCombineArray[(ISD::BUILTIN_OP_END+CHAR_BIT-1)/CHAR_BIT]; + + /// PromoteToType - For operations that must be promoted to a specific type, + /// this holds the destination type. This map should be sparse, so don't hold + /// it as an array. + /// + /// Targets add entries to this map with AddPromotedToType(..), clients access + /// this with getTypeToPromoteTo(..). + std::map, MVT::SimpleValueType> + PromoteToType; + + /// LibcallRoutineNames - Stores the name each libcall. + /// + const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL]; + + /// CmpLibcallCCs - The ISD::CondCode that should be used to test the result + /// of each of the comparison libcall against zero. + ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; + + /// LibcallCallingConvs - Stores the CallingConv that should be used for each + /// libcall. + CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; + +protected: + /// When lowering \@llvm.memset this field specifies the maximum number of + /// store operations that may be substituted for the call to memset. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memset will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, storing 9 bytes on a 32-bit machine + /// with 16-bit alignment would result in four 2-byte stores and one 1-byte + /// store. This only applies to setting a constant array of a constant size. + /// @brief Specify maximum number of store instructions per memset call. + unsigned maxStoresPerMemset; + + /// Maximum number of stores operations that may be substituted for the call + /// to memset, used for functions with OptSize attribute. + unsigned maxStoresPerMemsetOptSize; + + /// When lowering \@llvm.memcpy this field specifies the maximum number of + /// store operations that may be substituted for a call to memcpy. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memcpy will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, storing 7 bytes on a 32-bit machine + /// with 32-bit alignment would result in one 4-byte store, a one 2-byte store + /// and one 1-byte store. This only applies to copying a constant array of + /// constant size. + /// @brief Specify maximum bytes of store instructions per memcpy call. + unsigned maxStoresPerMemcpy; + + /// Maximum number of store operations that may be substituted for a call + /// to memcpy, used for functions with OptSize attribute. + unsigned maxStoresPerMemcpyOptSize; + + /// When lowering \@llvm.memmove this field specifies the maximum number of + /// store instructions that may be substituted for a call to memmove. Targets + /// must set this value based on the cost threshold for that target. Targets + /// should assume that the memmove will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, moving 9 bytes on a 32-bit machine + /// with 8-bit alignment would result in nine 1-byte stores. This only + /// applies to copying a constant array of constant size. + /// @brief Specify maximum bytes of store instructions per memmove call. + unsigned maxStoresPerMemmove; + + /// Maximum number of store instructions that may be substituted for a call + /// to memmove, used for functions with OpSize attribute. + unsigned maxStoresPerMemmoveOptSize; + + /// This field specifies whether the target can benefit from code placement + /// optimization. + bool benefitFromCodePlacementOpt; + +private: + /// isLegalRC - Return true if the value types that can be represented by the + /// specified register class are all legal. + bool isLegalRC(const TargetRegisterClass *RC) const; + + /// hasLegalSuperRegRegClasses - Return true if the specified register class + /// has one or more super-reg register classes that are legal. + bool hasLegalSuperRegRegClasses(const TargetRegisterClass *RC) const; +}; + +/// GetReturnInfo - Given an LLVM IR type and return type attributes, +/// compute the return value EVTs and flags, and optionally also +/// the offsets, if the return value is being lowered to memory. +void GetReturnInfo(const Type* ReturnType, Attributes attr, + SmallVectorImpl &Outs, + const TargetLowering &TLI, + SmallVectorImpl *Offsets = 0); + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetLoweringObjectFile.h b/final/include/llvm/Target/TargetLoweringObjectFile.h new file mode 100644 index 00000000000..34bf27132de --- /dev/null +++ b/final/include/llvm/Target/TargetLoweringObjectFile.h @@ -0,0 +1,240 @@ +//===-- llvm/Target/TargetLoweringObjectFile.h - Object 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 implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H +#define LLVM_TARGET_TARGETLOWERINGOBJECTFILE_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/SectionKind.h" + +namespace llvm { + class MachineModuleInfo; + class Mangler; + class MCAsmInfo; + class MCContext; + class MCExpr; + class MCSection; + class MCSectionMachO; + class MCSymbol; + class MCStreamer; + class GlobalValue; + class TargetMachine; + +class TargetLoweringObjectFile { + MCContext *Ctx; + + TargetLoweringObjectFile(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT + void operator=(const TargetLoweringObjectFile&); // DO NOT IMPLEMENT +protected: + + TargetLoweringObjectFile(); + + /// TextSection - Section directive for standard text. + /// + const MCSection *TextSection; + + /// DataSection - Section directive for standard data. + /// + const MCSection *DataSection; + + /// BSSSection - Section that is default initialized to zero. + const MCSection *BSSSection; + + /// ReadOnlySection - Section that is readonly and can contain arbitrary + /// initialized data. Targets are not required to have a readonly section. + /// If they don't, various bits of code will fall back to using the data + /// section for constants. + const MCSection *ReadOnlySection; + + /// StaticCtorSection - This section contains the static constructor pointer + /// list. + const MCSection *StaticCtorSection; + + /// StaticDtorSection - This section contains the static destructor pointer + /// list. + const MCSection *StaticDtorSection; + + /// LSDASection - If exception handling is supported by the target, this is + /// the section the Language Specific Data Area information is emitted to. + const MCSection *LSDASection; + + // Dwarf sections for debug info. If a target supports debug info, these must + // be set. + const MCSection *DwarfAbbrevSection; + const MCSection *DwarfInfoSection; + const MCSection *DwarfLineSection; + const MCSection *DwarfFrameSection; + const MCSection *DwarfPubNamesSection; + const MCSection *DwarfPubTypesSection; + const MCSection *DwarfDebugInlineSection; + const MCSection *DwarfStrSection; + const MCSection *DwarfLocSection; + const MCSection *DwarfARangesSection; + const MCSection *DwarfRangesSection; + const MCSection *DwarfMacroInfoSection; + + // Extra TLS Variable Data section. If the target needs to put additional + // information for a TLS variable, it'll go here. + const MCSection *TLSExtraDataSection; + + /// CommDirectiveSupportsAlignment - True if .comm supports alignment. This + /// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't + /// support alignment on comm. + bool CommDirectiveSupportsAlignment; + + /// SupportsWeakEmptyEHFrame - True if target object file supports a + /// weak_definition of constant 0 for an omitted EH frame. + bool SupportsWeakOmittedEHFrame; + + /// IsFunctionEHSymbolGlobal - This flag is set to true if the ".eh" symbol + /// for a function should be marked .globl. + bool IsFunctionEHSymbolGlobal; + + /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the + /// "EH_frame" symbol for EH information should be an assembler temporary (aka + /// private linkage, aka an L or .L label) or false if it should be a normal + /// non-.globl label. This defaults to true. + bool IsFunctionEHFrameSymbolPrivate; +public: + + MCContext &getContext() const { return *Ctx; } + + virtual ~TargetLoweringObjectFile(); + + /// Initialize - this method must be called before any actual lowering is + /// done. This specifies the current context for codegen, and gives the + /// lowering implementations a chance to set up their default sections. + virtual void Initialize(MCContext &ctx, const TargetMachine &TM) { + Ctx = &ctx; + } + + bool isFunctionEHSymbolGlobal() const { + return IsFunctionEHSymbolGlobal; + } + bool isFunctionEHFrameSymbolPrivate() const { + return IsFunctionEHFrameSymbolPrivate; + } + bool getSupportsWeakOmittedEHFrame() const { + return SupportsWeakOmittedEHFrame; + } + + bool getCommDirectiveSupportsAlignment() const { + return CommDirectiveSupportsAlignment; + } + + const MCSection *getTextSection() const { return TextSection; } + const MCSection *getDataSection() const { return DataSection; } + const MCSection *getBSSSection() const { return BSSSection; } + const MCSection *getStaticCtorSection() const { return StaticCtorSection; } + const MCSection *getStaticDtorSection() const { return StaticDtorSection; } + const MCSection *getLSDASection() const { return LSDASection; } + virtual const MCSection *getEHFrameSection() const = 0; + const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + const MCSection *getDwarfLineSection() const { return DwarfLineSection; } + const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} + const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} + const MCSection *getDwarfDebugInlineSection() const { + return DwarfDebugInlineSection; + } + const MCSection *getDwarfStrSection() const { return DwarfStrSection; } + const MCSection *getDwarfLocSection() const { return DwarfLocSection; } + const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} + const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + const MCSection *getDwarfMacroInfoSection() const { + return DwarfMacroInfoSection; + } + const MCSection *getTLSExtraDataSection() const { + return TLSExtraDataSection; + } + + /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively + /// decide not to emit the UsedDirective for some symbols in llvm.used. + /// FIXME: REMOVE this (rdar://7071300) + virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, + Mangler *) const { + return GV != 0; + } + + /// getSectionForConstant - Given a constant with the SectionKind, return a + /// section that it should be placed in. + virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + + /// getKindForGlobal - Classify the specified global variable into a set of + /// target independent categories embodied in SectionKind. + static SectionKind getKindForGlobal(const GlobalValue *GV, + const TargetMachine &TM); + + /// SectionForGlobal - This method computes the appropriate section to emit + /// the specified global variable or function definition. This should not + /// be passed external (or available externally) globals. + const MCSection *SectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler *Mang, + const TargetMachine &TM) const; + + /// SectionForGlobal - This method computes the appropriate section to emit + /// the specified global variable or function definition. This should not + /// be passed external (or available externally) globals. + const MCSection *SectionForGlobal(const GlobalValue *GV, + Mangler *Mang, + const TargetMachine &TM) const { + return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); + } + + + + /// getExplicitSectionGlobal - Targets should implement this method to assign + /// a section to globals with an explicit section specfied. The + /// implementation of this method can assume that GV->hasSection() is true. + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const = 0; + + /// getSpecialCasedSectionGlobals - Allow the target to completely override + /// section assignment of a global. + virtual const MCSection * + getSpecialCasedSectionGlobals(const GlobalValue *GV, Mangler *Mang, + SectionKind Kind) const { + return 0; + } + + /// getExprForDwarfGlobalReference - Return an MCExpr to use for a reference + /// to the specified global variable from exception handling information. + /// + virtual const MCExpr * + getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; + + /// + const MCExpr * + getExprForDwarfReference(const MCSymbol *Sym, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const; + + virtual unsigned getPersonalityEncoding() const; + virtual unsigned getLSDAEncoding() const; + virtual unsigned getFDEEncoding() const; + virtual unsigned getTTypeEncoding() const; + +protected: + virtual const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; +}; + +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Target/TargetMachine.h b/final/include/llvm/Target/TargetMachine.h new file mode 100644 index 00000000000..030bf5b89f7 --- /dev/null +++ b/final/include/llvm/Target/TargetMachine.h @@ -0,0 +1,390 @@ +//===-- llvm/Target/TargetMachine.h - Target Information --------*- 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 TargetMachine and LLVMTargetMachine classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHINE_H +#define LLVM_TARGET_TARGETMACHINE_H + +#include "llvm/Target/TargetInstrItineraries.h" +#include +#include + +namespace llvm { + +class Target; +class MCAsmInfo; +class TargetData; +class TargetSubtarget; +class TargetInstrInfo; +class TargetIntrinsicInfo; +class TargetJITInfo; +class TargetLowering; +class TargetSelectionDAGInfo; +class TargetFrameLowering; +class JITCodeEmitter; +class MCContext; +class TargetRegisterInfo; +class PassManagerBase; +class PassManager; +class Pass; +class TargetELFWriterInfo; +class formatted_raw_ostream; + +// Relocation model types. +namespace Reloc { + enum Model { + Default, + Static, + PIC_, // Cannot be named PIC due to collision with -DPIC + DynamicNoPIC + }; +} + +// Code model types. +namespace CodeModel { + enum Model { + Default, + Small, + Kernel, + Medium, + Large + }; +} + +// Code generation optimization level. +namespace CodeGenOpt { + enum Level { + None, // -O0 + Less, // -O1 + Default, // -O2, -Os + Aggressive // -O3 + }; +} + +namespace Sched { + enum Preference { + None, // No preference + Latency, // Scheduling for shortest total latency. + RegPressure, // Scheduling for lowest register pressure. + Hybrid, // Scheduling for both latency and register pressure. + ILP // Scheduling for ILP in low register pressure mode. + }; +} + +//===----------------------------------------------------------------------===// +/// +/// TargetMachine - Primary interface to the complete machine description for +/// the target machine. All target-specific information should be accessible +/// through this interface. +/// +class TargetMachine { + TargetMachine(const TargetMachine &); // DO NOT IMPLEMENT + void operator=(const TargetMachine &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetMachine(const Target &); + + /// getSubtargetImpl - virtual method implemented by subclasses that returns + /// a reference to that target's TargetSubtarget-derived member variable. + virtual const TargetSubtarget *getSubtargetImpl() const { return 0; } + + /// TheTarget - The Target that this machine was created for. + const Target &TheTarget; + + /// AsmInfo - Contains target specific asm information. + /// + const MCAsmInfo *AsmInfo; + + unsigned MCRelaxAll : 1; + unsigned MCNoExecStack : 1; + unsigned MCUseLoc : 1; + +public: + virtual ~TargetMachine(); + + const Target &getTarget() const { return TheTarget; } + + // Interfaces to the major aspects of target machine information: + // -- Instruction opcode and operand information + // -- Pipelines and scheduling information + // -- Stack frame information + // -- Selection DAG lowering information + // + virtual const TargetInstrInfo *getInstrInfo() const { return 0; } + virtual const TargetFrameLowering *getFrameLowering() const { return 0; } + virtual const TargetLowering *getTargetLowering() const { return 0; } + virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; } + virtual const TargetData *getTargetData() const { return 0; } + + /// getMCAsmInfo - Return target specific asm information. + /// + const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } + + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtarget. In debug builds, it verifies that the object being + /// returned is of the correct type. + template const STC &getSubtarget() const { + return *static_cast(getSubtargetImpl()); + } + + /// getRegisterInfo - If register information is available, return it. If + /// not, return null. This is kept separate from RegInfo until RegInfo has + /// details of graph coloring register allocation removed from it. + /// + virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; } + + /// getIntrinsicInfo - If intrinsic information is available, return it. If + /// not, return null. + /// + virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return 0; } + + /// getJITInfo - If this target supports a JIT, return information for it, + /// otherwise return null. + /// + virtual TargetJITInfo *getJITInfo() { return 0; } + + /// getInstrItineraryData - Returns instruction itinerary data for the target + /// or specific subtarget. + /// + virtual const InstrItineraryData *getInstrItineraryData() const { + return 0; + } + + /// getELFWriterInfo - If this target supports an ELF writer, return + /// information for it, otherwise return null. + /// + virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } + + /// hasMCRelaxAll - Check whether all machine code instructions should be + /// relaxed. + bool hasMCRelaxAll() const { return MCRelaxAll; } + + /// setMCRelaxAll - Set whether all machine code instructions should be + /// relaxed. + void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + + /// hasMCNoExecStack - Check whether an executable stack is not needed. + bool hasMCNoExecStack() const { return MCNoExecStack; } + + /// setMCNoExecStack - Set whether an executabel stack is not needed. + void setMCNoExecStack(bool Value) { MCNoExecStack = Value; } + + /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. + bool hasMCUseLoc() const { return MCUseLoc; } + + /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. + void setMCUseLoc(bool Value) { MCUseLoc = Value; } + + /// getRelocationModel - Returns the code generation relocation model. The + /// choices are static, PIC, and dynamic-no-pic, and target default. + static Reloc::Model getRelocationModel(); + + /// setRelocationModel - Sets the code generation relocation model. + /// + static void setRelocationModel(Reloc::Model Model); + + /// getCodeModel - Returns the code model. The choices are small, kernel, + /// medium, large, and target default. + static CodeModel::Model getCodeModel(); + + /// setCodeModel - Sets the code model. + /// + static void setCodeModel(CodeModel::Model Model); + + /// getAsmVerbosityDefault - Returns the default value of asm verbosity. + /// + static bool getAsmVerbosityDefault(); + + /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default + /// is false. + static void setAsmVerbosityDefault(bool); + + /// getDataSections - Return true if data objects should be emitted into their + /// own section, corresponds to -fdata-sections. + static bool getDataSections(); + + /// getFunctionSections - Return true if functions should be emitted into + /// their own section, corresponding to -ffunction-sections. + static bool getFunctionSections(); + + /// setDataSections - Set if the data are emit into separate sections. + static void setDataSections(bool); + + /// setFunctionSections - Set if the functions are emit into separate + /// sections. + static void setFunctionSections(bool); + + /// CodeGenFileType - These enums are meant to be passed into + /// addPassesToEmitFile to indicate what type of file to emit, and returned by + /// it to indicate what type of file could actually be made. + enum CodeGenFileType { + CGFT_AssemblyFile, + CGFT_ObjectFile, + CGFT_Null // Do not emit any output. + }; + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual bool getEnableTailMergeDefault() const { return true; } + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. This method should return true if emission of this file type + /// is not supported, or false on success. + virtual bool addPassesToEmitFile(PassManagerBase &, + formatted_raw_ostream &, + CodeGenFileType, + CodeGenOpt::Level, + bool = true) { + return true; + } + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a JITCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &, + JITCodeEmitter &, + CodeGenOpt::Level, + bool = true) { + return true; + } + + /// addPassesToEmitMC - Add passes to the specified pass manager to get + /// machine code emitted with the MCJIT. This method returns true if machine + /// code is not supported. It fills the MCContext Ctx pointer which can be + /// used to build custom MCStreamer. + /// + virtual bool addPassesToEmitMC(PassManagerBase &, + MCContext *&, + CodeGenOpt::Level, + bool = true) { + return true; + } +}; + +/// LLVMTargetMachine - This class describes a target machine that is +/// implemented with the LLVM target-independent code generator. +/// +class LLVMTargetMachine : public TargetMachine { + std::string TargetTriple; + +protected: // Can only create subclasses. + LLVMTargetMachine(const Target &T, const std::string &TargetTriple); + +private: + /// addCommonCodeGenPasses - Add standard LLVM codegen passes used for + /// both emitting to assembly files or machine code output. + /// + bool addCommonCodeGenPasses(PassManagerBase &, CodeGenOpt::Level, + bool DisableVerify, MCContext *&OutCtx); + + virtual void setCodeModelForJIT(); + virtual void setCodeModelForStatic(); + +public: + + const std::string &getTargetTriple() const { return TargetTriple; } + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. If OptLevel is None, the code generator should emit code as + /// fast as possible, though the generated code may be less efficient. + virtual bool addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level, + bool DisableVerify = true); + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a JITCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(PassManagerBase &PM, + JITCodeEmitter &MCE, + CodeGenOpt::Level, + bool DisableVerify = true); + + /// addPassesToEmitMC - Add passes to the specified pass manager to get + /// machine code emitted with the MCJIT. This method returns true if machine + /// code is not supported. It fills the MCContext Ctx pointer which can be + /// used to build custom MCStreamer. + /// + virtual bool addPassesToEmitMC(PassManagerBase &PM, + MCContext *&Ctx, + CodeGenOpt::Level OptLevel, + bool DisableVerify = true); + + /// Target-Independent Code Generator Pass Configuration Options. + + /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM + /// passes (which are run just before instruction selector). + virtual bool addPreISel(PassManagerBase &, CodeGenOpt::Level) { + return true; + } + + /// addInstSelector - This method should install an instruction selector pass, + /// which converts from LLVM code to machine instructions. + virtual bool addInstSelector(PassManagerBase &, CodeGenOpt::Level) { + return true; + } + + /// addPreRegAlloc - This method may be implemented by targets that want to + /// run passes immediately before register allocation. This should return + /// true if -print-machineinstrs should print after these passes. + virtual bool addPreRegAlloc(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPostRegAlloc - This method may be implemented by targets that want + /// to run passes after register allocation but before prolog-epilog + /// insertion. This should return true if -print-machineinstrs should print + /// after these passes. + virtual bool addPostRegAlloc(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPreSched2 - This method may be implemented by targets that want to + /// run passes after prolog-epilog insertion and before the second instruction + /// scheduling pass. This should return true if -print-machineinstrs should + /// print after these passes. + virtual bool addPreSched2(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + /// addPreEmitPass - This pass may be implemented by targets that want to run + /// passes immediately before machine code is emitted. This should return + /// true if -print-machineinstrs should print out the code after the passes. + virtual bool addPreEmitPass(PassManagerBase &, CodeGenOpt::Level) { + return false; + } + + + /// addCodeEmitter - This pass should be overridden by the target to add a + /// code emitter, if supported. If this is not supported, 'true' should be + /// returned. + virtual bool addCodeEmitter(PassManagerBase &, CodeGenOpt::Level, + JITCodeEmitter &) { + return true; + } + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual bool getEnableTailMergeDefault() const { return true; } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetOpcodes.h b/final/include/llvm/Target/TargetOpcodes.h new file mode 100644 index 00000000000..01fba6628ef --- /dev/null +++ b/final/include/llvm/Target/TargetOpcodes.h @@ -0,0 +1,86 @@ +//===-- llvm/Target/TargetOpcodes.h - Target Indep Opcodes ------*- 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 target independent instruction opcodes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETOPCODES_H +#define LLVM_TARGET_TARGETOPCODES_H + +namespace llvm { + +/// Invariant opcodes: All instruction sets have these as their low opcodes. +/// +/// Every instruction defined here must also appear in Target.td and the order +/// must be the same as in CodeGenTarget.cpp. +/// +namespace TargetOpcode { + enum { + PHI = 0, + INLINEASM = 1, + PROLOG_LABEL = 2, + EH_LABEL = 3, + GC_LABEL = 4, + + /// KILL - This instruction is a noop that is used only to adjust the + /// liveness of registers. This can be useful when dealing with + /// sub-registers. + KILL = 5, + + /// EXTRACT_SUBREG - This instruction takes two operands: a register + /// that has subregisters, and a subregister index. It returns the + /// extracted subregister value. This is commonly used to implement + /// truncation operations on target architectures which support it. + EXTRACT_SUBREG = 6, + + /// INSERT_SUBREG - This instruction takes three operands: a register that + /// has subregisters, a register providing an insert value, and a + /// subregister index. It returns the value of the first register with the + /// value of the second register inserted. The first register is often + /// defined by an IMPLICIT_DEF, because it is commonly used to implement + /// anyext operations on target architectures which support it. + INSERT_SUBREG = 7, + + /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef. + IMPLICIT_DEF = 8, + + /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that + /// the first operand is an immediate integer constant. This constant is + /// often zero, because it is commonly used to assert that the instruction + /// defining the register implicitly clears the high bits. + SUBREG_TO_REG = 9, + + /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain + /// register-to-register copy into a specific register class. This is only + /// used between instruction selection and MachineInstr creation, before + /// virtual registers have been created for all the instructions, and it's + /// only needed in cases where the register classes implied by the + /// instructions are insufficient. It is emitted as a COPY MachineInstr. + COPY_TO_REGCLASS = 10, + + /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic + DBG_VALUE = 11, + + /// REG_SEQUENCE - This variadic instruction is used to form a register that + /// represent a consecutive sequence of sub-registers. It's used as register + /// coalescing / allocation aid and must be eliminated before code emission. + /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5 + /// After register coalescing references of v1024 should be replace with + /// v1027:3, v1025 with v1027:4, etc. + REG_SEQUENCE = 12, + + /// COPY - Target-independent register copy. This instruction can also be + /// used to copy between subregisters of virtual registers. + COPY = 13 + }; +} // end namespace TargetOpcode +} // end namespace llvm + +#endif diff --git a/final/include/llvm/Target/TargetOptions.h b/final/include/llvm/Target/TargetOptions.h new file mode 100644 index 00000000000..97ceffdaecb --- /dev/null +++ b/final/include/llvm/Target/TargetOptions.h @@ -0,0 +1,162 @@ +//===-- llvm/Target/TargetOptions.h - Target Options ------------*- 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 command line option flags that are shared across various +// targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETOPTIONS_H +#define LLVM_TARGET_TARGETOPTIONS_H + +namespace llvm { + class MachineFunction; + + // Possible float ABI settings. Used with FloatABIType in TargetOptions.h. + namespace FloatABI { + enum ABIType { + Default, // Target-specific (either soft of hard depending on triple, etc). + Soft, // Soft float. + Hard // Hard float. + }; + } + + /// PrintMachineCode - This flag is enabled when the -print-machineinstrs + /// option is specified on the command line, and should enable debugging + /// output from the code generator. + extern bool PrintMachineCode; + + /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is + /// specified on the command line. If the target supports the frame pointer + /// elimination optimization, this option should disable it. + extern bool NoFramePointerElim; + + /// NoFramePointerElimNonLeaf - This flag is enabled when the + /// -disable-non-leaf-fp-elim is specified on the command line. If the target + /// supports the frame pointer elimination optimization, this option should + /// disable it for non-leaf functions. + extern bool NoFramePointerElimNonLeaf; + + /// DisableFramePointerElim - This returns true if frame pointer elimination + /// optimization should be disabled for the given machine function. + extern bool DisableFramePointerElim(const MachineFunction &MF); + + /// LessPreciseFPMAD - This flag is enabled when the + /// -enable-fp-mad is specified on the command line. When this flag is off + /// (the default), the code generator is not allowed to generate mad + /// (multiply add) if the result is "less precise" than doing those operations + /// individually. + extern bool LessPreciseFPMADOption; + extern bool LessPreciseFPMAD(); + + /// NoExcessFPPrecision - This flag is enabled when the + /// -disable-excess-fp-precision flag is specified on the command line. When + /// this flag is off (the default), the code generator is allowed to produce + /// results that are "more precise" than IEEE allows. This includes use of + /// FMA-like operations and use of the X86 FP registers without rounding all + /// over the place. + extern bool NoExcessFPPrecision; + + /// UnsafeFPMath - This flag is enabled when the + /// -enable-unsafe-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// produce results that are "less precise" than IEEE allows. This includes + /// use of X86 instructions like FSIN and FCOS instead of libcalls. + /// UnsafeFPMath implies LessPreciseFPMAD. + extern bool UnsafeFPMath; + + /// NoInfsFPMath - This flag is enabled when the + /// -enable-no-infs-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// assume the FP arithmetic arguments and results are never +-Infs. + extern bool NoInfsFPMath; + + /// NoNaNsFPMath - This flag is enabled when the + /// -enable-no-nans-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// assume the FP arithmetic arguments and results are never NaNs. + extern bool NoNaNsFPMath; + + /// HonorSignDependentRoundingFPMath - This returns true when the + /// -enable-sign-dependent-rounding-fp-math is specified. If this returns + /// false (the default), the code generator is allowed to assume that the + /// rounding behavior is the default (round-to-zero for all floating point to + /// integer conversions, and round-to-nearest for all other arithmetic + /// truncations). If this is enabled (set to true), the code generator must + /// assume that the rounding mode may dynamically change. + extern bool HonorSignDependentRoundingFPMathOption; + extern bool HonorSignDependentRoundingFPMath(); + + /// UseSoftFloat - This flag is enabled when the -soft-float flag is specified + /// on the command line. When this flag is on, the code generator will + /// generate libcalls to the software floating point library instead of + /// target FP instructions. + extern bool UseSoftFloat; + + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied + /// on the command line. This setting may either be Default, Soft, or Hard. + /// Default selects the target's default behavior. Soft selects the ABI for + /// UseSoftFloat, but does not inidcate that FP hardware may not be used. + /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). + /// Hard presumes that the normal FP ABI is used. + extern FloatABI::ABIType FloatABIType; + + /// NoZerosInBSS - By default some codegens place zero-initialized data to + /// .bss section. This flag disables such behaviour (necessary, e.g. for + /// crt*.o compiling). + extern bool NoZerosInBSS; + + /// JITExceptionHandling - This flag indicates that the JIT should emit + /// exception handling information. + extern bool JITExceptionHandling; + + /// JITEmitDebugInfo - This flag indicates that the JIT should try to emit + /// debug information and notify a debugger about it. + extern bool JITEmitDebugInfo; + + /// JITEmitDebugInfoToDisk - This flag indicates that the JIT should write + /// the object files generated by the JITEmitDebugInfo flag to disk. This + /// flag is hidden and is only for debugging the debug info. + extern bool JITEmitDebugInfoToDisk; + + /// UnwindTablesMandatory - This flag indicates that unwind tables should + /// be emitted for all functions. + extern bool UnwindTablesMandatory; + + /// GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is + /// specified on the commandline. When the flag is on, participating targets + /// will perform tail call optimization on all calls which use the fastcc + /// calling convention and which satisfy certain target-independent + /// criteria (being at the end of a function, having the same return type + /// as their parent function, etc.), using an alternate ABI if necessary. + extern bool GuaranteedTailCallOpt; + + /// StackAlignment - Override default stack alignment for target. + extern unsigned StackAlignment; + + /// RealignStack - This flag indicates whether the stack should be + /// automatically realigned, if needed. + extern bool RealignStack; + + /// DisableJumpTables - This flag indicates jump tables should not be + /// generated. + extern bool DisableJumpTables; + + /// EnableFastISel - This flag enables fast-path instruction selection + /// which trades away generated code quality in favor of reducing + /// compile time. + extern bool EnableFastISel; + + /// StrongPHIElim - This flag enables more aggressive PHI elimination + /// wth earlier copy coalescing. + extern bool StrongPHIElim; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetRegisterInfo.h b/final/include/llvm/Target/TargetRegisterInfo.h new file mode 100644 index 00000000000..1c5d7c71187 --- /dev/null +++ b/final/include/llvm/Target/TargetRegisterInfo.h @@ -0,0 +1,828 @@ +//=== Target/TargetRegisterInfo.h - Target Register Information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETREGISTERINFO_H +#define LLVM_TARGET_TARGETREGISTERINFO_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/DenseSet.h" +#include +#include + +namespace llvm { + +class BitVector; +class MachineFunction; +class MachineMove; +class RegScavenger; +template class SmallVectorImpl; +class raw_ostream; + +/// TargetRegisterDesc - This record contains all of the information known about +/// a particular register. The Overlaps field contains a pointer to a zero +/// terminated array of registers that this register aliases, starting with +/// itself. This is needed for architectures like X86 which have AL alias AX +/// alias EAX. The SubRegs field is a zero terminated array of registers that +/// are sub-registers of the specific register, e.g. AL, AH are sub-registers of +/// AX. The SuperRegs field is a zero terminated array of registers that are +/// super-registers of the specific register, e.g. RAX, EAX, are super-registers +/// of AX. +/// +struct TargetRegisterDesc { + const char *Name; // Printable name for the reg (for debugging) + const unsigned *Overlaps; // Overlapping registers, described above + const unsigned *SubRegs; // Sub-register set, described above + const unsigned *SuperRegs; // Super-register set, described above +}; + +class TargetRegisterClass { +public: + typedef const unsigned* iterator; + typedef const unsigned* const_iterator; + + typedef const EVT* vt_iterator; + typedef const TargetRegisterClass* const * sc_iterator; +private: + unsigned ID; + const char *Name; + const vt_iterator VTs; + const sc_iterator SubClasses; + const sc_iterator SuperClasses; + const sc_iterator SubRegClasses; + const sc_iterator SuperRegClasses; + const unsigned RegSize, Alignment; // Size & Alignment of register in bytes + const int CopyCost; + const iterator RegsBegin, RegsEnd; + DenseSet RegSet; +public: + TargetRegisterClass(unsigned id, + const char *name, + const EVT *vts, + const TargetRegisterClass * const *subcs, + const TargetRegisterClass * const *supcs, + const TargetRegisterClass * const *subregcs, + const TargetRegisterClass * const *superregcs, + unsigned RS, unsigned Al, int CC, + iterator RB, iterator RE) + : ID(id), Name(name), VTs(vts), SubClasses(subcs), SuperClasses(supcs), + SubRegClasses(subregcs), SuperRegClasses(superregcs), + RegSize(RS), Alignment(Al), CopyCost(CC), RegsBegin(RB), RegsEnd(RE) { + for (iterator I = RegsBegin, E = RegsEnd; I != E; ++I) + RegSet.insert(*I); + } + virtual ~TargetRegisterClass() {} // Allow subclasses + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// getName() - Return the register class name for debugging. + /// + const char *getName() const { return Name; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsEnd; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return (unsigned)(RegsEnd-RegsBegin); } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. This does not include virtual registers. + bool contains(unsigned Reg) const { + return RegSet.count(Reg); + } + + /// contains - Return true if both registers are in this class. + bool contains(unsigned Reg1, unsigned Reg2) const { + return contains(Reg1) && contains(Reg2); + } + + /// hasType - return true if this TargetRegisterClass has the ValueType vt. + /// + bool hasType(EVT vt) const { + for(int i = 0; VTs[i] != MVT::Other; ++i) + if (VTs[i] == vt) + return true; + return false; + } + + /// vt_begin / vt_end - Loop over all of the value types that can be + /// represented by values in this register class. + vt_iterator vt_begin() const { + return VTs; + } + + vt_iterator vt_end() const { + vt_iterator I = VTs; + while (*I != MVT::Other) ++I; + return I; + } + + /// subregclasses_begin / subregclasses_end - Loop over all of + /// the subreg register classes of this register class. + sc_iterator subregclasses_begin() const { + return SubRegClasses; + } + + sc_iterator subregclasses_end() const { + sc_iterator I = SubRegClasses; + while (*I != NULL) ++I; + return I; + } + + /// getSubRegisterRegClass - Return the register class of subregisters with + /// index SubIdx, or NULL if no such class exists. + const TargetRegisterClass* getSubRegisterRegClass(unsigned SubIdx) const { + assert(SubIdx>0 && "Invalid subregister index"); + return SubRegClasses[SubIdx-1]; + } + + /// superregclasses_begin / superregclasses_end - Loop over all of + /// the superreg register classes of this register class. + sc_iterator superregclasses_begin() const { + return SuperRegClasses; + } + + sc_iterator superregclasses_end() const { + sc_iterator I = SuperRegClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSubClass - return true if the specified TargetRegisterClass + /// is a proper subset of this TargetRegisterClass. + bool hasSubClass(const TargetRegisterClass *cs) const { + for (int i = 0; SubClasses[i] != NULL; ++i) + if (SubClasses[i] == cs) + return true; + return false; + } + + /// subclasses_begin / subclasses_end - Loop over all of the classes + /// that are proper subsets of this register class. + sc_iterator subclasses_begin() const { + return SubClasses; + } + + sc_iterator subclasses_end() const { + sc_iterator I = SubClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSuperClass - return true if the specified TargetRegisterClass is a + /// proper superset of this TargetRegisterClass. + bool hasSuperClass(const TargetRegisterClass *cs) const { + for (int i = 0; SuperClasses[i] != NULL; ++i) + if (SuperClasses[i] == cs) + return true; + return false; + } + + /// superclasses_begin / superclasses_end - Loop over all of the classes + /// that are proper supersets of this register class. + sc_iterator superclasses_begin() const { + return SuperClasses; + } + + sc_iterator superclasses_end() const { + sc_iterator I = SuperClasses; + while (*I != NULL) ++I; + return I; + } + + /// isASubClass - return true if this TargetRegisterClass is a subset + /// class of at least one other TargetRegisterClass. + bool isASubClass() const { + return SuperClasses[0] != 0; + } + + /// allocation_order_begin/end - These methods define a range of registers + /// which specify the registers in this class that are valid to register + /// allocate, and the preferred order to allocate them in. For example, + /// callee saved registers should be at the end of the list, because it is + /// cheaper to allocate caller saved registers. + /// + /// These methods take a MachineFunction argument, which can be used to tune + /// the allocatable registers based on the characteristics of the function, + /// subtarget, or other criteria. + /// + /// Register allocators should account for the fact that an allocation + /// order iterator may return a reserved register and always check + /// if the register is allocatable (getAllocatableSet()) before using it. + /// + /// By default, these methods return all registers in the class. + /// + virtual iterator allocation_order_begin(const MachineFunction &MF) const { + return begin(); + } + virtual iterator allocation_order_end(const MachineFunction &MF) const { + return end(); + } + + /// getSize - Return the size of the register in bytes, which is also the size + /// of a stack slot allocated to hold a spilled copy of this register. + unsigned getSize() const { return RegSize; } + + /// getAlignment - Return the minimum required alignment for a register of + /// this class. + unsigned getAlignment() const { return Alignment; } + + /// getCopyCost - Return the cost of copying a value between two registers in + /// this class. A negative number means the register class is very expensive + /// to copy e.g. status flag register classes. + int getCopyCost() const { return CopyCost; } +}; + + +/// TargetRegisterInfo base class - We assume that the target defines a static +/// array of TargetRegisterDesc objects that represent all of the machine +/// registers that the target has. As such, we simply have to track a pointer +/// to this array so that we can turn register number into a register +/// descriptor. +/// +class TargetRegisterInfo { +protected: + const unsigned* SubregHash; + const unsigned SubregHashSize; + const unsigned* AliasesHash; + const unsigned AliasesHashSize; +public: + typedef const TargetRegisterClass * const * regclass_iterator; +private: + const TargetRegisterDesc *Desc; // Pointer to the descriptor array + const char *const *SubRegIndexNames; // Names of subreg indexes. + unsigned NumRegs; // Number of entries in the array + + regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses + + int CallFrameSetupOpcode, CallFrameDestroyOpcode; + +protected: + TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + regclass_iterator RegClassBegin, + regclass_iterator RegClassEnd, + const char *const *subregindexnames, + int CallFrameSetupOpcode = -1, + int CallFrameDestroyOpcode = -1, + const unsigned* subregs = 0, + const unsigned subregsize = 0, + const unsigned* aliases = 0, + const unsigned aliasessize = 0); + virtual ~TargetRegisterInfo(); +public: + + // Register numbers can represent physical registers, virtual registers, and + // sometimes stack slots. The unsigned values are divided into these ranges: + // + // 0 Not a register, can be used as a sentinel. + // [1;2^30) Physical registers assigned by TableGen. + // [2^30;2^31) Stack slots. (Rarely used.) + // [2^31;2^32) Virtual registers assigned by MachineRegisterInfo. + // + // Further sentinels can be allocated from the small negative integers. + // DenseMapInfo uses -1u and -2u. + + /// isStackSlot - Sometimes it is useful the be able to store a non-negative + /// frame index in a variable that normally holds a register. isStackSlot() + /// returns true if Reg is in the range used for stack slots. + /// + /// Note that isVirtualRegister() and isPhysicalRegister() cannot handle stack + /// slots, so if a variable may contains a stack slot, always check + /// isStackSlot() first. + /// + static bool isStackSlot(unsigned Reg) { + return int(Reg) >= (1 << 30); + } + + /// stackSlot2Index - Compute the frame index from a register value + /// representing a stack slot. + static int stackSlot2Index(unsigned Reg) { + assert(isStackSlot(Reg) && "Not a stack slot"); + return int(Reg - (1u << 30)); + } + + /// index2StackSlot - Convert a non-negative frame index to a stack slot + /// register value. + static unsigned index2StackSlot(int FI) { + assert(FI >= 0 && "Cannot hold a negative frame index."); + return FI + (1u << 30); + } + + /// isPhysicalRegister - Return true if the specified register number is in + /// the physical register namespace. + static bool isPhysicalRegister(unsigned Reg) { + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) > 0; + } + + /// isVirtualRegister - Return true if the specified register number is in + /// the virtual register namespace. + static bool isVirtualRegister(unsigned Reg) { + assert(!isStackSlot(Reg) && "Not a register! Check isStackSlot() first."); + return int(Reg) < 0; + } + + /// virtReg2Index - Convert a virtual register number to a 0-based index. + /// The first virtual register in a function will get the index 0. + static unsigned virtReg2Index(unsigned Reg) { + assert(isVirtualRegister(Reg) && "Not a virtual register"); + return Reg - (1u << 31); + } + + /// index2VirtReg - Convert a 0-based index to a virtual register number. + /// This is the inverse operation of VirtReg2IndexFunctor below. + static unsigned index2VirtReg(unsigned Index) { + return Index + (1u << 31); + } + + /// getMinimalPhysRegClass - Returns the Register Class of a physical + /// register of the given type, picking the most sub register class of + /// the right type that contains this physreg. + const TargetRegisterClass * + getMinimalPhysRegClass(unsigned Reg, EVT VT = MVT::Other) const; + + /// getAllocatableSet - Returns a bitset indexed by register number + /// indicating if a register is allocatable or not. If a register class is + /// specified, returns the subset for the class. + BitVector getAllocatableSet(const MachineFunction &MF, + const TargetRegisterClass *RC = NULL) const; + + const TargetRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful if we have a + /// pointer to this object. + /// + const TargetRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + // The Overlaps set always begins with Reg itself. + return get(RegNo).Overlaps + 1; + } + + /// getOverlaps - Return a list of registers that overlap Reg, including + /// itself. This is the same as the alias set except Reg is included in the + /// list. + /// These are exactly the registers in { x | regsOverlap(x, Reg) }. + /// + const unsigned *getOverlaps(unsigned RegNo) const { + return get(RegNo).Overlaps; + } + + /// getSubRegisters - Return the list of registers that are sub-registers of + /// the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::RAX's sub-register list is EAX, AX, AL, AH. + /// + const unsigned *getSubRegisters(unsigned RegNo) const { + return get(RegNo).SubRegs; + } + + /// getSuperRegisters - Return the list of registers that are super-registers + /// of the specified register, or a null list of there are none. The list + /// returned is zero terminated and sorted according to super-sub register + /// relations. e.g. X86::AL's super-register list is RAX, EAX, AX. + /// + const unsigned *getSuperRegisters(unsigned RegNo) const { + return get(RegNo).SuperRegs; + } + + /// getName - Return the human-readable symbolic target-specific name for the + /// specified physical register. + const char *getName(unsigned RegNo) const { + return get(RegNo).Name; + } + + /// getNumRegs - Return the number of registers this target has (useful for + /// sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } + + /// getSubRegIndexName - Return the human-readable symbolic target-specific + /// name for the specified SubRegIndex. + const char *getSubRegIndexName(unsigned SubIdx) const { + assert(SubIdx && "This is not a subregister index"); + return SubRegIndexNames[SubIdx-1]; + } + + /// regsOverlap - Returns true if the two registers are equal or alias each + /// other. The registers may be virtual register. + bool regsOverlap(unsigned regA, unsigned regB) const { + if (regA == regB) + return true; + + if (isVirtualRegister(regA) || isVirtualRegister(regB)) + return false; + + // regA and regB are distinct physical registers. Do they alias? + size_t index = (regA + regB * 37) & (AliasesHashSize-1); + unsigned ProbeAmt = 0; + while (AliasesHash[index*2] != 0 && + AliasesHash[index*2+1] != 0) { + if (AliasesHash[index*2] == regA && AliasesHash[index*2+1] == regB) + return true; + + index = (index + ProbeAmt) & (AliasesHashSize-1); + ProbeAmt += 2; + } + + return false; + } + + /// isSubRegister - Returns true if regB is a sub-register of regA. + /// + bool isSubRegister(unsigned regA, unsigned regB) const { + // SubregHash is a simple quadratically probed hash table. + size_t index = (regA + regB * 37) & (SubregHashSize-1); + unsigned ProbeAmt = 2; + while (SubregHash[index*2] != 0 && + SubregHash[index*2+1] != 0) { + if (SubregHash[index*2] == regA && SubregHash[index*2+1] == regB) + return true; + + index = (index + ProbeAmt) & (SubregHashSize-1); + ProbeAmt += 2; + } + + return false; + } + + /// isSuperRegister - Returns true if regB is a super-register of regA. + /// + bool isSuperRegister(unsigned regA, unsigned regB) const { + return isSubRegister(regB, regA); + } + + /// getCalleeSavedRegs - Return a null-terminated list of all of the + /// callee saved registers on this target. The register should be in the + /// order of desired callee-save stack frame offset. The first register is + /// closed to the incoming stack pointer if stack grows down, and vice versa. + virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF = 0) + const = 0; + + + /// getReservedRegs - Returns a bitset indexed by physical register number + /// indicating if a register is a special register that has particular uses + /// and should be considered unavailable at all times, e.g. SP, RA. This is + /// used by register scavenger to determine what registers are free. + virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + + /// getSubReg - Returns the physical register number of sub-register "Index" + /// for physical register RegNo. Return zero if the sub-register does not + /// exist. + virtual unsigned getSubReg(unsigned RegNo, unsigned Index) const = 0; + + /// getSubRegIndex - For a given register pair, return the sub-register index + /// if the second register is a sub-register of the first. Return zero + /// otherwise. + virtual unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const = 0; + + /// getMatchingSuperReg - Return a super-register of the specified register + /// Reg so its sub-register of index SubIdx is Reg. + unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, + const TargetRegisterClass *RC) const { + for (const unsigned *SRs = getSuperRegisters(Reg); unsigned SR = *SRs;++SRs) + if (Reg == getSubReg(SR, SubIdx) && RC->contains(SR)) + return SR; + return 0; + } + + /// canCombineSubRegIndices - Given a register class and a list of + /// subregister indices, return true if it's possible to combine the + /// subregister indices into one that corresponds to a larger + /// subregister. Return the new subregister index by reference. Note the + /// new index may be zero if the given subregisters can be combined to + /// form the whole register. + virtual bool canCombineSubRegIndices(const TargetRegisterClass *RC, + SmallVectorImpl &SubIndices, + unsigned &NewSubIdx) const { + return 0; + } + + /// getMatchingSuperRegClass - Return a subclass of the specified register + /// class A so that each register in it has a sub-register of the + /// specified sub-register index which is in the specified register class B. + virtual const TargetRegisterClass * + getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, unsigned Idx) const { + return 0; + } + + /// composeSubRegIndices - Return the subregister index you get from composing + /// two subregister indices. + /// + /// If R:a:b is the same register as R:c, then composeSubRegIndices(a, b) + /// returns c. Note that composeSubRegIndices does not tell you about illegal + /// compositions. If R does not have a subreg a, or R:a does not have a subreg + /// b, composeSubRegIndices doesn't tell you. + /// + /// The ARM register Q0 has two D subregs dsub_0:D0 and dsub_1:D1. It also has + /// ssub_0:S0 - ssub_3:S3 subregs. + /// If you compose subreg indices dsub_1, ssub_0 you get ssub_2. + /// + virtual unsigned composeSubRegIndices(unsigned a, unsigned b) const { + // This default implementation is correct for most targets. + return b; + } + + //===--------------------------------------------------------------------===// + // Register Class Information + // + + /// Register class iterators + /// + regclass_iterator regclass_begin() const { return RegClassBegin; } + regclass_iterator regclass_end() const { return RegClassEnd; } + + unsigned getNumRegClasses() const { + return (unsigned)(regclass_end()-regclass_begin()); + } + + /// getRegClass - Returns the register class associated with the enumeration + /// value. See class TargetOperandInfo. + const TargetRegisterClass *getRegClass(unsigned i) const { + assert(i < getNumRegClasses() && "Register Class ID out of range"); + return RegClassBegin[i]; + } + + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer + /// values. If a target supports multiple different pointer register classes, + /// kind specifies which one is indicated. + virtual const TargetRegisterClass *getPointerRegClass(unsigned Kind=0) const { + assert(0 && "Target didn't implement getPointerRegClass!"); + return 0; // Must return a value in order to compile with VS 2005 + } + + /// getCrossCopyRegClass - Returns a legal register class to copy a register + /// in the specified class to or from. Returns NULL if it is possible to copy + /// between a two registers of the specified class. + virtual const TargetRegisterClass * + getCrossCopyRegClass(const TargetRegisterClass *RC) const { + return NULL; + } + + /// getRegPressureLimit - Return the register pressure "high water mark" for + /// the specific register class. The scheduler is in high register pressure + /// mode (for the specific register class) if it goes over the limit. + virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const { + return 0; + } + + /// getAllocationOrder - Returns the register allocation order for a specified + /// register class in the form of a pair of TargetRegisterClass iterators. + virtual std::pair + getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const { + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + } + + /// ResolveRegAllocHint - Resolves the specified register allocation hint + /// to a physical register. Returns the physical register if it is successful. + virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const { + if (Type == 0 && Reg && isPhysicalRegister(Reg)) + return Reg; + return 0; + } + + /// UpdateRegAllocHint - A callback to allow target a chance to update + /// register allocation hints when a register is "changed" (e.g. coalesced) + /// to another register. e.g. On ARM, some virtual registers should target + /// register pairs, if one of pair is coalesced to another register, the + /// allocation hint of the other half of the pair should be changed to point + /// to the new register. + virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + // Do nothing. + } + + /// requiresRegisterScavenging - returns true if the target requires (and can + /// make use of) the register scavenger. + virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { + return false; + } + + /// useFPForScavengingIndex - returns true if the target wants to use + /// frame pointer based accesses to spill to the scavenger emergency spill + /// slot. + virtual bool useFPForScavengingIndex(const MachineFunction &MF) const { + return true; + } + + /// requiresFrameIndexScavenging - returns true if the target requires post + /// PEI scavenging of registers for materializing frame index constants. + virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const { + return false; + } + + /// requiresVirtualBaseRegisters - Returns true if the target wants the + /// LocalStackAllocation pass to be run and virtual base registers + /// used for more efficient stack access. + virtual bool requiresVirtualBaseRegisters(const MachineFunction &MF) const { + return false; + } + + /// hasReservedSpillSlot - Return true if target has reserved a spill slot in + /// the stack frame of the given function for the specified register. e.g. On + /// x86, if the frame register is required, the first fixed stack object is + /// reserved as its spill slot. This tells PEI not to create a new stack frame + /// object for the given register. It should be called only after + /// processFunctionBeforeCalleeSavedScan(). + virtual bool hasReservedSpillSlot(const MachineFunction &MF, unsigned Reg, + int &FrameIdx) const { + return false; + } + + /// needsStackRealignment - true if storage within the function requires the + /// stack pointer to be aligned more than the normal calling convention calls + /// for. + virtual bool needsStackRealignment(const MachineFunction &MF) const { + return false; + } + + /// getFrameIndexInstrOffset - Get the offset from the referenced frame + /// index in the instruction, if there is one. + virtual int64_t getFrameIndexInstrOffset(const MachineInstr *MI, + int Idx) const { + return 0; + } + + /// needsFrameBaseReg - Returns true if the instruction's frame index + /// reference would be better served by a base register other than FP + /// or SP. Used by LocalStackFrameAllocation to determine which frame index + /// references it should create new base registers for. + virtual bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { + return false; + } + + /// materializeFrameBaseRegister - Insert defining instruction(s) for + /// BaseReg to be a pointer to FrameIdx before insertion point I. + virtual void materializeFrameBaseRegister(MachineBasicBlock *MBB, + unsigned BaseReg, int FrameIdx, + int64_t Offset) const { + assert(0 && "materializeFrameBaseRegister does not exist on this target"); + } + + /// resolveFrameIndex - Resolve a frame index operand of an instruction + /// to reference the indicated base register plus offset instead. + virtual void resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const { + assert(0 && "resolveFrameIndex does not exist on this target"); + } + + /// isFrameOffsetLegal - Determine whether a given offset immediate is + /// encodable to resolve a frame index. + virtual bool isFrameOffsetLegal(const MachineInstr *MI, + int64_t Offset) const { + assert(0 && "isFrameOffsetLegal does not exist on this target"); + return false; // Must return a value in order to compile with VS 2005 + } + + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the + /// frame setup/destroy instructions if they exist (-1 otherwise). Some + /// targets use pseudo instructions in order to abstract away the difference + /// between operating with a frame pointer and operating without, through the + /// use of these two instructions. + /// + int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + + /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog + /// code insertion to eliminate call frame setup and destroy pseudo + /// instructions (but only if the Target is using them). It is responsible + /// for eliminating these instructions, replacing them with concrete + /// instructions. This method need only be implemented if using call frame + /// setup/destroy pseudo instructions. + /// + virtual void + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && + "eliminateCallFramePseudoInstr must be implemented if using" + " call frame setup/destroy pseudo instructions!"); + assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); + } + + + /// saveScavengerRegister - Spill the register so it can be used by the + /// register scavenger. Return true if the register was spilled, false + /// otherwise. If this function does not spill the register, the scavenger + /// will instead spill it to the emergency spill slot. + /// + virtual bool saveScavengerRegister(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &UseMI, + const TargetRegisterClass *RC, + unsigned Reg) const { + return false; + } + + /// eliminateFrameIndex - This method must be overriden to eliminate abstract + /// frame indices from instructions which may use them. The instruction + /// referenced by the iterator contains an MO_FrameIndex operand which must be + /// eliminated by this method. This method may modify or replace the + /// specified instruction, as long as it keeps the iterator pointing at the + /// finished product. SPAdj is the SP adjustment due to call frame setup + /// instruction. + virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, RegScavenger *RS=NULL) const = 0; + + //===--------------------------------------------------------------------===// + /// Debug information queries. + + /// getDwarfRegNum - Map a target register to an equivalent dwarf register + /// number. Returns -1 if there is no equivalent value. The second + /// parameter allows targets to use different numberings for EH info and + /// debugging info. + virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0; + + /// getFrameRegister - This method should return the register used as a base + /// for values allocated in the current stack frame. + virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; + + /// getRARegister - This method should return the register where the return + /// address can be found. + virtual unsigned getRARegister() const = 0; +}; + + +// This is useful when building IndexedMaps keyed on virtual registers +struct VirtReg2IndexFunctor : public std::unary_function { + unsigned operator()(unsigned Reg) const { + return TargetRegisterInfo::virtReg2Index(Reg); + } +}; + +/// getCommonSubClass - find the largest common subclass of A and B. Return NULL +/// if there is no common subclass. +const TargetRegisterClass *getCommonSubClass(const TargetRegisterClass *A, + const TargetRegisterClass *B); + +/// PrintReg - Helper class for printing registers on a raw_ostream. +/// Prints virtual and physical registers with or without a TRI instance. +/// +/// The format is: +/// %noreg - NoRegister +/// %vreg5 - a virtual register. +/// %vreg5:sub_8bit - a virtual register with sub-register index (with TRI). +/// %EAX - a physical register +/// %physreg17 - a physical register when no TRI instance given. +/// +/// Usage: OS << PrintReg(Reg, TRI) << '\n'; +/// +class PrintReg { + const TargetRegisterInfo *TRI; + unsigned Reg; + unsigned SubIdx; +public: + PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, unsigned subidx = 0) + : TRI(tri), Reg(reg), SubIdx(subidx) {} + void print(raw_ostream&) const; +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const PrintReg &PR) { + PR.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetRegistry.h b/final/include/llvm/Target/TargetRegistry.h new file mode 100644 index 00000000000..f851ad0a9bf --- /dev/null +++ b/final/include/llvm/Target/TargetRegistry.h @@ -0,0 +1,779 @@ +//===-- Target/TargetRegistry.h - Target Registration -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the TargetRegistry interface, which tools can use to access +// the appropriate target specific classes (TargetMachine, AsmPrinter, etc.) +// which have been registered. +// +// Target specific class implementations should register themselves using the +// appropriate TargetRegistry interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETREGISTRY_H +#define LLVM_TARGET_TARGETREGISTRY_H + +#include "llvm/ADT/Triple.h" +#include +#include + +namespace llvm { + class AsmPrinter; + class Module; + class MCAssembler; + class MCAsmInfo; + class MCAsmParser; + class MCCodeEmitter; + class MCContext; + class MCDisassembler; + class MCInstPrinter; + class MCStreamer; + class TargetAsmBackend; + class TargetAsmLexer; + class TargetAsmParser; + class TargetMachine; + class raw_ostream; + class formatted_raw_ostream; + + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst); + + /// Target - Wrapper for Target specific information. + /// + /// For registration purposes, this is a POD type so that targets can be + /// registered without the use of static constructors. + /// + /// Targets should implement a single global instance of this class (which + /// will be zero initialized), and pass that instance to the TargetRegistry as + /// part of their initialization. + class Target { + public: + friend struct TargetRegistry; + + typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); + + typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T, + StringRef TT); + typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, + const std::string &TT, + const std::string &Features); + typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, + MCStreamer &Streamer); + typedef TargetAsmBackend *(*AsmBackendCtorTy)(const Target &T, + const std::string &TT); + typedef TargetAsmLexer *(*AsmLexerCtorTy)(const Target &T, + const MCAsmInfo &MAI); + typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T,MCAsmParser &P, + TargetMachine &TM); + typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T); + typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI); + typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, + TargetMachine &TM, + MCContext &Ctx); + typedef MCStreamer *(*ObjectStreamerCtorTy)(const Target &T, + const std::string &TT, + MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack); + typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, + formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst); + + private: + /// Next - The next registered target in the linked list, maintained by the + /// TargetRegistry. + Target *Next; + + /// TripleMatchQualityFn - The target function for rating the match quality + /// of a triple. + TripleMatchQualityFnTy TripleMatchQualityFn; + + /// Name - The target name. + const char *Name; + + /// ShortDesc - A short description of the target. + const char *ShortDesc; + + /// HasJIT - Whether this target supports the JIT. + bool HasJIT; + + AsmInfoCtorFnTy AsmInfoCtorFn; + + /// TargetMachineCtorFn - Construction function for this target's + /// TargetMachine, if registered. + TargetMachineCtorTy TargetMachineCtorFn; + + /// AsmBackendCtorFn - Construction function for this target's + /// TargetAsmBackend, if registered. + AsmBackendCtorTy AsmBackendCtorFn; + + /// AsmLexerCtorFn - Construction function for this target's TargetAsmLexer, + /// if registered. + AsmLexerCtorTy AsmLexerCtorFn; + + /// AsmParserCtorFn - Construction function for this target's + /// TargetAsmParser, if registered. + AsmParserCtorTy AsmParserCtorFn; + + /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, + /// if registered. + AsmPrinterCtorTy AsmPrinterCtorFn; + + /// MCDisassemblerCtorFn - Construction function for this target's + /// MCDisassembler, if registered. + MCDisassemblerCtorTy MCDisassemblerCtorFn; + + /// MCInstPrinterCtorFn - Construction function for this target's + /// MCInstPrinter, if registered. + MCInstPrinterCtorTy MCInstPrinterCtorFn; + + /// CodeEmitterCtorFn - Construction function for this target's CodeEmitter, + /// if registered. + CodeEmitterCtorTy CodeEmitterCtorFn; + + /// ObjectStreamerCtorFn - Construction function for this target's + /// ObjectStreamer, if registered. + ObjectStreamerCtorTy ObjectStreamerCtorFn; + + /// AsmStreamerCtorFn - Construction function for this target's + /// AsmStreamer, if registered (default = llvm::createAsmStreamer). + AsmStreamerCtorTy AsmStreamerCtorFn; + + public: + Target() : AsmStreamerCtorFn(llvm::createAsmStreamer) {} + + /// @name Target Information + /// @{ + + // getNext - Return the next registered target. + const Target *getNext() const { return Next; } + + /// getName - Get the target name. + const char *getName() const { return Name; } + + /// getShortDescription - Get a short description of the target. + const char *getShortDescription() const { return ShortDesc; } + + /// @} + /// @name Feature Predicates + /// @{ + + /// hasJIT - Check if this targets supports the just-in-time compilation. + bool hasJIT() const { return HasJIT; } + + /// hasTargetMachine - Check if this target supports code generation. + bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } + + /// hasAsmBackend - Check if this target supports .o generation. + bool hasAsmBackend() const { return AsmBackendCtorFn != 0; } + + /// hasAsmLexer - Check if this target supports .s lexing. + bool hasAsmLexer() const { return AsmLexerCtorFn != 0; } + + /// hasAsmParser - Check if this target supports .s parsing. + bool hasAsmParser() const { return AsmParserCtorFn != 0; } + + /// hasAsmPrinter - Check if this target supports .s printing. + bool hasAsmPrinter() const { return AsmPrinterCtorFn != 0; } + + /// hasMCDisassembler - Check if this target has a disassembler. + bool hasMCDisassembler() const { return MCDisassemblerCtorFn != 0; } + + /// hasMCInstPrinter - Check if this target has an instruction printer. + bool hasMCInstPrinter() const { return MCInstPrinterCtorFn != 0; } + + /// hasCodeEmitter - Check if this target supports instruction encoding. + bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + + /// hasObjectStreamer - Check if this target supports streaming to files. + bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; } + + /// hasAsmStreamer - Check if this target supports streaming to files. + bool hasAsmStreamer() const { return AsmStreamerCtorFn != 0; } + + /// @} + /// @name Feature Constructors + /// @{ + + /// createAsmInfo - Create a MCAsmInfo implementation for the specified + /// target triple. + /// + /// \arg Triple - This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + MCAsmInfo *createAsmInfo(StringRef Triple) const { + if (!AsmInfoCtorFn) + return 0; + return AsmInfoCtorFn(*this, Triple); + } + + /// createTargetMachine - Create a target specific machine implementation + /// for the specified \arg Triple. + /// + /// \arg Triple - This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + TargetMachine *createTargetMachine(const std::string &Triple, + const std::string &Features) const { + if (!TargetMachineCtorFn) + return 0; + return TargetMachineCtorFn(*this, Triple, Features); + } + + /// createAsmBackend - Create a target specific assembly parser. + /// + /// \arg Triple - The target triple string. + /// \arg Backend - The target independent assembler object. + TargetAsmBackend *createAsmBackend(const std::string &Triple) const { + if (!AsmBackendCtorFn) + return 0; + return AsmBackendCtorFn(*this, Triple); + } + + /// createAsmLexer - Create a target specific assembly lexer. + /// + TargetAsmLexer *createAsmLexer(const MCAsmInfo &MAI) const { + if (!AsmLexerCtorFn) + return 0; + return AsmLexerCtorFn(*this, MAI); + } + + /// createAsmParser - Create a target specific assembly parser. + /// + /// \arg Parser - The target independent parser implementation to use for + /// parsing and lexing. + TargetAsmParser *createAsmParser(MCAsmParser &Parser, + TargetMachine &TM) const { + if (!AsmParserCtorFn) + return 0; + return AsmParserCtorFn(*this, Parser, TM); + } + + /// createAsmPrinter - Create a target specific assembly printer pass. This + /// takes ownership of the MCStreamer object. + AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ + if (!AsmPrinterCtorFn) + return 0; + return AsmPrinterCtorFn(TM, Streamer); + } + + MCDisassembler *createMCDisassembler() const { + if (!MCDisassemblerCtorFn) + return 0; + return MCDisassemblerCtorFn(*this); + } + + MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, + const MCAsmInfo &MAI) const { + if (!MCInstPrinterCtorFn) + return 0; + return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI); + } + + + /// createCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createCodeEmitter(TargetMachine &TM, MCContext &Ctx) const { + if (!CodeEmitterCtorFn) + return 0; + return CodeEmitterCtorFn(*this, TM, Ctx); + } + + /// createObjectStreamer - Create a target specific MCStreamer. + /// + /// \arg TT - The target triple. + /// \arg Ctx - The target context. + /// \arg TAB - The target assembler backend object. Takes ownership. + /// \arg _OS - The stream object. + /// \arg _Emitter - The target independent assembler object.Takes ownership. + /// \arg RelaxAll - Relax all fixups? + /// \arg NoExecStack - Mark file as not needing a executable stack. + MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll, + bool NoExecStack) const { + if (!ObjectStreamerCtorFn) + return 0; + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); + } + + /// createAsmStreamer - Create a target specific MCStreamer. + MCStreamer *createAsmStreamer(MCContext &Ctx, + formatted_raw_ostream &OS, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *InstPrint, + MCCodeEmitter *CE, + TargetAsmBackend *TAB, + bool ShowInst) const { + // AsmStreamerCtorFn is default to llvm::createAsmStreamer + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, + InstPrint, CE, TAB, ShowInst); + } + + /// @} + }; + + /// TargetRegistry - Generic interface to target specific features. + struct TargetRegistry { + class iterator { + const Target *Current; + explicit iterator(Target *T) : Current(T) {} + friend struct TargetRegistry; + public: + iterator(const iterator &I) : Current(I.Current) {} + iterator() : Current(0) {} + + bool operator==(const iterator &x) const { + return Current == x.Current; + } + bool operator!=(const iterator &x) const { + return !operator==(x); + } + + // Iterator traversal: forward iteration only + iterator &operator++() { // Preincrement + assert(Current && "Cannot increment end iterator!"); + Current = Current->getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; + ++*this; + return tmp; + } + + const Target &operator*() const { + assert(Current && "Cannot dereference end iterator!"); + return *Current; + } + + const Target *operator->() const { + return &operator*(); + } + }; + + /// @name Registry Access + /// @{ + + static iterator begin(); + + static iterator end() { return iterator(); } + + /// lookupTarget - Lookup a target based on a target triple. + /// + /// \param Triple - The triple to use for finding a target. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &Triple, + std::string &Error); + + /// getClosestTargetForJIT - Pick the best target that is compatible with + /// the current host. If no close target can be found, this returns null + /// and sets the Error string to a reason. + /// + /// Maintained for compatibility through 2.6. + static const Target *getClosestTargetForJIT(std::string &Error); + + /// @} + /// @name Target Registration + /// @{ + + /// RegisterTarget - Register the given target. Attempts to register a + /// target which has already been registered will be ignored. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Name - The target name. This should be a static string. + /// @param ShortDesc - A short target description. This should be a static + /// string. + /// @param TQualityFn - The triple match quality computation function for + /// this target. + /// @param HasJIT - Whether the target supports JIT code + /// generation. + static void RegisterTarget(Target &T, + const char *Name, + const char *ShortDesc, + Target::TripleMatchQualityFnTy TQualityFn, + bool HasJIT = false); + + /// RegisterAsmInfo - Register a MCAsmInfo implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCAsmInfo for the target. + static void RegisterAsmInfo(Target &T, Target::AsmInfoCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.AsmInfoCtorFn) + T.AsmInfoCtorFn = Fn; + } + + /// RegisterTargetMachine - Register a TargetMachine implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct a TargetMachine for the target. + static void RegisterTargetMachine(Target &T, + Target::TargetMachineCtorTy Fn) { + // Ignore duplicate registration. + if (!T.TargetMachineCtorFn) + T.TargetMachineCtorFn = Fn; + } + + /// RegisterAsmBackend - Register a TargetAsmBackend implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmBackend for the target. + static void RegisterAsmBackend(Target &T, Target::AsmBackendCtorTy Fn) { + if (!T.AsmBackendCtorFn) + T.AsmBackendCtorFn = Fn; + } + + /// RegisterAsmLexer - Register a TargetAsmLexer implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmLexer for the target. + static void RegisterAsmLexer(Target &T, Target::AsmLexerCtorTy Fn) { + if (!T.AsmLexerCtorFn) + T.AsmLexerCtorFn = Fn; + } + + /// RegisterAsmParser - Register a TargetAsmParser implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmParser for the target. + static void RegisterAsmParser(Target &T, Target::AsmParserCtorTy Fn) { + if (!T.AsmParserCtorFn) + T.AsmParserCtorFn = Fn; + } + + /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given + /// target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { + // Ignore duplicate registration. + if (!T.AsmPrinterCtorFn) + T.AsmPrinterCtorFn = Fn; + } + + /// RegisterMCDisassembler - Register a MCDisassembler implementation for + /// the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCDisassembler for the target. + static void RegisterMCDisassembler(Target &T, + Target::MCDisassemblerCtorTy Fn) { + if (!T.MCDisassemblerCtorFn) + T.MCDisassemblerCtorFn = Fn; + } + + /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCInstPrinter for the target. + static void RegisterMCInstPrinter(Target &T, + Target::MCInstPrinterCtorTy Fn) { + if (!T.MCInstPrinterCtorFn) + T.MCInstPrinterCtorFn = Fn; + } + + /// RegisterCodeEmitter - Register a MCCodeEmitter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCCodeEmitter for the target. + static void RegisterCodeEmitter(Target &T, Target::CodeEmitterCtorTy Fn) { + if (!T.CodeEmitterCtorFn) + T.CodeEmitterCtorFn = Fn; + } + + /// RegisterObjectStreamer - Register a object code MCStreamer implementation + /// for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCStreamer for the target. + static void RegisterObjectStreamer(Target &T, Target::ObjectStreamerCtorTy Fn) { + if (!T.ObjectStreamerCtorFn) + T.ObjectStreamerCtorFn = Fn; + } + + /// RegisterAsmStreamer - Register an assembly MCStreamer implementation + /// for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCStreamer for the target. + static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { + if (T.AsmStreamerCtorFn == createAsmStreamer) + T.AsmStreamerCtorFn = Fn; + } + + /// @} + }; + + + //===--------------------------------------------------------------------===// + + /// RegisterTarget - Helper template for registering a target, for use in the + /// target's initialization function. Usage: + /// + /// + /// Target TheFooTarget; // The global target instance. + /// + /// extern "C" void LLVMInitializeFooTargetInfo() { + /// RegisterTarget X(TheFooTarget, "foo", "Foo description"); + /// } + template + struct RegisterTarget { + RegisterTarget(Target &T, const char *Name, const char *Desc) { + TargetRegistry::RegisterTarget(T, Name, Desc, + &getTripleMatchQuality, + HasJIT); + } + + static unsigned getTripleMatchQuality(const std::string &TT) { + if (Triple(TT).getArch() == TargetArchType) + return 20; + return 0; + } + }; + + /// RegisterAsmInfo - Helper template for registering a target assembly info + /// implementation. This invokes the static "Create" method on the class to + /// actually do the construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterAsmInfo X(TheFooTarget); + /// } + template + struct RegisterAsmInfo { + RegisterAsmInfo(Target &T) { + TargetRegistry::RegisterAsmInfo(T, &Allocator); + } + private: + static MCAsmInfo *Allocator(const Target &T, StringRef TT) { + return new MCAsmInfoImpl(T, TT); + } + + }; + + /// RegisterAsmInfoFn - Helper template for registering a target assembly info + /// implementation. This invokes the specified function to do the + /// construction. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterAsmInfoFn X(TheFooTarget, TheFunction); + /// } + struct RegisterAsmInfoFn { + RegisterAsmInfoFn(Target &T, Target::AsmInfoCtorFnTy Fn) { + TargetRegistry::RegisterAsmInfo(T, Fn); + } + }; + + + /// RegisterTargetMachine - Helper template for registering a target machine + /// implementation, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooTarget() { + /// extern Target TheFooTarget; + /// RegisterTargetMachine X(TheFooTarget); + /// } + template + struct RegisterTargetMachine { + RegisterTargetMachine(Target &T) { + TargetRegistry::RegisterTargetMachine(T, &Allocator); + } + + private: + static TargetMachine *Allocator(const Target &T, const std::string &TT, + const std::string &FS) { + return new TargetMachineImpl(T, TT, FS); + } + }; + + /// RegisterAsmBackend - Helper template for registering a target specific + /// assembler backend. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmBackend() { + /// extern Target TheFooTarget; + /// RegisterAsmBackend X(TheFooTarget); + /// } + template + struct RegisterAsmBackend { + RegisterAsmBackend(Target &T) { + TargetRegistry::RegisterAsmBackend(T, &Allocator); + } + + private: + static TargetAsmBackend *Allocator(const Target &T, + const std::string &Triple) { + return new AsmBackendImpl(T, Triple); + } + }; + + /// RegisterAsmLexer - Helper template for registering a target specific + /// assembly lexer, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmLexer() { + /// extern Target TheFooTarget; + /// RegisterAsmLexer X(TheFooTarget); + /// } + template + struct RegisterAsmLexer { + RegisterAsmLexer(Target &T) { + TargetRegistry::RegisterAsmLexer(T, &Allocator); + } + + private: + static TargetAsmLexer *Allocator(const Target &T, const MCAsmInfo &MAI) { + return new AsmLexerImpl(T, MAI); + } + }; + + /// RegisterAsmParser - Helper template for registering a target specific + /// assembly parser, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmParser() { + /// extern Target TheFooTarget; + /// RegisterAsmParser X(TheFooTarget); + /// } + template + struct RegisterAsmParser { + RegisterAsmParser(Target &T) { + TargetRegistry::RegisterAsmParser(T, &Allocator); + } + + private: + static TargetAsmParser *Allocator(const Target &T, MCAsmParser &P, + TargetMachine &TM) { + return new AsmParserImpl(T, P, TM); + } + }; + + /// RegisterAsmPrinter - Helper template for registering a target specific + /// assembly printer, for use in the target machine initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooAsmPrinter() { + /// extern Target TheFooTarget; + /// RegisterAsmPrinter X(TheFooTarget); + /// } + template + struct RegisterAsmPrinter { + RegisterAsmPrinter(Target &T) { + TargetRegistry::RegisterAsmPrinter(T, &Allocator); + } + + private: + static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) { + return new AsmPrinterImpl(TM, Streamer); + } + }; + + /// RegisterCodeEmitter - Helper template for registering a target specific + /// machine code emitter, for use in the target initialization + /// function. Usage: + /// + /// extern "C" void LLVMInitializeFooCodeEmitter() { + /// extern Target TheFooTarget; + /// RegisterCodeEmitter X(TheFooTarget); + /// } + template + struct RegisterCodeEmitter { + RegisterCodeEmitter(Target &T) { + TargetRegistry::RegisterCodeEmitter(T, &Allocator); + } + + private: + static MCCodeEmitter *Allocator(const Target &T, TargetMachine &TM, + MCContext &Ctx) { + return new CodeEmitterImpl(T, TM, Ctx); + } + }; + +} + +#endif diff --git a/final/include/llvm/Target/TargetSchedule.td b/final/include/llvm/Target/TargetSchedule.td new file mode 100644 index 00000000000..97ea82ab9e3 --- /dev/null +++ b/final/include/llvm/Target/TargetSchedule.td @@ -0,0 +1,130 @@ +//===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===// +// +// 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 target-independent scheduling interfaces which should +// be implemented by each target which is using TableGen based scheduling. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Processor functional unit - These values represent the function units +// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... +// These may be independent values for each chip set or may be shared across +// all chip sets of the target. Each functional unit is treated as a resource +// during scheduling and has an affect instruction order based on availability +// during a time interval. +// +class FuncUnit; + +//===----------------------------------------------------------------------===// +// Pipeline bypass / forwarding - These values specifies the symbolic names of +// pipeline bypasses which can be used to forward results of instructions +// that are forwarded to uses. +class Bypass; +def NoBypass : Bypass; + +class ReservationKind val> { + int Value = val; +} + +def Required : ReservationKind<0>; +def Reserved : ReservationKind<1>; + +//===----------------------------------------------------------------------===// +// Instruction stage - These values represent a non-pipelined step in +// the execution of an instruction. Cycles represents the number of +// discrete time slots needed to complete the stage. Units represent +// the choice of functional units that can be used to complete the +// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many +// cycles should elapse from the start of this stage to the start of +// the next stage in the itinerary. For example: +// +// A stage is specified in one of two ways: +// +// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles +// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit +// + +class InstrStage units, + int timeinc = -1, + ReservationKind kind = Required> { + int Cycles = cycles; // length of stage in machine cycles + list Units = units; // choice of functional units + int TimeInc = timeinc; // cycles till start of next stage + int Kind = kind.Value; // kind of FU reservation +} + +//===----------------------------------------------------------------------===// +// Instruction itinerary - An itinerary represents a sequential series of steps +// required to complete an instruction. Itineraries are represented as lists of +// instruction stages. +// + +//===----------------------------------------------------------------------===// +// Instruction itinerary classes - These values represent 'named' instruction +// itinerary. Using named itineraries simplifies managing groups of +// instructions across chip sets. An instruction uses the same itinerary class +// across all chip sets. Thus a new chip set can be added without modifying +// instruction information. +// +// NumMicroOps represents the number of micro-operations that each instruction +// in the class are decoded to. If the number is zero, then it means the +// instruction can decode into variable number of micro-ops and it must be +// determined dynamically. +// +class InstrItinClass { + int NumMicroOps = ops; +} +def NoItinerary : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Instruction itinerary data - These values provide a runtime map of an +// instruction itinerary class (name) to its itinerary data. +// +// OperandCycles are optional "cycle counts". They specify the cycle after +// instruction issue the values which correspond to specific operand indices +// are defined or read. Bypasses are optional "pipeline forwarding pathes", if +// a def by an instruction is available on a specific bypass and the use can +// read from the same bypass, then the operand use latency is reduced by one. +// +// InstrItinData, +// InstrStage<1, [A9_AGU]>], +// [3, 1], [A9_LdBypass]>, +// InstrItinData], +// [1, 1], [NoBypass, A9_LdBypass]>, +// +// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 +// (after issue) and the result of the load is available on cycle 3. The result +// is available via forwarding path A9_LdBypass. If it's used by the first +// source operand of instructions of IIC_iMVNr class, then the operand latency +// is reduced by 1. +class InstrItinData stages, + list operandcycles = [], + list bypasses = []> { + InstrItinClass TheClass = Class; + list Stages = stages; + list OperandCycles = operandcycles; + list Bypasses = bypasses; +} + +//===----------------------------------------------------------------------===// +// Processor itineraries - These values represent the set of all itinerary +// classes for a given chip set. +// +class ProcessorItineraries fu, list bp, + list iid> { + list FU = fu; + list BP = bp; + list IID = iid; +} + +// NoItineraries - A marker that can be used by processors without schedule +// info. +def NoItineraries : ProcessorItineraries<[], [], []>; + diff --git a/final/include/llvm/Target/TargetSelect.h b/final/include/llvm/Target/TargetSelect.h new file mode 100644 index 00000000000..1891f879741 --- /dev/null +++ b/final/include/llvm/Target/TargetSelect.h @@ -0,0 +1,125 @@ +//===- TargetSelect.h - Target Selection & Registration ---------*- 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 utilities to make sure that certain classes of targets are +// linked into the main application executable, and initialize them as +// appropriate. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSELECT_H +#define LLVM_TARGET_TARGETSELECT_H + +#include "llvm/Config/llvm-config.h" + +extern "C" { + // Declare all of the target-initialization functions that are available. +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" + +#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" + + // Declare all of the available assembly printer initialization functions. +#define LLVM_ASM_PRINTER(TargetName) void LLVMInitialize##TargetName##AsmPrinter(); +#include "llvm/Config/AsmPrinters.def" + + // Declare all of the available assembly parser initialization functions. +#define LLVM_ASM_PARSER(TargetName) void LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/AsmParsers.def" + + // Declare all of the available disassembler initialization functions. +#define LLVM_DISASSEMBLER(TargetName) void LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/Disassemblers.def" +} + +namespace llvm { + /// InitializeAllTargetInfos - The main program should call this function if + /// it wants access to all available targets that LLVM is configured to + /// support, to make them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllTargetInfos() { +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetInfo(); +#include "llvm/Config/Targets.def" + } + + /// InitializeAllTargets - The main program should call this function if it + /// wants access to all available target machines that LLVM is configured to + /// support, to make them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllTargets() { + // FIXME: Remove this, clients should do it. + InitializeAllTargetInfos(); + +#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##Target(); +#include "llvm/Config/Targets.def" + } + + /// InitializeAllAsmPrinters - The main program should call this function if + /// it wants all asm printers that LLVM is configured to support, to make them + /// available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllAsmPrinters() { +#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter(); +#include "llvm/Config/AsmPrinters.def" + } + + /// InitializeAllAsmParsers - The main program should call this function if it + /// wants all asm parsers that LLVM is configured to support, to make them + /// available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllAsmParsers() { +#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser(); +#include "llvm/Config/AsmParsers.def" + } + + /// InitializeAllDisassemblers - The main program should call this function if + /// it wants all disassemblers that LLVM is configured to support, to make + /// them available via the TargetRegistry. + /// + /// It is legal for a client to make multiple calls to this function. + inline void InitializeAllDisassemblers() { +#define LLVM_DISASSEMBLER(TargetName) LLVMInitialize##TargetName##Disassembler(); +#include "llvm/Config/Disassemblers.def" + } + + /// InitializeNativeTarget - The main program should call this function to + /// initialize the native target corresponding to the host. This is useful + /// for JIT applications to ensure that the target gets linked in correctly. + /// + /// It is legal for a client to make multiple calls to this function. + inline bool InitializeNativeTarget() { + // If we have a native target, initialize it to ensure it is linked in. +#ifdef LLVM_NATIVE_TARGET + LLVM_NATIVE_TARGETINFO(); + LLVM_NATIVE_TARGET(); + return false; +#else + return true; +#endif + } + + /// InitializeNativeTargetAsmPrinter - The main program should call + /// this function to initialize the native target asm printer. + inline bool InitializeNativeTargetAsmPrinter() { + // If we have a native target, initialize the corresponding asm printer. +#ifdef LLVM_NATIVE_ASMPRINTER + LLVM_NATIVE_ASMPRINTER(); + return false; +#else + return true; +#endif + } +} + +#endif diff --git a/final/include/llvm/Target/TargetSelectionDAG.td b/final/include/llvm/Target/TargetSelectionDAG.td new file mode 100644 index 00000000000..c9be40d23f0 --- /dev/null +++ b/final/include/llvm/Target/TargetSelectionDAG.td @@ -0,0 +1,893 @@ +//===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// +// +// 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 target-independent interfaces used by SelectionDAG +// instruction selection generators. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Selection DAG Type Constraint definitions. +// +// Note that the semantics of these constraints are hard coded into tblgen. To +// modify or add constraints, you have to hack tblgen. +// + +class SDTypeConstraint { + int OperandNum = opnum; +} + +// SDTCisVT - The specified operand has exactly this VT. +class SDTCisVT : SDTypeConstraint { + ValueType VT = vt; +} + +class SDTCisPtrTy : SDTypeConstraint; + +// SDTCisInt - The specified operand has integer type. +class SDTCisInt : SDTypeConstraint; + +// SDTCisFP - The specified operand has floating-point type. +class SDTCisFP : SDTypeConstraint; + +// SDTCisVec - The specified operand has a vector type. +class SDTCisVec : SDTypeConstraint; + +// SDTCisSameAs - The two specified operands have identical types. +class SDTCisSameAs : SDTypeConstraint { + int OtherOperandNum = OtherOp; +} + +// SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is +// smaller than the 'Other' operand. +class SDTCisVTSmallerThanOp : SDTypeConstraint { + int OtherOperandNum = OtherOp; +} + +class SDTCisOpSmallerThanOp : SDTypeConstraint{ + int BigOperandNum = BigOp; +} + +/// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same +/// type as the element type of OtherOp, which is a vector type. +class SDTCisEltOfVec + : SDTypeConstraint { + int OtherOpNum = OtherOp; +} + +/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type +/// with length less that of OtherOp, which is a vector type. +class SDTCisSubVecOfVec + : SDTypeConstraint { + int OtherOpNum = OtherOp; +} + +//===----------------------------------------------------------------------===// +// Selection DAG Type Profile definitions. +// +// These use the constraints defined above to describe the type requirements of +// the various nodes. These are not hard coded into tblgen, allowing targets to +// add their own if needed. +// + +// SDTypeProfile - This profile describes the type requirements of a Selection +// DAG node. +class SDTypeProfile constraints> { + int NumResults = numresults; + int NumOperands = numoperands; + list Constraints = constraints; +} + +// Builtin profiles. +def SDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for 'imm'. +def SDTFPLeaf : SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for 'fpimm'. +def SDTPtrLeaf: SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for '&g'. +def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. +def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. +def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. + +def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0> +]>; +def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2> +]>; +def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0> +]>; + +def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0> +]>; +def SDTFPSignOp : SDTypeProfile<1, 2, [ // fcopysign. + SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisFP<2> +]>; +def SDTFPTernaryOp : SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0> +]>; +def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz + SDTCisSameAs<0, 1>, SDTCisInt<0> +]>; +def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0> +]>; +def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1> +]>; +def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc + SDTCisSameAs<0, 1>, SDTCisFP<0> +]>; +def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1> +]>; +def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0> +]>; +def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp + SDTCisFP<0>, SDTCisInt<1> +]>; +def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int + SDTCisInt<0>, SDTCisFP<1> +]>; +def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, + SDTCisVTSmallerThanOp<2, 1> +]>; + +def SDTSetCC : SDTypeProfile<1, 3, [ // setcc + SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + +def SDTSelect : SDTypeProfile<1, 3, [ // select + SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> +]>; + +def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc + SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, + SDTCisVT<5, OtherVT> +]>; + +def SDTBr : SDTypeProfile<0, 1, [ // br + SDTCisVT<0, OtherVT> +]>; + +def SDTBrcond : SDTypeProfile<0, 2, [ // brcond + SDTCisInt<0>, SDTCisVT<1, OtherVT> +]>; + +def SDTBrind : SDTypeProfile<0, 1, [ // brind + SDTCisPtrTy<0> +]>; + +def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap + +def SDTLoad : SDTypeProfile<1, 1, [ // load + SDTCisPtrTy<1> +]>; + +def SDTStore : SDTypeProfile<0, 2, [ // store + SDTCisPtrTy<1> +]>; + +def SDTIStore : SDTypeProfile<1, 3, [ // indexed store + SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> +]>; + +def SDTVecShuffle : SDTypeProfile<1, 2, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> +]>; +def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract + SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> +]>; +def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert + SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> +]>; + +def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract + SDTCisSubVecOfVec<0,1>, SDTCisInt<2> +]>; +def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert + SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> +]>; + +def SDTPrefetch : SDTypeProfile<0, 3, [ // prefetch + SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisInt<1> +]>; + +def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier + SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, + SDTCisInt<0> +]>; +def SDTAtomic3 : SDTypeProfile<1, 3, [ + SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; +def SDTAtomic2 : SDTypeProfile<1, 2, [ + SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; + +def SDTConvertOp : SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff, fs, fu, sf, su + SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5> +]>; + +class SDCallSeqStart constraints> : + SDTypeProfile<0, 1, constraints>; +class SDCallSeqEnd constraints> : + SDTypeProfile<0, 2, constraints>; + +//===----------------------------------------------------------------------===// +// Selection DAG Node Properties. +// +// Note: These are hard coded into tblgen. +// +class SDNodeProperty; +def SDNPCommutative : SDNodeProperty; // X op Y == Y op X +def SDNPAssociative : SDNodeProperty; // (X op Y) op Z == X op (Y op Z) +def SDNPHasChain : SDNodeProperty; // R/W chain operand and result +def SDNPOutGlue : SDNodeProperty; // Write a flag result +def SDNPInGlue : SDNodeProperty; // Read a flag operand +def SDNPOptInGlue : SDNodeProperty; // Optionally read a flag operand +def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'. +def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'. +def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'. +def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand +def SDNPVariadic : SDNodeProperty; // Node has variable arguments. +def SDNPWantRoot : SDNodeProperty; // ComplexPattern gets the root of match +def SDNPWantParent : SDNodeProperty; // ComplexPattern gets the parent + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Operations +class SDPatternOperator; + +//===----------------------------------------------------------------------===// +// Selection DAG Node definitions. +// +class SDNode props = [], string sdclass = "SDNode"> + : SDPatternOperator { + string Opcode = opcode; + string SDClass = sdclass; + list Properties = props; + SDTypeProfile TypeProfile = typeprof; +} + +// Special TableGen-recognized dag nodes +def set; +def implicit; +def node; +def srcvalue; + +def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; +def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; +def fpimm : SDNode<"ISD::ConstantFP", SDTFPLeaf , [], "ConstantFPSDNode">; +def vt : SDNode<"ISD::VALUETYPE" , SDTOther , [], "VTSDNode">; +def bb : SDNode<"ISD::BasicBlock", SDTOther , [], "BasicBlockSDNode">; +def cond : SDNode<"ISD::CONDCODE" , SDTOther , [], "CondCodeSDNode">; +def undef : SDNode<"ISD::UNDEF" , SDTUNDEF , []>; +def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def jumptable : SDNode<"ISD::JumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def tjumptable : SDNode<"ISD::TargetJumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def frameindex : SDNode<"ISD::FrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def tframeindex : SDNode<"ISD::TargetFrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; +def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; + +def add : SDNode<"ISD::ADD" , SDTIntBinOp , + [SDNPCommutative, SDNPAssociative]>; +def sub : SDNode<"ISD::SUB" , SDTIntBinOp>; +def mul : SDNode<"ISD::MUL" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>; +def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>; +def smullohi : SDNode<"ISD::SMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; +def umullohi : SDNode<"ISD::UMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; +def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>; +def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>; +def srem : SDNode<"ISD::SREM" , SDTIntBinOp>; +def urem : SDNode<"ISD::UREM" , SDTIntBinOp>; +def sdivrem : SDNode<"ISD::SDIVREM" , SDTIntBinHiLoOp>; +def udivrem : SDNode<"ISD::UDIVREM" , SDTIntBinHiLoOp>; +def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>; +def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>; +def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>; +def rotl : SDNode<"ISD::ROTL" , SDTIntShiftOp>; +def rotr : SDNode<"ISD::ROTR" , SDTIntShiftOp>; +def and : SDNode<"ISD::AND" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def or : SDNode<"ISD::OR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def xor : SDNode<"ISD::XOR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, + [SDNPCommutative, SDNPOutGlue]>; +def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, + [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; +def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, + [SDNPOutGlue]>; +def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, + [SDNPOutGlue, SDNPInGlue]>; + +def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; +def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; +def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; +def cttz : SDNode<"ISD::CTTZ" , SDTIntUnaryOp>; +def ctpop : SDNode<"ISD::CTPOP" , SDTIntUnaryOp>; +def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; +def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; +def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; +def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; +def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; +def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; +def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; + + +def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; +def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; +def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; +def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; +def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; +def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; +def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; +def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; +def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; +def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; +def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; +def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; +def frint : SDNode<"ISD::FRINT" , SDTFPUnaryOp>; +def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; +def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; +def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; +def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; + +def fround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; +def fextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; +def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; + +def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; +def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; +def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; +def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; +def f16_to_f32 : SDNode<"ISD::FP16_TO_FP32", SDTIntToFPOp>; +def f32_to_f16 : SDNode<"ISD::FP32_TO_FP16", SDTFPToIntOp>; + +def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; +def select : SDNode<"ISD::SELECT" , SDTSelect>; +def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; +def vsetcc : SDNode<"ISD::VSETCC" , SDTSetCC>; + +def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; +def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; +def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; +def trap : SDNode<"ISD::TRAP" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; + +def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; + +def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, + [SDNPHasChain, SDNPSideEffect]>; + +def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; + +// Do not use ld, st directly. Use load, extload, sextload, zextload, store, +// and truncst (see below). +def ld : SDNode<"ISD::LOAD" , SDTLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def st : SDNode<"ISD::STORE" , SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def ist : SDNode<"ISD::STORE" , SDTIStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; + +def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>; +def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>; +def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>, + []>; +def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", + SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; +def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", + SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; + +// This operator does not do subvector type checking. The ARM +// backend, at least, needs it. +def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", + SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, + []>; + +// This operator does subvector type checking. +def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; +def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; + +// Nodes for intrinsics, you should use the intrinsic itself and let tblgen use +// these internally. Don't reference these directly. +def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", + SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, + [SDNPHasChain]>; +def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, + [SDNPHasChain]>; +def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; + +// Do not use cvt directly. Use cvt forms below +def cvt : SDNode<"ISD::CONVERT_RNDSAT", SDTConvertOp>; + +//===----------------------------------------------------------------------===// +// Selection DAG Condition Codes + +class CondCode; // ISD::CondCode enums +def SETOEQ : CondCode; def SETOGT : CondCode; +def SETOGE : CondCode; def SETOLT : CondCode; def SETOLE : CondCode; +def SETONE : CondCode; def SETO : CondCode; def SETUO : CondCode; +def SETUEQ : CondCode; def SETUGT : CondCode; def SETUGE : CondCode; +def SETULT : CondCode; def SETULE : CondCode; def SETUNE : CondCode; + +def SETEQ : CondCode; def SETGT : CondCode; def SETGE : CondCode; +def SETLT : CondCode; def SETLE : CondCode; def SETNE : CondCode; + + +//===----------------------------------------------------------------------===// +// Selection DAG Node Transformation Functions. +// +// This mechanism allows targets to manipulate nodes in the output DAG once a +// match has been formed. This is typically used to manipulate immediate +// values. +// +class SDNodeXForm { + SDNode Opcode = opc; + code XFormFunction = xformFunction; +} + +def NOOP_SDNodeXForm : SDNodeXForm; + + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Fragments. +// +// Pattern fragments are reusable chunks of dags that match specific things. +// They can take arguments and have C++ predicates that control whether they +// match. They are intended to make the patterns for common instructions more +// compact and readable. +// + +/// PatFrag - Represents a pattern fragment. This can match something on the +/// DAG, from a single node to multiple nested other fragments. +/// +class PatFrag : SDPatternOperator { + dag Operands = ops; + dag Fragment = frag; + code Predicate = pred; + SDNodeXForm OperandTransform = xform; +} + +// PatLeaf's are pattern fragments that have no operands. This is just a helper +// to define immediates and other common things concisely. +class PatLeaf + : PatFrag<(ops), frag, pred, xform>; + +// Leaf fragments. + +def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; +def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; + +def immAllOnesV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllOnes(N); +}]>; +def immAllZerosV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllZeros(N); +}]>; + + + +// Other helper fragments. +def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; +def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; +def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; + +// load fragments. +def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr), [{ + return cast(N)->getAddressingMode() == ISD::UNINDEXED; +}]>; +def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::NON_EXTLOAD; +}]>; + +// extending load fragments. +def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::EXTLOAD; +}]>; +def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::SEXTLOAD; +}]>; +def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ + return cast(N)->getExtensionType() == ISD::ZEXTLOAD; +}]>; + +def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; + +def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; + +def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; + +// store fragments. +def unindexedstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + return cast(N)->getAddressingMode() == ISD::UNINDEXED; +}]>; +def store : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr), [{ + return !cast(N)->isTruncatingStore(); +}]>; + +// truncstore fragments. +def truncstore : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr), [{ + return cast(N)->isTruncatingStore(); +}]>; +def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; +def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr), [{ + return cast(N)->getMemoryVT() == MVT::f64; +}]>; + +// indexed store fragments. +def istore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset), [{ + return !cast(N)->isTruncatingStore(); +}]>; + +def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), + (istore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; + +def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset), [{ + return cast(N)->isTruncatingStore(); +}]>; +def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; +def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; + +def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), + (istore node:$val, node:$ptr, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; + +def post_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; +def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i1; +}]>; +def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset), [{ + return cast(N)->getMemoryVT() == MVT::f32; +}]>; + +// setcc convenience fragments. +def setoeq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOEQ)>; +def setogt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGT)>; +def setoge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGE)>; +def setolt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLT)>; +def setole : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLE)>; +def setone : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETONE)>; +def seto : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETO)>; +def setuo : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUO)>; +def setueq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUEQ)>; +def setugt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGT)>; +def setuge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGE)>; +def setult : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULT)>; +def setule : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULE)>; +def setune : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUNE)>; +def seteq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETEQ)>; +def setgt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGT)>; +def setge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGE)>; +def setlt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLT)>; +def setle : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLE)>; +def setne : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETNE)>; + +def atomic_cmp_swap_8 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i8; +}]>; +def atomic_cmp_swap_16 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i16; +}]>; +def atomic_cmp_swap_32 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i32; +}]>; +def atomic_cmp_swap_64 : + PatFrag<(ops node:$ptr, node:$cmp, node:$swap), + (atomic_cmp_swap node:$ptr, node:$cmp, node:$swap), [{ + return cast(N)->getMemoryVT() == MVT::i64; +}]>; + +multiclass binary_atomic_op { + def _8 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i8; + }]>; + def _16 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i16; + }]>; + def _32 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i32; + }]>; + def _64 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val), [{ + return cast(N)->getMemoryVT() == MVT::i64; + }]>; +} + +defm atomic_load_add : binary_atomic_op; +defm atomic_swap : binary_atomic_op; +defm atomic_load_sub : binary_atomic_op; +defm atomic_load_and : binary_atomic_op; +defm atomic_load_or : binary_atomic_op; +defm atomic_load_xor : binary_atomic_op; +defm atomic_load_nand : binary_atomic_op; +defm atomic_load_min : binary_atomic_op; +defm atomic_load_max : binary_atomic_op; +defm atomic_load_umin : binary_atomic_op; +defm atomic_load_umax : binary_atomic_op; + +//===----------------------------------------------------------------------===// +// Selection DAG CONVERT_RNDSAT patterns + +def cvtff : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FF; + }]>; + +def cvtss : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SS; + }]>; + +def cvtsu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SU; + }]>; + +def cvtus : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_US; + }]>; + +def cvtuu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_UU; + }]>; + +def cvtsf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_SF; + }]>; + +def cvtuf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_UF; + }]>; + +def cvtfs : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FS; + }]>; + +def cvtfu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), + (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ + return cast(N)->getCvtCode() == ISD::CVT_FU; + }]>; + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Support. +// +// Patterns are what are actually matched against by the target-flavored +// instruction selection DAG. Instructions defined by the target implicitly +// define patterns in most cases, but patterns can also be explicitly added when +// an operation is defined by a sequence of instructions (e.g. loading a large +// immediate value on RISC targets that do not support immediates as large as +// their GPRs). +// + +class Pattern resultInstrs> { + dag PatternToMatch = patternToMatch; + list ResultInstrs = resultInstrs; + list Predicates = []; // See class Instruction in Target.td. + int AddedComplexity = 0; // See class Instruction in Target.td. +} + +// Pat - A simple (but common) form of a pattern, which produces a simple result +// not needing a full list. +class Pat : Pattern; + +//===----------------------------------------------------------------------===// +// Complex pattern definitions. +// + +// Complex patterns, e.g. X86 addressing mode, requires pattern matching code +// in C++. NumOperands is the number of operands returned by the select function; +// SelectFunc is the name of the function used to pattern match the max. pattern; +// RootNodes are the list of possible root nodes of the sub-dags to match. +// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; +// +class ComplexPattern roots = [], list props = []> { + ValueType Ty = ty; + int NumOperands = numops; + string SelectFunc = fn; + list RootNodes = roots; + list Properties = props; +} diff --git a/final/include/llvm/Target/TargetSelectionDAGInfo.h b/final/include/llvm/Target/TargetSelectionDAGInfo.h new file mode 100644 index 00000000000..c9ca7223b5f --- /dev/null +++ b/final/include/llvm/Target/TargetSelectionDAGInfo.h @@ -0,0 +1,101 @@ +//==-- llvm/Target/TargetSelectionDAGInfo.h - SelectionDAG 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 declares the TargetSelectionDAGInfo class, which targets can +// subclass to parameterize the SelectionDAG lowering and instruction +// selection process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSELECTIONDAGINFO_H +#define LLVM_TARGET_TARGETSELECTIONDAGINFO_H + +#include "llvm/CodeGen/SelectionDAGNodes.h" + +namespace llvm { + +class TargetData; +class TargetMachine; + +//===----------------------------------------------------------------------===// +/// TargetSelectionDAGInfo - Targets can subclass this to parameterize the +/// SelectionDAG lowering and instruction selection process. +/// +class TargetSelectionDAGInfo { + TargetSelectionDAGInfo(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT + void operator=(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT + + const TargetData *TD; + +protected: + const TargetData *getTargetData() const { return TD; } + +public: + explicit TargetSelectionDAGInfo(const TargetMachine &TM); + virtual ~TargetSelectionDAGInfo(); + + /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a + /// memcpy. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + /// + /// If AlwaysInline is true, the size is constant and the target should not + /// emit any calls and is strongly encouraged to attempt to emit inline code + /// even if it is beyond the usual threshold because this intrinsic is being + /// expanded in a place where calls are not feasible (e.g. within the prologue + /// for another call). If the target chooses to decline an AlwaysInline + /// request here, legalize will resort to using simple loads and stores. + virtual SDValue + EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const { + return SDValue(); + } + + /// EmitTargetCodeForMemmove - Emit target-specific code that performs a + /// memmove. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemmove(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) const { + return SDValue(); + } + + /// EmitTargetCodeForMemset - Emit target-specific code that performs a + /// memset. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple stores and can be more + /// efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + MachinePointerInfo DstPtrInfo) const { + return SDValue(); + } +}; + +} // end llvm namespace + +#endif diff --git a/final/include/llvm/Target/TargetSubtarget.h b/final/include/llvm/Target/TargetSubtarget.h new file mode 100644 index 00000000000..22b09bac073 --- /dev/null +++ b/final/include/llvm/Target/TargetSubtarget.h @@ -0,0 +1,67 @@ +//==-- llvm/Target/TargetSubtarget.h - Target Information --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the subtarget options of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSUBTARGET_H +#define LLVM_TARGET_TARGETSUBTARGET_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class SDep; +class SUnit; +class TargetRegisterClass; +template class SmallVectorImpl; + +//===----------------------------------------------------------------------===// +/// +/// TargetSubtarget - Generic base class for all target subtargets. All +/// Target-specific options that control code generation and printing should +/// be exposed through a TargetSubtarget-derived class. +/// +class TargetSubtarget { + TargetSubtarget(const TargetSubtarget&); // DO NOT IMPLEMENT + void operator=(const TargetSubtarget&); // DO NOT IMPLEMENT +protected: // Can only create subclasses... + TargetSubtarget(); +public: + // AntiDepBreakMode - Type of anti-dependence breaking that should + // be performed before post-RA scheduling. + typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; + typedef SmallVectorImpl RegClassVector; + + virtual ~TargetSubtarget(); + + /// getSpecialAddressLatency - For targets where it is beneficial to + /// backschedule instructions that compute addresses, return a value + /// indicating the number of scheduling cycles of backscheduling that + /// should be attempted. + virtual unsigned getSpecialAddressLatency() const { return 0; } + + // enablePostRAScheduler - If the target can benefit from post-regalloc + // scheduling and the specified optimization level meets the requirement + // return true to enable post-register-allocation scheduling. In + // CriticalPathRCs return any register classes that should only be broken + // if on the critical path. + virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; + // adjustSchedDependency - Perform target specific adjustments to + // the latency of a schedule dependency. + virtual void adjustSchedDependency(SUnit *def, SUnit *use, + SDep& dep) const { } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/IPO.h b/final/include/llvm/Transforms/IPO.h new file mode 100644 index 00000000000..12398813cc7 --- /dev/null +++ b/final/include/llvm/Transforms/IPO.h @@ -0,0 +1,212 @@ +//===- llvm/Transforms/IPO.h - Interprocedural Transformations --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the IPO transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_H +#define LLVM_TRANSFORMS_IPO_H + +#include + +namespace llvm { + +class ModulePass; +class Pass; +class Function; +class BasicBlock; +class GlobalValue; + +//===----------------------------------------------------------------------===// +// +// These functions removes symbols from functions and modules. If OnlyDebugInfo +// is true, only debugging information is removed from the module. +// +ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false); + +//===----------------------------------------------------------------------===// +// +// These functions strips symbols from functions and modules. +// Only debugging information is not stripped. +// +ModulePass *createStripNonDebugSymbolsPass(); + +//===----------------------------------------------------------------------===// +// +// These pass removes llvm.dbg.declare intrinsics. +ModulePass *createStripDebugDeclarePass(); + +//===----------------------------------------------------------------------===// +// +// These pass removes unused symbols' debug info. +ModulePass *createStripDeadDebugInfoPass(); + +//===----------------------------------------------------------------------===// +/// createLowerSetJmpPass - This function lowers the setjmp/longjmp intrinsics +/// to invoke/unwind instructions. This should really be part of the C/C++ +/// front-end, but it's so much easier to write transformations in LLVM proper. +/// +ModulePass *createLowerSetJmpPass(); + +//===----------------------------------------------------------------------===// +/// createConstantMergePass - This function returns a new pass that merges +/// duplicate global constants together into a single constant that is shared. +/// This is useful because some passes (ie TraceValues) insert a lot of string +/// constants into the program, regardless of whether or not they duplicate an +/// existing string. +/// +ModulePass *createConstantMergePass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalOptimizerPass - This function returns a new pass that optimizes +/// non-address taken internal globals. +/// +ModulePass *createGlobalOptimizerPass(); + + +//===----------------------------------------------------------------------===// +/// createDeadTypeEliminationPass - Return a new pass that eliminates symbol +/// table entries for types that are never used. +/// +ModulePass *createDeadTypeEliminationPass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalDCEPass - This transform is designed to eliminate unreachable +/// internal globals (functions or global variables) +/// +ModulePass *createGlobalDCEPass(); + + +//===----------------------------------------------------------------------===// +/// createGVExtractionPass - If deleteFn is true, this pass deletes as +/// the specified global values. Otherwise, it deletes as much of the module as +/// possible, except for the global values specified. +/// +ModulePass *createGVExtractionPass(std::vector& GVs, bool + deleteFn = false); + +//===----------------------------------------------------------------------===// +/// createFunctionInliningPass - Return a new pass object that uses a heuristic +/// to inline direct function calls to small functions. +/// +/// The -inline-threshold command line option takes precedence over the +/// threshold given here. +Pass *createFunctionInliningPass(); +Pass *createFunctionInliningPass(int Threshold); + +//===----------------------------------------------------------------------===// +/// createAlwaysInlinerPass - Return a new pass object that inlines only +/// functions that are marked as "always_inline". +Pass *createAlwaysInlinerPass(); + +//===----------------------------------------------------------------------===// +/// createPruneEHPass - Return a new pass object which transforms invoke +/// instructions into calls, if the callee can _not_ unwind the stack. +/// +Pass *createPruneEHPass(); + +//===----------------------------------------------------------------------===// +/// createInternalizePass - This pass loops over all of the functions in the +/// input module, internalizing all globals (functions and variables) not part +/// of the api. If a list of symbols is specified with the +/// -internalize-public-api-* command line options, those symbols are not +/// internalized and all others are. Otherwise if AllButMain is set and the +/// main function is found, all other globals are marked as internal. If no api +/// is supplied and AllButMain is not set, or no main function is found, nothing +/// is internalized. +/// +ModulePass *createInternalizePass(bool AllButMain); + +/// createInternalizePass - This pass loops over all of the functions in the +/// input module, internalizing all globals (functions and variables) not in the +/// given exportList. +/// +/// Note that commandline options that are used with the above function are not +/// used now! Also, when exportList is empty, nothing is internalized. +ModulePass *createInternalizePass(const std::vector &exportList); + +//===----------------------------------------------------------------------===// +/// createDeadArgEliminationPass - This pass removes arguments from functions +/// which are not used by the body of the function. +/// +ModulePass *createDeadArgEliminationPass(); + +/// DeadArgHacking pass - Same as DAE, but delete arguments of external +/// functions as well. This is definitely not safe, and should only be used by +/// bugpoint. +ModulePass *createDeadArgHackingPass(); + +//===----------------------------------------------------------------------===// +/// createArgumentPromotionPass - This pass promotes "by reference" arguments to +/// be passed by value if the number of elements passed is smaller or +/// equal to maxElements (maxElements == 0 means always promote). +/// +Pass *createArgumentPromotionPass(unsigned maxElements = 3); +Pass *createStructRetPromotionPass(); + +//===----------------------------------------------------------------------===// +/// createIPConstantPropagationPass - This pass propagates constants from call +/// sites into the bodies of functions. +/// +ModulePass *createIPConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +/// createIPSCCPPass - This pass propagates constants from call sites into the +/// bodies of functions, and keeps track of whether basic blocks are executable +/// in the process. +/// +ModulePass *createIPSCCPPass(); + +//===----------------------------------------------------------------------===// +// +/// createLoopExtractorPass - This pass extracts all natural loops from the +/// program into a function if it can. +/// +Pass *createLoopExtractorPass(); + +/// createSingleLoopExtractorPass - This pass extracts one natural loop from the +/// program into a function if it can. This is used by bugpoint. +/// +Pass *createSingleLoopExtractorPass(); + +/// createBlockExtractorPass - This pass extracts all blocks (except those +/// specified in the argument list) from the functions in the module. +/// +ModulePass *createBlockExtractorPass(); + +/// createStripDeadPrototypesPass - This pass removes any function declarations +/// (prototypes) that are not used. +ModulePass *createStripDeadPrototypesPass(); + +//===----------------------------------------------------------------------===// +/// createFunctionAttrsPass - This pass discovers functions that do not access +/// memory, or only read memory, and gives them the readnone/readonly attribute. +/// It also discovers function arguments that are not captured by the function +/// and marks them with the nocapture attribute. +/// +Pass *createFunctionAttrsPass(); + +//===----------------------------------------------------------------------===// +/// createMergeFunctionsPass - This pass discovers identical functions and +/// collapses them. +/// +ModulePass *createMergeFunctionsPass(); + +//===----------------------------------------------------------------------===// +/// createPartialInliningPass - This pass inlines parts of functions. +/// +ModulePass *createPartialInliningPass(); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/IPO/InlinerPass.h b/final/include/llvm/Transforms/IPO/InlinerPass.h new file mode 100644 index 00000000000..3ac4c591c94 --- /dev/null +++ b/final/include/llvm/Transforms/IPO/InlinerPass.h @@ -0,0 +1,97 @@ +//===- InlinerPass.h - Code common to all inliners --------------*- 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 simple policy-based bottom-up inliner. This file +// implements all of the boring mechanics of the bottom-up inlining, while the +// subclass determines WHAT to inline, which is the much more interesting +// component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_INLINERPASS_H +#define LLVM_TRANSFORMS_IPO_INLINERPASS_H + +#include "llvm/CallGraphSCCPass.h" + +namespace llvm { + class CallSite; + class TargetData; + class InlineCost; + template + class SmallPtrSet; + +/// Inliner - This class contains all of the helper code which is used to +/// perform the inlining operations that do not depend on the policy. +/// +struct Inliner : public CallGraphSCCPass { + explicit Inliner(char &ID); + explicit Inliner(char &ID, int Threshold); + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; + + // Main run interface method, this implements the interface required by the + // Pass class. + virtual bool runOnSCC(CallGraphSCC &SCC); + + // doFinalization - Remove now-dead linkonce functions at the end of + // processing to avoid breaking the SCC traversal. + virtual bool doFinalization(CallGraph &CG); + + /// This method returns the value specified by the -inline-threshold value, + /// specified on the command line. This is typically not directly needed. + /// + unsigned getInlineThreshold() const { return InlineThreshold; } + + /// Calculate the inline threshold for given Caller. This threshold is lower + /// if the caller is marked with OptimizeForSize and -inline-threshold is not + /// given on the comand line. It is higher if the callee is marked with the + /// inlinehint attribute. + /// + unsigned getInlineThreshold(CallSite CS) const; + + /// getInlineCost - This method must be implemented by the subclass to + /// determine the cost of inlining the specified call site. If the cost + /// returned is greater than the current inline threshold, the call site is + /// not inlined. + /// + virtual InlineCost getInlineCost(CallSite CS) = 0; + + // getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a + // higher threshold to determine if the function call should be inlined. + /// + virtual float getInlineFudgeFactor(CallSite CS) = 0; + + /// resetCachedCostInfo - erase any cached cost data from the derived class. + /// If the derived class has no such data this can be empty. + /// + virtual void resetCachedCostInfo(Function* Caller) = 0; + + /// growCachedCostInfo - update the cached cost info for Caller after Callee + /// has been inlined. + virtual void growCachedCostInfo(Function *Caller, Function *Callee) = 0; + + /// removeDeadFunctions - Remove dead functions that are not included in + /// DNR (Do Not Remove) list. + bool removeDeadFunctions(CallGraph &CG, + SmallPtrSet *DNR = NULL); +private: + // InlineThreshold - Cache the value here for easy access. + unsigned InlineThreshold; + + /// shouldInline - Return true if the inliner should attempt to + /// inline at the given CallSite. + bool shouldInline(CallSite CS); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Instrumentation.h b/final/include/llvm/Transforms/Instrumentation.h new file mode 100644 index 00000000000..aa9873fb8af --- /dev/null +++ b/final/include/llvm/Transforms/Instrumentation.h @@ -0,0 +1,33 @@ +//===- Transforms/Instrumentation.h - Instrumentation passes ----*- 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 constructor functions for instrumentation passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_H + +namespace llvm { + +class ModulePass; +class FunctionPass; + +// Insert edge profiling instrumentation +ModulePass *createEdgeProfilerPass(); + +// Insert optimal edge profiling instrumentation +ModulePass *createOptimalEdgeProfilerPass(); + +// Insert path profiling instrumentation +ModulePass *createPathProfilerPass(); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Scalar.h b/final/include/llvm/Transforms/Scalar.h new file mode 100644 index 00000000000..8d5ed44cff3 --- /dev/null +++ b/final/include/llvm/Transforms/Scalar.h @@ -0,0 +1,348 @@ +//===-- Scalar.h - Scalar Transformations -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the Scalar transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_H +#define LLVM_TRANSFORMS_SCALAR_H + +namespace llvm { + +class FunctionPass; +class Pass; +class GetElementPtrInst; +class PassInfo; +class TerminatorInst; +class TargetLowering; + +//===----------------------------------------------------------------------===// +// +// ConstantPropagation - A worklist driven constant propagation pass +// +FunctionPass *createConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +// +// SCCP - Sparse conditional constant propagation. +// +FunctionPass *createSCCPPass(); + +//===----------------------------------------------------------------------===// +// +// DeadInstElimination - This pass quickly removes trivially dead instructions +// without modifying the CFG of the function. It is a BasicBlockPass, so it +// runs efficiently when queued next to other BasicBlockPass's. +// +Pass *createDeadInstEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadCodeElimination - This pass is more powerful than DeadInstElimination, +// because it is worklist driven that can potentially revisit instructions when +// their other instructions become dead, to eliminate chains of dead +// computations. +// +FunctionPass *createDeadCodeEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadStoreElimination - This pass deletes stores that are post-dominated by +// must-aliased stores and are not loaded used between the stores. +// +FunctionPass *createDeadStoreEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// AggressiveDCE - This pass uses the SSA based Aggressive DCE algorithm. This +// algorithm assumes instructions are dead until proven otherwise, which makes +// it more successful are removing non-obviously dead instructions. +// +FunctionPass *createAggressiveDCEPass(); + +//===----------------------------------------------------------------------===// +// +// ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas +// if possible. +// +FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1, + bool UseDomTree = true); + +//===----------------------------------------------------------------------===// +// +// InductionVariableSimplify - Transform induction variables in a program to all +// use a single canonical induction variable per loop. +// +Pass *createIndVarSimplifyPass(); + +//===----------------------------------------------------------------------===// +// +// InstructionCombining - Combine instructions to form fewer, simple +// instructions. This pass does not modify the CFG, and has a tendency to make +// instructions dead, so a subsequent DCE pass is useful. +// +// This pass combines things like: +// %Y = add int 1, %X +// %Z = add int 1, %Y +// into: +// %Z = add int 2, %X +// +FunctionPass *createInstructionCombiningPass(); + +//===----------------------------------------------------------------------===// +// +// LICM - This pass is a loop invariant code motion and memory promotion pass. +// +Pass *createLICMPass(); + +//===----------------------------------------------------------------------===// +// +// LoopStrengthReduce - This pass is strength reduces GEP instructions that use +// a loop's canonical induction variable as one of their indices. It takes an +// optional parameter used to consult the target machine whether certain +// transformations are profitable. +// +Pass *createLoopStrengthReducePass(const TargetLowering *TLI = 0); + +//===----------------------------------------------------------------------===// +// +// LoopUnswitch - This pass is a simple loop unswitching pass. +// +Pass *createLoopUnswitchPass(bool OptimizeForSize = false); + +//===----------------------------------------------------------------------===// +// +// LoopInstSimplify - This pass simplifies instructions in a loop's body. +// +Pass *createLoopInstSimplifyPass(); + +//===----------------------------------------------------------------------===// +// +// LoopUnroll - This pass is a simple loop unrolling pass. +// +Pass *createLoopUnrollPass(); + +//===----------------------------------------------------------------------===// +// +// LoopRotate - This pass is a simple loop rotating pass. +// +Pass *createLoopRotatePass(); + +//===----------------------------------------------------------------------===// +// +// LoopIdiom - This pass recognizes and replaces idioms in loops. +// +Pass *createLoopIdiomPass(); + +//===----------------------------------------------------------------------===// +// +// PromoteMemoryToRegister - This pass is used to promote memory references to +// be register references. A simple example of the transformation performed by +// this pass is: +// +// FROM CODE TO CODE +// %X = alloca i32, i32 1 ret i32 42 +// store i32 42, i32 *%X +// %Y = load i32* %X +// ret i32 %Y +// +FunctionPass *createPromoteMemoryToRegisterPass(); + +//===----------------------------------------------------------------------===// +// +// DemoteRegisterToMemoryPass - This pass is used to demote registers to memory +// references. In basically undoes the PromoteMemoryToRegister pass to make cfg +// hacking easier. +// +FunctionPass *createDemoteRegisterToMemoryPass(); +extern char &DemoteRegisterToMemoryID; + +//===----------------------------------------------------------------------===// +// +// Reassociate - This pass reassociates commutative expressions in an order that +// is designed to promote better constant propagation, GCSE, LICM, PRE... +// +// For example: 4 + (x + 5) -> x + (4 + 5) +// +FunctionPass *createReassociatePass(); + +//===----------------------------------------------------------------------===// +// +// TailDuplication - Eliminate unconditional branches through controlled code +// duplication, creating simpler CFG structures. +// +FunctionPass *createTailDuplicationPass(); + +//===----------------------------------------------------------------------===// +// +// JumpThreading - Thread control through mult-pred/multi-succ blocks where some +// preds always go to some succ. +// +FunctionPass *createJumpThreadingPass(); + +//===----------------------------------------------------------------------===// +// +// CFGSimplification - Merge basic blocks, eliminate unreachable blocks, +// simplify terminator instructions, etc... +// +FunctionPass *createCFGSimplificationPass(); + +//===----------------------------------------------------------------------===// +// +// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting +// a dummy basic block. This pass may be "required" by passes that cannot deal +// with critical edges. For this usage, a pass must call: +// +// AU.addRequiredID(BreakCriticalEdgesID); +// +// This pass obviously invalidates the CFG, but can update forward dominator +// (set, immediate dominators, tree, and frontier) information. +// +FunctionPass *createBreakCriticalEdgesPass(); +extern char &BreakCriticalEdgesID; + +//===----------------------------------------------------------------------===// +// +// LoopSimplify - Insert Pre-header blocks into the CFG for every function in +// the module. This pass updates dominator information, loop information, and +// does not add critical edges to the CFG. +// +// AU.addRequiredID(LoopSimplifyID); +// +Pass *createLoopSimplifyPass(); +extern char &LoopSimplifyID; + +//===----------------------------------------------------------------------===// +// +// TailCallElimination - This pass eliminates call instructions to the current +// function which occur immediately before return instructions. +// +FunctionPass *createTailCallEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// LowerSwitch - This pass converts SwitchInst instructions into a sequence of +// chained binary branch instructions. +// +FunctionPass *createLowerSwitchPass(); +extern char &LowerSwitchID; + +//===----------------------------------------------------------------------===// +// +// LowerInvoke - This pass converts invoke and unwind instructions to use sjlj +// exception handling mechanisms. Note that after this pass runs the CFG is not +// entirely accurate (exceptional control flow edges are not correct anymore) so +// only very simple things should be done after the lowerinvoke pass has run +// (like generation of native code). This should *NOT* be used as a general +// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet" +// lowering pass. +// +FunctionPass *createLowerInvokePass(const TargetLowering *TLI = 0); +FunctionPass *createLowerInvokePass(const TargetLowering *TLI, + bool useExpensiveEHSupport); +extern char &LowerInvokePassID; + +//===----------------------------------------------------------------------===// +// +// BlockPlacement - This pass reorders basic blocks in order to increase the +// number of fall-through conditional branches. +// +FunctionPass *createBlockPlacementPass(); + +//===----------------------------------------------------------------------===// +// +// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop +// optimizations. +// +Pass *createLCSSAPass(); +extern char &LCSSAID; + +//===----------------------------------------------------------------------===// +// +// EarlyCSE - This pass performs a simple and fast CSE pass over the dominator +// tree. +// +FunctionPass *createEarlyCSEPass(); + +//===----------------------------------------------------------------------===// +// +// GVN - This pass performs global value numbering and redundant load +// elimination cotemporaneously. +// +FunctionPass *createGVNPass(bool NoLoads = false); + +//===----------------------------------------------------------------------===// +// +// MemCpyOpt - This pass performs optimizations related to eliminating memcpy +// calls and/or combining multiple stores into memset's. +// +FunctionPass *createMemCpyOptPass(); + +//===----------------------------------------------------------------------===// +// +// LoopDeletion - This pass performs DCE of non-infinite loops that it +// can prove are dead. +// +Pass *createLoopDeletionPass(); + +//===----------------------------------------------------------------------===// +// +/// createSimplifyLibCallsPass - This pass optimizes specific calls to +/// specific well-known (library) functions. +FunctionPass *createSimplifyLibCallsPass(); + +//===----------------------------------------------------------------------===// +// +// CodeGenPrepare - This pass prepares a function for instruction selection. +// +FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); + +//===----------------------------------------------------------------------===// +// +// InstructionNamer - Give any unnamed non-void instructions "tmp" names. +// +FunctionPass *createInstructionNamerPass(); +extern char &InstructionNamerID; + +//===----------------------------------------------------------------------===// +// +// GEPSplitter - Split complex GEPs into simple ones +// +FunctionPass *createGEPSplitterPass(); + +//===----------------------------------------------------------------------===// +// +// Sink - Code Sinking +// +FunctionPass *createSinkingPass(); + +//===----------------------------------------------------------------------===// +// +// LowerAtomic - Lower atomic intrinsics to non-atomic form +// +Pass *createLowerAtomicPass(); + +//===----------------------------------------------------------------------===// +// +// ValuePropagation - Propagate CFG-derived value information +// +Pass *createCorrelatedValuePropagationPass(); + +//===----------------------------------------------------------------------===// +// +// InstructionSimplifier - Remove redundant instructions. +// +FunctionPass *createInstructionSimplifierPass(); +extern char &InstructionSimplifierID; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/AddrModeMatcher.h b/final/include/llvm/Transforms/Utils/AddrModeMatcher.h new file mode 100644 index 00000000000..0678eccb5d6 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/AddrModeMatcher.h @@ -0,0 +1,108 @@ +//===- AddrModeMatcher.h - Addressing mode matching facility ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AddressingModeMatcher - This class exposes a single public method, which is +// used to construct a "maximal munch" of the addressing mode for the target +// specified by TLI for an access to "V" with an access type of AccessTy. This +// returns the addressing mode that is actually matched by value, but also +// returns the list of instructions involved in that addressing computation in +// AddrModeInsts. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H +#define LLVM_TRANSFORMS_UTILS_ADDRMODEMATCHER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + +class GlobalValue; +class Instruction; +class Value; +class Type; +class User; +class raw_ostream; + +/// ExtAddrMode - This is an extended version of TargetLowering::AddrMode +/// which holds actual Value*'s for register values. +struct ExtAddrMode : public TargetLowering::AddrMode { + Value *BaseReg; + Value *ScaledReg; + ExtAddrMode() : BaseReg(0), ScaledReg(0) {} + void print(raw_ostream &OS) const; + void dump() const; + + bool operator==(const ExtAddrMode& O) const { + return (BaseReg == O.BaseReg) && (ScaledReg == O.ScaledReg) && + (BaseGV == O.BaseGV) && (BaseOffs == O.BaseOffs) && + (HasBaseReg == O.HasBaseReg) && (Scale == O.Scale); + } +}; + +static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { + AM.print(OS); + return OS; +} + +class AddressingModeMatcher { + SmallVectorImpl &AddrModeInsts; + const TargetLowering &TLI; + + /// AccessTy/MemoryInst - This is the type for the access (e.g. double) and + /// the memory instruction that we're computing this address for. + const Type *AccessTy; + Instruction *MemoryInst; + + /// AddrMode - This is the addressing mode that we're building up. This is + /// part of the return value of this addressing mode matching stuff. + ExtAddrMode &AddrMode; + + /// IgnoreProfitability - This is set to true when we should not do + /// profitability checks. When true, IsProfitableToFoldIntoAddressingMode + /// always returns true. + bool IgnoreProfitability; + + AddressingModeMatcher(SmallVectorImpl &AMI, + const TargetLowering &T, const Type *AT, + Instruction *MI, ExtAddrMode &AM) + : AddrModeInsts(AMI), TLI(T), AccessTy(AT), MemoryInst(MI), AddrMode(AM) { + IgnoreProfitability = false; + } +public: + + /// Match - Find the maximal addressing mode that a load/store of V can fold, + /// give an access type of AccessTy. This returns a list of involved + /// instructions in AddrModeInsts. + static ExtAddrMode Match(Value *V, const Type *AccessTy, + Instruction *MemoryInst, + SmallVectorImpl &AddrModeInsts, + const TargetLowering &TLI) { + ExtAddrMode Result; + + bool Success = + AddressingModeMatcher(AddrModeInsts, TLI, AccessTy, + MemoryInst, Result).MatchAddr(V, 0); + (void)Success; assert(Success && "Couldn't select *anything*?"); + return Result; + } +private: + bool MatchScaledValue(Value *ScaleReg, int64_t Scale, unsigned Depth); + bool MatchAddr(Value *V, unsigned Depth); + bool MatchOperationAddr(User *Operation, unsigned Opcode, unsigned Depth); + bool IsProfitableToFoldIntoAddressingMode(Instruction *I, + ExtAddrMode &AMBefore, + ExtAddrMode &AMAfter); + bool ValueAlreadyLiveAtInst(Value *Val, Value *KnownLive1, Value *KnownLive2); +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/BasicBlockUtils.h b/final/include/llvm/Transforms/Utils/BasicBlockUtils.h new file mode 100644 index 00000000000..53358602870 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -0,0 +1,186 @@ +//===-- Transform/Utils/BasicBlockUtils.h - BasicBlock Utils ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform manipulations on basic blocks, and +// instructions contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_BASICBLOCK_H +#define LLVM_TRANSFORMS_UTILS_BASICBLOCK_H + +// FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock + +#include "llvm/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class AliasAnalysis; +class Instruction; +class Pass; +class ReturnInst; + +/// DeleteDeadBlock - Delete the specified block, which must have no +/// predecessors. +void DeleteDeadBlock(BasicBlock *BB); + + +/// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are +/// any single-entry PHI nodes in it, fold them away. This handles the case +/// when all entries to the PHI nodes in a block are guaranteed equal, such as +/// when the block has exactly one predecessor. +void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = 0); + +/// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it +/// is dead. Also recursively delete any operands that become dead as +/// a result. This includes tracing the def-use list from the PHI to see if +/// it is ultimately unused or if it reaches an unused cycle. Return true +/// if any PHIs were deleted. +bool DeleteDeadPHIs(BasicBlock *BB); + +/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, +/// if possible. The return value indicates success or failure. +bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = 0); + +// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) +// with a value, then remove and delete the original instruction. +// +void ReplaceInstWithValue(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Value *V); + +// ReplaceInstWithInst - Replace the instruction specified by BI with the +// instruction specified by I. The original instruction is deleted and BI is +// updated to point to the new instruction. +// +void ReplaceInstWithInst(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Instruction *I); + +// ReplaceInstWithInst - Replace the instruction specified by From with the +// instruction specified by To. +// +void ReplaceInstWithInst(Instruction *From, Instruction *To); + +/// FindFunctionBackedges - Analyze the specified function to find all of the +/// loop backedges in the function and return them. This is a relatively cheap +/// (compared to computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of edge info. +void FindFunctionBackedges(const Function &F, + SmallVectorImpl > &Result); + + +/// GetSuccessorNumber - Search for the specified successor of basic block BB +/// and return its position in the terminator instruction's list of +/// successors. It is an error to call this with a block that is not a +/// successor. +unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ); + +/// isCriticalEdge - Return true if the specified edge is a critical edge. +/// Critical edges are edges from a block with multiple successors to a block +/// with multiple predecessors. +/// +bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, + bool AllowIdenticalEdges = false); + +/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to +/// split the critical edge. This will update DominatorTree and +/// DominatorFrontier information if it is available, thus calling this pass +/// will not invalidate either of them. This returns the new block if the edge +/// was split, null otherwise. +/// +/// If MergeIdenticalEdges is true (not the default), *all* edges from TI to the +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may +/// have many edges to any one destination. This ensures that all edges to that +/// dest go to one block instead of each going to a different block, but isn't +/// the standard definition of a "critical edge". +/// +/// It is invalid to call this function on a critical edge that starts at an +/// IndirectBrInst. Splitting these edges will almost always create an invalid +/// program because the address of the new block won't be the one that is jumped +/// to. +/// +BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, + Pass *P = 0, bool MergeIdenticalEdges = false); + +inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, + Pass *P = 0) { + return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); +} + +/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return +/// false. Otherwise, split all edges between the two blocks and return true. +/// This updates all of the same analyses as the other SplitCriticalEdge +/// function. If P is specified, it updates the analyses +/// described above. +inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { + bool MadeChange = false; + TerminatorInst *TI = (*PI)->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == Succ) + MadeChange |= !!SplitCriticalEdge(TI, i, P); + return MadeChange; +} + +/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge +/// and return true, otherwise return false. This method requires that there be +/// an edge between the two blocks. If P is specified, it updates the analyses +/// described above. +inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, + Pass *P = 0, + bool MergeIdenticalEdges = false) { + TerminatorInst *TI = Src->getTerminator(); + unsigned i = 0; + while (1) { + assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); + if (TI->getSuccessor(i) == Dst) + return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges); + ++i; + } +} + +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. +BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); + +/// SplitBlock - Split the specified block at the specified instruction - every +/// thing before SplitPt stays in Old and everything starting with SplitPt moves +/// to a new block. The two blocks are joined by an unconditional branch and +/// the loop info is updated. +/// +BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); + +/// SplitBlockPredecessors - This method transforms BB by introducing a new +/// basic block into the function, and moving some of the predecessors of BB to +/// be predecessors of the new block. The new predecessors are indicated by the +/// Preds array, which has NumPreds elements in it. The new block is given a +/// suffix of 'Suffix'. This function returns the new block. +/// +/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree, +/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses. +/// In particular, it does not preserve LoopSimplify (because it's +/// complicated to handle the case where one of the edges being split +/// is an exit of a loop with other exits). +/// +BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds, + unsigned NumPreds, const char *Suffix, + Pass *P = 0); + +/// FoldReturnIntoUncondBranch - This method duplicates the specified return +/// instruction into a predecessor which ends in an unconditional branch. If +/// the return instruction returns a value defined by a PHI, propagate the +/// right value into the return. It returns the new return instruction in the +/// predecessor. +ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, + BasicBlock *Pred); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/BasicInliner.h b/final/include/llvm/Transforms/Utils/BasicInliner.h new file mode 100644 index 00000000000..4bca6b8c441 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/BasicInliner.h @@ -0,0 +1,55 @@ +//===- BasicInliner.h - Basic function level inliner ------------*- 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 simple function based inliner that does not use +// call graph information. +// +//===----------------------------------------------------------------------===// + +#ifndef BASICINLINER_H +#define BASICINLINER_H + +#include "llvm/Analysis/InlineCost.h" + +namespace llvm { + + class Function; + class TargetData; + struct BasicInlinerImpl; + + /// BasicInliner - BasicInliner provides function level inlining interface. + /// Clients provide list of functions which are inline without using + /// module level call graph information. Note that the BasicInliner is + /// free to delete a function if it is inlined into all call sites. + class BasicInliner { + public: + + explicit BasicInliner(TargetData *T = NULL); + ~BasicInliner(); + + /// addFunction - Add function into the list of functions to process. + /// All functions must be inserted using this interface before invoking + /// inlineFunctions(). + void addFunction(Function *F); + + /// neverInlineFunction - Sometimes a function is never to be inlined + /// because of one or other reason. + void neverInlineFunction(Function *F); + + /// inlineFuctions - Walk all call sites in all functions supplied by + /// client. Inline as many call sites as possible. Delete completely + /// inlined functions. + void inlineFunctions(); + + private: + BasicInlinerImpl *Impl; + }; +} + +#endif diff --git a/final/include/llvm/Transforms/Utils/BuildLibCalls.h b/final/include/llvm/Transforms/Utils/BuildLibCalls.h new file mode 100644 index 00000000000..e8259383846 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -0,0 +1,110 @@ +//===- BuildLibCalls.h - Utility builder for libcalls -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an interface to build some C language libcalls for +// optimization passes that need to call the various functions. +// +//===----------------------------------------------------------------------===// + +#ifndef TRANSFORMS_UTILS_BUILDLIBCALLS_H +#define TRANSFORMS_UTILS_BUILDLIBCALLS_H + +#include "llvm/Support/IRBuilder.h" + +namespace llvm { + class Value; + class TargetData; + + /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. + Value *CastToCStr(Value *V, IRBuilder<> &B); + + /// EmitStrLen - Emit a call to the strlen function to the builder, for the + /// specified pointer. Ptr is required to be some pointer type, and the + /// return value has 'intptr_t' type. + Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD); + + /// EmitStrChr - Emit a call to the strchr function to the builder, for the + /// specified pointer and character. Ptr is required to be some pointer type, + /// and the return value has 'i8*' type. + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD); + + /// EmitStrNCmp - Emit a call to the strncmp function to the builder. + Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const TargetData *TD); + + /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the + /// specified pointer arguments. + Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + const TargetData *TD, StringRef Name = "strcpy"); + + /// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the + /// specified pointer arguments and length. + Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B, + const TargetData *TD, StringRef Name = "strncpy"); + + /// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. + /// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src + /// are pointers. + Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, + IRBuilder<> &B, const TargetData *TD); + + /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is + /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. + Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B, + const TargetData *TD); + + /// EmitMemCmp - Emit a call to the memcmp function. + Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B, + const TargetData *TD); + + /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' + /// (e.g. 'floor'). This function is known to take a single of type matching + /// 'Op' and returns one value with the same type. If 'Op' is a long double, + /// 'l' is added as the suffix of name, if 'Op' is a float, we add a 'f' + /// suffix. + Value *EmitUnaryFloatFnCall(Value *Op, const char *Name, IRBuilder<> &B, + const AttrListPtr &Attrs); + + /// EmitPutChar - Emit a call to the putchar function. This assumes that Char + /// is an integer. + Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD); + + /// EmitPutS - Emit a call to the puts function. This assumes that Str is + /// some pointer. + void EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD); + + /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is + /// an i32, and File is a pointer to FILE. + void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, + const TargetData *TD); + + /// EmitFPutS - Emit a call to the puts function. Str is required to be a + /// pointer and File is a pointer to FILE. + void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD); + + /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is + /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. + void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, + const TargetData *TD); + + /// SimplifyFortifiedLibCalls - Helper class for folding checked library + /// calls (e.g. __strcpy_chk) into their unchecked counterparts. + class SimplifyFortifiedLibCalls { + protected: + CallInst *CI; + virtual void replaceCall(Value *With) = 0; + virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp, + bool isString) const = 0; + public: + virtual ~SimplifyFortifiedLibCalls(); + bool fold(CallInst *CI, const TargetData *TD); + }; +} + +#endif diff --git a/final/include/llvm/Transforms/Utils/Cloning.h b/final/include/llvm/Transforms/Utils/Cloning.h new file mode 100644 index 00000000000..24ebb109a0a --- /dev/null +++ b/final/include/llvm/Transforms/Utils/Cloning.h @@ -0,0 +1,219 @@ +//===- Cloning.h - Clone various parts of LLVM programs ---------*- 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 various functions that are used to clone chunks of LLVM +// code for various purposes. This varies from copying whole modules into new +// modules, to cloning functions with different arguments, to inlining +// functions, to copying basic blocks to support loop unrolling or superblock +// formation, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CLONING_H +#define LLVM_TRANSFORMS_UTILS_CLONING_H + +#include "llvm/ADT/ValueMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Transforms/Utils/ValueMapper.h" + +namespace llvm { + +class Module; +class Function; +class Instruction; +class Pass; +class LPPassManager; +class BasicBlock; +class Value; +class CallInst; +class InvokeInst; +class ReturnInst; +class CallSite; +class Trace; +class CallGraph; +class TargetData; +class Loop; +class LoopInfo; +class AllocaInst; + +/// CloneModule - Return an exact copy of the specified module +/// +Module *CloneModule(const Module *M); +Module *CloneModule(const Module *M, ValueToValueMapTy &VMap); + +/// ClonedCodeInfo - This struct can be used to capture information about code +/// being cloned, while it is being cloned. +struct ClonedCodeInfo { + /// ContainsCalls - This is set to true if the cloned code contains a normal + /// call instruction. + bool ContainsCalls; + + /// ContainsUnwinds - This is set to true if the cloned code contains an + /// unwind instruction. + bool ContainsUnwinds; + + /// ContainsDynamicAllocas - This is set to true if the cloned code contains + /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in + /// the entry block or they are in the entry block but are not a constant + /// size. + bool ContainsDynamicAllocas; + + ClonedCodeInfo() { + ContainsCalls = false; + ContainsUnwinds = false; + ContainsDynamicAllocas = false; + } +}; + + +/// CloneBasicBlock - Return a copy of the specified basic block, but without +/// embedding the block into a particular function. The block returned is an +/// exact copy of the specified basic block, without any remapping having been +/// performed. Because of this, this is only suitable for applications where +/// the basic block will be inserted into the same function that it was cloned +/// from (loop unrolling would use this, for example). +/// +/// Also, note that this function makes a direct copy of the basic block, and +/// can thus produce illegal LLVM code. In particular, it will copy any PHI +/// nodes from the original block, even though there are no predecessors for the +/// newly cloned block (thus, phi nodes will have to be updated). Also, this +/// block will branch to the old successors of the original block: these +/// successors will have to have any PHI nodes updated to account for the new +/// incoming edges. +/// +/// The correlation between instructions in the source and result basic blocks +/// is recorded in the VMap map. +/// +/// If you have a particular suffix you'd like to use to add to any cloned +/// names, specify it as the optional third parameter. +/// +/// If you would like the basic block to be auto-inserted into the end of a +/// function, you can specify it as the optional fourth parameter. +/// +/// If you would like to collect additional information about the cloned +/// function, you can specify a ClonedCodeInfo object with the optional fifth +/// parameter. +/// +BasicBlock *CloneBasicBlock(const BasicBlock *BB, + ValueToValueMapTy &VMap, + const Twine &NameSuffix = "", Function *F = 0, + ClonedCodeInfo *CodeInfo = 0); + + +/// CloneLoop - Clone Loop. Clone dominator info for loop insiders. Populate +/// VMap using old blocks to new blocks mapping. +Loop *CloneLoop(Loop *L, LPPassManager *LPM, LoopInfo *LI, + ValueToValueMapTy &VMap, Pass *P); + +/// CloneFunction - Return a copy of the specified function, but without +/// embedding the function into another module. Also, any references specified +/// in the VMap are changed to refer to their mapped value instead of the +/// original one. If any of the arguments to the function are in the VMap, +/// the arguments are deleted from the resultant function. The VMap is +/// updated to include mappings from all of the instructions and basicblocks in +/// the function from their old to new values. The final argument captures +/// information about the cloned code if non-null. +/// +/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue +/// mappings. +/// +Function *CloneFunction(const Function *F, + ValueToValueMapTy &VMap, + bool ModuleLevelChanges, + ClonedCodeInfo *CodeInfo = 0); + +/// CloneFunction - Version of the function that doesn't need the VMap. +/// +inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ + ValueToValueMapTy VMap; + return CloneFunction(F, VMap, CodeInfo); +} + +/// Clone OldFunc into NewFunc, transforming the old arguments into references +/// to VMap values. Note that if NewFunc already has basic blocks, the ones +/// cloned into it will be added to the end of the function. This function +/// fills in a list of return instructions, and can optionally append the +/// specified suffix to all values cloned. +/// +/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue +/// mappings. +/// +void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap, + bool ModuleLevelChanges, + SmallVectorImpl &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0); + +/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, +/// except that it does some simple constant prop and DCE on the fly. The +/// effect of this is to copy significantly less code in cases where (for +/// example) a function call with constant arguments is inlined, and those +/// constant arguments cause a significant amount of code in the callee to be +/// dead. Since this doesn't produce an exactly copy of the input, it can't be +/// used for things like CloneFunction or CloneModule. +/// +/// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue +/// mappings. +/// +void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap, + bool ModuleLevelChanges, + SmallVectorImpl &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0, + const TargetData *TD = 0, + Instruction *TheCall = 0); + + +/// InlineFunctionInfo - This class captures the data input to the +/// InlineFunction call, and records the auxiliary results produced by it. +class InlineFunctionInfo { +public: + explicit InlineFunctionInfo(CallGraph *cg = 0, const TargetData *td = 0) + : CG(cg), TD(td) {} + + /// CG - If non-null, InlineFunction will update the callgraph to reflect the + /// changes it makes. + CallGraph *CG; + const TargetData *TD; + + /// StaticAllocas - InlineFunction fills this in with all static allocas that + /// get copied into the caller. + SmallVector StaticAllocas; + + /// InlinedCalls - InlineFunction fills this in with callsites that were + /// inlined from the callee. This is only filled in if CG is non-null. + SmallVector InlinedCalls; + + void reset() { + StaticAllocas.clear(); + InlinedCalls.clear(); + } +}; + +/// InlineFunction - This function inlines the called function into the basic +/// block of the caller. This returns false if it is not possible to inline +/// this call. The program is still in a well defined state if this occurs +/// though. +/// +/// Note that this only does one level of inlining. For example, if the +/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now +/// exists in the instruction stream. Similiarly this will inline a recursive +/// function by one level. +/// +bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI); +bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI); +bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/FunctionUtils.h b/final/include/llvm/Transforms/Utils/FunctionUtils.h new file mode 100644 index 00000000000..785b08f8291 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/FunctionUtils.h @@ -0,0 +1,41 @@ +//===-- Transform/Utils/FunctionUtils.h - Function Utils --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of transformations manipulate LLVM functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H +#define LLVM_TRANSFORMS_UTILS_FUNCTION_H + +#include + +namespace llvm { + class BasicBlock; + class DominatorTree; + class Function; + class Loop; + + /// ExtractCodeRegion - rip out a sequence of basic blocks into a new function + /// + Function* ExtractCodeRegion(DominatorTree& DT, + const std::vector &code, + bool AggregateArgs = false); + + /// ExtractLoop - rip out a natural loop into a new function + /// + Function* ExtractLoop(DominatorTree& DT, Loop *L, + bool AggregateArgs = false); + + /// ExtractBasicBlock - rip out a basic block into a new function + /// + Function* ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs = false); +} + +#endif diff --git a/final/include/llvm/Transforms/Utils/Local.h b/final/include/llvm/Transforms/Utils/Local.h new file mode 100644 index 00000000000..2823fbb7199 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/Local.h @@ -0,0 +1,162 @@ +//===-- Local.h - Functions to perform local transformations ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform various local transformations to the +// program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H +#define LLVM_TRANSFORMS_UTILS_LOCAL_H + +namespace llvm { + +class User; +class BasicBlock; +class BranchInst; +class Instruction; +class Value; +class Pass; +class PHINode; +class AllocaInst; +class ConstantExpr; +class TargetData; + +template class SmallVectorImpl; + +//===----------------------------------------------------------------------===// +// Local constant propagation. +// + +/// ConstantFoldTerminator - If a terminator instruction is predicated on a +/// constant value, convert it into an unconditional branch to the constant +/// destination. This is a nontrivial operation because the successors of this +/// basic block must have their PHI nodes updated. +/// +bool ConstantFoldTerminator(BasicBlock *BB); + +//===----------------------------------------------------------------------===// +// Local dead code elimination. +// + +/// isInstructionTriviallyDead - Return true if the result produced by the +/// instruction is not used, and the instruction has no side effects. +/// +bool isInstructionTriviallyDead(Instruction *I); + +/// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is a +/// trivially dead instruction, delete it. If that makes any of its operands +/// trivially dead, delete them too, recursively. Return true if any +/// instructions were deleted. +bool RecursivelyDeleteTriviallyDeadInstructions(Value *V); + +/// RecursivelyDeleteDeadPHINode - If the specified value is an effectively +/// dead PHI node, due to being a def-use chain of single-use nodes that +/// either forms a cycle or is terminated by a trivially dead instruction, +/// delete it. If that makes any of its operands trivially dead, delete them +/// too, recursively. Return true if a change was made. +bool RecursivelyDeleteDeadPHINode(PHINode *PN); + + +/// SimplifyInstructionsInBlock - Scan the specified basic block and try to +/// simplify any instructions in it and recursively delete dead instructions. +/// +/// This returns true if it changed the code, note that it can delete +/// instructions in other blocks as well in this block. +/// +/// WARNING: Do not use this function on unreachable blocks, as recursive +/// simplification is not able to handle corner-case scenarios that can +/// arise in them. +bool SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD = 0); + +//===----------------------------------------------------------------------===// +// Control Flow Graph Restructuring. +// + +/// RemovePredecessorAndSimplify - Like BasicBlock::removePredecessor, this +/// method is called when we're about to delete Pred as a predecessor of BB. If +/// BB contains any PHI nodes, this drops the entries in the PHI nodes for Pred. +/// +/// Unlike the removePredecessor method, this attempts to simplify uses of PHI +/// nodes that collapse into identity values. For example, if we have: +/// x = phi(1, 0, 0, 0) +/// y = and x, z +/// +/// .. and delete the predecessor corresponding to the '1', this will attempt to +/// recursively fold the 'and' to 0. +void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, + TargetData *TD = 0); + + +/// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its +/// predecessor is known to have one successor (BB!). Eliminate the edge +/// between them, moving the instructions in the predecessor into BB. This +/// deletes the predecessor block. +/// +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = 0); + + +/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an +/// unconditional branch, and contains no instructions other than PHI nodes, +/// potential debug intrinsics and the branch. If possible, eliminate BB by +/// rewriting all the predecessors to branch to the successor block and return +/// true. If we can't transform, return false. +bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB); + +/// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI +/// nodes in this block. This doesn't try to be clever about PHI nodes +/// which differ only in the order of the incoming values, but instcombine +/// orders them so it usually won't matter. +/// +bool EliminateDuplicatePHINodes(BasicBlock *BB); + +/// SimplifyCFG - This function is used to do simplification of a CFG. For +/// example, it adjusts branches to branches to eliminate the extra hop, it +/// eliminates unreachable basic blocks, and does other "peephole" optimization +/// of the CFG. It returns true if a modification was made, possibly deleting +/// the basic block that was pointed to. +/// +bool SimplifyCFG(BasicBlock *BB, const TargetData *TD = 0); + +/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, +/// and if a predecessor branches to us and one of our successors, fold the +/// setcc into the predecessor and use logical operations to pick the right +/// destination. +bool FoldBranchToCommonDest(BranchInst *BI); + +/// DemoteRegToStack - This function takes a virtual register computed by an +/// Instruction and replaces it with a slot in the stack frame, allocated via +/// alloca. This allows the CFG to be changed around without fear of +/// invalidating the SSA information for the value. It returns the pointer to +/// the alloca inserted to create a stack slot for X. +/// +AllocaInst *DemoteRegToStack(Instruction &X, + bool VolatileLoads = false, + Instruction *AllocaPoint = 0); + +/// DemotePHIToStack - This function takes a virtual register computed by a phi +/// node and replaces it with a slot in the stack frame, allocated via alloca. +/// The phi node is deleted and it returns the pointer to the alloca inserted. +AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); + +/// getOrEnforceKnownAlignment - If the specified pointer has an alignment that +/// we can determine, return it, otherwise return 0. If PrefAlign is specified, +/// and it is more than the alignment of the ultimate object, see if we can +/// increase the alignment of the ultimate object, making this check succeed. +unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, + const TargetData *TD = 0); + +/// getKnownAlignment - Try to infer an alignment for the specified pointer. +static inline unsigned getKnownAlignment(Value *V, const TargetData *TD = 0) { + return getOrEnforceKnownAlignment(V, 0, TD); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/PromoteMemToReg.h b/final/include/llvm/Transforms/Utils/PromoteMemToReg.h new file mode 100644 index 00000000000..98d51a29ad7 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -0,0 +1,45 @@ +//===- PromoteMemToReg.h - Promote Allocas to Scalars -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an interface to promote alloca instructions to SSA +// registers, by using the SSA construction algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef TRANSFORMS_UTILS_PROMOTEMEMTOREG_H +#define TRANSFORMS_UTILS_PROMOTEMEMTOREG_H + +#include + +namespace llvm { + +class AllocaInst; +class DominatorTree; +class DominanceFrontier; +class AliasSetTracker; + +/// isAllocaPromotable - Return true if this alloca is legal for promotion. +/// This is true if there are only loads and stores to the alloca... +/// +bool isAllocaPromotable(const AllocaInst *AI); + +/// PromoteMemToReg - Promote the specified list of alloca instructions into +/// scalar registers, inserting PHI nodes as appropriate. This function makes +/// use of DominanceFrontier information. This function does not modify the CFG +/// of the function at all. All allocas must be from the same function. +/// +/// If AST is specified, the specified tracker is updated to reflect changes +/// made to the IR. +/// +void PromoteMemToReg(const std::vector &Allocas, + DominatorTree &DT, AliasSetTracker *AST = 0); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/SSAUpdater.h b/final/include/llvm/Transforms/Utils/SSAUpdater.h new file mode 100644 index 00000000000..b4048b9b440 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/SSAUpdater.h @@ -0,0 +1,163 @@ +//===-- SSAUpdater.h - Unstructured SSA Update Tool -------------*- 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 SSAUpdater class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATER_H +#define LLVM_TRANSFORMS_UTILS_SSAUPDATER_H + +namespace llvm { + class Value; + class BasicBlock; + class Use; + class PHINode; + template class SmallVectorImpl; + template class SSAUpdaterTraits; + class BumpPtrAllocator; + +/// SSAUpdater - This class updates SSA form for a set of values defined in +/// multiple blocks. This is used when code duplication or another unstructured +/// transformation wants to rewrite a set of uses of one value with uses of a +/// set of values. +class SSAUpdater { + friend class SSAUpdaterTraits; + +private: + /// AvailableVals - This keeps track of which value to use on a per-block + /// basis. When we insert PHI nodes, we keep track of them here. + //typedef DenseMap AvailableValsTy; + void *AV; + + /// ProtoType holds the type of the values being rewritten. + const Type *ProtoType; + + // PHI nodes are given a name based on ProtoName. + std::string ProtoName; + + /// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that + /// it creates to the vector. + SmallVectorImpl *InsertedPHIs; + +public: + /// SSAUpdater constructor. If InsertedPHIs is specified, it will be filled + /// in with all PHI Nodes created by rewriting. + explicit SSAUpdater(SmallVectorImpl *InsertedPHIs = 0); + ~SSAUpdater(); + + /// Initialize - Reset this object to get ready for a new set of SSA + /// updates with type 'Ty'. PHI nodes get a name based on 'Name'. + void Initialize(const Type *Ty, StringRef Name); + + /// AddAvailableValue - Indicate that a rewritten value is available at the + /// end of the specified block with the specified value. + void AddAvailableValue(BasicBlock *BB, Value *V); + + /// HasValueForBlock - Return true if the SSAUpdater already has a value for + /// the specified block. + bool HasValueForBlock(BasicBlock *BB) const; + + /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is + /// live at the end of the specified block. + Value *GetValueAtEndOfBlock(BasicBlock *BB); + + /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that + /// is live in the middle of the specified block. + /// + /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one + /// important case: if there is a definition of the rewritten value after the + /// 'use' in BB. Consider code like this: + /// + /// X1 = ... + /// SomeBB: + /// use(X) + /// X2 = ... + /// br Cond, SomeBB, OutBB + /// + /// In this case, there are two values (X1 and X2) added to the AvailableVals + /// set by the client of the rewriter, and those values are both live out of + /// their respective blocks. However, the use of X happens in the *middle* of + /// a block. Because of this, we need to insert a new PHI node in SomeBB to + /// merge the appropriate values, and this value isn't live out of the block. + /// + Value *GetValueInMiddleOfBlock(BasicBlock *BB); + + /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, + /// which use their value in the corresponding predecessor. Note that this + /// will not work if the use is supposed to be rewritten to a value defined in + /// the same block as the use, but above it. Any 'AddAvailableValue's added + /// for the use's block will be considered to be below it. + void RewriteUse(Use &U); + + /// RewriteUseAfterInsertions - Rewrite a use, just like RewriteUse. However, + /// this version of the method can rewrite uses in the same block as a + /// definition, because it assumes that all uses of a value are below any + /// inserted values. + void RewriteUseAfterInsertions(Use &U); + +private: + Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); + + void operator=(const SSAUpdater&); // DO NOT IMPLEMENT + SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT +}; + +/// LoadAndStorePromoter - This little helper class provides a convenient way to +/// promote a collection of loads and stores into SSA Form using the SSAUpdater. +/// This handles complexities that SSAUpdater doesn't, such as multiple loads +/// and stores in one block. +/// +/// Clients of this class are expected to subclass this and implement the +/// virtual methods. +/// +class LoadAndStorePromoter { +protected: + SSAUpdater &SSA; +public: + LoadAndStorePromoter(const SmallVectorImpl &Insts, + SSAUpdater &S, StringRef Name = StringRef()); + virtual ~LoadAndStorePromoter() {} + + /// run - This does the promotion. Insts is a list of loads and stores to + /// promote, and Name is the basename for the PHIs to insert. After this is + /// complete, the loads and stores are removed from the code. + void run(const SmallVectorImpl &Insts) const; + + + /// Return true if the specified instruction is in the Inst list (which was + /// passed into the run method). Clients should implement this with a more + /// efficient version if possible. + virtual bool isInstInList(Instruction *I, + const SmallVectorImpl &Insts) const { + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + if (Insts[i] == I) + return true; + return false; + } + + /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the + /// stores are found and inserted as available values, but + virtual void doExtraRewritesBeforeFinalDeletion() const { + } + + /// replaceLoadWithValue - Clients can choose to implement this to get + /// notified right before a load is RAUW'd another value. + virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const { + } + + /// This is called before each instruction is deleted. + virtual void instructionDeleted(Instruction *I) const { + } + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/final/include/llvm/Transforms/Utils/SSAUpdaterImpl.h new file mode 100644 index 00000000000..5a03d224ff7 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -0,0 +1,469 @@ +//===-- SSAUpdaterImpl.h - SSA Updater Implementation -----------*- 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 a template that implements the core algorithm for the +// SSAUpdater and MachineSSAUpdater. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H +#define LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H + +namespace llvm { + +template class SSAUpdaterTraits; + +template +class SSAUpdaterImpl { +private: + UpdaterT *Updater; + + typedef SSAUpdaterTraits Traits; + typedef typename Traits::BlkT BlkT; + typedef typename Traits::ValT ValT; + typedef typename Traits::PhiT PhiT; + + /// BBInfo - Per-basic block information used internally by SSAUpdaterImpl. + /// The predecessors of each block are cached here since pred_iterator is + /// slow and we need to iterate over the blocks at least a few times. + class BBInfo { + public: + BlkT *BB; // Back-pointer to the corresponding block. + ValT AvailableVal; // Value to use in this block. + BBInfo *DefBB; // Block that defines the available value. + int BlkNum; // Postorder number. + BBInfo *IDom; // Immediate dominator. + unsigned NumPreds; // Number of predecessor blocks. + BBInfo **Preds; // Array[NumPreds] of predecessor blocks. + PhiT *PHITag; // Marker for existing PHIs that match. + + BBInfo(BlkT *ThisBB, ValT V) + : BB(ThisBB), AvailableVal(V), DefBB(V ? this : 0), BlkNum(0), IDom(0), + NumPreds(0), Preds(0), PHITag(0) { } + }; + + typedef DenseMap AvailableValsTy; + AvailableValsTy *AvailableVals; + + SmallVectorImpl *InsertedPHIs; + + typedef SmallVectorImpl BlockListTy; + typedef DenseMap BBMapTy; + BBMapTy BBMap; + BumpPtrAllocator Allocator; + +public: + explicit SSAUpdaterImpl(UpdaterT *U, AvailableValsTy *A, + SmallVectorImpl *Ins) : + Updater(U), AvailableVals(A), InsertedPHIs(Ins) { } + + /// GetValue - Check to see if AvailableVals has an entry for the specified + /// BB and if so, return it. If not, construct SSA form by first + /// calculating the required placement of PHIs and then inserting new PHIs + /// where needed. + ValT GetValue(BlkT *BB) { + SmallVector BlockList; + BBInfo *PseudoEntry = BuildBlockList(BB, &BlockList); + + // Special case: bail out if BB is unreachable. + if (BlockList.size() == 0) { + ValT V = Traits::GetUndefVal(BB, Updater); + (*AvailableVals)[BB] = V; + return V; + } + + FindDominators(&BlockList, PseudoEntry); + FindPHIPlacement(&BlockList); + FindAvailableVals(&BlockList); + + return BBMap[BB]->DefBB->AvailableVal; + } + + /// BuildBlockList - Starting from the specified basic block, traverse back + /// through its predecessors until reaching blocks with known values. + /// Create BBInfo structures for the blocks and append them to the block + /// list. + BBInfo *BuildBlockList(BlkT *BB, BlockListTy *BlockList) { + SmallVector RootList; + SmallVector WorkList; + + BBInfo *Info = new (Allocator) BBInfo(BB, 0); + BBMap[BB] = Info; + WorkList.push_back(Info); + + // Search backward from BB, creating BBInfos along the way and stopping + // when reaching blocks that define the value. Record those defining + // blocks on the RootList. + SmallVector Preds; + while (!WorkList.empty()) { + Info = WorkList.pop_back_val(); + Preds.clear(); + Traits::FindPredecessorBlocks(Info->BB, &Preds); + Info->NumPreds = Preds.size(); + if (Info->NumPreds == 0) + Info->Preds = 0; + else + Info->Preds = static_cast + (Allocator.Allocate(Info->NumPreds * sizeof(BBInfo*), + AlignOf::Alignment)); + + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BlkT *Pred = Preds[p]; + // Check if BBMap already has a BBInfo for the predecessor block. + typename BBMapTy::value_type &BBMapBucket = + BBMap.FindAndConstruct(Pred); + if (BBMapBucket.second) { + Info->Preds[p] = BBMapBucket.second; + continue; + } + + // Create a new BBInfo for the predecessor. + ValT PredVal = AvailableVals->lookup(Pred); + BBInfo *PredInfo = new (Allocator) BBInfo(Pred, PredVal); + BBMapBucket.second = PredInfo; + Info->Preds[p] = PredInfo; + + if (PredInfo->AvailableVal) { + RootList.push_back(PredInfo); + continue; + } + WorkList.push_back(PredInfo); + } + } + + // Now that we know what blocks are backwards-reachable from the starting + // block, do a forward depth-first traversal to assign postorder numbers + // to those blocks. + BBInfo *PseudoEntry = new (Allocator) BBInfo(0, 0); + unsigned BlkNum = 1; + + // Initialize the worklist with the roots from the backward traversal. + while (!RootList.empty()) { + Info = RootList.pop_back_val(); + Info->IDom = PseudoEntry; + Info->BlkNum = -1; + WorkList.push_back(Info); + } + + while (!WorkList.empty()) { + Info = WorkList.back(); + + if (Info->BlkNum == -2) { + // All the successors have been handled; assign the postorder number. + Info->BlkNum = BlkNum++; + // If not a root, put it on the BlockList. + if (!Info->AvailableVal) + BlockList->push_back(Info); + WorkList.pop_back(); + continue; + } + + // Leave this entry on the worklist, but set its BlkNum to mark that its + // successors have been put on the worklist. When it returns to the top + // the list, after handling its successors, it will be assigned a + // number. + Info->BlkNum = -2; + + // Add unvisited successors to the work list. + for (typename Traits::BlkSucc_iterator SI = + Traits::BlkSucc_begin(Info->BB), + E = Traits::BlkSucc_end(Info->BB); SI != E; ++SI) { + BBInfo *SuccInfo = BBMap[*SI]; + if (!SuccInfo || SuccInfo->BlkNum) + continue; + SuccInfo->BlkNum = -1; + WorkList.push_back(SuccInfo); + } + } + PseudoEntry->BlkNum = BlkNum; + return PseudoEntry; + } + + /// IntersectDominators - This is the dataflow lattice "meet" operation for + /// finding dominators. Given two basic blocks, it walks up the dominator + /// tree until it finds a common dominator of both. It uses the postorder + /// number of the blocks to determine how to do that. + BBInfo *IntersectDominators(BBInfo *Blk1, BBInfo *Blk2) { + while (Blk1 != Blk2) { + while (Blk1->BlkNum < Blk2->BlkNum) { + Blk1 = Blk1->IDom; + if (!Blk1) + return Blk2; + } + while (Blk2->BlkNum < Blk1->BlkNum) { + Blk2 = Blk2->IDom; + if (!Blk2) + return Blk1; + } + } + return Blk1; + } + + /// FindDominators - Calculate the dominator tree for the subset of the CFG + /// corresponding to the basic blocks on the BlockList. This uses the + /// algorithm from: "A Simple, Fast Dominance Algorithm" by Cooper, Harvey + /// and Kennedy, published in Software--Practice and Experience, 2001, + /// 4:1-10. Because the CFG subset does not include any edges leading into + /// blocks that define the value, the results are not the usual dominator + /// tree. The CFG subset has a single pseudo-entry node with edges to a set + /// of root nodes for blocks that define the value. The dominators for this + /// subset CFG are not the standard dominators but they are adequate for + /// placing PHIs within the subset CFG. + void FindDominators(BlockListTy *BlockList, BBInfo *PseudoEntry) { + bool Changed; + do { + Changed = false; + // Iterate over the list in reverse order, i.e., forward on CFG edges. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + BBInfo *NewIDom = 0; + + // Iterate through the block's predecessors. + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BBInfo *Pred = Info->Preds[p]; + + // Treat an unreachable predecessor as a definition with 'undef'. + if (Pred->BlkNum == 0) { + Pred->AvailableVal = Traits::GetUndefVal(Pred->BB, Updater); + (*AvailableVals)[Pred->BB] = Pred->AvailableVal; + Pred->DefBB = Pred; + Pred->BlkNum = PseudoEntry->BlkNum; + PseudoEntry->BlkNum++; + } + + if (!NewIDom) + NewIDom = Pred; + else + NewIDom = IntersectDominators(NewIDom, Pred); + } + + // Check if the IDom value has changed. + if (NewIDom && NewIDom != Info->IDom) { + Info->IDom = NewIDom; + Changed = true; + } + } + } while (Changed); + } + + /// IsDefInDomFrontier - Search up the dominator tree from Pred to IDom for + /// any blocks containing definitions of the value. If one is found, then + /// the successor of Pred is in the dominance frontier for the definition, + /// and this function returns true. + bool IsDefInDomFrontier(const BBInfo *Pred, const BBInfo *IDom) { + for (; Pred != IDom; Pred = Pred->IDom) { + if (Pred->DefBB == Pred) + return true; + } + return false; + } + + /// FindPHIPlacement - PHIs are needed in the iterated dominance frontiers + /// of the known definitions. Iteratively add PHIs in the dom frontiers + /// until nothing changes. Along the way, keep track of the nearest + /// dominating definitions for non-PHI blocks. + void FindPHIPlacement(BlockListTy *BlockList) { + bool Changed; + do { + Changed = false; + // Iterate over the list in reverse order, i.e., forward on CFG edges. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + + // If this block already needs a PHI, there is nothing to do here. + if (Info->DefBB == Info) + continue; + + // Default to use the same def as the immediate dominator. + BBInfo *NewDefBB = Info->IDom->DefBB; + for (unsigned p = 0; p != Info->NumPreds; ++p) { + if (IsDefInDomFrontier(Info->Preds[p], Info->IDom)) { + // Need a PHI here. + NewDefBB = Info; + break; + } + } + + // Check if anything changed. + if (NewDefBB != Info->DefBB) { + Info->DefBB = NewDefBB; + Changed = true; + } + } + } while (Changed); + } + + /// FindAvailableVal - If this block requires a PHI, first check if an + /// existing PHI matches the PHI placement and reaching definitions computed + /// earlier, and if not, create a new PHI. Visit all the block's + /// predecessors to calculate the available value for each one and fill in + /// the incoming values for a new PHI. + void FindAvailableVals(BlockListTy *BlockList) { + // Go through the worklist in forward order (i.e., backward through the CFG) + // and check if existing PHIs can be used. If not, create empty PHIs where + // they are needed. + for (typename BlockListTy::iterator I = BlockList->begin(), + E = BlockList->end(); I != E; ++I) { + BBInfo *Info = *I; + // Check if there needs to be a PHI in BB. + if (Info->DefBB != Info) + continue; + + // Look for an existing PHI. + FindExistingPHI(Info->BB, BlockList); + if (Info->AvailableVal) + continue; + + ValT PHI = Traits::CreateEmptyPHI(Info->BB, Info->NumPreds, Updater); + Info->AvailableVal = PHI; + (*AvailableVals)[Info->BB] = PHI; + } + + // Now go back through the worklist in reverse order to fill in the + // arguments for any new PHIs added in the forward traversal. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + + if (Info->DefBB != Info) { + // Record the available value at join nodes to speed up subsequent + // uses of this SSAUpdater for the same value. + if (Info->NumPreds > 1) + (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal; + continue; + } + + // Check if this block contains a newly added PHI. + PhiT *PHI = Traits::ValueIsNewPHI(Info->AvailableVal, Updater); + if (!PHI) + continue; + + // Iterate through the block's predecessors. + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BBInfo *PredInfo = Info->Preds[p]; + BlkT *Pred = PredInfo->BB; + // Skip to the nearest preceding definition. + if (PredInfo->DefBB != PredInfo) + PredInfo = PredInfo->DefBB; + Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred); + } + + DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n"); + + // If the client wants to know about all new instructions, tell it. + if (InsertedPHIs) InsertedPHIs->push_back(PHI); + } + } + + /// FindExistingPHI - Look through the PHI nodes in a block to see if any of + /// them match what is needed. + void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) { + for (typename BlkT::iterator BBI = BB->begin(), BBE = BB->end(); + BBI != BBE; ++BBI) { + PhiT *SomePHI = Traits::InstrIsPHI(BBI); + if (!SomePHI) + break; + if (CheckIfPHIMatches(SomePHI)) { + RecordMatchingPHI(SomePHI); + break; + } + // Match failed: clear all the PHITag values. + for (typename BlockListTy::iterator I = BlockList->begin(), + E = BlockList->end(); I != E; ++I) + (*I)->PHITag = 0; + } + } + + /// CheckIfPHIMatches - Check if a PHI node matches the placement and values + /// in the BBMap. + bool CheckIfPHIMatches(PhiT *PHI) { + SmallVector WorkList; + WorkList.push_back(PHI); + + // Mark that the block containing this PHI has been visited. + BBMap[PHI->getParent()]->PHITag = PHI; + + while (!WorkList.empty()) { + PHI = WorkList.pop_back_val(); + + // Iterate through the PHI's incoming values. + for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), + E = Traits::PHI_end(PHI); I != E; ++I) { + ValT IncomingVal = I.getIncomingValue(); + BBInfo *PredInfo = BBMap[I.getIncomingBlock()]; + // Skip to the nearest preceding definition. + if (PredInfo->DefBB != PredInfo) + PredInfo = PredInfo->DefBB; + + // Check if it matches the expected value. + if (PredInfo->AvailableVal) { + if (IncomingVal == PredInfo->AvailableVal) + continue; + return false; + } + + // Check if the value is a PHI in the correct block. + PhiT *IncomingPHIVal = Traits::ValueIsPHI(IncomingVal, Updater); + if (!IncomingPHIVal || IncomingPHIVal->getParent() != PredInfo->BB) + return false; + + // If this block has already been visited, check if this PHI matches. + if (PredInfo->PHITag) { + if (IncomingPHIVal == PredInfo->PHITag) + continue; + return false; + } + PredInfo->PHITag = IncomingPHIVal; + + WorkList.push_back(IncomingPHIVal); + } + } + return true; + } + + /// RecordMatchingPHI - For a PHI node that matches, record it and its input + /// PHIs in both the BBMap and the AvailableVals mapping. + void RecordMatchingPHI(PhiT *PHI) { + SmallVector WorkList; + WorkList.push_back(PHI); + + // Record this PHI. + BlkT *BB = PHI->getParent(); + ValT PHIVal = Traits::GetPHIValue(PHI); + (*AvailableVals)[BB] = PHIVal; + BBMap[BB]->AvailableVal = PHIVal; + + while (!WorkList.empty()) { + PHI = WorkList.pop_back_val(); + + // Iterate through the PHI's incoming values. + for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), + E = Traits::PHI_end(PHI); I != E; ++I) { + ValT IncomingVal = I.getIncomingValue(); + PhiT *IncomingPHI = Traits::ValueIsPHI(IncomingVal, Updater); + if (!IncomingPHI) continue; + BB = IncomingPHI->getParent(); + BBInfo *Info = BBMap[BB]; + if (!Info || Info->AvailableVal) + continue; + + // Record the PHI and add it to the worklist. + (*AvailableVals)[BB] = IncomingVal; + Info->AvailableVal = IncomingVal; + WorkList.push_back(IncomingPHI); + } + } + } +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/final/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h new file mode 100644 index 00000000000..54506cfff4c --- /dev/null +++ b/final/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -0,0 +1,51 @@ +//===-- UnifyFunctionExitNodes.h - Ensure fn's have one return --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to ensure that functions have at most one return and one +// unwind instruction in them. Additionally, it keeps track of which node is +// the new exit node of the CFG. If there are no return or unwind instructions +// in the function, the getReturnBlock/getUnwindBlock methods will return a null +// pointer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H +#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H + +#include "llvm/Pass.h" + +namespace llvm { + +struct UnifyFunctionExitNodes : public FunctionPass { + BasicBlock *ReturnBlock, *UnwindBlock, *UnreachableBlock; +public: + static char ID; // Pass identification, replacement for typeid + UnifyFunctionExitNodes() : FunctionPass(ID), + ReturnBlock(0), UnwindBlock(0) { + initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry()); + } + + // We can preserve non-critical-edgeness when we unify function exit nodes + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistant) + // return, unwind, or unreachable basic blocks in the CFG. + // + BasicBlock *getReturnBlock() const { return ReturnBlock; } + BasicBlock *getUnwindBlock() const { return UnwindBlock; } + BasicBlock *getUnreachableBlock() const { return UnreachableBlock; } + + virtual bool runOnFunction(Function &F); +}; + +Pass *createUnifyFunctionExitNodesPass(); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Transforms/Utils/UnrollLoop.h b/final/include/llvm/Transforms/Utils/UnrollLoop.h new file mode 100644 index 00000000000..3d5ee1a62b8 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/UnrollLoop.h @@ -0,0 +1,29 @@ +//===- llvm/Transforms/Utils/UnrollLoop.h - Unrolling utilities -*- 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 some loop unrolling utilities. It does not define any +// actual pass or policy, but provides a single function to perform loop +// unrolling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H +#define LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H + +namespace llvm { + +class Loop; +class LoopInfo; +class LPPassManager; + +bool UnrollLoop(Loop *L, unsigned Count, LoopInfo* LI, LPPassManager* LPM); + +} + +#endif diff --git a/final/include/llvm/Transforms/Utils/ValueMapper.h b/final/include/llvm/Transforms/Utils/ValueMapper.h new file mode 100644 index 00000000000..d612213a871 --- /dev/null +++ b/final/include/llvm/Transforms/Utils/ValueMapper.h @@ -0,0 +1,50 @@ +//===- ValueMapper.h - Remapping for constants and metadata -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MapValue interface which is used by various parts of +// the Transforms/Utils library to implement cloning and linking facilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H +#define LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H + +#include "llvm/ADT/ValueMap.h" + +namespace llvm { + class Value; + class Instruction; + typedef ValueMap > ValueToValueMapTy; + + /// RemapFlags - These are flags that the value mapping APIs allow. + enum RemapFlags { + RF_None = 0, + + /// RF_NoModuleLevelChanges - If this flag is set, the remapper knows that + /// only local values within a function (such as an instruction or argument) + /// are mapped, not global values like functions and global metadata. + RF_NoModuleLevelChanges = 1, + + /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores + /// entries that are not in the value map. If it is unset, it aborts if an + /// operand is asked to be remapped which doesn't exist in the mapping. + RF_IgnoreMissingEntries = 2 + }; + + static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) { + return RemapFlags(unsigned(LHS)|unsigned(RHS)); + } + + Value *MapValue(const Value *V, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None); + void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, + RemapFlags Flags = RF_None); +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Type.h b/final/include/llvm/Type.h new file mode 100644 index 00000000000..0939d67265b --- /dev/null +++ b/final/include/llvm/Type.h @@ -0,0 +1,564 @@ +//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TYPE_H +#define LLVM_TYPE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Support/Casting.h" +#include "llvm/ADT/GraphTraits.h" +#include +#include + +namespace llvm { + +class DerivedType; +class PointerType; +class IntegerType; +class TypeMapBase; +class raw_ostream; +class Module; +class LLVMContext; + +/// This file contains the declaration of the Type class. For more "Type" type +/// stuff, look in DerivedTypes.h. +/// +/// The instances of the Type class are immutable: once they are created, +/// they are never changed. Also note that only one instance of a particular +/// type is ever created. Thus seeing if two types are equal is a matter of +/// doing a trivial pointer comparison. To enforce that no two equal instances +/// are created, Type instances can only be created via static factory methods +/// in class Type and in derived classes. +/// +/// Once allocated, Types are never free'd, unless they are an abstract type +/// that is resolved to a more concrete type. +/// +/// Types themself don't have a name, and can be named either by: +/// - using SymbolTable instance, typically from some Module, +/// - using convenience methods in the Module class (which uses module's +/// SymbolTable too). +/// +/// Opaque types are simple derived types with no state. There may be many +/// different Opaque type objects floating around, but two are only considered +/// identical if they are pointer equals of each other. This allows us to have +/// two opaque types that end up resolving to different concrete types later. +/// +/// Opaque types are also kinda weird and scary and different because they have +/// to keep a list of uses of the type. When, through linking, parsing, or +/// bitcode reading, they become resolved, they need to find and update all +/// users of the unknown type, causing them to reference a new, more concrete +/// type. Opaque types are deleted when their use list dwindles to zero users. +/// +/// @brief Root of type hierarchy +class Type : public AbstractTypeUser { +public: + //===-------------------------------------------------------------------===// + /// Definitions of all of the base types for the Type system. Based on this + /// value, you can cast to a "DerivedType" subclass (see DerivedTypes.h) + /// Note: If you add an element to this, you need to add an element to the + /// Type::getPrimitiveType function, or else things will break! + /// Also update LLVMTypeKind and LLVMGetTypeKind () in the C binding. + /// + enum TypeID { + // PrimitiveTypes .. make sure LastPrimitiveTyID stays up to date + VoidTyID = 0, ///< 0: type with no size + FloatTyID, ///< 1: 32 bit floating point type + DoubleTyID, ///< 2: 64 bit floating point type + X86_FP80TyID, ///< 3: 80 bit floating point type (X87) + FP128TyID, ///< 4: 128 bit floating point type (112-bit mantissa) + PPC_FP128TyID, ///< 5: 128 bit floating point type (two 64-bits) + LabelTyID, ///< 6: Labels + MetadataTyID, ///< 7: Metadata + X86_MMXTyID, ///< 8: MMX vectors (64 bits) + + // Derived types... see DerivedTypes.h file... + // Make sure FirstDerivedTyID stays up to date!!! + IntegerTyID, ///< 9: Arbitrary bit width integers + FunctionTyID, ///< 10: Functions + StructTyID, ///< 11: Structures + ArrayTyID, ///< 12: Arrays + PointerTyID, ///< 13: Pointers + OpaqueTyID, ///< 14: Opaque: type with unknown structure + VectorTyID, ///< 15: SIMD 'packed' format, or other vector type + + NumTypeIDs, // Must remain as last defined ID + LastPrimitiveTyID = X86_MMXTyID, + FirstDerivedTyID = IntegerTyID + }; + +private: + TypeID ID : 8; // The current base type of this type. + bool Abstract : 1; // True if type contains an OpaqueType + unsigned SubclassData : 23; //Space for subclasses to store data + + /// RefCount - This counts the number of PATypeHolders that are pointing to + /// this type. When this number falls to zero, if the type is abstract and + /// has no AbstractTypeUsers, the type is deleted. This is only sensical for + /// derived types. + /// + mutable unsigned RefCount; + + /// Context - This refers to the LLVMContext in which this type was uniqued. + LLVMContext &Context; + friend class LLVMContextImpl; + + const Type *getForwardedTypeInternal() const; + + // Some Type instances are allocated as arrays, some aren't. So we provide + // this method to get the right kind of destruction for the type of Type. + void destroy() const; // const is a lie, this does "delete this"! + +protected: + explicit Type(LLVMContext &C, TypeID id) : + ID(id), Abstract(false), SubclassData(0), + RefCount(0), Context(C), + ForwardType(0), NumContainedTys(0), + ContainedTys(0) {} + virtual ~Type() { + assert(AbstractTypeUsers.empty() && "Abstract types remain"); + } + + /// Types can become nonabstract later, if they are refined. + /// + inline void setAbstract(bool Val) { Abstract = Val; } + + unsigned getRefCount() const { return RefCount; } + + unsigned getSubclassData() const { return SubclassData; } + void setSubclassData(unsigned val) { SubclassData = val; } + + /// ForwardType - This field is used to implement the union find scheme for + /// abstract types. When types are refined to other types, this field is set + /// to the more refined type. Only abstract types can be forwarded. + mutable const Type *ForwardType; + + + /// AbstractTypeUsers - Implement a list of the users that need to be notified + /// if I am a type, and I get resolved into a more concrete type. + /// + mutable std::vector AbstractTypeUsers; + + /// NumContainedTys - Keeps track of how many PATypeHandle instances there + /// are at the end of this type instance for the list of contained types. It + /// is the subclasses responsibility to set this up. Set to 0 if there are no + /// contained types in this type. + unsigned NumContainedTys; + + /// ContainedTys - A pointer to the array of Types (PATypeHandle) contained + /// by this Type. For example, this includes the arguments of a function + /// type, the elements of a structure, the pointee of a pointer, the element + /// type of an array, etc. This pointer may be 0 for types that don't + /// contain other types (Integer, Double, Float). In general, the subclass + /// should arrange for space for the PATypeHandles to be included in the + /// allocation of the type object and set this pointer to the address of the + /// first element. This allows the Type class to manipulate the ContainedTys + /// without understanding the subclass's placement for this array. keeping + /// it here also allows the subtype_* members to be implemented MUCH more + /// efficiently, and dynamically very few types do not contain any elements. + PATypeHandle *ContainedTys; + +public: + void print(raw_ostream &O) const; + + /// @brief Debugging support: print to stderr + void dump() const; + + /// @brief Debugging support: print to stderr (use type names from context + /// module). + void dump(const Module *Context) const; + + /// getContext - Fetch the LLVMContext in which this type was uniqued. + LLVMContext &getContext() const { return Context; } + + //===--------------------------------------------------------------------===// + // Property accessors for dealing with types... Some of these virtual methods + // are defined in private classes defined in Type.cpp for primitive types. + // + + /// getDescription - Return the string representation of the type. + std::string getDescription() const; + + /// getTypeID - Return the type id for the type. This will return one + /// of the TypeID enum elements defined above. + /// + inline TypeID getTypeID() const { return ID; } + + /// isVoidTy - Return true if this is 'void'. + bool isVoidTy() const { return ID == VoidTyID; } + + /// isFloatTy - Return true if this is 'float', a 32-bit IEEE fp type. + bool isFloatTy() const { return ID == FloatTyID; } + + /// isDoubleTy - Return true if this is 'double', a 64-bit IEEE fp type. + bool isDoubleTy() const { return ID == DoubleTyID; } + + /// isX86_FP80Ty - Return true if this is x86 long double. + bool isX86_FP80Ty() const { return ID == X86_FP80TyID; } + + /// isFP128Ty - Return true if this is 'fp128'. + bool isFP128Ty() const { return ID == FP128TyID; } + + /// isPPC_FP128Ty - Return true if this is powerpc long double. + bool isPPC_FP128Ty() const { return ID == PPC_FP128TyID; } + + /// isFloatingPointTy - Return true if this is one of the five floating point + /// types + bool isFloatingPointTy() const { return ID == FloatTyID || ID == DoubleTyID || + ID == X86_FP80TyID || ID == FP128TyID || ID == PPC_FP128TyID; } + + /// isX86_MMXTy - Return true if this is X86 MMX. + bool isX86_MMXTy() const { return ID == X86_MMXTyID; } + + /// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP. + /// + bool isFPOrFPVectorTy() const; + + /// isLabelTy - Return true if this is 'label'. + bool isLabelTy() const { return ID == LabelTyID; } + + /// isMetadataTy - Return true if this is 'metadata'. + bool isMetadataTy() const { return ID == MetadataTyID; } + + /// isIntegerTy - True if this is an instance of IntegerType. + /// + bool isIntegerTy() const { return ID == IntegerTyID; } + + /// isIntegerTy - Return true if this is an IntegerType of the given width. + bool isIntegerTy(unsigned Bitwidth) const; + + /// isIntOrIntVectorTy - Return true if this is an integer type or a vector of + /// integer types. + /// + bool isIntOrIntVectorTy() const; + + /// isFunctionTy - True if this is an instance of FunctionType. + /// + bool isFunctionTy() const { return ID == FunctionTyID; } + + /// isStructTy - True if this is an instance of StructType. + /// + bool isStructTy() const { return ID == StructTyID; } + + /// isArrayTy - True if this is an instance of ArrayType. + /// + bool isArrayTy() const { return ID == ArrayTyID; } + + /// isPointerTy - True if this is an instance of PointerType. + /// + bool isPointerTy() const { return ID == PointerTyID; } + + /// isOpaqueTy - True if this is an instance of OpaqueType. + /// + bool isOpaqueTy() const { return ID == OpaqueTyID; } + + /// isVectorTy - True if this is an instance of VectorType. + /// + bool isVectorTy() const { return ID == VectorTyID; } + + /// isAbstract - True if the type is either an Opaque type, or is a derived + /// type that includes an opaque type somewhere in it. + /// + inline bool isAbstract() const { return Abstract; } + + /// canLosslesslyBitCastTo - Return true if this type could be converted + /// with a lossless BitCast to type 'Ty'. For example, i8* to i32*. BitCasts + /// are valid for types of the same size only where no re-interpretation of + /// the bits is done. + /// @brief Determine if this type could be losslessly bitcast to Ty + bool canLosslesslyBitCastTo(const Type *Ty) const; + + + /// Here are some useful little methods to query what type derived types are + /// Note that all other types can just compare to see if this == Type::xxxTy; + /// + inline bool isPrimitiveType() const { return ID <= LastPrimitiveTyID; } + inline bool isDerivedType() const { return ID >= FirstDerivedTyID; } + + /// isFirstClassType - Return true if the type is "first class", meaning it + /// is a valid type for a Value. + /// + inline bool isFirstClassType() const { + // There are more first-class kinds than non-first-class kinds, so a + // negative test is simpler than a positive one. + return ID != FunctionTyID && ID != VoidTyID && ID != OpaqueTyID; + } + + /// isSingleValueType - Return true if the type is a valid type for a + /// virtual register in codegen. This includes all first-class types + /// except struct and array types. + /// + inline bool isSingleValueType() const { + return (ID != VoidTyID && ID <= LastPrimitiveTyID) || + ID == IntegerTyID || ID == PointerTyID || ID == VectorTyID; + } + + /// isAggregateType - Return true if the type is an aggregate type. This + /// means it is valid as the first operand of an insertvalue or + /// extractvalue instruction. This includes struct and array types, but + /// does not include vector types. + /// + inline bool isAggregateType() const { + return ID == StructTyID || ID == ArrayTyID; + } + + /// isSized - Return true if it makes sense to take the size of this type. To + /// get the actual size for a particular target, it is reasonable to use the + /// TargetData subsystem to do this. + /// + bool isSized() const { + // If it's a primitive, it is always sized. + if (ID == IntegerTyID || isFloatingPointTy() || ID == PointerTyID || + ID == X86_MMXTyID) + return true; + // If it is not something that can have a size (e.g. a function or label), + // it doesn't have a size. + if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID) + return false; + // If it is something that can have a size and it's concrete, it definitely + // has a size, otherwise we have to try harder to decide. + return !isAbstract() || isSizedDerivedType(); + } + + /// getPrimitiveSizeInBits - Return the basic size of this type if it is a + /// primitive type. These are fixed by LLVM and are not target dependent. + /// This will return zero if the type does not have a size or is not a + /// primitive type. + /// + /// Note that this may not reflect the size of memory allocated for an + /// instance of the type or the number of bytes that are written when an + /// instance of the type is stored to memory. The TargetData class provides + /// additional query functions to provide this information. + /// + unsigned getPrimitiveSizeInBits() const; + + /// getScalarSizeInBits - If this is a vector type, return the + /// getPrimitiveSizeInBits value for the element type. Otherwise return the + /// getPrimitiveSizeInBits value for this type. + unsigned getScalarSizeInBits() const; + + /// getFPMantissaWidth - Return the width of the mantissa of this type. This + /// is only valid on floating point types. If the FP type does not + /// have a stable mantissa (e.g. ppc long double), this method returns -1. + int getFPMantissaWidth() const; + + /// getForwardedType - Return the type that this type has been resolved to if + /// it has been resolved to anything. This is used to implement the + /// union-find algorithm for type resolution, and shouldn't be used by general + /// purpose clients. + const Type *getForwardedType() const { + if (!ForwardType) return 0; + return getForwardedTypeInternal(); + } + + /// getVAArgsPromotedType - Return the type an argument of this type + /// will be promoted to if passed through a variable argument + /// function. + const Type *getVAArgsPromotedType(LLVMContext &C) const; + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return this. + const Type *getScalarType() const; + + //===--------------------------------------------------------------------===// + // Type Iteration support + // + typedef PATypeHandle *subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys; } + subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + + /// getContainedType - This method is used to implement the type iterator + /// (defined a the end of the file). For derived types, this returns the + /// types 'contained' in the derived type. + /// + const Type *getContainedType(unsigned i) const { + assert(i < NumContainedTys && "Index out of range!"); + return ContainedTys[i].get(); + } + + /// getNumContainedTypes - Return the number of types in the derived type. + /// + unsigned getNumContainedTypes() const { return NumContainedTys; } + + //===--------------------------------------------------------------------===// + // Static members exported by the Type class itself. Useful for getting + // instances of Type. + // + + /// getPrimitiveType - Return a type based on an identifier. + static const Type *getPrimitiveType(LLVMContext &C, TypeID IDNumber); + + //===--------------------------------------------------------------------===// + // These are the builtin types that are always available... + // + static const Type *getVoidTy(LLVMContext &C); + static const Type *getLabelTy(LLVMContext &C); + static const Type *getFloatTy(LLVMContext &C); + static const Type *getDoubleTy(LLVMContext &C); + static const Type *getMetadataTy(LLVMContext &C); + static const Type *getX86_FP80Ty(LLVMContext &C); + static const Type *getFP128Ty(LLVMContext &C); + static const Type *getPPC_FP128Ty(LLVMContext &C); + static const Type *getX86_MMXTy(LLVMContext &C); + static const IntegerType *getIntNTy(LLVMContext &C, unsigned N); + static const IntegerType *getInt1Ty(LLVMContext &C); + static const IntegerType *getInt8Ty(LLVMContext &C); + static const IntegerType *getInt16Ty(LLVMContext &C); + static const IntegerType *getInt32Ty(LLVMContext &C); + static const IntegerType *getInt64Ty(LLVMContext &C); + + //===--------------------------------------------------------------------===// + // Convenience methods for getting pointer types with one of the above builtin + // types as pointee. + // + static const PointerType *getFloatPtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getDoublePtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getX86_FP80PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getFP128PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getPPC_FP128PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getX86_MMXPtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getIntNPtrTy(LLVMContext &C, unsigned N, + unsigned AS = 0); + static const PointerType *getInt1PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt8PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); + static const PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Type *) { return true; } + + void addRef() const { + assert(isAbstract() && "Cannot add a reference to a non-abstract type!"); + ++RefCount; + } + + void dropRef() const { + assert(isAbstract() && "Cannot drop a reference to a non-abstract type!"); + assert(RefCount && "No objects are currently referencing this object!"); + + // If this is the last PATypeHolder using this object, and there are no + // PATypeHandles using it, the type is dead, delete it now. + if (--RefCount == 0 && AbstractTypeUsers.empty()) + this->destroy(); + } + + /// addAbstractTypeUser - Notify an abstract type that there is a new user of + /// it. This function is called primarily by the PATypeHandle class. + /// + void addAbstractTypeUser(AbstractTypeUser *U) const; + + /// removeAbstractTypeUser - Notify an abstract type that a user of the class + /// no longer has a handle to the type. This function is called primarily by + /// the PATypeHandle class. When there are no users of the abstract type, it + /// is annihilated, because there is no way to get a reference to it ever + /// again. + /// + void removeAbstractTypeUser(AbstractTypeUser *U) const; + + /// getPointerTo - Return a pointer to the current type. This is equivalent + /// to PointerType::get(Foo, AddrSpace). + const PointerType *getPointerTo(unsigned AddrSpace = 0) const; + +private: + /// isSizedDerivedType - Derived types like structures and arrays are sized + /// iff all of the members of the type are sized as well. Since asking for + /// their size is relatively uncommon, move this operation out of line. + bool isSizedDerivedType() const; + + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +protected: + // PromoteAbstractToConcrete - This is an internal method used to calculate + // change "Abstract" from true to false when types are refined. + void PromoteAbstractToConcrete(); + friend class TypeMapBase; +}; + +//===----------------------------------------------------------------------===// +// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class. +// These are defined here because they MUST be inlined, yet are dependent on +// the definition of the Type class. +// +inline void PATypeHandle::addUser() { + assert(Ty && "Type Handle has a null type!"); + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(User); +} +inline void PATypeHandle::removeUser() { + if (Ty->isAbstract()) + Ty->removeAbstractTypeUser(User); +} + +// Define inline methods for PATypeHolder. + +/// get - This implements the forwarding part of the union-find algorithm for +/// abstract types. Before every access to the Type*, we check to see if the +/// type we are pointing to is forwarding to a new type. If so, we drop our +/// reference to the type. +/// +inline Type* PATypeHolder::get() const { + if (Ty == 0) return 0; + const Type *NewTy = Ty->getForwardedType(); + if (!NewTy) return const_cast(Ty); + return *const_cast(this) = NewTy; +} + +inline void PATypeHolder::addRef() { + if (Ty && Ty->isAbstract()) + Ty->addRef(); +} + +inline void PATypeHolder::dropRef() { + if (Ty && Ty->isAbstract()) + Ty->dropRef(); +} + + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat a type as a +// graph of sub types... + +template <> struct GraphTraits { + typedef Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> struct GraphTraits { + typedef const Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> struct isa_impl { + static inline bool doit(const Type &Ty) { + return Ty.getTypeID() == Type::PointerTyID; + } +}; + +raw_ostream &operator<<(raw_ostream &OS, const Type &T); + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/TypeSymbolTable.h b/final/include/llvm/TypeSymbolTable.h new file mode 100644 index 00000000000..9fdcb983232 --- /dev/null +++ b/final/include/llvm/TypeSymbolTable.h @@ -0,0 +1,152 @@ +//===-- llvm/TypeSymbolTable.h - Implement a Type Symtab --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the name/type symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TYPE_SYMBOL_TABLE_H +#define LLVM_TYPE_SYMBOL_TABLE_H + +#include "llvm/Type.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +/// This class provides a symbol table of name/type pairs with operations to +/// support constructing, searching and iterating over the symbol table. The +/// class derives from AbstractTypeUser so that the contents of the symbol +/// table can be updated when abstract types become concrete. +class TypeSymbolTable : public AbstractTypeUser { + +/// @name Types +/// @{ +public: + + /// @brief A mapping of names to types. + typedef std::map TypeMap; + + /// @brief An iterator over the TypeMap. + typedef TypeMap::iterator iterator; + + /// @brief A const_iterator over the TypeMap. + typedef TypeMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + TypeSymbolTable():LastUnique(0) {} + ~TypeSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// Generates a unique name for a type based on the \p BaseName by + /// incrementing an integer and appending it to the name, if necessary + /// @returns the unique name + /// @brief Get a unique name for a type + std::string getUniqueName(StringRef BaseName) const; + + /// This method finds the type with the given \p name in the type map + /// and returns it. + /// @returns null if the name is not found, otherwise the Type + /// associated with the \p name. + /// @brief Lookup a type by name. + Type *lookup(StringRef name) const; + + /// Lookup the type associated with name. + /// @returns end() if the name is not found, or an iterator at the entry for + /// Type. + iterator find(StringRef Name) { + return tmap.find(Name); + } + + /// Lookup the type associated with name. + /// @returns end() if the name is not found, or an iterator at the entry for + /// Type. + const_iterator find(StringRef Name) const { + return tmap.find(Name); + } + + /// @returns true iff the symbol table is empty. + /// @brief Determine if the symbol table is empty + inline bool empty() const { return tmap.empty(); } + + /// @returns the size of the symbol table + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(tmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// Get an iterator to the start of the symbol table + inline iterator begin() { return tmap.begin(); } + + /// @brief Get a const_iterator to the start of the symbol table + inline const_iterator begin() const { return tmap.begin(); } + + /// Get an iterator to the end of the symbol table. + inline iterator end() { return tmap.end(); } + + /// Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return tmap.end(); } + +/// @} +/// @name Mutators +/// @{ +public: + + /// Inserts a type into the symbol table with the specified name. There can be + /// a many-to-one mapping between names and types. This method allows a type + /// with an existing entry in the symbol table to get a new name. + /// @brief Insert a type under a new name. + void insert(StringRef Name, const Type *Typ); + + /// Remove a type at the specified position in the symbol table. + /// @returns the removed Type. + /// @returns the Type that was erased from the symbol table. + Type* remove(iterator TI); + +/// @} +/// @name AbstractTypeUser Methods +/// @{ +private: + /// This function is called when one of the types in the type plane + /// is refined. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + + /// This function markes a type as being concrete (defined). + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +/// @} +/// @name Internal Data +/// @{ +private: + TypeMap tmap; ///< This is the mapping of names to types. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} + +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Use.h b/final/include/llvm/Use.h new file mode 100644 index 00000000000..ccbdd7fcae1 --- /dev/null +++ b/final/include/llvm/Use.h @@ -0,0 +1,222 @@ +//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines the Use class. The Use class represents the operand of an +// instruction or some other User instance which refers to a Value. The Use +// class keeps the "use list" of the referenced value up to date. +// +// Pointer tagging is used to efficiently find the User corresponding +// to a Use without having to store a User pointer in every Use. A +// User is preceded in memory by all the Uses corresponding to its +// operands, and the low bits of one of the fields (Prev) of the Use +// class are used to encode offsets to be able to find that User given +// a pointer to any Use. For details, see: +// +// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USE_H +#define LLVM_USE_H + +#include "llvm/ADT/PointerIntPair.h" +#include +#include + +namespace llvm { + +class Value; +class User; +class Use; +template +struct simplify_type; + +// Use** is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(Use** P) { return P; } + static inline Use **getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +//===----------------------------------------------------------------------===// +// Use Class +//===----------------------------------------------------------------------===// + +/// Use is here to make keeping the "use" list of a Value up-to-date really +/// easy. +class Use { +public: + /// swap - provide a fast substitute to std::swap + /// that also works with less standard-compliant compilers + void swap(Use &RHS); + +private: + /// Copy ctor - do not implement + Use(const Use &U); + + /// Destructor - Only for zap() + ~Use() { + if (Val) removeFromList(); + } + + enum PrevPtrTag { zeroDigitTag + , oneDigitTag + , stopTag + , fullStopTag }; + + /// Constructor + Use(PrevPtrTag tag) : Val(0) { + Prev.setInt(tag); + } + +public: + /// Normally Use will just implicitly convert to a Value* that it holds. + operator Value*() const { return Val; } + + /// If implicit conversion to Value* doesn't work, the get() method returns + /// the Value*. + Value *get() const { return Val; } + + /// getUser - This returns the User that contains this Use. For an + /// instruction operand, for example, this will return the instruction. + User *getUser() const; + + inline void set(Value *Val); + + Value *operator=(Value *RHS) { + set(RHS); + return RHS; + } + const Use &operator=(const Use &RHS) { + set(RHS.Val); + return *this; + } + + Value *operator->() { return Val; } + const Value *operator->() const { return Val; } + + Use *getNext() const { return Next; } + + + /// zap - This is used to destroy Use operands when the number of operands of + /// a User changes. + static void zap(Use *Start, const Use *Stop, bool del = false); + +private: + const Use* getImpliedUser() const; + static Use *initTags(Use *Start, Use *Stop); + + Value *Val; + Use *Next; + PointerIntPair Prev; + + void setPrev(Use **NewPrev) { + Prev.setPointer(NewPrev); + } + void addToList(Use **List) { + Next = *List; + if (Next) Next->setPrev(&Next); + setPrev(List); + *List = this; + } + void removeFromList() { + Use **StrippedPrev = Prev.getPointer(); + *StrippedPrev = Next; + if (Next) Next->setPrev(StrippedPrev); + } + + friend class Value; + friend class User; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast(Val.get()); + } +}; +template<> struct simplify_type { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast(Val.get()); + } +}; + + + +template // UserTy == 'User' or 'const User' +class value_use_iterator : public std::iterator { + typedef std::iterator super; + typedef value_use_iterator _Self; + + Use *U; + explicit value_use_iterator(Use *u) : U(u) {} + friend class Value; +public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + value_use_iterator(const _Self &I) : U(I.U) {} + value_use_iterator() {} + + bool operator==(const _Self &x) const { + return U == x.U; + } + bool operator!=(const _Self &x) const { + return !operator==(x); + } + + /// atEnd - return true if this iterator is equal to use_end() on the value. + bool atEnd() const { return U == 0; } + + // Iterator traversal: forward iteration only + _Self &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a pointer to the current User. + UserTy *operator*() const { + assert(U && "Cannot dereference end iterator!"); + return U->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + Use &getUse() const { return *U; } + + /// getOperandNo - Return the operand # of this use in its User. Defined in + /// User.h + /// + unsigned getOperandNo() const; +}; + +//===----------------------------------------------------------------------===// +// AugmentedUse layout struct +//===----------------------------------------------------------------------===// + +struct AugmentedUse : public Use { + PointerIntPair ref; + AugmentedUse(); // not implemented +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/User.h b/final/include/llvm/User.h new file mode 100644 index 00000000000..1363495f7c0 --- /dev/null +++ b/final/include/llvm/User.h @@ -0,0 +1,175 @@ +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the interface that one who 'use's a Value must implement. +// Each instance of the Value class keeps track of what User's have handles +// to it. +// +// * Instructions are the largest class of User's. +// * Constants may be users of other constants (think arrays and stuff) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USER_H +#define LLVM_USER_H + +#include "llvm/Value.h" + +namespace llvm { + +/// OperandTraits - Compile-time customization of +/// operand-related allocators and accessors +/// for use of the User class +template +struct OperandTraits; + +class User : public Value { + User(const User &); // Do not implement + void *operator new(size_t); // Do not implement + template + friend struct HungoffOperandTraits; +protected: + /// OperandList - This is a pointer to the array of Uses for this User. + /// For nodes of fixed arity (e.g. a binary operator) this array will live + /// prefixed to some derived class instance. For nodes of resizable variable + /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically + /// allocated and should be destroyed by the classes' virtual dtor. + Use *OperandList; + + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + + void *operator new(size_t s, unsigned Us); + User(const Type *ty, unsigned vty, Use *OpList, unsigned NumOps) + : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + Use *allocHungoffUses(unsigned) const; + void dropHungoffUses() { + Use::zap(OperandList, OperandList + NumOperands, true); + OperandList = 0; + // Reset NumOperands so User::operator delete() does the right thing. + NumOperands = 0; + } +public: + ~User() { + Use::zap(OperandList, OperandList + NumOperands); + } + /// operator delete - free memory allocated for User and Use objects + void operator delete(void *Usr); + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + assert(0 && "Constructor throws?"); + } + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned, bool) { + assert(0 && "Constructor throws?"); + } +protected: + template static Use &OpFrom(const U *that) { + return Idx < 0 + ? OperandTraits::op_end(const_cast(that))[Idx] + : OperandTraits::op_begin(const_cast(that))[Idx]; + } + template Use &Op() { + return OpFrom(this); + } + template const Use &Op() const { + return OpFrom(this); + } +public: + Value *getOperand(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < NumOperands && "setOperand() out of range!"); + assert((!isa((const Value*)this) || + isa((const Value*)this)) && + "Cannot mutate a constant with setOperand!"); + OperandList[i] = Val; + } + const Use &getOperandUse(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + Use &getOperandUse(unsigned i) { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + + unsigned getNumOperands() const { return NumOperands; } + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + + inline op_iterator op_begin() { return OperandList; } + inline const_op_iterator op_begin() const { return OperandList; } + inline op_iterator op_end() { return OperandList+NumOperands; } + inline const_op_iterator op_end() const { return OperandList+NumOperands; } + + // dropAllReferences() - This function is in charge of "letting go" of all + // objects that this User refers to. This allows one to + // 'delete' a whole class at a time, even though there may be circular + // references... First all references are dropped, and all use counts go to + // zero. Then everything is deleted for real. Note that no operations are + // valid on an object that has "dropped all references", except operator + // delete. + // + void dropAllReferences() { + for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) + i->set(0); + } + + /// replaceUsesOfWith - Replaces all references to the "From" definition with + /// references to the "To" definition. + /// + void replaceUsesOfWith(Value *From, Value *To); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const User *) { return true; } + static inline bool classof(const Value *V) { + return isa(V) || isa(V); + } +}; + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { + return static_cast(Val->get()); + } +}; + +template<> struct simplify_type + : public simplify_type {}; + + +// value_use_iterator::getOperandNo - Requires the definition of the User class. +template +unsigned value_use_iterator::getOperandNo() const { + return U - U->getUser()->op_begin(); +} + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/Value.h b/final/include/llvm/Value.h new file mode 100644 index 00000000000..130e2735f52 --- /dev/null +++ b/final/include/llvm/Value.h @@ -0,0 +1,409 @@ +//===-- llvm/Value.h - Definition of the Value class ------------*- 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 Value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_H +#define LLVM_VALUE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Use.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Constant; +class Argument; +class Instruction; +class BasicBlock; +class GlobalValue; +class Function; +class GlobalVariable; +class GlobalAlias; +class InlineAsm; +class ValueSymbolTable; +class TypeSymbolTable; +template class StringMapEntry; +template +class AssertingVH; +typedef StringMapEntry ValueName; +class raw_ostream; +class AssemblyAnnotationWriter; +class ValueHandleBase; +class LLVMContext; +class Twine; +class MDNode; + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +/// This is a very important LLVM class. It is the base class of all values +/// computed by a program that may be used as operands to other values. Value is +/// the super class of other important classes such as Instruction and Function. +/// All Values have a Type. Type is not a subclass of Value. All types can have +/// a name and they should belong to some Module. Setting the name on the Value +/// automatically updates the module's symbol table. +/// +/// Every value has a "use list" that keeps track of which other Values are +/// using this Value. A Value can also have an arbitrary number of ValueHandle +/// objects that watch it and listen to RAUW and Destroy events. See +/// llvm/Support/ValueHandle.h for details. +/// +/// @brief LLVM Value Representation +class Value { + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) + unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? +protected: + /// SubclassOptionalData - This member is similar to SubclassData, however it + /// is for holding information which may be used to aid optimization, but + /// which may be cleared to zero without affecting conservative + /// interpretation. + unsigned char SubclassOptionalData : 7; + +private: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + unsigned short SubclassData; + + PATypeHolder VTy; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueHandleBase; + friend class AbstractTypeUser; + ValueName *Name; + + void operator=(const Value &); // Do not implement + Value(const Value &); // Do not implement + +protected: + /// printCustom - Value subclasses can override this to implement custom + /// printing behavior. + virtual void printCustom(raw_ostream &O) const; + + Value(const Type *Ty, unsigned scid); +public: + virtual ~Value(); + + /// dump - Support for debugging, callable in GDB: V->dump() + // + void dump() const; + + /// print - Implement operator<< on Value. + /// + void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) const; + + /// All values are typed, get the type of this value. + /// + inline const Type *getType() const { return VTy; } + + /// All values hold a context through their type. + LLVMContext &getContext() const; + + // All values can potentially be named... + inline bool hasName() const { return Name != 0; } + ValueName *getValueName() const { return Name; } + + /// getName() - Return a constant reference to the value's name. This is cheap + /// and guaranteed to return the same reference as long as the value is not + /// modified. + /// + /// This is currently guaranteed to return a StringRef for which data() points + /// to a valid null terminated string. The use of StringRef.data() is + /// deprecated here, however, and clients should not rely on it. If such + /// behavior is needed, clients should use expensive getNameStr(), or switch + /// to an interface that does not depend on null termination. + StringRef getName() const; + + /// getNameStr() - Return the name of the specified value, *constructing a + /// string* to hold it. This is guaranteed to construct a string and is very + /// expensive, clients should use getName() unless necessary. + std::string getNameStr() const; + + /// setName() - Change the name of the value, choosing a new unique name if + /// the provided name is taken. + /// + /// \arg Name - The new name; or "" if the value's name should be removed. + void setName(const Twine &Name); + + + /// takeName - transfer the name from V to this value, setting V's name to + /// empty. It is an error to call V->takeName(V). + void takeName(Value *V); + + /// replaceAllUsesWith - Go through the uses list for this definition and make + /// each use point to "V" instead of "this". After this completes, 'this's + /// use list is guaranteed to be empty. + /// + void replaceAllUsesWith(Value *V); + + // uncheckedReplaceAllUsesWith - Just like replaceAllUsesWith but dangerous. + // Only use when in type resolution situations! + void uncheckedReplaceAllUsesWith(Value *V); + + //---------------------------------------------------------------------- + // Methods for handling the chain of uses of this Value. + // + typedef value_use_iterator use_iterator; + typedef value_use_iterator const_use_iterator; + + bool use_empty() const { return UseList == 0; } + use_iterator use_begin() { return use_iterator(UseList); } + const_use_iterator use_begin() const { return const_use_iterator(UseList); } + use_iterator use_end() { return use_iterator(0); } + const_use_iterator use_end() const { return const_use_iterator(0); } + User *use_back() { return *use_begin(); } + const User *use_back() const { return *use_begin(); } + + /// hasOneUse - Return true if there is exactly one user of this value. This + /// is specialized because it is a common request and does not require + /// traversing the whole use list. + /// + bool hasOneUse() const { + const_use_iterator I = use_begin(), E = use_end(); + if (I == E) return false; + return ++I == E; + } + + /// hasNUses - Return true if this Value has exactly N users. + /// + bool hasNUses(unsigned N) const; + + /// hasNUsesOrMore - Return true if this value has N users or more. This is + /// logically equivalent to getNumUses() >= N. + /// + bool hasNUsesOrMore(unsigned N) const; + + bool isUsedInBasicBlock(const BasicBlock *BB) const; + + /// getNumUses - This method computes the number of uses of this Value. This + /// is a linear time operation. Use hasOneUse, hasNUses, or hasMoreThanNUses + /// to check for specific values. + unsigned getNumUses() const; + + /// addUse - This method should only be used by the Use class. + /// + void addUse(Use &U) { U.addToList(&UseList); } + + /// An enumeration for keeping track of the concrete subclass of Value that + /// is actually instantiated. Values of this enumeration are kept in the + /// Value classes SubclassID field. They are used for concrete type + /// identification. + enum ValueTy { + ArgumentVal, // This is an instance of Argument + BasicBlockVal, // This is an instance of BasicBlock + FunctionVal, // This is an instance of Function + GlobalAliasVal, // This is an instance of GlobalAlias + GlobalVariableVal, // This is an instance of GlobalVariable + UndefValueVal, // This is an instance of UndefValue + BlockAddressVal, // This is an instance of BlockAddress + ConstantExprVal, // This is an instance of ConstantExpr + ConstantAggregateZeroVal, // This is an instance of ConstantAggregateZero + ConstantIntVal, // This is an instance of ConstantInt + ConstantFPVal, // This is an instance of ConstantFP + ConstantArrayVal, // This is an instance of ConstantArray + ConstantStructVal, // This is an instance of ConstantStruct + ConstantVectorVal, // This is an instance of ConstantVector + ConstantPointerNullVal, // This is an instance of ConstantPointerNull + MDNodeVal, // This is an instance of MDNode + MDStringVal, // This is an instance of MDString + InlineAsmVal, // This is an instance of InlineAsm + PseudoSourceValueVal, // This is an instance of PseudoSourceValue + FixedStackPseudoSourceValueVal, // This is an instance of + // FixedStackPseudoSourceValue + InstructionVal, // This is an instance of Instruction + // Enum values starting at InstructionVal are used for Instructions; + // don't add new values here! + + // Markers: + ConstantFirstVal = FunctionVal, + ConstantLastVal = ConstantPointerNullVal + }; + + /// getValueID - Return an ID for the concrete type of this object. This is + /// used to implement the classof checks. This should not be used for any + /// other purpose, as the values may change as LLVM evolves. Also, note that + /// for instructions, the Instruction's opcode is added to InstructionVal. So + /// this means three things: + /// # there is no value with code InstructionVal (no opcode==0). + /// # there are more possible values for the value type than in ValueTy enum. + /// # the InstructionVal enumerator must be the highest valued enumerator in + /// the ValueTy enum. + unsigned getValueID() const { + return SubclassID; + } + + /// getRawSubclassOptionalData - Return the raw optional flags value + /// contained in this value. This should only be used when testing two + /// Values for equivalence. + unsigned getRawSubclassOptionalData() const { + return SubclassOptionalData; + } + + /// clearSubclassOptionalData - Clear the optional flags contained in + /// this value. + void clearSubclassOptionalData() { + SubclassOptionalData = 0; + } + + /// hasSameSubclassOptionalData - Test whether the optional flags contained + /// in this value are equal to the optional flags in the given value. + bool hasSameSubclassOptionalData(const Value *V) const { + return SubclassOptionalData == V->SubclassOptionalData; + } + + /// intersectOptionalDataWith - Clear any optional flags in this value + /// that are not also set in the given value. + void intersectOptionalDataWith(const Value *V) { + SubclassOptionalData &= V->SubclassOptionalData; + } + + /// hasValueHandle - Return true if there is a value handle associated with + /// this value. + bool hasValueHandle() const { return HasValueHandle; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *) { + return true; // Values are always values. + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return VTy.getRawType(); } + + /// stripPointerCasts - This method strips off any unneeded pointer + /// casts from the specified value, returning the original uncasted value. + /// Note that the returned value has pointer type if the specified value does. + Value *stripPointerCasts(); + const Value *stripPointerCasts() const { + return const_cast(this)->stripPointerCasts(); + } + + /// isDereferenceablePointer - Test if this value is always a pointer to + /// allocated and suitably aligned memory for a simple load or store. + bool isDereferenceablePointer() const; + + /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, + /// return the value in the PHI node corresponding to PredBB. If not, return + /// ourself. This is useful if you want to know the value something has in a + /// predecessor block. + Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); + + const Value *DoPHITranslation(const BasicBlock *CurBB, + const BasicBlock *PredBB) const{ + return const_cast(this)->DoPHITranslation(CurBB, PredBB); + } + + /// MaximumAlignment - This is the greatest alignment value supported by + /// load, store, and alloca instructions, and global values. + static const unsigned MaximumAlignment = 1u << 29; + +protected: + unsigned short getSubclassDataFromValue() const { return SubclassData; } + void setValueSubclassData(unsigned short D) { SubclassData = D; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { + V.print(OS); + return OS; +} + +void Use::set(Value *V) { + if (Val) removeFromList(); + Val = V; + if (V) V->addUse(*this); +} + + +// isa - Provide some specializations of isa so that we don't have to include +// the subtype header files to test to see if the value is a subclass... +// +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantFirstVal && + Val.getValueID() <= Value::ConstantLastVal; + } +}; + +template <> struct isa_impl { + static inline bool doit (const Value &Val) { + return Val.getValueID() == Value::ArgumentVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::InlineAsmVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::InstructionVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::BasicBlockVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::FunctionVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalVariableVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return isa(Val) || isa(Val) || + isa(Val); + } +}; + +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() == Value::MDNodeVal; + } +}; + +// Value* is only 4-byte aligned. +template<> +class PointerLikeTypeTraits { + typedef Value* PT; +public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast(P); + } + enum { NumLowBitsAvailable = 2 }; +}; + +} // End llvm namespace + +#endif diff --git a/final/include/llvm/ValueSymbolTable.h b/final/include/llvm/ValueSymbolTable.h new file mode 100644 index 00000000000..1738cc4a7a7 --- /dev/null +++ b/final/include/llvm/ValueSymbolTable.h @@ -0,0 +1,133 @@ +//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the name/Value symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_SYMBOL_TABLE_H +#define LLVM_VALUE_SYMBOL_TABLE_H + +#include "llvm/Value.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + template + class SymbolTableListTraits; + class BasicBlock; + class Function; + class NamedMDNode; + class Module; + class StringRef; + +/// This class provides a symbol table of name/value pairs. It is essentially +/// a std::map but has a controlled interface provided by +/// LLVM as well as ensuring uniqueness of names. +/// +class ValueSymbolTable { + friend class Value; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; + friend class SymbolTableListTraits; +/// @name Types +/// @{ +public: + /// @brief A mapping of names to values. + typedef StringMap ValueMap; + + /// @brief An iterator over a ValueMap. + typedef ValueMap::iterator iterator; + + /// @brief A const_iterator over a ValueMap. + typedef ValueMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + ValueSymbolTable() : vmap(0), LastUnique(0) {} + ~ValueSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// This method finds the value with the given \p Name in the + /// the symbol table. + /// @returns the value associated with the \p Name + /// @brief Lookup a named Value. + Value *lookup(StringRef Name) const { return vmap.lookup(Name); } + + /// @returns true iff the symbol table is empty + /// @brief Determine if the symbol table is empty + inline bool empty() const { return vmap.empty(); } + + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(vmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// @brief Get an iterator that from the beginning of the symbol table. + inline iterator begin() { return vmap.begin(); } + + /// @brief Get a const_iterator that from the beginning of the symbol table. + inline const_iterator begin() const { return vmap.begin(); } + + /// @brief Get an iterator to the end of the symbol table. + inline iterator end() { return vmap.end(); } + + /// @brief Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return vmap.end(); } + +/// @} +/// @name Mutators +/// @{ +private: + /// This method adds the provided value \p N to the symbol table. The Value + /// must have a name which is used to place the value in the symbol table. + /// If the inserted name conflicts, this renames the value. + /// @brief Add a named value to the symbol table + void reinsertValue(Value *V); + + /// createValueName - This method attempts to create a value name and insert + /// it into the symbol table with the specified name. If it conflicts, it + /// auto-renames the name and returns that instead. + ValueName *createValueName(StringRef Name, Value *V); + + /// This method removes a value from the symbol table. It leaves the + /// ValueName attached to the value, but it is no longer inserted in the + /// symtab. + void removeValueName(ValueName *V); + +/// @} +/// @name Internal Data +/// @{ +private: + ValueMap vmap; ///< The map that holds the symbol table. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/Analysis/AliasAnalysis.cpp b/final/lib/Analysis/AliasAnalysis.cpp new file mode 100644 index 00000000000..be02ddbaa53 --- /dev/null +++ b/final/lib/Analysis/AliasAnalysis.cpp @@ -0,0 +1,383 @@ +//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==// +// +// 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 generic AliasAnalysis interface which is used as the +// common interface used by all clients and implementations of alias analysis. +// +// This file also implements the default version of the AliasAnalysis interface +// that is to be used when no other implementation is specified. This does some +// simple tests that detect obvious cases: two different global pointers cannot +// alias, a global cannot alias a malloc, two different mallocs cannot alias, +// etc. +// +// This alias analysis implementation really isn't very good for anything, but +// it is very fast, and makes a nice clean default implementation. Because it +// handles lots of little corner cases, other, more complex, alias analysis +// implementations may choose to rely on this pass to resolve these simple and +// easy cases. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Pass.h" +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Type.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +// Register the AliasAnalysis interface, providing a nice name to refer to. +INITIALIZE_ANALYSIS_GROUP(AliasAnalysis, "Alias Analysis", NoAA) +char AliasAnalysis::ID = 0; + +//===----------------------------------------------------------------------===// +// Default chaining methods +//===----------------------------------------------------------------------===// + +AliasAnalysis::AliasResult +AliasAnalysis::alias(const Location &LocA, const Location &LocB) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->alias(LocA, LocB); +} + +bool AliasAnalysis::pointsToConstantMemory(const Location &Loc, + bool OrLocal) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->pointsToConstantMemory(Loc, OrLocal); +} + +void AliasAnalysis::deleteValue(Value *V) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + AA->deleteValue(V); +} + +void AliasAnalysis::copyValue(Value *From, Value *To) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + AA->copyValue(From, To); +} + +void AliasAnalysis::addEscapingUse(Use &U) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + AA->addEscapingUse(U); +} + + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + + ModRefBehavior MRB = getModRefBehavior(CS); + if (MRB == DoesNotAccessMemory) + return NoModRef; + + ModRefResult Mask = ModRef; + if (onlyReadsMemory(MRB)) + Mask = Ref; + + if (onlyAccessesArgPointees(MRB)) { + bool doesAlias = false; + if (doesAccessArgPointees(MRB)) + for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + AI != AE; ++AI) + if (!isNoAlias(Location(*AI), Loc)) { + doesAlias = true; + break; + } + + if (!doesAlias) + return NoModRef; + } + + // If Loc is a constant memory location, the call definitely could not + // modify the memory location. + if ((Mask & Mod) && pointsToConstantMemory(Loc)) + Mask = ModRefResult(Mask & ~Mod); + + // If this is the end of the chain, don't forward. + if (!AA) return Mask; + + // Otherwise, fall back to the next AA in the chain. But we can merge + // in any mask we've managed to compute. + return ModRefResult(AA->getModRefInfo(CS, Loc) & Mask); +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + + // If CS1 or CS2 are readnone, they don't interact. + ModRefBehavior CS1B = getModRefBehavior(CS1); + if (CS1B == DoesNotAccessMemory) return NoModRef; + + ModRefBehavior CS2B = getModRefBehavior(CS2); + if (CS2B == DoesNotAccessMemory) return NoModRef; + + // If they both only read from memory, there is no dependence. + if (onlyReadsMemory(CS1B) && onlyReadsMemory(CS2B)) + return NoModRef; + + AliasAnalysis::ModRefResult Mask = ModRef; + + // If CS1 only reads memory, the only dependence on CS2 can be + // from CS1 reading memory written by CS2. + if (onlyReadsMemory(CS1B)) + Mask = ModRefResult(Mask & Ref); + + // If CS2 only access memory through arguments, accumulate the mod/ref + // information from CS1's references to the memory referenced by + // CS2's arguments. + if (onlyAccessesArgPointees(CS2B)) { + AliasAnalysis::ModRefResult R = NoModRef; + if (doesAccessArgPointees(CS2B)) + for (ImmutableCallSite::arg_iterator + I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) { + R = ModRefResult((R | getModRefInfo(CS1, *I, UnknownSize)) & Mask); + if (R == Mask) + break; + } + return R; + } + + // If CS1 only accesses memory through arguments, check if CS2 references + // any of the memory referenced by CS1's arguments. If not, return NoModRef. + if (onlyAccessesArgPointees(CS1B)) { + AliasAnalysis::ModRefResult R = NoModRef; + if (doesAccessArgPointees(CS1B)) + for (ImmutableCallSite::arg_iterator + I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) + if (getModRefInfo(CS2, *I, UnknownSize) != NoModRef) { + R = Mask; + break; + } + if (R == NoModRef) + return R; + } + + // If this is the end of the chain, don't forward. + if (!AA) return Mask; + + // Otherwise, fall back to the next AA in the chain. But we can merge + // in any mask we've managed to compute. + return ModRefResult(AA->getModRefInfo(CS1, CS2) & Mask); +} + +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + + ModRefBehavior Min = UnknownModRefBehavior; + + // Call back into the alias analysis with the other form of getModRefBehavior + // to see if it can give a better response. + if (const Function *F = CS.getCalledFunction()) + Min = getModRefBehavior(F); + + // If this is the end of the chain, don't forward. + if (!AA) return Min; + + // Otherwise, fall back to the next AA in the chain. But we can merge + // in any result we've managed to compute. + return ModRefBehavior(AA->getModRefBehavior(CS) & Min); +} + +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(const Function *F) { + assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); + return AA->getModRefBehavior(F); +} + +//===----------------------------------------------------------------------===// +// AliasAnalysis non-virtual helper method implementation +//===----------------------------------------------------------------------===// + +AliasAnalysis::Location AliasAnalysis::getLocation(const LoadInst *LI) { + return Location(LI->getPointerOperand(), + getTypeStoreSize(LI->getType()), + LI->getMetadata(LLVMContext::MD_tbaa)); +} + +AliasAnalysis::Location AliasAnalysis::getLocation(const StoreInst *SI) { + return Location(SI->getPointerOperand(), + getTypeStoreSize(SI->getValueOperand()->getType()), + SI->getMetadata(LLVMContext::MD_tbaa)); +} + +AliasAnalysis::Location AliasAnalysis::getLocation(const VAArgInst *VI) { + return Location(VI->getPointerOperand(), + UnknownSize, + VI->getMetadata(LLVMContext::MD_tbaa)); +} + + +AliasAnalysis::Location +AliasAnalysis::getLocationForSource(const MemTransferInst *MTI) { + uint64_t Size = UnknownSize; + if (ConstantInt *C = dyn_cast(MTI->getLength())) + Size = C->getValue().getZExtValue(); + + // memcpy/memmove can have TBAA tags. For memcpy, they apply + // to both the source and the destination. + MDNode *TBAATag = MTI->getMetadata(LLVMContext::MD_tbaa); + + return Location(MTI->getRawSource(), Size, TBAATag); +} + +AliasAnalysis::Location +AliasAnalysis::getLocationForDest(const MemIntrinsic *MTI) { + uint64_t Size = UnknownSize; + if (ConstantInt *C = dyn_cast(MTI->getLength())) + Size = C->getValue().getZExtValue(); + + // memcpy/memmove can have TBAA tags. For memcpy, they apply + // to both the source and the destination. + MDNode *TBAATag = MTI->getMetadata(LLVMContext::MD_tbaa); + + return Location(MTI->getRawDest(), Size, TBAATag); +} + + + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) { + // Be conservative in the face of volatile. + if (L->isVolatile()) + return ModRef; + + // If the load address doesn't alias the given address, it doesn't read + // or write the specified memory. + if (!alias(getLocation(L), Loc)) + return NoModRef; + + // Otherwise, a load just reads. + return Ref; +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(const StoreInst *S, const Location &Loc) { + // Be conservative in the face of volatile. + if (S->isVolatile()) + return ModRef; + + // If the store address cannot alias the pointer in question, then the + // specified memory cannot be modified by the store. + if (!alias(getLocation(S), Loc)) + return NoModRef; + + // If the pointer is a pointer to constant memory, then it could not have been + // modified by this store. + if (pointsToConstantMemory(Loc)) + return NoModRef; + + // Otherwise, a store just writes. + return Mod; +} + +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(const VAArgInst *V, const Location &Loc) { + // If the va_arg address cannot alias the pointer in question, then the + // specified memory cannot be accessed by the va_arg. + if (!alias(getLocation(V), Loc)) + return NoModRef; + + // If the pointer is a pointer to constant memory, then it could not have been + // modified by this va_arg. + if (pointsToConstantMemory(Loc)) + return NoModRef; + + // Otherwise, a va_arg reads and writes. + return ModRef; +} + +// AliasAnalysis destructor: DO NOT move this to the header file for +// AliasAnalysis or else clients of the AliasAnalysis class may not depend on +// the AliasAnalysis.o file in the current .a file, causing alias analysis +// support to not be included in the tool correctly! +// +AliasAnalysis::~AliasAnalysis() {} + +/// InitializeAliasAnalysis - Subclasses must call this method to initialize the +/// AliasAnalysis interface before any other methods are called. +/// +void AliasAnalysis::InitializeAliasAnalysis(Pass *P) { + TD = P->getAnalysisIfAvailable(); + AA = &P->getAnalysis(); +} + +// getAnalysisUsage - All alias analysis implementations should invoke this +// directly (using AliasAnalysis::getAnalysisUsage(AU)). +void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); // All AA's chain +} + +/// getTypeStoreSize - Return the TargetData store size for the given type, +/// if known, or a conservative value otherwise. +/// +uint64_t AliasAnalysis::getTypeStoreSize(const Type *Ty) { + return TD ? TD->getTypeStoreSize(Ty) : UnknownSize; +} + +/// canBasicBlockModify - Return true if it is possible for execution of the +/// specified basic block to modify the value pointed to by Ptr. +/// +bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB, + const Location &Loc) { + return canInstructionRangeModify(BB.front(), BB.back(), Loc); +} + +/// canInstructionRangeModify - Return true if it is possible for the execution +/// of the specified instructions to modify the value pointed to by Ptr. The +/// instructions to consider are all of the instructions in the range of [I1,I2] +/// INCLUSIVE. I1 and I2 must be in the same basic block. +/// +bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1, + const Instruction &I2, + const Location &Loc) { + assert(I1.getParent() == I2.getParent() && + "Instructions not in same basic block!"); + BasicBlock::const_iterator I = &I1; + BasicBlock::const_iterator E = &I2; + ++E; // Convert from inclusive to exclusive range. + + for (; I != E; ++I) // Check every instruction in range + if (getModRefInfo(I, Loc) & Mod) + return true; + return false; +} + +/// isNoAliasCall - Return true if this pointer is returned by a noalias +/// function. +bool llvm::isNoAliasCall(const Value *V) { + if (isa(V) || isa(V)) + return ImmutableCallSite(cast(V)) + .paramHasAttr(0, Attribute::NoAlias); + return false; +} + +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions (but not Global Aliases) +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// NoAlias returns +/// +bool llvm::isIdentifiedObject(const Value *V) { + if (isa(V)) + return true; + if (isa(V) && !isa(V)) + return true; + if (isNoAliasCall(V)) + return true; + if (const Argument *A = dyn_cast(V)) + return A->hasNoAliasAttr() || A->hasByValAttr(); + return false; +} diff --git a/final/lib/Analysis/AliasAnalysisCounter.cpp b/final/lib/Analysis/AliasAnalysisCounter.cpp new file mode 100644 index 00000000000..d947220e078 --- /dev/null +++ b/final/lib/Analysis/AliasAnalysisCounter.cpp @@ -0,0 +1,173 @@ +//===- AliasAnalysisCounter.cpp - Alias Analysis Query Counter ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass which can be used to count how many alias queries +// are being made and how the alias analysis implementation being used responds. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +PrintAll("count-aa-print-all-queries", cl::ReallyHidden, cl::init(true)); +static cl::opt +PrintAllFailures("count-aa-print-all-failed-queries", cl::ReallyHidden); + +namespace { + class AliasAnalysisCounter : public ModulePass, public AliasAnalysis { + unsigned No, May, Partial, Must; + unsigned NoMR, JustRef, JustMod, MR; + Module *M; + public: + static char ID; // Class identification, replacement for typeinfo + AliasAnalysisCounter() : ModulePass(ID) { + initializeAliasAnalysisCounterPass(*PassRegistry::getPassRegistry()); + No = May = Partial = Must = 0; + NoMR = JustRef = JustMod = MR = 0; + } + + void printLine(const char *Desc, unsigned Val, unsigned Sum) { + errs() << " " << Val << " " << Desc << " responses (" + << Val*100/Sum << "%)\n"; + } + ~AliasAnalysisCounter() { + unsigned AASum = No+May+Partial+Must; + unsigned MRSum = NoMR+JustRef+JustMod+MR; + if (AASum + MRSum) { // Print a report if any counted queries occurred... + errs() << "\n===== Alias Analysis Counter Report =====\n" + << " Analysis counted:\n" + << " " << AASum << " Total Alias Queries Performed\n"; + if (AASum) { + printLine("no alias", No, AASum); + printLine("may alias", May, AASum); + printLine("partial alias", Partial, AASum); + printLine("must alias", Must, AASum); + errs() << " Alias Analysis Counter Summary: " << No*100/AASum << "%/" + << May*100/AASum << "%/" + << Partial*100/AASum << "%/" + << Must*100/AASum<<"%\n\n"; + } + + errs() << " " << MRSum << " Total Mod/Ref Queries Performed\n"; + if (MRSum) { + printLine("no mod/ref", NoMR, MRSum); + printLine("ref", JustRef, MRSum); + printLine("mod", JustMod, MRSum); + printLine("mod/ref", MR, MRSum); + errs() << " Mod/Ref Analysis Counter Summary: " <M = &M; + InitializeAliasAnalysis(this); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.addRequired(); + AU.setPreservesAll(); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + // FIXME: We could count these too... + bool pointsToConstantMemory(const Location &Loc, bool OrLocal) { + return getAnalysis().pointsToConstantMemory(Loc, OrLocal); + } + + // Forwarding functions: just delegate to a real AA implementation, counting + // the number of responses... + AliasResult alias(const Location &LocA, const Location &LocB); + + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + }; +} + +char AliasAnalysisCounter::ID = 0; +INITIALIZE_AG_PASS(AliasAnalysisCounter, AliasAnalysis, "count-aa", + "Count Alias Analysis Query Responses", false, true, false) + +ModulePass *llvm::createAliasAnalysisCounterPass() { + return new AliasAnalysisCounter(); +} + +AliasAnalysis::AliasResult +AliasAnalysisCounter::alias(const Location &LocA, const Location &LocB) { + AliasResult R = getAnalysis().alias(LocA, LocB); + + const char *AliasString; + switch (R) { + default: llvm_unreachable("Unknown alias type!"); + case NoAlias: No++; AliasString = "No alias"; break; + case MayAlias: May++; AliasString = "May alias"; break; + case PartialAlias: Partial++; AliasString = "Partial alias"; break; + case MustAlias: Must++; AliasString = "Must alias"; break; + } + + if (PrintAll || (PrintAllFailures && R == MayAlias)) { + errs() << AliasString << ":\t"; + errs() << "[" << LocA.Size << "B] "; + WriteAsOperand(errs(), LocA.Ptr, true, M); + errs() << ", "; + errs() << "[" << LocB.Size << "B] "; + WriteAsOperand(errs(), LocB.Ptr, true, M); + errs() << "\n"; + } + + return R; +} + +AliasAnalysis::ModRefResult +AliasAnalysisCounter::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + ModRefResult R = getAnalysis().getModRefInfo(CS, Loc); + + const char *MRString; + switch (R) { + default: llvm_unreachable("Unknown mod/ref type!"); + case NoModRef: NoMR++; MRString = "NoModRef"; break; + case Ref: JustRef++; MRString = "JustRef"; break; + case Mod: JustMod++; MRString = "JustMod"; break; + case ModRef: MR++; MRString = "ModRef"; break; + } + + if (PrintAll || (PrintAllFailures && R == ModRef)) { + errs() << MRString << ": Ptr: "; + errs() << "[" << Loc.Size << "B] "; + WriteAsOperand(errs(), Loc.Ptr, true, M); + errs() << "\t<->" << *CS.getInstruction() << '\n'; + } + return R; +} diff --git a/final/lib/Analysis/AliasAnalysisEvaluator.cpp b/final/lib/Analysis/AliasAnalysisEvaluator.cpp new file mode 100644 index 00000000000..1afc1b71d93 --- /dev/null +++ b/final/lib/Analysis/AliasAnalysisEvaluator.cpp @@ -0,0 +1,304 @@ +//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple N^2 alias analysis accuracy evaluator. +// Basically, for each function in the program, it simply queries to see how the +// alias analysis implementation answers alias queries between each pair of +// pointers in the function. +// +// This is inspired and adapted from code by: Naveen Neelakantam, Francesco +// Spadini, and Wojciech Stryjewski. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SetVector.h" +using namespace llvm; + +static cl::opt PrintAll("print-all-alias-modref-info", cl::ReallyHidden); + +static cl::opt PrintNoAlias("print-no-aliases", cl::ReallyHidden); +static cl::opt PrintMayAlias("print-may-aliases", cl::ReallyHidden); +static cl::opt PrintPartialAlias("print-partial-aliases", cl::ReallyHidden); +static cl::opt PrintMustAlias("print-must-aliases", cl::ReallyHidden); + +static cl::opt PrintNoModRef("print-no-modref", cl::ReallyHidden); +static cl::opt PrintMod("print-mod", cl::ReallyHidden); +static cl::opt PrintRef("print-ref", cl::ReallyHidden); +static cl::opt PrintModRef("print-modref", cl::ReallyHidden); + +namespace { + class AAEval : public FunctionPass { + unsigned NoAlias, MayAlias, PartialAlias, MustAlias; + unsigned NoModRef, Mod, Ref, ModRef; + + public: + static char ID; // Pass identification, replacement for typeid + AAEval() : FunctionPass(ID) { + initializeAAEvalPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); + } + + bool doInitialization(Module &M) { + NoAlias = MayAlias = PartialAlias = MustAlias = 0; + NoModRef = Mod = Ref = ModRef = 0; + + if (PrintAll) { + PrintNoAlias = PrintMayAlias = true; + PrintPartialAlias = PrintMustAlias = true; + PrintNoModRef = PrintMod = PrintRef = PrintModRef = true; + } + return false; + } + + bool runOnFunction(Function &F); + bool doFinalization(Module &M); + }; +} + +char AAEval::ID = 0; +INITIALIZE_PASS_BEGIN(AAEval, "aa-eval", + "Exhaustive Alias Analysis Precision Evaluator", false, true) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(AAEval, "aa-eval", + "Exhaustive Alias Analysis Precision Evaluator", false, true) + +FunctionPass *llvm::createAAEvalPass() { return new AAEval(); } + +static void PrintResults(const char *Msg, bool P, const Value *V1, + const Value *V2, const Module *M) { + if (P) { + std::string o1, o2; + { + raw_string_ostream os1(o1), os2(o2); + WriteAsOperand(os1, V1, true, M); + WriteAsOperand(os2, V2, true, M); + } + + if (o2 < o1) + std::swap(o1, o2); + errs() << " " << Msg << ":\t" + << o1 << ", " + << o2 << "\n"; + } +} + +static inline void +PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr, + Module *M) { + if (P) { + errs() << " " << Msg << ": Ptr: "; + WriteAsOperand(errs(), Ptr, true, M); + errs() << "\t<->" << *I << '\n'; + } +} + +static inline void +PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB, + Module *M) { + if (P) { + errs() << " " << Msg << ": " << *CSA.getInstruction() + << " <-> " << *CSB.getInstruction() << '\n'; + } +} + +static inline bool isInterestingPointer(Value *V) { + return V->getType()->isPointerTy() + && !isa(V); +} + +bool AAEval::runOnFunction(Function &F) { + AliasAnalysis &AA = getAnalysis(); + + SetVector Pointers; + SetVector CallSites; + + for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) + if (I->getType()->isPointerTy()) // Add all pointer arguments. + Pointers.insert(I); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (I->getType()->isPointerTy()) // Add all pointer instructions. + Pointers.insert(&*I); + Instruction &Inst = *I; + if (CallSite CS = cast(&Inst)) { + Value *Callee = CS.getCalledValue(); + // Skip actual functions for direct function calls. + if (!isa(Callee) && isInterestingPointer(Callee)) + Pointers.insert(Callee); + // Consider formals. + for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + AI != AE; ++AI) + if (isInterestingPointer(*AI)) + Pointers.insert(*AI); + CallSites.insert(CS); + } else { + // Consider all operands. + for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); + OI != OE; ++OI) + if (isInterestingPointer(*OI)) + Pointers.insert(*OI); + } + } + + if (PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || + PrintNoModRef || PrintMod || PrintRef || PrintModRef) + errs() << "Function: " << F.getName() << ": " << Pointers.size() + << " pointers, " << CallSites.size() << " call sites\n"; + + // iterate over the worklist, and run the full (n^2)/2 disambiguations + for (SetVector::iterator I1 = Pointers.begin(), E = Pointers.end(); + I1 != E; ++I1) { + uint64_t I1Size = AliasAnalysis::UnknownSize; + const Type *I1ElTy = cast((*I1)->getType())->getElementType(); + if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); + + for (SetVector::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { + uint64_t I2Size = AliasAnalysis::UnknownSize; + const Type *I2ElTy =cast((*I2)->getType())->getElementType(); + if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); + + switch (AA.alias(*I1, I1Size, *I2, I2Size)) { + case AliasAnalysis::NoAlias: + PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); + ++NoAlias; break; + case AliasAnalysis::MayAlias: + PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); + ++MayAlias; break; + case AliasAnalysis::PartialAlias: + PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2, + F.getParent()); + ++PartialAlias; break; + case AliasAnalysis::MustAlias: + PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); + ++MustAlias; break; + default: + errs() << "Unknown alias query result!\n"; + } + } + } + + // Mod/ref alias analysis: compare all pairs of calls and values + for (SetVector::iterator C = CallSites.begin(), + Ce = CallSites.end(); C != Ce; ++C) { + Instruction *I = C->getInstruction(); + + for (SetVector::iterator V = Pointers.begin(), Ve = Pointers.end(); + V != Ve; ++V) { + uint64_t Size = AliasAnalysis::UnknownSize; + const Type *ElTy = cast((*V)->getType())->getElementType(); + if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy); + + switch (AA.getModRefInfo(*C, *V, Size)) { + case AliasAnalysis::NoModRef: + PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent()); + ++NoModRef; break; + case AliasAnalysis::Mod: + PrintModRefResults("Just Mod", PrintMod, I, *V, F.getParent()); + ++Mod; break; + case AliasAnalysis::Ref: + PrintModRefResults("Just Ref", PrintRef, I, *V, F.getParent()); + ++Ref; break; + case AliasAnalysis::ModRef: + PrintModRefResults("Both ModRef", PrintModRef, I, *V, F.getParent()); + ++ModRef; break; + default: + errs() << "Unknown alias query result!\n"; + } + } + } + + // Mod/ref alias analysis: compare all pairs of calls + for (SetVector::iterator C = CallSites.begin(), + Ce = CallSites.end(); C != Ce; ++C) { + for (SetVector::iterator D = CallSites.begin(); D != Ce; ++D) { + if (D == C) + continue; + switch (AA.getModRefInfo(*C, *D)) { + case AliasAnalysis::NoModRef: + PrintModRefResults("NoModRef", PrintNoModRef, *C, *D, F.getParent()); + ++NoModRef; break; + case AliasAnalysis::Mod: + PrintModRefResults("Just Mod", PrintMod, *C, *D, F.getParent()); + ++Mod; break; + case AliasAnalysis::Ref: + PrintModRefResults("Just Ref", PrintRef, *C, *D, F.getParent()); + ++Ref; break; + case AliasAnalysis::ModRef: + PrintModRefResults("Both ModRef", PrintModRef, *C, *D, F.getParent()); + ++ModRef; break; + } + } + } + + return false; +} + +static void PrintPercent(unsigned Num, unsigned Sum) { + errs() << "(" << Num*100ULL/Sum << "." + << ((Num*1000ULL/Sum) % 10) << "%)\n"; +} + +bool AAEval::doFinalization(Module &M) { + unsigned AliasSum = NoAlias + MayAlias + PartialAlias + MustAlias; + errs() << "===== Alias Analysis Evaluator Report =====\n"; + if (AliasSum == 0) { + errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; + } else { + errs() << " " << AliasSum << " Total Alias Queries Performed\n"; + errs() << " " << NoAlias << " no alias responses "; + PrintPercent(NoAlias, AliasSum); + errs() << " " << MayAlias << " may alias responses "; + PrintPercent(MayAlias, AliasSum); + errs() << " " << PartialAlias << " partial alias responses "; + PrintPercent(PartialAlias, AliasSum); + errs() << " " << MustAlias << " must alias responses "; + PrintPercent(MustAlias, AliasSum); + errs() << " Alias Analysis Evaluator Pointer Alias Summary: " + << NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/" + << PartialAlias*100/AliasSum << "%/" + << MustAlias*100/AliasSum << "%\n"; + } + + // Display the summary for mod/ref analysis + unsigned ModRefSum = NoModRef + Mod + Ref + ModRef; + if (ModRefSum == 0) { + errs() << " Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n"; + } else { + errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; + errs() << " " << NoModRef << " no mod/ref responses "; + PrintPercent(NoModRef, ModRefSum); + errs() << " " << Mod << " mod responses "; + PrintPercent(Mod, ModRefSum); + errs() << " " << Ref << " ref responses "; + PrintPercent(Ref, ModRefSum); + errs() << " " << ModRef << " mod & ref responses "; + PrintPercent(ModRef, ModRefSum); + errs() << " Alias Analysis Evaluator Mod/Ref Summary: " + << NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/" + << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n"; + } + + return false; +} diff --git a/final/lib/Analysis/AliasDebugger.cpp b/final/lib/Analysis/AliasDebugger.cpp new file mode 100644 index 00000000000..f15c05153e1 --- /dev/null +++ b/final/lib/Analysis/AliasDebugger.cpp @@ -0,0 +1,138 @@ +//===- AliasDebugger.cpp - Simple Alias Analysis Use Checker --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This simple pass checks alias analysis users to ensure that if they +// create a new value, they do not query AA without informing it of the value. +// It acts as a shim over any other AA pass you want. +// +// Yes keeping track of every value in the program is expensive, but this is +// a debugging pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include +using namespace llvm; + +namespace { + + class AliasDebugger : public ModulePass, public AliasAnalysis { + + //What we do is simple. Keep track of every value the AA could + //know about, and verify that queries are one of those. + //A query to a value that didn't exist when the AA was created + //means someone forgot to update the AA when creating new values + + std::set Vals; + + public: + static char ID; // Class identification, replacement for typeinfo + AliasDebugger() : ModulePass(ID) { + initializeAliasDebuggerPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) { + InitializeAliasAnalysis(this); // set up super class + + for(Module::global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + Vals.insert(&*I); + for (User::const_op_iterator OI = I->op_begin(), + OE = I->op_end(); OI != OE; ++OI) + Vals.insert(*OI); + } + + for(Module::iterator I = M.begin(), + E = M.end(); I != E; ++I){ + Vals.insert(&*I); + if(!I->isDeclaration()) { + for (Function::arg_iterator AI = I->arg_begin(), AE = I->arg_end(); + AI != AE; ++AI) + Vals.insert(&*AI); + for (Function::const_iterator FI = I->begin(), FE = I->end(); + FI != FE; ++FI) + for (BasicBlock::const_iterator BI = FI->begin(), BE = FI->end(); + BI != BE; ++BI) { + Vals.insert(&*BI); + for (User::const_op_iterator OI = BI->op_begin(), + OE = BI->op_end(); OI != OE; ++OI) + Vals.insert(*OI); + } + } + + } + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.setPreservesAll(); // Does not transform code + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const Location &LocA, const Location &LocB) { + assert(Vals.find(LocA.Ptr) != Vals.end() && + "Never seen value in AA before"); + assert(Vals.find(LocB.Ptr) != Vals.end() && + "Never seen value in AA before"); + return AliasAnalysis::alias(LocA, LocB); + } + + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + assert(Vals.find(Loc.Ptr) != Vals.end() && "Never seen value in AA before"); + return AliasAnalysis::getModRefInfo(CS, Loc); + } + + ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1,CS2); + } + + bool pointsToConstantMemory(const Location &Loc, bool OrLocal) { + assert(Vals.find(Loc.Ptr) != Vals.end() && "Never seen value in AA before"); + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + } + + virtual void deleteValue(Value *V) { + assert(Vals.find(V) != Vals.end() && "Never seen value in AA before"); + AliasAnalysis::deleteValue(V); + } + virtual void copyValue(Value *From, Value *To) { + Vals.insert(To); + AliasAnalysis::copyValue(From, To); + } + + }; +} + +char AliasDebugger::ID = 0; +INITIALIZE_AG_PASS(AliasDebugger, AliasAnalysis, "debug-aa", + "AA use debugger", false, true, false) + +Pass *llvm::createAliasDebugger() { return new AliasDebugger(); } + diff --git a/final/lib/Analysis/AliasSetTracker.cpp b/final/lib/Analysis/AliasSetTracker.cpp new file mode 100644 index 00000000000..3a46976d66f --- /dev/null +++ b/final/lib/Analysis/AliasSetTracker.cpp @@ -0,0 +1,648 @@ +//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// +// +// 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 AliasSetTracker and AliasSet classes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// mergeSetIn - Merge the specified alias set into this alias set. +/// +void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { + assert(!AS.Forward && "Alias set is already forwarding!"); + assert(!Forward && "This set is a forwarding set!!"); + + // Update the alias and access types of this set... + AccessTy |= AS.AccessTy; + AliasTy |= AS.AliasTy; + Volatile |= AS.Volatile; + + if (AliasTy == MustAlias) { + // Check that these two merged sets really are must aliases. Since both + // used to be must-alias sets, we can just check any pointer from each set + // for aliasing. + AliasAnalysis &AA = AST.getAliasAnalysis(); + PointerRec *L = getSomePointer(); + PointerRec *R = AS.getSomePointer(); + + // If the pointers are not a must-alias pair, this set becomes a may alias. + if (AA.alias(AliasAnalysis::Location(L->getValue(), + L->getSize(), + L->getTBAAInfo()), + AliasAnalysis::Location(R->getValue(), + R->getSize(), + R->getTBAAInfo())) + != AliasAnalysis::MustAlias) + AliasTy = MayAlias; + } + + if (CallSites.empty()) { // Merge call sites... + if (!AS.CallSites.empty()) + std::swap(CallSites, AS.CallSites); + } else if (!AS.CallSites.empty()) { + CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end()); + AS.CallSites.clear(); + } + + AS.Forward = this; // Forward across AS now... + addRef(); // AS is now pointing to us... + + // Merge the list of constituent pointers... + if (AS.PtrList) { + *PtrListEnd = AS.PtrList; + AS.PtrList->setPrevInList(PtrListEnd); + PtrListEnd = AS.PtrListEnd; + + AS.PtrList = 0; + AS.PtrListEnd = &AS.PtrList; + assert(*AS.PtrListEnd == 0 && "End of list is not null?"); + } +} + +void AliasSetTracker::removeAliasSet(AliasSet *AS) { + if (AliasSet *Fwd = AS->Forward) { + Fwd->dropRef(*this); + AS->Forward = 0; + } + AliasSets.erase(AS); +} + +void AliasSet::removeFromTracker(AliasSetTracker &AST) { + assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); + AST.removeAliasSet(this); +} + +void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry, + uint64_t Size, const MDNode *TBAAInfo, + bool KnownMustAlias) { + assert(!Entry.hasAliasSet() && "Entry already in set!"); + + // Check to see if we have to downgrade to _may_ alias. + if (isMustAlias() && !KnownMustAlias) + if (PointerRec *P = getSomePointer()) { + AliasAnalysis &AA = AST.getAliasAnalysis(); + AliasAnalysis::AliasResult Result = + AA.alias(AliasAnalysis::Location(P->getValue(), P->getSize(), + P->getTBAAInfo()), + AliasAnalysis::Location(Entry.getValue(), Size, TBAAInfo)); + if (Result != AliasAnalysis::MustAlias) + AliasTy = MayAlias; + else // First entry of must alias must have maximum size! + P->updateSizeAndTBAAInfo(Size, TBAAInfo); + assert(Result != AliasAnalysis::NoAlias && "Cannot be part of must set!"); + } + + Entry.setAliasSet(this); + Entry.updateSizeAndTBAAInfo(Size, TBAAInfo); + + // Add it to the end of the list... + assert(*PtrListEnd == 0 && "End of list is not null?"); + *PtrListEnd = &Entry; + PtrListEnd = Entry.setPrevInList(PtrListEnd); + assert(*PtrListEnd == 0 && "End of list is not null?"); + addRef(); // Entry points to alias set. +} + +void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) { + CallSites.push_back(CS.getInstruction()); + + AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(CS); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return; + if (AliasAnalysis::onlyReadsMemory(Behavior)) { + AliasTy = MayAlias; + AccessTy |= Refs; + return; + } + + // FIXME: This should use mod/ref information to make this not suck so bad + AliasTy = MayAlias; + AccessTy = ModRef; +} + +/// aliasesPointer - Return true if the specified pointer "may" (or must) +/// alias one of the members in the set. +/// +bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size, + const MDNode *TBAAInfo, + AliasAnalysis &AA) const { + if (AliasTy == MustAlias) { + assert(CallSites.empty() && "Illegal must alias set!"); + + // If this is a set of MustAliases, only check to see if the pointer aliases + // SOME value in the set. + PointerRec *SomePtr = getSomePointer(); + assert(SomePtr && "Empty must-alias set??"); + return AA.alias(AliasAnalysis::Location(SomePtr->getValue(), + SomePtr->getSize(), + SomePtr->getTBAAInfo()), + AliasAnalysis::Location(Ptr, Size, TBAAInfo)); + } + + // If this is a may-alias set, we have to check all of the pointers in the set + // to be sure it doesn't alias the set... + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.alias(AliasAnalysis::Location(Ptr, Size, TBAAInfo), + AliasAnalysis::Location(I.getPointer(), I.getSize(), + I.getTBAAInfo()))) + return true; + + // Check the call sites list and invoke list... + if (!CallSites.empty()) { + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (AA.getModRefInfo(CallSites[i], + AliasAnalysis::Location(Ptr, Size, TBAAInfo)) != + AliasAnalysis::NoModRef) + return true; + } + + return false; +} + +bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { + if (AA.doesNotAccessMemory(CS)) + return false; + + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (AA.getModRefInfo(getCallSite(i), CS) != AliasAnalysis::NoModRef || + AA.getModRefInfo(CS, getCallSite(i)) != AliasAnalysis::NoModRef) + return true; + } + + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.getModRefInfo(CS, I.getPointer(), I.getSize()) != + AliasAnalysis::NoModRef) + return true; + + return false; +} + +void AliasSetTracker::clear() { + // Delete all the PointerRec entries. + for (PointerMapType::iterator I = PointerMap.begin(), E = PointerMap.end(); + I != E; ++I) + I->second->eraseFromList(); + + PointerMap.clear(); + + // The alias sets should all be clear now. + AliasSets.clear(); +} + + +/// findAliasSetForPointer - Given a pointer, find the one alias set to put the +/// instruction referring to the pointer into. If there are multiple alias sets +/// that may alias the pointer, merge them together and return the unified set. +/// +AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr, + uint64_t Size, + const MDNode *TBAAInfo) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I->Forward || !I->aliasesPointer(Ptr, Size, TBAAInfo, AA)) continue; + + if (FoundSet == 0) { // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + } else { // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. + } + } + + return FoundSet; +} + +/// containsPointer - Return true if the specified location is represented by +/// this alias set, false otherwise. This does not modify the AST object or +/// alias sets. +bool AliasSetTracker::containsPointer(Value *Ptr, uint64_t Size, + const MDNode *TBAAInfo) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesPointer(Ptr, Size, TBAAInfo, AA)) + return true; + return false; +} + + + +AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I->Forward || !I->aliasesCallSite(CS, AA)) + continue; + + if (FoundSet == 0) // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + else if (!I->Forward) // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. + } + return FoundSet; +} + + + + +/// getAliasSetForPointer - Return the alias set that the specified pointer +/// lives in. +AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, uint64_t Size, + const MDNode *TBAAInfo, + bool *New) { + AliasSet::PointerRec &Entry = getEntryFor(Pointer); + + // Check to see if the pointer is already known. + if (Entry.hasAliasSet()) { + Entry.updateSizeAndTBAAInfo(Size, TBAAInfo); + // Return the set! + return *Entry.getAliasSet(*this)->getForwardedTarget(*this); + } + + if (AliasSet *AS = findAliasSetForPointer(Pointer, Size, TBAAInfo)) { + // Add it to the alias set it aliases. + AS->addPointer(*this, Entry, Size, TBAAInfo); + return *AS; + } + + if (New) *New = true; + // Otherwise create a new alias set to hold the loaded pointer. + AliasSets.push_back(new AliasSet()); + AliasSets.back().addPointer(*this, Entry, Size, TBAAInfo); + return AliasSets.back(); +} + +bool AliasSetTracker::add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo) { + bool NewPtr; + addPointer(Ptr, Size, TBAAInfo, AliasSet::NoModRef, NewPtr); + return NewPtr; +} + + +bool AliasSetTracker::add(LoadInst *LI) { + bool NewPtr; + AliasSet &AS = addPointer(LI->getOperand(0), + AA.getTypeStoreSize(LI->getType()), + LI->getMetadata(LLVMContext::MD_tbaa), + AliasSet::Refs, NewPtr); + if (LI->isVolatile()) AS.setVolatile(); + return NewPtr; +} + +bool AliasSetTracker::add(StoreInst *SI) { + bool NewPtr; + Value *Val = SI->getOperand(0); + AliasSet &AS = addPointer(SI->getOperand(1), + AA.getTypeStoreSize(Val->getType()), + SI->getMetadata(LLVMContext::MD_tbaa), + AliasSet::Mods, NewPtr); + if (SI->isVolatile()) AS.setVolatile(); + return NewPtr; +} + +bool AliasSetTracker::add(VAArgInst *VAAI) { + bool NewPtr; + addPointer(VAAI->getOperand(0), AliasAnalysis::UnknownSize, + VAAI->getMetadata(LLVMContext::MD_tbaa), + AliasSet::ModRef, NewPtr); + return NewPtr; +} + + +bool AliasSetTracker::add(CallSite CS) { + if (isa(CS.getInstruction())) + return true; // Ignore DbgInfo Intrinsics. + if (AA.doesNotAccessMemory(CS)) + return true; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (AS) { + AS->addCallSite(CS, AA); + return false; + } + AliasSets.push_back(new AliasSet()); + AS = &AliasSets.back(); + AS->addCallSite(CS, AA); + return true; +} + +bool AliasSetTracker::add(Instruction *I) { + // Dispatch to one of the other add methods. + if (LoadInst *LI = dyn_cast(I)) + return add(LI); + if (StoreInst *SI = dyn_cast(I)) + return add(SI); + if (CallInst *CI = dyn_cast(I)) + return add(CI); + if (InvokeInst *II = dyn_cast(I)) + return add(II); + if (VAArgInst *VAAI = dyn_cast(I)) + return add(VAAI); + return true; +} + +void AliasSetTracker::add(BasicBlock &BB) { + for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) + add(I); +} + +void AliasSetTracker::add(const AliasSetTracker &AST) { + assert(&AA == &AST.AA && + "Merging AliasSetTracker objects with different Alias Analyses!"); + + // Loop over all of the alias sets in AST, adding the pointers contained + // therein into the current alias sets. This can cause alias sets to be + // merged together in the current AST. + for (const_iterator I = AST.begin(), E = AST.end(); I != E; ++I) { + if (I->Forward) continue; // Ignore forwarding alias sets + + AliasSet &AS = const_cast(*I); + + // If there are any call sites in the alias set, add them to this AST. + for (unsigned i = 0, e = AS.CallSites.size(); i != e; ++i) + add(AS.CallSites[i]); + + // Loop over all of the pointers in this alias set. + bool X; + for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) { + AliasSet &NewAS = addPointer(ASI.getPointer(), ASI.getSize(), + ASI.getTBAAInfo(), + (AliasSet::AccessType)AS.AccessTy, X); + if (AS.isVolatile()) NewAS.setVolatile(); + } + } +} + +/// remove - Remove the specified (potentially non-empty) alias set from the +/// tracker. +void AliasSetTracker::remove(AliasSet &AS) { + // Drop all call sites. + AS.CallSites.clear(); + + // Clear the alias set. + unsigned NumRefs = 0; + while (!AS.empty()) { + AliasSet::PointerRec *P = AS.PtrList; + + Value *ValToRemove = P->getValue(); + + // Unlink and delete entry from the list of values. + P->eraseFromList(); + + // Remember how many references need to be dropped. + ++NumRefs; + + // Finally, remove the entry. + PointerMap.erase(ValToRemove); + } + + // Stop using the alias set, removing it. + AS.RefCount -= NumRefs; + if (AS.RefCount == 0) + AS.removeFromTracker(*this); +} + +bool +AliasSetTracker::remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo) { + AliasSet *AS = findAliasSetForPointer(Ptr, Size, TBAAInfo); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(LoadInst *LI) { + uint64_t Size = AA.getTypeStoreSize(LI->getType()); + const MDNode *TBAAInfo = LI->getMetadata(LLVMContext::MD_tbaa); + AliasSet *AS = findAliasSetForPointer(LI->getOperand(0), Size, TBAAInfo); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(StoreInst *SI) { + uint64_t Size = AA.getTypeStoreSize(SI->getOperand(0)->getType()); + const MDNode *TBAAInfo = SI->getMetadata(LLVMContext::MD_tbaa); + AliasSet *AS = findAliasSetForPointer(SI->getOperand(1), Size, TBAAInfo); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(VAArgInst *VAAI) { + AliasSet *AS = findAliasSetForPointer(VAAI->getOperand(0), + AliasAnalysis::UnknownSize, + VAAI->getMetadata(LLVMContext::MD_tbaa)); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(CallSite CS) { + if (AA.doesNotAccessMemory(CS)) + return false; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(Instruction *I) { + // Dispatch to one of the other remove methods... + if (LoadInst *LI = dyn_cast(I)) + return remove(LI); + if (StoreInst *SI = dyn_cast(I)) + return remove(SI); + if (CallInst *CI = dyn_cast(I)) + return remove(CI); + if (VAArgInst *VAAI = dyn_cast(I)) + return remove(VAAI); + return true; +} + + +// deleteValue method - This method is used to remove a pointer value from the +// AliasSetTracker entirely. It should be used when an instruction is deleted +// from the program to update the AST. If you don't use this, you would have +// dangling pointers to deleted instructions. +// +void AliasSetTracker::deleteValue(Value *PtrVal) { + // Notify the alias analysis implementation that this value is gone. + AA.deleteValue(PtrVal); + + // If this is a call instruction, remove the callsite from the appropriate + // AliasSet (if present). + if (CallSite CS = PtrVal) { + if (!AA.doesNotAccessMemory(CS)) { + // Scan all the alias sets to see if this call site is contained. + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I->Forward) continue; + + I->removeCallSite(CS); + } + } + } + + // First, look up the PointerRec for this pointer. + PointerMapType::iterator I = PointerMap.find(PtrVal); + if (I == PointerMap.end()) return; // Noop + + // If we found one, remove the pointer from the alias set it is in. + AliasSet::PointerRec *PtrValEnt = I->second; + AliasSet *AS = PtrValEnt->getAliasSet(*this); + + // Unlink and delete from the list of values. + PtrValEnt->eraseFromList(); + + // Stop using the alias set. + AS->dropRef(*this); + + PointerMap.erase(I); +} + +// copyValue - This method should be used whenever a preexisting value in the +// program is copied or cloned, introducing a new value. Note that it is ok for +// clients that use this method to introduce the same value multiple times: if +// the tracker already knows about a value, it will ignore the request. +// +void AliasSetTracker::copyValue(Value *From, Value *To) { + // Notify the alias analysis implementation that this value is copied. + AA.copyValue(From, To); + + // First, look up the PointerRec for this pointer. + PointerMapType::iterator I = PointerMap.find(From); + if (I == PointerMap.end()) + return; // Noop + assert(I->second->hasAliasSet() && "Dead entry?"); + + AliasSet::PointerRec &Entry = getEntryFor(To); + if (Entry.hasAliasSet()) return; // Already in the tracker! + + // Add it to the alias set it aliases... + I = PointerMap.find(From); + AliasSet *AS = I->second->getAliasSet(*this); + AS->addPointer(*this, Entry, I->second->getSize(), + I->second->getTBAAInfo(), + true); +} + + + +//===----------------------------------------------------------------------===// +// AliasSet/AliasSetTracker Printing Support +//===----------------------------------------------------------------------===// + +void AliasSet::print(raw_ostream &OS) const { + OS << " AliasSet[" << (void*)this << ", " << RefCount << "] "; + OS << (AliasTy == MustAlias ? "must" : "may") << " alias, "; + switch (AccessTy) { + case NoModRef: OS << "No access "; break; + case Refs : OS << "Ref "; break; + case Mods : OS << "Mod "; break; + case ModRef : OS << "Mod/Ref "; break; + default: llvm_unreachable("Bad value for AccessTy!"); + } + if (isVolatile()) OS << "[volatile] "; + if (Forward) + OS << " forwarding to " << (void*)Forward; + + + if (!empty()) { + OS << "Pointers: "; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I != begin()) OS << ", "; + WriteAsOperand(OS << "(", I.getPointer()); + OS << ", " << I.getSize() << ")"; + } + } + if (!CallSites.empty()) { + OS << "\n " << CallSites.size() << " Call Sites: "; + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (i) OS << ", "; + WriteAsOperand(OS, CallSites[i]); + } + } + OS << "\n"; +} + +void AliasSetTracker::print(raw_ostream &OS) const { + OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for " + << PointerMap.size() << " pointer values.\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) + I->print(OS); + OS << "\n"; +} + +void AliasSet::dump() const { print(dbgs()); } +void AliasSetTracker::dump() const { print(dbgs()); } + +//===----------------------------------------------------------------------===// +// ASTCallbackVH Class Implementation +//===----------------------------------------------------------------------===// + +void AliasSetTracker::ASTCallbackVH::deleted() { + assert(AST && "ASTCallbackVH called with a null AliasSetTracker!"); + AST->deleteValue(getValPtr()); + // this now dangles! +} + +AliasSetTracker::ASTCallbackVH::ASTCallbackVH(Value *V, AliasSetTracker *ast) + : CallbackVH(V), AST(ast) {} + +AliasSetTracker::ASTCallbackVH & +AliasSetTracker::ASTCallbackVH::operator=(Value *V) { + return *this = ASTCallbackVH(V, AST); +} + +//===----------------------------------------------------------------------===// +// AliasSetPrinter Pass +//===----------------------------------------------------------------------===// + +namespace { + class AliasSetPrinter : public FunctionPass { + AliasSetTracker *Tracker; + public: + static char ID; // Pass identification, replacement for typeid + AliasSetPrinter() : FunctionPass(ID) { + initializeAliasSetPrinterPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual bool runOnFunction(Function &F) { + Tracker = new AliasSetTracker(getAnalysis()); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + Tracker->add(&*I); + Tracker->print(errs()); + delete Tracker; + return false; + } + }; +} + +char AliasSetPrinter::ID = 0; +INITIALIZE_PASS_BEGIN(AliasSetPrinter, "print-alias-sets", + "Alias Set Printer", false, true) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(AliasSetPrinter, "print-alias-sets", + "Alias Set Printer", false, true) diff --git a/final/lib/Analysis/Analysis.cpp b/final/lib/Analysis/Analysis.cpp new file mode 100644 index 00000000000..74a27643269 --- /dev/null +++ b/final/lib/Analysis/Analysis.cpp @@ -0,0 +1,103 @@ +//===-- Analysis.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Analysis.h" +#include "llvm/InitializePasses.h" +#include "llvm/Analysis/Verifier.h" +#include + +using namespace llvm; + +/// initializeAnalysis - Initialize all passes linked into the Analysis library. +void llvm::initializeAnalysis(PassRegistry &Registry) { + initializeAliasAnalysisAnalysisGroup(Registry); + initializeAliasAnalysisCounterPass(Registry); + initializeAAEvalPass(Registry); + initializeAliasDebuggerPass(Registry); + initializeAliasSetPrinterPass(Registry); + initializeNoAAPass(Registry); + initializeBasicAliasAnalysisPass(Registry); + initializeCFGViewerPass(Registry); + initializeCFGPrinterPass(Registry); + initializeCFGOnlyViewerPass(Registry); + initializeCFGOnlyPrinterPass(Registry); + initializePrintDbgInfoPass(Registry); + initializeDominanceFrontierPass(Registry); + initializeDomViewerPass(Registry); + initializeDomPrinterPass(Registry); + initializeDomOnlyViewerPass(Registry); + initializePostDomViewerPass(Registry); + initializeDomOnlyPrinterPass(Registry); + initializePostDomPrinterPass(Registry); + initializePostDomOnlyViewerPass(Registry); + initializePostDomOnlyPrinterPass(Registry); + initializeIVUsersPass(Registry); + initializeInstCountPass(Registry); + initializeIntervalPartitionPass(Registry); + initializeLazyValueInfoPass(Registry); + initializeLibCallAliasAnalysisPass(Registry); + initializeLintPass(Registry); + initializeLoopDependenceAnalysisPass(Registry); + initializeLoopInfoPass(Registry); + initializeMemDepPrinterPass(Registry); + initializeMemoryDependenceAnalysisPass(Registry); + initializeModuleDebugInfoPrinterPass(Registry); + initializePostDominatorTreePass(Registry); + initializePostDominanceFrontierPass(Registry); + initializeProfileEstimatorPassPass(Registry); + initializeNoProfileInfoPass(Registry); + initializeNoPathProfileInfoPass(Registry); + initializeProfileInfoAnalysisGroup(Registry); + initializePathProfileInfoAnalysisGroup(Registry); + initializeLoaderPassPass(Registry); + initializePathProfileLoaderPassPass(Registry); + initializeProfileVerifierPassPass(Registry); + initializePathProfileVerifierPass(Registry); + initializeRegionInfoPass(Registry); + initializeRegionViewerPass(Registry); + initializeRegionPrinterPass(Registry); + initializeRegionOnlyViewerPass(Registry); + initializeRegionOnlyPrinterPass(Registry); + initializeScalarEvolutionPass(Registry); + initializeScalarEvolutionAliasAnalysisPass(Registry); + initializeTypeBasedAliasAnalysisPass(Registry); +} + +void LLVMInitializeAnalysis(LLVMPassRegistryRef R) { + initializeAnalysis(*unwrap(R)); +} + +LLVMBool LLVMVerifyModule(LLVMModuleRef M, LLVMVerifierFailureAction Action, + char **OutMessages) { + std::string Messages; + + LLVMBool Result = verifyModule(*unwrap(M), + static_cast(Action), + OutMessages? &Messages : 0); + + if (OutMessages) + *OutMessages = strdup(Messages.c_str()); + + return Result; +} + +LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action) { + return verifyFunction(*unwrap(Fn), + static_cast(Action)); +} + +void LLVMViewFunctionCFG(LLVMValueRef Fn) { + Function *F = unwrap(Fn); + F->viewCFG(); +} + +void LLVMViewFunctionCFGOnly(LLVMValueRef Fn) { + Function *F = unwrap(Fn); + F->viewCFGOnly(); +} diff --git a/final/lib/Analysis/BasicAliasAnalysis.cpp b/final/lib/Analysis/BasicAliasAnalysis.cpp new file mode 100644 index 00000000000..f7bcd9ec44d --- /dev/null +++ b/final/lib/Analysis/BasicAliasAnalysis.cpp @@ -0,0 +1,1170 @@ +//===- BasicAliasAnalysis.cpp - Stateless Alias Analysis Impl -------------===// +// +// 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 primary stateless implementation of the +// Alias Analysis interface that implements identities (two different +// globals cannot alias, etc), but does no stateful analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Useful predicates +//===----------------------------------------------------------------------===// + +/// isKnownNonNull - Return true if we know that the specified value is never +/// null. +static bool isKnownNonNull(const Value *V) { + // Alloca never returns null, malloc might. + if (isa(V)) return true; + + // A byval argument is never null. + if (const Argument *A = dyn_cast(V)) + return A->hasByValAttr(); + + // Global values are not null unless extern weak. + if (const GlobalValue *GV = dyn_cast(V)) + return !GV->hasExternalWeakLinkage(); + return false; +} + +/// isNonEscapingLocalObject - Return true if the pointer is to a function-local +/// object that never escapes from the function. +static bool isNonEscapingLocalObject(const Value *V) { + // If this is a local allocation, check to see if it escapes. + if (isa(V) || isNoAliasCall(V)) + // Set StoreCaptures to True so that we can assume in our callers that the + // pointer is not the result of a load instruction. Currently + // PointerMayBeCaptured doesn't have any special analysis for the + // StoreCaptures=false case; if it did, our callers could be refined to be + // more precise. + return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + + // If this is an argument that corresponds to a byval or noalias argument, + // then it has not escaped before entering the function. Check if it escapes + // inside the function. + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr() || A->hasNoAliasAttr()) { + // Don't bother analyzing arguments already known not to escape. + if (A->hasNoCaptureAttr()) + return true; + return !PointerMayBeCaptured(V, false, /*StoreCaptures=*/true); + } + return false; +} + +/// isEscapeSource - Return true if the pointer is one which would have +/// been considered an escape by isNonEscapingLocalObject. +static bool isEscapeSource(const Value *V) { + if (isa(V) || isa(V) || isa(V)) + return true; + + // The load case works because isNonEscapingLocalObject considers all + // stores to be escapes (it passes true for the StoreCaptures argument + // to PointerMayBeCaptured). + if (isa(V)) + return true; + + return false; +} + +/// getObjectSize - Return the size of the object specified by V, or +/// UnknownSize if unknown. +static uint64_t getObjectSize(const Value *V, const TargetData &TD) { + const Type *AccessTy; + if (const GlobalVariable *GV = dyn_cast(V)) { + if (!GV->hasDefinitiveInitializer()) + return AliasAnalysis::UnknownSize; + AccessTy = GV->getType()->getElementType(); + } else if (const AllocaInst *AI = dyn_cast(V)) { + if (!AI->isArrayAllocation()) + AccessTy = AI->getType()->getElementType(); + else + return AliasAnalysis::UnknownSize; + } else if (const CallInst* CI = extractMallocCall(V)) { + if (!isArrayMalloc(V, &TD)) + // The size is the argument to the malloc call. + if (const ConstantInt* C = dyn_cast(CI->getArgOperand(0))) + return C->getZExtValue(); + return AliasAnalysis::UnknownSize; + } else if (const Argument *A = dyn_cast(V)) { + if (A->hasByValAttr()) + AccessTy = cast(A->getType())->getElementType(); + else + return AliasAnalysis::UnknownSize; + } else { + return AliasAnalysis::UnknownSize; + } + + if (AccessTy->isSized()) + return TD.getTypeAllocSize(AccessTy); + return AliasAnalysis::UnknownSize; +} + +/// isObjectSmallerThan - Return true if we can prove that the object specified +/// by V is smaller than Size. +static bool isObjectSmallerThan(const Value *V, uint64_t Size, + const TargetData &TD) { + uint64_t ObjectSize = getObjectSize(V, TD); + return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize < Size; +} + +/// isObjectSize - Return true if we can prove that the object specified +/// by V has size Size. +static bool isObjectSize(const Value *V, uint64_t Size, + const TargetData &TD) { + uint64_t ObjectSize = getObjectSize(V, TD); + return ObjectSize != AliasAnalysis::UnknownSize && ObjectSize == Size; +} + +//===----------------------------------------------------------------------===// +// GetElementPtr Instruction Decomposition and Analysis +//===----------------------------------------------------------------------===// + +namespace { + enum ExtensionKind { + EK_NotExtended, + EK_SignExt, + EK_ZeroExt + }; + + struct VariableGEPIndex { + const Value *V; + ExtensionKind Extension; + int64_t Scale; + }; +} + + +/// GetLinearExpression - Analyze the specified value as a linear expression: +/// "A*V + B", where A and B are constant integers. Return the scale and offset +/// values as APInts and return V as a Value*, and return whether we looked +/// through any sign or zero extends. The incoming Value is known to have +/// IntegerType and it may already be sign or zero extended. +/// +/// Note that this looks through extends, so the high bits may not be +/// represented in the result. +static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset, + ExtensionKind &Extension, + const TargetData &TD, unsigned Depth) { + assert(V->getType()->isIntegerTy() && "Not an integer value"); + + // Limit our recursion depth. + if (Depth == 6) { + Scale = 1; + Offset = 0; + return V; + } + + if (BinaryOperator *BOp = dyn_cast(V)) { + if (ConstantInt *RHSC = dyn_cast(BOp->getOperand(1))) { + switch (BOp->getOpcode()) { + default: break; + case Instruction::Or: + // X|C == X+C if all the bits in C are unset in X. Otherwise we can't + // analyze it. + if (!MaskedValueIsZero(BOp->getOperand(0), RHSC->getValue(), &TD)) + break; + // FALL THROUGH. + case Instruction::Add: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension, + TD, Depth+1); + Offset += RHSC->getValue(); + return V; + case Instruction::Mul: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension, + TD, Depth+1); + Offset *= RHSC->getValue(); + Scale *= RHSC->getValue(); + return V; + case Instruction::Shl: + V = GetLinearExpression(BOp->getOperand(0), Scale, Offset, Extension, + TD, Depth+1); + Offset <<= RHSC->getValue().getLimitedValue(); + Scale <<= RHSC->getValue().getLimitedValue(); + return V; + } + } + } + + // Since GEP indices are sign extended anyway, we don't care about the high + // bits of a sign or zero extended value - just scales and offsets. The + // extensions have to be consistent though. + if ((isa(V) && Extension != EK_ZeroExt) || + (isa(V) && Extension != EK_SignExt)) { + Value *CastOp = cast(V)->getOperand(0); + unsigned OldWidth = Scale.getBitWidth(); + unsigned SmallWidth = CastOp->getType()->getPrimitiveSizeInBits(); + Scale = Scale.trunc(SmallWidth); + Offset = Offset.trunc(SmallWidth); + Extension = isa(V) ? EK_SignExt : EK_ZeroExt; + + Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension, + TD, Depth+1); + Scale = Scale.zext(OldWidth); + Offset = Offset.zext(OldWidth); + + return Result; + } + + Scale = 1; + Offset = 0; + return V; +} + +/// DecomposeGEPExpression - If V is a symbolic pointer expression, decompose it +/// into a base pointer with a constant offset and a number of scaled symbolic +/// offsets. +/// +/// The scaled symbolic offsets (represented by pairs of a Value* and a scale in +/// the VarIndices vector) are Value*'s that are known to be scaled by the +/// specified amount, but which may have other unrepresented high bits. As such, +/// the gep cannot necessarily be reconstructed from its decomposed form. +/// +/// When TargetData is around, this function is capable of analyzing everything +/// that GetUnderlyingObject can look through. When not, it just looks +/// through pointer casts. +/// +static const Value * +DecomposeGEPExpression(const Value *V, int64_t &BaseOffs, + SmallVectorImpl &VarIndices, + const TargetData *TD) { + // Limit recursion depth to limit compile time in crazy cases. + unsigned MaxLookup = 6; + + BaseOffs = 0; + do { + // See if this is a bitcast or GEP. + const Operator *Op = dyn_cast(V); + if (Op == 0) { + // The only non-operator case we can handle are GlobalAliases. + if (const GlobalAlias *GA = dyn_cast(V)) { + if (!GA->mayBeOverridden()) { + V = GA->getAliasee(); + continue; + } + } + return V; + } + + if (Op->getOpcode() == Instruction::BitCast) { + V = Op->getOperand(0); + continue; + } + + if (const Instruction *I = dyn_cast(V)) + // TODO: Get a DominatorTree and use it here. + if (const Value *Simplified = + SimplifyInstruction(const_cast(I), TD)) { + V = Simplified; + continue; + } + + const GEPOperator *GEPOp = dyn_cast(Op); + if (GEPOp == 0) + return V; + + // Don't attempt to analyze GEPs over unsized objects. + if (!cast(GEPOp->getOperand(0)->getType()) + ->getElementType()->isSized()) + return V; + + // If we are lacking TargetData information, we can't compute the offets of + // elements computed by GEPs. However, we can handle bitcast equivalent + // GEPs. + if (TD == 0) { + if (!GEPOp->hasAllZeroIndices()) + return V; + V = GEPOp->getOperand(0); + continue; + } + + // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices. + gep_type_iterator GTI = gep_type_begin(GEPOp); + for (User::const_op_iterator I = GEPOp->op_begin()+1, + E = GEPOp->op_end(); I != E; ++I) { + Value *Index = *I; + // Compute the (potentially symbolic) offset in bytes for this index. + if (const StructType *STy = dyn_cast(*GTI++)) { + // For a struct, add the member offset. + unsigned FieldNo = cast(Index)->getZExtValue(); + if (FieldNo == 0) continue; + + BaseOffs += TD->getStructLayout(STy)->getElementOffset(FieldNo); + continue; + } + + // For an array/pointer, add the element offset, explicitly scaled. + if (ConstantInt *CIdx = dyn_cast(Index)) { + if (CIdx->isZero()) continue; + BaseOffs += TD->getTypeAllocSize(*GTI)*CIdx->getSExtValue(); + continue; + } + + uint64_t Scale = TD->getTypeAllocSize(*GTI); + ExtensionKind Extension = EK_NotExtended; + + // If the integer type is smaller than the pointer size, it is implicitly + // sign extended to pointer size. + unsigned Width = cast(Index->getType())->getBitWidth(); + if (TD->getPointerSizeInBits() > Width) + Extension = EK_SignExt; + + // Use GetLinearExpression to decompose the index into a C1*V+C2 form. + APInt IndexScale(Width, 0), IndexOffset(Width, 0); + Index = GetLinearExpression(Index, IndexScale, IndexOffset, Extension, + *TD, 0); + + // The GEP index scale ("Scale") scales C1*V+C2, yielding (C1*V+C2)*Scale. + // This gives us an aggregate computation of (C1*Scale)*V + C2*Scale. + BaseOffs += IndexOffset.getSExtValue()*Scale; + Scale *= IndexScale.getSExtValue(); + + + // If we already had an occurrance of this index variable, merge this + // scale into it. For example, we want to handle: + // A[x][x] -> x*16 + x*4 -> x*20 + // This also ensures that 'x' only appears in the index list once. + for (unsigned i = 0, e = VarIndices.size(); i != e; ++i) { + if (VarIndices[i].V == Index && + VarIndices[i].Extension == Extension) { + Scale += VarIndices[i].Scale; + VarIndices.erase(VarIndices.begin()+i); + break; + } + } + + // Make sure that we have a scale that makes sense for this target's + // pointer size. + if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) { + Scale <<= ShiftBits; + Scale = (int64_t)Scale >> ShiftBits; + } + + if (Scale) { + VariableGEPIndex Entry = {Index, Extension, Scale}; + VarIndices.push_back(Entry); + } + } + + // Analyze the base pointer next. + V = GEPOp->getOperand(0); + } while (--MaxLookup); + + // If the chain of expressions is too deep, just return early. + return V; +} + +/// GetIndexDifference - Dest and Src are the variable indices from two +/// decomposed GetElementPtr instructions GEP1 and GEP2 which have common base +/// pointers. Subtract the GEP2 indices from GEP1 to find the symbolic +/// difference between the two pointers. +static void GetIndexDifference(SmallVectorImpl &Dest, + const SmallVectorImpl &Src) { + if (Src.empty()) return; + + for (unsigned i = 0, e = Src.size(); i != e; ++i) { + const Value *V = Src[i].V; + ExtensionKind Extension = Src[i].Extension; + int64_t Scale = Src[i].Scale; + + // Find V in Dest. This is N^2, but pointer indices almost never have more + // than a few variable indexes. + for (unsigned j = 0, e = Dest.size(); j != e; ++j) { + if (Dest[j].V != V || Dest[j].Extension != Extension) continue; + + // If we found it, subtract off Scale V's from the entry in Dest. If it + // goes to zero, remove the entry. + if (Dest[j].Scale != Scale) + Dest[j].Scale -= Scale; + else + Dest.erase(Dest.begin()+j); + Scale = 0; + break; + } + + // If we didn't consume this entry, add it to the end of the Dest list. + if (Scale) { + VariableGEPIndex Entry = { V, Extension, -Scale }; + Dest.push_back(Entry); + } + } +} + +//===----------------------------------------------------------------------===// +// BasicAliasAnalysis Pass +//===----------------------------------------------------------------------===// + +#ifndef NDEBUG +static const Function *getParent(const Value *V) { + if (const Instruction *inst = dyn_cast(V)) + return inst->getParent()->getParent(); + + if (const Argument *arg = dyn_cast(V)) + return arg->getParent(); + + return NULL; +} + +static bool notDifferentParent(const Value *O1, const Value *O2) { + + const Function *F1 = getParent(O1); + const Function *F2 = getParent(O2); + + return !F1 || !F2 || F1 == F2; +} +#endif + +namespace { + /// BasicAliasAnalysis - This is the primary alias analysis implementation. + struct BasicAliasAnalysis : public ImmutablePass, public AliasAnalysis { + static char ID; // Class identification, replacement for typeinfo + BasicAliasAnalysis() : ImmutablePass(ID) { + initializeBasicAliasAnalysisPass(*PassRegistry::getPassRegistry()); + } + + virtual void initializePass() { + InitializeAliasAnalysis(this); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + + virtual AliasResult alias(const Location &LocA, + const Location &LocB) { + assert(Visited.empty() && "Visited must be cleared after use!"); + assert(notDifferentParent(LocA.Ptr, LocB.Ptr) && + "BasicAliasAnalysis doesn't support interprocedural queries."); + AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.TBAATag, + LocB.Ptr, LocB.Size, LocB.TBAATag); + Visited.clear(); + return Alias; + } + + virtual ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + + virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + // The AliasAnalysis base class has some smarts, lets use them. + return AliasAnalysis::getModRefInfo(CS1, CS2); + } + + /// pointsToConstantMemory - Chase pointers until we find a (constant + /// global) or not. + virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal); + + /// getModRefBehavior - Return the behavior when calling the given + /// call site. + virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); + + /// getModRefBehavior - Return the behavior when calling the given function. + /// For use when the call site is not known. + virtual ModRefBehavior getModRefBehavior(const Function *F); + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const void *ID) { + if (ID == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + private: + // Visited - Track instructions visited by a aliasPHI, aliasSelect(), and aliasGEP(). + SmallPtrSet Visited; + + // aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP + // instruction against another. + AliasResult aliasGEP(const GEPOperator *V1, uint64_t V1Size, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo, + const Value *UnderlyingV1, const Value *UnderlyingV2); + + // aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI + // instruction against another. + AliasResult aliasPHI(const PHINode *PN, uint64_t PNSize, + const MDNode *PNTBAAInfo, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo); + + /// aliasSelect - Disambiguate a Select instruction against another value. + AliasResult aliasSelect(const SelectInst *SI, uint64_t SISize, + const MDNode *SITBAAInfo, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo); + + AliasResult aliasCheck(const Value *V1, uint64_t V1Size, + const MDNode *V1TBAATag, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAATag); + }; +} // End of anonymous namespace + +// Register this pass... +char BasicAliasAnalysis::ID = 0; +INITIALIZE_AG_PASS(BasicAliasAnalysis, AliasAnalysis, "basicaa", + "Basic Alias Analysis (stateless AA impl)", + false, true, false) + +ImmutablePass *llvm::createBasicAliasAnalysisPass() { + return new BasicAliasAnalysis(); +} + +/// pointsToConstantMemory - Returns whether the given pointer value +/// points to memory that is local to the function, with global constants being +/// considered local to all functions. +bool +BasicAliasAnalysis::pointsToConstantMemory(const Location &Loc, bool OrLocal) { + assert(Visited.empty() && "Visited must be cleared after use!"); + + unsigned MaxLookup = 8; + SmallVector Worklist; + Worklist.push_back(Loc.Ptr); + do { + const Value *V = GetUnderlyingObject(Worklist.pop_back_val(), TD); + if (!Visited.insert(V)) { + Visited.clear(); + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + } + + // An alloca instruction defines local memory. + if (OrLocal && isa(V)) + continue; + + // A global constant counts as local memory for our purposes. + if (const GlobalVariable *GV = dyn_cast(V)) { + // Note: this doesn't require GV to be "ODR" because it isn't legal for a + // global to be marked constant in some modules and non-constant in + // others. GV may even be a declaration, not a definition. + if (!GV->isConstant()) { + Visited.clear(); + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + } + continue; + } + + // If both select values point to local memory, then so does the select. + if (const SelectInst *SI = dyn_cast(V)) { + Worklist.push_back(SI->getTrueValue()); + Worklist.push_back(SI->getFalseValue()); + continue; + } + + // If all values incoming to a phi node point to local memory, then so does + // the phi. + if (const PHINode *PN = dyn_cast(V)) { + // Don't bother inspecting phi nodes with many operands. + if (PN->getNumIncomingValues() > MaxLookup) { + Visited.clear(); + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + } + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + Worklist.push_back(PN->getIncomingValue(i)); + continue; + } + + // Otherwise be conservative. + Visited.clear(); + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + + } while (!Worklist.empty() && --MaxLookup); + + Visited.clear(); + return Worklist.empty(); +} + +/// getModRefBehavior - Return the behavior when calling the given call site. +AliasAnalysis::ModRefBehavior +BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { + if (CS.doesNotAccessMemory()) + // Can't do better than this. + return DoesNotAccessMemory; + + ModRefBehavior Min = UnknownModRefBehavior; + + // If the callsite knows it only reads memory, don't return worse + // than that. + if (CS.onlyReadsMemory()) + Min = OnlyReadsMemory; + + // The AliasAnalysis base class has some smarts, lets use them. + return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); +} + +/// getModRefBehavior - Return the behavior when calling the given function. +/// For use when the call site is not known. +AliasAnalysis::ModRefBehavior +BasicAliasAnalysis::getModRefBehavior(const Function *F) { + // If the function declares it doesn't access memory, we can't do better. + if (F->doesNotAccessMemory()) + return DoesNotAccessMemory; + + // For intrinsics, we can check the table. + if (unsigned iid = F->getIntrinsicID()) { +#define GET_INTRINSIC_MODREF_BEHAVIOR +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_MODREF_BEHAVIOR + } + + ModRefBehavior Min = UnknownModRefBehavior; + + // If the function declares it only reads memory, go with that. + if (F->onlyReadsMemory()) + Min = OnlyReadsMemory; + + // Otherwise be conservative. + return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min); +} + +/// getModRefInfo - Check to see if the specified callsite can clobber the +/// specified memory object. Since we only look at local properties of this +/// function, we really can't say much about this query. We do, however, use +/// simple "address taken" analysis on local objects. +AliasAnalysis::ModRefResult +BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + assert(notDifferentParent(CS.getInstruction(), Loc.Ptr) && + "AliasAnalysis query involving multiple functions!"); + + const Value *Object = GetUnderlyingObject(Loc.Ptr, TD); + + // If this is a tail call and Loc.Ptr points to a stack location, we know that + // the tail call cannot access or modify the local stack. + // We cannot exclude byval arguments here; these belong to the caller of + // the current function not to the current function, and a tail callee + // may reference them. + if (isa(Object)) + if (const CallInst *CI = dyn_cast(CS.getInstruction())) + if (CI->isTailCall()) + return NoModRef; + + // If the pointer is to a locally allocated object that does not escape, + // then the call can not mod/ref the pointer unless the call takes the pointer + // as an argument, and itself doesn't capture it. + if (!isa(Object) && CS.getInstruction() != Object && + isNonEscapingLocalObject(Object)) { + bool PassedAsArg = false; + unsigned ArgNo = 0; + for (ImmutableCallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); + CI != CE; ++CI, ++ArgNo) { + // Only look at the no-capture pointer arguments. + if (!(*CI)->getType()->isPointerTy() || + !CS.paramHasAttr(ArgNo+1, Attribute::NoCapture)) + continue; + + // If this is a no-capture pointer argument, see if we can tell that it + // is impossible to alias the pointer we're checking. If not, we have to + // assume that the call could touch the pointer, even though it doesn't + // escape. + if (!isNoAlias(Location(cast(CI)), Loc)) { + PassedAsArg = true; + break; + } + } + + if (!PassedAsArg) + return NoModRef; + } + + ModRefResult Min = ModRef; + + // Finally, handle specific knowledge of intrinsics. + const IntrinsicInst *II = dyn_cast(CS.getInstruction()); + if (II != 0) + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::memcpy: + case Intrinsic::memmove: { + uint64_t Len = UnknownSize; + if (ConstantInt *LenCI = dyn_cast(II->getArgOperand(2))) + Len = LenCI->getZExtValue(); + Value *Dest = II->getArgOperand(0); + Value *Src = II->getArgOperand(1); + // If it can't overlap the source dest, then it doesn't modref the loc. + if (isNoAlias(Location(Dest, Len), Loc)) { + if (isNoAlias(Location(Src, Len), Loc)) + return NoModRef; + // If it can't overlap the dest, then worst case it reads the loc. + Min = Ref; + } else if (isNoAlias(Location(Src, Len), Loc)) { + // If it can't overlap the source, then worst case it mutates the loc. + Min = Mod; + } + break; + } + case Intrinsic::memset: + // Since memset is 'accesses arguments' only, the AliasAnalysis base class + // will handle it for the variable length case. + if (ConstantInt *LenCI = dyn_cast(II->getArgOperand(2))) { + uint64_t Len = LenCI->getZExtValue(); + Value *Dest = II->getArgOperand(0); + if (isNoAlias(Location(Dest, Len), Loc)) + return NoModRef; + } + // We know that memset doesn't load anything. + Min = Mod; + break; + case Intrinsic::atomic_cmp_swap: + case Intrinsic::atomic_swap: + case Intrinsic::atomic_load_add: + case Intrinsic::atomic_load_sub: + case Intrinsic::atomic_load_and: + case Intrinsic::atomic_load_nand: + case Intrinsic::atomic_load_or: + case Intrinsic::atomic_load_xor: + case Intrinsic::atomic_load_max: + case Intrinsic::atomic_load_min: + case Intrinsic::atomic_load_umax: + case Intrinsic::atomic_load_umin: + if (TD) { + Value *Op1 = II->getArgOperand(0); + uint64_t Op1Size = TD->getTypeStoreSize(Op1->getType()); + MDNode *Tag = II->getMetadata(LLVMContext::MD_tbaa); + if (isNoAlias(Location(Op1, Op1Size, Tag), Loc)) + return NoModRef; + } + break; + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: { + uint64_t PtrSize = + cast(II->getArgOperand(0))->getZExtValue(); + if (isNoAlias(Location(II->getArgOperand(1), + PtrSize, + II->getMetadata(LLVMContext::MD_tbaa)), + Loc)) + return NoModRef; + break; + } + case Intrinsic::invariant_end: { + uint64_t PtrSize = + cast(II->getArgOperand(1))->getZExtValue(); + if (isNoAlias(Location(II->getArgOperand(2), + PtrSize, + II->getMetadata(LLVMContext::MD_tbaa)), + Loc)) + return NoModRef; + break; + } + } + + // The AliasAnalysis base class has some smarts, lets use them. + return ModRefResult(AliasAnalysis::getModRefInfo(CS, Loc) & Min); +} + +/// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction +/// against another pointer. We know that V1 is a GEP, but we don't know +/// anything about V2. UnderlyingV1 is GetUnderlyingObject(GEP1, TD), +/// UnderlyingV2 is the same for V2. +/// +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo, + const Value *UnderlyingV1, + const Value *UnderlyingV2) { + // If this GEP has been visited before, we're on a use-def cycle. + // Such cycles are only valid when PHI nodes are involved or in unreachable + // code. The visitPHI function catches cycles containing PHIs, but there + // could still be a cycle without PHIs in unreachable code. + if (!Visited.insert(GEP1)) + return MayAlias; + + int64_t GEP1BaseOffset; + SmallVector GEP1VariableIndices; + + // If we have two gep instructions with must-alias'ing base pointers, figure + // out if the indexes to the GEP tell us anything about the derived pointer. + if (const GEPOperator *GEP2 = dyn_cast(V2)) { + // Do the base pointers alias? + AliasResult BaseAlias = aliasCheck(UnderlyingV1, UnknownSize, 0, + UnderlyingV2, UnknownSize, 0); + + // If we get a No or May, then return it immediately, no amount of analysis + // will improve this situation. + if (BaseAlias != MustAlias) return BaseAlias; + + // Otherwise, we have a MustAlias. Since the base pointers alias each other + // exactly, see if the computed offset from the common pointer tells us + // about the relation of the resulting pointer. + const Value *GEP1BasePtr = + DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices, TD); + + int64_t GEP2BaseOffset; + SmallVector GEP2VariableIndices; + const Value *GEP2BasePtr = + DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices, TD); + + // If DecomposeGEPExpression isn't able to look all the way through the + // addressing operation, we must not have TD and this is too complex for us + // to handle without it. + if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) { + assert(TD == 0 && + "DecomposeGEPExpression and GetUnderlyingObject disagree!"); + return MayAlias; + } + + // Subtract the GEP2 pointer from the GEP1 pointer to find out their + // symbolic difference. + GEP1BaseOffset -= GEP2BaseOffset; + GetIndexDifference(GEP1VariableIndices, GEP2VariableIndices); + + } else { + // Check to see if these two pointers are related by the getelementptr + // instruction. If one pointer is a GEP with a non-zero index of the other + // pointer, we know they cannot alias. + + // If both accesses are unknown size, we can't do anything useful here. + if (V1Size == UnknownSize && V2Size == UnknownSize) + return MayAlias; + + AliasResult R = aliasCheck(UnderlyingV1, UnknownSize, 0, + V2, V2Size, V2TBAAInfo); + if (R != MustAlias) + // If V2 may alias GEP base pointer, conservatively returns MayAlias. + // If V2 is known not to alias GEP base pointer, then the two values + // cannot alias per GEP semantics: "A pointer value formed from a + // getelementptr instruction is associated with the addresses associated + // with the first operand of the getelementptr". + return R; + + const Value *GEP1BasePtr = + DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices, TD); + + // If DecomposeGEPExpression isn't able to look all the way through the + // addressing operation, we must not have TD and this is too complex for us + // to handle without it. + if (GEP1BasePtr != UnderlyingV1) { + assert(TD == 0 && + "DecomposeGEPExpression and GetUnderlyingObject disagree!"); + return MayAlias; + } + } + + // In the two GEP Case, if there is no difference in the offsets of the + // computed pointers, the resultant pointers are a must alias. This + // hapens when we have two lexically identical GEP's (for example). + // + // In the other case, if we have getelementptr , 0, 0, 0, 0, ... and V2 + // must aliases the GEP, the end result is a must alias also. + if (GEP1BaseOffset == 0 && GEP1VariableIndices.empty()) + return MustAlias; + + // If there is a difference betwen the pointers, but the difference is + // less than the size of the associated memory object, then we know + // that the objects are partially overlapping. + if (GEP1BaseOffset != 0 && GEP1VariableIndices.empty()) { + if (GEP1BaseOffset >= 0 ? + (V2Size != UnknownSize && (uint64_t)GEP1BaseOffset < V2Size) : + (V1Size != UnknownSize && -(uint64_t)GEP1BaseOffset < V1Size && + GEP1BaseOffset != INT64_MIN)) + return PartialAlias; + } + + // If we have a known constant offset, see if this offset is larger than the + // access size being queried. If so, and if no variable indices can remove + // pieces of this constant, then we know we have a no-alias. For example, + // &A[100] != &A. + + // In order to handle cases like &A[100][i] where i is an out of range + // subscript, we have to ignore all constant offset pieces that are a multiple + // of a scaled index. Do this by removing constant offsets that are a + // multiple of any of our variable indices. This allows us to transform + // things like &A[i][1] because i has a stride of (e.g.) 8 bytes but the 1 + // provides an offset of 4 bytes (assuming a <= 4 byte access). + for (unsigned i = 0, e = GEP1VariableIndices.size(); + i != e && GEP1BaseOffset;++i) + if (int64_t RemovedOffset = GEP1BaseOffset/GEP1VariableIndices[i].Scale) + GEP1BaseOffset -= RemovedOffset*GEP1VariableIndices[i].Scale; + + // If our known offset is bigger than the access size, we know we don't have + // an alias. + if (GEP1BaseOffset) { + if (GEP1BaseOffset >= 0 ? + (V2Size != UnknownSize && (uint64_t)GEP1BaseOffset >= V2Size) : + (V1Size != UnknownSize && -(uint64_t)GEP1BaseOffset >= V1Size && + GEP1BaseOffset != INT64_MIN)) + return NoAlias; + } + + return MayAlias; +} + +/// aliasSelect - Provide a bunch of ad-hoc rules to disambiguate a Select +/// instruction against another. +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasSelect(const SelectInst *SI, uint64_t SISize, + const MDNode *SITBAAInfo, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo) { + // If this select has been visited before, we're on a use-def cycle. + // Such cycles are only valid when PHI nodes are involved or in unreachable + // code. The visitPHI function catches cycles containing PHIs, but there + // could still be a cycle without PHIs in unreachable code. + if (!Visited.insert(SI)) + return MayAlias; + + // If the values are Selects with the same condition, we can do a more precise + // check: just check for aliases between the values on corresponding arms. + if (const SelectInst *SI2 = dyn_cast(V2)) + if (SI->getCondition() == SI2->getCondition()) { + AliasResult Alias = + aliasCheck(SI->getTrueValue(), SISize, SITBAAInfo, + SI2->getTrueValue(), V2Size, V2TBAAInfo); + if (Alias == MayAlias) + return MayAlias; + AliasResult ThisAlias = + aliasCheck(SI->getFalseValue(), SISize, SITBAAInfo, + SI2->getFalseValue(), V2Size, V2TBAAInfo); + if (ThisAlias != Alias) + return MayAlias; + return Alias; + } + + // If both arms of the Select node NoAlias or MustAlias V2, then returns + // NoAlias / MustAlias. Otherwise, returns MayAlias. + AliasResult Alias = + aliasCheck(V2, V2Size, V2TBAAInfo, SI->getTrueValue(), SISize, SITBAAInfo); + if (Alias == MayAlias) + return MayAlias; + + // If V2 is visited, the recursive case will have been caught in the + // above aliasCheck call, so these subsequent calls to aliasCheck + // don't need to assume that V2 is being visited recursively. + Visited.erase(V2); + + AliasResult ThisAlias = + aliasCheck(V2, V2Size, V2TBAAInfo, SI->getFalseValue(), SISize, SITBAAInfo); + if (ThisAlias != Alias) + return MayAlias; + return Alias; +} + +// aliasPHI - Provide a bunch of ad-hoc rules to disambiguate a PHI instruction +// against another. +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize, + const MDNode *PNTBAAInfo, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo) { + // The PHI node has already been visited, avoid recursion any further. + if (!Visited.insert(PN)) + return MayAlias; + + // If the values are PHIs in the same block, we can do a more precise + // as well as efficient check: just check for aliases between the values + // on corresponding edges. + if (const PHINode *PN2 = dyn_cast(V2)) + if (PN2->getParent() == PN->getParent()) { + AliasResult Alias = + aliasCheck(PN->getIncomingValue(0), PNSize, PNTBAAInfo, + PN2->getIncomingValueForBlock(PN->getIncomingBlock(0)), + V2Size, V2TBAAInfo); + if (Alias == MayAlias) + return MayAlias; + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) { + AliasResult ThisAlias = + aliasCheck(PN->getIncomingValue(i), PNSize, PNTBAAInfo, + PN2->getIncomingValueForBlock(PN->getIncomingBlock(i)), + V2Size, V2TBAAInfo); + if (ThisAlias != Alias) + return MayAlias; + } + return Alias; + } + + SmallPtrSet UniqueSrc; + SmallVector V1Srcs; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *PV1 = PN->getIncomingValue(i); + if (isa(PV1)) + // If any of the source itself is a PHI, return MayAlias conservatively + // to avoid compile time explosion. The worst possible case is if both + // sides are PHI nodes. In which case, this is O(m x n) time where 'm' + // and 'n' are the number of PHI sources. + return MayAlias; + if (UniqueSrc.insert(PV1)) + V1Srcs.push_back(PV1); + } + + AliasResult Alias = aliasCheck(V2, V2Size, V2TBAAInfo, + V1Srcs[0], PNSize, PNTBAAInfo); + // Early exit if the check of the first PHI source against V2 is MayAlias. + // Other results are not possible. + if (Alias == MayAlias) + return MayAlias; + + // If all sources of the PHI node NoAlias or MustAlias V2, then returns + // NoAlias / MustAlias. Otherwise, returns MayAlias. + for (unsigned i = 1, e = V1Srcs.size(); i != e; ++i) { + Value *V = V1Srcs[i]; + + // If V2 is visited, the recursive case will have been caught in the + // above aliasCheck call, so these subsequent calls to aliasCheck + // don't need to assume that V2 is being visited recursively. + Visited.erase(V2); + + AliasResult ThisAlias = aliasCheck(V2, V2Size, V2TBAAInfo, + V, PNSize, PNTBAAInfo); + if (ThisAlias != Alias || ThisAlias == MayAlias) + return MayAlias; + } + + return Alias; +} + +// aliasCheck - Provide a bunch of ad-hoc rules to disambiguate in common cases, +// such as array references. +// +AliasAnalysis::AliasResult +BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size, + const MDNode *V1TBAAInfo, + const Value *V2, uint64_t V2Size, + const MDNode *V2TBAAInfo) { + // If either of the memory references is empty, it doesn't matter what the + // pointer values are. + if (V1Size == 0 || V2Size == 0) + return NoAlias; + + // Strip off any casts if they exist. + V1 = V1->stripPointerCasts(); + V2 = V2->stripPointerCasts(); + + // Are we checking for alias of the same value? + if (V1 == V2) return MustAlias; + + if (!V1->getType()->isPointerTy() || !V2->getType()->isPointerTy()) + return NoAlias; // Scalars cannot alias each other + + // Figure out what objects these things are pointing to if we can. + const Value *O1 = GetUnderlyingObject(V1, TD); + const Value *O2 = GetUnderlyingObject(V2, TD); + + // Null values in the default address space don't point to any object, so they + // don't alias any other pointer. + if (const ConstantPointerNull *CPN = dyn_cast(O1)) + if (CPN->getType()->getAddressSpace() == 0) + return NoAlias; + if (const ConstantPointerNull *CPN = dyn_cast(O2)) + if (CPN->getType()->getAddressSpace() == 0) + return NoAlias; + + if (O1 != O2) { + // If V1/V2 point to two different objects we know that we have no alias. + if (isIdentifiedObject(O1) && isIdentifiedObject(O2)) + return NoAlias; + + // Constant pointers can't alias with non-const isIdentifiedObject objects. + if ((isa(O1) && isIdentifiedObject(O2) && !isa(O2)) || + (isa(O2) && isIdentifiedObject(O1) && !isa(O1))) + return NoAlias; + + // Arguments can't alias with local allocations or noalias calls + // in the same function. + if (((isa(O1) && (isa(O2) || isNoAliasCall(O2))) || + (isa(O2) && (isa(O1) || isNoAliasCall(O1))))) + return NoAlias; + + // Most objects can't alias null. + if ((isa(O2) && isKnownNonNull(O1)) || + (isa(O1) && isKnownNonNull(O2))) + return NoAlias; + + // If one pointer is the result of a call/invoke or load and the other is a + // non-escaping local object within the same function, then we know the + // object couldn't escape to a point where the call could return it. + // + // Note that if the pointers are in different functions, there are a + // variety of complications. A call with a nocapture argument may still + // temporary store the nocapture argument's value in a temporary memory + // location if that memory location doesn't escape. Or it may pass a + // nocapture value to other functions as long as they don't capture it. + if (isEscapeSource(O1) && isNonEscapingLocalObject(O2)) + return NoAlias; + if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) + return NoAlias; + } + + // If the size of one access is larger than the entire object on the other + // side, then we know such behavior is undefined and can assume no alias. + if (TD) + if ((V1Size != UnknownSize && isObjectSmallerThan(O2, V1Size, *TD)) || + (V2Size != UnknownSize && isObjectSmallerThan(O1, V2Size, *TD))) + return NoAlias; + + // FIXME: This isn't aggressively handling alias(GEP, PHI) for example: if the + // GEP can't simplify, we don't even look at the PHI cases. + if (!isa(V1) && isa(V2)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + std::swap(O1, O2); + } + if (const GEPOperator *GV1 = dyn_cast(V1)) { + AliasResult Result = aliasGEP(GV1, V1Size, V2, V2Size, V2TBAAInfo, O1, O2); + if (Result != MayAlias) return Result; + } + + if (isa(V2) && !isa(V1)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + } + if (const PHINode *PN = dyn_cast(V1)) { + AliasResult Result = aliasPHI(PN, V1Size, V1TBAAInfo, + V2, V2Size, V2TBAAInfo); + if (Result != MayAlias) return Result; + } + + if (isa(V2) && !isa(V1)) { + std::swap(V1, V2); + std::swap(V1Size, V2Size); + } + if (const SelectInst *S1 = dyn_cast(V1)) { + AliasResult Result = aliasSelect(S1, V1Size, V1TBAAInfo, + V2, V2Size, V2TBAAInfo); + if (Result != MayAlias) return Result; + } + + // If both pointers are pointing into the same object and one of them + // accesses is accessing the entire object, then the accesses must + // overlap in some way. + if (TD && O1 == O2) + if ((V1Size != UnknownSize && isObjectSize(O1, V1Size, *TD)) || + (V2Size != UnknownSize && isObjectSize(O2, V2Size, *TD))) + return PartialAlias; + + return AliasAnalysis::alias(Location(V1, V1Size, V1TBAAInfo), + Location(V2, V2Size, V2TBAAInfo)); +} diff --git a/final/lib/Analysis/CFGPrinter.cpp b/final/lib/Analysis/CFGPrinter.cpp new file mode 100644 index 00000000000..7bb063fbbbc --- /dev/null +++ b/final/lib/Analysis/CFGPrinter.cpp @@ -0,0 +1,165 @@ +//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===// +// +// 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 '-dot-cfg' analysis pass, which emits the +// cfg..dot file for each function in the program, with a graph of the +// CFG for that function. +// +// The other main feature of this file is that it implements the +// Function::viewCFG method, which is useful for debugging passes which operate +// on the CFG. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CFGPrinter.h" + +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + struct CFGViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGViewer() : FunctionPass(ID) { + initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F) { + F.viewCFG(); + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGViewer::ID = 0; +INITIALIZE_PASS(CFGViewer, "view-cfg", "View CFG of function", false, true) + +namespace { + struct CFGOnlyViewer : public FunctionPass { + static char ID; // Pass identifcation, replacement for typeid + CFGOnlyViewer() : FunctionPass(ID) { + initializeCFGOnlyViewerPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F) { + F.viewCFGOnly(); + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGOnlyViewer::ID = 0; +INITIALIZE_PASS(CFGOnlyViewer, "view-cfg-only", + "View CFG of function (with no function bodies)", false, true) + +namespace { + struct CFGPrinter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGPrinter() : FunctionPass(ID) { + initializeCFGPrinterPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F) { + std::string Filename = "cfg." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) + WriteGraph(File, (const Function*)&F); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGPrinter::ID = 0; +INITIALIZE_PASS(CFGPrinter, "dot-cfg", "Print CFG of function to 'dot' file", + false, true) + +namespace { + struct CFGOnlyPrinter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CFGOnlyPrinter() : FunctionPass(ID) { + initializeCFGOnlyPrinterPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F) { + std::string Filename = "cfg." + F.getNameStr() + ".dot"; + errs() << "Writing '" << Filename << "'..."; + + std::string ErrorInfo; + raw_fd_ostream File(Filename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) + WriteGraph(File, (const Function*)&F, true); + else + errs() << " error opening file for writing!"; + errs() << "\n"; + return false; + } + void print(raw_ostream &OS, const Module* = 0) const {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; +} + +char CFGOnlyPrinter::ID = 0; +INITIALIZE_PASS(CFGOnlyPrinter, "dot-cfg-only", + "Print CFG of function to 'dot' file (with no function bodies)", + false, true) + +/// viewCFG - This function is meant for use from the debugger. You can just +/// say 'call F->viewCFG()' and a ghostview window should pop up from the +/// program, displaying the CFG of the current function. This depends on there +/// being a 'dot' and 'gv' program in your path. +/// +void Function::viewCFG() const { + ViewGraph(this, "cfg" + getNameStr()); +} + +/// viewCFGOnly - This function is meant for use from the debugger. It works +/// just like viewCFG, but it does not include the contents of basic blocks +/// into the nodes, just the label. If you are only interested in the CFG t +/// his can make the graph smaller. +/// +void Function::viewCFGOnly() const { + ViewGraph(this, "cfg" + getNameStr(), true); +} + +FunctionPass *llvm::createCFGPrinterPass () { + return new CFGPrinter(); +} + +FunctionPass *llvm::createCFGOnlyPrinterPass () { + return new CFGOnlyPrinter(); +} + diff --git a/final/lib/Analysis/CMakeLists.txt b/final/lib/Analysis/CMakeLists.txt new file mode 100644 index 00000000000..6be561718c7 --- /dev/null +++ b/final/lib/Analysis/CMakeLists.txt @@ -0,0 +1,59 @@ +add_llvm_library(LLVMAnalysis + AliasAnalysis.cpp + AliasAnalysisCounter.cpp + AliasAnalysisEvaluator.cpp + AliasDebugger.cpp + AliasSetTracker.cpp + Analysis.cpp + BasicAliasAnalysis.cpp + CFGPrinter.cpp + CaptureTracking.cpp + ConstantFolding.cpp + DIBuilder.cpp + DbgInfoPrinter.cpp + DebugInfo.cpp + DomPrinter.cpp + DominanceFrontier.cpp + IVUsers.cpp + InlineCost.cpp + InstCount.cpp + InstructionSimplify.cpp + Interval.cpp + IntervalPartition.cpp + LazyValueInfo.cpp + LibCallAliasAnalysis.cpp + LibCallSemantics.cpp + Lint.cpp + Loads.cpp + LoopDependenceAnalysis.cpp + LoopInfo.cpp + LoopPass.cpp + MemDepPrinter.cpp + MemoryBuiltins.cpp + MemoryDependenceAnalysis.cpp + ModuleDebugInfoPrinter.cpp + NoAliasAnalysis.cpp + PHITransAddr.cpp + PathNumbering.cpp + PathProfileInfo.cpp + PathProfileVerifier.cpp + PostDominators.cpp + ProfileEstimatorPass.cpp + ProfileInfo.cpp + ProfileInfoLoader.cpp + ProfileInfoLoaderPass.cpp + ProfileVerifierPass.cpp + RegionInfo.cpp + RegionPass.cpp + RegionPrinter.cpp + ScalarEvolution.cpp + ScalarEvolutionAliasAnalysis.cpp + ScalarEvolutionExpander.cpp + ScalarEvolutionNormalization.cpp + SparsePropagation.cpp + Trace.cpp + TypeBasedAliasAnalysis.cpp + ValueTracking.cpp + ) + +add_subdirectory(IPA) diff --git a/final/lib/Analysis/CaptureTracking.cpp b/final/lib/Analysis/CaptureTracking.cpp new file mode 100644 index 00000000000..42a54d9d1eb --- /dev/null +++ b/final/lib/Analysis/CaptureTracking.cpp @@ -0,0 +1,147 @@ +//===--- CaptureTracking.cpp - Determine whether a pointer is captured ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help determine which pointers are captured. +// A pointer value is captured if the function makes a copy of any part of the +// pointer that outlives the call. Not being captured means, more or less, that +// the pointer is only dereferenced and not stored in a global. Returning part +// of the pointer as the function return value may or may not count as capturing +// the pointer, depending on the context. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Instructions.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CallSite.h" +using namespace llvm; + +/// As its comment mentions, PointerMayBeCaptured can be expensive. +/// However, it's not easy for BasicAA to cache the result, because +/// it's an ImmutablePass. To work around this, bound queries at a +/// fixed number of uses. +/// +/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep +/// a cache. Then we can move the code from BasicAliasAnalysis into +/// that path, and remove this threshold. +static int const Threshold = 20; + +/// PointerMayBeCaptured - Return true if this pointer value may be captured +/// by the enclosing function (which is required to exist). This routine can +/// be expensive, so consider caching the results. The boolean ReturnCaptures +/// specifies whether returning the value (or part of it) from the function +/// counts as capturing it or not. The boolean StoreCaptures specified whether +/// storing the value (or part of it) into memory anywhere automatically +/// counts as capturing it or not. +bool llvm::PointerMayBeCaptured(const Value *V, + bool ReturnCaptures, bool StoreCaptures) { + assert(V->getType()->isPointerTy() && "Capture is for pointers only!"); + SmallVector Worklist; + SmallSet Visited; + int Count = 0; + + for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end(); + UI != UE; ++UI) { + // If there are lots of uses, conservatively say that the value + // is captured to avoid taking too much compile time. + if (Count++ >= Threshold) + return true; + + Use *U = &UI.getUse(); + Visited.insert(U); + Worklist.push_back(U); + } + + while (!Worklist.empty()) { + Use *U = Worklist.pop_back_val(); + Instruction *I = cast(U->getUser()); + V = U->get(); + + switch (I->getOpcode()) { + case Instruction::Call: + case Instruction::Invoke: { + CallSite CS(I); + // Not captured if the callee is readonly, doesn't return a copy through + // its return value and doesn't unwind (a readonly function can leak bits + // by throwing an exception or not depending on the input value). + if (CS.onlyReadsMemory() && CS.doesNotThrow() && I->getType()->isVoidTy()) + break; + + // Not captured if only passed via 'nocapture' arguments. Note that + // calling a function pointer does not in itself cause the pointer to + // be captured. This is a subtle point considering that (for example) + // the callee might return its own address. It is analogous to saying + // that loading a value from a pointer does not cause the pointer to be + // captured, even though the loaded value might be the pointer itself + // (think of self-referential objects). + CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); + for (CallSite::arg_iterator A = B; A != E; ++A) + if (A->get() == V && !CS.paramHasAttr(A - B + 1, Attribute::NoCapture)) + // The parameter is not marked 'nocapture' - captured. + return true; + // Only passed via 'nocapture' arguments, or is the called function - not + // captured. + break; + } + case Instruction::Load: + // Loading from a pointer does not cause it to be captured. + break; + case Instruction::VAArg: + // "va-arg" from a pointer does not cause it to be captured. + break; + case Instruction::Ret: + if (ReturnCaptures) + return true; + break; + case Instruction::Store: + if (V == I->getOperand(0)) + // Stored the pointer - conservatively assume it may be captured. + // TODO: If StoreCaptures is not true, we could do Fancy analysis + // to determine whether this store is not actually an escape point. + // In that case, BasicAliasAnalysis should be updated as well to + // take advantage of this. + return true; + // Storing to the pointee does not cause the pointer to be captured. + break; + case Instruction::BitCast: + case Instruction::GetElementPtr: + case Instruction::PHI: + case Instruction::Select: + // The original value is not captured via this if the new value isn't. + for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) { + Use *U = &UI.getUse(); + if (Visited.insert(U)) + Worklist.push_back(U); + } + break; + case Instruction::ICmp: + // Don't count comparisons of a no-alias return value against null as + // captures. This allows us to ignore comparisons of malloc results + // with null, for example. + if (isNoAliasCall(V->stripPointerCasts())) + if (ConstantPointerNull *CPN = + dyn_cast(I->getOperand(1))) + if (CPN->getType()->getAddressSpace() == 0) + break; + // Otherwise, be conservative. There are crazy ways to capture pointers + // using comparisons. + return true; + default: + // Something else - be conservative and say it is captured. + return true; + } + } + + // All uses examined - not captured. + return false; +} diff --git a/final/lib/Analysis/ConstantFolding.cpp b/final/lib/Analysis/ConstantFolding.cpp new file mode 100644 index 00000000000..cd8d52c1c46 --- /dev/null +++ b/final/lib/Analysis/ConstantFolding.cpp @@ -0,0 +1,1400 @@ +//===-- ConstantFolding.cpp - Fold instructions into constants ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines routines for folding instructions into constants. +// +// Also, to supplement the basic VMCore ConstantExpr simplifications, +// this file defines some additional folding routines that can make use of +// TargetData information. These functions cannot go in VMCore due to library +// dependency issues. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/FEnv.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Constant Folding internal helper functions +//===----------------------------------------------------------------------===// + +/// FoldBitCast - Constant fold bitcast, symbolically evaluating it with +/// TargetData. This always returns a non-null constant, but it may be a +/// ConstantExpr if unfoldable. +static Constant *FoldBitCast(Constant *C, const Type *DestTy, + const TargetData &TD) { + + // This only handles casts to vectors currently. + const VectorType *DestVTy = dyn_cast(DestTy); + if (DestVTy == 0) + return ConstantExpr::getBitCast(C, DestTy); + + // If this is a scalar -> vector cast, convert the input into a <1 x scalar> + // vector so the code below can handle it uniformly. + if (isa(C) || isa(C)) { + Constant *Ops = C; // don't take the address of C! + return FoldBitCast(ConstantVector::get(Ops), DestTy, TD); + } + + // If this is a bitcast from constant vector -> vector, fold it. + ConstantVector *CV = dyn_cast(C); + if (CV == 0) + return ConstantExpr::getBitCast(C, DestTy); + + // If the element types match, VMCore can fold it. + unsigned NumDstElt = DestVTy->getNumElements(); + unsigned NumSrcElt = CV->getNumOperands(); + if (NumDstElt == NumSrcElt) + return ConstantExpr::getBitCast(C, DestTy); + + const Type *SrcEltTy = CV->getType()->getElementType(); + const Type *DstEltTy = DestVTy->getElementType(); + + // Otherwise, we're changing the number of elements in a vector, which + // requires endianness information to do the right thing. For example, + // bitcast (<2 x i64> to <4 x i32>) + // folds to (little endian): + // <4 x i32> + // and to (big endian): + // <4 x i32> + + // First thing is first. We only want to think about integer here, so if + // we have something in FP form, recast it as integer. + if (DstEltTy->isFloatingPointTy()) { + // Fold to an vector of integers with same size as our FP type. + unsigned FPWidth = DstEltTy->getPrimitiveSizeInBits(); + const Type *DestIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumDstElt); + // Recursively handle this integer conversion, if possible. + C = FoldBitCast(C, DestIVTy, TD); + if (!C) return ConstantExpr::getBitCast(C, DestTy); + + // Finally, VMCore can handle this now that #elts line up. + return ConstantExpr::getBitCast(C, DestTy); + } + + // Okay, we know the destination is integer, if the input is FP, convert + // it to integer first. + if (SrcEltTy->isFloatingPointTy()) { + unsigned FPWidth = SrcEltTy->getPrimitiveSizeInBits(); + const Type *SrcIVTy = + VectorType::get(IntegerType::get(C->getContext(), FPWidth), NumSrcElt); + // Ask VMCore to do the conversion now that #elts line up. + C = ConstantExpr::getBitCast(C, SrcIVTy); + CV = dyn_cast(C); + if (!CV) // If VMCore wasn't able to fold it, bail out. + return C; + } + + // Now we know that the input and output vectors are both integer vectors + // of the same size, and that their #elements is not the same. Do the + // conversion here, which depends on whether the input or output has + // more elements. + bool isLittleEndian = TD.isLittleEndian(); + + SmallVector Result; + if (NumDstElt < NumSrcElt) { + // Handle: bitcast (<4 x i32> to <2 x i64>) + Constant *Zero = Constant::getNullValue(DstEltTy); + unsigned Ratio = NumSrcElt/NumDstElt; + unsigned SrcBitSize = SrcEltTy->getPrimitiveSizeInBits(); + unsigned SrcElt = 0; + for (unsigned i = 0; i != NumDstElt; ++i) { + // Build each element of the result. + Constant *Elt = Zero; + unsigned ShiftAmt = isLittleEndian ? 0 : SrcBitSize*(Ratio-1); + for (unsigned j = 0; j != Ratio; ++j) { + Constant *Src = dyn_cast(CV->getOperand(SrcElt++)); + if (!Src) // Reject constantexpr elements. + return ConstantExpr::getBitCast(C, DestTy); + + // Zero extend the element to the right size. + Src = ConstantExpr::getZExt(Src, Elt->getType()); + + // Shift it to the right place, depending on endianness. + Src = ConstantExpr::getShl(Src, + ConstantInt::get(Src->getType(), ShiftAmt)); + ShiftAmt += isLittleEndian ? SrcBitSize : -SrcBitSize; + + // Mix it in. + Elt = ConstantExpr::getOr(Elt, Src); + } + Result.push_back(Elt); + } + } else { + // Handle: bitcast (<2 x i64> to <4 x i32>) + unsigned Ratio = NumDstElt/NumSrcElt; + unsigned DstBitSize = DstEltTy->getPrimitiveSizeInBits(); + + // Loop over each source value, expanding into multiple results. + for (unsigned i = 0; i != NumSrcElt; ++i) { + Constant *Src = dyn_cast(CV->getOperand(i)); + if (!Src) // Reject constantexpr elements. + return ConstantExpr::getBitCast(C, DestTy); + + unsigned ShiftAmt = isLittleEndian ? 0 : DstBitSize*(Ratio-1); + for (unsigned j = 0; j != Ratio; ++j) { + // Shift the piece of the value into the right place, depending on + // endianness. + Constant *Elt = ConstantExpr::getLShr(Src, + ConstantInt::get(Src->getType(), ShiftAmt)); + ShiftAmt += isLittleEndian ? DstBitSize : -DstBitSize; + + // Truncate and remember this piece. + Result.push_back(ConstantExpr::getTrunc(Elt, DstEltTy)); + } + } + } + + return ConstantVector::get(Result); +} + + +/// IsConstantOffsetFromGlobal - If this constant is actually a constant offset +/// from a global, return the global and the constant. Because of +/// constantexprs, this function is recursive. +static bool IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV, + int64_t &Offset, const TargetData &TD) { + // Trivial case, constant is the global. + if ((GV = dyn_cast(C))) { + Offset = 0; + return true; + } + + // Otherwise, if this isn't a constant expr, bail out. + ConstantExpr *CE = dyn_cast(C); + if (!CE) return false; + + // Look through ptr->int and ptr->ptr casts. + if (CE->getOpcode() == Instruction::PtrToInt || + CE->getOpcode() == Instruction::BitCast) + return IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD); + + // i32* getelementptr ([5 x i32]* @a, i32 0, i32 5) + if (CE->getOpcode() == Instruction::GetElementPtr) { + // Cannot compute this if the element type of the pointer is missing size + // info. + if (!cast(CE->getOperand(0)->getType()) + ->getElementType()->isSized()) + return false; + + // If the base isn't a global+constant, we aren't either. + if (!IsConstantOffsetFromGlobal(CE->getOperand(0), GV, Offset, TD)) + return false; + + // Otherwise, add any offset that our operands provide. + gep_type_iterator GTI = gep_type_begin(CE); + for (User::const_op_iterator i = CE->op_begin() + 1, e = CE->op_end(); + i != e; ++i, ++GTI) { + ConstantInt *CI = dyn_cast(*i); + if (!CI) return false; // Index isn't a simple constant? + if (CI->isZero()) continue; // Not adding anything. + + if (const StructType *ST = dyn_cast(*GTI)) { + // N = N + Offset + Offset += TD.getStructLayout(ST)->getElementOffset(CI->getZExtValue()); + } else { + const SequentialType *SQT = cast(*GTI); + Offset += TD.getTypeAllocSize(SQT->getElementType())*CI->getSExtValue(); + } + } + return true; + } + + return false; +} + +/// ReadDataFromGlobal - Recursive helper to read bits out of global. C is the +/// constant being copied out of. ByteOffset is an offset into C. CurPtr is the +/// pointer to copy results into and BytesLeft is the number of bytes left in +/// the CurPtr buffer. TD is the target data. +static bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, + unsigned char *CurPtr, unsigned BytesLeft, + const TargetData &TD) { + assert(ByteOffset <= TD.getTypeAllocSize(C->getType()) && + "Out of range access"); + + // If this element is zero or undefined, we can just return since *CurPtr is + // zero initialized. + if (isa(C) || isa(C)) + return true; + + if (ConstantInt *CI = dyn_cast(C)) { + if (CI->getBitWidth() > 64 || + (CI->getBitWidth() & 7) != 0) + return false; + + uint64_t Val = CI->getZExtValue(); + unsigned IntBytes = unsigned(CI->getBitWidth()/8); + + for (unsigned i = 0; i != BytesLeft && ByteOffset != IntBytes; ++i) { + CurPtr[i] = (unsigned char)(Val >> (ByteOffset * 8)); + ++ByteOffset; + } + return true; + } + + if (ConstantFP *CFP = dyn_cast(C)) { + if (CFP->getType()->isDoubleTy()) { + C = FoldBitCast(C, Type::getInt64Ty(C->getContext()), TD); + return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, TD); + } + if (CFP->getType()->isFloatTy()){ + C = FoldBitCast(C, Type::getInt32Ty(C->getContext()), TD); + return ReadDataFromGlobal(C, ByteOffset, CurPtr, BytesLeft, TD); + } + return false; + } + + if (ConstantStruct *CS = dyn_cast(C)) { + const StructLayout *SL = TD.getStructLayout(CS->getType()); + unsigned Index = SL->getElementContainingOffset(ByteOffset); + uint64_t CurEltOffset = SL->getElementOffset(Index); + ByteOffset -= CurEltOffset; + + while (1) { + // If the element access is to the element itself and not to tail padding, + // read the bytes from the element. + uint64_t EltSize = TD.getTypeAllocSize(CS->getOperand(Index)->getType()); + + if (ByteOffset < EltSize && + !ReadDataFromGlobal(CS->getOperand(Index), ByteOffset, CurPtr, + BytesLeft, TD)) + return false; + + ++Index; + + // Check to see if we read from the last struct element, if so we're done. + if (Index == CS->getType()->getNumElements()) + return true; + + // If we read all of the bytes we needed from this element we're done. + uint64_t NextEltOffset = SL->getElementOffset(Index); + + if (BytesLeft <= NextEltOffset-CurEltOffset-ByteOffset) + return true; + + // Move to the next element of the struct. + CurPtr += NextEltOffset-CurEltOffset-ByteOffset; + BytesLeft -= NextEltOffset-CurEltOffset-ByteOffset; + ByteOffset = 0; + CurEltOffset = NextEltOffset; + } + // not reached. + } + + if (ConstantArray *CA = dyn_cast(C)) { + uint64_t EltSize = TD.getTypeAllocSize(CA->getType()->getElementType()); + uint64_t Index = ByteOffset / EltSize; + uint64_t Offset = ByteOffset - Index * EltSize; + for (; Index != CA->getType()->getNumElements(); ++Index) { + if (!ReadDataFromGlobal(CA->getOperand(Index), Offset, CurPtr, + BytesLeft, TD)) + return false; + if (EltSize >= BytesLeft) + return true; + + Offset = 0; + BytesLeft -= EltSize; + CurPtr += EltSize; + } + return true; + } + + if (ConstantVector *CV = dyn_cast(C)) { + uint64_t EltSize = TD.getTypeAllocSize(CV->getType()->getElementType()); + uint64_t Index = ByteOffset / EltSize; + uint64_t Offset = ByteOffset - Index * EltSize; + for (; Index != CV->getType()->getNumElements(); ++Index) { + if (!ReadDataFromGlobal(CV->getOperand(Index), Offset, CurPtr, + BytesLeft, TD)) + return false; + if (EltSize >= BytesLeft) + return true; + + Offset = 0; + BytesLeft -= EltSize; + CurPtr += EltSize; + } + return true; + } + + if (ConstantExpr *CE = dyn_cast(C)) { + if (CE->getOpcode() == Instruction::IntToPtr && + CE->getOperand(0)->getType() == TD.getIntPtrType(CE->getContext())) + return ReadDataFromGlobal(CE->getOperand(0), ByteOffset, CurPtr, + BytesLeft, TD); + } + + // Otherwise, unknown initializer type. + return false; +} + +static Constant *FoldReinterpretLoadFromConstPtr(Constant *C, + const TargetData &TD) { + const Type *LoadTy = cast(C->getType())->getElementType(); + const IntegerType *IntType = dyn_cast(LoadTy); + + // If this isn't an integer load we can't fold it directly. + if (!IntType) { + // If this is a float/double load, we can try folding it as an int32/64 load + // and then bitcast the result. This can be useful for union cases. Note + // that address spaces don't matter here since we're not going to result in + // an actual new load. + const Type *MapTy; + if (LoadTy->isFloatTy()) + MapTy = Type::getInt32PtrTy(C->getContext()); + else if (LoadTy->isDoubleTy()) + MapTy = Type::getInt64PtrTy(C->getContext()); + else if (LoadTy->isVectorTy()) { + MapTy = IntegerType::get(C->getContext(), + TD.getTypeAllocSizeInBits(LoadTy)); + MapTy = PointerType::getUnqual(MapTy); + } else + return 0; + + C = FoldBitCast(C, MapTy, TD); + if (Constant *Res = FoldReinterpretLoadFromConstPtr(C, TD)) + return FoldBitCast(Res, LoadTy, TD); + return 0; + } + + unsigned BytesLoaded = (IntType->getBitWidth() + 7) / 8; + if (BytesLoaded > 32 || BytesLoaded == 0) return 0; + + GlobalValue *GVal; + int64_t Offset; + if (!IsConstantOffsetFromGlobal(C, GVal, Offset, TD)) + return 0; + + GlobalVariable *GV = dyn_cast(GVal); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || + !GV->getInitializer()->getType()->isSized()) + return 0; + + // If we're loading off the beginning of the global, some bytes may be valid, + // but we don't try to handle this. + if (Offset < 0) return 0; + + // If we're not accessing anything in this constant, the result is undefined. + if (uint64_t(Offset) >= TD.getTypeAllocSize(GV->getInitializer()->getType())) + return UndefValue::get(IntType); + + unsigned char RawBytes[32] = {0}; + if (!ReadDataFromGlobal(GV->getInitializer(), Offset, RawBytes, + BytesLoaded, TD)) + return 0; + + APInt ResultVal = APInt(IntType->getBitWidth(), RawBytes[BytesLoaded-1]); + for (unsigned i = 1; i != BytesLoaded; ++i) { + ResultVal <<= 8; + ResultVal |= RawBytes[BytesLoaded-1-i]; + } + + return ConstantInt::get(IntType->getContext(), ResultVal); +} + +/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would +/// produce if it is constant and determinable. If this is not determinable, +/// return null. +Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, + const TargetData *TD) { + // First, try the easy cases: + if (GlobalVariable *GV = dyn_cast(C)) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + return GV->getInitializer(); + + // If the loaded value isn't a constant expr, we can't handle it. + ConstantExpr *CE = dyn_cast(C); + if (!CE) return 0; + + if (CE->getOpcode() == Instruction::GetElementPtr) { + if (GlobalVariable *GV = dyn_cast(CE->getOperand(0))) + if (GV->isConstant() && GV->hasDefinitiveInitializer()) + if (Constant *V = + ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE)) + return V; + } + + // Instead of loading constant c string, use corresponding integer value + // directly if string length is small enough. + std::string Str; + if (TD && GetConstantStringInfo(CE, Str) && !Str.empty()) { + unsigned StrLen = Str.length(); + const Type *Ty = cast(CE->getType())->getElementType(); + unsigned NumBits = Ty->getPrimitiveSizeInBits(); + // Replace load with immediate integer if the result is an integer or fp + // value. + if ((NumBits >> 3) == StrLen + 1 && (NumBits & 7) == 0 && + (isa(Ty) || Ty->isFloatingPointTy())) { + APInt StrVal(NumBits, 0); + APInt SingleChar(NumBits, 0); + if (TD->isLittleEndian()) { + for (signed i = StrLen-1; i >= 0; i--) { + SingleChar = (uint64_t) Str[i] & UCHAR_MAX; + StrVal = (StrVal << 8) | SingleChar; + } + } else { + for (unsigned i = 0; i < StrLen; i++) { + SingleChar = (uint64_t) Str[i] & UCHAR_MAX; + StrVal = (StrVal << 8) | SingleChar; + } + // Append NULL at the end. + SingleChar = 0; + StrVal = (StrVal << 8) | SingleChar; + } + + Constant *Res = ConstantInt::get(CE->getContext(), StrVal); + if (Ty->isFloatingPointTy()) + Res = ConstantExpr::getBitCast(Res, Ty); + return Res; + } + } + + // If this load comes from anywhere in a constant global, and if the global + // is all undef or zero, we know what it loads. + if (GlobalVariable *GV = + dyn_cast(GetUnderlyingObject(CE, TD))) { + if (GV->isConstant() && GV->hasDefinitiveInitializer()) { + const Type *ResTy = cast(C->getType())->getElementType(); + if (GV->getInitializer()->isNullValue()) + return Constant::getNullValue(ResTy); + if (isa(GV->getInitializer())) + return UndefValue::get(ResTy); + } + } + + // Try hard to fold loads from bitcasted strange and non-type-safe things. We + // currently don't do any of this for big endian systems. It can be + // generalized in the future if someone is interested. + if (TD && TD->isLittleEndian()) + return FoldReinterpretLoadFromConstPtr(CE, *TD); + return 0; +} + +static Constant *ConstantFoldLoadInst(const LoadInst *LI, const TargetData *TD){ + if (LI->isVolatile()) return 0; + + if (Constant *C = dyn_cast(LI->getOperand(0))) + return ConstantFoldLoadFromConstPtr(C, TD); + + return 0; +} + +/// SymbolicallyEvaluateBinop - One of Op0/Op1 is a constant expression. +/// Attempt to symbolically evaluate the result of a binary operator merging +/// these together. If target data info is available, it is provided as TD, +/// otherwise TD is null. +static Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, + Constant *Op1, const TargetData *TD){ + // SROA + + // Fold (and 0xffffffff00000000, (shl x, 32)) -> shl. + // Fold (lshr (or X, Y), 32) -> (lshr [X/Y], 32) if one doesn't contribute + // bits. + + + // If the constant expr is something like &A[123] - &A[4].f, fold this into a + // constant. This happens frequently when iterating over a global array. + if (Opc == Instruction::Sub && TD) { + GlobalValue *GV1, *GV2; + int64_t Offs1, Offs2; + + if (IsConstantOffsetFromGlobal(Op0, GV1, Offs1, *TD)) + if (IsConstantOffsetFromGlobal(Op1, GV2, Offs2, *TD) && + GV1 == GV2) { + // (&GV+C1) - (&GV+C2) -> C1-C2, pointer arithmetic cannot overflow. + return ConstantInt::get(Op0->getType(), Offs1-Offs2); + } + } + + return 0; +} + +/// CastGEPIndices - If array indices are not pointer-sized integers, +/// explicitly cast them so that they aren't implicitly casted by the +/// getelementptr. +static Constant *CastGEPIndices(Constant *const *Ops, unsigned NumOps, + const Type *ResultTy, + const TargetData *TD) { + if (!TD) return 0; + const Type *IntPtrTy = TD->getIntPtrType(ResultTy->getContext()); + + bool Any = false; + SmallVector NewIdxs; + for (unsigned i = 1; i != NumOps; ++i) { + if ((i == 1 || + !isa(GetElementPtrInst::getIndexedType(Ops[0]->getType(), + reinterpret_cast(Ops+1), + i-1))) && + Ops[i]->getType() != IntPtrTy) { + Any = true; + NewIdxs.push_back(ConstantExpr::getCast(CastInst::getCastOpcode(Ops[i], + true, + IntPtrTy, + true), + Ops[i], IntPtrTy)); + } else + NewIdxs.push_back(Ops[i]); + } + if (!Any) return 0; + + Constant *C = + ConstantExpr::getGetElementPtr(Ops[0], &NewIdxs[0], NewIdxs.size()); + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) + C = Folded; + return C; +} + +/// SymbolicallyEvaluateGEP - If we can symbolically evaluate the specified GEP +/// constant expression, do so. +static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, + const Type *ResultTy, + const TargetData *TD) { + Constant *Ptr = Ops[0]; + if (!TD || !cast(Ptr->getType())->getElementType()->isSized()) + return 0; + + const Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext()); + + // If this is a constant expr gep that is effectively computing an + // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' + for (unsigned i = 1; i != NumOps; ++i) + if (!isa(Ops[i])) { + + // If this is "gep i8* Ptr, (sub 0, V)", fold this as: + // "inttoptr (sub (ptrtoint Ptr), V)" + if (NumOps == 2 && + cast(ResultTy)->getElementType()->isIntegerTy(8)) { + ConstantExpr *CE = dyn_cast(Ops[1]); + assert((CE == 0 || CE->getType() == IntPtrTy) && + "CastGEPIndices didn't canonicalize index types!"); + if (CE && CE->getOpcode() == Instruction::Sub && + CE->getOperand(0)->isNullValue()) { + Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType()); + Res = ConstantExpr::getSub(Res, CE->getOperand(1)); + Res = ConstantExpr::getIntToPtr(Res, ResultTy); + if (ConstantExpr *ResCE = dyn_cast(Res)) + Res = ConstantFoldConstantExpression(ResCE, TD); + return Res; + } + } + return 0; + } + + unsigned BitWidth = TD->getTypeSizeInBits(IntPtrTy); + APInt Offset = APInt(BitWidth, + TD->getIndexedOffset(Ptr->getType(), + (Value**)Ops+1, NumOps-1)); + Ptr = cast(Ptr->stripPointerCasts()); + + // If this is a GEP of a GEP, fold it all into a single GEP. + while (GEPOperator *GEP = dyn_cast(Ptr)) { + SmallVector NestedOps(GEP->op_begin()+1, GEP->op_end()); + + // Do not try the incorporate the sub-GEP if some index is not a number. + bool AllConstantInt = true; + for (unsigned i = 0, e = NestedOps.size(); i != e; ++i) + if (!isa(NestedOps[i])) { + AllConstantInt = false; + break; + } + if (!AllConstantInt) + break; + + Ptr = cast(GEP->getOperand(0)); + Offset += APInt(BitWidth, + TD->getIndexedOffset(Ptr->getType(), + (Value**)NestedOps.data(), + NestedOps.size())); + Ptr = cast(Ptr->stripPointerCasts()); + } + + // If the base value for this address is a literal integer value, fold the + // getelementptr to the resulting integer value casted to the pointer type. + APInt BasePtr(BitWidth, 0); + if (ConstantExpr *CE = dyn_cast(Ptr)) + if (CE->getOpcode() == Instruction::IntToPtr) + if (ConstantInt *Base = dyn_cast(CE->getOperand(0))) + BasePtr = Base->getValue().zextOrTrunc(BitWidth); + if (Ptr->isNullValue() || BasePtr != 0) { + Constant *C = ConstantInt::get(Ptr->getContext(), Offset+BasePtr); + return ConstantExpr::getIntToPtr(C, ResultTy); + } + + // Otherwise form a regular getelementptr. Recompute the indices so that + // we eliminate over-indexing of the notional static type array bounds. + // This makes it easy to determine if the getelementptr is "inbounds". + // Also, this helps GlobalOpt do SROA on GlobalVariables. + const Type *Ty = Ptr->getType(); + SmallVector NewIdxs; + do { + if (const SequentialType *ATy = dyn_cast(Ty)) { + if (ATy->isPointerTy()) { + // The only pointer indexing we'll do is on the first index of the GEP. + if (!NewIdxs.empty()) + break; + + // Only handle pointers to sized types, not pointers to functions. + if (!ATy->getElementType()->isSized()) + return 0; + } + + // Determine which element of the array the offset points into. + APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType())); + const IntegerType *IntPtrTy = TD->getIntPtrType(Ty->getContext()); + if (ElemSize == 0) + // The element size is 0. This may be [0 x Ty]*, so just use a zero + // index for this level and proceed to the next level to see if it can + // accommodate the offset. + NewIdxs.push_back(ConstantInt::get(IntPtrTy, 0)); + else { + // The element size is non-zero divide the offset by the element + // size (rounding down), to compute the index at this level. + APInt NewIdx = Offset.udiv(ElemSize); + Offset -= NewIdx * ElemSize; + NewIdxs.push_back(ConstantInt::get(IntPtrTy, NewIdx)); + } + Ty = ATy->getElementType(); + } else if (const StructType *STy = dyn_cast(Ty)) { + // Determine which field of the struct the offset points into. The + // getZExtValue is at least as safe as the StructLayout API because we + // know the offset is within the struct at this point. + const StructLayout &SL = *TD->getStructLayout(STy); + unsigned ElIdx = SL.getElementContainingOffset(Offset.getZExtValue()); + NewIdxs.push_back(ConstantInt::get(Type::getInt32Ty(Ty->getContext()), + ElIdx)); + Offset -= APInt(BitWidth, SL.getElementOffset(ElIdx)); + Ty = STy->getTypeAtIndex(ElIdx); + } else { + // We've reached some non-indexable type. + break; + } + } while (Ty != cast(ResultTy)->getElementType()); + + // If we haven't used up the entire offset by descending the static + // type, then the offset is pointing into the middle of an indivisible + // member, so we can't simplify it. + if (Offset != 0) + return 0; + + // Create a GEP. + Constant *C = + ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size()); + assert(cast(C->getType())->getElementType() == Ty && + "Computed GetElementPtr has unexpected type!"); + + // If we ended up indexing a member with a type that doesn't match + // the type of what the original indices indexed, add a cast. + if (Ty != cast(ResultTy)->getElementType()) + C = FoldBitCast(C, ResultTy, *TD); + + return C; +} + + + +//===----------------------------------------------------------------------===// +// Constant Folding public APIs +//===----------------------------------------------------------------------===// + +/// ConstantFoldInstruction - Try to constant fold the specified instruction. +/// If successful, the constant result is returned, if not, null is returned. +/// Note that this fails if not all of the operands are constant. Otherwise, +/// this function can only fail when attempting to fold instructions like loads +/// and stores, which have no constant expression form. +Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { + // Handle PHI nodes quickly here... + if (PHINode *PN = dyn_cast(I)) { + Constant *CommonValue = 0; + + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = PN->getIncomingValue(i); + // If the incoming value is undef then skip it. Note that while we could + // skip the value if it is equal to the phi node itself we choose not to + // because that would break the rule that constant folding only applies if + // all operands are constants. + if (isa(Incoming)) + continue; + // If the incoming value is not a constant, or is a different constant to + // the one we saw previously, then give up. + Constant *C = dyn_cast(Incoming); + if (!C || (CommonValue && C != CommonValue)) + return 0; + CommonValue = C; + } + + // If we reach here, all incoming values are the same constant or undef. + return CommonValue ? CommonValue : UndefValue::get(PN->getType()); + } + + // Scan the operand list, checking to see if they are all constants, if so, + // hand off to ConstantFoldInstOperands. + SmallVector Ops; + for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) + if (Constant *Op = dyn_cast(*i)) + Ops.push_back(Op); + else + return 0; // All operands not constant! + + if (const CmpInst *CI = dyn_cast(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), Ops[0], Ops[1], + TD); + + if (const LoadInst *LI = dyn_cast(I)) + return ConstantFoldLoadInst(LI, TD); + + if (InsertValueInst *IVI = dyn_cast(I)) + return ConstantExpr::getInsertValue( + cast(IVI->getAggregateOperand()), + cast(IVI->getInsertedValueOperand()), + IVI->idx_begin(), IVI->getNumIndices()); + + if (ExtractValueInst *EVI = dyn_cast(I)) + return ConstantExpr::getExtractValue( + cast(EVI->getAggregateOperand()), + EVI->idx_begin(), EVI->getNumIndices()); + + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + Ops.data(), Ops.size(), TD); +} + +/// ConstantFoldConstantExpression - Attempt to fold the constant expression +/// using the specified TargetData. If successful, the constant result is +/// result is returned, if not, null is returned. +Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, + const TargetData *TD) { + SmallVector Ops; + for (User::const_op_iterator i = CE->op_begin(), e = CE->op_end(); + i != e; ++i) { + Constant *NewC = cast(*i); + // Recursively fold the ConstantExpr's operands. + if (ConstantExpr *NewCE = dyn_cast(NewC)) + NewC = ConstantFoldConstantExpression(NewCE, TD); + Ops.push_back(NewC); + } + + if (CE->isCompare()) + return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1], + TD); + return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(), + Ops.data(), Ops.size(), TD); +} + +/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the +/// specified opcode and operands. If successful, the constant result is +/// returned, if not, null is returned. Note that this function can fail when +/// attempting to fold instructions like loads and stores, which have no +/// constant expression form. +/// +/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc +/// information, due to only being passed an opcode and operands. Constant +/// folding using this function strips this information. +/// +Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant* const* Ops, unsigned NumOps, + const TargetData *TD) { + // Handle easy binops first. + if (Instruction::isBinaryOp(Opcode)) { + if (isa(Ops[0]) || isa(Ops[1])) + if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], TD)) + return C; + + return ConstantExpr::get(Opcode, Ops[0], Ops[1]); + } + + switch (Opcode) { + default: return 0; + case Instruction::ICmp: + case Instruction::FCmp: assert(0 && "Invalid for compares"); + case Instruction::Call: + if (Function *F = dyn_cast(Ops[NumOps - 1])) + if (canConstantFoldCallTo(F)) + return ConstantFoldCall(F, Ops, NumOps - 1); + return 0; + case Instruction::PtrToInt: + // If the input is a inttoptr, eliminate the pair. This requires knowing + // the width of a pointer, so it can't be done in ConstantExpr::getCast. + if (ConstantExpr *CE = dyn_cast(Ops[0])) { + if (TD && CE->getOpcode() == Instruction::IntToPtr) { + Constant *Input = CE->getOperand(0); + unsigned InWidth = Input->getType()->getScalarSizeInBits(); + if (TD->getPointerSizeInBits() < InWidth) { + Constant *Mask = + ConstantInt::get(CE->getContext(), APInt::getLowBitsSet(InWidth, + TD->getPointerSizeInBits())); + Input = ConstantExpr::getAnd(Input, Mask); + } + // Do a zext or trunc to get to the dest size. + return ConstantExpr::getIntegerCast(Input, DestTy, false); + } + } + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::IntToPtr: + // If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if + // the int size is >= the ptr size. This requires knowing the width of a + // pointer, so it can't be done in ConstantExpr::getCast. + if (ConstantExpr *CE = dyn_cast(Ops[0])) + if (TD && + TD->getPointerSizeInBits() <= CE->getType()->getScalarSizeInBits() && + CE->getOpcode() == Instruction::PtrToInt) + return FoldBitCast(CE->getOperand(0), DestTy, *TD); + + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); + case Instruction::BitCast: + if (TD) + return FoldBitCast(Ops[0], DestTy, *TD); + return ConstantExpr::getBitCast(Ops[0], DestTy); + case Instruction::Select: + return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); + case Instruction::ExtractElement: + return ConstantExpr::getExtractElement(Ops[0], Ops[1]); + case Instruction::InsertElement: + return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); + case Instruction::ShuffleVector: + return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + case Instruction::GetElementPtr: + if (Constant *C = CastGEPIndices(Ops, NumOps, DestTy, TD)) + return C; + if (Constant *C = SymbolicallyEvaluateGEP(Ops, NumOps, DestTy, TD)) + return C; + + return ConstantExpr::getGetElementPtr(Ops[0], Ops+1, NumOps-1); + } +} + +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, + Constant *Ops0, Constant *Ops1, + const TargetData *TD) { + // fold: icmp (inttoptr x), null -> icmp x, 0 + // fold: icmp (ptrtoint x), 0 -> icmp x, null + // fold: icmp (inttoptr x), (inttoptr y) -> icmp trunc/zext x, trunc/zext y + // fold: icmp (ptrtoint x), (ptrtoint y) -> icmp x, y + // + // ConstantExpr::getCompare cannot do this, because it doesn't have TD + // around to know if bit truncation is happening. + if (ConstantExpr *CE0 = dyn_cast(Ops0)) { + if (TD && Ops1->isNullValue()) { + const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + if (CE0->getOpcode() == Instruction::IntToPtr) { + // Convert the integer value to the right size to ensure we get the + // proper extension or truncation. + Constant *C = ConstantExpr::getIntegerCast(CE0->getOperand(0), + IntPtrTy, false); + Constant *Null = Constant::getNullValue(C->getType()); + return ConstantFoldCompareInstOperands(Predicate, C, Null, TD); + } + + // Only do this transformation if the int is intptrty in size, otherwise + // there is a truncation or extension that we aren't modeling. + if (CE0->getOpcode() == Instruction::PtrToInt && + CE0->getType() == IntPtrTy) { + Constant *C = CE0->getOperand(0); + Constant *Null = Constant::getNullValue(C->getType()); + return ConstantFoldCompareInstOperands(Predicate, C, Null, TD); + } + } + + if (ConstantExpr *CE1 = dyn_cast(Ops1)) { + if (TD && CE0->getOpcode() == CE1->getOpcode()) { + const Type *IntPtrTy = TD->getIntPtrType(CE0->getContext()); + + if (CE0->getOpcode() == Instruction::IntToPtr) { + // Convert the integer value to the right size to ensure we get the + // proper extension or truncation. + Constant *C0 = ConstantExpr::getIntegerCast(CE0->getOperand(0), + IntPtrTy, false); + Constant *C1 = ConstantExpr::getIntegerCast(CE1->getOperand(0), + IntPtrTy, false); + return ConstantFoldCompareInstOperands(Predicate, C0, C1, TD); + } + + // Only do this transformation if the int is intptrty in size, otherwise + // there is a truncation or extension that we aren't modeling. + if ((CE0->getOpcode() == Instruction::PtrToInt && + CE0->getType() == IntPtrTy && + CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType())) + return ConstantFoldCompareInstOperands(Predicate, CE0->getOperand(0), + CE1->getOperand(0), TD); + } + } + + // icmp eq (or x, y), 0 -> (icmp eq x, 0) & (icmp eq y, 0) + // icmp ne (or x, y), 0 -> (icmp ne x, 0) | (icmp ne y, 0) + if ((Predicate == ICmpInst::ICMP_EQ || Predicate == ICmpInst::ICMP_NE) && + CE0->getOpcode() == Instruction::Or && Ops1->isNullValue()) { + Constant *LHS = + ConstantFoldCompareInstOperands(Predicate, CE0->getOperand(0), Ops1,TD); + Constant *RHS = + ConstantFoldCompareInstOperands(Predicate, CE0->getOperand(1), Ops1,TD); + unsigned OpC = + Predicate == ICmpInst::ICMP_EQ ? Instruction::And : Instruction::Or; + Constant *Ops[] = { LHS, RHS }; + return ConstantFoldInstOperands(OpC, LHS->getType(), Ops, 2, TD); + } + } + + return ConstantExpr::getCompare(Predicate, Ops0, Ops1); +} + + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *llvm::ConstantFoldLoadThroughGEPConstantExpr(Constant *C, + ConstantExpr *CE) { + if (CE->getOperand(1) != Constant::getNullValue(CE->getOperand(1)->getType())) + return 0; // Do not allow stepping over the value! + + // Loop over all of the operands, tracking down which value we are + // addressing... + gep_type_iterator I = gep_type_begin(CE), E = gep_type_end(CE); + for (++I; I != E; ++I) + if (const StructType *STy = dyn_cast(*I)) { + ConstantInt *CU = cast(I.getOperand()); + assert(CU->getZExtValue() < STy->getNumElements() && + "Struct index out of range!"); + unsigned El = (unsigned)CU->getZExtValue(); + if (ConstantStruct *CS = dyn_cast(C)) { + C = CS->getOperand(El); + } else if (isa(C)) { + C = Constant::getNullValue(STy->getElementType(El)); + } else if (isa(C)) { + C = UndefValue::get(STy->getElementType(El)); + } else { + return 0; + } + } else if (ConstantInt *CI = dyn_cast(I.getOperand())) { + if (const ArrayType *ATy = dyn_cast(*I)) { + if (CI->getZExtValue() >= ATy->getNumElements()) + return 0; + if (ConstantArray *CA = dyn_cast(C)) + C = CA->getOperand(CI->getZExtValue()); + else if (isa(C)) + C = Constant::getNullValue(ATy->getElementType()); + else if (isa(C)) + C = UndefValue::get(ATy->getElementType()); + else + return 0; + } else if (const VectorType *VTy = dyn_cast(*I)) { + if (CI->getZExtValue() >= VTy->getNumElements()) + return 0; + if (ConstantVector *CP = dyn_cast(C)) + C = CP->getOperand(CI->getZExtValue()); + else if (isa(C)) + C = Constant::getNullValue(VTy->getElementType()); + else if (isa(C)) + C = UndefValue::get(VTy->getElementType()); + else + return 0; + } else { + return 0; + } + } else { + return 0; + } + return C; +} + + +//===----------------------------------------------------------------------===// +// Constant Folding for Calls +// + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool +llvm::canConstantFoldCallTo(const Function *F) { + switch (F->getIntrinsicID()) { + case Intrinsic::sqrt: + case Intrinsic::powi: + case Intrinsic::bswap: + case Intrinsic::ctpop: + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::uadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::convert_from_fp16: + case Intrinsic::convert_to_fp16: + case Intrinsic::x86_sse_cvtss2si: + case Intrinsic::x86_sse_cvtss2si64: + case Intrinsic::x86_sse_cvttss2si: + case Intrinsic::x86_sse_cvttss2si64: + case Intrinsic::x86_sse2_cvtsd2si: + case Intrinsic::x86_sse2_cvtsd2si64: + case Intrinsic::x86_sse2_cvttsd2si: + case Intrinsic::x86_sse2_cvttsd2si64: + return true; + default: + return false; + case 0: break; + } + + if (!F->hasName()) return false; + StringRef Name = F->getName(); + + // In these cases, the check of the length is required. We don't want to + // return true for a name like "cos\0blah" which strcmp would return equal to + // "cos", but has length 8. + switch (Name[0]) { + default: return false; + case 'a': + return Name == "acos" || Name == "asin" || + Name == "atan" || Name == "atan2"; + case 'c': + return Name == "cos" || Name == "ceil" || Name == "cosf" || Name == "cosh"; + case 'e': + return Name == "exp"; + case 'f': + return Name == "fabs" || Name == "fmod" || Name == "floor"; + case 'l': + return Name == "log" || Name == "log10"; + case 'p': + return Name == "pow"; + case 's': + return Name == "sin" || Name == "sinh" || Name == "sqrt" || + Name == "sinf" || Name == "sqrtf"; + case 't': + return Name == "tan" || Name == "tanh"; + } +} + +static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, + const Type *Ty) { + sys::llvm_fenv_clearexcept(); + V = NativeFP(V); + if (sys::llvm_fenv_testexcept()) { + sys::llvm_fenv_clearexcept(); + return 0; + } + + if (Ty->isFloatTy()) + return ConstantFP::get(Ty->getContext(), APFloat((float)V)); + if (Ty->isDoubleTy()) + return ConstantFP::get(Ty->getContext(), APFloat(V)); + llvm_unreachable("Can only constant fold float/double"); + return 0; // dummy return to suppress warning +} + +static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), + double V, double W, const Type *Ty) { + sys::llvm_fenv_clearexcept(); + V = NativeFP(V, W); + if (sys::llvm_fenv_testexcept()) { + sys::llvm_fenv_clearexcept(); + return 0; + } + + if (Ty->isFloatTy()) + return ConstantFP::get(Ty->getContext(), APFloat((float)V)); + if (Ty->isDoubleTy()) + return ConstantFP::get(Ty->getContext(), APFloat(V)); + llvm_unreachable("Can only constant fold float/double"); + return 0; // dummy return to suppress warning +} + +/// ConstantFoldConvertToInt - Attempt to an SSE floating point to integer +/// conversion of a constant floating point. If roundTowardZero is false, the +/// default IEEE rounding is used (toward nearest, ties to even). This matches +/// the behavior of the non-truncating SSE instructions in the default rounding +/// mode. The desired integer type Ty is used to select how many bits are +/// available for the result. Returns null if the conversion cannot be +/// performed, otherwise returns the Constant value resulting from the +/// conversion. +static Constant *ConstantFoldConvertToInt(ConstantFP *Op, bool roundTowardZero, + const Type *Ty) { + assert(Op && "Called with NULL operand"); + APFloat Val(Op->getValueAPF()); + + // All of these conversion intrinsics form an integer of at most 64bits. + unsigned ResultWidth = cast(Ty)->getBitWidth(); + assert(ResultWidth <= 64 && + "Can only constant fold conversions to 64 and 32 bit ints"); + + uint64_t UIntVal; + bool isExact = false; + APFloat::roundingMode mode = roundTowardZero? APFloat::rmTowardZero + : APFloat::rmNearestTiesToEven; + APFloat::opStatus status = Val.convertToInteger(&UIntVal, ResultWidth, + /*isSigned=*/true, mode, + &isExact); + if (status != APFloat::opOK && status != APFloat::opInexact) + return 0; + return ConstantInt::get(Ty, UIntVal, /*isSigned=*/true); +} + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant * +llvm::ConstantFoldCall(Function *F, + Constant *const *Operands, unsigned NumOperands) { + if (!F->hasName()) return 0; + StringRef Name = F->getName(); + + const Type *Ty = F->getReturnType(); + if (NumOperands == 1) { + if (ConstantFP *Op = dyn_cast(Operands[0])) { + if (F->getIntrinsicID() == Intrinsic::convert_to_fp16) { + APFloat Val(Op->getValueAPF()); + + bool lost = false; + Val.convert(APFloat::IEEEhalf, APFloat::rmNearestTiesToEven, &lost); + + return ConstantInt::get(F->getContext(), Val.bitcastToAPInt()); + } + + if (!Ty->isFloatTy() && !Ty->isDoubleTy()) + return 0; + + /// We only fold functions with finite arguments. Folding NaN and inf is + /// likely to be aborted with an exception anyway, and some host libms + /// have known errors raising exceptions. + if (Op->getValueAPF().isNaN() || Op->getValueAPF().isInfinity()) + return 0; + + /// Currently APFloat versions of these functions do not exist, so we use + /// the host native double versions. Float versions are not called + /// directly but for all these it is true (float)(f((double)arg)) == + /// f(arg). Long double not supported yet. + double V = Ty->isFloatTy() ? (double)Op->getValueAPF().convertToFloat() : + Op->getValueAPF().convertToDouble(); + switch (Name[0]) { + case 'a': + if (Name == "acos") + return ConstantFoldFP(acos, V, Ty); + else if (Name == "asin") + return ConstantFoldFP(asin, V, Ty); + else if (Name == "atan") + return ConstantFoldFP(atan, V, Ty); + break; + case 'c': + if (Name == "ceil") + return ConstantFoldFP(ceil, V, Ty); + else if (Name == "cos") + return ConstantFoldFP(cos, V, Ty); + else if (Name == "cosh") + return ConstantFoldFP(cosh, V, Ty); + else if (Name == "cosf") + return ConstantFoldFP(cos, V, Ty); + break; + case 'e': + if (Name == "exp") + return ConstantFoldFP(exp, V, Ty); + break; + case 'f': + if (Name == "fabs") + return ConstantFoldFP(fabs, V, Ty); + else if (Name == "floor") + return ConstantFoldFP(floor, V, Ty); + break; + case 'l': + if (Name == "log" && V > 0) + return ConstantFoldFP(log, V, Ty); + else if (Name == "log10" && V > 0) + return ConstantFoldFP(log10, V, Ty); + else if (F->getIntrinsicID() == Intrinsic::sqrt && + (Ty->isFloatTy() || Ty->isDoubleTy())) { + if (V >= -0.0) + return ConstantFoldFP(sqrt, V, Ty); + else // Undefined + return Constant::getNullValue(Ty); + } + break; + case 's': + if (Name == "sin") + return ConstantFoldFP(sin, V, Ty); + else if (Name == "sinh") + return ConstantFoldFP(sinh, V, Ty); + else if (Name == "sqrt" && V >= 0) + return ConstantFoldFP(sqrt, V, Ty); + else if (Name == "sqrtf" && V >= 0) + return ConstantFoldFP(sqrt, V, Ty); + else if (Name == "sinf") + return ConstantFoldFP(sin, V, Ty); + break; + case 't': + if (Name == "tan") + return ConstantFoldFP(tan, V, Ty); + else if (Name == "tanh") + return ConstantFoldFP(tanh, V, Ty); + break; + default: + break; + } + return 0; + } + + if (ConstantInt *Op = dyn_cast(Operands[0])) { + switch (F->getIntrinsicID()) { + case Intrinsic::bswap: + return ConstantInt::get(F->getContext(), Op->getValue().byteSwap()); + case Intrinsic::ctpop: + return ConstantInt::get(Ty, Op->getValue().countPopulation()); + case Intrinsic::cttz: + return ConstantInt::get(Ty, Op->getValue().countTrailingZeros()); + case Intrinsic::ctlz: + return ConstantInt::get(Ty, Op->getValue().countLeadingZeros()); + case Intrinsic::convert_from_fp16: { + APFloat Val(Op->getValue()); + + bool lost = false; + APFloat::opStatus status = + Val.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost); + + // Conversion is always precise. + (void)status; + assert(status == APFloat::opOK && !lost && + "Precision lost during fp16 constfolding"); + + return ConstantFP::get(F->getContext(), Val); + } + default: + return 0; + } + } + + if (ConstantVector *Op = dyn_cast(Operands[0])) { + switch (F->getIntrinsicID()) { + default: break; + case Intrinsic::x86_sse_cvtss2si: + case Intrinsic::x86_sse_cvtss2si64: + case Intrinsic::x86_sse2_cvtsd2si: + case Intrinsic::x86_sse2_cvtsd2si64: + if (ConstantFP *FPOp = dyn_cast(Op->getOperand(0))) + return ConstantFoldConvertToInt(FPOp, /*roundTowardZero=*/false, Ty); + case Intrinsic::x86_sse_cvttss2si: + case Intrinsic::x86_sse_cvttss2si64: + case Intrinsic::x86_sse2_cvttsd2si: + case Intrinsic::x86_sse2_cvttsd2si64: + if (ConstantFP *FPOp = dyn_cast(Op->getOperand(0))) + return ConstantFoldConvertToInt(FPOp, /*roundTowardZero=*/true, Ty); + } + } + + if (isa(Operands[0])) { + if (F->getIntrinsicID() == Intrinsic::bswap) + return Operands[0]; + return 0; + } + + return 0; + } + + if (NumOperands == 2) { + if (ConstantFP *Op1 = dyn_cast(Operands[0])) { + if (!Ty->isFloatTy() && !Ty->isDoubleTy()) + return 0; + double Op1V = Ty->isFloatTy() ? + (double)Op1->getValueAPF().convertToFloat() : + Op1->getValueAPF().convertToDouble(); + if (ConstantFP *Op2 = dyn_cast(Operands[1])) { + if (Op2->getType() != Op1->getType()) + return 0; + + double Op2V = Ty->isFloatTy() ? + (double)Op2->getValueAPF().convertToFloat(): + Op2->getValueAPF().convertToDouble(); + + if (Name == "pow") + return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); + if (Name == "fmod") + return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty); + if (Name == "atan2") + return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); + } else if (ConstantInt *Op2C = dyn_cast(Operands[1])) { + if (F->getIntrinsicID() == Intrinsic::powi && Ty->isFloatTy()) + return ConstantFP::get(F->getContext(), + APFloat((float)std::pow((float)Op1V, + (int)Op2C->getZExtValue()))); + if (F->getIntrinsicID() == Intrinsic::powi && Ty->isDoubleTy()) + return ConstantFP::get(F->getContext(), + APFloat((double)std::pow((double)Op1V, + (int)Op2C->getZExtValue()))); + } + return 0; + } + + + if (ConstantInt *Op1 = dyn_cast(Operands[0])) { + if (ConstantInt *Op2 = dyn_cast(Operands[1])) { + switch (F->getIntrinsicID()) { + default: break; + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::smul_with_overflow: { + APInt Res; + bool Overflow; + switch (F->getIntrinsicID()) { + default: assert(0 && "Invalid case"); + case Intrinsic::sadd_with_overflow: + Res = Op1->getValue().sadd_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::uadd_with_overflow: + Res = Op1->getValue().uadd_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::ssub_with_overflow: + Res = Op1->getValue().ssub_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::usub_with_overflow: + Res = Op1->getValue().usub_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::smul_with_overflow: + Res = Op1->getValue().smul_ov(Op2->getValue(), Overflow); + break; + } + Constant *Ops[] = { + ConstantInt::get(F->getContext(), Res), + ConstantInt::get(Type::getInt1Ty(F->getContext()), Overflow) + }; + return ConstantStruct::get(F->getContext(), Ops, 2, false); + } + } + } + + return 0; + } + return 0; + } + return 0; +} diff --git a/final/lib/Analysis/DIBuilder.cpp b/final/lib/Analysis/DIBuilder.cpp new file mode 100644 index 00000000000..766624f87ce --- /dev/null +++ b/final/lib/Analysis/DIBuilder.cpp @@ -0,0 +1,801 @@ +//===--- DIBuilder.cpp - Debug Information Builder ------------------------===// +// +// 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 DIBuilder. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Dwarf.h" + +using namespace llvm; +using namespace llvm::dwarf; + +static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { + assert((Tag & LLVMDebugVersionMask) == 0 && + "Tag too large for debug encoding!"); + return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion); +} + +DIBuilder::DIBuilder(Module &m) + : M(m), VMContext(M.getContext()), TheCU(0), DeclareFn(0), ValueFn(0) {} + +/// createCompileUnit - A CompileUnit provides an anchor for all debugging +/// information generated during this instance of compilation. +void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, + StringRef Directory, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RunTimeVer) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + ConstantInt::get(Type::getInt32Ty(VMContext), Lang), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + MDString::get(VMContext, Producer), + // Deprecate isMain field. + ConstantInt::get(Type::getInt1Ty(VMContext), true), // isMain + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + MDString::get(VMContext, Flags), + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) + }; + TheCU = DICompileUnit(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createFile - Create a file descriptor to hold debugging information +/// for a file. +DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { + assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_file_type), + MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory), + TheCU + }; + return DIFile(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createEnumerator - Create a single enumerator value. +DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), + MDString::get(VMContext, Name), + ConstantInt::get(Type::getInt64Ty(VMContext), Val) + }; + return DIEnumerator(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createBasicType - Create debugging information entry for a basic +/// type, e.g 'char'. +DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { + // Basic types are encoded in DIBasicType format. Line number, filename, + // offset and flags are always empty here. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_base_type), + TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; + ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createQaulifiedType - Create debugging information entry for a qualified +/// type, e.g. 'const int'. +DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { + // Qualified types are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + TheCU, + MDString::get(VMContext, StringRef()), // Empty name. + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + FromTy + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createPointerType - Create debugging information entry for a pointer. +DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits, StringRef Name) { + // Pointer types are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), + TheCU, + MDString::get(VMContext, Name), + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + PointeeTy + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createReferenceType - Create debugging information entry for a reference. +DIType DIBuilder::createReferenceType(DIType RTy) { + // References are encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_reference_type), + TheCU, + NULL, // Name + NULL, // Filename + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + RTy + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createTypedef - Create debugging information entry for a typedef. +DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, + unsigned LineNo) { + // typedefs are encoded in DIDerivedType format. + assert(Ty.Verify() && "Invalid typedef type!"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_typedef), + Ty.getContext(), + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + Ty + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createFriend - Create debugging information entry for a 'friend'. +DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { + // typedefs are encoded in DIDerivedType format. + assert(Ty.Verify() && "Invalid type!"); + assert(FriendTy.Verify() && "Invalid friend type!"); + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_friend), + Ty, + NULL, // Name + Ty.getFile(), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags + FriendTy + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createInheritance - Create debugging information entry to establish +/// inheritnace relationship between two types. +DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, + uint64_t BaseOffset, unsigned Flags) { + // TAG_inheritance is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), + Ty, + NULL, // Name + Ty.getFile(), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size + ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align + ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + BaseTy + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createMemberType - Create debugging information entry for a member. +DIType DIBuilder::createMemberType(StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType Ty) { + // TAG_member is encoded in DIDerivedType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_member), + File, // Or TheCU ? Ty ? + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + Ty + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createClassType - Create debugging information entry for a class. +DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType DerivedFrom, DIArray Elements, + MDNode *VTableHoder, MDNode *TemplateParams) { + // TAG_class_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_class_type), + Context, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + DerivedFrom, + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + VTableHoder, + TemplateParams + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createTemplateTypeParameter - Create debugging information for template +/// type parameter. +DITemplateTypeParameter +DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, + DIType Ty, MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), + Context, + MDString::get(VMContext, Name), + Ty, + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) + }; + return DITemplateTypeParameter(MDNode::get(VMContext, &Elts[0], + array_lengthof(Elts))); +} + +/// createTemplateValueParameter - Create debugging information for template +/// value parameter. +DITemplateValueParameter +DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, + DIType Ty, uint64_t Val, + MDNode *File, unsigned LineNo, + unsigned ColumnNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_template_value_parameter), + Context, + MDString::get(VMContext, Name), + Ty, + ConstantInt::get(Type::getInt64Ty(VMContext), Val), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) + }; + return DITemplateValueParameter(MDNode::get(VMContext, &Elts[0], + array_lengthof(Elts))); +} + +/// createStructType - Create debugging information entry for a struct. +DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DIArray Elements, + unsigned RunTimeLang) { + // TAG_structure_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), + Context, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createUnionType - Create debugging information entry for an union. +DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, + DIFile File, + unsigned LineNumber, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, + DIArray Elements, unsigned RunTimeLang) { + // TAG_union_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_union_type), + Scope, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createSubroutineType - Create subroutine type. +DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) { + // TAG_subroutine_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), + File, + MDString::get(VMContext, ""), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + ParameterTypes, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createEnumerationType - Create debugging information entry for an +/// enumeration. +DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, DIArray Elements) { + // TAG_enumeration_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), + Scope, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Elements, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); + NMD->addOperand(Node); + return DIType(Node); +} + +/// createArrayType - Create debugging information entry for an array. +DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts) { + // TAG_array_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_array_type), + TheCU, + MDString::get(VMContext, ""), + TheCU, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), Size), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Ty, + Subscripts, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createVectorType - Create debugging information entry for a vector. +DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType Ty, DIArray Subscripts) { + // TAG_vector_type is encoded in DICompositeType format. + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_vector_type), + TheCU, + MDString::get(VMContext, ""), + TheCU, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt64Ty(VMContext), Size), + ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + Ty, + Subscripts, + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + }; + return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// createArtificialType - Create a new DIType with "artificial" flag set. +DIType DIBuilder::createArtificialType(DIType Ty) { + if (Ty.isArtificial()) + return Ty; + + SmallVector Elts; + MDNode *N = Ty; + assert (N && "Unexpected input DIType!"); + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (Value *V = N->getOperand(i)) + Elts.push_back(V); + else + Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); + } + + unsigned CurFlags = Ty.getFlags(); + CurFlags = CurFlags | DIType::FlagArtificial; + + // Flags are stored at this slot. + Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); + + return DIType(MDNode::get(VMContext, Elts.data(), Elts.size())); +} + +/// retainType - Retain DIType in a module even if it is not referenced +/// through debug info anchors. +void DIBuilder::retainType(DIType T) { + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty"); + NMD->addOperand(T); +} + +/// createUnspecifiedParameter - Create unspeicified type descriptor +/// for the subroutine type. +DIDescriptor DIBuilder::createUnspecifiedParameter() { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) + }; + return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1)); +} + +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType() { + // Give the temporary MDNode a tag. It doesn't matter what tag we + // use here as long as DIType accepts it. + Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); + return DIType(Node); +} + +/// createTemporaryType - Create a temporary forward-declared type. +DIType DIBuilder::createTemporaryType(DIFile F) { + // Give the temporary MDNode a tag. It doesn't matter what tag we + // use here as long as DIType accepts it. + Value *Elts[] = { + GetTagConstant(VMContext, DW_TAG_base_type), + F.getCompileUnit(), + NULL, + F + }; + MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); + return DIType(Node); +} + +/// getOrCreateArray - Get a DIArray, create one if required. +DIArray DIBuilder::getOrCreateArray(Value *const *Elements, unsigned NumElements) { + if (NumElements == 0) { + Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); + return DIArray(MDNode::get(VMContext, &Null, 1)); + } + return DIArray(MDNode::get(VMContext, Elements, NumElements)); +} + +/// getOrCreateSubrange - Create a descriptor for a value range. This +/// implicitly uniques the values returned. +DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), + ConstantInt::get(Type::getInt64Ty(VMContext), Lo), + ConstantInt::get(Type::getInt64Ty(VMContext), Hi) + }; + + return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); +} + +/// createGlobalVariable - Create a new descriptor for the specified global. +DIGlobalVariable DIBuilder:: +createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber, + DIType Ty, bool isLocalToUnit, llvm::Value *Val) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_variable), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + TheCU, + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ + Val + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + // Create a named metadata so that we do not lose this mdnode. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); + NMD->addOperand(Node); + return DIGlobalVariable(Node); +} + +/// createStaticVariable - Create a new descriptor for the specified static +/// variable. +DIGlobalVariable DIBuilder:: +createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile F, unsigned LineNumber, + DIType Ty, bool isLocalToUnit, llvm::Value *Val) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_variable), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Context, + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ + Val + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + // Create a named metadata so that we do not lose this mdnode. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); + NMD->addOperand(Node); + return DIGlobalVariable(Node); +} + +/// createVariable - Create a new descriptor for the specified variable. +DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile File, + unsigned LineNo, DIType Ty, + bool AlwaysPreserve, unsigned Flags, + unsigned ArgNo) { + Value *Elts[] = { + GetTagConstant(VMContext, Tag), + Scope, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), + Ty, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags) + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + if (AlwaysPreserve) { + // The optimizer may remove local variable. If there is an interest + // to preserve variable info in such situation then stash it in a + // named mdnode. + DISubprogram Fn(getDISubprogram(Scope)); + StringRef FName = "fn"; + if (Fn.getFunction()) + FName = Fn.getFunction()->getName(); + char One = '\1'; + if (FName.startswith(StringRef(&One, 1))) + FName = FName.substr(1); + NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, FName); + FnLocals->addOperand(Node); + } + return DIVariable(Node); +} + +/// createComplexVariable - Create a new descriptor for the specified variable +/// which has a complex address expression for its address. +DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIFile F, + unsigned LineNo, + DIType Ty, Value *const *Addr, + unsigned NumAddr, unsigned ArgNo) { + SmallVector Elts; + Elts.push_back(GetTagConstant(VMContext, Tag)); + Elts.push_back(Scope); + Elts.push_back(MDString::get(VMContext, Name)); + Elts.push_back(F); + Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24)))); + Elts.push_back(Ty); + Elts.append(Addr, Addr+NumAddr); + + return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size())); +} + +/// createFunction - Create a new descriptor for the specified function. +DISubprogram DIBuilder::createFunction(DIDescriptor Context, + StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DIType Ty, + bool isLocalToUnit, bool isDefinition, + unsigned Flags, bool isOptimized, + Function *Fn) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Context, + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Ty, + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + ConstantInt::get(Type::getInt32Ty(VMContext), 0), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + Fn + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + + // Create a named metadata so that we do not lose this mdnode. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); + NMD->addOperand(Node); + return DISubprogram(Node); +} + +/// createMethod - Create a new descriptor for the specified C++ method. +DISubprogram DIBuilder::createMethod(DIDescriptor Context, + StringRef Name, + StringRef LinkageName, + DIFile F, + unsigned LineNo, DIType Ty, + bool isLocalToUnit, + bool isDefinition, + unsigned VK, unsigned VIndex, + MDNode *VTableHolder, + unsigned Flags, + bool isOptimized, + Function *Fn) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), + llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), + Context, + MDString::get(VMContext, Name), + MDString::get(VMContext, Name), + MDString::get(VMContext, LinkageName), + F, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), + Ty, + ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), + ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), + ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), + ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), + VTableHolder, + ConstantInt::get(Type::getInt32Ty(VMContext), Flags), + ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), + Fn + }; + MDNode *Node = MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)); + + // Create a named metadata so that we do not lose this mdnode. + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); + NMD->addOperand(Node); + return DISubprogram(Node); +} + +/// createNameSpace - This creates new descriptor for a namespace +/// with the specified parent scope. +DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo) { + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_namespace), + Scope, + MDString::get(VMContext, Name), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) + }; + return DINameSpace(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, + unsigned Line, unsigned Col) { + // Defeat MDNode uniqing for lexical blocks by using unique id. + static unsigned int unique_id = 0; + Value *Elts[] = { + GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), + Scope, + ConstantInt::get(Type::getInt32Ty(VMContext), Line), + ConstantInt::get(Type::getInt32Ty(VMContext), Col), + File, + ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) + }; + return DILexicalBlock(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts))); +} + +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + Instruction *InsertBefore) { + assert(Storage && "no storage passed to dbg.declare"); + assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare"); + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), VarInfo }; + return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); +} + +/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + BasicBlock *InsertAtEnd) { + assert(Storage && "no storage passed to dbg.declare"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare"); + if (!DeclareFn) + DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); + + Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), VarInfo }; + + // If this block already has a terminator then insert this intrinsic + // before the terminator. + if (TerminatorInst *T = InsertAtEnd->getTerminator()) + return CallInst::Create(DeclareFn, Args, Args+2, "", T); + else + return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd); +} + +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, + DIVariable VarInfo, + Instruction *InsertBefore) { + assert(V && "no value passed to dbg.value"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + if (!ValueFn) + ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); + + Value *Args[] = { MDNode::get(V->getContext(), &V, 1), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo }; + return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); +} + +/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, + DIVariable VarInfo, + BasicBlock *InsertAtEnd) { + assert(V && "no value passed to dbg.value"); + assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.value"); + if (!ValueFn) + ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); + + Value *Args[] = { MDNode::get(V->getContext(), &V, 1), + ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), + VarInfo }; + return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); +} + diff --git a/final/lib/Analysis/DbgInfoPrinter.cpp b/final/lib/Analysis/DbgInfoPrinter.cpp new file mode 100644 index 00000000000..b23c3514d0b --- /dev/null +++ b/final/lib/Analysis/DbgInfoPrinter.cpp @@ -0,0 +1,224 @@ +//===- DbgInfoPrinter.cpp - Print debug info in a human readable form ------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass that prints instructions, and associated debug +// info: +// +// - source/line/col information +// - original variable name +// - original type name +// +//===----------------------------------------------------------------------===// + +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Metadata.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt +PrintDirectory("print-fullpath", + cl::desc("Print fullpath when printing debug info"), + cl::Hidden); + +namespace { + class PrintDbgInfo : public FunctionPass { + raw_ostream &Out; + void printVariableDeclaration(const Value *V); + public: + static char ID; // Pass identification + PrintDbgInfo() : FunctionPass(ID), Out(errs()) { + initializePrintDbgInfoPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + }; + char PrintDbgInfo::ID = 0; +} + +INITIALIZE_PASS(PrintDbgInfo, "print-dbginfo", + "Print debug info in human readable form", false, false) + +FunctionPass *llvm::createDbgInfoPrinterPass() { return new PrintDbgInfo(); } + +/// Find the debug info descriptor corresponding to this global variable. +static Value *findDbgGlobalDeclare(GlobalVariable *V) { + const Module *M = V->getParent(); + NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv"); + if (!NMD) + return 0; + + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIDescriptor DIG(cast(NMD->getOperand(i))); + if (!DIG.isGlobalVariable()) + continue; + if (DIGlobalVariable(DIG).getGlobal() == V) + return DIG; + } + return 0; +} + +/// Find the debug info descriptor corresponding to this function. +static Value *findDbgSubprogramDeclare(Function *V) { + const Module *M = V->getParent(); + NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.sp"); + if (!NMD) + return 0; + + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIDescriptor DIG(cast(NMD->getOperand(i))); + if (!DIG.isSubprogram()) + continue; + if (DISubprogram(DIG).getFunction() == V) + return DIG; + } + return 0; +} + +/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any. +/// It looks through pointer casts too. +static const DbgDeclareInst *findDbgDeclare(const Value *V) { + V = V->stripPointerCasts(); + + if (!isa(V) && !isa(V)) + return 0; + + const Function *F = NULL; + if (const Instruction *I = dyn_cast(V)) + F = I->getParent()->getParent(); + else if (const Argument *A = dyn_cast(V)) + F = A->getParent(); + + for (Function::const_iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) + for (BasicBlock::const_iterator BI = (*FI).begin(), BE = (*FI).end(); + BI != BE; ++BI) + if (const DbgDeclareInst *DDI = dyn_cast(BI)) + if (DDI->getAddress() == V) + return DDI; + + return 0; +} + +static bool getLocationInfo(const Value *V, std::string &DisplayName, + std::string &Type, unsigned &LineNo, + std::string &File, std::string &Dir) { + DICompileUnit Unit; + DIType TypeD; + + if (GlobalVariable *GV = dyn_cast(const_cast(V))) { + Value *DIGV = findDbgGlobalDeclare(GV); + if (!DIGV) return false; + DIGlobalVariable Var(cast(DIGV)); + + StringRef D = Var.getDisplayName(); + if (!D.empty()) + DisplayName = D; + LineNo = Var.getLineNumber(); + Unit = Var.getCompileUnit(); + TypeD = Var.getType(); + } else if (Function *F = dyn_cast(const_cast(V))){ + Value *DIF = findDbgSubprogramDeclare(F); + if (!DIF) return false; + DISubprogram Var(cast(DIF)); + + StringRef D = Var.getDisplayName(); + if (!D.empty()) + DisplayName = D; + LineNo = Var.getLineNumber(); + Unit = Var.getCompileUnit(); + TypeD = Var.getType(); + } else { + const DbgDeclareInst *DDI = findDbgDeclare(V); + if (!DDI) return false; + DIVariable Var(cast(DDI->getVariable())); + + StringRef D = Var.getName(); + if (!D.empty()) + DisplayName = D; + LineNo = Var.getLineNumber(); + Unit = Var.getCompileUnit(); + TypeD = Var.getType(); + } + + StringRef T = TypeD.getName(); + if (!T.empty()) + Type = T; + StringRef F = Unit.getFilename(); + if (!F.empty()) + File = F; + StringRef D = Unit.getDirectory(); + if (!D.empty()) + Dir = D; + return true; +} + +void PrintDbgInfo::printVariableDeclaration(const Value *V) { + std::string DisplayName, File, Directory, Type; + unsigned LineNo; + + if (!getLocationInfo(V, DisplayName, Type, LineNo, File, Directory)) + return; + + Out << "; "; + WriteAsOperand(Out, V, false, 0); + if (isa(V)) + Out << " is function " << DisplayName + << " of type " << Type << " declared at "; + else + Out << " is variable " << DisplayName + << " of type " << Type << " declared at "; + + if (PrintDirectory) + Out << Directory << "/"; + + Out << File << ":" << LineNo << "\n"; +} + +bool PrintDbgInfo::runOnFunction(Function &F) { + if (F.isDeclaration()) + return false; + + Out << "function " << F.getName() << "\n\n"; + + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) { + BasicBlock *BB = I; + + if (I != F.begin() && (pred_begin(BB) == pred_end(BB))) + // Skip dead blocks. + continue; + + Out << BB->getName(); + Out << ":"; + + Out << "\n"; + + for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); + i != e; ++i) { + + printVariableDeclaration(i); + + if (const User *U = dyn_cast(i)) { + for(unsigned i=0;igetNumOperands();i++) + printVariableDeclaration(U->getOperand(i)); + } + } + } + return false; +} diff --git a/final/lib/Analysis/DebugInfo.cpp b/final/lib/Analysis/DebugInfo.cpp new file mode 100644 index 00000000000..67f8147f4d6 --- /dev/null +++ b/final/lib/Analysis/DebugInfo.cpp @@ -0,0 +1,948 @@ +//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===// +// +// 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 helper classes used to build and interpret debug +// information in LLVM IR form. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace llvm::dwarf; + +//===----------------------------------------------------------------------===// +// DIDescriptor +//===----------------------------------------------------------------------===// + +DIDescriptor::DIDescriptor(const DIFile F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DISubprogram F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DILexicalBlock F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIVariable F) : DbgNode(F.DbgNode) { +} + +DIDescriptor::DIDescriptor(const DIType F) : DbgNode(F.DbgNode) { +} + +StringRef +DIDescriptor::getStringField(unsigned Elt) const { + if (DbgNode == 0) + return StringRef(); + + if (Elt < DbgNode->getNumOperands()) + if (MDString *MDS = dyn_cast_or_null(DbgNode->getOperand(Elt))) + return MDS->getString(); + + return StringRef(); +} + +uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + if (ConstantInt *CI = dyn_cast(DbgNode->getOperand(Elt))) + return CI->getZExtValue(); + + return 0; +} + +DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { + if (DbgNode == 0) + return DIDescriptor(); + + if (Elt < DbgNode->getNumOperands()) + return + DIDescriptor(dyn_cast_or_null(DbgNode->getOperand(Elt))); + return DIDescriptor(); +} + +GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + return 0; +} + +Constant *DIDescriptor::getConstantField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + return 0; +} + +Function *DIDescriptor::getFunctionField(unsigned Elt) const { + if (DbgNode == 0) + return 0; + + if (Elt < DbgNode->getNumOperands()) + return dyn_cast_or_null(DbgNode->getOperand(Elt)); + return 0; +} + +unsigned DIVariable::getNumAddrElements() const { + if (getVersion() <= llvm::LLVMDebugVersion8) + return DbgNode->getNumOperands()-6; + return DbgNode->getNumOperands()-7; +} + + +//===----------------------------------------------------------------------===// +// Predicates +//===----------------------------------------------------------------------===// + +/// isBasicType - Return true if the specified tag is legal for +/// DIBasicType. +bool DIDescriptor::isBasicType() const { + return DbgNode && getTag() == dwarf::DW_TAG_base_type; +} + +/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. +bool DIDescriptor::isDerivedType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_reference_type: + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_restrict_type: + case dwarf::DW_TAG_member: + case dwarf::DW_TAG_inheritance: + case dwarf::DW_TAG_friend: + return true; + default: + // CompositeTypes are currently modelled as DerivedTypes. + return isCompositeType(); + } +} + +/// isCompositeType - Return true if the specified tag is legal for +/// DICompositeType. +bool DIDescriptor::isCompositeType() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_array_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_subroutine_type: + case dwarf::DW_TAG_class_type: + return true; + default: + return false; + } +} + +/// isVariable - Return true if the specified tag is legal for DIVariable. +bool DIDescriptor::isVariable() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_auto_variable: + case dwarf::DW_TAG_arg_variable: + case dwarf::DW_TAG_return_variable: + return true; + default: + return false; + } +} + +/// isType - Return true if the specified tag is legal for DIType. +bool DIDescriptor::isType() const { + return isBasicType() || isCompositeType() || isDerivedType(); +} + +/// isSubprogram - Return true if the specified tag is legal for +/// DISubprogram. +bool DIDescriptor::isSubprogram() const { + return DbgNode && getTag() == dwarf::DW_TAG_subprogram; +} + +/// isGlobalVariable - Return true if the specified tag is legal for +/// DIGlobalVariable. +bool DIDescriptor::isGlobalVariable() const { + return DbgNode && (getTag() == dwarf::DW_TAG_variable || + getTag() == dwarf::DW_TAG_constant); +} + +/// isGlobal - Return true if the specified tag is legal for DIGlobal. +bool DIDescriptor::isGlobal() const { + return isGlobalVariable(); +} + +/// isUnspecifiedParmeter - Return true if the specified tag is +/// DW_TAG_unspecified_parameters. +bool DIDescriptor::isUnspecifiedParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters; +} + +/// isScope - Return true if the specified tag is one of the scope +/// related tag. +bool DIDescriptor::isScope() const { + if (!DbgNode) return false; + switch (getTag()) { + case dwarf::DW_TAG_compile_unit: + case dwarf::DW_TAG_lexical_block: + case dwarf::DW_TAG_subprogram: + case dwarf::DW_TAG_namespace: + return true; + default: + break; + } + return false; +} + +/// isTemplateTypeParameter - Return true if the specified tag is +/// DW_TAG_template_type_parameter. +bool DIDescriptor::isTemplateTypeParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter; +} + +/// isTemplateValueParameter - Return true if the specified tag is +/// DW_TAG_template_value_parameter. +bool DIDescriptor::isTemplateValueParameter() const { + return DbgNode && getTag() == dwarf::DW_TAG_template_value_parameter; +} + +/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. +bool DIDescriptor::isCompileUnit() const { + return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; +} + +/// isFile - Return true if the specified tag is DW_TAG_file_type. +bool DIDescriptor::isFile() const { + return DbgNode && getTag() == dwarf::DW_TAG_file_type; +} + +/// isNameSpace - Return true if the specified tag is DW_TAG_namespace. +bool DIDescriptor::isNameSpace() const { + return DbgNode && getTag() == dwarf::DW_TAG_namespace; +} + +/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. +bool DIDescriptor::isLexicalBlock() const { + return DbgNode && getTag() == dwarf::DW_TAG_lexical_block; +} + +/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. +bool DIDescriptor::isSubrange() const { + return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; +} + +/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. +bool DIDescriptor::isEnumerator() const { + return DbgNode && getTag() == dwarf::DW_TAG_enumerator; +} + +//===----------------------------------------------------------------------===// +// Simple Descriptor Constructors and other Methods +//===----------------------------------------------------------------------===// + +DIType::DIType(const MDNode *N) : DIScope(N) { + if (!N) return; + if (!isBasicType() && !isDerivedType() && !isCompositeType()) { + DbgNode = 0; + } +} + +unsigned DIArray::getNumElements() const { + if (!DbgNode) + return 0; + return DbgNode->getNumOperands(); +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(DIDescriptor &D) { + if (!DbgNode) + return; + + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (DbgNode != D) { + MDNode *Node = const_cast(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null(DN); + Node->replaceAllUsesWith(const_cast(V)); + MDNode::deleteTemporary(Node); + } +} + +/// replaceAllUsesWith - Replace all uses of debug info referenced by +/// this descriptor. +void DIType::replaceAllUsesWith(MDNode *D) { + if (!DbgNode) + return; + + // Since we use a TrackingVH for the node, its easy for clients to manufacture + // legitimate situations where they want to replaceAllUsesWith() on something + // which, due to uniquing, has merged with the source. We shield clients from + // this detail by allowing a value to be replaced with replaceAllUsesWith() + // itself. + if (DbgNode != D) { + MDNode *Node = const_cast(DbgNode); + const MDNode *DN = D; + const Value *V = cast_or_null(DN); + Node->replaceAllUsesWith(const_cast(V)); + MDNode::deleteTemporary(Node); + } +} + +/// Verify - Verify that a compile unit is well formed. +bool DICompileUnit::Verify() const { + if (!DbgNode) + return false; + StringRef N = getFilename(); + if (N.empty()) + return false; + // It is possible that directory and produce string is empty. + return true; +} + +/// Verify - Verify that a type descriptor is well formed. +bool DIType::Verify() const { + if (!DbgNode) + return false; + if (!getContext().Verify()) + return false; + unsigned Tag = getTag(); + if (!isBasicType() && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type && + Tag != dwarf::DW_TAG_reference_type && Tag != dwarf::DW_TAG_restrict_type + && Tag != dwarf::DW_TAG_vector_type && Tag != dwarf::DW_TAG_array_type + && Tag != dwarf::DW_TAG_enumeration_type + && getFilename().empty()) + return false; + return true; +} + +/// Verify - Verify that a basic type descriptor is well formed. +bool DIBasicType::Verify() const { + return isBasicType(); +} + +/// Verify - Verify that a derived type descriptor is well formed. +bool DIDerivedType::Verify() const { + return isDerivedType(); +} + +/// Verify - Verify that a composite type descriptor is well formed. +bool DICompositeType::Verify() const { + if (!DbgNode) + return false; + if (!getContext().Verify()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.Verify()) + return false; + return true; +} + +/// Verify - Verify that a subprogram descriptor is well formed. +bool DISubprogram::Verify() const { + if (!DbgNode) + return false; + + if (!getContext().Verify()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.Verify()) + return false; + + DICompositeType Ty = getType(); + if (!Ty.Verify()) + return false; + return true; +} + +/// Verify - Verify that a global variable descriptor is well formed. +bool DIGlobalVariable::Verify() const { + if (!DbgNode) + return false; + + if (getDisplayName().empty()) + return false; + + if (!getContext().Verify()) + return false; + + DICompileUnit CU = getCompileUnit(); + if (!CU.Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + if (!getGlobal() && !getConstant()) + return false; + + return true; +} + +/// Verify - Verify that a variable descriptor is well formed. +bool DIVariable::Verify() const { + if (!DbgNode) + return false; + + if (!getContext().Verify()) + return false; + + if (!getCompileUnit().Verify()) + return false; + + DIType Ty = getType(); + if (!Ty.Verify()) + return false; + + return true; +} + +/// Verify - Verify that a location descriptor is well formed. +bool DILocation::Verify() const { + if (!DbgNode) + return false; + + return DbgNode->getNumOperands() == 4; +} + +/// Verify - Verify that a namespace descriptor is well formed. +bool DINameSpace::Verify() const { + if (!DbgNode) + return false; + if (getName().empty()) + return false; + if (!getCompileUnit().Verify()) + return false; + return true; +} + +/// getOriginalTypeSize - If this type is derived from a base type then +/// return base type size. +uint64_t DIDerivedType::getOriginalTypeSize() const { + unsigned Tag = getTag(); + if (Tag == dwarf::DW_TAG_member || Tag == dwarf::DW_TAG_typedef || + Tag == dwarf::DW_TAG_const_type || Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_restrict_type) { + DIType BaseType = getTypeDerivedFrom(); + // If this type is not derived from any type then take conservative + // approach. + if (!BaseType.isValid()) + return getSizeInBits(); + if (BaseType.isDerivedType()) + return DIDerivedType(BaseType).getOriginalTypeSize(); + else + return BaseType.getSizeInBits(); + } + + return getSizeInBits(); +} + +/// isInlinedFnArgument - Return true if this variable provides debugging +/// information for an inlined function arguments. +bool DIVariable::isInlinedFnArgument(const Function *CurFn) { + assert(CurFn && "Invalid function"); + if (!getContext().isSubprogram()) + return false; + // This variable is not inlined function argument if its scope + // does not describe current function. + return !(DISubprogram(getContext()).describes(CurFn)); +} + +/// describes - Return true if this subprogram provides debugging +/// information for the function F. +bool DISubprogram::describes(const Function *F) { + assert(F && "Invalid function"); + if (F == getFunction()) + return true; + StringRef Name = getLinkageName(); + if (Name.empty()) + Name = getName(); + if (F->getName() == Name) + return true; + return false; +} + +unsigned DISubprogram::isOptimized() const { + assert (DbgNode && "Invalid subprogram descriptor!"); + if (DbgNode->getNumOperands() == 16) + return getUnsignedField(15); + return 0; +} + +StringRef DIScope::getFilename() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getFilename(); + if (isSubprogram()) + return DISubprogram(DbgNode).getFilename(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getFilename(); + if (isNameSpace()) + return DINameSpace(DbgNode).getFilename(); + if (isType()) + return DIType(DbgNode).getFilename(); + if (isFile()) + return DIFile(DbgNode).getFilename(); + assert(0 && "Invalid DIScope!"); + return StringRef(); +} + +StringRef DIScope::getDirectory() const { + if (!DbgNode) + return StringRef(); + if (isLexicalBlock()) + return DILexicalBlock(DbgNode).getDirectory(); + if (isSubprogram()) + return DISubprogram(DbgNode).getDirectory(); + if (isCompileUnit()) + return DICompileUnit(DbgNode).getDirectory(); + if (isNameSpace()) + return DINameSpace(DbgNode).getDirectory(); + if (isType()) + return DIType(DbgNode).getDirectory(); + if (isFile()) + return DIFile(DbgNode).getDirectory(); + assert(0 && "Invalid DIScope!"); + return StringRef(); +} + +//===----------------------------------------------------------------------===// +// DIDescriptor: dump routines for all descriptors. +//===----------------------------------------------------------------------===// + + +/// print - Print descriptor. +void DIDescriptor::print(raw_ostream &OS) const { + OS << "[" << dwarf::TagString(getTag()) << "] "; + OS.write_hex((intptr_t) &*DbgNode) << ']'; +} + +/// print - Print compile unit. +void DICompileUnit::print(raw_ostream &OS) const { + if (getLanguage()) + OS << " [" << dwarf::LanguageString(getLanguage()) << "] "; + + OS << " [" << getDirectory() << "/" << getFilename() << "]"; +} + +/// print - Print type. +void DIType::print(raw_ostream &OS) const { + if (!DbgNode) return; + + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "] "; + + unsigned Tag = getTag(); + OS << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().print(OS); + OS << " [" + << "line " << getLineNumber() << ", " + << getSizeInBits() << " bits, " + << getAlignInBits() << " bit alignment, " + << getOffsetInBits() << " bit offset" + << "] "; + + if (isPrivate()) + OS << " [private] "; + else if (isProtected()) + OS << " [protected] "; + + if (isForwardDecl()) + OS << " [fwd] "; + + if (isBasicType()) + DIBasicType(DbgNode).print(OS); + else if (isDerivedType()) + DIDerivedType(DbgNode).print(OS); + else if (isCompositeType()) + DICompositeType(DbgNode).print(OS); + else { + OS << "Invalid DIType\n"; + return; + } + + OS << "\n"; +} + +/// print - Print basic type. +void DIBasicType::print(raw_ostream &OS) const { + OS << " [" << dwarf::AttributeEncodingString(getEncoding()) << "] "; +} + +/// print - Print derived type. +void DIDerivedType::print(raw_ostream &OS) const { + OS << "\n\t Derived From: "; getTypeDerivedFrom().print(OS); +} + +/// print - Print composite type. +void DICompositeType::print(raw_ostream &OS) const { + DIArray A = getTypeArray(); + OS << " [" << A.getNumElements() << " elements]"; +} + +/// print - Print subprogram. +void DISubprogram::print(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "] "; + + unsigned Tag = getTag(); + OS << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().print(OS); + OS << " [" << getLineNumber() << "] "; + + if (isLocalToUnit()) + OS << " [local] "; + + if (isDefinition()) + OS << " [def] "; + + OS << "\n"; +} + +/// print - Print global variable. +void DIGlobalVariable::print(raw_ostream &OS) const { + OS << " ["; + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "] "; + + unsigned Tag = getTag(); + OS << " [" << dwarf::TagString(Tag) << "] "; + + // TODO : Print context + getCompileUnit().print(OS); + OS << " [" << getLineNumber() << "] "; + + if (isLocalToUnit()) + OS << " [local] "; + + if (isDefinition()) + OS << " [def] "; + + if (isGlobalVariable()) + DIGlobalVariable(DbgNode).print(OS); + OS << "]\n"; +} + +/// print - Print variable. +void DIVariable::print(raw_ostream &OS) const { + StringRef Res = getName(); + if (!Res.empty()) + OS << " [" << Res << "] "; + + getCompileUnit().print(OS); + OS << " [" << getLineNumber() << "] "; + getType().print(OS); + OS << "\n"; + + // FIXME: Dump complex addresses +} + +/// dump - Print descriptor to dbgs() with a newline. +void DIDescriptor::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print compile unit to dbgs() with a newline. +void DICompileUnit::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print type to dbgs() with a newline. +void DIType::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print basic type to dbgs() with a newline. +void DIBasicType::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print derived type to dbgs() with a newline. +void DIDerivedType::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print composite type to dbgs() with a newline. +void DICompositeType::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print subprogram to dbgs() with a newline. +void DISubprogram::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print global variable. +void DIGlobalVariable::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// dump - Print variable. +void DIVariable::dump() const { + print(dbgs()); dbgs() << '\n'; +} + +/// fixupObjcLikeName - Replace contains special characters used +/// in a typical Objective-C names with '.' in a given string. +static void fixupObjcLikeName(std::string &Str) { + for (size_t i = 0, e = Str.size(); i < e; ++i) { + char C = Str[i]; + if (C == '[' || C == ']' || C == ' ' || C == ':' || C == '+' || + C == '(' || C == ')') + Str[i] = '.'; + } +} + +/// getFnSpecificMDNode - Return a NameMDNode, if available, that is +/// suitable to hold function specific information. +NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, StringRef FuncName) { + if (FuncName.find('[') == StringRef::npos) + return M.getNamedMetadata(Twine("llvm.dbg.lv.", FuncName)); + std::string Name = FuncName; + fixupObjcLikeName(Name); + return M.getNamedMetadata(Twine("llvm.dbg.lv.", Name)); +} + +/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable +/// to hold function specific information. +NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, StringRef FuncName) { + SmallString<32> Out; + if (FuncName.find('[') == StringRef::npos) + return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", FuncName) + .toStringRef(Out)); + + std::string Name = FuncName; + fixupObjcLikeName(Name); + return M.getOrInsertNamedMetadata(Twine("llvm.dbg.lv.", Name) + .toStringRef(Out)); +} + + +//===----------------------------------------------------------------------===// +// DebugInfoFinder implementations. +//===----------------------------------------------------------------------===// + +/// processModule - Process entire module and collect debug info. +void DebugInfoFinder::processModule(Module &M) { + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) + for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; + ++BI) { + if (DbgDeclareInst *DDI = dyn_cast(BI)) + processDeclare(DDI); + + DebugLoc Loc = BI->getDebugLoc(); + if (Loc.isUnknown()) + continue; + + LLVMContext &Ctx = BI->getContext(); + DIDescriptor Scope(Loc.getScope(Ctx)); + + if (Scope.isCompileUnit()) + addCompileUnit(DICompileUnit(Scope)); + else if (Scope.isSubprogram()) + processSubprogram(DISubprogram(Scope)); + else if (Scope.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(Scope)); + + if (MDNode *IA = Loc.getInlinedAt(Ctx)) + processLocation(DILocation(IA)); + } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv")) { + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIGlobalVariable DIG(cast(NMD->getOperand(i))); + if (addGlobalVariable(DIG)) { + addCompileUnit(DIG.getCompileUnit()); + processType(DIG.getType()); + } + } + } + + if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + processSubprogram(DISubprogram(NMD->getOperand(i))); +} + +/// processLocation - Process DILocation. +void DebugInfoFinder::processLocation(DILocation Loc) { + if (!Loc.Verify()) return; + DIDescriptor S(Loc.getScope()); + if (S.isCompileUnit()) + addCompileUnit(DICompileUnit(S)); + else if (S.isSubprogram()) + processSubprogram(DISubprogram(S)); + else if (S.isLexicalBlock()) + processLexicalBlock(DILexicalBlock(S)); + processLocation(Loc.getOrigLocation()); +} + +/// processType - Process DIType. +void DebugInfoFinder::processType(DIType DT) { + if (!addType(DT)) + return; + + addCompileUnit(DT.getCompileUnit()); + if (DT.isCompositeType()) { + DICompositeType DCT(DT); + processType(DCT.getTypeDerivedFrom()); + DIArray DA = DCT.getTypeArray(); + for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { + DIDescriptor D = DA.getElement(i); + if (D.isType()) + processType(DIType(D)); + else if (D.isSubprogram()) + processSubprogram(DISubprogram(D)); + } + } else if (DT.isDerivedType()) { + DIDerivedType DDT(DT); + processType(DDT.getTypeDerivedFrom()); + } +} + +/// processLexicalBlock +void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { + DIScope Context = LB.getContext(); + if (Context.isLexicalBlock()) + return processLexicalBlock(DILexicalBlock(Context)); + else + return processSubprogram(DISubprogram(Context)); +} + +/// processSubprogram - Process DISubprogram. +void DebugInfoFinder::processSubprogram(DISubprogram SP) { + if (!addSubprogram(SP)) + return; + addCompileUnit(SP.getCompileUnit()); + processType(SP.getType()); +} + +/// processDeclare - Process DbgDeclareInst. +void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) { + MDNode *N = dyn_cast(DDI->getVariable()); + if (!N) return; + + DIDescriptor DV(N); + if (!DV.isVariable()) + return; + + if (!NodesSeen.insert(DV)) + return; + + addCompileUnit(DIVariable(N).getCompileUnit()); + processType(DIVariable(N).getType()); +} + +/// addType - Add type into Tys. +bool DebugInfoFinder::addType(DIType DT) { + if (!DT.isValid()) + return false; + + if (!NodesSeen.insert(DT)) + return false; + + TYs.push_back(DT); + return true; +} + +/// addCompileUnit - Add compile unit into CUs. +bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { + if (!CU.Verify()) + return false; + + if (!NodesSeen.insert(CU)) + return false; + + CUs.push_back(CU); + return true; +} + +/// addGlobalVariable - Add global variable into GVs. +bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { + if (!DIDescriptor(DIG).isGlobalVariable()) + return false; + + if (!NodesSeen.insert(DIG)) + return false; + + GVs.push_back(DIG); + return true; +} + +// addSubprogram - Add subprgoram into SPs. +bool DebugInfoFinder::addSubprogram(DISubprogram SP) { + if (!DIDescriptor(SP).isSubprogram()) + return false; + + if (!NodesSeen.insert(SP)) + return false; + + SPs.push_back(SP); + return true; +} + +/// getDISubprogram - Find subprogram that is enclosing this scope. +DISubprogram llvm::getDISubprogram(const MDNode *Scope) { + DIDescriptor D(Scope); + if (D.isSubprogram()) + return DISubprogram(Scope); + + if (D.isLexicalBlock()) + return getDISubprogram(DILexicalBlock(Scope).getContext()); + + return DISubprogram(); +} + +/// getDICompositeType - Find underlying composite type. +DICompositeType llvm::getDICompositeType(DIType T) { + if (T.isCompositeType()) + return DICompositeType(T); + + if (T.isDerivedType()) + return getDICompositeType(DIDerivedType(T).getTypeDerivedFrom()); + + return DICompositeType(); +} diff --git a/final/lib/Analysis/DomPrinter.cpp b/final/lib/Analysis/DomPrinter.cpp new file mode 100644 index 00000000000..cde431459d5 --- /dev/null +++ b/final/lib/Analysis/DomPrinter.cpp @@ -0,0 +1,232 @@ +//===- DomPrinter.cpp - DOT printer for the dominance trees ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines '-dot-dom' and '-dot-postdom' analysis passes, which emit +// a dom..dot or postdom..dot file for each function in the +// program, with a graph of the dominance/postdominance tree of that +// function. +// +// There are also passes available to directly call dotty ('-view-dom' or +// '-view-postdom'). By appending '-only' like '-dot-dom-only' only the +// names of the bbs are printed, but the content is hidden. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DomPrinter.h" +#include "llvm/Analysis/DOTGraphTraitsPass.h" +#include "llvm/Analysis/PostDominators.h" + +using namespace llvm; + +namespace llvm { +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) + : DefaultDOTGraphTraits(isSimple) {} + + std::string getNodeLabel(DomTreeNode *Node, DomTreeNode *Graph) { + + BasicBlock *BB = Node->getBlock(); + + if (!BB) + return "Post dominance root node"; + + + if (isSimple()) + return DOTGraphTraits + ::getSimpleNodeLabel(BB, BB->getParent()); + else + return DOTGraphTraits + ::getCompleteNodeLabel(BB, BB->getParent()); + } +}; + +template<> +struct DOTGraphTraits : public DOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) + : DOTGraphTraits(isSimple) {} + + static std::string getGraphName(DominatorTree *DT) { + return "Dominator tree"; + } + + std::string getNodeLabel(DomTreeNode *Node, DominatorTree *G) { + return DOTGraphTraits::getNodeLabel(Node, G->getRootNode()); + } +}; + +template<> +struct DOTGraphTraits + : public DOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) + : DOTGraphTraits(isSimple) {} + + static std::string getGraphName(PostDominatorTree *DT) { + return "Post dominator tree"; + } + + std::string getNodeLabel(DomTreeNode *Node, PostDominatorTree *G ) { + return DOTGraphTraits::getNodeLabel(Node, G->getRootNode()); + } +}; +} + +namespace { +struct DomViewer + : public DOTGraphTraitsViewer { + static char ID; + DomViewer() : DOTGraphTraitsViewer("dom", ID){ + initializeDomViewerPass(*PassRegistry::getPassRegistry()); + } +}; + +struct DomOnlyViewer + : public DOTGraphTraitsViewer { + static char ID; + DomOnlyViewer() : DOTGraphTraitsViewer("domonly", ID){ + initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry()); + } +}; + +struct PostDomViewer + : public DOTGraphTraitsViewer { + static char ID; + PostDomViewer() : + DOTGraphTraitsViewer("postdom", ID){ + initializePostDomViewerPass(*PassRegistry::getPassRegistry()); + } +}; + +struct PostDomOnlyViewer + : public DOTGraphTraitsViewer { + static char ID; + PostDomOnlyViewer() : + DOTGraphTraitsViewer("postdomonly", ID){ + initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry()); + } +}; +} // end anonymous namespace + +char DomViewer::ID = 0; +INITIALIZE_PASS(DomViewer, "view-dom", + "View dominance tree of function", false, false) + +char DomOnlyViewer::ID = 0; +INITIALIZE_PASS(DomOnlyViewer, "view-dom-only", + "View dominance tree of function (with no function bodies)", + false, false) + +char PostDomViewer::ID = 0; +INITIALIZE_PASS(PostDomViewer, "view-postdom", + "View postdominance tree of function", false, false) + +char PostDomOnlyViewer::ID = 0; +INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only", + "View postdominance tree of function " + "(with no function bodies)", + false, false) + +namespace { +struct DomPrinter + : public DOTGraphTraitsPrinter { + static char ID; + DomPrinter() : DOTGraphTraitsPrinter("dom", ID) { + initializeDomPrinterPass(*PassRegistry::getPassRegistry()); + } +}; + +struct DomOnlyPrinter + : public DOTGraphTraitsPrinter { + static char ID; + DomOnlyPrinter() : DOTGraphTraitsPrinter("domonly", ID) { + initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); + } +}; + +struct PostDomPrinter + : public DOTGraphTraitsPrinter { + static char ID; + PostDomPrinter() : + DOTGraphTraitsPrinter("postdom", ID) { + initializePostDomPrinterPass(*PassRegistry::getPassRegistry()); + } +}; + +struct PostDomOnlyPrinter + : public DOTGraphTraitsPrinter { + static char ID; + PostDomOnlyPrinter() : + DOTGraphTraitsPrinter("postdomonly", ID) { + initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry()); + } +}; +} // end anonymous namespace + + + +char DomPrinter::ID = 0; +INITIALIZE_PASS(DomPrinter, "dot-dom", + "Print dominance tree of function to 'dot' file", + false, false) + +char DomOnlyPrinter::ID = 0; +INITIALIZE_PASS(DomOnlyPrinter, "dot-dom-only", + "Print dominance tree of function to 'dot' file " + "(with no function bodies)", + false, false) + +char PostDomPrinter::ID = 0; +INITIALIZE_PASS(PostDomPrinter, "dot-postdom", + "Print postdominance tree of function to 'dot' file", + false, false) + +char PostDomOnlyPrinter::ID = 0; +INITIALIZE_PASS(PostDomOnlyPrinter, "dot-postdom-only", + "Print postdominance tree of function to 'dot' file " + "(with no function bodies)", + false, false) + +// Create methods available outside of this file, to use them +// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by +// the link time optimization. + +FunctionPass *llvm::createDomPrinterPass() { + return new DomPrinter(); +} + +FunctionPass *llvm::createDomOnlyPrinterPass() { + return new DomOnlyPrinter(); +} + +FunctionPass *llvm::createDomViewerPass() { + return new DomViewer(); +} + +FunctionPass *llvm::createDomOnlyViewerPass() { + return new DomOnlyViewer(); +} + +FunctionPass *llvm::createPostDomPrinterPass() { + return new PostDomPrinter(); +} + +FunctionPass *llvm::createPostDomOnlyPrinterPass() { + return new PostDomOnlyPrinter(); +} + +FunctionPass *llvm::createPostDomViewerPass() { + return new PostDomViewer(); +} + +FunctionPass *llvm::createPostDomOnlyViewerPass() { + return new PostDomOnlyViewer(); +} diff --git a/final/lib/Analysis/DominanceFrontier.cpp b/final/lib/Analysis/DominanceFrontier.cpp new file mode 100644 index 00000000000..6de4e1e1d7d --- /dev/null +++ b/final/lib/Analysis/DominanceFrontier.cpp @@ -0,0 +1,137 @@ +//===- DominanceFrontier.cpp - Dominance Frontier Calculation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +char DominanceFrontier::ID = 0; +INITIALIZE_PASS_BEGIN(DominanceFrontier, "domfrontier", + "Dominance Frontier Construction", true, true) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_END(DominanceFrontier, "domfrontier", + "Dominance Frontier Construction", true, true) + +namespace { + class DFCalculateWorkObject { + public: + DFCalculateWorkObject(BasicBlock *B, BasicBlock *P, + const DomTreeNode *N, + const DomTreeNode *PN) + : currentBB(B), parentBB(P), Node(N), parentNode(PN) {} + BasicBlock *currentBB; + BasicBlock *parentBB; + const DomTreeNode *Node; + const DomTreeNode *parentNode; + }; +} + +const DominanceFrontier::DomSetType & +DominanceFrontier::calculate(const DominatorTree &DT, + const DomTreeNode *Node) { + BasicBlock *BB = Node->getBlock(); + DomSetType *Result = NULL; + + std::vector workList; + SmallPtrSet visited; + + workList.push_back(DFCalculateWorkObject(BB, NULL, Node, NULL)); + do { + DFCalculateWorkObject *currentW = &workList.back(); + assert (currentW && "Missing work object."); + + BasicBlock *currentBB = currentW->currentBB; + BasicBlock *parentBB = currentW->parentBB; + const DomTreeNode *currentNode = currentW->Node; + const DomTreeNode *parentNode = currentW->parentNode; + assert (currentBB && "Invalid work object. Missing current Basic Block"); + assert (currentNode && "Invalid work object. Missing current Node"); + DomSetType &S = Frontiers[currentBB]; + + // Visit each block only once. + if (visited.count(currentBB) == 0) { + visited.insert(currentBB); + + // Loop over CFG successors to calculate DFlocal[currentNode] + for (succ_iterator SI = succ_begin(currentBB), SE = succ_end(currentBB); + SI != SE; ++SI) { + // Does Node immediately dominate this successor? + if (DT[*SI]->getIDom() != currentNode) + S.insert(*SI); + } + } + + // At this point, S is DFlocal. Now we union in DFup's of our children... + // Loop through and visit the nodes that Node immediately dominates (Node's + // children in the IDomTree) + bool visitChild = false; + for (DomTreeNode::const_iterator NI = currentNode->begin(), + NE = currentNode->end(); NI != NE; ++NI) { + DomTreeNode *IDominee = *NI; + BasicBlock *childBB = IDominee->getBlock(); + if (visited.count(childBB) == 0) { + workList.push_back(DFCalculateWorkObject(childBB, currentBB, + IDominee, currentNode)); + visitChild = true; + } + } + + // If all children are visited or there is any child then pop this block + // from the workList. + if (!visitChild) { + + if (!parentBB) { + Result = &S; + break; + } + + DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end(); + DomSetType &parentSet = Frontiers[parentBB]; + for (; CDFI != CDFE; ++CDFI) { + if (!DT.properlyDominates(parentNode, DT[*CDFI])) + parentSet.insert(*CDFI); + } + workList.pop_back(); + } + + } while (!workList.empty()); + + return *Result; +} + +void DominanceFrontierBase::print(raw_ostream &OS, const Module* ) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) { + OS << " DomFrontier for BB "; + if (I->first) + WriteAsOperand(OS, I->first, false); + else + OS << " <>"; + OS << " is:\t"; + + const std::set &BBs = I->second; + + for (std::set::const_iterator I = BBs.begin(), E = BBs.end(); + I != E; ++I) { + OS << ' '; + if (*I) + WriteAsOperand(OS, *I, false); + else + OS << "<>"; + } + OS << "\n"; + } +} + +void DominanceFrontierBase::dump() const { + print(dbgs()); +} + diff --git a/final/lib/Analysis/IPA/CMakeLists.txt b/final/lib/Analysis/IPA/CMakeLists.txt new file mode 100644 index 00000000000..8ffef29870a --- /dev/null +++ b/final/lib/Analysis/IPA/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMipa + CallGraph.cpp + CallGraphSCCPass.cpp + FindUsedTypes.cpp + GlobalsModRef.cpp + IPA.cpp + ) diff --git a/final/lib/Analysis/IPA/CallGraph.cpp b/final/lib/Analysis/IPA/CallGraph.cpp new file mode 100644 index 00000000000..690c4b4b6f1 --- /dev/null +++ b/final/lib/Analysis/IPA/CallGraph.cpp @@ -0,0 +1,340 @@ +//===- CallGraph.cpp - Build a Module's call graph ------------------------===// +// +// 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 CallGraph class and provides the BasicCallGraph +// default implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +//===----------------------------------------------------------------------===// +// BasicCallGraph class definition +// +class BasicCallGraph : public ModulePass, public CallGraph { + // Root is root of the call graph, or the external node if a 'main' function + // couldn't be found. + // + CallGraphNode *Root; + + // ExternalCallingNode - This node has edges to all external functions and + // those internal functions that have their address taken. + CallGraphNode *ExternalCallingNode; + + // CallsExternalNode - This node has edges to it from all functions making + // indirect calls or calling an external function. + CallGraphNode *CallsExternalNode; + +public: + static char ID; // Class identification, replacement for typeinfo + BasicCallGraph() : ModulePass(ID), Root(0), + ExternalCallingNode(0), CallsExternalNode(0) { + initializeBasicCallGraphPass(*PassRegistry::getPassRegistry()); + } + + // runOnModule - Compute the call graph for the specified module. + virtual bool runOnModule(Module &M) { + CallGraph::initialize(M); + + ExternalCallingNode = getOrInsertFunction(0); + CallsExternalNode = new CallGraphNode(0); + Root = 0; + + // Add every function to the call graph. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + addToCallGraph(I); + + // If we didn't find a main function, use the external call graph node + if (Root == 0) Root = ExternalCallingNode; + + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual void print(raw_ostream &OS, const Module *) const { + OS << "CallGraph Root is: "; + if (Function *F = getRoot()->getFunction()) + OS << F->getName() << "\n"; + else { + OS << "<>\n"; + } + + CallGraph::print(OS, 0); + } + + virtual void releaseMemory() { + destroy(); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it should + /// override this to adjust the this pointer as needed for the specified pass + /// info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &CallGraph::ID) + return (CallGraph*)this; + return this; + } + + CallGraphNode* getExternalCallingNode() const { return ExternalCallingNode; } + CallGraphNode* getCallsExternalNode() const { return CallsExternalNode; } + + // getRoot - Return the root of the call graph, which is either main, or if + // main cannot be found, the external node. + // + CallGraphNode *getRoot() { return Root; } + const CallGraphNode *getRoot() const { return Root; } + +private: + //===--------------------------------------------------------------------- + // Implementation of CallGraph construction + // + + // addToCallGraph - Add a function to the call graph, and link the node to all + // of the functions that it calls. + // + void addToCallGraph(Function *F) { + CallGraphNode *Node = getOrInsertFunction(F); + + // If this function has external linkage, anything could call it. + if (!F->hasLocalLinkage()) { + ExternalCallingNode->addCalledFunction(CallSite(), Node); + + // Found the entry point? + if (F->getName() == "main") { + if (Root) // Found multiple external mains? Don't pick one. + Root = ExternalCallingNode; + else + Root = Node; // Found a main, keep track of it! + } + } + + // Loop over all of the users of the function, looking for non-call uses. + for (Value::use_iterator I = F->use_begin(), E = F->use_end(); I != E; ++I){ + User *U = *I; + if ((!isa(U) && !isa(U)) + || !CallSite(cast(U)).isCallee(I)) { + // Not a call, or being used as a parameter rather than as the callee. + ExternalCallingNode->addCalledFunction(CallSite(), Node); + break; + } + } + + // If this function is not defined in this translation unit, it could call + // anything. + if (F->isDeclaration() && !F->isIntrinsic()) + Node->addCalledFunction(CallSite(), CallsExternalNode); + + // Look for calls by this function. + for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB) + for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); + II != IE; ++II) { + CallSite CS(cast(II)); + if (CS && !isa(II)) { + const Function *Callee = CS.getCalledFunction(); + if (Callee) + Node->addCalledFunction(CS, getOrInsertFunction(Callee)); + else + Node->addCalledFunction(CS, CallsExternalNode); + } + } + } + + // + // destroy - Release memory for the call graph + virtual void destroy() { + /// CallsExternalNode is not in the function map, delete it explicitly. + if (CallsExternalNode) { + CallsExternalNode->allReferencesDropped(); + delete CallsExternalNode; + CallsExternalNode = 0; + } + CallGraph::destroy(); + } +}; + +} //End anonymous namespace + +INITIALIZE_ANALYSIS_GROUP(CallGraph, "Call Graph", BasicCallGraph) +INITIALIZE_AG_PASS(BasicCallGraph, CallGraph, "basiccg", + "Basic CallGraph Construction", false, true, true) + +char CallGraph::ID = 0; +char BasicCallGraph::ID = 0; + +void CallGraph::initialize(Module &M) { + Mod = &M; +} + +void CallGraph::destroy() { + if (FunctionMap.empty()) return; + + // Reset all node's use counts to zero before deleting them to prevent an + // assertion from firing. +#ifndef NDEBUG + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + I->second->allReferencesDropped(); +#endif + + for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); + I != E; ++I) + delete I->second; + FunctionMap.clear(); +} + +void CallGraph::print(raw_ostream &OS, Module*) const { + for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I) + I->second->print(OS); +} +void CallGraph::dump() const { + print(dbgs(), 0); +} + +//===----------------------------------------------------------------------===// +// Implementations of public modification methods +// + +// removeFunctionFromModule - Unlink the function from this module, returning +// it. Because this removes the function from the module, the call graph node +// is destroyed. This is only valid if the function does not call any other +// functions (ie, there are no edges in it's CGN). The easiest way to do this +// is to dropAllReferences before calling this. +// +Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) { + assert(CGN->empty() && "Cannot remove function from call " + "graph if it references other functions!"); + Function *F = CGN->getFunction(); // Get the function for the call graph node + delete CGN; // Delete the call graph node for this func + FunctionMap.erase(F); // Remove the call graph node from the map + + Mod->getFunctionList().remove(F); + return F; +} + +/// spliceFunction - Replace the function represented by this node by another. +/// This does not rescan the body of the function, so it is suitable when +/// splicing the body of the old function to the new while also updating all +/// callers from old to new. +/// +void CallGraph::spliceFunction(const Function *From, const Function *To) { + assert(FunctionMap.count(From) && "No CallGraphNode for function!"); + assert(!FunctionMap.count(To) && + "Pointing CallGraphNode at a function that already exists"); + FunctionMapTy::iterator I = FunctionMap.find(From); + I->second->F = const_cast(To); + FunctionMap[To] = I->second; + FunctionMap.erase(I); +} + +// getOrInsertFunction - This method is identical to calling operator[], but +// it will insert a new CallGraphNode for the specified function if one does +// not already exist. +CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) { + CallGraphNode *&CGN = FunctionMap[F]; + if (CGN) return CGN; + + assert((!F || F->getParent() == Mod) && "Function not in current module!"); + return CGN = new CallGraphNode(const_cast(F)); +} + +void CallGraphNode::print(raw_ostream &OS) const { + if (Function *F = getFunction()) + OS << "Call graph node for function: '" << F->getName() << "'"; + else + OS << "Call graph node <>"; + + OS << "<<" << this << ">> #uses=" << getNumReferences() << '\n'; + + for (const_iterator I = begin(), E = end(); I != E; ++I) { + OS << " CS<" << I->first << "> calls "; + if (Function *FI = I->second->getFunction()) + OS << "function '" << FI->getName() <<"'\n"; + else + OS << "external node\n"; + } + OS << '\n'; +} + +void CallGraphNode::dump() const { print(dbgs()); } + +/// removeCallEdgeFor - This method removes the edge in the node for the +/// specified call site. Note that this method takes linear time, so it +/// should be used sparingly. +void CallGraphNode::removeCallEdgeFor(CallSite CS) { + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callsite to remove!"); + if (I->first == CS.getInstruction()) { + I->second->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + return; + } + } +} + +// removeAnyCallEdgeTo - This method removes any call edges from this node to +// the specified callee function. This takes more time to execute than +// removeCallEdgeTo, so it should not be used unless necessary. +void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) { + for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i) + if (CalledFunctions[i].second == Callee) { + Callee->DropRef(); + CalledFunctions[i] = CalledFunctions.back(); + CalledFunctions.pop_back(); + --i; --e; + } +} + +/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite +/// from this node to the specified callee function. +void CallGraphNode::removeOneAbstractEdgeTo(CallGraphNode *Callee) { + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callee to remove!"); + CallRecord &CR = *I; + if (CR.second == Callee && CR.first == 0) { + Callee->DropRef(); + *I = CalledFunctions.back(); + CalledFunctions.pop_back(); + return; + } + } +} + +/// replaceCallEdge - This method replaces the edge in the node for the +/// specified call site with a new one. Note that this method takes linear +/// time, so it should be used sparingly. +void CallGraphNode::replaceCallEdge(CallSite CS, + CallSite NewCS, CallGraphNode *NewNode){ + for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) { + assert(I != CalledFunctions.end() && "Cannot find callsite to remove!"); + if (I->first == CS.getInstruction()) { + I->second->DropRef(); + I->first = NewCS.getInstruction(); + I->second = NewNode; + NewNode->AddRef(); + return; + } + } +} + +// Enuse that users of CallGraph.h also link with this file +DEFINING_FILE_FOR(CallGraph) diff --git a/final/lib/Analysis/IPA/CallGraphSCCPass.cpp b/final/lib/Analysis/IPA/CallGraphSCCPass.cpp new file mode 100644 index 00000000000..725ab72f559 --- /dev/null +++ b/final/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -0,0 +1,608 @@ +//===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===// +// +// 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 CallGraphSCCPass class, which is used for passes +// which are implemented as bottom-up traversals on the call graph. Because +// there may be cycles in the call graph, passes of this type operate on the +// call-graph in SCC order: that is, they process function bottom-up, except for +// recursive functions, which they process all at once. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "cgscc-passmgr" +#include "llvm/CallGraphSCCPass.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Function.h" +#include "llvm/PassManagers.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/ADT/SCCIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +MaxIterations("max-cg-scc-iterations", cl::ReallyHidden, cl::init(4)); + +STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC"); + +//===----------------------------------------------------------------------===// +// CGPassManager +// +/// CGPassManager manages FPPassManagers and CallGraphSCCPasses. + +namespace { + +class CGPassManager : public ModulePass, public PMDataManager { +public: + static char ID; + explicit CGPassManager(int Depth) + : ModulePass(ID), PMDataManager(Depth) { } + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnModule(Module &M); + + bool doInitialization(CallGraph &CG); + bool doFinalization(CallGraph &CG); + + /// Pass Manager itself does not invalidate any analysis info. + void getAnalysisUsage(AnalysisUsage &Info) const { + // CGPassManager walks SCC and it needs CallGraph. + Info.addRequired(); + Info.setPreservesAll(); + } + + virtual const char *getPassName() const { + return "CallGraph Pass Manager"; + } + + virtual PMDataManager *getAsPMDataManager() { return this; } + virtual Pass *getAsPass() { return this; } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Call Graph SCC Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } + } + + Pass *getContainedPass(unsigned N) { + assert(N < PassVector.size() && "Pass number out of range!"); + return static_cast(PassVector[N]); + } + + virtual PassManagerType getPassManagerType() const { + return PMT_CallGraphPassManager; + } + +private: + bool RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG, + bool &DevirtualizedCall); + + bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, + CallGraph &CG, bool &CallGraphUpToDate, + bool &DevirtualizedCall); + bool RefreshCallGraph(CallGraphSCC &CurSCC, CallGraph &CG, + bool IsCheckingMode); +}; + +} // end anonymous namespace. + +char CGPassManager::ID = 0; + + +bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC, + CallGraph &CG, bool &CallGraphUpToDate, + bool &DevirtualizedCall) { + bool Changed = false; + PMDataManager *PM = P->getAsPMDataManager(); + + if (PM == 0) { + CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P; + if (!CallGraphUpToDate) { + DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false); + CallGraphUpToDate = true; + } + + { + TimeRegion PassTimer(getPassTimer(CGSP)); + Changed = CGSP->runOnSCC(CurSCC); + } + + // After the CGSCCPass is done, when assertions are enabled, use + // RefreshCallGraph to verify that the callgraph was correctly updated. +#ifndef NDEBUG + if (Changed) + RefreshCallGraph(CurSCC, CG, true); +#endif + + return Changed; + } + + + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + FPPassManager *FPP = (FPPassManager*)P; + + // Run pass P on all functions in the current SCC. + for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end(); + I != E; ++I) { + if (Function *F = (*I)->getFunction()) { + dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); + TimeRegion PassTimer(getPassTimer(FPP)); + Changed |= FPP->runOnFunction(*F); + } + } + + // The function pass(es) modified the IR, they may have clobbered the + // callgraph. + if (Changed && CallGraphUpToDate) { + DEBUG(dbgs() << "CGSCCPASSMGR: Pass Dirtied SCC: " + << P->getPassName() << '\n'); + CallGraphUpToDate = false; + } + return Changed; +} + + +/// RefreshCallGraph - Scan the functions in the specified CFG and resync the +/// callgraph with the call sites found in it. This is used after +/// FunctionPasses have potentially munged the callgraph, and can be used after +/// CallGraphSCC passes to verify that they correctly updated the callgraph. +/// +/// This function returns true if it devirtualized an existing function call, +/// meaning it turned an indirect call into a direct call. This happens when +/// a function pass like GVN optimizes away stuff feeding the indirect call. +/// This never happens in checking mode. +/// +bool CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC, + CallGraph &CG, bool CheckingMode) { + DenseMap CallSites; + + DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size() + << " nodes:\n"; + for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end(); + I != E; ++I) + (*I)->dump(); + ); + + bool MadeChange = false; + bool DevirtualizedCall = false; + + // Scan all functions in the SCC. + unsigned FunctionNo = 0; + for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end(); + SCCIdx != E; ++SCCIdx, ++FunctionNo) { + CallGraphNode *CGN = *SCCIdx; + Function *F = CGN->getFunction(); + if (F == 0 || F->isDeclaration()) continue; + + // Walk the function body looking for call sites. Sync up the call sites in + // CGN with those actually in the function. + + // Keep track of the number of direct and indirect calls that were + // invalidated and removed. + unsigned NumDirectRemoved = 0, NumIndirectRemoved = 0; + + // Get the set of call sites currently in the function. + for (CallGraphNode::iterator I = CGN->begin(), E = CGN->end(); I != E; ) { + // If this call site is null, then the function pass deleted the call + // entirely and the WeakVH nulled it out. + if (I->first == 0 || + // If we've already seen this call site, then the FunctionPass RAUW'd + // one call with another, which resulted in two "uses" in the edge + // list of the same call. + CallSites.count(I->first) || + + // If the call edge is not from a call or invoke, then the function + // pass RAUW'd a call with another value. This can happen when + // constant folding happens of well known functions etc. + !CallSite(I->first)) { + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // If this was an indirect call site, count it. + if (I->second->getFunction() == 0) + ++NumIndirectRemoved; + else + ++NumDirectRemoved; + + // Just remove the edge from the set of callees, keep track of whether + // I points to the last element of the vector. + bool WasLast = I + 1 == E; + CGN->removeCallEdge(I); + + // If I pointed to the last element of the vector, we have to bail out: + // iterator checking rejects comparisons of the resultant pointer with + // end. + if (WasLast) + break; + E = CGN->end(); + continue; + } + + assert(!CallSites.count(I->first) && + "Call site occurs in node multiple times"); + CallSites.insert(std::make_pair(I->first, I->second)); + ++I; + } + + // Loop over all of the instructions in the function, getting the callsites. + // Keep track of the number of direct/indirect calls added. + unsigned NumDirectAdded = 0, NumIndirectAdded = 0; + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + CallSite CS(cast(I)); + if (!CS || isa(I)) continue; + + // If this call site already existed in the callgraph, just verify it + // matches up to expectations and remove it from CallSites. + DenseMap::iterator ExistingIt = + CallSites.find(CS.getInstruction()); + if (ExistingIt != CallSites.end()) { + CallGraphNode *ExistingNode = ExistingIt->second; + + // Remove from CallSites since we have now seen it. + CallSites.erase(ExistingIt); + + // Verify that the callee is right. + if (ExistingNode->getFunction() == CS.getCalledFunction()) + continue; + + // If we are in checking mode, we are not allowed to actually mutate + // the callgraph. If this is a case where we can infer that the + // callgraph is less precise than it could be (e.g. an indirect call + // site could be turned direct), don't reject it in checking mode, and + // don't tweak it to be more precise. + if (CheckingMode && CS.getCalledFunction() && + ExistingNode->getFunction() == 0) + continue; + + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // If not, we either went from a direct call to indirect, indirect to + // direct, or direct to different direct. + CallGraphNode *CalleeNode; + if (Function *Callee = CS.getCalledFunction()) { + CalleeNode = CG.getOrInsertFunction(Callee); + // Keep track of whether we turned an indirect call into a direct + // one. + if (ExistingNode->getFunction() == 0) { + DevirtualizedCall = true; + DEBUG(dbgs() << " CGSCCPASSMGR: Devirtualized call to '" + << Callee->getName() << "'\n"); + } + } else { + CalleeNode = CG.getCallsExternalNode(); + } + + // Update the edge target in CGN. + CGN->replaceCallEdge(CS, CS, CalleeNode); + MadeChange = true; + continue; + } + + assert(!CheckingMode && + "CallGraphSCCPass did not update the CallGraph correctly!"); + + // If the call site didn't exist in the CGN yet, add it. + CallGraphNode *CalleeNode; + if (Function *Callee = CS.getCalledFunction()) { + CalleeNode = CG.getOrInsertFunction(Callee); + ++NumDirectAdded; + } else { + CalleeNode = CG.getCallsExternalNode(); + ++NumIndirectAdded; + } + + CGN->addCalledFunction(CS, CalleeNode); + MadeChange = true; + } + + // We scanned the old callgraph node, removing invalidated call sites and + // then added back newly found call sites. One thing that can happen is + // that an old indirect call site was deleted and replaced with a new direct + // call. In this case, we have devirtualized a call, and CGSCCPM would like + // to iteratively optimize the new code. Unfortunately, we don't really + // have a great way to detect when this happens. As an approximation, we + // just look at whether the number of indirect calls is reduced and the + // number of direct calls is increased. There are tons of ways to fool this + // (e.g. DCE'ing an indirect call and duplicating an unrelated block with a + // direct call) but this is close enough. + if (NumIndirectRemoved > NumIndirectAdded && + NumDirectRemoved < NumDirectAdded) + DevirtualizedCall = true; + + // After scanning this function, if we still have entries in callsites, then + // they are dangling pointers. WeakVH should save us for this, so abort if + // this happens. + assert(CallSites.empty() && "Dangling pointers found in call sites map"); + + // Periodically do an explicit clear to remove tombstones when processing + // large scc's. + if ((FunctionNo & 15) == 15) + CallSites.clear(); + } + + DEBUG(if (MadeChange) { + dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n"; + for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end(); + I != E; ++I) + (*I)->dump(); + if (DevirtualizedCall) + dbgs() << "CGSCCPASSMGR: Refresh devirtualized a call!\n"; + + } else { + dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n"; + } + ); + + return DevirtualizedCall; +} + +/// RunAllPassesOnSCC - Execute the body of the entire pass manager on the +/// specified SCC. This keeps track of whether a function pass devirtualizes +/// any calls and returns it in DevirtualizedCall. +bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG, + bool &DevirtualizedCall) { + bool Changed = false; + + // CallGraphUpToDate - Keep track of whether the callgraph is known to be + // up-to-date or not. The CGSSC pass manager runs two types of passes: + // CallGraphSCC Passes and other random function passes. Because other + // random function passes are not CallGraph aware, they may clobber the + // call graph by introducing new calls or deleting other ones. This flag + // is set to false when we run a function pass so that we know to clean up + // the callgraph when we need to run a CGSCCPass again. + bool CallGraphUpToDate = true; + + // Run all passes on current SCC. + for (unsigned PassNo = 0, e = getNumContainedPasses(); + PassNo != e; ++PassNo) { + Pass *P = getContainedPass(PassNo); + + // If we're in -debug-pass=Executions mode, construct the SCC node list, + // otherwise avoid constructing this string as it is expensive. + if (isPassDebuggingExecutionsOrMore()) { + std::string Functions; + #ifndef NDEBUG + raw_string_ostream OS(Functions); + for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end(); + I != E; ++I) { + if (I != CurSCC.begin()) OS << ", "; + (*I)->print(OS); + } + OS.flush(); + #endif + dumpPassInfo(P, EXECUTION_MSG, ON_CG_MSG, Functions); + } + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + // Actually run this pass on the current SCC. + Changed |= RunPassOnSCC(P, CurSCC, CG, + CallGraphUpToDate, DevirtualizedCall); + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_CG_MSG, ""); + dumpPreservedSet(P); + + verifyPreservedAnalysis(P); + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, "", ON_CG_MSG); + } + + // If the callgraph was left out of date (because the last pass run was a + // functionpass), refresh it before we move on to the next SCC. + if (!CallGraphUpToDate) + DevirtualizedCall |= RefreshCallGraph(CurSCC, CG, false); + return Changed; +} + +/// run - Execute all of the passes scheduled for execution. Keep track of +/// whether any of the passes modifies the module, and if so, return true. +bool CGPassManager::runOnModule(Module &M) { + CallGraph &CG = getAnalysis(); + bool Changed = doInitialization(CG); + + // Walk the callgraph in bottom-up SCC order. + scc_iterator CGI = scc_begin(&CG); + + CallGraphSCC CurSCC(&CGI); + while (!CGI.isAtEnd()) { + // Copy the current SCC and increment past it so that the pass can hack + // on the SCC if it wants to without invalidating our iterator. + std::vector &NodeVec = *CGI; + CurSCC.initialize(&NodeVec[0], &NodeVec[0]+NodeVec.size()); + ++CGI; + + // At the top level, we run all the passes in this pass manager on the + // functions in this SCC. However, we support iterative compilation in the + // case where a function pass devirtualizes a call to a function. For + // example, it is very common for a function pass (often GVN or instcombine) + // to eliminate the addressing that feeds into a call. With that improved + // information, we would like the call to be an inline candidate, infer + // mod-ref information etc. + // + // Because of this, we allow iteration up to a specified iteration count. + // This only happens in the case of a devirtualized call, so we only burn + // compile time in the case that we're making progress. We also have a hard + // iteration count limit in case there is crazy code. + unsigned Iteration = 0; + bool DevirtualizedCall = false; + do { + DEBUG(if (Iteration) + dbgs() << " SCCPASSMGR: Re-visiting SCC, iteration #" + << Iteration << '\n'); + DevirtualizedCall = false; + Changed |= RunAllPassesOnSCC(CurSCC, CG, DevirtualizedCall); + } while (Iteration++ < MaxIterations && DevirtualizedCall); + + if (DevirtualizedCall) + DEBUG(dbgs() << " CGSCCPASSMGR: Stopped iteration after " << Iteration + << " times, due to -max-cg-scc-iterations\n"); + + if (Iteration > MaxSCCIterations) + MaxSCCIterations = Iteration; + + } + Changed |= doFinalization(CG); + return Changed; +} + + +/// Initialize CG +bool CGPassManager::doInitialization(CallGraph &CG) { + bool Changed = false; + for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { + if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + Changed |= ((FPPassManager*)PM)->doInitialization(CG.getModule()); + } else { + Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doInitialization(CG); + } + } + return Changed; +} + +/// Finalize CG +bool CGPassManager::doFinalization(CallGraph &CG) { + bool Changed = false; + for (unsigned i = 0, e = getNumContainedPasses(); i != e; ++i) { + if (PMDataManager *PM = getContainedPass(i)->getAsPMDataManager()) { + assert(PM->getPassManagerType() == PMT_FunctionPassManager && + "Invalid CGPassManager member"); + Changed |= ((FPPassManager*)PM)->doFinalization(CG.getModule()); + } else { + Changed |= ((CallGraphSCCPass*)getContainedPass(i))->doFinalization(CG); + } + } + return Changed; +} + +//===----------------------------------------------------------------------===// +// CallGraphSCC Implementation +//===----------------------------------------------------------------------===// + +/// ReplaceNode - This informs the SCC and the pass manager that the specified +/// Old node has been deleted, and New is to be used in its place. +void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) { + assert(Old != New && "Should not replace node with self"); + for (unsigned i = 0; ; ++i) { + assert(i != Nodes.size() && "Node not in SCC"); + if (Nodes[i] != Old) continue; + Nodes[i] = New; + break; + } + + // Update the active scc_iterator so that it doesn't contain dangling + // pointers to the old CallGraphNode. + scc_iterator *CGI = (scc_iterator*)Context; + CGI->ReplaceNode(Old, New); +} + + +//===----------------------------------------------------------------------===// +// CallGraphSCCPass Implementation +//===----------------------------------------------------------------------===// + +/// Assign pass manager to manage this pass. +void CallGraphSCCPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find CGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_CallGraphPassManager) + PMS.pop(); + + assert(!PMS.empty() && "Unable to handle Call Graph Pass"); + CGPassManager *CGP; + + if (PMS.top()->getPassManagerType() == PMT_CallGraphPassManager) + CGP = (CGPassManager*)PMS.top(); + else { + // Create new Call Graph SCC Pass Manager if it does not exist. + assert(!PMS.empty() && "Unable to create Call Graph Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + CGP = new CGPassManager(PMD->getDepth() + 1); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(CGP); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + Pass *P = CGP; + TPM->schedulePass(P); + + // [4] Push new manager into PMS + PMS.push(CGP); + } + + CGP->add(this); +} + +/// getAnalysisUsage - For this class, we declare that we require and preserve +/// the call graph. If the derived class implements this method, it should +/// always explicitly call the implementation here. +void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); +} + + +//===----------------------------------------------------------------------===// +// PrintCallGraphPass Implementation +//===----------------------------------------------------------------------===// + +namespace { + /// PrintCallGraphPass - Print a Module corresponding to a call graph. + /// + class PrintCallGraphPass : public CallGraphSCCPass { + std::string Banner; + raw_ostream &Out; // raw_ostream to print on. + + public: + static char ID; + PrintCallGraphPass(const std::string &B, raw_ostream &o) + : CallGraphSCCPass(ID), Banner(B), Out(o) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + bool runOnSCC(CallGraphSCC &SCC) { + Out << Banner; + for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) + (*I)->getFunction()->print(Out); + return false; + } + }; + +} // end anonymous namespace. + +char PrintCallGraphPass::ID = 0; + +Pass *CallGraphSCCPass::createPrinterPass(raw_ostream &O, + const std::string &Banner) const { + return new PrintCallGraphPass(Banner, O); +} + diff --git a/final/lib/Analysis/IPA/FindUsedTypes.cpp b/final/lib/Analysis/IPA/FindUsedTypes.cpp new file mode 100644 index 00000000000..06ae34cfd98 --- /dev/null +++ b/final/lib/Analysis/IPA/FindUsedTypes.cpp @@ -0,0 +1,103 @@ +//===- FindUsedTypes.cpp - Find all Types used by a module ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to seek out all of the types in use by the program. Note +// that this analysis explicitly does not include types only used by the symbol +// table. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +char FindUsedTypes::ID = 0; +INITIALIZE_PASS(FindUsedTypes, "print-used-types", + "Find Used Types", false, true) + +// IncorporateType - Incorporate one type and all of its subtypes into the +// collection of used types. +// +void FindUsedTypes::IncorporateType(const Type *Ty) { + // If ty doesn't already exist in the used types map, add it now, otherwise + // return. + if (!UsedTypes.insert(Ty).second) return; // Already contain Ty. + + // Make sure to add any types this type references now. + // + for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); + I != E; ++I) + IncorporateType(*I); +} + +void FindUsedTypes::IncorporateValue(const Value *V) { + IncorporateType(V->getType()); + + // If this is a constant, it could be using other types... + if (const Constant *C = dyn_cast(V)) { + if (!isa(C)) + for (User::const_op_iterator OI = C->op_begin(), OE = C->op_end(); + OI != OE; ++OI) + IncorporateValue(*OI); + } +} + + +// run - This incorporates all types used by the specified module +// +bool FindUsedTypes::runOnModule(Module &m) { + UsedTypes.clear(); // reset if run multiple times... + + // Loop over global variables, incorporating their types + for (Module::const_global_iterator I = m.global_begin(), E = m.global_end(); + I != E; ++I) { + IncorporateType(I->getType()); + if (I->hasInitializer()) + IncorporateValue(I->getInitializer()); + } + + for (Module::iterator MI = m.begin(), ME = m.end(); MI != ME; ++MI) { + IncorporateType(MI->getType()); + const Function &F = *MI; + + // Loop over all of the instructions in the function, adding their return + // type as well as the types of their operands. + // + for (const_inst_iterator II = inst_begin(F), IE = inst_end(F); + II != IE; ++II) { + const Instruction &I = *II; + + IncorporateType(I.getType()); // Incorporate the type of the instruction + for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end(); + OI != OE; ++OI) + IncorporateValue(*OI); // Insert inst operand types as well + } + } + + return false; +} + +// Print the types found in the module. If the optional Module parameter is +// passed in, then the types are printed symbolically if possible, using the +// symbol table from the module. +// +void FindUsedTypes::print(raw_ostream &OS, const Module *M) const { + OS << "Types in use by this module:\n"; + for (std::set::const_iterator I = UsedTypes.begin(), + E = UsedTypes.end(); I != E; ++I) { + OS << " "; + WriteTypeSymbolic(OS, *I, M); + OS << '\n'; + } +} diff --git a/final/lib/Analysis/IPA/GlobalsModRef.cpp b/final/lib/Analysis/IPA/GlobalsModRef.cpp new file mode 100644 index 00000000000..116aaf418ea --- /dev/null +++ b/final/lib/Analysis/IPA/GlobalsModRef.cpp @@ -0,0 +1,609 @@ +//===- GlobalsModRef.cpp - Simple Mod/Ref Analysis for Globals ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This simple pass provides alias and mod/ref information for global values +// that do not have their address taken, and keeps track of whether functions +// read or write memory (are "pure"). For this simple (but very common) case, +// we can provide pretty accurate and useful information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "globalsmodref-aa" +#include "llvm/Analysis/Passes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SCCIterator.h" +#include +using namespace llvm; + +STATISTIC(NumNonAddrTakenGlobalVars, + "Number of global vars without address taken"); +STATISTIC(NumNonAddrTakenFunctions,"Number of functions without address taken"); +STATISTIC(NumNoMemFunctions, "Number of functions that do not access memory"); +STATISTIC(NumReadMemFunctions, "Number of functions that only read memory"); +STATISTIC(NumIndirectGlobalVars, "Number of indirect global objects"); + +namespace { + /// FunctionRecord - One instance of this structure is stored for every + /// function in the program. Later, the entries for these functions are + /// removed if the function is found to call an external function (in which + /// case we know nothing about it. + struct FunctionRecord { + /// GlobalInfo - Maintain mod/ref info for all of the globals without + /// addresses taken that are read or written (transitively) by this + /// function. + std::map GlobalInfo; + + /// MayReadAnyGlobal - May read global variables, but it is not known which. + bool MayReadAnyGlobal; + + unsigned getInfoForGlobal(const GlobalValue *GV) const { + unsigned Effect = MayReadAnyGlobal ? AliasAnalysis::Ref : 0; + std::map::const_iterator I = + GlobalInfo.find(GV); + if (I != GlobalInfo.end()) + Effect |= I->second; + return Effect; + } + + /// FunctionEffect - Capture whether or not this function reads or writes to + /// ANY memory. If not, we can do a lot of aggressive analysis on it. + unsigned FunctionEffect; + + FunctionRecord() : MayReadAnyGlobal (false), FunctionEffect(0) {} + }; + + /// GlobalsModRef - The actual analysis pass. + class GlobalsModRef : public ModulePass, public AliasAnalysis { + /// NonAddressTakenGlobals - The globals that do not have their addresses + /// taken. + std::set NonAddressTakenGlobals; + + /// IndirectGlobals - The memory pointed to by this global is known to be + /// 'owned' by the global. + std::set IndirectGlobals; + + /// AllocsForIndirectGlobals - If an instruction allocates memory for an + /// indirect global, this map indicates which one. + std::map AllocsForIndirectGlobals; + + /// FunctionInfo - For each function, keep track of what globals are + /// modified or read. + std::map FunctionInfo; + + public: + static char ID; + GlobalsModRef() : ModulePass(ID) { + initializeGlobalsModRefPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) { + InitializeAliasAnalysis(this); // set up super class + AnalyzeGlobals(M); // find non-addr taken globals + AnalyzeCallGraph(getAnalysis(), M); // Propagate on CG + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.addRequired(); + AU.setPreservesAll(); // Does not transform code + } + + //------------------------------------------------ + // Implement the AliasAnalysis API + // + AliasResult alias(const Location &LocA, const Location &LocB); + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + return AliasAnalysis::getModRefInfo(CS1, CS2); + } + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(const Function *F) { + ModRefBehavior Min = UnknownModRefBehavior; + + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + Min = DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + Min = OnlyReadsMemory; + } + + return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min); + } + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + ModRefBehavior getModRefBehavior(ImmutableCallSite CS) { + ModRefBehavior Min = UnknownModRefBehavior; + + if (const Function* F = CS.getCalledFunction()) + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + Min = DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + Min = OnlyReadsMemory; + } + + return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); + } + + virtual void deleteValue(Value *V); + virtual void copyValue(Value *From, Value *To); + virtual void addEscapingUse(Use &U); + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + private: + /// getFunctionInfo - Return the function info for the function, or null if + /// we don't have anything useful to say about it. + FunctionRecord *getFunctionInfo(const Function *F) { + std::map::iterator I = + FunctionInfo.find(F); + if (I != FunctionInfo.end()) + return &I->second; + return 0; + } + + void AnalyzeGlobals(Module &M); + void AnalyzeCallGraph(CallGraph &CG, Module &M); + bool AnalyzeUsesOfPointer(Value *V, std::vector &Readers, + std::vector &Writers, + GlobalValue *OkayStoreDest = 0); + bool AnalyzeIndirectGlobalMemory(GlobalValue *GV); + }; +} + +char GlobalsModRef::ID = 0; +INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, + "globalsmodref-aa", "Simple mod/ref analysis for globals", + false, true, false) +INITIALIZE_AG_DEPENDENCY(CallGraph) +INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, + "globalsmodref-aa", "Simple mod/ref analysis for globals", + false, true, false) + +Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); } + +/// AnalyzeGlobals - Scan through the users of all of the internal +/// GlobalValue's in the program. If none of them have their "address taken" +/// (really, their address passed to something nontrivial), record this fact, +/// and record the functions that they are used directly in. +void GlobalsModRef::AnalyzeGlobals(Module &M) { + std::vector Readers, Writers; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->hasLocalLinkage()) { + if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { + // Remember that we are tracking this global. + NonAddressTakenGlobals.insert(I); + ++NumNonAddrTakenFunctions; + } + Readers.clear(); Writers.clear(); + } + + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (I->hasLocalLinkage()) { + if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { + // Remember that we are tracking this global, and the mod/ref fns + NonAddressTakenGlobals.insert(I); + + for (unsigned i = 0, e = Readers.size(); i != e; ++i) + FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref; + + if (!I->isConstant()) // No need to keep track of writers to constants + for (unsigned i = 0, e = Writers.size(); i != e; ++i) + FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod; + ++NumNonAddrTakenGlobalVars; + + // If this global holds a pointer type, see if it is an indirect global. + if (I->getType()->getElementType()->isPointerTy() && + AnalyzeIndirectGlobalMemory(I)) + ++NumIndirectGlobalVars; + } + Readers.clear(); Writers.clear(); + } +} + +/// AnalyzeUsesOfPointer - Look at all of the users of the specified pointer. +/// If this is used by anything complex (i.e., the address escapes), return +/// true. Also, while we are at it, keep track of those functions that read and +/// write to the value. +/// +/// If OkayStoreDest is non-null, stores into this global are allowed. +bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, + std::vector &Readers, + std::vector &Writers, + GlobalValue *OkayStoreDest) { + if (!V->getType()->isPointerTy()) return true; + + for (Value::use_iterator UI = V->use_begin(), E=V->use_end(); UI != E; ++UI) { + User *U = *UI; + if (LoadInst *LI = dyn_cast(U)) { + Readers.push_back(LI->getParent()->getParent()); + } else if (StoreInst *SI = dyn_cast(U)) { + if (V == SI->getOperand(1)) { + Writers.push_back(SI->getParent()->getParent()); + } else if (SI->getOperand(1) != OkayStoreDest) { + return true; // Storing the pointer + } + } else if (GetElementPtrInst *GEP = dyn_cast(U)) { + if (AnalyzeUsesOfPointer(GEP, Readers, Writers)) return true; + } else if (BitCastInst *BCI = dyn_cast(U)) { + if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest)) + return true; + } else if (isFreeCall(U)) { + Writers.push_back(cast(U)->getParent()->getParent()); + } else if (CallInst *CI = dyn_cast(U)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 0, e = CI->getNumArgOperands(); i != e; ++i) + if (CI->getArgOperand(i) == V) return true; + } else if (InvokeInst *II = dyn_cast(U)) { + // Make sure that this is just the function being called, not that it is + // passing into the function. + for (unsigned i = 0, e = II->getNumArgOperands(); i != e; ++i) + if (II->getArgOperand(i) == V) return true; + } else if (ConstantExpr *CE = dyn_cast(U)) { + if (CE->getOpcode() == Instruction::GetElementPtr || + CE->getOpcode() == Instruction::BitCast) { + if (AnalyzeUsesOfPointer(CE, Readers, Writers)) + return true; + } else { + return true; + } + } else if (ICmpInst *ICI = dyn_cast(U)) { + if (!isa(ICI->getOperand(1))) + return true; // Allow comparison against null. + } else { + return true; + } + } + + return false; +} + +/// AnalyzeIndirectGlobalMemory - We found an non-address-taken global variable +/// which holds a pointer type. See if the global always points to non-aliased +/// heap memory: that is, all initializers of the globals are allocations, and +/// those allocations have no use other than initialization of the global. +/// Further, all loads out of GV must directly use the memory, not store the +/// pointer somewhere. If this is true, we consider the memory pointed to by +/// GV to be owned by GV and can disambiguate other pointers from it. +bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) { + // Keep track of values related to the allocation of the memory, f.e. the + // value produced by the malloc call and any casts. + std::vector AllocRelatedValues; + + // Walk the user list of the global. If we find anything other than a direct + // load or store, bail out. + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I){ + User *U = *I; + if (LoadInst *LI = dyn_cast(U)) { + // The pointer loaded from the global can only be used in simple ways: + // we allow addressing of it and loading storing to it. We do *not* allow + // storing the loaded pointer somewhere else or passing to a function. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(LI, ReadersWriters, ReadersWriters)) + return false; // Loaded pointer escapes. + // TODO: Could try some IP mod/ref of the loaded pointer. + } else if (StoreInst *SI = dyn_cast(U)) { + // Storing the global itself. + if (SI->getOperand(0) == GV) return false; + + // If storing the null pointer, ignore it. + if (isa(SI->getOperand(0))) + continue; + + // Check the value being stored. + Value *Ptr = GetUnderlyingObject(SI->getOperand(0)); + + if (isMalloc(Ptr)) { + // Okay, easy case. + } else if (CallInst *CI = dyn_cast(Ptr)) { + Function *F = CI->getCalledFunction(); + if (!F || !F->isDeclaration()) return false; // Too hard to analyze. + if (F->getName() != "calloc") return false; // Not calloc. + } else { + return false; // Too hard to analyze. + } + + // Analyze all uses of the allocation. If any of them are used in a + // non-simple way (e.g. stored to another global) bail out. + std::vector ReadersWriters; + if (AnalyzeUsesOfPointer(Ptr, ReadersWriters, ReadersWriters, GV)) + return false; // Loaded pointer escapes. + + // Remember that this allocation is related to the indirect global. + AllocRelatedValues.push_back(Ptr); + } else { + // Something complex, bail out. + return false; + } + } + + // Okay, this is an indirect global. Remember all of the allocations for + // this global in AllocsForIndirectGlobals. + while (!AllocRelatedValues.empty()) { + AllocsForIndirectGlobals[AllocRelatedValues.back()] = GV; + AllocRelatedValues.pop_back(); + } + IndirectGlobals.insert(GV); + return true; +} + +/// AnalyzeCallGraph - At this point, we know the functions where globals are +/// immediately stored to and read from. Propagate this information up the call +/// graph to all callers and compute the mod/ref info for all memory for each +/// function. +void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) { + // We do a bottom-up SCC traversal of the call graph. In other words, we + // visit all callees before callers (leaf-first). + for (scc_iterator I = scc_begin(&CG), E = scc_end(&CG); I != E; + ++I) { + std::vector &SCC = *I; + assert(!SCC.empty() && "SCC with no functions?"); + + if (!SCC[0]->getFunction()) { + // Calls externally - can't say anything useful. Remove any existing + // function records (may have been created when scanning globals). + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + FunctionInfo.erase(SCC[i]->getFunction()); + continue; + } + + FunctionRecord &FR = FunctionInfo[SCC[0]->getFunction()]; + + bool KnowNothing = false; + unsigned FunctionEffect = 0; + + // Collect the mod/ref properties due to called functions. We only compute + // one mod-ref set. + for (unsigned i = 0, e = SCC.size(); i != e && !KnowNothing; ++i) { + Function *F = SCC[i]->getFunction(); + if (!F) { + KnowNothing = true; + break; + } + + if (F->isDeclaration()) { + // Try to get mod/ref behaviour from function attributes. + if (F->doesNotAccessMemory()) { + // Can't do better than that! + } else if (F->onlyReadsMemory()) { + FunctionEffect |= Ref; + if (!F->isIntrinsic()) + // This function might call back into the module and read a global - + // consider every global as possibly being read by this function. + FR.MayReadAnyGlobal = true; + } else { + FunctionEffect |= ModRef; + // Can't say anything useful unless it's an intrinsic - they don't + // read or write global variables of the kind considered here. + KnowNothing = !F->isIntrinsic(); + } + continue; + } + + for (CallGraphNode::iterator CI = SCC[i]->begin(), E = SCC[i]->end(); + CI != E && !KnowNothing; ++CI) + if (Function *Callee = CI->second->getFunction()) { + if (FunctionRecord *CalleeFR = getFunctionInfo(Callee)) { + // Propagate function effect up. + FunctionEffect |= CalleeFR->FunctionEffect; + + // Incorporate callee's effects on globals into our info. + for (std::map::iterator GI = + CalleeFR->GlobalInfo.begin(), E = CalleeFR->GlobalInfo.end(); + GI != E; ++GI) + FR.GlobalInfo[GI->first] |= GI->second; + FR.MayReadAnyGlobal |= CalleeFR->MayReadAnyGlobal; + } else { + // Can't say anything about it. However, if it is inside our SCC, + // then nothing needs to be done. + CallGraphNode *CalleeNode = CG[Callee]; + if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()) + KnowNothing = true; + } + } else { + KnowNothing = true; + } + } + + // If we can't say anything useful about this SCC, remove all SCC functions + // from the FunctionInfo map. + if (KnowNothing) { + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + FunctionInfo.erase(SCC[i]->getFunction()); + continue; + } + + // Scan the function bodies for explicit loads or stores. + for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i) + for (inst_iterator II = inst_begin(SCC[i]->getFunction()), + E = inst_end(SCC[i]->getFunction()); + II != E && FunctionEffect != ModRef; ++II) + if (isa(*II)) { + FunctionEffect |= Ref; + if (cast(*II).isVolatile()) + // Volatile loads may have side-effects, so mark them as writing + // memory (for example, a flag inside the processor). + FunctionEffect |= Mod; + } else if (isa(*II)) { + FunctionEffect |= Mod; + if (cast(*II).isVolatile()) + // Treat volatile stores as reading memory somewhere. + FunctionEffect |= Ref; + } else if (isMalloc(&cast(*II)) || + isFreeCall(&cast(*II))) { + FunctionEffect |= ModRef; + } + + if ((FunctionEffect & Mod) == 0) + ++NumReadMemFunctions; + if (FunctionEffect == 0) + ++NumNoMemFunctions; + FR.FunctionEffect = FunctionEffect; + + // Finally, now that we know the full effect on this SCC, clone the + // information to each function in the SCC. + for (unsigned i = 1, e = SCC.size(); i != e; ++i) + FunctionInfo[SCC[i]->getFunction()] = FR; + } +} + + + +/// alias - If one of the pointers is to a global that we are tracking, and the +/// other is some random pointer, we know there cannot be an alias, because the +/// address of the global isn't taken. +AliasAnalysis::AliasResult +GlobalsModRef::alias(const Location &LocA, + const Location &LocB) { + // Get the base object these pointers point to. + const Value *UV1 = GetUnderlyingObject(LocA.Ptr); + const Value *UV2 = GetUnderlyingObject(LocB.Ptr); + + // If either of the underlying values is a global, they may be non-addr-taken + // globals, which we can answer queries about. + const GlobalValue *GV1 = dyn_cast(UV1); + const GlobalValue *GV2 = dyn_cast(UV2); + if (GV1 || GV2) { + // If the global's address is taken, pretend we don't know it's a pointer to + // the global. + if (GV1 && !NonAddressTakenGlobals.count(GV1)) GV1 = 0; + if (GV2 && !NonAddressTakenGlobals.count(GV2)) GV2 = 0; + + // If the two pointers are derived from two different non-addr-taken + // globals, or if one is and the other isn't, we know these can't alias. + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + + // Otherwise if they are both derived from the same addr-taken global, we + // can't know the two accesses don't overlap. + } + + // These pointers may be based on the memory owned by an indirect global. If + // so, we may be able to handle this. First check to see if the base pointer + // is a direct load from an indirect global. + GV1 = GV2 = 0; + if (const LoadInst *LI = dyn_cast(UV1)) + if (GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (IndirectGlobals.count(GV)) + GV1 = GV; + if (const LoadInst *LI = dyn_cast(UV2)) + if (const GlobalVariable *GV = dyn_cast(LI->getOperand(0))) + if (IndirectGlobals.count(GV)) + GV2 = GV; + + // These pointers may also be from an allocation for the indirect global. If + // so, also handle them. + if (AllocsForIndirectGlobals.count(UV1)) + GV1 = AllocsForIndirectGlobals[UV1]; + if (AllocsForIndirectGlobals.count(UV2)) + GV2 = AllocsForIndirectGlobals[UV2]; + + // Now that we know whether the two pointers are related to indirect globals, + // use this to disambiguate the pointers. If either pointer is based on an + // indirect global and if they are not both based on the same indirect global, + // they cannot alias. + if ((GV1 || GV2) && GV1 != GV2) + return NoAlias; + + return AliasAnalysis::alias(LocA, LocB); +} + +AliasAnalysis::ModRefResult +GlobalsModRef::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + unsigned Known = ModRef; + + // If we are asking for mod/ref info of a direct call with a pointer to a + // global we are tracking, return information if we have it. + if (const GlobalValue *GV = + dyn_cast(GetUnderlyingObject(Loc.Ptr))) + if (GV->hasLocalLinkage()) + if (const Function *F = CS.getCalledFunction()) + if (NonAddressTakenGlobals.count(GV)) + if (const FunctionRecord *FR = getFunctionInfo(F)) + Known = FR->getInfoForGlobal(GV); + + if (Known == NoModRef) + return NoModRef; // No need to query other mod/ref analyses + return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, Loc)); +} + + +//===----------------------------------------------------------------------===// +// Methods to update the analysis as a result of the client transformation. +// +void GlobalsModRef::deleteValue(Value *V) { + if (GlobalValue *GV = dyn_cast(V)) { + if (NonAddressTakenGlobals.erase(GV)) { + // This global might be an indirect global. If so, remove it and remove + // any AllocRelatedValues for it. + if (IndirectGlobals.erase(GV)) { + // Remove any entries in AllocsForIndirectGlobals for this global. + for (std::map::iterator + I = AllocsForIndirectGlobals.begin(), + E = AllocsForIndirectGlobals.end(); I != E; ) { + if (I->second == GV) { + AllocsForIndirectGlobals.erase(I++); + } else { + ++I; + } + } + } + } + } + + // Otherwise, if this is an allocation related to an indirect global, remove + // it. + AllocsForIndirectGlobals.erase(V); + + AliasAnalysis::deleteValue(V); +} + +void GlobalsModRef::copyValue(Value *From, Value *To) { + AliasAnalysis::copyValue(From, To); +} + +void GlobalsModRef::addEscapingUse(Use &U) { + // For the purposes of this analysis, it is conservatively correct to treat + // a newly escaping value equivalently to a deleted one. We could perhaps + // be more precise by processing the new use and attempting to update our + // saved analysis results to accomodate it. + deleteValue(U); + + AliasAnalysis::addEscapingUse(U); +} diff --git a/final/lib/Analysis/IPA/IPA.cpp b/final/lib/Analysis/IPA/IPA.cpp new file mode 100644 index 00000000000..0ba2e04c630 --- /dev/null +++ b/final/lib/Analysis/IPA/IPA.cpp @@ -0,0 +1,29 @@ +//===-- IPA.cpp -----------------------------------------------------------===// +// +// 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 common initialization routines for the IPA library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" +#include "llvm-c/Initialization.h" + +using namespace llvm; + +/// initializeIPA - Initialize all passes linked into the IPA library. +void llvm::initializeIPA(PassRegistry &Registry) { + initializeBasicCallGraphPass(Registry); + initializeCallGraphAnalysisGroup(Registry); + initializeFindUsedTypesPass(Registry); + initializeGlobalsModRefPass(Registry); +} + +void LLVMInitializeIPA(LLVMPassRegistryRef R) { + initializeIPA(*unwrap(R)); +} diff --git a/final/lib/Analysis/IPA/Makefile b/final/lib/Analysis/IPA/Makefile new file mode 100644 index 00000000000..b850c9ff7f4 --- /dev/null +++ b/final/lib/Analysis/IPA/Makefile @@ -0,0 +1,15 @@ +##===- lib/Analysis/IPA/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMipa +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Analysis/IVUsers.cpp b/final/lib/Analysis/IVUsers.cpp new file mode 100644 index 00000000000..c8382186df3 --- /dev/null +++ b/final/lib/Analysis/IVUsers.cpp @@ -0,0 +1,263 @@ +//===- IVUsers.cpp - Induction Variable Users -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements bookkeeping for "interesting" users of expressions +// computed from induction variables. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "iv-users" +#include "llvm/Analysis/IVUsers.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +char IVUsers::ID = 0; +INITIALIZE_PASS_BEGIN(IVUsers, "iv-users", + "Induction Variable Users", false, true) +INITIALIZE_PASS_DEPENDENCY(LoopInfo) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) +INITIALIZE_PASS_END(IVUsers, "iv-users", + "Induction Variable Users", false, true) + +Pass *llvm::createIVUsersPass() { + return new IVUsers(); +} + +/// isInteresting - Test whether the given expression is "interesting" when +/// used by the given expression, within the context of analyzing the +/// given loop. +static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, + ScalarEvolution *SE) { + // An addrec is interesting if it's affine or if it has an interesting start. + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // Keep things simple. Don't touch loop-variant strides. + if (AR->getLoop() == L) + return AR->isAffine() || !L->contains(I); + // Otherwise recurse to see if the start value is interesting, and that + // the step value is not interesting, since we don't yet know how to + // do effective SCEV expansions for addrecs with interesting steps. + return isInteresting(AR->getStart(), I, L, SE) && + !isInteresting(AR->getStepRecurrence(*SE), I, L, SE); + } + + // An add is interesting if exactly one of its operands is interesting. + if (const SCEVAddExpr *Add = dyn_cast(S)) { + bool AnyInterestingYet = false; + for (SCEVAddExpr::op_iterator OI = Add->op_begin(), OE = Add->op_end(); + OI != OE; ++OI) + if (isInteresting(*OI, I, L, SE)) { + if (AnyInterestingYet) + return false; + AnyInterestingYet = true; + } + return AnyInterestingYet; + } + + // Nothing else is interesting here. + return false; +} + +/// AddUsersIfInteresting - Inspect the specified instruction. If it is a +/// reducible SCEV, recursively add its users to the IVUsesByStride set and +/// return true. Otherwise, return false. +bool IVUsers::AddUsersIfInteresting(Instruction *I) { + if (!SE->isSCEVable(I->getType())) + return false; // Void and FP expressions cannot be reduced. + + // LSR is not APInt clean, do not touch integers bigger than 64-bits. + if (SE->getTypeSizeInBits(I->getType()) > 64) + return false; + + if (!Processed.insert(I)) + return true; // Instruction already handled. + + // Get the symbolic expression for this instruction. + const SCEV *ISE = SE->getSCEV(I); + + // If we've come to an uninteresting expression, stop the traversal and + // call this a user. + if (!isInteresting(ISE, I, L, SE)) + return false; + + SmallPtrSet UniqueUsers; + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + if (!UniqueUsers.insert(User)) + continue; + + // Do not infinitely recurse on PHI nodes. + if (isa(User) && Processed.count(User)) + continue; + + // Descend recursively, but not into PHI nodes outside the current loop. + // It's important to see the entire expression outside the loop to get + // choices that depend on addressing mode use right, although we won't + // consider references outside the loop in all cases. + // If User is already in Processed, we don't want to recurse into it again, + // but do want to record a second reference in the same instruction. + bool AddUserToIVUsers = false; + if (LI->getLoopFor(User->getParent()) != L) { + if (isa(User) || Processed.count(User) || + !AddUsersIfInteresting(User)) { + DEBUG(dbgs() << "FOUND USER in other loop: " << *User << '\n' + << " OF SCEV: " << *ISE << '\n'); + AddUserToIVUsers = true; + } + } else if (Processed.count(User) || + !AddUsersIfInteresting(User)) { + DEBUG(dbgs() << "FOUND USER: " << *User << '\n' + << " OF SCEV: " << *ISE << '\n'); + AddUserToIVUsers = true; + } + + if (AddUserToIVUsers) { + // Okay, we found a user that we cannot reduce. + IVUses.push_back(new IVStrideUse(this, User, I)); + IVStrideUse &NewUse = IVUses.back(); + // Transform the expression into a normalized form. + ISE = TransformForPostIncUse(NormalizeAutodetect, + ISE, User, I, + NewUse.PostIncLoops, + *SE, *DT); + DEBUG(dbgs() << " NORMALIZED TO: " << *ISE << '\n'); + } + } + return true; +} + +IVStrideUse &IVUsers::AddUser(Instruction *User, Value *Operand) { + IVUses.push_back(new IVStrideUse(this, User, Operand)); + return IVUses.back(); +} + +IVUsers::IVUsers() + : LoopPass(ID) { + initializeIVUsersPass(*PassRegistry::getPassRegistry()); +} + +void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); +} + +bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { + + L = l; + LI = &getAnalysis(); + DT = &getAnalysis(); + SE = &getAnalysis(); + + // Find all uses of induction variables in this loop, and categorize + // them by stride. Start by finding all of the PHI nodes in the header for + // this loop. If they are induction variables, inspect their uses. + for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) + (void)AddUsersIfInteresting(I); + + return false; +} + +void IVUsers::print(raw_ostream &OS, const Module *M) const { + OS << "IV Users for loop "; + WriteAsOperand(OS, L->getHeader(), false); + if (SE->hasLoopInvariantBackedgeTakenCount(L)) { + OS << " with backedge-taken count " + << *SE->getBackedgeTakenCount(L); + } + OS << ":\n"; + + for (ilist::const_iterator UI = IVUses.begin(), + E = IVUses.end(); UI != E; ++UI) { + OS << " "; + WriteAsOperand(OS, UI->getOperandValToReplace(), false); + OS << " = " << *getReplacementExpr(*UI); + for (PostIncLoopSet::const_iterator + I = UI->PostIncLoops.begin(), + E = UI->PostIncLoops.end(); I != E; ++I) { + OS << " (post-inc with loop "; + WriteAsOperand(OS, (*I)->getHeader(), false); + OS << ")"; + } + OS << " in "; + UI->getUser()->print(OS); + OS << '\n'; + } +} + +void IVUsers::dump() const { + print(dbgs()); +} + +void IVUsers::releaseMemory() { + Processed.clear(); + IVUses.clear(); +} + +/// getReplacementExpr - Return a SCEV expression which computes the +/// value of the OperandValToReplace. +const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &IU) const { + return SE->getSCEV(IU.getOperandValToReplace()); +} + +/// getExpr - Return the expression for the use. +const SCEV *IVUsers::getExpr(const IVStrideUse &IU) const { + return + TransformForPostIncUse(Normalize, getReplacementExpr(IU), + IU.getUser(), IU.getOperandValToReplace(), + const_cast(IU.getPostIncLoops()), + *SE, *DT); +} + +static const SCEVAddRecExpr *findAddRecForLoop(const SCEV *S, const Loop *L) { + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + if (AR->getLoop() == L) + return AR; + return findAddRecForLoop(AR->getStart(), L); + } + + if (const SCEVAddExpr *Add = dyn_cast(S)) { + for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) + if (const SCEVAddRecExpr *AR = findAddRecForLoop(*I, L)) + return AR; + return 0; + } + + return 0; +} + +const SCEV *IVUsers::getStride(const IVStrideUse &IU, const Loop *L) const { + if (const SCEVAddRecExpr *AR = findAddRecForLoop(getExpr(IU), L)) + return AR->getStepRecurrence(*SE); + return 0; +} + +void IVStrideUse::transformToPostInc(const Loop *L) { + PostIncLoops.insert(L); +} + +void IVStrideUse::deleted() { + // Remove this user from the list. + Parent->IVUses.erase(this); + // this now dangles! +} diff --git a/final/lib/Analysis/InlineCost.cpp b/final/lib/Analysis/InlineCost.cpp new file mode 100644 index 00000000000..47f91cfc3be --- /dev/null +++ b/final/lib/Analysis/InlineCost.cpp @@ -0,0 +1,648 @@ +//===- InlineCost.cpp - Cost analysis for inliner -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements inline cost analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InlineCost.h" +#include "llvm/Support/CallSite.h" +#include "llvm/CallingConv.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/ADT/SmallPtrSet.h" + +using namespace llvm; + +/// callIsSmall - If a call is likely to lower to a single target instruction, +/// or is otherwise deemed small return true. +/// TODO: Perhaps calls like memcpy, strcpy, etc? +bool llvm::callIsSmall(const Function *F) { + if (!F) return false; + + if (F->hasLocalLinkage()) return false; + + if (!F->hasName()) return false; + + StringRef Name = F->getName(); + + // These will all likely lower to a single selection DAG node. + if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" || + Name == "fabs" || Name == "fabsf" || Name == "fabsl" || + Name == "sin" || Name == "sinf" || Name == "sinl" || + Name == "cos" || Name == "cosf" || Name == "cosl" || + Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl" ) + return true; + + // These are all likely to be optimized into something smaller. + if (Name == "pow" || Name == "powf" || Name == "powl" || + Name == "exp2" || Name == "exp2l" || Name == "exp2f" || + Name == "floor" || Name == "floorf" || Name == "ceil" || + Name == "round" || Name == "ffs" || Name == "ffsl" || + Name == "abs" || Name == "labs" || Name == "llabs") + return true; + + return false; +} + +/// analyzeBasicBlock - Fill in the current structure with information gleaned +/// from the specified block. +void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { + ++NumBlocks; + unsigned NumInstsBeforeThisBB = NumInsts; + for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); + II != E; ++II) { + if (isa(II)) continue; // PHI nodes don't count. + + // Special handling for calls. + if (isa(II) || isa(II)) { + if (isa(II)) + continue; // Debug intrinsics don't count as size. + + ImmutableCallSite CS(cast(II)); + + // If this function contains a call to setjmp or _setjmp, never inline + // it. This is a hack because we depend on the user marking their local + // variables as volatile if they are live across a setjmp call, and they + // probably won't do this in callers. + if (const Function *F = CS.getCalledFunction()) { + // If a function is both internal and has a single use, then it is + // extremely likely to get inlined in the future (it was probably + // exposed by an interleaved devirtualization pass). + if (F->hasInternalLinkage() && F->hasOneUse()) + ++NumInlineCandidates; + + if (F->isDeclaration() && + (F->getName() == "setjmp" || F->getName() == "_setjmp")) + callsSetJmp = true; + + // If this call is to function itself, then the function is recursive. + // Inlining it into other functions is a bad idea, because this is + // basically just a form of loop peeling, and our metrics aren't useful + // for that case. + if (F == BB->getParent()) + isRecursive = true; + } + + if (!isa(II) && !callIsSmall(CS.getCalledFunction())) { + // Each argument to a call takes on average one instruction to set up. + NumInsts += CS.arg_size(); + + // We don't want inline asm to count as a call - that would prevent loop + // unrolling. The argument setup cost is still real, though. + if (!isa(CS.getCalledValue())) + ++NumCalls; + } + } + + if (const AllocaInst *AI = dyn_cast(II)) { + if (!AI->isStaticAlloca()) + this->usesDynamicAlloca = true; + } + + if (isa(II) || II->getType()->isVectorTy()) + ++NumVectorInsts; + + if (const CastInst *CI = dyn_cast(II)) { + // Noop casts, including ptr <-> int, don't count. + if (CI->isLosslessCast() || isa(CI) || + isa(CI)) + continue; + // Result of a cmp instruction is often extended (to be used by other + // cmp instructions, logical or return instructions). These are usually + // nop on most sane targets. + if (isa(CI->getOperand(0))) + continue; + } else if (const GetElementPtrInst *GEPI = dyn_cast(II)){ + // If a GEP has all constant indices, it will probably be folded with + // a load/store. + if (GEPI->hasAllConstantIndices()) + continue; + } + + ++NumInsts; + } + + if (isa(BB->getTerminator())) + ++NumRets; + + // We never want to inline functions that contain an indirectbr. This is + // incorrect because all the blockaddress's (in static global initializers + // for example) would be referring to the original function, and this indirect + // jump would jump from the inlined copy of the function into the original + // function which is extremely undefined behavior. + if (isa(BB->getTerminator())) + containsIndirectBr = true; + + // Remember NumInsts for this BB. + NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB; +} + +// CountCodeReductionForConstant - Figure out an approximation for how many +// instructions will be constant folded if the specified value is constant. +// +unsigned CodeMetrics::CountCodeReductionForConstant(Value *V) { + unsigned Reduction = 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + User *U = *UI; + if (isa(U) || isa(U)) { + // We will be able to eliminate all but one of the successors. + const TerminatorInst &TI = cast(*U); + const unsigned NumSucc = TI.getNumSuccessors(); + unsigned Instrs = 0; + for (unsigned I = 0; I != NumSucc; ++I) + Instrs += NumBBInsts[TI.getSuccessor(I)]; + // We don't know which blocks will be eliminated, so use the average size. + Reduction += InlineConstants::InstrCost*Instrs*(NumSucc-1)/NumSucc; + } else { + // Figure out if this instruction will be removed due to simple constant + // propagation. + Instruction &Inst = cast(*U); + + // We can't constant propagate instructions which have effects or + // read memory. + // + // FIXME: It would be nice to capture the fact that a load from a + // pointer-to-constant-global is actually a *really* good thing to zap. + // Unfortunately, we don't know the pointer that may get propagated here, + // so we can't make this decision. + if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() || + isa(Inst)) + continue; + + bool AllOperandsConstant = true; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) + if (!isa(Inst.getOperand(i)) && Inst.getOperand(i) != V) { + AllOperandsConstant = false; + break; + } + + if (AllOperandsConstant) { + // We will get to remove this instruction... + Reduction += InlineConstants::InstrCost; + + // And any other instructions that use it which become constants + // themselves. + Reduction += CountCodeReductionForConstant(&Inst); + } + } + } + return Reduction; +} + +// CountCodeReductionForAlloca - Figure out an approximation of how much smaller +// the function will be if it is inlined into a context where an argument +// becomes an alloca. +// +unsigned CodeMetrics::CountCodeReductionForAlloca(Value *V) { + if (!V->getType()->isPointerTy()) return 0; // Not a pointer + unsigned Reduction = 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + Instruction *I = cast(*UI); + if (isa(I) || isa(I)) + Reduction += InlineConstants::InstrCost; + else if (GetElementPtrInst *GEP = dyn_cast(I)) { + // If the GEP has variable indices, we won't be able to do much with it. + if (GEP->hasAllConstantIndices()) + Reduction += CountCodeReductionForAlloca(GEP); + } else if (BitCastInst *BCI = dyn_cast(I)) { + // Track pointer through bitcasts. + Reduction += CountCodeReductionForAlloca(BCI); + } else { + // If there is some other strange instruction, we're not going to be able + // to do much if we inline this. + return 0; + } + } + + return Reduction; +} + +/// analyzeFunction - Fill in the current structure with information gleaned +/// from the specified function. +void CodeMetrics::analyzeFunction(Function *F) { + // Look at the size of the callee. + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + analyzeBasicBlock(&*BB); +} + +/// analyzeFunction - Fill in the current structure with information gleaned +/// from the specified function. +void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { + Metrics.analyzeFunction(F); + + // A function with exactly one return has it removed during the inlining + // process (see InlineFunction), so don't count it. + // FIXME: This knowledge should really be encoded outside of FunctionInfo. + if (Metrics.NumRets==1) + --Metrics.NumInsts; + + // Check out all of the arguments to the function, figuring out how much + // code can be eliminated if one of the arguments is a constant. + ArgumentWeights.reserve(F->arg_size()); + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + ArgumentWeights.push_back(ArgInfo(Metrics.CountCodeReductionForConstant(I), + Metrics.CountCodeReductionForAlloca(I))); +} + +/// NeverInline - returns true if the function should never be inlined into +/// any caller +bool InlineCostAnalyzer::FunctionInfo::NeverInline() { + return (Metrics.callsSetJmp || Metrics.isRecursive || + Metrics.containsIndirectBr); +} +// getSpecializationBonus - The heuristic used to determine the per-call +// performance boost for using a specialization of Callee with argument +// specializedArgNo replaced by a constant. +int InlineCostAnalyzer::getSpecializationBonus(Function *Callee, + SmallVectorImpl &SpecializedArgNos) +{ + if (Callee->mayBeOverridden()) + return 0; + + int Bonus = 0; + // If this function uses the coldcc calling convention, prefer not to + // specialize it. + if (Callee->getCallingConv() == CallingConv::Cold) + Bonus -= InlineConstants::ColdccPenalty; + + // Get information about the callee. + FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI->Metrics.NumBlocks == 0) + CalleeFI->analyzeFunction(Callee); + + unsigned ArgNo = 0; + unsigned i = 0; + for (Function::arg_iterator I = Callee->arg_begin(), E = Callee->arg_end(); + I != E; ++I, ++ArgNo) + if (ArgNo == SpecializedArgNos[i]) { + ++i; + Bonus += CountBonusForConstant(I); + } + + // Calls usually take a long time, so they make the specialization gain + // smaller. + Bonus -= CalleeFI->Metrics.NumCalls * InlineConstants::CallPenalty; + + return Bonus; +} + +// ConstantFunctionBonus - Figure out how much of a bonus we can get for +// possibly devirtualizing a function. We'll subtract the size of the function +// we may wish to inline from the indirect call bonus providing a limit on +// growth. Leave an upper limit of 0 for the bonus - we don't want to penalize +// inlining because we decide we don't want to give a bonus for +// devirtualizing. +int InlineCostAnalyzer::ConstantFunctionBonus(CallSite CS, Constant *C) { + + // This could just be NULL. + if (!C) return 0; + + Function *F = dyn_cast(C); + if (!F) return 0; + + int Bonus = InlineConstants::IndirectCallBonus + getInlineSize(CS, F); + return (Bonus > 0) ? 0 : Bonus; +} + +// CountBonusForConstant - Figure out an approximation for how much per-call +// performance boost we can expect if the specified value is constant. +int InlineCostAnalyzer::CountBonusForConstant(Value *V, Constant *C) { + unsigned Bonus = 0; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + User *U = *UI; + if (CallInst *CI = dyn_cast(U)) { + // Turning an indirect call into a direct call is a BIG win + if (CI->getCalledValue() == V) + Bonus += ConstantFunctionBonus(CallSite(CI), C); + } else if (InvokeInst *II = dyn_cast(U)) { + // Turning an indirect call into a direct call is a BIG win + if (II->getCalledValue() == V) + Bonus += ConstantFunctionBonus(CallSite(II), C); + } + // FIXME: Eliminating conditional branches and switches should + // also yield a per-call performance boost. + else { + // Figure out the bonuses that wll accrue due to simple constant + // propagation. + Instruction &Inst = cast(*U); + + // We can't constant propagate instructions which have effects or + // read memory. + // + // FIXME: It would be nice to capture the fact that a load from a + // pointer-to-constant-global is actually a *really* good thing to zap. + // Unfortunately, we don't know the pointer that may get propagated here, + // so we can't make this decision. + if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() || + isa(Inst)) + continue; + + bool AllOperandsConstant = true; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) + if (!isa(Inst.getOperand(i)) && Inst.getOperand(i) != V) { + AllOperandsConstant = false; + break; + } + + if (AllOperandsConstant) + Bonus += CountBonusForConstant(&Inst); + } + } + + return Bonus; +} + +int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) { + // Get information about the callee. + FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI->Metrics.NumBlocks == 0) + CalleeFI->analyzeFunction(Callee); + + // InlineCost - This value measures how good of an inline candidate this call + // site is to inline. A lower inline cost make is more likely for the call to + // be inlined. This value may go negative. + // + int InlineCost = 0; + + // Compute any size reductions we can expect due to arguments being passed into + // the function. + // + unsigned ArgNo = 0; + CallSite::arg_iterator I = CS.arg_begin(); + for (Function::arg_iterator FI = Callee->arg_begin(), FE = Callee->arg_end(); + FI != FE; ++I, ++FI, ++ArgNo) { + + // If an alloca is passed in, inlining this function is likely to allow + // significant future optimization possibilities (like scalar promotion, and + // scalarization), so encourage the inlining of the function. + // + if (isa(I)) + InlineCost -= CalleeFI->ArgumentWeights[ArgNo].AllocaWeight; + + // If this is a constant being passed into the function, use the argument + // weights calculated for the callee to determine how much will be folded + // away with this information. + else if (isa(I)) + InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight; + } + + // Each argument passed in has a cost at both the caller and the callee + // sides. Measurements show that each argument costs about the same as an + // instruction. + InlineCost -= (CS.arg_size() * InlineConstants::InstrCost); + + // Now that we have considered all of the factors that make the call site more + // likely to be inlined, look at factors that make us not want to inline it. + + // Calls usually take a long time, so they make the inlining gain smaller. + InlineCost += CalleeFI->Metrics.NumCalls * InlineConstants::CallPenalty; + + // Look at the size of the callee. Each instruction counts as 5. + InlineCost += CalleeFI->Metrics.NumInsts*InlineConstants::InstrCost; + + return InlineCost; +} + +int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) { + // Get information about the callee. + FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI->Metrics.NumBlocks == 0) + CalleeFI->analyzeFunction(Callee); + + bool isDirectCall = CS.getCalledFunction() == Callee; + Instruction *TheCall = CS.getInstruction(); + int Bonus = 0; + + // If there is only one call of the function, and it has internal linkage, + // make it almost guaranteed to be inlined. + // + if (Callee->hasLocalLinkage() && Callee->hasOneUse() && isDirectCall) + Bonus += InlineConstants::LastCallToStaticBonus; + + // If the instruction after the call, or if the normal destination of the + // invoke is an unreachable instruction, the function is noreturn. As such, + // there is little point in inlining this. + if (InvokeInst *II = dyn_cast(TheCall)) { + if (isa(II->getNormalDest()->begin())) + Bonus += InlineConstants::NoreturnPenalty; + } else if (isa(++BasicBlock::iterator(TheCall))) + Bonus += InlineConstants::NoreturnPenalty; + + // If this function uses the coldcc calling convention, prefer not to inline + // it. + if (Callee->getCallingConv() == CallingConv::Cold) + Bonus += InlineConstants::ColdccPenalty; + + // Add to the inline quality for properties that make the call valuable to + // inline. This includes factors that indicate that the result of inlining + // the function will be optimizable. Currently this just looks at arguments + // passed into the function. + // + CallSite::arg_iterator I = CS.arg_begin(); + for (Function::arg_iterator FI = Callee->arg_begin(), FE = Callee->arg_end(); + FI != FE; ++I, ++FI) + // Compute any constant bonus due to inlining we want to give here. + if (isa(I)) + Bonus += CountBonusForConstant(FI, cast(I)); + + return Bonus; +} + +// getInlineCost - The heuristic used to determine if we should inline the +// function call or not. +// +InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, + SmallPtrSet &NeverInline) { + return getInlineCost(CS, CS.getCalledFunction(), NeverInline); +} + +InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, + Function *Callee, + SmallPtrSet &NeverInline) { + Instruction *TheCall = CS.getInstruction(); + Function *Caller = TheCall->getParent()->getParent(); + + // Don't inline functions which can be redefined at link-time to mean + // something else. Don't inline functions marked noinline or call sites + // marked noinline. + if (Callee->mayBeOverridden() || + Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee) || + CS.isNoInline()) + return llvm::InlineCost::getNever(); + + // Get information about the callee. + FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI->Metrics.NumBlocks == 0) + CalleeFI->analyzeFunction(Callee); + + // If we should never inline this, return a huge cost. + if (CalleeFI->NeverInline()) + return InlineCost::getNever(); + + // FIXME: It would be nice to kill off CalleeFI->NeverInline. Then we + // could move this up and avoid computing the FunctionInfo for + // things we are going to just return always inline for. This + // requires handling setjmp somewhere else, however. + if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline)) + return InlineCost::getAlways(); + + if (CalleeFI->Metrics.usesDynamicAlloca) { + // Get infomation about the caller. + FunctionInfo &CallerFI = CachedFunctionInfo[Caller]; + + // If we haven't calculated this information yet, do so now. + if (CallerFI.Metrics.NumBlocks == 0) { + CallerFI.analyzeFunction(Caller); + + // Recompute the CalleeFI pointer, getting Caller could have invalidated + // it. + CalleeFI = &CachedFunctionInfo[Callee]; + } + + // Don't inline a callee with dynamic alloca into a caller without them. + // Functions containing dynamic alloca's are inefficient in various ways; + // don't create more inefficiency. + if (!CallerFI.Metrics.usesDynamicAlloca) + return InlineCost::getNever(); + } + + // InlineCost - This value measures how good of an inline candidate this call + // site is to inline. A lower inline cost make is more likely for the call to + // be inlined. This value may go negative due to the fact that bonuses + // are negative numbers. + // + int InlineCost = getInlineSize(CS, Callee) + getInlineBonuses(CS, Callee); + return llvm::InlineCost::get(InlineCost); +} + +// getSpecializationCost - The heuristic used to determine the code-size +// impact of creating a specialized version of Callee with argument +// SpecializedArgNo replaced by a constant. +InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee, + SmallVectorImpl &SpecializedArgNos) +{ + // Don't specialize functions which can be redefined at link-time to mean + // something else. + if (Callee->mayBeOverridden()) + return llvm::InlineCost::getNever(); + + // Get information about the callee. + FunctionInfo *CalleeFI = &CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI->Metrics.NumBlocks == 0) + CalleeFI->analyzeFunction(Callee); + + int Cost = 0; + + // Look at the orginal size of the callee. Each instruction counts as 5. + Cost += CalleeFI->Metrics.NumInsts * InlineConstants::InstrCost; + + // Offset that with the amount of code that can be constant-folded + // away with the given arguments replaced by constants. + for (SmallVectorImpl::iterator an = SpecializedArgNos.begin(), + ae = SpecializedArgNos.end(); an != ae; ++an) + Cost -= CalleeFI->ArgumentWeights[*an].ConstantWeight; + + return llvm::InlineCost::get(Cost); +} + +// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a +// higher threshold to determine if the function call should be inlined. +float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) { + Function *Callee = CS.getCalledFunction(); + + // Get information about the callee. + FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; + + // If we haven't calculated this information yet, do so now. + if (CalleeFI.Metrics.NumBlocks == 0) + CalleeFI.analyzeFunction(Callee); + + float Factor = 1.0f; + // Single BB functions are often written to be inlined. + if (CalleeFI.Metrics.NumBlocks == 1) + Factor += 0.5f; + + // Be more aggressive if the function contains a good chunk (if it mades up + // at least 10% of the instructions) of vector instructions. + if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/2) + Factor += 2.0f; + else if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/10) + Factor += 1.5f; + return Factor; +} + +/// growCachedCostInfo - update the cached cost info for Caller after Callee has +/// been inlined. +void +InlineCostAnalyzer::growCachedCostInfo(Function *Caller, Function *Callee) { + CodeMetrics &CallerMetrics = CachedFunctionInfo[Caller].Metrics; + + // For small functions we prefer to recalculate the cost for better accuracy. + if (CallerMetrics.NumBlocks < 10 || CallerMetrics.NumInsts < 1000) { + resetCachedCostInfo(Caller); + return; + } + + // For large functions, we can save a lot of computation time by skipping + // recalculations. + if (CallerMetrics.NumCalls > 0) + --CallerMetrics.NumCalls; + + if (Callee == 0) return; + + CodeMetrics &CalleeMetrics = CachedFunctionInfo[Callee].Metrics; + + // If we don't have metrics for the callee, don't recalculate them just to + // update an approximation in the caller. Instead, just recalculate the + // caller info from scratch. + if (CalleeMetrics.NumBlocks == 0) { + resetCachedCostInfo(Caller); + return; + } + + // Since CalleeMetrics were already calculated, we know that the CallerMetrics + // reference isn't invalidated: both were in the DenseMap. + CallerMetrics.usesDynamicAlloca |= CalleeMetrics.usesDynamicAlloca; + + // FIXME: If any of these three are true for the callee, the callee was + // not inlined into the caller, so I think they're redundant here. + CallerMetrics.callsSetJmp |= CalleeMetrics.callsSetJmp; + CallerMetrics.isRecursive |= CalleeMetrics.isRecursive; + CallerMetrics.containsIndirectBr |= CalleeMetrics.containsIndirectBr; + + CallerMetrics.NumInsts += CalleeMetrics.NumInsts; + CallerMetrics.NumBlocks += CalleeMetrics.NumBlocks; + CallerMetrics.NumCalls += CalleeMetrics.NumCalls; + CallerMetrics.NumVectorInsts += CalleeMetrics.NumVectorInsts; + CallerMetrics.NumRets += CalleeMetrics.NumRets; + + // analyzeBasicBlock counts each function argument as an inst. + if (CallerMetrics.NumInsts >= Callee->arg_size()) + CallerMetrics.NumInsts -= Callee->arg_size(); + else + CallerMetrics.NumInsts = 0; + + // We are not updating the argument weights. We have already determined that + // Caller is a fairly large function, so we accept the loss of precision. +} + +/// clear - empty the cache of inline costs +void InlineCostAnalyzer::clear() { + CachedFunctionInfo.clear(); +} diff --git a/final/lib/Analysis/InstCount.cpp b/final/lib/Analysis/InstCount.cpp new file mode 100644 index 00000000000..3b385d26ba3 --- /dev/null +++ b/final/lib/Analysis/InstCount.cpp @@ -0,0 +1,87 @@ +//===-- InstCount.cpp - Collects the count of all instructions ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass collects the count of all instructions and reports them +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instcount" +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(TotalInsts , "Number of instructions (of all types)"); +STATISTIC(TotalBlocks, "Number of basic blocks"); +STATISTIC(TotalFuncs , "Number of non-external functions"); +STATISTIC(TotalMemInst, "Number of memory instructions"); + +#define HANDLE_INST(N, OPCODE, CLASS) \ + STATISTIC(Num ## OPCODE ## Inst, "Number of " #OPCODE " insts"); + +#include "llvm/Instruction.def" + + +namespace { + class InstCount : public FunctionPass, public InstVisitor { + friend class InstVisitor; + + void visitFunction (Function &F) { ++TotalFuncs; } + void visitBasicBlock(BasicBlock &BB) { ++TotalBlocks; } + +#define HANDLE_INST(N, OPCODE, CLASS) \ + void visit##OPCODE(CLASS &) { ++Num##OPCODE##Inst; ++TotalInsts; } + +#include "llvm/Instruction.def" + + void visitInstruction(Instruction &I) { + errs() << "Instruction Count does not know about " << I; + llvm_unreachable(0); + } + public: + static char ID; // Pass identification, replacement for typeid + InstCount() : FunctionPass(ID) { + initializeInstCountPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + virtual void print(raw_ostream &O, const Module *M) const {} + + }; +} + +char InstCount::ID = 0; +INITIALIZE_PASS(InstCount, "instcount", + "Counts the various types of Instructions", false, true) + +FunctionPass *llvm::createInstCountPass() { return new InstCount(); } + +// InstCount::run - This is the main Analysis entry point for a +// function. +// +bool InstCount::runOnFunction(Function &F) { + unsigned StartMemInsts = + NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + + NumInvokeInst + NumAllocaInst; + visit(F); + unsigned EndMemInsts = + NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst + + NumInvokeInst + NumAllocaInst; + TotalMemInst += EndMemInsts-StartMemInsts; + return false; +} diff --git a/final/lib/Analysis/InstructionSimplify.cpp b/final/lib/Analysis/InstructionSimplify.cpp new file mode 100644 index 00000000000..48edc5ceaca --- /dev/null +++ b/final/lib/Analysis/InstructionSimplify.cpp @@ -0,0 +1,2170 @@ +//===- InstructionSimplify.cpp - Fold instruction operands ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements routines for folding instructions into simpler forms +// that do not require creating new instructions. This does constant folding +// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either +// returning a constant ("and i32 %x, 0" -> "0") or an already existing value +// ("and i32 %x, %x" -> "%x"). All operands are assumed to have already been +// simplified: This is usually true and assuming it simplifies the logic (if +// they have not been simplified then results are correct but maybe suboptimal). +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instsimplify" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/PatternMatch.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; +using namespace llvm::PatternMatch; + +enum { RecursionLimit = 3 }; + +STATISTIC(NumExpand, "Number of expansions"); +STATISTIC(NumFactor , "Number of factorizations"); +STATISTIC(NumReassoc, "Number of reassociations"); + +static Value *SimplifyAndInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); +static Value *SimplifyBinOp(unsigned, Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); +static Value *SimplifyCmpInst(unsigned, Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); +static Value *SimplifyOrInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); +static Value *SimplifyXorInst(Value *, Value *, const TargetData *, + const DominatorTree *, unsigned); + +/// ValueDominatesPHI - Does the given value dominate the specified phi node? +static bool ValueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) { + Instruction *I = dyn_cast(V); + if (!I) + // Arguments and constants dominate all instructions. + return true; + + // If we have a DominatorTree then do a precise test. + if (DT) + return DT->dominates(I, P); + + // Otherwise, if the instruction is in the entry block, and is not an invoke, + // then it obviously dominates all phi nodes. + if (I->getParent() == &I->getParent()->getParent()->getEntryBlock() && + !isa(I)) + return true; + + return false; +} + +/// ExpandBinOp - Simplify "A op (B op' C)" by distributing op over op', turning +/// it into "(A op B) op' (A op C)". Here "op" is given by Opcode and "op'" is +/// given by OpcodeToExpand, while "A" corresponds to LHS and "B op' C" to RHS. +/// Also performs the transform "(A op' B) op C" -> "(A op C) op' (B op C)". +/// Returns the simplified value, or null if no simplification was performed. +static Value *ExpandBinOp(unsigned Opcode, Value *LHS, Value *RHS, + unsigned OpcToExpand, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + Instruction::BinaryOps OpcodeToExpand = (Instruction::BinaryOps)OpcToExpand; + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + // Check whether the expression has the form "(A op' B) op C". + if (BinaryOperator *Op0 = dyn_cast(LHS)) + if (Op0->getOpcode() == OpcodeToExpand) { + // It does! Try turning it into "(A op C) op' (B op C)". + Value *A = Op0->getOperand(0), *B = Op0->getOperand(1), *C = RHS; + // Do "A op C" and "B op C" both simplify? + if (Value *L = SimplifyBinOp(Opcode, A, C, TD, DT, MaxRecurse)) + if (Value *R = SimplifyBinOp(Opcode, B, C, TD, DT, MaxRecurse)) { + // They do! Return "L op' R" if it simplifies or is already available. + // If "L op' R" equals "A op' B" then "L op' R" is just the LHS. + if ((L == A && R == B) || (Instruction::isCommutative(OpcodeToExpand) + && L == B && R == A)) { + ++NumExpand; + return LHS; + } + // Otherwise return "L op' R" if it simplifies. + if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, TD, DT, + MaxRecurse)) { + ++NumExpand; + return V; + } + } + } + + // Check whether the expression has the form "A op (B op' C)". + if (BinaryOperator *Op1 = dyn_cast(RHS)) + if (Op1->getOpcode() == OpcodeToExpand) { + // It does! Try turning it into "(A op B) op' (A op C)". + Value *A = LHS, *B = Op1->getOperand(0), *C = Op1->getOperand(1); + // Do "A op B" and "A op C" both simplify? + if (Value *L = SimplifyBinOp(Opcode, A, B, TD, DT, MaxRecurse)) + if (Value *R = SimplifyBinOp(Opcode, A, C, TD, DT, MaxRecurse)) { + // They do! Return "L op' R" if it simplifies or is already available. + // If "L op' R" equals "B op' C" then "L op' R" is just the RHS. + if ((L == B && R == C) || (Instruction::isCommutative(OpcodeToExpand) + && L == C && R == B)) { + ++NumExpand; + return RHS; + } + // Otherwise return "L op' R" if it simplifies. + if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, TD, DT, + MaxRecurse)) { + ++NumExpand; + return V; + } + } + } + + return 0; +} + +/// FactorizeBinOp - Simplify "LHS Opcode RHS" by factorizing out a common term +/// using the operation OpCodeToExtract. For example, when Opcode is Add and +/// OpCodeToExtract is Mul then this tries to turn "(A*B)+(A*C)" into "A*(B+C)". +/// Returns the simplified value, or null if no simplification was performed. +static Value *FactorizeBinOp(unsigned Opcode, Value *LHS, Value *RHS, + unsigned OpcToExtract, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + Instruction::BinaryOps OpcodeToExtract = (Instruction::BinaryOps)OpcToExtract; + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + BinaryOperator *Op0 = dyn_cast(LHS); + BinaryOperator *Op1 = dyn_cast(RHS); + + if (!Op0 || Op0->getOpcode() != OpcodeToExtract || + !Op1 || Op1->getOpcode() != OpcodeToExtract) + return 0; + + // The expression has the form "(A op' B) op (C op' D)". + Value *A = Op0->getOperand(0), *B = Op0->getOperand(1); + Value *C = Op1->getOperand(0), *D = Op1->getOperand(1); + + // Use left distributivity, i.e. "X op' (Y op Z) = (X op' Y) op (X op' Z)". + // Does the instruction have the form "(A op' B) op (A op' D)" or, in the + // commutative case, "(A op' B) op (C op' A)"? + if (A == C || (Instruction::isCommutative(OpcodeToExtract) && A == D)) { + Value *DD = A == C ? D : C; + // Form "A op' (B op DD)" if it simplifies completely. + // Does "B op DD" simplify? + if (Value *V = SimplifyBinOp(Opcode, B, DD, TD, DT, MaxRecurse)) { + // It does! Return "A op' V" if it simplifies or is already available. + // If V equals B then "A op' V" is just the LHS. If V equals DD then + // "A op' V" is just the RHS. + if (V == B || V == DD) { + ++NumFactor; + return V == B ? LHS : RHS; + } + // Otherwise return "A op' V" if it simplifies. + if (Value *W = SimplifyBinOp(OpcodeToExtract, A, V, TD, DT, MaxRecurse)) { + ++NumFactor; + return W; + } + } + } + + // Use right distributivity, i.e. "(X op Y) op' Z = (X op' Z) op (Y op' Z)". + // Does the instruction have the form "(A op' B) op (C op' B)" or, in the + // commutative case, "(A op' B) op (B op' D)"? + if (B == D || (Instruction::isCommutative(OpcodeToExtract) && B == C)) { + Value *CC = B == D ? C : D; + // Form "(A op CC) op' B" if it simplifies completely.. + // Does "A op CC" simplify? + if (Value *V = SimplifyBinOp(Opcode, A, CC, TD, DT, MaxRecurse)) { + // It does! Return "V op' B" if it simplifies or is already available. + // If V equals A then "V op' B" is just the LHS. If V equals CC then + // "V op' B" is just the RHS. + if (V == A || V == CC) { + ++NumFactor; + return V == A ? LHS : RHS; + } + // Otherwise return "V op' B" if it simplifies. + if (Value *W = SimplifyBinOp(OpcodeToExtract, V, B, TD, DT, MaxRecurse)) { + ++NumFactor; + return W; + } + } + } + + return 0; +} + +/// SimplifyAssociativeBinOp - Generic simplifications for associative binary +/// operations. Returns the simpler value, or null if none was found. +static Value *SimplifyAssociativeBinOp(unsigned Opc, Value *LHS, Value *RHS, + const TargetData *TD, + const DominatorTree *DT, + unsigned MaxRecurse) { + Instruction::BinaryOps Opcode = (Instruction::BinaryOps)Opc; + assert(Instruction::isAssociative(Opcode) && "Not an associative operation!"); + + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + BinaryOperator *Op0 = dyn_cast(LHS); + BinaryOperator *Op1 = dyn_cast(RHS); + + // Transform: "(A op B) op C" ==> "A op (B op C)" if it simplifies completely. + if (Op0 && Op0->getOpcode() == Opcode) { + Value *A = Op0->getOperand(0); + Value *B = Op0->getOperand(1); + Value *C = RHS; + + // Does "B op C" simplify? + if (Value *V = SimplifyBinOp(Opcode, B, C, TD, DT, MaxRecurse)) { + // It does! Return "A op V" if it simplifies or is already available. + // If V equals B then "A op V" is just the LHS. + if (V == B) return LHS; + // Otherwise return "A op V" if it simplifies. + if (Value *W = SimplifyBinOp(Opcode, A, V, TD, DT, MaxRecurse)) { + ++NumReassoc; + return W; + } + } + } + + // Transform: "A op (B op C)" ==> "(A op B) op C" if it simplifies completely. + if (Op1 && Op1->getOpcode() == Opcode) { + Value *A = LHS; + Value *B = Op1->getOperand(0); + Value *C = Op1->getOperand(1); + + // Does "A op B" simplify? + if (Value *V = SimplifyBinOp(Opcode, A, B, TD, DT, MaxRecurse)) { + // It does! Return "V op C" if it simplifies or is already available. + // If V equals B then "V op C" is just the RHS. + if (V == B) return RHS; + // Otherwise return "V op C" if it simplifies. + if (Value *W = SimplifyBinOp(Opcode, V, C, TD, DT, MaxRecurse)) { + ++NumReassoc; + return W; + } + } + } + + // The remaining transforms require commutativity as well as associativity. + if (!Instruction::isCommutative(Opcode)) + return 0; + + // Transform: "(A op B) op C" ==> "(C op A) op B" if it simplifies completely. + if (Op0 && Op0->getOpcode() == Opcode) { + Value *A = Op0->getOperand(0); + Value *B = Op0->getOperand(1); + Value *C = RHS; + + // Does "C op A" simplify? + if (Value *V = SimplifyBinOp(Opcode, C, A, TD, DT, MaxRecurse)) { + // It does! Return "V op B" if it simplifies or is already available. + // If V equals A then "V op B" is just the LHS. + if (V == A) return LHS; + // Otherwise return "V op B" if it simplifies. + if (Value *W = SimplifyBinOp(Opcode, V, B, TD, DT, MaxRecurse)) { + ++NumReassoc; + return W; + } + } + } + + // Transform: "A op (B op C)" ==> "B op (C op A)" if it simplifies completely. + if (Op1 && Op1->getOpcode() == Opcode) { + Value *A = LHS; + Value *B = Op1->getOperand(0); + Value *C = Op1->getOperand(1); + + // Does "C op A" simplify? + if (Value *V = SimplifyBinOp(Opcode, C, A, TD, DT, MaxRecurse)) { + // It does! Return "B op V" if it simplifies or is already available. + // If V equals C then "B op V" is just the RHS. + if (V == C) return RHS; + // Otherwise return "B op V" if it simplifies. + if (Value *W = SimplifyBinOp(Opcode, B, V, TD, DT, MaxRecurse)) { + ++NumReassoc; + return W; + } + } + } + + return 0; +} + +/// ThreadBinOpOverSelect - In the case of a binary operation with a select +/// instruction as an operand, try to simplify the binop by seeing whether +/// evaluating it on both branches of the select results in the same value. +/// Returns the common value if so, otherwise returns null. +static Value *ThreadBinOpOverSelect(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD, + const DominatorTree *DT, + unsigned MaxRecurse) { + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + SelectInst *SI; + if (isa(LHS)) { + SI = cast(LHS); + } else { + assert(isa(RHS) && "No select instruction operand!"); + SI = cast(RHS); + } + + // Evaluate the BinOp on the true and false branches of the select. + Value *TV; + Value *FV; + if (SI == LHS) { + TV = SimplifyBinOp(Opcode, SI->getTrueValue(), RHS, TD, DT, MaxRecurse); + FV = SimplifyBinOp(Opcode, SI->getFalseValue(), RHS, TD, DT, MaxRecurse); + } else { + TV = SimplifyBinOp(Opcode, LHS, SI->getTrueValue(), TD, DT, MaxRecurse); + FV = SimplifyBinOp(Opcode, LHS, SI->getFalseValue(), TD, DT, MaxRecurse); + } + + // If they simplified to the same value, then return the common value. + // If they both failed to simplify then return null. + if (TV == FV) + return TV; + + // If one branch simplified to undef, return the other one. + if (TV && isa(TV)) + return FV; + if (FV && isa(FV)) + return TV; + + // If applying the operation did not change the true and false select values, + // then the result of the binop is the select itself. + if (TV == SI->getTrueValue() && FV == SI->getFalseValue()) + return SI; + + // If one branch simplified and the other did not, and the simplified + // value is equal to the unsimplified one, return the simplified value. + // For example, select (cond, X, X & Z) & Z -> X & Z. + if ((FV && !TV) || (TV && !FV)) { + // Check that the simplified value has the form "X op Y" where "op" is the + // same as the original operation. + Instruction *Simplified = dyn_cast(FV ? FV : TV); + if (Simplified && Simplified->getOpcode() == Opcode) { + // The value that didn't simplify is "UnsimplifiedLHS op UnsimplifiedRHS". + // We already know that "op" is the same as for the simplified value. See + // if the operands match too. If so, return the simplified value. + Value *UnsimplifiedBranch = FV ? SI->getTrueValue() : SI->getFalseValue(); + Value *UnsimplifiedLHS = SI == LHS ? UnsimplifiedBranch : LHS; + Value *UnsimplifiedRHS = SI == LHS ? RHS : UnsimplifiedBranch; + if (Simplified->getOperand(0) == UnsimplifiedLHS && + Simplified->getOperand(1) == UnsimplifiedRHS) + return Simplified; + if (Simplified->isCommutative() && + Simplified->getOperand(1) == UnsimplifiedLHS && + Simplified->getOperand(0) == UnsimplifiedRHS) + return Simplified; + } + } + + return 0; +} + +/// ThreadCmpOverSelect - In the case of a comparison with a select instruction, +/// try to simplify the comparison by seeing whether both branches of the select +/// result in the same value. Returns the common value if so, otherwise returns +/// null. +static Value *ThreadCmpOverSelect(CmpInst::Predicate Pred, Value *LHS, + Value *RHS, const TargetData *TD, + const DominatorTree *DT, + unsigned MaxRecurse) { + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + // Make sure the select is on the LHS. + if (!isa(LHS)) { + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + assert(isa(LHS) && "Not comparing with a select instruction!"); + SelectInst *SI = cast(LHS); + + // Now that we have "cmp select(Cond, TV, FV), RHS", analyse it. + // Does "cmp TV, RHS" simplify? + if (Value *TCmp = SimplifyCmpInst(Pred, SI->getTrueValue(), RHS, TD, DT, + MaxRecurse)) { + // It does! Does "cmp FV, RHS" simplify? + if (Value *FCmp = SimplifyCmpInst(Pred, SI->getFalseValue(), RHS, TD, DT, + MaxRecurse)) { + // It does! If they simplified to the same value, then use it as the + // result of the original comparison. + if (TCmp == FCmp) + return TCmp; + Value *Cond = SI->getCondition(); + // If the false value simplified to false, then the result of the compare + // is equal to "Cond && TCmp". This also catches the case when the false + // value simplified to false and the true value to true, returning "Cond". + if (match(FCmp, m_Zero())) + if (Value *V = SimplifyAndInst(Cond, TCmp, TD, DT, MaxRecurse)) + return V; + // If the true value simplified to true, then the result of the compare + // is equal to "Cond || FCmp". + if (match(TCmp, m_One())) + if (Value *V = SimplifyOrInst(Cond, FCmp, TD, DT, MaxRecurse)) + return V; + // Finally, if the false value simplified to true and the true value to + // false, then the result of the compare is equal to "!Cond". + if (match(FCmp, m_One()) && match(TCmp, m_Zero())) + if (Value *V = + SimplifyXorInst(Cond, Constant::getAllOnesValue(Cond->getType()), + TD, DT, MaxRecurse)) + return V; + } + } + + return 0; +} + +/// ThreadBinOpOverPHI - In the case of a binary operation with an operand that +/// is a PHI instruction, try to simplify the binop by seeing whether evaluating +/// it on the incoming phi values yields the same result for every value. If so +/// returns the common value, otherwise returns null. +static Value *ThreadBinOpOverPHI(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + PHINode *PI; + if (isa(LHS)) { + PI = cast(LHS); + // Bail out if RHS and the phi may be mutually interdependent due to a loop. + if (!ValueDominatesPHI(RHS, PI, DT)) + return 0; + } else { + assert(isa(RHS) && "No PHI instruction operand!"); + PI = cast(RHS); + // Bail out if LHS and the phi may be mutually interdependent due to a loop. + if (!ValueDominatesPHI(LHS, PI, DT)) + return 0; + } + + // Evaluate the BinOp on the incoming phi values. + Value *CommonValue = 0; + for (unsigned i = 0, e = PI->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = PI->getIncomingValue(i); + // If the incoming value is the phi node itself, it can safely be skipped. + if (Incoming == PI) continue; + Value *V = PI == LHS ? + SimplifyBinOp(Opcode, Incoming, RHS, TD, DT, MaxRecurse) : + SimplifyBinOp(Opcode, LHS, Incoming, TD, DT, MaxRecurse); + // If the operation failed to simplify, or simplified to a different value + // to previously, then give up. + if (!V || (CommonValue && V != CommonValue)) + return 0; + CommonValue = V; + } + + return CommonValue; +} + +/// ThreadCmpOverPHI - In the case of a comparison with a PHI instruction, try +/// try to simplify the comparison by seeing whether comparing with all of the +/// incoming phi values yields the same result every time. If so returns the +/// common result, otherwise returns null. +static Value *ThreadCmpOverPHI(CmpInst::Predicate Pred, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + // Recursion is always used, so bail out at once if we already hit the limit. + if (!MaxRecurse--) + return 0; + + // Make sure the phi is on the LHS. + if (!isa(LHS)) { + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + assert(isa(LHS) && "Not comparing with a phi instruction!"); + PHINode *PI = cast(LHS); + + // Bail out if RHS and the phi may be mutually interdependent due to a loop. + if (!ValueDominatesPHI(RHS, PI, DT)) + return 0; + + // Evaluate the BinOp on the incoming phi values. + Value *CommonValue = 0; + for (unsigned i = 0, e = PI->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = PI->getIncomingValue(i); + // If the incoming value is the phi node itself, it can safely be skipped. + if (Incoming == PI) continue; + Value *V = SimplifyCmpInst(Pred, Incoming, RHS, TD, DT, MaxRecurse); + // If the operation failed to simplify, or simplified to a different value + // to previously, then give up. + if (!V || (CommonValue && V != CommonValue)) + return 0; + CommonValue = V; + } + + return CommonValue; +} + +/// SimplifyAddInst - Given operands for an Add, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Add, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X + undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + // X + 0 -> X + if (match(Op1, m_Zero())) + return Op0; + + // X + (Y - X) -> Y + // (Y - X) + X -> Y + // Eg: X + -X -> 0 + Value *Y = 0; + if (match(Op1, m_Sub(m_Value(Y), m_Specific(Op0))) || + match(Op0, m_Sub(m_Value(Y), m_Specific(Op1)))) + return Y; + + // X + ~X -> -1 since ~X = -X-1 + if (match(Op0, m_Not(m_Specific(Op1))) || + match(Op1, m_Not(m_Specific(Op0)))) + return Constant::getAllOnesValue(Op0->getType()); + + /// i1 add -> xor. + if (MaxRecurse && Op0->getType()->isIntegerTy(1)) + if (Value *V = SimplifyXorInst(Op0, Op1, TD, DT, MaxRecurse-1)) + return V; + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::Add, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // Mul distributes over Add. Try some generic simplifications based on this. + if (Value *V = FactorizeBinOp(Instruction::Add, Op0, Op1, Instruction::Mul, + TD, DT, MaxRecurse)) + return V; + + // Threading Add over selects and phi nodes is pointless, so don't bother. + // Threading over the select in "A + select(cond, B, C)" means evaluating + // "A+B" and "A+C" and seeing if they are equal; but they are equal if and + // only if B and C are equal. If B and C are equal then (since we assume + // that operands have already been simplified) "select(cond, B, C)" should + // have been simplified to the common value of B and C already. Analysing + // "A+B" and "A+C" thus gains nothing, but costs compile time. Similarly + // for threading over phi nodes. + + return 0; +} + +Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyAddInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit); +} + +/// SimplifySubInst - Given operands for a Sub, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Sub, CLHS->getType(), + Ops, 2, TD); + } + + // X - undef -> undef + // undef - X -> undef + if (match(Op0, m_Undef()) || match(Op1, m_Undef())) + return UndefValue::get(Op0->getType()); + + // X - 0 -> X + if (match(Op1, m_Zero())) + return Op0; + + // X - X -> 0 + if (Op0 == Op1) + return Constant::getNullValue(Op0->getType()); + + // (X*2) - X -> X + // (X<<1) - X -> X + Value *X = 0; + if (match(Op0, m_Mul(m_Specific(Op1), m_ConstantInt<2>())) || + match(Op0, m_Shl(m_Specific(Op1), m_One()))) + return Op1; + + // (X + Y) - Z -> X + (Y - Z) or Y + (X - Z) if everything simplifies. + // For example, (X + Y) - Y -> X; (Y + X) - Y -> X + Value *Y = 0, *Z = Op1; + if (MaxRecurse && match(Op0, m_Add(m_Value(X), m_Value(Y)))) { // (X + Y) - Z + // See if "V === Y - Z" simplifies. + if (Value *V = SimplifyBinOp(Instruction::Sub, Y, Z, TD, DT, MaxRecurse-1)) + // It does! Now see if "X + V" simplifies. + if (Value *W = SimplifyBinOp(Instruction::Add, X, V, TD, DT, + MaxRecurse-1)) { + // It does, we successfully reassociated! + ++NumReassoc; + return W; + } + // See if "V === X - Z" simplifies. + if (Value *V = SimplifyBinOp(Instruction::Sub, X, Z, TD, DT, MaxRecurse-1)) + // It does! Now see if "Y + V" simplifies. + if (Value *W = SimplifyBinOp(Instruction::Add, Y, V, TD, DT, + MaxRecurse-1)) { + // It does, we successfully reassociated! + ++NumReassoc; + return W; + } + } + + // X - (Y + Z) -> (X - Y) - Z or (X - Z) - Y if everything simplifies. + // For example, X - (X + 1) -> -1 + X = Op0; + if (MaxRecurse && match(Op1, m_Add(m_Value(Y), m_Value(Z)))) { // X - (Y + Z) + // See if "V === X - Y" simplifies. + if (Value *V = SimplifyBinOp(Instruction::Sub, X, Y, TD, DT, MaxRecurse-1)) + // It does! Now see if "V - Z" simplifies. + if (Value *W = SimplifyBinOp(Instruction::Sub, V, Z, TD, DT, + MaxRecurse-1)) { + // It does, we successfully reassociated! + ++NumReassoc; + return W; + } + // See if "V === X - Z" simplifies. + if (Value *V = SimplifyBinOp(Instruction::Sub, X, Z, TD, DT, MaxRecurse-1)) + // It does! Now see if "V - Y" simplifies. + if (Value *W = SimplifyBinOp(Instruction::Sub, V, Y, TD, DT, + MaxRecurse-1)) { + // It does, we successfully reassociated! + ++NumReassoc; + return W; + } + } + + // Z - (X - Y) -> (Z - X) + Y if everything simplifies. + // For example, X - (X - Y) -> Y. + Z = Op0; + if (MaxRecurse && match(Op1, m_Sub(m_Value(X), m_Value(Y)))) // Z - (X - Y) + // See if "V === Z - X" simplifies. + if (Value *V = SimplifyBinOp(Instruction::Sub, Z, X, TD, DT, MaxRecurse-1)) + // It does! Now see if "V + Y" simplifies. + if (Value *W = SimplifyBinOp(Instruction::Add, V, Y, TD, DT, + MaxRecurse-1)) { + // It does, we successfully reassociated! + ++NumReassoc; + return W; + } + + // Mul distributes over Sub. Try some generic simplifications based on this. + if (Value *V = FactorizeBinOp(Instruction::Sub, Op0, Op1, Instruction::Mul, + TD, DT, MaxRecurse)) + return V; + + // i1 sub -> xor. + if (MaxRecurse && Op0->getType()->isIntegerTy(1)) + if (Value *V = SimplifyXorInst(Op0, Op1, TD, DT, MaxRecurse-1)) + return V; + + // Threading Sub over selects and phi nodes is pointless, so don't bother. + // Threading over the select in "A - select(cond, B, C)" means evaluating + // "A-B" and "A-C" and seeing if they are equal; but they are equal if and + // only if B and C are equal. If B and C are equal then (since we assume + // that operands have already been simplified) "select(cond, B, C)" should + // have been simplified to the common value of B and C already. Analysing + // "A-B" and "A-C" thus gains nothing, but costs compile time. Similarly + // for threading over phi nodes. + + return 0; +} + +Value *llvm::SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifySubInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit); +} + +/// SimplifyMulInst - Given operands for a Mul, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Mul, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X * undef -> 0 + if (match(Op1, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // X * 0 -> 0 + if (match(Op1, m_Zero())) + return Op1; + + // X * 1 -> X + if (match(Op1, m_One())) + return Op0; + + // (X / Y) * Y -> X if the division is exact. + Value *X = 0, *Y = 0; + if ((match(Op0, m_IDiv(m_Value(X), m_Value(Y))) && Y == Op1) || // (X / Y) * Y + (match(Op1, m_IDiv(m_Value(X), m_Value(Y))) && Y == Op0)) { // Y * (X / Y) + BinaryOperator *Div = cast(Y == Op1 ? Op0 : Op1); + if (Div->isExact()) + return X; + } + + // i1 mul -> and. + if (MaxRecurse && Op0->getType()->isIntegerTy(1)) + if (Value *V = SimplifyAndInst(Op0, Op1, TD, DT, MaxRecurse-1)) + return V; + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // Mul distributes over Add. Try some generic simplifications based on this. + if (Value *V = ExpandBinOp(Instruction::Mul, Op0, Op1, Instruction::Add, + TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Instruction::Mul, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyMulInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyMulInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyDiv - Given operands for an SDiv or UDiv, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Constant *C0 = dyn_cast(Op0)) { + if (Constant *C1 = dyn_cast(Op1)) { + Constant *Ops[] = { C0, C1 }; + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + } + } + + bool isSigned = Opcode == Instruction::SDiv; + + // X / undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + // undef / X -> 0 + if (match(Op0, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // 0 / X -> 0, we don't need to preserve faults! + if (match(Op0, m_Zero())) + return Op0; + + // X / 1 -> X + if (match(Op1, m_One())) + return Op0; + + if (Op0->getType()->isIntegerTy(1)) + // It can't be division by zero, hence it must be division by one. + return Op0; + + // X / X -> 1 + if (Op0 == Op1) + return ConstantInt::get(Op0->getType(), 1); + + // (X * Y) / Y -> X if the multiplication does not overflow. + Value *X = 0, *Y = 0; + if (match(Op0, m_Mul(m_Value(X), m_Value(Y))) && (X == Op1 || Y == Op1)) { + if (Y != Op1) std::swap(X, Y); // Ensure expression is (X * Y) / Y, Y = Op1 + BinaryOperator *Mul = cast(Op0); + // If the Mul knows it does not overflow, then we are good to go. + if ((isSigned && Mul->hasNoSignedWrap()) || + (!isSigned && Mul->hasNoUnsignedWrap())) + return X; + // If X has the form X = A / Y then X * Y cannot overflow. + if (BinaryOperator *Div = dyn_cast(X)) + if (Div->getOpcode() == Opcode && Div->getOperand(1) == Y) + return X; + } + + // (X rem Y) / Y -> 0 + if ((isSigned && match(Op0, m_SRem(m_Value(), m_Specific(Op1)))) || + (!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1))))) + return Constant::getNullValue(Op0->getType()); + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +/// SimplifySDivInst - Given operands for an SDiv, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifySDivInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Value *V = SimplifyDiv(Instruction::SDiv, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifySDivInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifySDivInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyUDivInst - Given operands for a UDiv, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyUDivInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Value *V = SimplifyDiv(Instruction::UDiv, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyUDivInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyUDivInst(Op0, Op1, TD, DT, RecursionLimit); +} + +static Value *SimplifyFDivInst(Value *Op0, Value *Op1, const TargetData *, + const DominatorTree *, unsigned) { + // undef / X -> undef (the undef could be a snan). + if (match(Op0, m_Undef())) + return Op0; + + // X / undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + return 0; +} + +Value *llvm::SimplifyFDivInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyFDivInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyShift - Given operands for an Shl, LShr or AShr, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyShift(unsigned Opcode, Value *Op0, Value *Op1, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Constant *C0 = dyn_cast(Op0)) { + if (Constant *C1 = dyn_cast(Op1)) { + Constant *Ops[] = { C0, C1 }; + return ConstantFoldInstOperands(Opcode, C0->getType(), Ops, 2, TD); + } + } + + // 0 shift by X -> 0 + if (match(Op0, m_Zero())) + return Op0; + + // X shift by 0 -> X + if (match(Op1, m_Zero())) + return Op0; + + // X shift by undef -> undef because it may shift by the bitwidth. + if (match(Op1, m_Undef())) + return Op1; + + // Shifting by the bitwidth or more is undefined. + if (ConstantInt *CI = dyn_cast(Op1)) + if (CI->getValue().getLimitedValue() >= + Op0->getType()->getScalarSizeInBits()) + return UndefValue::get(Op0->getType()); + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Opcode, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +/// SimplifyShlInst - Given operands for an Shl, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Value *V = SimplifyShift(Instruction::Shl, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // undef << X -> 0 + if (match(Op0, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // (X >> A) << A -> X + Value *X; + if (match(Op0, m_Shr(m_Value(X), m_Specific(Op1))) && + cast(Op0)->isExact()) + return X; + return 0; +} + +Value *llvm::SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyShlInst(Op0, Op1, isNSW, isNUW, TD, DT, RecursionLimit); +} + +/// SimplifyLShrInst - Given operands for an LShr, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Value *V = SimplifyShift(Instruction::LShr, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // undef >>l X -> 0 + if (match(Op0, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // (X << A) >> A -> X + Value *X; + if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) && + cast(Op0)->hasNoUnsignedWrap()) + return X; + + return 0; +} + +Value *llvm::SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyLShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit); +} + +/// SimplifyAShrInst - Given operands for an AShr, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (Value *V = SimplifyShift(Instruction::AShr, Op0, Op1, TD, DT, MaxRecurse)) + return V; + + // all ones >>a X -> all ones + if (match(Op0, m_AllOnes())) + return Op0; + + // undef >>a X -> all ones + if (match(Op0, m_Undef())) + return Constant::getAllOnesValue(Op0->getType()); + + // (X << A) >> A -> X + Value *X; + if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) && + cast(Op0)->hasNoSignedWrap()) + return X; + + return 0; +} + +Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyAShrInst(Op0, Op1, isExact, TD, DT, RecursionLimit); +} + +/// SimplifyAndInst - Given operands for an And, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::And, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X & undef -> 0 + if (match(Op1, m_Undef())) + return Constant::getNullValue(Op0->getType()); + + // X & X = X + if (Op0 == Op1) + return Op0; + + // X & 0 = 0 + if (match(Op1, m_Zero())) + return Op1; + + // X & -1 = X + if (match(Op1, m_AllOnes())) + return Op0; + + // A & ~A = ~A & A = 0 + if (match(Op0, m_Not(m_Specific(Op1))) || + match(Op1, m_Not(m_Specific(Op0)))) + return Constant::getNullValue(Op0->getType()); + + // (A | ?) & A = A + Value *A = 0, *B = 0; + if (match(Op0, m_Or(m_Value(A), m_Value(B))) && + (A == Op1 || B == Op1)) + return Op1; + + // A & (A | ?) = A + if (match(Op1, m_Or(m_Value(A), m_Value(B))) && + (A == Op0 || B == Op0)) + return Op0; + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::And, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // And distributes over Or. Try some generic simplifications based on this. + if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Or, + TD, DT, MaxRecurse)) + return V; + + // And distributes over Xor. Try some generic simplifications based on this. + if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Xor, + TD, DT, MaxRecurse)) + return V; + + // Or distributes over And. Try some generic simplifications based on this. + if (Value *V = FactorizeBinOp(Instruction::And, Op0, Op1, Instruction::Or, + TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Instruction::And, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Instruction::And, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyAndInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyAndInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyOrInst - Given operands for an Or, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Or, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // X | undef -> -1 + if (match(Op1, m_Undef())) + return Constant::getAllOnesValue(Op0->getType()); + + // X | X = X + if (Op0 == Op1) + return Op0; + + // X | 0 = X + if (match(Op1, m_Zero())) + return Op0; + + // X | -1 = -1 + if (match(Op1, m_AllOnes())) + return Op1; + + // A | ~A = ~A | A = -1 + if (match(Op0, m_Not(m_Specific(Op1))) || + match(Op1, m_Not(m_Specific(Op0)))) + return Constant::getAllOnesValue(Op0->getType()); + + // (A & ?) | A = A + Value *A = 0, *B = 0; + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + (A == Op1 || B == Op1)) + return Op1; + + // A | (A & ?) = A + if (match(Op1, m_And(m_Value(A), m_Value(B))) && + (A == Op0 || B == Op0)) + return Op0; + + // ~(A & ?) | A = -1 + if (match(Op0, m_Not(m_And(m_Value(A), m_Value(B)))) && + (A == Op1 || B == Op1)) + return Constant::getAllOnesValue(Op1->getType()); + + // A | ~(A & ?) = -1 + if (match(Op1, m_Not(m_And(m_Value(A), m_Value(B)))) && + (A == Op0 || B == Op0)) + return Constant::getAllOnesValue(Op0->getType()); + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // Or distributes over And. Try some generic simplifications based on this. + if (Value *V = ExpandBinOp(Instruction::Or, Op0, Op1, Instruction::And, + TD, DT, MaxRecurse)) + return V; + + // And distributes over Or. Try some generic simplifications based on this. + if (Value *V = FactorizeBinOp(Instruction::Or, Op0, Op1, Instruction::And, + TD, DT, MaxRecurse)) + return V; + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverSelect(Instruction::Or, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(Op0) || isa(Op1)) + if (Value *V = ThreadBinOpOverPHI(Instruction::Or, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyOrInst(Op0, Op1, TD, DT, RecursionLimit); +} + +/// SimplifyXorInst - Given operands for a Xor, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT, unsigned MaxRecurse) { + if (Constant *CLHS = dyn_cast(Op0)) { + if (Constant *CRHS = dyn_cast(Op1)) { + Constant *Ops[] = { CLHS, CRHS }; + return ConstantFoldInstOperands(Instruction::Xor, CLHS->getType(), + Ops, 2, TD); + } + + // Canonicalize the constant to the RHS. + std::swap(Op0, Op1); + } + + // A ^ undef -> undef + if (match(Op1, m_Undef())) + return Op1; + + // A ^ 0 = A + if (match(Op1, m_Zero())) + return Op0; + + // A ^ A = 0 + if (Op0 == Op1) + return Constant::getNullValue(Op0->getType()); + + // A ^ ~A = ~A ^ A = -1 + if (match(Op0, m_Not(m_Specific(Op1))) || + match(Op1, m_Not(m_Specific(Op0)))) + return Constant::getAllOnesValue(Op0->getType()); + + // Try some generic simplifications for associative operations. + if (Value *V = SimplifyAssociativeBinOp(Instruction::Xor, Op0, Op1, TD, DT, + MaxRecurse)) + return V; + + // And distributes over Xor. Try some generic simplifications based on this. + if (Value *V = FactorizeBinOp(Instruction::Xor, Op0, Op1, Instruction::And, + TD, DT, MaxRecurse)) + return V; + + // Threading Xor over selects and phi nodes is pointless, so don't bother. + // Threading over the select in "A ^ select(cond, B, C)" means evaluating + // "A^B" and "A^C" and seeing if they are equal; but they are equal if and + // only if B and C are equal. If B and C are equal then (since we assume + // that operands have already been simplified) "select(cond, B, C)" should + // have been simplified to the common value of B and C already. Analysing + // "A^B" and "A^C" thus gains nothing, but costs compile time. Similarly + // for threading over phi nodes. + + return 0; +} + +Value *llvm::SimplifyXorInst(Value *Op0, Value *Op1, const TargetData *TD, + const DominatorTree *DT) { + return ::SimplifyXorInst(Op0, Op1, TD, DT, RecursionLimit); +} + +static const Type *GetCompareTy(Value *Op) { + return CmpInst::makeCmpResultType(Op->getType()); +} + +/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate; + assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!"); + + if (Constant *CLHS = dyn_cast(LHS)) { + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); + + // If we have a constant, make sure it is on the RHS. + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + + const Type *ITy = GetCompareTy(LHS); // The return type. + const Type *OpTy = LHS->getType(); // The operand type. + + // icmp X, X -> true/false + // X icmp undef -> true/false. For example, icmp ugt %X, undef -> false + // because X could be 0. + if (LHS == RHS || isa(RHS)) + return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); + + // Special case logic when the operands have i1 type. + if (OpTy->isIntegerTy(1) || (OpTy->isVectorTy() && + cast(OpTy)->getElementType()->isIntegerTy(1))) { + switch (Pred) { + default: break; + case ICmpInst::ICMP_EQ: + // X == 1 -> X + if (match(RHS, m_One())) + return LHS; + break; + case ICmpInst::ICMP_NE: + // X != 0 -> X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_UGT: + // X >u 0 -> X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_UGE: + // X >=u 1 -> X + if (match(RHS, m_One())) + return LHS; + break; + case ICmpInst::ICMP_SLT: + // X X + if (match(RHS, m_Zero())) + return LHS; + break; + case ICmpInst::ICMP_SLE: + // X <=s -1 -> X + if (match(RHS, m_One())) + return LHS; + break; + } + } + + // icmp , - Different stack variables have + // different addresses, and what's more the address of a stack variable is + // never null or equal to the address of a global. Note that generalizing + // to the case where LHS is a global variable address or null is pointless, + // since if both LHS and RHS are constants then we already constant folded + // the compare, and if only one of them is then we moved it to RHS already. + if (isa(LHS) && (isa(RHS) || isa(RHS) || + isa(RHS))) + // We already know that LHS != RHS. + return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred)); + + // If we are comparing with zero then try hard since this is a common case. + if (match(RHS, m_Zero())) { + bool LHSKnownNonNegative, LHSKnownNegative; + switch (Pred) { + default: + assert(false && "Unknown ICmp predicate!"); + case ICmpInst::ICMP_ULT: + return ConstantInt::getFalse(LHS->getContext()); + case ICmpInst::ICMP_UGE: + return ConstantInt::getTrue(LHS->getContext()); + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_ULE: + if (isKnownNonZero(LHS, TD)) + return ConstantInt::getFalse(LHS->getContext()); + break; + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_UGT: + if (isKnownNonZero(LHS, TD)) + return ConstantInt::getTrue(LHS->getContext()); + break; + case ICmpInst::ICMP_SLT: + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); + if (LHSKnownNegative) + return ConstantInt::getTrue(LHS->getContext()); + if (LHSKnownNonNegative) + return ConstantInt::getFalse(LHS->getContext()); + break; + case ICmpInst::ICMP_SLE: + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); + if (LHSKnownNegative) + return ConstantInt::getTrue(LHS->getContext()); + if (LHSKnownNonNegative && isKnownNonZero(LHS, TD)) + return ConstantInt::getFalse(LHS->getContext()); + break; + case ICmpInst::ICMP_SGE: + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); + if (LHSKnownNegative) + return ConstantInt::getFalse(LHS->getContext()); + if (LHSKnownNonNegative) + return ConstantInt::getTrue(LHS->getContext()); + break; + case ICmpInst::ICMP_SGT: + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, TD); + if (LHSKnownNegative) + return ConstantInt::getFalse(LHS->getContext()); + if (LHSKnownNonNegative && isKnownNonZero(LHS, TD)) + return ConstantInt::getTrue(LHS->getContext()); + break; + } + } + + // See if we are doing a comparison with a constant integer. + if (ConstantInt *CI = dyn_cast(RHS)) { + // Rule out tautological comparisons (eg., ult 0 or uge 0). + ConstantRange RHS_CR = ICmpInst::makeConstantRange(Pred, CI->getValue()); + if (RHS_CR.isEmptySet()) + return ConstantInt::getFalse(CI->getContext()); + if (RHS_CR.isFullSet()) + return ConstantInt::getTrue(CI->getContext()); + + // Many binary operators with constant RHS have easy to compute constant + // range. Use them to check whether the comparison is a tautology. + uint32_t Width = CI->getBitWidth(); + APInt Lower = APInt(Width, 0); + APInt Upper = APInt(Width, 0); + ConstantInt *CI2; + if (match(LHS, m_URem(m_Value(), m_ConstantInt(CI2)))) { + // 'urem x, CI2' produces [0, CI2). + Upper = CI2->getValue(); + } else if (match(LHS, m_SRem(m_Value(), m_ConstantInt(CI2)))) { + // 'srem x, CI2' produces (-|CI2|, |CI2|). + Upper = CI2->getValue().abs(); + Lower = (-Upper) + 1; + } else if (match(LHS, m_UDiv(m_Value(), m_ConstantInt(CI2)))) { + // 'udiv x, CI2' produces [0, UINT_MAX / CI2]. + APInt NegOne = APInt::getAllOnesValue(Width); + if (!CI2->isZero()) + Upper = NegOne.udiv(CI2->getValue()) + 1; + } else if (match(LHS, m_SDiv(m_Value(), m_ConstantInt(CI2)))) { + // 'sdiv x, CI2' produces [INT_MIN / CI2, INT_MAX / CI2]. + APInt IntMin = APInt::getSignedMinValue(Width); + APInt IntMax = APInt::getSignedMaxValue(Width); + APInt Val = CI2->getValue().abs(); + if (!Val.isMinValue()) { + Lower = IntMin.sdiv(Val); + Upper = IntMax.sdiv(Val) + 1; + } + } else if (match(LHS, m_LShr(m_Value(), m_ConstantInt(CI2)))) { + // 'lshr x, CI2' produces [0, UINT_MAX >> CI2]. + APInt NegOne = APInt::getAllOnesValue(Width); + if (CI2->getValue().ult(Width)) + Upper = NegOne.lshr(CI2->getValue()) + 1; + } else if (match(LHS, m_AShr(m_Value(), m_ConstantInt(CI2)))) { + // 'ashr x, CI2' produces [INT_MIN >> CI2, INT_MAX >> CI2]. + APInt IntMin = APInt::getSignedMinValue(Width); + APInt IntMax = APInt::getSignedMaxValue(Width); + if (CI2->getValue().ult(Width)) { + Lower = IntMin.ashr(CI2->getValue()); + Upper = IntMax.ashr(CI2->getValue()) + 1; + } + } else if (match(LHS, m_Or(m_Value(), m_ConstantInt(CI2)))) { + // 'or x, CI2' produces [CI2, UINT_MAX]. + Lower = CI2->getValue(); + } else if (match(LHS, m_And(m_Value(), m_ConstantInt(CI2)))) { + // 'and x, CI2' produces [0, CI2]. + Upper = CI2->getValue() + 1; + } + if (Lower != Upper) { + ConstantRange LHS_CR = ConstantRange(Lower, Upper); + if (RHS_CR.contains(LHS_CR)) + return ConstantInt::getTrue(RHS->getContext()); + if (RHS_CR.inverse().contains(LHS_CR)) + return ConstantInt::getFalse(RHS->getContext()); + } + } + + // Compare of cast, for example (zext X) != 0 -> X != 0 + if (isa(LHS) && (isa(RHS) || isa(RHS))) { + Instruction *LI = cast(LHS); + Value *SrcOp = LI->getOperand(0); + const Type *SrcTy = SrcOp->getType(); + const Type *DstTy = LI->getType(); + + // Turn icmp (ptrtoint x), (ptrtoint/constant) into a compare of the input + // if the integer type is the same size as the pointer type. + if (MaxRecurse && TD && isa(LI) && + TD->getPointerSizeInBits() == DstTy->getPrimitiveSizeInBits()) { + if (Constant *RHSC = dyn_cast(RHS)) { + // Transfer the cast to the constant. + if (Value *V = SimplifyICmpInst(Pred, SrcOp, + ConstantExpr::getIntToPtr(RHSC, SrcTy), + TD, DT, MaxRecurse-1)) + return V; + } else if (PtrToIntInst *RI = dyn_cast(RHS)) { + if (RI->getOperand(0)->getType() == SrcTy) + // Compare without the cast. + if (Value *V = SimplifyICmpInst(Pred, SrcOp, RI->getOperand(0), + TD, DT, MaxRecurse-1)) + return V; + } + } + + if (isa(LHS)) { + // Turn icmp (zext X), (zext Y) into a compare of X and Y if they have the + // same type. + if (ZExtInst *RI = dyn_cast(RHS)) { + if (MaxRecurse && SrcTy == RI->getOperand(0)->getType()) + // Compare X and Y. Note that signed predicates become unsigned. + if (Value *V = SimplifyICmpInst(ICmpInst::getUnsignedPredicate(Pred), + SrcOp, RI->getOperand(0), TD, DT, + MaxRecurse-1)) + return V; + } + // Turn icmp (zext X), Cst into a compare of X and Cst if Cst is extended + // too. If not, then try to deduce the result of the comparison. + else if (ConstantInt *CI = dyn_cast(RHS)) { + // Compute the constant that would happen if we truncated to SrcTy then + // reextended to DstTy. + Constant *Trunc = ConstantExpr::getTrunc(CI, SrcTy); + Constant *RExt = ConstantExpr::getCast(CastInst::ZExt, Trunc, DstTy); + + // If the re-extended constant didn't change then this is effectively + // also a case of comparing two zero-extended values. + if (RExt == CI && MaxRecurse) + if (Value *V = SimplifyICmpInst(ICmpInst::getUnsignedPredicate(Pred), + SrcOp, Trunc, TD, DT, MaxRecurse-1)) + return V; + + // Otherwise the upper bits of LHS are zero while RHS has a non-zero bit + // there. Use this to work out the result of the comparison. + if (RExt != CI) { + switch (Pred) { + default: + assert(false && "Unknown ICmp predicate!"); + // LHS getContext()); + + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + return ConstantInt::getTrue(CI->getContext()); + + // LHS is non-negative. If RHS is negative then LHS >s LHS. If RHS + // is non-negative then LHS getValue().isNegative() ? + ConstantInt::getTrue(CI->getContext()) : + ConstantInt::getFalse(CI->getContext()); + + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + return CI->getValue().isNegative() ? + ConstantInt::getFalse(CI->getContext()) : + ConstantInt::getTrue(CI->getContext()); + } + } + } + } + + if (isa(LHS)) { + // Turn icmp (sext X), (sext Y) into a compare of X and Y if they have the + // same type. + if (SExtInst *RI = dyn_cast(RHS)) { + if (MaxRecurse && SrcTy == RI->getOperand(0)->getType()) + // Compare X and Y. Note that the predicate does not change. + if (Value *V = SimplifyICmpInst(Pred, SrcOp, RI->getOperand(0), + TD, DT, MaxRecurse-1)) + return V; + } + // Turn icmp (sext X), Cst into a compare of X and Cst if Cst is extended + // too. If not, then try to deduce the result of the comparison. + else if (ConstantInt *CI = dyn_cast(RHS)) { + // Compute the constant that would happen if we truncated to SrcTy then + // reextended to DstTy. + Constant *Trunc = ConstantExpr::getTrunc(CI, SrcTy); + Constant *RExt = ConstantExpr::getCast(CastInst::SExt, Trunc, DstTy); + + // If the re-extended constant didn't change then this is effectively + // also a case of comparing two sign-extended values. + if (RExt == CI && MaxRecurse) + if (Value *V = SimplifyICmpInst(Pred, SrcOp, Trunc, TD, DT, + MaxRecurse-1)) + return V; + + // Otherwise the upper bits of LHS are all equal, while RHS has varying + // bits there. Use this to work out the result of the comparison. + if (RExt != CI) { + switch (Pred) { + default: + assert(false && "Unknown ICmp predicate!"); + case ICmpInst::ICMP_EQ: + return ConstantInt::getFalse(CI->getContext()); + case ICmpInst::ICMP_NE: + return ConstantInt::getTrue(CI->getContext()); + + // If RHS is non-negative then LHS s RHS. + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + return CI->getValue().isNegative() ? + ConstantInt::getTrue(CI->getContext()) : + ConstantInt::getFalse(CI->getContext()); + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + return CI->getValue().isNegative() ? + ConstantInt::getFalse(CI->getContext()) : + ConstantInt::getTrue(CI->getContext()); + + // If LHS is non-negative then LHS u RHS. + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + // Comparison is true iff the LHS =s 0. + if (MaxRecurse) + if (Value *V = SimplifyICmpInst(ICmpInst::ICMP_SGE, SrcOp, + Constant::getNullValue(SrcTy), + TD, DT, MaxRecurse-1)) + return V; + break; + } + } + } + } + } + + // Special logic for binary operators. + BinaryOperator *LBO = dyn_cast(LHS); + BinaryOperator *RBO = dyn_cast(RHS); + if (MaxRecurse && (LBO || RBO)) { + // Analyze the case when either LHS or RHS is an add instruction. + Value *A = 0, *B = 0, *C = 0, *D = 0; + // LHS = A + B (or A and B are null); RHS = C + D (or C and D are null). + bool NoLHSWrapProblem = false, NoRHSWrapProblem = false; + if (LBO && LBO->getOpcode() == Instruction::Add) { + A = LBO->getOperand(0); B = LBO->getOperand(1); + NoLHSWrapProblem = ICmpInst::isEquality(Pred) || + (CmpInst::isUnsigned(Pred) && LBO->hasNoUnsignedWrap()) || + (CmpInst::isSigned(Pred) && LBO->hasNoSignedWrap()); + } + if (RBO && RBO->getOpcode() == Instruction::Add) { + C = RBO->getOperand(0); D = RBO->getOperand(1); + NoRHSWrapProblem = ICmpInst::isEquality(Pred) || + (CmpInst::isUnsigned(Pred) && RBO->hasNoUnsignedWrap()) || + (CmpInst::isSigned(Pred) && RBO->hasNoSignedWrap()); + } + + // icmp (X+Y), X -> icmp Y, 0 for equalities or if there is no overflow. + if ((A == RHS || B == RHS) && NoLHSWrapProblem) + if (Value *V = SimplifyICmpInst(Pred, A == RHS ? B : A, + Constant::getNullValue(RHS->getType()), + TD, DT, MaxRecurse-1)) + return V; + + // icmp X, (X+Y) -> icmp 0, Y for equalities or if there is no overflow. + if ((C == LHS || D == LHS) && NoRHSWrapProblem) + if (Value *V = SimplifyICmpInst(Pred, + Constant::getNullValue(LHS->getType()), + C == LHS ? D : C, TD, DT, MaxRecurse-1)) + return V; + + // icmp (X+Y), (X+Z) -> icmp Y,Z for equalities or if there is no overflow. + if (A && C && (A == C || A == D || B == C || B == D) && + NoLHSWrapProblem && NoRHSWrapProblem) { + // Determine Y and Z in the form icmp (X+Y), (X+Z). + Value *Y = (A == C || A == D) ? B : A; + Value *Z = (C == A || C == B) ? D : C; + if (Value *V = SimplifyICmpInst(Pred, Y, Z, TD, DT, MaxRecurse-1)) + return V; + } + } + + Value *V; + if (LBO && match(LBO, m_URem(m_Value(V), m_Specific(RHS)))) { + bool KnownNonNegative, KnownNegative; + switch (Pred) { + default: + break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + return ConstantInt::getFalse(RHS->getContext()); + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + ComputeSignBit(LHS, KnownNonNegative, KnownNegative, TD); + if (!KnownNonNegative) + break; + // fall-through + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + return ConstantInt::getTrue(RHS->getContext()); + } + } + + if (MaxRecurse && LBO && RBO && LBO->getOpcode() == RBO->getOpcode() && + LBO->getOperand(1) == RBO->getOperand(1)) { + switch (LBO->getOpcode()) { + default: break; + case Instruction::UDiv: + case Instruction::LShr: + if (ICmpInst::isSigned(Pred)) + break; + // fall-through + case Instruction::SDiv: + case Instruction::AShr: + if (!LBO->isExact() && !RBO->isExact()) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + case Instruction::Shl: { + bool NUW = LBO->hasNoUnsignedWrap() && LBO->hasNoUnsignedWrap(); + bool NSW = LBO->hasNoSignedWrap() && RBO->hasNoSignedWrap(); + if (!NUW && !NSW) + break; + if (!NSW && ICmpInst::isSigned(Pred)) + break; + if (Value *V = SimplifyICmpInst(Pred, LBO->getOperand(0), + RBO->getOperand(0), TD, DT, MaxRecurse-1)) + return V; + break; + } + } + } + + // If the comparison is with the result of a select instruction, check whether + // comparing with either branch of the select always yields the same value. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadCmpOverSelect(Pred, LHS, RHS, TD, DT, MaxRecurse)) + return V; + + // If the comparison is with the result of a phi instruction, check whether + // doing the compare with each incoming phi value yields a common result. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadCmpOverPHI(Pred, LHS, RHS, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyICmpInst(Predicate, LHS, RHS, TD, DT, RecursionLimit); +} + +/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + CmpInst::Predicate Pred = (CmpInst::Predicate)Predicate; + assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!"); + + if (Constant *CLHS = dyn_cast(LHS)) { + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantFoldCompareInstOperands(Pred, CLHS, CRHS, TD); + + // If we have a constant, make sure it is on the RHS. + std::swap(LHS, RHS); + Pred = CmpInst::getSwappedPredicate(Pred); + } + + // Fold trivial predicates. + if (Pred == FCmpInst::FCMP_FALSE) + return ConstantInt::get(GetCompareTy(LHS), 0); + if (Pred == FCmpInst::FCMP_TRUE) + return ConstantInt::get(GetCompareTy(LHS), 1); + + if (isa(RHS)) // fcmp pred X, undef -> undef + return UndefValue::get(GetCompareTy(LHS)); + + // fcmp x,x -> true/false. Not all compares are foldable. + if (LHS == RHS) { + if (CmpInst::isTrueWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 1); + if (CmpInst::isFalseWhenEqual(Pred)) + return ConstantInt::get(GetCompareTy(LHS), 0); + } + + // Handle fcmp with constant RHS + if (Constant *RHSC = dyn_cast(RHS)) { + // If the constant is a nan, see if we can fold the comparison based on it. + if (ConstantFP *CFP = dyn_cast(RHSC)) { + if (CFP->getValueAPF().isNaN()) { + if (FCmpInst::isOrdered(Pred)) // True "if ordered and foo" + return ConstantInt::getFalse(CFP->getContext()); + assert(FCmpInst::isUnordered(Pred) && + "Comparison must be either ordered or unordered!"); + // True if unordered. + return ConstantInt::getTrue(CFP->getContext()); + } + // Check whether the constant is an infinity. + if (CFP->getValueAPF().isInfinity()) { + if (CFP->getValueAPF().isNegative()) { + switch (Pred) { + case FCmpInst::FCMP_OLT: + // No value is ordered and less than negative infinity. + return ConstantInt::getFalse(CFP->getContext()); + case FCmpInst::FCMP_UGE: + // All values are unordered with or at least negative infinity. + return ConstantInt::getTrue(CFP->getContext()); + default: + break; + } + } else { + switch (Pred) { + case FCmpInst::FCMP_OGT: + // No value is ordered and greater than infinity. + return ConstantInt::getFalse(CFP->getContext()); + case FCmpInst::FCMP_ULE: + // All values are unordered with and at most infinity. + return ConstantInt::getTrue(CFP->getContext()); + default: + break; + } + } + } + } + } + + // If the comparison is with the result of a select instruction, check whether + // comparing with either branch of the select always yields the same value. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadCmpOverSelect(Pred, LHS, RHS, TD, DT, MaxRecurse)) + return V; + + // If the comparison is with the result of a phi instruction, check whether + // doing the compare with each incoming phi value yields a common result. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadCmpOverPHI(Pred, LHS, RHS, TD, DT, MaxRecurse)) + return V; + + return 0; +} + +Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyFCmpInst(Predicate, LHS, RHS, TD, DT, RecursionLimit); +} + +/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold +/// the result. If not, this returns null. +Value *llvm::SimplifySelectInst(Value *CondVal, Value *TrueVal, Value *FalseVal, + const TargetData *TD, const DominatorTree *) { + // select true, X, Y -> X + // select false, X, Y -> Y + if (ConstantInt *CB = dyn_cast(CondVal)) + return CB->getZExtValue() ? TrueVal : FalseVal; + + // select C, X, X -> X + if (TrueVal == FalseVal) + return TrueVal; + + if (isa(TrueVal)) // select C, undef, X -> X + return FalseVal; + if (isa(FalseVal)) // select C, X, undef -> X + return TrueVal; + if (isa(CondVal)) { // select undef, X, Y -> X or Y + if (isa(TrueVal)) + return TrueVal; + return FalseVal; + } + + return 0; +} + +/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can +/// fold the result. If not, this returns null. +Value *llvm::SimplifyGEPInst(Value *const *Ops, unsigned NumOps, + const TargetData *TD, const DominatorTree *) { + // The type of the GEP pointer operand. + const PointerType *PtrTy = cast(Ops[0]->getType()); + + // getelementptr P -> P. + if (NumOps == 1) + return Ops[0]; + + if (isa(Ops[0])) { + // Compute the (pointer) type returned by the GEP instruction. + const Type *LastType = GetElementPtrInst::getIndexedType(PtrTy, &Ops[1], + NumOps-1); + const Type *GEPTy = PointerType::get(LastType, PtrTy->getAddressSpace()); + return UndefValue::get(GEPTy); + } + + if (NumOps == 2) { + // getelementptr P, 0 -> P. + if (ConstantInt *C = dyn_cast(Ops[1])) + if (C->isZero()) + return Ops[0]; + // getelementptr P, N -> P if P points to a type of zero size. + if (TD) { + const Type *Ty = PtrTy->getElementType(); + if (Ty->isSized() && TD->getTypeAllocSize(Ty) == 0) + return Ops[0]; + } + } + + // Check to see if this is constant foldable. + for (unsigned i = 0; i != NumOps; ++i) + if (!isa(Ops[i])) + return 0; + + return ConstantExpr::getGetElementPtr(cast(Ops[0]), + (Constant *const*)Ops+1, NumOps-1); +} + +/// SimplifyPHINode - See if we can fold the given phi. If not, returns null. +static Value *SimplifyPHINode(PHINode *PN, const DominatorTree *DT) { + // If all of the PHI's incoming values are the same then replace the PHI node + // with the common value. + Value *CommonValue = 0; + bool HasUndefInput = false; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = PN->getIncomingValue(i); + // If the incoming value is the phi node itself, it can safely be skipped. + if (Incoming == PN) continue; + if (isa(Incoming)) { + // Remember that we saw an undef value, but otherwise ignore them. + HasUndefInput = true; + continue; + } + if (CommonValue && Incoming != CommonValue) + return 0; // Not the same, bail out. + CommonValue = Incoming; + } + + // If CommonValue is null then all of the incoming values were either undef or + // equal to the phi node itself. + if (!CommonValue) + return UndefValue::get(PN->getType()); + + // If we have a PHI node like phi(X, undef, X), where X is defined by some + // instruction, we cannot return X as the result of the PHI node unless it + // dominates the PHI block. + if (HasUndefInput) + return ValueDominatesPHI(CommonValue, PN, DT) ? CommonValue : 0; + + return CommonValue; +} + + +//=== Helper functions for higher up the class hierarchy. + +/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can +/// fold the result. If not, this returns null. +static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + switch (Opcode) { + case Instruction::Add: + return SimplifyAddInst(LHS, RHS, /*isNSW*/false, /*isNUW*/false, + TD, DT, MaxRecurse); + case Instruction::Sub: + return SimplifySubInst(LHS, RHS, /*isNSW*/false, /*isNUW*/false, + TD, DT, MaxRecurse); + case Instruction::Mul: return SimplifyMulInst (LHS, RHS, TD, DT, MaxRecurse); + case Instruction::SDiv: return SimplifySDivInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::UDiv: return SimplifyUDivInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::FDiv: return SimplifyFDivInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::Shl: + return SimplifyShlInst(LHS, RHS, /*isNSW*/false, /*isNUW*/false, + TD, DT, MaxRecurse); + case Instruction::LShr: + return SimplifyLShrInst(LHS, RHS, /*isExact*/false, TD, DT, MaxRecurse); + case Instruction::AShr: + return SimplifyAShrInst(LHS, RHS, /*isExact*/false, TD, DT, MaxRecurse); + case Instruction::And: return SimplifyAndInst(LHS, RHS, TD, DT, MaxRecurse); + case Instruction::Or: return SimplifyOrInst (LHS, RHS, TD, DT, MaxRecurse); + case Instruction::Xor: return SimplifyXorInst(LHS, RHS, TD, DT, MaxRecurse); + default: + if (Constant *CLHS = dyn_cast(LHS)) + if (Constant *CRHS = dyn_cast(RHS)) { + Constant *COps[] = {CLHS, CRHS}; + return ConstantFoldInstOperands(Opcode, LHS->getType(), COps, 2, TD); + } + + // If the operation is associative, try some generic simplifications. + if (Instruction::isAssociative(Opcode)) + if (Value *V = SimplifyAssociativeBinOp(Opcode, LHS, RHS, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a select instruction, check whether + // operating on either branch of the select always yields the same value. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadBinOpOverSelect(Opcode, LHS, RHS, TD, DT, + MaxRecurse)) + return V; + + // If the operation is with the result of a phi instruction, check whether + // operating on all incoming values of the phi always yields the same value. + if (isa(LHS) || isa(RHS)) + if (Value *V = ThreadBinOpOverPHI(Opcode, LHS, RHS, TD, DT, MaxRecurse)) + return V; + + return 0; + } +} + +Value *llvm::SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyBinOp(Opcode, LHS, RHS, TD, DT, RecursionLimit); +} + +/// SimplifyCmpInst - Given operands for a CmpInst, see if we can +/// fold the result. +static Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT, + unsigned MaxRecurse) { + if (CmpInst::isIntPredicate((CmpInst::Predicate)Predicate)) + return SimplifyICmpInst(Predicate, LHS, RHS, TD, DT, MaxRecurse); + return SimplifyFCmpInst(Predicate, LHS, RHS, TD, DT, MaxRecurse); +} + +Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, + const TargetData *TD, const DominatorTree *DT) { + return ::SimplifyCmpInst(Predicate, LHS, RHS, TD, DT, RecursionLimit); +} + +/// SimplifyInstruction - See if we can compute a simplified version of this +/// instruction. If not, this returns null. +Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, + const DominatorTree *DT) { + Value *Result; + + switch (I->getOpcode()) { + default: + Result = ConstantFoldInstruction(I, TD); + break; + case Instruction::Add: + Result = SimplifyAddInst(I->getOperand(0), I->getOperand(1), + cast(I)->hasNoSignedWrap(), + cast(I)->hasNoUnsignedWrap(), + TD, DT); + break; + case Instruction::Sub: + Result = SimplifySubInst(I->getOperand(0), I->getOperand(1), + cast(I)->hasNoSignedWrap(), + cast(I)->hasNoUnsignedWrap(), + TD, DT); + break; + case Instruction::Mul: + Result = SimplifyMulInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::SDiv: + Result = SimplifySDivInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::UDiv: + Result = SimplifyUDivInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::FDiv: + Result = SimplifyFDivInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::Shl: + Result = SimplifyShlInst(I->getOperand(0), I->getOperand(1), + cast(I)->hasNoSignedWrap(), + cast(I)->hasNoUnsignedWrap(), + TD, DT); + break; + case Instruction::LShr: + Result = SimplifyLShrInst(I->getOperand(0), I->getOperand(1), + cast(I)->isExact(), + TD, DT); + break; + case Instruction::AShr: + Result = SimplifyAShrInst(I->getOperand(0), I->getOperand(1), + cast(I)->isExact(), + TD, DT); + break; + case Instruction::And: + Result = SimplifyAndInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::Or: + Result = SimplifyOrInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::Xor: + Result = SimplifyXorInst(I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::ICmp: + Result = SimplifyICmpInst(cast(I)->getPredicate(), + I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::FCmp: + Result = SimplifyFCmpInst(cast(I)->getPredicate(), + I->getOperand(0), I->getOperand(1), TD, DT); + break; + case Instruction::Select: + Result = SimplifySelectInst(I->getOperand(0), I->getOperand(1), + I->getOperand(2), TD, DT); + break; + case Instruction::GetElementPtr: { + SmallVector Ops(I->op_begin(), I->op_end()); + Result = SimplifyGEPInst(&Ops[0], Ops.size(), TD, DT); + break; + } + case Instruction::PHI: + Result = SimplifyPHINode(cast(I), DT); + break; + } + + /// If called on unreachable code, the above logic may report that the + /// instruction simplified to itself. Make life easier for users by + /// detecting that case here, returning a safe value instead. + return Result == I ? UndefValue::get(I->getType()) : Result; +} + +/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then +/// delete the From instruction. In addition to a basic RAUW, this does a +/// recursive simplification of the newly formed instructions. This catches +/// things where one simplification exposes other opportunities. This only +/// simplifies and deletes scalar operations, it does not change the CFG. +/// +void llvm::ReplaceAndSimplifyAllUses(Instruction *From, Value *To, + const TargetData *TD, + const DominatorTree *DT) { + assert(From != To && "ReplaceAndSimplifyAllUses(X,X) is not valid!"); + + // FromHandle/ToHandle - This keeps a WeakVH on the from/to values so that + // we can know if it gets deleted out from under us or replaced in a + // recursive simplification. + WeakVH FromHandle(From); + WeakVH ToHandle(To); + + while (!From->use_empty()) { + // Update the instruction to use the new value. + Use &TheUse = From->use_begin().getUse(); + Instruction *User = cast(TheUse.getUser()); + TheUse = To; + + // Check to see if the instruction can be folded due to the operand + // replacement. For example changing (or X, Y) into (or X, -1) can replace + // the 'or' with -1. + Value *SimplifiedVal; + { + // Sanity check to make sure 'User' doesn't dangle across + // SimplifyInstruction. + AssertingVH<> UserHandle(User); + + SimplifiedVal = SimplifyInstruction(User, TD, DT); + if (SimplifiedVal == 0) continue; + } + + // Recursively simplify this user to the new value. + ReplaceAndSimplifyAllUses(User, SimplifiedVal, TD, DT); + From = dyn_cast_or_null((Value*)FromHandle); + To = ToHandle; + + assert(ToHandle && "To value deleted by recursive simplification?"); + + // If the recursive simplification ended up revisiting and deleting + // 'From' then we're done. + if (From == 0) + return; + } + + // If 'From' has value handles referring to it, do a real RAUW to update them. + From->replaceAllUsesWith(To); + + From->eraseFromParent(); +} diff --git a/final/lib/Analysis/Interval.cpp b/final/lib/Analysis/Interval.cpp new file mode 100644 index 00000000000..ca9cdcaf246 --- /dev/null +++ b/final/lib/Analysis/Interval.cpp @@ -0,0 +1,58 @@ +//===- Interval.cpp - Interval class code ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definition of the Interval class, which represents a +// partition of a control flow graph of some kind. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Interval.h" +#include "llvm/BasicBlock.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Interval Implementation +//===----------------------------------------------------------------------===// + +// isLoop - Find out if there is a back edge in this interval... +// +bool Interval::isLoop() const { + // There is a loop in this interval iff one of the predecessors of the header + // node lives in the interval. + for (::pred_iterator I = ::pred_begin(HeaderNode), E = ::pred_end(HeaderNode); + I != E; ++I) + if (contains(*I)) + return true; + return false; +} + + +void Interval::print(raw_ostream &OS) const { + OS << "-------------------------------------------------------------\n" + << "Interval Contents:\n"; + + // Print out all of the basic blocks in the interval... + for (std::vector::const_iterator I = Nodes.begin(), + E = Nodes.end(); I != E; ++I) + OS << **I << "\n"; + + OS << "Interval Predecessors:\n"; + for (std::vector::const_iterator I = Predecessors.begin(), + E = Predecessors.end(); I != E; ++I) + OS << **I << "\n"; + + OS << "Interval Successors:\n"; + for (std::vector::const_iterator I = Successors.begin(), + E = Successors.end(); I != E; ++I) + OS << **I << "\n"; +} diff --git a/final/lib/Analysis/IntervalPartition.cpp b/final/lib/Analysis/IntervalPartition.cpp new file mode 100644 index 00000000000..2e259b147b8 --- /dev/null +++ b/final/lib/Analysis/IntervalPartition.cpp @@ -0,0 +1,114 @@ +//===- IntervalPartition.cpp - Interval Partition module code -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definition of the IntervalPartition class, which +// calculates and represent the interval partition of a function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/IntervalIterator.h" +using namespace llvm; + +char IntervalPartition::ID = 0; +INITIALIZE_PASS(IntervalPartition, "intervals", + "Interval Partition Construction", true, true) + +//===----------------------------------------------------------------------===// +// IntervalPartition Implementation +//===----------------------------------------------------------------------===// + +// releaseMemory - Reset state back to before function was analyzed +void IntervalPartition::releaseMemory() { + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + delete Intervals[i]; + IntervalMap.clear(); + Intervals.clear(); + RootInterval = 0; +} + +void IntervalPartition::print(raw_ostream &O, const Module*) const { + for(unsigned i = 0, e = Intervals.size(); i != e; ++i) + Intervals[i]->print(O); +} + +// addIntervalToPartition - Add an interval to the internal list of intervals, +// and then add mappings from all of the basic blocks in the interval to the +// interval itself (in the IntervalMap). +// +void IntervalPartition::addIntervalToPartition(Interval *I) { + Intervals.push_back(I); + + // Add mappings for all of the basic blocks in I to the IntervalPartition + for (Interval::node_iterator It = I->Nodes.begin(), End = I->Nodes.end(); + It != End; ++It) + IntervalMap.insert(std::make_pair(*It, I)); +} + +// updatePredecessors - Interval generation only sets the successor fields of +// the interval data structures. After interval generation is complete, +// run through all of the intervals and propagate successor info as +// predecessor info. +// +void IntervalPartition::updatePredecessors(Interval *Int) { + BasicBlock *Header = Int->getHeaderNode(); + for (Interval::succ_iterator I = Int->Successors.begin(), + E = Int->Successors.end(); I != E; ++I) + getBlockInterval(*I)->Predecessors.push_back(Header); +} + +// IntervalPartition ctor - Build the first level interval partition for the +// specified function... +// +bool IntervalPartition::runOnFunction(Function &F) { + // Pass false to intervals_begin because we take ownership of it's memory + function_interval_iterator I = intervals_begin(&F, false); + assert(I != intervals_end(&F) && "No intervals in function!?!?!"); + + addIntervalToPartition(RootInterval = *I); + + ++I; // After the first one... + + // Add the rest of the intervals to the partition. + for (function_interval_iterator E = intervals_end(&F); I != E; ++I) + addIntervalToPartition(*I); + + // Now that we know all of the successor information, propagate this to the + // predecessors for each block. + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + updatePredecessors(Intervals[i]); + return false; +} + + +// IntervalPartition ctor - Build a reduced interval partition from an +// existing interval graph. This takes an additional boolean parameter to +// distinguish it from a copy constructor. Always pass in false for now. +// +IntervalPartition::IntervalPartition(IntervalPartition &IP, bool) + : FunctionPass(ID) { + assert(IP.getRootInterval() && "Cannot operate on empty IntervalPartitions!"); + + // Pass false to intervals_begin because we take ownership of it's memory + interval_part_interval_iterator I = intervals_begin(IP, false); + assert(I != intervals_end(IP) && "No intervals in interval partition!?!?!"); + + addIntervalToPartition(RootInterval = *I); + + ++I; // After the first one... + + // Add the rest of the intervals to the partition. + for (interval_part_interval_iterator E = intervals_end(IP); I != E; ++I) + addIntervalToPartition(*I); + + // Now that we know all of the successor information, propagate this to the + // predecessors for each block. + for (unsigned i = 0, e = Intervals.size(); i != e; ++i) + updatePredecessors(Intervals[i]); +} + diff --git a/final/lib/Analysis/LazyValueInfo.cpp b/final/lib/Analysis/LazyValueInfo.cpp new file mode 100644 index 00000000000..9e7da6ce2de --- /dev/null +++ b/final/lib/Analysis/LazyValueInfo.cpp @@ -0,0 +1,1125 @@ +//===- LazyValueInfo.cpp - Value constraint analysis ----------------------===// +// +// 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 interface for lazy computation of value constraint +// information. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lazy-value-info" +#include "llvm/Analysis/LazyValueInfo.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +#include +using namespace llvm; + +char LazyValueInfo::ID = 0; +INITIALIZE_PASS(LazyValueInfo, "lazy-value-info", + "Lazy Value Information Analysis", false, true) + +namespace llvm { + FunctionPass *createLazyValueInfoPass() { return new LazyValueInfo(); } +} + + +//===----------------------------------------------------------------------===// +// LVILatticeVal +//===----------------------------------------------------------------------===// + +/// LVILatticeVal - This is the information tracked by LazyValueInfo for each +/// value. +/// +/// FIXME: This is basically just for bringup, this can be made a lot more rich +/// in the future. +/// +namespace { +class LVILatticeVal { + enum LatticeValueTy { + /// undefined - This Value has no known value yet. + undefined, + + /// constant - This Value has a specific constant value. + constant, + /// notconstant - This Value is known to not have the specified value. + notconstant, + + /// constantrange - The Value falls within this range. + constantrange, + + /// overdefined - This value is not known to be constant, and we know that + /// it has a value. + overdefined + }; + + /// Val: This stores the current lattice value along with the Constant* for + /// the constant if this is a 'constant' or 'notconstant' value. + LatticeValueTy Tag; + Constant *Val; + ConstantRange Range; + +public: + LVILatticeVal() : Tag(undefined), Val(0), Range(1, true) {} + + static LVILatticeVal get(Constant *C) { + LVILatticeVal Res; + if (!isa(C)) + Res.markConstant(C); + return Res; + } + static LVILatticeVal getNot(Constant *C) { + LVILatticeVal Res; + if (!isa(C)) + Res.markNotConstant(C); + return Res; + } + static LVILatticeVal getRange(ConstantRange CR) { + LVILatticeVal Res; + Res.markConstantRange(CR); + return Res; + } + + bool isUndefined() const { return Tag == undefined; } + bool isConstant() const { return Tag == constant; } + bool isNotConstant() const { return Tag == notconstant; } + bool isConstantRange() const { return Tag == constantrange; } + bool isOverdefined() const { return Tag == overdefined; } + + Constant *getConstant() const { + assert(isConstant() && "Cannot get the constant of a non-constant!"); + return Val; + } + + Constant *getNotConstant() const { + assert(isNotConstant() && "Cannot get the constant of a non-notconstant!"); + return Val; + } + + ConstantRange getConstantRange() const { + assert(isConstantRange() && + "Cannot get the constant-range of a non-constant-range!"); + return Range; + } + + /// markOverdefined - Return true if this is a change in status. + bool markOverdefined() { + if (isOverdefined()) + return false; + Tag = overdefined; + return true; + } + + /// markConstant - Return true if this is a change in status. + bool markConstant(Constant *V) { + assert(V && "Marking constant with NULL"); + if (ConstantInt *CI = dyn_cast(V)) + return markConstantRange(ConstantRange(CI->getValue())); + if (isa(V)) + return false; + + assert((!isConstant() || getConstant() == V) && + "Marking constant with different value"); + assert(isUndefined()); + Tag = constant; + Val = V; + return true; + } + + /// markNotConstant - Return true if this is a change in status. + bool markNotConstant(Constant *V) { + assert(V && "Marking constant with NULL"); + if (ConstantInt *CI = dyn_cast(V)) + return markConstantRange(ConstantRange(CI->getValue()+1, CI->getValue())); + if (isa(V)) + return false; + + assert((!isConstant() || getConstant() != V) && + "Marking constant !constant with same value"); + assert((!isNotConstant() || getNotConstant() == V) && + "Marking !constant with different value"); + assert(isUndefined() || isConstant()); + Tag = notconstant; + Val = V; + return true; + } + + /// markConstantRange - Return true if this is a change in status. + bool markConstantRange(const ConstantRange NewR) { + if (isConstantRange()) { + if (NewR.isEmptySet()) + return markOverdefined(); + + bool changed = Range == NewR; + Range = NewR; + return changed; + } + + assert(isUndefined()); + if (NewR.isEmptySet()) + return markOverdefined(); + + Tag = constantrange; + Range = NewR; + return true; + } + + /// mergeIn - Merge the specified lattice value into this one, updating this + /// one and returning true if anything changed. + bool mergeIn(const LVILatticeVal &RHS) { + if (RHS.isUndefined() || isOverdefined()) return false; + if (RHS.isOverdefined()) return markOverdefined(); + + if (isUndefined()) { + Tag = RHS.Tag; + Val = RHS.Val; + Range = RHS.Range; + return true; + } + + if (isConstant()) { + if (RHS.isConstant()) { + if (Val == RHS.Val) + return false; + return markOverdefined(); + } + + if (RHS.isNotConstant()) { + if (Val == RHS.Val) + return markOverdefined(); + + // Unless we can prove that the two Constants are different, we must + // move to overdefined. + // FIXME: use TargetData for smarter constant folding. + if (ConstantInt *Res = dyn_cast( + ConstantFoldCompareInstOperands(CmpInst::ICMP_NE, + getConstant(), + RHS.getNotConstant()))) + if (Res->isOne()) + return markNotConstant(RHS.getNotConstant()); + + return markOverdefined(); + } + + // RHS is a ConstantRange, LHS is a non-integer Constant. + + // FIXME: consider the case where RHS is a range [1, 0) and LHS is + // a function. The correct result is to pick up RHS. + + return markOverdefined(); + } + + if (isNotConstant()) { + if (RHS.isConstant()) { + if (Val == RHS.Val) + return markOverdefined(); + + // Unless we can prove that the two Constants are different, we must + // move to overdefined. + // FIXME: use TargetData for smarter constant folding. + if (ConstantInt *Res = dyn_cast( + ConstantFoldCompareInstOperands(CmpInst::ICMP_NE, + getNotConstant(), + RHS.getConstant()))) + if (Res->isOne()) + return false; + + return markOverdefined(); + } + + if (RHS.isNotConstant()) { + if (Val == RHS.Val) + return false; + return markOverdefined(); + } + + return markOverdefined(); + } + + assert(isConstantRange() && "New LVILattice type?"); + if (!RHS.isConstantRange()) + return markOverdefined(); + + ConstantRange NewR = Range.unionWith(RHS.getConstantRange()); + if (NewR.isFullSet()) + return markOverdefined(); + return markConstantRange(NewR); + } +}; + +} // end anonymous namespace. + +namespace llvm { +raw_ostream &operator<<(raw_ostream &OS, const LVILatticeVal &Val) { + if (Val.isUndefined()) + return OS << "undefined"; + if (Val.isOverdefined()) + return OS << "overdefined"; + + if (Val.isNotConstant()) + return OS << "notconstant<" << *Val.getNotConstant() << '>'; + else if (Val.isConstantRange()) + return OS << "constantrange<" << Val.getConstantRange().getLower() << ", " + << Val.getConstantRange().getUpper() << '>'; + return OS << "constant<" << *Val.getConstant() << '>'; +} +} + +//===----------------------------------------------------------------------===// +// LazyValueInfoCache Decl +//===----------------------------------------------------------------------===// + +namespace { + /// LVIValueHandle - A callback value handle update the cache when + /// values are erased. + class LazyValueInfoCache; + struct LVIValueHandle : public CallbackVH { + LazyValueInfoCache *Parent; + + LVIValueHandle(Value *V, LazyValueInfoCache *P) + : CallbackVH(V), Parent(P) { } + + void deleted(); + void allUsesReplacedWith(Value *V) { + deleted(); + } + }; +} + +namespace llvm { + template<> + struct DenseMapInfo { + typedef DenseMapInfo PointerInfo; + static inline LVIValueHandle getEmptyKey() { + return LVIValueHandle(PointerInfo::getEmptyKey(), + static_cast(0)); + } + static inline LVIValueHandle getTombstoneKey() { + return LVIValueHandle(PointerInfo::getTombstoneKey(), + static_cast(0)); + } + static unsigned getHashValue(const LVIValueHandle &Val) { + return PointerInfo::getHashValue(Val); + } + static bool isEqual(const LVIValueHandle &LHS, const LVIValueHandle &RHS) { + return LHS == RHS; + } + }; + + template<> + struct DenseMapInfo, Value*> > { + typedef std::pair, Value*> PairTy; + typedef DenseMapInfo > APointerInfo; + typedef DenseMapInfo BPointerInfo; + static inline PairTy getEmptyKey() { + return std::make_pair(APointerInfo::getEmptyKey(), + BPointerInfo::getEmptyKey()); + } + static inline PairTy getTombstoneKey() { + return std::make_pair(APointerInfo::getTombstoneKey(), + BPointerInfo::getTombstoneKey()); + } + static unsigned getHashValue( const PairTy &Val) { + return APointerInfo::getHashValue(Val.first) ^ + BPointerInfo::getHashValue(Val.second); + } + static bool isEqual(const PairTy &LHS, const PairTy &RHS) { + return APointerInfo::isEqual(LHS.first, RHS.first) && + BPointerInfo::isEqual(LHS.second, RHS.second); + } + }; +} + +namespace { + /// LazyValueInfoCache - This is the cache kept by LazyValueInfo which + /// maintains information about queries across the clients' queries. + class LazyValueInfoCache { + /// ValueCacheEntryTy - This is all of the cached block information for + /// exactly one Value*. The entries are sorted by the BasicBlock* of the + /// entries, allowing us to do a lookup with a binary search. + typedef std::map, LVILatticeVal> ValueCacheEntryTy; + + /// ValueCache - This is all of the cached information for all values, + /// mapped from Value* to key information. + DenseMap ValueCache; + + /// OverDefinedCache - This tracks, on a per-block basis, the set of + /// values that are over-defined at the end of that block. This is required + /// for cache updating. + typedef std::pair, Value*> OverDefinedPairTy; + DenseSet OverDefinedCache; + + /// BlockValueStack - This stack holds the state of the value solver + /// during a query. It basically emulates the callstack of the naive + /// recursive value lookup process. + std::stack > BlockValueStack; + + friend struct LVIValueHandle; + + /// OverDefinedCacheUpdater - A helper object that ensures that the + /// OverDefinedCache is updated whenever solveBlockValue returns. + struct OverDefinedCacheUpdater { + LazyValueInfoCache *Parent; + Value *Val; + BasicBlock *BB; + LVILatticeVal &BBLV; + + OverDefinedCacheUpdater(Value *V, BasicBlock *B, LVILatticeVal &LV, + LazyValueInfoCache *P) + : Parent(P), Val(V), BB(B), BBLV(LV) { } + + bool markResult(bool changed) { + if (changed && BBLV.isOverdefined()) + Parent->OverDefinedCache.insert(std::make_pair(BB, Val)); + return changed; + } + }; + + + + LVILatticeVal getBlockValue(Value *Val, BasicBlock *BB); + bool getEdgeValue(Value *V, BasicBlock *F, BasicBlock *T, + LVILatticeVal &Result); + bool hasBlockValue(Value *Val, BasicBlock *BB); + + // These methods process one work item and may add more. A false value + // returned means that the work item was not completely processed and must + // be revisited after going through the new items. + bool solveBlockValue(Value *Val, BasicBlock *BB); + bool solveBlockValueNonLocal(LVILatticeVal &BBLV, + Value *Val, BasicBlock *BB); + bool solveBlockValuePHINode(LVILatticeVal &BBLV, + PHINode *PN, BasicBlock *BB); + bool solveBlockValueConstantRange(LVILatticeVal &BBLV, + Instruction *BBI, BasicBlock *BB); + + void solve(); + + ValueCacheEntryTy &lookup(Value *V) { + return ValueCache[LVIValueHandle(V, this)]; + } + + public: + /// getValueInBlock - This is the query interface to determine the lattice + /// value for the specified Value* at the end of the specified block. + LVILatticeVal getValueInBlock(Value *V, BasicBlock *BB); + + /// getValueOnEdge - This is the query interface to determine the lattice + /// value for the specified Value* that is true on the specified edge. + LVILatticeVal getValueOnEdge(Value *V, BasicBlock *FromBB,BasicBlock *ToBB); + + /// threadEdge - This is the update interface to inform the cache that an + /// edge from PredBB to OldSucc has been threaded to be from PredBB to + /// NewSucc. + void threadEdge(BasicBlock *PredBB,BasicBlock *OldSucc,BasicBlock *NewSucc); + + /// eraseBlock - This is part of the update interface to inform the cache + /// that a block has been deleted. + void eraseBlock(BasicBlock *BB); + + /// clear - Empty the cache. + void clear() { + ValueCache.clear(); + OverDefinedCache.clear(); + } + }; +} // end anonymous namespace + +void LVIValueHandle::deleted() { + typedef std::pair, Value*> OverDefinedPairTy; + + SmallVector ToErase; + for (DenseSet::iterator + I = Parent->OverDefinedCache.begin(), + E = Parent->OverDefinedCache.end(); + I != E; ++I) { + if (I->second == getValPtr()) + ToErase.push_back(*I); + } + + for (SmallVector::iterator I = ToErase.begin(), + E = ToErase.end(); I != E; ++I) + Parent->OverDefinedCache.erase(*I); + + // This erasure deallocates *this, so it MUST happen after we're done + // using any and all members of *this. + Parent->ValueCache.erase(*this); +} + +void LazyValueInfoCache::eraseBlock(BasicBlock *BB) { + SmallVector ToErase; + for (DenseSet::iterator I = OverDefinedCache.begin(), + E = OverDefinedCache.end(); I != E; ++I) { + if (I->first == BB) + ToErase.push_back(*I); + } + + for (SmallVector::iterator I = ToErase.begin(), + E = ToErase.end(); I != E; ++I) + OverDefinedCache.erase(*I); + + for (DenseMap::iterator + I = ValueCache.begin(), E = ValueCache.end(); I != E; ++I) + I->second.erase(BB); +} + +void LazyValueInfoCache::solve() { + while (!BlockValueStack.empty()) { + std::pair &e = BlockValueStack.top(); + if (solveBlockValue(e.second, e.first)) + BlockValueStack.pop(); + } +} + +bool LazyValueInfoCache::hasBlockValue(Value *Val, BasicBlock *BB) { + // If already a constant, there is nothing to compute. + if (isa(Val)) + return true; + + LVIValueHandle ValHandle(Val, this); + if (!ValueCache.count(ValHandle)) return false; + return ValueCache[ValHandle].count(BB); +} + +LVILatticeVal LazyValueInfoCache::getBlockValue(Value *Val, BasicBlock *BB) { + // If already a constant, there is nothing to compute. + if (Constant *VC = dyn_cast(Val)) + return LVILatticeVal::get(VC); + + return lookup(Val)[BB]; +} + +bool LazyValueInfoCache::solveBlockValue(Value *Val, BasicBlock *BB) { + if (isa(Val)) + return true; + + ValueCacheEntryTy &Cache = lookup(Val); + LVILatticeVal &BBLV = Cache[BB]; + + // OverDefinedCacheUpdater is a helper object that will update + // the OverDefinedCache for us when this method exits. Make sure to + // call markResult on it as we exist, passing a bool to indicate if the + // cache needs updating, i.e. if we have solve a new value or not. + OverDefinedCacheUpdater ODCacheUpdater(Val, BB, BBLV, this); + + // If we've already computed this block's value, return it. + if (!BBLV.isUndefined()) { + DEBUG(dbgs() << " reuse BB '" << BB->getName() << "' val=" << BBLV <<'\n'); + + // Since we're reusing a cached value here, we don't need to update the + // OverDefinedCahce. The cache will have been properly updated + // whenever the cached value was inserted. + ODCacheUpdater.markResult(false); + return true; + } + + // Otherwise, this is the first time we're seeing this block. Reset the + // lattice value to overdefined, so that cycles will terminate and be + // conservatively correct. + BBLV.markOverdefined(); + + Instruction *BBI = dyn_cast(Val); + if (BBI == 0 || BBI->getParent() != BB) { + return ODCacheUpdater.markResult(solveBlockValueNonLocal(BBLV, Val, BB)); + } + + if (PHINode *PN = dyn_cast(BBI)) { + return ODCacheUpdater.markResult(solveBlockValuePHINode(BBLV, PN, BB)); + } + + if (AllocaInst *AI = dyn_cast(BBI)) { + BBLV = LVILatticeVal::getNot(ConstantPointerNull::get(AI->getType())); + return ODCacheUpdater.markResult(true); + } + + // We can only analyze the definitions of certain classes of instructions + // (integral binops and casts at the moment), so bail if this isn't one. + LVILatticeVal Result; + if ((!isa(BBI) && !isa(BBI)) || + !BBI->getType()->isIntegerTy()) { + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because inst def found.\n"); + BBLV.markOverdefined(); + return ODCacheUpdater.markResult(true); + } + + // FIXME: We're currently limited to binops with a constant RHS. This should + // be improved. + BinaryOperator *BO = dyn_cast(BBI); + if (BO && !isa(BO->getOperand(1))) { + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because inst def found.\n"); + + BBLV.markOverdefined(); + return ODCacheUpdater.markResult(true); + } + + return ODCacheUpdater.markResult(solveBlockValueConstantRange(BBLV, BBI, BB)); +} + +static bool InstructionDereferencesPointer(Instruction *I, Value *Ptr) { + if (LoadInst *L = dyn_cast(I)) { + return L->getPointerAddressSpace() == 0 && + GetUnderlyingObject(L->getPointerOperand()) == + GetUnderlyingObject(Ptr); + } + if (StoreInst *S = dyn_cast(I)) { + return S->getPointerAddressSpace() == 0 && + GetUnderlyingObject(S->getPointerOperand()) == + GetUnderlyingObject(Ptr); + } + if (MemIntrinsic *MI = dyn_cast(I)) { + if (MI->isVolatile()) return false; + if (MI->getAddressSpace() != 0) return false; + + // FIXME: check whether it has a valuerange that excludes zero? + ConstantInt *Len = dyn_cast(MI->getLength()); + if (!Len || Len->isZero()) return false; + + if (MI->getRawDest() == Ptr || MI->getDest() == Ptr) + return true; + if (MemTransferInst *MTI = dyn_cast(MI)) + return MTI->getRawSource() == Ptr || MTI->getSource() == Ptr; + } + return false; +} + +bool LazyValueInfoCache::solveBlockValueNonLocal(LVILatticeVal &BBLV, + Value *Val, BasicBlock *BB) { + LVILatticeVal Result; // Start Undefined. + + // If this is a pointer, and there's a load from that pointer in this BB, + // then we know that the pointer can't be NULL. + bool NotNull = false; + if (Val->getType()->isPointerTy()) { + if (isa(Val)) { + NotNull = true; + } else { + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();BI != BE;++BI){ + if (InstructionDereferencesPointer(BI, Val)) { + NotNull = true; + break; + } + } + } + } + + // If this is the entry block, we must be asking about an argument. The + // value is overdefined. + if (BB == &BB->getParent()->getEntryBlock()) { + assert(isa(Val) && "Unknown live-in to the entry block"); + if (NotNull) { + const PointerType *PTy = cast(Val->getType()); + Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); + } else { + Result.markOverdefined(); + } + BBLV = Result; + return true; + } + + // Loop over all of our predecessors, merging what we know from them into + // result. + bool EdgesMissing = false; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) { + LVILatticeVal EdgeResult; + EdgesMissing |= !getEdgeValue(Val, *PI, BB, EdgeResult); + if (EdgesMissing) + continue; + + Result.mergeIn(EdgeResult); + + // If we hit overdefined, exit early. The BlockVals entry is already set + // to overdefined. + if (Result.isOverdefined()) { + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because of pred.\n"); + // If we previously determined that this is a pointer that can't be null + // then return that rather than giving up entirely. + if (NotNull) { + const PointerType *PTy = cast(Val->getType()); + Result = LVILatticeVal::getNot(ConstantPointerNull::get(PTy)); + } + + BBLV = Result; + return true; + } + } + if (EdgesMissing) + return false; + + // Return the merged value, which is more precise than 'overdefined'. + assert(!Result.isOverdefined()); + BBLV = Result; + return true; +} + +bool LazyValueInfoCache::solveBlockValuePHINode(LVILatticeVal &BBLV, + PHINode *PN, BasicBlock *BB) { + LVILatticeVal Result; // Start Undefined. + + // Loop over all of our predecessors, merging what we know from them into + // result. + bool EdgesMissing = false; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + BasicBlock *PhiBB = PN->getIncomingBlock(i); + Value *PhiVal = PN->getIncomingValue(i); + LVILatticeVal EdgeResult; + EdgesMissing |= !getEdgeValue(PhiVal, PhiBB, BB, EdgeResult); + if (EdgesMissing) + continue; + + Result.mergeIn(EdgeResult); + + // If we hit overdefined, exit early. The BlockVals entry is already set + // to overdefined. + if (Result.isOverdefined()) { + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because of pred.\n"); + + BBLV = Result; + return true; + } + } + if (EdgesMissing) + return false; + + // Return the merged value, which is more precise than 'overdefined'. + assert(!Result.isOverdefined() && "Possible PHI in entry block?"); + BBLV = Result; + return true; +} + +bool LazyValueInfoCache::solveBlockValueConstantRange(LVILatticeVal &BBLV, + Instruction *BBI, + BasicBlock *BB) { + // Figure out the range of the LHS. If that fails, bail. + if (!hasBlockValue(BBI->getOperand(0), BB)) { + BlockValueStack.push(std::make_pair(BB, BBI->getOperand(0))); + return false; + } + + LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB); + if (!LHSVal.isConstantRange()) { + BBLV.markOverdefined(); + return true; + } + + ConstantRange LHSRange = LHSVal.getConstantRange(); + ConstantRange RHSRange(1); + const IntegerType *ResultTy = cast(BBI->getType()); + if (isa(BBI)) { + if (ConstantInt *RHS = dyn_cast(BBI->getOperand(1))) { + RHSRange = ConstantRange(RHS->getValue()); + } else { + BBLV.markOverdefined(); + return true; + } + } + + // NOTE: We're currently limited by the set of operations that ConstantRange + // can evaluate symbolically. Enhancing that set will allows us to analyze + // more definitions. + LVILatticeVal Result; + switch (BBI->getOpcode()) { + case Instruction::Add: + Result.markConstantRange(LHSRange.add(RHSRange)); + break; + case Instruction::Sub: + Result.markConstantRange(LHSRange.sub(RHSRange)); + break; + case Instruction::Mul: + Result.markConstantRange(LHSRange.multiply(RHSRange)); + break; + case Instruction::UDiv: + Result.markConstantRange(LHSRange.udiv(RHSRange)); + break; + case Instruction::Shl: + Result.markConstantRange(LHSRange.shl(RHSRange)); + break; + case Instruction::LShr: + Result.markConstantRange(LHSRange.lshr(RHSRange)); + break; + case Instruction::Trunc: + Result.markConstantRange(LHSRange.truncate(ResultTy->getBitWidth())); + break; + case Instruction::SExt: + Result.markConstantRange(LHSRange.signExtend(ResultTy->getBitWidth())); + break; + case Instruction::ZExt: + Result.markConstantRange(LHSRange.zeroExtend(ResultTy->getBitWidth())); + break; + case Instruction::BitCast: + Result.markConstantRange(LHSRange); + break; + case Instruction::And: + Result.markConstantRange(LHSRange.binaryAnd(RHSRange)); + break; + case Instruction::Or: + Result.markConstantRange(LHSRange.binaryOr(RHSRange)); + break; + + // Unhandled instructions are overdefined. + default: + DEBUG(dbgs() << " compute BB '" << BB->getName() + << "' - overdefined because inst def found.\n"); + Result.markOverdefined(); + break; + } + + BBLV = Result; + return true; +} + +/// getEdgeValue - This method attempts to infer more complex +bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, + BasicBlock *BBTo, LVILatticeVal &Result) { + // If already a constant, there is nothing to compute. + if (Constant *VC = dyn_cast(Val)) { + Result = LVILatticeVal::get(VC); + return true; + } + + // TODO: Handle more complex conditionals. If (v == 0 || v2 < 1) is false, we + // know that v != 0. + if (BranchInst *BI = dyn_cast(BBFrom->getTerminator())) { + // If this is a conditional branch and only one successor goes to BBTo, then + // we maybe able to infer something from the condition. + if (BI->isConditional() && + BI->getSuccessor(0) != BI->getSuccessor(1)) { + bool isTrueDest = BI->getSuccessor(0) == BBTo; + assert(BI->getSuccessor(!isTrueDest) == BBTo && + "BBTo isn't a successor of BBFrom"); + + // If V is the condition of the branch itself, then we know exactly what + // it is. + if (BI->getCondition() == Val) { + Result = LVILatticeVal::get(ConstantInt::get( + Type::getInt1Ty(Val->getContext()), isTrueDest)); + return true; + } + + // If the condition of the branch is an equality comparison, we may be + // able to infer the value. + ICmpInst *ICI = dyn_cast(BI->getCondition()); + if (ICI && ICI->getOperand(0) == Val && + isa(ICI->getOperand(1))) { + if (ICI->isEquality()) { + // We know that V has the RHS constant if this is a true SETEQ or + // false SETNE. + if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ)) + Result = LVILatticeVal::get(cast(ICI->getOperand(1))); + else + Result = LVILatticeVal::getNot(cast(ICI->getOperand(1))); + return true; + } + + if (ConstantInt *CI = dyn_cast(ICI->getOperand(1))) { + // Calculate the range of values that would satisfy the comparison. + ConstantRange CmpRange(CI->getValue(), CI->getValue()+1); + ConstantRange TrueValues = + ConstantRange::makeICmpRegion(ICI->getPredicate(), CmpRange); + + // If we're interested in the false dest, invert the condition. + if (!isTrueDest) TrueValues = TrueValues.inverse(); + + // Figure out the possible values of the query BEFORE this branch. + if (!hasBlockValue(Val, BBFrom)) { + BlockValueStack.push(std::make_pair(BBFrom, Val)); + return false; + } + + LVILatticeVal InBlock = getBlockValue(Val, BBFrom); + if (!InBlock.isConstantRange()) { + Result = LVILatticeVal::getRange(TrueValues); + return true; + } + + // Find all potential values that satisfy both the input and output + // conditions. + ConstantRange PossibleValues = + TrueValues.intersectWith(InBlock.getConstantRange()); + + Result = LVILatticeVal::getRange(PossibleValues); + return true; + } + } + } + } + + // If the edge was formed by a switch on the value, then we may know exactly + // what it is. + if (SwitchInst *SI = dyn_cast(BBFrom->getTerminator())) { + if (SI->getCondition() == Val) { + // We don't know anything in the default case. + if (SI->getDefaultDest() == BBTo) { + Result.markOverdefined(); + return true; + } + + // We only know something if there is exactly one value that goes from + // BBFrom to BBTo. + unsigned NumEdges = 0; + ConstantInt *EdgeVal = 0; + for (unsigned i = 1, e = SI->getNumSuccessors(); i != e; ++i) { + if (SI->getSuccessor(i) != BBTo) continue; + if (NumEdges++) break; + EdgeVal = SI->getCaseValue(i); + } + assert(EdgeVal && "Missing successor?"); + if (NumEdges == 1) { + Result = LVILatticeVal::get(EdgeVal); + return true; + } + } + } + + // Otherwise see if the value is known in the block. + if (hasBlockValue(Val, BBFrom)) { + Result = getBlockValue(Val, BBFrom); + return true; + } + BlockValueStack.push(std::make_pair(BBFrom, Val)); + return false; +} + +LVILatticeVal LazyValueInfoCache::getValueInBlock(Value *V, BasicBlock *BB) { + DEBUG(dbgs() << "LVI Getting block end value " << *V << " at '" + << BB->getName() << "'\n"); + + BlockValueStack.push(std::make_pair(BB, V)); + solve(); + LVILatticeVal Result = getBlockValue(V, BB); + + DEBUG(dbgs() << " Result = " << Result << "\n"); + return Result; +} + +LVILatticeVal LazyValueInfoCache:: +getValueOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB) { + DEBUG(dbgs() << "LVI Getting edge value " << *V << " from '" + << FromBB->getName() << "' to '" << ToBB->getName() << "'\n"); + + LVILatticeVal Result; + if (!getEdgeValue(V, FromBB, ToBB, Result)) { + solve(); + bool WasFastQuery = getEdgeValue(V, FromBB, ToBB, Result); + (void)WasFastQuery; + assert(WasFastQuery && "More work to do after problem solved?"); + } + + DEBUG(dbgs() << " Result = " << Result << "\n"); + return Result; +} + +void LazyValueInfoCache::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, + BasicBlock *NewSucc) { + // When an edge in the graph has been threaded, values that we could not + // determine a value for before (i.e. were marked overdefined) may be possible + // to solve now. We do NOT try to proactively update these values. Instead, + // we clear their entries from the cache, and allow lazy updating to recompute + // them when needed. + + // The updating process is fairly simple: we need to dropped cached info + // for all values that were marked overdefined in OldSucc, and for those same + // values in any successor of OldSucc (except NewSucc) in which they were + // also marked overdefined. + std::vector worklist; + worklist.push_back(OldSucc); + + DenseSet ClearSet; + for (DenseSet::iterator I = OverDefinedCache.begin(), + E = OverDefinedCache.end(); I != E; ++I) { + if (I->first == OldSucc) + ClearSet.insert(I->second); + } + + // Use a worklist to perform a depth-first search of OldSucc's successors. + // NOTE: We do not need a visited list since any blocks we have already + // visited will have had their overdefined markers cleared already, and we + // thus won't loop to their successors. + while (!worklist.empty()) { + BasicBlock *ToUpdate = worklist.back(); + worklist.pop_back(); + + // Skip blocks only accessible through NewSucc. + if (ToUpdate == NewSucc) continue; + + bool changed = false; + for (DenseSet::iterator I = ClearSet.begin(), E = ClearSet.end(); + I != E; ++I) { + // If a value was marked overdefined in OldSucc, and is here too... + DenseSet::iterator OI = + OverDefinedCache.find(std::make_pair(ToUpdate, *I)); + if (OI == OverDefinedCache.end()) continue; + + // Remove it from the caches. + ValueCacheEntryTy &Entry = ValueCache[LVIValueHandle(*I, this)]; + ValueCacheEntryTy::iterator CI = Entry.find(ToUpdate); + + assert(CI != Entry.end() && "Couldn't find entry to update?"); + Entry.erase(CI); + OverDefinedCache.erase(OI); + + // If we removed anything, then we potentially need to update + // blocks successors too. + changed = true; + } + + if (!changed) continue; + + worklist.insert(worklist.end(), succ_begin(ToUpdate), succ_end(ToUpdate)); + } +} + +//===----------------------------------------------------------------------===// +// LazyValueInfo Impl +//===----------------------------------------------------------------------===// + +/// getCache - This lazily constructs the LazyValueInfoCache. +static LazyValueInfoCache &getCache(void *&PImpl) { + if (!PImpl) + PImpl = new LazyValueInfoCache(); + return *static_cast(PImpl); +} + +bool LazyValueInfo::runOnFunction(Function &F) { + if (PImpl) + getCache(PImpl).clear(); + + TD = getAnalysisIfAvailable(); + // Fully lazy. + return false; +} + +void LazyValueInfo::releaseMemory() { + // If the cache was allocated, free it. + if (PImpl) { + delete &getCache(PImpl); + PImpl = 0; + } +} + +Constant *LazyValueInfo::getConstant(Value *V, BasicBlock *BB) { + LVILatticeVal Result = getCache(PImpl).getValueInBlock(V, BB); + + if (Result.isConstant()) + return Result.getConstant(); + if (Result.isConstantRange()) { + ConstantRange CR = Result.getConstantRange(); + if (const APInt *SingleVal = CR.getSingleElement()) + return ConstantInt::get(V->getContext(), *SingleVal); + } + return 0; +} + +/// getConstantOnEdge - Determine whether the specified value is known to be a +/// constant on the specified edge. Return null if not. +Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB, + BasicBlock *ToBB) { + LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); + + if (Result.isConstant()) + return Result.getConstant(); + if (Result.isConstantRange()) { + ConstantRange CR = Result.getConstantRange(); + if (const APInt *SingleVal = CR.getSingleElement()) + return ConstantInt::get(V->getContext(), *SingleVal); + } + return 0; +} + +/// getPredicateOnEdge - Determine whether the specified value comparison +/// with a constant is known to be true or false on the specified CFG edge. +/// Pred is a CmpInst predicate. +LazyValueInfo::Tristate +LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, + BasicBlock *FromBB, BasicBlock *ToBB) { + LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); + + // If we know the value is a constant, evaluate the conditional. + Constant *Res = 0; + if (Result.isConstant()) { + Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, TD); + if (ConstantInt *ResCI = dyn_cast(Res)) + return ResCI->isZero() ? False : True; + return Unknown; + } + + if (Result.isConstantRange()) { + ConstantInt *CI = dyn_cast(C); + if (!CI) return Unknown; + + ConstantRange CR = Result.getConstantRange(); + if (Pred == ICmpInst::ICMP_EQ) { + if (!CR.contains(CI->getValue())) + return False; + + if (CR.isSingleElement() && CR.contains(CI->getValue())) + return True; + } else if (Pred == ICmpInst::ICMP_NE) { + if (!CR.contains(CI->getValue())) + return True; + + if (CR.isSingleElement() && CR.contains(CI->getValue())) + return False; + } + + // Handle more complex predicates. + ConstantRange TrueValues = + ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue()); + if (TrueValues.contains(CR)) + return True; + if (TrueValues.inverse().contains(CR)) + return False; + return Unknown; + } + + if (Result.isNotConstant()) { + // If this is an equality comparison, we can try to fold it knowing that + // "V != C1". + if (Pred == ICmpInst::ICMP_EQ) { + // !C1 == C -> false iff C1 == C. + Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, + Result.getNotConstant(), C, TD); + if (Res->isNullValue()) + return False; + } else if (Pred == ICmpInst::ICMP_NE) { + // !C1 != C -> true iff C1 == C. + Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, + Result.getNotConstant(), C, TD); + if (Res->isNullValue()) + return True; + } + return Unknown; + } + + return Unknown; +} + +void LazyValueInfo::threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, + BasicBlock *NewSucc) { + if (PImpl) getCache(PImpl).threadEdge(PredBB, OldSucc, NewSucc); +} + +void LazyValueInfo::eraseBlock(BasicBlock *BB) { + if (PImpl) getCache(PImpl).eraseBlock(BB); +} diff --git a/final/lib/Analysis/LibCallAliasAnalysis.cpp b/final/lib/Analysis/LibCallAliasAnalysis.cpp new file mode 100644 index 00000000000..efb722bb97c --- /dev/null +++ b/final/lib/Analysis/LibCallAliasAnalysis.cpp @@ -0,0 +1,137 @@ +//===- LibCallAliasAnalysis.cpp - Implement AliasAnalysis for libcalls ----===// +// +// 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 LibCallAliasAnalysis class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LibCallAliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/LibCallSemantics.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +using namespace llvm; + +// Register this pass... +char LibCallAliasAnalysis::ID = 0; +INITIALIZE_AG_PASS(LibCallAliasAnalysis, AliasAnalysis, "libcall-aa", + "LibCall Alias Analysis", false, true, false) + +FunctionPass *llvm::createLibCallAliasAnalysisPass(LibCallInfo *LCI) { + return new LibCallAliasAnalysis(LCI); +} + +LibCallAliasAnalysis::~LibCallAliasAnalysis() { + delete LCI; +} + +void LibCallAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + AU.setPreservesAll(); // Does not transform code +} + + + +/// AnalyzeLibCallDetails - Given a call to a function with the specified +/// LibCallFunctionInfo, see if we can improve the mod/ref footprint of the call +/// vs the specified pointer/size. +AliasAnalysis::ModRefResult +LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, + ImmutableCallSite CS, + const Location &Loc) { + // If we have a function, check to see what kind of mod/ref effects it + // has. Start by including any info globally known about the function. + AliasAnalysis::ModRefResult MRInfo = FI->UniversalBehavior; + if (MRInfo == NoModRef) return MRInfo; + + // If that didn't tell us that the function is 'readnone', check to see + // if we have detailed info and if 'P' is any of the locations we know + // about. + const LibCallFunctionInfo::LocationMRInfo *Details = FI->LocationDetails; + if (Details == 0) + return MRInfo; + + // If the details array is of the 'DoesNot' kind, we only know something if + // the pointer is a match for one of the locations in 'Details'. If we find a + // match, we can prove some interactions cannot happen. + // + if (FI->DetailsType == LibCallFunctionInfo::DoesNot) { + // Find out if the pointer refers to a known location. + for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) { + const LibCallLocationInfo &LocInfo = + LCI->getLocationInfo(Details[i].LocationID); + LibCallLocationInfo::LocResult Res = LocInfo.isLocation(CS, Loc); + if (Res != LibCallLocationInfo::Yes) continue; + + // If we find a match against a location that we 'do not' interact with, + // learn this info into MRInfo. + return ModRefResult(MRInfo & ~Details[i].MRInfo); + } + return MRInfo; + } + + // If the details are of the 'DoesOnly' sort, we know something if the pointer + // is a match for one of the locations in 'Details'. Also, if we can prove + // that the pointers is *not* one of the locations in 'Details', we know that + // the call is NoModRef. + assert(FI->DetailsType == LibCallFunctionInfo::DoesOnly); + + // Find out if the pointer refers to a known location. + bool NoneMatch = true; + for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) { + const LibCallLocationInfo &LocInfo = + LCI->getLocationInfo(Details[i].LocationID); + LibCallLocationInfo::LocResult Res = LocInfo.isLocation(CS, Loc); + if (Res == LibCallLocationInfo::No) continue; + + // If we don't know if this pointer points to the location, then we have to + // assume it might alias in some case. + if (Res == LibCallLocationInfo::Unknown) { + NoneMatch = false; + continue; + } + + // If we know that this pointer definitely is pointing into the location, + // merge in this information. + return ModRefResult(MRInfo & Details[i].MRInfo); + } + + // If we found that the pointer is guaranteed to not match any of the + // locations in our 'DoesOnly' rule, then we know that the pointer must point + // to some other location. Since the libcall doesn't mod/ref any other + // locations, return NoModRef. + if (NoneMatch) + return NoModRef; + + // Otherwise, return any other info gained so far. + return MRInfo; +} + +// getModRefInfo - Check to see if the specified callsite can clobber the +// specified memory object. +// +AliasAnalysis::ModRefResult +LibCallAliasAnalysis::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + ModRefResult MRInfo = ModRef; + + // If this is a direct call to a function that LCI knows about, get the + // information about the runtime function. + if (LCI) { + if (const Function *F = CS.getCalledFunction()) { + if (const LibCallFunctionInfo *FI = LCI->getFunctionInfo(F)) { + MRInfo = ModRefResult(MRInfo & AnalyzeLibCallDetails(FI, CS, Loc)); + if (MRInfo == NoModRef) return NoModRef; + } + } + } + + // The AliasAnalysis base class has some smarts, lets use them. + return (ModRefResult)(MRInfo | AliasAnalysis::getModRefInfo(CS, Loc)); +} diff --git a/final/lib/Analysis/LibCallSemantics.cpp b/final/lib/Analysis/LibCallSemantics.cpp new file mode 100644 index 00000000000..81b0f46f374 --- /dev/null +++ b/final/lib/Analysis/LibCallSemantics.cpp @@ -0,0 +1,63 @@ +//===- LibCallSemantics.cpp - Describe library semantics ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements interfaces that can be used to describe language +// specific runtime library interfaces (e.g. libc, libm, etc) to LLVM +// optimizers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LibCallSemantics.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Function.h" +using namespace llvm; + +/// getMap - This impl pointer in ~LibCallInfo is actually a StringMap. This +/// helper does the cast. +static StringMap *getMap(void *Ptr) { + return static_cast *>(Ptr); +} + +LibCallInfo::~LibCallInfo() { + delete getMap(Impl); +} + +const LibCallLocationInfo &LibCallInfo::getLocationInfo(unsigned LocID) const { + // Get location info on the first call. + if (NumLocations == 0) + NumLocations = getLocationInfo(Locations); + + assert(LocID < NumLocations && "Invalid location ID!"); + return Locations[LocID]; +} + + +/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to +/// the specified function if we have it. If not, return null. +const LibCallFunctionInfo * +LibCallInfo::getFunctionInfo(const Function *F) const { + StringMap *Map = getMap(Impl); + + /// If this is the first time we are querying for this info, lazily construct + /// the StringMap to index it. + if (Map == 0) { + Impl = Map = new StringMap(); + + const LibCallFunctionInfo *Array = getFunctionInfoArray(); + if (Array == 0) return 0; + + // We now have the array of entries. Populate the StringMap. + for (unsigned i = 0; Array[i].Name; ++i) + (*Map)[Array[i].Name] = Array+i; + } + + // Look up this function in the string map. + return Map->lookup(F->getName()); +} + diff --git a/final/lib/Analysis/Lint.cpp b/final/lib/Analysis/Lint.cpp new file mode 100644 index 00000000000..fc7edc0525f --- /dev/null +++ b/final/lib/Analysis/Lint.cpp @@ -0,0 +1,658 @@ +//===-- Lint.cpp - Check for common errors in LLVM IR ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass statically checks for common and easily-identified constructs +// which produce undefined or likely unintended behavior in LLVM IR. +// +// It is not a guarantee of correctness, in two ways. First, it isn't +// comprehensive. There are checks which could be done statically which are +// not yet implemented. Some of these are indicated by TODO comments, but +// those aren't comprehensive either. Second, many conditions cannot be +// checked statically. This pass does no dynamic instrumentation, so it +// can't check for all possible problems. +// +// Another limitation is that it assumes all code will be executed. A store +// through a null pointer in a basic block which is never reached is harmless, +// but this pass will warn about it anyway. This is the main reason why most +// of these checks live here instead of in the Verifier pass. +// +// Optimization passes may make conditions that this pass checks for more or +// less obvious. If an optimization pass appears to be introducing a warning, +// it may be that the optimization pass is merely exposing an existing +// condition in the code. +// +// This code may be run before instcombine. In many cases, instcombine checks +// for the same kinds of things and turns instructions with undefined behavior +// into unreachable (or equivalent). Because of this, this pass makes some +// effort to look through bitcasts and so on. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/Lint.h" +#include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Pass.h" +#include "llvm/PassManager.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Function.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +namespace { + namespace MemRef { + static unsigned Read = 1; + static unsigned Write = 2; + static unsigned Callee = 4; + static unsigned Branchee = 8; + } + + class Lint : public FunctionPass, public InstVisitor { + friend class InstVisitor; + + void visitFunction(Function &F); + + void visitCallSite(CallSite CS); + void visitMemoryReference(Instruction &I, Value *Ptr, + uint64_t Size, unsigned Align, + const Type *Ty, unsigned Flags); + + void visitCallInst(CallInst &I); + void visitInvokeInst(InvokeInst &I); + void visitReturnInst(ReturnInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitXor(BinaryOperator &I); + void visitSub(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + void visitShl(BinaryOperator &I); + void visitSDiv(BinaryOperator &I); + void visitUDiv(BinaryOperator &I); + void visitSRem(BinaryOperator &I); + void visitURem(BinaryOperator &I); + void visitAllocaInst(AllocaInst &I); + void visitVAArgInst(VAArgInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + void visitExtractElementInst(ExtractElementInst &I); + void visitInsertElementInst(InsertElementInst &I); + void visitUnreachableInst(UnreachableInst &I); + + Value *findValue(Value *V, bool OffsetOk) const; + Value *findValueImpl(Value *V, bool OffsetOk, + SmallPtrSet &Visited) const; + + public: + Module *Mod; + AliasAnalysis *AA; + DominatorTree *DT; + TargetData *TD; + + std::string Messages; + raw_string_ostream MessagesStr; + + static char ID; // Pass identification, replacement for typeid + Lint() : FunctionPass(ID), MessagesStr(Messages) { + initializeLintPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + } + virtual void print(raw_ostream &O, const Module *M) const {} + + void WriteValue(const Value *V) { + if (!V) return; + if (isa(V)) { + MessagesStr << *V << '\n'; + } else { + WriteAsOperand(MessagesStr, V, true, Mod); + MessagesStr << '\n'; + } + } + + // CheckFailed - A check failed, so print out the condition and the message + // that failed. This provides a nice place to put a breakpoint if you want + // to see why something is not correct. + void CheckFailed(const Twine &Message, + const Value *V1 = 0, const Value *V2 = 0, + const Value *V3 = 0, const Value *V4 = 0) { + MessagesStr << Message.str() << "\n"; + WriteValue(V1); + WriteValue(V2); + WriteValue(V3); + WriteValue(V4); + } + }; +} + +char Lint::ID = 0; +INITIALIZE_PASS_BEGIN(Lint, "lint", "Statically lint-checks LLVM IR", + false, true) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR", + false, true) + +// Assert - We know that cond should be true, if not print an error message. +#define Assert(C, M) \ + do { if (!(C)) { CheckFailed(M); return; } } while (0) +#define Assert1(C, M, V1) \ + do { if (!(C)) { CheckFailed(M, V1); return; } } while (0) +#define Assert2(C, M, V1, V2) \ + do { if (!(C)) { CheckFailed(M, V1, V2); return; } } while (0) +#define Assert3(C, M, V1, V2, V3) \ + do { if (!(C)) { CheckFailed(M, V1, V2, V3); return; } } while (0) +#define Assert4(C, M, V1, V2, V3, V4) \ + do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0) + +// Lint::run - This is the main Analysis entry point for a +// function. +// +bool Lint::runOnFunction(Function &F) { + Mod = F.getParent(); + AA = &getAnalysis(); + DT = &getAnalysis(); + TD = getAnalysisIfAvailable(); + visit(F); + dbgs() << MessagesStr.str(); + Messages.clear(); + return false; +} + +void Lint::visitFunction(Function &F) { + // This isn't undefined behavior, it's just a little unusual, and it's a + // fairly common mistake to neglect to name a function. + Assert1(F.hasName() || F.hasLocalLinkage(), + "Unusual: Unnamed function with non-local linkage", &F); + + // TODO: Check for irreducible control flow. +} + +void Lint::visitCallSite(CallSite CS) { + Instruction &I = *CS.getInstruction(); + Value *Callee = CS.getCalledValue(); + + visitMemoryReference(I, Callee, AliasAnalysis::UnknownSize, + 0, 0, MemRef::Callee); + + if (Function *F = dyn_cast(findValue(Callee, /*OffsetOk=*/false))) { + Assert1(CS.getCallingConv() == F->getCallingConv(), + "Undefined behavior: Caller and callee calling convention differ", + &I); + + const FunctionType *FT = F->getFunctionType(); + unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin()); + + Assert1(FT->isVarArg() ? + FT->getNumParams() <= NumActualArgs : + FT->getNumParams() == NumActualArgs, + "Undefined behavior: Call argument count mismatches callee " + "argument count", &I); + + Assert1(FT->getReturnType() == I.getType(), + "Undefined behavior: Call return type mismatches " + "callee return type", &I); + + // Check argument types (in case the callee was casted) and attributes. + // TODO: Verify that caller and callee attributes are compatible. + Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end(); + CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + for (; AI != AE; ++AI) { + Value *Actual = *AI; + if (PI != PE) { + Argument *Formal = PI++; + Assert1(Formal->getType() == Actual->getType(), + "Undefined behavior: Call argument type mismatches " + "callee parameter type", &I); + + // Check that noalias arguments don't alias other arguments. This is + // not fully precise because we don't know the sizes of the dereferenced + // memory regions. + if (Formal->hasNoAliasAttr() && Actual->getType()->isPointerTy()) + for (CallSite::arg_iterator BI = CS.arg_begin(); BI != AE; ++BI) + if (AI != BI && (*BI)->getType()->isPointerTy()) { + AliasAnalysis::AliasResult Result = AA->alias(*AI, *BI); + Assert1(Result != AliasAnalysis::MustAlias && + Result != AliasAnalysis::PartialAlias, + "Unusual: noalias argument aliases another argument", &I); + } + + // Check that an sret argument points to valid memory. + if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { + const Type *Ty = + cast(Formal->getType())->getElementType(); + visitMemoryReference(I, Actual, AA->getTypeStoreSize(Ty), + TD ? TD->getABITypeAlignment(Ty) : 0, + Ty, MemRef::Read | MemRef::Write); + } + } + } + } + + if (CS.isCall() && cast(CS.getInstruction())->isTailCall()) + for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + AI != AE; ++AI) { + Value *Obj = findValue(*AI, /*OffsetOk=*/true); + Assert1(!isa(Obj), + "Undefined behavior: Call with \"tail\" keyword references " + "alloca", &I); + } + + + if (IntrinsicInst *II = dyn_cast(&I)) + switch (II->getIntrinsicID()) { + default: break; + + // TODO: Check more intrinsics + + case Intrinsic::memcpy: { + MemCpyInst *MCI = cast(&I); + // TODO: If the size is known, use it. + visitMemoryReference(I, MCI->getDest(), AliasAnalysis::UnknownSize, + MCI->getAlignment(), 0, + MemRef::Write); + visitMemoryReference(I, MCI->getSource(), AliasAnalysis::UnknownSize, + MCI->getAlignment(), 0, + MemRef::Read); + + // Check that the memcpy arguments don't overlap. The AliasAnalysis API + // isn't expressive enough for what we really want to do. Known partial + // overlap is not distinguished from the case where nothing is known. + uint64_t Size = 0; + if (const ConstantInt *Len = + dyn_cast(findValue(MCI->getLength(), + /*OffsetOk=*/false))) + if (Len->getValue().isIntN(32)) + Size = Len->getValue().getZExtValue(); + Assert1(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != + AliasAnalysis::MustAlias, + "Undefined behavior: memcpy source and destination overlap", &I); + break; + } + case Intrinsic::memmove: { + MemMoveInst *MMI = cast(&I); + // TODO: If the size is known, use it. + visitMemoryReference(I, MMI->getDest(), AliasAnalysis::UnknownSize, + MMI->getAlignment(), 0, + MemRef::Write); + visitMemoryReference(I, MMI->getSource(), AliasAnalysis::UnknownSize, + MMI->getAlignment(), 0, + MemRef::Read); + break; + } + case Intrinsic::memset: { + MemSetInst *MSI = cast(&I); + // TODO: If the size is known, use it. + visitMemoryReference(I, MSI->getDest(), AliasAnalysis::UnknownSize, + MSI->getAlignment(), 0, + MemRef::Write); + break; + } + + case Intrinsic::vastart: + Assert1(I.getParent()->getParent()->isVarArg(), + "Undefined behavior: va_start called in a non-varargs function", + &I); + + visitMemoryReference(I, CS.getArgument(0), AliasAnalysis::UnknownSize, + 0, 0, MemRef::Read | MemRef::Write); + break; + case Intrinsic::vacopy: + visitMemoryReference(I, CS.getArgument(0), AliasAnalysis::UnknownSize, + 0, 0, MemRef::Write); + visitMemoryReference(I, CS.getArgument(1), AliasAnalysis::UnknownSize, + 0, 0, MemRef::Read); + break; + case Intrinsic::vaend: + visitMemoryReference(I, CS.getArgument(0), AliasAnalysis::UnknownSize, + 0, 0, MemRef::Read | MemRef::Write); + break; + + case Intrinsic::stackrestore: + // Stackrestore doesn't read or write memory, but it sets the + // stack pointer, which the compiler may read from or write to + // at any time, so check it for both readability and writeability. + visitMemoryReference(I, CS.getArgument(0), AliasAnalysis::UnknownSize, + 0, 0, MemRef::Read | MemRef::Write); + break; + } +} + +void Lint::visitCallInst(CallInst &I) { + return visitCallSite(&I); +} + +void Lint::visitInvokeInst(InvokeInst &I) { + return visitCallSite(&I); +} + +void Lint::visitReturnInst(ReturnInst &I) { + Function *F = I.getParent()->getParent(); + Assert1(!F->doesNotReturn(), + "Unusual: Return statement in function with noreturn attribute", + &I); + + if (Value *V = I.getReturnValue()) { + Value *Obj = findValue(V, /*OffsetOk=*/true); + Assert1(!isa(Obj), + "Unusual: Returning alloca value", &I); + } +} + +// TODO: Check that the reference is in bounds. +// TODO: Check readnone/readonly function attributes. +void Lint::visitMemoryReference(Instruction &I, + Value *Ptr, uint64_t Size, unsigned Align, + const Type *Ty, unsigned Flags) { + // If no memory is being referenced, it doesn't matter if the pointer + // is valid. + if (Size == 0) + return; + + Value *UnderlyingObject = findValue(Ptr, /*OffsetOk=*/true); + Assert1(!isa(UnderlyingObject), + "Undefined behavior: Null pointer dereference", &I); + Assert1(!isa(UnderlyingObject), + "Undefined behavior: Undef pointer dereference", &I); + Assert1(!isa(UnderlyingObject) || + !cast(UnderlyingObject)->isAllOnesValue(), + "Unusual: All-ones pointer dereference", &I); + Assert1(!isa(UnderlyingObject) || + !cast(UnderlyingObject)->isOne(), + "Unusual: Address one pointer dereference", &I); + + if (Flags & MemRef::Write) { + if (const GlobalVariable *GV = dyn_cast(UnderlyingObject)) + Assert1(!GV->isConstant(), + "Undefined behavior: Write to read-only memory", &I); + Assert1(!isa(UnderlyingObject) && + !isa(UnderlyingObject), + "Undefined behavior: Write to text section", &I); + } + if (Flags & MemRef::Read) { + Assert1(!isa(UnderlyingObject), + "Unusual: Load from function body", &I); + Assert1(!isa(UnderlyingObject), + "Undefined behavior: Load from block address", &I); + } + if (Flags & MemRef::Callee) { + Assert1(!isa(UnderlyingObject), + "Undefined behavior: Call to block address", &I); + } + if (Flags & MemRef::Branchee) { + Assert1(!isa(UnderlyingObject) || + isa(UnderlyingObject), + "Undefined behavior: Branch to non-blockaddress", &I); + } + + if (TD) { + if (Align == 0 && Ty) Align = TD->getABITypeAlignment(Ty); + + if (Align != 0) { + unsigned BitWidth = TD->getTypeSizeInBits(Ptr->getType()); + APInt Mask = APInt::getAllOnesValue(BitWidth), + KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + ComputeMaskedBits(Ptr, Mask, KnownZero, KnownOne, TD); + Assert1(!(KnownOne & APInt::getLowBitsSet(BitWidth, Log2_32(Align))), + "Undefined behavior: Memory reference address is misaligned", &I); + } + } +} + +void Lint::visitLoadInst(LoadInst &I) { + visitMemoryReference(I, I.getPointerOperand(), + AA->getTypeStoreSize(I.getType()), I.getAlignment(), + I.getType(), MemRef::Read); +} + +void Lint::visitStoreInst(StoreInst &I) { + visitMemoryReference(I, I.getPointerOperand(), + AA->getTypeStoreSize(I.getOperand(0)->getType()), + I.getAlignment(), + I.getOperand(0)->getType(), MemRef::Write); +} + +void Lint::visitXor(BinaryOperator &I) { + Assert1(!isa(I.getOperand(0)) || + !isa(I.getOperand(1)), + "Undefined result: xor(undef, undef)", &I); +} + +void Lint::visitSub(BinaryOperator &I) { + Assert1(!isa(I.getOperand(0)) || + !isa(I.getOperand(1)), + "Undefined result: sub(undef, undef)", &I); +} + +void Lint::visitLShr(BinaryOperator &I) { + if (ConstantInt *CI = + dyn_cast(findValue(I.getOperand(1), /*OffsetOk=*/false))) + Assert1(CI->getValue().ult(cast(I.getType())->getBitWidth()), + "Undefined result: Shift count out of range", &I); +} + +void Lint::visitAShr(BinaryOperator &I) { + if (ConstantInt *CI = + dyn_cast(findValue(I.getOperand(1), /*OffsetOk=*/false))) + Assert1(CI->getValue().ult(cast(I.getType())->getBitWidth()), + "Undefined result: Shift count out of range", &I); +} + +void Lint::visitShl(BinaryOperator &I) { + if (ConstantInt *CI = + dyn_cast(findValue(I.getOperand(1), /*OffsetOk=*/false))) + Assert1(CI->getValue().ult(cast(I.getType())->getBitWidth()), + "Undefined result: Shift count out of range", &I); +} + +static bool isZero(Value *V, TargetData *TD) { + // Assume undef could be zero. + if (isa(V)) return true; + + unsigned BitWidth = cast(V->getType())->getBitWidth(); + APInt Mask = APInt::getAllOnesValue(BitWidth), + KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD); + return KnownZero.isAllOnesValue(); +} + +void Lint::visitSDiv(BinaryOperator &I) { + Assert1(!isZero(I.getOperand(1), TD), + "Undefined behavior: Division by zero", &I); +} + +void Lint::visitUDiv(BinaryOperator &I) { + Assert1(!isZero(I.getOperand(1), TD), + "Undefined behavior: Division by zero", &I); +} + +void Lint::visitSRem(BinaryOperator &I) { + Assert1(!isZero(I.getOperand(1), TD), + "Undefined behavior: Division by zero", &I); +} + +void Lint::visitURem(BinaryOperator &I) { + Assert1(!isZero(I.getOperand(1), TD), + "Undefined behavior: Division by zero", &I); +} + +void Lint::visitAllocaInst(AllocaInst &I) { + if (isa(I.getArraySize())) + // This isn't undefined behavior, it's just an obvious pessimization. + Assert1(&I.getParent()->getParent()->getEntryBlock() == I.getParent(), + "Pessimization: Static alloca outside of entry block", &I); + + // TODO: Check for an unusual size (MSB set?) +} + +void Lint::visitVAArgInst(VAArgInst &I) { + visitMemoryReference(I, I.getOperand(0), AliasAnalysis::UnknownSize, 0, 0, + MemRef::Read | MemRef::Write); +} + +void Lint::visitIndirectBrInst(IndirectBrInst &I) { + visitMemoryReference(I, I.getAddress(), AliasAnalysis::UnknownSize, 0, 0, + MemRef::Branchee); + + Assert1(I.getNumDestinations() != 0, + "Undefined behavior: indirectbr with no destinations", &I); +} + +void Lint::visitExtractElementInst(ExtractElementInst &I) { + if (ConstantInt *CI = + dyn_cast(findValue(I.getIndexOperand(), + /*OffsetOk=*/false))) + Assert1(CI->getValue().ult(I.getVectorOperandType()->getNumElements()), + "Undefined result: extractelement index out of range", &I); +} + +void Lint::visitInsertElementInst(InsertElementInst &I) { + if (ConstantInt *CI = + dyn_cast(findValue(I.getOperand(2), + /*OffsetOk=*/false))) + Assert1(CI->getValue().ult(I.getType()->getNumElements()), + "Undefined result: insertelement index out of range", &I); +} + +void Lint::visitUnreachableInst(UnreachableInst &I) { + // This isn't undefined behavior, it's merely suspicious. + Assert1(&I == I.getParent()->begin() || + prior(BasicBlock::iterator(&I))->mayHaveSideEffects(), + "Unusual: unreachable immediately preceded by instruction without " + "side effects", &I); +} + +/// findValue - Look through bitcasts and simple memory reference patterns +/// to identify an equivalent, but more informative, value. If OffsetOk +/// is true, look through getelementptrs with non-zero offsets too. +/// +/// Most analysis passes don't require this logic, because instcombine +/// will simplify most of these kinds of things away. But it's a goal of +/// this Lint pass to be useful even on non-optimized IR. +Value *Lint::findValue(Value *V, bool OffsetOk) const { + SmallPtrSet Visited; + return findValueImpl(V, OffsetOk, Visited); +} + +/// findValueImpl - Implementation helper for findValue. +Value *Lint::findValueImpl(Value *V, bool OffsetOk, + SmallPtrSet &Visited) const { + // Detect self-referential values. + if (!Visited.insert(V)) + return UndefValue::get(V->getType()); + + // TODO: Look through sext or zext cast, when the result is known to + // be interpreted as signed or unsigned, respectively. + // TODO: Look through eliminable cast pairs. + // TODO: Look through calls with unique return values. + // TODO: Look through vector insert/extract/shuffle. + V = OffsetOk ? GetUnderlyingObject(V, TD) : V->stripPointerCasts(); + if (LoadInst *L = dyn_cast(V)) { + BasicBlock::iterator BBI = L; + BasicBlock *BB = L->getParent(); + SmallPtrSet VisitedBlocks; + for (;;) { + if (!VisitedBlocks.insert(BB)) break; + if (Value *U = FindAvailableLoadedValue(L->getPointerOperand(), + BB, BBI, 6, AA)) + return findValueImpl(U, OffsetOk, Visited); + if (BBI != BB->begin()) break; + BB = BB->getUniquePredecessor(); + if (!BB) break; + BBI = BB->end(); + } + } else if (PHINode *PN = dyn_cast(V)) { + if (Value *W = PN->hasConstantValue()) + if (W != V) + return findValueImpl(W, OffsetOk, Visited); + } else if (CastInst *CI = dyn_cast(V)) { + if (CI->isNoopCast(TD ? TD->getIntPtrType(V->getContext()) : + Type::getInt64Ty(V->getContext()))) + return findValueImpl(CI->getOperand(0), OffsetOk, Visited); + } else if (ExtractValueInst *Ex = dyn_cast(V)) { + if (Value *W = FindInsertedValue(Ex->getAggregateOperand(), + Ex->idx_begin(), + Ex->idx_end())) + if (W != V) + return findValueImpl(W, OffsetOk, Visited); + } else if (ConstantExpr *CE = dyn_cast(V)) { + // Same as above, but for ConstantExpr instead of Instruction. + if (Instruction::isCast(CE->getOpcode())) { + if (CastInst::isNoopCast(Instruction::CastOps(CE->getOpcode()), + CE->getOperand(0)->getType(), + CE->getType(), + TD ? TD->getIntPtrType(V->getContext()) : + Type::getInt64Ty(V->getContext()))) + return findValueImpl(CE->getOperand(0), OffsetOk, Visited); + } else if (CE->getOpcode() == Instruction::ExtractValue) { + const SmallVector &Indices = CE->getIndices(); + if (Value *W = FindInsertedValue(CE->getOperand(0), + Indices.begin(), + Indices.end())) + if (W != V) + return findValueImpl(W, OffsetOk, Visited); + } + } + + // As a last resort, try SimplifyInstruction or constant folding. + if (Instruction *Inst = dyn_cast(V)) { + if (Value *W = SimplifyInstruction(Inst, TD, DT)) + return findValueImpl(W, OffsetOk, Visited); + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (Value *W = ConstantFoldConstantExpression(CE, TD)) + if (W != V) + return findValueImpl(W, OffsetOk, Visited); + } + + return V; +} + +//===----------------------------------------------------------------------===// +// Implement the public interfaces to this file... +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createLintPass() { + return new Lint(); +} + +/// lintFunction - Check a function for errors, printing messages on stderr. +/// +void llvm::lintFunction(const Function &f) { + Function &F = const_cast(f); + assert(!F.isDeclaration() && "Cannot lint external functions"); + + FunctionPassManager FPM(F.getParent()); + Lint *V = new Lint(); + FPM.add(V); + FPM.run(F); +} + +/// lintModule - Check a module for errors, printing messages on stderr. +/// +void llvm::lintModule(const Module &M) { + PassManager PM; + Lint *V = new Lint(); + PM.add(V); + PM.run(const_cast(M)); +} diff --git a/final/lib/Analysis/Loads.cpp b/final/lib/Analysis/Loads.cpp new file mode 100644 index 00000000000..2ea27fb62fc --- /dev/null +++ b/final/lib/Analysis/Loads.cpp @@ -0,0 +1,235 @@ +//===- Loads.cpp - Local load analysis ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines simple local analyses for load instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetData.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/IntrinsicInst.h" +using namespace llvm; + +/// AreEquivalentAddressValues - Test if A and B will obviously have the same +/// value. This includes recognizing that %t0 and %t1 will have the same +/// value in code like this: +/// %t0 = getelementptr \@a, 0, 3 +/// store i32 0, i32* %t0 +/// %t1 = getelementptr \@a, 0, 3 +/// %t2 = load i32* %t1 +/// +static bool AreEquivalentAddressValues(const Value *A, const Value *B) { + // Test if the values are trivially equivalent. + if (A == B) return true; + + // Test if the values come from identical arithmetic instructions. + // Use isIdenticalToWhenDefined instead of isIdenticalTo because + // this function is only used when one address use dominates the + // other, which means that they'll always either have the same + // value or one of them will have an undefined value. + if (isa(A) || isa(A) || + isa(A) || isa(A)) + if (const Instruction *BI = dyn_cast(B)) + if (cast(A)->isIdenticalToWhenDefined(BI)) + return true; + + // Otherwise they may not be equivalent. + return false; +} + +/// getUnderlyingObjectWithOffset - Strip off up to MaxLookup GEPs and +/// bitcasts to get back to the underlying object being addressed, keeping +/// track of the offset in bytes from the GEPs relative to the result. +/// This is closely related to GetUnderlyingObject but is located +/// here to avoid making VMCore depend on TargetData. +static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD, + uint64_t &ByteOffset, + unsigned MaxLookup = 6) { + if (!V->getType()->isPointerTy()) + return V; + for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { + if (GEPOperator *GEP = dyn_cast(V)) { + if (!GEP->hasAllConstantIndices()) + return V; + SmallVector Indices(GEP->op_begin() + 1, GEP->op_end()); + ByteOffset += TD->getIndexedOffset(GEP->getPointerOperandType(), + &Indices[0], Indices.size()); + V = GEP->getPointerOperand(); + } else if (Operator::getOpcode(V) == Instruction::BitCast) { + V = cast(V)->getOperand(0); + } else if (GlobalAlias *GA = dyn_cast(V)) { + if (GA->mayBeOverridden()) + return V; + V = GA->getAliasee(); + } else { + return V; + } + assert(V->getType()->isPointerTy() && "Unexpected operand type!"); + } + return V; +} + +/// isSafeToLoadUnconditionally - Return true if we know that executing a load +/// from this value cannot trap. If it is not obviously safe to load from the +/// specified pointer, we do a quick local scan of the basic block containing +/// ScanFrom, to determine if the address is already accessed. +bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, + unsigned Align, const TargetData *TD) { + uint64_t ByteOffset = 0; + Value *Base = V; + if (TD) + Base = getUnderlyingObjectWithOffset(V, TD, ByteOffset); + + const Type *BaseType = 0; + unsigned BaseAlign = 0; + if (const AllocaInst *AI = dyn_cast(Base)) { + // An alloca is safe to load from as load as it is suitably aligned. + BaseType = AI->getAllocatedType(); + BaseAlign = AI->getAlignment(); + } else if (const GlobalValue *GV = dyn_cast(Base)) { + // Global variables are safe to load from but their size cannot be + // guaranteed if they are overridden. + if (!isa(GV) && !GV->mayBeOverridden()) { + BaseType = GV->getType()->getElementType(); + BaseAlign = GV->getAlignment(); + } + } + + if (BaseType && BaseType->isSized()) { + if (TD && BaseAlign == 0) + BaseAlign = TD->getPrefTypeAlignment(BaseType); + + if (Align <= BaseAlign) { + if (!TD) + return true; // Loading directly from an alloca or global is OK. + + // Check if the load is within the bounds of the underlying object. + const PointerType *AddrTy = cast(V->getType()); + uint64_t LoadSize = TD->getTypeStoreSize(AddrTy->getElementType()); + if (ByteOffset + LoadSize <= TD->getTypeAllocSize(BaseType) && + (Align == 0 || (ByteOffset % Align) == 0)) + return true; + } + } + + // Otherwise, be a little bit aggressive by scanning the local block where we + // want to check to see if the pointer is already being loaded or stored + // from/to. If so, the previous load or store would have already trapped, + // so there is no harm doing an extra load (also, CSE will later eliminate + // the load entirely). + BasicBlock::iterator BBI = ScanFrom, E = ScanFrom->getParent()->begin(); + + while (BBI != E) { + --BBI; + + // If we see a free or a call which may write to memory (i.e. which might do + // a free) the pointer could be marked invalid. + if (isa(BBI) && BBI->mayWriteToMemory() && + !isa(BBI)) + return false; + + if (LoadInst *LI = dyn_cast(BBI)) { + if (AreEquivalentAddressValues(LI->getOperand(0), V)) return true; + } else if (StoreInst *SI = dyn_cast(BBI)) { + if (AreEquivalentAddressValues(SI->getOperand(1), V)) return true; + } + } + return false; +} + +/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at the +/// instruction before ScanFrom) checking to see if we have the value at the +/// memory address *Ptr locally available within a small number of instructions. +/// If the value is available, return it. +/// +/// If not, return the iterator for the last validated instruction that the +/// value would be live through. If we scanned the entire block and didn't find +/// something that invalidates *Ptr or provides it, ScanFrom would be left at +/// begin() and this returns null. ScanFrom could also be left +/// +/// MaxInstsToScan specifies the maximum instructions to scan in the block. If +/// it is set to 0, it will scan the whole block. You can also optionally +/// specify an alias analysis implementation, which makes this more precise. +Value *llvm::FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, + BasicBlock::iterator &ScanFrom, + unsigned MaxInstsToScan, + AliasAnalysis *AA) { + if (MaxInstsToScan == 0) MaxInstsToScan = ~0U; + + // If we're using alias analysis to disambiguate get the size of *Ptr. + uint64_t AccessSize = 0; + if (AA) { + const Type *AccessTy = cast(Ptr->getType())->getElementType(); + AccessSize = AA->getTypeStoreSize(AccessTy); + } + + while (ScanFrom != ScanBB->begin()) { + // We must ignore debug info directives when counting (otherwise they + // would affect codegen). + Instruction *Inst = --ScanFrom; + if (isa(Inst)) + continue; + + // Restore ScanFrom to expected value in case next test succeeds + ScanFrom++; + + // Don't scan huge blocks. + if (MaxInstsToScan-- == 0) return 0; + + --ScanFrom; + // If this is a load of Ptr, the loaded value is available. + if (LoadInst *LI = dyn_cast(Inst)) + if (AreEquivalentAddressValues(LI->getOperand(0), Ptr)) + return LI; + + if (StoreInst *SI = dyn_cast(Inst)) { + // If this is a store through Ptr, the value is available! + if (AreEquivalentAddressValues(SI->getOperand(1), Ptr)) + return SI->getOperand(0); + + // If Ptr is an alloca and this is a store to a different alloca, ignore + // the store. This is a trivial form of alias analysis that is important + // for reg2mem'd code. + if ((isa(Ptr) || isa(Ptr)) && + (isa(SI->getOperand(1)) || + isa(SI->getOperand(1)))) + continue; + + // If we have alias analysis and it says the store won't modify the loaded + // value, ignore the store. + if (AA && + (AA->getModRefInfo(SI, Ptr, AccessSize) & AliasAnalysis::Mod) == 0) + continue; + + // Otherwise the store that may or may not alias the pointer, bail out. + ++ScanFrom; + return 0; + } + + // If this is some other instruction that may clobber Ptr, bail out. + if (Inst->mayWriteToMemory()) { + // If alias analysis claims that it really won't modify the load, + // ignore it. + if (AA && + (AA->getModRefInfo(Inst, Ptr, AccessSize) & AliasAnalysis::Mod) == 0) + continue; + + // May modify the pointer, bail out. + ++ScanFrom; + return 0; + } + } + + // Got to the start of the block, we didn't find it, but are done for this + // block. + return 0; +} diff --git a/final/lib/Analysis/LoopDependenceAnalysis.cpp b/final/lib/Analysis/LoopDependenceAnalysis.cpp new file mode 100644 index 00000000000..c1afe8fbd61 --- /dev/null +++ b/final/lib/Analysis/LoopDependenceAnalysis.cpp @@ -0,0 +1,358 @@ +//===- LoopDependenceAnalysis.cpp - LDA Implementation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the (beginning) of an implementation of a loop dependence analysis +// framework, which is used to detect dependences in memory accesses in loops. +// +// Please note that this is work in progress and the interface is subject to +// change. +// +// TODO: adapt as implementation progresses. +// +// TODO: document lingo (pair, subscript, index) +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lda" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/LoopDependenceAnalysis.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Instructions.h" +#include "llvm/Operator.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +STATISTIC(NumAnswered, "Number of dependence queries answered"); +STATISTIC(NumAnalysed, "Number of distinct dependence pairs analysed"); +STATISTIC(NumDependent, "Number of pairs with dependent accesses"); +STATISTIC(NumIndependent, "Number of pairs with independent accesses"); +STATISTIC(NumUnknown, "Number of pairs with unknown accesses"); + +LoopPass *llvm::createLoopDependenceAnalysisPass() { + return new LoopDependenceAnalysis(); +} + +INITIALIZE_PASS_BEGIN(LoopDependenceAnalysis, "lda", + "Loop Dependence Analysis", false, true) +INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(LoopDependenceAnalysis, "lda", + "Loop Dependence Analysis", false, true) +char LoopDependenceAnalysis::ID = 0; + +//===----------------------------------------------------------------------===// +// Utility Functions +//===----------------------------------------------------------------------===// + +static inline bool IsMemRefInstr(const Value *V) { + const Instruction *I = dyn_cast(V); + return I && (I->mayReadFromMemory() || I->mayWriteToMemory()); +} + +static void GetMemRefInstrs(const Loop *L, + SmallVectorImpl &Memrefs) { + for (Loop::block_iterator b = L->block_begin(), be = L->block_end(); + b != be; ++b) + for (BasicBlock::iterator i = (*b)->begin(), ie = (*b)->end(); + i != ie; ++i) + if (IsMemRefInstr(i)) + Memrefs.push_back(i); +} + +static bool IsLoadOrStoreInst(Value *I) { + return isa(I) || isa(I); +} + +static Value *GetPointerOperand(Value *I) { + if (LoadInst *i = dyn_cast(I)) + return i->getPointerOperand(); + if (StoreInst *i = dyn_cast(I)) + return i->getPointerOperand(); + llvm_unreachable("Value is no load or store instruction!"); + // Never reached. + return 0; +} + +static AliasAnalysis::AliasResult UnderlyingObjectsAlias(AliasAnalysis *AA, + const Value *A, + const Value *B) { + const Value *aObj = GetUnderlyingObject(A); + const Value *bObj = GetUnderlyingObject(B); + return AA->alias(aObj, AA->getTypeStoreSize(aObj->getType()), + bObj, AA->getTypeStoreSize(bObj->getType())); +} + +static inline const SCEV *GetZeroSCEV(ScalarEvolution *SE) { + return SE->getConstant(Type::getInt32Ty(SE->getContext()), 0L); +} + +//===----------------------------------------------------------------------===// +// Dependence Testing +//===----------------------------------------------------------------------===// + +bool LoopDependenceAnalysis::isDependencePair(const Value *A, + const Value *B) const { + return IsMemRefInstr(A) && + IsMemRefInstr(B) && + (cast(A)->mayWriteToMemory() || + cast(B)->mayWriteToMemory()); +} + +bool LoopDependenceAnalysis::findOrInsertDependencePair(Value *A, + Value *B, + DependencePair *&P) { + void *insertPos = 0; + FoldingSetNodeID id; + id.AddPointer(A); + id.AddPointer(B); + + P = Pairs.FindNodeOrInsertPos(id, insertPos); + if (P) return true; + + P = new (PairAllocator) DependencePair(id, A, B); + Pairs.InsertNode(P, insertPos); + return false; +} + +void LoopDependenceAnalysis::getLoops(const SCEV *S, + DenseSet* Loops) const { + // Refactor this into an SCEVVisitor, if efficiency becomes a concern. + for (const Loop *L = this->L; L != 0; L = L->getParentLoop()) + if (!SE->isLoopInvariant(S, L)) + Loops->insert(L); +} + +bool LoopDependenceAnalysis::isLoopInvariant(const SCEV *S) const { + DenseSet loops; + getLoops(S, &loops); + return loops.empty(); +} + +bool LoopDependenceAnalysis::isAffine(const SCEV *S) const { + const SCEVAddRecExpr *rec = dyn_cast(S); + return isLoopInvariant(S) || (rec && rec->isAffine()); +} + +bool LoopDependenceAnalysis::isZIVPair(const SCEV *A, const SCEV *B) const { + return isLoopInvariant(A) && isLoopInvariant(B); +} + +bool LoopDependenceAnalysis::isSIVPair(const SCEV *A, const SCEV *B) const { + DenseSet loops; + getLoops(A, &loops); + getLoops(B, &loops); + return loops.size() == 1; +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseZIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + assert(isZIVPair(A, B) && "Attempted to ZIV-test non-ZIV SCEVs!"); + return A == B ? Dependent : Independent; +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseSIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + return Unknown; // TODO: Implement. +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseMIV(const SCEV *A, + const SCEV *B, + Subscript *S) const { + return Unknown; // TODO: Implement. +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analyseSubscript(const SCEV *A, + const SCEV *B, + Subscript *S) const { + DEBUG(dbgs() << " Testing subscript: " << *A << ", " << *B << "\n"); + + if (A == B) { + DEBUG(dbgs() << " -> [D] same SCEV\n"); + return Dependent; + } + + if (!isAffine(A) || !isAffine(B)) { + DEBUG(dbgs() << " -> [?] not affine\n"); + return Unknown; + } + + if (isZIVPair(A, B)) + return analyseZIV(A, B, S); + + if (isSIVPair(A, B)) + return analyseSIV(A, B, S); + + return analyseMIV(A, B, S); +} + +LoopDependenceAnalysis::DependenceResult +LoopDependenceAnalysis::analysePair(DependencePair *P) const { + DEBUG(dbgs() << "Analysing:\n" << *P->A << "\n" << *P->B << "\n"); + + // We only analyse loads and stores but no possible memory accesses by e.g. + // free, call, or invoke instructions. + if (!IsLoadOrStoreInst(P->A) || !IsLoadOrStoreInst(P->B)) { + DEBUG(dbgs() << "--> [?] no load/store\n"); + return Unknown; + } + + Value *aPtr = GetPointerOperand(P->A); + Value *bPtr = GetPointerOperand(P->B); + + switch (UnderlyingObjectsAlias(AA, aPtr, bPtr)) { + case AliasAnalysis::MayAlias: + case AliasAnalysis::PartialAlias: + // We can not analyse objects if we do not know about their aliasing. + DEBUG(dbgs() << "---> [?] may alias\n"); + return Unknown; + + case AliasAnalysis::NoAlias: + // If the objects noalias, they are distinct, accesses are independent. + DEBUG(dbgs() << "---> [I] no alias\n"); + return Independent; + + case AliasAnalysis::MustAlias: + break; // The underlying objects alias, test accesses for dependence. + } + + const GEPOperator *aGEP = dyn_cast(aPtr); + const GEPOperator *bGEP = dyn_cast(bPtr); + + if (!aGEP || !bGEP) + return Unknown; + + // FIXME: Is filtering coupled subscripts necessary? + + // Collect GEP operand pairs (FIXME: use GetGEPOperands from BasicAA), adding + // trailing zeroes to the smaller GEP, if needed. + typedef SmallVector, 4> GEPOpdPairsTy; + GEPOpdPairsTy opds; + for(GEPOperator::const_op_iterator aIdx = aGEP->idx_begin(), + aEnd = aGEP->idx_end(), + bIdx = bGEP->idx_begin(), + bEnd = bGEP->idx_end(); + aIdx != aEnd && bIdx != bEnd; + aIdx += (aIdx != aEnd), bIdx += (bIdx != bEnd)) { + const SCEV* aSCEV = (aIdx != aEnd) ? SE->getSCEV(*aIdx) : GetZeroSCEV(SE); + const SCEV* bSCEV = (bIdx != bEnd) ? SE->getSCEV(*bIdx) : GetZeroSCEV(SE); + opds.push_back(std::make_pair(aSCEV, bSCEV)); + } + + if (!opds.empty() && opds[0].first != opds[0].second) { + // We cannot (yet) handle arbitrary GEP pointer offsets. By limiting + // + // TODO: this could be relaxed by adding the size of the underlying object + // to the first subscript. If we have e.g. (GEP x,0,i; GEP x,2,-i) and we + // know that x is a [100 x i8]*, we could modify the first subscript to be + // (i, 200-i) instead of (i, -i). + return Unknown; + } + + // Now analyse the collected operand pairs (skipping the GEP ptr offsets). + for (GEPOpdPairsTy::const_iterator i = opds.begin() + 1, end = opds.end(); + i != end; ++i) { + Subscript subscript; + DependenceResult result = analyseSubscript(i->first, i->second, &subscript); + if (result != Dependent) { + // We either proved independence or failed to analyse this subscript. + // Further subscripts will not improve the situation, so abort early. + return result; + } + P->Subscripts.push_back(subscript); + } + // We successfully analysed all subscripts but failed to prove independence. + return Dependent; +} + +bool LoopDependenceAnalysis::depends(Value *A, Value *B) { + assert(isDependencePair(A, B) && "Values form no dependence pair!"); + ++NumAnswered; + + DependencePair *p; + if (!findOrInsertDependencePair(A, B, p)) { + // The pair is not cached, so analyse it. + ++NumAnalysed; + switch (p->Result = analysePair(p)) { + case Dependent: ++NumDependent; break; + case Independent: ++NumIndependent; break; + case Unknown: ++NumUnknown; break; + } + } + return p->Result != Independent; +} + +//===----------------------------------------------------------------------===// +// LoopDependenceAnalysis Implementation +//===----------------------------------------------------------------------===// + +bool LoopDependenceAnalysis::runOnLoop(Loop *L, LPPassManager &) { + this->L = L; + AA = &getAnalysis(); + SE = &getAnalysis(); + return false; +} + +void LoopDependenceAnalysis::releaseMemory() { + Pairs.clear(); + PairAllocator.Reset(); +} + +void LoopDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); +} + +static void PrintLoopInfo(raw_ostream &OS, + LoopDependenceAnalysis *LDA, const Loop *L) { + if (!L->empty()) return; // ignore non-innermost loops + + SmallVector memrefs; + GetMemRefInstrs(L, memrefs); + + OS << "Loop at depth " << L->getLoopDepth() << ", header block: "; + WriteAsOperand(OS, L->getHeader(), false); + OS << "\n"; + + OS << " Load/store instructions: " << memrefs.size() << "\n"; + for (SmallVector::const_iterator x = memrefs.begin(), + end = memrefs.end(); x != end; ++x) + OS << "\t" << (x - memrefs.begin()) << ": " << **x << "\n"; + + OS << " Pairwise dependence results:\n"; + for (SmallVector::const_iterator x = memrefs.begin(), + end = memrefs.end(); x != end; ++x) + for (SmallVector::const_iterator y = x + 1; + y != end; ++y) + if (LDA->isDependencePair(*x, *y)) + OS << "\t" << (x - memrefs.begin()) << "," << (y - memrefs.begin()) + << ": " << (LDA->depends(*x, *y) ? "dependent" : "independent") + << "\n"; +} + +void LoopDependenceAnalysis::print(raw_ostream &OS, const Module*) const { + // TODO: doc why const_cast is safe + PrintLoopInfo(OS, const_cast(this), this->L); +} diff --git a/final/lib/Analysis/LoopInfo.cpp b/final/lib/Analysis/LoopInfo.cpp new file mode 100644 index 00000000000..05831402f40 --- /dev/null +++ b/final/lib/Analysis/LoopInfo.cpp @@ -0,0 +1,419 @@ +//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===// +// +// 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 LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. Note that the +// loops identified may actually be several natural loops that share the same +// header node... not just a single natural loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +// Always verify loopinfo if expensive checking is enabled. +#ifdef XDEBUG +static bool VerifyLoopInfo = true; +#else +static bool VerifyLoopInfo = false; +#endif +static cl::opt +VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo), + cl::desc("Verify loop info (time consuming)")); + +char LoopInfo::ID = 0; +INITIALIZE_PASS_BEGIN(LoopInfo, "loops", "Natural Loop Information", true, true) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_END(LoopInfo, "loops", "Natural Loop Information", true, true) + +//===----------------------------------------------------------------------===// +// Loop implementation +// + +/// isLoopInvariant - Return true if the specified value is loop invariant +/// +bool Loop::isLoopInvariant(Value *V) const { + if (Instruction *I = dyn_cast(V)) + return !contains(I); + return true; // All non-instructions are loop invariant +} + +/// hasLoopInvariantOperands - Return true if all the operands of the +/// specified instruction are loop invariant. +bool Loop::hasLoopInvariantOperands(Instruction *I) const { + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (!isLoopInvariant(I->getOperand(i))) + return false; + + return true; +} + +/// makeLoopInvariant - If the given value is an instruciton inside of the +/// loop and it can be hoisted, do so to make it trivially loop-invariant. +/// Return true if the value after any hoisting is loop invariant. This +/// function can be used as a slightly more aggressive replacement for +/// isLoopInvariant. +/// +/// If InsertPt is specified, it is the point to hoist instructions to. +/// If null, the terminator of the loop preheader is used. +/// +bool Loop::makeLoopInvariant(Value *V, bool &Changed, + Instruction *InsertPt) const { + if (Instruction *I = dyn_cast(V)) + return makeLoopInvariant(I, Changed, InsertPt); + return true; // All non-instructions are loop-invariant. +} + +/// makeLoopInvariant - If the given instruction is inside of the +/// loop and it can be hoisted, do so to make it trivially loop-invariant. +/// Return true if the instruction after any hoisting is loop invariant. This +/// function can be used as a slightly more aggressive replacement for +/// isLoopInvariant. +/// +/// If InsertPt is specified, it is the point to hoist instructions to. +/// If null, the terminator of the loop preheader is used. +/// +bool Loop::makeLoopInvariant(Instruction *I, bool &Changed, + Instruction *InsertPt) const { + // Test if the value is already loop-invariant. + if (isLoopInvariant(I)) + return true; + if (!I->isSafeToSpeculativelyExecute()) + return false; + if (I->mayReadFromMemory()) + return false; + // Determine the insertion point, unless one was given. + if (!InsertPt) { + BasicBlock *Preheader = getLoopPreheader(); + // Without a preheader, hoisting is not feasible. + if (!Preheader) + return false; + InsertPt = Preheader->getTerminator(); + } + // Don't hoist instructions with loop-variant operands. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt)) + return false; + + // Hoist. + I->moveBefore(InsertPt); + Changed = true; + return true; +} + +/// getCanonicalInductionVariable - Check to see if the loop has a canonical +/// induction variable: an integer recurrence that starts at 0 and increments +/// by one each time through the loop. If so, return the phi node that +/// corresponds to it. +/// +/// The IndVarSimplify pass transforms loops to have a canonical induction +/// variable. +/// +PHINode *Loop::getCanonicalInductionVariable() const { + BasicBlock *H = getHeader(); + + BasicBlock *Incoming = 0, *Backedge = 0; + pred_iterator PI = pred_begin(H); + assert(PI != pred_end(H) && + "Loop must have at least one backedge!"); + Backedge = *PI++; + if (PI == pred_end(H)) return 0; // dead loop + Incoming = *PI++; + if (PI != pred_end(H)) return 0; // multiple backedges? + + if (contains(Incoming)) { + if (contains(Backedge)) + return 0; + std::swap(Incoming, Backedge); + } else if (!contains(Backedge)) + return 0; + + // Loop over all of the PHI nodes, looking for a canonical indvar. + for (BasicBlock::iterator I = H->begin(); isa(I); ++I) { + PHINode *PN = cast(I); + if (ConstantInt *CI = + dyn_cast(PN->getIncomingValueForBlock(Incoming))) + if (CI->isNullValue()) + if (Instruction *Inc = + dyn_cast(PN->getIncomingValueForBlock(Backedge))) + if (Inc->getOpcode() == Instruction::Add && + Inc->getOperand(0) == PN) + if (ConstantInt *CI = dyn_cast(Inc->getOperand(1))) + if (CI->equalsInt(1)) + return PN; + } + return 0; +} + +/// getTripCount - Return a loop-invariant LLVM value indicating the number of +/// times the loop will be executed. Note that this means that the backedge +/// of the loop executes N-1 times. If the trip-count cannot be determined, +/// this returns null. +/// +/// The IndVarSimplify pass transforms loops to have a form that this +/// function easily understands. +/// +Value *Loop::getTripCount() const { + // Canonical loops will end with a 'cmp ne I, V', where I is the incremented + // canonical induction variable and V is the trip count of the loop. + PHINode *IV = getCanonicalInductionVariable(); + if (IV == 0 || IV->getNumIncomingValues() != 2) return 0; + + bool P0InLoop = contains(IV->getIncomingBlock(0)); + Value *Inc = IV->getIncomingValue(!P0InLoop); + BasicBlock *BackedgeBlock = IV->getIncomingBlock(!P0InLoop); + + if (BranchInst *BI = dyn_cast(BackedgeBlock->getTerminator())) + if (BI->isConditional()) { + if (ICmpInst *ICI = dyn_cast(BI->getCondition())) { + if (ICI->getOperand(0) == Inc) { + if (BI->getSuccessor(0) == getHeader()) { + if (ICI->getPredicate() == ICmpInst::ICMP_NE) + return ICI->getOperand(1); + } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) { + return ICI->getOperand(1); + } + } + } + } + + return 0; +} + +/// getSmallConstantTripCount - Returns the trip count of this loop as a +/// normal unsigned value, if possible. Returns 0 if the trip count is unknown +/// or not constant. Will also return 0 if the trip count is very large +/// (>= 2^32) +unsigned Loop::getSmallConstantTripCount() const { + Value* TripCount = this->getTripCount(); + if (TripCount) { + if (ConstantInt *TripCountC = dyn_cast(TripCount)) { + // Guard against huge trip counts. + if (TripCountC->getValue().getActiveBits() <= 32) { + return (unsigned)TripCountC->getZExtValue(); + } + } + } + return 0; +} + +/// getSmallConstantTripMultiple - Returns the largest constant divisor of the +/// trip count of this loop as a normal unsigned value, if possible. This +/// means that the actual trip count is always a multiple of the returned +/// value (don't forget the trip count could very well be zero as well!). +/// +/// Returns 1 if the trip count is unknown or not guaranteed to be the +/// multiple of a constant (which is also the case if the trip count is simply +/// constant, use getSmallConstantTripCount for that case), Will also return 1 +/// if the trip count is very large (>= 2^32). +unsigned Loop::getSmallConstantTripMultiple() const { + Value* TripCount = this->getTripCount(); + // This will hold the ConstantInt result, if any + ConstantInt *Result = NULL; + if (TripCount) { + // See if the trip count is constant itself + Result = dyn_cast(TripCount); + // if not, see if it is a multiplication + if (!Result) + if (BinaryOperator *BO = dyn_cast(TripCount)) { + switch (BO->getOpcode()) { + case BinaryOperator::Mul: + Result = dyn_cast(BO->getOperand(1)); + break; + case BinaryOperator::Shl: + if (ConstantInt *CI = dyn_cast(BO->getOperand(1))) + if (CI->getValue().getActiveBits() <= 5) + return 1u << CI->getZExtValue(); + break; + default: + break; + } + } + } + // Guard against huge trip counts. + if (Result && Result->getValue().getActiveBits() <= 32) { + return (unsigned)Result->getZExtValue(); + } else { + return 1; + } +} + +/// isLCSSAForm - Return true if the Loop is in LCSSA form +bool Loop::isLCSSAForm(DominatorTree &DT) const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallPtrSet LoopBBs(block_begin(), block_end()); + + for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) { + BasicBlock *BB = *BI; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;++I) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + User *U = *UI; + BasicBlock *UserBB = cast(U)->getParent(); + if (PHINode *P = dyn_cast(U)) + UserBB = P->getIncomingBlock(UI); + + // Check the current block, as a fast-path, before checking whether + // the use is anywhere in the loop. Most values are used in the same + // block they are defined in. Also, blocks not reachable from the + // entry are special; uses in them don't need to go through PHIs. + if (UserBB != BB && + !LoopBBs.count(UserBB) && + DT.isReachableFromEntry(UserBB)) + return false; + } + } + + return true; +} + +/// isLoopSimplifyForm - Return true if the Loop is in the form that +/// the LoopSimplify form transforms loops to, which is sometimes called +/// normal form. +bool Loop::isLoopSimplifyForm() const { + // Normal-form loops have a preheader, a single backedge, and all of their + // exits have all their predecessors inside the loop. + return getLoopPreheader() && getLoopLatch() && hasDedicatedExits(); +} + +/// hasDedicatedExits - Return true if no exit block for the loop +/// has a predecessor that is outside the loop. +bool Loop::hasDedicatedExits() const { + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallPtrSet LoopBBs(block_begin(), block_end()); + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector ExitBlocks; + getExitBlocks(ExitBlocks); + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + for (pred_iterator PI = pred_begin(ExitBlocks[i]), + PE = pred_end(ExitBlocks[i]); PI != PE; ++PI) + if (!LoopBBs.count(*PI)) + return false; + // All the requirements are met. + return true; +} + +/// getUniqueExitBlocks - Return all unique successor blocks of this loop. +/// These are the blocks _outside of the current loop_ which are branched to. +/// This assumes that loop exits are in canonical form. +/// +void +Loop::getUniqueExitBlocks(SmallVectorImpl &ExitBlocks) const { + assert(hasDedicatedExits() && + "getUniqueExitBlocks assumes the loop has canonical form exits!"); + + // Sort the blocks vector so that we can use binary search to do quick + // lookups. + SmallVector LoopBBs(block_begin(), block_end()); + std::sort(LoopBBs.begin(), LoopBBs.end()); + + SmallVector switchExitBlocks; + + for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) { + + BasicBlock *current = *BI; + switchExitBlocks.clear(); + + for (succ_iterator I = succ_begin(*BI), E = succ_end(*BI); I != E; ++I) { + // If block is inside the loop then it is not a exit block. + if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) + continue; + + pred_iterator PI = pred_begin(*I); + BasicBlock *firstPred = *PI; + + // If current basic block is this exit block's first predecessor + // then only insert exit block in to the output ExitBlocks vector. + // This ensures that same exit block is not inserted twice into + // ExitBlocks vector. + if (current != firstPred) + continue; + + // If a terminator has more then two successors, for example SwitchInst, + // then it is possible that there are multiple edges from current block + // to one exit block. + if (std::distance(succ_begin(current), succ_end(current)) <= 2) { + ExitBlocks.push_back(*I); + continue; + } + + // In case of multiple edges from current block to exit block, collect + // only one edge in ExitBlocks. Use switchExitBlocks to keep track of + // duplicate edges. + if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I) + == switchExitBlocks.end()) { + switchExitBlocks.push_back(*I); + ExitBlocks.push_back(*I); + } + } + } +} + +/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one +/// block, return that block. Otherwise return null. +BasicBlock *Loop::getUniqueExitBlock() const { + SmallVector UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return 0; +} + +void Loop::dump() const { + print(dbgs()); +} + +//===----------------------------------------------------------------------===// +// LoopInfo implementation +// +bool LoopInfo::runOnFunction(Function &) { + releaseMemory(); + LI.Calculate(getAnalysis().getBase()); // Update + return false; +} + +void LoopInfo::verifyAnalysis() const { + // LoopInfo is a FunctionPass, but verifying every loop in the function + // each time verifyAnalysis is called is very expensive. The + // -verify-loop-info option can enable this. In order to perform some + // checking by default, LoopPass has been taught to call verifyLoop + // manually during loop pass sequences. + + if (!VerifyLoopInfo) return; + + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(); + } + + // TODO: check BBMap consistency. +} + +void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + +void LoopInfo::print(raw_ostream &OS, const Module*) const { + LI.print(OS); +} + diff --git a/final/lib/Analysis/LoopPass.cpp b/final/lib/Analysis/LoopPass.cpp new file mode 100644 index 00000000000..8e1a7bfef69 --- /dev/null +++ b/final/lib/Analysis/LoopPass.cpp @@ -0,0 +1,403 @@ +//===- LoopPass.cpp - Loop Pass and Loop Pass Manager ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LoopPass and LPPassManager. All loop optimization +// and transformation passes are derived from LoopPass. LPPassManager is +// responsible for managing LoopPasses. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Timer.h" +using namespace llvm; + +namespace { + +/// PrintLoopPass - Print a Function corresponding to a Loop. +/// +class PrintLoopPass : public LoopPass { +private: + std::string Banner; + raw_ostream &Out; // raw_ostream to print on. + +public: + static char ID; + PrintLoopPass(const std::string &B, raw_ostream &o) + : LoopPass(ID), Banner(B), Out(o) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + bool runOnLoop(Loop *L, LPPassManager &) { + Out << Banner; + for (Loop::block_iterator b = L->block_begin(), be = L->block_end(); + b != be; + ++b) { + (*b)->print(Out); + } + return false; + } +}; + +char PrintLoopPass::ID = 0; +} + +//===----------------------------------------------------------------------===// +// LPPassManager +// + +char LPPassManager::ID = 0; + +LPPassManager::LPPassManager(int Depth) + : FunctionPass(ID), PMDataManager(Depth) { + skipThisLoop = false; + redoThisLoop = false; + LI = NULL; + CurrentLoop = NULL; +} + +/// Delete loop from the loop queue and loop hierarchy (LoopInfo). +void LPPassManager::deleteLoopFromQueue(Loop *L) { + + if (Loop *ParentLoop = L->getParentLoop()) { // Not a top-level loop. + // Reparent all of the blocks in this loop. Since BBLoop had a parent, + // they are now all in it. + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + if (LI->getLoopFor(*I) == L) // Don't change blocks in subloops. + LI->changeLoopFor(*I, ParentLoop); + + // Remove the loop from its parent loop. + for (Loop::iterator I = ParentLoop->begin(), E = ParentLoop->end();; + ++I) { + assert(I != E && "Couldn't find loop"); + if (*I == L) { + ParentLoop->removeChildLoop(I); + break; + } + } + + // Move all subloops into the parent loop. + while (!L->empty()) + ParentLoop->addChildLoop(L->removeChildLoop(L->end()-1)); + } else { + // Reparent all of the blocks in this loop. Since BBLoop had no parent, + // they no longer in a loop at all. + + for (unsigned i = 0; i != L->getBlocks().size(); ++i) { + // Don't change blocks in subloops. + if (LI->getLoopFor(L->getBlocks()[i]) == L) { + LI->removeBlock(L->getBlocks()[i]); + --i; + } + } + + // Remove the loop from the top-level LoopInfo object. + for (LoopInfo::iterator I = LI->begin(), E = LI->end();; ++I) { + assert(I != E && "Couldn't find loop"); + if (*I == L) { + LI->removeLoop(I); + break; + } + } + + // Move all of the subloops to the top-level. + while (!L->empty()) + LI->addTopLevelLoop(L->removeChildLoop(L->end()-1)); + } + + delete L; + + // If L is current loop then skip rest of the passes and let + // runOnFunction remove L from LQ. Otherwise, remove L from LQ now + // and continue applying other passes on CurrentLoop. + if (CurrentLoop == L) { + skipThisLoop = true; + return; + } + + for (std::deque::iterator I = LQ.begin(), + E = LQ.end(); I != E; ++I) { + if (*I == L) { + LQ.erase(I); + break; + } + } +} + +// Inset loop into loop nest (LoopInfo) and loop queue (LQ). +void LPPassManager::insertLoop(Loop *L, Loop *ParentLoop) { + + assert (CurrentLoop != L && "Cannot insert CurrentLoop"); + + // Insert into loop nest + if (ParentLoop) + ParentLoop->addChildLoop(L); + else + LI->addTopLevelLoop(L); + + insertLoopIntoQueue(L); +} + +void LPPassManager::insertLoopIntoQueue(Loop *L) { + // Insert L into loop queue + if (L == CurrentLoop) + redoLoop(L); + else if (!L->getParentLoop()) + // This is top level loop. + LQ.push_front(L); + else { + // Insert L after the parent loop. + for (std::deque::iterator I = LQ.begin(), + E = LQ.end(); I != E; ++I) { + if (*I == L->getParentLoop()) { + // deque does not support insert after. + ++I; + LQ.insert(I, 1, L); + break; + } + } + } +} + +// Reoptimize this loop. LPPassManager will re-insert this loop into the +// queue. This allows LoopPass to change loop nest for the loop. This +// utility may send LPPassManager into infinite loops so use caution. +void LPPassManager::redoLoop(Loop *L) { + assert (CurrentLoop == L && "Can redo only CurrentLoop"); + redoThisLoop = true; +} + +/// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for +/// all loop passes. +void LPPassManager::cloneBasicBlockSimpleAnalysis(BasicBlock *From, + BasicBlock *To, Loop *L) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + LoopPass *LP = getContainedPass(Index); + LP->cloneBasicBlockAnalysis(From, To, L); + } +} + +/// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes. +void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) { + if (BasicBlock *BB = dyn_cast(V)) { + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; + ++BI) { + Instruction &I = *BI; + deleteSimpleAnalysisValue(&I, L); + } + } + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + LoopPass *LP = getContainedPass(Index); + LP->deleteAnalysisValue(V, L); + } +} + + +// Recurse through all subloops and all loops into LQ. +static void addLoopIntoQueue(Loop *L, std::deque &LQ) { + LQ.push_back(L); + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + addLoopIntoQueue(*I, LQ); +} + +/// Pass Manager itself does not invalidate any analysis info. +void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const { + // LPPassManager needs LoopInfo. In the long term LoopInfo class will + // become part of LPPassManager. + Info.addRequired(); + Info.setPreservesAll(); +} + +/// run - Execute all of the passes scheduled for execution. Keep track of +/// whether any of the passes modifies the function, and if so, return true. +bool LPPassManager::runOnFunction(Function &F) { + LI = &getAnalysis(); + bool Changed = false; + + // Collect inherited analysis from Module level pass manager. + populateInheritedAnalysis(TPM->activeStack); + + // Populate Loop Queue + for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) + addLoopIntoQueue(*I, LQ); + + if (LQ.empty()) // No loops, skip calling finalizers + return false; + + // Initialization + for (std::deque::const_iterator I = LQ.begin(), E = LQ.end(); + I != E; ++I) { + Loop *L = *I; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + LoopPass *P = getContainedPass(Index); + Changed |= P->doInitialization(L, *this); + } + } + + // Walk Loops + while (!LQ.empty()) { + + CurrentLoop = LQ.back(); + skipThisLoop = false; + redoThisLoop = false; + + // Run all passes on the current Loop. + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + LoopPass *P = getContainedPass(Index); + + dumpPassInfo(P, EXECUTION_MSG, ON_LOOP_MSG, + CurrentLoop->getHeader()->getName()); + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + { + PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader()); + TimeRegion PassTimer(getPassTimer(P)); + + Changed |= P->runOnLoop(CurrentLoop, *this); + } + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_LOOP_MSG, + skipThisLoop ? "" : + CurrentLoop->getHeader()->getName()); + dumpPreservedSet(P); + + if (!skipThisLoop) { + // Manually check that this loop is still healthy. This is done + // instead of relying on LoopInfo::verifyLoop since LoopInfo + // is a function pass and it's really expensive to verify every + // loop in the function every time. That level of checking can be + // enabled with the -verify-loop-info option. + { + TimeRegion PassTimer(getPassTimer(LI)); + CurrentLoop->verifyLoop(); + } + + // Then call the regular verifyAnalysis functions. + verifyPreservedAnalysis(P); + } + + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, + skipThisLoop ? "" : + CurrentLoop->getHeader()->getName(), + ON_LOOP_MSG); + + if (skipThisLoop) + // Do not run other passes on this loop. + break; + } + + // If the loop was deleted, release all the loop passes. This frees up + // some memory, and avoids trouble with the pass manager trying to call + // verifyAnalysis on them. + if (skipThisLoop) + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + freePass(P, "", ON_LOOP_MSG); + } + + // Pop the loop from queue after running all passes. + LQ.pop_back(); + + if (redoThisLoop) + LQ.push_back(CurrentLoop); + } + + // Finalization + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + LoopPass *P = getContainedPass(Index); + Changed |= P->doFinalization(); + } + + return Changed; +} + +/// Print passes managed by this manager +void LPPassManager::dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Loop Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } +} + + +//===----------------------------------------------------------------------===// +// LoopPass + +Pass *LoopPass::createPrinterPass(raw_ostream &O, + const std::string &Banner) const { + return new PrintLoopPass(Banner, O); +} + +// Check if this pass is suitable for the current LPPassManager, if +// available. This pass P is not suitable for a LPPassManager if P +// is not preserving higher level analysis info used by other +// LPPassManager passes. In such case, pop LPPassManager from the +// stack. This will force assignPassManager() to create new +// LPPassManger as expected. +void LoopPass::preparePassManager(PMStack &PMS) { + + // Find LPPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_LoopPassManager) + PMS.pop(); + + // If this pass is destroying high level information that is used + // by other passes that are managed by LPM then do not insert + // this pass in current LPM. Use new LPPassManager. + if (PMS.top()->getPassManagerType() == PMT_LoopPassManager && + !PMS.top()->preserveHigherLevelAnalysis(this)) + PMS.pop(); +} + +/// Assign pass manager to manage this pass. +void LoopPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find LPPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_LoopPassManager) + PMS.pop(); + + LPPassManager *LPPM; + if (PMS.top()->getPassManagerType() == PMT_LoopPassManager) + LPPM = (LPPassManager*)PMS.top(); + else { + // Create new Loop Pass Manager if it does not exist. + assert (!PMS.empty() && "Unable to create Loop Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + LPPM = new LPPassManager(PMD->getDepth() + 1); + LPPM->populateInheritedAnalysis(PMS); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(LPPM); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + Pass *P = LPPM->getAsPass(); + TPM->schedulePass(P); + + // [4] Push new manager into PMS + PMS.push(LPPM); + } + + LPPM->add(this); +} diff --git a/final/lib/Analysis/Makefile b/final/lib/Analysis/Makefile new file mode 100644 index 00000000000..4af6d350a64 --- /dev/null +++ b/final/lib/Analysis/Makefile @@ -0,0 +1,16 @@ +##===- lib/Analysis/Makefile -------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMAnalysis +DIRS = IPA +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Analysis/MemDepPrinter.cpp b/final/lib/Analysis/MemDepPrinter.cpp new file mode 100644 index 00000000000..64d215c37cc --- /dev/null +++ b/final/lib/Analysis/MemDepPrinter.cpp @@ -0,0 +1,167 @@ +//===- MemDepPrinter.cpp - Printer for MemoryDependenceAnalysis -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/LLVMContext.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SetVector.h" +using namespace llvm; + +namespace { + struct MemDepPrinter : public FunctionPass { + const Function *F; + + typedef PointerIntPair InstAndClobberFlag; + typedef std::pair Dep; + typedef SmallSetVector DepSet; + typedef DenseMap DepSetMap; + DepSetMap Deps; + + static char ID; // Pass identifcation, replacement for typeid + MemDepPrinter() : FunctionPass(ID) { + initializeMemDepPrinterPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &F); + + void print(raw_ostream &OS, const Module * = 0) const; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + AU.setPreservesAll(); + } + + virtual void releaseMemory() { + Deps.clear(); + F = 0; + } + }; +} + +char MemDepPrinter::ID = 0; +INITIALIZE_PASS_BEGIN(MemDepPrinter, "print-memdeps", + "Print MemDeps of function", false, true) +INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis) +INITIALIZE_PASS_END(MemDepPrinter, "print-memdeps", + "Print MemDeps of function", false, true) + +FunctionPass *llvm::createMemDepPrinter() { + return new MemDepPrinter(); +} + +bool MemDepPrinter::runOnFunction(Function &F) { + this->F = &F; + AliasAnalysis &AA = getAnalysis(); + MemoryDependenceAnalysis &MDA = getAnalysis(); + + // All this code uses non-const interfaces because MemDep is not + // const-friendly, though nothing is actually modified. + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + Instruction *Inst = &*I; + + if (!Inst->mayReadFromMemory() && !Inst->mayWriteToMemory()) + continue; + + MemDepResult Res = MDA.getDependency(Inst); + if (!Res.isNonLocal()) { + assert(Res.isClobber() != Res.isDef() && + "Local dep should be def or clobber!"); + Deps[Inst].insert(std::make_pair(InstAndClobberFlag(Res.getInst(), + Res.isClobber()), + static_cast(0))); + } else if (CallSite CS = cast(Inst)) { + const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI = + MDA.getNonLocalCallDependency(CS); + + DepSet &InstDeps = Deps[Inst]; + for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator + I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { + const MemDepResult &Res = I->getResult(); + assert(Res.isClobber() != Res.isDef() && + "Resolved non-local call dep should be def or clobber!"); + InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(), + Res.isClobber()), + I->getBB())); + } + } else { + SmallVector NLDI; + if (LoadInst *LI = dyn_cast(Inst)) { + // FIXME: Volatile is not handled properly here. + AliasAnalysis::Location Loc = AA.getLocation(LI); + MDA.getNonLocalPointerDependency(Loc, !LI->isVolatile(), + LI->getParent(), NLDI); + } else if (StoreInst *SI = dyn_cast(Inst)) { + // FIXME: Volatile is not handled properly here. + AliasAnalysis::Location Loc = AA.getLocation(SI); + MDA.getNonLocalPointerDependency(Loc, false, SI->getParent(), NLDI); + } else if (VAArgInst *VI = dyn_cast(Inst)) { + AliasAnalysis::Location Loc = AA.getLocation(VI); + MDA.getNonLocalPointerDependency(Loc, false, VI->getParent(), NLDI); + } else { + llvm_unreachable("Unknown memory instruction!"); + } + + DepSet &InstDeps = Deps[Inst]; + for (SmallVectorImpl::const_iterator + I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { + const MemDepResult &Res = I->getResult(); + assert(Res.isClobber() != Res.isDef() && + "Resolved non-local pointer dep should be def or clobber!"); + InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(), + Res.isClobber()), + I->getBB())); + } + } + } + + return false; +} + +void MemDepPrinter::print(raw_ostream &OS, const Module *M) const { + for (const_inst_iterator I = inst_begin(*F), E = inst_end(*F); I != E; ++I) { + const Instruction *Inst = &*I; + + DepSetMap::const_iterator DI = Deps.find(Inst); + if (DI == Deps.end()) + continue; + + const DepSet &InstDeps = DI->second; + + for (DepSet::const_iterator I = InstDeps.begin(), E = InstDeps.end(); + I != E; ++I) { + const Instruction *DepInst = I->first.getPointer(); + bool isClobber = I->first.getInt(); + const BasicBlock *DepBB = I->second; + + OS << " " << (isClobber ? "Clobber" : " Def"); + if (DepBB) { + OS << " in block "; + WriteAsOperand(OS, DepBB, /*PrintType=*/false, M); + } + OS << " from: "; + if (DepInst == Inst) + OS << ""; + else + DepInst->print(OS); + OS << "\n"; + } + + Inst->print(OS); + OS << "\n\n"; + } +} diff --git a/final/lib/Analysis/MemoryBuiltins.cpp b/final/lib/Analysis/MemoryBuiltins.cpp new file mode 100644 index 00000000000..1ab18ca054a --- /dev/null +++ b/final/lib/Analysis/MemoryBuiltins.cpp @@ -0,0 +1,207 @@ +//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions identifies calls to builtin functions that allocate +// or free memory. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// malloc Call Utility Functions. +// + +/// isMalloc - Returns true if the value is either a malloc call or a +/// bitcast of the result of a malloc call. +bool llvm::isMalloc(const Value *I) { + return extractMallocCall(I) || extractMallocCallFromBitCast(I); +} + +static bool isMallocCall(const CallInst *CI) { + if (!CI) + return false; + + Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "malloc") + return false; + + // Check malloc prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = Callee->getFunctionType(); + if (FTy->getNumParams() != 1) + return false; + if (IntegerType *ITy = dyn_cast(FTy->param_begin()->get())) { + if (ITy->getBitWidth() != 32 && ITy->getBitWidth() != 64) + return false; + return true; + } + + return false; +} + +/// extractMallocCall - Returns the corresponding CallInst if the instruction +/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we +/// ignore InvokeInst here. +const CallInst *llvm::extractMallocCall(const Value *I) { + const CallInst *CI = dyn_cast(I); + return (isMallocCall(CI)) ? CI : NULL; +} + +CallInst *llvm::extractMallocCall(Value *I) { + CallInst *CI = dyn_cast(I); + return (isMallocCall(CI)) ? CI : NULL; +} + +static bool isBitCastOfMallocCall(const BitCastInst *BCI) { + if (!BCI) + return false; + + return isMallocCall(dyn_cast(BCI->getOperand(0))); +} + +/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the +/// instruction is a bitcast of the result of a malloc call. +CallInst *llvm::extractMallocCallFromBitCast(Value *I) { + BitCastInst *BCI = dyn_cast(I); + return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) + : NULL; +} + +const CallInst *llvm::extractMallocCallFromBitCast(const Value *I) { + const BitCastInst *BCI = dyn_cast(I); + return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) + : NULL; +} + +static Value *computeArraySize(const CallInst *CI, const TargetData *TD, + bool LookThroughSExt = false) { + if (!CI) + return NULL; + + // The size of the malloc's result type must be known to determine array size. + const Type *T = getMallocAllocatedType(CI); + if (!T || !T->isSized() || !TD) + return NULL; + + unsigned ElementSize = TD->getTypeAllocSize(T); + if (const StructType *ST = dyn_cast(T)) + ElementSize = TD->getStructLayout(ST)->getSizeInBytes(); + + // If malloc call's arg can be determined to be a multiple of ElementSize, + // return the multiple. Otherwise, return NULL. + Value *MallocArg = CI->getArgOperand(0); + Value *Multiple = NULL; + if (ComputeMultiple(MallocArg, ElementSize, Multiple, + LookThroughSExt)) + return Multiple; + + return NULL; +} + +/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// is a call to malloc whose array size can be determined and the array size +/// is not constant 1. Otherwise, return NULL. +const CallInst *llvm::isArrayMalloc(const Value *I, const TargetData *TD) { + const CallInst *CI = extractMallocCall(I); + Value *ArraySize = computeArraySize(CI, TD); + + if (ArraySize && + ArraySize != ConstantInt::get(CI->getArgOperand(0)->getType(), 1)) + return CI; + + // CI is a non-array malloc or we can't figure out that it is an array malloc. + return NULL; +} + +/// getMallocType - Returns the PointerType resulting from the malloc call. +/// The PointerType depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const PointerType *llvm::getMallocType(const CallInst *CI) { + assert(isMalloc(CI) && "getMallocType and not malloc call"); + + const PointerType *MallocType = NULL; + unsigned NumOfBitCastUses = 0; + + // Determine if CallInst has a bitcast use. + for (Value::const_use_iterator UI = CI->use_begin(), E = CI->use_end(); + UI != E; ) + if (const BitCastInst *BCI = dyn_cast(*UI++)) { + MallocType = cast(BCI->getDestTy()); + NumOfBitCastUses++; + } + + // Malloc call has 1 bitcast use, so type is the bitcast's destination type. + if (NumOfBitCastUses == 1) + return MallocType; + + // Malloc call was not bitcast, so type is the malloc function's return type. + if (NumOfBitCastUses == 0) + return cast(CI->getType()); + + // Type could not be determined. + return NULL; +} + +/// getMallocAllocatedType - Returns the Type allocated by malloc call. +/// The Type depends on the number of bitcast uses of the malloc call: +/// 0: PointerType is the malloc calls' return type. +/// 1: PointerType is the bitcast's result type. +/// >1: Unique PointerType cannot be determined, return NULL. +const Type *llvm::getMallocAllocatedType(const CallInst *CI) { + const PointerType *PT = getMallocType(CI); + return PT ? PT->getElementType() : NULL; +} + +/// getMallocArraySize - Returns the array size of a malloc call. If the +/// argument passed to malloc is a multiple of the size of the malloced type, +/// then return that multiple. For non-array mallocs, the multiple is +/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be +/// determined. +Value *llvm::getMallocArraySize(CallInst *CI, const TargetData *TD, + bool LookThroughSExt) { + assert(isMalloc(CI) && "getMallocArraySize and not malloc call"); + return computeArraySize(CI, TD, LookThroughSExt); +} + +//===----------------------------------------------------------------------===// +// free Call Utility Functions. +// + +/// isFreeCall - Returns non-null if the value is a call to the builtin free() +const CallInst *llvm::isFreeCall(const Value *I) { + const CallInst *CI = dyn_cast(I); + if (!CI) + return 0; + Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || !Callee->isDeclaration() || Callee->getName() != "free") + return 0; + + // Check free prototype. + // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin + // attribute will exist. + const FunctionType *FTy = Callee->getFunctionType(); + if (!FTy->getReturnType()->isVoidTy()) + return 0; + if (FTy->getNumParams() != 1) + return 0; + if (FTy->param_begin()->get() != Type::getInt8PtrTy(Callee->getContext())) + return 0; + + return CI; +} diff --git a/final/lib/Analysis/MemoryDependenceAnalysis.cpp b/final/lib/Analysis/MemoryDependenceAnalysis.cpp new file mode 100644 index 00000000000..35043bddfaf --- /dev/null +++ b/final/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -0,0 +1,1324 @@ +//===- MemoryDependenceAnalysis.cpp - Mem Deps Implementation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an analysis that determines, for a given memory +// operation, what preceding memory operations it depends on. It builds on +// alias analysis information, and tries to provide a lazy, caching interface to +// a common kind of alias information query. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "memdep" +#include "llvm/Analysis/MemoryDependenceAnalysis.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/PHITransAddr.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/PredIteratorCache.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +STATISTIC(NumCacheNonLocal, "Number of fully cached non-local responses"); +STATISTIC(NumCacheDirtyNonLocal, "Number of dirty cached non-local responses"); +STATISTIC(NumUncacheNonLocal, "Number of uncached non-local responses"); + +STATISTIC(NumCacheNonLocalPtr, + "Number of fully cached non-local ptr responses"); +STATISTIC(NumCacheDirtyNonLocalPtr, + "Number of cached, but dirty, non-local ptr responses"); +STATISTIC(NumUncacheNonLocalPtr, + "Number of uncached non-local ptr responses"); +STATISTIC(NumCacheCompleteNonLocalPtr, + "Number of block queries that were completely cached"); + +char MemoryDependenceAnalysis::ID = 0; + +// Register this pass... +INITIALIZE_PASS_BEGIN(MemoryDependenceAnalysis, "memdep", + "Memory Dependence Analysis", false, true) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(MemoryDependenceAnalysis, "memdep", + "Memory Dependence Analysis", false, true) + +MemoryDependenceAnalysis::MemoryDependenceAnalysis() +: FunctionPass(ID), PredCache(0) { + initializeMemoryDependenceAnalysisPass(*PassRegistry::getPassRegistry()); +} +MemoryDependenceAnalysis::~MemoryDependenceAnalysis() { +} + +/// Clean up memory in between runs +void MemoryDependenceAnalysis::releaseMemory() { + LocalDeps.clear(); + NonLocalDeps.clear(); + NonLocalPointerDeps.clear(); + ReverseLocalDeps.clear(); + ReverseNonLocalDeps.clear(); + ReverseNonLocalPtrDeps.clear(); + PredCache->clear(); +} + + + +/// getAnalysisUsage - Does not modify anything. It uses Alias Analysis. +/// +void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); +} + +bool MemoryDependenceAnalysis::runOnFunction(Function &) { + AA = &getAnalysis(); + TD = getAnalysisIfAvailable(); + if (PredCache == 0) + PredCache.reset(new PredIteratorCache()); + return false; +} + +/// RemoveFromReverseMap - This is a helper function that removes Val from +/// 'Inst's set in ReverseMap. If the set becomes empty, remove Inst's entry. +template +static void RemoveFromReverseMap(DenseMap > &ReverseMap, + Instruction *Inst, KeyTy Val) { + typename DenseMap >::iterator + InstIt = ReverseMap.find(Inst); + assert(InstIt != ReverseMap.end() && "Reverse map out of sync?"); + bool Found = InstIt->second.erase(Val); + assert(Found && "Invalid reverse map!"); (void)Found; + if (InstIt->second.empty()) + ReverseMap.erase(InstIt); +} + +/// GetLocation - If the given instruction references a specific memory +/// location, fill in Loc with the details, otherwise set Loc.Ptr to null. +/// Return a ModRefInfo value describing the general behavior of the +/// instruction. +static +AliasAnalysis::ModRefResult GetLocation(const Instruction *Inst, + AliasAnalysis::Location &Loc, + AliasAnalysis *AA) { + if (const LoadInst *LI = dyn_cast(Inst)) { + if (LI->isVolatile()) { + Loc = AliasAnalysis::Location(); + return AliasAnalysis::ModRef; + } + Loc = AA->getLocation(LI); + return AliasAnalysis::Ref; + } + + if (const StoreInst *SI = dyn_cast(Inst)) { + if (SI->isVolatile()) { + Loc = AliasAnalysis::Location(); + return AliasAnalysis::ModRef; + } + Loc = AA->getLocation(SI); + return AliasAnalysis::Mod; + } + + if (const VAArgInst *V = dyn_cast(Inst)) { + Loc = AA->getLocation(V); + return AliasAnalysis::ModRef; + } + + if (const CallInst *CI = isFreeCall(Inst)) { + // calls to free() deallocate the entire structure + Loc = AliasAnalysis::Location(CI->getArgOperand(0)); + return AliasAnalysis::Mod; + } + + if (const IntrinsicInst *II = dyn_cast(Inst)) + switch (II->getIntrinsicID()) { + case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: + case Intrinsic::invariant_start: + Loc = AliasAnalysis::Location(II->getArgOperand(1), + cast(II->getArgOperand(0)) + ->getZExtValue(), + II->getMetadata(LLVMContext::MD_tbaa)); + // These intrinsics don't really modify the memory, but returning Mod + // will allow them to be handled conservatively. + return AliasAnalysis::Mod; + case Intrinsic::invariant_end: + Loc = AliasAnalysis::Location(II->getArgOperand(2), + cast(II->getArgOperand(1)) + ->getZExtValue(), + II->getMetadata(LLVMContext::MD_tbaa)); + // These intrinsics don't really modify the memory, but returning Mod + // will allow them to be handled conservatively. + return AliasAnalysis::Mod; + default: + break; + } + + // Otherwise, just do the coarse-grained thing that always works. + if (Inst->mayWriteToMemory()) + return AliasAnalysis::ModRef; + if (Inst->mayReadFromMemory()) + return AliasAnalysis::Ref; + return AliasAnalysis::NoModRef; +} + +/// getCallSiteDependencyFrom - Private helper for finding the local +/// dependencies of a call site. +MemDepResult MemoryDependenceAnalysis:: +getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall, + BasicBlock::iterator ScanIt, BasicBlock *BB) { + // Walk backwards through the block, looking for dependencies + while (ScanIt != BB->begin()) { + Instruction *Inst = --ScanIt; + + // If this inst is a memory op, get the pointer it accessed + AliasAnalysis::Location Loc; + AliasAnalysis::ModRefResult MR = GetLocation(Inst, Loc, AA); + if (Loc.Ptr) { + // A simple instruction. + if (AA->getModRefInfo(CS, Loc) != AliasAnalysis::NoModRef) + return MemDepResult::getClobber(Inst); + continue; + } + + if (CallSite InstCS = cast(Inst)) { + // Debug intrinsics don't cause dependences. + if (isa(Inst)) continue; + // If these two calls do not interfere, look past it. + switch (AA->getModRefInfo(CS, InstCS)) { + case AliasAnalysis::NoModRef: + // If the two calls are the same, return InstCS as a Def, so that + // CS can be found redundant and eliminated. + if (isReadOnlyCall && !(MR & AliasAnalysis::Mod) && + CS.getInstruction()->isIdenticalToWhenDefined(Inst)) + return MemDepResult::getDef(Inst); + + // Otherwise if the two calls don't interact (e.g. InstCS is readnone) + // keep scanning. + break; + default: + return MemDepResult::getClobber(Inst); + } + } + } + + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (BB != &BB->getParent()->getEntryBlock()) + return MemDepResult::getNonLocal(); + return MemDepResult::getClobber(ScanIt); +} + +/// getPointerDependencyFrom - Return the instruction on which a memory +/// location depends. If isLoad is true, this routine ignores may-aliases with +/// read-only operations. If isLoad is false, this routine ignores may-aliases +/// with reads from read-only locations. +MemDepResult MemoryDependenceAnalysis:: +getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad, + BasicBlock::iterator ScanIt, BasicBlock *BB) { + + Value *InvariantTag = 0; + + // Walk backwards through the basic block, looking for dependencies. + while (ScanIt != BB->begin()) { + Instruction *Inst = --ScanIt; + + // If we're in an invariant region, no dependencies can be found before + // we pass an invariant-begin marker. + if (InvariantTag == Inst) { + InvariantTag = 0; + continue; + } + + if (IntrinsicInst *II = dyn_cast(Inst)) { + // Debug intrinsics don't (and can't) cause dependences. + if (isa(II)) continue; + + // If we pass an invariant-end marker, then we've just entered an + // invariant region and can start ignoring dependencies. + if (II->getIntrinsicID() == Intrinsic::invariant_end) { + // FIXME: This only considers queries directly on the invariant-tagged + // pointer, not on query pointers that are indexed off of them. It'd + // be nice to handle that at some point. + AliasAnalysis::AliasResult R = + AA->alias(AliasAnalysis::Location(II->getArgOperand(2)), MemLoc); + if (R == AliasAnalysis::MustAlias) + InvariantTag = II->getArgOperand(0); + + continue; + } + + // If we reach a lifetime begin or end marker, then the query ends here + // because the value is undefined. + if (II->getIntrinsicID() == Intrinsic::lifetime_start) { + // FIXME: This only considers queries directly on the invariant-tagged + // pointer, not on query pointers that are indexed off of them. It'd + // be nice to handle that at some point. + AliasAnalysis::AliasResult R = + AA->alias(AliasAnalysis::Location(II->getArgOperand(1)), MemLoc); + if (R == AliasAnalysis::MustAlias) + return MemDepResult::getDef(II); + continue; + } + } + + // If we're querying on a load and we're in an invariant region, we're done + // at this point. Nothing a load depends on can live in an invariant region. + // + // FIXME: this will prevent us from returning load/load must-aliases, so GVN + // won't remove redundant loads. + if (isLoad && InvariantTag) continue; + + // Values depend on loads if the pointers are must aliased. This means that + // a load depends on another must aliased load from the same value. + if (LoadInst *LI = dyn_cast(Inst)) { + AliasAnalysis::Location LoadLoc = AA->getLocation(LI); + + // If we found a pointer, check if it could be the same as our pointer. + AliasAnalysis::AliasResult R = AA->alias(LoadLoc, MemLoc); + if (R == AliasAnalysis::NoAlias) + continue; + + // May-alias loads don't depend on each other without a dependence. + if (isLoad && R != AliasAnalysis::MustAlias) + continue; + + // Stores don't alias loads from read-only memory. + if (!isLoad && AA->pointsToConstantMemory(LoadLoc)) + continue; + + // Stores depend on may and must aliased loads, loads depend on must-alias + // loads. + return MemDepResult::getDef(Inst); + } + + if (StoreInst *SI = dyn_cast(Inst)) { + // There can't be stores to the value we care about inside an + // invariant region. + if (InvariantTag) continue; + + // If alias analysis can tell that this store is guaranteed to not modify + // the query pointer, ignore it. Use getModRefInfo to handle cases where + // the query pointer points to constant memory etc. + if (AA->getModRefInfo(SI, MemLoc) == AliasAnalysis::NoModRef) + continue; + + // Ok, this store might clobber the query pointer. Check to see if it is + // a must alias: in this case, we want to return this as a def. + AliasAnalysis::Location StoreLoc = AA->getLocation(SI); + + // If we found a pointer, check if it could be the same as our pointer. + AliasAnalysis::AliasResult R = AA->alias(StoreLoc, MemLoc); + + if (R == AliasAnalysis::NoAlias) + continue; + if (R == AliasAnalysis::MustAlias) + return MemDepResult::getDef(Inst); + return MemDepResult::getClobber(Inst); + } + + // If this is an allocation, and if we know that the accessed pointer is to + // the allocation, return Def. This means that there is no dependence and + // the access can be optimized based on that. For example, a load could + // turn into undef. + // Note: Only determine this to be a malloc if Inst is the malloc call, not + // a subsequent bitcast of the malloc call result. There can be stores to + // the malloced memory between the malloc call and its bitcast uses, and we + // need to continue scanning until the malloc call. + if (isa(Inst) || + (isa(Inst) && extractMallocCall(Inst))) { + const Value *AccessPtr = GetUnderlyingObject(MemLoc.Ptr, TD); + + if (AccessPtr == Inst || + AA->alias(Inst, 1, AccessPtr, 1) == AliasAnalysis::MustAlias) + return MemDepResult::getDef(Inst); + continue; + } + + // See if this instruction (e.g. a call or vaarg) mod/ref's the pointer. + switch (AA->getModRefInfo(Inst, MemLoc)) { + case AliasAnalysis::NoModRef: + // If the call has no effect on the queried pointer, just ignore it. + continue; + case AliasAnalysis::Mod: + // If we're in an invariant region, we can ignore calls that ONLY + // modify the pointer. + if (InvariantTag) continue; + return MemDepResult::getClobber(Inst); + case AliasAnalysis::Ref: + // If the call is known to never store to the pointer, and if this is a + // load query, we can safely ignore it (scan past it). + if (isLoad) + continue; + default: + // Otherwise, there is a potential dependence. Return a clobber. + return MemDepResult::getClobber(Inst); + } + } + + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (BB != &BB->getParent()->getEntryBlock()) + return MemDepResult::getNonLocal(); + return MemDepResult::getClobber(ScanIt); +} + +/// getDependency - Return the instruction on which a memory operation +/// depends. +MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) { + Instruction *ScanPos = QueryInst; + + // Check for a cached result + MemDepResult &LocalCache = LocalDeps[QueryInst]; + + // If the cached entry is non-dirty, just return it. Note that this depends + // on MemDepResult's default constructing to 'dirty'. + if (!LocalCache.isDirty()) + return LocalCache; + + // Otherwise, if we have a dirty entry, we know we can start the scan at that + // instruction, which may save us some work. + if (Instruction *Inst = LocalCache.getInst()) { + ScanPos = Inst; + + RemoveFromReverseMap(ReverseLocalDeps, Inst, QueryInst); + } + + BasicBlock *QueryParent = QueryInst->getParent(); + + // Do the scan. + if (BasicBlock::iterator(QueryInst) == QueryParent->begin()) { + // No dependence found. If this is the entry block of the function, it is a + // clobber, otherwise it is non-local. + if (QueryParent != &QueryParent->getParent()->getEntryBlock()) + LocalCache = MemDepResult::getNonLocal(); + else + LocalCache = MemDepResult::getClobber(QueryInst); + } else { + AliasAnalysis::Location MemLoc; + AliasAnalysis::ModRefResult MR = GetLocation(QueryInst, MemLoc, AA); + if (MemLoc.Ptr) { + // If we can do a pointer scan, make it happen. + bool isLoad = !(MR & AliasAnalysis::Mod); + if (IntrinsicInst *II = dyn_cast(QueryInst)) + isLoad |= II->getIntrinsicID() == Intrinsic::lifetime_end; + + LocalCache = getPointerDependencyFrom(MemLoc, isLoad, ScanPos, + QueryParent); + } else if (isa(QueryInst) || isa(QueryInst)) { + CallSite QueryCS(QueryInst); + bool isReadOnly = AA->onlyReadsMemory(QueryCS); + LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos, + QueryParent); + } else + // Non-memory instruction. + LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos)); + } + + // Remember the result! + if (Instruction *I = LocalCache.getInst()) + ReverseLocalDeps[I].insert(QueryInst); + + return LocalCache; +} + +#ifndef NDEBUG +/// AssertSorted - This method is used when -debug is specified to verify that +/// cache arrays are properly kept sorted. +static void AssertSorted(MemoryDependenceAnalysis::NonLocalDepInfo &Cache, + int Count = -1) { + if (Count == -1) Count = Cache.size(); + if (Count == 0) return; + + for (unsigned i = 1; i != unsigned(Count); ++i) + assert(!(Cache[i] < Cache[i-1]) && "Cache isn't sorted!"); +} +#endif + +/// getNonLocalCallDependency - Perform a full dependency query for the +/// specified call, returning the set of blocks that the value is +/// potentially live across. The returned set of results will include a +/// "NonLocal" result for all blocks where the value is live across. +/// +/// This method assumes the instruction returns a "NonLocal" dependency +/// within its own block. +/// +/// This returns a reference to an internal data structure that may be +/// invalidated on the next non-local query or when an instruction is +/// removed. Clients must copy this data if they want it around longer than +/// that. +const MemoryDependenceAnalysis::NonLocalDepInfo & +MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) { + assert(getDependency(QueryCS.getInstruction()).isNonLocal() && + "getNonLocalCallDependency should only be used on calls with non-local deps!"); + PerInstNLInfo &CacheP = NonLocalDeps[QueryCS.getInstruction()]; + NonLocalDepInfo &Cache = CacheP.first; + + /// DirtyBlocks - This is the set of blocks that need to be recomputed. In + /// the cached case, this can happen due to instructions being deleted etc. In + /// the uncached case, this starts out as the set of predecessors we care + /// about. + SmallVector DirtyBlocks; + + if (!Cache.empty()) { + // Okay, we have a cache entry. If we know it is not dirty, just return it + // with no computation. + if (!CacheP.second) { + ++NumCacheNonLocal; + return Cache; + } + + // If we already have a partially computed set of results, scan them to + // determine what is dirty, seeding our initial DirtyBlocks worklist. + for (NonLocalDepInfo::iterator I = Cache.begin(), E = Cache.end(); + I != E; ++I) + if (I->getResult().isDirty()) + DirtyBlocks.push_back(I->getBB()); + + // Sort the cache so that we can do fast binary search lookups below. + std::sort(Cache.begin(), Cache.end()); + + ++NumCacheDirtyNonLocal; + //cerr << "CACHED CASE: " << DirtyBlocks.size() << " dirty: " + // << Cache.size() << " cached: " << *QueryInst; + } else { + // Seed DirtyBlocks with each of the preds of QueryInst's block. + BasicBlock *QueryBB = QueryCS.getInstruction()->getParent(); + for (BasicBlock **PI = PredCache->GetPreds(QueryBB); *PI; ++PI) + DirtyBlocks.push_back(*PI); + ++NumUncacheNonLocal; + } + + // isReadonlyCall - If this is a read-only call, we can be more aggressive. + bool isReadonlyCall = AA->onlyReadsMemory(QueryCS); + + SmallPtrSet Visited; + + unsigned NumSortedEntries = Cache.size(); + DEBUG(AssertSorted(Cache)); + + // Iterate while we still have blocks to update. + while (!DirtyBlocks.empty()) { + BasicBlock *DirtyBB = DirtyBlocks.back(); + DirtyBlocks.pop_back(); + + // Already processed this block? + if (!Visited.insert(DirtyBB)) + continue; + + // Do a binary search to see if we already have an entry for this block in + // the cache set. If so, find it. + DEBUG(AssertSorted(Cache, NumSortedEntries)); + NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.begin()+NumSortedEntries, + NonLocalDepEntry(DirtyBB)); + if (Entry != Cache.begin() && prior(Entry)->getBB() == DirtyBB) + --Entry; + + NonLocalDepEntry *ExistingResult = 0; + if (Entry != Cache.begin()+NumSortedEntries && + Entry->getBB() == DirtyBB) { + // If we already have an entry, and if it isn't already dirty, the block + // is done. + if (!Entry->getResult().isDirty()) + continue; + + // Otherwise, remember this slot so we can update the value. + ExistingResult = &*Entry; + } + + // If the dirty entry has a pointer, start scanning from it so we don't have + // to rescan the entire block. + BasicBlock::iterator ScanPos = DirtyBB->end(); + if (ExistingResult) { + if (Instruction *Inst = ExistingResult->getResult().getInst()) { + ScanPos = Inst; + // We're removing QueryInst's use of Inst. + RemoveFromReverseMap(ReverseNonLocalDeps, Inst, + QueryCS.getInstruction()); + } + } + + // Find out if this block has a local dependency for QueryInst. + MemDepResult Dep; + + if (ScanPos != DirtyBB->begin()) { + Dep = getCallSiteDependencyFrom(QueryCS, isReadonlyCall,ScanPos, DirtyBB); + } else if (DirtyBB != &DirtyBB->getParent()->getEntryBlock()) { + // No dependence found. If this is the entry block of the function, it is + // a clobber, otherwise it is non-local. + Dep = MemDepResult::getNonLocal(); + } else { + Dep = MemDepResult::getClobber(ScanPos); + } + + // If we had a dirty entry for the block, update it. Otherwise, just add + // a new entry. + if (ExistingResult) + ExistingResult->setResult(Dep); + else + Cache.push_back(NonLocalDepEntry(DirtyBB, Dep)); + + // If the block has a dependency (i.e. it isn't completely transparent to + // the value), remember the association! + if (!Dep.isNonLocal()) { + // Keep the ReverseNonLocalDeps map up to date so we can efficiently + // update this when we remove instructions. + if (Instruction *Inst = Dep.getInst()) + ReverseNonLocalDeps[Inst].insert(QueryCS.getInstruction()); + } else { + + // If the block *is* completely transparent to the load, we need to check + // the predecessors of this block. Add them to our worklist. + for (BasicBlock **PI = PredCache->GetPreds(DirtyBB); *PI; ++PI) + DirtyBlocks.push_back(*PI); + } + } + + return Cache; +} + +/// getNonLocalPointerDependency - Perform a full dependency query for an +/// access to the specified (non-volatile) memory location, returning the +/// set of instructions that either define or clobber the value. +/// +/// This method assumes the pointer has a "NonLocal" dependency within its +/// own block. +/// +void MemoryDependenceAnalysis:: +getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, bool isLoad, + BasicBlock *FromBB, + SmallVectorImpl &Result) { + assert(Loc.Ptr->getType()->isPointerTy() && + "Can't get pointer deps of a non-pointer!"); + Result.clear(); + + PHITransAddr Address(const_cast(Loc.Ptr), TD); + + // This is the set of blocks we've inspected, and the pointer we consider in + // each block. Because of critical edges, we currently bail out if querying + // a block with multiple different pointers. This can happen during PHI + // translation. + DenseMap Visited; + if (!getNonLocalPointerDepFromBB(Address, Loc, isLoad, FromBB, + Result, Visited, true)) + return; + Result.clear(); + Result.push_back(NonLocalDepResult(FromBB, + MemDepResult::getClobber(FromBB->begin()), + const_cast(Loc.Ptr))); +} + +/// GetNonLocalInfoForBlock - Compute the memdep value for BB with +/// Pointer/PointeeSize using either cached information in Cache or by doing a +/// lookup (which may use dirty cache info if available). If we do a lookup, +/// add the result to the cache. +MemDepResult MemoryDependenceAnalysis:: +GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *BB, + NonLocalDepInfo *Cache, unsigned NumSortedEntries) { + + // Do a binary search to see if we already have an entry for this block in + // the cache set. If so, find it. + NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache->begin(), Cache->begin()+NumSortedEntries, + NonLocalDepEntry(BB)); + if (Entry != Cache->begin() && (Entry-1)->getBB() == BB) + --Entry; + + NonLocalDepEntry *ExistingResult = 0; + if (Entry != Cache->begin()+NumSortedEntries && Entry->getBB() == BB) + ExistingResult = &*Entry; + + // If we have a cached entry, and it is non-dirty, use it as the value for + // this dependency. + if (ExistingResult && !ExistingResult->getResult().isDirty()) { + ++NumCacheNonLocalPtr; + return ExistingResult->getResult(); + } + + // Otherwise, we have to scan for the value. If we have a dirty cache + // entry, start scanning from its position, otherwise we scan from the end + // of the block. + BasicBlock::iterator ScanPos = BB->end(); + if (ExistingResult && ExistingResult->getResult().getInst()) { + assert(ExistingResult->getResult().getInst()->getParent() == BB && + "Instruction invalidated?"); + ++NumCacheDirtyNonLocalPtr; + ScanPos = ExistingResult->getResult().getInst(); + + // Eliminating the dirty entry from 'Cache', so update the reverse info. + ValueIsLoadPair CacheKey(Loc.Ptr, isLoad); + RemoveFromReverseMap(ReverseNonLocalPtrDeps, ScanPos, CacheKey); + } else { + ++NumUncacheNonLocalPtr; + } + + // Scan the block for the dependency. + MemDepResult Dep = getPointerDependencyFrom(Loc, isLoad, ScanPos, BB); + + // If we had a dirty entry for the block, update it. Otherwise, just add + // a new entry. + if (ExistingResult) + ExistingResult->setResult(Dep); + else + Cache->push_back(NonLocalDepEntry(BB, Dep)); + + // If the block has a dependency (i.e. it isn't completely transparent to + // the value), remember the reverse association because we just added it + // to Cache! + if (Dep.isNonLocal()) + return Dep; + + // Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently + // update MemDep when we remove instructions. + Instruction *Inst = Dep.getInst(); + assert(Inst && "Didn't depend on anything?"); + ValueIsLoadPair CacheKey(Loc.Ptr, isLoad); + ReverseNonLocalPtrDeps[Inst].insert(CacheKey); + return Dep; +} + +/// SortNonLocalDepInfoCache - Sort the a NonLocalDepInfo cache, given a certain +/// number of elements in the array that are already properly ordered. This is +/// optimized for the case when only a few entries are added. +static void +SortNonLocalDepInfoCache(MemoryDependenceAnalysis::NonLocalDepInfo &Cache, + unsigned NumSortedEntries) { + switch (Cache.size() - NumSortedEntries) { + case 0: + // done, no new entries. + break; + case 2: { + // Two new entries, insert the last one into place. + NonLocalDepEntry Val = Cache.back(); + Cache.pop_back(); + MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.end()-1, Val); + Cache.insert(Entry, Val); + // FALL THROUGH. + } + case 1: + // One new entry, Just insert the new value at the appropriate position. + if (Cache.size() != 1) { + NonLocalDepEntry Val = Cache.back(); + Cache.pop_back(); + MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry = + std::upper_bound(Cache.begin(), Cache.end(), Val); + Cache.insert(Entry, Val); + } + break; + default: + // Added many values, do a full scale sort. + std::sort(Cache.begin(), Cache.end()); + break; + } +} + +/// getNonLocalPointerDepFromBB - Perform a dependency query based on +/// pointer/pointeesize starting at the end of StartBB. Add any clobber/def +/// results to the results vector and keep track of which blocks are visited in +/// 'Visited'. +/// +/// This has special behavior for the first block queries (when SkipFirstBlock +/// is true). In this special case, it ignores the contents of the specified +/// block and starts returning dependence info for its predecessors. +/// +/// This function returns false on success, or true to indicate that it could +/// not compute dependence information for some reason. This should be treated +/// as a clobber dependence on the first instruction in the predecessor block. +bool MemoryDependenceAnalysis:: +getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + const AliasAnalysis::Location &Loc, + bool isLoad, BasicBlock *StartBB, + SmallVectorImpl &Result, + DenseMap &Visited, + bool SkipFirstBlock) { + + // Look up the cached info for Pointer. + ValueIsLoadPair CacheKey(Pointer.getAddr(), isLoad); + + // Set up a temporary NLPI value. If the map doesn't yet have an entry for + // CacheKey, this value will be inserted as the associated value. Otherwise, + // it'll be ignored, and we'll have to check to see if the cached size and + // tbaa tag are consistent with the current query. + NonLocalPointerInfo InitialNLPI; + InitialNLPI.Size = Loc.Size; + InitialNLPI.TBAATag = Loc.TBAATag; + + // Get the NLPI for CacheKey, inserting one into the map if it doesn't + // already have one. + std::pair Pair = + NonLocalPointerDeps.insert(std::make_pair(CacheKey, InitialNLPI)); + NonLocalPointerInfo *CacheInfo = &Pair.first->second; + + // If we already have a cache entry for this CacheKey, we may need to do some + // work to reconcile the cache entry and the current query. + if (!Pair.second) { + if (CacheInfo->Size < Loc.Size) { + // The query's Size is greater than the cached one. Throw out the + // cached data and procede with the query at the greater size. + CacheInfo->Pair = BBSkipFirstBlockPair(); + CacheInfo->Size = Loc.Size; + for (NonLocalDepInfo::iterator DI = CacheInfo->NonLocalDeps.begin(), + DE = CacheInfo->NonLocalDeps.end(); DI != DE; ++DI) + if (Instruction *Inst = DI->getResult().getInst()) + RemoveFromReverseMap(ReverseNonLocalPtrDeps, Inst, CacheKey); + CacheInfo->NonLocalDeps.clear(); + } else if (CacheInfo->Size > Loc.Size) { + // This query's Size is less than the cached one. Conservatively restart + // the query using the greater size. + return getNonLocalPointerDepFromBB(Pointer, + Loc.getWithNewSize(CacheInfo->Size), + isLoad, StartBB, Result, Visited, + SkipFirstBlock); + } + + // If the query's TBAATag is inconsistent with the cached one, + // conservatively throw out the cached data and restart the query with + // no tag if needed. + if (CacheInfo->TBAATag != Loc.TBAATag) { + if (CacheInfo->TBAATag) { + CacheInfo->Pair = BBSkipFirstBlockPair(); + CacheInfo->TBAATag = 0; + for (NonLocalDepInfo::iterator DI = CacheInfo->NonLocalDeps.begin(), + DE = CacheInfo->NonLocalDeps.end(); DI != DE; ++DI) + if (Instruction *Inst = DI->getResult().getInst()) + RemoveFromReverseMap(ReverseNonLocalPtrDeps, Inst, CacheKey); + CacheInfo->NonLocalDeps.clear(); + } + if (Loc.TBAATag) + return getNonLocalPointerDepFromBB(Pointer, Loc.getWithoutTBAATag(), + isLoad, StartBB, Result, Visited, + SkipFirstBlock); + } + } + + NonLocalDepInfo *Cache = &CacheInfo->NonLocalDeps; + + // If we have valid cached information for exactly the block we are + // investigating, just return it with no recomputation. + if (CacheInfo->Pair == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) { + // We have a fully cached result for this query then we can just return the + // cached results and populate the visited set. However, we have to verify + // that we don't already have conflicting results for these blocks. Check + // to ensure that if a block in the results set is in the visited set that + // it was for the same pointer query. + if (!Visited.empty()) { + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); + I != E; ++I) { + DenseMap::iterator VI = Visited.find(I->getBB()); + if (VI == Visited.end() || VI->second == Pointer.getAddr()) + continue; + + // We have a pointer mismatch in a block. Just return clobber, saying + // that something was clobbered in this result. We could also do a + // non-fully cached query, but there is little point in doing this. + return true; + } + } + + Value *Addr = Pointer.getAddr(); + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); + I != E; ++I) { + Visited.insert(std::make_pair(I->getBB(), Addr)); + if (!I->getResult().isNonLocal()) + Result.push_back(NonLocalDepResult(I->getBB(), I->getResult(), Addr)); + } + ++NumCacheCompleteNonLocalPtr; + return false; + } + + // Otherwise, either this is a new block, a block with an invalid cache + // pointer or one that we're about to invalidate by putting more info into it + // than its valid cache info. If empty, the result will be valid cache info, + // otherwise it isn't. + if (Cache->empty()) + CacheInfo->Pair = BBSkipFirstBlockPair(StartBB, SkipFirstBlock); + else + CacheInfo->Pair = BBSkipFirstBlockPair(); + + SmallVector Worklist; + Worklist.push_back(StartBB); + + // Keep track of the entries that we know are sorted. Previously cached + // entries will all be sorted. The entries we add we only sort on demand (we + // don't insert every element into its sorted position). We know that we + // won't get any reuse from currently inserted values, because we don't + // revisit blocks after we insert info for them. + unsigned NumSortedEntries = Cache->size(); + DEBUG(AssertSorted(*Cache)); + + while (!Worklist.empty()) { + BasicBlock *BB = Worklist.pop_back_val(); + + // Skip the first block if we have it. + if (!SkipFirstBlock) { + // Analyze the dependency of *Pointer in FromBB. See if we already have + // been here. + assert(Visited.count(BB) && "Should check 'visited' before adding to WL"); + + // Get the dependency info for Pointer in BB. If we have cached + // information, we will use it, otherwise we compute it. + DEBUG(AssertSorted(*Cache, NumSortedEntries)); + MemDepResult Dep = GetNonLocalInfoForBlock(Loc, isLoad, BB, Cache, + NumSortedEntries); + + // If we got a Def or Clobber, add this to the list of results. + if (!Dep.isNonLocal()) { + Result.push_back(NonLocalDepResult(BB, Dep, Pointer.getAddr())); + continue; + } + } + + // If 'Pointer' is an instruction defined in this block, then we need to do + // phi translation to change it into a value live in the predecessor block. + // If not, we just add the predecessors to the worklist and scan them with + // the same Pointer. + if (!Pointer.NeedsPHITranslationFromBlock(BB)) { + SkipFirstBlock = false; + for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) { + // Verify that we haven't looked at this block yet. + std::pair::iterator, bool> + InsertRes = Visited.insert(std::make_pair(*PI, Pointer.getAddr())); + if (InsertRes.second) { + // First time we've looked at *PI. + Worklist.push_back(*PI); + continue; + } + + // If we have seen this block before, but it was with a different + // pointer then we have a phi translation failure and we have to treat + // this as a clobber. + if (InsertRes.first->second != Pointer.getAddr()) + goto PredTranslationFailure; + } + continue; + } + + // We do need to do phi translation, if we know ahead of time we can't phi + // translate this value, don't even try. + if (!Pointer.IsPotentiallyPHITranslatable()) + goto PredTranslationFailure; + + // We may have added values to the cache list before this PHI translation. + // If so, we haven't done anything to ensure that the cache remains sorted. + // Sort it now (if needed) so that recursive invocations of + // getNonLocalPointerDepFromBB and other routines that could reuse the cache + // value will only see properly sorted cache arrays. + if (Cache && NumSortedEntries != Cache->size()) { + SortNonLocalDepInfoCache(*Cache, NumSortedEntries); + NumSortedEntries = Cache->size(); + } + Cache = 0; + + for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) { + BasicBlock *Pred = *PI; + + // Get the PHI translated pointer in this predecessor. This can fail if + // not translatable, in which case the getAddr() returns null. + PHITransAddr PredPointer(Pointer); + PredPointer.PHITranslateValue(BB, Pred, 0); + + Value *PredPtrVal = PredPointer.getAddr(); + + // Check to see if we have already visited this pred block with another + // pointer. If so, we can't do this lookup. This failure can occur + // with PHI translation when a critical edge exists and the PHI node in + // the successor translates to a pointer value different than the + // pointer the block was first analyzed with. + std::pair::iterator, bool> + InsertRes = Visited.insert(std::make_pair(Pred, PredPtrVal)); + + if (!InsertRes.second) { + // If the predecessor was visited with PredPtr, then we already did + // the analysis and can ignore it. + if (InsertRes.first->second == PredPtrVal) + continue; + + // Otherwise, the block was previously analyzed with a different + // pointer. We can't represent the result of this case, so we just + // treat this as a phi translation failure. + goto PredTranslationFailure; + } + + // If PHI translation was unable to find an available pointer in this + // predecessor, then we have to assume that the pointer is clobbered in + // that predecessor. We can still do PRE of the load, which would insert + // a computation of the pointer in this predecessor. + if (PredPtrVal == 0) { + // Add the entry to the Result list. + NonLocalDepResult Entry(Pred, + MemDepResult::getClobber(Pred->getTerminator()), + PredPtrVal); + Result.push_back(Entry); + + // Since we had a phi translation failure, the cache for CacheKey won't + // include all of the entries that we need to immediately satisfy future + // queries. Mark this in NonLocalPointerDeps by setting the + // BBSkipFirstBlockPair pointer to null. This requires reuse of the + // cached value to do more work but not miss the phi trans failure. + NonLocalPointerInfo &NLPI = NonLocalPointerDeps[CacheKey]; + NLPI.Pair = BBSkipFirstBlockPair(); + continue; + } + + // FIXME: it is entirely possible that PHI translating will end up with + // the same value. Consider PHI translating something like: + // X = phi [x, bb1], [y, bb2]. PHI translating for bb1 doesn't *need* + // to recurse here, pedantically speaking. + + // If we have a problem phi translating, fall through to the code below + // to handle the failure condition. + if (getNonLocalPointerDepFromBB(PredPointer, + Loc.getWithNewPtr(PredPointer.getAddr()), + isLoad, Pred, + Result, Visited)) + goto PredTranslationFailure; + } + + // Refresh the CacheInfo/Cache pointer so that it isn't invalidated. + CacheInfo = &NonLocalPointerDeps[CacheKey]; + Cache = &CacheInfo->NonLocalDeps; + NumSortedEntries = Cache->size(); + + // Since we did phi translation, the "Cache" set won't contain all of the + // results for the query. This is ok (we can still use it to accelerate + // specific block queries) but we can't do the fastpath "return all + // results from the set" Clear out the indicator for this. + CacheInfo->Pair = BBSkipFirstBlockPair(); + SkipFirstBlock = false; + continue; + + PredTranslationFailure: + + if (Cache == 0) { + // Refresh the CacheInfo/Cache pointer if it got invalidated. + CacheInfo = &NonLocalPointerDeps[CacheKey]; + Cache = &CacheInfo->NonLocalDeps; + NumSortedEntries = Cache->size(); + } + + // Since we failed phi translation, the "Cache" set won't contain all of the + // results for the query. This is ok (we can still use it to accelerate + // specific block queries) but we can't do the fastpath "return all + // results from the set". Clear out the indicator for this. + CacheInfo->Pair = BBSkipFirstBlockPair(); + + // If *nothing* works, mark the pointer as being clobbered by the first + // instruction in this block. + // + // If this is the magic first block, return this as a clobber of the whole + // incoming value. Since we can't phi translate to one of the predecessors, + // we have to bail out. + if (SkipFirstBlock) + return true; + + for (NonLocalDepInfo::reverse_iterator I = Cache->rbegin(); ; ++I) { + assert(I != Cache->rend() && "Didn't find current block??"); + if (I->getBB() != BB) + continue; + + assert(I->getResult().isNonLocal() && + "Should only be here with transparent block"); + I->setResult(MemDepResult::getClobber(BB->begin())); + ReverseNonLocalPtrDeps[BB->begin()].insert(CacheKey); + Result.push_back(NonLocalDepResult(I->getBB(), I->getResult(), + Pointer.getAddr())); + break; + } + } + + // Okay, we're done now. If we added new values to the cache, re-sort it. + SortNonLocalDepInfoCache(*Cache, NumSortedEntries); + DEBUG(AssertSorted(*Cache)); + return false; +} + +/// RemoveCachedNonLocalPointerDependencies - If P exists in +/// CachedNonLocalPointerInfo, remove it. +void MemoryDependenceAnalysis:: +RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P) { + CachedNonLocalPointerInfo::iterator It = + NonLocalPointerDeps.find(P); + if (It == NonLocalPointerDeps.end()) return; + + // Remove all of the entries in the BB->val map. This involves removing + // instructions from the reverse map. + NonLocalDepInfo &PInfo = It->second.NonLocalDeps; + + for (unsigned i = 0, e = PInfo.size(); i != e; ++i) { + Instruction *Target = PInfo[i].getResult().getInst(); + if (Target == 0) continue; // Ignore non-local dep results. + assert(Target->getParent() == PInfo[i].getBB()); + + // Eliminating the dirty entry from 'Cache', so update the reverse info. + RemoveFromReverseMap(ReverseNonLocalPtrDeps, Target, P); + } + + // Remove P from NonLocalPointerDeps (which deletes NonLocalDepInfo). + NonLocalPointerDeps.erase(It); +} + + +/// invalidateCachedPointerInfo - This method is used to invalidate cached +/// information about the specified pointer, because it may be too +/// conservative in memdep. This is an optional call that can be used when +/// the client detects an equivalence between the pointer and some other +/// value and replaces the other value with ptr. This can make Ptr available +/// in more places that cached info does not necessarily keep. +void MemoryDependenceAnalysis::invalidateCachedPointerInfo(Value *Ptr) { + // If Ptr isn't really a pointer, just ignore it. + if (!Ptr->getType()->isPointerTy()) return; + // Flush store info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, false)); + // Flush load info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true)); +} + +/// invalidateCachedPredecessors - Clear the PredIteratorCache info. +/// This needs to be done when the CFG changes, e.g., due to splitting +/// critical edges. +void MemoryDependenceAnalysis::invalidateCachedPredecessors() { + PredCache->clear(); +} + +/// removeInstruction - Remove an instruction from the dependence analysis, +/// updating the dependence of instructions that previously depended on it. +/// This method attempts to keep the cache coherent using the reverse map. +void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) { + // Walk through the Non-local dependencies, removing this one as the value + // for any cached queries. + NonLocalDepMapType::iterator NLDI = NonLocalDeps.find(RemInst); + if (NLDI != NonLocalDeps.end()) { + NonLocalDepInfo &BlockMap = NLDI->second.first; + for (NonLocalDepInfo::iterator DI = BlockMap.begin(), DE = BlockMap.end(); + DI != DE; ++DI) + if (Instruction *Inst = DI->getResult().getInst()) + RemoveFromReverseMap(ReverseNonLocalDeps, Inst, RemInst); + NonLocalDeps.erase(NLDI); + } + + // If we have a cached local dependence query for this instruction, remove it. + // + LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst); + if (LocalDepEntry != LocalDeps.end()) { + // Remove us from DepInst's reverse set now that the local dep info is gone. + if (Instruction *Inst = LocalDepEntry->second.getInst()) + RemoveFromReverseMap(ReverseLocalDeps, Inst, RemInst); + + // Remove this local dependency info. + LocalDeps.erase(LocalDepEntry); + } + + // If we have any cached pointer dependencies on this instruction, remove + // them. If the instruction has non-pointer type, then it can't be a pointer + // base. + + // Remove it from both the load info and the store info. The instruction + // can't be in either of these maps if it is non-pointer. + if (RemInst->getType()->isPointerTy()) { + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, false)); + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, true)); + } + + // Loop over all of the things that depend on the instruction we're removing. + // + SmallVector, 8> ReverseDepsToAdd; + + // If we find RemInst as a clobber or Def in any of the maps for other values, + // we need to replace its entry with a dirty version of the instruction after + // it. If RemInst is a terminator, we use a null dirty value. + // + // Using a dirty version of the instruction after RemInst saves having to scan + // the entire block to get to this point. + MemDepResult NewDirtyVal; + if (!RemInst->isTerminator()) + NewDirtyVal = MemDepResult::getDirty(++BasicBlock::iterator(RemInst)); + + ReverseDepMapType::iterator ReverseDepIt = ReverseLocalDeps.find(RemInst); + if (ReverseDepIt != ReverseLocalDeps.end()) { + SmallPtrSet &ReverseDeps = ReverseDepIt->second; + // RemInst can't be the terminator if it has local stuff depending on it. + assert(!ReverseDeps.empty() && !isa(RemInst) && + "Nothing can locally depend on a terminator"); + + for (SmallPtrSet::iterator I = ReverseDeps.begin(), + E = ReverseDeps.end(); I != E; ++I) { + Instruction *InstDependingOnRemInst = *I; + assert(InstDependingOnRemInst != RemInst && + "Already removed our local dep info"); + + LocalDeps[InstDependingOnRemInst] = NewDirtyVal; + + // Make sure to remember that new things depend on NewDepInst. + assert(NewDirtyVal.getInst() && "There is no way something else can have " + "a local dep on this if it is a terminator!"); + ReverseDepsToAdd.push_back(std::make_pair(NewDirtyVal.getInst(), + InstDependingOnRemInst)); + } + + ReverseLocalDeps.erase(ReverseDepIt); + + // Add new reverse deps after scanning the set, to avoid invalidating the + // 'ReverseDeps' reference. + while (!ReverseDepsToAdd.empty()) { + ReverseLocalDeps[ReverseDepsToAdd.back().first] + .insert(ReverseDepsToAdd.back().second); + ReverseDepsToAdd.pop_back(); + } + } + + ReverseDepIt = ReverseNonLocalDeps.find(RemInst); + if (ReverseDepIt != ReverseNonLocalDeps.end()) { + SmallPtrSet &Set = ReverseDepIt->second; + for (SmallPtrSet::iterator I = Set.begin(), E = Set.end(); + I != E; ++I) { + assert(*I != RemInst && "Already removed NonLocalDep info for RemInst"); + + PerInstNLInfo &INLD = NonLocalDeps[*I]; + // The information is now dirty! + INLD.second = true; + + for (NonLocalDepInfo::iterator DI = INLD.first.begin(), + DE = INLD.first.end(); DI != DE; ++DI) { + if (DI->getResult().getInst() != RemInst) continue; + + // Convert to a dirty entry for the subsequent instruction. + DI->setResult(NewDirtyVal); + + if (Instruction *NextI = NewDirtyVal.getInst()) + ReverseDepsToAdd.push_back(std::make_pair(NextI, *I)); + } + } + + ReverseNonLocalDeps.erase(ReverseDepIt); + + // Add new reverse deps after scanning the set, to avoid invalidating 'Set' + while (!ReverseDepsToAdd.empty()) { + ReverseNonLocalDeps[ReverseDepsToAdd.back().first] + .insert(ReverseDepsToAdd.back().second); + ReverseDepsToAdd.pop_back(); + } + } + + // If the instruction is in ReverseNonLocalPtrDeps then it appears as a + // value in the NonLocalPointerDeps info. + ReverseNonLocalPtrDepTy::iterator ReversePtrDepIt = + ReverseNonLocalPtrDeps.find(RemInst); + if (ReversePtrDepIt != ReverseNonLocalPtrDeps.end()) { + SmallPtrSet &Set = ReversePtrDepIt->second; + SmallVector,8> ReversePtrDepsToAdd; + + for (SmallPtrSet::iterator I = Set.begin(), + E = Set.end(); I != E; ++I) { + ValueIsLoadPair P = *I; + assert(P.getPointer() != RemInst && + "Already removed NonLocalPointerDeps info for RemInst"); + + NonLocalDepInfo &NLPDI = NonLocalPointerDeps[P].NonLocalDeps; + + // The cache is not valid for any specific block anymore. + NonLocalPointerDeps[P].Pair = BBSkipFirstBlockPair(); + + // Update any entries for RemInst to use the instruction after it. + for (NonLocalDepInfo::iterator DI = NLPDI.begin(), DE = NLPDI.end(); + DI != DE; ++DI) { + if (DI->getResult().getInst() != RemInst) continue; + + // Convert to a dirty entry for the subsequent instruction. + DI->setResult(NewDirtyVal); + + if (Instruction *NewDirtyInst = NewDirtyVal.getInst()) + ReversePtrDepsToAdd.push_back(std::make_pair(NewDirtyInst, P)); + } + + // Re-sort the NonLocalDepInfo. Changing the dirty entry to its + // subsequent value may invalidate the sortedness. + std::sort(NLPDI.begin(), NLPDI.end()); + } + + ReverseNonLocalPtrDeps.erase(ReversePtrDepIt); + + while (!ReversePtrDepsToAdd.empty()) { + ReverseNonLocalPtrDeps[ReversePtrDepsToAdd.back().first] + .insert(ReversePtrDepsToAdd.back().second); + ReversePtrDepsToAdd.pop_back(); + } + } + + + assert(!NonLocalDeps.count(RemInst) && "RemInst got reinserted?"); + AA->deleteValue(RemInst); + DEBUG(verifyRemoved(RemInst)); +} +/// verifyRemoved - Verify that the specified instruction does not occur +/// in our internal data structures. +void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const { + for (LocalDepMapType::const_iterator I = LocalDeps.begin(), + E = LocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + assert(I->second.getInst() != D && + "Inst occurs in data structures"); + } + + for (CachedNonLocalPointerInfo::const_iterator I =NonLocalPointerDeps.begin(), + E = NonLocalPointerDeps.end(); I != E; ++I) { + assert(I->first.getPointer() != D && "Inst occurs in NLPD map key"); + const NonLocalDepInfo &Val = I->second.NonLocalDeps; + for (NonLocalDepInfo::const_iterator II = Val.begin(), E = Val.end(); + II != E; ++II) + assert(II->getResult().getInst() != D && "Inst occurs as NLPD value"); + } + + for (NonLocalDepMapType::const_iterator I = NonLocalDeps.begin(), + E = NonLocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + const PerInstNLInfo &INLD = I->second; + for (NonLocalDepInfo::const_iterator II = INLD.first.begin(), + EE = INLD.first.end(); II != EE; ++II) + assert(II->getResult().getInst() != D && "Inst occurs in data structures"); + } + + for (ReverseDepMapType::const_iterator I = ReverseLocalDeps.begin(), + E = ReverseLocalDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + for (SmallPtrSet::const_iterator II = I->second.begin(), + EE = I->second.end(); II != EE; ++II) + assert(*II != D && "Inst occurs in data structures"); + } + + for (ReverseDepMapType::const_iterator I = ReverseNonLocalDeps.begin(), + E = ReverseNonLocalDeps.end(); + I != E; ++I) { + assert(I->first != D && "Inst occurs in data structures"); + for (SmallPtrSet::const_iterator II = I->second.begin(), + EE = I->second.end(); II != EE; ++II) + assert(*II != D && "Inst occurs in data structures"); + } + + for (ReverseNonLocalPtrDepTy::const_iterator + I = ReverseNonLocalPtrDeps.begin(), + E = ReverseNonLocalPtrDeps.end(); I != E; ++I) { + assert(I->first != D && "Inst occurs in rev NLPD map"); + + for (SmallPtrSet::const_iterator II = I->second.begin(), + E = I->second.end(); II != E; ++II) + assert(*II != ValueIsLoadPair(D, false) && + *II != ValueIsLoadPair(D, true) && + "Inst occurs in ReverseNonLocalPtrDeps map"); + } + +} diff --git a/final/lib/Analysis/ModuleDebugInfoPrinter.cpp b/final/lib/Analysis/ModuleDebugInfoPrinter.cpp new file mode 100644 index 00000000000..e7e999cebeb --- /dev/null +++ b/final/lib/Analysis/ModuleDebugInfoPrinter.cpp @@ -0,0 +1,87 @@ +//===-- ModuleDebugInfoPrinter.cpp - Prints module debug info metadata ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass decodes the debug info metadata in a module and prints in a +// (sufficiently-prepared-) human-readable form. +// +// For example, run this pass from opt along with the -analyze option, and +// it'll print to standard output. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +namespace { + class ModuleDebugInfoPrinter : public ModulePass { + DebugInfoFinder Finder; + public: + static char ID; // Pass identification, replacement for typeid + ModuleDebugInfoPrinter() : ModulePass(ID) { + initializeModuleDebugInfoPrinterPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnModule(Module &M); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + virtual void print(raw_ostream &O, const Module *M) const; + }; +} + +char ModuleDebugInfoPrinter::ID = 0; +INITIALIZE_PASS(ModuleDebugInfoPrinter, "module-debuginfo", + "Decodes module-level debug info", false, true) + +ModulePass *llvm::createModuleDebugInfoPrinterPass() { + return new ModuleDebugInfoPrinter(); +} + +bool ModuleDebugInfoPrinter::runOnModule(Module &M) { + Finder.processModule(M); + return false; +} + +void ModuleDebugInfoPrinter::print(raw_ostream &O, const Module *M) const { + for (DebugInfoFinder::iterator I = Finder.compile_unit_begin(), + E = Finder.compile_unit_end(); I != E; ++I) { + O << "Compile Unit: "; + DICompileUnit(*I).print(O); + O << '\n'; + } + + for (DebugInfoFinder::iterator I = Finder.subprogram_begin(), + E = Finder.subprogram_end(); I != E; ++I) { + O << "Subprogram: "; + DISubprogram(*I).print(O); + O << '\n'; + } + + for (DebugInfoFinder::iterator I = Finder.global_variable_begin(), + E = Finder.global_variable_end(); I != E; ++I) { + O << "GlobalVariable: "; + DIGlobalVariable(*I).print(O); + O << '\n'; + } + + for (DebugInfoFinder::iterator I = Finder.type_begin(), + E = Finder.type_end(); I != E; ++I) { + O << "Type: "; + DIType(*I).print(O); + O << '\n'; + } +} diff --git a/final/lib/Analysis/NoAliasAnalysis.cpp b/final/lib/Analysis/NoAliasAnalysis.cpp new file mode 100644 index 00000000000..101c2d5b028 --- /dev/null +++ b/final/lib/Analysis/NoAliasAnalysis.cpp @@ -0,0 +1,88 @@ +//===- NoAliasAnalysis.cpp - Minimal Alias Analysis Impl ------------------===// +// +// 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 default implementation of the Alias Analysis interface +// that simply returns "I don't know" for all queries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetData.h" +using namespace llvm; + +namespace { + /// NoAA - This class implements the -no-aa pass, which always returns "I + /// don't know" for alias queries. NoAA is unlike other alias analysis + /// implementations, in that it does not chain to a previous analysis. As + /// such it doesn't follow many of the rules that other alias analyses must. + /// + struct NoAA : public ImmutablePass, public AliasAnalysis { + static char ID; // Class identification, replacement for typeinfo + NoAA() : ImmutablePass(ID) { + initializeNoAAPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + } + + virtual void initializePass() { + // Note: NoAA does not call InitializeAliasAnalysis because it's + // special and does not support chaining. + TD = getAnalysisIfAvailable(); + } + + virtual AliasResult alias(const Location &LocA, const Location &LocB) { + return MayAlias; + } + + virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS) { + return UnknownModRefBehavior; + } + virtual ModRefBehavior getModRefBehavior(const Function *F) { + return UnknownModRefBehavior; + } + + virtual bool pointsToConstantMemory(const Location &Loc, + bool OrLocal) { + return false; + } + virtual ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + return ModRef; + } + virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + return ModRef; + } + + virtual void deleteValue(Value *V) {} + virtual void copyValue(Value *From, Value *To) {} + virtual void addEscapingUse(Use &U) {} + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const void *ID) { + if (ID == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + }; +} // End of anonymous namespace + +// Register this pass... +char NoAA::ID = 0; +INITIALIZE_AG_PASS(NoAA, AliasAnalysis, "no-aa", + "No Alias Analysis (always returns 'may' alias)", + true, true, true) + +ImmutablePass *llvm::createNoAAPass() { return new NoAA(); } diff --git a/final/lib/Analysis/PHITransAddr.cpp b/final/lib/Analysis/PHITransAddr.cpp new file mode 100644 index 00000000000..93da5a48518 --- /dev/null +++ b/final/lib/Analysis/PHITransAddr.cpp @@ -0,0 +1,441 @@ +//===- PHITransAddr.cpp - PHI Translation for Addresses -------------------===// +// +// 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 PHITransAddr class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/PHITransAddr.h" +#include "llvm/Instructions.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static bool CanPHITrans(Instruction *Inst) { + if (isa(Inst) || + isa(Inst)) + return true; + + if (isa(Inst) && + Inst->isSafeToSpeculativelyExecute()) + return true; + + if (Inst->getOpcode() == Instruction::Add && + isa(Inst->getOperand(1))) + return true; + + // cerr << "MEMDEP: Could not PHI translate: " << *Pointer; + // if (isa(PtrInst) || isa(PtrInst)) + // cerr << "OP:\t\t\t\t" << *PtrInst->getOperand(0); + return false; +} + +void PHITransAddr::dump() const { + if (Addr == 0) { + dbgs() << "PHITransAddr: null\n"; + return; + } + dbgs() << "PHITransAddr: " << *Addr << "\n"; + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + dbgs() << " Input #" << i << " is " << *InstInputs[i] << "\n"; +} + + +static bool VerifySubExpr(Value *Expr, + SmallVectorImpl &InstInputs) { + // If this is a non-instruction value, there is nothing to do. + Instruction *I = dyn_cast(Expr); + if (I == 0) return true; + + // If it's an instruction, it is either in Tmp or its operands recursively + // are. + SmallVectorImpl::iterator Entry = + std::find(InstInputs.begin(), InstInputs.end(), I); + if (Entry != InstInputs.end()) { + InstInputs.erase(Entry); + return true; + } + + // If it isn't in the InstInputs list it is a subexpr incorporated into the + // address. Sanity check that it is phi translatable. + if (!CanPHITrans(I)) { + errs() << "Non phi translatable instruction found in PHITransAddr:\n"; + errs() << *I << '\n'; + llvm_unreachable("Either something is missing from InstInputs or " + "CanPHITrans is wrong."); + return false; + } + + // Validate the operands of the instruction. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (!VerifySubExpr(I->getOperand(i), InstInputs)) + return false; + + return true; +} + +/// Verify - Check internal consistency of this data structure. If the +/// structure is valid, it returns true. If invalid, it prints errors and +/// returns false. +bool PHITransAddr::Verify() const { + if (Addr == 0) return true; + + SmallVector Tmp(InstInputs.begin(), InstInputs.end()); + + if (!VerifySubExpr(Addr, Tmp)) + return false; + + if (!Tmp.empty()) { + errs() << "PHITransAddr contains extra instructions:\n"; + for (unsigned i = 0, e = InstInputs.size(); i != e; ++i) + errs() << " InstInput #" << i << " is " << *InstInputs[i] << "\n"; + llvm_unreachable("This is unexpected."); + return false; + } + + // a-ok. + return true; +} + + +/// IsPotentiallyPHITranslatable - If this needs PHI translation, return true +/// if we have some hope of doing it. This should be used as a filter to +/// avoid calling PHITranslateValue in hopeless situations. +bool PHITransAddr::IsPotentiallyPHITranslatable() const { + // If the input value is not an instruction, or if it is not defined in CurBB, + // then we don't need to phi translate it. + Instruction *Inst = dyn_cast(Addr); + return Inst == 0 || CanPHITrans(Inst); +} + + +static void RemoveInstInputs(Value *V, + SmallVectorImpl &InstInputs) { + Instruction *I = dyn_cast(V); + if (I == 0) return; + + // If the instruction is in the InstInputs list, remove it. + SmallVectorImpl::iterator Entry = + std::find(InstInputs.begin(), InstInputs.end(), I); + if (Entry != InstInputs.end()) { + InstInputs.erase(Entry); + return; + } + + assert(!isa(I) && "Error, removing something that isn't an input"); + + // Otherwise, it must have instruction inputs itself. Zap them recursively. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + if (Instruction *Op = dyn_cast(I->getOperand(i))) + RemoveInstInputs(Op, InstInputs); + } +} + +Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, + BasicBlock *PredBB, + const DominatorTree *DT) { + // If this is a non-instruction value, it can't require PHI translation. + Instruction *Inst = dyn_cast(V); + if (Inst == 0) return V; + + // Determine whether 'Inst' is an input to our PHI translatable expression. + bool isInput = std::count(InstInputs.begin(), InstInputs.end(), Inst); + + // Handle inputs instructions if needed. + if (isInput) { + if (Inst->getParent() != CurBB) { + // If it is an input defined in a different block, then it remains an + // input. + return Inst; + } + + // If 'Inst' is defined in this block and is an input that needs to be phi + // translated, we need to incorporate the value into the expression or fail. + + // In either case, the instruction itself isn't an input any longer. + InstInputs.erase(std::find(InstInputs.begin(), InstInputs.end(), Inst)); + + // If this is a PHI, go ahead and translate it. + if (PHINode *PN = dyn_cast(Inst)) + return AddAsInput(PN->getIncomingValueForBlock(PredBB)); + + // If this is a non-phi value, and it is analyzable, we can incorporate it + // into the expression by making all instruction operands be inputs. + if (!CanPHITrans(Inst)) + return 0; + + // All instruction operands are now inputs (and of course, they may also be + // defined in this block, so they may need to be phi translated themselves. + for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i) + if (Instruction *Op = dyn_cast(Inst->getOperand(i))) + InstInputs.push_back(Op); + } + + // Ok, it must be an intermediate result (either because it started that way + // or because we just incorporated it into the expression). See if its + // operands need to be phi translated, and if so, reconstruct it. + + if (CastInst *Cast = dyn_cast(Inst)) { + if (!Cast->isSafeToSpeculativelyExecute()) return 0; + Value *PHIIn = PHITranslateSubExpr(Cast->getOperand(0), CurBB, PredBB, DT); + if (PHIIn == 0) return 0; + if (PHIIn == Cast->getOperand(0)) + return Cast; + + // Find an available version of this cast. + + // Constants are trivial to find. + if (Constant *C = dyn_cast(PHIIn)) + return AddAsInput(ConstantExpr::getCast(Cast->getOpcode(), + C, Cast->getType())); + + // Otherwise we have to see if a casted version of the incoming pointer + // is available. If so, we can use it, otherwise we have to fail. + for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end(); + UI != E; ++UI) { + if (CastInst *CastI = dyn_cast(*UI)) + if (CastI->getOpcode() == Cast->getOpcode() && + CastI->getType() == Cast->getType() && + (!DT || DT->dominates(CastI->getParent(), PredBB))) + return CastI; + } + return 0; + } + + // Handle getelementptr with at least one PHI translatable operand. + if (GetElementPtrInst *GEP = dyn_cast(Inst)) { + SmallVector GEPOps; + bool AnyChanged = false; + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { + Value *GEPOp = PHITranslateSubExpr(GEP->getOperand(i), CurBB, PredBB, DT); + if (GEPOp == 0) return 0; + + AnyChanged |= GEPOp != GEP->getOperand(i); + GEPOps.push_back(GEPOp); + } + + if (!AnyChanged) + return GEP; + + // Simplify the GEP to handle 'gep x, 0' -> x etc. + if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD, DT)) { + for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) + RemoveInstInputs(GEPOps[i], InstInputs); + + return AddAsInput(V); + } + + // Scan to see if we have this GEP available. + Value *APHIOp = GEPOps[0]; + for (Value::use_iterator UI = APHIOp->use_begin(), E = APHIOp->use_end(); + UI != E; ++UI) { + if (GetElementPtrInst *GEPI = dyn_cast(*UI)) + if (GEPI->getType() == GEP->getType() && + GEPI->getNumOperands() == GEPOps.size() && + GEPI->getParent()->getParent() == CurBB->getParent() && + (!DT || DT->dominates(GEPI->getParent(), PredBB))) { + bool Mismatch = false; + for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) + if (GEPI->getOperand(i) != GEPOps[i]) { + Mismatch = true; + break; + } + if (!Mismatch) + return GEPI; + } + } + return 0; + } + + // Handle add with a constant RHS. + if (Inst->getOpcode() == Instruction::Add && + isa(Inst->getOperand(1))) { + // PHI translate the LHS. + Constant *RHS = cast(Inst->getOperand(1)); + bool isNSW = cast(Inst)->hasNoSignedWrap(); + bool isNUW = cast(Inst)->hasNoUnsignedWrap(); + + Value *LHS = PHITranslateSubExpr(Inst->getOperand(0), CurBB, PredBB, DT); + if (LHS == 0) return 0; + + // If the PHI translated LHS is an add of a constant, fold the immediates. + if (BinaryOperator *BOp = dyn_cast(LHS)) + if (BOp->getOpcode() == Instruction::Add) + if (ConstantInt *CI = dyn_cast(BOp->getOperand(1))) { + LHS = BOp->getOperand(0); + RHS = ConstantExpr::getAdd(RHS, CI); + isNSW = isNUW = false; + + // If the old 'LHS' was an input, add the new 'LHS' as an input. + if (std::count(InstInputs.begin(), InstInputs.end(), BOp)) { + RemoveInstInputs(BOp, InstInputs); + AddAsInput(LHS); + } + } + + // See if the add simplifies away. + if (Value *Res = SimplifyAddInst(LHS, RHS, isNSW, isNUW, TD, DT)) { + // If we simplified the operands, the LHS is no longer an input, but Res + // is. + RemoveInstInputs(LHS, InstInputs); + return AddAsInput(Res); + } + + // If we didn't modify the add, just return it. + if (LHS == Inst->getOperand(0) && RHS == Inst->getOperand(1)) + return Inst; + + // Otherwise, see if we have this add available somewhere. + for (Value::use_iterator UI = LHS->use_begin(), E = LHS->use_end(); + UI != E; ++UI) { + if (BinaryOperator *BO = dyn_cast(*UI)) + if (BO->getOpcode() == Instruction::Add && + BO->getOperand(0) == LHS && BO->getOperand(1) == RHS && + BO->getParent()->getParent() == CurBB->getParent() && + (!DT || DT->dominates(BO->getParent(), PredBB))) + return BO; + } + + return 0; + } + + // Otherwise, we failed. + return 0; +} + + +/// PHITranslateValue - PHI translate the current address up the CFG from +/// CurBB to Pred, updating our state to reflect any needed changes. If the +/// dominator tree DT is non-null, the translated value must dominate +/// PredBB. This returns true on failure and sets Addr to null. +bool PHITransAddr::PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT) { + assert(Verify() && "Invalid PHITransAddr!"); + Addr = PHITranslateSubExpr(Addr, CurBB, PredBB, DT); + assert(Verify() && "Invalid PHITransAddr!"); + + if (DT) { + // Make sure the value is live in the predecessor. + if (Instruction *Inst = dyn_cast_or_null(Addr)) + if (!DT->dominates(Inst->getParent(), PredBB)) + Addr = 0; + } + + return Addr == 0; +} + +/// PHITranslateWithInsertion - PHI translate this value into the specified +/// predecessor block, inserting a computation of the value if it is +/// unavailable. +/// +/// All newly created instructions are added to the NewInsts list. This +/// returns null on failure. +/// +Value *PHITransAddr:: +PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree &DT, + SmallVectorImpl &NewInsts) { + unsigned NISize = NewInsts.size(); + + // Attempt to PHI translate with insertion. + Addr = InsertPHITranslatedSubExpr(Addr, CurBB, PredBB, DT, NewInsts); + + // If successful, return the new value. + if (Addr) return Addr; + + // If not, destroy any intermediate instructions inserted. + while (NewInsts.size() != NISize) + NewInsts.pop_back_val()->eraseFromParent(); + return 0; +} + + +/// InsertPHITranslatedPointer - Insert a computation of the PHI translated +/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB +/// block. All newly created instructions are added to the NewInsts list. +/// This returns null on failure. +/// +Value *PHITransAddr:: +InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, + BasicBlock *PredBB, const DominatorTree &DT, + SmallVectorImpl &NewInsts) { + // See if we have a version of this value already available and dominating + // PredBB. If so, there is no need to insert a new instance of it. + PHITransAddr Tmp(InVal, TD); + if (!Tmp.PHITranslateValue(CurBB, PredBB, &DT)) + return Tmp.getAddr(); + + // If we don't have an available version of this value, it must be an + // instruction. + Instruction *Inst = cast(InVal); + + // Handle cast of PHI translatable value. + if (CastInst *Cast = dyn_cast(Inst)) { + if (!Cast->isSafeToSpeculativelyExecute()) return 0; + Value *OpVal = InsertPHITranslatedSubExpr(Cast->getOperand(0), + CurBB, PredBB, DT, NewInsts); + if (OpVal == 0) return 0; + + // Otherwise insert a cast at the end of PredBB. + CastInst *New = CastInst::Create(Cast->getOpcode(), + OpVal, InVal->getType(), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); + NewInsts.push_back(New); + return New; + } + + // Handle getelementptr with at least one PHI operand. + if (GetElementPtrInst *GEP = dyn_cast(Inst)) { + SmallVector GEPOps; + BasicBlock *CurBB = GEP->getParent(); + for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { + Value *OpVal = InsertPHITranslatedSubExpr(GEP->getOperand(i), + CurBB, PredBB, DT, NewInsts); + if (OpVal == 0) return 0; + GEPOps.push_back(OpVal); + } + + GetElementPtrInst *Result = + GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); + Result->setIsInBounds(GEP->isInBounds()); + NewInsts.push_back(Result); + return Result; + } + +#if 0 + // FIXME: This code works, but it is unclear that we actually want to insert + // a big chain of computation in order to make a value available in a block. + // This needs to be evaluated carefully to consider its cost trade offs. + + // Handle add with a constant RHS. + if (Inst->getOpcode() == Instruction::Add && + isa(Inst->getOperand(1))) { + // PHI translate the LHS. + Value *OpVal = InsertPHITranslatedSubExpr(Inst->getOperand(0), + CurBB, PredBB, DT, NewInsts); + if (OpVal == 0) return 0; + + BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1), + InVal->getName()+".phi.trans.insert", + PredBB->getTerminator()); + Res->setHasNoSignedWrap(cast(Inst)->hasNoSignedWrap()); + Res->setHasNoUnsignedWrap(cast(Inst)->hasNoUnsignedWrap()); + NewInsts.push_back(Res); + return Res; + } +#endif + + return 0; +} diff --git a/final/lib/Analysis/PathNumbering.cpp b/final/lib/Analysis/PathNumbering.cpp new file mode 100644 index 00000000000..5d3f6bbc7b6 --- /dev/null +++ b/final/lib/Analysis/PathNumbering.cpp @@ -0,0 +1,525 @@ +//===- PathNumbering.cpp --------------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Ball-Larus path numbers uniquely identify paths through a directed acyclic +// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony +// edges to obtain a DAG, and thus the unique path numbers [Ball96]. +// +// The purpose of this analysis is to enumerate the edges in a CFG in order +// to obtain paths from path numbers in a convenient manner. As described in +// [Ball96] edges can be enumerated such that given a path number by following +// the CFG and updating the path number, the path is obtained. +// +// [Ball96] +// T. Ball and J. R. Larus. "Efficient Path Profiling." +// International Symposium on Microarchitecture, pages 46-57, 1996. +// http://portal.acm.org/citation.cfm?id=243857 +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "ball-larus-numbering" + +#include "llvm/Analysis/PathNumbering.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InstrTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/TypeBuilder.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +// Are we enabling early termination +static cl::opt ProcessEarlyTermination( + "path-profile-early-termination", cl::Hidden, + cl::desc("In path profiling, insert extra instrumentation to account for " + "unexpected function termination.")); + +// Returns the basic block for the BallLarusNode +BasicBlock* BallLarusNode::getBlock() { + return(_basicBlock); +} + +// Returns the number of paths to the exit starting at the node. +unsigned BallLarusNode::getNumberPaths() { + return(_numberPaths); +} + +// Sets the number of paths to the exit starting at the node. +void BallLarusNode::setNumberPaths(unsigned numberPaths) { + _numberPaths = numberPaths; +} + +// Gets the NodeColor used in graph algorithms. +BallLarusNode::NodeColor BallLarusNode::getColor() { + return(_color); +} + +// Sets the NodeColor used in graph algorithms. +void BallLarusNode::setColor(BallLarusNode::NodeColor color) { + _color = color; +} + +// Returns an iterator over predecessor edges. Includes phony and +// backedges. +BLEdgeIterator BallLarusNode::predBegin() { + return(_predEdges.begin()); +} + +// Returns the end sentinel for the predecessor iterator. +BLEdgeIterator BallLarusNode::predEnd() { + return(_predEdges.end()); +} + +// Returns the number of predecessor edges. Includes phony and +// backedges. +unsigned BallLarusNode::getNumberPredEdges() { + return(_predEdges.size()); +} + +// Returns an iterator over successor edges. Includes phony and +// backedges. +BLEdgeIterator BallLarusNode::succBegin() { + return(_succEdges.begin()); +} + +// Returns the end sentinel for the successor iterator. +BLEdgeIterator BallLarusNode::succEnd() { + return(_succEdges.end()); +} + +// Returns the number of successor edges. Includes phony and +// backedges. +unsigned BallLarusNode::getNumberSuccEdges() { + return(_succEdges.size()); +} + +// Add an edge to the predecessor list. +void BallLarusNode::addPredEdge(BallLarusEdge* edge) { + _predEdges.push_back(edge); +} + +// Remove an edge from the predecessor list. +void BallLarusNode::removePredEdge(BallLarusEdge* edge) { + removeEdge(_predEdges, edge); +} + +// Add an edge to the successor list. +void BallLarusNode::addSuccEdge(BallLarusEdge* edge) { + _succEdges.push_back(edge); +} + +// Remove an edge from the successor list. +void BallLarusNode::removeSuccEdge(BallLarusEdge* edge) { + removeEdge(_succEdges, edge); +} + +// Returns the name of the BasicBlock being represented. If BasicBlock +// is null then returns "". If BasicBlock has no name, then +// "" is returned. Intended for use with debug output. +std::string BallLarusNode::getName() { + std::stringstream name; + + if(getBlock() != NULL) { + if(getBlock()->hasName()) { + std::string tempName(getBlock()->getName()); + name << tempName.c_str() << " (" << _uid << ")"; + } else + name << " (" << _uid << ")"; + } else + name << " (" << _uid << ")"; + + return name.str(); +} + +// Removes an edge from an edgeVector. Used by removePredEdge and +// removeSuccEdge. +void BallLarusNode::removeEdge(BLEdgeVector& v, BallLarusEdge* e) { + // TODO: Avoid linear scan by using a set instead + for(BLEdgeIterator i = v.begin(), + end = v.end(); + i != end; + ++i) { + if((*i) == e) { + v.erase(i); + break; + } + } +} + +// Returns the source node of this edge. +BallLarusNode* BallLarusEdge::getSource() const { + return(_source); +} + +// Returns the target node of this edge. +BallLarusNode* BallLarusEdge::getTarget() const { + return(_target); +} + +// Sets the type of the edge. +BallLarusEdge::EdgeType BallLarusEdge::getType() const { + return _edgeType; +} + +// Gets the type of the edge. +void BallLarusEdge::setType(EdgeType type) { + _edgeType = type; +} + +// Returns the weight of this edge. Used to decode path numbers to sequences +// of basic blocks. +unsigned BallLarusEdge::getWeight() { + return(_weight); +} + +// Sets the weight of the edge. Used during path numbering. +void BallLarusEdge::setWeight(unsigned weight) { + _weight = weight; +} + +// Gets the phony edge originating at the root. +BallLarusEdge* BallLarusEdge::getPhonyRoot() { + return _phonyRoot; +} + +// Sets the phony edge originating at the root. +void BallLarusEdge::setPhonyRoot(BallLarusEdge* phonyRoot) { + _phonyRoot = phonyRoot; +} + +// Gets the phony edge terminating at the exit. +BallLarusEdge* BallLarusEdge::getPhonyExit() { + return _phonyExit; +} + +// Sets the phony edge terminating at the exit. +void BallLarusEdge::setPhonyExit(BallLarusEdge* phonyExit) { + _phonyExit = phonyExit; +} + +// Gets the associated real edge if this is a phony edge. +BallLarusEdge* BallLarusEdge::getRealEdge() { + return _realEdge; +} + +// Sets the associated real edge if this is a phony edge. +void BallLarusEdge::setRealEdge(BallLarusEdge* realEdge) { + _realEdge = realEdge; +} + +// Returns the duplicate number of the edge. +unsigned BallLarusEdge::getDuplicateNumber() { + return(_duplicateNumber); +} + +// Initialization that requires virtual functions which are not fully +// functional in the constructor. +void BallLarusDag::init() { + BLBlockNodeMap inDag; + std::stack dfsStack; + + _root = addNode(&(_function.getEntryBlock())); + _exit = addNode(NULL); + + // start search from root + dfsStack.push(getRoot()); + + // dfs to add each bb into the dag + while(dfsStack.size()) + buildNode(inDag, dfsStack); + + // put in the final edge + addEdge(getExit(),getRoot(),0); +} + +// Frees all memory associated with the DAG. +BallLarusDag::~BallLarusDag() { + for(BLEdgeIterator edge = _edges.begin(), end = _edges.end(); edge != end; + ++edge) + delete (*edge); + + for(BLNodeIterator node = _nodes.begin(), end = _nodes.end(); node != end; + ++node) + delete (*node); +} + +// Calculate the path numbers by assigning edge increments as prescribed +// in Ball-Larus path profiling. +void BallLarusDag::calculatePathNumbers() { + BallLarusNode* node; + std::queue bfsQueue; + bfsQueue.push(getExit()); + + while(bfsQueue.size() > 0) { + node = bfsQueue.front(); + + DEBUG(dbgs() << "calculatePathNumbers on " << node->getName() << "\n"); + + bfsQueue.pop(); + unsigned prevPathNumber = node->getNumberPaths(); + calculatePathNumbersFrom(node); + + // Check for DAG splitting + if( node->getNumberPaths() > 100000000 && node != getRoot() ) { + // Add new phony edge from the split-node to the DAG's exit + BallLarusEdge* exitEdge = addEdge(node, getExit(), 0); + exitEdge->setType(BallLarusEdge::SPLITEDGE_PHONY); + + // Counters to handle the possibilty of a multi-graph + BasicBlock* oldTarget = 0; + unsigned duplicateNumber = 0; + + // Iterate through each successor edge, adding phony edges + for( BLEdgeIterator succ = node->succBegin(), end = node->succEnd(); + succ != end; oldTarget = (*succ)->getTarget()->getBlock(), succ++ ) { + + if( (*succ)->getType() == BallLarusEdge::NORMAL ) { + // is this edge a duplicate? + if( oldTarget != (*succ)->getTarget()->getBlock() ) + duplicateNumber = 0; + + // create the new phony edge: root -> succ + BallLarusEdge* rootEdge = + addEdge(getRoot(), (*succ)->getTarget(), duplicateNumber++); + rootEdge->setType(BallLarusEdge::SPLITEDGE_PHONY); + rootEdge->setRealEdge(*succ); + + // split on this edge and reference it's exit/root phony edges + (*succ)->setType(BallLarusEdge::SPLITEDGE); + (*succ)->setPhonyRoot(rootEdge); + (*succ)->setPhonyExit(exitEdge); + (*succ)->setWeight(0); + } + } + + calculatePathNumbersFrom(node); + } + + DEBUG(dbgs() << "prev, new number paths " << prevPathNumber << ", " + << node->getNumberPaths() << ".\n"); + + if(prevPathNumber == 0 && node->getNumberPaths() != 0) { + DEBUG(dbgs() << "node ready : " << node->getName() << "\n"); + for(BLEdgeIterator pred = node->predBegin(), end = node->predEnd(); + pred != end; pred++) { + if( (*pred)->getType() == BallLarusEdge::BACKEDGE || + (*pred)->getType() == BallLarusEdge::SPLITEDGE ) + continue; + + BallLarusNode* nextNode = (*pred)->getSource(); + // not yet visited? + if(nextNode->getNumberPaths() == 0) + bfsQueue.push(nextNode); + } + } + } + + DEBUG(dbgs() << "\tNumber of paths: " << getRoot()->getNumberPaths() << "\n"); +} + +// Returns the number of paths for the Dag. +unsigned BallLarusDag::getNumberOfPaths() { + return(getRoot()->getNumberPaths()); +} + +// Returns the root (i.e. entry) node for the DAG. +BallLarusNode* BallLarusDag::getRoot() { + return _root; +} + +// Returns the exit node for the DAG. +BallLarusNode* BallLarusDag::getExit() { + return _exit; +} + +// Returns the function for the DAG. +Function& BallLarusDag::getFunction() { + return(_function); +} + +// Clears the node colors. +void BallLarusDag::clearColors(BallLarusNode::NodeColor color) { + for (BLNodeIterator nodeIt = _nodes.begin(); nodeIt != _nodes.end(); nodeIt++) + (*nodeIt)->setColor(color); +} + +// Processes one node and its imediate edges for building the DAG. +void BallLarusDag::buildNode(BLBlockNodeMap& inDag, BLNodeStack& dfsStack) { + BallLarusNode* currentNode = dfsStack.top(); + BasicBlock* currentBlock = currentNode->getBlock(); + + if(currentNode->getColor() != BallLarusNode::WHITE) { + // we have already visited this node + dfsStack.pop(); + currentNode->setColor(BallLarusNode::BLACK); + } else { + // are there any external procedure calls? + if( ProcessEarlyTermination ) { + for( BasicBlock::iterator bbCurrent = currentNode->getBlock()->begin(), + bbEnd = currentNode->getBlock()->end(); bbCurrent != bbEnd; + bbCurrent++ ) { + Instruction& instr = *bbCurrent; + if( instr.getOpcode() == Instruction::Call ) { + BallLarusEdge* callEdge = addEdge(currentNode, getExit(), 0); + callEdge->setType(BallLarusEdge::CALLEDGE_PHONY); + break; + } + } + } + + TerminatorInst* terminator = currentNode->getBlock()->getTerminator(); + if(isa(terminator) || isa(terminator) + || isa(terminator)) + addEdge(currentNode, getExit(),0); + + currentNode->setColor(BallLarusNode::GRAY); + inDag[currentBlock] = currentNode; + + BasicBlock* oldSuccessor = 0; + unsigned duplicateNumber = 0; + + // iterate through this node's successors + for(succ_iterator successor = succ_begin(currentBlock), + succEnd = succ_end(currentBlock); successor != succEnd; + oldSuccessor = *successor, ++successor ) { + BasicBlock* succBB = *successor; + + // is this edge a duplicate? + if (oldSuccessor == succBB) + duplicateNumber++; + else + duplicateNumber = 0; + + buildEdge(inDag, dfsStack, currentNode, succBB, duplicateNumber); + } + } +} + +// Process an edge in the CFG for DAG building. +void BallLarusDag::buildEdge(BLBlockNodeMap& inDag, std::stack& + dfsStack, BallLarusNode* currentNode, + BasicBlock* succBB, unsigned duplicateCount) { + BallLarusNode* succNode = inDag[succBB]; + + if(succNode && succNode->getColor() == BallLarusNode::BLACK) { + // visited node and forward edge + addEdge(currentNode, succNode, duplicateCount); + } else if(succNode && succNode->getColor() == BallLarusNode::GRAY) { + // visited node and back edge + DEBUG(dbgs() << "Backedge detected.\n"); + addBackedge(currentNode, succNode, duplicateCount); + } else { + BallLarusNode* childNode; + // not visited node and forward edge + if(succNode) // an unvisited node that is child of a gray node + childNode = succNode; + else { // an unvisited node that is a child of a an unvisted node + childNode = addNode(succBB); + inDag[succBB] = childNode; + } + addEdge(currentNode, childNode, duplicateCount); + dfsStack.push(childNode); + } +} + +// The weight on each edge is the increment required along any path that +// contains that edge. +void BallLarusDag::calculatePathNumbersFrom(BallLarusNode* node) { + if(node == getExit()) + // The Exit node must be base case + node->setNumberPaths(1); + else { + unsigned sumPaths = 0; + BallLarusNode* succNode; + + for(BLEdgeIterator succ = node->succBegin(), end = node->succEnd(); + succ != end; succ++) { + if( (*succ)->getType() == BallLarusEdge::BACKEDGE || + (*succ)->getType() == BallLarusEdge::SPLITEDGE ) + continue; + + (*succ)->setWeight(sumPaths); + succNode = (*succ)->getTarget(); + + if( !succNode->getNumberPaths() ) + return; + sumPaths += succNode->getNumberPaths(); + } + + node->setNumberPaths(sumPaths); + } +} + +// Allows subclasses to determine which type of Node is created. +// Override this method to produce subclasses of BallLarusNode if +// necessary. The destructor of BallLarusDag will call free on each +// pointer created. +BallLarusNode* BallLarusDag::createNode(BasicBlock* BB) { + return( new BallLarusNode(BB) ); +} + +// Allows subclasses to determine which type of Edge is created. +// Override this method to produce subclasses of BallLarusEdge if +// necessary. The destructor of BallLarusDag will call free on each +// pointer created. +BallLarusEdge* BallLarusDag::createEdge(BallLarusNode* source, + BallLarusNode* target, + unsigned duplicateCount) { + return( new BallLarusEdge(source, target, duplicateCount) ); +} + +// Proxy to node's constructor. Updates the DAG state. +BallLarusNode* BallLarusDag::addNode(BasicBlock* BB) { + BallLarusNode* newNode = createNode(BB); + _nodes.push_back(newNode); + return( newNode ); +} + +// Proxy to edge's constructor. Updates the DAG state. +BallLarusEdge* BallLarusDag::addEdge(BallLarusNode* source, + BallLarusNode* target, + unsigned duplicateCount) { + BallLarusEdge* newEdge = createEdge(source, target, duplicateCount); + _edges.push_back(newEdge); + source->addSuccEdge(newEdge); + target->addPredEdge(newEdge); + return(newEdge); +} + +// Adds a backedge with its phony edges. Updates the DAG state. +void BallLarusDag::addBackedge(BallLarusNode* source, BallLarusNode* target, + unsigned duplicateCount) { + BallLarusEdge* childEdge = addEdge(source, target, duplicateCount); + childEdge->setType(BallLarusEdge::BACKEDGE); + + childEdge->setPhonyRoot(addEdge(getRoot(), target,0)); + childEdge->setPhonyExit(addEdge(source, getExit(),0)); + + childEdge->getPhonyRoot()->setRealEdge(childEdge); + childEdge->getPhonyRoot()->setType(BallLarusEdge::BACKEDGE_PHONY); + + childEdge->getPhonyExit()->setRealEdge(childEdge); + childEdge->getPhonyExit()->setType(BallLarusEdge::BACKEDGE_PHONY); + _backEdges.push_back(childEdge); +} diff --git a/final/lib/Analysis/PathProfileInfo.cpp b/final/lib/Analysis/PathProfileInfo.cpp new file mode 100644 index 00000000000..b361d3f4fa9 --- /dev/null +++ b/final/lib/Analysis/PathProfileInfo.cpp @@ -0,0 +1,434 @@ +//===- PathProfileInfo.cpp ------------------------------------*- 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 interface used by optimizers to load path profiles, +// and provides a loader pass which reads a path profile file. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "path-profile-info" + +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include "llvm/Analysis/PathProfileInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; + +// command line option for loading path profiles +static cl::opt +PathProfileInfoFilename("path-profile-loader-file", cl::init("llvmprof.out"), + cl::value_desc("filename"), + cl::desc("Path profile file loaded by -path-profile-loader"), cl::Hidden); + +namespace { + class PathProfileLoaderPass : public ModulePass, public PathProfileInfo { + public: + PathProfileLoaderPass() : ModulePass(ID) { } + ~PathProfileLoaderPass(); + + // this pass doesn't change anything (only loads information) + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + // the full name of the loader pass + virtual const char* getPassName() const { + return "Path Profiling Information Loader"; + } + + // required since this pass implements multiple inheritance + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &PathProfileInfo::ID) + return (PathProfileInfo*)this; + return this; + } + + // entry point to run the pass + bool runOnModule(Module &M); + + // pass identification + static char ID; + + private: + // make a reference table to refer to function by number + void buildFunctionRefs(Module &M); + + // process argument info of a program from the input file + void handleArgumentInfo(); + + // process path number information from the input file + void handlePathInfo(); + + // array of references to the functions in the module + std::vector _functions; + + // path profile file handle + FILE* _file; + + // path profile file name + std::string _filename; + }; +} + +// register PathLoader +char PathProfileLoaderPass::ID = 0; + +INITIALIZE_ANALYSIS_GROUP(PathProfileInfo, "Path Profile Information", + NoPathProfileInfo) +INITIALIZE_AG_PASS(PathProfileLoaderPass, PathProfileInfo, + "path-profile-loader", + "Load path profile information from file", + false, true, false) + +char &llvm::PathProfileLoaderPassID = PathProfileLoaderPass::ID; + +// link PathLoader as a pass, and make it available as an optimisation +ModulePass *llvm::createPathProfileLoaderPass() { + return new PathProfileLoaderPass; +} + +// ---------------------------------------------------------------------------- +// PathEdge implementation +// +ProfilePathEdge::ProfilePathEdge (BasicBlock* source, BasicBlock* target, + unsigned duplicateNumber) + : _source(source), _target(target), _duplicateNumber(duplicateNumber) {} + +// ---------------------------------------------------------------------------- +// Path implementation +// + +ProfilePath::ProfilePath (unsigned int number, unsigned int count, + double countStdDev, PathProfileInfo* ppi) + : _number(number) , _count(count), _countStdDev(countStdDev), _ppi(ppi) {} + +double ProfilePath::getFrequency() const { + return 100 * double(_count) / + double(_ppi->_functionPathCounts[_ppi->_currentFunction]); +} + +static BallLarusEdge* getNextEdge (BallLarusNode* node, + unsigned int pathNumber) { + BallLarusEdge* best = 0; + + for( BLEdgeIterator next = node->succBegin(), + end = node->succEnd(); next != end; next++ ) { + if( (*next)->getType() != BallLarusEdge::BACKEDGE && // no backedges + (*next)->getType() != BallLarusEdge::SPLITEDGE && // no split edges + (*next)->getWeight() <= pathNumber && // weight must be <= pathNumber + (!best || (best->getWeight() < (*next)->getWeight())) ) // best one? + best = *next; + } + + return best; +} + +ProfilePathEdgeVector* ProfilePath::getPathEdges() const { + BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); + unsigned int increment = _number; + ProfilePathEdgeVector* pev = new ProfilePathEdgeVector; + + while (currentNode != _ppi->_currentDag->getExit()) { + BallLarusEdge* next = getNextEdge(currentNode, increment); + + increment -= next->getWeight(); + + if( next->getType() != BallLarusEdge::BACKEDGE_PHONY && + next->getType() != BallLarusEdge::SPLITEDGE_PHONY && + next->getTarget() != _ppi->_currentDag->getExit() ) + pev->push_back(ProfilePathEdge( + next->getSource()->getBlock(), + next->getTarget()->getBlock(), + next->getDuplicateNumber())); + + if( next->getType() == BallLarusEdge::BACKEDGE_PHONY && + next->getTarget() == _ppi->_currentDag->getExit() ) + pev->push_back(ProfilePathEdge( + next->getRealEdge()->getSource()->getBlock(), + next->getRealEdge()->getTarget()->getBlock(), + next->getDuplicateNumber())); + + if( next->getType() == BallLarusEdge::SPLITEDGE_PHONY && + next->getSource() == _ppi->_currentDag->getRoot() ) + pev->push_back(ProfilePathEdge( + next->getRealEdge()->getSource()->getBlock(), + next->getRealEdge()->getTarget()->getBlock(), + next->getDuplicateNumber())); + + // set the new node + currentNode = next->getTarget(); + } + + return pev; +} + +ProfilePathBlockVector* ProfilePath::getPathBlocks() const { + BallLarusNode* currentNode = _ppi->_currentDag->getRoot (); + unsigned int increment = _number; + ProfilePathBlockVector* pbv = new ProfilePathBlockVector; + + while (currentNode != _ppi->_currentDag->getExit()) { + BallLarusEdge* next = getNextEdge(currentNode, increment); + increment -= next->getWeight(); + + // add block to the block list if it is a real edge + if( next->getType() == BallLarusEdge::NORMAL) + pbv->push_back (currentNode->getBlock()); + // make the back edge the last edge since we are at the end + else if( next->getTarget() == _ppi->_currentDag->getExit() ) { + pbv->push_back (currentNode->getBlock()); + pbv->push_back (next->getRealEdge()->getTarget()->getBlock()); + } + + // set the new node + currentNode = next->getTarget(); + } + + return pbv; +} + +BasicBlock* ProfilePath::getFirstBlockInPath() const { + BallLarusNode* root = _ppi->_currentDag->getRoot(); + BallLarusEdge* edge = getNextEdge(root, _number); + + if( edge && (edge->getType() == BallLarusEdge::BACKEDGE_PHONY || + edge->getType() == BallLarusEdge::SPLITEDGE_PHONY) ) + return edge->getTarget()->getBlock(); + + return root->getBlock(); +} + +// ---------------------------------------------------------------------------- +// PathProfileInfo implementation +// + +// Pass identification +char llvm::PathProfileInfo::ID = 0; + +PathProfileInfo::PathProfileInfo () : _currentDag(0) , _currentFunction(0) { +} + +PathProfileInfo::~PathProfileInfo() { + if (_currentDag) + delete _currentDag; +} + +// set the function for which paths are currently begin processed +void PathProfileInfo::setCurrentFunction(Function* F) { + // Make sure it exists + if (!F) return; + + if (_currentDag) + delete _currentDag; + + _currentFunction = F; + _currentDag = new BallLarusDag(*F); + _currentDag->init(); + _currentDag->calculatePathNumbers(); +} + +// get the function for which paths are currently being processed +Function* PathProfileInfo::getCurrentFunction() const { + return _currentFunction; +} + +// get the entry block of the function +BasicBlock* PathProfileInfo::getCurrentFunctionEntry() { + return _currentDag->getRoot()->getBlock(); +} + +// return the path based on its number +ProfilePath* PathProfileInfo::getPath(unsigned int number) { + return _functionPaths[_currentFunction][number]; +} + +// return the number of paths which a function may potentially execute +unsigned int PathProfileInfo::getPotentialPathCount() { + return _currentDag ? _currentDag->getNumberOfPaths() : 0; +} + +// return an iterator for the beginning of a functions executed paths +ProfilePathIterator PathProfileInfo::pathBegin() { + return _functionPaths[_currentFunction].begin(); +} + +// return an iterator for the end of a functions executed paths +ProfilePathIterator PathProfileInfo::pathEnd() { + return _functionPaths[_currentFunction].end(); +} + +// returns the total number of paths run in the function +unsigned int PathProfileInfo::pathsRun() { + return _currentFunction ? _functionPaths[_currentFunction].size() : 0; +} + +// ---------------------------------------------------------------------------- +// PathLoader implementation +// + +// remove all generated paths +PathProfileLoaderPass::~PathProfileLoaderPass() { + for( FunctionPathIterator funcNext = _functionPaths.begin(), + funcEnd = _functionPaths.end(); funcNext != funcEnd; funcNext++) + for( ProfilePathIterator pathNext = funcNext->second.begin(), + pathEnd = funcNext->second.end(); pathNext != pathEnd; pathNext++) + delete pathNext->second; +} + +// entry point of the pass; this loads and parses a file +bool PathProfileLoaderPass::runOnModule(Module &M) { + // get the filename and setup the module's function references + _filename = PathProfileInfoFilename; + buildFunctionRefs (M); + + if (!(_file = fopen(_filename.c_str(), "rb"))) { + errs () << "error: input '" << _filename << "' file does not exist.\n"; + return false; + } + + ProfilingType profType; + + while( fread(&profType, sizeof(ProfilingType), 1, _file) ) { + switch (profType) { + case ArgumentInfo: + handleArgumentInfo (); + break; + case PathInfo: + handlePathInfo (); + break; + default: + errs () << "error: bad path profiling file syntax, " << profType << "\n"; + fclose (_file); + return false; + } + } + + fclose (_file); + + return true; +} + +// create a reference table for functions defined in the path profile file +void PathProfileLoaderPass::buildFunctionRefs (Module &M) { + _functions.push_back(0); // make the 0 index a null pointer + + for (Module::iterator F = M.begin(), E = M.end(); F != E; F++) { + if (F->isDeclaration()) + continue; + _functions.push_back(F); + } +} + +// handle command like argument infor in the output file +void PathProfileLoaderPass::handleArgumentInfo() { + // get the argument list's length + unsigned savedArgsLength; + if( fread(&savedArgsLength, sizeof(unsigned), 1, _file) != 1 ) { + errs() << "warning: argument info header/data mismatch\n"; + return; + } + + // allocate a buffer, and get the arguments + char* args = new char[savedArgsLength+1]; + if( fread(args, 1, savedArgsLength, _file) != savedArgsLength ) + errs() << "warning: argument info header/data mismatch\n"; + + args[savedArgsLength] = '\0'; + argList = std::string(args); + delete [] args; // cleanup dynamic string + + // byte alignment + if (savedArgsLength & 3) + fseek(_file, 4-(savedArgsLength&3), SEEK_CUR); +} + +// Handle path profile information in the output file +void PathProfileLoaderPass::handlePathInfo () { + // get the number of functions in this profile + unsigned functionCount; + if( fread(&functionCount, sizeof(functionCount), 1, _file) != 1 ) { + errs() << "warning: path info header/data mismatch\n"; + return; + } + + // gather path information for each function + for (unsigned i = 0; i < functionCount; i++) { + PathProfileHeader pathHeader; + if( fread(&pathHeader, sizeof(pathHeader), 1, _file) != 1 ) { + errs() << "warning: bad header for path function info\n"; + break; + } + + Function* f = _functions[pathHeader.fnNumber]; + + // dynamically allocate a table to store path numbers + PathProfileTableEntry* pathTable = + new PathProfileTableEntry[pathHeader.numEntries]; + + if( fread(pathTable, sizeof(PathProfileTableEntry), + pathHeader.numEntries, _file) != pathHeader.numEntries) { + delete [] pathTable; + errs() << "warning: path function info header/data mismatch\n"; + return; + } + + // Build a new path for the current function + unsigned int totalPaths = 0; + for (unsigned int j = 0; j < pathHeader.numEntries; j++) { + totalPaths += pathTable[j].pathCounter; + _functionPaths[f][pathTable[j].pathNumber] + = new ProfilePath(pathTable[j].pathNumber, pathTable[j].pathCounter, + 0, this); + } + + _functionPathCounts[f] = totalPaths; + + delete [] pathTable; + } +} + +//===----------------------------------------------------------------------===// +// NoProfile PathProfileInfo implementation +// + +namespace { + struct NoPathProfileInfo : public ImmutablePass, public PathProfileInfo { + static char ID; // Class identification, replacement for typeinfo + NoPathProfileInfo() : ImmutablePass(ID) { + initializeNoPathProfileInfoPass(*PassRegistry::getPassRegistry()); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &PathProfileInfo::ID) + return (PathProfileInfo*)this; + return this; + } + + virtual const char *getPassName() const { + return "NoPathProfileInfo"; + } + }; +} // End of anonymous namespace + +char NoPathProfileInfo::ID = 0; +// Register this pass... +INITIALIZE_AG_PASS(NoPathProfileInfo, PathProfileInfo, "no-path-profile", + "No Path Profile Information", false, true, true) + +ImmutablePass *llvm::createNoPathProfileInfoPass() { return new NoPathProfileInfo(); } diff --git a/final/lib/Analysis/PathProfileVerifier.cpp b/final/lib/Analysis/PathProfileVerifier.cpp new file mode 100644 index 00000000000..c5497731420 --- /dev/null +++ b/final/lib/Analysis/PathProfileVerifier.cpp @@ -0,0 +1,207 @@ +//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This verifier derives an edge profile file from current path profile +// information +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "path-profile-verifier" + +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include "llvm/Analysis/PathProfileInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +#include + +using namespace llvm; + +namespace { + class PathProfileVerifier : public ModulePass { + private: + bool runOnModule(Module &M); + + public: + static char ID; // Pass identification, replacement for typeid + PathProfileVerifier() : ModulePass(ID) { + initializePathProfileVerifierPass(*PassRegistry::getPassRegistry()); + } + + + virtual const char *getPassName() const { + return "Path Profiler Verifier"; + } + + // The verifier requires the path profile and edge profile. + virtual void getAnalysisUsage(AnalysisUsage& AU) const; + }; +} + +static cl::opt +EdgeProfileFilename("path-profile-verifier-file", + cl::init("edgefrompath.llvmprof.out"), + cl::value_desc("filename"), + cl::desc("Edge profile file generated by -path-profile-verifier"), + cl::Hidden); + +char PathProfileVerifier::ID = 0; +INITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier", + "Compare the path profile derived edge profile against the " + "edge profile.", true, true) + +ModulePass *llvm::createPathProfileVerifierPass() { + return new PathProfileVerifier(); +} + +// The verifier requires the path profile and edge profile. +void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const { + AU.addRequired(); + AU.addPreserved(); +} + +typedef std::map DuplicateToIndexMap; +typedef std::map BlockToDuplicateMap; +typedef std::map NestedBlockToIndexMap; + +// the verifier iterates through each path to gather the total +// number of edge frequencies +bool PathProfileVerifier::runOnModule (Module &M) { + PathProfileInfo& pathProfileInfo = getAnalysis(); + + // setup a data structure to map path edges which index an + // array of edge counters + NestedBlockToIndexMap arrayMap; + unsigned i = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + + arrayMap[0][F->begin()][0] = i++; + + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + + unsigned duplicate = 0; + BasicBlock* prev = 0; + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; + prev = TI->getSuccessor(s), ++s) { + if (prev == TI->getSuccessor(s)) + duplicate++; + else duplicate = 0; + + arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++; + } + } + } + + std::vector edgeArray(i); + + // iterate through each path and increment the edge counters as needed + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + + pathProfileInfo.setCurrentFunction(F); + + DEBUG(dbgs() << "function '" << F->getName() << "' ran " + << pathProfileInfo.pathsRun() + << "/" << pathProfileInfo.getPotentialPathCount() + << " potential paths\n"); + + for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(), + endPath = pathProfileInfo.pathEnd(); + nextPath != endPath; nextPath++ ) { + ProfilePath* currentPath = nextPath->second; + + ProfilePathEdgeVector* pev = currentPath->getPathEdges(); + DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": " + << currentPath->getCount() << "\n"); + // setup the entry edge (normally path profiling doens't care about this) + if (currentPath->getFirstBlockInPath() == &F->getEntryBlock()) + edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]] + += currentPath->getCount(); + + for( ProfilePathEdgeIterator nextEdge = pev->begin(), + endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) { + if (nextEdge != pev->begin()) + DEBUG(dbgs() << " :: "); + + BasicBlock* source = nextEdge->getSource(); + BasicBlock* target = nextEdge->getTarget(); + unsigned duplicateNumber = nextEdge->getDuplicateNumber(); + DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber + << "}--> " << target->getNameStr()); + + // Ensure all the referenced edges exist + // TODO: make this a separate function + if( !arrayMap.count(source) ) { + errs() << " error [" << F->getNameStr() << "()]: source '" + << source->getNameStr() + << "' does not exist in the array map.\n"; + } else if( !arrayMap[source].count(target) ) { + errs() << " error [" << F->getNameStr() << "()]: target '" + << target->getNameStr() + << "' does not exist in the array map.\n"; + } else if( !arrayMap[source][target].count(duplicateNumber) ) { + errs() << " error [" << F->getNameStr() << "()]: edge " + << source->getNameStr() << " -> " << target->getNameStr() + << " duplicate number " << duplicateNumber + << " does not exist in the array map.\n"; + } else { + edgeArray[arrayMap[source][target][duplicateNumber]] + += currentPath->getCount(); + } + } + + DEBUG(errs() << "\n"); + + delete pev; + } + } + + std::string errorInfo; + std::string filename = EdgeProfileFilename; + + // Open a handle to the file + FILE* edgeFile = fopen(filename.c_str(),"wb"); + + if (!edgeFile) { + errs() << "error: unable to open file '" << filename << "' for output.\n"; + return false; + } + + errs() << "Generating edge profile '" << filename << "' ...\n"; + + // write argument info + unsigned type = ArgumentInfo; + unsigned num = pathProfileInfo.argList.size(); + int zeros = 0; + + fwrite(&type,sizeof(unsigned),1,edgeFile); + fwrite(&num,sizeof(unsigned),1,edgeFile); + fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile); + if (num&3) + fwrite(&zeros, 1, 4-(num&3), edgeFile); + + type = EdgeInfo; + num = edgeArray.size(); + fwrite(&type,sizeof(unsigned),1,edgeFile); + fwrite(&num,sizeof(unsigned),1,edgeFile); + + // write each edge to the file + for( std::vector::iterator s = edgeArray.begin(), + e = edgeArray.end(); s != e; s++) + fwrite(&*s, sizeof (unsigned), 1, edgeFile); + + fclose (edgeFile); + + return true; +} diff --git a/final/lib/Analysis/PostDominators.cpp b/final/lib/Analysis/PostDominators.cpp new file mode 100644 index 00000000000..3f0deab9ea8 --- /dev/null +++ b/final/lib/Analysis/PostDominators.cpp @@ -0,0 +1,102 @@ +//===- PostDominators.cpp - Post-Dominator Calculation --------------------===// +// +// 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 post-dominator construction algorithms. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "postdomtree" + +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Instructions.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Analysis/DominatorInternals.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// PostDominatorTree Implementation +//===----------------------------------------------------------------------===// + +char PostDominatorTree::ID = 0; +char PostDominanceFrontier::ID = 0; +INITIALIZE_PASS(PostDominatorTree, "postdomtree", + "Post-Dominator Tree Construction", true, true) + +bool PostDominatorTree::runOnFunction(Function &F) { + DT->recalculate(F); + return false; +} + +PostDominatorTree::~PostDominatorTree() { + delete DT; +} + +void PostDominatorTree::print(raw_ostream &OS, const Module *) const { + DT->print(OS); +} + + +FunctionPass* llvm::createPostDomTree() { + return new PostDominatorTree(); +} + +//===----------------------------------------------------------------------===// +// PostDominanceFrontier Implementation +//===----------------------------------------------------------------------===// + +INITIALIZE_PASS_BEGIN(PostDominanceFrontier, "postdomfrontier", + "Post-Dominance Frontier Construction", true, true) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) +INITIALIZE_PASS_END(PostDominanceFrontier, "postdomfrontier", + "Post-Dominance Frontier Construction", true, true) + +const DominanceFrontier::DomSetType & +PostDominanceFrontier::calculate(const PostDominatorTree &DT, + const DomTreeNode *Node) { + // Loop over CFG successors to calculate DFlocal[Node] + BasicBlock *BB = Node->getBlock(); + DomSetType &S = Frontiers[BB]; // The new set to fill in... + if (getRoots().empty()) return S; + + if (BB) + for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); + SI != SE; ++SI) { + BasicBlock *P = *SI; + // Does Node immediately dominate this predecessor? + DomTreeNode *SINode = DT[P]; + if (SINode && SINode->getIDom() != Node) + S.insert(P); + } + + // At this point, S is DFlocal. Now we union in DFup's of our children... + // Loop through and visit the nodes that Node immediately dominates (Node's + // children in the IDomTree) + // + for (DomTreeNode::const_iterator + NI = Node->begin(), NE = Node->end(); NI != NE; ++NI) { + DomTreeNode *IDominee = *NI; + const DomSetType &ChildDF = calculate(DT, IDominee); + + DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end(); + for (; CDFI != CDFE; ++CDFI) { + if (!DT.properlyDominates(Node, DT[*CDFI])) + S.insert(*CDFI); + } + } + + return S; +} + +FunctionPass* llvm::createPostDomFrontier() { + return new PostDominanceFrontier(); +} diff --git a/final/lib/Analysis/ProfileEstimatorPass.cpp b/final/lib/Analysis/ProfileEstimatorPass.cpp new file mode 100644 index 00000000000..667ee1cc348 --- /dev/null +++ b/final/lib/Analysis/ProfileEstimatorPass.cpp @@ -0,0 +1,426 @@ +//===- ProfileEstimatorPass.cpp - LLVM Pass to estimate profile info ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a concrete implementation of profiling information that +// estimates the profiling information in a very crude and unimaginative way. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-estimator" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +using namespace llvm; + +static cl::opt +LoopWeight( + "profile-estimator-loop-weight", cl::init(10), + cl::value_desc("loop-weight"), + cl::desc("Number of loop executions used for profile-estimator") +); + +namespace { + class ProfileEstimatorPass : public FunctionPass, public ProfileInfo { + double ExecCount; + LoopInfo *LI; + std::set BBToVisit; + std::map LoopExitWeights; + std::map MinimalWeight; + public: + static char ID; // Class identification, replacement for typeinfo + explicit ProfileEstimatorPass(const double execcount = 0) + : FunctionPass(ID), ExecCount(execcount) { + initializeProfileEstimatorPassPass(*PassRegistry::getPassRegistry()); + if (execcount == 0) ExecCount = LoopWeight; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual const char *getPassName() const { + return "Profiling information estimator"; + } + + /// run - Estimate the profile information from the specified file. + virtual bool runOnFunction(Function &F); + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &ProfileInfo::ID) + return (ProfileInfo*)this; + return this; + } + + virtual void recurseBasicBlock(BasicBlock *BB); + + void inline printEdgeWeight(Edge); + }; +} // End of anonymous namespace + +char ProfileEstimatorPass::ID = 0; +INITIALIZE_AG_PASS_BEGIN(ProfileEstimatorPass, ProfileInfo, "profile-estimator", + "Estimate profiling information", false, true, false) +INITIALIZE_PASS_DEPENDENCY(LoopInfo) +INITIALIZE_AG_PASS_END(ProfileEstimatorPass, ProfileInfo, "profile-estimator", + "Estimate profiling information", false, true, false) + +namespace llvm { + char &ProfileEstimatorPassID = ProfileEstimatorPass::ID; + + FunctionPass *createProfileEstimatorPass() { + return new ProfileEstimatorPass(); + } + + /// createProfileEstimatorPass - This function returns a Pass that estimates + /// profiling information using the given loop execution count. + Pass *createProfileEstimatorPass(const unsigned execcount) { + return new ProfileEstimatorPass(execcount); + } +} + +static double ignoreMissing(double w) { + if (w == ProfileInfo::MissingValue) return 0; + return w; +} + +static void inline printEdgeError(ProfileInfo::Edge e, const char *M) { + DEBUG(dbgs() << "-- Edge " << e << " is not calculated, " << M << "\n"); +} + +void inline ProfileEstimatorPass::printEdgeWeight(Edge E) { + DEBUG(dbgs() << "-- Weight of Edge " << E << ":" + << format("%20.20g", getEdgeWeight(E)) << "\n"); +} + +// recurseBasicBlock() - This calculates the ProfileInfo estimation for a +// single block and then recurses into the successors. +// The algorithm preserves the flow condition, meaning that the sum of the +// weight of the incoming edges must be equal the block weight which must in +// turn be equal to the sume of the weights of the outgoing edges. +// Since the flow of an block is deterimined from the current state of the +// flow, once an edge has a flow assigned this flow is never changed again, +// otherwise it would be possible to violate the flow condition in another +// block. +void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) { + + // Break the recursion if this BasicBlock was already visited. + if (BBToVisit.find(BB) == BBToVisit.end()) return; + + // Read the LoopInfo for this block. + bool BBisHeader = LI->isLoopHeader(BB); + Loop* BBLoop = LI->getLoopFor(BB); + + // To get the block weight, read all incoming edges. + double BBWeight = 0; + std::set ProcessedPreds; + for ( pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi ) { + // If this block was not considered already, add weight. + Edge edge = getEdge(*bbi,BB); + double w = getEdgeWeight(edge); + if (ProcessedPreds.insert(*bbi).second) { + BBWeight += ignoreMissing(w); + } + // If this block is a loop header and the predecessor is contained in this + // loop, thus the edge is a backedge, continue and do not check if the + // value is valid. + if (BBisHeader && BBLoop->contains(*bbi)) { + printEdgeError(edge, "but is backedge, continueing"); + continue; + } + // If the edges value is missing (and this is no loop header, and this is + // no backedge) return, this block is currently non estimatable. + if (w == MissingValue) { + printEdgeError(edge, "returning"); + return; + } + } + if (getExecutionCount(BB) != MissingValue) { + BBWeight = getExecutionCount(BB); + } + + // Fetch all necessary information for current block. + SmallVector ExitEdges; + SmallVector Edges; + if (BBLoop) { + BBLoop->getExitEdges(ExitEdges); + } + + // If this is a loop header, consider the following: + // Exactly the flow that is entering this block, must exit this block too. So + // do the following: + // *) get all the exit edges, read the flow that is already leaving this + // loop, remember the edges that do not have any flow on them right now. + // (The edges that have already flow on them are most likely exiting edges of + // other loops, do not touch those flows because the previously caclulated + // loopheaders would not be exact anymore.) + // *) In case there is not a single exiting edge left, create one at the loop + // latch to prevent the flow from building up in the loop. + // *) Take the flow that is not leaving the loop already and distribute it on + // the remaining exiting edges. + // (This ensures that all flow that enters the loop also leaves it.) + // *) Increase the flow into the loop by increasing the weight of this block. + // There is at least one incoming backedge that will bring us this flow later + // on. (So that the flow condition in this node is valid again.) + if (BBisHeader) { + double incoming = BBWeight; + // Subtract the flow leaving the loop. + std::set ProcessedExits; + for (SmallVector::iterator ei = ExitEdges.begin(), + ee = ExitEdges.end(); ei != ee; ++ei) { + if (ProcessedExits.insert(*ei).second) { + double w = getEdgeWeight(*ei); + if (w == MissingValue) { + Edges.push_back(*ei); + // Check if there is a necessary minimal weight, if yes, subtract it + // from weight. + if (MinimalWeight.find(*ei) != MinimalWeight.end()) { + incoming -= MinimalWeight[*ei]; + DEBUG(dbgs() << "Reserving " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n"); + } + } else { + incoming -= w; + } + } + } + // If no exit edges, create one: + if (Edges.size() == 0) { + BasicBlock *Latch = BBLoop->getLoopLatch(); + if (Latch) { + Edge edge = getEdge(Latch,0); + EdgeInformation[BB->getParent()][edge] = BBWeight; + printEdgeWeight(edge); + edge = getEdge(Latch, BB); + EdgeInformation[BB->getParent()][edge] = BBWeight * ExecCount; + printEdgeWeight(edge); + } + } + + // Distribute remaining weight to the exting edges. To prevent fractions + // from building up and provoking precision problems the weight which is to + // be distributed is split and the rounded, the last edge gets a somewhat + // bigger value, but we are close enough for an estimation. + double fraction = floor(incoming/Edges.size()); + for (SmallVector::iterator ei = Edges.begin(), ee = Edges.end(); + ei != ee; ++ei) { + double w = 0; + if (ei != (ee-1)) { + w = fraction; + incoming -= fraction; + } else { + w = incoming; + } + EdgeInformation[BB->getParent()][*ei] += w; + // Read necessary minimal weight. + if (MinimalWeight.find(*ei) != MinimalWeight.end()) { + EdgeInformation[BB->getParent()][*ei] += MinimalWeight[*ei]; + DEBUG(dbgs() << "Additionally " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n"); + } + printEdgeWeight(*ei); + + // Add minimal weight to paths to all exit edges, this is used to ensure + // that enough flow is reaching this edges. + Path p; + const BasicBlock *Dest = GetPath(BB, (*ei).first, p, GetPathToDest); + while (Dest != BB) { + const BasicBlock *Parent = p.find(Dest)->second; + Edge e = getEdge(Parent, Dest); + if (MinimalWeight.find(e) == MinimalWeight.end()) { + MinimalWeight[e] = 0; + } + MinimalWeight[e] += w; + DEBUG(dbgs() << "Minimal Weight for " << e << ": " << format("%.20g",MinimalWeight[e]) << "\n"); + Dest = Parent; + } + } + // Increase flow into the loop. + BBWeight *= (ExecCount+1); + } + + BlockInformation[BB->getParent()][BB] = BBWeight; + // Up until now we considered only the loop exiting edges, now we have a + // definite block weight and must distribute this onto the outgoing edges. + // Since there may be already flow attached to some of the edges, read this + // flow first and remember the edges that have still now flow attached. + Edges.clear(); + std::set ProcessedSuccs; + + succ_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + // Also check for (BB,0) edges that may already contain some flow. (But only + // in case there are no successors.) + if (bbi == bbe) { + Edge edge = getEdge(BB,0); + EdgeInformation[BB->getParent()][edge] = BBWeight; + printEdgeWeight(edge); + } + for ( ; bbi != bbe; ++bbi ) { + if (ProcessedSuccs.insert(*bbi).second) { + Edge edge = getEdge(BB,*bbi); + double w = getEdgeWeight(edge); + if (w != MissingValue) { + BBWeight -= getEdgeWeight(edge); + } else { + Edges.push_back(edge); + // If minimal weight is necessary, reserve weight by subtracting weight + // from block weight, this is readded later on. + if (MinimalWeight.find(edge) != MinimalWeight.end()) { + BBWeight -= MinimalWeight[edge]; + DEBUG(dbgs() << "Reserving " << format("%.20g",MinimalWeight[edge]) << " at " << edge << "\n"); + } + } + } + } + + double fraction = floor(BBWeight/Edges.size()); + // Finally we know what flow is still not leaving the block, distribute this + // flow onto the empty edges. + for (SmallVector::iterator ei = Edges.begin(), ee = Edges.end(); + ei != ee; ++ei) { + if (ei != (ee-1)) { + EdgeInformation[BB->getParent()][*ei] += fraction; + BBWeight -= fraction; + } else { + EdgeInformation[BB->getParent()][*ei] += BBWeight; + } + // Readd minial necessary weight. + if (MinimalWeight.find(*ei) != MinimalWeight.end()) { + EdgeInformation[BB->getParent()][*ei] += MinimalWeight[*ei]; + DEBUG(dbgs() << "Additionally " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n"); + } + printEdgeWeight(*ei); + } + + // This block is visited, mark this before the recursion. + BBToVisit.erase(BB); + + // Recurse into successors. + for (succ_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } +} + +bool ProfileEstimatorPass::runOnFunction(Function &F) { + if (F.isDeclaration()) return false; + + // Fetch LoopInfo and clear ProfileInfo for this function. + LI = &getAnalysis(); + FunctionInformation.erase(&F); + BlockInformation[&F].clear(); + EdgeInformation[&F].clear(); + BBToVisit.clear(); + + // Mark all blocks as to visit. + for (Function::iterator bi = F.begin(), be = F.end(); bi != be; ++bi) + BBToVisit.insert(bi); + + // Clear Minimal Edges. + MinimalWeight.clear(); + + DEBUG(dbgs() << "Working on function " << F.getNameStr() << "\n"); + + // Since the entry block is the first one and has no predecessors, the edge + // (0,entry) is inserted with the starting weight of 1. + BasicBlock *entry = &F.getEntryBlock(); + BlockInformation[&F][entry] = pow(2.0, 32.0); + Edge edge = getEdge(0,entry); + EdgeInformation[&F][edge] = BlockInformation[&F][entry]; + printEdgeWeight(edge); + + // Since recurseBasicBlock() maybe returns with a block which was not fully + // estimated, use recurseBasicBlock() until everything is calculated. + bool cleanup = false; + recurseBasicBlock(entry); + while (BBToVisit.size() > 0 && !cleanup) { + // Remember number of open blocks, this is later used to check if progress + // was made. + unsigned size = BBToVisit.size(); + + // Try to calculate all blocks in turn. + for (std::set::iterator bi = BBToVisit.begin(), + be = BBToVisit.end(); bi != be; ++bi) { + recurseBasicBlock(*bi); + // If at least one block was finished, break because iterator may be + // invalid. + if (BBToVisit.size() < size) break; + } + + // If there was not a single block resolved, make some assumptions. + if (BBToVisit.size() == size) { + bool found = false; + for (std::set::iterator BBI = BBToVisit.begin(), BBE = BBToVisit.end(); + (BBI != BBE) && (!found); ++BBI) { + BasicBlock *BB = *BBI; + // Try each predecessor if it can be assumend. + for (pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + (bbi != bbe) && (!found); ++bbi) { + Edge e = getEdge(*bbi,BB); + double w = getEdgeWeight(e); + // Check that edge from predecessor is still free. + if (w == MissingValue) { + // Check if there is a circle from this block to predecessor. + Path P; + const BasicBlock *Dest = GetPath(BB, *bbi, P, GetPathToDest); + if (Dest != *bbi) { + // If there is no circle, just set edge weight to 0 + EdgeInformation[&F][e] = 0; + DEBUG(dbgs() << "Assuming edge weight: "); + printEdgeWeight(e); + found = true; + } + } + } + } + if (!found) { + cleanup = true; + DEBUG(dbgs() << "No assumption possible in Fuction "< +#include +#include +using namespace llvm; + +namespace llvm { + template<> char ProfileInfoT::ID = 0; +} + +// Register the ProfileInfo interface, providing a nice name to refer to. +INITIALIZE_ANALYSIS_GROUP(ProfileInfo, "Profile Information", NoProfileInfo) + +namespace llvm { + +template <> +ProfileInfoT::ProfileInfoT() {} +template <> +ProfileInfoT::~ProfileInfoT() {} + +template <> +ProfileInfoT::ProfileInfoT() { + MachineProfile = 0; +} +template <> +ProfileInfoT::~ProfileInfoT() { + if (MachineProfile) delete MachineProfile; +} + +template<> +char ProfileInfoT::ID = 0; + +template<> +const double ProfileInfoT::MissingValue = -1; + +template<> const +double ProfileInfoT::MissingValue = -1; + +template<> double +ProfileInfoT::getExecutionCount(const BasicBlock *BB) { + std::map::iterator J = + BlockInformation.find(BB->getParent()); + if (J != BlockInformation.end()) { + BlockCounts::iterator I = J->second.find(BB); + if (I != J->second.end()) + return I->second; + } + + double Count = MissingValue; + + const_pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + + // Are there zero predecessors of this block? + if (PI == PE) { + Edge e = getEdge(0, BB); + Count = getEdgeWeight(e); + } else { + // Otherwise, if there are predecessors, the execution count of this block is + // the sum of the edge frequencies from the incoming edges. + std::set ProcessedPreds; + Count = 0; + for (; PI != PE; ++PI) { + const BasicBlock *P = *PI; + if (ProcessedPreds.insert(P).second) { + double w = getEdgeWeight(getEdge(P, BB)); + if (w == MissingValue) { + Count = MissingValue; + break; + } + Count += w; + } + } + } + + // If the predecessors did not suffice to get block weight, try successors. + if (Count == MissingValue) { + + succ_const_iterator SI = succ_begin(BB), SE = succ_end(BB); + + // Are there zero successors of this block? + if (SI == SE) { + Edge e = getEdge(BB,0); + Count = getEdgeWeight(e); + } else { + std::set ProcessedSuccs; + Count = 0; + for (; SI != SE; ++SI) + if (ProcessedSuccs.insert(*SI).second) { + double w = getEdgeWeight(getEdge(BB, *SI)); + if (w == MissingValue) { + Count = MissingValue; + break; + } + Count += w; + } + } + } + + if (Count != MissingValue) BlockInformation[BB->getParent()][BB] = Count; + return Count; +} + +template<> +double ProfileInfoT:: + getExecutionCount(const MachineBasicBlock *MBB) { + std::map::iterator J = + BlockInformation.find(MBB->getParent()); + if (J != BlockInformation.end()) { + BlockCounts::iterator I = J->second.find(MBB); + if (I != J->second.end()) + return I->second; + } + + return MissingValue; +} + +template<> +double ProfileInfoT::getExecutionCount(const Function *F) { + std::map::iterator J = + FunctionInformation.find(F); + if (J != FunctionInformation.end()) + return J->second; + + // isDeclaration() is checked here and not at start of function to allow + // functions without a body still to have a execution count. + if (F->isDeclaration()) return MissingValue; + + double Count = getExecutionCount(&F->getEntryBlock()); + if (Count != MissingValue) FunctionInformation[F] = Count; + return Count; +} + +template<> +double ProfileInfoT:: + getExecutionCount(const MachineFunction *MF) { + std::map::iterator J = + FunctionInformation.find(MF); + if (J != FunctionInformation.end()) + return J->second; + + double Count = getExecutionCount(&MF->front()); + if (Count != MissingValue) FunctionInformation[MF] = Count; + return Count; +} + +template<> +void ProfileInfoT:: + setExecutionCount(const BasicBlock *BB, double w) { + DEBUG(dbgs() << "Creating Block " << BB->getName() + << " (weight: " << format("%.20g",w) << ")\n"); + BlockInformation[BB->getParent()][BB] = w; +} + +template<> +void ProfileInfoT:: + setExecutionCount(const MachineBasicBlock *MBB, double w) { + DEBUG(dbgs() << "Creating Block " << MBB->getBasicBlock()->getName() + << " (weight: " << format("%.20g",w) << ")\n"); + BlockInformation[MBB->getParent()][MBB] = w; +} + +template<> +void ProfileInfoT::addEdgeWeight(Edge e, double w) { + double oldw = getEdgeWeight(e); + assert (oldw != MissingValue && "Adding weight to Edge with no previous weight"); + DEBUG(dbgs() << "Adding to Edge " << e + << " (new weight: " << format("%.20g",oldw + w) << ")\n"); + EdgeInformation[getFunction(e)][e] = oldw + w; +} + +template<> +void ProfileInfoT:: + addExecutionCount(const BasicBlock *BB, double w) { + double oldw = getExecutionCount(BB); + assert (oldw != MissingValue && "Adding weight to Block with no previous weight"); + DEBUG(dbgs() << "Adding to Block " << BB->getName() + << " (new weight: " << format("%.20g",oldw + w) << ")\n"); + BlockInformation[BB->getParent()][BB] = oldw + w; +} + +template<> +void ProfileInfoT::removeBlock(const BasicBlock *BB) { + std::map::iterator J = + BlockInformation.find(BB->getParent()); + if (J == BlockInformation.end()) return; + + DEBUG(dbgs() << "Deleting " << BB->getName() << "\n"); + J->second.erase(BB); +} + +template<> +void ProfileInfoT::removeEdge(Edge e) { + std::map::iterator J = + EdgeInformation.find(getFunction(e)); + if (J == EdgeInformation.end()) return; + + DEBUG(dbgs() << "Deleting" << e << "\n"); + J->second.erase(e); +} + +template<> +void ProfileInfoT:: + replaceEdge(const Edge &oldedge, const Edge &newedge) { + double w; + if ((w = getEdgeWeight(newedge)) == MissingValue) { + w = getEdgeWeight(oldedge); + DEBUG(dbgs() << "Replacing " << oldedge << " with " << newedge << "\n"); + } else { + w += getEdgeWeight(oldedge); + DEBUG(dbgs() << "Adding " << oldedge << " to " << newedge << "\n"); + } + setEdgeWeight(newedge,w); + removeEdge(oldedge); +} + +template<> +const BasicBlock *ProfileInfoT:: + GetPath(const BasicBlock *Src, const BasicBlock *Dest, + Path &P, unsigned Mode) { + const BasicBlock *BB = 0; + bool hasFoundPath = false; + + std::queue BFS; + BFS.push(Src); + + while(BFS.size() && !hasFoundPath) { + BB = BFS.front(); + BFS.pop(); + + succ_const_iterator Succ = succ_begin(BB), End = succ_end(BB); + if (Succ == End) { + P[0] = BB; + if (Mode & GetPathToExit) { + hasFoundPath = true; + BB = 0; + } + } + for(;Succ != End; ++Succ) { + if (P.find(*Succ) != P.end()) continue; + Edge e = getEdge(BB,*Succ); + if ((Mode & GetPathWithNewEdges) && (getEdgeWeight(e) != MissingValue)) continue; + P[*Succ] = BB; + BFS.push(*Succ); + if ((Mode & GetPathToDest) && *Succ == Dest) { + hasFoundPath = true; + BB = *Succ; + break; + } + if ((Mode & GetPathToValue) && (getExecutionCount(*Succ) != MissingValue)) { + hasFoundPath = true; + BB = *Succ; + break; + } + } + } + + return BB; +} + +template<> +void ProfileInfoT:: + divertFlow(const Edge &oldedge, const Edge &newedge) { + DEBUG(dbgs() << "Diverting " << oldedge << " via " << newedge ); + + // First check if the old edge was taken, if not, just delete it... + if (getEdgeWeight(oldedge) == 0) { + removeEdge(oldedge); + return; + } + + Path P; + P[newedge.first] = 0; + P[newedge.second] = newedge.first; + const BasicBlock *BB = GetPath(newedge.second,oldedge.second,P,GetPathToExit | GetPathToDest); + + double w = getEdgeWeight (oldedge); + DEBUG(dbgs() << ", Weight: " << format("%.20g",w) << "\n"); + do { + const BasicBlock *Parent = P.find(BB)->second; + Edge e = getEdge(Parent,BB); + double oldw = getEdgeWeight(e); + double oldc = getExecutionCount(e.first); + setEdgeWeight(e, w+oldw); + if (Parent != oldedge.first) { + setExecutionCount(e.first, w+oldc); + } + BB = Parent; + } while (BB != newedge.first); + removeEdge(oldedge); +} + +/// Replaces all occurences of RmBB in the ProfilingInfo with DestBB. +/// This checks all edges of the function the blocks reside in and replaces the +/// occurences of RmBB with DestBB. +template<> +void ProfileInfoT:: + replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB) { + DEBUG(dbgs() << "Replacing " << RmBB->getName() + << " with " << DestBB->getName() << "\n"); + const Function *F = DestBB->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + Edge e, newedge; + bool erasededge = false; + EdgeWeights::iterator I = J->second.begin(), E = J->second.end(); + while(I != E) { + e = (I++)->first; + bool foundedge = false; bool eraseedge = false; + if (e.first == RmBB) { + if (e.second == DestBB) { + eraseedge = true; + } else { + newedge = getEdge(DestBB, e.second); + foundedge = true; + } + } + if (e.second == RmBB) { + if (e.first == DestBB) { + eraseedge = true; + } else { + newedge = getEdge(e.first, DestBB); + foundedge = true; + } + } + if (foundedge) { + replaceEdge(e, newedge); + } + if (eraseedge) { + if (erasededge) { + Edge newedge = getEdge(DestBB, DestBB); + replaceEdge(e, newedge); + } else { + removeEdge(e); + erasededge = true; + } + } + } +} + +/// Splits an edge in the ProfileInfo and redirects flow over NewBB. +/// Since its possible that there is more than one edge in the CFG from FristBB +/// to SecondBB its necessary to redirect the flow proporionally. +template<> +void ProfileInfoT::splitEdge(const BasicBlock *FirstBB, + const BasicBlock *SecondBB, + const BasicBlock *NewBB, + bool MergeIdenticalEdges) { + const Function *F = FirstBB->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + // Generate edges and read current weight. + Edge e = getEdge(FirstBB, SecondBB); + Edge n1 = getEdge(FirstBB, NewBB); + Edge n2 = getEdge(NewBB, SecondBB); + EdgeWeights &ECs = J->second; + double w = ECs[e]; + + int succ_count = 0; + if (!MergeIdenticalEdges) { + // First count the edges from FristBB to SecondBB, if there is more than + // one, only slice out a proporional part for NewBB. + for(succ_const_iterator BBI = succ_begin(FirstBB), BBE = succ_end(FirstBB); + BBI != BBE; ++BBI) { + if (*BBI == SecondBB) succ_count++; + } + // When the NewBB is completely new, increment the count by one so that + // the counts are properly distributed. + if (getExecutionCount(NewBB) == ProfileInfo::MissingValue) succ_count++; + } else { + // When the edges are merged anyway, then redirect all flow. + succ_count = 1; + } + + // We know now how many edges there are from FirstBB to SecondBB, reroute a + // proportional part of the edge weight over NewBB. + double neww = floor(w / succ_count); + ECs[n1] += neww; + ECs[n2] += neww; + BlockInformation[F][NewBB] += neww; + if (succ_count == 1) { + ECs.erase(e); + } else { + ECs[e] -= neww; + } +} + +template<> +void ProfileInfoT::splitBlock(const BasicBlock *Old, + const BasicBlock* New) { + const Function *F = Old->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + DEBUG(dbgs() << "Splitting " << Old->getName() << " to " << New->getName() << "\n"); + + std::set Edges; + for (EdgeWeights::iterator ewi = J->second.begin(), ewe = J->second.end(); + ewi != ewe; ++ewi) { + Edge old = ewi->first; + if (old.first == Old) { + Edges.insert(old); + } + } + for (std::set::iterator EI = Edges.begin(), EE = Edges.end(); + EI != EE; ++EI) { + Edge newedge = getEdge(New, EI->second); + replaceEdge(*EI, newedge); + } + + double w = getExecutionCount(Old); + setEdgeWeight(getEdge(Old, New), w); + setExecutionCount(New, w); +} + +template<> +void ProfileInfoT::splitBlock(const BasicBlock *BB, + const BasicBlock* NewBB, + BasicBlock *const *Preds, + unsigned NumPreds) { + const Function *F = BB->getParent(); + std::map::iterator J = + EdgeInformation.find(F); + if (J == EdgeInformation.end()) return; + + DEBUG(dbgs() << "Splitting " << NumPreds << " Edges from " << BB->getName() + << " to " << NewBB->getName() << "\n"); + + // Collect weight that was redirected over NewBB. + double newweight = 0; + + std::set ProcessedPreds; + // For all requestes Predecessors. + for (unsigned pred = 0; pred < NumPreds; ++pred) { + const BasicBlock * Pred = Preds[pred]; + if (ProcessedPreds.insert(Pred).second) { + // Create edges and read old weight. + Edge oldedge = getEdge(Pred, BB); + Edge newedge = getEdge(Pred, NewBB); + + // Remember how much weight was redirected. + newweight += getEdgeWeight(oldedge); + + replaceEdge(oldedge,newedge); + } + } + + Edge newedge = getEdge(NewBB,BB); + setEdgeWeight(newedge, newweight); + setExecutionCount(NewBB, newweight); +} + +template<> +void ProfileInfoT::transfer(const Function *Old, + const Function *New) { + DEBUG(dbgs() << "Replacing Function " << Old->getName() << " with " + << New->getName() << "\n"); + std::map::iterator J = + EdgeInformation.find(Old); + if(J != EdgeInformation.end()) { + EdgeInformation[New] = J->second; + } + EdgeInformation.erase(Old); + BlockInformation.erase(Old); + FunctionInformation.erase(Old); +} + +static double readEdgeOrRemember(ProfileInfo::Edge edge, double w, + ProfileInfo::Edge &tocalc, unsigned &uncalc) { + if (w == ProfileInfo::MissingValue) { + tocalc = edge; + uncalc++; + return 0; + } else { + return w; + } +} + +template<> +bool ProfileInfoT:: + CalculateMissingEdge(const BasicBlock *BB, Edge &removed, + bool assumeEmptySelf) { + Edge edgetocalc; + unsigned uncalculated = 0; + + // collect weights of all incoming and outgoing edges, rememer edges that + // have no value + double incount = 0; + SmallSet pred_visited; + const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + if (bbi==bbe) { + Edge e = getEdge(0,BB); + incount += readEdgeOrRemember(e, getEdgeWeight(e) ,edgetocalc,uncalculated); + } + for (;bbi != bbe; ++bbi) { + if (pred_visited.insert(*bbi)) { + Edge e = getEdge(*bbi,BB); + incount += readEdgeOrRemember(e, getEdgeWeight(e) ,edgetocalc,uncalculated); + } + } + + double outcount = 0; + SmallSet succ_visited; + succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB); + if (sbbi==sbbe) { + Edge e = getEdge(BB,0); + if (getEdgeWeight(e) == MissingValue) { + double w = getExecutionCount(BB); + if (w != MissingValue) { + setEdgeWeight(e,w); + removed = e; + } + } + outcount += readEdgeOrRemember(e, getEdgeWeight(e), edgetocalc, uncalculated); + } + for (;sbbi != sbbe; ++sbbi) { + if (succ_visited.insert(*sbbi)) { + Edge e = getEdge(BB,*sbbi); + outcount += readEdgeOrRemember(e, getEdgeWeight(e), edgetocalc, uncalculated); + } + } + + // if exactly one edge weight was missing, calculate it and remove it from + // spanning tree + if (uncalculated == 0 ) { + return true; + } else + if (uncalculated == 1) { + if (incount < outcount) { + EdgeInformation[BB->getParent()][edgetocalc] = outcount-incount; + } else { + EdgeInformation[BB->getParent()][edgetocalc] = incount-outcount; + } + DEBUG(dbgs() << "--Calc Edge Counter for " << edgetocalc << ": " + << format("%.20g", getEdgeWeight(edgetocalc)) << "\n"); + removed = edgetocalc; + return true; + } else + if (uncalculated == 2 && assumeEmptySelf && edgetocalc.first == edgetocalc.second && incount == outcount) { + setEdgeWeight(edgetocalc, incount * 10); + removed = edgetocalc; + return true; + } else { + return false; + } +} + +static void readEdge(ProfileInfo *PI, ProfileInfo::Edge e, double &calcw, std::set &misscount) { + double w = PI->getEdgeWeight(e); + if (w != ProfileInfo::MissingValue) { + calcw += w; + } else { + misscount.insert(e); + } +} + +template<> +bool ProfileInfoT::EstimateMissingEdges(const BasicBlock *BB) { + double inWeight = 0; + std::set inMissing; + std::set ProcessedPreds; + const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + if (bbi == bbe) { + readEdge(this,getEdge(0,BB),inWeight,inMissing); + } + for( ; bbi != bbe; ++bbi ) { + if (ProcessedPreds.insert(*bbi).second) { + readEdge(this,getEdge(*bbi,BB),inWeight,inMissing); + } + } + + double outWeight = 0; + std::set outMissing; + std::set ProcessedSuccs; + succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB); + if (sbbi == sbbe) + readEdge(this,getEdge(BB,0),outWeight,outMissing); + for ( ; sbbi != sbbe; ++sbbi ) { + if (ProcessedSuccs.insert(*sbbi).second) { + readEdge(this,getEdge(BB,*sbbi),outWeight,outMissing); + } + } + + double share; + std::set::iterator ei,ee; + if (inMissing.size() == 0 && outMissing.size() > 0) { + ei = outMissing.begin(); + ee = outMissing.end(); + share = inWeight/outMissing.size(); + setExecutionCount(BB,inWeight); + } else + if (inMissing.size() > 0 && outMissing.size() == 0 && outWeight == 0) { + ei = inMissing.begin(); + ee = inMissing.end(); + share = 0; + setExecutionCount(BB,0); + } else + if (inMissing.size() == 0 && outMissing.size() == 0) { + setExecutionCount(BB,outWeight); + return true; + } else { + return false; + } + for ( ; ei != ee; ++ei ) { + setEdgeWeight(*ei,share); + } + return true; +} + +template<> +void ProfileInfoT::repair(const Function *F) { +// if (getExecutionCount(&(F->getEntryBlock())) == 0) { +// for (Function::const_iterator FI = F->begin(), FE = F->end(); +// FI != FE; ++FI) { +// const BasicBlock* BB = &(*FI); +// { +// const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); +// if (NBB == End) { +// setEdgeWeight(getEdge(0,BB),0); +// } +// for(;NBB != End; ++NBB) { +// setEdgeWeight(getEdge(*NBB,BB),0); +// } +// } +// { +// succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB); +// if (NBB == End) { +// setEdgeWeight(getEdge(0,BB),0); +// } +// for(;NBB != End; ++NBB) { +// setEdgeWeight(getEdge(*NBB,BB),0); +// } +// } +// } +// return; +// } + // The set of BasicBlocks that are still unvisited. + std::set Unvisited; + + // The set of return edges (Edges with no successors). + std::set ReturnEdges; + double ReturnWeight = 0; + + // First iterate over the whole function and collect: + // 1) The blocks in this function in the Unvisited set. + // 2) The return edges in the ReturnEdges set. + // 3) The flow that is leaving the function already via return edges. + + // Data structure for searching the function. + std::queue BFS; + const BasicBlock *BB = &(F->getEntryBlock()); + BFS.push(BB); + Unvisited.insert(BB); + + while (BFS.size()) { + BB = BFS.front(); BFS.pop(); + succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB); + if (NBB == End) { + Edge e = getEdge(BB,0); + double w = getEdgeWeight(e); + if (w == MissingValue) { + // If the return edge has no value, try to read value from block. + double bw = getExecutionCount(BB); + if (bw != MissingValue) { + setEdgeWeight(e,bw); + ReturnWeight += bw; + } else { + // If both return edge and block provide no value, collect edge. + ReturnEdges.insert(e); + } + } else { + // If the return edge has a proper value, collect it. + ReturnWeight += w; + } + } + for (;NBB != End; ++NBB) { + if (Unvisited.insert(*NBB).second) { + BFS.push(*NBB); + } + } + } + + while (Unvisited.size() > 0) { + unsigned oldUnvisitedCount = Unvisited.size(); + bool FoundPath = false; + + // If there is only one edge left, calculate it. + if (ReturnEdges.size() == 1) { + ReturnWeight = getExecutionCount(&(F->getEntryBlock())) - ReturnWeight; + + Edge e = *ReturnEdges.begin(); + setEdgeWeight(e,ReturnWeight); + setExecutionCount(e.first,ReturnWeight); + + Unvisited.erase(e.first); + ReturnEdges.erase(e); + continue; + } + + // Calculate all blocks where only one edge is missing, this may also + // resolve furhter return edges. + std::set::iterator FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE) { + const BasicBlock *BB = *FI; ++FI; + Edge e; + if(CalculateMissingEdge(BB,e,true)) { + if (BlockInformation[F].find(BB) == BlockInformation[F].end()) { + setExecutionCount(BB,getExecutionCount(BB)); + } + Unvisited.erase(BB); + if (e.first != 0 && e.second == 0) { + ReturnEdges.erase(e); + ReturnWeight += getEdgeWeight(e); + } + } + } + if (oldUnvisitedCount > Unvisited.size()) continue; + + // Estimate edge weights by dividing the flow proportionally. + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE) { + const BasicBlock *BB = *FI; ++FI; + const BasicBlock *Dest = 0; + bool AllEdgesHaveSameReturn = true; + // Check each Successor, these must all end up in the same or an empty + // return block otherwise its dangerous to do an estimation on them. + for (succ_const_iterator Succ = succ_begin(BB), End = succ_end(BB); + Succ != End; ++Succ) { + Path P; + GetPath(*Succ, 0, P, GetPathToExit); + if (Dest && Dest != P[0]) { + AllEdgesHaveSameReturn = false; + } + Dest = P[0]; + } + if (AllEdgesHaveSameReturn) { + if(EstimateMissingEdges(BB)) { + Unvisited.erase(BB); + break; + } + } + } + if (oldUnvisitedCount > Unvisited.size()) continue; + + // Check if there is a path to an block that has a known value and redirect + // flow accordingly. + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE && !FoundPath) { + // Fetch path. + const BasicBlock *BB = *FI; ++FI; + Path P; + const BasicBlock *Dest = GetPath(BB, 0, P, GetPathToValue); + + // Calculate incoming flow. + double iw = 0; unsigned inmissing = 0; unsigned incount = 0; unsigned invalid = 0; + std::set Processed; + for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); + NBB != End; ++NBB) { + if (Processed.insert(*NBB).second) { + Edge e = getEdge(*NBB, BB); + double ew = getEdgeWeight(e); + if (ew != MissingValue) { + iw += ew; + invalid++; + } else { + // If the path contains the successor, this means its a backedge, + // do not count as missing. + if (P.find(*NBB) == P.end()) + inmissing++; + } + incount++; + } + } + if (inmissing == incount) continue; + if (invalid == 0) continue; + + // Subtract (already) outgoing flow. + Processed.clear(); + for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB); + NBB != End; ++NBB) { + if (Processed.insert(*NBB).second) { + Edge e = getEdge(BB, *NBB); + double ew = getEdgeWeight(e); + if (ew != MissingValue) { + iw -= ew; + } + } + } + if (iw < 0) continue; + + // Check the recieving end of the path if it can handle the flow. + double ow = getExecutionCount(Dest); + Processed.clear(); + for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB); + NBB != End; ++NBB) { + if (Processed.insert(*NBB).second) { + Edge e = getEdge(BB, *NBB); + double ew = getEdgeWeight(e); + if (ew != MissingValue) { + ow -= ew; + } + } + } + if (ow < 0) continue; + + // Determine how much flow shall be used. + double ew = getEdgeWeight(getEdge(P[Dest],Dest)); + if (ew != MissingValue) { + ew = ew Processed; + for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); + NBB != End; ++NBB) { + if (Processed.insert(*NBB).second) { + Edge e = getEdge(*NBB, BB); + double ew = getEdgeWeight(e); + if (ew != MissingValue) { + iw += ew; + } + } + } + setEdgeWeight(e,iw * 10); + FoundPath = true; + } + } + } + if (FoundPath) continue; + + // Determine backedges, set them to zero. + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE && !FoundPath) { + const BasicBlock *BB = *FI; ++FI; + const BasicBlock *Dest = 0; + Path P; + bool BackEdgeFound = false; + for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); + NBB != End; ++NBB) { + Dest = GetPath(BB, *NBB, P, GetPathToDest | GetPathWithNewEdges); + if (Dest == *NBB) { + BackEdgeFound = true; + break; + } + } + if (BackEdgeFound) { + Edge e = getEdge(Dest,BB); + double w = getEdgeWeight(e); + if (w == MissingValue) { + setEdgeWeight(e,0); + FoundPath = true; + } + do { + Edge e = getEdge(P[Dest], Dest); + double w = getEdgeWeight(e); + if (w == MissingValue) { + setEdgeWeight(e,0); + FoundPath = true; + } + Dest = P[Dest]; + } while (Dest != BB); + } + } + if (FoundPath) continue; + + // Channel flow to return block. + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE && !FoundPath) { + const BasicBlock *BB = *FI; ++FI; + + Path P; + const BasicBlock *Dest = GetPath(BB, 0, P, GetPathToExit | GetPathWithNewEdges); + Dest = P[0]; + if (!Dest) continue; + + if (getEdgeWeight(getEdge(Dest,0)) == MissingValue) { + // Calculate incoming flow. + double iw = 0; + std::set Processed; + for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); + NBB != End; ++NBB) { + if (Processed.insert(*NBB).second) { + Edge e = getEdge(*NBB, BB); + double ew = getEdgeWeight(e); + if (ew != MissingValue) { + iw += ew; + } + } + } + do { + Edge e = getEdge(P[Dest], Dest); + double w = getEdgeWeight(e); + if (w == MissingValue) { + setEdgeWeight(e,iw); + FoundPath = true; + } else { + assert(0 && "Edge should not have value already!"); + } + Dest = P[Dest]; + } while (Dest != BB); + } + } + if (FoundPath) continue; + + // Speculatively set edges to zero. + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE && !FoundPath) { + const BasicBlock *BB = *FI; ++FI; + + for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB); + NBB != End; ++NBB) { + Edge e = getEdge(*NBB,BB); + double w = getEdgeWeight(e); + if (w == MissingValue) { + setEdgeWeight(e,0); + FoundPath = true; + break; + } + } + } + if (FoundPath) continue; + + errs() << "{"; + FI = Unvisited.begin(), FE = Unvisited.end(); + while(FI != FE) { + const BasicBlock *BB = *FI; ++FI; + dbgs() << BB->getName(); + if (FI != FE) + dbgs() << ","; + } + errs() << "}"; + + errs() << "ASSERT: could not repair function"; + assert(0 && "could not repair function"); + } + + EdgeWeights J = EdgeInformation[F]; + for (EdgeWeights::iterator EI = J.begin(), EE = J.end(); EI != EE; ++EI) { + Edge e = EI->first; + + bool SuccFound = false; + if (e.first != 0) { + succ_const_iterator NBB = succ_begin(e.first), End = succ_end(e.first); + if (NBB == End) { + if (0 == e.second) { + SuccFound = true; + } + } + for (;NBB != End; ++NBB) { + if (*NBB == e.second) { + SuccFound = true; + break; + } + } + if (!SuccFound) { + removeEdge(e); + } + } + } +} + +raw_ostream& operator<<(raw_ostream &O, const Function *F) { + return O << F->getName(); +} + +raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF) { + return O << MF->getFunction()->getName() << "(MF)"; +} + +raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB) { + return O << BB->getName(); +} + +raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB) { + return O << MBB->getBasicBlock()->getName() << "(MB)"; +} + +raw_ostream& operator<<(raw_ostream &O, std::pair E) { + O << "("; + + if (E.first) + O << E.first; + else + O << "0"; + + O << ","; + + if (E.second) + O << E.second; + else + O << "0"; + + return O << ")"; +} + +raw_ostream& operator<<(raw_ostream &O, std::pair E) { + O << "("; + + if (E.first) + O << E.first; + else + O << "0"; + + O << ","; + + if (E.second) + O << E.second; + else + O << "0"; + + return O << ")"; +} + +} // namespace llvm + +//===----------------------------------------------------------------------===// +// NoProfile ProfileInfo implementation +// + +namespace { + struct NoProfileInfo : public ImmutablePass, public ProfileInfo { + static char ID; // Class identification, replacement for typeinfo + NoProfileInfo() : ImmutablePass(ID) { + initializeNoProfileInfoPass(*PassRegistry::getPassRegistry()); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &ProfileInfo::ID) + return (ProfileInfo*)this; + return this; + } + + virtual const char *getPassName() const { + return "NoProfileInfo"; + } + }; +} // End of anonymous namespace + +char NoProfileInfo::ID = 0; +// Register this pass... +INITIALIZE_AG_PASS(NoProfileInfo, ProfileInfo, "no-profile", + "No Profile Information", false, true, true) + +ImmutablePass *llvm::createNoProfileInfoPass() { return new NoProfileInfo(); } diff --git a/final/lib/Analysis/ProfileInfoLoader.cpp b/final/lib/Analysis/ProfileInfoLoader.cpp new file mode 100644 index 00000000000..25481b2ee67 --- /dev/null +++ b/final/lib/Analysis/ProfileInfoLoader.cpp @@ -0,0 +1,158 @@ +//===- ProfileInfoLoad.cpp - Load profile information from disk -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ProfileInfoLoader class is used to load and represent profiling +// information read in from the dump file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Analysis/ProfileInfoTypes.h" +#include "llvm/Module.h" +#include "llvm/InstrTypes.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +using namespace llvm; + +// ByteSwap - Byteswap 'Var' if 'Really' is true. +// +static inline unsigned ByteSwap(unsigned Var, bool Really) { + if (!Really) return Var; + return ((Var & (255U<< 0U)) << 24U) | + ((Var & (255U<< 8U)) << 8U) | + ((Var & (255U<<16U)) >> 8U) | + ((Var & (255U<<24U)) >> 24U); +} + +static unsigned AddCounts(unsigned A, unsigned B) { + // If either value is undefined, use the other. + if (A == ProfileInfoLoader::Uncounted) return B; + if (B == ProfileInfoLoader::Uncounted) return A; + return A + B; +} + +static void ReadProfilingBlock(const char *ToolName, FILE *F, + bool ShouldByteSwap, + std::vector &Data) { + // Read the number of entries... + unsigned NumEntries; + if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) { + errs() << ToolName << ": data packet truncated!\n"; + perror(0); + exit(1); + } + NumEntries = ByteSwap(NumEntries, ShouldByteSwap); + + // Read the counts... + std::vector TempSpace(NumEntries); + + // Read in the block of data... + if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) { + errs() << ToolName << ": data packet truncated!\n"; + perror(0); + exit(1); + } + + // Make sure we have enough space... The space is initialised to -1 to + // facitiltate the loading of missing values for OptimalEdgeProfiling. + if (Data.size() < NumEntries) + Data.resize(NumEntries, ProfileInfoLoader::Uncounted); + + // Accumulate the data we just read into the data. + if (!ShouldByteSwap) { + for (unsigned i = 0; i != NumEntries; ++i) { + Data[i] = AddCounts(TempSpace[i], Data[i]); + } + } else { + for (unsigned i = 0; i != NumEntries; ++i) { + Data[i] = AddCounts(ByteSwap(TempSpace[i], true), Data[i]); + } + } +} + +const unsigned ProfileInfoLoader::Uncounted = ~0U; + +// ProfileInfoLoader ctor - Read the specified profiling data file, exiting the +// program if the file is invalid or broken. +// +ProfileInfoLoader::ProfileInfoLoader(const char *ToolName, + const std::string &Filename, + Module &TheModule) : + Filename(Filename), + M(TheModule), Warned(false) { + FILE *F = fopen(Filename.c_str(), "rb"); + if (F == 0) { + errs() << ToolName << ": Error opening '" << Filename << "': "; + perror(0); + exit(1); + } + + // Keep reading packets until we run out of them. + unsigned PacketType; + while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) { + // If the low eight bits of the packet are zero, we must be dealing with an + // endianness mismatch. Byteswap all words read from the profiling + // information. + bool ShouldByteSwap = (char)PacketType == 0; + PacketType = ByteSwap(PacketType, ShouldByteSwap); + + switch (PacketType) { + case ArgumentInfo: { + unsigned ArgLength; + if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) { + errs() << ToolName << ": arguments packet truncated!\n"; + perror(0); + exit(1); + } + ArgLength = ByteSwap(ArgLength, ShouldByteSwap); + + // Read in the arguments... + std::vector Chars(ArgLength+4); + + if (ArgLength) + if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) { + errs() << ToolName << ": arguments packet truncated!\n"; + perror(0); + exit(1); + } + CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength])); + break; + } + + case FunctionInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts); + break; + + case BlockInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts); + break; + + case EdgeInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts); + break; + + case OptEdgeInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, OptimalEdgeCounts); + break; + + case BBTraceInfo: + ReadProfilingBlock(ToolName, F, ShouldByteSwap, BBTrace); + break; + + default: + errs() << ToolName << ": Unknown packet type #" << PacketType << "!\n"; + exit(1); + } + } + + fclose(F); +} + diff --git a/final/lib/Analysis/ProfileInfoLoaderPass.cpp b/final/lib/Analysis/ProfileInfoLoaderPass.cpp new file mode 100644 index 00000000000..098079bcffc --- /dev/null +++ b/final/lib/Analysis/ProfileInfoLoaderPass.cpp @@ -0,0 +1,267 @@ +//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a concrete implementation of profiling information that +// loads the information from a profile dump file. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-loader" +#include "llvm/BasicBlock.h" +#include "llvm/InstrTypes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Analysis/ProfileInfoLoader.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallSet.h" +#include +using namespace llvm; + +STATISTIC(NumEdgesRead, "The # of edges read."); + +static cl::opt +ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"), + cl::value_desc("filename"), + cl::desc("Profile file loaded by -profile-loader")); + +namespace { + class LoaderPass : public ModulePass, public ProfileInfo { + std::string Filename; + std::set SpanningTree; + std::set BBisUnvisited; + unsigned ReadCount; + public: + static char ID; // Class identification, replacement for typeinfo + explicit LoaderPass(const std::string &filename = "") + : ModulePass(ID), Filename(filename) { + initializeLoaderPassPass(*PassRegistry::getPassRegistry()); + if (filename.empty()) Filename = ProfileInfoFilename; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual const char *getPassName() const { + return "Profiling information loader"; + } + + // recurseBasicBlock() - Calculates the edge weights for as much basic + // blocks as possbile. + virtual void recurseBasicBlock(const BasicBlock *BB); + virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &); + virtual void readEdge(ProfileInfo::Edge, std::vector&); + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &ProfileInfo::ID) + return (ProfileInfo*)this; + return this; + } + + /// run - Load the profile information from the specified file. + virtual bool runOnModule(Module &M); + }; +} // End of anonymous namespace + +char LoaderPass::ID = 0; +INITIALIZE_AG_PASS(LoaderPass, ProfileInfo, "profile-loader", + "Load profile information from llvmprof.out", false, true, false) + +char &llvm::ProfileLoaderPassID = LoaderPass::ID; + +ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); } + +/// createProfileLoaderPass - This function returns a Pass that loads the +/// profiling information for the module from the specified filename, making it +/// available to the optimizers. +Pass *llvm::createProfileLoaderPass(const std::string &Filename) { + return new LoaderPass(Filename); +} + +void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc, + unsigned &uncalc, double &count) { + double w; + if ((w = getEdgeWeight(edge)) == MissingValue) { + tocalc = edge; + uncalc++; + } else { + count+=w; + } +} + +// recurseBasicBlock - Visits all neighbours of a block and then tries to +// calculate the missing edge values. +void LoaderPass::recurseBasicBlock(const BasicBlock *BB) { + + // break recursion if already visited + if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return; + BBisUnvisited.erase(BB); + if (!BB) return; + + for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } + for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi) { + recurseBasicBlock(*bbi); + } + + Edge tocalc; + if (CalculateMissingEdge(BB, tocalc)) { + SpanningTree.erase(tocalc); + } +} + +void LoaderPass::readEdge(ProfileInfo::Edge e, + std::vector &ECs) { + if (ReadCount < ECs.size()) { + double weight = ECs[ReadCount++]; + if (weight != ProfileInfoLoader::Uncounted) { + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also representable + // in double. + EdgeInformation[getFunction(e)][e] += (double)weight; + + DEBUG(dbgs() << "--Read Edge Counter for " << e + << " (# "<< (ReadCount-1) << "): " + << (unsigned)getEdgeWeight(e) << "\n"); + } else { + // This happens only if reading optimal profiling information, not when + // reading regular profiling information. + SpanningTree.insert(e); + } + } +} + +bool LoaderPass::runOnModule(Module &M) { + ProfileInfoLoader PIL("profile-loader", Filename, M); + + EdgeInformation.clear(); + std::vector Counters = PIL.getRawEdgeCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(dbgs()<<"Working on "<getNameStr()<<"\n"); + readEdge(getEdge(0,&F->getEntryBlock()), Counters); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + readEdge(getEdge(BB,TI->getSuccessor(s)), Counters); + } + } + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + NumEdgesRead = ReadCount; + } + + Counters = PIL.getRawOptimalEdgeCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + DEBUG(dbgs()<<"Working on "<getNameStr()<<"\n"); + readEdge(getEdge(0,&F->getEntryBlock()), Counters); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + TerminatorInst *TI = BB->getTerminator(); + if (TI->getNumSuccessors() == 0) { + readEdge(getEdge(BB,0), Counters); + } + for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { + readEdge(getEdge(BB,TI->getSuccessor(s)), Counters); + } + } + while (SpanningTree.size() > 0) { + + unsigned size = SpanningTree.size(); + + BBisUnvisited.clear(); + for (std::set::iterator ei = SpanningTree.begin(), + ee = SpanningTree.end(); ei != ee; ++ei) { + BBisUnvisited.insert(ei->first); + BBisUnvisited.insert(ei->second); + } + while (BBisUnvisited.size() > 0) { + recurseBasicBlock(*BBisUnvisited.begin()); + } + + if (SpanningTree.size() == size) { + DEBUG(dbgs()<<"{"); + for (std::set::iterator ei = SpanningTree.begin(), + ee = SpanningTree.end(); ei != ee; ++ei) { + DEBUG(dbgs()<< *ei <<","); + } + assert(0 && "No edge calculated!"); + } + + } + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + NumEdgesRead = ReadCount; + } + + BlockInformation.clear(); + Counters = PIL.getRawBlockCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (ReadCount < Counters.size()) + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also + // representable in double. + BlockInformation[F][BB] = (double)Counters[ReadCount++]; + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + } + + FunctionInformation.clear(); + Counters = PIL.getRawFunctionCounts(); + if (Counters.size() > 0) { + ReadCount = 0; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + if (F->isDeclaration()) continue; + if (ReadCount < Counters.size()) + // Here the data realm changes from the unsigned of the file to the + // double of the ProfileInfo. This conversion is save because we know + // that everything thats representable in unsinged is also + // representable in double. + FunctionInformation[F] = (double)Counters[ReadCount++]; + } + if (ReadCount != Counters.size()) { + errs() << "WARNING: profile information is inconsistent with " + << "the current program!\n"; + } + } + + return false; +} diff --git a/final/lib/Analysis/ProfileVerifierPass.cpp b/final/lib/Analysis/ProfileVerifierPass.cpp new file mode 100644 index 00000000000..a01751849c5 --- /dev/null +++ b/final/lib/Analysis/ProfileVerifierPass.cpp @@ -0,0 +1,382 @@ +//===- ProfileVerifierPass.cpp - LLVM Pass to estimate profile info -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass that checks profiling information for +// plausibility. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "profile-verifier" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CFG.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Debug.h" +#include +using namespace llvm; + +static cl::opt +ProfileVerifierDisableAssertions("profile-verifier-noassert", + cl::desc("Disable assertions")); + +namespace llvm { + template + class ProfileVerifierPassT : public FunctionPass { + + struct DetailedBlockInfo { + const BType *BB; + double BBWeight; + double inWeight; + int inCount; + double outWeight; + int outCount; + }; + + ProfileInfoT *PI; + std::set BBisVisited; + std::set FisVisited; + bool DisableAssertions; + + // When debugging is enabled, the verifier prints a whole slew of debug + // information, otherwise its just the assert. These are all the helper + // functions. + bool PrintedDebugTree; + std::set BBisPrinted; + void debugEntry(DetailedBlockInfo*); + void printDebugInfo(const BType *BB); + + public: + static char ID; // Class identification, replacement for typeinfo + + explicit ProfileVerifierPassT () : FunctionPass(ID) { + initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); + DisableAssertions = ProfileVerifierDisableAssertions; + } + explicit ProfileVerifierPassT (bool da) : FunctionPass(ID), + DisableAssertions(da) { + initializeProfileVerifierPassPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired >(); + } + + const char *getPassName() const { + return "Profiling information verifier"; + } + + /// run - Verify the profile information. + bool runOnFunction(FType &F); + void recurseBasicBlock(const BType*); + + bool exitReachable(const FType*); + double ReadOrAssert(typename ProfileInfoT::Edge); + void CheckValue(bool, const char*, DetailedBlockInfo*); + }; + + typedef ProfileVerifierPassT ProfileVerifierPass; + + template + void ProfileVerifierPassT::printDebugInfo(const BType *BB) { + + if (BBisPrinted.find(BB) != BBisPrinted.end()) return; + + double BBWeight = PI->getExecutionCount(BB); + if (BBWeight == ProfileInfoT::MissingValue) { BBWeight = 0; } + double inWeight = 0; + int inCount = 0; + std::set ProcessedPreds; + for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedPreds.insert(*bbi).second) { + typename ProfileInfoT::Edge E = PI->getEdge(*bbi,BB); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { EdgeWeight = 0; } + dbgs() << "calculated in-edge " << E << ": " + << format("%20.20g",EdgeWeight) << "\n"; + inWeight += EdgeWeight; + inCount++; + } + } + double outWeight = 0; + int outCount = 0; + std::set ProcessedSuccs; + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + if (ProcessedSuccs.insert(*bbi).second) { + typename ProfileInfoT::Edge E = PI->getEdge(BB,*bbi); + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { EdgeWeight = 0; } + dbgs() << "calculated out-edge " << E << ": " + << format("%20.20g",EdgeWeight) << "\n"; + outWeight += EdgeWeight; + outCount++; + } + } + dbgs() << "Block " << BB->getNameStr() << " in " + << BB->getParent()->getNameStr() << ":" + << "BBWeight=" << format("%20.20g",BBWeight) << "," + << "inWeight=" << format("%20.20g",inWeight) << "," + << "inCount=" << inCount << "," + << "outWeight=" << format("%20.20g",outWeight) << "," + << "outCount" << outCount << "\n"; + + // mark as visited and recurse into subnodes + BBisPrinted.insert(BB); + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + printDebugInfo(*bbi); + } + } + + template + void ProfileVerifierPassT::debugEntry (DetailedBlockInfo *DI) { + dbgs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in " + << DI->BB->getParent()->getNameStr() << ":" + << "BBWeight=" << format("%20.20g",DI->BBWeight) << "," + << "inWeight=" << format("%20.20g",DI->inWeight) << "," + << "inCount=" << DI->inCount << "," + << "outWeight=" << format("%20.20g",DI->outWeight) << "," + << "outCount=" << DI->outCount << "\n"; + if (!PrintedDebugTree) { + PrintedDebugTree = true; + printDebugInfo(&(DI->BB->getParent()->getEntryBlock())); + } + } + + // This compares A and B for equality. + static bool Equals(double A, double B) { + return A == B; + } + + // This checks if the function "exit" is reachable from an given function + // via calls, this is necessary to check if a profile is valid despite the + // counts not fitting exactly. + template + bool ProfileVerifierPassT::exitReachable(const FType *F) { + if (!F) return false; + + if (FisVisited.count(F)) return false; + + FType *Exit = F->getParent()->getFunction("exit"); + if (Exit == F) { + return true; + } + + FisVisited.insert(F); + bool exits = false; + for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (const CallInst *CI = dyn_cast(&*I)) { + FType *F = CI->getCalledFunction(); + if (F) { + exits |= exitReachable(F); + } else { + // This is a call to a pointer, all bets are off... + exits = true; + } + if (exits) break; + } + } + return exits; + } + + #define ASSERTMESSAGE(M) \ + { dbgs() << "ASSERT:" << (M) << "\n"; \ + if (!DisableAssertions) assert(0 && (M)); } + + template + double ProfileVerifierPassT::ReadOrAssert(typename ProfileInfoT::Edge E) { + double EdgeWeight = PI->getEdgeWeight(E); + if (EdgeWeight == ProfileInfoT::MissingValue) { + dbgs() << "Edge " << E << " in Function " + << ProfileInfoT::getFunction(E)->getNameStr() << ": "; + ASSERTMESSAGE("Edge has missing value"); + return 0; + } else { + if (EdgeWeight < 0) { + dbgs() << "Edge " << E << " in Function " + << ProfileInfoT::getFunction(E)->getNameStr() << ": "; + ASSERTMESSAGE("Edge has negative value"); + } + return EdgeWeight; + } + } + + template + void ProfileVerifierPassT::CheckValue(bool Error, + const char *Message, + DetailedBlockInfo *DI) { + if (Error) { + DEBUG(debugEntry(DI)); + dbgs() << "Block " << DI->BB->getNameStr() << " in Function " + << DI->BB->getParent()->getNameStr() << ": "; + ASSERTMESSAGE(Message); + } + return; + } + + // This calculates the Information for a block and then recurses into the + // successors. + template + void ProfileVerifierPassT::recurseBasicBlock(const BType *BB) { + + // Break the recursion by remembering all visited blocks. + if (BBisVisited.find(BB) != BBisVisited.end()) return; + + // Use a data structure to store all the information, this can then be handed + // to debug printers. + DetailedBlockInfo DI; + DI.BB = BB; + DI.outCount = DI.inCount = 0; + DI.inWeight = DI.outWeight = 0; + + // Read predecessors. + std::set ProcessedPreds; + const_pred_iterator bpi = pred_begin(BB), bpe = pred_end(BB); + // If there are none, check for (0,BB) edge. + if (bpi == bpe) { + DI.inWeight += ReadOrAssert(PI->getEdge(0,BB)); + DI.inCount++; + } + for (;bpi != bpe; ++bpi) { + if (ProcessedPreds.insert(*bpi).second) { + DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB)); + DI.inCount++; + } + } + + // Read successors. + std::set ProcessedSuccs; + succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + // If there is an (0,BB) edge, consider it too. (This is done not only when + // there are no successors, but every time; not every function contains + // return blocks with no successors (think loop latch as return block)). + double w = PI->getEdgeWeight(PI->getEdge(BB,0)); + if (w != ProfileInfoT::MissingValue) { + DI.outWeight += w; + DI.outCount++; + } + for (;bbi != bbe; ++bbi) { + if (ProcessedSuccs.insert(*bbi).second) { + DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi)); + DI.outCount++; + } + } + + // Read block weight. + DI.BBWeight = PI->getExecutionCount(BB); + CheckValue(DI.BBWeight == ProfileInfoT::MissingValue, + "BasicBlock has missing value", &DI); + CheckValue(DI.BBWeight < 0, + "BasicBlock has negative value", &DI); + + // Check if this block is a setjmp target. + bool isSetJmpTarget = false; + if (DI.outWeight > DI.inWeight) { + for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + FType *F = CI->getCalledFunction(); + if (F && (F->getName() == "_setjmp")) { + isSetJmpTarget = true; break; + } + } + } + } + // Check if this block is eventually reaching exit. + bool isExitReachable = false; + if (DI.inWeight > DI.outWeight) { + for (typename BType::const_iterator i = BB->begin(), ie = BB->end(); + i != ie; ++i) { + if (const CallInst *CI = dyn_cast(&*i)) { + FType *F = CI->getCalledFunction(); + if (F) { + FisVisited.clear(); + isExitReachable |= exitReachable(F); + } else { + // This is a call to a pointer, all bets are off... + isExitReachable = true; + } + if (isExitReachable) break; + } + } + } + + if (DI.inCount > 0 && DI.outCount == 0) { + // If this is a block with no successors. + if (!isSetJmpTarget) { + CheckValue(!Equals(DI.inWeight,DI.BBWeight), + "inWeight and BBWeight do not match", &DI); + } + } else if (DI.inCount == 0 && DI.outCount > 0) { + // If this is a block with no predecessors. + if (!isExitReachable) + CheckValue(!Equals(DI.BBWeight,DI.outWeight), + "BBWeight and outWeight do not match", &DI); + } else { + // If this block has successors and predecessors. + if (DI.inWeight > DI.outWeight && !isExitReachable) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "inWeight and outWeight do not match", &DI); + if (DI.inWeight < DI.outWeight && !isSetJmpTarget) + CheckValue(!Equals(DI.inWeight,DI.outWeight), + "inWeight and outWeight do not match", &DI); + } + + + // Mark this block as visited, rescurse into successors. + BBisVisited.insert(BB); + for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB); + bbi != bbe; ++bbi ) { + recurseBasicBlock(*bbi); + } + } + + template + bool ProfileVerifierPassT::runOnFunction(FType &F) { + PI = getAnalysisIfAvailable >(); + if (!PI) + ASSERTMESSAGE("No ProfileInfo available"); + + // Prepare global variables. + PrintedDebugTree = false; + BBisVisited.clear(); + + // Fetch entry block and recurse into it. + const BType *entry = &F.getEntryBlock(); + recurseBasicBlock(entry); + + if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry)) + ASSERTMESSAGE("Function count and entry block count do not match"); + + return false; + } + + template + char ProfileVerifierPassT::ID = 0; +} + +INITIALIZE_PASS_BEGIN(ProfileVerifierPass, "profile-verifier", + "Verify profiling information", false, true) +INITIALIZE_AG_DEPENDENCY(ProfileInfo) +INITIALIZE_PASS_END(ProfileVerifierPass, "profile-verifier", + "Verify profiling information", false, true) + +namespace llvm { + FunctionPass *createProfileVerifierPass() { + return new ProfileVerifierPass(ProfileVerifierDisableAssertions); + } +} + diff --git a/final/lib/Analysis/README.txt b/final/lib/Analysis/README.txt new file mode 100644 index 00000000000..0e96e4c950c --- /dev/null +++ b/final/lib/Analysis/README.txt @@ -0,0 +1,30 @@ +Analysis Opportunities: + +//===---------------------------------------------------------------------===// + +In test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll, the +ScalarEvolution expression for %r is this: + + {1,+,3,+,2} + +Outside the loop, this could be evaluated simply as (%n * %n), however +ScalarEvolution currently evaluates it as + + (-2 + (2 * (trunc i65 (((zext i64 (-2 + %n) to i65) * (zext i64 (-1 + %n) to i65)) /u 2) to i64)) + (3 * %n)) + +In addition to being much more complicated, it involves i65 arithmetic, +which is very inefficient when expanded into code. + +//===---------------------------------------------------------------------===// + +In formatValue in test/CodeGen/X86/lsr-delayed-fold.ll, + +ScalarEvolution is forming this expression: + +((trunc i64 (-1 * %arg5) to i32) + (trunc i64 %arg5 to i32) + (-1 * (trunc i64 undef to i32))) + +This could be folded to + +(-1 * (trunc i64 undef to i32)) + +//===---------------------------------------------------------------------===// diff --git a/final/lib/Analysis/RegionInfo.cpp b/final/lib/Analysis/RegionInfo.cpp new file mode 100644 index 00000000000..e2f6a8bf5d9 --- /dev/null +++ b/final/lib/Analysis/RegionInfo.cpp @@ -0,0 +1,851 @@ +//===- RegionInfo.cpp - SESE region detection analysis --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Detects single entry single exit regions in the control flow graph. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionIterator.h" + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Assembly/Writer.h" + +#define DEBUG_TYPE "region" +#include "llvm/Support/Debug.h" + +#include +#include + +using namespace llvm; + +// Always verify if expensive checking is enabled. +#ifdef XDEBUG +static bool VerifyRegionInfo = true; +#else +static bool VerifyRegionInfo = false; +#endif + +static cl::opt +VerifyRegionInfoX("verify-region-info", cl::location(VerifyRegionInfo), + cl::desc("Verify region info (time consuming)")); + +STATISTIC(numRegions, "The # of regions"); +STATISTIC(numSimpleRegions, "The # of simple regions"); + +//===----------------------------------------------------------------------===// +/// PrintStyle - Print region in difference ways. +enum PrintStyle { PrintNone, PrintBB, PrintRN }; + +static cl::opt printStyle("print-region-style", cl::Hidden, + cl::desc("style of printing regions"), + cl::values( + clEnumValN(PrintNone, "none", "print no details"), + clEnumValN(PrintBB, "bb", "print regions in detail with block_iterator"), + clEnumValN(PrintRN, "rn", "print regions in detail with element_iterator"), + clEnumValEnd)); +//===----------------------------------------------------------------------===// +/// Region Implementation +Region::Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RInfo, + DominatorTree *dt, Region *Parent) + : RegionNode(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {} + +Region::~Region() { + // Free the cached nodes. + for (BBNodeMapT::iterator it = BBNodeMap.begin(), + ie = BBNodeMap.end(); it != ie; ++it) + delete it->second; + + // Only clean the cache for this Region. Caches of child Regions will be + // cleaned when the child Regions are deleted. + BBNodeMap.clear(); + + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; +} + +void Region::replaceEntry(BasicBlock *BB) { + entry.setPointer(BB); +} + +void Region::replaceExit(BasicBlock *BB) { + assert(exit && "No exit to replace!"); + exit = BB; +} + +bool Region::contains(const BasicBlock *B) const { + BasicBlock *BB = const_cast(B); + + assert(DT->getNode(BB) && "BB not part of the dominance tree"); + + BasicBlock *entry = getEntry(), *exit = getExit(); + + // Toplevel region. + if (!exit) + return true; + + return (DT->dominates(entry, BB) + && !(DT->dominates(exit, BB) && DT->dominates(entry, exit))); +} + +bool Region::contains(const Loop *L) const { + // BBs that are not part of any loop are element of the Loop + // described by the NULL pointer. This loop is not part of any region, + // except if the region describes the whole function. + if (L == 0) + return getExit() == 0; + + if (!contains(L->getHeader())) + return false; + + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + for (SmallVectorImpl::iterator BI = ExitingBlocks.begin(), + BE = ExitingBlocks.end(); BI != BE; ++BI) + if (!contains(*BI)) + return false; + + return true; +} + +Loop *Region::outermostLoopInRegion(Loop *L) const { + if (!contains(L)) + return 0; + + while (L && contains(L->getParentLoop())) { + L = L->getParentLoop(); + } + + return L; +} + +Loop *Region::outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const { + assert(LI && BB && "LI and BB cannot be null!"); + Loop *L = LI->getLoopFor(BB); + return outermostLoopInRegion(L); +} + +BasicBlock *Region::getEnteringBlock() const { + BasicBlock *entry = getEntry(); + BasicBlock *Pred; + BasicBlock *enteringBlock = 0; + + for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE; + ++PI) { + Pred = *PI; + if (DT->getNode(Pred) && !contains(Pred)) { + if (enteringBlock) + return 0; + + enteringBlock = Pred; + } + } + + return enteringBlock; +} + +BasicBlock *Region::getExitingBlock() const { + BasicBlock *exit = getExit(); + BasicBlock *Pred; + BasicBlock *exitingBlock = 0; + + if (!exit) + return 0; + + for (pred_iterator PI = pred_begin(exit), PE = pred_end(exit); PI != PE; + ++PI) { + Pred = *PI; + if (contains(Pred)) { + if (exitingBlock) + return 0; + + exitingBlock = Pred; + } + } + + return exitingBlock; +} + +bool Region::isSimple() const { + return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock(); +} + +std::string Region::getNameStr() const { + std::string exitName; + std::string entryName; + + if (getEntry()->getName().empty()) { + raw_string_ostream OS(entryName); + + WriteAsOperand(OS, getEntry(), false); + entryName = OS.str(); + } else + entryName = getEntry()->getNameStr(); + + if (getExit()) { + if (getExit()->getName().empty()) { + raw_string_ostream OS(exitName); + + WriteAsOperand(OS, getExit(), false); + exitName = OS.str(); + } else + exitName = getExit()->getNameStr(); + } else + exitName = ""; + + return entryName + " => " + exitName; +} + +void Region::verifyBBInRegion(BasicBlock *BB) const { + if (!contains(BB)) + llvm_unreachable("Broken region found!"); + + BasicBlock *entry = getEntry(), *exit = getExit(); + + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + if (!contains(*SI) && exit != *SI) + llvm_unreachable("Broken region found!"); + + if (entry != BB) + for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); SI != SE; ++SI) + if (!contains(*SI)) + llvm_unreachable("Broken region found!"); +} + +void Region::verifyWalk(BasicBlock *BB, std::set *visited) const { + BasicBlock *exit = getExit(); + + visited->insert(BB); + + verifyBBInRegion(BB); + + for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) + if (*SI != exit && visited->find(*SI) == visited->end()) + verifyWalk(*SI, visited); +} + +void Region::verifyRegion() const { + // Only do verification when user wants to, otherwise this expensive + // check will be invoked by PassManager. + if (!VerifyRegionInfo) return; + + std::set visited; + verifyWalk(getEntry(), &visited); +} + +void Region::verifyRegionNest() const { + for (Region::const_iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->verifyRegionNest(); + + verifyRegion(); +} + +Region::block_iterator Region::block_begin() { + return GraphTraits >::nodes_begin(this); +} + +Region::block_iterator Region::block_end() { + return GraphTraits >::nodes_end(this); +} + +Region::const_block_iterator Region::block_begin() const { + return GraphTraits >::nodes_begin(this); +} + +Region::const_block_iterator Region::block_end() const { + return GraphTraits >::nodes_end(this); +} + +Region::element_iterator Region::element_begin() { + return GraphTraits::nodes_begin(this); +} + +Region::element_iterator Region::element_end() { + return GraphTraits::nodes_end(this); +} + +Region::const_element_iterator Region::element_begin() const { + return GraphTraits::nodes_begin(this); +} + +Region::const_element_iterator Region::element_end() const { + return GraphTraits::nodes_end(this); +} + +Region* Region::getSubRegionNode(BasicBlock *BB) const { + Region *R = RI->getRegionFor(BB); + + if (!R || R == this) + return 0; + + // If we pass the BB out of this region, that means our code is broken. + assert(contains(R) && "BB not in current region!"); + + while (contains(R->getParent()) && R->getParent() != this) + R = R->getParent(); + + if (R->getEntry() != BB) + return 0; + + return R; +} + +RegionNode* Region::getBBNode(BasicBlock *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + + BBNodeMapT::const_iterator at = BBNodeMap.find(BB); + + if (at != BBNodeMap.end()) + return at->second; + + RegionNode *NewNode = new RegionNode(const_cast(this), BB); + BBNodeMap.insert(std::make_pair(BB, NewNode)); + return NewNode; +} + +RegionNode* Region::getNode(BasicBlock *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + if (Region* Child = getSubRegionNode(BB)) + return Child->getNode(); + + return getBBNode(BB); +} + +void Region::transferChildrenTo(Region *To) { + for (iterator I = begin(), E = end(); I != E; ++I) { + (*I)->parent = To; + To->children.push_back(*I); + } + children.clear(); +} + +void Region::addSubRegion(Region *SubRegion, bool moveChildren) { + assert(SubRegion->parent == 0 && "SubRegion already has a parent!"); + assert(std::find(begin(), end(), SubRegion) == children.end() + && "Subregion already exists!"); + + SubRegion->parent = this; + children.push_back(SubRegion); + + if (!moveChildren) + return; + + assert(SubRegion->children.size() == 0 + && "SubRegions that contain children are not supported"); + + for (element_iterator I = element_begin(), E = element_end(); I != E; ++I) + if (!(*I)->isSubRegion()) { + BasicBlock *BB = (*I)->getNodeAs(); + + if (SubRegion->contains(BB)) + RI->setRegionFor(BB, SubRegion); + } + + std::vector Keep; + for (iterator I = begin(), E = end(); I != E; ++I) + if (SubRegion->contains(*I) && *I != SubRegion) { + SubRegion->children.push_back(*I); + (*I)->parent = SubRegion; + } else + Keep.push_back(*I); + + children.clear(); + children.insert(children.begin(), Keep.begin(), Keep.end()); +} + + +Region *Region::removeSubRegion(Region *Child) { + assert(Child->parent == this && "Child is not a child of this region!"); + Child->parent = 0; + RegionSet::iterator I = std::find(children.begin(), children.end(), Child); + assert(I != children.end() && "Region does not exit. Unable to remove."); + children.erase(children.begin()+(I-begin())); + return Child; +} + +unsigned Region::getDepth() const { + unsigned Depth = 0; + + for (Region *R = parent; R != 0; R = R->parent) + ++Depth; + + return Depth; +} + +Region *Region::getExpandedRegion() const { + unsigned NumSuccessors = exit->getTerminator()->getNumSuccessors(); + + if (NumSuccessors == 0) + return NULL; + + for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit()); + PI != PE; ++PI) + if (!DT->dominates(getEntry(), *PI)) + return NULL; + + Region *R = RI->getRegionFor(exit); + + if (R->getEntry() != exit) { + if (exit->getTerminator()->getNumSuccessors() == 1) + return new Region(getEntry(), *succ_begin(exit), RI, DT); + else + return NULL; + } + + while (R->getParent() && R->getParent()->getEntry() == exit) + R = R->getParent(); + + if (!DT->dominates(getEntry(), R->getExit())) + for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit()); + PI != PE; ++PI) + if (!DT->dominates(R->getExit(), *PI)) + return NULL; + + return new Region(getEntry(), R->getExit(), RI, DT); +} + +void Region::print(raw_ostream &OS, bool print_tree, unsigned level) const { + if (print_tree) + OS.indent(level*2) << "[" << level << "] " << getNameStr(); + else + OS.indent(level*2) << getNameStr(); + + OS << "\n"; + + + if (printStyle != PrintNone) { + OS.indent(level*2) << "{\n"; + OS.indent(level*2 + 2); + + if (printStyle == PrintBB) { + for (const_block_iterator I = block_begin(), E = block_end(); I!=E; ++I) + OS << **I << ", "; // TODO: remove the last "," + } else if (printStyle == PrintRN) { + for (const_element_iterator I = element_begin(), E = element_end(); I!=E; ++I) + OS << **I << ", "; // TODO: remove the last ", + } + + OS << "\n"; + } + + if (print_tree) + for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->print(OS, print_tree, level+1); + + if (printStyle != PrintNone) + OS.indent(level*2) << "} \n"; +} + +void Region::dump() const { + print(dbgs(), true, getDepth()); +} + +void Region::clearNodeCache() { + // Free the cached nodes. + for (BBNodeMapT::iterator I = BBNodeMap.begin(), + IE = BBNodeMap.end(); I != IE; ++I) + delete I->second; + + BBNodeMap.clear(); + for (Region::iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->clearNodeCache(); +} + +//===----------------------------------------------------------------------===// +// RegionInfo implementation +// + +bool RegionInfo::isCommonDomFrontier(BasicBlock *BB, BasicBlock *entry, + BasicBlock *exit) const { + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { + BasicBlock *P = *PI; + if (DT->dominates(entry, P) && !DT->dominates(exit, P)) + return false; + } + return true; +} + +bool RegionInfo::isRegion(BasicBlock *entry, BasicBlock *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + typedef DominanceFrontier::DomSetType DST; + + DST *entrySuccs = &DF->find(entry)->second; + + // Exit is the header of a loop that contains the entry. In this case, + // the dominance frontier must only contain the exit. + if (!DT->dominates(entry, exit)) { + for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); + SI != SE; ++SI) + if (*SI != exit && *SI != entry) + return false; + + return true; + } + + DST *exitSuccs = &DF->find(exit)->second; + + // Do not allow edges leaving the region. + for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI == exit || *SI == entry) + continue; + if (exitSuccs->find(*SI) == exitSuccs->end()) + return false; + if (!isCommonDomFrontier(*SI, entry, exit)) + return false; + } + + // Do not allow edges pointing into the region. + for (DST::iterator SI = exitSuccs->begin(), SE = exitSuccs->end(); + SI != SE; ++SI) + if (DT->properlyDominates(entry, *SI) && *SI != exit) + return false; + + + return true; +} + +void RegionInfo::insertShortCut(BasicBlock *entry, BasicBlock *exit, + BBtoBBMap *ShortCut) const { + assert(entry && exit && "entry and exit must not be null!"); + + BBtoBBMap::iterator e = ShortCut->find(exit); + + if (e == ShortCut->end()) + // No further region at exit available. + (*ShortCut)[entry] = exit; + else { + // We found a region e that starts at exit. Therefore (entry, e->second) + // is also a region, that is larger than (entry, exit). Insert the + // larger one. + BasicBlock *BB = e->second; + (*ShortCut)[entry] = BB; + } +} + +DomTreeNode* RegionInfo::getNextPostDom(DomTreeNode* N, + BBtoBBMap *ShortCut) const { + BBtoBBMap::iterator e = ShortCut->find(N->getBlock()); + + if (e == ShortCut->end()) + return N->getIDom(); + + return PDT->getNode(e->second)->getIDom(); +} + +bool RegionInfo::isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + + unsigned num_successors = succ_end(entry) - succ_begin(entry); + + if (num_successors <= 1 && exit == *(succ_begin(entry))) + return true; + + return false; +} + +void RegionInfo::updateStatistics(Region *R) { + ++numRegions; + + // TODO: Slow. Should only be enabled if -stats is used. + if (R->isSimple()) ++numSimpleRegions; +} + +Region *RegionInfo::createRegion(BasicBlock *entry, BasicBlock *exit) { + assert(entry && exit && "entry and exit must not be null!"); + + if (isTrivialRegion(entry, exit)) + return 0; + + Region *region = new Region(entry, exit, this, DT); + BBtoRegion.insert(std::make_pair(entry, region)); + + #ifdef XDEBUG + region->verifyRegion(); + #else + DEBUG(region->verifyRegion()); + #endif + + updateStatistics(region); + return region; +} + +void RegionInfo::findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut) { + assert(entry); + + DomTreeNode *N = PDT->getNode(entry); + + if (!N) + return; + + Region *lastRegion= 0; + BasicBlock *lastExit = entry; + + // As only a BasicBlock that postdominates entry can finish a region, walk the + // post dominance tree upwards. + while ((N = getNextPostDom(N, ShortCut))) { + BasicBlock *exit = N->getBlock(); + + if (!exit) + break; + + if (isRegion(entry, exit)) { + Region *newRegion = createRegion(entry, exit); + + if (lastRegion) + newRegion->addSubRegion(lastRegion); + + lastRegion = newRegion; + lastExit = exit; + } + + // This can never be a region, so stop the search. + if (!DT->dominates(entry, exit)) + break; + } + + // Tried to create regions from entry to lastExit. Next time take a + // shortcut from entry to lastExit. + if (lastExit != entry) + insertShortCut(entry, lastExit, ShortCut); +} + +void RegionInfo::scanForRegions(Function &F, BBtoBBMap *ShortCut) { + BasicBlock *entry = &(F.getEntryBlock()); + DomTreeNode *N = DT->getNode(entry); + + // Iterate over the dominance tree in post order to start with the small + // regions from the bottom of the dominance tree. If the small regions are + // detected first, detection of bigger regions is faster, as we can jump + // over the small regions. + for (po_iterator FI = po_begin(N), FE = po_end(N); FI != FE; + ++FI) { + findRegionsWithEntry(FI->getBlock(), ShortCut); + } +} + +Region *RegionInfo::getTopMostParent(Region *region) { + while (region->parent) + region = region->getParent(); + + return region; +} + +void RegionInfo::buildRegionsTree(DomTreeNode *N, Region *region) { + BasicBlock *BB = N->getBlock(); + + // Passed region exit + while (BB == region->getExit()) + region = region->getParent(); + + BBtoRegionMap::iterator it = BBtoRegion.find(BB); + + // This basic block is a start block of a region. It is already in the + // BBtoRegion relation. Only the child basic blocks have to be updated. + if (it != BBtoRegion.end()) { + Region *newRegion = it->second;; + region->addSubRegion(getTopMostParent(newRegion)); + region = newRegion; + } else { + BBtoRegion[BB] = region; + } + + for (DomTreeNode::iterator CI = N->begin(), CE = N->end(); CI != CE; ++CI) + buildRegionsTree(*CI, region); +} + +void RegionInfo::releaseMemory() { + BBtoRegion.clear(); + if (TopLevelRegion) + delete TopLevelRegion; + TopLevelRegion = 0; +} + +RegionInfo::RegionInfo() : FunctionPass(ID) { + initializeRegionInfoPass(*PassRegistry::getPassRegistry()); + TopLevelRegion = 0; +} + +RegionInfo::~RegionInfo() { + releaseMemory(); +} + +void RegionInfo::Calculate(Function &F) { + // ShortCut a function where for every BB the exit of the largest region + // starting with BB is stored. These regions can be threated as single BBS. + // This improves performance on linear CFGs. + BBtoBBMap ShortCut; + + scanForRegions(F, &ShortCut); + BasicBlock *BB = &F.getEntryBlock(); + buildRegionsTree(DT->getNode(BB), TopLevelRegion); +} + +bool RegionInfo::runOnFunction(Function &F) { + releaseMemory(); + + DT = &getAnalysis(); + PDT = &getAnalysis(); + DF = &getAnalysis(); + + TopLevelRegion = new Region(&F.getEntryBlock(), 0, this, DT, 0); + updateStatistics(TopLevelRegion); + + Calculate(F); + + return false; +} + +void RegionInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequired(); + AU.addRequired(); +} + +void RegionInfo::print(raw_ostream &OS, const Module *) const { + OS << "Region tree:\n"; + TopLevelRegion->print(OS, true, 0); + OS << "End region tree\n"; +} + +void RegionInfo::verifyAnalysis() const { + // Only do verification when user wants to, otherwise this expensive check + // will be invoked by PMDataManager::verifyPreservedAnalysis when + // a regionpass (marked PreservedAll) finish. + if (!VerifyRegionInfo) return; + + TopLevelRegion->verifyRegionNest(); +} + +// Region pass manager support. +Region *RegionInfo::getRegionFor(BasicBlock *BB) const { + BBtoRegionMap::const_iterator I= + BBtoRegion.find(BB); + return I != BBtoRegion.end() ? I->second : 0; +} + +void RegionInfo::setRegionFor(BasicBlock *BB, Region *R) { + BBtoRegion[BB] = R; +} + +Region *RegionInfo::operator[](BasicBlock *BB) const { + return getRegionFor(BB); +} + +BasicBlock *RegionInfo::getMaxRegionExit(BasicBlock *BB) const { + BasicBlock *Exit = NULL; + + while (true) { + // Get largest region that starts at BB. + Region *R = getRegionFor(BB); + while (R && R->getParent() && R->getParent()->getEntry() == BB) + R = R->getParent(); + + // Get the single exit of BB. + if (R && R->getEntry() == BB) + Exit = R->getExit(); + else if (++succ_begin(BB) == succ_end(BB)) + Exit = *succ_begin(BB); + else // No single exit exists. + return Exit; + + // Get largest region that starts at Exit. + Region *ExitR = getRegionFor(Exit); + while (ExitR && ExitR->getParent() + && ExitR->getParent()->getEntry() == Exit) + ExitR = ExitR->getParent(); + + for (pred_iterator PI = pred_begin(Exit), PE = pred_end(Exit); PI != PE; + ++PI) + if (!R->contains(*PI) && !ExitR->contains(*PI)) + break; + + // This stops infinite cycles. + if (DT->dominates(Exit, BB)) + break; + + BB = Exit; + } + + return Exit; +} + +Region* +RegionInfo::getCommonRegion(Region *A, Region *B) const { + assert (A && B && "One of the Regions is NULL"); + + if (A->contains(B)) return A; + + while (!B->contains(A)) + B = B->getParent(); + + return B; +} + +Region* +RegionInfo::getCommonRegion(SmallVectorImpl &Regions) const { + Region* ret = Regions.back(); + Regions.pop_back(); + + for (SmallVectorImpl::const_iterator I = Regions.begin(), + E = Regions.end(); I != E; ++I) + ret = getCommonRegion(ret, *I); + + return ret; +} + +Region* +RegionInfo::getCommonRegion(SmallVectorImpl &BBs) const { + Region* ret = getRegionFor(BBs.back()); + BBs.pop_back(); + + for (SmallVectorImpl::const_iterator I = BBs.begin(), + E = BBs.end(); I != E; ++I) + ret = getCommonRegion(ret, getRegionFor(*I)); + + return ret; +} + +void RegionInfo::splitBlock(BasicBlock* NewBB, BasicBlock *OldBB) +{ + Region *R = getRegionFor(OldBB); + + setRegionFor(NewBB, R); + + while (R->getEntry() == OldBB && !R->isTopLevelRegion()) { + R->replaceEntry(NewBB); + R = R->getParent(); + } + + setRegionFor(OldBB, R); +} + +char RegionInfo::ID = 0; +INITIALIZE_PASS_BEGIN(RegionInfo, "regions", + "Detect single entry single exit regions", true, true) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) +INITIALIZE_PASS_DEPENDENCY(DominanceFrontier) +INITIALIZE_PASS_END(RegionInfo, "regions", + "Detect single entry single exit regions", true, true) + +// Create methods available outside of this file, to use them +// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by +// the link time optimization. + +namespace llvm { + FunctionPass *createRegionInfoPass() { + return new RegionInfo(); + } +} + diff --git a/final/lib/Analysis/RegionPass.cpp b/final/lib/Analysis/RegionPass.cpp new file mode 100644 index 00000000000..3269dcc63d5 --- /dev/null +++ b/final/lib/Analysis/RegionPass.cpp @@ -0,0 +1,275 @@ +//===- RegionPass.cpp - Region Pass and Region Pass Manager ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements RegionPass and RGPassManager. All region optimization +// and transformation passes are derived from RegionPass. RGPassManager is +// responsible for managing RegionPasses. +// most of these codes are COPY from LoopPass.cpp +// +//===----------------------------------------------------------------------===// +#include "llvm/Analysis/RegionPass.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/Support/Timer.h" + +#define DEBUG_TYPE "regionpassmgr" +#include "llvm/Support/Debug.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// RGPassManager +// + +char RGPassManager::ID = 0; + +RGPassManager::RGPassManager(int Depth) + : FunctionPass(ID), PMDataManager(Depth) { + skipThisRegion = false; + redoThisRegion = false; + RI = NULL; + CurrentRegion = NULL; +} + +// Recurse through all subregions and all regions into RQ. +static void addRegionIntoQueue(Region *R, std::deque &RQ) { + RQ.push_back(R); + for (Region::iterator I = R->begin(), E = R->end(); I != E; ++I) + addRegionIntoQueue(*I, RQ); +} + +/// Pass Manager itself does not invalidate any analysis info. +void RGPassManager::getAnalysisUsage(AnalysisUsage &Info) const { + Info.addRequired(); + Info.setPreservesAll(); +} + +/// run - Execute all of the passes scheduled for execution. Keep track of +/// whether any of the passes modifies the function, and if so, return true. +bool RGPassManager::runOnFunction(Function &F) { + RI = &getAnalysis(); + bool Changed = false; + + // Collect inherited analysis from Module level pass manager. + populateInheritedAnalysis(TPM->activeStack); + + addRegionIntoQueue(RI->getTopLevelRegion(), RQ); + + if (RQ.empty()) // No regions, skip calling finalizers + return false; + + // Initialization + for (std::deque::const_iterator I = RQ.begin(), E = RQ.end(); + I != E; ++I) { + Region *R = *I; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *RP = (RegionPass *)getContainedPass(Index); + Changed |= RP->doInitialization(R, *this); + } + } + + // Walk Regions + while (!RQ.empty()) { + + CurrentRegion = RQ.back(); + skipThisRegion = false; + redoThisRegion = false; + + // Run all passes on the current Region. + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *P = (RegionPass*)getContainedPass(Index); + + dumpPassInfo(P, EXECUTION_MSG, ON_REGION_MSG, + CurrentRegion->getNameStr()); + dumpRequiredSet(P); + + initializeAnalysisImpl(P); + + { + PassManagerPrettyStackEntry X(P, *CurrentRegion->getEntry()); + + TimeRegion PassTimer(getPassTimer(P)); + Changed |= P->runOnRegion(CurrentRegion, *this); + } + + if (Changed) + dumpPassInfo(P, MODIFICATION_MSG, ON_REGION_MSG, + skipThisRegion ? "" : + CurrentRegion->getNameStr()); + dumpPreservedSet(P); + + if (!skipThisRegion) { + // Manually check that this region is still healthy. This is done + // instead of relying on RegionInfo::verifyRegion since RegionInfo + // is a function pass and it's really expensive to verify every + // Region in the function every time. That level of checking can be + // enabled with the -verify-region-info option. + { + TimeRegion PassTimer(getPassTimer(P)); + CurrentRegion->verifyRegion(); + } + + // Then call the regular verifyAnalysis functions. + verifyPreservedAnalysis(P); + } + + removeNotPreservedAnalysis(P); + recordAvailableAnalysis(P); + removeDeadPasses(P, + skipThisRegion ? "" : + CurrentRegion->getNameStr(), + ON_REGION_MSG); + + if (skipThisRegion) + // Do not run other passes on this region. + break; + } + + // If the region was deleted, release all the region passes. This frees up + // some memory, and avoids trouble with the pass manager trying to call + // verifyAnalysis on them. + if (skipThisRegion) + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + freePass(P, "", ON_REGION_MSG); + } + + // Pop the region from queue after running all passes. + RQ.pop_back(); + + if (redoThisRegion) + RQ.push_back(CurrentRegion); + + // Free all region nodes created in region passes. + RI->clearNodeCache(); + } + + // Finalization + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + RegionPass *P = (RegionPass*)getContainedPass(Index); + Changed |= P->doFinalization(); + } + + // Print the region tree after all pass. + DEBUG( + dbgs() << "\nRegion tree of function " << F.getName() + << " after all region Pass:\n"; + RI->dump(); + dbgs() << "\n"; + ); + + return Changed; +} + +/// Print passes managed by this manager +void RGPassManager::dumpPassStructure(unsigned Offset) { + errs().indent(Offset*2) << "Region Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } +} + +namespace { +//===----------------------------------------------------------------------===// +// PrintRegionPass +class PrintRegionPass : public RegionPass { +private: + std::string Banner; + raw_ostream &Out; // raw_ostream to print on. + +public: + static char ID; + PrintRegionPass() : RegionPass(ID), Out(dbgs()) {} + PrintRegionPass(const std::string &B, raw_ostream &o) + : RegionPass(ID), Banner(B), Out(o) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual bool runOnRegion(Region *R, RGPassManager &RGM) { + Out << Banner; + for (Region::block_iterator I = R->block_begin(), E = R->block_end(); + I != E; ++I) + (*I)->getEntry()->print(Out); + + return false; + } +}; + +char PrintRegionPass::ID = 0; +} //end anonymous namespace + +//===----------------------------------------------------------------------===// +// RegionPass + +// Check if this pass is suitable for the current RGPassManager, if +// available. This pass P is not suitable for a RGPassManager if P +// is not preserving higher level analysis info used by other +// RGPassManager passes. In such case, pop RGPassManager from the +// stack. This will force assignPassManager() to create new +// LPPassManger as expected. +void RegionPass::preparePassManager(PMStack &PMS) { + + // Find RGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_RegionPassManager) + PMS.pop(); + + + // If this pass is destroying high level information that is used + // by other passes that are managed by LPM then do not insert + // this pass in current LPM. Use new RGPassManager. + if (PMS.top()->getPassManagerType() == PMT_RegionPassManager && + !PMS.top()->preserveHigherLevelAnalysis(this)) + PMS.pop(); +} + +/// Assign pass manager to manage this pass. +void RegionPass::assignPassManager(PMStack &PMS, + PassManagerType PreferredType) { + // Find RGPassManager + while (!PMS.empty() && + PMS.top()->getPassManagerType() > PMT_RegionPassManager) + PMS.pop(); + + RGPassManager *RGPM; + + // Create new Region Pass Manager if it does not exist. + if (PMS.top()->getPassManagerType() == PMT_RegionPassManager) + RGPM = (RGPassManager*)PMS.top(); + else { + + assert (!PMS.empty() && "Unable to create Region Pass Manager"); + PMDataManager *PMD = PMS.top(); + + // [1] Create new Call Graph Pass Manager + RGPM = new RGPassManager(PMD->getDepth() + 1); + RGPM->populateInheritedAnalysis(PMS); + + // [2] Set up new manager's top level manager + PMTopLevelManager *TPM = PMD->getTopLevelManager(); + TPM->addIndirectPassManager(RGPM); + + // [3] Assign manager to manage this new manager. This may create + // and push new managers into PMS + TPM->schedulePass(RGPM); + + // [4] Push new manager into PMS + PMS.push(RGPM); + } + + RGPM->add(this); +} + +/// Get the printer pass +Pass *RegionPass::createPrinterPass(raw_ostream &O, + const std::string &Banner) const { + return new PrintRegionPass(Banner, O); +} diff --git a/final/lib/Analysis/RegionPrinter.cpp b/final/lib/Analysis/RegionPrinter.cpp new file mode 100644 index 00000000000..a1730b0a3ca --- /dev/null +++ b/final/lib/Analysis/RegionPrinter.cpp @@ -0,0 +1,220 @@ +//===- RegionPrinter.cpp - Print regions tree pass ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Print out the region tree of a function using dotty/graphviz. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/Analysis/RegionPrinter.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/DOTGraphTraitsPass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +/// onlySimpleRegion - Show only the simple regions in the RegionViewer. +static cl::opt +onlySimpleRegions("only-simple-regions", + cl::desc("Show only simple regions in the graphviz viewer"), + cl::Hidden, + cl::init(false)); + +namespace llvm { +template<> +struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) + : DefaultDOTGraphTraits(isSimple) {} + + std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { + + if (!Node->isSubRegion()) { + BasicBlock *BB = Node->getNodeAs(); + + if (isSimple()) + return DOTGraphTraits + ::getSimpleNodeLabel(BB, BB->getParent()); + else + return DOTGraphTraits + ::getCompleteNodeLabel(BB, BB->getParent()); + } + + return "Not implemented"; + } +}; + +template<> +struct DOTGraphTraits : public DOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) + : DOTGraphTraits(isSimple) {} + + static std::string getGraphName(RegionInfo *DT) { + return "Region Graph"; + } + + std::string getNodeLabel(RegionNode *Node, RegionInfo *G) { + return DOTGraphTraits::getNodeLabel(Node, + G->getTopLevelRegion()); + } + + std::string getEdgeAttributes(RegionNode *srcNode, + GraphTraits::ChildIteratorType CI, RegionInfo *RI) { + + RegionNode *destNode = *CI; + + if (srcNode->isSubRegion() || destNode->isSubRegion()) + return ""; + + // In case of a backedge, do not use it to define the layout of the nodes. + BasicBlock *srcBB = srcNode->getNodeAs(); + BasicBlock *destBB = destNode->getNodeAs(); + + Region *R = RI->getRegionFor(destBB); + + while (R && R->getParent()) + if (R->getParent()->getEntry() == destBB) + R = R->getParent(); + else + break; + + if (R->getEntry() == destBB && R->contains(srcBB)) + return "constraint=false"; + + return ""; + } + + // Print the cluster of the subregions. This groups the single basic blocks + // and adds a different background color for each group. + static void printRegionCluster(const Region *R, GraphWriter &GW, + unsigned depth = 0) { + raw_ostream &O = GW.getOStream(); + O.indent(2 * depth) << "subgraph cluster_" << static_cast(R) + << " {\n"; + O.indent(2 * (depth + 1)) << "label = \"\";\n"; + + if (!onlySimpleRegions || R->isSimple()) { + O.indent(2 * (depth + 1)) << "style = filled;\n"; + O.indent(2 * (depth + 1)) << "color = " + << ((R->getDepth() * 2 % 12) + 1) << "\n"; + + } else { + O.indent(2 * (depth + 1)) << "style = solid;\n"; + O.indent(2 * (depth + 1)) << "color = " + << ((R->getDepth() * 2 % 12) + 2) << "\n"; + } + + for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) + printRegionCluster(*RI, GW, depth + 1); + + RegionInfo *RI = R->getRegionInfo(); + + for (Region::const_block_iterator BI = R->block_begin(), + BE = R->block_end(); BI != BE; ++BI) { + BasicBlock *BB = (*BI)->getNodeAs(); + if (RI->getRegionFor(BB) == R) + O.indent(2 * (depth + 1)) << "Node" + << static_cast(RI->getTopLevelRegion()->getBBNode(BB)) + << ";\n"; + } + + O.indent(2 * depth) << "}\n"; + } + + static void addCustomGraphFeatures(const RegionInfo* RI, + GraphWriter &GW) { + raw_ostream &O = GW.getOStream(); + O << "\tcolorscheme = \"paired12\"\n"; + printRegionCluster(RI->getTopLevelRegion(), GW, 4); + } +}; +} //end namespace llvm + +namespace { + +struct RegionViewer + : public DOTGraphTraitsViewer { + static char ID; + RegionViewer() : DOTGraphTraitsViewer("reg", ID){ + initializeRegionViewerPass(*PassRegistry::getPassRegistry()); + } +}; +char RegionViewer::ID = 0; + +struct RegionOnlyViewer + : public DOTGraphTraitsViewer { + static char ID; + RegionOnlyViewer() : DOTGraphTraitsViewer("regonly", ID) { + initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); + } +}; +char RegionOnlyViewer::ID = 0; + +struct RegionPrinter + : public DOTGraphTraitsPrinter { + static char ID; + RegionPrinter() : + DOTGraphTraitsPrinter("reg", ID) { + initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); + } +}; +char RegionPrinter::ID = 0; +} //end anonymous namespace + +INITIALIZE_PASS(RegionPrinter, "dot-regions", + "Print regions of function to 'dot' file", true, true) + +INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", + true, true) + +INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", + "View regions of function (with no function bodies)", + true, true) + +namespace { + +struct RegionOnlyPrinter + : public DOTGraphTraitsPrinter { + static char ID; + RegionOnlyPrinter() : + DOTGraphTraitsPrinter("reg", ID) { + initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); + } +}; + +} + +char RegionOnlyPrinter::ID = 0; +INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", + "Print regions of function to 'dot' file " + "(with no function bodies)", + true, true) + +FunctionPass* llvm::createRegionViewerPass() { + return new RegionViewer(); +} + +FunctionPass* llvm::createRegionOnlyViewerPass() { + return new RegionOnlyViewer(); +} + +FunctionPass* llvm::createRegionPrinterPass() { + return new RegionPrinter(); +} + +FunctionPass* llvm::createRegionOnlyPrinterPass() { + return new RegionOnlyPrinter(); +} + diff --git a/final/lib/Analysis/ScalarEvolution.cpp b/final/lib/Analysis/ScalarEvolution.cpp new file mode 100644 index 00000000000..62244ccb3a0 --- /dev/null +++ b/final/lib/Analysis/ScalarEvolution.cpp @@ -0,0 +1,6317 @@ +//===- ScalarEvolution.cpp - Scalar Evolution Analysis ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the scalar evolution analysis +// engine, which is used primarily to analyze expressions involving induction +// variables in loops. +// +// There are several aspects to this library. First is the representation of +// scalar expressions, which are represented as subclasses of the SCEV class. +// These classes are used to represent certain types of subexpressions that we +// can handle. We only create one SCEV of a particular shape, so +// pointer-comparisons for equality are legal. +// +// One important aspect of the SCEV objects is that they are never cyclic, even +// if there is a cycle in the dataflow for an expression (ie, a PHI node). If +// the PHI node is one of the idioms that we can represent (e.g., a polynomial +// recurrence) then we represent it directly as a recurrence node, otherwise we +// represent it as a SCEVUnknown node. +// +// In addition to being able to represent expressions of various types, we also +// have folders that are used to build the *canonical* representation for a +// particular expression. These folders are capable of using a variety of +// rewrite rules to simplify the expressions. +// +// Once the folders are defined, we can implement the more interesting +// higher-level code, such as the code that recognizes PHI nodes of various +// types, computes the execution count of a loop, etc. +// +// TODO: We should use these routines and value representations to implement +// dependence analysis! +// +//===----------------------------------------------------------------------===// +// +// There are several good references for the techniques used in this analysis. +// +// Chains of recurrences -- a method to expedite the evaluation +// of closed-form functions +// Olaf Bachmann, Paul S. Wang, Eugene V. Zima +// +// On computational properties of chains of recurrences +// Eugene V. Zima +// +// Symbolic Evaluation of Chains of Recurrences for Loop Optimization +// Robert A. van Engelen +// +// Efficient Symbolic Analysis for Optimizing Compilers +// Robert A. van Engelen +// +// Using the chains of recurrences algebra for data dependence testing and +// induction variable substitution +// MS Thesis, Johnie Birch +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "scalar-evolution" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; + +STATISTIC(NumArrayLenItCounts, + "Number of trip counts computed with array length"); +STATISTIC(NumTripCountsComputed, + "Number of loops with predictable loop counts"); +STATISTIC(NumTripCountsNotComputed, + "Number of loops without predictable loop counts"); +STATISTIC(NumBruteForceTripCountsComputed, + "Number of loops with trip counts computed by force"); + +static cl::opt +MaxBruteForceIterations("scalar-evolution-max-iterations", cl::ReallyHidden, + cl::desc("Maximum number of iterations SCEV will " + "symbolically execute a constant " + "derived loop"), + cl::init(100)); + +INITIALIZE_PASS_BEGIN(ScalarEvolution, "scalar-evolution", + "Scalar Evolution Analysis", false, true) +INITIALIZE_PASS_DEPENDENCY(LoopInfo) +INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_END(ScalarEvolution, "scalar-evolution", + "Scalar Evolution Analysis", false, true) +char ScalarEvolution::ID = 0; + +//===----------------------------------------------------------------------===// +// SCEV class definitions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Implementation of the SCEV class. +// + +void SCEV::dump() const { + print(dbgs()); + dbgs() << '\n'; +} + +void SCEV::print(raw_ostream &OS) const { + switch (getSCEVType()) { + case scConstant: + WriteAsOperand(OS, cast(this)->getValue(), false); + return; + case scTruncate: { + const SCEVTruncateExpr *Trunc = cast(this); + const SCEV *Op = Trunc->getOperand(); + OS << "(trunc " << *Op->getType() << " " << *Op << " to " + << *Trunc->getType() << ")"; + return; + } + case scZeroExtend: { + const SCEVZeroExtendExpr *ZExt = cast(this); + const SCEV *Op = ZExt->getOperand(); + OS << "(zext " << *Op->getType() << " " << *Op << " to " + << *ZExt->getType() << ")"; + return; + } + case scSignExtend: { + const SCEVSignExtendExpr *SExt = cast(this); + const SCEV *Op = SExt->getOperand(); + OS << "(sext " << *Op->getType() << " " << *Op << " to " + << *SExt->getType() << ")"; + return; + } + case scAddRecExpr: { + const SCEVAddRecExpr *AR = cast(this); + OS << "{" << *AR->getOperand(0); + for (unsigned i = 1, e = AR->getNumOperands(); i != e; ++i) + OS << ",+," << *AR->getOperand(i); + OS << "}<"; + if (AR->hasNoUnsignedWrap()) + OS << "nuw><"; + if (AR->hasNoSignedWrap()) + OS << "nsw><"; + WriteAsOperand(OS, AR->getLoop()->getHeader(), /*PrintType=*/false); + OS << ">"; + return; + } + case scAddExpr: + case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: { + const SCEVNAryExpr *NAry = cast(this); + const char *OpStr = 0; + switch (NAry->getSCEVType()) { + case scAddExpr: OpStr = " + "; break; + case scMulExpr: OpStr = " * "; break; + case scUMaxExpr: OpStr = " umax "; break; + case scSMaxExpr: OpStr = " smax "; break; + } + OS << "("; + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); + I != E; ++I) { + OS << **I; + if (llvm::next(I) != E) + OS << OpStr; + } + OS << ")"; + return; + } + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast(this); + OS << "(" << *UDiv->getLHS() << " /u " << *UDiv->getRHS() << ")"; + return; + } + case scUnknown: { + const SCEVUnknown *U = cast(this); + const Type *AllocTy; + if (U->isSizeOf(AllocTy)) { + OS << "sizeof(" << *AllocTy << ")"; + return; + } + if (U->isAlignOf(AllocTy)) { + OS << "alignof(" << *AllocTy << ")"; + return; + } + + const Type *CTy; + Constant *FieldNo; + if (U->isOffsetOf(CTy, FieldNo)) { + OS << "offsetof(" << *CTy << ", "; + WriteAsOperand(OS, FieldNo, false); + OS << ")"; + return; + } + + // Otherwise just print it normally. + WriteAsOperand(OS, U->getValue(), false); + return; + } + case scCouldNotCompute: + OS << "***COULDNOTCOMPUTE***"; + return; + default: break; + } + llvm_unreachable("Unknown SCEV kind!"); +} + +const Type *SCEV::getType() const { + switch (getSCEVType()) { + case scConstant: + return cast(this)->getType(); + case scTruncate: + case scZeroExtend: + case scSignExtend: + return cast(this)->getType(); + case scAddRecExpr: + case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: + return cast(this)->getType(); + case scAddExpr: + return cast(this)->getType(); + case scUDivExpr: + return cast(this)->getType(); + case scUnknown: + return cast(this)->getType(); + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return 0; + default: break; + } + llvm_unreachable("Unknown SCEV kind!"); + return 0; +} + +bool SCEV::isZero() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isZero(); + return false; +} + +bool SCEV::isOne() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isOne(); + return false; +} + +bool SCEV::isAllOnesValue() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isAllOnesValue(); + return false; +} + +SCEVCouldNotCompute::SCEVCouldNotCompute() : + SCEV(FoldingSetNodeIDRef(), scCouldNotCompute) {} + +bool SCEVCouldNotCompute::classof(const SCEV *S) { + return S->getSCEVType() == scCouldNotCompute; +} + +const SCEV *ScalarEvolution::getConstant(ConstantInt *V) { + FoldingSetNodeID ID; + ID.AddInteger(scConstant); + ID.AddPointer(V); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = new (SCEVAllocator) SCEVConstant(ID.Intern(SCEVAllocator), V); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getConstant(const APInt& Val) { + return getConstant(ConstantInt::get(getContext(), Val)); +} + +const SCEV * +ScalarEvolution::getConstant(const Type *Ty, uint64_t V, bool isSigned) { + const IntegerType *ITy = cast(getEffectiveSCEVType(Ty)); + return getConstant(ConstantInt::get(ITy, V, isSigned)); +} + +SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID, + unsigned SCEVTy, const SCEV *op, const Type *ty) + : SCEV(ID, SCEVTy), Op(op), Ty(ty) {} + +SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scTruncate, op, ty) { + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot truncate non-integer value!"); +} + +SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scZeroExtend, op, ty) { + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot zero extend non-integer value!"); +} + +SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, + const SCEV *op, const Type *ty) + : SCEVCastExpr(ID, scSignExtend, op, ty) { + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot sign extend non-integer value!"); +} + +void SCEVUnknown::deleted() { + // Clear this SCEVUnknown from various maps. + SE->forgetMemoizedResults(this); + + // Remove this SCEVUnknown from the uniquing map. + SE->UniqueSCEVs.RemoveNode(this); + + // Release the value. + setValPtr(0); +} + +void SCEVUnknown::allUsesReplacedWith(Value *New) { + // Clear this SCEVUnknown from various maps. + SE->forgetMemoizedResults(this); + + // Remove this SCEVUnknown from the uniquing map. + SE->UniqueSCEVs.RemoveNode(this); + + // Update this SCEVUnknown to point to the new value. This is needed + // because there may still be outstanding SCEVs which still point to + // this SCEVUnknown. + setValPtr(New); +} + +bool SCEVUnknown::isSizeOf(const Type *&AllocTy) const { + if (ConstantExpr *VCE = dyn_cast(getValue())) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr && + CE->getOperand(0)->isNullValue() && + CE->getNumOperands() == 2) + if (ConstantInt *CI = dyn_cast(CE->getOperand(1))) + if (CI->isOne()) { + AllocTy = cast(CE->getOperand(0)->getType()) + ->getElementType(); + return true; + } + + return false; +} + +bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { + if (ConstantExpr *VCE = dyn_cast(getValue())) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr && + CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast(CE->getOperand(0)->getType())->getElementType(); + if (const StructType *STy = dyn_cast(Ty)) + if (!STy->isPacked() && + CE->getNumOperands() == 3 && + CE->getOperand(1)->isNullValue()) { + if (ConstantInt *CI = dyn_cast(CE->getOperand(2))) + if (CI->isOne() && + STy->getNumElements() == 2 && + STy->getElementType(0)->isIntegerTy(1)) { + AllocTy = STy->getElementType(1); + return true; + } + } + } + + return false; +} + +bool SCEVUnknown::isOffsetOf(const Type *&CTy, Constant *&FieldNo) const { + if (ConstantExpr *VCE = dyn_cast(getValue())) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr && + CE->getNumOperands() == 3 && + CE->getOperand(0)->isNullValue() && + CE->getOperand(1)->isNullValue()) { + const Type *Ty = + cast(CE->getOperand(0)->getType())->getElementType(); + // Ignore vector types here so that ScalarEvolutionExpander doesn't + // emit getelementptrs that index into vectors. + if (Ty->isStructTy() || Ty->isArrayTy()) { + CTy = Ty; + FieldNo = CE->getOperand(2); + return true; + } + } + + return false; +} + +//===----------------------------------------------------------------------===// +// SCEV Utilities +//===----------------------------------------------------------------------===// + +namespace { + /// SCEVComplexityCompare - Return true if the complexity of the LHS is less + /// than the complexity of the RHS. This comparator is used to canonicalize + /// expressions. + class SCEVComplexityCompare { + const LoopInfo *const LI; + public: + explicit SCEVComplexityCompare(const LoopInfo *li) : LI(li) {} + + // Return true or false if LHS is less than, or at least RHS, respectively. + bool operator()(const SCEV *LHS, const SCEV *RHS) const { + return compare(LHS, RHS) < 0; + } + + // Return negative, zero, or positive, if LHS is less than, equal to, or + // greater than RHS, respectively. A three-way result allows recursive + // comparisons to be more efficient. + int compare(const SCEV *LHS, const SCEV *RHS) const { + // Fast-path: SCEVs are uniqued so we can do a quick equality check. + if (LHS == RHS) + return 0; + + // Primarily, sort the SCEVs by their getSCEVType(). + unsigned LType = LHS->getSCEVType(), RType = RHS->getSCEVType(); + if (LType != RType) + return (int)LType - (int)RType; + + // Aside from the getSCEVType() ordering, the particular ordering + // isn't very important except that it's beneficial to be consistent, + // so that (a + b) and (b + a) don't end up as different expressions. + switch (LType) { + case scUnknown: { + const SCEVUnknown *LU = cast(LHS); + const SCEVUnknown *RU = cast(RHS); + + // Sort SCEVUnknown values with some loose heuristics. TODO: This is + // not as complete as it could be. + const Value *LV = LU->getValue(), *RV = RU->getValue(); + + // Order pointer values after integer values. This helps SCEVExpander + // form GEPs. + bool LIsPointer = LV->getType()->isPointerTy(), + RIsPointer = RV->getType()->isPointerTy(); + if (LIsPointer != RIsPointer) + return (int)LIsPointer - (int)RIsPointer; + + // Compare getValueID values. + unsigned LID = LV->getValueID(), + RID = RV->getValueID(); + if (LID != RID) + return (int)LID - (int)RID; + + // Sort arguments by their position. + if (const Argument *LA = dyn_cast(LV)) { + const Argument *RA = cast(RV); + unsigned LArgNo = LA->getArgNo(), RArgNo = RA->getArgNo(); + return (int)LArgNo - (int)RArgNo; + } + + // For instructions, compare their loop depth, and their operand + // count. This is pretty loose. + if (const Instruction *LInst = dyn_cast(LV)) { + const Instruction *RInst = cast(RV); + + // Compare loop depths. + const BasicBlock *LParent = LInst->getParent(), + *RParent = RInst->getParent(); + if (LParent != RParent) { + unsigned LDepth = LI->getLoopDepth(LParent), + RDepth = LI->getLoopDepth(RParent); + if (LDepth != RDepth) + return (int)LDepth - (int)RDepth; + } + + // Compare the number of operands. + unsigned LNumOps = LInst->getNumOperands(), + RNumOps = RInst->getNumOperands(); + return (int)LNumOps - (int)RNumOps; + } + + return 0; + } + + case scConstant: { + const SCEVConstant *LC = cast(LHS); + const SCEVConstant *RC = cast(RHS); + + // Compare constant values. + const APInt &LA = LC->getValue()->getValue(); + const APInt &RA = RC->getValue()->getValue(); + unsigned LBitWidth = LA.getBitWidth(), RBitWidth = RA.getBitWidth(); + if (LBitWidth != RBitWidth) + return (int)LBitWidth - (int)RBitWidth; + return LA.ult(RA) ? -1 : 1; + } + + case scAddRecExpr: { + const SCEVAddRecExpr *LA = cast(LHS); + const SCEVAddRecExpr *RA = cast(RHS); + + // Compare addrec loop depths. + const Loop *LLoop = LA->getLoop(), *RLoop = RA->getLoop(); + if (LLoop != RLoop) { + unsigned LDepth = LLoop->getLoopDepth(), + RDepth = RLoop->getLoopDepth(); + if (LDepth != RDepth) + return (int)LDepth - (int)RDepth; + } + + // Addrec complexity grows with operand count. + unsigned LNumOps = LA->getNumOperands(), RNumOps = RA->getNumOperands(); + if (LNumOps != RNumOps) + return (int)LNumOps - (int)RNumOps; + + // Lexicographically compare. + for (unsigned i = 0; i != LNumOps; ++i) { + long X = compare(LA->getOperand(i), RA->getOperand(i)); + if (X != 0) + return X; + } + + return 0; + } + + case scAddExpr: + case scMulExpr: + case scSMaxExpr: + case scUMaxExpr: { + const SCEVNAryExpr *LC = cast(LHS); + const SCEVNAryExpr *RC = cast(RHS); + + // Lexicographically compare n-ary expressions. + unsigned LNumOps = LC->getNumOperands(), RNumOps = RC->getNumOperands(); + for (unsigned i = 0; i != LNumOps; ++i) { + if (i >= RNumOps) + return 1; + long X = compare(LC->getOperand(i), RC->getOperand(i)); + if (X != 0) + return X; + } + return (int)LNumOps - (int)RNumOps; + } + + case scUDivExpr: { + const SCEVUDivExpr *LC = cast(LHS); + const SCEVUDivExpr *RC = cast(RHS); + + // Lexicographically compare udiv expressions. + long X = compare(LC->getLHS(), RC->getLHS()); + if (X != 0) + return X; + return compare(LC->getRHS(), RC->getRHS()); + } + + case scTruncate: + case scZeroExtend: + case scSignExtend: { + const SCEVCastExpr *LC = cast(LHS); + const SCEVCastExpr *RC = cast(RHS); + + // Compare cast expressions by operand. + return compare(LC->getOperand(), RC->getOperand()); + } + + default: + break; + } + + llvm_unreachable("Unknown SCEV kind!"); + return 0; + } + }; +} + +/// GroupByComplexity - Given a list of SCEV objects, order them by their +/// complexity, and group objects of the same complexity together by value. +/// When this routine is finished, we know that any duplicates in the vector are +/// consecutive and that complexity is monotonically increasing. +/// +/// Note that we go take special precautions to ensure that we get deterministic +/// results from this routine. In other words, we don't want the results of +/// this to depend on where the addresses of various SCEV objects happened to +/// land in memory. +/// +static void GroupByComplexity(SmallVectorImpl &Ops, + LoopInfo *LI) { + if (Ops.size() < 2) return; // Noop + if (Ops.size() == 2) { + // This is the common case, which also happens to be trivially simple. + // Special case it. + const SCEV *&LHS = Ops[0], *&RHS = Ops[1]; + if (SCEVComplexityCompare(LI)(RHS, LHS)) + std::swap(LHS, RHS); + return; + } + + // Do the rough sort by complexity. + std::stable_sort(Ops.begin(), Ops.end(), SCEVComplexityCompare(LI)); + + // Now that we are sorted by complexity, group elements of the same + // complexity. Note that this is, at worst, N^2, but the vector is likely to + // be extremely short in practice. Note that we take this approach because we + // do not want to depend on the addresses of the objects we are grouping. + for (unsigned i = 0, e = Ops.size(); i != e-2; ++i) { + const SCEV *S = Ops[i]; + unsigned Complexity = S->getSCEVType(); + + // If there are any objects of the same complexity and same value as this + // one, group them. + for (unsigned j = i+1; j != e && Ops[j]->getSCEVType() == Complexity; ++j) { + if (Ops[j] == S) { // Found a duplicate. + // Move it to immediately after i'th element. + std::swap(Ops[i+1], Ops[j]); + ++i; // no need to rescan it. + if (i == e-2) return; // Done! + } + } + } +} + + + +//===----------------------------------------------------------------------===// +// Simple SCEV method implementations +//===----------------------------------------------------------------------===// + +/// BinomialCoefficient - Compute BC(It, K). The result has width W. +/// Assume, K > 0. +static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, + ScalarEvolution &SE, + const Type* ResultTy) { + // Handle the simplest case efficiently. + if (K == 1) + return SE.getTruncateOrZeroExtend(It, ResultTy); + + // We are using the following formula for BC(It, K): + // + // BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / K! + // + // Suppose, W is the bitwidth of the return value. We must be prepared for + // overflow. Hence, we must assure that the result of our computation is + // equal to the accurate one modulo 2^W. Unfortunately, division isn't + // safe in modular arithmetic. + // + // However, this code doesn't use exactly that formula; the formula it uses + // is something like the following, where T is the number of factors of 2 in + // K! (i.e. trailing zeros in the binary representation of K!), and ^ is + // exponentiation: + // + // BC(It, K) = (It * (It - 1) * ... * (It - K + 1)) / 2^T / (K! / 2^T) + // + // This formula is trivially equivalent to the previous formula. However, + // this formula can be implemented much more efficiently. The trick is that + // K! / 2^T is odd, and exact division by an odd number *is* safe in modular + // arithmetic. To do exact division in modular arithmetic, all we have + // to do is multiply by the inverse. Therefore, this step can be done at + // width W. + // + // The next issue is how to safely do the division by 2^T. The way this + // is done is by doing the multiplication step at a width of at least W + T + // bits. This way, the bottom W+T bits of the product are accurate. Then, + // when we perform the division by 2^T (which is equivalent to a right shift + // by T), the bottom W bits are accurate. Extra bits are okay; they'll get + // truncated out after the division by 2^T. + // + // In comparison to just directly using the first formula, this technique + // is much more efficient; using the first formula requires W * K bits, + // but this formula less than W + K bits. Also, the first formula requires + // a division step, whereas this formula only requires multiplies and shifts. + // + // It doesn't matter whether the subtraction step is done in the calculation + // width or the input iteration count's width; if the subtraction overflows, + // the result must be zero anyway. We prefer here to do it in the width of + // the induction variable because it helps a lot for certain cases; CodeGen + // isn't smart enough to ignore the overflow, which leads to much less + // efficient code if the width of the subtraction is wider than the native + // register width. + // + // (It's possible to not widen at all by pulling out factors of 2 before + // the multiplication; for example, K=2 can be calculated as + // It/2*(It+(It*INT_MIN/INT_MIN)+-1). However, it requires + // extra arithmetic, so it's not an obvious win, and it gets + // much more complicated for K > 3.) + + // Protection from insane SCEVs; this bound is conservative, + // but it probably doesn't matter. + if (K > 1000) + return SE.getCouldNotCompute(); + + unsigned W = SE.getTypeSizeInBits(ResultTy); + + // Calculate K! / 2^T and T; we divide out the factors of two before + // multiplying for calculating K! / 2^T to avoid overflow. + // Other overflow doesn't matter because we only care about the bottom + // W bits of the result. + APInt OddFactorial(W, 1); + unsigned T = 1; + for (unsigned i = 3; i <= K; ++i) { + APInt Mult(W, i); + unsigned TwoFactors = Mult.countTrailingZeros(); + T += TwoFactors; + Mult = Mult.lshr(TwoFactors); + OddFactorial *= Mult; + } + + // We need at least W + T bits for the multiplication step + unsigned CalculationBits = W + T; + + // Calculate 2^T, at width T+W. + APInt DivFactor = APInt(CalculationBits, 1).shl(T); + + // Calculate the multiplicative inverse of K! / 2^T; + // this multiplication factor will perform the exact division by + // K! / 2^T. + APInt Mod = APInt::getSignedMinValue(W+1); + APInt MultiplyFactor = OddFactorial.zext(W+1); + MultiplyFactor = MultiplyFactor.multiplicativeInverse(Mod); + MultiplyFactor = MultiplyFactor.trunc(W); + + // Calculate the product, at width T+W + const IntegerType *CalculationTy = IntegerType::get(SE.getContext(), + CalculationBits); + const SCEV *Dividend = SE.getTruncateOrZeroExtend(It, CalculationTy); + for (unsigned i = 1; i != K; ++i) { + const SCEV *S = SE.getMinusSCEV(It, SE.getConstant(It->getType(), i)); + Dividend = SE.getMulExpr(Dividend, + SE.getTruncateOrZeroExtend(S, CalculationTy)); + } + + // Divide by 2^T + const SCEV *DivResult = SE.getUDivExpr(Dividend, SE.getConstant(DivFactor)); + + // Truncate the result, and divide by K! / 2^T. + + return SE.getMulExpr(SE.getConstant(MultiplyFactor), + SE.getTruncateOrZeroExtend(DivResult, ResultTy)); +} + +/// evaluateAtIteration - Return the value of this chain of recurrences at +/// the specified iteration number. We can evaluate this recurrence by +/// multiplying each element in the chain by the binomial coefficient +/// corresponding to it. In other words, we can evaluate {A,+,B,+,C,+,D} as: +/// +/// A*BC(It, 0) + B*BC(It, 1) + C*BC(It, 2) + D*BC(It, 3) +/// +/// where BC(It, k) stands for binomial coefficient. +/// +const SCEV *SCEVAddRecExpr::evaluateAtIteration(const SCEV *It, + ScalarEvolution &SE) const { + const SCEV *Result = getStart(); + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + // The computation is correct in the face of overflow provided that the + // multiplication is performed _after_ the evaluation of the binomial + // coefficient. + const SCEV *Coeff = BinomialCoefficient(It, i, SE, getType()); + if (isa(Coeff)) + return Coeff; + + Result = SE.getAddExpr(Result, SE.getMulExpr(getOperand(i), Coeff)); + } + return Result; +} + +//===----------------------------------------------------------------------===// +// SCEV Expression folder implementations +//===----------------------------------------------------------------------===// + +const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) > getTypeSizeInBits(Ty) && + "This is not a truncating conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + FoldingSetNodeID ID; + ID.AddInteger(scTruncate); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) + return getConstant( + cast(ConstantExpr::getTrunc(SC->getValue(), + getEffectiveSCEVType(Ty)))); + + // trunc(trunc(x)) --> trunc(x) + if (const SCEVTruncateExpr *ST = dyn_cast(Op)) + return getTruncateExpr(ST->getOperand(), Ty); + + // trunc(sext(x)) --> sext(x) if widening or trunc(x) if narrowing + if (const SCEVSignExtendExpr *SS = dyn_cast(Op)) + return getTruncateOrSignExtend(SS->getOperand(), Ty); + + // trunc(zext(x)) --> zext(x) if widening or trunc(x) if narrowing + if (const SCEVZeroExtendExpr *SZ = dyn_cast(Op)) + return getTruncateOrZeroExtend(SZ->getOperand(), Ty); + + // trunc(x1+x2+...+xN) --> trunc(x1)+trunc(x2)+...+trunc(xN) if we can + // eliminate all the truncates. + if (const SCEVAddExpr *SA = dyn_cast(Op)) { + SmallVector Operands; + bool hasTrunc = false; + for (unsigned i = 0, e = SA->getNumOperands(); i != e && !hasTrunc; ++i) { + const SCEV *S = getTruncateExpr(SA->getOperand(i), Ty); + hasTrunc = isa(S); + Operands.push_back(S); + } + if (!hasTrunc) + return getAddExpr(Operands, false, false); + UniqueSCEVs.FindNodeOrInsertPos(ID, IP); // Mutates IP, returns NULL. + } + + // trunc(x1*x2*...*xN) --> trunc(x1)*trunc(x2)*...*trunc(xN) if we can + // eliminate all the truncates. + if (const SCEVMulExpr *SM = dyn_cast(Op)) { + SmallVector Operands; + bool hasTrunc = false; + for (unsigned i = 0, e = SM->getNumOperands(); i != e && !hasTrunc; ++i) { + const SCEV *S = getTruncateExpr(SM->getOperand(i), Ty); + hasTrunc = isa(S); + Operands.push_back(S); + } + if (!hasTrunc) + return getMulExpr(Operands, false, false); + UniqueSCEVs.FindNodeOrInsertPos(ID, IP); // Mutates IP, returns NULL. + } + + // If the input value is a chrec scev, truncate the chrec's operands. + if (const SCEVAddRecExpr *AddRec = dyn_cast(Op)) { + SmallVector Operands; + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) + Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty)); + return getAddRecExpr(Operands, AddRec->getLoop()); + } + + // As a special case, fold trunc(undef) to undef. We don't want to + // know too much about SCEVUnknowns, but this special case is handy + // and harmless. + if (const SCEVUnknown *U = dyn_cast(Op)) + if (isa(U->getValue())) + return getSCEV(UndefValue::get(Ty)); + + // The cast wasn't folded; create an explicit cast node. We can reuse + // the existing insert position since if we get here, we won't have + // made any changes which would invalidate it. + SCEV *S = new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator), + Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) + return getConstant( + cast(ConstantExpr::getZExt(SC->getValue(), + getEffectiveSCEVType(Ty)))); + + // zext(zext(x)) --> zext(x) + if (const SCEVZeroExtendExpr *SZ = dyn_cast(Op)) + return getZeroExtendExpr(SZ->getOperand(), Ty); + + // Before doing any expensive analysis, check to see if we've already + // computed a SCEV for this Op and Ty. + FoldingSetNodeID ID; + ID.AddInteger(scZeroExtend); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // zext(trunc(x)) --> zext(x) or x or trunc(x) + if (const SCEVTruncateExpr *ST = dyn_cast(Op)) { + // It's possible the bits taken off by the truncate were all zero bits. If + // so, we should be able to simplify this further. + const SCEV *X = ST->getOperand(); + ConstantRange CR = getUnsignedRange(X); + unsigned TruncBits = getTypeSizeInBits(ST->getType()); + unsigned NewBits = getTypeSizeInBits(Ty); + if (CR.truncate(TruncBits).zeroExtend(NewBits).contains( + CR.zextOrTrunc(NewBits))) + return getTruncateOrZeroExtend(X, Ty); + } + + // If the input value is a chrec scev, and we can prove that the value + // did not overflow the old, smaller, value, we can zero extend all of the + // operands (often constants). This allows analysis of something like + // this: for (unsigned char X = 0; X < 100; ++X) { int Y = X; } + if (const SCEVAddRecExpr *AR = dyn_cast(Op)) + if (AR->isAffine()) { + const SCEV *Start = AR->getStart(); + const SCEV *Step = AR->getStepRecurrence(*this); + unsigned BitWidth = getTypeSizeInBits(AR->getType()); + const Loop *L = AR->getLoop(); + + // If we have special knowledge that this addrec won't overflow, + // we don't need to do any further analysis. + if (AR->hasNoUnsignedWrap()) + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + + // Check whether the backedge-taken count is SCEVCouldNotCompute. + // Note that this serves two purposes: It filters out loops that are + // simply not analyzable, and it covers the case where this code is + // being called from within backedge-taken count analysis, such that + // attempting to ask for the backedge-taken count would likely result + // in infinite recursion. In the later case, the analysis code will + // cope with a conservative value, and it will take care to purge + // that value once it has finished. + const SCEV *MaxBECount = getMaxBackedgeTakenCount(L); + if (!isa(MaxBECount)) { + // Manually compute the final value for AR, checking for + // overflow. + + // Check whether the backedge-taken count can be losslessly casted to + // the addrec's type. The count is always unsigned. + const SCEV *CastedMaxBECount = + getTruncateOrZeroExtend(MaxBECount, Start->getType()); + const SCEV *RecastedMaxBECount = + getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); + if (MaxBECount == RecastedMaxBECount) { + const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + // Check whether Start+Step*MaxBECount has no unsigned overflow. + const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step); + const SCEV *Add = getAddExpr(Start, ZMul); + const SCEV *OperandExtendedAdd = + getAddExpr(getZeroExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getZeroExtendExpr(Step, WideTy))); + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + + // Similar to above, only this time treat the step value as signed. + // This covers loops that count down. + const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); + Add = getAddExpr(Start, SMul); + OperandExtendedAdd = + getAddExpr(getZeroExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getSignExtendExpr(Step, WideTy))); + if (getZeroExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + + // If the backedge is guarded by a comparison with the pre-inc value + // the addrec is safe. Also, if the entry is guarded by a comparison + // with the start value and the backedge is guarded by a comparison + // with the post-inc value, the addrec is safe. + if (isKnownPositive(Step)) { + const SCEV *N = getConstant(APInt::getMinValue(BitWidth) - + getUnsignedRange(Step).getUnsignedMax()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N) || + (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_ULT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + } else if (isKnownNegative(Step)) { + const SCEV *N = getConstant(APInt::getMaxValue(BitWidth) - + getSignedRange(Step).getSignedMin()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, AR, N) || + (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_UGT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_UGT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getZeroExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + } + } + + // The cast wasn't folded; create an explicit cast node. + // Recompute the insert position, as it may have been invalidated. + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator), + Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Fold if the operand is constant. + if (const SCEVConstant *SC = dyn_cast(Op)) + return getConstant( + cast(ConstantExpr::getSExt(SC->getValue(), + getEffectiveSCEVType(Ty)))); + + // sext(sext(x)) --> sext(x) + if (const SCEVSignExtendExpr *SS = dyn_cast(Op)) + return getSignExtendExpr(SS->getOperand(), Ty); + + // sext(zext(x)) --> zext(x) + if (const SCEVZeroExtendExpr *SZ = dyn_cast(Op)) + return getZeroExtendExpr(SZ->getOperand(), Ty); + + // Before doing any expensive analysis, check to see if we've already + // computed a SCEV for this Op and Ty. + FoldingSetNodeID ID; + ID.AddInteger(scSignExtend); + ID.AddPointer(Op); + ID.AddPointer(Ty); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + + // If the input value is provably positive, build a zext instead. + if (isKnownNonNegative(Op)) + return getZeroExtendExpr(Op, Ty); + + // sext(trunc(x)) --> sext(x) or x or trunc(x) + if (const SCEVTruncateExpr *ST = dyn_cast(Op)) { + // It's possible the bits taken off by the truncate were all sign bits. If + // so, we should be able to simplify this further. + const SCEV *X = ST->getOperand(); + ConstantRange CR = getSignedRange(X); + unsigned TruncBits = getTypeSizeInBits(ST->getType()); + unsigned NewBits = getTypeSizeInBits(Ty); + if (CR.truncate(TruncBits).signExtend(NewBits).contains( + CR.sextOrTrunc(NewBits))) + return getTruncateOrSignExtend(X, Ty); + } + + // If the input value is a chrec scev, and we can prove that the value + // did not overflow the old, smaller, value, we can sign extend all of the + // operands (often constants). This allows analysis of something like + // this: for (signed char X = 0; X < 100; ++X) { int Y = X; } + if (const SCEVAddRecExpr *AR = dyn_cast(Op)) + if (AR->isAffine()) { + const SCEV *Start = AR->getStart(); + const SCEV *Step = AR->getStepRecurrence(*this); + unsigned BitWidth = getTypeSizeInBits(AR->getType()); + const Loop *L = AR->getLoop(); + + // If we have special knowledge that this addrec won't overflow, + // we don't need to do any further analysis. + if (AR->hasNoSignedWrap()) + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + + // Check whether the backedge-taken count is SCEVCouldNotCompute. + // Note that this serves two purposes: It filters out loops that are + // simply not analyzable, and it covers the case where this code is + // being called from within backedge-taken count analysis, such that + // attempting to ask for the backedge-taken count would likely result + // in infinite recursion. In the later case, the analysis code will + // cope with a conservative value, and it will take care to purge + // that value once it has finished. + const SCEV *MaxBECount = getMaxBackedgeTakenCount(L); + if (!isa(MaxBECount)) { + // Manually compute the final value for AR, checking for + // overflow. + + // Check whether the backedge-taken count can be losslessly casted to + // the addrec's type. The count is always unsigned. + const SCEV *CastedMaxBECount = + getTruncateOrZeroExtend(MaxBECount, Start->getType()); + const SCEV *RecastedMaxBECount = + getTruncateOrZeroExtend(CastedMaxBECount, MaxBECount->getType()); + if (MaxBECount == RecastedMaxBECount) { + const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); + // Check whether Start+Step*MaxBECount has no signed overflow. + const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); + const SCEV *Add = getAddExpr(Start, SMul); + const SCEV *OperandExtendedAdd = + getAddExpr(getSignExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getSignExtendExpr(Step, WideTy))); + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + + // Similar to above, only this time treat the step value as unsigned. + // This covers loops that count up with an unsigned step. + const SCEV *UMul = getMulExpr(CastedMaxBECount, Step); + Add = getAddExpr(Start, UMul); + OperandExtendedAdd = + getAddExpr(getSignExtendExpr(Start, WideTy), + getMulExpr(getZeroExtendExpr(CastedMaxBECount, WideTy), + getZeroExtendExpr(Step, WideTy))); + if (getSignExtendExpr(Add, WideTy) == OperandExtendedAdd) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getZeroExtendExpr(Step, Ty), + L); + } + + // If the backedge is guarded by a comparison with the pre-inc value + // the addrec is safe. Also, if the entry is guarded by a comparison + // with the start value and the backedge is guarded by a comparison + // with the post-inc value, the addrec is safe. + if (isKnownPositive(Step)) { + const SCEV *N = getConstant(APInt::getSignedMinValue(BitWidth) - + getSignedRange(Step).getSignedMax()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, AR, N) || + (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SLT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } else if (isKnownNegative(Step)) { + const SCEV *N = getConstant(APInt::getSignedMaxValue(BitWidth) - + getSignedRange(Step).getSignedMin()); + if (isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, AR, N) || + (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGT, Start, N) && + isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_SGT, + AR->getPostIncExpr(*this), N))) + // Return the expression with the addrec on the outside. + return getAddRecExpr(getSignExtendExpr(Start, Ty), + getSignExtendExpr(Step, Ty), + L); + } + } + } + + // The cast wasn't folded; create an explicit cast node. + // Recompute the insert position, as it may have been invalidated. + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator), + Op, Ty); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +/// getAnyExtendExpr - Return a SCEV for the given operand extended with +/// unspecified bits out to the given type. +/// +const SCEV *ScalarEvolution::getAnyExtendExpr(const SCEV *Op, + const Type *Ty) { + assert(getTypeSizeInBits(Op->getType()) < getTypeSizeInBits(Ty) && + "This is not an extending conversion!"); + assert(isSCEVable(Ty) && + "This is not a conversion to a SCEVable type!"); + Ty = getEffectiveSCEVType(Ty); + + // Sign-extend negative constants. + if (const SCEVConstant *SC = dyn_cast(Op)) + if (SC->getValue()->getValue().isNegative()) + return getSignExtendExpr(Op, Ty); + + // Peel off a truncate cast. + if (const SCEVTruncateExpr *T = dyn_cast(Op)) { + const SCEV *NewOp = T->getOperand(); + if (getTypeSizeInBits(NewOp->getType()) < getTypeSizeInBits(Ty)) + return getAnyExtendExpr(NewOp, Ty); + return getTruncateOrNoop(NewOp, Ty); + } + + // Next try a zext cast. If the cast is folded, use it. + const SCEV *ZExt = getZeroExtendExpr(Op, Ty); + if (!isa(ZExt)) + return ZExt; + + // Next try a sext cast. If the cast is folded, use it. + const SCEV *SExt = getSignExtendExpr(Op, Ty); + if (!isa(SExt)) + return SExt; + + // Force the cast to be folded into the operands of an addrec. + if (const SCEVAddRecExpr *AR = dyn_cast(Op)) { + SmallVector Ops; + for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); + I != E; ++I) + Ops.push_back(getAnyExtendExpr(*I, Ty)); + return getAddRecExpr(Ops, AR->getLoop()); + } + + // As a special case, fold anyext(undef) to undef. We don't want to + // know too much about SCEVUnknowns, but this special case is handy + // and harmless. + if (const SCEVUnknown *U = dyn_cast(Op)) + if (isa(U->getValue())) + return getSCEV(UndefValue::get(Ty)); + + // If the expression is obviously signed, use the sext cast value. + if (isa(Op)) + return SExt; + + // Absent any other information, use the zext cast value. + return ZExt; +} + +/// CollectAddOperandsWithScales - Process the given Ops list, which is +/// a list of operands to be added under the given scale, update the given +/// map. This is a helper function for getAddRecExpr. As an example of +/// what it does, given a sequence of operands that would form an add +/// expression like this: +/// +/// m + n + 13 + (A * (o + p + (B * q + m + 29))) + r + (-1 * r) +/// +/// where A and B are constants, update the map with these values: +/// +/// (m, 1+A*B), (n, 1), (o, A), (p, A), (q, A*B), (r, 0) +/// +/// and add 13 + A*B*29 to AccumulatedConstant. +/// This will allow getAddRecExpr to produce this: +/// +/// 13+A*B*29 + n + (m * (1+A*B)) + ((o + p) * A) + (q * A*B) +/// +/// This form often exposes folding opportunities that are hidden in +/// the original operand list. +/// +/// Return true iff it appears that any interesting folding opportunities +/// may be exposed. This helps getAddRecExpr short-circuit extra work in +/// the common case where no interesting opportunities are present, and +/// is also used as a check to avoid infinite recursion. +/// +static bool +CollectAddOperandsWithScales(DenseMap &M, + SmallVector &NewOps, + APInt &AccumulatedConstant, + const SCEV *const *Ops, size_t NumOperands, + const APInt &Scale, + ScalarEvolution &SE) { + bool Interesting = false; + + // Iterate over the add operands. They are sorted, with constants first. + unsigned i = 0; + while (const SCEVConstant *C = dyn_cast(Ops[i])) { + ++i; + // Pull a buried constant out to the outside. + if (Scale != 1 || AccumulatedConstant != 0 || C->getValue()->isZero()) + Interesting = true; + AccumulatedConstant += Scale * C->getValue()->getValue(); + } + + // Next comes everything else. We're especially interested in multiplies + // here, but they're in the middle, so just visit the rest with one loop. + for (; i != NumOperands; ++i) { + const SCEVMulExpr *Mul = dyn_cast(Ops[i]); + if (Mul && isa(Mul->getOperand(0))) { + APInt NewScale = + Scale * cast(Mul->getOperand(0))->getValue()->getValue(); + if (Mul->getNumOperands() == 2 && isa(Mul->getOperand(1))) { + // A multiplication of a constant with another add; recurse. + const SCEVAddExpr *Add = cast(Mul->getOperand(1)); + Interesting |= + CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant, + Add->op_begin(), Add->getNumOperands(), + NewScale, SE); + } else { + // A multiplication of a constant with some other value. Update + // the map. + SmallVector MulOps(Mul->op_begin()+1, Mul->op_end()); + const SCEV *Key = SE.getMulExpr(MulOps); + std::pair::iterator, bool> Pair = + M.insert(std::make_pair(Key, NewScale)); + if (Pair.second) { + NewOps.push_back(Pair.first->first); + } else { + Pair.first->second += NewScale; + // The map already had an entry for this value, which may indicate + // a folding opportunity. + Interesting = true; + } + } + } else { + // An ordinary operand. Update the map. + std::pair::iterator, bool> Pair = + M.insert(std::make_pair(Ops[i], Scale)); + if (Pair.second) { + NewOps.push_back(Pair.first->first); + } else { + Pair.first->second += Scale; + // The map already had an entry for this value, which may indicate + // a folding opportunity. + Interesting = true; + } + } + } + + return Interesting; +} + +namespace { + struct APIntCompare { + bool operator()(const APInt &LHS, const APInt &RHS) const { + return LHS.ult(RHS); + } + }; +} + +/// getAddExpr - Get a canonical add expression, or something simpler if +/// possible. +const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, + bool HasNUW, bool HasNSW) { + assert(!Ops.empty() && "Cannot get empty add!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && + "SCEVAddExpr operand types don't match!"); +#endif + + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (SmallVectorImpl::const_iterator I = Ops.begin(), + E = Ops.end(); I != E; ++I) + if (!isKnownNonNegative(*I)) { + All = false; + break; + } + if (All) HasNUW = true; + } + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + Ops[0] = getConstant(LHSC->getValue()->getValue() + + RHSC->getValue()->getValue()); + if (Ops.size() == 2) return Ops[0]; + Ops.erase(Ops.begin()+1); // Erase the folded element + LHSC = cast(Ops[0]); + } + + // If we are left with a constant zero being added, strip it off. + if (LHSC->getValue()->isZero()) { + Ops.erase(Ops.begin()); + --Idx; + } + + if (Ops.size() == 1) return Ops[0]; + } + + // Okay, check to see if the same value occurs in the operand list more than + // once. If so, merge them together into an multiply expression. Since we + // sorted the list, these values are required to be adjacent. + const Type *Ty = Ops[0]->getType(); + bool FoundMatch = false; + for (unsigned i = 0, e = Ops.size(); i != e-1; ++i) + if (Ops[i] == Ops[i+1]) { // X + Y + Y --> X + Y*2 + // Scan ahead to count how many equal operands there are. + unsigned Count = 2; + while (i+Count != e && Ops[i+Count] == Ops[i]) + ++Count; + // Merge the values into a multiply. + const SCEV *Scale = getConstant(Ty, Count); + const SCEV *Mul = getMulExpr(Scale, Ops[i]); + if (Ops.size() == Count) + return Mul; + Ops[i] = Mul; + Ops.erase(Ops.begin()+i+1, Ops.begin()+i+Count); + --i; e -= Count - 1; + FoundMatch = true; + } + if (FoundMatch) + return getAddExpr(Ops, HasNUW, HasNSW); + + // Check for truncates. If all the operands are truncated from the same + // type, see if factoring out the truncate would permit the result to be + // folded. eg., trunc(x) + m*trunc(n) --> trunc(x + trunc(m)*n) + // if the contents of the resulting outer trunc fold to something simple. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + const SCEVTruncateExpr *Trunc = cast(Ops[Idx]); + const Type *DstType = Trunc->getType(); + const Type *SrcType = Trunc->getOperand()->getType(); + SmallVector LargeOps; + bool Ok = true; + // Check all the operands to see if they can be represented in the + // source type of the truncate. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + if (const SCEVTruncateExpr *T = dyn_cast(Ops[i])) { + if (T->getOperand()->getType() != SrcType) { + Ok = false; + break; + } + LargeOps.push_back(T->getOperand()); + } else if (const SCEVConstant *C = dyn_cast(Ops[i])) { + LargeOps.push_back(getAnyExtendExpr(C, SrcType)); + } else if (const SCEVMulExpr *M = dyn_cast(Ops[i])) { + SmallVector LargeMulOps; + for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) { + if (const SCEVTruncateExpr *T = + dyn_cast(M->getOperand(j))) { + if (T->getOperand()->getType() != SrcType) { + Ok = false; + break; + } + LargeMulOps.push_back(T->getOperand()); + } else if (const SCEVConstant *C = + dyn_cast(M->getOperand(j))) { + LargeMulOps.push_back(getAnyExtendExpr(C, SrcType)); + } else { + Ok = false; + break; + } + } + if (Ok) + LargeOps.push_back(getMulExpr(LargeMulOps)); + } else { + Ok = false; + break; + } + } + if (Ok) { + // Evaluate the expression in the larger type. + const SCEV *Fold = getAddExpr(LargeOps, HasNUW, HasNSW); + // If it folds to something simple, use it. Otherwise, don't. + if (isa(Fold) || isa(Fold)) + return getTruncateExpr(Fold, DstType); + } + } + + // Skip past any other cast SCEVs. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddExpr) + ++Idx; + + // If there are add operands they would be next. + if (Idx < Ops.size()) { + bool DeletedAdd = false; + while (const SCEVAddExpr *Add = dyn_cast(Ops[Idx])) { + // If we have an add, expand the add operands onto the end of the operands + // list. + Ops.erase(Ops.begin()+Idx); + Ops.append(Add->op_begin(), Add->op_end()); + DeletedAdd = true; + } + + // If we deleted at least one add, we added operands to the end of the list, + // and they are not necessarily sorted. Recurse to resort and resimplify + // any operands we just acquired. + if (DeletedAdd) + return getAddExpr(Ops); + } + + // Skip over the add expression until we get to a multiply. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr) + ++Idx; + + // Check to see if there are any folding opportunities present with + // operands multiplied by constant values. + if (Idx < Ops.size() && isa(Ops[Idx])) { + uint64_t BitWidth = getTypeSizeInBits(Ty); + DenseMap M; + SmallVector NewOps; + APInt AccumulatedConstant(BitWidth, 0); + if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant, + Ops.data(), Ops.size(), + APInt(BitWidth, 1), *this)) { + // Some interesting folding opportunity is present, so its worthwhile to + // re-generate the operands list. Group the operands by constant scale, + // to avoid multiplying by the same constant scale multiple times. + std::map, APIntCompare> MulOpLists; + for (SmallVector::const_iterator I = NewOps.begin(), + E = NewOps.end(); I != E; ++I) + MulOpLists[M.find(*I)->second].push_back(*I); + // Re-generate the operands list. + Ops.clear(); + if (AccumulatedConstant != 0) + Ops.push_back(getConstant(AccumulatedConstant)); + for (std::map, APIntCompare>::iterator + I = MulOpLists.begin(), E = MulOpLists.end(); I != E; ++I) + if (I->first != 0) + Ops.push_back(getMulExpr(getConstant(I->first), + getAddExpr(I->second))); + if (Ops.empty()) + return getConstant(Ty, 0); + if (Ops.size() == 1) + return Ops[0]; + return getAddExpr(Ops); + } + } + + // If we are adding something to a multiply expression, make sure the + // something is not already an operand of the multiply. If so, merge it into + // the multiply. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + const SCEVMulExpr *Mul = cast(Ops[Idx]); + for (unsigned MulOp = 0, e = Mul->getNumOperands(); MulOp != e; ++MulOp) { + const SCEV *MulOpSCEV = Mul->getOperand(MulOp); + if (isa(MulOpSCEV)) + continue; + for (unsigned AddOp = 0, e = Ops.size(); AddOp != e; ++AddOp) + if (MulOpSCEV == Ops[AddOp]) { + // Fold W + X + (X * Y * Z) --> W + (X * ((Y*Z)+1)) + const SCEV *InnerMul = Mul->getOperand(MulOp == 0); + if (Mul->getNumOperands() != 2) { + // If the multiply has more than two operands, we must get the + // Y*Z term. + SmallVector MulOps(Mul->op_begin(), + Mul->op_begin()+MulOp); + MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end()); + InnerMul = getMulExpr(MulOps); + } + const SCEV *One = getConstant(Ty, 1); + const SCEV *AddOne = getAddExpr(One, InnerMul); + const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV); + if (Ops.size() == 2) return OuterMul; + if (AddOp < Idx) { + Ops.erase(Ops.begin()+AddOp); + Ops.erase(Ops.begin()+Idx-1); + } else { + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+AddOp-1); + } + Ops.push_back(OuterMul); + return getAddExpr(Ops); + } + + // Check this multiply against other multiplies being added together. + for (unsigned OtherMulIdx = Idx+1; + OtherMulIdx < Ops.size() && isa(Ops[OtherMulIdx]); + ++OtherMulIdx) { + const SCEVMulExpr *OtherMul = cast(Ops[OtherMulIdx]); + // If MulOp occurs in OtherMul, we can fold the two multiplies + // together. + for (unsigned OMulOp = 0, e = OtherMul->getNumOperands(); + OMulOp != e; ++OMulOp) + if (OtherMul->getOperand(OMulOp) == MulOpSCEV) { + // Fold X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E)) + const SCEV *InnerMul1 = Mul->getOperand(MulOp == 0); + if (Mul->getNumOperands() != 2) { + SmallVector MulOps(Mul->op_begin(), + Mul->op_begin()+MulOp); + MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end()); + InnerMul1 = getMulExpr(MulOps); + } + const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0); + if (OtherMul->getNumOperands() != 2) { + SmallVector MulOps(OtherMul->op_begin(), + OtherMul->op_begin()+OMulOp); + MulOps.append(OtherMul->op_begin()+OMulOp+1, OtherMul->op_end()); + InnerMul2 = getMulExpr(MulOps); + } + const SCEV *InnerMulSum = getAddExpr(InnerMul1,InnerMul2); + const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum); + if (Ops.size() == 2) return OuterMul; + Ops.erase(Ops.begin()+Idx); + Ops.erase(Ops.begin()+OtherMulIdx-1); + Ops.push_back(OuterMul); + return getAddExpr(Ops); + } + } + } + } + + // If there are any add recurrences in the operands list, see if any other + // added values are loop invariant. If so, we can fold them into the + // recurrence. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr) + ++Idx; + + // Scan over all recurrences, trying to fold loop invariants into them. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + // Scan all of the other operands to this add and add them to the vector if + // they are loop invariant w.r.t. the recurrence. + SmallVector LIOps; + const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); + const Loop *AddRecLoop = AddRec->getLoop(); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (isLoopInvariant(Ops[i], AddRecLoop)) { + LIOps.push_back(Ops[i]); + Ops.erase(Ops.begin()+i); + --i; --e; + } + + // If we found some loop invariants, fold them into the recurrence. + if (!LIOps.empty()) { + // NLI + LI + {Start,+,Step} --> NLI + {LI+Start,+,Step} + LIOps.push_back(AddRec->getStart()); + + SmallVector AddRecOps(AddRec->op_begin(), + AddRec->op_end()); + AddRecOps[0] = getAddExpr(LIOps); + + // Build the new addrec. Propagate the NUW and NSW flags if both the + // outer add and the inner addrec are guaranteed to have no overflow. + const SCEV *NewRec = getAddRecExpr(AddRecOps, AddRecLoop, + HasNUW && AddRec->hasNoUnsignedWrap(), + HasNSW && AddRec->hasNoSignedWrap()); + + // If all of the other operands were loop invariant, we are done. + if (Ops.size() == 1) return NewRec; + + // Otherwise, add the folded AddRec by the non-liv parts. + for (unsigned i = 0;; ++i) + if (Ops[i] == AddRec) { + Ops[i] = NewRec; + break; + } + return getAddExpr(Ops); + } + + // Okay, if there weren't any loop invariants to be folded, check to see if + // there are multiple AddRec's with the same loop induction variable being + // added together. If so, we can fold them. + for (unsigned OtherIdx = Idx+1; + OtherIdx < Ops.size() && isa(Ops[OtherIdx]); + ++OtherIdx) + if (AddRecLoop == cast(Ops[OtherIdx])->getLoop()) { + // Other + {A,+,B} + {C,+,D} --> Other + {A+C,+,B+D} + SmallVector AddRecOps(AddRec->op_begin(), + AddRec->op_end()); + for (; OtherIdx != Ops.size() && isa(Ops[OtherIdx]); + ++OtherIdx) + if (const SCEVAddRecExpr *OtherAddRec = + dyn_cast(Ops[OtherIdx])) + if (OtherAddRec->getLoop() == AddRecLoop) { + for (unsigned i = 0, e = OtherAddRec->getNumOperands(); + i != e; ++i) { + if (i >= AddRecOps.size()) { + AddRecOps.append(OtherAddRec->op_begin()+i, + OtherAddRec->op_end()); + break; + } + AddRecOps[i] = getAddExpr(AddRecOps[i], + OtherAddRec->getOperand(i)); + } + Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + } + Ops[Idx] = getAddRecExpr(AddRecOps, AddRecLoop); + return getAddExpr(Ops); + } + + // Otherwise couldn't fold anything into this recurrence. Move onto the + // next one. + } + + // Okay, it looks like we really DO need an add expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scAddExpr); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + SCEVAddExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); + S = new (SCEVAllocator) SCEVAddExpr(ID.Intern(SCEVAllocator), + O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + } + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + +/// getMulExpr - Get a canonical multiply expression, or something simpler if +/// possible. +const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, + bool HasNUW, bool HasNSW) { + assert(!Ops.empty() && "Cannot get empty mul!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && + "SCEVMulExpr operand types don't match!"); +#endif + + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (SmallVectorImpl::const_iterator I = Ops.begin(), + E = Ops.end(); I != E; ++I) + if (!isKnownNonNegative(*I)) { + All = false; + break; + } + if (All) HasNUW = true; + } + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + + // C1*(C2+V) -> C1*C2 + C1*V + if (Ops.size() == 2) + if (const SCEVAddExpr *Add = dyn_cast(Ops[1])) + if (Add->getNumOperands() == 2 && + isa(Add->getOperand(0))) + return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)), + getMulExpr(LHSC, Add->getOperand(1))); + + ++Idx; + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + LHSC->getValue()->getValue() * + RHSC->getValue()->getValue()); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant one being multiplied, strip it off. + if (cast(Ops[0])->getValue()->equalsInt(1)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isZero()) { + // If we have a multiply of zero, it will always be zero. + return Ops[0]; + } else if (Ops[0]->isAllOnesValue()) { + // If we have a mul by -1 of an add, try distributing the -1 among the + // add operands. + if (Ops.size() == 2) + if (const SCEVAddExpr *Add = dyn_cast(Ops[1])) { + SmallVector NewOps; + bool AnyFolded = false; + for (SCEVAddRecExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) { + const SCEV *Mul = getMulExpr(Ops[0], *I); + if (!isa(Mul)) AnyFolded = true; + NewOps.push_back(Mul); + } + if (AnyFolded) + return getAddExpr(NewOps); + } + } + + if (Ops.size() == 1) + return Ops[0]; + } + + // Skip over the add expression until we get to a multiply. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr) + ++Idx; + + // If there are mul operands inline them all into this expression. + if (Idx < Ops.size()) { + bool DeletedMul = false; + while (const SCEVMulExpr *Mul = dyn_cast(Ops[Idx])) { + // If we have an mul, expand the mul operands onto the end of the operands + // list. + Ops.erase(Ops.begin()+Idx); + Ops.append(Mul->op_begin(), Mul->op_end()); + DeletedMul = true; + } + + // If we deleted at least one mul, we added operands to the end of the list, + // and they are not necessarily sorted. Recurse to resort and resimplify + // any operands we just acquired. + if (DeletedMul) + return getMulExpr(Ops); + } + + // If there are any add recurrences in the operands list, see if any other + // added values are loop invariant. If so, we can fold them into the + // recurrence. + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scAddRecExpr) + ++Idx; + + // Scan over all recurrences, trying to fold loop invariants into them. + for (; Idx < Ops.size() && isa(Ops[Idx]); ++Idx) { + // Scan all of the other operands to this mul and add them to the vector if + // they are loop invariant w.r.t. the recurrence. + SmallVector LIOps; + const SCEVAddRecExpr *AddRec = cast(Ops[Idx]); + const Loop *AddRecLoop = AddRec->getLoop(); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (isLoopInvariant(Ops[i], AddRecLoop)) { + LIOps.push_back(Ops[i]); + Ops.erase(Ops.begin()+i); + --i; --e; + } + + // If we found some loop invariants, fold them into the recurrence. + if (!LIOps.empty()) { + // NLI * LI * {Start,+,Step} --> NLI * {LI*Start,+,LI*Step} + SmallVector NewOps; + NewOps.reserve(AddRec->getNumOperands()); + const SCEV *Scale = getMulExpr(LIOps); + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) + NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i))); + + // Build the new addrec. Propagate the NUW and NSW flags if both the + // outer mul and the inner addrec are guaranteed to have no overflow. + const SCEV *NewRec = getAddRecExpr(NewOps, AddRecLoop, + HasNUW && AddRec->hasNoUnsignedWrap(), + HasNSW && AddRec->hasNoSignedWrap()); + + // If all of the other operands were loop invariant, we are done. + if (Ops.size() == 1) return NewRec; + + // Otherwise, multiply the folded AddRec by the non-liv parts. + for (unsigned i = 0;; ++i) + if (Ops[i] == AddRec) { + Ops[i] = NewRec; + break; + } + return getMulExpr(Ops); + } + + // Okay, if there weren't any loop invariants to be folded, check to see if + // there are multiple AddRec's with the same loop induction variable being + // multiplied together. If so, we can fold them. + for (unsigned OtherIdx = Idx+1; + OtherIdx < Ops.size() && isa(Ops[OtherIdx]); + ++OtherIdx) + if (AddRecLoop == cast(Ops[OtherIdx])->getLoop()) { + // F * G, where F = {A,+,B} and G = {C,+,D} --> + // {A*C,+,F*D + G*B + B*D} + for (; OtherIdx != Ops.size() && isa(Ops[OtherIdx]); + ++OtherIdx) + if (const SCEVAddRecExpr *OtherAddRec = + dyn_cast(Ops[OtherIdx])) + if (OtherAddRec->getLoop() == AddRecLoop) { + const SCEVAddRecExpr *F = AddRec, *G = OtherAddRec; + const SCEV *NewStart = getMulExpr(F->getStart(), G->getStart()); + const SCEV *B = F->getStepRecurrence(*this); + const SCEV *D = G->getStepRecurrence(*this); + const SCEV *NewStep = getAddExpr(getMulExpr(F, D), + getMulExpr(G, B), + getMulExpr(B, D)); + const SCEV *NewAddRec = getAddRecExpr(NewStart, NewStep, + F->getLoop()); + if (Ops.size() == 2) return NewAddRec; + Ops[Idx] = AddRec = cast(NewAddRec); + Ops.erase(Ops.begin() + OtherIdx); --OtherIdx; + } + return getMulExpr(Ops); + } + + // Otherwise couldn't fold anything into this recurrence. Move onto the + // next one. + } + + // Okay, it looks like we really DO need an mul expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scMulExpr); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + SCEVMulExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); + S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator), + O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + } + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + +/// getUDivExpr - Get a canonical unsigned division expression, or something +/// simpler if possible. +const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS, + const SCEV *RHS) { + assert(getEffectiveSCEVType(LHS->getType()) == + getEffectiveSCEVType(RHS->getType()) && + "SCEVUDivExpr operand types don't match!"); + + if (const SCEVConstant *RHSC = dyn_cast(RHS)) { + if (RHSC->getValue()->equalsInt(1)) + return LHS; // X udiv 1 --> x + // If the denominator is zero, the result of the udiv is undefined. Don't + // try to analyze it, because the resolution chosen here may differ from + // the resolution chosen in other parts of the compiler. + if (!RHSC->getValue()->isZero()) { + // Determine if the division can be folded into the operands of + // its operands. + // TODO: Generalize this to non-constants by using known-bits information. + const Type *Ty = LHS->getType(); + unsigned LZ = RHSC->getValue()->getValue().countLeadingZeros(); + unsigned MaxShiftAmt = getTypeSizeInBits(Ty) - LZ - 1; + // For non-power-of-two values, effectively round the value up to the + // nearest power of two. + if (!RHSC->getValue()->getValue().isPowerOf2()) + ++MaxShiftAmt; + const IntegerType *ExtTy = + IntegerType::get(getContext(), getTypeSizeInBits(Ty) + MaxShiftAmt); + // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. + if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) + if (const SCEVConstant *Step = + dyn_cast(AR->getStepRecurrence(*this))) + if (!Step->getValue()->getValue() + .urem(RHSC->getValue()->getValue()) && + getZeroExtendExpr(AR, ExtTy) == + getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), + getZeroExtendExpr(Step, ExtTy), + AR->getLoop())) { + SmallVector Operands; + for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i) + Operands.push_back(getUDivExpr(AR->getOperand(i), RHS)); + return getAddRecExpr(Operands, AR->getLoop()); + } + // (A*B)/C --> A*(B/C) if safe and B/C can be folded. + if (const SCEVMulExpr *M = dyn_cast(LHS)) { + SmallVector Operands; + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) + Operands.push_back(getZeroExtendExpr(M->getOperand(i), ExtTy)); + if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands)) + // Find an operand that's safely divisible. + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) { + const SCEV *Op = M->getOperand(i); + const SCEV *Div = getUDivExpr(Op, RHSC); + if (!isa(Div) && getMulExpr(Div, RHSC) == Op) { + Operands = SmallVector(M->op_begin(), + M->op_end()); + Operands[i] = Div; + return getMulExpr(Operands); + } + } + } + // (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded. + if (const SCEVAddRecExpr *A = dyn_cast(LHS)) { + SmallVector Operands; + for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) + Operands.push_back(getZeroExtendExpr(A->getOperand(i), ExtTy)); + if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) { + Operands.clear(); + for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i) { + const SCEV *Op = getUDivExpr(A->getOperand(i), RHS); + if (isa(Op) || + getMulExpr(Op, RHS) != A->getOperand(i)) + break; + Operands.push_back(Op); + } + if (Operands.size() == A->getNumOperands()) + return getAddExpr(Operands); + } + } + + // Fold if both operands are constant. + if (const SCEVConstant *LHSC = dyn_cast(LHS)) { + Constant *LHSCV = LHSC->getValue(); + Constant *RHSCV = RHSC->getValue(); + return getConstant(cast(ConstantExpr::getUDiv(LHSCV, + RHSCV))); + } + } + } + + FoldingSetNodeID ID; + ID.AddInteger(scUDivExpr); + ID.AddPointer(LHS); + ID.AddPointer(RHS); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + SCEV *S = new (SCEVAllocator) SCEVUDivExpr(ID.Intern(SCEVAllocator), + LHS, RHS); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + + +/// getAddRecExpr - Get an add recurrence expression for the specified loop. +/// Simplify the expression as much as possible. +const SCEV *ScalarEvolution::getAddRecExpr(const SCEV *Start, + const SCEV *Step, const Loop *L, + bool HasNUW, bool HasNSW) { + SmallVector Operands; + Operands.push_back(Start); + if (const SCEVAddRecExpr *StepChrec = dyn_cast(Step)) + if (StepChrec->getLoop() == L) { + Operands.append(StepChrec->op_begin(), StepChrec->op_end()); + return getAddRecExpr(Operands, L); + } + + Operands.push_back(Step); + return getAddRecExpr(Operands, L, HasNUW, HasNSW); +} + +/// getAddRecExpr - Get an add recurrence expression for the specified loop. +/// Simplify the expression as much as possible. +const SCEV * +ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, + const Loop *L, + bool HasNUW, bool HasNSW) { + if (Operands.size() == 1) return Operands[0]; +#ifndef NDEBUG + const Type *ETy = getEffectiveSCEVType(Operands[0]->getType()); + for (unsigned i = 1, e = Operands.size(); i != e; ++i) + assert(getEffectiveSCEVType(Operands[i]->getType()) == ETy && + "SCEVAddRecExpr operand types don't match!"); + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + assert(isLoopInvariant(Operands[i], L) && + "SCEVAddRecExpr operand is not loop-invariant!"); +#endif + + if (Operands.back()->isZero()) { + Operands.pop_back(); + return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X + } + + // It's tempting to want to call getMaxBackedgeTakenCount count here and + // use that information to infer NUW and NSW flags. However, computing a + // BE count requires calling getAddRecExpr, so we may not yet have a + // meaningful BE count at this point (and if we don't, we'd be stuck + // with a SCEVCouldNotCompute as the cached BE count). + + // If HasNSW is true and all the operands are non-negative, infer HasNUW. + if (!HasNUW && HasNSW) { + bool All = true; + for (SmallVectorImpl::const_iterator I = Operands.begin(), + E = Operands.end(); I != E; ++I) + if (!isKnownNonNegative(*I)) { + All = false; + break; + } + if (All) HasNUW = true; + } + + // Canonicalize nested AddRecs in by nesting them in order of loop depth. + if (const SCEVAddRecExpr *NestedAR = dyn_cast(Operands[0])) { + const Loop *NestedLoop = NestedAR->getLoop(); + if (L->contains(NestedLoop) ? + (L->getLoopDepth() < NestedLoop->getLoopDepth()) : + (!NestedLoop->contains(L) && + DT->dominates(L->getHeader(), NestedLoop->getHeader()))) { + SmallVector NestedOperands(NestedAR->op_begin(), + NestedAR->op_end()); + Operands[0] = NestedAR->getStart(); + // AddRecs require their operands be loop-invariant with respect to their + // loops. Don't perform this transformation if it would break this + // requirement. + bool AllInvariant = true; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!isLoopInvariant(Operands[i], L)) { + AllInvariant = false; + break; + } + if (AllInvariant) { + NestedOperands[0] = getAddRecExpr(Operands, L); + AllInvariant = true; + for (unsigned i = 0, e = NestedOperands.size(); i != e; ++i) + if (!isLoopInvariant(NestedOperands[i], NestedLoop)) { + AllInvariant = false; + break; + } + if (AllInvariant) + // Ok, both add recurrences are valid after the transformation. + return getAddRecExpr(NestedOperands, NestedLoop, HasNUW, HasNSW); + } + // Reset Operands to its original state. + Operands[0] = NestedAR; + } + } + + // Okay, it looks like we really DO need an addrec expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scAddRecExpr); + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + ID.AddPointer(Operands[i]); + ID.AddPointer(L); + void *IP = 0; + SCEVAddRecExpr *S = + static_cast(UniqueSCEVs.FindNodeOrInsertPos(ID, IP)); + if (!S) { + const SCEV **O = SCEVAllocator.Allocate(Operands.size()); + std::uninitialized_copy(Operands.begin(), Operands.end(), O); + S = new (SCEVAllocator) SCEVAddRecExpr(ID.Intern(SCEVAllocator), + O, Operands.size(), L); + UniqueSCEVs.InsertNode(S, IP); + } + if (HasNUW) S->setHasNoUnsignedWrap(true); + if (HasNSW) S->setHasNoSignedWrap(true); + return S; +} + +const SCEV *ScalarEvolution::getSMaxExpr(const SCEV *LHS, + const SCEV *RHS) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getSMaxExpr(Ops); +} + +const SCEV * +ScalarEvolution::getSMaxExpr(SmallVectorImpl &Ops) { + assert(!Ops.empty() && "Cannot get empty smax!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && + "SCEVSMaxExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + APIntOps::smax(LHSC->getValue()->getValue(), + RHSC->getValue()->getValue())); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant minimum-int, strip it off. + if (cast(Ops[0])->getValue()->isMinValue(true)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isMaxValue(true)) { + // If we have an smax with a constant maximum-int, it will always be + // maximum-int. + return Ops[0]; + } + + if (Ops.size() == 1) return Ops[0]; + } + + // Find the first SMax + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scSMaxExpr) + ++Idx; + + // Check to see if one of the operands is an SMax. If so, expand its operands + // onto our operand list, and recurse to simplify. + if (Idx < Ops.size()) { + bool DeletedSMax = false; + while (const SCEVSMaxExpr *SMax = dyn_cast(Ops[Idx])) { + Ops.erase(Ops.begin()+Idx); + Ops.append(SMax->op_begin(), SMax->op_end()); + DeletedSMax = true; + } + + if (DeletedSMax) + return getSMaxExpr(Ops); + } + + // Okay, check to see if the same value occurs in the operand list twice. If + // so, delete one. Since we sorted the list, these values are required to + // be adjacent. + for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) + // X smax Y smax Y --> X smax Y + // X smax Y --> X, if X is always greater than Y + if (Ops[i] == Ops[i+1] || + isKnownPredicate(ICmpInst::ICMP_SGE, Ops[i], Ops[i+1])) { + Ops.erase(Ops.begin()+i+1, Ops.begin()+i+2); + --i; --e; + } else if (isKnownPredicate(ICmpInst::ICMP_SLE, Ops[i], Ops[i+1])) { + Ops.erase(Ops.begin()+i, Ops.begin()+i+1); + --i; --e; + } + + if (Ops.size() == 1) return Ops[0]; + + assert(!Ops.empty() && "Reduced smax down to nothing!"); + + // Okay, it looks like we really DO need an smax expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scSMaxExpr); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); + SCEV *S = new (SCEVAllocator) SCEVSMaxExpr(ID.Intern(SCEVAllocator), + O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getUMaxExpr(const SCEV *LHS, + const SCEV *RHS) { + SmallVector Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return getUMaxExpr(Ops); +} + +const SCEV * +ScalarEvolution::getUMaxExpr(SmallVectorImpl &Ops) { + assert(!Ops.empty() && "Cannot get empty umax!"); + if (Ops.size() == 1) return Ops[0]; +#ifndef NDEBUG + const Type *ETy = getEffectiveSCEVType(Ops[0]->getType()); + for (unsigned i = 1, e = Ops.size(); i != e; ++i) + assert(getEffectiveSCEVType(Ops[i]->getType()) == ETy && + "SCEVUMaxExpr operand types don't match!"); +#endif + + // Sort by complexity, this groups all similar expression types together. + GroupByComplexity(Ops, LI); + + // If there are any constants, fold them together. + unsigned Idx = 0; + if (const SCEVConstant *LHSC = dyn_cast(Ops[0])) { + ++Idx; + assert(Idx < Ops.size()); + while (const SCEVConstant *RHSC = dyn_cast(Ops[Idx])) { + // We found two constants, fold them together! + ConstantInt *Fold = ConstantInt::get(getContext(), + APIntOps::umax(LHSC->getValue()->getValue(), + RHSC->getValue()->getValue())); + Ops[0] = getConstant(Fold); + Ops.erase(Ops.begin()+1); // Erase the folded element + if (Ops.size() == 1) return Ops[0]; + LHSC = cast(Ops[0]); + } + + // If we are left with a constant minimum-int, strip it off. + if (cast(Ops[0])->getValue()->isMinValue(false)) { + Ops.erase(Ops.begin()); + --Idx; + } else if (cast(Ops[0])->getValue()->isMaxValue(false)) { + // If we have an umax with a constant maximum-int, it will always be + // maximum-int. + return Ops[0]; + } + + if (Ops.size() == 1) return Ops[0]; + } + + // Find the first UMax + while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scUMaxExpr) + ++Idx; + + // Check to see if one of the operands is a UMax. If so, expand its operands + // onto our operand list, and recurse to simplify. + if (Idx < Ops.size()) { + bool DeletedUMax = false; + while (const SCEVUMaxExpr *UMax = dyn_cast(Ops[Idx])) { + Ops.erase(Ops.begin()+Idx); + Ops.append(UMax->op_begin(), UMax->op_end()); + DeletedUMax = true; + } + + if (DeletedUMax) + return getUMaxExpr(Ops); + } + + // Okay, check to see if the same value occurs in the operand list twice. If + // so, delete one. Since we sorted the list, these values are required to + // be adjacent. + for (unsigned i = 0, e = Ops.size()-1; i != e; ++i) + // X umax Y umax Y --> X umax Y + // X umax Y --> X, if X is always greater than Y + if (Ops[i] == Ops[i+1] || + isKnownPredicate(ICmpInst::ICMP_UGE, Ops[i], Ops[i+1])) { + Ops.erase(Ops.begin()+i+1, Ops.begin()+i+2); + --i; --e; + } else if (isKnownPredicate(ICmpInst::ICMP_ULE, Ops[i], Ops[i+1])) { + Ops.erase(Ops.begin()+i, Ops.begin()+i+1); + --i; --e; + } + + if (Ops.size() == 1) return Ops[0]; + + assert(!Ops.empty() && "Reduced umax down to nothing!"); + + // Okay, it looks like we really DO need a umax expr. Check to see if we + // already have one, otherwise create a new one. + FoldingSetNodeID ID; + ID.AddInteger(scUMaxExpr); + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + ID.AddPointer(Ops[i]); + void *IP = 0; + if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; + const SCEV **O = SCEVAllocator.Allocate(Ops.size()); + std::uninitialized_copy(Ops.begin(), Ops.end(), O); + SCEV *S = new (SCEVAllocator) SCEVUMaxExpr(ID.Intern(SCEVAllocator), + O, Ops.size()); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +const SCEV *ScalarEvolution::getSMinExpr(const SCEV *LHS, + const SCEV *RHS) { + // ~smax(~x, ~y) == smin(x, y). + return getNotSCEV(getSMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); +} + +const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, + const SCEV *RHS) { + // ~umax(~x, ~y) == umin(x, y) + return getNotSCEV(getUMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS))); +} + +const SCEV *ScalarEvolution::getSizeOfExpr(const Type *AllocTy) { + // If we have TargetData, we can bypass creating a target-independent + // constant expression and then folding it back into a ConstantInt. + // This is just a compile-time optimization. + if (TD) + return getConstant(TD->getIntPtrType(getContext()), + TD->getTypeAllocSize(AllocTy)); + + Constant *C = ConstantExpr::getSizeOf(AllocTy); + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) + C = Folded; + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); + return getTruncateOrZeroExtend(getSCEV(C), Ty); +} + +const SCEV *ScalarEvolution::getAlignOfExpr(const Type *AllocTy) { + Constant *C = ConstantExpr::getAlignOf(AllocTy); + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) + C = Folded; + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); + return getTruncateOrZeroExtend(getSCEV(C), Ty); +} + +const SCEV *ScalarEvolution::getOffsetOfExpr(const StructType *STy, + unsigned FieldNo) { + // If we have TargetData, we can bypass creating a target-independent + // constant expression and then folding it back into a ConstantInt. + // This is just a compile-time optimization. + if (TD) + return getConstant(TD->getIntPtrType(getContext()), + TD->getStructLayout(STy)->getElementOffset(FieldNo)); + + Constant *C = ConstantExpr::getOffsetOf(STy, FieldNo); + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) + C = Folded; + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); + return getTruncateOrZeroExtend(getSCEV(C), Ty); +} + +const SCEV *ScalarEvolution::getOffsetOfExpr(const Type *CTy, + Constant *FieldNo) { + Constant *C = ConstantExpr::getOffsetOf(CTy, FieldNo); + if (ConstantExpr *CE = dyn_cast(C)) + if (Constant *Folded = ConstantFoldConstantExpression(CE, TD)) + C = Folded; + const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(CTy)); + return getTruncateOrZeroExtend(getSCEV(C), Ty); +} + +const SCEV *ScalarEvolution::getUnknown(Value *V) { + // Don't attempt to do anything other than create a SCEVUnknown object + // here. createSCEV only calls getUnknown after checking for all other + // interesting possibilities, and any other code that calls getUnknown + // is doing so in order to hide a value from SCEV canonicalization. + + FoldingSetNodeID ID; + ID.AddInteger(scUnknown); + ID.AddPointer(V); + void *IP = 0; + if (SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) { + assert(cast(S)->getValue() == V && + "Stale SCEVUnknown in uniquing map!"); + return S; + } + SCEV *S = new (SCEVAllocator) SCEVUnknown(ID.Intern(SCEVAllocator), V, this, + FirstUnknown); + FirstUnknown = cast(S); + UniqueSCEVs.InsertNode(S, IP); + return S; +} + +//===----------------------------------------------------------------------===// +// Basic SCEV Analysis and PHI Idiom Recognition Code +// + +/// isSCEVable - Test if values of the given type are analyzable within +/// the SCEV framework. This primarily includes integer types, and it +/// can optionally include pointer types if the ScalarEvolution class +/// has access to target-specific information. +bool ScalarEvolution::isSCEVable(const Type *Ty) const { + // Integers and pointers are always SCEVable. + return Ty->isIntegerTy() || Ty->isPointerTy(); +} + +/// getTypeSizeInBits - Return the size in bits of the specified type, +/// for which isSCEVable must return true. +uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + // If we have a TargetData, use it! + if (TD) + return TD->getTypeSizeInBits(Ty); + + // Integer types have fixed sizes. + if (Ty->isIntegerTy()) + return Ty->getPrimitiveSizeInBits(); + + // The only other support type is pointer. Without TargetData, conservatively + // assume pointers are 64-bit. + assert(Ty->isPointerTy() && "isSCEVable permitted a non-SCEVable type!"); + return 64; +} + +/// getEffectiveSCEVType - Return a type with the same bitwidth as +/// the given type and which represents how SCEV will treat the given +/// type, for which isSCEVable must return true. For pointer types, +/// this is the pointer-sized integer type. +const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { + assert(isSCEVable(Ty) && "Type is not SCEVable!"); + + if (Ty->isIntegerTy()) + return Ty; + + // The only other support type is pointer. + assert(Ty->isPointerTy() && "Unexpected non-pointer non-integer type!"); + if (TD) return TD->getIntPtrType(getContext()); + + // Without TargetData, conservatively assume pointers are 64-bit. + return Type::getInt64Ty(getContext()); +} + +const SCEV *ScalarEvolution::getCouldNotCompute() { + return &CouldNotCompute; +} + +/// getSCEV - Return an existing SCEV if it exists, otherwise analyze the +/// expression and create a new one. +const SCEV *ScalarEvolution::getSCEV(Value *V) { + assert(isSCEVable(V->getType()) && "Value is not SCEVable!"); + + ValueExprMapType::const_iterator I = ValueExprMap.find(V); + if (I != ValueExprMap.end()) return I->second; + const SCEV *S = createSCEV(V); + + // The process of creating a SCEV for V may have caused other SCEVs + // to have been created, so it's necessary to insert the new entry + // from scratch, rather than trying to remember the insert position + // above. + ValueExprMap.insert(std::make_pair(SCEVCallbackVH(V, this), S)); + return S; +} + +/// getNegativeSCEV - Return a SCEV corresponding to -V = -1*V +/// +const SCEV *ScalarEvolution::getNegativeSCEV(const SCEV *V) { + if (const SCEVConstant *VC = dyn_cast(V)) + return getConstant( + cast(ConstantExpr::getNeg(VC->getValue()))); + + const Type *Ty = V->getType(); + Ty = getEffectiveSCEVType(Ty); + return getMulExpr(V, + getConstant(cast(Constant::getAllOnesValue(Ty)))); +} + +/// getNotSCEV - Return a SCEV corresponding to ~V = -1-V +const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) { + if (const SCEVConstant *VC = dyn_cast(V)) + return getConstant( + cast(ConstantExpr::getNot(VC->getValue()))); + + const Type *Ty = V->getType(); + Ty = getEffectiveSCEVType(Ty); + const SCEV *AllOnes = + getConstant(cast(Constant::getAllOnesValue(Ty))); + return getMinusSCEV(AllOnes, V); +} + +/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1, +/// and thus the HasNUW and HasNSW bits apply to the resultant add, not +/// whether the sub would have overflowed. +const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS, + bool HasNUW, bool HasNSW) { + // Fast path: X - X --> 0. + if (LHS == RHS) + return getConstant(LHS->getType(), 0); + + // X - Y --> X + -Y + return getAddExpr(LHS, getNegativeSCEV(RHS), HasNUW, HasNSW); +} + +/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is zero +/// extended. +const SCEV * +ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot truncate or zero extend with non-integer arguments!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) + return getTruncateExpr(V, Ty); + return getZeroExtendExpr(V, Ty); +} + +/// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is sign +/// extended. +const SCEV * +ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, + const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot truncate or zero extend with non-integer arguments!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty)) + return getTruncateExpr(V, Ty); + return getSignExtendExpr(V, Ty); +} + +/// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is zero +/// extended. The conversion must not be narrowing. +const SCEV * +ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot noop or zero extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrZeroExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getZeroExtendExpr(V, Ty); +} + +/// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. If the type must be extended, it is sign +/// extended. The conversion must not be narrowing. +const SCEV * +ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot noop or sign extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrSignExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getSignExtendExpr(V, Ty); +} + +/// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of +/// the input value to the specified type. If the type must be extended, +/// it is extended with unspecified bits. The conversion must not be +/// narrowing. +const SCEV * +ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot noop or any extend with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && + "getNoopOrAnyExtend cannot truncate!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getAnyExtendExpr(V, Ty); +} + +/// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the +/// input value to the specified type. The conversion must not be widening. +const SCEV * +ScalarEvolution::getTruncateOrNoop(const SCEV *V, const Type *Ty) { + const Type *SrcTy = V->getType(); + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && + "Cannot truncate or noop with non-integer arguments!"); + assert(getTypeSizeInBits(SrcTy) >= getTypeSizeInBits(Ty) && + "getTruncateOrNoop cannot extend!"); + if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) + return V; // No conversion + return getTruncateExpr(V, Ty); +} + +/// getUMaxFromMismatchedTypes - Promote the operands to the wider of +/// the types using zero-extension, and then perform a umax operation +/// with them. +const SCEV *ScalarEvolution::getUMaxFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS) { + const SCEV *PromotedLHS = LHS; + const SCEV *PromotedRHS = RHS; + + if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType())) + PromotedRHS = getZeroExtendExpr(RHS, LHS->getType()); + else + PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType()); + + return getUMaxExpr(PromotedLHS, PromotedRHS); +} + +/// getUMinFromMismatchedTypes - Promote the operands to the wider of +/// the types using zero-extension, and then perform a umin operation +/// with them. +const SCEV *ScalarEvolution::getUMinFromMismatchedTypes(const SCEV *LHS, + const SCEV *RHS) { + const SCEV *PromotedLHS = LHS; + const SCEV *PromotedRHS = RHS; + + if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType())) + PromotedRHS = getZeroExtendExpr(RHS, LHS->getType()); + else + PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType()); + + return getUMinExpr(PromotedLHS, PromotedRHS); +} + +/// PushDefUseChildren - Push users of the given Instruction +/// onto the given Worklist. +static void +PushDefUseChildren(Instruction *I, + SmallVectorImpl &Worklist) { + // Push the def-use children onto the Worklist stack. + for (Value::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + Worklist.push_back(cast(*UI)); +} + +/// ForgetSymbolicValue - This looks up computed SCEV values for all +/// instructions that depend on the given instruction and removes them from +/// the ValueExprMapType map if they reference SymName. This is used during PHI +/// resolution. +void +ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) { + SmallVector Worklist; + PushDefUseChildren(PN, Worklist); + + SmallPtrSet Visited; + Visited.insert(PN); + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + ValueExprMapType::iterator It = + ValueExprMap.find(static_cast(I)); + if (It != ValueExprMap.end()) { + const SCEV *Old = It->second; + + // Short-circuit the def-use traversal if the symbolic name + // ceases to appear in expressions. + if (Old != SymName && !hasOperand(Old, SymName)) + continue; + + // SCEVUnknown for a PHI either means that it has an unrecognized + // structure, it's a PHI that's in the progress of being computed + // by createNodeForPHI, or it's a single-value PHI. In the first case, + // additional loop trip count information isn't going to change anything. + // In the second case, createNodeForPHI will perform the necessary + // updates on its own when it gets to that point. In the third, we do + // want to forget the SCEVUnknown. + if (!isa(I) || + !isa(Old) || + (I != PN && Old == SymName)) { + forgetMemoizedResults(Old); + ValueExprMap.erase(It); + } + } + + PushDefUseChildren(I, Worklist); + } +} + +/// createNodeForPHI - PHI nodes have two cases. Either the PHI node exists in +/// a loop header, making it a potential recurrence, or it doesn't. +/// +const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { + if (const Loop *L = LI->getLoopFor(PN->getParent())) + if (L->getHeader() == PN->getParent()) { + // The loop may have multiple entrances or multiple exits; we can analyze + // this phi as an addrec if it has a unique entry value and a unique + // backedge value. + Value *BEValueV = 0, *StartValueV = 0; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *V = PN->getIncomingValue(i); + if (L->contains(PN->getIncomingBlock(i))) { + if (!BEValueV) { + BEValueV = V; + } else if (BEValueV != V) { + BEValueV = 0; + break; + } + } else if (!StartValueV) { + StartValueV = V; + } else if (StartValueV != V) { + StartValueV = 0; + break; + } + } + if (BEValueV && StartValueV) { + // While we are analyzing this PHI node, handle its value symbolically. + const SCEV *SymbolicName = getUnknown(PN); + assert(ValueExprMap.find(PN) == ValueExprMap.end() && + "PHI node already processed?"); + ValueExprMap.insert(std::make_pair(SCEVCallbackVH(PN, this), SymbolicName)); + + // Using this symbolic name for the PHI, analyze the value coming around + // the back-edge. + const SCEV *BEValue = getSCEV(BEValueV); + + // NOTE: If BEValue is loop invariant, we know that the PHI node just + // has a special value for the first iteration of the loop. + + // If the value coming around the backedge is an add with the symbolic + // value we just inserted, then we found a simple induction variable! + if (const SCEVAddExpr *Add = dyn_cast(BEValue)) { + // If there is a single occurrence of the symbolic value, replace it + // with a recurrence. + unsigned FoundIndex = Add->getNumOperands(); + for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i) + if (Add->getOperand(i) == SymbolicName) + if (FoundIndex == e) { + FoundIndex = i; + break; + } + + if (FoundIndex != Add->getNumOperands()) { + // Create an add with everything but the specified operand. + SmallVector Ops; + for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i) + if (i != FoundIndex) + Ops.push_back(Add->getOperand(i)); + const SCEV *Accum = getAddExpr(Ops); + + // This is not a valid addrec if the step amount is varying each + // loop iteration, but is not itself an addrec in this loop. + if (isLoopInvariant(Accum, L) || + (isa(Accum) && + cast(Accum)->getLoop() == L)) { + bool HasNUW = false; + bool HasNSW = false; + + // If the increment doesn't overflow, then neither the addrec nor + // the post-increment will overflow. + if (const AddOperator *OBO = dyn_cast(BEValueV)) { + if (OBO->hasNoUnsignedWrap()) + HasNUW = true; + if (OBO->hasNoSignedWrap()) + HasNSW = true; + } else if (const GEPOperator *GEP = + dyn_cast(BEValueV)) { + // If the increment is a GEP, then we know it won't perform a + // signed overflow, because the address space cannot be + // wrapped around. + // + // NOTE: This isn't strictly true, because you could have an + // object straddling the 2G address boundary in a 32-bit address + // space (for example). We really want to model this as a "has + // no signed/unsigned wrap" where the base pointer is treated as + // unsigned and the increment is known to not have signed + // wrapping. + // + // This is a highly theoretical concern though, and this is good + // enough for all cases we know of at this point. :) + // + HasNSW |= GEP->isInBounds(); + } + + const SCEV *StartVal = getSCEV(StartValueV); + const SCEV *PHISCEV = + getAddRecExpr(StartVal, Accum, L, HasNUW, HasNSW); + + // Since the no-wrap flags are on the increment, they apply to the + // post-incremented value as well. + if (isLoopInvariant(Accum, L)) + (void)getAddRecExpr(getAddExpr(StartVal, Accum), + Accum, L, HasNUW, HasNSW); + + // Okay, for the entire analysis of this edge we assumed the PHI + // to be symbolic. We now need to go back and purge all of the + // entries for the scalars that use the symbolic expression. + ForgetSymbolicName(PN, SymbolicName); + ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV; + return PHISCEV; + } + } + } else if (const SCEVAddRecExpr *AddRec = + dyn_cast(BEValue)) { + // Otherwise, this could be a loop like this: + // i = 0; for (j = 1; ..; ++j) { .... i = j; } + // In this case, j = {1,+,1} and BEValue is j. + // Because the other in-value of i (0) fits the evolution of BEValue + // i really is an addrec evolution. + if (AddRec->getLoop() == L && AddRec->isAffine()) { + const SCEV *StartVal = getSCEV(StartValueV); + + // If StartVal = j.start - j.stride, we can use StartVal as the + // initial step of the addrec evolution. + if (StartVal == getMinusSCEV(AddRec->getOperand(0), + AddRec->getOperand(1))) { + const SCEV *PHISCEV = + getAddRecExpr(StartVal, AddRec->getOperand(1), L); + + // Okay, for the entire analysis of this edge we assumed the PHI + // to be symbolic. We now need to go back and purge all of the + // entries for the scalars that use the symbolic expression. + ForgetSymbolicName(PN, SymbolicName); + ValueExprMap[SCEVCallbackVH(PN, this)] = PHISCEV; + return PHISCEV; + } + } + } + } + } + + // If the PHI has a single incoming value, follow that value, unless the + // PHI's incoming blocks are in a different loop, in which case doing so + // risks breaking LCSSA form. Instcombine would normally zap these, but + // it doesn't have DominatorTree information, so it may miss cases. + if (Value *V = SimplifyInstruction(PN, TD, DT)) + if (LI->replacementPreservesLCSSAForm(PN, V)) + return getSCEV(V); + + // If it's not a loop phi, we can't handle it yet. + return getUnknown(PN); +} + +/// createNodeForGEP - Expand GEP instructions into add and multiply +/// operations. This allows them to be analyzed by regular SCEV code. +/// +const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { + + // Don't blindly transfer the inbounds flag from the GEP instruction to the + // Add expression, because the Instruction may be guarded by control flow + // and the no-overflow bits may not be valid for the expression in any + // context. + bool isInBounds = GEP->isInBounds(); + + const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType()); + Value *Base = GEP->getOperand(0); + // Don't attempt to analyze GEPs over unsized objects. + if (!cast(Base->getType())->getElementType()->isSized()) + return getUnknown(GEP); + const SCEV *TotalOffset = getConstant(IntPtrTy, 0); + gep_type_iterator GTI = gep_type_begin(GEP); + for (GetElementPtrInst::op_iterator I = llvm::next(GEP->op_begin()), + E = GEP->op_end(); + I != E; ++I) { + Value *Index = *I; + // Compute the (potentially symbolic) offset in bytes for this index. + if (const StructType *STy = dyn_cast(*GTI++)) { + // For a struct, add the member offset. + unsigned FieldNo = cast(Index)->getZExtValue(); + const SCEV *FieldOffset = getOffsetOfExpr(STy, FieldNo); + + // Add the field offset to the running total offset. + TotalOffset = getAddExpr(TotalOffset, FieldOffset); + } else { + // For an array, add the element offset, explicitly scaled. + const SCEV *ElementSize = getSizeOfExpr(*GTI); + const SCEV *IndexS = getSCEV(Index); + // Getelementptr indices are signed. + IndexS = getTruncateOrSignExtend(IndexS, IntPtrTy); + + // Multiply the index by the element size to compute the element offset. + const SCEV *LocalOffset = getMulExpr(IndexS, ElementSize, /*NUW*/ false, + /*NSW*/ isInBounds); + + // Add the element offset to the running total offset. + TotalOffset = getAddExpr(TotalOffset, LocalOffset); + } + } + + // Get the SCEV for the GEP base. + const SCEV *BaseS = getSCEV(Base); + + // Add the total offset from all the GEP indices to the base. + return getAddExpr(BaseS, TotalOffset, /*NUW*/ false, + /*NSW*/ isInBounds); +} + +/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is +/// guaranteed to end in (at every loop iteration). It is, at the same time, +/// the minimum number of times S is divisible by 2. For example, given {4,+,8} +/// it returns 2. If S is guaranteed to be 0, it returns the bitwidth of S. +uint32_t +ScalarEvolution::GetMinTrailingZeros(const SCEV *S) { + if (const SCEVConstant *C = dyn_cast(S)) + return C->getValue()->getValue().countTrailingZeros(); + + if (const SCEVTruncateExpr *T = dyn_cast(S)) + return std::min(GetMinTrailingZeros(T->getOperand()), + (uint32_t)getTypeSizeInBits(T->getType())); + + if (const SCEVZeroExtendExpr *E = dyn_cast(S)) { + uint32_t OpRes = GetMinTrailingZeros(E->getOperand()); + return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ? + getTypeSizeInBits(E->getType()) : OpRes; + } + + if (const SCEVSignExtendExpr *E = dyn_cast(S)) { + uint32_t OpRes = GetMinTrailingZeros(E->getOperand()); + return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ? + getTypeSizeInBits(E->getType()) : OpRes; + } + + if (const SCEVAddExpr *A = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0)); + for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i))); + return MinOpRes; + } + + if (const SCEVMulExpr *M = dyn_cast(S)) { + // The result is the sum of all operands results. + uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0)); + uint32_t BitWidth = getTypeSizeInBits(M->getType()); + for (unsigned i = 1, e = M->getNumOperands(); + SumOpRes != BitWidth && i != e; ++i) + SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i)), + BitWidth); + return SumOpRes; + } + + if (const SCEVAddRecExpr *A = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0)); + for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i))); + return MinOpRes; + } + + if (const SCEVSMaxExpr *M = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0)); + for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i))); + return MinOpRes; + } + + if (const SCEVUMaxExpr *M = dyn_cast(S)) { + // The result is the min of all operands results. + uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0)); + for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i) + MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i))); + return MinOpRes; + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + unsigned BitWidth = getTypeSizeInBits(U->getType()); + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt Zeros(BitWidth, 0), Ones(BitWidth, 0); + ComputeMaskedBits(U->getValue(), Mask, Zeros, Ones); + return Zeros.countTrailingOnes(); + } + + // SCEVUDivExpr + return 0; +} + +/// getUnsignedRange - Determine the unsigned range for a particular SCEV. +/// +ConstantRange +ScalarEvolution::getUnsignedRange(const SCEV *S) { + // See if we've computed this range already. + DenseMap::iterator I = UnsignedRanges.find(S); + if (I != UnsignedRanges.end()) + return I->second; + + if (const SCEVConstant *C = dyn_cast(S)) + return setUnsignedRange(C, ConstantRange(C->getValue()->getValue())); + + unsigned BitWidth = getTypeSizeInBits(S->getType()); + ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true); + + // If the value has known zeros, the maximum unsigned value will have those + // known zeros as well. + uint32_t TZ = GetMinTrailingZeros(S); + if (TZ != 0) + ConservativeResult = + ConstantRange(APInt::getMinValue(BitWidth), + APInt::getMaxValue(BitWidth).lshr(TZ).shl(TZ) + 1); + + if (const SCEVAddExpr *Add = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Add->getOperand(0)); + for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) + X = X.add(getUnsignedRange(Add->getOperand(i))); + return setUnsignedRange(Add, ConservativeResult.intersectWith(X)); + } + + if (const SCEVMulExpr *Mul = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Mul->getOperand(0)); + for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) + X = X.multiply(getUnsignedRange(Mul->getOperand(i))); + return setUnsignedRange(Mul, ConservativeResult.intersectWith(X)); + } + + if (const SCEVSMaxExpr *SMax = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(SMax->getOperand(0)); + for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) + X = X.smax(getUnsignedRange(SMax->getOperand(i))); + return setUnsignedRange(SMax, ConservativeResult.intersectWith(X)); + } + + if (const SCEVUMaxExpr *UMax = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(UMax->getOperand(0)); + for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) + X = X.umax(getUnsignedRange(UMax->getOperand(i))); + return setUnsignedRange(UMax, ConservativeResult.intersectWith(X)); + } + + if (const SCEVUDivExpr *UDiv = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(UDiv->getLHS()); + ConstantRange Y = getUnsignedRange(UDiv->getRHS()); + return setUnsignedRange(UDiv, ConservativeResult.intersectWith(X.udiv(Y))); + } + + if (const SCEVZeroExtendExpr *ZExt = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(ZExt->getOperand()); + return setUnsignedRange(ZExt, + ConservativeResult.intersectWith(X.zeroExtend(BitWidth))); + } + + if (const SCEVSignExtendExpr *SExt = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(SExt->getOperand()); + return setUnsignedRange(SExt, + ConservativeResult.intersectWith(X.signExtend(BitWidth))); + } + + if (const SCEVTruncateExpr *Trunc = dyn_cast(S)) { + ConstantRange X = getUnsignedRange(Trunc->getOperand()); + return setUnsignedRange(Trunc, + ConservativeResult.intersectWith(X.truncate(BitWidth))); + } + + if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { + // If there's no unsigned wrap, the value will never be less than its + // initial value. + if (AddRec->hasNoUnsignedWrap()) + if (const SCEVConstant *C = dyn_cast(AddRec->getStart())) + if (!C->getValue()->isZero()) + ConservativeResult = + ConservativeResult.intersectWith( + ConstantRange(C->getValue()->getValue(), APInt(BitWidth, 0))); + + // TODO: non-affine addrec + if (AddRec->isAffine()) { + const Type *Ty = AddRec->getType(); + const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); + if (!isa(MaxBECount) && + getTypeSizeInBits(MaxBECount->getType()) <= BitWidth) { + MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); + + const SCEV *Start = AddRec->getStart(); + const SCEV *Step = AddRec->getStepRecurrence(*this); + + ConstantRange StartRange = getUnsignedRange(Start); + ConstantRange StepRange = getSignedRange(Step); + ConstantRange MaxBECountRange = getUnsignedRange(MaxBECount); + ConstantRange EndRange = + StartRange.add(MaxBECountRange.multiply(StepRange)); + + // Check for overflow. This must be done with ConstantRange arithmetic + // because we could be called from within the ScalarEvolution overflow + // checking code. + ConstantRange ExtStartRange = StartRange.zextOrTrunc(BitWidth*2+1); + ConstantRange ExtStepRange = StepRange.sextOrTrunc(BitWidth*2+1); + ConstantRange ExtMaxBECountRange = + MaxBECountRange.zextOrTrunc(BitWidth*2+1); + ConstantRange ExtEndRange = EndRange.zextOrTrunc(BitWidth*2+1); + if (ExtStartRange.add(ExtMaxBECountRange.multiply(ExtStepRange)) != + ExtEndRange) + return setUnsignedRange(AddRec, ConservativeResult); + + APInt Min = APIntOps::umin(StartRange.getUnsignedMin(), + EndRange.getUnsignedMin()); + APInt Max = APIntOps::umax(StartRange.getUnsignedMax(), + EndRange.getUnsignedMax()); + if (Min.isMinValue() && Max.isMaxValue()) + return setUnsignedRange(AddRec, ConservativeResult); + return setUnsignedRange(AddRec, + ConservativeResult.intersectWith(ConstantRange(Min, Max+1))); + } + } + + return setUnsignedRange(AddRec, ConservativeResult); + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt Zeros(BitWidth, 0), Ones(BitWidth, 0); + ComputeMaskedBits(U->getValue(), Mask, Zeros, Ones, TD); + if (Ones == ~Zeros + 1) + return setUnsignedRange(U, ConservativeResult); + return setUnsignedRange(U, + ConservativeResult.intersectWith(ConstantRange(Ones, ~Zeros + 1))); + } + + return setUnsignedRange(S, ConservativeResult); +} + +/// getSignedRange - Determine the signed range for a particular SCEV. +/// +ConstantRange +ScalarEvolution::getSignedRange(const SCEV *S) { + // See if we've computed this range already. + DenseMap::iterator I = SignedRanges.find(S); + if (I != SignedRanges.end()) + return I->second; + + if (const SCEVConstant *C = dyn_cast(S)) + return setSignedRange(C, ConstantRange(C->getValue()->getValue())); + + unsigned BitWidth = getTypeSizeInBits(S->getType()); + ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true); + + // If the value has known zeros, the maximum signed value will have those + // known zeros as well. + uint32_t TZ = GetMinTrailingZeros(S); + if (TZ != 0) + ConservativeResult = + ConstantRange(APInt::getSignedMinValue(BitWidth), + APInt::getSignedMaxValue(BitWidth).ashr(TZ).shl(TZ) + 1); + + if (const SCEVAddExpr *Add = dyn_cast(S)) { + ConstantRange X = getSignedRange(Add->getOperand(0)); + for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) + X = X.add(getSignedRange(Add->getOperand(i))); + return setSignedRange(Add, ConservativeResult.intersectWith(X)); + } + + if (const SCEVMulExpr *Mul = dyn_cast(S)) { + ConstantRange X = getSignedRange(Mul->getOperand(0)); + for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) + X = X.multiply(getSignedRange(Mul->getOperand(i))); + return setSignedRange(Mul, ConservativeResult.intersectWith(X)); + } + + if (const SCEVSMaxExpr *SMax = dyn_cast(S)) { + ConstantRange X = getSignedRange(SMax->getOperand(0)); + for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) + X = X.smax(getSignedRange(SMax->getOperand(i))); + return setSignedRange(SMax, ConservativeResult.intersectWith(X)); + } + + if (const SCEVUMaxExpr *UMax = dyn_cast(S)) { + ConstantRange X = getSignedRange(UMax->getOperand(0)); + for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) + X = X.umax(getSignedRange(UMax->getOperand(i))); + return setSignedRange(UMax, ConservativeResult.intersectWith(X)); + } + + if (const SCEVUDivExpr *UDiv = dyn_cast(S)) { + ConstantRange X = getSignedRange(UDiv->getLHS()); + ConstantRange Y = getSignedRange(UDiv->getRHS()); + return setSignedRange(UDiv, ConservativeResult.intersectWith(X.udiv(Y))); + } + + if (const SCEVZeroExtendExpr *ZExt = dyn_cast(S)) { + ConstantRange X = getSignedRange(ZExt->getOperand()); + return setSignedRange(ZExt, + ConservativeResult.intersectWith(X.zeroExtend(BitWidth))); + } + + if (const SCEVSignExtendExpr *SExt = dyn_cast(S)) { + ConstantRange X = getSignedRange(SExt->getOperand()); + return setSignedRange(SExt, + ConservativeResult.intersectWith(X.signExtend(BitWidth))); + } + + if (const SCEVTruncateExpr *Trunc = dyn_cast(S)) { + ConstantRange X = getSignedRange(Trunc->getOperand()); + return setSignedRange(Trunc, + ConservativeResult.intersectWith(X.truncate(BitWidth))); + } + + if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { + // If there's no signed wrap, and all the operands have the same sign or + // zero, the value won't ever change sign. + if (AddRec->hasNoSignedWrap()) { + bool AllNonNeg = true; + bool AllNonPos = true; + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) { + if (!isKnownNonNegative(AddRec->getOperand(i))) AllNonNeg = false; + if (!isKnownNonPositive(AddRec->getOperand(i))) AllNonPos = false; + } + if (AllNonNeg) + ConservativeResult = ConservativeResult.intersectWith( + ConstantRange(APInt(BitWidth, 0), + APInt::getSignedMinValue(BitWidth))); + else if (AllNonPos) + ConservativeResult = ConservativeResult.intersectWith( + ConstantRange(APInt::getSignedMinValue(BitWidth), + APInt(BitWidth, 1))); + } + + // TODO: non-affine addrec + if (AddRec->isAffine()) { + const Type *Ty = AddRec->getType(); + const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop()); + if (!isa(MaxBECount) && + getTypeSizeInBits(MaxBECount->getType()) <= BitWidth) { + MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty); + + const SCEV *Start = AddRec->getStart(); + const SCEV *Step = AddRec->getStepRecurrence(*this); + + ConstantRange StartRange = getSignedRange(Start); + ConstantRange StepRange = getSignedRange(Step); + ConstantRange MaxBECountRange = getUnsignedRange(MaxBECount); + ConstantRange EndRange = + StartRange.add(MaxBECountRange.multiply(StepRange)); + + // Check for overflow. This must be done with ConstantRange arithmetic + // because we could be called from within the ScalarEvolution overflow + // checking code. + ConstantRange ExtStartRange = StartRange.sextOrTrunc(BitWidth*2+1); + ConstantRange ExtStepRange = StepRange.sextOrTrunc(BitWidth*2+1); + ConstantRange ExtMaxBECountRange = + MaxBECountRange.zextOrTrunc(BitWidth*2+1); + ConstantRange ExtEndRange = EndRange.sextOrTrunc(BitWidth*2+1); + if (ExtStartRange.add(ExtMaxBECountRange.multiply(ExtStepRange)) != + ExtEndRange) + return setSignedRange(AddRec, ConservativeResult); + + APInt Min = APIntOps::smin(StartRange.getSignedMin(), + EndRange.getSignedMin()); + APInt Max = APIntOps::smax(StartRange.getSignedMax(), + EndRange.getSignedMax()); + if (Min.isMinSignedValue() && Max.isMaxSignedValue()) + return setSignedRange(AddRec, ConservativeResult); + return setSignedRange(AddRec, + ConservativeResult.intersectWith(ConstantRange(Min, Max+1))); + } + } + + return setSignedRange(AddRec, ConservativeResult); + } + + if (const SCEVUnknown *U = dyn_cast(S)) { + // For a SCEVUnknown, ask ValueTracking. + if (!U->getValue()->getType()->isIntegerTy() && !TD) + return setSignedRange(U, ConservativeResult); + unsigned NS = ComputeNumSignBits(U->getValue(), TD); + if (NS == 1) + return setSignedRange(U, ConservativeResult); + return setSignedRange(U, ConservativeResult.intersectWith( + ConstantRange(APInt::getSignedMinValue(BitWidth).ashr(NS - 1), + APInt::getSignedMaxValue(BitWidth).ashr(NS - 1)+1))); + } + + return setSignedRange(S, ConservativeResult); +} + +/// createSCEV - We know that there is no SCEV for the specified value. +/// Analyze the expression. +/// +const SCEV *ScalarEvolution::createSCEV(Value *V) { + if (!isSCEVable(V->getType())) + return getUnknown(V); + + unsigned Opcode = Instruction::UserOp1; + if (Instruction *I = dyn_cast(V)) { + Opcode = I->getOpcode(); + + // Don't attempt to analyze instructions in blocks that aren't + // reachable. Such instructions don't matter, and they aren't required + // to obey basic rules for definitions dominating uses which this + // analysis depends on. + if (!DT->isReachableFromEntry(I->getParent())) + return getUnknown(V); + } else if (ConstantExpr *CE = dyn_cast(V)) + Opcode = CE->getOpcode(); + else if (ConstantInt *CI = dyn_cast(V)) + return getConstant(CI); + else if (isa(V)) + return getConstant(V->getType(), 0); + else if (GlobalAlias *GA = dyn_cast(V)) + return GA->mayBeOverridden() ? getUnknown(V) : getSCEV(GA->getAliasee()); + else + return getUnknown(V); + + Operator *U = cast(V); + switch (Opcode) { + case Instruction::Add: { + // The simple thing to do would be to just call getSCEV on both operands + // and call getAddExpr with the result. However if we're looking at a + // bunch of things all added together, this can be quite inefficient, + // because it leads to N-1 getAddExpr calls for N ultimate operands. + // Instead, gather up all the operands and make a single getAddExpr call. + // LLVM IR canonical form means we need only traverse the left operands. + SmallVector AddOps; + AddOps.push_back(getSCEV(U->getOperand(1))); + for (Value *Op = U->getOperand(0); ; Op = U->getOperand(0)) { + unsigned Opcode = Op->getValueID() - Value::InstructionVal; + if (Opcode != Instruction::Add && Opcode != Instruction::Sub) + break; + U = cast(Op); + const SCEV *Op1 = getSCEV(U->getOperand(1)); + if (Opcode == Instruction::Sub) + AddOps.push_back(getNegativeSCEV(Op1)); + else + AddOps.push_back(Op1); + } + AddOps.push_back(getSCEV(U->getOperand(0))); + return getAddExpr(AddOps); + } + case Instruction::Mul: { + // See the Add code above. + SmallVector MulOps; + MulOps.push_back(getSCEV(U->getOperand(1))); + for (Value *Op = U->getOperand(0); + Op->getValueID() == Instruction::Mul + Value::InstructionVal; + Op = U->getOperand(0)) { + U = cast(Op); + MulOps.push_back(getSCEV(U->getOperand(1))); + } + MulOps.push_back(getSCEV(U->getOperand(0))); + return getMulExpr(MulOps); + } + case Instruction::UDiv: + return getUDivExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Sub: + return getMinusSCEV(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::And: + // For an expression like x&255 that merely masks off the high bits, + // use zext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + if (CI->isNullValue()) + return getSCEV(U->getOperand(1)); + if (CI->isAllOnesValue()) + return getSCEV(U->getOperand(0)); + const APInt &A = CI->getValue(); + + // Instcombine's ShrinkDemandedConstant may strip bits out of + // constants, obscuring what would otherwise be a low-bits mask. + // Use ComputeMaskedBits to compute what ShrinkDemandedConstant + // knew about to reconstruct a low-bits mask value. + unsigned LZ = A.countLeadingZeros(); + unsigned BitWidth = A.getBitWidth(); + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0); + ComputeMaskedBits(U->getOperand(0), AllOnes, KnownZero, KnownOne, TD); + + APInt EffectiveMask = APInt::getLowBitsSet(BitWidth, BitWidth - LZ); + + if (LZ != 0 && !((~A & ~KnownZero) & EffectiveMask)) + return + getZeroExtendExpr(getTruncateExpr(getSCEV(U->getOperand(0)), + IntegerType::get(getContext(), BitWidth - LZ)), + U->getType()); + } + break; + + case Instruction::Or: + // If the RHS of the Or is a constant, we may have something like: + // X*4+1 which got turned into X*4|1. Handle this as an Add so loop + // optimizations will transparently handle this case. + // + // In order for this transformation to be safe, the LHS must be of the + // form X*(2^n) and the Or constant must be less than 2^n. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + const SCEV *LHS = getSCEV(U->getOperand(0)); + const APInt &CIVal = CI->getValue(); + if (GetMinTrailingZeros(LHS) >= + (CIVal.getBitWidth() - CIVal.countLeadingZeros())) { + // Build a plain add SCEV. + const SCEV *S = getAddExpr(LHS, getSCEV(CI)); + // If the LHS of the add was an addrec and it has no-wrap flags, + // transfer the no-wrap flags, since an or won't introduce a wrap. + if (const SCEVAddRecExpr *NewAR = dyn_cast(S)) { + const SCEVAddRecExpr *OldAR = cast(LHS); + if (OldAR->hasNoUnsignedWrap()) + const_cast(NewAR)->setHasNoUnsignedWrap(true); + if (OldAR->hasNoSignedWrap()) + const_cast(NewAR)->setHasNoSignedWrap(true); + } + return S; + } + } + break; + case Instruction::Xor: + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + // If the RHS of the xor is a signbit, then this is just an add. + // Instcombine turns add of signbit into xor as a strength reduction step. + if (CI->getValue().isSignBit()) + return getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + + // If the RHS of xor is -1, then this is a not operation. + if (CI->isAllOnesValue()) + return getNotSCEV(getSCEV(U->getOperand(0))); + + // Model xor(and(x, C), C) as and(~x, C), if C is a low-bits mask. + // This is a variant of the check for xor with -1, and it handles + // the case where instcombine has trimmed non-demanded bits out + // of an xor with -1. + if (BinaryOperator *BO = dyn_cast(U->getOperand(0))) + if (ConstantInt *LCI = dyn_cast(BO->getOperand(1))) + if (BO->getOpcode() == Instruction::And && + LCI->getValue() == CI->getValue()) + if (const SCEVZeroExtendExpr *Z = + dyn_cast(getSCEV(U->getOperand(0)))) { + const Type *UTy = U->getType(); + const SCEV *Z0 = Z->getOperand(); + const Type *Z0Ty = Z0->getType(); + unsigned Z0TySize = getTypeSizeInBits(Z0Ty); + + // If C is a low-bits mask, the zero extend is serving to + // mask off the high bits. Complement the operand and + // re-apply the zext. + if (APIntOps::isMask(Z0TySize, CI->getValue())) + return getZeroExtendExpr(getNotSCEV(Z0), UTy); + + // If C is a single bit, it may be in the sign-bit position + // before the zero-extend. In this case, represent the xor + // using an add, which is equivalent, and re-apply the zext. + APInt Trunc = CI->getValue().trunc(Z0TySize); + if (Trunc.zext(getTypeSizeInBits(UTy)) == CI->getValue() && + Trunc.isSignBit()) + return getZeroExtendExpr(getAddExpr(Z0, getConstant(Trunc)), + UTy); + } + } + break; + + case Instruction::Shl: + // Turn shift left of a constant amount into a multiply. + if (ConstantInt *SA = dyn_cast(U->getOperand(1))) { + uint32_t BitWidth = cast(U->getType())->getBitWidth(); + + // If the shift count is not less than the bitwidth, the result of + // the shift is undefined. Don't try to analyze it, because the + // resolution chosen here may differ from the resolution chosen in + // other parts of the compiler. + if (SA->getValue().uge(BitWidth)) + break; + + Constant *X = ConstantInt::get(getContext(), + APInt(BitWidth, 1).shl(SA->getZExtValue())); + return getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + } + break; + + case Instruction::LShr: + // Turn logical shift right of a constant into a unsigned divide. + if (ConstantInt *SA = dyn_cast(U->getOperand(1))) { + uint32_t BitWidth = cast(U->getType())->getBitWidth(); + + // If the shift count is not less than the bitwidth, the result of + // the shift is undefined. Don't try to analyze it, because the + // resolution chosen here may differ from the resolution chosen in + // other parts of the compiler. + if (SA->getValue().uge(BitWidth)) + break; + + Constant *X = ConstantInt::get(getContext(), + APInt(BitWidth, 1).shl(SA->getZExtValue())); + return getUDivExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + } + break; + + case Instruction::AShr: + // For a two-shift sext-inreg, use sext(trunc(x)) as the SCEV expression. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) + if (Operator *L = dyn_cast(U->getOperand(0))) + if (L->getOpcode() == Instruction::Shl && + L->getOperand(1) == U->getOperand(1)) { + uint64_t BitWidth = getTypeSizeInBits(U->getType()); + + // If the shift count is not less than the bitwidth, the result of + // the shift is undefined. Don't try to analyze it, because the + // resolution chosen here may differ from the resolution chosen in + // other parts of the compiler. + if (CI->getValue().uge(BitWidth)) + break; + + uint64_t Amt = BitWidth - CI->getZExtValue(); + if (Amt == BitWidth) + return getSCEV(L->getOperand(0)); // shift by zero --> noop + return + getSignExtendExpr(getTruncateExpr(getSCEV(L->getOperand(0)), + IntegerType::get(getContext(), + Amt)), + U->getType()); + } + break; + + case Instruction::Trunc: + return getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::ZExt: + return getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::SExt: + return getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::BitCast: + // BitCasts are no-op casts so we just eliminate the cast. + if (isSCEVable(U->getType()) && isSCEVable(U->getOperand(0)->getType())) + return getSCEV(U->getOperand(0)); + break; + + // It's tempting to handle inttoptr and ptrtoint as no-ops, however this can + // lead to pointer expressions which cannot safely be expanded to GEPs, + // because ScalarEvolution doesn't respect the GEP aliasing rules when + // simplifying integer expressions. + + case Instruction::GetElementPtr: + return createNodeForGEP(cast(U)); + + case Instruction::PHI: + return createNodeForPHI(cast(U)); + + case Instruction::Select: + // This could be a smax or umax that was lowered earlier. + // Try to recover it. + if (ICmpInst *ICI = dyn_cast(U->getOperand(0))) { + Value *LHS = ICI->getOperand(0); + Value *RHS = ICI->getOperand(1); + switch (ICI->getPredicate()) { + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + // a >s b ? a+x : b+x -> smax(a, b)+x + // a >s b ? b+x : a+x -> smin(a, b)+x + if (LHS->getType() == U->getType()) { + const SCEV *LS = getSCEV(LHS); + const SCEV *RS = getSCEV(RHS); + const SCEV *LA = getSCEV(U->getOperand(1)); + const SCEV *RA = getSCEV(U->getOperand(2)); + const SCEV *LDiff = getMinusSCEV(LA, LS); + const SCEV *RDiff = getMinusSCEV(RA, RS); + if (LDiff == RDiff) + return getAddExpr(getSMaxExpr(LS, RS), LDiff); + LDiff = getMinusSCEV(LA, RS); + RDiff = getMinusSCEV(RA, LS); + if (LDiff == RDiff) + return getAddExpr(getSMinExpr(LS, RS), LDiff); + } + break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + // a >u b ? a+x : b+x -> umax(a, b)+x + // a >u b ? b+x : a+x -> umin(a, b)+x + if (LHS->getType() == U->getType()) { + const SCEV *LS = getSCEV(LHS); + const SCEV *RS = getSCEV(RHS); + const SCEV *LA = getSCEV(U->getOperand(1)); + const SCEV *RA = getSCEV(U->getOperand(2)); + const SCEV *LDiff = getMinusSCEV(LA, LS); + const SCEV *RDiff = getMinusSCEV(RA, RS); + if (LDiff == RDiff) + return getAddExpr(getUMaxExpr(LS, RS), LDiff); + LDiff = getMinusSCEV(LA, RS); + RDiff = getMinusSCEV(RA, LS); + if (LDiff == RDiff) + return getAddExpr(getUMinExpr(LS, RS), LDiff); + } + break; + case ICmpInst::ICMP_NE: + // n != 0 ? n+x : 1+x -> umax(n, 1)+x + if (LHS->getType() == U->getType() && + isa(RHS) && + cast(RHS)->isZero()) { + const SCEV *One = getConstant(LHS->getType(), 1); + const SCEV *LS = getSCEV(LHS); + const SCEV *LA = getSCEV(U->getOperand(1)); + const SCEV *RA = getSCEV(U->getOperand(2)); + const SCEV *LDiff = getMinusSCEV(LA, LS); + const SCEV *RDiff = getMinusSCEV(RA, One); + if (LDiff == RDiff) + return getAddExpr(getUMaxExpr(One, LS), LDiff); + } + break; + case ICmpInst::ICMP_EQ: + // n == 0 ? 1+x : n+x -> umax(n, 1)+x + if (LHS->getType() == U->getType() && + isa(RHS) && + cast(RHS)->isZero()) { + const SCEV *One = getConstant(LHS->getType(), 1); + const SCEV *LS = getSCEV(LHS); + const SCEV *LA = getSCEV(U->getOperand(1)); + const SCEV *RA = getSCEV(U->getOperand(2)); + const SCEV *LDiff = getMinusSCEV(LA, One); + const SCEV *RDiff = getMinusSCEV(RA, LS); + if (LDiff == RDiff) + return getAddExpr(getUMaxExpr(One, LS), LDiff); + } + break; + default: + break; + } + } + + default: // We cannot analyze this expression. + break; + } + + return getUnknown(V); +} + + + +//===----------------------------------------------------------------------===// +// Iteration Count Computation Code +// + +/// getBackedgeTakenCount - If the specified loop has a predictable +/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute +/// object. The backedge-taken count is the number of times the loop header +/// will be branched to from within the loop. This is one less than the +/// trip count of the loop, since it doesn't count the first iteration, +/// when the header is branched to from outside the loop. +/// +/// Note that it is not valid to call this method on a loop without a +/// loop-invariant backedge-taken count (see +/// hasLoopInvariantBackedgeTakenCount). +/// +const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenInfo(L).Exact; +} + +/// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except +/// return the least SCEV value that is known never to be less than the +/// actual backedge taken count. +const SCEV *ScalarEvolution::getMaxBackedgeTakenCount(const Loop *L) { + return getBackedgeTakenInfo(L).Max; +} + +/// PushLoopPHIs - Push PHI nodes in the header of the given loop +/// onto the given Worklist. +static void +PushLoopPHIs(const Loop *L, SmallVectorImpl &Worklist) { + BasicBlock *Header = L->getHeader(); + + // Push all Loop-header PHIs onto the Worklist stack. + for (BasicBlock::iterator I = Header->begin(); + PHINode *PN = dyn_cast(I); ++I) + Worklist.push_back(PN); +} + +const ScalarEvolution::BackedgeTakenInfo & +ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { + // Initially insert a CouldNotCompute for this loop. If the insertion + // succeeds, proceed to actually compute a backedge-taken count and + // update the value. The temporary CouldNotCompute value tells SCEV + // code elsewhere that it shouldn't attempt to request a new + // backedge-taken count, which could result in infinite recursion. + std::pair::iterator, bool> Pair = + BackedgeTakenCounts.insert(std::make_pair(L, getCouldNotCompute())); + if (!Pair.second) + return Pair.first->second; + + BackedgeTakenInfo BECount = ComputeBackedgeTakenCount(L); + if (BECount.Exact != getCouldNotCompute()) { + assert(isLoopInvariant(BECount.Exact, L) && + isLoopInvariant(BECount.Max, L) && + "Computed backedge-taken count isn't loop invariant for loop!"); + ++NumTripCountsComputed; + + // Update the value in the map. + Pair.first->second = BECount; + } else { + if (BECount.Max != getCouldNotCompute()) + // Update the value in the map. + Pair.first->second = BECount; + if (isa(L->getHeader()->begin())) + // Only count loops that have phi nodes as not being computable. + ++NumTripCountsNotComputed; + } + + // Now that we know more about the trip count for this loop, forget any + // existing SCEV values for PHI nodes in this loop since they are only + // conservative estimates made without the benefit of trip count + // information. This is similar to the code in forgetLoop, except that + // it handles SCEVUnknown PHI nodes specially. + if (BECount.hasAnyInfo()) { + SmallVector Worklist; + PushLoopPHIs(L, Worklist); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + ValueExprMapType::iterator It = + ValueExprMap.find(static_cast(I)); + if (It != ValueExprMap.end()) { + const SCEV *Old = It->second; + + // SCEVUnknown for a PHI either means that it has an unrecognized + // structure, or it's a PHI that's in the progress of being computed + // by createNodeForPHI. In the former case, additional loop trip + // count information isn't going to change anything. In the later + // case, createNodeForPHI will perform the necessary updates on its + // own when it gets to that point. + if (!isa(I) || !isa(Old)) { + forgetMemoizedResults(Old); + ValueExprMap.erase(It); + } + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } + } + return Pair.first->second; +} + +/// forgetLoop - This method should be called by the client when it has +/// changed a loop in a way that may effect ScalarEvolution's ability to +/// compute a trip count, or if the loop is deleted. +void ScalarEvolution::forgetLoop(const Loop *L) { + // Drop any stored trip count value. + BackedgeTakenCounts.erase(L); + + // Drop information about expressions based on loop-header PHIs. + SmallVector Worklist; + PushLoopPHIs(L, Worklist); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + Instruction *I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + ValueExprMapType::iterator It = ValueExprMap.find(static_cast(I)); + if (It != ValueExprMap.end()) { + forgetMemoizedResults(It->second); + ValueExprMap.erase(It); + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } + + // Forget all contained loops too, to avoid dangling entries in the + // ValuesAtScopes map. + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + forgetLoop(*I); +} + +/// forgetValue - This method should be called by the client when it has +/// changed a value in a way that may effect its value, or which may +/// disconnect it from a def-use chain linking it to a loop. +void ScalarEvolution::forgetValue(Value *V) { + Instruction *I = dyn_cast(V); + if (!I) return; + + // Drop information about expressions based on loop-header PHIs. + SmallVector Worklist; + Worklist.push_back(I); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + ValueExprMapType::iterator It = ValueExprMap.find(static_cast(I)); + if (It != ValueExprMap.end()) { + forgetMemoizedResults(It->second); + ValueExprMap.erase(It); + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } +} + +/// ComputeBackedgeTakenCount - Compute the number of times the backedge +/// of the specified loop will execute. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) { + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + // Examine all exits and pick the most conservative values. + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + bool CouldNotComputeBECount = false; + for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { + BackedgeTakenInfo NewBTI = + ComputeBackedgeTakenCountFromExit(L, ExitingBlocks[i]); + + if (NewBTI.Exact == getCouldNotCompute()) { + // We couldn't compute an exact value for this exit, so + // we won't be able to compute an exact value for the loop. + CouldNotComputeBECount = true; + BECount = getCouldNotCompute(); + } else if (!CouldNotComputeBECount) { + if (BECount == getCouldNotCompute()) + BECount = NewBTI.Exact; + else + BECount = getUMinFromMismatchedTypes(BECount, NewBTI.Exact); + } + if (MaxBECount == getCouldNotCompute()) + MaxBECount = NewBTI.Max; + else if (NewBTI.Max != getCouldNotCompute()) + MaxBECount = getUMinFromMismatchedTypes(MaxBECount, NewBTI.Max); + } + + return BackedgeTakenInfo(BECount, MaxBECount); +} + +/// ComputeBackedgeTakenCountFromExit - Compute the number of times the backedge +/// of the specified loop will execute if it exits via the specified block. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L, + BasicBlock *ExitingBlock) { + + // Okay, we've chosen an exiting block. See what condition causes us to + // exit at this block. + // + // FIXME: we should be able to handle switch instructions (with a single exit) + BranchInst *ExitBr = dyn_cast(ExitingBlock->getTerminator()); + if (ExitBr == 0) return getCouldNotCompute(); + assert(ExitBr->isConditional() && "If unconditional, it can't be in loop!"); + + // At this point, we know we have a conditional branch that determines whether + // the loop is exited. However, we don't know if the branch is executed each + // time through the loop. If not, then the execution count of the branch will + // not be equal to the trip count of the loop. + // + // Currently we check for this by checking to see if the Exit branch goes to + // the loop header. If so, we know it will always execute the same number of + // times as the loop. We also handle the case where the exit block *is* the + // loop header. This is common for un-rotated loops. + // + // If both of those tests fail, walk up the unique predecessor chain to the + // header, stopping if there is an edge that doesn't exit the loop. If the + // header is reached, the execution count of the branch will be equal to the + // trip count of the loop. + // + // More extensive analysis could be done to handle more cases here. + // + if (ExitBr->getSuccessor(0) != L->getHeader() && + ExitBr->getSuccessor(1) != L->getHeader() && + ExitBr->getParent() != L->getHeader()) { + // The simple checks failed, try climbing the unique predecessor chain + // up to the header. + bool Ok = false; + for (BasicBlock *BB = ExitBr->getParent(); BB; ) { + BasicBlock *Pred = BB->getUniquePredecessor(); + if (!Pred) + return getCouldNotCompute(); + TerminatorInst *PredTerm = Pred->getTerminator(); + for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i) { + BasicBlock *PredSucc = PredTerm->getSuccessor(i); + if (PredSucc == BB) + continue; + // If the predecessor has a successor that isn't BB and isn't + // outside the loop, assume the worst. + if (L->contains(PredSucc)) + return getCouldNotCompute(); + } + if (Pred == L->getHeader()) { + Ok = true; + break; + } + BB = Pred; + } + if (!Ok) + return getCouldNotCompute(); + } + + // Proceed to the next level to examine the exit condition expression. + return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(), + ExitBr->getSuccessor(0), + ExitBr->getSuccessor(1)); +} + +/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the +/// backedge of the specified loop will execute if its exit condition +/// were a conditional branch of ExitCond, TBB, and FBB. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, + Value *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { + // Check if the controlling expression for this loop is an And or Or. + if (BinaryOperator *BO = dyn_cast(ExitCond)) { + if (BO->getOpcode() == Instruction::And) { + // Recurse on the operands of the and. + BackedgeTakenInfo BTI0 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); + BackedgeTakenInfo BTI1 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + if (L->contains(TBB)) { + // Both conditions must be true for the loop to continue executing. + // Choose the less conservative count. + if (BTI0.Exact == getCouldNotCompute() || + BTI1.Exact == getCouldNotCompute()) + BECount = getCouldNotCompute(); + else + BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max == getCouldNotCompute()) + MaxBECount = BTI1.Max; + else if (BTI1.Max == getCouldNotCompute()) + MaxBECount = BTI0.Max; + else + MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + } else { + // Both conditions must be true at the same time for the loop to exit. + // For now, be conservative. + assert(L->contains(FBB) && "Loop block has no successor in loop!"); + if (BTI0.Max == BTI1.Max) + MaxBECount = BTI0.Max; + if (BTI0.Exact == BTI1.Exact) + BECount = BTI0.Exact; + } + + return BackedgeTakenInfo(BECount, MaxBECount); + } + if (BO->getOpcode() == Instruction::Or) { + // Recurse on the operands of the or. + BackedgeTakenInfo BTI0 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB); + BackedgeTakenInfo BTI1 = + ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB); + const SCEV *BECount = getCouldNotCompute(); + const SCEV *MaxBECount = getCouldNotCompute(); + if (L->contains(FBB)) { + // Both conditions must be false for the loop to continue executing. + // Choose the less conservative count. + if (BTI0.Exact == getCouldNotCompute() || + BTI1.Exact == getCouldNotCompute()) + BECount = getCouldNotCompute(); + else + BECount = getUMinFromMismatchedTypes(BTI0.Exact, BTI1.Exact); + if (BTI0.Max == getCouldNotCompute()) + MaxBECount = BTI1.Max; + else if (BTI1.Max == getCouldNotCompute()) + MaxBECount = BTI0.Max; + else + MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max); + } else { + // Both conditions must be false at the same time for the loop to exit. + // For now, be conservative. + assert(L->contains(TBB) && "Loop block has no successor in loop!"); + if (BTI0.Max == BTI1.Max) + MaxBECount = BTI0.Max; + if (BTI0.Exact == BTI1.Exact) + BECount = BTI0.Exact; + } + + return BackedgeTakenInfo(BECount, MaxBECount); + } + } + + // With an icmp, it may be feasible to compute an exact backedge-taken count. + // Proceed to the next level to examine the icmp. + if (ICmpInst *ExitCondICmp = dyn_cast(ExitCond)) + return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB); + + // Check for a constant condition. These are normally stripped out by + // SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to + // preserve the CFG and is temporarily leaving constant conditions + // in place. + if (ConstantInt *CI = dyn_cast(ExitCond)) { + if (L->contains(FBB) == !CI->getZExtValue()) + // The backedge is always taken. + return getCouldNotCompute(); + else + // The backedge is never taken. + return getConstant(CI->getType(), 0); + } + + // If it's not an integer or pointer comparison then compute it the hard way. + return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); +} + +static const SCEVAddRecExpr * +isSimpleUnwrappingAddRec(const SCEV *S, const Loop *L) { + const SCEVAddRecExpr *SA = dyn_cast(S); + + // The SCEV must be an addrec of this loop. + if (!SA || SA->getLoop() != L || !SA->isAffine()) + return 0; + + // The SCEV must be known to not wrap in some way to be interesting. + if (!SA->hasNoUnsignedWrap() && !SA->hasNoSignedWrap()) + return 0; + + // The stride must be a constant so that we know if it is striding up or down. + if (!isa(SA->getOperand(1))) + return 0; + return SA; +} + +/// getMinusSCEVForExitTest - When considering an exit test for a loop with a +/// "x != y" exit test, we turn this into a computation that evaluates x-y != 0, +/// and this function returns the expression to use for x-y. We know and take +/// advantage of the fact that this subtraction is only being used in a +/// comparison by zero context. +/// +static const SCEV *getMinusSCEVForExitTest(const SCEV *LHS, const SCEV *RHS, + const Loop *L, ScalarEvolution &SE) { + // If either LHS or RHS is an AddRec SCEV (of this loop) that is known to not + // wrap (either NSW or NUW), then we know that the value will either become + // the other one (and thus the loop terminates), that the loop will terminate + // through some other exit condition first, or that the loop has undefined + // behavior. This information is useful when the addrec has a stride that is + // != 1 or -1, because it means we can't "miss" the exit value. + // + // In any of these three cases, it is safe to turn the exit condition into a + // "counting down" AddRec (to zero) by subtracting the two inputs as normal, + // but since we know that the "end cannot be missed" we can force the + // resulting AddRec to be a NUW addrec. Since it is counting down, this means + // that the AddRec *cannot* pass zero. + + // See if LHS and RHS are addrec's we can handle. + const SCEVAddRecExpr *LHSA = isSimpleUnwrappingAddRec(LHS, L); + const SCEVAddRecExpr *RHSA = isSimpleUnwrappingAddRec(RHS, L); + + // If neither addrec is interesting, just return a minus. + if (RHSA == 0 && LHSA == 0) + return SE.getMinusSCEV(LHS, RHS); + + // If only one of LHS and RHS are an AddRec of this loop, make sure it is LHS. + if (RHSA && LHSA == 0) { + // Safe because a-b === b-a for comparisons against zero. + std::swap(LHS, RHS); + std::swap(LHSA, RHSA); + } + + // Handle the case when only one is advancing in a non-overflowing way. + if (RHSA == 0) { + // If RHS is loop varying, then we can't predict when LHS will cross it. + if (!SE.isLoopInvariant(RHS, L)) + return SE.getMinusSCEV(LHS, RHS); + + // If LHS has a positive stride, then we compute RHS-LHS, because the loop + // is counting up until it crosses RHS (which must be larger than LHS). If + // it is negative, we compute LHS-RHS because we're counting down to RHS. + const ConstantInt *Stride = + cast(LHSA->getOperand(1))->getValue(); + if (Stride->getValue().isNegative()) + std::swap(LHS, RHS); + + return SE.getMinusSCEV(RHS, LHS, true /*HasNUW*/); + } + + // If both LHS and RHS are interesting, we have something like: + // a+i*4 != b+i*8. + const ConstantInt *LHSStride = + cast(LHSA->getOperand(1))->getValue(); + const ConstantInt *RHSStride = + cast(RHSA->getOperand(1))->getValue(); + + // If the strides are equal, then this is just a (complex) loop invariant + // comparison of a and b. + if (LHSStride == RHSStride) + return SE.getMinusSCEV(LHSA->getStart(), RHSA->getStart()); + + // If the signs of the strides differ, then the negative stride is counting + // down to the positive stride. + if (LHSStride->getValue().isNegative() != RHSStride->getValue().isNegative()){ + if (RHSStride->getValue().isNegative()) + std::swap(LHS, RHS); + } else { + // If LHS's stride is smaller than RHS's stride, then "b" must be less than + // "a" and "b" is RHS is counting up (catching up) to LHS. This is true + // whether the strides are positive or negative. + if (RHSStride->getValue().slt(LHSStride->getValue())) + std::swap(LHS, RHS); + } + + return SE.getMinusSCEV(LHS, RHS, true /*HasNUW*/); +} + +/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the +/// backedge of the specified loop will execute if its exit condition +/// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, + ICmpInst *ExitCond, + BasicBlock *TBB, + BasicBlock *FBB) { + + // If the condition was exit on true, convert the condition to exit on false + ICmpInst::Predicate Cond; + if (!L->contains(FBB)) + Cond = ExitCond->getPredicate(); + else + Cond = ExitCond->getInversePredicate(); + + // Handle common loops like: for (X = "string"; *X; ++X) + if (LoadInst *LI = dyn_cast(ExitCond->getOperand(0))) + if (Constant *RHS = dyn_cast(ExitCond->getOperand(1))) { + BackedgeTakenInfo ItCnt = + ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond); + if (ItCnt.hasAnyInfo()) + return ItCnt; + } + + const SCEV *LHS = getSCEV(ExitCond->getOperand(0)); + const SCEV *RHS = getSCEV(ExitCond->getOperand(1)); + + // Try to evaluate any dependencies out of the loop. + LHS = getSCEVAtScope(LHS, L); + RHS = getSCEVAtScope(RHS, L); + + // At this point, we would like to compute how many iterations of the + // loop the predicate will return true for these inputs. + if (isLoopInvariant(LHS, L) && !isLoopInvariant(RHS, L)) { + // If there is a loop-invariant, force it into the RHS. + std::swap(LHS, RHS); + Cond = ICmpInst::getSwappedPredicate(Cond); + } + + // Simplify the operands before analyzing them. + (void)SimplifyICmpOperands(Cond, LHS, RHS); + + // If we have a comparison of a chrec against a constant, try to use value + // ranges to answer this query. + if (const SCEVConstant *RHSC = dyn_cast(RHS)) + if (const SCEVAddRecExpr *AddRec = dyn_cast(LHS)) + if (AddRec->getLoop() == L) { + // Form the constant range. + ConstantRange CompRange( + ICmpInst::makeConstantRange(Cond, RHSC->getValue()->getValue())); + + const SCEV *Ret = AddRec->getNumIterationsInRange(CompRange, *this); + if (!isa(Ret)) return Ret; + } + + switch (Cond) { + case ICmpInst::ICMP_NE: { // while (X != Y) + // Convert to: while (X-Y != 0) + BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEVForExitTest(LHS, RHS, L, + *this), L); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_EQ: { // while (X == Y) + // Convert to: while (X-Y == 0) + BackedgeTakenInfo BTI = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_SLT: { + BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, true); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_SGT: { + BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, true); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_ULT: { + BackedgeTakenInfo BTI = HowManyLessThans(LHS, RHS, L, false); + if (BTI.hasAnyInfo()) return BTI; + break; + } + case ICmpInst::ICMP_UGT: { + BackedgeTakenInfo BTI = HowManyLessThans(getNotSCEV(LHS), + getNotSCEV(RHS), L, false); + if (BTI.hasAnyInfo()) return BTI; + break; + } + default: +#if 0 + dbgs() << "ComputeBackedgeTakenCount "; + if (ExitCond->getOperand(0)->getType()->isUnsigned()) + dbgs() << "[unsigned] "; + dbgs() << *LHS << " " + << Instruction::getOpcodeName(Instruction::ICmp) + << " " << *RHS << "\n"; +#endif + break; + } + return + ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); +} + +static ConstantInt * +EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, ConstantInt *C, + ScalarEvolution &SE) { + const SCEV *InVal = SE.getConstant(C); + const SCEV *Val = AddRec->evaluateAtIteration(InVal, SE); + assert(isa(Val) && + "Evaluation of SCEV at constant didn't fold correctly?"); + return cast(Val)->getValue(); +} + +/// GetAddressedElementFromGlobal - Given a global variable with an initializer +/// and a GEP expression (missing the pointer index) indexing into it, return +/// the addressed element of the initializer or null if the index expression is +/// invalid. +static Constant * +GetAddressedElementFromGlobal(GlobalVariable *GV, + const std::vector &Indices) { + Constant *Init = GV->getInitializer(); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) { + uint64_t Idx = Indices[i]->getZExtValue(); + if (ConstantStruct *CS = dyn_cast(Init)) { + assert(Idx < CS->getNumOperands() && "Bad struct index!"); + Init = cast(CS->getOperand(Idx)); + } else if (ConstantArray *CA = dyn_cast(Init)) { + if (Idx >= CA->getNumOperands()) return 0; // Bogus program + Init = cast(CA->getOperand(Idx)); + } else if (isa(Init)) { + if (const StructType *STy = dyn_cast(Init->getType())) { + assert(Idx < STy->getNumElements() && "Bad struct index!"); + Init = Constant::getNullValue(STy->getElementType(Idx)); + } else if (const ArrayType *ATy = dyn_cast(Init->getType())) { + if (Idx >= ATy->getNumElements()) return 0; // Bogus program + Init = Constant::getNullValue(ATy->getElementType()); + } else { + llvm_unreachable("Unknown constant aggregate type!"); + } + return 0; + } else { + return 0; // Unknown initializer type + } + } + return Init; +} + +/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of +/// 'icmp op load X, cst', try to see if we can compute the backedge +/// execution count. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount( + LoadInst *LI, + Constant *RHS, + const Loop *L, + ICmpInst::Predicate predicate) { + if (LI->isVolatile()) return getCouldNotCompute(); + + // Check to see if the loaded pointer is a getelementptr of a global. + // TODO: Use SCEV instead of manually grubbing with GEPs. + GetElementPtrInst *GEP = dyn_cast(LI->getOperand(0)); + if (!GEP) return getCouldNotCompute(); + + // Make sure that it is really a constant global we are gepping, with an + // initializer, and make sure the first IDX is really 0. + GlobalVariable *GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer() || + GEP->getNumOperands() < 3 || !isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isNullValue()) + return getCouldNotCompute(); + + // Okay, we allow one non-constant index into the GEP instruction. + Value *VarIdx = 0; + std::vector Indexes; + unsigned VarIdxNum = 0; + for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) + if (ConstantInt *CI = dyn_cast(GEP->getOperand(i))) { + Indexes.push_back(CI); + } else if (!isa(GEP->getOperand(i))) { + if (VarIdx) return getCouldNotCompute(); // Multiple non-constant idx's. + VarIdx = GEP->getOperand(i); + VarIdxNum = i-2; + Indexes.push_back(0); + } + + // Okay, we know we have a (load (gep GV, 0, X)) comparison with a constant. + // Check to see if X is a loop variant variable value now. + const SCEV *Idx = getSCEV(VarIdx); + Idx = getSCEVAtScope(Idx, L); + + // We can only recognize very limited forms of loop index expressions, in + // particular, only affine AddRec's like {C1,+,C2}. + const SCEVAddRecExpr *IdxExpr = dyn_cast(Idx); + if (!IdxExpr || !IdxExpr->isAffine() || isLoopInvariant(IdxExpr, L) || + !isa(IdxExpr->getOperand(0)) || + !isa(IdxExpr->getOperand(1))) + return getCouldNotCompute(); + + unsigned MaxSteps = MaxBruteForceIterations; + for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) { + ConstantInt *ItCst = ConstantInt::get( + cast(IdxExpr->getType()), IterationNum); + ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, *this); + + // Form the GEP offset. + Indexes[VarIdxNum] = Val; + + Constant *Result = GetAddressedElementFromGlobal(GV, Indexes); + if (Result == 0) break; // Cannot compute! + + // Evaluate the condition for this iteration. + Result = ConstantExpr::getICmp(predicate, Result, RHS); + if (!isa(Result)) break; // Couldn't decide for sure + if (cast(Result)->getValue().isMinValue()) { +#if 0 + dbgs() << "\n***\n*** Computed loop count " << *ItCst + << "\n*** From global " << *GV << "*** BB: " << *L->getHeader() + << "***\n"; +#endif + ++NumArrayLenItCounts; + return getConstant(ItCst); // Found terminating iteration! + } + } + return getCouldNotCompute(); +} + + +/// CanConstantFold - Return true if we can constant fold an instruction of the +/// specified type, assuming that all operands were constants. +static bool CanConstantFold(const Instruction *I) { + if (isa(I) || isa(I) || + isa(I) || isa(I) || isa(I)) + return true; + + if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) + return canConstantFoldCallTo(F); + return false; +} + +/// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node +/// in the loop that V is derived from. We allow arbitrary operations along the +/// way, but the operands of an operation must either be constants or a value +/// derived from a constant PHI. If this expression does not fit with these +/// constraints, return null. +static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) { + // If this is not an instruction, or if this is an instruction outside of the + // loop, it can't be derived from a loop PHI. + Instruction *I = dyn_cast(V); + if (I == 0 || !L->contains(I)) return 0; + + if (PHINode *PN = dyn_cast(I)) { + if (L->getHeader() == I->getParent()) + return PN; + else + // We don't currently keep track of the control flow needed to evaluate + // PHIs, so we cannot handle PHIs inside of loops. + return 0; + } + + // If we won't be able to constant fold this expression even if the operands + // are constants, return early. + if (!CanConstantFold(I)) return 0; + + // Otherwise, we can evaluate this instruction if all of its operands are + // constant or derived from a PHI node themselves. + PHINode *PHI = 0; + for (unsigned Op = 0, e = I->getNumOperands(); Op != e; ++Op) + if (!isa(I->getOperand(Op))) { + PHINode *P = getConstantEvolvingPHI(I->getOperand(Op), L); + if (P == 0) return 0; // Not evolving from PHI + if (PHI == 0) + PHI = P; + else if (PHI != P) + return 0; // Evolving from multiple different PHIs. + } + + // This is a expression evolving from a constant PHI! + return PHI; +} + +/// EvaluateExpression - Given an expression that passes the +/// getConstantEvolvingPHI predicate, evaluate its value assuming the PHI node +/// in the loop has the value PHIVal. If we can't fold this expression for some +/// reason, return null. +static Constant *EvaluateExpression(Value *V, Constant *PHIVal, + const TargetData *TD) { + if (isa(V)) return PHIVal; + if (Constant *C = dyn_cast(V)) return C; + Instruction *I = cast(V); + + std::vector Operands(I->getNumOperands()); + + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + Operands[i] = EvaluateExpression(I->getOperand(i), PHIVal, TD); + if (Operands[i] == 0) return 0; + } + + if (const CmpInst *CI = dyn_cast(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), Operands[0], + Operands[1], TD); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size(), TD); +} + +/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is +/// in the header of its containing loop, we know the loop executes a +/// constant number of times, and the PHI node is just a recurrence +/// involving constants, fold it. +Constant * +ScalarEvolution::getConstantEvolutionLoopExitValue(PHINode *PN, + const APInt &BEs, + const Loop *L) { + std::map::const_iterator I = + ConstantEvolutionLoopExitValue.find(PN); + if (I != ConstantEvolutionLoopExitValue.end()) + return I->second; + + if (BEs.ugt(MaxBruteForceIterations)) + return ConstantEvolutionLoopExitValue[PN] = 0; // Not going to evaluate it. + + Constant *&RetVal = ConstantEvolutionLoopExitValue[PN]; + + // Since the loop is canonicalized, the PHI node must have two entries. One + // entry must be a constant (coming in from outside of the loop), and the + // second must be derived from the same PHI. + bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1)); + Constant *StartCST = + dyn_cast(PN->getIncomingValue(!SecondIsBackedge)); + if (StartCST == 0) + return RetVal = 0; // Must be a constant. + + Value *BEValue = PN->getIncomingValue(SecondIsBackedge); + if (getConstantEvolvingPHI(BEValue, L) != PN && + !isa(BEValue)) + return RetVal = 0; // Not derived from same PHI. + + // Execute the loop symbolically to determine the exit value. + if (BEs.getActiveBits() >= 32) + return RetVal = 0; // More than 2^32-1 iterations?? Not doing it! + + unsigned NumIterations = BEs.getZExtValue(); // must be in range + unsigned IterationNum = 0; + for (Constant *PHIVal = StartCST; ; ++IterationNum) { + if (IterationNum == NumIterations) + return RetVal = PHIVal; // Got exit value! + + // Compute the value of the PHI node for the next iteration. + Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); + if (NextPHI == PHIVal) + return RetVal = NextPHI; // Stopped evolving! + if (NextPHI == 0) + return 0; // Couldn't evaluate! + PHIVal = NextPHI; + } +} + +/// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute a +/// constant number of times (the condition evolves only from constants), +/// try to evaluate a few iterations of the loop until we get the exit +/// condition gets a value of ExitWhen (true or false). If we cannot +/// evaluate the trip count of the loop, return getCouldNotCompute(). +const SCEV * +ScalarEvolution::ComputeBackedgeTakenCountExhaustively(const Loop *L, + Value *Cond, + bool ExitWhen) { + PHINode *PN = getConstantEvolvingPHI(Cond, L); + if (PN == 0) return getCouldNotCompute(); + + // If the loop is canonicalized, the PHI will have exactly two entries. + // That's the only form we support here. + if (PN->getNumIncomingValues() != 2) return getCouldNotCompute(); + + // One entry must be a constant (coming in from outside of the loop), and the + // second must be derived from the same PHI. + bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1)); + Constant *StartCST = + dyn_cast(PN->getIncomingValue(!SecondIsBackedge)); + if (StartCST == 0) return getCouldNotCompute(); // Must be a constant. + + Value *BEValue = PN->getIncomingValue(SecondIsBackedge); + if (getConstantEvolvingPHI(BEValue, L) != PN && + !isa(BEValue)) + return getCouldNotCompute(); // Not derived from same PHI. + + // Okay, we find a PHI node that defines the trip count of this loop. Execute + // the loop symbolically to determine when the condition gets a value of + // "ExitWhen". + unsigned IterationNum = 0; + unsigned MaxIterations = MaxBruteForceIterations; // Limit analysis. + for (Constant *PHIVal = StartCST; + IterationNum != MaxIterations; ++IterationNum) { + ConstantInt *CondVal = + dyn_cast_or_null(EvaluateExpression(Cond, PHIVal, TD)); + + // Couldn't symbolically evaluate. + if (!CondVal) return getCouldNotCompute(); + + if (CondVal->getValue() == uint64_t(ExitWhen)) { + ++NumBruteForceTripCountsComputed; + return getConstant(Type::getInt32Ty(getContext()), IterationNum); + } + + // Compute the value of the PHI node for the next iteration. + Constant *NextPHI = EvaluateExpression(BEValue, PHIVal, TD); + if (NextPHI == 0 || NextPHI == PHIVal) + return getCouldNotCompute();// Couldn't evaluate or not making progress... + PHIVal = NextPHI; + } + + // Too many iterations were needed to evaluate. + return getCouldNotCompute(); +} + +/// getSCEVAtScope - Return a SCEV expression for the specified value +/// at the specified scope in the program. The L value specifies a loop +/// nest to evaluate the expression at, where null is the top-level or a +/// specified loop is immediately inside of the loop. +/// +/// This method can be used to compute the exit value for a variable defined +/// in a loop by querying what the value will hold in the parent loop. +/// +/// In the case that a relevant loop exit value cannot be computed, the +/// original value V is returned. +const SCEV *ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) { + // Check to see if we've folded this expression at this loop before. + std::map &Values = ValuesAtScopes[V]; + std::pair::iterator, bool> Pair = + Values.insert(std::make_pair(L, static_cast(0))); + if (!Pair.second) + return Pair.first->second ? Pair.first->second : V; + + // Otherwise compute it. + const SCEV *C = computeSCEVAtScope(V, L); + ValuesAtScopes[V][L] = C; + return C; +} + +const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { + if (isa(V)) return V; + + // If this instruction is evolved from a constant-evolving PHI, compute the + // exit value from the loop without using SCEVs. + if (const SCEVUnknown *SU = dyn_cast(V)) { + if (Instruction *I = dyn_cast(SU->getValue())) { + const Loop *LI = (*this->LI)[I->getParent()]; + if (LI && LI->getParentLoop() == L) // Looking for loop exit value. + if (PHINode *PN = dyn_cast(I)) + if (PN->getParent() == LI->getHeader()) { + // Okay, there is no closed form solution for the PHI node. Check + // to see if the loop that contains it has a known backedge-taken + // count. If so, we may be able to force computation of the exit + // value. + const SCEV *BackedgeTakenCount = getBackedgeTakenCount(LI); + if (const SCEVConstant *BTCC = + dyn_cast(BackedgeTakenCount)) { + // Okay, we know how many times the containing loop executes. If + // this is a constant evolving PHI node, get the final value at + // the specified iteration number. + Constant *RV = getConstantEvolutionLoopExitValue(PN, + BTCC->getValue()->getValue(), + LI); + if (RV) return getSCEV(RV); + } + } + + // Okay, this is an expression that we cannot symbolically evaluate + // into a SCEV. Check to see if it's possible to symbolically evaluate + // the arguments into constants, and if so, try to constant propagate the + // result. This is particularly useful for computing loop exit values. + if (CanConstantFold(I)) { + SmallVector Operands; + bool MadeImprovement = false; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + Value *Op = I->getOperand(i); + if (Constant *C = dyn_cast(Op)) { + Operands.push_back(C); + continue; + } + + // If any of the operands is non-constant and if they are + // non-integer and non-pointer, don't even try to analyze them + // with scev techniques. + if (!isSCEVable(Op->getType())) + return V; + + const SCEV *OrigV = getSCEV(Op); + const SCEV *OpV = getSCEVAtScope(OrigV, L); + MadeImprovement |= OrigV != OpV; + + Constant *C = 0; + if (const SCEVConstant *SC = dyn_cast(OpV)) + C = SC->getValue(); + if (const SCEVUnknown *SU = dyn_cast(OpV)) + C = dyn_cast(SU->getValue()); + if (!C) return V; + if (C->getType() != Op->getType()) + C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + Op->getType(), + false), + C, Op->getType()); + Operands.push_back(C); + } + + // Check to see if getSCEVAtScope actually made an improvement. + if (MadeImprovement) { + Constant *C = 0; + if (const CmpInst *CI = dyn_cast(I)) + C = ConstantFoldCompareInstOperands(CI->getPredicate(), + Operands[0], Operands[1], TD); + else + C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size(), TD); + if (!C) return V; + return getSCEV(C); + } + } + } + + // This is some other type of SCEVUnknown, just return it. + return V; + } + + if (const SCEVCommutativeExpr *Comm = dyn_cast(V)) { + // Avoid performing the look-up in the common case where the specified + // expression has no loop-variant portions. + for (unsigned i = 0, e = Comm->getNumOperands(); i != e; ++i) { + const SCEV *OpAtScope = getSCEVAtScope(Comm->getOperand(i), L); + if (OpAtScope != Comm->getOperand(i)) { + // Okay, at least one of these operands is loop variant but might be + // foldable. Build a new instance of the folded commutative expression. + SmallVector NewOps(Comm->op_begin(), + Comm->op_begin()+i); + NewOps.push_back(OpAtScope); + + for (++i; i != e; ++i) { + OpAtScope = getSCEVAtScope(Comm->getOperand(i), L); + NewOps.push_back(OpAtScope); + } + if (isa(Comm)) + return getAddExpr(NewOps); + if (isa(Comm)) + return getMulExpr(NewOps); + if (isa(Comm)) + return getSMaxExpr(NewOps); + if (isa(Comm)) + return getUMaxExpr(NewOps); + llvm_unreachable("Unknown commutative SCEV type!"); + } + } + // If we got here, all operands are loop invariant. + return Comm; + } + + if (const SCEVUDivExpr *Div = dyn_cast(V)) { + const SCEV *LHS = getSCEVAtScope(Div->getLHS(), L); + const SCEV *RHS = getSCEVAtScope(Div->getRHS(), L); + if (LHS == Div->getLHS() && RHS == Div->getRHS()) + return Div; // must be loop invariant + return getUDivExpr(LHS, RHS); + } + + // If this is a loop recurrence for a loop that does not contain L, then we + // are dealing with the final value computed by the loop. + if (const SCEVAddRecExpr *AddRec = dyn_cast(V)) { + // First, attempt to evaluate each operand. + // Avoid performing the look-up in the common case where the specified + // expression has no loop-variant portions. + for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) { + const SCEV *OpAtScope = getSCEVAtScope(AddRec->getOperand(i), L); + if (OpAtScope == AddRec->getOperand(i)) + continue; + + // Okay, at least one of these operands is loop variant but might be + // foldable. Build a new instance of the folded commutative expression. + SmallVector NewOps(AddRec->op_begin(), + AddRec->op_begin()+i); + NewOps.push_back(OpAtScope); + for (++i; i != e; ++i) + NewOps.push_back(getSCEVAtScope(AddRec->getOperand(i), L)); + + AddRec = cast(getAddRecExpr(NewOps, AddRec->getLoop())); + break; + } + + // If the scope is outside the addrec's loop, evaluate it by using the + // loop exit value of the addrec. + if (!AddRec->getLoop()->contains(L)) { + // To evaluate this recurrence, we need to know how many times the AddRec + // loop iterates. Compute this now. + const SCEV *BackedgeTakenCount = getBackedgeTakenCount(AddRec->getLoop()); + if (BackedgeTakenCount == getCouldNotCompute()) return AddRec; + + // Then, evaluate the AddRec. + return AddRec->evaluateAtIteration(BackedgeTakenCount, *this); + } + + return AddRec; + } + + if (const SCEVZeroExtendExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getZeroExtendExpr(Op, Cast->getType()); + } + + if (const SCEVSignExtendExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getSignExtendExpr(Op, Cast->getType()); + } + + if (const SCEVTruncateExpr *Cast = dyn_cast(V)) { + const SCEV *Op = getSCEVAtScope(Cast->getOperand(), L); + if (Op == Cast->getOperand()) + return Cast; // must be loop invariant + return getTruncateExpr(Op, Cast->getType()); + } + + llvm_unreachable("Unknown SCEV type!"); + return 0; +} + +/// getSCEVAtScope - This is a convenience function which does +/// getSCEVAtScope(getSCEV(V), L). +const SCEV *ScalarEvolution::getSCEVAtScope(Value *V, const Loop *L) { + return getSCEVAtScope(getSCEV(V), L); +} + +/// SolveLinEquationWithOverflow - Finds the minimum unsigned root of the +/// following equation: +/// +/// A * X = B (mod N) +/// +/// where N = 2^BW and BW is the common bit width of A and B. The signedness of +/// A and B isn't important. +/// +/// If the equation does not have a solution, SCEVCouldNotCompute is returned. +static const SCEV *SolveLinEquationWithOverflow(const APInt &A, const APInt &B, + ScalarEvolution &SE) { + uint32_t BW = A.getBitWidth(); + assert(BW == B.getBitWidth() && "Bit widths must be the same."); + assert(A != 0 && "A must be non-zero."); + + // 1. D = gcd(A, N) + // + // The gcd of A and N may have only one prime factor: 2. The number of + // trailing zeros in A is its multiplicity + uint32_t Mult2 = A.countTrailingZeros(); + // D = 2^Mult2 + + // 2. Check if B is divisible by D. + // + // B is divisible by D if and only if the multiplicity of prime factor 2 for B + // is not less than multiplicity of this prime factor for D. + if (B.countTrailingZeros() < Mult2) + return SE.getCouldNotCompute(); + + // 3. Compute I: the multiplicative inverse of (A / D) in arithmetic + // modulo (N / D). + // + // (N / D) may need BW+1 bits in its representation. Hence, we'll use this + // bit width during computations. + APInt AD = A.lshr(Mult2).zext(BW + 1); // AD = A / D + APInt Mod(BW + 1, 0); + Mod.setBit(BW - Mult2); // Mod = N / D + APInt I = AD.multiplicativeInverse(Mod); + + // 4. Compute the minimum unsigned root of the equation: + // I * (B / D) mod (N / D) + APInt Result = (I * B.lshr(Mult2).zext(BW + 1)).urem(Mod); + + // The result is guaranteed to be less than 2^BW so we may truncate it to BW + // bits. + return SE.getConstant(Result.trunc(BW)); +} + +/// SolveQuadraticEquation - Find the roots of the quadratic equation for the +/// given quadratic chrec {L,+,M,+,N}. This returns either the two roots (which +/// might be the same) or two SCEVCouldNotCompute objects. +/// +static std::pair +SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { + assert(AddRec->getNumOperands() == 3 && "This is not a quadratic chrec!"); + const SCEVConstant *LC = dyn_cast(AddRec->getOperand(0)); + const SCEVConstant *MC = dyn_cast(AddRec->getOperand(1)); + const SCEVConstant *NC = dyn_cast(AddRec->getOperand(2)); + + // We currently can only solve this if the coefficients are constants. + if (!LC || !MC || !NC) { + const SCEV *CNC = SE.getCouldNotCompute(); + return std::make_pair(CNC, CNC); + } + + uint32_t BitWidth = LC->getValue()->getValue().getBitWidth(); + const APInt &L = LC->getValue()->getValue(); + const APInt &M = MC->getValue()->getValue(); + const APInt &N = NC->getValue()->getValue(); + APInt Two(BitWidth, 2); + APInt Four(BitWidth, 4); + + { + using namespace APIntOps; + const APInt& C = L; + // Convert from chrec coefficients to polynomial coefficients AX^2+BX+C + // The B coefficient is M-N/2 + APInt B(M); + B -= sdiv(N,Two); + + // The A coefficient is N/2 + APInt A(N.sdiv(Two)); + + // Compute the B^2-4ac term. + APInt SqrtTerm(B); + SqrtTerm *= B; + SqrtTerm -= Four * (A * C); + + // Compute sqrt(B^2-4ac). This is guaranteed to be the nearest + // integer value or else APInt::sqrt() will assert. + APInt SqrtVal(SqrtTerm.sqrt()); + + // Compute the two solutions for the quadratic formula. + // The divisions must be performed as signed divisions. + APInt NegB(-B); + APInt TwoA( A << 1 ); + if (TwoA.isMinValue()) { + const SCEV *CNC = SE.getCouldNotCompute(); + return std::make_pair(CNC, CNC); + } + + LLVMContext &Context = SE.getContext(); + + ConstantInt *Solution1 = + ConstantInt::get(Context, (NegB + SqrtVal).sdiv(TwoA)); + ConstantInt *Solution2 = + ConstantInt::get(Context, (NegB - SqrtVal).sdiv(TwoA)); + + return std::make_pair(SE.getConstant(Solution1), + SE.getConstant(Solution2)); + } // end APIntOps namespace +} + +/// HowFarToZero - Return the number of times a backedge comparing the specified +/// value to zero will execute. If not computable, return CouldNotCompute. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { + // If the value is a constant + if (const SCEVConstant *C = dyn_cast(V)) { + // If the value is already zero, the branch will execute zero times. + if (C->getValue()->isZero()) return C; + return getCouldNotCompute(); // Otherwise it will loop infinitely. + } + + const SCEVAddRecExpr *AddRec = dyn_cast(V); + if (!AddRec || AddRec->getLoop() != L) + return getCouldNotCompute(); + + // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of + // the quadratic equation to solve it. + if (AddRec->isQuadratic() && AddRec->getType()->isIntegerTy()) { + std::pair Roots = + SolveQuadraticEquation(AddRec, *this); + const SCEVConstant *R1 = dyn_cast(Roots.first); + const SCEVConstant *R2 = dyn_cast(Roots.second); + if (R1 && R2) { +#if 0 + dbgs() << "HFTZ: " << *V << " - sol#1: " << *R1 + << " sol#2: " << *R2 << "\n"; +#endif + // Pick the smallest positive root value. + if (ConstantInt *CB = + dyn_cast(ConstantExpr::getICmp(CmpInst::ICMP_ULT, + R1->getValue(), + R2->getValue()))) { + if (CB->getZExtValue() == false) + std::swap(R1, R2); // R1 is the minimum root now. + + // We can only use this value if the chrec ends up with an exact zero + // value at this index. When solving for "X*X != 5", for example, we + // should not accept a root of 2. + const SCEV *Val = AddRec->evaluateAtIteration(R1, *this); + if (Val->isZero()) + return R1; // We found a quadratic root! + } + } + return getCouldNotCompute(); + } + + // Otherwise we can only handle this if it is affine. + if (!AddRec->isAffine()) + return getCouldNotCompute(); + + // If this is an affine expression, the execution count of this branch is + // the minimum unsigned root of the following equation: + // + // Start + Step*N = 0 (mod 2^BW) + // + // equivalent to: + // + // Step*N = -Start (mod 2^BW) + // + // where BW is the common bit width of Start and Step. + + // Get the initial value for the loop. + const SCEV *Start = getSCEVAtScope(AddRec->getStart(), L->getParentLoop()); + const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop()); + + // If the AddRec is NUW, then (in an unsigned sense) it cannot be counting up + // to wrap to 0, it must be counting down to equal 0. Also, while counting + // down, it cannot "miss" 0 (which would cause it to wrap), regardless of what + // the stride is. As such, NUW addrec's will always become zero in + // "start / -stride" steps, and we know that the division is exact. + if (AddRec->hasNoUnsignedWrap()) + // FIXME: We really want an "isexact" bit for udiv. + return getUDivExpr(Start, getNegativeSCEV(Step)); + + // For now we handle only constant steps. + const SCEVConstant *StepC = dyn_cast(Step); + if (StepC == 0) + return getCouldNotCompute(); + + // First, handle unitary steps. + if (StepC->getValue()->equalsInt(1)) // 1*N = -Start (mod 2^BW), so: + return getNegativeSCEV(Start); // N = -Start (as unsigned) + + if (StepC->getValue()->isAllOnesValue()) // -1*N = -Start (mod 2^BW), so: + return Start; // N = Start (as unsigned) + + // Then, try to solve the above equation provided that Start is constant. + if (const SCEVConstant *StartC = dyn_cast(Start)) + return SolveLinEquationWithOverflow(StepC->getValue()->getValue(), + -StartC->getValue()->getValue(), + *this); + return getCouldNotCompute(); +} + +/// HowFarToNonZero - Return the number of times a backedge checking the +/// specified value for nonzero will execute. If not computable, return +/// CouldNotCompute +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { + // Loops that look like: while (X == 0) are very strange indeed. We don't + // handle them yet except for the trivial case. This could be expanded in the + // future as needed. + + // If the value is a constant, check to see if it is known to be non-zero + // already. If so, the backedge will execute zero times. + if (const SCEVConstant *C = dyn_cast(V)) { + if (!C->getValue()->isNullValue()) + return getConstant(C->getType(), 0); + return getCouldNotCompute(); // Otherwise it will loop infinitely. + } + + // We could implement others, but I really doubt anyone writes loops like + // this, and if they did, they would already be constant folded. + return getCouldNotCompute(); +} + +/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB +/// (which may not be an immediate predecessor) which has exactly one +/// successor from which BB is reachable, or null if no such block is +/// found. +/// +std::pair +ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB) { + // If the block has a unique predecessor, then there is no path from the + // predecessor to the block that does not go through the direct edge + // from the predecessor to the block. + if (BasicBlock *Pred = BB->getSinglePredecessor()) + return std::make_pair(Pred, BB); + + // A loop's header is defined to be a block that dominates the loop. + // If the header has a unique predecessor outside the loop, it must be + // a block that has exactly one successor that can reach the loop. + if (Loop *L = LI->getLoopFor(BB)) + return std::make_pair(L->getLoopPredecessor(), L->getHeader()); + + return std::pair(); +} + +/// HasSameValue - SCEV structural equivalence is usually sufficient for +/// testing whether two expressions are equal, however for the purposes of +/// looking for a condition guarding a loop, it can be useful to be a little +/// more general, since a front-end may have replicated the controlling +/// expression. +/// +static bool HasSameValue(const SCEV *A, const SCEV *B) { + // Quick check to see if they are the same SCEV. + if (A == B) return true; + + // Otherwise, if they're both SCEVUnknown, it's possible that they hold + // two different instructions with the same value. Check for this case. + if (const SCEVUnknown *AU = dyn_cast(A)) + if (const SCEVUnknown *BU = dyn_cast(B)) + if (const Instruction *AI = dyn_cast(AU->getValue())) + if (const Instruction *BI = dyn_cast(BU->getValue())) + if (AI->isIdenticalTo(BI) && !AI->mayReadFromMemory()) + return true; + + // Otherwise assume they may have a different value. + return false; +} + +/// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with +/// predicate Pred. Return true iff any changes were made. +/// +bool ScalarEvolution::SimplifyICmpOperands(ICmpInst::Predicate &Pred, + const SCEV *&LHS, const SCEV *&RHS) { + bool Changed = false; + + // Canonicalize a constant to the right side. + if (const SCEVConstant *LHSC = dyn_cast(LHS)) { + // Check for both operands constant. + if (const SCEVConstant *RHSC = dyn_cast(RHS)) { + if (ConstantExpr::getICmp(Pred, + LHSC->getValue(), + RHSC->getValue())->isNullValue()) + goto trivially_false; + else + goto trivially_true; + } + // Otherwise swap the operands to put the constant on the right. + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + Changed = true; + } + + // If we're comparing an addrec with a value which is loop-invariant in the + // addrec's loop, put the addrec on the left. Also make a dominance check, + // as both operands could be addrecs loop-invariant in each other's loop. + if (const SCEVAddRecExpr *AR = dyn_cast(RHS)) { + const Loop *L = AR->getLoop(); + if (isLoopInvariant(LHS, L) && properlyDominates(LHS, L->getHeader())) { + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + Changed = true; + } + } + + // If there's a constant operand, canonicalize comparisons with boundary + // cases, and canonicalize *-or-equal comparisons to regular comparisons. + if (const SCEVConstant *RC = dyn_cast(RHS)) { + const APInt &RA = RC->getValue()->getValue(); + switch (Pred) { + default: llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_NE: + break; + case ICmpInst::ICMP_UGE: + if ((RA - 1).isMinValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA - 1); + Changed = true; + break; + } + if (RA.isMaxValue()) { + Pred = ICmpInst::ICMP_EQ; + Changed = true; + break; + } + if (RA.isMinValue()) goto trivially_true; + + Pred = ICmpInst::ICMP_UGT; + RHS = getConstant(RA - 1); + Changed = true; + break; + case ICmpInst::ICMP_ULE: + if ((RA + 1).isMaxValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA + 1); + Changed = true; + break; + } + if (RA.isMinValue()) { + Pred = ICmpInst::ICMP_EQ; + Changed = true; + break; + } + if (RA.isMaxValue()) goto trivially_true; + + Pred = ICmpInst::ICMP_ULT; + RHS = getConstant(RA + 1); + Changed = true; + break; + case ICmpInst::ICMP_SGE: + if ((RA - 1).isMinSignedValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA - 1); + Changed = true; + break; + } + if (RA.isMaxSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + Changed = true; + break; + } + if (RA.isMinSignedValue()) goto trivially_true; + + Pred = ICmpInst::ICMP_SGT; + RHS = getConstant(RA - 1); + Changed = true; + break; + case ICmpInst::ICMP_SLE: + if ((RA + 1).isMaxSignedValue()) { + Pred = ICmpInst::ICMP_NE; + RHS = getConstant(RA + 1); + Changed = true; + break; + } + if (RA.isMinSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + Changed = true; + break; + } + if (RA.isMaxSignedValue()) goto trivially_true; + + Pred = ICmpInst::ICMP_SLT; + RHS = getConstant(RA + 1); + Changed = true; + break; + case ICmpInst::ICMP_UGT: + if (RA.isMinValue()) { + Pred = ICmpInst::ICMP_NE; + Changed = true; + break; + } + if ((RA + 1).isMaxValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA + 1); + Changed = true; + break; + } + if (RA.isMaxValue()) goto trivially_false; + break; + case ICmpInst::ICMP_ULT: + if (RA.isMaxValue()) { + Pred = ICmpInst::ICMP_NE; + Changed = true; + break; + } + if ((RA - 1).isMinValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA - 1); + Changed = true; + break; + } + if (RA.isMinValue()) goto trivially_false; + break; + case ICmpInst::ICMP_SGT: + if (RA.isMinSignedValue()) { + Pred = ICmpInst::ICMP_NE; + Changed = true; + break; + } + if ((RA + 1).isMaxSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA + 1); + Changed = true; + break; + } + if (RA.isMaxSignedValue()) goto trivially_false; + break; + case ICmpInst::ICMP_SLT: + if (RA.isMaxSignedValue()) { + Pred = ICmpInst::ICMP_NE; + Changed = true; + break; + } + if ((RA - 1).isMinSignedValue()) { + Pred = ICmpInst::ICMP_EQ; + RHS = getConstant(RA - 1); + Changed = true; + break; + } + if (RA.isMinSignedValue()) goto trivially_false; + break; + } + } + + // Check for obvious equality. + if (HasSameValue(LHS, RHS)) { + if (ICmpInst::isTrueWhenEqual(Pred)) + goto trivially_true; + if (ICmpInst::isFalseWhenEqual(Pred)) + goto trivially_false; + } + + // If possible, canonicalize GE/LE comparisons to GT/LT comparisons, by + // adding or subtracting 1 from one of the operands. + switch (Pred) { + case ICmpInst::ICMP_SLE: + if (!getSignedRange(RHS).getSignedMax().isMaxSignedValue()) { + RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS, + /*HasNUW=*/false, /*HasNSW=*/true); + Pred = ICmpInst::ICMP_SLT; + Changed = true; + } else if (!getSignedRange(LHS).getSignedMin().isMinSignedValue()) { + LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS, + /*HasNUW=*/false, /*HasNSW=*/true); + Pred = ICmpInst::ICMP_SLT; + Changed = true; + } + break; + case ICmpInst::ICMP_SGE: + if (!getSignedRange(RHS).getSignedMin().isMinSignedValue()) { + RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS, + /*HasNUW=*/false, /*HasNSW=*/true); + Pred = ICmpInst::ICMP_SGT; + Changed = true; + } else if (!getSignedRange(LHS).getSignedMax().isMaxSignedValue()) { + LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS, + /*HasNUW=*/false, /*HasNSW=*/true); + Pred = ICmpInst::ICMP_SGT; + Changed = true; + } + break; + case ICmpInst::ICMP_ULE: + if (!getUnsignedRange(RHS).getUnsignedMax().isMaxValue()) { + RHS = getAddExpr(getConstant(RHS->getType(), 1, true), RHS, + /*HasNUW=*/true, /*HasNSW=*/false); + Pred = ICmpInst::ICMP_ULT; + Changed = true; + } else if (!getUnsignedRange(LHS).getUnsignedMin().isMinValue()) { + LHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), LHS, + /*HasNUW=*/true, /*HasNSW=*/false); + Pred = ICmpInst::ICMP_ULT; + Changed = true; + } + break; + case ICmpInst::ICMP_UGE: + if (!getUnsignedRange(RHS).getUnsignedMin().isMinValue()) { + RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS, + /*HasNUW=*/true, /*HasNSW=*/false); + Pred = ICmpInst::ICMP_UGT; + Changed = true; + } else if (!getUnsignedRange(LHS).getUnsignedMax().isMaxValue()) { + LHS = getAddExpr(getConstant(RHS->getType(), 1, true), LHS, + /*HasNUW=*/true, /*HasNSW=*/false); + Pred = ICmpInst::ICMP_UGT; + Changed = true; + } + break; + default: + break; + } + + // TODO: More simplifications are possible here. + + return Changed; + +trivially_true: + // Return 0 == 0. + LHS = RHS = getConstant(ConstantInt::getFalse(getContext())); + Pred = ICmpInst::ICMP_EQ; + return true; + +trivially_false: + // Return 0 != 0. + LHS = RHS = getConstant(ConstantInt::getFalse(getContext())); + Pred = ICmpInst::ICMP_NE; + return true; +} + +bool ScalarEvolution::isKnownNegative(const SCEV *S) { + return getSignedRange(S).getSignedMax().isNegative(); +} + +bool ScalarEvolution::isKnownPositive(const SCEV *S) { + return getSignedRange(S).getSignedMin().isStrictlyPositive(); +} + +bool ScalarEvolution::isKnownNonNegative(const SCEV *S) { + return !getSignedRange(S).getSignedMin().isNegative(); +} + +bool ScalarEvolution::isKnownNonPositive(const SCEV *S) { + return !getSignedRange(S).getSignedMax().isStrictlyPositive(); +} + +bool ScalarEvolution::isKnownNonZero(const SCEV *S) { + return isKnownNegative(S) || isKnownPositive(S); +} + +bool ScalarEvolution::isKnownPredicate(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + // Canonicalize the inputs first. + (void)SimplifyICmpOperands(Pred, LHS, RHS); + + // If LHS or RHS is an addrec, check to see if the condition is true in + // every iteration of the loop. + if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) + if (isLoopEntryGuardedByCond( + AR->getLoop(), Pred, AR->getStart(), RHS) && + isLoopBackedgeGuardedByCond( + AR->getLoop(), Pred, AR->getPostIncExpr(*this), RHS)) + return true; + if (const SCEVAddRecExpr *AR = dyn_cast(RHS)) + if (isLoopEntryGuardedByCond( + AR->getLoop(), Pred, LHS, AR->getStart()) && + isLoopBackedgeGuardedByCond( + AR->getLoop(), Pred, LHS, AR->getPostIncExpr(*this))) + return true; + + // Otherwise see what can be done with known constant ranges. + return isKnownPredicateWithRanges(Pred, LHS, RHS); +} + +bool +ScalarEvolution::isKnownPredicateWithRanges(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + if (HasSameValue(LHS, RHS)) + return ICmpInst::isTrueWhenEqual(Pred); + + // This code is split out from isKnownPredicate because it is called from + // within isLoopEntryGuardedByCond. + switch (Pred) { + default: + llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + break; + case ICmpInst::ICMP_SGT: + Pred = ICmpInst::ICMP_SLT; + std::swap(LHS, RHS); + case ICmpInst::ICMP_SLT: { + ConstantRange LHSRange = getSignedRange(LHS); + ConstantRange RHSRange = getSignedRange(RHS); + if (LHSRange.getSignedMax().slt(RHSRange.getSignedMin())) + return true; + if (LHSRange.getSignedMin().sge(RHSRange.getSignedMax())) + return false; + break; + } + case ICmpInst::ICMP_SGE: + Pred = ICmpInst::ICMP_SLE; + std::swap(LHS, RHS); + case ICmpInst::ICMP_SLE: { + ConstantRange LHSRange = getSignedRange(LHS); + ConstantRange RHSRange = getSignedRange(RHS); + if (LHSRange.getSignedMax().sle(RHSRange.getSignedMin())) + return true; + if (LHSRange.getSignedMin().sgt(RHSRange.getSignedMax())) + return false; + break; + } + case ICmpInst::ICMP_UGT: + Pred = ICmpInst::ICMP_ULT; + std::swap(LHS, RHS); + case ICmpInst::ICMP_ULT: { + ConstantRange LHSRange = getUnsignedRange(LHS); + ConstantRange RHSRange = getUnsignedRange(RHS); + if (LHSRange.getUnsignedMax().ult(RHSRange.getUnsignedMin())) + return true; + if (LHSRange.getUnsignedMin().uge(RHSRange.getUnsignedMax())) + return false; + break; + } + case ICmpInst::ICMP_UGE: + Pred = ICmpInst::ICMP_ULE; + std::swap(LHS, RHS); + case ICmpInst::ICMP_ULE: { + ConstantRange LHSRange = getUnsignedRange(LHS); + ConstantRange RHSRange = getUnsignedRange(RHS); + if (LHSRange.getUnsignedMax().ule(RHSRange.getUnsignedMin())) + return true; + if (LHSRange.getUnsignedMin().ugt(RHSRange.getUnsignedMax())) + return false; + break; + } + case ICmpInst::ICMP_NE: { + if (getUnsignedRange(LHS).intersectWith(getUnsignedRange(RHS)).isEmptySet()) + return true; + if (getSignedRange(LHS).intersectWith(getSignedRange(RHS)).isEmptySet()) + return true; + + const SCEV *Diff = getMinusSCEV(LHS, RHS); + if (isKnownNonZero(Diff)) + return true; + break; + } + case ICmpInst::ICMP_EQ: + // The check at the top of the function catches the case where + // the values are known to be equal. + break; + } + return false; +} + +/// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is +/// protected by a conditional between LHS and RHS. This is used to +/// to eliminate casts. +bool +ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L, + ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + // Interpret a null as meaning no loop, where there is obviously no guard + // (interprocedural conditions notwithstanding). + if (!L) return true; + + BasicBlock *Latch = L->getLoopLatch(); + if (!Latch) + return false; + + BranchInst *LoopContinuePredicate = + dyn_cast(Latch->getTerminator()); + if (!LoopContinuePredicate || + LoopContinuePredicate->isUnconditional()) + return false; + + return isImpliedCond(Pred, LHS, RHS, + LoopContinuePredicate->getCondition(), + LoopContinuePredicate->getSuccessor(0) != L->getHeader()); +} + +/// isLoopEntryGuardedByCond - Test whether entry to the loop is protected +/// by a conditional between LHS and RHS. This is used to help avoid max +/// expressions in loop trip counts, and to eliminate casts. +bool +ScalarEvolution::isLoopEntryGuardedByCond(const Loop *L, + ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS) { + // Interpret a null as meaning no loop, where there is obviously no guard + // (interprocedural conditions notwithstanding). + if (!L) return false; + + // Starting at the loop predecessor, climb up the predecessor chain, as long + // as there are predecessors that can be found that have unique successors + // leading to the original header. + for (std::pair + Pair(L->getLoopPredecessor(), L->getHeader()); + Pair.first; + Pair = getPredecessorWithUniqueSuccessorForBB(Pair.first)) { + + BranchInst *LoopEntryPredicate = + dyn_cast(Pair.first->getTerminator()); + if (!LoopEntryPredicate || + LoopEntryPredicate->isUnconditional()) + continue; + + if (isImpliedCond(Pred, LHS, RHS, + LoopEntryPredicate->getCondition(), + LoopEntryPredicate->getSuccessor(0) != Pair.second)) + return true; + } + + return false; +} + +/// isImpliedCond - Test whether the condition described by Pred, LHS, +/// and RHS is true whenever the given Cond value evaluates to true. +bool ScalarEvolution::isImpliedCond(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + Value *FoundCondValue, + bool Inverse) { + // Recursively handle And and Or conditions. + if (BinaryOperator *BO = dyn_cast(FoundCondValue)) { + if (BO->getOpcode() == Instruction::And) { + if (!Inverse) + return isImpliedCond(Pred, LHS, RHS, BO->getOperand(0), Inverse) || + isImpliedCond(Pred, LHS, RHS, BO->getOperand(1), Inverse); + } else if (BO->getOpcode() == Instruction::Or) { + if (Inverse) + return isImpliedCond(Pred, LHS, RHS, BO->getOperand(0), Inverse) || + isImpliedCond(Pred, LHS, RHS, BO->getOperand(1), Inverse); + } + } + + ICmpInst *ICI = dyn_cast(FoundCondValue); + if (!ICI) return false; + + // Bail if the ICmp's operands' types are wider than the needed type + // before attempting to call getSCEV on them. This avoids infinite + // recursion, since the analysis of widening casts can require loop + // exit condition information for overflow checking, which would + // lead back here. + if (getTypeSizeInBits(LHS->getType()) < + getTypeSizeInBits(ICI->getOperand(0)->getType())) + return false; + + // Now that we found a conditional branch that dominates the loop, check to + // see if it is the comparison we are looking for. + ICmpInst::Predicate FoundPred; + if (Inverse) + FoundPred = ICI->getInversePredicate(); + else + FoundPred = ICI->getPredicate(); + + const SCEV *FoundLHS = getSCEV(ICI->getOperand(0)); + const SCEV *FoundRHS = getSCEV(ICI->getOperand(1)); + + // Balance the types. The case where FoundLHS' type is wider than + // LHS' type is checked for above. + if (getTypeSizeInBits(LHS->getType()) > + getTypeSizeInBits(FoundLHS->getType())) { + if (CmpInst::isSigned(Pred)) { + FoundLHS = getSignExtendExpr(FoundLHS, LHS->getType()); + FoundRHS = getSignExtendExpr(FoundRHS, LHS->getType()); + } else { + FoundLHS = getZeroExtendExpr(FoundLHS, LHS->getType()); + FoundRHS = getZeroExtendExpr(FoundRHS, LHS->getType()); + } + } + + // Canonicalize the query to match the way instcombine will have + // canonicalized the comparison. + if (SimplifyICmpOperands(Pred, LHS, RHS)) + if (LHS == RHS) + return CmpInst::isTrueWhenEqual(Pred); + if (SimplifyICmpOperands(FoundPred, FoundLHS, FoundRHS)) + if (FoundLHS == FoundRHS) + return CmpInst::isFalseWhenEqual(Pred); + + // Check to see if we can make the LHS or RHS match. + if (LHS == FoundRHS || RHS == FoundLHS) { + if (isa(RHS)) { + std::swap(FoundLHS, FoundRHS); + FoundPred = ICmpInst::getSwappedPredicate(FoundPred); + } else { + std::swap(LHS, RHS); + Pred = ICmpInst::getSwappedPredicate(Pred); + } + } + + // Check whether the found predicate is the same as the desired predicate. + if (FoundPred == Pred) + return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS); + + // Check whether swapping the found predicate makes it the same as the + // desired predicate. + if (ICmpInst::getSwappedPredicate(FoundPred) == Pred) { + if (isa(RHS)) + return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS); + else + return isImpliedCondOperands(ICmpInst::getSwappedPredicate(Pred), + RHS, LHS, FoundLHS, FoundRHS); + } + + // Check whether the actual condition is beyond sufficient. + if (FoundPred == ICmpInst::ICMP_EQ) + if (ICmpInst::isTrueWhenEqual(Pred)) + if (isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS)) + return true; + if (Pred == ICmpInst::ICMP_NE) + if (!ICmpInst::isTrueWhenEqual(FoundPred)) + if (isImpliedCondOperands(FoundPred, LHS, RHS, FoundLHS, FoundRHS)) + return true; + + // Otherwise assume the worst. + return false; +} + +/// isImpliedCondOperands - Test whether the condition described by Pred, +/// LHS, and RHS is true whenever the condition described by Pred, FoundLHS, +/// and FoundRHS is true. +bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS) { + return isImpliedCondOperandsHelper(Pred, LHS, RHS, + FoundLHS, FoundRHS) || + // ~x < ~y --> x > y + isImpliedCondOperandsHelper(Pred, LHS, RHS, + getNotSCEV(FoundRHS), + getNotSCEV(FoundLHS)); +} + +/// isImpliedCondOperandsHelper - Test whether the condition described by +/// Pred, LHS, and RHS is true whenever the condition described by Pred, +/// FoundLHS, and FoundRHS is true. +bool +ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS) { + switch (Pred) { + default: llvm_unreachable("Unexpected ICmpInst::Predicate value!"); + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_NE: + if (HasSameValue(LHS, FoundLHS) && HasSameValue(RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + if (isKnownPredicateWithRanges(ICmpInst::ICMP_SLE, LHS, FoundLHS) && + isKnownPredicateWithRanges(ICmpInst::ICMP_SGE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + if (isKnownPredicateWithRanges(ICmpInst::ICMP_SGE, LHS, FoundLHS) && + isKnownPredicateWithRanges(ICmpInst::ICMP_SLE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + if (isKnownPredicateWithRanges(ICmpInst::ICMP_ULE, LHS, FoundLHS) && + isKnownPredicateWithRanges(ICmpInst::ICMP_UGE, RHS, FoundRHS)) + return true; + break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + if (isKnownPredicateWithRanges(ICmpInst::ICMP_UGE, LHS, FoundLHS) && + isKnownPredicateWithRanges(ICmpInst::ICMP_ULE, RHS, FoundRHS)) + return true; + break; + } + + return false; +} + +/// getBECount - Subtract the end and start values and divide by the step, +/// rounding up, to get the number of times the backedge is executed. Return +/// CouldNotCompute if an intermediate computation overflows. +const SCEV *ScalarEvolution::getBECount(const SCEV *Start, + const SCEV *End, + const SCEV *Step, + bool NoWrap) { + assert(!isKnownNegative(Step) && + "This code doesn't handle negative strides yet!"); + + const Type *Ty = Start->getType(); + const SCEV *NegOne = getConstant(Ty, (uint64_t)-1); + const SCEV *Diff = getMinusSCEV(End, Start); + const SCEV *RoundUp = getAddExpr(Step, NegOne); + + // Add an adjustment to the difference between End and Start so that + // the division will effectively round up. + const SCEV *Add = getAddExpr(Diff, RoundUp); + + if (!NoWrap) { + // Check Add for unsigned overflow. + // TODO: More sophisticated things could be done here. + const Type *WideTy = IntegerType::get(getContext(), + getTypeSizeInBits(Ty) + 1); + const SCEV *EDiff = getZeroExtendExpr(Diff, WideTy); + const SCEV *ERoundUp = getZeroExtendExpr(RoundUp, WideTy); + const SCEV *OperandExtendedAdd = getAddExpr(EDiff, ERoundUp); + if (getZeroExtendExpr(Add, WideTy) != OperandExtendedAdd) + return getCouldNotCompute(); + } + + return getUDivExpr(Add, Step); +} + +/// HowManyLessThans - Return the number of times a backedge containing the +/// specified less-than comparison will execute. If not computable, return +/// CouldNotCompute. +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, + const Loop *L, bool isSigned) { + // Only handle: "ADDREC < LoopInvariant". + if (!isLoopInvariant(RHS, L)) return getCouldNotCompute(); + + const SCEVAddRecExpr *AddRec = dyn_cast(LHS); + if (!AddRec || AddRec->getLoop() != L) + return getCouldNotCompute(); + + // Check to see if we have a flag which makes analysis easy. + bool NoWrap = isSigned ? AddRec->hasNoSignedWrap() : + AddRec->hasNoUnsignedWrap(); + + if (AddRec->isAffine()) { + unsigned BitWidth = getTypeSizeInBits(AddRec->getType()); + const SCEV *Step = AddRec->getStepRecurrence(*this); + + if (Step->isZero()) + return getCouldNotCompute(); + if (Step->isOne()) { + // With unit stride, the iteration never steps past the limit value. + } else if (isKnownPositive(Step)) { + // Test whether a positive iteration can step past the limit + // value and past the maximum value for its type in a single step. + // Note that it's not sufficient to check NoWrap here, because even + // though the value after a wrap is undefined, it's not undefined + // behavior, so if wrap does occur, the loop could either terminate or + // loop infinitely, but in either case, the loop is guaranteed to + // iterate at least until the iteration where the wrapping occurs. + const SCEV *One = getConstant(Step->getType(), 1); + if (isSigned) { + APInt Max = APInt::getSignedMaxValue(BitWidth); + if ((Max - getSignedRange(getMinusSCEV(Step, One)).getSignedMax()) + .slt(getSignedRange(RHS).getSignedMax())) + return getCouldNotCompute(); + } else { + APInt Max = APInt::getMaxValue(BitWidth); + if ((Max - getUnsignedRange(getMinusSCEV(Step, One)).getUnsignedMax()) + .ult(getUnsignedRange(RHS).getUnsignedMax())) + return getCouldNotCompute(); + } + } else + // TODO: Handle negative strides here and below. + return getCouldNotCompute(); + + // We know the LHS is of the form {n,+,s} and the RHS is some loop-invariant + // m. So, we count the number of iterations in which {n,+,s} < m is true. + // Note that we cannot simply return max(m-n,0)/s because it's not safe to + // treat m-n as signed nor unsigned due to overflow possibility. + + // First, we get the value of the LHS in the first iteration: n + const SCEV *Start = AddRec->getOperand(0); + + // Determine the minimum constant start value. + const SCEV *MinStart = getConstant(isSigned ? + getSignedRange(Start).getSignedMin() : + getUnsignedRange(Start).getUnsignedMin()); + + // If we know that the condition is true in order to enter the loop, + // then we know that it will run exactly (m-n)/s times. Otherwise, we + // only know that it will execute (max(m,n)-n)/s times. In both cases, + // the division must round up. + const SCEV *End = RHS; + if (!isLoopEntryGuardedByCond(L, + isSigned ? ICmpInst::ICMP_SLT : + ICmpInst::ICMP_ULT, + getMinusSCEV(Start, Step), RHS)) + End = isSigned ? getSMaxExpr(RHS, Start) + : getUMaxExpr(RHS, Start); + + // Determine the maximum constant end value. + const SCEV *MaxEnd = getConstant(isSigned ? + getSignedRange(End).getSignedMax() : + getUnsignedRange(End).getUnsignedMax()); + + // If MaxEnd is within a step of the maximum integer value in its type, + // adjust it down to the minimum value which would produce the same effect. + // This allows the subsequent ceiling division of (N+(step-1))/step to + // compute the correct value. + const SCEV *StepMinusOne = getMinusSCEV(Step, + getConstant(Step->getType(), 1)); + MaxEnd = isSigned ? + getSMinExpr(MaxEnd, + getMinusSCEV(getConstant(APInt::getSignedMaxValue(BitWidth)), + StepMinusOne)) : + getUMinExpr(MaxEnd, + getMinusSCEV(getConstant(APInt::getMaxValue(BitWidth)), + StepMinusOne)); + + // Finally, we subtract these two values and divide, rounding up, to get + // the number of times the backedge is executed. + const SCEV *BECount = getBECount(Start, End, Step, NoWrap); + + // The maximum backedge count is similar, except using the minimum start + // value and the maximum end value. + const SCEV *MaxBECount = getBECount(MinStart, MaxEnd, Step, NoWrap); + + return BackedgeTakenInfo(BECount, MaxBECount); + } + + return getCouldNotCompute(); +} + +/// getNumIterationsInRange - Return the number of iterations of this loop that +/// produce values in the specified constant range. Another way of looking at +/// this is that it returns the first iteration number where the value is not in +/// the condition, thus computing the exit count. If the iteration count can't +/// be computed, an instance of SCEVCouldNotCompute is returned. +const SCEV *SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range, + ScalarEvolution &SE) const { + if (Range.isFullSet()) // Infinite loop. + return SE.getCouldNotCompute(); + + // If the start is a non-zero constant, shift the range to simplify things. + if (const SCEVConstant *SC = dyn_cast(getStart())) + if (!SC->getValue()->isZero()) { + SmallVector Operands(op_begin(), op_end()); + Operands[0] = SE.getConstant(SC->getType(), 0); + const SCEV *Shifted = SE.getAddRecExpr(Operands, getLoop()); + if (const SCEVAddRecExpr *ShiftedAddRec = + dyn_cast(Shifted)) + return ShiftedAddRec->getNumIterationsInRange( + Range.subtract(SC->getValue()->getValue()), SE); + // This is strange and shouldn't happen. + return SE.getCouldNotCompute(); + } + + // The only time we can solve this is when we have all constant indices. + // Otherwise, we cannot determine the overflow conditions. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!isa(getOperand(i))) + return SE.getCouldNotCompute(); + + + // Okay at this point we know that all elements of the chrec are constants and + // that the start element is zero. + + // First check to see if the range contains zero. If not, the first + // iteration exits. + unsigned BitWidth = SE.getTypeSizeInBits(getType()); + if (!Range.contains(APInt(BitWidth, 0))) + return SE.getConstant(getType(), 0); + + if (isAffine()) { + // If this is an affine expression then we have this situation: + // Solve {0,+,A} in Range === Ax in Range + + // We know that zero is in the range. If A is positive then we know that + // the upper value of the range must be the first possible exit value. + // If A is negative then the lower of the range is the last possible loop + // value. Also note that we already checked for a full range. + APInt One(BitWidth,1); + APInt A = cast(getOperand(1))->getValue()->getValue(); + APInt End = A.sge(One) ? (Range.getUpper() - One) : Range.getLower(); + + // The exit value should be (End+A)/A. + APInt ExitVal = (End + A).udiv(A); + ConstantInt *ExitValue = ConstantInt::get(SE.getContext(), ExitVal); + + // Evaluate at the exit value. If we really did fall out of the valid + // range, then we computed our trip count, otherwise wrap around or other + // things must have happened. + ConstantInt *Val = EvaluateConstantChrecAtConstant(this, ExitValue, SE); + if (Range.contains(Val->getValue())) + return SE.getCouldNotCompute(); // Something strange happened + + // Ensure that the previous value is in the range. This is a sanity check. + assert(Range.contains( + EvaluateConstantChrecAtConstant(this, + ConstantInt::get(SE.getContext(), ExitVal - One), SE)->getValue()) && + "Linear scev computation is off in a bad way!"); + return SE.getConstant(ExitValue); + } else if (isQuadratic()) { + // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of the + // quadratic equation to solve it. To do this, we must frame our problem in + // terms of figuring out when zero is crossed, instead of when + // Range.getUpper() is crossed. + SmallVector NewOps(op_begin(), op_end()); + NewOps[0] = SE.getNegativeSCEV(SE.getConstant(Range.getUpper())); + const SCEV *NewAddRec = SE.getAddRecExpr(NewOps, getLoop()); + + // Next, solve the constructed addrec + std::pair Roots = + SolveQuadraticEquation(cast(NewAddRec), SE); + const SCEVConstant *R1 = dyn_cast(Roots.first); + const SCEVConstant *R2 = dyn_cast(Roots.second); + if (R1) { + // Pick the smallest positive root value. + if (ConstantInt *CB = + dyn_cast(ConstantExpr::getICmp(ICmpInst::ICMP_ULT, + R1->getValue(), R2->getValue()))) { + if (CB->getZExtValue() == false) + std::swap(R1, R2); // R1 is the minimum root now. + + // Make sure the root is not off by one. The returned iteration should + // not be in the range, but the previous one should be. When solving + // for "X*X < 5", for example, we should not return a root of 2. + ConstantInt *R1Val = EvaluateConstantChrecAtConstant(this, + R1->getValue(), + SE); + if (Range.contains(R1Val->getValue())) { + // The next iteration must be out of the range... + ConstantInt *NextVal = + ConstantInt::get(SE.getContext(), R1->getValue()->getValue()+1); + + R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE); + if (!Range.contains(R1Val->getValue())) + return SE.getConstant(NextVal); + return SE.getCouldNotCompute(); // Something strange happened + } + + // If R1 was not in the range, then it is a good return value. Make + // sure that R1-1 WAS in the range though, just in case. + ConstantInt *NextVal = + ConstantInt::get(SE.getContext(), R1->getValue()->getValue()-1); + R1Val = EvaluateConstantChrecAtConstant(this, NextVal, SE); + if (Range.contains(R1Val->getValue())) + return R1; + return SE.getCouldNotCompute(); // Something strange happened + } + } + } + + return SE.getCouldNotCompute(); +} + + + +//===----------------------------------------------------------------------===// +// SCEVCallbackVH Class Implementation +//===----------------------------------------------------------------------===// + +void ScalarEvolution::SCEVCallbackVH::deleted() { + assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!"); + if (PHINode *PN = dyn_cast(getValPtr())) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->ValueExprMap.erase(getValPtr()); + // this now dangles! +} + +void ScalarEvolution::SCEVCallbackVH::allUsesReplacedWith(Value *V) { + assert(SE && "SCEVCallbackVH called with a null ScalarEvolution!"); + + // Forget all the expressions associated with users of the old value, + // so that future queries will recompute the expressions using the new + // value. + Value *Old = getValPtr(); + SmallVector Worklist; + SmallPtrSet Visited; + for (Value::use_iterator UI = Old->use_begin(), UE = Old->use_end(); + UI != UE; ++UI) + Worklist.push_back(*UI); + while (!Worklist.empty()) { + User *U = Worklist.pop_back_val(); + // Deleting the Old value will cause this to dangle. Postpone + // that until everything else is done. + if (U == Old) + continue; + if (!Visited.insert(U)) + continue; + if (PHINode *PN = dyn_cast(U)) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->ValueExprMap.erase(U); + for (Value::use_iterator UI = U->use_begin(), UE = U->use_end(); + UI != UE; ++UI) + Worklist.push_back(*UI); + } + // Delete the Old value. + if (PHINode *PN = dyn_cast(Old)) + SE->ConstantEvolutionLoopExitValue.erase(PN); + SE->ValueExprMap.erase(Old); + // this now dangles! +} + +ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se) + : CallbackVH(V), SE(se) {} + +//===----------------------------------------------------------------------===// +// ScalarEvolution Class Implementation +//===----------------------------------------------------------------------===// + +ScalarEvolution::ScalarEvolution() + : FunctionPass(ID), FirstUnknown(0) { + initializeScalarEvolutionPass(*PassRegistry::getPassRegistry()); +} + +bool ScalarEvolution::runOnFunction(Function &F) { + this->F = &F; + LI = &getAnalysis(); + TD = getAnalysisIfAvailable(); + DT = &getAnalysis(); + return false; +} + +void ScalarEvolution::releaseMemory() { + // Iterate through all the SCEVUnknown instances and call their + // destructors, so that they release their references to their values. + for (SCEVUnknown *U = FirstUnknown; U; U = U->Next) + U->~SCEVUnknown(); + FirstUnknown = 0; + + ValueExprMap.clear(); + BackedgeTakenCounts.clear(); + ConstantEvolutionLoopExitValue.clear(); + ValuesAtScopes.clear(); + LoopDispositions.clear(); + BlockDispositions.clear(); + UnsignedRanges.clear(); + SignedRanges.clear(); + UniqueSCEVs.clear(); + SCEVAllocator.Reset(); +} + +void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); +} + +bool ScalarEvolution::hasLoopInvariantBackedgeTakenCount(const Loop *L) { + return !isa(getBackedgeTakenCount(L)); +} + +static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE, + const Loop *L) { + // Print all inner loops first + for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I) + PrintLoopInfo(OS, SE, *I); + + OS << "Loop "; + WriteAsOperand(OS, L->getHeader(), /*PrintType=*/false); + OS << ": "; + + SmallVector ExitBlocks; + L->getExitBlocks(ExitBlocks); + if (ExitBlocks.size() != 1) + OS << " "; + + if (SE->hasLoopInvariantBackedgeTakenCount(L)) { + OS << "backedge-taken count is " << *SE->getBackedgeTakenCount(L); + } else { + OS << "Unpredictable backedge-taken count. "; + } + + OS << "\n" + "Loop "; + WriteAsOperand(OS, L->getHeader(), /*PrintType=*/false); + OS << ": "; + + if (!isa(SE->getMaxBackedgeTakenCount(L))) { + OS << "max backedge-taken count is " << *SE->getMaxBackedgeTakenCount(L); + } else { + OS << "Unpredictable max backedge-taken count. "; + } + + OS << "\n"; +} + +void ScalarEvolution::print(raw_ostream &OS, const Module *) const { + // ScalarEvolution's implementation of the print method is to print + // out SCEV values of all instructions that are interesting. Doing + // this potentially causes it to create new SCEV objects though, + // which technically conflicts with the const qualifier. This isn't + // observable from outside the class though, so casting away the + // const isn't dangerous. + ScalarEvolution &SE = *const_cast(this); + + OS << "Classifying expressions for: "; + WriteAsOperand(OS, F, /*PrintType=*/false); + OS << "\n"; + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + if (isSCEVable(I->getType()) && !isa(*I)) { + OS << *I << '\n'; + OS << " --> "; + const SCEV *SV = SE.getSCEV(&*I); + SV->print(OS); + + const Loop *L = LI->getLoopFor((*I).getParent()); + + const SCEV *AtUse = SE.getSCEVAtScope(SV, L); + if (AtUse != SV) { + OS << " --> "; + AtUse->print(OS); + } + + if (L) { + OS << "\t\t" "Exits: "; + const SCEV *ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop()); + if (!SE.isLoopInvariant(ExitValue, L)) { + OS << "<>"; + } else { + OS << *ExitValue; + } + } + + OS << "\n"; + } + + OS << "Determining loop execution counts for: "; + WriteAsOperand(OS, F, /*PrintType=*/false); + OS << "\n"; + for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) + PrintLoopInfo(OS, &SE, *I); +} + +ScalarEvolution::LoopDisposition +ScalarEvolution::getLoopDisposition(const SCEV *S, const Loop *L) { + std::map &Values = LoopDispositions[S]; + std::pair::iterator, bool> Pair = + Values.insert(std::make_pair(L, LoopVariant)); + if (!Pair.second) + return Pair.first->second; + + LoopDisposition D = computeLoopDisposition(S, L); + return LoopDispositions[S][L] = D; +} + +ScalarEvolution::LoopDisposition +ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) { + switch (S->getSCEVType()) { + case scConstant: + return LoopInvariant; + case scTruncate: + case scZeroExtend: + case scSignExtend: + return getLoopDisposition(cast(S)->getOperand(), L); + case scAddRecExpr: { + const SCEVAddRecExpr *AR = cast(S); + + // If L is the addrec's loop, it's computable. + if (AR->getLoop() == L) + return LoopComputable; + + // Add recurrences are never invariant in the function-body (null loop). + if (!L) + return LoopVariant; + + // This recurrence is variant w.r.t. L if L contains AR's loop. + if (L->contains(AR->getLoop())) + return LoopVariant; + + // This recurrence is invariant w.r.t. L if AR's loop contains L. + if (AR->getLoop()->contains(L)) + return LoopInvariant; + + // This recurrence is variant w.r.t. L if any of its operands + // are variant. + for (SCEVAddRecExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); + I != E; ++I) + if (!isLoopInvariant(*I, L)) + return LoopVariant; + + // Otherwise it's loop-invariant. + return LoopInvariant; + } + case scAddExpr: + case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: { + const SCEVNAryExpr *NAry = cast(S); + bool HasVarying = false; + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); + I != E; ++I) { + LoopDisposition D = getLoopDisposition(*I, L); + if (D == LoopVariant) + return LoopVariant; + if (D == LoopComputable) + HasVarying = true; + } + return HasVarying ? LoopComputable : LoopInvariant; + } + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast(S); + LoopDisposition LD = getLoopDisposition(UDiv->getLHS(), L); + if (LD == LoopVariant) + return LoopVariant; + LoopDisposition RD = getLoopDisposition(UDiv->getRHS(), L); + if (RD == LoopVariant) + return LoopVariant; + return (LD == LoopInvariant && RD == LoopInvariant) ? + LoopInvariant : LoopComputable; + } + case scUnknown: + // All non-instruction values are loop invariant. All instructions are loop + // invariant if they are not contained in the specified loop. + // Instructions are never considered invariant in the function body + // (null loop) because they are defined within the "loop". + if (Instruction *I = dyn_cast(cast(S)->getValue())) + return (L && !L->contains(I)) ? LoopInvariant : LoopVariant; + return LoopInvariant; + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return LoopVariant; + default: break; + } + llvm_unreachable("Unknown SCEV kind!"); + return LoopVariant; +} + +bool ScalarEvolution::isLoopInvariant(const SCEV *S, const Loop *L) { + return getLoopDisposition(S, L) == LoopInvariant; +} + +bool ScalarEvolution::hasComputableLoopEvolution(const SCEV *S, const Loop *L) { + return getLoopDisposition(S, L) == LoopComputable; +} + +ScalarEvolution::BlockDisposition +ScalarEvolution::getBlockDisposition(const SCEV *S, const BasicBlock *BB) { + std::map &Values = BlockDispositions[S]; + std::pair::iterator, bool> + Pair = Values.insert(std::make_pair(BB, DoesNotDominateBlock)); + if (!Pair.second) + return Pair.first->second; + + BlockDisposition D = computeBlockDisposition(S, BB); + return BlockDispositions[S][BB] = D; +} + +ScalarEvolution::BlockDisposition +ScalarEvolution::computeBlockDisposition(const SCEV *S, const BasicBlock *BB) { + switch (S->getSCEVType()) { + case scConstant: + return ProperlyDominatesBlock; + case scTruncate: + case scZeroExtend: + case scSignExtend: + return getBlockDisposition(cast(S)->getOperand(), BB); + case scAddRecExpr: { + // This uses a "dominates" query instead of "properly dominates" query + // to test for proper dominance too, because the instruction which + // produces the addrec's value is a PHI, and a PHI effectively properly + // dominates its entire containing block. + const SCEVAddRecExpr *AR = cast(S); + if (!DT->dominates(AR->getLoop()->getHeader(), BB)) + return DoesNotDominateBlock; + } + // FALL THROUGH into SCEVNAryExpr handling. + case scAddExpr: + case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: { + const SCEVNAryExpr *NAry = cast(S); + bool Proper = true; + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); + I != E; ++I) { + BlockDisposition D = getBlockDisposition(*I, BB); + if (D == DoesNotDominateBlock) + return DoesNotDominateBlock; + if (D == DominatesBlock) + Proper = false; + } + return Proper ? ProperlyDominatesBlock : DominatesBlock; + } + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast(S); + const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS(); + BlockDisposition LD = getBlockDisposition(LHS, BB); + if (LD == DoesNotDominateBlock) + return DoesNotDominateBlock; + BlockDisposition RD = getBlockDisposition(RHS, BB); + if (RD == DoesNotDominateBlock) + return DoesNotDominateBlock; + return (LD == ProperlyDominatesBlock && RD == ProperlyDominatesBlock) ? + ProperlyDominatesBlock : DominatesBlock; + } + case scUnknown: + if (Instruction *I = + dyn_cast(cast(S)->getValue())) { + if (I->getParent() == BB) + return DominatesBlock; + if (DT->properlyDominates(I->getParent(), BB)) + return ProperlyDominatesBlock; + return DoesNotDominateBlock; + } + return ProperlyDominatesBlock; + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return DoesNotDominateBlock; + default: break; + } + llvm_unreachable("Unknown SCEV kind!"); + return DoesNotDominateBlock; +} + +bool ScalarEvolution::dominates(const SCEV *S, const BasicBlock *BB) { + return getBlockDisposition(S, BB) >= DominatesBlock; +} + +bool ScalarEvolution::properlyDominates(const SCEV *S, const BasicBlock *BB) { + return getBlockDisposition(S, BB) == ProperlyDominatesBlock; +} + +bool ScalarEvolution::hasOperand(const SCEV *S, const SCEV *Op) const { + switch (S->getSCEVType()) { + case scConstant: + return false; + case scTruncate: + case scZeroExtend: + case scSignExtend: { + const SCEVCastExpr *Cast = cast(S); + const SCEV *CastOp = Cast->getOperand(); + return Op == CastOp || hasOperand(CastOp, Op); + } + case scAddRecExpr: + case scAddExpr: + case scMulExpr: + case scUMaxExpr: + case scSMaxExpr: { + const SCEVNAryExpr *NAry = cast(S); + for (SCEVNAryExpr::op_iterator I = NAry->op_begin(), E = NAry->op_end(); + I != E; ++I) { + const SCEV *NAryOp = *I; + if (NAryOp == Op || hasOperand(NAryOp, Op)) + return true; + } + return false; + } + case scUDivExpr: { + const SCEVUDivExpr *UDiv = cast(S); + const SCEV *LHS = UDiv->getLHS(), *RHS = UDiv->getRHS(); + return LHS == Op || hasOperand(LHS, Op) || + RHS == Op || hasOperand(RHS, Op); + } + case scUnknown: + return false; + case scCouldNotCompute: + llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!"); + return false; + default: break; + } + llvm_unreachable("Unknown SCEV kind!"); + return false; +} + +void ScalarEvolution::forgetMemoizedResults(const SCEV *S) { + ValuesAtScopes.erase(S); + LoopDispositions.erase(S); + BlockDispositions.erase(S); + UnsignedRanges.erase(S); + SignedRanges.erase(S); +} diff --git a/final/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/final/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp new file mode 100644 index 00000000000..e9edb3e083d --- /dev/null +++ b/final/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -0,0 +1,173 @@ +//===- ScalarEvolutionAliasAnalysis.cpp - SCEV-based Alias Analysis -------===// +// +// 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 ScalarEvolutionAliasAnalysis pass, which implements a +// simple alias analysis implemented in terms of ScalarEvolution queries. +// +// This differs from traditional loop dependence analysis in that it tests +// for dependencies within a single iteration of a loop, rather than +// dependencies between different iterations. +// +// ScalarEvolution has a more complete understanding of pointer arithmetic +// than BasicAliasAnalysis' collection of ad-hoc analyses. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + /// ScalarEvolutionAliasAnalysis - This is a simple alias analysis + /// implementation that uses ScalarEvolution to answer queries. + class ScalarEvolutionAliasAnalysis : public FunctionPass, + public AliasAnalysis { + ScalarEvolution *SE; + + public: + static char ID; // Class identification, replacement for typeinfo + ScalarEvolutionAliasAnalysis() : FunctionPass(ID), SE(0) { + initializeScalarEvolutionAliasAnalysisPass( + *PassRegistry::getPassRegistry()); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(AnalysisID PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + private: + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual bool runOnFunction(Function &F); + virtual AliasResult alias(const Location &LocA, const Location &LocB); + + Value *GetBaseValue(const SCEV *S); + }; +} // End of anonymous namespace + +// Register this pass... +char ScalarEvolutionAliasAnalysis::ID = 0; +INITIALIZE_AG_PASS_BEGIN(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa", + "ScalarEvolution-based Alias Analysis", false, true, false) +INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) +INITIALIZE_AG_PASS_END(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa", + "ScalarEvolution-based Alias Analysis", false, true, false) + +FunctionPass *llvm::createScalarEvolutionAliasAnalysisPass() { + return new ScalarEvolutionAliasAnalysis(); +} + +void +ScalarEvolutionAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredTransitive(); + AU.setPreservesAll(); + AliasAnalysis::getAnalysisUsage(AU); +} + +bool +ScalarEvolutionAliasAnalysis::runOnFunction(Function &F) { + InitializeAliasAnalysis(this); + SE = &getAnalysis(); + return false; +} + +/// GetBaseValue - Given an expression, try to find a +/// base value. Return null is none was found. +Value * +ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) { + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // In an addrec, assume that the base will be in the start, rather + // than the step. + return GetBaseValue(AR->getStart()); + } else if (const SCEVAddExpr *A = dyn_cast(S)) { + // If there's a pointer operand, it'll be sorted at the end of the list. + const SCEV *Last = A->getOperand(A->getNumOperands()-1); + if (Last->getType()->isPointerTy()) + return GetBaseValue(Last); + } else if (const SCEVUnknown *U = dyn_cast(S)) { + // This is a leaf node. + return U->getValue(); + } + // No Identified object found. + return 0; +} + +AliasAnalysis::AliasResult +ScalarEvolutionAliasAnalysis::alias(const Location &LocA, + const Location &LocB) { + // If either of the memory references is empty, it doesn't matter what the + // pointer values are. This allows the code below to ignore this special + // case. + if (LocA.Size == 0 || LocB.Size == 0) + return NoAlias; + + // This is ScalarEvolutionAliasAnalysis. Get the SCEVs! + const SCEV *AS = SE->getSCEV(const_cast(LocA.Ptr)); + const SCEV *BS = SE->getSCEV(const_cast(LocB.Ptr)); + + // If they evaluate to the same expression, it's a MustAlias. + if (AS == BS) return MustAlias; + + // If something is known about the difference between the two addresses, + // see if it's enough to prove a NoAlias. + if (SE->getEffectiveSCEVType(AS->getType()) == + SE->getEffectiveSCEVType(BS->getType())) { + unsigned BitWidth = SE->getTypeSizeInBits(AS->getType()); + APInt ASizeInt(BitWidth, LocA.Size); + APInt BSizeInt(BitWidth, LocB.Size); + + // Compute the difference between the two pointers. + const SCEV *BA = SE->getMinusSCEV(BS, AS); + + // Test whether the difference is known to be great enough that memory of + // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt + // are non-zero, which is special-cased above. + if (ASizeInt.ule(SE->getUnsignedRange(BA).getUnsignedMin()) && + (-BSizeInt).uge(SE->getUnsignedRange(BA).getUnsignedMax())) + return NoAlias; + + // Folding the subtraction while preserving range information can be tricky + // (because of INT_MIN, etc.); if the prior test failed, swap AS and BS + // and try again to see if things fold better that way. + + // Compute the difference between the two pointers. + const SCEV *AB = SE->getMinusSCEV(AS, BS); + + // Test whether the difference is known to be great enough that memory of + // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt + // are non-zero, which is special-cased above. + if (BSizeInt.ule(SE->getUnsignedRange(AB).getUnsignedMin()) && + (-ASizeInt).uge(SE->getUnsignedRange(AB).getUnsignedMax())) + return NoAlias; + } + + // If ScalarEvolution can find an underlying object, form a new query. + // The correctness of this depends on ScalarEvolution not recognizing + // inttoptr and ptrtoint operators. + Value *AO = GetBaseValue(AS); + Value *BO = GetBaseValue(BS); + if ((AO && AO != LocA.Ptr) || (BO && BO != LocB.Ptr)) + if (alias(Location(AO ? AO : LocA.Ptr, + AO ? +UnknownSize : LocA.Size, + AO ? 0 : LocA.TBAATag), + Location(BO ? BO : LocB.Ptr, + BO ? +UnknownSize : LocB.Size, + BO ? 0 : LocB.TBAATag)) == NoAlias) + return NoAlias; + + // Forward the query to the next analysis. + return AliasAnalysis::alias(LocA, LocB); +} diff --git a/final/lib/Analysis/ScalarEvolutionExpander.cpp b/final/lib/Analysis/ScalarEvolutionExpander.cpp new file mode 100644 index 00000000000..76a94ea2746 --- /dev/null +++ b/final/lib/Analysis/ScalarEvolutionExpander.cpp @@ -0,0 +1,1376 @@ +//===- ScalarEvolutionExpander.cpp - Scalar Evolution Analysis --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the scalar evolution expander, +// which is used to generate the code corresponding to a given scalar evolution +// expression. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ScalarEvolutionExpander.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +/// ReuseOrCreateCast - Arrange for there to be a cast of V to Ty at IP, +/// reusing an existing cast if a suitable one exists, moving an existing +/// cast if a suitable one exists but isn't in the right place, or +/// creating a new one. +Value *SCEVExpander::ReuseOrCreateCast(Value *V, const Type *Ty, + Instruction::CastOps Op, + BasicBlock::iterator IP) { + // Check to see if there is already a cast! + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); + UI != E; ++UI) { + User *U = *UI; + if (U->getType() == Ty) + if (CastInst *CI = dyn_cast(U)) + if (CI->getOpcode() == Op) { + // If the cast isn't where we want it, fix it. + if (BasicBlock::iterator(CI) != IP) { + // Create a new cast, and leave the old cast in place in case + // it is being used as an insert point. Clear its operand + // so that it doesn't hold anything live. + Instruction *NewCI = CastInst::Create(Op, V, Ty, "", IP); + NewCI->takeName(CI); + CI->replaceAllUsesWith(NewCI); + CI->setOperand(0, UndefValue::get(V->getType())); + rememberInstruction(NewCI); + return NewCI; + } + rememberInstruction(CI); + return CI; + } + } + + // Create a new cast. + Instruction *I = CastInst::Create(Op, V, Ty, V->getName(), IP); + rememberInstruction(I); + return I; +} + +/// InsertNoopCastOfTo - Insert a cast of V to the specified type, +/// which must be possible with a noop cast, doing what we can to share +/// the casts. +Value *SCEVExpander::InsertNoopCastOfTo(Value *V, const Type *Ty) { + Instruction::CastOps Op = CastInst::getCastOpcode(V, false, Ty, false); + assert((Op == Instruction::BitCast || + Op == Instruction::PtrToInt || + Op == Instruction::IntToPtr) && + "InsertNoopCastOfTo cannot perform non-noop casts!"); + assert(SE.getTypeSizeInBits(V->getType()) == SE.getTypeSizeInBits(Ty) && + "InsertNoopCastOfTo cannot change sizes!"); + + // Short-circuit unnecessary bitcasts. + if (Op == Instruction::BitCast && V->getType() == Ty) + return V; + + // Short-circuit unnecessary inttoptr<->ptrtoint casts. + if ((Op == Instruction::PtrToInt || Op == Instruction::IntToPtr) && + SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(V->getType())) { + if (CastInst *CI = dyn_cast(V)) + if ((CI->getOpcode() == Instruction::PtrToInt || + CI->getOpcode() == Instruction::IntToPtr) && + SE.getTypeSizeInBits(CI->getType()) == + SE.getTypeSizeInBits(CI->getOperand(0)->getType())) + return CI->getOperand(0); + if (ConstantExpr *CE = dyn_cast(V)) + if ((CE->getOpcode() == Instruction::PtrToInt || + CE->getOpcode() == Instruction::IntToPtr) && + SE.getTypeSizeInBits(CE->getType()) == + SE.getTypeSizeInBits(CE->getOperand(0)->getType())) + return CE->getOperand(0); + } + + // Fold a cast of a constant. + if (Constant *C = dyn_cast(V)) + return ConstantExpr::getCast(Op, C, Ty); + + // Cast the argument at the beginning of the entry block, after + // any bitcasts of other arguments. + if (Argument *A = dyn_cast(V)) { + BasicBlock::iterator IP = A->getParent()->getEntryBlock().begin(); + while ((isa(IP) && + isa(cast(IP)->getOperand(0)) && + cast(IP)->getOperand(0) != A) || + isa(IP)) + ++IP; + return ReuseOrCreateCast(A, Ty, Op, IP); + } + + // Cast the instruction immediately after the instruction. + Instruction *I = cast(V); + BasicBlock::iterator IP = I; ++IP; + if (InvokeInst *II = dyn_cast(I)) + IP = II->getNormalDest()->begin(); + while (isa(IP) || isa(IP)) ++IP; + return ReuseOrCreateCast(I, Ty, Op, IP); +} + +/// InsertBinop - Insert the specified binary operator, doing a small amount +/// of work to avoid inserting an obviously redundant operation. +Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, + Value *LHS, Value *RHS) { + // Fold a binop with constant operands. + if (Constant *CLHS = dyn_cast(LHS)) + if (Constant *CRHS = dyn_cast(RHS)) + return ConstantExpr::get(Opcode, CLHS, CRHS); + + // Do a quick scan to see if we have this binop nearby. If so, reuse it. + unsigned ScanLimit = 6; + BasicBlock::iterator BlockBegin = Builder.GetInsertBlock()->begin(); + // Scanning starts from the last instruction before the insertion point. + BasicBlock::iterator IP = Builder.GetInsertPoint(); + if (IP != BlockBegin) { + --IP; + for (; ScanLimit; --IP, --ScanLimit) { + // Don't count dbg.value against the ScanLimit, to avoid perturbing the + // generated code. + if (isa(IP)) + ScanLimit++; + if (IP->getOpcode() == (unsigned)Opcode && IP->getOperand(0) == LHS && + IP->getOperand(1) == RHS) + return IP; + if (IP == BlockBegin) break; + } + } + + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(LHS) || !L->isLoopInvariant(RHS)) break; + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + + // If we haven't found this binop, insert it. + Value *BO = Builder.CreateBinOp(Opcode, LHS, RHS, "tmp"); + rememberInstruction(BO); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + + return BO; +} + +/// FactorOutConstant - Test if S is divisible by Factor, using signed +/// division. If so, update S with Factor divided out and return true. +/// S need not be evenly divisible if a reasonable remainder can be +/// computed. +/// TODO: When ScalarEvolution gets a SCEVSDivExpr, this can be made +/// unnecessary; in its place, just signed-divide Ops[i] by the scale and +/// check to see if the divide was folded. +static bool FactorOutConstant(const SCEV *&S, + const SCEV *&Remainder, + const SCEV *Factor, + ScalarEvolution &SE, + const TargetData *TD) { + // Everything is divisible by one. + if (Factor->isOne()) + return true; + + // x/x == 1. + if (S == Factor) { + S = SE.getConstant(S->getType(), 1); + return true; + } + + // For a Constant, check for a multiple of the given factor. + if (const SCEVConstant *C = dyn_cast(S)) { + // 0/x == 0. + if (C->isZero()) + return true; + // Check for divisibility. + if (const SCEVConstant *FC = dyn_cast(Factor)) { + ConstantInt *CI = + ConstantInt::get(SE.getContext(), + C->getValue()->getValue().sdiv( + FC->getValue()->getValue())); + // If the quotient is zero and the remainder is non-zero, reject + // the value at this scale. It will be considered for subsequent + // smaller scales. + if (!CI->isZero()) { + const SCEV *Div = SE.getConstant(CI); + S = Div; + Remainder = + SE.getAddExpr(Remainder, + SE.getConstant(C->getValue()->getValue().srem( + FC->getValue()->getValue()))); + return true; + } + } + } + + // In a Mul, check if there is a constant operand which is a multiple + // of the given factor. + if (const SCEVMulExpr *M = dyn_cast(S)) { + if (TD) { + // With TargetData, the size is known. Check if there is a constant + // operand which is a multiple of the given factor. If so, we can + // factor it. + const SCEVConstant *FC = cast(Factor); + if (const SCEVConstant *C = dyn_cast(M->getOperand(0))) + if (!C->getValue()->getValue().srem(FC->getValue()->getValue())) { + SmallVector NewMulOps(M->op_begin(), M->op_end()); + NewMulOps[0] = + SE.getConstant(C->getValue()->getValue().sdiv( + FC->getValue()->getValue())); + S = SE.getMulExpr(NewMulOps); + return true; + } + } else { + // Without TargetData, check if Factor can be factored out of any of the + // Mul's operands. If so, we can just remove it. + for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) { + const SCEV *SOp = M->getOperand(i); + const SCEV *Remainder = SE.getConstant(SOp->getType(), 0); + if (FactorOutConstant(SOp, Remainder, Factor, SE, TD) && + Remainder->isZero()) { + SmallVector NewMulOps(M->op_begin(), M->op_end()); + NewMulOps[i] = SOp; + S = SE.getMulExpr(NewMulOps); + return true; + } + } + } + } + + // In an AddRec, check if both start and step are divisible. + if (const SCEVAddRecExpr *A = dyn_cast(S)) { + const SCEV *Step = A->getStepRecurrence(SE); + const SCEV *StepRem = SE.getConstant(Step->getType(), 0); + if (!FactorOutConstant(Step, StepRem, Factor, SE, TD)) + return false; + if (!StepRem->isZero()) + return false; + const SCEV *Start = A->getStart(); + if (!FactorOutConstant(Start, Remainder, Factor, SE, TD)) + return false; + S = SE.getAddRecExpr(Start, Step, A->getLoop()); + return true; + } + + return false; +} + +/// SimplifyAddOperands - Sort and simplify a list of add operands. NumAddRecs +/// is the number of SCEVAddRecExprs present, which are kept at the end of +/// the list. +/// +static void SimplifyAddOperands(SmallVectorImpl &Ops, + const Type *Ty, + ScalarEvolution &SE) { + unsigned NumAddRecs = 0; + for (unsigned i = Ops.size(); i > 0 && isa(Ops[i-1]); --i) + ++NumAddRecs; + // Group Ops into non-addrecs and addrecs. + SmallVector NoAddRecs(Ops.begin(), Ops.end() - NumAddRecs); + SmallVector AddRecs(Ops.end() - NumAddRecs, Ops.end()); + // Let ScalarEvolution sort and simplify the non-addrecs list. + const SCEV *Sum = NoAddRecs.empty() ? + SE.getConstant(Ty, 0) : + SE.getAddExpr(NoAddRecs); + // If it returned an add, use the operands. Otherwise it simplified + // the sum into a single value, so just use that. + Ops.clear(); + if (const SCEVAddExpr *Add = dyn_cast(Sum)) + Ops.append(Add->op_begin(), Add->op_end()); + else if (!Sum->isZero()) + Ops.push_back(Sum); + // Then append the addrecs. + Ops.append(AddRecs.begin(), AddRecs.end()); +} + +/// SplitAddRecs - Flatten a list of add operands, moving addrec start values +/// out to the top level. For example, convert {a + b,+,c} to a, b, {0,+,d}. +/// This helps expose more opportunities for folding parts of the expressions +/// into GEP indices. +/// +static void SplitAddRecs(SmallVectorImpl &Ops, + const Type *Ty, + ScalarEvolution &SE) { + // Find the addrecs. + SmallVector AddRecs; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + while (const SCEVAddRecExpr *A = dyn_cast(Ops[i])) { + const SCEV *Start = A->getStart(); + if (Start->isZero()) break; + const SCEV *Zero = SE.getConstant(Ty, 0); + AddRecs.push_back(SE.getAddRecExpr(Zero, + A->getStepRecurrence(SE), + A->getLoop())); + if (const SCEVAddExpr *Add = dyn_cast(Start)) { + Ops[i] = Zero; + Ops.append(Add->op_begin(), Add->op_end()); + e += Add->getNumOperands(); + } else { + Ops[i] = Start; + } + } + if (!AddRecs.empty()) { + // Add the addrecs onto the end of the list. + Ops.append(AddRecs.begin(), AddRecs.end()); + // Resort the operand list, moving any constants to the front. + SimplifyAddOperands(Ops, Ty, SE); + } +} + +/// expandAddToGEP - Expand an addition expression with a pointer type into +/// a GEP instead of using ptrtoint+arithmetic+inttoptr. This helps +/// BasicAliasAnalysis and other passes analyze the result. See the rules +/// for getelementptr vs. inttoptr in +/// http://llvm.org/docs/LangRef.html#pointeraliasing +/// for details. +/// +/// Design note: The correctness of using getelementptr here depends on +/// ScalarEvolution not recognizing inttoptr and ptrtoint operators, as +/// they may introduce pointer arithmetic which may not be safely converted +/// into getelementptr. +/// +/// Design note: It might seem desirable for this function to be more +/// loop-aware. If some of the indices are loop-invariant while others +/// aren't, it might seem desirable to emit multiple GEPs, keeping the +/// loop-invariant portions of the overall computation outside the loop. +/// However, there are a few reasons this is not done here. Hoisting simple +/// arithmetic is a low-level optimization that often isn't very +/// important until late in the optimization process. In fact, passes +/// like InstructionCombining will combine GEPs, even if it means +/// pushing loop-invariant computation down into loops, so even if the +/// GEPs were split here, the work would quickly be undone. The +/// LoopStrengthReduction pass, which is usually run quite late (and +/// after the last InstructionCombining pass), takes care of hoisting +/// loop-invariant portions of expressions, after considering what +/// can be folded using target addressing modes. +/// +Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, + const SCEV *const *op_end, + const PointerType *PTy, + const Type *Ty, + Value *V) { + const Type *ElTy = PTy->getElementType(); + SmallVector GepIndices; + SmallVector Ops(op_begin, op_end); + bool AnyNonZeroIndices = false; + + // Split AddRecs up into parts as either of the parts may be usable + // without the other. + SplitAddRecs(Ops, Ty, SE); + + // Descend down the pointer's type and attempt to convert the other + // operands into GEP indices, at each level. The first index in a GEP + // indexes into the array implied by the pointer operand; the rest of + // the indices index into the element or field type selected by the + // preceding index. + for (;;) { + // If the scale size is not 0, attempt to factor out a scale for + // array indexing. + SmallVector ScaledOps; + if (ElTy->isSized()) { + const SCEV *ElSize = SE.getSizeOfExpr(ElTy); + if (!ElSize->isZero()) { + SmallVector NewOps; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + const SCEV *Op = Ops[i]; + const SCEV *Remainder = SE.getConstant(Ty, 0); + if (FactorOutConstant(Op, Remainder, ElSize, SE, SE.TD)) { + // Op now has ElSize factored out. + ScaledOps.push_back(Op); + if (!Remainder->isZero()) + NewOps.push_back(Remainder); + AnyNonZeroIndices = true; + } else { + // The operand was not divisible, so add it to the list of operands + // we'll scan next iteration. + NewOps.push_back(Ops[i]); + } + } + // If we made any changes, update Ops. + if (!ScaledOps.empty()) { + Ops = NewOps; + SimplifyAddOperands(Ops, Ty, SE); + } + } + } + + // Record the scaled array index for this level of the type. If + // we didn't find any operands that could be factored, tentatively + // assume that element zero was selected (since the zero offset + // would obviously be folded away). + Value *Scaled = ScaledOps.empty() ? + Constant::getNullValue(Ty) : + expandCodeFor(SE.getAddExpr(ScaledOps), Ty); + GepIndices.push_back(Scaled); + + // Collect struct field index operands. + while (const StructType *STy = dyn_cast(ElTy)) { + bool FoundFieldNo = false; + // An empty struct has no fields. + if (STy->getNumElements() == 0) break; + if (SE.TD) { + // With TargetData, field offsets are known. See if a constant offset + // falls within any of the struct fields. + if (Ops.empty()) break; + if (const SCEVConstant *C = dyn_cast(Ops[0])) + if (SE.getTypeSizeInBits(C->getType()) <= 64) { + const StructLayout &SL = *SE.TD->getStructLayout(STy); + uint64_t FullOffset = C->getValue()->getZExtValue(); + if (FullOffset < SL.getSizeInBytes()) { + unsigned ElIdx = SL.getElementContainingOffset(FullOffset); + GepIndices.push_back( + ConstantInt::get(Type::getInt32Ty(Ty->getContext()), ElIdx)); + ElTy = STy->getTypeAtIndex(ElIdx); + Ops[0] = + SE.getConstant(Ty, FullOffset - SL.getElementOffset(ElIdx)); + AnyNonZeroIndices = true; + FoundFieldNo = true; + } + } + } else { + // Without TargetData, just check for an offsetof expression of the + // appropriate struct type. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (const SCEVUnknown *U = dyn_cast(Ops[i])) { + const Type *CTy; + Constant *FieldNo; + if (U->isOffsetOf(CTy, FieldNo) && CTy == STy) { + GepIndices.push_back(FieldNo); + ElTy = + STy->getTypeAtIndex(cast(FieldNo)->getZExtValue()); + Ops[i] = SE.getConstant(Ty, 0); + AnyNonZeroIndices = true; + FoundFieldNo = true; + break; + } + } + } + // If no struct field offsets were found, tentatively assume that + // field zero was selected (since the zero offset would obviously + // be folded away). + if (!FoundFieldNo) { + ElTy = STy->getTypeAtIndex(0u); + GepIndices.push_back( + Constant::getNullValue(Type::getInt32Ty(Ty->getContext()))); + } + } + + if (const ArrayType *ATy = dyn_cast(ElTy)) + ElTy = ATy->getElementType(); + else + break; + } + + // If none of the operands were convertible to proper GEP indices, cast + // the base to i8* and do an ugly getelementptr with that. It's still + // better than ptrtoint+arithmetic+inttoptr at least. + if (!AnyNonZeroIndices) { + // Cast the base to i8*. + V = InsertNoopCastOfTo(V, + Type::getInt8PtrTy(Ty->getContext(), PTy->getAddressSpace())); + + // Expand the operands for a plain byte offset. + Value *Idx = expandCodeFor(SE.getAddExpr(Ops), Ty); + + // Fold a GEP with constant operands. + if (Constant *CLHS = dyn_cast(V)) + if (Constant *CRHS = dyn_cast(Idx)) + return ConstantExpr::getGetElementPtr(CLHS, &CRHS, 1); + + // Do a quick scan to see if we have this GEP nearby. If so, reuse it. + unsigned ScanLimit = 6; + BasicBlock::iterator BlockBegin = Builder.GetInsertBlock()->begin(); + // Scanning starts from the last instruction before the insertion point. + BasicBlock::iterator IP = Builder.GetInsertPoint(); + if (IP != BlockBegin) { + --IP; + for (; ScanLimit; --IP, --ScanLimit) { + // Don't count dbg.value against the ScanLimit, to avoid perturbing the + // generated code. + if (isa(IP)) + ScanLimit++; + if (IP->getOpcode() == Instruction::GetElementPtr && + IP->getOperand(0) == V && IP->getOperand(1) == Idx) + return IP; + if (IP == BlockBegin) break; + } + } + + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(V) || !L->isLoopInvariant(Idx)) break; + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + + // Emit a GEP. + Value *GEP = Builder.CreateGEP(V, Idx, "uglygep"); + rememberInstruction(GEP); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + + return GEP; + } + + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(V)) break; + + bool AnyIndexNotLoopInvariant = false; + for (SmallVectorImpl::const_iterator I = GepIndices.begin(), + E = GepIndices.end(); I != E; ++I) + if (!L->isLoopInvariant(*I)) { + AnyIndexNotLoopInvariant = true; + break; + } + if (AnyIndexNotLoopInvariant) + break; + + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + + // Insert a pretty getelementptr. Note that this GEP is not marked inbounds, + // because ScalarEvolution may have changed the address arithmetic to + // compute a value which is beyond the end of the allocated object. + Value *Casted = V; + if (V->getType() != PTy) + Casted = InsertNoopCastOfTo(Casted, PTy); + Value *GEP = Builder.CreateGEP(Casted, + GepIndices.begin(), + GepIndices.end(), + "scevgep"); + Ops.push_back(SE.getUnknown(GEP)); + rememberInstruction(GEP); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + + return expand(SE.getAddExpr(Ops)); +} + +/// isNonConstantNegative - Return true if the specified scev is negated, but +/// not a constant. +static bool isNonConstantNegative(const SCEV *F) { + const SCEVMulExpr *Mul = dyn_cast(F); + if (!Mul) return false; + + // If there is a constant factor, it will be first. + const SCEVConstant *SC = dyn_cast(Mul->getOperand(0)); + if (!SC) return false; + + // Return true if the value is negative, this matches things like (-42 * V). + return SC->getValue()->getValue().isNegative(); +} + +/// PickMostRelevantLoop - Given two loops pick the one that's most relevant for +/// SCEV expansion. If they are nested, this is the most nested. If they are +/// neighboring, pick the later. +static const Loop *PickMostRelevantLoop(const Loop *A, const Loop *B, + DominatorTree &DT) { + if (!A) return B; + if (!B) return A; + if (A->contains(B)) return B; + if (B->contains(A)) return A; + if (DT.dominates(A->getHeader(), B->getHeader())) return B; + if (DT.dominates(B->getHeader(), A->getHeader())) return A; + return A; // Arbitrarily break the tie. +} + +/// getRelevantLoop - Get the most relevant loop associated with the given +/// expression, according to PickMostRelevantLoop. +const Loop *SCEVExpander::getRelevantLoop(const SCEV *S) { + // Test whether we've already computed the most relevant loop for this SCEV. + std::pair::iterator, bool> Pair = + RelevantLoops.insert(std::make_pair(S, static_cast(0))); + if (!Pair.second) + return Pair.first->second; + + if (isa(S)) + // A constant has no relevant loops. + return 0; + if (const SCEVUnknown *U = dyn_cast(S)) { + if (const Instruction *I = dyn_cast(U->getValue())) + return Pair.first->second = SE.LI->getLoopFor(I->getParent()); + // A non-instruction has no relevant loops. + return 0; + } + if (const SCEVNAryExpr *N = dyn_cast(S)) { + const Loop *L = 0; + if (const SCEVAddRecExpr *AR = dyn_cast(S)) + L = AR->getLoop(); + for (SCEVNAryExpr::op_iterator I = N->op_begin(), E = N->op_end(); + I != E; ++I) + L = PickMostRelevantLoop(L, getRelevantLoop(*I), *SE.DT); + return RelevantLoops[N] = L; + } + if (const SCEVCastExpr *C = dyn_cast(S)) { + const Loop *Result = getRelevantLoop(C->getOperand()); + return RelevantLoops[C] = Result; + } + if (const SCEVUDivExpr *D = dyn_cast(S)) { + const Loop *Result = + PickMostRelevantLoop(getRelevantLoop(D->getLHS()), + getRelevantLoop(D->getRHS()), + *SE.DT); + return RelevantLoops[D] = Result; + } + llvm_unreachable("Unexpected SCEV type!"); + return 0; +} + +namespace { + +/// LoopCompare - Compare loops by PickMostRelevantLoop. +class LoopCompare { + DominatorTree &DT; +public: + explicit LoopCompare(DominatorTree &dt) : DT(dt) {} + + bool operator()(std::pair LHS, + std::pair RHS) const { + // Keep pointer operands sorted at the end. + if (LHS.second->getType()->isPointerTy() != + RHS.second->getType()->isPointerTy()) + return LHS.second->getType()->isPointerTy(); + + // Compare loops with PickMostRelevantLoop. + if (LHS.first != RHS.first) + return PickMostRelevantLoop(LHS.first, RHS.first, DT) != LHS.first; + + // If one operand is a non-constant negative and the other is not, + // put the non-constant negative on the right so that a sub can + // be used instead of a negate and add. + if (isNonConstantNegative(LHS.second)) { + if (!isNonConstantNegative(RHS.second)) + return false; + } else if (isNonConstantNegative(RHS.second)) + return true; + + // Otherwise they are equivalent according to this comparison. + return false; + } +}; + +} + +Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + + // Collect all the add operands in a loop, along with their associated loops. + // Iterate in reverse so that constants are emitted last, all else equal, and + // so that pointer operands are inserted first, which the code below relies on + // to form more involved GEPs. + SmallVector, 8> OpsAndLoops; + for (std::reverse_iterator I(S->op_end()), + E(S->op_begin()); I != E; ++I) + OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I)); + + // Sort by loop. Use a stable sort so that constants follow non-constants and + // pointer operands precede non-pointer operands. + std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT)); + + // Emit instructions to add all the operands. Hoist as much as possible + // out of loops, and form meaningful getelementptrs where possible. + Value *Sum = 0; + for (SmallVectorImpl >::iterator + I = OpsAndLoops.begin(), E = OpsAndLoops.end(); I != E; ) { + const Loop *CurLoop = I->first; + const SCEV *Op = I->second; + if (!Sum) { + // This is the first operand. Just expand it. + Sum = expand(Op); + ++I; + } else if (const PointerType *PTy = dyn_cast(Sum->getType())) { + // The running sum expression is a pointer. Try to form a getelementptr + // at this level with that as the base. + SmallVector NewOps; + for (; I != E && I->first == CurLoop; ++I) { + // If the operand is SCEVUnknown and not instructions, peek through + // it, to enable more of it to be folded into the GEP. + const SCEV *X = I->second; + if (const SCEVUnknown *U = dyn_cast(X)) + if (!isa(U->getValue())) + X = SE.getSCEV(U->getValue()); + NewOps.push_back(X); + } + Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, Sum); + } else if (const PointerType *PTy = dyn_cast(Op->getType())) { + // The running sum is an integer, and there's a pointer at this level. + // Try to form a getelementptr. If the running sum is instructions, + // use a SCEVUnknown to avoid re-analyzing them. + SmallVector NewOps; + NewOps.push_back(isa(Sum) ? SE.getUnknown(Sum) : + SE.getSCEV(Sum)); + for (++I; I != E && I->first == CurLoop; ++I) + NewOps.push_back(I->second); + Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, expand(Op)); + } else if (isNonConstantNegative(Op)) { + // Instead of doing a negate and add, just do a subtract. + Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty); + Sum = InsertNoopCastOfTo(Sum, Ty); + Sum = InsertBinop(Instruction::Sub, Sum, W); + ++I; + } else { + // A simple add. + Value *W = expandCodeFor(Op, Ty); + Sum = InsertNoopCastOfTo(Sum, Ty); + // Canonicalize a constant to the RHS. + if (isa(Sum)) std::swap(Sum, W); + Sum = InsertBinop(Instruction::Add, Sum, W); + ++I; + } + } + + return Sum; +} + +Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + + // Collect all the mul operands in a loop, along with their associated loops. + // Iterate in reverse so that constants are emitted last, all else equal. + SmallVector, 8> OpsAndLoops; + for (std::reverse_iterator I(S->op_end()), + E(S->op_begin()); I != E; ++I) + OpsAndLoops.push_back(std::make_pair(getRelevantLoop(*I), *I)); + + // Sort by loop. Use a stable sort so that constants follow non-constants. + std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT)); + + // Emit instructions to mul all the operands. Hoist as much as possible + // out of loops. + Value *Prod = 0; + for (SmallVectorImpl >::iterator + I = OpsAndLoops.begin(), E = OpsAndLoops.end(); I != E; ) { + const SCEV *Op = I->second; + if (!Prod) { + // This is the first operand. Just expand it. + Prod = expand(Op); + ++I; + } else if (Op->isAllOnesValue()) { + // Instead of doing a multiply by negative one, just do a negate. + Prod = InsertNoopCastOfTo(Prod, Ty); + Prod = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), Prod); + ++I; + } else { + // A simple mul. + Value *W = expandCodeFor(Op, Ty); + Prod = InsertNoopCastOfTo(Prod, Ty); + // Canonicalize a constant to the RHS. + if (isa(Prod)) std::swap(Prod, W); + Prod = InsertBinop(Instruction::Mul, Prod, W); + ++I; + } + } + + return Prod; +} + +Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + + Value *LHS = expandCodeFor(S->getLHS(), Ty); + if (const SCEVConstant *SC = dyn_cast(S->getRHS())) { + const APInt &RHS = SC->getValue()->getValue(); + if (RHS.isPowerOf2()) + return InsertBinop(Instruction::LShr, LHS, + ConstantInt::get(Ty, RHS.logBase2())); + } + + Value *RHS = expandCodeFor(S->getRHS(), Ty); + return InsertBinop(Instruction::UDiv, LHS, RHS); +} + +/// Move parts of Base into Rest to leave Base with the minimal +/// expression that provides a pointer operand suitable for a +/// GEP expansion. +static void ExposePointerBase(const SCEV *&Base, const SCEV *&Rest, + ScalarEvolution &SE) { + while (const SCEVAddRecExpr *A = dyn_cast(Base)) { + Base = A->getStart(); + Rest = SE.getAddExpr(Rest, + SE.getAddRecExpr(SE.getConstant(A->getType(), 0), + A->getStepRecurrence(SE), + A->getLoop())); + } + if (const SCEVAddExpr *A = dyn_cast(Base)) { + Base = A->getOperand(A->getNumOperands()-1); + SmallVector NewAddOps(A->op_begin(), A->op_end()); + NewAddOps.back() = Rest; + Rest = SE.getAddExpr(NewAddOps); + ExposePointerBase(Base, Rest, SE); + } +} + +/// getAddRecExprPHILiterally - Helper for expandAddRecExprLiterally. Expand +/// the base addrec, which is the addrec without any non-loop-dominating +/// values, and return the PHI. +PHINode * +SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, + const Loop *L, + const Type *ExpandTy, + const Type *IntTy) { + // Reuse a previously-inserted PHI, if present. + for (BasicBlock::iterator I = L->getHeader()->begin(); + PHINode *PN = dyn_cast(I); ++I) + if (SE.isSCEVable(PN->getType()) && + (SE.getEffectiveSCEVType(PN->getType()) == + SE.getEffectiveSCEVType(Normalized->getType())) && + SE.getSCEV(PN) == Normalized) + if (BasicBlock *LatchBlock = L->getLoopLatch()) { + Instruction *IncV = + cast(PN->getIncomingValueForBlock(LatchBlock)); + + // Determine if this is a well-behaved chain of instructions leading + // back to the PHI. It probably will be, if we're scanning an inner + // loop already visited by LSR for example, but it wouldn't have + // to be. + do { + if (IncV->getNumOperands() == 0 || isa(IncV) || + (isa(IncV) && !isa(IncV))) { + IncV = 0; + break; + } + // If any of the operands don't dominate the insert position, bail. + // Addrec operands are always loop-invariant, so this can only happen + // if there are instructions which haven't been hoisted. + for (User::op_iterator OI = IncV->op_begin()+1, + OE = IncV->op_end(); OI != OE; ++OI) + if (Instruction *OInst = dyn_cast(OI)) + if (!SE.DT->dominates(OInst, IVIncInsertPos)) { + IncV = 0; + break; + } + if (!IncV) + break; + // Advance to the next instruction. + IncV = dyn_cast(IncV->getOperand(0)); + if (!IncV) + break; + if (IncV->mayHaveSideEffects()) { + IncV = 0; + break; + } + } while (IncV != PN); + + if (IncV) { + // Ok, the add recurrence looks usable. + // Remember this PHI, even in post-inc mode. + InsertedValues.insert(PN); + // Remember the increment. + IncV = cast(PN->getIncomingValueForBlock(LatchBlock)); + rememberInstruction(IncV); + if (L == IVIncInsertLoop) + do { + if (SE.DT->dominates(IncV, IVIncInsertPos)) + break; + // Make sure the increment is where we want it. But don't move it + // down past a potential existing post-inc user. + IncV->moveBefore(IVIncInsertPos); + IVIncInsertPos = IncV; + IncV = cast(IncV->getOperand(0)); + } while (IncV != PN); + return PN; + } + } + + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Expand code for the start value. + Value *StartV = expandCodeFor(Normalized->getStart(), ExpandTy, + L->getHeader()->begin()); + + // Expand code for the step value. Insert instructions right before the + // terminator corresponding to the back-edge. Do this before creating the PHI + // so that PHI reuse code doesn't see an incomplete PHI. If the stride is + // negative, insert a sub instead of an add for the increment (unless it's a + // constant, because subtracts of constants are canonicalized to adds). + const SCEV *Step = Normalized->getStepRecurrence(SE); + bool isPointer = ExpandTy->isPointerTy(); + bool isNegative = !isPointer && isNonConstantNegative(Step); + if (isNegative) + Step = SE.getNegativeSCEV(Step); + Value *StepV = expandCodeFor(Step, IntTy, L->getHeader()->begin()); + + // Create the PHI. + Builder.SetInsertPoint(L->getHeader(), L->getHeader()->begin()); + PHINode *PN = Builder.CreatePHI(ExpandTy, "lsr.iv"); + rememberInstruction(PN); + + // Create the step instructions and populate the PHI. + BasicBlock *Header = L->getHeader(); + for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); + HPI != HPE; ++HPI) { + BasicBlock *Pred = *HPI; + + // Add a start value. + if (!L->contains(Pred)) { + PN->addIncoming(StartV, Pred); + continue; + } + + // Create a step value and add it to the PHI. If IVIncInsertLoop is + // non-null and equal to the addrec's loop, insert the instructions + // at IVIncInsertPos. + Instruction *InsertPos = L == IVIncInsertLoop ? + IVIncInsertPos : Pred->getTerminator(); + Builder.SetInsertPoint(InsertPos->getParent(), InsertPos); + Value *IncV; + // If the PHI is a pointer, use a GEP, otherwise use an add or sub. + if (isPointer) { + const PointerType *GEPPtrTy = cast(ExpandTy); + // If the step isn't constant, don't use an implicitly scaled GEP, because + // that would require a multiply inside the loop. + if (!isa(StepV)) + GEPPtrTy = PointerType::get(Type::getInt1Ty(SE.getContext()), + GEPPtrTy->getAddressSpace()); + const SCEV *const StepArray[1] = { SE.getSCEV(StepV) }; + IncV = expandAddToGEP(StepArray, StepArray+1, GEPPtrTy, IntTy, PN); + if (IncV->getType() != PN->getType()) { + IncV = Builder.CreateBitCast(IncV, PN->getType(), "tmp"); + rememberInstruction(IncV); + } + } else { + IncV = isNegative ? + Builder.CreateSub(PN, StepV, "lsr.iv.next") : + Builder.CreateAdd(PN, StepV, "lsr.iv.next"); + rememberInstruction(IncV); + } + PN->addIncoming(IncV, Pred); + } + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + + // Remember this PHI, even in post-inc mode. + InsertedValues.insert(PN); + + return PN; +} + +Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { + const Type *STy = S->getType(); + const Type *IntTy = SE.getEffectiveSCEVType(STy); + const Loop *L = S->getLoop(); + + // Determine a normalized form of this expression, which is the expression + // before any post-inc adjustment is made. + const SCEVAddRecExpr *Normalized = S; + if (PostIncLoops.count(L)) { + PostIncLoopSet Loops; + Loops.insert(L); + Normalized = + cast(TransformForPostIncUse(Normalize, S, 0, 0, + Loops, SE, *SE.DT)); + } + + // Strip off any non-loop-dominating component from the addrec start. + const SCEV *Start = Normalized->getStart(); + const SCEV *PostLoopOffset = 0; + if (!SE.properlyDominates(Start, L->getHeader())) { + PostLoopOffset = Start; + Start = SE.getConstant(Normalized->getType(), 0); + Normalized = + cast(SE.getAddRecExpr(Start, + Normalized->getStepRecurrence(SE), + Normalized->getLoop())); + } + + // Strip off any non-loop-dominating component from the addrec step. + const SCEV *Step = Normalized->getStepRecurrence(SE); + const SCEV *PostLoopScale = 0; + if (!SE.dominates(Step, L->getHeader())) { + PostLoopScale = Step; + Step = SE.getConstant(Normalized->getType(), 1); + Normalized = + cast(SE.getAddRecExpr(Start, Step, + Normalized->getLoop())); + } + + // Expand the core addrec. If we need post-loop scaling, force it to + // expand to an integer type to avoid the need for additional casting. + const Type *ExpandTy = PostLoopScale ? IntTy : STy; + PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy); + + // Accommodate post-inc mode, if necessary. + Value *Result; + if (!PostIncLoops.count(L)) + Result = PN; + else { + // In PostInc mode, use the post-incremented value. + BasicBlock *LatchBlock = L->getLoopLatch(); + assert(LatchBlock && "PostInc mode requires a unique loop latch!"); + Result = PN->getIncomingValueForBlock(LatchBlock); + } + + // Re-apply any non-loop-dominating scale. + if (PostLoopScale) { + Result = InsertNoopCastOfTo(Result, IntTy); + Result = Builder.CreateMul(Result, + expandCodeFor(PostLoopScale, IntTy)); + rememberInstruction(Result); + } + + // Re-apply any non-loop-dominating offset. + if (PostLoopOffset) { + if (const PointerType *PTy = dyn_cast(ExpandTy)) { + const SCEV *const OffsetArray[1] = { PostLoopOffset }; + Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result); + } else { + Result = InsertNoopCastOfTo(Result, IntTy); + Result = Builder.CreateAdd(Result, + expandCodeFor(PostLoopOffset, IntTy)); + rememberInstruction(Result); + } + } + + return Result; +} + +Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { + if (!CanonicalMode) return expandAddRecExprLiterally(S); + + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + const Loop *L = S->getLoop(); + + // First check for an existing canonical IV in a suitable type. + PHINode *CanonicalIV = 0; + if (PHINode *PN = L->getCanonicalInductionVariable()) + if (SE.getTypeSizeInBits(PN->getType()) >= SE.getTypeSizeInBits(Ty)) + CanonicalIV = PN; + + // Rewrite an AddRec in terms of the canonical induction variable, if + // its type is more narrow. + if (CanonicalIV && + SE.getTypeSizeInBits(CanonicalIV->getType()) > + SE.getTypeSizeInBits(Ty)) { + SmallVector NewOps(S->getNumOperands()); + for (unsigned i = 0, e = S->getNumOperands(); i != e; ++i) + NewOps[i] = SE.getAnyExtendExpr(S->op_begin()[i], CanonicalIV->getType()); + Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop())); + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + BasicBlock::iterator NewInsertPt = + llvm::next(BasicBlock::iterator(cast(V))); + while (isa(NewInsertPt) || isa(NewInsertPt)) + ++NewInsertPt; + V = expandCodeFor(SE.getTruncateExpr(SE.getUnknown(V), Ty), 0, + NewInsertPt); + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + return V; + } + + // {X,+,F} --> X + {0,+,F} + if (!S->getStart()->isZero()) { + SmallVector NewOps(S->op_begin(), S->op_end()); + NewOps[0] = SE.getConstant(Ty, 0); + const SCEV *Rest = SE.getAddRecExpr(NewOps, L); + + // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the + // comments on expandAddToGEP for details. + const SCEV *Base = S->getStart(); + const SCEV *RestArray[1] = { Rest }; + // Dig into the expression to find the pointer base for a GEP. + ExposePointerBase(Base, RestArray[0], SE); + // If we found a pointer, expand the AddRec with a GEP. + if (const PointerType *PTy = dyn_cast(Base->getType())) { + // Make sure the Base isn't something exotic, such as a multiplied + // or divided pointer value. In those cases, the result type isn't + // actually a pointer type. + if (!isa(Base) && !isa(Base)) { + Value *StartV = expand(Base); + assert(StartV->getType() == PTy && "Pointer type mismatch for GEP!"); + return expandAddToGEP(RestArray, RestArray+1, PTy, Ty, StartV); + } + } + + // Just do a normal add. Pre-expand the operands to suppress folding. + return expand(SE.getAddExpr(SE.getUnknown(expand(S->getStart())), + SE.getUnknown(expand(Rest)))); + } + + // If we don't yet have a canonical IV, create one. + if (!CanonicalIV) { + // Create and insert the PHI node for the induction variable in the + // specified loop. + BasicBlock *Header = L->getHeader(); + CanonicalIV = PHINode::Create(Ty, "indvar", Header->begin()); + rememberInstruction(CanonicalIV); + + Constant *One = ConstantInt::get(Ty, 1); + for (pred_iterator HPI = pred_begin(Header), HPE = pred_end(Header); + HPI != HPE; ++HPI) { + BasicBlock *HP = *HPI; + if (L->contains(HP)) { + // Insert a unit add instruction right before the terminator + // corresponding to the back-edge. + Instruction *Add = BinaryOperator::CreateAdd(CanonicalIV, One, + "indvar.next", + HP->getTerminator()); + rememberInstruction(Add); + CanonicalIV->addIncoming(Add, HP); + } else { + CanonicalIV->addIncoming(Constant::getNullValue(Ty), HP); + } + } + } + + // {0,+,1} --> Insert a canonical induction variable into the loop! + if (S->isAffine() && S->getOperand(1)->isOne()) { + assert(Ty == SE.getEffectiveSCEVType(CanonicalIV->getType()) && + "IVs with types different from the canonical IV should " + "already have been handled!"); + return CanonicalIV; + } + + // {0,+,F} --> {0,+,1} * F + + // If this is a simple linear addrec, emit it now as a special case. + if (S->isAffine()) // {0,+,F} --> i*F + return + expand(SE.getTruncateOrNoop( + SE.getMulExpr(SE.getUnknown(CanonicalIV), + SE.getNoopOrAnyExtend(S->getOperand(1), + CanonicalIV->getType())), + Ty)); + + // If this is a chain of recurrences, turn it into a closed form, using the + // folders, then expandCodeFor the closed form. This allows the folders to + // simplify the expression without having to build a bunch of special code + // into this folder. + const SCEV *IH = SE.getUnknown(CanonicalIV); // Get I as a "symbolic" SCEV. + + // Promote S up to the canonical IV type, if the cast is foldable. + const SCEV *NewS = S; + const SCEV *Ext = SE.getNoopOrAnyExtend(S, CanonicalIV->getType()); + if (isa(Ext)) + NewS = Ext; + + const SCEV *V = cast(NewS)->evaluateAtIteration(IH, SE); + //cerr << "Evaluated: " << *this << "\n to: " << *V << "\n"; + + // Truncate the result down to the original type, if needed. + const SCEV *T = SE.getTruncateOrNoop(V, Ty); + return expand(T); +} + +Value *SCEVExpander::visitTruncateExpr(const SCEVTruncateExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateTrunc(V, Ty, "tmp"); + rememberInstruction(I); + return I; +} + +Value *SCEVExpander::visitZeroExtendExpr(const SCEVZeroExtendExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateZExt(V, Ty, "tmp"); + rememberInstruction(I); + return I; +} + +Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); + Value *V = expandCodeFor(S->getOperand(), + SE.getEffectiveSCEVType(S->getOperand()->getType())); + Value *I = Builder.CreateSExt(V, Ty, "tmp"); + rememberInstruction(I); + return I; +} + +Value *SCEVExpander::visitSMaxExpr(const SCEVSMaxExpr *S) { + Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); + const Type *Ty = LHS->getType(); + for (int i = S->getNumOperands()-2; i >= 0; --i) { + // In the case of mixed integer and pointer types, do the + // rest of the comparisons as integer. + if (S->getOperand(i)->getType() != Ty) { + Ty = SE.getEffectiveSCEVType(Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); + } + Value *RHS = expandCodeFor(S->getOperand(i), Ty); + Value *ICmp = Builder.CreateICmpSGT(LHS, RHS, "tmp"); + rememberInstruction(ICmp); + Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "smax"); + rememberInstruction(Sel); + LHS = Sel; + } + // In the case of mixed integer and pointer types, cast the + // final result back to the pointer type. + if (LHS->getType() != S->getType()) + LHS = InsertNoopCastOfTo(LHS, S->getType()); + return LHS; +} + +Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { + Value *LHS = expand(S->getOperand(S->getNumOperands()-1)); + const Type *Ty = LHS->getType(); + for (int i = S->getNumOperands()-2; i >= 0; --i) { + // In the case of mixed integer and pointer types, do the + // rest of the comparisons as integer. + if (S->getOperand(i)->getType() != Ty) { + Ty = SE.getEffectiveSCEVType(Ty); + LHS = InsertNoopCastOfTo(LHS, Ty); + } + Value *RHS = expandCodeFor(S->getOperand(i), Ty); + Value *ICmp = Builder.CreateICmpUGT(LHS, RHS, "tmp"); + rememberInstruction(ICmp); + Value *Sel = Builder.CreateSelect(ICmp, LHS, RHS, "umax"); + rememberInstruction(Sel); + LHS = Sel; + } + // In the case of mixed integer and pointer types, cast the + // final result back to the pointer type. + if (LHS->getType() != S->getType()) + LHS = InsertNoopCastOfTo(LHS, S->getType()); + return LHS; +} + +Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty, + Instruction *I) { + BasicBlock::iterator IP = I; + while (isInsertedInstruction(IP) || isa(IP)) + ++IP; + Builder.SetInsertPoint(IP->getParent(), IP); + return expandCodeFor(SH, Ty); +} + +Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty) { + // Expand the code for this SCEV. + Value *V = expand(SH); + if (Ty) { + assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) && + "non-trivial casts should be done with the SCEVs directly!"); + V = InsertNoopCastOfTo(V, Ty); + } + return V; +} + +Value *SCEVExpander::expand(const SCEV *S) { + // Compute an insertion point for this SCEV object. Hoist the instructions + // as far out in the loop nest as possible. + Instruction *InsertPt = Builder.GetInsertPoint(); + for (Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock()); ; + L = L->getParentLoop()) + if (SE.isLoopInvariant(S, L)) { + if (!L) break; + if (BasicBlock *Preheader = L->getLoopPreheader()) + InsertPt = Preheader->getTerminator(); + } else { + // If the SCEV is computable at this level, insert it into the header + // after the PHIs (and after any other instructions that we've inserted + // there) so that it is guaranteed to dominate any user inside the loop. + if (L && SE.hasComputableLoopEvolution(S, L) && !PostIncLoops.count(L)) + InsertPt = L->getHeader()->getFirstNonPHI(); + while (isInsertedInstruction(InsertPt) || isa(InsertPt)) + InsertPt = llvm::next(BasicBlock::iterator(InsertPt)); + break; + } + + // Check to see if we already expanded this here. + std::map, + AssertingVH >::iterator I = + InsertedExpressions.find(std::make_pair(S, InsertPt)); + if (I != InsertedExpressions.end()) + return I->second; + + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + Builder.SetInsertPoint(InsertPt->getParent(), InsertPt); + + // Expand the expression into instructions. + Value *V = visit(S); + + // Remember the expanded value for this SCEV at this location. + if (PostIncLoops.empty()) + InsertedExpressions[std::make_pair(S, InsertPt)] = V; + + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + return V; +} + +void SCEVExpander::rememberInstruction(Value *I) { + if (!PostIncLoops.empty()) + InsertedPostIncValues.insert(I); + else + InsertedValues.insert(I); + + // If we just claimed an existing instruction and that instruction had + // been the insert point, adjust the insert point forward so that + // subsequently inserted code will be dominated. + if (Builder.GetInsertPoint() == I) { + BasicBlock::iterator It = cast(I); + do { ++It; } while (isInsertedInstruction(It) || + isa(It)); + Builder.SetInsertPoint(Builder.GetInsertBlock(), It); + } +} + +void SCEVExpander::restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I) { + // If we acquired more instructions since the old insert point was saved, + // advance past them. + while (isInsertedInstruction(I) || isa(I)) ++I; + + Builder.SetInsertPoint(BB, I); +} + +/// getOrInsertCanonicalInductionVariable - This method returns the +/// canonical induction variable of the specified type for the specified +/// loop (inserting one if there is none). A canonical induction variable +/// starts at zero and steps by one on each iteration. +PHINode * +SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, + const Type *Ty) { + assert(Ty->isIntegerTy() && "Can only insert integer induction variables!"); + + // Build a SCEV for {0,+,1}. + const SCEV *H = SE.getAddRecExpr(SE.getConstant(Ty, 0), + SE.getConstant(Ty, 1), L); + + // Emit code for it. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + PHINode *V = cast(expandCodeFor(H, 0, L->getHeader()->begin())); + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + + return V; +} diff --git a/final/lib/Analysis/ScalarEvolutionNormalization.cpp b/final/lib/Analysis/ScalarEvolutionNormalization.cpp new file mode 100644 index 00000000000..ac36cef89eb --- /dev/null +++ b/final/lib/Analysis/ScalarEvolutionNormalization.cpp @@ -0,0 +1,183 @@ +//===- ScalarEvolutionNormalization.cpp - See below -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements utilities for working with "normalized" expressions. +// See the comments at the top of ScalarEvolutionNormalization.h for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Analysis/ScalarEvolutionNormalization.h" +using namespace llvm; + +/// IVUseShouldUsePostIncValue - We have discovered a "User" of an IV expression +/// and now we need to decide whether the user should use the preinc or post-inc +/// value. If this user should use the post-inc version of the IV, return true. +/// +/// Choosing wrong here can break dominance properties (if we choose to use the +/// post-inc value when we cannot) or it can end up adding extra live-ranges to +/// the loop, resulting in reg-reg copies (if we use the pre-inc value when we +/// should use the post-inc value). +static bool IVUseShouldUsePostIncValue(Instruction *User, Value *Operand, + const Loop *L, DominatorTree *DT) { + // If the user is in the loop, use the preinc value. + if (L->contains(User)) return false; + + BasicBlock *LatchBlock = L->getLoopLatch(); + if (!LatchBlock) + return false; + + // Ok, the user is outside of the loop. If it is dominated by the latch + // block, use the post-inc value. + if (DT->dominates(LatchBlock, User->getParent())) + return true; + + // There is one case we have to be careful of: PHI nodes. These little guys + // can live in blocks that are not dominated by the latch block, but (since + // their uses occur in the predecessor block, not the block the PHI lives in) + // should still use the post-inc value. Check for this case now. + PHINode *PN = dyn_cast(User); + if (!PN || !Operand) return false; // not a phi, not dominated by latch block. + + // Look at all of the uses of Operand by the PHI node. If any use corresponds + // to a block that is not dominated by the latch block, give up and use the + // preincremented value. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == Operand && + !DT->dominates(LatchBlock, PN->getIncomingBlock(i))) + return false; + + // Okay, all uses of Operand by PN are in predecessor blocks that really are + // dominated by the latch block. Use the post-incremented value. + return true; +} + +const SCEV *llvm::TransformForPostIncUse(TransformKind Kind, + const SCEV *S, + Instruction *User, + Value *OperandValToReplace, + PostIncLoopSet &Loops, + ScalarEvolution &SE, + DominatorTree &DT) { + if (isa(S) || isa(S)) + return S; + + if (const SCEVCastExpr *X = dyn_cast(S)) { + const SCEV *O = X->getOperand(); + const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, + Loops, SE, DT); + if (O != N) + switch (S->getSCEVType()) { + case scZeroExtend: return SE.getZeroExtendExpr(N, S->getType()); + case scSignExtend: return SE.getSignExtendExpr(N, S->getType()); + case scTruncate: return SE.getTruncateExpr(N, S->getType()); + default: llvm_unreachable("Unexpected SCEVCastExpr kind!"); + } + return S; + } + + if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // An addrec. This is the interesting part. + SmallVector Operands; + const Loop *L = AR->getLoop(); + // The addrec conceptually uses its operands at loop entry. + Instruction *LUser = L->getHeader()->begin(); + // Transform each operand. + for (SCEVNAryExpr::op_iterator I = AR->op_begin(), E = AR->op_end(); + I != E; ++I) { + const SCEV *O = *I; + const SCEV *N = TransformForPostIncUse(Kind, O, LUser, 0, Loops, SE, DT); + Operands.push_back(N); + } + const SCEV *Result = SE.getAddRecExpr(Operands, L); + switch (Kind) { + default: llvm_unreachable("Unexpected transform name!"); + case NormalizeAutodetect: + if (IVUseShouldUsePostIncValue(User, OperandValToReplace, L, &DT)) { + const SCEV *TransformedStep = + TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), + User, OperandValToReplace, Loops, SE, DT); + Result = SE.getMinusSCEV(Result, TransformedStep); + Loops.insert(L); + } +#if 0 + // This assert is conceptually correct, but ScalarEvolution currently + // sometimes fails to canonicalize two equal SCEVs to exactly the same + // form. It's possibly a pessimization when this happens, but it isn't a + // correctness problem, so disable this assert for now. + assert(S == TransformForPostIncUse(Denormalize, Result, + User, OperandValToReplace, + Loops, SE, DT) && + "SCEV normalization is not invertible!"); +#endif + break; + case Normalize: + if (Loops.count(L)) { + const SCEV *TransformedStep = + TransformForPostIncUse(Kind, AR->getStepRecurrence(SE), + User, OperandValToReplace, Loops, SE, DT); + Result = SE.getMinusSCEV(Result, TransformedStep); + } +#if 0 + // See the comment on the assert above. + assert(S == TransformForPostIncUse(Denormalize, Result, + User, OperandValToReplace, + Loops, SE, DT) && + "SCEV normalization is not invertible!"); +#endif + break; + case Denormalize: + if (Loops.count(L)) + Result = cast(Result)->getPostIncExpr(SE); + break; + } + return Result; + } + + if (const SCEVNAryExpr *X = dyn_cast(S)) { + SmallVector Operands; + bool Changed = false; + // Transform each operand. + for (SCEVNAryExpr::op_iterator I = X->op_begin(), E = X->op_end(); + I != E; ++I) { + const SCEV *O = *I; + const SCEV *N = TransformForPostIncUse(Kind, O, User, OperandValToReplace, + Loops, SE, DT); + Changed |= N != O; + Operands.push_back(N); + } + // If any operand actually changed, return a transformed result. + if (Changed) + switch (S->getSCEVType()) { + case scAddExpr: return SE.getAddExpr(Operands); + case scMulExpr: return SE.getMulExpr(Operands); + case scSMaxExpr: return SE.getSMaxExpr(Operands); + case scUMaxExpr: return SE.getUMaxExpr(Operands); + default: llvm_unreachable("Unexpected SCEVNAryExpr kind!"); + } + return S; + } + + if (const SCEVUDivExpr *X = dyn_cast(S)) { + const SCEV *LO = X->getLHS(); + const SCEV *RO = X->getRHS(); + const SCEV *LN = TransformForPostIncUse(Kind, LO, User, OperandValToReplace, + Loops, SE, DT); + const SCEV *RN = TransformForPostIncUse(Kind, RO, User, OperandValToReplace, + Loops, SE, DT); + if (LO != LN || RO != RN) + return SE.getUDivExpr(LN, RN); + return S; + } + + llvm_unreachable("Unexpected SCEV kind!"); + return 0; +} diff --git a/final/lib/Analysis/SparsePropagation.cpp b/final/lib/Analysis/SparsePropagation.cpp new file mode 100644 index 00000000000..d8c207b4bd4 --- /dev/null +++ b/final/lib/Analysis/SparsePropagation.cpp @@ -0,0 +1,347 @@ +//===- SparsePropagation.cpp - Sparse Conditional Property Propagation ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an abstract sparse conditional propagation algorithm, +// modeled after SCCP, but with a customizable lattice function. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sparseprop" +#include "llvm/Analysis/SparsePropagation.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// AbstractLatticeFunction Implementation +//===----------------------------------------------------------------------===// + +AbstractLatticeFunction::~AbstractLatticeFunction() {} + +/// PrintValue - Render the specified lattice value to the specified stream. +void AbstractLatticeFunction::PrintValue(LatticeVal V, raw_ostream &OS) { + if (V == UndefVal) + OS << "undefined"; + else if (V == OverdefinedVal) + OS << "overdefined"; + else if (V == UntrackedVal) + OS << "untracked"; + else + OS << "unknown lattice value"; +} + +//===----------------------------------------------------------------------===// +// SparseSolver Implementation +//===----------------------------------------------------------------------===// + +/// getOrInitValueState - Return the LatticeVal object that corresponds to the +/// value, initializing the value's state if it hasn't been entered into the +/// map yet. This function is necessary because not all values should start +/// out in the underdefined state... Arguments should be overdefined, and +/// constants should be marked as constants. +/// +SparseSolver::LatticeVal SparseSolver::getOrInitValueState(Value *V) { + DenseMap::iterator I = ValueState.find(V); + if (I != ValueState.end()) return I->second; // Common case, in the map + + LatticeVal LV; + if (LatticeFunc->IsUntrackedValue(V)) + return LatticeFunc->getUntrackedVal(); + else if (Constant *C = dyn_cast(V)) + LV = LatticeFunc->ComputeConstant(C); + else if (Argument *A = dyn_cast(V)) + LV = LatticeFunc->ComputeArgument(A); + else if (!isa(V)) + // All other non-instructions are overdefined. + LV = LatticeFunc->getOverdefinedVal(); + else + // All instructions are underdefined by default. + LV = LatticeFunc->getUndefVal(); + + // If this value is untracked, don't add it to the map. + if (LV == LatticeFunc->getUntrackedVal()) + return LV; + return ValueState[V] = LV; +} + +/// UpdateState - When the state for some instruction is potentially updated, +/// this function notices and adds I to the worklist if needed. +void SparseSolver::UpdateState(Instruction &Inst, LatticeVal V) { + DenseMap::iterator I = ValueState.find(&Inst); + if (I != ValueState.end() && I->second == V) + return; // No change. + + // An update. Visit uses of I. + ValueState[&Inst] = V; + InstWorkList.push_back(&Inst); +} + +/// MarkBlockExecutable - This method can be used by clients to mark all of +/// the blocks that are known to be intrinsically live in the processed unit. +void SparseSolver::MarkBlockExecutable(BasicBlock *BB) { + DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n"); + BBExecutable.insert(BB); // Basic block is executable! + BBWorkList.push_back(BB); // Add the block to the work list! +} + +/// markEdgeExecutable - Mark a basic block as executable, adding it to the BB +/// work list if it is not already executable... +void SparseSolver::markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest) { + if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second) + return; // This edge is already known to be executable! + + DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName() + << " -> " << Dest->getName() << "\n"); + + if (BBExecutable.count(Dest)) { + // The destination is already executable, but we just made an edge + // feasible that wasn't before. Revisit the PHI nodes in the block + // because they have potentially new operands. + for (BasicBlock::iterator I = Dest->begin(); isa(I); ++I) + visitPHINode(*cast(I)); + + } else { + MarkBlockExecutable(Dest); + } +} + + +/// getFeasibleSuccessors - Return a vector of booleans to indicate which +/// successors are reachable from a given terminator instruction. +void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI, + SmallVectorImpl &Succs, + bool AggressiveUndef) { + Succs.resize(TI.getNumSuccessors()); + if (TI.getNumSuccessors() == 0) return; + + if (BranchInst *BI = dyn_cast(&TI)) { + if (BI->isUnconditional()) { + Succs[0] = true; + return; + } + + LatticeVal BCValue; + if (AggressiveUndef) + BCValue = getOrInitValueState(BI->getCondition()); + else + BCValue = getLatticeState(BI->getCondition()); + + if (BCValue == LatticeFunc->getOverdefinedVal() || + BCValue == LatticeFunc->getUntrackedVal()) { + // Overdefined condition variables can branch either way. + Succs[0] = Succs[1] = true; + return; + } + + // If undefined, neither is feasible yet. + if (BCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = LatticeFunc->GetConstant(BCValue, BI->getCondition(), *this); + if (C == 0 || !isa(C)) { + // Non-constant values can go either way. + Succs[0] = Succs[1] = true; + return; + } + + // Constant condition variables mean the branch can only go a single way + Succs[C->isNullValue()] = true; + return; + } + + if (isa(TI)) { + // Invoke instructions successors are always executable. + // TODO: Could ask the lattice function if the value can throw. + Succs[0] = Succs[1] = true; + return; + } + + if (isa(TI)) { + Succs.assign(Succs.size(), true); + return; + } + + SwitchInst &SI = cast(TI); + LatticeVal SCValue; + if (AggressiveUndef) + SCValue = getOrInitValueState(SI.getCondition()); + else + SCValue = getLatticeState(SI.getCondition()); + + if (SCValue == LatticeFunc->getOverdefinedVal() || + SCValue == LatticeFunc->getUntrackedVal()) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + // If undefined, neither is feasible yet. + if (SCValue == LatticeFunc->getUndefVal()) + return; + + Constant *C = LatticeFunc->GetConstant(SCValue, SI.getCondition(), *this); + if (C == 0 || !isa(C)) { + // All destinations are executable! + Succs.assign(TI.getNumSuccessors(), true); + return; + } + + Succs[SI.findCaseValue(cast(C))] = true; +} + + +/// isEdgeFeasible - Return true if the control flow edge from the 'From' +/// basic block to the 'To' basic block is currently feasible... +bool SparseSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To, + bool AggressiveUndef) { + SmallVector SuccFeasible; + TerminatorInst *TI = From->getTerminator(); + getFeasibleSuccessors(*TI, SuccFeasible, AggressiveUndef); + + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == To && SuccFeasible[i]) + return true; + + return false; +} + +void SparseSolver::visitTerminatorInst(TerminatorInst &TI) { + SmallVector SuccFeasible; + getFeasibleSuccessors(TI, SuccFeasible, true); + + BasicBlock *BB = TI.getParent(); + + // Mark all feasible successors executable... + for (unsigned i = 0, e = SuccFeasible.size(); i != e; ++i) + if (SuccFeasible[i]) + markEdgeExecutable(BB, TI.getSuccessor(i)); +} + +void SparseSolver::visitPHINode(PHINode &PN) { + // The lattice function may store more information on a PHINode than could be + // computed from its incoming values. For example, SSI form stores its sigma + // functions as PHINodes with a single incoming value. + if (LatticeFunc->IsSpecialCasedPHI(&PN)) { + LatticeVal IV = LatticeFunc->ComputeInstructionState(PN, *this); + if (IV != LatticeFunc->getUntrackedVal()) + UpdateState(PN, IV); + return; + } + + LatticeVal PNIV = getOrInitValueState(&PN); + LatticeVal Overdefined = LatticeFunc->getOverdefinedVal(); + + // If this value is already overdefined (common) just return. + if (PNIV == Overdefined || PNIV == LatticeFunc->getUntrackedVal()) + return; // Quick exit + + // Super-extra-high-degree PHI nodes are unlikely to ever be interesting, + // and slow us down a lot. Just mark them overdefined. + if (PN.getNumIncomingValues() > 64) { + UpdateState(PN, Overdefined); + return; + } + + // Look at all of the executable operands of the PHI node. If any of them + // are overdefined, the PHI becomes overdefined as well. Otherwise, ask the + // transfer function to give us the merge of the incoming values. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + // If the edge is not yet known to be feasible, it doesn't impact the PHI. + if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent(), true)) + continue; + + // Merge in this value. + LatticeVal OpVal = getOrInitValueState(PN.getIncomingValue(i)); + if (OpVal != PNIV) + PNIV = LatticeFunc->MergeValues(PNIV, OpVal); + + if (PNIV == Overdefined) + break; // Rest of input values don't matter. + } + + // Update the PHI with the compute value, which is the merge of the inputs. + UpdateState(PN, PNIV); +} + + +void SparseSolver::visitInst(Instruction &I) { + // PHIs are handled by the propagation logic, they are never passed into the + // transfer functions. + if (PHINode *PN = dyn_cast(&I)) + return visitPHINode(*PN); + + // Otherwise, ask the transfer function what the result is. If this is + // something that we care about, remember it. + LatticeVal IV = LatticeFunc->ComputeInstructionState(I, *this); + if (IV != LatticeFunc->getUntrackedVal()) + UpdateState(I, IV); + + if (TerminatorInst *TI = dyn_cast(&I)) + visitTerminatorInst(*TI); +} + +void SparseSolver::Solve(Function &F) { + MarkBlockExecutable(&F.getEntryBlock()); + + // Process the work lists until they are empty! + while (!BBWorkList.empty() || !InstWorkList.empty()) { + // Process the instruction work list. + while (!InstWorkList.empty()) { + Instruction *I = InstWorkList.back(); + InstWorkList.pop_back(); + + DEBUG(dbgs() << "\nPopped off I-WL: " << *I << "\n"); + + // "I" got into the work list because it made a transition. See if any + // users are both live and in need of updating. + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + Instruction *U = cast(*UI); + if (BBExecutable.count(U->getParent())) // Inst is executable? + visitInst(*U); + } + } + + // Process the basic block work list. + while (!BBWorkList.empty()) { + BasicBlock *BB = BBWorkList.back(); + BBWorkList.pop_back(); + + DEBUG(dbgs() << "\nPopped off BBWL: " << *BB); + + // Notify all instructions in this basic block that they are newly + // executable. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + visitInst(*I); + } + } +} + +void SparseSolver::Print(Function &F, raw_ostream &OS) const { + OS << "\nFUNCTION: " << F.getNameStr() << "\n"; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (!BBExecutable.count(BB)) + OS << "INFEASIBLE: "; + OS << "\t"; + if (BB->hasName()) + OS << BB->getNameStr() << ":\n"; + else + OS << "; anon bb\n"; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + LatticeFunc->PrintValue(getLatticeState(I), OS); + OS << *I << "\n"; + } + + OS << "\n"; + } +} + diff --git a/final/lib/Analysis/Trace.cpp b/final/lib/Analysis/Trace.cpp new file mode 100644 index 00000000000..68a39cd581f --- /dev/null +++ b/final/lib/Analysis/Trace.cpp @@ -0,0 +1,51 @@ +//===- Trace.cpp - Implementation of Trace class --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents a single trace of LLVM basic blocks. A trace is a +// single entry, multiple exit, region of code that is often hot. Trace-based +// optimizations treat traces almost like they are a large, strange, basic +// block: because the trace path is assumed to be hot, optimizations for the +// fall-through path are made at the expense of the non-fall-through paths. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Trace.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +Function *Trace::getFunction() const { + return getEntryBasicBlock()->getParent(); +} + +Module *Trace::getModule() const { + return getFunction()->getParent(); +} + +/// print - Write trace to output stream. +/// +void Trace::print(raw_ostream &O) const { + Function *F = getFunction(); + O << "; Trace from function " << F->getNameStr() << ", blocks:\n"; + for (const_iterator i = begin(), e = end(); i != e; ++i) { + O << "; "; + WriteAsOperand(O, *i, true, getModule()); + O << "\n"; + } + O << "; Trace parent function: \n" << *F; +} + +/// dump - Debugger convenience method; writes trace to standard error +/// output stream. +/// +void Trace::dump() const { + print(dbgs()); +} diff --git a/final/lib/Analysis/TypeBasedAliasAnalysis.cpp b/final/lib/Analysis/TypeBasedAliasAnalysis.cpp new file mode 100644 index 00000000000..40e18ab2fbf --- /dev/null +++ b/final/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -0,0 +1,299 @@ +//===- TypeBasedAliasAnalysis.cpp - Type-Based Alias Analysis -------------===// +// +// 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 TypeBasedAliasAnalysis pass, which implements +// metadata-based TBAA. +// +// In LLVM IR, memory does not have types, so LLVM's own type system is not +// suitable for doing TBAA. Instead, metadata is added to the IR to describe +// a type system of a higher level language. This can be used to implement +// typical C/C++ TBAA, but it can also be used to implement custom alias +// analysis behavior for other languages. +// +// The current metadata format is very simple. TBAA MDNodes have up to +// three fields, e.g.: +// !0 = metadata !{ metadata !"an example type tree" } +// !1 = metadata !{ metadata !"int", metadata !0 } +// !2 = metadata !{ metadata !"float", metadata !0 } +// !3 = metadata !{ metadata !"const float", metadata !2, i64 1 } +// +// The first field is an identity field. It can be any value, usually +// an MDString, which uniquely identifies the type. The most important +// name in the tree is the name of the root node. Two trees with +// different root node names are entirely disjoint, even if they +// have leaves with common names. +// +// The second field identifies the type's parent node in the tree, or +// is null or omitted for a root node. A type is considered to alias +// all of its decendents and all of its ancestors in the tree. Also, +// a type is considered to alias all types in other trees, so that +// bitcode produced from multiple front-ends is handled conservatively. +// +// If the third field is present, it's an integer which if equal to 1 +// indicates that the type is "constant" (meaning pointsToConstantMemory +// should return true; see +// http://llvm.org/docs/AliasAnalysis.html#OtherItfs). +// +// TODO: The current metadata format doesn't support struct +// fields. For example: +// struct X { +// double d; +// int i; +// }; +// void foo(struct X *x, struct X *y, double *p) { +// *x = *y; +// *p = 0.0; +// } +// Struct X has a double member, so the store to *x can alias the store to *p. +// Currently it's not possible to precisely describe all the things struct X +// aliases, so struct assignments must use conservative TBAA nodes. There's +// no scheme for attaching metadata to @llvm.memcpy yet either. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Metadata.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +// A handy option for disabling TBAA functionality. The same effect can also be +// achieved by stripping the !tbaa tags from IR, but this option is sometimes +// more convenient. +static cl::opt EnableTBAA("enable-tbaa", cl::init(true)); + +namespace { + /// TBAANode - This is a simple wrapper around an MDNode which provides a + /// higher-level interface by hiding the details of how alias analysis + /// information is encoded in its operands. + class TBAANode { + const MDNode *Node; + + public: + TBAANode() : Node(0) {} + explicit TBAANode(const MDNode *N) : Node(N) {} + + /// getNode - Get the MDNode for this TBAANode. + const MDNode *getNode() const { return Node; } + + /// getParent - Get this TBAANode's Alias tree parent. + TBAANode getParent() const { + if (Node->getNumOperands() < 2) + return TBAANode(); + MDNode *P = dyn_cast_or_null(Node->getOperand(1)); + if (!P) + return TBAANode(); + // Ok, this node has a valid parent. Return it. + return TBAANode(P); + } + + /// TypeIsImmutable - Test if this TBAANode represents a type for objects + /// which are not modified (by any means) in the context where this + /// AliasAnalysis is relevant. + bool TypeIsImmutable() const { + if (Node->getNumOperands() < 3) + return false; + ConstantInt *CI = dyn_cast(Node->getOperand(2)); + if (!CI) + return false; + return CI->getValue()[0]; + } + }; +} + +namespace { + /// TypeBasedAliasAnalysis - This is a simple alias analysis + /// implementation that uses TypeBased to answer queries. + class TypeBasedAliasAnalysis : public ImmutablePass, + public AliasAnalysis { + public: + static char ID; // Class identification, replacement for typeinfo + TypeBasedAliasAnalysis() : ImmutablePass(ID) { + initializeTypeBasedAliasAnalysisPass(*PassRegistry::getPassRegistry()); + } + + virtual void initializePass() { + InitializeAliasAnalysis(this); + } + + /// getAdjustedAnalysisPointer - This method is used when a pass implements + /// an analysis interface through multiple inheritance. If needed, it + /// should override this to adjust the this pointer as needed for the + /// specified pass info. + virtual void *getAdjustedAnalysisPointer(const void *PI) { + if (PI == &AliasAnalysis::ID) + return (AliasAnalysis*)this; + return this; + } + + bool Aliases(const MDNode *A, const MDNode *B) const; + + private: + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual AliasResult alias(const Location &LocA, const Location &LocB); + virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal); + virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); + virtual ModRefBehavior getModRefBehavior(const Function *F); + virtual ModRefResult getModRefInfo(ImmutableCallSite CS, + const Location &Loc); + virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2); + }; +} // End of anonymous namespace + +// Register this pass... +char TypeBasedAliasAnalysis::ID = 0; +INITIALIZE_AG_PASS(TypeBasedAliasAnalysis, AliasAnalysis, "tbaa", + "Type-Based Alias Analysis", false, true, false) + +ImmutablePass *llvm::createTypeBasedAliasAnalysisPass() { + return new TypeBasedAliasAnalysis(); +} + +void +TypeBasedAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AliasAnalysis::getAnalysisUsage(AU); +} + +/// Aliases - Test whether the type represented by A may alias the +/// type represented by B. +bool +TypeBasedAliasAnalysis::Aliases(const MDNode *A, + const MDNode *B) const { + // Keep track of the root node for A and B. + TBAANode RootA, RootB; + + // Climb the tree from A to see if we reach B. + for (TBAANode T(A); ; ) { + if (T.getNode() == B) + // B is an ancestor of A. + return true; + + RootA = T; + T = T.getParent(); + if (!T.getNode()) + break; + } + + // Climb the tree from B to see if we reach A. + for (TBAANode T(B); ; ) { + if (T.getNode() == A) + // A is an ancestor of B. + return true; + + RootB = T; + T = T.getParent(); + if (!T.getNode()) + break; + } + + // Neither node is an ancestor of the other. + + // If they have different roots, they're part of different potentially + // unrelated type systems, so we must be conservative. + if (RootA.getNode() != RootB.getNode()) + return true; + + // If they have the same root, then we've proved there's no alias. + return false; +} + +AliasAnalysis::AliasResult +TypeBasedAliasAnalysis::alias(const Location &LocA, + const Location &LocB) { + if (!EnableTBAA) + return AliasAnalysis::alias(LocA, LocB); + + // Get the attached MDNodes. If either value lacks a tbaa MDNode, we must + // be conservative. + const MDNode *AM = LocA.TBAATag; + if (!AM) return AliasAnalysis::alias(LocA, LocB); + const MDNode *BM = LocB.TBAATag; + if (!BM) return AliasAnalysis::alias(LocA, LocB); + + // If they may alias, chain to the next AliasAnalysis. + if (Aliases(AM, BM)) + return AliasAnalysis::alias(LocA, LocB); + + // Otherwise return a definitive result. + return NoAlias; +} + +bool TypeBasedAliasAnalysis::pointsToConstantMemory(const Location &Loc, + bool OrLocal) { + if (!EnableTBAA) + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + + const MDNode *M = Loc.TBAATag; + if (!M) return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); + + // If this is an "immutable" type, we can assume the pointer is pointing + // to constant memory. + if (TBAANode(M).TypeIsImmutable()) + return true; + + return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal); +} + +AliasAnalysis::ModRefBehavior +TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) { + if (!EnableTBAA) + return AliasAnalysis::getModRefBehavior(CS); + + ModRefBehavior Min = UnknownModRefBehavior; + + // If this is an "immutable" type, we can assume the call doesn't write + // to memory. + if (const MDNode *M = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) + if (TBAANode(M).TypeIsImmutable()) + Min = OnlyReadsMemory; + + return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min); +} + +AliasAnalysis::ModRefBehavior +TypeBasedAliasAnalysis::getModRefBehavior(const Function *F) { + // Functions don't have metadata. Just chain to the next implementation. + return AliasAnalysis::getModRefBehavior(F); +} + +AliasAnalysis::ModRefResult +TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS, + const Location &Loc) { + if (!EnableTBAA) + return AliasAnalysis::getModRefInfo(CS, Loc); + + if (const MDNode *L = Loc.TBAATag) + if (const MDNode *M = + CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) + if (!Aliases(L, M)) + return NoModRef; + + return AliasAnalysis::getModRefInfo(CS, Loc); +} + +AliasAnalysis::ModRefResult +TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) { + if (!EnableTBAA) + return AliasAnalysis::getModRefInfo(CS1, CS2); + + if (const MDNode *M1 = + CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) + if (const MDNode *M2 = + CS2.getInstruction()->getMetadata(LLVMContext::MD_tbaa)) + if (!Aliases(M1, M2)) + return NoModRef; + + return AliasAnalysis::getModRefInfo(CS1, CS2); +} diff --git a/final/lib/Analysis/ValueTracking.cpp b/final/lib/Analysis/ValueTracking.cpp new file mode 100644 index 00000000000..231b95b618f --- /dev/null +++ b/final/lib/Analysis/ValueTracking.cpp @@ -0,0 +1,1743 @@ +//===- ValueTracking.cpp - Walk computations to compute properties --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines that help analyze properties that chains of +// computations have. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Operator.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/PatternMatch.h" +#include "llvm/ADT/SmallPtrSet.h" +#include +using namespace llvm; +using namespace llvm::PatternMatch; + +const unsigned MaxDepth = 6; + +/// getBitWidth - Returns the bitwidth of the given scalar or pointer type (if +/// unknown returns 0). For vector types, returns the element type's bitwidth. +static unsigned getBitWidth(const Type *Ty, const TargetData *TD) { + if (unsigned BitWidth = Ty->getScalarSizeInBits()) + return BitWidth; + assert(isa(Ty) && "Expected a pointer type!"); + return TD ? TD->getPointerSizeInBits() : 0; +} + +/// ComputeMaskedBits - Determine which of the bits specified in Mask are +/// known to be either zero or one and return them in the KnownZero/KnownOne +/// bit sets. This code only analyzes bits in Mask, in order to short-circuit +/// processing. +/// NOTE: we cannot consider 'undef' to be "IsZero" here. The problem is that +/// we cannot optimize based on the assumption that it is zero without changing +/// it to be an explicit zero. If we don't change it to zero, other code could +/// optimized based on the contradictory assumption that it is non-zero. +/// Because instcombine aggressively folds operations with undef args anyway, +/// this won't lose us code quality. +/// +/// This function is defined on values with integer type, values with pointer +/// type (but only if TD is non-null), and vectors of integers. In the case +/// where V is a vector, the mask, known zero, and known one values are the +/// same width as the vector element, and the bit is set only if it is true +/// for all of the elements in the vector. +void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, + APInt &KnownZero, APInt &KnownOne, + const TargetData *TD, unsigned Depth) { + assert(V && "No Value?"); + assert(Depth <= MaxDepth && "Limit Search Depth"); + unsigned BitWidth = Mask.getBitWidth(); + assert((V->getType()->isIntOrIntVectorTy() || V->getType()->isPointerTy()) + && "Not integer or pointer type!"); + assert((!TD || + TD->getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) && + (!V->getType()->isIntOrIntVectorTy() || + V->getType()->getScalarSizeInBits() == BitWidth) && + KnownZero.getBitWidth() == BitWidth && + KnownOne.getBitWidth() == BitWidth && + "V, Mask, KnownOne and KnownZero should have same BitWidth"); + + if (ConstantInt *CI = dyn_cast(V)) { + // We know all of the bits for a constant! + KnownOne = CI->getValue() & Mask; + KnownZero = ~KnownOne & Mask; + return; + } + // Null and aggregate-zero are all-zeros. + if (isa(V) || + isa(V)) { + KnownOne.clearAllBits(); + KnownZero = Mask; + return; + } + // Handle a constant vector by taking the intersection of the known bits of + // each element. + if (ConstantVector *CV = dyn_cast(V)) { + KnownZero.setAllBits(); KnownOne.setAllBits(); + for (unsigned i = 0, e = CV->getNumOperands(); i != e; ++i) { + APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0); + ComputeMaskedBits(CV->getOperand(i), Mask, KnownZero2, KnownOne2, + TD, Depth); + KnownZero &= KnownZero2; + KnownOne &= KnownOne2; + } + return; + } + // The address of an aligned GlobalValue has trailing zeros. + if (GlobalValue *GV = dyn_cast(V)) { + unsigned Align = GV->getAlignment(); + if (Align == 0 && TD && GV->getType()->getElementType()->isSized()) { + const Type *ObjectType = GV->getType()->getElementType(); + // If the object is defined in the current Module, we'll be giving + // it the preferred alignment. Otherwise, we have to assume that it + // may only have the minimum ABI alignment. + if (!GV->isDeclaration() && !GV->mayBeOverridden()) + Align = TD->getPrefTypeAlignment(ObjectType); + else + Align = TD->getABITypeAlignment(ObjectType); + } + if (Align > 0) + KnownZero = Mask & APInt::getLowBitsSet(BitWidth, + CountTrailingZeros_32(Align)); + else + KnownZero.clearAllBits(); + KnownOne.clearAllBits(); + return; + } + // A weak GlobalAlias is totally unknown. A non-weak GlobalAlias has + // the bits of its aliasee. + if (GlobalAlias *GA = dyn_cast(V)) { + if (GA->mayBeOverridden()) { + KnownZero.clearAllBits(); KnownOne.clearAllBits(); + } else { + ComputeMaskedBits(GA->getAliasee(), Mask, KnownZero, KnownOne, + TD, Depth+1); + } + return; + } + + KnownZero.clearAllBits(); KnownOne.clearAllBits(); // Start out not knowing anything. + + if (Depth == MaxDepth || Mask == 0) + return; // Limit search depth. + + Operator *I = dyn_cast(V); + if (!I) return; + + APInt KnownZero2(KnownZero), KnownOne2(KnownOne); + switch (I->getOpcode()) { + default: break; + case Instruction::And: { + // If either the LHS or the RHS are Zero, the result is zero. + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + APInt Mask2(Mask & ~KnownZero); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + return; + } + case Instruction::Or: { + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + APInt Mask2(Mask & ~KnownOne); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + return; + } + case Instruction::Xor: { + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero, KnownOne, TD, Depth+1); + ComputeMaskedBits(I->getOperand(0), Mask, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + APInt KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + KnownZero = KnownZeroOut; + return; + } + case Instruction::Mul: { + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(1), Mask2, KnownZero, KnownOne, TD,Depth+1); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If low bits are zero in either operand, output low known-0 bits. + // Also compute a conserative estimate for high known-0 bits. + // More trickiness is possible, but this is sufficient for the + // interesting case of alignment computation. + KnownOne.clearAllBits(); + unsigned TrailZ = KnownZero.countTrailingOnes() + + KnownZero2.countTrailingOnes(); + unsigned LeadZ = std::max(KnownZero.countLeadingOnes() + + KnownZero2.countLeadingOnes(), + BitWidth) - BitWidth; + + TrailZ = std::min(TrailZ, BitWidth); + LeadZ = std::min(LeadZ, BitWidth); + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) | + APInt::getHighBitsSet(BitWidth, LeadZ); + KnownZero &= Mask; + return; + } + case Instruction::UDiv: { + // For the purposes of computing leading zeros we can conservatively + // treat a udiv as a logical right shift by the power of 2 known to + // be less than the denominator. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(0), + AllOnes, KnownZero2, KnownOne2, TD, Depth+1); + unsigned LeadZ = KnownZero2.countLeadingOnes(); + + KnownOne2.clearAllBits(); + KnownZero2.clearAllBits(); + ComputeMaskedBits(I->getOperand(1), + AllOnes, KnownZero2, KnownOne2, TD, Depth+1); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); + + KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; + return; + } + case Instruction::Select: + ComputeMaskedBits(I->getOperand(2), Mask, KnownZero, KnownOne, TD, Depth+1); + ComputeMaskedBits(I->getOperand(1), Mask, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::SIToFP: + case Instruction::UIToFP: + return; // Can't work with floating point. + case Instruction::PtrToInt: + case Instruction::IntToPtr: + // We can't handle these if we don't know the pointer size. + if (!TD) return; + // FALL THROUGH and handle them the same as zext/trunc. + case Instruction::ZExt: + case Instruction::Trunc: { + const Type *SrcTy = I->getOperand(0)->getType(); + + unsigned SrcBitWidth; + // Note that we handle pointer operands here because of inttoptr/ptrtoint + // which fall through here. + if (SrcTy->isPointerTy()) + SrcBitWidth = TD->getTypeSizeInBits(SrcTy); + else + SrcBitWidth = SrcTy->getScalarSizeInBits(); + + APInt MaskIn = Mask.zextOrTrunc(SrcBitWidth); + KnownZero = KnownZero.zextOrTrunc(SrcBitWidth); + KnownOne = KnownOne.zextOrTrunc(SrcBitWidth); + ComputeMaskedBits(I->getOperand(0), MaskIn, KnownZero, KnownOne, TD, + Depth+1); + KnownZero = KnownZero.zextOrTrunc(BitWidth); + KnownOne = KnownOne.zextOrTrunc(BitWidth); + // Any top bits are known to be zero. + if (BitWidth > SrcBitWidth) + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + return; + } + case Instruction::BitCast: { + const Type *SrcTy = I->getOperand(0)->getType(); + if ((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + // TODO: For now, not handling conversions like: + // (bitcast i64 %x to <2 x i32>) + !I->getType()->isVectorTy()) { + ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, TD, + Depth+1); + return; + } + break; + } + case Instruction::SExt: { + // Compute the bits in the result that are not present in the input. + unsigned SrcBitWidth = I->getOperand(0)->getType()->getScalarSizeInBits(); + + APInt MaskIn = Mask.trunc(SrcBitWidth); + KnownZero = KnownZero.trunc(SrcBitWidth); + KnownOne = KnownOne.trunc(SrcBitWidth); + ComputeMaskedBits(I->getOperand(0), MaskIn, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + if (KnownZero[SrcBitWidth-1]) // Input sign bit known zero + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + else if (KnownOne[SrcBitWidth-1]) // Input sign bit known set + KnownOne |= APInt::getHighBitsSet(BitWidth, BitWidth - SrcBitWidth); + return; + } + case Instruction::Shl: + // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + APInt Mask2(Mask.lshr(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero <<= ShiftAmt; + KnownOne <<= ShiftAmt; + KnownZero |= APInt::getLowBitsSet(BitWidth, ShiftAmt); // low bits known 0 + return; + } + break; + case Instruction::LShr: + // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + // Compute the new bits that are at the top now. + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth); + + // Unsigned shift right. + APInt Mask2(Mask.shl(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero,KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = APIntOps::lshr(KnownZero, ShiftAmt); + KnownOne = APIntOps::lshr(KnownOne, ShiftAmt); + // high bits known zero. + KnownZero |= APInt::getHighBitsSet(BitWidth, ShiftAmt); + return; + } + break; + case Instruction::AShr: + // (ashr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { + // Compute the new bits that are at the top now. + uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1); + + // Signed shift right. + APInt Mask2(Mask.shl(ShiftAmt)); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = APIntOps::lshr(KnownZero, ShiftAmt); + KnownOne = APIntOps::lshr(KnownOne, ShiftAmt); + + APInt HighBits(APInt::getHighBitsSet(BitWidth, ShiftAmt)); + if (KnownZero[BitWidth-ShiftAmt-1]) // New bits are known zero. + KnownZero |= HighBits; + else if (KnownOne[BitWidth-ShiftAmt-1]) // New bits are known one. + KnownOne |= HighBits; + return; + } + break; + case Instruction::Sub: { + if (ConstantInt *CLHS = dyn_cast(I->getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + if (!CLHS->getValue().isNegative()) { + unsigned NLZ = (CLHS->getValue()+1).countLeadingZeros(); + // NLZ can't be BitWidth with no sign bit + APInt MaskV = APInt::getHighBitsSet(BitWidth, NLZ+1); + ComputeMaskedBits(I->getOperand(1), MaskV, KnownZero2, KnownOne2, + TD, Depth+1); + + // If all of the MaskV bits are known to be zero, then we know the + // output top bits are zero, because we now know that the output is + // from [0-C]. + if ((KnownZero2 & MaskV) == MaskV) { + unsigned NLZ2 = CLHS->getValue().countLeadingZeros(); + // Top bits known zero. + KnownZero = APInt::getHighBitsSet(BitWidth, NLZ2) & Mask; + } + } + } + } + // fall through + case Instruction::Add: { + // If one of the operands has trailing zeros, then the bits that the + // other operand has in those bit positions will be preserved in the + // result. For an add, this works with either operand. For a subtract, + // this only works if the known zeros are in the right operand. + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + APInt Mask2 = APInt::getLowBitsSet(BitWidth, + BitWidth - Mask.countLeadingZeros()); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, TD, + Depth+1); + assert((LHSKnownZero & LHSKnownOne) == 0 && + "Bits known to be one AND zero?"); + unsigned LHSKnownZeroOut = LHSKnownZero.countTrailingOnes(); + + ComputeMaskedBits(I->getOperand(1), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + unsigned RHSKnownZeroOut = KnownZero2.countTrailingOnes(); + + // Determine which operand has more trailing zeros, and use that + // many bits from the other operand. + if (LHSKnownZeroOut > RHSKnownZeroOut) { + if (I->getOpcode() == Instruction::Add) { + APInt Mask = APInt::getLowBitsSet(BitWidth, LHSKnownZeroOut); + KnownZero |= KnownZero2 & Mask; + KnownOne |= KnownOne2 & Mask; + } else { + // If the known zeros are in the left operand for a subtract, + // fall back to the minimum known zeros in both operands. + KnownZero |= APInt::getLowBitsSet(BitWidth, + std::min(LHSKnownZeroOut, + RHSKnownZeroOut)); + } + } else if (RHSKnownZeroOut >= LHSKnownZeroOut) { + APInt Mask = APInt::getLowBitsSet(BitWidth, RHSKnownZeroOut); + KnownZero |= LHSKnownZero & Mask; + KnownOne |= LHSKnownOne & Mask; + } + return; + } + case Instruction::SRem: + if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + APInt RA = Rem->getValue().abs(); + if (RA.isPowerOf2()) { + APInt LowBits = RA - 1; + APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero2, KnownOne2, TD, + Depth+1); + + // The low bits of the first operand are unchanged by the srem. + KnownZero = KnownZero2 & LowBits; + KnownOne = KnownOne2 & LowBits; + + // If the first operand is non-negative or has all low bits zero, then + // the upper bits are all zero. + if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits)) + KnownZero |= ~LowBits; + + // If the first operand is negative and not all low bits are zero, then + // the upper bits are all one. + if (KnownOne2[BitWidth-1] && ((KnownOne2 & LowBits) != 0)) + KnownOne |= ~LowBits; + + KnownZero &= Mask; + KnownOne &= Mask; + + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + } + } + + // The sign bit is the LHS's sign bit, except when the result of the + // remainder is zero. + if (Mask.isNegative() && KnownZero.isNonNegative()) { + APInt Mask2 = APInt::getSignBit(BitWidth); + APInt LHSKnownZero(BitWidth, 0), LHSKnownOne(BitWidth, 0); + ComputeMaskedBits(I->getOperand(0), Mask2, LHSKnownZero, LHSKnownOne, TD, + Depth+1); + // If it's known zero, our sign bit is also zero. + if (LHSKnownZero.isNegative()) + KnownZero |= LHSKnownZero; + } + + break; + case Instruction::URem: { + if (ConstantInt *Rem = dyn_cast(I->getOperand(1))) { + APInt RA = Rem->getValue(); + if (RA.isPowerOf2()) { + APInt LowBits = (RA - 1); + APInt Mask2 = LowBits & Mask; + KnownZero |= ~LowBits & Mask; + ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne, TD, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + break; + } + } + + // Since the result is less than or equal to either operand, any leading + // zero bits in either operand must also exist in the result. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(I->getOperand(0), AllOnes, KnownZero, KnownOne, + TD, Depth+1); + ComputeMaskedBits(I->getOperand(1), AllOnes, KnownZero2, KnownOne2, + TD, Depth+1); + + unsigned Leaders = std::max(KnownZero.countLeadingOnes(), + KnownZero2.countLeadingOnes()); + KnownOne.clearAllBits(); + KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & Mask; + break; + } + + case Instruction::Alloca: { + AllocaInst *AI = cast(V); + unsigned Align = AI->getAlignment(); + if (Align == 0 && TD) + Align = TD->getABITypeAlignment(AI->getType()->getElementType()); + + if (Align > 0) + KnownZero = Mask & APInt::getLowBitsSet(BitWidth, + CountTrailingZeros_32(Align)); + break; + } + case Instruction::GetElementPtr: { + // Analyze all of the subscripts of this getelementptr instruction + // to determine if we can prove known low zero bits. + APInt LocalMask = APInt::getAllOnesValue(BitWidth); + APInt LocalKnownZero(BitWidth, 0), LocalKnownOne(BitWidth, 0); + ComputeMaskedBits(I->getOperand(0), LocalMask, + LocalKnownZero, LocalKnownOne, TD, Depth+1); + unsigned TrailZ = LocalKnownZero.countTrailingOnes(); + + gep_type_iterator GTI = gep_type_begin(I); + for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i, ++GTI) { + Value *Index = I->getOperand(i); + if (const StructType *STy = dyn_cast(*GTI)) { + // Handle struct member offset arithmetic. + if (!TD) return; + const StructLayout *SL = TD->getStructLayout(STy); + unsigned Idx = cast(Index)->getZExtValue(); + uint64_t Offset = SL->getElementOffset(Idx); + TrailZ = std::min(TrailZ, + CountTrailingZeros_64(Offset)); + } else { + // Handle array index arithmetic. + const Type *IndexedTy = GTI.getIndexedType(); + if (!IndexedTy->isSized()) return; + unsigned GEPOpiBits = Index->getType()->getScalarSizeInBits(); + uint64_t TypeSize = TD ? TD->getTypeAllocSize(IndexedTy) : 1; + LocalMask = APInt::getAllOnesValue(GEPOpiBits); + LocalKnownZero = LocalKnownOne = APInt(GEPOpiBits, 0); + ComputeMaskedBits(Index, LocalMask, + LocalKnownZero, LocalKnownOne, TD, Depth+1); + TrailZ = std::min(TrailZ, + unsigned(CountTrailingZeros_64(TypeSize) + + LocalKnownZero.countTrailingOnes())); + } + } + + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) & Mask; + break; + } + case Instruction::PHI: { + PHINode *P = cast(I); + // Handle the case of a simple two-predecessor recurrence PHI. + // There's a lot more that could theoretically be done here, but + // this is sufficient to catch some interesting cases. + if (P->getNumIncomingValues() == 2) { + for (unsigned i = 0; i != 2; ++i) { + Value *L = P->getIncomingValue(i); + Value *R = P->getIncomingValue(!i); + Operator *LU = dyn_cast(L); + if (!LU) + continue; + unsigned Opcode = LU->getOpcode(); + // Check for operations that have the property that if + // both their operands have low zero bits, the result + // will have low zero bits. + if (Opcode == Instruction::Add || + Opcode == Instruction::Sub || + Opcode == Instruction::And || + Opcode == Instruction::Or || + Opcode == Instruction::Mul) { + Value *LL = LU->getOperand(0); + Value *LR = LU->getOperand(1); + // Find a recurrence. + if (LL == I) + L = LR; + else if (LR == I) + L = LL; + else + break; + // Ok, we have a PHI of the form L op= R. Check for low + // zero bits. + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(R, Mask2, KnownZero2, KnownOne2, TD, Depth+1); + Mask2 = APInt::getLowBitsSet(BitWidth, + KnownZero2.countTrailingOnes()); + + // We need to take the minimum number of known bits + APInt KnownZero3(KnownZero), KnownOne3(KnownOne); + ComputeMaskedBits(L, Mask2, KnownZero3, KnownOne3, TD, Depth+1); + + KnownZero = Mask & + APInt::getLowBitsSet(BitWidth, + std::min(KnownZero2.countTrailingOnes(), + KnownZero3.countTrailingOnes())); + break; + } + } + } + + // Unreachable blocks may have zero-operand PHI nodes. + if (P->getNumIncomingValues() == 0) + return; + + // Otherwise take the unions of the known bit sets of the operands, + // taking conservative care to avoid excessive recursion. + if (Depth < MaxDepth - 1 && !KnownZero && !KnownOne) { + KnownZero = APInt::getAllOnesValue(BitWidth); + KnownOne = APInt::getAllOnesValue(BitWidth); + for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) { + // Skip direct self references. + if (P->getIncomingValue(i) == P) continue; + + KnownZero2 = APInt(BitWidth, 0); + KnownOne2 = APInt(BitWidth, 0); + // Recurse, but cap the recursion to one level, because we don't + // want to waste time spinning around in loops. + ComputeMaskedBits(P->getIncomingValue(i), KnownZero | KnownOne, + KnownZero2, KnownOne2, TD, MaxDepth-1); + KnownZero &= KnownZero2; + KnownOne &= KnownOne2; + // If all bits have been ruled out, there's no need to check + // more operands. + if (!KnownZero && !KnownOne) + break; + } + } + break; + } + case Instruction::Call: + if (IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::ctpop: + case Intrinsic::ctlz: + case Intrinsic::cttz: { + unsigned LowBits = Log2_32(BitWidth)+1; + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); + break; + } + } + } + break; + } +} + +/// ComputeSignBit - Determine whether the sign bit is known to be zero or +/// one. Convenience wrapper around ComputeMaskedBits. +void llvm::ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, + const TargetData *TD, unsigned Depth) { + unsigned BitWidth = getBitWidth(V->getType(), TD); + if (!BitWidth) { + KnownZero = false; + KnownOne = false; + return; + } + APInt ZeroBits(BitWidth, 0); + APInt OneBits(BitWidth, 0); + ComputeMaskedBits(V, APInt::getSignBit(BitWidth), ZeroBits, OneBits, TD, + Depth); + KnownOne = OneBits[BitWidth - 1]; + KnownZero = ZeroBits[BitWidth - 1]; +} + +/// isPowerOfTwo - Return true if the given value is known to have exactly one +/// bit set when defined. For vectors return true if every element is known to +/// be a power of two when defined. Supports values with integer or pointer +/// types and vectors of integers. +bool llvm::isPowerOfTwo(Value *V, const TargetData *TD, unsigned Depth) { + if (ConstantInt *CI = dyn_cast(V)) + return CI->getValue().isPowerOf2(); + // TODO: Handle vector constants. + + // 1 << X is clearly a power of two if the one is not shifted off the end. If + // it is shifted off the end then the result is undefined. + if (match(V, m_Shl(m_One(), m_Value()))) + return true; + + // (signbit) >>l X is clearly a power of two if the one is not shifted off the + // bottom. If it is shifted off the bottom then the result is undefined. + if (match(V, m_LShr(m_SignBit(), m_Value()))) + return true; + + // The remaining tests are all recursive, so bail out if we hit the limit. + if (Depth++ == MaxDepth) + return false; + + if (ZExtInst *ZI = dyn_cast(V)) + return isPowerOfTwo(ZI->getOperand(0), TD, Depth); + + if (SelectInst *SI = dyn_cast(V)) + return isPowerOfTwo(SI->getTrueValue(), TD, Depth) && + isPowerOfTwo(SI->getFalseValue(), TD, Depth); + + // An exact divide or right shift can only shift off zero bits, so the result + // is a power of two only if the first operand is a power of two. + if (match(V, m_Shr(m_Value(), m_Value())) || + match(V, m_IDiv(m_Value(), m_Value()))) { + BinaryOperator *BO = cast(V); + if (BO->isExact()) + return isPowerOfTwo(BO->getOperand(0), TD, Depth); + } + + return false; +} + +/// isKnownNonZero - Return true if the given value is known to be non-zero +/// when defined. For vectors return true if every element is known to be +/// non-zero when defined. Supports values with integer or pointer type and +/// vectors of integers. +bool llvm::isKnownNonZero(Value *V, const TargetData *TD, unsigned Depth) { + if (Constant *C = dyn_cast(V)) { + if (C->isNullValue()) + return false; + if (isa(C)) + // Must be non-zero due to null test above. + return true; + // TODO: Handle vectors + return false; + } + + // The remaining tests are all recursive, so bail out if we hit the limit. + if (Depth++ == MaxDepth) + return false; + + unsigned BitWidth = getBitWidth(V->getType(), TD); + + // X | Y != 0 if X != 0 or Y != 0. + Value *X = 0, *Y = 0; + if (match(V, m_Or(m_Value(X), m_Value(Y)))) + return isKnownNonZero(X, TD, Depth) || isKnownNonZero(Y, TD, Depth); + + // ext X != 0 if X != 0. + if (isa(V) || isa(V)) + return isKnownNonZero(cast(V)->getOperand(0), TD, Depth); + + // shl X, Y != 0 if X is odd. Note that the value of the shift is undefined + // if the lowest bit is shifted off the end. + if (BitWidth && match(V, m_Shl(m_Value(X), m_Value(Y)))) { + // shl nuw can't remove any non-zero bits. + BinaryOperator *BO = cast(V); + if (BO->hasNoUnsignedWrap()) + return isKnownNonZero(X, TD, Depth); + + APInt KnownZero(BitWidth, 0); + APInt KnownOne(BitWidth, 0); + ComputeMaskedBits(X, APInt(BitWidth, 1), KnownZero, KnownOne, TD, Depth); + if (KnownOne[0]) + return true; + } + // shr X, Y != 0 if X is negative. Note that the value of the shift is not + // defined if the sign bit is shifted off the end. + else if (match(V, m_Shr(m_Value(X), m_Value(Y)))) { + // shr exact can only shift out zero bits. + BinaryOperator *BO = cast(V); + if (BO->isExact()) + return isKnownNonZero(X, TD, Depth); + + bool XKnownNonNegative, XKnownNegative; + ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth); + if (XKnownNegative) + return true; + } + // div exact can only produce a zero if the dividend is zero. + else if (match(V, m_IDiv(m_Value(X), m_Value()))) { + BinaryOperator *BO = cast(V); + if (BO->isExact()) + return isKnownNonZero(X, TD, Depth); + } + // X + Y. + else if (match(V, m_Add(m_Value(X), m_Value(Y)))) { + bool XKnownNonNegative, XKnownNegative; + bool YKnownNonNegative, YKnownNegative; + ComputeSignBit(X, XKnownNonNegative, XKnownNegative, TD, Depth); + ComputeSignBit(Y, YKnownNonNegative, YKnownNegative, TD, Depth); + + // If X and Y are both non-negative (as signed values) then their sum is not + // zero unless both X and Y are zero. + if (XKnownNonNegative && YKnownNonNegative) + if (isKnownNonZero(X, TD, Depth) || isKnownNonZero(Y, TD, Depth)) + return true; + + // If X and Y are both negative (as signed values) then their sum is not + // zero unless both X and Y equal INT_MIN. + if (BitWidth && XKnownNegative && YKnownNegative) { + APInt KnownZero(BitWidth, 0); + APInt KnownOne(BitWidth, 0); + APInt Mask = APInt::getSignedMaxValue(BitWidth); + // The sign bit of X is set. If some other bit is set then X is not equal + // to INT_MIN. + ComputeMaskedBits(X, Mask, KnownZero, KnownOne, TD, Depth); + if ((KnownOne & Mask) != 0) + return true; + // The sign bit of Y is set. If some other bit is set then Y is not equal + // to INT_MIN. + ComputeMaskedBits(Y, Mask, KnownZero, KnownOne, TD, Depth); + if ((KnownOne & Mask) != 0) + return true; + } + + // The sum of a non-negative number and a power of two is not zero. + if (XKnownNonNegative && isPowerOfTwo(Y, TD, Depth)) + return true; + if (YKnownNonNegative && isPowerOfTwo(X, TD, Depth)) + return true; + } + // (C ? X : Y) != 0 if X != 0 and Y != 0. + else if (SelectInst *SI = dyn_cast(V)) { + if (isKnownNonZero(SI->getTrueValue(), TD, Depth) && + isKnownNonZero(SI->getFalseValue(), TD, Depth)) + return true; + } + + if (!BitWidth) return false; + APInt KnownZero(BitWidth, 0); + APInt KnownOne(BitWidth, 0); + ComputeMaskedBits(V, APInt::getAllOnesValue(BitWidth), KnownZero, KnownOne, + TD, Depth); + return KnownOne != 0; +} + +/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use +/// this predicate to simplify operations downstream. Mask is known to be zero +/// for bits that V cannot have. +/// +/// This function is defined on values with integer type, values with pointer +/// type (but only if TD is non-null), and vectors of integers. In the case +/// where V is a vector, the mask, known zero, and known one values are the +/// same width as the vector element, and the bit is set only if it is true +/// for all of the elements in the vector. +bool llvm::MaskedValueIsZero(Value *V, const APInt &Mask, + const TargetData *TD, unsigned Depth) { + APInt KnownZero(Mask.getBitWidth(), 0), KnownOne(Mask.getBitWidth(), 0); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD, Depth); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + return (KnownZero & Mask) == Mask; +} + + + +/// ComputeNumSignBits - Return the number of times the sign bit of the +/// register is replicated into the other bits. We know that at least 1 bit +/// is always equal to the sign bit (itself), but other cases can give us +/// information. For example, immediately after an "ashr X, 2", we know that +/// the top 3 bits are all equal to each other, so we return 3. +/// +/// 'Op' must have a scalar integer type. +/// +unsigned llvm::ComputeNumSignBits(Value *V, const TargetData *TD, + unsigned Depth) { + assert((TD || V->getType()->isIntOrIntVectorTy()) && + "ComputeNumSignBits requires a TargetData object to operate " + "on non-integer values!"); + const Type *Ty = V->getType(); + unsigned TyBits = TD ? TD->getTypeSizeInBits(V->getType()->getScalarType()) : + Ty->getScalarSizeInBits(); + unsigned Tmp, Tmp2; + unsigned FirstAnswer = 1; + + // Note that ConstantInt is handled by the general ComputeMaskedBits case + // below. + + if (Depth == 6) + return 1; // Limit search depth. + + Operator *U = dyn_cast(V); + switch (Operator::getOpcode(V)) { + default: break; + case Instruction::SExt: + Tmp = TyBits - U->getOperand(0)->getType()->getScalarSizeInBits(); + return ComputeNumSignBits(U->getOperand(0), TD, Depth+1) + Tmp; + + case Instruction::AShr: + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + // ashr X, C -> adds C sign bits. + if (ConstantInt *C = dyn_cast(U->getOperand(1))) { + Tmp += C->getZExtValue(); + if (Tmp > TyBits) Tmp = TyBits; + } + // vector ashr X, -> adds C sign bits + if (ConstantVector *C = dyn_cast(U->getOperand(1))) { + if (ConstantInt *CI = dyn_cast_or_null(C->getSplatValue())) { + Tmp += CI->getZExtValue(); + if (Tmp > TyBits) Tmp = TyBits; + } + } + return Tmp; + case Instruction::Shl: + if (ConstantInt *C = dyn_cast(U->getOperand(1))) { + // shl destroys sign bits. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (C->getZExtValue() >= TyBits || // Bad shift. + C->getZExtValue() >= Tmp) break; // Shifted all sign bits out. + return Tmp - C->getZExtValue(); + } + break; + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: // NOT is handled here. + // Logical binary ops preserve the number of sign bits at the worst. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp != 1) { + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + FirstAnswer = std::min(Tmp, Tmp2); + // We computed what we know about the sign bits as our first + // answer. Now proceed to the generic code that uses + // ComputeMaskedBits, and pick whichever answer is better. + } + break; + + case Instruction::Select: + Tmp = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + Tmp2 = ComputeNumSignBits(U->getOperand(2), TD, Depth+1); + return std::min(Tmp, Tmp2); + + case Instruction::Add: + // Add can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + + // Special case decrementing a value (ADD X, -1): + if (ConstantInt *CRHS = dyn_cast(U->getOperand(1))) + if (CRHS->isAllOnesValue()) { + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(U->getOperand(0), Mask, KnownZero, KnownOne, TD, + Depth+1); + + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(TyBits, 1)) == Mask) + return TyBits; + + // If we are subtracting one from a positive number, there is no carry + // out of the result. + if (KnownZero.isNegative()) + return Tmp; + } + + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp2 == 1) return 1; + return std::min(Tmp, Tmp2)-1; + + case Instruction::Sub: + Tmp2 = ComputeNumSignBits(U->getOperand(1), TD, Depth+1); + if (Tmp2 == 1) return 1; + + // Handle NEG. + if (ConstantInt *CLHS = dyn_cast(U->getOperand(0))) + if (CLHS->isNullValue()) { + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(U->getOperand(1), Mask, KnownZero, KnownOne, + TD, Depth+1); + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(TyBits, 1)) == Mask) + return TyBits; + + // If the input is known to be positive (the sign bit is known clear), + // the output of the NEG has the same number of sign bits as the input. + if (KnownZero.isNegative()) + return Tmp2; + + // Otherwise, we treat this like a SUB. + } + + // Sub can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1); + if (Tmp == 1) return 1; // Early out. + return std::min(Tmp, Tmp2)-1; + + case Instruction::PHI: { + PHINode *PN = cast(U); + // Don't analyze large in-degree PHIs. + if (PN->getNumIncomingValues() > 4) break; + + // Take the minimum of all incoming values. This can't infinitely loop + // because of our depth threshold. + Tmp = ComputeNumSignBits(PN->getIncomingValue(0), TD, Depth+1); + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) { + if (Tmp == 1) return Tmp; + Tmp = std::min(Tmp, + ComputeNumSignBits(PN->getIncomingValue(i), TD, Depth+1)); + } + return Tmp; + } + + case Instruction::Trunc: + // FIXME: it's tricky to do anything useful for this, but it is an important + // case for targets like X86. + break; + } + + // Finally, if we can prove that the top bits of the result are 0's or 1's, + // use this information. + APInt KnownZero(TyBits, 0), KnownOne(TyBits, 0); + APInt Mask = APInt::getAllOnesValue(TyBits); + ComputeMaskedBits(V, Mask, KnownZero, KnownOne, TD, Depth); + + if (KnownZero.isNegative()) { // sign bit is 0 + Mask = KnownZero; + } else if (KnownOne.isNegative()) { // sign bit is 1; + Mask = KnownOne; + } else { + // Nothing known. + return FirstAnswer; + } + + // Okay, we know that the sign bit in Mask is set. Use CLZ to determine + // the number of identical bits in the top of the input value. + Mask = ~Mask; + Mask <<= Mask.getBitWidth()-TyBits; + // Return # leading zeros. We use 'min' here in case Val was zero before + // shifting. We don't want to return '64' as for an i32 "0". + return std::max(FirstAnswer, std::min(TyBits, Mask.countLeadingZeros())); +} + +/// ComputeMultiple - This function computes the integer multiple of Base that +/// equals V. If successful, it returns true and returns the multiple in +/// Multiple. If unsuccessful, it returns false. It looks +/// through SExt instructions only if LookThroughSExt is true. +bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, + bool LookThroughSExt, unsigned Depth) { + const unsigned MaxDepth = 6; + + assert(V && "No Value?"); + assert(Depth <= MaxDepth && "Limit Search Depth"); + assert(V->getType()->isIntegerTy() && "Not integer or pointer type!"); + + const Type *T = V->getType(); + + ConstantInt *CI = dyn_cast(V); + + if (Base == 0) + return false; + + if (Base == 1) { + Multiple = V; + return true; + } + + ConstantExpr *CO = dyn_cast(V); + Constant *BaseVal = ConstantInt::get(T, Base); + if (CO && CO == BaseVal) { + // Multiple is 1. + Multiple = ConstantInt::get(T, 1); + return true; + } + + if (CI && CI->getZExtValue() % Base == 0) { + Multiple = ConstantInt::get(T, CI->getZExtValue() / Base); + return true; + } + + if (Depth == MaxDepth) return false; // Limit search depth. + + Operator *I = dyn_cast(V); + if (!I) return false; + + switch (I->getOpcode()) { + default: break; + case Instruction::SExt: + if (!LookThroughSExt) return false; + // otherwise fall through to ZExt + case Instruction::ZExt: + return ComputeMultiple(I->getOperand(0), Base, Multiple, + LookThroughSExt, Depth+1); + case Instruction::Shl: + case Instruction::Mul: { + Value *Op0 = I->getOperand(0); + Value *Op1 = I->getOperand(1); + + if (I->getOpcode() == Instruction::Shl) { + ConstantInt *Op1CI = dyn_cast(Op1); + if (!Op1CI) return false; + // Turn Op0 << Op1 into Op0 * 2^Op1 + APInt Op1Int = Op1CI->getValue(); + uint64_t BitToSet = Op1Int.getLimitedValue(Op1Int.getBitWidth() - 1); + APInt API(Op1Int.getBitWidth(), 0); + API.setBit(BitToSet); + Op1 = ConstantInt::get(V->getContext(), API); + } + + Value *Mul0 = NULL; + if (ComputeMultiple(Op0, Base, Mul0, LookThroughSExt, Depth+1)) { + if (Constant *Op1C = dyn_cast(Op1)) + if (Constant *MulC = dyn_cast(Mul0)) { + if (Op1C->getType()->getPrimitiveSizeInBits() < + MulC->getType()->getPrimitiveSizeInBits()) + Op1C = ConstantExpr::getZExt(Op1C, MulC->getType()); + if (Op1C->getType()->getPrimitiveSizeInBits() > + MulC->getType()->getPrimitiveSizeInBits()) + MulC = ConstantExpr::getZExt(MulC, Op1C->getType()); + + // V == Base * (Mul0 * Op1), so return (Mul0 * Op1) + Multiple = ConstantExpr::getMul(MulC, Op1C); + return true; + } + + if (ConstantInt *Mul0CI = dyn_cast(Mul0)) + if (Mul0CI->getValue() == 1) { + // V == Base * Op1, so return Op1 + Multiple = Op1; + return true; + } + } + + Value *Mul1 = NULL; + if (ComputeMultiple(Op1, Base, Mul1, LookThroughSExt, Depth+1)) { + if (Constant *Op0C = dyn_cast(Op0)) + if (Constant *MulC = dyn_cast(Mul1)) { + if (Op0C->getType()->getPrimitiveSizeInBits() < + MulC->getType()->getPrimitiveSizeInBits()) + Op0C = ConstantExpr::getZExt(Op0C, MulC->getType()); + if (Op0C->getType()->getPrimitiveSizeInBits() > + MulC->getType()->getPrimitiveSizeInBits()) + MulC = ConstantExpr::getZExt(MulC, Op0C->getType()); + + // V == Base * (Mul1 * Op0), so return (Mul1 * Op0) + Multiple = ConstantExpr::getMul(MulC, Op0C); + return true; + } + + if (ConstantInt *Mul1CI = dyn_cast(Mul1)) + if (Mul1CI->getValue() == 1) { + // V == Base * Op0, so return Op0 + Multiple = Op0; + return true; + } + } + } + } + + // We could not determine if V is a multiple of Base. + return false; +} + +/// CannotBeNegativeZero - Return true if we can prove that the specified FP +/// value is never equal to -0.0. +/// +/// NOTE: this function will need to be revisited when we support non-default +/// rounding modes! +/// +bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) { + if (const ConstantFP *CFP = dyn_cast(V)) + return !CFP->getValueAPF().isNegZero(); + + if (Depth == 6) + return 1; // Limit search depth. + + const Operator *I = dyn_cast(V); + if (I == 0) return false; + + // (add x, 0.0) is guaranteed to return +0.0, not -0.0. + if (I->getOpcode() == Instruction::FAdd && + isa(I->getOperand(1)) && + cast(I->getOperand(1))->isNullValue()) + return true; + + // sitofp and uitofp turn into +0.0 for zero. + if (isa(I) || isa(I)) + return true; + + if (const IntrinsicInst *II = dyn_cast(I)) + // sqrt(-0.0) = -0.0, no other negative results are possible. + if (II->getIntrinsicID() == Intrinsic::sqrt) + return CannotBeNegativeZero(II->getArgOperand(0), Depth+1); + + if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) { + if (F->isDeclaration()) { + // abs(x) != -0.0 + if (F->getName() == "abs") return true; + // fabs[lf](x) != -0.0 + if (F->getName() == "fabs") return true; + if (F->getName() == "fabsf") return true; + if (F->getName() == "fabsl") return true; + if (F->getName() == "sqrt" || F->getName() == "sqrtf" || + F->getName() == "sqrtl") + return CannotBeNegativeZero(CI->getArgOperand(0), Depth+1); + } + } + + return false; +} + +/// isBytewiseValue - If the specified value can be set by repeating the same +/// byte in memory, return the i8 value that it is represented with. This is +/// true for all i8 values obviously, but is also true for i32 0, i32 -1, +/// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated +/// byte store (e.g. i16 0x1234), return null. +Value *llvm::isBytewiseValue(Value *V) { + // All byte-wide stores are splatable, even of arbitrary variables. + if (V->getType()->isIntegerTy(8)) return V; + + // Handle 'null' ConstantArrayZero etc. + if (Constant *C = dyn_cast(V)) + if (C->isNullValue()) + return Constant::getNullValue(Type::getInt8Ty(V->getContext())); + + // Constant float and double values can be handled as integer values if the + // corresponding integer value is "byteable". An important case is 0.0. + if (ConstantFP *CFP = dyn_cast(V)) { + if (CFP->getType()->isFloatTy()) + V = ConstantExpr::getBitCast(CFP, Type::getInt32Ty(V->getContext())); + if (CFP->getType()->isDoubleTy()) + V = ConstantExpr::getBitCast(CFP, Type::getInt64Ty(V->getContext())); + // Don't handle long double formats, which have strange constraints. + } + + // We can handle constant integers that are power of two in size and a + // multiple of 8 bits. + if (ConstantInt *CI = dyn_cast(V)) { + unsigned Width = CI->getBitWidth(); + if (isPowerOf2_32(Width) && Width > 8) { + // We can handle this value if the recursive binary decomposition is the + // same at all levels. + APInt Val = CI->getValue(); + APInt Val2; + while (Val.getBitWidth() != 8) { + unsigned NextWidth = Val.getBitWidth()/2; + Val2 = Val.lshr(NextWidth); + Val2 = Val2.trunc(Val.getBitWidth()/2); + Val = Val.trunc(Val.getBitWidth()/2); + + // If the top/bottom halves aren't the same, reject it. + if (Val != Val2) + return 0; + } + return ConstantInt::get(V->getContext(), Val); + } + } + + // A ConstantArray is splatable if all its members are equal and also + // splatable. + if (ConstantArray *CA = dyn_cast(V)) { + if (CA->getNumOperands() == 0) + return 0; + + Value *Val = isBytewiseValue(CA->getOperand(0)); + if (!Val) + return 0; + + for (unsigned I = 1, E = CA->getNumOperands(); I != E; ++I) + if (CA->getOperand(I-1) != CA->getOperand(I)) + return 0; + + return Val; + } + + // Conceptually, we could handle things like: + // %a = zext i8 %X to i16 + // %b = shl i16 %a, 8 + // %c = or i16 %a, %b + // but until there is an example that actually needs this, it doesn't seem + // worth worrying about. + return 0; +} + + +// This is the recursive version of BuildSubAggregate. It takes a few different +// arguments. Idxs is the index within the nested struct From that we are +// looking at now (which is of type IndexedType). IdxSkip is the number of +// indices from Idxs that should be left out when inserting into the resulting +// struct. To is the result struct built so far, new insertvalue instructions +// build on that. +static Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, + SmallVector &Idxs, + unsigned IdxSkip, + Instruction *InsertBefore) { + const llvm::StructType *STy = llvm::dyn_cast(IndexedType); + if (STy) { + // Save the original To argument so we can modify it + Value *OrigTo = To; + // General case, the type indexed by Idxs is a struct + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + // Process each struct element recursively + Idxs.push_back(i); + Value *PrevTo = To; + To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, + InsertBefore); + Idxs.pop_back(); + if (!To) { + // Couldn't find any inserted value for this index? Cleanup + while (PrevTo != OrigTo) { + InsertValueInst* Del = cast(PrevTo); + PrevTo = Del->getAggregateOperand(); + Del->eraseFromParent(); + } + // Stop processing elements + break; + } + } + // If we succesfully found a value for each of our subaggregates + if (To) + return To; + } + // Base case, the type indexed by SourceIdxs is not a struct, or not all of + // the struct's elements had a value that was inserted directly. In the latter + // case, perhaps we can't determine each of the subelements individually, but + // we might be able to find the complete struct somewhere. + + // Find the value that is at that particular spot + Value *V = FindInsertedValue(From, Idxs.begin(), Idxs.end()); + + if (!V) + return NULL; + + // Insert the value in the new (sub) aggregrate + return llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, + Idxs.end(), "tmp", InsertBefore); +} + +// This helper takes a nested struct and extracts a part of it (which is again a +// struct) into a new value. For example, given the struct: +// { a, { b, { c, d }, e } } +// and the indices "1, 1" this returns +// { c, d }. +// +// It does this by inserting an insertvalue for each element in the resulting +// struct, as opposed to just inserting a single struct. This will only work if +// each of the elements of the substruct are known (ie, inserted into From by an +// insertvalue instruction somewhere). +// +// All inserted insertvalue instructions are inserted before InsertBefore +static Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, + const unsigned *idx_end, + Instruction *InsertBefore) { + assert(InsertBefore && "Must have someplace to insert!"); + const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), + idx_begin, + idx_end); + Value *To = UndefValue::get(IndexedType); + SmallVector Idxs(idx_begin, idx_end); + unsigned IdxSkip = Idxs.size(); + + return BuildSubAggregate(From, To, IndexedType, Idxs, IdxSkip, InsertBefore); +} + +/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if +/// the scalar value indexed is already around as a register, for example if it +/// were inserted directly into the aggregrate. +/// +/// If InsertBefore is not null, this function will duplicate (modified) +/// insertvalues when a part of a nested struct is extracted. +Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, + const unsigned *idx_end, Instruction *InsertBefore) { + // Nothing to index? Just return V then (this is useful at the end of our + // recursion) + if (idx_begin == idx_end) + return V; + // We have indices, so V should have an indexable type + assert((V->getType()->isStructTy() || V->getType()->isArrayTy()) + && "Not looking at a struct or array?"); + assert(ExtractValueInst::getIndexedType(V->getType(), idx_begin, idx_end) + && "Invalid indices for type?"); + const CompositeType *PTy = cast(V->getType()); + + if (isa(V)) + return UndefValue::get(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (isa(V)) + return Constant::getNullValue(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (Constant *C = dyn_cast(V)) { + if (isa(C) || isa(C)) + // Recursively process this constant + return FindInsertedValue(C->getOperand(*idx_begin), idx_begin + 1, + idx_end, InsertBefore); + } else if (InsertValueInst *I = dyn_cast(V)) { + // Loop the indices for the insertvalue instruction in parallel with the + // requested indices + const unsigned *req_idx = idx_begin; + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i, ++req_idx) { + if (req_idx == idx_end) { + if (InsertBefore) + // The requested index identifies a part of a nested aggregate. Handle + // this specially. For example, + // %A = insertvalue { i32, {i32, i32 } } undef, i32 10, 1, 0 + // %B = insertvalue { i32, {i32, i32 } } %A, i32 11, 1, 1 + // %C = extractvalue {i32, { i32, i32 } } %B, 1 + // This can be changed into + // %A = insertvalue {i32, i32 } undef, i32 10, 0 + // %C = insertvalue {i32, i32 } %A, i32 11, 1 + // which allows the unused 0,0 element from the nested struct to be + // removed. + return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); + else + // We can't handle this without inserting insertvalues + return 0; + } + + // This insert value inserts something else than what we are looking for. + // See if the (aggregrate) value inserted into has the value we are + // looking for, then. + if (*req_idx != *i) + return FindInsertedValue(I->getAggregateOperand(), idx_begin, idx_end, + InsertBefore); + } + // If we end up here, the indices of the insertvalue match with those + // requested (though possibly only partially). Now we recursively look at + // the inserted value, passing any remaining indices. + return FindInsertedValue(I->getInsertedValueOperand(), req_idx, idx_end, + InsertBefore); + } else if (ExtractValueInst *I = dyn_cast(V)) { + // If we're extracting a value from an aggregrate that was extracted from + // something else, we can extract from that something else directly instead. + // However, we will need to chain I's indices with the requested indices. + + // Calculate the number of indices required + unsigned size = I->getNumIndices() + (idx_end - idx_begin); + // Allocate some space to put the new indices in + SmallVector Idxs; + Idxs.reserve(size); + // Add indices from the extract value instruction + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i) + Idxs.push_back(*i); + + // Add requested indices + for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i) + Idxs.push_back(*i); + + assert(Idxs.size() == size + && "Number of indices added not correct?"); + + return FindInsertedValue(I->getAggregateOperand(), Idxs.begin(), Idxs.end(), + InsertBefore); + } + // Otherwise, we don't know (such as, extracting from a function return value + // or load instruction) + return 0; +} + +/// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if +/// it can be expressed as a base pointer plus a constant offset. Return the +/// base and offset to the caller. +Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, + const TargetData &TD) { + Operator *PtrOp = dyn_cast(Ptr); + if (PtrOp == 0) return Ptr; + + // Just look through bitcasts. + if (PtrOp->getOpcode() == Instruction::BitCast) + return GetPointerBaseWithConstantOffset(PtrOp->getOperand(0), Offset, TD); + + // If this is a GEP with constant indices, we can look through it. + GEPOperator *GEP = dyn_cast(PtrOp); + if (GEP == 0 || !GEP->hasAllConstantIndices()) return Ptr; + + gep_type_iterator GTI = gep_type_begin(GEP); + for (User::op_iterator I = GEP->idx_begin(), E = GEP->idx_end(); I != E; + ++I, ++GTI) { + ConstantInt *OpC = cast(*I); + if (OpC->isZero()) continue; + + // Handle a struct and array indices which add their offset to the pointer. + if (const StructType *STy = dyn_cast(*GTI)) { + Offset += TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); + } else { + uint64_t Size = TD.getTypeAllocSize(GTI.getIndexedType()); + Offset += OpC->getSExtValue()*Size; + } + } + + // Re-sign extend from the pointer size if needed to get overflow edge cases + // right. + unsigned PtrSize = TD.getPointerSizeInBits(); + if (PtrSize < 64) + Offset = (Offset << (64-PtrSize)) >> (64-PtrSize); + + return GetPointerBaseWithConstantOffset(GEP->getPointerOperand(), Offset, TD); +} + + +/// GetConstantStringInfo - This function computes the length of a +/// null-terminated C string pointed to by V. If successful, it returns true +/// and returns the string in Str. If unsuccessful, it returns false. +bool llvm::GetConstantStringInfo(const Value *V, std::string &Str, + uint64_t Offset, + bool StopAtNul) { + // If V is NULL then return false; + if (V == NULL) return false; + + // Look through bitcast instructions. + if (const BitCastInst *BCI = dyn_cast(V)) + return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way + const User *GEP = 0; + if (const GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (const ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() == Instruction::BitCast) + return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); + if (CE->getOpcode() != Instruction::GetElementPtr) + return false; + GEP = CE; + } + + if (GEP) { + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return false; + + // Make sure the index-ee is a pointer to array of i8. + const PointerType *PT = cast(GEP->getOperand(0)->getType()); + const ArrayType *AT = dyn_cast(PT->getElementType()); + if (AT == 0 || !AT->getElementType()->isIntegerTy(8)) + return false; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + const ConstantInt *FirstIdx = dyn_cast(GEP->getOperand(1)); + if (FirstIdx == 0 || !FirstIdx->isZero()) + return false; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (const ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return false; + return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, + StopAtNul); + } + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + const GlobalVariable* GV = dyn_cast(V); + if (!GV || !GV->isConstant() || !GV->hasDefinitiveInitializer()) + return false; + const Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case + if (isa(GlobalInit)) { + // This is a degenerate case. The initializer is constant zero so the + // length of the string must be zero. + Str.clear(); + return true; + } + + // Must be a Constant Array + const ConstantArray *Array = dyn_cast(GlobalInit); + if (Array == 0 || !Array->getType()->getElementType()->isIntegerTy(8)) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + if (Offset > NumElts) + return false; + + // Traverse the constant array from 'Offset' which is the place the GEP refers + // to in the array. + Str.reserve(NumElts-Offset); + for (unsigned i = Offset; i != NumElts; ++i) { + const Constant *Elt = Array->getOperand(i); + const ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return false; + if (StopAtNul && CI->isZero()) + return true; // we found end of string, success! + Str += (char)CI->getZExtValue(); + } + + // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. + return true; +} + +// These next two are very similar to the above, but also look through PHI +// nodes. +// TODO: See if we can integrate these two together. + +/// GetStringLengthH - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +static uint64_t GetStringLengthH(Value *V, SmallPtrSet &PHIs) { + // Look through noop bitcast instructions. + if (BitCastInst *BCI = dyn_cast(V)) + return GetStringLengthH(BCI->getOperand(0), PHIs); + + // If this is a PHI node, there are two cases: either we have already seen it + // or we haven't. + if (PHINode *PN = dyn_cast(V)) { + if (!PHIs.insert(PN)) + return ~0ULL; // already in the set. + + // If it was new, see if all the input strings are the same length. + uint64_t LenSoFar = ~0ULL; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + uint64_t Len = GetStringLengthH(PN->getIncomingValue(i), PHIs); + if (Len == 0) return 0; // Unknown length -> unknown. + + if (Len == ~0ULL) continue; + + if (Len != LenSoFar && LenSoFar != ~0ULL) + return 0; // Disagree -> unknown. + LenSoFar = Len; + } + + // Success, all agree. + return LenSoFar; + } + + // strlen(select(c,x,y)) -> strlen(x) ^ strlen(y) + if (SelectInst *SI = dyn_cast(V)) { + uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs); + if (Len1 == 0) return 0; + uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs); + if (Len2 == 0) return 0; + if (Len1 == ~0ULL) return Len2; + if (Len2 == ~0ULL) return Len1; + if (Len1 != Len2) return 0; + return Len1; + } + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return unknown. + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() != Instruction::GetElementPtr) + return 0; + GEP = CE; + } else { + return 0; + } + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return 0; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt *Idx = dyn_cast(GEP->getOperand(1))) { + if (!Idx->isZero()) + return 0; + } else + return 0; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return 0; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer() || + GV->mayBeOverridden()) + return 0; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case, which is a degenerate case. The + // initializer is constant zero so the length of the string must be zero. + if (isa(GlobalInit)) + return 1; // Len = 0 offset by 1. + + // Must be a Constant Array + ConstantArray *Array = dyn_cast(GlobalInit); + if (!Array || !Array->getType()->getElementType()->isIntegerTy(8)) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + // Traverse the constant array from StartIdx (derived above) which is + // the place the GEP refers to in the array. + for (unsigned i = StartIdx; i != NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return 0; + if (CI->isZero()) + return i-StartIdx+1; // We found end of string, success! + } + + return 0; // The array isn't null terminated, conservatively return 'unknown'. +} + +/// GetStringLength - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +uint64_t llvm::GetStringLength(Value *V) { + if (!V->getType()->isPointerTy()) return 0; + + SmallPtrSet PHIs; + uint64_t Len = GetStringLengthH(V, PHIs); + // If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return + // an empty string as a length. + return Len == ~0ULL ? 1 : Len; +} + +Value * +llvm::GetUnderlyingObject(Value *V, const TargetData *TD, unsigned MaxLookup) { + if (!V->getType()->isPointerTy()) + return V; + for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { + if (GEPOperator *GEP = dyn_cast(V)) { + V = GEP->getPointerOperand(); + } else if (Operator::getOpcode(V) == Instruction::BitCast) { + V = cast(V)->getOperand(0); + } else if (GlobalAlias *GA = dyn_cast(V)) { + if (GA->mayBeOverridden()) + return V; + V = GA->getAliasee(); + } else { + // See if InstructionSimplify knows any relevant tricks. + if (Instruction *I = dyn_cast(V)) + // TODO: Aquire a DominatorTree and use it. + if (Value *Simplified = SimplifyInstruction(I, TD, 0)) { + V = Simplified; + continue; + } + + return V; + } + assert(V->getType()->isPointerTy() && "Unexpected operand type!"); + } + return V; +} diff --git a/final/lib/Archive/Archive.cpp b/final/lib/Archive/Archive.cpp new file mode 100644 index 00000000000..1eab27d3eba --- /dev/null +++ b/final/lib/Archive/Archive.cpp @@ -0,0 +1,261 @@ +//===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the Archive and ArchiveMember +// classes that is common to both reading and writing archives.. +// +//===----------------------------------------------------------------------===// + +#include "ArchiveInternals.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Module.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/system_error.h" +#include +#include +using namespace llvm; + +// getMemberSize - compute the actual physical size of the file member as seen +// on disk. This isn't the size of member's payload. Use getSize() for that. +unsigned +ArchiveMember::getMemberSize() const { + // Basically its the file size plus the header size + unsigned result = info.fileSize + sizeof(ArchiveMemberHeader); + + // If it has a long filename, include the name length + if (hasLongFilename()) + result += path.str().length() + 1; + + // If its now odd lengthed, include the padding byte + if (result % 2 != 0 ) + result++; + + return result; +} + +// This default constructor is only use by the ilist when it creates its +// sentry node. We give it specific static values to make it stand out a bit. +ArchiveMember::ArchiveMember() + : parent(0), path("--invalid--"), flags(0), data(0) +{ + info.user = sys::Process::GetCurrentUserId(); + info.group = sys::Process::GetCurrentGroupId(); + info.mode = 0777; + info.fileSize = 0; + info.modTime = sys::TimeValue::now(); +} + +// This is the constructor that the Archive class uses when it is building or +// reading an archive. It just defaults a few things and ensures the parent is +// set for the iplist. The Archive class fills in the ArchiveMember's data. +// This is required because correctly setting the data may depend on other +// things in the Archive. +ArchiveMember::ArchiveMember(Archive* PAR) + : parent(PAR), path(), flags(0), data(0) +{ +} + +// This method allows an ArchiveMember to be replaced with the data for a +// different file, presumably as an update to the member. It also makes sure +// the flags are reset correctly. +bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) { + bool Exists; + if (sys::fs::exists(newFile.str(), Exists) || !Exists) { + if (ErrMsg) + *ErrMsg = "Can not replace an archive member with a non-existent file"; + return true; + } + + data = 0; + path = newFile; + + // SVR4 symbol tables have an empty name + if (path.str() == ARFILE_SVR4_SYMTAB_NAME) + flags |= SVR4SymbolTableFlag; + else + flags &= ~SVR4SymbolTableFlag; + + // BSD4.4 symbol tables have a special name + if (path.str() == ARFILE_BSD4_SYMTAB_NAME) + flags |= BSD4SymbolTableFlag; + else + flags &= ~BSD4SymbolTableFlag; + + // LLVM symbol tables have a very specific name + if (path.str() == ARFILE_LLVM_SYMTAB_NAME) + flags |= LLVMSymbolTableFlag; + else + flags &= ~LLVMSymbolTableFlag; + + // String table name + if (path.str() == ARFILE_STRTAB_NAME) + flags |= StringTableFlag; + else + flags &= ~StringTableFlag; + + // If it has a slash then it has a path + bool hasSlash = path.str().find('/') != std::string::npos; + if (hasSlash) + flags |= HasPathFlag; + else + flags &= ~HasPathFlag; + + // If it has a slash or its over 15 chars then its a long filename format + if (hasSlash || path.str().length() > 15) + flags |= HasLongFilenameFlag; + else + flags &= ~HasLongFilenameFlag; + + // Get the signature and status info + const char* signature = (const char*) data; + SmallString<4> magic; + if (!signature) { + sys::fs::get_magic(path.str(), magic.capacity(), magic); + signature = magic.c_str(); + const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg); + if (FSinfo) + info = *FSinfo; + else + return true; + } + + // Determine what kind of file it is. + switch (sys::IdentifyFileType(signature,4)) { + case sys::Bitcode_FileType: + flags |= BitcodeFlag; + break; + default: + flags &= ~BitcodeFlag; + break; + } + return false; +} + +// Archive constructor - this is the only constructor that gets used for the +// Archive class. Everything else (default,copy) is deprecated. This just +// initializes and maps the file into memory, if requested. +Archive::Archive(const sys::Path& filename, LLVMContext& C) + : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), + symTabSize(0), firstFileOffset(0), modules(), foreignST(0), Context(C) { +} + +bool +Archive::mapToMemory(std::string* ErrMsg) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFile(archPath.c_str(), File)) { + if (ErrMsg) + *ErrMsg = ec.message(); + return true; + } + mapfile = File.take(); + base = mapfile->getBufferStart(); + return false; +} + +void Archive::cleanUpMemory() { + // Shutdown the file mapping + delete mapfile; + mapfile = 0; + base = 0; + + // Forget the entire symbol table + symTab.clear(); + symTabSize = 0; + + firstFileOffset = 0; + + // Free the foreign symbol table member + if (foreignST) { + delete foreignST; + foreignST = 0; + } + + // Delete any Modules and ArchiveMember's we've allocated as a result of + // symbol table searches. + for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) { + delete I->second.first; + delete I->second.second; + } +} + +// Archive destructor - just clean up memory +Archive::~Archive() { + cleanUpMemory(); +} + + + +static void getSymbols(Module*M, std::vector& symbols) { + // Loop over global variables + for (Module::global_iterator GI = M->global_begin(), GE=M->global_end(); GI != GE; ++GI) + if (!GI->isDeclaration() && !GI->hasLocalLinkage()) + if (!GI->getName().empty()) + symbols.push_back(GI->getName()); + + // Loop over functions + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) + if (!FI->isDeclaration() && !FI->hasLocalLinkage()) + if (!FI->getName().empty()) + symbols.push_back(FI->getName()); + + // Loop over aliases + for (Module::alias_iterator AI = M->alias_begin(), AE = M->alias_end(); + AI != AE; ++AI) { + if (AI->hasName()) + symbols.push_back(AI->getName()); + } +} + +// Get just the externally visible defined symbols from the bitcode +bool llvm::GetBitcodeSymbols(const sys::Path& fName, + LLVMContext& Context, + std::vector& symbols, + std::string* ErrMsg) { + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(fName.c_str(), Buffer)) { + if (ErrMsg) *ErrMsg = "Could not open file '" + fName.str() + "'" + ": " + + ec.message(); + return true; + } + + Module *M = ParseBitcodeFile(Buffer.get(), Context, ErrMsg); + if (!M) + return true; + + // Get the symbols + getSymbols(M, symbols); + + // Done with the module. + delete M; + return true; +} + +Module* +llvm::GetBitcodeSymbols(const char *BufPtr, unsigned Length, + const std::string& ModuleID, + LLVMContext& Context, + std::vector& symbols, + std::string* ErrMsg) { + // Get the module. + OwningPtr Buffer( + MemoryBuffer::getMemBufferCopy(StringRef(BufPtr, Length),ModuleID.c_str())); + + Module *M = ParseBitcodeFile(Buffer.get(), Context, ErrMsg); + if (!M) + return 0; + + // Get the symbols + getSymbols(M, symbols); + + // Done with the module. Note that it's the caller's responsibility to delete + // the Module. + return M; +} diff --git a/final/lib/Archive/ArchiveInternals.h b/final/lib/Archive/ArchiveInternals.h new file mode 100644 index 00000000000..55684f7023d --- /dev/null +++ b/final/lib/Archive/ArchiveInternals.h @@ -0,0 +1,89 @@ +//===-- lib/Archive/ArchiveInternals.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Internal implementation header for LLVM Archive files. +// +//===----------------------------------------------------------------------===// + +#ifndef LIB_ARCHIVE_ARCHIVEINTERNALS_H +#define LIB_ARCHIVE_ARCHIVEINTERNALS_H + +#include "llvm/Bitcode/Archive.h" +#include "llvm/Support/TimeValue.h" +#include "llvm/ADT/StringExtras.h" + +#include + +#define ARFILE_MAGIC "!\n" ///< magic string +#define ARFILE_MAGIC_LEN (sizeof(ARFILE_MAGIC)-1) ///< length of magic string +#define ARFILE_SVR4_SYMTAB_NAME "/ " ///< SVR4 symtab entry name +#define ARFILE_LLVM_SYMTAB_NAME "#_LLVM_SYM_TAB_#" ///< LLVM symtab entry name +#define ARFILE_BSD4_SYMTAB_NAME "__.SYMDEF SORTED" ///< BSD4 symtab entry name +#define ARFILE_STRTAB_NAME "// " ///< Name of string table +#define ARFILE_PAD "\n" ///< inter-file align padding +#define ARFILE_MEMBER_MAGIC "`\n" ///< fmag field magic # + +namespace llvm { + + class LLVMContext; + + /// The ArchiveMemberHeader structure is used internally for bitcode + /// archives. + /// The header precedes each file member in the archive. This structure is + /// defined using character arrays for direct and correct interpretation + /// regardless of the endianess of the machine that produced it. + /// @brief Archive File Member Header + class ArchiveMemberHeader { + /// @name Data + /// @{ + public: + char name[16]; ///< Name of the file member. + char date[12]; ///< File date, decimal seconds since Epoch + char uid[6]; ///< user id in ASCII decimal + char gid[6]; ///< group id in ASCII decimal + char mode[8]; ///< file mode in ASCII octal + char size[10]; ///< file size in ASCII decimal + char fmag[2]; ///< Always contains ARFILE_MAGIC_TERMINATOR + + /// @} + /// @name Methods + /// @{ + public: + void init() { + memset(name,' ',16); + memset(date,' ',12); + memset(uid,' ',6); + memset(gid,' ',6); + memset(mode,' ',8); + memset(size,' ',10); + fmag[0] = '`'; + fmag[1] = '\n'; + } + + bool checkSignature() { + return 0 == memcmp(fmag, ARFILE_MEMBER_MAGIC,2); + } + }; + + // Get just the externally visible defined symbols from the bitcode + bool GetBitcodeSymbols(const sys::Path& fName, + LLVMContext& Context, + std::vector& symbols, + std::string* ErrMsg); + + Module* GetBitcodeSymbols(const char *Buffer, unsigned Length, + const std::string& ModuleID, + LLVMContext& Context, + std::vector& symbols, + std::string* ErrMsg); +} + +#endif + +// vim: sw=2 ai diff --git a/final/lib/Archive/ArchiveReader.cpp b/final/lib/Archive/ArchiveReader.cpp new file mode 100644 index 00000000000..eef6fe0b1c1 --- /dev/null +++ b/final/lib/Archive/ArchiveReader.cpp @@ -0,0 +1,630 @@ +//===-- ArchiveReader.cpp - Read LLVM archive files -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Builds up standard unix archive files (.a) containing LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#include "ArchiveInternals.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Module.h" +#include +#include +using namespace llvm; + +/// Read a variable-bit-rate encoded unsigned integer +static inline unsigned readInteger(const char*&At, const char*End) { + unsigned Shift = 0; + unsigned Result = 0; + + do { + if (At == End) + return Result; + Result |= (unsigned)((*At++) & 0x7F) << Shift; + Shift += 7; + } while (At[-1] & 0x80); + return Result; +} + +// Completely parse the Archive's symbol table and populate symTab member var. +bool +Archive::parseSymbolTable(const void* data, unsigned size, std::string* error) { + const char* At = (const char*) data; + const char* End = At + size; + while (At < End) { + unsigned offset = readInteger(At, End); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab offset!"; + return false; + } + unsigned length = readInteger(At, End); + if (At == End) { + if (error) + *error = "Ran out of data reading vbr_uint for symtab length!"; + return false; + } + if (At + length > End) { + if (error) + *error = "Malformed symbol table: length not consistent with size"; + return false; + } + // we don't care if it can't be inserted (duplicate entry) + symTab.insert(std::make_pair(std::string(At, length), offset)); + At += length; + } + symTabSize = size; + return true; +} + +// This member parses an ArchiveMemberHeader that is presumed to be pointed to +// by At. The At pointer is updated to the byte just after the header, which +// can be variable in size. +ArchiveMember* +Archive::parseMemberHeader(const char*& At, const char* End, std::string* error) +{ + if (At + sizeof(ArchiveMemberHeader) >= End) { + if (error) + *error = "Unexpected end of file"; + return 0; + } + + // Cast archive member header + ArchiveMemberHeader* Hdr = (ArchiveMemberHeader*)At; + At += sizeof(ArchiveMemberHeader); + + // Extract the size and determine if the file is + // compressed or not (negative length). + int flags = 0; + int MemberSize = atoi(Hdr->size); + if (MemberSize < 0) { + flags |= ArchiveMember::CompressedFlag; + MemberSize = -MemberSize; + } + + // Check the size of the member for sanity + if (At + MemberSize > End) { + if (error) + *error = "invalid member length in archive file"; + return 0; + } + + // Check the member signature + if (!Hdr->checkSignature()) { + if (error) + *error = "invalid file member signature"; + return 0; + } + + // Convert and check the member name + // The empty name ( '/' and 15 blanks) is for a foreign (non-LLVM) symbol + // table. The special name "//" and 14 blanks is for a string table, used + // for long file names. This library doesn't generate either of those but + // it will accept them. If the name starts with #1/ and the remainder is + // digits, then those digits specify the length of the name that is + // stored immediately following the header. The special name + // __LLVM_SYM_TAB__ identifies the symbol table for LLVM bitcode. + // Anything else is a regular, short filename that is terminated with + // a '/' and blanks. + + std::string pathname; + switch (Hdr->name[0]) { + case '#': + if (Hdr->name[1] == '1' && Hdr->name[2] == '/') { + if (isdigit(Hdr->name[3])) { + unsigned len = atoi(&Hdr->name[3]); + const char *nulp = (const char *)memchr(At, '\0', len); + pathname.assign(At, nulp != 0 ? (uintptr_t)(nulp - At) : len); + At += len; + MemberSize -= len; + flags |= ArchiveMember::HasLongFilenameFlag; + } else { + if (error) + *error = "invalid long filename"; + return 0; + } + } else if (Hdr->name[1] == '_' && + (0 == memcmp(Hdr->name, ARFILE_LLVM_SYMTAB_NAME, 16))) { + // The member is using a long file name (>15 chars) format. + // This format is standard for 4.4BSD and Mac OSX operating + // systems. LLVM uses it similarly. In this format, the + // remainder of the name field (after #1/) specifies the + // length of the file name which occupy the first bytes of + // the member's data. The pathname already has the #1/ stripped. + pathname.assign(ARFILE_LLVM_SYMTAB_NAME); + flags |= ArchiveMember::LLVMSymbolTableFlag; + } + break; + case '/': + if (Hdr->name[1]== '/') { + if (0 == memcmp(Hdr->name, ARFILE_STRTAB_NAME, 16)) { + pathname.assign(ARFILE_STRTAB_NAME); + flags |= ArchiveMember::StringTableFlag; + } else { + if (error) + *error = "invalid string table name"; + return 0; + } + } else if (Hdr->name[1] == ' ') { + if (0 == memcmp(Hdr->name, ARFILE_SVR4_SYMTAB_NAME, 16)) { + pathname.assign(ARFILE_SVR4_SYMTAB_NAME); + flags |= ArchiveMember::SVR4SymbolTableFlag; + } else { + if (error) + *error = "invalid SVR4 symbol table name"; + return 0; + } + } else if (isdigit(Hdr->name[1])) { + unsigned index = atoi(&Hdr->name[1]); + if (index < strtab.length()) { + const char* namep = strtab.c_str() + index; + const char* endp = strtab.c_str() + strtab.length(); + const char* p = namep; + const char* last_p = p; + while (p < endp) { + if (*p == '\n' && *last_p == '/') { + pathname.assign(namep, last_p - namep); + flags |= ArchiveMember::HasLongFilenameFlag; + break; + } + last_p = p; + p++; + } + if (p >= endp) { + if (error) + *error = "missing name termiantor in string table"; + return 0; + } + } else { + if (error) + *error = "name index beyond string table"; + return 0; + } + } + break; + case '_': + if (Hdr->name[1] == '_' && + (0 == memcmp(Hdr->name, ARFILE_BSD4_SYMTAB_NAME, 16))) { + pathname.assign(ARFILE_BSD4_SYMTAB_NAME); + flags |= ArchiveMember::BSD4SymbolTableFlag; + break; + } + /* FALL THROUGH */ + + default: + char* slash = (char*) memchr(Hdr->name, '/', 16); + if (slash == 0) + slash = Hdr->name + 16; + pathname.assign(Hdr->name, slash - Hdr->name); + break; + } + + // Determine if this is a bitcode file + switch (sys::IdentifyFileType(At, 4)) { + case sys::Bitcode_FileType: + flags |= ArchiveMember::BitcodeFlag; + break; + default: + flags &= ~ArchiveMember::BitcodeFlag; + break; + } + + // Instantiate the ArchiveMember to be filled + ArchiveMember* member = new ArchiveMember(this); + + // Fill in fields of the ArchiveMember + member->parent = this; + member->path.set(pathname); + member->info.fileSize = MemberSize; + member->info.modTime.fromEpochTime(atoi(Hdr->date)); + unsigned int mode; + sscanf(Hdr->mode, "%o", &mode); + member->info.mode = mode; + member->info.user = atoi(Hdr->uid); + member->info.group = atoi(Hdr->gid); + member->flags = flags; + member->data = At; + + return member; +} + +bool +Archive::checkSignature(std::string* error) { + // Check the magic string at file's header + if (mapfile->getBufferSize() < 8 || memcmp(base, ARFILE_MAGIC, 8)) { + if (error) + *error = "invalid signature for an archive file"; + return false; + } + return true; +} + +// This function loads the entire archive and fully populates its ilist with +// the members of the archive file. This is typically used in preparation for +// editing the contents of the archive. +bool +Archive::loadArchive(std::string* error) { + + // Set up parsing + members.clear(); + symTab.clear(); + const char *At = base; + const char *End = mapfile->getBufferEnd(); + + if (!checkSignature(error)) + return false; + + At += 8; // Skip the magic string. + + bool seenSymbolTable = false; + bool foundFirstFile = false; + while (At < End) { + // parse the member header + const char* Save = At; + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; + + // check if this is the foreign symbol table + if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { + // We just save this but don't do anything special + // with it. It doesn't count as the "first file". + if (foreignST) { + // What? Multiple foreign symbol tables? Just chuck it + // and retain the last one found. + delete foreignST; + } + foreignST = mbr; + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + } else if (mbr->isStringTable()) { + // Simply suck the entire string table into a string + // variable. This will be used to get the names of the + // members that use the "/ddd" format for their names + // (SVR4 style long names). + strtab.assign(At, mbr->getSize()); + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + delete mbr; + } else if (mbr->isLLVMSymbolTable()) { + // This is the LLVM symbol table for the archive. If we've seen it + // already, its an error. Otherwise, parse the symbol table and move on. + if (seenSymbolTable) { + if (error) + *error = "invalid archive: multiple symbol tables"; + return false; + } + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), error)) + return false; + seenSymbolTable = true; + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + delete mbr; // We don't need this member in the list of members. + } else { + // This is just a regular file. If its the first one, save its offset. + // Otherwise just push it on the list and move on to the next file. + if (!foundFirstFile) { + firstFileOffset = Save - base; + foundFirstFile = true; + } + members.push_back(mbr); + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + } + } + return true; +} + +// Open and completely load the archive file. +Archive* +Archive::OpenAndLoad(const sys::Path& file, LLVMContext& C, + std::string* ErrorMessage) { + std::auto_ptr result ( new Archive(file, C)); + if (result->mapToMemory(ErrorMessage)) + return 0; + if (!result->loadArchive(ErrorMessage)) + return 0; + return result.release(); +} + +// Get all the bitcode modules from the archive +bool +Archive::getAllModules(std::vector& Modules, + std::string* ErrMessage) { + + for (iterator I=begin(), E=end(); I != E; ++I) { + if (I->isBitcode()) { + std::string FullMemberName = archPath.str() + + "(" + I->getPath().str() + ")"; + MemoryBuffer *Buffer = + MemoryBuffer::getMemBufferCopy(StringRef(I->getData(), I->getSize()), + FullMemberName.c_str()); + + Module *M = ParseBitcodeFile(Buffer, Context, ErrMessage); + delete Buffer; + if (!M) + return true; + + Modules.push_back(M); + } + } + return false; +} + +// Load just the symbol table from the archive file +bool +Archive::loadSymbolTable(std::string* ErrorMsg) { + + // Set up parsing + members.clear(); + symTab.clear(); + const char *At = base; + const char *End = mapfile->getBufferEnd(); + + // Make sure we're dealing with an archive + if (!checkSignature(ErrorMsg)) + return false; + + At += 8; // Skip signature + + // Parse the first file member header + const char* FirstFile = At; + ArchiveMember* mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) + return false; + + if (mbr->isSVR4SymbolTable() || mbr->isBSD4SymbolTable()) { + // Skip the foreign symbol table, we don't do anything with it + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + delete mbr; + + // Read the next one + FirstFile = At; + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } + } + + if (mbr->isStringTable()) { + // Process the string table entry + strtab.assign((const char*)mbr->getData(), mbr->getSize()); + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + delete mbr; + // Get the next one + FirstFile = At; + mbr = parseMemberHeader(At, End, ErrorMsg); + if (!mbr) { + delete mbr; + return false; + } + } + + // See if its the symbol table + if (mbr->isLLVMSymbolTable()) { + if (!parseSymbolTable(mbr->getData(), mbr->getSize(), ErrorMsg)) { + delete mbr; + return false; + } + + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + delete mbr; + // Can't be any more symtab headers so just advance + FirstFile = At; + } else { + // There's no symbol table in the file. We have to rebuild it from scratch + // because the intent of this method is to get the symbol table loaded so + // it can be searched efficiently. + // Add the member to the members list + members.push_back(mbr); + } + + firstFileOffset = FirstFile - base; + return true; +} + +// Open the archive and load just the symbol tables +Archive* Archive::OpenAndLoadSymbols(const sys::Path& file, + LLVMContext& C, + std::string* ErrorMessage) { + std::auto_ptr result ( new Archive(file, C) ); + if (result->mapToMemory(ErrorMessage)) + return 0; + if (!result->loadSymbolTable(ErrorMessage)) + return 0; + return result.release(); +} + +// Look up one symbol in the symbol table and return the module that defines +// that symbol. +Module* +Archive::findModuleDefiningSymbol(const std::string& symbol, + std::string* ErrMsg) { + SymTabType::iterator SI = symTab.find(symbol); + if (SI == symTab.end()) + return 0; + + // The symbol table was previously constructed assuming that the members were + // written without the symbol table header. Because VBR encoding is used, the + // values could not be adjusted to account for the offset of the symbol table + // because that could affect the size of the symbol table due to VBR encoding. + // We now have to account for this by adjusting the offset by the size of the + // symbol table and its header. + unsigned fileOffset = + SI->second + // offset in symbol-table-less file + firstFileOffset; // add offset to first "real" file in archive + + // See if the module is already loaded + ModuleMap::iterator MI = modules.find(fileOffset); + if (MI != modules.end()) + return MI->second.first; + + // Module hasn't been loaded yet, we need to load it + const char* modptr = base + fileOffset; + ArchiveMember* mbr = parseMemberHeader(modptr, mapfile->getBufferEnd(), + ErrMsg); + if (!mbr) + return 0; + + // Now, load the bitcode module to get the Module. + std::string FullMemberName = archPath.str() + "(" + + mbr->getPath().str() + ")"; + MemoryBuffer *Buffer = + MemoryBuffer::getMemBufferCopy(StringRef(mbr->getData(), mbr->getSize()), + FullMemberName.c_str()); + + Module *m = getLazyBitcodeModule(Buffer, Context, ErrMsg); + if (!m) + return 0; + + modules.insert(std::make_pair(fileOffset, std::make_pair(m, mbr))); + + return m; +} + +// Look up multiple symbols in the symbol table and return a set of +// Modules that define those symbols. +bool +Archive::findModulesDefiningSymbols(std::set& symbols, + std::set& result, + std::string* error) { + if (!mapfile || !base) { + if (error) + *error = "Empty archive invalid for finding modules defining symbols"; + return false; + } + + if (symTab.empty()) { + // We don't have a symbol table, so we must build it now but lets also + // make sure that we populate the modules table as we do this to ensure + // that we don't load them twice when findModuleDefiningSymbol is called + // below. + + // Get a pointer to the first file + const char* At = base + firstFileOffset; + const char* End = mapfile->getBufferEnd(); + + while ( At < End) { + // Compute the offset to be put in the symbol table + unsigned offset = At - base - firstFileOffset; + + // Parse the file's header + ArchiveMember* mbr = parseMemberHeader(At, End, error); + if (!mbr) + return false; + + // If it contains symbols + if (mbr->isBitcode()) { + // Get the symbols + std::vector symbols; + std::string FullMemberName = archPath.str() + "(" + + mbr->getPath().str() + ")"; + Module* M = + GetBitcodeSymbols(At, mbr->getSize(), FullMemberName, Context, + symbols, error); + + if (M) { + // Insert the module's symbols into the symbol table + for (std::vector::iterator I = symbols.begin(), + E=symbols.end(); I != E; ++I ) { + symTab.insert(std::make_pair(*I, offset)); + } + // Insert the Module and the ArchiveMember into the table of + // modules. + modules.insert(std::make_pair(offset, std::make_pair(M, mbr))); + } else { + if (error) + *error = "Can't parse bitcode member: " + + mbr->getPath().str() + ": " + *error; + delete mbr; + return false; + } + } + + // Go to the next file location + At += mbr->getSize(); + if ((intptr_t(At) & 1) == 1) + At++; + } + } + + // At this point we have a valid symbol table (one way or another) so we + // just use it to quickly find the symbols requested. + + for (std::set::iterator I=symbols.begin(), + E=symbols.end(); I != E;) { + // See if this symbol exists + Module* m = findModuleDefiningSymbol(*I,error); + if (m) { + // The symbol exists, insert the Module into our result, duplicates will + // be ignored. + result.insert(m); + + // Remove the symbol now that its been resolved, being careful to + // post-increment the iterator. + symbols.erase(I++); + } else { + ++I; + } + } + return true; +} + +bool Archive::isBitcodeArchive() { + // Make sure the symTab has been loaded. In most cases this should have been + // done when the archive was constructed, but still, this is just in case. + if (symTab.empty()) + if (!loadSymbolTable(0)) + return false; + + // Now that we know it's been loaded, return true + // if it has a size + if (symTab.size()) return true; + + // We still can't be sure it isn't a bitcode archive + if (!loadArchive(0)) + return false; + + std::vector Modules; + std::string ErrorMessage; + + // Scan the archive, trying to load a bitcode member. We only load one to + // see if this works. + for (iterator I = begin(), E = end(); I != E; ++I) { + if (!I->isBitcode()) + continue; + + std::string FullMemberName = + archPath.str() + "(" + I->getPath().str() + ")"; + + MemoryBuffer *Buffer = + MemoryBuffer::getMemBufferCopy(StringRef(I->getData(), I->getSize()), + FullMemberName.c_str()); + Module *M = ParseBitcodeFile(Buffer, Context); + delete Buffer; + if (!M) + return false; // Couldn't parse bitcode, not a bitcode archive. + delete M; + return true; + } + + return false; +} diff --git a/final/lib/Archive/ArchiveWriter.cpp b/final/lib/Archive/ArchiveWriter.cpp new file mode 100644 index 00000000000..8fcc7aa29cc --- /dev/null +++ b/final/lib/Archive/ArchiveWriter.cpp @@ -0,0 +1,489 @@ +//===-- ArchiveWriter.cpp - Write LLVM archive files ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Builds up an LLVM archive file (.a) containing LLVM bitcode. +// +//===----------------------------------------------------------------------===// + +#include "ArchiveInternals.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" +#include +#include +#include +using namespace llvm; + +// Write an integer using variable bit rate encoding. This saves a few bytes +// per entry in the symbol table. +static inline void writeInteger(unsigned num, std::ofstream& ARFile) { + while (1) { + if (num < 0x80) { // done? + ARFile << (unsigned char)num; + return; + } + + // Nope, we are bigger than a character, output the next 7 bits and set the + // high bit to say that there is more coming... + ARFile << (unsigned char)(0x80 | ((unsigned char)num & 0x7F)); + num >>= 7; // Shift out 7 bits now... + } +} + +// Compute how many bytes are taken by a given VBR encoded value. This is needed +// to pre-compute the size of the symbol table. +static inline unsigned numVbrBytes(unsigned num) { + + // Note that the following nested ifs are somewhat equivalent to a binary + // search. We split it in half by comparing against 2^14 first. This allows + // most reasonable values to be done in 2 comparisons instead of 1 for + // small ones and four for large ones. We expect this to access file offsets + // in the 2^10 to 2^24 range and symbol lengths in the 2^0 to 2^8 range, + // so this approach is reasonable. + if (num < 1<<14) { + if (num < 1<<7) + return 1; + else + return 2; + } + if (num < 1<<21) + return 3; + + if (num < 1<<28) + return 4; + return 5; // anything >= 2^28 takes 5 bytes +} + +// Create an empty archive. +Archive* Archive::CreateEmpty(const sys::Path& FilePath, LLVMContext& C) { + Archive* result = new Archive(FilePath, C); + return result; +} + +// Fill the ArchiveMemberHeader with the information from a member. If +// TruncateNames is true, names are flattened to 15 chars or less. The sz field +// is provided here instead of coming from the mbr because the member might be +// stored compressed and the compressed size is not the ArchiveMember's size. +// Furthermore compressed files have negative size fields to identify them as +// compressed. +bool +Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, + int sz, bool TruncateNames) const { + + // Set the permissions mode, uid and gid + hdr.init(); + char buffer[32]; + sprintf(buffer, "%-8o", mbr.getMode()); + memcpy(hdr.mode,buffer,8); + sprintf(buffer, "%-6u", mbr.getUser()); + memcpy(hdr.uid,buffer,6); + sprintf(buffer, "%-6u", mbr.getGroup()); + memcpy(hdr.gid,buffer,6); + + // Set the last modification date + uint64_t secondsSinceEpoch = mbr.getModTime().toEpochTime(); + sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch)); + memcpy(hdr.date,buffer,12); + + // Get rid of trailing blanks in the name + std::string mbrPath = mbr.getPath().str(); + size_t mbrLen = mbrPath.length(); + while (mbrLen > 0 && mbrPath[mbrLen-1] == ' ') { + mbrPath.erase(mbrLen-1,1); + mbrLen--; + } + + // Set the name field in one of its various flavors. + bool writeLongName = false; + if (mbr.isStringTable()) { + memcpy(hdr.name,ARFILE_STRTAB_NAME,16); + } else if (mbr.isSVR4SymbolTable()) { + memcpy(hdr.name,ARFILE_SVR4_SYMTAB_NAME,16); + } else if (mbr.isBSD4SymbolTable()) { + memcpy(hdr.name,ARFILE_BSD4_SYMTAB_NAME,16); + } else if (mbr.isLLVMSymbolTable()) { + memcpy(hdr.name,ARFILE_LLVM_SYMTAB_NAME,16); + } else if (TruncateNames) { + const char* nm = mbrPath.c_str(); + unsigned len = mbrPath.length(); + size_t slashpos = mbrPath.rfind('/'); + if (slashpos != std::string::npos) { + nm += slashpos + 1; + len -= slashpos +1; + } + if (len > 15) + len = 15; + memcpy(hdr.name,nm,len); + hdr.name[len] = '/'; + } else if (mbrPath.length() < 16 && mbrPath.find('/') == std::string::npos) { + memcpy(hdr.name,mbrPath.c_str(),mbrPath.length()); + hdr.name[mbrPath.length()] = '/'; + } else { + std::string nm = "#1/"; + nm += utostr(mbrPath.length()); + memcpy(hdr.name,nm.data(),nm.length()); + if (sz < 0) + sz -= mbrPath.length(); + else + sz += mbrPath.length(); + writeLongName = true; + } + + // Set the size field + if (sz < 0) { + buffer[0] = '-'; + sprintf(&buffer[1],"%-9u",(unsigned)-sz); + } else { + sprintf(buffer, "%-10u", (unsigned)sz); + } + memcpy(hdr.size,buffer,10); + + return writeLongName; +} + +// Insert a file into the archive before some other member. This also takes care +// of extracting the necessary flags and information from the file. +bool +Archive::addFileBefore(const sys::Path& filePath, iterator where, + std::string* ErrMsg) { + bool Exists; + if (sys::fs::exists(filePath.str(), Exists) || !Exists) { + if (ErrMsg) + *ErrMsg = "Can not add a non-existent file to archive"; + return true; + } + + ArchiveMember* mbr = new ArchiveMember(this); + + mbr->data = 0; + mbr->path = filePath; + const sys::FileStatus *FSInfo = mbr->path.getFileStatus(false, ErrMsg); + if (!FSInfo) { + delete mbr; + return true; + } + mbr->info = *FSInfo; + + unsigned flags = 0; + bool hasSlash = filePath.str().find('/') != std::string::npos; + if (hasSlash) + flags |= ArchiveMember::HasPathFlag; + if (hasSlash || filePath.str().length() > 15) + flags |= ArchiveMember::HasLongFilenameFlag; + + sys::LLVMFileType type; + if (sys::fs::identify_magic(mbr->path.str(), type)) + type = sys::Unknown_FileType; + switch (type) { + case sys::Bitcode_FileType: + flags |= ArchiveMember::BitcodeFlag; + break; + default: + break; + } + mbr->flags = flags; + members.insert(where,mbr); + return false; +} + +// Write one member out to the file. +bool +Archive::writeMember( + const ArchiveMember& member, + std::ofstream& ARFile, + bool CreateSymbolTable, + bool TruncateNames, + bool ShouldCompress, + std::string* ErrMsg +) { + + unsigned filepos = ARFile.tellp(); + filepos -= 8; + + // Get the data and its size either from the + // member's in-memory data or directly from the file. + size_t fSize = member.getSize(); + const char *data = (const char*)member.getData(); + MemoryBuffer *mFile = 0; + if (!data) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFile(member.getPath().c_str(), File)) { + if (ErrMsg) + *ErrMsg = ec.message(); + return true; + } + mFile = File.take(); + data = mFile->getBufferStart(); + fSize = mFile->getBufferSize(); + } + + // Now that we have the data in memory, update the + // symbol table if it's a bitcode file. + if (CreateSymbolTable && member.isBitcode()) { + std::vector symbols; + std::string FullMemberName = archPath.str() + "(" + member.getPath().str() + + ")"; + Module* M = + GetBitcodeSymbols(data, fSize, FullMemberName, Context, symbols, ErrMsg); + + // If the bitcode parsed successfully + if ( M ) { + for (std::vector::iterator SI = symbols.begin(), + SE = symbols.end(); SI != SE; ++SI) { + + std::pair Res = + symTab.insert(std::make_pair(*SI,filepos)); + + if (Res.second) { + symTabSize += SI->length() + + numVbrBytes(SI->length()) + + numVbrBytes(filepos); + } + } + // We don't need this module any more. + delete M; + } else { + delete mFile; + if (ErrMsg) + *ErrMsg = "Can't parse bitcode member: " + member.getPath().str() + + ": " + *ErrMsg; + return true; + } + } + + int hdrSize = fSize; + + // Compute the fields of the header + ArchiveMemberHeader Hdr; + bool writeLongName = fillHeader(member,Hdr,hdrSize,TruncateNames); + + // Write header to archive file + ARFile.write((char*)&Hdr, sizeof(Hdr)); + + // Write the long filename if its long + if (writeLongName) { + ARFile.write(member.getPath().str().data(), + member.getPath().str().length()); + } + + // Write the (possibly compressed) member's content to the file. + ARFile.write(data,fSize); + + // Make sure the member is an even length + if ((ARFile.tellp() & 1) == 1) + ARFile << ARFILE_PAD; + + // Close the mapped file if it was opened + delete mFile; + return false; +} + +// Write out the LLVM symbol table as an archive member to the file. +void +Archive::writeSymbolTable(std::ofstream& ARFile) { + + // Construct the symbol table's header + ArchiveMemberHeader Hdr; + Hdr.init(); + memcpy(Hdr.name,ARFILE_LLVM_SYMTAB_NAME,16); + uint64_t secondsSinceEpoch = sys::TimeValue::now().toEpochTime(); + char buffer[32]; + sprintf(buffer, "%-8o", 0644); + memcpy(Hdr.mode,buffer,8); + sprintf(buffer, "%-6u", sys::Process::GetCurrentUserId()); + memcpy(Hdr.uid,buffer,6); + sprintf(buffer, "%-6u", sys::Process::GetCurrentGroupId()); + memcpy(Hdr.gid,buffer,6); + sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch)); + memcpy(Hdr.date,buffer,12); + sprintf(buffer,"%-10u",symTabSize); + memcpy(Hdr.size,buffer,10); + + // Write the header + ARFile.write((char*)&Hdr, sizeof(Hdr)); + +#ifndef NDEBUG + // Save the starting position of the symbol tables data content. + unsigned startpos = ARFile.tellp(); +#endif + + // Write out the symbols sequentially + for ( Archive::SymTabType::iterator I = symTab.begin(), E = symTab.end(); + I != E; ++I) + { + // Write out the file index + writeInteger(I->second, ARFile); + // Write out the length of the symbol + writeInteger(I->first.length(), ARFile); + // Write out the symbol + ARFile.write(I->first.data(), I->first.length()); + } + +#ifndef NDEBUG + // Now that we're done with the symbol table, get the ending file position + unsigned endpos = ARFile.tellp(); +#endif + + // Make sure that the amount we wrote is what we pre-computed. This is + // critical for file integrity purposes. + assert(endpos - startpos == symTabSize && "Invalid symTabSize computation"); + + // Make sure the symbol table is even sized + if (symTabSize % 2 != 0 ) + ARFile << ARFILE_PAD; +} + +// Write the entire archive to the file specified when the archive was created. +// This writes to a temporary file first. Options are for creating a symbol +// table, flattening the file names (no directories, 15 chars max) and +// compressing each archive member. +bool +Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, + std::string* ErrMsg) +{ + // Make sure they haven't opened up the file, not loaded it, + // but are now trying to write it which would wipe out the file. + if (members.empty() && mapfile && mapfile->getBufferSize() > 8) { + if (ErrMsg) + *ErrMsg = "Can't write an archive not opened for writing"; + return true; + } + + // Create a temporary file to store the archive in + sys::Path TmpArchive = archPath; + if (TmpArchive.createTemporaryFileOnDisk(ErrMsg)) + return true; + + // Make sure the temporary gets removed if we crash + sys::RemoveFileOnSignal(TmpArchive); + + // Create archive file for output. + std::ios::openmode io_mode = std::ios::out | std::ios::trunc | + std::ios::binary; + std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode); + + // Check for errors opening or creating archive file. + if (!ArchiveFile.is_open() || ArchiveFile.bad()) { + TmpArchive.eraseFromDisk(); + if (ErrMsg) + *ErrMsg = "Error opening archive file: " + archPath.str(); + return true; + } + + // If we're creating a symbol table, reset it now + if (CreateSymbolTable) { + symTabSize = 0; + symTab.clear(); + } + + // Write magic string to archive. + ArchiveFile << ARFILE_MAGIC; + + // Loop over all member files, and write them out. Note that this also + // builds the symbol table, symTab. + for (MembersList::iterator I = begin(), E = end(); I != E; ++I) { + if (writeMember(*I, ArchiveFile, CreateSymbolTable, + TruncateNames, Compress, ErrMsg)) { + TmpArchive.eraseFromDisk(); + ArchiveFile.close(); + return true; + } + } + + // Close archive file. + ArchiveFile.close(); + + // Write the symbol table + if (CreateSymbolTable) { + // At this point we have written a file that is a legal archive but it + // doesn't have a symbol table in it. To aid in faster reading and to + // ensure compatibility with other archivers we need to put the symbol + // table first in the file. Unfortunately, this means mapping the file + // we just wrote back in and copying it to the destination file. + sys::Path FinalFilePath = archPath; + + // Map in the archive we just wrote. + { + OwningPtr arch; + if (error_code ec = MemoryBuffer::getFile(TmpArchive.c_str(), arch)) { + if (ErrMsg) + *ErrMsg = ec.message(); + return true; + } + const char* base = arch->getBufferStart(); + + // Open another temporary file in order to avoid invalidating the + // mmapped data + if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg)) + return true; + sys::RemoveFileOnSignal(FinalFilePath); + + std::ofstream FinalFile(FinalFilePath.c_str(), io_mode); + if (!FinalFile.is_open() || FinalFile.bad()) { + TmpArchive.eraseFromDisk(); + if (ErrMsg) + *ErrMsg = "Error opening archive file: " + FinalFilePath.str(); + return true; + } + + // Write the file magic number + FinalFile << ARFILE_MAGIC; + + // If there is a foreign symbol table, put it into the file now. Most + // ar(1) implementations require the symbol table to be first but llvm-ar + // can deal with it being after a foreign symbol table. This ensures + // compatibility with other ar(1) implementations as well as allowing the + // archive to store both native .o and LLVM .bc files, both indexed. + if (foreignST) { + if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) { + FinalFile.close(); + TmpArchive.eraseFromDisk(); + return true; + } + } + + // Put out the LLVM symbol table now. + writeSymbolTable(FinalFile); + + // Copy the temporary file contents being sure to skip the file's magic + // number. + FinalFile.write(base + sizeof(ARFILE_MAGIC)-1, + arch->getBufferSize()-sizeof(ARFILE_MAGIC)+1); + + // Close up shop + FinalFile.close(); + } // free arch. + + // Move the final file over top of TmpArchive + if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg)) + return true; + } + + // Before we replace the actual archive, we need to forget all the + // members, since they point to data in that old archive. We need to do + // this because we cannot replace an open file on Windows. + cleanUpMemory(); + + if (TmpArchive.renamePathOnDisk(archPath, ErrMsg)) + return true; + + // Set correct read and write permissions after temporary file is moved + // to final destination path. + if (archPath.makeReadableOnDisk(ErrMsg)) + return true; + if (archPath.makeWriteableOnDisk(ErrMsg)) + return true; + + return false; +} diff --git a/final/lib/Archive/CMakeLists.txt b/final/lib/Archive/CMakeLists.txt new file mode 100644 index 00000000000..7ff478a41a5 --- /dev/null +++ b/final/lib/Archive/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_library(LLVMArchive + Archive.cpp + ArchiveReader.cpp + ArchiveWriter.cpp + ) diff --git a/final/lib/Archive/Makefile b/final/lib/Archive/Makefile new file mode 100644 index 00000000000..da9780403a0 --- /dev/null +++ b/final/lib/Archive/Makefile @@ -0,0 +1,17 @@ +##===- lib/Archive/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMArchive + +# We only want an archive so only those modules actually used by a tool are +# included. +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/final/lib/AsmParser/CMakeLists.txt b/final/lib/AsmParser/CMakeLists.txt new file mode 100644 index 00000000000..985ebe20098 --- /dev/null +++ b/final/lib/AsmParser/CMakeLists.txt @@ -0,0 +1,6 @@ +# AsmParser +add_llvm_library(LLVMAsmParser + LLLexer.cpp + LLParser.cpp + Parser.cpp + ) diff --git a/final/lib/AsmParser/LLLexer.cpp b/final/lib/AsmParser/LLLexer.cpp new file mode 100644 index 00000000000..857fa1ef626 --- /dev/null +++ b/final/lib/AsmParser/LLLexer.cpp @@ -0,0 +1,874 @@ +//===- LLLexer.cpp - Lexer for .ll Files ----------------------------------===// +// +// 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 .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLLexer.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instruction.h" +#include "llvm/LLVMContext.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Assembly/Parser.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +using namespace llvm; + +bool LLLexer::Error(LocTy ErrorLoc, const Twine &Msg) const { + ErrorInfo = SM.GetMessage(ErrorLoc, Msg, "error"); + return true; +} + +//===----------------------------------------------------------------------===// +// Helper functions. +//===----------------------------------------------------------------------===// + +// atoull - Convert an ascii string of decimal digits into the unsigned long +// long representation... this does not have to do input error checking, +// because we know that the input will be matched by a suitable regex... +// +uint64_t LLLexer::atoull(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; Buffer++) { + uint64_t OldRes = Result; + Result *= 10; + Result += *Buffer-'0'; + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; ++Buffer) { + uint64_t OldRes = Result; + Result *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Result += C-'0'; + else if (C >= 'A' && C <= 'F') + Result += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Result += C-'a'+10; + + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +void LLLexer::HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + assert(Buffer != End); + Pair[0] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[0] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[0] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[0] += C-'a'+10; + } + Pair[1] = 0; + for (int i=0; i<16 && Buffer != End; i++, Buffer++) { + Pair[1] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[1] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[1] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[1] += C-'a'+10; + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +/// FP80HexToIntPair - translate an 80 bit FP80 number (20 hexits) into +/// { low64, high16 } as usual for an APInt. +void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[1] = 0; + for (int i=0; i<4 && Buffer != End; i++, Buffer++) { + assert(Buffer != End); + Pair[1] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[1] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[1] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[1] += C-'a'+10; + } + Pair[0] = 0; + for (int i=0; i<16; i++, Buffer++) { + Pair[0] *= 16; + char C = *Buffer; + if (C >= '0' && C <= '9') + Pair[0] += C-'0'; + else if (C >= 'A' && C <= 'F') + Pair[0] += C-'A'+10; + else if (C >= 'a' && C <= 'f') + Pair[0] += C-'a'+10; + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +// UnEscapeLexed - Run through the specified buffer and change \xx codes to the +// appropriate character. +static void UnEscapeLexed(std::string &Str) { + if (Str.empty()) return; + + char *Buffer = &Str[0], *EndBuffer = Buffer+Str.size(); + char *BOut = Buffer; + for (char *BIn = Buffer; BIn != EndBuffer; ) { + if (BIn[0] == '\\') { + if (BIn < EndBuffer-1 && BIn[1] == '\\') { + *BOut++ = '\\'; // Two \ becomes one + BIn += 2; + } else if (BIn < EndBuffer-2 && isxdigit(BIn[1]) && isxdigit(BIn[2])) { + char Tmp = BIn[3]; BIn[3] = 0; // Terminate string + *BOut = (char)strtol(BIn+1, 0, 16); // Convert to number + BIn[3] = Tmp; // Restore character + BIn += 3; // Skip over handled chars + ++BOut; + } else { + *BOut++ = *BIn++; + } + } else { + *BOut++ = *BIn++; + } + } + Str.resize(BOut-Buffer); +} + +/// isLabelChar - Return true for [-a-zA-Z$._0-9]. +static bool isLabelChar(char C) { + return isalnum(C) || C == '-' || C == '$' || C == '.' || C == '_'; +} + + +/// isLabelTail - Return true if this pointer points to a valid end of a label. +static const char *isLabelTail(const char *CurPtr) { + while (1) { + if (CurPtr[0] == ':') return CurPtr+1; + if (!isLabelChar(CurPtr[0])) return 0; + ++CurPtr; + } +} + + + +//===----------------------------------------------------------------------===// +// Lexer definition. +//===----------------------------------------------------------------------===// + +LLLexer::LLLexer(MemoryBuffer *StartBuf, SourceMgr &sm, SMDiagnostic &Err, + LLVMContext &C) + : CurBuf(StartBuf), ErrorInfo(Err), SM(sm), Context(C), APFloatVal(0.0) { + CurPtr = CurBuf->getBufferStart(); +} + +std::string LLLexer::getFilename() const { + return CurBuf->getBufferIdentifier(); +} + +int LLLexer::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. + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } +} + + +lltok::Kind LLLexer::LexToken() { + TokStart = CurPtr; + + int CurChar = getNextChar(); + switch (CurChar) { + default: + // Handle letters: [a-zA-Z_] + if (isalpha(CurChar) || CurChar == '_') + return LexIdentifier(); + + return lltok::Error; + case EOF: return lltok::Eof; + case 0: + case ' ': + case '\t': + case '\n': + case '\r': + // Ignore whitespace. + return LexToken(); + case '+': return LexPositive(); + case '@': return LexAt(); + case '%': return LexPercent(); + case '"': return LexQuote(); + case '.': + if (const char *Ptr = isLabelTail(CurPtr)) { + CurPtr = Ptr; + StrVal.assign(TokStart, CurPtr-1); + return lltok::LabelStr; + } + if (CurPtr[0] == '.' && CurPtr[1] == '.') { + CurPtr += 2; + return lltok::dotdotdot; + } + return lltok::Error; + case '$': + if (const char *Ptr = isLabelTail(CurPtr)) { + CurPtr = Ptr; + StrVal.assign(TokStart, CurPtr-1); + return lltok::LabelStr; + } + return lltok::Error; + case ';': + SkipLineComment(); + return LexToken(); + case '!': return LexExclaim(); + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': + return LexDigitOrNegative(); + case '=': return lltok::equal; + case '[': return lltok::lsquare; + case ']': return lltok::rsquare; + case '{': return lltok::lbrace; + case '}': return lltok::rbrace; + case '<': return lltok::less; + case '>': return lltok::greater; + case '(': return lltok::lparen; + case ')': return lltok::rparen; + case ',': return lltok::comma; + case '*': return lltok::star; + case '\\': return lltok::backslash; + } +} + +void LLLexer::SkipLineComment() { + while (1) { + if (CurPtr[0] == '\n' || CurPtr[0] == '\r' || getNextChar() == EOF) + return; + } +} + +/// LexAt - Lex all tokens that start with an @ character: +/// GlobalVar @\"[^\"]*\" +/// GlobalVar @[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// GlobalVarID @[0-9]+ +lltok::Kind LLLexer::LexAt() { + // Handle AtStringConstant: @\"[^\"]*\" + if (CurPtr[0] == '"') { + ++CurPtr; + + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in global variable name"); + return lltok::Error; + } + if (CurChar == '"') { + StrVal.assign(TokStart+2, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::GlobalVar; + } + } + } + + // Handle GlobalVarName: @[-a-zA-Z$._][-a-zA-Z$._0-9]* + if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip @ + return lltok::GlobalVar; + } + + // Handle GlobalVarID: @[0-9]+ + if (isdigit(CurPtr[0])) { + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart+1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return lltok::GlobalID; + } + + return lltok::Error; +} + + +/// LexPercent - Lex all tokens that start with a % character: +/// LocalVar ::= %\"[^\"]*\" +/// LocalVar ::= %[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// LocalVarID ::= %[0-9]+ +lltok::Kind LLLexer::LexPercent() { + // Handle LocalVarName: %\"[^\"]*\" + if (CurPtr[0] == '"') { + ++CurPtr; + + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in string constant"); + return lltok::Error; + } + if (CurChar == '"') { + StrVal.assign(TokStart+2, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::LocalVar; + } + } + } + + // Handle LocalVarName: %[-a-zA-Z$._][-a-zA-Z$._0-9]* + if (isalpha(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip % + return lltok::LocalVar; + } + + // Handle LocalVarID: %[0-9]+ + if (isdigit(CurPtr[0])) { + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart+1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return lltok::LocalVarID; + } + + return lltok::Error; +} + +/// LexQuote - Lex all tokens that start with a " character: +/// QuoteLabel "[^"]+": +/// StringConstant "[^"]*" +lltok::Kind LLLexer::LexQuote() { + while (1) { + int CurChar = getNextChar(); + + if (CurChar == EOF) { + Error("end of file in quoted string"); + return lltok::Error; + } + + if (CurChar != '"') continue; + + if (CurPtr[0] != ':') { + StrVal.assign(TokStart+1, CurPtr-1); + UnEscapeLexed(StrVal); + return lltok::StringConstant; + } + + ++CurPtr; + StrVal.assign(TokStart+1, CurPtr-2); + UnEscapeLexed(StrVal); + return lltok::LabelStr; + } +} + +static bool JustWhitespaceNewLine(const char *&Ptr) { + const char *ThisPtr = Ptr; + while (*ThisPtr == ' ' || *ThisPtr == '\t') + ++ThisPtr; + if (*ThisPtr == '\n' || *ThisPtr == '\r') { + Ptr = ThisPtr; + return true; + } + return false; +} + +/// LexExclaim: +/// !foo +/// ! +lltok::Kind LLLexer::LexExclaim() { + // Lex a metadata name as a MetadataVar. + if (isalpha(CurPtr[0])) { + ++CurPtr; + while (isalnum(CurPtr[0]) || CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip ! + return lltok::MetadataVar; + } + return lltok::exclaim; +} + +/// LexIdentifier: Handle several related productions: +/// Label [-a-zA-Z$._0-9]+: +/// IntegerType i[0-9]+ +/// Keyword sdiv, float, ... +/// HexIntConstant [us]0x[0-9A-Fa-f]+ +lltok::Kind LLLexer::LexIdentifier() { + const char *StartChar = CurPtr; + const char *IntEnd = CurPtr[-1] == 'i' ? 0 : StartChar; + const char *KeywordEnd = 0; + + for (; isLabelChar(*CurPtr); ++CurPtr) { + // If we decide this is an integer, remember the end of the sequence. + if (!IntEnd && !isdigit(*CurPtr)) IntEnd = CurPtr; + if (!KeywordEnd && !isalnum(*CurPtr) && *CurPtr != '_') KeywordEnd = CurPtr; + } + + // If we stopped due to a colon, this really is a label. + if (*CurPtr == ':') { + StrVal.assign(StartChar-1, CurPtr++); + return lltok::LabelStr; + } + + // Otherwise, this wasn't a label. If this was valid as an integer type, + // return it. + if (IntEnd == 0) IntEnd = CurPtr; + if (IntEnd != StartChar) { + CurPtr = IntEnd; + uint64_t NumBits = atoull(StartChar, CurPtr); + if (NumBits < IntegerType::MIN_INT_BITS || + NumBits > IntegerType::MAX_INT_BITS) { + Error("bitwidth for integer type out of range!"); + return lltok::Error; + } + TyVal = IntegerType::get(Context, NumBits); + return lltok::Type; + } + + // Otherwise, this was a letter sequence. See which keyword this is. + if (KeywordEnd == 0) KeywordEnd = CurPtr; + CurPtr = KeywordEnd; + --StartChar; + unsigned Len = CurPtr-StartChar; +#define KEYWORD(STR) \ + if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) \ + return lltok::kw_##STR; + + KEYWORD(begin); KEYWORD(end); + KEYWORD(true); KEYWORD(false); + KEYWORD(declare); KEYWORD(define); + KEYWORD(global); KEYWORD(constant); + + KEYWORD(private); + KEYWORD(linker_private); + KEYWORD(linker_private_weak); + KEYWORD(linker_private_weak_def_auto); + KEYWORD(internal); + KEYWORD(available_externally); + KEYWORD(linkonce); + KEYWORD(linkonce_odr); + KEYWORD(weak); + KEYWORD(weak_odr); + KEYWORD(appending); + KEYWORD(dllimport); + KEYWORD(dllexport); + KEYWORD(common); + KEYWORD(default); + KEYWORD(hidden); + KEYWORD(protected); + KEYWORD(unnamed_addr); + KEYWORD(extern_weak); + KEYWORD(external); + KEYWORD(thread_local); + KEYWORD(zeroinitializer); + KEYWORD(undef); + KEYWORD(null); + KEYWORD(to); + KEYWORD(tail); + KEYWORD(target); + KEYWORD(triple); + KEYWORD(deplibs); + KEYWORD(datalayout); + KEYWORD(volatile); + KEYWORD(nuw); + KEYWORD(nsw); + KEYWORD(exact); + KEYWORD(inbounds); + KEYWORD(align); + KEYWORD(addrspace); + KEYWORD(section); + KEYWORD(alias); + KEYWORD(module); + KEYWORD(asm); + KEYWORD(sideeffect); + KEYWORD(alignstack); + KEYWORD(gc); + + KEYWORD(ccc); + KEYWORD(fastcc); + KEYWORD(coldcc); + KEYWORD(x86_stdcallcc); + KEYWORD(x86_fastcallcc); + KEYWORD(x86_thiscallcc); + KEYWORD(arm_apcscc); + KEYWORD(arm_aapcscc); + KEYWORD(arm_aapcs_vfpcc); + KEYWORD(msp430_intrcc); + KEYWORD(ptx_kernel); + KEYWORD(ptx_device); + + KEYWORD(cc); + KEYWORD(c); + + KEYWORD(signext); + KEYWORD(zeroext); + KEYWORD(inreg); + KEYWORD(sret); + KEYWORD(nounwind); + KEYWORD(noreturn); + KEYWORD(noalias); + KEYWORD(nocapture); + KEYWORD(byval); + KEYWORD(nest); + KEYWORD(readnone); + KEYWORD(readonly); + + KEYWORD(inlinehint); + KEYWORD(noinline); + KEYWORD(alwaysinline); + KEYWORD(optsize); + KEYWORD(ssp); + KEYWORD(sspreq); + KEYWORD(noredzone); + KEYWORD(noimplicitfloat); + KEYWORD(naked); + KEYWORD(hotpatch); + + KEYWORD(type); + KEYWORD(opaque); + + KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle); + KEYWORD(sge); KEYWORD(ult); KEYWORD(ugt); KEYWORD(ule); KEYWORD(uge); + KEYWORD(oeq); KEYWORD(one); KEYWORD(olt); KEYWORD(ogt); KEYWORD(ole); + KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une); + + KEYWORD(x); + KEYWORD(blockaddress); +#undef KEYWORD + + // Keywords for types. +#define TYPEKEYWORD(STR, LLVMTY) \ + if (Len == strlen(STR) && !memcmp(StartChar, STR, strlen(STR))) { \ + TyVal = LLVMTY; return lltok::Type; } + TYPEKEYWORD("void", Type::getVoidTy(Context)); + TYPEKEYWORD("float", Type::getFloatTy(Context)); + TYPEKEYWORD("double", Type::getDoubleTy(Context)); + TYPEKEYWORD("x86_fp80", Type::getX86_FP80Ty(Context)); + TYPEKEYWORD("fp128", Type::getFP128Ty(Context)); + TYPEKEYWORD("ppc_fp128", Type::getPPC_FP128Ty(Context)); + TYPEKEYWORD("label", Type::getLabelTy(Context)); + TYPEKEYWORD("metadata", Type::getMetadataTy(Context)); + TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context)); +#undef TYPEKEYWORD + + // Handle special forms for autoupgrading. Drop these in LLVM 3.0. This is + // to avoid conflicting with the sext/zext instructions, below. + if (Len == 4 && !memcmp(StartChar, "sext", 4)) { + // Scan CurPtr ahead, seeing if there is just whitespace before the newline. + if (JustWhitespaceNewLine(CurPtr)) + return lltok::kw_signext; + } else if (Len == 4 && !memcmp(StartChar, "zext", 4)) { + // Scan CurPtr ahead, seeing if there is just whitespace before the newline. + if (JustWhitespaceNewLine(CurPtr)) + return lltok::kw_zeroext; + } else if (Len == 6 && !memcmp(StartChar, "malloc", 6)) { + // FIXME: Remove in LLVM 3.0. + // Autoupgrade malloc instruction. + return lltok::kw_malloc; + } else if (Len == 4 && !memcmp(StartChar, "free", 4)) { + // FIXME: Remove in LLVM 3.0. + // Autoupgrade malloc instruction. + return lltok::kw_free; + } + + // Keywords for instructions. +#define INSTKEYWORD(STR, Enum) \ + if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) { \ + UIntVal = Instruction::Enum; return lltok::kw_##STR; } + + INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd); + INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub); + INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul); + INSTKEYWORD(udiv, UDiv); INSTKEYWORD(sdiv, SDiv); INSTKEYWORD(fdiv, FDiv); + INSTKEYWORD(urem, URem); INSTKEYWORD(srem, SRem); INSTKEYWORD(frem, FRem); + INSTKEYWORD(shl, Shl); INSTKEYWORD(lshr, LShr); INSTKEYWORD(ashr, AShr); + INSTKEYWORD(and, And); INSTKEYWORD(or, Or); INSTKEYWORD(xor, Xor); + INSTKEYWORD(icmp, ICmp); INSTKEYWORD(fcmp, FCmp); + + INSTKEYWORD(phi, PHI); + INSTKEYWORD(call, Call); + INSTKEYWORD(trunc, Trunc); + INSTKEYWORD(zext, ZExt); + INSTKEYWORD(sext, SExt); + INSTKEYWORD(fptrunc, FPTrunc); + INSTKEYWORD(fpext, FPExt); + INSTKEYWORD(uitofp, UIToFP); + INSTKEYWORD(sitofp, SIToFP); + INSTKEYWORD(fptoui, FPToUI); + INSTKEYWORD(fptosi, FPToSI); + INSTKEYWORD(inttoptr, IntToPtr); + INSTKEYWORD(ptrtoint, PtrToInt); + INSTKEYWORD(bitcast, BitCast); + INSTKEYWORD(select, Select); + INSTKEYWORD(va_arg, VAArg); + INSTKEYWORD(ret, Ret); + INSTKEYWORD(br, Br); + INSTKEYWORD(switch, Switch); + INSTKEYWORD(indirectbr, IndirectBr); + INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(unwind, Unwind); + INSTKEYWORD(unreachable, Unreachable); + + INSTKEYWORD(alloca, Alloca); + INSTKEYWORD(load, Load); + INSTKEYWORD(store, Store); + INSTKEYWORD(getelementptr, GetElementPtr); + + INSTKEYWORD(extractelement, ExtractElement); + INSTKEYWORD(insertelement, InsertElement); + INSTKEYWORD(shufflevector, ShuffleVector); + INSTKEYWORD(getresult, ExtractValue); + INSTKEYWORD(extractvalue, ExtractValue); + INSTKEYWORD(insertvalue, InsertValue); +#undef INSTKEYWORD + + // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by + // the CFE to avoid forcing it to deal with 64-bit numbers. + if ((TokStart[0] == 'u' || TokStart[0] == 's') && + TokStart[1] == '0' && TokStart[2] == 'x' && isxdigit(TokStart[3])) { + int len = CurPtr-TokStart-3; + uint32_t bits = len * 4; + APInt Tmp(bits, StringRef(TokStart+3, len), 16); + uint32_t activeBits = Tmp.getActiveBits(); + if (activeBits > 0 && activeBits < bits) + Tmp = Tmp.trunc(activeBits); + APSIntVal = APSInt(Tmp, TokStart[0] == 'u'); + return lltok::APSInt; + } + + // If this is "cc1234", return this as just "cc". + if (TokStart[0] == 'c' && TokStart[1] == 'c') { + CurPtr = TokStart+2; + return lltok::kw_cc; + } + + // If this starts with "call", return it as CALL. This is to support old + // broken .ll files. FIXME: remove this with LLVM 3.0. + if (CurPtr-TokStart > 4 && !memcmp(TokStart, "call", 4)) { + CurPtr = TokStart+4; + UIntVal = Instruction::Call; + return lltok::kw_call; + } + + // Finally, if this isn't known, return an error. + CurPtr = TokStart+1; + return lltok::Error; +} + + +/// Lex0x: Handle productions that start with 0x, knowing that it matches and +/// that this is not a label: +/// HexFPConstant 0x[0-9A-Fa-f]+ +/// HexFP80Constant 0xK[0-9A-Fa-f]+ +/// HexFP128Constant 0xL[0-9A-Fa-f]+ +/// HexPPC128Constant 0xM[0-9A-Fa-f]+ +lltok::Kind LLLexer::Lex0x() { + CurPtr = TokStart + 2; + + char Kind; + if (CurPtr[0] >= 'K' && CurPtr[0] <= 'M') { + Kind = *CurPtr++; + } else { + Kind = 'J'; + } + + if (!isxdigit(CurPtr[0])) { + // Bad token, return it as an error. + CurPtr = TokStart+1; + return lltok::Error; + } + + while (isxdigit(CurPtr[0])) + ++CurPtr; + + if (Kind == 'J') { + // HexFPConstant - Floating point constant represented in IEEE format as a + // hexadecimal number for when exponential notation is not precise enough. + // Float and double only. + APFloatVal = APFloat(BitsToDouble(HexIntToVal(TokStart+2, CurPtr))); + return lltok::APFloat; + } + + uint64_t Pair[2]; + switch (Kind) { + default: llvm_unreachable("Unknown kind!"); + case 'K': + // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) + FP80HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(80, 2, Pair)); + return lltok::APFloat; + case 'L': + // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(128, 2, Pair), true); + return lltok::APFloat; + case 'M': + // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APInt(128, 2, Pair)); + return lltok::APFloat; + } +} + +/// LexIdentifier: Handle several related productions: +/// Label [-a-zA-Z$._0-9]+: +/// NInteger -[0-9]+ +/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? +/// PInteger [0-9]+ +/// HexFPConstant 0x[0-9A-Fa-f]+ +/// HexFP80Constant 0xK[0-9A-Fa-f]+ +/// HexFP128Constant 0xL[0-9A-Fa-f]+ +/// HexPPC128Constant 0xM[0-9A-Fa-f]+ +lltok::Kind LLLexer::LexDigitOrNegative() { + // If the letter after the negative is a number, this is probably a label. + if (!isdigit(TokStart[0]) && !isdigit(CurPtr[0])) { + // Okay, this is not a number after the -, it's probably a label. + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + + return lltok::Error; + } + + // At this point, it is either a label, int or fp constant. + + // Skip digits, we have at least one. + for (; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + // Check to see if this really is a label afterall, e.g. "-1:". + if (isLabelChar(CurPtr[0]) || CurPtr[0] == ':') { + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + } + + // If the next character is a '.', then it is a fp value, otherwise its + // integer. + if (CurPtr[0] != '.') { + if (TokStart[0] == '0' && TokStart[1] == 'x') + return Lex0x(); + unsigned Len = CurPtr-TokStart; + uint32_t numBits = ((Len * 64) / 19) + 2; + APInt Tmp(numBits, StringRef(TokStart, Len), 10); + if (TokStart[0] == '-') { + uint32_t minBits = Tmp.getMinSignedBits(); + if (minBits > 0 && minBits < numBits) + Tmp = Tmp.trunc(minBits); + APSIntVal = APSInt(Tmp, false); + } else { + uint32_t activeBits = Tmp.getActiveBits(); + if (activeBits > 0 && activeBits < numBits) + Tmp = Tmp.trunc(activeBits); + APSIntVal = APSInt(Tmp, true); + } + return lltok::APSInt; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(CurPtr[0])) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(CurPtr[1]) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + CurPtr += 2; + while (isdigit(CurPtr[0])) ++CurPtr; + } + } + + APFloatVal = APFloat(std::atof(TokStart)); + return lltok::APFloat; +} + +/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? +lltok::Kind LLLexer::LexPositive() { + // If the letter after the negative is a number, this is probably not a + // label. + if (!isdigit(CurPtr[0])) + return lltok::Error; + + // Skip digits. + for (++CurPtr; isdigit(CurPtr[0]); ++CurPtr) + /*empty*/; + + // At this point, we need a '.'. + if (CurPtr[0] != '.') { + CurPtr = TokStart+1; + return lltok::Error; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(CurPtr[0])) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(CurPtr[1]) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && isdigit(CurPtr[2]))) { + CurPtr += 2; + while (isdigit(CurPtr[0])) ++CurPtr; + } + } + + APFloatVal = APFloat(std::atof(TokStart)); + return lltok::APFloat; +} diff --git a/final/lib/AsmParser/LLLexer.h b/final/lib/AsmParser/LLLexer.h new file mode 100644 index 00000000000..09ae8017f40 --- /dev/null +++ b/final/lib/AsmParser/LLLexer.h @@ -0,0 +1,90 @@ +//===- LLLexer.h - Lexer for LLVM Assembly 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 .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LIB_ASMPARSER_LLLEXER_H +#define LIB_ASMPARSER_LLLEXER_H + +#include "LLToken.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/SourceMgr.h" +#include + +namespace llvm { + class MemoryBuffer; + class Type; + class SMDiagnostic; + class LLVMContext; + + class LLLexer { + const char *CurPtr; + MemoryBuffer *CurBuf; + SMDiagnostic &ErrorInfo; + SourceMgr &SM; + LLVMContext &Context; + + // Information about the current token. + const char *TokStart; + lltok::Kind CurKind; + std::string StrVal; + unsigned UIntVal; + const Type *TyVal; + APFloat APFloatVal; + APSInt APSIntVal; + + std::string TheError; + public: + explicit LLLexer(MemoryBuffer *StartBuf, SourceMgr &SM, SMDiagnostic &, + LLVMContext &C); + ~LLLexer() {} + + lltok::Kind Lex() { + return CurKind = LexToken(); + } + + typedef SMLoc LocTy; + LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); } + lltok::Kind getKind() const { return CurKind; } + const std::string &getStrVal() const { return StrVal; } + const Type *getTyVal() const { return TyVal; } + unsigned getUIntVal() const { return UIntVal; } + const APSInt &getAPSIntVal() const { return APSIntVal; } + const APFloat &getAPFloatVal() const { return APFloatVal; } + + + bool Error(LocTy L, const Twine &Msg) const; + bool Error(const Twine &Msg) const { return Error(getLoc(), Msg); } + std::string getFilename() const; + + private: + lltok::Kind LexToken(); + + int getNextChar(); + void SkipLineComment(); + lltok::Kind LexIdentifier(); + lltok::Kind LexDigitOrNegative(); + lltok::Kind LexPositive(); + lltok::Kind LexAt(); + lltok::Kind LexExclaim(); + lltok::Kind LexPercent(); + lltok::Kind LexQuote(); + lltok::Kind Lex0x(); + + uint64_t atoull(const char *Buffer, const char *End); + uint64_t HexIntToVal(const char *Buffer, const char *End); + void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); + void FP80HexToIntPair(const char *Buff, const char *End, uint64_t Pair[2]); + }; +} // end namespace llvm + +#endif diff --git a/final/lib/AsmParser/LLParser.cpp b/final/lib/AsmParser/LLParser.cpp new file mode 100644 index 00000000000..fc10c040547 --- /dev/null +++ b/final/lib/AsmParser/LLParser.cpp @@ -0,0 +1,3976 @@ +//===-- LLParser.cpp - Parser Class ---------------------------------------===// +// +// 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 parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLParser.h" +#include "llvm/AutoUpgrade.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// Run: module ::= toplevelentity* +bool LLParser::Run() { + // Prime the lexer. + Lex.Lex(); + + return ParseTopLevelEntities() || + ValidateEndOfModule(); +} + +/// ValidateEndOfModule - Do final validity and sanity checks at the end of the +/// module. +bool LLParser::ValidateEndOfModule() { + // Handle any instruction metadata forward references. + if (!ForwardRefInstMetadata.empty()) { + for (DenseMap >::iterator + I = ForwardRefInstMetadata.begin(), E = ForwardRefInstMetadata.end(); + I != E; ++I) { + Instruction *Inst = I->first; + const std::vector &MDList = I->second; + + for (unsigned i = 0, e = MDList.size(); i != e; ++i) { + unsigned SlotNo = MDList[i].MDSlot; + + if (SlotNo >= NumberedMetadata.size() || NumberedMetadata[SlotNo] == 0) + return Error(MDList[i].Loc, "use of undefined metadata '!" + + Twine(SlotNo) + "'"); + Inst->setMetadata(MDList[i].MDKind, NumberedMetadata[SlotNo]); + } + } + ForwardRefInstMetadata.clear(); + } + + + // Update auto-upgraded malloc calls to "malloc". + // FIXME: Remove in LLVM 3.0. + if (MallocF) { + MallocF->setName("malloc"); + // If setName() does not set the name to "malloc", then there is already a + // declaration of "malloc". In that case, iterate over all calls to MallocF + // and get them to call the declared "malloc" instead. + if (MallocF->getName() != "malloc") { + Constant *RealMallocF = M->getFunction("malloc"); + if (RealMallocF->getType() != MallocF->getType()) + RealMallocF = ConstantExpr::getBitCast(RealMallocF, MallocF->getType()); + MallocF->replaceAllUsesWith(RealMallocF); + MallocF->eraseFromParent(); + MallocF = NULL; + } + } + + + // If there are entries in ForwardRefBlockAddresses at this point, they are + // references after the function was defined. Resolve those now. + while (!ForwardRefBlockAddresses.empty()) { + // Okay, we are referencing an already-parsed function, resolve them now. + Function *TheFn = 0; + const ValID &Fn = ForwardRefBlockAddresses.begin()->first; + if (Fn.Kind == ValID::t_GlobalName) + TheFn = M->getFunction(Fn.StrVal); + else if (Fn.UIntVal < NumberedVals.size()) + TheFn = dyn_cast(NumberedVals[Fn.UIntVal]); + + if (TheFn == 0) + return Error(Fn.Loc, "unknown function referenced by blockaddress"); + + // Resolve all these references. + if (ResolveForwardRefBlockAddresses(TheFn, + ForwardRefBlockAddresses.begin()->second, + 0)) + return true; + + ForwardRefBlockAddresses.erase(ForwardRefBlockAddresses.begin()); + } + + + if (!ForwardRefTypes.empty()) + return Error(ForwardRefTypes.begin()->second.second, + "use of undefined type named '" + + ForwardRefTypes.begin()->first + "'"); + if (!ForwardRefTypeIDs.empty()) + return Error(ForwardRefTypeIDs.begin()->second.second, + "use of undefined type '%" + + Twine(ForwardRefTypeIDs.begin()->first) + "'"); + + if (!ForwardRefVals.empty()) + return Error(ForwardRefVals.begin()->second.second, + "use of undefined value '@" + ForwardRefVals.begin()->first + + "'"); + + if (!ForwardRefValIDs.empty()) + return Error(ForwardRefValIDs.begin()->second.second, + "use of undefined value '@" + + Twine(ForwardRefValIDs.begin()->first) + "'"); + + if (!ForwardRefMDNodes.empty()) + return Error(ForwardRefMDNodes.begin()->second.second, + "use of undefined metadata '!" + + Twine(ForwardRefMDNodes.begin()->first) + "'"); + + + // Look for intrinsic functions and CallInst that need to be upgraded + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) + UpgradeCallsToIntrinsic(FI++); // must be post-increment, as we remove + + // Check debug info intrinsics. + CheckDebugInfoIntrinsics(M); + return false; +} + +bool LLParser::ResolveForwardRefBlockAddresses(Function *TheFn, + std::vector > &Refs, + PerFunctionState *PFS) { + // Loop over all the references, resolving them. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) { + BasicBlock *Res; + if (PFS) { + if (Refs[i].first.Kind == ValID::t_LocalName) + Res = PFS->GetBB(Refs[i].first.StrVal, Refs[i].first.Loc); + else + Res = PFS->GetBB(Refs[i].first.UIntVal, Refs[i].first.Loc); + } else if (Refs[i].first.Kind == ValID::t_LocalID) { + return Error(Refs[i].first.Loc, + "cannot take address of numeric label after the function is defined"); + } else { + Res = dyn_cast_or_null( + TheFn->getValueSymbolTable().lookup(Refs[i].first.StrVal)); + } + + if (Res == 0) + return Error(Refs[i].first.Loc, + "referenced value is not a basic block"); + + // Get the BlockAddress for this and update references to use it. + BlockAddress *BA = BlockAddress::get(TheFn, Res); + Refs[i].second->replaceAllUsesWith(BA); + Refs[i].second->eraseFromParent(); + } + return false; +} + + +//===----------------------------------------------------------------------===// +// Top-Level Entities +//===----------------------------------------------------------------------===// + +bool LLParser::ParseTopLevelEntities() { + while (1) { + switch (Lex.getKind()) { + default: return TokError("expected top-level entity"); + case lltok::Eof: return false; + //case lltok::kw_define: + case lltok::kw_declare: if (ParseDeclare()) return true; break; + case lltok::kw_define: if (ParseDefine()) return true; break; + case lltok::kw_module: if (ParseModuleAsm()) return true; break; + case lltok::kw_target: if (ParseTargetDefinition()) return true; break; + case lltok::kw_deplibs: if (ParseDepLibs()) return true; break; + case lltok::kw_type: if (ParseUnnamedType()) return true; break; + case lltok::LocalVarID: if (ParseUnnamedType()) return true; break; + case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0 + case lltok::LocalVar: if (ParseNamedType()) return true; break; + case lltok::GlobalID: if (ParseUnnamedGlobal()) return true; break; + case lltok::GlobalVar: if (ParseNamedGlobal()) return true; break; + case lltok::exclaim: if (ParseStandaloneMetadata()) return true; break; + case lltok::MetadataVar: if (ParseNamedMetadata()) return true; break; + + // The Global variable production with no name can have many different + // optional leading prefixes, the production is: + // GlobalVar ::= OptionalLinkage OptionalVisibility OptionalThreadLocal + // OptionalAddrSpace OptionalUnNammedAddr + // ('constant'|'global') ... + case lltok::kw_private: // OptionalLinkage + case lltok::kw_linker_private: // OptionalLinkage + case lltok::kw_linker_private_weak: // OptionalLinkage + case lltok::kw_linker_private_weak_def_auto: // OptionalLinkage + case lltok::kw_internal: // OptionalLinkage + case lltok::kw_weak: // OptionalLinkage + case lltok::kw_weak_odr: // OptionalLinkage + case lltok::kw_linkonce: // OptionalLinkage + case lltok::kw_linkonce_odr: // OptionalLinkage + case lltok::kw_appending: // OptionalLinkage + case lltok::kw_dllexport: // OptionalLinkage + case lltok::kw_common: // OptionalLinkage + case lltok::kw_dllimport: // OptionalLinkage + case lltok::kw_extern_weak: // OptionalLinkage + case lltok::kw_external: { // OptionalLinkage + unsigned Linkage, Visibility; + if (ParseOptionalLinkage(Linkage) || + ParseOptionalVisibility(Visibility) || + ParseGlobal("", SMLoc(), Linkage, true, Visibility)) + return true; + break; + } + case lltok::kw_default: // OptionalVisibility + case lltok::kw_hidden: // OptionalVisibility + case lltok::kw_protected: { // OptionalVisibility + unsigned Visibility; + if (ParseOptionalVisibility(Visibility) || + ParseGlobal("", SMLoc(), 0, false, Visibility)) + return true; + break; + } + + case lltok::kw_thread_local: // OptionalThreadLocal + case lltok::kw_addrspace: // OptionalAddrSpace + case lltok::kw_constant: // GlobalType + case lltok::kw_global: // GlobalType + if (ParseGlobal("", SMLoc(), 0, false, 0)) return true; + break; + } + } +} + + +/// toplevelentity +/// ::= 'module' 'asm' STRINGCONSTANT +bool LLParser::ParseModuleAsm() { + assert(Lex.getKind() == lltok::kw_module); + Lex.Lex(); + + std::string AsmStr; + if (ParseToken(lltok::kw_asm, "expected 'module asm'") || + ParseStringConstant(AsmStr)) return true; + + M->appendModuleInlineAsm(AsmStr); + return false; +} + +/// toplevelentity +/// ::= 'target' 'triple' '=' STRINGCONSTANT +/// ::= 'target' 'datalayout' '=' STRINGCONSTANT +bool LLParser::ParseTargetDefinition() { + assert(Lex.getKind() == lltok::kw_target); + std::string Str; + switch (Lex.Lex()) { + default: return TokError("unknown target property"); + case lltok::kw_triple: + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after target triple") || + ParseStringConstant(Str)) + return true; + M->setTargetTriple(Str); + return false; + case lltok::kw_datalayout: + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after target datalayout") || + ParseStringConstant(Str)) + return true; + M->setDataLayout(Str); + return false; + } +} + +/// toplevelentity +/// ::= 'deplibs' '=' '[' ']' +/// ::= 'deplibs' '=' '[' STRINGCONSTANT (',' STRINGCONSTANT)* ']' +bool LLParser::ParseDepLibs() { + assert(Lex.getKind() == lltok::kw_deplibs); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after deplibs") || + ParseToken(lltok::lsquare, "expected '=' after deplibs")) + return true; + + if (EatIfPresent(lltok::rsquare)) + return false; + + std::string Str; + if (ParseStringConstant(Str)) return true; + M->addLibrary(Str); + + while (EatIfPresent(lltok::comma)) { + if (ParseStringConstant(Str)) return true; + M->addLibrary(Str); + } + + return ParseToken(lltok::rsquare, "expected ']' at end of list"); +} + +/// ParseUnnamedType: +/// ::= 'type' type +/// ::= LocalVarID '=' 'type' type +bool LLParser::ParseUnnamedType() { + unsigned TypeID = NumberedTypes.size(); + + // Handle the LocalVarID form. + if (Lex.getKind() == lltok::LocalVarID) { + if (Lex.getUIntVal() != TypeID) + return Error(Lex.getLoc(), "type expected to be numbered '%" + + Twine(TypeID) + "'"); + Lex.Lex(); // eat LocalVarID; + + if (ParseToken(lltok::equal, "expected '=' after name")) + return true; + } + + LocTy TypeLoc = Lex.getLoc(); + if (ParseToken(lltok::kw_type, "expected 'type' after '='")) return true; + + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty)) return true; + + // See if this type was previously referenced. + std::map >::iterator + FI = ForwardRefTypeIDs.find(TypeID); + if (FI != ForwardRefTypeIDs.end()) { + if (FI->second.first.get() == Ty) + return Error(TypeLoc, "self referential type is invalid"); + + cast(FI->second.first.get())->refineAbstractTypeTo(Ty); + Ty = FI->second.first.get(); + ForwardRefTypeIDs.erase(FI); + } + + NumberedTypes.push_back(Ty); + + return false; +} + +/// toplevelentity +/// ::= LocalVar '=' 'type' type +bool LLParser::ParseNamedType() { + std::string Name = Lex.getStrVal(); + LocTy NameLoc = Lex.getLoc(); + Lex.Lex(); // eat LocalVar. + + PATypeHolder Ty(Type::getVoidTy(Context)); + + if (ParseToken(lltok::equal, "expected '=' after name") || + ParseToken(lltok::kw_type, "expected 'type' after name") || + ParseType(Ty)) + return true; + + // Set the type name, checking for conflicts as we do so. + bool AlreadyExists = M->addTypeName(Name, Ty); + if (!AlreadyExists) return false; + + // See if this type is a forward reference. We need to eagerly resolve + // types to allow recursive type redefinitions below. + std::map >::iterator + FI = ForwardRefTypes.find(Name); + if (FI != ForwardRefTypes.end()) { + if (FI->second.first.get() == Ty) + return Error(NameLoc, "self referential type is invalid"); + + cast(FI->second.first.get())->refineAbstractTypeTo(Ty); + Ty = FI->second.first.get(); + ForwardRefTypes.erase(FI); + } + + // Inserting a name that is already defined, get the existing name. + const Type *Existing = M->getTypeByName(Name); + assert(Existing && "Conflict but no matching type?!"); + + // Otherwise, this is an attempt to redefine a type. That's okay if + // the redefinition is identical to the original. + // FIXME: REMOVE REDEFINITIONS IN LLVM 3.0 + if (Existing == Ty) return false; + + // Any other kind of (non-equivalent) redefinition is an error. + return Error(NameLoc, "redefinition of type named '" + Name + "' of type '" + + Ty->getDescription() + "'"); +} + + +/// toplevelentity +/// ::= 'declare' FunctionHeader +bool LLParser::ParseDeclare() { + assert(Lex.getKind() == lltok::kw_declare); + Lex.Lex(); + + Function *F; + return ParseFunctionHeader(F, false); +} + +/// toplevelentity +/// ::= 'define' FunctionHeader '{' ... +bool LLParser::ParseDefine() { + assert(Lex.getKind() == lltok::kw_define); + Lex.Lex(); + + Function *F; + return ParseFunctionHeader(F, true) || + ParseFunctionBody(*F); +} + +/// ParseGlobalType +/// ::= 'constant' +/// ::= 'global' +bool LLParser::ParseGlobalType(bool &IsConstant) { + if (Lex.getKind() == lltok::kw_constant) + IsConstant = true; + else if (Lex.getKind() == lltok::kw_global) + IsConstant = false; + else { + IsConstant = false; + return TokError("expected 'global' or 'constant'"); + } + Lex.Lex(); + return false; +} + +/// ParseUnnamedGlobal: +/// OptionalVisibility ALIAS ... +/// OptionalLinkage OptionalVisibility ... -> global variable +/// GlobalID '=' OptionalVisibility ALIAS ... +/// GlobalID '=' OptionalLinkage OptionalVisibility ... -> global variable +bool LLParser::ParseUnnamedGlobal() { + unsigned VarID = NumberedVals.size(); + std::string Name; + LocTy NameLoc = Lex.getLoc(); + + // Handle the GlobalID form. + if (Lex.getKind() == lltok::GlobalID) { + if (Lex.getUIntVal() != VarID) + return Error(Lex.getLoc(), "variable expected to be numbered '%" + + Twine(VarID) + "'"); + Lex.Lex(); // eat GlobalID; + + if (ParseToken(lltok::equal, "expected '=' after name")) + return true; + } + + bool HasLinkage; + unsigned Linkage, Visibility; + if (ParseOptionalLinkage(Linkage, HasLinkage) || + ParseOptionalVisibility(Visibility)) + return true; + + if (HasLinkage || Lex.getKind() != lltok::kw_alias) + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); + return ParseAlias(Name, NameLoc, Visibility); +} + +/// ParseNamedGlobal: +/// GlobalVar '=' OptionalVisibility ALIAS ... +/// GlobalVar '=' OptionalLinkage OptionalVisibility ... -> global variable +bool LLParser::ParseNamedGlobal() { + assert(Lex.getKind() == lltok::GlobalVar); + LocTy NameLoc = Lex.getLoc(); + std::string Name = Lex.getStrVal(); + Lex.Lex(); + + bool HasLinkage; + unsigned Linkage, Visibility; + if (ParseToken(lltok::equal, "expected '=' in global variable") || + ParseOptionalLinkage(Linkage, HasLinkage) || + ParseOptionalVisibility(Visibility)) + return true; + + if (HasLinkage || Lex.getKind() != lltok::kw_alias) + return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility); + return ParseAlias(Name, NameLoc, Visibility); +} + +// MDString: +// ::= '!' STRINGCONSTANT +bool LLParser::ParseMDString(MDString *&Result) { + std::string Str; + if (ParseStringConstant(Str)) return true; + Result = MDString::get(Context, Str); + return false; +} + +// MDNode: +// ::= '!' MDNodeNumber +// +/// This version of ParseMDNodeID returns the slot number and null in the case +/// of a forward reference. +bool LLParser::ParseMDNodeID(MDNode *&Result, unsigned &SlotNo) { + // !{ ..., !42, ... } + if (ParseUInt32(SlotNo)) return true; + + // Check existing MDNode. + if (SlotNo < NumberedMetadata.size() && NumberedMetadata[SlotNo] != 0) + Result = NumberedMetadata[SlotNo]; + else + Result = 0; + return false; +} + +bool LLParser::ParseMDNodeID(MDNode *&Result) { + // !{ ..., !42, ... } + unsigned MID = 0; + if (ParseMDNodeID(Result, MID)) return true; + + // If not a forward reference, just return it now. + if (Result) return false; + + // Otherwise, create MDNode forward reference. + MDNode *FwdNode = MDNode::getTemporary(Context, 0, 0); + ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc()); + + if (NumberedMetadata.size() <= MID) + NumberedMetadata.resize(MID+1); + NumberedMetadata[MID] = FwdNode; + Result = FwdNode; + return false; +} + +/// ParseNamedMetadata: +/// !foo = !{ !1, !2 } +bool LLParser::ParseNamedMetadata() { + assert(Lex.getKind() == lltok::MetadataVar); + std::string Name = Lex.getStrVal(); + Lex.Lex(); + + if (ParseToken(lltok::equal, "expected '=' here") || + ParseToken(lltok::exclaim, "Expected '!' here") || + ParseToken(lltok::lbrace, "Expected '{' here")) + return true; + + NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name); + if (Lex.getKind() != lltok::rbrace) + do { + if (ParseToken(lltok::exclaim, "Expected '!' here")) + return true; + + MDNode *N = 0; + if (ParseMDNodeID(N)) return true; + NMD->addOperand(N); + } while (EatIfPresent(lltok::comma)); + + if (ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + return false; +} + +/// ParseStandaloneMetadata: +/// !42 = !{...} +bool LLParser::ParseStandaloneMetadata() { + assert(Lex.getKind() == lltok::exclaim); + Lex.Lex(); + unsigned MetadataID = 0; + + LocTy TyLoc; + PATypeHolder Ty(Type::getVoidTy(Context)); + SmallVector Elts; + if (ParseUInt32(MetadataID) || + ParseToken(lltok::equal, "expected '=' here") || + ParseType(Ty, TyLoc) || + ParseToken(lltok::exclaim, "Expected '!' here") || + ParseToken(lltok::lbrace, "Expected '{' here") || + ParseMDNodeVector(Elts, NULL) || + ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + MDNode *Init = MDNode::get(Context, Elts.data(), Elts.size()); + + // See if this was forward referenced, if so, handle it. + std::map, LocTy> >::iterator + FI = ForwardRefMDNodes.find(MetadataID); + if (FI != ForwardRefMDNodes.end()) { + MDNode *Temp = FI->second.first; + Temp->replaceAllUsesWith(Init); + MDNode::deleteTemporary(Temp); + ForwardRefMDNodes.erase(FI); + + assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); + } else { + if (MetadataID >= NumberedMetadata.size()) + NumberedMetadata.resize(MetadataID+1); + + if (NumberedMetadata[MetadataID] != 0) + return TokError("Metadata id is already used"); + NumberedMetadata[MetadataID] = Init; + } + + return false; +} + +/// ParseAlias: +/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee +/// Aliasee +/// ::= TypeAndValue +/// ::= 'bitcast' '(' TypeAndValue 'to' Type ')' +/// ::= 'getelementptr' 'inbounds'? '(' ... ')' +/// +/// Everything through visibility has already been parsed. +/// +bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, + unsigned Visibility) { + assert(Lex.getKind() == lltok::kw_alias); + Lex.Lex(); + unsigned Linkage; + LocTy LinkageLoc = Lex.getLoc(); + if (ParseOptionalLinkage(Linkage)) + return true; + + if (Linkage != GlobalValue::ExternalLinkage && + Linkage != GlobalValue::WeakAnyLinkage && + Linkage != GlobalValue::WeakODRLinkage && + Linkage != GlobalValue::InternalLinkage && + Linkage != GlobalValue::PrivateLinkage && + Linkage != GlobalValue::LinkerPrivateLinkage && + Linkage != GlobalValue::LinkerPrivateWeakLinkage && + Linkage != GlobalValue::LinkerPrivateWeakDefAutoLinkage) + return Error(LinkageLoc, "invalid linkage type for alias"); + + Constant *Aliasee; + LocTy AliaseeLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::kw_bitcast && + Lex.getKind() != lltok::kw_getelementptr) { + if (ParseGlobalTypeAndValue(Aliasee)) return true; + } else { + // The bitcast dest type is not present, it is implied by the dest type. + ValID ID; + if (ParseValID(ID)) return true; + if (ID.Kind != ValID::t_Constant) + return Error(AliaseeLoc, "invalid aliasee"); + Aliasee = ID.ConstantVal; + } + + if (!Aliasee->getType()->isPointerTy()) + return Error(AliaseeLoc, "alias must have pointer type"); + + // Okay, create the alias but do not insert it into the module yet. + GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), + (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee); + GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); + + // See if this value already exists in the symbol table. If so, it is either + // a redefinition or a definition of a forward reference. + if (GlobalValue *Val = M->getNamedValue(Name)) { + // See if this was a redefinition. If so, there is no entry in + // ForwardRefVals. + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I == ForwardRefVals.end()) + return Error(NameLoc, "redefinition of global named '@" + Name + "'"); + + // Otherwise, this was a definition of forward ref. Verify that types + // agree. + if (Val->getType() != GA->getType()) + return Error(NameLoc, + "forward reference and definition of alias have different types"); + + // If they agree, just RAUW the old value with the alias and remove the + // forward ref info. + Val->replaceAllUsesWith(GA); + Val->eraseFromParent(); + ForwardRefVals.erase(I); + } + + // Insert into the module, we know its name won't collide now. + M->getAliasList().push_back(GA); + assert(GA->getName() == Name && "Should not be a name conflict!"); + + return false; +} + +/// ParseGlobal +/// ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalThreadLocal +/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const +/// ::= OptionalLinkage OptionalVisibility OptionalThreadLocal +/// OptionalAddrSpace OptionalUnNammedAddr GlobalType Type Const +/// +/// Everything through visibility has been parsed already. +/// +bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, + unsigned Linkage, bool HasLinkage, + unsigned Visibility) { + unsigned AddrSpace; + bool ThreadLocal, IsConstant, UnnamedAddr; + LocTy UnnamedAddrLoc; + LocTy TyLoc; + + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseOptionalToken(lltok::kw_thread_local, ThreadLocal) || + ParseOptionalAddrSpace(AddrSpace) || + ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, + &UnnamedAddrLoc) || + ParseGlobalType(IsConstant) || + ParseType(Ty, TyLoc)) + return true; + + // If the linkage is specified and is external, then no initializer is + // present. + Constant *Init = 0; + if (!HasLinkage || (Linkage != GlobalValue::DLLImportLinkage && + Linkage != GlobalValue::ExternalWeakLinkage && + Linkage != GlobalValue::ExternalLinkage)) { + if (ParseGlobalValue(Ty, Init)) + return true; + } + + if (Ty->isFunctionTy() || Ty->isLabelTy()) + return Error(TyLoc, "invalid type for global variable"); + + GlobalVariable *GV = 0; + + // See if the global was forward referenced, if so, use the global. + if (!Name.empty()) { + if (GlobalValue *GVal = M->getNamedValue(Name)) { + if (!ForwardRefVals.erase(Name) || !isa(GVal)) + return Error(NameLoc, "redefinition of global '@" + Name + "'"); + GV = cast(GVal); + } + } else { + std::map >::iterator + I = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + GV = cast(I->second.first); + ForwardRefValIDs.erase(I); + } + } + + if (GV == 0) { + GV = new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, 0, + Name, 0, false, AddrSpace); + } else { + if (GV->getType()->getElementType() != Ty) + return Error(TyLoc, + "forward reference and definition of global have different types"); + + // Move the forward-reference to the correct spot in the module. + M->getGlobalList().splice(M->global_end(), M->getGlobalList(), GV); + } + + if (Name.empty()) + NumberedVals.push_back(GV); + + // Set the parsed properties on the global. + if (Init) + GV->setInitializer(Init); + GV->setConstant(IsConstant); + GV->setLinkage((GlobalValue::LinkageTypes)Linkage); + GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setThreadLocal(ThreadLocal); + GV->setUnnamedAddr(UnnamedAddr); + + // Parse attributes on the global. + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); + + if (Lex.getKind() == lltok::kw_section) { + Lex.Lex(); + GV->setSection(Lex.getStrVal()); + if (ParseToken(lltok::StringConstant, "expected global section string")) + return true; + } else if (Lex.getKind() == lltok::kw_align) { + unsigned Alignment; + if (ParseOptionalAlignment(Alignment)) return true; + GV->setAlignment(Alignment); + } else { + TokError("unknown global variable property!"); + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// GlobalValue Reference/Resolution Routines. +//===----------------------------------------------------------------------===// + +/// GetGlobalVal - Get a value with the specified name or ID, creating a +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. +GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, + LocTy Loc) { + const PointerType *PTy = dyn_cast(Ty); + if (PTy == 0) { + Error(Loc, "global variable reference must have pointer type"); + return 0; + } + + // Look this name up in the normal function symbol table. + GlobalValue *Val = + cast_or_null(M->getValueSymbolTable().lookup(Name)); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + Error(Loc, "'@" + Name + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal; + if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { + // Function types can return opaque but functions can't. + if (FT->getReturnType()->isOpaqueTy()) { + Error(Loc, "function may not return opaque type"); + return 0; + } + + FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, Name, M); + } else { + FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, + GlobalValue::ExternalWeakLinkage, 0, Name); + } + + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) { + const PointerType *PTy = dyn_cast(Ty); + if (PTy == 0) { + Error(Loc, "global variable reference must have pointer type"); + return 0; + } + + GlobalValue *Val = ID < NumberedVals.size() ? NumberedVals[ID] : 0; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + Error(Loc, "'@" + Twine(ID) + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal; + if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { + // Function types can return opaque but functions can't. + if (FT->getReturnType()->isOpaqueTy()) { + Error(Loc, "function may not return opaque type"); + return 0; + } + FwdVal = Function::Create(FT, GlobalValue::ExternalWeakLinkage, "", M); + } else { + FwdVal = new GlobalVariable(*M, PTy->getElementType(), false, + GlobalValue::ExternalWeakLinkage, 0, ""); + } + + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + + +//===----------------------------------------------------------------------===// +// Helper Routines. +//===----------------------------------------------------------------------===// + +/// ParseToken - If the current token has the specified kind, eat it and return +/// success. Otherwise, emit the specified error and return failure. +bool LLParser::ParseToken(lltok::Kind T, const char *ErrMsg) { + if (Lex.getKind() != T) + return TokError(ErrMsg); + Lex.Lex(); + return false; +} + +/// ParseStringConstant +/// ::= StringConstant +bool LLParser::ParseStringConstant(std::string &Result) { + if (Lex.getKind() != lltok::StringConstant) + return TokError("expected string constant"); + Result = Lex.getStrVal(); + Lex.Lex(); + return false; +} + +/// ParseUInt32 +/// ::= uint32 +bool LLParser::ParseUInt32(unsigned &Val) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + return TokError("expected integer"); + uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(0xFFFFFFFFULL+1); + if (Val64 != unsigned(Val64)) + return TokError("expected 32-bit integer (too large)"); + Val = Val64; + Lex.Lex(); + return false; +} + + +/// ParseOptionalAddrSpace +/// := /*empty*/ +/// := 'addrspace' '(' uint32 ')' +bool LLParser::ParseOptionalAddrSpace(unsigned &AddrSpace) { + AddrSpace = 0; + if (!EatIfPresent(lltok::kw_addrspace)) + return false; + return ParseToken(lltok::lparen, "expected '(' in address space") || + ParseUInt32(AddrSpace) || + ParseToken(lltok::rparen, "expected ')' in address space"); +} + +/// ParseOptionalAttrs - Parse a potentially empty attribute list. AttrKind +/// indicates what kind of attribute list this is: 0: function arg, 1: result, +/// 2: function attr. +/// 3: function arg after value: FIXME: REMOVE IN LLVM 3.0 +bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { + Attrs = Attribute::None; + LocTy AttrLoc = Lex.getLoc(); + + while (1) { + switch (Lex.getKind()) { + case lltok::kw_sext: + case lltok::kw_zext: + // Treat these as signext/zeroext if they occur in the argument list after + // the value, as in "call i8 @foo(i8 10 sext)". If they occur before the + // value, as in "call i8 @foo(i8 sext (" then it is part of a constant + // expr. + // FIXME: REMOVE THIS IN LLVM 3.0 + if (AttrKind == 3) { + if (Lex.getKind() == lltok::kw_sext) + Attrs |= Attribute::SExt; + else + Attrs |= Attribute::ZExt; + break; + } + // FALL THROUGH. + default: // End of attributes. + if (AttrKind != 2 && (Attrs & Attribute::FunctionOnly)) + return Error(AttrLoc, "invalid use of function-only attribute"); + + if (AttrKind != 0 && AttrKind != 3 && (Attrs & Attribute::ParameterOnly)) + return Error(AttrLoc, "invalid use of parameter-only attribute"); + + return false; + case lltok::kw_zeroext: Attrs |= Attribute::ZExt; break; + case lltok::kw_signext: Attrs |= Attribute::SExt; break; + case lltok::kw_inreg: Attrs |= Attribute::InReg; break; + case lltok::kw_sret: Attrs |= Attribute::StructRet; break; + case lltok::kw_noalias: Attrs |= Attribute::NoAlias; break; + case lltok::kw_nocapture: Attrs |= Attribute::NoCapture; break; + case lltok::kw_byval: Attrs |= Attribute::ByVal; break; + case lltok::kw_nest: Attrs |= Attribute::Nest; break; + + case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break; + case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break; + case lltok::kw_noinline: Attrs |= Attribute::NoInline; break; + case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break; + case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break; + case lltok::kw_inlinehint: Attrs |= Attribute::InlineHint; break; + case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break; + case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break; + case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break; + case lltok::kw_sspreq: Attrs |= Attribute::StackProtectReq; break; + case lltok::kw_noredzone: Attrs |= Attribute::NoRedZone; break; + case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; + case lltok::kw_naked: Attrs |= Attribute::Naked; break; + case lltok::kw_hotpatch: Attrs |= Attribute::Hotpatch; break; + + case lltok::kw_alignstack: { + unsigned Alignment; + if (ParseOptionalStackAlignment(Alignment)) + return true; + Attrs |= Attribute::constructStackAlignmentFromInt(Alignment); + continue; + } + + case lltok::kw_align: { + unsigned Alignment; + if (ParseOptionalAlignment(Alignment)) + return true; + Attrs |= Attribute::constructAlignmentFromInt(Alignment); + continue; + } + + } + Lex.Lex(); + } +} + +/// ParseOptionalLinkage +/// ::= /*empty*/ +/// ::= 'private' +/// ::= 'linker_private' +/// ::= 'linker_private_weak' +/// ::= 'linker_private_weak_def_auto' +/// ::= 'internal' +/// ::= 'weak' +/// ::= 'weak_odr' +/// ::= 'linkonce' +/// ::= 'linkonce_odr' +/// ::= 'available_externally' +/// ::= 'appending' +/// ::= 'dllexport' +/// ::= 'common' +/// ::= 'dllimport' +/// ::= 'extern_weak' +/// ::= 'external' +bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage) { + HasLinkage = false; + switch (Lex.getKind()) { + default: Res=GlobalValue::ExternalLinkage; return false; + case lltok::kw_private: Res = GlobalValue::PrivateLinkage; break; + case lltok::kw_linker_private: Res = GlobalValue::LinkerPrivateLinkage; break; + case lltok::kw_linker_private_weak: + Res = GlobalValue::LinkerPrivateWeakLinkage; + break; + case lltok::kw_linker_private_weak_def_auto: + Res = GlobalValue::LinkerPrivateWeakDefAutoLinkage; + break; + case lltok::kw_internal: Res = GlobalValue::InternalLinkage; break; + case lltok::kw_weak: Res = GlobalValue::WeakAnyLinkage; break; + case lltok::kw_weak_odr: Res = GlobalValue::WeakODRLinkage; break; + case lltok::kw_linkonce: Res = GlobalValue::LinkOnceAnyLinkage; break; + case lltok::kw_linkonce_odr: Res = GlobalValue::LinkOnceODRLinkage; break; + case lltok::kw_available_externally: + Res = GlobalValue::AvailableExternallyLinkage; + break; + case lltok::kw_appending: Res = GlobalValue::AppendingLinkage; break; + case lltok::kw_dllexport: Res = GlobalValue::DLLExportLinkage; break; + case lltok::kw_common: Res = GlobalValue::CommonLinkage; break; + case lltok::kw_dllimport: Res = GlobalValue::DLLImportLinkage; break; + case lltok::kw_extern_weak: Res = GlobalValue::ExternalWeakLinkage; break; + case lltok::kw_external: Res = GlobalValue::ExternalLinkage; break; + } + Lex.Lex(); + HasLinkage = true; + return false; +} + +/// ParseOptionalVisibility +/// ::= /*empty*/ +/// ::= 'default' +/// ::= 'hidden' +/// ::= 'protected' +/// +bool LLParser::ParseOptionalVisibility(unsigned &Res) { + switch (Lex.getKind()) { + default: Res = GlobalValue::DefaultVisibility; return false; + case lltok::kw_default: Res = GlobalValue::DefaultVisibility; break; + case lltok::kw_hidden: Res = GlobalValue::HiddenVisibility; break; + case lltok::kw_protected: Res = GlobalValue::ProtectedVisibility; break; + } + Lex.Lex(); + return false; +} + +/// ParseOptionalCallingConv +/// ::= /*empty*/ +/// ::= 'ccc' +/// ::= 'fastcc' +/// ::= 'coldcc' +/// ::= 'x86_stdcallcc' +/// ::= 'x86_fastcallcc' +/// ::= 'x86_thiscallcc' +/// ::= 'arm_apcscc' +/// ::= 'arm_aapcscc' +/// ::= 'arm_aapcs_vfpcc' +/// ::= 'msp430_intrcc' +/// ::= 'ptx_kernel' +/// ::= 'ptx_device' +/// ::= 'cc' UINT +/// +bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) { + switch (Lex.getKind()) { + default: CC = CallingConv::C; return false; + case lltok::kw_ccc: CC = CallingConv::C; break; + case lltok::kw_fastcc: CC = CallingConv::Fast; break; + case lltok::kw_coldcc: CC = CallingConv::Cold; break; + case lltok::kw_x86_stdcallcc: CC = CallingConv::X86_StdCall; break; + case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break; + case lltok::kw_x86_thiscallcc: CC = CallingConv::X86_ThisCall; break; + case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break; + case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break; + case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break; + case lltok::kw_msp430_intrcc: CC = CallingConv::MSP430_INTR; break; + case lltok::kw_ptx_kernel: CC = CallingConv::PTX_Kernel; break; + case lltok::kw_ptx_device: CC = CallingConv::PTX_Device; break; + case lltok::kw_cc: { + unsigned ArbitraryCC; + Lex.Lex(); + if (ParseUInt32(ArbitraryCC)) { + return true; + } else + CC = static_cast(ArbitraryCC); + return false; + } + break; + } + + Lex.Lex(); + return false; +} + +/// ParseInstructionMetadata +/// ::= !dbg !42 (',' !dbg !57)* +bool LLParser::ParseInstructionMetadata(Instruction *Inst, + PerFunctionState *PFS) { + do { + if (Lex.getKind() != lltok::MetadataVar) + return TokError("expected metadata after comma"); + + std::string Name = Lex.getStrVal(); + unsigned MDK = M->getMDKindID(Name.c_str()); + Lex.Lex(); + + MDNode *Node; + SMLoc Loc = Lex.getLoc(); + + if (ParseToken(lltok::exclaim, "expected '!' here")) + return true; + + // This code is similar to that of ParseMetadataValue, however it needs to + // have special-case code for a forward reference; see the comments on + // ForwardRefInstMetadata for details. Also, MDStrings are not supported + // at the top level here. + if (Lex.getKind() == lltok::lbrace) { + ValID ID; + if (ParseMetadataListValue(ID, PFS)) + return true; + assert(ID.Kind == ValID::t_MDNode); + Inst->setMetadata(MDK, ID.MDNodeVal); + } else { + unsigned NodeID = 0; + if (ParseMDNodeID(Node, NodeID)) + return true; + if (Node) { + // If we got the node, add it to the instruction. + Inst->setMetadata(MDK, Node); + } else { + MDRef R = { Loc, MDK, NodeID }; + // Otherwise, remember that this should be resolved later. + ForwardRefInstMetadata[Inst].push_back(R); + } + } + + // If this is the end of the list, we're done. + } while (EatIfPresent(lltok::comma)); + return false; +} + +/// ParseOptionalAlignment +/// ::= /* empty */ +/// ::= 'align' 4 +bool LLParser::ParseOptionalAlignment(unsigned &Alignment) { + Alignment = 0; + if (!EatIfPresent(lltok::kw_align)) + return false; + LocTy AlignLoc = Lex.getLoc(); + if (ParseUInt32(Alignment)) return true; + if (!isPowerOf2_32(Alignment)) + return Error(AlignLoc, "alignment is not a power of two"); + if (Alignment > Value::MaximumAlignment) + return Error(AlignLoc, "huge alignments are not supported yet"); + return false; +} + +/// ParseOptionalCommaAlign +/// ::= +/// ::= ',' align 4 +/// +/// This returns with AteExtraComma set to true if it ate an excess comma at the +/// end. +bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment, + bool &AteExtraComma) { + AteExtraComma = false; + while (EatIfPresent(lltok::comma)) { + // Metadata at the end is an early exit. + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + return false; + } + + if (Lex.getKind() != lltok::kw_align) + return Error(Lex.getLoc(), "expected metadata or 'align'"); + + if (ParseOptionalAlignment(Alignment)) return true; + } + + return false; +} + +/// ParseOptionalStackAlignment +/// ::= /* empty */ +/// ::= 'alignstack' '(' 4 ')' +bool LLParser::ParseOptionalStackAlignment(unsigned &Alignment) { + Alignment = 0; + if (!EatIfPresent(lltok::kw_alignstack)) + return false; + LocTy ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) + return Error(ParenLoc, "expected '('"); + LocTy AlignLoc = Lex.getLoc(); + if (ParseUInt32(Alignment)) return true; + ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) + return Error(ParenLoc, "expected ')'"); + if (!isPowerOf2_32(Alignment)) + return Error(AlignLoc, "stack alignment is not a power of two"); + return false; +} + +/// ParseIndexList - This parses the index list for an insert/extractvalue +/// instruction. This sets AteExtraComma in the case where we eat an extra +/// comma at the end of the line and find that it is followed by metadata. +/// Clients that don't allow metadata can call the version of this function that +/// only takes one argument. +/// +/// ParseIndexList +/// ::= (',' uint32)+ +/// +bool LLParser::ParseIndexList(SmallVectorImpl &Indices, + bool &AteExtraComma) { + AteExtraComma = false; + + if (Lex.getKind() != lltok::comma) + return TokError("expected ',' as start of index list"); + + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + return false; + } + unsigned Idx = 0; + if (ParseUInt32(Idx)) return true; + Indices.push_back(Idx); + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Type Parsing. +//===----------------------------------------------------------------------===// + +/// ParseType - Parse and resolve a full type. +bool LLParser::ParseType(PATypeHolder &Result, bool AllowVoid) { + LocTy TypeLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + + // Verify no unresolved uprefs. + if (!UpRefs.empty()) + return Error(UpRefs.back().Loc, "invalid unresolved type up reference"); + + if (!AllowVoid && Result.get()->isVoidTy()) + return Error(TypeLoc, "void type only allowed for function results"); + + return false; +} + +/// HandleUpRefs - Every time we finish a new layer of types, this function is +/// called. It loops through the UpRefs vector, which is a list of the +/// currently active types. For each type, if the up-reference is contained in +/// the newly completed type, we decrement the level count. When the level +/// count reaches zero, the up-referenced type is the type that is passed in: +/// thus we can complete the cycle. +/// +PATypeHolder LLParser::HandleUpRefs(const Type *ty) { + // If Ty isn't abstract, or if there are no up-references in it, then there is + // nothing to resolve here. + if (!ty->isAbstract() || UpRefs.empty()) return ty; + + PATypeHolder Ty(ty); +#if 0 + dbgs() << "Type '" << Ty->getDescription() + << "' newly formed. Resolving upreferences.\n" + << UpRefs.size() << " upreferences active!\n"; +#endif + + // If we find any resolvable upreferences (i.e., those whose NestingLevel goes + // to zero), we resolve them all together before we resolve them to Ty. At + // the end of the loop, if there is anything to resolve to Ty, it will be in + // this variable. + OpaqueType *TypeToResolve = 0; + + for (unsigned i = 0; i != UpRefs.size(); ++i) { + // Determine if 'Ty' directly contains this up-references 'LastContainedTy'. + bool ContainsType = + std::find(Ty->subtype_begin(), Ty->subtype_end(), + UpRefs[i].LastContainedTy) != Ty->subtype_end(); + +#if 0 + dbgs() << " UR#" << i << " - TypeContains(" << Ty->getDescription() << ", " + << UpRefs[i].LastContainedTy->getDescription() << ") = " + << (ContainsType ? "true" : "false") + << " level=" << UpRefs[i].NestingLevel << "\n"; +#endif + if (!ContainsType) + continue; + + // Decrement level of upreference + unsigned Level = --UpRefs[i].NestingLevel; + UpRefs[i].LastContainedTy = Ty; + + // If the Up-reference has a non-zero level, it shouldn't be resolved yet. + if (Level != 0) + continue; + +#if 0 + dbgs() << " * Resolving upreference for " << UpRefs[i].UpRefTy << "\n"; +#endif + if (!TypeToResolve) + TypeToResolve = UpRefs[i].UpRefTy; + else + UpRefs[i].UpRefTy->refineAbstractTypeTo(TypeToResolve); + UpRefs.erase(UpRefs.begin()+i); // Remove from upreference list. + --i; // Do not skip the next element. + } + + if (TypeToResolve) + TypeToResolve->refineAbstractTypeTo(Ty); + + return Ty; +} + + +/// ParseTypeRec - The recursive function used to process the internal +/// implementation details of types. +bool LLParser::ParseTypeRec(PATypeHolder &Result) { + switch (Lex.getKind()) { + default: + return TokError("expected type"); + case lltok::Type: + // TypeRec ::= 'float' | 'void' (etc) + Result = Lex.getTyVal(); + Lex.Lex(); + break; + case lltok::kw_opaque: + // TypeRec ::= 'opaque' + Result = OpaqueType::get(Context); + Lex.Lex(); + break; + case lltok::lbrace: + // TypeRec ::= '{' ... '}' + if (ParseStructType(Result, false)) + return true; + break; + case lltok::lsquare: + // TypeRec ::= '[' ... ']' + Lex.Lex(); // eat the lsquare. + if (ParseArrayVectorType(Result, false)) + return true; + break; + case lltok::less: // Either vector or packed struct. + // TypeRec ::= '<' ... '>' + Lex.Lex(); + if (Lex.getKind() == lltok::lbrace) { + if (ParseStructType(Result, true) || + ParseToken(lltok::greater, "expected '>' at end of packed struct")) + return true; + } else if (ParseArrayVectorType(Result, true)) + return true; + break; + case lltok::LocalVar: + case lltok::StringConstant: // FIXME: REMOVE IN LLVM 3.0 + // TypeRec ::= %foo + if (const Type *T = M->getTypeByName(Lex.getStrVal())) { + Result = T; + } else { + Result = OpaqueType::get(Context); + ForwardRefTypes.insert(std::make_pair(Lex.getStrVal(), + std::make_pair(Result, + Lex.getLoc()))); + M->addTypeName(Lex.getStrVal(), Result.get()); + } + Lex.Lex(); + break; + + case lltok::LocalVarID: + // TypeRec ::= %4 + if (Lex.getUIntVal() < NumberedTypes.size()) + Result = NumberedTypes[Lex.getUIntVal()]; + else { + std::map >::iterator + I = ForwardRefTypeIDs.find(Lex.getUIntVal()); + if (I != ForwardRefTypeIDs.end()) + Result = I->second.first; + else { + Result = OpaqueType::get(Context); + ForwardRefTypeIDs.insert(std::make_pair(Lex.getUIntVal(), + std::make_pair(Result, + Lex.getLoc()))); + } + } + Lex.Lex(); + break; + case lltok::backslash: { + // TypeRec ::= '\' 4 + Lex.Lex(); + unsigned Val; + if (ParseUInt32(Val)) return true; + OpaqueType *OT = OpaqueType::get(Context); //Use temporary placeholder. + UpRefs.push_back(UpRefRecord(Lex.getLoc(), Val, OT)); + Result = OT; + break; + } + } + + // Parse the type suffixes. + while (1) { + switch (Lex.getKind()) { + // End of type. + default: return false; + + // TypeRec ::= TypeRec '*' + case lltok::star: + if (Result.get()->isLabelTy()) + return TokError("basic block pointers are invalid"); + if (Result.get()->isVoidTy()) + return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); + Result = HandleUpRefs(PointerType::getUnqual(Result.get())); + Lex.Lex(); + break; + + // TypeRec ::= TypeRec 'addrspace' '(' uint32 ')' '*' + case lltok::kw_addrspace: { + if (Result.get()->isLabelTy()) + return TokError("basic block pointers are invalid"); + if (Result.get()->isVoidTy()) + return TokError("pointers to void are invalid; use i8* instead"); + if (!PointerType::isValidElementType(Result.get())) + return TokError("pointer to this type is invalid"); + unsigned AddrSpace; + if (ParseOptionalAddrSpace(AddrSpace) || + ParseToken(lltok::star, "expected '*' in address space")) + return true; + + Result = HandleUpRefs(PointerType::get(Result.get(), AddrSpace)); + break; + } + + /// Types '(' ArgTypeListI ')' OptFuncAttrs + case lltok::lparen: + if (ParseFunctionType(Result)) + return true; + break; + } + } +} + +/// ParseParameterList +/// ::= '(' ')' +/// ::= '(' Arg (',' Arg)* ')' +/// Arg +/// ::= Type OptionalAttributes Value OptionalAttributes +bool LLParser::ParseParameterList(SmallVectorImpl &ArgList, + PerFunctionState &PFS) { + if (ParseToken(lltok::lparen, "expected '(' in call")) + return true; + + while (Lex.getKind() != lltok::rparen) { + // If this isn't the first argument, we need a comma. + if (!ArgList.empty() && + ParseToken(lltok::comma, "expected ',' in argument list")) + return true; + + // Parse the argument. + LocTy ArgLoc; + PATypeHolder ArgTy(Type::getVoidTy(Context)); + unsigned ArgAttrs1 = Attribute::None; + unsigned ArgAttrs2 = Attribute::None; + Value *V; + if (ParseType(ArgTy, ArgLoc)) + return true; + + // Otherwise, handle normal operands. + if (ParseOptionalAttrs(ArgAttrs1, 0) || + ParseValue(ArgTy, V, PFS) || + // FIXME: Should not allow attributes after the argument, remove this + // in LLVM 3.0. + ParseOptionalAttrs(ArgAttrs2, 3)) + return true; + ArgList.push_back(ParamInfo(ArgLoc, V, ArgAttrs1|ArgAttrs2)); + } + + Lex.Lex(); // Lex the ')'. + return false; +} + + + +/// ParseArgumentList - Parse the argument list for a function type or function +/// prototype. If 'inType' is true then we are parsing a FunctionType. +/// ::= '(' ArgTypeListI ')' +/// ArgTypeListI +/// ::= /*empty*/ +/// ::= '...' +/// ::= ArgTypeList ',' '...' +/// ::= ArgType (',' ArgType)* +/// +bool LLParser::ParseArgumentList(std::vector &ArgList, + bool &isVarArg, bool inType) { + isVarArg = false; + assert(Lex.getKind() == lltok::lparen); + Lex.Lex(); // eat the (. + + if (Lex.getKind() == lltok::rparen) { + // empty + } else if (Lex.getKind() == lltok::dotdotdot) { + isVarArg = true; + Lex.Lex(); + } else { + LocTy TypeLoc = Lex.getLoc(); + PATypeHolder ArgTy(Type::getVoidTy(Context)); + unsigned Attrs; + std::string Name; + + // If we're parsing a type, use ParseTypeRec, because we allow recursive + // types (such as a function returning a pointer to itself). If parsing a + // function prototype, we require fully resolved types. + if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) || + ParseOptionalAttrs(Attrs, 0)) return true; + + if (ArgTy->isVoidTy()) + return Error(TypeLoc, "argument can not have void type"); + + if (Lex.getKind() == lltok::LocalVar || + Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0 + Name = Lex.getStrVal(); + Lex.Lex(); + } + + if (!FunctionType::isValidArgumentType(ArgTy)) + return Error(TypeLoc, "invalid type for function argument"); + + ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); + + while (EatIfPresent(lltok::comma)) { + // Handle ... at end of arg list. + if (EatIfPresent(lltok::dotdotdot)) { + isVarArg = true; + break; + } + + // Otherwise must be an argument type. + TypeLoc = Lex.getLoc(); + if ((inType ? ParseTypeRec(ArgTy) : ParseType(ArgTy)) || + ParseOptionalAttrs(Attrs, 0)) return true; + + if (ArgTy->isVoidTy()) + return Error(TypeLoc, "argument can not have void type"); + + if (Lex.getKind() == lltok::LocalVar || + Lex.getKind() == lltok::StringConstant) { // FIXME: REMOVE IN LLVM 3.0 + Name = Lex.getStrVal(); + Lex.Lex(); + } else { + Name = ""; + } + + if (!ArgTy->isFirstClassType() && !ArgTy->isOpaqueTy()) + return Error(TypeLoc, "invalid type for function argument"); + + ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); + } + } + + return ParseToken(lltok::rparen, "expected ')' at end of argument list"); +} + +/// ParseFunctionType +/// ::= Type ArgumentList OptionalAttrs +bool LLParser::ParseFunctionType(PATypeHolder &Result) { + assert(Lex.getKind() == lltok::lparen); + + if (!FunctionType::isValidReturnType(Result)) + return TokError("invalid function return type"); + + std::vector ArgList; + bool isVarArg; + unsigned Attrs; + if (ParseArgumentList(ArgList, isVarArg, true) || + // FIXME: Allow, but ignore attributes on function types! + // FIXME: Remove in LLVM 3.0 + ParseOptionalAttrs(Attrs, 2)) + return true; + + // Reject names on the arguments lists. + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + if (!ArgList[i].Name.empty()) + return Error(ArgList[i].Loc, "argument name invalid in function type"); + if (!ArgList[i].Attrs != 0) { + // Allow but ignore attributes on function types; this permits + // auto-upgrade. + // FIXME: REJECT ATTRIBUTES ON FUNCTION TYPES in LLVM 3.0 + } + } + + std::vector ArgListTy; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ArgListTy.push_back(ArgList[i].Type); + + Result = HandleUpRefs(FunctionType::get(Result.get(), + ArgListTy, isVarArg)); + return false; +} + +/// ParseStructType: Handles packed and unpacked types. parsed elsewhere. +/// TypeRec +/// ::= '{' '}' +/// ::= '{' TypeRec (',' TypeRec)* '}' +/// ::= '<' '{' '}' '>' +/// ::= '<' '{' TypeRec (',' TypeRec)* '}' '>' +bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { + assert(Lex.getKind() == lltok::lbrace); + Lex.Lex(); // Consume the '{' + + if (EatIfPresent(lltok::rbrace)) { + Result = StructType::get(Context, Packed); + return false; + } + + std::vector ParamsList; + LocTy EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + ParamsList.push_back(Result); + + if (Result->isVoidTy()) + return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); + + while (EatIfPresent(lltok::comma)) { + EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + + if (Result->isVoidTy()) + return Error(EltTyLoc, "struct element can not have void type"); + if (!StructType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for struct"); + + ParamsList.push_back(Result); + } + + if (ParseToken(lltok::rbrace, "expected '}' at end of struct")) + return true; + + std::vector ParamsListTy; + for (unsigned i = 0, e = ParamsList.size(); i != e; ++i) + ParamsListTy.push_back(ParamsList[i].get()); + Result = HandleUpRefs(StructType::get(Context, ParamsListTy, Packed)); + return false; +} + +/// ParseArrayVectorType - Parse an array or vector type, assuming the first +/// token has already been consumed. +/// TypeRec +/// ::= '[' APSINTVAL 'x' Types ']' +/// ::= '<' APSINTVAL 'x' Types '>' +bool LLParser::ParseArrayVectorType(PATypeHolder &Result, bool isVector) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() || + Lex.getAPSIntVal().getBitWidth() > 64) + return TokError("expected number in address space"); + + LocTy SizeLoc = Lex.getLoc(); + uint64_t Size = Lex.getAPSIntVal().getZExtValue(); + Lex.Lex(); + + if (ParseToken(lltok::kw_x, "expected 'x' after element count")) + return true; + + LocTy TypeLoc = Lex.getLoc(); + PATypeHolder EltTy(Type::getVoidTy(Context)); + if (ParseTypeRec(EltTy)) return true; + + if (EltTy->isVoidTy()) + return Error(TypeLoc, "array and vector element type cannot be void"); + + if (ParseToken(isVector ? lltok::greater : lltok::rsquare, + "expected end of sequential type")) + return true; + + if (isVector) { + if (Size == 0) + return Error(SizeLoc, "zero element vector is illegal"); + if ((unsigned)Size != Size) + return Error(SizeLoc, "size too large for vector"); + if (!VectorType::isValidElementType(EltTy)) + return Error(TypeLoc, "vector element type must be fp or integer"); + Result = VectorType::get(EltTy, unsigned(Size)); + } else { + if (!ArrayType::isValidElementType(EltTy)) + return Error(TypeLoc, "invalid array element type"); + Result = HandleUpRefs(ArrayType::get(EltTy, Size)); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Function Semantic Analysis. +//===----------------------------------------------------------------------===// + +LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f, + int functionNumber) + : P(p), F(f), FunctionNumber(functionNumber) { + + // Insert unnamed arguments into the NumberedVals list. + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); + AI != E; ++AI) + if (!AI->hasName()) + NumberedVals.push_back(AI); +} + +LLParser::PerFunctionState::~PerFunctionState() { + // If there were any forward referenced non-basicblock values, delete them. + for (std::map >::iterator + I = ForwardRefVals.begin(), E = ForwardRefVals.end(); I != E; ++I) + if (!isa(I->second.first)) { + I->second.first->replaceAllUsesWith( + UndefValue::get(I->second.first->getType())); + delete I->second.first; + I->second.first = 0; + } + + for (std::map >::iterator + I = ForwardRefValIDs.begin(), E = ForwardRefValIDs.end(); I != E; ++I) + if (!isa(I->second.first)) { + I->second.first->replaceAllUsesWith( + UndefValue::get(I->second.first->getType())); + delete I->second.first; + I->second.first = 0; + } +} + +bool LLParser::PerFunctionState::FinishFunction() { + // Check to see if someone took the address of labels in this block. + if (!P.ForwardRefBlockAddresses.empty()) { + ValID FunctionID; + if (!F.getName().empty()) { + FunctionID.Kind = ValID::t_GlobalName; + FunctionID.StrVal = F.getName(); + } else { + FunctionID.Kind = ValID::t_GlobalID; + FunctionID.UIntVal = FunctionNumber; + } + + std::map > >::iterator + FRBAI = P.ForwardRefBlockAddresses.find(FunctionID); + if (FRBAI != P.ForwardRefBlockAddresses.end()) { + // Resolve all these references. + if (P.ResolveForwardRefBlockAddresses(&F, FRBAI->second, this)) + return true; + + P.ForwardRefBlockAddresses.erase(FRBAI); + } + } + + if (!ForwardRefVals.empty()) + return P.Error(ForwardRefVals.begin()->second.second, + "use of undefined value '%" + ForwardRefVals.begin()->first + + "'"); + if (!ForwardRefValIDs.empty()) + return P.Error(ForwardRefValIDs.begin()->second.second, + "use of undefined value '%" + + Twine(ForwardRefValIDs.begin()->first) + "'"); + return false; +} + + +/// GetVal - Get a value with the specified name or ID, creating a +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. +Value *LLParser::PerFunctionState::GetVal(const std::string &Name, + const Type *Ty, LocTy Loc) { + // Look this name up in the normal function symbol table. + Value *Val = F.getValueSymbolTable().lookup(Name); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + if (Ty->isLabelTy()) + P.Error(Loc, "'%" + Name + "' is not a basic block"); + else + P.Error(Loc, "'%" + Name + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + // Don't make placeholders with invalid type. + if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) { + P.Error(Loc, "invalid use of a non-first-class type"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) + FwdVal = BasicBlock::Create(F.getContext(), Name, &F); + else + FwdVal = new Argument(Ty, Name); + + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty, + LocTy Loc) { + // Look this name up in the normal function symbol table. + Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : 0; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (Val == 0) { + std::map >::iterator + I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) { + if (Val->getType() == Ty) return Val; + if (Ty->isLabelTy()) + P.Error(Loc, "'%" + Twine(ID) + "' is not a basic block"); + else + P.Error(Loc, "'%" + Twine(ID) + "' defined with type '" + + Val->getType()->getDescription() + "'"); + return 0; + } + + if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) { + P.Error(Loc, "invalid use of a non-first-class type"); + return 0; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) + FwdVal = BasicBlock::Create(F.getContext(), "", &F); + else + FwdVal = new Argument(Ty); + + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +/// SetInstName - After an instruction is parsed and inserted into its +/// basic block, this installs its name. +bool LLParser::PerFunctionState::SetInstName(int NameID, + const std::string &NameStr, + LocTy NameLoc, Instruction *Inst) { + // If this instruction has void type, it cannot have a name or ID specified. + if (Inst->getType()->isVoidTy()) { + if (NameID != -1 || !NameStr.empty()) + return P.Error(NameLoc, "instructions returning void cannot have a name"); + return false; + } + + // If this was a numbered instruction, verify that the instruction is the + // expected value and resolve any forward references. + if (NameStr.empty()) { + // If neither a name nor an ID was specified, just use the next ID. + if (NameID == -1) + NameID = NumberedVals.size(); + + if (unsigned(NameID) != NumberedVals.size()) + return P.Error(NameLoc, "instruction expected to be numbered '%" + + Twine(NumberedVals.size()) + "'"); + + std::map >::iterator FI = + ForwardRefValIDs.find(NameID); + if (FI != ForwardRefValIDs.end()) { + if (FI->second.first->getType() != Inst->getType()) + return P.Error(NameLoc, "instruction forward referenced with type '" + + FI->second.first->getType()->getDescription() + "'"); + FI->second.first->replaceAllUsesWith(Inst); + delete FI->second.first; + ForwardRefValIDs.erase(FI); + } + + NumberedVals.push_back(Inst); + return false; + } + + // Otherwise, the instruction had a name. Resolve forward refs and set it. + std::map >::iterator + FI = ForwardRefVals.find(NameStr); + if (FI != ForwardRefVals.end()) { + if (FI->second.first->getType() != Inst->getType()) + return P.Error(NameLoc, "instruction forward referenced with type '" + + FI->second.first->getType()->getDescription() + "'"); + FI->second.first->replaceAllUsesWith(Inst); + delete FI->second.first; + ForwardRefVals.erase(FI); + } + + // Set the name on the instruction. + Inst->setName(NameStr); + + if (Inst->getName() != NameStr) + return P.Error(NameLoc, "multiple definition of local value named '" + + NameStr + "'"); + return false; +} + +/// GetBB - Get a basic block with the specified name or ID, creating a +/// forward reference record if needed. +BasicBlock *LLParser::PerFunctionState::GetBB(const std::string &Name, + LocTy Loc) { + return cast_or_null(GetVal(Name, + Type::getLabelTy(F.getContext()), Loc)); +} + +BasicBlock *LLParser::PerFunctionState::GetBB(unsigned ID, LocTy Loc) { + return cast_or_null(GetVal(ID, + Type::getLabelTy(F.getContext()), Loc)); +} + +/// DefineBB - Define the specified basic block, which is either named or +/// unnamed. If there is an error, this returns null otherwise it returns +/// the block being defined. +BasicBlock *LLParser::PerFunctionState::DefineBB(const std::string &Name, + LocTy Loc) { + BasicBlock *BB; + if (Name.empty()) + BB = GetBB(NumberedVals.size(), Loc); + else + BB = GetBB(Name, Loc); + if (BB == 0) return 0; // Already diagnosed error. + + // Move the block to the end of the function. Forward ref'd blocks are + // inserted wherever they happen to be referenced. + F.getBasicBlockList().splice(F.end(), F.getBasicBlockList(), BB); + + // Remove the block from forward ref sets. + if (Name.empty()) { + ForwardRefValIDs.erase(NumberedVals.size()); + NumberedVals.push_back(BB); + } else { + // BB forward references are already in the function symbol table. + ForwardRefVals.erase(Name); + } + + return BB; +} + +//===----------------------------------------------------------------------===// +// Constants. +//===----------------------------------------------------------------------===// + +/// ParseValID - Parse an abstract value that doesn't necessarily have a +/// type implied. For example, if we parse "4" we don't know what integer type +/// it has. The value will later be combined with its type and checked for +/// sanity. PFS is used to convert function-local operands of metadata (since +/// metadata operands are not just parsed here but also converted to values). +/// PFS can be null when we are not parsing metadata values inside a function. +bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { + ID.Loc = Lex.getLoc(); + switch (Lex.getKind()) { + default: return TokError("expected value token"); + case lltok::GlobalID: // @42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_GlobalID; + break; + case lltok::GlobalVar: // @foo + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_GlobalName; + break; + case lltok::LocalVarID: // %42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_LocalID; + break; + case lltok::LocalVar: // %foo + case lltok::StringConstant: // "foo" - FIXME: REMOVE IN LLVM 3.0 + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_LocalName; + break; + case lltok::exclaim: // !42, !{...}, or !"foo" + return ParseMetadataValue(ID, PFS); + case lltok::APSInt: + ID.APSIntVal = Lex.getAPSIntVal(); + ID.Kind = ValID::t_APSInt; + break; + case lltok::APFloat: + ID.APFloatVal = Lex.getAPFloatVal(); + ID.Kind = ValID::t_APFloat; + break; + case lltok::kw_true: + ID.ConstantVal = ConstantInt::getTrue(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_false: + ID.ConstantVal = ConstantInt::getFalse(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_null: ID.Kind = ValID::t_Null; break; + case lltok::kw_undef: ID.Kind = ValID::t_Undef; break; + case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break; + + case lltok::lbrace: { + // ValID ::= '{' ConstVector '}' + Lex.Lex(); + SmallVector Elts; + if (ParseGlobalValueVector(Elts) || + ParseToken(lltok::rbrace, "expected end of struct constant")) + return true; + + ID.ConstantVal = ConstantStruct::get(Context, Elts.data(), + Elts.size(), false); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::less: { + // ValID ::= '<' ConstVector '>' --> Vector. + // ValID ::= '<' '{' ConstVector '}' '>' --> Packed Struct. + Lex.Lex(); + bool isPackedStruct = EatIfPresent(lltok::lbrace); + + SmallVector Elts; + LocTy FirstEltLoc = Lex.getLoc(); + if (ParseGlobalValueVector(Elts) || + (isPackedStruct && + ParseToken(lltok::rbrace, "expected end of packed struct")) || + ParseToken(lltok::greater, "expected end of constant")) + return true; + + if (isPackedStruct) { + ID.ConstantVal = + ConstantStruct::get(Context, Elts.data(), Elts.size(), true); + ID.Kind = ValID::t_Constant; + return false; + } + + if (Elts.empty()) + return Error(ID.Loc, "constant vector must not be empty"); + + if (!Elts[0]->getType()->isIntegerTy() && + !Elts[0]->getType()->isFloatingPointTy()) + return Error(FirstEltLoc, + "vector elements must have integer or floating point type"); + + // Verify that all the vector elements have the same type. + for (unsigned i = 1, e = Elts.size(); i != e; ++i) + if (Elts[i]->getType() != Elts[0]->getType()) + return Error(FirstEltLoc, + "vector element #" + Twine(i) + + " is not of type '" + Elts[0]->getType()->getDescription()); + + ID.ConstantVal = ConstantVector::get(Elts); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::lsquare: { // Array Constant + Lex.Lex(); + SmallVector Elts; + LocTy FirstEltLoc = Lex.getLoc(); + if (ParseGlobalValueVector(Elts) || + ParseToken(lltok::rsquare, "expected end of array constant")) + return true; + + // Handle empty element. + if (Elts.empty()) { + // Use undef instead of an array because it's inconvenient to determine + // the element type at this point, there being no elements to examine. + ID.Kind = ValID::t_EmptyArray; + return false; + } + + if (!Elts[0]->getType()->isFirstClassType()) + return Error(FirstEltLoc, "invalid array element type: " + + Elts[0]->getType()->getDescription()); + + ArrayType *ATy = ArrayType::get(Elts[0]->getType(), Elts.size()); + + // Verify all elements are correct type! + for (unsigned i = 0, e = Elts.size(); i != e; ++i) { + if (Elts[i]->getType() != Elts[0]->getType()) + return Error(FirstEltLoc, + "array element #" + Twine(i) + + " is not of type '" +Elts[0]->getType()->getDescription()); + } + + ID.ConstantVal = ConstantArray::get(ATy, Elts.data(), Elts.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_c: // c "foo" + Lex.Lex(); + ID.ConstantVal = ConstantArray::get(Context, Lex.getStrVal(), false); + if (ParseToken(lltok::StringConstant, "expected string")) return true; + ID.Kind = ValID::t_Constant; + return false; + + case lltok::kw_asm: { + // ValID ::= 'asm' SideEffect? AlignStack? STRINGCONSTANT ',' STRINGCONSTANT + bool HasSideEffect, AlignStack; + Lex.Lex(); + if (ParseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || + ParseOptionalToken(lltok::kw_alignstack, AlignStack) || + ParseStringConstant(ID.StrVal) || + ParseToken(lltok::comma, "expected comma in inline asm expression") || + ParseToken(lltok::StringConstant, "expected constraint string")) + return true; + ID.StrVal2 = Lex.getStrVal(); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1); + ID.Kind = ValID::t_InlineAsm; + return false; + } + + case lltok::kw_blockaddress: { + // ValID ::= 'blockaddress' '(' @foo ',' %bar ')' + Lex.Lex(); + + ValID Fn, Label; + LocTy FnLoc, LabelLoc; + + if (ParseToken(lltok::lparen, "expected '(' in block address expression") || + ParseValID(Fn) || + ParseToken(lltok::comma, "expected comma in block address expression")|| + ParseValID(Label) || + ParseToken(lltok::rparen, "expected ')' in block address expression")) + return true; + + if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName) + return Error(Fn.Loc, "expected function name in blockaddress"); + if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName) + return Error(Label.Loc, "expected basic block name in blockaddress"); + + // Make a global variable as a placeholder for this reference. + GlobalVariable *FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), + false, GlobalValue::InternalLinkage, + 0, ""); + ForwardRefBlockAddresses[Fn].push_back(std::make_pair(Label, FwdRef)); + ID.ConstantVal = FwdRef; + ID.Kind = ValID::t_Constant; + return false; + } + + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: + case lltok::kw_ptrtoint: { + unsigned Opc = Lex.getUIntVal(); + PATypeHolder DestTy(Type::getVoidTy(Context)); + Constant *SrcVal; + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") || + ParseGlobalTypeAndValue(SrcVal) || + ParseToken(lltok::kw_to, "expected 'to' in constantexpr cast") || + ParseType(DestTy) || + ParseToken(lltok::rparen, "expected ')' at end of constantexpr cast")) + return true; + if (!CastInst::castIsValid((Instruction::CastOps)Opc, SrcVal, DestTy)) + return Error(ID.Loc, "invalid cast opcode for cast from '" + + SrcVal->getType()->getDescription() + "' to '" + + DestTy->getDescription() + "'"); + ID.ConstantVal = ConstantExpr::getCast((Instruction::CastOps)Opc, + SrcVal, DestTy); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_extractvalue: { + Lex.Lex(); + Constant *Val; + SmallVector Indices; + if (ParseToken(lltok::lparen, "expected '(' in extractvalue constantexpr")|| + ParseGlobalTypeAndValue(Val) || + ParseIndexList(Indices) || + ParseToken(lltok::rparen, "expected ')' in extractvalue constantexpr")) + return true; + + if (!Val->getType()->isAggregateType()) + return Error(ID.Loc, "extractvalue operand must be aggregate type"); + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), + Indices.end())) + return Error(ID.Loc, "invalid indices for extractvalue"); + ID.ConstantVal = + ConstantExpr::getExtractValue(Val, Indices.data(), Indices.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_insertvalue: { + Lex.Lex(); + Constant *Val0, *Val1; + SmallVector Indices; + if (ParseToken(lltok::lparen, "expected '(' in insertvalue constantexpr")|| + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in insertvalue constantexpr")|| + ParseGlobalTypeAndValue(Val1) || + ParseIndexList(Indices) || + ParseToken(lltok::rparen, "expected ')' in insertvalue constantexpr")) + return true; + if (!Val0->getType()->isAggregateType()) + return Error(ID.Loc, "insertvalue operand must be aggregate type"); + if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), + Indices.end())) + return Error(ID.Loc, "invalid indices for insertvalue"); + ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, + Indices.data(), Indices.size()); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_icmp: + case lltok::kw_fcmp: { + unsigned PredVal, Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + if (ParseCmpPredicate(PredVal, Opc) || + ParseToken(lltok::lparen, "expected '(' in compare constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in compare constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in compare constantexpr")) + return true; + + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "compare operands must have the same type"); + + CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal; + + if (Opc == Instruction::FCmp) { + if (!Val0->getType()->isFPOrFPVectorTy()) + return Error(ID.Loc, "fcmp requires floating point operands"); + ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1); + } else { + assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!"); + if (!Val0->getType()->isIntOrIntVectorTy() && + !Val0->getType()->isPointerTy()) + return Error(ID.Loc, "icmp requires pointer or integer operands"); + ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1); + } + ID.Kind = ValID::t_Constant; + return false; + } + + // Binary Operators. + case lltok::kw_add: + case lltok::kw_fadd: + case lltok::kw_sub: + case lltok::kw_fsub: + case lltok::kw_mul: + case lltok::kw_fmul: + case lltok::kw_udiv: + case lltok::kw_sdiv: + case lltok::kw_fdiv: + case lltok::kw_urem: + case lltok::kw_srem: + case lltok::kw_frem: + case lltok::kw_shl: + case lltok::kw_lshr: + case lltok::kw_ashr: { + bool NUW = false; + bool NSW = false; + bool Exact = false; + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + LocTy ModifierLoc = Lex.getLoc(); + if (Opc == Instruction::Add || Opc == Instruction::Sub || + Opc == Instruction::Mul || Opc == Instruction::Shl) { + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + if (EatIfPresent(lltok::kw_nsw)) { + NSW = true; + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + } + } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv || + Opc == Instruction::LShr || Opc == Instruction::AShr) { + if (EatIfPresent(lltok::kw_exact)) + Exact = true; + } + if (ParseToken(lltok::lparen, "expected '(' in binary constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in binary constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in binary constantexpr")) + return true; + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "operands of constexpr must have same type"); + if (!Val0->getType()->isIntOrIntVectorTy()) { + if (NUW) + return Error(ModifierLoc, "nuw only applies to integer operations"); + if (NSW) + return Error(ModifierLoc, "nsw only applies to integer operations"); + } + // Check that the type is valid for the operator. + switch (Opc) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::Shl: + case Instruction::AShr: + case Instruction::LShr: + if (!Val0->getType()->isIntOrIntVectorTy()) + return Error(ID.Loc, "constexpr requires integer operands"); + break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + if (!Val0->getType()->isFPOrFPVectorTy()) + return Error(ID.Loc, "constexpr requires fp operands"); + break; + default: llvm_unreachable("Unknown binary operator!"); + } + unsigned Flags = 0; + if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; + if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap; + if (Exact) Flags |= PossiblyExactOperator::IsExact; + Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags); + ID.ConstantVal = C; + ID.Kind = ValID::t_Constant; + return false; + } + + // Logical Operations + case lltok::kw_and: + case lltok::kw_or: + case lltok::kw_xor: { + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' in logical constantexpr") || + ParseGlobalTypeAndValue(Val0) || + ParseToken(lltok::comma, "expected comma in logical constantexpr") || + ParseGlobalTypeAndValue(Val1) || + ParseToken(lltok::rparen, "expected ')' in logical constantexpr")) + return true; + if (Val0->getType() != Val1->getType()) + return Error(ID.Loc, "operands of constexpr must have same type"); + if (!Val0->getType()->isIntOrIntVectorTy()) + return Error(ID.Loc, + "constexpr requires integer or integer vector operands"); + ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1); + ID.Kind = ValID::t_Constant; + return false; + } + + case lltok::kw_getelementptr: + case lltok::kw_shufflevector: + case lltok::kw_insertelement: + case lltok::kw_extractelement: + case lltok::kw_select: { + unsigned Opc = Lex.getUIntVal(); + SmallVector Elts; + bool InBounds = false; + Lex.Lex(); + if (Opc == Instruction::GetElementPtr) + InBounds = EatIfPresent(lltok::kw_inbounds); + if (ParseToken(lltok::lparen, "expected '(' in constantexpr") || + ParseGlobalValueVector(Elts) || + ParseToken(lltok::rparen, "expected ')' in constantexpr")) + return true; + + if (Opc == Instruction::GetElementPtr) { + if (Elts.size() == 0 || !Elts[0]->getType()->isPointerTy()) + return Error(ID.Loc, "getelementptr requires pointer operand"); + + if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), + (Value**)(Elts.data() + 1), + Elts.size() - 1)) + return Error(ID.Loc, "invalid indices for getelementptr"); + ID.ConstantVal = InBounds ? + ConstantExpr::getInBoundsGetElementPtr(Elts[0], + Elts.data() + 1, + Elts.size() - 1) : + ConstantExpr::getGetElementPtr(Elts[0], + Elts.data() + 1, Elts.size() - 1); + } else if (Opc == Instruction::Select) { + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to select"); + if (const char *Reason = SelectInst::areInvalidOperands(Elts[0], Elts[1], + Elts[2])) + return Error(ID.Loc, Reason); + ID.ConstantVal = ConstantExpr::getSelect(Elts[0], Elts[1], Elts[2]); + } else if (Opc == Instruction::ShuffleVector) { + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to shufflevector"); + if (!ShuffleVectorInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + return Error(ID.Loc, "invalid operands to shufflevector"); + ID.ConstantVal = + ConstantExpr::getShuffleVector(Elts[0], Elts[1],Elts[2]); + } else if (Opc == Instruction::ExtractElement) { + if (Elts.size() != 2) + return Error(ID.Loc, "expected two operands to extractelement"); + if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1])) + return Error(ID.Loc, "invalid extractelement operands"); + ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]); + } else { + assert(Opc == Instruction::InsertElement && "Unknown opcode"); + if (Elts.size() != 3) + return Error(ID.Loc, "expected three operands to insertelement"); + if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + return Error(ID.Loc, "invalid insertelement operands"); + ID.ConstantVal = + ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]); + } + + ID.Kind = ValID::t_Constant; + return false; + } + } + + Lex.Lex(); + return false; +} + +/// ParseGlobalValue - Parse a global value with the specified type. +bool LLParser::ParseGlobalValue(const Type *Ty, Constant *&C) { + C = 0; + ValID ID; + Value *V = NULL; + bool Parsed = ParseValID(ID) || + ConvertValIDToValue(Ty, ID, V, NULL); + if (V && !(C = dyn_cast(V))) + return Error(ID.Loc, "global values must be constants"); + return Parsed; +} + +bool LLParser::ParseGlobalTypeAndValue(Constant *&V) { + PATypeHolder Type(Type::getVoidTy(Context)); + return ParseType(Type) || + ParseGlobalValue(Type, V); +} + +/// ParseGlobalValueVector +/// ::= /*empty*/ +/// ::= TypeAndValue (',' TypeAndValue)* +bool LLParser::ParseGlobalValueVector(SmallVectorImpl &Elts) { + // Empty list. + if (Lex.getKind() == lltok::rbrace || + Lex.getKind() == lltok::rsquare || + Lex.getKind() == lltok::greater || + Lex.getKind() == lltok::rparen) + return false; + + Constant *C; + if (ParseGlobalTypeAndValue(C)) return true; + Elts.push_back(C); + + while (EatIfPresent(lltok::comma)) { + if (ParseGlobalTypeAndValue(C)) return true; + Elts.push_back(C); + } + + return false; +} + +bool LLParser::ParseMetadataListValue(ValID &ID, PerFunctionState *PFS) { + assert(Lex.getKind() == lltok::lbrace); + Lex.Lex(); + + SmallVector Elts; + if (ParseMDNodeVector(Elts, PFS) || + ParseToken(lltok::rbrace, "expected end of metadata node")) + return true; + + ID.MDNodeVal = MDNode::get(Context, Elts.data(), Elts.size()); + ID.Kind = ValID::t_MDNode; + return false; +} + +/// ParseMetadataValue +/// ::= !42 +/// ::= !{...} +/// ::= !"string" +bool LLParser::ParseMetadataValue(ValID &ID, PerFunctionState *PFS) { + assert(Lex.getKind() == lltok::exclaim); + Lex.Lex(); + + // MDNode: + // !{ ... } + if (Lex.getKind() == lltok::lbrace) + return ParseMetadataListValue(ID, PFS); + + // Standalone metadata reference + // !42 + if (Lex.getKind() == lltok::APSInt) { + if (ParseMDNodeID(ID.MDNodeVal)) return true; + ID.Kind = ValID::t_MDNode; + return false; + } + + // MDString: + // ::= '!' STRINGCONSTANT + if (ParseMDString(ID.MDStringVal)) return true; + ID.Kind = ValID::t_MDString; + return false; +} + + +//===----------------------------------------------------------------------===// +// Function Parsing. +//===----------------------------------------------------------------------===// + +bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, + PerFunctionState *PFS) { + if (Ty->isFunctionTy()) + return Error(ID.Loc, "functions are not values, refer to them as pointers"); + + switch (ID.Kind) { + default: llvm_unreachable("Unknown ValID!"); + case ValID::t_LocalID: + if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); + V = PFS->GetVal(ID.UIntVal, Ty, ID.Loc); + return (V == 0); + case ValID::t_LocalName: + if (!PFS) return Error(ID.Loc, "invalid use of function-local name"); + V = PFS->GetVal(ID.StrVal, Ty, ID.Loc); + return (V == 0); + case ValID::t_InlineAsm: { + const PointerType *PTy = dyn_cast(Ty); + const FunctionType *FTy = + PTy ? dyn_cast(PTy->getElementType()) : 0; + if (!FTy || !InlineAsm::Verify(FTy, ID.StrVal2)) + return Error(ID.Loc, "invalid type for inline asm constraint string"); + V = InlineAsm::get(FTy, ID.StrVal, ID.StrVal2, ID.UIntVal&1, ID.UIntVal>>1); + return false; + } + case ValID::t_MDNode: + if (!Ty->isMetadataTy()) + return Error(ID.Loc, "metadata value must have metadata type"); + V = ID.MDNodeVal; + return false; + case ValID::t_MDString: + if (!Ty->isMetadataTy()) + return Error(ID.Loc, "metadata value must have metadata type"); + V = ID.MDStringVal; + return false; + case ValID::t_GlobalName: + V = GetGlobalVal(ID.StrVal, Ty, ID.Loc); + return V == 0; + case ValID::t_GlobalID: + V = GetGlobalVal(ID.UIntVal, Ty, ID.Loc); + return V == 0; + case ValID::t_APSInt: + if (!Ty->isIntegerTy()) + return Error(ID.Loc, "integer constant must have integer type"); + ID.APSIntVal = ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits()); + V = ConstantInt::get(Context, ID.APSIntVal); + return false; + case ValID::t_APFloat: + if (!Ty->isFloatingPointTy() || + !ConstantFP::isValueValidForType(Ty, ID.APFloatVal)) + return Error(ID.Loc, "floating point constant invalid for type"); + + // The lexer has no type info, so builds all float and double FP constants + // as double. Fix this here. Long double does not need this. + if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble && + Ty->isFloatTy()) { + bool Ignored; + ID.APFloatVal.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, + &Ignored); + } + V = ConstantFP::get(Context, ID.APFloatVal); + + if (V->getType() != Ty) + return Error(ID.Loc, "floating point constant does not have type '" + + Ty->getDescription() + "'"); + + return false; + case ValID::t_Null: + if (!Ty->isPointerTy()) + return Error(ID.Loc, "null must be a pointer type"); + V = ConstantPointerNull::get(cast(Ty)); + return false; + case ValID::t_Undef: + // FIXME: LabelTy should not be a first-class type. + if ((!Ty->isFirstClassType() || Ty->isLabelTy()) && + !Ty->isOpaqueTy()) + return Error(ID.Loc, "invalid type for undef constant"); + V = UndefValue::get(Ty); + return false; + case ValID::t_EmptyArray: + if (!Ty->isArrayTy() || cast(Ty)->getNumElements() != 0) + return Error(ID.Loc, "invalid empty array initializer"); + V = UndefValue::get(Ty); + return false; + case ValID::t_Zero: + // FIXME: LabelTy should not be a first-class type. + if (!Ty->isFirstClassType() || Ty->isLabelTy()) + return Error(ID.Loc, "invalid type for null constant"); + V = Constant::getNullValue(Ty); + return false; + case ValID::t_Constant: + if (ID.ConstantVal->getType() != Ty) + return Error(ID.Loc, "constant expression type mismatch"); + + V = ID.ConstantVal; + return false; + } +} + +bool LLParser::ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS) { + V = 0; + ValID ID; + return ParseValID(ID, &PFS) || + ConvertValIDToValue(Ty, ID, V, &PFS); +} + +bool LLParser::ParseTypeAndValue(Value *&V, PerFunctionState &PFS) { + PATypeHolder T(Type::getVoidTy(Context)); + return ParseType(T) || + ParseValue(T, V, PFS); +} + +bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS) { + Value *V; + Loc = Lex.getLoc(); + if (ParseTypeAndValue(V, PFS)) return true; + if (!isa(V)) + return Error(Loc, "expected a basic block"); + BB = cast(V); + return false; +} + + +/// FunctionHeader +/// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs +/// OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection +/// OptionalAlign OptGC +bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { + // Parse the linkage. + LocTy LinkageLoc = Lex.getLoc(); + unsigned Linkage; + + unsigned Visibility, RetAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc = Lex.getLoc(); + if (ParseOptionalLinkage(Linkage) || + ParseOptionalVisibility(Visibility) || + ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/)) + return true; + + // Verify that the linkage is ok. + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::ExternalLinkage: + break; // always ok. + case GlobalValue::DLLImportLinkage: + case GlobalValue::ExternalWeakLinkage: + if (isDefine) + return Error(LinkageLoc, "invalid linkage for function definition"); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::LinkerPrivateLinkage: + case GlobalValue::LinkerPrivateWeakLinkage: + case GlobalValue::LinkerPrivateWeakDefAutoLinkage: + case GlobalValue::InternalLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::DLLExportLinkage: + if (!isDefine) + return Error(LinkageLoc, "invalid linkage for function declaration"); + break; + case GlobalValue::AppendingLinkage: + case GlobalValue::CommonLinkage: + return Error(LinkageLoc, "invalid function linkage type"); + } + + if (!FunctionType::isValidReturnType(RetType) || + RetType->isOpaqueTy()) + return Error(RetTypeLoc, "invalid function return type"); + + LocTy NameLoc = Lex.getLoc(); + + std::string FunctionName; + if (Lex.getKind() == lltok::GlobalVar) { + FunctionName = Lex.getStrVal(); + } else if (Lex.getKind() == lltok::GlobalID) { // @42 is ok. + unsigned NameID = Lex.getUIntVal(); + + if (NameID != NumberedVals.size()) + return TokError("function expected to be numbered '%" + + Twine(NumberedVals.size()) + "'"); + } else { + return TokError("expected function name"); + } + + Lex.Lex(); + + if (Lex.getKind() != lltok::lparen) + return TokError("expected '(' in function argument list"); + + std::vector ArgList; + bool isVarArg; + unsigned FuncAttrs; + std::string Section; + unsigned Alignment; + std::string GC; + bool UnnamedAddr; + LocTy UnnamedAddrLoc; + + if (ParseArgumentList(ArgList, isVarArg, false) || + ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, + &UnnamedAddrLoc) || + ParseOptionalAttrs(FuncAttrs, 2) || + (EatIfPresent(lltok::kw_section) && + ParseStringConstant(Section)) || + ParseOptionalAlignment(Alignment) || + (EatIfPresent(lltok::kw_gc) && + ParseStringConstant(GC))) + return true; + + // If the alignment was parsed as an attribute, move to the alignment field. + if (FuncAttrs & Attribute::Alignment) { + Alignment = Attribute::getAlignmentFromAttrs(FuncAttrs); + FuncAttrs &= ~Attribute::Alignment; + } + + // Okay, if we got here, the function is syntactically valid. Convert types + // and do semantic checks. + std::vector ParamTypeList; + SmallVector Attrs; + // FIXME : In 3.0, stop accepting zext, sext and inreg as optional function + // attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FuncAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FuncAttrs & ObsoleteFuncAttrs; + FuncAttrs &= ~ObsoleteFuncAttrs; + } + + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + ParamTypeList.push_back(ArgList[i].Type); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (FuncAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FuncAttrs)); + + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + if (PAL.paramHasAttr(1, Attribute::StructRet) && !RetType->isVoidTy()) + return Error(RetTypeLoc, "functions with 'sret' argument must return void"); + + const FunctionType *FT = + FunctionType::get(RetType, ParamTypeList, isVarArg); + const PointerType *PFT = PointerType::getUnqual(FT); + + Fn = 0; + if (!FunctionName.empty()) { + // If this was a definition of a forward reference, remove the definition + // from the forward reference table and fill in the forward ref. + std::map >::iterator FRVI = + ForwardRefVals.find(FunctionName); + if (FRVI != ForwardRefVals.end()) { + Fn = M->getFunction(FunctionName); + if (Fn->getType() != PFT) + return Error(FRVI->second.second, "invalid forward reference to " + "function '" + FunctionName + "' with wrong type!"); + + ForwardRefVals.erase(FRVI); + } else if ((Fn = M->getFunction(FunctionName))) { + // If this function already exists in the symbol table, then it is + // multiply defined. We accept a few cases for old backwards compat. + // FIXME: Remove this stuff for LLVM 3.0. + if (Fn->getType() != PFT || Fn->getAttributes() != PAL || + (!Fn->isDeclaration() && isDefine)) { + // If the redefinition has different type or different attributes, + // reject it. If both have bodies, reject it. + return Error(NameLoc, "invalid redefinition of function '" + + FunctionName + "'"); + } else if (Fn->isDeclaration()) { + // Make sure to strip off any argument names so we can't get conflicts. + for (Function::arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end(); + AI != AE; ++AI) + AI->setName(""); + } + } else if (M->getNamedValue(FunctionName)) { + return Error(NameLoc, "redefinition of function '@" + FunctionName + "'"); + } + + } else { + // If this is a definition of a forward referenced function, make sure the + // types agree. + std::map >::iterator I + = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + Fn = cast(I->second.first); + if (Fn->getType() != PFT) + return Error(NameLoc, "type of definition and forward reference of '@" + + Twine(NumberedVals.size()) + "' disagree"); + ForwardRefValIDs.erase(I); + } + } + + if (Fn == 0) + Fn = Function::Create(FT, GlobalValue::ExternalLinkage, FunctionName, M); + else // Move the forward-reference to the correct spot in the module. + M->getFunctionList().splice(M->end(), M->getFunctionList(), Fn); + + if (FunctionName.empty()) + NumberedVals.push_back(Fn); + + Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); + Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); + Fn->setCallingConv(CC); + Fn->setAttributes(PAL); + Fn->setUnnamedAddr(UnnamedAddr); + Fn->setAlignment(Alignment); + Fn->setSection(Section); + if (!GC.empty()) Fn->setGC(GC.c_str()); + + // Add all of the arguments we parsed to the function. + Function::arg_iterator ArgIt = Fn->arg_begin(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) { + // If we run out of arguments in the Function prototype, exit early. + // FIXME: REMOVE THIS IN LLVM 3.0, this is just for the mismatch case above. + if (ArgIt == Fn->arg_end()) break; + + // If the argument has a name, insert it into the argument symbol table. + if (ArgList[i].Name.empty()) continue; + + // Set the name, if it conflicted, it will be auto-renamed. + ArgIt->setName(ArgList[i].Name); + + if (ArgIt->getName() != ArgList[i].Name) + return Error(ArgList[i].Loc, "redefinition of argument '%" + + ArgList[i].Name + "'"); + } + + return false; +} + + +/// ParseFunctionBody +/// ::= '{' BasicBlock+ '}' +/// ::= 'begin' BasicBlock+ 'end' // FIXME: remove in LLVM 3.0 +/// +bool LLParser::ParseFunctionBody(Function &Fn) { + if (Lex.getKind() != lltok::lbrace && Lex.getKind() != lltok::kw_begin) + return TokError("expected '{' in function body"); + Lex.Lex(); // eat the {. + + int FunctionNumber = -1; + if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1; + + PerFunctionState PFS(*this, Fn, FunctionNumber); + + // We need at least one basic block. + if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::kw_end) + return TokError("function body requires at least one basic block"); + + while (Lex.getKind() != lltok::rbrace && Lex.getKind() != lltok::kw_end) + if (ParseBasicBlock(PFS)) return true; + + // Eat the }. + Lex.Lex(); + + // Verify function is ok. + return PFS.FinishFunction(); +} + +/// ParseBasicBlock +/// ::= LabelStr? Instruction* +bool LLParser::ParseBasicBlock(PerFunctionState &PFS) { + // If this basic block starts out with a name, remember it. + std::string Name; + LocTy NameLoc = Lex.getLoc(); + if (Lex.getKind() == lltok::LabelStr) { + Name = Lex.getStrVal(); + Lex.Lex(); + } + + BasicBlock *BB = PFS.DefineBB(Name, NameLoc); + if (BB == 0) return true; + + std::string NameStr; + + // Parse the instructions in this block until we get a terminator. + Instruction *Inst; + SmallVector, 4> MetadataOnInst; + do { + // This instruction may have three possibilities for a name: a) none + // specified, b) name specified "%foo =", c) number specified: "%4 =". + LocTy NameLoc = Lex.getLoc(); + int NameID = -1; + NameStr = ""; + + if (Lex.getKind() == lltok::LocalVarID) { + NameID = Lex.getUIntVal(); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after instruction id")) + return true; + } else if (Lex.getKind() == lltok::LocalVar || + // FIXME: REMOVE IN LLVM 3.0 + Lex.getKind() == lltok::StringConstant) { + NameStr = Lex.getStrVal(); + Lex.Lex(); + if (ParseToken(lltok::equal, "expected '=' after instruction name")) + return true; + } + + switch (ParseInstruction(Inst, BB, PFS)) { + default: assert(0 && "Unknown ParseInstruction result!"); + case InstError: return true; + case InstNormal: + BB->getInstList().push_back(Inst); + + // With a normal result, we check to see if the instruction is followed by + // a comma and metadata. + if (EatIfPresent(lltok::comma)) + if (ParseInstructionMetadata(Inst, &PFS)) + return true; + break; + case InstExtraComma: + BB->getInstList().push_back(Inst); + + // If the instruction parser ate an extra comma at the end of it, it + // *must* be followed by metadata. + if (ParseInstructionMetadata(Inst, &PFS)) + return true; + break; + } + + // Set the name on the instruction. + if (PFS.SetInstName(NameID, NameStr, NameLoc, Inst)) return true; + } while (!isa(Inst)); + + return false; +} + +//===----------------------------------------------------------------------===// +// Instruction Parsing. +//===----------------------------------------------------------------------===// + +/// ParseInstruction - Parse one of the many different instructions. +/// +int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS) { + lltok::Kind Token = Lex.getKind(); + if (Token == lltok::Eof) + return TokError("found end of file when expecting more instructions"); + LocTy Loc = Lex.getLoc(); + unsigned KeywordVal = Lex.getUIntVal(); + Lex.Lex(); // Eat the keyword. + + switch (Token) { + default: return Error(Loc, "expected instruction opcode"); + // Terminator Instructions. + case lltok::kw_unwind: Inst = new UnwindInst(Context); return false; + case lltok::kw_unreachable: Inst = new UnreachableInst(Context); return false; + case lltok::kw_ret: return ParseRet(Inst, BB, PFS); + case lltok::kw_br: return ParseBr(Inst, PFS); + case lltok::kw_switch: return ParseSwitch(Inst, PFS); + case lltok::kw_indirectbr: return ParseIndirectBr(Inst, PFS); + case lltok::kw_invoke: return ParseInvoke(Inst, PFS); + // Binary Operators. + case lltok::kw_add: + case lltok::kw_sub: + case lltok::kw_mul: + case lltok::kw_shl: { + LocTy ModifierLoc = Lex.getLoc(); + bool NUW = EatIfPresent(lltok::kw_nuw); + bool NSW = EatIfPresent(lltok::kw_nsw); + if (!NUW) NUW = EatIfPresent(lltok::kw_nuw); + + if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true; + + if (NUW) cast(Inst)->setHasNoUnsignedWrap(true); + if (NSW) cast(Inst)->setHasNoSignedWrap(true); + return false; + } + case lltok::kw_fadd: + case lltok::kw_fsub: + case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2); + + case lltok::kw_sdiv: + case lltok::kw_udiv: + case lltok::kw_lshr: + case lltok::kw_ashr: { + bool Exact = EatIfPresent(lltok::kw_exact); + + if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true; + if (Exact) cast(Inst)->setIsExact(true); + return false; + } + + case lltok::kw_urem: + case lltok::kw_srem: return ParseArithmetic(Inst, PFS, KeywordVal, 1); + case lltok::kw_fdiv: + case lltok::kw_frem: return ParseArithmetic(Inst, PFS, KeywordVal, 2); + case lltok::kw_and: + case lltok::kw_or: + case lltok::kw_xor: return ParseLogical(Inst, PFS, KeywordVal); + case lltok::kw_icmp: + case lltok::kw_fcmp: return ParseCompare(Inst, PFS, KeywordVal); + // Casts. + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: + case lltok::kw_ptrtoint: return ParseCast(Inst, PFS, KeywordVal); + // Other. + case lltok::kw_select: return ParseSelect(Inst, PFS); + case lltok::kw_va_arg: return ParseVA_Arg(Inst, PFS); + case lltok::kw_extractelement: return ParseExtractElement(Inst, PFS); + case lltok::kw_insertelement: return ParseInsertElement(Inst, PFS); + case lltok::kw_shufflevector: return ParseShuffleVector(Inst, PFS); + case lltok::kw_phi: return ParsePHI(Inst, PFS); + case lltok::kw_call: return ParseCall(Inst, PFS, false); + case lltok::kw_tail: return ParseCall(Inst, PFS, true); + // Memory. + case lltok::kw_alloca: return ParseAlloc(Inst, PFS); + case lltok::kw_malloc: return ParseAlloc(Inst, PFS, BB, false); + case lltok::kw_free: return ParseFree(Inst, PFS, BB); + case lltok::kw_load: return ParseLoad(Inst, PFS, false); + case lltok::kw_store: return ParseStore(Inst, PFS, false); + case lltok::kw_volatile: + if (EatIfPresent(lltok::kw_load)) + return ParseLoad(Inst, PFS, true); + else if (EatIfPresent(lltok::kw_store)) + return ParseStore(Inst, PFS, true); + else + return TokError("expected 'load' or 'store'"); + case lltok::kw_getresult: return ParseGetResult(Inst, PFS); + case lltok::kw_getelementptr: return ParseGetElementPtr(Inst, PFS); + case lltok::kw_extractvalue: return ParseExtractValue(Inst, PFS); + case lltok::kw_insertvalue: return ParseInsertValue(Inst, PFS); + } +} + +/// ParseCmpPredicate - Parse an integer or fp predicate, based on Kind. +bool LLParser::ParseCmpPredicate(unsigned &P, unsigned Opc) { + if (Opc == Instruction::FCmp) { + switch (Lex.getKind()) { + default: TokError("expected fcmp predicate (e.g. 'oeq')"); + case lltok::kw_oeq: P = CmpInst::FCMP_OEQ; break; + case lltok::kw_one: P = CmpInst::FCMP_ONE; break; + case lltok::kw_olt: P = CmpInst::FCMP_OLT; break; + case lltok::kw_ogt: P = CmpInst::FCMP_OGT; break; + case lltok::kw_ole: P = CmpInst::FCMP_OLE; break; + case lltok::kw_oge: P = CmpInst::FCMP_OGE; break; + case lltok::kw_ord: P = CmpInst::FCMP_ORD; break; + case lltok::kw_uno: P = CmpInst::FCMP_UNO; break; + case lltok::kw_ueq: P = CmpInst::FCMP_UEQ; break; + case lltok::kw_une: P = CmpInst::FCMP_UNE; break; + case lltok::kw_ult: P = CmpInst::FCMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::FCMP_UGT; break; + case lltok::kw_ule: P = CmpInst::FCMP_ULE; break; + case lltok::kw_uge: P = CmpInst::FCMP_UGE; break; + case lltok::kw_true: P = CmpInst::FCMP_TRUE; break; + case lltok::kw_false: P = CmpInst::FCMP_FALSE; break; + } + } else { + switch (Lex.getKind()) { + default: TokError("expected icmp predicate (e.g. 'eq')"); + case lltok::kw_eq: P = CmpInst::ICMP_EQ; break; + case lltok::kw_ne: P = CmpInst::ICMP_NE; break; + case lltok::kw_slt: P = CmpInst::ICMP_SLT; break; + case lltok::kw_sgt: P = CmpInst::ICMP_SGT; break; + case lltok::kw_sle: P = CmpInst::ICMP_SLE; break; + case lltok::kw_sge: P = CmpInst::ICMP_SGE; break; + case lltok::kw_ult: P = CmpInst::ICMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::ICMP_UGT; break; + case lltok::kw_ule: P = CmpInst::ICMP_ULE; break; + case lltok::kw_uge: P = CmpInst::ICMP_UGE; break; + } + } + Lex.Lex(); + return false; +} + +//===----------------------------------------------------------------------===// +// Terminator Instructions. +//===----------------------------------------------------------------------===// + +/// ParseRet - Parse a return instruction. +/// ::= 'ret' void (',' !dbg, !1)* +/// ::= 'ret' TypeAndValue (',' !dbg, !1)* +/// ::= 'ret' TypeAndValue (',' TypeAndValue)+ (',' !dbg, !1)* +/// [[obsolete: LLVM 3.0]] +int LLParser::ParseRet(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS) { + PATypeHolder Ty(Type::getVoidTy(Context)); + if (ParseType(Ty, true /*void allowed*/)) return true; + + if (Ty->isVoidTy()) { + Inst = ReturnInst::Create(Context); + return false; + } + + Value *RV; + if (ParseValue(Ty, RV, PFS)) return true; + + bool ExtraComma = false; + if (EatIfPresent(lltok::comma)) { + // Parse optional custom metadata, e.g. !dbg + if (Lex.getKind() == lltok::MetadataVar) { + ExtraComma = true; + } else { + // The normal case is one return value. + // FIXME: LLVM 3.0 remove MRV support for 'ret i32 1, i32 2', requiring + // use of 'ret {i32,i32} {i32 1, i32 2}' + SmallVector RVs; + RVs.push_back(RV); + + do { + // If optional custom metadata, e.g. !dbg is seen then this is the + // end of MRV. + if (Lex.getKind() == lltok::MetadataVar) + break; + if (ParseTypeAndValue(RV, PFS)) return true; + RVs.push_back(RV); + } while (EatIfPresent(lltok::comma)); + + RV = UndefValue::get(PFS.getFunction().getReturnType()); + for (unsigned i = 0, e = RVs.size(); i != e; ++i) { + Instruction *I = InsertValueInst::Create(RV, RVs[i], i, "mrv"); + BB->getInstList().push_back(I); + RV = I; + } + } + } + + Inst = ReturnInst::Create(Context, RV); + return ExtraComma ? InstExtraComma : InstNormal; +} + + +/// ParseBr +/// ::= 'br' TypeAndValue +/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseBr(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc, Loc2; + Value *Op0; + BasicBlock *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS)) return true; + + if (BasicBlock *BB = dyn_cast(Op0)) { + Inst = BranchInst::Create(BB); + return false; + } + + if (Op0->getType() != Type::getInt1Ty(Context)) + return Error(Loc, "branch condition must have 'i1' type"); + + if (ParseToken(lltok::comma, "expected ',' after branch condition") || + ParseTypeAndBasicBlock(Op1, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after true destination") || + ParseTypeAndBasicBlock(Op2, Loc2, PFS)) + return true; + + Inst = BranchInst::Create(Op1, Op2, Op0); + return false; +} + +/// ParseSwitch +/// Instruction +/// ::= 'switch' TypeAndValue ',' TypeAndValue '[' JumpTable ']' +/// JumpTable +/// ::= (TypeAndValue ',' TypeAndValue)* +bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) { + LocTy CondLoc, BBLoc; + Value *Cond; + BasicBlock *DefaultBB; + if (ParseTypeAndValue(Cond, CondLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after switch condition") || + ParseTypeAndBasicBlock(DefaultBB, BBLoc, PFS) || + ParseToken(lltok::lsquare, "expected '[' with switch table")) + return true; + + if (!Cond->getType()->isIntegerTy()) + return Error(CondLoc, "switch condition must have integer type"); + + // Parse the jump table pairs. + SmallPtrSet SeenCases; + SmallVector, 32> Table; + while (Lex.getKind() != lltok::rsquare) { + Value *Constant; + BasicBlock *DestBB; + + if (ParseTypeAndValue(Constant, CondLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after case value") || + ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + + if (!SeenCases.insert(Constant)) + return Error(CondLoc, "duplicate case value in switch"); + if (!isa(Constant)) + return Error(CondLoc, "case value is not a constant integer"); + + Table.push_back(std::make_pair(cast(Constant), DestBB)); + } + + Lex.Lex(); // Eat the ']'. + + SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size()); + for (unsigned i = 0, e = Table.size(); i != e; ++i) + SI->addCase(Table[i].first, Table[i].second); + Inst = SI; + return false; +} + +/// ParseIndirectBr +/// Instruction +/// ::= 'indirectbr' TypeAndValue ',' '[' LabelList ']' +bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { + LocTy AddrLoc; + Value *Address; + if (ParseTypeAndValue(Address, AddrLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after indirectbr address") || + ParseToken(lltok::lsquare, "expected '[' with indirectbr")) + return true; + + if (!Address->getType()->isPointerTy()) + return Error(AddrLoc, "indirectbr address must have pointer type"); + + // Parse the destination list. + SmallVector DestList; + + if (Lex.getKind() != lltok::rsquare) { + BasicBlock *DestBB; + if (ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + DestList.push_back(DestBB); + + while (EatIfPresent(lltok::comma)) { + if (ParseTypeAndBasicBlock(DestBB, PFS)) + return true; + DestList.push_back(DestBB); + } + } + + if (ParseToken(lltok::rsquare, "expected ']' at end of block list")) + return true; + + IndirectBrInst *IBI = IndirectBrInst::Create(Address, DestList.size()); + for (unsigned i = 0, e = DestList.size(); i != e; ++i) + IBI->addDestination(DestList[i]); + Inst = IBI; + return false; +} + + +/// ParseInvoke +/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList +/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue +bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { + LocTy CallLoc = Lex.getLoc(); + unsigned RetAttrs, FnAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector ArgList; + + BasicBlock *NormalBB, *UnwindBB; + if (ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/) || + ParseValID(CalleeID) || + ParseParameterList(ArgList, PFS) || + ParseOptionalAttrs(FnAttrs, 2) || + ParseToken(lltok::kw_to, "expected 'to' in invoke") || + ParseTypeAndBasicBlock(NormalBB, PFS) || + ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") || + ParseTypeAndBasicBlock(UnwindBB, PFS)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; + if (!(PFTy = dyn_cast(RetType)) || + !(Ty = dyn_cast(PFTy->getElementType()))) { + // Pull out the types of all of the arguments... + std::vector ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) + return Error(RetTypeLoc, "Invalid result type for LLVM function"); + + Ty = FunctionType::get(RetType, ParamTypes, false); + PFTy = PointerType::getUnqual(Ty); + } + + // Look up the callee. + Value *Callee; + if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; + + // FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional + // function attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FnAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FnAttrs & ObsoleteFuncAttrs; + FnAttrs &= ~ObsoleteFuncAttrs; + } + + // Set up the Attributes for the function. + SmallVector Attrs; + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + SmallVector Args; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + const Type *ExpectedTy = 0; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { + return Error(ArgList[i].Loc, "too many arguments specified"); + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + return Error(ArgList[i].Loc, "argument is not of expected type '" + + ExpectedTy->getDescription() + "'"); + Args.push_back(ArgList[i].V); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (I != E) + return Error(CallLoc, "not enough parameters specified for call"); + + if (FnAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Finish off the Attributes and check them + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + InvokeInst *II = InvokeInst::Create(Callee, NormalBB, UnwindBB, + Args.begin(), Args.end()); + II->setCallingConv(CC); + II->setAttributes(PAL); + Inst = II; + return false; +} + + + +//===----------------------------------------------------------------------===// +// Binary Operators. +//===----------------------------------------------------------------------===// + +/// ParseArithmetic +/// ::= ArithmeticOps TypeAndValue ',' Value +/// +/// If OperandType is 0, then any FP or integer operand is allowed. If it is 1, +/// then any integer operand is allowed, if it is 2, any fp operand is allowed. +bool LLParser::ParseArithmetic(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc, unsigned OperandType) { + LocTy Loc; Value *LHS, *RHS; + if (ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' in arithmetic operation") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + bool Valid; + switch (OperandType) { + default: llvm_unreachable("Unknown operand type!"); + case 0: // int or FP. + Valid = LHS->getType()->isIntOrIntVectorTy() || + LHS->getType()->isFPOrFPVectorTy(); + break; + case 1: Valid = LHS->getType()->isIntOrIntVectorTy(); break; + case 2: Valid = LHS->getType()->isFPOrFPVectorTy(); break; + } + + if (!Valid) + return Error(Loc, "invalid operand type for instruction"); + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + +/// ParseLogical +/// ::= ArithmeticOps TypeAndValue ',' Value { +bool LLParser::ParseLogical(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + LocTy Loc; Value *LHS, *RHS; + if (ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' in logical operation") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + if (!LHS->getType()->isIntOrIntVectorTy()) + return Error(Loc,"instruction requires integer or integer vector operands"); + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + + +/// ParseCompare +/// ::= 'icmp' IPredicates TypeAndValue ',' Value +/// ::= 'fcmp' FPredicates TypeAndValue ',' Value +bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + // Parse the integer/fp comparison predicate. + LocTy Loc; + unsigned Pred; + Value *LHS, *RHS; + if (ParseCmpPredicate(Pred, Opc) || + ParseTypeAndValue(LHS, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after compare value") || + ParseValue(LHS->getType(), RHS, PFS)) + return true; + + if (Opc == Instruction::FCmp) { + if (!LHS->getType()->isFPOrFPVectorTy()) + return Error(Loc, "fcmp requires floating point operands"); + Inst = new FCmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } else { + assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!"); + if (!LHS->getType()->isIntOrIntVectorTy() && + !LHS->getType()->isPointerTy()) + return Error(Loc, "icmp requires integer operands"); + Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Other Instructions. +//===----------------------------------------------------------------------===// + + +/// ParseCast +/// ::= CastOpc TypeAndValue 'to' Type +bool LLParser::ParseCast(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc) { + LocTy Loc; Value *Op; + PATypeHolder DestTy(Type::getVoidTy(Context)); + if (ParseTypeAndValue(Op, Loc, PFS) || + ParseToken(lltok::kw_to, "expected 'to' after cast value") || + ParseType(DestTy)) + return true; + + if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy)) { + CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy); + return Error(Loc, "invalid cast opcode for cast from '" + + Op->getType()->getDescription() + "' to '" + + DestTy->getDescription() + "'"); + } + Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy); + return false; +} + +/// ParseSelect +/// ::= 'select' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseSelect(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after select condition") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after select value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (const char *Reason = SelectInst::areInvalidOperands(Op0, Op1, Op2)) + return Error(Loc, Reason); + + Inst = SelectInst::Create(Op0, Op1, Op2); + return false; +} + +/// ParseVA_Arg +/// ::= 'va_arg' TypeAndValue ',' Type +bool LLParser::ParseVA_Arg(Instruction *&Inst, PerFunctionState &PFS) { + Value *Op; + PATypeHolder EltTy(Type::getVoidTy(Context)); + LocTy TypeLoc; + if (ParseTypeAndValue(Op, PFS) || + ParseToken(lltok::comma, "expected ',' after vaarg operand") || + ParseType(EltTy, TypeLoc)) + return true; + + if (!EltTy->isFirstClassType()) + return Error(TypeLoc, "va_arg requires operand with first class type"); + + Inst = new VAArgInst(Op, EltTy); + return false; +} + +/// ParseExtractElement +/// ::= 'extractelement' TypeAndValue ',' TypeAndValue +bool LLParser::ParseExtractElement(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after extract value") || + ParseTypeAndValue(Op1, PFS)) + return true; + + if (!ExtractElementInst::isValidOperands(Op0, Op1)) + return Error(Loc, "invalid extractelement operands"); + + Inst = ExtractElementInst::Create(Op0, Op1); + return false; +} + +/// ParseInsertElement +/// ::= 'insertelement' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseInsertElement(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (!InsertElementInst::isValidOperands(Op0, Op1, Op2)) + return Error(Loc, "invalid insertelement operands"); + + Inst = InsertElementInst::Create(Op0, Op1, Op2); + return false; +} + +/// ParseShuffleVector +/// ::= 'shufflevector' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::ParseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc; + Value *Op0, *Op1, *Op2; + if (ParseTypeAndValue(Op0, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after shuffle mask") || + ParseTypeAndValue(Op1, PFS) || + ParseToken(lltok::comma, "expected ',' after shuffle value") || + ParseTypeAndValue(Op2, PFS)) + return true; + + if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2)) + return Error(Loc, "invalid extractelement operands"); + + Inst = new ShuffleVectorInst(Op0, Op1, Op2); + return false; +} + +/// ParsePHI +/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')* +int LLParser::ParsePHI(Instruction *&Inst, PerFunctionState &PFS) { + PATypeHolder Ty(Type::getVoidTy(Context)); + Value *Op0, *Op1; + LocTy TypeLoc = Lex.getLoc(); + + if (ParseType(Ty) || + ParseToken(lltok::lsquare, "expected '[' in phi value list") || + ParseValue(Ty, Op0, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseValue(Type::getLabelTy(Context), Op1, PFS) || + ParseToken(lltok::rsquare, "expected ']' in phi value list")) + return true; + + bool AteExtraComma = false; + SmallVector, 16> PHIVals; + while (1) { + PHIVals.push_back(std::make_pair(Op0, cast(Op1))); + + if (!EatIfPresent(lltok::comma)) + break; + + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + break; + } + + if (ParseToken(lltok::lsquare, "expected '[' in phi value list") || + ParseValue(Ty, Op0, PFS) || + ParseToken(lltok::comma, "expected ',' after insertelement value") || + ParseValue(Type::getLabelTy(Context), Op1, PFS) || + ParseToken(lltok::rsquare, "expected ']' in phi value list")) + return true; + } + + if (!Ty->isFirstClassType()) + return Error(TypeLoc, "phi node must have first class type"); + + PHINode *PN = PHINode::Create(Ty); + PN->reserveOperandSpace(PHIVals.size()); + for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) + PN->addIncoming(PHIVals[i].first, PHIVals[i].second); + Inst = PN; + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseCall +/// ::= 'tail'? 'call' OptionalCallingConv OptionalAttrs Type Value +/// ParameterList OptionalAttrs +bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, + bool isTail) { + unsigned RetAttrs, FnAttrs; + CallingConv::ID CC; + PATypeHolder RetType(Type::getVoidTy(Context)); + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector ArgList; + LocTy CallLoc = Lex.getLoc(); + + if ((isTail && ParseToken(lltok::kw_call, "expected 'tail call'")) || + ParseOptionalCallingConv(CC) || + ParseOptionalAttrs(RetAttrs, 1) || + ParseType(RetType, RetTypeLoc, true /*void allowed*/) || + ParseValID(CalleeID) || + ParseParameterList(ArgList, PFS) || + ParseOptionalAttrs(FnAttrs, 2)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + const PointerType *PFTy = 0; + const FunctionType *Ty = 0; + if (!(PFTy = dyn_cast(RetType)) || + !(Ty = dyn_cast(PFTy->getElementType()))) { + // Pull out the types of all of the arguments... + std::vector ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) + return Error(RetTypeLoc, "Invalid result type for LLVM function"); + + Ty = FunctionType::get(RetType, ParamTypes, false); + PFTy = PointerType::getUnqual(Ty); + } + + // Look up the callee. + Value *Callee; + if (ConvertValIDToValue(PFTy, CalleeID, Callee, &PFS)) return true; + + // FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional + // function attributes. + unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg; + if (FnAttrs & ObsoleteFuncAttrs) { + RetAttrs |= FnAttrs & ObsoleteFuncAttrs; + FnAttrs &= ~ObsoleteFuncAttrs; + } + + // Set up the Attributes for the function. + SmallVector Attrs; + if (RetAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttrs)); + + SmallVector Args; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + const Type *ExpectedTy = 0; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { + return Error(ArgList[i].Loc, "too many arguments specified"); + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + return Error(ArgList[i].Loc, "argument is not of expected type '" + + ExpectedTy->getDescription() + "'"); + Args.push_back(ArgList[i].V); + if (ArgList[i].Attrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(i+1, ArgList[i].Attrs)); + } + + if (I != E) + return Error(CallLoc, "not enough parameters specified for call"); + + if (FnAttrs != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0, FnAttrs)); + + // Finish off the Attributes and check them + AttrListPtr PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); + + CallInst *CI = CallInst::Create(Callee, Args.begin(), Args.end()); + CI->setTailCall(isTail); + CI->setCallingConv(CC); + CI->setAttributes(PAL); + Inst = CI; + return false; +} + +//===----------------------------------------------------------------------===// +// Memory Instructions. +//===----------------------------------------------------------------------===// + +/// ParseAlloc +/// ::= 'malloc' Type (',' TypeAndValue)? (',' OptionalInfo)? +/// ::= 'alloca' Type (',' TypeAndValue)? (',' OptionalInfo)? +int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS, + BasicBlock* BB, bool isAlloca) { + PATypeHolder Ty(Type::getVoidTy(Context)); + Value *Size = 0; + LocTy SizeLoc; + unsigned Alignment = 0; + if (ParseType(Ty)) return true; + + bool AteExtraComma = false; + if (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::kw_align) { + if (ParseOptionalAlignment(Alignment)) return true; + } else if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + } else { + if (ParseTypeAndValue(Size, SizeLoc, PFS) || + ParseOptionalCommaAlign(Alignment, AteExtraComma)) + return true; + } + } + + if (Size && !Size->getType()->isIntegerTy()) + return Error(SizeLoc, "element count must have integer type"); + + if (isAlloca) { + Inst = new AllocaInst(Ty, Size, Alignment); + return AteExtraComma ? InstExtraComma : InstNormal; + } + + // Autoupgrade old malloc instruction to malloc call. + // FIXME: Remove in LLVM 3.0. + if (Size && !Size->getType()->isIntegerTy(32)) + return Error(SizeLoc, "element count must be i32"); + const Type *IntPtrTy = Type::getInt32Ty(Context); + Constant *AllocSize = ConstantExpr::getSizeOf(Ty); + AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, IntPtrTy); + if (!MallocF) + // Prototype malloc as "void *(int32)". + // This function is renamed as "malloc" in ValidateEndOfModule(). + MallocF = cast( + M->getOrInsertFunction("", Type::getInt8PtrTy(Context), IntPtrTy, NULL)); + Inst = CallInst::CreateMalloc(BB, IntPtrTy, Ty, AllocSize, Size, MallocF); +return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseFree +/// ::= 'free' TypeAndValue +bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS, + BasicBlock* BB) { + Value *Val; LocTy Loc; + if (ParseTypeAndValue(Val, Loc, PFS)) return true; + if (!Val->getType()->isPointerTy()) + return Error(Loc, "operand to free must be a pointer"); + Inst = CallInst::CreateFree(Val, BB); + return false; +} + +/// ParseLoad +/// ::= 'volatile'? 'load' TypeAndValue (',' OptionalInfo)? +int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS, + bool isVolatile) { + Value *Val; LocTy Loc; + unsigned Alignment = 0; + bool AteExtraComma = false; + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseOptionalCommaAlign(Alignment, AteExtraComma)) + return true; + + if (!Val->getType()->isPointerTy() || + !cast(Val->getType())->getElementType()->isFirstClassType()) + return Error(Loc, "load operand must be a pointer to a first class type"); + + Inst = new LoadInst(Val, "", isVolatile, Alignment); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseStore +/// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)? +int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS, + bool isVolatile) { + Value *Val, *Ptr; LocTy Loc, PtrLoc; + unsigned Alignment = 0; + bool AteExtraComma = false; + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseToken(lltok::comma, "expected ',' after store operand") || + ParseTypeAndValue(Ptr, PtrLoc, PFS) || + ParseOptionalCommaAlign(Alignment, AteExtraComma)) + return true; + + if (!Ptr->getType()->isPointerTy()) + return Error(PtrLoc, "store operand must be a pointer"); + if (!Val->getType()->isFirstClassType()) + return Error(Loc, "store operand must be a first class value"); + if (cast(Ptr->getType())->getElementType() != Val->getType()) + return Error(Loc, "stored value and pointer type do not match"); + + Inst = new StoreInst(Val, Ptr, isVolatile, Alignment); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseGetResult +/// ::= 'getresult' TypeAndValue ',' i32 +/// FIXME: Remove support for getresult in LLVM 3.0 +bool LLParser::ParseGetResult(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val; LocTy ValLoc, EltLoc; + unsigned Element; + if (ParseTypeAndValue(Val, ValLoc, PFS) || + ParseToken(lltok::comma, "expected ',' after getresult operand") || + ParseUInt32(Element, EltLoc)) + return true; + + if (!Val->getType()->isStructTy() && !Val->getType()->isArrayTy()) + return Error(ValLoc, "getresult inst requires an aggregate operand"); + if (!ExtractValueInst::getIndexedType(Val->getType(), Element)) + return Error(EltLoc, "invalid getresult index for value"); + Inst = ExtractValueInst::Create(Val, Element); + return false; +} + +/// ParseGetElementPtr +/// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)* +int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { + Value *Ptr, *Val; LocTy Loc, EltLoc; + + bool InBounds = EatIfPresent(lltok::kw_inbounds); + + if (ParseTypeAndValue(Ptr, Loc, PFS)) return true; + + if (!Ptr->getType()->isPointerTy()) + return Error(Loc, "base of getelementptr must be a pointer"); + + SmallVector Indices; + bool AteExtraComma = false; + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + break; + } + if (ParseTypeAndValue(Val, EltLoc, PFS)) return true; + if (!Val->getType()->isIntegerTy()) + return Error(EltLoc, "getelementptr index must be an integer"); + Indices.push_back(Val); + } + + if (!GetElementPtrInst::getIndexedType(Ptr->getType(), + Indices.begin(), Indices.end())) + return Error(Loc, "invalid getelementptr indices"); + Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end()); + if (InBounds) + cast(Inst)->setIsInBounds(true); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseExtractValue +/// ::= 'extractvalue' TypeAndValue (',' uint32)+ +int LLParser::ParseExtractValue(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val; LocTy Loc; + SmallVector Indices; + bool AteExtraComma; + if (ParseTypeAndValue(Val, Loc, PFS) || + ParseIndexList(Indices, AteExtraComma)) + return true; + + if (!Val->getType()->isAggregateType()) + return Error(Loc, "extractvalue operand must be aggregate type"); + + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), + Indices.end())) + return Error(Loc, "invalid indices for extractvalue"); + Inst = ExtractValueInst::Create(Val, Indices.begin(), Indices.end()); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +/// ParseInsertValue +/// ::= 'insertvalue' TypeAndValue ',' TypeAndValue (',' uint32)+ +int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { + Value *Val0, *Val1; LocTy Loc0, Loc1; + SmallVector Indices; + bool AteExtraComma; + if (ParseTypeAndValue(Val0, Loc0, PFS) || + ParseToken(lltok::comma, "expected comma after insertvalue operand") || + ParseTypeAndValue(Val1, Loc1, PFS) || + ParseIndexList(Indices, AteExtraComma)) + return true; + + if (!Val0->getType()->isAggregateType()) + return Error(Loc0, "insertvalue operand must be aggregate type"); + + if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), + Indices.end())) + return Error(Loc0, "invalid indices for insertvalue"); + Inst = InsertValueInst::Create(Val0, Val1, Indices.begin(), Indices.end()); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +//===----------------------------------------------------------------------===// +// Embedded metadata. +//===----------------------------------------------------------------------===// + +/// ParseMDNodeVector +/// ::= Element (',' Element)* +/// Element +/// ::= 'null' | TypeAndValue +bool LLParser::ParseMDNodeVector(SmallVectorImpl &Elts, + PerFunctionState *PFS) { + // Check for an empty list. + if (Lex.getKind() == lltok::rbrace) + return false; + + do { + // Null is a special case since it is typeless. + if (EatIfPresent(lltok::kw_null)) { + Elts.push_back(0); + continue; + } + + Value *V = 0; + PATypeHolder Ty(Type::getVoidTy(Context)); + ValID ID; + if (ParseType(Ty) || ParseValID(ID, PFS) || + ConvertValIDToValue(Ty, ID, V, PFS)) + return true; + + Elts.push_back(V); + } while (EatIfPresent(lltok::comma)); + + return false; +} diff --git a/final/lib/AsmParser/LLParser.h b/final/lib/AsmParser/LLParser.h new file mode 100644 index 00000000000..93e7f778ebc --- /dev/null +++ b/final/lib/AsmParser/LLParser.h @@ -0,0 +1,378 @@ +//===-- LLParser.h - Parser Class -------------------------------*- 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 parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASMPARSER_LLPARSER_H +#define LLVM_ASMPARSER_LLPARSER_H + +#include "LLLexer.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/ValueHandle.h" +#include + +namespace llvm { + class Module; + class OpaqueType; + class Function; + class Value; + class BasicBlock; + class Instruction; + class Constant; + class GlobalValue; + class MDString; + class MDNode; + + /// ValID - Represents a reference of a definition of some sort with no type. + /// There are several cases where we have to parse the value but where the + /// type can depend on later context. This may either be a numeric reference + /// or a symbolic (%var) reference. This is just a discriminated union. + struct ValID { + enum { + t_LocalID, t_GlobalID, // ID in UIntVal. + t_LocalName, t_GlobalName, // Name in StrVal. + t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal. + t_Null, t_Undef, t_Zero, // No value. + t_EmptyArray, // No value: [] + t_Constant, // Value in ConstantVal. + t_InlineAsm, // Value in StrVal/StrVal2/UIntVal. + t_MDNode, // Value in MDNodeVal. + t_MDString // Value in MDStringVal. + } Kind; + + LLLexer::LocTy Loc; + unsigned UIntVal; + std::string StrVal, StrVal2; + APSInt APSIntVal; + APFloat APFloatVal; + Constant *ConstantVal; + MDNode *MDNodeVal; + MDString *MDStringVal; + ValID() : APFloatVal(0.0) {} + + bool operator<(const ValID &RHS) const { + if (Kind == t_LocalID || Kind == t_GlobalID) + return UIntVal < RHS.UIntVal; + assert((Kind == t_LocalName || Kind == t_GlobalName) && + "Ordering not defined for this ValID kind yet"); + return StrVal < RHS.StrVal; + } + }; + + class LLParser { + public: + typedef LLLexer::LocTy LocTy; + private: + LLVMContext &Context; + LLLexer Lex; + Module *M; + + // Instruction metadata resolution. Each instruction can have a list of + // MDRef info associated with them. + // + // The simpler approach of just creating temporary MDNodes and then calling + // RAUW on them when the definition is processed doesn't work because some + // instruction metadata kinds, such as dbg, get stored in the IR in an + // "optimized" format which doesn't participate in the normal value use + // lists. This means that RAUW doesn't work, even on temporary MDNodes + // which otherwise support RAUW. Instead, we defer resolving MDNode + // references until the definitions have been processed. + struct MDRef { + SMLoc Loc; + unsigned MDKind, MDSlot; + }; + DenseMap > ForwardRefInstMetadata; + + // Type resolution handling data structures. + std::map > ForwardRefTypes; + std::map > ForwardRefTypeIDs; + std::vector NumberedTypes; + std::vector > NumberedMetadata; + std::map, LocTy> > ForwardRefMDNodes; + struct UpRefRecord { + /// Loc - This is the location of the upref. + LocTy Loc; + + /// NestingLevel - The number of nesting levels that need to be popped + /// before this type is resolved. + unsigned NestingLevel; + + /// LastContainedTy - This is the type at the current binding level for + /// the type. Every time we reduce the nesting level, this gets updated. + const Type *LastContainedTy; + + /// UpRefTy - This is the actual opaque type that the upreference is + /// represented with. + OpaqueType *UpRefTy; + + UpRefRecord(LocTy L, unsigned NL, OpaqueType *URTy) + : Loc(L), NestingLevel(NL), LastContainedTy((Type*)URTy), + UpRefTy(URTy) {} + }; + std::vector UpRefs; + + // Global Value reference information. + std::map > ForwardRefVals; + std::map > ForwardRefValIDs; + std::vector NumberedVals; + + // References to blockaddress. The key is the function ValID, the value is + // a list of references to blocks in that function. + std::map > > + ForwardRefBlockAddresses; + + Function *MallocF; + public: + LLParser(MemoryBuffer *F, SourceMgr &SM, SMDiagnostic &Err, Module *m) : + Context(m->getContext()), Lex(F, SM, Err, m->getContext()), + M(m), MallocF(NULL) {} + bool Run(); + + LLVMContext& getContext() { return Context; } + + private: + + bool Error(LocTy L, const Twine &Msg) const { + return Lex.Error(L, Msg); + } + bool TokError(const Twine &Msg) const { + return Error(Lex.getLoc(), Msg); + } + + /// GetGlobalVal - Get a value with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. + GlobalValue *GetGlobalVal(const std::string &N, const Type *Ty, LocTy Loc); + GlobalValue *GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc); + + // Helper Routines. + bool ParseToken(lltok::Kind T, const char *ErrMsg); + bool EatIfPresent(lltok::Kind T) { + if (Lex.getKind() != T) return false; + Lex.Lex(); + return true; + } + bool ParseOptionalToken(lltok::Kind T, bool &Present, LocTy *Loc = 0) { + if (Lex.getKind() != T) { + Present = false; + } else { + if (Loc) + *Loc = Lex.getLoc(); + Lex.Lex(); + Present = true; + } + return false; + } + bool ParseStringConstant(std::string &Result); + bool ParseUInt32(unsigned &Val); + bool ParseUInt32(unsigned &Val, LocTy &Loc) { + Loc = Lex.getLoc(); + return ParseUInt32(Val); + } + bool ParseOptionalAddrSpace(unsigned &AddrSpace); + bool ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind); + bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage); + bool ParseOptionalLinkage(unsigned &Linkage) { + bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage); + } + bool ParseOptionalVisibility(unsigned &Visibility); + bool ParseOptionalCallingConv(CallingConv::ID &CC); + bool ParseOptionalAlignment(unsigned &Alignment); + bool ParseOptionalStackAlignment(unsigned &Alignment); + bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma); + bool ParseIndexList(SmallVectorImpl &Indices,bool &AteExtraComma); + bool ParseIndexList(SmallVectorImpl &Indices) { + bool AteExtraComma; + if (ParseIndexList(Indices, AteExtraComma)) return true; + if (AteExtraComma) + return TokError("expected index"); + return false; + } + + // Top-Level Entities + bool ParseTopLevelEntities(); + bool ValidateEndOfModule(); + bool ParseTargetDefinition(); + bool ParseDepLibs(); + bool ParseModuleAsm(); + bool ParseUnnamedType(); + bool ParseNamedType(); + bool ParseDeclare(); + bool ParseDefine(); + + bool ParseGlobalType(bool &IsConstant); + bool ParseUnnamedGlobal(); + bool ParseNamedGlobal(); + bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, + bool HasLinkage, unsigned Visibility); + bool ParseAlias(const std::string &Name, LocTy Loc, unsigned Visibility); + bool ParseStandaloneMetadata(); + bool ParseNamedMetadata(); + bool ParseMDString(MDString *&Result); + bool ParseMDNodeID(MDNode *&Result); + bool ParseMDNodeID(MDNode *&Result, unsigned &SlotNo); + + // Type Parsing. + bool ParseType(PATypeHolder &Result, bool AllowVoid = false); + bool ParseType(PATypeHolder &Result, LocTy &Loc, bool AllowVoid = false) { + Loc = Lex.getLoc(); + return ParseType(Result, AllowVoid); + } + bool ParseTypeRec(PATypeHolder &H); + bool ParseStructType(PATypeHolder &H, bool Packed); + bool ParseArrayVectorType(PATypeHolder &H, bool isVector); + bool ParseFunctionType(PATypeHolder &Result); + PATypeHolder HandleUpRefs(const Type *Ty); + + // Function Semantic Analysis. + class PerFunctionState { + LLParser &P; + Function &F; + std::map > ForwardRefVals; + std::map > ForwardRefValIDs; + std::vector NumberedVals; + + /// FunctionNumber - If this is an unnamed function, this is the slot + /// number of it, otherwise it is -1. + int FunctionNumber; + public: + PerFunctionState(LLParser &p, Function &f, int FunctionNumber); + ~PerFunctionState(); + + Function &getFunction() const { return F; } + + bool FinishFunction(); + + /// GetVal - Get a value with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. + Value *GetVal(const std::string &Name, const Type *Ty, LocTy Loc); + Value *GetVal(unsigned ID, const Type *Ty, LocTy Loc); + + /// SetInstName - After an instruction is parsed and inserted into its + /// basic block, this installs its name. + bool SetInstName(int NameID, const std::string &NameStr, LocTy NameLoc, + Instruction *Inst); + + /// GetBB - Get a basic block with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// is not a BasicBlock. + BasicBlock *GetBB(const std::string &Name, LocTy Loc); + BasicBlock *GetBB(unsigned ID, LocTy Loc); + + /// DefineBB - Define the specified basic block, which is either named or + /// unnamed. If there is an error, this returns null otherwise it returns + /// the block being defined. + BasicBlock *DefineBB(const std::string &Name, LocTy Loc); + }; + + bool ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, + PerFunctionState *PFS); + + bool ParseValue(const Type *Ty, Value *&V, PerFunctionState &PFS); + bool ParseValue(const Type *Ty, Value *&V, LocTy &Loc, + PerFunctionState &PFS) { + Loc = Lex.getLoc(); + return ParseValue(Ty, V, PFS); + } + + bool ParseTypeAndValue(Value *&V, PerFunctionState &PFS); + bool ParseTypeAndValue(Value *&V, LocTy &Loc, PerFunctionState &PFS) { + Loc = Lex.getLoc(); + return ParseTypeAndValue(V, PFS); + } + bool ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, + PerFunctionState &PFS); + bool ParseTypeAndBasicBlock(BasicBlock *&BB, PerFunctionState &PFS) { + LocTy Loc; + return ParseTypeAndBasicBlock(BB, Loc, PFS); + } + + + struct ParamInfo { + LocTy Loc; + Value *V; + unsigned Attrs; + ParamInfo(LocTy loc, Value *v, unsigned attrs) + : Loc(loc), V(v), Attrs(attrs) {} + }; + bool ParseParameterList(SmallVectorImpl &ArgList, + PerFunctionState &PFS); + + // Constant Parsing. + bool ParseValID(ValID &ID, PerFunctionState *PFS = NULL); + bool ParseGlobalValue(const Type *Ty, Constant *&V); + bool ParseGlobalTypeAndValue(Constant *&V); + bool ParseGlobalValueVector(SmallVectorImpl &Elts); + bool ParseMetadataListValue(ValID &ID, PerFunctionState *PFS); + bool ParseMetadataValue(ValID &ID, PerFunctionState *PFS); + bool ParseMDNodeVector(SmallVectorImpl &, PerFunctionState *PFS); + bool ParseInstructionMetadata(Instruction *Inst, PerFunctionState *PFS); + + // Function Parsing. + struct ArgInfo { + LocTy Loc; + PATypeHolder Type; + unsigned Attrs; + std::string Name; + ArgInfo(LocTy L, PATypeHolder Ty, unsigned Attr, const std::string &N) + : Loc(L), Type(Ty), Attrs(Attr), Name(N) {} + }; + bool ParseArgumentList(std::vector &ArgList, + bool &isVarArg, bool inType); + bool ParseFunctionHeader(Function *&Fn, bool isDefine); + bool ParseFunctionBody(Function &Fn); + bool ParseBasicBlock(PerFunctionState &PFS); + + // Instruction Parsing. Each instruction parsing routine can return with a + // normal result, an error result, or return having eaten an extra comma. + enum InstResult { InstNormal = 0, InstError = 1, InstExtraComma = 2 }; + int ParseInstruction(Instruction *&Inst, BasicBlock *BB, + PerFunctionState &PFS); + bool ParseCmpPredicate(unsigned &Pred, unsigned Opc); + + int ParseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); + bool ParseBr(Instruction *&Inst, PerFunctionState &PFS); + bool ParseSwitch(Instruction *&Inst, PerFunctionState &PFS); + bool ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS); + bool ParseInvoke(Instruction *&Inst, PerFunctionState &PFS); + + bool ParseArithmetic(Instruction *&I, PerFunctionState &PFS, unsigned Opc, + unsigned OperandType); + bool ParseLogical(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseCompare(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseCast(Instruction *&I, PerFunctionState &PFS, unsigned Opc); + bool ParseSelect(Instruction *&I, PerFunctionState &PFS); + bool ParseVA_Arg(Instruction *&I, PerFunctionState &PFS); + bool ParseExtractElement(Instruction *&I, PerFunctionState &PFS); + bool ParseInsertElement(Instruction *&I, PerFunctionState &PFS); + bool ParseShuffleVector(Instruction *&I, PerFunctionState &PFS); + int ParsePHI(Instruction *&I, PerFunctionState &PFS); + bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail); + int ParseAlloc(Instruction *&I, PerFunctionState &PFS, + BasicBlock *BB = 0, bool isAlloca = true); + bool ParseFree(Instruction *&I, PerFunctionState &PFS, BasicBlock *BB); + int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile); + int ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile); + bool ParseGetResult(Instruction *&I, PerFunctionState &PFS); + int ParseGetElementPtr(Instruction *&I, PerFunctionState &PFS); + int ParseExtractValue(Instruction *&I, PerFunctionState &PFS); + int ParseInsertValue(Instruction *&I, PerFunctionState &PFS); + + bool ResolveForwardRefBlockAddresses(Function *TheFn, + std::vector > &Refs, + PerFunctionState *PFS); + }; +} // End llvm namespace + +#endif diff --git a/final/lib/AsmParser/LLToken.h b/final/lib/AsmParser/LLToken.h new file mode 100644 index 00000000000..576da191aec --- /dev/null +++ b/final/lib/AsmParser/LLToken.h @@ -0,0 +1,148 @@ +//===- LLToken.h - Token Codes for LLVM Assembly Files ----------*- 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 enums for the .ll lexer. +// +//===----------------------------------------------------------------------===// + +#ifndef LIBS_ASMPARSER_LLTOKEN_H +#define LIBS_ASMPARSER_LLTOKEN_H + +namespace llvm { +namespace lltok { + enum Kind { + // Markers + Eof, Error, + + // Tokens with no info. + dotdotdot, // ... + equal, comma, // = , + star, // * + lsquare, rsquare, // [ ] + lbrace, rbrace, // { } + less, greater, // < > + lparen, rparen, // ( ) + backslash, // \ (not /) + exclaim, // ! + + kw_x, + kw_begin, kw_end, + kw_true, kw_false, + kw_declare, kw_define, + kw_global, kw_constant, + + kw_private, kw_linker_private, kw_linker_private_weak, + kw_linker_private_weak_def_auto, kw_internal, + kw_linkonce, kw_linkonce_odr, kw_weak, kw_weak_odr, kw_appending, + kw_dllimport, kw_dllexport, kw_common, kw_available_externally, + kw_default, kw_hidden, kw_protected, + kw_unnamed_addr, + kw_extern_weak, + kw_external, kw_thread_local, + kw_zeroinitializer, + kw_undef, kw_null, + kw_to, + kw_tail, + kw_target, + kw_triple, + kw_deplibs, + kw_datalayout, + kw_volatile, + kw_nuw, + kw_nsw, + kw_exact, + kw_inbounds, + kw_align, + kw_addrspace, + kw_section, + kw_alias, + kw_module, + kw_asm, + kw_sideeffect, + kw_alignstack, + kw_gc, + kw_c, + + kw_cc, kw_ccc, kw_fastcc, kw_coldcc, + kw_x86_stdcallcc, kw_x86_fastcallcc, kw_x86_thiscallcc, + kw_arm_apcscc, kw_arm_aapcscc, kw_arm_aapcs_vfpcc, + kw_msp430_intrcc, + kw_ptx_kernel, kw_ptx_device, + + kw_signext, + kw_zeroext, + kw_inreg, + kw_sret, + kw_nounwind, + kw_noreturn, + kw_noalias, + kw_nocapture, + kw_byval, + kw_nest, + kw_readnone, + kw_readonly, + + kw_inlinehint, + kw_noinline, + kw_alwaysinline, + kw_optsize, + kw_ssp, + kw_sspreq, + kw_noredzone, + kw_noimplicitfloat, + kw_naked, + kw_hotpatch, + + kw_type, + kw_opaque, + + kw_eq, kw_ne, kw_slt, kw_sgt, kw_sle, kw_sge, kw_ult, kw_ugt, kw_ule, + kw_uge, kw_oeq, kw_one, kw_olt, kw_ogt, kw_ole, kw_oge, kw_ord, kw_uno, + kw_ueq, kw_une, + + // Instruction Opcodes (Opcode in UIntVal). + kw_add, kw_fadd, kw_sub, kw_fsub, kw_mul, kw_fmul, + kw_udiv, kw_sdiv, kw_fdiv, + kw_urem, kw_srem, kw_frem, kw_shl, kw_lshr, kw_ashr, + kw_and, kw_or, kw_xor, kw_icmp, kw_fcmp, + + kw_phi, kw_call, + kw_trunc, kw_zext, kw_sext, kw_fptrunc, kw_fpext, kw_uitofp, kw_sitofp, + kw_fptoui, kw_fptosi, kw_inttoptr, kw_ptrtoint, kw_bitcast, + kw_select, kw_va_arg, + + kw_ret, kw_br, kw_switch, kw_indirectbr, kw_invoke, kw_unwind, + kw_unreachable, + + kw_malloc, kw_alloca, kw_free, kw_load, kw_store, kw_getelementptr, + + kw_extractelement, kw_insertelement, kw_shufflevector, kw_getresult, + kw_extractvalue, kw_insertvalue, kw_blockaddress, + + // Unsigned Valued tokens (UIntVal). + GlobalID, // @42 + LocalVarID, // %42 + + // String valued tokens (StrVal). + LabelStr, // foo: + GlobalVar, // @foo @"foo" + LocalVar, // %foo %"foo" + MetadataVar, // !foo + StringConstant, // "foo" + + // Type valued tokens (TyVal). + Type, + + APFloat, // APFloatVal + APSInt // APSInt + }; +} // end namespace lltok +} // end namespace llvm + +#endif diff --git a/final/lib/AsmParser/Makefile b/final/lib/AsmParser/Makefile new file mode 100644 index 00000000000..995bb0e130e --- /dev/null +++ b/final/lib/AsmParser/Makefile @@ -0,0 +1,14 @@ +##===- lib/AsmParser/Makefile ------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME := LLVMAsmParser +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common diff --git a/final/lib/AsmParser/Parser.cpp b/final/lib/AsmParser/Parser.cpp new file mode 100644 index 00000000000..59fb471f2b9 --- /dev/null +++ b/final/lib/AsmParser/Parser.cpp @@ -0,0 +1,62 @@ +//===- Parser.cpp - Main dispatch module for the Parser library -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This library implements the functionality defined in llvm/Assembly/Parser.h +// +//===----------------------------------------------------------------------===// + +#include "llvm/Assembly/Parser.h" +#include "LLParser.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include +using namespace llvm; + +Module *llvm::ParseAssembly(MemoryBuffer *F, + Module *M, + SMDiagnostic &Err, + LLVMContext &Context) { + SourceMgr SM; + SM.AddNewSourceBuffer(F, SMLoc()); + + // If we are parsing into an existing module, do it. + if (M) + return LLParser(F, SM, Err, M).Run() ? 0 : M; + + // Otherwise create a new module. + OwningPtr M2(new Module(F->getBufferIdentifier(), Context)); + if (LLParser(F, SM, Err, M2.get()).Run()) + return 0; + return M2.take(); +} + +Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, + LLVMContext &Context) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); + return 0; + } + + return ParseAssembly(File.take(), 0, Err, Context); +} + +Module *llvm::ParseAssemblyString(const char *AsmString, Module *M, + SMDiagnostic &Err, LLVMContext &Context) { + MemoryBuffer *F = + MemoryBuffer::getMemBuffer(StringRef(AsmString, strlen(AsmString)), + ""); + + return ParseAssembly(F, M, Err, Context); +} diff --git a/final/lib/Bitcode/CMakeLists.txt b/final/lib/Bitcode/CMakeLists.txt new file mode 100644 index 00000000000..ff7e290cad1 --- /dev/null +++ b/final/lib/Bitcode/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(Reader) +add_subdirectory(Writer) diff --git a/final/lib/Bitcode/Makefile b/final/lib/Bitcode/Makefile new file mode 100644 index 00000000000..2d6b5ad1fe8 --- /dev/null +++ b/final/lib/Bitcode/Makefile @@ -0,0 +1,14 @@ +##===- lib/Bitcode/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 = Reader Writer + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Bitcode/Reader/BitReader.cpp b/final/lib/Bitcode/Reader/BitReader.cpp new file mode 100644 index 00000000000..15844c0041c --- /dev/null +++ b/final/lib/Bitcode/Reader/BitReader.cpp @@ -0,0 +1,88 @@ +//===-- BitReader.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/BitReader.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/MemoryBuffer.h" +#include +#include + +using namespace llvm; + +/* Builds a module from the bitcode in the specified memory buffer, returning a + reference to the module via the OutModule parameter. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, char **OutMessage) { + return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule, + OutMessage); +} + +LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutModule, + char **OutMessage) { + std::string Message; + + *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), *unwrap(ContextRef), + &Message)); + if (!*OutModule) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; +} + +/* Reads a module from the specified path, returning via the OutModule parameter + a module provider which performs lazy deserialization. Returns 0 on success. + Optionally returns a human-readable error message via OutMessage. */ +LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutM, + char **OutMessage) { + std::string Message; + + *OutM = wrap(getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef), + &Message)); + if (!*OutM) { + if (OutMessage) + *OutMessage = strdup(Message.c_str()); + return 1; + } + + return 0; + +} + +LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage) { + return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM, + OutMessage); +} + +/* Deprecated: Use LLVMGetBitcodeModuleInContext instead. */ +LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage) { + return LLVMGetBitcodeModuleInContext(ContextRef, MemBuf, + reinterpret_cast(OutMP), + OutMessage); +} + +/* Deprecated: Use LLVMGetBitcodeModule instead. */ +LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage) { + return LLVMGetBitcodeModuleProviderInContext(LLVMGetGlobalContext(), MemBuf, + OutMP, OutMessage); +} diff --git a/final/lib/Bitcode/Reader/BitcodeReader.cpp b/final/lib/Bitcode/Reader/BitcodeReader.cpp new file mode 100644 index 00000000000..dbf8da02799 --- /dev/null +++ b/final/lib/Bitcode/Reader/BitcodeReader.cpp @@ -0,0 +1,2690 @@ +//===- BitcodeReader.cpp - Internal BitcodeReader implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitcodeReader class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "BitcodeReader.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/AutoUpgrade.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/OperandTraits.h" +using namespace llvm; + +void BitcodeReader::FreeState() { + if (BufferOwned) + delete Buffer; + Buffer = 0; + std::vector().swap(TypeList); + ValueList.clear(); + MDValueList.clear(); + + std::vector().swap(MAttributes); + std::vector().swap(FunctionBBs); + std::vector().swap(FunctionsWithBodies); + DeferredFunctionInfo.clear(); + MDKindMap.clear(); +} + +//===----------------------------------------------------------------------===// +// Helper functions to implement forward reference resolution, etc. +//===----------------------------------------------------------------------===// + +/// ConvertToString - Convert a string from a record into an std::string, return +/// true on failure. +template +static bool ConvertToString(SmallVector &Record, unsigned Idx, + StrTy &Result) { + if (Idx > Record.size()) + return true; + + for (unsigned i = Idx, e = Record.size(); i != e; ++i) + Result += (char)Record[i]; + return false; +} + +static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) { + switch (Val) { + default: // Map unknown/new linkages to external + case 0: return GlobalValue::ExternalLinkage; + case 1: return GlobalValue::WeakAnyLinkage; + case 2: return GlobalValue::AppendingLinkage; + case 3: return GlobalValue::InternalLinkage; + case 4: return GlobalValue::LinkOnceAnyLinkage; + case 5: return GlobalValue::DLLImportLinkage; + case 6: return GlobalValue::DLLExportLinkage; + case 7: return GlobalValue::ExternalWeakLinkage; + case 8: return GlobalValue::CommonLinkage; + case 9: return GlobalValue::PrivateLinkage; + case 10: return GlobalValue::WeakODRLinkage; + case 11: return GlobalValue::LinkOnceODRLinkage; + case 12: return GlobalValue::AvailableExternallyLinkage; + case 13: return GlobalValue::LinkerPrivateLinkage; + case 14: return GlobalValue::LinkerPrivateWeakLinkage; + case 15: return GlobalValue::LinkerPrivateWeakDefAutoLinkage; + } +} + +static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) { + switch (Val) { + default: // Map unknown visibilities to default. + case 0: return GlobalValue::DefaultVisibility; + case 1: return GlobalValue::HiddenVisibility; + case 2: return GlobalValue::ProtectedVisibility; + } +} + +static int GetDecodedCastOpcode(unsigned Val) { + switch (Val) { + default: return -1; + case bitc::CAST_TRUNC : return Instruction::Trunc; + case bitc::CAST_ZEXT : return Instruction::ZExt; + case bitc::CAST_SEXT : return Instruction::SExt; + case bitc::CAST_FPTOUI : return Instruction::FPToUI; + case bitc::CAST_FPTOSI : return Instruction::FPToSI; + case bitc::CAST_UITOFP : return Instruction::UIToFP; + case bitc::CAST_SITOFP : return Instruction::SIToFP; + case bitc::CAST_FPTRUNC : return Instruction::FPTrunc; + case bitc::CAST_FPEXT : return Instruction::FPExt; + case bitc::CAST_PTRTOINT: return Instruction::PtrToInt; + case bitc::CAST_INTTOPTR: return Instruction::IntToPtr; + case bitc::CAST_BITCAST : return Instruction::BitCast; + } +} +static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) { + switch (Val) { + default: return -1; + case bitc::BINOP_ADD: + return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add; + case bitc::BINOP_SUB: + return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub; + case bitc::BINOP_MUL: + return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul; + case bitc::BINOP_UDIV: return Instruction::UDiv; + case bitc::BINOP_SDIV: + return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv; + case bitc::BINOP_UREM: return Instruction::URem; + case bitc::BINOP_SREM: + return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem; + case bitc::BINOP_SHL: return Instruction::Shl; + case bitc::BINOP_LSHR: return Instruction::LShr; + case bitc::BINOP_ASHR: return Instruction::AShr; + case bitc::BINOP_AND: return Instruction::And; + case bitc::BINOP_OR: return Instruction::Or; + case bitc::BINOP_XOR: return Instruction::Xor; + } +} + +namespace llvm { +namespace { + /// @brief A class for maintaining the slot number definition + /// as a placeholder for the actual definition for forward constants defs. + class ConstantPlaceHolder : public ConstantExpr { + void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT + public: + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + explicit ConstantPlaceHolder(const Type *Ty, LLVMContext& Context) + : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) { + Op<0>() = UndefValue::get(Type::getInt32Ty(Context)); + } + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + //static inline bool classof(const ConstantPlaceHolder *) { return true; } + static bool classof(const Value *V) { + return isa(V) && + cast(V)->getOpcode() == Instruction::UserOp1; + } + + + /// Provide fast operand accessors + //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + }; +} + +// FIXME: can we inherit this from ConstantExpr? +template <> +struct OperandTraits : + public FixedNumOperandTraits { +}; +} + + +void BitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) { + if (Idx == size()) { + push_back(V); + return; + } + + if (Idx >= size()) + resize(Idx+1); + + WeakVH &OldV = ValuePtrs[Idx]; + if (OldV == 0) { + OldV = V; + return; + } + + // Handle constants and non-constants (e.g. instrs) differently for + // efficiency. + if (Constant *PHC = dyn_cast(&*OldV)) { + ResolveConstants.push_back(std::make_pair(PHC, Idx)); + OldV = V; + } else { + // If there was a forward reference to this value, replace it. + Value *PrevVal = OldV; + OldV->replaceAllUsesWith(V); + delete PrevVal; + } +} + + +Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx, + const Type *Ty) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = ValuePtrs[Idx]) { + assert(Ty == V->getType() && "Type mismatch in constant table!"); + return cast(V); + } + + // Create and return a placeholder, which will later be RAUW'd. + Constant *C = new ConstantPlaceHolder(Ty, Context); + ValuePtrs[Idx] = C; + return C; +} + +Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, const Type *Ty) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = ValuePtrs[Idx]) { + assert((Ty == 0 || Ty == V->getType()) && "Type mismatch in value table!"); + return V; + } + + // No type specified, must be invalid reference. + if (Ty == 0) return 0; + + // Create and return a placeholder, which will later be RAUW'd. + Value *V = new Argument(Ty); + ValuePtrs[Idx] = V; + return V; +} + +/// ResolveConstantForwardRefs - Once all constants are read, this method bulk +/// resolves any forward references. The idea behind this is that we sometimes +/// get constants (such as large arrays) which reference *many* forward ref +/// constants. Replacing each of these causes a lot of thrashing when +/// building/reuniquing the constant. Instead of doing this, we look at all the +/// uses and rewrite all the place holders at once for any constant that uses +/// a placeholder. +void BitcodeReaderValueList::ResolveConstantForwardRefs() { + // Sort the values by-pointer so that they are efficient to look up with a + // binary search. + std::sort(ResolveConstants.begin(), ResolveConstants.end()); + + SmallVector NewOps; + + while (!ResolveConstants.empty()) { + Value *RealVal = operator[](ResolveConstants.back().second); + Constant *Placeholder = ResolveConstants.back().first; + ResolveConstants.pop_back(); + + // Loop over all users of the placeholder, updating them to reference the + // new value. If they reference more than one placeholder, update them all + // at once. + while (!Placeholder->use_empty()) { + Value::use_iterator UI = Placeholder->use_begin(); + User *U = *UI; + + // If the using object isn't uniqued, just update the operands. This + // handles instructions and initializers for global variables. + if (!isa(U) || isa(U)) { + UI.getUse().set(RealVal); + continue; + } + + // Otherwise, we have a constant that uses the placeholder. Replace that + // constant with a new constant that has *all* placeholder uses updated. + Constant *UserC = cast(U); + for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); + I != E; ++I) { + Value *NewOp; + if (!isa(*I)) { + // Not a placeholder reference. + NewOp = *I; + } else if (*I == Placeholder) { + // Common case is that it just references this one placeholder. + NewOp = RealVal; + } else { + // Otherwise, look up the placeholder in ResolveConstants. + ResolveConstantsTy::iterator It = + std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(), + std::pair(cast(*I), + 0)); + assert(It != ResolveConstants.end() && It->first == *I); + NewOp = operator[](It->second); + } + + NewOps.push_back(cast(NewOp)); + } + + // Make the new constant. + Constant *NewC; + if (ConstantArray *UserCA = dyn_cast(UserC)) { + NewC = ConstantArray::get(UserCA->getType(), &NewOps[0], + NewOps.size()); + } else if (ConstantStruct *UserCS = dyn_cast(UserC)) { + NewC = ConstantStruct::get(Context, &NewOps[0], NewOps.size(), + UserCS->getType()->isPacked()); + } else if (isa(UserC)) { + NewC = ConstantVector::get(NewOps); + } else { + assert(isa(UserC) && "Must be a ConstantExpr."); + NewC = cast(UserC)->getWithOperands(&NewOps[0], + NewOps.size()); + } + + UserC->replaceAllUsesWith(NewC); + UserC->destroyConstant(); + NewOps.clear(); + } + + // Update all ValueHandles, they should be the only users at this point. + Placeholder->replaceAllUsesWith(RealVal); + delete Placeholder; + } +} + +void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) { + if (Idx == size()) { + push_back(V); + return; + } + + if (Idx >= size()) + resize(Idx+1); + + WeakVH &OldV = MDValuePtrs[Idx]; + if (OldV == 0) { + OldV = V; + return; + } + + // If there was a forward reference to this value, replace it. + MDNode *PrevVal = cast(OldV); + OldV->replaceAllUsesWith(V); + MDNode::deleteTemporary(PrevVal); + // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new + // value for Idx. + MDValuePtrs[Idx] = V; +} + +Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) { + if (Idx >= size()) + resize(Idx + 1); + + if (Value *V = MDValuePtrs[Idx]) { + assert(V->getType()->isMetadataTy() && "Type mismatch in value table!"); + return V; + } + + // Create and return a placeholder, which will later be RAUW'd. + Value *V = MDNode::getTemporary(Context, 0, 0); + MDValuePtrs[Idx] = V; + return V; +} + +const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) { + // If the TypeID is in range, return it. + if (ID < TypeList.size()) + return TypeList[ID].get(); + if (!isTypeTable) return 0; + + // The type table allows forward references. Push as many Opaque types as + // needed to get up to ID. + while (TypeList.size() <= ID) + TypeList.push_back(OpaqueType::get(Context)); + return TypeList.back().get(); +} + +//===----------------------------------------------------------------------===// +// Functions for parsing blocks from the bitcode file +//===----------------------------------------------------------------------===// + +bool BitcodeReader::ParseAttributeBlock() { + if (Stream.EnterSubBlock(bitc::PARAMATTR_BLOCK_ID)) + return Error("Malformed block record"); + + if (!MAttributes.empty()) + return Error("Multiple PARAMATTR blocks found!"); + + SmallVector Record; + + SmallVector Attrs; + + // Read all the records. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: ignore. + break; + case bitc::PARAMATTR_CODE_ENTRY: { // ENTRY: [paramidx0, attr0, ...] + if (Record.size() & 1) + return Error("Invalid ENTRY record"); + + // FIXME : Remove this autoupgrade code in LLVM 3.0. + // If Function attributes are using index 0 then transfer them + // to index ~0. Index 0 is used for return value attributes but used to be + // used for function attributes. + Attributes RetAttribute = Attribute::None; + Attributes FnAttribute = Attribute::None; + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + // FIXME: remove in LLVM 3.0 + // The alignment is stored as a 16-bit raw value from bits 31--16. + // We shift the bits above 31 down by 11 bits. + + unsigned Alignment = (Record[i+1] & (0xffffull << 16)) >> 16; + if (Alignment && !isPowerOf2_32(Alignment)) + return Error("Alignment is not a power of two."); + + Attributes ReconstitutedAttr = Record[i+1] & 0xffff; + if (Alignment) + ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment); + ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11; + Record[i+1] = ReconstitutedAttr; + + if (Record[i] == 0) + RetAttribute = Record[i+1]; + else if (Record[i] == ~0U) + FnAttribute = Record[i+1]; + } + + unsigned OldRetAttrs = (Attribute::NoUnwind|Attribute::NoReturn| + Attribute::ReadOnly|Attribute::ReadNone); + + if (FnAttribute == Attribute::None && RetAttribute != Attribute::None && + (RetAttribute & OldRetAttrs) != 0) { + if (FnAttribute == Attribute::None) { // add a slot so they get added. + Record.push_back(~0U); + Record.push_back(0); + } + + FnAttribute |= RetAttribute & OldRetAttrs; + RetAttribute &= ~OldRetAttrs; + } + + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + if (Record[i] == 0) { + if (RetAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(0, RetAttribute)); + } else if (Record[i] == ~0U) { + if (FnAttribute != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(~0U, FnAttribute)); + } else if (Record[i+1] != Attribute::None) + Attrs.push_back(AttributeWithIndex::get(Record[i], Record[i+1])); + } + + MAttributes.push_back(AttrListPtr::get(Attrs.begin(), Attrs.end())); + Attrs.clear(); + break; + } + } + } +} + + +bool BitcodeReader::ParseTypeTable() { + if (Stream.EnterSubBlock(bitc::TYPE_BLOCK_ID)) + return Error("Malformed block record"); + + if (!TypeList.empty()) + return Error("Multiple TYPE_BLOCKs found!"); + + SmallVector Record; + unsigned NumRecords = 0; + + // Read all the records for this type table. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (NumRecords != TypeList.size()) + return Error("Invalid type forward reference in TYPE_BLOCK"); + if (Stream.ReadBlockEnd()) + return Error("Error at end of type table block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + const Type *ResultTy = 0; + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + ResultTy = 0; + break; + case bitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries] + // TYPE_CODE_NUMENTRY contains a count of the number of types in the + // type list. This allows us to reserve space. + if (Record.size() < 1) + return Error("Invalid TYPE_CODE_NUMENTRY record"); + TypeList.reserve(Record[0]); + continue; + case bitc::TYPE_CODE_VOID: // VOID + ResultTy = Type::getVoidTy(Context); + break; + case bitc::TYPE_CODE_FLOAT: // FLOAT + ResultTy = Type::getFloatTy(Context); + break; + case bitc::TYPE_CODE_DOUBLE: // DOUBLE + ResultTy = Type::getDoubleTy(Context); + break; + case bitc::TYPE_CODE_X86_FP80: // X86_FP80 + ResultTy = Type::getX86_FP80Ty(Context); + break; + case bitc::TYPE_CODE_FP128: // FP128 + ResultTy = Type::getFP128Ty(Context); + break; + case bitc::TYPE_CODE_PPC_FP128: // PPC_FP128 + ResultTy = Type::getPPC_FP128Ty(Context); + break; + case bitc::TYPE_CODE_LABEL: // LABEL + ResultTy = Type::getLabelTy(Context); + break; + case bitc::TYPE_CODE_OPAQUE: // OPAQUE + ResultTy = 0; + break; + case bitc::TYPE_CODE_METADATA: // METADATA + ResultTy = Type::getMetadataTy(Context); + break; + case bitc::TYPE_CODE_X86_MMX: // X86_MMX + ResultTy = Type::getX86_MMXTy(Context); + break; + case bitc::TYPE_CODE_INTEGER: // INTEGER: [width] + if (Record.size() < 1) + return Error("Invalid Integer type record"); + + ResultTy = IntegerType::get(Context, Record[0]); + break; + case bitc::TYPE_CODE_POINTER: { // POINTER: [pointee type] or + // [pointee type, address space] + if (Record.size() < 1) + return Error("Invalid POINTER type record"); + unsigned AddressSpace = 0; + if (Record.size() == 2) + AddressSpace = Record[1]; + ResultTy = PointerType::get(getTypeByID(Record[0], true), + AddressSpace); + break; + } + case bitc::TYPE_CODE_FUNCTION: { + // FIXME: attrid is dead, remove it in LLVM 3.0 + // FUNCTION: [vararg, attrid, retty, paramty x N] + if (Record.size() < 3) + return Error("Invalid FUNCTION type record"); + std::vector ArgTys; + for (unsigned i = 3, e = Record.size(); i != e; ++i) + ArgTys.push_back(getTypeByID(Record[i], true)); + + ResultTy = FunctionType::get(getTypeByID(Record[2], true), ArgTys, + Record[0]); + break; + } + case bitc::TYPE_CODE_STRUCT: { // STRUCT: [ispacked, eltty x N] + if (Record.size() < 1) + return Error("Invalid STRUCT type record"); + std::vector EltTys; + for (unsigned i = 1, e = Record.size(); i != e; ++i) + EltTys.push_back(getTypeByID(Record[i], true)); + ResultTy = StructType::get(Context, EltTys, Record[0]); + break; + } + case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty] + if (Record.size() < 2) + return Error("Invalid ARRAY type record"); + ResultTy = ArrayType::get(getTypeByID(Record[1], true), Record[0]); + break; + case bitc::TYPE_CODE_VECTOR: // VECTOR: [numelts, eltty] + if (Record.size() < 2) + return Error("Invalid VECTOR type record"); + ResultTy = VectorType::get(getTypeByID(Record[1], true), Record[0]); + break; + } + + if (NumRecords == TypeList.size()) { + // If this is a new type slot, just append it. + TypeList.push_back(ResultTy ? ResultTy : OpaqueType::get(Context)); + ++NumRecords; + } else if (ResultTy == 0) { + // Otherwise, this was forward referenced, so an opaque type was created, + // but the result type is actually just an opaque. Leave the one we + // created previously. + ++NumRecords; + } else { + // Otherwise, this was forward referenced, so an opaque type was created. + // Resolve the opaque type to the real type now. + assert(NumRecords < TypeList.size() && "Typelist imbalance"); + const OpaqueType *OldTy = cast(TypeList[NumRecords++].get()); + + // Don't directly push the new type on the Tab. Instead we want to replace + // the opaque type we previously inserted with the new concrete value. The + // refinement from the abstract (opaque) type to the new type causes all + // uses of the abstract type to use the concrete type (NewTy). This will + // also cause the opaque type to be deleted. + const_cast(OldTy)->refineAbstractTypeTo(ResultTy); + + // This should have replaced the old opaque type with the new type in the + // value table... or with a preexisting type that was already in the + // system. Let's just make sure it did. + assert(TypeList[NumRecords-1].get() != OldTy && + "refineAbstractType didn't work!"); + } + } +} + + +bool BitcodeReader::ParseTypeSymbolTable() { + if (Stream.EnterSubBlock(bitc::TYPE_SYMTAB_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this type table. + std::string TypeName; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of type symbol table block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + break; + case bitc::TST_CODE_ENTRY: // TST_ENTRY: [typeid, namechar x N] + if (ConvertToString(Record, 1, TypeName)) + return Error("Invalid TST_ENTRY record"); + unsigned TypeID = Record[0]; + if (TypeID >= TypeList.size()) + return Error("Invalid Type ID in TST_ENTRY record"); + + TheModule->addTypeName(TypeName, TypeList[TypeID].get()); + TypeName.clear(); + break; + } + } +} + +bool BitcodeReader::ParseValueSymbolTable() { + if (Stream.EnterSubBlock(bitc::VALUE_SYMTAB_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this value table. + SmallString<128> ValueName; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of value symbol table block"); + return false; + } + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: unknown type. + break; + case bitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N] + if (ConvertToString(Record, 1, ValueName)) + return Error("Invalid VST_ENTRY record"); + unsigned ValueID = Record[0]; + if (ValueID >= ValueList.size()) + return Error("Invalid Value ID in VST_ENTRY record"); + Value *V = ValueList[ValueID]; + + V->setName(StringRef(ValueName.data(), ValueName.size())); + ValueName.clear(); + break; + } + case bitc::VST_CODE_BBENTRY: { + if (ConvertToString(Record, 1, ValueName)) + return Error("Invalid VST_BBENTRY record"); + BasicBlock *BB = getBasicBlock(Record[0]); + if (BB == 0) + return Error("Invalid BB ID in VST_BBENTRY record"); + + BB->setName(StringRef(ValueName.data(), ValueName.size())); + ValueName.clear(); + break; + } + } + } +} + +bool BitcodeReader::ParseMetadata() { + unsigned NextMDValueNo = MDValueList.size(); + + if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records. + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + bool IsFunctionLocal = false; + // Read a record. + Record.clear(); + Code = Stream.ReadRecord(Code, Record); + switch (Code) { + default: // Default behavior: ignore. + break; + case bitc::METADATA_NAME: { + // Read named of the named metadata. + unsigned NameLength = Record.size(); + SmallString<8> Name; + Name.resize(NameLength); + for (unsigned i = 0; i != NameLength; ++i) + Name[i] = Record[i]; + Record.clear(); + Code = Stream.ReadCode(); + + // METADATA_NAME is always followed by METADATA_NAMED_NODE2. + // Or METADATA_NAMED_NODE in LLVM 2.7. FIXME: Remove this in LLVM 3.0. + unsigned NextBitCode = Stream.ReadRecord(Code, Record); + if (NextBitCode == bitc::METADATA_NAMED_NODE) { + LLVM2_7MetadataDetected = true; + } else if (NextBitCode != bitc::METADATA_NAMED_NODE2) + assert ( 0 && "Invalid Named Metadata record"); + + // Read named metadata elements. + unsigned Size = Record.size(); + NamedMDNode *NMD = TheModule->getOrInsertNamedMetadata(Name); + for (unsigned i = 0; i != Size; ++i) { + MDNode *MD = dyn_cast(MDValueList.getValueFwdRef(Record[i])); + if (MD == 0) + return Error("Malformed metadata record"); + NMD->addOperand(MD); + } + // Backwards compatibility hack: NamedMDValues used to be Values, + // and they got their own slots in the value numbering. They are no + // longer Values, however we still need to account for them in the + // numbering in order to be able to read old bitcode files. + // FIXME: Remove this in LLVM 3.0. + if (LLVM2_7MetadataDetected) + MDValueList.AssignValue(0, NextMDValueNo++); + break; + } + case bitc::METADATA_FN_NODE: // FIXME: Remove in LLVM 3.0. + case bitc::METADATA_FN_NODE2: + IsFunctionLocal = true; + // fall-through + case bitc::METADATA_NODE: // FIXME: Remove in LLVM 3.0. + case bitc::METADATA_NODE2: { + + // Detect 2.7-era metadata. + // FIXME: Remove in LLVM 3.0. + if (Code == bitc::METADATA_FN_NODE || Code == bitc::METADATA_NODE) + LLVM2_7MetadataDetected = true; + + if (Record.size() % 2 == 1) + return Error("Invalid METADATA_NODE2 record"); + + unsigned Size = Record.size(); + SmallVector Elts; + for (unsigned i = 0; i != Size; i += 2) { + const Type *Ty = getTypeByID(Record[i]); + if (!Ty) return Error("Invalid METADATA_NODE2 record"); + if (Ty->isMetadataTy()) + Elts.push_back(MDValueList.getValueFwdRef(Record[i+1])); + else if (!Ty->isVoidTy()) + Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty)); + else + Elts.push_back(NULL); + } + Value *V = MDNode::getWhenValsUnresolved(Context, + Elts.data(), Elts.size(), + IsFunctionLocal); + IsFunctionLocal = false; + MDValueList.AssignValue(V, NextMDValueNo++); + break; + } + case bitc::METADATA_STRING: { + unsigned MDStringLength = Record.size(); + SmallString<8> String; + String.resize(MDStringLength); + for (unsigned i = 0; i != MDStringLength; ++i) + String[i] = Record[i]; + Value *V = MDString::get(Context, + StringRef(String.data(), String.size())); + MDValueList.AssignValue(V, NextMDValueNo++); + break; + } + case bitc::METADATA_KIND: { + unsigned RecordLength = Record.size(); + if (Record.empty() || RecordLength < 2) + return Error("Invalid METADATA_KIND record"); + SmallString<8> Name; + Name.resize(RecordLength-1); + unsigned Kind = Record[0]; + for (unsigned i = 1; i != RecordLength; ++i) + Name[i-1] = Record[i]; + + unsigned NewKind = TheModule->getMDKindID(Name.str()); + if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second) + return Error("Conflicting METADATA_KIND records"); + break; + } + } + } +} + +/// DecodeSignRotatedValue - Decode a signed value stored with the sign bit in +/// the LSB for dense VBR encoding. +static uint64_t DecodeSignRotatedValue(uint64_t V) { + if ((V & 1) == 0) + return V >> 1; + if (V != 1) + return -(V >> 1); + // There is no such thing as -0 with integers. "-0" really means MININT. + return 1ULL << 63; +} + +/// ResolveGlobalAndAliasInits - Resolve all of the initializers for global +/// values and aliases that we can. +bool BitcodeReader::ResolveGlobalAndAliasInits() { + std::vector > GlobalInitWorklist; + std::vector > AliasInitWorklist; + + GlobalInitWorklist.swap(GlobalInits); + AliasInitWorklist.swap(AliasInits); + + while (!GlobalInitWorklist.empty()) { + unsigned ValID = GlobalInitWorklist.back().second; + if (ValID >= ValueList.size()) { + // Not ready to resolve this yet, it requires something later in the file. + GlobalInits.push_back(GlobalInitWorklist.back()); + } else { + if (Constant *C = dyn_cast(ValueList[ValID])) + GlobalInitWorklist.back().first->setInitializer(C); + else + return Error("Global variable initializer is not a constant!"); + } + GlobalInitWorklist.pop_back(); + } + + while (!AliasInitWorklist.empty()) { + unsigned ValID = AliasInitWorklist.back().second; + if (ValID >= ValueList.size()) { + AliasInits.push_back(AliasInitWorklist.back()); + } else { + if (Constant *C = dyn_cast(ValueList[ValID])) + AliasInitWorklist.back().first->setAliasee(C); + else + return Error("Alias initializer is not a constant!"); + } + AliasInitWorklist.pop_back(); + } + return false; +} + +bool BitcodeReader::ParseConstants() { + if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this value table. + const Type *CurTy = Type::getInt32Ty(Context); + unsigned NextCstNo = ValueList.size(); + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) + break; + + if (Code == bitc::ENTER_SUBBLOCK) { + // No known subblocks, always skip them. + Stream.ReadSubBlockID(); + if (Stream.SkipBlock()) + return Error("Malformed block record"); + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + Value *V = 0; + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { + default: // Default behavior: unknown constant + case bitc::CST_CODE_UNDEF: // UNDEF + V = UndefValue::get(CurTy); + break; + case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid] + if (Record.empty()) + return Error("Malformed CST_SETTYPE record"); + if (Record[0] >= TypeList.size()) + return Error("Invalid Type ID in CST_SETTYPE record"); + CurTy = TypeList[Record[0]]; + continue; // Skip the ValueList manipulation. + case bitc::CST_CODE_NULL: // NULL + V = Constant::getNullValue(CurTy); + break; + case bitc::CST_CODE_INTEGER: // INTEGER: [intval] + if (!CurTy->isIntegerTy() || Record.empty()) + return Error("Invalid CST_INTEGER record"); + V = ConstantInt::get(CurTy, DecodeSignRotatedValue(Record[0])); + break; + case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval] + if (!CurTy->isIntegerTy() || Record.empty()) + return Error("Invalid WIDE_INTEGER record"); + + unsigned NumWords = Record.size(); + SmallVector Words; + Words.resize(NumWords); + for (unsigned i = 0; i != NumWords; ++i) + Words[i] = DecodeSignRotatedValue(Record[i]); + V = ConstantInt::get(Context, + APInt(cast(CurTy)->getBitWidth(), + NumWords, &Words[0])); + break; + } + case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval] + if (Record.empty()) + return Error("Invalid FLOAT record"); + if (CurTy->isFloatTy()) + V = ConstantFP::get(Context, APFloat(APInt(32, (uint32_t)Record[0]))); + else if (CurTy->isDoubleTy()) + V = ConstantFP::get(Context, APFloat(APInt(64, Record[0]))); + else if (CurTy->isX86_FP80Ty()) { + // Bits are not stored the same way as a normal i80 APInt, compensate. + uint64_t Rearrange[2]; + Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16); + Rearrange[1] = Record[0] >> 48; + V = ConstantFP::get(Context, APFloat(APInt(80, 2, Rearrange))); + } else if (CurTy->isFP128Ty()) + V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]), true)); + else if (CurTy->isPPC_FP128Ty()) + V = ConstantFP::get(Context, APFloat(APInt(128, 2, &Record[0]))); + else + V = UndefValue::get(CurTy); + break; + } + + case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + unsigned Size = Record.size(); + std::vector Elts; + + if (const StructType *STy = dyn_cast(CurTy)) { + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], + STy->getElementType(i))); + V = ConstantStruct::get(STy, Elts); + } else if (const ArrayType *ATy = dyn_cast(CurTy)) { + const Type *EltTy = ATy->getElementType(); + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); + V = ConstantArray::get(ATy, Elts); + } else if (const VectorType *VTy = dyn_cast(CurTy)) { + const Type *EltTy = VTy->getElementType(); + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy)); + V = ConstantVector::get(Elts); + } else { + V = UndefValue::get(CurTy); + } + break; + } + case bitc::CST_CODE_STRING: { // STRING: [values] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + const ArrayType *ATy = cast(CurTy); + const Type *EltTy = ATy->getElementType(); + + unsigned Size = Record.size(); + std::vector Elts; + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ConstantInt::get(EltTy, Record[i])); + V = ConstantArray::get(ATy, Elts); + break; + } + case bitc::CST_CODE_CSTRING: { // CSTRING: [values] + if (Record.empty()) + return Error("Invalid CST_AGGREGATE record"); + + const ArrayType *ATy = cast(CurTy); + const Type *EltTy = ATy->getElementType(); + + unsigned Size = Record.size(); + std::vector Elts; + for (unsigned i = 0; i != Size; ++i) + Elts.push_back(ConstantInt::get(EltTy, Record[i])); + Elts.push_back(Constant::getNullValue(EltTy)); + V = ConstantArray::get(ATy, Elts); + break; + } + case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval] + if (Record.size() < 3) return Error("Invalid CE_BINOP record"); + int Opc = GetDecodedBinaryOpcode(Record[0], CurTy); + if (Opc < 0) { + V = UndefValue::get(CurTy); // Unknown binop. + } else { + Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy); + Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy); + unsigned Flags = 0; + if (Record.size() >= 4) { + if (Opc == Instruction::Add || + Opc == Instruction::Sub || + Opc == Instruction::Mul || + Opc == Instruction::Shl) { + if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP)) + Flags |= OverflowingBinaryOperator::NoSignedWrap; + if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) + Flags |= OverflowingBinaryOperator::NoUnsignedWrap; + } else if (Opc == Instruction::SDiv || + Opc == Instruction::UDiv || + Opc == Instruction::LShr || + Opc == Instruction::AShr) { + if (Record[3] & (1 << bitc::PEO_EXACT)) + Flags |= SDivOperator::IsExact; + } + } + V = ConstantExpr::get(Opc, LHS, RHS, Flags); + } + break; + } + case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval] + if (Record.size() < 3) return Error("Invalid CE_CAST record"); + int Opc = GetDecodedCastOpcode(Record[0]); + if (Opc < 0) { + V = UndefValue::get(CurTy); // Unknown cast. + } else { + const Type *OpTy = getTypeByID(Record[1]); + if (!OpTy) return Error("Invalid CE_CAST record"); + Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy); + V = ConstantExpr::getCast(Opc, Op, CurTy); + } + break; + } + case bitc::CST_CODE_CE_INBOUNDS_GEP: + case bitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands] + if (Record.size() & 1) return Error("Invalid CE_GEP record"); + SmallVector Elts; + for (unsigned i = 0, e = Record.size(); i != e; i += 2) { + const Type *ElTy = getTypeByID(Record[i]); + if (!ElTy) return Error("Invalid CE_GEP record"); + Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); + } + if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP) + V = ConstantExpr::getInBoundsGetElementPtr(Elts[0], &Elts[1], + Elts.size()-1); + else + V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], + Elts.size()-1); + break; + } + case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#] + if (Record.size() < 3) return Error("Invalid CE_SELECT record"); + V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0], + Type::getInt1Ty(Context)), + ValueList.getConstantFwdRef(Record[1],CurTy), + ValueList.getConstantFwdRef(Record[2],CurTy)); + break; + case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval] + if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record"); + const VectorType *OpTy = + dyn_cast_or_null(getTypeByID(Record[0])); + if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context)); + V = ConstantExpr::getExtractElement(Op0, Op1); + break; + } + case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval] + const VectorType *OpTy = dyn_cast(CurTy); + if (Record.size() < 3 || OpTy == 0) + return Error("Invalid CE_INSERTELT record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[1], + OpTy->getElementType()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context)); + V = ConstantExpr::getInsertElement(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval] + const VectorType *OpTy = dyn_cast(CurTy); + if (Record.size() < 3 || OpTy == 0) + return Error("Invalid CE_SHUFFLEVEC record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy); + const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + OpTy->getNumElements()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy); + V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval] + const VectorType *RTy = dyn_cast(CurTy); + const VectorType *OpTy = + dyn_cast_or_null(getTypeByID(Record[0])); + if (Record.size() < 4 || RTy == 0 || OpTy == 0) + return Error("Invalid CE_SHUFVEC_EX record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); + const Type *ShufTy = VectorType::get(Type::getInt32Ty(Context), + RTy->getNumElements()); + Constant *Op2 = ValueList.getConstantFwdRef(Record[3], ShufTy); + V = ConstantExpr::getShuffleVector(Op0, Op1, Op2); + break; + } + case bitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred] + if (Record.size() < 4) return Error("Invalid CE_CMP record"); + const Type *OpTy = getTypeByID(Record[0]); + if (OpTy == 0) return Error("Invalid CE_CMP record"); + Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); + Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); + + if (OpTy->isFPOrFPVectorTy()) + V = ConstantExpr::getFCmp(Record[3], Op0, Op1); + else + V = ConstantExpr::getICmp(Record[3], Op0, Op1); + break; + } + case bitc::CST_CODE_INLINEASM: { + if (Record.size() < 2) return Error("Invalid INLINEASM record"); + std::string AsmStr, ConstrStr; + bool HasSideEffects = Record[0] & 1; + bool IsAlignStack = Record[0] >> 1; + unsigned AsmStrSize = Record[1]; + if (2+AsmStrSize >= Record.size()) + return Error("Invalid INLINEASM record"); + unsigned ConstStrSize = Record[2+AsmStrSize]; + if (3+AsmStrSize+ConstStrSize > Record.size()) + return Error("Invalid INLINEASM record"); + + for (unsigned i = 0; i != AsmStrSize; ++i) + AsmStr += (char)Record[2+i]; + for (unsigned i = 0; i != ConstStrSize; ++i) + ConstrStr += (char)Record[3+AsmStrSize+i]; + const PointerType *PTy = cast(CurTy); + V = InlineAsm::get(cast(PTy->getElementType()), + AsmStr, ConstrStr, HasSideEffects, IsAlignStack); + break; + } + case bitc::CST_CODE_BLOCKADDRESS:{ + if (Record.size() < 3) return Error("Invalid CE_BLOCKADDRESS record"); + const Type *FnTy = getTypeByID(Record[0]); + if (FnTy == 0) return Error("Invalid CE_BLOCKADDRESS record"); + Function *Fn = + dyn_cast_or_null(ValueList.getConstantFwdRef(Record[1],FnTy)); + if (Fn == 0) return Error("Invalid CE_BLOCKADDRESS record"); + + GlobalVariable *FwdRef = new GlobalVariable(*Fn->getParent(), + Type::getInt8Ty(Context), + false, GlobalValue::InternalLinkage, + 0, ""); + BlockAddrFwdRefs[Fn].push_back(std::make_pair(Record[2], FwdRef)); + V = FwdRef; + break; + } + } + + ValueList.AssignValue(V, NextCstNo); + ++NextCstNo; + } + + if (NextCstNo != ValueList.size()) + return Error("Invalid constant reference!"); + + if (Stream.ReadBlockEnd()) + return Error("Error at end of constants block"); + + // Once all the constants have been read, go through and resolve forward + // references. + ValueList.ResolveConstantForwardRefs(); + return false; +} + +/// RememberAndSkipFunctionBody - When we see the block for a function body, +/// remember where it is and then skip it. This lets us lazily deserialize the +/// functions. +bool BitcodeReader::RememberAndSkipFunctionBody() { + // Get the function we are talking about. + if (FunctionsWithBodies.empty()) + return Error("Insufficient function protos"); + + Function *Fn = FunctionsWithBodies.back(); + FunctionsWithBodies.pop_back(); + + // Save the current stream state. + uint64_t CurBit = Stream.GetCurrentBitNo(); + DeferredFunctionInfo[Fn] = CurBit; + + // Skip over the function block for now. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + return false; +} + +bool BitcodeReader::ParseModule() { + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + std::vector SectionTable; + std::vector GCTable; + + // Read all the records for this module. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of module block"); + + // Patch the initializers for globals and aliases up. + ResolveGlobalAndAliasInits(); + if (!GlobalInits.empty() || !AliasInits.empty()) + return Error("Malformed global initializer set"); + if (!FunctionsWithBodies.empty()) + return Error("Too few function bodies found"); + + // Look for intrinsic functions which need to be upgraded at some point + for (Module::iterator FI = TheModule->begin(), FE = TheModule->end(); + FI != FE; ++FI) { + Function* NewFn; + if (UpgradeIntrinsicFunction(FI, NewFn)) + UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn)); + } + + // Look for global variables which need to be renamed. + for (Module::global_iterator + GI = TheModule->global_begin(), GE = TheModule->global_end(); + GI != GE; ++GI) + UpgradeGlobalVariable(GI); + + // Force deallocation of memory for these vectors to favor the client that + // want lazy deserialization. + std::vector >().swap(GlobalInits); + std::vector >().swap(AliasInits); + std::vector().swap(FunctionsWithBodies); + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + switch (Stream.ReadSubBlockID()) { + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + case bitc::BLOCKINFO_BLOCK_ID: + if (Stream.ReadBlockInfoBlock()) + return Error("Malformed BlockInfoBlock"); + break; + case bitc::PARAMATTR_BLOCK_ID: + if (ParseAttributeBlock()) + return true; + break; + case bitc::TYPE_BLOCK_ID: + if (ParseTypeTable()) + return true; + break; + case bitc::TYPE_SYMTAB_BLOCK_ID: + if (ParseTypeSymbolTable()) + return true; + break; + case bitc::VALUE_SYMTAB_BLOCK_ID: + if (ParseValueSymbolTable()) + return true; + break; + case bitc::CONSTANTS_BLOCK_ID: + if (ParseConstants() || ResolveGlobalAndAliasInits()) + return true; + break; + case bitc::METADATA_BLOCK_ID: + if (ParseMetadata()) + return true; + break; + case bitc::FUNCTION_BLOCK_ID: + // If this is the first function body we've seen, reverse the + // FunctionsWithBodies list. + if (!HasReversedFunctionsWithBodies) { + std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end()); + HasReversedFunctionsWithBodies = true; + } + + if (RememberAndSkipFunctionBody()) + return true; + break; + } + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + switch (Stream.ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_VERSION: // VERSION: [version#] + if (Record.size() < 1) + return Error("Malformed MODULE_CODE_VERSION"); + // Only version #0 is supported so far. + if (Record[0] != 0) + return Error("Unknown bitstream version!"); + break; + case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_TRIPLE record"); + TheModule->setTargetTriple(S); + break; + } + case bitc::MODULE_CODE_DATALAYOUT: { // DATALAYOUT: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_DATALAYOUT record"); + TheModule->setDataLayout(S); + break; + } + case bitc::MODULE_CODE_ASM: { // ASM: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_ASM record"); + TheModule->setModuleInlineAsm(S); + break; + } + case bitc::MODULE_CODE_DEPLIB: { // DEPLIB: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_DEPLIB record"); + TheModule->addLibrary(S); + break; + } + case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_SECTIONNAME record"); + SectionTable.push_back(S); + break; + } + case bitc::MODULE_CODE_GCNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_GCNAME record"); + GCTable.push_back(S); + break; + } + // GLOBALVAR: [pointer type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal, + // unnamed_addr] + case bitc::MODULE_CODE_GLOBALVAR: { + if (Record.size() < 6) + return Error("Invalid MODULE_CODE_GLOBALVAR record"); + const Type *Ty = getTypeByID(Record[0]); + if (!Ty) return Error("Invalid MODULE_CODE_GLOBALVAR record"); + if (!Ty->isPointerTy()) + return Error("Global not a pointer type!"); + unsigned AddressSpace = cast(Ty)->getAddressSpace(); + Ty = cast(Ty)->getElementType(); + + bool isConstant = Record[1]; + GlobalValue::LinkageTypes Linkage = GetDecodedLinkage(Record[3]); + unsigned Alignment = (1 << Record[4]) >> 1; + std::string Section; + if (Record[5]) { + if (Record[5]-1 >= SectionTable.size()) + return Error("Invalid section ID"); + Section = SectionTable[Record[5]-1]; + } + GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility; + if (Record.size() > 6) + Visibility = GetDecodedVisibility(Record[6]); + bool isThreadLocal = false; + if (Record.size() > 7) + isThreadLocal = Record[7]; + + bool UnnamedAddr = false; + if (Record.size() > 8) + UnnamedAddr = Record[8]; + + GlobalVariable *NewGV = + new GlobalVariable(*TheModule, Ty, isConstant, Linkage, 0, "", 0, + isThreadLocal, AddressSpace); + NewGV->setAlignment(Alignment); + if (!Section.empty()) + NewGV->setSection(Section); + NewGV->setVisibility(Visibility); + NewGV->setThreadLocal(isThreadLocal); + NewGV->setUnnamedAddr(UnnamedAddr); + + ValueList.push_back(NewGV); + + // Remember which value to use for the global initializer. + if (unsigned InitID = Record[2]) + GlobalInits.push_back(std::make_pair(NewGV, InitID-1)); + break; + } + // FUNCTION: [type, callingconv, isproto, linkage, paramattr, + // alignment, section, visibility, gc, unnamed_addr] + case bitc::MODULE_CODE_FUNCTION: { + if (Record.size() < 8) + return Error("Invalid MODULE_CODE_FUNCTION record"); + const Type *Ty = getTypeByID(Record[0]); + if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record"); + if (!Ty->isPointerTy()) + return Error("Function not a pointer type!"); + const FunctionType *FTy = + dyn_cast(cast(Ty)->getElementType()); + if (!FTy) + return Error("Function not a pointer to function type!"); + + Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage, + "", TheModule); + + Func->setCallingConv(static_cast(Record[1])); + bool isProto = Record[2]; + Func->setLinkage(GetDecodedLinkage(Record[3])); + Func->setAttributes(getAttributes(Record[4])); + + Func->setAlignment((1 << Record[5]) >> 1); + if (Record[6]) { + if (Record[6]-1 >= SectionTable.size()) + return Error("Invalid section ID"); + Func->setSection(SectionTable[Record[6]-1]); + } + Func->setVisibility(GetDecodedVisibility(Record[7])); + if (Record.size() > 8 && Record[8]) { + if (Record[8]-1 > GCTable.size()) + return Error("Invalid GC ID"); + Func->setGC(GCTable[Record[8]-1].c_str()); + } + bool UnnamedAddr = false; + if (Record.size() > 9) + UnnamedAddr = Record[9]; + Func->setUnnamedAddr(UnnamedAddr); + ValueList.push_back(Func); + + // If this is a function with a body, remember the prototype we are + // creating now, so that we can match up the body with them later. + if (!isProto) + FunctionsWithBodies.push_back(Func); + break; + } + // ALIAS: [alias type, aliasee val#, linkage] + // ALIAS: [alias type, aliasee val#, linkage, visibility] + case bitc::MODULE_CODE_ALIAS: { + if (Record.size() < 3) + return Error("Invalid MODULE_ALIAS record"); + const Type *Ty = getTypeByID(Record[0]); + if (!Ty) return Error("Invalid MODULE_ALIAS record"); + if (!Ty->isPointerTy()) + return Error("Function not a pointer type!"); + + GlobalAlias *NewGA = new GlobalAlias(Ty, GetDecodedLinkage(Record[2]), + "", 0, TheModule); + // Old bitcode files didn't have visibility field. + if (Record.size() > 3) + NewGA->setVisibility(GetDecodedVisibility(Record[3])); + ValueList.push_back(NewGA); + AliasInits.push_back(std::make_pair(NewGA, Record[1])); + break; + } + /// MODULE_CODE_PURGEVALS: [numvals] + case bitc::MODULE_CODE_PURGEVALS: + // Trim down the value list to the specified size. + if (Record.size() < 1 || Record[0] > ValueList.size()) + return Error("Invalid MODULE_PURGEVALS record"); + ValueList.shrinkTo(Record[0]); + break; + } + Record.clear(); + } + + return Error("Premature end of bitstream"); +} + +bool BitcodeReader::ParseBitcodeInto(Module *M) { + TheModule = 0; + + unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart(); + unsigned char *BufEnd = BufPtr+Buffer->getBufferSize(); + + if (Buffer->getBufferSize() & 3) { + if (!isRawBitcode(BufPtr, BufEnd) && !isBitcodeWrapper(BufPtr, BufEnd)) + return Error("Invalid bitcode signature"); + else + return Error("Bitcode stream should be a multiple of 4 bytes in length"); + } + + // If we have a wrapper header, parse it and ignore the non-bc file contents. + // The magic number is 0x0B17C0DE stored in little endian. + if (isBitcodeWrapper(BufPtr, BufEnd)) + if (SkipBitcodeWrapperHeader(BufPtr, BufEnd)) + return Error("Invalid bitcode wrapper header"); + + StreamFile.init(BufPtr, BufEnd); + Stream.init(StreamFile); + + // Sniff for the signature. + if (Stream.Read(8) != 'B' || + Stream.Read(8) != 'C' || + Stream.Read(4) != 0x0 || + Stream.Read(4) != 0xC || + Stream.Read(4) != 0xE || + Stream.Read(4) != 0xD) + return Error("Invalid bitcode signature"); + + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + + if (Code != bitc::ENTER_SUBBLOCK) + return Error("Invalid record at top-level"); + + unsigned BlockID = Stream.ReadSubBlockID(); + + // We only know the MODULE subblock ID. + switch (BlockID) { + case bitc::BLOCKINFO_BLOCK_ID: + if (Stream.ReadBlockInfoBlock()) + return Error("Malformed BlockInfoBlock"); + break; + case bitc::MODULE_BLOCK_ID: + // Reject multiple MODULE_BLOCK's in a single bitstream. + if (TheModule) + return Error("Multiple MODULE_BLOCKs in same stream"); + TheModule = M; + if (ParseModule()) + return true; + break; + default: + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + } + } + + return false; +} + +bool BitcodeReader::ParseModuleTriple(std::string &Triple) { + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return Error("Malformed block record"); + + SmallVector Record; + + // Read all the records for this module. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of module block"); + + return false; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + switch (Stream.ReadSubBlockID()) { + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + } + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + switch (Stream.ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_VERSION: // VERSION: [version#] + if (Record.size() < 1) + return Error("Malformed MODULE_CODE_VERSION"); + // Only version #0 is supported so far. + if (Record[0] != 0) + return Error("Unknown bitstream version!"); + break; + case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] + std::string S; + if (ConvertToString(Record, 0, S)) + return Error("Invalid MODULE_CODE_TRIPLE record"); + Triple = S; + break; + } + } + Record.clear(); + } + + return Error("Premature end of bitstream"); +} + +bool BitcodeReader::ParseTriple(std::string &Triple) { + if (Buffer->getBufferSize() & 3) + return Error("Bitcode stream should be a multiple of 4 bytes in length"); + + unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart(); + unsigned char *BufEnd = BufPtr+Buffer->getBufferSize(); + + // If we have a wrapper header, parse it and ignore the non-bc file contents. + // The magic number is 0x0B17C0DE stored in little endian. + if (isBitcodeWrapper(BufPtr, BufEnd)) + if (SkipBitcodeWrapperHeader(BufPtr, BufEnd)) + return Error("Invalid bitcode wrapper header"); + + StreamFile.init(BufPtr, BufEnd); + Stream.init(StreamFile); + + // Sniff for the signature. + if (Stream.Read(8) != 'B' || + Stream.Read(8) != 'C' || + Stream.Read(4) != 0x0 || + Stream.Read(4) != 0xC || + Stream.Read(4) != 0xE || + Stream.Read(4) != 0xD) + return Error("Invalid bitcode signature"); + + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (!Stream.AtEndOfStream()) { + unsigned Code = Stream.ReadCode(); + + if (Code != bitc::ENTER_SUBBLOCK) + return Error("Invalid record at top-level"); + + unsigned BlockID = Stream.ReadSubBlockID(); + + // We only know the MODULE subblock ID. + switch (BlockID) { + case bitc::MODULE_BLOCK_ID: + if (ParseModuleTriple(Triple)) + return true; + break; + default: + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + } + } + + return false; +} + +/// ParseMetadataAttachment - Parse metadata attachments. +bool BitcodeReader::ParseMetadataAttachment() { + if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) + return Error("Malformed block record"); + + SmallVector Record; + while(1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of PARAMATTR block"); + break; + } + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + // Read a metadata attachment record. + Record.clear(); + switch (Stream.ReadRecord(Code, Record)) { + default: // Default behavior: ignore. + break; + // FIXME: Remove in LLVM 3.0. + case bitc::METADATA_ATTACHMENT: + LLVM2_7MetadataDetected = true; + case bitc::METADATA_ATTACHMENT2: { + unsigned RecordLength = Record.size(); + if (Record.empty() || (RecordLength - 1) % 2 == 1) + return Error ("Invalid METADATA_ATTACHMENT reader!"); + Instruction *Inst = InstructionList[Record[0]]; + for (unsigned i = 1; i != RecordLength; i = i+2) { + unsigned Kind = Record[i]; + DenseMap::iterator I = + MDKindMap.find(Kind); + if (I == MDKindMap.end()) + return Error("Invalid metadata kind ID"); + Value *Node = MDValueList.getValueFwdRef(Record[i+1]); + Inst->setMetadata(I->second, cast(Node)); + } + break; + } + } + } + return false; +} + +/// ParseFunctionBody - Lazily parse the specified function body block. +bool BitcodeReader::ParseFunctionBody(Function *F) { + if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID)) + return Error("Malformed block record"); + + InstructionList.clear(); + unsigned ModuleValueListSize = ValueList.size(); + unsigned ModuleMDValueListSize = MDValueList.size(); + + // Add all the function arguments to the value table. + for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) + ValueList.push_back(I); + + unsigned NextValueNo = ValueList.size(); + BasicBlock *CurBB = 0; + unsigned CurBBNo = 0; + + DebugLoc LastLoc; + + // Read all the records. + SmallVector Record; + while (1) { + unsigned Code = Stream.ReadCode(); + if (Code == bitc::END_BLOCK) { + if (Stream.ReadBlockEnd()) + return Error("Error at end of function block"); + break; + } + + if (Code == bitc::ENTER_SUBBLOCK) { + switch (Stream.ReadSubBlockID()) { + default: // Skip unknown content. + if (Stream.SkipBlock()) + return Error("Malformed block record"); + break; + case bitc::CONSTANTS_BLOCK_ID: + if (ParseConstants()) return true; + NextValueNo = ValueList.size(); + break; + case bitc::VALUE_SYMTAB_BLOCK_ID: + if (ParseValueSymbolTable()) return true; + break; + case bitc::METADATA_ATTACHMENT_ID: + if (ParseMetadataAttachment()) return true; + break; + case bitc::METADATA_BLOCK_ID: + if (ParseMetadata()) return true; + break; + } + continue; + } + + if (Code == bitc::DEFINE_ABBREV) { + Stream.ReadAbbrevRecord(); + continue; + } + + // Read a record. + Record.clear(); + Instruction *I = 0; + unsigned BitCode = Stream.ReadRecord(Code, Record); + switch (BitCode) { + default: // Default behavior: reject + return Error("Unknown instruction"); + case bitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks] + if (Record.size() < 1 || Record[0] == 0) + return Error("Invalid DECLAREBLOCKS record"); + // Create all the basic blocks for the function. + FunctionBBs.resize(Record[0]); + for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i) + FunctionBBs[i] = BasicBlock::Create(Context, "", F); + CurBB = FunctionBBs[0]; + continue; + + + case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: // DEBUG_LOC_AGAIN + // This record indicates that the last instruction is at the same + // location as the previous instruction with a location. + I = 0; + + // Get the last instruction emitted. + if (CurBB && !CurBB->empty()) + I = &CurBB->back(); + else if (CurBBNo && FunctionBBs[CurBBNo-1] && + !FunctionBBs[CurBBNo-1]->empty()) + I = &FunctionBBs[CurBBNo-1]->back(); + + if (I == 0) return Error("Invalid DEBUG_LOC_AGAIN record"); + I->setDebugLoc(LastLoc); + I = 0; + continue; + + // FIXME: Remove this in LLVM 3.0. + case bitc::FUNC_CODE_DEBUG_LOC: + LLVM2_7MetadataDetected = true; + case bitc::FUNC_CODE_DEBUG_LOC2: { // DEBUG_LOC: [line, col, scope, ia] + I = 0; // Get the last instruction emitted. + if (CurBB && !CurBB->empty()) + I = &CurBB->back(); + else if (CurBBNo && FunctionBBs[CurBBNo-1] && + !FunctionBBs[CurBBNo-1]->empty()) + I = &FunctionBBs[CurBBNo-1]->back(); + if (I == 0 || Record.size() < 4) + return Error("Invalid FUNC_CODE_DEBUG_LOC record"); + + unsigned Line = Record[0], Col = Record[1]; + unsigned ScopeID = Record[2], IAID = Record[3]; + + MDNode *Scope = 0, *IA = 0; + if (ScopeID) Scope = cast(MDValueList.getValueFwdRef(ScopeID-1)); + if (IAID) IA = cast(MDValueList.getValueFwdRef(IAID-1)); + LastLoc = DebugLoc::get(Line, Col, Scope, IA); + I->setDebugLoc(LastLoc); + I = 0; + continue; + } + + case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode] + unsigned OpNum = 0; + Value *LHS, *RHS; + if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || + getValue(Record, OpNum, LHS->getType(), RHS) || + OpNum+1 > Record.size()) + return Error("Invalid BINOP record"); + + int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType()); + if (Opc == -1) return Error("Invalid BINOP record"); + I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + InstructionList.push_back(I); + if (OpNum < Record.size()) { + if (Opc == Instruction::Add || + Opc == Instruction::Sub || + Opc == Instruction::Mul || + Opc == Instruction::Shl) { + if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP)) + cast(I)->setHasNoSignedWrap(true); + if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) + cast(I)->setHasNoUnsignedWrap(true); + } else if (Opc == Instruction::SDiv || + Opc == Instruction::UDiv || + Opc == Instruction::LShr || + Opc == Instruction::AShr) { + if (Record[OpNum] & (1 << bitc::PEO_EXACT)) + cast(I)->setIsExact(true); + } + } + break; + } + case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum+2 != Record.size()) + return Error("Invalid CAST record"); + + const Type *ResTy = getTypeByID(Record[OpNum]); + int Opc = GetDecodedCastOpcode(Record[OpNum+1]); + if (Opc == -1 || ResTy == 0) + return Error("Invalid CAST record"); + I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_INBOUNDS_GEP: + case bitc::FUNC_CODE_INST_GEP: { // GEP: [n x operands] + unsigned OpNum = 0; + Value *BasePtr; + if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr)) + return Error("Invalid GEP record"); + + SmallVector GEPIdx; + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid GEP record"); + GEPIdx.push_back(Op); + } + + I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end()); + InstructionList.push_back(I); + if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP) + cast(I)->setIsInBounds(true); + break; + } + + case bitc::FUNC_CODE_INST_EXTRACTVAL: { + // EXTRACTVAL: [opty, opval, n x indices] + unsigned OpNum = 0; + Value *Agg; + if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + return Error("Invalid EXTRACTVAL record"); + + SmallVector EXTRACTVALIdx; + for (unsigned RecSize = Record.size(); + OpNum != RecSize; ++OpNum) { + uint64_t Index = Record[OpNum]; + if ((unsigned)Index != Index) + return Error("Invalid EXTRACTVAL index"); + EXTRACTVALIdx.push_back((unsigned)Index); + } + + I = ExtractValueInst::Create(Agg, + EXTRACTVALIdx.begin(), EXTRACTVALIdx.end()); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_INSERTVAL: { + // INSERTVAL: [opty, opval, opty, opval, n x indices] + unsigned OpNum = 0; + Value *Agg; + if (getValueTypePair(Record, OpNum, NextValueNo, Agg)) + return Error("Invalid INSERTVAL record"); + Value *Val; + if (getValueTypePair(Record, OpNum, NextValueNo, Val)) + return Error("Invalid INSERTVAL record"); + + SmallVector INSERTVALIdx; + for (unsigned RecSize = Record.size(); + OpNum != RecSize; ++OpNum) { + uint64_t Index = Record[OpNum]; + if ((unsigned)Index != Index) + return Error("Invalid INSERTVAL index"); + INSERTVALIdx.push_back((unsigned)Index); + } + + I = InsertValueInst::Create(Agg, Val, + INSERTVALIdx.begin(), INSERTVALIdx.end()); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval] + // obsolete form of select + // handles select i1 ... in old bitcode + unsigned OpNum = 0; + Value *TrueVal, *FalseVal, *Cond; + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + getValue(Record, OpNum, TrueVal->getType(), FalseVal) || + getValue(Record, OpNum, Type::getInt1Ty(Context), Cond)) + return Error("Invalid SELECT record"); + + I = SelectInst::Create(Cond, TrueVal, FalseVal); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred] + // new form of select + // handles select i1 or select [N x i1] + unsigned OpNum = 0; + Value *TrueVal, *FalseVal, *Cond; + if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) || + getValue(Record, OpNum, TrueVal->getType(), FalseVal) || + getValueTypePair(Record, OpNum, NextValueNo, Cond)) + return Error("Invalid SELECT record"); + + // select condition can be either i1 or [N x i1] + if (const VectorType* vector_type = + dyn_cast(Cond->getType())) { + // expect + if (vector_type->getElementType() != Type::getInt1Ty(Context)) + return Error("Invalid SELECT condition type"); + } else { + // expect i1 + if (Cond->getType() != Type::getInt1Ty(Context)) + return Error("Invalid SELECT condition type"); + } + + I = SelectInst::Create(Cond, TrueVal, FalseVal); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval] + unsigned OpNum = 0; + Value *Vec, *Idx; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec) || + getValue(Record, OpNum, Type::getInt32Ty(Context), Idx)) + return Error("Invalid EXTRACTELT record"); + I = ExtractElementInst::Create(Vec, Idx); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval] + unsigned OpNum = 0; + Value *Vec, *Elt, *Idx; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec) || + getValue(Record, OpNum, + cast(Vec->getType())->getElementType(), Elt) || + getValue(Record, OpNum, Type::getInt32Ty(Context), Idx)) + return Error("Invalid INSERTELT record"); + I = InsertElementInst::Create(Vec, Elt, Idx); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval] + unsigned OpNum = 0; + Value *Vec1, *Vec2, *Mask; + if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) || + getValue(Record, OpNum, Vec1->getType(), Vec2)) + return Error("Invalid SHUFFLEVEC record"); + + if (getValueTypePair(Record, OpNum, NextValueNo, Mask)) + return Error("Invalid SHUFFLEVEC record"); + I = new ShuffleVectorInst(Vec1, Vec2, Mask); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_CMP: // CMP: [opty, opval, opval, pred] + // Old form of ICmp/FCmp returning bool + // Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were + // both legal on vectors but had different behaviour. + case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred] + // FCmp/ICmp returning bool or vector of bool + + unsigned OpNum = 0; + Value *LHS, *RHS; + if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || + getValue(Record, OpNum, LHS->getType(), RHS) || + OpNum+1 != Record.size()) + return Error("Invalid CMP record"); + + if (LHS->getType()->isFPOrFPVectorTy()) + I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS); + else + I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_GETRESULT: { // GETRESULT: [ty, val, n] + if (Record.size() != 2) + return Error("Invalid GETRESULT record"); + unsigned OpNum = 0; + Value *Op; + getValueTypePair(Record, OpNum, NextValueNo, Op); + unsigned Index = Record[1]; + I = ExtractValueInst::Create(Op, Index); + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval] + { + unsigned Size = Record.size(); + if (Size == 0) { + I = ReturnInst::Create(Context); + InstructionList.push_back(I); + break; + } + + unsigned OpNum = 0; + SmallVector Vs; + do { + Value *Op = NULL; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid RET record"); + Vs.push_back(Op); + } while(OpNum != Record.size()); + + const Type *ReturnType = F->getReturnType(); + // Handle multiple return values. FIXME: Remove in LLVM 3.0. + if (Vs.size() > 1 || + (ReturnType->isStructTy() && + (Vs.empty() || Vs[0]->getType() != ReturnType))) { + Value *RV = UndefValue::get(ReturnType); + for (unsigned i = 0, e = Vs.size(); i != e; ++i) { + I = InsertValueInst::Create(RV, Vs[i], i, "mrv"); + InstructionList.push_back(I); + CurBB->getInstList().push_back(I); + ValueList.AssignValue(I, NextValueNo++); + RV = I; + } + I = ReturnInst::Create(Context, RV); + InstructionList.push_back(I); + break; + } + + I = ReturnInst::Create(Context, Vs[0]); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#] + if (Record.size() != 1 && Record.size() != 3) + return Error("Invalid BR record"); + BasicBlock *TrueDest = getBasicBlock(Record[0]); + if (TrueDest == 0) + return Error("Invalid BR record"); + + if (Record.size() == 1) { + I = BranchInst::Create(TrueDest); + InstructionList.push_back(I); + } + else { + BasicBlock *FalseDest = getBasicBlock(Record[1]); + Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context)); + if (FalseDest == 0 || Cond == 0) + return Error("Invalid BR record"); + I = BranchInst::Create(TrueDest, FalseDest, Cond); + InstructionList.push_back(I); + } + break; + } + case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...] + if (Record.size() < 3 || (Record.size() & 1) == 0) + return Error("Invalid SWITCH record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Cond = getFnValueByID(Record[1], OpTy); + BasicBlock *Default = getBasicBlock(Record[2]); + if (OpTy == 0 || Cond == 0 || Default == 0) + return Error("Invalid SWITCH record"); + unsigned NumCases = (Record.size()-3)/2; + SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases); + InstructionList.push_back(SI); + for (unsigned i = 0, e = NumCases; i != e; ++i) { + ConstantInt *CaseVal = + dyn_cast_or_null(getFnValueByID(Record[3+i*2], OpTy)); + BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]); + if (CaseVal == 0 || DestBB == 0) { + delete SI; + return Error("Invalid SWITCH record!"); + } + SI->addCase(CaseVal, DestBB); + } + I = SI; + break; + } + case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...] + if (Record.size() < 2) + return Error("Invalid INDIRECTBR record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Address = getFnValueByID(Record[1], OpTy); + if (OpTy == 0 || Address == 0) + return Error("Invalid INDIRECTBR record"); + unsigned NumDests = Record.size()-2; + IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests); + InstructionList.push_back(IBI); + for (unsigned i = 0, e = NumDests; i != e; ++i) { + if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) { + IBI->addDestination(DestBB); + } else { + delete IBI; + return Error("Invalid INDIRECTBR record!"); + } + } + I = IBI; + break; + } + + case bitc::FUNC_CODE_INST_INVOKE: { + // INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...] + if (Record.size() < 4) return Error("Invalid INVOKE record"); + AttrListPtr PAL = getAttributes(Record[0]); + unsigned CCInfo = Record[1]; + BasicBlock *NormalBB = getBasicBlock(Record[2]); + BasicBlock *UnwindBB = getBasicBlock(Record[3]); + + unsigned OpNum = 4; + Value *Callee; + if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + return Error("Invalid INVOKE record"); + + const PointerType *CalleeTy = dyn_cast(Callee->getType()); + const FunctionType *FTy = !CalleeTy ? 0 : + dyn_cast(CalleeTy->getElementType()); + + // Check that the right number of fixed parameters are here. + if (FTy == 0 || NormalBB == 0 || UnwindBB == 0 || + Record.size() < OpNum+FTy->getNumParams()) + return Error("Invalid INVOKE record"); + + SmallVector Ops; + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i))); + if (Ops.back() == 0) return Error("Invalid INVOKE record"); + } + + if (!FTy->isVarArg()) { + if (Record.size() != OpNum) + return Error("Invalid INVOKE record"); + } else { + // Read type/value pairs for varargs params. + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid INVOKE record"); + Ops.push_back(Op); + } + } + + I = InvokeInst::Create(Callee, NormalBB, UnwindBB, + Ops.begin(), Ops.end()); + InstructionList.push_back(I); + cast(I)->setCallingConv( + static_cast(CCInfo)); + cast(I)->setAttributes(PAL); + break; + } + case bitc::FUNC_CODE_INST_UNWIND: // UNWIND + I = new UnwindInst(Context); + InstructionList.push_back(I); + break; + case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE + I = new UnreachableInst(Context); + InstructionList.push_back(I); + break; + case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...] + if (Record.size() < 1 || ((Record.size()-1)&1)) + return Error("Invalid PHI record"); + const Type *Ty = getTypeByID(Record[0]); + if (!Ty) return Error("Invalid PHI record"); + + PHINode *PN = PHINode::Create(Ty); + InstructionList.push_back(PN); + PN->reserveOperandSpace((Record.size()-1)/2); + + for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) { + Value *V = getFnValueByID(Record[1+i], Ty); + BasicBlock *BB = getBasicBlock(Record[2+i]); + if (!V || !BB) return Error("Invalid PHI record"); + PN->addIncoming(V, BB); + } + I = PN; + break; + } + + case bitc::FUNC_CODE_INST_MALLOC: { // MALLOC: [instty, op, align] + // Autoupgrade malloc instruction to malloc call. + // FIXME: Remove in LLVM 3.0. + if (Record.size() < 3) + return Error("Invalid MALLOC record"); + const PointerType *Ty = + dyn_cast_or_null(getTypeByID(Record[0])); + Value *Size = getFnValueByID(Record[1], Type::getInt32Ty(Context)); + if (!Ty || !Size) return Error("Invalid MALLOC record"); + if (!CurBB) return Error("Invalid malloc instruction with no BB"); + const Type *Int32Ty = IntegerType::getInt32Ty(CurBB->getContext()); + Constant *AllocSize = ConstantExpr::getSizeOf(Ty->getElementType()); + AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, Int32Ty); + I = CallInst::CreateMalloc(CurBB, Int32Ty, Ty->getElementType(), + AllocSize, Size, NULL); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_FREE: { // FREE: [op, opty] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum != Record.size()) + return Error("Invalid FREE record"); + if (!CurBB) return Error("Invalid free instruction with no BB"); + I = CallInst::CreateFree(Op, CurBB); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align] + // For backward compatibility, tolerate a lack of an opty, and use i32. + // Remove this in LLVM 3.0. + if (Record.size() < 3 || Record.size() > 4) + return Error("Invalid ALLOCA record"); + unsigned OpNum = 0; + const PointerType *Ty = + dyn_cast_or_null(getTypeByID(Record[OpNum++])); + const Type *OpTy = Record.size() == 4 ? getTypeByID(Record[OpNum++]) : + Type::getInt32Ty(Context); + Value *Size = getFnValueByID(Record[OpNum++], OpTy); + unsigned Align = Record[OpNum++]; + if (!Ty || !Size) return Error("Invalid ALLOCA record"); + I = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol] + unsigned OpNum = 0; + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op) || + OpNum+2 != Record.size()) + return Error("Invalid LOAD record"); + + I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_STORE2: { // STORE2:[ptrty, ptr, val, align, vol] + unsigned OpNum = 0; + Value *Val, *Ptr; + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) || + getValue(Record, OpNum, + cast(Ptr->getType())->getElementType(), Val) || + OpNum+2 != Record.size()) + return Error("Invalid STORE record"); + + I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_STORE: { // STORE:[val, valty, ptr, align, vol] + // FIXME: Legacy form of store instruction. Should be removed in LLVM 3.0. + unsigned OpNum = 0; + Value *Val, *Ptr; + if (getValueTypePair(Record, OpNum, NextValueNo, Val) || + getValue(Record, OpNum, + PointerType::getUnqual(Val->getType()), Ptr)|| + OpNum+2 != Record.size()) + return Error("Invalid STORE record"); + + I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1); + InstructionList.push_back(I); + break; + } + // FIXME: Remove this in LLVM 3.0. + case bitc::FUNC_CODE_INST_CALL: + LLVM2_7MetadataDetected = true; + case bitc::FUNC_CODE_INST_CALL2: { + // CALL: [paramattrs, cc, fnty, fnid, arg0, arg1...] + if (Record.size() < 3) + return Error("Invalid CALL record"); + + AttrListPtr PAL = getAttributes(Record[0]); + unsigned CCInfo = Record[1]; + + unsigned OpNum = 2; + Value *Callee; + if (getValueTypePair(Record, OpNum, NextValueNo, Callee)) + return Error("Invalid CALL record"); + + const PointerType *OpTy = dyn_cast(Callee->getType()); + const FunctionType *FTy = 0; + if (OpTy) FTy = dyn_cast(OpTy->getElementType()); + if (!FTy || Record.size() < FTy->getNumParams()+OpNum) + return Error("Invalid CALL record"); + + SmallVector Args; + // Read the fixed params. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) { + if (FTy->getParamType(i)->getTypeID()==Type::LabelTyID) + Args.push_back(getBasicBlock(Record[OpNum])); + else + Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i))); + if (Args.back() == 0) return Error("Invalid CALL record"); + } + + // Read type/value pairs for varargs params. + if (!FTy->isVarArg()) { + if (OpNum != Record.size()) + return Error("Invalid CALL record"); + } else { + while (OpNum != Record.size()) { + Value *Op; + if (getValueTypePair(Record, OpNum, NextValueNo, Op)) + return Error("Invalid CALL record"); + Args.push_back(Op); + } + } + + I = CallInst::Create(Callee, Args.begin(), Args.end()); + InstructionList.push_back(I); + cast(I)->setCallingConv( + static_cast(CCInfo>>1)); + cast(I)->setTailCall(CCInfo & 1); + cast(I)->setAttributes(PAL); + break; + } + case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty] + if (Record.size() < 3) + return Error("Invalid VAARG record"); + const Type *OpTy = getTypeByID(Record[0]); + Value *Op = getFnValueByID(Record[1], OpTy); + const Type *ResTy = getTypeByID(Record[2]); + if (!OpTy || !Op || !ResTy) + return Error("Invalid VAARG record"); + I = new VAArgInst(Op, ResTy); + InstructionList.push_back(I); + break; + } + } + + // Add instruction to end of current BB. If there is no current BB, reject + // this file. + if (CurBB == 0) { + delete I; + return Error("Invalid instruction with no BB"); + } + CurBB->getInstList().push_back(I); + + // If this was a terminator instruction, move to the next block. + if (isa(I)) { + ++CurBBNo; + CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : 0; + } + + // Non-void values get registered in the value table for future use. + if (I && !I->getType()->isVoidTy()) + ValueList.AssignValue(I, NextValueNo++); + } + + // Check the function list for unresolved values. + if (Argument *A = dyn_cast(ValueList.back())) { + if (A->getParent() == 0) { + // We found at least one unresolved value. Nuke them all to avoid leaks. + for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){ + if ((A = dyn_cast(ValueList[i])) && A->getParent() == 0) { + A->replaceAllUsesWith(UndefValue::get(A->getType())); + delete A; + } + } + return Error("Never resolved value found in function!"); + } + } + + // FIXME: Check for unresolved forward-declared metadata references + // and clean up leaks. + + // See if anything took the address of blocks in this function. If so, + // resolve them now. + DenseMap >::iterator BAFRI = + BlockAddrFwdRefs.find(F); + if (BAFRI != BlockAddrFwdRefs.end()) { + std::vector &RefList = BAFRI->second; + for (unsigned i = 0, e = RefList.size(); i != e; ++i) { + unsigned BlockIdx = RefList[i].first; + if (BlockIdx >= FunctionBBs.size()) + return Error("Invalid blockaddress block #"); + + GlobalVariable *FwdRef = RefList[i].second; + FwdRef->replaceAllUsesWith(BlockAddress::get(F, FunctionBBs[BlockIdx])); + FwdRef->eraseFromParent(); + } + + BlockAddrFwdRefs.erase(BAFRI); + } + + // FIXME: Remove this in LLVM 3.0. + unsigned NewMDValueListSize = MDValueList.size(); + + // Trim the value list down to the size it was before we parsed this function. + ValueList.shrinkTo(ModuleValueListSize); + MDValueList.shrinkTo(ModuleMDValueListSize); + + // Backwards compatibility hack: Function-local metadata numbers + // were previously not reset between functions. This is now fixed, + // however we still need to understand the old numbering in order + // to be able to read old bitcode files. + // FIXME: Remove this in LLVM 3.0. + if (LLVM2_7MetadataDetected) + MDValueList.resize(NewMDValueListSize); + + std::vector().swap(FunctionBBs); + + return false; +} + +//===----------------------------------------------------------------------===// +// GVMaterializer implementation +//===----------------------------------------------------------------------===// + + +bool BitcodeReader::isMaterializable(const GlobalValue *GV) const { + if (const Function *F = dyn_cast(GV)) { + return F->isDeclaration() && + DeferredFunctionInfo.count(const_cast(F)); + } + return false; +} + +bool BitcodeReader::Materialize(GlobalValue *GV, std::string *ErrInfo) { + Function *F = dyn_cast(GV); + // If it's not a function or is already material, ignore the request. + if (!F || !F->isMaterializable()) return false; + + DenseMap::iterator DFII = DeferredFunctionInfo.find(F); + assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!"); + + // Move the bit stream to the saved position of the deferred function body. + Stream.JumpToBit(DFII->second); + + if (ParseFunctionBody(F)) { + if (ErrInfo) *ErrInfo = ErrorString; + return true; + } + + // Upgrade any old intrinsic calls in the function. + for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(), + E = UpgradedIntrinsics.end(); I != E; ++I) { + if (I->first != I->second) { + for (Value::use_iterator UI = I->first->use_begin(), + UE = I->first->use_end(); UI != UE; ) { + if (CallInst* CI = dyn_cast(*UI++)) + UpgradeIntrinsicCall(CI, I->second); + } + } + } + + return false; +} + +bool BitcodeReader::isDematerializable(const GlobalValue *GV) const { + const Function *F = dyn_cast(GV); + if (!F || F->isDeclaration()) + return false; + return DeferredFunctionInfo.count(const_cast(F)); +} + +void BitcodeReader::Dematerialize(GlobalValue *GV) { + Function *F = dyn_cast(GV); + // If this function isn't dematerializable, this is a noop. + if (!F || !isDematerializable(F)) + return; + + assert(DeferredFunctionInfo.count(F) && "No info to read function later?"); + + // Just forget the function body, we can remat it later. + F->deleteBody(); +} + + +bool BitcodeReader::MaterializeModule(Module *M, std::string *ErrInfo) { + assert(M == TheModule && + "Can only Materialize the Module this BitcodeReader is attached to."); + // Iterate over the module, deserializing any functions that are still on + // disk. + for (Module::iterator F = TheModule->begin(), E = TheModule->end(); + F != E; ++F) + if (F->isMaterializable() && + Materialize(F, ErrInfo)) + return true; + + // Upgrade any intrinsic calls that slipped through (should not happen!) and + // delete the old functions to clean up. We can't do this unless the entire + // module is materialized because there could always be another function body + // with calls to the old function. + for (std::vector >::iterator I = + UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) { + if (I->first != I->second) { + for (Value::use_iterator UI = I->first->use_begin(), + UE = I->first->use_end(); UI != UE; ) { + if (CallInst* CI = dyn_cast(*UI++)) + UpgradeIntrinsicCall(CI, I->second); + } + if (!I->first->use_empty()) + I->first->replaceAllUsesWith(I->second); + I->first->eraseFromParent(); + } + } + std::vector >().swap(UpgradedIntrinsics); + + // Check debug info intrinsics. + CheckDebugInfoIntrinsics(TheModule); + + return false; +} + + +//===----------------------------------------------------------------------===// +// External interface +//===----------------------------------------------------------------------===// + +/// getLazyBitcodeModule - lazy function-at-a-time loading from a file. +/// +Module *llvm::getLazyBitcodeModule(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg) { + Module *M = new Module(Buffer->getBufferIdentifier(), Context); + BitcodeReader *R = new BitcodeReader(Buffer, Context); + M->setMaterializer(R); + if (R->ParseBitcodeInto(M)) { + if (ErrMsg) + *ErrMsg = R->getErrorString(); + + delete M; // Also deletes R. + return 0; + } + // Have the BitcodeReader dtor delete 'Buffer'. + R->setBufferOwned(true); + return M; +} + +/// ParseBitcodeFile - Read the specified bitcode file, returning the module. +/// If an error occurs, return null and fill in *ErrMsg if non-null. +Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context, + std::string *ErrMsg){ + Module *M = getLazyBitcodeModule(Buffer, Context, ErrMsg); + if (!M) return 0; + + // Don't let the BitcodeReader dtor delete 'Buffer', regardless of whether + // there was an error. + static_cast(M->getMaterializer())->setBufferOwned(false); + + // Read in the entire module, and destroy the BitcodeReader. + if (M->MaterializeAllPermanently(ErrMsg)) { + delete M; + return 0; + } + + return M; +} + +std::string llvm::getBitcodeTargetTriple(MemoryBuffer *Buffer, + LLVMContext& Context, + std::string *ErrMsg) { + BitcodeReader *R = new BitcodeReader(Buffer, Context); + // Don't let the BitcodeReader dtor delete 'Buffer'. + R->setBufferOwned(false); + + std::string Triple(""); + if (R->ParseTriple(Triple)) + if (ErrMsg) + *ErrMsg = R->getErrorString(); + + delete R; + return Triple; +} diff --git a/final/lib/Bitcode/Reader/BitcodeReader.h b/final/lib/Bitcode/Reader/BitcodeReader.h new file mode 100644 index 00000000000..f8fc079c73d --- /dev/null +++ b/final/lib/Bitcode/Reader/BitcodeReader.h @@ -0,0 +1,282 @@ +//===- BitcodeReader.h - Internal BitcodeReader impl ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitcodeReader class. +// +//===----------------------------------------------------------------------===// + +#ifndef BITCODE_READER_H +#define BITCODE_READER_H + +#include "llvm/GVMaterializer.h" +#include "llvm/Attributes.h" +#include "llvm/Type.h" +#include "llvm/OperandTraits.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + class MemoryBuffer; + class LLVMContext; + +//===----------------------------------------------------------------------===// +// BitcodeReaderValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderValueList { + std::vector ValuePtrs; + + /// ResolveConstants - As we resolve forward-referenced constants, we add + /// information about them to this vector. This allows us to resolve them in + /// bulk instead of resolving each reference at a time. See the code in + /// ResolveConstantForwardRefs for more information about this. + /// + /// The key of this vector is the placeholder constant, the value is the slot + /// number that holds the resolved value. + typedef std::vector > ResolveConstantsTy; + ResolveConstantsTy ResolveConstants; + LLVMContext& Context; +public: + BitcodeReaderValueList(LLVMContext& C) : Context(C) {} + ~BitcodeReaderValueList() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + } + + // vector compatibility methods + unsigned size() const { return ValuePtrs.size(); } + void resize(unsigned N) { ValuePtrs.resize(N); } + void push_back(Value *V) { + ValuePtrs.push_back(V); + } + + void clear() { + assert(ResolveConstants.empty() && "Constants not resolved?"); + ValuePtrs.clear(); + } + + Value *operator[](unsigned i) const { + assert(i < ValuePtrs.size()); + return ValuePtrs[i]; + } + + Value *back() const { return ValuePtrs.back(); } + void pop_back() { ValuePtrs.pop_back(); } + bool empty() const { return ValuePtrs.empty(); } + void shrinkTo(unsigned N) { + assert(N <= size() && "Invalid shrinkTo request!"); + ValuePtrs.resize(N); + } + + Constant *getConstantFwdRef(unsigned Idx, const Type *Ty); + Value *getValueFwdRef(unsigned Idx, const Type *Ty); + + void AssignValue(Value *V, unsigned Idx); + + /// ResolveConstantForwardRefs - Once all constants are read, this method bulk + /// resolves any forward references. + void ResolveConstantForwardRefs(); +}; + + +//===----------------------------------------------------------------------===// +// BitcodeReaderMDValueList Class +//===----------------------------------------------------------------------===// + +class BitcodeReaderMDValueList { + std::vector MDValuePtrs; + + LLVMContext &Context; +public: + BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {} + + // vector compatibility methods + unsigned size() const { return MDValuePtrs.size(); } + void resize(unsigned N) { MDValuePtrs.resize(N); } + void push_back(Value *V) { MDValuePtrs.push_back(V); } + void clear() { MDValuePtrs.clear(); } + Value *back() const { return MDValuePtrs.back(); } + void pop_back() { MDValuePtrs.pop_back(); } + bool empty() const { return MDValuePtrs.empty(); } + + Value *operator[](unsigned i) const { + assert(i < MDValuePtrs.size()); + return MDValuePtrs[i]; + } + + void shrinkTo(unsigned N) { + assert(N <= size() && "Invalid shrinkTo request!"); + MDValuePtrs.resize(N); + } + + Value *getValueFwdRef(unsigned Idx); + void AssignValue(Value *V, unsigned Idx); +}; + +class BitcodeReader : public GVMaterializer { + LLVMContext &Context; + Module *TheModule; + MemoryBuffer *Buffer; + bool BufferOwned; + BitstreamReader StreamFile; + BitstreamCursor Stream; + + const char *ErrorString; + + std::vector TypeList; + BitcodeReaderValueList ValueList; + BitcodeReaderMDValueList MDValueList; + SmallVector InstructionList; + + std::vector > GlobalInits; + std::vector > AliasInits; + + /// MAttributes - The set of attributes by index. Index zero in the + /// file is for null, and is thus not represented here. As such all indices + /// are off by one. + std::vector MAttributes; + + /// FunctionBBs - While parsing a function body, this is a list of the basic + /// blocks for the function. + std::vector FunctionBBs; + + // When reading the module header, this list is populated with functions that + // have bodies later in the file. + std::vector FunctionsWithBodies; + + // When intrinsic functions are encountered which require upgrading they are + // stored here with their replacement function. + typedef std::vector > UpgradedIntrinsicMap; + UpgradedIntrinsicMap UpgradedIntrinsics; + + // Map the bitcode's custom MDKind ID to the Module's MDKind ID. + DenseMap MDKindMap; + + // After the module header has been read, the FunctionsWithBodies list is + // reversed. This keeps track of whether we've done this yet. + bool HasReversedFunctionsWithBodies; + + /// DeferredFunctionInfo - When function bodies are initially scanned, this + /// map contains info about where to find deferred function body in the + /// stream. + DenseMap DeferredFunctionInfo; + + /// BlockAddrFwdRefs - These are blockaddr references to basic blocks. These + /// are resolved lazily when functions are loaded. + typedef std::pair BlockAddrRefTy; + DenseMap > BlockAddrFwdRefs; + + /// LLVM2_7MetadataDetected - True if metadata produced by LLVM 2.7 or + /// earlier was detected, in which case we behave slightly differently, + /// for compatibility. + /// FIXME: Remove in LLVM 3.0. + bool LLVM2_7MetadataDetected; + +public: + explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C) + : Context(C), TheModule(0), Buffer(buffer), BufferOwned(false), + ErrorString(0), ValueList(C), MDValueList(C), + LLVM2_7MetadataDetected(false) { + HasReversedFunctionsWithBodies = false; + } + ~BitcodeReader() { + FreeState(); + } + + void FreeState(); + + /// setBufferOwned - If this is true, the reader will destroy the MemoryBuffer + /// when the reader is destroyed. + void setBufferOwned(bool Owned) { BufferOwned = Owned; } + + virtual bool isMaterializable(const GlobalValue *GV) const; + virtual bool isDematerializable(const GlobalValue *GV) const; + virtual bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0); + virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0); + virtual void Dematerialize(GlobalValue *GV); + + bool Error(const char *Str) { + ErrorString = Str; + return true; + } + const char *getErrorString() const { return ErrorString; } + + /// @brief Main interface to parsing a bitcode buffer. + /// @returns true if an error occurred. + bool ParseBitcodeInto(Module *M); + + /// @brief Cheap mechanism to just extract module triple + /// @returns true if an error occurred. + bool ParseTriple(std::string &Triple); +private: + const Type *getTypeByID(unsigned ID, bool isTypeTable = false); + Value *getFnValueByID(unsigned ID, const Type *Ty) { + if (Ty == Type::getMetadataTy(Context)) + return MDValueList.getValueFwdRef(ID); + else + return ValueList.getValueFwdRef(ID, Ty); + } + BasicBlock *getBasicBlock(unsigned ID) const { + if (ID >= FunctionBBs.size()) return 0; // Invalid ID + return FunctionBBs[ID]; + } + AttrListPtr getAttributes(unsigned i) const { + if (i-1 < MAttributes.size()) + return MAttributes[i-1]; + return AttrListPtr(); + } + + /// getValueTypePair - Read a value/type pair out of the specified record from + /// slot 'Slot'. Increment Slot past the number of slots used in the record. + /// Return true on failure. + bool getValueTypePair(SmallVector &Record, unsigned &Slot, + unsigned InstNum, Value *&ResVal) { + if (Slot == Record.size()) return true; + unsigned ValNo = (unsigned)Record[Slot++]; + if (ValNo < InstNum) { + // If this is not a forward reference, just return the value we already + // have. + ResVal = getFnValueByID(ValNo, 0); + return ResVal == 0; + } else if (Slot == Record.size()) { + return true; + } + + unsigned TypeNo = (unsigned)Record[Slot++]; + ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo)); + return ResVal == 0; + } + bool getValue(SmallVector &Record, unsigned &Slot, + const Type *Ty, Value *&ResVal) { + if (Slot == Record.size()) return true; + unsigned ValNo = (unsigned)Record[Slot++]; + ResVal = getFnValueByID(ValNo, Ty); + return ResVal == 0; + } + + + bool ParseModule(); + bool ParseAttributeBlock(); + bool ParseTypeTable(); + bool ParseTypeSymbolTable(); + bool ParseValueSymbolTable(); + bool ParseConstants(); + bool RememberAndSkipFunctionBody(); + bool ParseFunctionBody(Function *F); + bool ResolveGlobalAndAliasInits(); + bool ParseMetadata(); + bool ParseMetadataAttachment(); + bool ParseModuleTriple(std::string &Triple); +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/Bitcode/Reader/CMakeLists.txt b/final/lib/Bitcode/Reader/CMakeLists.txt new file mode 100644 index 00000000000..693d4310b83 --- /dev/null +++ b/final/lib/Bitcode/Reader/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMBitReader + BitReader.cpp + BitcodeReader.cpp + ) diff --git a/final/lib/Bitcode/Reader/Makefile b/final/lib/Bitcode/Reader/Makefile new file mode 100644 index 00000000000..59af8d53a73 --- /dev/null +++ b/final/lib/Bitcode/Reader/Makefile @@ -0,0 +1,15 @@ +##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMBitReader +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Bitcode/Writer/BitWriter.cpp b/final/lib/Bitcode/Writer/BitWriter.cpp new file mode 100644 index 00000000000..42884224633 --- /dev/null +++ b/final/lib/Bitcode/Writer/BitWriter.cpp @@ -0,0 +1,40 @@ +//===-- BitWriter.cpp -----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/BitWriter.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + + +/*===-- Operations on modules ---------------------------------------------===*/ + +int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path) { + std::string ErrorInfo; + raw_fd_ostream OS(Path, ErrorInfo, + raw_fd_ostream::F_Binary); + + if (!ErrorInfo.empty()) + return -1; + + WriteBitcodeToFile(unwrap(M), OS); + return 0; +} + +int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, + int Unbuffered) { + raw_fd_ostream OS(FD, ShouldClose, Unbuffered); + + WriteBitcodeToFile(unwrap(M), OS); + return 0; +} + +int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int FileHandle) { + return LLVMWriteBitcodeToFD(M, FileHandle, true, false); +} diff --git a/final/lib/Bitcode/Writer/BitcodeWriter.cpp b/final/lib/Bitcode/Writer/BitcodeWriter.cpp new file mode 100644 index 00000000000..f8ef8c668c4 --- /dev/null +++ b/final/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -0,0 +1,1672 @@ +//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Bitcode writer implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Bitcode/LLVMBitCodes.h" +#include "ValueEnumerator.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" +#include "llvm/Operator.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Program.h" +#include +using namespace llvm; + +/// These are manifest constants used by the bitcode writer. They do not need to +/// be kept in sync with the reader, but need to be consistent within this file. +enum { + CurVersion = 0, + + // VALUE_SYMTAB_BLOCK abbrev id's. + VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + VST_ENTRY_7_ABBREV, + VST_ENTRY_6_ABBREV, + VST_BBENTRY_6_ABBREV, + + // CONSTANTS_BLOCK abbrev id's. + CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + CONSTANTS_INTEGER_ABBREV, + CONSTANTS_CE_CAST_Abbrev, + CONSTANTS_NULL_Abbrev, + + // FUNCTION_BLOCK abbrev id's. + FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + FUNCTION_INST_BINOP_ABBREV, + FUNCTION_INST_BINOP_FLAGS_ABBREV, + FUNCTION_INST_CAST_ABBREV, + FUNCTION_INST_RET_VOID_ABBREV, + FUNCTION_INST_RET_VAL_ABBREV, + FUNCTION_INST_UNREACHABLE_ABBREV +}; + + +static unsigned GetEncodedCastOpcode(unsigned Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown cast instruction!"); + case Instruction::Trunc : return bitc::CAST_TRUNC; + case Instruction::ZExt : return bitc::CAST_ZEXT; + case Instruction::SExt : return bitc::CAST_SEXT; + case Instruction::FPToUI : return bitc::CAST_FPTOUI; + case Instruction::FPToSI : return bitc::CAST_FPTOSI; + case Instruction::UIToFP : return bitc::CAST_UITOFP; + case Instruction::SIToFP : return bitc::CAST_SITOFP; + case Instruction::FPTrunc : return bitc::CAST_FPTRUNC; + case Instruction::FPExt : return bitc::CAST_FPEXT; + case Instruction::PtrToInt: return bitc::CAST_PTRTOINT; + case Instruction::IntToPtr: return bitc::CAST_INTTOPTR; + case Instruction::BitCast : return bitc::CAST_BITCAST; + } +} + +static unsigned GetEncodedBinaryOpcode(unsigned Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown binary instruction!"); + case Instruction::Add: + case Instruction::FAdd: return bitc::BINOP_ADD; + case Instruction::Sub: + case Instruction::FSub: return bitc::BINOP_SUB; + case Instruction::Mul: + case Instruction::FMul: return bitc::BINOP_MUL; + case Instruction::UDiv: return bitc::BINOP_UDIV; + case Instruction::FDiv: + case Instruction::SDiv: return bitc::BINOP_SDIV; + case Instruction::URem: return bitc::BINOP_UREM; + case Instruction::FRem: + case Instruction::SRem: return bitc::BINOP_SREM; + case Instruction::Shl: return bitc::BINOP_SHL; + case Instruction::LShr: return bitc::BINOP_LSHR; + case Instruction::AShr: return bitc::BINOP_ASHR; + case Instruction::And: return bitc::BINOP_AND; + case Instruction::Or: return bitc::BINOP_OR; + case Instruction::Xor: return bitc::BINOP_XOR; + } +} + + + +static void WriteStringRecord(unsigned Code, const std::string &Str, + unsigned AbbrevToUse, BitstreamWriter &Stream) { + SmallVector Vals; + + // Code: [strchar x N] + for (unsigned i = 0, e = Str.size(); i != e; ++i) + Vals.push_back(Str[i]); + + // Emit the finished record. + Stream.EmitRecord(Code, Vals, AbbrevToUse); +} + +// Emit information about parameter attributes. +static void WriteAttributeTable(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const std::vector &Attrs = VE.getAttributes(); + if (Attrs.empty()) return; + + Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3); + + SmallVector Record; + for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { + const AttrListPtr &A = Attrs[i]; + for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) { + const AttributeWithIndex &PAWI = A.getSlot(i); + Record.push_back(PAWI.Index); + + // FIXME: remove in LLVM 3.0 + // Store the alignment in the bitcode as a 16-bit raw value instead of a + // 5-bit log2 encoded value. Shift the bits above the alignment up by + // 11 bits. + uint64_t FauxAttr = PAWI.Attrs & 0xffff; + if (PAWI.Attrs & Attribute::Alignment) + FauxAttr |= (1ull<<16)<<(((PAWI.Attrs & Attribute::Alignment)-1) >> 16); + FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11; + + Record.push_back(FauxAttr); + } + + Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); + Record.clear(); + } + + Stream.ExitBlock(); +} + +/// WriteTypeTable - Write out the type table for a module. +static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { + const ValueEnumerator::TypeList &TypeList = VE.getTypes(); + + Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */); + SmallVector TypeVals; + + // Abbrev for TYPE_CODE_POINTER. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0 + unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_FUNCTION. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg + Abbv->Add(BitCodeAbbrevOp(0)); // FIXME: DEAD value, remove in LLVM 3.0 + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_STRUCT. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned StructAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for TYPE_CODE_ARRAY. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv); + + // Emit an entry count so the reader can reserve space. + TypeVals.push_back(TypeList.size()); + Stream.EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals); + TypeVals.clear(); + + // Loop over all of the types, emitting each in turn. + for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { + const Type *T = TypeList[i].first; + int AbbrevToUse = 0; + unsigned Code = 0; + + switch (T->getTypeID()) { + default: llvm_unreachable("Unknown type!"); + case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break; + case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break; + case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break; + case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break; + case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break; + case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break; + case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break; + case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break; + case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break; + case Type::X86_MMXTyID: Code = bitc::TYPE_CODE_X86_MMX; break; + case Type::IntegerTyID: + // INTEGER: [width] + Code = bitc::TYPE_CODE_INTEGER; + TypeVals.push_back(cast(T)->getBitWidth()); + break; + case Type::PointerTyID: { + const PointerType *PTy = cast(T); + // POINTER: [pointee type, address space] + Code = bitc::TYPE_CODE_POINTER; + TypeVals.push_back(VE.getTypeID(PTy->getElementType())); + unsigned AddressSpace = PTy->getAddressSpace(); + TypeVals.push_back(AddressSpace); + if (AddressSpace == 0) AbbrevToUse = PtrAbbrev; + break; + } + case Type::FunctionTyID: { + const FunctionType *FT = cast(T); + // FUNCTION: [isvararg, attrid, retty, paramty x N] + Code = bitc::TYPE_CODE_FUNCTION; + TypeVals.push_back(FT->isVarArg()); + TypeVals.push_back(0); // FIXME: DEAD: remove in llvm 3.0 + TypeVals.push_back(VE.getTypeID(FT->getReturnType())); + for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) + TypeVals.push_back(VE.getTypeID(FT->getParamType(i))); + AbbrevToUse = FunctionAbbrev; + break; + } + case Type::StructTyID: { + const StructType *ST = cast(T); + // STRUCT: [ispacked, eltty x N] + Code = bitc::TYPE_CODE_STRUCT; + TypeVals.push_back(ST->isPacked()); + // Output all of the element types. + for (StructType::element_iterator I = ST->element_begin(), + E = ST->element_end(); I != E; ++I) + TypeVals.push_back(VE.getTypeID(*I)); + AbbrevToUse = StructAbbrev; + break; + } + case Type::ArrayTyID: { + const ArrayType *AT = cast(T); + // ARRAY: [numelts, eltty] + Code = bitc::TYPE_CODE_ARRAY; + TypeVals.push_back(AT->getNumElements()); + TypeVals.push_back(VE.getTypeID(AT->getElementType())); + AbbrevToUse = ArrayAbbrev; + break; + } + case Type::VectorTyID: { + const VectorType *VT = cast(T); + // VECTOR [numelts, eltty] + Code = bitc::TYPE_CODE_VECTOR; + TypeVals.push_back(VT->getNumElements()); + TypeVals.push_back(VE.getTypeID(VT->getElementType())); + break; + } + } + + // Emit the finished record. + Stream.EmitRecord(Code, TypeVals, AbbrevToUse); + TypeVals.clear(); + } + + Stream.ExitBlock(); +} + +static unsigned getEncodedLinkage(const GlobalValue *GV) { + switch (GV->getLinkage()) { + default: llvm_unreachable("Invalid linkage!"); + case GlobalValue::ExternalLinkage: return 0; + case GlobalValue::WeakAnyLinkage: return 1; + case GlobalValue::AppendingLinkage: return 2; + case GlobalValue::InternalLinkage: return 3; + case GlobalValue::LinkOnceAnyLinkage: return 4; + case GlobalValue::DLLImportLinkage: return 5; + case GlobalValue::DLLExportLinkage: return 6; + case GlobalValue::ExternalWeakLinkage: return 7; + case GlobalValue::CommonLinkage: return 8; + case GlobalValue::PrivateLinkage: return 9; + case GlobalValue::WeakODRLinkage: return 10; + case GlobalValue::LinkOnceODRLinkage: return 11; + case GlobalValue::AvailableExternallyLinkage: return 12; + case GlobalValue::LinkerPrivateLinkage: return 13; + case GlobalValue::LinkerPrivateWeakLinkage: return 14; + case GlobalValue::LinkerPrivateWeakDefAutoLinkage: return 15; + } +} + +static unsigned getEncodedVisibility(const GlobalValue *GV) { + switch (GV->getVisibility()) { + default: llvm_unreachable("Invalid visibility!"); + case GlobalValue::DefaultVisibility: return 0; + case GlobalValue::HiddenVisibility: return 1; + case GlobalValue::ProtectedVisibility: return 2; + } +} + +// Emit top-level description of module, including target triple, inline asm, +// descriptors for global variables, and function prototype info. +static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, + BitstreamWriter &Stream) { + // Emit the list of dependent libraries for the Module. + for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I) + WriteStringRecord(bitc::MODULE_CODE_DEPLIB, *I, 0/*TODO*/, Stream); + + // Emit various pieces of data attached to a module. + if (!M->getTargetTriple().empty()) + WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(), + 0/*TODO*/, Stream); + if (!M->getDataLayout().empty()) + WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(), + 0/*TODO*/, Stream); + if (!M->getModuleInlineAsm().empty()) + WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(), + 0/*TODO*/, Stream); + + // Emit information about sections and GC, computing how many there are. Also + // compute the maximum alignment value. + std::map SectionMap; + std::map GCMap; + unsigned MaxAlignment = 0; + unsigned MaxGlobalType = 0; + for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); + GV != E; ++GV) { + MaxAlignment = std::max(MaxAlignment, GV->getAlignment()); + MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV->getType())); + + if (!GV->hasSection()) continue; + // Give section names unique ID's. + unsigned &Entry = SectionMap[GV->getSection()]; + if (Entry != 0) continue; + WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(), + 0/*TODO*/, Stream); + Entry = SectionMap.size(); + } + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + MaxAlignment = std::max(MaxAlignment, F->getAlignment()); + if (F->hasSection()) { + // Give section names unique ID's. + unsigned &Entry = SectionMap[F->getSection()]; + if (!Entry) { + WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(), + 0/*TODO*/, Stream); + Entry = SectionMap.size(); + } + } + if (F->hasGC()) { + // Same for GC names. + unsigned &Entry = GCMap[F->getGC()]; + if (!Entry) { + WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(), + 0/*TODO*/, Stream); + Entry = GCMap.size(); + } + } + } + + // Emit abbrev for globals, now that we know # sections and max alignment. + unsigned SimpleGVarAbbrev = 0; + if (!M->global_empty()) { + // Add an abbrev for common globals with no visibility or thread localness. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(MaxGlobalType+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Linkage. + if (MaxAlignment == 0) // Alignment. + Abbv->Add(BitCodeAbbrevOp(0)); + else { + unsigned MaxEncAlignment = Log2_32(MaxAlignment)+1; + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(MaxEncAlignment+1))); + } + if (SectionMap.empty()) // Section. + Abbv->Add(BitCodeAbbrevOp(0)); + else + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(SectionMap.size()+1))); + // Don't bother emitting vis + thread local. + SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv); + } + + // Emit the global variable information. + SmallVector Vals; + for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end(); + GV != E; ++GV) { + unsigned AbbrevToUse = 0; + + // GLOBALVAR: [type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal, + // unnamed_addr] + Vals.push_back(VE.getTypeID(GV->getType())); + Vals.push_back(GV->isConstant()); + Vals.push_back(GV->isDeclaration() ? 0 : + (VE.getValueID(GV->getInitializer()) + 1)); + Vals.push_back(getEncodedLinkage(GV)); + Vals.push_back(Log2_32(GV->getAlignment())+1); + Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0); + if (GV->isThreadLocal() || + GV->getVisibility() != GlobalValue::DefaultVisibility || + GV->hasUnnamedAddr()) { + Vals.push_back(getEncodedVisibility(GV)); + Vals.push_back(GV->isThreadLocal()); + Vals.push_back(GV->hasUnnamedAddr()); + } else { + AbbrevToUse = SimpleGVarAbbrev; + } + + Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse); + Vals.clear(); + } + + // Emit the function proto information. + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + // FUNCTION: [type, callingconv, isproto, paramattr, + // linkage, alignment, section, visibility, gc, unnamed_addr] + Vals.push_back(VE.getTypeID(F->getType())); + Vals.push_back(F->getCallingConv()); + Vals.push_back(F->isDeclaration()); + Vals.push_back(getEncodedLinkage(F)); + Vals.push_back(VE.getAttributeID(F->getAttributes())); + Vals.push_back(Log2_32(F->getAlignment())+1); + Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0); + Vals.push_back(getEncodedVisibility(F)); + Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0); + Vals.push_back(F->hasUnnamedAddr()); + + unsigned AbbrevToUse = 0; + Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse); + Vals.clear(); + } + + + // Emit the alias information. + for (Module::const_alias_iterator AI = M->alias_begin(), E = M->alias_end(); + AI != E; ++AI) { + Vals.push_back(VE.getTypeID(AI->getType())); + Vals.push_back(VE.getValueID(AI->getAliasee())); + Vals.push_back(getEncodedLinkage(AI)); + Vals.push_back(getEncodedVisibility(AI)); + unsigned AbbrevToUse = 0; + Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); + Vals.clear(); + } +} + +static uint64_t GetOptimizationFlags(const Value *V) { + uint64_t Flags = 0; + + if (const OverflowingBinaryOperator *OBO = + dyn_cast(V)) { + if (OBO->hasNoSignedWrap()) + Flags |= 1 << bitc::OBO_NO_SIGNED_WRAP; + if (OBO->hasNoUnsignedWrap()) + Flags |= 1 << bitc::OBO_NO_UNSIGNED_WRAP; + } else if (const PossiblyExactOperator *PEO = + dyn_cast(V)) { + if (PEO->isExact()) + Flags |= 1 << bitc::PEO_EXACT; + } + + return Flags; +} + +static void WriteMDNode(const MDNode *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVector &Record) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (N->getOperand(i)) { + Record.push_back(VE.getTypeID(N->getOperand(i)->getType())); + Record.push_back(VE.getValueID(N->getOperand(i))); + } else { + Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext()))); + Record.push_back(0); + } + } + unsigned MDCode = N->isFunctionLocal() ? bitc::METADATA_FN_NODE2 : + bitc::METADATA_NODE2; + Stream.EmitRecord(MDCode, Record, 0); + Record.clear(); +} + +static void WriteModuleMetadata(const Module *M, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const ValueEnumerator::ValueList &Vals = VE.getMDValues(); + bool StartedMetadataBlock = false; + unsigned MDSAbbrev = 0; + SmallVector Record; + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + + if (const MDNode *N = dyn_cast(Vals[i].first)) { + if (!N->isFunctionLocal() || !N->getFunction()) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + WriteMDNode(N, VE, Stream, Record); + } + } else if (const MDString *MDS = dyn_cast(Vals[i].first)) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + + // Abbrev for METADATA_STRING. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + MDSAbbrev = Stream.EmitAbbrev(Abbv); + StartedMetadataBlock = true; + } + + // Code: [strchar x N] + Record.append(MDS->begin(), MDS->end()); + + // Emit the finished record. + Stream.EmitRecord(bitc::METADATA_STRING, Record, MDSAbbrev); + Record.clear(); + } + } + + // Write named metadata. + for (Module::const_named_metadata_iterator I = M->named_metadata_begin(), + E = M->named_metadata_end(); I != E; ++I) { + const NamedMDNode *NMD = I; + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + + // Write name. + StringRef Str = NMD->getName(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) + Record.push_back(Str[i]); + Stream.EmitRecord(bitc::METADATA_NAME, Record, 0/*TODO*/); + Record.clear(); + + // Write named metadata operands. + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + Record.push_back(VE.getValueID(NMD->getOperand(i))); + Stream.EmitRecord(bitc::METADATA_NAMED_NODE2, Record, 0); + Record.clear(); + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} + +static void WriteFunctionLocalMetadata(const Function &F, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + bool StartedMetadataBlock = false; + SmallVector Record; + const SmallVector &Vals = VE.getFunctionLocalMDValues(); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) + if (const MDNode *N = Vals[i]) + if (N->isFunctionLocal() && N->getFunction() == &F) { + if (!StartedMetadataBlock) { + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + StartedMetadataBlock = true; + } + WriteMDNode(N, VE, Stream, Record); + } + + if (StartedMetadataBlock) + Stream.ExitBlock(); +} + +static void WriteMetadataAttachment(const Function &F, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3); + + SmallVector Record; + + // Write metadata attachments + // METADATA_ATTACHMENT2 - [m x [value, [n x [id, mdnode]]] + SmallVector, 4> MDs; + + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + MDs.clear(); + I->getAllMetadataOtherThanDebugLoc(MDs); + + // If no metadata, ignore instruction. + if (MDs.empty()) continue; + + Record.push_back(VE.getInstructionID(I)); + + for (unsigned i = 0, e = MDs.size(); i != e; ++i) { + Record.push_back(MDs[i].first); + Record.push_back(VE.getValueID(MDs[i].second)); + } + Stream.EmitRecord(bitc::METADATA_ATTACHMENT2, Record, 0); + Record.clear(); + } + + Stream.ExitBlock(); +} + +static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) { + SmallVector Record; + + // Write metadata kinds + // METADATA_KIND - [n x [id, name]] + SmallVector Names; + M->getMDKindNames(Names); + + if (Names.empty()) return; + + Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3); + + for (unsigned MDKindID = 0, e = Names.size(); MDKindID != e; ++MDKindID) { + Record.push_back(MDKindID); + StringRef KName = Names[MDKindID]; + Record.append(KName.begin(), KName.end()); + + Stream.EmitRecord(bitc::METADATA_KIND, Record, 0); + Record.clear(); + } + + Stream.ExitBlock(); +} + +static void WriteConstants(unsigned FirstVal, unsigned LastVal, + const ValueEnumerator &VE, + BitstreamWriter &Stream, bool isGlobal) { + if (FirstVal == LastVal) return; + + Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4); + + unsigned AggregateAbbrev = 0; + unsigned String8Abbrev = 0; + unsigned CString7Abbrev = 0; + unsigned CString6Abbrev = 0; + // If this is a constant pool for the module, emit module-specific abbrevs. + if (isGlobal) { + // Abbrev for CST_CODE_AGGREGATE. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1))); + AggregateAbbrev = Stream.EmitAbbrev(Abbv); + + // Abbrev for CST_CODE_STRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + String8Abbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + CString7Abbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + CString6Abbrev = Stream.EmitAbbrev(Abbv); + } + + SmallVector Record; + + const ValueEnumerator::ValueList &Vals = VE.getValues(); + const Type *LastTy = 0; + for (unsigned i = FirstVal; i != LastVal; ++i) { + const Value *V = Vals[i].first; + // If we need to switch types, do so now. + if (V->getType() != LastTy) { + LastTy = V->getType(); + Record.push_back(VE.getTypeID(LastTy)); + Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record, + CONSTANTS_SETTYPE_ABBREV); + Record.clear(); + } + + if (const InlineAsm *IA = dyn_cast(V)) { + Record.push_back(unsigned(IA->hasSideEffects()) | + unsigned(IA->isAlignStack()) << 1); + + // Add the asm string. + const std::string &AsmStr = IA->getAsmString(); + Record.push_back(AsmStr.size()); + for (unsigned i = 0, e = AsmStr.size(); i != e; ++i) + Record.push_back(AsmStr[i]); + + // Add the constraint string. + const std::string &ConstraintStr = IA->getConstraintString(); + Record.push_back(ConstraintStr.size()); + for (unsigned i = 0, e = ConstraintStr.size(); i != e; ++i) + Record.push_back(ConstraintStr[i]); + Stream.EmitRecord(bitc::CST_CODE_INLINEASM, Record); + Record.clear(); + continue; + } + const Constant *C = cast(V); + unsigned Code = -1U; + unsigned AbbrevToUse = 0; + if (C->isNullValue()) { + Code = bitc::CST_CODE_NULL; + } else if (isa(C)) { + Code = bitc::CST_CODE_UNDEF; + } else if (const ConstantInt *IV = dyn_cast(C)) { + if (IV->getBitWidth() <= 64) { + uint64_t V = IV->getSExtValue(); + if ((int64_t)V >= 0) + Record.push_back(V << 1); + else + Record.push_back((-V << 1) | 1); + Code = bitc::CST_CODE_INTEGER; + AbbrevToUse = CONSTANTS_INTEGER_ABBREV; + } else { // Wide integers, > 64 bits in size. + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NWords = IV->getValue().getActiveWords(); + const uint64_t *RawWords = IV->getValue().getRawData(); + for (unsigned i = 0; i != NWords; ++i) { + int64_t V = RawWords[i]; + if (V >= 0) + Record.push_back(V << 1); + else + Record.push_back((-V << 1) | 1); + } + Code = bitc::CST_CODE_WIDE_INTEGER; + } + } else if (const ConstantFP *CFP = dyn_cast(C)) { + Code = bitc::CST_CODE_FLOAT; + const Type *Ty = CFP->getType(); + if (Ty->isFloatTy() || Ty->isDoubleTy()) { + Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + } else if (Ty->isX86_FP80Ty()) { + // api needed to prevent premature destruction + // bits are not in the same order as a normal i80 APInt, compensate. + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Record.push_back((p[1] << 48) | (p[0] >> 16)); + Record.push_back(p[0] & 0xffffLL); + } else if (Ty->isFP128Ty() || Ty->isPPC_FP128Ty()) { + APInt api = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = api.getRawData(); + Record.push_back(p[0]); + Record.push_back(p[1]); + } else { + assert (0 && "Unknown FP type!"); + } + } else if (isa(C) && cast(C)->isString()) { + const ConstantArray *CA = cast(C); + // Emit constant strings specially. + unsigned NumOps = CA->getNumOperands(); + // If this is a null-terminated string, use the denser CSTRING encoding. + if (CA->getOperand(NumOps-1)->isNullValue()) { + Code = bitc::CST_CODE_CSTRING; + --NumOps; // Don't encode the null, which isn't allowed by char6. + } else { + Code = bitc::CST_CODE_STRING; + AbbrevToUse = String8Abbrev; + } + bool isCStr7 = Code == bitc::CST_CODE_CSTRING; + bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned char V = cast(CA->getOperand(i))->getZExtValue(); + Record.push_back(V); + isCStr7 &= (V & 128) == 0; + if (isCStrChar6) + isCStrChar6 = BitCodeAbbrevOp::isChar6(V); + } + + if (isCStrChar6) + AbbrevToUse = CString6Abbrev; + else if (isCStr7) + AbbrevToUse = CString7Abbrev; + } else if (isa(C) || isa(V) || + isa(V)) { + Code = bitc::CST_CODE_AGGREGATE; + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) + Record.push_back(VE.getValueID(C->getOperand(i))); + AbbrevToUse = AggregateAbbrev; + } else if (const ConstantExpr *CE = dyn_cast(C)) { + switch (CE->getOpcode()) { + default: + if (Instruction::isCast(CE->getOpcode())) { + Code = bitc::CST_CODE_CE_CAST; + Record.push_back(GetEncodedCastOpcode(CE->getOpcode())); + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + AbbrevToUse = CONSTANTS_CE_CAST_Abbrev; + } else { + assert(CE->getNumOperands() == 2 && "Unknown constant expr!"); + Code = bitc::CST_CODE_CE_BINOP; + Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + uint64_t Flags = GetOptimizationFlags(CE); + if (Flags != 0) + Record.push_back(Flags); + } + break; + case Instruction::GetElementPtr: + Code = bitc::CST_CODE_CE_GEP; + if (cast(C)->isInBounds()) + Code = bitc::CST_CODE_CE_INBOUNDS_GEP; + for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { + Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); + Record.push_back(VE.getValueID(C->getOperand(i))); + } + break; + case Instruction::Select: + Code = bitc::CST_CODE_CE_SELECT; + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ExtractElement: + Code = bitc::CST_CODE_CE_EXTRACTELT; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + break; + case Instruction::InsertElement: + Code = bitc::CST_CODE_CE_INSERTELT; + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ShuffleVector: + // If the return type and argument types are the same, this is a + // standard shufflevector instruction. If the types are different, + // then the shuffle is widening or truncating the input vectors, and + // the argument type must also be encoded. + if (C->getType() == C->getOperand(0)->getType()) { + Code = bitc::CST_CODE_CE_SHUFFLEVEC; + } else { + Code = bitc::CST_CODE_CE_SHUFVEC_EX; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + } + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; + case Instruction::ICmp: + case Instruction::FCmp: + Code = bitc::CST_CODE_CE_CMP; + Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(CE->getPredicate()); + break; + } + } else if (const BlockAddress *BA = dyn_cast(C)) { + assert(BA->getFunction() == BA->getBasicBlock()->getParent() && + "Malformed blockaddress"); + Code = bitc::CST_CODE_BLOCKADDRESS; + Record.push_back(VE.getTypeID(BA->getFunction()->getType())); + Record.push_back(VE.getValueID(BA->getFunction())); + Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); + } else { +#ifndef NDEBUG + C->dump(); +#endif + llvm_unreachable("Unknown constant!"); + } + Stream.EmitRecord(Code, Record, AbbrevToUse); + Record.clear(); + } + + Stream.ExitBlock(); +} + +static void WriteModuleConstants(const ValueEnumerator &VE, + BitstreamWriter &Stream) { + const ValueEnumerator::ValueList &Vals = VE.getValues(); + + // Find the first constant to emit, which is the first non-globalvalue value. + // We know globalvalues have been emitted by WriteModuleInfo. + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + if (!isa(Vals[i].first)) { + WriteConstants(i, Vals.size(), VE, Stream, true); + return; + } + } +} + +/// PushValueAndType - The file has to encode both the value and type id for +/// many values, because we need to know what type to create for forward +/// references. However, most operands are not forward references, so this type +/// field is not needed. +/// +/// This function adds V's value ID to Vals. If the value ID is higher than the +/// instruction ID, then it is a forward reference, and it also includes the +/// type ID. +static bool PushValueAndType(const Value *V, unsigned InstID, + SmallVector &Vals, + ValueEnumerator &VE) { + unsigned ValID = VE.getValueID(V); + Vals.push_back(ValID); + if (ValID >= InstID) { + Vals.push_back(VE.getTypeID(V->getType())); + return true; + } + return false; +} + +/// WriteInstruction - Emit an instruction to the specified stream. +static void WriteInstruction(const Instruction &I, unsigned InstID, + ValueEnumerator &VE, BitstreamWriter &Stream, + SmallVector &Vals) { + unsigned Code = 0; + unsigned AbbrevToUse = 0; + VE.setInstructionID(&I); + switch (I.getOpcode()) { + default: + if (Instruction::isCast(I.getOpcode())) { + Code = bitc::FUNC_CODE_INST_CAST; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_CAST_ABBREV; + Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(GetEncodedCastOpcode(I.getOpcode())); + } else { + assert(isa(I) && "Unknown instruction!"); + Code = bitc::FUNC_CODE_INST_BINOP; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_BINOP_ABBREV; + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode())); + uint64_t Flags = GetOptimizationFlags(&I); + if (Flags != 0) { + if (AbbrevToUse == FUNCTION_INST_BINOP_ABBREV) + AbbrevToUse = FUNCTION_INST_BINOP_FLAGS_ABBREV; + Vals.push_back(Flags); + } + } + break; + + case Instruction::GetElementPtr: + Code = bitc::FUNC_CODE_INST_GEP; + if (cast(&I)->isInBounds()) + Code = bitc::FUNC_CODE_INST_INBOUNDS_GEP; + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); + break; + case Instruction::ExtractValue: { + Code = bitc::FUNC_CODE_INST_EXTRACTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + const ExtractValueInst *EVI = cast(&I); + for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } + case Instruction::InsertValue: { + Code = bitc::FUNC_CODE_INST_INSERTVAL; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + PushValueAndType(I.getOperand(1), InstID, Vals, VE); + const InsertValueInst *IVI = cast(&I); + for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) + Vals.push_back(*i); + break; + } + case Instruction::Select: + Code = bitc::FUNC_CODE_INST_VSELECT; + PushValueAndType(I.getOperand(1), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(2))); + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + break; + case Instruction::ExtractElement: + Code = bitc::FUNC_CODE_INST_EXTRACTELT; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + break; + case Instruction::InsertElement: + Code = bitc::FUNC_CODE_INST_INSERTELT; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(VE.getValueID(I.getOperand(2))); + break; + case Instruction::ShuffleVector: + Code = bitc::FUNC_CODE_INST_SHUFFLEVEC; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(VE.getValueID(I.getOperand(2))); + break; + case Instruction::ICmp: + case Instruction::FCmp: + // compare returning Int1Ty or vector of Int1Ty + Code = bitc::FUNC_CODE_INST_CMP2; + PushValueAndType(I.getOperand(0), InstID, Vals, VE); + Vals.push_back(VE.getValueID(I.getOperand(1))); + Vals.push_back(cast(I).getPredicate()); + break; + + case Instruction::Ret: + { + Code = bitc::FUNC_CODE_INST_RET; + unsigned NumOperands = I.getNumOperands(); + if (NumOperands == 0) + AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV; + else if (NumOperands == 1) { + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) + AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV; + } else { + for (unsigned i = 0, e = NumOperands; i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); + } + } + break; + case Instruction::Br: + { + Code = bitc::FUNC_CODE_INST_BR; + BranchInst &II = cast(I); + Vals.push_back(VE.getValueID(II.getSuccessor(0))); + if (II.isConditional()) { + Vals.push_back(VE.getValueID(II.getSuccessor(1))); + Vals.push_back(VE.getValueID(II.getCondition())); + } + } + break; + case Instruction::Switch: + Code = bitc::FUNC_CODE_INST_SWITCH; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + case Instruction::IndirectBr: + Code = bitc::FUNC_CODE_INST_INDIRECTBR; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + + case Instruction::Invoke: { + const InvokeInst *II = cast(&I); + const Value *Callee(II->getCalledValue()); + const PointerType *PTy = cast(Callee->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + Code = bitc::FUNC_CODE_INST_INVOKE; + + Vals.push_back(VE.getAttributeID(II->getAttributes())); + Vals.push_back(II->getCallingConv()); + Vals.push_back(VE.getValueID(II->getNormalDest())); + Vals.push_back(VE.getValueID(II->getUnwindDest())); + PushValueAndType(Callee, InstID, Vals, VE); + + // Emit value #'s for the fixed parameters. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); // fixed param. + + // Emit type/value pairs for varargs params. + if (FTy->isVarArg()) { + for (unsigned i = FTy->getNumParams(), e = I.getNumOperands()-3; + i != e; ++i) + PushValueAndType(I.getOperand(i), InstID, Vals, VE); // vararg + } + break; + } + case Instruction::Unwind: + Code = bitc::FUNC_CODE_INST_UNWIND; + break; + case Instruction::Unreachable: + Code = bitc::FUNC_CODE_INST_UNREACHABLE; + AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV; + break; + + case Instruction::PHI: + Code = bitc::FUNC_CODE_INST_PHI; + Vals.push_back(VE.getTypeID(I.getType())); + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) + Vals.push_back(VE.getValueID(I.getOperand(i))); + break; + + case Instruction::Alloca: + Code = bitc::FUNC_CODE_INST_ALLOCA; + Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + Vals.push_back(VE.getValueID(I.getOperand(0))); // size. + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + break; + + case Instruction::Load: + Code = bitc::FUNC_CODE_INST_LOAD; + if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr + AbbrevToUse = FUNCTION_INST_LOAD_ABBREV; + + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + Vals.push_back(cast(I).isVolatile()); + break; + case Instruction::Store: + Code = bitc::FUNC_CODE_INST_STORE2; + PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr + Vals.push_back(VE.getValueID(I.getOperand(0))); // val. + Vals.push_back(Log2_32(cast(I).getAlignment())+1); + Vals.push_back(cast(I).isVolatile()); + break; + case Instruction::Call: { + const CallInst &CI = cast(I); + const PointerType *PTy = cast(CI.getCalledValue()->getType()); + const FunctionType *FTy = cast(PTy->getElementType()); + + Code = bitc::FUNC_CODE_INST_CALL2; + + Vals.push_back(VE.getAttributeID(CI.getAttributes())); + Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall())); + PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee + + // Emit value #'s for the fixed parameters. + for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) + Vals.push_back(VE.getValueID(CI.getArgOperand(i))); // fixed param. + + // Emit type/value pairs for varargs params. + if (FTy->isVarArg()) { + for (unsigned i = FTy->getNumParams(), e = CI.getNumArgOperands(); + i != e; ++i) + PushValueAndType(CI.getArgOperand(i), InstID, Vals, VE); // varargs + } + break; + } + case Instruction::VAArg: + Code = bitc::FUNC_CODE_INST_VAARG; + Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty + Vals.push_back(VE.getValueID(I.getOperand(0))); // valist. + Vals.push_back(VE.getTypeID(I.getType())); // restype. + break; + } + + Stream.EmitRecord(Code, Vals, AbbrevToUse); + Vals.clear(); +} + +// Emit names for globals/functions etc. +static void WriteValueSymbolTable(const ValueSymbolTable &VST, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + if (VST.empty()) return; + Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4); + + // FIXME: Set up the abbrev, we know how many values there are! + // FIXME: We know if the type names can use 7-bit ascii. + SmallVector NameVals; + + for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end(); + SI != SE; ++SI) { + + const ValueName &Name = *SI; + + // Figure out the encoding to use for the name. + bool is7Bit = true; + bool isChar6 = true; + for (const char *C = Name.getKeyData(), *E = C+Name.getKeyLength(); + C != E; ++C) { + if (isChar6) + isChar6 = BitCodeAbbrevOp::isChar6(*C); + if ((unsigned char)*C & 128) { + is7Bit = false; + break; // don't bother scanning the rest. + } + } + + unsigned AbbrevToUse = VST_ENTRY_8_ABBREV; + + // VST_ENTRY: [valueid, namechar x N] + // VST_BBENTRY: [bbid, namechar x N] + unsigned Code; + if (isa(SI->getValue())) { + Code = bitc::VST_CODE_BBENTRY; + if (isChar6) + AbbrevToUse = VST_BBENTRY_6_ABBREV; + } else { + Code = bitc::VST_CODE_ENTRY; + if (isChar6) + AbbrevToUse = VST_ENTRY_6_ABBREV; + else if (is7Bit) + AbbrevToUse = VST_ENTRY_7_ABBREV; + } + + NameVals.push_back(VE.getValueID(SI->getValue())); + for (const char *P = Name.getKeyData(), + *E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P) + NameVals.push_back((unsigned char)*P); + + // Emit the finished record. + Stream.EmitRecord(Code, NameVals, AbbrevToUse); + NameVals.clear(); + } + Stream.ExitBlock(); +} + +/// WriteFunction - Emit a function body to the module stream. +static void WriteFunction(const Function &F, ValueEnumerator &VE, + BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4); + VE.incorporateFunction(F); + + SmallVector Vals; + + // Emit the number of basic blocks, so the reader can create them ahead of + // time. + Vals.push_back(VE.getBasicBlocks().size()); + Stream.EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals); + Vals.clear(); + + // If there are function-local constants, emit them now. + unsigned CstStart, CstEnd; + VE.getFunctionConstantRange(CstStart, CstEnd); + WriteConstants(CstStart, CstEnd, VE, Stream, false); + + // If there is function-local metadata, emit it now. + WriteFunctionLocalMetadata(F, VE, Stream); + + // Keep a running idea of what the instruction ID is. + unsigned InstID = CstEnd; + + bool NeedsMetadataAttachment = false; + + DebugLoc LastDL; + + // Finally, emit all the instructions, in order. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + WriteInstruction(*I, InstID, VE, Stream, Vals); + + if (!I->getType()->isVoidTy()) + ++InstID; + + // If the instruction has metadata, write a metadata attachment later. + NeedsMetadataAttachment |= I->hasMetadataOtherThanDebugLoc(); + + // If the instruction has a debug location, emit it. + DebugLoc DL = I->getDebugLoc(); + if (DL.isUnknown()) { + // nothing todo. + } else if (DL == LastDL) { + // Just repeat the same debug loc as last time. + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); + } else { + MDNode *Scope, *IA; + DL.getScopeAndInlinedAt(Scope, IA, I->getContext()); + + Vals.push_back(DL.getLine()); + Vals.push_back(DL.getCol()); + Vals.push_back(Scope ? VE.getValueID(Scope)+1 : 0); + Vals.push_back(IA ? VE.getValueID(IA)+1 : 0); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC2, Vals); + Vals.clear(); + + LastDL = DL; + } + } + + // Emit names for all the instructions etc. + WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream); + + if (NeedsMetadataAttachment) + WriteMetadataAttachment(F, VE, Stream); + VE.purgeFunction(); + Stream.ExitBlock(); +} + +/// WriteTypeSymbolTable - Emit a block for the specified type symtab. +static void WriteTypeSymbolTable(const TypeSymbolTable &TST, + const ValueEnumerator &VE, + BitstreamWriter &Stream) { + if (TST.empty()) return; + + Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3); + + // 7-bit fixed width VST_CODE_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + unsigned V7Abbrev = Stream.EmitAbbrev(Abbv); + + SmallVector NameVals; + + for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); + TI != TE; ++TI) { + // TST_ENTRY: [typeid, namechar x N] + NameVals.push_back(VE.getTypeID(TI->second)); + + const std::string &Str = TI->first; + bool is7Bit = true; + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + NameVals.push_back((unsigned char)Str[i]); + if (Str[i] & 128) + is7Bit = false; + } + + // Emit the finished record. + Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0); + NameVals.clear(); + } + + Stream.ExitBlock(); +} + +// Emit blockinfo, which defines the standard abbreviations etc. +static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { + // We only want to emit block info records for blocks that have multiple + // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. Other + // blocks can defined their abbrevs inline. + Stream.EnterBlockInfoBlock(2); + + { // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_8_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // 7-bit fixed width VST_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_7_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // 6-bit char6 VST_ENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_6_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // 6-bit char6 VST_BBENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_BBENTRY_6_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + + + { // SETTYPE abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_SETTYPE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // INTEGER abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_INTEGER_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // CE_CAST abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id + + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_CE_CAST_Abbrev) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // NULL abbrev for CONSTANTS_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL)); + if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, + Abbv) != CONSTANTS_NULL_Abbrev) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + // FIXME: This should only use space for first class types! + + { // INST_LOAD abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_LOAD_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_BINOP abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_CAST abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty + Log2_32_Ceil(VE.getTypes().size()+1))); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_CAST_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + { // INST_RET abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_RET_VOID_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_RET abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_RET_VAL_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE)); + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, + Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + + Stream.ExitBlock(); +} + + +/// WriteModule - Emit the specified module to the bitstream. +static void WriteModule(const Module *M, BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); + + // Emit the version number if it is non-zero. + if (CurVersion) { + SmallVector Vals; + Vals.push_back(CurVersion); + Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); + } + + // Analyze the module, enumerating globals, functions, etc. + ValueEnumerator VE(M); + + // Emit blockinfo, which defines the standard abbreviations etc. + WriteBlockInfo(VE, Stream); + + // Emit information about parameter attributes. + WriteAttributeTable(VE, Stream); + + // Emit information describing all of the types in the module. + WriteTypeTable(VE, Stream); + + // Emit top-level description of module, including target triple, inline asm, + // descriptors for global variables, and function prototype info. + WriteModuleInfo(M, VE, Stream); + + // Emit constants. + WriteModuleConstants(VE, Stream); + + // Emit metadata. + WriteModuleMetadata(M, VE, Stream); + + // Emit function bodies. + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) + if (!I->isDeclaration()) + WriteFunction(*I, VE, Stream); + + // Emit metadata. + WriteModuleMetadataStore(M, Stream); + + // Emit the type symbol table information. + WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream); + + // Emit names for globals/functions etc. + WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream); + + Stream.ExitBlock(); +} + +/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a +/// header and trailer to make it compatible with the system archiver. To do +/// this we emit the following header, and then emit a trailer that pads the +/// file out to be a multiple of 16 bytes. +/// +/// struct bc_header { +/// uint32_t Magic; // 0x0B17C0DE +/// uint32_t Version; // Version, currently always 0. +/// uint32_t BitcodeOffset; // Offset to traditional bitcode file. +/// uint32_t BitcodeSize; // Size of traditional bitcode file. +/// uint32_t CPUType; // CPU specifier. +/// ... potentially more later ... +/// }; +enum { + DarwinBCSizeFieldOffset = 3*4, // Offset to bitcode_size. + DarwinBCHeaderSize = 5*4 +}; + +/// isARMTriplet - Return true if the triplet looks like: +/// arm-*, thumb-*, armv[0-9]-*, thumbv[0-9]-*, armv5te-*, or armv6t2-*. +static bool isARMTriplet(const std::string &TT) { + size_t Pos = 0; + size_t Size = TT.size(); + if (Size >= 6 && + TT[0] == 't' && TT[1] == 'h' && TT[2] == 'u' && + TT[3] == 'm' && TT[4] == 'b') + Pos = 5; + else if (Size >= 4 && TT[0] == 'a' && TT[1] == 'r' && TT[2] == 'm') + Pos = 3; + else + return false; + + if (TT[Pos] == '-') + return true; + else if (TT[Pos] == 'v') { + if (Size >= Pos+4 && + TT[Pos+1] == '6' && TT[Pos+2] == 't' && TT[Pos+3] == '2') + return true; + else if (Size >= Pos+4 && + TT[Pos+1] == '5' && TT[Pos+2] == 't' && TT[Pos+3] == 'e') + return true; + } else + return false; + while (++Pos < Size && TT[Pos] != '-') { + if (!isdigit(TT[Pos])) + return false; + } + return true; +} + +static void EmitDarwinBCHeader(BitstreamWriter &Stream, + const std::string &TT) { + unsigned CPUType = ~0U; + + // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*, arm-*, thumb-*, + // armv[0-9]-*, thumbv[0-9]-*, armv5te-*, or armv6t2-*. The CPUType is a magic + // number from /usr/include/mach/machine.h. It is ok to reproduce the + // specific constants here because they are implicitly part of the Darwin ABI. + enum { + DARWIN_CPU_ARCH_ABI64 = 0x01000000, + DARWIN_CPU_TYPE_X86 = 7, + DARWIN_CPU_TYPE_ARM = 12, + DARWIN_CPU_TYPE_POWERPC = 18 + }; + + if (TT.find("x86_64-") == 0) + CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64; + else if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' && + TT[4] == '-' && TT[1] - '3' < 6) + CPUType = DARWIN_CPU_TYPE_X86; + else if (TT.find("powerpc-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC; + else if (TT.find("powerpc64-") == 0) + CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64; + else if (isARMTriplet(TT)) + CPUType = DARWIN_CPU_TYPE_ARM; + + // Traditional Bitcode starts after header. + unsigned BCOffset = DarwinBCHeaderSize; + + Stream.Emit(0x0B17C0DE, 32); + Stream.Emit(0 , 32); // Version. + Stream.Emit(BCOffset , 32); + Stream.Emit(0 , 32); // Filled in later. + Stream.Emit(CPUType , 32); +} + +/// EmitDarwinBCTrailer - Emit the darwin epilog after the bitcode file and +/// finalize the header. +static void EmitDarwinBCTrailer(BitstreamWriter &Stream, unsigned BufferSize) { + // Update the size field in the header. + Stream.BackpatchWord(DarwinBCSizeFieldOffset, BufferSize-DarwinBCHeaderSize); + + // If the file is not a multiple of 16 bytes, insert dummy padding. + while (BufferSize & 15) { + Stream.Emit(0, 8); + ++BufferSize; + } +} + + +/// WriteBitcodeToFile - Write the specified module to the specified output +/// stream. +void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out) { + std::vector Buffer; + BitstreamWriter Stream(Buffer); + + Buffer.reserve(256*1024); + + WriteBitcodeToStream( M, Stream ); + + // Write the generated bitstream to "Out". + Out.write((char*)&Buffer.front(), Buffer.size()); +} + +/// WriteBitcodeToStream - Write the specified module to the specified output +/// stream. +void llvm::WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream) { + // If this is darwin or another generic macho target, emit a file header and + // trailer if needed. + bool isMacho = + M->getTargetTriple().find("-darwin") != std::string::npos || + M->getTargetTriple().find("-macho") != std::string::npos; + if (isMacho) + EmitDarwinBCHeader(Stream, M->getTargetTriple()); + + // Emit the file header. + Stream.Emit((unsigned)'B', 8); + Stream.Emit((unsigned)'C', 8); + Stream.Emit(0x0, 4); + Stream.Emit(0xC, 4); + Stream.Emit(0xE, 4); + Stream.Emit(0xD, 4); + + // Emit the module. + WriteModule(M, Stream); + + if (isMacho) + EmitDarwinBCTrailer(Stream, Stream.getBuffer().size()); +} diff --git a/final/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/final/lib/Bitcode/Writer/BitcodeWriterPass.cpp new file mode 100644 index 00000000000..91e115cba6c --- /dev/null +++ b/final/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -0,0 +1,41 @@ +//===--- Bitcode/Writer/BitcodeWriterPass.cpp - Bitcode Writer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// BitcodeWriterPass implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + class WriteBitcodePass : public ModulePass { + raw_ostream &OS; // raw_ostream to print on + public: + static char ID; // Pass identification, replacement for typeid + explicit WriteBitcodePass(raw_ostream &o) + : ModulePass(ID), OS(o) {} + + const char *getPassName() const { return "Bitcode Writer"; } + + bool runOnModule(Module &M) { + WriteBitcodeToFile(&M, OS); + return false; + } + }; +} + +char WriteBitcodePass::ID = 0; + +/// createBitcodeWriterPass - Create and return a pass that writes the module +/// to the specified ostream. +ModulePass *llvm::createBitcodeWriterPass(raw_ostream &Str) { + return new WriteBitcodePass(Str); +} diff --git a/final/lib/Bitcode/Writer/CMakeLists.txt b/final/lib/Bitcode/Writer/CMakeLists.txt new file mode 100644 index 00000000000..f097b097c33 --- /dev/null +++ b/final/lib/Bitcode/Writer/CMakeLists.txt @@ -0,0 +1,6 @@ +add_llvm_library(LLVMBitWriter + BitWriter.cpp + BitcodeWriter.cpp + BitcodeWriterPass.cpp + ValueEnumerator.cpp + ) diff --git a/final/lib/Bitcode/Writer/Makefile b/final/lib/Bitcode/Writer/Makefile new file mode 100644 index 00000000000..7b0bd72159a --- /dev/null +++ b/final/lib/Bitcode/Writer/Makefile @@ -0,0 +1,15 @@ +##===- lib/Bitcode/Reader/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMBitWriter +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Bitcode/Writer/ValueEnumerator.cpp b/final/lib/Bitcode/Writer/ValueEnumerator.cpp new file mode 100644 index 00000000000..2f02262c36a --- /dev/null +++ b/final/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -0,0 +1,511 @@ +//===-- ValueEnumerator.cpp - Number values and types for bitcode writer --===// +// +// 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 ValueEnumerator class. +// +//===----------------------------------------------------------------------===// + +#include "ValueEnumerator.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/Instructions.h" +#include +using namespace llvm; + +static bool isSingleValueType(const std::pair &P) { + return P.first->isSingleValueType(); +} + +static bool isIntegerValue(const std::pair &V) { + return V.first->getType()->isIntegerTy(); +} + +static bool CompareByFrequency(const std::pair &P1, + const std::pair &P2) { + return P1.second > P2.second; +} + +/// ValueEnumerator - Enumerate module-level information. +ValueEnumerator::ValueEnumerator(const Module *M) { + // Enumerate the global variables. + for (Module::const_global_iterator I = M->global_begin(), + E = M->global_end(); I != E; ++I) + EnumerateValue(I); + + // Enumerate the functions. + for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { + EnumerateValue(I); + EnumerateAttributes(cast(I)->getAttributes()); + } + + // Enumerate the aliases. + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + EnumerateValue(I); + + // Remember what is the cutoff between globalvalue's and other constants. + unsigned FirstConstant = Values.size(); + + // Enumerate the global variable initializers. + for (Module::const_global_iterator I = M->global_begin(), + E = M->global_end(); I != E; ++I) + if (I->hasInitializer()) + EnumerateValue(I->getInitializer()); + + // Enumerate the aliasees. + for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + EnumerateValue(I->getAliasee()); + + // Enumerate types used by the type symbol table. + EnumerateTypeSymbolTable(M->getTypeSymbolTable()); + + // Insert constants and metadata that are named at module level into the slot + // pool so that the module symbol table can refer to them... + EnumerateValueSymbolTable(M->getValueSymbolTable()); + EnumerateNamedMetadata(M); + + SmallVector, 8> MDs; + + // Enumerate types used by function bodies and argument lists. + for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { + + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I) + EnumerateType(I->getType()); + + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ + for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); + OI != E; ++OI) { + if (MDNode *MD = dyn_cast(*OI)) + if (MD->isFunctionLocal() && MD->getFunction()) + // These will get enumerated during function-incorporation. + continue; + EnumerateOperandType(*OI); + } + EnumerateType(I->getType()); + if (const CallInst *CI = dyn_cast(I)) + EnumerateAttributes(CI->getAttributes()); + else if (const InvokeInst *II = dyn_cast(I)) + EnumerateAttributes(II->getAttributes()); + + // Enumerate metadata attached with this instruction. + MDs.clear(); + I->getAllMetadataOtherThanDebugLoc(MDs); + for (unsigned i = 0, e = MDs.size(); i != e; ++i) + EnumerateMetadata(MDs[i].second); + + if (!I->getDebugLoc().isUnknown()) { + MDNode *Scope, *IA; + I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); + if (Scope) EnumerateMetadata(Scope); + if (IA) EnumerateMetadata(IA); + } + } + } + + // Optimize constant ordering. + OptimizeConstants(FirstConstant, Values.size()); + + // Sort the type table by frequency so that most commonly used types are early + // in the table (have low bit-width). + std::stable_sort(Types.begin(), Types.end(), CompareByFrequency); + + // Partition the Type ID's so that the single-value types occur before the + // aggregate types. This allows the aggregate types to be dropped from the + // type table after parsing the global variable initializers. + std::partition(Types.begin(), Types.end(), isSingleValueType); + + // Now that we rearranged the type table, rebuild TypeMap. + for (unsigned i = 0, e = Types.size(); i != e; ++i) + TypeMap[Types[i].first] = i+1; +} + +unsigned ValueEnumerator::getInstructionID(const Instruction *Inst) const { + InstructionMapType::const_iterator I = InstructionMap.find(Inst); + assert (I != InstructionMap.end() && "Instruction is not mapped!"); + return I->second; +} + +void ValueEnumerator::setInstructionID(const Instruction *I) { + InstructionMap[I] = InstructionCount++; +} + +unsigned ValueEnumerator::getValueID(const Value *V) const { + if (isa(V) || isa(V)) { + ValueMapType::const_iterator I = MDValueMap.find(V); + assert(I != MDValueMap.end() && "Value not in slotcalculator!"); + return I->second-1; + } + + ValueMapType::const_iterator I = ValueMap.find(V); + assert(I != ValueMap.end() && "Value not in slotcalculator!"); + return I->second-1; +} + +// Optimize constant ordering. +namespace { + struct CstSortPredicate { + ValueEnumerator &VE; + explicit CstSortPredicate(ValueEnumerator &ve) : VE(ve) {} + bool operator()(const std::pair &LHS, + const std::pair &RHS) { + // Sort by plane. + if (LHS.first->getType() != RHS.first->getType()) + return VE.getTypeID(LHS.first->getType()) < + VE.getTypeID(RHS.first->getType()); + // Then by frequency. + return LHS.second > RHS.second; + } + }; +} + +/// OptimizeConstants - Reorder constant pool for denser encoding. +void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) { + if (CstStart == CstEnd || CstStart+1 == CstEnd) return; + + CstSortPredicate P(*this); + std::stable_sort(Values.begin()+CstStart, Values.begin()+CstEnd, P); + + // Ensure that integer constants are at the start of the constant pool. This + // is important so that GEP structure indices come before gep constant exprs. + std::partition(Values.begin()+CstStart, Values.begin()+CstEnd, + isIntegerValue); + + // Rebuild the modified portion of ValueMap. + for (; CstStart != CstEnd; ++CstStart) + ValueMap[Values[CstStart].first] = CstStart+1; +} + + +/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol +/// table. +void ValueEnumerator::EnumerateTypeSymbolTable(const TypeSymbolTable &TST) { + for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); + TI != TE; ++TI) + EnumerateType(TI->second); +} + +/// EnumerateValueSymbolTable - Insert all of the values in the specified symbol +/// table into the values table. +void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) { + for (ValueSymbolTable::const_iterator VI = VST.begin(), VE = VST.end(); + VI != VE; ++VI) + EnumerateValue(VI->getValue()); +} + +/// EnumerateNamedMetadata - Insert all of the values referenced by +/// named metadata in the specified module. +void ValueEnumerator::EnumerateNamedMetadata(const Module *M) { + for (Module::const_named_metadata_iterator I = M->named_metadata_begin(), + E = M->named_metadata_end(); I != E; ++I) + EnumerateNamedMDNode(I); +} + +void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) { + for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) + EnumerateMetadata(MD->getOperand(i)); +} + +/// EnumerateMDNodeOperands - Enumerate all non-function-local values +/// and types referenced by the given MDNode. +void ValueEnumerator::EnumerateMDNodeOperands(const MDNode *N) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + if (Value *V = N->getOperand(i)) { + if (isa(V) || isa(V)) + EnumerateMetadata(V); + else if (!isa(V) && !isa(V)) + EnumerateValue(V); + } else + EnumerateType(Type::getVoidTy(N->getContext())); + } +} + +void ValueEnumerator::EnumerateMetadata(const Value *MD) { + assert((isa(MD) || isa(MD)) && "Invalid metadata kind"); + + // Enumerate the type of this value. + EnumerateType(MD->getType()); + + const MDNode *N = dyn_cast(MD); + + // In the module-level pass, skip function-local nodes themselves, but + // do walk their operands. + if (N && N->isFunctionLocal() && N->getFunction()) { + EnumerateMDNodeOperands(N); + return; + } + + // Check to see if it's already in! + unsigned &MDValueID = MDValueMap[MD]; + if (MDValueID) { + // Increment use count. + MDValues[MDValueID-1].second++; + return; + } + MDValues.push_back(std::make_pair(MD, 1U)); + MDValueID = MDValues.size(); + + // Enumerate all non-function-local operands. + if (N) + EnumerateMDNodeOperands(N); +} + +/// EnumerateFunctionLocalMetadataa - Incorporate function-local metadata +/// information reachable from the given MDNode. +void ValueEnumerator::EnumerateFunctionLocalMetadata(const MDNode *N) { + assert(N->isFunctionLocal() && N->getFunction() && + "EnumerateFunctionLocalMetadata called on non-function-local mdnode!"); + + // Enumerate the type of this value. + EnumerateType(N->getType()); + + // Check to see if it's already in! + unsigned &MDValueID = MDValueMap[N]; + if (MDValueID) { + // Increment use count. + MDValues[MDValueID-1].second++; + return; + } + MDValues.push_back(std::make_pair(N, 1U)); + MDValueID = MDValues.size(); + + // To incoroporate function-local information visit all function-local + // MDNodes and all function-local values they reference. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (Value *V = N->getOperand(i)) { + if (MDNode *O = dyn_cast(V)) { + if (O->isFunctionLocal() && O->getFunction()) + EnumerateFunctionLocalMetadata(O); + } else if (isa(V) || isa(V)) + EnumerateValue(V); + } + + // Also, collect all function-local MDNodes for easy access. + FunctionLocalMDs.push_back(N); +} + +void ValueEnumerator::EnumerateValue(const Value *V) { + assert(!V->getType()->isVoidTy() && "Can't insert void values!"); + assert(!isa(V) && !isa(V) && + "EnumerateValue doesn't handle Metadata!"); + + // Check to see if it's already in! + unsigned &ValueID = ValueMap[V]; + if (ValueID) { + // Increment use count. + Values[ValueID-1].second++; + return; + } + + // Enumerate the type of this value. + EnumerateType(V->getType()); + + if (const Constant *C = dyn_cast(V)) { + if (isa(C)) { + // Initializers for globals are handled explicitly elsewhere. + } else if (isa(C) && cast(C)->isString()) { + // Do not enumerate the initializers for an array of simple characters. + // The initializers just polute the value table, and we emit the strings + // specially. + } else if (C->getNumOperands()) { + // If a constant has operands, enumerate them. This makes sure that if a + // constant has uses (for example an array of const ints), that they are + // inserted also. + + // We prefer to enumerate them with values before we enumerate the user + // itself. This makes it more likely that we can avoid forward references + // in the reader. We know that there can be no cycles in the constants + // graph that don't go through a global variable. + for (User::const_op_iterator I = C->op_begin(), E = C->op_end(); + I != E; ++I) + if (!isa(*I)) // Don't enumerate BB operand to BlockAddress. + EnumerateValue(*I); + + // Finally, add the value. Doing this could make the ValueID reference be + // dangling, don't reuse it. + Values.push_back(std::make_pair(V, 1U)); + ValueMap[V] = Values.size(); + return; + } + } + + // Add the value. + Values.push_back(std::make_pair(V, 1U)); + ValueID = Values.size(); +} + + +void ValueEnumerator::EnumerateType(const Type *Ty) { + unsigned &TypeID = TypeMap[Ty]; + + if (TypeID) { + // If we've already seen this type, just increase its occurrence count. + Types[TypeID-1].second++; + return; + } + + // First time we saw this type, add it. + Types.push_back(std::make_pair(Ty, 1U)); + TypeID = Types.size(); + + // Enumerate subtypes. + for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); + I != E; ++I) + EnumerateType(*I); +} + +// Enumerate the types for the specified value. If the value is a constant, +// walk through it, enumerating the types of the constant. +void ValueEnumerator::EnumerateOperandType(const Value *V) { + EnumerateType(V->getType()); + + if (const Constant *C = dyn_cast(V)) { + // If this constant is already enumerated, ignore it, we know its type must + // be enumerated. + if (ValueMap.count(V)) return; + + // This constant may have operands, make sure to enumerate the types in + // them. + for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { + const User *Op = C->getOperand(i); + + // Don't enumerate basic blocks here, this happens as operands to + // blockaddress. + if (isa(Op)) continue; + + EnumerateOperandType(Op); + } + + if (const MDNode *N = dyn_cast(V)) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (Value *Elem = N->getOperand(i)) + EnumerateOperandType(Elem); + } + } else if (isa(V) || isa(V)) + EnumerateMetadata(V); +} + +void ValueEnumerator::EnumerateAttributes(const AttrListPtr &PAL) { + if (PAL.isEmpty()) return; // null is always 0. + // Do a lookup. + unsigned &Entry = AttributeMap[PAL.getRawPointer()]; + if (Entry == 0) { + // Never saw this before, add it. + Attributes.push_back(PAL); + Entry = Attributes.size(); + } +} + + +void ValueEnumerator::incorporateFunction(const Function &F) { + InstructionCount = 0; + NumModuleValues = Values.size(); + NumModuleMDValues = MDValues.size(); + + // Adding function arguments to the value table. + for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); + I != E; ++I) + EnumerateValue(I); + + FirstFuncConstantID = Values.size(); + + // Add all function-level constants to the value table. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) + for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); + OI != E; ++OI) { + if ((isa(*OI) && !isa(*OI)) || + isa(*OI)) + EnumerateValue(*OI); + } + BasicBlocks.push_back(BB); + ValueMap[BB] = BasicBlocks.size(); + } + + // Optimize the constant layout. + OptimizeConstants(FirstFuncConstantID, Values.size()); + + // Add the function's parameter attributes so they are available for use in + // the function's instruction. + EnumerateAttributes(F.getAttributes()); + + FirstInstID = Values.size(); + + SmallVector FnLocalMDVector; + // Add all of the instructions. + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) { + for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); + OI != E; ++OI) { + if (MDNode *MD = dyn_cast(*OI)) + if (MD->isFunctionLocal() && MD->getFunction()) + // Enumerate metadata after the instructions they might refer to. + FnLocalMDVector.push_back(MD); + } + + SmallVector, 8> MDs; + I->getAllMetadataOtherThanDebugLoc(MDs); + for (unsigned i = 0, e = MDs.size(); i != e; ++i) { + MDNode *N = MDs[i].second; + if (N->isFunctionLocal() && N->getFunction()) + FnLocalMDVector.push_back(N); + } + + if (!I->getType()->isVoidTy()) + EnumerateValue(I); + } + } + + // Add all of the function-local metadata. + for (unsigned i = 0, e = FnLocalMDVector.size(); i != e; ++i) + EnumerateFunctionLocalMetadata(FnLocalMDVector[i]); +} + +void ValueEnumerator::purgeFunction() { + /// Remove purged values from the ValueMap. + for (unsigned i = NumModuleValues, e = Values.size(); i != e; ++i) + ValueMap.erase(Values[i].first); + for (unsigned i = NumModuleMDValues, e = MDValues.size(); i != e; ++i) + MDValueMap.erase(MDValues[i].first); + for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i) + ValueMap.erase(BasicBlocks[i]); + + Values.resize(NumModuleValues); + MDValues.resize(NumModuleMDValues); + BasicBlocks.clear(); + FunctionLocalMDs.clear(); +} + +static void IncorporateFunctionInfoGlobalBBIDs(const Function *F, + DenseMap &IDMap) { + unsigned Counter = 0; + for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + IDMap[BB] = ++Counter; +} + +/// getGlobalBasicBlockID - This returns the function-specific ID for the +/// specified basic block. This is relatively expensive information, so it +/// should only be used by rare constructs such as address-of-label. +unsigned ValueEnumerator::getGlobalBasicBlockID(const BasicBlock *BB) const { + unsigned &Idx = GlobalBasicBlockIDs[BB]; + if (Idx != 0) + return Idx-1; + + IncorporateFunctionInfoGlobalBBIDs(BB->getParent(), GlobalBasicBlockIDs); + return getGlobalBasicBlockID(BB); +} + diff --git a/final/lib/Bitcode/Writer/ValueEnumerator.h b/final/lib/Bitcode/Writer/ValueEnumerator.h new file mode 100644 index 00000000000..cd1d2371b70 --- /dev/null +++ b/final/lib/Bitcode/Writer/ValueEnumerator.h @@ -0,0 +1,156 @@ +//===-- Bitcode/Writer/ValueEnumerator.h - Number values --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class gives values and types Unique ID's. +// +//===----------------------------------------------------------------------===// + +#ifndef VALUE_ENUMERATOR_H +#define VALUE_ENUMERATOR_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Attributes.h" +#include + +namespace llvm { + +class Type; +class Value; +class Instruction; +class BasicBlock; +class Function; +class Module; +class MDNode; +class NamedMDNode; +class AttrListPtr; +class TypeSymbolTable; +class ValueSymbolTable; +class MDSymbolTable; + +class ValueEnumerator { +public: + // For each type, we remember its Type* and occurrence frequency. + typedef std::vector > TypeList; + + // For each value, we remember its Value* and occurrence frequency. + typedef std::vector > ValueList; +private: + typedef DenseMap TypeMapType; + TypeMapType TypeMap; + TypeList Types; + + typedef DenseMap ValueMapType; + ValueMapType ValueMap; + ValueList Values; + ValueList MDValues; + SmallVector FunctionLocalMDs; + ValueMapType MDValueMap; + + typedef DenseMap AttributeMapType; + AttributeMapType AttributeMap; + std::vector Attributes; + + /// GlobalBasicBlockIDs - This map memoizes the basic block ID's referenced by + /// the "getGlobalBasicBlockID" method. + mutable DenseMap GlobalBasicBlockIDs; + + typedef DenseMap InstructionMapType; + InstructionMapType InstructionMap; + unsigned InstructionCount; + + /// BasicBlocks - This contains all the basic blocks for the currently + /// incorporated function. Their reverse mapping is stored in ValueMap. + std::vector BasicBlocks; + + /// When a function is incorporated, this is the size of the Values list + /// before incorporation. + unsigned NumModuleValues; + + /// When a function is incorporated, this is the size of the MDValues list + /// before incorporation. + unsigned NumModuleMDValues; + + unsigned FirstFuncConstantID; + unsigned FirstInstID; + + ValueEnumerator(const ValueEnumerator &); // DO NOT IMPLEMENT + void operator=(const ValueEnumerator &); // DO NOT IMPLEMENT +public: + ValueEnumerator(const Module *M); + + unsigned getValueID(const Value *V) const; + + unsigned getTypeID(const Type *T) const { + TypeMapType::const_iterator I = TypeMap.find(T); + assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); + return I->second-1; + } + + unsigned getInstructionID(const Instruction *I) const; + void setInstructionID(const Instruction *I); + + unsigned getAttributeID(const AttrListPtr &PAL) const { + if (PAL.isEmpty()) return 0; // Null maps to zero. + AttributeMapType::const_iterator I = AttributeMap.find(PAL.getRawPointer()); + assert(I != AttributeMap.end() && "Attribute not in ValueEnumerator!"); + return I->second; + } + + /// getFunctionConstantRange - Return the range of values that corresponds to + /// function-local constants. + void getFunctionConstantRange(unsigned &Start, unsigned &End) const { + Start = FirstFuncConstantID; + End = FirstInstID; + } + + const ValueList &getValues() const { return Values; } + const ValueList &getMDValues() const { return MDValues; } + const SmallVector &getFunctionLocalMDValues() const { + return FunctionLocalMDs; + } + const TypeList &getTypes() const { return Types; } + const std::vector &getBasicBlocks() const { + return BasicBlocks; + } + const std::vector &getAttributes() const { + return Attributes; + } + + /// getGlobalBasicBlockID - This returns the function-specific ID for the + /// specified basic block. This is relatively expensive information, so it + /// should only be used by rare constructs such as address-of-label. + unsigned getGlobalBasicBlockID(const BasicBlock *BB) const; + + /// incorporateFunction/purgeFunction - If you'd like to deal with a function, + /// use these two methods to get its data into the ValueEnumerator! + /// + void incorporateFunction(const Function &F); + void purgeFunction(); + +private: + void OptimizeConstants(unsigned CstStart, unsigned CstEnd); + + void EnumerateMDNodeOperands(const MDNode *N); + void EnumerateMetadata(const Value *MD); + void EnumerateFunctionLocalMetadata(const MDNode *N); + void EnumerateNamedMDNode(const NamedMDNode *NMD); + void EnumerateValue(const Value *V); + void EnumerateType(const Type *T); + void EnumerateOperandType(const Value *V); + void EnumerateAttributes(const AttrListPtr &PAL); + + void EnumerateTypeSymbolTable(const TypeSymbolTable &ST); + void EnumerateValueSymbolTable(const ValueSymbolTable &ST); + void EnumerateNamedMetadata(const Module *M); +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/CMakeLists.txt b/final/lib/CMakeLists.txt new file mode 100644 index 00000000000..e2838c373a3 --- /dev/null +++ b/final/lib/CMakeLists.txt @@ -0,0 +1,14 @@ +# `Support' library is added on the top-level CMakeLists.txt + +add_subdirectory(VMCore) +add_subdirectory(CodeGen) +add_subdirectory(Bitcode) +add_subdirectory(Transforms) +add_subdirectory(Linker) +add_subdirectory(Analysis) +add_subdirectory(MC) +add_subdirectory(Object) +add_subdirectory(ExecutionEngine) +add_subdirectory(Target) +add_subdirectory(AsmParser) +add_subdirectory(Archive) diff --git a/final/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/final/lib/CodeGen/AggressiveAntiDepBreaker.cpp new file mode 100644 index 00000000000..b520d8fcedc --- /dev/null +++ b/final/lib/CodeGen/AggressiveAntiDepBreaker.cpp @@ -0,0 +1,963 @@ +//===----- AggressiveAntiDepBreaker.cpp - Anti-dep breaker ----------------===// +// +// 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 AggressiveAntiDepBreaker class, which +// implements register anti-dependence breaking during post-RA +// scheduling. It attempts to break all anti-dependencies within a +// block. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "AggressiveAntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// If DebugDiv > 0 then only break antidep with (ID % DebugDiv) == DebugMod +static cl::opt +DebugDiv("agg-antidep-debugdiv", + cl::desc("Debug control for aggressive anti-dep breaker"), + cl::init(0), cl::Hidden); +static cl::opt +DebugMod("agg-antidep-debugmod", + cl::desc("Debug control for aggressive anti-dep breaker"), + cl::init(0), cl::Hidden); + +AggressiveAntiDepState::AggressiveAntiDepState(const unsigned TargetRegs, + MachineBasicBlock *BB) : + NumTargetRegs(TargetRegs), GroupNodes(TargetRegs, 0), + GroupNodeIndices(TargetRegs, 0), + KillIndices(TargetRegs, 0), + DefIndices(TargetRegs, 0) +{ + const unsigned BBSize = BB->size(); + for (unsigned i = 0; i < NumTargetRegs; ++i) { + // Initialize all registers to be in their own group. Initially we + // assign the register to the same-indexed GroupNode. + GroupNodeIndices[i] = i; + // Initialize the indices to indicate that no registers are live. + KillIndices[i] = ~0u; + DefIndices[i] = BBSize; + } +} + +unsigned AggressiveAntiDepState::GetGroup(unsigned Reg) { + unsigned Node = GroupNodeIndices[Reg]; + while (GroupNodes[Node] != Node) + Node = GroupNodes[Node]; + + return Node; +} + +void AggressiveAntiDepState::GetGroupRegs( + unsigned Group, + std::vector &Regs, + std::multimap *RegRefs) +{ + for (unsigned Reg = 0; Reg != NumTargetRegs; ++Reg) { + if ((GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0)) + Regs.push_back(Reg); + } +} + +unsigned AggressiveAntiDepState::UnionGroups(unsigned Reg1, unsigned Reg2) +{ + assert(GroupNodes[0] == 0 && "GroupNode 0 not parent!"); + assert(GroupNodeIndices[0] == 0 && "Reg 0 not in Group 0!"); + + // find group for each register + unsigned Group1 = GetGroup(Reg1); + unsigned Group2 = GetGroup(Reg2); + + // if either group is 0, then that must become the parent + unsigned Parent = (Group1 == 0) ? Group1 : Group2; + unsigned Other = (Parent == Group1) ? Group2 : Group1; + GroupNodes.at(Other) = Parent; + return Parent; +} + +unsigned AggressiveAntiDepState::LeaveGroup(unsigned Reg) +{ + // Create a new GroupNode for Reg. Reg's existing GroupNode must + // stay as is because there could be other GroupNodes referring to + // it. + unsigned idx = GroupNodes.size(); + GroupNodes.push_back(idx); + GroupNodeIndices[Reg] = idx; + return idx; +} + +bool AggressiveAntiDepState::IsLive(unsigned Reg) +{ + // KillIndex must be defined and DefIndex not defined for a register + // to be live. + return((KillIndices[Reg] != ~0u) && (DefIndices[Reg] == ~0u)); +} + + + +AggressiveAntiDepBreaker:: +AggressiveAntiDepBreaker(MachineFunction& MFi, + TargetSubtarget::RegClassVector& CriticalPathRCs) : + AntiDepBreaker(), MF(MFi), + MRI(MF.getRegInfo()), + TII(MF.getTarget().getInstrInfo()), + TRI(MF.getTarget().getRegisterInfo()), + AllocatableSet(TRI->getAllocatableSet(MF)), + State(NULL) { + /* Collect a bitset of all registers that are only broken if they + are on the critical path. */ + for (unsigned i = 0, e = CriticalPathRCs.size(); i < e; ++i) { + BitVector CPSet = TRI->getAllocatableSet(MF, CriticalPathRCs[i]); + if (CriticalPathSet.none()) + CriticalPathSet = CPSet; + else + CriticalPathSet |= CPSet; + } + + DEBUG(dbgs() << "AntiDep Critical-Path Registers:"); + DEBUG(for (int r = CriticalPathSet.find_first(); r != -1; + r = CriticalPathSet.find_next(r)) + dbgs() << " " << TRI->getName(r)); + DEBUG(dbgs() << '\n'); +} + +AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { + delete State; +} + +void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { + assert(State == NULL); + State = new AggressiveAntiDepState(TRI->getNumRegs(), BB); + + bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); + std::vector &KillIndices = State->GetKillIndices(); + std::vector &DefIndices = State->GetDefIndices(); + + // Determine the live-out physregs for this block. + if (IsReturnBlock) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + for (const unsigned *Alias = TRI->getOverlaps(*I); + unsigned Reg = *Alias; ++Alias) { + State->UnionGroups(Reg, 0); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + } + } + } + + // In a non-return block, examine the live-in regs of all successors. + // Note a return block can have successors if the return instruction is + // predicated. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + for (const unsigned *Alias = TRI->getOverlaps(*I); + unsigned Reg = *Alias; ++Alias) { + State->UnionGroups(Reg, 0); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + } + } + + // Mark live-out callee-saved registers. In a return block this is + // all callee-saved registers. In non-return this is any + // callee-saved register that is not saved in the prolog. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + BitVector Pristine = MFI->getPristineRegs(BB); + for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { + unsigned Reg = *I; + if (!IsReturnBlock && !Pristine.test(Reg)) continue; + for (const unsigned *Alias = TRI->getOverlaps(Reg); + unsigned AliasReg = *Alias; ++Alias) { + State->UnionGroups(AliasReg, 0); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } +} + +void AggressiveAntiDepBreaker::FinishBlock() { + delete State; + State = NULL; +} + +void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) { + assert(Count < InsertPosIndex && "Instruction index out of expected range!"); + + std::set PassthruRegs; + GetPassthruRegs(MI, PassthruRegs); + PrescanInstruction(MI, Count, PassthruRegs); + ScanInstruction(MI, Count); + + DEBUG(dbgs() << "Observe: "); + DEBUG(MI->dump()); + DEBUG(dbgs() << "\tRegs:"); + + std::vector &DefIndices = State->GetDefIndices(); + for (unsigned Reg = 0; Reg != TRI->getNumRegs(); ++Reg) { + // If Reg is current live, then mark that it can't be renamed as + // we don't know the extent of its live-range anymore (now that it + // has been scheduled). If it is not live but was defined in the + // previous schedule region, then set its def index to the most + // conservative location (i.e. the beginning of the previous + // schedule region). + if (State->IsLive(Reg)) { + DEBUG(if (State->GetGroup(Reg) != 0) + dbgs() << " " << TRI->getName(Reg) << "=g" << + State->GetGroup(Reg) << "->g0(region live-out)"); + State->UnionGroups(Reg, 0); + } else if ((DefIndices[Reg] < InsertPosIndex) + && (DefIndices[Reg] >= Count)) { + DefIndices[Reg] = Count; + } + } + DEBUG(dbgs() << '\n'); +} + +bool AggressiveAntiDepBreaker::IsImplicitDefUse(MachineInstr *MI, + MachineOperand& MO) +{ + if (!MO.isReg() || !MO.isImplicit()) + return false; + + unsigned Reg = MO.getReg(); + if (Reg == 0) + return false; + + MachineOperand *Op = NULL; + if (MO.isDef()) + Op = MI->findRegisterUseOperand(Reg, true); + else + Op = MI->findRegisterDefOperand(Reg); + + return((Op != NULL) && Op->isImplicit()); +} + +void AggressiveAntiDepBreaker::GetPassthruRegs(MachineInstr *MI, + std::set& PassthruRegs) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + if ((MO.isDef() && MI->isRegTiedToUseOperand(i)) || + IsImplicitDefUse(MI, MO)) { + const unsigned Reg = MO.getReg(); + PassthruRegs.insert(Reg); + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + PassthruRegs.insert(*Subreg); + } + } + } +} + +/// AntiDepEdges - Return in Edges the anti- and output- dependencies +/// in SU that we want to consider for breaking. +static void AntiDepEdges(const SUnit *SU, std::vector& Edges) { + SmallSet RegSet; + for (SUnit::const_pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + if ((P->getKind() == SDep::Anti) || (P->getKind() == SDep::Output)) { + unsigned Reg = P->getReg(); + if (RegSet.count(Reg) == 0) { + Edges.push_back(&*P); + RegSet.insert(Reg); + } + } + } +} + +/// CriticalPathStep - Return the next SUnit after SU on the bottom-up +/// critical path. +static const SUnit *CriticalPathStep(const SUnit *SU) { + const SDep *Next = 0; + unsigned NextDepth = 0; + // Find the predecessor edge with the greatest depth. + if (SU != 0) { + for (SUnit::const_pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + const SUnit *PredSU = P->getSUnit(); + unsigned PredLatency = P->getLatency(); + unsigned PredTotalLatency = PredSU->getDepth() + PredLatency; + // In the case of a latency tie, prefer an anti-dependency edge over + // other types of edges. + if (NextDepth < PredTotalLatency || + (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) { + NextDepth = PredTotalLatency; + Next = &*P; + } + } + } + + return (Next) ? Next->getSUnit() : 0; +} + +void AggressiveAntiDepBreaker::HandleLastUse(unsigned Reg, unsigned KillIdx, + const char *tag, + const char *header, + const char *footer) { + std::vector &KillIndices = State->GetKillIndices(); + std::vector &DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + if (!State->IsLive(Reg)) { + KillIndices[Reg] = KillIdx; + DefIndices[Reg] = ~0u; + RegRefs.erase(Reg); + State->LeaveGroup(Reg); + DEBUG(if (header != NULL) { + dbgs() << header << TRI->getName(Reg); header = NULL; }); + DEBUG(dbgs() << "->g" << State->GetGroup(Reg) << tag); + } + // Repeat for subregisters. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + unsigned SubregReg = *Subreg; + if (!State->IsLive(SubregReg)) { + KillIndices[SubregReg] = KillIdx; + DefIndices[SubregReg] = ~0u; + RegRefs.erase(SubregReg); + State->LeaveGroup(SubregReg); + DEBUG(if (header != NULL) { + dbgs() << header << TRI->getName(Reg); header = NULL; }); + DEBUG(dbgs() << " " << TRI->getName(SubregReg) << "->g" << + State->GetGroup(SubregReg) << tag); + } + } + + DEBUG(if ((header == NULL) && (footer != NULL)) dbgs() << footer); +} + +void AggressiveAntiDepBreaker::PrescanInstruction(MachineInstr *MI, + unsigned Count, + std::set& PassthruRegs) { + std::vector &DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // Handle dead defs by simulating a last-use of the register just + // after the def. A dead def can occur because the def is truely + // dead, or because only a subregister is live at the def. If we + // don't do this the dead def will be incorrectly merged into the + // previous def. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + HandleLastUse(Reg, Count + 1, "", "\tDead Def: ", "\n"); + } + + DEBUG(dbgs() << "\tDef Groups:"); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + DEBUG(dbgs() << " " << TRI->getName(Reg) << "=g" << State->GetGroup(Reg)); + + // If MI's defs have a special allocation requirement, don't allow + // any def registers to be changed. Also assume all registers + // defined in a call must not be changed (ABI). + if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq() || + TII->isPredicated(MI)) { + DEBUG(if (State->GetGroup(Reg) != 0) dbgs() << "->g0(alloc-req)"); + State->UnionGroups(Reg, 0); + } + + // Any aliased that are live at this point are completely or + // partially defined here, so group those aliases with Reg. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (State->IsLive(AliasReg)) { + State->UnionGroups(Reg, AliasReg); + DEBUG(dbgs() << "->g" << State->GetGroup(Reg) << "(via " << + TRI->getName(AliasReg) << ")"); + } + } + + // Note register reference... + const TargetRegisterClass *RC = NULL; + if (i < MI->getDesc().getNumOperands()) + RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; + RegRefs.insert(std::make_pair(Reg, RR)); + } + + DEBUG(dbgs() << '\n'); + + // Scan the register defs for this instruction and update + // live-ranges. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + // Ignore KILLs and passthru registers for liveness... + if (MI->isKill() || (PassthruRegs.count(Reg) != 0)) + continue; + + // Update def for Reg and aliases. + for (const unsigned *Alias = TRI->getOverlaps(Reg); + unsigned AliasReg = *Alias; ++Alias) + DefIndices[AliasReg] = Count; + } +} + +void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr *MI, + unsigned Count) { + DEBUG(dbgs() << "\tUse Groups:"); + std::multimap& + RegRefs = State->GetRegRefs(); + + // If MI's uses have special allocation requirement, don't allow + // any use registers to be changed. Also assume all registers + // used in a call must not be changed (ABI). + // FIXME: The issue with predicated instruction is more complex. We are being + // conservatively here because the kill markers cannot be trusted after + // if-conversion: + // %R6 = LDR %SP, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14] + // ... + // STR %R0, %R6, %reg0, 0, pred:0, pred:%CPSR; mem:ST4[%395] + // %R6 = LDR %SP, %reg0, 100, pred:0, pred:%CPSR; mem:LD4[FixedStack12] + // STR %R0, %R6, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8) + // + // The first R6 kill is not really a kill since it's killed by a predicated + // instruction which may not be executed. The second R6 def may or may not + // re-define R6 so it's not safe to change it since the last R6 use cannot be + // changed. + bool Special = MI->getDesc().isCall() || + MI->getDesc().hasExtraSrcRegAllocReq() || + TII->isPredicated(MI); + + // Scan the register uses for this instruction and update + // live-ranges, groups and RegRefs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + DEBUG(dbgs() << " " << TRI->getName(Reg) << "=g" << + State->GetGroup(Reg)); + + // It wasn't previously live but now it is, this is a kill. Forget + // the previous live-range information and start a new live-range + // for the register. + HandleLastUse(Reg, Count, "(last-use)"); + + if (Special) { + DEBUG(if (State->GetGroup(Reg) != 0) dbgs() << "->g0(alloc-req)"); + State->UnionGroups(Reg, 0); + } + + // Note register reference... + const TargetRegisterClass *RC = NULL; + if (i < MI->getDesc().getNumOperands()) + RC = MI->getDesc().OpInfo[i].getRegClass(TRI); + AggressiveAntiDepState::RegisterReference RR = { &MO, RC }; + RegRefs.insert(std::make_pair(Reg, RR)); + } + + DEBUG(dbgs() << '\n'); + + // Form a group of all defs and uses of a KILL instruction to ensure + // that all registers are renamed as a group. + if (MI->isKill()) { + DEBUG(dbgs() << "\tKill Group:"); + + unsigned FirstReg = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + if (FirstReg != 0) { + DEBUG(dbgs() << "=" << TRI->getName(Reg)); + State->UnionGroups(FirstReg, Reg); + } else { + DEBUG(dbgs() << " " << TRI->getName(Reg)); + FirstReg = Reg; + } + } + + DEBUG(dbgs() << "->g" << State->GetGroup(FirstReg) << '\n'); + } +} + +BitVector AggressiveAntiDepBreaker::GetRenameRegisters(unsigned Reg) { + BitVector BV(TRI->getNumRegs(), false); + bool first = true; + + // Check all references that need rewriting for Reg. For each, use + // the corresponding register class to narrow the set of registers + // that are appropriate for renaming. + std::pair::iterator, + std::multimap::iterator> + Range = State->GetRegRefs().equal_range(Reg); + for (std::multimap::iterator Q = Range.first, + QE = Range.second; Q != QE; ++Q) { + const TargetRegisterClass *RC = Q->second.RC; + if (RC == NULL) continue; + + BitVector RCBV = TRI->getAllocatableSet(MF, RC); + if (first) { + BV |= RCBV; + first = false; + } else { + BV &= RCBV; + } + + DEBUG(dbgs() << " " << RC->getName()); + } + + return BV; +} + +bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters( + unsigned AntiDepGroupIndex, + RenameOrderType& RenameOrder, + std::map &RenameMap) { + std::vector &KillIndices = State->GetKillIndices(); + std::vector &DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // Collect all referenced registers in the same group as + // AntiDepReg. These all need to be renamed together if we are to + // break the anti-dependence. + std::vector Regs; + State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs); + assert(Regs.size() > 0 && "Empty register group!"); + if (Regs.size() == 0) + return false; + + // Find the "superest" register in the group. At the same time, + // collect the BitVector of registers that can be used to rename + // each register. + DEBUG(dbgs() << "\tRename Candidates for Group g" << AntiDepGroupIndex + << ":\n"); + std::map RenameRegisterMap; + unsigned SuperReg = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + if ((SuperReg == 0) || TRI->isSuperRegister(SuperReg, Reg)) + SuperReg = Reg; + + // If Reg has any references, then collect possible rename regs + if (RegRefs.count(Reg) > 0) { + DEBUG(dbgs() << "\t\t" << TRI->getName(Reg) << ":"); + + BitVector BV = GetRenameRegisters(Reg); + RenameRegisterMap.insert(std::pair(Reg, BV)); + + DEBUG(dbgs() << " ::"); + DEBUG(for (int r = BV.find_first(); r != -1; r = BV.find_next(r)) + dbgs() << " " << TRI->getName(r)); + DEBUG(dbgs() << "\n"); + } + } + + // All group registers should be a subreg of SuperReg. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + if (Reg == SuperReg) continue; + bool IsSub = TRI->isSubRegister(SuperReg, Reg); + assert(IsSub && "Expecting group subregister"); + if (!IsSub) + return false; + } + +#ifndef NDEBUG + // If DebugDiv > 0 then only rename (renamecnt % DebugDiv) == DebugMod + if (DebugDiv > 0) { + static int renamecnt = 0; + if (renamecnt++ % DebugDiv != DebugMod) + return false; + + dbgs() << "*** Performing rename " << TRI->getName(SuperReg) << + " for debug ***\n"; + } +#endif + + // Check each possible rename register for SuperReg in round-robin + // order. If that register is available, and the corresponding + // registers are available for the other group subregisters, then we + // can use those registers to rename. + + // FIXME: Using getMinimalPhysRegClass is very conservative. We should + // check every use of the register and find the largest register class + // that can be used in all of them. + const TargetRegisterClass *SuperRC = + TRI->getMinimalPhysRegClass(SuperReg, MVT::Other); + + const TargetRegisterClass::iterator RB = SuperRC->allocation_order_begin(MF); + const TargetRegisterClass::iterator RE = SuperRC->allocation_order_end(MF); + if (RB == RE) { + DEBUG(dbgs() << "\tEmpty Super Regclass!!\n"); + return false; + } + + DEBUG(dbgs() << "\tFind Registers:"); + + if (RenameOrder.count(SuperRC) == 0) + RenameOrder.insert(RenameOrderType::value_type(SuperRC, RE)); + + const TargetRegisterClass::iterator OrigR = RenameOrder[SuperRC]; + const TargetRegisterClass::iterator EndR = ((OrigR == RE) ? RB : OrigR); + TargetRegisterClass::iterator R = OrigR; + do { + if (R == RB) R = RE; + --R; + const unsigned NewSuperReg = *R; + // Don't consider non-allocatable registers + if (!AllocatableSet.test(NewSuperReg)) continue; + // Don't replace a register with itself. + if (NewSuperReg == SuperReg) continue; + + DEBUG(dbgs() << " [" << TRI->getName(NewSuperReg) << ':'); + RenameMap.clear(); + + // For each referenced group register (which must be a SuperReg or + // a subregister of SuperReg), find the corresponding subregister + // of NewSuperReg and make sure it is free to be renamed. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + unsigned Reg = Regs[i]; + unsigned NewReg = 0; + if (Reg == SuperReg) { + NewReg = NewSuperReg; + } else { + unsigned NewSubRegIdx = TRI->getSubRegIndex(SuperReg, Reg); + if (NewSubRegIdx != 0) + NewReg = TRI->getSubReg(NewSuperReg, NewSubRegIdx); + } + + DEBUG(dbgs() << " " << TRI->getName(NewReg)); + + // Check if Reg can be renamed to NewReg. + BitVector BV = RenameRegisterMap[Reg]; + if (!BV.test(NewReg)) { + DEBUG(dbgs() << "(no rename)"); + goto next_super_reg; + } + + // If NewReg is dead and NewReg's most recent def is not before + // Regs's kill, it's safe to replace Reg with NewReg. We + // must also check all aliases of NewReg, because we can't define a + // register when any sub or super is already live. + if (State->IsLive(NewReg) || (KillIndices[Reg] > DefIndices[NewReg])) { + DEBUG(dbgs() << "(live)"); + goto next_super_reg; + } else { + bool found = false; + for (const unsigned *Alias = TRI->getAliasSet(NewReg); + *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (State->IsLive(AliasReg) || + (KillIndices[Reg] > DefIndices[AliasReg])) { + DEBUG(dbgs() << "(alias " << TRI->getName(AliasReg) << " live)"); + found = true; + break; + } + } + if (found) + goto next_super_reg; + } + + // Record that 'Reg' can be renamed to 'NewReg'. + RenameMap.insert(std::pair(Reg, NewReg)); + } + + // If we fall-out here, then every register in the group can be + // renamed, as recorded in RenameMap. + RenameOrder.erase(SuperRC); + RenameOrder.insert(RenameOrderType::value_type(SuperRC, R)); + DEBUG(dbgs() << "]\n"); + return true; + + next_super_reg: + DEBUG(dbgs() << ']'); + } while (R != EndR); + + DEBUG(dbgs() << '\n'); + + // No registers are free and available! + return false; +} + +/// BreakAntiDependencies - Identifiy anti-dependencies within the +/// ScheduleDAG and break them by renaming registers. +/// +unsigned AggressiveAntiDepBreaker::BreakAntiDependencies( + const std::vector& SUnits, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned InsertPosIndex) { + std::vector &KillIndices = State->GetKillIndices(); + std::vector &DefIndices = State->GetDefIndices(); + std::multimap& + RegRefs = State->GetRegRefs(); + + // The code below assumes that there is at least one instruction, + // so just duck out immediately if the block is empty. + if (SUnits.empty()) return 0; + + // For each regclass the next register to use for renaming. + RenameOrderType RenameOrder; + + // ...need a map from MI to SUnit. + std::map MISUnitMap; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + const SUnit *SU = &SUnits[i]; + MISUnitMap.insert(std::pair(SU->getInstr(), + SU)); + } + + // Track progress along the critical path through the SUnit graph as + // we walk the instructions. This is needed for regclasses that only + // break critical-path anti-dependencies. + const SUnit *CriticalPathSU = 0; + MachineInstr *CriticalPathMI = 0; + if (CriticalPathSet.any()) { + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + const SUnit *SU = &SUnits[i]; + if (!CriticalPathSU || + ((SU->getDepth() + SU->Latency) > + (CriticalPathSU->getDepth() + CriticalPathSU->Latency))) { + CriticalPathSU = SU; + } + } + + CriticalPathMI = CriticalPathSU->getInstr(); + } + +#ifndef NDEBUG + DEBUG(dbgs() << "\n===== Aggressive anti-dependency breaking\n"); + DEBUG(dbgs() << "Available regs:"); + for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { + if (!State->IsLive(Reg)) + DEBUG(dbgs() << " " << TRI->getName(Reg)); + } + DEBUG(dbgs() << '\n'); +#endif + + // Attempt to break anti-dependence edges. Walk the instructions + // from the bottom up, tracking information about liveness as we go + // to help determine which registers are available. + unsigned Broken = 0; + unsigned Count = InsertPosIndex - 1; + for (MachineBasicBlock::iterator I = End, E = Begin; + I != E; --Count) { + MachineInstr *MI = --I; + + DEBUG(dbgs() << "Anti: "); + DEBUG(MI->dump()); + + std::set PassthruRegs; + GetPassthruRegs(MI, PassthruRegs); + + // Process the defs in MI... + PrescanInstruction(MI, Count, PassthruRegs); + + // The dependence edges that represent anti- and output- + // dependencies that are candidates for breaking. + std::vector Edges; + const SUnit *PathSU = MISUnitMap[MI]; + AntiDepEdges(PathSU, Edges); + + // If MI is not on the critical path, then we don't rename + // registers in the CriticalPathSet. + BitVector *ExcludeRegs = NULL; + if (MI == CriticalPathMI) { + CriticalPathSU = CriticalPathStep(CriticalPathSU); + CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->getInstr() : 0; + } else { + ExcludeRegs = &CriticalPathSet; + } + + // Ignore KILL instructions (they form a group in ScanInstruction + // but don't cause any anti-dependence breaking themselves) + if (!MI->isKill()) { + // Attempt to break each anti-dependency... + for (unsigned i = 0, e = Edges.size(); i != e; ++i) { + const SDep *Edge = Edges[i]; + SUnit *NextSU = Edge->getSUnit(); + + if ((Edge->getKind() != SDep::Anti) && + (Edge->getKind() != SDep::Output)) continue; + + unsigned AntiDepReg = Edge->getReg(); + DEBUG(dbgs() << "\tAntidep reg: " << TRI->getName(AntiDepReg)); + assert(AntiDepReg != 0 && "Anti-dependence on reg0?"); + + if (!AllocatableSet.test(AntiDepReg)) { + // Don't break anti-dependencies on non-allocatable registers. + DEBUG(dbgs() << " (non-allocatable)\n"); + continue; + } else if ((ExcludeRegs != NULL) && ExcludeRegs->test(AntiDepReg)) { + // Don't break anti-dependencies for critical path registers + // if not on the critical path + DEBUG(dbgs() << " (not critical-path)\n"); + continue; + } else if (PassthruRegs.count(AntiDepReg) != 0) { + // If the anti-dep register liveness "passes-thru", then + // don't try to change it. It will be changed along with + // the use if required to break an earlier antidep. + DEBUG(dbgs() << " (passthru)\n"); + continue; + } else { + // No anti-dep breaking for implicit deps + MachineOperand *AntiDepOp = MI->findRegisterDefOperand(AntiDepReg); + assert(AntiDepOp != NULL && + "Can't find index for defined register operand"); + if ((AntiDepOp == NULL) || AntiDepOp->isImplicit()) { + DEBUG(dbgs() << " (implicit)\n"); + continue; + } + + // If the SUnit has other dependencies on the SUnit that + // it anti-depends on, don't bother breaking the + // anti-dependency since those edges would prevent such + // units from being scheduled past each other + // regardless. + // + // Also, if there are dependencies on other SUnits with the + // same register as the anti-dependency, don't attempt to + // break it. + for (SUnit::const_pred_iterator P = PathSU->Preds.begin(), + PE = PathSU->Preds.end(); P != PE; ++P) { + if (P->getSUnit() == NextSU ? + (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) : + (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) { + AntiDepReg = 0; + break; + } + } + for (SUnit::const_pred_iterator P = PathSU->Preds.begin(), + PE = PathSU->Preds.end(); P != PE; ++P) { + if ((P->getSUnit() == NextSU) && (P->getKind() != SDep::Anti) && + (P->getKind() != SDep::Output)) { + DEBUG(dbgs() << " (real dependency)\n"); + AntiDepReg = 0; + break; + } else if ((P->getSUnit() != NextSU) && + (P->getKind() == SDep::Data) && + (P->getReg() == AntiDepReg)) { + DEBUG(dbgs() << " (other dependency)\n"); + AntiDepReg = 0; + break; + } + } + + if (AntiDepReg == 0) continue; + } + + assert(AntiDepReg != 0); + if (AntiDepReg == 0) continue; + + // Determine AntiDepReg's register group. + const unsigned GroupIndex = State->GetGroup(AntiDepReg); + if (GroupIndex == 0) { + DEBUG(dbgs() << " (zero group)\n"); + continue; + } + + DEBUG(dbgs() << '\n'); + + // Look for a suitable register to use to break the anti-dependence. + std::map RenameMap; + if (FindSuitableFreeRegisters(GroupIndex, RenameOrder, RenameMap)) { + DEBUG(dbgs() << "\tBreaking anti-dependence edge on " + << TRI->getName(AntiDepReg) << ":"); + + // Handle each group register... + for (std::map::iterator + S = RenameMap.begin(), E = RenameMap.end(); S != E; ++S) { + unsigned CurrReg = S->first; + unsigned NewReg = S->second; + + DEBUG(dbgs() << " " << TRI->getName(CurrReg) << "->" << + TRI->getName(NewReg) << "(" << + RegRefs.count(CurrReg) << " refs)"); + + // Update the references to the old register CurrReg to + // refer to the new register NewReg. + std::pair::iterator, + std::multimap::iterator> + Range = RegRefs.equal_range(CurrReg); + for (std::multimap::iterator + Q = Range.first, QE = Range.second; Q != QE; ++Q) { + Q->second.Operand->setReg(NewReg); + // If the SU for the instruction being updated has debug + // information related to the anti-dependency register, make + // sure to update that as well. + const SUnit *SU = MISUnitMap[Q->second.Operand->getParent()]; + if (!SU) continue; + for (unsigned i = 0, e = SU->DbgInstrList.size() ; i < e ; ++i) { + MachineInstr *DI = SU->DbgInstrList[i]; + assert (DI->getNumOperands()==3 && DI->getOperand(0).isReg() && + DI->getOperand(0).getReg() + && "Non register dbg_value attached to SUnit!"); + if (DI->getOperand(0).getReg() == AntiDepReg) + DI->getOperand(0).setReg(NewReg); + } + } + + // We just went back in time and modified history; the + // liveness information for CurrReg is now inconsistent. Set + // the state as if it were dead. + State->UnionGroups(NewReg, 0); + RegRefs.erase(NewReg); + DefIndices[NewReg] = DefIndices[CurrReg]; + KillIndices[NewReg] = KillIndices[CurrReg]; + + State->UnionGroups(CurrReg, 0); + RegRefs.erase(CurrReg); + DefIndices[CurrReg] = KillIndices[CurrReg]; + KillIndices[CurrReg] = ~0u; + assert(((KillIndices[CurrReg] == ~0u) != + (DefIndices[CurrReg] == ~0u)) && + "Kill and Def maps aren't consistent for AntiDepReg!"); + } + + ++Broken; + DEBUG(dbgs() << '\n'); + } + } + } + + ScanInstruction(MI, Count); + } + + return Broken; +} diff --git a/final/lib/CodeGen/AggressiveAntiDepBreaker.h b/final/lib/CodeGen/AggressiveAntiDepBreaker.h new file mode 100644 index 00000000000..9d715ccf79f --- /dev/null +++ b/final/lib/CodeGen/AggressiveAntiDepBreaker.h @@ -0,0 +1,184 @@ +//=- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AggressiveAntiDepBreaker class, which +// implements register anti-dependence breaking during post-RA +// scheduling. It attempts to break all anti-dependencies within a +// block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H +#define LLVM_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H + +#include "AntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { + /// Class AggressiveAntiDepState + /// Contains all the state necessary for anti-dep breaking. + class AggressiveAntiDepState { + public: + /// RegisterReference - Information about a register reference + /// within a liverange + typedef struct { + /// Operand - The registers operand + MachineOperand *Operand; + /// RC - The register class + const TargetRegisterClass *RC; + } RegisterReference; + + private: + /// NumTargetRegs - Number of non-virtual target registers + /// (i.e. TRI->getNumRegs()). + const unsigned NumTargetRegs; + + /// GroupNodes - Implements a disjoint-union data structure to + /// form register groups. A node is represented by an index into + /// the vector. A node can "point to" itself to indicate that it + /// is the parent of a group, or point to another node to indicate + /// that it is a member of the same group as that node. + std::vector GroupNodes; + + /// GroupNodeIndices - For each register, the index of the GroupNode + /// currently representing the group that the register belongs to. + /// Register 0 is always represented by the 0 group, a group + /// composed of registers that are not eligible for anti-aliasing. + std::vector GroupNodeIndices; + + /// RegRefs - Map registers to all their references within a live range. + std::multimap RegRefs; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + std::vector KillIndices; + + /// DefIndices - The index of the most recent complete def (proceding bottom + /// up), or ~0u if the register is live. + std::vector DefIndices; + + public: + AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB); + + /// GetKillIndices - Return the kill indices. + std::vector &GetKillIndices() { return KillIndices; } + + /// GetDefIndices - Return the define indices. + std::vector &GetDefIndices() { return DefIndices; } + + /// GetRegRefs - Return the RegRefs map. + std::multimap& GetRegRefs() { return RegRefs; } + + // GetGroup - Get the group for a register. The returned value is + // the index of the GroupNode representing the group. + unsigned GetGroup(unsigned Reg); + + // GetGroupRegs - Return a vector of the registers belonging to a + // group. If RegRefs is non-NULL then only included referenced registers. + void GetGroupRegs( + unsigned Group, + std::vector &Regs, + std::multimap *RegRefs); + + // UnionGroups - Union Reg1's and Reg2's groups to form a new + // group. Return the index of the GroupNode representing the + // group. + unsigned UnionGroups(unsigned Reg1, unsigned Reg2); + + // LeaveGroup - Remove a register from its current group and place + // it alone in its own group. Return the index of the GroupNode + // representing the registers new group. + unsigned LeaveGroup(unsigned Reg); + + /// IsLive - Return true if Reg is live + bool IsLive(unsigned Reg); + }; + + + /// Class AggressiveAntiDepBreaker + class AggressiveAntiDepBreaker : public AntiDepBreaker { + MachineFunction& MF; + MachineRegisterInfo &MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + + /// AllocatableSet - The set of allocatable registers. + /// We'll be ignoring anti-dependencies on non-allocatable registers, + /// because they may not be safe to break. + const BitVector AllocatableSet; + + /// CriticalPathSet - The set of registers that should only be + /// renamed if they are on the critical path. + BitVector CriticalPathSet; + + /// State - The state used to identify and rename anti-dependence + /// registers. + AggressiveAntiDepState *State; + + public: + AggressiveAntiDepBreaker(MachineFunction& MFi, + TargetSubtarget::RegClassVector& CriticalPathRCs); + ~AggressiveAntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + void StartBlock(MachineBasicBlock *BB); + + /// BreakAntiDependencies - Identifiy anti-dependencies along the critical + /// path + /// of the ScheduleDAG and break them by renaming registers. + /// + unsigned BreakAntiDependencies(const std::vector& SUnits, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned InsertPosIndex); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); + + /// Finish - Finish anti-dep breaking for a basic block. + void FinishBlock(); + + private: + typedef std::map RenameOrderType; + + /// IsImplicitDefUse - Return true if MO represents a register + /// that is both implicitly used and defined in MI + bool IsImplicitDefUse(MachineInstr *MI, MachineOperand& MO); + + /// GetPassthruRegs - If MI implicitly def/uses a register, then + /// return that register and all subregisters. + void GetPassthruRegs(MachineInstr *MI, std::set& PassthruRegs); + + void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag, + const char *header =NULL, const char *footer =NULL); + + void PrescanInstruction(MachineInstr *MI, unsigned Count, + std::set& PassthruRegs); + void ScanInstruction(MachineInstr *MI, unsigned Count); + BitVector GetRenameRegisters(unsigned Reg); + bool FindSuitableFreeRegisters(unsigned AntiDepGroupIndex, + RenameOrderType& RenameOrder, + std::map &RenameMap); + }; +} + +#endif diff --git a/final/lib/CodeGen/AllocationOrder.cpp b/final/lib/CodeGen/AllocationOrder.cpp new file mode 100644 index 00000000000..20c7625f325 --- /dev/null +++ b/final/lib/CodeGen/AllocationOrder.cpp @@ -0,0 +1,68 @@ +//===-- llvm/CodeGen/AllocationOrder.cpp - Allocation Order ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an allocation order for virtual registers. +// +// The preferred allocation order for a virtual register depends on allocation +// hints and target hooks. The AllocationOrder class encapsulates all of that. +// +//===----------------------------------------------------------------------===// + +#include "AllocationOrder.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +// Compare VirtRegMap::getRegAllocPref(). +AllocationOrder::AllocationOrder(unsigned VirtReg, + const VirtRegMap &VRM, + const BitVector &ReservedRegs) + : Pos(0), Reserved(ReservedRegs) { + const TargetRegisterClass *RC = VRM.getRegInfo().getRegClass(VirtReg); + std::pair HintPair = + VRM.getRegInfo().getRegAllocationHint(VirtReg); + + // HintPair.second is a register, phys or virt. + Hint = HintPair.second; + + // Translate to physreg, or 0 if not assigned yet. + if (TargetRegisterInfo::isVirtualRegister(Hint)) + Hint = VRM.getPhys(Hint); + + // The remaining allocation order may depend on the hint. + tie(Begin, End) = VRM.getTargetRegInfo() + .getAllocationOrder(RC, HintPair.first, Hint, VRM.getMachineFunction()); + + // Target-dependent hints require resolution. + if (HintPair.first) + Hint = VRM.getTargetRegInfo().ResolveRegAllocHint(HintPair.first, Hint, + VRM.getMachineFunction()); + + // The hint must be a valid physreg for allocation. + if (Hint && (!TargetRegisterInfo::isPhysicalRegister(Hint) || + !RC->contains(Hint) || ReservedRegs.test(Hint))) + Hint = 0; +} + +unsigned AllocationOrder::next() { + // First take the hint. + if (!Pos) { + Pos = Begin; + if (Hint) + return Hint; + } + // Then look at the order from TRI. + while(Pos != End) { + unsigned Reg = *Pos++; + if (Reg != Hint && !Reserved.test(Reg)) + return Reg; + } + return 0; +} diff --git a/final/lib/CodeGen/AllocationOrder.h b/final/lib/CodeGen/AllocationOrder.h new file mode 100644 index 00000000000..61fd8f881a8 --- /dev/null +++ b/final/lib/CodeGen/AllocationOrder.h @@ -0,0 +1,56 @@ +//===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- C++ -*-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an allocation order for virtual registers. +// +// The preferred allocation order for a virtual register depends on allocation +// hints and target hooks. The AllocationOrder class encapsulates all of that. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ALLOCATIONORDER_H +#define LLVM_CODEGEN_ALLOCATIONORDER_H + +namespace llvm { + +class BitVector; +class VirtRegMap; + +class AllocationOrder { + const unsigned *Begin; + const unsigned *End; + const unsigned *Pos; + const BitVector &Reserved; + unsigned Hint; +public: + + /// AllocationOrder - Create a new AllocationOrder for VirtReg. + /// @param VirtReg Virtual register to allocate for. + /// @param VRM Virtual register map for function. + /// @param ReservedRegs Set of reserved registers as returned by + /// TargetRegisterInfo::getReservedRegs(). + AllocationOrder(unsigned VirtReg, + const VirtRegMap &VRM, + const BitVector &ReservedRegs); + + /// next - Return the next physical register in the allocation order, or 0. + /// It is safe to call next again after it returned 0. + /// It will keep returning 0 until rewind() is called. + unsigned next(); + + /// rewind - Start over from the beginning. + void rewind() { Pos = 0; } + + /// isHint - Return true if PhysReg is a preferred register. + bool isHint(unsigned PhysReg) const { return PhysReg == Hint; } +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/CodeGen/Analysis.cpp b/final/lib/CodeGen/Analysis.cpp new file mode 100644 index 00000000000..36638c36de6 --- /dev/null +++ b/final/lib/CodeGen/Analysis.cpp @@ -0,0 +1,303 @@ +//===-- Analysis.cpp - CodeGen LLVM IR Analysis Utilities --*- 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 several CodeGen-specific LLVM IR analysis utilties. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Analysis.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence +/// of insertvalue or extractvalue indices that identify a member, return +/// the linearized index of the start of the member. +/// +unsigned llvm::ComputeLinearIndex(const Type *Ty, + const unsigned *Indices, + const unsigned *IndicesEnd, + unsigned CurIndex) { + // Base case: We're done. + if (Indices && Indices == IndicesEnd) + return CurIndex; + + // Given a struct type, recursively traverse the elements. + if (const StructType *STy = dyn_cast(Ty)) { + for (StructType::element_iterator EB = STy->element_begin(), + EI = EB, + EE = STy->element_end(); + EI != EE; ++EI) { + if (Indices && *Indices == unsigned(EI - EB)) + return ComputeLinearIndex(*EI, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(*EI, 0, 0, CurIndex); + } + return CurIndex; + } + // Given an array type, recursively traverse the elements. + else if (const ArrayType *ATy = dyn_cast(Ty)) { + const Type *EltTy = ATy->getElementType(); + for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { + if (Indices && *Indices == i) + return ComputeLinearIndex(EltTy, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(EltTy, 0, 0, CurIndex); + } + return CurIndex; + } + // We haven't found the type we're looking for, so keep searching. + return CurIndex + 1; +} + +/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of +/// EVTs that represent all the individual underlying +/// non-aggregate types that comprise it. +/// +/// If Offsets is non-null, it points to a vector to be filled in +/// with the in-memory offsets of each of the individual values. +/// +void llvm::ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, + SmallVectorImpl &ValueVTs, + SmallVectorImpl *Offsets, + uint64_t StartingOffset) { + // Given a struct type, recursively traverse the elements. + if (const StructType *STy = dyn_cast(Ty)) { + const StructLayout *SL = TLI.getTargetData()->getStructLayout(STy); + for (StructType::element_iterator EB = STy->element_begin(), + EI = EB, + EE = STy->element_end(); + EI != EE; ++EI) + ComputeValueVTs(TLI, *EI, ValueVTs, Offsets, + StartingOffset + SL->getElementOffset(EI - EB)); + return; + } + // Given an array type, recursively traverse the elements. + if (const ArrayType *ATy = dyn_cast(Ty)) { + const Type *EltTy = ATy->getElementType(); + uint64_t EltSize = TLI.getTargetData()->getTypeAllocSize(EltTy); + for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) + ComputeValueVTs(TLI, EltTy, ValueVTs, Offsets, + StartingOffset + i * EltSize); + return; + } + // Interpret void as zero return values. + if (Ty->isVoidTy()) + return; + // Base case: we can get an EVT for this LLVM IR type. + ValueVTs.push_back(TLI.getValueType(Ty)); + if (Offsets) + Offsets->push_back(StartingOffset); +} + +/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. +GlobalVariable *llvm::ExtractTypeInfo(Value *V) { + V = V->stripPointerCasts(); + GlobalVariable *GV = dyn_cast(V); + + if (GV && GV->getName() == "llvm.eh.catch.all.value") { + assert(GV->hasInitializer() && + "The EH catch-all value must have an initializer"); + Value *Init = GV->getInitializer(); + GV = dyn_cast(Init); + if (!GV) V = cast(Init); + } + + assert((GV || isa(V)) && + "TypeInfo must be a global variable or NULL"); + return GV; +} + +/// hasInlineAsmMemConstraint - Return true if the inline asm instruction being +/// processed uses a memory 'm' constraint. +bool +llvm::hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos, + const TargetLowering &TLI) { + for (unsigned i = 0, e = CInfos.size(); i != e; ++i) { + InlineAsm::ConstraintInfo &CI = CInfos[i]; + for (unsigned j = 0, ee = CI.Codes.size(); j != ee; ++j) { + TargetLowering::ConstraintType CType = TLI.getConstraintType(CI.Codes[j]); + if (CType == TargetLowering::C_Memory) + return true; + } + + // Indirect operand accesses access memory. + if (CI.isIndirect) + return true; + } + + return false; +} + +/// getFCmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR floating-point condition code. This includes +/// consideration of global floating-point math flags. +/// +ISD::CondCode llvm::getFCmpCondCode(FCmpInst::Predicate Pred) { + ISD::CondCode FPC, FOC; + switch (Pred) { + case FCmpInst::FCMP_FALSE: FOC = FPC = ISD::SETFALSE; break; + case FCmpInst::FCMP_OEQ: FOC = ISD::SETEQ; FPC = ISD::SETOEQ; break; + case FCmpInst::FCMP_OGT: FOC = ISD::SETGT; FPC = ISD::SETOGT; break; + case FCmpInst::FCMP_OGE: FOC = ISD::SETGE; FPC = ISD::SETOGE; break; + case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break; + case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break; + case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break; + case FCmpInst::FCMP_ORD: FOC = FPC = ISD::SETO; break; + case FCmpInst::FCMP_UNO: FOC = FPC = ISD::SETUO; break; + case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break; + case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break; + case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break; + case FCmpInst::FCMP_ULT: FOC = ISD::SETLT; FPC = ISD::SETULT; break; + case FCmpInst::FCMP_ULE: FOC = ISD::SETLE; FPC = ISD::SETULE; break; + case FCmpInst::FCMP_UNE: FOC = ISD::SETNE; FPC = ISD::SETUNE; break; + case FCmpInst::FCMP_TRUE: FOC = FPC = ISD::SETTRUE; break; + default: + llvm_unreachable("Invalid FCmp predicate opcode!"); + FOC = FPC = ISD::SETFALSE; + break; + } + if (NoNaNsFPMath) + return FOC; + else + return FPC; +} + +/// getICmpCondCode - Return the ISD condition code corresponding to +/// the given LLVM IR integer condition code. +/// +ISD::CondCode llvm::getICmpCondCode(ICmpInst::Predicate Pred) { + switch (Pred) { + case ICmpInst::ICMP_EQ: return ISD::SETEQ; + case ICmpInst::ICMP_NE: return ISD::SETNE; + case ICmpInst::ICMP_SLE: return ISD::SETLE; + case ICmpInst::ICMP_ULE: return ISD::SETULE; + case ICmpInst::ICMP_SGE: return ISD::SETGE; + case ICmpInst::ICMP_UGE: return ISD::SETUGE; + case ICmpInst::ICMP_SLT: return ISD::SETLT; + case ICmpInst::ICMP_ULT: return ISD::SETULT; + case ICmpInst::ICMP_SGT: return ISD::SETGT; + case ICmpInst::ICMP_UGT: return ISD::SETUGT; + default: + llvm_unreachable("Invalid ICmp predicate opcode!"); + return ISD::SETNE; + } +} + +/// Test if the given instruction is in a position to be optimized +/// with a tail-call. This roughly means that it's in a block with +/// a return and there's nothing that needs to be scheduled +/// between it and the return. +/// +/// This function only tests target-independent requirements. +bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr, + const TargetLowering &TLI) { + const Instruction *I = CS.getInstruction(); + const BasicBlock *ExitBB = I->getParent(); + const TerminatorInst *Term = ExitBB->getTerminator(); + const ReturnInst *Ret = dyn_cast(Term); + const Function *F = ExitBB->getParent(); + + // The block must end in a return statement or unreachable. + // + // FIXME: Decline tailcall if it's not guaranteed and if the block ends in + // an unreachable, for now. The way tailcall optimization is currently + // implemented means it will add an epilogue followed by a jump. That is + // not profitable. Also, if the callee is a special function (e.g. + // longjmp on x86), it can end up causing miscompilation that has not + // been fully understood. + if (!Ret && + (!GuaranteedTailCallOpt || !isa(Term))) return false; + + // If I will have a chain, make sure no other instruction that will have a + // chain interposes between I and the return. + if (I->mayHaveSideEffects() || I->mayReadFromMemory() || + !I->isSafeToSpeculativelyExecute()) + for (BasicBlock::const_iterator BBI = prior(prior(ExitBB->end())); ; + --BBI) { + if (&*BBI == I) + break; + // Debug info intrinsics do not get in the way of tail call optimization. + if (isa(BBI)) + continue; + if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() || + !BBI->isSafeToSpeculativelyExecute()) + return false; + } + + // If the block ends with a void return or unreachable, it doesn't matter + // what the call's return type is. + if (!Ret || Ret->getNumOperands() == 0) return true; + + // If the return value is undef, it doesn't matter what the call's + // return type is. + if (isa(Ret->getOperand(0))) return true; + + // Conservatively require the attributes of the call to match those of + // the return. Ignore noalias because it doesn't affect the call sequence. + unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) + return false; + + // It's not safe to eliminate the sign / zero extension of the return value. + if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) + return false; + + // Otherwise, make sure the unmodified return value of I is the return value. + for (const Instruction *U = dyn_cast(Ret->getOperand(0)); ; + U = dyn_cast(U->getOperand(0))) { + if (!U) + return false; + if (!U->hasOneUse()) + return false; + if (U == I) + break; + // Check for a truly no-op truncate. + if (isa(U) && + TLI.isTruncateFree(U->getOperand(0)->getType(), U->getType())) + continue; + // Check for a truly no-op bitcast. + if (isa(U) && + (U->getOperand(0)->getType() == U->getType() || + (U->getOperand(0)->getType()->isPointerTy() && + U->getType()->isPointerTy()))) + continue; + // Otherwise it's not a true no-op. + return false; + } + + return true; +} + +bool llvm::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, + const TargetLowering &TLI) { + const Function *F = DAG.getMachineFunction().getFunction(); + + // Conservatively require the attributes of the call to match those of + // the return. Ignore noalias because it doesn't affect the call sequence. + unsigned CallerRetAttr = F->getAttributes().getRetAttributes(); + if (CallerRetAttr & ~Attribute::NoAlias) + return false; + + // It's not safe to eliminate the sign / zero extension of the return value. + if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) + return false; + + // Check if the only use is a function return node. + return TLI.isUsedByReturnOnly(Node); +} diff --git a/final/lib/CodeGen/AntiDepBreaker.h b/final/lib/CodeGen/AntiDepBreaker.h new file mode 100644 index 00000000000..086b7579563 --- /dev/null +++ b/final/lib/CodeGen/AntiDepBreaker.h @@ -0,0 +1,59 @@ +//=- llvm/CodeGen/AntiDepBreaker.h - Anti-Dependence Breaking -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AntiDepBreaker class, which implements +// anti-dependence breaking heuristics for post-register-allocation scheduling. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ANTIDEPBREAKER_H +#define LLVM_CODEGEN_ANTIDEPBREAKER_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include + +namespace llvm { + +/// AntiDepBreaker - This class works into conjunction with the +/// post-RA scheduler to rename registers to break register +/// anti-dependencies. +class AntiDepBreaker { +public: + virtual ~AntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + virtual void StartBlock(MachineBasicBlock *BB) =0; + + /// BreakAntiDependencies - Identifiy anti-dependencies within a + /// basic-block region and break them by renaming registers. Return + /// the number of anti-dependencies broken. + /// + virtual unsigned BreakAntiDependencies(const std::vector& SUnits, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned InsertPosIndex) =0; + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + virtual void Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) =0; + + /// Finish - Finish anti-dep breaking for a basic block. + virtual void FinishBlock() =0; +}; + +} + +#endif diff --git a/final/lib/CodeGen/AsmPrinter/ARMException.cpp b/final/lib/CodeGen/AsmPrinter/ARMException.cpp new file mode 100644 index 00000000000..0db28a636ad --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -0,0 +1,87 @@ +//===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +ARMException::ARMException(AsmPrinter *A) + : DwarfException(A), + shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false) + {} + +ARMException::~ARMException() {} + +void ARMException::EndModule() { +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void ARMException::BeginFunction(const MachineFunction *MF) { + Asm->OutStreamer.EmitFnStart(); + if (!Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void ARMException::EndFunction() { + if (Asm->MF->getFunction()->doesNotThrow() && !UnwindTablesMandatory) + Asm->OutStreamer.EmitCantUnwind(); + else { + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); + + // Emit references to personality. + if (const Function * Personality = + MMI->getPersonalities()[MMI->getPersonalityIndex()]) { + MCSymbol *PerSym = Asm->Mang->getSymbol(Personality); + Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); + Asm->OutStreamer.EmitPersonality(PerSym); + } + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + Asm->OutStreamer.EmitHandlerData(); + + // Emit actual exception table + EmitExceptionTable(); + } + + Asm->OutStreamer.EmitFnEnd(); +} diff --git a/final/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/final/lib/CodeGen/AsmPrinter/AsmPrinter.cpp new file mode 100644 index 00000000000..f740c7400bc --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -0,0 +1,1904 @@ +//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===// +// +// 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 AsmPrinter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "DwarfDebug.h" +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Timer.h" +using namespace llvm; + +static const char *DWARFGroupName = "DWARF Emission"; +static const char *DbgTimerName = "DWARF Debug Writer"; +static const char *EHTimerName = "DWARF Exception Writer"; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +char AsmPrinter::ID = 0; + +typedef DenseMap gcp_map_type; +static gcp_map_type &getGCMap(void *&P) { + if (P == 0) + P = new gcp_map_type(); + return *(gcp_map_type*)P; +} + + +/// getGVAlignmentLog2 - Return the alignment to use for the specified global +/// value in log2 form. This rounds up to the preferred alignment if possible +/// and legal. +static unsigned getGVAlignmentLog2(const GlobalValue *GV, const TargetData &TD, + unsigned InBits = 0) { + unsigned NumBits = 0; + if (const GlobalVariable *GVar = dyn_cast(GV)) + NumBits = TD.getPreferredAlignmentLog(GVar); + + // If InBits is specified, round it to it. + if (InBits > NumBits) + NumBits = InBits; + + // If the GV has a specified alignment, take it into account. + if (GV->getAlignment() == 0) + return NumBits; + + unsigned GVAlign = Log2_32(GV->getAlignment()); + + // If the GVAlign is larger than NumBits, or if we are required to obey + // NumBits because the GV has an assigned section, obey it. + if (GVAlign > NumBits || GV->hasSection()) + NumBits = GVAlign; + return NumBits; +} + + + + +AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) + : MachineFunctionPass(ID), + TM(tm), MAI(tm.getMCAsmInfo()), + OutContext(Streamer.getContext()), + OutStreamer(Streamer), + LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { + DD = 0; DE = 0; MMI = 0; LI = 0; + GCMetadataPrinters = 0; + VerboseAsm = Streamer.isVerboseAsm(); +} + +AsmPrinter::~AsmPrinter() { + assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); + + if (GCMetadataPrinters != 0) { + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + + for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I) + delete I->second; + delete &GCMap; + GCMetadataPrinters = 0; + } + + delete &OutStreamer; +} + +/// getFunctionNumber - Return a unique ID for the current function. +/// +unsigned AsmPrinter::getFunctionNumber() const { + return MF->getFunctionNumber(); +} + +const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { + return TM.getTargetLowering()->getObjFileLowering(); +} + + +/// getTargetData - Return information about data layout. +const TargetData &AsmPrinter::getTargetData() const { + return *TM.getTargetData(); +} + +/// getCurrentSection() - Return the current section we are emitting to. +const MCSection *AsmPrinter::getCurrentSection() const { + return OutStreamer.getCurrentSection(); +} + + + +void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); + if (isVerbose()) + AU.addRequired(); +} + +bool AsmPrinter::doInitialization(Module &M) { + MMI = getAnalysisIfAvailable(); + MMI->AnalyzeModule(M); + + // Initialize TargetLoweringObjectFile. + const_cast(getObjFileLowering()) + .Initialize(OutContext, TM); + + Mang = new Mangler(OutContext, *TM.getTargetData()); + + // Allow the target to emit any magic that it wants at the start of the file. + EmitStartOfAsmFile(M); + + // Very minimal debug info. It is ignored if we emit actual debug info. If we + // don't, this at least helps the user find where a global came from. + if (MAI->hasSingleParameterDotFile()) { + // .file "foo.c" + OutStreamer.EmitFileDirective(M.getModuleIdentifier()); + } + + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) + MP->beginAssembly(*this); + + // Emit module-level inline asm if it exists. + if (!M.getModuleInlineAsm().empty()) { + OutStreamer.AddComment("Start of file scope inline assembly"); + OutStreamer.AddBlankLine(); + EmitInlineAsm(M.getModuleInlineAsm()+"\n"); + OutStreamer.AddComment("End of file scope inline assembly"); + OutStreamer.AddBlankLine(); + } + + if (MAI->doesSupportDebugInformation()) + DD = new DwarfDebug(this, &M); + + if (MAI->doesSupportExceptionHandling()) + switch (MAI->getExceptionHandlingType()) { + default: + case ExceptionHandling::DwarfTable: + DE = new DwarfTableException(this); + break; + case ExceptionHandling::DwarfCFI: + DE = new DwarfCFIException(this); + break; + case ExceptionHandling::ARM: + DE = new ARMException(this); + break; + } + + return false; +} + +void AsmPrinter::EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const { + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::CommonLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + case GlobalValue::LinkerPrivateWeakLinkage: + case GlobalValue::LinkerPrivateWeakDefAutoLinkage: + if (MAI->getWeakDefDirective() != 0) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + + if ((GlobalValue::LinkageTypes)Linkage != + GlobalValue::LinkerPrivateWeakDefAutoLinkage) + // .weak_definition _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + else + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); + } else if (MAI->getLinkOnceDirective() != 0) { + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + //NOTE: linkonce is handled by the section the symbol was assigned to. + } else { + // .weak _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); + } + break; + case GlobalValue::DLLExportLinkage: + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol. + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + case GlobalValue::LinkerPrivateLinkage: + break; + default: + llvm_unreachable("Unknown linkage type!"); + } +} + + +/// EmitGlobalVariable - Emit the specified global variable to the .s file. +void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { + if (!GV->hasInitializer()) // External globals require no code. + return; + + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GV)) + return; + + if (isVerbose()) { + WriteAsOperand(OutStreamer.GetCommentOS(), GV, + /*PrintType=*/false, GV->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + MCSymbol *GVSym = Mang->getSymbol(GV); + EmitVisibility(GVSym, GV->getVisibility()); + + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject); + + SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); + + const TargetData *TD = TM.getTargetData(); + uint64_t Size = TD->getTypeAllocSize(GV->getType()->getElementType()); + + // If the alignment is specified, we *must* obey it. Overaligning a global + // with a specified alignment is a prompt way to break globals emitted to + // sections and expected to be contiguous (e.g. ObjC metadata). + unsigned AlignLog = getGVAlignmentLog2(GV, *TD); + + // Handle common and BSS local symbols (.lcomm). + if (GVKind.isCommon() || GVKind.isBSSLocal()) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + + if (isVerbose()) { + WriteAsOperand(OutStreamer.GetCommentOS(), GV, + /*PrintType=*/false, GV->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + // Handle common symbols. + if (GVKind.isCommon()) { + unsigned Align = 1 << AlignLog; + if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) + Align = 0; + + // .comm _foo, 42, 4 + OutStreamer.EmitCommonSymbol(GVSym, Size, Align); + return; + } + + // Handle local BSS symbols. + if (MAI->hasMachoZeroFillDirective()) { + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + // .zerofill __DATA, __bss, _foo, 400, 5 + OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); + return; + } + + if (MAI->hasLCOMMDirective()) { + // .lcomm _foo, 42 + OutStreamer.EmitLocalCommonSymbol(GVSym, Size); + return; + } + + unsigned Align = 1 << AlignLog; + if (!getObjFileLowering().getCommDirectiveSupportsAlignment()) + Align = 0; + + // .local _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Local); + // .comm _foo, 42, 4 + OutStreamer.EmitCommonSymbol(GVSym, Size, Align); + return; + } + + const MCSection *TheSection = + getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + + // Handle the zerofill directive on darwin, which is a special form of BSS + // emission. + if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective()) { + if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. + + // .globl _foo + OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); + // .zerofill __DATA, __common, _foo, 400, 5 + OutStreamer.EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog); + return; + } + + // Handle thread local data for mach-o which requires us to output an + // additional structure of data and mangle the original symbol so that we + // can reference it later. + // + // TODO: This should become an "emit thread local global" method on TLOF. + // All of this macho specific stuff should be sunk down into TLOFMachO and + // stuff like "TLSExtraDataSection" should no longer be part of the parent + // TLOF class. This will also make it more obvious that stuff like + // MCStreamer::EmitTBSSSymbol is macho specific and only called from macho + // specific code. + if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective()) { + // Emit the .tbss symbol + MCSymbol *MangSym = + OutContext.GetOrCreateSymbol(GVSym->getName() + Twine("$tlv$init")); + + if (GVKind.isThreadBSS()) + OutStreamer.EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog); + else if (GVKind.isThreadData()) { + OutStreamer.SwitchSection(TheSection); + + EmitAlignment(AlignLog, GV); + OutStreamer.EmitLabel(MangSym); + + EmitGlobalConstant(GV->getInitializer()); + } + + OutStreamer.AddBlankLine(); + + // Emit the variable struct for the runtime. + const MCSection *TLVSect + = getObjFileLowering().getTLSExtraDataSection(); + + OutStreamer.SwitchSection(TLVSect); + // Emit the linkage here. + EmitLinkage(GV->getLinkage(), GVSym); + OutStreamer.EmitLabel(GVSym); + + // Three pointers in size: + // - __tlv_bootstrap - used to make sure support exists + // - spare pointer, used when mapped by the runtime + // - pointer to mangled symbol above with initializer + unsigned PtrSize = TD->getPointerSizeInBits()/8; + OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"), + PtrSize, 0); + OutStreamer.EmitIntValue(0, PtrSize, 0); + OutStreamer.EmitSymbolValue(MangSym, PtrSize, 0); + + OutStreamer.AddBlankLine(); + return; + } + + OutStreamer.SwitchSection(TheSection); + + EmitLinkage(GV->getLinkage(), GVSym); + EmitAlignment(AlignLog, GV); + + OutStreamer.EmitLabel(GVSym); + + EmitGlobalConstant(GV->getInitializer()); + + if (MAI->hasDotTypeDotSizeDirective()) + // .size foo, 42 + OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext)); + + OutStreamer.AddBlankLine(); +} + +/// EmitFunctionHeader - This method emits the header for the current +/// function. +void AsmPrinter::EmitFunctionHeader() { + // Print out constants referenced by the function + EmitConstantPool(); + + // Print the 'header' of function. + const Function *F = MF->getFunction(); + + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitVisibility(CurrentFnSym, F->getVisibility()); + + EmitLinkage(F->getLinkage(), CurrentFnSym); + EmitAlignment(MF->getAlignment(), F); + + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); + + if (isVerbose()) { + WriteAsOperand(OutStreamer.GetCommentOS(), F, + /*PrintType=*/false, F->getParent()); + OutStreamer.GetCommentOS() << '\n'; + } + + // Emit the CurrentFnSym. This is a virtual function to allow targets to + // do their wild and crazy things as required. + EmitFunctionEntryLabel(); + + // If the function had address-taken blocks that got deleted, then we have + // references to the dangling symbols. Emit them at the start of the function + // so that we don't get references to undefined symbols. + std::vector DeadBlockSyms; + MMI->takeDeletedSymbolsForFunction(F, DeadBlockSyms); + for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) { + OutStreamer.AddComment("Address taken block that was later removed"); + OutStreamer.EmitLabel(DeadBlockSyms[i]); + } + + // Add some workaround for linkonce linkage on Cygwin\MinGW. + if (MAI->getLinkOnceDirective() != 0 && + (F->hasLinkOnceLinkage() || F->hasWeakLinkage())) { + // FIXME: What is this? + MCSymbol *FakeStub = + OutContext.GetOrCreateSymbol(Twine("Lllvm$workaround$fake$stub$")+ + CurrentFnSym->getName()); + OutStreamer.EmitLabel(FakeStub); + } + + // Emit pre-function debug and/or EH information. + if (DE) { + NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); + DE->BeginFunction(MF); + } + if (DD) { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + DD->beginFunction(MF); + } +} + +/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the +/// function. This can be overridden by targets as required to do custom stuff. +void AsmPrinter::EmitFunctionEntryLabel() { + // The function label could have already been emitted if two symbols end up + // conflicting due to asm renaming. Detect this and emit an error. + if (CurrentFnSym->isUndefined()) + return OutStreamer.EmitLabel(CurrentFnSym); + + report_fatal_error("'" + Twine(CurrentFnSym->getName()) + + "' label emitted multiple times to assembly file"); +} + + +static void EmitDebugLoc(DebugLoc DL, const MachineFunction *MF, + raw_ostream &CommentOS) { + const LLVMContext &Ctx = MF->getFunction()->getContext(); + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << ""; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << "[ "; + EmitDebugLoc(InlinedAtDL, MF, CommentOS); + CommentOS << " ]"; + } + } +} + +/// EmitComments - Pretty-print comments for instructions. +static void EmitComments(const MachineInstr &MI, raw_ostream &CommentOS) { + const MachineFunction *MF = MI.getParent()->getParent(); + const TargetMachine &TM = MF->getTarget(); + + DebugLoc DL = MI.getDebugLoc(); + if (!DL.isUnknown()) { // Print source line info. + EmitDebugLoc(DL, MF, CommentOS); + CommentOS << '\n'; + } + + // Check for spills and reloads + int FI; + + const MachineFrameInfo *FrameInfo = MF->getFrameInfo(); + + // We assume a single instruction only has a spill or reload, not + // both. + const MachineMemOperand *MMO; + if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Reload\n"; + } + } else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Reload\n"; + } else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) { + MMO = *MI.memoperands_begin(); + CommentOS << MMO->getSize() << "-byte Spill\n"; + } + } else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { + if (FrameInfo->isSpillSlotObjectIndex(FI)) + CommentOS << MMO->getSize() << "-byte Folded Spill\n"; + } + + // Check for spill-induced copies + if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) + CommentOS << " Reload Reuse\n"; +} + +/// EmitImplicitDef - This method emits the specified machine instruction +/// that is an implicit def. +static void EmitImplicitDef(const MachineInstr *MI, AsmPrinter &AP) { + unsigned RegNo = MI->getOperand(0).getReg(); + AP.OutStreamer.AddComment(Twine("implicit-def: ") + + AP.TM.getRegisterInfo()->getName(RegNo)); + AP.OutStreamer.AddBlankLine(); +} + +static void EmitKill(const MachineInstr *MI, AsmPrinter &AP) { + std::string Str = "kill:"; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &Op = MI->getOperand(i); + assert(Op.isReg() && "KILL instruction must have only register operands"); + Str += ' '; + Str += AP.TM.getRegisterInfo()->getName(Op.getReg()); + Str += (Op.isDef() ? "" : ""); + } + AP.OutStreamer.AddComment(Str); + AP.OutStreamer.AddBlankLine(); +} + +/// EmitDebugValueComment - This method handles the target-independent form +/// of DBG_VALUE, returning true if it was able to do so. A false return +/// means the target will need to handle MI in EmitInstruction. +static bool EmitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { + // This code handles only the 3-operand target-independent form. + if (MI->getNumOperands() != 3) + return false; + + SmallString<128> Str; + raw_svector_ostream OS(Str); + OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: "; + + // cast away const; DIetc do not take const operands for some reason. + DIVariable V(const_cast(MI->getOperand(2).getMetadata())); + if (V.getContext().isSubprogram()) + OS << DISubprogram(V.getContext()).getDisplayName() << ":"; + OS << V.getName() << " <- "; + + // Register or immediate value. Register 0 means undef. + if (MI->getOperand(0).isFPImm()) { + APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); + if (MI->getOperand(0).getFPImm()->getType()->isFloatTy()) { + OS << (double)APF.convertToFloat(); + } else if (MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) { + OS << APF.convertToDouble(); + } else { + // There is no good way to print long double. Convert a copy to + // double. Ah well, it's only a comment. + bool ignored; + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + OS << "(long double) " << APF.convertToDouble(); + } + } else if (MI->getOperand(0).isImm()) { + OS << MI->getOperand(0).getImm(); + } else { + assert(MI->getOperand(0).isReg() && "Unknown operand type"); + if (MI->getOperand(0).getReg() == 0) { + // Suppress offset, it is not meaningful here. + OS << "undef"; + // NOTE: Want this comment at start of line, don't emit with AddComment. + AP.OutStreamer.EmitRawText(OS.str()); + return true; + } + OS << AP.TM.getRegisterInfo()->getName(MI->getOperand(0).getReg()); + } + + OS << '+' << MI->getOperand(1).getImm(); + // NOTE: Want this comment at start of line, don't emit with AddComment. + AP.OutStreamer.EmitRawText(OS.str()); + return true; +} + +/// EmitFunctionBody - This method emits the body and trailer for a +/// function. +void AsmPrinter::EmitFunctionBody() { + // Emit target-specific gunk before the function body. + EmitFunctionBodyStart(); + + bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); + + // Print out code for the function. + bool HasAnyRealCode = false; + const MachineInstr *LastMI = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + // Print a label for the basic block. + EmitBasicBlockStart(I); + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + LastMI = II; + + // Print the assembly for the instruction. + if (!II->isLabel() && !II->isImplicitDef() && !II->isKill() && + !II->isDebugValue()) { + HasAnyRealCode = true; + ++EmittedInsts; + } + + if (ShouldPrintDebugScopes) { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + DD->beginInstruction(II); + } + + if (isVerbose()) + EmitComments(*II, OutStreamer.GetCommentOS()); + + switch (II->getOpcode()) { + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); + break; + case TargetOpcode::INLINEASM: + EmitInlineAsm(II); + break; + case TargetOpcode::DBG_VALUE: + if (isVerbose()) { + if (!EmitDebugValueComment(II, *this)) + EmitInstruction(II); + } + break; + case TargetOpcode::IMPLICIT_DEF: + if (isVerbose()) EmitImplicitDef(II, *this); + break; + case TargetOpcode::KILL: + if (isVerbose()) EmitKill(II, *this); + break; + default: + EmitInstruction(II); + break; + } + + if (ShouldPrintDebugScopes) { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + DD->endInstruction(II); + } + } + } + + // If the last instruction was a prolog label, then we have a situation where + // we emitted a prolog but no function body. This results in the ending prolog + // label equaling the end of function label and an invalid "row" in the + // FDE. We need to emit a noop in this situation so that the FDE's rows are + // valid. + bool RequiresNoop = LastMI && LastMI->isPrologLabel(); + + // If the function is empty and the object file uses .subsections_via_symbols, + // then we need to emit *something* to the function body to prevent the + // labels from collapsing together. Just emit a noop. + if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) || RequiresNoop) { + MCInst Noop; + TM.getInstrInfo()->getNoopForMachoTarget(Noop); + if (Noop.getOpcode()) { + OutStreamer.AddComment("avoids zero-length function"); + OutStreamer.EmitInstruction(Noop); + } else // Target not mc-ized yet. + OutStreamer.EmitRawText(StringRef("\tnop\n")); + } + + // Emit target-specific gunk after the function body. + EmitFunctionBodyEnd(); + + // If the target wants a .size directive for the size of the function, emit + // it. + if (MAI->hasDotTypeDotSizeDirective()) { + // Create a symbol for the end of function, so we can get the size as + // difference between the function label and the temp label. + MCSymbol *FnEndLabel = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(FnEndLabel); + + const MCExpr *SizeExp = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(FnEndLabel, OutContext), + MCSymbolRefExpr::Create(CurrentFnSym, OutContext), + OutContext); + OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); + } + + // Emit post-function debug information. + if (DD) { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + DD->endFunction(MF); + } + if (DE) { + NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); + DE->EndFunction(); + } + MMI->EndFunction(); + + // Print out jump tables referenced by the function. + EmitJumpTableInfo(); + + OutStreamer.AddBlankLine(); +} + +/// getDebugValueLocation - Get location information encoded by DBG_VALUE +/// operands. +MachineLocation AsmPrinter::getDebugValueLocation(const MachineInstr *MI) const { + // Target specific DBG_VALUE instructions are handled by each target. + return MachineLocation(); +} + +bool AsmPrinter::doFinalization(Module &M) { + // Emit global variables. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + EmitGlobalVariable(I); + + // Emit visibility info for declarations + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { + const Function &F = *I; + if (!F.isDeclaration()) + continue; + GlobalValue::VisibilityTypes V = F.getVisibility(); + if (V == GlobalValue::DefaultVisibility) + continue; + + MCSymbol *Name = Mang->getSymbol(&F); + EmitVisibility(Name, V, false); + } + + // Finalize debug and EH information. + if (DE) { + { + NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); + DE->EndModule(); + } + delete DE; DE = 0; + } + if (DD) { + { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + DD->endModule(); + } + delete DD; DD = 0; + } + + // If the target wants to know about weak references, print them all. + if (MAI->getWeakRefDirective()) { + // FIXME: This is not lazy, it would be nice to only print weak references + // to stuff that is actually used. Note that doing so would require targets + // to notice uses in operands (due to constant exprs etc). This should + // happen with the MC stuff eventually. + + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasExternalWeakLinkage()) continue; + OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference); + } + + for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { + if (!I->hasExternalWeakLinkage()) continue; + OutStreamer.EmitSymbolAttribute(Mang->getSymbol(I), MCSA_WeakReference); + } + } + + if (MAI->hasSetDirective()) { + OutStreamer.AddBlankLine(); + for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + MCSymbol *Name = Mang->getSymbol(I); + + const GlobalValue *GV = cast(I->getAliasedGlobal()); + MCSymbol *Target = Mang->getSymbol(GV); + + if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) + OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); + else if (I->hasWeakLinkage()) + OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(I->hasLocalLinkage() && "Invalid alias linkage"); + + EmitVisibility(Name, I->getVisibility()); + + // Emit the directives as assignments aka .set: + OutStreamer.EmitAssignment(Name, + MCSymbolRefExpr::Create(Target, OutContext)); + } + } + + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) + MP->finishAssembly(*this); + + // If we don't have any trampolines, then we don't require stack memory + // to be executable. Some targets have a directive to declare this. + Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); + if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) + if (const MCSection *S = MAI->getNonexecutableStackSection(OutContext)) + OutStreamer.SwitchSection(S); + + // Allow the target to emit any magic that it wants at the end of the file, + // after everything else has gone out. + EmitEndOfAsmFile(M); + + delete Mang; Mang = 0; + MMI = 0; + + OutStreamer.Finish(); + return false; +} + +void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { + this->MF = &MF; + // Get the function symbol. + CurrentFnSym = Mang->getSymbol(MF.getFunction()); + + if (isVerbose()) + LI = &getAnalysis(); +} + +namespace { + // SectionCPs - Keep track the alignment, constpool entries per Section. + struct SectionCPs { + const MCSection *S; + unsigned Alignment; + SmallVector CPEs; + SectionCPs(const MCSection *s, unsigned a) : S(s), Alignment(a) {} + }; +} + +/// EmitConstantPool - Print to the current output stream assembly +/// representations of the constants in the constant pool MCP. This is +/// used to print out constants which have been "spilled to memory" by +/// the code generator. +/// +void AsmPrinter::EmitConstantPool() { + const MachineConstantPool *MCP = MF->getConstantPool(); + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // Calculate sections for constant pool entries. We collect entries to go into + // the same section together to reduce amount of section switch statements. + SmallVector CPSections; + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + const MachineConstantPoolEntry &CPE = CP[i]; + unsigned Align = CPE.getAlignment(); + + SectionKind Kind; + switch (CPE.getRelocationInfo()) { + default: llvm_unreachable("Unknown section kind"); + case 2: Kind = SectionKind::getReadOnlyWithRel(); break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + case 4: Kind = SectionKind::getMergeableConst4(); break; + case 8: Kind = SectionKind::getMergeableConst8(); break; + case 16: Kind = SectionKind::getMergeableConst16();break; + default: Kind = SectionKind::getMergeableConst(); break; + } + } + + const MCSection *S = getObjFileLowering().getSectionForConstant(Kind); + + // The number of sections are small, just do a linear search from the + // last section to the first. + bool Found = false; + unsigned SecIdx = CPSections.size(); + while (SecIdx != 0) { + if (CPSections[--SecIdx].S == S) { + Found = true; + break; + } + } + if (!Found) { + SecIdx = CPSections.size(); + CPSections.push_back(SectionCPs(S, Align)); + } + + if (Align > CPSections[SecIdx].Alignment) + CPSections[SecIdx].Alignment = Align; + CPSections[SecIdx].CPEs.push_back(i); + } + + // Now print stuff into the calculated sections. + for (unsigned i = 0, e = CPSections.size(); i != e; ++i) { + OutStreamer.SwitchSection(CPSections[i].S); + EmitAlignment(Log2_32(CPSections[i].Alignment)); + + unsigned Offset = 0; + for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) { + unsigned CPI = CPSections[i].CPEs[j]; + MachineConstantPoolEntry CPE = CP[CPI]; + + // Emit inter-object padding for alignment. + unsigned AlignMask = CPE.getAlignment() - 1; + unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; + OutStreamer.EmitFill(NewOffset - Offset, 0/*fillval*/, 0/*addrspace*/); + + const Type *Ty = CPE.getType(); + Offset = NewOffset + TM.getTargetData()->getTypeAllocSize(Ty); + OutStreamer.EmitLabel(GetCPISymbol(CPI)); + + if (CPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); + else + EmitGlobalConstant(CPE.Val.ConstVal); + } + } +} + +/// EmitJumpTableInfo - Print assembly representations of the jump tables used +/// by the current function to the current output stream. +/// +void AsmPrinter::EmitJumpTableInfo() { + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + if (MJTI == 0) return; + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return; + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // Pick the directive to use to print the jump table entries, and switch to + // the appropriate section. + const Function *F = MF->getFunction(); + bool JTInDiffSection = false; + if (// In PIC mode, we need to emit the jump table to the same section as the + // function body itself, otherwise the label differences won't make sense. + // FIXME: Need a better predicate for this: what about custom entries? + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + // We should also do if the section name is NULL or function is declared + // in discardable section + // FIXME: this isn't the right predicate, should be based on the MCSection + // for the function. + F->isWeakForLinker()) { + OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM)); + } else { + // Otherwise, drop it in the readonly section. + const MCSection *ReadOnlySection = + getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly()); + OutStreamer.SwitchSection(ReadOnlySection); + JTInDiffSection = true; + } + + EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData()))); + + for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { + const std::vector &JTBBs = JT[JTI].MBBs; + + // If this jump table was deleted, ignore it. + if (JTBBs.empty()) continue; + + // For the EK_LabelDifference32 entry, if the target supports .set, emit a + // .set directive for each unique entry. This reduces the number of + // relocations the assembler will generate for the jump table. + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && + MAI->hasSetDirective()) { + SmallPtrSet EmittedSets; + const TargetLowering *TLI = TM.getTargetLowering(); + const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext); + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { + const MachineBasicBlock *MBB = JTBBs[ii]; + if (!EmittedSets.insert(MBB)) continue; + + // .set LJTSet, LBB32-base + const MCExpr *LHS = + MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); + OutStreamer.EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), + MCBinaryExpr::CreateSub(LHS, Base, OutContext)); + } + } + + // On some targets (e.g. Darwin) we want to emit two consecutive labels + // before each jump table. The first label is never referenced, but tells + // the assembler and linker the extents of the jump table object. The + // second label is actually referenced by the code. + if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) + // FIXME: This doesn't have to have any specific name, just any randomly + // named and numbered 'l' label would work. Simplify GetJTISymbol. + OutStreamer.EmitLabel(GetJTISymbol(JTI, true)); + + OutStreamer.EmitLabel(GetJTISymbol(JTI)); + + for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) + EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); + } +} + +/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the +/// current stream. +void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, + unsigned UID) const { + assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block"); + const MCExpr *Value = 0; + switch (MJTI->getEntryKind()) { + case MachineJumpTableInfo::EK_Inline: + llvm_unreachable("Cannot emit EK_Inline jump table entry"); break; + case MachineJumpTableInfo::EK_Custom32: + Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID, + OutContext); + break; + case MachineJumpTableInfo::EK_BlockAddress: + // EK_BlockAddress - Each entry is a plain address of block, e.g.: + // .word LBB123 + Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); + break; + case MachineJumpTableInfo::EK_GPRel32BlockAddress: { + // EK_GPRel32BlockAddress - Each entry is an address of block, encoded + // with a relocation as gp-relative, e.g.: + // .gprel32 LBB123 + MCSymbol *MBBSym = MBB->getSymbol(); + OutStreamer.EmitGPRel32Value(MCSymbolRefExpr::Create(MBBSym, OutContext)); + return; + } + + case MachineJumpTableInfo::EK_LabelDifference32: { + // EK_LabelDifference32 - Each entry is the address of the block minus + // the address of the jump table. This is used for PIC jump tables where + // gprel32 is not supported. e.g.: + // .word LBB123 - LJTI1_2 + // If the .set directive is supported, this is emitted as: + // .set L4_5_set_123, LBB123 - LJTI1_2 + // .word L4_5_set_123 + + // If we have emitted set directives for the jump table entries, print + // them rather than the entries themselves. If we're emitting PIC, then + // emit the table entries as differences between two text section labels. + if (MAI->hasSetDirective()) { + // If we used .set, reference the .set's symbol. + Value = MCSymbolRefExpr::Create(GetJTSetSymbol(UID, MBB->getNumber()), + OutContext); + break; + } + // Otherwise, use the difference as the jump table entry. + Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); + const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext); + Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext); + break; + } + } + + assert(Value && "Unknown entry kind!"); + + unsigned EntrySize = MJTI->getEntrySize(*TM.getTargetData()); + OutStreamer.EmitValue(Value, EntrySize, /*addrspace*/0); +} + + +/// EmitSpecialLLVMGlobal - Check to see if the specified global is a +/// special global used by LLVM. If so, emit it and return true, otherwise +/// do nothing and return false. +bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { + if (GV->getName() == "llvm.used") { + if (MAI->hasNoDeadStrip()) // No need to emit this at all. + EmitLLVMUsedList(GV->getInitializer()); + return true; + } + + // Ignore debug and non-emitted data. This handles llvm.compiler.used. + if (GV->getSection() == "llvm.metadata" || + GV->hasAvailableExternallyLinkage()) + return true; + + if (!GV->hasAppendingLinkage()) return false; + + assert(GV->hasInitializer() && "Not a special LLVM global!"); + + const TargetData *TD = TM.getTargetData(); + unsigned Align = Log2_32(TD->getPointerPrefAlignment()); + if (GV->getName() == "llvm.global_ctors") { + OutStreamer.SwitchSection(getObjFileLowering().getStaticCtorSection()); + EmitAlignment(Align); + EmitXXStructorList(GV->getInitializer()); + + if (TM.getRelocationModel() == Reloc::Static && + MAI->hasStaticCtorDtorReferenceInStaticMode()) { + StringRef Sym(".constructors_used"); + OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym), + MCSA_Reference); + } + return true; + } + + if (GV->getName() == "llvm.global_dtors") { + OutStreamer.SwitchSection(getObjFileLowering().getStaticDtorSection()); + EmitAlignment(Align); + EmitXXStructorList(GV->getInitializer()); + + if (TM.getRelocationModel() == Reloc::Static && + MAI->hasStaticCtorDtorReferenceInStaticMode()) { + StringRef Sym(".destructors_used"); + OutStreamer.EmitSymbolAttribute(OutContext.GetOrCreateSymbol(Sym), + MCSA_Reference); + } + return true; + } + + return false; +} + +/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each +/// global in the specified llvm.used list for which emitUsedDirectiveFor +/// is true, as being used with this directive. +void AsmPrinter::EmitLLVMUsedList(Constant *List) { + // Should be an array of 'i8*'. + ConstantArray *InitList = dyn_cast(List); + if (InitList == 0) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + const GlobalValue *GV = + dyn_cast(InitList->getOperand(i)->stripPointerCasts()); + if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) + OutStreamer.EmitSymbolAttribute(Mang->getSymbol(GV), MCSA_NoDeadStrip); + } +} + +/// EmitXXStructorList - Emit the ctor or dtor list. This just prints out the +/// function pointers, ignoring the init priority. +void AsmPrinter::EmitXXStructorList(Constant *List) { + // Should be an array of '{ int, void ()* }' structs. The first value is the + // init priority, which we ignore. + if (!isa(List)) return; + ConstantArray *InitList = cast(List); + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + return; // Found a null terminator, exit printing. + // Emit the function pointer. + EmitGlobalConstant(CS->getOperand(1)); + } +} + +//===--------------------------------------------------------------------===// +// Emission and print routines +// + +/// EmitInt8 - Emit a byte directive and value. +/// +void AsmPrinter::EmitInt8(int Value) const { + OutStreamer.EmitIntValue(Value, 1, 0/*addrspace*/); +} + +/// EmitInt16 - Emit a short directive and value. +/// +void AsmPrinter::EmitInt16(int Value) const { + OutStreamer.EmitIntValue(Value, 2, 0/*addrspace*/); +} + +/// EmitInt32 - Emit a long directive and value. +/// +void AsmPrinter::EmitInt32(int Value) const { + OutStreamer.EmitIntValue(Value, 4, 0/*addrspace*/); +} + +/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size +/// in bytes of the directive is specified by Size and Hi/Lo specify the +/// labels. This implicitly uses .set if it is available. +void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) const { + // Get the Hi-Lo expression. + const MCExpr *Diff = + MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(Hi, OutContext), + MCSymbolRefExpr::Create(Lo, OutContext), + OutContext); + + if (!MAI->hasSetDirective()) { + OutStreamer.EmitValue(Diff, Size, 0/*AddrSpace*/); + return; + } + + // Otherwise, emit with .set (aka assignment). + MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++); + OutStreamer.EmitAssignment(SetLabel, Diff); + OutStreamer.EmitSymbolValue(SetLabel, Size, 0/*AddrSpace*/); +} + +/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo" +/// where the size in bytes of the directive is specified by Size and Hi/Lo +/// specify the labels. This implicitly uses .set if it is available. +void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, + const MCSymbol *Lo, unsigned Size) + const { + + // Emit Hi+Offset - Lo + // Get the Hi+Offset expression. + const MCExpr *Plus = + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Hi, OutContext), + MCConstantExpr::Create(Offset, OutContext), + OutContext); + + // Get the Hi+Offset-Lo expression. + const MCExpr *Diff = + MCBinaryExpr::CreateSub(Plus, + MCSymbolRefExpr::Create(Lo, OutContext), + OutContext); + + if (!MAI->hasSetDirective()) + OutStreamer.EmitValue(Diff, 4, 0/*AddrSpace*/); + else { + // Otherwise, emit with .set (aka assignment). + MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++); + OutStreamer.EmitAssignment(SetLabel, Diff); + OutStreamer.EmitSymbolValue(SetLabel, 4, 0/*AddrSpace*/); + } +} + +/// EmitLabelPlusOffset - Emit something like ".long Label+Offset" +/// where the size in bytes of the directive is specified by Size and Label +/// specifies the label. This implicitly uses .set if it is available. +void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, + unsigned Size) + const { + + // Emit Label+Offset + const MCExpr *Plus = + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Label, OutContext), + MCConstantExpr::Create(Offset, OutContext), + OutContext); + + OutStreamer.EmitValue(Plus, 4, 0/*AddrSpace*/); +} + + +//===----------------------------------------------------------------------===// + +// EmitAlignment - Emit an alignment directive to the specified power of +// two boundary. For example, if you pass in 3 here, you will get an 8 +// byte alignment. If a global value is specified, and if that global has +// an explicit alignment requested, it will override the alignment request +// if required for correctness. +// +void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { + if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getTargetData(), NumBits); + + if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. + + if (getCurrentSection()->getKind().isText()) + OutStreamer.EmitCodeAlignment(1 << NumBits); + else + OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0); +} + +//===----------------------------------------------------------------------===// +// Constant emission. +//===----------------------------------------------------------------------===// + +/// LowerConstant - Lower the specified LLVM Constant to an MCExpr. +/// +static const MCExpr *LowerConstant(const Constant *CV, AsmPrinter &AP) { + MCContext &Ctx = AP.OutContext; + + if (CV->isNullValue() || isa(CV)) + return MCConstantExpr::Create(0, Ctx); + + if (const ConstantInt *CI = dyn_cast(CV)) + return MCConstantExpr::Create(CI->getZExtValue(), Ctx); + + if (const GlobalValue *GV = dyn_cast(CV)) + return MCSymbolRefExpr::Create(AP.Mang->getSymbol(GV), Ctx); + + if (const BlockAddress *BA = dyn_cast(CV)) + return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx); + + const ConstantExpr *CE = dyn_cast(CV); + if (CE == 0) { + llvm_unreachable("Unknown constant value to lower!"); + return MCConstantExpr::Create(0, Ctx); + } + + switch (CE->getOpcode()) { + default: + // If the code isn't optimized, there may be outstanding folding + // opportunities. Attempt to fold the expression using TargetData as a + // last resort before giving up. + if (Constant *C = + ConstantFoldConstantExpression(CE, AP.TM.getTargetData())) + if (C != CE) + return LowerConstant(C, AP); + + // Otherwise report the problem to the user. + { + std::string S; + raw_string_ostream OS(S); + OS << "Unsupported expression in static initializer: "; + WriteAsOperand(OS, CE, /*PrintType=*/false, + !AP.MF ? 0 : AP.MF->getFunction()->getParent()); + report_fatal_error(OS.str()); + } + return MCConstantExpr::Create(0, Ctx); + case Instruction::GetElementPtr: { + const TargetData &TD = *AP.TM.getTargetData(); + // Generate a symbolic expression for the byte address + const Constant *PtrVal = CE->getOperand(0); + SmallVector IdxVec(CE->op_begin()+1, CE->op_end()); + int64_t Offset = TD.getIndexedOffset(PtrVal->getType(), &IdxVec[0], + IdxVec.size()); + + const MCExpr *Base = LowerConstant(CE->getOperand(0), AP); + if (Offset == 0) + return Base; + + // Truncate/sext the offset to the pointer size. + if (TD.getPointerSizeInBits() != 64) { + int SExtAmount = 64-TD.getPointerSizeInBits(); + Offset = (Offset << SExtAmount) >> SExtAmount; + } + + return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx), + Ctx); + } + + case Instruction::Trunc: + // We emit the value and depend on the assembler to truncate the generated + // expression properly. This is important for differences between + // blockaddress labels. Since the two labels are in the same function, it + // is reasonable to treat their delta as a 32-bit value. + // FALL THROUGH. + case Instruction::BitCast: + return LowerConstant(CE->getOperand(0), AP); + + case Instruction::IntToPtr: { + const TargetData &TD = *AP.TM.getTargetData(); + // Handle casts to pointers by changing them into casts to the appropriate + // integer type. This promotes constant folding and simplifies this code. + Constant *Op = CE->getOperand(0); + Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()), + false/*ZExt*/); + return LowerConstant(Op, AP); + } + + case Instruction::PtrToInt: { + const TargetData &TD = *AP.TM.getTargetData(); + // Support only foldable casts to/from pointers that can be eliminated by + // changing the pointer to the appropriately sized integer type. + Constant *Op = CE->getOperand(0); + const Type *Ty = CE->getType(); + + const MCExpr *OpExpr = LowerConstant(Op, AP); + + // We can emit the pointer value into this slot if the slot is an + // integer slot equal to the size of the pointer. + if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType())) + return OpExpr; + + // Otherwise the pointer is smaller than the resultant integer, mask off + // the high bits so we are sure to get a proper truncation if the input is + // a constant expr. + unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType()); + const MCExpr *MaskExpr = MCConstantExpr::Create(~0ULL >> (64-InBits), Ctx); + return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx); + } + + // The MC library also has a right-shift operator, but it isn't consistently + // signed or unsigned between different targets. + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::SDiv: + case Instruction::SRem: + case Instruction::Shl: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP); + const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP); + switch (CE->getOpcode()) { + default: llvm_unreachable("Unknown binary operator constant cast expr"); + case Instruction::Add: return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx); + case Instruction::Sub: return MCBinaryExpr::CreateSub(LHS, RHS, Ctx); + case Instruction::Mul: return MCBinaryExpr::CreateMul(LHS, RHS, Ctx); + case Instruction::SDiv: return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx); + case Instruction::SRem: return MCBinaryExpr::CreateMod(LHS, RHS, Ctx); + case Instruction::Shl: return MCBinaryExpr::CreateShl(LHS, RHS, Ctx); + case Instruction::And: return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx); + case Instruction::Or: return MCBinaryExpr::CreateOr (LHS, RHS, Ctx); + case Instruction::Xor: return MCBinaryExpr::CreateXor(LHS, RHS, Ctx); + } + } + } +} + +static void EmitGlobalConstantImpl(const Constant *C, unsigned AddrSpace, + AsmPrinter &AP); + +static void EmitGlobalConstantArray(const ConstantArray *CA, unsigned AddrSpace, + AsmPrinter &AP) { + if (AddrSpace != 0 || !CA->isString()) { + // Not a string. Print the values in successive locations + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + EmitGlobalConstantImpl(CA->getOperand(i), AddrSpace, AP); + return; + } + + // Otherwise, it can be emitted as .ascii. + SmallVector TmpVec; + TmpVec.reserve(CA->getNumOperands()); + for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) + TmpVec.push_back(cast(CA->getOperand(i))->getZExtValue()); + + AP.OutStreamer.EmitBytes(StringRef(TmpVec.data(), TmpVec.size()), AddrSpace); +} + +static void EmitGlobalConstantVector(const ConstantVector *CV, + unsigned AddrSpace, AsmPrinter &AP) { + for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i) + EmitGlobalConstantImpl(CV->getOperand(i), AddrSpace, AP); +} + +static void EmitGlobalConstantStruct(const ConstantStruct *CS, + unsigned AddrSpace, AsmPrinter &AP) { + // Print the fields in successive locations. Pad to align if needed! + const TargetData *TD = AP.TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CS->getType()); + const StructLayout *Layout = TD->getStructLayout(CS->getType()); + uint64_t SizeSoFar = 0; + for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) { + const Constant *Field = CS->getOperand(i); + + // Check if padding is needed and insert one or more 0s. + uint64_t FieldSize = TD->getTypeAllocSize(Field->getType()); + uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1)) + - Layout->getElementOffset(i)) - FieldSize; + SizeSoFar += FieldSize + PadSize; + + // Now print the actual field value. + EmitGlobalConstantImpl(Field, AddrSpace, AP); + + // Insert padding - this may include padding to increase the size of the + // current field up to the ABI size (if the struct is not packed) as well + // as padding to ensure that the next field starts at the right offset. + AP.OutStreamer.EmitZeros(PadSize, AddrSpace); + } + assert(SizeSoFar == Layout->getSizeInBytes() && + "Layout of constant struct may be incorrect!"); +} + +static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace, + AsmPrinter &AP) { + // FP Constants are printed as integer constants to avoid losing + // precision. + if (CFP->getType()->isDoubleTy()) { + if (AP.isVerbose()) { + double Val = CFP->getValueAPF().convertToDouble(); + AP.OutStreamer.GetCommentOS() << "double " << Val << '\n'; + } + + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); + return; + } + + if (CFP->getType()->isFloatTy()) { + if (AP.isVerbose()) { + float Val = CFP->getValueAPF().convertToFloat(); + AP.OutStreamer.GetCommentOS() << "float " << Val << '\n'; + } + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + AP.OutStreamer.EmitIntValue(Val, 4, AddrSpace); + return; + } + + if (CFP->getType()->isX86_FP80Ty()) { + // all long double variants are printed as hex + // API needed to prevent premature destruction + APInt API = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = API.getRawData(); + if (AP.isVerbose()) { + // Convert to double so we can print the approximate val as a comment. + APFloat DoubleVal = CFP->getValueAPF(); + bool ignored; + DoubleVal.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, + &ignored); + AP.OutStreamer.GetCommentOS() << "x86_fp80 ~= " + << DoubleVal.convertToDouble() << '\n'; + } + + if (AP.TM.getTargetData()->isBigEndian()) { + AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + } else { + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[1], 2, AddrSpace); + } + + // Emit the tail padding for the long double. + const TargetData &TD = *AP.TM.getTargetData(); + AP.OutStreamer.EmitZeros(TD.getTypeAllocSize(CFP->getType()) - + TD.getTypeStoreSize(CFP->getType()), AddrSpace); + return; + } + + assert(CFP->getType()->isPPC_FP128Ty() && + "Floating point constant type not handled"); + // All long double variants are printed as hex + // API needed to prevent premature destruction. + APInt API = CFP->getValueAPF().bitcastToAPInt(); + const uint64_t *p = API.getRawData(); + if (AP.TM.getTargetData()->isBigEndian()) { + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace); + } else { + AP.OutStreamer.EmitIntValue(p[1], 8, AddrSpace); + AP.OutStreamer.EmitIntValue(p[0], 8, AddrSpace); + } +} + +static void EmitGlobalConstantLargeInt(const ConstantInt *CI, + unsigned AddrSpace, AsmPrinter &AP) { + const TargetData *TD = AP.TM.getTargetData(); + unsigned BitWidth = CI->getBitWidth(); + assert((BitWidth & 63) == 0 && "only support multiples of 64-bits"); + + // We don't expect assemblers to support integer data directives + // for more than 64 bits, so we emit the data in at most 64-bit + // quantities at a time. + const uint64_t *RawData = CI->getValue().getRawData(); + for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { + uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i]; + AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace); + } +} + +static void EmitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace, + AsmPrinter &AP) { + if (isa(CV) || isa(CV)) { + uint64_t Size = AP.TM.getTargetData()->getTypeAllocSize(CV->getType()); + return AP.OutStreamer.EmitZeros(Size, AddrSpace); + } + + if (const ConstantInt *CI = dyn_cast(CV)) { + unsigned Size = AP.TM.getTargetData()->getTypeAllocSize(CV->getType()); + switch (Size) { + case 1: + case 2: + case 4: + case 8: + if (AP.isVerbose()) + AP.OutStreamer.GetCommentOS() << format("0x%llx\n", CI->getZExtValue()); + AP.OutStreamer.EmitIntValue(CI->getZExtValue(), Size, AddrSpace); + return; + default: + EmitGlobalConstantLargeInt(CI, AddrSpace, AP); + return; + } + } + + if (const ConstantArray *CVA = dyn_cast(CV)) + return EmitGlobalConstantArray(CVA, AddrSpace, AP); + + if (const ConstantStruct *CVS = dyn_cast(CV)) + return EmitGlobalConstantStruct(CVS, AddrSpace, AP); + + if (const ConstantFP *CFP = dyn_cast(CV)) + return EmitGlobalConstantFP(CFP, AddrSpace, AP); + + if (isa(CV)) { + unsigned Size = AP.TM.getTargetData()->getTypeAllocSize(CV->getType()); + AP.OutStreamer.EmitIntValue(0, Size, AddrSpace); + return; + } + + if (const ConstantVector *V = dyn_cast(CV)) + return EmitGlobalConstantVector(V, AddrSpace, AP); + + // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it + // thread the streamer with EmitValue. + AP.OutStreamer.EmitValue(LowerConstant(CV, AP), + AP.TM.getTargetData()->getTypeAllocSize(CV->getType()), + AddrSpace); +} + +/// EmitGlobalConstant - Print a general LLVM constant to the .s file. +void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) { + uint64_t Size = TM.getTargetData()->getTypeAllocSize(CV->getType()); + if (Size) + EmitGlobalConstantImpl(CV, AddrSpace, *this); + else if (MAI->hasSubsectionsViaSymbols()) { + // If the global has zero size, emit a single byte so that two labels don't + // look like they are at the same location. + OutStreamer.EmitIntValue(0, 1, AddrSpace); + } +} + +void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + // Target doesn't support this yet! + llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); +} + +void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { + if (Offset > 0) + OS << '+' << Offset; + else if (Offset < 0) + OS << Offset; +} + +//===----------------------------------------------------------------------===// +// Symbol Lowering Routines. +//===----------------------------------------------------------------------===// + +/// GetTempSymbol - Return the MCSymbol corresponding to the assembler +/// temporary label with the specified stem and unique ID. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + + Name + Twine(ID)); +} + +/// GetTempSymbol - Return an assembler temporary label with the specified +/// stem. +MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const { + return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+ + Name); +} + + +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const { + return MMI->getAddrLabelSymbol(BA->getBasicBlock()); +} + +MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const { + return MMI->getAddrLabelSymbol(BB); +} + +/// GetCPISymbol - Return the symbol for the specified constant pool entry. +MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { + return OutContext.GetOrCreateSymbol + (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber()) + + "_" + Twine(CPID)); +} + +/// GetJTISymbol - Return the symbol for the specified jump table entry. +MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { + return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate); +} + +/// GetJTSetSymbol - Return the symbol for the specified jump table .set +/// FIXME: privatize to AsmPrinter. +MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { + return OutContext.GetOrCreateSymbol + (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" + + Twine(UID) + "_set_" + Twine(MBBID)); +} + +/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with +/// global value name as its base, with the specified suffix, and where the +/// symbol is forced to have private linkage if ForcePrivate is true. +MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix, + bool ForcePrivate) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, GV, ForcePrivate); + NameStr.append(Suffix.begin(), Suffix.end()); + return OutContext.GetOrCreateSymbol(NameStr.str()); +} + +/// GetExternalSymbolSymbol - Return the MCSymbol for the specified +/// ExternalSymbol. +MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, Sym); + return OutContext.GetOrCreateSymbol(NameStr.str()); +} + + + +/// PrintParentLoopComment - Print comments about parent loops of this one. +static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop, + unsigned FunctionNumber) { + if (Loop == 0) return; + PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber); + OS.indent(Loop->getLoopDepth()*2) + << "Parent Loop BB" << FunctionNumber << "_" + << Loop->getHeader()->getNumber() + << " Depth=" << Loop->getLoopDepth() << '\n'; +} + + +/// PrintChildLoopComment - Print comments about child loops within +/// the loop for this basic block, with nesting. +static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, + unsigned FunctionNumber) { + // Add child loop information + for (MachineLoop::iterator CL = Loop->begin(), E = Loop->end();CL != E; ++CL){ + OS.indent((*CL)->getLoopDepth()*2) + << "Child Loop BB" << FunctionNumber << "_" + << (*CL)->getHeader()->getNumber() << " Depth " << (*CL)->getLoopDepth() + << '\n'; + PrintChildLoopComment(OS, *CL, FunctionNumber); + } +} + +/// EmitBasicBlockLoopComments - Pretty-print comments for basic blocks. +static void EmitBasicBlockLoopComments(const MachineBasicBlock &MBB, + const MachineLoopInfo *LI, + const AsmPrinter &AP) { + // Add loop depth information + const MachineLoop *Loop = LI->getLoopFor(&MBB); + if (Loop == 0) return; + + MachineBasicBlock *Header = Loop->getHeader(); + assert(Header && "No header for loop"); + + // If this block is not a loop header, just print out what is the loop header + // and return. + if (Header != &MBB) { + AP.OutStreamer.AddComment(" in Loop: Header=BB" + + Twine(AP.getFunctionNumber())+"_" + + Twine(Loop->getHeader()->getNumber())+ + " Depth="+Twine(Loop->getLoopDepth())); + return; + } + + // Otherwise, it is a loop header. Print out information about child and + // parent loops. + raw_ostream &OS = AP.OutStreamer.GetCommentOS(); + + PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber()); + + OS << "=>"; + OS.indent(Loop->getLoopDepth()*2-2); + + OS << "This "; + if (Loop->empty()) + OS << "Inner "; + OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n'; + + PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); +} + + +/// EmitBasicBlockStart - This method prints the label for the specified +/// MachineBasicBlock, an alignment (if present) and a comment describing +/// it if appropriate. +void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { + // Emit an alignment directive for this block, if needed. + if (unsigned Align = MBB->getAlignment()) + EmitAlignment(Log2_32(Align)); + + // If the block has its address taken, emit any labels that were used to + // reference the block. It is possible that there is more than one label + // here, because multiple LLVM BB's may have been RAUW'd to this block after + // the references were generated. + if (MBB->hasAddressTaken()) { + const BasicBlock *BB = MBB->getBasicBlock(); + if (isVerbose()) + OutStreamer.AddComment("Block address taken"); + + std::vector Syms = MMI->getAddrLabelSymbolToEmit(BB); + + for (unsigned i = 0, e = Syms.size(); i != e; ++i) + OutStreamer.EmitLabel(Syms[i]); + } + + // Print the main label for the block. + if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { + if (isVerbose() && OutStreamer.hasRawTextSupport()) { + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) + OutStreamer.AddComment("%" + BB->getName()); + + EmitBasicBlockLoopComments(*MBB, LI, *this); + + // NOTE: Want this comment at start of line, don't emit with AddComment. + OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" + + Twine(MBB->getNumber()) + ":"); + } + } else { + if (isVerbose()) { + if (const BasicBlock *BB = MBB->getBasicBlock()) + if (BB->hasName()) + OutStreamer.AddComment("%" + BB->getName()); + EmitBasicBlockLoopComments(*MBB, LI, *this); + } + + OutStreamer.EmitLabel(MBB->getSymbol()); + } +} + +void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition) const { + MCSymbolAttr Attr = MCSA_Invalid; + + switch (Visibility) { + default: break; + case GlobalValue::HiddenVisibility: + if (IsDefinition) + Attr = MAI->getHiddenVisibilityAttr(); + else + Attr = MAI->getHiddenDeclarationVisibilityAttr(); + break; + case GlobalValue::ProtectedVisibility: + Attr = MAI->getProtectedVisibilityAttr(); + break; + } + + if (Attr != MCSA_Invalid) + OutStreamer.EmitSymbolAttribute(Sym, Attr); +} + +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool AsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; + + // Otherwise, check the last instruction. + const MachineInstr &LastInst = Pred->back(); + return !LastInst.getDesc().isBarrier(); +} + + + +GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { + if (!S->usesMetadata()) + return 0; + + gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); + gcp_map_type::iterator GCPI = GCMap.find(S); + if (GCPI != GCMap.end()) + return GCPI->second; + + const char *Name = S->getName().c_str(); + + for (GCMetadataPrinterRegistry::iterator + I = GCMetadataPrinterRegistry::begin(), + E = GCMetadataPrinterRegistry::end(); I != E; ++I) + if (strcmp(Name, I->getName()) == 0) { + GCMetadataPrinter *GMP = I->instantiate(); + GMP->S = S; + GCMap.insert(std::make_pair(S, GMP)); + return GMP; + } + + report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); + return 0; +} + diff --git a/final/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/final/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp new file mode 100644 index 00000000000..98a1bf2f1ce --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -0,0 +1,318 @@ +//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===// +// +// 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 Dwarf emissions parts of AsmPrinter. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Dwarf.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Dwarf Emission Helper Routines +//===----------------------------------------------------------------------===// + +/// EmitSLEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitSLEB128(int Value, const char *Desc) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + if (MAI->hasLEB128()) { + OutStreamer.EmitSLEB128IntValue(Value); + return; + } + + // If we don't have .sleb128, emit as .bytes. + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned char Byte = static_cast(Value & 0x7f); + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + if (IsMore) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (IsMore); +} + +/// EmitULEB128 - emit the specified signed leb128 value. +void AsmPrinter::EmitULEB128(unsigned Value, const char *Desc, + unsigned PadTo) const { + if (isVerbose() && Desc) + OutStreamer.AddComment(Desc); + + // FIXME: Should we add a PadTo option to the streamer? + if (MAI->hasLEB128() && PadTo == 0) { + OutStreamer.EmitULEB128IntValue(Value); + return; + } + + // If we don't have .uleb128 or we want to emit padding, emit as .bytes. + do { + unsigned char Byte = static_cast(Value & 0x7f); + Value >>= 7; + if (Value || PadTo != 0) Byte |= 0x80; + OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); + } while (Value); + + if (PadTo) { + if (PadTo > 1) + OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); + OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); + } +} + +/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. +void AsmPrinter::EmitCFAByte(unsigned Val) const { + if (isVerbose()) { + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + OutStreamer.AddComment("DW_CFA_offset + Reg (" + + Twine(Val-dwarf::DW_CFA_offset) + ")"); + else + OutStreamer.AddComment(dwarf::CallFrameString(Val)); + } + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +static const char *DecodeDWARFEncoding(unsigned Encoding) { + switch (Encoding) { + case dwarf::DW_EH_PE_absptr: return "absptr"; + case dwarf::DW_EH_PE_omit: return "omit"; + case dwarf::DW_EH_PE_pcrel: return "pcrel"; + case dwarf::DW_EH_PE_udata4: return "udata4"; + case dwarf::DW_EH_PE_udata8: return "udata8"; + case dwarf::DW_EH_PE_sdata4: return "sdata4"; + case dwarf::DW_EH_PE_sdata8: return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + return "indirect pcrel udata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + return "indirect pcrel sdata4"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + return "indirect pcrel udata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + return "indirect pcrel sdata8"; + } + + return ""; +} + + +/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an +/// encoding. If verbose assembly output is enabled, we output comments +/// describing the encoding. Desc is an optional string saying what the +/// encoding is specifying (e.g. "LSDA"). +void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { + if (isVerbose()) { + if (Desc != 0) + OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + Twine(DecodeDWARFEncoding(Val))); + else + OutStreamer.AddComment(Twine("Encoding = ") + + DecodeDWARFEncoding(Val)); + } + + OutStreamer.EmitIntValue(Val, 1, 0/*addrspace*/); +} + +/// GetSizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + default: assert(0 && "Invalid encoded value."); + case dwarf::DW_EH_PE_absptr: return TM.getTargetData()->getPointerSize(); + case dwarf::DW_EH_PE_udata2: return 2; + case dwarf::DW_EH_PE_udata4: return 4; + case dwarf::DW_EH_PE_udata8: return 8; + } +} + +void AsmPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfReference(Sym, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitAbsValue(Exp, GetSizeOfEncodedValue(Encoding)); +} + +void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + const MCExpr *Exp = + TLOF.getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); + OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding), /*addrspace*/0); +} + +/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of its +/// section. This can be done with a special directive if the target supports +/// it (e.g. cygwin) or by emitting it as an offset from a label at the start +/// of the section. +/// +/// SectionLabel is a temporary label emitted at the start of the section that +/// Label lives in. +void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const { + // On COFF targets, we have to emit the special .secrel32 directive. + if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { + // FIXME: MCize. + OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); + return; + } + + // Get the section that we're referring to, based on SectionLabel. + const MCSection &Section = SectionLabel->getSection(); + + // If Label has already been emitted, verify that it is in the same section as + // section label for sanity. + assert((!Label->isInSection() || &Label->getSection() == &Section) && + "Section offset using wrong section base for label"); + + // If the section in question will end up with an address of 0 anyway, we can + // just emit an absolute reference to save a relocation. + if (Section.isBaseAddressKnownZero()) { + OutStreamer.EmitSymbolValue(Label, 4, 0/*AddrSpace*/); + return; + } + + // Otherwise, emit it as a label difference from the start of the section. + EmitLabelDifference(Label, SectionLabel, 4); +} + +//===----------------------------------------------------------------------===// +// Dwarf Lowering Routines +//===----------------------------------------------------------------------===// + + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +void AsmPrinter::EmitFrameMoves(const std::vector &Moves, + MCSymbol *BaseLabel, bool isEH) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + + int stackGrowth = TM.getTargetData()->getPointerSize(); + if (TM.getFrameLowering()->getStackGrowthDirection() != + TargetFrameLowering::StackGrowsUp) + stackGrowth *= -1; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + EmitCFAByte(dwarf::DW_CFA_advance_loc4); + EmitLabelDifference(ThisSym, BaseLabel, 4); + BaseLabel = ThisSym; + } + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + EmitCFAByte(dwarf::DW_CFA_def_cfa_offset); + } else { + EmitCFAByte(dwarf::DW_CFA_def_cfa); + EmitULEB128(RI->getDwarfRegNum(Src.getReg(), isEH), "Register"); + } + + EmitULEB128(-Src.getOffset(), "Offset"); + continue; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + EmitCFAByte(dwarf::DW_CFA_def_cfa_register); + EmitULEB128(RI->getDwarfRegNum(Dst.getReg(), isEH), "Register"); + continue; + } + + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + EmitCFAByte(dwarf::DW_CFA_offset_extended_sf); + EmitULEB128(Reg, "Reg"); + EmitSLEB128(Offset, "Offset"); + } else if (Reg < 64) { + EmitCFAByte(dwarf::DW_CFA_offset + Reg); + EmitULEB128(Offset, "Offset"); + } else { + EmitCFAByte(dwarf::DW_CFA_offset_extended); + EmitULEB128(Reg, "Reg"); + EmitULEB128(Offset, "Offset"); + } + } +} + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +void AsmPrinter::EmitCFIFrameMoves(const std::vector &Moves) const { + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + + int stackGrowth = TM.getTargetData()->getPointerSize(); + if (TM.getFrameLowering()->getStackGrowthDirection() != + TargetFrameLowering::StackGrowsUp) + stackGrowth *= -1; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset()); + } else { + assert("Machine move not supported yet"); + // Reg + Offset + } + } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + OutStreamer.EmitCFIDefCfaRegister(RI->getDwarfRegNum(Dst.getReg(), true)); + } else { + assert(!Dst.isReg() && "Machine move not supported yet."); + OutStreamer.EmitCFIOffset(RI->getDwarfRegNum(Src.getReg(), true), + Dst.getOffset()); + } + } +} diff --git a/final/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/final/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp new file mode 100644 index 00000000000..c6166e2365a --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -0,0 +1,409 @@ +//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===// +// +// 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 inline assembler pieces of the AsmPrinter class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Constants.h" +#include "llvm/InlineAsm.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct SrcMgrDiagInfo { + const MDNode *LocInfo; + LLVMContext::InlineAsmDiagHandlerTy DiagHandler; + void *DiagContext; + }; +} + +/// SrcMgrDiagHandler - This callback is invoked when the SourceMgr for an +/// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo +/// struct above. +static void SrcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { + SrcMgrDiagInfo *DiagInfo = static_cast(diagInfo); + assert(DiagInfo && "Diagnostic context not passed down?"); + + // If the inline asm had metadata associated with it, pull out a location + // cookie corresponding to which line the error occurred on. + unsigned LocCookie = 0; + if (const MDNode *LocInfo = DiagInfo->LocInfo) { + unsigned ErrorLine = Diag.getLineNo()-1; + if (ErrorLine >= LocInfo->getNumOperands()) + ErrorLine = 0; + + if (LocInfo->getNumOperands() != 0) + if (const ConstantInt *CI = + dyn_cast(LocInfo->getOperand(ErrorLine))) + LocCookie = CI->getZExtValue(); + } + + DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); +} + +/// EmitInlineAsm - Emit a blob of inline asm to the output streamer. +void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode) const { + assert(!Str.empty() && "Can't emit empty inline asm block"); + + // Remember if the buffer is nul terminated or not so we can avoid a copy. + bool isNullTerminated = Str.back() == 0; + if (isNullTerminated) + Str = Str.substr(0, Str.size()-1); + + // If the output streamer is actually a .s file, just emit the blob textually. + // This is useful in case the asm parser doesn't handle something but the + // system assembler does. + if (OutStreamer.hasRawTextSupport()) { + OutStreamer.EmitRawText(Str); + return; + } + + SourceMgr SrcMgr; + SrcMgrDiagInfo DiagInfo; + + // If the current LLVMContext has an inline asm handler, set it in SourceMgr. + LLVMContext &LLVMCtx = MMI->getModule()->getContext(); + bool HasDiagHandler = false; + if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { + // If the source manager has an issue, we arrange for SrcMgrDiagHandler + // to be invoked, getting DiagInfo passed into it. + DiagInfo.LocInfo = LocMDNode; + DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); + DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); + SrcMgr.setDiagHandler(SrcMgrDiagHandler, &DiagInfo); + HasDiagHandler = true; + } + + MemoryBuffer *Buffer; + if (isNullTerminated) + Buffer = MemoryBuffer::getMemBuffer(Str, ""); + else + Buffer = MemoryBuffer::getMemBufferCopy(Str, ""); + + // Tell SrcMgr about this buffer, it takes ownership of the buffer. + SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + + OwningPtr Parser(createMCAsmParser(TM.getTarget(), SrcMgr, + OutContext, OutStreamer, + *MAI)); + OwningPtr TAP(TM.getTarget().createAsmParser(*Parser, TM)); + if (!TAP) + report_fatal_error("Inline asm not supported by this streamer because" + " we don't have an asm parser for this target\n"); + Parser->setTargetParser(*TAP.get()); + + // Don't implicitly switch to the text section before the asm. + int Res = Parser->Run(/*NoInitialTextSection*/ true, + /*NoFinalize*/ true); + if (Res && !HasDiagHandler) + report_fatal_error("Error parsing inline asm\n"); +} + + +/// EmitInlineAsm - This method formats and emits the specified machine +/// instruction that is an inline asm. +void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { + assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms"); + + unsigned NumOperands = MI->getNumOperands(); + + // Count the number of register definitions to find the asm string. + unsigned NumDefs = 0; + for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef(); + ++NumDefs) + assert(NumDefs != NumOperands-2 && "No asm string?"); + + assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?"); + + // Disassemble the AsmStr, printing out the literal pieces, the operands, etc. + const char *AsmStr = MI->getOperand(NumDefs).getSymbolName(); + + // If this asmstr is empty, just print the #APP/#NOAPP markers. + // These are useful to see where empty asm's wound up. + if (AsmStr[0] == 0) { + // Don't emit the comments if writing to a .o file. + if (!OutStreamer.hasRawTextSupport()) return; + + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); + return; + } + + // Emit the #APP start marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmStart()); + + // Get the !srcloc metadata node if we have it, and decode the loc cookie from + // it. + unsigned LocCookie = 0; + const MDNode *LocMD = 0; + for (unsigned i = MI->getNumOperands(); i != 0; --i) { + if (MI->getOperand(i-1).isMetadata() && + (LocMD = MI->getOperand(i-1).getMetadata()) && + LocMD->getNumOperands() != 0) { + if (const ConstantInt *CI = dyn_cast(LocMD->getOperand(0))) { + LocCookie = CI->getZExtValue(); + break; + } + } + } + + // Emit the inline asm to a temporary string so we can emit it through + // EmitInlineAsm. + SmallString<256> StringData; + raw_svector_ostream OS(StringData); + + OS << '\t'; + + // The variant of the current asmprinter. + int AsmPrinterVariant = MAI->getAssemblerDialect(); + + int CurVariant = -1; // The number of the {.|.|.} region we are in. + const char *LastEmitted = AsmStr; // One past the last character emitted. + + while (*LastEmitted) { + switch (*LastEmitted) { + default: { + // Not a special case, emit the string section literally. + const char *LiteralEnd = LastEmitted+1; + while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' && + *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n') + ++LiteralEnd; + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS.write(LastEmitted, LiteralEnd-LastEmitted); + LastEmitted = LiteralEnd; + break; + } + case '\n': + ++LastEmitted; // Consume newline character. + OS << '\n'; // Indent code with newline. + break; + case '$': { + ++LastEmitted; // Consume '$' character. + bool Done = true; + + // Handle escapes. + switch (*LastEmitted) { + default: Done = false; break; + case '$': // $$ -> $ + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) + OS << '$'; + ++LastEmitted; // Consume second '$' character. + break; + case '(': // $( -> same as GCC's { character. + ++LastEmitted; // Consume '(' character. + if (CurVariant != -1) + report_fatal_error("Nested variants found in inline asm string: '" + + Twine(AsmStr) + "'"); + CurVariant = 0; // We're in the first variant now. + break; + case '|': + ++LastEmitted; // consume '|' character. + if (CurVariant == -1) + OS << '|'; // this is gcc's behavior for | outside a variant + else + ++CurVariant; // We're in the next variant. + break; + case ')': // $) -> same as GCC's } char. + ++LastEmitted; // consume ')' character. + if (CurVariant == -1) + OS << '}'; // this is gcc's behavior for } outside a variant + else + CurVariant = -1; + break; + } + if (Done) break; + + bool HasCurlyBraces = false; + if (*LastEmitted == '{') { // ${variable} + ++LastEmitted; // Consume '{' character. + HasCurlyBraces = true; + } + + // If we have ${:foo}, then this is not a real operand reference, it is a + // "magic" string reference, just like in .td files. Arrange to call + // PrintSpecial. + if (HasCurlyBraces && *LastEmitted == ':') { + ++LastEmitted; + const char *StrStart = LastEmitted; + const char *StrEnd = strchr(StrStart, '}'); + if (StrEnd == 0) + report_fatal_error("Unterminated ${:foo} operand in inline asm" + " string: '" + Twine(AsmStr) + "'"); + + std::string Val(StrStart, StrEnd); + PrintSpecial(MI, OS, Val.c_str()); + LastEmitted = StrEnd+1; + break; + } + + const char *IDStart = LastEmitted; + const char *IDEnd = IDStart; + while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd; + + unsigned Val; + if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val)) + report_fatal_error("Bad $ operand number in inline asm string: '" + + Twine(AsmStr) + "'"); + LastEmitted = IDEnd; + + char Modifier[2] = { 0, 0 }; + + if (HasCurlyBraces) { + // If we have curly braces, check for a modifier character. This + // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm. + if (*LastEmitted == ':') { + ++LastEmitted; // Consume ':' character. + if (*LastEmitted == 0) + report_fatal_error("Bad ${:} expression in inline asm string: '" + + Twine(AsmStr) + "'"); + + Modifier[0] = *LastEmitted; + ++LastEmitted; // Consume modifier character. + } + + if (*LastEmitted != '}') + report_fatal_error("Bad ${} expression in inline asm string: '" + + Twine(AsmStr) + "'"); + ++LastEmitted; // Consume '}' character. + } + + if (Val >= NumOperands-1) + report_fatal_error("Invalid $ operand number in inline asm string: '" + + Twine(AsmStr) + "'"); + + // Okay, we finally have a value number. Ask the target to print this + // operand! + if (CurVariant == -1 || CurVariant == AsmPrinterVariant) { + unsigned OpNo = InlineAsm::MIOp_FirstOperand; + + bool Error = false; + + // Scan to find the machine operand number for the operand. + for (; Val; --Val) { + if (OpNo >= MI->getNumOperands()) break; + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1; + } + + if (OpNo >= MI->getNumOperands()) { + Error = true; + } else { + unsigned OpFlags = MI->getOperand(OpNo).getImm(); + ++OpNo; // Skip over the ID number. + + if (Modifier[0] == 'l') // labels are target independent + // FIXME: What if the operand isn't an MBB, report error? + OS << *MI->getOperand(OpNo).getMBB()->getSymbol(); + else { + AsmPrinter *AP = const_cast(this); + if (InlineAsm::isMemKind(OpFlags)) { + Error = AP->PrintAsmMemoryOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, + OS); + } else { + Error = AP->PrintAsmOperand(MI, OpNo, AsmPrinterVariant, + Modifier[0] ? Modifier : 0, OS); + } + } + } + if (Error) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "invalid operand in inline asm: '" << AsmStr << "'"; + MMI->getModule()->getContext().emitError(LocCookie, Msg.str()); + } + } + break; + } + } + } + OS << '\n' << (char)0; // null terminate string. + EmitInlineAsm(OS.str(), LocMD); + + // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't + // enabled, so we use EmitRawText. + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ + MAI->getInlineAsmEnd()); +} + + +/// PrintSpecial - Print information related to the specified machine instr +/// that is independent of the operand, and may be independent of the instr +/// itself. This can be useful for portably encoding the comment character +/// or other bits of target-specific knowledge into the asmstrings. The +/// syntax used is ${:comment}. Targets can override this to add support +/// for their own strange codes. +void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, + const char *Code) const { + if (!strcmp(Code, "private")) { + OS << MAI->getPrivateGlobalPrefix(); + } else if (!strcmp(Code, "comment")) { + OS << MAI->getCommentString(); + } else if (!strcmp(Code, "uid")) { + // Comparing the address of MI isn't sufficient, because machineinstrs may + // be allocated to the same address across functions. + + // If this is a new LastFn instruction, bump the counter. + if (LastMI != MI || LastFn != getFunctionNumber()) { + ++Counter; + LastMI = MI; + LastFn = getFunctionNumber(); + } + OS << Counter; + } else { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Unknown special formatter '" << Code + << "' for machine instr: " << *MI; + report_fatal_error(Msg.str()); + } +} + +/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM +/// instruction, using the specified assembler variant. Targets should +/// override this to format as appropriate. +bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + +bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + // Target doesn't support this yet! + return true; +} + diff --git a/final/lib/CodeGen/AsmPrinter/CMakeLists.txt b/final/lib/CodeGen/AsmPrinter/CMakeLists.txt new file mode 100644 index 00000000000..1377e4dd73e --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -0,0 +1,13 @@ +add_llvm_library(LLVMAsmPrinter + ARMException.cpp + AsmPrinter.cpp + AsmPrinterDwarf.cpp + AsmPrinterInlineAsm.cpp + DIE.cpp + DwarfCFIException.cpp + DwarfDebug.cpp + DwarfException.cpp + DwarfTableException.cpp + OcamlGCPrinter.cpp + ) + diff --git a/final/lib/CodeGen/AsmPrinter/DIE.cpp b/final/lib/CodeGen/AsmPrinter/DIE.cpp new file mode 100644 index 00000000000..21396ca37f0 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DIE.cpp @@ -0,0 +1,368 @@ +//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#include "DIE.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// DIEAbbrevData Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(Attribute); + ID.AddInteger(Form); +} + +//===----------------------------------------------------------------------===// +// DIEAbbrev Implementation +//===----------------------------------------------------------------------===// + +/// Profile - Used to gather unique data for the abbreviation folding set. +/// +void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(Tag); + ID.AddInteger(ChildrenFlag); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) + Data[i].Profile(ID); +} + +/// Emit - Print the abbreviation using the specified asm printer. +/// +void DIEAbbrev::Emit(AsmPrinter *AP) const { + // Emit its Dwarf tag type. + // FIXME: Doing work even in non-asm-verbose runs. + AP->EmitULEB128(Tag, dwarf::TagString(Tag)); + + // Emit whether it has children DIEs. + // FIXME: Doing work even in non-asm-verbose runs. + AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); + + // For each attribute description. + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + const DIEAbbrevData &AttrData = Data[i]; + + // Emit attribute type. + // FIXME: Doing work even in non-asm-verbose runs. + AP->EmitULEB128(AttrData.getAttribute(), + dwarf::AttributeString(AttrData.getAttribute())); + + // Emit form type. + // FIXME: Doing work even in non-asm-verbose runs. + AP->EmitULEB128(AttrData.getForm(), + dwarf::FormEncodingString(AttrData.getForm())); + } + + // Mark end of abbreviation. + AP->EmitULEB128(0, "EOM(1)"); + AP->EmitULEB128(0, "EOM(2)"); +} + +#ifndef NDEBUG +void DIEAbbrev::print(raw_ostream &O) { + O << "Abbreviation @" + << format("0x%lx", (long)(intptr_t)this) + << " " + << dwarf::TagString(Tag) + << " " + << dwarf::ChildrenString(ChildrenFlag) + << '\n'; + + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + O << " " + << dwarf::AttributeString(Data[i].getAttribute()) + << " " + << dwarf::FormEncodingString(Data[i].getForm()) + << '\n'; + } +} +void DIEAbbrev::dump() { print(dbgs()); } +#endif + +//===----------------------------------------------------------------------===// +// DIE Implementation +//===----------------------------------------------------------------------===// + +DIE::~DIE() { + for (unsigned i = 0, N = Children.size(); i < N; ++i) + delete Children[i]; +} + +/// addSiblingOffset - Add a sibling offset field to the front of the DIE. +/// +DIEValue *DIE::addSiblingOffset(BumpPtrAllocator &A) { + DIEInteger *DI = new (A) DIEInteger(0); + Values.insert(Values.begin(), DI); + Abbrev.AddFirstAttribute(dwarf::DW_AT_sibling, dwarf::DW_FORM_ref4); + return DI; +} + +#ifndef NDEBUG +void DIE::print(raw_ostream &O, unsigned IncIndent) { + IndentCount += IncIndent; + const std::string Indent(IndentCount, ' '); + bool isBlock = Abbrev.getTag() == 0; + + if (!isBlock) { + O << Indent + << "Die: " + << format("0x%lx", (long)(intptr_t)this) + << ", Offset: " << Offset + << ", Size: " << Size << "\n"; + + O << Indent + << dwarf::TagString(Abbrev.getTag()) + << " " + << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n"; + } else { + O << "Size: " << Size << "\n"; + } + + const SmallVector &Data = Abbrev.getData(); + + IndentCount += 2; + for (unsigned i = 0, N = Data.size(); i < N; ++i) { + O << Indent; + + if (!isBlock) + O << dwarf::AttributeString(Data[i].getAttribute()); + else + O << "Blk[" << i << "]"; + + O << " " + << dwarf::FormEncodingString(Data[i].getForm()) + << " "; + Values[i]->print(O); + O << "\n"; + } + IndentCount -= 2; + + for (unsigned j = 0, M = Children.size(); j < M; ++j) { + Children[j]->print(O, 4); + } + + if (!isBlock) O << "\n"; + IndentCount -= IncIndent; +} + +void DIE::dump() { + print(dbgs()); +} +#endif + + +#ifndef NDEBUG +void DIEValue::dump() { + print(dbgs()); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEInteger Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit integer of appropriate size. +/// +void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const { + unsigned Size = ~0U; + switch (Form) { + case dwarf::DW_FORM_flag: // Fall thru + case dwarf::DW_FORM_ref1: // Fall thru + case dwarf::DW_FORM_data1: Size = 1; break; + case dwarf::DW_FORM_ref2: // Fall thru + case dwarf::DW_FORM_data2: Size = 2; break; + case dwarf::DW_FORM_ref4: // Fall thru + case dwarf::DW_FORM_data4: Size = 4; break; + case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_data8: Size = 8; break; + case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; + case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; + case dwarf::DW_FORM_addr: Size = Asm->getTargetData().getPointerSize(); break; + default: llvm_unreachable("DIE Value form not supported yet"); + } + Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/); +} + +/// SizeOf - Determine size of integer value in bytes. +/// +unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { + switch (Form) { + case dwarf::DW_FORM_flag: // Fall thru + case dwarf::DW_FORM_ref1: // Fall thru + case dwarf::DW_FORM_data1: return sizeof(int8_t); + case dwarf::DW_FORM_ref2: // Fall thru + case dwarf::DW_FORM_data2: return sizeof(int16_t); + case dwarf::DW_FORM_ref4: // Fall thru + case dwarf::DW_FORM_data4: return sizeof(int32_t); + case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_data8: return sizeof(int64_t); + case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); + case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); + case dwarf::DW_FORM_addr: return AP->getTargetData().getPointerSize(); + default: llvm_unreachable("DIE Value form not supported yet"); break; + } + return 0; +} + +#ifndef NDEBUG +void DIEInteger::print(raw_ostream &O) { + O << "Int: " << (int64_t)Integer + << format(" 0x%llx", (unsigned long long)Integer); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEString Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit string value. +/// +void DIEString::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitBytes(Str, /*addrspace*/0); + // Emit nul terminator. + AP->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); +} + +#ifndef NDEBUG +void DIEString::print(raw_ostream &O) { + O << "Str: \"" << Str << "\""; +} +#endif + +//===----------------------------------------------------------------------===// +// DIELabel Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit label value. +/// +void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->OutStreamer.EmitSymbolValue(Label, SizeOf(AP, Form), 0/*AddrSpace*/); +} + +/// SizeOf - Determine size of label value in bytes. +/// +unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return AP->getTargetData().getPointerSize(); +} + +#ifndef NDEBUG +void DIELabel::print(raw_ostream &O) { + O << "Lbl: " << Label->getName(); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEDelta Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// +void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form)); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const { + if (Form == dwarf::DW_FORM_data4) return 4; + return AP->getTargetData().getPointerSize(); +} + +#ifndef NDEBUG +void DIEDelta::print(raw_ostream &O) { + O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName(); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEEntry Implementation +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit debug information entry offset. +/// +void DIEEntry::EmitValue(AsmPrinter *AP, unsigned Form) const { + AP->EmitInt32(Entry->getOffset()); +} + +#ifndef NDEBUG +void DIEEntry::print(raw_ostream &O) { + O << format("Die: 0x%lx", (long)(intptr_t)Entry); +} +#endif + +//===----------------------------------------------------------------------===// +// DIEBlock Implementation +//===----------------------------------------------------------------------===// + +/// ComputeSize - calculate the size of the block. +/// +unsigned DIEBlock::ComputeSize(AsmPrinter *AP) { + if (!Size) { + const SmallVector &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) + Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm()); + } + + return Size; +} + +/// EmitValue - Emit block data. +/// +void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const { + switch (Form) { + default: assert(0 && "Improper form for block"); break; + case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; + case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break; + } + + const SmallVector &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) + Values[i]->EmitValue(Asm, AbbrevData[i].getForm()); +} + +/// SizeOf - Determine size of block data in bytes. +/// +unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const { + switch (Form) { + case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); + case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); + case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); + case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + default: llvm_unreachable("Improper form for block"); break; + } + return 0; +} + +#ifndef NDEBUG +void DIEBlock::print(raw_ostream &O) { + O << "Blk: "; + DIE::print(O, 5); +} +#endif diff --git a/final/lib/CodeGen/AsmPrinter/DIE.h b/final/lib/CodeGen/AsmPrinter/DIE.h new file mode 100644 index 00000000000..d56c0947795 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DIE.h @@ -0,0 +1,434 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DIE_H__ +#define CODEGEN_ASMPRINTER_DIE_H__ + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { + class AsmPrinter; + class MCSymbol; + class raw_ostream; + + //===--------------------------------------------------------------------===// + /// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a + /// Dwarf abbreviation. + class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + unsigned Attribute; + + /// Form - Dwarf form code. + /// + unsigned Form; + public: + DIEAbbrevData(unsigned A, unsigned F) : Attribute(A), Form(F) {} + + // Accessors. + unsigned getAttribute() const { return Attribute; } + unsigned getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + }; + + //===--------------------------------------------------------------------===// + /// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug + /// information object. + class DIEAbbrev : public FoldingSetNode { + /// Tag - Dwarf tag code. + /// + unsigned Tag; + + /// Unique number for node. + /// + unsigned Number; + + /// ChildrenFlag - Dwarf children flag. + /// + unsigned ChildrenFlag; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + + public: + DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} + virtual ~DIEAbbrev() {} + + // Accessors. + unsigned getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + unsigned getChildrenFlag() const { return ChildrenFlag; } + const SmallVector &getData() const { return Data; } + void setTag(unsigned T) { Tag = T; } + void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(unsigned Attribute, unsigned Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// AddFirstAttribute - Adds a set of attribute information to the front + /// of the abbreviation. + void AddFirstAttribute(unsigned Attribute, unsigned Form) { + Data.insert(Data.begin(), DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIE - A structured debug information entry. Has an abbreviation which + /// describes it's organization. + class DIEValue; + + class DIE { + protected: + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Children DIEs. + /// + std::vector Children; + + DIE *Parent; + + /// Attributes values. + /// + SmallVector Values; + + // Private data for print() + mutable unsigned IndentCount; + public: + explicit DIE(unsigned Tag) + : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), + Size(0), Parent (0), IndentCount(0) {} + virtual ~DIE(); + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + unsigned getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector &getChildren() const { return Children; } + const SmallVector &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + void setTag(unsigned Tag) { Abbrev.setTag(Tag); } + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(unsigned Attribute, unsigned Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// SiblingOffset - Return the offset of the debug information entry's + /// sibling. + unsigned getSiblingOffset() const { return Offset + Size; } + + /// addSiblingOffset - Add a sibling offset field to the front of the DIE. + /// The caller is responsible for deleting the return value at or after the + /// same time it destroys this DIE. + /// + DIEValue *addSiblingOffset(BumpPtrAllocator &A); + + /// addChild - Add a child to the DIE. + /// + void addChild(DIE *Child) { + if (Child->getParent()) { + assert (Child->getParent() == this && "Unexpected DIE Parent!"); + return; + } + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Children.push_back(Child); + Child->Parent = this; + } + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IncIndent = 0); + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEValue - A debug information entry value. + /// + class DIEValue { + public: + enum { + isInteger, + isString, + isLabel, + isSectionOffset, + isDelta, + isEntry, + isBlock + }; + protected: + /// Type - Type of data stored in the value. + /// + unsigned Type; + public: + explicit DIEValue(unsigned T) : Type(T) {} + virtual ~DIEValue() {} + + // Accessors + unsigned getType() const { return Type; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const = 0; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *) { return true; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O) = 0; + void dump(); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEInteger - An integer value DIE. + /// + class DIEInteger : public DIEValue { + uint64_t Integer; + public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static unsigned BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + if ((char)Int == (signed)Int) return dwarf::DW_FORM_data1; + if ((short)Int == (signed)Int) return dwarf::DW_FORM_data2; + if ((int)Int == (signed)Int) return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEInteger *) { return true; } + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEString - A string value DIE. This DIE keeps string reference only. + /// + class DIEString : public DIEValue { + const StringRef Str; + public: + explicit DIEString(const StringRef S) : DIEValue(isString), Str(S) {} + + /// EmitValue - Emit string value. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + /// SizeOf - Determine size of string value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned /*Form*/) const { + return Str.size() + sizeof(char); // sizeof('\0'); + } + + // Implement isa/cast/dyncast. + static bool classof(const DIEString *) { return true; } + static bool classof(const DIEValue *S) { return S->getType() == isString; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIELabel - A label expression DIE. + // + class DIELabel : public DIEValue { + const MCSymbol *Label; + public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIELabel *) { return true; } + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEDelta - A simple label difference DIE. + /// + class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + /// SizeOf - Determine size of delta value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEDelta *) { return true; } + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEntry - A pointer to another debug information entry. An instance of + /// this class can also be used as a proxy for a debug information entry not + /// yet defined (ie. types.) + class DIEEntry : public DIEValue { + DIE *const Entry; + public: + explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {} + + DIE *getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const { + return sizeof(int32_t); + } + + // Implement isa/cast/dyncast. + static bool classof(const DIEEntry *) { return true; } + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + + //===--------------------------------------------------------------------===// + /// DIEBlock - A block of values. Primarily used for location expressions. + // + class DIEBlock : public DIEValue, public DIE { + unsigned Size; // Size in bytes excluding size header. + public: + DIEBlock() + : DIEValue(isBlock), DIE(0), Size(0) {} + virtual ~DIEBlock() {} + + /// ComputeSize - calculate the size of the block. + /// + unsigned ComputeSize(AsmPrinter *AP); + + /// BestForm - Choose the best form for data. + /// + unsigned BestForm() const { + if ((unsigned char)Size == Size) return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit block data. + /// + virtual void EmitValue(AsmPrinter *AP, unsigned Form) const; + + /// SizeOf - Determine size of block data in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const; + + // Implement isa/cast/dyncast. + static bool classof(const DIEBlock *) { return true; } + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + virtual void print(raw_ostream &O); +#endif + }; + +} // end llvm namespace + +#endif diff --git a/final/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/final/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp new file mode 100644 index 00000000000..68be2eed8f0 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -0,0 +1,138 @@ +//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +DwarfCFIException::DwarfCFIException(AsmPrinter *A) + : DwarfException(A), + shouldEmitTable(false), shouldEmitMoves(false), shouldEmitTableModule(false) + {} + +DwarfCFIException::~DwarfCFIException() {} + +/// EndModule - Emit all exception information that should come after the +/// content. +void DwarfCFIException::EndModule() { + if (!Asm->MAI->isExceptionHandlingDwarf()) + return; + + if (!shouldEmitTableModule) + return; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + + // Begin eh frame section. + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + + // Emit references to all used personality functions + const std::vector &Personalities = MMI->getPersonalities(); + for (size_t i = 0, e = Personalities.size(); i != e; ++i) { + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("personality", i)); + Asm->EmitReference(Personalities[i], PerEncoding); + } +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void DwarfCFIException::BeginFunction(const MachineFunction *MF) { + shouldEmitTable = shouldEmitMoves = false; + + // If any landing pads survive, we need an EH table. + shouldEmitTable = !MMI->getLandingPads().empty(); + + // See if we need frame move info. + shouldEmitMoves = + !Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; + + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); + + shouldEmitTableModule |= shouldEmitTable; + + if (shouldEmitMoves) { + const TargetFrameLowering *TFL = Asm->TM.getFrameLowering(); + Asm->OutStreamer.EmitCFIStartProc(); + + // Indicate locations of general callee saved registers in frame. + std::vector Moves; + TFL->getInitialFrameState(Moves); + Asm->EmitCFIFrameMoves(Moves); + Asm->EmitCFIFrameMoves(MMI->getFrameMoves()); + } + + if (!shouldEmitTable) + return; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + // Provide LSDA information. + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + if (LSDAEncoding != dwarf::DW_EH_PE_omit) + Asm->OutStreamer.EmitCFILsda(Asm->GetTempSymbol("exception", + Asm->getFunctionNumber()), + LSDAEncoding); + + // Indicate personality routine, if any. + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + if (PerEncoding != dwarf::DW_EH_PE_omit && + MMI->getPersonalities()[MMI->getPersonalityIndex()]) + Asm->OutStreamer.EmitCFIPersonality(Asm->GetTempSymbol("personality", + MMI->getPersonalityIndex()), + PerEncoding); +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void DwarfCFIException::EndFunction() { + if (!shouldEmitMoves && !shouldEmitTable) return; + + if (shouldEmitMoves) + Asm->OutStreamer.EmitCFIEndProc(); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + if (shouldEmitTable) + EmitExceptionTable(); +} diff --git a/final/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/final/lib/CodeGen/AsmPrinter/DwarfDebug.cpp new file mode 100644 index 00000000000..15330c28d2c --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -0,0 +1,3792 @@ +//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dwarfdebug" +#include "DwarfDebug.h" +#include "DIE.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/Path.h" +using namespace llvm; + +static cl::opt PrintDbgScope("print-dbgscope", cl::Hidden, + cl::desc("Print DbgScope information for each machine instruction")); + +static cl::opt DisableDebugInfoPrinting("disable-debug-info-print", + cl::Hidden, + cl::desc("Disable debug info printing")); + +static cl::opt UnknownLocations("use-unknown-locations", cl::Hidden, + cl::desc("Make an absense of debug location information explicit."), + cl::init(false)); + +#ifndef NDEBUG +STATISTIC(BlocksWithoutLineNo, "Number of blocks without any line number"); +#endif + +namespace { + const char *DWARFGroupName = "DWARF Emission"; + const char *DbgTimerName = "DWARF Debug Writer"; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// + +/// Configuration values for initial hash set sizes (log2). +/// +static const unsigned InitAbbreviationsSetSize = 9; // log2(512) + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class CompileUnit { + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + const OwningPtr CUDie; + + /// IndexTyDie - An anonymous type for index type. Owned by CUDie. + DIE *IndexTyDie; + + /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + DenseMap MDNodeToDieMap; + + /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEEntry proxy. + DenseMap MDNodeToDIEEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + StringMap Globals; + + /// GlobalTypes - A map of globally visible types for this unit. + /// + StringMap GlobalTypes; + +public: + CompileUnit(unsigned I, DIE *D) + : ID(I), CUDie(D), IndexTyDie(0) {} + + // Accessors. + unsigned getID() const { return ID; } + DIE* getCUDie() const { return CUDie.get(); } + const StringMap &getGlobals() const { return Globals; } + const StringMap &getGlobalTypes() const { return GlobalTypes; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { return !CUDie->getChildren().empty(); } + + /// addGlobal - Add a new global entity to the compile unit. + /// + void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; } + + /// addGlobalType - Add a new global type to the compile unit. + /// + void addGlobalType(StringRef Name, DIE *Die) { + GlobalTypes[Name] = Die; + } + + /// getDIE - Returns the debug information entry map slot for the + /// specified debug variable. + DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } + + /// insertDIE - Insert DIE into the map. + void insertDIE(const MDNode *N, DIE *D) { + MDNodeToDieMap.insert(std::make_pair(N, D)); + } + + /// getDIEEntry - Returns the debug information entry for the speciefied + /// debug variable. + DIEEntry *getDIEEntry(const MDNode *N) { + DenseMap::iterator I = + MDNodeToDIEEntryMap.find(N); + if (I == MDNodeToDIEEntryMap.end()) + return NULL; + return I->second; + } + + /// insertDIEEntry - Insert debug information entry into the map. + void insertDIEEntry(const MDNode *N, DIEEntry *E) { + MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); + } + + /// addDie - Adds or interns the DIE to the compile unit. + /// + void addDie(DIE *Buffer) { + this->CUDie->addChild(Buffer); + } + + // getIndexTyDie - Get an anonymous type for index type. + DIE *getIndexTyDie() { + return IndexTyDie; + } + + // setIndexTyDie - Set D as anonymous type for index which can be reused + // later. + void setIndexTyDie(DIE *D) { + IndexTyDie = D; + } + +}; + +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class DbgVariable { + DIVariable Var; // Variable Descriptor. + DIE *TheDIE; // Variable DIE. + unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. +public: + // AbsVar may be NULL. + DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + void setDIE(DIE *D) { TheDIE = D; } + DIE *getDIE() const { return TheDIE; } + void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } + unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } + StringRef getName() const { return Var.getName(); } + unsigned getTag() const { return Var.getTag(); } + bool variableHasComplexAddress() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.hasComplexAddress(); + } + bool isBlockByrefVariable() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.isBlockByrefVariable(); + } + unsigned getNumAddrElements() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.getNumAddrElements(); + } + uint64_t getAddrElement(unsigned i) const { + return Var.getAddrElement(i); + } + DIType getType() const { + DIType Ty = Var.getType(); + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (Var.isBlockByrefVariable()) { + /* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + either the struct, or a pointer to the struct, as its type. This + is necessary for various behind-the-scenes things the compiler + needs to do with by-reference variables in blocks. + + However, as far as the original *programmer* is concerned, the + variable should still have type 'SomeType', as originally declared. + + The following function dives into the __Block_byref_x_VarName + struct to find the original type of the variable. This will be + passed back to the code generating the type for the Debug + Information Entry for the variable 'VarName'. 'VarName' will then + have the original type 'SomeType' in its debug information. + + The original type 'SomeType' will be the type of the field named + 'VarName' inside the __Block_byref_x_VarName struct. + + NOTE: In order for this to not completely fail on the debugger + side, the Debug Information Entry for the variable VarName needs to + have a DW_AT_location that tells the debugger how to unwind through + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function addBlockByrefType does this. */ + DIType subType = Ty; + unsigned tag = Ty.getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + subType = DTy.getTypeDerivedFrom(); + } + + DICompositeType blockStruct = DICompositeType(subType); + DIArray Elements = blockStruct.getTypeArray(); + + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + if (getName() == DT.getName()) + return (DT.getTypeDerivedFrom()); + } + return Ty; + } + return Ty; + } +}; + +//===----------------------------------------------------------------------===// +/// DbgRange - This is used to track range of instructions with identical +/// debug info scope. +/// +typedef std::pair DbgRange; + +//===----------------------------------------------------------------------===// +/// DbgScope - This class is used to track scope information. +/// +class DbgScope { + DbgScope *Parent; // Parent to this scope. + DIDescriptor Desc; // Debug info descriptor for scope. + // Location at which this scope is inlined. + AssertingVH InlinedAtLocation; + bool AbstractScope; // Abstract Scope + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. + unsigned DFSIn, DFSOut; + // Scopes defined in scope. Contents not owned. + SmallVector Scopes; + // Variables declared in scope. Contents owned. + SmallVector Variables; + SmallVector Ranges; + // Private state for dump() + mutable unsigned IndentLevel; +public: + DbgScope(DbgScope *P, DIDescriptor D, const MDNode *I = 0) + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), + LastInsn(0), FirstInsn(0), + DFSIn(0), DFSOut(0), IndentLevel(0) {} + virtual ~DbgScope(); + + // Accessors. + DbgScope *getParent() const { return Parent; } + void setParent(DbgScope *P) { Parent = P; } + DIDescriptor getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + const SmallVector &getScopes() { return Scopes; } + const SmallVector &getDbgVariables() { return Variables; } + const SmallVector &getRanges() { return Ranges; } + + /// openInsnRange - This scope covers instruction range starting from MI. + void openInsnRange(const MachineInstr *MI) { + if (!FirstInsn) + FirstInsn = MI; + + if (Parent) + Parent->openInsnRange(MI); + } + + /// extendInsnRange - Extend the current instruction range covered by + /// this scope. + void extendInsnRange(const MachineInstr *MI) { + assert (FirstInsn && "MI Range is not open!"); + LastInsn = MI; + if (Parent) + Parent->extendInsnRange(MI); + } + + /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected + /// until now. This is used when a new scope is encountered while walking + /// machine instructions. + void closeInsnRange(DbgScope *NewScope = NULL) { + assert (LastInsn && "Last insn missing!"); + Ranges.push_back(DbgRange(FirstInsn, LastInsn)); + FirstInsn = NULL; + LastInsn = NULL; + // If Parent dominates NewScope then do not close Parent's instruction + // range. + if (Parent && (!NewScope || !Parent->dominates(NewScope))) + Parent->closeInsnRange(NewScope); + } + + void setAbstractScope() { AbstractScope = true; } + bool isAbstractScope() const { return AbstractScope; } + + // Depth First Search support to walk and mainpluate DbgScope hierarchy. + unsigned getDFSOut() const { return DFSOut; } + void setDFSOut(unsigned O) { DFSOut = O; } + unsigned getDFSIn() const { return DFSIn; } + void setDFSIn(unsigned I) { DFSIn = I; } + bool dominates(const DbgScope *S) { + if (S == this) + return true; + if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) + return true; + return false; + } + + /// addScope - Add a scope to the scope. + /// + void addScope(DbgScope *S) { Scopes.push_back(S); } + + /// addVariable - Add a variable to the scope. + /// + void addVariable(DbgVariable *V) { Variables.push_back(V); } + +#ifndef NDEBUG + void dump() const; +#endif +}; + +} // end llvm namespace + +#ifndef NDEBUG +void DbgScope::dump() const { + raw_ostream &err = dbgs(); + err.indent(IndentLevel); + const MDNode *N = Desc; + N->dump(); + if (AbstractScope) + err << "Abstract Scope\n"; + + IndentLevel += 2; + if (!Scopes.empty()) + err << "Children ...\n"; + for (unsigned i = 0, e = Scopes.size(); i != e; ++i) + if (Scopes[i] != this) + Scopes[i]->dump(); + + IndentLevel -= 2; +} +#endif + +DbgScope::~DbgScope() { + for (unsigned j = 0, M = Variables.size(); j < M; ++j) + delete Variables[j]; +} + +DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) + : Asm(A), MMI(Asm->MMI), FirstCU(0), + AbbreviationsSet(InitAbbreviationsSetSize), + CurrentFnDbgScope(0), PrevLabel(NULL) { + NextStringPoolNumber = 0; + + DwarfFrameSectionSym = DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; + DwarfStrSectionSym = TextSectionSym = 0; + DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0; + FunctionBeginSym = FunctionEndSym = 0; + DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); + { + NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); + beginModule(M); + } +} +DwarfDebug::~DwarfDebug() { + for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) + DIEBlocks[j]->~DIEBlock(); +} + +MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { + std::pair &Entry = StringPool[Str]; + if (Entry.first) return Entry.first; + + Entry.second = NextStringPoolNumber++; + return Entry.first = Asm->GetTempSymbol("string", Entry.second); +} + + +/// assignAbbrevNumber - Define a unique number for the abbreviation. +/// +void DwarfDebug::assignAbbrevNumber(DIEAbbrev &Abbrev) { + // Profile the node so that we can make it unique. + FoldingSetNodeID ID; + Abbrev.Profile(ID); + + // Check the set for priors. + DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); + + // If it's newly added. + if (InSet == &Abbrev) { + // Add to abbreviation list. + Abbreviations.push_back(&Abbrev); + + // Assign the vector position + 1 as its number. + Abbrev.setNumber(Abbreviations.size()); + } else { + // Assign existing abbreviation number. + Abbrev.setNumber(InSet->getNumber()); + } +} + +/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug +/// information entry. +DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) { + DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); + return Value; +} + +/// addUInt - Add an unsigned integer attribute data and value. +/// +void DwarfDebug::addUInt(DIE *Die, unsigned Attribute, + unsigned Form, uint64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(false, Integer); + DIEValue *Value = Integer == 1 ? + DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addSInt - Add an signed integer attribute data and value. +/// +void DwarfDebug::addSInt(DIE *Die, unsigned Attribute, + unsigned Form, int64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(true, Integer); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addString - Add a string attribute data and value. DIEString only +/// keeps string reference. +void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, + StringRef String) { + DIEValue *Value = new (DIEValueAllocator) DIEString(String); + Die->addValue(Attribute, Form, Value); +} + +/// addLabel - Add a Dwarf label attribute data and value. +/// +void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label) { + DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); + Die->addValue(Attribute, Form, Value); +} + +/// addDelta - Add a label delta attribute data and value. +/// +void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die->addValue(Attribute, Form, Value); +} + +/// addDIEEntry - Add a DIE attribute data and value. +/// +void DwarfDebug::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, + DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); +} + + +/// addBlock - Add block data. +/// +void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, + DIEBlock *Block) { + Block->ComputeSize(Asm); + DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. + Die->addValue(Attribute, Block->BestForm(), Block); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, DIVariable V) { + // Verify variable. + if (!V.Verify()) + return; + + unsigned Line = V.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = GetOrCreateSourceID(V.getContext().getFilename()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, DIGlobalVariable G) { + // Verify global variable. + if (!G.Verify()) + return; + + unsigned Line = G.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = GetOrCreateSourceID(G.getContext().getFilename()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, DISubprogram SP) { + // Verify subprogram. + if (!SP.Verify()) + return; + // If the line number is 0, don't add it. + if (SP.getLineNumber() == 0) + return; + + unsigned Line = SP.getLineNumber(); + if (!SP.getContext().Verify()) + return; + unsigned FileID = GetOrCreateSourceID(SP.getFilename()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, DIType Ty) { + // Verify type. + if (!Ty.Verify()) + return; + + unsigned Line = Ty.getLineNumber(); + if (Line == 0 || !Ty.getContext().Verify()) + return; + unsigned FileID = GetOrCreateSourceID(Ty.getFilename()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, DINameSpace NS) { + // Verify namespace. + if (!NS.Verify()) + return; + + unsigned Line = NS.getLineNumber(); + if (Line == 0) + return; + StringRef FN = NS.getFilename(); + + unsigned FileID = GetOrCreateSourceID(FN); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based +/// on provided frame index. +void DwarfDebug::addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI) { + MachineLocation Location; + unsigned FrameReg; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + Location.set(FrameReg, Offset); + + if (DV->variableHasComplexAddress()) + addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); + else if (DV->isBlockByrefVariable()) + addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); + else + addAddress(Die, dwarf::DW_AT_location, Location); +} + +/// addComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIType Ty = DV->getType(); + + // Decode the original location, and use that as the start of the byref + // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) { + uint64_t Element = DV->getAddrElement(i); + + if (Element == DIBuilder::OpPlus) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIBuilder Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/* Byref variables, in Blocks, are declared by the programmer as "SomeType + VarName;", but the compiler creates a __Block_byref_x_VarName struct, and + gives the variable VarName either the struct, or a pointer to the struct, as + its type. This is necessary for various behind-the-scenes things the + compiler needs to do with by-reference variables in Blocks. + + However, as far as the original *programmer* is concerned, the variable + should still have type 'SomeType', as originally declared. + + The function getBlockByrefType dives into the __Block_byref_x_VarName + struct to find the original type of the variable, which is then assigned to + the variable's Debug Information Entry as its real type. So far, so good. + However now the debugger will expect the variable VarName to have the type + SomeType. So we need the location attribute for the variable to be an + expression that explains to the debugger how to navigate through the + pointers and struct to find the actual variable of type SomeType. + + The following function does just that. We start by getting + the "normal" location for the variable. This will be the location + of either the struct __Block_byref_x_VarName or the pointer to the + struct __Block_byref_x_VarName. + + The struct will look something like: + + struct __Block_byref_x_VarName { + ... + struct __Block_byref_x_VarName *forwarding; + ... + SomeType VarName; + ... + }; + + If we are given the struct directly (as our starting point) we + need to tell the debugger to: + + 1). Add the offset of the forwarding field. + + 2). Follow that pointer to get the real __Block_byref_x_VarName + struct to use (the real one may have been copied onto the heap). + + 3). Add the offset for the field VarName, to find the actual variable. + + If we started with a pointer to the struct, then we need to + dereference that pointer first, before the other steps. + Translating this into DWARF ops, we will need to append the following + to the current location description for the variable: + + DW_OP_deref -- optional, if we start with a pointer + DW_OP_plus_uconst + DW_OP_deref + DW_OP_plus_uconst + + That is what this function does. */ + +/// addBlockByrefAddress - Start with the address based on the location +/// provided, and generate the DWARF information necessary to find the +/// actual Block variable (navigating the Block struct) based on the +/// starting location. Add the DWARF information to the die. For +/// more information, read large comment just above here. +/// +void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIType Ty = DV->getType(); + DIType TmpTy = Ty; + unsigned Tag = Ty.getTag(); + bool isPointer = false; + + StringRef varName = DV->getName(); + + if (Tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + TmpTy = DTy.getTypeDerivedFrom(); + isPointer = true; + } + + DICompositeType blockStruct = DICompositeType(TmpTy); + + // Find the __forwarding field and the variable field in the __Block_byref + // struct. + DIArray Fields = blockStruct.getTypeArray(); + DIDescriptor varField = DIDescriptor(); + DIDescriptor forwardingField = DIDescriptor(); + + for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { + DIDescriptor Element = Fields.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + StringRef fieldName = DT.getName(); + if (fieldName == "__forwarding") + forwardingField = Element; + else if (fieldName == varName) + varField = Element; + } + + // Get the offsets for the forwarding field and the variable field. + unsigned forwardingFieldOffset = + DIDerivedType(forwardingField).getOffsetInBits() >> 3; + unsigned varFieldOffset = + DIDerivedType(varField).getOffsetInBits() >> 3; + + // Decode the original location, and use that as the start of the byref + // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + // If we started with a pointer to the __Block_byref... struct, then + // the first thing we need to do is dereference the pointer (DW_OP_deref). + if (isPointer) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Next add the offset for the '__forwarding' field: + // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in + // adding the offset if it's 0. + if (forwardingFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); + } + + // Now dereference the __forwarding field to get to the real __Block_byref + // struct: DW_OP_deref. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Now that we've got the real __Block_byref... struct, add the offset + // for the variable's field to get to the location of the actual variable: + // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. + if (varFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/// addAddress - Add an address attribute to a die based on the location +/// provided. +void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (RI->getFrameRegister(*Asm->MF) == Location.getReg() + && Location.getOffset()) { + // If variable offset is based in frame register then use fbreg. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); + addSInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + addBlock(Die, Attribute, 0, Block); + return; + } + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + addBlock(Die, Attribute, 0, Block); +} + +/// addRegisterAddress - Add register location entry in variable DIE. +bool DwarfDebug::addRegisterAddress(DIE *Die, const MachineOperand &MO) { + assert (MO.isReg() && "Invalid machine operand!"); + if (!MO.getReg()) + return false; + MachineLocation Location; + Location.set(MO.getReg()); + addAddress(Die, dwarf::DW_AT_location, Location); + return true; +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool DwarfDebug::addConstantValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + unsigned Imm = MO.getImm(); + addUInt(Block, 0, dwarf::DW_FORM_udata, Imm); + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantFPValue - Add constant value entry in variable DIE. +bool DwarfDebug::addConstantFPValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isFPImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + APFloat FPImm = MO.getFPImm()->getValueAPF(); + + // Get the raw data form of the floating point. + const APInt FltVal = FPImm.bitcastToAPInt(); + const char *FltPtr = (const char*)FltVal.getRawData(); + + int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & FltPtr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool DwarfDebug::addConstantValue(DIE *Die, ConstantInt *CI, + bool Unsigned) { + if (CI->getBitWidth() <= 64) { + if (Unsigned) + addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + CI->getZExtValue()); + else + addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, + CI->getSExtValue()); + return true; + } + + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + // Get the raw data form of the large APInt. + const APInt Val = CI->getValue(); + const char *Ptr = (const char*)Val.getRawData(); + + int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & Ptr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addToContextOwner - Add Die into the list of its context owner's children. +void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) { + if (Context.isType()) { + DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); + ContextDIE->addChild(Die); + } else if (Context.isNameSpace()) { + DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); + ContextDIE->addChild(Die); + } else if (Context.isSubprogram()) { + DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context)); + ContextDIE->addChild(Die); + } else if (DIE *ContextDIE = getCompileUnit(Context)->getDIE(Context)) + ContextDIE->addChild(Die); + else + getCompileUnit(Context)->addDie(Die); +} + +/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the +/// given DIType. +DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) { + CompileUnit *TypeCU = getCompileUnit(Ty); + DIE *TyDIE = TypeCU->getDIE(Ty); + if (TyDIE) + return TyDIE; + + // Create new type. + TyDIE = new DIE(dwarf::DW_TAG_base_type); + TypeCU->insertDIE(Ty, TyDIE); + if (Ty.isBasicType()) + constructTypeDIE(*TyDIE, DIBasicType(Ty)); + else if (Ty.isCompositeType()) + constructTypeDIE(*TyDIE, DICompositeType(Ty)); + else { + assert(Ty.isDerivedType() && "Unknown kind of DIType"); + constructTypeDIE(*TyDIE, DIDerivedType(Ty)); + } + + addToContextOwner(TyDIE, Ty.getContext()); + return TyDIE; +} + +/// addType - Add a new type attribute to the specified entity. +void DwarfDebug::addType(DIE *Entity, DIType Ty) { + if (!Ty.Verify()) + return; + + // Check for pre-existence. + CompileUnit *TypeCU = getCompileUnit(Ty); + DIEEntry *Entry = TypeCU->getDIEEntry(Ty); + // If it exists then use the existing value. + if (Entry) { + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); + return; + } + + // Construct type. + DIE *Buffer = getOrCreateTypeDIE(Ty); + + // Set up proxy. + Entry = createDIEEntry(Buffer); + TypeCU->insertDIEEntry(Ty, Entry); + + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); +} + +/// constructTypeDIE - Construct basic type die from DIBasicType. +void DwarfDebug::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { + // Get core information. + StringRef Name = BTy.getName(); + Buffer.setTag(dwarf::DW_TAG_base_type); + addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + uint64_t Size = BTy.getSizeInBits() >> 3; + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); +} + +/// constructTypeDIE - Construct derived type die from DIDerivedType. +void DwarfDebug::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { + // Get core information. + StringRef Name = DTy.getName(); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + + // FIXME - Workaround for templates. + if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; + + Buffer.setTag(Tag); + + // Map to main type, void will not have a type. + DIType FromTy = DTy.getTypeDerivedFrom(); + addType(&Buffer, FromTy); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + + // Add source line info if available and TyDesc is not a forward declaration. + if (!DTy.isForwardDecl()) + addSourceLine(&Buffer, DTy); +} + +/// constructTypeDIE - Construct type DIE from DICompositeType. +void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { + // Get core information. + StringRef Name = CTy.getName(); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_array_type: + constructArrayTypeDIE(Buffer, &CTy); + break; + case dwarf::DW_TAG_enumeration_type: { + DIArray Elements = CTy.getTypeArray(); + + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIDescriptor Enum(Elements.getElement(i)); + if (Enum.isEnumerator()) { + ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); + Buffer.addChild(ElemDie); + } + } + } + break; + case dwarf::DW_TAG_subroutine_type: { + // Add return type. + DIArray Elements = CTy.getTypeArray(); + DIDescriptor RTy = Elements.getElement(0); + addType(&Buffer, DIType(RTy)); + + bool isPrototyped = true; + // Add arguments. + for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Elements.getElement(i); + if (Ty.isUnspecifiedParameter()) { + DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); + Buffer.addChild(Arg); + isPrototyped = false; + } else { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + addType(Arg, DIType(Ty)); + Buffer.addChild(Arg); + } + } + // Add prototype flag. + if (isPrototyped) + addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + } + break; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_class_type: { + // Add elements to structure type. + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + unsigned N = Elements.getNumElements(); + if (N == 0) + break; + + // Add elements to structure type. + for (unsigned i = 0; i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIE *ElemDie = NULL; + if (Element.isSubprogram()) { + DISubprogram SP(Element); + ElemDie = createSubprogramDIE(DISubprogram(Element)); + if (SP.isProtected()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (SP.isPrivate()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + else + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (SP.isExplicit()) + addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); + } + else if (Element.isVariable()) { + DIVariable DV(Element); + ElemDie = new DIE(dwarf::DW_TAG_variable); + addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + DV.getName()); + addType(ElemDie, DV.getType()); + addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(ElemDie, DV); + } else if (Element.isDerivedType()) + ElemDie = createMemberDIE(DIDerivedType(Element)); + else + continue; + Buffer.addChild(ElemDie); + } + + if (CTy.isAppleBlockExtension()) + addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); + + unsigned RLang = CTy.getRunTimeLang(); + if (RLang) + addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, + dwarf::DW_FORM_data1, RLang); + + DICompositeType ContainingType = CTy.getContainingType(); + if (DIDescriptor(ContainingType).isCompositeType()) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DIType(ContainingType))); + else { + DIDescriptor Context = CTy.getContext(); + addToContextOwner(&Buffer, Context); + } + + if (Tag == dwarf::DW_TAG_class_type) { + DIArray TParams = CTy.getTemplateParams(); + unsigned N = TParams.getNumElements(); + // Add template parameters. + for (unsigned i = 0; i < N; ++i) { + DIDescriptor Element = TParams.getElement(i); + if (Element.isTemplateTypeParameter()) + Buffer.addChild(getOrCreateTemplateTypeParameterDIE( + DITemplateTypeParameter(Element))); + else if (Element.isTemplateValueParameter()) + Buffer.addChild(getOrCreateTemplateValueParameterDIE( + DITemplateValueParameter(Element))); + } + } + break; + } + default: + break; + } + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type + || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) + { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + else + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + addSourceLine(&Buffer, CTy); + } +} + +/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateTypeParameter. +DIE * +DwarfDebug::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { + CompileUnit *TypeCU = getCompileUnit(TP); + DIE *ParamDIE = TypeCU->getDIE(TP); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_type_parameter); + addType(ParamDIE, TP.getType()); + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TP.getName()); + return ParamDIE; +} + +/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateValueParameter. +DIE * +DwarfDebug::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV) { + CompileUnit *TVCU = getCompileUnit(TPV); + DIE *ParamDIE = TVCU->getDIE(TPV); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_value_parameter); + addType(ParamDIE, TPV.getType()); + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TPV.getName()); + addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + TPV.getValue()); + return ParamDIE; +} + +/// constructSubrangeDIE - Construct subrange DIE from DISubrange. +void DwarfDebug::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); + DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); + + addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + if (L) + addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); + + Buffer.addChild(DW_Subrange); +} + +/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. +void DwarfDebug::constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy) { + Buffer.setTag(dwarf::DW_TAG_array_type); + if (CTy->getTag() == dwarf::DW_TAG_vector_type) + addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); + + // Emit derived type. + addType(&Buffer, CTy->getTypeDerivedFrom()); + DIArray Elements = CTy->getTypeArray(); + + // Get an anonymous type for index type. + CompileUnit *TheCU = getCompileUnit(*CTy); + DIE *IdxTy = TheCU->getIndexTyDie(); + if (!IdxTy) { + // Construct an anonymous type for index type. + IdxTy = new DIE(dwarf::DW_TAG_base_type); + addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); + addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_ATE_signed); + TheCU->addDie(IdxTy); + TheCU->setIndexTyDie(IdxTy); + } + + // Add subranges to array type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); + } +} + +/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. +DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator ETy) { + DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); + StringRef Name = ETy.getName(); + addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + int64_t Value = ETy.getEnumValue(); + addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); + return Enumerator; +} + +/// getRealLinkageName - If special LLVM prefix that is used to inform the asm +/// printer to not emit usual symbol prefix before the symbol name is used then +/// return linkage name after skipping this special LLVM prefix. +static StringRef getRealLinkageName(StringRef LinkageName) { + char One = '\1'; + if (LinkageName.startswith(StringRef(&One, 1))) + return LinkageName.substr(1); + return LinkageName; +} + +/// createMemberDIE - Create new member DIE. +DIE *DwarfDebug::createMemberDIE(DIDerivedType DT) { + DIE *MemberDie = new DIE(DT.getTag()); + StringRef Name = DT.getName(); + if (!Name.empty()) + addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + addType(MemberDie, DT.getTypeDerivedFrom()); + + addSourceLine(MemberDie, DT); + + DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); + + if (Size != FieldSize) { + // Handle bitfield. + addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); + addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); + + uint64_t Offset = DT.getOffsetInBits(); + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + uint64_t FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + + // Maybe we need to work from the other end. + if (Asm->getTargetData().isLittleEndian()) + Offset = FieldSize - (Offset + Size); + addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); + + // Here WD_AT_data_member_location points to the anonymous + // field that includes this bit field. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); + + } else + // This is not a bitfield. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); + + if (DT.getTag() == dwarf::DW_TAG_inheritance + && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following + // expression to extract appropriate offset from vtable. + // BaseAddr = ObAddr + *((*ObAddr) - Offset) + + DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, + VBaseLocationDie); + } else + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + + if (DT.isProtected()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (DT.isPrivate()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + // Otherwise C++ member and base classes are considered public. + else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (DT.isVirtual()) + addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, + dwarf::DW_VIRTUALITY_virtual); + return MemberDie; +} + +/// createSubprogramDIE - Create new DIE using SP. +DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { + CompileUnit *SPCU = getCompileUnit(SP); + DIE *SPDie = SPCU->getDIE(SP); + if (SPDie) + return SPDie; + + SPDie = new DIE(dwarf::DW_TAG_subprogram); + // Constructors and operators for anonymous aggregates do not have names. + if (!SP.getName().empty()) + addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); + + StringRef LinkageName = SP.getLinkageName(); + if (!LinkageName.empty()) + addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); + + addSourceLine(SPDie, SP); + + if (SP.isPrototyped()) + addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + + // Add Return Type. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + + if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) + addType(SPDie, SPTy); + else + addType(SPDie, DIType(Args.getElement(0))); + + unsigned VK = SP.getVirtuality(); + if (VK) { + addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); + addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); + ContainingTypeMap.insert(std::make_pair(SPDie, + SP.getContainingType())); + } + + if (!SP.isDefinition()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. Do not add arguments for subprogram definition. They will + // be handled while processing variables. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i))); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + } + + if (SP.isArtificial()) + addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + + if (!SP.isLocalToUnit()) + addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + + if (SP.isOptimized()) + addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + + if (unsigned isa = Asm->getISAEncoding()) { + addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); + } + + // DW_TAG_inlined_subroutine may refer to this DIE. + SPCU->insertDIE(SP, SPDie); + + // Add to context owner. + addToContextOwner(SPDie, SP.getContext()); + + return SPDie; +} + +DbgScope *DwarfDebug::getOrCreateAbstractScope(const MDNode *N) { + assert(N && "Invalid Scope encoding!"); + + DbgScope *AScope = AbstractScopes.lookup(N); + if (AScope) + return AScope; + + DbgScope *Parent = NULL; + + DIDescriptor Scope(N); + if (Scope.isLexicalBlock()) { + DILexicalBlock DB(N); + DIDescriptor ParentDesc = DB.getContext(); + Parent = getOrCreateAbstractScope(ParentDesc); + } + + AScope = new DbgScope(Parent, DIDescriptor(N), NULL); + + if (Parent) + Parent->addScope(AScope); + AScope->setAbstractScope(); + AbstractScopes[N] = AScope; + if (DIDescriptor(N).isSubprogram()) + AbstractScopesList.push_back(AScope); + return AScope; +} + +/// isSubprogramContext - Return true if Context is either a subprogram +/// or another context nested inside a subprogram. +static bool isSubprogramContext(const MDNode *Context) { + if (!Context) + return false; + DIDescriptor D(Context); + if (D.isSubprogram()) + return true; + if (D.isType()) + return isSubprogramContext(DIType(Context).getContext()); + return false; +} + +/// updateSubprogramScopeDIE - Find DIE for the given subprogram and +/// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. +/// If there are global variables in this scope then create and insert +/// DIEs for these variables. +DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) { + CompileUnit *SPCU = getCompileUnit(SPNode); + DIE *SPDie = SPCU->getDIE(SPNode); + + assert(SPDie && "Unable to find subprogram DIE!"); + DISubprogram SP(SPNode); + + // There is not any need to generate specification DIE for a function + // defined at compile unit level. If a function is defined inside another + // function then gdb prefers the definition at top level and but does not + // expect specification DIE in parent function. So avoid creating + // specification DIE for a function defined inside a function. + if (SP.isDefinition() && !SP.getContext().isCompileUnit() && + !SP.getContext().isFile() && + !isSubprogramContext(SP.getContext())) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + DIType ATy = DIType(DIType(Args.getElement(i))); + addType(Arg, ATy); + if (ATy.isArtificial()) + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); + SPCU->addDie(SPDie); + } + + // Pick up abstract subprogram DIE. + if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) { + SPDie = new DIE(dwarf::DW_TAG_subprogram); + addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsSPDIE); + SPCU->addDie(SPDie); + } + + addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); + addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + MachineLocation Location(RI->getFrameRegister(*Asm->MF)); + addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + + return SPDie; +} + +/// constructLexicalScope - Construct new DW_TAG_lexical_block +/// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. +DIE *DwarfDebug::constructLexicalScopeDIE(DbgScope *Scope) { + + DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); + if (Scope->isAbstractScope()) + return ScopeDIE; + + const SmallVector &Ranges = Scope->getRanges(); + if (Ranges.empty()) + return 0; + + SmallVector::const_iterator RI = Ranges.begin(); + if (Ranges.size() > 1) { + // .debug_range section has not been laid out yet. Emit offset in + // .debug_range as a uint, size 4, for now. emitDIE will handle + // DW_AT_ranges appropriately. + addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, + DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); + for (SmallVector::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); + DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); + } + DebugRangeSymbols.push_back(NULL); + DebugRangeSymbols.push_back(NULL); + return ScopeDIE; + } + + const MCSymbol *Start = getLabelBeforeInsn(RI->first); + const MCSymbol *End = getLabelAfterInsn(RI->second); + + if (End == 0) return 0; + + assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); + assert(End->isDefined() && "Invalid end label for an inlined scope!"); + + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); + + return ScopeDIE; +} + +/// constructInlinedScopeDIE - This scope represents inlined body of +/// a function. Construct DIE to represent this concrete inlined copy +/// of the function. +DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) { + + const SmallVector &Ranges = Scope->getRanges(); + assert (Ranges.empty() == false + && "DbgScope does not have instruction markers!"); + + // FIXME : .debug_inlined section specification does not clearly state how + // to emit inlined scope that is split into multiple instruction ranges. + // For now, use first instruction range and emit low_pc/high_pc pair and + // corresponding .debug_inlined section entry for this pair. + SmallVector::const_iterator RI = Ranges.begin(); + const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); + const MCSymbol *EndLabel = getLabelAfterInsn(RI->second); + + if (StartLabel == 0 || EndLabel == 0) { + assert (0 && "Unexpected Start and End labels for a inlined scope!"); + return 0; + } + assert(StartLabel->isDefined() && + "Invalid starting label for an inlined scope!"); + assert(EndLabel->isDefined() && + "Invalid end label for an inlined scope!"); + + if (!Scope->getScopeNode()) + return NULL; + DIScope DS(Scope->getScopeNode()); + DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); + + DISubprogram InlinedSP = getDISubprogram(DS); + CompileUnit *TheCU = getCompileUnit(InlinedSP); + DIE *OriginDIE = TheCU->getDIE(InlinedSP); + assert(OriginDIE && "Unable to find Origin DIE!"); + addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, OriginDIE); + + addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); + addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); + + InlinedSubprogramDIEs.insert(OriginDIE); + + // Track the start label for this inlined function. + DenseMap >::iterator + I = InlineInfo.find(InlinedSP); + + if (I == InlineInfo.end()) { + InlineInfo[InlinedSP].push_back(std::make_pair(StartLabel, + ScopeDIE)); + InlinedSPNodes.push_back(InlinedSP); + } else + I->second.push_back(std::make_pair(StartLabel, ScopeDIE)); + + DILocation DL(Scope->getInlinedAt()); + addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID()); + addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); + + return ScopeDIE; +} + + +/// constructVariableDIE - Construct a DIE for the given DbgVariable. +DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) { + StringRef Name = DV->getName(); + if (Name.empty()) + return NULL; + + // Translate tag to proper Dwarf tag. The result variable is dropped for + // now. + unsigned Tag; + switch (DV->getTag()) { + case dwarf::DW_TAG_return_variable: + return NULL; + case dwarf::DW_TAG_arg_variable: + Tag = dwarf::DW_TAG_formal_parameter; + break; + case dwarf::DW_TAG_auto_variable: // fall thru + default: + Tag = dwarf::DW_TAG_variable; + break; + } + + // Define variable debug information entry. + DIE *VariableDie = new DIE(Tag); + + DIE *AbsDIE = NULL; + DenseMap::iterator + V2AVI = VarToAbstractVarMap.find(DV); + if (V2AVI != VarToAbstractVarMap.end()) + AbsDIE = V2AVI->second->getDIE(); + + if (AbsDIE) + addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsDIE); + else { + addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + addSourceLine(VariableDie, DV->getVariable()); + + // Add variable type. + addType(VariableDie, DV->getType()); + } + + if (Tag == dwarf::DW_TAG_formal_parameter && DV->getType().isArtificial()) + addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + else if (DIVariable(DV->getVariable()).isArtificial()) + addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + + if (Scope->isAbstractScope()) { + DV->setDIE(VariableDie); + return VariableDie; + } + + // Add variable address. + + unsigned Offset = DV->getDotDebugLocOffset(); + if (Offset != ~0U) { + addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, + Asm->GetTempSymbol("debug_loc", Offset)); + DV->setDIE(VariableDie); + UseDotDebugLocEntry.insert(VariableDie); + return VariableDie; + } + + // Check if variable is described by a DBG_VALUE instruction. + DenseMap::iterator DVI = + DbgVariableToDbgInstMap.find(DV); + if (DVI != DbgVariableToDbgInstMap.end()) { + const MachineInstr *DVInsn = DVI->second; + bool updated = false; + // FIXME : Handle getNumOperands != 3 + if (DVInsn->getNumOperands() == 3) { + if (DVInsn->getOperand(0).isReg()) { + const MachineOperand RegOp = DVInsn->getOperand(0); + const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + if (DVInsn->getOperand(1).isImm() && + TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { + addVariableAddress(DV, VariableDie, DVInsn->getOperand(1).getImm()); + updated = true; + } else + updated = addRegisterAddress(VariableDie, RegOp); + } + else if (DVInsn->getOperand(0).isImm()) + updated = addConstantValue(VariableDie, DVInsn->getOperand(0)); + else if (DVInsn->getOperand(0).isFPImm()) + updated = + addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + } else { + MachineLocation Location = Asm->getDebugValueLocation(DVInsn); + if (Location.getReg()) { + addAddress(VariableDie, dwarf::DW_AT_location, Location); + updated = true; + } + } + if (!updated) { + // If variableDie is not updated then DBG_VALUE instruction does not + // have valid variable info. + delete VariableDie; + return NULL; + } + DV->setDIE(VariableDie); + return VariableDie; + } + + // .. else use frame index, if available. + int FI = 0; + if (findVariableFrameIndex(DV, &FI)) + addVariableAddress(DV, VariableDie, FI); + + DV->setDIE(VariableDie); + return VariableDie; + +} + +void DwarfDebug::addPubTypes(DISubprogram SP) { + DICompositeType SPTy = SP.getType(); + unsigned SPTag = SPTy.getTag(); + if (SPTag != dwarf::DW_TAG_subroutine_type) + return; + + DIArray Args = SPTy.getTypeArray(); + for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) { + DIType ATy(Args.getElement(i)); + if (!ATy.Verify()) + continue; + DICompositeType CATy = getDICompositeType(ATy); + if (DIDescriptor(CATy).Verify() && !CATy.getName().empty() + && !CATy.isForwardDecl()) { + CompileUnit *TheCU = getCompileUnit(CATy); + if (DIEEntry *Entry = TheCU->getDIEEntry(CATy)) + TheCU->addGlobalType(CATy.getName(), Entry->getEntry()); + } + } +} + +/// constructScopeDIE - Construct a DIE for this scope. +DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) { + if (!Scope || !Scope->getScopeNode()) + return NULL; + + SmallVector Children; + + // Collect arguments for current function. + if (Scope == CurrentFnDbgScope) + for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) + if (DbgVariable *ArgDV = CurrentFnArguments[i]) + if (DIE *Arg = constructVariableDIE(ArgDV, Scope)) + Children.push_back(Arg); + + // Collect lexical scope childrens first. + const SmallVector &Variables = Scope->getDbgVariables(); + for (unsigned i = 0, N = Variables.size(); i < N; ++i) + if (DIE *Variable = constructVariableDIE(Variables[i], Scope)) + Children.push_back(Variable); + const SmallVector &Scopes = Scope->getScopes(); + for (unsigned j = 0, M = Scopes.size(); j < M; ++j) + if (DIE *Nested = constructScopeDIE(Scopes[j])) + Children.push_back(Nested); + DIScope DS(Scope->getScopeNode()); + DIE *ScopeDIE = NULL; + if (Scope->getInlinedAt()) + ScopeDIE = constructInlinedScopeDIE(Scope); + else if (DS.isSubprogram()) { + ProcessedSPNodes.insert(DS); + if (Scope->isAbstractScope()) { + ScopeDIE = getCompileUnit(DS)->getDIE(DS); + // Note down abstract DIE. + if (ScopeDIE) + AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); + } + else + ScopeDIE = updateSubprogramScopeDIE(DS); + } + else { + // There is no need to emit empty lexical block DIE. + if (Children.empty()) + return NULL; + ScopeDIE = constructLexicalScopeDIE(Scope); + } + + if (!ScopeDIE) return NULL; + + // Add children + for (SmallVector::iterator I = Children.begin(), + E = Children.end(); I != E; ++I) + ScopeDIE->addChild(*I); + + if (DS.isSubprogram()) + addPubTypes(DISubprogram(DS)); + + return ScopeDIE; +} + +/// GetOrCreateSourceID - Look up the source id with the given directory and +/// source file names. If none currently exists, create a new id and insert it +/// in the SourceIds map. This can update DirectoryNames and SourceFileNames +/// maps as well. + +unsigned DwarfDebug::GetOrCreateSourceID(StringRef FileName){ + // If FE did not provide a file name, then assume stdin. + if (FileName.empty()) + return GetOrCreateSourceID(""); + + StringMapEntry &Entry = SourceIdMap.GetOrCreateValue(FileName); + if (Entry.getValue()) + return Entry.getValue(); + + unsigned SrcId = SourceIdMap.size(); + Entry.setValue(SrcId); + + // Print out a .file directive to specify files for .loc directives. + Asm->OutStreamer.EmitDwarfFileDirective(SrcId, FileName); + + return SrcId; +} + +/// getOrCreateNameSpace - Create a DIE for DINameSpace. +DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) { + CompileUnit *TheCU = getCompileUnit(NS); + DIE *NDie = TheCU->getDIE(NS); + if (NDie) + return NDie; + NDie = new DIE(dwarf::DW_TAG_namespace); + TheCU->insertDIE(NS, NDie); + if (!NS.getName().empty()) + addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName()); + addSourceLine(NDie, NS); + addToContextOwner(NDie, NS.getContext()); + return NDie; +} + +/// constructCompileUnit - Create new CompileUnit for the given +/// metadata node with tag DW_TAG_compile_unit. +void DwarfDebug::constructCompileUnit(const MDNode *N) { + DICompileUnit DIUnit(N); + StringRef FN = DIUnit.getFilename(); + StringRef Dir = DIUnit.getDirectory(); + unsigned ID = GetOrCreateSourceID(FN); + + DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, + DIUnit.getProducer()); + addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + DIUnit.getLanguage()); + addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); + // Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This + // simplifies debug range entries. + addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0); + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. + if (Asm->MAI->doesDwarfUsesAbsoluteLabelForStmtList()) + addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("section_line")); + else + addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + + if (!Dir.empty()) + addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); + if (DIUnit.isOptimized()) + addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + + StringRef Flags = DIUnit.getFlags(); + if (!Flags.empty()) + addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); + + unsigned RVer = DIUnit.getRunTimeVersion(); + if (RVer) + addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); + + CompileUnit *NewCU = new CompileUnit(ID, Die); + if (!FirstCU) + FirstCU = NewCU; + CUMap.insert(std::make_pair(N, NewCU)); +} + +/// getCompielUnit - Get CompileUnit DIE. +CompileUnit *DwarfDebug::getCompileUnit(const MDNode *N) const { + assert (N && "Invalid DwarfDebug::getCompileUnit argument!"); + DIDescriptor D(N); + const MDNode *CUNode = NULL; + if (D.isCompileUnit()) + CUNode = N; + else if (D.isSubprogram()) + CUNode = DISubprogram(N).getCompileUnit(); + else if (D.isType()) + CUNode = DIType(N).getCompileUnit(); + else if (D.isGlobalVariable()) + CUNode = DIGlobalVariable(N).getCompileUnit(); + else if (D.isVariable()) + CUNode = DIVariable(N).getCompileUnit(); + else if (D.isNameSpace()) + CUNode = DINameSpace(N).getCompileUnit(); + else if (D.isFile()) + CUNode = DIFile(N).getCompileUnit(); + else + return FirstCU; + + DenseMap::const_iterator I + = CUMap.find(CUNode); + if (I == CUMap.end()) + return FirstCU; + return I->second; +} + +/// isUnsignedDIType - Return true if type encoding is unsigned. +static bool isUnsignedDIType(DIType Ty) { + DIDerivedType DTy(Ty); + if (DTy.Verify()) + return isUnsignedDIType(DTy.getTypeDerivedFrom()); + + DIBasicType BTy(Ty); + if (BTy.Verify()) { + unsigned Encoding = BTy.getEncoding(); + if (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char) + return true; + } + return false; +} + +// Return const exprssion if value is a GEP to access merged global +// constant. e.g. +// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) +static const ConstantExpr *getMergedGlobalExpr(const Value *V) { + const ConstantExpr *CE = dyn_cast_or_null(V); + if (!CE || CE->getNumOperands() != 3 || + CE->getOpcode() != Instruction::GetElementPtr) + return NULL; + + // First operand points to a global value. + if (!isa(CE->getOperand(0))) + return NULL; + + // Second operand is zero. + const ConstantInt *CI = + dyn_cast_or_null(CE->getOperand(1)); + if (!CI || !CI->isZero()) + return NULL; + + // Third operand is offset. + if (!isa(CE->getOperand(2))) + return NULL; + + return CE; +} + +/// constructGlobalVariableDIE - Construct global variable DIE. +void DwarfDebug::constructGlobalVariableDIE(const MDNode *N) { + DIGlobalVariable GV(N); + + // If debug information is malformed then ignore it. + if (GV.Verify() == false) + return; + + // Check for pre-existence. + CompileUnit *TheCU = getCompileUnit(N); + if (TheCU->getDIE(GV)) + return; + + DIType GTy = GV.getType(); + DIE *VariableDIE = new DIE(GV.getTag()); + + bool isGlobalVariable = GV.getGlobal() != NULL; + + // Add name. + addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); + StringRef LinkageName = GV.getLinkageName(); + if (!LinkageName.empty() && isGlobalVariable) + addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); + // Add type. + addType(VariableDIE, GTy); + if (GTy.isCompositeType() && !GTy.getName().empty() + && !GTy.isForwardDecl()) { + DIEEntry *Entry = TheCU->getDIEEntry(GTy); + assert(Entry && "Missing global type!"); + TheCU->addGlobalType(GTy.getName(), Entry->getEntry()); + } + // Add scoping info. + if (!GV.isLocalToUnit()) { + addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + // Expose as global. + TheCU->addGlobal(GV.getName(), VariableDIE); + } + // Add line number info. + addSourceLine(VariableDIE, GV); + // Add to map. + TheCU->insertDIE(N, VariableDIE); + // Add to context owner. + DIDescriptor GVContext = GV.getContext(); + addToContextOwner(VariableDIE, GVContext); + // Add location. + if (isGlobalVariable) { + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(GV.getGlobal())); + // Do not create specification DIE if context is either compile unit + // or a subprogram. + if (GV.isDefinition() && !GVContext.isCompileUnit() && + !GVContext.isFile() && !isSubprogramContext(GVContext)) { + // Create specification DIE. + DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); + addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, + dwarf::DW_FORM_ref4, VariableDIE); + addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + TheCU->addDie(VariableSpecDIE); + } else { + addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + } + } else if (ConstantInt *CI = + dyn_cast_or_null(GV.getConstant())) + addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); + else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { + // GV is a merged global. + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(cast(CE->getOperand(0)))); + ConstantInt *CII = cast(CE->getOperand(2)); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + } + + return; +} + +/// construct SubprogramDIE - Construct subprogram DIE. +void DwarfDebug::constructSubprogramDIE(const MDNode *N) { + DISubprogram SP(N); + + // Check for pre-existence. + CompileUnit *TheCU = getCompileUnit(N); + if (TheCU->getDIE(N)) + return; + + if (!SP.isDefinition()) + // This is a method declaration which will be handled while constructing + // class type. + return; + + DIE *SubprogramDie = createSubprogramDIE(SP); + + // Add to map. + TheCU->insertDIE(N, SubprogramDie); + + // Add to context owner. + addToContextOwner(SubprogramDie, SP.getContext()); + + // Expose as global. + TheCU->addGlobal(SP.getName(), SubprogramDie); + + return; +} + +/// beginModule - Emit all Dwarf sections that should come prior to the +/// content. Create global DIEs and emit initial debug info sections. +/// This is inovked by the target AsmPrinter. +void DwarfDebug::beginModule(Module *M) { + if (DisableDebugInfoPrinting) + return; + + DebugInfoFinder DbgFinder; + DbgFinder.processModule(*M); + + bool HasDebugInfo = false; + + // Scan all the compile-units to see if there are any marked as the main unit. + // if not, we do not generate debug info. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) { + if (DICompileUnit(*I).isMain()) { + HasDebugInfo = true; + break; + } + } + + if (!HasDebugInfo) return; + + // Tell MMI that we have debug info. + MMI->setDebugInfoAvailability(true); + + // Emit initial sections. + EmitSectionLabels(); + + // Create all the compile unit DIEs. + for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), + E = DbgFinder.compile_unit_end(); I != E; ++I) + constructCompileUnit(*I); + + // Create DIEs for each subprogram. + for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(), + E = DbgFinder.subprogram_end(); I != E; ++I) + constructSubprogramDIE(*I); + + // Create DIEs for each global variable. + for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(), + E = DbgFinder.global_variable_end(); I != E; ++I) + constructGlobalVariableDIE(*I); + + //getOrCreateTypeDIE + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + + if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) + getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + + // Prime section data. + SectionMap.insert(Asm->getObjFileLowering().getTextSection()); +} + +/// endModule - Emit all Dwarf sections that should come after the content. +/// +void DwarfDebug::endModule() { + if (!FirstCU) return; + const Module *M = MMI->getModule(); + DenseMap DeadFnScopeMap; + if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) { + for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) { + if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue; + DISubprogram SP(AllSPs->getOperand(SI)); + if (!SP.Verify()) continue; + + // Collect info for variables that were optimized out. + if (!SP.isDefinition()) continue; + StringRef FName = SP.getLinkageName(); + if (FName.empty()) + FName = SP.getName(); + NamedMDNode *NMD = getFnSpecificMDNode(*(MMI->getModule()), FName); + if (!NMD) continue; + unsigned E = NMD->getNumOperands(); + if (!E) continue; + DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL); + DeadFnScopeMap[SP] = Scope; + for (unsigned I = 0; I != E; ++I) { + DIVariable DV(NMD->getOperand(I)); + if (!DV.Verify()) continue; + Scope->addVariable(new DbgVariable(DV)); + } + + // Construct subprogram DIE and add variables DIEs. + constructSubprogramDIE(SP); + DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP); + const SmallVector &Variables = Scope->getDbgVariables(); + for (unsigned i = 0, N = Variables.size(); i < N; ++i) { + DIE *VariableDIE = constructVariableDIE(Variables[i], Scope); + if (VariableDIE) + ScopeDIE->addChild(VariableDIE); + } + } + } + + // Attach DW_AT_inline attribute with inlined subprogram DIEs. + for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), + AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { + DIE *ISP = *AI; + addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + } + + for (DenseMap::iterator CI = ContainingTypeMap.begin(), + CE = ContainingTypeMap.end(); CI != CE; ++CI) { + DIE *SPDie = CI->first; + const MDNode *N = dyn_cast_or_null(CI->second); + if (!N) continue; + DIE *NDie = getCompileUnit(N)->getDIE(N); + if (!NDie) continue; + addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie); + } + + // Standard sections final addresses. + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end")); + Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end")); + + // End text sections. + for (unsigned i = 1, N = SectionMap.size(); i <= N; ++i) { + Asm->OutStreamer.SwitchSection(SectionMap[i]); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", i)); + } + + // Emit common frame information. + emitCommonDebugFrame(); + + // Emit function debug frame information + for (std::vector::iterator I = DebugFrames.begin(), + E = DebugFrames.end(); I != E; ++I) + emitFunctionDebugFrame(*I); + + // Compute DIE offsets and sizes. + computeSizeAndOffsets(); + + // Emit all the DIEs into a debug info section + emitDebugInfo(); + + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); + + // Emit info into a debug pubnames section. + emitDebugPubNames(); + + // Emit info into a debug pubtypes section. + emitDebugPubTypes(); + + // Emit info into a debug loc section. + emitDebugLoc(); + + // Emit info into a debug aranges section. + EmitDebugARanges(); + + // Emit info into a debug ranges section. + emitDebugRanges(); + + // Emit info into a debug macinfo section. + emitDebugMacInfo(); + + // Emit inline info. + emitDebugInlineInfo(); + + // Emit info into a debug str section. + emitDebugStr(); + + // clean up. + DeleteContainerSeconds(DeadFnScopeMap); + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) + delete I->second; + FirstCU = NULL; // Reset for the next Module, if any. +} + +/// findAbstractVariable - Find abstract variable, if any, associated with Var. +DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &Var, + DebugLoc ScopeLoc) { + + DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var); + if (AbsDbgVariable) + return AbsDbgVariable; + + LLVMContext &Ctx = Var->getContext(); + DbgScope *Scope = AbstractScopes.lookup(ScopeLoc.getScope(Ctx)); + if (!Scope) + return NULL; + + AbsDbgVariable = new DbgVariable(Var); + Scope->addVariable(AbsDbgVariable); + AbstractVariables[Var] = AbsDbgVariable; + return AbsDbgVariable; +} + +/// addCurrentFnArgument - If Var is an current function argument that add +/// it in CurrentFnArguments list. +bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, + DbgVariable *Var, DbgScope *Scope) { + if (Scope != CurrentFnDbgScope) + return false; + DIVariable DV = Var->getVariable(); + if (DV.getTag() != dwarf::DW_TAG_arg_variable) + return false; + unsigned ArgNo = DV.getArgNumber(); + if (ArgNo == 0) + return false; + + size_t Size = CurrentFnArguments.size(); + if (Size == 0) + CurrentFnArguments.resize(MF->getFunction()->arg_size()); + // llvm::Function argument size is not good indicator of how many + // arguments does the function have at source level. + if (ArgNo > Size) + CurrentFnArguments.resize(ArgNo * 2); + CurrentFnArguments[ArgNo - 1] = Var; + return true; +} + +/// collectVariableInfoFromMMITable - Collect variable information from +/// side table maintained by MMI. +void +DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, + SmallPtrSet &Processed) { + const LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); + MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); + for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), + VE = VMap.end(); VI != VE; ++VI) { + const MDNode *Var = VI->first; + if (!Var) continue; + Processed.insert(Var); + DIVariable DV(Var); + const std::pair &VP = VI->second; + + DbgScope *Scope = 0; + if (const MDNode *IA = VP.second.getInlinedAt(Ctx)) + Scope = ConcreteScopes.lookup(IA); + if (Scope == 0) + Scope = DbgScopeMap.lookup(VP.second.getScope(Ctx)); + + // If variable scope is not found then skip this variable. + if (Scope == 0) + continue; + + DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); + DbgVariable *RegVar = new DbgVariable(DV); + recordVariableFrameIndex(RegVar, VP.first); + if (!addCurrentFnArgument(MF, RegVar, Scope)) + Scope->addVariable(RegVar); + if (AbsDbgVariable) { + recordVariableFrameIndex(AbsDbgVariable, VP.first); + VarToAbstractVarMap[RegVar] = AbsDbgVariable; + } + } +} + +/// isDbgValueInDefinedReg - Return true if debug value, encoded by +/// DBG_VALUE instruction, is in a defined reg. +static bool isDbgValueInDefinedReg(const MachineInstr *MI) { + assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); + if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg()) + return true; + return false; +} + +/// collectVariableInfo - Populate DbgScope entries with variables' info. +void +DwarfDebug::collectVariableInfo(const MachineFunction *MF, + SmallPtrSet &Processed) { + + /// collection info from MMI table. + collectVariableInfoFromMMITable(MF, Processed); + + SmallVector DbgValues; + // Collect variable information from DBG_VALUE machine instructions; + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + if (!MInsn->isDebugValue()) + continue; + DbgValues.push_back(MInsn); + } + + // This is a collection of DBV_VALUE instructions describing same variable. + SmallVector MultipleValues; + for(SmallVector::iterator I = DbgValues.begin(), + E = DbgValues.end(); I != E; ++I) { + const MachineInstr *MInsn = *I; + MultipleValues.clear(); + if (isDbgValueInDefinedReg(MInsn)) + MultipleValues.push_back(MInsn); + DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata()); + if (Processed.count(DV) != 0) + continue; + + const MachineInstr *PrevMI = MInsn; + for (SmallVector::iterator MI = I+1, + ME = DbgValues.end(); MI != ME; ++MI) { + const MDNode *Var = + (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata(); + if (Var == DV && + !PrevMI->isIdenticalTo(*MI)) + MultipleValues.push_back(*MI); + PrevMI = *MI; + } + + DbgScope *Scope = NULL; + if (DV.getTag() == dwarf::DW_TAG_arg_variable && + DISubprogram(DV.getContext()).describes(MF->getFunction())) + Scope = CurrentFnDbgScope; + else + Scope = findDbgScope(MInsn); + // If variable scope is not found then skip this variable. + if (!Scope) + continue; + + Processed.insert(DV); + DbgVariable *RegVar = new DbgVariable(DV); + if (!addCurrentFnArgument(MF, RegVar, Scope)) + Scope->addVariable(RegVar); + if (DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc())) { + DbgVariableToDbgInstMap[AbsVar] = MInsn; + VarToAbstractVarMap[RegVar] = AbsVar; + } + if (MultipleValues.size() <= 1) { + DbgVariableToDbgInstMap[RegVar] = MInsn; + continue; + } + + // handle multiple DBG_VALUE instructions describing one variable. + if (DotDebugLocEntries.empty()) + RegVar->setDotDebugLocOffset(0); + else + RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); + const MachineInstr *Begin = NULL; + const MachineInstr *End = NULL; + for (SmallVector::iterator + MVI = MultipleValues.begin(), MVE = MultipleValues.end(); + MVI != MVE; ++MVI) { + if (!Begin) { + Begin = *MVI; + continue; + } + End = *MVI; + MachineLocation MLoc; + if (Begin->getNumOperands() == 3) { + if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm()) + MLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm()); + } else + MLoc = Asm->getDebugValueLocation(Begin); + + const MCSymbol *FLabel = getLabelBeforeInsn(Begin); + const MCSymbol *SLabel = getLabelBeforeInsn(End); + if (MLoc.getReg()) + DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc)); + + Begin = End; + if (MVI + 1 == MVE) { + // If End is the last instruction then its value is valid + // until the end of the funtion. + MachineLocation EMLoc; + if (End->getNumOperands() == 3) { + if (End->getOperand(0).isReg() && Begin->getOperand(1).isImm()) + EMLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm()); + } else + EMLoc = Asm->getDebugValueLocation(End); + if (EMLoc.getReg()) + DotDebugLocEntries. + push_back(DotDebugLocEntry(SLabel, FunctionEndSym, EMLoc)); + } + } + DotDebugLocEntries.push_back(DotDebugLocEntry()); + } + + // Collect info for variables that were optimized out. + const Function *F = MF->getFunction(); + if (NamedMDNode *NMD = getFnSpecificMDNode(*(F->getParent()), F->getName())) { + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIVariable DV(cast(NMD->getOperand(i))); + if (!DV || !Processed.insert(DV)) + continue; + DbgScope *Scope = DbgScopeMap.lookup(DV.getContext()); + if (Scope) + Scope->addVariable(new DbgVariable(DV)); + } + } +} + +/// getLabelBeforeInsn - Return Label preceding the instruction. +const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { + DenseMap::iterator I = + LabelsBeforeInsn.find(MI); + if (I == LabelsBeforeInsn.end()) + // FunctionBeginSym always preceeds all the instruction in current function. + return FunctionBeginSym; + return I->second; +} + +/// getLabelAfterInsn - Return Label immediately following the instruction. +const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { + DenseMap::iterator I = + LabelsAfterInsn.find(MI); + if (I == LabelsAfterInsn.end()) + return NULL; + return I->second; +} + +/// beginInstruction - Process beginning of an instruction. +void DwarfDebug::beginInstruction(const MachineInstr *MI) { + if (InsnNeedsLabel.count(MI) == 0) { + LabelsBeforeInsn[MI] = PrevLabel; + return; + } + + // Check location. + DebugLoc DL = MI->getDebugLoc(); + if (!DL.isUnknown()) { + const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); + PrevLabel = recordSourceLine(DL.getLine(), DL.getCol(), Scope); + PrevInstLoc = DL; + LabelsBeforeInsn[MI] = PrevLabel; + return; + } + + // If location is unknown then use temp label for this DBG_VALUE + // instruction. + if (MI->isDebugValue()) { + PrevLabel = MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(PrevLabel); + LabelsBeforeInsn[MI] = PrevLabel; + return; + } + + if (UnknownLocations) { + PrevLabel = recordSourceLine(0, 0, 0); + LabelsBeforeInsn[MI] = PrevLabel; + return; + } + + assert (0 && "Instruction is not processed!"); +} + +/// endInstruction - Process end of an instruction. +void DwarfDebug::endInstruction(const MachineInstr *MI) { + if (InsnsEndScopeSet.count(MI) != 0) { + // Emit a label if this instruction ends a scope. + MCSymbol *Label = MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(Label); + LabelsAfterInsn[MI] = Label; + } +} + +/// getOrCreateDbgScope - Create DbgScope for the scope. +DbgScope *DwarfDebug::getOrCreateDbgScope(const MDNode *Scope, + const MDNode *InlinedAt) { + if (!InlinedAt) { + DbgScope *WScope = DbgScopeMap.lookup(Scope); + if (WScope) + return WScope; + WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL); + DbgScopeMap.insert(std::make_pair(Scope, WScope)); + if (DIDescriptor(Scope).isLexicalBlock()) { + DbgScope *Parent = + getOrCreateDbgScope(DILexicalBlock(Scope).getContext(), NULL); + WScope->setParent(Parent); + Parent->addScope(WScope); + } + + if (!WScope->getParent()) { + StringRef SPName = DISubprogram(Scope).getLinkageName(); + // We used to check only for a linkage name, but that fails + // since we began omitting the linkage name for private + // functions. The new way is to check for the name in metadata, + // but that's not supported in old .ll test cases. Ergo, we + // check both. + if (SPName == Asm->MF->getFunction()->getName() || + DISubprogram(Scope).getFunction() == Asm->MF->getFunction()) + CurrentFnDbgScope = WScope; + } + + return WScope; + } + + getOrCreateAbstractScope(Scope); + DbgScope *WScope = DbgScopeMap.lookup(InlinedAt); + if (WScope) + return WScope; + + WScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt); + DbgScopeMap.insert(std::make_pair(InlinedAt, WScope)); + DILocation DL(InlinedAt); + DbgScope *Parent = + getOrCreateDbgScope(DL.getScope(), DL.getOrigLocation()); + WScope->setParent(Parent); + Parent->addScope(WScope); + + ConcreteScopes[InlinedAt] = WScope; + + return WScope; +} + +/// hasValidLocation - Return true if debug location entry attached with +/// machine instruction encodes valid location info. +static bool hasValidLocation(LLVMContext &Ctx, + const MachineInstr *MInsn, + const MDNode *&Scope, const MDNode *&InlinedAt) { + DebugLoc DL = MInsn->getDebugLoc(); + if (DL.isUnknown()) return false; + + const MDNode *S = DL.getScope(Ctx); + + // There is no need to create another DIE for compile unit. For all + // other scopes, create one DbgScope now. This will be translated + // into a scope DIE at the end. + if (DIScope(S).isCompileUnit()) return false; + + Scope = S; + InlinedAt = DL.getInlinedAt(Ctx); + return true; +} + +/// calculateDominanceGraph - Calculate dominance graph for DbgScope +/// hierarchy. +static void calculateDominanceGraph(DbgScope *Scope) { + assert (Scope && "Unable to calculate scop edominance graph!"); + SmallVector WorkStack; + WorkStack.push_back(Scope); + unsigned Counter = 0; + while (!WorkStack.empty()) { + DbgScope *WS = WorkStack.back(); + const SmallVector &Children = WS->getScopes(); + bool visitedChildren = false; + for (SmallVector::const_iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) { + DbgScope *ChildScope = *SI; + if (!ChildScope->getDFSOut()) { + WorkStack.push_back(ChildScope); + visitedChildren = true; + ChildScope->setDFSIn(++Counter); + break; + } + } + if (!visitedChildren) { + WorkStack.pop_back(); + WS->setDFSOut(++Counter); + } + } +} + +/// printDbgScopeInfo - Print DbgScope info for each machine instruction. +static +void printDbgScopeInfo(LLVMContext &Ctx, const MachineFunction *MF, + DenseMap &MI2ScopeMap) +{ +#ifndef NDEBUG + unsigned PrevDFSIn = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + const MDNode *Scope = NULL; + const MDNode *InlinedAt = NULL; + + // Check if instruction has valid location information. + if (hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) { + dbgs() << " [ "; + if (InlinedAt) + dbgs() << "*"; + DenseMap::iterator DI = + MI2ScopeMap.find(MInsn); + if (DI != MI2ScopeMap.end()) { + DbgScope *S = DI->second; + dbgs() << S->getDFSIn(); + PrevDFSIn = S->getDFSIn(); + } else + dbgs() << PrevDFSIn; + } else + dbgs() << " [ x" << PrevDFSIn; + dbgs() << " ]"; + MInsn->dump(); + } + dbgs() << "\n"; + } +#endif +} +/// extractScopeInformation - Scan machine instructions in this function +/// and collect DbgScopes. Return true, if at least one scope was found. +bool DwarfDebug::extractScopeInformation() { + // If scope information was extracted using .dbg intrinsics then there is not + // any need to extract these information by scanning each instruction. + if (!DbgScopeMap.empty()) + return false; + + // Scan each instruction and create scopes. First build working set of scopes. + LLVMContext &Ctx = Asm->MF->getFunction()->getContext(); + SmallVector MIRanges; + DenseMap MI2ScopeMap; + const MDNode *PrevScope = NULL; + const MDNode *PrevInlinedAt = NULL; + const MachineInstr *RangeBeginMI = NULL; + const MachineInstr *PrevMI = NULL; + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + const MDNode *Scope = NULL; + const MDNode *InlinedAt = NULL; + + // Check if instruction has valid location information. + if (!hasValidLocation(Ctx, MInsn, Scope, InlinedAt)) { + PrevMI = MInsn; + continue; + } + + // If scope has not changed then skip this instruction. + if (Scope == PrevScope && PrevInlinedAt == InlinedAt) { + PrevMI = MInsn; + continue; + } + + // Ignore DBG_VALUE. It does not contribute any instruction in output. + if (MInsn->isDebugValue()) + continue; + + if (RangeBeginMI) { + // If we have alread seen a beginning of a instruction range and + // current instruction scope does not match scope of first instruction + // in this range then create a new instruction range. + DbgRange R(RangeBeginMI, PrevMI); + MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, + PrevInlinedAt); + MIRanges.push_back(R); + } + + // This is a beginning of a new instruction range. + RangeBeginMI = MInsn; + + // Reset previous markers. + PrevMI = MInsn; + PrevScope = Scope; + PrevInlinedAt = InlinedAt; + } + } + + // Create last instruction range. + if (RangeBeginMI && PrevMI && PrevScope) { + DbgRange R(RangeBeginMI, PrevMI); + MIRanges.push_back(R); + MI2ScopeMap[RangeBeginMI] = getOrCreateDbgScope(PrevScope, PrevInlinedAt); + } + + if (!CurrentFnDbgScope) + return false; + + calculateDominanceGraph(CurrentFnDbgScope); + if (PrintDbgScope) + printDbgScopeInfo(Ctx, Asm->MF, MI2ScopeMap); + + // Find ranges of instructions covered by each DbgScope; + DbgScope *PrevDbgScope = NULL; + for (SmallVector::const_iterator RI = MIRanges.begin(), + RE = MIRanges.end(); RI != RE; ++RI) { + const DbgRange &R = *RI; + DbgScope *S = MI2ScopeMap.lookup(R.first); + assert (S && "Lost DbgScope for a machine instruction!"); + if (PrevDbgScope && !PrevDbgScope->dominates(S)) + PrevDbgScope->closeInsnRange(S); + S->openInsnRange(R.first); + S->extendInsnRange(R.second); + PrevDbgScope = S; + } + + if (PrevDbgScope) + PrevDbgScope->closeInsnRange(); + + identifyScopeMarkers(); + + return !DbgScopeMap.empty(); +} + +/// identifyScopeMarkers() - +/// Each DbgScope has first instruction and last instruction to mark beginning +/// and end of a scope respectively. Create an inverse map that list scopes +/// starts (and ends) with an instruction. One instruction may start (or end) +/// multiple scopes. Ignore scopes that are not reachable. +void DwarfDebug::identifyScopeMarkers() { + SmallVector WorkList; + WorkList.push_back(CurrentFnDbgScope); + while (!WorkList.empty()) { + DbgScope *S = WorkList.pop_back_val(); + + const SmallVector &Children = S->getScopes(); + if (!Children.empty()) + for (SmallVector::const_iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) + WorkList.push_back(*SI); + + if (S->isAbstractScope()) + continue; + + const SmallVector &Ranges = S->getRanges(); + if (Ranges.empty()) + continue; + for (SmallVector::const_iterator RI = Ranges.begin(), + RE = Ranges.end(); RI != RE; ++RI) { + assert(RI->first && "DbgRange does not have first instruction!"); + assert(RI->second && "DbgRange does not have second instruction!"); + InsnsEndScopeSet.insert(RI->second); + } + } +} + +/// FindFirstDebugLoc - Find the first debug location in the function. This +/// is intended to be an approximation for the source position of the +/// beginning of the function. +static DebugLoc FindFirstDebugLoc(const MachineFunction *MF) { + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator MBBI = I->begin(), MBBE = I->end(); + MBBI != MBBE; ++MBBI) { + DebugLoc DL = MBBI->getDebugLoc(); + if (!DL.isUnknown()) + return DL; + } + return DebugLoc(); +} + +#ifndef NDEBUG +/// CheckLineNumbers - Count basicblocks whose instructions do not have any +/// line number information. +static void CheckLineNumbers(const MachineFunction *MF) { + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + bool FoundLineNo = false; + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MI = II; + if (!MI->getDebugLoc().isUnknown()) { + FoundLineNo = true; + break; + } + } + if (!FoundLineNo && I->size()) + ++BlocksWithoutLineNo; + } +} +#endif + +/// beginFunction - Gather pre-function debug information. Assumes being +/// emitted immediately after the function entry point. +void DwarfDebug::beginFunction(const MachineFunction *MF) { + if (!MMI->hasDebugInfo()) return; + if (!extractScopeInformation()) return; + +#ifndef NDEBUG + CheckLineNumbers(MF); +#endif + + FunctionBeginSym = Asm->GetTempSymbol("func_begin", + Asm->getFunctionNumber()); + // Assumes in correct section after the entry point. + Asm->OutStreamer.EmitLabel(FunctionBeginSym); + + // Emit label for the implicitly defined dbg.stoppoint at the start of the + // function. + DebugLoc FDL = FindFirstDebugLoc(MF); + if (FDL.isUnknown()) return; + + const MDNode *Scope = FDL.getScope(MF->getFunction()->getContext()); + const MDNode *TheScope = 0; + + DISubprogram SP = getDISubprogram(Scope); + unsigned Line, Col; + if (SP.Verify()) { + Line = SP.getLineNumber(); + Col = 0; + TheScope = SP; + } else { + Line = FDL.getLine(); + Col = FDL.getCol(); + TheScope = Scope; + } + + recordSourceLine(Line, Col, TheScope); + + /// ProcessedArgs - Collection of arguments already processed. + SmallPtrSet ProcessedArgs; + + DebugLoc PrevLoc; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MI = II; + DebugLoc DL = MI->getDebugLoc(); + if (MI->isDebugValue()) { + assert (MI->getNumOperands() > 1 && "Invalid machine instruction!"); + DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata()); + if (!DV.Verify()) continue; + // If DBG_VALUE is for a local variable then it needs a label. + if (DV.getTag() != dwarf::DW_TAG_arg_variable) + InsnNeedsLabel.insert(MI); + // DBG_VALUE for inlined functions argument needs a label. + else if (!DISubprogram(getDISubprogram(DV.getContext())). + describes(MF->getFunction())) + InsnNeedsLabel.insert(MI); + // DBG_VALUE indicating argument location change needs a label. + else if (!ProcessedArgs.insert(DV)) + InsnNeedsLabel.insert(MI); + } else { + // If location is unknown then instruction needs a location only if + // UnknownLocations flag is set. + if (DL.isUnknown()) { + if (UnknownLocations && !PrevLoc.isUnknown()) + InsnNeedsLabel.insert(MI); + } else if (DL != PrevLoc) + // Otherwise, instruction needs a location only if it is new location. + InsnNeedsLabel.insert(MI); + } + + if (!DL.isUnknown() || UnknownLocations) + PrevLoc = DL; + } + + PrevLabel = FunctionBeginSym; +} + +/// endFunction - Gather and emit post-function debug information. +/// +void DwarfDebug::endFunction(const MachineFunction *MF) { + if (!MMI->hasDebugInfo() || DbgScopeMap.empty()) return; + + if (CurrentFnDbgScope) { + + // Define end label for subprogram. + FunctionEndSym = Asm->GetTempSymbol("func_end", + Asm->getFunctionNumber()); + // Assumes in correct section after the entry point. + Asm->OutStreamer.EmitLabel(FunctionEndSym); + + SmallPtrSet ProcessedVars; + collectVariableInfo(MF, ProcessedVars); + + // Construct abstract scopes. + for (SmallVector::iterator AI = AbstractScopesList.begin(), + AE = AbstractScopesList.end(); AI != AE; ++AI) { + DISubprogram SP((*AI)->getScopeNode()); + if (SP.Verify()) { + // Collect info for variables that were optimized out. + StringRef FName = SP.getLinkageName(); + if (FName.empty()) + FName = SP.getName(); + if (NamedMDNode *NMD = + getFnSpecificMDNode(*(MF->getFunction()->getParent()), FName)) { + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIVariable DV(cast(NMD->getOperand(i))); + if (!DV || !ProcessedVars.insert(DV)) + continue; + DbgScope *Scope = AbstractScopes.lookup(DV.getContext()); + if (Scope) + Scope->addVariable(new DbgVariable(DV)); + } + } + } + if (ProcessedSPNodes.count((*AI)->getScopeNode()) == 0) + constructScopeDIE(*AI); + } + + DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope); + + if (!DisableFramePointerElim(*MF)) + addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr, + dwarf::DW_FORM_flag, 1); + + + DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), + MMI->getFrameMoves())); + } + + // Clear debug info + CurrentFnDbgScope = NULL; + CurrentFnArguments.clear(); + InsnNeedsLabel.clear(); + DbgVariableToFrameIndexMap.clear(); + VarToAbstractVarMap.clear(); + DbgVariableToDbgInstMap.clear(); + DeleteContainerSeconds(DbgScopeMap); + InsnsEndScopeSet.clear(); + ConcreteScopes.clear(); + DeleteContainerSeconds(AbstractScopes); + AbstractScopesList.clear(); + AbstractVariables.clear(); + LabelsBeforeInsn.clear(); + LabelsAfterInsn.clear(); + PrevLabel = NULL; +} + +/// recordVariableFrameIndex - Record a variable's index. +void DwarfDebug::recordVariableFrameIndex(const DbgVariable *V, int Index) { + assert (V && "Invalid DbgVariable!"); + DbgVariableToFrameIndexMap[V] = Index; +} + +/// findVariableFrameIndex - Return true if frame index for the variable +/// is found. Update FI to hold value of the index. +bool DwarfDebug::findVariableFrameIndex(const DbgVariable *V, int *FI) { + assert (V && "Invalid DbgVariable!"); + DenseMap::iterator I = + DbgVariableToFrameIndexMap.find(V); + if (I == DbgVariableToFrameIndexMap.end()) + return false; + *FI = I->second; + return true; +} + +/// findDbgScope - Find DbgScope for the debug loc attached with an +/// instruction. +DbgScope *DwarfDebug::findDbgScope(const MachineInstr *MInsn) { + DbgScope *Scope = NULL; + LLVMContext &Ctx = + MInsn->getParent()->getParent()->getFunction()->getContext(); + DebugLoc DL = MInsn->getDebugLoc(); + + if (DL.isUnknown()) + return Scope; + + if (const MDNode *IA = DL.getInlinedAt(Ctx)) + Scope = ConcreteScopes.lookup(IA); + if (Scope == 0) + Scope = DbgScopeMap.lookup(DL.getScope(Ctx)); + + return Scope; +} + + +/// recordSourceLine - Register a source line with debug info. Returns the +/// unique label that was emitted and which provides correspondence to +/// the source line list. +MCSymbol *DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, + const MDNode *S) { + StringRef Fn; + + unsigned Src = 1; + if (S) { + DIDescriptor Scope(S); + + if (Scope.isCompileUnit()) { + DICompileUnit CU(S); + Fn = CU.getFilename(); + } else if (Scope.isFile()) { + DIFile F(S); + Fn = F.getFilename(); + } else if (Scope.isSubprogram()) { + DISubprogram SP(S); + Fn = SP.getFilename(); + } else if (Scope.isLexicalBlock()) { + DILexicalBlock DB(S); + Fn = DB.getFilename(); + } else + assert(0 && "Unexpected scope info"); + + Src = GetOrCreateSourceID(Fn); + } + + Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, DWARF2_FLAG_IS_STMT, + 0, 0); + + MCSymbol *Label = MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(Label); + return Label; +} + +//===----------------------------------------------------------------------===// +// Emit Methods +//===----------------------------------------------------------------------===// + +/// computeSizeAndOffset - Compute the size and offset of a DIE. +/// +unsigned +DwarfDebug::computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last) { + // Get the children. + const std::vector &Children = Die->getChildren(); + + // If not last sibling and has children then add sibling offset attribute. + if (!Last && !Children.empty()) + Die->addSiblingOffset(DIEValueAllocator); + + // Record the abbreviation. + assignAbbrevNumber(Die->getAbbrev()); + + // Get the abbreviation for this DIE. + unsigned AbbrevNumber = Die->getAbbrevNumber(); + const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + + // Set DIE offset + Die->setOffset(Offset); + + // Start the size with the size of abbreviation code. + Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); + + const SmallVector &Values = Die->getValues(); + const SmallVector &AbbrevData = Abbrev->getData(); + + // Size the DIE attribute values. + for (unsigned i = 0, N = Values.size(); i < N; ++i) + // Size attribute value. + Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); + + // Size the DIE children if any. + if (!Children.empty()) { + assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes && + "Children flag not set"); + + for (unsigned j = 0, M = Children.size(); j < M; ++j) + Offset = computeSizeAndOffset(Children[j], Offset, (j + 1) == M); + + // End of children marker. + Offset += sizeof(int8_t); + } + + Die->setSize(Offset - Die->getOffset()); + return Offset; +} + +/// computeSizeAndOffsets - Compute the size and offset of all the DIEs. +/// +void DwarfDebug::computeSizeAndOffsets() { + unsigned PrevOffset = 0; + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + // Compute size of compile unit header. + static unsigned Offset = PrevOffset + + sizeof(int32_t) + // Length of Compilation Unit Info + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t); // Pointer Size (in bytes) + computeSizeAndOffset(I->second->getCUDie(), Offset, true); + PrevOffset = Offset; + } +} + +/// EmitSectionSym - Switch to the specified MCSection and emit an assembler +/// temporary label to it if SymbolStem is specified. +static MCSymbol *EmitSectionSym(AsmPrinter *Asm, const MCSection *Section, + const char *SymbolStem = 0) { + Asm->OutStreamer.SwitchSection(Section); + if (!SymbolStem) return 0; + + MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); + Asm->OutStreamer.EmitLabel(TmpSym); + return TmpSym; +} + +/// EmitSectionLabels - Emit initial Dwarf sections with a label at +/// the start of each one. +void DwarfDebug::EmitSectionLabels() { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + // Dwarf sections base addresses. + if (Asm->MAI->doesDwarfRequireFrameSection()) { + DwarfFrameSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfFrameSection(), "section_debug_frame"); + } + + DwarfInfoSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + DwarfAbbrevSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + EmitSectionSym(Asm, TLOF.getDwarfARangesSection()); + + if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) + EmitSectionSym(Asm, MacroInfo); + + EmitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); + EmitSectionSym(Asm, TLOF.getDwarfLocSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubNamesSection()); + EmitSectionSym(Asm, TLOF.getDwarfPubTypesSection()); + DwarfStrSectionSym = + EmitSectionSym(Asm, TLOF.getDwarfStrSection(), "section_str"); + DwarfDebugRangeSectionSym = EmitSectionSym(Asm, TLOF.getDwarfRangesSection(), + "debug_range"); + + DwarfDebugLocSectionSym = EmitSectionSym(Asm, TLOF.getDwarfLocSection(), + "section_debug_loc"); + + TextSectionSym = EmitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); + EmitSectionSym(Asm, TLOF.getDataSection()); +} + +/// emitDIE - Recusively Emits a debug information entry. +/// +void DwarfDebug::emitDIE(DIE *Die) { + // Get the abbreviation for this DIE. + unsigned AbbrevNumber = Die->getAbbrevNumber(); + const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + + // Emit the code (index) for the abbreviation. + if (Asm->isVerbose()) + Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + + Twine::utohexstr(Die->getOffset()) + ":0x" + + Twine::utohexstr(Die->getSize()) + " " + + dwarf::TagString(Abbrev->getTag())); + Asm->EmitULEB128(AbbrevNumber); + + const SmallVector &Values = Die->getValues(); + const SmallVector &AbbrevData = Abbrev->getData(); + + // Emit the DIE attribute values. + for (unsigned i = 0, N = Values.size(); i < N; ++i) { + unsigned Attr = AbbrevData[i].getAttribute(); + unsigned Form = AbbrevData[i].getForm(); + assert(Form && "Too many attributes for DIE (check abbreviation)"); + + if (Asm->isVerbose()) + Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); + + switch (Attr) { + case dwarf::DW_AT_sibling: + Asm->EmitInt32(Die->getSiblingOffset()); + break; + case dwarf::DW_AT_abstract_origin: { + DIEEntry *E = cast(Values[i]); + DIE *Origin = E->getEntry(); + unsigned Addr = Origin->getOffset(); + Asm->EmitInt32(Addr); + break; + } + case dwarf::DW_AT_ranges: { + // DW_AT_range Value encodes offset in debug_range section. + DIEInteger *V = cast(Values[i]); + + if (Asm->MAI->doesDwarfUsesLabelOffsetForRanges()) { + Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, + V->getValue(), + 4); + } else { + Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym, + V->getValue(), + DwarfDebugRangeSectionSym, + 4); + } + break; + } + case dwarf::DW_AT_location: { + if (UseDotDebugLocEntry.count(Die) != 0) { + DIELabel *L = cast(Values[i]); + Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4); + } else + Values[i]->EmitValue(Asm, Form); + break; + } + case dwarf::DW_AT_accessibility: { + if (Asm->isVerbose()) { + DIEInteger *V = cast(Values[i]); + Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue())); + } + Values[i]->EmitValue(Asm, Form); + break; + } + default: + // Emit an attribute using the defined form. + Values[i]->EmitValue(Asm, Form); + break; + } + } + + // Emit the DIE children if any. + if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) { + const std::vector &Children = Die->getChildren(); + + for (unsigned j = 0, M = Children.size(); j < M; ++j) + emitDIE(Children[j]); + + if (Asm->isVerbose()) + Asm->OutStreamer.AddComment("End Of Children Mark"); + Asm->EmitInt8(0); + } +} + +/// emitDebugInfo - Emit the debug info section. +/// +void DwarfDebug::emitDebugInfo() { + // Start debug info section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfInfoSection()); + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + DIE *Die = TheCU->getCUDie(); + + // Emit the compile units header. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_begin", + TheCU->getID())); + + // Emit size of content not including length itself + unsigned ContentSize = Die->getSize() + + sizeof(int16_t) + // DWARF version number + sizeof(int32_t) + // Offset Into Abbrev. Section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int32_t); // FIXME - extra pad for gdb bug. + + Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); + Asm->EmitInt32(ContentSize); + Asm->OutStreamer.AddComment("DWARF version number"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); + Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"), + DwarfAbbrevSectionSym); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); + + emitDIE(Die); + // FIXME - extra padding for gdb bug. + Asm->OutStreamer.AddComment("4 extra padding bytes for GDB"); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->EmitInt8(0); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID())); + } +} + +/// emitAbbreviations - Emit the abbreviation section. +/// +void DwarfDebug::emitAbbreviations() const { + // Check to see if it is worth the effort. + if (!Abbreviations.empty()) { + // Start the debug abbrev section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAbbrevSection()); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_begin")); + + // For each abbrevation. + for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) { + // Get abbreviation data + const DIEAbbrev *Abbrev = Abbreviations[i]; + + // Emit the abbrevations code (base 1 index.) + Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); + + // Emit the abbreviations data. + Abbrev->Emit(Asm); + } + + // Mark end of abbreviations. + Asm->EmitULEB128(0, "EOM(3)"); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("abbrev_end")); + } +} + +/// emitEndOfLineMatrix - Emit the last address of the section and the end of +/// the line matrix. +/// +void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { + // Define last address of section. + Asm->OutStreamer.AddComment("Extended Op"); + Asm->EmitInt8(0); + + Asm->OutStreamer.AddComment("Op size"); + Asm->EmitInt8(Asm->getTargetData().getPointerSize() + 1); + Asm->OutStreamer.AddComment("DW_LNE_set_address"); + Asm->EmitInt8(dwarf::DW_LNE_set_address); + + Asm->OutStreamer.AddComment("Section end label"); + + Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); + + // Mark end of matrix. + Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); + Asm->EmitInt8(0); + Asm->EmitInt8(1); + Asm->EmitInt8(1); +} + +/// emitCommonDebugFrame - Emit common frame info into a debug frame section. +/// +void DwarfDebug::emitCommonDebugFrame() { + if (!Asm->MAI->doesDwarfRequireFrameSection()) + return; + + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameLowering()->getStackGrowthDirection() == + TargetFrameLowering::StackGrowsDown) + stackGrowth *= -1; + + // Start the dwarf frame section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common")); + Asm->OutStreamer.AddComment("Length of Common Information Entry"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_frame_common_end"), + Asm->GetTempSymbol("debug_frame_common_begin"), 4); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_begin")); + Asm->OutStreamer.AddComment("CIE Identifier Tag"); + Asm->EmitInt32((int)dwarf::DW_CIE_ID); + Asm->OutStreamer.AddComment("CIE Version"); + Asm->EmitInt8(dwarf::DW_CIE_VERSION); + Asm->OutStreamer.AddComment("CIE Augmentation"); + Asm->OutStreamer.EmitIntValue(0, 1, /*addrspace*/0); // nul terminator. + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->OutStreamer.AddComment("CIE RA Column"); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), false)); + + std::vector Moves; + TFI->getInitialFrameState(Moves); + + Asm->EmitFrameMoves(Moves, 0, false); + + Asm->EmitAlignment(2); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_frame_common_end")); +} + +/// emitFunctionDebugFrame - Emit per function frame info into a debug frame +/// section. +void DwarfDebug:: +emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) { + if (!Asm->MAI->doesDwarfRequireFrameSection()) + return; + + // Start the dwarf frame section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfFrameSection()); + + Asm->OutStreamer.AddComment("Length of Frame Information Entry"); + MCSymbol *DebugFrameBegin = + Asm->GetTempSymbol("debug_frame_begin", DebugFrameInfo.Number); + MCSymbol *DebugFrameEnd = + Asm->GetTempSymbol("debug_frame_end", DebugFrameInfo.Number); + Asm->EmitLabelDifference(DebugFrameEnd, DebugFrameBegin, 4); + + Asm->OutStreamer.EmitLabel(DebugFrameBegin); + + Asm->OutStreamer.AddComment("FDE CIE offset"); + Asm->EmitSectionOffset(Asm->GetTempSymbol("debug_frame_common"), + DwarfFrameSectionSym); + + Asm->OutStreamer.AddComment("FDE initial location"); + MCSymbol *FuncBeginSym = + Asm->GetTempSymbol("func_begin", DebugFrameInfo.Number); + Asm->OutStreamer.EmitSymbolValue(FuncBeginSym, + Asm->getTargetData().getPointerSize(), + 0/*AddrSpace*/); + + + Asm->OutStreamer.AddComment("FDE address range"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("func_end",DebugFrameInfo.Number), + FuncBeginSym, Asm->getTargetData().getPointerSize()); + + Asm->EmitFrameMoves(DebugFrameInfo.Moves, FuncBeginSym, false); + + Asm->EmitAlignment(2); + Asm->OutStreamer.EmitLabel(DebugFrameEnd); +} + +/// emitDebugPubNames - Emit visible names into a debug pubnames section. +/// +void DwarfDebug::emitDebugPubNames() { + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + // Start the dwarf pubnames section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfPubNamesSection()); + + Asm->OutStreamer.AddComment("Length of Public Names Info"); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubnames_end", TheCU->getID()), + Asm->GetTempSymbol("pubnames_begin", TheCU->getID()), 4); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", + TheCU->getID())); + + Asm->OutStreamer.AddComment("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + + Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", TheCU->getID()), + DwarfInfoSectionSym); + + Asm->OutStreamer.AddComment("Compilation Unit Length"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", TheCU->getID()), + Asm->GetTempSymbol("info_begin", TheCU->getID()), + 4); + + const StringMap &Globals = TheCU->getGlobals(); + for (StringMap::const_iterator + GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE *Entity = GI->second; + + Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(Entity->getOffset()); + + if (Asm->isVerbose()) + Asm->OutStreamer.AddComment("External Name"); + Asm->OutStreamer.EmitBytes(StringRef(Name, strlen(Name)+1), 0); + } + + Asm->OutStreamer.AddComment("End Mark"); + Asm->EmitInt32(0); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", + TheCU->getID())); + } +} + +void DwarfDebug::emitDebugPubTypes() { + for (DenseMap::iterator I = CUMap.begin(), + E = CUMap.end(); I != E; ++I) { + CompileUnit *TheCU = I->second; + // Start the dwarf pubnames section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfPubTypesSection()); + Asm->OutStreamer.AddComment("Length of Public Types Info"); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("pubtypes_end", TheCU->getID()), + Asm->GetTempSymbol("pubtypes_begin", TheCU->getID()), 4); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin", + TheCU->getID())); + + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + + Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); + Asm->EmitSectionOffset(Asm->GetTempSymbol("info_begin", TheCU->getID()), + DwarfInfoSectionSym); + + Asm->OutStreamer.AddComment("Compilation Unit Length"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("info_end", TheCU->getID()), + Asm->GetTempSymbol("info_begin", TheCU->getID()), + 4); + + const StringMap &Globals = TheCU->getGlobalTypes(); + for (StringMap::const_iterator + GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { + const char *Name = GI->getKeyData(); + DIE * Entity = GI->second; + + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(Entity->getOffset()); + + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name"); + Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1), 0); + } + + Asm->OutStreamer.AddComment("End Mark"); + Asm->EmitInt32(0); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end", + TheCU->getID())); + } +} + +/// emitDebugStr - Emit visible names into a debug str section. +/// +void DwarfDebug::emitDebugStr() { + // Check to see if it is worth the effort. + if (StringPool.empty()) return; + + // Start the dwarf str section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfStrSection()); + + // Get all of the string pool entries and put them in an array by their ID so + // we can sort them. + SmallVector >*>, 64> Entries; + + for (StringMap >::iterator + I = StringPool.begin(), E = StringPool.end(); I != E; ++I) + Entries.push_back(std::make_pair(I->second.second, &*I)); + + array_pod_sort(Entries.begin(), Entries.end()); + + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + // Emit a label for reference from debug information entries. + Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first); + + // Emit the string itself. + Asm->OutStreamer.EmitBytes(Entries[i].second->getKey(), 0/*addrspace*/); + } +} + +/// emitDebugLoc - Emit visible names into a debug loc section. +/// +void DwarfDebug::emitDebugLoc() { + if (DotDebugLocEntries.empty()) + return; + + for (SmallVector::iterator + I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); + I != E; ++I) { + DotDebugLocEntry &Entry = *I; + if (I + 1 != DotDebugLocEntries.end()) + Entry.Merge(I+1); + } + + // Start the dwarf loc section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + unsigned char Size = Asm->getTargetData().getPointerSize(); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); + unsigned index = 1; + for (SmallVector::iterator + I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); + I != E; ++I, ++index) { + DotDebugLocEntry &Entry = *I; + if (Entry.isMerged()) continue; + if (Entry.isEmpty()) { + Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0); + Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index)); + } else { + Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size, 0); + Asm->OutStreamer.EmitSymbolValue(Entry.End, Size, 0); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Entry.Loc.getReg(), false); + if (int Offset = Entry.Loc.getOffset()) { + // If the value is at a certain offset from frame register then + // use DW_OP_fbreg. + unsigned OffsetSize = Offset ? MCAsmInfo::getSLEB128Size(Offset) : 1; + Asm->OutStreamer.AddComment("Loc expr size"); + Asm->EmitInt16(1 + OffsetSize); + Asm->OutStreamer.AddComment( + dwarf::OperationEncodingString(dwarf::DW_OP_fbreg)); + Asm->EmitInt8(dwarf::DW_OP_fbreg); + Asm->OutStreamer.AddComment("Offset"); + Asm->EmitSLEB128(Offset); + } else { + if (Reg < 32) { + Asm->OutStreamer.AddComment("Loc expr size"); + Asm->EmitInt16(1); + Asm->OutStreamer.AddComment( + dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); + Asm->EmitInt8(dwarf::DW_OP_reg0 + Reg); + } else { + Asm->OutStreamer.AddComment("Loc expr size"); + Asm->EmitInt16(1 + MCAsmInfo::getULEB128Size(Reg)); + Asm->EmitInt8(dwarf::DW_OP_regx); + Asm->EmitULEB128(Reg); + } + } + } + } +} + +/// EmitDebugARanges - Emit visible names into a debug aranges section. +/// +void DwarfDebug::EmitDebugARanges() { + // Start the dwarf aranges section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); +} + +/// emitDebugRanges - Emit visible names into a debug ranges section. +/// +void DwarfDebug::emitDebugRanges() { + // Start the dwarf ranges section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfRangesSection()); + unsigned char Size = Asm->getTargetData().getPointerSize(); + for (SmallVector::iterator + I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); + I != E; ++I) { + if (*I) + Asm->OutStreamer.EmitSymbolValue(const_cast(*I), Size, 0); + else + Asm->OutStreamer.EmitIntValue(0, Size, /*addrspace*/0); + } +} + +/// emitDebugMacInfo - Emit visible names into a debug macinfo section. +/// +void DwarfDebug::emitDebugMacInfo() { + if (const MCSection *LineInfo = + Asm->getObjFileLowering().getDwarfMacroInfoSection()) { + // Start the dwarf macinfo section. + Asm->OutStreamer.SwitchSection(LineInfo); + } +} + +/// emitDebugInlineInfo - Emit inline info using following format. +/// Section Header: +/// 1. length of section +/// 2. Dwarf version number +/// 3. address size. +/// +/// Entries (one "entry" for each function that was inlined): +/// +/// 1. offset into __debug_str section for MIPS linkage name, if exists; +/// otherwise offset into __debug_str for regular function name. +/// 2. offset into __debug_str section for regular function name. +/// 3. an unsigned LEB128 number indicating the number of distinct inlining +/// instances for the function. +/// +/// The rest of the entry consists of a {die_offset, low_pc} pair for each +/// inlined instance; the die_offset points to the inlined_subroutine die in the +/// __debug_info section, and the low_pc is the starting address for the +/// inlining instance. +void DwarfDebug::emitDebugInlineInfo() { + if (!Asm->MAI->doesDwarfUsesInlineInfoSection()) + return; + + if (!FirstCU) + return; + + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfDebugInlineSection()); + + Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_inlined_end", 1), + Asm->GetTempSymbol("debug_inlined_begin", 1), 4); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1)); + + Asm->OutStreamer.AddComment("Dwarf Version"); + Asm->EmitInt16(dwarf::DWARF_VERSION); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(Asm->getTargetData().getPointerSize()); + + for (SmallVector::iterator I = InlinedSPNodes.begin(), + E = InlinedSPNodes.end(); I != E; ++I) { + + const MDNode *Node = *I; + DenseMap >::iterator II + = InlineInfo.find(Node); + SmallVector &Labels = II->second; + DISubprogram SP(Node); + StringRef LName = SP.getLinkageName(); + StringRef Name = SP.getName(); + + Asm->OutStreamer.AddComment("MIPS linkage name"); + if (LName.empty()) { + Asm->OutStreamer.EmitBytes(Name, 0); + Asm->OutStreamer.EmitIntValue(0, 1, 0); // nul terminator. + } else + Asm->EmitSectionOffset(getStringPoolEntry(getRealLinkageName(LName)), + DwarfStrSectionSym); + + Asm->OutStreamer.AddComment("Function name"); + Asm->EmitSectionOffset(getStringPoolEntry(Name), DwarfStrSectionSym); + Asm->EmitULEB128(Labels.size(), "Inline count"); + + for (SmallVector::iterator LI = Labels.begin(), + LE = Labels.end(); LI != LE; ++LI) { + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset"); + Asm->EmitInt32(LI->second->getOffset()); + + if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc"); + Asm->OutStreamer.EmitSymbolValue(LI->first, + Asm->getTargetData().getPointerSize(),0); + } + } + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1)); +} diff --git a/final/lib/CodeGen/AsmPrinter/DwarfDebug.h b/final/lib/CodeGen/AsmPrinter/DwarfDebug.h new file mode 100644 index 00000000000..2863ea38060 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -0,0 +1,602 @@ +//===-- llvm/CodeGen/DwarfDebug.h - Dwarf Debug Framework ------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf debug info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ + +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "DIE.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/UniqueVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class CompileUnit; +class DbgConcreteScope; +class DbgScope; +class DbgVariable; +class MachineFrameInfo; +class MachineModuleInfo; +class MachineOperand; +class MCAsmInfo; +class DIEAbbrev; +class DIE; +class DIEBlock; +class DIEEntry; + +class DIEnumerator; +class DIDescriptor; +class DIVariable; +class DIGlobal; +class DIGlobalVariable; +class DISubprogram; +class DIBasicType; +class DIDerivedType; +class DIType; +class DINameSpace; +class DISubrange; +class DICompositeType; +class DITemplateTypeParameter; +class DITemplateValueParameter; + +//===----------------------------------------------------------------------===// +/// SrcLineInfo - This class is used to record source line correspondence. +/// +class SrcLineInfo { + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + MCSymbol *Label; // Label in code ID number. +public: + SrcLineInfo(unsigned L, unsigned C, unsigned S, MCSymbol *label) + : Line(L), Column(C), SourceID(S), Label(label) {} + + // Accessors + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + unsigned getSourceID() const { return SourceID; } + MCSymbol *getLabel() const { return Label; } +}; + +/// DotDebugLocEntry - This struct describes location entries emitted in +/// .debug_loc section. +typedef struct DotDebugLocEntry { + const MCSymbol *Begin; + const MCSymbol *End; + MachineLocation Loc; + bool Merged; + DotDebugLocEntry() : Begin(0), End(0), Merged(false) {} + DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L) + : Begin(B), End(E), Loc(L), Merged(false) {} + /// Empty entries are also used as a trigger to emit temp label. Such + /// labels are referenced is used to find debug_loc offset for a given DIE. + bool isEmpty() { return Begin == 0 && End == 0; } + bool isMerged() { return Merged; } + void Merge(DotDebugLocEntry *Next) { + if (!(Begin && Loc == Next->Loc && End == Next->Begin)) + return; + Next->Begin = Begin; + Merged = true; + } +} DotDebugLocEntry; + +class DwarfDebug { + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + + //===--------------------------------------------------------------------===// + // Attributes used to construct specific Dwarf sections. + // + + CompileUnit *FirstCU; + DenseMap CUMap; + + /// AbbreviationsSet - Used to uniquely define abbreviations. + /// + FoldingSet AbbreviationsSet; + + /// Abbreviations - A list of all the unique abbreviations in use. + /// + std::vector Abbreviations; + + /// SourceIdMap - Source id map, i.e. pair of directory id and source file + /// id mapped to a unique id. + StringMap SourceIdMap; + + /// DIEBlocks - A list of all the DIEBlocks in use. + std::vector DIEBlocks; + + // DIEValueAllocator - All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + + /// StringPool - A String->Symbol mapping of strings used by indirect + /// references. + StringMap > StringPool; + unsigned NextStringPoolNumber; + + MCSymbol *getStringPoolEntry(StringRef Str); + + /// SectionMap - Provides a unique id per text section. + /// + UniqueVector SectionMap; + + /// CurrentFnDbgScope - Top level scope for the current function. + /// + DbgScope *CurrentFnDbgScope; + + /// CurrentFnArguments - List of Arguments (DbgValues) for current function. + SmallVector CurrentFnArguments; + + /// DbgScopeMap - Tracks the scopes in the current function. Owns the + /// contained DbgScope*s. + /// + DenseMap DbgScopeMap; + + /// ConcreteScopes - Tracks the concrete scopees in the current function. + /// These scopes are also included in DbgScopeMap. + DenseMap ConcreteScopes; + + /// AbstractScopes - Tracks the abstract scopes a module. These scopes are + /// not included DbgScopeMap. AbstractScopes owns its DbgScope*s. + DenseMap AbstractScopes; + + /// AbstractSPDies - Collection of abstract subprogram DIEs. + DenseMap AbstractSPDies; + + /// AbstractScopesList - Tracks abstract scopes constructed while processing + /// a function. This list is cleared during endFunction(). + SmallVectorAbstractScopesList; + + /// AbstractVariables - Collection on abstract variables. Owned by the + /// DbgScopes in AbstractScopes. + DenseMap AbstractVariables; + + /// DbgVariableToFrameIndexMap - Tracks frame index used to find + /// variable's value. + DenseMap DbgVariableToFrameIndexMap; + + /// DbgVariableToDbgInstMap - Maps DbgVariable to corresponding DBG_VALUE + /// machine instruction. + DenseMap DbgVariableToDbgInstMap; + + /// DotDebugLocEntries - Collection of DotDebugLocEntry. + SmallVector DotDebugLocEntries; + + /// UseDotDebugLocEntry - DW_AT_location attributes for the DIEs in this set + /// idetifies corresponding .debug_loc entry offset. + SmallPtrSet UseDotDebugLocEntry; + + /// VarToAbstractVarMap - Maps DbgVariable with corresponding Abstract + /// DbgVariable, if any. + DenseMap VarToAbstractVarMap; + + /// InliendSubprogramDIEs - Collection of subprgram DIEs that are marked + /// (at the end of the module) as DW_AT_inline. + SmallPtrSet InlinedSubprogramDIEs; + + /// ContainingTypeMap - This map is used to keep track of subprogram DIEs that + /// need DW_AT_containing_type attribute. This attribute points to a DIE that + /// corresponds to the MDNode mapped with the subprogram DIE. + DenseMap ContainingTypeMap; + + typedef SmallVector ScopeVector; + + SmallPtrSet InsnsEndScopeSet; + + /// InlineInfo - Keep track of inlined functions and their location. This + /// information is used to populate debug_inlined section. + typedef std::pair InlineInfoLabels; + DenseMap > InlineInfo; + SmallVector InlinedSPNodes; + + // ProcessedSPNodes - This is a collection of subprogram MDNodes that + // are processed to create DIEs. + SmallPtrSet ProcessedSPNodes; + + /// LabelsBeforeInsn - Maps instruction with label emitted before + /// instruction. + DenseMap LabelsBeforeInsn; + + /// LabelsAfterInsn - Maps instruction with label emitted after + /// instruction. + DenseMap LabelsAfterInsn; + + /// insnNeedsLabel - Collection of instructions that need a label to mark + /// a debuggging information entity. + SmallPtrSet InsnNeedsLabel; + + SmallVector DebugRangeSymbols; + + /// Previous instruction's location information. This is used to determine + /// label location to indicate scope boundries in dwarf debug info. + DebugLoc PrevInstLoc; + MCSymbol *PrevLabel; + + struct FunctionDebugFrameInfo { + unsigned Number; + std::vector Moves; + + FunctionDebugFrameInfo(unsigned Num, const std::vector &M) + : Number(Num), Moves(M) {} + }; + + std::vector DebugFrames; + + // Section Symbols: these are assembler temporary labels that are emitted at + // the beginning of each supported dwarf section. These are used to form + // section offsets and are created by EmitSectionLabels. + MCSymbol *DwarfFrameSectionSym, *DwarfInfoSectionSym, *DwarfAbbrevSectionSym; + MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym; + MCSymbol *DwarfDebugLocSectionSym; + MCSymbol *FunctionBeginSym, *FunctionEndSym; + + DIEInteger *DIEIntegerOne; +private: + + /// getNumSourceIds - Return the number of unique source ids. + unsigned getNumSourceIds() const { + return SourceIdMap.size(); + } + + /// assignAbbrevNumber - Define a unique number for the abbreviation. + /// + void assignAbbrevNumber(DIEAbbrev &Abbrev); + + /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug + /// information entry. + DIEEntry *createDIEEntry(DIE *Entry); + + /// addUInt - Add an unsigned integer attribute data and value. + /// + void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); + + /// addSInt - Add an signed integer attribute data and value. + /// + void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); + + /// addString - Add a string attribute data and value. + /// + void addString(DIE *Die, unsigned Attribute, unsigned Form, + const StringRef Str); + + /// addLabel - Add a Dwarf label attribute data and value. + /// + void addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label); + + /// addDelta - Add a label delta attribute data and value. + /// + void addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo); + + /// addDIEEntry - Add a DIE attribute data and value. + /// + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); + + /// addBlock - Add block data. + /// + void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); + + /// addSourceLine - Add location information to specified debug information + /// entry. + void addSourceLine(DIE *Die, DIVariable V); + void addSourceLine(DIE *Die, DIGlobalVariable G); + void addSourceLine(DIE *Die, DISubprogram SP); + void addSourceLine(DIE *Die, DIType Ty); + void addSourceLine(DIE *Die, DINameSpace NS); + + /// addAddress - Add an address attribute to a die based on the location + /// provided. + void addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addRegisterAddress - Add register location entry in variable DIE. + bool addRegisterAddress(DIE *Die, const MachineOperand &MO); + + /// addConstantValue - Add constant value entry in variable DIE. + bool addConstantValue(DIE *Die, const MachineOperand &MO); + bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); + + /// addConstantFPValue - Add constant value entry in variable DIE. + bool addConstantFPValue(DIE *Die, const MachineOperand &MO); + + /// addComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of addComplexAddress. + /// addBlockByrefAddress - Start with the address based on the location + /// provided, and generate the DWARF information necessary to find the + /// actual Block variable (navigating the Block struct) based on the + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use addComplexAddress instead. + /// + void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based + /// on provided frame index. + void addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI); + + /// addToContextOwner - Add Die into the list of its context owner's children. + void addToContextOwner(DIE *Die, DIDescriptor Context); + + /// addType - Add a new type attribute to the specified entity. + void addType(DIE *Entity, DIType Ty); + + + /// getOrCreateNameSpace - Create a DIE for DINameSpace. + DIE *getOrCreateNameSpace(DINameSpace NS); + + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the + /// given DIType. + DIE *getOrCreateTypeDIE(DIType Ty); + + /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateTypeParameter. + DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); + + /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateValueParameter. + DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); + + void addPubTypes(DISubprogram SP); + + /// constructTypeDIE - Construct basic type die from DIBasicType. + void constructTypeDIE(DIE &Buffer, + DIBasicType BTy); + + /// constructTypeDIE - Construct derived type die from DIDerivedType. + void constructTypeDIE(DIE &Buffer, + DIDerivedType DTy); + + /// constructTypeDIE - Construct type DIE from DICompositeType. + void constructTypeDIE(DIE &Buffer, + DICompositeType CTy); + + /// constructSubrangeDIE - Construct subrange DIE from DISubrange. + void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); + + /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. + void constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy); + + /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *constructEnumTypeDIE(DIEnumerator ETy); + + /// createMemberDIE - Create new member DIE. + DIE *createMemberDIE(DIDerivedType DT); + + /// createSubprogramDIE - Create new DIE using SP. + DIE *createSubprogramDIE(DISubprogram SP); + + /// getOrCreateDbgScope - Create DbgScope for the scope. + DbgScope *getOrCreateDbgScope(const MDNode *Scope, const MDNode *InlinedAt); + + DbgScope *getOrCreateAbstractScope(const MDNode *N); + + /// findAbstractVariable - Find abstract variable associated with Var. + DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc); + + /// updateSubprogramScopeDIE - Find DIE for the given subprogram and + /// attach appropriate DW_AT_low_pc and DW_AT_high_pc attributes. + /// If there are global variables in this scope then create and insert + /// DIEs for these variables. + DIE *updateSubprogramScopeDIE(const MDNode *SPNode); + + /// constructLexicalScope - Construct new DW_TAG_lexical_block + /// for this scope and attach DW_AT_low_pc/DW_AT_high_pc labels. + DIE *constructLexicalScopeDIE(DbgScope *Scope); + + /// constructInlinedScopeDIE - This scope represents inlined body of + /// a function. Construct DIE to represent this concrete inlined copy + /// of the function. + DIE *constructInlinedScopeDIE(DbgScope *Scope); + + /// constructVariableDIE - Construct a DIE for the given DbgVariable. + DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S); + + /// constructScopeDIE - Construct a DIE for this scope. + DIE *constructScopeDIE(DbgScope *Scope); + + /// EmitSectionLabels - Emit initial Dwarf sections with a label at + /// the start of each one. + void EmitSectionLabels(); + + /// emitDIE - Recusively Emits a debug information entry. + /// + void emitDIE(DIE *Die); + + /// computeSizeAndOffset - Compute the size and offset of a DIE. + /// + unsigned computeSizeAndOffset(DIE *Die, unsigned Offset, bool Last); + + /// computeSizeAndOffsets - Compute the size and offset of all the DIEs. + /// + void computeSizeAndOffsets(); + + /// EmitDebugInfo - Emit the debug info section. + /// + void emitDebugInfo(); + + /// emitAbbreviations - Emit the abbreviation section. + /// + void emitAbbreviations() const; + + /// emitEndOfLineMatrix - Emit the last address of the section and the end of + /// the line matrix. + /// + void emitEndOfLineMatrix(unsigned SectionEnd); + + /// emitCommonDebugFrame - Emit common frame info into a debug frame section. + /// + void emitCommonDebugFrame(); + + /// emitFunctionDebugFrame - Emit per function frame info into a debug frame + /// section. + void emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo); + + /// emitDebugPubNames - Emit visible names into a debug pubnames section. + /// + void emitDebugPubNames(); + + /// emitDebugPubTypes - Emit visible types into a debug pubtypes section. + /// + void emitDebugPubTypes(); + + /// emitDebugStr - Emit visible names into a debug str section. + /// + void emitDebugStr(); + + /// emitDebugLoc - Emit visible names into a debug loc section. + /// + void emitDebugLoc(); + + /// EmitDebugARanges - Emit visible names into a debug aranges section. + /// + void EmitDebugARanges(); + + /// emitDebugRanges - Emit visible names into a debug ranges section. + /// + void emitDebugRanges(); + + /// emitDebugMacInfo - Emit visible names into a debug macinfo section. + /// + void emitDebugMacInfo(); + + /// emitDebugInlineInfo - Emit inline info using following format. + /// Section Header: + /// 1. length of section + /// 2. Dwarf version number + /// 3. address size. + /// + /// Entries (one "entry" for each function that was inlined): + /// + /// 1. offset into __debug_str section for MIPS linkage name, if exists; + /// otherwise offset into __debug_str for regular function name. + /// 2. offset into __debug_str section for regular function name. + /// 3. an unsigned LEB128 number indicating the number of distinct inlining + /// instances for the function. + /// + /// The rest of the entry consists of a {die_offset, low_pc} pair for each + /// inlined instance; the die_offset points to the inlined_subroutine die in + /// the __debug_info section, and the low_pc is the starting address for the + /// inlining instance. + void emitDebugInlineInfo(); + + /// GetOrCreateSourceID - Look up the source id with the given directory and + /// source file names. If none currently exists, create a new id and insert it + /// in the SourceIds map. + unsigned GetOrCreateSourceID(StringRef FullName); + + /// constructCompileUnit - Create new CompileUnit for the given + /// metadata node with tag DW_TAG_compile_unit. + void constructCompileUnit(const MDNode *N); + + /// getCompielUnit - Get CompileUnit DIE. + CompileUnit *getCompileUnit(const MDNode *N) const; + + /// constructGlobalVariableDIE - Construct global variable DIE. + void constructGlobalVariableDIE(const MDNode *N); + + /// construct SubprogramDIE - Construct subprogram DIE. + void constructSubprogramDIE(const MDNode *N); + + /// recordSourceLine - Register a source line with debug info. Returns the + /// unique label that was emitted and which provides correspondence to + /// the source line list. + MCSymbol *recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope); + + /// recordVariableFrameIndex - Record a variable's index. + void recordVariableFrameIndex(const DbgVariable *V, int Index); + + /// findVariableFrameIndex - Return true if frame index for the variable + /// is found. Update FI to hold value of the index. + bool findVariableFrameIndex(const DbgVariable *V, int *FI); + + /// findDbgScope - Find DbgScope for the debug loc attached with an + /// instruction. + DbgScope *findDbgScope(const MachineInstr *MI); + + /// identifyScopeMarkers() - Indentify instructions that are marking + /// beginning of or end of a scope. + void identifyScopeMarkers(); + + /// extractScopeInformation - Scan machine instructions in this function + /// and collect DbgScopes. Return true, if atleast one scope was found. + bool extractScopeInformation(); + + /// addCurrentFnArgument - If Var is an current function argument that add + /// it in CurrentFnArguments list. + bool addCurrentFnArgument(const MachineFunction *MF, + DbgVariable *Var, DbgScope *Scope); + + /// collectVariableInfo - Populate DbgScope entries with variables' info. + void collectVariableInfo(const MachineFunction *, + SmallPtrSet &ProcessedVars); + + /// collectVariableInfoFromMMITable - Collect variable information from + /// side table maintained by MMI. + void collectVariableInfoFromMMITable(const MachineFunction * MF, + SmallPtrSet &P); +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfDebug(AsmPrinter *A, Module *M); + ~DwarfDebug(); + + /// beginModule - Emit all Dwarf sections that should come prior to the + /// content. + void beginModule(Module *M); + + /// endModule - Emit all Dwarf sections that should come after the content. + /// + void endModule(); + + /// beginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void beginFunction(const MachineFunction *MF); + + /// endFunction - Gather and emit post-function debug information. + /// + void endFunction(const MachineFunction *MF); + + /// getLabelBeforeInsn - Return Label preceding the instruction. + const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); + + /// getLabelAfterInsn - Return Label immediately following the instruction. + const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + + /// beginInstruction - Process beginning of an instruction. + void beginInstruction(const MachineInstr *MI); + + /// endInstruction - Prcess end of an instruction. + void endInstruction(const MachineInstr *MI); +}; +} // End of namespace llvm + +#endif diff --git a/final/lib/CodeGen/AsmPrinter/DwarfException.cpp b/final/lib/CodeGen/AsmPrinter/DwarfException.cpp new file mode 100644 index 00000000000..967a2783da1 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -0,0 +1,676 @@ +//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +DwarfException::DwarfException(AsmPrinter *A) + : Asm(A), MMI(Asm->MMI) {} + +DwarfException::~DwarfException() {} + +/// SharedTypeIds - How many leading type ids two landing pads have in common. +unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + unsigned Count = 0; + + for (; Count != MinSize; ++Count) + if (LIds[Count] != RIds[Count]) + return Count; + + return Count; +} + +/// PadLT - Order landing pads lexicographically by type id. +bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + + for (unsigned i = 0; i != MinSize; ++i) + if (LIds[i] != RIds[i]) + return LIds[i] < RIds[i]; + + return LSize < RSize; +} + +/// ComputeActionsTable - Compute the actions table and gather the first action +/// index for each landing pad site. +unsigned DwarfException:: +ComputeActionsTable(const SmallVectorImpl &LandingPads, + SmallVectorImpl &Actions, + SmallVectorImpl &FirstActions) { + + // The action table follows the call-site table in the LSDA. The individual + // records are of two types: + // + // * Catch clause + // * Exception specification + // + // The two record kinds have the same format, with only small differences. + // They are distinguished by the "switch value" field: Catch clauses + // (TypeInfos) have strictly positive switch values, and exception + // specifications (FilterIds) have strictly negative switch values. Value 0 + // indicates a catch-all clause. + // + // Negative type IDs index into FilterIds. Positive type IDs index into + // TypeInfos. The value written for a positive type ID is just the type ID + // itself. For a negative type ID, however, the value written is the + // (negative) byte offset of the corresponding FilterIds entry. The byte + // offset is usually equal to the type ID (because the FilterIds entries are + // written using a variable width encoding, which outputs one byte per entry + // as long as the value written is not too large) but can differ. This kind + // of complication does not occur for positive type IDs because type infos are + // output using a fixed width encoding. FilterOffsets[i] holds the byte + // offset corresponding to FilterIds[i]. + + const std::vector &FilterIds = MMI->getFilterIds(); + SmallVector FilterOffsets; + FilterOffsets.reserve(FilterIds.size()); + int Offset = -1; + + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { + FilterOffsets.push_back(Offset); + Offset -= MCAsmInfo::getULEB128Size(*I); + } + + FirstActions.reserve(LandingPads.size()); + + int FirstAction = 0; + unsigned SizeActions = 0; + const LandingPadInfo *PrevLPI = 0; + + for (SmallVectorImpl::const_iterator + I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { + const LandingPadInfo *LPI = *I; + const std::vector &TypeIds = LPI->TypeIds; + unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; + unsigned SizeSiteActions = 0; + + if (NumShared < TypeIds.size()) { + unsigned SizeAction = 0; + unsigned PrevAction = (unsigned)-1; + + if (NumShared) { + unsigned SizePrevIds = PrevLPI->TypeIds.size(); + assert(Actions.size()); + PrevAction = Actions.size() - 1; + SizeAction = + MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); + SizeAction -= + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction += -Actions[PrevAction].NextAction; + PrevAction = Actions[PrevAction].Previous; + } + } + + // Compute the actions. + for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { + int TypeID = TypeIds[J]; + assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; + Actions.push_back(Action); + PrevAction = Actions.size() - 1; + } + + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + // Information used when created the call-site table. The action record + // field of the call site record is the offset of the first associated + // action record, relative to the start of the actions table. This value is + // biased by 1 (1 indicating the start of the actions table), and 0 + // indicates that there are no actions. + FirstActions.push_back(FirstAction); + + // Compute this sites contribution to size. + SizeActions += SizeSiteActions; + + PrevLPI = LPI; + } + + return SizeActions; +} + +/// CallToNoUnwindFunction - Return `true' if this is a call to a function +/// marked `nounwind'. Return `false' otherwise. +bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) { + assert(MI->getDesc().isCall() && "This should be a call instruction!"); + + bool MarkedNoUnwind = false; + bool SawFunc = false; + + for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { + const MachineOperand &MO = MI->getOperand(I); + + if (!MO.isGlobal()) continue; + + const Function *F = dyn_cast(MO.getGlobal()); + if (F == 0) continue; + + if (SawFunc) { + // Be conservative. If we have more than one function operand for this + // call, then we can't make the assumption that it's the callee and + // not a parameter to the call. + // + // FIXME: Determine if there's a way to say that `F' is the callee or + // parameter. + MarkedNoUnwind = false; + break; + } + + MarkedNoUnwind = F->doesNotThrow(); + SawFunc = true; + } + + return MarkedNoUnwind; +} + +/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke +/// has a try-range containing the call, a non-zero landing pad, and an +/// appropriate action. The entry for an ordinary call has a try-range +/// containing the call and zero for the landing pad and the action. Calls +/// marked 'nounwind' have no entry and must not be contained in the try-range +/// of any entry - they form gaps in the table. Entries must be ordered by +/// try-range address. +void DwarfException:: +ComputeCallSiteTable(SmallVectorImpl &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl &LandingPads, + const SmallVectorImpl &FirstActions) { + // The end label of the previous invoke or nounwind try-range. + MCSymbol *LastLabel = 0; + + // Whether there is a potentially throwing instruction (currently this means + // an ordinary call) between the end of the previous try-range and now. + bool SawPotentiallyThrowing = false; + + // Whether the last CallSite entry was for an invoke. + bool PreviousIsInvoke = false; + + // Visit all instructions in order of address. + for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); + MI != E; ++MI) { + if (!MI->isLabel()) { + if (MI->getDesc().isCall()) + SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); + continue; + } + + // End of the previous try-range? + MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); + if (BeginLabel == LastLabel) + SawPotentiallyThrowing = false; + + // Beginning of a new try-range? + RangeMapType::const_iterator L = PadMap.find(BeginLabel); + if (L == PadMap.end()) + // Nope, it was just some random label. + continue; + + const PadRange &P = L->second; + const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; + assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && + "Inconsistent landing pad map!"); + + // For Dwarf exception handling (SjLj handling doesn't use this). If some + // instruction between the previous try-range and this one may throw, + // create a call-site entry with no landing pad for the region between the + // try-ranges. + if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { + CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; + CallSites.push_back(Site); + PreviousIsInvoke = false; + } + + LastLabel = LandingPad->EndLabels[P.RangeIndex]; + assert(BeginLabel && LastLabel && "Invalid landing pad!"); + + if (!LandingPad->LandingPadLabel) { + // Create a gap. + PreviousIsInvoke = false; + } else { + // This try-range is for an invoke. + CallSiteEntry Site = { + BeginLabel, + LastLabel, + LandingPad->LandingPadLabel, + FirstActions[P.PadIndex] + }; + + // Try to merge with the previous call-site. SJLJ doesn't do this + if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) { + CallSiteEntry &Prev = CallSites.back(); + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } + } + + // Otherwise, create a new call-site. + if (Asm->MAI->isExceptionHandlingDwarf()) + CallSites.push_back(Site); + else { + // SjLj EH must maintain the call sites in the order assigned + // to them by the SjLjPrepare pass. + unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); + if (CallSites.size() < SiteNo) + CallSites.resize(SiteNo); + CallSites[SiteNo - 1] = Site; + } + PreviousIsInvoke = true; + } + } + } + + // If some instruction between the previous try-range and the end of the + // function may throw, create a call-site entry with no landing pad for the + // region following the try-range. + if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { + CallSiteEntry Site = { LastLabel, 0, 0, 0 }; + CallSites.push_back(Site); + } +} + +/// EmitExceptionTable - Emit landing pads and actions. +/// +/// The general organization of the table is complex, but the basic concepts are +/// easy. First there is a header which describes the location and organization +/// of the three components that follow. +/// +/// 1. The landing pad site information describes the range of code covered by +/// the try. In our case it's an accumulation of the ranges covered by the +/// invokes in the try. There is also a reference to the landing pad that +/// handles the exception once processed. Finally an index into the actions +/// table. +/// 2. The action table, in our case, is composed of pairs of type IDs and next +/// action offset. Starting with the action index from the landing pad +/// site, each type ID is checked for a match to the current exception. If +/// it matches then the exception and type id are passed on to the landing +/// pad. Otherwise the next action is looked up. This chain is terminated +/// with a next action of zero. If no type id is found then the frame is +/// unwound and handling continues. +/// 3. Type ID table contains references to all the C++ typeinfo for all +/// catches in the function. This tables is reverse indexed base 1. +void DwarfException::EmitExceptionTable() { + const std::vector &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector LandingPads; + LandingPads.reserve(PadInfos.size()); + + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector Actions; + SmallVector FirstActions; + unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); + + // Invokes and nounwind calls have entries in PadMap (due to being bracketed + // by try-range labels when lowered). Ordinary calls do not, so appropriate + // try-ranges for them need be deduced when using DWARF exception handling. + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + // Compute the call-site table. + SmallVector CallSites; + ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); + + // Final tallies. + + // Call sites. + bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; + + unsigned CallSiteTableLength; + if (IsSJLJ) + CallSiteTableLength = 0; + else { + unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 + unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 + CallSiteTableLength = + CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); + } + + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { + CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); + if (IsSJLJ) + CallSiteTableLength += MCAsmInfo::getULEB128Size(i); + } + + // Type infos. + const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); + unsigned TTypeEncoding; + unsigned TypeFormatSize; + + if (!HaveTTData) { + // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say + // that we're omitting that bit. + TTypeEncoding = dwarf::DW_EH_PE_omit; + // dwarf::DW_EH_PE_absptr + TypeFormatSize = Asm->getTargetData().getPointerSize(); + } else { + // Okay, we have actual filters or typeinfos to emit. As such, we need to + // pick a type encoding for them. We're about to emit a list of pointers to + // typeinfo objects at the end of the LSDA. However, unless we're in static + // mode, this reference will require a relocation by the dynamic linker. + // + // Because of this, we have a couple of options: + // + // 1) If we are in -static mode, we can always use an absolute reference + // from the LSDA, because the static linker will resolve it. + // + // 2) Otherwise, if the LSDA section is writable, we can output the direct + // reference to the typeinfo and allow the dynamic linker to relocate + // it. Since it is in a writable section, the dynamic linker won't + // have a problem. + // + // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, + // we need to use some form of indirection. For example, on Darwin, + // we can output a statically-relocatable reference to a dyld stub. The + // offset to the stub is constant, but the contents are in a section + // that is updated by the dynamic linker. This is easy enough, but we + // need to tell the personality function of the unwinder to indirect + // through the dyld stub. + // + // FIXME: When (3) is actually implemented, we'll have to emit the stubs + // somewhere. This predicate should be moved to a shared location that is + // in target-independent code. + // + TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); + TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); + } + + // Begin the exception table. + // Sometimes we want not to emit the data into separate section (e.g. ARM + // EHABI). In this case LSDASection will be NULL. + if (LSDASection) + Asm->OutStreamer.SwitchSection(LSDASection); + Asm->EmitAlignment(2); + + // Emit the LSDA. + MCSymbol *GCCETSym = + Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ + Twine(Asm->getFunctionNumber())); + Asm->OutStreamer.EmitLabel(GCCETSym); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception", + Asm->getFunctionNumber())); + + if (IsSJLJ) + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_", + Asm->getFunctionNumber())); + + // Emit the LSDA header. + Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + Asm->EmitEncodingByte(TTypeEncoding, "@TType"); + + // The type infos need to be aligned. GCC does this by inserting padding just + // before the type infos. However, this changes the size of the exception + // table, so you need to take this into account when you output the exception + // table size. However, the size is output using a variable length encoding. + // So by increasing the size by inserting padding, you may increase the number + // of bytes used for writing the size. If it increases, say by one byte, then + // you now need to output one less byte of padding to get the type infos + // aligned. However this decreases the size of the exception table. This + // changes the value you have to output for the exception table size. Due to + // the variable length encoding, the number of bytes used for writing the + // length may decrease. If so, you then have to increase the amount of + // padding. And so on. If you look carefully at the GCC code you will see that + // it indeed does this in a loop, going on and on until the values stabilize. + // We chose another solution: don't output padding inside the table like GCC + // does, instead output it before the table. + unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; + unsigned CallSiteTableLengthSize = + MCAsmInfo::getULEB128Size(CallSiteTableLength); + unsigned TTypeBaseOffset = + sizeof(int8_t) + // Call site format + CallSiteTableLengthSize + // Call site table length size + CallSiteTableLength + // Call site table length + SizeActions + // Actions size + SizeTypes; + unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset); + unsigned TotalSize = + sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size + TTypeBaseOffset; // TType base offset + unsigned SizeAlign = (4 - TotalSize) & 3; + + if (HaveTTData) { + // Account for any extra padding that will be added to the call site table + // length. + Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); + SizeAlign = 0; + } + + // SjLj Exception handling + if (IsSJLJ) { + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + + // Add extra padding if it wasn't added to the TType base offset. + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + + // Emit the landing pad site information. + unsigned idx = 0; + for (SmallVectorImpl::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { + const CallSiteEntry &S = *I; + + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + Asm->EmitULEB128(idx, "Landing pad"); + + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128(S.Action, "Action"); + } + } else { + // DWARF Exception handling + assert(Asm->MAI->isExceptionHandlingDwarf()); + + // The call-site table is a list of all call sites that may throw an + // exception (including C++ 'throw' statements) in the procedure + // fragment. It immediately follows the LSDA header. Each entry indicates, + // for a given call, the first corresponding action record and corresponding + // landing pad. + // + // The table begins with the number of bytes, stored as an LEB128 + // compressed, unsigned integer. The records immediately follow the record + // count. They are sorted in increasing call-site address. Each record + // indicates: + // + // * The position of the call-site. + // * The position of the landing pad. + // * The first action record for that call site. + // + // A missing entry in the call-site table indicates that a call is not + // supposed to throw. + + // Emit the landing pad call site table. + Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); + + // Add extra padding if it wasn't added to the TType base offset. + Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); + + for (SmallVectorImpl::const_iterator + I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { + const CallSiteEntry &S = *I; + + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); + + MCSymbol *BeginLabel = S.BeginLabel; + if (BeginLabel == 0) + BeginLabel = EHFuncBeginSym; + MCSymbol *EndLabel = S.EndLabel; + if (EndLabel == 0) + EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); + + // Offset of the call site relative to the previous call site, counted in + // number of 16-byte bundles. The first call site is counted relative to + // the start of the procedure fragment. + Asm->OutStreamer.AddComment("Region start"); + Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); + + Asm->OutStreamer.AddComment("Region length"); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); + + + // Offset of the landing pad, counted in 16-byte bundles relative to the + // @LPStart address. + Asm->OutStreamer.AddComment("Landing pad"); + if (!S.PadLabel) + Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + else + Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); + + // Offset of the first associated action record, relative to the start of + // the action table. This value is biased by 1 (1 indicates the start of + // the action table), and 0 indicates that there are no actions. + Asm->EmitULEB128(S.Action, "Action"); + } + } + + // Emit the Action Table. + if (Actions.size() != 0) { + Asm->OutStreamer.AddComment("-- Action Record Table --"); + Asm->OutStreamer.AddBlankLine(); + } + + for (SmallVectorImpl::const_iterator + I = Actions.begin(), E = Actions.end(); I != E; ++I) { + const ActionEntry &Action = *I; + Asm->OutStreamer.AddComment("Action Record"); + Asm->OutStreamer.AddBlankLine(); + + // Type Filter + // + // Used by the runtime to match the type of the thrown exception to the + // type of the catch clauses or the types in the exception specification. + Asm->EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); + + // Action Record + // + // Self-relative signed displacement in bytes of the next action record, + // or 0 if there is no next action record. + Asm->EmitSLEB128(Action.NextAction, " Next action"); + } + + // Emit the Catch TypeInfos. + if (!TypeInfos.empty()) { + Asm->OutStreamer.AddComment("-- Catch TypeInfos --"); + Asm->OutStreamer.AddBlankLine(); + } + for (std::vector::const_reverse_iterator + I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { + const GlobalVariable *GV = *I; + + Asm->OutStreamer.AddComment("TypeInfo"); + if (GV) + Asm->EmitReference(GV, TTypeEncoding); + else + Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), + 0); + } + + // Emit the Exception Specifications. + if (!FilterIds.empty()) { + Asm->OutStreamer.AddComment("-- Filter IDs --"); + Asm->OutStreamer.AddBlankLine(); + } + for (std::vector::const_iterator + I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { + unsigned TypeID = *I; + Asm->EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); + } + + Asm->EmitAlignment(2); +} + +/// EndModule - Emit all exception information that should come after the +/// content. +void DwarfException::EndModule() { + assert(0 && "Should be implemented"); +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void DwarfException::BeginFunction(const MachineFunction *MF) { + assert(0 && "Should be implemented"); +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void DwarfException::EndFunction() { + assert(0 && "Should be implemented"); +} diff --git a/final/lib/CodeGen/AsmPrinter/DwarfException.h b/final/lib/CodeGen/AsmPrinter/DwarfException.h new file mode 100644 index 00000000000..06b1de62fbd --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfException.h @@ -0,0 +1,274 @@ +//===-- DwarfException.h - Dwarf Exception Framework -----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H + +#include "llvm/ADT/DenseMap.h" +#include + +namespace llvm { + +template class SmallVectorImpl; +struct LandingPadInfo; +class MachineModuleInfo; +class MachineMove; +class MachineInstr; +class MachineFunction; +class MCAsmInfo; +class MCExpr; +class MCSymbol; +class Function; +class AsmPrinter; + +//===----------------------------------------------------------------------===// +/// DwarfException - Emits Dwarf exception handling directives. +/// +class DwarfException { +protected: + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + /// MMI - Collected machine module information. + MachineModuleInfo *MMI; + + /// EmitExceptionTable - Emit landing pads and actions. + /// + /// The general organization of the table is complex, but the basic concepts + /// are easy. First there is a header which describes the location and + /// organization of the three components that follow. + /// 1. The landing pad site information describes the range of code covered + /// by the try. In our case it's an accumulation of the ranges covered + /// by the invokes in the try. There is also a reference to the landing + /// pad that handles the exception once processed. Finally an index into + /// the actions table. + /// 2. The action table, in our case, is composed of pairs of type ids + /// and next action offset. Starting with the action index from the + /// landing pad site, each type Id is checked for a match to the current + /// exception. If it matches then the exception and type id are passed + /// on to the landing pad. Otherwise the next action is looked up. This + /// chain is terminated with a next action of zero. If no type id is + /// found the frame is unwound and handling continues. + /// 3. Type id table contains references to all the C++ typeinfo for all + /// catches in the function. This tables is reversed indexed base 1. + + /// SharedTypeIds - How many leading type ids two landing pads have in common. + static unsigned SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R); + + /// PadLT - Order landing pads lexicographically by type id. + static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R); + + /// PadRange - Structure holding a try-range and the associated landing pad. + struct PadRange { + // The index of the landing pad. + unsigned PadIndex; + // The index of the begin and end labels in the landing pad's label lists. + unsigned RangeIndex; + }; + + typedef DenseMap RangeMapType; + + /// ActionEntry - Structure describing an entry in the actions table. + struct ActionEntry { + int ValueForTypeID; // The value to write - may not be equal to the type id. + int NextAction; + unsigned Previous; + }; + + /// CallSiteEntry - Structure describing an entry in the call-site table. + struct CallSiteEntry { + // The 'try-range' is BeginLabel .. EndLabel. + MCSymbol *BeginLabel; // zero indicates the start of the function. + MCSymbol *EndLabel; // zero indicates the end of the function. + + // The landing pad starts at PadLabel. + MCSymbol *PadLabel; // zero indicates that there is no landing pad. + unsigned Action; + }; + + /// ComputeActionsTable - Compute the actions table and gather the first + /// action index for each landing pad site. + unsigned ComputeActionsTable(const SmallVectorImpl&LPs, + SmallVectorImpl &Actions, + SmallVectorImpl &FirstActions); + + /// CallToNoUnwindFunction - Return `true' if this is a call to a function + /// marked `nounwind'. Return `false' otherwise. + bool CallToNoUnwindFunction(const MachineInstr *MI); + + /// ComputeCallSiteTable - Compute the call-site table. The entry for an + /// invoke has a try-range containing the call, a non-zero landing pad and an + /// appropriate action. The entry for an ordinary call has a try-range + /// containing the call and zero for the landing pad and the action. Calls + /// marked 'nounwind' have no entry and must not be contained in the try-range + /// of any entry - they form gaps in the table. Entries must be ordered by + /// try-range address. + void ComputeCallSiteTable(SmallVectorImpl &CallSites, + const RangeMapType &PadMap, + const SmallVectorImpl &LPs, + const SmallVectorImpl &FirstActions); + void EmitExceptionTable(); + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfException(AsmPrinter *A); + virtual ~DwarfException(); + + /// EndModule - Emit all exception information that should come after the + /// content. + virtual void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + virtual void BeginFunction(const MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + virtual void EndFunction(); +}; + +class DwarfCFIException : public DwarfException { + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfCFIException(AsmPrinter *A); + virtual ~DwarfCFIException(); + + /// EndModule - Emit all exception information that should come after the + /// content. + virtual void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + virtual void BeginFunction(const MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + virtual void EndFunction(); +}; + +class DwarfTableException : public DwarfException { + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; + + /// shouldEmitMovesModule - Per-module flag to indicate if frame moves + /// should be emitted. + bool shouldEmitMovesModule; + + struct FunctionEHFrameInfo { + MCSymbol *FunctionEHSym; // L_foo.eh + unsigned Number; + unsigned PersonalityIndex; + bool adjustsStack; + bool hasLandingPads; + std::vector Moves; + const Function *function; + + FunctionEHFrameInfo(MCSymbol *EHSym, unsigned Num, unsigned P, + bool hC, bool hL, + const std::vector &M, + const Function *f): + FunctionEHSym(EHSym), Number(Num), PersonalityIndex(P), + adjustsStack(hC), hasLandingPads(hL), Moves(M), function (f) { } + }; + + std::vector EHFrames; + + /// UsesLSDA - Indicates whether an FDE that uses the CIE at the given index + /// uses an LSDA. If so, then we need to encode that information in the CIE's + /// augmentation. + DenseMap UsesLSDA; + + /// EmitCIE - Emit a Common Information Entry (CIE). This holds information + /// that is shared among many Frame Description Entries. There is at least + /// one CIE in every non-empty .debug_frame section. + void EmitCIE(const Function *Personality, unsigned Index); + + /// EmitFDE - Emit the Frame Description Entry (FDE) for the function. + void EmitFDE(const FunctionEHFrameInfo &EHFrameInfo); +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + DwarfTableException(AsmPrinter *A); + virtual ~DwarfTableException(); + + /// EndModule - Emit all exception information that should come after the + /// content. + virtual void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + virtual void BeginFunction(const MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + virtual void EndFunction(); +}; + + +class ARMException : public DwarfException { + /// shouldEmitTable - Per-function flag to indicate if EH tables should + /// be emitted. + bool shouldEmitTable; + + /// shouldEmitMoves - Per-function flag to indicate if frame moves info + /// should be emitted. + bool shouldEmitMoves; + + /// shouldEmitTableModule - Per-module flag to indicate if EH tables + /// should be emitted. + bool shouldEmitTableModule; +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + ARMException(AsmPrinter *A); + virtual ~ARMException(); + + /// EndModule - Emit all exception information that should come after the + /// content. + virtual void EndModule(); + + /// BeginFunction - Gather pre-function exception information. Assumes being + /// emitted immediately after the function entry point. + virtual void BeginFunction(const MachineFunction *MF); + + /// EndFunction - Gather and emit post-function exception information. + virtual void EndFunction(); +}; + +} // End of namespace llvm + +#endif diff --git a/final/lib/CodeGen/AsmPrinter/DwarfTableException.cpp b/final/lib/CodeGen/AsmPrinter/DwarfTableException.cpp new file mode 100644 index 00000000000..751901183cd --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/DwarfTableException.cpp @@ -0,0 +1,349 @@ +//===-- CodeGen/AsmPrinter/DwarfTableException.cpp - Dwarf Exception Impl --==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// The implementation emits all the necessary tables "by hands". +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +using namespace llvm; + +DwarfTableException::DwarfTableException(AsmPrinter *A) + : DwarfException(A), + shouldEmitTable(false), shouldEmitMoves(false), + shouldEmitTableModule(false), shouldEmitMovesModule(false) {} + +DwarfTableException::~DwarfTableException() {} + +/// EmitCIE - Emit a Common Information Entry (CIE). This holds information that +/// is shared among many Frame Description Entries. There is at least one CIE +/// in every non-empty .debug_frame section. +void DwarfTableException::EmitCIE(const Function *PersonalityFn, unsigned Index) { + // Size and sign of stack growth. + int stackGrowth = Asm->getTargetData().getPointerSize(); + if (Asm->TM.getFrameLowering()->getStackGrowthDirection() == + TargetFrameLowering::StackGrowsDown) + stackGrowth *= -1; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + // Begin eh frame section. + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + + MCSymbol *EHFrameSym; + if (TLOF.isFunctionEHFrameSymbolPrivate()) + EHFrameSym = Asm->GetTempSymbol("EH_frame", Index); + else + EHFrameSym = Asm->OutContext.GetOrCreateSymbol(Twine("EH_frame") + + Twine(Index)); + Asm->OutStreamer.EmitLabel(EHFrameSym); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_eh_frame", Index)); + + // Define base labels. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common", Index)); + + // Define the eh frame length. + Asm->OutStreamer.AddComment("Length of Common Information Entry"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_frame_common_end", Index), + Asm->GetTempSymbol("eh_frame_common_begin", Index), + 4); + + // EH frame header. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_begin",Index)); + Asm->OutStreamer.AddComment("CIE Identifier Tag"); + Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + Asm->OutStreamer.AddComment("DW_CIE_VERSION"); + Asm->OutStreamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1/*size*/, 0/*addr*/); + + // The personality presence indicates that language specific information will + // show up in the eh frame. Find out how we are supposed to lower the + // personality function reference: + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + + char Augmentation[6] = { 0 }; + unsigned AugmentationSize = 0; + char *APtr = Augmentation + 1; + + if (PersonalityFn) { + // There is a personality function. + *APtr++ = 'P'; + AugmentationSize += 1 + Asm->GetSizeOfEncodedValue(PerEncoding); + } + + if (UsesLSDA[Index]) { + // An LSDA pointer is in the FDE augmentation. + *APtr++ = 'L'; + ++AugmentationSize; + } + + if (FDEEncoding != dwarf::DW_EH_PE_absptr) { + // A non-default pointer encoding for the FDE. + *APtr++ = 'R'; + ++AugmentationSize; + } + + if (APtr != Augmentation + 1) + Augmentation[0] = 'z'; + + Asm->OutStreamer.AddComment("CIE Augmentation"); + Asm->OutStreamer.EmitBytes(StringRef(Augmentation, strlen(Augmentation)+1),0); + + // Round out reader. + Asm->EmitULEB128(1, "CIE Code Alignment Factor"); + Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor"); + Asm->OutStreamer.AddComment("CIE Return Address Column"); + + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); + + if (Augmentation[0]) { + Asm->EmitULEB128(AugmentationSize, "Augmentation Size"); + + // If there is a personality, we need to indicate the function's location. + if (PersonalityFn) { + Asm->EmitEncodingByte(PerEncoding, "Personality"); + Asm->OutStreamer.AddComment("Personality"); + Asm->EmitReference(PersonalityFn, PerEncoding); + } + if (UsesLSDA[Index]) + Asm->EmitEncodingByte(LSDAEncoding, "LSDA"); + if (FDEEncoding != dwarf::DW_EH_PE_absptr) + Asm->EmitEncodingByte(FDEEncoding, "FDE"); + } + + // Indicate locations of general callee saved registers in frame. + std::vector Moves; + TFI->getInitialFrameState(Moves); + Asm->EmitFrameMoves(Moves, 0, true); + + // On Darwin the linker honors the alignment of eh_frame, which means it must + // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get + // holes which confuse readers of eh_frame. + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_common_end", Index)); +} + +/// EmitFDE - Emit the Frame Description Entry (FDE) for the function. +void DwarfTableException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { + assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && + "Should not emit 'available externally' functions at all"); + + const Function *TheFunc = EHFrameInfo.function; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + + // Externally visible entry into the functions eh frame info. If the + // corresponding function is static, this should not be externally visible. + if (!TheFunc->hasLocalLinkage() && TLOF.isFunctionEHSymbolGlobal()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym,MCSA_Global); + + // If corresponding function is weak definition, this should be too. + if (TheFunc->isWeakForLinker() && Asm->MAI->getWeakDefDirective()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_WeakDefinition); + + // If corresponding function is hidden, this should be too. + if (TheFunc->hasHiddenVisibility()) + if (MCSymbolAttr HiddenAttr = Asm->MAI->getHiddenVisibilityAttr()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + HiddenAttr); + + // If there are no calls then you can't unwind. This may mean we can omit the + // EH Frame, but some environments do not handle weak absolute symbols. If + // UnwindTablesMandatory is set we cannot do this optimization; the unwind + // info is to be available for non-EH uses. + if (!EHFrameInfo.adjustsStack && !UnwindTablesMandatory && + (!TheFunc->isWeakForLinker() || + !Asm->MAI->getWeakDefDirective() || + TLOF.getSupportsWeakOmittedEHFrame())) { + Asm->OutStreamer.EmitAssignment(EHFrameInfo.FunctionEHSym, + MCConstantExpr::Create(0, Asm->OutContext)); + // This name has no connection to the function, so it might get + // dead-stripped when the function is not, erroneously. Prohibit + // dead-stripping unconditionally. + if (Asm->MAI->hasNoDeadStrip()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_NoDeadStrip); + } else { + Asm->OutStreamer.EmitLabel(EHFrameInfo.FunctionEHSym); + + // EH frame header. + Asm->OutStreamer.AddComment("Length of Frame Information Entry"); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_end", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), 4); + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_begin", + EHFrameInfo.Number)); + + Asm->OutStreamer.AddComment("FDE CIE offset"); + Asm->EmitLabelDifference( + Asm->GetTempSymbol("eh_frame_begin", EHFrameInfo.Number), + Asm->GetTempSymbol("eh_frame_common", + EHFrameInfo.PersonalityIndex), 4); + + MCSymbol *EHFuncBeginSym = + Asm->GetTempSymbol("eh_func_begin", EHFrameInfo.Number); + + Asm->OutStreamer.AddComment("FDE initial location"); + Asm->EmitReference(EHFuncBeginSym, FDEEncoding); + + Asm->OutStreamer.AddComment("FDE address range"); + Asm->EmitLabelDifference(Asm->GetTempSymbol("eh_func_end", + EHFrameInfo.Number), + EHFuncBeginSym, + Asm->GetSizeOfEncodedValue(FDEEncoding)); + + // If there is a personality and landing pads then point to the language + // specific data area in the exception table. + if (MMI->getPersonalities()[0] != NULL) { + unsigned Size = Asm->GetSizeOfEncodedValue(LSDAEncoding); + + Asm->EmitULEB128(Size, "Augmentation size"); + Asm->OutStreamer.AddComment("Language Specific Data Area"); + if (EHFrameInfo.hasLandingPads) + Asm->EmitReference(Asm->GetTempSymbol("exception", EHFrameInfo.Number), + LSDAEncoding); + else + Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); + + } else { + Asm->EmitULEB128(0, "Augmentation size"); + } + + // Indicate locations of function specific callee saved registers in frame. + Asm->EmitFrameMoves(EHFrameInfo.Moves, EHFuncBeginSym, true); + + // On Darwin the linker honors the alignment of eh_frame, which means it + // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you + // get holes which confuse readers of eh_frame. + Asm->EmitAlignment(Asm->getTargetData().getPointerSize() == 4 ? 2 : 3); + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_frame_end", + EHFrameInfo.Number)); + + // If the function is marked used, this table should be also. We cannot + // make the mark unconditional in this case, since retaining the table also + // retains the function in this case, and there is code around that depends + // on unused functions (calling undefined externals) being dead-stripped to + // link correctly. Yes, there really is. + if (MMI->isUsedFunction(EHFrameInfo.function)) + if (Asm->MAI->hasNoDeadStrip()) + Asm->OutStreamer.EmitSymbolAttribute(EHFrameInfo.FunctionEHSym, + MCSA_NoDeadStrip); + } + Asm->OutStreamer.AddBlankLine(); +} + +/// EndModule - Emit all exception information that should come after the +/// content. +void DwarfTableException::EndModule() { + if (!Asm->MAI->isExceptionHandlingDwarf()) + return; + + if (!shouldEmitMovesModule && !shouldEmitTableModule) + return; + + const std::vector &Personalities = MMI->getPersonalities(); + + for (unsigned I = 0, E = Personalities.size(); I < E; ++I) + EmitCIE(Personalities[I], I); + + for (std::vector::iterator + I = EHFrames.begin(), E = EHFrames.end(); I != E; ++I) + EmitFDE(*I); +} + +/// BeginFunction - Gather pre-function exception information. Assumes it's +/// being emitted immediately after the function entry point. +void DwarfTableException::BeginFunction(const MachineFunction *MF) { + shouldEmitTable = shouldEmitMoves = false; + + // If any landing pads survive, we need an EH table. + shouldEmitTable = !MMI->getLandingPads().empty(); + + // See if we need frame move info. + shouldEmitMoves = + !Asm->MF->getFunction()->doesNotThrow() || UnwindTablesMandatory; + + if (shouldEmitMoves || shouldEmitTable) + // Assumes in correct section after the entry point. + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", + Asm->getFunctionNumber())); + + shouldEmitTableModule |= shouldEmitTable; + shouldEmitMovesModule |= shouldEmitMoves; +} + +/// EndFunction - Gather and emit post-function exception information. +/// +void DwarfTableException::EndFunction() { + if (!shouldEmitMoves && !shouldEmitTable) return; + + Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", + Asm->getFunctionNumber())); + + // Record if this personality index uses a landing pad. + bool HasLandingPad = !MMI->getLandingPads().empty(); + UsesLSDA[MMI->getPersonalityIndex()] |= HasLandingPad; + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + + if (HasLandingPad) + EmitExceptionTable(); + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + MCSymbol *FunctionEHSym = + Asm->GetSymbolWithGlobalValueBase(Asm->MF->getFunction(), ".eh", + TLOF.isFunctionEHFrameSymbolPrivate()); + + // Save EH frame information + EHFrames. + push_back(FunctionEHFrameInfo(FunctionEHSym, + Asm->getFunctionNumber(), + MMI->getPersonalityIndex(), + Asm->MF->getFrameInfo()->adjustsStack(), + !MMI->getLandingPads().empty(), + MMI->getFrameMoves(), + Asm->MF->getFunction())); +} diff --git a/final/lib/CodeGen/AsmPrinter/Makefile b/final/lib/CodeGen/AsmPrinter/Makefile new file mode 100644 index 00000000000..60aa6cbcf6f --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/Makefile @@ -0,0 +1,13 @@ +##===- lib/CodeGen/AsmPrinter/Makefile ---------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMAsmPrinter + +include $(LEVEL)/Makefile.common diff --git a/final/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/final/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp new file mode 100644 index 00000000000..11538176775 --- /dev/null +++ b/final/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -0,0 +1,166 @@ +//===-- OcamlGCPrinter.cpp - Ocaml frametable emitter ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements printing the assembly code for an Ocaml frametable. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/Module.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include +using namespace llvm; + +namespace { + + class OcamlGCMetadataPrinter : public GCMetadataPrinter { + public: + void beginAssembly(AsmPrinter &AP); + void finishAssembly(AsmPrinter &AP); + }; + +} + +static GCMetadataPrinterRegistry::Add +Y("ocaml", "ocaml 3.10-compatible collector"); + +void llvm::linkOcamlGCPrinter() { } + +static void EmitCamlGlobal(const Module &M, AsmPrinter &AP, const char *Id) { + const std::string &MId = M.getModuleIdentifier(); + + std::string SymName; + SymName += "caml"; + size_t Letter = SymName.size(); + SymName.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); + SymName += "__"; + SymName += Id; + + // Capitalize the first letter of the module name. + SymName[Letter] = toupper(SymName[Letter]); + + SmallString<128> TmpStr; + AP.Mang->getNameWithPrefix(TmpStr, SymName); + + MCSymbol *Sym = AP.OutContext.GetOrCreateSymbol(TmpStr); + + AP.OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global); + AP.OutStreamer.EmitLabel(Sym); +} + +void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) { + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), AP, "code_begin"); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), AP, "data_begin"); +} + +/// emitAssembly - Print the frametable. The ocaml frametable format is thus: +/// +/// extern "C" struct align(sizeof(intptr_t)) { +/// uint16_t NumDescriptors; +/// struct align(sizeof(intptr_t)) { +/// void *ReturnAddress; +/// uint16_t FrameSize; +/// uint16_t NumLiveOffsets; +/// uint16_t LiveOffsets[NumLiveOffsets]; +/// } Descriptors[NumDescriptors]; +/// } caml${module}__frametable; +/// +/// Note that this precludes programs from stack frames larger than 64K +/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if +/// either condition is detected in a function which uses the GC. +/// +void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { + unsigned IntPtrSize = AP.TM.getTargetData()->getPointerSize(); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); + EmitCamlGlobal(getModule(), AP, "code_end"); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), AP, "data_end"); + + // FIXME: Why does ocaml emit this?? + AP.OutStreamer.EmitIntValue(0, IntPtrSize, 0); + + AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getDataSection()); + EmitCamlGlobal(getModule(), AP, "frametable"); + + int NumDescriptors = 0; + for (iterator I = begin(), IE = end(); I != IE; ++I) { + GCFunctionInfo &FI = **I; + for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { + NumDescriptors++; + } + } + + if (NumDescriptors >= 1<<16) { + // Very rude! + report_fatal_error(" Too much descriptor for ocaml GC"); + } + AP.EmitInt16(NumDescriptors); + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); + + for (iterator I = begin(), IE = end(); I != IE; ++I) { + GCFunctionInfo &FI = **I; + + uint64_t FrameSize = FI.getFrameSize(); + if (FrameSize >= 1<<16) { + // Very rude! + report_fatal_error("Function '" + FI.getFunction().getName() + + "' is too large for the ocaml GC! " + "Frame size " + Twine(FrameSize) + ">= 65536.\n" + "(" + Twine(uintptr_t(&FI)) + ")"); + } + + AP.OutStreamer.AddComment("live roots for " + + Twine(FI.getFunction().getName())); + AP.OutStreamer.AddBlankLine(); + + for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { + size_t LiveCount = FI.live_size(J); + if (LiveCount >= 1<<16) { + // Very rude! + report_fatal_error("Function '" + FI.getFunction().getName() + + "' is too large for the ocaml GC! " + "Live root count "+Twine(LiveCount)+" >= 65536."); + } + + AP.OutStreamer.EmitSymbolValue(J->Label, IntPtrSize, 0); + AP.EmitInt16(FrameSize); + AP.EmitInt16(LiveCount); + + for (GCFunctionInfo::live_iterator K = FI.live_begin(J), + KE = FI.live_end(J); K != KE; ++K) { + if (K->StackOffset >= 1<<16) { + // Very rude! + report_fatal_error( + "GC root stack offset is outside of fixed stack frame and out " + "of range for ocaml GC!"); + } + AP.EmitInt16(K->StackOffset); + } + + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); + } + } +} diff --git a/final/lib/CodeGen/BranchFolding.cpp b/final/lib/CodeGen/BranchFolding.cpp new file mode 100644 index 00000000000..78a87431fea --- /dev/null +++ b/final/lib/CodeGen/BranchFolding.cpp @@ -0,0 +1,1341 @@ +//===-- BranchFolding.cpp - Fold machine code branch instructions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass forwards branches to unconditional branches to make them branch +// directly to the target block. This pass often results in dead MBB's, which +// it then removes. +// +// Note that this pass must be run after register allocation, it cannot handle +// SSA form. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "branchfolding" +#include "BranchFolding.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +STATISTIC(NumDeadBlocks, "Number of dead blocks removed"); +STATISTIC(NumBranchOpts, "Number of branches optimized"); +STATISTIC(NumTailMerge , "Number of block tails merged"); + +static cl::opt FlagEnableTailMerge("enable-tail-merge", + cl::init(cl::BOU_UNSET), cl::Hidden); + +// Throttle for huge numbers of predecessors (compile speed problems) +static cl::opt +TailMergeThreshold("tail-merge-threshold", + cl::desc("Max number of predecessors to consider tail merging"), + cl::init(150), cl::Hidden); + +// Heuristic for tail merging (and, inversely, tail duplication). +// TODO: This should be replaced with a target query. +static cl::opt +TailMergeSize("tail-merge-size", + cl::desc("Min number of instructions to consider tail merging"), + cl::init(3), cl::Hidden); + +namespace { + /// BranchFolderPass - Wrap branch folder in a machine function pass. + class BranchFolderPass : public MachineFunctionPass, + public BranchFolder { + public: + static char ID; + explicit BranchFolderPass(bool defaultEnableTailMerge) + : MachineFunctionPass(ID), BranchFolder(defaultEnableTailMerge) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "Control Flow Optimizer"; } + }; +} + +char BranchFolderPass::ID = 0; + +FunctionPass *llvm::createBranchFoldingPass(bool DefaultEnableTailMerge) { + return new BranchFolderPass(DefaultEnableTailMerge); +} + +bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) { + return OptimizeFunction(MF, + MF.getTarget().getInstrInfo(), + MF.getTarget().getRegisterInfo(), + getAnalysisIfAvailable()); +} + + +BranchFolder::BranchFolder(bool defaultEnableTailMerge) { + switch (FlagEnableTailMerge) { + case cl::BOU_UNSET: EnableTailMerge = defaultEnableTailMerge; break; + case cl::BOU_TRUE: EnableTailMerge = true; break; + case cl::BOU_FALSE: EnableTailMerge = false; break; + } +} + +/// RemoveDeadBlock - Remove the specified dead machine basic block from the +/// function, updating the CFG. +void BranchFolder::RemoveDeadBlock(MachineBasicBlock *MBB) { + assert(MBB->pred_empty() && "MBB must be dead!"); + DEBUG(dbgs() << "\nRemoving MBB: " << *MBB); + + MachineFunction *MF = MBB->getParent(); + // drop all successors. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_end()-1); + + // Remove the block. + MF->erase(MBB); +} + +/// OptimizeImpDefsBlock - If a basic block is just a bunch of implicit_def +/// followed by terminators, and if the implicitly defined registers are not +/// used by the terminators, remove those implicit_def's. e.g. +/// BB1: +/// r0 = implicit_def +/// r1 = implicit_def +/// br +/// This block can be optimized away later if the implicit instructions are +/// removed. +bool BranchFolder::OptimizeImpDefsBlock(MachineBasicBlock *MBB) { + SmallSet ImpDefRegs; + MachineBasicBlock::iterator I = MBB->begin(); + while (I != MBB->end()) { + if (!I->isImplicitDef()) + break; + unsigned Reg = I->getOperand(0).getReg(); + ImpDefRegs.insert(Reg); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + ImpDefRegs.insert(SubReg); + ++I; + } + if (ImpDefRegs.empty()) + return false; + + MachineBasicBlock::iterator FirstTerm = I; + while (I != MBB->end()) { + if (!TII->isUnpredicatedTerminator(I)) + return false; + // See if it uses any of the implicitly defined registers. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (ImpDefRegs.count(Reg)) + return false; + } + ++I; + } + + I = MBB->begin(); + while (I != FirstTerm) { + MachineInstr *ImpDefMI = &*I; + ++I; + MBB->erase(ImpDefMI); + } + + return true; +} + +/// OptimizeFunction - Perhaps branch folding, tail merging and other +/// CFG optimizations on the given function. +bool BranchFolder::OptimizeFunction(MachineFunction &MF, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + MachineModuleInfo *mmi) { + if (!tii) return false; + + TII = tii; + TRI = tri; + MMI = mmi; + + RS = TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : NULL; + + // Fix CFG. The later algorithms expect it to be right. + bool MadeChange = false; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; I++) { + MachineBasicBlock *MBB = I, *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, true)) + MadeChange |= MBB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); + MadeChange |= OptimizeImpDefsBlock(MBB); + } + + bool MadeChangeThisIteration = true; + while (MadeChangeThisIteration) { + MadeChangeThisIteration = false; + MadeChangeThisIteration |= TailMergeBlocks(MF); + MadeChangeThisIteration |= OptimizeBranches(MF); + MadeChange |= MadeChangeThisIteration; + } + + // See if any jump tables have become dead as the code generator + // did its thing. + MachineJumpTableInfo *JTI = MF.getJumpTableInfo(); + if (JTI == 0) { + delete RS; + return MadeChange; + } + + // Walk the function to find jump tables that are live. + BitVector JTIsLive(JTI->getJumpTables().size()); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); + BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) { + MachineOperand &Op = I->getOperand(op); + if (!Op.isJTI()) continue; + + // Remember that this JT is live. + JTIsLive.set(Op.getIndex()); + } + } + + // Finally, remove dead jump tables. This happens when the + // indirect jump was unreachable (and thus deleted). + for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i) + if (!JTIsLive.test(i)) { + JTI->RemoveJumpTable(i); + MadeChange = true; + } + + delete RS; + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Tail Merging of Blocks +//===----------------------------------------------------------------------===// + +/// HashMachineInstr - Compute a hash value for MI and its operands. +static unsigned HashMachineInstr(const MachineInstr *MI) { + unsigned Hash = MI->getOpcode(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &Op = MI->getOperand(i); + + // Merge in bits from the operand if easy. + unsigned OperandHash = 0; + switch (Op.getType()) { + case MachineOperand::MO_Register: OperandHash = Op.getReg(); break; + case MachineOperand::MO_Immediate: OperandHash = Op.getImm(); break; + case MachineOperand::MO_MachineBasicBlock: + OperandHash = Op.getMBB()->getNumber(); + break; + case MachineOperand::MO_FrameIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + OperandHash = Op.getIndex(); + break; + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_ExternalSymbol: + // Global address / external symbol are too hard, don't bother, but do + // pull in the offset. + OperandHash = Op.getOffset(); + break; + default: break; + } + + Hash += ((OperandHash << 3) | Op.getType()) << (i&31); + } + return Hash; +} + +/// HashEndOfMBB - Hash the last instruction in the MBB. +static unsigned HashEndOfMBB(const MachineBasicBlock *MBB) { + MachineBasicBlock::const_iterator I = MBB->end(); + if (I == MBB->begin()) + return 0; // Empty MBB. + + --I; + // Skip debug info so it will not affect codegen. + while (I->isDebugValue()) { + if (I==MBB->begin()) + return 0; // MBB empty except for debug info. + --I; + } + + return HashMachineInstr(I); +} + +/// ComputeCommonTailLength - Given two machine basic blocks, compute the number +/// of instructions they actually have in common together at their end. Return +/// iterators for the first shared instruction in each block. +static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2, + MachineBasicBlock::iterator &I1, + MachineBasicBlock::iterator &I2) { + I1 = MBB1->end(); + I2 = MBB2->end(); + + unsigned TailLen = 0; + while (I1 != MBB1->begin() && I2 != MBB2->begin()) { + --I1; --I2; + // Skip debugging pseudos; necessary to avoid changing the code. + while (I1->isDebugValue()) { + if (I1==MBB1->begin()) { + while (I2->isDebugValue()) { + if (I2==MBB2->begin()) + // I1==DBG at begin; I2==DBG at begin + return TailLen; + --I2; + } + ++I2; + // I1==DBG at begin; I2==non-DBG, or first of DBGs not at begin + return TailLen; + } + --I1; + } + // I1==first (untested) non-DBG preceding known match + while (I2->isDebugValue()) { + if (I2==MBB2->begin()) { + ++I1; + // I1==non-DBG, or first of DBGs not at begin; I2==DBG at begin + return TailLen; + } + --I2; + } + // I1, I2==first (untested) non-DBGs preceding known match + if (!I1->isIdenticalTo(I2) || + // FIXME: This check is dubious. It's used to get around a problem where + // people incorrectly expect inline asm directives to remain in the same + // relative order. This is untenable because normal compiler + // optimizations (like this one) may reorder and/or merge these + // directives. + I1->isInlineAsm()) { + ++I1; ++I2; + break; + } + ++TailLen; + } + // Back past possible debugging pseudos at beginning of block. This matters + // when one block differs from the other only by whether debugging pseudos + // are present at the beginning. (This way, the various checks later for + // I1==MBB1->begin() work as expected.) + if (I1 == MBB1->begin() && I2 != MBB2->begin()) { + --I2; + while (I2->isDebugValue()) { + if (I2 == MBB2->begin()) { + return TailLen; + } + --I2; + } + ++I2; + } + if (I2 == MBB2->begin() && I1 != MBB1->begin()) { + --I1; + while (I1->isDebugValue()) { + if (I1 == MBB1->begin()) + return TailLen; + --I1; + } + ++I1; + } + return TailLen; +} + +/// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything +/// after it, replacing it with an unconditional branch to NewDest. +void BranchFolder::ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, + MachineBasicBlock *NewDest) { + TII->ReplaceTailWithBranchTo(OldInst, NewDest); + ++NumTailMerge; +} + +/// SplitMBBAt - Given a machine basic block and an iterator into it, split the +/// MBB so that the part before the iterator falls into the part starting at the +/// iterator. This returns the new MBB. +MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB, + MachineBasicBlock::iterator BBI1) { + if (!TII->isLegalToSplitMBBAt(CurMBB, BBI1)) + return 0; + + MachineFunction &MF = *CurMBB.getParent(); + + // Create the fall-through block. + MachineFunction::iterator MBBI = &CurMBB; + MachineBasicBlock *NewMBB =MF.CreateMachineBasicBlock(CurMBB.getBasicBlock()); + CurMBB.getParent()->insert(++MBBI, NewMBB); + + // Move all the successors of this block to the specified block. + NewMBB->transferSuccessors(&CurMBB); + + // Add an edge from CurMBB to NewMBB for the fall-through. + CurMBB.addSuccessor(NewMBB); + + // Splice the code over. + NewMBB->splice(NewMBB->end(), &CurMBB, BBI1, CurMBB.end()); + + // For targets that use the register scavenger, we must maintain LiveIns. + if (RS) { + RS->enterBasicBlock(&CurMBB); + if (!CurMBB.empty()) + RS->forward(prior(CurMBB.end())); + BitVector RegsLiveAtExit(TRI->getNumRegs()); + RS->getRegsUsed(RegsLiveAtExit, false); + for (unsigned int i = 0, e = TRI->getNumRegs(); i != e; i++) + if (RegsLiveAtExit[i]) + NewMBB->addLiveIn(i); + } + + return NewMBB; +} + +/// EstimateRuntime - Make a rough estimate for how long it will take to run +/// the specified code. +static unsigned EstimateRuntime(MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E) { + unsigned Time = 0; + for (; I != E; ++I) { + if (I->isDebugValue()) + continue; + const TargetInstrDesc &TID = I->getDesc(); + if (TID.isCall()) + Time += 10; + else if (TID.mayLoad() || TID.mayStore()) + Time += 2; + else + ++Time; + } + return Time; +} + +// CurMBB needs to add an unconditional branch to SuccMBB (we removed these +// branches temporarily for tail merging). In the case where CurMBB ends +// with a conditional branch to the next block, optimize by reversing the +// test and conditionally branching to SuccMBB instead. +static void FixTail(MachineBasicBlock *CurMBB, MachineBasicBlock *SuccBB, + const TargetInstrInfo *TII) { + MachineFunction *MF = CurMBB->getParent(); + MachineFunction::iterator I = llvm::next(MachineFunction::iterator(CurMBB)); + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + DebugLoc dl; // FIXME: this is nowhere + if (I != MF->end() && + !TII->AnalyzeBranch(*CurMBB, TBB, FBB, Cond, true)) { + MachineBasicBlock *NextBB = I; + if (TBB == NextBB && !Cond.empty() && !FBB) { + if (!TII->ReverseBranchCondition(Cond)) { + TII->RemoveBranch(*CurMBB); + TII->InsertBranch(*CurMBB, SuccBB, NULL, Cond, dl); + return; + } + } + } + TII->InsertBranch(*CurMBB, SuccBB, NULL, + SmallVector(), dl); +} + +bool +BranchFolder::MergePotentialsElt::operator<(const MergePotentialsElt &o) const { + if (getHash() < o.getHash()) + return true; + else if (getHash() > o.getHash()) + return false; + else if (getBlock()->getNumber() < o.getBlock()->getNumber()) + return true; + else if (getBlock()->getNumber() > o.getBlock()->getNumber()) + return false; + else { + // _GLIBCXX_DEBUG checks strict weak ordering, which involves comparing + // an object with itself. +#ifndef _GLIBCXX_DEBUG + llvm_unreachable("Predecessor appears twice"); +#endif + return false; + } +} + +/// CountTerminators - Count the number of terminators in the given +/// block and set I to the position of the first non-terminator, if there +/// is one, or MBB->end() otherwise. +static unsigned CountTerminators(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &I) { + I = MBB->end(); + unsigned NumTerms = 0; + for (;;) { + if (I == MBB->begin()) { + I = MBB->end(); + break; + } + --I; + if (!I->getDesc().isTerminator()) break; + ++NumTerms; + } + return NumTerms; +} + +/// ProfitableToMerge - Check if two machine basic blocks have a common tail +/// and decide if it would be profitable to merge those tails. Return the +/// length of the common tail and iterators to the first common instruction +/// in each block. +static bool ProfitableToMerge(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2, + unsigned minCommonTailLength, + unsigned &CommonTailLen, + MachineBasicBlock::iterator &I1, + MachineBasicBlock::iterator &I2, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2); + if (CommonTailLen == 0) + return false; + DEBUG(dbgs() << "Common tail length of BB#" << MBB1->getNumber() + << " and BB#" << MBB2->getNumber() << " is " << CommonTailLen + << '\n'); + + // It's almost always profitable to merge any number of non-terminator + // instructions with the block that falls through into the common successor. + if (MBB1 == PredBB || MBB2 == PredBB) { + MachineBasicBlock::iterator I; + unsigned NumTerms = CountTerminators(MBB1 == PredBB ? MBB2 : MBB1, I); + if (CommonTailLen > NumTerms) + return true; + } + + // If one of the blocks can be completely merged and happens to be in + // a position where the other could fall through into it, merge any number + // of instructions, because it can be done without a branch. + // TODO: If the blocks are not adjacent, move one of them so that they are? + if (MBB1->isLayoutSuccessor(MBB2) && I2 == MBB2->begin()) + return true; + if (MBB2->isLayoutSuccessor(MBB1) && I1 == MBB1->begin()) + return true; + + // If both blocks have an unconditional branch temporarily stripped out, + // count that as an additional common instruction for the following + // heuristics. + unsigned EffectiveTailLen = CommonTailLen; + if (SuccBB && MBB1 != PredBB && MBB2 != PredBB && + !MBB1->back().getDesc().isBarrier() && + !MBB2->back().getDesc().isBarrier()) + ++EffectiveTailLen; + + // Check if the common tail is long enough to be worthwhile. + if (EffectiveTailLen >= minCommonTailLength) + return true; + + // If we are optimizing for code size, 2 instructions in common is enough if + // we don't have to split a block. At worst we will be introducing 1 new + // branch instruction, which is likely to be smaller than the 2 + // instructions that would be deleted in the merge. + MachineFunction *MF = MBB1->getParent(); + if (EffectiveTailLen >= 2 && + MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize) && + (I1 == MBB1->begin() || I2 == MBB2->begin())) + return true; + + return false; +} + +/// ComputeSameTails - Look through all the blocks in MergePotentials that have +/// hash CurHash (guaranteed to match the last element). Build the vector +/// SameTails of all those that have the (same) largest number of instructions +/// in common of any pair of these blocks. SameTails entries contain an +/// iterator into MergePotentials (from which the MachineBasicBlock can be +/// found) and a MachineBasicBlock::iterator into that MBB indicating the +/// instruction where the matching code sequence begins. +/// Order of elements in SameTails is the reverse of the order in which +/// those blocks appear in MergePotentials (where they are not necessarily +/// consecutive). +unsigned BranchFolder::ComputeSameTails(unsigned CurHash, + unsigned minCommonTailLength, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + unsigned maxCommonTailLength = 0U; + SameTails.clear(); + MachineBasicBlock::iterator TrialBBI1, TrialBBI2; + MPIterator HighestMPIter = prior(MergePotentials.end()); + for (MPIterator CurMPIter = prior(MergePotentials.end()), + B = MergePotentials.begin(); + CurMPIter != B && CurMPIter->getHash() == CurHash; + --CurMPIter) { + for (MPIterator I = prior(CurMPIter); I->getHash() == CurHash ; --I) { + unsigned CommonTailLen; + if (ProfitableToMerge(CurMPIter->getBlock(), I->getBlock(), + minCommonTailLength, + CommonTailLen, TrialBBI1, TrialBBI2, + SuccBB, PredBB)) { + if (CommonTailLen > maxCommonTailLength) { + SameTails.clear(); + maxCommonTailLength = CommonTailLen; + HighestMPIter = CurMPIter; + SameTails.push_back(SameTailElt(CurMPIter, TrialBBI1)); + } + if (HighestMPIter == CurMPIter && + CommonTailLen == maxCommonTailLength) + SameTails.push_back(SameTailElt(I, TrialBBI2)); + } + if (I == B) + break; + } + } + return maxCommonTailLength; +} + +/// RemoveBlocksWithHash - Remove all blocks with hash CurHash from +/// MergePotentials, restoring branches at ends of blocks as appropriate. +void BranchFolder::RemoveBlocksWithHash(unsigned CurHash, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + MPIterator CurMPIter, B; + for (CurMPIter = prior(MergePotentials.end()), B = MergePotentials.begin(); + CurMPIter->getHash() == CurHash; + --CurMPIter) { + // Put the unconditional branch back, if we need one. + MachineBasicBlock *CurMBB = CurMPIter->getBlock(); + if (SuccBB && CurMBB != PredBB) + FixTail(CurMBB, SuccBB, TII); + if (CurMPIter == B) + break; + } + if (CurMPIter->getHash() != CurHash) + CurMPIter++; + MergePotentials.erase(CurMPIter, MergePotentials.end()); +} + +/// CreateCommonTailOnlyBlock - None of the blocks to be tail-merged consist +/// only of the common tail. Create a block that does by splitting one. +bool BranchFolder::CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB, + unsigned maxCommonTailLength, + unsigned &commonTailIndex) { + commonTailIndex = 0; + unsigned TimeEstimate = ~0U; + for (unsigned i = 0, e = SameTails.size(); i != e; ++i) { + // Use PredBB if possible; that doesn't require a new branch. + if (SameTails[i].getBlock() == PredBB) { + commonTailIndex = i; + break; + } + // Otherwise, make a (fairly bogus) choice based on estimate of + // how long it will take the various blocks to execute. + unsigned t = EstimateRuntime(SameTails[i].getBlock()->begin(), + SameTails[i].getTailStartPos()); + if (t <= TimeEstimate) { + TimeEstimate = t; + commonTailIndex = i; + } + } + + MachineBasicBlock::iterator BBI = + SameTails[commonTailIndex].getTailStartPos(); + MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + + // If the common tail includes any debug info we will take it pretty + // randomly from one of the inputs. Might be better to remove it? + DEBUG(dbgs() << "\nSplitting BB#" << MBB->getNumber() << ", size " + << maxCommonTailLength); + + MachineBasicBlock *newMBB = SplitMBBAt(*MBB, BBI); + if (!newMBB) { + DEBUG(dbgs() << "... failed!"); + return false; + } + + SameTails[commonTailIndex].setBlock(newMBB); + SameTails[commonTailIndex].setTailStartPos(newMBB->begin()); + + // If we split PredBB, newMBB is the new predecessor. + if (PredBB == MBB) + PredBB = newMBB; + + return true; +} + +// See if any of the blocks in MergePotentials (which all have a common single +// successor, or all have no successor) can be tail-merged. If there is a +// successor, any blocks in MergePotentials that are not tail-merged and +// are not immediately before Succ must have an unconditional branch to +// Succ added (but the predecessor/successor lists need no adjustment). +// The lone predecessor of Succ that falls through into Succ, +// if any, is given in PredBB. + +bool BranchFolder::TryTailMergeBlocks(MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB) { + bool MadeChange = false; + + // Except for the special cases below, tail-merge if there are at least + // this many instructions in common. + unsigned minCommonTailLength = TailMergeSize; + + DEBUG(dbgs() << "\nTryTailMergeBlocks: "; + for (unsigned i = 0, e = MergePotentials.size(); i != e; ++i) + dbgs() << "BB#" << MergePotentials[i].getBlock()->getNumber() + << (i == e-1 ? "" : ", "); + dbgs() << "\n"; + if (SuccBB) { + dbgs() << " with successor BB#" << SuccBB->getNumber() << '\n'; + if (PredBB) + dbgs() << " which has fall-through from BB#" + << PredBB->getNumber() << "\n"; + } + dbgs() << "Looking for common tails of at least " + << minCommonTailLength << " instruction" + << (minCommonTailLength == 1 ? "" : "s") << '\n'; + ); + + // Sort by hash value so that blocks with identical end sequences sort + // together. + std::stable_sort(MergePotentials.begin(), MergePotentials.end()); + + // Walk through equivalence sets looking for actual exact matches. + while (MergePotentials.size() > 1) { + unsigned CurHash = MergePotentials.back().getHash(); + + // Build SameTails, identifying the set of blocks with this hash code + // and with the maximum number of instructions in common. + unsigned maxCommonTailLength = ComputeSameTails(CurHash, + minCommonTailLength, + SuccBB, PredBB); + + // If we didn't find any pair that has at least minCommonTailLength + // instructions in common, remove all blocks with this hash code and retry. + if (SameTails.empty()) { + RemoveBlocksWithHash(CurHash, SuccBB, PredBB); + continue; + } + + // If one of the blocks is the entire common tail (and not the entry + // block, which we can't jump to), we can treat all blocks with this same + // tail at once. Use PredBB if that is one of the possibilities, as that + // will not introduce any extra branches. + MachineBasicBlock *EntryBB = MergePotentials.begin()->getBlock()-> + getParent()->begin(); + unsigned commonTailIndex = SameTails.size(); + // If there are two blocks, check to see if one can be made to fall through + // into the other. + if (SameTails.size() == 2 && + SameTails[0].getBlock()->isLayoutSuccessor(SameTails[1].getBlock()) && + SameTails[1].tailIsWholeBlock()) + commonTailIndex = 1; + else if (SameTails.size() == 2 && + SameTails[1].getBlock()->isLayoutSuccessor( + SameTails[0].getBlock()) && + SameTails[0].tailIsWholeBlock()) + commonTailIndex = 0; + else { + // Otherwise just pick one, favoring the fall-through predecessor if + // there is one. + for (unsigned i = 0, e = SameTails.size(); i != e; ++i) { + MachineBasicBlock *MBB = SameTails[i].getBlock(); + if (MBB == EntryBB && SameTails[i].tailIsWholeBlock()) + continue; + if (MBB == PredBB) { + commonTailIndex = i; + break; + } + if (SameTails[i].tailIsWholeBlock()) + commonTailIndex = i; + } + } + + if (commonTailIndex == SameTails.size() || + (SameTails[commonTailIndex].getBlock() == PredBB && + !SameTails[commonTailIndex].tailIsWholeBlock())) { + // None of the blocks consist entirely of the common tail. + // Split a block so that one does. + if (!CreateCommonTailOnlyBlock(PredBB, + maxCommonTailLength, commonTailIndex)) { + RemoveBlocksWithHash(CurHash, SuccBB, PredBB); + continue; + } + } + + MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + // MBB is common tail. Adjust all other BB's to jump to this one. + // Traversal must be forwards so erases work. + DEBUG(dbgs() << "\nUsing common tail in BB#" << MBB->getNumber() + << " for "); + for (unsigned int i=0, e = SameTails.size(); i != e; ++i) { + if (commonTailIndex == i) + continue; + DEBUG(dbgs() << "BB#" << SameTails[i].getBlock()->getNumber() + << (i == e-1 ? "" : ", ")); + // Hack the end off BB i, making it jump to BB commonTailIndex instead. + ReplaceTailWithBranchTo(SameTails[i].getTailStartPos(), MBB); + // BB i is no longer a predecessor of SuccBB; remove it from the worklist. + MergePotentials.erase(SameTails[i].getMPIter()); + } + DEBUG(dbgs() << "\n"); + // We leave commonTailIndex in the worklist in case there are other blocks + // that match it with a smaller number of instructions. + MadeChange = true; + } + return MadeChange; +} + +bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { + + if (!EnableTailMerge) return false; + + bool MadeChange = false; + + // First find blocks with no successors. + MergePotentials.clear(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + if (I->succ_empty()) + MergePotentials.push_back(MergePotentialsElt(HashEndOfMBB(I), I)); + } + + // See if we can do any tail merging on those. + if (MergePotentials.size() < TailMergeThreshold && + MergePotentials.size() >= 2) + MadeChange |= TryTailMergeBlocks(NULL, NULL); + + // Look at blocks (IBB) with multiple predecessors (PBB). + // We change each predecessor to a canonical form, by + // (1) temporarily removing any unconditional branch from the predecessor + // to IBB, and + // (2) alter conditional branches so they branch to the other block + // not IBB; this may require adding back an unconditional branch to IBB + // later, where there wasn't one coming in. E.g. + // Bcc IBB + // fallthrough to QBB + // here becomes + // Bncc QBB + // with a conceptual B to IBB after that, which never actually exists. + // With those changes, we see whether the predecessors' tails match, + // and merge them if so. We change things out of canonical form and + // back to the way they were later in the process. (OptimizeBranches + // would undo some of this, but we can't use it, because we'd get into + // a compile-time infinite loop repeatedly doing and undoing the same + // transformations.) + + for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end(); + I != E; ++I) { + if (I->pred_size() >= 2 && I->pred_size() < TailMergeThreshold) { + SmallPtrSet UniquePreds; + MachineBasicBlock *IBB = I; + MachineBasicBlock *PredBB = prior(I); + MergePotentials.clear(); + for (MachineBasicBlock::pred_iterator P = I->pred_begin(), + E2 = I->pred_end(); + P != E2; ++P) { + MachineBasicBlock *PBB = *P; + // Skip blocks that loop to themselves, can't tail merge these. + if (PBB == IBB) + continue; + // Visit each predecessor only once. + if (!UniquePreds.insert(PBB)) + continue; + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*PBB, TBB, FBB, Cond, true)) { + // Failing case: IBB is the target of a cbr, and + // we cannot reverse the branch. + SmallVector NewCond(Cond); + if (!Cond.empty() && TBB == IBB) { + if (TII->ReverseBranchCondition(NewCond)) + continue; + // This is the QBB case described above + if (!FBB) + FBB = llvm::next(MachineFunction::iterator(PBB)); + } + // Failing case: the only way IBB can be reached from PBB is via + // exception handling. Happens for landing pads. Would be nice + // to have a bit in the edge so we didn't have to do all this. + if (IBB->isLandingPad()) { + MachineFunction::iterator IP = PBB; IP++; + MachineBasicBlock *PredNextBB = NULL; + if (IP != MF.end()) + PredNextBB = IP; + if (TBB == NULL) { + if (IBB != PredNextBB) // fallthrough + continue; + } else if (FBB) { + if (TBB != IBB && FBB != IBB) // cbr then ubr + continue; + } else if (Cond.empty()) { + if (TBB != IBB) // ubr + continue; + } else { + if (TBB != IBB && IBB != PredNextBB) // cbr + continue; + } + } + // Remove the unconditional branch at the end, if any. + if (TBB && (Cond.empty() || FBB)) { + DebugLoc dl; // FIXME: this is nowhere + TII->RemoveBranch(*PBB); + if (!Cond.empty()) + // reinsert conditional branch only, for now + TII->InsertBranch(*PBB, (TBB == IBB) ? FBB : TBB, 0, NewCond, dl); + } + MergePotentials.push_back(MergePotentialsElt(HashEndOfMBB(PBB), *P)); + } + } + if (MergePotentials.size() >= 2) + MadeChange |= TryTailMergeBlocks(IBB, PredBB); + // Reinsert an unconditional branch if needed. + // The 1 below can occur as a result of removing blocks in TryTailMergeBlocks. + PredBB = prior(I); // this may have been changed in TryTailMergeBlocks + if (MergePotentials.size() == 1 && + MergePotentials.begin()->getBlock() != PredBB) + FixTail(MergePotentials.begin()->getBlock(), IBB, TII); + } + } + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Branch Optimization +//===----------------------------------------------------------------------===// + +bool BranchFolder::OptimizeBranches(MachineFunction &MF) { + bool MadeChange = false; + + // Make sure blocks are numbered in order + MF.RenumberBlocks(); + + for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { + MachineBasicBlock *MBB = I++; + MadeChange |= OptimizeBlock(MBB); + + // If it is dead, remove it. + if (MBB->pred_empty()) { + RemoveDeadBlock(MBB); + MadeChange = true; + ++NumDeadBlocks; + } + } + return MadeChange; +} + +// Blocks should be considered empty if they contain only debug info; +// else the debug info would affect codegen. +static bool IsEmptyBlock(MachineBasicBlock *MBB) { + if (MBB->empty()) + return true; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); + MBBI!=MBBE; ++MBBI) { + if (!MBBI->isDebugValue()) + return false; + } + return true; +} + +// Blocks with only debug info and branches should be considered the same +// as blocks with only branches. +static bool IsBranchOnlyBlock(MachineBasicBlock *MBB) { + MachineBasicBlock::iterator MBBI, MBBE; + for (MBBI = MBB->begin(), MBBE = MBB->end(); MBBI!=MBBE; ++MBBI) { + if (!MBBI->isDebugValue()) + break; + } + return (MBBI->getDesc().isBranch()); +} + +/// IsBetterFallthrough - Return true if it would be clearly better to +/// fall-through to MBB1 than to fall through into MBB2. This has to return +/// a strict ordering, returning true for both (MBB1,MBB2) and (MBB2,MBB1) will +/// result in infinite loops. +static bool IsBetterFallthrough(MachineBasicBlock *MBB1, + MachineBasicBlock *MBB2) { + // Right now, we use a simple heuristic. If MBB2 ends with a call, and + // MBB1 doesn't, we prefer to fall through into MBB1. This allows us to + // optimize branches that branch to either a return block or an assert block + // into a fallthrough to the return. + if (IsEmptyBlock(MBB1) || IsEmptyBlock(MBB2)) return false; + + // If there is a clear successor ordering we make sure that one block + // will fall through to the next + if (MBB1->isSuccessor(MBB2)) return true; + if (MBB2->isSuccessor(MBB1)) return false; + + // Neither block consists entirely of debug info (per IsEmptyBlock check), + // so we needn't test for falling off the beginning here. + MachineBasicBlock::iterator MBB1I = --MBB1->end(); + while (MBB1I->isDebugValue()) + --MBB1I; + MachineBasicBlock::iterator MBB2I = --MBB2->end(); + while (MBB2I->isDebugValue()) + --MBB2I; + return MBB2I->getDesc().isCall() && !MBB1I->getDesc().isCall(); +} + +/// OptimizeBlock - Analyze and optimize control flow related to the specified +/// block. This is never called on the entry block. +bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) { + bool MadeChange = false; + MachineFunction &MF = *MBB->getParent(); + DebugLoc dl; // FIXME: this is nowhere +ReoptimizeBlock: + + MachineFunction::iterator FallThrough = MBB; + ++FallThrough; + + // If this block is empty, make everyone use its fall-through, not the block + // explicitly. Landing pads should not do this since the landing-pad table + // points to this block. Blocks with their addresses taken shouldn't be + // optimized away. + if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) { + // Dead block? Leave for cleanup later. + if (MBB->pred_empty()) return MadeChange; + + if (FallThrough == MF.end()) { + // TODO: Simplify preds to not branch here if possible! + } else { + // Rewrite all predecessors of the old block to go to the fallthrough + // instead. + while (!MBB->pred_empty()) { + MachineBasicBlock *Pred = *(MBB->pred_end()-1); + Pred->ReplaceUsesOfBlockWith(MBB, FallThrough); + } + // If MBB was the target of a jump table, update jump tables to go to the + // fallthrough instead. + if (MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) + MJTI->ReplaceMBBInJumpTables(MBB, FallThrough); + MadeChange = true; + } + return MadeChange; + } + + // Check to see if we can simplify the terminator of the block before this + // one. + MachineBasicBlock &PrevBB = *prior(MachineFunction::iterator(MBB)); + + MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0; + SmallVector PriorCond; + bool PriorUnAnalyzable = + TII->AnalyzeBranch(PrevBB, PriorTBB, PriorFBB, PriorCond, true); + if (!PriorUnAnalyzable) { + // If the CFG for the prior block has extra edges, remove them. + MadeChange |= PrevBB.CorrectExtraCFGEdges(PriorTBB, PriorFBB, + !PriorCond.empty()); + + // If the previous branch is conditional and both conditions go to the same + // destination, remove the branch, replacing it with an unconditional one or + // a fall-through. + if (PriorTBB && PriorTBB == PriorFBB) { + TII->RemoveBranch(PrevBB); + PriorCond.clear(); + if (PriorTBB != MBB) + TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond, dl); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the previous block unconditionally falls through to this block and + // this block has no other predecessors, move the contents of this block + // into the prior block. This doesn't usually happen when SimplifyCFG + // has been used, but it can happen if tail merging splits a fall-through + // predecessor of a block. + // This has to check PrevBB->succ_size() because EH edges are ignored by + // AnalyzeBranch. + if (PriorCond.empty() && !PriorTBB && MBB->pred_size() == 1 && + PrevBB.succ_size() == 1 && + !MBB->hasAddressTaken()) { + DEBUG(dbgs() << "\nMerging into block: " << PrevBB + << "From MBB: " << *MBB); + PrevBB.splice(PrevBB.end(), MBB, MBB->begin(), MBB->end()); + PrevBB.removeSuccessor(PrevBB.succ_begin());; + assert(PrevBB.succ_empty()); + PrevBB.transferSuccessors(MBB); + MadeChange = true; + return MadeChange; + } + + // If the previous branch *only* branches to *this* block (conditional or + // not) remove the branch. + if (PriorTBB == MBB && PriorFBB == 0) { + TII->RemoveBranch(PrevBB); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the prior block branches somewhere else on the condition and here if + // the condition is false, remove the uncond second branch. + if (PriorFBB == MBB) { + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorTBB, 0, PriorCond, dl); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + + // If the prior block branches here on true and somewhere else on false, and + // if the branch condition is reversible, reverse the branch to create a + // fall-through. + if (PriorTBB == MBB) { + SmallVector NewPriorCond(PriorCond); + if (!TII->ReverseBranchCondition(NewPriorCond)) { + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorFBB, 0, NewPriorCond, dl); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + } + + // If this block has no successors (e.g. it is a return block or ends with + // a call to a no-return function like abort or __cxa_throw) and if the pred + // falls through into this block, and if it would otherwise fall through + // into the block after this, move this block to the end of the function. + // + // We consider it more likely that execution will stay in the function (e.g. + // due to loops) than it is to exit it. This asserts in loops etc, moving + // the assert condition out of the loop body. + if (MBB->succ_empty() && !PriorCond.empty() && PriorFBB == 0 && + MachineFunction::iterator(PriorTBB) == FallThrough && + !MBB->canFallThrough()) { + bool DoTransform = true; + + // We have to be careful that the succs of PredBB aren't both no-successor + // blocks. If neither have successors and if PredBB is the second from + // last block in the function, we'd just keep swapping the two blocks for + // last. Only do the swap if one is clearly better to fall through than + // the other. + if (FallThrough == --MF.end() && + !IsBetterFallthrough(PriorTBB, MBB)) + DoTransform = false; + + if (DoTransform) { + // Reverse the branch so we will fall through on the previous true cond. + SmallVector NewPriorCond(PriorCond); + if (!TII->ReverseBranchCondition(NewPriorCond)) { + DEBUG(dbgs() << "\nMoving MBB: " << *MBB + << "To make fallthrough to: " << *PriorTBB << "\n"); + + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, MBB, 0, NewPriorCond, dl); + + // Move this block to the end of the function. + MBB->moveAfter(--MF.end()); + MadeChange = true; + ++NumBranchOpts; + return MadeChange; + } + } + } + } + + // Analyze the branch in the current block. + MachineBasicBlock *CurTBB = 0, *CurFBB = 0; + SmallVector CurCond; + bool CurUnAnalyzable= TII->AnalyzeBranch(*MBB, CurTBB, CurFBB, CurCond, true); + if (!CurUnAnalyzable) { + // If the CFG for the prior block has extra edges, remove them. + MadeChange |= MBB->CorrectExtraCFGEdges(CurTBB, CurFBB, !CurCond.empty()); + + // If this is a two-way branch, and the FBB branches to this block, reverse + // the condition so the single-basic-block loop is faster. Instead of: + // Loop: xxx; jcc Out; jmp Loop + // we want: + // Loop: xxx; jncc Loop; jmp Out + if (CurTBB && CurFBB && CurFBB == MBB && CurTBB != MBB) { + SmallVector NewCond(CurCond); + if (!TII->ReverseBranchCondition(NewCond)) { + TII->RemoveBranch(*MBB); + TII->InsertBranch(*MBB, CurFBB, CurTBB, NewCond, dl); + MadeChange = true; + ++NumBranchOpts; + goto ReoptimizeBlock; + } + } + + // If this branch is the only thing in its block, see if we can forward + // other blocks across it. + if (CurTBB && CurCond.empty() && CurFBB == 0 && + IsBranchOnlyBlock(MBB) && CurTBB != MBB && + !MBB->hasAddressTaken()) { + // This block may contain just an unconditional branch. Because there can + // be 'non-branch terminators' in the block, try removing the branch and + // then seeing if the block is empty. + TII->RemoveBranch(*MBB); + // If the only things remaining in the block are debug info, remove these + // as well, so this will behave the same as an empty block in non-debug + // mode. + if (!MBB->empty()) { + bool NonDebugInfoFound = false; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (!I->isDebugValue()) { + NonDebugInfoFound = true; + break; + } + } + if (!NonDebugInfoFound) + // Make the block empty, losing the debug info (we could probably + // improve this in some cases.) + MBB->erase(MBB->begin(), MBB->end()); + } + // If this block is just an unconditional branch to CurTBB, we can + // usually completely eliminate the block. The only case we cannot + // completely eliminate the block is when the block before this one + // falls through into MBB and we can't understand the prior block's branch + // condition. + if (MBB->empty()) { + bool PredHasNoFallThrough = !PrevBB.canFallThrough(); + if (PredHasNoFallThrough || !PriorUnAnalyzable || + !PrevBB.isSuccessor(MBB)) { + // If the prior block falls through into us, turn it into an + // explicit branch to us to make updates simpler. + if (!PredHasNoFallThrough && PrevBB.isSuccessor(MBB) && + PriorTBB != MBB && PriorFBB != MBB) { + if (PriorTBB == 0) { + assert(PriorCond.empty() && PriorFBB == 0 && + "Bad branch analysis"); + PriorTBB = MBB; + } else { + assert(PriorFBB == 0 && "Machine CFG out of date!"); + PriorFBB = MBB; + } + TII->RemoveBranch(PrevBB); + TII->InsertBranch(PrevBB, PriorTBB, PriorFBB, PriorCond, dl); + } + + // Iterate through all the predecessors, revectoring each in-turn. + size_t PI = 0; + bool DidChange = false; + bool HasBranchToSelf = false; + while(PI != MBB->pred_size()) { + MachineBasicBlock *PMBB = *(MBB->pred_begin() + PI); + if (PMBB == MBB) { + // If this block has an uncond branch to itself, leave it. + ++PI; + HasBranchToSelf = true; + } else { + DidChange = true; + PMBB->ReplaceUsesOfBlockWith(MBB, CurTBB); + // If this change resulted in PMBB ending in a conditional + // branch where both conditions go to the same destination, + // change this to an unconditional branch (and fix the CFG). + MachineBasicBlock *NewCurTBB = 0, *NewCurFBB = 0; + SmallVector NewCurCond; + bool NewCurUnAnalyzable = TII->AnalyzeBranch(*PMBB, NewCurTBB, + NewCurFBB, NewCurCond, true); + if (!NewCurUnAnalyzable && NewCurTBB && NewCurTBB == NewCurFBB) { + TII->RemoveBranch(*PMBB); + NewCurCond.clear(); + TII->InsertBranch(*PMBB, NewCurTBB, 0, NewCurCond, dl); + MadeChange = true; + ++NumBranchOpts; + PMBB->CorrectExtraCFGEdges(NewCurTBB, 0, false); + } + } + } + + // Change any jumptables to go to the new MBB. + if (MachineJumpTableInfo *MJTI = MF.getJumpTableInfo()) + MJTI->ReplaceMBBInJumpTables(MBB, CurTBB); + if (DidChange) { + ++NumBranchOpts; + MadeChange = true; + if (!HasBranchToSelf) return MadeChange; + } + } + } + + // Add the branch back if the block is more than just an uncond branch. + TII->InsertBranch(*MBB, CurTBB, 0, CurCond, dl); + } + } + + // If the prior block doesn't fall through into this block, and if this + // block doesn't fall through into some other block, see if we can find a + // place to move this block where a fall-through will happen. + if (!PrevBB.canFallThrough()) { + + // Now we know that there was no fall-through into this block, check to + // see if it has a fall-through into its successor. + bool CurFallsThru = MBB->canFallThrough(); + + if (!MBB->isLandingPad()) { + // Check all the predecessors of this block. If one of them has no fall + // throughs, move this block right after it. + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + E = MBB->pred_end(); PI != E; ++PI) { + // Analyze the branch at the end of the pred. + MachineBasicBlock *PredBB = *PI; + MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; + MachineBasicBlock *PredTBB = 0, *PredFBB = 0; + SmallVector PredCond; + if (PredBB != MBB && !PredBB->canFallThrough() && + !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) + && (!CurFallsThru || !CurTBB || !CurFBB) + && (!CurFallsThru || MBB->getNumber() >= PredBB->getNumber())) { + // If the current block doesn't fall through, just move it. + // If the current block can fall through and does not end with a + // conditional branch, we need to append an unconditional jump to + // the (current) next block. To avoid a possible compile-time + // infinite loop, move blocks only backward in this case. + // Also, if there are already 2 branches here, we cannot add a third; + // this means we have the case + // Bcc next + // B elsewhere + // next: + if (CurFallsThru) { + MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(MBB)); + CurCond.clear(); + TII->InsertBranch(*MBB, NextBB, 0, CurCond, dl); + } + MBB->moveAfter(PredBB); + MadeChange = true; + goto ReoptimizeBlock; + } + } + } + + if (!CurFallsThru) { + // Check all successors to see if we can move this block before it. + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + E = MBB->succ_end(); SI != E; ++SI) { + // Analyze the branch at the end of the block before the succ. + MachineBasicBlock *SuccBB = *SI; + MachineFunction::iterator SuccPrev = SuccBB; --SuccPrev; + + // If this block doesn't already fall-through to that successor, and if + // the succ doesn't already have a block that can fall through into it, + // and if the successor isn't an EH destination, we can arrange for the + // fallthrough to happen. + if (SuccBB != MBB && &*SuccPrev != MBB && + !SuccPrev->canFallThrough() && !CurUnAnalyzable && + !SuccBB->isLandingPad()) { + MBB->moveBefore(SuccBB); + MadeChange = true; + goto ReoptimizeBlock; + } + } + + // Okay, there is no really great place to put this block. If, however, + // the block before this one would be a fall-through if this block were + // removed, move this block to the end of the function. + MachineBasicBlock *PrevTBB = 0, *PrevFBB = 0; + SmallVector PrevCond; + if (FallThrough != MF.end() && + !TII->AnalyzeBranch(PrevBB, PrevTBB, PrevFBB, PrevCond, true) && + PrevBB.isSuccessor(FallThrough)) { + MBB->moveAfter(--MF.end()); + MadeChange = true; + return MadeChange; + } + } + } + + return MadeChange; +} diff --git a/final/lib/CodeGen/BranchFolding.h b/final/lib/CodeGen/BranchFolding.h new file mode 100644 index 00000000000..15dfa7f6bee --- /dev/null +++ b/final/lib/CodeGen/BranchFolding.h @@ -0,0 +1,116 @@ +//===-- BranchFolding.h - Fold machine code branch instructions --*- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BRANCHFOLDING_HPP +#define LLVM_CODEGEN_BRANCHFOLDING_HPP + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include + +namespace llvm { + class MachineFunction; + class MachineModuleInfo; + class RegScavenger; + class TargetInstrInfo; + class TargetRegisterInfo; + template class SmallVectorImpl; + + class BranchFolder { + public: + explicit BranchFolder(bool defaultEnableTailMerge); + + bool OptimizeFunction(MachineFunction &MF, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + MachineModuleInfo *mmi); + private: + class MergePotentialsElt { + unsigned Hash; + MachineBasicBlock *Block; + public: + MergePotentialsElt(unsigned h, MachineBasicBlock *b) + : Hash(h), Block(b) {} + + unsigned getHash() const { return Hash; } + MachineBasicBlock *getBlock() const { return Block; } + + void setBlock(MachineBasicBlock *MBB) { + Block = MBB; + } + + bool operator<(const MergePotentialsElt &) const; + }; + typedef std::vector::iterator MPIterator; + std::vector MergePotentials; + + class SameTailElt { + MPIterator MPIter; + MachineBasicBlock::iterator TailStartPos; + public: + SameTailElt(MPIterator mp, MachineBasicBlock::iterator tsp) + : MPIter(mp), TailStartPos(tsp) {} + + MPIterator getMPIter() const { + return MPIter; + } + MergePotentialsElt &getMergePotentialsElt() const { + return *getMPIter(); + } + MachineBasicBlock::iterator getTailStartPos() const { + return TailStartPos; + } + unsigned getHash() const { + return getMergePotentialsElt().getHash(); + } + MachineBasicBlock *getBlock() const { + return getMergePotentialsElt().getBlock(); + } + bool tailIsWholeBlock() const { + return TailStartPos == getBlock()->begin(); + } + + void setBlock(MachineBasicBlock *MBB) { + getMergePotentialsElt().setBlock(MBB); + } + void setTailStartPos(MachineBasicBlock::iterator Pos) { + TailStartPos = Pos; + } + }; + std::vector SameTails; + + bool EnableTailMerge; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineModuleInfo *MMI; + RegScavenger *RS; + + bool TailMergeBlocks(MachineFunction &MF); + bool TryTailMergeBlocks(MachineBasicBlock* SuccBB, + MachineBasicBlock* PredBB); + void ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst, + MachineBasicBlock *NewDest); + MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB, + MachineBasicBlock::iterator BBI1); + unsigned ComputeSameTails(unsigned CurHash, unsigned minCommonTailLength, + MachineBasicBlock *SuccBB, + MachineBasicBlock *PredBB); + void RemoveBlocksWithHash(unsigned CurHash, MachineBasicBlock* SuccBB, + MachineBasicBlock* PredBB); + bool CreateCommonTailOnlyBlock(MachineBasicBlock *&PredBB, + unsigned maxCommonTailLength, + unsigned &commonTailIndex); + + bool OptimizeBranches(MachineFunction &MF); + bool OptimizeBlock(MachineBasicBlock *MBB); + void RemoveDeadBlock(MachineBasicBlock *MBB); + bool OptimizeImpDefsBlock(MachineBasicBlock *MBB); + }; +} + +#endif /* LLVM_CODEGEN_BRANCHFOLDING_HPP */ diff --git a/final/lib/CodeGen/CMakeLists.txt b/final/lib/CodeGen/CMakeLists.txt new file mode 100644 index 00000000000..d7d0e1b3812 --- /dev/null +++ b/final/lib/CodeGen/CMakeLists.txt @@ -0,0 +1,99 @@ +add_llvm_library(LLVMCodeGen + AggressiveAntiDepBreaker.cpp + AllocationOrder.cpp + Analysis.cpp + BranchFolding.cpp + CalcSpillWeights.cpp + CallingConvLower.cpp + CodeGen.cpp + CodePlacementOpt.cpp + CriticalAntiDepBreaker.cpp + DeadMachineInstructionElim.cpp + DwarfEHPrepare.cpp + EdgeBundles.cpp + ELFCodeEmitter.cpp + ELFWriter.cpp + ExpandISelPseudos.cpp + GCMetadata.cpp + GCMetadataPrinter.cpp + GCStrategy.cpp + IfConversion.cpp + InlineSpiller.cpp + IntrinsicLowering.cpp + LLVMTargetMachine.cpp + LatencyPriorityQueue.cpp + LiveDebugVariables.cpp + LiveInterval.cpp + LiveIntervalAnalysis.cpp + LiveIntervalUnion.cpp + LiveStackAnalysis.cpp + LiveVariables.cpp + LiveRangeEdit.cpp + LocalStackSlotAllocation.cpp + LowerSubregs.cpp + MachineBasicBlock.cpp + MachineCSE.cpp + MachineDominators.cpp + MachineFunction.cpp + MachineFunctionAnalysis.cpp + MachineFunctionPass.cpp + MachineFunctionPrinterPass.cpp + MachineInstr.cpp + MachineLICM.cpp + MachineLoopInfo.cpp + MachineLoopRanges.cpp + MachineModuleInfo.cpp + MachineModuleInfoImpls.cpp + MachinePassRegistry.cpp + MachineRegisterInfo.cpp + MachineSSAUpdater.cpp + MachineSink.cpp + MachineVerifier.cpp + ObjectCodeEmitter.cpp + OcamlGC.cpp + OptimizePHIs.cpp + PHIElimination.cpp + PHIEliminationUtils.cpp + Passes.cpp + PeepholeOptimizer.cpp + PostRASchedulerList.cpp + PreAllocSplitting.cpp + ProcessImplicitDefs.cpp + PrologEpilogInserter.cpp + PseudoSourceValue.cpp + RegAllocBasic.cpp + RegAllocFast.cpp + RegAllocGreedy.cpp + RegAllocLinearScan.cpp + RegAllocPBQP.cpp + RegisterCoalescer.cpp + RegisterScavenging.cpp + RenderMachineFunction.cpp + ScheduleDAG.cpp + ScheduleDAGEmit.cpp + ScheduleDAGInstrs.cpp + ScheduleDAGPrinter.cpp + ScoreboardHazardRecognizer.cpp + ShadowStackGC.cpp + ShrinkWrapping.cpp + SimpleRegisterCoalescing.cpp + SjLjEHPrepare.cpp + SlotIndexes.cpp + Spiller.cpp + SpillPlacement.cpp + SplitKit.cpp + Splitter.cpp + StackProtector.cpp + StackSlotColoring.cpp + StrongPHIElimination.cpp + TailDuplication.cpp + TargetInstrInfoImpl.cpp + TargetLoweringObjectFileImpl.cpp + TwoAddressInstructionPass.cpp + UnreachableBlockElim.cpp + VirtRegMap.cpp + VirtRegRewriter.cpp + ) + +add_subdirectory(SelectionDAG) +add_subdirectory(AsmPrinter) diff --git a/final/lib/CodeGen/CalcSpillWeights.cpp b/final/lib/CodeGen/CalcSpillWeights.cpp new file mode 100644 index 00000000000..76bb3d148b0 --- /dev/null +++ b/final/lib/CodeGen/CalcSpillWeights.cpp @@ -0,0 +1,227 @@ +//===------------------------ CalcSpillWeights.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "calcspillweights" + +#include "llvm/Function.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +using namespace llvm; + +char CalculateSpillWeights::ID = 0; +INITIALIZE_PASS_BEGIN(CalculateSpillWeights, "calcspillweights", + "Calculate spill weights", false, false) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(CalculateSpillWeights, "calcspillweights", + "Calculate spill weights", false, false) + +void CalculateSpillWeights::getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addRequired(); + au.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(au); +} + +bool CalculateSpillWeights::runOnMachineFunction(MachineFunction &fn) { + + DEBUG(dbgs() << "********** Compute Spill Weights **********\n" + << "********** Function: " + << fn.getFunction()->getName() << '\n'); + + LiveIntervals &lis = getAnalysis(); + VirtRegAuxInfo vrai(fn, lis, getAnalysis()); + for (LiveIntervals::iterator I = lis.begin(), E = lis.end(); I != E; ++I) { + LiveInterval &li = *I->second; + if (TargetRegisterInfo::isVirtualRegister(li.reg)) + vrai.CalculateWeightAndHint(li); + } + return false; +} + +// Return the preferred allocation register for reg, given a COPY instruction. +static unsigned copyHint(const MachineInstr *mi, unsigned reg, + const TargetRegisterInfo &tri, + const MachineRegisterInfo &mri) { + unsigned sub, hreg, hsub; + if (mi->getOperand(0).getReg() == reg) { + sub = mi->getOperand(0).getSubReg(); + hreg = mi->getOperand(1).getReg(); + hsub = mi->getOperand(1).getSubReg(); + } else { + sub = mi->getOperand(1).getSubReg(); + hreg = mi->getOperand(0).getReg(); + hsub = mi->getOperand(0).getSubReg(); + } + + if (!hreg) + return 0; + + if (TargetRegisterInfo::isVirtualRegister(hreg)) + return sub == hsub ? hreg : 0; + + const TargetRegisterClass *rc = mri.getRegClass(reg); + + // Only allow physreg hints in rc. + if (sub == 0) + return rc->contains(hreg) ? hreg : 0; + + // reg:sub should match the physreg hreg. + return tri.getMatchingSuperReg(hreg, sub, rc); +} + +void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) { + MachineRegisterInfo &mri = mf_.getRegInfo(); + const TargetRegisterInfo &tri = *mf_.getTarget().getRegisterInfo(); + MachineBasicBlock *mbb = 0; + MachineLoop *loop = 0; + unsigned loopDepth = 0; + bool isExiting = false; + float totalWeight = 0; + SmallPtrSet visited; + + // Find the best physreg hist and the best virtreg hint. + float bestPhys = 0, bestVirt = 0; + unsigned hintPhys = 0, hintVirt = 0; + + // Don't recompute a target specific hint. + bool noHint = mri.getRegAllocationHint(li.reg).first != 0; + + for (MachineRegisterInfo::reg_iterator I = mri.reg_begin(li.reg); + MachineInstr *mi = I.skipInstruction();) { + if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue()) + continue; + if (!visited.insert(mi)) + continue; + + // Get loop info for mi. + if (mi->getParent() != mbb) { + mbb = mi->getParent(); + loop = loops_.getLoopFor(mbb); + loopDepth = loop ? loop->getLoopDepth() : 0; + isExiting = loop ? loop->isLoopExiting(mbb) : false; + } + + // Calculate instr weight. + bool reads, writes; + tie(reads, writes) = mi->readsWritesVirtualRegister(li.reg); + float weight = LiveIntervals::getSpillWeight(writes, reads, loopDepth); + + // Give extra weight to what looks like a loop induction variable update. + if (writes && isExiting && lis_.isLiveOutOfMBB(li, mbb)) + weight *= 3; + + totalWeight += weight; + + // Get allocation hints from copies. + if (noHint || !mi->isCopy()) + continue; + unsigned hint = copyHint(mi, li.reg, tri, mri); + if (!hint) + continue; + float hweight = hint_[hint] += weight; + if (TargetRegisterInfo::isPhysicalRegister(hint)) { + if (hweight > bestPhys && lis_.isAllocatable(hint)) + bestPhys = hweight, hintPhys = hint; + } else { + if (hweight > bestVirt) + bestVirt = hweight, hintVirt = hint; + } + } + + hint_.clear(); + + // Always prefer the physreg hint. + if (unsigned hint = hintPhys ? hintPhys : hintVirt) { + mri.setRegAllocationHint(li.reg, 0, hint); + // Weakly boost the spill weifght of hinted registers. + totalWeight *= 1.01F; + } + + // Mark li as unspillable if all live ranges are tiny. + if (li.isZeroLength()) { + li.markNotSpillable(); + return; + } + + // If all of the definitions of the interval are re-materializable, + // it is a preferred candidate for spilling. If none of the defs are + // loads, then it's potentially very cheap to re-materialize. + // FIXME: this gets much more complicated once we support non-trivial + // re-materialization. + bool isLoad = false; + SmallVector spillIs; + if (lis_.isReMaterializable(li, spillIs, isLoad)) { + if (isLoad) + totalWeight *= 0.9F; + else + totalWeight *= 0.5F; + } + + li.weight = normalizeSpillWeight(totalWeight, li.getSize()); +} + +void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { + MachineRegisterInfo &mri = mf_.getRegInfo(); + const TargetRegisterInfo *tri = mf_.getTarget().getRegisterInfo(); + const TargetRegisterClass *orc = mri.getRegClass(reg); + SmallPtrSet rcs; + + for (MachineRegisterInfo::reg_nodbg_iterator I = mri.reg_nodbg_begin(reg), + E = mri.reg_nodbg_end(); I != E; ++I) { + // The targets don't have accurate enough regclass descriptions that we can + // handle subregs. We need something similar to + // TRI::getMatchingSuperRegClass, but returning a super class instead of a + // sub class. + if (I.getOperand().getSubReg()) { + DEBUG(dbgs() << "Cannot handle subregs: " << I.getOperand() << '\n'); + return; + } + if (const TargetRegisterClass *rc = + I->getDesc().getRegClass(I.getOperandNo(), tri)) + rcs.insert(rc); + } + + // If we found no regclass constraints, just leave reg as is. + // In theory, we could inflate to the largest superclass of reg's existing + // class, but that might not be legal for the current cpu setting. + // This could happen if reg is only used by COPY instructions, so we may need + // to improve on this. + if (rcs.empty()) { + return; + } + + // Compute the intersection of all classes in rcs. + // This ought to be independent of iteration order, but if the target register + // classes don't form a proper algebra, it is possible to get different + // results. The solution is to make sure the intersection of any two register + // classes is also a register class or the null set. + const TargetRegisterClass *rc = 0; + for (SmallPtrSet::iterator I = rcs.begin(), + E = rcs.end(); I != E; ++I) { + rc = rc ? getCommonSubClass(rc, *I) : *I; + assert(rc && "Incompatible regclass constraints found"); + } + + if (rc == orc) + return; + DEBUG(dbgs() << "Inflating " << orc->getName() << ':' << PrintReg(reg) + << " to " << rc->getName() <<".\n"); + mri.setRegClass(reg, rc); +} diff --git a/final/lib/CodeGen/CallingConvLower.cpp b/final/lib/CodeGen/CallingConvLower.cpp new file mode 100644 index 00000000000..ecd69a08e86 --- /dev/null +++ b/final/lib/CodeGen/CallingConvLower.cpp @@ -0,0 +1,177 @@ +//===-- CallingConvLower.cpp - Calling Conventions ------------------------===// +// +// 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 CCState class, used for lowering and implementing +// calling conventions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +CCState::CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &tm, + SmallVector &locs, LLVMContext &C) + : CallingConv(CC), IsVarArg(isVarArg), TM(tm), + TRI(*TM.getRegisterInfo()), Locs(locs), Context(C) { + // No stack is used. + StackOffset = 0; + + UsedRegs.resize((TRI.getNumRegs()+31)/32); +} + +// HandleByVal - Allocate a stack slot large enough to pass an argument by +// value. The size and alignment information of the argument is encoded in its +// parameter attribute. +void CCState::HandleByVal(unsigned ValNo, MVT ValVT, + MVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, + ISD::ArgFlagsTy ArgFlags) { + unsigned Align = ArgFlags.getByValAlign(); + unsigned Size = ArgFlags.getByValSize(); + if (MinSize > (int)Size) + Size = MinSize; + if (MinAlign > (int)Align) + Align = MinAlign; + unsigned Offset = AllocateStack(Size, Align); + + addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + TM.getTargetLowering()->HandleByVal(const_cast(this)); +} + +/// MarkAllocated - Mark a register and all of its aliases as allocated. +void CCState::MarkAllocated(unsigned Reg) { + for (const unsigned *Alias = TRI.getOverlaps(Reg); + unsigned Reg = *Alias; ++Alias) + UsedRegs[Reg/32] |= 1 << (Reg&31); +} + +/// AnalyzeFormalArguments - Analyze an array of argument values, +/// incorporating info about the formals into this state. +void +CCState::AnalyzeFormalArguments(const SmallVectorImpl &Ins, + CCAssignFn Fn) { + unsigned NumArgs = Ins.size(); + + for (unsigned i = 0; i != NumArgs; ++i) { + MVT ArgVT = Ins[i].VT; + ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + dbgs() << "Formal argument #" << i << " has unhandled type " + << EVT(ArgVT).getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// CheckReturn - Analyze the return values of a function, returning true if +/// the return can be performed without sret-demotion, and false otherwise. +bool CCState::CheckReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + // Determine which register each value should be copied into. + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + MVT VT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) + return false; + } + return true; +} + +/// AnalyzeReturn - Analyze the returned values of a return, +/// incorporating info about the result values into this state. +void CCState::AnalyzeReturn(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + // Determine which register each value should be copied into. + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + MVT VT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + dbgs() << "Return operand #" << i << " has unhandled type " + << EVT(VT).getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallOperands - Analyze the outgoing arguments to a call, +/// incorporating info about the passed values into this state. +void CCState::AnalyzeCallOperands(const SmallVectorImpl &Outs, + CCAssignFn Fn) { + unsigned NumOps = Outs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + MVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + dbgs() << "Call operand #" << i << " has unhandled type " + << EVT(ArgVT).getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallOperands - Same as above except it takes vectors of types +/// and argument flags. +void CCState::AnalyzeCallOperands(SmallVectorImpl &ArgVTs, + SmallVectorImpl &Flags, + CCAssignFn Fn) { + unsigned NumOps = ArgVTs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + MVT ArgVT = ArgVTs[i]; + ISD::ArgFlagsTy ArgFlags = Flags[i]; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) { +#ifndef NDEBUG + dbgs() << "Call operand #" << i << " has unhandled type " + << EVT(ArgVT).getEVTString(); +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallResult - Analyze the return values of a call, +/// incorporating info about the passed values into this state. +void CCState::AnalyzeCallResult(const SmallVectorImpl &Ins, + CCAssignFn Fn) { + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + MVT VT = Ins[i].VT; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) { +#ifndef NDEBUG + dbgs() << "Call result #" << i << " has unhandled type " + << EVT(VT).getEVTString() << "\n"; +#endif + llvm_unreachable(0); + } + } +} + +/// AnalyzeCallResult - Same as above except it's specialized for calls which +/// produce a single value. +void CCState::AnalyzeCallResult(MVT VT, CCAssignFn Fn) { + if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) { +#ifndef NDEBUG + dbgs() << "Call result has unhandled type " + << EVT(VT).getEVTString(); +#endif + llvm_unreachable(0); + } +} diff --git a/final/lib/CodeGen/CodeGen.cpp b/final/lib/CodeGen/CodeGen.cpp new file mode 100644 index 00000000000..515e6f9fde8 --- /dev/null +++ b/final/lib/CodeGen/CodeGen.cpp @@ -0,0 +1,61 @@ +//===-- CodeGen.cpp -------------------------------------------------------===// +// +// 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 common initialization routines for the +// CodeGen library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/InitializePasses.h" +#include "llvm-c/Initialization.h" + +using namespace llvm; + +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. +void llvm::initializeCodeGen(PassRegistry &Registry) { + initializeCalculateSpillWeightsPass(Registry); + initializeDeadMachineInstructionElimPass(Registry); + initializeGCModuleInfoPass(Registry); + initializeIfConverterPass(Registry); + initializeLiveDebugVariablesPass(Registry); + initializeLiveIntervalsPass(Registry); + initializeLiveStacksPass(Registry); + initializeLiveVariablesPass(Registry); + initializeMachineCSEPass(Registry); + initializeMachineDominatorTreePass(Registry); + initializeMachineLICMPass(Registry); + initializeMachineLoopInfoPass(Registry); + initializeMachineModuleInfoPass(Registry); + initializeMachineSinkingPass(Registry); + initializeMachineVerifierPassPass(Registry); + initializeOptimizePHIsPass(Registry); + initializePHIEliminationPass(Registry); + initializePeepholeOptimizerPass(Registry); + initializePreAllocSplittingPass(Registry); + initializeProcessImplicitDefsPass(Registry); + initializePEIPass(Registry); + initializeRALinScanPass(Registry); + initializeRegisterCoalescerAnalysisGroup(Registry); + initializeRenderMachineFunctionPass(Registry); + initializeSimpleRegisterCoalescingPass(Registry); + initializeSlotIndexesPass(Registry); + initializeLoopSplitterPass(Registry); + initializeStackProtectorPass(Registry); + initializeStackSlotColoringPass(Registry); + initializeStrongPHIEliminationPass(Registry); + initializeTwoAddressInstructionPassPass(Registry); + initializeUnreachableBlockElimPass(Registry); + initializeUnreachableMachineBlockElimPass(Registry); + initializeVirtRegMapPass(Registry); + initializeLowerIntrinsicsPass(Registry); +} + +void LLVMInitializeCodeGen(LLVMPassRegistryRef R) { + initializeCodeGen(*unwrap(R)); +} diff --git a/final/lib/CodeGen/CodePlacementOpt.cpp b/final/lib/CodeGen/CodePlacementOpt.cpp new file mode 100644 index 00000000000..e37356a60cf --- /dev/null +++ b/final/lib/CodeGen/CodePlacementOpt.cpp @@ -0,0 +1,425 @@ +//===-- CodePlacementOpt.cpp - Code Placement pass. -----------------------===// +// +// 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 pass that optimizes code placement and aligns loop +// headers to target-specific alignment boundaries. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "code-placement" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumLoopsAligned, "Number of loops aligned"); +STATISTIC(NumIntraElim, "Number of intra loop branches eliminated"); +STATISTIC(NumIntraMoved, "Number of intra loop branches moved"); + +namespace { + class CodePlacementOpt : public MachineFunctionPass { + const MachineLoopInfo *MLI; + const TargetInstrInfo *TII; + const TargetLowering *TLI; + + public: + static char ID; + CodePlacementOpt() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { + return "Code Placement Optimizer"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + bool HasFallthrough(MachineBasicBlock *MBB); + bool HasAnalyzableTerminator(MachineBasicBlock *MBB); + void Splice(MachineFunction &MF, + MachineFunction::iterator InsertPt, + MachineFunction::iterator Begin, + MachineFunction::iterator End); + bool EliminateUnconditionalJumpsToTop(MachineFunction &MF, + MachineLoop *L); + bool MoveDiscontiguousLoopBlocks(MachineFunction &MF, + MachineLoop *L); + bool OptimizeIntraLoopEdgesInLoopNest(MachineFunction &MF, MachineLoop *L); + bool OptimizeIntraLoopEdges(MachineFunction &MF); + bool AlignLoops(MachineFunction &MF); + bool AlignLoop(MachineFunction &MF, MachineLoop *L, unsigned Align); + }; + + char CodePlacementOpt::ID = 0; +} // end anonymous namespace + +FunctionPass *llvm::createCodePlacementOptPass() { + return new CodePlacementOpt(); +} + +/// HasFallthrough - Test whether the given branch has a fallthrough, either as +/// a plain fallthrough or as a fallthrough case of a conditional branch. +/// +bool CodePlacementOpt::HasFallthrough(MachineBasicBlock *MBB) { + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) + return false; + // This conditional branch has no fallthrough. + if (FBB) + return false; + // An unconditional branch has no fallthrough. + if (Cond.empty() && TBB) + return false; + // It has a fallthrough. + return true; +} + +/// HasAnalyzableTerminator - Test whether AnalyzeBranch will succeed on MBB. +/// This is called before major changes are begun to test whether it will be +/// possible to complete the changes. +/// +/// Target-specific code is hereby encouraged to make AnalyzeBranch succeed +/// whenever possible. +/// +bool CodePlacementOpt::HasAnalyzableTerminator(MachineBasicBlock *MBB) { + // Conservatively ignore EH landing pads. + if (MBB->isLandingPad()) return false; + + // Aggressively handle return blocks and similar constructs. + if (MBB->succ_empty()) return true; + + // Ask the target's AnalyzeBranch if it can handle this block. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + // Make sure the terminator is understood. + if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) + return false; + // Ignore blocks which look like they might have EH-related control flow. + // AnalyzeBranch thinks it knows how to analyze such things, but it doesn't + // recognize the possibility of a control transfer through an unwind. + // Such blocks contain EH_LABEL instructions, however they may be in the + // middle of the block. Instead of searching for them, just check to see + // if the CFG disagrees with AnalyzeBranch. + if (1u + !Cond.empty() != MBB->succ_size()) + return false; + // Make sure we have the option of reversing the condition. + if (!Cond.empty() && TII->ReverseBranchCondition(Cond)) + return false; + return true; +} + +/// Splice - Move the sequence of instructions [Begin,End) to just before +/// InsertPt. Update branch instructions as needed to account for broken +/// fallthrough edges and to take advantage of newly exposed fallthrough +/// opportunities. +/// +void CodePlacementOpt::Splice(MachineFunction &MF, + MachineFunction::iterator InsertPt, + MachineFunction::iterator Begin, + MachineFunction::iterator End) { + assert(Begin != MF.begin() && End != MF.begin() && InsertPt != MF.begin() && + "Splice can't change the entry block!"); + MachineFunction::iterator OldBeginPrior = prior(Begin); + MachineFunction::iterator OldEndPrior = prior(End); + + MF.splice(InsertPt, Begin, End); + + prior(Begin)->updateTerminator(); + OldBeginPrior->updateTerminator(); + OldEndPrior->updateTerminator(); +} + +/// EliminateUnconditionalJumpsToTop - Move blocks which unconditionally jump +/// to the loop top to the top of the loop so that they have a fall through. +/// This can introduce a branch on entry to the loop, but it can eliminate a +/// branch within the loop. See the @simple case in +/// test/CodeGen/X86/loop_blocks.ll for an example of this. +bool CodePlacementOpt::EliminateUnconditionalJumpsToTop(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + MachineBasicBlock *TopMBB = L->getTopBlock(); + + bool BotHasFallthrough = HasFallthrough(L->getBottomBlock()); + + if (TopMBB == MF.begin() || + HasAnalyzableTerminator(prior(MachineFunction::iterator(TopMBB)))) { + new_top: + for (MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin(), + PE = TopMBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *Pred = *PI; + if (Pred == TopMBB) continue; + if (HasFallthrough(Pred)) continue; + if (!L->contains(Pred)) continue; + + // Verify that we can analyze all the loop entry edges before beginning + // any changes which will require us to be able to analyze them. + if (Pred == MF.begin()) + continue; + if (!HasAnalyzableTerminator(Pred)) + continue; + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(Pred)))) + continue; + + // Move the block. + DEBUG(dbgs() << "CGP: Moving blocks starting at BB#" << Pred->getNumber() + << " to top of loop.\n"); + Changed = true; + + // Move it and all the blocks that can reach it via fallthrough edges + // exclusively, to keep existing fallthrough edges intact. + MachineFunction::iterator Begin = Pred; + MachineFunction::iterator End = llvm::next(Begin); + while (Begin != MF.begin()) { + MachineFunction::iterator Prior = prior(Begin); + if (Prior == MF.begin()) + break; + // Stop when a non-fallthrough edge is found. + if (!HasFallthrough(Prior)) + break; + // Stop if a block which could fall-through out of the loop is found. + if (Prior->isSuccessor(End)) + break; + // If we've reached the top, stop scanning. + if (Prior == MachineFunction::iterator(TopMBB)) { + // We know top currently has a fall through (because we just checked + // it) which would be lost if we do the transformation, so it isn't + // worthwhile to do the transformation unless it would expose a new + // fallthrough edge. + if (!Prior->isSuccessor(End)) + goto next_pred; + // Otherwise we can stop scanning and procede to move the blocks. + break; + } + // If we hit a switch or something complicated, don't move anything + // for this predecessor. + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(Prior)))) + break; + // Ok, the block prior to Begin will be moved along with the rest. + // Extend the range to include it. + Begin = Prior; + ++NumIntraMoved; + } + + // Move the blocks. + Splice(MF, TopMBB, Begin, End); + + // Update TopMBB. + TopMBB = L->getTopBlock(); + + // We have a new loop top. Iterate on it. We shouldn't have to do this + // too many times if BranchFolding has done a reasonable job. + goto new_top; + next_pred:; + } + } + + // If the loop previously didn't exit with a fall-through and it now does, + // we eliminated a branch. + if (Changed && + !BotHasFallthrough && + HasFallthrough(L->getBottomBlock())) { + ++NumIntraElim; + } + + return Changed; +} + +/// MoveDiscontiguousLoopBlocks - Move any loop blocks that are not in the +/// portion of the loop contiguous with the header. This usually makes the loop +/// contiguous, provided that AnalyzeBranch can handle all the relevant +/// branching. See the @cfg_islands case in test/CodeGen/X86/loop_blocks.ll +/// for an example of this. +bool CodePlacementOpt::MoveDiscontiguousLoopBlocks(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + MachineBasicBlock *TopMBB = L->getTopBlock(); + MachineBasicBlock *BotMBB = L->getBottomBlock(); + + // Determine a position to move orphaned loop blocks to. If TopMBB is not + // entered via fallthrough and BotMBB is exited via fallthrough, prepend them + // to the top of the loop to avoid loosing that fallthrough. Otherwise append + // them to the bottom, even if it previously had a fallthrough, on the theory + // that it's worth an extra branch to keep the loop contiguous. + MachineFunction::iterator InsertPt = + llvm::next(MachineFunction::iterator(BotMBB)); + bool InsertAtTop = false; + if (TopMBB != MF.begin() && + !HasFallthrough(prior(MachineFunction::iterator(TopMBB))) && + HasFallthrough(BotMBB)) { + InsertPt = TopMBB; + InsertAtTop = true; + } + + // Keep a record of which blocks are in the portion of the loop contiguous + // with the loop header. + SmallPtrSet ContiguousBlocks; + for (MachineFunction::iterator I = TopMBB, + E = llvm::next(MachineFunction::iterator(BotMBB)); I != E; ++I) + ContiguousBlocks.insert(I); + + // Find non-contigous blocks and fix them. + if (InsertPt != MF.begin() && HasAnalyzableTerminator(prior(InsertPt))) + for (MachineLoop::block_iterator BI = L->block_begin(), BE = L->block_end(); + BI != BE; ++BI) { + MachineBasicBlock *BB = *BI; + + // Verify that we can analyze all the loop entry edges before beginning + // any changes which will require us to be able to analyze them. + if (!HasAnalyzableTerminator(BB)) + continue; + if (!HasAnalyzableTerminator(prior(MachineFunction::iterator(BB)))) + continue; + + // If the layout predecessor is part of the loop, this block will be + // processed along with it. This keeps them in their relative order. + if (BB != MF.begin() && + L->contains(prior(MachineFunction::iterator(BB)))) + continue; + + // Check to see if this block is already contiguous with the main + // portion of the loop. + if (!ContiguousBlocks.insert(BB)) + continue; + + // Move the block. + DEBUG(dbgs() << "CGP: Moving blocks starting at BB#" << BB->getNumber() + << " to be contiguous with loop.\n"); + Changed = true; + + // Process this block and all loop blocks contiguous with it, to keep + // them in their relative order. + MachineFunction::iterator Begin = BB; + MachineFunction::iterator End = llvm::next(MachineFunction::iterator(BB)); + for (; End != MF.end(); ++End) { + if (!L->contains(End)) break; + if (!HasAnalyzableTerminator(End)) break; + ContiguousBlocks.insert(End); + ++NumIntraMoved; + } + + // If we're inserting at the bottom of the loop, and the code we're + // moving originally had fall-through successors, bring the sucessors + // up with the loop blocks to preserve the fall-through edges. + if (!InsertAtTop) + for (; End != MF.end(); ++End) { + if (L->contains(End)) break; + if (!HasAnalyzableTerminator(End)) break; + if (!HasFallthrough(prior(End))) break; + } + + // Move the blocks. This may invalidate TopMBB and/or BotMBB, but + // we don't need them anymore at this point. + Splice(MF, InsertPt, Begin, End); + } + + return Changed; +} + +/// OptimizeIntraLoopEdgesInLoopNest - Reposition loop blocks to minimize +/// intra-loop branching and to form contiguous loops. +/// +/// This code takes the approach of making minor changes to the existing +/// layout to fix specific loop-oriented problems. Also, it depends on +/// AnalyzeBranch, which can't understand complex control instructions. +/// +bool CodePlacementOpt::OptimizeIntraLoopEdgesInLoopNest(MachineFunction &MF, + MachineLoop *L) { + bool Changed = false; + + // Do optimization for nested loops. + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) + Changed |= OptimizeIntraLoopEdgesInLoopNest(MF, *I); + + // Do optimization for this loop. + Changed |= EliminateUnconditionalJumpsToTop(MF, L); + Changed |= MoveDiscontiguousLoopBlocks(MF, L); + + return Changed; +} + +/// OptimizeIntraLoopEdges - Reposition loop blocks to minimize +/// intra-loop branching and to form contiguous loops. +/// +bool CodePlacementOpt::OptimizeIntraLoopEdges(MachineFunction &MF) { + bool Changed = false; + + if (!TLI->shouldOptimizeCodePlacement()) + return Changed; + + // Do optimization for each loop in the function. + for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); + I != E; ++I) + if (!(*I)->getParentLoop()) + Changed |= OptimizeIntraLoopEdgesInLoopNest(MF, *I); + + return Changed; +} + +/// AlignLoops - Align loop headers to target preferred alignments. +/// +bool CodePlacementOpt::AlignLoops(MachineFunction &MF) { + const Function *F = MF.getFunction(); + if (F->hasFnAttr(Attribute::OptimizeForSize)) + return false; + + unsigned Align = TLI->getPrefLoopAlignment(); + if (!Align) + return false; // Don't care about loop alignment. + + bool Changed = false; + + for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); + I != E; ++I) + Changed |= AlignLoop(MF, *I, Align); + + return Changed; +} + +/// AlignLoop - Align loop headers to target preferred alignments. +/// +bool CodePlacementOpt::AlignLoop(MachineFunction &MF, MachineLoop *L, + unsigned Align) { + bool Changed = false; + + // Do alignment for nested loops. + for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) + Changed |= AlignLoop(MF, *I, Align); + + L->getTopBlock()->setAlignment(Align); + Changed = true; + ++NumLoopsAligned; + + return Changed; +} + +bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) { + MLI = &getAnalysis(); + if (MLI->empty()) + return false; // No loops. + + TLI = MF.getTarget().getTargetLowering(); + TII = MF.getTarget().getInstrInfo(); + + bool Changed = OptimizeIntraLoopEdges(MF); + + Changed |= AlignLoops(MF); + + return Changed; +} diff --git a/final/lib/CodeGen/CriticalAntiDepBreaker.cpp b/final/lib/CodeGen/CriticalAntiDepBreaker.cpp new file mode 100644 index 00000000000..f79598de1d9 --- /dev/null +++ b/final/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -0,0 +1,668 @@ +//===----- CriticalAntiDepBreaker.cpp - Anti-dep breaker -------- ---------===// +// +// 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 CriticalAntiDepBreaker class, which +// implements register anti-dependence breaking along a blocks +// critical path during post-RA scheduler. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "CriticalAntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +CriticalAntiDepBreaker:: +CriticalAntiDepBreaker(MachineFunction& MFi) : + AntiDepBreaker(), MF(MFi), + MRI(MF.getRegInfo()), + TII(MF.getTarget().getInstrInfo()), + TRI(MF.getTarget().getRegisterInfo()), + AllocatableSet(TRI->getAllocatableSet(MF)), + Classes(TRI->getNumRegs(), static_cast(0)), + KillIndices(TRI->getNumRegs(), 0), + DefIndices(TRI->getNumRegs(), 0) {} + +CriticalAntiDepBreaker::~CriticalAntiDepBreaker() { +} + +void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { + const unsigned BBSize = BB->size(); + for (unsigned i = 0, e = TRI->getNumRegs(); i != e; ++i) { + // Clear out the register class data. + Classes[i] = static_cast(0); + + // Initialize the indices to indicate that no registers are live. + KillIndices[i] = ~0u; + DefIndices[i] = BBSize; + } + + // Clear "do not change" set. + KeepRegs.clear(); + + bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn()); + + // Determine the live-out physregs for this block. + if (IsReturnBlock) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + unsigned Reg = *I; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + } + + // In a non-return block, examine the live-in regs of all successors. + // Note a return block can have successors if the return instruction is + // predicated. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } + + // Mark live-out callee-saved registers. In a return block this is + // all callee-saved registers. In non-return this is any + // callee-saved register that is not saved in the prolog. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + BitVector Pristine = MFI->getPristineRegs(BB); + for (const unsigned *I = TRI->getCalleeSavedRegs(); *I; ++I) { + unsigned Reg = *I; + if (!IsReturnBlock && !Pristine.test(Reg)) continue; + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = BB->size(); + DefIndices[Reg] = ~0u; + + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + Classes[AliasReg] = reinterpret_cast(-1); + KillIndices[AliasReg] = BB->size(); + DefIndices[AliasReg] = ~0u; + } + } +} + +void CriticalAntiDepBreaker::FinishBlock() { + RegRefs.clear(); + KeepRegs.clear(); +} + +void CriticalAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, + unsigned InsertPosIndex) { + if (MI->isDebugValue()) + return; + assert(Count < InsertPosIndex && "Instruction index out of expected range!"); + + for (unsigned Reg = 0; Reg != TRI->getNumRegs(); ++Reg) { + if (KillIndices[Reg] != ~0u) { + // If Reg is currently live, then mark that it can't be renamed as + // we don't know the extent of its live-range anymore (now that it + // has been scheduled). + Classes[Reg] = reinterpret_cast(-1); + KillIndices[Reg] = Count; + } else if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) { + // Any register which was defined within the previous scheduling region + // may have been rescheduled and its lifetime may overlap with registers + // in ways not reflected in our current liveness state. For each such + // register, adjust the liveness state to be conservatively correct. + Classes[Reg] = reinterpret_cast(-1); + + // Move the def index to the end of the previous region, to reflect + // that the def could theoretically have been scheduled at the end. + DefIndices[Reg] = InsertPosIndex; + } + } + + PrescanInstruction(MI); + ScanInstruction(MI, Count); +} + +/// CriticalPathStep - Return the next SUnit after SU on the bottom-up +/// critical path. +static const SDep *CriticalPathStep(const SUnit *SU) { + const SDep *Next = 0; + unsigned NextDepth = 0; + // Find the predecessor edge with the greatest depth. + for (SUnit::const_pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end(); + P != PE; ++P) { + const SUnit *PredSU = P->getSUnit(); + unsigned PredLatency = P->getLatency(); + unsigned PredTotalLatency = PredSU->getDepth() + PredLatency; + // In the case of a latency tie, prefer an anti-dependency edge over + // other types of edges. + if (NextDepth < PredTotalLatency || + (NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) { + NextDepth = PredTotalLatency; + Next = &*P; + } + } + return Next; +} + +void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr *MI) { + // It's not safe to change register allocation for source operands of + // that have special allocation requirements. Also assume all registers + // used in a call must not be changed (ABI). + // FIXME: The issue with predicated instruction is more complex. We are being + // conservative here because the kill markers cannot be trusted after + // if-conversion: + // %R6 = LDR %SP, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14] + // ... + // STR %R0, %R6, %reg0, 0, pred:0, pred:%CPSR; mem:ST4[%395] + // %R6 = LDR %SP, %reg0, 100, pred:0, pred:%CPSR; mem:LD4[FixedStack12] + // STR %R0, %R6, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8) + // + // The first R6 kill is not really a kill since it's killed by a predicated + // instruction which may not be executed. The second R6 def may or may not + // re-define R6 so it's not safe to change it since the last R6 use cannot be + // changed. + bool Special = MI->getDesc().isCall() || + MI->getDesc().hasExtraSrcRegAllocReq() || + TII->isPredicated(MI); + + // Scan the register operands for this instruction and update + // Classes and RegRefs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + const TargetRegisterClass *NewRC = 0; + + if (i < MI->getDesc().getNumOperands()) + NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + + // For now, only allow the register to be changed if its register + // class is consistent across all uses. + if (!Classes[Reg] && NewRC) + Classes[Reg] = NewRC; + else if (!NewRC || Classes[Reg] != NewRC) + Classes[Reg] = reinterpret_cast(-1); + + // Now check for aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + // If an alias of the reg is used during the live range, give up. + // Note that this allows us to skip checking if AntiDepReg + // overlaps with any of the aliases, among other things. + unsigned AliasReg = *Alias; + if (Classes[AliasReg]) { + Classes[AliasReg] = reinterpret_cast(-1); + Classes[Reg] = reinterpret_cast(-1); + } + } + + // If we're still willing to consider this register, note the reference. + if (Classes[Reg] != reinterpret_cast(-1)) + RegRefs.insert(std::make_pair(Reg, &MO)); + + if (MO.isUse() && Special) { + if (KeepRegs.insert(Reg)) { + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) + KeepRegs.insert(*Subreg); + } + } + } +} + +void CriticalAntiDepBreaker::ScanInstruction(MachineInstr *MI, + unsigned Count) { + // Update liveness. + // Proceding upwards, registers that are defed but not used in this + // instruction are now dead. + + if (!TII->isPredicated(MI)) { + // Predicated defs are modeled as read + write, i.e. similar to two + // address updates. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isDef()) continue; + // Ignore two-addr defs. + if (MI->isRegTiedToUseOperand(i)) continue; + + DefIndices[Reg] = Count; + KillIndices[Reg] = ~0u; + assert(((KillIndices[Reg] == ~0u) != + (DefIndices[Reg] == ~0u)) && + "Kill and Def maps aren't consistent for Reg!"); + KeepRegs.erase(Reg); + Classes[Reg] = 0; + RegRefs.erase(Reg); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + unsigned SubregReg = *Subreg; + DefIndices[SubregReg] = Count; + KillIndices[SubregReg] = ~0u; + KeepRegs.erase(SubregReg); + Classes[SubregReg] = 0; + RegRefs.erase(SubregReg); + } + // Conservatively mark super-registers as unusable. + for (const unsigned *Super = TRI->getSuperRegisters(Reg); + *Super; ++Super) { + unsigned SuperReg = *Super; + Classes[SuperReg] = reinterpret_cast(-1); + } + } + } + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isUse()) continue; + + const TargetRegisterClass *NewRC = 0; + if (i < MI->getDesc().getNumOperands()) + NewRC = MI->getDesc().OpInfo[i].getRegClass(TRI); + + // For now, only allow the register to be changed if its register + // class is consistent across all uses. + if (!Classes[Reg] && NewRC) + Classes[Reg] = NewRC; + else if (!NewRC || Classes[Reg] != NewRC) + Classes[Reg] = reinterpret_cast(-1); + + RegRefs.insert(std::make_pair(Reg, &MO)); + + // It wasn't previously live but now it is, this is a kill. + if (KillIndices[Reg] == ~0u) { + KillIndices[Reg] = Count; + DefIndices[Reg] = ~0u; + assert(((KillIndices[Reg] == ~0u) != + (DefIndices[Reg] == ~0u)) && + "Kill and Def maps aren't consistent for Reg!"); + } + // Repeat, for all aliases. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (KillIndices[AliasReg] == ~0u) { + KillIndices[AliasReg] = Count; + DefIndices[AliasReg] = ~0u; + } + } + } +} + +// Check all machine operands that reference the antidependent register and must +// be replaced by NewReg. Return true if any of their parent instructions may +// clobber the new register. +// +// Note: AntiDepReg may be referenced by a two-address instruction such that +// it's use operand is tied to a def operand. We guard against the case in which +// the two-address instruction also defines NewReg, as may happen with +// pre/postincrement loads. In this case, both the use and def operands are in +// RegRefs because the def is inserted by PrescanInstruction and not erased +// during ScanInstruction. So checking for an instructions with definitions of +// both NewReg and AntiDepReg covers it. +bool +CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin, + RegRefIter RegRefEnd, + unsigned NewReg) +{ + for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) { + MachineOperand *RefOper = I->second; + + // Don't allow the instruction defining AntiDepReg to earlyclobber its + // operands, in case they may be assigned to NewReg. In this case antidep + // breaking must fail, but it's too rare to bother optimizing. + if (RefOper->isDef() && RefOper->isEarlyClobber()) + return true; + + // Handle cases in which this instructions defines NewReg. + MachineInstr *MI = RefOper->getParent(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &CheckOper = MI->getOperand(i); + + if (!CheckOper.isReg() || !CheckOper.isDef() || + CheckOper.getReg() != NewReg) + continue; + + // Don't allow the instruction to define NewReg and AntiDepReg. + // When AntiDepReg is renamed it will be an illegal op. + if (RefOper->isDef()) + return true; + + // Don't allow an instruction using AntiDepReg to be earlyclobbered by + // NewReg + if (CheckOper.isEarlyClobber()) + return true; + + // Don't allow inline asm to define NewReg at all. Who know what it's + // doing with it. + if (MI->isInlineAsm()) + return true; + } + } + return false; +} + +unsigned +CriticalAntiDepBreaker::findSuitableFreeRegister(RegRefIter RegRefBegin, + RegRefIter RegRefEnd, + unsigned AntiDepReg, + unsigned LastNewReg, + const TargetRegisterClass *RC) +{ + for (TargetRegisterClass::iterator R = RC->allocation_order_begin(MF), + RE = RC->allocation_order_end(MF); R != RE; ++R) { + unsigned NewReg = *R; + // Don't consider non-allocatable registers + if (!AllocatableSet.test(NewReg)) continue; + // Don't replace a register with itself. + if (NewReg == AntiDepReg) continue; + // Don't replace a register with one that was recently used to repair + // an anti-dependence with this AntiDepReg, because that would + // re-introduce that anti-dependence. + if (NewReg == LastNewReg) continue; + // If any instructions that define AntiDepReg also define the NewReg, it's + // not suitable. For example, Instruction with multiple definitions can + // result in this condition. + if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue; + // If NewReg is dead and NewReg's most recent def is not before + // AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg. + assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u)) + && "Kill and Def maps aren't consistent for AntiDepReg!"); + assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u)) + && "Kill and Def maps aren't consistent for NewReg!"); + if (KillIndices[NewReg] != ~0u || + Classes[NewReg] == reinterpret_cast(-1) || + KillIndices[AntiDepReg] > DefIndices[NewReg]) + continue; + return NewReg; + } + + // No registers are free and available! + return 0; +} + +unsigned CriticalAntiDepBreaker:: +BreakAntiDependencies(const std::vector& SUnits, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned InsertPosIndex) { + // The code below assumes that there is at least one instruction, + // so just duck out immediately if the block is empty. + if (SUnits.empty()) return 0; + + // Keep a map of the MachineInstr*'s back to the SUnit representing them. + // This is used for updating debug information. + DenseMap MISUnitMap; + + // Find the node at the bottom of the critical path. + const SUnit *Max = 0; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + const SUnit *SU = &SUnits[i]; + MISUnitMap[SU->getInstr()] = SU; + if (!Max || SU->getDepth() + SU->Latency > Max->getDepth() + Max->Latency) + Max = SU; + } + +#ifndef NDEBUG + { + DEBUG(dbgs() << "Critical path has total latency " + << (Max->getDepth() + Max->Latency) << "\n"); + DEBUG(dbgs() << "Available regs:"); + for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { + if (KillIndices[Reg] == ~0u) + DEBUG(dbgs() << " " << TRI->getName(Reg)); + } + DEBUG(dbgs() << '\n'); + } +#endif + + // Track progress along the critical path through the SUnit graph as we walk + // the instructions. + const SUnit *CriticalPathSU = Max; + MachineInstr *CriticalPathMI = CriticalPathSU->getInstr(); + + // Consider this pattern: + // A = ... + // ... = A + // A = ... + // ... = A + // A = ... + // ... = A + // A = ... + // ... = A + // There are three anti-dependencies here, and without special care, + // we'd break all of them using the same register: + // A = ... + // ... = A + // B = ... + // ... = B + // B = ... + // ... = B + // B = ... + // ... = B + // because at each anti-dependence, B is the first register that + // isn't A which is free. This re-introduces anti-dependencies + // at all but one of the original anti-dependencies that we were + // trying to break. To avoid this, keep track of the most recent + // register that each register was replaced with, avoid + // using it to repair an anti-dependence on the same register. + // This lets us produce this: + // A = ... + // ... = A + // B = ... + // ... = B + // C = ... + // ... = C + // B = ... + // ... = B + // This still has an anti-dependence on B, but at least it isn't on the + // original critical path. + // + // TODO: If we tracked more than one register here, we could potentially + // fix that remaining critical edge too. This is a little more involved, + // because unlike the most recent register, less recent registers should + // still be considered, though only if no other registers are available. + std::vector LastNewReg(TRI->getNumRegs(), 0); + + // Attempt to break anti-dependence edges on the critical path. Walk the + // instructions from the bottom up, tracking information about liveness + // as we go to help determine which registers are available. + unsigned Broken = 0; + unsigned Count = InsertPosIndex - 1; + for (MachineBasicBlock::iterator I = End, E = Begin; + I != E; --Count) { + MachineInstr *MI = --I; + if (MI->isDebugValue()) + continue; + + // Check if this instruction has a dependence on the critical path that + // is an anti-dependence that we may be able to break. If it is, set + // AntiDepReg to the non-zero register associated with the anti-dependence. + // + // We limit our attention to the critical path as a heuristic to avoid + // breaking anti-dependence edges that aren't going to significantly + // impact the overall schedule. There are a limited number of registers + // and we want to save them for the important edges. + // + // TODO: Instructions with multiple defs could have multiple + // anti-dependencies. The current code here only knows how to break one + // edge per instruction. Note that we'd have to be able to break all of + // the anti-dependencies in an instruction in order to be effective. + unsigned AntiDepReg = 0; + if (MI == CriticalPathMI) { + if (const SDep *Edge = CriticalPathStep(CriticalPathSU)) { + const SUnit *NextSU = Edge->getSUnit(); + + // Only consider anti-dependence edges. + if (Edge->getKind() == SDep::Anti) { + AntiDepReg = Edge->getReg(); + assert(AntiDepReg != 0 && "Anti-dependence on reg0?"); + if (!AllocatableSet.test(AntiDepReg)) + // Don't break anti-dependencies on non-allocatable registers. + AntiDepReg = 0; + else if (KeepRegs.count(AntiDepReg)) + // Don't break anti-dependencies if an use down below requires + // this exact register. + AntiDepReg = 0; + else { + // If the SUnit has other dependencies on the SUnit that it + // anti-depends on, don't bother breaking the anti-dependency + // since those edges would prevent such units from being + // scheduled past each other regardless. + // + // Also, if there are dependencies on other SUnits with the + // same register as the anti-dependency, don't attempt to + // break it. + for (SUnit::const_pred_iterator P = CriticalPathSU->Preds.begin(), + PE = CriticalPathSU->Preds.end(); P != PE; ++P) + if (P->getSUnit() == NextSU ? + (P->getKind() != SDep::Anti || P->getReg() != AntiDepReg) : + (P->getKind() == SDep::Data && P->getReg() == AntiDepReg)) { + AntiDepReg = 0; + break; + } + } + } + CriticalPathSU = NextSU; + CriticalPathMI = CriticalPathSU->getInstr(); + } else { + // We've reached the end of the critical path. + CriticalPathSU = 0; + CriticalPathMI = 0; + } + } + + PrescanInstruction(MI); + + // If MI's defs have a special allocation requirement, don't allow + // any def registers to be changed. Also assume all registers + // defined in a call must not be changed (ABI). + if (MI->getDesc().isCall() || MI->getDesc().hasExtraDefRegAllocReq() || + TII->isPredicated(MI)) + // If this instruction's defs have special allocation requirement, don't + // break this anti-dependency. + AntiDepReg = 0; + else if (AntiDepReg) { + // If this instruction has a use of AntiDepReg, breaking it + // is invalid. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (MO.isUse() && TRI->regsOverlap(AntiDepReg, Reg)) { + AntiDepReg = 0; + break; + } + } + } + + // Determine AntiDepReg's register class, if it is live and is + // consistently used within a single class. + const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg] : 0; + assert((AntiDepReg == 0 || RC != NULL) && + "Register should be live if it's causing an anti-dependence!"); + if (RC == reinterpret_cast(-1)) + AntiDepReg = 0; + + // Look for a suitable register to use to break the anti-depenence. + // + // TODO: Instead of picking the first free register, consider which might + // be the best. + if (AntiDepReg != 0) { + std::pair::iterator, + std::multimap::iterator> + Range = RegRefs.equal_range(AntiDepReg); + if (unsigned NewReg = findSuitableFreeRegister(Range.first, Range.second, + AntiDepReg, + LastNewReg[AntiDepReg], + RC)) { + DEBUG(dbgs() << "Breaking anti-dependence edge on " + << TRI->getName(AntiDepReg) + << " with " << RegRefs.count(AntiDepReg) << " references" + << " using " << TRI->getName(NewReg) << "!\n"); + + // Update the references to the old register to refer to the new + // register. + for (std::multimap::iterator + Q = Range.first, QE = Range.second; Q != QE; ++Q) { + Q->second->setReg(NewReg); + // If the SU for the instruction being updated has debug information + // related to the anti-dependency register, make sure to update that + // as well. + const SUnit *SU = MISUnitMap[Q->second->getParent()]; + if (!SU) continue; + for (unsigned i = 0, e = SU->DbgInstrList.size() ; i < e ; ++i) { + MachineInstr *DI = SU->DbgInstrList[i]; + assert (DI->getNumOperands()==3 && DI->getOperand(0).isReg() && + DI->getOperand(0).getReg() + && "Non register dbg_value attached to SUnit!"); + if (DI->getOperand(0).getReg() == AntiDepReg) + DI->getOperand(0).setReg(NewReg); + } + } + + // We just went back in time and modified history; the + // liveness information for the anti-dependence reg is now + // inconsistent. Set the state as if it were dead. + Classes[NewReg] = Classes[AntiDepReg]; + DefIndices[NewReg] = DefIndices[AntiDepReg]; + KillIndices[NewReg] = KillIndices[AntiDepReg]; + assert(((KillIndices[NewReg] == ~0u) != + (DefIndices[NewReg] == ~0u)) && + "Kill and Def maps aren't consistent for NewReg!"); + + Classes[AntiDepReg] = 0; + DefIndices[AntiDepReg] = KillIndices[AntiDepReg]; + KillIndices[AntiDepReg] = ~0u; + assert(((KillIndices[AntiDepReg] == ~0u) != + (DefIndices[AntiDepReg] == ~0u)) && + "Kill and Def maps aren't consistent for AntiDepReg!"); + + RegRefs.erase(AntiDepReg); + LastNewReg[AntiDepReg] = NewReg; + ++Broken; + } + } + + ScanInstruction(MI, Count); + } + + return Broken; +} diff --git a/final/lib/CodeGen/CriticalAntiDepBreaker.h b/final/lib/CodeGen/CriticalAntiDepBreaker.h new file mode 100644 index 00000000000..0daaef27344 --- /dev/null +++ b/final/lib/CodeGen/CriticalAntiDepBreaker.h @@ -0,0 +1,106 @@ +//=- llvm/CodeGen/CriticalAntiDepBreaker.h - Anti-Dep Support -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CriticalAntiDepBreaker class, which +// implements register anti-dependence breaking along a blocks +// critical path during post-RA scheduler. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H +#define LLVM_CODEGEN_CRITICALANTIDEPBREAKER_H + +#include "AntiDepBreaker.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { +class TargetInstrInfo; +class TargetRegisterInfo; + + class CriticalAntiDepBreaker : public AntiDepBreaker { + MachineFunction& MF; + MachineRegisterInfo &MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + + /// AllocatableSet - The set of allocatable registers. + /// We'll be ignoring anti-dependencies on non-allocatable registers, + /// because they may not be safe to break. + const BitVector AllocatableSet; + + /// Classes - For live regs that are only used in one register class in a + /// live range, the register class. If the register is not live, the + /// corresponding value is null. If the register is live but used in + /// multiple register classes, the corresponding value is -1 casted to a + /// pointer. + std::vector Classes; + + /// RegRefs - Map registers to all their references within a live range. + std::multimap RegRefs; + typedef std::multimap::const_iterator + RegRefIter; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + std::vector KillIndices; + + /// DefIndices - The index of the most recent complete def (proceding bottom + /// up), or ~0u if the register is live. + std::vector DefIndices; + + /// KeepRegs - A set of registers which are live and cannot be changed to + /// break anti-dependencies. + SmallSet KeepRegs; + + public: + CriticalAntiDepBreaker(MachineFunction& MFi); + ~CriticalAntiDepBreaker(); + + /// Start - Initialize anti-dep breaking for a new basic block. + void StartBlock(MachineBasicBlock *BB); + + /// BreakAntiDependencies - Identifiy anti-dependencies along the critical + /// path + /// of the ScheduleDAG and break them by renaming registers. + /// + unsigned BreakAntiDependencies(const std::vector& SUnits, + MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned InsertPosIndex); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex); + + /// Finish - Finish anti-dep breaking for a basic block. + void FinishBlock(); + + private: + void PrescanInstruction(MachineInstr *MI); + void ScanInstruction(MachineInstr *MI, unsigned Count); + bool isNewRegClobberedByRefs(RegRefIter RegRefBegin, + RegRefIter RegRefEnd, + unsigned NewReg); + unsigned findSuitableFreeRegister(RegRefIter RegRefBegin, + RegRefIter RegRefEnd, + unsigned AntiDepReg, + unsigned LastNewReg, + const TargetRegisterClass *RC); + }; +} + +#endif diff --git a/final/lib/CodeGen/DeadMachineInstructionElim.cpp b/final/lib/CodeGen/DeadMachineInstructionElim.cpp new file mode 100644 index 00000000000..fdc1d914214 --- /dev/null +++ b/final/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -0,0 +1,196 @@ +//===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an extremely simple MachineInstr-level dead-code-elimination pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "codegen-dce" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumDeletes, "Number of dead instructions deleted"); + +namespace { + class DeadMachineInstructionElim : public MachineFunctionPass { + virtual bool runOnMachineFunction(MachineFunction &MF); + + const TargetRegisterInfo *TRI; + const MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + BitVector LivePhysRegs; + + public: + static char ID; // Pass identification, replacement for typeid + DeadMachineInstructionElim() : MachineFunctionPass(ID) { + initializeDeadMachineInstructionElimPass(*PassRegistry::getPassRegistry()); + } + + private: + bool isDead(const MachineInstr *MI) const; + }; +} +char DeadMachineInstructionElim::ID = 0; + +INITIALIZE_PASS(DeadMachineInstructionElim, "dead-mi-elimination", + "Remove dead machine instructions", false, false) + +FunctionPass *llvm::createDeadMachineInstructionElimPass() { + return new DeadMachineInstructionElim(); +} + +bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { + // Technically speaking inline asm without side effects and no defs can still + // be deleted. But there is so much bad inline asm code out there, we should + // let them be. + if (MI->isInlineAsm()) + return false; + + // Don't delete instructions with side effects. + bool SawStore = false; + if (!MI->isSafeToMove(TII, 0, SawStore) && !MI->isPHI()) + return false; + + // Examine each operand. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg) ? + LivePhysRegs[Reg] : !MRI->use_nodbg_empty(Reg)) { + // This def has a non-debug use. Don't delete the instruction! + return false; + } + } + } + + // If there are no defs with uses, the instruction is dead. + return true; +} + +bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) { + bool AnyChanges = false; + MRI = &MF.getRegInfo(); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + + // Treat reserved registers as always live. + BitVector ReservedRegs = TRI->getReservedRegs(MF); + + // Loop over all instructions in all blocks, from bottom to top, so that it's + // more likely that chains of dependent but ultimately dead instructions will + // be cleaned up. + for (MachineFunction::reverse_iterator I = MF.rbegin(), E = MF.rend(); + I != E; ++I) { + MachineBasicBlock *MBB = &*I; + + // Start out assuming that reserved registers are live out of this block. + LivePhysRegs = ReservedRegs; + + // Also add any explicit live-out physregs for this block. + if (!MBB->empty() && MBB->back().getDesc().isReturn()) + for (MachineRegisterInfo::liveout_iterator LOI = MRI->liveout_begin(), + LOE = MRI->liveout_end(); LOI != LOE; ++LOI) { + unsigned Reg = *LOI; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + LivePhysRegs.set(Reg); + } + + // FIXME: Add live-ins from sucessors to LivePhysRegs. Normally, physregs + // are not live across blocks, but some targets (x86) can have flags live + // out of a block. + + // Now scan the instructions and delete dead ones, tracking physreg + // liveness as we go. + for (MachineBasicBlock::reverse_iterator MII = MBB->rbegin(), + MIE = MBB->rend(); MII != MIE; ) { + MachineInstr *MI = &*MII; + + // If the instruction is dead, delete it! + if (isDead(MI)) { + DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI); + // It is possible that some DBG_VALUE instructions refer to this + // instruction. Examine each def operand for such references; + // if found, mark the DBG_VALUE as undef (but don't delete it). + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + MachineRegisterInfo::use_iterator nextI; + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg), + E = MRI->use_end(); I!=E; I=nextI) { + nextI = llvm::next(I); // I is invalidated by the setReg + MachineOperand& Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + if (UseMI==MI) + continue; + assert(Use.isDebug()); + UseMI->getOperand(0).setReg(0U); + } + } + AnyChanges = true; + MI->eraseFromParent(); + ++NumDeletes; + MIE = MBB->rend(); + // MII is now pointing to the next instruction to process, + // so don't increment it. + continue; + } + + // Record the physreg defs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + LivePhysRegs.reset(Reg); + // Check the subreg set, not the alias set, because a def + // of a super-register may still be partially live after + // this def. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + *SubRegs; ++SubRegs) + LivePhysRegs.reset(*SubRegs); + } + } + } + // Record the physreg uses, after the defs, in case a physreg is + // both defined and used in the same instruction. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse()) { + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + LivePhysRegs.set(Reg); + for (const unsigned *AliasSet = TRI->getAliasSet(Reg); + *AliasSet; ++AliasSet) + LivePhysRegs.set(*AliasSet); + } + } + } + + // We didn't delete the current instruction, so increment MII to + // the next one. + ++MII; + } + } + + LivePhysRegs.clear(); + return AnyChanges; +} diff --git a/final/lib/CodeGen/DwarfEHPrepare.cpp b/final/lib/CodeGen/DwarfEHPrepare.cpp new file mode 100644 index 00000000000..0ebb5b0db70 --- /dev/null +++ b/final/lib/CodeGen/DwarfEHPrepare.cpp @@ -0,0 +1,670 @@ +//===-- DwarfEHPrepare - Prepare exception handling for code generation ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass mulches exception handling code into a form adapted to code +// generation. Required if using dwarf exception handling. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dwarfehprepare" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/SSAUpdater.h" +using namespace llvm; + +STATISTIC(NumLandingPadsSplit, "Number of landing pads split"); +STATISTIC(NumUnwindsLowered, "Number of unwind instructions lowered"); +STATISTIC(NumExceptionValuesMoved, "Number of eh.exception calls moved"); + +namespace { + class DwarfEHPrepare : public FunctionPass { + const TargetMachine *TM; + const TargetLowering *TLI; + + // The eh.exception intrinsic. + Function *ExceptionValueIntrinsic; + + // The eh.selector intrinsic. + Function *SelectorIntrinsic; + + // _Unwind_Resume_or_Rethrow or _Unwind_SjLj_Resume call. + Constant *URoR; + + // The EH language-specific catch-all type. + GlobalVariable *EHCatchAllValue; + + // _Unwind_Resume or the target equivalent. + Constant *RewindFunction; + + // We both use and preserve dominator info. + DominatorTree *DT; + + // The function we are running on. + Function *F; + + // The landing pads for this function. + typedef SmallPtrSet BBSet; + BBSet LandingPads; + + bool NormalizeLandingPads(); + bool LowerUnwinds(); + bool MoveExceptionValueCalls(); + + Instruction *CreateExceptionValueCall(BasicBlock *BB); + + /// CleanupSelectors - Any remaining eh.selector intrinsic calls which still + /// use the "llvm.eh.catch.all.value" call need to convert to using its + /// initializer instead. + bool CleanupSelectors(SmallPtrSet &Sels); + + bool HasCatchAllInSelector(IntrinsicInst *); + + /// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups. + void FindAllCleanupSelectors(SmallPtrSet &Sels, + SmallPtrSet &CatchAllSels); + + /// FindAllURoRInvokes - Find all URoR invokes in the function. + void FindAllURoRInvokes(SmallPtrSet &URoRInvokes); + + /// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow" or + /// "_Unwind_SjLj_Resume" calls. The "unwind" part of these invokes jump to + /// a landing pad within the current function. This is a candidate to merge + /// the selector associated with the URoR invoke with the one from the + /// URoR's landing pad. + bool HandleURoRInvokes(); + + /// FindSelectorAndURoR - Find the eh.selector call and URoR call associated + /// with the eh.exception call. This recursively looks past instructions + /// which don't change the EH pointer value, like casts or PHI nodes. + bool FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, + SmallPtrSet &SelCalls); + + public: + static char ID; // Pass identification, replacement for typeid. + DwarfEHPrepare(const TargetMachine *tm) : + FunctionPass(ID), TM(tm), TLI(TM->getTargetLowering()), + ExceptionValueIntrinsic(0), SelectorIntrinsic(0), + URoR(0), EHCatchAllValue(0), RewindFunction(0) { + initializeDominatorTreePass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnFunction(Function &Fn); + + // getAnalysisUsage - We need the dominator tree for handling URoR. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); + } + + const char *getPassName() const { + return "Exception handling preparation"; + } + + }; +} // end anonymous namespace + +char DwarfEHPrepare::ID = 0; + +FunctionPass *llvm::createDwarfEHPass(const TargetMachine *tm) { + return new DwarfEHPrepare(tm); +} + +/// HasCatchAllInSelector - Return true if the intrinsic instruction has a +/// catch-all. +bool DwarfEHPrepare::HasCatchAllInSelector(IntrinsicInst *II) { + if (!EHCatchAllValue) return false; + + unsigned ArgIdx = II->getNumArgOperands() - 1; + GlobalVariable *GV = dyn_cast(II->getArgOperand(ArgIdx)); + return GV == EHCatchAllValue; +} + +/// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups. +void DwarfEHPrepare:: +FindAllCleanupSelectors(SmallPtrSet &Sels, + SmallPtrSet &CatchAllSels) { + for (Value::use_iterator + I = SelectorIntrinsic->use_begin(), + E = SelectorIntrinsic->use_end(); I != E; ++I) { + IntrinsicInst *II = cast(*I); + + if (II->getParent()->getParent() != F) + continue; + + if (!HasCatchAllInSelector(II)) + Sels.insert(II); + else + CatchAllSels.insert(II); + } +} + +/// FindAllURoRInvokes - Find all URoR invokes in the function. +void DwarfEHPrepare:: +FindAllURoRInvokes(SmallPtrSet &URoRInvokes) { + for (Value::use_iterator + I = URoR->use_begin(), + E = URoR->use_end(); I != E; ++I) { + if (InvokeInst *II = dyn_cast(*I)) + URoRInvokes.insert(II); + } +} + +/// CleanupSelectors - Any remaining eh.selector intrinsic calls which still use +/// the "llvm.eh.catch.all.value" call need to convert to using its +/// initializer instead. +bool DwarfEHPrepare::CleanupSelectors(SmallPtrSet &Sels) { + if (!EHCatchAllValue) return false; + + if (!SelectorIntrinsic) { + SelectorIntrinsic = + Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector); + if (!SelectorIntrinsic) return false; + } + + bool Changed = false; + for (SmallPtrSet::iterator + I = Sels.begin(), E = Sels.end(); I != E; ++I) { + IntrinsicInst *Sel = *I; + + // Index of the "llvm.eh.catch.all.value" variable. + unsigned OpIdx = Sel->getNumArgOperands() - 1; + GlobalVariable *GV = dyn_cast(Sel->getArgOperand(OpIdx)); + if (GV != EHCatchAllValue) continue; + Sel->setArgOperand(OpIdx, EHCatchAllValue->getInitializer()); + Changed = true; + } + + return Changed; +} + +/// FindSelectorAndURoR - Find the eh.selector call associated with the +/// eh.exception call. And indicate if there is a URoR "invoke" associated with +/// the eh.exception call. This recursively looks past instructions which don't +/// change the EH pointer value, like casts or PHI nodes. +bool +DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, + SmallPtrSet &SelCalls) { + SmallPtrSet SeenPHIs; + bool Changed = false; + + for (Value::use_iterator + I = Inst->use_begin(), E = Inst->use_end(); I != E; ++I) { + Instruction *II = dyn_cast(*I); + if (!II || II->getParent()->getParent() != F) continue; + + if (IntrinsicInst *Sel = dyn_cast(II)) { + if (Sel->getIntrinsicID() == Intrinsic::eh_selector) + SelCalls.insert(Sel); + } else if (InvokeInst *Invoke = dyn_cast(II)) { + if (Invoke->getCalledFunction() == URoR) + URoRInvoke = true; + } else if (CastInst *CI = dyn_cast(II)) { + Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls); + } else if (PHINode *PN = dyn_cast(II)) { + if (SeenPHIs.insert(PN)) + // Don't process a PHI node more than once. + Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls); + } + } + + return Changed; +} + +/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow" or +/// "_Unwind_SjLj_Resume" calls. The "unwind" part of these invokes jump to a +/// landing pad within the current function. This is a candidate to merge the +/// selector associated with the URoR invoke with the one from the URoR's +/// landing pad. +bool DwarfEHPrepare::HandleURoRInvokes() { + if (!EHCatchAllValue) { + EHCatchAllValue = + F->getParent()->getNamedGlobal("llvm.eh.catch.all.value"); + if (!EHCatchAllValue) return false; + } + + if (!SelectorIntrinsic) { + SelectorIntrinsic = + Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector); + if (!SelectorIntrinsic) return false; + } + + SmallPtrSet Sels; + SmallPtrSet CatchAllSels; + FindAllCleanupSelectors(Sels, CatchAllSels); + + if (!URoR) { + URoR = F->getParent()->getFunction("_Unwind_Resume_or_Rethrow"); + if (!URoR) { + URoR = F->getParent()->getFunction("_Unwind_SjLj_Resume"); + if (!URoR) return CleanupSelectors(CatchAllSels); + } + } + + SmallPtrSet URoRInvokes; + FindAllURoRInvokes(URoRInvokes); + + SmallPtrSet SelsToConvert; + + for (SmallPtrSet::iterator + SI = Sels.begin(), SE = Sels.end(); SI != SE; ++SI) { + const BasicBlock *SelBB = (*SI)->getParent(); + for (SmallPtrSet::iterator + UI = URoRInvokes.begin(), UE = URoRInvokes.end(); UI != UE; ++UI) { + const BasicBlock *URoRBB = (*UI)->getParent(); + if (DT->dominates(SelBB, URoRBB)) { + SelsToConvert.insert(*SI); + break; + } + } + } + + bool Changed = false; + + if (Sels.size() != SelsToConvert.size()) { + // If we haven't been able to convert all of the clean-up selectors, then + // loop through the slow way to see if they still need to be converted. + if (!ExceptionValueIntrinsic) { + ExceptionValueIntrinsic = + Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception); + if (!ExceptionValueIntrinsic) + return CleanupSelectors(CatchAllSels); + } + + for (Value::use_iterator + I = ExceptionValueIntrinsic->use_begin(), + E = ExceptionValueIntrinsic->use_end(); I != E; ++I) { + IntrinsicInst *EHPtr = dyn_cast(*I); + if (!EHPtr || EHPtr->getParent()->getParent() != F) continue; + + bool URoRInvoke = false; + SmallPtrSet SelCalls; + Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls); + + if (URoRInvoke) { + // This EH pointer is being used by an invoke of an URoR instruction and + // an eh.selector intrinsic call. If the eh.selector is a 'clean-up', we + // need to convert it to a 'catch-all'. + for (SmallPtrSet::iterator + SI = SelCalls.begin(), SE = SelCalls.end(); SI != SE; ++SI) + if (!HasCatchAllInSelector(*SI)) + SelsToConvert.insert(*SI); + } + } + } + + if (!SelsToConvert.empty()) { + // Convert all clean-up eh.selectors, which are associated with "invokes" of + // URoR calls, into catch-all eh.selectors. + Changed = true; + + for (SmallPtrSet::iterator + SI = SelsToConvert.begin(), SE = SelsToConvert.end(); + SI != SE; ++SI) { + IntrinsicInst *II = *SI; + + // Use the exception object pointer and the personality function + // from the original selector. + CallSite CS(II); + IntrinsicInst::op_iterator I = CS.arg_begin(); + IntrinsicInst::op_iterator E = CS.arg_end(); + IntrinsicInst::op_iterator B = prior(E); + + // Exclude last argument if it is an integer. + if (isa(B)) E = B; + + // Add exception object pointer (front). + // Add personality function (next). + // Add in any filter IDs (rest). + SmallVector Args(I, E); + + Args.push_back(EHCatchAllValue->getInitializer()); // Catch-all indicator. + + CallInst *NewSelector = + CallInst::Create(SelectorIntrinsic, Args.begin(), Args.end(), + "eh.sel.catch.all", II); + + NewSelector->setTailCall(II->isTailCall()); + NewSelector->setAttributes(II->getAttributes()); + NewSelector->setCallingConv(II->getCallingConv()); + + II->replaceAllUsesWith(NewSelector); + II->eraseFromParent(); + } + } + + Changed |= CleanupSelectors(CatchAllSels); + return Changed; +} + +/// NormalizeLandingPads - Normalize and discover landing pads, noting them +/// in the LandingPads set. A landing pad is normal if the only CFG edges +/// that end at it are unwind edges from invoke instructions. If we inlined +/// through an invoke we could have a normal branch from the previous +/// unwind block through to the landing pad for the original invoke. +/// Abnormal landing pads are fixed up by redirecting all unwind edges to +/// a new basic block which falls through to the original. +bool DwarfEHPrepare::NormalizeLandingPads() { + bool Changed = false; + + const MCAsmInfo *MAI = TM->getMCAsmInfo(); + bool usingSjLjEH = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (!isa(TI)) + continue; + BasicBlock *LPad = TI->getSuccessor(1); + // Skip landing pads that have already been normalized. + if (LandingPads.count(LPad)) + continue; + + // Check that only invoke unwind edges end at the landing pad. + bool OnlyUnwoundTo = true; + bool SwitchOK = usingSjLjEH; + for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); + PI != PE; ++PI) { + TerminatorInst *PT = (*PI)->getTerminator(); + // The SjLj dispatch block uses a switch instruction. This is effectively + // an unwind edge, so we can disregard it here. There will only ever + // be one dispatch, however, so if there are multiple switches, one + // of them truly is a normal edge, not an unwind edge. + if (SwitchOK && isa(PT)) { + SwitchOK = false; + continue; + } + if (!isa(PT) || LPad == PT->getSuccessor(0)) { + OnlyUnwoundTo = false; + break; + } + } + + if (OnlyUnwoundTo) { + // Only unwind edges lead to the landing pad. Remember the landing pad. + LandingPads.insert(LPad); + continue; + } + + // At least one normal edge ends at the landing pad. Redirect the unwind + // edges to a new basic block which falls through into this one. + + // Create the new basic block. + BasicBlock *NewBB = BasicBlock::Create(F->getContext(), + LPad->getName() + "_unwind_edge"); + + // Insert it into the function right before the original landing pad. + LPad->getParent()->getBasicBlockList().insert(LPad, NewBB); + + // Redirect unwind edges from the original landing pad to NewBB. + for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ) { + TerminatorInst *PT = (*PI++)->getTerminator(); + if (isa(PT) && PT->getSuccessor(1) == LPad) + // Unwind to the new block. + PT->setSuccessor(1, NewBB); + } + + // If there are any PHI nodes in LPad, we need to update them so that they + // merge incoming values from NewBB instead. + for (BasicBlock::iterator II = LPad->begin(); isa(II); ++II) { + PHINode *PN = cast(II); + pred_iterator PB = pred_begin(NewBB), PE = pred_end(NewBB); + + // Check to see if all of the values coming in via unwind edges are the + // same. If so, we don't need to create a new PHI node. + Value *InVal = PN->getIncomingValueForBlock(*PB); + for (pred_iterator PI = PB; PI != PE; ++PI) { + if (PI != PB && InVal != PN->getIncomingValueForBlock(*PI)) { + InVal = 0; + break; + } + } + + if (InVal == 0) { + // Different unwind edges have different values. Create a new PHI node + // in NewBB. + PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()+".unwind", + NewBB); + // Add an entry for each unwind edge, using the value from the old PHI. + for (pred_iterator PI = PB; PI != PE; ++PI) + NewPN->addIncoming(PN->getIncomingValueForBlock(*PI), *PI); + + // Now use this new PHI as the common incoming value for NewBB in PN. + InVal = NewPN; + } + + // Revector exactly one entry in the PHI node to come from NewBB + // and delete all other entries that come from unwind edges. If + // there are both normal and unwind edges from the same predecessor, + // this leaves an entry for the normal edge. + for (pred_iterator PI = PB; PI != PE; ++PI) + PN->removeIncomingValue(*PI); + PN->addIncoming(InVal, NewBB); + } + + // Add a fallthrough from NewBB to the original landing pad. + BranchInst::Create(LPad, NewBB); + + // Now update DominatorTree analysis information. + DT->splitBlock(NewBB); + + // Remember the newly constructed landing pad. The original landing pad + // LPad is no longer a landing pad now that all unwind edges have been + // revectored to NewBB. + LandingPads.insert(NewBB); + ++NumLandingPadsSplit; + Changed = true; + } + + return Changed; +} + +/// LowerUnwinds - Turn unwind instructions into calls to _Unwind_Resume, +/// rethrowing any previously caught exception. This will crash horribly +/// at runtime if there is no such exception: using unwind to throw a new +/// exception is currently not supported. +bool DwarfEHPrepare::LowerUnwinds() { + SmallVector UnwindInsts; + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + TerminatorInst *TI = I->getTerminator(); + if (isa(TI)) + UnwindInsts.push_back(TI); + } + + if (UnwindInsts.empty()) return false; + + // Find the rewind function if we didn't already. + if (!RewindFunction) { + LLVMContext &Ctx = UnwindInsts[0]->getContext(); + std::vector + Params(1, Type::getInt8PtrTy(Ctx)); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), + Params, false); + const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); + RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy); + } + + bool Changed = false; + + for (SmallVectorImpl::iterator + I = UnwindInsts.begin(), E = UnwindInsts.end(); I != E; ++I) { + TerminatorInst *TI = *I; + + // Replace the unwind instruction with a call to _Unwind_Resume (or the + // appropriate target equivalent) followed by an UnreachableInst. + + // Create the call... + CallInst *CI = CallInst::Create(RewindFunction, + CreateExceptionValueCall(TI->getParent()), + "", TI); + CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + // ...followed by an UnreachableInst. + new UnreachableInst(TI->getContext(), TI); + + // Nuke the unwind instruction. + TI->eraseFromParent(); + ++NumUnwindsLowered; + Changed = true; + } + + return Changed; +} + +/// MoveExceptionValueCalls - Ensure that eh.exception is only ever called from +/// landing pads by replacing calls outside of landing pads with direct use of +/// a register holding the appropriate value; this requires adding calls inside +/// all landing pads to initialize the register. Also, move eh.exception calls +/// inside landing pads to the start of the landing pad (optional, but may make +/// things simpler for later passes). +bool DwarfEHPrepare::MoveExceptionValueCalls() { + // If the eh.exception intrinsic is not declared in the module then there is + // nothing to do. Speed up compilation by checking for this common case. + if (!ExceptionValueIntrinsic && + !F->getParent()->getFunction(Intrinsic::getName(Intrinsic::eh_exception))) + return false; + + bool Changed = false; + + // Move calls to eh.exception that are inside a landing pad to the start of + // the landing pad. + for (BBSet::const_iterator LI = LandingPads.begin(), LE = LandingPads.end(); + LI != LE; ++LI) { + BasicBlock *LP = *LI; + for (BasicBlock::iterator II = LP->getFirstNonPHIOrDbg(), IE = LP->end(); + II != IE;) + if (EHExceptionInst *EI = dyn_cast(II++)) { + // Found a call to eh.exception. + if (!EI->use_empty()) { + // If there is already a call to eh.exception at the start of the + // landing pad, then get hold of it; otherwise create such a call. + Value *CallAtStart = CreateExceptionValueCall(LP); + + // If the call was at the start of a landing pad then leave it alone. + if (EI == CallAtStart) + continue; + EI->replaceAllUsesWith(CallAtStart); + } + EI->eraseFromParent(); + ++NumExceptionValuesMoved; + Changed = true; + } + } + + // Look for calls to eh.exception that are not in a landing pad. If one is + // found, then a register that holds the exception value will be created in + // each landing pad, and the SSAUpdater will be used to compute the values + // returned by eh.exception calls outside of landing pads. + SSAUpdater SSA; + + // Remember where we found the eh.exception call, to avoid rescanning earlier + // basic blocks which we already know contain no eh.exception calls. + bool FoundCallOutsideLandingPad = false; + Function::iterator BB = F->begin(); + for (Function::iterator BE = F->end(); BB != BE; ++BB) { + // Skip over landing pads. + if (LandingPads.count(BB)) + continue; + + for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); + II != IE; ++II) + if (isa(II)) { + SSA.Initialize(II->getType(), II->getName()); + FoundCallOutsideLandingPad = true; + break; + } + + if (FoundCallOutsideLandingPad) + break; + } + + // If all calls to eh.exception are in landing pads then we are done. + if (!FoundCallOutsideLandingPad) + return Changed; + + // Add a call to eh.exception at the start of each landing pad, and tell the + // SSAUpdater that this is the value produced by the landing pad. + for (BBSet::iterator LI = LandingPads.begin(), LE = LandingPads.end(); + LI != LE; ++LI) + SSA.AddAvailableValue(*LI, CreateExceptionValueCall(*LI)); + + // Now turn all calls to eh.exception that are not in a landing pad into a use + // of the appropriate register. + for (Function::iterator BE = F->end(); BB != BE; ++BB) { + // Skip over landing pads. + if (LandingPads.count(BB)) + continue; + + for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); + II != IE;) + if (EHExceptionInst *EI = dyn_cast(II++)) { + // Found a call to eh.exception, replace it with the value from any + // upstream landing pad(s). + EI->replaceAllUsesWith(SSA.GetValueAtEndOfBlock(BB)); + EI->eraseFromParent(); + ++NumExceptionValuesMoved; + } + } + + return true; +} + +/// CreateExceptionValueCall - Insert a call to the eh.exception intrinsic at +/// the start of the basic block (unless there already is one, in which case +/// the existing call is returned). +Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) { + Instruction *Start = BB->getFirstNonPHIOrDbg(); + // Is this a call to eh.exception? + if (IntrinsicInst *CI = dyn_cast(Start)) + if (CI->getIntrinsicID() == Intrinsic::eh_exception) + // Reuse the existing call. + return Start; + + // Find the eh.exception intrinsic if we didn't already. + if (!ExceptionValueIntrinsic) + ExceptionValueIntrinsic = Intrinsic::getDeclaration(F->getParent(), + Intrinsic::eh_exception); + + // Create the call. + return CallInst::Create(ExceptionValueIntrinsic, "eh.value.call", Start); +} + +bool DwarfEHPrepare::runOnFunction(Function &Fn) { + bool Changed = false; + + // Initialize internal state. + DT = &getAnalysis(); + F = &Fn; + + // Ensure that only unwind edges end at landing pads (a landing pad is a + // basic block where an invoke unwind edge ends). + Changed |= NormalizeLandingPads(); + + // Turn unwind instructions into libcalls. + Changed |= LowerUnwinds(); + + // TODO: Move eh.selector calls to landing pads and combine them. + + // Move eh.exception calls to landing pads. + Changed |= MoveExceptionValueCalls(); + + Changed |= HandleURoRInvokes(); + + LandingPads.clear(); + + return Changed; +} diff --git a/final/lib/CodeGen/ELF.h b/final/lib/CodeGen/ELF.h new file mode 100644 index 00000000000..e08feeb2753 --- /dev/null +++ b/final/lib/CodeGen/ELF.h @@ -0,0 +1,227 @@ +//===-- lib/CodeGen/ELF.h - ELF constants and data structures ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on the Tool +// Interface Standard (TIS) Executable and Linking Format (ELF) Specification +// Version 1.2, May 1995. The ELF64 is based on HP/Intel definition of the +// ELF-64 object file format document, Version 1.5 Draft 2 May 27, 1998 +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ELF_H +#define CODEGEN_ELF_H + +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class GlobalValue; + + /// ELFSym - This struct contains information about each symbol that is + /// added to logical symbol table for the module. This is eventually + /// turned into a real symbol table in the file. + struct ELFSym { + + // ELF symbols are related to llvm ones by being one of the two llvm + // types, for the other ones (section, file, func) a null pointer is + // assumed by default. + union { + const GlobalValue *GV; // If this is a pointer to a GV + const char *Ext; // If this is a pointer to a named symbol + } Source; + + // Describes from which source type this ELF symbol comes from, + // they can be GlobalValue, ExternalSymbol or neither. + enum { + isGV, // The Source.GV field is valid. + isExtSym, // The Source.ExtSym field is valid. + isOther // Not a GlobalValue or External Symbol + }; + unsigned SourceType; + + bool isGlobalValue() const { return SourceType == isGV; } + bool isExternalSym() const { return SourceType == isExtSym; } + + // getGlobalValue - If this is a global value which originated the + // elf symbol, return a reference to it. + const GlobalValue *getGlobalValue() const { + assert(SourceType == isGV && "This is not a global value"); + return Source.GV; + } + + // getExternalSym - If this is an external symbol which originated the + // elf symbol, return a reference to it. + const char *getExternalSymbol() const { + assert(SourceType == isExtSym && "This is not an external symbol"); + return Source.Ext; + } + + // getGV - From a global value return a elf symbol to represent it + static ELFSym *getGV(const GlobalValue *GV, unsigned Bind, + unsigned Type, unsigned Visibility) { + ELFSym *Sym = new ELFSym(); + Sym->Source.GV = GV; + Sym->setBind(Bind); + Sym->setType(Type); + Sym->setVisibility(Visibility); + Sym->SourceType = isGV; + return Sym; + } + + // getExtSym - Create and return an elf symbol to represent an + // external symbol + static ELFSym *getExtSym(const char *Ext) { + ELFSym *Sym = new ELFSym(); + Sym->Source.Ext = Ext; + Sym->setBind(ELF::STB_GLOBAL); + Sym->setType(ELF::STT_NOTYPE); + Sym->setVisibility(ELF::STV_DEFAULT); + Sym->SourceType = isExtSym; + return Sym; + } + + // getSectionSym - Returns a elf symbol to represent an elf section + static ELFSym *getSectionSym() { + ELFSym *Sym = new ELFSym(); + Sym->setBind(ELF::STB_LOCAL); + Sym->setType(ELF::STT_SECTION); + Sym->setVisibility(ELF::STV_DEFAULT); + Sym->SourceType = isOther; + return Sym; + } + + // getFileSym - Returns a elf symbol to represent the module identifier + static ELFSym *getFileSym() { + ELFSym *Sym = new ELFSym(); + Sym->setBind(ELF::STB_LOCAL); + Sym->setType(ELF::STT_FILE); + Sym->setVisibility(ELF::STV_DEFAULT); + Sym->SectionIdx = 0xfff1; // ELFSection::SHN_ABS; + Sym->SourceType = isOther; + return Sym; + } + + // getUndefGV - Returns a STT_NOTYPE symbol + static ELFSym *getUndefGV(const GlobalValue *GV, unsigned Bind) { + ELFSym *Sym = new ELFSym(); + Sym->Source.GV = GV; + Sym->setBind(Bind); + Sym->setType(ELF::STT_NOTYPE); + Sym->setVisibility(ELF::STV_DEFAULT); + Sym->SectionIdx = 0; //ELFSection::SHN_UNDEF; + Sym->SourceType = isGV; + return Sym; + } + + // ELF specific fields + unsigned NameIdx; // Index in .strtab of name, once emitted. + uint64_t Value; + unsigned Size; + uint8_t Info; + uint8_t Other; + unsigned short SectionIdx; + + // Symbol index into the Symbol table + unsigned SymTabIdx; + + ELFSym() : SourceType(isOther), NameIdx(0), Value(0), + Size(0), Info(0), Other(ELF::STV_DEFAULT), SectionIdx(0), + SymTabIdx(0) {} + + unsigned getBind() const { return (Info >> 4) & 0xf; } + unsigned getType() const { return Info & 0xf; } + bool isLocalBind() const { return getBind() == ELF::STB_LOCAL; } + bool isFileType() const { return getType() == ELF::STT_FILE; } + + void setBind(unsigned X) { + assert(X == (X & 0xF) && "Bind value out of range!"); + Info = (Info & 0x0F) | (X << 4); + } + + void setType(unsigned X) { + assert(X == (X & 0xF) && "Type value out of range!"); + Info = (Info & 0xF0) | X; + } + + void setVisibility(unsigned V) { + assert(V == (V & 0x3) && "Visibility value out of range!"); + Other = V; + } + }; + + /// ELFSection - This struct contains information about each section that is + /// emitted to the file. This is eventually turned into the section header + /// table at the end of the file. + class ELFSection : public BinaryObject { + public: + // ELF specific fields + unsigned NameIdx; // sh_name - .shstrtab idx of name, once emitted. + unsigned Type; // sh_type - Section contents & semantics + unsigned Flags; // sh_flags - Section flags. + uint64_t Addr; // sh_addr - The mem addr this section is in. + unsigned Offset; // sh_offset - Offset from the file start + unsigned Size; // sh_size - The section size. + unsigned Link; // sh_link - Section header table index link. + unsigned Info; // sh_info - Auxillary information. + unsigned Align; // sh_addralign - Alignment of section. + unsigned EntSize; // sh_entsize - Size of entries in the section e + + /// SectionIdx - The number of the section in the Section Table. + unsigned short SectionIdx; + + /// Sym - The symbol to represent this section if it has one. + ELFSym *Sym; + + /// getSymIndex - Returns the symbol table index of the symbol + /// representing this section. + unsigned getSymbolTableIndex() const { + assert(Sym && "section not present in the symbol table"); + return Sym->SymTabIdx; + } + + ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit) + : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0), + Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0), Sym(0) {} + }; + + /// ELFRelocation - This class contains all the information necessary to + /// to generate any 32-bit or 64-bit ELF relocation entry. + class ELFRelocation { + uint64_t r_offset; // offset in the section of the object this applies to + uint32_t r_symidx; // symbol table index of the symbol to use + uint32_t r_type; // machine specific relocation type + int64_t r_add; // explicit relocation addend + bool r_rela; // if true then the addend is part of the entry + // otherwise the addend is at the location specified + // by r_offset + public: + uint64_t getInfo(bool is64Bit) const { + if (is64Bit) + return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL); + else + return (r_symidx << 8) + (r_type & 0xFFL); + } + + uint64_t getOffset() const { return r_offset; } + int64_t getAddend() const { return r_add; } + + ELFRelocation(uint64_t off, uint32_t sym, uint32_t type, + bool rela = true, int64_t addend = 0) : + r_offset(off), r_symidx(sym), r_type(type), + r_add(addend), r_rela(rela) {} + }; + +} // end namespace llvm + +#endif diff --git a/final/lib/CodeGen/ELFCodeEmitter.cpp b/final/lib/CodeGen/ELFCodeEmitter.cpp new file mode 100644 index 00000000000..3fb087c5ea8 --- /dev/null +++ b/final/lib/CodeGen/ELFCodeEmitter.cpp @@ -0,0 +1,205 @@ +//===-- lib/CodeGen/ELFCodeEmitter.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "elfce" + +#include "ELF.h" +#include "ELFWriter.h" +#include "ELFCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +//===----------------------------------------------------------------------===// +// ELFCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. +void ELFCodeEmitter::startFunction(MachineFunction &MF) { + DEBUG(dbgs() << "processing function: " + << MF.getFunction()->getName() << "\n"); + + // Get the ELF Section that this function belongs in. + ES = &EW.getTextSection(MF.getFunction()); + + // Set the desired binary object to be used by the code emitters + setBinaryObject(ES); + + // Get the function alignment in bytes + unsigned Align = (1 << MF.getAlignment()); + + // The function must start on its required alignment + ES->emitAlignment(Align); + + // Update the section alignment if needed. + ES->Align = std::max(ES->Align, Align); + + // Record the function start offset + FnStartOff = ES->getCurrentPCOffset(); + + // Emit constant pool and jump tables to their appropriate sections. + // They need to be emitted before the function because in some targets + // the later may reference JT or CP entry address. + emitConstantPool(MF.getConstantPool()); + if (MF.getJumpTableInfo()) + emitJumpTables(MF.getJumpTableInfo()); +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. +bool ELFCodeEmitter::finishFunction(MachineFunction &MF) { + // Add a symbol to represent the function. + const Function *F = MF.getFunction(); + ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELF::STT_FUNC, + EW.getGlobalELFVisibility(F)); + FnSym->SectionIdx = ES->SectionIdx; + FnSym->Size = ES->getCurrentPCOffset()-FnStartOff; + EW.AddPendingGlobalSymbol(F, true); + + // Offset from start of Section + FnSym->Value = FnStartOff; + + if (!F->hasPrivateLinkage()) + EW.SymbolList.push_back(FnSym); + + // Patch up Jump Table Section relocations to use the real MBBs offsets + // now that the MBB label offsets inside the function are known. + if (MF.getJumpTableInfo()) { + ELFSection &JTSection = EW.getJumpTableSection(); + for (std::vector::iterator MRI = JTRelocations.begin(), + MRE = JTRelocations.end(); MRI != MRE; ++MRI) { + MachineRelocation &MR = *MRI; + uintptr_t MBBOffset = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setResultPointer((void*)MBBOffset); + MR.setConstantVal(ES->SectionIdx); + JTSection.addRelocation(MR); + } + } + + // If we have emitted any relocations to function-specific objects such as + // basic blocks, constant pools entries, or jump tables, record their + // addresses now so that we can rewrite them with the correct addresses later + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + intptr_t Addr; + if (MR.isGlobalValue()) { + EW.AddPendingGlobalSymbol(MR.getGlobalValue()); + } else if (MR.isExternalSymbol()) { + EW.AddPendingExternalSymbol(MR.getExternalSymbol()); + } else if (MR.isBasicBlock()) { + Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setConstantVal(ES->SectionIdx); + MR.setResultPointer((void*)Addr); + } else if (MR.isConstantPoolIndex()) { + Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); + MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + ELFSection &JTSection = EW.getJumpTableSection(); + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setConstantVal(JTSection.SectionIdx); + MR.setResultPointer((void*)Addr); + } else { + llvm_unreachable("Unhandled relocation type"); + } + ES->addRelocation(MR); + } + + // Clear per-function data structures. + JTRelocations.clear(); + Relocations.clear(); + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); + return false; +} + +/// emitConstantPool - For each constant pool entry, figure out which section +/// the constant should live in and emit the constant +void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // TODO: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf constant pools!"); + + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = CP[i]; + + // Record the constant pool location and the section index + ELFSection &CstPool = EW.getConstantPoolSection(CPE); + CPLocations.push_back(CstPool.size()); + CPSections.push_back(CstPool.SectionIdx); + + if (CPE.isMachineConstantPoolEntry()) + assert("CPE.isMachineConstantPoolEntry not supported yet"); + + // Emit the constant to constant pool section + EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool); + } +} + +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. +void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for elf jump tables!"); + + const TargetELFWriterInfo *TEW = TM.getELFWriterInfo(); + unsigned EntrySize = 4; //MJTI->getEntrySize(); + + // Get the ELF Section to emit the jump table + ELFSection &JTSection = EW.getJumpTableSection(); + + // For each JT, record its offset from the start of the section + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + + // Record JT 'i' offset in the JT section + JTLocations.push_back(JTSection.size()); + + // Each MBB entry in the Jump table section has a relocation entry + // against the current text section. + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + unsigned MachineRelTy = TEW->getAbsoluteLabelMachineRelTy(); + MachineRelocation MR = + MachineRelocation::getBB(JTSection.size(), MachineRelTy, MBBs[mi]); + + // Add the relocation to the Jump Table section + JTRelocations.push_back(MR); + + // Output placeholder for MBB in the JT section + for (unsigned s=0; s < EntrySize; ++s) + JTSection.emitByte(0); + } + } +} + +} // end namespace llvm diff --git a/final/lib/CodeGen/ELFCodeEmitter.h b/final/lib/CodeGen/ELFCodeEmitter.h new file mode 100644 index 00000000000..2ec1f6e873d --- /dev/null +++ b/final/lib/CodeGen/ELFCodeEmitter.h @@ -0,0 +1,78 @@ +//===-- lib/CodeGen/ELFCodeEmitter.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef ELFCODEEMITTER_H +#define ELFCODEEMITTER_H + +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include + +namespace llvm { + class ELFWriter; + class ELFSection; + + /// ELFCodeEmitter - This class is used by the ELFWriter to + /// emit the code for functions to the ELF file. + class ELFCodeEmitter : public ObjectCodeEmitter { + ELFWriter &EW; + + /// Target machine description + TargetMachine &TM; + + /// Section containing code for functions + ELFSection *ES; + + /// Relocations - Record relocations needed by the current function + std::vector Relocations; + + /// JTRelocations - Record relocations needed by the relocation + /// section. + std::vector JTRelocations; + + /// FnStartPtr - Function offset from the beginning of ELFSection 'ES' + uintptr_t FnStartOff; + public: + explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {} + + /// addRelocation - Register new relocations for this function + void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + /// emitConstantPool - For each constant pool entry, figure out which + /// section the constant should live in and emit data to it + void emitConstantPool(MachineConstantPool *MCP); + + /// emitJumpTables - Emit all the jump tables for a given jump table + /// info and record them to the appropriate section. + void emitJumpTables(MachineJumpTableInfo *MJTI); + + void startFunction(MachineFunction &F); + bool finishFunction(MachineFunction &F); + + /// emitLabel - Emits a label + virtual void emitLabel(MCSymbol *Label) { + assert("emitLabel not implemented"); + } + + /// getLabelAddress - Return the address of the specified LabelID, + /// only usable after the LabelID has been emitted. + virtual uintptr_t getLabelAddress(MCSymbol *Label) const { + assert("getLabelAddress not implemented"); + return 0; + } + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {} + +}; // end class ELFCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/final/lib/CodeGen/ELFWriter.cpp b/final/lib/CodeGen/ELFWriter.cpp new file mode 100644 index 00000000000..0fd1e8e83bd --- /dev/null +++ b/final/lib/CodeGen/ELFWriter.cpp @@ -0,0 +1,1103 @@ +//===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===// +// +// 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 target-independent ELF writer. This file writes out +// the ELF file in the following order: +// +// #1. ELF Header +// #2. '.text' section +// #3. '.data' section +// #4. '.bss' section (conceptual position in file) +// ... +// #X. '.shstrtab' section +// #Y. Section Table +// +// The entries in the section table are laid out as: +// #0. Null entry [required] +// #1. ".text" entry - the program code +// #2. ".data" entry - global variables with initializers. [ if needed ] +// #3. ".bss" entry - global variables without initializers. [ if needed ] +// ... +// #N. ".shstrtab" entry - String table for the section names. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "elfwriter" +#include "ELF.h" +#include "ELFWriter.h" +#include "ELFCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/PassManager.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetELFWriterInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +using namespace llvm; + +char ELFWriter::ID = 0; + +//===----------------------------------------------------------------------===// +// ELFWriter Implementation +//===----------------------------------------------------------------------===// + +ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) + : MachineFunctionPass(ID), O(o), TM(tm), + OutContext(*new MCContext(*TM.getMCAsmInfo(), new TargetAsmInfo(tm))), + TLOF(TM.getTargetLowering()->getObjFileLowering()), + is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64), + isLittleEndian(TM.getTargetData()->isLittleEndian()), + ElfHdr(isLittleEndian, is64Bit) { + + MAI = TM.getMCAsmInfo(); + TEW = TM.getELFWriterInfo(); + + // Create the object code emitter object for this target. + ElfCE = new ELFCodeEmitter(*this); + + // Inital number of sections + NumSections = 0; +} + +ELFWriter::~ELFWriter() { + delete ElfCE; + delete &OutContext; + + while(!SymbolList.empty()) { + delete SymbolList.back(); + SymbolList.pop_back(); + } + + while(!PrivateSyms.empty()) { + delete PrivateSyms.back(); + PrivateSyms.pop_back(); + } + + while(!SectionList.empty()) { + delete SectionList.back(); + SectionList.pop_back(); + } + + // Release the name mangler object. + delete Mang; Mang = 0; +} + +// doInitialization - Emit the file header and all of the global variables for +// the module to the ELF file. +bool ELFWriter::doInitialization(Module &M) { + // Initialize TargetLoweringObjectFile. + const_cast(TLOF).Initialize(OutContext, TM); + + Mang = new Mangler(OutContext, *TM.getTargetData()); + + // ELF Header + // ---------- + // Fields e_shnum e_shstrndx are only known after all section have + // been emitted. They locations in the ouput buffer are recorded so + // to be patched up later. + // + // Note + // ---- + // emitWord method behaves differently for ELF32 and ELF64, writing + // 4 bytes in the former and 8 in the last for *_off and *_addr elf types + + ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0] + ElfHdr.emitByte('E'); // e_ident[EI_MAG1] + ElfHdr.emitByte('L'); // e_ident[EI_MAG2] + ElfHdr.emitByte('F'); // e_ident[EI_MAG3] + + ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS] + ElfHdr.emitByte(TEW->getEIData()); // e_ident[EI_DATA] + ElfHdr.emitByte(ELF::EV_CURRENT); // e_ident[EI_VERSION] + ElfHdr.emitAlignment(16); // e_ident[EI_NIDENT-EI_PAD] + + ElfHdr.emitWord16(ELF::ET_REL); // e_type + ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target + ElfHdr.emitWord32(ELF::EV_CURRENT); // e_version + ElfHdr.emitWord(0); // e_entry, no entry point in .o file + ElfHdr.emitWord(0); // e_phoff, no program header for .o + ELFHdr_e_shoff_Offset = ElfHdr.size(); + ElfHdr.emitWord(0); // e_shoff = sec hdr table off in bytes + ElfHdr.emitWord32(TEW->getEFlags()); // e_flags = whatever the target wants + ElfHdr.emitWord16(TEW->getHdrSize()); // e_ehsize = ELF header size + ElfHdr.emitWord16(0); // e_phentsize = prog header entry size + ElfHdr.emitWord16(0); // e_phnum = # prog header entries = 0 + + // e_shentsize = Section header entry size + ElfHdr.emitWord16(TEW->getSHdrSize()); + + // e_shnum = # of section header ents + ELFHdr_e_shnum_Offset = ElfHdr.size(); + ElfHdr.emitWord16(0); // Placeholder + + // e_shstrndx = Section # of '.shstrtab' + ELFHdr_e_shstrndx_Offset = ElfHdr.size(); + ElfHdr.emitWord16(0); // Placeholder + + // Add the null section, which is required to be first in the file. + getNullSection(); + + // The first entry in the symtab is the null symbol and the second + // is a local symbol containing the module/file name + SymbolList.push_back(new ELFSym()); + SymbolList.push_back(ELFSym::getFileSym()); + + return false; +} + +// AddPendingGlobalSymbol - Add a global to be processed and to +// the global symbol lookup, use a zero index because the table +// index will be determined later. +void ELFWriter::AddPendingGlobalSymbol(const GlobalValue *GV, + bool AddToLookup /* = false */) { + PendingGlobals.insert(GV); + if (AddToLookup) + GblSymLookup[GV] = 0; +} + +// AddPendingExternalSymbol - Add the external to be processed +// and to the external symbol lookup, use a zero index because +// the symbol table index will be determined later. +void ELFWriter::AddPendingExternalSymbol(const char *External) { + PendingExternals.insert(External); + ExtSymLookup[External] = 0; +} + +ELFSection &ELFWriter::getDataSection() { + const MCSectionELF *Data = (const MCSectionELF *)TLOF.getDataSection(); + return getSection(Data->getSectionName(), Data->getType(), + Data->getFlags(), 4); +} + +ELFSection &ELFWriter::getBSSSection() { + const MCSectionELF *BSS = (const MCSectionELF *)TLOF.getBSSSection(); + return getSection(BSS->getSectionName(), BSS->getType(), BSS->getFlags(), 4); +} + +// getCtorSection - Get the static constructor section +ELFSection &ELFWriter::getCtorSection() { + const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection(); + return getSection(Ctor->getSectionName(), Ctor->getType(), Ctor->getFlags()); +} + +// getDtorSection - Get the static destructor section +ELFSection &ELFWriter::getDtorSection() { + const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection(); + return getSection(Dtor->getSectionName(), Dtor->getType(), Dtor->getFlags()); +} + +// getTextSection - Get the text section for the specified function +ELFSection &ELFWriter::getTextSection(const Function *F) { + const MCSectionELF *Text = + (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM); + return getSection(Text->getSectionName(), Text->getType(), Text->getFlags()); +} + +// getJumpTableSection - Get a read only section for constants when +// emitting jump tables. TODO: add PIC support +ELFSection &ELFWriter::getJumpTableSection() { + const MCSectionELF *JT = + (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly()); + return getSection(JT->getSectionName(), JT->getType(), JT->getFlags(), + TM.getTargetData()->getPointerABIAlignment()); +} + +// getConstantPoolSection - Get a constant pool section based on the machine +// constant pool entry type and relocation info. +ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) { + SectionKind Kind; + switch (CPE.getRelocationInfo()) { + default: llvm_unreachable("Unknown section kind"); + case 2: Kind = SectionKind::getReadOnlyWithRel(); break; + case 1: + Kind = SectionKind::getReadOnlyWithRelLocal(); + break; + case 0: + switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { + case 4: Kind = SectionKind::getMergeableConst4(); break; + case 8: Kind = SectionKind::getMergeableConst8(); break; + case 16: Kind = SectionKind::getMergeableConst16(); break; + default: Kind = SectionKind::getMergeableConst(); break; + } + } + + const MCSectionELF *CPSect = + (const MCSectionELF *)TLOF.getSectionForConstant(Kind); + return getSection(CPSect->getSectionName(), CPSect->getType(), + CPSect->getFlags(), CPE.getAlignment()); +} + +// getRelocSection - Return the relocation section of section 'S'. 'RelA' +// is true if the relocation section contains entries with addends. +ELFSection &ELFWriter::getRelocSection(ELFSection &S) { + unsigned SectionType = TEW->hasRelocationAddend() ? + ELF::SHT_RELA : ELF::SHT_REL; + + std::string SectionName(".rel"); + if (TEW->hasRelocationAddend()) + SectionName.append("a"); + SectionName.append(S.getName()); + + return getSection(SectionName, SectionType, 0, TEW->getPrefELFAlignment()); +} + +// getGlobalELFVisibility - Returns the ELF specific visibility type +unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { + switch (GV->getVisibility()) { + default: + llvm_unreachable("unknown visibility type"); + case GlobalValue::DefaultVisibility: + return ELF::STV_DEFAULT; + case GlobalValue::HiddenVisibility: + return ELF::STV_HIDDEN; + case GlobalValue::ProtectedVisibility: + return ELF::STV_PROTECTED; + } + return 0; +} + +// getGlobalELFBinding - Returns the ELF specific binding type +unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) { + if (GV->hasInternalLinkage()) + return ELF::STB_LOCAL; + + if (GV->isWeakForLinker() && !GV->hasCommonLinkage()) + return ELF::STB_WEAK; + + return ELF::STB_GLOBAL; +} + +// getGlobalELFType - Returns the ELF specific type for a global +unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) { + if (GV->isDeclaration()) + return ELF::STT_NOTYPE; + + if (isa(GV)) + return ELF::STT_FUNC; + + return ELF::STT_OBJECT; +} + +// IsELFUndefSym - True if the global value must be marked as a symbol +// which points to a SHN_UNDEF section. This means that the symbol has +// no definition on the module. +static bool IsELFUndefSym(const GlobalValue *GV) { + return GV->isDeclaration() || (isa(GV)); +} + +// AddToSymbolList - Update the symbol lookup and If the symbol is +// private add it to PrivateSyms list, otherwise to SymbolList. +void ELFWriter::AddToSymbolList(ELFSym *GblSym) { + assert(GblSym->isGlobalValue() && "Symbol must be a global value"); + + const GlobalValue *GV = GblSym->getGlobalValue(); + if (GV->hasPrivateLinkage()) { + // For a private symbols, keep track of the index inside + // the private list since it will never go to the symbol + // table and won't be patched up later. + PrivateSyms.push_back(GblSym); + GblSymLookup[GV] = PrivateSyms.size()-1; + } else { + // Non private symbol are left with zero indices until + // they are patched up during the symbol table emition + // (where the indicies are created). + SymbolList.push_back(GblSym); + GblSymLookup[GV] = 0; + } +} + +/// HasCommonSymbols - True if this section holds common symbols, this is +/// indicated on the ELF object file by a symbol with SHN_COMMON section +/// header index. +static bool HasCommonSymbols(const MCSectionELF &S) { + // FIXME: this is wrong, a common symbol can be in .data for example. + if (StringRef(S.getSectionName()).startswith(".gnu.linkonce.")) + return true; + + return false; +} + + +// EmitGlobal - Choose the right section for global and emit it +void ELFWriter::EmitGlobal(const GlobalValue *GV) { + + // Check if the referenced symbol is already emitted + if (GblSymLookup.find(GV) != GblSymLookup.end()) + return; + + // Handle ELF Bind, Visibility and Type for the current symbol + unsigned SymBind = getGlobalELFBinding(GV); + unsigned SymType = getGlobalELFType(GV); + bool IsUndefSym = IsELFUndefSym(GV); + + ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind) + : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV)); + + if (!IsUndefSym) { + assert(isa(GV) && "GV not a global variable!"); + const GlobalVariable *GVar = dyn_cast(GV); + + // Handle special llvm globals + if (EmitSpecialLLVMGlobal(GVar)) + return; + + // Get the ELF section where this global belongs from TLOF + const MCSectionELF *S = + (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM); + ELFSection &ES = + getSection(S->getSectionName(), S->getType(), S->getFlags()); + SectionKind Kind = S->getKind(); + + // The symbol align should update the section alignment if needed + const TargetData *TD = TM.getTargetData(); + unsigned Align = TD->getPreferredAlignment(GVar); + unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); + GblSym->Size = Size; + + if (HasCommonSymbols(*S)) { // Symbol must go to a common section + GblSym->SectionIdx = ELF::SHN_COMMON; + + // A new linkonce section is created for each global in the + // common section, the default alignment is 1 and the symbol + // value contains its alignment. + ES.Align = 1; + GblSym->Value = Align; + + } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS. + GblSym->SectionIdx = ES.SectionIdx; + + // Update the size with alignment and the next object can + // start in the right offset in the section + if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1); + ES.Align = std::max(ES.Align, Align); + + // GblSym->Value should contain the virtual offset inside the section. + // Virtual because the BSS space is not allocated on ELF objects + GblSym->Value = ES.Size; + ES.Size += Size; + + } else { // The symbol must go to some kind of data section + GblSym->SectionIdx = ES.SectionIdx; + + // GblSym->Value should contain the symbol offset inside the section, + // and all symbols should start on their required alignment boundary + ES.Align = std::max(ES.Align, Align); + ES.emitAlignment(Align); + GblSym->Value = ES.size(); + + // Emit the global to the data section 'ES' + EmitGlobalConstant(GVar->getInitializer(), ES); + } + } + + AddToSymbolList(GblSym); +} + +void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, + ELFSection &GblS) { + + // Print the fields in successive locations. Pad to align if needed! + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CVS->getType()); + const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); + uint64_t sizeSoFar = 0; + for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { + const Constant* field = CVS->getOperand(i); + + // Check if padding is needed and insert one or more 0s. + uint64_t fieldSize = TD->getTypeAllocSize(field->getType()); + uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) + - cvsLayout->getElementOffset(i)) - fieldSize; + sizeSoFar += fieldSize + padSize; + + // Now print the actual field value. + EmitGlobalConstant(field, GblS); + + // Insert padding - this may include padding to increase the size of the + // current field up to the ABI size (if the struct is not packed) as well + // as padding to ensure that the next field starts at the right offset. + GblS.emitZeros(padSize); + } + assert(sizeSoFar == cvsLayout->getSizeInBytes() && + "Layout of constant struct may be incorrect!"); +} + +void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { + const TargetData *TD = TM.getTargetData(); + unsigned Size = TD->getTypeAllocSize(CV->getType()); + + if (const ConstantArray *CVA = dyn_cast(CV)) { + for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) + EmitGlobalConstant(CVA->getOperand(i), GblS); + return; + } else if (isa(CV)) { + GblS.emitZeros(Size); + return; + } else if (const ConstantStruct *CVS = dyn_cast(CV)) { + EmitGlobalConstantStruct(CVS, GblS); + return; + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + APInt Val = CFP->getValueAPF().bitcastToAPInt(); + if (CFP->getType()->isDoubleTy()) + GblS.emitWord64(Val.getZExtValue()); + else if (CFP->getType()->isFloatTy()) + GblS.emitWord32(Val.getZExtValue()); + else if (CFP->getType()->isX86_FP80Ty()) { + unsigned PadSize = TD->getTypeAllocSize(CFP->getType())- + TD->getTypeStoreSize(CFP->getType()); + GblS.emitWordFP80(Val.getRawData(), PadSize); + } else if (CFP->getType()->isPPC_FP128Ty()) + llvm_unreachable("PPC_FP128Ty global emission not implemented"); + return; + } else if (const ConstantInt *CI = dyn_cast(CV)) { + if (Size == 1) + GblS.emitByte(CI->getZExtValue()); + else if (Size == 2) + GblS.emitWord16(CI->getZExtValue()); + else if (Size == 4) + GblS.emitWord32(CI->getZExtValue()); + else + EmitGlobalConstantLargeInt(CI, GblS); + return; + } else if (const ConstantVector *CP = dyn_cast(CV)) { + const VectorType *PTy = CP->getType(); + for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) + EmitGlobalConstant(CP->getOperand(I), GblS); + return; + } else if (const ConstantExpr *CE = dyn_cast(CV)) { + // Resolve a constant expression which returns a (Constant, Offset) + // pair. If 'Res.first' is a GlobalValue, emit a relocation with + // the offset 'Res.second', otherwise emit a global constant like + // it is always done for not contant expression types. + CstExprResTy Res = ResolveConstantExpr(CE); + const Constant *Op = Res.first; + + if (isa(Op)) + EmitGlobalDataRelocation(cast(Op), + TD->getTypeAllocSize(Op->getType()), + GblS, Res.second); + else + EmitGlobalConstant(Op, GblS); + + return; + } else if (CV->getType()->getTypeID() == Type::PointerTyID) { + // Fill the data entry with zeros or emit a relocation entry + if (isa(CV)) + GblS.emitZeros(Size); + else + EmitGlobalDataRelocation(cast(CV), + Size, GblS); + return; + } else if (const GlobalValue *GV = dyn_cast(CV)) { + // This is a constant address for a global variable or function and + // therefore must be referenced using a relocation entry. + EmitGlobalDataRelocation(GV, Size, GblS); + return; + } + + std::string msg; + raw_string_ostream ErrorMsg(msg); + ErrorMsg << "Constant unimp for type: " << *CV->getType(); + report_fatal_error(ErrorMsg.str()); +} + +// ResolveConstantExpr - Resolve the constant expression until it stop +// yielding other constant expressions. +CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { + const TargetData *TD = TM.getTargetData(); + + // There ins't constant expression inside others anymore + if (!isa(CV)) + return std::make_pair(CV, 0); + + const ConstantExpr *CE = dyn_cast(CV); + switch (CE->getOpcode()) { + case Instruction::BitCast: + return ResolveConstantExpr(CE->getOperand(0)); + + case Instruction::GetElementPtr: { + const Constant *ptrVal = CE->getOperand(0); + SmallVector idxVec(CE->op_begin()+1, CE->op_end()); + int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0], + idxVec.size()); + return std::make_pair(ptrVal, Offset); + } + case Instruction::IntToPtr: { + Constant *Op = CE->getOperand(0); + Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), + false/*ZExt*/); + return ResolveConstantExpr(Op); + } + case Instruction::PtrToInt: { + Constant *Op = CE->getOperand(0); + const Type *Ty = CE->getType(); + + // We can emit the pointer value into this slot if the slot is an + // integer slot greater or equal to the size of the pointer. + if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) + return ResolveConstantExpr(Op); + + llvm_unreachable("Integer size less then pointer size"); + } + case Instruction::Add: + case Instruction::Sub: { + // Only handle cases where there's a constant expression with GlobalValue + // as first operand and ConstantInt as second, which are the cases we can + // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1 + // 1) Instruction::Add => (global) + CstInt + // 2) Instruction::Sub => (global) + -CstInt + const Constant *Op0 = CE->getOperand(0); + const Constant *Op1 = CE->getOperand(1); + assert(isa(Op1) && "Op1 must be a ConstantInt"); + + CstExprResTy Res = ResolveConstantExpr(Op0); + assert(isa(Res.first) && "Op0 must be a GlobalValue"); + + const APInt &RHS = cast(Op1)->getValue(); + switch (CE->getOpcode()) { + case Instruction::Add: + return std::make_pair(Res.first, RHS.getSExtValue()); + case Instruction::Sub: + return std::make_pair(Res.first, (-RHS).getSExtValue()); + } + } + } + + report_fatal_error(CE->getOpcodeName() + + StringRef(": Unsupported ConstantExpr type")); + + return std::make_pair(CV, 0); // silence warning +} + +void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, + ELFSection &GblS, int64_t Offset) { + // Create the relocation entry for the global value + MachineRelocation MR = + MachineRelocation::getGV(GblS.getCurrentPCOffset(), + TEW->getAbsoluteLabelMachineRelTy(), + const_cast(GV), + Offset); + + // Fill the data entry with zeros + GblS.emitZeros(Size); + + // Add the relocation entry for the current data section + GblS.addRelocation(MR); +} + +void ELFWriter::EmitGlobalConstantLargeInt(const ConstantInt *CI, + ELFSection &S) { + const TargetData *TD = TM.getTargetData(); + unsigned BitWidth = CI->getBitWidth(); + assert(isPowerOf2_32(BitWidth) && + "Non-power-of-2-sized integers not handled!"); + + const uint64_t *RawData = CI->getValue().getRawData(); + uint64_t Val = 0; + for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { + Val = (TD->isBigEndian()) ? RawData[e - i - 1] : RawData[i]; + S.emitWord64(Val); + } +} + +/// EmitSpecialLLVMGlobal - Check to see if the specified global is a +/// special global used by LLVM. If so, emit it and return true, otherwise +/// do nothing and return false. +bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { + if (GV->getName() == "llvm.used") + llvm_unreachable("not implemented yet"); + + // Ignore debug and non-emitted data. This handles llvm.compiler.used. + if (GV->getSection() == "llvm.metadata" || + GV->hasAvailableExternallyLinkage()) + return true; + + if (!GV->hasAppendingLinkage()) return false; + + assert(GV->hasInitializer() && "Not a special LLVM global!"); + + const TargetData *TD = TM.getTargetData(); + unsigned Align = TD->getPointerPrefAlignment(); + if (GV->getName() == "llvm.global_ctors") { + ELFSection &Ctor = getCtorSection(); + Ctor.emitAlignment(Align); + EmitXXStructorList(GV->getInitializer(), Ctor); + return true; + } + + if (GV->getName() == "llvm.global_dtors") { + ELFSection &Dtor = getDtorSection(); + Dtor.emitAlignment(Align); + EmitXXStructorList(GV->getInitializer(), Dtor); + return true; + } + + return false; +} + +/// EmitXXStructorList - Emit the ctor or dtor list. This just emits out the +/// function pointers, ignoring the init priority. +void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) { + // Should be an array of '{ int, void ()* }' structs. The first value is the + // init priority, which we ignore. + if (!isa(List)) return; + ConstantArray *InitList = cast(List); + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + if (CS->getOperand(1)->isNullValue()) + return; // Found a null terminator, exit printing. + // Emit the function pointer. + EmitGlobalConstant(CS->getOperand(1), Xtor); + } +} + +bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { + // Nothing to do here, this is all done through the ElfCE object above. + return false; +} + +/// doFinalization - Now that the module has been completely processed, emit +/// the ELF file to 'O'. +bool ELFWriter::doFinalization(Module &M) { + // Emit .data section placeholder + getDataSection(); + + // Emit .bss section placeholder + getBSSSection(); + + // Build and emit data, bss and "common" sections. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + EmitGlobal(I); + + // Emit all pending globals + for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end(); + I != E; ++I) + EmitGlobal(*I); + + // Emit all pending externals + for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end(); + I != E; ++I) + SymbolList.push_back(ELFSym::getExtSym(*I)); + + // Emit a symbol for each section created until now, skip null section + for (unsigned i = 1, e = SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + ELFSym *SectionSym = ELFSym::getSectionSym(); + SectionSym->SectionIdx = ES.SectionIdx; + SymbolList.push_back(SectionSym); + ES.Sym = SymbolList.back(); + } + + // Emit string table + EmitStringTable(M.getModuleIdentifier()); + + // Emit the symbol table now, if non-empty. + EmitSymbolTable(); + + // Emit the relocation sections. + EmitRelocations(); + + // Emit the sections string table. + EmitSectionTableStringTable(); + + // Dump the sections and section table to the .o file. + OutputSectionsAndSectionTable(); + + return false; +} + +// RelocateField - Patch relocatable field with 'Offset' in 'BO' +// using a 'Value' of known 'Size' +void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset, + int64_t Value, unsigned Size) { + if (Size == 32) + BO.fixWord32(Value, Offset); + else if (Size == 64) + BO.fixWord64(Value, Offset); + else + llvm_unreachable("don't know howto patch relocatable field"); +} + +/// EmitRelocations - Emit relocations +void ELFWriter::EmitRelocations() { + + // True if the target uses the relocation entry to hold the addend, + // otherwise the addend is written directly to the relocatable field. + bool HasRelA = TEW->hasRelocationAddend(); + + // Create Relocation sections for each section which needs it. + for (unsigned i=0, e=SectionList.size(); i != e; ++i) { + ELFSection &S = *SectionList[i]; + + // This section does not have relocations + if (!S.hasRelocations()) continue; + ELFSection &RelSec = getRelocSection(S); + + // 'Link' - Section hdr idx of the associated symbol table + // 'Info' - Section hdr idx of the section to which the relocation applies + ELFSection &SymTab = getSymbolTableSection(); + RelSec.Link = SymTab.SectionIdx; + RelSec.Info = S.SectionIdx; + RelSec.EntSize = TEW->getRelocationEntrySize(); + + // Get the relocations from Section + std::vector Relos = S.getRelocations(); + for (std::vector::iterator MRI = Relos.begin(), + MRE = Relos.end(); MRI != MRE; ++MRI) { + MachineRelocation &MR = *MRI; + + // Relocatable field offset from the section start + unsigned RelOffset = MR.getMachineCodeOffset(); + + // Symbol index in the symbol table + unsigned SymIdx = 0; + + // Target specific relocation field type and size + unsigned RelType = TEW->getRelocationType(MR.getRelocationType()); + unsigned RelTySize = TEW->getRelocationTySize(RelType); + int64_t Addend = 0; + + // There are several machine relocations types, and each one of + // them needs a different approach to retrieve the symbol table index. + if (MR.isGlobalValue()) { + const GlobalValue *G = MR.getGlobalValue(); + int64_t GlobalOffset = MR.getConstantVal(); + SymIdx = GblSymLookup[G]; + if (G->hasPrivateLinkage()) { + // If the target uses a section offset in the relocation: + // SymIdx + Addend = section sym for global + section offset + unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx; + Addend = PrivateSyms[SymIdx]->Value + GlobalOffset; + SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); + } else { + Addend = TEW->getDefaultAddendForRelTy(RelType, GlobalOffset); + } + } else if (MR.isExternalSymbol()) { + const char *ExtSym = MR.getExternalSymbol(); + SymIdx = ExtSymLookup[ExtSym]; + Addend = TEW->getDefaultAddendForRelTy(RelType); + } else { + // Get the symbol index for the section symbol + unsigned SectionIdx = MR.getConstantVal(); + SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); + + // The symbol offset inside the section + int64_t SymOffset = (int64_t)MR.getResultPointer(); + + // For pc relative relocations where symbols are defined in the same + // section they are referenced, ignore the relocation entry and patch + // the relocatable field with the symbol offset directly. + if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) { + int64_t Value = TEW->computeRelocation(SymOffset, RelOffset, RelType); + RelocateField(S, RelOffset, Value, RelTySize); + continue; + } + + Addend = TEW->getDefaultAddendForRelTy(RelType, SymOffset); + } + + // The target without addend on the relocation symbol must be + // patched in the relocation place itself to contain the addend + // otherwise write zeros to make sure there is no garbage there + RelocateField(S, RelOffset, HasRelA ? 0 : Addend, RelTySize); + + // Get the relocation entry and emit to the relocation section + ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend); + EmitRelocation(RelSec, Rel, HasRelA); + } + } +} + +/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel' +void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, + bool HasRelA) { + RelSec.emitWord(Rel.getOffset()); + RelSec.emitWord(Rel.getInfo(is64Bit)); + if (HasRelA) + RelSec.emitWord(Rel.getAddend()); +} + +/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable' +void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) { + if (is64Bit) { + SymbolTable.emitWord32(Sym.NameIdx); + SymbolTable.emitByte(Sym.Info); + SymbolTable.emitByte(Sym.Other); + SymbolTable.emitWord16(Sym.SectionIdx); + SymbolTable.emitWord64(Sym.Value); + SymbolTable.emitWord64(Sym.Size); + } else { + SymbolTable.emitWord32(Sym.NameIdx); + SymbolTable.emitWord32(Sym.Value); + SymbolTable.emitWord32(Sym.Size); + SymbolTable.emitByte(Sym.Info); + SymbolTable.emitByte(Sym.Other); + SymbolTable.emitWord16(Sym.SectionIdx); + } +} + +/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab' +/// Section Header Table +void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab, + const ELFSection &SHdr) { + SHdrTab.emitWord32(SHdr.NameIdx); + SHdrTab.emitWord32(SHdr.Type); + if (is64Bit) { + SHdrTab.emitWord64(SHdr.Flags); + SHdrTab.emitWord(SHdr.Addr); + SHdrTab.emitWord(SHdr.Offset); + SHdrTab.emitWord64(SHdr.Size); + SHdrTab.emitWord32(SHdr.Link); + SHdrTab.emitWord32(SHdr.Info); + SHdrTab.emitWord64(SHdr.Align); + SHdrTab.emitWord64(SHdr.EntSize); + } else { + SHdrTab.emitWord32(SHdr.Flags); + SHdrTab.emitWord(SHdr.Addr); + SHdrTab.emitWord(SHdr.Offset); + SHdrTab.emitWord32(SHdr.Size); + SHdrTab.emitWord32(SHdr.Link); + SHdrTab.emitWord32(SHdr.Info); + SHdrTab.emitWord32(SHdr.Align); + SHdrTab.emitWord32(SHdr.EntSize); + } +} + +/// EmitStringTable - If the current symbol table is non-empty, emit the string +/// table for it +void ELFWriter::EmitStringTable(const std::string &ModuleName) { + if (!SymbolList.size()) return; // Empty symbol table. + ELFSection &StrTab = getStringTableSection(); + + // Set the zero'th symbol to a null byte, as required. + StrTab.emitByte(0); + + // Walk on the symbol list and write symbol names into the string table. + unsigned Index = 1; + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + ELFSym &Sym = *(*I); + + std::string Name; + if (Sym.isGlobalValue()) { + SmallString<40> NameStr; + Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false); + Name.append(NameStr.begin(), NameStr.end()); + } else if (Sym.isExternalSym()) + Name.append(Sym.getExternalSymbol()); + else if (Sym.isFileType()) + Name.append(ModuleName); + + if (Name.empty()) { + Sym.NameIdx = 0; + } else { + Sym.NameIdx = Index; + StrTab.emitString(Name); + + // Keep track of the number of bytes emitted to this section. + Index += Name.size()+1; + } + } + assert(Index == StrTab.size()); + StrTab.Size = Index; +} + +// SortSymbols - On the symbol table local symbols must come before +// all other symbols with non-local bindings. The return value is +// the position of the first non local symbol. +unsigned ELFWriter::SortSymbols() { + unsigned FirstNonLocalSymbol; + std::vector LocalSyms, OtherSyms; + + for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { + if ((*I)->isLocalBind()) + LocalSyms.push_back(*I); + else + OtherSyms.push_back(*I); + } + SymbolList.clear(); + FirstNonLocalSymbol = LocalSyms.size(); + + for (unsigned i = 0; i < FirstNonLocalSymbol; ++i) + SymbolList.push_back(LocalSyms[i]); + + for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I) + SymbolList.push_back(*I); + + LocalSyms.clear(); + OtherSyms.clear(); + + return FirstNonLocalSymbol; +} + +/// EmitSymbolTable - Emit the symbol table itself. +void ELFWriter::EmitSymbolTable() { + if (!SymbolList.size()) return; // Empty symbol table. + + // Now that we have emitted the string table and know the offset into the + // string table of each symbol, emit the symbol table itself. + ELFSection &SymTab = getSymbolTableSection(); + SymTab.Align = TEW->getPrefELFAlignment(); + + // Section Index of .strtab. + SymTab.Link = getStringTableSection().SectionIdx; + + // Size of each symtab entry. + SymTab.EntSize = TEW->getSymTabEntrySize(); + + // Reorder the symbol table with local symbols first! + unsigned FirstNonLocalSymbol = SortSymbols(); + + // Emit all the symbols to the symbol table. + for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) { + ELFSym &Sym = *SymbolList[i]; + + // Emit symbol to the symbol table + EmitSymbol(SymTab, Sym); + + // Record the symbol table index for each symbol + if (Sym.isGlobalValue()) + GblSymLookup[Sym.getGlobalValue()] = i; + else if (Sym.isExternalSym()) + ExtSymLookup[Sym.getExternalSymbol()] = i; + + // Keep track on the symbol index into the symbol table + Sym.SymTabIdx = i; + } + + // One greater than the symbol table index of the last local symbol + SymTab.Info = FirstNonLocalSymbol; + SymTab.Size = SymTab.size(); +} + +/// EmitSectionTableStringTable - This method adds and emits a section for the +/// ELF Section Table string table: the string table that holds all of the +/// section names. +void ELFWriter::EmitSectionTableStringTable() { + // First step: add the section for the string table to the list of sections: + ELFSection &SHStrTab = getSectionHeaderStringTableSection(); + + // Now that we know which section number is the .shstrtab section, update the + // e_shstrndx entry in the ELF header. + ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset); + + // Set the NameIdx of each section in the string table and emit the bytes for + // the string table. + unsigned Index = 0; + + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); + // Set the index into the table. Note if we have lots of entries with + // common suffixes, we could memoize them here if we cared. + S.NameIdx = Index; + SHStrTab.emitString(S.getName()); + + // Keep track of the number of bytes emitted to this section. + Index += S.getName().size()+1; + } + + // Set the size of .shstrtab now that we know what it is. + assert(Index == SHStrTab.size()); + SHStrTab.Size = Index; +} + +/// OutputSectionsAndSectionTable - Now that we have constructed the file header +/// and all of the sections, emit these to the ostream destination and emit the +/// SectionTable. +void ELFWriter::OutputSectionsAndSectionTable() { + // Pass #1: Compute the file offset for each section. + size_t FileOff = ElfHdr.size(); // File header first. + + // Adjust alignment of all section if needed, skip the null section. + for (unsigned i=1, e=SectionList.size(); i < e; ++i) { + ELFSection &ES = *SectionList[i]; + if (!ES.size()) { + ES.Offset = FileOff; + continue; + } + + // Update Section size + if (!ES.Size) + ES.Size = ES.size(); + + // Align FileOff to whatever the alignment restrictions of the section are. + if (ES.Align) + FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1); + + ES.Offset = FileOff; + FileOff += ES.Size; + } + + // Align Section Header. + unsigned TableAlign = TEW->getPrefELFAlignment(); + FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); + + // Now that we know where all of the sections will be emitted, set the e_shnum + // entry in the ELF header. + ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset); + + // Now that we know the offset in the file of the section table, update the + // e_shoff address in the ELF header. + ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset); + + // Now that we know all of the data in the file header, emit it and all of the + // sections! + O.write((char *)&ElfHdr.getData()[0], ElfHdr.size()); + FileOff = ElfHdr.size(); + + // Section Header Table blob + BinaryObject SHdrTable(isLittleEndian, is64Bit); + + // Emit all of sections to the file and build the section header table. + for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { + ELFSection &S = *(*I); + DEBUG(dbgs() << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName() + << ", Size: " << S.Size << ", Offset: " << S.Offset + << ", SectionData Size: " << S.size() << "\n"); + + // Align FileOff to whatever the alignment restrictions of the section are. + if (S.size()) { + if (S.Align) { + for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1); + FileOff != NewFileOff; ++FileOff) + O << (char)0xAB; + } + O.write((char *)&S.getData()[0], S.Size); + FileOff += S.Size; + } + + EmitSectionHeader(SHdrTable, S); + } + + // Align output for the section table. + for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); + FileOff != NewFileOff; ++FileOff) + O << (char)0xAB; + + // Emit the section table itself. + O.write((char *)&SHdrTable.getData()[0], SHdrTable.size()); +} diff --git a/final/lib/CodeGen/ELFWriter.h b/final/lib/CodeGen/ELFWriter.h new file mode 100644 index 00000000000..b8bac5598ec --- /dev/null +++ b/final/lib/CodeGen/ELFWriter.h @@ -0,0 +1,251 @@ +//===-- ELFWriter.h - Target-independent ELF writer support -----*- 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 ELFWriter class. +// +//===----------------------------------------------------------------------===// + +#ifndef ELFWRITER_H +#define ELFWRITER_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include + +namespace llvm { + class BinaryObject; + class Constant; + class ConstantInt; + class ConstantStruct; + class ELFCodeEmitter; + class ELFRelocation; + class ELFSection; + struct ELFSym; + class GlobalVariable; + class JITDebugRegisterer; + class Mangler; + class MachineCodeEmitter; + class MachineConstantPoolEntry; + class ObjectCodeEmitter; + class MCAsmInfo; + class TargetELFWriterInfo; + class TargetLoweringObjectFile; + class raw_ostream; + class SectionKind; + class MCContext; + class TargetMachine; + + typedef std::vector::iterator ELFSymIter; + typedef std::vector::iterator ELFSectionIter; + typedef SetVector::const_iterator PendingGblsIter; + typedef SetVector::const_iterator PendingExtsIter; + typedef std::pair CstExprResTy; + + /// ELFWriter - This class implements the common target-independent code for + /// writing ELF files. Targets should derive a class from this to + /// parameterize the output format. + /// + class ELFWriter : public MachineFunctionPass { + friend class ELFCodeEmitter; + friend class JITDebugRegisterer; + public: + static char ID; + + /// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter + ObjectCodeEmitter *getObjectCodeEmitter() { + return reinterpret_cast(ElfCE); + } + + ELFWriter(raw_ostream &O, TargetMachine &TM); + ~ELFWriter(); + + protected: + /// Output stream to send the resultant object file to. + raw_ostream &O; + + /// Target machine description. + TargetMachine &TM; + + /// Context object for machine code objects. + MCContext &OutContext; + + /// Target Elf Writer description. + const TargetELFWriterInfo *TEW; + + /// Mang - The object used to perform name mangling for this module. + Mangler *Mang; + + /// MCE - The MachineCodeEmitter object that we are exposing to emit machine + /// code for functions to the .o file. + ELFCodeEmitter *ElfCE; + + /// TLOF - Target Lowering Object File, provide section names for globals + /// and other object file specific stuff + const TargetLoweringObjectFile &TLOF; + + /// MAI - Target Asm Info, provide information about section names for + /// globals and other target specific stuff. + const MCAsmInfo *MAI; + + //===------------------------------------------------------------------===// + // Properties inferred automatically from the target machine. + //===------------------------------------------------------------------===// + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating whether to emit a 32- or 64-bit ELF file. + bool is64Bit, isLittleEndian; + + /// doInitialization - Emit the file header and all of the global variables + /// for the module to the ELF file. + bool doInitialization(Module &M); + bool runOnMachineFunction(MachineFunction &MF); + + /// doFinalization - Now that the module has been completely processed, emit + /// the ELF file to 'O'. + bool doFinalization(Module &M); + + private: + /// Blob containing the Elf header + BinaryObject ElfHdr; + + /// SectionList - This is the list of sections that we have emitted to the + /// file. Once the file has been completely built, the section header table + /// is constructed from this info. + std::vector SectionList; + unsigned NumSections; // Always = SectionList.size() + + /// SectionLookup - This is a mapping from section name to section number in + /// the SectionList. Used to quickly gather the Section Index from MAI names + std::map SectionLookup; + + /// PendingGlobals - Globals not processed as symbols yet. + SetVector PendingGlobals; + + /// GblSymLookup - This is a mapping from global value to a symbol index + /// in the symbol table or private symbols list. This is useful since reloc + /// symbol references must be quickly mapped to their indices on the lists. + std::map GblSymLookup; + + /// PendingExternals - Externals not processed as symbols yet. + SetVector PendingExternals; + + /// ExtSymLookup - This is a mapping from externals to a symbol index + /// in the symbol table list. This is useful since reloc symbol references + /// must be quickly mapped to their symbol table indices. + std::map ExtSymLookup; + + /// SymbolList - This is the list of symbols emitted to the symbol table. + /// When the SymbolList is finally built, local symbols must be placed in + /// the beginning while non-locals at the end. + std::vector SymbolList; + + /// PrivateSyms - Record private symbols, every symbol here must never be + /// present in the SymbolList. + std::vector PrivateSyms; + + /// getSection - Return the section with the specified name, creating a new + /// section if one does not already exist. + ELFSection &getSection(const std::string &Name, unsigned Type, + unsigned Flags = 0, unsigned Align = 0) { + ELFSection *&SN = SectionLookup[Name]; + if (SN) return *SN; + + SectionList.push_back(new ELFSection(Name, isLittleEndian, is64Bit)); + SN = SectionList.back(); + SN->SectionIdx = NumSections++; + SN->Type = Type; + SN->Flags = Flags; + SN->Link = ELF::SHN_UNDEF; + SN->Align = Align; + return *SN; + } + + ELFSection &getNonExecStackSection() { + return getSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, 1); + } + + ELFSection &getSymbolTableSection() { + return getSection(".symtab", ELF::SHT_SYMTAB, 0); + } + + ELFSection &getStringTableSection() { + return getSection(".strtab", ELF::SHT_STRTAB, 0, 1); + } + + ELFSection &getSectionHeaderStringTableSection() { + return getSection(".shstrtab", ELF::SHT_STRTAB, 0, 1); + } + + ELFSection &getNullSection() { + return getSection("", ELF::SHT_NULL, 0); + } + + ELFSection &getDataSection(); + ELFSection &getBSSSection(); + ELFSection &getCtorSection(); + ELFSection &getDtorSection(); + ELFSection &getJumpTableSection(); + ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE); + ELFSection &getTextSection(const Function *F); + ELFSection &getRelocSection(ELFSection &S); + + // Helpers for obtaining ELF specific info. + unsigned getGlobalELFBinding(const GlobalValue *GV); + unsigned getGlobalELFType(const GlobalValue *GV); + unsigned getGlobalELFVisibility(const GlobalValue *GV); + + // AddPendingGlobalSymbol - Add a global to be processed and to + // the global symbol lookup, use a zero index because the table + // index will be determined later. + void AddPendingGlobalSymbol(const GlobalValue *GV, + bool AddToLookup = false); + + // AddPendingExternalSymbol - Add the external to be processed + // and to the external symbol lookup, use a zero index because + // the symbol table index will be determined later. + void AddPendingExternalSymbol(const char *External); + + // AddToSymbolList - Update the symbol lookup and If the symbol is + // private add it to PrivateSyms list, otherwise to SymbolList. + void AddToSymbolList(ELFSym *GblSym); + + // As we complete the ELF file, we need to update fields in the ELF header + // (e.g. the location of the section table). These members keep track of + // the offset in ELFHeader of these various pieces to update and other + // locations in the file. + unsigned ELFHdr_e_shoff_Offset; // e_shoff in ELF header. + unsigned ELFHdr_e_shstrndx_Offset; // e_shstrndx in ELF header. + unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header. + + private: + void EmitGlobal(const GlobalValue *GV); + void EmitGlobalConstant(const Constant *C, ELFSection &GblS); + void EmitGlobalConstantStruct(const ConstantStruct *CVS, + ELFSection &GblS); + void EmitGlobalConstantLargeInt(const ConstantInt *CI, ELFSection &S); + void EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, + ELFSection &GblS, int64_t Offset = 0); + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + void EmitXXStructorList(Constant *List, ELFSection &Xtor); + void EmitRelocations(); + void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA); + void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr); + void EmitSectionTableStringTable(); + void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym); + void EmitSymbolTable(); + void EmitStringTable(const std::string &ModuleName); + void OutputSectionsAndSectionTable(); + void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value, + unsigned Size); + unsigned SortSymbols(); + CstExprResTy ResolveConstantExpr(const Constant *CV); + }; +} + +#endif diff --git a/final/lib/CodeGen/EdgeBundles.cpp b/final/lib/CodeGen/EdgeBundles.cpp new file mode 100644 index 00000000000..aed8bc94799 --- /dev/null +++ b/final/lib/CodeGen/EdgeBundles.cpp @@ -0,0 +1,86 @@ +//===-------- EdgeBundles.cpp - Bundles of CFG edges ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the implementation of the EdgeBundles analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/EdgeBundles.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/GraphWriter.h" + +using namespace llvm; + +static cl::opt +ViewEdgeBundles("view-edge-bundles", cl::Hidden, + cl::desc("Pop up a window to show edge bundle graphs")); + +char EdgeBundles::ID = 0; + +INITIALIZE_PASS(EdgeBundles, "edge-bundles", "Bundle Machine CFG Edges", + /* cfg = */true, /* analysis = */ true) + +char &llvm::EdgeBundlesID = EdgeBundles::ID; + +void EdgeBundles::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool EdgeBundles::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + EC.clear(); + EC.grow(2 * MF->size()); + + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; + ++I) { + const MachineBasicBlock &MBB = *I; + unsigned OutE = 2 * MBB.getNumber() + 1; + // Join the outgoing bundle with the ingoing bundles of all successors. + for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), + SE = MBB.succ_end(); SI != SE; ++SI) + EC.join(OutE, 2 * (*SI)->getNumber()); + } + EC.compress(); + if (ViewEdgeBundles) + view(); + return false; +} + +/// view - Visualize the annotated bipartite CFG with Graphviz. +void EdgeBundles::view() const { + ViewGraph(*this, "EdgeBundles"); +} + +/// Specialize WriteGraph, the standard implementation won't work. +raw_ostream &llvm::WriteGraph(raw_ostream &O, const EdgeBundles &G, + bool ShortNames, + const std::string &Title) { + const MachineFunction *MF = G.getMachineFunction(); + + O << "digraph {\n"; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + unsigned BB = I->getNumber(); + O << "\t\"BB#" << BB << "\" [ shape=box ]\n" + << '\t' << G.getBundle(BB, false) << " -> \"BB#" << BB << "\"\n" + << "\t\"BB#" << BB << "\" -> " << G.getBundle(BB, true) << '\n'; + for (MachineBasicBlock::const_succ_iterator SI = I->succ_begin(), + SE = I->succ_end(); SI != SE; ++SI) + O << "\t\"BB#" << BB << "\" -> \"BB#" << (*SI)->getNumber() + << "\" [ color=lightgray ]\n"; + } + O << "}\n"; + return O; +} + + diff --git a/final/lib/CodeGen/ExpandISelPseudos.cpp b/final/lib/CodeGen/ExpandISelPseudos.cpp new file mode 100644 index 00000000000..b5ec303f5d9 --- /dev/null +++ b/final/lib/CodeGen/ExpandISelPseudos.cpp @@ -0,0 +1,82 @@ +//===-- llvm/CodeGen/ExpandISelPseudos.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Expand Psuedo-instructions produced by ISel. These are usually to allow +// the expansion to contain control flow, such as a conditional move +// implemented with a conditional branch and a phi, or an atomic operation +// implemented with a loop. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "expand-isel-pseudos" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace { + class ExpandISelPseudos : public MachineFunctionPass { + public: + static char ID; // Pass identification, replacement for typeid + ExpandISelPseudos() : MachineFunctionPass(ID) {} + + private: + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { + return "Expand ISel Pseudo-instructions"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + MachineFunctionPass::getAnalysisUsage(AU); + } + }; +} // end anonymous namespace + +char ExpandISelPseudos::ID = 0; +INITIALIZE_PASS(ExpandISelPseudos, "expand-isel-pseudos", + "Expand CodeGen Pseudo-instructions", false, false) + +FunctionPass *llvm::createExpandISelPseudosPass() { + return new ExpandISelPseudos(); +} + +bool ExpandISelPseudos::runOnMachineFunction(MachineFunction &MF) { + bool Changed = false; + const TargetLowering *TLI = MF.getTarget().getTargetLowering(); + + // Iterate through each instruction in the function, looking for pseudos. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + MachineBasicBlock *MBB = I; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); + MBBI != MBBE; ) { + MachineInstr *MI = MBBI++; + + // If MI is a pseudo, expand it. + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.usesCustomInsertionHook()) { + Changed = true; + MachineBasicBlock *NewMBB = + TLI->EmitInstrWithCustomInserter(MI, MBB); + // The expansion may involve new basic blocks. + if (NewMBB != MBB) { + MBB = NewMBB; + I = NewMBB; + MBBI = NewMBB->begin(); + MBBE = NewMBB->end(); + } + } + } + } + + return Changed; +} diff --git a/final/lib/CodeGen/GCMetadata.cpp b/final/lib/CodeGen/GCMetadata.cpp new file mode 100644 index 00000000000..d757cf409d5 --- /dev/null +++ b/final/lib/CodeGen/GCMetadata.cpp @@ -0,0 +1,213 @@ +//===-- GCMetadata.cpp - Garbage collector metadata -----------------------===// +// +// 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 GCFunctionInfo class and GCModuleInfo pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + + class Printer : public FunctionPass { + static char ID; + raw_ostream &OS; + + public: + explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {} + + + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + }; + + class Deleter : public FunctionPass { + static char ID; + + public: + Deleter(); + + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnFunction(Function &F); + bool doFinalization(Module &M); + }; + +} + +INITIALIZE_PASS(GCModuleInfo, "collector-metadata", + "Create Garbage Collector Module Metadata", false, false) + +// ----------------------------------------------------------------------------- + +GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) + : F(F), S(S), FrameSize(~0LL) {} + +GCFunctionInfo::~GCFunctionInfo() {} + +// ----------------------------------------------------------------------------- + +char GCModuleInfo::ID = 0; + +GCModuleInfo::GCModuleInfo() + : ImmutablePass(ID) { + initializeGCModuleInfoPass(*PassRegistry::getPassRegistry()); +} + +GCModuleInfo::~GCModuleInfo() { + clear(); +} + +GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M, + const std::string &Name) { + strategy_map_type::iterator NMI = StrategyMap.find(Name); + if (NMI != StrategyMap.end()) + return NMI->getValue(); + + for (GCRegistry::iterator I = GCRegistry::begin(), + E = GCRegistry::end(); I != E; ++I) { + if (Name == I->getName()) { + GCStrategy *S = I->instantiate(); + S->M = M; + S->Name = Name; + StrategyMap.GetOrCreateValue(Name).setValue(S); + StrategyList.push_back(S); + return S; + } + } + + dbgs() << "unsupported GC: " << Name << "\n"; + llvm_unreachable(0); +} + +GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { + assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); + assert(F.hasGC()); + + finfo_map_type::iterator I = FInfoMap.find(&F); + if (I != FInfoMap.end()) + return *I->second; + + GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC()); + GCFunctionInfo *GFI = S->insertFunctionInfo(F); + FInfoMap[&F] = GFI; + return *GFI; +} + +void GCModuleInfo::clear() { + FInfoMap.clear(); + StrategyMap.clear(); + + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + StrategyList.clear(); +} + +// ----------------------------------------------------------------------------- + +char Printer::ID = 0; + +FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) { + return new Printer(OS); +} + + +const char *Printer::getPassName() const { + return "Print Garbage Collector Information"; +} + +void Printer::getAnalysisUsage(AnalysisUsage &AU) const { + FunctionPass::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired(); +} + +static const char *DescKind(GC::PointKind Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown GC point kind"); + case GC::Loop: return "loop"; + case GC::Return: return "return"; + case GC::PreCall: return "pre-call"; + case GC::PostCall: return "post-call"; + } +} + +bool Printer::runOnFunction(Function &F) { + if (F.hasGC()) return false; + + GCFunctionInfo *FD = &getAnalysis().getFunctionInfo(F); + + OS << "GC roots for " << FD->getFunction().getNameStr() << ":\n"; + for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(), + RE = FD->roots_end(); RI != RE; ++RI) + OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n"; + + OS << "GC safe points for " << FD->getFunction().getNameStr() << ":\n"; + for (GCFunctionInfo::iterator PI = FD->begin(), + PE = FD->end(); PI != PE; ++PI) { + + OS << "\t" << PI->Label->getName() << ": " + << DescKind(PI->Kind) << ", live = {"; + + for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI), + RE = FD->live_end(PI);;) { + OS << " " << RI->Num; + if (++RI == RE) + break; + OS << ","; + } + + OS << " }\n"; + } + + return false; +} + +// ----------------------------------------------------------------------------- + +char Deleter::ID = 0; + +FunctionPass *llvm::createGCInfoDeleter() { + return new Deleter(); +} + +Deleter::Deleter() : FunctionPass(ID) {} + +const char *Deleter::getPassName() const { + return "Delete Garbage Collector Information"; +} + +void Deleter::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + +bool Deleter::runOnFunction(Function &MF) { + return false; +} + +bool Deleter::doFinalization(Module &M) { + GCModuleInfo *GMI = getAnalysisIfAvailable(); + assert(GMI && "Deleter didn't require GCModuleInfo?!"); + GMI->clear(); + return false; +} diff --git a/final/lib/CodeGen/GCMetadataPrinter.cpp b/final/lib/CodeGen/GCMetadataPrinter.cpp new file mode 100644 index 00000000000..f80e9ced0bc --- /dev/null +++ b/final/lib/CodeGen/GCMetadataPrinter.cpp @@ -0,0 +1,27 @@ +//===-- GCMetadataPrinter.cpp - Garbage collection infrastructure ---------===// +// +// 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 abstract base class GCMetadataPrinter. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCMetadataPrinter.h" +using namespace llvm; + +GCMetadataPrinter::GCMetadataPrinter() { } + +GCMetadataPrinter::~GCMetadataPrinter() { } + +void GCMetadataPrinter::beginAssembly(AsmPrinter &AP) { + // Default is no action. +} + +void GCMetadataPrinter::finishAssembly(AsmPrinter &AP) { + // Default is no action. +} diff --git a/final/lib/CodeGen/GCStrategy.cpp b/final/lib/CodeGen/GCStrategy.cpp new file mode 100644 index 00000000000..766c6ee542a --- /dev/null +++ b/final/lib/CodeGen/GCStrategy.cpp @@ -0,0 +1,416 @@ +//===-- GCStrategy.cpp - Garbage collection infrastructure -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements target- and collector-independent garbage collection +// infrastructure. +// +// MachineCodeAnalysis identifies the GC safe points in the machine code. Roots +// are identified in SelectionDAGISel. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { + + /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or + /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as + /// directed by the GCStrategy. It also performs automatic root initialization + /// and custom intrinsic lowering. + class LowerIntrinsics : public FunctionPass { + static bool NeedsDefaultLoweringPass(const GCStrategy &C); + static bool NeedsCustomLoweringPass(const GCStrategy &C); + static bool CouldBecomeSafePoint(Instruction *I); + bool PerformDefaultLowering(Function &F, GCStrategy &Coll); + static bool InsertRootInitializers(Function &F, + AllocaInst **Roots, unsigned Count); + + public: + static char ID; + + LowerIntrinsics(); + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + }; + + + /// MachineCodeAnalysis - This is a target-independent pass over the machine + /// function representation to identify safe points for the garbage collector + /// in the machine code. It inserts labels at safe points and populates a + /// GCMetadata record for each function. + class MachineCodeAnalysis : public MachineFunctionPass { + const TargetMachine *TM; + GCFunctionInfo *FI; + MachineModuleInfo *MMI; + const TargetInstrInfo *TII; + + void FindSafePoints(MachineFunction &MF); + void VisitCallPoint(MachineBasicBlock::iterator MI); + MCSymbol *InsertLabel(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + DebugLoc DL) const; + + void FindStackOffsets(MachineFunction &MF); + + public: + static char ID; + + MachineCodeAnalysis(); + const char *getPassName() const; + void getAnalysisUsage(AnalysisUsage &AU) const; + + bool runOnMachineFunction(MachineFunction &MF); + }; + +} + +// ----------------------------------------------------------------------------- + +GCStrategy::GCStrategy() : + NeededSafePoints(0), + CustomReadBarriers(false), + CustomWriteBarriers(false), + CustomRoots(false), + InitRoots(true), + UsesMetadata(false) +{} + +GCStrategy::~GCStrategy() { + for (iterator I = begin(), E = end(); I != E; ++I) + delete *I; + + Functions.clear(); +} + +bool GCStrategy::initializeCustomLowering(Module &M) { return false; } + +bool GCStrategy::performCustomLowering(Function &F) { + dbgs() << "gc " << getName() << " must override performCustomLowering.\n"; + llvm_unreachable(0); + return 0; +} + +GCFunctionInfo *GCStrategy::insertFunctionInfo(const Function &F) { + GCFunctionInfo *FI = new GCFunctionInfo(F, *this); + Functions.push_back(FI); + return FI; +} + +// ----------------------------------------------------------------------------- + +INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", + false, false) +INITIALIZE_PASS_DEPENDENCY(GCModuleInfo) +INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false) + +FunctionPass *llvm::createGCLoweringPass() { + return new LowerIntrinsics(); +} + +char LowerIntrinsics::ID = 0; + +LowerIntrinsics::LowerIntrinsics() + : FunctionPass(ID) { + initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry()); + } + +const char *LowerIntrinsics::getPassName() const { + return "Lower Garbage Collection Instructions"; +} + +void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addPreserved(); +} + +/// doInitialization - If this module uses the GC intrinsics, find them now. +bool LowerIntrinsics::doInitialization(Module &M) { + // FIXME: This is rather antisocial in the context of a JIT since it performs + // work against the entire module. But this cannot be done at + // runFunction time (initializeCustomLowering likely needs to change + // the module). + GCModuleInfo *MI = getAnalysisIfAvailable(); + assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?"); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isDeclaration() && I->hasGC()) + MI->getFunctionInfo(*I); // Instantiate the GC strategy. + + bool MadeChange = false; + for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + if (NeedsCustomLoweringPass(**I)) + if ((*I)->initializeCustomLowering(M)) + MadeChange = true; + + return MadeChange; +} + +bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, + unsigned Count) { + // Scroll past alloca instructions. + BasicBlock::iterator IP = F.getEntryBlock().begin(); + while (isa(IP)) ++IP; + + // Search for initializers in the initial BB. + SmallPtrSet InitedRoots; + for (; !CouldBecomeSafePoint(IP); ++IP) + if (StoreInst *SI = dyn_cast(IP)) + if (AllocaInst *AI = + dyn_cast(SI->getOperand(1)->stripPointerCasts())) + InitedRoots.insert(AI); + + // Add root initializers. + bool MadeChange = false; + + for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) + if (!InitedRoots.count(*I)) { + StoreInst* SI = new StoreInst(ConstantPointerNull::get(cast( + cast((*I)->getType())->getElementType())), + *I); + SI->insertAfter(*I); + MadeChange = true; + } + + return MadeChange; +} + +bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &C) { + // Default lowering is necessary only if read or write barriers have a default + // action. The default for roots is no action. + return !C.customWriteBarrier() + || !C.customReadBarrier() + || C.initializeRoots(); +} + +bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) { + // Custom lowering is only necessary if enabled for some action. + return C.customWriteBarrier() + || C.customReadBarrier() + || C.customRoots(); +} + +/// CouldBecomeSafePoint - Predicate to conservatively determine whether the +/// instruction could introduce a safe point. +bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) { + // The natural definition of instructions which could introduce safe points + // are: + // + // - call, invoke (AfterCall, BeforeCall) + // - phis (Loops) + // - invoke, ret, unwind (Exit) + // + // However, instructions as seemingly inoccuous as arithmetic can become + // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead + // it is necessary to take a conservative approach. + + if (isa(I) || isa(I) || + isa(I) || isa(I)) + return false; + + // llvm.gcroot is safe because it doesn't do anything at runtime. + if (CallInst *CI = dyn_cast(I)) + if (Function *F = CI->getCalledFunction()) + if (unsigned IID = F->getIntrinsicID()) + if (IID == Intrinsic::gcroot) + return false; + + return true; +} + +/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores. +/// Leave gcroot intrinsics; the code generator needs to see those. +bool LowerIntrinsics::runOnFunction(Function &F) { + // Quick exit for functions that do not use GC. + if (!F.hasGC()) + return false; + + GCFunctionInfo &FI = getAnalysis().getFunctionInfo(F); + GCStrategy &S = FI.getStrategy(); + + bool MadeChange = false; + + if (NeedsDefaultLoweringPass(S)) + MadeChange |= PerformDefaultLowering(F, S); + + bool UseCustomLoweringPass = NeedsCustomLoweringPass(S); + if (UseCustomLoweringPass) + MadeChange |= S.performCustomLowering(F); + + // Custom lowering may modify the CFG, so dominators must be recomputed. + if (UseCustomLoweringPass) { + if (DominatorTree *DT = getAnalysisIfAvailable()) + DT->DT->recalculate(F); + } + + return MadeChange; +} + +bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { + bool LowerWr = !S.customWriteBarrier(); + bool LowerRd = !S.customReadBarrier(); + bool InitRoots = S.initializeRoots(); + + SmallVector Roots; + + bool MadeChange = false; + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) { + if (IntrinsicInst *CI = dyn_cast(II++)) { + Function *F = CI->getCalledFunction(); + switch (F->getIntrinsicID()) { + case Intrinsic::gcwrite: + if (LowerWr) { + // Replace a write barrier with a simple store. + Value *St = new StoreInst(CI->getArgOperand(0), + CI->getArgOperand(2), CI); + CI->replaceAllUsesWith(St); + CI->eraseFromParent(); + } + break; + case Intrinsic::gcread: + if (LowerRd) { + // Replace a read barrier with a simple load. + Value *Ld = new LoadInst(CI->getArgOperand(1), "", CI); + Ld->takeName(CI); + CI->replaceAllUsesWith(Ld); + CI->eraseFromParent(); + } + break; + case Intrinsic::gcroot: + if (InitRoots) { + // Initialize the GC root, but do not delete the intrinsic. The + // backend needs the intrinsic to flag the stack slot. + Roots.push_back(cast( + CI->getArgOperand(0)->stripPointerCasts())); + } + break; + default: + continue; + } + + MadeChange = true; + } + } + } + + if (Roots.size()) + MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size()); + + return MadeChange; +} + +// ----------------------------------------------------------------------------- + +FunctionPass *llvm::createGCMachineCodeAnalysisPass() { + return new MachineCodeAnalysis(); +} + +char MachineCodeAnalysis::ID = 0; + +MachineCodeAnalysis::MachineCodeAnalysis() + : MachineFunctionPass(ID) {} + +const char *MachineCodeAnalysis::getPassName() const { + return "Analyze Machine Code For Garbage Collection"; +} + +void MachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + MachineFunctionPass::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); +} + +MCSymbol *MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + DebugLoc DL) const { + MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol(); + BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label); + return Label; +} + +void MachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) { + // Find the return address (next instruction), too, so as to bracket the call + // instruction. + MachineBasicBlock::iterator RAI = CI; + ++RAI; + + if (FI->getStrategy().needsSafePoint(GC::PreCall)) { + MCSymbol* Label = InsertLabel(*CI->getParent(), CI, CI->getDebugLoc()); + FI->addSafePoint(GC::PreCall, Label, CI->getDebugLoc()); + } + + if (FI->getStrategy().needsSafePoint(GC::PostCall)) { + MCSymbol* Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc()); + FI->addSafePoint(GC::PostCall, Label, CI->getDebugLoc()); + } +} + +void MachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { + for (MachineFunction::iterator BBI = MF.begin(), + BBE = MF.end(); BBI != BBE; ++BBI) + for (MachineBasicBlock::iterator MI = BBI->begin(), + ME = BBI->end(); MI != ME; ++MI) + if (MI->getDesc().isCall()) + VisitCallPoint(MI); +} + +void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { + const TargetFrameLowering *TFI = TM->getFrameLowering(); + assert(TFI && "TargetRegisterInfo not available!"); + + for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(), + RE = FI->roots_end(); RI != RE; ++RI) + RI->StackOffset = TFI->getFrameIndexOffset(MF, RI->Num); +} + +bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { + // Quick exit for functions that do not use GC. + if (!MF.getFunction()->hasGC()) + return false; + + FI = &getAnalysis().getFunctionInfo(*MF.getFunction()); + if (!FI->getStrategy().needsSafePoints()) + return false; + + TM = &MF.getTarget(); + MMI = &getAnalysis(); + TII = TM->getInstrInfo(); + + // Find the size of the stack frame. + FI->setFrameSize(MF.getFrameInfo()->getStackSize()); + + // Find all safe points. + FindSafePoints(MF); + + // Find the stack offsets for all roots. + FindStackOffsets(MF); + + return false; +} diff --git a/final/lib/CodeGen/IfConversion.cpp b/final/lib/CodeGen/IfConversion.cpp new file mode 100644 index 00000000000..db53b0473a9 --- /dev/null +++ b/final/lib/CodeGen/IfConversion.cpp @@ -0,0 +1,1528 @@ +//===-- IfConversion.cpp - Machine code if conversion pass. ---------------===// +// +// 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 machine instruction level if-conversion pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ifcvt" +#include "BranchFolding.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +// Hidden options for help debugging. +static cl::opt IfCvtFnStart("ifcvt-fn-start", cl::init(-1), cl::Hidden); +static cl::opt IfCvtFnStop("ifcvt-fn-stop", cl::init(-1), cl::Hidden); +static cl::opt IfCvtLimit("ifcvt-limit", cl::init(-1), cl::Hidden); +static cl::opt DisableSimple("disable-ifcvt-simple", + cl::init(false), cl::Hidden); +static cl::opt DisableSimpleF("disable-ifcvt-simple-false", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangle("disable-ifcvt-triangle", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleR("disable-ifcvt-triangle-rev", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleF("disable-ifcvt-triangle-false", + cl::init(false), cl::Hidden); +static cl::opt DisableTriangleFR("disable-ifcvt-triangle-false-rev", + cl::init(false), cl::Hidden); +static cl::opt DisableDiamond("disable-ifcvt-diamond", + cl::init(false), cl::Hidden); +static cl::opt IfCvtBranchFold("ifcvt-branch-fold", + cl::init(true), cl::Hidden); + +STATISTIC(NumSimple, "Number of simple if-conversions performed"); +STATISTIC(NumSimpleFalse, "Number of simple (F) if-conversions performed"); +STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); +STATISTIC(NumTriangleRev, "Number of triangle (R) if-conversions performed"); +STATISTIC(NumTriangleFalse,"Number of triangle (F) if-conversions performed"); +STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed"); +STATISTIC(NumDiamonds, "Number of diamond if-conversions performed"); +STATISTIC(NumIfConvBBs, "Number of if-converted blocks"); +STATISTIC(NumDupBBs, "Number of duplicated blocks"); + +namespace { + class IfConverter : public MachineFunctionPass { + enum IfcvtKind { + ICNotClassfied, // BB data valid, but not classified. + ICSimpleFalse, // Same as ICSimple, but on the false path. + ICSimple, // BB is entry of an one split, no rejoin sub-CFG. + ICTriangleFRev, // Same as ICTriangleFalse, but false path rev condition. + ICTriangleRev, // Same as ICTriangle, but true path rev condition. + ICTriangleFalse, // Same as ICTriangle, but on the false path. + ICTriangle, // BB is entry of a triangle sub-CFG. + ICDiamond // BB is entry of a diamond sub-CFG. + }; + + /// BBInfo - One per MachineBasicBlock, this is used to cache the result + /// if-conversion feasibility analysis. This includes results from + /// TargetInstrInfo::AnalyzeBranch() (i.e. TBB, FBB, and Cond), and its + /// classification, and common tail block of its successors (if it's a + /// diamond shape), its size, whether it's predicable, and whether any + /// instruction can clobber the 'would-be' predicate. + /// + /// IsDone - True if BB is not to be considered for ifcvt. + /// IsBeingAnalyzed - True if BB is currently being analyzed. + /// IsAnalyzed - True if BB has been analyzed (info is still valid). + /// IsEnqueued - True if BB has been enqueued to be ifcvt'ed. + /// IsBrAnalyzable - True if AnalyzeBranch() returns false. + /// HasFallThrough - True if BB may fallthrough to the following BB. + /// IsUnpredicable - True if BB is known to be unpredicable. + /// ClobbersPred - True if BB could modify predicates (e.g. has + /// cmp, call, etc.) + /// NonPredSize - Number of non-predicated instructions. + /// ExtraCost - Extra cost for multi-cycle instructions. + /// ExtraCost2 - Some instructions are slower when predicated + /// BB - Corresponding MachineBasicBlock. + /// TrueBB / FalseBB- See AnalyzeBranch(). + /// BrCond - Conditions for end of block conditional branches. + /// Predicate - Predicate used in the BB. + struct BBInfo { + bool IsDone : 1; + bool IsBeingAnalyzed : 1; + bool IsAnalyzed : 1; + bool IsEnqueued : 1; + bool IsBrAnalyzable : 1; + bool HasFallThrough : 1; + bool IsUnpredicable : 1; + bool CannotBeCopied : 1; + bool ClobbersPred : 1; + unsigned NonPredSize; + unsigned ExtraCost; + unsigned ExtraCost2; + MachineBasicBlock *BB; + MachineBasicBlock *TrueBB; + MachineBasicBlock *FalseBB; + SmallVector BrCond; + SmallVector Predicate; + BBInfo() : IsDone(false), IsBeingAnalyzed(false), + IsAnalyzed(false), IsEnqueued(false), IsBrAnalyzable(false), + HasFallThrough(false), IsUnpredicable(false), + CannotBeCopied(false), ClobbersPred(false), NonPredSize(0), + ExtraCost(0), ExtraCost2(0), BB(0), TrueBB(0), FalseBB(0) {} + }; + + /// IfcvtToken - Record information about pending if-conversions to attempt: + /// BBI - Corresponding BBInfo. + /// Kind - Type of block. See IfcvtKind. + /// NeedSubsumption - True if the to-be-predicated BB has already been + /// predicated. + /// NumDups - Number of instructions that would be duplicated due + /// to this if-conversion. (For diamonds, the number of + /// identical instructions at the beginnings of both + /// paths). + /// NumDups2 - For diamonds, the number of identical instructions + /// at the ends of both paths. + struct IfcvtToken { + BBInfo &BBI; + IfcvtKind Kind; + bool NeedSubsumption; + unsigned NumDups; + unsigned NumDups2; + IfcvtToken(BBInfo &b, IfcvtKind k, bool s, unsigned d, unsigned d2 = 0) + : BBI(b), Kind(k), NeedSubsumption(s), NumDups(d), NumDups2(d2) {} + }; + + /// Roots - Basic blocks that do not have successors. These are the starting + /// points of Graph traversal. + std::vector Roots; + + /// BBAnalysis - Results of if-conversion feasibility analysis indexed by + /// basic block number. + std::vector BBAnalysis; + + const TargetLowering *TLI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const InstrItineraryData *InstrItins; + const MachineLoopInfo *MLI; + bool MadeChange; + int FnNum; + public: + static char ID; + IfConverter() : MachineFunctionPass(ID), FnNum(-1) { + initializeIfConverterPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "If Converter"; } + + private: + bool ReverseBranchCondition(BBInfo &BBI); + bool ValidSimple(BBInfo &TrueBBI, unsigned &Dups, + float Prediction, float Confidence) const; + bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch, unsigned &Dups, + float Prediction, float Confidence) const; + bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, + unsigned &Dups1, unsigned &Dups2) const; + void ScanInstructions(BBInfo &BBI); + BBInfo &AnalyzeBlock(MachineBasicBlock *BB, + std::vector &Tokens); + bool FeasibilityAnalysis(BBInfo &BBI, SmallVectorImpl &Cond, + bool isTriangle = false, bool RevBranch = false); + void AnalyzeBlocks(MachineFunction &MF, std::vector &Tokens); + void InvalidatePreds(MachineBasicBlock *BB); + void RemoveExtraEdges(BBInfo &BBI); + bool IfConvertSimple(BBInfo &BBI, IfcvtKind Kind); + bool IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind); + bool IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, + unsigned NumDups1, unsigned NumDups2); + void PredicateBlock(BBInfo &BBI, + MachineBasicBlock::iterator E, + SmallVectorImpl &Cond, + SmallSet &Redefs); + void CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, + SmallVectorImpl &Cond, + SmallSet &Redefs, + bool IgnoreBr = false); + void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges = true); + + bool MeetIfcvtSizeLimit(MachineBasicBlock &BB, + unsigned Cycle, unsigned Extra, + float Prediction, float Confidence) const { + return Cycle > 0 && TII->isProfitableToIfCvt(BB, Cycle, Extra, + Prediction, Confidence); + } + + bool MeetIfcvtSizeLimit(MachineBasicBlock &TBB, + unsigned TCycle, unsigned TExtra, + MachineBasicBlock &FBB, + unsigned FCycle, unsigned FExtra, + float Prediction, float Confidence) const { + return TCycle > 0 && FCycle > 0 && + TII->isProfitableToIfCvt(TBB, TCycle, TExtra, FBB, FCycle, FExtra, + Prediction, Confidence); + } + + // blockAlwaysFallThrough - Block ends without a terminator. + bool blockAlwaysFallThrough(BBInfo &BBI) const { + return BBI.IsBrAnalyzable && BBI.TrueBB == NULL; + } + + // IfcvtTokenCmp - Used to sort if-conversion candidates. + static bool IfcvtTokenCmp(IfcvtToken *C1, IfcvtToken *C2) { + int Incr1 = (C1->Kind == ICDiamond) + ? -(int)(C1->NumDups + C1->NumDups2) : (int)C1->NumDups; + int Incr2 = (C2->Kind == ICDiamond) + ? -(int)(C2->NumDups + C2->NumDups2) : (int)C2->NumDups; + if (Incr1 > Incr2) + return true; + else if (Incr1 == Incr2) { + // Favors subsumption. + if (C1->NeedSubsumption == false && C2->NeedSubsumption == true) + return true; + else if (C1->NeedSubsumption == C2->NeedSubsumption) { + // Favors diamond over triangle, etc. + if ((unsigned)C1->Kind < (unsigned)C2->Kind) + return true; + else if (C1->Kind == C2->Kind) + return C1->BBI.BB->getNumber() < C2->BBI.BB->getNumber(); + } + } + return false; + } + }; + + char IfConverter::ID = 0; +} + +INITIALIZE_PASS_BEGIN(IfConverter, "if-converter", "If Converter", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false) + +FunctionPass *llvm::createIfConverterPass() { return new IfConverter(); } + +bool IfConverter::runOnMachineFunction(MachineFunction &MF) { + TLI = MF.getTarget().getTargetLowering(); + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + MLI = &getAnalysis(); + InstrItins = MF.getTarget().getInstrItineraryData(); + if (!TII) return false; + + // Tail merge tend to expose more if-conversion opportunities. + BranchFolder BF(true); + bool BFChange = BF.OptimizeFunction(MF, TII, + MF.getTarget().getRegisterInfo(), + getAnalysisIfAvailable()); + + DEBUG(dbgs() << "\nIfcvt: function (" << ++FnNum << ") \'" + << MF.getFunction()->getName() << "\'"); + + if (FnNum < IfCvtFnStart || (IfCvtFnStop != -1 && FnNum > IfCvtFnStop)) { + DEBUG(dbgs() << " skipped\n"); + return false; + } + DEBUG(dbgs() << "\n"); + + MF.RenumberBlocks(); + BBAnalysis.resize(MF.getNumBlockIDs()); + + // Look for root nodes, i.e. blocks without successors. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + if (I->succ_empty()) + Roots.push_back(I); + + std::vector Tokens; + MadeChange = false; + unsigned NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + + NumTriangleRev + NumTriangleFalse + NumTriangleFRev + NumDiamonds; + while (IfCvtLimit == -1 || (int)NumIfCvts < IfCvtLimit) { + // Do an initial analysis for each basic block and find all the potential + // candidates to perform if-conversion. + bool Change = false; + AnalyzeBlocks(MF, Tokens); + while (!Tokens.empty()) { + IfcvtToken *Token = Tokens.back(); + Tokens.pop_back(); + BBInfo &BBI = Token->BBI; + IfcvtKind Kind = Token->Kind; + unsigned NumDups = Token->NumDups; + unsigned NumDups2 = Token->NumDups2; + + delete Token; + + // If the block has been evicted out of the queue or it has already been + // marked dead (due to it being predicated), then skip it. + if (BBI.IsDone) + BBI.IsEnqueued = false; + if (!BBI.IsEnqueued) + continue; + + BBI.IsEnqueued = false; + + bool RetVal = false; + switch (Kind) { + default: assert(false && "Unexpected!"); + break; + case ICSimple: + case ICSimpleFalse: { + bool isFalse = Kind == ICSimpleFalse; + if ((isFalse && DisableSimpleF) || (!isFalse && DisableSimple)) break; + DEBUG(dbgs() << "Ifcvt (Simple" << (Kind == ICSimpleFalse ? + " false" : "") + << "): BB#" << BBI.BB->getNumber() << " (" + << ((Kind == ICSimpleFalse) + ? BBI.FalseBB->getNumber() + : BBI.TrueBB->getNumber()) << ") "); + RetVal = IfConvertSimple(BBI, Kind); + DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) { + if (isFalse) ++NumSimpleFalse; + else ++NumSimple; + } + break; + } + case ICTriangle: + case ICTriangleRev: + case ICTriangleFalse: + case ICTriangleFRev: { + bool isFalse = Kind == ICTriangleFalse; + bool isRev = (Kind == ICTriangleRev || Kind == ICTriangleFRev); + if (DisableTriangle && !isFalse && !isRev) break; + if (DisableTriangleR && !isFalse && isRev) break; + if (DisableTriangleF && isFalse && !isRev) break; + if (DisableTriangleFR && isFalse && isRev) break; + DEBUG(dbgs() << "Ifcvt (Triangle"); + if (isFalse) + DEBUG(dbgs() << " false"); + if (isRev) + DEBUG(dbgs() << " rev"); + DEBUG(dbgs() << "): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" + << BBI.FalseBB->getNumber() << ") "); + RetVal = IfConvertTriangle(BBI, Kind); + DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) { + if (isFalse) { + if (isRev) ++NumTriangleFRev; + else ++NumTriangleFalse; + } else { + if (isRev) ++NumTriangleRev; + else ++NumTriangle; + } + } + break; + } + case ICDiamond: { + if (DisableDiamond) break; + DEBUG(dbgs() << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" + << BBI.FalseBB->getNumber() << ") "); + RetVal = IfConvertDiamond(BBI, Kind, NumDups, NumDups2); + DEBUG(dbgs() << (RetVal ? "succeeded!" : "failed!") << "\n"); + if (RetVal) ++NumDiamonds; + break; + } + } + + Change |= RetVal; + + NumIfCvts = NumSimple + NumSimpleFalse + NumTriangle + NumTriangleRev + + NumTriangleFalse + NumTriangleFRev + NumDiamonds; + if (IfCvtLimit != -1 && (int)NumIfCvts >= IfCvtLimit) + break; + } + + if (!Change) + break; + MadeChange |= Change; + } + + // Delete tokens in case of early exit. + while (!Tokens.empty()) { + IfcvtToken *Token = Tokens.back(); + Tokens.pop_back(); + delete Token; + } + + Tokens.clear(); + Roots.clear(); + BBAnalysis.clear(); + + if (MadeChange && IfCvtBranchFold) { + BranchFolder BF(false); + BF.OptimizeFunction(MF, TII, + MF.getTarget().getRegisterInfo(), + getAnalysisIfAvailable()); + } + + MadeChange |= BFChange; + return MadeChange; +} + +/// findFalseBlock - BB has a fallthrough. Find its 'false' successor given +/// its 'true' successor. +static MachineBasicBlock *findFalseBlock(MachineBasicBlock *BB, + MachineBasicBlock *TrueBB) { + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + E = BB->succ_end(); SI != E; ++SI) { + MachineBasicBlock *SuccBB = *SI; + if (SuccBB != TrueBB) + return SuccBB; + } + return NULL; +} + +/// ReverseBranchCondition - Reverse the condition of the end of the block +/// branch. Swap block's 'true' and 'false' successors. +bool IfConverter::ReverseBranchCondition(BBInfo &BBI) { + DebugLoc dl; // FIXME: this is nowhere + if (!TII->ReverseBranchCondition(BBI.BrCond)) { + TII->RemoveBranch(*BBI.BB); + TII->InsertBranch(*BBI.BB, BBI.FalseBB, BBI.TrueBB, BBI.BrCond, dl); + std::swap(BBI.TrueBB, BBI.FalseBB); + return true; + } + return false; +} + +/// getNextBlock - Returns the next block in the function blocks ordering. If +/// it is the end, returns NULL. +static inline MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator E = BB->getParent()->end(); + if (++I == E) + return NULL; + return I; +} + +/// ValidSimple - Returns true if the 'true' block (along with its +/// predecessor) forms a valid simple shape for ifcvt. It also returns the +/// number of instructions that the ifcvt would need to duplicate if performed +/// in Dups. +bool IfConverter::ValidSimple(BBInfo &TrueBBI, unsigned &Dups, + float Prediction, float Confidence) const { + Dups = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone) + return false; + + if (TrueBBI.IsBrAnalyzable) + return false; + + if (TrueBBI.BB->pred_size() > 1) { + if (TrueBBI.CannotBeCopied || + !TII->isProfitableToDupForIfCvt(*TrueBBI.BB, TrueBBI.NonPredSize, + Prediction, Confidence)) + return false; + Dups = TrueBBI.NonPredSize; + } + + return true; +} + +/// ValidTriangle - Returns true if the 'true' and 'false' blocks (along +/// with their common predecessor) forms a valid triangle shape for ifcvt. +/// If 'FalseBranch' is true, it checks if 'true' block's false branch +/// branches to the 'false' block rather than the other way around. It also +/// returns the number of instructions that the ifcvt would need to duplicate +/// if performed in 'Dups'. +bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch, unsigned &Dups, + float Prediction, float Confidence) const { + Dups = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone) + return false; + + if (TrueBBI.BB->pred_size() > 1) { + if (TrueBBI.CannotBeCopied) + return false; + + unsigned Size = TrueBBI.NonPredSize; + if (TrueBBI.IsBrAnalyzable) { + if (TrueBBI.TrueBB && TrueBBI.BrCond.empty()) + // Ends with an unconditional branch. It will be removed. + --Size; + else { + MachineBasicBlock *FExit = FalseBranch + ? TrueBBI.TrueBB : TrueBBI.FalseBB; + if (FExit) + // Require a conditional branch + ++Size; + } + } + if (!TII->isProfitableToDupForIfCvt(*TrueBBI.BB, Size, + Prediction, Confidence)) + return false; + Dups = Size; + } + + MachineBasicBlock *TExit = FalseBranch ? TrueBBI.FalseBB : TrueBBI.TrueBB; + if (!TExit && blockAlwaysFallThrough(TrueBBI)) { + MachineFunction::iterator I = TrueBBI.BB; + if (++I == TrueBBI.BB->getParent()->end()) + return false; + TExit = I; + } + return TExit && TExit == FalseBBI.BB; +} + +/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along +/// with their common predecessor) forms a valid diamond shape for ifcvt. +bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI, + unsigned &Dups1, unsigned &Dups2) const { + Dups1 = Dups2 = 0; + if (TrueBBI.IsBeingAnalyzed || TrueBBI.IsDone || + FalseBBI.IsBeingAnalyzed || FalseBBI.IsDone) + return false; + + MachineBasicBlock *TT = TrueBBI.TrueBB; + MachineBasicBlock *FT = FalseBBI.TrueBB; + + if (!TT && blockAlwaysFallThrough(TrueBBI)) + TT = getNextBlock(TrueBBI.BB); + if (!FT && blockAlwaysFallThrough(FalseBBI)) + FT = getNextBlock(FalseBBI.BB); + if (TT != FT) + return false; + if (TT == NULL && (TrueBBI.IsBrAnalyzable || FalseBBI.IsBrAnalyzable)) + return false; + if (TrueBBI.BB->pred_size() > 1 || FalseBBI.BB->pred_size() > 1) + return false; + + // FIXME: Allow true block to have an early exit? + if (TrueBBI.FalseBB || FalseBBI.FalseBB || + (TrueBBI.ClobbersPred && FalseBBI.ClobbersPred)) + return false; + + // Count duplicate instructions at the beginning of the true and false blocks. + MachineBasicBlock::iterator TIB = TrueBBI.BB->begin(); + MachineBasicBlock::iterator FIB = FalseBBI.BB->begin(); + MachineBasicBlock::iterator TIE = TrueBBI.BB->end(); + MachineBasicBlock::iterator FIE = FalseBBI.BB->end(); + while (TIB != TIE && FIB != FIE) { + // Skip dbg_value instructions. These do not count. + if (TIB->isDebugValue()) { + while (TIB != TIE && TIB->isDebugValue()) + ++TIB; + if (TIB == TIE) + break; + } + if (FIB->isDebugValue()) { + while (FIB != FIE && FIB->isDebugValue()) + ++FIB; + if (FIB == FIE) + break; + } + if (!TIB->isIdenticalTo(FIB)) + break; + ++Dups1; + ++TIB; + ++FIB; + } + + // Now, in preparation for counting duplicate instructions at the ends of the + // blocks, move the end iterators up past any branch instructions. + while (TIE != TIB) { + --TIE; + if (!TIE->getDesc().isBranch()) + break; + } + while (FIE != FIB) { + --FIE; + if (!FIE->getDesc().isBranch()) + break; + } + + // If Dups1 includes all of a block, then don't count duplicate + // instructions at the end of the blocks. + if (TIB == TIE || FIB == FIE) + return true; + + // Count duplicate instructions at the ends of the blocks. + while (TIE != TIB && FIE != FIB) { + // Skip dbg_value instructions. These do not count. + if (TIE->isDebugValue()) { + while (TIE != TIB && TIE->isDebugValue()) + --TIE; + if (TIE == TIB) + break; + } + if (FIE->isDebugValue()) { + while (FIE != FIB && FIE->isDebugValue()) + --FIE; + if (FIE == FIB) + break; + } + if (!TIE->isIdenticalTo(FIE)) + break; + ++Dups2; + --TIE; + --FIE; + } + + return true; +} + +/// ScanInstructions - Scan all the instructions in the block to determine if +/// the block is predicable. In most cases, that means all the instructions +/// in the block are isPredicable(). Also checks if the block contains any +/// instruction which can clobber a predicate (e.g. condition code register). +/// If so, the block is not predicable unless it's the last instruction. +void IfConverter::ScanInstructions(BBInfo &BBI) { + if (BBI.IsDone) + return; + + bool AlreadyPredicated = BBI.Predicate.size() > 0; + // First analyze the end of BB branches. + BBI.TrueBB = BBI.FalseBB = NULL; + BBI.BrCond.clear(); + BBI.IsBrAnalyzable = + !TII->AnalyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.HasFallThrough = BBI.IsBrAnalyzable && BBI.FalseBB == NULL; + + if (BBI.BrCond.size()) { + // No false branch. This BB must end with a conditional branch and a + // fallthrough. + if (!BBI.FalseBB) + BBI.FalseBB = findFalseBlock(BBI.BB, BBI.TrueBB); + if (!BBI.FalseBB) { + // Malformed bcc? True and false blocks are the same? + BBI.IsUnpredicable = true; + return; + } + } + + // Then scan all the instructions. + BBI.NonPredSize = 0; + BBI.ExtraCost = 0; + BBI.ExtraCost2 = 0; + BBI.ClobbersPred = false; + for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end(); + I != E; ++I) { + if (I->isDebugValue()) + continue; + + const TargetInstrDesc &TID = I->getDesc(); + if (TID.isNotDuplicable()) + BBI.CannotBeCopied = true; + + bool isPredicated = TII->isPredicated(I); + bool isCondBr = BBI.IsBrAnalyzable && TID.isConditionalBranch(); + + if (!isCondBr) { + if (!isPredicated) { + BBI.NonPredSize++; + unsigned ExtraPredCost = 0; + unsigned NumCycles = TII->getInstrLatency(InstrItins, &*I, + &ExtraPredCost); + if (NumCycles > 1) + BBI.ExtraCost += NumCycles-1; + BBI.ExtraCost2 += ExtraPredCost; + } else if (!AlreadyPredicated) { + // FIXME: This instruction is already predicated before the + // if-conversion pass. It's probably something like a conditional move. + // Mark this block unpredicable for now. + BBI.IsUnpredicable = true; + return; + } + } + + if (BBI.ClobbersPred && !isPredicated) { + // Predicate modification instruction should end the block (except for + // already predicated instructions and end of block branches). + if (isCondBr) { + // A conditional branch is not predicable, but it may be eliminated. + continue; + } + + // Predicate may have been modified, the subsequent (currently) + // unpredicated instructions cannot be correctly predicated. + BBI.IsUnpredicable = true; + return; + } + + // FIXME: Make use of PredDefs? e.g. ADDC, SUBC sets predicates but are + // still potentially predicable. + std::vector PredDefs; + if (TII->DefinesPredicate(I, PredDefs)) + BBI.ClobbersPred = true; + + if (!TII->isPredicable(I)) { + BBI.IsUnpredicable = true; + return; + } + } +} + +/// FeasibilityAnalysis - Determine if the block is a suitable candidate to be +/// predicated by the specified predicate. +bool IfConverter::FeasibilityAnalysis(BBInfo &BBI, + SmallVectorImpl &Pred, + bool isTriangle, bool RevBranch) { + // If the block is dead or unpredicable, then it cannot be predicated. + if (BBI.IsDone || BBI.IsUnpredicable) + return false; + + // If it is already predicated, check if its predicate subsumes the new + // predicate. + if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Pred)) + return false; + + if (BBI.BrCond.size()) { + if (!isTriangle) + return false; + + // Test predicate subsumption. + SmallVector RevPred(Pred.begin(), Pred.end()); + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (RevBranch) { + if (TII->ReverseBranchCondition(Cond)) + return false; + } + if (TII->ReverseBranchCondition(RevPred) || + !TII->SubsumesPredicate(Cond, RevPred)) + return false; + } + + return true; +} + +/// AnalyzeBlock - Analyze the structure of the sub-CFG starting from +/// the specified block. Record its successors and whether it looks like an +/// if-conversion candidate. +IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB, + std::vector &Tokens) { + BBInfo &BBI = BBAnalysis[BB->getNumber()]; + + if (BBI.IsAnalyzed || BBI.IsBeingAnalyzed) + return BBI; + + BBI.BB = BB; + BBI.IsBeingAnalyzed = true; + + ScanInstructions(BBI); + + // Unanalyzable or ends with fallthrough or unconditional branch. + if (!BBI.IsBrAnalyzable || BBI.BrCond.empty()) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + // Do not ifcvt if either path is a back edge to the entry block. + if (BBI.TrueBB == BB || BBI.FalseBB == BB) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + // Do not ifcvt if true and false fallthrough blocks are the same. + if (!BBI.FalseBB) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + BBInfo &TrueBBI = AnalyzeBlock(BBI.TrueBB, Tokens); + BBInfo &FalseBBI = AnalyzeBlock(BBI.FalseBB, Tokens); + + if (TrueBBI.IsDone && FalseBBI.IsDone) { + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; + } + + SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); + bool CanRevCond = !TII->ReverseBranchCondition(RevCond); + + unsigned Dups = 0; + unsigned Dups2 = 0; + bool TNeedSub = TrueBBI.Predicate.size() > 0; + bool FNeedSub = FalseBBI.Predicate.size() > 0; + bool Enqueued = false; + + // Try to predict the branch, using loop info to guide us. + // General heuristics are: + // - backedge -> 90% taken + // - early exit -> 20% taken + // - branch predictor confidence -> 90% + float Prediction = 0.5f; + float Confidence = 0.9f; + MachineLoop *Loop = MLI->getLoopFor(BB); + if (Loop) { + if (TrueBBI.BB == Loop->getHeader()) + Prediction = 0.9f; + else if (FalseBBI.BB == Loop->getHeader()) + Prediction = 0.1f; + + MachineLoop *TrueLoop = MLI->getLoopFor(TrueBBI.BB); + MachineLoop *FalseLoop = MLI->getLoopFor(FalseBBI.BB); + if (!TrueLoop || TrueLoop->getParentLoop() == Loop) + Prediction = 0.2f; + else if (!FalseLoop || FalseLoop->getParentLoop() == Loop) + Prediction = 0.8f; + } + + if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI, Dups, Dups2) && + MeetIfcvtSizeLimit(*TrueBBI.BB, (TrueBBI.NonPredSize - (Dups + Dups2) + + TrueBBI.ExtraCost), TrueBBI.ExtraCost2, + *FalseBBI.BB, (FalseBBI.NonPredSize - (Dups + Dups2) + + FalseBBI.ExtraCost),FalseBBI.ExtraCost2, + Prediction, Confidence) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + // Diamond: + // EBB + // / \_ + // | | + // TBB FBB + // \ / + // TailBB + // Note TailBB can be empty. + Tokens.push_back(new IfcvtToken(BBI, ICDiamond, TNeedSub|FNeedSub, Dups, + Dups2)); + Enqueued = true; + } + + if (ValidTriangle(TrueBBI, FalseBBI, false, Dups, Prediction, Confidence) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost, + TrueBBI.ExtraCost2, Prediction, Confidence) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) { + // Triangle: + // EBB + // | \_ + // | | + // | TBB + // | / + // FBB + Tokens.push_back(new IfcvtToken(BBI, ICTriangle, TNeedSub, Dups)); + Enqueued = true; + } + + if (ValidTriangle(TrueBBI, FalseBBI, true, Dups, Prediction, Confidence) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost, + TrueBBI.ExtraCost2, Prediction, Confidence) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond, true, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleRev, TNeedSub, Dups)); + Enqueued = true; + } + + if (ValidSimple(TrueBBI, Dups, Prediction, Confidence) && + MeetIfcvtSizeLimit(*TrueBBI.BB, TrueBBI.NonPredSize + TrueBBI.ExtraCost, + TrueBBI.ExtraCost2, Prediction, Confidence) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { + // Simple (split, no rejoin): + // EBB + // | \_ + // | | + // | TBB---> exit + // | + // FBB + Tokens.push_back(new IfcvtToken(BBI, ICSimple, TNeedSub, Dups)); + Enqueued = true; + } + + if (CanRevCond) { + // Try the other path... + if (ValidTriangle(FalseBBI, TrueBBI, false, Dups, + 1.0-Prediction, Confidence) && + MeetIfcvtSizeLimit(*FalseBBI.BB, + FalseBBI.NonPredSize + FalseBBI.ExtraCost, + FalseBBI.ExtraCost2, 1.0-Prediction, Confidence) && + FeasibilityAnalysis(FalseBBI, RevCond, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleFalse, FNeedSub, Dups)); + Enqueued = true; + } + + if (ValidTriangle(FalseBBI, TrueBBI, true, Dups, + 1.0-Prediction, Confidence) && + MeetIfcvtSizeLimit(*FalseBBI.BB, + FalseBBI.NonPredSize + FalseBBI.ExtraCost, + FalseBBI.ExtraCost2, 1.0-Prediction, Confidence) && + FeasibilityAnalysis(FalseBBI, RevCond, true, true)) { + Tokens.push_back(new IfcvtToken(BBI, ICTriangleFRev, FNeedSub, Dups)); + Enqueued = true; + } + + if (ValidSimple(FalseBBI, Dups, 1.0-Prediction, Confidence) && + MeetIfcvtSizeLimit(*FalseBBI.BB, + FalseBBI.NonPredSize + FalseBBI.ExtraCost, + FalseBBI.ExtraCost2, 1.0-Prediction, Confidence) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + Tokens.push_back(new IfcvtToken(BBI, ICSimpleFalse, FNeedSub, Dups)); + Enqueued = true; + } + } + + BBI.IsEnqueued = Enqueued; + BBI.IsBeingAnalyzed = false; + BBI.IsAnalyzed = true; + return BBI; +} + +/// AnalyzeBlocks - Analyze all blocks and find entries for all if-conversion +/// candidates. +void IfConverter::AnalyzeBlocks(MachineFunction &MF, + std::vector &Tokens) { + std::set Visited; + for (unsigned i = 0, e = Roots.size(); i != e; ++i) { + for (idf_ext_iterator I=idf_ext_begin(Roots[i],Visited), + E = idf_ext_end(Roots[i], Visited); I != E; ++I) { + MachineBasicBlock *BB = *I; + AnalyzeBlock(BB, Tokens); + } + } + + // Sort to favor more complex ifcvt scheme. + std::stable_sort(Tokens.begin(), Tokens.end(), IfcvtTokenCmp); +} + +/// canFallThroughTo - Returns true either if ToBB is the next block after BB or +/// that all the intervening blocks are empty (given BB can fall through to its +/// next block). +static bool canFallThroughTo(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { + MachineFunction::iterator PI = BB; + MachineFunction::iterator I = llvm::next(PI); + MachineFunction::iterator TI = ToBB; + MachineFunction::iterator E = BB->getParent()->end(); + while (I != TI) { + // Check isSuccessor to avoid case where the next block is empty, but + // it's not a successor. + if (I == E || !I->empty() || !PI->isSuccessor(I)) + return false; + PI = I++; + } + return true; +} + +/// InvalidatePreds - Invalidate predecessor BB info so it would be re-analyzed +/// to determine if it can be if-converted. If predecessor is already enqueued, +/// dequeue it! +void IfConverter::InvalidatePreds(MachineBasicBlock *BB) { + for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), + E = BB->pred_end(); PI != E; ++PI) { + BBInfo &PBBI = BBAnalysis[(*PI)->getNumber()]; + if (PBBI.IsDone || PBBI.BB == BB) + continue; + PBBI.IsAnalyzed = false; + PBBI.IsEnqueued = false; + } +} + +/// InsertUncondBranch - Inserts an unconditional branch from BB to ToBB. +/// +static void InsertUncondBranch(MachineBasicBlock *BB, MachineBasicBlock *ToBB, + const TargetInstrInfo *TII) { + DebugLoc dl; // FIXME: this is nowhere + SmallVector NoCond; + TII->InsertBranch(*BB, ToBB, NULL, NoCond, dl); +} + +/// RemoveExtraEdges - Remove true / false edges if either / both are no longer +/// successors. +void IfConverter::RemoveExtraEdges(BBInfo &BBI) { + MachineBasicBlock *TBB = NULL, *FBB = NULL; + SmallVector Cond; + if (!TII->AnalyzeBranch(*BBI.BB, TBB, FBB, Cond)) + BBI.BB->CorrectExtraCFGEdges(TBB, FBB, !Cond.empty()); +} + +/// InitPredRedefs / UpdatePredRedefs - Defs by predicated instructions are +/// modeled as read + write (sort like two-address instructions). These +/// routines track register liveness and add implicit uses to if-converted +/// instructions to conform to the model. +static void InitPredRedefs(MachineBasicBlock *BB, SmallSet &Redefs, + const TargetRegisterInfo *TRI) { + for (MachineBasicBlock::livein_iterator I = BB->livein_begin(), + E = BB->livein_end(); I != E; ++I) { + unsigned Reg = *I; + Redefs.insert(Reg); + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) + Redefs.insert(*Subreg); + } +} + +static void UpdatePredRedefs(MachineInstr *MI, SmallSet &Redefs, + const TargetRegisterInfo *TRI, + bool AddImpUse = false) { + SmallVector Defs; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (MO.isDef()) + Defs.push_back(Reg); + else if (MO.isKill()) { + Redefs.erase(Reg); + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) + Redefs.erase(*SR); + } + } + for (unsigned i = 0, e = Defs.size(); i != e; ++i) { + unsigned Reg = Defs[i]; + if (Redefs.count(Reg)) { + if (AddImpUse) + // Treat predicated update as read + write. + MI->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/, + true/*IsImp*/,false/*IsKill*/)); + } else { + Redefs.insert(Reg); + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) + Redefs.insert(*SR); + } + } +} + +static void UpdatePredRedefs(MachineBasicBlock::iterator I, + MachineBasicBlock::iterator E, + SmallSet &Redefs, + const TargetRegisterInfo *TRI) { + while (I != E) { + UpdatePredRedefs(I, Redefs, TRI); + ++I; + } +} + +/// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG. +/// +bool IfConverter::IfConvertSimple(BBInfo &BBI, IfcvtKind Kind) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + BBInfo *CvtBBI = &TrueBBI; + BBInfo *NextBBI = &FalseBBI; + + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (Kind == ICSimpleFalse) + std::swap(CvtBBI, NextBBI); + + if (CvtBBI->IsDone || + (CvtBBI->CannotBeCopied && CvtBBI->BB->pred_size() > 1)) { + // Something has changed. It's no longer safe to predicate this block. + BBI.IsAnalyzed = false; + CvtBBI->IsAnalyzed = false; + return false; + } + + if (Kind == ICSimpleFalse) + if (TII->ReverseBranchCondition(Cond)) + assert(false && "Unable to reverse branch condition!"); + + // Initialize liveins to the first BB. These are potentiall redefined by + // predicated instructions. + SmallSet Redefs; + InitPredRedefs(CvtBBI->BB, Redefs, TRI); + InitPredRedefs(NextBBI->BB, Redefs, TRI); + + if (CvtBBI->BB->pred_size() > 1) { + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + // Copy instructions in the true block, predicate them, and add them to + // the entry block. + CopyAndPredicateBlock(BBI, *CvtBBI, Cond, Redefs); + } else { + PredicateBlock(*CvtBBI, CvtBBI->BB->end(), Cond, Redefs); + + // Merge converted block into entry block. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, *CvtBBI); + } + + bool IterIfcvt = true; + if (!canFallThroughTo(BBI.BB, NextBBI->BB)) { + InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.HasFallThrough = false; + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch + // will have to be predicated on the new condition, that will not be + // available if cmp executes. + IterIfcvt = false; + } + + RemoveExtraEdges(BBI); + + // Update block info. BB can be iteratively if-converted. + if (!IterIfcvt) + BBI.IsDone = true; + InvalidatePreds(BBI.BB); + CvtBBI->IsDone = true; + + // FIXME: Must maintain LiveIns. + return true; +} + +/// IfConvertTriangle - If convert a triangle sub-CFG. +/// +bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + BBInfo *CvtBBI = &TrueBBI; + BBInfo *NextBBI = &FalseBBI; + DebugLoc dl; // FIXME: this is nowhere + + SmallVector Cond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (Kind == ICTriangleFalse || Kind == ICTriangleFRev) + std::swap(CvtBBI, NextBBI); + + if (CvtBBI->IsDone || + (CvtBBI->CannotBeCopied && CvtBBI->BB->pred_size() > 1)) { + // Something has changed. It's no longer safe to predicate this block. + BBI.IsAnalyzed = false; + CvtBBI->IsAnalyzed = false; + return false; + } + + if (Kind == ICTriangleFalse || Kind == ICTriangleFRev) + if (TII->ReverseBranchCondition(Cond)) + assert(false && "Unable to reverse branch condition!"); + + if (Kind == ICTriangleRev || Kind == ICTriangleFRev) { + if (ReverseBranchCondition(*CvtBBI)) { + // BB has been changed, modify its predecessors (except for this + // one) so they don't get ifcvt'ed based on bad intel. + for (MachineBasicBlock::pred_iterator PI = CvtBBI->BB->pred_begin(), + E = CvtBBI->BB->pred_end(); PI != E; ++PI) { + MachineBasicBlock *PBB = *PI; + if (PBB == BBI.BB) + continue; + BBInfo &PBBI = BBAnalysis[PBB->getNumber()]; + if (PBBI.IsEnqueued) { + PBBI.IsAnalyzed = false; + PBBI.IsEnqueued = false; + } + } + } + } + + // Initialize liveins to the first BB. These are potentially redefined by + // predicated instructions. + SmallSet Redefs; + InitPredRedefs(CvtBBI->BB, Redefs, TRI); + InitPredRedefs(NextBBI->BB, Redefs, TRI); + + bool HasEarlyExit = CvtBBI->FalseBB != NULL; + if (CvtBBI->BB->pred_size() > 1) { + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + // Copy instructions in the true block, predicate them, and add them to + // the entry block. + CopyAndPredicateBlock(BBI, *CvtBBI, Cond, Redefs, true); + } else { + // Predicate the 'true' block after removing its branch. + CvtBBI->NonPredSize -= TII->RemoveBranch(*CvtBBI->BB); + PredicateBlock(*CvtBBI, CvtBBI->BB->end(), Cond, Redefs); + + // Now merge the entry of the triangle with the true block. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, *CvtBBI, false); + } + + // If 'true' block has a 'false' successor, add an exit branch to it. + if (HasEarlyExit) { + SmallVector RevCond(CvtBBI->BrCond.begin(), + CvtBBI->BrCond.end()); + if (TII->ReverseBranchCondition(RevCond)) + assert(false && "Unable to reverse branch condition!"); + TII->InsertBranch(*BBI.BB, CvtBBI->FalseBB, NULL, RevCond, dl); + BBI.BB->addSuccessor(CvtBBI->FalseBB); + } + + // Merge in the 'false' block if the 'false' block has no other + // predecessors. Otherwise, add an unconditional branch to 'false'. + bool FalseBBDead = false; + bool IterIfcvt = true; + bool isFallThrough = canFallThroughTo(BBI.BB, NextBBI->BB); + if (!isFallThrough) { + // Only merge them if the true block does not fallthrough to the false + // block. By not merging them, we make it possible to iteratively + // ifcvt the blocks. + if (!HasEarlyExit && + NextBBI->BB->pred_size() == 1 && !NextBBI->HasFallThrough) { + MergeBlocks(BBI, *NextBBI); + FalseBBDead = true; + } else { + InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.HasFallThrough = false; + } + // Mixed predicated and unpredicated code. This cannot be iteratively + // predicated. + IterIfcvt = false; + } + + RemoveExtraEdges(BBI); + + // Update block info. BB can be iteratively if-converted. + if (!IterIfcvt) + BBI.IsDone = true; + InvalidatePreds(BBI.BB); + CvtBBI->IsDone = true; + if (FalseBBDead) + NextBBI->IsDone = true; + + // FIXME: Must maintain LiveIns. + return true; +} + +/// IfConvertDiamond - If convert a diamond sub-CFG. +/// +bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, + unsigned NumDups1, unsigned NumDups2) { + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + MachineBasicBlock *TailBB = TrueBBI.TrueBB; + // True block must fall through or end with an unanalyzable terminator. + if (!TailBB) { + if (blockAlwaysFallThrough(TrueBBI)) + TailBB = FalseBBI.TrueBB; + assert((TailBB || !TrueBBI.IsBrAnalyzable) && "Unexpected!"); + } + + if (TrueBBI.IsDone || FalseBBI.IsDone || + TrueBBI.BB->pred_size() > 1 || + FalseBBI.BB->pred_size() > 1) { + // Something has changed. It's no longer safe to predicate these blocks. + BBI.IsAnalyzed = false; + TrueBBI.IsAnalyzed = false; + FalseBBI.IsAnalyzed = false; + return false; + } + + // Put the predicated instructions from the 'true' block before the + // instructions from the 'false' block, unless the true block would clobber + // the predicate, in which case, do the opposite. + BBInfo *BBI1 = &TrueBBI; + BBInfo *BBI2 = &FalseBBI; + SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); + if (TII->ReverseBranchCondition(RevCond)) + assert(false && "Unable to reverse branch condition!"); + SmallVector *Cond1 = &BBI.BrCond; + SmallVector *Cond2 = &RevCond; + + // Figure out the more profitable ordering. + bool DoSwap = false; + if (TrueBBI.ClobbersPred && !FalseBBI.ClobbersPred) + DoSwap = true; + else if (TrueBBI.ClobbersPred == FalseBBI.ClobbersPred) { + if (TrueBBI.NonPredSize > FalseBBI.NonPredSize) + DoSwap = true; + } + if (DoSwap) { + std::swap(BBI1, BBI2); + std::swap(Cond1, Cond2); + } + + // Remove the conditional branch from entry to the blocks. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + + // Initialize liveins to the first BB. These are potentially redefined by + // predicated instructions. + SmallSet Redefs; + InitPredRedefs(BBI1->BB, Redefs, TRI); + + // Remove the duplicated instructions at the beginnings of both paths. + MachineBasicBlock::iterator DI1 = BBI1->BB->begin(); + MachineBasicBlock::iterator DI2 = BBI2->BB->begin(); + MachineBasicBlock::iterator DIE1 = BBI1->BB->end(); + MachineBasicBlock::iterator DIE2 = BBI2->BB->end(); + // Skip dbg_value instructions + while (DI1 != DIE1 && DI1->isDebugValue()) + ++DI1; + while (DI2 != DIE2 && DI2->isDebugValue()) + ++DI2; + BBI1->NonPredSize -= NumDups1; + BBI2->NonPredSize -= NumDups1; + + // Skip past the dups on each side separately since there may be + // differing dbg_value entries. + for (unsigned i = 0; i < NumDups1; ++DI1) { + if (!DI1->isDebugValue()) + ++i; + } + while (NumDups1 != 0) { + ++DI2; + if (!DI2->isDebugValue()) + --NumDups1; + } + + UpdatePredRedefs(BBI1->BB->begin(), DI1, Redefs, TRI); + BBI.BB->splice(BBI.BB->end(), BBI1->BB, BBI1->BB->begin(), DI1); + BBI2->BB->erase(BBI2->BB->begin(), DI2); + + // Predicate the 'true' block after removing its branch. + BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); + DI1 = BBI1->BB->end(); + for (unsigned i = 0; i != NumDups2; ) { + // NumDups2 only counted non-dbg_value instructions, so this won't + // run off the head of the list. + assert (DI1 != BBI1->BB->begin()); + --DI1; + // skip dbg_value instructions + if (!DI1->isDebugValue()) + ++i; + } + BBI1->BB->erase(DI1, BBI1->BB->end()); + PredicateBlock(*BBI1, BBI1->BB->end(), *Cond1, Redefs); + + // Predicate the 'false' block. + BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB); + DI2 = BBI2->BB->end(); + while (NumDups2 != 0) { + // NumDups2 only counted non-dbg_value instructions, so this won't + // run off the head of the list. + assert (DI2 != BBI2->BB->begin()); + --DI2; + // skip dbg_value instructions + if (!DI2->isDebugValue()) + --NumDups2; + } + PredicateBlock(*BBI2, DI2, *Cond2, Redefs); + + // Merge the true block into the entry of the diamond. + MergeBlocks(BBI, *BBI1, TailBB == 0); + MergeBlocks(BBI, *BBI2, TailBB == 0); + + // If the if-converted block falls through or unconditionally branches into + // the tail block, and the tail block does not have other predecessors, then + // fold the tail block in as well. Otherwise, unless it falls through to the + // tail, add a unconditional branch to it. + if (TailBB) { + BBInfo TailBBI = BBAnalysis[TailBB->getNumber()]; + bool CanMergeTail = !TailBBI.HasFallThrough; + // There may still be a fall-through edge from BBI1 or BBI2 to TailBB; + // check if there are any other predecessors besides those. + unsigned NumPreds = TailBB->pred_size(); + if (NumPreds > 1) + CanMergeTail = false; + else if (NumPreds == 1 && CanMergeTail) { + MachineBasicBlock::pred_iterator PI = TailBB->pred_begin(); + if (*PI != BBI1->BB && *PI != BBI2->BB) + CanMergeTail = false; + } + if (CanMergeTail) { + MergeBlocks(BBI, TailBBI); + TailBBI.IsDone = true; + } else { + BBI.BB->addSuccessor(TailBB); + InsertUncondBranch(BBI.BB, TailBB, TII); + BBI.HasFallThrough = false; + } + } + + // RemoveExtraEdges won't work if the block has an unanalyzable branch, + // which can happen here if TailBB is unanalyzable and is merged, so + // explicitly remove BBI1 and BBI2 as successors. + BBI.BB->removeSuccessor(BBI1->BB); + BBI.BB->removeSuccessor(BBI2->BB); + RemoveExtraEdges(BBI); + + // Update block info. + BBI.IsDone = TrueBBI.IsDone = FalseBBI.IsDone = true; + InvalidatePreds(BBI.BB); + + // FIXME: Must maintain LiveIns. + return true; +} + +/// PredicateBlock - Predicate instructions from the start of the block to the +/// specified end with the specified condition. +void IfConverter::PredicateBlock(BBInfo &BBI, + MachineBasicBlock::iterator E, + SmallVectorImpl &Cond, + SmallSet &Redefs) { + for (MachineBasicBlock::iterator I = BBI.BB->begin(); I != E; ++I) { + if (I->isDebugValue() || TII->isPredicated(I)) + continue; + if (!TII->PredicateInstruction(I, Cond)) { +#ifndef NDEBUG + dbgs() << "Unable to predicate " << *I << "!\n"; +#endif + llvm_unreachable(0); + } + + // If the predicated instruction now redefines a register as the result of + // if-conversion, add an implicit kill. + UpdatePredRedefs(I, Redefs, TRI, true); + } + + std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); + + BBI.IsAnalyzed = false; + BBI.NonPredSize = 0; + + ++NumIfConvBBs; +} + +/// CopyAndPredicateBlock - Copy and predicate instructions from source BB to +/// the destination block. Skip end of block branches if IgnoreBr is true. +void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, + SmallVectorImpl &Cond, + SmallSet &Redefs, + bool IgnoreBr) { + MachineFunction &MF = *ToBBI.BB->getParent(); + + for (MachineBasicBlock::iterator I = FromBBI.BB->begin(), + E = FromBBI.BB->end(); I != E; ++I) { + const TargetInstrDesc &TID = I->getDesc(); + // Do not copy the end of the block branches. + if (IgnoreBr && TID.isBranch()) + break; + + MachineInstr *MI = MF.CloneMachineInstr(I); + ToBBI.BB->insert(ToBBI.BB->end(), MI); + ToBBI.NonPredSize++; + unsigned ExtraPredCost = 0; + unsigned NumCycles = TII->getInstrLatency(InstrItins, &*I, &ExtraPredCost); + if (NumCycles > 1) + ToBBI.ExtraCost += NumCycles-1; + ToBBI.ExtraCost2 += ExtraPredCost; + + if (!TII->isPredicated(I) && !MI->isDebugValue()) { + if (!TII->PredicateInstruction(MI, Cond)) { +#ifndef NDEBUG + dbgs() << "Unable to predicate " << *I << "!\n"; +#endif + llvm_unreachable(0); + } + } + + // If the predicated instruction now redefines a register as the result of + // if-conversion, add an implicit kill. + UpdatePredRedefs(MI, Redefs, TRI, true); + } + + if (!IgnoreBr) { + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. + if (Succ == FallThrough) + continue; + ToBBI.BB->addSuccessor(Succ); + } + } + + std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), + std::back_inserter(ToBBI.Predicate)); + std::copy(Cond.begin(), Cond.end(), std::back_inserter(ToBBI.Predicate)); + + ToBBI.ClobbersPred |= FromBBI.ClobbersPred; + ToBBI.IsAnalyzed = false; + + ++NumDupBBs; +} + +/// MergeBlocks - Move all instructions from FromBB to the end of ToBB. +/// This will leave FromBB as an empty block, so remove all of its +/// successor edges except for the fall-through edge. If AddEdges is true, +/// i.e., when FromBBI's branch is being moved, add those successor edges to +/// ToBBI. +void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges) { + ToBBI.BB->splice(ToBBI.BB->end(), + FromBBI.BB, FromBBI.BB->begin(), FromBBI.BB->end()); + + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. + if (Succ == FallThrough) + continue; + FromBBI.BB->removeSuccessor(Succ); + if (AddEdges) + ToBBI.BB->addSuccessor(Succ); + } + + // Now FromBBI always falls through to the next block! + if (NBB && !FromBBI.BB->isSuccessor(NBB)) + FromBBI.BB->addSuccessor(NBB); + + std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), + std::back_inserter(ToBBI.Predicate)); + FromBBI.Predicate.clear(); + + ToBBI.NonPredSize += FromBBI.NonPredSize; + ToBBI.ExtraCost += FromBBI.ExtraCost; + ToBBI.ExtraCost2 += FromBBI.ExtraCost2; + FromBBI.NonPredSize = 0; + FromBBI.ExtraCost = 0; + FromBBI.ExtraCost2 = 0; + + ToBBI.ClobbersPred |= FromBBI.ClobbersPred; + ToBBI.HasFallThrough = FromBBI.HasFallThrough; + ToBBI.IsAnalyzed = false; + FromBBI.IsAnalyzed = false; +} diff --git a/final/lib/CodeGen/InlineSpiller.cpp b/final/lib/CodeGen/InlineSpiller.cpp new file mode 100644 index 00000000000..34ae3ec2f3e --- /dev/null +++ b/final/lib/CodeGen/InlineSpiller.cpp @@ -0,0 +1,439 @@ +//===-------- InlineSpiller.cpp - Insert spills and restores inline -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The inline spiller modifies the machine function directly instead of +// inserting spills and restores in VirtRegMap. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "Spiller.h" +#include "LiveRangeEdit.h" +#include "VirtRegMap.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt +VerifySpills("verify-spills", cl::desc("Verify after each spill/split")); + +namespace { +class InlineSpiller : public Spiller { + MachineFunctionPass &pass_; + MachineFunction &mf_; + LiveIntervals &lis_; + LiveStacks &lss_; + AliasAnalysis *aa_; + VirtRegMap &vrm_; + MachineFrameInfo &mfi_; + MachineRegisterInfo &mri_; + const TargetInstrInfo &tii_; + const TargetRegisterInfo &tri_; + const BitVector reserved_; + + // Variables that are valid during spill(), but used by multiple methods. + LiveRangeEdit *edit_; + const TargetRegisterClass *rc_; + int stackSlot_; + + // Values that failed to remat at some point. + SmallPtrSet usedValues_; + + ~InlineSpiller() {} + +public: + InlineSpiller(MachineFunctionPass &pass, + MachineFunction &mf, + VirtRegMap &vrm) + : pass_(pass), + mf_(mf), + lis_(pass.getAnalysis()), + lss_(pass.getAnalysis()), + aa_(&pass.getAnalysis()), + vrm_(vrm), + mfi_(*mf.getFrameInfo()), + mri_(mf.getRegInfo()), + tii_(*mf.getTarget().getInstrInfo()), + tri_(*mf.getTarget().getRegisterInfo()), + reserved_(tri_.getReservedRegs(mf_)) {} + + void spill(LiveInterval *li, + SmallVectorImpl &newIntervals, + const SmallVectorImpl &spillIs); + + void spill(LiveRangeEdit &); + +private: + bool reMaterializeFor(MachineBasicBlock::iterator MI); + void reMaterializeAll(); + + bool coalesceStackAccess(MachineInstr *MI); + bool foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + MachineInstr *LoadMI = 0); + void insertReload(LiveInterval &NewLI, MachineBasicBlock::iterator MI); + void insertSpill(LiveInterval &NewLI, MachineBasicBlock::iterator MI); +}; +} + +namespace llvm { +Spiller *createInlineSpiller(MachineFunctionPass &pass, + MachineFunction &mf, + VirtRegMap &vrm) { + if (VerifySpills) + mf.verify(&pass, "When creating inline spiller"); + return new InlineSpiller(pass, mf, vrm); +} +} + +/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading. +bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { + SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex(); + VNInfo *OrigVNI = edit_->getParent().getVNInfoAt(UseIdx); + + if (!OrigVNI) { + DEBUG(dbgs() << "\tadding flags: "); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.getReg() == edit_->getReg()) + MO.setIsUndef(); + } + DEBUG(dbgs() << UseIdx << '\t' << *MI); + return true; + } + + LiveRangeEdit::Remat RM(OrigVNI); + if (!edit_->canRematerializeAt(RM, UseIdx, false, lis_)) { + usedValues_.insert(OrigVNI); + DEBUG(dbgs() << "\tcannot remat for " << UseIdx << '\t' << *MI); + return false; + } + + // If the instruction also writes edit_->getReg(), it had better not require + // the same register for uses and defs. + bool Reads, Writes; + SmallVector Ops; + tie(Reads, Writes) = MI->readsWritesVirtualRegister(edit_->getReg(), &Ops); + if (Writes) { + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(Ops[i]); + if (MO.isUse() ? MI->isRegTiedToDefOperand(Ops[i]) : MO.getSubReg()) { + usedValues_.insert(OrigVNI); + DEBUG(dbgs() << "\tcannot remat tied reg: " << UseIdx << '\t' << *MI); + return false; + } + } + } + + // Before rematerializing into a register for a single instruction, try to + // fold a load into the instruction. That avoids allocating a new register. + if (RM.OrigMI->getDesc().canFoldAsLoad() && + foldMemoryOperand(MI, Ops, RM.OrigMI)) { + edit_->markRematerialized(RM.ParentVNI); + return true; + } + + // Alocate a new register for the remat. + LiveInterval &NewLI = edit_->create(mri_, lis_, vrm_); + NewLI.markNotSpillable(); + + // Rematting for a copy: Set allocation hint to be the destination register. + if (MI->isCopy()) + mri_.setRegAllocationHint(NewLI.reg, 0, MI->getOperand(0).getReg()); + + // Finally we can rematerialize OrigMI before MI. + SlotIndex DefIdx = edit_->rematerializeAt(*MI->getParent(), MI, NewLI.reg, RM, + lis_, tii_, tri_); + DEBUG(dbgs() << "\tremat: " << DefIdx << '\t' + << *lis_.getInstructionFromIndex(DefIdx)); + + // Replace operands + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(Ops[i]); + if (MO.isReg() && MO.isUse() && MO.getReg() == edit_->getReg()) { + MO.setReg(NewLI.reg); + MO.setIsKill(); + } + } + DEBUG(dbgs() << "\t " << UseIdx << '\t' << *MI); + + VNInfo *DefVNI = NewLI.getNextValue(DefIdx, 0, lis_.getVNInfoAllocator()); + NewLI.addRange(LiveRange(DefIdx, UseIdx.getDefIndex(), DefVNI)); + DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); + return true; +} + +/// reMaterializeAll - Try to rematerialize as many uses as possible, +/// and trim the live ranges after. +void InlineSpiller::reMaterializeAll() { + // Do a quick scan of the interval values to find if any are remattable. + if (!edit_->anyRematerializable(lis_, tii_, aa_)) + return; + + usedValues_.clear(); + + // Try to remat before all uses of edit_->getReg(). + bool anyRemat = false; + for (MachineRegisterInfo::use_nodbg_iterator + RI = mri_.use_nodbg_begin(edit_->getReg()); + MachineInstr *MI = RI.skipInstruction();) + anyRemat |= reMaterializeFor(MI); + + if (!anyRemat) + return; + + // Remove any values that were completely rematted. + bool anyRemoved = false; + for (LiveInterval::vni_iterator I = edit_->getParent().vni_begin(), + E = edit_->getParent().vni_end(); I != E; ++I) { + VNInfo *VNI = *I; + if (VNI->hasPHIKill() || !edit_->didRematerialize(VNI) || + usedValues_.count(VNI)) + continue; + MachineInstr *DefMI = lis_.getInstructionFromIndex(VNI->def); + DEBUG(dbgs() << "\tremoving dead def: " << VNI->def << '\t' << *DefMI); + lis_.RemoveMachineInstrFromMaps(DefMI); + vrm_.RemoveMachineInstrFromMaps(DefMI); + DefMI->eraseFromParent(); + VNI->def = SlotIndex(); + anyRemoved = true; + } + + if (!anyRemoved) + return; + + // Removing values may cause debug uses where parent is not live. + for (MachineRegisterInfo::use_iterator RI = mri_.use_begin(edit_->getReg()); + MachineInstr *MI = RI.skipInstruction();) { + if (!MI->isDebugValue()) + continue; + // Try to preserve the debug value if parent is live immediately after it. + MachineBasicBlock::iterator NextMI = MI; + ++NextMI; + if (NextMI != MI->getParent()->end() && !lis_.isNotInMIMap(NextMI)) { + SlotIndex Idx = lis_.getInstructionIndex(NextMI); + VNInfo *VNI = edit_->getParent().getVNInfoAt(Idx); + if (VNI && (VNI->hasPHIKill() || usedValues_.count(VNI))) + continue; + } + DEBUG(dbgs() << "Removing debug info due to remat:" << "\t" << *MI); + MI->eraseFromParent(); + } +} + +/// If MI is a load or store of stackSlot_, it can be removed. +bool InlineSpiller::coalesceStackAccess(MachineInstr *MI) { + int FI = 0; + unsigned reg; + if (!(reg = tii_.isLoadFromStackSlot(MI, FI)) && + !(reg = tii_.isStoreToStackSlot(MI, FI))) + return false; + + // We have a stack access. Is it the right register and slot? + if (reg != edit_->getReg() || FI != stackSlot_) + return false; + + DEBUG(dbgs() << "Coalescing stack access: " << *MI); + lis_.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + return true; +} + +/// foldMemoryOperand - Try folding stack slot references in Ops into MI. +/// @param MI Instruction using or defining the current register. +/// @param Ops Operand indices from readsWritesVirtualRegister(). +/// @param LoadMI Load instruction to use instead of stack slot when non-null. +/// @return True on success, and MI will be erased. +bool InlineSpiller::foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + MachineInstr *LoadMI) { + // TargetInstrInfo::foldMemoryOperand only expects explicit, non-tied + // operands. + SmallVector FoldOps; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + unsigned Idx = Ops[i]; + MachineOperand &MO = MI->getOperand(Idx); + if (MO.isImplicit()) + continue; + // FIXME: Teach targets to deal with subregs. + if (MO.getSubReg()) + return false; + // We cannot fold a load instruction into a def. + if (LoadMI && MO.isDef()) + return false; + // Tied use operands should not be passed to foldMemoryOperand. + if (!MI->isRegTiedToDefOperand(Idx)) + FoldOps.push_back(Idx); + } + + MachineInstr *FoldMI = + LoadMI ? tii_.foldMemoryOperand(MI, FoldOps, LoadMI) + : tii_.foldMemoryOperand(MI, FoldOps, stackSlot_); + if (!FoldMI) + return false; + lis_.ReplaceMachineInstrInMaps(MI, FoldMI); + if (!LoadMI) + vrm_.addSpillSlotUse(stackSlot_, FoldMI); + MI->eraseFromParent(); + DEBUG(dbgs() << "\tfolded: " << *FoldMI); + return true; +} + +/// insertReload - Insert a reload of NewLI.reg before MI. +void InlineSpiller::insertReload(LiveInterval &NewLI, + MachineBasicBlock::iterator MI) { + MachineBasicBlock &MBB = *MI->getParent(); + SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); + tii_.loadRegFromStackSlot(MBB, MI, NewLI.reg, stackSlot_, rc_, &tri_); + --MI; // Point to load instruction. + SlotIndex LoadIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); + vrm_.addSpillSlotUse(stackSlot_, MI); + DEBUG(dbgs() << "\treload: " << LoadIdx << '\t' << *MI); + VNInfo *LoadVNI = NewLI.getNextValue(LoadIdx, 0, + lis_.getVNInfoAllocator()); + NewLI.addRange(LiveRange(LoadIdx, Idx, LoadVNI)); +} + +/// insertSpill - Insert a spill of NewLI.reg after MI. +void InlineSpiller::insertSpill(LiveInterval &NewLI, + MachineBasicBlock::iterator MI) { + MachineBasicBlock &MBB = *MI->getParent(); + + // Get the defined value. It could be an early clobber so keep the def index. + SlotIndex Idx = lis_.getInstructionIndex(MI).getDefIndex(); + VNInfo *VNI = edit_->getParent().getVNInfoAt(Idx); + assert(VNI && VNI->def.getDefIndex() == Idx && "Inconsistent VNInfo"); + Idx = VNI->def; + + tii_.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, stackSlot_, rc_, &tri_); + --MI; // Point to store instruction. + SlotIndex StoreIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex(); + vrm_.addSpillSlotUse(stackSlot_, MI); + DEBUG(dbgs() << "\tspilled: " << StoreIdx << '\t' << *MI); + VNInfo *StoreVNI = NewLI.getNextValue(Idx, 0, lis_.getVNInfoAllocator()); + NewLI.addRange(LiveRange(Idx, StoreIdx, StoreVNI)); +} + +void InlineSpiller::spill(LiveInterval *li, + SmallVectorImpl &newIntervals, + const SmallVectorImpl &spillIs) { + LiveRangeEdit edit(*li, newIntervals, &spillIs); + spill(edit); + if (VerifySpills) + mf_.verify(&pass_, "After inline spill"); +} + +void InlineSpiller::spill(LiveRangeEdit &edit) { + edit_ = &edit; + assert(!TargetRegisterInfo::isStackSlot(edit.getReg()) + && "Trying to spill a stack slot."); + DEBUG(dbgs() << "Inline spilling " + << mri_.getRegClass(edit.getReg())->getName() + << ':' << edit.getParent() << "\nFrom original " + << PrintReg(vrm_.getOriginal(edit.getReg())) << '\n'); + assert(edit.getParent().isSpillable() && + "Attempting to spill already spilled value."); + + reMaterializeAll(); + + // Remat may handle everything. + if (edit_->getParent().empty()) + return; + + rc_ = mri_.getRegClass(edit.getReg()); + + // Share a stack slot among all descendants of Orig. + unsigned Orig = vrm_.getOriginal(edit.getReg()); + stackSlot_ = vrm_.getStackSlot(Orig); + if (stackSlot_ == VirtRegMap::NO_STACK_SLOT) + stackSlot_ = vrm_.assignVirt2StackSlot(Orig); + + if (Orig != edit.getReg()) + vrm_.assignVirt2StackSlot(edit.getReg(), stackSlot_); + + // Update LiveStacks now that we are committed to spilling. + LiveInterval &stacklvr = lss_.getOrCreateInterval(stackSlot_, rc_); + if (!stacklvr.hasAtLeastOneValue()) + stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator()); + stacklvr.MergeRangesInAsValue(edit_->getParent(), stacklvr.getValNumInfo(0)); + + // Iterate over instructions using register. + for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(edit.getReg()); + MachineInstr *MI = RI.skipInstruction();) { + + // Debug values are not allowed to affect codegen. + if (MI->isDebugValue()) { + // Modify DBG_VALUE now that the value is in a spill slot. + uint64_t Offset = MI->getOperand(1).getImm(); + const MDNode *MDPtr = MI->getOperand(2).getMetadata(); + DebugLoc DL = MI->getDebugLoc(); + if (MachineInstr *NewDV = tii_.emitFrameIndexDebugValue(mf_, stackSlot_, + Offset, MDPtr, DL)) { + DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MBB->erase(MI), NewDV); + } else { + DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI); + MI->eraseFromParent(); + } + continue; + } + + // Stack slot accesses may coalesce away. + if (coalesceStackAccess(MI)) + continue; + + // Analyze instruction. + bool Reads, Writes; + SmallVector Ops; + tie(Reads, Writes) = MI->readsWritesVirtualRegister(edit.getReg(), &Ops); + + // Attempt to fold memory ops. + if (foldMemoryOperand(MI, Ops)) + continue; + + // Allocate interval around instruction. + // FIXME: Infer regclass from instruction alone. + LiveInterval &NewLI = edit.create(mri_, lis_, vrm_); + NewLI.markNotSpillable(); + + if (Reads) + insertReload(NewLI, MI); + + // Rewrite instruction operands. + bool hasLiveDef = false; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(Ops[i]); + MO.setReg(NewLI.reg); + if (MO.isUse()) { + if (!MI->isRegTiedToDefOperand(Ops[i])) + MO.setIsKill(); + } else { + if (!MO.isDead()) + hasLiveDef = true; + } + } + + // FIXME: Use a second vreg if instruction has no tied ops. + if (Writes && hasLiveDef) + insertSpill(NewLI, MI); + + DEBUG(dbgs() << "\tinterval: " << NewLI << '\n'); + } +} diff --git a/final/lib/CodeGen/IntrinsicLowering.cpp b/final/lib/CodeGen/IntrinsicLowering.cpp new file mode 100644 index 00000000000..3861ddadf65 --- /dev/null +++ b/final/lib/CodeGen/IntrinsicLowering.cpp @@ -0,0 +1,564 @@ +//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// +// +// 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 IntrinsicLowering class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +template +static void EnsureFunctionExists(Module &M, const char *Name, + ArgIt ArgBegin, ArgIt ArgEnd, + const Type *RetTy) { + // Insert a correctly-typed definition now. + std::vector ParamTys; + for (ArgIt I = ArgBegin; I != ArgEnd; ++I) + ParamTys.push_back(I->getType()); + M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false)); +} + +static void EnsureFPIntrinsicsExist(Module &M, Function *Fn, + const char *FName, + const char *DName, const char *LDName) { + // Insert definitions for all the floating point types. + switch((int)Fn->arg_begin()->getType()->getTypeID()) { + case Type::FloatTyID: + EnsureFunctionExists(M, FName, Fn->arg_begin(), Fn->arg_end(), + Type::getFloatTy(M.getContext())); + break; + case Type::DoubleTyID: + EnsureFunctionExists(M, DName, Fn->arg_begin(), Fn->arg_end(), + Type::getDoubleTy(M.getContext())); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + EnsureFunctionExists(M, LDName, Fn->arg_begin(), Fn->arg_end(), + Fn->arg_begin()->getType()); + break; + } +} + +/// ReplaceCallWith - This function is used when we want to lower an intrinsic +/// call to a call of an external function. This handles hard cases such as +/// when there was already a prototype for the external function, and if that +/// prototype doesn't match the arguments we expect to pass in. +template +static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI, + ArgIt ArgBegin, ArgIt ArgEnd, + const Type *RetTy) { + // If we haven't already looked up this function, check to see if the + // program already contains a function with this name. + Module *M = CI->getParent()->getParent()->getParent(); + // Get or insert the definition now. + std::vector ParamTys; + for (ArgIt I = ArgBegin; I != ArgEnd; ++I) + ParamTys.push_back((*I)->getType()); + Constant* FCache = M->getOrInsertFunction(NewFn, + FunctionType::get(RetTy, ParamTys, false)); + + IRBuilder<> Builder(CI->getParent(), CI); + SmallVector Args(ArgBegin, ArgEnd); + CallInst *NewCI = Builder.CreateCall(FCache, Args.begin(), Args.end()); + NewCI->setName(CI->getName()); + if (!CI->use_empty()) + CI->replaceAllUsesWith(NewCI); + return NewCI; +} + +// VisualStudio defines setjmp as _setjmp +#if defined(_MSC_VER) && defined(setjmp) && \ + !defined(setjmp_undefined_for_msvc) +# pragma push_macro("setjmp") +# undef setjmp +# define setjmp_undefined_for_msvc +#endif + +void IntrinsicLowering::AddPrototypes(Module &M) { + LLVMContext &Context = M.getContext(); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (I->isDeclaration() && !I->use_empty()) + switch (I->getIntrinsicID()) { + default: break; + case Intrinsic::setjmp: + EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), + Type::getInt32Ty(M.getContext())); + break; + case Intrinsic::longjmp: + EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(), + Type::getVoidTy(M.getContext())); + break; + case Intrinsic::siglongjmp: + EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), + Type::getVoidTy(M.getContext())); + break; + case Intrinsic::memcpy: + M.getOrInsertFunction("memcpy", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::memmove: + M.getOrInsertFunction("memmove", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::memset: + M.getOrInsertFunction("memset", + Type::getInt8PtrTy(Context), + Type::getInt8PtrTy(Context), + Type::getInt32Ty(M.getContext()), + TD.getIntPtrType(Context), (Type *)0); + break; + case Intrinsic::sqrt: + EnsureFPIntrinsicsExist(M, I, "sqrtf", "sqrt", "sqrtl"); + break; + case Intrinsic::sin: + EnsureFPIntrinsicsExist(M, I, "sinf", "sin", "sinl"); + break; + case Intrinsic::cos: + EnsureFPIntrinsicsExist(M, I, "cosf", "cos", "cosl"); + break; + case Intrinsic::pow: + EnsureFPIntrinsicsExist(M, I, "powf", "pow", "powl"); + break; + case Intrinsic::log: + EnsureFPIntrinsicsExist(M, I, "logf", "log", "logl"); + break; + case Intrinsic::log2: + EnsureFPIntrinsicsExist(M, I, "log2f", "log2", "log2l"); + break; + case Intrinsic::log10: + EnsureFPIntrinsicsExist(M, I, "log10f", "log10", "log10l"); + break; + case Intrinsic::exp: + EnsureFPIntrinsicsExist(M, I, "expf", "exp", "expl"); + break; + case Intrinsic::exp2: + EnsureFPIntrinsicsExist(M, I, "exp2f", "exp2", "exp2l"); + break; + } +} + +/// LowerBSWAP - Emit the code to lower bswap of V before the specified +/// instruction IP. +static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { + assert(V->getType()->isIntegerTy() && "Can't bswap a non-integer type!"); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + + IRBuilder<> Builder(IP->getParent(), IP); + + switch(BitSize) { + default: llvm_unreachable("Unhandled type size of value to byteswap!"); + case 16: { + Value *Tmp1 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.2"); + Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.1"); + V = Builder.CreateOr(Tmp1, Tmp2, "bswap.i16"); + break; + } + case 32: { + Value *Tmp4 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), + "bswap.4"); + Value *Tmp3 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.3"); + Value *Tmp2 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.2"); + Value *Tmp1 = Builder.CreateLShr(V,ConstantInt::get(V->getType(), 24), + "bswap.1"); + Tmp3 = Builder.CreateAnd(Tmp3, + ConstantInt::get(Type::getInt32Ty(Context), 0xFF0000), + "bswap.and3"); + Tmp2 = Builder.CreateAnd(Tmp2, + ConstantInt::get(Type::getInt32Ty(Context), 0xFF00), + "bswap.and2"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or1"); + Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or2"); + V = Builder.CreateOr(Tmp4, Tmp2, "bswap.i32"); + break; + } + case 64: { + Value *Tmp8 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 56), + "bswap.8"); + Value *Tmp7 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 40), + "bswap.7"); + Value *Tmp6 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 24), + "bswap.6"); + Value *Tmp5 = Builder.CreateShl(V, ConstantInt::get(V->getType(), 8), + "bswap.5"); + Value* Tmp4 = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 8), + "bswap.4"); + Value* Tmp3 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 24), + "bswap.3"); + Value* Tmp2 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 40), + "bswap.2"); + Value* Tmp1 = Builder.CreateLShr(V, + ConstantInt::get(V->getType(), 56), + "bswap.1"); + Tmp7 = Builder.CreateAnd(Tmp7, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF000000000000ULL), + "bswap.and7"); + Tmp6 = Builder.CreateAnd(Tmp6, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF0000000000ULL), + "bswap.and6"); + Tmp5 = Builder.CreateAnd(Tmp5, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF00000000ULL), + "bswap.and5"); + Tmp4 = Builder.CreateAnd(Tmp4, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF000000ULL), + "bswap.and4"); + Tmp3 = Builder.CreateAnd(Tmp3, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF0000ULL), + "bswap.and3"); + Tmp2 = Builder.CreateAnd(Tmp2, + ConstantInt::get(Type::getInt64Ty(Context), + 0xFF00ULL), + "bswap.and2"); + Tmp8 = Builder.CreateOr(Tmp8, Tmp7, "bswap.or1"); + Tmp6 = Builder.CreateOr(Tmp6, Tmp5, "bswap.or2"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp3, "bswap.or3"); + Tmp2 = Builder.CreateOr(Tmp2, Tmp1, "bswap.or4"); + Tmp8 = Builder.CreateOr(Tmp8, Tmp6, "bswap.or5"); + Tmp4 = Builder.CreateOr(Tmp4, Tmp2, "bswap.or6"); + V = Builder.CreateOr(Tmp8, Tmp4, "bswap.i64"); + break; + } + } + return V; +} + +/// LowerCTPOP - Emit the code to lower ctpop of V before the specified +/// instruction IP. +static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) { + assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!"); + + static const uint64_t MaskValues[6] = { + 0x5555555555555555ULL, 0x3333333333333333ULL, + 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL, + 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL + }; + + IRBuilder<> Builder(IP->getParent(), IP); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + unsigned WordSize = (BitSize + 63) / 64; + Value *Count = ConstantInt::get(V->getType(), 0); + + for (unsigned n = 0; n < WordSize; ++n) { + Value *PartValue = V; + for (unsigned i = 1, ct = 0; i < (BitSize>64 ? 64 : BitSize); + i <<= 1, ++ct) { + Value *MaskCst = ConstantInt::get(V->getType(), MaskValues[ct]); + Value *LHS = Builder.CreateAnd(PartValue, MaskCst, "cppop.and1"); + Value *VShift = Builder.CreateLShr(PartValue, + ConstantInt::get(V->getType(), i), + "ctpop.sh"); + Value *RHS = Builder.CreateAnd(VShift, MaskCst, "cppop.and2"); + PartValue = Builder.CreateAdd(LHS, RHS, "ctpop.step"); + } + Count = Builder.CreateAdd(PartValue, Count, "ctpop.part"); + if (BitSize > 64) { + V = Builder.CreateLShr(V, ConstantInt::get(V->getType(), 64), + "ctpop.part.sh"); + BitSize -= 64; + } + } + + return Count; +} + +/// LowerCTLZ - Emit the code to lower ctlz of V before the specified +/// instruction IP. +static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) { + + IRBuilder<> Builder(IP->getParent(), IP); + + unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); + for (unsigned i = 1; i < BitSize; i <<= 1) { + Value *ShVal = ConstantInt::get(V->getType(), i); + ShVal = Builder.CreateLShr(V, ShVal, "ctlz.sh"); + V = Builder.CreateOr(V, ShVal, "ctlz.step"); + } + + V = Builder.CreateNot(V); + return LowerCTPOP(Context, V, IP); +} + +static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname, + const char *Dname, + const char *LDname) { + CallSite CS(CI); + switch (CI->getArgOperand(0)->getType()->getTypeID()) { + default: llvm_unreachable("Invalid type in intrinsic"); + case Type::FloatTyID: + ReplaceCallWith(Fname, CI, CS.arg_begin(), CS.arg_end(), + Type::getFloatTy(CI->getContext())); + break; + case Type::DoubleTyID: + ReplaceCallWith(Dname, CI, CS.arg_begin(), CS.arg_end(), + Type::getDoubleTy(CI->getContext())); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + ReplaceCallWith(LDname, CI, CS.arg_begin(), CS.arg_end(), + CI->getArgOperand(0)->getType()); + break; + } +} + +void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { + IRBuilder<> Builder(CI->getParent(), CI); + LLVMContext &Context = CI->getContext(); + + const Function *Callee = CI->getCalledFunction(); + assert(Callee && "Cannot lower an indirect call!"); + + CallSite CS(CI); + switch (Callee->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + report_fatal_error("Cannot lower a call to a non-intrinsic function '"+ + Callee->getName() + "'!"); + default: + report_fatal_error("Code generator does not support intrinsic function '"+ + Callee->getName()+"'!"); + + // The setjmp/longjmp intrinsics should only exist in the code if it was + // never optimized (ie, right out of the CFE), or if it has been hacked on + // by the lowerinvoke pass. In both cases, the right thing to do is to + // convert the call to an explicit setjmp or longjmp call. + case Intrinsic::setjmp: { + Value *V = ReplaceCallWith("setjmp", CI, CS.arg_begin(), CS.arg_end(), + Type::getInt32Ty(Context)); + if (!CI->getType()->isVoidTy()) + CI->replaceAllUsesWith(V); + break; + } + case Intrinsic::sigsetjmp: + if (!CI->getType()->isVoidTy()) + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + + case Intrinsic::longjmp: { + ReplaceCallWith("longjmp", CI, CS.arg_begin(), CS.arg_end(), + Type::getVoidTy(Context)); + break; + } + + case Intrinsic::siglongjmp: { + // Insert the call to abort + ReplaceCallWith("abort", CI, CS.arg_end(), CS.arg_end(), + Type::getVoidTy(Context)); + break; + } + case Intrinsic::ctpop: + CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI)); + break; + + case Intrinsic::bswap: + CI->replaceAllUsesWith(LowerBSWAP(Context, CI->getArgOperand(0), CI)); + break; + + case Intrinsic::ctlz: + CI->replaceAllUsesWith(LowerCTLZ(Context, CI->getArgOperand(0), CI)); + break; + + case Intrinsic::cttz: { + // cttz(x) -> ctpop(~X & (X-1)) + Value *Src = CI->getArgOperand(0); + Value *NotSrc = Builder.CreateNot(Src); + NotSrc->setName(Src->getName() + ".not"); + Value *SrcM1 = ConstantInt::get(Src->getType(), 1); + SrcM1 = Builder.CreateSub(Src, SrcM1); + Src = LowerCTPOP(Context, Builder.CreateAnd(NotSrc, SrcM1), CI); + CI->replaceAllUsesWith(Src); + break; + } + + case Intrinsic::stacksave: + case Intrinsic::stackrestore: { + if (!Warned) + errs() << "WARNING: this target does not support the llvm.stack" + << (Callee->getIntrinsicID() == Intrinsic::stacksave ? + "save" : "restore") << " intrinsic.\n"; + Warned = true; + if (Callee->getIntrinsicID() == Intrinsic::stacksave) + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + } + + case Intrinsic::returnaddress: + case Intrinsic::frameaddress: + errs() << "WARNING: this target does not support the llvm." + << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? + "return" : "frame") << "address intrinsic.\n"; + CI->replaceAllUsesWith(ConstantPointerNull::get( + cast(CI->getType()))); + break; + + case Intrinsic::prefetch: + break; // Simply strip out prefetches on unsupported architectures + + case Intrinsic::pcmarker: + break; // Simply strip out pcmarker on unsupported architectures + case Intrinsic::readcyclecounter: { + errs() << "WARNING: this target does not support the llvm.readcyclecoun" + << "ter intrinsic. It is being lowered to a constant 0\n"; + CI->replaceAllUsesWith(ConstantInt::get(Type::getInt64Ty(Context), 0)); + break; + } + + case Intrinsic::dbg_declare: + break; // Simply strip out debugging intrinsics + + case Intrinsic::eh_exception: + case Intrinsic::eh_selector: + CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); + break; + + case Intrinsic::eh_typeid_for: + // Return something different to eh_selector. + CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); + break; + + case Intrinsic::var_annotation: + break; // Strip out annotate intrinsic + + case Intrinsic::memcpy: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getArgOperand(0); + Ops[1] = CI->getArgOperand(1); + Ops[2] = Size; + ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); + break; + } + case Intrinsic::memmove: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getArgOperand(0); + Ops[1] = CI->getArgOperand(1); + Ops[2] = Size; + ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); + break; + } + case Intrinsic::memset: { + const IntegerType *IntPtr = TD.getIntPtrType(Context); + Value *Size = Builder.CreateIntCast(CI->getArgOperand(2), IntPtr, + /* isSigned */ false); + Value *Ops[3]; + Ops[0] = CI->getArgOperand(0); + // Extend the amount to i32. + Ops[1] = Builder.CreateIntCast(CI->getArgOperand(1), + Type::getInt32Ty(Context), + /* isSigned */ false); + Ops[2] = Size; + ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType()); + break; + } + case Intrinsic::sqrt: { + ReplaceFPIntrinsicWithCall(CI, "sqrtf", "sqrt", "sqrtl"); + break; + } + case Intrinsic::log: { + ReplaceFPIntrinsicWithCall(CI, "logf", "log", "logl"); + break; + } + case Intrinsic::log2: { + ReplaceFPIntrinsicWithCall(CI, "log2f", "log2", "log2l"); + break; + } + case Intrinsic::log10: { + ReplaceFPIntrinsicWithCall(CI, "log10f", "log10", "log10l"); + break; + } + case Intrinsic::exp: { + ReplaceFPIntrinsicWithCall(CI, "expf", "exp", "expl"); + break; + } + case Intrinsic::exp2: { + ReplaceFPIntrinsicWithCall(CI, "exp2f", "exp2", "exp2l"); + break; + } + case Intrinsic::pow: { + ReplaceFPIntrinsicWithCall(CI, "powf", "pow", "powl"); + break; + } + case Intrinsic::flt_rounds: + // Lower to "round to the nearest" + if (!CI->getType()->isVoidTy()) + CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); + break; + case Intrinsic::invariant_start: + case Intrinsic::lifetime_start: + // Discard region information. + CI->replaceAllUsesWith(UndefValue::get(CI->getType())); + break; + case Intrinsic::invariant_end: + case Intrinsic::lifetime_end: + // Discard region information. + break; + } + + assert(CI->use_empty() && + "Lowering should have eliminated any uses of the intrinsic call!"); + CI->eraseFromParent(); +} + +bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) { + // Verify this is a simple bswap. + if (CI->getNumArgOperands() != 1 || + CI->getType() != CI->getArgOperand(0)->getType() || + !CI->getType()->isIntegerTy()) + return false; + + const IntegerType *Ty = dyn_cast(CI->getType()); + if (!Ty) + return false; + + // Okay, we can do this xform, do so now. + const Type *Tys[] = { Ty }; + Module *M = CI->getParent()->getParent()->getParent(); + Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1); + + Value *Op = CI->getArgOperand(0); + Op = CallInst::Create(Int, Op, CI->getName(), CI); + + CI->replaceAllUsesWith(Op); + CI->eraseFromParent(); + return true; +} diff --git a/final/lib/CodeGen/LLVMTargetMachine.cpp b/final/lib/CodeGen/LLVMTargetMachine.cpp new file mode 100644 index 00000000000..377f80db7bf --- /dev/null +++ b/final/lib/CodeGen/LLVMTargetMachine.cpp @@ -0,0 +1,453 @@ +//===-- LLVMTargetMachine.cpp - Implement the LLVMTargetMachine class -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LLVMTargetMachine class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/StandardPasses.h" +using namespace llvm; + +namespace llvm { + bool EnableFastISel; +} + +static cl::opt DisablePostRA("disable-post-ra", cl::Hidden, + cl::desc("Disable Post Regalloc")); +static cl::opt DisableBranchFold("disable-branch-fold", cl::Hidden, + cl::desc("Disable branch folding")); +static cl::opt DisableTailDuplicate("disable-tail-duplicate", cl::Hidden, + cl::desc("Disable tail duplication")); +static cl::opt DisableEarlyTailDup("disable-early-taildup", cl::Hidden, + cl::desc("Disable pre-register allocation tail duplication")); +static cl::opt DisableCodePlace("disable-code-place", cl::Hidden, + cl::desc("Disable code placement")); +static cl::opt DisableSSC("disable-ssc", cl::Hidden, + cl::desc("Disable Stack Slot Coloring")); +static cl::opt DisableMachineLICM("disable-machine-licm", cl::Hidden, + cl::desc("Disable Machine LICM")); +static cl::opt DisablePostRAMachineLICM("disable-postra-machine-licm", + cl::Hidden, + cl::desc("Disable Machine LICM")); +static cl::opt DisableMachineSink("disable-machine-sink", cl::Hidden, + cl::desc("Disable Machine Sinking")); +static cl::opt DisableLSR("disable-lsr", cl::Hidden, + cl::desc("Disable Loop Strength Reduction Pass")); +static cl::opt DisableCGP("disable-cgp", cl::Hidden, + cl::desc("Disable Codegen Prepare")); +static cl::opt PrintLSR("print-lsr-output", cl::Hidden, + cl::desc("Print LLVM IR produced by the loop-reduce pass")); +static cl::opt PrintISelInput("print-isel-input", cl::Hidden, + cl::desc("Print LLVM IR input to isel pass")); +static cl::opt PrintGCInfo("print-gc", cl::Hidden, + cl::desc("Dump garbage collector data")); +static cl::opt ShowMCEncoding("show-mc-encoding", cl::Hidden, + cl::desc("Show encoding in .s output")); +static cl::opt ShowMCInst("show-mc-inst", cl::Hidden, + cl::desc("Show instruction structure in .s output")); +static cl::opt EnableMCLogging("enable-mc-api-logging", cl::Hidden, + cl::desc("Enable MC API logging")); +static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, + cl::desc("Verify generated machine code"), + cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); + +static cl::opt +AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), + cl::init(cl::BOU_UNSET)); + +static bool getVerboseAsm() { + switch (AsmVerbose) { + default: + case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault(); + case cl::BOU_TRUE: return true; + case cl::BOU_FALSE: return false; + } +} + +// Enable or disable FastISel. Both options are needed, because +// FastISel is enabled by default with -fast, and we wish to be +// able to enable or disable fast-isel independently from -O0. +static cl::opt +EnableFastISelOption("fast-isel", cl::Hidden, + cl::desc("Enable the \"fast\" instruction selector")); + +LLVMTargetMachine::LLVMTargetMachine(const Target &T, + const std::string &Triple) + : TargetMachine(T), TargetTriple(Triple) { + AsmInfo = T.createAsmInfo(TargetTriple); +} + +// Set the default code model for the JIT for a generic target. +// FIXME: Is small right here? or .is64Bit() ? Large : Small? +void LLVMTargetMachine::setCodeModelForJIT() { + setCodeModel(CodeModel::Small); +} + +// Set the default code model for static compilation for a generic target. +void LLVMTargetMachine::setCodeModelForStatic() { + setCodeModel(CodeModel::Small); +} + +bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + formatted_raw_ostream &Out, + CodeGenFileType FileType, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { + // Add common CodeGen passes. + MCContext *Context = 0; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Context)) + return true; + assert(Context != 0 && "Failed to get MCContext"); + + const MCAsmInfo &MAI = *getMCAsmInfo(); + OwningPtr AsmStreamer; + + switch (FileType) { + default: return true; + case CGFT_AssemblyFile: { + MCInstPrinter *InstPrinter = + getTarget().createMCInstPrinter(MAI.getAssemblerDialect(), MAI); + + // Create a code emitter if asked to show the encoding. + MCCodeEmitter *MCE = 0; + TargetAsmBackend *TAB = 0; + if (ShowMCEncoding) { + MCE = getTarget().createCodeEmitter(*this, *Context); + TAB = getTarget().createAsmBackend(TargetTriple); + } + + MCStreamer *S = getTarget().createAsmStreamer(*Context, Out, + getVerboseAsm(), + hasMCUseLoc(), + InstPrinter, + MCE, TAB, + ShowMCInst); + AsmStreamer.reset(S); + break; + } + case CGFT_ObjectFile: { + // Create the code emitter for the target if it exists. If not, .o file + // emission fails. + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Context); + TargetAsmBackend *TAB = getTarget().createAsmBackend(TargetTriple); + if (MCE == 0 || TAB == 0) + return true; + + AsmStreamer.reset(getTarget().createObjectStreamer(TargetTriple, *Context, + *TAB, Out, MCE, + hasMCRelaxAll(), + hasMCNoExecStack())); + AsmStreamer.get()->InitSections(); + break; + } + case CGFT_Null: + // The Null output is intended for use for performance analysis and testing, + // not real users. + AsmStreamer.reset(createNullStreamer(*Context)); + break; + } + + if (EnableMCLogging) + AsmStreamer.reset(createLoggingStreamer(AsmStreamer.take(), errs())); + + // Create the AsmPrinter, which takes ownership of AsmStreamer if successful. + FunctionPass *Printer = getTarget().createAsmPrinter(*this, *AsmStreamer); + if (Printer == 0) + return true; + + // If successful, createAsmPrinter took ownership of AsmStreamer. + AsmStreamer.take(); + + PM.add(Printer); + + // Make sure the code model is set. + setCodeModelForStatic(); + PM.add(createGCInfoDeleter()); + return false; +} + +/// addPassesToEmitMachineCode - Add passes to the specified pass manager to +/// get machine code emitted. This uses a JITCodeEmitter object to handle +/// actually outputting the machine code and resolving things like the address +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, + JITCodeEmitter &JCE, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { + // Make sure the code model is set. + setCodeModelForJIT(); + + // Add common CodeGen passes. + MCContext *Ctx = 0; + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) + return true; + + addCodeEmitter(PM, OptLevel, JCE); + PM.add(createGCInfoDeleter()); + + return false; // success! +} + +/// addPassesToEmitMC - Add passes to the specified pass manager to get +/// machine code emitted with the MCJIT. This method returns true if machine +/// code is not supported. It fills the MCContext Ctx pointer which can be +/// used to build custom MCStreamer. +/// +bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, + MCContext *&Ctx, + CodeGenOpt::Level OptLevel, + bool DisableVerify) { + // Add common CodeGen passes. + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify, Ctx)) + return true; + // Make sure the code model is set. + setCodeModelForJIT(); + + return false; // success! +} + +static void printNoVerify(PassManagerBase &PM, const char *Banner) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); +} + +static void printAndVerify(PassManagerBase &PM, + const char *Banner) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); + + if (VerifyMachineCode) + PM.add(createMachineVerifierPass(Banner)); +} + +/// addCommonCodeGenPasses - Add standard LLVM codegen passes used for both +/// emitting to assembly files or machine code output. +/// +bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, + CodeGenOpt::Level OptLevel, + bool DisableVerify, + MCContext *&OutContext) { + // Standard LLVM-Level Passes. + + // Basic AliasAnalysis support. + createStandardAliasAnalysisPasses(&PM); + + // Before running any passes, run the verifier to determine if the input + // coming from the front-end and/or optimizer is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + + // Run loop strength reduction before anything else. + if (OptLevel != CodeGenOpt::None && !DisableLSR) { + PM.add(createLoopStrengthReducePass(getTargetLowering())); + if (PrintLSR) + PM.add(createPrintFunctionPass("\n\n*** Code after LSR ***\n", &dbgs())); + } + + PM.add(createGCLoweringPass()); + + // Make sure that no unreachable blocks are instruction selected. + PM.add(createUnreachableBlockEliminationPass()); + + // Turn exception handling constructs into something the code generators can + // handle. + switch (getMCAsmInfo()->getExceptionHandlingType()) { + case ExceptionHandling::SjLj: + // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both + // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise, + // catch info can get misplaced when a selector ends up more than one block + // removed from the parent invoke(s). This could happen when a landing + // pad is shared by multiple invokes and is also a target of a normal + // edge from elsewhere. + PM.add(createSjLjEHPass(getTargetLowering())); + // FALLTHROUGH + case ExceptionHandling::DwarfCFI: + case ExceptionHandling::DwarfTable: + case ExceptionHandling::ARM: + PM.add(createDwarfEHPass(this)); + break; + case ExceptionHandling::None: + PM.add(createLowerInvokePass(getTargetLowering())); + + // The lower invoke pass may create unreachable code. Remove it. + PM.add(createUnreachableBlockEliminationPass()); + break; + } + + if (OptLevel != CodeGenOpt::None && !DisableCGP) + PM.add(createCodeGenPreparePass(getTargetLowering())); + + PM.add(createStackProtectorPass(getTargetLowering())); + + addPreISel(PM, OptLevel); + + if (PrintISelInput) + PM.add(createPrintFunctionPass("\n\n" + "*** Final LLVM Code input to ISel ***\n", + &dbgs())); + + // All passes which modify the LLVM IR are now complete; run the verifier + // to ensure that the IR is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + + // Standard Lower-Level Passes. + + // Install a MachineModuleInfo class, which is an immutable pass that holds + // all the per-module stuff we're generating, including MCContext. + TargetAsmInfo *TAI = new TargetAsmInfo(*this); + MachineModuleInfo *MMI = new MachineModuleInfo(*getMCAsmInfo(), TAI); + PM.add(MMI); + OutContext = &MMI->getContext(); // Return the MCContext specifically by-ref. + + // Set up a MachineFunction for the rest of CodeGen to work on. + PM.add(new MachineFunctionAnalysis(*this, OptLevel)); + + // Enable FastISel with -fast, but allow that to be overridden. + if (EnableFastISelOption == cl::BOU_TRUE || + (OptLevel == CodeGenOpt::None && EnableFastISelOption != cl::BOU_FALSE)) + EnableFastISel = true; + + // Ask the target for an isel. + if (addInstSelector(PM, OptLevel)) + return true; + + // Print the instruction selected machine code... + printAndVerify(PM, "After Instruction Selection"); + + // Expand pseudo-instructions emitted by ISel. + PM.add(createExpandISelPseudosPass()); + + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + if (OptLevel != CodeGenOpt::None) + PM.add(createOptimizePHIsPass()); + + // If the target requests it, assign local variables to stack slots relative + // to one another and simplify frame index references where possible. + PM.add(createLocalStackSlotAllocationPass()); + + if (OptLevel != CodeGenOpt::None) { + // With optimization, dead code should already be eliminated. However + // there is one known exception: lowered code for arguments that are only + // used by tail calls, where the tail calls reuse the incoming stack + // arguments directly (see t11 in test/CodeGen/X86/sibcall.ll). + PM.add(createDeadMachineInstructionElimPass()); + printAndVerify(PM, "After codegen DCE pass"); + + if (!DisableMachineLICM) + PM.add(createMachineLICMPass()); + PM.add(createMachineCSEPass()); + if (!DisableMachineSink) + PM.add(createMachineSinkingPass()); + printAndVerify(PM, "After Machine LICM, CSE and Sinking passes"); + + PM.add(createPeepholeOptimizerPass()); + printAndVerify(PM, "After codegen peephole optimization pass"); + } + + // Pre-ra tail duplication. + if (OptLevel != CodeGenOpt::None && !DisableEarlyTailDup) { + PM.add(createTailDuplicatePass(true)); + printAndVerify(PM, "After Pre-RegAlloc TailDuplicate"); + } + + // Run pre-ra passes. + if (addPreRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PreRegAlloc passes"); + + // Perform register allocation. + PM.add(createRegisterAllocator(OptLevel)); + printAndVerify(PM, "After Register Allocation"); + + // Perform stack slot coloring and post-ra machine LICM. + if (OptLevel != CodeGenOpt::None) { + // FIXME: Re-enable coloring with register when it's capable of adding + // kill markers. + if (!DisableSSC) + PM.add(createStackSlotColoringPass(false)); + + // Run post-ra machine LICM to hoist reloads / remats. + if (!DisablePostRAMachineLICM) + PM.add(createMachineLICMPass(false)); + + printAndVerify(PM, "After StackSlotColoring and postra Machine LICM"); + } + + // Run post-ra passes. + if (addPostRegAlloc(PM, OptLevel)) + printAndVerify(PM, "After PostRegAlloc passes"); + + PM.add(createLowerSubregsPass()); + printAndVerify(PM, "After LowerSubregs"); + + // Insert prolog/epilog code. Eliminate abstract frame index references... + PM.add(createPrologEpilogCodeInserter()); + printAndVerify(PM, "After PrologEpilogCodeInserter"); + + // Run pre-sched2 passes. + if (addPreSched2(PM, OptLevel)) + printAndVerify(PM, "After PreSched2 passes"); + + // Second pass scheduler. + if (OptLevel != CodeGenOpt::None && !DisablePostRA) { + PM.add(createPostRAScheduler(OptLevel)); + printAndVerify(PM, "After PostRAScheduler"); + } + + // Branch folding must be run after regalloc and prolog/epilog insertion. + if (OptLevel != CodeGenOpt::None && !DisableBranchFold) { + PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); + printNoVerify(PM, "After BranchFolding"); + } + + // Tail duplication. + if (OptLevel != CodeGenOpt::None && !DisableTailDuplicate) { + PM.add(createTailDuplicatePass(false)); + printNoVerify(PM, "After TailDuplicate"); + } + + PM.add(createGCMachineCodeAnalysisPass()); + + if (PrintGCInfo) + PM.add(createGCInfoPrinter(dbgs())); + + if (OptLevel != CodeGenOpt::None && !DisableCodePlace) { + PM.add(createCodePlacementOptPass()); + printNoVerify(PM, "After CodePlacementOpt"); + } + + if (addPreEmitPass(PM, OptLevel)) + printNoVerify(PM, "After PreEmit passes"); + + return false; +} diff --git a/final/lib/CodeGen/LatencyPriorityQueue.cpp b/final/lib/CodeGen/LatencyPriorityQueue.cpp new file mode 100644 index 00000000000..0eb009ddac2 --- /dev/null +++ b/final/lib/CodeGen/LatencyPriorityQueue.cpp @@ -0,0 +1,152 @@ +//===---- LatencyPriorityQueue.cpp - A latency-oriented priority queue ----===// +// +// 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 LatencyPriorityQueue class, which is a +// SchedulingPriorityQueue that schedules using latency information to +// reduce the length of the critical path through the basic block. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "scheduler" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +bool latency_sort::operator()(const SUnit *LHS, const SUnit *RHS) const { + // The isScheduleHigh flag allows nodes with wraparound dependencies that + // cannot easily be modeled as edges with latencies to be scheduled as + // soon as possible in a top-down schedule. + if (LHS->isScheduleHigh && !RHS->isScheduleHigh) + return false; + if (!LHS->isScheduleHigh && RHS->isScheduleHigh) + return true; + + unsigned LHSNum = LHS->NodeNum; + unsigned RHSNum = RHS->NodeNum; + + // The most important heuristic is scheduling the critical path. + unsigned LHSLatency = PQ->getLatency(LHSNum); + unsigned RHSLatency = PQ->getLatency(RHSNum); + if (LHSLatency < RHSLatency) return true; + if (LHSLatency > RHSLatency) return false; + + // After that, if two nodes have identical latencies, look to see if one will + // unblock more other nodes than the other. + unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum); + unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum); + if (LHSBlocked < RHSBlocked) return true; + if (LHSBlocked > RHSBlocked) return false; + + // Finally, just to provide a stable ordering, use the node number as a + // deciding factor. + return LHSNum < RHSNum; +} + + +/// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor +/// of SU, return it, otherwise return null. +SUnit *LatencyPriorityQueue::getSingleUnscheduledPred(SUnit *SU) { + SUnit *OnlyAvailablePred = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + SUnit &Pred = *I->getSUnit(); + if (!Pred.isScheduled) { + // We found an available, but not scheduled, predecessor. If it's the + // only one we have found, keep track of it... otherwise give up. + if (OnlyAvailablePred && OnlyAvailablePred != &Pred) + return 0; + OnlyAvailablePred = &Pred; + } + } + + return OnlyAvailablePred; +} + +void LatencyPriorityQueue::push(SUnit *SU) { + // Look at all of the successors of this node. Count the number of nodes that + // this node is the sole unscheduled node for. + unsigned NumNodesBlocking = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (getSingleUnscheduledPred(I->getSUnit()) == SU) + ++NumNodesBlocking; + } + NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking; + + Queue.push_back(SU); +} + + +// ScheduledNode - As nodes are scheduled, we look to see if there are any +// successor nodes that have a single unscheduled predecessor. If so, that +// single predecessor has a higher priority, since scheduling it will make +// the node available. +void LatencyPriorityQueue::ScheduledNode(SUnit *SU) { + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + AdjustPriorityOfUnscheduledPreds(I->getSUnit()); + } +} + +/// AdjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just +/// scheduled. If SU is not itself available, then there is at least one +/// predecessor node that has not been scheduled yet. If SU has exactly ONE +/// unscheduled predecessor, we want to increase its priority: it getting +/// scheduled will make this node available, so it is better than some other +/// node of the same priority that will not make a node available. +void LatencyPriorityQueue::AdjustPriorityOfUnscheduledPreds(SUnit *SU) { + if (SU->isAvailable) return; // All preds scheduled. + + SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU); + if (OnlyAvailablePred == 0 || !OnlyAvailablePred->isAvailable) return; + + // Okay, we found a single predecessor that is available, but not scheduled. + // Since it is available, it must be in the priority queue. First remove it. + remove(OnlyAvailablePred); + + // Reinsert the node into the priority queue, which recomputes its + // NumNodesSolelyBlocking value. + push(OnlyAvailablePred); +} + +SUnit *LatencyPriorityQueue::pop() { + if (empty()) return NULL; + std::vector::iterator Best = Queue.begin(); + for (std::vector::iterator I = llvm::next(Queue.begin()), + E = Queue.end(); I != E; ++I) + if (Picker(*Best, *I)) + Best = I; + SUnit *V = *Best; + if (Best != prior(Queue.end())) + std::swap(*Best, Queue.back()); + Queue.pop_back(); + return V; +} + +void LatencyPriorityQueue::remove(SUnit *SU) { + assert(!Queue.empty() && "Queue is empty!"); + std::vector::iterator I = std::find(Queue.begin(), Queue.end(), SU); + if (I != prior(Queue.end())) + std::swap(*I, Queue.back()); + Queue.pop_back(); +} + +#ifdef NDEBUG +void LatencyPriorityQueue::dump(ScheduleDAG *DAG) const {} +#else +void LatencyPriorityQueue::dump(ScheduleDAG *DAG) const { + LatencyPriorityQueue q = *this; + while (!q.empty()) { + SUnit *su = q.pop(); + dbgs() << "Height " << su->getHeight() << ": "; + su->dump(DAG); + } +} +#endif diff --git a/final/lib/CodeGen/LiveDebugVariables.cpp b/final/lib/CodeGen/LiveDebugVariables.cpp new file mode 100644 index 00000000000..853ec1ac7c1 --- /dev/null +++ b/final/lib/CodeGen/LiveDebugVariables.cpp @@ -0,0 +1,711 @@ +//===- LiveDebugVariables.cpp - Tracking debug info variables -------------===// +// +// 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 LiveDebugVariables analysis. +// +// Remove all DBG_VALUE instructions referencing virtual registers and replace +// them with a data structure tracking where live user variables are kept - in a +// virtual register or in a stack slot. +// +// Allow the data structure to be updated during register allocation when values +// are moved between registers and stack slots. Finally emit new DBG_VALUE +// instructions after register allocation is complete. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "livedebug" +#include "LiveDebugVariables.h" +#include "VirtRegMap.h" +#include "llvm/Constants.h" +#include "llvm/Metadata.h" +#include "llvm/Value.h" +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +static cl::opt +EnableLDV("live-debug-variables", cl::init(true), + cl::desc("Enable the live debug variables pass"), cl::Hidden); + +char LiveDebugVariables::ID = 0; + +INITIALIZE_PASS_BEGIN(LiveDebugVariables, "livedebugvars", + "Debug Variable Analysis", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_END(LiveDebugVariables, "livedebugvars", + "Debug Variable Analysis", false, false) + +void LiveDebugVariables::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequiredTransitive(); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +LiveDebugVariables::LiveDebugVariables() : MachineFunctionPass(ID), pImpl(0) { + initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); +} + +/// LocMap - Map of where a user value is live, and its location. +typedef IntervalMap LocMap; + +/// UserValue - A user value is a part of a debug info user variable. +/// +/// A DBG_VALUE instruction notes that (a sub-register of) a virtual register +/// holds part of a user variable. The part is identified by a byte offset. +/// +/// UserValues are grouped into equivalence classes for easier searching. Two +/// user values are related if they refer to the same variable, or if they are +/// held by the same virtual register. The equivalence class is the transitive +/// closure of that relation. +namespace { +class UserValue { + const MDNode *variable; ///< The debug info variable we are part of. + unsigned offset; ///< Byte offset into variable. + DebugLoc dl; ///< The debug location for the variable. This is + ///< used by dwarf writer to find lexical scope. + UserValue *leader; ///< Equivalence class leader. + UserValue *next; ///< Next value in equivalence class, or null. + + /// Numbered locations referenced by locmap. + SmallVector locations; + + /// Map of slot indices where this value is live. + LocMap locInts; + + /// coalesceLocation - After LocNo was changed, check if it has become + /// identical to another location, and coalesce them. This may cause LocNo or + /// a later location to be erased, but no earlier location will be erased. + void coalesceLocation(unsigned LocNo); + + /// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo. + void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo, + LiveIntervals &LIS, const TargetInstrInfo &TII); + + /// insertDebugKill - Insert an undef DBG_VALUE into MBB at Idx. + void insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS, const TargetInstrInfo &TII); + +public: + /// UserValue - Create a new UserValue. + UserValue(const MDNode *var, unsigned o, DebugLoc L, + LocMap::Allocator &alloc) + : variable(var), offset(o), dl(L), leader(this), next(0), locInts(alloc) + {} + + /// getLeader - Get the leader of this value's equivalence class. + UserValue *getLeader() { + UserValue *l = leader; + while (l != l->leader) + l = l->leader; + return leader = l; + } + + /// getNext - Return the next UserValue in the equivalence class. + UserValue *getNext() const { return next; } + + /// match - Does this UserValue match the aprameters? + bool match(const MDNode *Var, unsigned Offset) const { + return Var == variable && Offset == offset; + } + + /// merge - Merge equivalence classes. + static UserValue *merge(UserValue *L1, UserValue *L2) { + L2 = L2->getLeader(); + if (!L1) + return L2; + L1 = L1->getLeader(); + if (L1 == L2) + return L1; + // Splice L2 before L1's members. + UserValue *End = L2; + while (End->next) + End->leader = L1, End = End->next; + End->leader = L1; + End->next = L1->next; + L1->next = L2; + return L1; + } + + /// getLocationNo - Return the location number that matches Loc. + unsigned getLocationNo(const MachineOperand &LocMO) { + if (LocMO.isReg() && LocMO.getReg() == 0) + return ~0u; + for (unsigned i = 0, e = locations.size(); i != e; ++i) + if (LocMO.isIdenticalTo(locations[i])) + return i; + locations.push_back(LocMO); + // We are storing a MachineOperand outside a MachineInstr. + locations.back().clearParent(); + return locations.size() - 1; + } + + /// addDef - Add a definition point to this value. + void addDef(SlotIndex Idx, const MachineOperand &LocMO) { + // Add a singular (Idx,Idx) -> Loc mapping. + LocMap::iterator I = locInts.find(Idx); + if (!I.valid() || I.start() != Idx) + I.insert(Idx, Idx.getNextSlot(), getLocationNo(LocMO)); + } + + /// extendDef - Extend the current definition as far as possible down the + /// dominator tree. Stop when meeting an existing def or when leaving the live + /// range of VNI. + /// @param Idx Starting point for the definition. + /// @param LocNo Location number to propagate. + /// @param LI Restrict liveness to where LI has the value VNI. May be null. + /// @param VNI When LI is not null, this is the value to restrict to. + /// @param LIS Live intervals analysis. + /// @param MDT Dominator tree. + void extendDef(SlotIndex Idx, unsigned LocNo, + LiveInterval *LI, const VNInfo *VNI, + LiveIntervals &LIS, MachineDominatorTree &MDT); + + /// computeIntervals - Compute the live intervals of all locations after + /// collecting all their def points. + void computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT); + + /// renameRegister - Update locations to rewrite OldReg as NewReg:SubIdx. + void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx, + const TargetRegisterInfo *TRI); + + /// rewriteLocations - Rewrite virtual register locations according to the + /// provided virtual register map. + void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI); + + /// emitDebugVariables - Recreate DBG_VALUE instruction from data structures. + void emitDebugValues(VirtRegMap *VRM, + LiveIntervals &LIS, const TargetInstrInfo &TRI); + + /// findDebugLoc - Return DebugLoc used for this DBG_VALUE instruction. A + /// variable may have more than one corresponding DBG_VALUE instructions. + /// Only first one needs DebugLoc to identify variable's lexical scope + /// in source file. + DebugLoc findDebugLoc(); + void print(raw_ostream&, const TargetRegisterInfo*); +}; +} // namespace + +/// LDVImpl - Implementation of the LiveDebugVariables pass. +namespace { +class LDVImpl { + LiveDebugVariables &pass; + LocMap::Allocator allocator; + MachineFunction *MF; + LiveIntervals *LIS; + MachineDominatorTree *MDT; + const TargetRegisterInfo *TRI; + + /// userValues - All allocated UserValue instances. + SmallVector userValues; + + /// Map virtual register to eq class leader. + typedef DenseMap VRMap; + VRMap virtRegToEqClass; + + /// Map user variable to eq class leader. + typedef DenseMap UVMap; + UVMap userVarMap; + + /// getUserValue - Find or create a UserValue. + UserValue *getUserValue(const MDNode *Var, unsigned Offset, DebugLoc DL); + + /// lookupVirtReg - Find the EC leader for VirtReg or null. + UserValue *lookupVirtReg(unsigned VirtReg); + + /// mapVirtReg - Map virtual register to an equivalence class. + void mapVirtReg(unsigned VirtReg, UserValue *EC); + + /// handleDebugValue - Add DBG_VALUE instruction to our maps. + /// @param MI DBG_VALUE instruction + /// @param Idx Last valid SLotIndex before instruction. + /// @return True if the DBG_VALUE instruction should be deleted. + bool handleDebugValue(MachineInstr *MI, SlotIndex Idx); + + /// collectDebugValues - Collect and erase all DBG_VALUE instructions, adding + /// a UserValue def for each instruction. + /// @param mf MachineFunction to be scanned. + /// @return True if any debug values were found. + bool collectDebugValues(MachineFunction &mf); + + /// computeIntervals - Compute the live intervals of all user values after + /// collecting all their def points. + void computeIntervals(); + +public: + LDVImpl(LiveDebugVariables *ps) : pass(*ps) {} + bool runOnMachineFunction(MachineFunction &mf); + + /// clear - Relase all memory. + void clear() { + DeleteContainerPointers(userValues); + userValues.clear(); + virtRegToEqClass.clear(); + userVarMap.clear(); + } + + /// renameRegister - Replace all references to OldReg wiht NewReg:SubIdx. + void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx); + + /// emitDebugVariables - Recreate DBG_VALUE instruction from data structures. + void emitDebugValues(VirtRegMap *VRM); + + void print(raw_ostream&); +}; +} // namespace + +void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) { + if (const MDString *MDS = dyn_cast(variable->getOperand(2))) + OS << "!\"" << MDS->getString() << "\"\t"; + if (offset) + OS << '+' << offset; + for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) { + OS << " [" << I.start() << ';' << I.stop() << "):"; + if (I.value() == ~0u) + OS << "undef"; + else + OS << I.value(); + } + for (unsigned i = 0, e = locations.size(); i != e; ++i) + OS << " Loc" << i << '=' << locations[i]; + OS << '\n'; +} + +void LDVImpl::print(raw_ostream &OS) { + OS << "********** DEBUG VARIABLES **********\n"; + for (unsigned i = 0, e = userValues.size(); i != e; ++i) + userValues[i]->print(OS, TRI); +} + +void UserValue::coalesceLocation(unsigned LocNo) { + unsigned KeepLoc = 0; + for (unsigned e = locations.size(); KeepLoc != e; ++KeepLoc) { + if (KeepLoc == LocNo) + continue; + if (locations[KeepLoc].isIdenticalTo(locations[LocNo])) + break; + } + // No matches. + if (KeepLoc == locations.size()) + return; + + // Keep the smaller location, erase the larger one. + unsigned EraseLoc = LocNo; + if (KeepLoc > EraseLoc) + std::swap(KeepLoc, EraseLoc); + locations.erase(locations.begin() + EraseLoc); + + // Rewrite values. + for (LocMap::iterator I = locInts.begin(); I.valid(); ++I) { + unsigned v = I.value(); + if (v == EraseLoc) + I.setValue(KeepLoc); // Coalesce when possible. + else if (v > EraseLoc) + I.setValueUnchecked(v-1); // Avoid coalescing with untransformed values. + } +} + +UserValue *LDVImpl::getUserValue(const MDNode *Var, unsigned Offset, + DebugLoc DL) { + UserValue *&Leader = userVarMap[Var]; + if (Leader) { + UserValue *UV = Leader->getLeader(); + Leader = UV; + for (; UV; UV = UV->getNext()) + if (UV->match(Var, Offset)) + return UV; + } + + UserValue *UV = new UserValue(Var, Offset, DL, allocator); + userValues.push_back(UV); + Leader = UserValue::merge(Leader, UV); + return UV; +} + +void LDVImpl::mapVirtReg(unsigned VirtReg, UserValue *EC) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && "Only map VirtRegs"); + UserValue *&Leader = virtRegToEqClass[VirtReg]; + Leader = UserValue::merge(Leader, EC); +} + +UserValue *LDVImpl::lookupVirtReg(unsigned VirtReg) { + if (UserValue *UV = virtRegToEqClass.lookup(VirtReg)) + return UV->getLeader(); + return 0; +} + +bool LDVImpl::handleDebugValue(MachineInstr *MI, SlotIndex Idx) { + // DBG_VALUE loc, offset, variable + if (MI->getNumOperands() != 3 || + !MI->getOperand(1).isImm() || !MI->getOperand(2).isMetadata()) { + DEBUG(dbgs() << "Can't handle " << *MI); + return false; + } + + // Get or create the UserValue for (variable,offset). + unsigned Offset = MI->getOperand(1).getImm(); + const MDNode *Var = MI->getOperand(2).getMetadata(); + UserValue *UV = getUserValue(Var, Offset, MI->getDebugLoc()); + + // If the location is a virtual register, make sure it is mapped. + if (MI->getOperand(0).isReg()) { + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + mapVirtReg(Reg, UV); + } + + UV->addDef(Idx, MI->getOperand(0)); + return true; +} + +bool LDVImpl::collectDebugValues(MachineFunction &mf) { + bool Changed = false; + for (MachineFunction::iterator MFI = mf.begin(), MFE = mf.end(); MFI != MFE; + ++MFI) { + MachineBasicBlock *MBB = MFI; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), MBBE = MBB->end(); + MBBI != MBBE;) { + if (!MBBI->isDebugValue()) { + ++MBBI; + continue; + } + // DBG_VALUE has no slot index, use the previous instruction instead. + SlotIndex Idx = MBBI == MBB->begin() ? + LIS->getMBBStartIdx(MBB) : + LIS->getInstructionIndex(llvm::prior(MBBI)).getDefIndex(); + // Handle consecutive DBG_VALUE instructions with the same slot index. + do { + if (handleDebugValue(MBBI, Idx)) { + MBBI = MBB->erase(MBBI); + Changed = true; + } else + ++MBBI; + } while (MBBI != MBBE && MBBI->isDebugValue()); + } + } + return Changed; +} + +void UserValue::extendDef(SlotIndex Idx, unsigned LocNo, + LiveInterval *LI, const VNInfo *VNI, + LiveIntervals &LIS, MachineDominatorTree &MDT) { + SmallVector Todo; + Todo.push_back(Idx); + + do { + SlotIndex Start = Todo.pop_back_val(); + MachineBasicBlock *MBB = LIS.getMBBFromIndex(Start); + SlotIndex Stop = LIS.getMBBEndIdx(MBB); + LocMap::iterator I = locInts.find(Start); + + // Limit to VNI's live range. + bool ToEnd = true; + if (LI && VNI) { + LiveRange *Range = LI->getLiveRangeContaining(Start); + if (!Range || Range->valno != VNI) + continue; + if (Range->end < Stop) + Stop = Range->end, ToEnd = false; + } + + // There could already be a short def at Start. + if (I.valid() && I.start() <= Start) { + // Stop when meeting a different location or an already extended interval. + Start = Start.getNextSlot(); + if (I.value() != LocNo || I.stop() != Start) + continue; + // This is a one-slot placeholder. Just skip it. + ++I; + } + + // Limited by the next def. + if (I.valid() && I.start() < Stop) + Stop = I.start(), ToEnd = false; + + if (Start >= Stop) + continue; + + I.insert(Start, Stop, LocNo); + + // If we extended to the MBB end, propagate down the dominator tree. + if (!ToEnd) + continue; + const std::vector &Children = + MDT.getNode(MBB)->getChildren(); + for (unsigned i = 0, e = Children.size(); i != e; ++i) + Todo.push_back(LIS.getMBBStartIdx(Children[i]->getBlock())); + } while (!Todo.empty()); +} + +void +UserValue::computeIntervals(LiveIntervals &LIS, MachineDominatorTree &MDT) { + SmallVector, 16> Defs; + + // Collect all defs to be extended (Skipping undefs). + for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) + if (I.value() != ~0u) + Defs.push_back(std::make_pair(I.start(), I.value())); + + for (unsigned i = 0, e = Defs.size(); i != e; ++i) { + SlotIndex Idx = Defs[i].first; + unsigned LocNo = Defs[i].second; + const MachineOperand &Loc = locations[LocNo]; + + // Register locations are constrained to where the register value is live. + if (Loc.isReg() && LIS.hasInterval(Loc.getReg())) { + LiveInterval *LI = &LIS.getInterval(Loc.getReg()); + const VNInfo *VNI = LI->getVNInfoAt(Idx); + extendDef(Idx, LocNo, LI, VNI, LIS, MDT); + } else + extendDef(Idx, LocNo, 0, 0, LIS, MDT); + } + + // Finally, erase all the undefs. + for (LocMap::iterator I = locInts.begin(); I.valid();) + if (I.value() == ~0u) + I.erase(); + else + ++I; +} + +void LDVImpl::computeIntervals() { + for (unsigned i = 0, e = userValues.size(); i != e; ++i) + userValues[i]->computeIntervals(*LIS, *MDT); +} + +bool LDVImpl::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + LIS = &pass.getAnalysis(); + MDT = &pass.getAnalysis(); + TRI = mf.getTarget().getRegisterInfo(); + clear(); + DEBUG(dbgs() << "********** COMPUTING LIVE DEBUG VARIABLES: " + << ((Value*)mf.getFunction())->getName() + << " **********\n"); + + bool Changed = collectDebugValues(mf); + computeIntervals(); + DEBUG(print(dbgs())); + return Changed; +} + +bool LiveDebugVariables::runOnMachineFunction(MachineFunction &mf) { + if (!EnableLDV) + return false; + if (!pImpl) + pImpl = new LDVImpl(this); + return static_cast(pImpl)->runOnMachineFunction(mf); +} + +void LiveDebugVariables::releaseMemory() { + if (pImpl) + static_cast(pImpl)->clear(); +} + +LiveDebugVariables::~LiveDebugVariables() { + if (pImpl) + delete static_cast(pImpl); +} + +void UserValue:: +renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx, + const TargetRegisterInfo *TRI) { + for (unsigned i = locations.size(); i; --i) { + unsigned LocNo = i - 1; + MachineOperand &Loc = locations[LocNo]; + if (!Loc.isReg() || Loc.getReg() != OldReg) + continue; + if (TargetRegisterInfo::isPhysicalRegister(NewReg)) + Loc.substPhysReg(NewReg, *TRI); + else + Loc.substVirtReg(NewReg, SubIdx, *TRI); + coalesceLocation(LocNo); + } +} + +void LDVImpl:: +renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx) { + UserValue *UV = lookupVirtReg(OldReg); + if (!UV) + return; + + if (TargetRegisterInfo::isVirtualRegister(NewReg)) + mapVirtReg(NewReg, UV); + virtRegToEqClass.erase(OldReg); + + do { + UV->renameRegister(OldReg, NewReg, SubIdx, TRI); + UV = UV->getNext(); + } while (UV); +} + +void LiveDebugVariables:: +renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx) { + if (pImpl) + static_cast(pImpl)->renameRegister(OldReg, NewReg, SubIdx); +} + +void +UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI) { + // Iterate over locations in reverse makes it easier to handle coalescing. + for (unsigned i = locations.size(); i ; --i) { + unsigned LocNo = i-1; + MachineOperand &Loc = locations[LocNo]; + // Only virtual registers are rewritten. + if (!Loc.isReg() || !Loc.getReg() || + !TargetRegisterInfo::isVirtualRegister(Loc.getReg())) + continue; + unsigned VirtReg = Loc.getReg(); + if (VRM.isAssignedReg(VirtReg) && + TargetRegisterInfo::isPhysicalRegister(VRM.getPhys(VirtReg))) { + Loc.substPhysReg(VRM.getPhys(VirtReg), TRI); + } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT && + VRM.isSpillSlotUsed(VRM.getStackSlot(VirtReg))) { + // FIXME: Translate SubIdx to a stackslot offset. + Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg)); + } else { + Loc.setReg(0); + Loc.setSubReg(0); + } + coalesceLocation(LocNo); + } + DEBUG(print(dbgs(), &TRI)); +} + +/// findInsertLocation - Find an iterator for inserting a DBG_VALUE +/// instruction. +static MachineBasicBlock::iterator +findInsertLocation(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS) { + SlotIndex Start = LIS.getMBBStartIdx(MBB); + Idx = Idx.getBaseIndex(); + + // Try to find an insert location by going backwards from Idx. + MachineInstr *MI; + while (!(MI = LIS.getInstructionFromIndex(Idx))) { + // We've reached the beginning of MBB. + if (Idx == Start) { + MachineBasicBlock::iterator I = MBB->SkipPHIsAndLabels(MBB->begin()); + return I; + } + Idx = Idx.getPrevIndex(); + } + + // Don't insert anything after the first terminator, though. + return MI->getDesc().isTerminator() ? MBB->getFirstTerminator() : + llvm::next(MachineBasicBlock::iterator(MI)); +} + +DebugLoc UserValue::findDebugLoc() { + DebugLoc D = dl; + dl = DebugLoc(); + return D; +} +void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, + unsigned LocNo, + LiveIntervals &LIS, + const TargetInstrInfo &TII) { + MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); + MachineOperand &Loc = locations[LocNo]; + + // Frame index locations may require a target callback. + if (Loc.isFI()) { + MachineInstr *MI = TII.emitFrameIndexDebugValue(*MBB->getParent(), + Loc.getIndex(), offset, variable, + findDebugLoc()); + if (MI) { + MBB->insert(I, MI); + return; + } + } + // This is not a frame index, or the target is happy with a standard FI. + BuildMI(*MBB, I, findDebugLoc(), TII.get(TargetOpcode::DBG_VALUE)) + .addOperand(Loc).addImm(offset).addMetadata(variable); +} + +void UserValue::insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, + LiveIntervals &LIS, const TargetInstrInfo &TII) { + MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); + BuildMI(*MBB, I, findDebugLoc(), TII.get(TargetOpcode::DBG_VALUE)).addReg(0) + .addImm(offset).addMetadata(variable); +} + +void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, + const TargetInstrInfo &TII) { + MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(); + + for (LocMap::const_iterator I = locInts.begin(); I.valid();) { + SlotIndex Start = I.start(); + SlotIndex Stop = I.stop(); + unsigned LocNo = I.value(); + DEBUG(dbgs() << "\t[" << Start << ';' << Stop << "):" << LocNo); + MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start); + SlotIndex MBBEnd = LIS.getMBBEndIdx(MBB); + + DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd); + insertDebugValue(MBB, Start, LocNo, LIS, TII); + + // This interval may span multiple basic blocks. + // Insert a DBG_VALUE into each one. + while(Stop > MBBEnd) { + // Move to the next block. + Start = MBBEnd; + if (++MBB == MFEnd) + break; + MBBEnd = LIS.getMBBEndIdx(MBB); + DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd); + insertDebugValue(MBB, Start, LocNo, LIS, TII); + } + DEBUG(dbgs() << '\n'); + if (MBB == MFEnd) + break; + + ++I; + if (Stop == MBBEnd) + continue; + // The current interval ends before MBB. + // Insert a kill if there is a gap. + if (!I.valid() || I.start() > Stop) + insertDebugKill(MBB, Stop, LIS, TII); + } +} + +void LDVImpl::emitDebugValues(VirtRegMap *VRM) { + DEBUG(dbgs() << "********** EMITTING LIVE DEBUG VARIABLES **********\n"); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + for (unsigned i = 0, e = userValues.size(); i != e; ++i) { + userValues[i]->rewriteLocations(*VRM, *TRI); + userValues[i]->emitDebugValues(VRM, *LIS, *TII); + } +} + +void LiveDebugVariables::emitDebugValues(VirtRegMap *VRM) { + if (pImpl) + static_cast(pImpl)->emitDebugValues(VRM); +} + + +#ifndef NDEBUG +void LiveDebugVariables::dump() { + if (pImpl) + static_cast(pImpl)->print(dbgs()); +} +#endif + diff --git a/final/lib/CodeGen/LiveDebugVariables.h b/final/lib/CodeGen/LiveDebugVariables.h new file mode 100644 index 00000000000..a6e40a19845 --- /dev/null +++ b/final/lib/CodeGen/LiveDebugVariables.h @@ -0,0 +1,63 @@ +//===- LiveDebugVariables.h - Tracking debug info variables ----*- 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 the interface to the LiveDebugVariables analysis. +// +// The analysis removes DBG_VALUE instructions for virtual registers and tracks +// live user variables in a data structure that can be updated during register +// allocation. +// +// After register allocation new DBG_VALUE instructions are emitted to reflect +// the new locations of user variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEDEBUGVARIABLES_H +#define LLVM_CODEGEN_LIVEDEBUGVARIABLES_H + +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class VirtRegMap; + +class LiveDebugVariables : public MachineFunctionPass { + void *pImpl; +public: + static char ID; // Pass identification, replacement for typeid + + LiveDebugVariables(); + ~LiveDebugVariables(); + + /// renameRegister - Move any user variables in OldReg to NewReg:SubIdx. + /// @param OldReg Old virtual register that is going away. + /// @param NewReg New register holding the user variables. + /// @param SubIdx If NewReg is a virtual register, SubIdx may indicate a sub- + /// register. + void renameRegister(unsigned OldReg, unsigned NewReg, unsigned SubIdx); + + /// emitDebugValues - Emit new DBG_VALUE instructions reflecting the changes + /// that happened during register allocation. + /// @param VRM Rename virtual registers according to map. + void emitDebugValues(VirtRegMap *VRM); + + /// dump - Print data structures to dbgs(). + void dump(); + +private: + + virtual bool runOnMachineFunction(MachineFunction &); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &) const; + +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_LIVEDEBUGVARIABLES_H diff --git a/final/lib/CodeGen/LiveInterval.cpp b/final/lib/CodeGen/LiveInterval.cpp new file mode 100644 index 00000000000..585e3a2dc24 --- /dev/null +++ b/final/lib/CodeGen/LiveInterval.cpp @@ -0,0 +1,801 @@ +//===-- LiveInterval.cpp - Live Interval Representation -------------------===// +// +// 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 LiveRange and LiveInterval classes. Given some +// numbering of each the machine instructions an interval [i, j) is said to be a +// live interval for register v if there is no instruction with number j' > j +// such that v is live at j' and there is no instruction with number i' < i such +// that v is live at i'. In this implementation intervals can have holes, +// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each +// individual range is represented as an instance of LiveRange, and the whole +// interval is represented as an instance of LiveInterval. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include +using namespace llvm; + +// CompEnd - Compare LiveRange ends. +namespace { +struct CompEnd { + bool operator()(SlotIndex A, const LiveRange &B) const { + return A < B.end; + } + bool operator()(const LiveRange &A, SlotIndex B) const { + return A.end < B; + } + bool operator()(const LiveRange &A, const LiveRange &B) const { + return A.end < B.end; + } +}; +} + +LiveInterval::iterator LiveInterval::find(SlotIndex Pos) { + assert(Pos.isValid() && "Cannot search for an invalid index"); + return std::upper_bound(begin(), end(), Pos, CompEnd()); +} + +/// killedInRange - Return true if the interval has kills in [Start,End). +bool LiveInterval::killedInRange(SlotIndex Start, SlotIndex End) const { + Ranges::const_iterator r = + std::lower_bound(ranges.begin(), ranges.end(), End); + + // Now r points to the first interval with start >= End, or ranges.end(). + if (r == ranges.begin()) + return false; + + --r; + // Now r points to the last interval with end <= End. + // r->end is the kill point. + return r->end >= Start && r->end < End; +} + +// overlaps - Return true if the intersection of the two live intervals is +// not empty. +// +// An example for overlaps(): +// +// 0: A = ... +// 4: B = ... +// 8: C = A + B ;; last use of A +// +// The live intervals should look like: +// +// A = [3, 11) +// B = [7, x) +// C = [11, y) +// +// A->overlaps(C) should return false since we want to be able to join +// A and C. +// +bool LiveInterval::overlapsFrom(const LiveInterval& other, + const_iterator StartPos) const { + assert(!empty() && "empty interval"); + const_iterator i = begin(); + const_iterator ie = end(); + const_iterator j = StartPos; + const_iterator je = other.end(); + + assert((StartPos->start <= i->start || StartPos == other.begin()) && + StartPos != other.end() && "Bogus start position hint!"); + + if (i->start < j->start) { + i = std::upper_bound(i, ie, j->start); + if (i != ranges.begin()) --i; + } else if (j->start < i->start) { + ++StartPos; + if (StartPos != other.end() && StartPos->start <= i->start) { + assert(StartPos < other.end() && i < end()); + j = std::upper_bound(j, je, i->start); + if (j != other.ranges.begin()) --j; + } + } else { + return true; + } + + if (j == je) return false; + + while (i != ie) { + if (i->start > j->start) { + std::swap(i, j); + std::swap(ie, je); + } + + if (i->end > j->start) + return true; + ++i; + } + + return false; +} + +/// overlaps - Return true if the live interval overlaps a range specified +/// by [Start, End). +bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const { + assert(Start < End && "Invalid range"); + const_iterator I = std::lower_bound(begin(), end(), End); + return I != begin() && (--I)->end > Start; +} + + +/// ValNo is dead, remove it. If it is the largest value number, just nuke it +/// (and any other deleted values neighboring it), otherwise mark it as ~1U so +/// it can be nuked later. +void LiveInterval::markValNoForDeletion(VNInfo *ValNo) { + if (ValNo->id == getNumValNums()-1) { + do { + valnos.pop_back(); + } while (!valnos.empty() && valnos.back()->isUnused()); + } else { + ValNo->setIsUnused(true); + } +} + +/// RenumberValues - Renumber all values in order of appearance and delete the +/// remaining unused values. +void LiveInterval::RenumberValues(LiveIntervals &lis) { + SmallPtrSet Seen; + bool seenPHIDef = false; + valnos.clear(); + for (const_iterator I = begin(), E = end(); I != E; ++I) { + VNInfo *VNI = I->valno; + if (!Seen.insert(VNI)) + continue; + assert(!VNI->isUnused() && "Unused valno used by live range"); + VNI->id = (unsigned)valnos.size(); + valnos.push_back(VNI); + VNI->setHasPHIKill(false); + if (VNI->isPHIDef()) + seenPHIDef = true; + } + + // Recompute phi kill flags. + if (!seenPHIDef) + return; + for (const_vni_iterator I = vni_begin(), E = vni_end(); I != E; ++I) { + VNInfo *VNI = *I; + if (!VNI->isPHIDef()) + continue; + const MachineBasicBlock *PHIBB = lis.getMBBFromIndex(VNI->def); + assert(PHIBB && "No basic block for phi-def"); + for (MachineBasicBlock::const_pred_iterator PI = PHIBB->pred_begin(), + PE = PHIBB->pred_end(); PI != PE; ++PI) { + VNInfo *KVNI = getVNInfoAt(lis.getMBBEndIdx(*PI).getPrevSlot()); + if (KVNI) + KVNI->setHasPHIKill(true); + } + } +} + +/// extendIntervalEndTo - This method is used when we want to extend the range +/// specified by I to end at the specified endpoint. To do this, we should +/// merge and eliminate all ranges that this will overlap with. The iterator is +/// not invalidated. +void LiveInterval::extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd) { + assert(I != ranges.end() && "Not a valid interval!"); + VNInfo *ValNo = I->valno; + + // Search for the first interval that we can't merge with. + Ranges::iterator MergeTo = llvm::next(I); + for (; MergeTo != ranges.end() && NewEnd >= MergeTo->end; ++MergeTo) { + assert(MergeTo->valno == ValNo && "Cannot merge with differing values!"); + } + + // If NewEnd was in the middle of an interval, make sure to get its endpoint. + I->end = std::max(NewEnd, prior(MergeTo)->end); + + // Erase any dead ranges. + ranges.erase(llvm::next(I), MergeTo); + + // If the newly formed range now touches the range after it and if they have + // the same value number, merge the two ranges into one range. + Ranges::iterator Next = llvm::next(I); + if (Next != ranges.end() && Next->start <= I->end && Next->valno == ValNo) { + I->end = Next->end; + ranges.erase(Next); + } +} + + +/// extendIntervalStartTo - This method is used when we want to extend the range +/// specified by I to start at the specified endpoint. To do this, we should +/// merge and eliminate all ranges that this will overlap with. +LiveInterval::Ranges::iterator +LiveInterval::extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStart) { + assert(I != ranges.end() && "Not a valid interval!"); + VNInfo *ValNo = I->valno; + + // Search for the first interval that we can't merge with. + Ranges::iterator MergeTo = I; + do { + if (MergeTo == ranges.begin()) { + I->start = NewStart; + ranges.erase(MergeTo, I); + return I; + } + assert(MergeTo->valno == ValNo && "Cannot merge with differing values!"); + --MergeTo; + } while (NewStart <= MergeTo->start); + + // If we start in the middle of another interval, just delete a range and + // extend that interval. + if (MergeTo->end >= NewStart && MergeTo->valno == ValNo) { + MergeTo->end = I->end; + } else { + // Otherwise, extend the interval right after. + ++MergeTo; + MergeTo->start = NewStart; + MergeTo->end = I->end; + } + + ranges.erase(llvm::next(MergeTo), llvm::next(I)); + return MergeTo; +} + +LiveInterval::iterator +LiveInterval::addRangeFrom(LiveRange LR, iterator From) { + SlotIndex Start = LR.start, End = LR.end; + iterator it = std::upper_bound(From, ranges.end(), Start); + + // If the inserted interval starts in the middle or right at the end of + // another interval, just extend that interval to contain the range of LR. + if (it != ranges.begin()) { + iterator B = prior(it); + if (LR.valno == B->valno) { + if (B->start <= Start && B->end >= Start) { + extendIntervalEndTo(B, End); + return B; + } + } else { + // Check to make sure that we are not overlapping two live ranges with + // different valno's. + assert(B->end <= Start && + "Cannot overlap two LiveRanges with differing ValID's" + " (did you def the same reg twice in a MachineInstr?)"); + } + } + + // Otherwise, if this range ends in the middle of, or right next to, another + // interval, merge it into that interval. + if (it != ranges.end()) { + if (LR.valno == it->valno) { + if (it->start <= End) { + it = extendIntervalStartTo(it, Start); + + // If LR is a complete superset of an interval, we may need to grow its + // endpoint as well. + if (End > it->end) + extendIntervalEndTo(it, End); + return it; + } + } else { + // Check to make sure that we are not overlapping two live ranges with + // different valno's. + assert(it->start >= End && + "Cannot overlap two LiveRanges with differing ValID's"); + } + } + + // Otherwise, this is just a new range that doesn't interact with anything. + // Insert it. + return ranges.insert(it, LR); +} + +/// extendInBlock - If this interval is live before UseIdx in the basic +/// block that starts at StartIdx, extend it to be live at UseIdx and return +/// the value. If there is no live range before UseIdx, return NULL. +VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx) { + if (empty()) + return 0; + iterator I = std::upper_bound(begin(), end(), UseIdx); + if (I == begin()) + return 0; + --I; + if (I->end <= StartIdx) + return 0; + if (I->end <= UseIdx) + extendIntervalEndTo(I, UseIdx.getNextSlot()); + return I->valno; +} + +/// removeRange - Remove the specified range from this interval. Note that +/// the range must be in a single LiveRange in its entirety. +void LiveInterval::removeRange(SlotIndex Start, SlotIndex End, + bool RemoveDeadValNo) { + // Find the LiveRange containing this span. + Ranges::iterator I = find(Start); + assert(I != ranges.end() && "Range is not in interval!"); + assert(I->containsRange(Start, End) && "Range is not entirely in interval!"); + + // If the span we are removing is at the start of the LiveRange, adjust it. + VNInfo *ValNo = I->valno; + if (I->start == Start) { + if (I->end == End) { + if (RemoveDeadValNo) { + // Check if val# is dead. + bool isDead = true; + for (const_iterator II = begin(), EE = end(); II != EE; ++II) + if (II != I && II->valno == ValNo) { + isDead = false; + break; + } + if (isDead) { + // Now that ValNo is dead, remove it. + markValNoForDeletion(ValNo); + } + } + + ranges.erase(I); // Removed the whole LiveRange. + } else + I->start = End; + return; + } + + // Otherwise if the span we are removing is at the end of the LiveRange, + // adjust the other way. + if (I->end == End) { + I->end = Start; + return; + } + + // Otherwise, we are splitting the LiveRange into two pieces. + SlotIndex OldEnd = I->end; + I->end = Start; // Trim the old interval. + + // Insert the new one. + ranges.insert(llvm::next(I), LiveRange(End, OldEnd, ValNo)); +} + +/// removeValNo - Remove all the ranges defined by the specified value#. +/// Also remove the value# from value# list. +void LiveInterval::removeValNo(VNInfo *ValNo) { + if (empty()) return; + Ranges::iterator I = ranges.end(); + Ranges::iterator E = ranges.begin(); + do { + --I; + if (I->valno == ValNo) + ranges.erase(I); + } while (I != E); + // Now that ValNo is dead, remove it. + markValNoForDeletion(ValNo); +} + +/// findDefinedVNInfo - Find the VNInfo defined by the specified +/// index (register interval). +VNInfo *LiveInterval::findDefinedVNInfoForRegInt(SlotIndex Idx) const { + for (LiveInterval::const_vni_iterator i = vni_begin(), e = vni_end(); + i != e; ++i) { + if ((*i)->def == Idx) + return *i; + } + + return 0; +} + +/// join - Join two live intervals (this, and other) together. This applies +/// mappings to the value numbers in the LHS/RHS intervals as specified. If +/// the intervals are not joinable, this aborts. +void LiveInterval::join(LiveInterval &Other, + const int *LHSValNoAssignments, + const int *RHSValNoAssignments, + SmallVector &NewVNInfo, + MachineRegisterInfo *MRI) { + // Determine if any of our live range values are mapped. This is uncommon, so + // we want to avoid the interval scan if not. + bool MustMapCurValNos = false; + unsigned NumVals = getNumValNums(); + unsigned NumNewVals = NewVNInfo.size(); + for (unsigned i = 0; i != NumVals; ++i) { + unsigned LHSValID = LHSValNoAssignments[i]; + if (i != LHSValID || + (NewVNInfo[LHSValID] && NewVNInfo[LHSValID] != getValNumInfo(i))) + MustMapCurValNos = true; + } + + // If we have to apply a mapping to our base interval assignment, rewrite it + // now. + if (MustMapCurValNos) { + // Map the first live range. + iterator OutIt = begin(); + OutIt->valno = NewVNInfo[LHSValNoAssignments[OutIt->valno->id]]; + ++OutIt; + for (iterator I = OutIt, E = end(); I != E; ++I) { + OutIt->valno = NewVNInfo[LHSValNoAssignments[I->valno->id]]; + + // If this live range has the same value # as its immediate predecessor, + // and if they are neighbors, remove one LiveRange. This happens when we + // have [0,3:0)[4,7:1) and map 0/1 onto the same value #. + if (OutIt->valno == (OutIt-1)->valno && (OutIt-1)->end == OutIt->start) { + (OutIt-1)->end = OutIt->end; + } else { + if (I != OutIt) { + OutIt->start = I->start; + OutIt->end = I->end; + } + + // Didn't merge, on to the next one. + ++OutIt; + } + } + + // If we merge some live ranges, chop off the end. + ranges.erase(OutIt, end()); + } + + // Remember assignements because val# ids are changing. + SmallVector OtherAssignments; + for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) + OtherAssignments.push_back(RHSValNoAssignments[I->valno->id]); + + // Update val# info. Renumber them and make sure they all belong to this + // LiveInterval now. Also remove dead val#'s. + unsigned NumValNos = 0; + for (unsigned i = 0; i < NumNewVals; ++i) { + VNInfo *VNI = NewVNInfo[i]; + if (VNI) { + if (NumValNos >= NumVals) + valnos.push_back(VNI); + else + valnos[NumValNos] = VNI; + VNI->id = NumValNos++; // Renumber val#. + } + } + if (NumNewVals < NumVals) + valnos.resize(NumNewVals); // shrinkify + + // Okay, now insert the RHS live ranges into the LHS. + iterator InsertPos = begin(); + unsigned RangeNo = 0; + for (iterator I = Other.begin(), E = Other.end(); I != E; ++I, ++RangeNo) { + // Map the valno in the other live range to the current live range. + I->valno = NewVNInfo[OtherAssignments[RangeNo]]; + assert(I->valno && "Adding a dead range?"); + InsertPos = addRangeFrom(*I, InsertPos); + } + + ComputeJoinedWeight(Other); +} + +/// MergeRangesInAsValue - Merge all of the intervals in RHS into this live +/// interval as the specified value number. The LiveRanges in RHS are +/// allowed to overlap with LiveRanges in the current interval, but only if +/// the overlapping LiveRanges have the specified value number. +void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, + VNInfo *LHSValNo) { + // TODO: Make this more efficient. + iterator InsertPos = begin(); + for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + // Map the valno in the other live range to the current live range. + LiveRange Tmp = *I; + Tmp.valno = LHSValNo; + InsertPos = addRangeFrom(Tmp, InsertPos); + } +} + + +/// MergeValueInAsValue - Merge all of the live ranges of a specific val# +/// in RHS into this live interval as the specified value number. +/// The LiveRanges in RHS are allowed to overlap with LiveRanges in the +/// current interval, it will replace the value numbers of the overlaped +/// live ranges with the specified value number. +void LiveInterval::MergeValueInAsValue( + const LiveInterval &RHS, + const VNInfo *RHSValNo, VNInfo *LHSValNo) { + SmallVector ReplacedValNos; + iterator IP = begin(); + for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + assert(I->valno == RHS.getValNumInfo(I->valno->id) && "Bad VNInfo"); + if (I->valno != RHSValNo) + continue; + SlotIndex Start = I->start, End = I->end; + IP = std::upper_bound(IP, end(), Start); + // If the start of this range overlaps with an existing liverange, trim it. + if (IP != begin() && IP[-1].end > Start) { + if (IP[-1].valno != LHSValNo) { + ReplacedValNos.push_back(IP[-1].valno); + IP[-1].valno = LHSValNo; // Update val#. + } + Start = IP[-1].end; + // Trimmed away the whole range? + if (Start >= End) continue; + } + // If the end of this range overlaps with an existing liverange, trim it. + if (IP != end() && End > IP->start) { + if (IP->valno != LHSValNo) { + ReplacedValNos.push_back(IP->valno); + IP->valno = LHSValNo; // Update val#. + } + End = IP->start; + // If this trimmed away the whole range, ignore it. + if (Start == End) continue; + } + + // Map the valno in the other live range to the current live range. + IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP); + } + + + SmallSet Seen; + for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) { + VNInfo *V1 = ReplacedValNos[i]; + if (Seen.insert(V1)) { + bool isDead = true; + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (I->valno == V1) { + isDead = false; + break; + } + if (isDead) { + // Now that V1 is dead, remove it. + markValNoForDeletion(V1); + } + } + } +} + + + +/// MergeValueNumberInto - This method is called when two value nubmers +/// are found to be equivalent. This eliminates V1, replacing all +/// LiveRanges with the V1 value number with the V2 value number. This can +/// cause merging of V1/V2 values numbers and compaction of the value space. +VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) { + assert(V1 != V2 && "Identical value#'s are always equivalent!"); + + // This code actually merges the (numerically) larger value number into the + // smaller value number, which is likely to allow us to compactify the value + // space. The only thing we have to be careful of is to preserve the + // instruction that defines the result value. + + // Make sure V2 is smaller than V1. + if (V1->id < V2->id) { + V1->copyFrom(*V2); + std::swap(V1, V2); + } + + // Merge V1 live ranges into V2. + for (iterator I = begin(); I != end(); ) { + iterator LR = I++; + if (LR->valno != V1) continue; // Not a V1 LiveRange. + + // Okay, we found a V1 live range. If it had a previous, touching, V2 live + // range, extend it. + if (LR != begin()) { + iterator Prev = LR-1; + if (Prev->valno == V2 && Prev->end == LR->start) { + Prev->end = LR->end; + + // Erase this live-range. + ranges.erase(LR); + I = Prev+1; + LR = Prev; + } + } + + // Okay, now we have a V1 or V2 live range that is maximally merged forward. + // Ensure that it is a V2 live-range. + LR->valno = V2; + + // If we can merge it into later V2 live ranges, do so now. We ignore any + // following V1 live ranges, as they will be merged in subsequent iterations + // of the loop. + if (I != end()) { + if (I->start == LR->end && I->valno == V2) { + LR->end = I->end; + ranges.erase(I); + I = LR+1; + } + } + } + + // Merge the relevant flags. + V2->mergeFlags(V1); + + // Now that V1 is dead, remove it. + markValNoForDeletion(V1); + + return V2; +} + +void LiveInterval::Copy(const LiveInterval &RHS, + MachineRegisterInfo *MRI, + VNInfo::Allocator &VNInfoAllocator) { + ranges.clear(); + valnos.clear(); + std::pair Hint = MRI->getRegAllocationHint(RHS.reg); + MRI->setRegAllocationHint(reg, Hint.first, Hint.second); + + weight = RHS.weight; + for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { + const VNInfo *VNI = RHS.getValNumInfo(i); + createValueCopy(VNI, VNInfoAllocator); + } + for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) { + const LiveRange &LR = RHS.ranges[i]; + addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id))); + } +} + +unsigned LiveInterval::getSize() const { + unsigned Sum = 0; + for (const_iterator I = begin(), E = end(); I != E; ++I) + Sum += I->start.distance(I->end); + return Sum; +} + +/// ComputeJoinedWeight - Set the weight of a live interval Joined +/// after Other has been merged into it. +void LiveInterval::ComputeJoinedWeight(const LiveInterval &Other) { + // If either of these intervals was spilled, the weight is the + // weight of the non-spilled interval. This can only happen with + // iterative coalescers. + + if (Other.weight != HUGE_VALF) { + weight += Other.weight; + } + else if (weight == HUGE_VALF && + !TargetRegisterInfo::isPhysicalRegister(reg)) { + // Remove this assert if you have an iterative coalescer + assert(0 && "Joining to spilled interval"); + weight = Other.weight; + } + else { + // Otherwise the weight stays the same + // Remove this assert if you have an iterative coalescer + assert(0 && "Joining from spilled interval"); + } +} + +raw_ostream& llvm::operator<<(raw_ostream& os, const LiveRange &LR) { + return os << '[' << LR.start << ',' << LR.end << ':' << LR.valno->id << ")"; +} + +void LiveRange::dump() const { + dbgs() << *this << "\n"; +} + +void LiveInterval::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { + OS << PrintReg(reg, TRI); + if (weight != 0) + OS << ',' << weight; + + if (empty()) + OS << " EMPTY"; + else { + OS << " = "; + for (LiveInterval::Ranges::const_iterator I = ranges.begin(), + E = ranges.end(); I != E; ++I) { + OS << *I; + assert(I->valno == getValNumInfo(I->valno->id) && "Bad VNInfo"); + } + } + + // Print value number info. + if (getNumValNums()) { + OS << " "; + unsigned vnum = 0; + for (const_vni_iterator i = vni_begin(), e = vni_end(); i != e; + ++i, ++vnum) { + const VNInfo *vni = *i; + if (vnum) OS << " "; + OS << vnum << "@"; + if (vni->isUnused()) { + OS << "x"; + } else { + OS << vni->def; + if (vni->isPHIDef()) + OS << "-phidef"; + if (vni->hasPHIKill()) + OS << "-phikill"; + if (vni->hasRedefByEC()) + OS << "-ec"; + } + } + } +} + +void LiveInterval::dump() const { + dbgs() << *this << "\n"; +} + + +void LiveRange::print(raw_ostream &os) const { + os << *this; +} + +unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) { + // Create initial equivalence classes. + eqClass_.clear(); + eqClass_.grow(LI->getNumValNums()); + + const VNInfo *used = 0, *unused = 0; + + // Determine connections. + for (LiveInterval::const_vni_iterator I = LI->vni_begin(), E = LI->vni_end(); + I != E; ++I) { + const VNInfo *VNI = *I; + // Group all unused values into one class. + if (VNI->isUnused()) { + if (unused) + eqClass_.join(unused->id, VNI->id); + unused = VNI; + continue; + } + used = VNI; + if (VNI->isPHIDef()) { + const MachineBasicBlock *MBB = lis_.getMBBFromIndex(VNI->def); + assert(MBB && "Phi-def has no defining MBB"); + // Connect to values live out of predecessors. + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) + if (const VNInfo *PVNI = + LI->getVNInfoAt(lis_.getMBBEndIdx(*PI).getPrevSlot())) + eqClass_.join(VNI->id, PVNI->id); + } else { + // Normal value defined by an instruction. Check for two-addr redef. + // FIXME: This could be coincidental. Should we really check for a tied + // operand constraint? + // Note that VNI->def may be a use slot for an early clobber def. + if (const VNInfo *UVNI = LI->getVNInfoAt(VNI->def.getPrevSlot())) + eqClass_.join(VNI->id, UVNI->id); + } + } + + // Lump all the unused values in with the last used value. + if (used && unused) + eqClass_.join(used->id, unused->id); + + eqClass_.compress(); + return eqClass_.getNumClasses(); +} + +void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[]) { + assert(LIV[0] && "LIV[0] must be set"); + LiveInterval &LI = *LIV[0]; + + // First move runs to new intervals. + LiveInterval::iterator J = LI.begin(), E = LI.end(); + while (J != E && eqClass_[J->valno->id] == 0) + ++J; + for (LiveInterval::iterator I = J; I != E; ++I) { + if (unsigned eq = eqClass_[I->valno->id]) { + assert((LIV[eq]->empty() || LIV[eq]->expiredAt(I->start)) && + "New intervals should be empty"); + LIV[eq]->ranges.push_back(*I); + } else + *J++ = *I; + } + LI.ranges.erase(J, E); + + // Transfer VNInfos to their new owners and renumber them. + unsigned j = 0, e = LI.getNumValNums(); + while (j != e && eqClass_[j] == 0) + ++j; + for (unsigned i = j; i != e; ++i) { + VNInfo *VNI = LI.getValNumInfo(i); + if (unsigned eq = eqClass_[i]) { + VNI->id = LIV[eq]->getNumValNums(); + LIV[eq]->valnos.push_back(VNI); + } else { + VNI->id = j; + LI.valnos[j++] = VNI; + } + } + LI.valnos.resize(j); +} diff --git a/final/lib/CodeGen/LiveIntervalAnalysis.cpp b/final/lib/CodeGen/LiveIntervalAnalysis.cpp new file mode 100644 index 00000000000..8a2db3e1a38 --- /dev/null +++ b/final/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -0,0 +1,2162 @@ +//===-- LiveIntervalAnalysis.cpp - Live Interval Analysis -----------------===// +// +// 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 LiveInterval analysis pass which is used +// by the Linear Scan Register allocator. This pass linearizes the +// basic blocks of the function in DFS order and uses the +// LiveVariables pass to conservatively compute live intervals for +// each virtual and physical register. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "liveintervals" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "VirtRegMap.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/ProcessImplicitDefs.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +#include +using namespace llvm; + +// Hidden options for help debugging. +static cl::opt DisableReMat("disable-rematerialization", + cl::init(false), cl::Hidden); + +STATISTIC(numIntervals , "Number of original intervals"); +STATISTIC(numFolds , "Number of loads/stores folded into instructions"); +STATISTIC(numSplits , "Number of intervals split"); + +char LiveIntervals::ID = 0; +INITIALIZE_PASS_BEGIN(LiveIntervals, "liveintervals", + "Live Interval Analysis", false, false) +INITIALIZE_PASS_DEPENDENCY(LiveVariables) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(PHIElimination) +INITIALIZE_PASS_DEPENDENCY(TwoAddressInstructionPass) +INITIALIZE_PASS_DEPENDENCY(ProcessImplicitDefs) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(LiveIntervals, "liveintervals", + "Live Interval Analysis", false, false) + +void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + + if (!StrongPHIElim) { + AU.addPreservedID(PHIEliminationID); + AU.addRequiredID(PHIEliminationID); + } + + AU.addRequiredID(TwoAddressInstructionPassID); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void LiveIntervals::releaseMemory() { + // Free the live intervals themselves. + for (DenseMap::iterator I = r2iMap_.begin(), + E = r2iMap_.end(); I != E; ++I) + delete I->second; + + r2iMap_.clear(); + + // Release VNInfo memory regions, VNInfo objects don't need to be dtor'd. + VNInfoAllocator.Reset(); + while (!CloneMIs.empty()) { + MachineInstr *MI = CloneMIs.back(); + CloneMIs.pop_back(); + mf_->DeleteMachineInstr(MI); + } +} + +/// runOnMachineFunction - Register allocate the whole function +/// +bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &mf_->getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + aa_ = &getAnalysis(); + lv_ = &getAnalysis(); + indexes_ = &getAnalysis(); + allocatableRegs_ = tri_->getAllocatableSet(fn); + + computeIntervals(); + + numIntervals += getNumIntervals(); + + DEBUG(dump()); + return true; +} + +/// print - Implement the dump method. +void LiveIntervals::print(raw_ostream &OS, const Module* ) const { + OS << "********** INTERVALS **********\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) { + I->second->print(OS, tri_); + OS << "\n"; + } + + printInstrs(OS); +} + +void LiveIntervals::printInstrs(raw_ostream &OS) const { + OS << "********** MACHINEINSTRS **********\n"; + mf_->print(OS, indexes_); +} + +void LiveIntervals::dumpInstrs() const { + printInstrs(dbgs()); +} + +bool LiveIntervals::conflictsWithPhysReg(const LiveInterval &li, + VirtRegMap &vrm, unsigned reg) { + // We don't handle fancy stuff crossing basic block boundaries + if (li.ranges.size() != 1) + return true; + const LiveRange &range = li.ranges.front(); + SlotIndex idx = range.start.getBaseIndex(); + SlotIndex end = range.end.getPrevSlot().getBaseIndex().getNextIndex(); + + // Skip deleted instructions + MachineInstr *firstMI = getInstructionFromIndex(idx); + while (!firstMI && idx != end) { + idx = idx.getNextIndex(); + firstMI = getInstructionFromIndex(idx); + } + if (!firstMI) + return false; + + // Find last instruction in range + SlotIndex lastIdx = end.getPrevIndex(); + MachineInstr *lastMI = getInstructionFromIndex(lastIdx); + while (!lastMI && lastIdx != idx) { + lastIdx = lastIdx.getPrevIndex(); + lastMI = getInstructionFromIndex(lastIdx); + } + if (!lastMI) + return false; + + // Range cannot cross basic block boundaries or terminators + MachineBasicBlock *MBB = firstMI->getParent(); + if (MBB != lastMI->getParent() || lastMI->getDesc().isTerminator()) + return true; + + MachineBasicBlock::const_iterator E = lastMI; + ++E; + for (MachineBasicBlock::const_iterator I = firstMI; I != E; ++I) { + const MachineInstr &MI = *I; + + // Allow copies to and from li.reg + if (MI.isCopy()) + if (MI.getOperand(0).getReg() == li.reg || + MI.getOperand(1).getReg() == li.reg) + continue; + + // Check for operands using reg + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand& mop = MI.getOperand(i); + if (!mop.isReg()) + continue; + unsigned PhysReg = mop.getReg(); + if (PhysReg == 0 || PhysReg == li.reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(PhysReg)) { + if (!vrm.hasPhys(PhysReg)) + continue; + PhysReg = vrm.getPhys(PhysReg); + } + if (PhysReg && tri_->regsOverlap(PhysReg, reg)) + return true; + } + } + + // No conflicts found. + return false; +} + +bool LiveIntervals::conflictsWithAliasRef(LiveInterval &li, unsigned Reg, + SmallPtrSet &JoinedCopies) { + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + for (SlotIndex index = I->start.getBaseIndex(), + end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); + index != end; + index = index.getNextIndex()) { + MachineInstr *MI = getInstructionFromIndex(index); + if (!MI) + continue; // skip deleted instructions + + if (JoinedCopies.count(MI)) + continue; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned PhysReg = MO.getReg(); + if (PhysReg == 0 || PhysReg == Reg || + TargetRegisterInfo::isVirtualRegister(PhysReg)) + continue; + if (tri_->regsOverlap(Reg, PhysReg)) + return true; + } + } + } + + return false; +} + +static +bool MultipleDefsBySameMI(const MachineInstr &MI, unsigned MOIdx) { + unsigned Reg = MI.getOperand(MOIdx).getReg(); + for (unsigned i = MOIdx+1, e = MI.getNumOperands(); i < e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg()) + continue; + if (MO.getReg() == Reg && MO.isDef()) { + assert(MI.getOperand(MOIdx).getSubReg() != MO.getSubReg() && + MI.getOperand(MOIdx).getSubReg() && + (MO.getSubReg() || MO.isImplicit())); + return true; + } + } + return false; +} + +/// isPartialRedef - Return true if the specified def at the specific index is +/// partially re-defining the specified live interval. A common case of this is +/// a definition of the sub-register. +bool LiveIntervals::isPartialRedef(SlotIndex MIIdx, MachineOperand &MO, + LiveInterval &interval) { + if (!MO.getSubReg() || MO.isEarlyClobber()) + return false; + + SlotIndex RedefIndex = MIIdx.getDefIndex(); + const LiveRange *OldLR = + interval.getLiveRangeContaining(RedefIndex.getUseIndex()); + MachineInstr *DefMI = getInstructionFromIndex(OldLR->valno->def); + if (DefMI != 0) { + return DefMI->findRegisterDefOperandIdx(interval.reg) != -1; + } + return false; +} + +void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, + MachineOperand& MO, + unsigned MOIdx, + LiveInterval &interval) { + DEBUG(dbgs() << "\t\tregister: " << PrintReg(interval.reg, tri_)); + + // Virtual registers may be defined multiple times (due to phi + // elimination and 2-addr elimination). Much of what we do only has to be + // done once for the vreg. We use an empty interval to detect the first + // time we see a vreg. + LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg); + if (interval.empty()) { + // Get the Idx of the defining instructions. + SlotIndex defIndex = MIIdx.getDefIndex(); + // Earlyclobbers move back one, so that they overlap the live range + // of inputs. + if (MO.isEarlyClobber()) + defIndex = MIIdx.getUseIndex(); + + // Make sure the first definition is not a partial redefinition. Add an + // of the full register. + if (MO.getSubReg()) + mi->addRegisterDefined(interval.reg); + + MachineInstr *CopyMI = NULL; + if (mi->isCopyLike()) { + CopyMI = mi; + } + + VNInfo *ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator); + assert(ValNo->id == 0 && "First value in interval is not 0?"); + + // Loop over all of the blocks that the vreg is defined in. There are + // two cases we have to handle here. The most common case is a vreg + // whose lifetime is contained within a basic block. In this case there + // will be a single kill, in MBB, which comes after the definition. + if (vi.Kills.size() == 1 && vi.Kills[0]->getParent() == mbb) { + // FIXME: what about dead vars? + SlotIndex killIdx; + if (vi.Kills[0] != mi) + killIdx = getInstructionIndex(vi.Kills[0]).getDefIndex(); + else + killIdx = defIndex.getStoreIndex(); + + // If the kill happens after the definition, we have an intra-block + // live range. + if (killIdx > defIndex) { + assert(vi.AliveBlocks.empty() && + "Shouldn't be alive across any blocks!"); + LiveRange LR(defIndex, killIdx, ValNo); + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR << "\n"); + return; + } + } + + // The other case we handle is when a virtual register lives to the end + // of the defining block, potentially live across some blocks, then is + // live into some number of blocks, but gets killed. Start by adding a + // range that goes from this definition to the end of the defining block. + LiveRange NewLR(defIndex, getMBBEndIdx(mbb), ValNo); + DEBUG(dbgs() << " +" << NewLR); + interval.addRange(NewLR); + + bool PHIJoin = lv_->isPHIJoin(interval.reg); + + if (PHIJoin) { + // A phi join register is killed at the end of the MBB and revived as a new + // valno in the killing blocks. + assert(vi.AliveBlocks.empty() && "Phi join can't pass through blocks"); + DEBUG(dbgs() << " phi-join"); + ValNo->setHasPHIKill(true); + } else { + // Iterate over all of the blocks that the variable is completely + // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the + // live interval. + for (SparseBitVector<>::iterator I = vi.AliveBlocks.begin(), + E = vi.AliveBlocks.end(); I != E; ++I) { + MachineBasicBlock *aliveBlock = mf_->getBlockNumbered(*I); + LiveRange LR(getMBBStartIdx(aliveBlock), getMBBEndIdx(aliveBlock), ValNo); + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR); + } + } + + // Finally, this virtual register is live from the start of any killing + // block to the 'use' slot of the killing instruction. + for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { + MachineInstr *Kill = vi.Kills[i]; + SlotIndex Start = getMBBStartIdx(Kill->getParent()); + SlotIndex killIdx = getInstructionIndex(Kill).getDefIndex(); + + // Create interval with one of a NEW value number. Note that this value + // number isn't actually defined by an instruction, weird huh? :) + if (PHIJoin) { + assert(getInstructionFromIndex(Start) == 0 && + "PHI def index points at actual instruction."); + ValNo = interval.getNextValue(Start, 0, VNInfoAllocator); + ValNo->setIsPHIDef(true); + } + LiveRange LR(Start, killIdx, ValNo); + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR); + } + + } else { + if (MultipleDefsBySameMI(*mi, MOIdx)) + // Multiple defs of the same virtual register by the same instruction. + // e.g. %reg1031:5, %reg1031:6 = VLD1q16 %reg1024, ... + // This is likely due to elimination of REG_SEQUENCE instructions. Return + // here since there is nothing to do. + return; + + // If this is the second time we see a virtual register definition, it + // must be due to phi elimination or two addr elimination. If this is + // the result of two address elimination, then the vreg is one of the + // def-and-use register operand. + + // It may also be partial redef like this: + // 80 %reg1041:6 = VSHRNv4i16 %reg1034, 12, pred:14, pred:%reg0 + // 120 %reg1041:5 = VSHRNv4i16 %reg1039, 12, pred:14, pred:%reg0 + bool PartReDef = isPartialRedef(MIIdx, MO, interval); + if (PartReDef || mi->isRegTiedToUseOperand(MOIdx)) { + // If this is a two-address definition, then we have already processed + // the live range. The only problem is that we didn't realize there + // are actually two values in the live interval. Because of this we + // need to take the LiveRegion that defines this register and split it + // into two values. + SlotIndex RedefIndex = MIIdx.getDefIndex(); + if (MO.isEarlyClobber()) + RedefIndex = MIIdx.getUseIndex(); + + const LiveRange *OldLR = + interval.getLiveRangeContaining(RedefIndex.getUseIndex()); + VNInfo *OldValNo = OldLR->valno; + SlotIndex DefIndex = OldValNo->def.getDefIndex(); + + // Delete the previous value, which should be short and continuous, + // because the 2-addr copy must be in the same MBB as the redef. + interval.removeRange(DefIndex, RedefIndex); + + // The new value number (#1) is defined by the instruction we claimed + // defined value #0. + VNInfo *ValNo = interval.createValueCopy(OldValNo, VNInfoAllocator); + + // Value#0 is now defined by the 2-addr instruction. + OldValNo->def = RedefIndex; + OldValNo->setCopy(0); + + // A re-def may be a copy. e.g. %reg1030:6 = VMOVD %reg1026, ... + if (PartReDef && mi->isCopyLike()) + OldValNo->setCopy(&*mi); + + // Add the new live interval which replaces the range for the input copy. + LiveRange LR(DefIndex, RedefIndex, ValNo); + DEBUG(dbgs() << " replace range with " << LR); + interval.addRange(LR); + + // If this redefinition is dead, we need to add a dummy unit live + // range covering the def slot. + if (MO.isDead()) + interval.addRange(LiveRange(RedefIndex, RedefIndex.getStoreIndex(), + OldValNo)); + + DEBUG({ + dbgs() << " RESULT: "; + interval.print(dbgs(), tri_); + }); + } else if (lv_->isPHIJoin(interval.reg)) { + // In the case of PHI elimination, each variable definition is only + // live until the end of the block. We've already taken care of the + // rest of the live range. + + SlotIndex defIndex = MIIdx.getDefIndex(); + if (MO.isEarlyClobber()) + defIndex = MIIdx.getUseIndex(); + + VNInfo *ValNo; + MachineInstr *CopyMI = NULL; + if (mi->isCopyLike()) + CopyMI = mi; + ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator); + + SlotIndex killIndex = getMBBEndIdx(mbb); + LiveRange LR(defIndex, killIndex, ValNo); + interval.addRange(LR); + ValNo->setHasPHIKill(true); + DEBUG(dbgs() << " phi-join +" << LR); + } else { + llvm_unreachable("Multiply defined register"); + } + } + + DEBUG(dbgs() << '\n'); +} + +void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator mi, + SlotIndex MIIdx, + MachineOperand& MO, + LiveInterval &interval, + MachineInstr *CopyMI) { + // A physical register cannot be live across basic block, so its + // lifetime must end somewhere in its defining basic block. + DEBUG(dbgs() << "\t\tregister: " << PrintReg(interval.reg, tri_)); + + SlotIndex baseIndex = MIIdx; + SlotIndex start = baseIndex.getDefIndex(); + // Earlyclobbers move back one. + if (MO.isEarlyClobber()) + start = MIIdx.getUseIndex(); + SlotIndex end = start; + + // If it is not used after definition, it is considered dead at + // the instruction defining it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + // For earlyclobbers, the defSlot was pushed back one; the extra + // advance below compensates. + if (MO.isDead()) { + DEBUG(dbgs() << " dead"); + end = start.getStoreIndex(); + goto exit; + } + + // If it is not dead on definition, it must be killed by a + // subsequent instruction. Hence its interval is: + // [defSlot(def), useSlot(kill)+1) + baseIndex = baseIndex.getNextIndex(); + while (++mi != MBB->end()) { + + if (mi->isDebugValue()) + continue; + if (getInstructionFromIndex(baseIndex) == 0) + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + + if (mi->killsRegister(interval.reg, tri_)) { + DEBUG(dbgs() << " killed"); + end = baseIndex.getDefIndex(); + goto exit; + } else { + int DefIdx = mi->findRegisterDefOperandIdx(interval.reg,false,false,tri_); + if (DefIdx != -1) { + if (mi->isRegTiedToUseOperand(DefIdx)) { + // Two-address instruction. + end = baseIndex.getDefIndex(); + } else { + // Another instruction redefines the register before it is ever read. + // Then the register is essentially dead at the instruction that + // defines it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + DEBUG(dbgs() << " dead"); + end = start.getStoreIndex(); + } + goto exit; + } + } + + baseIndex = baseIndex.getNextIndex(); + } + + // The only case we should have a dead physreg here without a killing or + // instruction where we know it's dead is if it is live-in to the function + // and never used. Another possible case is the implicit use of the + // physical register has been deleted by two-address pass. + end = start.getStoreIndex(); + +exit: + assert(start < end && "did not find end of interval?"); + + // Already exists? Extend old live interval. + VNInfo *ValNo = interval.getVNInfoAt(start); + bool Extend = ValNo != 0; + if (!Extend) + ValNo = interval.getNextValue(start, CopyMI, VNInfoAllocator); + if (Extend && MO.isEarlyClobber()) + ValNo->setHasRedefByEC(true); + LiveRange LR(start, end, ValNo); + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR << '\n'); +} + +void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + SlotIndex MIIdx, + MachineOperand& MO, + unsigned MOIdx) { + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) + handleVirtualRegisterDef(MBB, MI, MIIdx, MO, MOIdx, + getOrCreateInterval(MO.getReg())); + else if (allocatableRegs_[MO.getReg()]) { + MachineInstr *CopyMI = NULL; + if (MI->isCopyLike()) + CopyMI = MI; + handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, + getOrCreateInterval(MO.getReg()), CopyMI); + // Def of a register also defines its sub-registers. + for (const unsigned* AS = tri_->getSubRegisters(MO.getReg()); *AS; ++AS) + // If MI also modifies the sub-register explicitly, avoid processing it + // more than once. Do not pass in TRI here so it checks for exact match. + if (!MI->definesRegister(*AS)) + handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, + getOrCreateInterval(*AS), 0); + } +} + +void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, + SlotIndex MIIdx, + LiveInterval &interval, bool isAlias) { + DEBUG(dbgs() << "\t\tlivein register: " << PrintReg(interval.reg, tri_)); + + // Look for kills, if it reaches a def before it's killed, then it shouldn't + // be considered a livein. + MachineBasicBlock::iterator mi = MBB->begin(); + MachineBasicBlock::iterator E = MBB->end(); + // Skip over DBG_VALUE at the start of the MBB. + if (mi != E && mi->isDebugValue()) { + while (++mi != E && mi->isDebugValue()) + ; + if (mi == E) + // MBB is empty except for DBG_VALUE's. + return; + } + + SlotIndex baseIndex = MIIdx; + SlotIndex start = baseIndex; + if (getInstructionFromIndex(baseIndex) == 0) + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + + SlotIndex end = baseIndex; + bool SeenDefUse = false; + + while (mi != E) { + if (mi->killsRegister(interval.reg, tri_)) { + DEBUG(dbgs() << " killed"); + end = baseIndex.getDefIndex(); + SeenDefUse = true; + break; + } else if (mi->definesRegister(interval.reg, tri_)) { + // Another instruction redefines the register before it is ever read. + // Then the register is essentially dead at the instruction that defines + // it. Hence its interval is: + // [defSlot(def), defSlot(def)+1) + DEBUG(dbgs() << " dead"); + end = start.getStoreIndex(); + SeenDefUse = true; + break; + } + + while (++mi != E && mi->isDebugValue()) + // Skip over DBG_VALUE. + ; + if (mi != E) + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + } + + // Live-in register might not be used at all. + if (!SeenDefUse) { + if (isAlias) { + DEBUG(dbgs() << " dead"); + end = MIIdx.getStoreIndex(); + } else { + DEBUG(dbgs() << " live through"); + end = baseIndex; + } + } + + SlotIndex defIdx = getMBBStartIdx(MBB); + assert(getInstructionFromIndex(defIdx) == 0 && + "PHI def index points at actual instruction."); + VNInfo *vni = + interval.getNextValue(defIdx, 0, VNInfoAllocator); + vni->setIsPHIDef(true); + LiveRange LR(start, end, vni); + + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR << '\n'); +} + +/// computeIntervals - computes the live intervals for virtual +/// registers. for some ordering of the machine instructions [1,N] a +/// live interval is an interval [i, j) where 1 <= i <= j < N for +/// which a variable is live +void LiveIntervals::computeIntervals() { + DEBUG(dbgs() << "********** COMPUTING LIVE INTERVALS **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); + + SmallVector UndefUses; + for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = MBBI; + if (MBB->empty()) + continue; + + // Track the index of the current machine instr. + SlotIndex MIIndex = getMBBStartIdx(MBB); + DEBUG(dbgs() << "BB#" << MBB->getNumber() + << ":\t\t# derived from " << MBB->getName() << "\n"); + + // Create intervals for live-ins to this BB first. + for (MachineBasicBlock::livein_iterator LI = MBB->livein_begin(), + LE = MBB->livein_end(); LI != LE; ++LI) { + handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*LI)); + // Multiple live-ins can alias the same register. + for (const unsigned* AS = tri_->getSubRegisters(*LI); *AS; ++AS) + if (!hasInterval(*AS)) + handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*AS), + true); + } + + // Skip over empty initial indices. + if (getInstructionFromIndex(MIIndex) == 0) + MIIndex = indexes_->getNextNonNullIndex(MIIndex); + + for (MachineBasicBlock::iterator MI = MBB->begin(), miEnd = MBB->end(); + MI != miEnd; ++MI) { + DEBUG(dbgs() << MIIndex << "\t" << *MI); + if (MI->isDebugValue()) + continue; + + // Handle defs. + for (int i = MI->getNumOperands() - 1; i >= 0; --i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + + // handle register defs - build intervals + if (MO.isDef()) + handleRegisterDef(MBB, MI, MIIndex, MO, i); + else if (MO.isUndef()) + UndefUses.push_back(MO.getReg()); + } + + // Move to the next instr slot. + MIIndex = indexes_->getNextNonNullIndex(MIIndex); + } + } + + // Create empty intervals for registers defined by implicit_def's (except + // for those implicit_def that define values which are liveout of their + // blocks. + for (unsigned i = 0, e = UndefUses.size(); i != e; ++i) { + unsigned UndefReg = UndefUses[i]; + (void)getOrCreateInterval(UndefReg); + } +} + +LiveInterval* LiveIntervals::createInterval(unsigned reg) { + float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F; + return new LiveInterval(reg, Weight); +} + +/// dupInterval - Duplicate a live interval. The caller is responsible for +/// managing the allocated memory. +LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { + LiveInterval *NewLI = createInterval(li->reg); + NewLI->Copy(*li, mri_, getVNInfoAllocator()); + return NewLI; +} + +/// shrinkToUses - After removing some uses of a register, shrink its live +/// range to just the remaining uses. This method does not compute reaching +/// defs for new uses, and it doesn't remove dead defs. +void LiveIntervals::shrinkToUses(LiveInterval *li, + SmallVectorImpl *dead) { + DEBUG(dbgs() << "Shrink: " << *li << '\n'); + assert(TargetRegisterInfo::isVirtualRegister(li->reg) + && "Can't only shrink physical registers"); + // Find all the values used, including PHI kills. + SmallVector, 16> WorkList; + + // Visit all instructions reading li->reg. + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li->reg); + MachineInstr *UseMI = I.skipInstruction();) { + if (UseMI->isDebugValue() || !UseMI->readsVirtualRegister(li->reg)) + continue; + SlotIndex Idx = getInstructionIndex(UseMI).getUseIndex(); + VNInfo *VNI = li->getVNInfoAt(Idx); + assert(VNI && "Live interval not live into reading instruction"); + if (VNI->def == Idx) { + // Special case: An early-clobber tied operand reads and writes the + // register one slot early. + Idx = Idx.getPrevSlot(); + VNI = li->getVNInfoAt(Idx); + assert(VNI && "Early-clobber tied value not available"); + } + WorkList.push_back(std::make_pair(Idx, VNI)); + } + + // Create a new live interval with only minimal live segments per def. + LiveInterval NewLI(li->reg, 0); + for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end(); + I != E; ++I) { + VNInfo *VNI = *I; + if (VNI->isUnused()) + continue; + NewLI.addRange(LiveRange(VNI->def, VNI->def.getNextSlot(), VNI)); + + // A use tied to an early-clobber def ends at the load slot and isn't caught + // above. Catch it here instead. This probably only ever happens for inline + // assembly. + if (VNI->def.isUse()) + if (VNInfo *UVNI = li->getVNInfoAt(VNI->def.getLoadIndex())) + WorkList.push_back(std::make_pair(VNI->def.getLoadIndex(), UVNI)); + } + + // Keep track of the PHIs that are in use. + SmallPtrSet UsedPHIs; + + // Extend intervals to reach all uses in WorkList. + while (!WorkList.empty()) { + SlotIndex Idx = WorkList.back().first; + VNInfo *VNI = WorkList.back().second; + WorkList.pop_back(); + const MachineBasicBlock *MBB = getMBBFromIndex(Idx); + SlotIndex BlockStart = getMBBStartIdx(MBB); + + // Extend the live range for VNI to be live at Idx. + if (VNInfo *ExtVNI = NewLI.extendInBlock(BlockStart, Idx)) { + (void)ExtVNI; + assert(ExtVNI == VNI && "Unexpected existing value number"); + // Is this a PHIDef we haven't seen before? + if (!VNI->isPHIDef() || VNI->def != BlockStart || !UsedPHIs.insert(VNI)) + continue; + // The PHI is live, make sure the predecessors are live-out. + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); + VNInfo *PVNI = li->getVNInfoAt(Stop); + // A predecessor is not required to have a live-out value for a PHI. + if (PVNI) { + assert(PVNI->hasPHIKill() && "Missing hasPHIKill flag"); + WorkList.push_back(std::make_pair(Stop, PVNI)); + } + } + continue; + } + + // VNI is live-in to MBB. + DEBUG(dbgs() << " live-in at " << BlockStart << '\n'); + NewLI.addRange(LiveRange(BlockStart, Idx.getNextSlot(), VNI)); + + // Make sure VNI is live-out from the predecessors. + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + SlotIndex Stop = getMBBEndIdx(*PI).getPrevSlot(); + assert(li->getVNInfoAt(Stop) == VNI && "Wrong value out of predecessor"); + WorkList.push_back(std::make_pair(Stop, VNI)); + } + } + + // Handle dead values. + for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end(); + I != E; ++I) { + VNInfo *VNI = *I; + if (VNI->isUnused()) + continue; + LiveInterval::iterator LII = NewLI.FindLiveRangeContaining(VNI->def); + assert(LII != NewLI.end() && "Missing live range for PHI"); + if (LII->end != VNI->def.getNextSlot()) + continue; + if (VNI->isPHIDef()) { + // This is a dead PHI. Remove it. + VNI->setIsUnused(true); + NewLI.removeRange(*LII); + } else { + // This is a dead def. Make sure the instruction knows. + MachineInstr *MI = getInstructionFromIndex(VNI->def); + assert(MI && "No instruction defining live value"); + MI->addRegisterDead(li->reg, tri_); + if (dead && MI->allDefsAreDead()) { + DEBUG(dbgs() << "All defs dead: " << *MI); + dead->push_back(MI); + } + } + } + + // Move the trimmed ranges back. + li->ranges.swap(NewLI.ranges); + DEBUG(dbgs() << "Shrink: " << *li << '\n'); +} + + +//===----------------------------------------------------------------------===// +// Register allocator hooks. +// + +MachineBasicBlock::iterator +LiveIntervals::getLastSplitPoint(const LiveInterval &li, + MachineBasicBlock *mbb) const { + const MachineBasicBlock *lpad = mbb->getLandingPadSuccessor(); + + // If li is not live into a landing pad, we can insert spill code before the + // first terminator. + if (!lpad || !isLiveInToMBB(li, lpad)) + return mbb->getFirstTerminator(); + + // When there is a landing pad, spill code must go before the call instruction + // that can throw. + MachineBasicBlock::iterator I = mbb->end(), B = mbb->begin(); + while (I != B) { + --I; + if (I->getDesc().isCall()) + return I; + } + // The block contains no calls that can throw, so use the first terminator. + return mbb->getFirstTerminator(); +} + +void LiveIntervals::addKillFlags() { + for (iterator I = begin(), E = end(); I != E; ++I) { + unsigned Reg = I->first; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (mri_->reg_nodbg_empty(Reg)) + continue; + LiveInterval *LI = I->second; + + // Every instruction that kills Reg corresponds to a live range end point. + for (LiveInterval::iterator RI = LI->begin(), RE = LI->end(); RI != RE; + ++RI) { + // A LOAD index indicates an MBB edge. + if (RI->end.isLoad()) + continue; + MachineInstr *MI = getInstructionFromIndex(RI->end); + if (!MI) + continue; + MI->addRegisterKilled(Reg, NULL); + } + } +} + +/// getReMatImplicitUse - If the remat definition MI has one (for now, we only +/// allow one) virtual register operand, then its uses are implicitly using +/// the register. Returns the virtual register. +unsigned LiveIntervals::getReMatImplicitUse(const LiveInterval &li, + MachineInstr *MI) const { + unsigned RegOp = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || Reg == li.reg) + continue; + + if (TargetRegisterInfo::isPhysicalRegister(Reg) && + !allocatableRegs_[Reg]) + continue; + // FIXME: For now, only remat MI with at most one register operand. + assert(!RegOp && + "Can't rematerialize instruction with multiple register operand!"); + RegOp = MO.getReg(); +#ifndef NDEBUG + break; +#endif + } + return RegOp; +} + +/// isValNoAvailableAt - Return true if the val# of the specified interval +/// which reaches the given instruction also reaches the specified use index. +bool LiveIntervals::isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI, + SlotIndex UseIdx) const { + VNInfo *UValNo = li.getVNInfoAt(UseIdx); + return UValNo && UValNo == li.getVNInfoAt(getInstructionIndex(MI)); +} + +/// isReMaterializable - Returns true if the definition MI of the specified +/// val# of the specified interval is re-materializable. +bool +LiveIntervals::isReMaterializable(const LiveInterval &li, + const VNInfo *ValNo, MachineInstr *MI, + const SmallVectorImpl &SpillIs, + bool &isLoad) { + if (DisableReMat) + return false; + + if (!tii_->isTriviallyReMaterializable(MI, aa_)) + return false; + + // Target-specific code can mark an instruction as being rematerializable + // if it has one virtual reg use, though it had better be something like + // a PIC base register which is likely to be live everywhere. + unsigned ImpUse = getReMatImplicitUse(li, MI); + if (ImpUse) { + const LiveInterval &ImpLi = getInterval(ImpUse); + for (MachineRegisterInfo::use_nodbg_iterator + ri = mri_->use_nodbg_begin(li.reg), re = mri_->use_nodbg_end(); + ri != re; ++ri) { + MachineInstr *UseMI = &*ri; + SlotIndex UseIdx = getInstructionIndex(UseMI); + if (li.getVNInfoAt(UseIdx) != ValNo) + continue; + if (!isValNoAvailableAt(ImpLi, MI, UseIdx)) + return false; + } + + // If a register operand of the re-materialized instruction is going to + // be spilled next, then it's not legal to re-materialize this instruction. + for (unsigned i = 0, e = SpillIs.size(); i != e; ++i) + if (ImpUse == SpillIs[i]->reg) + return false; + } + return true; +} + +/// isReMaterializable - Returns true if the definition MI of the specified +/// val# of the specified interval is re-materializable. +bool LiveIntervals::isReMaterializable(const LiveInterval &li, + const VNInfo *ValNo, MachineInstr *MI) { + SmallVector Dummy1; + bool Dummy2; + return isReMaterializable(li, ValNo, MI, Dummy1, Dummy2); +} + +/// isReMaterializable - Returns true if every definition of MI of every +/// val# of the specified interval is re-materializable. +bool +LiveIntervals::isReMaterializable(const LiveInterval &li, + const SmallVectorImpl &SpillIs, + bool &isLoad) { + isLoad = false; + for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); + i != e; ++i) { + const VNInfo *VNI = *i; + if (VNI->isUnused()) + continue; // Dead val#. + // Is the def for the val# rematerializable? + MachineInstr *ReMatDefMI = getInstructionFromIndex(VNI->def); + if (!ReMatDefMI) + return false; + bool DefIsLoad = false; + if (!ReMatDefMI || + !isReMaterializable(li, VNI, ReMatDefMI, SpillIs, DefIsLoad)) + return false; + isLoad |= DefIsLoad; + } + return true; +} + +/// FilterFoldedOps - Filter out two-address use operands. Return +/// true if it finds any issue with the operands that ought to prevent +/// folding. +static bool FilterFoldedOps(MachineInstr *MI, + SmallVector &Ops, + unsigned &MRInfo, + SmallVector &FoldOps) { + MRInfo = 0; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + unsigned OpIdx = Ops[i]; + MachineOperand &MO = MI->getOperand(OpIdx); + // FIXME: fold subreg use. + if (MO.getSubReg()) + return true; + if (MO.isDef()) + MRInfo |= (unsigned)VirtRegMap::isMod; + else { + // Filter out two-address use operand(s). + if (MI->isRegTiedToDefOperand(OpIdx)) { + MRInfo = VirtRegMap::isModRef; + continue; + } + MRInfo |= (unsigned)VirtRegMap::isRef; + } + FoldOps.push_back(OpIdx); + } + return false; +} + + +/// tryFoldMemoryOperand - Attempts to fold either a spill / restore from +/// slot / to reg or any rematerialized load into ith operand of specified +/// MI. If it is successul, MI is updated with the newly created MI and +/// returns true. +bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, + VirtRegMap &vrm, MachineInstr *DefMI, + SlotIndex InstrIdx, + SmallVector &Ops, + bool isSS, int Slot, unsigned Reg) { + // If it is an implicit def instruction, just delete it. + if (MI->isImplicitDef()) { + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + ++numFolds; + return true; + } + + // Filter the list of operand indexes that are to be folded. Abort if + // any operand will prevent folding. + unsigned MRInfo = 0; + SmallVector FoldOps; + if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps)) + return false; + + // The only time it's safe to fold into a two address instruction is when + // it's folding reload and spill from / into a spill stack slot. + if (DefMI && (MRInfo & VirtRegMap::isMod)) + return false; + + MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(MI, FoldOps, Slot) + : tii_->foldMemoryOperand(MI, FoldOps, DefMI); + if (fmi) { + // Remember this instruction uses the spill slot. + if (isSS) vrm.addSpillSlotUse(Slot, fmi); + + // Attempt to fold the memory reference into the instruction. If + // we can do this, we don't need to insert spill code. + if (isSS && !mf_->getFrameInfo()->isImmutableObjectIndex(Slot)) + vrm.virtFolded(Reg, MI, fmi, (VirtRegMap::ModRef)MRInfo); + vrm.transferSpillPts(MI, fmi); + vrm.transferRestorePts(MI, fmi); + vrm.transferEmergencySpills(MI, fmi); + ReplaceMachineInstrInMaps(MI, fmi); + MI->eraseFromParent(); + MI = fmi; + ++numFolds; + return true; + } + return false; +} + +/// canFoldMemoryOperand - Returns true if the specified load / store +/// folding is possible. +bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI, + SmallVector &Ops, + bool ReMat) const { + // Filter the list of operand indexes that are to be folded. Abort if + // any operand will prevent folding. + unsigned MRInfo = 0; + SmallVector FoldOps; + if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps)) + return false; + + // It's only legal to remat for a use, not a def. + if (ReMat && (MRInfo & VirtRegMap::isMod)) + return false; + + return tii_->canFoldMemoryOperand(MI, FoldOps); +} + +bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const { + LiveInterval::Ranges::const_iterator itr = li.ranges.begin(); + + MachineBasicBlock *mbb = indexes_->getMBBCoveringRange(itr->start, itr->end); + + if (mbb == 0) + return false; + + for (++itr; itr != li.ranges.end(); ++itr) { + MachineBasicBlock *mbb2 = + indexes_->getMBBCoveringRange(itr->start, itr->end); + + if (mbb2 != mbb) + return false; + } + + return true; +} + +/// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of +/// interval on to-be re-materialized operands of MI) with new register. +void LiveIntervals::rewriteImplicitOps(const LiveInterval &li, + MachineInstr *MI, unsigned NewVReg, + VirtRegMap &vrm) { + // There is an implicit use. That means one of the other operand is + // being remat'ed and the remat'ed instruction has li.reg as an + // use operand. Make sure we rewrite that as well. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (!vrm.isReMaterialized(Reg)) + continue; + MachineInstr *ReMatMI = vrm.getReMaterializedMI(Reg); + MachineOperand *UseMO = ReMatMI->findRegisterUseOperand(li.reg); + if (UseMO) + UseMO->setReg(NewVReg); + } +} + +/// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions +/// for addIntervalsForSpills to rewrite uses / defs for the given live range. +bool LiveIntervals:: +rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI, + bool TrySplit, SlotIndex index, SlotIndex end, + MachineInstr *MI, + MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, + const TargetRegisterClass* rc, + SmallVector &ReMatIds, + const MachineLoopInfo *loopInfo, + unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse, + DenseMap &MBBVRegsMap, + std::vector &NewLIs) { + bool CanFold = false; + RestartInstruction: + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& mop = MI->getOperand(i); + if (!mop.isReg()) + continue; + unsigned Reg = mop.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (Reg != li.reg) + continue; + + bool TryFold = !DefIsReMat; + bool FoldSS = true; // Default behavior unless it's a remat. + int FoldSlot = Slot; + if (DefIsReMat) { + // If this is the rematerializable definition MI itself and + // all of its uses are rematerialized, simply delete it. + if (MI == ReMatOrigDefMI && CanDelete) { + DEBUG(dbgs() << "\t\t\t\tErasing re-materializable def: " + << *MI << '\n'); + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + break; + } + + // If def for this use can't be rematerialized, then try folding. + // If def is rematerializable and it's a load, also try folding. + TryFold = !ReMatDefMI || (ReMatDefMI && (MI == ReMatOrigDefMI || isLoad)); + if (isLoad) { + // Try fold loads (from stack slot, constant pool, etc.) into uses. + FoldSS = isLoadSS; + FoldSlot = LdSlot; + } + } + + // Scan all of the operands of this instruction rewriting operands + // to use NewVReg instead of li.reg as appropriate. We do this for + // two reasons: + // + // 1. If the instr reads the same spilled vreg multiple times, we + // want to reuse the NewVReg. + // 2. If the instr is a two-addr instruction, we are required to + // keep the src/dst regs pinned. + // + // Keep track of whether we replace a use and/or def so that we can + // create the spill interval with the appropriate range. + SmallVector Ops; + tie(HasUse, HasDef) = MI->readsWritesVirtualRegister(Reg, &Ops); + + // Create a new virtual register for the spill interval. + // Create the new register now so we can map the fold instruction + // to the new register so when it is unfolded we get the correct + // answer. + bool CreatedNewVReg = false; + if (NewVReg == 0) { + NewVReg = mri_->createVirtualRegister(rc); + vrm.grow(); + CreatedNewVReg = true; + + // The new virtual register should get the same allocation hints as the + // old one. + std::pair Hint = mri_->getRegAllocationHint(Reg); + if (Hint.first || Hint.second) + mri_->setRegAllocationHint(NewVReg, Hint.first, Hint.second); + } + + if (!TryFold) + CanFold = false; + else { + // Do not fold load / store here if we are splitting. We'll find an + // optimal point to insert a load / store later. + if (!TrySplit) { + if (tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, + Ops, FoldSS, FoldSlot, NewVReg)) { + // Folding the load/store can completely change the instruction in + // unpredictable ways, rescan it from the beginning. + + if (FoldSS) { + // We need to give the new vreg the same stack slot as the + // spilled interval. + vrm.assignVirt2StackSlot(NewVReg, FoldSlot); + } + + HasUse = false; + HasDef = false; + CanFold = false; + if (isNotInMIMap(MI)) + break; + goto RestartInstruction; + } + } else { + // We'll try to fold it later if it's profitable. + CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat); + } + } + + mop.setReg(NewVReg); + if (mop.isImplicit()) + rewriteImplicitOps(li, MI, NewVReg, vrm); + + // Reuse NewVReg for other reads. + bool HasEarlyClobber = false; + for (unsigned j = 0, e = Ops.size(); j != e; ++j) { + MachineOperand &mopj = MI->getOperand(Ops[j]); + mopj.setReg(NewVReg); + if (mopj.isImplicit()) + rewriteImplicitOps(li, MI, NewVReg, vrm); + if (mopj.isEarlyClobber()) + HasEarlyClobber = true; + } + + if (CreatedNewVReg) { + if (DefIsReMat) { + vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI); + if (ReMatIds[VNI->id] == VirtRegMap::MAX_STACK_SLOT) { + // Each valnum may have its own remat id. + ReMatIds[VNI->id] = vrm.assignVirtReMatId(NewVReg); + } else { + vrm.assignVirtReMatId(NewVReg, ReMatIds[VNI->id]); + } + if (!CanDelete || (HasUse && HasDef)) { + // If this is a two-addr instruction then its use operands are + // rematerializable but its def is not. It should be assigned a + // stack slot. + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + } else { + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + } else if (HasUse && HasDef && + vrm.getStackSlot(NewVReg) == VirtRegMap::NO_STACK_SLOT) { + // If this interval hasn't been assigned a stack slot (because earlier + // def is a deleted remat def), do it now. + assert(Slot != VirtRegMap::NO_STACK_SLOT); + vrm.assignVirt2StackSlot(NewVReg, Slot); + } + + // Re-matting an instruction with virtual register use. Add the + // register as an implicit use on the use MI. + if (DefIsReMat && ImpUse) + MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); + + // Create a new register interval for this spill / remat. + LiveInterval &nI = getOrCreateInterval(NewVReg); + if (CreatedNewVReg) { + NewLIs.push_back(&nI); + MBBVRegsMap.insert(std::make_pair(MI->getParent()->getNumber(), NewVReg)); + if (TrySplit) + vrm.setIsSplitFromReg(NewVReg, li.reg); + } + + if (HasUse) { + if (CreatedNewVReg) { + LiveRange LR(index.getLoadIndex(), index.getDefIndex(), + nI.getNextValue(SlotIndex(), 0, VNInfoAllocator)); + DEBUG(dbgs() << " +" << LR); + nI.addRange(LR); + } else { + // Extend the split live interval to this def / use. + SlotIndex End = index.getDefIndex(); + LiveRange LR(nI.ranges[nI.ranges.size()-1].end, End, + nI.getValNumInfo(nI.getNumValNums()-1)); + DEBUG(dbgs() << " +" << LR); + nI.addRange(LR); + } + } + if (HasDef) { + // An early clobber starts at the use slot, except for an early clobber + // tied to a use operand (yes, that is a thing). + LiveRange LR(HasEarlyClobber && !HasUse ? + index.getUseIndex() : index.getDefIndex(), + index.getStoreIndex(), + nI.getNextValue(SlotIndex(), 0, VNInfoAllocator)); + DEBUG(dbgs() << " +" << LR); + nI.addRange(LR); + } + + DEBUG({ + dbgs() << "\t\t\t\tAdded new interval: "; + nI.print(dbgs(), tri_); + dbgs() << '\n'; + }); + } + return CanFold; +} +bool LiveIntervals::anyKillInMBBAfterIdx(const LiveInterval &li, + const VNInfo *VNI, + MachineBasicBlock *MBB, + SlotIndex Idx) const { + return li.killedInRange(Idx.getNextSlot(), getMBBEndIdx(MBB)); +} + +/// RewriteInfo - Keep track of machine instrs that will be rewritten +/// during spilling. +namespace { + struct RewriteInfo { + SlotIndex Index; + MachineInstr *MI; + RewriteInfo(SlotIndex i, MachineInstr *mi) : Index(i), MI(mi) {} + }; + + struct RewriteInfoCompare { + bool operator()(const RewriteInfo &LHS, const RewriteInfo &RHS) const { + return LHS.Index < RHS.Index; + } + }; +} + +void LiveIntervals:: +rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, + LiveInterval::Ranges::const_iterator &I, + MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI, + unsigned Slot, int LdSlot, + bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete, + VirtRegMap &vrm, + const TargetRegisterClass* rc, + SmallVector &ReMatIds, + const MachineLoopInfo *loopInfo, + BitVector &SpillMBBs, + DenseMap > &SpillIdxes, + BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes, + DenseMap &MBBVRegsMap, + std::vector &NewLIs) { + bool AllCanFold = true; + unsigned NewVReg = 0; + SlotIndex start = I->start.getBaseIndex(); + SlotIndex end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); + + // First collect all the def / use in this live range that will be rewritten. + // Make sure they are sorted according to instruction index. + std::vector RewriteMIs; + for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg), + re = mri_->reg_end(); ri != re; ) { + MachineInstr *MI = &*ri; + MachineOperand &O = ri.getOperand(); + ++ri; + if (MI->isDebugValue()) { + // Modify DBG_VALUE now that the value is in a spill slot. + if (Slot != VirtRegMap::MAX_STACK_SLOT || isLoadSS) { + uint64_t Offset = MI->getOperand(1).getImm(); + const MDNode *MDPtr = MI->getOperand(2).getMetadata(); + DebugLoc DL = MI->getDebugLoc(); + int FI = isLoadSS ? LdSlot : (int)Slot; + if (MachineInstr *NewDV = tii_->emitFrameIndexDebugValue(*mf_, FI, + Offset, MDPtr, DL)) { + DEBUG(dbgs() << "Modifying debug info due to spill:" << "\t" << *MI); + ReplaceMachineInstrInMaps(MI, NewDV); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MBB->erase(MI), NewDV); + continue; + } + } + + DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI); + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + continue; + } + assert(!(O.isImplicit() && O.isUse()) && + "Spilling register that's used as implicit use?"); + SlotIndex index = getInstructionIndex(MI); + if (index < start || index >= end) + continue; + + if (O.isUndef()) + // Must be defined by an implicit def. It should not be spilled. Note, + // this is for correctness reason. e.g. + // 8 %reg1024 = IMPLICIT_DEF + // 12 %reg1024 = INSERT_SUBREG %reg1024, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. + continue; + RewriteMIs.push_back(RewriteInfo(index, MI)); + } + std::sort(RewriteMIs.begin(), RewriteMIs.end(), RewriteInfoCompare()); + + unsigned ImpUse = DefIsReMat ? getReMatImplicitUse(li, ReMatDefMI) : 0; + // Now rewrite the defs and uses. + for (unsigned i = 0, e = RewriteMIs.size(); i != e; ) { + RewriteInfo &rwi = RewriteMIs[i]; + ++i; + SlotIndex index = rwi.Index; + MachineInstr *MI = rwi.MI; + // If MI def and/or use the same register multiple times, then there + // are multiple entries. + while (i != e && RewriteMIs[i].MI == MI) { + assert(RewriteMIs[i].Index == index); + ++i; + } + MachineBasicBlock *MBB = MI->getParent(); + + if (ImpUse && MI != ReMatDefMI) { + // Re-matting an instruction with virtual register use. Prevent interval + // from being spilled. + getInterval(ImpUse).markNotSpillable(); + } + + unsigned MBBId = MBB->getNumber(); + unsigned ThisVReg = 0; + if (TrySplit) { + DenseMap::iterator NVI = MBBVRegsMap.find(MBBId); + if (NVI != MBBVRegsMap.end()) { + ThisVReg = NVI->second; + // One common case: + // x = use + // ... + // ... + // def = ... + // = use + // It's better to start a new interval to avoid artifically + // extend the new interval. + if (MI->readsWritesVirtualRegister(li.reg) == + std::make_pair(false,true)) { + MBBVRegsMap.erase(MBB->getNumber()); + ThisVReg = 0; + } + } + } + + bool IsNew = ThisVReg == 0; + if (IsNew) { + // This ends the previous live interval. If all of its def / use + // can be folded, give it a low spill weight. + if (NewVReg && TrySplit && AllCanFold) { + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } + AllCanFold = true; + } + NewVReg = ThisVReg; + + bool HasDef = false; + bool HasUse = false; + bool CanFold = rewriteInstructionForSpills(li, I->valno, TrySplit, + index, end, MI, ReMatOrigDefMI, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + CanDelete, vrm, rc, ReMatIds, loopInfo, NewVReg, + ImpUse, HasDef, HasUse, MBBVRegsMap, NewLIs); + if (!HasDef && !HasUse) + continue; + + AllCanFold &= CanFold; + + // Update weight of spill interval. + LiveInterval &nI = getOrCreateInterval(NewVReg); + if (!TrySplit) { + // The spill weight is now infinity as it cannot be spilled again. + nI.markNotSpillable(); + continue; + } + + // Keep track of the last def and first use in each MBB. + if (HasDef) { + if (MI != ReMatOrigDefMI || !CanDelete) { + bool HasKill = false; + if (!HasUse) + HasKill = anyKillInMBBAfterIdx(li, I->valno, MBB, index.getDefIndex()); + else { + // If this is a two-address code, then this index starts a new VNInfo. + const VNInfo *VNI = li.findDefinedVNInfoForRegInt(index.getDefIndex()); + if (VNI) + HasKill = anyKillInMBBAfterIdx(li, VNI, MBB, index.getDefIndex()); + } + DenseMap >::iterator SII = + SpillIdxes.find(MBBId); + if (!HasKill) { + if (SII == SpillIdxes.end()) { + std::vector S; + S.push_back(SRInfo(index, NewVReg, true)); + SpillIdxes.insert(std::make_pair(MBBId, S)); + } else if (SII->second.back().vreg != NewVReg) { + SII->second.push_back(SRInfo(index, NewVReg, true)); + } else if (index > SII->second.back().index) { + // If there is an earlier def and this is a two-address + // instruction, then it's not possible to fold the store (which + // would also fold the load). + SRInfo &Info = SII->second.back(); + Info.index = index; + Info.canFold = !HasUse; + } + SpillMBBs.set(MBBId); + } else if (SII != SpillIdxes.end() && + SII->second.back().vreg == NewVReg && + index > SII->second.back().index) { + // There is an earlier def that's not killed (must be two-address). + // The spill is no longer needed. + SII->second.pop_back(); + if (SII->second.empty()) { + SpillIdxes.erase(MBBId); + SpillMBBs.reset(MBBId); + } + } + } + } + + if (HasUse) { + DenseMap >::iterator SII = + SpillIdxes.find(MBBId); + if (SII != SpillIdxes.end() && + SII->second.back().vreg == NewVReg && + index > SII->second.back().index) + // Use(s) following the last def, it's not safe to fold the spill. + SII->second.back().canFold = false; + DenseMap >::iterator RII = + RestoreIdxes.find(MBBId); + if (RII != RestoreIdxes.end() && RII->second.back().vreg == NewVReg) + // If we are splitting live intervals, only fold if it's the first + // use and there isn't another use later in the MBB. + RII->second.back().canFold = false; + else if (IsNew) { + // Only need a reload if there isn't an earlier def / use. + if (RII == RestoreIdxes.end()) { + std::vector Infos; + Infos.push_back(SRInfo(index, NewVReg, true)); + RestoreIdxes.insert(std::make_pair(MBBId, Infos)); + } else { + RII->second.push_back(SRInfo(index, NewVReg, true)); + } + RestoreMBBs.set(MBBId); + } + } + + // Update spill weight. + unsigned loopDepth = loopInfo->getLoopDepth(MBB); + nI.weight += getSpillWeight(HasDef, HasUse, loopDepth); + } + + if (NewVReg && TrySplit && AllCanFold) { + // If all of its def / use can be folded, give it a low spill weight. + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } +} + +bool LiveIntervals::alsoFoldARestore(int Id, SlotIndex index, + unsigned vr, BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes) { + if (!RestoreMBBs[Id]) + return false; + std::vector &Restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = Restores.size(); i != e; ++i) + if (Restores[i].index == index && + Restores[i].vreg == vr && + Restores[i].canFold) + return true; + return false; +} + +void LiveIntervals::eraseRestoreInfo(int Id, SlotIndex index, + unsigned vr, BitVector &RestoreMBBs, + DenseMap > &RestoreIdxes) { + if (!RestoreMBBs[Id]) + return; + std::vector &Restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = Restores.size(); i != e; ++i) + if (Restores[i].index == index && Restores[i].vreg) + Restores[i].index = SlotIndex(); +} + +/// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being +/// spilled and create empty intervals for their uses. +void +LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, + const TargetRegisterClass* rc, + std::vector &NewLIs) { + for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg), + re = mri_->reg_end(); ri != re; ) { + MachineOperand &O = ri.getOperand(); + MachineInstr *MI = &*ri; + ++ri; + if (MI->isDebugValue()) { + // Remove debug info for now. + O.setReg(0U); + DEBUG(dbgs() << "Removing debug info due to spill:" << "\t" << *MI); + continue; + } + if (O.isDef()) { + assert(MI->isImplicitDef() && + "Register def was not rewritten?"); + RemoveMachineInstrFromMaps(MI); + vrm.RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } else { + // This must be an use of an implicit_def so it's not part of the live + // interval. Create a new empty live interval for it. + // FIXME: Can we simply erase some of the instructions? e.g. Stores? + unsigned NewVReg = mri_->createVirtualRegister(rc); + vrm.grow(); + vrm.setIsImplicitlyDefined(NewVReg); + NewLIs.push_back(&getOrCreateInterval(NewVReg)); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == li.reg) { + MO.setReg(NewVReg); + MO.setIsUndef(); + } + } + } + } +} + +float +LiveIntervals::getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { + // Limit the loop depth ridiculousness. + if (loopDepth > 200) + loopDepth = 200; + + // The loop depth is used to roughly estimate the number of times the + // instruction is executed. Something like 10^d is simple, but will quickly + // overflow a float. This expression behaves like 10^d for small d, but is + // more tempered for large d. At d=200 we get 6.7e33 which leaves a bit of + // headroom before overflow. + float lc = std::pow(1 + (100.0f / (loopDepth+10)), (float)loopDepth); + + return (isDef + isUse) * lc; +} + +static void normalizeSpillWeights(std::vector &NewLIs) { + for (unsigned i = 0, e = NewLIs.size(); i != e; ++i) + NewLIs[i]->weight = + normalizeSpillWeight(NewLIs[i]->weight, NewLIs[i]->getSize()); +} + +std::vector LiveIntervals:: +addIntervalsForSpills(const LiveInterval &li, + const SmallVectorImpl &SpillIs, + const MachineLoopInfo *loopInfo, VirtRegMap &vrm) { + assert(li.isSpillable() && "attempt to spill already spilled interval!"); + + DEBUG({ + dbgs() << "\t\t\t\tadding intervals for spills for interval: "; + li.print(dbgs(), tri_); + dbgs() << '\n'; + }); + + // Each bit specify whether a spill is required in the MBB. + BitVector SpillMBBs(mf_->getNumBlockIDs()); + DenseMap > SpillIdxes; + BitVector RestoreMBBs(mf_->getNumBlockIDs()); + DenseMap > RestoreIdxes; + DenseMap MBBVRegsMap; + std::vector NewLIs; + const TargetRegisterClass* rc = mri_->getRegClass(li.reg); + + unsigned NumValNums = li.getNumValNums(); + SmallVector ReMatDefs; + ReMatDefs.resize(NumValNums, NULL); + SmallVector ReMatOrigDefs; + ReMatOrigDefs.resize(NumValNums, NULL); + SmallVector ReMatIds; + ReMatIds.resize(NumValNums, VirtRegMap::MAX_STACK_SLOT); + BitVector ReMatDelete(NumValNums); + unsigned Slot = VirtRegMap::MAX_STACK_SLOT; + + // Spilling a split live interval. It cannot be split any further. Also, + // it's also guaranteed to be a single val# / range interval. + if (vrm.getPreSplitReg(li.reg)) { + vrm.setIsSplitFromReg(li.reg, 0); + // Unset the split kill marker on the last use. + SlotIndex KillIdx = vrm.getKillPoint(li.reg); + if (KillIdx != SlotIndex()) { + MachineInstr *KillMI = getInstructionFromIndex(KillIdx); + assert(KillMI && "Last use disappeared?"); + int KillOp = KillMI->findRegisterUseOperandIdx(li.reg, true); + assert(KillOp != -1 && "Last use disappeared?"); + KillMI->getOperand(KillOp).setIsKill(false); + } + vrm.removeKillPoint(li.reg); + bool DefIsReMat = vrm.isReMaterialized(li.reg); + Slot = vrm.getStackSlot(li.reg); + assert(Slot != VirtRegMap::MAX_STACK_SLOT); + MachineInstr *ReMatDefMI = DefIsReMat ? + vrm.getReMaterializedMI(li.reg) : NULL; + int LdSlot = 0; + bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + bool isLoad = isLoadSS || + (DefIsReMat && (ReMatDefMI->getDesc().canFoldAsLoad())); + bool IsFirstRange = true; + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + // If this is a split live interval with multiple ranges, it means there + // are two-address instructions that re-defined the value. Only the + // first def can be rematerialized! + if (IsFirstRange) { + // Note ReMatOrigDefMI has already been deleted. + rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + false, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } else { + rewriteInstructionsForSpills(li, false, I, NULL, 0, + Slot, 0, false, false, false, + false, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } + IsFirstRange = false; + } + + handleSpilledImpDefs(li, vrm, rc, NewLIs); + normalizeSpillWeights(NewLIs); + return NewLIs; + } + + bool TrySplit = !intervalIsInOneMBB(li); + if (TrySplit) + ++numSplits; + bool NeedStackSlot = false; + for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end(); + i != e; ++i) { + const VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (VNI->isUnused()) + continue; // Dead val#. + // Is the def for the val# rematerializable? + MachineInstr *ReMatDefMI = getInstructionFromIndex(VNI->def); + bool dummy; + if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, SpillIs, dummy)) { + // Remember how to remat the def of this val#. + ReMatOrigDefs[VN] = ReMatDefMI; + // Original def may be modified so we have to make a copy here. + MachineInstr *Clone = mf_->CloneMachineInstr(ReMatDefMI); + CloneMIs.push_back(Clone); + ReMatDefs[VN] = Clone; + + bool CanDelete = true; + if (VNI->hasPHIKill()) { + // A kill is a phi node, not all of its uses can be rematerialized. + // It must not be deleted. + CanDelete = false; + // Need a stack slot if there is any live range where uses cannot be + // rematerialized. + NeedStackSlot = true; + } + if (CanDelete) + ReMatDelete.set(VN); + } else { + // Need a stack slot if there is any live range where uses cannot be + // rematerialized. + NeedStackSlot = true; + } + } + + // One stack slot per live interval. + if (NeedStackSlot && vrm.getPreSplitReg(li.reg) == 0) { + if (vrm.getStackSlot(li.reg) == VirtRegMap::NO_STACK_SLOT) + Slot = vrm.assignVirt2StackSlot(li.reg); + + // This case only occurs when the prealloc splitter has already assigned + // a stack slot to this vreg. + else + Slot = vrm.getStackSlot(li.reg); + } + + // Create new intervals and rewrite defs and uses. + for (LiveInterval::Ranges::const_iterator + I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { + MachineInstr *ReMatDefMI = ReMatDefs[I->valno->id]; + MachineInstr *ReMatOrigDefMI = ReMatOrigDefs[I->valno->id]; + bool DefIsReMat = ReMatDefMI != NULL; + bool CanDelete = ReMatDelete[I->valno->id]; + int LdSlot = 0; + bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + bool isLoad = isLoadSS || + (DefIsReMat && ReMatDefMI->getDesc().canFoldAsLoad()); + rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + CanDelete, vrm, rc, ReMatIds, loopInfo, + SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes, + MBBVRegsMap, NewLIs); + } + + // Insert spills / restores if we are splitting. + if (!TrySplit) { + handleSpilledImpDefs(li, vrm, rc, NewLIs); + normalizeSpillWeights(NewLIs); + return NewLIs; + } + + SmallPtrSet AddedKill; + SmallVector Ops; + if (NeedStackSlot) { + int Id = SpillMBBs.find_first(); + while (Id != -1) { + std::vector &spills = SpillIdxes[Id]; + for (unsigned i = 0, e = spills.size(); i != e; ++i) { + SlotIndex index = spills[i].index; + unsigned VReg = spills[i].vreg; + LiveInterval &nI = getOrCreateInterval(VReg); + bool isReMat = vrm.isReMaterialized(VReg); + MachineInstr *MI = getInstructionFromIndex(index); + bool CanFold = false; + bool FoundUse = false; + Ops.clear(); + if (spills[i].canFold) { + CanFold = true; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg() || MO.getReg() != VReg) + continue; + + Ops.push_back(j); + if (MO.isDef()) + continue; + if (isReMat || + (!FoundUse && !alsoFoldARestore(Id, index, VReg, + RestoreMBBs, RestoreIdxes))) { + // MI has two-address uses of the same register. If the use + // isn't the first and only use in the BB, then we can't fold + // it. FIXME: Move this to rewriteInstructionsForSpills. + CanFold = false; + break; + } + FoundUse = true; + } + } + // Fold the store into the def if possible. + bool Folded = false; + if (CanFold && !Ops.empty()) { + if (tryFoldMemoryOperand(MI, vrm, NULL, index, Ops, true, Slot,VReg)){ + Folded = true; + if (FoundUse) { + // Also folded uses, do not issue a load. + eraseRestoreInfo(Id, index, VReg, RestoreMBBs, RestoreIdxes); + nI.removeRange(index.getLoadIndex(), index.getDefIndex()); + } + nI.removeRange(index.getDefIndex(), index.getStoreIndex()); + } + } + + // Otherwise tell the spiller to issue a spill. + if (!Folded) { + LiveRange *LR = &nI.ranges[nI.ranges.size()-1]; + bool isKill = LR->end == index.getStoreIndex(); + if (!MI->registerDefIsDead(nI.reg)) + // No need to spill a dead def. + vrm.addSpillPoint(VReg, isKill, MI); + if (isKill) + AddedKill.insert(&nI); + } + } + Id = SpillMBBs.find_next(Id); + } + } + + int Id = RestoreMBBs.find_first(); + while (Id != -1) { + std::vector &restores = RestoreIdxes[Id]; + for (unsigned i = 0, e = restores.size(); i != e; ++i) { + SlotIndex index = restores[i].index; + if (index == SlotIndex()) + continue; + unsigned VReg = restores[i].vreg; + LiveInterval &nI = getOrCreateInterval(VReg); + bool isReMat = vrm.isReMaterialized(VReg); + MachineInstr *MI = getInstructionFromIndex(index); + bool CanFold = false; + Ops.clear(); + if (restores[i].canFold) { + CanFold = true; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg() || MO.getReg() != VReg) + continue; + + if (MO.isDef()) { + // If this restore were to be folded, it would have been folded + // already. + CanFold = false; + break; + } + Ops.push_back(j); + } + } + + // Fold the load into the use if possible. + bool Folded = false; + if (CanFold && !Ops.empty()) { + if (!isReMat) + Folded = tryFoldMemoryOperand(MI, vrm, NULL,index,Ops,true,Slot,VReg); + else { + MachineInstr *ReMatDefMI = vrm.getReMaterializedMI(VReg); + int LdSlot = 0; + bool isLoadSS = tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot); + // If the rematerializable def is a load, also try to fold it. + if (isLoadSS || ReMatDefMI->getDesc().canFoldAsLoad()) + Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, + Ops, isLoadSS, LdSlot, VReg); + if (!Folded) { + unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI); + if (ImpUse) { + // Re-matting an instruction with virtual register use. Add the + // register as an implicit use on the use MI and mark the register + // interval as unspillable. + LiveInterval &ImpLi = getInterval(ImpUse); + ImpLi.markNotSpillable(); + MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); + } + } + } + } + // If folding is not possible / failed, then tell the spiller to issue a + // load / rematerialization for us. + if (Folded) + nI.removeRange(index.getLoadIndex(), index.getDefIndex()); + else + vrm.addRestorePoint(VReg, MI); + } + Id = RestoreMBBs.find_next(Id); + } + + // Finalize intervals: add kills, finalize spill weights, and filter out + // dead intervals. + std::vector RetNewLIs; + for (unsigned i = 0, e = NewLIs.size(); i != e; ++i) { + LiveInterval *LI = NewLIs[i]; + if (!LI->empty()) { + if (!AddedKill.count(LI)) { + LiveRange *LR = &LI->ranges[LI->ranges.size()-1]; + SlotIndex LastUseIdx = LR->end.getBaseIndex(); + MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx); + int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg, false); + assert(UseIdx != -1); + if (!LastUse->isRegTiedToDefOperand(UseIdx)) { + LastUse->getOperand(UseIdx).setIsKill(); + vrm.addKillPoint(LI->reg, LastUseIdx); + } + } + RetNewLIs.push_back(LI); + } + } + + handleSpilledImpDefs(li, vrm, rc, RetNewLIs); + normalizeSpillWeights(RetNewLIs); + return RetNewLIs; +} + +/// hasAllocatableSuperReg - Return true if the specified physical register has +/// any super register that's allocatable. +bool LiveIntervals::hasAllocatableSuperReg(unsigned Reg) const { + for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) + if (allocatableRegs_[*AS] && hasInterval(*AS)) + return true; + return false; +} + +/// getRepresentativeReg - Find the largest super register of the specified +/// physical register. +unsigned LiveIntervals::getRepresentativeReg(unsigned Reg) const { + // Find the largest super-register that is allocatable. + unsigned BestReg = Reg; + for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) { + unsigned SuperReg = *AS; + if (!hasAllocatableSuperReg(SuperReg) && hasInterval(SuperReg)) { + BestReg = SuperReg; + break; + } + } + return BestReg; +} + +/// getNumConflictsWithPhysReg - Return the number of uses and defs of the +/// specified interval that conflicts with the specified physical register. +unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li, + unsigned PhysReg) const { + unsigned NumConflicts = 0; + const LiveInterval &pli = getInterval(getRepresentativeReg(PhysReg)); + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + MachineInstr *MI = O.getParent(); + if (MI->isDebugValue()) + continue; + SlotIndex Index = getInstructionIndex(MI); + if (pli.liveAt(Index)) + ++NumConflicts; + } + return NumConflicts; +} + +/// spillPhysRegAroundRegDefsUses - Spill the specified physical register +/// around all defs and uses of the specified interval. Return true if it +/// was able to cut its interval. +bool LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li, + unsigned PhysReg, VirtRegMap &vrm) { + unsigned SpillReg = getRepresentativeReg(PhysReg); + + DEBUG(dbgs() << "spillPhysRegAroundRegDefsUses " << tri_->getName(PhysReg) + << " represented by " << tri_->getName(SpillReg) << '\n'); + + for (const unsigned *AS = tri_->getAliasSet(PhysReg); *AS; ++AS) + // If there are registers which alias PhysReg, but which are not a + // sub-register of the chosen representative super register. Assert + // since we can't handle it yet. + assert(*AS == SpillReg || !allocatableRegs_[*AS] || !hasInterval(*AS) || + tri_->isSuperRegister(*AS, SpillReg)); + + bool Cut = false; + SmallVector PRegs; + if (hasInterval(SpillReg)) + PRegs.push_back(SpillReg); + for (const unsigned *SR = tri_->getSubRegisters(SpillReg); *SR; ++SR) + if (hasInterval(*SR)) + PRegs.push_back(*SR); + + DEBUG({ + dbgs() << "Trying to spill:"; + for (unsigned i = 0, e = PRegs.size(); i != e; ++i) + dbgs() << ' ' << tri_->getName(PRegs[i]); + dbgs() << '\n'; + }); + + SmallPtrSet SeenMIs; + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg), + E = mri_->reg_end(); I != E; ++I) { + MachineOperand &O = I.getOperand(); + MachineInstr *MI = O.getParent(); + if (MI->isDebugValue() || SeenMIs.count(MI)) + continue; + SeenMIs.insert(MI); + SlotIndex Index = getInstructionIndex(MI); + bool LiveReg = false; + for (unsigned i = 0, e = PRegs.size(); i != e; ++i) { + unsigned PReg = PRegs[i]; + LiveInterval &pli = getInterval(PReg); + if (!pli.liveAt(Index)) + continue; + LiveReg = true; + SlotIndex StartIdx = Index.getLoadIndex(); + SlotIndex EndIdx = Index.getNextIndex().getBaseIndex(); + if (!pli.isInOneLiveRange(StartIdx, EndIdx)) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Ran out of registers during register allocation!"; + if (MI->isInlineAsm()) { + Msg << "\nPlease check your inline asm statement for invalid " + << "constraints:\n"; + MI->print(Msg, tm_); + } + report_fatal_error(Msg.str()); + } + pli.removeRange(StartIdx, EndIdx); + LiveReg = true; + } + if (!LiveReg) + continue; + DEBUG(dbgs() << "Emergency spill around " << Index << '\t' << *MI); + vrm.addEmergencySpill(SpillReg, MI); + Cut = true; + } + return Cut; +} + +LiveRange LiveIntervals::addLiveRangeToEndOfBlock(unsigned reg, + MachineInstr* startInst) { + LiveInterval& Interval = getOrCreateInterval(reg); + VNInfo* VN = Interval.getNextValue( + SlotIndex(getInstructionIndex(startInst).getDefIndex()), + startInst, getVNInfoAllocator()); + VN->setHasPHIKill(true); + LiveRange LR( + SlotIndex(getInstructionIndex(startInst).getDefIndex()), + getMBBEndIdx(startInst->getParent()), VN); + Interval.addRange(LR); + + return LR; +} + diff --git a/final/lib/CodeGen/LiveIntervalUnion.cpp b/final/lib/CodeGen/LiveIntervalUnion.cpp new file mode 100644 index 00000000000..205f28a0d65 --- /dev/null +++ b/final/lib/CodeGen/LiveIntervalUnion.cpp @@ -0,0 +1,315 @@ +//===-- LiveIntervalUnion.cpp - Live interval union data structure --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LiveIntervalUnion represents a coalesced set of live intervals. This may be +// used during coalescing to represent a congruence class, or during register +// allocation to model liveness of a physical register. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "LiveIntervalUnion.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/CodeGen/MachineLoopRanges.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + + +// Merge a LiveInterval's segments. Guarantee no overlaps. +void LiveIntervalUnion::unify(LiveInterval &VirtReg) { + if (VirtReg.empty()) + return; + ++Tag; + + // Insert each of the virtual register's live segments into the map. + LiveInterval::iterator RegPos = VirtReg.begin(); + LiveInterval::iterator RegEnd = VirtReg.end(); + SegmentIter SegPos = Segments.find(RegPos->start); + + for (;;) { + SegPos.insert(RegPos->start, RegPos->end, &VirtReg); + if (++RegPos == RegEnd) + return; + SegPos.advanceTo(RegPos->start); + } +} + +// Remove a live virtual register's segments from this union. +void LiveIntervalUnion::extract(LiveInterval &VirtReg) { + if (VirtReg.empty()) + return; + ++Tag; + + // Remove each of the virtual register's live segments from the map. + LiveInterval::iterator RegPos = VirtReg.begin(); + LiveInterval::iterator RegEnd = VirtReg.end(); + SegmentIter SegPos = Segments.find(RegPos->start); + + for (;;) { + assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval"); + SegPos.erase(); + if (!SegPos.valid()) + return; + + // Skip all segments that may have been coalesced. + RegPos = VirtReg.advanceTo(RegPos, SegPos.start()); + if (RegPos == RegEnd) + return; + + SegPos.advanceTo(RegPos->start); + } +} + +void +LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { + OS << "LIU " << PrintReg(RepReg, TRI); + if (empty()) { + OS << " empty\n"; + return; + } + for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) { + OS << " [" << SI.start() << ' ' << SI.stop() << "):" + << PrintReg(SI.value()->reg, TRI); + } + OS << '\n'; +} + +void LiveIntervalUnion::InterferenceResult::print(raw_ostream &OS, + const TargetRegisterInfo *TRI) const { + OS << '[' << start() << ';' << stop() << "):" + << PrintReg(interference()->reg, TRI); +} + +void LiveIntervalUnion::Query::print(raw_ostream &OS, + const TargetRegisterInfo *TRI) { + OS << "Interferences with "; + LiveUnion->print(OS, TRI); + InterferenceResult IR = firstInterference(); + while (isInterference(IR)) { + OS << " "; + IR.print(OS, TRI); + OS << '\n'; + nextInterference(IR); + } +} + +#ifndef NDEBUG +// Verify the live intervals in this union and add them to the visited set. +void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) { + for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI) + VisitedVRegs.set(SI.value()->reg); +} +#endif //!NDEBUG + +// Private interface accessed by Query. +// +// Find a pair of segments that intersect, one in the live virtual register +// (LiveInterval), and the other in this LiveIntervalUnion. The caller (Query) +// is responsible for advancing the LiveIntervalUnion segments to find a +// "notable" intersection, which requires query-specific logic. +// +// This design assumes only a fast mechanism for intersecting a single live +// virtual register segment with a set of LiveIntervalUnion segments. This may +// be ok since most virtual registers have very few segments. If we had a data +// structure that optimizd MxN intersection of segments, then we would bypass +// the loop that advances within the LiveInterval. +// +// If no intersection exists, set VirtRegI = VirtRegEnd, and set SI to the first +// segment whose start point is greater than LiveInterval's end point. +// +// Assumes that segments are sorted by start position in both +// LiveInterval and LiveSegments. +void LiveIntervalUnion::Query::findIntersection(InterferenceResult &IR) const { + // Search until reaching the end of the LiveUnion segments. + LiveInterval::iterator VirtRegEnd = VirtReg->end(); + if (IR.VirtRegI == VirtRegEnd) + return; + while (IR.LiveUnionI.valid()) { + // Slowly advance the live virtual reg iterator until we surpass the next + // segment in LiveUnion. + // + // Note: If this is ever used for coalescing of fixed registers and we have + // a live vreg with thousands of segments, then change this code to use + // upperBound instead. + IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); + if (IR.VirtRegI == VirtRegEnd) + break; // Retain current (nonoverlapping) LiveUnionI + + // VirtRegI may have advanced far beyond LiveUnionI, catch up. + IR.LiveUnionI.advanceTo(IR.VirtRegI->start); + + // Check if no LiveUnionI exists with VirtRegI->Start < LiveUnionI.end + if (!IR.LiveUnionI.valid()) + break; + if (IR.LiveUnionI.start() < IR.VirtRegI->end) { + assert(overlap(*IR.VirtRegI, IR.LiveUnionI) && + "upperBound postcondition"); + break; + } + } + if (!IR.LiveUnionI.valid()) + IR.VirtRegI = VirtRegEnd; +} + +// Find the first intersection, and cache interference info +// (retain segment iterators into both VirtReg and LiveUnion). +const LiveIntervalUnion::InterferenceResult & +LiveIntervalUnion::Query::firstInterference() { + if (CheckedFirstInterference) + return FirstInterference; + CheckedFirstInterference = true; + InterferenceResult &IR = FirstInterference; + + // Quickly skip interference check for empty sets. + if (VirtReg->empty() || LiveUnion->empty()) { + IR.VirtRegI = VirtReg->end(); + } else if (VirtReg->beginIndex() < LiveUnion->startIndex()) { + // VirtReg starts first, perform double binary search. + IR.VirtRegI = VirtReg->find(LiveUnion->startIndex()); + if (IR.VirtRegI != VirtReg->end()) + IR.LiveUnionI = LiveUnion->find(IR.VirtRegI->start); + } else { + // LiveUnion starts first, perform double binary search. + IR.LiveUnionI = LiveUnion->find(VirtReg->beginIndex()); + if (IR.LiveUnionI.valid()) + IR.VirtRegI = VirtReg->find(IR.LiveUnionI.start()); + else + IR.VirtRegI = VirtReg->end(); + } + findIntersection(FirstInterference); + assert((IR.VirtRegI == VirtReg->end() || IR.LiveUnionI.valid()) + && "Uninitialized iterator"); + return FirstInterference; +} + +// Treat the result as an iterator and advance to the next interfering pair +// of segments. This is a plain iterator with no filter. +bool LiveIntervalUnion::Query::nextInterference(InterferenceResult &IR) const { + assert(isInterference(IR) && "iteration past end of interferences"); + + // Advance either the VirtReg or LiveUnion segment to ensure that we visit all + // unique overlapping pairs. + if (IR.VirtRegI->end < IR.LiveUnionI.stop()) { + if (++IR.VirtRegI == VirtReg->end()) + return false; + } + else { + if (!(++IR.LiveUnionI).valid()) { + IR.VirtRegI = VirtReg->end(); + return false; + } + } + // Short-circuit findIntersection() if possible. + if (overlap(*IR.VirtRegI, IR.LiveUnionI)) + return true; + + // Find the next intersection. + findIntersection(IR); + return isInterference(IR); +} + +// Scan the vector of interfering virtual registers in this union. Assume it's +// quite small. +bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const { + SmallVectorImpl::const_iterator I = + std::find(InterferingVRegs.begin(), InterferingVRegs.end(), VirtReg); + return I != InterferingVRegs.end(); +} + +// Count the number of virtual registers in this union that interfere with this +// query's live virtual register. +// +// The number of times that we either advance IR.VirtRegI or call +// LiveUnion.upperBound() will be no more than the number of holes in +// VirtReg. So each invocation of collectInterferingVRegs() takes +// time proportional to |VirtReg Holes| * time(LiveUnion.upperBound()). +// +// For comments on how to speed it up, see Query::findIntersection(). +unsigned LiveIntervalUnion::Query:: +collectInterferingVRegs(unsigned MaxInterferingRegs) { + InterferenceResult IR = firstInterference(); + LiveInterval::iterator VirtRegEnd = VirtReg->end(); + LiveInterval *RecentInterferingVReg = NULL; + if (IR.VirtRegI != VirtRegEnd) while (IR.LiveUnionI.valid()) { + // Advance the union's iterator to reach an unseen interfering vreg. + do { + if (IR.LiveUnionI.value() == RecentInterferingVReg) + continue; + + if (!isSeenInterference(IR.LiveUnionI.value())) + break; + + // Cache the most recent interfering vreg to bypass isSeenInterference. + RecentInterferingVReg = IR.LiveUnionI.value(); + + } while ((++IR.LiveUnionI).valid()); + if (!IR.LiveUnionI.valid()) + break; + + // Advance the VirtReg iterator until surpassing the next segment in + // LiveUnion. + IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start()); + if (IR.VirtRegI == VirtRegEnd) + break; + + // Check for intersection with the union's segment. + if (overlap(*IR.VirtRegI, IR.LiveUnionI)) { + + if (!IR.LiveUnionI.value()->isSpillable()) + SeenUnspillableVReg = true; + + if (InterferingVRegs.size() == MaxInterferingRegs) + // Leave SeenAllInterferences set to false to indicate that at least one + // interference exists beyond those we collected. + return MaxInterferingRegs; + + InterferingVRegs.push_back(IR.LiveUnionI.value()); + + // Cache the most recent interfering vreg to bypass isSeenInterference. + RecentInterferingVReg = IR.LiveUnionI.value(); + ++IR.LiveUnionI; + continue; + } + // VirtRegI may have advanced far beyond LiveUnionI, + // do a fast intersection test to "catch up" + IR.LiveUnionI.advanceTo(IR.VirtRegI->start); + } + SeenAllInterferences = true; + return InterferingVRegs.size(); +} + +bool LiveIntervalUnion::Query::checkLoopInterference(MachineLoopRange *Loop) { + // VirtReg is likely live throughout the loop, so start by checking LIU-Loop + // overlaps. + IntervalMapOverlaps + Overlaps(LiveUnion->getMap(), Loop->getMap()); + if (!Overlaps.valid()) + return false; + + // The loop is overlapping an LIU assignment. Check VirtReg as well. + LiveInterval::iterator VRI = VirtReg->find(Overlaps.start()); + + for (;;) { + if (VRI == VirtReg->end()) + return false; + if (VRI->start < Overlaps.stop()) + return true; + + Overlaps.advanceTo(VRI->start); + if (!Overlaps.valid()) + return false; + if (Overlaps.start() < VRI->end) + return true; + + VRI = VirtReg->advanceTo(VRI, Overlaps.start()); + } +} diff --git a/final/lib/CodeGen/LiveIntervalUnion.h b/final/lib/CodeGen/LiveIntervalUnion.h new file mode 100644 index 00000000000..6f9c5f4455e --- /dev/null +++ b/final/lib/CodeGen/LiveIntervalUnion.h @@ -0,0 +1,258 @@ +//===-- LiveIntervalUnion.h - Live interval union data struct --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LiveIntervalUnion is a union of live segments across multiple live virtual +// registers. This may be used during coalescing to represent a congruence +// class, or during register allocation to model liveness of a physical +// register. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVALUNION +#define LLVM_CODEGEN_LIVEINTERVALUNION + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/CodeGen/LiveInterval.h" + +#include + +namespace llvm { + +class MachineLoopRange; +class TargetRegisterInfo; + +#ifndef NDEBUG +// forward declaration +template class SparseBitVector; +typedef SparseBitVector<128> LiveVirtRegBitSet; +#endif + +/// Compare a live virtual register segment to a LiveIntervalUnion segment. +inline bool +overlap(const LiveRange &VRSeg, + const IntervalMap::const_iterator &LUSeg) { + return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end; +} + +/// Union of live intervals that are strong candidates for coalescing into a +/// single register (either physical or virtual depending on the context). We +/// expect the constituent live intervals to be disjoint, although we may +/// eventually make exceptions to handle value-based interference. +class LiveIntervalUnion { + // A set of live virtual register segments that supports fast insertion, + // intersection, and removal. + // Mapping SlotIndex intervals to virtual register numbers. + typedef IntervalMap LiveSegments; + +public: + // SegmentIter can advance to the next segment ordered by starting position + // which may belong to a different live virtual register. We also must be able + // to reach the current segment's containing virtual register. + typedef LiveSegments::iterator SegmentIter; + + // LiveIntervalUnions share an external allocator. + typedef LiveSegments::Allocator Allocator; + + class InterferenceResult; + class Query; + +private: + const unsigned RepReg; // representative register number + unsigned Tag; // unique tag for current contents. + LiveSegments Segments; // union of virtual reg segments + +public: + LiveIntervalUnion(unsigned r, Allocator &a) : RepReg(r), Tag(0), Segments(a) + {} + + // Iterate over all segments in the union of live virtual registers ordered + // by their starting position. + SegmentIter begin() { return Segments.begin(); } + SegmentIter end() { return Segments.end(); } + SegmentIter find(SlotIndex x) { return Segments.find(x); } + bool empty() const { return Segments.empty(); } + SlotIndex startIndex() const { return Segments.start(); } + + // Provide public access to the underlying map to allow overlap iteration. + typedef LiveSegments Map; + const Map &getMap() { return Segments; } + + /// getTag - Return an opaque tag representing the current state of the union. + unsigned getTag() const { return Tag; } + + /// changedSince - Return true if the union change since getTag returned tag. + bool changedSince(unsigned tag) const { return tag != Tag; } + + // Add a live virtual register to this union and merge its segments. + void unify(LiveInterval &VirtReg); + + // Remove a live virtual register's segments from this union. + void extract(LiveInterval &VirtReg); + + // Print union, using TRI to translate register names + void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; + +#ifndef NDEBUG + // Verify the live intervals in this union and add them to the visited set. + void verify(LiveVirtRegBitSet& VisitedVRegs); +#endif + + /// Cache a single interference test result in the form of two intersecting + /// segments. This allows efficiently iterating over the interferences. The + /// iteration logic is handled by LiveIntervalUnion::Query which may + /// filter interferences depending on the type of query. + class InterferenceResult { + friend class Query; + + LiveInterval::iterator VirtRegI; // current position in VirtReg + SegmentIter LiveUnionI; // current position in LiveUnion + + // Internal ctor. + InterferenceResult(LiveInterval::iterator VRegI, SegmentIter UnionI) + : VirtRegI(VRegI), LiveUnionI(UnionI) {} + + public: + // Public default ctor. + InterferenceResult(): VirtRegI(), LiveUnionI() {} + + /// start - Return the start of the current overlap. + SlotIndex start() const { + return std::max(VirtRegI->start, LiveUnionI.start()); + } + + /// stop - Return the end of the current overlap. + SlotIndex stop() const { + return std::min(VirtRegI->end, LiveUnionI.stop()); + } + + /// interference - Return the register that is interfering here. + LiveInterval *interference() const { return LiveUnionI.value(); } + + // Note: this interface provides raw access to the iterators because the + // result has no way to tell if it's valid to dereference them. + + // Access the VirtReg segment. + LiveInterval::iterator virtRegPos() const { return VirtRegI; } + + // Access the LiveUnion segment. + const SegmentIter &liveUnionPos() const { return LiveUnionI; } + + bool operator==(const InterferenceResult &IR) const { + return VirtRegI == IR.VirtRegI && LiveUnionI == IR.LiveUnionI; + } + bool operator!=(const InterferenceResult &IR) const { + return !operator==(IR); + } + + void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; + }; + + /// Query interferences between a single live virtual register and a live + /// interval union. + class Query { + LiveIntervalUnion *LiveUnion; + LiveInterval *VirtReg; + InterferenceResult FirstInterference; + SmallVector InterferingVRegs; + bool CheckedFirstInterference; + bool SeenAllInterferences; + bool SeenUnspillableVReg; + unsigned Tag; + + public: + Query(): LiveUnion(), VirtReg() {} + + Query(LiveInterval *VReg, LiveIntervalUnion *LIU): + LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false), + SeenAllInterferences(false), SeenUnspillableVReg(false) + {} + + void clear() { + LiveUnion = NULL; + VirtReg = NULL; + InterferingVRegs.clear(); + CheckedFirstInterference = false; + SeenAllInterferences = false; + SeenUnspillableVReg = false; + Tag = 0; + } + + void init(LiveInterval *VReg, LiveIntervalUnion *LIU) { + assert(VReg && LIU && "Invalid arguments"); + if (VirtReg == VReg && LiveUnion == LIU && !LIU->changedSince(Tag)) { + // Retain cached results, e.g. firstInterference. + return; + } + clear(); + LiveUnion = LIU; + VirtReg = VReg; + Tag = LIU->getTag(); + } + + LiveInterval &virtReg() const { + assert(VirtReg && "uninitialized"); + return *VirtReg; + } + + bool isInterference(const InterferenceResult &IR) const { + if (IR.VirtRegI != VirtReg->end()) { + assert(overlap(*IR.VirtRegI, IR.LiveUnionI) && + "invalid segment iterators"); + return true; + } + return false; + } + + // Does this live virtual register interfere with the union? + bool checkInterference() { return isInterference(firstInterference()); } + + // Get the first pair of interfering segments, or a noninterfering result. + // This initializes the firstInterference_ cache. + const InterferenceResult &firstInterference(); + + // Treat the result as an iterator and advance to the next interfering pair + // of segments. Visiting each unique interfering pairs means that the same + // VirtReg or LiveUnion segment may be visited multiple times. + bool nextInterference(InterferenceResult &IR) const; + + // Count the virtual registers in this union that interfere with this + // query's live virtual register, up to maxInterferingRegs. + unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX); + + // Was this virtual register visited during collectInterferingVRegs? + bool isSeenInterference(LiveInterval *VReg) const; + + // Did collectInterferingVRegs collect all interferences? + bool seenAllInterferences() const { return SeenAllInterferences; } + + // Did collectInterferingVRegs encounter an unspillable vreg? + bool seenUnspillableVReg() const { return SeenUnspillableVReg; } + + // Vector generated by collectInterferingVRegs. + const SmallVectorImpl &interferingVRegs() const { + return InterferingVRegs; + } + + /// checkLoopInterference - Return true if there is interference overlapping + /// Loop. + bool checkLoopInterference(MachineLoopRange*); + + void print(raw_ostream &OS, const TargetRegisterInfo *TRI); + private: + Query(const Query&); // DO NOT IMPLEMENT + void operator=(const Query&); // DO NOT IMPLEMENT + + // Private interface for queries + void findIntersection(InterferenceResult &IR) const; + }; +}; + +} // end namespace llvm + +#endif // !defined(LLVM_CODEGEN_LIVEINTERVALUNION) diff --git a/final/lib/CodeGen/LiveRangeEdit.cpp b/final/lib/CodeGen/LiveRangeEdit.cpp new file mode 100644 index 00000000000..7de1284cb97 --- /dev/null +++ b/final/lib/CodeGen/LiveRangeEdit.cpp @@ -0,0 +1,130 @@ +//===--- LiveRangeEdit.cpp - Basic tools for editing a register live range --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The LiveRangeEdit class represents changes done to a virtual register when it +// is spilled or split. +//===----------------------------------------------------------------------===// + +#include "LiveRangeEdit.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" + +using namespace llvm; + +LiveInterval &LiveRangeEdit::create(MachineRegisterInfo &mri, + LiveIntervals &lis, + VirtRegMap &vrm) { + const TargetRegisterClass *RC = mri.getRegClass(getReg()); + unsigned VReg = mri.createVirtualRegister(RC); + vrm.grow(); + vrm.setIsSplitFromReg(VReg, vrm.getOriginal(getReg())); + LiveInterval &li = lis.getOrCreateInterval(VReg); + newRegs_.push_back(&li); + return li; +} + +void LiveRangeEdit::scanRemattable(LiveIntervals &lis, + const TargetInstrInfo &tii, + AliasAnalysis *aa) { + for (LiveInterval::vni_iterator I = parent_.vni_begin(), + E = parent_.vni_end(); I != E; ++I) { + VNInfo *VNI = *I; + if (VNI->isUnused()) + continue; + MachineInstr *DefMI = lis.getInstructionFromIndex(VNI->def); + if (!DefMI) + continue; + if (tii.isTriviallyReMaterializable(DefMI, aa)) + remattable_.insert(VNI); + } + scannedRemattable_ = true; +} + +bool LiveRangeEdit::anyRematerializable(LiveIntervals &lis, + const TargetInstrInfo &tii, + AliasAnalysis *aa) { + if (!scannedRemattable_) + scanRemattable(lis, tii, aa); + return !remattable_.empty(); +} + +/// allUsesAvailableAt - Return true if all registers used by OrigMI at +/// OrigIdx are also available with the same value at UseIdx. +bool LiveRangeEdit::allUsesAvailableAt(const MachineInstr *OrigMI, + SlotIndex OrigIdx, + SlotIndex UseIdx, + LiveIntervals &lis) { + OrigIdx = OrigIdx.getUseIndex(); + UseIdx = UseIdx.getUseIndex(); + for (unsigned i = 0, e = OrigMI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = OrigMI->getOperand(i); + if (!MO.isReg() || !MO.getReg() || MO.getReg() == getReg()) + continue; + // Reserved registers are OK. + if (MO.isUndef() || !lis.hasInterval(MO.getReg())) + continue; + // We don't want to move any defs. + if (MO.isDef()) + return false; + // We cannot depend on virtual registers in uselessRegs_. + if (uselessRegs_) + for (unsigned ui = 0, ue = uselessRegs_->size(); ui != ue; ++ui) + if ((*uselessRegs_)[ui]->reg == MO.getReg()) + return false; + + LiveInterval &li = lis.getInterval(MO.getReg()); + const VNInfo *OVNI = li.getVNInfoAt(OrigIdx); + if (!OVNI) + continue; + if (OVNI != li.getVNInfoAt(UseIdx)) + return false; + } + return true; +} + +bool LiveRangeEdit::canRematerializeAt(Remat &RM, + SlotIndex UseIdx, + bool cheapAsAMove, + LiveIntervals &lis) { + assert(scannedRemattable_ && "Call anyRematerializable first"); + + // Use scanRemattable info. + if (!remattable_.count(RM.ParentVNI)) + return false; + + // No defining instruction. + RM.OrigMI = lis.getInstructionFromIndex(RM.ParentVNI->def); + assert(RM.OrigMI && "Defining instruction for remattable value disappeared"); + + // If only cheap remats were requested, bail out early. + if (cheapAsAMove && !RM.OrigMI->getDesc().isAsCheapAsAMove()) + return false; + + // Verify that all used registers are available with the same values. + if (!allUsesAvailableAt(RM.OrigMI, RM.ParentVNI->def, UseIdx, lis)) + return false; + + return true; +} + +SlotIndex LiveRangeEdit::rematerializeAt(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, + const Remat &RM, + LiveIntervals &lis, + const TargetInstrInfo &tii, + const TargetRegisterInfo &tri) { + assert(RM.OrigMI && "Invalid remat"); + tii.reMaterialize(MBB, MI, DestReg, 0, RM.OrigMI, tri); + rematted_.insert(RM.ParentVNI); + return lis.InsertMachineInstrInMaps(--MI).getDefIndex(); +} + diff --git a/final/lib/CodeGen/LiveRangeEdit.h b/final/lib/CodeGen/LiveRangeEdit.h new file mode 100644 index 00000000000..95181305600 --- /dev/null +++ b/final/lib/CodeGen/LiveRangeEdit.h @@ -0,0 +1,135 @@ +//===---- LiveRangeEdit.h - Basic tools for split and spill -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The LiveRangeEdit class represents changes done to a virtual register when it +// is spilled or split. +// +// The parent register is never changed. Instead, a number of new virtual +// registers are created and added to the newRegs vector. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVERANGEEDIT_H +#define LLVM_CODEGEN_LIVERANGEEDIT_H + +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace llvm { + +class AliasAnalysis; +class LiveIntervals; +class MachineRegisterInfo; +class VirtRegMap; + +class LiveRangeEdit { + LiveInterval &parent_; + SmallVectorImpl &newRegs_; + const SmallVectorImpl *uselessRegs_; + + /// firstNew_ - Index of the first register added to newRegs_. + const unsigned firstNew_; + + /// scannedRemattable_ - true when remattable values have been identified. + bool scannedRemattable_; + + /// remattable_ - Values defined by remattable instructions as identified by + /// tii.isTriviallyReMaterializable(). + SmallPtrSet remattable_; + + /// rematted_ - Values that were actually rematted, and so need to have their + /// live range trimmed or entirely removed. + SmallPtrSet rematted_; + + /// scanRemattable - Identify the parent_ values that may rematerialize. + void scanRemattable(LiveIntervals &lis, + const TargetInstrInfo &tii, + AliasAnalysis *aa); + + /// allUsesAvailableAt - Return true if all registers used by OrigMI at + /// OrigIdx are also available with the same value at UseIdx. + bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx, + SlotIndex UseIdx, LiveIntervals &lis); + +public: + /// Create a LiveRangeEdit for breaking down parent into smaller pieces. + /// @param parent The register being spilled or split. + /// @param newRegs List to receive any new registers created. This needn't be + /// empty initially, any existing registers are ignored. + /// @param uselessRegs List of registers that can't be used when + /// rematerializing values because they are about to be removed. + LiveRangeEdit(LiveInterval &parent, + SmallVectorImpl &newRegs, + const SmallVectorImpl *uselessRegs = 0) + : parent_(parent), newRegs_(newRegs), uselessRegs_(uselessRegs), + firstNew_(newRegs.size()), scannedRemattable_(false) {} + + LiveInterval &getParent() const { return parent_; } + unsigned getReg() const { return parent_.reg; } + + /// Iterator for accessing the new registers added by this edit. + typedef SmallVectorImpl::const_iterator iterator; + iterator begin() const { return newRegs_.begin()+firstNew_; } + iterator end() const { return newRegs_.end(); } + unsigned size() const { return newRegs_.size()-firstNew_; } + bool empty() const { return size() == 0; } + LiveInterval *get(unsigned idx) const { return newRegs_[idx+firstNew_]; } + + /// create - Create a new register with the same class and stack slot as + /// parent. + LiveInterval &create(MachineRegisterInfo&, LiveIntervals&, VirtRegMap&); + + /// anyRematerializable - Return true if any parent values may be + /// rematerializable. + /// This function must be called before any rematerialization is attempted. + bool anyRematerializable(LiveIntervals&, const TargetInstrInfo&, + AliasAnalysis*); + + /// Remat - Information needed to rematerialize at a specific location. + struct Remat { + VNInfo *ParentVNI; // parent_'s value at the remat location. + MachineInstr *OrigMI; // Instruction defining ParentVNI. + explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(0) {} + }; + + /// canRematerializeAt - Determine if ParentVNI can be rematerialized at + /// UseIdx. It is assumed that parent_.getVNINfoAt(UseIdx) == ParentVNI. + /// When cheapAsAMove is set, only cheap remats are allowed. + bool canRematerializeAt(Remat &RM, + SlotIndex UseIdx, + bool cheapAsAMove, + LiveIntervals &lis); + + /// rematerializeAt - Rematerialize RM.ParentVNI into DestReg by inserting an + /// instruction into MBB before MI. The new instruction is mapped, but + /// liveness is not updated. + /// Return the SlotIndex of the new instruction. + SlotIndex rematerializeAt(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, + const Remat &RM, + LiveIntervals&, + const TargetInstrInfo&, + const TargetRegisterInfo&); + + /// markRematerialized - explicitly mark a value as rematerialized after doing + /// it manually. + void markRematerialized(const VNInfo *ParentVNI) { + rematted_.insert(ParentVNI); + } + + /// didRematerialize - Return true if ParentVNI was rematerialized anywhere. + bool didRematerialize(const VNInfo *ParentVNI) const { + return rematted_.count(ParentVNI); + } +}; + +} + +#endif diff --git a/final/lib/CodeGen/LiveStackAnalysis.cpp b/final/lib/CodeGen/LiveStackAnalysis.cpp new file mode 100644 index 00000000000..c75196a4721 --- /dev/null +++ b/final/lib/CodeGen/LiveStackAnalysis.cpp @@ -0,0 +1,82 @@ +//===-- LiveStackAnalysis.cpp - Live Stack Slot Analysis ------------------===// +// +// 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 live stack slot analysis pass. It is analogous to +// live interval analysis except it's analyzing liveness of stack slots rather +// than registers. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "livestacks" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +char LiveStacks::ID = 0; +INITIALIZE_PASS(LiveStacks, "livestacks", + "Live Stack Slot Analysis", false, false) + +char &llvm::LiveStacksID = LiveStacks::ID; + +void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addPreserved(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void LiveStacks::releaseMemory() { + // Release VNInfo memory regions, VNInfo objects don't need to be dtor'd. + VNInfoAllocator.Reset(); + S2IMap.clear(); + S2RCMap.clear(); +} + +bool LiveStacks::runOnMachineFunction(MachineFunction &) { + // FIXME: No analysis is being done right now. We are relying on the + // register allocators to provide the information. + return false; +} + +LiveInterval & +LiveStacks::getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { + assert(Slot >= 0 && "Spill slot indice must be >= 0"); + SS2IntervalMap::iterator I = S2IMap.find(Slot); + if (I == S2IMap.end()) { + I = S2IMap.insert(I, std::make_pair(Slot, + LiveInterval(TargetRegisterInfo::index2StackSlot(Slot), 0.0F))); + S2RCMap.insert(std::make_pair(Slot, RC)); + } else { + // Use the largest common subclass register class. + const TargetRegisterClass *OldRC = S2RCMap[Slot]; + S2RCMap[Slot] = getCommonSubClass(OldRC, RC); + } + return I->second; +} + +/// print - Implement the dump method. +void LiveStacks::print(raw_ostream &OS, const Module*) const { + + OS << "********** INTERVALS **********\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) { + I->second.print(OS); + int Slot = I->first; + const TargetRegisterClass *RC = getIntervalRegClass(Slot); + if (RC) + OS << " [" << RC->getName() << "]\n"; + else + OS << " [Unknown]\n"; + } +} diff --git a/final/lib/CodeGen/LiveVariables.cpp b/final/lib/CodeGen/LiveVariables.cpp new file mode 100644 index 00000000000..dd43ef2530c --- /dev/null +++ b/final/lib/CodeGen/LiveVariables.cpp @@ -0,0 +1,772 @@ +//===-- LiveVariables.cpp - Live Variable Analysis for Machine Code -------===// +// +// 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 LiveVariable analysis pass. For each machine +// instruction in the function, this pass calculates the set of registers that +// are immediately dead after the instruction (i.e., the instruction calculates +// the value, but it is never used) and the set of registers that are used by +// the instruction, but are never used after the instruction (i.e., they are +// killed). +// +// This class computes live variables using are sparse implementation based on +// the machine code SSA form. This class computes live variable information for +// each virtual and _register allocatable_ physical register in a function. It +// uses the dominance properties of SSA form to efficiently compute live +// variables for virtual registers, and assumes that physical registers are only +// live within a single basic block (allowing it to do a single local analysis +// to resolve physical register lifetimes in each basic block). If a physical +// register is not register allocatable, it is not tracked. This is useful for +// things like the stack pointer and condition codes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +char LiveVariables::ID = 0; +INITIALIZE_PASS_BEGIN(LiveVariables, "livevars", + "Live Variable Analysis", false, false) +INITIALIZE_PASS_DEPENDENCY(UnreachableMachineBlockElim) +INITIALIZE_PASS_END(LiveVariables, "livevars", + "Live Variable Analysis", false, false) + + +void LiveVariables::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequiredID(UnreachableMachineBlockElimID); + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +MachineInstr * +LiveVariables::VarInfo::findKill(const MachineBasicBlock *MBB) const { + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + if (Kills[i]->getParent() == MBB) + return Kills[i]; + return NULL; +} + +void LiveVariables::VarInfo::dump() const { + dbgs() << " Alive in blocks: "; + for (SparseBitVector<>::iterator I = AliveBlocks.begin(), + E = AliveBlocks.end(); I != E; ++I) + dbgs() << *I << ", "; + dbgs() << "\n Killed by:"; + if (Kills.empty()) + dbgs() << " No instructions.\n"; + else { + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + dbgs() << "\n #" << i << ": " << *Kills[i]; + dbgs() << "\n"; + } +} + +/// getVarInfo - Get (possibly creating) a VarInfo object for the given vreg. +LiveVariables::VarInfo &LiveVariables::getVarInfo(unsigned RegIdx) { + assert(TargetRegisterInfo::isVirtualRegister(RegIdx) && + "getVarInfo: not a virtual register!"); + VirtRegInfo.grow(RegIdx); + return VirtRegInfo[RegIdx]; +} + +void LiveVariables::MarkVirtRegAliveInBlock(VarInfo& VRInfo, + MachineBasicBlock *DefBlock, + MachineBasicBlock *MBB, + std::vector &WorkList) { + unsigned BBNum = MBB->getNumber(); + + // Check to see if this basic block is one of the killing blocks. If so, + // remove it. + for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i) + if (VRInfo.Kills[i]->getParent() == MBB) { + VRInfo.Kills.erase(VRInfo.Kills.begin()+i); // Erase entry + break; + } + + if (MBB == DefBlock) return; // Terminate recursion + + if (VRInfo.AliveBlocks.test(BBNum)) + return; // We already know the block is live + + // Mark the variable known alive in this bb + VRInfo.AliveBlocks.set(BBNum); + + for (MachineBasicBlock::const_pred_reverse_iterator PI = MBB->pred_rbegin(), + E = MBB->pred_rend(); PI != E; ++PI) + WorkList.push_back(*PI); +} + +void LiveVariables::MarkVirtRegAliveInBlock(VarInfo &VRInfo, + MachineBasicBlock *DefBlock, + MachineBasicBlock *MBB) { + std::vector WorkList; + MarkVirtRegAliveInBlock(VRInfo, DefBlock, MBB, WorkList); + + while (!WorkList.empty()) { + MachineBasicBlock *Pred = WorkList.back(); + WorkList.pop_back(); + MarkVirtRegAliveInBlock(VRInfo, DefBlock, Pred, WorkList); + } +} + +void LiveVariables::HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, + MachineInstr *MI) { + assert(MRI->getVRegDef(reg) && "Register use before def!"); + + unsigned BBNum = MBB->getNumber(); + + VarInfo& VRInfo = getVarInfo(reg); + VRInfo.NumUses++; + + // Check to see if this basic block is already a kill block. + if (!VRInfo.Kills.empty() && VRInfo.Kills.back()->getParent() == MBB) { + // Yes, this register is killed in this basic block already. Increase the + // live range by updating the kill instruction. + VRInfo.Kills.back() = MI; + return; + } + +#ifndef NDEBUG + for (unsigned i = 0, e = VRInfo.Kills.size(); i != e; ++i) + assert(VRInfo.Kills[i]->getParent() != MBB && "entry should be at end!"); +#endif + + // This situation can occur: + // + // ,------. + // | | + // | v + // | t2 = phi ... t1 ... + // | | + // | v + // | t1 = ... + // | ... = ... t1 ... + // | | + // `------' + // + // where there is a use in a PHI node that's a predecessor to the defining + // block. We don't want to mark all predecessors as having the value "alive" + // in this case. + if (MBB == MRI->getVRegDef(reg)->getParent()) return; + + // Add a new kill entry for this basic block. If this virtual register is + // already marked as alive in this basic block, that means it is alive in at + // least one of the successor blocks, it's not a kill. + if (!VRInfo.AliveBlocks.test(BBNum)) + VRInfo.Kills.push_back(MI); + + // Update all dominating blocks to mark them as "known live". + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + E = MBB->pred_end(); PI != E; ++PI) + MarkVirtRegAliveInBlock(VRInfo, MRI->getVRegDef(reg)->getParent(), *PI); +} + +void LiveVariables::HandleVirtRegDef(unsigned Reg, MachineInstr *MI) { + VarInfo &VRInfo = getVarInfo(Reg); + + if (VRInfo.AliveBlocks.empty()) + // If vr is not alive in any block, then defaults to dead. + VRInfo.Kills.push_back(MI); +} + +/// FindLastPartialDef - Return the last partial def of the specified register. +/// Also returns the sub-registers that're defined by the instruction. +MachineInstr *LiveVariables::FindLastPartialDef(unsigned Reg, + SmallSet &PartDefRegs) { + unsigned LastDefReg = 0; + unsigned LastDefDist = 0; + MachineInstr *LastDef = NULL; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (!Def) + continue; + unsigned Dist = DistanceMap[Def]; + if (Dist > LastDefDist) { + LastDefReg = SubReg; + LastDef = Def; + LastDefDist = Dist; + } + } + + if (!LastDef) + return 0; + + PartDefRegs.insert(LastDefReg); + for (unsigned i = 0, e = LastDef->getNumOperands(); i != e; ++i) { + MachineOperand &MO = LastDef->getOperand(i); + if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) + continue; + unsigned DefReg = MO.getReg(); + if (TRI->isSubRegister(Reg, DefReg)) { + PartDefRegs.insert(DefReg); + for (const unsigned *SubRegs = TRI->getSubRegisters(DefReg); + unsigned SubReg = *SubRegs; ++SubRegs) + PartDefRegs.insert(SubReg); + } + } + return LastDef; +} + +/// HandlePhysRegUse - Turn previous partial def's into read/mod/writes. Add +/// implicit defs to a machine instruction if there was an earlier def of its +/// super-register. +void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { + MachineInstr *LastDef = PhysRegDef[Reg]; + // If there was a previous use or a "full" def all is well. + if (!LastDef && !PhysRegUse[Reg]) { + // Otherwise, the last sub-register def implicitly defines this register. + // e.g. + // AH = + // AL = ... , + // = AH + // ... + // = EAX + // All of the sub-registers must have been defined before the use of Reg! + SmallSet PartDefRegs; + MachineInstr *LastPartialDef = FindLastPartialDef(Reg, PartDefRegs); + // If LastPartialDef is NULL, it must be using a livein register. + if (LastPartialDef) { + LastPartialDef->addOperand(MachineOperand::CreateReg(Reg, true/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[Reg] = LastPartialDef; + SmallSet Processed; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (Processed.count(SubReg)) + continue; + if (PartDefRegs.count(SubReg)) + continue; + // This part of Reg was defined before the last partial def. It's killed + // here. + LastPartialDef->addOperand(MachineOperand::CreateReg(SubReg, + false/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[SubReg] = LastPartialDef; + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Processed.insert(*SS); + } + } + } + else if (LastDef && !PhysRegUse[Reg] && + !LastDef->findRegisterDefOperand(Reg)) + // Last def defines the super register, add an implicit def of reg. + LastDef->addOperand(MachineOperand::CreateReg(Reg, + true/*IsDef*/, true/*IsImp*/)); + + // Remember this use. + PhysRegUse[Reg] = MI; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + PhysRegUse[SubReg] = MI; +} + +/// FindLastRefOrPartRef - Return the last reference or partial reference of +/// the specified register. +MachineInstr *LiveVariables::FindLastRefOrPartRef(unsigned Reg) { + MachineInstr *LastDef = PhysRegDef[Reg]; + MachineInstr *LastUse = PhysRegUse[Reg]; + if (!LastDef && !LastUse) + return 0; + + MachineInstr *LastRefOrPartRef = LastUse ? LastUse : LastDef; + unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef]; + unsigned LastPartDefDist = 0; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (Def && Def != LastDef) { + // There was a def of this sub-register in between. This is a partial + // def, keep track of the last one. + unsigned Dist = DistanceMap[Def]; + if (Dist > LastPartDefDist) + LastPartDefDist = Dist; + } else if (MachineInstr *Use = PhysRegUse[SubReg]) { + unsigned Dist = DistanceMap[Use]; + if (Dist > LastRefOrPartRefDist) { + LastRefOrPartRefDist = Dist; + LastRefOrPartRef = Use; + } + } + } + + return LastRefOrPartRef; +} + +bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) { + MachineInstr *LastDef = PhysRegDef[Reg]; + MachineInstr *LastUse = PhysRegUse[Reg]; + if (!LastDef && !LastUse) + return false; + + MachineInstr *LastRefOrPartRef = LastUse ? LastUse : LastDef; + unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef]; + // The whole register is used. + // AL = + // AH = + // + // = AX + // = AL, AX + // AX = + // + // Or whole register is defined, but not used at all. + // AX = + // ... + // AX = + // + // Or whole register is defined, but only partly used. + // AX = AL + // = AL + // AX = + MachineInstr *LastPartDef = 0; + unsigned LastPartDefDist = 0; + SmallSet PartUses; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (Def && Def != LastDef) { + // There was a def of this sub-register in between. This is a partial + // def, keep track of the last one. + unsigned Dist = DistanceMap[Def]; + if (Dist > LastPartDefDist) { + LastPartDefDist = Dist; + LastPartDef = Def; + } + continue; + } + if (MachineInstr *Use = PhysRegUse[SubReg]) { + PartUses.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.insert(*SS); + unsigned Dist = DistanceMap[Use]; + if (Dist > LastRefOrPartRefDist) { + LastRefOrPartRefDist = Dist; + LastRefOrPartRef = Use; + } + } + } + + if (!PhysRegUse[Reg]) { + // Partial uses. Mark register def dead and add implicit def of + // sub-registers which are used. + // EAX = op AL + // That is, EAX def is dead but AL def extends pass it. + PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (!PartUses.count(SubReg)) + continue; + bool NeedDef = true; + if (PhysRegDef[Reg] == PhysRegDef[SubReg]) { + MachineOperand *MO = PhysRegDef[Reg]->findRegisterDefOperand(SubReg); + if (MO) { + NeedDef = false; + assert(!MO->isDead()); + } + } + if (NeedDef) + PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg, + true/*IsDef*/, true/*IsImp*/)); + MachineInstr *LastSubRef = FindLastRefOrPartRef(SubReg); + if (LastSubRef) + LastSubRef->addRegisterKilled(SubReg, TRI, true); + else { + LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true); + PhysRegUse[SubReg] = LastRefOrPartRef; + for (const unsigned *SSRegs = TRI->getSubRegisters(SubReg); + unsigned SSReg = *SSRegs; ++SSRegs) + PhysRegUse[SSReg] = LastRefOrPartRef; + } + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.erase(*SS); + } + } else if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI) { + if (LastPartDef) + // The last partial def kills the register. + LastPartDef->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/, + true/*IsImp*/, true/*IsKill*/)); + else { + MachineOperand *MO = + LastRefOrPartRef->findRegisterDefOperand(Reg, false, TRI); + bool NeedEC = MO->isEarlyClobber() && MO->getReg() != Reg; + // If the last reference is the last def, then it's not used at all. + // That is, unless we are currently processing the last reference itself. + LastRefOrPartRef->addRegisterDead(Reg, TRI, true); + if (NeedEC) { + // If we are adding a subreg def and the superreg def is marked early + // clobber, add an early clobber marker to the subreg def. + MO = LastRefOrPartRef->findRegisterDefOperand(Reg); + if (MO) + MO->setIsEarlyClobber(); + } + } + } else + LastRefOrPartRef->addRegisterKilled(Reg, TRI, true); + return true; +} + +void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI, + SmallVector &Defs) { + // What parts of the register are previously defined? + SmallSet Live; + if (PhysRegDef[Reg] || PhysRegUse[Reg]) { + Live.insert(Reg); + for (const unsigned *SS = TRI->getSubRegisters(Reg); *SS; ++SS) + Live.insert(*SS); + } else { + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + // If a register isn't itself defined, but all parts that make up of it + // are defined, then consider it also defined. + // e.g. + // AL = + // AH = + // = AX + if (Live.count(SubReg)) + continue; + if (PhysRegDef[SubReg] || PhysRegUse[SubReg]) { + Live.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Live.insert(*SS); + } + } + } + + // Start from the largest piece, find the last time any part of the register + // is referenced. + HandlePhysRegKill(Reg, MI); + // Only some of the sub-registers are used. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (!Live.count(SubReg)) + // Skip if this sub-register isn't defined. + continue; + HandlePhysRegKill(SubReg, MI); + } + + if (MI) + Defs.push_back(Reg); // Remember this def. +} + +void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI, + SmallVector &Defs) { + while (!Defs.empty()) { + unsigned Reg = Defs.back(); + Defs.pop_back(); + PhysRegDef[Reg] = MI; + PhysRegUse[Reg] = NULL; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + PhysRegDef[SubReg] = MI; + PhysRegUse[SubReg] = NULL; + } + } +} + +bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + MRI = &mf.getRegInfo(); + TRI = MF->getTarget().getRegisterInfo(); + + ReservedRegisters = TRI->getReservedRegs(mf); + + unsigned NumRegs = TRI->getNumRegs(); + PhysRegDef = new MachineInstr*[NumRegs]; + PhysRegUse = new MachineInstr*[NumRegs]; + PHIVarInfo = new SmallVector[MF->getNumBlockIDs()]; + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); + PHIJoins.clear(); + + analyzePHINodes(mf); + + // Calculate live variable information in depth first order on the CFG of the + // function. This guarantees that we will see the definition of a virtual + // register before its uses due to dominance properties of SSA (except for PHI + // nodes, which are treated as a special case). + MachineBasicBlock *Entry = MF->begin(); + SmallPtrSet Visited; + + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + + // Mark live-in registers as live-in. + SmallVector Defs; + for (MachineBasicBlock::livein_iterator II = MBB->livein_begin(), + EE = MBB->livein_end(); II != EE; ++II) { + assert(TargetRegisterInfo::isPhysicalRegister(*II) && + "Cannot have a live-in virtual register!"); + HandlePhysRegDef(*II, 0, Defs); + } + + // Loop over all of the instructions, processing them. + DistanceMap.clear(); + unsigned Dist = 0; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + MachineInstr *MI = I; + if (MI->isDebugValue()) + continue; + DistanceMap.insert(std::make_pair(MI, Dist++)); + + // Process all of the operands of the instruction... + unsigned NumOperandsToProcess = MI->getNumOperands(); + + // Unless it is a PHI node. In this case, ONLY process the DEF, not any + // of the uses. They will be handled in other basic blocks. + if (MI->isPHI()) + NumOperandsToProcess = 1; + + // Clear kill and dead markers. LV will recompute them. + SmallVector UseRegs; + SmallVector DefRegs; + for (unsigned i = 0; i != NumOperandsToProcess; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned MOReg = MO.getReg(); + if (MO.isUse()) { + MO.setIsKill(false); + UseRegs.push_back(MOReg); + } else /*MO.isDef()*/ { + MO.setIsDead(false); + DefRegs.push_back(MOReg); + } + } + + // Process all uses. + for (unsigned i = 0, e = UseRegs.size(); i != e; ++i) { + unsigned MOReg = UseRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + HandleVirtRegUse(MOReg, MBB, MI); + else if (!ReservedRegisters[MOReg]) + HandlePhysRegUse(MOReg, MI); + } + + // Process all defs. + for (unsigned i = 0, e = DefRegs.size(); i != e; ++i) { + unsigned MOReg = DefRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + HandleVirtRegDef(MOReg, MI); + else if (!ReservedRegisters[MOReg]) + HandlePhysRegDef(MOReg, MI, Defs); + } + UpdatePhysRegDefs(MI, Defs); + } + + // Handle any virtual assignments from PHI nodes which might be at the + // bottom of this basic block. We check all of our successor blocks to see + // if they have PHI nodes, and if so, we simulate an assignment at the end + // of the current block. + if (!PHIVarInfo[MBB->getNumber()].empty()) { + SmallVector& VarInfoVec = PHIVarInfo[MBB->getNumber()]; + + for (SmallVector::iterator I = VarInfoVec.begin(), + E = VarInfoVec.end(); I != E; ++I) + // Mark it alive only in the block we are representing. + MarkVirtRegAliveInBlock(getVarInfo(*I),MRI->getVRegDef(*I)->getParent(), + MBB); + } + + // Finally, if the last instruction in the block is a return, make sure to + // mark it as using all of the live-out values in the function. + // Things marked both call and return are tail calls; do not do this for + // them. The tail callee need not take the same registers as input + // that it produces as output, and there are dependencies for its input + // registers elsewhere. + if (!MBB->empty() && MBB->back().getDesc().isReturn() + && !MBB->back().getDesc().isCall()) { + MachineInstr *Ret = &MBB->back(); + + for (MachineRegisterInfo::liveout_iterator + I = MF->getRegInfo().liveout_begin(), + E = MF->getRegInfo().liveout_end(); I != E; ++I) { + assert(TargetRegisterInfo::isPhysicalRegister(*I) && + "Cannot have a live-out virtual register!"); + HandlePhysRegUse(*I, Ret); + + // Add live-out registers as implicit uses. + if (!Ret->readsRegister(*I)) + Ret->addOperand(MachineOperand::CreateReg(*I, false, true)); + } + } + + // Loop over PhysRegDef / PhysRegUse, killing any registers that are + // available at the end of the basic block. + for (unsigned i = 0; i != NumRegs; ++i) + if (PhysRegDef[i] || PhysRegUse[i]) + HandlePhysRegDef(i, 0, Defs); + + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); + } + + // Convert and transfer the dead / killed information we have gathered into + // VirtRegInfo onto MI's. + for (unsigned i = 0, e1 = VirtRegInfo.size(); i != e1; ++i) { + const unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + for (unsigned j = 0, e2 = VirtRegInfo[Reg].Kills.size(); j != e2; ++j) + if (VirtRegInfo[Reg].Kills[j] == MRI->getVRegDef(Reg)) + VirtRegInfo[Reg].Kills[j]->addRegisterDead(Reg, TRI); + else + VirtRegInfo[Reg].Kills[j]->addRegisterKilled(Reg, TRI); + } + + // Check to make sure there are no unreachable blocks in the MC CFG for the + // function. If so, it is due to a bug in the instruction selector or some + // other part of the code generator if this happens. +#ifndef NDEBUG + for(MachineFunction::iterator i = MF->begin(), e = MF->end(); i != e; ++i) + assert(Visited.count(&*i) != 0 && "unreachable basic block found"); +#endif + + delete[] PhysRegDef; + delete[] PhysRegUse; + delete[] PHIVarInfo; + + return false; +} + +/// replaceKillInstruction - Update register kill info by replacing a kill +/// instruction with a new one. +void LiveVariables::replaceKillInstruction(unsigned Reg, MachineInstr *OldMI, + MachineInstr *NewMI) { + VarInfo &VI = getVarInfo(Reg); + std::replace(VI.Kills.begin(), VI.Kills.end(), OldMI, NewMI); +} + +/// removeVirtualRegistersKilled - Remove all killed info for the specified +/// instruction. +void LiveVariables::removeVirtualRegistersKilled(MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isKill()) { + MO.setIsKill(false); + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + bool removed = getVarInfo(Reg).removeKill(MI); + assert(removed && "kill not in register's VarInfo?"); + removed = true; + } + } + } +} + +/// analyzePHINodes - Gather information about the PHI nodes in here. In +/// particular, we want to map the variable information of a virtual register +/// which is used in a PHI node. We map that to the BB the vreg is coming from. +/// +void LiveVariables::analyzePHINodes(const MachineFunction& Fn) { + for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->isPHI(); ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + PHIVarInfo[BBI->getOperand(i + 1).getMBB()->getNumber()] + .push_back(BBI->getOperand(i).getReg()); +} + +bool LiveVariables::VarInfo::isLiveIn(const MachineBasicBlock &MBB, + unsigned Reg, + MachineRegisterInfo &MRI) { + unsigned Num = MBB.getNumber(); + + // Reg is live-through. + if (AliveBlocks.test(Num)) + return true; + + // Registers defined in MBB cannot be live in. + const MachineInstr *Def = MRI.getVRegDef(Reg); + if (Def && Def->getParent() == &MBB) + return false; + + // Reg was not defined in MBB, was it killed here? + return findKill(&MBB); +} + +bool LiveVariables::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB) { + LiveVariables::VarInfo &VI = getVarInfo(Reg); + + // Loop over all of the successors of the basic block, checking to see if + // the value is either live in the block, or if it is killed in the block. + std::vector OpSuccBlocks; + for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), + E = MBB.succ_end(); SI != E; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + + // Is it alive in this successor? + unsigned SuccIdx = SuccMBB->getNumber(); + if (VI.AliveBlocks.test(SuccIdx)) + return true; + OpSuccBlocks.push_back(SuccMBB); + } + + // Check to see if this value is live because there is a use in a successor + // that kills it. + switch (OpSuccBlocks.size()) { + case 1: { + MachineBasicBlock *SuccMBB = OpSuccBlocks[0]; + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (VI.Kills[i]->getParent() == SuccMBB) + return true; + break; + } + case 2: { + MachineBasicBlock *SuccMBB1 = OpSuccBlocks[0], *SuccMBB2 = OpSuccBlocks[1]; + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (VI.Kills[i]->getParent() == SuccMBB1 || + VI.Kills[i]->getParent() == SuccMBB2) + return true; + break; + } + default: + std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end()); + for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i) + if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(), + VI.Kills[i]->getParent())) + return true; + } + return false; +} + +/// addNewBlock - Add a new basic block BB as an empty succcessor to DomBB. All +/// variables that are live out of DomBB will be marked as passing live through +/// BB. +void LiveVariables::addNewBlock(MachineBasicBlock *BB, + MachineBasicBlock *DomBB, + MachineBasicBlock *SuccBB) { + const unsigned NumNew = BB->getNumber(); + + // All registers used by PHI nodes in SuccBB must be live through BB. + for (MachineBasicBlock::const_iterator BBI = SuccBB->begin(), + BBE = SuccBB->end(); BBI != BBE && BBI->isPHI(); ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + if (BBI->getOperand(i+1).getMBB() == BB) + getVarInfo(BBI->getOperand(i).getReg()).AliveBlocks.set(NumNew); + + // Update info for all live variables + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + VarInfo &VI = getVarInfo(Reg); + if (!VI.AliveBlocks.test(NumNew) && VI.isLiveIn(*SuccBB, Reg, *MRI)) + VI.AliveBlocks.set(NumNew); + } +} diff --git a/final/lib/CodeGen/LocalStackSlotAllocation.cpp b/final/lib/CodeGen/LocalStackSlotAllocation.cpp new file mode 100644 index 00000000000..1318d621249 --- /dev/null +++ b/final/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -0,0 +1,359 @@ +//===- LocalStackSlotAllocation.cpp - Pre-allocate locals to stack slots --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass assigns local frame indices to stack slots relative to one another +// and allocates additional base registers to access them when the target +// estimates they are likely to be out of range of stack pointer and frame +// pointer relative addressing. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "localstackalloc" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetFrameLowering.h" + +using namespace llvm; + +STATISTIC(NumAllocations, "Number of frame indices allocated into local block"); +STATISTIC(NumBaseRegisters, "Number of virtual frame base registers allocated"); +STATISTIC(NumReplacements, "Number of frame indices references replaced"); + +namespace { + class FrameRef { + MachineBasicBlock::iterator MI; // Instr referencing the frame + int64_t LocalOffset; // Local offset of the frame idx referenced + public: + FrameRef(MachineBasicBlock::iterator I, int64_t Offset) : + MI(I), LocalOffset(Offset) {} + bool operator<(const FrameRef &RHS) const { + return LocalOffset < RHS.LocalOffset; + } + MachineBasicBlock::iterator getMachineInstr() { return MI; } + }; + + class LocalStackSlotPass: public MachineFunctionPass { + SmallVector LocalOffsets; + + void AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, int64_t &Offset, + bool StackGrowsDown, unsigned &MaxAlign); + void calculateFrameObjectOffsets(MachineFunction &Fn); + bool insertFrameReferenceRegisters(MachineFunction &Fn); + public: + static char ID; // Pass identification, replacement for typeid + explicit LocalStackSlotPass() : MachineFunctionPass(ID) { } + bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + const char *getPassName() const { + return "Local Stack Slot Allocation"; + } + + private: + }; +} // end anonymous namespace + +char LocalStackSlotPass::ID = 0; + +FunctionPass *llvm::createLocalStackSlotAllocationPass() { + return new LocalStackSlotPass(); +} + +bool LocalStackSlotPass::runOnMachineFunction(MachineFunction &MF) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); + unsigned LocalObjectCount = MFI->getObjectIndexEnd(); + + // If the target doesn't want/need this pass, or if there are no locals + // to consider, early exit. + if (!TRI->requiresVirtualBaseRegisters(MF) || LocalObjectCount == 0) + return true; + + // Make sure we have enough space to store the local offsets. + LocalOffsets.resize(MFI->getObjectIndexEnd()); + + // Lay out the local blob. + calculateFrameObjectOffsets(MF); + + // Insert virtual base registers to resolve frame index references. + bool UsedBaseRegs = insertFrameReferenceRegisters(MF); + + // Tell MFI whether any base registers were allocated. PEI will only + // want to use the local block allocations from this pass if there were any. + // Otherwise, PEI can do a bit better job of getting the alignment right + // without a hole at the start since it knows the alignment of the stack + // at the start of local allocation, and this pass doesn't. + MFI->setUseLocalStackAllocationBlock(UsedBaseRegs); + + return true; +} + +/// AdjustStackOffset - Helper function used to adjust the stack frame offset. +void LocalStackSlotPass::AdjustStackOffset(MachineFrameInfo *MFI, + int FrameIdx, int64_t &Offset, + bool StackGrowsDown, + unsigned &MaxAlign) { + // If the stack grows down, add the object size to find the lowest address. + if (StackGrowsDown) + Offset += MFI->getObjectSize(FrameIdx); + + unsigned Align = MFI->getObjectAlignment(FrameIdx); + + // If the alignment of this object is greater than that of the stack, then + // increase the stack alignment to match. + MaxAlign = std::max(MaxAlign, Align); + + // Adjust to alignment boundary. + Offset = (Offset + Align - 1) / Align * Align; + + int64_t LocalOffset = StackGrowsDown ? -Offset : Offset; + DEBUG(dbgs() << "Allocate FI(" << FrameIdx << ") to local offset " + << LocalOffset << "\n"); + // Keep the offset available for base register allocation + LocalOffsets[FrameIdx] = LocalOffset; + // And tell MFI about it for PEI to use later + MFI->mapLocalFrameObject(FrameIdx, LocalOffset); + + if (!StackGrowsDown) + Offset += MFI->getObjectSize(FrameIdx); + + ++NumAllocations; +} + +/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the +/// abstract stack objects. +/// +void LocalStackSlotPass::calculateFrameObjectOffsets(MachineFunction &Fn) { + // Loop over all of the stack objects, assigning sequential addresses... + MachineFrameInfo *MFI = Fn.getFrameInfo(); + const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); + bool StackGrowsDown = + TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; + int64_t Offset = 0; + unsigned MaxAlign = 0; + + // Make sure that the stack protector comes before the local variables on the + // stack. + SmallSet LargeStackObjs; + if (MFI->getStackProtectorIndex() >= 0) { + AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), Offset, + StackGrowsDown, MaxAlign); + + // Assign large stack objects first. + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isDeadObjectIndex(i)) + continue; + if (MFI->getStackProtectorIndex() == (int)i) + continue; + if (!MFI->MayNeedStackProtector(i)) + continue; + + AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); + LargeStackObjs.insert(i); + } + } + + // Then assign frame offsets to stack objects that are not used to spill + // callee saved registers. + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isDeadObjectIndex(i)) + continue; + if (MFI->getStackProtectorIndex() == (int)i) + continue; + if (LargeStackObjs.count(i)) + continue; + + AdjustStackOffset(MFI, i, Offset, StackGrowsDown, MaxAlign); + } + + // Remember how big this blob of stack space is + MFI->setLocalFrameSize(Offset); + MFI->setLocalFrameMaxAlign(MaxAlign); +} + +static inline bool +lookupCandidateBaseReg(const SmallVector, 8> &Regs, + std::pair &RegOffset, + int64_t FrameSizeAdjust, + int64_t LocalFrameOffset, + const MachineInstr *MI, + const TargetRegisterInfo *TRI) { + unsigned e = Regs.size(); + for (unsigned i = 0; i < e; ++i) { + RegOffset = Regs[i]; + // Check if the relative offset from the where the base register references + // to the target address is in range for the instruction. + int64_t Offset = FrameSizeAdjust + LocalFrameOffset - RegOffset.second; + if (TRI->isFrameOffsetLegal(MI, Offset)) + return true; + } + return false; +} + +bool LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { + // Scan the function's instructions looking for frame index references. + // For each, ask the target if it wants a virtual base register for it + // based on what we can tell it about where the local will end up in the + // stack frame. If it wants one, re-use a suitable one we've previously + // allocated, or if there isn't one that fits the bill, allocate a new one + // and ask the target to create a defining instruction for it. + bool UsedBaseReg = false; + + MachineFrameInfo *MFI = Fn.getFrameInfo(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); + bool StackGrowsDown = + TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; + + // Collect all of the instructions in the block that reference + // a frame index. Also store the frame index referenced to ease later + // lookup. (For any insn that has more than one FI reference, we arbitrarily + // choose the first one). + SmallVector FrameReferenceInsns; + + // A base register definition is a register + offset pair. + SmallVector, 8> BaseRegisters; + + for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { + MachineInstr *MI = I; + + // Debug value instructions can't be out of range, so they don't need + // any updates. + if (MI->isDebugValue()) + continue; + + // For now, allocate the base register(s) within the basic block + // where they're used, and don't try to keep them around outside + // of that. It may be beneficial to try sharing them more broadly + // than that, but the increased register pressure makes that a + // tricky thing to balance. Investigate if re-materializing these + // becomes an issue. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + // Consider replacing all frame index operands that reference + // an object allocated in the local block. + if (MI->getOperand(i).isFI()) { + // Don't try this with values not in the local block. + if (!MFI->isObjectPreAllocated(MI->getOperand(i).getIndex())) + break; + FrameReferenceInsns. + push_back(FrameRef(MI, LocalOffsets[MI->getOperand(i).getIndex()])); + break; + } + } + } + } + + // Sort the frame references by local offset + array_pod_sort(FrameReferenceInsns.begin(), FrameReferenceInsns.end()); + + MachineBasicBlock *Entry = Fn.begin(); + + // Loop through the frame references and allocate for them as necessary. + for (int ref = 0, e = FrameReferenceInsns.size(); ref < e ; ++ref) { + MachineBasicBlock::iterator I = + FrameReferenceInsns[ref].getMachineInstr(); + MachineInstr *MI = I; + for (unsigned idx = 0, e = MI->getNumOperands(); idx != e; ++idx) { + // Consider replacing all frame index operands that reference + // an object allocated in the local block. + if (MI->getOperand(idx).isFI()) { + int FrameIdx = MI->getOperand(idx).getIndex(); + + assert(MFI->isObjectPreAllocated(FrameIdx) && + "Only pre-allocated locals expected!"); + + DEBUG(dbgs() << "Considering: " << *MI); + if (TRI->needsFrameBaseReg(MI, LocalOffsets[FrameIdx])) { + unsigned BaseReg = 0; + int64_t Offset = 0; + int64_t FrameSizeAdjust = + StackGrowsDown ? MFI->getLocalFrameSize() : 0; + + DEBUG(dbgs() << " Replacing FI in: " << *MI); + + // If we have a suitable base register available, use it; otherwise + // create a new one. Note that any offset encoded in the + // instruction itself will be taken into account by the target, + // so we don't have to adjust for it here when reusing a base + // register. + std::pair RegOffset; + if (lookupCandidateBaseReg(BaseRegisters, RegOffset, + FrameSizeAdjust, + LocalOffsets[FrameIdx], + MI, TRI)) { + DEBUG(dbgs() << " Reusing base register " << + RegOffset.first << "\n"); + // We found a register to reuse. + BaseReg = RegOffset.first; + Offset = FrameSizeAdjust + LocalOffsets[FrameIdx] - + RegOffset.second; + } else { + // No previously defined register was in range, so create a + // new one. + int64_t InstrOffset = TRI->getFrameIndexInstrOffset(MI, idx); + const TargetRegisterClass *RC = TRI->getPointerRegClass(); + BaseReg = Fn.getRegInfo().createVirtualRegister(RC); + + DEBUG(dbgs() << " Materializing base register " << BaseReg << + " at frame local offset " << + LocalOffsets[FrameIdx] + InstrOffset << "\n"); + + // Tell the target to insert the instruction to initialize + // the base register. + // MachineBasicBlock::iterator InsertionPt = Entry->begin(); + TRI->materializeFrameBaseRegister(Entry, BaseReg, FrameIdx, + InstrOffset); + + // The base register already includes any offset specified + // by the instruction, so account for that so it doesn't get + // applied twice. + Offset = -InstrOffset; + + int64_t BaseOffset = FrameSizeAdjust + LocalOffsets[FrameIdx] + + InstrOffset; + BaseRegisters.push_back( + std::pair(BaseReg, BaseOffset)); + ++NumBaseRegisters; + UsedBaseReg = true; + } + assert(BaseReg != 0 && "Unable to allocate virtual base register!"); + + // Modify the instruction to use the new base register rather + // than the frame index operand. + TRI->resolveFrameIndex(I, BaseReg, Offset); + DEBUG(dbgs() << "Resolved: " << *MI); + + ++NumReplacements; + } + } + } + } + return UsedBaseReg; +} diff --git a/final/lib/CodeGen/LowerSubregs.cpp b/final/lib/CodeGen/LowerSubregs.cpp new file mode 100644 index 00000000000..7871ba9c17e --- /dev/null +++ b/final/lib/CodeGen/LowerSubregs.cpp @@ -0,0 +1,223 @@ +//===-- LowerSubregs.cpp - Subregister Lowering instruction pass ----------===// +// +// 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 MachineFunction pass which runs after register +// allocation that turns subreg insert/extract instructions into register +// copies, as needed. This ensures correct codegen even if the coalescer +// isn't able to remove all subreg instructions. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lowersubregs" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct LowerSubregsInstructionPass : public MachineFunctionPass { + private: + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification, replacement for typeid + LowerSubregsInstructionPass() : MachineFunctionPass(ID) {} + + const char *getPassName() const { + return "Subregister lowering instruction pass"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - pass entry point + bool runOnMachineFunction(MachineFunction&); + + private: + bool LowerSubregToReg(MachineInstr *MI); + bool LowerCopy(MachineInstr *MI); + + void TransferDeadFlag(MachineInstr *MI, unsigned DstReg, + const TargetRegisterInfo *TRI); + void TransferImplicitDefs(MachineInstr *MI); + }; + + char LowerSubregsInstructionPass::ID = 0; +} + +FunctionPass *llvm::createLowerSubregsPass() { + return new LowerSubregsInstructionPass(); +} + +/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead, +/// and the lowered replacement instructions immediately precede it. +/// Mark the replacement instructions with the dead flag. +void +LowerSubregsInstructionPass::TransferDeadFlag(MachineInstr *MI, + unsigned DstReg, + const TargetRegisterInfo *TRI) { + for (MachineBasicBlock::iterator MII = + prior(MachineBasicBlock::iterator(MI)); ; --MII) { + if (MII->addRegisterDead(DstReg, TRI)) + break; + assert(MII != MI->getParent()->begin() && + "copyPhysReg output doesn't reference destination register!"); + } +} + +/// TransferImplicitDefs - MI is a pseudo-instruction, and the lowered +/// replacement instructions immediately precede it. Copy any implicit-def +/// operands from MI to the replacement instruction. +void +LowerSubregsInstructionPass::TransferImplicitDefs(MachineInstr *MI) { + MachineBasicBlock::iterator CopyMI = MI; + --CopyMI; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isImplicit() || MO.isUse()) + continue; + CopyMI->addOperand(MachineOperand::CreateReg(MO.getReg(), true, true)); + } +} + +bool LowerSubregsInstructionPass::LowerSubregToReg(MachineInstr *MI) { + MachineBasicBlock *MBB = MI->getParent(); + assert((MI->getOperand(0).isReg() && MI->getOperand(0).isDef()) && + MI->getOperand(1).isImm() && + (MI->getOperand(2).isReg() && MI->getOperand(2).isUse()) && + MI->getOperand(3).isImm() && "Invalid subreg_to_reg"); + + unsigned DstReg = MI->getOperand(0).getReg(); + unsigned InsReg = MI->getOperand(2).getReg(); + assert(!MI->getOperand(2).getSubReg() && "SubIdx on physreg?"); + unsigned SubIdx = MI->getOperand(3).getImm(); + + assert(SubIdx != 0 && "Invalid index for insert_subreg"); + unsigned DstSubReg = TRI->getSubReg(DstReg, SubIdx); + + assert(TargetRegisterInfo::isPhysicalRegister(DstReg) && + "Insert destination must be in a physical register"); + assert(TargetRegisterInfo::isPhysicalRegister(InsReg) && + "Inserted value must be in a physical register"); + + DEBUG(dbgs() << "subreg: CONVERTING: " << *MI); + + if (DstSubReg == InsReg) { + // No need to insert an identify copy instruction. + // Watch out for case like this: + // %RAX = SUBREG_TO_REG 0, %EAX, 3 + // We must leave %RAX live. + if (DstReg != InsReg) { + MI->setDesc(TII->get(TargetOpcode::KILL)); + MI->RemoveOperand(3); // SubIdx + MI->RemoveOperand(1); // Imm + DEBUG(dbgs() << "subreg: replace by: " << *MI); + return true; + } + DEBUG(dbgs() << "subreg: eliminated!"); + } else { + TII->copyPhysReg(*MBB, MI, MI->getDebugLoc(), DstSubReg, InsReg, + MI->getOperand(2).isKill()); + // Transfer the kill/dead flags, if needed. + if (MI->getOperand(0).isDead()) + TransferDeadFlag(MI, DstSubReg, TRI); + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + dbgs() << "subreg: " << *(--dMI); + }); + } + + DEBUG(dbgs() << '\n'); + MBB->erase(MI); + return true; +} + +bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) { + MachineOperand &DstMO = MI->getOperand(0); + MachineOperand &SrcMO = MI->getOperand(1); + + if (SrcMO.getReg() == DstMO.getReg()) { + DEBUG(dbgs() << "identity copy: " << *MI); + // No need to insert an identity copy instruction, but replace with a KILL + // if liveness is changed. + if (DstMO.isDead() || SrcMO.isUndef() || MI->getNumOperands() > 2) { + // We must make sure the super-register gets killed. Replace the + // instruction with KILL. + MI->setDesc(TII->get(TargetOpcode::KILL)); + DEBUG(dbgs() << "replaced by: " << *MI); + return true; + } + // Vanilla identity copy. + MI->eraseFromParent(); + return true; + } + + DEBUG(dbgs() << "real copy: " << *MI); + TII->copyPhysReg(*MI->getParent(), MI, MI->getDebugLoc(), + DstMO.getReg(), SrcMO.getReg(), SrcMO.isKill()); + + if (DstMO.isDead()) + TransferDeadFlag(MI, DstMO.getReg(), TRI); + if (MI->getNumOperands() > 2) + TransferImplicitDefs(MI); + DEBUG({ + MachineBasicBlock::iterator dMI = MI; + dbgs() << "replaced by: " << *(--dMI); + }); + MI->eraseFromParent(); + return true; +} + +/// runOnMachineFunction - Reduce subregister inserts and extracts to register +/// copies. +/// +bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "Machine Function\n" + << "********** LOWERING SUBREG INSTRS **********\n" + << "********** Function: " + << MF.getFunction()->getName() << '\n'); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + + bool MadeChange = false; + + for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end(); + mbbi != mbbe; ++mbbi) { + for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); + mi != me;) { + MachineBasicBlock::iterator nmi = llvm::next(mi); + MachineInstr *MI = mi; + assert(!MI->isInsertSubreg() && "INSERT_SUBREG should no longer appear"); + assert(MI->getOpcode() != TargetOpcode::EXTRACT_SUBREG && + "EXTRACT_SUBREG should no longer appear"); + if (MI->isSubregToReg()) { + MadeChange |= LowerSubregToReg(MI); + } else if (MI->isCopy()) { + MadeChange |= LowerCopy(MI); + } + mi = nmi; + } + } + + return MadeChange; +} diff --git a/final/lib/CodeGen/MachineBasicBlock.cpp b/final/lib/CodeGen/MachineBasicBlock.cpp new file mode 100644 index 00000000000..ccbff0af5b2 --- /dev/null +++ b/final/lib/CodeGen/MachineBasicBlock.cpp @@ -0,0 +1,692 @@ +//===-- llvm/CodeGen/MachineBasicBlock.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the sequence of machine instructions for a basic block. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/BasicBlock.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/LeakDetector.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb) + : BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false), + AddressTaken(false) { + Insts.Parent = this; +} + +MachineBasicBlock::~MachineBasicBlock() { + LeakDetector::removeGarbageObject(this); +} + +/// getSymbol - Return the MCSymbol for this basic block. +/// +MCSymbol *MachineBasicBlock::getSymbol() const { + const MachineFunction *MF = getParent(); + MCContext &Ctx = MF->getContext(); + const char *Prefix = Ctx.getAsmInfo().getPrivateGlobalPrefix(); + return Ctx.GetOrCreateSymbol(Twine(Prefix) + "BB" + + Twine(MF->getFunctionNumber()) + "_" + + Twine(getNumber())); +} + + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineBasicBlock &MBB) { + MBB.print(OS); + return OS; +} + +/// addNodeToList (MBB) - When an MBB is added to an MF, we need to update the +/// parent pointer of the MBB, the MBB numbering, and any instructions in the +/// MBB to be on the right operand list for registers. +/// +/// MBBs start out as #-1. When a MBB is added to a MachineFunction, it +/// gets the next available unique MBB number. If it is removed from a +/// MachineFunction, it goes back to being #-1. +void ilist_traits::addNodeToList(MachineBasicBlock *N) { + MachineFunction &MF = *N->getParent(); + N->Number = MF.addToMBBNumbering(N); + + // Make sure the instructions have their operands in the reginfo lists. + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + for (MachineBasicBlock::iterator I = N->begin(), E = N->end(); I != E; ++I) + I->AddRegOperandsToUseLists(RegInfo); + + LeakDetector::removeGarbageObject(N); +} + +void ilist_traits::removeNodeFromList(MachineBasicBlock *N) { + N->getParent()->removeFromMBBNumbering(N->Number); + N->Number = -1; + LeakDetector::addGarbageObject(N); +} + + +/// addNodeToList (MI) - When we add an instruction to a basic block +/// list, we update its parent pointer and add its operands from reg use/def +/// lists if appropriate. +void ilist_traits::addNodeToList(MachineInstr *N) { + assert(N->getParent() == 0 && "machine instruction already in a basic block"); + N->setParent(Parent); + + // Add the instruction's register operands to their corresponding + // use/def lists. + MachineFunction *MF = Parent->getParent(); + N->AddRegOperandsToUseLists(MF->getRegInfo()); + + LeakDetector::removeGarbageObject(N); +} + +/// removeNodeFromList (MI) - When we remove an instruction from a basic block +/// list, we update its parent pointer and remove its operands from reg use/def +/// lists if appropriate. +void ilist_traits::removeNodeFromList(MachineInstr *N) { + assert(N->getParent() != 0 && "machine instruction not in a basic block"); + + // Remove from the use/def lists. + N->RemoveRegOperandsFromUseLists(); + + N->setParent(0); + + LeakDetector::addGarbageObject(N); +} + +/// transferNodesFromList (MI) - When moving a range of instructions from one +/// MBB list to another, we need to update the parent pointers and the use/def +/// lists. +void ilist_traits:: +transferNodesFromList(ilist_traits &fromList, + MachineBasicBlock::iterator first, + MachineBasicBlock::iterator last) { + assert(Parent->getParent() == fromList.Parent->getParent() && + "MachineInstr parent mismatch!"); + + // Splice within the same MBB -> no change. + if (Parent == fromList.Parent) return; + + // If splicing between two blocks within the same function, just update the + // parent pointers. + for (; first != last; ++first) + first->setParent(Parent); +} + +void ilist_traits::deleteNode(MachineInstr* MI) { + assert(!MI->getParent() && "MI is still in a block!"); + Parent->getParent()->DeleteMachineInstr(MI); +} + +MachineBasicBlock::iterator MachineBasicBlock::getFirstNonPHI() { + iterator I = begin(); + while (I != end() && I->isPHI()) + ++I; + return I; +} + +MachineBasicBlock::iterator +MachineBasicBlock::SkipPHIsAndLabels(MachineBasicBlock::iterator I) { + while (I != end() && (I->isPHI() || I->isLabel() || I->isDebugValue())) + ++I; + return I; +} + +MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() { + iterator I = end(); + while (I != begin() && ((--I)->getDesc().isTerminator() || I->isDebugValue())) + ; /*noop */ + while (I != end() && !I->getDesc().isTerminator()) + ++I; + return I; +} + +MachineBasicBlock::iterator MachineBasicBlock::getLastNonDebugInstr() { + iterator B = begin(), I = end(); + while (I != B) { + --I; + if (I->isDebugValue()) + continue; + return I; + } + // The block is all debug values. + return end(); +} + +const MachineBasicBlock *MachineBasicBlock::getLandingPadSuccessor() const { + // A block with a landing pad successor only has one other successor. + if (succ_size() > 2) + return 0; + for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I) + if ((*I)->isLandingPad()) + return *I; + return 0; +} + +void MachineBasicBlock::dump() const { + print(dbgs()); +} + +StringRef MachineBasicBlock::getName() const { + if (const BasicBlock *LBB = getBasicBlock()) + return LBB->getName(); + else + return "(null)"; +} + +void MachineBasicBlock::print(raw_ostream &OS, SlotIndexes *Indexes) const { + const MachineFunction *MF = getParent(); + if (!MF) { + OS << "Can't print out MachineBasicBlock because parent MachineFunction" + << " is null\n"; + return; + } + + if (Alignment) { OS << "Alignment " << Alignment << "\n"; } + + if (Indexes) + OS << Indexes->getMBBStartIdx(this) << '\t'; + + OS << "BB#" << getNumber() << ": "; + + const char *Comma = ""; + if (const BasicBlock *LBB = getBasicBlock()) { + OS << Comma << "derived from LLVM BB "; + WriteAsOperand(OS, LBB, /*PrintType=*/false); + Comma = ", "; + } + if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; } + if (hasAddressTaken()) { OS << Comma << "ADDRESS TAKEN"; Comma = ", "; } + OS << '\n'; + + const TargetRegisterInfo *TRI = MF->getTarget().getRegisterInfo(); + if (!livein_empty()) { + if (Indexes) OS << '\t'; + OS << " Live Ins:"; + for (livein_iterator I = livein_begin(),E = livein_end(); I != E; ++I) + OS << ' ' << PrintReg(*I, TRI); + OS << '\n'; + } + // Print the preds of this block according to the CFG. + if (!pred_empty()) { + if (Indexes) OS << '\t'; + OS << " Predecessors according to CFG:"; + for (const_pred_iterator PI = pred_begin(), E = pred_end(); PI != E; ++PI) + OS << " BB#" << (*PI)->getNumber(); + OS << '\n'; + } + + for (const_iterator I = begin(); I != end(); ++I) { + if (Indexes) { + if (Indexes->hasIndex(I)) + OS << Indexes->getInstructionIndex(I); + OS << '\t'; + } + OS << '\t'; + I->print(OS, &getParent()->getTarget()); + } + + // Print the successors of this block according to the CFG. + if (!succ_empty()) { + if (Indexes) OS << '\t'; + OS << " Successors according to CFG:"; + for (const_succ_iterator SI = succ_begin(), E = succ_end(); SI != E; ++SI) + OS << " BB#" << (*SI)->getNumber(); + OS << '\n'; + } +} + +void MachineBasicBlock::removeLiveIn(unsigned Reg) { + std::vector::iterator I = + std::find(LiveIns.begin(), LiveIns.end(), Reg); + assert(I != LiveIns.end() && "Not a live in!"); + LiveIns.erase(I); +} + +bool MachineBasicBlock::isLiveIn(unsigned Reg) const { + livein_iterator I = std::find(livein_begin(), livein_end(), Reg); + return I != livein_end(); +} + +void MachineBasicBlock::moveBefore(MachineBasicBlock *NewAfter) { + getParent()->splice(NewAfter, this); +} + +void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) { + MachineFunction::iterator BBI = NewBefore; + getParent()->splice(++BBI, this); +} + +void MachineBasicBlock::updateTerminator() { + const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo(); + // A block with no successors has no concerns with fall-through edges. + if (this->succ_empty()) return; + + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + DebugLoc dl; // FIXME: this is nowhere + bool B = TII->AnalyzeBranch(*this, TBB, FBB, Cond); + (void) B; + assert(!B && "UpdateTerminators requires analyzable predecessors!"); + if (Cond.empty()) { + if (TBB) { + // The block has an unconditional branch. If its successor is now + // its layout successor, delete the branch. + if (isLayoutSuccessor(TBB)) + TII->RemoveBranch(*this); + } else { + // The block has an unconditional fallthrough. If its successor is not + // its layout successor, insert a branch. + TBB = *succ_begin(); + if (!isLayoutSuccessor(TBB)) + TII->InsertBranch(*this, TBB, 0, Cond, dl); + } + } else { + if (FBB) { + // The block has a non-fallthrough conditional branch. If one of its + // successors is its layout successor, rewrite it to a fallthrough + // conditional branch. + if (isLayoutSuccessor(TBB)) { + if (TII->ReverseBranchCondition(Cond)) + return; + TII->RemoveBranch(*this); + TII->InsertBranch(*this, FBB, 0, Cond, dl); + } else if (isLayoutSuccessor(FBB)) { + TII->RemoveBranch(*this); + TII->InsertBranch(*this, TBB, 0, Cond, dl); + } + } else { + // The block has a fallthrough conditional branch. + MachineBasicBlock *MBBA = *succ_begin(); + MachineBasicBlock *MBBB = *llvm::next(succ_begin()); + if (MBBA == TBB) std::swap(MBBB, MBBA); + if (isLayoutSuccessor(TBB)) { + if (TII->ReverseBranchCondition(Cond)) { + // We can't reverse the condition, add an unconditional branch. + Cond.clear(); + TII->InsertBranch(*this, MBBA, 0, Cond, dl); + return; + } + TII->RemoveBranch(*this); + TII->InsertBranch(*this, MBBA, 0, Cond, dl); + } else if (!isLayoutSuccessor(MBBA)) { + TII->RemoveBranch(*this); + TII->InsertBranch(*this, TBB, MBBA, Cond, dl); + } + } + } +} + +void MachineBasicBlock::addSuccessor(MachineBasicBlock *succ) { + Successors.push_back(succ); + succ->addPredecessor(this); +} + +void MachineBasicBlock::removeSuccessor(MachineBasicBlock *succ) { + succ->removePredecessor(this); + succ_iterator I = std::find(Successors.begin(), Successors.end(), succ); + assert(I != Successors.end() && "Not a current successor!"); + Successors.erase(I); +} + +MachineBasicBlock::succ_iterator +MachineBasicBlock::removeSuccessor(succ_iterator I) { + assert(I != Successors.end() && "Not a current successor!"); + (*I)->removePredecessor(this); + return Successors.erase(I); +} + +void MachineBasicBlock::addPredecessor(MachineBasicBlock *pred) { + Predecessors.push_back(pred); +} + +void MachineBasicBlock::removePredecessor(MachineBasicBlock *pred) { + std::vector::iterator I = + std::find(Predecessors.begin(), Predecessors.end(), pred); + assert(I != Predecessors.end() && "Pred is not a predecessor of this block!"); + Predecessors.erase(I); +} + +void MachineBasicBlock::transferSuccessors(MachineBasicBlock *fromMBB) { + if (this == fromMBB) + return; + + while (!fromMBB->succ_empty()) { + MachineBasicBlock *Succ = *fromMBB->succ_begin(); + addSuccessor(Succ); + fromMBB->removeSuccessor(Succ); + } +} + +void +MachineBasicBlock::transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB) { + if (this == fromMBB) + return; + + while (!fromMBB->succ_empty()) { + MachineBasicBlock *Succ = *fromMBB->succ_begin(); + addSuccessor(Succ); + fromMBB->removeSuccessor(Succ); + + // Fix up any PHI nodes in the successor. + for (MachineBasicBlock::iterator MI = Succ->begin(), ME = Succ->end(); + MI != ME && MI->isPHI(); ++MI) + for (unsigned i = 2, e = MI->getNumOperands()+1; i != e; i += 2) { + MachineOperand &MO = MI->getOperand(i); + if (MO.getMBB() == fromMBB) + MO.setMBB(this); + } + } +} + +bool MachineBasicBlock::isSuccessor(const MachineBasicBlock *MBB) const { + std::vector::const_iterator I = + std::find(Successors.begin(), Successors.end(), MBB); + return I != Successors.end(); +} + +bool MachineBasicBlock::isLayoutSuccessor(const MachineBasicBlock *MBB) const { + MachineFunction::const_iterator I(this); + return llvm::next(I) == MachineFunction::const_iterator(MBB); +} + +bool MachineBasicBlock::canFallThrough() { + MachineFunction::iterator Fallthrough = this; + ++Fallthrough; + // If FallthroughBlock is off the end of the function, it can't fall through. + if (Fallthrough == getParent()->end()) + return false; + + // If FallthroughBlock isn't a successor, no fallthrough is possible. + if (!isSuccessor(Fallthrough)) + return false; + + // Analyze the branches, if any, at the end of the block. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + const TargetInstrInfo *TII = getParent()->getTarget().getInstrInfo(); + if (TII->AnalyzeBranch(*this, TBB, FBB, Cond)) { + // If we couldn't analyze the branch, examine the last instruction. + // If the block doesn't end in a known control barrier, assume fallthrough + // is possible. The isPredicable check is needed because this code can be + // called during IfConversion, where an instruction which is normally a + // Barrier is predicated and thus no longer an actual control barrier. This + // is over-conservative though, because if an instruction isn't actually + // predicated we could still treat it like a barrier. + return empty() || !back().getDesc().isBarrier() || + back().getDesc().isPredicable(); + } + + // If there is no branch, control always falls through. + if (TBB == 0) return true; + + // If there is some explicit branch to the fallthrough block, it can obviously + // reach, even though the branch should get folded to fall through implicitly. + if (MachineFunction::iterator(TBB) == Fallthrough || + MachineFunction::iterator(FBB) == Fallthrough) + return true; + + // If it's an unconditional branch to some block not the fall through, it + // doesn't fall through. + if (Cond.empty()) return false; + + // Otherwise, if it is conditional and has no explicit false block, it falls + // through. + return FBB == 0; +} + +MachineBasicBlock * +MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { + MachineFunction *MF = getParent(); + DebugLoc dl; // FIXME: this is nowhere + + // We may need to update this's terminator, but we can't do that if + // AnalyzeBranch fails. If this uses a jump table, we won't touch it. + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (TII->AnalyzeBranch(*this, TBB, FBB, Cond)) + return NULL; + + // Avoid bugpoint weirdness: A block may end with a conditional branch but + // jumps to the same MBB is either case. We have duplicate CFG edges in that + // case that we can't handle. Since this never happens in properly optimized + // code, just skip those edges. + if (TBB && TBB == FBB) { + DEBUG(dbgs() << "Won't split critical edge after degenerate BB#" + << getNumber() << '\n'); + return NULL; + } + + MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(); + MF->insert(llvm::next(MachineFunction::iterator(this)), NMBB); + DEBUG(dbgs() << "Splitting critical edge:" + " BB#" << getNumber() + << " -- BB#" << NMBB->getNumber() + << " -- BB#" << Succ->getNumber() << '\n'); + + ReplaceUsesOfBlockWith(Succ, NMBB); + updateTerminator(); + + // Insert unconditional "jump Succ" instruction in NMBB if necessary. + NMBB->addSuccessor(Succ); + if (!NMBB->isLayoutSuccessor(Succ)) { + Cond.clear(); + MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, Succ, NULL, Cond, dl); + } + + // Fix PHI nodes in Succ so they refer to NMBB instead of this + for (MachineBasicBlock::iterator i = Succ->begin(), e = Succ->end(); + i != e && i->isPHI(); ++i) + for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) + if (i->getOperand(ni+1).getMBB() == this) + i->getOperand(ni+1).setMBB(NMBB); + + if (LiveVariables *LV = + P->getAnalysisIfAvailable()) + LV->addNewBlock(NMBB, this, Succ); + + if (MachineDominatorTree *MDT = + P->getAnalysisIfAvailable()) { + // Update dominator information. + MachineDomTreeNode *SucccDTNode = MDT->getNode(Succ); + + bool IsNewIDom = true; + for (const_pred_iterator PI = Succ->pred_begin(), E = Succ->pred_end(); + PI != E; ++PI) { + MachineBasicBlock *PredBB = *PI; + if (PredBB == NMBB) + continue; + if (!MDT->dominates(SucccDTNode, MDT->getNode(PredBB))) { + IsNewIDom = false; + break; + } + } + + // We know "this" dominates the newly created basic block. + MachineDomTreeNode *NewDTNode = MDT->addNewBlock(NMBB, this); + + // If all the other predecessors of "Succ" are dominated by "Succ" itself + // then the new block is the new immediate dominator of "Succ". Otherwise, + // the new block doesn't dominate anything. + if (IsNewIDom) + MDT->changeImmediateDominator(SucccDTNode, NewDTNode); + } + + if (MachineLoopInfo *MLI = P->getAnalysisIfAvailable()) + if (MachineLoop *TIL = MLI->getLoopFor(this)) { + // If one or the other blocks were not in a loop, the new block is not + // either, and thus LI doesn't need to be updated. + if (MachineLoop *DestLoop = MLI->getLoopFor(Succ)) { + if (TIL == DestLoop) { + // Both in the same loop, the NMBB joins loop. + DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase()); + } else if (TIL->contains(DestLoop)) { + // Edge from an outer loop to an inner loop. Add to the outer loop. + TIL->addBasicBlockToLoop(NMBB, MLI->getBase()); + } else if (DestLoop->contains(TIL)) { + // Edge from an inner loop to an outer loop. Add to the outer loop. + DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase()); + } else { + // Edge from two loops with no containment relation. Because these + // are natural loops, we know that the destination block must be the + // header of its loop (adding a branch into a loop elsewhere would + // create an irreducible loop). + assert(DestLoop->getHeader() == Succ && + "Should not create irreducible loops!"); + if (MachineLoop *P = DestLoop->getParentLoop()) + P->addBasicBlockToLoop(NMBB, MLI->getBase()); + } + } + } + + return NMBB; +} + +/// removeFromParent - This method unlinks 'this' from the containing function, +/// and returns it, but does not delete it. +MachineBasicBlock *MachineBasicBlock::removeFromParent() { + assert(getParent() && "Not embedded in a function!"); + getParent()->remove(this); + return this; +} + + +/// eraseFromParent - This method unlinks 'this' from the containing function, +/// and deletes it. +void MachineBasicBlock::eraseFromParent() { + assert(getParent() && "Not embedded in a function!"); + getParent()->erase(this); +} + + +/// ReplaceUsesOfBlockWith - Given a machine basic block that branched to +/// 'Old', change the code and CFG so that it branches to 'New' instead. +void MachineBasicBlock::ReplaceUsesOfBlockWith(MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Cannot replace self with self!"); + + MachineBasicBlock::iterator I = end(); + while (I != begin()) { + --I; + if (!I->getDesc().isTerminator()) break; + + // Scan the operands of this machine instruction, replacing any uses of Old + // with New. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (I->getOperand(i).isMBB() && + I->getOperand(i).getMBB() == Old) + I->getOperand(i).setMBB(New); + } + + // Update the successor information. + removeSuccessor(Old); + addSuccessor(New); +} + +/// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in the +/// CFG to be inserted. If we have proven that MBB can only branch to DestA and +/// DestB, remove any other MBB successors from the CFG. DestA and DestB can be +/// null. +/// +/// Besides DestA and DestB, retain other edges leading to LandingPads +/// (currently there can be only one; we don't check or require that here). +/// Note it is possible that DestA and/or DestB are LandingPads. +bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, + MachineBasicBlock *DestB, + bool isCond) { + // The values of DestA and DestB frequently come from a call to the + // 'TargetInstrInfo::AnalyzeBranch' method. We take our meaning of the initial + // values from there. + // + // 1. If both DestA and DestB are null, then the block ends with no branches + // (it falls through to its successor). + // 2. If DestA is set, DestB is null, and isCond is false, then the block ends + // with only an unconditional branch. + // 3. If DestA is set, DestB is null, and isCond is true, then the block ends + // with a conditional branch that falls through to a successor (DestB). + // 4. If DestA and DestB is set and isCond is true, then the block ends with a + // conditional branch followed by an unconditional branch. DestA is the + // 'true' destination and DestB is the 'false' destination. + + bool Changed = false; + + MachineFunction::iterator FallThru = + llvm::next(MachineFunction::iterator(this)); + + if (DestA == 0 && DestB == 0) { + // Block falls through to successor. + DestA = FallThru; + DestB = FallThru; + } else if (DestA != 0 && DestB == 0) { + if (isCond) + // Block ends in conditional jump that falls through to successor. + DestB = FallThru; + } else { + assert(DestA && DestB && isCond && + "CFG in a bad state. Cannot correct CFG edges"); + } + + // Remove superfluous edges. I.e., those which aren't destinations of this + // basic block, duplicate edges, or landing pads. + SmallPtrSet SeenMBBs; + MachineBasicBlock::succ_iterator SI = succ_begin(); + while (SI != succ_end()) { + const MachineBasicBlock *MBB = *SI; + if (!SeenMBBs.insert(MBB) || + (MBB != DestA && MBB != DestB && !MBB->isLandingPad())) { + // This is a superfluous edge, remove it. + SI = removeSuccessor(SI); + Changed = true; + } else { + ++SI; + } + } + + return Changed; +} + +/// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping +/// any DBG_VALUE instructions. Return UnknownLoc if there is none. +DebugLoc +MachineBasicBlock::findDebugLoc(MachineBasicBlock::iterator &MBBI) { + DebugLoc DL; + MachineBasicBlock::iterator E = end(); + if (MBBI != E) { + // Skip debug declarations, we don't want a DebugLoc from them. + MachineBasicBlock::iterator MBBI2 = MBBI; + while (MBBI2 != E && MBBI2->isDebugValue()) + MBBI2++; + if (MBBI2 != E) + DL = MBBI2->getDebugLoc(); + } + return DL; +} + +void llvm::WriteAsOperand(raw_ostream &OS, const MachineBasicBlock *MBB, + bool t) { + OS << "BB#" << MBB->getNumber(); +} + diff --git a/final/lib/CodeGen/MachineCSE.cpp b/final/lib/CodeGen/MachineCSE.cpp new file mode 100644 index 00000000000..07a7d27b019 --- /dev/null +++ b/final/lib/CodeGen/MachineCSE.cpp @@ -0,0 +1,531 @@ +//===-- MachineCSE.cpp - Machine Common Subexpression Elimination Pass ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs global common subexpression elimination on machine +// instructions using a scoped hash table based value numbering scheme. It +// must be run while the machine function is still in SSA form. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-cse" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ScopedHashTable.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/RecyclingAllocator.h" + +using namespace llvm; + +STATISTIC(NumCoalesces, "Number of copies coalesced"); +STATISTIC(NumCSEs, "Number of common subexpression eliminated"); +STATISTIC(NumPhysCSEs, + "Number of physreg referencing common subexpr eliminated"); +STATISTIC(NumCommutes, "Number of copies coalesced after commuting"); + +namespace { + class MachineCSE : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + AliasAnalysis *AA; + MachineDominatorTree *DT; + MachineRegisterInfo *MRI; + public: + static char ID; // Pass identification + MachineCSE() : MachineFunctionPass(ID), LookAheadLimit(5), CurrVN(0) { + initializeMachineCSEPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addPreservedID(MachineLoopInfoID); + AU.addRequired(); + AU.addPreserved(); + } + + virtual void releaseMemory() { + ScopeMap.clear(); + Exps.clear(); + } + + private: + const unsigned LookAheadLimit; + typedef RecyclingAllocator > AllocatorTy; + typedef ScopedHashTable ScopedHTType; + typedef ScopedHTType::ScopeTy ScopeType; + DenseMap ScopeMap; + ScopedHTType VNT; + SmallVector Exps; + unsigned CurrVN; + + bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB); + bool isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E) const ; + bool hasLivePhysRegDefUses(const MachineInstr *MI, + const MachineBasicBlock *MBB, + SmallSet &PhysRefs) const; + bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, + SmallSet &PhysRefs) const; + bool isCSECandidate(MachineInstr *MI); + bool isProfitableToCSE(unsigned CSReg, unsigned Reg, + MachineInstr *CSMI, MachineInstr *MI); + void EnterScope(MachineBasicBlock *MBB); + void ExitScope(MachineBasicBlock *MBB); + bool ProcessBlock(MachineBasicBlock *MBB); + void ExitScopeIfDone(MachineDomTreeNode *Node, + DenseMap &OpenChildren, + DenseMap &ParentMap); + bool PerformCSE(MachineDomTreeNode *Node); + }; +} // end anonymous namespace + +char MachineCSE::ID = 0; +INITIALIZE_PASS_BEGIN(MachineCSE, "machine-cse", + "Machine Common Subexpression Elimination", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(MachineCSE, "machine-cse", + "Machine Common Subexpression Elimination", false, false) + +FunctionPass *llvm::createMachineCSEPass() { return new MachineCSE(); } + +bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI, + MachineBasicBlock *MBB) { + bool Changed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (!MRI->hasOneNonDBGUse(Reg)) + // Only coalesce single use copies. This ensure the copy will be + // deleted. + continue; + MachineInstr *DefMI = MRI->getVRegDef(Reg); + if (DefMI->getParent() != MBB) + continue; + if (!DefMI->isCopy()) + continue; + unsigned SrcReg = DefMI->getOperand(1).getReg(); + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) + continue; + if (DefMI->getOperand(0).getSubReg() || DefMI->getOperand(1).getSubReg()) + continue; + if (!MRI->constrainRegClass(SrcReg, MRI->getRegClass(Reg))) + continue; + DEBUG(dbgs() << "Coalescing: " << *DefMI); + DEBUG(dbgs() << "*** to: " << *MI); + MO.setReg(SrcReg); + MRI->clearKillFlags(SrcReg); + DefMI->eraseFromParent(); + ++NumCoalesces; + Changed = true; + } + + return Changed; +} + +bool +MachineCSE::isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E) const { + unsigned LookAheadLeft = LookAheadLimit; + while (LookAheadLeft) { + // Skip over dbg_value's. + while (I != E && I->isDebugValue()) + ++I; + + if (I == E) + // Reached end of block, register is obviously dead. + return true; + + bool SeenDef = false; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + if (!TRI->regsOverlap(MO.getReg(), Reg)) + continue; + if (MO.isUse()) + // Found a use! + return false; + SeenDef = true; + } + if (SeenDef) + // See a def of Reg (or an alias) before encountering any use, it's + // trivially dead. + return true; + + --LookAheadLeft; + ++I; + } + return false; +} + +/// hasLivePhysRegDefUses - Return true if the specified instruction read/write +/// physical registers (except for dead defs of physical registers). It also +/// returns the physical register def by reference if it's the only one and the +/// instruction does not uses a physical register. +bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI, + const MachineBasicBlock *MBB, + SmallSet &PhysRefs) const { + MachineBasicBlock::const_iterator I = MI; I = llvm::next(I); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + // If the def is dead, it's ok. But the def may not marked "dead". That's + // common since this pass is run before livevariables. We can scan + // forward a few instructions and check if it is obviously dead. + if (MO.isDef() && + (MO.isDead() || isPhysDefTriviallyDead(Reg, I, MBB->end()))) + continue; + PhysRefs.insert(Reg); + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) + PhysRefs.insert(*Alias); + } + + return !PhysRefs.empty(); +} + +bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, + SmallSet &PhysRefs) const { + // For now conservatively returns false if the common subexpression is + // not in the same basic block as the given instruction. + MachineBasicBlock *MBB = MI->getParent(); + if (CSMI->getParent() != MBB) + return false; + MachineBasicBlock::const_iterator I = CSMI; I = llvm::next(I); + MachineBasicBlock::const_iterator E = MI; + unsigned LookAheadLeft = LookAheadLimit; + while (LookAheadLeft) { + // Skip over dbg_value's. + while (I != E && I->isDebugValue()) + ++I; + + if (I == E) + return true; + + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned MOReg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + continue; + if (PhysRefs.count(MOReg)) + return false; + } + + --LookAheadLeft; + ++I; + } + + return false; +} + +bool MachineCSE::isCSECandidate(MachineInstr *MI) { + if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() || + MI->isKill() || MI->isInlineAsm() || MI->isDebugValue()) + return false; + + // Ignore copies. + if (MI->isCopyLike()) + return false; + + // Ignore stuff that we obviously can't move. + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayStore() || TID.isCall() || TID.isTerminator() || + MI->hasUnmodeledSideEffects()) + return false; + + if (TID.mayLoad()) { + // Okay, this instruction does a load. As a refinement, we allow the target + // to decide whether the loaded value is actually a constant. If so, we can + // actually use it as a load. + if (!MI->isInvariantLoad(AA)) + // FIXME: we should be able to hoist loads with no other side effects if + // there are no other instructions which can change memory in this loop. + // This is a trivial form of alias analysis. + return false; + } + return true; +} + +/// isProfitableToCSE - Return true if it's profitable to eliminate MI with a +/// common expression that defines Reg. +bool MachineCSE::isProfitableToCSE(unsigned CSReg, unsigned Reg, + MachineInstr *CSMI, MachineInstr *MI) { + // FIXME: Heuristics that works around the lack the live range splitting. + + // Heuristics #1: Don't CSE "cheap" computation if the def is not local or in + // an immediate predecessor. We don't want to increase register pressure and + // end up causing other computation to be spilled. + if (MI->getDesc().isAsCheapAsAMove()) { + MachineBasicBlock *CSBB = CSMI->getParent(); + MachineBasicBlock *BB = MI->getParent(); + if (CSBB != BB && !CSBB->isSuccessor(BB)) + return false; + } + + // Heuristics #2: If the expression doesn't not use a vr and the only use + // of the redundant computation are copies, do not cse. + bool HasVRegUse = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + HasVRegUse = true; + break; + } + } + if (!HasVRegUse) { + bool HasNonCopyUse = false; + for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg), + E = MRI->use_nodbg_end(); I != E; ++I) { + MachineInstr *Use = &*I; + // Ignore copies. + if (!Use->isCopyLike()) { + HasNonCopyUse = true; + break; + } + } + if (!HasNonCopyUse) + return false; + } + + // Heuristics #3: If the common subexpression is used by PHIs, do not reuse + // it unless the defined value is already used in the BB of the new use. + bool HasPHI = false; + SmallPtrSet CSBBs; + for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(CSReg), + E = MRI->use_nodbg_end(); I != E; ++I) { + MachineInstr *Use = &*I; + HasPHI |= Use->isPHI(); + CSBBs.insert(Use->getParent()); + } + + if (!HasPHI) + return true; + return CSBBs.count(MI->getParent()); +} + +void MachineCSE::EnterScope(MachineBasicBlock *MBB) { + DEBUG(dbgs() << "Entering: " << MBB->getName() << '\n'); + ScopeType *Scope = new ScopeType(VNT); + ScopeMap[MBB] = Scope; +} + +void MachineCSE::ExitScope(MachineBasicBlock *MBB) { + DEBUG(dbgs() << "Exiting: " << MBB->getName() << '\n'); + DenseMap::iterator SI = ScopeMap.find(MBB); + assert(SI != ScopeMap.end()); + ScopeMap.erase(SI); + delete SI->second; +} + +bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { + bool Changed = false; + + SmallVector, 8> CSEPairs; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) { + MachineInstr *MI = &*I; + ++I; + + if (!isCSECandidate(MI)) + continue; + + bool FoundCSE = VNT.count(MI); + if (!FoundCSE) { + // Look for trivial copy coalescing opportunities. + if (PerformTrivialCoalescing(MI, MBB)) { + // After coalescing MI itself may become a copy. + if (MI->isCopyLike()) + continue; + FoundCSE = VNT.count(MI); + } + } + + // Commute commutable instructions. + bool Commuted = false; + if (!FoundCSE && MI->getDesc().isCommutable()) { + MachineInstr *NewMI = TII->commuteInstruction(MI); + if (NewMI) { + Commuted = true; + FoundCSE = VNT.count(NewMI); + if (NewMI != MI) + // New instruction. It doesn't need to be kept. + NewMI->eraseFromParent(); + else if (!FoundCSE) + // MI was changed but it didn't help, commute it back! + (void)TII->commuteInstruction(MI); + } + } + + // If the instruction defines physical registers and the values *may* be + // used, then it's not safe to replace it with a common subexpression. + // It's also not safe if the instruction uses physical registers. + SmallSet PhysRefs; + if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs)) { + FoundCSE = false; + + // ... Unless the CS is local and it also defines the physical register + // which is not clobbered in between and the physical register uses + // were not clobbered. + unsigned CSVN = VNT.lookup(MI); + MachineInstr *CSMI = Exps[CSVN]; + if (PhysRegDefsReach(CSMI, MI, PhysRefs)) + FoundCSE = true; + } + + if (!FoundCSE) { + VNT.insert(MI, CurrVN++); + Exps.push_back(MI); + continue; + } + + // Found a common subexpression, eliminate it. + unsigned CSVN = VNT.lookup(MI); + MachineInstr *CSMI = Exps[CSVN]; + DEBUG(dbgs() << "Examining: " << *MI); + DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI); + + // Check if it's profitable to perform this CSE. + bool DoCSE = true; + unsigned NumDefs = MI->getDesc().getNumDefs(); + for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned OldReg = MO.getReg(); + unsigned NewReg = CSMI->getOperand(i).getReg(); + if (OldReg == NewReg) + continue; + assert(TargetRegisterInfo::isVirtualRegister(OldReg) && + TargetRegisterInfo::isVirtualRegister(NewReg) && + "Do not CSE physical register defs!"); + if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) { + DoCSE = false; + break; + } + CSEPairs.push_back(std::make_pair(OldReg, NewReg)); + --NumDefs; + } + + // Actually perform the elimination. + if (DoCSE) { + for (unsigned i = 0, e = CSEPairs.size(); i != e; ++i) { + MRI->replaceRegWith(CSEPairs[i].first, CSEPairs[i].second); + MRI->clearKillFlags(CSEPairs[i].second); + } + MI->eraseFromParent(); + ++NumCSEs; + if (!PhysRefs.empty()) + ++NumPhysCSEs; + if (Commuted) + ++NumCommutes; + } else { + DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n"); + VNT.insert(MI, CurrVN++); + Exps.push_back(MI); + } + CSEPairs.clear(); + } + + return Changed; +} + +/// ExitScopeIfDone - Destroy scope for the MBB that corresponds to the given +/// dominator tree node if its a leaf or all of its children are done. Walk +/// up the dominator tree to destroy ancestors which are now done. +void +MachineCSE::ExitScopeIfDone(MachineDomTreeNode *Node, + DenseMap &OpenChildren, + DenseMap &ParentMap) { + if (OpenChildren[Node]) + return; + + // Pop scope. + ExitScope(Node->getBlock()); + + // Now traverse upwards to pop ancestors whose offsprings are all done. + while (MachineDomTreeNode *Parent = ParentMap[Node]) { + unsigned Left = --OpenChildren[Parent]; + if (Left != 0) + break; + ExitScope(Parent->getBlock()); + Node = Parent; + } +} + +bool MachineCSE::PerformCSE(MachineDomTreeNode *Node) { + SmallVector Scopes; + SmallVector WorkList; + DenseMap ParentMap; + DenseMap OpenChildren; + + CurrVN = 0; + + // Perform a DFS walk to determine the order of visit. + WorkList.push_back(Node); + do { + Node = WorkList.pop_back_val(); + Scopes.push_back(Node); + const std::vector &Children = Node->getChildren(); + unsigned NumChildren = Children.size(); + OpenChildren[Node] = NumChildren; + for (unsigned i = 0; i != NumChildren; ++i) { + MachineDomTreeNode *Child = Children[i]; + ParentMap[Child] = Node; + WorkList.push_back(Child); + } + } while (!WorkList.empty()); + + // Now perform CSE. + bool Changed = false; + for (unsigned i = 0, e = Scopes.size(); i != e; ++i) { + MachineDomTreeNode *Node = Scopes[i]; + MachineBasicBlock *MBB = Node->getBlock(); + EnterScope(MBB); + Changed |= ProcessBlock(MBB); + // If it's a leaf node, it's done. Traverse upwards to pop ancestors. + ExitScopeIfDone(Node, OpenChildren, ParentMap); + } + + return Changed; +} + +bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + MRI = &MF.getRegInfo(); + AA = &getAnalysis(); + DT = &getAnalysis(); + return PerformCSE(DT->getRootNode()); +} diff --git a/final/lib/CodeGen/MachineDominators.cpp b/final/lib/CodeGen/MachineDominators.cpp new file mode 100644 index 00000000000..04c8ecbf9bd --- /dev/null +++ b/final/lib/CodeGen/MachineDominators.cpp @@ -0,0 +1,59 @@ +//===- MachineDominators.cpp - Machine Dominator Calculation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements simple dominator construction algorithms for finding +// forward dominators on machine functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +namespace llvm { +TEMPLATE_INSTANTIATION(class DomTreeNodeBase); +TEMPLATE_INSTANTIATION(class DominatorTreeBase); +} + +char MachineDominatorTree::ID = 0; + +INITIALIZE_PASS(MachineDominatorTree, "machinedomtree", + "MachineDominator Tree Construction", true, true) + +char &llvm::MachineDominatorsID = MachineDominatorTree::ID; + +void MachineDominatorTree::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool MachineDominatorTree::runOnMachineFunction(MachineFunction &F) { + DT->recalculate(F); + + return false; +} + +MachineDominatorTree::MachineDominatorTree() + : MachineFunctionPass(ID) { + initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); + DT = new DominatorTreeBase(false); +} + +MachineDominatorTree::~MachineDominatorTree() { + delete DT; +} + +void MachineDominatorTree::releaseMemory() { + DT->releaseMemory(); +} + +void MachineDominatorTree::print(raw_ostream &OS, const Module*) const { + DT->print(OS); +} diff --git a/final/lib/CodeGen/MachineFunction.cpp b/final/lib/CodeGen/MachineFunction.cpp new file mode 100644 index 00000000000..d81e4a1d015 --- /dev/null +++ b/final/lib/CodeGen/MachineFunction.cpp @@ -0,0 +1,752 @@ +//===-- MachineFunction.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect native machine code information for a function. This allows +// target-specific information about the generated code to be stored with each +// function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Config/config.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachineFunction implementation +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +MachineFunctionInfo::~MachineFunctionInfo() {} + +void ilist_traits::deleteNode(MachineBasicBlock *MBB) { + MBB->getParent()->DeleteMachineBasicBlock(MBB); +} + +MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM, + unsigned FunctionNum, MachineModuleInfo &mmi, + GCModuleInfo* gmi) + : Fn(F), Target(TM), Ctx(mmi.getContext()), MMI(mmi), GMI(gmi) { + if (TM.getRegisterInfo()) + RegInfo = new (Allocator) MachineRegisterInfo(*TM.getRegisterInfo()); + else + RegInfo = 0; + MFInfo = 0; + FrameInfo = new (Allocator) MachineFrameInfo(*TM.getFrameLowering()); + if (Fn->hasFnAttr(Attribute::StackAlignment)) + FrameInfo->setMaxAlignment(Attribute::getStackAlignmentFromAttrs( + Fn->getAttributes().getFnAttributes())); + ConstantPool = new (Allocator) MachineConstantPool(TM.getTargetData()); + Alignment = TM.getTargetLowering()->getFunctionAlignment(F); + FunctionNumber = FunctionNum; + JumpTableInfo = 0; +} + +MachineFunction::~MachineFunction() { + BasicBlocks.clear(); + InstructionRecycler.clear(Allocator); + BasicBlockRecycler.clear(Allocator); + if (RegInfo) { + RegInfo->~MachineRegisterInfo(); + Allocator.Deallocate(RegInfo); + } + if (MFInfo) { + MFInfo->~MachineFunctionInfo(); + Allocator.Deallocate(MFInfo); + } + FrameInfo->~MachineFrameInfo(); Allocator.Deallocate(FrameInfo); + ConstantPool->~MachineConstantPool(); Allocator.Deallocate(ConstantPool); + + if (JumpTableInfo) { + JumpTableInfo->~MachineJumpTableInfo(); + Allocator.Deallocate(JumpTableInfo); + } +} + +/// getOrCreateJumpTableInfo - Get the JumpTableInfo for this function, if it +/// does already exist, allocate one. +MachineJumpTableInfo *MachineFunction:: +getOrCreateJumpTableInfo(unsigned EntryKind) { + if (JumpTableInfo) return JumpTableInfo; + + JumpTableInfo = new (Allocator) + MachineJumpTableInfo((MachineJumpTableInfo::JTEntryKind)EntryKind); + return JumpTableInfo; +} + +/// RenumberBlocks - This discards all of the MachineBasicBlock numbers and +/// recomputes them. This guarantees that the MBB numbers are sequential, +/// dense, and match the ordering of the blocks within the function. If a +/// specific MachineBasicBlock is specified, only that block and those after +/// it are renumbered. +void MachineFunction::RenumberBlocks(MachineBasicBlock *MBB) { + if (empty()) { MBBNumbering.clear(); return; } + MachineFunction::iterator MBBI, E = end(); + if (MBB == 0) + MBBI = begin(); + else + MBBI = MBB; + + // Figure out the block number this should have. + unsigned BlockNo = 0; + if (MBBI != begin()) + BlockNo = prior(MBBI)->getNumber()+1; + + for (; MBBI != E; ++MBBI, ++BlockNo) { + if (MBBI->getNumber() != (int)BlockNo) { + // Remove use of the old number. + if (MBBI->getNumber() != -1) { + assert(MBBNumbering[MBBI->getNumber()] == &*MBBI && + "MBB number mismatch!"); + MBBNumbering[MBBI->getNumber()] = 0; + } + + // If BlockNo is already taken, set that block's number to -1. + if (MBBNumbering[BlockNo]) + MBBNumbering[BlockNo]->setNumber(-1); + + MBBNumbering[BlockNo] = MBBI; + MBBI->setNumber(BlockNo); + } + } + + // Okay, all the blocks are renumbered. If we have compactified the block + // numbering, shrink MBBNumbering now. + assert(BlockNo <= MBBNumbering.size() && "Mismatch!"); + MBBNumbering.resize(BlockNo); +} + +/// CreateMachineInstr - Allocate a new MachineInstr. Use this instead +/// of `new MachineInstr'. +/// +MachineInstr * +MachineFunction::CreateMachineInstr(const TargetInstrDesc &TID, + DebugLoc DL, bool NoImp) { + return new (InstructionRecycler.Allocate(Allocator)) + MachineInstr(TID, DL, NoImp); +} + +/// CloneMachineInstr - Create a new MachineInstr which is a copy of the +/// 'Orig' instruction, identical in all ways except the instruction +/// has no parent, prev, or next. +/// +MachineInstr * +MachineFunction::CloneMachineInstr(const MachineInstr *Orig) { + return new (InstructionRecycler.Allocate(Allocator)) + MachineInstr(*this, *Orig); +} + +/// DeleteMachineInstr - Delete the given MachineInstr. +/// +void +MachineFunction::DeleteMachineInstr(MachineInstr *MI) { + MI->~MachineInstr(); + InstructionRecycler.Deallocate(Allocator, MI); +} + +/// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this +/// instead of `new MachineBasicBlock'. +/// +MachineBasicBlock * +MachineFunction::CreateMachineBasicBlock(const BasicBlock *bb) { + return new (BasicBlockRecycler.Allocate(Allocator)) + MachineBasicBlock(*this, bb); +} + +/// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. +/// +void +MachineFunction::DeleteMachineBasicBlock(MachineBasicBlock *MBB) { + assert(MBB->getParent() == this && "MBB parent mismatch!"); + MBB->~MachineBasicBlock(); + BasicBlockRecycler.Deallocate(Allocator, MBB); +} + +MachineMemOperand * +MachineFunction::getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, + uint64_t s, unsigned base_alignment, + const MDNode *TBAAInfo) { + return new (Allocator) MachineMemOperand(PtrInfo, f, s, base_alignment, + TBAAInfo); +} + +MachineMemOperand * +MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size) { + return new (Allocator) + MachineMemOperand(MachinePointerInfo(MMO->getValue(), + MMO->getOffset()+Offset), + MMO->getFlags(), Size, + MMO->getBaseAlignment(), 0); +} + +MachineInstr::mmo_iterator +MachineFunction::allocateMemRefsArray(unsigned long Num) { + return Allocator.Allocate(Num); +} + +std::pair +MachineFunction::extractLoadMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End) { + // Count the number of load mem refs. + unsigned Num = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) + if ((*I)->isLoad()) + ++Num; + + // Allocate a new array and populate it with the load information. + MachineInstr::mmo_iterator Result = allocateMemRefsArray(Num); + unsigned Index = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) { + if ((*I)->isLoad()) { + if (!(*I)->isStore()) + // Reuse the MMO. + Result[Index] = *I; + else { + // Clone the MMO and unset the store flag. + MachineMemOperand *JustLoad = + getMachineMemOperand((*I)->getPointerInfo(), + (*I)->getFlags() & ~MachineMemOperand::MOStore, + (*I)->getSize(), (*I)->getBaseAlignment(), + (*I)->getTBAAInfo()); + Result[Index] = JustLoad; + } + ++Index; + } + } + return std::make_pair(Result, Result + Num); +} + +std::pair +MachineFunction::extractStoreMemRefs(MachineInstr::mmo_iterator Begin, + MachineInstr::mmo_iterator End) { + // Count the number of load mem refs. + unsigned Num = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) + if ((*I)->isStore()) + ++Num; + + // Allocate a new array and populate it with the store information. + MachineInstr::mmo_iterator Result = allocateMemRefsArray(Num); + unsigned Index = 0; + for (MachineInstr::mmo_iterator I = Begin; I != End; ++I) { + if ((*I)->isStore()) { + if (!(*I)->isLoad()) + // Reuse the MMO. + Result[Index] = *I; + else { + // Clone the MMO and unset the load flag. + MachineMemOperand *JustStore = + getMachineMemOperand((*I)->getPointerInfo(), + (*I)->getFlags() & ~MachineMemOperand::MOLoad, + (*I)->getSize(), (*I)->getBaseAlignment(), + (*I)->getTBAAInfo()); + Result[Index] = JustStore; + } + ++Index; + } + } + return std::make_pair(Result, Result + Num); +} + +void MachineFunction::dump() const { + print(dbgs()); +} + +void MachineFunction::print(raw_ostream &OS, SlotIndexes *Indexes) const { + OS << "# Machine code for function " << Fn->getName() << ":\n"; + + // Print Frame Information + FrameInfo->print(*this, OS); + + // Print JumpTable Information + if (JumpTableInfo) + JumpTableInfo->print(OS); + + // Print Constant Pool + ConstantPool->print(OS); + + const TargetRegisterInfo *TRI = getTarget().getRegisterInfo(); + + if (RegInfo && !RegInfo->livein_empty()) { + OS << "Function Live Ins: "; + for (MachineRegisterInfo::livein_iterator + I = RegInfo->livein_begin(), E = RegInfo->livein_end(); I != E; ++I) { + if (TRI) + OS << "%" << TRI->getName(I->first); + else + OS << " %physreg" << I->first; + + if (I->second) + OS << " in reg%" << I->second; + + if (llvm::next(I) != E) + OS << ", "; + } + OS << '\n'; + } + if (RegInfo && !RegInfo->liveout_empty()) { + OS << "Function Live Outs: "; + for (MachineRegisterInfo::liveout_iterator + I = RegInfo->liveout_begin(), E = RegInfo->liveout_end(); I != E; ++I){ + if (TRI) + OS << '%' << TRI->getName(*I); + else + OS << "%physreg" << *I; + + if (llvm::next(I) != E) + OS << " "; + } + OS << '\n'; + } + + for (const_iterator BB = begin(), E = end(); BB != E; ++BB) { + OS << '\n'; + BB->print(OS, Indexes); + } + + OS << "\n# End machine code for function " << Fn->getName() << ".\n\n"; +} + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(const MachineFunction *F) { + return "CFG for '" + F->getFunction()->getNameStr() + "' function"; + } + + std::string getNodeLabel(const MachineBasicBlock *Node, + const MachineFunction *Graph) { + std::string OutStr; + { + raw_string_ostream OSS(OutStr); + + if (isSimple()) { + OSS << "BB#" << Node->getNumber(); + if (const BasicBlock *BB = Node->getBasicBlock()) + OSS << ": " << BB->getName(); + } else + Node->print(OSS); + } + + if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); + + // Process string output to make it nicer... + for (unsigned i = 0; i != OutStr.length(); ++i) + if (OutStr[i] == '\n') { // Left justify + OutStr[i] = '\\'; + OutStr.insert(OutStr.begin()+i+1, 'l'); + } + return OutStr; + } + }; +} + +void MachineFunction::viewCFG() const +{ +#ifndef NDEBUG + ViewGraph(this, "mf" + getFunction()->getNameStr()); +#else + errs() << "MachineFunction::viewCFG is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +void MachineFunction::viewCFGOnly() const +{ +#ifndef NDEBUG + ViewGraph(this, "mf" + getFunction()->getNameStr(), true); +#else + errs() << "MachineFunction::viewCFGOnly is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +/// addLiveIn - Add the specified physical register as a live-in value and +/// create a corresponding virtual register for it. +unsigned MachineFunction::addLiveIn(unsigned PReg, + const TargetRegisterClass *RC) { + MachineRegisterInfo &MRI = getRegInfo(); + unsigned VReg = MRI.getLiveInVirtReg(PReg); + if (VReg) { + assert(MRI.getRegClass(VReg) == RC && "Register class mismatch!"); + return VReg; + } + VReg = MRI.createVirtualRegister(RC); + MRI.addLiveIn(PReg, VReg); + return VReg; +} + +/// getJTISymbol - Return the MCSymbol for the specified non-empty jump table. +/// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a +/// normal 'L' label is returned. +MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx, + bool isLinkerPrivate) const { + assert(JumpTableInfo && "No jump tables"); + + assert(JTI < JumpTableInfo->getJumpTables().size() && "Invalid JTI!"); + const MCAsmInfo &MAI = *getTarget().getMCAsmInfo(); + + const char *Prefix = isLinkerPrivate ? MAI.getLinkerPrivateGlobalPrefix() : + MAI.getPrivateGlobalPrefix(); + SmallString<60> Name; + raw_svector_ostream(Name) + << Prefix << "JTI" << getFunctionNumber() << '_' << JTI; + return Ctx.GetOrCreateSymbol(Name.str()); +} + +/// getPICBaseSymbol - Return a function-local symbol to represent the PIC +/// base. +MCSymbol *MachineFunction::getPICBaseSymbol() const { + const MCAsmInfo &MAI = *Target.getMCAsmInfo(); + return Ctx.GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix())+ + Twine(getFunctionNumber())+"$pb"); +} + +//===----------------------------------------------------------------------===// +// MachineFrameInfo implementation +//===----------------------------------------------------------------------===// + +/// CreateFixedObject - Create a new object at a fixed location on the stack. +/// All fixed objects should be created before other objects are created for +/// efficiency. By default, fixed objects are immutable. This returns an +/// index with a negative value. +/// +int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset, + bool Immutable) { + assert(Size != 0 && "Cannot allocate zero size fixed stack objects!"); + // The alignment of the frame index can be determined from its offset from + // the incoming frame position. If the frame object is at offset 32 and + // the stack is guaranteed to be 16-byte aligned, then we know that the + // object is 16-byte aligned. + unsigned StackAlign = TFI.getStackAlignment(); + unsigned Align = MinAlign(SPOffset, StackAlign); + Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable, + /*isSS*/false, false)); + return -++NumFixedObjects; +} + + +BitVector +MachineFrameInfo::getPristineRegs(const MachineBasicBlock *MBB) const { + assert(MBB && "MBB must be valid"); + const MachineFunction *MF = MBB->getParent(); + assert(MF && "MBB must be part of a MachineFunction"); + const TargetMachine &TM = MF->getTarget(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + BitVector BV(TRI->getNumRegs()); + + // Before CSI is calculated, no registers are considered pristine. They can be + // freely used and PEI will make sure they are saved. + if (!isCalleeSavedInfoValid()) + return BV; + + for (const unsigned *CSR = TRI->getCalleeSavedRegs(MF); CSR && *CSR; ++CSR) + BV.set(*CSR); + + // The entry MBB always has all CSRs pristine. + if (MBB == &MF->front()) + return BV; + + // On other MBBs the saved CSRs are not pristine. + const std::vector &CSI = getCalleeSavedInfo(); + for (std::vector::const_iterator I = CSI.begin(), + E = CSI.end(); I != E; ++I) + BV.reset(I->getReg()); + + return BV; +} + + +void MachineFrameInfo::print(const MachineFunction &MF, raw_ostream &OS) const{ + if (Objects.empty()) return; + + const TargetFrameLowering *FI = MF.getTarget().getFrameLowering(); + int ValOffset = (FI ? FI->getOffsetOfLocalArea() : 0); + + OS << "Frame Objects:\n"; + + for (unsigned i = 0, e = Objects.size(); i != e; ++i) { + const StackObject &SO = Objects[i]; + OS << " fi#" << (int)(i-NumFixedObjects) << ": "; + if (SO.Size == ~0ULL) { + OS << "dead\n"; + continue; + } + if (SO.Size == 0) + OS << "variable sized"; + else + OS << "size=" << SO.Size; + OS << ", align=" << SO.Alignment; + + if (i < NumFixedObjects) + OS << ", fixed"; + if (i < NumFixedObjects || SO.SPOffset != -1) { + int64_t Off = SO.SPOffset - ValOffset; + OS << ", at location [SP"; + if (Off > 0) + OS << "+" << Off; + else if (Off < 0) + OS << Off; + OS << "]"; + } + OS << "\n"; + } +} + +void MachineFrameInfo::dump(const MachineFunction &MF) const { + print(MF, dbgs()); +} + +//===----------------------------------------------------------------------===// +// MachineJumpTableInfo implementation +//===----------------------------------------------------------------------===// + +/// getEntrySize - Return the size of each entry in the jump table. +unsigned MachineJumpTableInfo::getEntrySize(const TargetData &TD) const { + // The size of a jump table entry is 4 bytes unless the entry is just the + // address of a block, in which case it is the pointer size. + switch (getEntryKind()) { + case MachineJumpTableInfo::EK_BlockAddress: + return TD.getPointerSize(); + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_Custom32: + return 4; + case MachineJumpTableInfo::EK_Inline: + return 0; + } + assert(0 && "Unknown jump table encoding!"); + return ~0; +} + +/// getEntryAlignment - Return the alignment of each entry in the jump table. +unsigned MachineJumpTableInfo::getEntryAlignment(const TargetData &TD) const { + // The alignment of a jump table entry is the alignment of int32 unless the + // entry is just the address of a block, in which case it is the pointer + // alignment. + switch (getEntryKind()) { + case MachineJumpTableInfo::EK_BlockAddress: + return TD.getPointerABIAlignment(); + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_Custom32: + return TD.getABIIntegerTypeAlignment(32); + case MachineJumpTableInfo::EK_Inline: + return 1; + } + assert(0 && "Unknown jump table encoding!"); + return ~0; +} + +/// createJumpTableIndex - Create a new jump table entry in the jump table info. +/// +unsigned MachineJumpTableInfo::createJumpTableIndex( + const std::vector &DestBBs) { + assert(!DestBBs.empty() && "Cannot create an empty jump table!"); + JumpTables.push_back(MachineJumpTableEntry(DestBBs)); + return JumpTables.size()-1; +} + +/// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update +/// the jump tables to branch to New instead. +bool MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Not making a change?"); + bool MadeChange = false; + for (size_t i = 0, e = JumpTables.size(); i != e; ++i) + ReplaceMBBInJumpTable(i, Old, New); + return MadeChange; +} + +/// ReplaceMBBInJumpTable - If Old is a target of the jump tables, update +/// the jump table to branch to New instead. +bool MachineJumpTableInfo::ReplaceMBBInJumpTable(unsigned Idx, + MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Not making a change?"); + bool MadeChange = false; + MachineJumpTableEntry &JTE = JumpTables[Idx]; + for (size_t j = 0, e = JTE.MBBs.size(); j != e; ++j) + if (JTE.MBBs[j] == Old) { + JTE.MBBs[j] = New; + MadeChange = true; + } + return MadeChange; +} + +void MachineJumpTableInfo::print(raw_ostream &OS) const { + if (JumpTables.empty()) return; + + OS << "Jump Tables:\n"; + + for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) { + OS << " jt#" << i << ": "; + for (unsigned j = 0, f = JumpTables[i].MBBs.size(); j != f; ++j) + OS << " BB#" << JumpTables[i].MBBs[j]->getNumber(); + } + + OS << '\n'; +} + +void MachineJumpTableInfo::dump() const { print(dbgs()); } + + +//===----------------------------------------------------------------------===// +// MachineConstantPool implementation +//===----------------------------------------------------------------------===// + +const Type *MachineConstantPoolEntry::getType() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getType(); + return Val.ConstVal->getType(); +} + + +unsigned MachineConstantPoolEntry::getRelocationInfo() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getRelocationInfo(); + return Val.ConstVal->getRelocationInfo(); +} + +MachineConstantPool::~MachineConstantPool() { + for (unsigned i = 0, e = Constants.size(); i != e; ++i) + if (Constants[i].isMachineConstantPoolEntry()) + delete Constants[i].Val.MachineCPVal; + for (DenseSet::iterator I = + MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end(); + I != E; ++I) + delete *I; +} + +/// CanShareConstantPoolEntry - Test whether the given two constants +/// can be allocated the same constant pool entry. +static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B, + const TargetData *TD) { + // Handle the trivial case quickly. + if (A == B) return true; + + // If they have the same type but weren't the same constant, quickly + // reject them. + if (A->getType() == B->getType()) return false; + + // For now, only support constants with the same size. + if (TD->getTypeStoreSize(A->getType()) != TD->getTypeStoreSize(B->getType())) + return false; + + // If a floating-point value and an integer value have the same encoding, + // they can share a constant-pool entry. + if (const ConstantFP *AFP = dyn_cast(A)) + if (const ConstantInt *BI = dyn_cast(B)) + return AFP->getValueAPF().bitcastToAPInt() == BI->getValue(); + if (const ConstantFP *BFP = dyn_cast(B)) + if (const ConstantInt *AI = dyn_cast(A)) + return BFP->getValueAPF().bitcastToAPInt() == AI->getValue(); + + // Two vectors can share an entry if each pair of corresponding + // elements could. + if (const ConstantVector *AV = dyn_cast(A)) + if (const ConstantVector *BV = dyn_cast(B)) { + if (AV->getType()->getNumElements() != BV->getType()->getNumElements()) + return false; + for (unsigned i = 0, e = AV->getType()->getNumElements(); i != e; ++i) + if (!CanShareConstantPoolEntry(AV->getOperand(i), + BV->getOperand(i), TD)) + return false; + return true; + } + + // TODO: Handle other cases. + + return false; +} + +/// getConstantPoolIndex - Create a new entry in the constant pool or return +/// an existing one. User must specify the log2 of the minimum required +/// alignment for the object. +/// +unsigned MachineConstantPool::getConstantPoolIndex(const Constant *C, + unsigned Alignment) { + assert(Alignment && "Alignment must be specified!"); + if (Alignment > PoolAlignment) PoolAlignment = Alignment; + + // Check to see if we already have this constant. + // + // FIXME, this could be made much more efficient for large constant pools. + for (unsigned i = 0, e = Constants.size(); i != e; ++i) + if (!Constants[i].isMachineConstantPoolEntry() && + CanShareConstantPoolEntry(Constants[i].Val.ConstVal, C, TD)) { + if ((unsigned)Constants[i].getAlignment() < Alignment) + Constants[i].Alignment = Alignment; + return i; + } + + Constants.push_back(MachineConstantPoolEntry(C, Alignment)); + return Constants.size()-1; +} + +unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V, + unsigned Alignment) { + assert(Alignment && "Alignment must be specified!"); + if (Alignment > PoolAlignment) PoolAlignment = Alignment; + + // Check to see if we already have this constant. + // + // FIXME, this could be made much more efficient for large constant pools. + int Idx = V->getExistingMachineCPValue(this, Alignment); + if (Idx != -1) { + MachineCPVsSharingEntries.insert(V); + return (unsigned)Idx; + } + + Constants.push_back(MachineConstantPoolEntry(V, Alignment)); + return Constants.size()-1; +} + +void MachineConstantPool::print(raw_ostream &OS) const { + if (Constants.empty()) return; + + OS << "Constant Pool:\n"; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + OS << " cp#" << i << ": "; + if (Constants[i].isMachineConstantPoolEntry()) + Constants[i].Val.MachineCPVal->print(OS); + else + OS << *(Value*)Constants[i].Val.ConstVal; + OS << ", align=" << Constants[i].getAlignment(); + OS << "\n"; + } +} + +void MachineConstantPool::dump() const { print(dbgs()); } diff --git a/final/lib/CodeGen/MachineFunctionAnalysis.cpp b/final/lib/CodeGen/MachineFunctionAnalysis.cpp new file mode 100644 index 00000000000..054c750c9f2 --- /dev/null +++ b/final/lib/CodeGen/MachineFunctionAnalysis.cpp @@ -0,0 +1,58 @@ +//===-- MachineFunctionAnalysis.cpp ---------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definitions of the MachineFunctionAnalysis members. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +using namespace llvm; + +char MachineFunctionAnalysis::ID = 0; + +MachineFunctionAnalysis::MachineFunctionAnalysis(const TargetMachine &tm, + CodeGenOpt::Level OL) : + FunctionPass(ID), TM(tm), OptLevel(OL), MF(0) { + initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); +} + +MachineFunctionAnalysis::~MachineFunctionAnalysis() { + releaseMemory(); + assert(!MF && "MachineFunctionAnalysis left initialized!"); +} + +void MachineFunctionAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); +} + +bool MachineFunctionAnalysis::doInitialization(Module &M) { + MachineModuleInfo *MMI = getAnalysisIfAvailable(); + assert(MMI && "MMI not around yet??"); + MMI->setModule(&M); + NextFnNum = 0; + return false; +} + + +bool MachineFunctionAnalysis::runOnFunction(Function &F) { + assert(!MF && "MachineFunctionAnalysis already initialized!"); + MF = new MachineFunction(&F, TM, NextFnNum++, + getAnalysis(), + getAnalysisIfAvailable()); + return false; +} + +void MachineFunctionAnalysis::releaseMemory() { + delete MF; + MF = 0; +} diff --git a/final/lib/CodeGen/MachineFunctionPass.cpp b/final/lib/CodeGen/MachineFunctionPass.cpp new file mode 100644 index 00000000000..e5a491270a8 --- /dev/null +++ b/final/lib/CodeGen/MachineFunctionPass.cpp @@ -0,0 +1,56 @@ +//===-- MachineFunctionPass.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the definitions of the MachineFunctionPass members. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFunctionAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/Passes.h" +using namespace llvm; + +Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, + const std::string &Banner) const { + return createMachineFunctionPrinterPass(O, Banner); +} + +bool MachineFunctionPass::runOnFunction(Function &F) { + // Do not codegen any 'available_externally' functions at all, they have + // definitions outside the translation unit. + if (F.hasAvailableExternallyLinkage()) + return false; + + MachineFunction &MF = getAnalysis().getMF(); + return runOnMachineFunction(MF); +} + +void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); + + // MachineFunctionPass preserves all LLVM IR passes, but there's no + // high-level way to express this. Instead, just list a bunch of + // passes explicitly. This does not include setPreservesCFG, + // because CodeGen overloads that to mean preserving the MachineBasicBlock + // CFG in addition to the LLVM IR CFG. + AU.addPreserved(); + AU.addPreserved("scalar-evolution"); + AU.addPreserved("iv-users"); + AU.addPreserved("memdep"); + AU.addPreserved("live-values"); + AU.addPreserved("domtree"); + AU.addPreserved("domfrontier"); + AU.addPreserved("loops"); + AU.addPreserved("lda"); + + FunctionPass::getAnalysisUsage(AU); +} diff --git a/final/lib/CodeGen/MachineFunctionPrinterPass.cpp b/final/lib/CodeGen/MachineFunctionPrinterPass.cpp new file mode 100644 index 00000000000..2aaa798a02c --- /dev/null +++ b/final/lib/CodeGen/MachineFunctionPrinterPass.cpp @@ -0,0 +1,60 @@ +//===-- MachineFunctionPrinterPass.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// MachineFunctionPrinterPass implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +/// MachineFunctionPrinterPass - This is a pass to dump the IR of a +/// MachineFunction. +/// +struct MachineFunctionPrinterPass : public MachineFunctionPass { + static char ID; + + raw_ostream &OS; + const std::string Banner; + + MachineFunctionPrinterPass(raw_ostream &os, const std::string &banner) + : MachineFunctionPass(ID), OS(os), Banner(banner) {} + + const char *getPassName() const { return "MachineFunction Printer"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) { + OS << "# " << Banner << ":\n"; + MF.print(OS); + return false; + } +}; + +char MachineFunctionPrinterPass::ID = 0; +} + +namespace llvm { +/// Returns a newly-created MachineFunction Printer pass. The +/// default banner is empty. +/// +MachineFunctionPass *createMachineFunctionPrinterPass(raw_ostream &OS, + const std::string &Banner){ + return new MachineFunctionPrinterPass(OS, Banner); +} + +} diff --git a/final/lib/CodeGen/MachineInstr.cpp b/final/lib/CodeGen/MachineInstr.cpp new file mode 100644 index 00000000000..dce05d3e3f4 --- /dev/null +++ b/final/lib/CodeGen/MachineInstr.cpp @@ -0,0 +1,1671 @@ +//===-- lib/CodeGen/MachineInstr.cpp --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods common to all machine instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/Metadata.h" +#include "llvm/Type.h" +#include "llvm/Value.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrDesc.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LeakDetector.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/FoldingSet.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachineOperand Implementation +//===----------------------------------------------------------------------===// + +/// AddRegOperandToRegInfo - Add this register operand to the specified +/// MachineRegisterInfo. If it is null, then the next/prev fields should be +/// explicitly nulled out. +void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { + assert(isReg() && "Can only add reg operand to use lists"); + + // If the reginfo pointer is null, just explicitly null out or next/prev + // pointers, to ensure they are not garbage. + if (RegInfo == 0) { + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; + return; + } + + // Otherwise, add this operand to the head of the registers use/def list. + MachineOperand **Head = &RegInfo->getRegUseDefListHead(getReg()); + + // For SSA values, we prefer to keep the definition at the start of the list. + // we do this by skipping over the definition if it is at the head of the + // list. + if (*Head && (*Head)->isDef()) + Head = &(*Head)->Contents.Reg.Next; + + Contents.Reg.Next = *Head; + if (Contents.Reg.Next) { + assert(getReg() == Contents.Reg.Next->getReg() && + "Different regs on the same list!"); + Contents.Reg.Next->Contents.Reg.Prev = &Contents.Reg.Next; + } + + Contents.Reg.Prev = Head; + *Head = this; +} + +/// RemoveRegOperandFromRegInfo - Remove this register operand from the +/// MachineRegisterInfo it is linked with. +void MachineOperand::RemoveRegOperandFromRegInfo() { + assert(isOnRegUseList() && "Reg operand is not on a use list"); + // Unlink this from the doubly linked list of operands. + MachineOperand *NextOp = Contents.Reg.Next; + *Contents.Reg.Prev = NextOp; + if (NextOp) { + assert(NextOp->getReg() == getReg() && "Corrupt reg use/def chain!"); + NextOp->Contents.Reg.Prev = Contents.Reg.Prev; + } + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; +} + +void MachineOperand::setReg(unsigned Reg) { + if (getReg() == Reg) return; // No change. + + // Otherwise, we have to change the register. If this operand is embedded + // into a machine function, we need to update the old and new register's + // use/def lists. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) { + RemoveRegOperandFromRegInfo(); + SmallContents.RegNo = Reg; + AddRegOperandToRegInfo(&MF->getRegInfo()); + return; + } + + // Otherwise, just change the register, no problem. :) + SmallContents.RegNo = Reg; +} + +void MachineOperand::substVirtReg(unsigned Reg, unsigned SubIdx, + const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::isVirtualRegister(Reg)); + if (SubIdx && getSubReg()) + SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); + setReg(Reg); + if (SubIdx) + setSubReg(SubIdx); +} + +void MachineOperand::substPhysReg(unsigned Reg, const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + if (getSubReg()) { + Reg = TRI.getSubReg(Reg, getSubReg()); + assert(Reg && "Invalid SubReg for physical register"); + setSubReg(0); + } + setReg(Reg); +} + +/// ChangeToImmediate - Replace this operand with a new immediate operand of +/// the specified value. If an operand is known to be an immediate already, +/// the setImm method should be used. +void MachineOperand::ChangeToImmediate(int64_t ImmVal) { + // If this operand is currently a register operand, and if this is in a + // function, deregister the operand from the register's use/def list. + if (isReg() && getParent() && getParent()->getParent() && + getParent()->getParent()->getParent()) + RemoveRegOperandFromRegInfo(); + + OpKind = MO_Immediate; + Contents.ImmVal = ImmVal; +} + +/// ChangeToRegister - Replace this operand with a new register operand of +/// the specified value. If an operand is known to be an register already, +/// the setReg method should be used. +void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, + bool isKill, bool isDead, bool isUndef, + bool isDebug) { + // If this operand is already a register operand, use setReg to update the + // register's use/def lists. + if (isReg()) { + assert(!isEarlyClobber()); + setReg(Reg); + } else { + // Otherwise, change this to a register and set the reg#. + OpKind = MO_Register; + SmallContents.RegNo = Reg; + + // If this operand is embedded in a function, add the operand to the + // register's use/def list. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) + AddRegOperandToRegInfo(&MF->getRegInfo()); + } + + IsDef = isDef; + IsImp = isImp; + IsKill = isKill; + IsDead = isDead; + IsUndef = isUndef; + IsEarlyClobber = false; + IsDebug = isDebug; + SubReg = 0; +} + +/// isIdenticalTo - Return true if this operand is identical to the specified +/// operand. +bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { + if (getType() != Other.getType() || + getTargetFlags() != Other.getTargetFlags()) + return false; + + switch (getType()) { + default: llvm_unreachable("Unrecognized operand type"); + case MachineOperand::MO_Register: + return getReg() == Other.getReg() && isDef() == Other.isDef() && + getSubReg() == Other.getSubReg(); + case MachineOperand::MO_Immediate: + return getImm() == Other.getImm(); + case MachineOperand::MO_FPImmediate: + return getFPImm() == Other.getFPImm(); + case MachineOperand::MO_MachineBasicBlock: + return getMBB() == Other.getMBB(); + case MachineOperand::MO_FrameIndex: + return getIndex() == Other.getIndex(); + case MachineOperand::MO_ConstantPoolIndex: + return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); + case MachineOperand::MO_JumpTableIndex: + return getIndex() == Other.getIndex(); + case MachineOperand::MO_GlobalAddress: + return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); + case MachineOperand::MO_ExternalSymbol: + return !strcmp(getSymbolName(), Other.getSymbolName()) && + getOffset() == Other.getOffset(); + case MachineOperand::MO_BlockAddress: + return getBlockAddress() == Other.getBlockAddress(); + case MachineOperand::MO_MCSymbol: + return getMCSymbol() == Other.getMCSymbol(); + case MachineOperand::MO_Metadata: + return getMetadata() == Other.getMetadata(); + } +} + +/// print - Print the specified machine operand. +/// +void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { + // If the instruction is embedded into a basic block, we can find the + // target info for the instruction. + if (!TM) + if (const MachineInstr *MI = getParent()) + if (const MachineBasicBlock *MBB = MI->getParent()) + if (const MachineFunction *MF = MBB->getParent()) + TM = &MF->getTarget(); + const TargetRegisterInfo *TRI = TM ? TM->getRegisterInfo() : 0; + + switch (getType()) { + case MachineOperand::MO_Register: + OS << PrintReg(getReg(), TRI, getSubReg()); + + if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || + isEarlyClobber()) { + OS << '<'; + bool NeedComma = false; + if (isDef()) { + if (NeedComma) OS << ','; + if (isEarlyClobber()) + OS << "earlyclobber,"; + if (isImplicit()) + OS << "imp-"; + OS << "def"; + NeedComma = true; + } else if (isImplicit()) { + OS << "imp-use"; + NeedComma = true; + } + + if (isKill() || isDead() || isUndef()) { + if (NeedComma) OS << ','; + if (isKill()) OS << "kill"; + if (isDead()) OS << "dead"; + if (isUndef()) { + if (isKill() || isDead()) + OS << ','; + OS << "undef"; + } + } + OS << '>'; + } + break; + case MachineOperand::MO_Immediate: + OS << getImm(); + break; + case MachineOperand::MO_FPImmediate: + if (getFPImm()->getType()->isFloatTy()) + OS << getFPImm()->getValueAPF().convertToFloat(); + else + OS << getFPImm()->getValueAPF().convertToDouble(); + break; + case MachineOperand::MO_MachineBasicBlock: + OS << "getNumber() << ">"; + break; + case MachineOperand::MO_FrameIndex: + OS << "'; + break; + case MachineOperand::MO_ConstantPoolIndex: + OS << "'; + break; + case MachineOperand::MO_JumpTableIndex: + OS << "'; + break; + case MachineOperand::MO_GlobalAddress: + OS << "'; + break; + case MachineOperand::MO_ExternalSymbol: + OS << "'; + break; + case MachineOperand::MO_BlockAddress: + OS << '<'; + WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false); + OS << '>'; + break; + case MachineOperand::MO_Metadata: + OS << '<'; + WriteAsOperand(OS, getMetadata(), /*PrintType=*/false); + OS << '>'; + break; + case MachineOperand::MO_MCSymbol: + OS << "'; + break; + default: + llvm_unreachable("Unrecognized operand type"); + } + + if (unsigned TF = getTargetFlags()) + OS << "[TF=" << TF << ']'; +} + +//===----------------------------------------------------------------------===// +// MachineMemOperand Implementation +//===----------------------------------------------------------------------===// + +/// getAddrSpace - Return the LLVM IR address space number that this pointer +/// points into. +unsigned MachinePointerInfo::getAddrSpace() const { + if (V == 0) return 0; + return cast(V->getType())->getAddressSpace(); +} + +/// getConstantPool - Return a MachinePointerInfo record that refers to the +/// constant pool. +MachinePointerInfo MachinePointerInfo::getConstantPool() { + return MachinePointerInfo(PseudoSourceValue::getConstantPool()); +} + +/// getFixedStack - Return a MachinePointerInfo record that refers to the +/// the specified FrameIndex. +MachinePointerInfo MachinePointerInfo::getFixedStack(int FI, int64_t offset) { + return MachinePointerInfo(PseudoSourceValue::getFixedStack(FI), offset); +} + +MachinePointerInfo MachinePointerInfo::getJumpTable() { + return MachinePointerInfo(PseudoSourceValue::getJumpTable()); +} + +MachinePointerInfo MachinePointerInfo::getGOT() { + return MachinePointerInfo(PseudoSourceValue::getGOT()); +} + +MachinePointerInfo MachinePointerInfo::getStack(int64_t Offset) { + return MachinePointerInfo(PseudoSourceValue::getStack(), Offset); +} + +MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, unsigned f, + uint64_t s, unsigned int a, + const MDNode *TBAAInfo) + : PtrInfo(ptrinfo), Size(s), + Flags((f & ((1 << MOMaxBits) - 1)) | ((Log2_32(a) + 1) << MOMaxBits)), + TBAAInfo(TBAAInfo) { + assert((PtrInfo.V == 0 || isa(PtrInfo.V->getType())) && + "invalid pointer value"); + assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); + assert((isLoad() || isStore()) && "Not a load/store!"); +} + +/// Profile - Gather unique data for the object. +/// +void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(getOffset()); + ID.AddInteger(Size); + ID.AddPointer(getValue()); + ID.AddInteger(Flags); +} + +void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { + // The Value and Offset may differ due to CSE. But the flags and size + // should be the same. + assert(MMO->getFlags() == getFlags() && "Flags mismatch!"); + assert(MMO->getSize() == getSize() && "Size mismatch!"); + + if (MMO->getBaseAlignment() >= getBaseAlignment()) { + // Update the alignment value. + Flags = (Flags & ((1 << MOMaxBits) - 1)) | + ((Log2_32(MMO->getBaseAlignment()) + 1) << MOMaxBits); + // Also update the base and offset, because the new alignment may + // not be applicable with the old ones. + PtrInfo = MMO->PtrInfo; + } +} + +/// getAlignment - Return the minimum known alignment in bytes of the +/// actual memory reference. +uint64_t MachineMemOperand::getAlignment() const { + return MinAlign(getBaseAlignment(), getOffset()); +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { + assert((MMO.isLoad() || MMO.isStore()) && + "SV has to be a load, store or both."); + + if (MMO.isVolatile()) + OS << "Volatile "; + + if (MMO.isLoad()) + OS << "LD"; + if (MMO.isStore()) + OS << "ST"; + OS << MMO.getSize(); + + // Print the address information. + OS << "["; + if (!MMO.getValue()) + OS << ""; + else + WriteAsOperand(OS, MMO.getValue(), /*PrintType=*/false); + + // If the alignment of the memory reference itself differs from the alignment + // of the base pointer, print the base alignment explicitly, next to the base + // pointer. + if (MMO.getBaseAlignment() != MMO.getAlignment()) + OS << "(align=" << MMO.getBaseAlignment() << ")"; + + if (MMO.getOffset() != 0) + OS << "+" << MMO.getOffset(); + OS << "]"; + + // Print the alignment of the reference. + if (MMO.getBaseAlignment() != MMO.getAlignment() || + MMO.getBaseAlignment() != MMO.getSize()) + OS << "(align=" << MMO.getAlignment() << ")"; + + // Print TBAA info. + if (const MDNode *TBAAInfo = MMO.getTBAAInfo()) { + OS << "(tbaa="; + if (TBAAInfo->getNumOperands() > 0) + WriteAsOperand(OS, TBAAInfo->getOperand(0), /*PrintType=*/false); + else + OS << ""; + OS << ")"; + } + + return OS; +} + +//===----------------------------------------------------------------------===// +// MachineInstr Implementation +//===----------------------------------------------------------------------===// + +/// MachineInstr ctor - This constructor creates a dummy MachineInstr with +/// TID NULL and no operands. +MachineInstr::MachineInstr() + : TID(0), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), + Parent(0) { + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +void MachineInstr::addImplicitDefUseOperands() { + if (TID->ImplicitDefs) + for (const unsigned *ImpDefs = TID->ImplicitDefs; *ImpDefs; ++ImpDefs) + addOperand(MachineOperand::CreateReg(*ImpDefs, true, true)); + if (TID->ImplicitUses) + for (const unsigned *ImpUses = TID->ImplicitUses; *ImpUses; ++ImpUses) + addOperand(MachineOperand::CreateReg(*ImpUses, false, true)); +} + +/// MachineInstr ctor - This constructor creates a MachineInstr and adds the +/// implicit operands. It reserves space for the number of operands specified by +/// the TargetInstrDesc. +MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0) { + if (!NoImp) + NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + if (!NoImp) + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +/// MachineInstr ctor - As above, but with a DebugLoc. +MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, + bool NoImp) + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { + if (!NoImp) + NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + if (!NoImp) + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); +} + +/// MachineInstr ctor - Work exactly the same as the ctor two above, except +/// that the MachineInstr is created and added to the end of the specified +/// basic block. +MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0) { + assert(MBB && "Cannot use inserting ctor with null basic block!"); + NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); + MBB->push_back(this); // Add instruction to end of basic block! +} + +/// MachineInstr ctor - As above, but with a DebugLoc. +/// +MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, + const TargetInstrDesc &tid) + : TID(&tid), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(dl) { + assert(MBB && "Cannot use inserting ctor with null basic block!"); + NumImplicitOps = TID->getNumImplicitDefs() + TID->getNumImplicitUses(); + Operands.reserve(NumImplicitOps + TID->getNumOperands()); + addImplicitDefUseOperands(); + // Make sure that we get added to a machine basicblock + LeakDetector::addGarbageObject(this); + MBB->push_back(this); // Add instruction to end of basic block! +} + +/// MachineInstr ctor - Copies MachineInstr arg exactly +/// +MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) + : TID(&MI.getDesc()), NumImplicitOps(0), Flags(0), AsmPrinterFlags(0), + MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), + Parent(0), debugLoc(MI.getDebugLoc()) { + Operands.reserve(MI.getNumOperands()); + + // Add operands + for (unsigned i = 0; i != MI.getNumOperands(); ++i) + addOperand(MI.getOperand(i)); + NumImplicitOps = MI.NumImplicitOps; + + // Copy all the flags. + Flags = MI.Flags; + + // Set parent to null. + Parent = 0; + + LeakDetector::addGarbageObject(this); +} + +MachineInstr::~MachineInstr() { + LeakDetector::removeGarbageObject(this); +#ifndef NDEBUG + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + assert(Operands[i].ParentMI == this && "ParentMI mismatch!"); + assert((!Operands[i].isReg() || !Operands[i].isOnRegUseList()) && + "Reg operand def/use list corrupted"); + } +#endif +} + +/// getRegInfo - If this instruction is embedded into a MachineFunction, +/// return the MachineRegisterInfo object for the current function, otherwise +/// return null. +MachineRegisterInfo *MachineInstr::getRegInfo() { + if (MachineBasicBlock *MBB = getParent()) + return &MBB->getParent()->getRegInfo(); + return 0; +} + +/// RemoveRegOperandsFromUseLists - Unlink all of the register operands in +/// this instruction from their respective use lists. This requires that the +/// operands already be on their use lists. +void MachineInstr::RemoveRegOperandsFromUseLists() { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } +} + +/// AddRegOperandsToUseLists - Add all of the register operands in +/// this instruction from their respective use lists. This requires that the +/// operands not be on their use lists yet. +void MachineInstr::AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo) { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(&RegInfo); + } +} + + +/// addOperand - Add the specified operand to the instruction. If it is an +/// implicit operand, it is added to the end of the operand list. If it is +/// an explicit operand it is added at the end of the explicit operand list +/// (before the first implicit operand). +void MachineInstr::addOperand(const MachineOperand &Op) { + bool isImpReg = Op.isReg() && Op.isImplicit(); + assert((isImpReg || !OperandsComplete()) && + "Trying to add an operand to a machine instr that is already done!"); + + MachineRegisterInfo *RegInfo = getRegInfo(); + + // If we are adding the operand to the end of the list, our job is simpler. + // This is true most of the time, so this is a reasonable optimization. + if (isImpReg || NumImplicitOps == 0) { + // We can only do this optimization if we know that the operand list won't + // reallocate. + if (Operands.empty() || Operands.size()+1 <= Operands.capacity()) { + Operands.push_back(Op); + + // Set the parent of the operand. + Operands.back().ParentMI = this; + + // If the operand is a register, update the operand's use list. + if (Op.isReg()) { + Operands.back().AddRegOperandToRegInfo(RegInfo); + // If the register operand is flagged as early, mark the operand as such + unsigned OpNo = Operands.size() - 1; + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } + return; + } + } + + // Otherwise, we have to insert a real operand before any implicit ones. + unsigned OpNo = Operands.size()-NumImplicitOps; + + // If this instruction isn't embedded into a function, then we don't need to + // update any operand lists. + if (RegInfo == 0) { + // Simple insertion, no reginfo update needed for other register operands. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + // Do explicitly set the reginfo for this operand though, to ensure the + // next/prev fields are properly nulled out. + if (Operands[OpNo].isReg()) { + Operands[OpNo].AddRegOperandToRegInfo(0); + // If the register operand is flagged as early, mark the operand as such + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } + + } else if (Operands.size()+1 <= Operands.capacity()) { + // Otherwise, we have to remove register operands from their register use + // list, add the operand, then add the register operands back to their use + // list. This also must handle the case when the operand list reallocates + // to somewhere else. + + // If insertion of this operand won't cause reallocation of the operand + // list, just remove the implicit operands, add the operand, then re-add all + // the rest of the operands. + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + assert(Operands[i].isReg() && "Should only be an implicit reg!"); + Operands[i].RemoveRegOperandFromRegInfo(); + } + + // Add the operand. If it is a register, add it to the reg list. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + if (Operands[OpNo].isReg()) { + Operands[OpNo].AddRegOperandToRegInfo(RegInfo); + // If the register operand is flagged as early, mark the operand as such + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } + + // Re-add all the implicit ops. + for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) { + assert(Operands[i].isReg() && "Should only be an implicit reg!"); + Operands[i].AddRegOperandToRegInfo(RegInfo); + } + } else { + // Otherwise, we will be reallocating the operand list. Remove all reg + // operands from their list, then readd them after the operand list is + // reallocated. + RemoveRegOperandsFromUseLists(); + + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + // Re-add all the operands. + AddRegOperandsToUseLists(*RegInfo); + + // If the register operand is flagged as early, mark the operand as such + if (Operands[OpNo].isReg() + && TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } +} + +/// RemoveOperand - Erase an operand from an instruction, leaving it with one +/// fewer operand than it started with. +/// +void MachineInstr::RemoveOperand(unsigned OpNo) { + assert(OpNo < Operands.size() && "Invalid operand number"); + + // Special case removing the last one. + if (OpNo == Operands.size()-1) { + // If needed, remove from the reg def/use list. + if (Operands.back().isReg() && Operands.back().isOnRegUseList()) + Operands.back().RemoveRegOperandFromRegInfo(); + + Operands.pop_back(); + return; + } + + // Otherwise, we are removing an interior operand. If we have reginfo to + // update, remove all operands that will be shifted down from their reg lists, + // move everything down, then re-add them. + MachineRegisterInfo *RegInfo = getRegInfo(); + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } + } + + Operands.erase(Operands.begin()+OpNo); + + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(RegInfo); + } + } +} + +/// addMemOperand - Add a MachineMemOperand to the machine instruction. +/// This function should be used only occasionally. The setMemRefs function +/// is the primary method for setting up a MachineInstr's MemRefs list. +void MachineInstr::addMemOperand(MachineFunction &MF, + MachineMemOperand *MO) { + mmo_iterator OldMemRefs = MemRefs; + mmo_iterator OldMemRefsEnd = MemRefsEnd; + + size_t NewNum = (MemRefsEnd - MemRefs) + 1; + mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NewNum); + mmo_iterator NewMemRefsEnd = NewMemRefs + NewNum; + + std::copy(OldMemRefs, OldMemRefsEnd, NewMemRefs); + NewMemRefs[NewNum - 1] = MO; + + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; +} + +bool MachineInstr::isIdenticalTo(const MachineInstr *Other, + MICheckType Check) const { + // If opcodes or number of operands are not the same then the two + // instructions are obviously not identical. + if (Other->getOpcode() != getOpcode() || + Other->getNumOperands() != getNumOperands()) + return false; + + // Check operands to make sure they match. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + const MachineOperand &OMO = Other->getOperand(i); + // Clients may or may not want to ignore defs when testing for equality. + // For example, machine CSE pass only cares about finding common + // subexpressions, so it's safe to ignore virtual register defs. + if (Check != CheckDefs && MO.isReg() && MO.isDef()) { + if (Check == IgnoreDefs) + continue; + // Check == IgnoreVRegDefs + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) || + TargetRegisterInfo::isPhysicalRegister(OMO.getReg())) + if (MO.getReg() != OMO.getReg()) + return false; + } else if (!MO.isIdenticalTo(OMO)) + return false; + } + return true; +} + +/// removeFromParent - This method unlinks 'this' from the containing basic +/// block, and returns it, but does not delete it. +MachineInstr *MachineInstr::removeFromParent() { + assert(getParent() && "Not embedded in a basic block!"); + getParent()->remove(this); + return this; +} + + +/// eraseFromParent - This method unlinks 'this' from the containing basic +/// block, and deletes it. +void MachineInstr::eraseFromParent() { + assert(getParent() && "Not embedded in a basic block!"); + getParent()->erase(this); +} + + +/// OperandComplete - Return true if it's illegal to add a new operand +/// +bool MachineInstr::OperandsComplete() const { + unsigned short NumOperands = TID->getNumOperands(); + if (!TID->isVariadic() && getNumOperands()-NumImplicitOps >= NumOperands) + return true; // Broken: we have all the operands of this instruction! + return false; +} + +/// getNumExplicitOperands - Returns the number of non-implicit operands. +/// +unsigned MachineInstr::getNumExplicitOperands() const { + unsigned NumOperands = TID->getNumOperands(); + if (!TID->isVariadic()) + return NumOperands; + + for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isImplicit()) + NumOperands++; + } + return NumOperands; +} + +bool MachineInstr::isStackAligningInlineAsm() const { + if (isInlineAsm()) { + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_IsAlignStack) + return true; + } + return false; +} + +/// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of +/// the specific register or -1 if it is not found. It further tightens +/// the search criteria to a use that kills the register if isKill is true. +int MachineInstr::findRegisterUseOperandIdx(unsigned Reg, bool isKill, + const TargetRegisterInfo *TRI) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MOReg == Reg || + (TRI && + TargetRegisterInfo::isPhysicalRegister(MOReg) && + TargetRegisterInfo::isPhysicalRegister(Reg) && + TRI->isSubRegister(MOReg, Reg))) + if (!isKill || MO.isKill()) + return i; + } + return -1; +} + +/// readsWritesVirtualRegister - Return a pair of bools (reads, writes) +/// indicating if this instruction reads or writes Reg. This also considers +/// partial defines. +std::pair +MachineInstr::readsWritesVirtualRegister(unsigned Reg, + SmallVectorImpl *Ops) const { + bool PartDef = false; // Partial redefine. + bool FullDef = false; // Full define. + bool Use = false; + + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || MO.getReg() != Reg) + continue; + if (Ops) + Ops->push_back(i); + if (MO.isUse()) + Use |= !MO.isUndef(); + else if (MO.getSubReg()) + PartDef = true; + else + FullDef = true; + } + // A partial redefine uses Reg unless there is also a full define. + return std::make_pair(Use || (PartDef && !FullDef), PartDef || FullDef); +} + +/// findRegisterDefOperandIdx() - Returns the operand index that is a def of +/// the specified register or -1 if it is not found. If isDead is true, defs +/// that are not dead are skipped. If TargetRegisterInfo is non-null, then it +/// also checks if there is a def of a super-register. +int +MachineInstr::findRegisterDefOperandIdx(unsigned Reg, bool isDead, bool Overlap, + const TargetRegisterInfo *TRI) const { + bool isPhys = TargetRegisterInfo::isPhysicalRegister(Reg); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned MOReg = MO.getReg(); + bool Found = (MOReg == Reg); + if (!Found && TRI && isPhys && + TargetRegisterInfo::isPhysicalRegister(MOReg)) { + if (Overlap) + Found = TRI->regsOverlap(MOReg, Reg); + else + Found = TRI->isSubRegister(MOReg, Reg); + } + if (Found && (!isDead || MO.isDead())) + return i; + } + return -1; +} + +/// findFirstPredOperandIdx() - Find the index of the first operand in the +/// operand list that is used to represent the predicate. It returns -1 if +/// none is found. +int MachineInstr::findFirstPredOperandIdx() const { + const TargetInstrDesc &TID = getDesc(); + if (TID.isPredicable()) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (TID.OpInfo[i].isPredicate()) + return i; + } + + return -1; +} + +/// isRegTiedToUseOperand - Given the index of a register def operand, +/// check if the register def is tied to a source operand, due to either +/// two-address elimination or inline assembly constraints. Returns the +/// first tied use operand index by reference is UseOpIdx is not null. +bool MachineInstr:: +isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { + if (isInlineAsm()) { + assert(DefOpIdx > InlineAsm::MIOp_FirstOperand); + const MachineOperand &MO = getOperand(DefOpIdx); + if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) + return false; + // Determine the actual operand index that corresponds to this index. + unsigned DefNo = 0; + unsigned DefPart = 0; + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); + i < e; ) { + const MachineOperand &FMO = getOperand(i); + // After the normal asm operands there may be additional imp-def regs. + if (!FMO.isImm()) + return false; + // Skip over this def. + unsigned NumOps = InlineAsm::getNumOperandRegisters(FMO.getImm()); + unsigned PrevDef = i + 1; + i = PrevDef + NumOps; + if (i > DefOpIdx) { + DefPart = DefOpIdx - PrevDef; + break; + } + ++DefNo; + } + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); + i != e; ++i) { + const MachineOperand &FMO = getOperand(i); + if (!FMO.isImm()) + continue; + if (i+1 >= e || !getOperand(i+1).isReg() || !getOperand(i+1).isUse()) + continue; + unsigned Idx; + if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && + Idx == DefNo) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i + 1 + DefPart; + return true; + } + } + return false; + } + + assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); + const TargetInstrDesc &TID = getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (MO.isReg() && MO.isUse() && + TID.getOperandConstraint(i, TOI::TIED_TO) == (int)DefOpIdx) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i; + return true; + } + } + return false; +} + +/// isRegTiedToDefOperand - Return true if the operand of the specified index +/// is a register use and it is tied to an def operand. It also returns the def +/// operand index by reference. +bool MachineInstr:: +isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { + if (isInlineAsm()) { + const MachineOperand &MO = getOperand(UseOpIdx); + if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) + return false; + + // Find the flag operand corresponding to UseOpIdx + unsigned FlagIdx, NumOps=0; + for (FlagIdx = InlineAsm::MIOp_FirstOperand; + FlagIdx < UseOpIdx; FlagIdx += NumOps+1) { + const MachineOperand &UFMO = getOperand(FlagIdx); + // After the normal asm operands there may be additional imp-def regs. + if (!UFMO.isImm()) + return false; + NumOps = InlineAsm::getNumOperandRegisters(UFMO.getImm()); + assert(NumOps < getNumOperands() && "Invalid inline asm flag"); + if (UseOpIdx < FlagIdx+NumOps+1) + break; + } + if (FlagIdx >= UseOpIdx) + return false; + const MachineOperand &UFMO = getOperand(FlagIdx); + unsigned DefNo; + if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { + if (!DefOpIdx) + return true; + + unsigned DefIdx = InlineAsm::MIOp_FirstOperand; + // Remember to adjust the index. First operand is asm string, second is + // the HasSideEffects and AlignStack bits, then there is a flag for each. + while (DefNo) { + const MachineOperand &FMO = getOperand(DefIdx); + assert(FMO.isImm()); + // Skip over this def. + DefIdx += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; + --DefNo; + } + *DefOpIdx = DefIdx + UseOpIdx - FlagIdx; + return true; + } + return false; + } + + const TargetInstrDesc &TID = getDesc(); + if (UseOpIdx >= TID.getNumOperands()) + return false; + const MachineOperand &MO = getOperand(UseOpIdx); + if (!MO.isReg() || !MO.isUse()) + return false; + int DefIdx = TID.getOperandConstraint(UseOpIdx, TOI::TIED_TO); + if (DefIdx == -1) + return false; + if (DefOpIdx) + *DefOpIdx = (unsigned)DefIdx; + return true; +} + +/// clearKillInfo - Clears kill flags on all operands. +/// +void MachineInstr::clearKillInfo() { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (MO.isReg() && MO.isUse()) + MO.setIsKill(false); + } +} + +/// copyKillDeadInfo - Copies kill / dead operand properties from MI. +/// +void MachineInstr::copyKillDeadInfo(const MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || (!MO.isKill() && !MO.isDead())) + continue; + for (unsigned j = 0, ee = getNumOperands(); j != ee; ++j) { + MachineOperand &MOp = getOperand(j); + if (!MOp.isIdenticalTo(MO)) + continue; + if (MO.isKill()) + MOp.setIsKill(); + else + MOp.setIsDead(); + break; + } + } +} + +/// copyPredicates - Copies predicate operand(s) from MI. +void MachineInstr::copyPredicates(const MachineInstr *MI) { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (TID.OpInfo[i].isPredicate()) { + // Predicated operands must be last operands. + addOperand(MI->getOperand(i)); + } + } +} + +void MachineInstr::substituteRegister(unsigned FromReg, + unsigned ToReg, + unsigned SubIdx, + const TargetRegisterInfo &RegInfo) { + if (TargetRegisterInfo::isPhysicalRegister(ToReg)) { + if (SubIdx) + ToReg = RegInfo.getSubReg(ToReg, SubIdx); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || MO.getReg() != FromReg) + continue; + MO.substPhysReg(ToReg, RegInfo); + } + } else { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || MO.getReg() != FromReg) + continue; + MO.substVirtReg(ToReg, SubIdx, RegInfo); + } + } +} + +/// isSafeToMove - Return true if it is safe to move this instruction. If +/// SawStore is set to true, it means that there is a store (or call) between +/// the instruction's location and its intended destination. +bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, + AliasAnalysis *AA, + bool &SawStore) const { + // Ignore stuff that we obviously can't move. + if (TID->mayStore() || TID->isCall()) { + SawStore = true; + return false; + } + + if (isLabel() || isDebugValue() || + TID->isTerminator() || hasUnmodeledSideEffects()) + return false; + + // See if this instruction does a load. If so, we have to guarantee that the + // loaded value doesn't change between the load and the its intended + // destination. The check for isInvariantLoad gives the targe the chance to + // classify the load as always returning a constant, e.g. a constant pool + // load. + if (TID->mayLoad() && !isInvariantLoad(AA)) + // Otherwise, this is a real load. If there is a store between the load and + // end of block, or if the load is volatile, we can't move it. + return !SawStore && !hasVolatileMemoryRef(); + + return true; +} + +/// isSafeToReMat - Return true if it's safe to rematerialize the specified +/// instruction which defined the specified register instead of copying it. +bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, + AliasAnalysis *AA, + unsigned DstReg) const { + bool SawStore = false; + if (!TII->isTriviallyReMaterializable(this, AA) || + !isSafeToMove(TII, AA, SawStore)) + return false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg()) + continue; + // FIXME: For now, do not remat any instruction with register operands. + // Later on, we can loosen the restriction is the register operands have + // not been modified between the def and use. Note, this is different from + // MachineSink because the code is no longer in two-address form (at least + // partially). + if (MO.isUse()) + return false; + else if (!MO.isDead() && MO.getReg() != DstReg) + return false; + } + return true; +} + +/// hasVolatileMemoryRef - Return true if this instruction may have a +/// volatile memory reference, or if the information describing the +/// memory reference is not available. Return false if it is known to +/// have no volatile memory references. +bool MachineInstr::hasVolatileMemoryRef() const { + // An instruction known never to access memory won't have a volatile access. + if (!TID->mayStore() && + !TID->mayLoad() && + !TID->isCall() && + !hasUnmodeledSideEffects()) + return false; + + // Otherwise, if the instruction has no memory reference information, + // conservatively assume it wasn't preserved. + if (memoperands_empty()) + return true; + + // Check the memory reference information for volatile references. + for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I) + if ((*I)->isVolatile()) + return true; + + return false; +} + +/// isInvariantLoad - Return true if this instruction is loading from a +/// location whose value is invariant across the function. For example, +/// loading a value from the constant pool or from the argument area +/// of a function if it does not change. This should only return true of +/// *all* loads the instruction does are invariant (if it does multiple loads). +bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { + // If the instruction doesn't load at all, it isn't an invariant load. + if (!TID->mayLoad()) + return false; + + // If the instruction has lost its memoperands, conservatively assume that + // it may not be an invariant load. + if (memoperands_empty()) + return false; + + const MachineFrameInfo *MFI = getParent()->getParent()->getFrameInfo(); + + for (mmo_iterator I = memoperands_begin(), + E = memoperands_end(); I != E; ++I) { + if ((*I)->isVolatile()) return false; + if ((*I)->isStore()) return false; + + if (const Value *V = (*I)->getValue()) { + // A load from a constant PseudoSourceValue is invariant. + if (const PseudoSourceValue *PSV = dyn_cast(V)) + if (PSV->isConstant(MFI)) + continue; + // If we have an AliasAnalysis, ask it whether the memory is constant. + if (AA && AA->pointsToConstantMemory( + AliasAnalysis::Location(V, (*I)->getSize(), + (*I)->getTBAAInfo()))) + continue; + } + + // Otherwise assume conservatively. + return false; + } + + // Everything checks out. + return true; +} + +/// isConstantValuePHI - If the specified instruction is a PHI that always +/// merges together the same virtual register, return the register, otherwise +/// return 0. +unsigned MachineInstr::isConstantValuePHI() const { + if (!isPHI()) + return 0; + assert(getNumOperands() >= 3 && + "It's illegal to have a PHI without source operands"); + + unsigned Reg = getOperand(1).getReg(); + for (unsigned i = 3, e = getNumOperands(); i < e; i += 2) + if (getOperand(i).getReg() != Reg) + return 0; + return Reg; +} + +bool MachineInstr::hasUnmodeledSideEffects() const { + if (getDesc().hasUnmodeledSideEffects()) + return true; + if (isInlineAsm()) { + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_HasSideEffects) + return true; + } + + return false; +} + +/// allDefsAreDead - Return true if all the defs of this instruction are dead. +/// +bool MachineInstr::allDefsAreDead() const { + for (unsigned i = 0, e = getNumOperands(); i < e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || MO.isUse()) + continue; + if (!MO.isDead()) + return false; + } + return true; +} + +/// copyImplicitOps - Copy implicit register operands from specified +/// instruction to this instruction. +void MachineInstr::copyImplicitOps(const MachineInstr *MI) { + for (unsigned i = MI->getDesc().getNumOperands(), e = MI->getNumOperands(); + i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isImplicit()) + addOperand(MO); + } +} + +void MachineInstr::dump() const { + dbgs() << " " << *this; +} + +static void printDebugLoc(DebugLoc DL, const MachineFunction *MF, + raw_ostream &CommentOS) { + const LLVMContext &Ctx = MF->getFunction()->getContext(); + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << ""; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, MF, CommentOS); + CommentOS << " ]"; + } + } +} + +void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { + // We can be a bit tidier if we know the TargetMachine and/or MachineFunction. + const MachineFunction *MF = 0; + const MachineRegisterInfo *MRI = 0; + if (const MachineBasicBlock *MBB = getParent()) { + MF = MBB->getParent(); + if (!TM && MF) + TM = &MF->getTarget(); + if (MF) + MRI = &MF->getRegInfo(); + } + + // Save a list of virtual registers. + SmallVector VirtRegs; + + // Print explicitly defined operands on the left of an assignment syntax. + unsigned StartOp = 0, e = getNumOperands(); + for (; StartOp < e && getOperand(StartOp).isReg() && + getOperand(StartOp).isDef() && + !getOperand(StartOp).isImplicit(); + ++StartOp) { + if (StartOp != 0) OS << ", "; + getOperand(StartOp).print(OS, TM); + unsigned Reg = getOperand(StartOp).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + VirtRegs.push_back(Reg); + } + + if (StartOp != 0) + OS << " = "; + + // Print the opcode name. + OS << getDesc().getName(); + + // Print the rest of the operands. + bool OmittedAnyCallClobbers = false; + bool FirstOp = true; + + if (isInlineAsm()) { + // Print asm string. + OS << " "; + getOperand(InlineAsm::MIOp_AsmString).print(OS, TM); + + // Print HasSideEffects, IsAlignStack + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_HasSideEffects) + OS << " [sideeffect]"; + if (ExtraInfo & InlineAsm::Extra_IsAlignStack) + OS << " [alignstack]"; + + StartOp = InlineAsm::MIOp_FirstOperand; + FirstOp = false; + } + + + for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + + if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) + VirtRegs.push_back(MO.getReg()); + + // Omit call-clobbered registers which aren't used anywhere. This makes + // call instructions much less noisy on targets where calls clobber lots + // of registers. Don't rely on MO.isDead() because we may be called before + // LiveVariables is run, or we may be looking at a non-allocatable reg. + if (MF && getDesc().isCall() && + MO.isReg() && MO.isImplicit() && MO.isDef()) { + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + const MachineRegisterInfo &MRI = MF->getRegInfo(); + if (MRI.use_empty(Reg) && !MRI.isLiveOut(Reg)) { + bool HasAliasLive = false; + for (const unsigned *Alias = TM->getRegisterInfo()->getAliasSet(Reg); + unsigned AliasReg = *Alias; ++Alias) + if (!MRI.use_empty(AliasReg) || MRI.isLiveOut(AliasReg)) { + HasAliasLive = true; + break; + } + if (!HasAliasLive) { + OmittedAnyCallClobbers = true; + continue; + } + } + } + } + + if (FirstOp) FirstOp = false; else OS << ","; + OS << " "; + if (i < getDesc().NumOperands) { + const TargetOperandInfo &TOI = getDesc().OpInfo[i]; + if (TOI.isPredicate()) + OS << "pred:"; + if (TOI.isOptionalDef()) + OS << "opt:"; + } + if (isDebugValue() && MO.isMetadata()) { + // Pretty print DBG_VALUE instructions. + const MDNode *MD = MO.getMetadata(); + if (const MDString *MDS = dyn_cast(MD->getOperand(2))) + OS << "!\"" << MDS->getString() << '\"'; + else + MO.print(OS, TM); + } else if (TM && (isInsertSubreg() || isRegSequence()) && MO.isImm()) { + OS << TM->getRegisterInfo()->getSubRegIndexName(MO.getImm()); + } else + MO.print(OS, TM); + } + + // Briefly indicate whether any call clobbers were omitted. + if (OmittedAnyCallClobbers) { + if (!FirstOp) OS << ","; + OS << " ..."; + } + + bool HaveSemi = false; + if (Flags) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + OS << " flags: "; + + if (Flags & FrameSetup) + OS << "FrameSetup"; + } + + if (!memoperands_empty()) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + + OS << " mem:"; + for (mmo_iterator i = memoperands_begin(), e = memoperands_end(); + i != e; ++i) { + OS << **i; + if (llvm::next(i) != e) + OS << " "; + } + } + + // Print the regclass of any virtual registers encountered. + if (MRI && !VirtRegs.empty()) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + for (unsigned i = 0; i != VirtRegs.size(); ++i) { + const TargetRegisterClass *RC = MRI->getRegClass(VirtRegs[i]); + OS << " " << RC->getName() << ':' << PrintReg(VirtRegs[i]); + for (unsigned j = i+1; j != VirtRegs.size();) { + if (MRI->getRegClass(VirtRegs[j]) != RC) { + ++j; + continue; + } + if (VirtRegs[i] != VirtRegs[j]) + OS << "," << PrintReg(VirtRegs[j]); + VirtRegs.erase(VirtRegs.begin()+j); + } + } + } + + // Print debug location information. + if (!debugLoc.isUnknown() && MF) { + if (!HaveSemi) OS << ";"; HaveSemi = true; + OS << " dbg:"; + printDebugLoc(debugLoc, MF, OS); + } + + OS << '\n'; +} + +bool MachineInstr::addRegisterKilled(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound) { + bool isPhysReg = TargetRegisterInfo::isPhysicalRegister(IncomingReg); + bool hasAliases = isPhysReg && RegInfo->getAliasSet(IncomingReg); + bool Found = false; + SmallVector DeadOps; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + + if (Reg == IncomingReg) { + if (!Found) { + if (MO.isKill()) + // The register is already marked kill. + return true; + if (isPhysReg && isRegTiedToDefOperand(i)) + // Two-address uses of physregs must not be marked kill. + return true; + MO.setIsKill(); + Found = true; + } + } else if (hasAliases && MO.isKill() && + TargetRegisterInfo::isPhysicalRegister(Reg)) { + // A super-register kill already exists. + if (RegInfo->isSuperRegister(IncomingReg, Reg)) + return true; + if (RegInfo->isSubRegister(IncomingReg, Reg)) + DeadOps.push_back(i); + } + } + + // Trim unneeded kill operands. + while (!DeadOps.empty()) { + unsigned OpIdx = DeadOps.back(); + if (getOperand(OpIdx).isImplicit()) + RemoveOperand(OpIdx); + else + getOperand(OpIdx).setIsKill(false); + DeadOps.pop_back(); + } + + // If not found, this means an alias of one of the operands is killed. Add a + // new implicit operand if required. + if (!Found && AddIfNotFound) { + addOperand(MachineOperand::CreateReg(IncomingReg, + false /*IsDef*/, + true /*IsImp*/, + true /*IsKill*/)); + return true; + } + return Found; +} + +bool MachineInstr::addRegisterDead(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo, + bool AddIfNotFound) { + bool isPhysReg = TargetRegisterInfo::isPhysicalRegister(IncomingReg); + bool hasAliases = isPhysReg && RegInfo->getAliasSet(IncomingReg); + bool Found = false; + SmallVector DeadOps; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + + if (Reg == IncomingReg) { + if (!Found) { + if (MO.isDead()) + // The register is already marked dead. + return true; + MO.setIsDead(); + Found = true; + } + } else if (hasAliases && MO.isDead() && + TargetRegisterInfo::isPhysicalRegister(Reg)) { + // There exists a super-register that's marked dead. + if (RegInfo->isSuperRegister(IncomingReg, Reg)) + return true; + if (RegInfo->getSubRegisters(IncomingReg) && + RegInfo->getSuperRegisters(Reg) && + RegInfo->isSubRegister(IncomingReg, Reg)) + DeadOps.push_back(i); + } + } + + // Trim unneeded dead operands. + while (!DeadOps.empty()) { + unsigned OpIdx = DeadOps.back(); + if (getOperand(OpIdx).isImplicit()) + RemoveOperand(OpIdx); + else + getOperand(OpIdx).setIsDead(false); + DeadOps.pop_back(); + } + + // If not found, this means an alias of one of the operands is dead. Add a + // new implicit operand if required. + if (Found || !AddIfNotFound) + return Found; + + addOperand(MachineOperand::CreateReg(IncomingReg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + true /*IsDead*/)); + return true; +} + +void MachineInstr::addRegisterDefined(unsigned IncomingReg, + const TargetRegisterInfo *RegInfo) { + if (TargetRegisterInfo::isPhysicalRegister(IncomingReg)) { + MachineOperand *MO = findRegisterDefOperand(IncomingReg, false, RegInfo); + if (MO) + return; + } else { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (MO.isReg() && MO.getReg() == IncomingReg && MO.isDef() && + MO.getSubReg() == 0) + return; + } + } + addOperand(MachineOperand::CreateReg(IncomingReg, + true /*IsDef*/, + true /*IsImp*/)); +} + +void MachineInstr::setPhysRegsDeadExcept(const SmallVectorImpl &UsedRegs, + const TargetRegisterInfo &TRI) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + bool Dead = true; + for (SmallVectorImpl::const_iterator I = UsedRegs.begin(), + E = UsedRegs.end(); I != E; ++I) + if (TRI.regsOverlap(*I, Reg)) { + Dead = false; + break; + } + // If there are no uses, including partial uses, the def is dead. + if (Dead) MO.setIsDead(); + } +} + +unsigned +MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) { + unsigned Hash = MI->getOpcode() * 37; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + uint64_t Key = (uint64_t)MO.getType() << 32; + switch (MO.getType()) { + default: break; + case MachineOperand::MO_Register: + if (MO.isDef() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) + continue; // Skip virtual register defs. + Key |= MO.getReg(); + break; + case MachineOperand::MO_Immediate: + Key |= MO.getImm(); + break; + case MachineOperand::MO_FrameIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + Key |= MO.getIndex(); + break; + case MachineOperand::MO_MachineBasicBlock: + Key |= DenseMapInfo::getHashValue(MO.getMBB()); + break; + case MachineOperand::MO_GlobalAddress: + Key |= DenseMapInfo::getHashValue(MO.getGlobal()); + break; + case MachineOperand::MO_BlockAddress: + Key |= DenseMapInfo::getHashValue(MO.getBlockAddress()); + break; + case MachineOperand::MO_MCSymbol: + Key |= DenseMapInfo::getHashValue(MO.getMCSymbol()); + break; + } + Key += ~(Key << 32); + Key ^= (Key >> 22); + Key += ~(Key << 13); + Key ^= (Key >> 8); + Key += (Key << 3); + Key ^= (Key >> 15); + Key += ~(Key << 27); + Key ^= (Key >> 31); + Hash = (unsigned)Key + Hash * 37; + } + return Hash; +} diff --git a/final/lib/CodeGen/MachineLICM.cpp b/final/lib/CodeGen/MachineLICM.cpp new file mode 100644 index 00000000000..1c0f6ade856 --- /dev/null +++ b/final/lib/CodeGen/MachineLICM.cpp @@ -0,0 +1,1202 @@ +//===-- MachineLICM.cpp - Machine Loop Invariant Code Motion Pass ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs loop invariant code motion on machine instructions. We +// attempt to remove as much code from the body of a loop as possible. +// +// This pass does not attempt to throttle itself to limit register pressure. +// The register allocation phases are expected to perform rematerialization +// to recover when register pressure is high. +// +// This pass is not intended to be a replacement or a complete alternative +// for the LLVM-IR-level LICM pass. It is only designed to hoist simple +// constructs that are not exposed before lowering and instruction selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-licm" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +STATISTIC(NumHoisted, + "Number of machine instructions hoisted out of loops"); +STATISTIC(NumLowRP, + "Number of instructions hoisted in low reg pressure situation"); +STATISTIC(NumHighLatency, + "Number of high latency instructions hoisted"); +STATISTIC(NumCSEed, + "Number of hoisted machine instructions CSEed"); +STATISTIC(NumPostRAHoisted, + "Number of machine instructions hoisted out of loops post regalloc"); + +namespace { + class MachineLICM : public MachineFunctionPass { + bool PreRegAlloc; + + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetLowering *TLI; + const TargetRegisterInfo *TRI; + const MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + const InstrItineraryData *InstrItins; + + // Various analyses that we use... + AliasAnalysis *AA; // Alias analysis info. + MachineLoopInfo *MLI; // Current MachineLoopInfo + MachineDominatorTree *DT; // Machine dominator tree for the cur loop + + // State that is updated as we process loops + bool Changed; // True if a loop is changed. + bool FirstInLoop; // True if it's the first LICM in the loop. + MachineLoop *CurLoop; // The current loop we are working on. + MachineBasicBlock *CurPreheader; // The preheader for CurLoop. + + BitVector AllocatableSet; + + // Track 'estimated' register pressure. + SmallSet RegSeen; + SmallVector RegPressure; + + // Register pressure "limit" per register class. If the pressure + // is higher than the limit, then it's considered high. + SmallVector RegLimit; + + // Register pressure on path leading from loop preheader to current BB. + SmallVector, 16> BackTrace; + + // For each opcode, keep a list of potential CSE instructions. + DenseMap > CSEMap; + + public: + static char ID; // Pass identification, replacement for typeid + MachineLICM() : + MachineFunctionPass(ID), PreRegAlloc(true) { + initializeMachineLICMPass(*PassRegistry::getPassRegistry()); + } + + explicit MachineLICM(bool PreRA) : + MachineFunctionPass(ID), PreRegAlloc(PreRA) { + initializeMachineLICMPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + const char *getPassName() const { return "Machine Instruction LICM"; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual void releaseMemory() { + RegSeen.clear(); + RegPressure.clear(); + RegLimit.clear(); + BackTrace.clear(); + for (DenseMap >::iterator + CI = CSEMap.begin(), CE = CSEMap.end(); CI != CE; ++CI) + CI->second.clear(); + CSEMap.clear(); + } + + private: + /// CandidateInfo - Keep track of information about hoisting candidates. + struct CandidateInfo { + MachineInstr *MI; + unsigned Def; + int FI; + CandidateInfo(MachineInstr *mi, unsigned def, int fi) + : MI(mi), Def(def), FI(fi) {} + }; + + /// HoistRegionPostRA - Walk the specified region of the CFG and hoist loop + /// invariants out to the preheader. + void HoistRegionPostRA(); + + /// HoistPostRA - When an instruction is found to only use loop invariant + /// operands that is safe to hoist, this instruction is called to do the + /// dirty work. + void HoistPostRA(MachineInstr *MI, unsigned Def); + + /// ProcessMI - Examine the instruction for potentai LICM candidate. Also + /// gather register def and frame object update information. + void ProcessMI(MachineInstr *MI, unsigned *PhysRegDefs, + SmallSet &StoredFIs, + SmallVector &Candidates); + + /// AddToLiveIns - Add register 'Reg' to the livein sets of BBs in the + /// current loop. + void AddToLiveIns(unsigned Reg); + + /// IsLICMCandidate - Returns true if the instruction may be a suitable + /// candidate for LICM. e.g. If the instruction is a call, then it's + /// obviously not safe to hoist it. + bool IsLICMCandidate(MachineInstr &I); + + /// IsLoopInvariantInst - Returns true if the instruction is loop + /// invariant. I.e., all virtual register operands are defined outside of + /// the loop, physical registers aren't accessed (explicitly or implicitly), + /// and the instruction is hoistable. + /// + bool IsLoopInvariantInst(MachineInstr &I); + + /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' + /// and an use in the current loop, return true if the target considered + /// it 'high'. + bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx, + unsigned Reg) const; + + bool IsCheapInstruction(MachineInstr &MI) const; + + /// CanCauseHighRegPressure - Visit BBs from header to current BB, + /// check if hoisting an instruction of the given cost matrix can cause high + /// register pressure. + bool CanCauseHighRegPressure(DenseMap &Cost); + + /// UpdateBackTraceRegPressure - Traverse the back trace from header to + /// the current block and update their register pressures to reflect the + /// effect of hoisting MI from the current block to the preheader. + void UpdateBackTraceRegPressure(const MachineInstr *MI); + + /// IsProfitableToHoist - Return true if it is potentially profitable to + /// hoist the given loop invariant. + bool IsProfitableToHoist(MachineInstr &MI); + + /// HoistRegion - Walk the specified region of the CFG (defined by all + /// blocks dominated by the specified block, and that are in the current + /// loop) in depth first order w.r.t the DominatorTree. This allows us to + /// visit definitions before uses, allowing us to hoist a loop body in one + /// pass without iteration. + /// + void HoistRegion(MachineDomTreeNode *N, bool IsHeader = false); + + /// InitRegPressure - Find all virtual register references that are liveout + /// of the preheader to initialize the starting "register pressure". Note + /// this does not count live through (livein but not used) registers. + void InitRegPressure(MachineBasicBlock *BB); + + /// UpdateRegPressure - Update estimate of register pressure after the + /// specified instruction. + void UpdateRegPressure(const MachineInstr *MI); + + /// ExtractHoistableLoad - Unfold a load from the given machineinstr if + /// the load itself could be hoisted. Return the unfolded and hoistable + /// load, or null if the load couldn't be unfolded or if it wouldn't + /// be hoistable. + MachineInstr *ExtractHoistableLoad(MachineInstr *MI); + + /// LookForDuplicate - Find an instruction amount PrevMIs that is a + /// duplicate of MI. Return this instruction if it's found. + const MachineInstr *LookForDuplicate(const MachineInstr *MI, + std::vector &PrevMIs); + + /// EliminateCSE - Given a LICM'ed instruction, look for an instruction on + /// the preheader that compute the same value. If it's found, do a RAU on + /// with the definition of the existing instruction rather than hoisting + /// the instruction to the preheader. + bool EliminateCSE(MachineInstr *MI, + DenseMap >::iterator &CI); + + /// Hoist - When an instruction is found to only use loop invariant operands + /// that is safe to hoist, this instruction is called to do the dirty work. + /// It returns true if the instruction is hoisted. + bool Hoist(MachineInstr *MI, MachineBasicBlock *Preheader); + + /// InitCSEMap - Initialize the CSE map with instructions that are in the + /// current loop preheader that may become duplicates of instructions that + /// are hoisted out of the loop. + void InitCSEMap(MachineBasicBlock *BB); + + /// getCurPreheader - Get the preheader for the current loop, splitting + /// a critical edge if needed. + MachineBasicBlock *getCurPreheader(); + }; +} // end anonymous namespace + +char MachineLICM::ID = 0; +INITIALIZE_PASS_BEGIN(MachineLICM, "machinelicm", + "Machine Loop Invariant Code Motion", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(MachineLICM, "machinelicm", + "Machine Loop Invariant Code Motion", false, false) + +FunctionPass *llvm::createMachineLICMPass(bool PreRegAlloc) { + return new MachineLICM(PreRegAlloc); +} + +/// LoopIsOuterMostWithPredecessor - Test if the given loop is the outer-most +/// loop that has a unique predecessor. +static bool LoopIsOuterMostWithPredecessor(MachineLoop *CurLoop) { + // Check whether this loop even has a unique predecessor. + if (!CurLoop->getLoopPredecessor()) + return false; + // Ok, now check to see if any of its outer loops do. + for (MachineLoop *L = CurLoop->getParentLoop(); L; L = L->getParentLoop()) + if (L->getLoopPredecessor()) + return false; + // None of them did, so this is the outermost with a unique predecessor. + return true; +} + +bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { + if (PreRegAlloc) + DEBUG(dbgs() << "******** Pre-regalloc Machine LICM: "); + else + DEBUG(dbgs() << "******** Post-regalloc Machine LICM: "); + DEBUG(dbgs() << MF.getFunction()->getName() << " ********\n"); + + Changed = FirstInLoop = false; + TM = &MF.getTarget(); + TII = TM->getInstrInfo(); + TLI = TM->getTargetLowering(); + TRI = TM->getRegisterInfo(); + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + InstrItins = TM->getInstrItineraryData(); + AllocatableSet = TRI->getAllocatableSet(MF); + + if (PreRegAlloc) { + // Estimate register pressure during pre-regalloc pass. + unsigned NumRC = TRI->getNumRegClasses(); + RegPressure.resize(NumRC); + std::fill(RegPressure.begin(), RegPressure.end(), 0); + RegLimit.resize(NumRC); + for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), + E = TRI->regclass_end(); I != E; ++I) + RegLimit[(*I)->getID()] = TRI->getRegPressureLimit(*I, MF); + } + + // Get our Loop information... + MLI = &getAnalysis(); + DT = &getAnalysis(); + AA = &getAnalysis(); + + SmallVector Worklist(MLI->begin(), MLI->end()); + while (!Worklist.empty()) { + CurLoop = Worklist.pop_back_val(); + CurPreheader = 0; + + // If this is done before regalloc, only visit outer-most preheader-sporting + // loops. + if (PreRegAlloc && !LoopIsOuterMostWithPredecessor(CurLoop)) { + Worklist.append(CurLoop->begin(), CurLoop->end()); + continue; + } + + if (!PreRegAlloc) + HoistRegionPostRA(); + else { + // CSEMap is initialized for loop header when the first instruction is + // being hoisted. + MachineDomTreeNode *N = DT->getNode(CurLoop->getHeader()); + FirstInLoop = true; + HoistRegion(N, true); + CSEMap.clear(); + } + } + + return Changed; +} + +/// InstructionStoresToFI - Return true if instruction stores to the +/// specified frame. +static bool InstructionStoresToFI(const MachineInstr *MI, int FI) { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); o != oe; ++o) { + if (!(*o)->isStore() || !(*o)->getValue()) + continue; + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + if (Value->getFrameIndex() == FI) + return true; + } + } + return false; +} + +/// ProcessMI - Examine the instruction for potentai LICM candidate. Also +/// gather register def and frame object update information. +void MachineLICM::ProcessMI(MachineInstr *MI, + unsigned *PhysRegDefs, + SmallSet &StoredFIs, + SmallVector &Candidates) { + bool RuledOut = false; + bool HasNonInvariantUse = false; + unsigned Def = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isFI()) { + // Remember if the instruction stores to the frame index. + int FI = MO.getIndex(); + if (!StoredFIs.count(FI) && + MFI->isSpillSlotObjectIndex(FI) && + InstructionStoresToFI(MI, FI)) + StoredFIs.insert(FI); + HasNonInvariantUse = true; + continue; + } + + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + assert(TargetRegisterInfo::isPhysicalRegister(Reg) && + "Not expecting virtual register!"); + + if (!MO.isDef()) { + if (Reg && PhysRegDefs[Reg]) + // If it's using a non-loop-invariant register, then it's obviously not + // safe to hoist. + HasNonInvariantUse = true; + continue; + } + + if (MO.isImplicit()) { + ++PhysRegDefs[Reg]; + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + ++PhysRegDefs[*AS]; + if (!MO.isDead()) + // Non-dead implicit def? This cannot be hoisted. + RuledOut = true; + // No need to check if a dead implicit def is also defined by + // another instruction. + continue; + } + + // FIXME: For now, avoid instructions with multiple defs, unless + // it's a dead implicit def. + if (Def) + RuledOut = true; + else + Def = Reg; + + // If we have already seen another instruction that defines the same + // register, then this is not safe. + if (++PhysRegDefs[Reg] > 1) + // MI defined register is seen defined by another instruction in + // the loop, it cannot be a LICM candidate. + RuledOut = true; + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + if (++PhysRegDefs[*AS] > 1) + RuledOut = true; + } + + // Only consider reloads for now and remats which do not have register + // operands. FIXME: Consider unfold load folding instructions. + if (Def && !RuledOut) { + int FI = INT_MIN; + if ((!HasNonInvariantUse && IsLICMCandidate(*MI)) || + (TII->isLoadFromStackSlot(MI, FI) && MFI->isSpillSlotObjectIndex(FI))) + Candidates.push_back(CandidateInfo(MI, Def, FI)); + } +} + +/// HoistRegionPostRA - Walk the specified region of the CFG and hoist loop +/// invariants out to the preheader. +void MachineLICM::HoistRegionPostRA() { + unsigned NumRegs = TRI->getNumRegs(); + unsigned *PhysRegDefs = new unsigned[NumRegs]; + std::fill(PhysRegDefs, PhysRegDefs + NumRegs, 0); + + SmallVector Candidates; + SmallSet StoredFIs; + + // Walk the entire region, count number of defs for each register, and + // collect potential LICM candidates. + const std::vector Blocks = CurLoop->getBlocks(); + for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { + MachineBasicBlock *BB = Blocks[i]; + // Conservatively treat live-in's as an external def. + // FIXME: That means a reload that're reused in successor block(s) will not + // be LICM'ed. + for (MachineBasicBlock::livein_iterator I = BB->livein_begin(), + E = BB->livein_end(); I != E; ++I) { + unsigned Reg = *I; + ++PhysRegDefs[Reg]; + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + ++PhysRegDefs[*AS]; + } + + for (MachineBasicBlock::iterator + MII = BB->begin(), E = BB->end(); MII != E; ++MII) { + MachineInstr *MI = &*MII; + ProcessMI(MI, PhysRegDefs, StoredFIs, Candidates); + } + } + + // Now evaluate whether the potential candidates qualify. + // 1. Check if the candidate defined register is defined by another + // instruction in the loop. + // 2. If the candidate is a load from stack slot (always true for now), + // check if the slot is stored anywhere in the loop. + for (unsigned i = 0, e = Candidates.size(); i != e; ++i) { + if (Candidates[i].FI != INT_MIN && + StoredFIs.count(Candidates[i].FI)) + continue; + + if (PhysRegDefs[Candidates[i].Def] == 1) { + bool Safe = true; + MachineInstr *MI = Candidates[i].MI; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + const MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg() || MO.isDef() || !MO.getReg()) + continue; + if (PhysRegDefs[MO.getReg()]) { + // If it's using a non-loop-invariant register, then it's obviously + // not safe to hoist. + Safe = false; + break; + } + } + if (Safe) + HoistPostRA(MI, Candidates[i].Def); + } + } + + delete[] PhysRegDefs; +} + +/// AddToLiveIns - Add register 'Reg' to the livein sets of BBs in the current +/// loop, and make sure it is not killed by any instructions in the loop. +void MachineLICM::AddToLiveIns(unsigned Reg) { + const std::vector Blocks = CurLoop->getBlocks(); + for (unsigned i = 0, e = Blocks.size(); i != e; ++i) { + MachineBasicBlock *BB = Blocks[i]; + if (!BB->isLiveIn(Reg)) + BB->addLiveIn(Reg); + for (MachineBasicBlock::iterator + MII = BB->begin(), E = BB->end(); MII != E; ++MII) { + MachineInstr *MI = &*MII; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.getReg() || MO.isDef()) continue; + if (MO.getReg() == Reg || TRI->isSuperRegister(Reg, MO.getReg())) + MO.setIsKill(false); + } + } + } +} + +/// HoistPostRA - When an instruction is found to only use loop invariant +/// operands that is safe to hoist, this instruction is called to do the +/// dirty work. +void MachineLICM::HoistPostRA(MachineInstr *MI, unsigned Def) { + MachineBasicBlock *Preheader = getCurPreheader(); + if (!Preheader) return; + + // Now move the instructions to the predecessor, inserting it before any + // terminator instructions. + DEBUG({ + dbgs() << "Hoisting " << *MI; + if (Preheader->getBasicBlock()) + dbgs() << " to MachineBasicBlock " + << Preheader->getName(); + if (MI->getParent()->getBasicBlock()) + dbgs() << " from MachineBasicBlock " + << MI->getParent()->getName(); + dbgs() << "\n"; + }); + + // Splice the instruction to the preheader. + MachineBasicBlock *MBB = MI->getParent(); + Preheader->splice(Preheader->getFirstTerminator(), MBB, MI); + + // Add register to livein list to all the BBs in the current loop since a + // loop invariant must be kept live throughout the whole loop. This is + // important to ensure later passes do not scavenge the def register. + AddToLiveIns(Def); + + ++NumPostRAHoisted; + Changed = true; +} + +/// HoistRegion - Walk the specified region of the CFG (defined by all blocks +/// dominated by the specified block, and that are in the current loop) in depth +/// first order w.r.t the DominatorTree. This allows us to visit definitions +/// before uses, allowing us to hoist a loop body in one pass without iteration. +/// +void MachineLICM::HoistRegion(MachineDomTreeNode *N, bool IsHeader) { + assert(N != 0 && "Null dominator tree node?"); + MachineBasicBlock *BB = N->getBlock(); + + // If this subregion is not in the top level loop at all, exit. + if (!CurLoop->contains(BB)) return; + + MachineBasicBlock *Preheader = getCurPreheader(); + if (!Preheader) + return; + + if (IsHeader) { + // Compute registers which are livein into the loop headers. + RegSeen.clear(); + BackTrace.clear(); + InitRegPressure(Preheader); + } + + // Remember livein register pressure. + BackTrace.push_back(RegPressure); + + for (MachineBasicBlock::iterator + MII = BB->begin(), E = BB->end(); MII != E; ) { + MachineBasicBlock::iterator NextMII = MII; ++NextMII; + MachineInstr *MI = &*MII; + if (!Hoist(MI, Preheader)) + UpdateRegPressure(MI); + MII = NextMII; + } + + // Don't hoist things out of a large switch statement. This often causes + // code to be hoisted that wasn't going to be executed, and increases + // register pressure in a situation where it's likely to matter. + if (BB->succ_size() < 25) { + const std::vector &Children = N->getChildren(); + for (unsigned I = 0, E = Children.size(); I != E; ++I) + HoistRegion(Children[I]); + } + + BackTrace.pop_back(); +} + +static bool isOperandKill(const MachineOperand &MO, MachineRegisterInfo *MRI) { + return MO.isKill() || MRI->hasOneNonDBGUse(MO.getReg()); +} + +/// InitRegPressure - Find all virtual register references that are liveout of +/// the preheader to initialize the starting "register pressure". Note this +/// does not count live through (livein but not used) registers. +void MachineLICM::InitRegPressure(MachineBasicBlock *BB) { + std::fill(RegPressure.begin(), RegPressure.end(), 0); + + // If the preheader has only a single predecessor and it ends with a + // fallthrough or an unconditional branch, then scan its predecessor for live + // defs as well. This happens whenever the preheader is created by splitting + // the critical edge from the loop predecessor to the loop header. + if (BB->pred_size() == 1) { + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*BB, TBB, FBB, Cond, false) && Cond.empty()) + InitRegPressure(*BB->pred_begin()); + } + + for (MachineBasicBlock::iterator MII = BB->begin(), E = BB->end(); + MII != E; ++MII) { + MachineInstr *MI = &*MII; + for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + bool isNew = RegSeen.insert(Reg); + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (MO.isDef()) + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + else { + bool isKill = isOperandKill(MO, MRI); + if (isNew && !isKill) + // Haven't seen this, it must be a livein. + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + else if (!isNew && isKill) + RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT); + } + } + } +} + +/// UpdateRegPressure - Update estimate of register pressure after the +/// specified instruction. +void MachineLICM::UpdateRegPressure(const MachineInstr *MI) { + if (MI->isImplicitDef()) + return; + + SmallVector Defs; + for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + bool isNew = RegSeen.insert(Reg); + if (MO.isDef()) + Defs.push_back(Reg); + else if (!isNew && isOperandKill(MO, MRI)) { + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCCost = TLI->getRepRegClassCostFor(VT); + + if (RCCost > RegPressure[RCId]) + RegPressure[RCId] = 0; + else + RegPressure[RCId] -= RCCost; + } + } + + while (!Defs.empty()) { + unsigned Reg = Defs.pop_back_val(); + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCCost = TLI->getRepRegClassCostFor(VT); + RegPressure[RCId] += RCCost; + } +} + +/// IsLICMCandidate - Returns true if the instruction may be a suitable +/// candidate for LICM. e.g. If the instruction is a call, then it's obviously +/// not safe to hoist it. +bool MachineLICM::IsLICMCandidate(MachineInstr &I) { + // Check if it's safe to move the instruction. + bool DontMoveAcrossStore = true; + if (!I.isSafeToMove(TII, AA, DontMoveAcrossStore)) + return false; + + return true; +} + +/// IsLoopInvariantInst - Returns true if the instruction is loop +/// invariant. I.e., all virtual register operands are defined outside of the +/// loop, physical registers aren't accessed explicitly, and there are no side +/// effects that aren't captured by the operands or other flags. +/// +bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { + if (!IsLICMCandidate(I)) + return false; + + // The instruction is loop invariant if all of its operands are. + for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I.getOperand(i); + + if (!MO.isReg()) + continue; + + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + // Don't hoist an instruction that uses or defines a physical register. + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!MRI->def_empty(Reg)) + return false; + if (AllocatableSet.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!MRI->def_empty(AliasReg)) + return false; + if (AllocatableSet.test(AliasReg)) + return false; + } + // Otherwise it's safe to move. + continue; + } else if (!MO.isDead()) { + // A def that isn't dead. We can't move it. + return false; + } else if (CurLoop->getHeader()->isLiveIn(Reg)) { + // If the reg is live into the loop, we can't hoist an instruction + // which would clobber it. + return false; + } + } + + if (!MO.isUse()) + continue; + + assert(MRI->getVRegDef(Reg) && + "Machine instr not mapped for this vreg?!"); + + // If the loop contains the definition of an operand, then the instruction + // isn't loop invariant. + if (CurLoop->contains(MRI->getVRegDef(Reg))) + return false; + } + + // If we got this far, the instruction is loop invariant! + return true; +} + + +/// HasPHIUses - Return true if the specified register has any PHI use. +static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *MRI) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (UseMI->isPHI()) + return true; + } + return false; +} + + +/// HasHighOperandLatency - Compute operand latency between a def of 'Reg' +/// and an use in the current loop, return true if the target considered +/// it 'high'. +bool MachineLICM::HasHighOperandLatency(MachineInstr &MI, + unsigned DefIdx, unsigned Reg) const { + if (!InstrItins || InstrItins->isEmpty() || MRI->use_nodbg_empty(Reg)) + return false; + + for (MachineRegisterInfo::use_nodbg_iterator I = MRI->use_nodbg_begin(Reg), + E = MRI->use_nodbg_end(); I != E; ++I) { + MachineInstr *UseMI = &*I; + if (UseMI->isCopyLike()) + continue; + if (!CurLoop->contains(UseMI->getParent())) + continue; + for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = UseMI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (MOReg != Reg) + continue; + + if (TII->hasHighOperandLatency(InstrItins, MRI, &MI, DefIdx, UseMI, i)) + return true; + } + + // Only look at the first in loop use. + break; + } + + return false; +} + +/// IsCheapInstruction - Return true if the instruction is marked "cheap" or +/// the operand latency between its def and a use is one or less. +bool MachineLICM::IsCheapInstruction(MachineInstr &MI) const { + if (MI.getDesc().isAsCheapAsAMove() || MI.isCopyLike()) + return true; + if (!InstrItins || InstrItins->isEmpty()) + return false; + + bool isCheap = false; + unsigned NumDefs = MI.getDesc().getNumDefs(); + for (unsigned i = 0, e = MI.getNumOperands(); NumDefs && i != e; ++i) { + MachineOperand &DefMO = MI.getOperand(i); + if (!DefMO.isReg() || !DefMO.isDef()) + continue; + --NumDefs; + unsigned Reg = DefMO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + + if (!TII->hasLowDefLatency(InstrItins, &MI, i)) + return false; + isCheap = true; + } + + return isCheap; +} + +/// CanCauseHighRegPressure - Visit BBs from header to current BB, check +/// if hoisting an instruction of the given cost matrix can cause high +/// register pressure. +bool MachineLICM::CanCauseHighRegPressure(DenseMap &Cost) { + for (DenseMap::iterator CI = Cost.begin(), CE = Cost.end(); + CI != CE; ++CI) { + if (CI->second <= 0) + continue; + + unsigned RCId = CI->first; + for (unsigned i = BackTrace.size(); i != 0; --i) { + SmallVector &RP = BackTrace[i-1]; + if (RP[RCId] + CI->second >= RegLimit[RCId]) + return true; + } + } + + return false; +} + +/// UpdateBackTraceRegPressure - Traverse the back trace from header to the +/// current block and update their register pressures to reflect the effect +/// of hoisting MI from the current block to the preheader. +void MachineLICM::UpdateBackTraceRegPressure(const MachineInstr *MI) { + if (MI->isImplicitDef()) + return; + + // First compute the 'cost' of the instruction, i.e. its contribution + // to register pressure. + DenseMap Cost; + for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCCost = TLI->getRepRegClassCostFor(VT); + if (MO.isDef()) { + DenseMap::iterator CI = Cost.find(RCId); + if (CI != Cost.end()) + CI->second += RCCost; + else + Cost.insert(std::make_pair(RCId, RCCost)); + } else if (isOperandKill(MO, MRI)) { + DenseMap::iterator CI = Cost.find(RCId); + if (CI != Cost.end()) + CI->second -= RCCost; + else + Cost.insert(std::make_pair(RCId, -RCCost)); + } + } + + // Update register pressure of blocks from loop header to current block. + for (unsigned i = 0, e = BackTrace.size(); i != e; ++i) { + SmallVector &RP = BackTrace[i]; + for (DenseMap::iterator CI = Cost.begin(), CE = Cost.end(); + CI != CE; ++CI) { + unsigned RCId = CI->first; + RP[RCId] += CI->second; + } + } +} + +/// IsProfitableToHoist - Return true if it is potentially profitable to hoist +/// the given loop invariant. +bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { + if (MI.isImplicitDef()) + return true; + + // If the instruction is cheap, only hoist if it is re-materilizable. LICM + // will increase register pressure. It's probably not worth it if the + // instruction is cheap. + // Also hoist loads from constant memory, e.g. load from stubs, GOT. Hoisting + // these tend to help performance in low register pressure situation. The + // trade off is it may cause spill in high pressure situation. It will end up + // adding a store in the loop preheader. But the reload is no more expensive. + // The side benefit is these loads are frequently CSE'ed. + if (IsCheapInstruction(MI)) { + if (!TII->isTriviallyReMaterializable(&MI, AA)) + return false; + } else { + // Estimate register pressure to determine whether to LICM the instruction. + // In low register pressure situation, we can be more aggressive about + // hoisting. Also, favors hoisting long latency instructions even in + // moderately high pressure situation. + // FIXME: If there are long latency loop-invariant instructions inside the + // loop at this point, why didn't the optimizer's LICM hoist them? + DenseMap Cost; + for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (MO.isDef()) { + if (HasHighOperandLatency(MI, i, Reg)) { + ++NumHighLatency; + return true; + } + + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCCost = TLI->getRepRegClassCostFor(VT); + DenseMap::iterator CI = Cost.find(RCId); + if (CI != Cost.end()) + CI->second += RCCost; + else + Cost.insert(std::make_pair(RCId, RCCost)); + } else if (isOperandKill(MO, MRI)) { + // Is a virtual register use is a kill, hoisting it out of the loop + // may actually reduce register pressure or be register pressure + // neutral. + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + EVT VT = *RC->vt_begin(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned RCCost = TLI->getRepRegClassCostFor(VT); + DenseMap::iterator CI = Cost.find(RCId); + if (CI != Cost.end()) + CI->second -= RCCost; + else + Cost.insert(std::make_pair(RCId, -RCCost)); + } + } + + // Visit BBs from header to current BB, if hoisting this doesn't cause + // high register pressure, then it's safe to proceed. + if (!CanCauseHighRegPressure(Cost)) { + ++NumLowRP; + return true; + } + + // High register pressure situation, only hoist if the instruction is going to + // be remat'ed. + if (!TII->isTriviallyReMaterializable(&MI, AA) && + !MI.isInvariantLoad(AA)) + return false; + } + + // If result(s) of this instruction is used by PHIs, then don't hoist it. + // The presence of joins makes it difficult for current register allocator + // implementation to perform remat. + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + if (HasPHIUses(MO.getReg(), MRI)) + return false; + } + + return true; +} + +MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { + // Don't unfold simple loads. + if (MI->getDesc().canFoldAsLoad()) + return 0; + + // If not, we may be able to unfold a load and hoist that. + // First test whether the instruction is loading from an amenable + // memory location. + if (!MI->isInvariantLoad(AA)) + return 0; + + // Next determine the register class for a temporary register. + unsigned LoadRegIndex; + unsigned NewOpc = + TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), + /*UnfoldLoad=*/true, + /*UnfoldStore=*/false, + &LoadRegIndex); + if (NewOpc == 0) return 0; + const TargetInstrDesc &TID = TII->get(NewOpc); + if (TID.getNumDefs() != 1) return 0; + const TargetRegisterClass *RC = TID.OpInfo[LoadRegIndex].getRegClass(TRI); + // Ok, we're unfolding. Create a temporary register and do the unfold. + unsigned Reg = MRI->createVirtualRegister(RC); + + MachineFunction &MF = *MI->getParent()->getParent(); + SmallVector NewMIs; + bool Success = + TII->unfoldMemoryOperand(MF, MI, Reg, + /*UnfoldLoad=*/true, /*UnfoldStore=*/false, + NewMIs); + (void)Success; + assert(Success && + "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold " + "succeeded!"); + assert(NewMIs.size() == 2 && + "Unfolded a load into multiple instructions!"); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MI, NewMIs[0]); + MBB->insert(MI, NewMIs[1]); + // If unfolding produced a load that wasn't loop-invariant or profitable to + // hoist, discard the new instructions and bail. + if (!IsLoopInvariantInst(*NewMIs[0]) || !IsProfitableToHoist(*NewMIs[0])) { + NewMIs[0]->eraseFromParent(); + NewMIs[1]->eraseFromParent(); + return 0; + } + + // Update register pressure for the unfolded instruction. + UpdateRegPressure(NewMIs[1]); + + // Otherwise we successfully unfolded a load that we can hoist. + MI->eraseFromParent(); + return NewMIs[0]; +} + +void MachineLICM::InitCSEMap(MachineBasicBlock *BB) { + for (MachineBasicBlock::iterator I = BB->begin(),E = BB->end(); I != E; ++I) { + const MachineInstr *MI = &*I; + unsigned Opcode = MI->getOpcode(); + DenseMap >::iterator + CI = CSEMap.find(Opcode); + if (CI != CSEMap.end()) + CI->second.push_back(MI); + else { + std::vector CSEMIs; + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); + } + } +} + +const MachineInstr* +MachineLICM::LookForDuplicate(const MachineInstr *MI, + std::vector &PrevMIs) { + for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) { + const MachineInstr *PrevMI = PrevMIs[i]; + if (TII->produceSameValue(MI, PrevMI, (PreRegAlloc ? MRI : 0))) + return PrevMI; + } + return 0; +} + +bool MachineLICM::EliminateCSE(MachineInstr *MI, + DenseMap >::iterator &CI) { + // Do not CSE implicit_def so ProcessImplicitDefs can properly propagate + // the undef property onto uses. + if (CI == CSEMap.end() || MI->isImplicitDef()) + return false; + + if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) { + DEBUG(dbgs() << "CSEing " << *MI << " with " << *Dup); + + // Replace virtual registers defined by MI by their counterparts defined + // by Dup. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + // Physical registers may not differ here. + assert((!MO.isReg() || MO.getReg() == 0 || + !TargetRegisterInfo::isPhysicalRegister(MO.getReg()) || + MO.getReg() == Dup->getOperand(i).getReg()) && + "Instructions with different phys regs are not identical!"); + + if (MO.isReg() && MO.isDef() && + !TargetRegisterInfo::isPhysicalRegister(MO.getReg())) { + MRI->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); + MRI->clearKillFlags(Dup->getOperand(i).getReg()); + } + } + MI->eraseFromParent(); + ++NumCSEed; + return true; + } + return false; +} + +/// Hoist - When an instruction is found to use only loop invariant operands +/// that are safe to hoist, this instruction is called to do the dirty work. +/// +bool MachineLICM::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader) { + // First check whether we should hoist this instruction. + if (!IsLoopInvariantInst(*MI) || !IsProfitableToHoist(*MI)) { + // If not, try unfolding a hoistable load. + MI = ExtractHoistableLoad(MI); + if (!MI) return false; + } + + // Now move the instructions to the predecessor, inserting it before any + // terminator instructions. + DEBUG({ + dbgs() << "Hoisting " << *MI; + if (Preheader->getBasicBlock()) + dbgs() << " to MachineBasicBlock " + << Preheader->getName(); + if (MI->getParent()->getBasicBlock()) + dbgs() << " from MachineBasicBlock " + << MI->getParent()->getName(); + dbgs() << "\n"; + }); + + // If this is the first instruction being hoisted to the preheader, + // initialize the CSE map with potential common expressions. + if (FirstInLoop) { + InitCSEMap(Preheader); + FirstInLoop = false; + } + + // Look for opportunity to CSE the hoisted instruction. + unsigned Opcode = MI->getOpcode(); + DenseMap >::iterator + CI = CSEMap.find(Opcode); + if (!EliminateCSE(MI, CI)) { + // Otherwise, splice the instruction to the preheader. + Preheader->splice(Preheader->getFirstTerminator(),MI->getParent(),MI); + + // Update register pressure for BBs from header to this block. + UpdateBackTraceRegPressure(MI); + + // Clear the kill flags of any register this instruction defines, + // since they may need to be live throughout the entire loop + // rather than just live for part of it. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && !MO.isDead()) + MRI->clearKillFlags(MO.getReg()); + } + + // Add to the CSE map. + if (CI != CSEMap.end()) + CI->second.push_back(MI); + else { + std::vector CSEMIs; + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); + } + } + + ++NumHoisted; + Changed = true; + + return true; +} + +MachineBasicBlock *MachineLICM::getCurPreheader() { + // Determine the block to which to hoist instructions. If we can't find a + // suitable loop predecessor, we can't do any hoisting. + + // If we've tried to get a preheader and failed, don't try again. + if (CurPreheader == reinterpret_cast(-1)) + return 0; + + if (!CurPreheader) { + CurPreheader = CurLoop->getLoopPreheader(); + if (!CurPreheader) { + MachineBasicBlock *Pred = CurLoop->getLoopPredecessor(); + if (!Pred) { + CurPreheader = reinterpret_cast(-1); + return 0; + } + + CurPreheader = Pred->SplitCriticalEdge(CurLoop->getHeader(), this); + if (!CurPreheader) { + CurPreheader = reinterpret_cast(-1); + return 0; + } + } + } + return CurPreheader; +} diff --git a/final/lib/CodeGen/MachineLoopInfo.cpp b/final/lib/CodeGen/MachineLoopInfo.cpp new file mode 100644 index 00000000000..189cb2ba5d1 --- /dev/null +++ b/final/lib/CodeGen/MachineLoopInfo.cpp @@ -0,0 +1,83 @@ +//===- MachineLoopInfo.cpp - Natural Loop Calculator ----------------------===// +// +// 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 MachineLoopInfo class that is used to identify natural +// loops and determine the loop depth of various nodes of the CFG. Note that +// the loops identified may actually be several natural loops that share the +// same header node... not just a single natural loop. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace llvm { +#define MLB class LoopBase +TEMPLATE_INSTANTIATION(MLB); +#undef MLB +#define MLIB class LoopInfoBase +TEMPLATE_INSTANTIATION(MLIB); +#undef MLIB +} + +char MachineLoopInfo::ID = 0; +INITIALIZE_PASS_BEGIN(MachineLoopInfo, "machine-loops", + "Machine Natural Loop Construction", true, true) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_END(MachineLoopInfo, "machine-loops", + "Machine Natural Loop Construction", true, true) + +char &llvm::MachineLoopInfoID = MachineLoopInfo::ID; + +bool MachineLoopInfo::runOnMachineFunction(MachineFunction &) { + releaseMemory(); + LI.Calculate(getAnalysis().getBase()); // Update + return false; +} + +void MachineLoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +MachineBasicBlock *MachineLoop::getTopBlock() { + MachineBasicBlock *TopMBB = getHeader(); + MachineFunction::iterator Begin = TopMBB->getParent()->begin(); + if (TopMBB != Begin) { + MachineBasicBlock *PriorMBB = prior(MachineFunction::iterator(TopMBB)); + while (contains(PriorMBB)) { + TopMBB = PriorMBB; + if (TopMBB == Begin) break; + PriorMBB = prior(MachineFunction::iterator(TopMBB)); + } + } + return TopMBB; +} + +MachineBasicBlock *MachineLoop::getBottomBlock() { + MachineBasicBlock *BotMBB = getHeader(); + MachineFunction::iterator End = BotMBB->getParent()->end(); + if (BotMBB != prior(End)) { + MachineBasicBlock *NextMBB = llvm::next(MachineFunction::iterator(BotMBB)); + while (contains(NextMBB)) { + BotMBB = NextMBB; + if (BotMBB == llvm::next(MachineFunction::iterator(BotMBB))) break; + NextMBB = llvm::next(MachineFunction::iterator(BotMBB)); + } + } + return BotMBB; +} + +void MachineLoop::dump() const { + print(dbgs()); +} diff --git a/final/lib/CodeGen/MachineLoopRanges.cpp b/final/lib/CodeGen/MachineLoopRanges.cpp new file mode 100644 index 00000000000..17fe67f6504 --- /dev/null +++ b/final/lib/CodeGen/MachineLoopRanges.cpp @@ -0,0 +1,116 @@ +//===- MachineLoopRanges.cpp - Ranges of machine loops --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the implementation of the MachineLoopRanges analysis. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineLoopRanges.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +char MachineLoopRanges::ID = 0; +INITIALIZE_PASS_BEGIN(MachineLoopRanges, "machine-loop-ranges", + "Machine Loop Ranges", true, true) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(MachineLoopRanges, "machine-loop-ranges", + "Machine Loop Ranges", true, true) + +char &llvm::MachineLoopRangesID = MachineLoopRanges::ID; + +void MachineLoopRanges::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +/// runOnMachineFunction - Don't do much, loop ranges are computed on demand. +bool MachineLoopRanges::runOnMachineFunction(MachineFunction &) { + releaseMemory(); + Indexes = &getAnalysis(); + return false; +} + +void MachineLoopRanges::releaseMemory() { + DeleteContainerSeconds(Cache); + Cache.clear(); +} + +MachineLoopRange *MachineLoopRanges::getLoopRange(const MachineLoop *Loop) { + MachineLoopRange *&Range = Cache[Loop]; + if (!Range) + Range = new MachineLoopRange(Loop, Allocator, *Indexes); + return Range; +} + +/// Create a MachineLoopRange, only accessible to MachineLoopRanges. +MachineLoopRange::MachineLoopRange(const MachineLoop *loop, + MachineLoopRange::Allocator &alloc, + SlotIndexes &Indexes) + : Loop(loop), Intervals(alloc), Area(0) { + // Compute loop coverage. + for (MachineLoop::block_iterator I = Loop->block_begin(), + E = Loop->block_end(); I != E; ++I) { + const std::pair &Range = Indexes.getMBBRange(*I); + Intervals.insert(Range.first, Range.second, 1u); + Area += Range.first.distance(Range.second); + } +} + +/// overlaps - Return true if this loop overlaps the given range of machine +/// instructions. +bool MachineLoopRange::overlaps(SlotIndex Start, SlotIndex Stop) { + Map::const_iterator I = Intervals.find(Start); + return I.valid() && Stop > I.start(); +} + +unsigned MachineLoopRange::getNumber() const { + return Loop->getHeader()->getNumber(); +} + +/// byNumber - Comparator for array_pod_sort that sorts a list of +/// MachineLoopRange pointers by number. +int MachineLoopRange::byNumber(const void *pa, const void *pb) { + const MachineLoopRange *a = *static_cast(pa); + const MachineLoopRange *b = *static_cast(pb); + unsigned na = a->getNumber(); + unsigned nb = b->getNumber(); + if (na < nb) + return -1; + if (na > nb) + return 1; + return 0; +} + +/// byAreaDesc - Comparator for array_pod_sort that sorts a list of +/// MachineLoopRange pointers by: +/// 1. Descending area. +/// 2. Ascending number. +int MachineLoopRange::byAreaDesc(const void *pa, const void *pb) { + const MachineLoopRange *a = *static_cast(pa); + const MachineLoopRange *b = *static_cast(pb); + if (a->getArea() != b->getArea()) + return a->getArea() > b->getArea() ? -1 : 1; + return byNumber(pa, pb); +} + +void MachineLoopRange::print(raw_ostream &OS) const { + OS << "Loop#" << getNumber() << " ="; + for (Map::const_iterator I = Intervals.begin(); I.valid(); ++I) + OS << " [" << I.start() << ';' << I.stop() << ')'; +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineLoopRange &MLR) { + MLR.print(OS); + return OS; +} diff --git a/final/lib/CodeGen/MachineModuleInfo.cpp b/final/lib/CodeGen/MachineModuleInfo.cpp new file mode 100644 index 00000000000..fadc594efcb --- /dev/null +++ b/final/lib/CodeGen/MachineModuleInfo.cpp @@ -0,0 +1,567 @@ +//===-- llvm/CodeGen/MachineModuleInfo.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineModuleInfo.h" + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Module.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; +using namespace llvm::dwarf; + +// Handle the Pass registration stuff necessary to use TargetData's. +INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo", + "Machine Module Information", false, false) +char MachineModuleInfo::ID = 0; + +// Out of line virtual method. +MachineModuleInfoImpl::~MachineModuleInfoImpl() {} + +namespace llvm { +class MMIAddrLabelMapCallbackPtr : CallbackVH { + MMIAddrLabelMap *Map; +public: + MMIAddrLabelMapCallbackPtr() : Map(0) {} + MMIAddrLabelMapCallbackPtr(Value *V) : CallbackVH(V), Map(0) {} + + void setPtr(BasicBlock *BB) { + ValueHandleBase::operator=(BB); + } + + void setMap(MMIAddrLabelMap *map) { Map = map; } + + virtual void deleted(); + virtual void allUsesReplacedWith(Value *V2); +}; + +class MMIAddrLabelMap { + MCContext &Context; + struct AddrLabelSymEntry { + /// Symbols - The symbols for the label. This is a pointer union that is + /// either one symbol (the common case) or a list of symbols. + PointerUnion*> Symbols; + + Function *Fn; // The containing function of the BasicBlock. + unsigned Index; // The index in BBCallbacks for the BasicBlock. + }; + + DenseMap, AddrLabelSymEntry> AddrLabelSymbols; + + /// BBCallbacks - Callbacks for the BasicBlock's that we have entries for. We + /// use this so we get notified if a block is deleted or RAUWd. + std::vector BBCallbacks; + + /// DeletedAddrLabelsNeedingEmission - This is a per-function list of symbols + /// whose corresponding BasicBlock got deleted. These symbols need to be + /// emitted at some point in the file, so AsmPrinter emits them after the + /// function body. + DenseMap, std::vector > + DeletedAddrLabelsNeedingEmission; +public: + + MMIAddrLabelMap(MCContext &context) : Context(context) {} + ~MMIAddrLabelMap() { + assert(DeletedAddrLabelsNeedingEmission.empty() && + "Some labels for deleted blocks never got emitted"); + + // Deallocate any of the 'list of symbols' case. + for (DenseMap, AddrLabelSymEntry>::iterator + I = AddrLabelSymbols.begin(), E = AddrLabelSymbols.end(); I != E; ++I) + if (I->second.Symbols.is*>()) + delete I->second.Symbols.get*>(); + } + + MCSymbol *getAddrLabelSymbol(BasicBlock *BB); + std::vector getAddrLabelSymbolToEmit(BasicBlock *BB); + + void takeDeletedSymbolsForFunction(Function *F, + std::vector &Result); + + void UpdateForDeletedBlock(BasicBlock *BB); + void UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New); +}; +} + +MCSymbol *MMIAddrLabelMap::getAddrLabelSymbol(BasicBlock *BB) { + assert(BB->hasAddressTaken() && + "Shouldn't get label for block without address taken"); + AddrLabelSymEntry &Entry = AddrLabelSymbols[BB]; + + // If we already had an entry for this block, just return it. + if (!Entry.Symbols.isNull()) { + assert(BB->getParent() == Entry.Fn && "Parent changed"); + if (Entry.Symbols.is()) + return Entry.Symbols.get(); + return (*Entry.Symbols.get*>())[0]; + } + + // Otherwise, this is a new entry, create a new symbol for it and add an + // entry to BBCallbacks so we can be notified if the BB is deleted or RAUWd. + BBCallbacks.push_back(BB); + BBCallbacks.back().setMap(this); + Entry.Index = BBCallbacks.size()-1; + Entry.Fn = BB->getParent(); + MCSymbol *Result = Context.CreateTempSymbol(); + Entry.Symbols = Result; + return Result; +} + +std::vector +MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) { + assert(BB->hasAddressTaken() && + "Shouldn't get label for block without address taken"); + AddrLabelSymEntry &Entry = AddrLabelSymbols[BB]; + + std::vector Result; + + // If we already had an entry for this block, just return it. + if (Entry.Symbols.isNull()) + Result.push_back(getAddrLabelSymbol(BB)); + else if (MCSymbol *Sym = Entry.Symbols.dyn_cast()) + Result.push_back(Sym); + else + Result = *Entry.Symbols.get*>(); + return Result; +} + + +/// takeDeletedSymbolsForFunction - If we have any deleted symbols for F, return +/// them. +void MMIAddrLabelMap:: +takeDeletedSymbolsForFunction(Function *F, std::vector &Result) { + DenseMap, std::vector >::iterator I = + DeletedAddrLabelsNeedingEmission.find(F); + + // If there are no entries for the function, just return. + if (I == DeletedAddrLabelsNeedingEmission.end()) return; + + // Otherwise, take the list. + std::swap(Result, I->second); + DeletedAddrLabelsNeedingEmission.erase(I); +} + + +void MMIAddrLabelMap::UpdateForDeletedBlock(BasicBlock *BB) { + // If the block got deleted, there is no need for the symbol. If the symbol + // was already emitted, we can just forget about it, otherwise we need to + // queue it up for later emission when the function is output. + AddrLabelSymEntry Entry = AddrLabelSymbols[BB]; + AddrLabelSymbols.erase(BB); + assert(!Entry.Symbols.isNull() && "Didn't have a symbol, why a callback?"); + BBCallbacks[Entry.Index] = 0; // Clear the callback. + + assert((BB->getParent() == 0 || BB->getParent() == Entry.Fn) && + "Block/parent mismatch"); + + // Handle both the single and the multiple symbols cases. + if (MCSymbol *Sym = Entry.Symbols.dyn_cast()) { + if (Sym->isDefined()) + return; + + // If the block is not yet defined, we need to emit it at the end of the + // function. Add the symbol to the DeletedAddrLabelsNeedingEmission list + // for the containing Function. Since the block is being deleted, its + // parent may already be removed, we have to get the function from 'Entry'. + DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym); + } else { + std::vector *Syms = Entry.Symbols.get*>(); + + for (unsigned i = 0, e = Syms->size(); i != e; ++i) { + MCSymbol *Sym = (*Syms)[i]; + if (Sym->isDefined()) continue; // Ignore already emitted labels. + + // If the block is not yet defined, we need to emit it at the end of the + // function. Add the symbol to the DeletedAddrLabelsNeedingEmission list + // for the containing Function. Since the block is being deleted, its + // parent may already be removed, we have to get the function from + // 'Entry'. + DeletedAddrLabelsNeedingEmission[Entry.Fn].push_back(Sym); + } + + // The entry is deleted, free the memory associated with the symbol list. + delete Syms; + } +} + +void MMIAddrLabelMap::UpdateForRAUWBlock(BasicBlock *Old, BasicBlock *New) { + // Get the entry for the RAUW'd block and remove it from our map. + AddrLabelSymEntry OldEntry = AddrLabelSymbols[Old]; + AddrLabelSymbols.erase(Old); + assert(!OldEntry.Symbols.isNull() && "Didn't have a symbol, why a callback?"); + + AddrLabelSymEntry &NewEntry = AddrLabelSymbols[New]; + + // If New is not address taken, just move our symbol over to it. + if (NewEntry.Symbols.isNull()) { + BBCallbacks[OldEntry.Index].setPtr(New); // Update the callback. + NewEntry = OldEntry; // Set New's entry. + return; + } + + BBCallbacks[OldEntry.Index] = 0; // Update the callback. + + // Otherwise, we need to add the old symbol to the new block's set. If it is + // just a single entry, upgrade it to a symbol list. + if (MCSymbol *PrevSym = NewEntry.Symbols.dyn_cast()) { + std::vector *SymList = new std::vector(); + SymList->push_back(PrevSym); + NewEntry.Symbols = SymList; + } + + std::vector *SymList = + NewEntry.Symbols.get*>(); + + // If the old entry was a single symbol, add it. + if (MCSymbol *Sym = OldEntry.Symbols.dyn_cast()) { + SymList->push_back(Sym); + return; + } + + // Otherwise, concatenate the list. + std::vector *Syms =OldEntry.Symbols.get*>(); + SymList->insert(SymList->end(), Syms->begin(), Syms->end()); + delete Syms; +} + + +void MMIAddrLabelMapCallbackPtr::deleted() { + Map->UpdateForDeletedBlock(cast(getValPtr())); +} + +void MMIAddrLabelMapCallbackPtr::allUsesReplacedWith(Value *V2) { + Map->UpdateForRAUWBlock(cast(getValPtr()), cast(V2)); +} + + +//===----------------------------------------------------------------------===// + +MachineModuleInfo::MachineModuleInfo(const MCAsmInfo &MAI, + const TargetAsmInfo *TAI) +: ImmutablePass(ID), Context(MAI, TAI), + ObjFileMMI(0), + CurCallSite(0), CallsEHReturn(0), CallsUnwindInit(0), DbgInfoAvailable(false), + CallsExternalVAFunctionWithFloatingPointArguments(false) { + initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); + // Always emit some info, by default "no personality" info. + Personalities.push_back(NULL); + AddrLabelSymbols = 0; + TheModule = 0; +} + +MachineModuleInfo::MachineModuleInfo() +: ImmutablePass(ID), Context(*(MCAsmInfo*)0, NULL) { + assert(0 && "This MachineModuleInfo constructor should never be called, MMI " + "should always be explicitly constructed by LLVMTargetMachine"); + abort(); +} + +MachineModuleInfo::~MachineModuleInfo() { + delete ObjFileMMI; + + // FIXME: Why isn't doFinalization being called?? + //assert(AddrLabelSymbols == 0 && "doFinalization not called"); + delete AddrLabelSymbols; + AddrLabelSymbols = 0; +} + +/// doInitialization - Initialize the state for a new module. +/// +bool MachineModuleInfo::doInitialization() { + assert(AddrLabelSymbols == 0 && "Improperly initialized"); + return false; +} + +/// doFinalization - Tear down the state after completion of a module. +/// +bool MachineModuleInfo::doFinalization() { + delete AddrLabelSymbols; + AddrLabelSymbols = 0; + return false; +} + +/// EndFunction - Discard function meta information. +/// +void MachineModuleInfo::EndFunction() { + // Clean up frame info. + FrameMoves.clear(); + + // Clean up exception info. + LandingPads.clear(); + CallSiteMap.clear(); + TypeInfos.clear(); + FilterIds.clear(); + FilterEnds.clear(); + CallsEHReturn = 0; + CallsUnwindInit = 0; + VariableDbgInfo.clear(); +} + +/// AnalyzeModule - Scan the module for global debug information. +/// +void MachineModuleInfo::AnalyzeModule(const Module &M) { + // Insert functions in the llvm.used array (but not llvm.compiler.used) into + // UsedFunctions. + const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); + if (!GV || !GV->hasInitializer()) return; + + // Should be an array of 'i8*'. + const ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (InitList == 0) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (const Function *F = + dyn_cast(InitList->getOperand(i)->stripPointerCasts())) + UsedFunctions.insert(F); +} + +//===- Address of Block Management ----------------------------------------===// + + +/// getAddrLabelSymbol - Return the symbol to be used for the specified basic +/// block when its address is taken. This cannot be its normal LBB label +/// because the block may be accessed outside its containing function. +MCSymbol *MachineModuleInfo::getAddrLabelSymbol(const BasicBlock *BB) { + // Lazily create AddrLabelSymbols. + if (AddrLabelSymbols == 0) + AddrLabelSymbols = new MMIAddrLabelMap(Context); + return AddrLabelSymbols->getAddrLabelSymbol(const_cast(BB)); +} + +/// getAddrLabelSymbolToEmit - Return the symbol to be used for the specified +/// basic block when its address is taken. If other blocks were RAUW'd to +/// this one, we may have to emit them as well, return the whole set. +std::vector MachineModuleInfo:: +getAddrLabelSymbolToEmit(const BasicBlock *BB) { + // Lazily create AddrLabelSymbols. + if (AddrLabelSymbols == 0) + AddrLabelSymbols = new MMIAddrLabelMap(Context); + return AddrLabelSymbols->getAddrLabelSymbolToEmit(const_cast(BB)); +} + + +/// takeDeletedSymbolsForFunction - If the specified function has had any +/// references to address-taken blocks generated, but the block got deleted, +/// return the symbol now so we can emit it. This prevents emitting a +/// reference to a symbol that has no definition. +void MachineModuleInfo:: +takeDeletedSymbolsForFunction(const Function *F, + std::vector &Result) { + // If no blocks have had their addresses taken, we're done. + if (AddrLabelSymbols == 0) return; + return AddrLabelSymbols-> + takeDeletedSymbolsForFunction(const_cast(F), Result); +} + +//===- EH -----------------------------------------------------------------===// + +/// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the +/// specified MachineBasicBlock. +LandingPadInfo &MachineModuleInfo::getOrCreateLandingPadInfo + (MachineBasicBlock *LandingPad) { + unsigned N = LandingPads.size(); + for (unsigned i = 0; i < N; ++i) { + LandingPadInfo &LP = LandingPads[i]; + if (LP.LandingPadBlock == LandingPad) + return LP; + } + + LandingPads.push_back(LandingPadInfo(LandingPad)); + return LandingPads[N]; +} + +/// addInvoke - Provide the begin and end labels of an invoke style call and +/// associate it with a try landing pad block. +void MachineModuleInfo::addInvoke(MachineBasicBlock *LandingPad, + MCSymbol *BeginLabel, MCSymbol *EndLabel) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.BeginLabels.push_back(BeginLabel); + LP.EndLabels.push_back(EndLabel); +} + +/// addLandingPad - Provide the label of a try LandingPad block. +/// +MCSymbol *MachineModuleInfo::addLandingPad(MachineBasicBlock *LandingPad) { + MCSymbol *LandingPadLabel = Context.CreateTempSymbol(); + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.LandingPadLabel = LandingPadLabel; + return LandingPadLabel; +} + +/// addPersonality - Provide the personality function for the exception +/// information. +void MachineModuleInfo::addPersonality(MachineBasicBlock *LandingPad, + const Function *Personality) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.Personality = Personality; + + for (unsigned i = 0; i < Personalities.size(); ++i) + if (Personalities[i] == Personality) + return; + + // If this is the first personality we're adding go + // ahead and add it at the beginning. + if (Personalities[0] == NULL) + Personalities[0] = Personality; + else + Personalities.push_back(Personality); +} + +/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. +/// +void MachineModuleInfo::addCatchTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + for (unsigned N = TyInfo.size(); N; --N) + LP.TypeIds.push_back(getTypeIDFor(TyInfo[N - 1])); +} + +/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. +/// +void MachineModuleInfo::addFilterTypeInfo(MachineBasicBlock *LandingPad, + std::vector &TyInfo) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + std::vector IdsInFilter(TyInfo.size()); + for (unsigned I = 0, E = TyInfo.size(); I != E; ++I) + IdsInFilter[I] = getTypeIDFor(TyInfo[I]); + LP.TypeIds.push_back(getFilterIDFor(IdsInFilter)); +} + +/// addCleanup - Add a cleanup action for a landing pad. +/// +void MachineModuleInfo::addCleanup(MachineBasicBlock *LandingPad) { + LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); + LP.TypeIds.push_back(0); +} + +/// TidyLandingPads - Remap landing pad labels and remove any deleted landing +/// pads. +void MachineModuleInfo::TidyLandingPads(DenseMap *LPMap) { + for (unsigned i = 0; i != LandingPads.size(); ) { + LandingPadInfo &LandingPad = LandingPads[i]; + if (LandingPad.LandingPadLabel && + !LandingPad.LandingPadLabel->isDefined() && + (!LPMap || (*LPMap)[LandingPad.LandingPadLabel] == 0)) + LandingPad.LandingPadLabel = 0; + + // Special case: we *should* emit LPs with null LP MBB. This indicates + // "nounwind" case. + if (!LandingPad.LandingPadLabel && LandingPad.LandingPadBlock) { + LandingPads.erase(LandingPads.begin() + i); + continue; + } + + for (unsigned j = 0, e = LandingPads[i].BeginLabels.size(); j != e; ++j) { + MCSymbol *BeginLabel = LandingPad.BeginLabels[j]; + MCSymbol *EndLabel = LandingPad.EndLabels[j]; + if ((BeginLabel->isDefined() || + (LPMap && (*LPMap)[BeginLabel] != 0)) && + (EndLabel->isDefined() || + (LPMap && (*LPMap)[EndLabel] != 0))) continue; + + LandingPad.BeginLabels.erase(LandingPad.BeginLabels.begin() + j); + LandingPad.EndLabels.erase(LandingPad.EndLabels.begin() + j); + --j, --e; + } + + // Remove landing pads with no try-ranges. + if (LandingPads[i].BeginLabels.empty()) { + LandingPads.erase(LandingPads.begin() + i); + continue; + } + + // If there is no landing pad, ensure that the list of typeids is empty. + // If the only typeid is a cleanup, this is the same as having no typeids. + if (!LandingPad.LandingPadBlock || + (LandingPad.TypeIds.size() == 1 && !LandingPad.TypeIds[0])) + LandingPad.TypeIds.clear(); + ++i; + } +} + +/// getTypeIDFor - Return the type id for the specified typeinfo. This is +/// function wide. +unsigned MachineModuleInfo::getTypeIDFor(const GlobalVariable *TI) { + for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i) + if (TypeInfos[i] == TI) return i + 1; + + TypeInfos.push_back(TI); + return TypeInfos.size(); +} + +/// getFilterIDFor - Return the filter id for the specified typeinfos. This is +/// function wide. +int MachineModuleInfo::getFilterIDFor(std::vector &TyIds) { + // If the new filter coincides with the tail of an existing filter, then + // re-use the existing filter. Folding filters more than this requires + // re-ordering filters and/or their elements - probably not worth it. + for (std::vector::iterator I = FilterEnds.begin(), + E = FilterEnds.end(); I != E; ++I) { + unsigned i = *I, j = TyIds.size(); + + while (i && j) + if (FilterIds[--i] != TyIds[--j]) + goto try_next; + + if (!j) + // The new filter coincides with range [i, end) of the existing filter. + return -(1 + i); + +try_next:; + } + + // Add the new filter. + int FilterID = -(1 + FilterIds.size()); + FilterIds.reserve(FilterIds.size() + TyIds.size() + 1); + for (unsigned I = 0, N = TyIds.size(); I != N; ++I) + FilterIds.push_back(TyIds[I]); + FilterEnds.push_back(FilterIds.size()); + FilterIds.push_back(0); // terminator + return FilterID; +} + +/// getPersonality - Return the personality function for the current function. +const Function *MachineModuleInfo::getPersonality() const { + // FIXME: Until PR1414 will be fixed, we're using 1 personality function per + // function + return !LandingPads.empty() ? LandingPads[0].Personality : NULL; +} + +/// getPersonalityIndex - Return unique index for current personality +/// function. NULL/first personality function should always get zero index. +unsigned MachineModuleInfo::getPersonalityIndex() const { + const Function* Personality = NULL; + + // Scan landing pads. If there is at least one non-NULL personality - use it. + for (unsigned i = 0; i != LandingPads.size(); ++i) + if (LandingPads[i].Personality) { + Personality = LandingPads[i].Personality; + break; + } + + for (unsigned i = 0; i < Personalities.size(); ++i) { + if (Personalities[i] == Personality) + return i; + } + + // This will happen if the current personality function is + // in the zero index. + return 0; +} diff --git a/final/lib/CodeGen/MachineModuleInfoImpls.cpp b/final/lib/CodeGen/MachineModuleInfoImpls.cpp new file mode 100644 index 00000000000..5ab56c09f5f --- /dev/null +++ b/final/lib/CodeGen/MachineModuleInfoImpls.cpp @@ -0,0 +1,45 @@ +//===-- llvm/CodeGen/MachineModuleInfoImpls.cpp ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements object-file format specific implementations of +// MachineModuleInfoImpl. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MachineModuleInfoMachO +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +void MachineModuleInfoMachO::Anchor() {} +void MachineModuleInfoELF::Anchor() {} + +static int SortSymbolPair(const void *LHS, const void *RHS) { + typedef std::pair PairTy; + const MCSymbol *LHSS = ((const PairTy *)LHS)->first; + const MCSymbol *RHSS = ((const PairTy *)RHS)->first; + return LHSS->getName().compare(RHSS->getName()); +} + +/// GetSortedStubs - Return the entries from a DenseMap in a deterministic +/// sorted orer. +MachineModuleInfoImpl::SymbolListTy +MachineModuleInfoImpl::GetSortedStubs(const DenseMap&Map) { + MachineModuleInfoImpl::SymbolListTy List(Map.begin(), Map.end()); + + if (!List.empty()) + qsort(&List[0], List.size(), sizeof(List[0]), SortSymbolPair); + return List; +} + diff --git a/final/lib/CodeGen/MachinePassRegistry.cpp b/final/lib/CodeGen/MachinePassRegistry.cpp new file mode 100644 index 00000000000..9f4ef128780 --- /dev/null +++ b/final/lib/CodeGen/MachinePassRegistry.cpp @@ -0,0 +1,41 @@ +//===-- CodeGen/MachineInstr.cpp ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the machine function pass registry for register allocators +// and instruction schedulers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachinePassRegistry.h" + +using namespace llvm; + + +/// Add - Adds a function pass to the registration list. +/// +void MachinePassRegistry::Add(MachinePassRegistryNode *Node) { + Node->setNext(List); + List = Node; + if (Listener) Listener->NotifyAdd(Node->getName(), + Node->getCtor(), + Node->getDescription()); +} + + +/// Remove - Removes a function pass from the registration list. +/// +void MachinePassRegistry::Remove(MachinePassRegistryNode *Node) { + for (MachinePassRegistryNode **I = &List; *I; I = (*I)->getNextAddress()) { + if (*I == Node) { + if (Listener) Listener->NotifyRemove(Node->getName()); + *I = (*I)->getNext(); + break; + } + } +} diff --git a/final/lib/CodeGen/MachineRegisterInfo.cpp b/final/lib/CodeGen/MachineRegisterInfo.cpp new file mode 100644 index 00000000000..7244d5f03a9 --- /dev/null +++ b/final/lib/CodeGen/MachineRegisterInfo.cpp @@ -0,0 +1,241 @@ +//===-- lib/Codegen/MachineRegisterInfo.cpp -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the MachineRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) { + VRegInfo.reserve(256); + RegAllocHints.reserve(256); + RegClass2VRegMap = new std::vector[TRI.getNumRegClasses()]; + UsedPhysRegs.resize(TRI.getNumRegs()); + + // Create the physreg use/def lists. + PhysRegUseDefLists = new MachineOperand*[TRI.getNumRegs()]; + memset(PhysRegUseDefLists, 0, sizeof(MachineOperand*)*TRI.getNumRegs()); +} + +MachineRegisterInfo::~MachineRegisterInfo() { +#ifndef NDEBUG + for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i) + assert(VRegInfo[TargetRegisterInfo::index2VirtReg(i)].second == 0 && + "Vreg use list non-empty still?"); + for (unsigned i = 0, e = UsedPhysRegs.size(); i != e; ++i) + assert(!PhysRegUseDefLists[i] && + "PhysRegUseDefLists has entries after all instructions are deleted"); +#endif + delete [] PhysRegUseDefLists; + delete [] RegClass2VRegMap; +} + +/// setRegClass - Set the register class of the specified virtual register. +/// +void +MachineRegisterInfo::setRegClass(unsigned Reg, const TargetRegisterClass *RC) { + const TargetRegisterClass *OldRC = VRegInfo[Reg].first; + VRegInfo[Reg].first = RC; + + // Remove from old register class's vregs list. This may be slow but + // fortunately this operation is rarely needed. + std::vector &VRegs = RegClass2VRegMap[OldRC->getID()]; + std::vector::iterator I = + std::find(VRegs.begin(), VRegs.end(), Reg); + VRegs.erase(I); + + // Add to new register class's vregs list. + RegClass2VRegMap[RC->getID()].push_back(Reg); +} + +const TargetRegisterClass * +MachineRegisterInfo::constrainRegClass(unsigned Reg, + const TargetRegisterClass *RC) { + const TargetRegisterClass *OldRC = getRegClass(Reg); + if (OldRC == RC) + return RC; + const TargetRegisterClass *NewRC = getCommonSubClass(OldRC, RC); + if (!NewRC) + return 0; + if (NewRC != OldRC) + setRegClass(Reg, NewRC); + return NewRC; +} + +/// createVirtualRegister - Create and return a new virtual register in the +/// function with the specified register class. +/// +unsigned +MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ + assert(RegClass && "Cannot create register without RegClass!"); + + // New virtual register number. + unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs()); + + // Add a reg, but keep track of whether the vector reallocated or not. + const unsigned FirstVirtReg = TargetRegisterInfo::index2VirtReg(0); + void *ArrayBase = getNumVirtRegs() == 0 ? 0 : &VRegInfo[FirstVirtReg]; + VRegInfo.grow(Reg); + VRegInfo[Reg].first = RegClass; + RegAllocHints.grow(Reg); + + if (ArrayBase && &VRegInfo[FirstVirtReg] != ArrayBase) + // The vector reallocated, handle this now. + HandleVRegListReallocation(); + RegClass2VRegMap[RegClass->getID()].push_back(Reg); + return Reg; +} + +/// HandleVRegListReallocation - We just added a virtual register to the +/// VRegInfo info list and it reallocated. Update the use/def lists info +/// pointers. +void MachineRegisterInfo::HandleVRegListReallocation() { + // The back pointers for the vreg lists point into the previous vector. + // Update them to point to their correct slots. + for (unsigned i = 0, e = getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + MachineOperand *List = VRegInfo[Reg].second; + if (!List) continue; + // Update the back-pointer to be accurate once more. + List->Contents.Reg.Prev = &VRegInfo[Reg].second; + } +} + +/// replaceRegWith - Replace all instances of FromReg with ToReg in the +/// machine function. This is like llvm-level X->replaceAllUsesWith(Y), +/// except that it also changes any definitions of the register as well. +void MachineRegisterInfo::replaceRegWith(unsigned FromReg, unsigned ToReg) { + assert(FromReg != ToReg && "Cannot replace a reg with itself"); + + // TODO: This could be more efficient by bulk changing the operands. + for (reg_iterator I = reg_begin(FromReg), E = reg_end(); I != E; ) { + MachineOperand &O = I.getOperand(); + ++I; + O.setReg(ToReg); + } +} + + +/// getVRegDef - Return the machine instr that defines the specified virtual +/// register or null if none is found. This assumes that the code is in SSA +/// form, so there should only be one definition. +MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const { + // Since we are in SSA form, we can use the first definition. + if (!def_empty(Reg)) + return &*def_begin(Reg); + return 0; +} + +bool MachineRegisterInfo::hasOneUse(unsigned RegNo) const { + use_iterator UI = use_begin(RegNo); + if (UI == use_end()) + return false; + return ++UI == use_end(); +} + +bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const { + use_nodbg_iterator UI = use_nodbg_begin(RegNo); + if (UI == use_nodbg_end()) + return false; + return ++UI == use_nodbg_end(); +} + +/// clearKillFlags - Iterate over all the uses of the given register and +/// clear the kill flag from the MachineOperand. This function is used by +/// optimization passes which extend register lifetimes and need only +/// preserve conservative kill flag information. +void MachineRegisterInfo::clearKillFlags(unsigned Reg) const { + for (use_iterator UI = use_begin(Reg), UE = use_end(); UI != UE; ++UI) + UI.getOperand().setIsKill(false); +} + +bool MachineRegisterInfo::isLiveIn(unsigned Reg) const { + for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) + if (I->first == Reg || I->second == Reg) + return true; + return false; +} + +bool MachineRegisterInfo::isLiveOut(unsigned Reg) const { + for (liveout_iterator I = liveout_begin(), E = liveout_end(); I != E; ++I) + if (*I == Reg) + return true; + return false; +} + +/// getLiveInPhysReg - If VReg is a live-in virtual register, return the +/// corresponding live-in physical register. +unsigned MachineRegisterInfo::getLiveInPhysReg(unsigned VReg) const { + for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) + if (I->second == VReg) + return I->first; + return 0; +} + +/// getLiveInVirtReg - If PReg is a live-in physical register, return the +/// corresponding live-in physical register. +unsigned MachineRegisterInfo::getLiveInVirtReg(unsigned PReg) const { + for (livein_iterator I = livein_begin(), E = livein_end(); I != E; ++I) + if (I->first == PReg) + return I->second; + return 0; +} + +/// EmitLiveInCopies - Emit copies to initialize livein virtual registers +/// into the given entry block. +void +MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB, + const TargetRegisterInfo &TRI, + const TargetInstrInfo &TII) { + // Emit the copies into the top of the block. + for (unsigned i = 0, e = LiveIns.size(); i != e; ++i) + if (LiveIns[i].second) { + if (use_empty(LiveIns[i].second)) { + // The livein has no uses. Drop it. + // + // It would be preferable to have isel avoid creating live-in + // records for unused arguments in the first place, but it's + // complicated by the debug info code for arguments. + LiveIns.erase(LiveIns.begin() + i); + --i; --e; + } else { + // Emit a copy. + BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(), + TII.get(TargetOpcode::COPY), LiveIns[i].second) + .addReg(LiveIns[i].first); + + // Add the register to the entry block live-in set. + EntryMBB->addLiveIn(LiveIns[i].first); + } + } else { + // Add the register to the entry block live-in set. + EntryMBB->addLiveIn(LiveIns[i].first); + } +} + +void MachineRegisterInfo::closePhysRegsUsed(const TargetRegisterInfo &TRI) { + for (int i = UsedPhysRegs.find_first(); i >= 0; + i = UsedPhysRegs.find_next(i)) + for (const unsigned *SS = TRI.getSubRegisters(i); + unsigned SubReg = *SS; ++SS) + if (SubReg > unsigned(i)) + UsedPhysRegs.set(SubReg); +} + +#ifndef NDEBUG +void MachineRegisterInfo::dumpUses(unsigned Reg) const { + for (use_iterator I = use_begin(Reg), E = use_end(); I != E; ++I) + I.getOperand().getParent()->dump(); +} +#endif diff --git a/final/lib/CodeGen/MachineSSAUpdater.cpp b/final/lib/CodeGen/MachineSSAUpdater.cpp new file mode 100644 index 00000000000..84d6df25397 --- /dev/null +++ b/final/lib/CodeGen/MachineSSAUpdater.cpp @@ -0,0 +1,372 @@ +//===- MachineSSAUpdater.cpp - Unstructured SSA Update Tool ---------------===// +// +// 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 MachineSSAUpdater class. It's based on SSAUpdater +// class in lib/Transforms/Utils. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineSSAUpdater.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/SSAUpdaterImpl.h" +using namespace llvm; + +typedef DenseMap AvailableValsTy; +static AvailableValsTy &getAvailableVals(void *AV) { + return *static_cast(AV); +} + +MachineSSAUpdater::MachineSSAUpdater(MachineFunction &MF, + SmallVectorImpl *NewPHI) + : AV(0), InsertedPHIs(NewPHI) { + TII = MF.getTarget().getInstrInfo(); + MRI = &MF.getRegInfo(); +} + +MachineSSAUpdater::~MachineSSAUpdater() { + delete &getAvailableVals(AV); +} + +/// Initialize - Reset this object to get ready for a new set of SSA +/// updates. ProtoValue is the value used to name PHI nodes. +void MachineSSAUpdater::Initialize(unsigned V) { + if (AV == 0) + AV = new AvailableValsTy(); + else + getAvailableVals(AV).clear(); + + VR = V; + VRC = MRI->getRegClass(VR); +} + +/// HasValueForBlock - Return true if the MachineSSAUpdater already has a value for +/// the specified block. +bool MachineSSAUpdater::HasValueForBlock(MachineBasicBlock *BB) const { + return getAvailableVals(AV).count(BB); +} + +/// AddAvailableValue - Indicate that a rewritten value is available in the +/// specified block with the specified value. +void MachineSSAUpdater::AddAvailableValue(MachineBasicBlock *BB, unsigned V) { + getAvailableVals(AV)[BB] = V; +} + +/// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is +/// live at the end of the specified block. +unsigned MachineSSAUpdater::GetValueAtEndOfBlock(MachineBasicBlock *BB) { + return GetValueAtEndOfBlockInternal(BB); +} + +static +unsigned LookForIdenticalPHI(MachineBasicBlock *BB, + SmallVector, 8> &PredValues) { + if (BB->empty()) + return 0; + + MachineBasicBlock::iterator I = BB->front(); + if (!I->isPHI()) + return 0; + + AvailableValsTy AVals; + for (unsigned i = 0, e = PredValues.size(); i != e; ++i) + AVals[PredValues[i].first] = PredValues[i].second; + while (I != BB->end() && I->isPHI()) { + bool Same = true; + for (unsigned i = 1, e = I->getNumOperands(); i != e; i += 2) { + unsigned SrcReg = I->getOperand(i).getReg(); + MachineBasicBlock *SrcBB = I->getOperand(i+1).getMBB(); + if (AVals[SrcBB] != SrcReg) { + Same = false; + break; + } + } + if (Same) + return I->getOperand(0).getReg(); + ++I; + } + return 0; +} + +/// InsertNewDef - Insert an empty PHI or IMPLICIT_DEF instruction which define +/// a value of the given register class at the start of the specified basic +/// block. It returns the virtual register defined by the instruction. +static +MachineInstr *InsertNewDef(unsigned Opcode, + MachineBasicBlock *BB, MachineBasicBlock::iterator I, + const TargetRegisterClass *RC, + MachineRegisterInfo *MRI, + const TargetInstrInfo *TII) { + unsigned NewVR = MRI->createVirtualRegister(RC); + return BuildMI(*BB, I, DebugLoc(), TII->get(Opcode), NewVR); +} + +/// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that +/// is live in the middle of the specified block. +/// +/// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one +/// important case: if there is a definition of the rewritten value after the +/// 'use' in BB. Consider code like this: +/// +/// X1 = ... +/// SomeBB: +/// use(X) +/// X2 = ... +/// br Cond, SomeBB, OutBB +/// +/// In this case, there are two values (X1 and X2) added to the AvailableVals +/// set by the client of the rewriter, and those values are both live out of +/// their respective blocks. However, the use of X happens in the *middle* of +/// a block. Because of this, we need to insert a new PHI node in SomeBB to +/// merge the appropriate values, and this value isn't live out of the block. +/// +unsigned MachineSSAUpdater::GetValueInMiddleOfBlock(MachineBasicBlock *BB) { + // If there is no definition of the renamed variable in this block, just use + // GetValueAtEndOfBlock to do our work. + if (!HasValueForBlock(BB)) + return GetValueAtEndOfBlockInternal(BB); + + // If there are no predecessors, just return undef. + if (BB->pred_empty()) { + // Insert an implicit_def to represent an undef value. + MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF, + BB, BB->getFirstTerminator(), + VRC, MRI, TII); + return NewDef->getOperand(0).getReg(); + } + + // Otherwise, we have the hard case. Get the live-in values for each + // predecessor. + SmallVector, 8> PredValues; + unsigned SingularValue = 0; + + bool isFirstPred = true; + for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), + E = BB->pred_end(); PI != E; ++PI) { + MachineBasicBlock *PredBB = *PI; + unsigned PredVal = GetValueAtEndOfBlockInternal(PredBB); + PredValues.push_back(std::make_pair(PredBB, PredVal)); + + // Compute SingularValue. + if (isFirstPred) { + SingularValue = PredVal; + isFirstPred = false; + } else if (PredVal != SingularValue) + SingularValue = 0; + } + + // Otherwise, if all the merged values are the same, just use it. + if (SingularValue != 0) + return SingularValue; + + // If an identical PHI is already in BB, just reuse it. + unsigned DupPHI = LookForIdenticalPHI(BB, PredValues); + if (DupPHI) + return DupPHI; + + // Otherwise, we do need a PHI: insert one now. + MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->front(); + MachineInstr *InsertedPHI = InsertNewDef(TargetOpcode::PHI, BB, + Loc, VRC, MRI, TII); + + // Fill in all the predecessors of the PHI. + MachineInstrBuilder MIB(InsertedPHI); + for (unsigned i = 0, e = PredValues.size(); i != e; ++i) + MIB.addReg(PredValues[i].second).addMBB(PredValues[i].first); + + // See if the PHI node can be merged to a single value. This can happen in + // loop cases when we get a PHI of itself and one other value. + if (unsigned ConstVal = InsertedPHI->isConstantValuePHI()) { + InsertedPHI->eraseFromParent(); + return ConstVal; + } + + // If the client wants to know about all new instructions, tell it. + if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI); + + DEBUG(dbgs() << " Inserted PHI: " << *InsertedPHI << "\n"); + return InsertedPHI->getOperand(0).getReg(); +} + +static +MachineBasicBlock *findCorrespondingPred(const MachineInstr *MI, + MachineOperand *U) { + for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) { + if (&MI->getOperand(i) == U) + return MI->getOperand(i+1).getMBB(); + } + + llvm_unreachable("MachineOperand::getParent() failure?"); + return 0; +} + +/// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, +/// which use their value in the corresponding predecessor. +void MachineSSAUpdater::RewriteUse(MachineOperand &U) { + MachineInstr *UseMI = U.getParent(); + unsigned NewVR = 0; + if (UseMI->isPHI()) { + MachineBasicBlock *SourceBB = findCorrespondingPred(UseMI, &U); + NewVR = GetValueAtEndOfBlockInternal(SourceBB); + } else { + NewVR = GetValueInMiddleOfBlock(UseMI->getParent()); + } + + U.setReg(NewVR); +} + +void MachineSSAUpdater::ReplaceRegWith(unsigned OldReg, unsigned NewReg) { + MRI->replaceRegWith(OldReg, NewReg); + + AvailableValsTy &AvailableVals = getAvailableVals(AV); + for (DenseMap::iterator + I = AvailableVals.begin(), E = AvailableVals.end(); I != E; ++I) + if (I->second == OldReg) + I->second = NewReg; +} + +/// MachinePHIiter - Iterator for PHI operands. This is used for the +/// PHI_iterator in the SSAUpdaterImpl template. +namespace { + class MachinePHIiter { + private: + MachineInstr *PHI; + unsigned idx; + + public: + explicit MachinePHIiter(MachineInstr *P) // begin iterator + : PHI(P), idx(1) {} + MachinePHIiter(MachineInstr *P, bool) // end iterator + : PHI(P), idx(PHI->getNumOperands()) {} + + MachinePHIiter &operator++() { idx += 2; return *this; } + bool operator==(const MachinePHIiter& x) const { return idx == x.idx; } + bool operator!=(const MachinePHIiter& x) const { return !operator==(x); } + unsigned getIncomingValue() { return PHI->getOperand(idx).getReg(); } + MachineBasicBlock *getIncomingBlock() { + return PHI->getOperand(idx+1).getMBB(); + } + }; +} + +/// SSAUpdaterTraits - Traits for the SSAUpdaterImpl +/// template, specialized for MachineSSAUpdater. +namespace llvm { +template<> +class SSAUpdaterTraits { +public: + typedef MachineBasicBlock BlkT; + typedef unsigned ValT; + typedef MachineInstr PhiT; + + typedef MachineBasicBlock::succ_iterator BlkSucc_iterator; + static BlkSucc_iterator BlkSucc_begin(BlkT *BB) { return BB->succ_begin(); } + static BlkSucc_iterator BlkSucc_end(BlkT *BB) { return BB->succ_end(); } + + typedef MachinePHIiter PHI_iterator; + static inline PHI_iterator PHI_begin(PhiT *PHI) { return PHI_iterator(PHI); } + static inline PHI_iterator PHI_end(PhiT *PHI) { + return PHI_iterator(PHI, true); + } + + /// FindPredecessorBlocks - Put the predecessors of BB into the Preds + /// vector. + static void FindPredecessorBlocks(MachineBasicBlock *BB, + SmallVectorImpl *Preds){ + for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), + E = BB->pred_end(); PI != E; ++PI) + Preds->push_back(*PI); + } + + /// GetUndefVal - Create an IMPLICIT_DEF instruction with a new register. + /// Add it into the specified block and return the register. + static unsigned GetUndefVal(MachineBasicBlock *BB, + MachineSSAUpdater *Updater) { + // Insert an implicit_def to represent an undef value. + MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF, + BB, BB->getFirstTerminator(), + Updater->VRC, Updater->MRI, + Updater->TII); + return NewDef->getOperand(0).getReg(); + } + + /// CreateEmptyPHI - Create a PHI instruction that defines a new register. + /// Add it into the specified block and return the register. + static unsigned CreateEmptyPHI(MachineBasicBlock *BB, unsigned NumPreds, + MachineSSAUpdater *Updater) { + MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->front(); + MachineInstr *PHI = InsertNewDef(TargetOpcode::PHI, BB, Loc, + Updater->VRC, Updater->MRI, + Updater->TII); + return PHI->getOperand(0).getReg(); + } + + /// AddPHIOperand - Add the specified value as an operand of the PHI for + /// the specified predecessor block. + static void AddPHIOperand(MachineInstr *PHI, unsigned Val, + MachineBasicBlock *Pred) { + PHI->addOperand(MachineOperand::CreateReg(Val, false)); + PHI->addOperand(MachineOperand::CreateMBB(Pred)); + } + + /// InstrIsPHI - Check if an instruction is a PHI. + /// + static MachineInstr *InstrIsPHI(MachineInstr *I) { + if (I && I->isPHI()) + return I; + return 0; + } + + /// ValueIsPHI - Check if the instruction that defines the specified register + /// is a PHI instruction. + static MachineInstr *ValueIsPHI(unsigned Val, MachineSSAUpdater *Updater) { + return InstrIsPHI(Updater->MRI->getVRegDef(Val)); + } + + /// ValueIsNewPHI - Like ValueIsPHI but also check if the PHI has no source + /// operands, i.e., it was just added. + static MachineInstr *ValueIsNewPHI(unsigned Val, MachineSSAUpdater *Updater) { + MachineInstr *PHI = ValueIsPHI(Val, Updater); + if (PHI && PHI->getNumOperands() <= 1) + return PHI; + return 0; + } + + /// GetPHIValue - For the specified PHI instruction, return the register + /// that it defines. + static unsigned GetPHIValue(MachineInstr *PHI) { + return PHI->getOperand(0).getReg(); + } +}; + +} // End llvm namespace + +/// GetValueAtEndOfBlockInternal - Check to see if AvailableVals has an entry +/// for the specified BB and if so, return it. If not, construct SSA form by +/// first calculating the required placement of PHIs and then inserting new +/// PHIs where needed. +unsigned MachineSSAUpdater::GetValueAtEndOfBlockInternal(MachineBasicBlock *BB){ + AvailableValsTy &AvailableVals = getAvailableVals(AV); + if (unsigned V = AvailableVals[BB]) + return V; + + SSAUpdaterImpl Impl(this, &AvailableVals, InsertedPHIs); + return Impl.GetValue(BB); +} diff --git a/final/lib/CodeGen/MachineSink.cpp b/final/lib/CodeGen/MachineSink.cpp new file mode 100644 index 00000000000..8a93a24287b --- /dev/null +++ b/final/lib/CodeGen/MachineSink.cpp @@ -0,0 +1,607 @@ +//===-- MachineSink.cpp - Sinking for machine instructions ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass moves instructions into successor blocks when possible, so that +// they aren't executed on paths where their results aren't needed. +// +// This pass is not intended to be a replacement or a complete alternative +// for an LLVM-IR-level sinking pass. It is only designed to sink simple +// constructs that are not exposed before lowering and instruction selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-sink" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +SplitEdges("machine-sink-split", + cl::desc("Split critical edges during machine sinking"), + cl::init(true), cl::Hidden); + +STATISTIC(NumSunk, "Number of machine instructions sunk"); +STATISTIC(NumSplit, "Number of critical edges split"); +STATISTIC(NumCoalesces, "Number of copies coalesced"); + +namespace { + class MachineSinking : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; // Machine register information + MachineDominatorTree *DT; // Machine dominator tree + MachineLoopInfo *LI; + AliasAnalysis *AA; + BitVector AllocatableSet; // Which physregs are allocatable? + + // Remember which edges have been considered for breaking. + SmallSet, 8> + CEBCandidates; + + public: + static char ID; // Pass identification + MachineSinking() : MachineFunctionPass(ID) { + initializeMachineSinkingPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + } + + virtual void releaseMemory() { + CEBCandidates.clear(); + } + + private: + bool ProcessBlock(MachineBasicBlock &MBB); + bool isWorthBreakingCriticalEdge(MachineInstr *MI, + MachineBasicBlock *From, + MachineBasicBlock *To); + MachineBasicBlock *SplitCriticalEdge(MachineInstr *MI, + MachineBasicBlock *From, + MachineBasicBlock *To, + bool BreakPHIEdge); + bool SinkInstruction(MachineInstr *MI, bool &SawStore); + bool AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB, + MachineBasicBlock *DefMBB, + bool &BreakPHIEdge, bool &LocalUse) const; + bool PerformTrivialForwardCoalescing(MachineInstr *MI, + MachineBasicBlock *MBB); + }; +} // end anonymous namespace + +char MachineSinking::ID = 0; +INITIALIZE_PASS_BEGIN(MachineSinking, "machine-sink", + "Machine code sinking", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(MachineSinking, "machine-sink", + "Machine code sinking", false, false) + +FunctionPass *llvm::createMachineSinkingPass() { return new MachineSinking(); } + +bool MachineSinking::PerformTrivialForwardCoalescing(MachineInstr *MI, + MachineBasicBlock *MBB) { + if (!MI->isCopy()) + return false; + + unsigned SrcReg = MI->getOperand(1).getReg(); + unsigned DstReg = MI->getOperand(0).getReg(); + if (!TargetRegisterInfo::isVirtualRegister(SrcReg) || + !TargetRegisterInfo::isVirtualRegister(DstReg) || + !MRI->hasOneNonDBGUse(SrcReg)) + return false; + + const TargetRegisterClass *SRC = MRI->getRegClass(SrcReg); + const TargetRegisterClass *DRC = MRI->getRegClass(DstReg); + if (SRC != DRC) + return false; + + MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (DefMI->isCopyLike()) + return false; + DEBUG(dbgs() << "Coalescing: " << *DefMI); + DEBUG(dbgs() << "*** to: " << *MI); + MRI->replaceRegWith(DstReg, SrcReg); + MI->eraseFromParent(); + ++NumCoalesces; + return true; +} + +/// AllUsesDominatedByBlock - Return true if all uses of the specified register +/// occur in blocks dominated by the specified block. If any use is in the +/// definition block, then return false since it is never legal to move def +/// after uses. +bool +MachineSinking::AllUsesDominatedByBlock(unsigned Reg, + MachineBasicBlock *MBB, + MachineBasicBlock *DefMBB, + bool &BreakPHIEdge, + bool &LocalUse) const { + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Only makes sense for vregs"); + + if (MRI->use_nodbg_empty(Reg)) + return true; + + // Ignoring debug uses is necessary so debug info doesn't affect the code. + // This may leave a referencing dbg_value in the original block, before + // the definition of the vreg. Dwarf generator handles this although the + // user might not get the right info at runtime. + + // BreakPHIEdge is true if all the uses are in the successor MBB being sunken + // into and they are all PHI nodes. In this case, machine-sink must break + // the critical edge first. e.g. + // + // BB#1: derived from LLVM BB %bb4.preheader + // Predecessors according to CFG: BB#0 + // ... + // %reg16385 = DEC64_32r %reg16437, %EFLAGS + // ... + // JE_4 , %EFLAGS + // Successors according to CFG: BB#37 BB#2 + // + // BB#2: derived from LLVM BB %bb.nph + // Predecessors according to CFG: BB#0 BB#1 + // %reg16386 = PHI %reg16434, , %reg16385, + BreakPHIEdge = true; + for (MachineRegisterInfo::use_nodbg_iterator + I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end(); + I != E; ++I) { + MachineInstr *UseInst = &*I; + MachineBasicBlock *UseBlock = UseInst->getParent(); + if (!(UseBlock == MBB && UseInst->isPHI() && + UseInst->getOperand(I.getOperandNo()+1).getMBB() == DefMBB)) { + BreakPHIEdge = false; + break; + } + } + if (BreakPHIEdge) + return true; + + for (MachineRegisterInfo::use_nodbg_iterator + I = MRI->use_nodbg_begin(Reg), E = MRI->use_nodbg_end(); + I != E; ++I) { + // Determine the block of the use. + MachineInstr *UseInst = &*I; + MachineBasicBlock *UseBlock = UseInst->getParent(); + if (UseInst->isPHI()) { + // PHI nodes use the operand in the predecessor block, not the block with + // the PHI. + UseBlock = UseInst->getOperand(I.getOperandNo()+1).getMBB(); + } else if (UseBlock == DefMBB) { + LocalUse = true; + return false; + } + + // Check that it dominates. + if (!DT->dominates(MBB, UseBlock)) + return false; + } + + return true; +} + +bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "******** Machine Sinking ********\n"); + + const TargetMachine &TM = MF.getTarget(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + MRI = &MF.getRegInfo(); + DT = &getAnalysis(); + LI = &getAnalysis(); + AA = &getAnalysis(); + AllocatableSet = TRI->getAllocatableSet(MF); + + bool EverMadeChange = false; + + while (1) { + bool MadeChange = false; + + // Process all basic blocks. + CEBCandidates.clear(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) + MadeChange |= ProcessBlock(*I); + + // If this iteration over the code changed anything, keep iterating. + if (!MadeChange) break; + EverMadeChange = true; + } + return EverMadeChange; +} + +bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { + // Can't sink anything out of a block that has less than two successors. + if (MBB.succ_size() <= 1 || MBB.empty()) return false; + + // Don't bother sinking code out of unreachable blocks. In addition to being + // unprofitable, it can also lead to infinite looping, because in an + // unreachable loop there may be nowhere to stop. + if (!DT->isReachableFromEntry(&MBB)) return false; + + bool MadeChange = false; + + // Walk the basic block bottom-up. Remember if we saw a store. + MachineBasicBlock::iterator I = MBB.end(); + --I; + bool ProcessedBegin, SawStore = false; + do { + MachineInstr *MI = I; // The instruction to sink. + + // Predecrement I (if it's not begin) so that it isn't invalidated by + // sinking. + ProcessedBegin = I == MBB.begin(); + if (!ProcessedBegin) + --I; + + if (MI->isDebugValue()) + continue; + + if (PerformTrivialForwardCoalescing(MI, &MBB)) + continue; + + if (SinkInstruction(MI, SawStore)) + ++NumSunk, MadeChange = true; + + // If we just processed the first instruction in the block, we're done. + } while (!ProcessedBegin); + + return MadeChange; +} + +bool MachineSinking::isWorthBreakingCriticalEdge(MachineInstr *MI, + MachineBasicBlock *From, + MachineBasicBlock *To) { + // FIXME: Need much better heuristics. + + // If the pass has already considered breaking this edge (during this pass + // through the function), then let's go ahead and break it. This means + // sinking multiple "cheap" instructions into the same block. + if (!CEBCandidates.insert(std::make_pair(From, To))) + return true; + + if (!MI->isCopy() && !MI->getDesc().isAsCheapAsAMove()) + return true; + + // MI is cheap, we probably don't want to break the critical edge for it. + // However, if this would allow some definitions of its source operands + // to be sunk then it's probably worth it. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || !TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (MRI->hasOneNonDBGUse(Reg)) + return true; + } + + return false; +} + +MachineBasicBlock *MachineSinking::SplitCriticalEdge(MachineInstr *MI, + MachineBasicBlock *FromBB, + MachineBasicBlock *ToBB, + bool BreakPHIEdge) { + if (!isWorthBreakingCriticalEdge(MI, FromBB, ToBB)) + return 0; + + // Avoid breaking back edge. From == To means backedge for single BB loop. + if (!SplitEdges || FromBB == ToBB) + return 0; + + // Check for backedges of more "complex" loops. + if (LI->getLoopFor(FromBB) == LI->getLoopFor(ToBB) && + LI->isLoopHeader(ToBB)) + return 0; + + // It's not always legal to break critical edges and sink the computation + // to the edge. + // + // BB#1: + // v1024 + // Beq BB#3 + // + // BB#2: + // ... no uses of v1024 + // + // BB#3: + // ... + // = v1024 + // + // If BB#1 -> BB#3 edge is broken and computation of v1024 is inserted: + // + // BB#1: + // ... + // Bne BB#2 + // BB#4: + // v1024 = + // B BB#3 + // BB#2: + // ... no uses of v1024 + // + // BB#3: + // ... + // = v1024 + // + // This is incorrect since v1024 is not computed along the BB#1->BB#2->BB#3 + // flow. We need to ensure the new basic block where the computation is + // sunk to dominates all the uses. + // It's only legal to break critical edge and sink the computation to the + // new block if all the predecessors of "To", except for "From", are + // not dominated by "From". Given SSA property, this means these + // predecessors are dominated by "To". + // + // There is no need to do this check if all the uses are PHI nodes. PHI + // sources are only defined on the specific predecessor edges. + if (!BreakPHIEdge) { + for (MachineBasicBlock::pred_iterator PI = ToBB->pred_begin(), + E = ToBB->pred_end(); PI != E; ++PI) { + if (*PI == FromBB) + continue; + if (!DT->dominates(ToBB, *PI)) + return 0; + } + } + + return FromBB->SplitCriticalEdge(ToBB, this); +} + +static bool AvoidsSinking(MachineInstr *MI, MachineRegisterInfo *MRI) { + return MI->isInsertSubreg() || MI->isSubregToReg() || MI->isRegSequence(); +} + +/// SinkInstruction - Determine whether it is safe to sink the specified machine +/// instruction out of its current block into a successor. +bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { + // Don't sink insert_subreg, subreg_to_reg, reg_sequence. These are meant to + // be close to the source to make it easier to coalesce. + if (AvoidsSinking(MI, MRI)) + return false; + + // Check if it's safe to move the instruction. + if (!MI->isSafeToMove(TII, AA, SawStore)) + return false; + + // FIXME: This should include support for sinking instructions within the + // block they are currently in to shorten the live ranges. We often get + // instructions sunk into the top of a large block, but it would be better to + // also sink them down before their first use in the block. This xform has to + // be careful not to *increase* register pressure though, e.g. sinking + // "x = y + z" down if it kills y and z would increase the live ranges of y + // and z and only shrink the live range of x. + + // Loop over all the operands of the specified instruction. If there is + // anything we can't handle, bail out. + MachineBasicBlock *ParentBlock = MI->getParent(); + + // SuccToSinkTo - This is the successor to sink this instruction to, once we + // decide. + MachineBasicBlock *SuccToSinkTo = 0; + + bool BreakPHIEdge = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; // Ignore non-register operands. + + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!MRI->def_empty(Reg)) + return false; + + if (AllocatableSet.test(Reg)) + return false; + + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!MRI->def_empty(AliasReg)) + return false; + + if (AllocatableSet.test(AliasReg)) + return false; + } + } else if (!MO.isDead()) { + // A def that isn't dead. We can't move it. + return false; + } + } else { + // Virtual register uses are always safe to sink. + if (MO.isUse()) continue; + + // If it's not safe to move defs of the register class, then abort. + if (!TII->isSafeToMoveRegClassDefs(MRI->getRegClass(Reg))) + return false; + + // FIXME: This picks a successor to sink into based on having one + // successor that dominates all the uses. However, there are cases where + // sinking can happen but where the sink point isn't a successor. For + // example: + // + // x = computation + // if () {} else {} + // use x + // + // the instruction could be sunk over the whole diamond for the + // if/then/else (or loop, etc), allowing it to be sunk into other blocks + // after that. + + // Virtual register defs can only be sunk if all their uses are in blocks + // dominated by one of the successors. + if (SuccToSinkTo) { + // If a previous operand picked a block to sink to, then this operand + // must be sinkable to the same block. + bool LocalUse = false; + if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, ParentBlock, + BreakPHIEdge, LocalUse)) + return false; + + continue; + } + + // Otherwise, we should look at all the successors and decide which one + // we should sink to. + for (MachineBasicBlock::succ_iterator SI = ParentBlock->succ_begin(), + E = ParentBlock->succ_end(); SI != E; ++SI) { + bool LocalUse = false; + if (AllUsesDominatedByBlock(Reg, *SI, ParentBlock, + BreakPHIEdge, LocalUse)) { + SuccToSinkTo = *SI; + break; + } + if (LocalUse) + // Def is used locally, it's never safe to move this def. + return false; + } + + // If we couldn't find a block to sink to, ignore this instruction. + if (SuccToSinkTo == 0) + return false; + } + } + + // If there are no outputs, it must have side-effects. + if (SuccToSinkTo == 0) + return false; + + // It's not safe to sink instructions to EH landing pad. Control flow into + // landing pad is implicitly defined. + if (SuccToSinkTo->isLandingPad()) + return false; + + // It is not possible to sink an instruction into its own block. This can + // happen with loops. + if (MI->getParent() == SuccToSinkTo) + return false; + + // If the instruction to move defines a dead physical register which is live + // when leaving the basic block, don't move it because it could turn into a + // "zombie" define of that preg. E.g., EFLAGS. () + for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { + const MachineOperand &MO = MI->getOperand(I); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0 || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + if (SuccToSinkTo->isLiveIn(Reg)) + return false; + } + + DEBUG(dbgs() << "Sink instr " << *MI << "\tinto block " << *SuccToSinkTo); + + // If the block has multiple predecessors, this would introduce computation on + // a path that it doesn't already exist. We could split the critical edge, + // but for now we just punt. + if (SuccToSinkTo->pred_size() > 1) { + // We cannot sink a load across a critical edge - there may be stores in + // other code paths. + bool TryBreak = false; + bool store = true; + if (!MI->isSafeToMove(TII, AA, store)) { + DEBUG(dbgs() << " *** NOTE: Won't sink load along critical edge.\n"); + TryBreak = true; + } + + // We don't want to sink across a critical edge if we don't dominate the + // successor. We could be introducing calculations to new code paths. + if (!TryBreak && !DT->dominates(ParentBlock, SuccToSinkTo)) { + DEBUG(dbgs() << " *** NOTE: Critical edge found\n"); + TryBreak = true; + } + + // Don't sink instructions into a loop. + if (!TryBreak && LI->isLoopHeader(SuccToSinkTo)) { + DEBUG(dbgs() << " *** NOTE: Loop header found\n"); + TryBreak = true; + } + + // Otherwise we are OK with sinking along a critical edge. + if (!TryBreak) + DEBUG(dbgs() << "Sinking along critical edge.\n"); + else { + MachineBasicBlock *NewSucc = + SplitCriticalEdge(MI, ParentBlock, SuccToSinkTo, BreakPHIEdge); + if (!NewSucc) { + DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to " + "break critical edge\n"); + return false; + } else { + DEBUG(dbgs() << " *** Splitting critical edge:" + " BB#" << ParentBlock->getNumber() + << " -- BB#" << NewSucc->getNumber() + << " -- BB#" << SuccToSinkTo->getNumber() << '\n'); + SuccToSinkTo = NewSucc; + ++NumSplit; + BreakPHIEdge = false; + } + } + } + + if (BreakPHIEdge) { + // BreakPHIEdge is true if all the uses are in the successor MBB being + // sunken into and they are all PHI nodes. In this case, machine-sink must + // break the critical edge first. + MachineBasicBlock *NewSucc = SplitCriticalEdge(MI, ParentBlock, + SuccToSinkTo, BreakPHIEdge); + if (!NewSucc) { + DEBUG(dbgs() << " *** PUNTING: Not legal or profitable to " + "break critical edge\n"); + return false; + } + + DEBUG(dbgs() << " *** Splitting critical edge:" + " BB#" << ParentBlock->getNumber() + << " -- BB#" << NewSucc->getNumber() + << " -- BB#" << SuccToSinkTo->getNumber() << '\n'); + SuccToSinkTo = NewSucc; + ++NumSplit; + } + + // Determine where to insert into. Skip phi nodes. + MachineBasicBlock::iterator InsertPos = SuccToSinkTo->begin(); + while (InsertPos != SuccToSinkTo->end() && InsertPos->isPHI()) + ++InsertPos; + + // Move the instruction. + SuccToSinkTo->splice(InsertPos, ParentBlock, MI, + ++MachineBasicBlock::iterator(MI)); + + // Conservatively, clear any kill flags, since it's possible that they are no + // longer correct. + MI->clearKillInfo(); + + return true; +} diff --git a/final/lib/CodeGen/MachineVerifier.cpp b/final/lib/CodeGen/MachineVerifier.cpp new file mode 100644 index 00000000000..7351119f472 --- /dev/null +++ b/final/lib/CodeGen/MachineVerifier.cpp @@ -0,0 +1,1216 @@ +//===-- MachineVerifier.cpp - Machine Code Verifier -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Pass to verify generated machine code. The following is checked: +// +// Operand counts: All explicit operands must be present. +// +// Register classes: All physical and virtual register operands must be +// compatible with the register class required by the instruction descriptor. +// +// Register live intervals: Registers must be defined only once, and must be +// defined before use. +// +// The machine code verifier is enabled from LLVMTargetMachine.cpp with the +// command-line option -verify-machineinstrs, or by defining the environment +// variable LLVM_VERIFY_MACHINEINSTRS to the name of a file that will receive +// the verifier errors. +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + struct MachineVerifier { + + MachineVerifier(Pass *pass, const char *b) : + PASS(pass), + Banner(b), + OutFileName(getenv("LLVM_VERIFY_MACHINEINSTRS")) + {} + + bool runOnMachineFunction(MachineFunction &MF); + + Pass *const PASS; + const char *Banner; + const char *const OutFileName; + raw_ostream *OS; + const MachineFunction *MF; + const TargetMachine *TM; + const TargetRegisterInfo *TRI; + const MachineRegisterInfo *MRI; + + unsigned foundErrors; + + typedef SmallVector RegVector; + typedef DenseSet RegSet; + typedef DenseMap RegMap; + + BitVector regsReserved; + RegSet regsLive; + RegVector regsDefined, regsDead, regsKilled; + RegSet regsLiveInButUnused; + + SlotIndex lastIndex; + + // Add Reg and any sub-registers to RV + void addRegWithSubRegs(RegVector &RV, unsigned Reg) { + RV.push_back(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++) + RV.push_back(*R); + } + + struct BBInfo { + // Is this MBB reachable from the MF entry point? + bool reachable; + + // Vregs that must be live in because they are used without being + // defined. Map value is the user. + RegMap vregsLiveIn; + + // Regs killed in MBB. They may be defined again, and will then be in both + // regsKilled and regsLiveOut. + RegSet regsKilled; + + // Regs defined in MBB and live out. Note that vregs passing through may + // be live out without being mentioned here. + RegSet regsLiveOut; + + // Vregs that pass through MBB untouched. This set is disjoint from + // regsKilled and regsLiveOut. + RegSet vregsPassed; + + // Vregs that must pass through MBB because they are needed by a successor + // block. This set is disjoint from regsLiveOut. + RegSet vregsRequired; + + BBInfo() : reachable(false) {} + + // Add register to vregsPassed if it belongs there. Return true if + // anything changed. + bool addPassed(unsigned Reg) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return false; + if (regsKilled.count(Reg) || regsLiveOut.count(Reg)) + return false; + return vregsPassed.insert(Reg).second; + } + + // Same for a full set. + bool addPassed(const RegSet &RS) { + bool changed = false; + for (RegSet::const_iterator I = RS.begin(), E = RS.end(); I != E; ++I) + if (addPassed(*I)) + changed = true; + return changed; + } + + // Add register to vregsRequired if it belongs there. Return true if + // anything changed. + bool addRequired(unsigned Reg) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return false; + if (regsLiveOut.count(Reg)) + return false; + return vregsRequired.insert(Reg).second; + } + + // Same for a full set. + bool addRequired(const RegSet &RS) { + bool changed = false; + for (RegSet::const_iterator I = RS.begin(), E = RS.end(); I != E; ++I) + if (addRequired(*I)) + changed = true; + return changed; + } + + // Same for a full map. + bool addRequired(const RegMap &RM) { + bool changed = false; + for (RegMap::const_iterator I = RM.begin(), E = RM.end(); I != E; ++I) + if (addRequired(I->first)) + changed = true; + return changed; + } + + // Live-out registers are either in regsLiveOut or vregsPassed. + bool isLiveOut(unsigned Reg) const { + return regsLiveOut.count(Reg) || vregsPassed.count(Reg); + } + }; + + // Extra register info per MBB. + DenseMap MBBInfoMap; + + bool isReserved(unsigned Reg) { + return Reg < regsReserved.size() && regsReserved.test(Reg); + } + + // Analysis information if available + LiveVariables *LiveVars; + LiveIntervals *LiveInts; + LiveStacks *LiveStks; + SlotIndexes *Indexes; + + void visitMachineFunctionBefore(); + void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB); + void visitMachineInstrBefore(const MachineInstr *MI); + void visitMachineOperand(const MachineOperand *MO, unsigned MONum); + void visitMachineInstrAfter(const MachineInstr *MI); + void visitMachineBasicBlockAfter(const MachineBasicBlock *MBB); + void visitMachineFunctionAfter(); + + void report(const char *msg, const MachineFunction *MF); + void report(const char *msg, const MachineBasicBlock *MBB); + void report(const char *msg, const MachineInstr *MI); + void report(const char *msg, const MachineOperand *MO, unsigned MONum); + + void markReachable(const MachineBasicBlock *MBB); + void calcRegsPassed(); + void checkPHIOps(const MachineBasicBlock *MBB); + + void calcRegsRequired(); + void verifyLiveVariables(); + void verifyLiveIntervals(); + }; + + struct MachineVerifierPass : public MachineFunctionPass { + static char ID; // Pass ID, replacement for typeid + const char *const Banner; + + MachineVerifierPass(const char *b = 0) + : MachineFunctionPass(ID), Banner(b) { + initializeMachineVerifierPassPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) { + MF.verify(this, Banner); + return false; + } + }; + +} + +char MachineVerifierPass::ID = 0; +INITIALIZE_PASS(MachineVerifierPass, "machineverifier", + "Verify generated machine code", false, false) + +FunctionPass *llvm::createMachineVerifierPass(const char *Banner) { + return new MachineVerifierPass(Banner); +} + +void MachineFunction::verify(Pass *p, const char *Banner) const { + MachineVerifier(p, Banner) + .runOnMachineFunction(const_cast(*this)); +} + +bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) { + raw_ostream *OutFile = 0; + if (OutFileName) { + std::string ErrorInfo; + OutFile = new raw_fd_ostream(OutFileName, ErrorInfo, + raw_fd_ostream::F_Append); + if (!ErrorInfo.empty()) { + errs() << "Error opening '" << OutFileName << "': " << ErrorInfo << '\n'; + exit(1); + } + + OS = OutFile; + } else { + OS = &errs(); + } + + foundErrors = 0; + + this->MF = &MF; + TM = &MF.getTarget(); + TRI = TM->getRegisterInfo(); + MRI = &MF.getRegInfo(); + + LiveVars = NULL; + LiveInts = NULL; + LiveStks = NULL; + Indexes = NULL; + if (PASS) { + LiveInts = PASS->getAnalysisIfAvailable(); + // We don't want to verify LiveVariables if LiveIntervals is available. + if (!LiveInts) + LiveVars = PASS->getAnalysisIfAvailable(); + LiveStks = PASS->getAnalysisIfAvailable(); + Indexes = PASS->getAnalysisIfAvailable(); + } + + visitMachineFunctionBefore(); + for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end(); + MFI!=MFE; ++MFI) { + visitMachineBasicBlockBefore(MFI); + for (MachineBasicBlock::const_iterator MBBI = MFI->begin(), + MBBE = MFI->end(); MBBI != MBBE; ++MBBI) { + if (MBBI->getParent() != MFI) { + report("Bad instruction parent pointer", MFI); + *OS << "Instruction: " << *MBBI; + continue; + } + visitMachineInstrBefore(MBBI); + for (unsigned I = 0, E = MBBI->getNumOperands(); I != E; ++I) + visitMachineOperand(&MBBI->getOperand(I), I); + visitMachineInstrAfter(MBBI); + } + visitMachineBasicBlockAfter(MFI); + } + visitMachineFunctionAfter(); + + if (OutFile) + delete OutFile; + else if (foundErrors) + report_fatal_error("Found "+Twine(foundErrors)+" machine code errors."); + + // Clean up. + regsLive.clear(); + regsDefined.clear(); + regsDead.clear(); + regsKilled.clear(); + regsLiveInButUnused.clear(); + MBBInfoMap.clear(); + + return false; // no changes +} + +void MachineVerifier::report(const char *msg, const MachineFunction *MF) { + assert(MF); + *OS << '\n'; + if (!foundErrors++) { + if (Banner) + *OS << "# " << Banner << '\n'; + MF->print(*OS, Indexes); + } + *OS << "*** Bad machine code: " << msg << " ***\n" + << "- function: " << MF->getFunction()->getNameStr() << "\n"; +} + +void MachineVerifier::report(const char *msg, const MachineBasicBlock *MBB) { + assert(MBB); + report(msg, MBB->getParent()); + *OS << "- basic block: " << MBB->getName() + << " " << (void*)MBB + << " (BB#" << MBB->getNumber() << ")"; + if (Indexes) + *OS << " [" << Indexes->getMBBStartIdx(MBB) + << ';' << Indexes->getMBBEndIdx(MBB) << ')'; + *OS << '\n'; +} + +void MachineVerifier::report(const char *msg, const MachineInstr *MI) { + assert(MI); + report(msg, MI->getParent()); + *OS << "- instruction: "; + if (Indexes && Indexes->hasIndex(MI)) + *OS << Indexes->getInstructionIndex(MI) << '\t'; + MI->print(*OS, TM); +} + +void MachineVerifier::report(const char *msg, + const MachineOperand *MO, unsigned MONum) { + assert(MO); + report(msg, MO->getParent()); + *OS << "- operand " << MONum << ": "; + MO->print(*OS, TM); + *OS << "\n"; +} + +void MachineVerifier::markReachable(const MachineBasicBlock *MBB) { + BBInfo &MInfo = MBBInfoMap[MBB]; + if (!MInfo.reachable) { + MInfo.reachable = true; + for (MachineBasicBlock::const_succ_iterator SuI = MBB->succ_begin(), + SuE = MBB->succ_end(); SuI != SuE; ++SuI) + markReachable(*SuI); + } +} + +void MachineVerifier::visitMachineFunctionBefore() { + lastIndex = SlotIndex(); + regsReserved = TRI->getReservedRegs(*MF); + + // A sub-register of a reserved register is also reserved + for (int Reg = regsReserved.find_first(); Reg>=0; + Reg = regsReserved.find_next(Reg)) { + for (const unsigned *Sub = TRI->getSubRegisters(Reg); *Sub; ++Sub) { + // FIXME: This should probably be: + // assert(regsReserved.test(*Sub) && "Non-reserved sub-register"); + regsReserved.set(*Sub); + } + } + markReachable(&MF->front()); +} + +// Does iterator point to a and b as the first two elements? +static bool matchPair(MachineBasicBlock::const_succ_iterator i, + const MachineBasicBlock *a, const MachineBasicBlock *b) { + if (*i == a) + return *++i == b; + if (*i == b) + return *++i == a; + return false; +} + +void +MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + // Count the number of landing pad successors. + SmallPtrSet LandingPadSuccs; + for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), + E = MBB->succ_end(); I != E; ++I) { + if ((*I)->isLandingPad()) + LandingPadSuccs.insert(*I); + } + if (LandingPadSuccs.size() > 1) + report("MBB has more than one landing pad successor", MBB); + + // Call AnalyzeBranch. If it succeeds, there several more conditions to check. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + if (!TII->AnalyzeBranch(*const_cast(MBB), + TBB, FBB, Cond)) { + // Ok, AnalyzeBranch thinks it knows what's going on with this block. Let's + // check whether its answers match up with reality. + if (!TBB && !FBB) { + // Block falls through to its successor. + MachineFunction::const_iterator MBBI = MBB; + ++MBBI; + if (MBBI == MF->end()) { + // It's possible that the block legitimately ends with a noreturn + // call or an unreachable, in which case it won't actually fall + // out the bottom of the function. + } else if (MBB->succ_size() == LandingPadSuccs.size()) { + // It's possible that the block legitimately ends with a noreturn + // call or an unreachable, in which case it won't actuall fall + // out of the block. + } else if (MBB->succ_size() != 1+LandingPadSuccs.size()) { + report("MBB exits via unconditional fall-through but doesn't have " + "exactly one CFG successor!", MBB); + } else if (!MBB->isSuccessor(MBBI)) { + report("MBB exits via unconditional fall-through but its successor " + "differs from its CFG successor!", MBB); + } + if (!MBB->empty() && MBB->back().getDesc().isBarrier() && + !TII->isPredicated(&MBB->back())) { + report("MBB exits via unconditional fall-through but ends with a " + "barrier instruction!", MBB); + } + if (!Cond.empty()) { + report("MBB exits via unconditional fall-through but has a condition!", + MBB); + } + } else if (TBB && !FBB && Cond.empty()) { + // Block unconditionally branches somewhere. + if (MBB->succ_size() != 1+LandingPadSuccs.size()) { + report("MBB exits via unconditional branch but doesn't have " + "exactly one CFG successor!", MBB); + } else if (!MBB->isSuccessor(TBB)) { + report("MBB exits via unconditional branch but the CFG " + "successor doesn't match the actual successor!", MBB); + } + if (MBB->empty()) { + report("MBB exits via unconditional branch but doesn't contain " + "any instructions!", MBB); + } else if (!MBB->back().getDesc().isBarrier()) { + report("MBB exits via unconditional branch but doesn't end with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via unconditional branch but the branch isn't a " + "terminator instruction!", MBB); + } + } else if (TBB && !FBB && !Cond.empty()) { + // Block conditionally branches somewhere, otherwise falls through. + MachineFunction::const_iterator MBBI = MBB; + ++MBBI; + if (MBBI == MF->end()) { + report("MBB conditionally falls through out of function!", MBB); + } if (MBB->succ_size() != 2) { + report("MBB exits via conditional branch/fall-through but doesn't have " + "exactly two CFG successors!", MBB); + } else if (!matchPair(MBB->succ_begin(), TBB, MBBI)) { + report("MBB exits via conditional branch/fall-through but the CFG " + "successors don't match the actual successors!", MBB); + } + if (MBB->empty()) { + report("MBB exits via conditional branch/fall-through but doesn't " + "contain any instructions!", MBB); + } else if (MBB->back().getDesc().isBarrier()) { + report("MBB exits via conditional branch/fall-through but ends with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via conditional branch/fall-through but the branch " + "isn't a terminator instruction!", MBB); + } + } else if (TBB && FBB) { + // Block conditionally branches somewhere, otherwise branches + // somewhere else. + if (MBB->succ_size() != 2) { + report("MBB exits via conditional branch/branch but doesn't have " + "exactly two CFG successors!", MBB); + } else if (!matchPair(MBB->succ_begin(), TBB, FBB)) { + report("MBB exits via conditional branch/branch but the CFG " + "successors don't match the actual successors!", MBB); + } + if (MBB->empty()) { + report("MBB exits via conditional branch/branch but doesn't " + "contain any instructions!", MBB); + } else if (!MBB->back().getDesc().isBarrier()) { + report("MBB exits via conditional branch/branch but doesn't end with a " + "barrier instruction!", MBB); + } else if (!MBB->back().getDesc().isTerminator()) { + report("MBB exits via conditional branch/branch but the branch " + "isn't a terminator instruction!", MBB); + } + if (Cond.empty()) { + report("MBB exits via conditinal branch/branch but there's no " + "condition!", MBB); + } + } else { + report("AnalyzeBranch returned invalid data!", MBB); + } + } + + regsLive.clear(); + for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) { + if (!TargetRegisterInfo::isPhysicalRegister(*I)) { + report("MBB live-in list contains non-physical register", MBB); + continue; + } + regsLive.insert(*I); + for (const unsigned *R = TRI->getSubRegisters(*I); *R; R++) + regsLive.insert(*R); + } + regsLiveInButUnused = regsLive; + + const MachineFrameInfo *MFI = MF->getFrameInfo(); + assert(MFI && "Function has no frame info"); + BitVector PR = MFI->getPristineRegs(MBB); + for (int I = PR.find_first(); I>0; I = PR.find_next(I)) { + regsLive.insert(I); + for (const unsigned *R = TRI->getSubRegisters(I); *R; R++) + regsLive.insert(*R); + } + + regsKilled.clear(); + regsDefined.clear(); + + if (Indexes) + lastIndex = Indexes->getMBBStartIdx(MBB); +} + +void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) { + const TargetInstrDesc &TI = MI->getDesc(); + if (MI->getNumOperands() < TI.getNumOperands()) { + report("Too few operands", MI); + *OS << TI.getNumOperands() << " operands expected, but " + << MI->getNumExplicitOperands() << " given.\n"; + } + + // Check the MachineMemOperands for basic consistency. + for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), + E = MI->memoperands_end(); I != E; ++I) { + if ((*I)->isLoad() && !TI.mayLoad()) + report("Missing mayLoad flag", MI); + if ((*I)->isStore() && !TI.mayStore()) + report("Missing mayStore flag", MI); + } + + // Debug values must not have a slot index. + // Other instructions must have one. + if (LiveInts) { + bool mapped = !LiveInts->isNotInMIMap(MI); + if (MI->isDebugValue()) { + if (mapped) + report("Debug instruction has a slot index", MI); + } else { + if (!mapped) + report("Missing slot index", MI); + } + } + +} + +void +MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { + const MachineInstr *MI = MO->getParent(); + const TargetInstrDesc &TI = MI->getDesc(); + const TargetOperandInfo &TOI = TI.OpInfo[MONum]; + + // The first TI.NumDefs operands must be explicit register defines + if (MONum < TI.getNumDefs()) { + if (!MO->isReg()) + report("Explicit definition must be a register", MO, MONum); + else if (!MO->isDef()) + report("Explicit definition marked as use", MO, MONum); + else if (MO->isImplicit()) + report("Explicit definition marked as implicit", MO, MONum); + } else if (MONum < TI.getNumOperands()) { + // Don't check if it's the last operand in a variadic instruction. See, + // e.g., LDM_RET in the arm back end. + if (MO->isReg() && !(TI.isVariadic() && MONum == TI.getNumOperands()-1)) { + if (MO->isDef() && !TOI.isOptionalDef()) + report("Explicit operand marked as def", MO, MONum); + if (MO->isImplicit()) + report("Explicit operand marked as implicit", MO, MONum); + } + } else { + // ARM adds %reg0 operands to indicate predicates. We'll allow that. + if (MO->isReg() && !MO->isImplicit() && !TI.isVariadic() && MO->getReg()) + report("Extra explicit operand on non-variadic instruction", MO, MONum); + } + + switch (MO->getType()) { + case MachineOperand::MO_Register: { + const unsigned Reg = MO->getReg(); + if (!Reg) + return; + + // Check Live Variables. + if (MI->isDebugValue()) { + // Liveness checks are not valid for debug values. + } else if (MO->isUndef()) { + // An doesn't refer to any register, so just skip it. + } else if (MO->isUse()) { + regsLiveInButUnused.erase(Reg); + + bool isKill = false; + unsigned defIdx; + if (MI->isRegTiedToDefOperand(MONum, &defIdx)) { + // A two-addr use counts as a kill if use and def are the same. + unsigned DefReg = MI->getOperand(defIdx).getReg(); + if (Reg == DefReg) { + isKill = true; + // And in that case an explicit kill flag is not allowed. + if (MO->isKill()) + report("Illegal kill flag on two-address instruction operand", + MO, MONum); + } else if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + report("Two-address instruction operands must be identical", + MO, MONum); + } + } else + isKill = MO->isKill(); + + if (isKill) + addRegWithSubRegs(regsKilled, Reg); + + // Check that LiveVars knows this kill. + if (LiveVars && TargetRegisterInfo::isVirtualRegister(Reg) && + MO->isKill()) { + LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg); + if (std::find(VI.Kills.begin(), + VI.Kills.end(), MI) == VI.Kills.end()) + report("Kill missing from LiveVariables", MO, MONum); + } + + // Check LiveInts liveness and kill. + if (TargetRegisterInfo::isVirtualRegister(Reg) && + LiveInts && !LiveInts->isNotInMIMap(MI)) { + SlotIndex UseIdx = LiveInts->getInstructionIndex(MI).getUseIndex(); + if (LiveInts->hasInterval(Reg)) { + const LiveInterval &LI = LiveInts->getInterval(Reg); + if (!LI.liveAt(UseIdx)) { + report("No live range at use", MO, MONum); + *OS << UseIdx << " is not live in " << LI << '\n'; + } + // Check for extra kill flags. + // Note that we allow missing kill flags for now. + if (MO->isKill() && !LI.killedAt(UseIdx.getDefIndex())) { + report("Live range continues after kill flag", MO, MONum); + *OS << "Live range: " << LI << '\n'; + } + } else { + report("Virtual register has no Live interval", MO, MONum); + } + } + + // Use of a dead register. + if (!regsLive.count(Reg)) { + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + // Reserved registers may be used even when 'dead'. + if (!isReserved(Reg)) + report("Using an undefined physical register", MO, MONum); + } else { + BBInfo &MInfo = MBBInfoMap[MI->getParent()]; + // We don't know which virtual registers are live in, so only complain + // if vreg was killed in this MBB. Otherwise keep track of vregs that + // must be live in. PHI instructions are handled separately. + if (MInfo.regsKilled.count(Reg)) + report("Using a killed virtual register", MO, MONum); + else if (!MI->isPHI()) + MInfo.vregsLiveIn.insert(std::make_pair(Reg, MI)); + } + } + } else { + assert(MO->isDef()); + // Register defined. + // TODO: verify that earlyclobber ops are not used. + if (MO->isDead()) + addRegWithSubRegs(regsDead, Reg); + else + addRegWithSubRegs(regsDefined, Reg); + + // Check LiveInts for a live range, but only for virtual registers. + if (LiveInts && TargetRegisterInfo::isVirtualRegister(Reg) && + !LiveInts->isNotInMIMap(MI)) { + SlotIndex DefIdx = LiveInts->getInstructionIndex(MI).getDefIndex(); + if (LiveInts->hasInterval(Reg)) { + const LiveInterval &LI = LiveInts->getInterval(Reg); + if (const VNInfo *VNI = LI.getVNInfoAt(DefIdx)) { + assert(VNI && "NULL valno is not allowed"); + if (VNI->def != DefIdx && !MO->isEarlyClobber()) { + report("Inconsistent valno->def", MO, MONum); + *OS << "Valno " << VNI->id << " is not defined at " + << DefIdx << " in " << LI << '\n'; + } + } else { + report("No live range at def", MO, MONum); + *OS << DefIdx << " is not live in " << LI << '\n'; + } + } else { + report("Virtual register has no Live interval", MO, MONum); + } + } + } + + // Check register classes. + if (MONum < TI.getNumOperands() && !MO->isImplicit()) { + unsigned SubIdx = MO->getSubReg(); + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + unsigned sr = Reg; + if (SubIdx) { + unsigned s = TRI->getSubReg(Reg, SubIdx); + if (!s) { + report("Invalid subregister index for physical register", + MO, MONum); + return; + } + sr = s; + } + if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (!DRC->contains(sr)) { + report("Illegal physical register for instruction", MO, MONum); + *OS << TRI->getName(sr) << " is not a " + << DRC->getName() << " register.\n"; + } + } + } else { + // Virtual register. + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + if (SubIdx) { + const TargetRegisterClass *SRC = RC->getSubRegisterRegClass(SubIdx); + if (!SRC) { + report("Invalid subregister index for virtual register", MO, MONum); + *OS << "Register class " << RC->getName() + << " does not support subreg index " << SubIdx << "\n"; + return; + } + RC = SRC; + } + if (const TargetRegisterClass *DRC = TOI.getRegClass(TRI)) { + if (RC != DRC && !RC->hasSuperClass(DRC)) { + report("Illegal virtual register for instruction", MO, MONum); + *OS << "Expected a " << DRC->getName() << " register, but got a " + << RC->getName() << " register\n"; + } + } + } + } + break; + } + + case MachineOperand::MO_MachineBasicBlock: + if (MI->isPHI() && !MO->getMBB()->isSuccessor(MI->getParent())) + report("PHI operand is not in the CFG", MO, MONum); + break; + + case MachineOperand::MO_FrameIndex: + if (LiveStks && LiveStks->hasInterval(MO->getIndex()) && + LiveInts && !LiveInts->isNotInMIMap(MI)) { + LiveInterval &LI = LiveStks->getInterval(MO->getIndex()); + SlotIndex Idx = LiveInts->getInstructionIndex(MI); + if (TI.mayLoad() && !LI.liveAt(Idx.getUseIndex())) { + report("Instruction loads from dead spill slot", MO, MONum); + *OS << "Live stack: " << LI << '\n'; + } + if (TI.mayStore() && !LI.liveAt(Idx.getDefIndex())) { + report("Instruction stores to dead spill slot", MO, MONum); + *OS << "Live stack: " << LI << '\n'; + } + } + break; + + default: + break; + } +} + +void MachineVerifier::visitMachineInstrAfter(const MachineInstr *MI) { + BBInfo &MInfo = MBBInfoMap[MI->getParent()]; + set_union(MInfo.regsKilled, regsKilled); + set_subtract(regsLive, regsKilled); regsKilled.clear(); + set_subtract(regsLive, regsDead); regsDead.clear(); + set_union(regsLive, regsDefined); regsDefined.clear(); + + if (Indexes && Indexes->hasIndex(MI)) { + SlotIndex idx = Indexes->getInstructionIndex(MI); + if (!(idx > lastIndex)) { + report("Instruction index out of order", MI); + *OS << "Last instruction was at " << lastIndex << '\n'; + } + lastIndex = idx; + } +} + +void +MachineVerifier::visitMachineBasicBlockAfter(const MachineBasicBlock *MBB) { + MBBInfoMap[MBB].regsLiveOut = regsLive; + regsLive.clear(); + + if (Indexes) { + SlotIndex stop = Indexes->getMBBEndIdx(MBB); + if (!(stop > lastIndex)) { + report("Block ends before last instruction index", MBB); + *OS << "Block ends at " << stop + << " last instruction was at " << lastIndex << '\n'; + } + lastIndex = stop; + } +} + +// Calculate the largest possible vregsPassed sets. These are the registers that +// can pass through an MBB live, but may not be live every time. It is assumed +// that all vregsPassed sets are empty before the call. +void MachineVerifier::calcRegsPassed() { + // First push live-out regs to successors' vregsPassed. Remember the MBBs that + // have any vregsPassed. + DenseSet todo; + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + const MachineBasicBlock &MBB(*MFI); + BBInfo &MInfo = MBBInfoMap[&MBB]; + if (!MInfo.reachable) + continue; + for (MachineBasicBlock::const_succ_iterator SuI = MBB.succ_begin(), + SuE = MBB.succ_end(); SuI != SuE; ++SuI) { + BBInfo &SInfo = MBBInfoMap[*SuI]; + if (SInfo.addPassed(MInfo.regsLiveOut)) + todo.insert(*SuI); + } + } + + // Iteratively push vregsPassed to successors. This will converge to the same + // final state regardless of DenseSet iteration order. + while (!todo.empty()) { + const MachineBasicBlock *MBB = *todo.begin(); + todo.erase(MBB); + BBInfo &MInfo = MBBInfoMap[MBB]; + for (MachineBasicBlock::const_succ_iterator SuI = MBB->succ_begin(), + SuE = MBB->succ_end(); SuI != SuE; ++SuI) { + if (*SuI == MBB) + continue; + BBInfo &SInfo = MBBInfoMap[*SuI]; + if (SInfo.addPassed(MInfo.vregsPassed)) + todo.insert(*SuI); + } + } +} + +// Calculate the set of virtual registers that must be passed through each basic +// block in order to satisfy the requirements of successor blocks. This is very +// similar to calcRegsPassed, only backwards. +void MachineVerifier::calcRegsRequired() { + // First push live-in regs to predecessors' vregsRequired. + DenseSet todo; + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + const MachineBasicBlock &MBB(*MFI); + BBInfo &MInfo = MBBInfoMap[&MBB]; + for (MachineBasicBlock::const_pred_iterator PrI = MBB.pred_begin(), + PrE = MBB.pred_end(); PrI != PrE; ++PrI) { + BBInfo &PInfo = MBBInfoMap[*PrI]; + if (PInfo.addRequired(MInfo.vregsLiveIn)) + todo.insert(*PrI); + } + } + + // Iteratively push vregsRequired to predecessors. This will converge to the + // same final state regardless of DenseSet iteration order. + while (!todo.empty()) { + const MachineBasicBlock *MBB = *todo.begin(); + todo.erase(MBB); + BBInfo &MInfo = MBBInfoMap[MBB]; + for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(), + PrE = MBB->pred_end(); PrI != PrE; ++PrI) { + if (*PrI == MBB) + continue; + BBInfo &SInfo = MBBInfoMap[*PrI]; + if (SInfo.addRequired(MInfo.vregsRequired)) + todo.insert(*PrI); + } + } +} + +// Check PHI instructions at the beginning of MBB. It is assumed that +// calcRegsPassed has been run so BBInfo::isLiveOut is valid. +void MachineVerifier::checkPHIOps(const MachineBasicBlock *MBB) { + for (MachineBasicBlock::const_iterator BBI = MBB->begin(), BBE = MBB->end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + DenseSet seen; + + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + unsigned Reg = BBI->getOperand(i).getReg(); + const MachineBasicBlock *Pre = BBI->getOperand(i + 1).getMBB(); + if (!Pre->isSuccessor(MBB)) + continue; + seen.insert(Pre); + BBInfo &PrInfo = MBBInfoMap[Pre]; + if (PrInfo.reachable && !PrInfo.isLiveOut(Reg)) + report("PHI operand is not live-out from predecessor", + &BBI->getOperand(i), i); + } + + // Did we see all predecessors? + for (MachineBasicBlock::const_pred_iterator PrI = MBB->pred_begin(), + PrE = MBB->pred_end(); PrI != PrE; ++PrI) { + if (!seen.count(*PrI)) { + report("Missing PHI operand", BBI); + *OS << "BB#" << (*PrI)->getNumber() + << " is a predecessor according to the CFG.\n"; + } + } + } +} + +void MachineVerifier::visitMachineFunctionAfter() { + calcRegsPassed(); + + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + BBInfo &MInfo = MBBInfoMap[MFI]; + + // Skip unreachable MBBs. + if (!MInfo.reachable) + continue; + + checkPHIOps(MFI); + } + + // Now check liveness info if available + if (LiveVars || LiveInts) + calcRegsRequired(); + if (LiveVars) + verifyLiveVariables(); + if (LiveInts) + verifyLiveIntervals(); +} + +void MachineVerifier::verifyLiveVariables() { + assert(LiveVars && "Don't call verifyLiveVariables without LiveVars"); + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + LiveVariables::VarInfo &VI = LiveVars->getVarInfo(Reg); + for (MachineFunction::const_iterator MFI = MF->begin(), MFE = MF->end(); + MFI != MFE; ++MFI) { + BBInfo &MInfo = MBBInfoMap[MFI]; + + // Our vregsRequired should be identical to LiveVariables' AliveBlocks + if (MInfo.vregsRequired.count(Reg)) { + if (!VI.AliveBlocks.test(MFI->getNumber())) { + report("LiveVariables: Block missing from AliveBlocks", MFI); + *OS << "Virtual register " << PrintReg(Reg) + << " must be live through the block.\n"; + } + } else { + if (VI.AliveBlocks.test(MFI->getNumber())) { + report("LiveVariables: Block should not be in AliveBlocks", MFI); + *OS << "Virtual register " << PrintReg(Reg) + << " is not needed live through the block.\n"; + } + } + } + } +} + +void MachineVerifier::verifyLiveIntervals() { + assert(LiveInts && "Don't call verifyLiveIntervals without LiveInts"); + for (LiveIntervals::const_iterator LVI = LiveInts->begin(), + LVE = LiveInts->end(); LVI != LVE; ++LVI) { + const LiveInterval &LI = *LVI->second; + + // Spilling and splitting may leave unused registers around. Skip them. + if (MRI->use_empty(LI.reg)) + continue; + + // Physical registers have much weirdness going on, mostly from coalescing. + // We should probably fix it, but for now just ignore them. + if (TargetRegisterInfo::isPhysicalRegister(LI.reg)) + continue; + + assert(LVI->first == LI.reg && "Invalid reg to interval mapping"); + + for (LiveInterval::const_vni_iterator I = LI.vni_begin(), E = LI.vni_end(); + I!=E; ++I) { + VNInfo *VNI = *I; + const VNInfo *DefVNI = LI.getVNInfoAt(VNI->def); + + if (!DefVNI) { + if (!VNI->isUnused()) { + report("Valno not live at def and not marked unused", MF); + *OS << "Valno #" << VNI->id << " in " << LI << '\n'; + } + continue; + } + + if (VNI->isUnused()) + continue; + + if (DefVNI != VNI) { + report("Live range at def has different valno", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << " where valno #" << DefVNI->id << " is live in " << LI << '\n'; + continue; + } + + const MachineBasicBlock *MBB = LiveInts->getMBBFromIndex(VNI->def); + if (!MBB) { + report("Invalid definition index", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << " in " << LI << '\n'; + continue; + } + + if (VNI->isPHIDef()) { + if (VNI->def != LiveInts->getMBBStartIdx(MBB)) { + report("PHIDef value is not defined at MBB start", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << ", not at the beginning of BB#" << MBB->getNumber() + << " in " << LI << '\n'; + } + } else { + // Non-PHI def. + const MachineInstr *MI = LiveInts->getInstructionFromIndex(VNI->def); + if (!MI) { + report("No instruction at def index", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << " in " << LI << '\n'; + } else if (!MI->modifiesRegister(LI.reg, TRI)) { + report("Defining instruction does not modify register", MI); + *OS << "Valno #" << VNI->id << " in " << LI << '\n'; + } + + bool isEarlyClobber = false; + if (MI) { + for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + if (MOI->isReg() && MOI->getReg() == LI.reg && MOI->isDef() && + MOI->isEarlyClobber()) { + isEarlyClobber = true; + break; + } + } + } + + // Early clobber defs begin at USE slots, but other defs must begin at + // DEF slots. + if (isEarlyClobber) { + if (!VNI->def.isUse()) { + report("Early clobber def must be at a USE slot", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << " in " << LI << '\n'; + } + } else if (!VNI->def.isDef()) { + report("Non-PHI, non-early clobber def must be at a DEF slot", MF); + *OS << "Valno #" << VNI->id << " is defined at " << VNI->def + << " in " << LI << '\n'; + } + } + } + + for (LiveInterval::const_iterator I = LI.begin(), E = LI.end(); I!=E; ++I) { + const VNInfo *VNI = I->valno; + assert(VNI && "Live range has no valno"); + + if (VNI->id >= LI.getNumValNums() || VNI != LI.getValNumInfo(VNI->id)) { + report("Foreign valno in live range", MF); + I->print(*OS); + *OS << " has a valno not in " << LI << '\n'; + } + + if (VNI->isUnused()) { + report("Live range valno is marked unused", MF); + I->print(*OS); + *OS << " in " << LI << '\n'; + } + + const MachineBasicBlock *MBB = LiveInts->getMBBFromIndex(I->start); + if (!MBB) { + report("Bad start of live segment, no basic block", MF); + I->print(*OS); + *OS << " in " << LI << '\n'; + continue; + } + SlotIndex MBBStartIdx = LiveInts->getMBBStartIdx(MBB); + if (I->start != MBBStartIdx && I->start != VNI->def) { + report("Live segment must begin at MBB entry or valno def", MBB); + I->print(*OS); + *OS << " in " << LI << '\n' << "Basic block starts at " + << MBBStartIdx << '\n'; + } + + const MachineBasicBlock *EndMBB = + LiveInts->getMBBFromIndex(I->end.getPrevSlot()); + if (!EndMBB) { + report("Bad end of live segment, no basic block", MF); + I->print(*OS); + *OS << " in " << LI << '\n'; + continue; + } + if (I->end != LiveInts->getMBBEndIdx(EndMBB)) { + // The live segment is ending inside EndMBB + const MachineInstr *MI = + LiveInts->getInstructionFromIndex(I->end.getPrevSlot()); + if (!MI) { + report("Live segment doesn't end at a valid instruction", EndMBB); + I->print(*OS); + *OS << " in " << LI << '\n' << "Basic block starts at " + << MBBStartIdx << '\n'; + } else if (TargetRegisterInfo::isVirtualRegister(LI.reg) && + !MI->readsVirtualRegister(LI.reg)) { + // A live range can end with either a redefinition, a kill flag on a + // use, or a dead flag on a def. + // FIXME: Should we check for each of these? + bool hasDeadDef = false; + for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + if (MOI->isReg() && MOI->getReg() == LI.reg && MOI->isDef() && MOI->isDead()) { + hasDeadDef = true; + break; + } + } + + if (!hasDeadDef) { + report("Instruction killing live segment neither defines nor reads " + "register", MI); + I->print(*OS); + *OS << " in " << LI << '\n'; + } + } + } + + // Now check all the basic blocks in this live segment. + MachineFunction::const_iterator MFI = MBB; + // Is this live range the beginning of a non-PHIDef VN? + if (I->start == VNI->def && !VNI->isPHIDef()) { + // Not live-in to any blocks. + if (MBB == EndMBB) + continue; + // Skip this block. + ++MFI; + } + for (;;) { + assert(LiveInts->isLiveInToMBB(LI, MFI)); + // We don't know how to track physregs into a landing pad. + if (TargetRegisterInfo::isPhysicalRegister(LI.reg) && + MFI->isLandingPad()) { + if (&*MFI == EndMBB) + break; + ++MFI; + continue; + } + // Check that VNI is live-out of all predecessors. + for (MachineBasicBlock::const_pred_iterator PI = MFI->pred_begin(), + PE = MFI->pred_end(); PI != PE; ++PI) { + SlotIndex PEnd = LiveInts->getMBBEndIdx(*PI).getPrevSlot(); + const VNInfo *PVNI = LI.getVNInfoAt(PEnd); + + if (VNI->isPHIDef() && VNI->def == LiveInts->getMBBStartIdx(MFI)) { + if (PVNI && !PVNI->hasPHIKill()) { + report("Value live out of predecessor doesn't have PHIKill", MF); + *OS << "Valno #" << PVNI->id << " live out of BB#" + << (*PI)->getNumber() << '@' << PEnd + << " doesn't have PHIKill, but Valno #" << VNI->id + << " is PHIDef and defined at the beginning of BB#" + << MFI->getNumber() << '@' << LiveInts->getMBBStartIdx(MFI) + << " in " << LI << '\n'; + } + continue; + } + + if (!PVNI) { + report("Register not marked live out of predecessor", *PI); + *OS << "Valno #" << VNI->id << " live into BB#" << MFI->getNumber() + << '@' << LiveInts->getMBBStartIdx(MFI) << ", not live at " + << PEnd << " in " << LI << '\n'; + continue; + } + + if (PVNI != VNI) { + report("Different value live out of predecessor", *PI); + *OS << "Valno #" << PVNI->id << " live out of BB#" + << (*PI)->getNumber() << '@' << PEnd + << "\nValno #" << VNI->id << " live into BB#" << MFI->getNumber() + << '@' << LiveInts->getMBBStartIdx(MFI) << " in " << LI << '\n'; + } + } + if (&*MFI == EndMBB) + break; + ++MFI; + } + } + + // Check the LI only has one connected component. + if (TargetRegisterInfo::isVirtualRegister(LI.reg)) { + ConnectedVNInfoEqClasses ConEQ(*LiveInts); + unsigned NumComp = ConEQ.Classify(&LI); + if (NumComp > 1) { + report("Multiple connected components in live interval", MF); + *OS << NumComp << " components in " << LI << '\n'; + for (unsigned comp = 0; comp != NumComp; ++comp) { + *OS << comp << ": valnos"; + for (LiveInterval::const_vni_iterator I = LI.vni_begin(), + E = LI.vni_end(); I!=E; ++I) + if (comp == ConEQ.getEqClass(*I)) + *OS << ' ' << (*I)->id; + *OS << '\n'; + } + } + } + } +} + diff --git a/final/lib/CodeGen/Makefile b/final/lib/CodeGen/Makefile new file mode 100644 index 00000000000..4ab3e3c0013 --- /dev/null +++ b/final/lib/CodeGen/Makefile @@ -0,0 +1,22 @@ +##===- lib/CodeGen/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMCodeGen +PARALLEL_DIRS = SelectionDAG AsmPrinter +BUILD_ARCHIVE = 1 + +include $(LEVEL)/Makefile.common + +# Xcode prior to 2.4 generates an error in -pedantic mode with use of HUGE_VAL +# in this directory. Disable -pedantic for this broken compiler. +ifneq ($(HUGE_VAL_SANITY),yes) +CompileCommonOpts := $(filter-out -pedantic, $(CompileCommonOpts)) +endif + diff --git a/final/lib/CodeGen/ObjectCodeEmitter.cpp b/final/lib/CodeGen/ObjectCodeEmitter.cpp new file mode 100644 index 00000000000..cf05275d7a3 --- /dev/null +++ b/final/lib/CodeGen/ObjectCodeEmitter.cpp @@ -0,0 +1,141 @@ +//===-- llvm/CodeGen/ObjectCodeEmitter.cpp -------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/BinaryObject.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/CodeGen/ObjectCodeEmitter.h" + +//===----------------------------------------------------------------------===// +// ObjectCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +ObjectCodeEmitter::ObjectCodeEmitter() : BO(0) {} +ObjectCodeEmitter::ObjectCodeEmitter(BinaryObject *bo) : BO(bo) {} +ObjectCodeEmitter::~ObjectCodeEmitter() {} + +/// setBinaryObject - set the BinaryObject we are writting to +void ObjectCodeEmitter::setBinaryObject(BinaryObject *bo) { BO = bo; } + +/// emitByte - This callback is invoked when a byte needs to be +/// written to the data stream, without buffer overflow testing. +void ObjectCodeEmitter::emitByte(uint8_t B) { + BO->emitByte(B); +} + +/// emitWordLE - This callback is invoked when a 32-bit word needs to be +/// written to the data stream in little-endian format. +void ObjectCodeEmitter::emitWordLE(uint32_t W) { + BO->emitWordLE(W); +} + +/// emitWordBE - This callback is invoked when a 32-bit word needs to be +/// written to the data stream in big-endian format. +void ObjectCodeEmitter::emitWordBE(uint32_t W) { + BO->emitWordBE(W); +} + +/// emitDWordLE - This callback is invoked when a 64-bit word needs to be +/// written to the data stream in little-endian format. +void ObjectCodeEmitter::emitDWordLE(uint64_t W) { + BO->emitDWordLE(W); +} + +/// emitDWordBE - This callback is invoked when a 64-bit word needs to be +/// written to the data stream in big-endian format. +void ObjectCodeEmitter::emitDWordBE(uint64_t W) { + BO->emitDWordBE(W); +} + +/// emitAlignment - Align 'BO' to the necessary alignment boundary. +void ObjectCodeEmitter::emitAlignment(unsigned Alignment /* 0 */, + uint8_t fill /* 0 */) { + BO->emitAlignment(Alignment, fill); +} + +/// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitULEB128Bytes(uint64_t Value) { + BO->emitULEB128Bytes(Value); +} + +/// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitSLEB128Bytes(uint64_t Value) { + BO->emitSLEB128Bytes(Value); +} + +/// emitString - This callback is invoked when a String needs to be +/// written to the data stream. +void ObjectCodeEmitter::emitString(const std::string &String) { + BO->emitString(String); +} + +/// getCurrentPCValue - This returns the address that the next emitted byte +/// will be output to. +uintptr_t ObjectCodeEmitter::getCurrentPCValue() const { + return BO->getCurrentPCOffset(); +} + +/// getCurrentPCOffset - Return the offset from the start of the emitted +/// buffer that we are currently writing to. +uintptr_t ObjectCodeEmitter::getCurrentPCOffset() const { + return BO->getCurrentPCOffset(); +} + +/// addRelocation - Whenever a relocatable address is needed, it should be +/// noted with this interface. +void ObjectCodeEmitter::addRelocation(const MachineRelocation& relocation) { + BO->addRelocation(relocation); +} + +/// StartMachineBasicBlock - This should be called by the target when a new +/// basic block is about to be emitted. This way the MCE knows where the +/// start of the block is, and can implement getMachineBasicBlockAddress. +void ObjectCodeEmitter::StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); +} + +/// getMachineBasicBlockAddress - Return the address of the specified +/// MachineBasicBlock, only usable after the label for the MBB has been +/// emitted. +uintptr_t +ObjectCodeEmitter::getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; +} + +/// getJumpTableEntryAddress - Return the address of the jump table with index +/// 'Index' in the function that last called initJumpTableInfo. +uintptr_t ObjectCodeEmitter::getJumpTableEntryAddress(unsigned Index) const { + assert(JTLocations.size() > Index && "JT not emitted!"); + return JTLocations[Index]; +} + +/// getConstantPoolEntryAddress - Return the address of the 'Index' entry in +/// the constant pool that was last emitted with the emitConstantPool method. +uintptr_t ObjectCodeEmitter::getConstantPoolEntryAddress(unsigned Index) const { + assert(CPLocations.size() > Index && "CP not emitted!"); + return CPLocations[Index]; +} + +/// getConstantPoolEntrySection - Return the section of the 'Index' entry in +/// the constant pool that was last emitted with the emitConstantPool method. +uintptr_t ObjectCodeEmitter::getConstantPoolEntrySection(unsigned Index) const { + assert(CPSections.size() > Index && "CP not emitted!"); + return CPSections[Index]; +} + +} // end namespace llvm + diff --git a/final/lib/CodeGen/OcamlGC.cpp b/final/lib/CodeGen/OcamlGC.cpp new file mode 100644 index 00000000000..48db200c513 --- /dev/null +++ b/final/lib/CodeGen/OcamlGC.cpp @@ -0,0 +1,37 @@ +//===-- OcamlGC.cpp - Ocaml frametable GC strategy ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements lowering for the llvm.gc* intrinsics compatible with +// Objective Caml 3.10.0, which uses a liveness-accurate static stack map. +// +// The frametable emitter is in OcamlGCPrinter.cpp. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GCs.h" +#include "llvm/CodeGen/GCStrategy.h" + +using namespace llvm; + +namespace { + class OcamlGC : public GCStrategy { + public: + OcamlGC(); + }; +} + +static GCRegistry::Add +X("ocaml", "ocaml 3.10-compatible GC"); + +void llvm::linkOcamlGC() { } + +OcamlGC::OcamlGC() { + NeededSafePoints = 1 << GC::PostCall; + UsesMetadata = true; +} diff --git a/final/lib/CodeGen/OptimizePHIs.cpp b/final/lib/CodeGen/OptimizePHIs.cpp new file mode 100644 index 00000000000..c05be130ec6 --- /dev/null +++ b/final/lib/CodeGen/OptimizePHIs.cpp @@ -0,0 +1,190 @@ +//===-- OptimizePHIs.cpp - Optimize machine instruction PHIs --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass optimizes machine instruction PHIs to take advantage of +// opportunities created during DAG legalization. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "phi-opt" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Function.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumPHICycles, "Number of PHI cycles replaced"); +STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles"); + +namespace { + class OptimizePHIs : public MachineFunctionPass { + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification + OptimizePHIs() : MachineFunctionPass(ID) { + initializeOptimizePHIsPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + typedef SmallPtrSet InstrSet; + typedef SmallPtrSetIterator InstrSetIterator; + + bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg, + InstrSet &PHIsInCycle); + bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle); + bool OptimizeBB(MachineBasicBlock &MBB); + }; +} + +char OptimizePHIs::ID = 0; +INITIALIZE_PASS(OptimizePHIs, "opt-phis", + "Optimize machine instruction PHIs", false, false) + +FunctionPass *llvm::createOptimizePHIsPass() { return new OptimizePHIs(); } + +bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) { + MRI = &Fn.getRegInfo(); + TII = Fn.getTarget().getInstrInfo(); + + // Find dead PHI cycles and PHI cycles that can be replaced by a single + // value. InstCombine does these optimizations, but DAG legalization may + // introduce new opportunities, e.g., when i64 values are split up for + // 32-bit targets. + bool Changed = false; + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + Changed |= OptimizeBB(*I); + + return Changed; +} + +/// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands +/// are copies of SingleValReg, possibly via copies through other PHIs. If +/// SingleValReg is zero on entry, it is set to the register with the single +/// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that +/// have been scanned. +bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI, + unsigned &SingleValReg, + InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + // Scan the PHI operands. + for (unsigned i = 1; i != MI->getNumOperands(); i += 2) { + unsigned SrcReg = MI->getOperand(i).getReg(); + if (SrcReg == DstReg) + continue; + MachineInstr *SrcMI = MRI->getVRegDef(SrcReg); + + // Skip over register-to-register moves. + if (SrcMI && SrcMI->isCopy() && + !SrcMI->getOperand(0).getSubReg() && + !SrcMI->getOperand(1).getSubReg() && + TargetRegisterInfo::isVirtualRegister(SrcMI->getOperand(1).getReg())) + SrcMI = MRI->getVRegDef(SrcMI->getOperand(1).getReg()); + if (!SrcMI) + return false; + + if (SrcMI->isPHI()) { + if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle)) + return false; + } else { + // Fail if there is more than one non-phi/non-move register. + if (SingleValReg != 0) + return false; + SingleValReg = SrcReg; + } + } + return true; +} + +/// IsDeadPHICycle - Check if the register defined by a PHI is only used by +/// other PHIs in a cycle. +bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(DstReg) && + "PHI destination is not a virtual register"); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(DstReg), + E = MRI->use_end(); I != E; ++I) { + MachineInstr *UseMI = &*I; + if (!UseMI->isPHI() || !IsDeadPHICycle(UseMI, PHIsInCycle)) + return false; + } + + return true; +} + +/// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by +/// a single value. +bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) { + bool Changed = false; + for (MachineBasicBlock::iterator + MII = MBB.begin(), E = MBB.end(); MII != E; ) { + MachineInstr *MI = &*MII++; + if (!MI->isPHI()) + break; + + // Check for single-value PHI cycles. + unsigned SingleValReg = 0; + InstrSet PHIsInCycle; + if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) && + SingleValReg != 0) { + MRI->replaceRegWith(MI->getOperand(0).getReg(), SingleValReg); + MI->eraseFromParent(); + ++NumPHICycles; + Changed = true; + continue; + } + + // Check for dead PHI cycles. + PHIsInCycle.clear(); + if (IsDeadPHICycle(MI, PHIsInCycle)) { + for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end(); + PI != PE; ++PI) { + MachineInstr *PhiMI = *PI; + if (&*MII == PhiMI) + ++MII; + PhiMI->eraseFromParent(); + } + ++NumDeadPHICycles; + Changed = true; + } + } + return Changed; +} diff --git a/final/lib/CodeGen/PHIElimination.cpp b/final/lib/CodeGen/PHIElimination.cpp new file mode 100644 index 00000000000..5f7cf582c96 --- /dev/null +++ b/final/lib/CodeGen/PHIElimination.cpp @@ -0,0 +1,427 @@ +//===-- PhiElimination.cpp - Eliminate PHI nodes by inserting copies ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass eliminates machine instruction PHI nodes by inserting copy +// instructions. This destroys SSA information, but is the desired input for +// some register allocators. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "phielim" +#include "PHIEliminationUtils.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Function.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include +#include +using namespace llvm; + +namespace { + class PHIElimination : public MachineFunctionPass { + MachineRegisterInfo *MRI; // Machine register information + + public: + static char ID; // Pass identification, replacement for typeid + PHIElimination() : MachineFunctionPass(ID) { + initializePHIEliminationPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &Fn); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + private: + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions + /// in predecessor basic blocks. + /// + bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB); + void LowerAtomicPHINode(MachineBasicBlock &MBB, + MachineBasicBlock::iterator AfterPHIsIt); + + /// analyzePHINodes - Gather information about the PHI nodes in + /// here. In particular, we want to map the number of uses of a virtual + /// register which is used in a PHI node. We map that to the BB the + /// vreg is coming from. This is used later to determine when the vreg + /// is killed in the BB. + /// + void analyzePHINodes(const MachineFunction& Fn); + + /// Split critical edges where necessary for good coalescer performance. + bool SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB, + LiveVariables &LV, MachineLoopInfo *MLI); + + typedef std::pair BBVRegPair; + typedef DenseMap VRegPHIUse; + + VRegPHIUse VRegPHIUseCount; + + // Defs of PHI sources which are implicit_def. + SmallPtrSet ImpDefs; + + // Map reusable lowered PHI node -> incoming join register. + typedef DenseMap LoweredPHIMap; + LoweredPHIMap LoweredPHIs; + }; +} + +STATISTIC(NumAtomic, "Number of atomic phis lowered"); +STATISTIC(NumCriticalEdgesSplit, "Number of critical edges split"); +STATISTIC(NumReused, "Number of reused lowered phis"); + +char PHIElimination::ID = 0; +INITIALIZE_PASS(PHIElimination, "phi-node-elimination", + "Eliminate PHI nodes for register allocation", false, false) + +char& llvm::PHIEliminationID = PHIElimination::ID; + +void PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool PHIElimination::runOnMachineFunction(MachineFunction &MF) { + MRI = &MF.getRegInfo(); + + bool Changed = false; + + // Split critical edges to help the coalescer + if (LiveVariables *LV = getAnalysisIfAvailable()) { + MachineLoopInfo *MLI = getAnalysisIfAvailable(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= SplitPHIEdges(MF, *I, *LV, MLI); + } + + // Populate VRegPHIUseCount + analyzePHINodes(MF); + + // Eliminate PHI instructions by inserting copies into predecessor blocks. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= EliminatePHINodes(MF, *I); + + // Remove dead IMPLICIT_DEF instructions. + for (SmallPtrSet::iterator I = ImpDefs.begin(), + E = ImpDefs.end(); I != E; ++I) { + MachineInstr *DefMI = *I; + unsigned DefReg = DefMI->getOperand(0).getReg(); + if (MRI->use_nodbg_empty(DefReg)) + DefMI->eraseFromParent(); + } + + // Clean up the lowered PHI instructions. + for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end(); + I != E; ++I) + MF.DeleteMachineInstr(I->first); + + LoweredPHIs.clear(); + ImpDefs.clear(); + VRegPHIUseCount.clear(); + + return Changed; +} + +/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in +/// predecessor basic blocks. +/// +bool PHIElimination::EliminatePHINodes(MachineFunction &MF, + MachineBasicBlock &MBB) { + if (MBB.empty() || !MBB.front().isPHI()) + return false; // Quick exit for basic blocks without PHIs. + + // Get an iterator to the first instruction after the last PHI node (this may + // also be the end of the basic block). + MachineBasicBlock::iterator AfterPHIsIt = MBB.SkipPHIsAndLabels(MBB.begin()); + + while (MBB.front().isPHI()) + LowerAtomicPHINode(MBB, AfterPHIsIt); + + return true; +} + +/// isSourceDefinedByImplicitDef - Return true if all sources of the phi node +/// are implicit_def's. +static bool isSourceDefinedByImplicitDef(const MachineInstr *MPhi, + const MachineRegisterInfo *MRI) { + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { + unsigned SrcReg = MPhi->getOperand(i).getReg(); + const MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (!DefMI || !DefMI->isImplicitDef()) + return false; + } + return true; +} + + + +/// LowerAtomicPHINode - Lower the PHI node at the top of the specified block, +/// under the assuption that it needs to be lowered in a way that supports +/// atomic execution of PHIs. This lowering method is always correct all of the +/// time. +/// +void PHIElimination::LowerAtomicPHINode( + MachineBasicBlock &MBB, + MachineBasicBlock::iterator AfterPHIsIt) { + ++NumAtomic; + // Unlink the PHI node from the basic block, but don't delete the PHI yet. + MachineInstr *MPhi = MBB.remove(MBB.begin()); + + unsigned NumSrcs = (MPhi->getNumOperands() - 1) / 2; + unsigned DestReg = MPhi->getOperand(0).getReg(); + assert(MPhi->getOperand(0).getSubReg() == 0 && "Can't handle sub-reg PHIs"); + bool isDead = MPhi->getOperand(0).isDead(); + + // Create a new register for the incoming PHI arguments. + MachineFunction &MF = *MBB.getParent(); + unsigned IncomingReg = 0; + bool reusedIncoming = false; // Is IncomingReg reused from an earlier PHI? + + // Insert a register to register copy at the top of the current block (but + // after any remaining phi nodes) which copies the new incoming register + // into the phi node destination. + const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); + if (isSourceDefinedByImplicitDef(MPhi, MRI)) + // If all sources of a PHI node are implicit_def, just emit an + // implicit_def instead of a copy. + BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(), + TII->get(TargetOpcode::IMPLICIT_DEF), DestReg); + else { + // Can we reuse an earlier PHI node? This only happens for critical edges, + // typically those created by tail duplication. + unsigned &entry = LoweredPHIs[MPhi]; + if (entry) { + // An identical PHI node was already lowered. Reuse the incoming register. + IncomingReg = entry; + reusedIncoming = true; + ++NumReused; + DEBUG(dbgs() << "Reusing " << PrintReg(IncomingReg) << " for " << *MPhi); + } else { + const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(DestReg); + entry = IncomingReg = MF.getRegInfo().createVirtualRegister(RC); + } + BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(), + TII->get(TargetOpcode::COPY), DestReg) + .addReg(IncomingReg); + } + + // Update live variable information if there is any. + LiveVariables *LV = getAnalysisIfAvailable(); + if (LV) { + MachineInstr *PHICopy = prior(AfterPHIsIt); + + if (IncomingReg) { + LiveVariables::VarInfo &VI = LV->getVarInfo(IncomingReg); + + // Increment use count of the newly created virtual register. + VI.NumUses++; + LV->setPHIJoin(IncomingReg); + + // When we are reusing the incoming register, it may already have been + // killed in this block. The old kill will also have been inserted at + // AfterPHIsIt, so it appears before the current PHICopy. + if (reusedIncoming) + if (MachineInstr *OldKill = VI.findKill(&MBB)) { + DEBUG(dbgs() << "Remove old kill from " << *OldKill); + LV->removeVirtualRegisterKilled(IncomingReg, OldKill); + DEBUG(MBB.dump()); + } + + // Add information to LiveVariables to know that the incoming value is + // killed. Note that because the value is defined in several places (once + // each for each incoming block), the "def" block and instruction fields + // for the VarInfo is not filled in. + LV->addVirtualRegisterKilled(IncomingReg, PHICopy); + } + + // Since we are going to be deleting the PHI node, if it is the last use of + // any registers, or if the value itself is dead, we need to move this + // information over to the new copy we just inserted. + LV->removeVirtualRegistersKilled(MPhi); + + // If the result is dead, update LV. + if (isDead) { + LV->addVirtualRegisterDead(DestReg, PHICopy); + LV->removeVirtualRegisterDead(DestReg, MPhi); + } + } + + // Adjust the VRegPHIUseCount map to account for the removal of this PHI node. + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) + --VRegPHIUseCount[BBVRegPair(MPhi->getOperand(i+1).getMBB()->getNumber(), + MPhi->getOperand(i).getReg())]; + + // Now loop over all of the incoming arguments, changing them to copy into the + // IncomingReg register in the corresponding predecessor basic block. + SmallPtrSet MBBsInsertedInto; + for (int i = NumSrcs - 1; i >= 0; --i) { + unsigned SrcReg = MPhi->getOperand(i*2+1).getReg(); + unsigned SrcSubReg = MPhi->getOperand(i*2+1).getSubReg(); + + assert(TargetRegisterInfo::isVirtualRegister(SrcReg) && + "Machine PHI Operands must all be virtual registers!"); + + // Get the MachineBasicBlock equivalent of the BasicBlock that is the source + // path the PHI. + MachineBasicBlock &opBlock = *MPhi->getOperand(i*2+2).getMBB(); + + // If source is defined by an implicit def, there is no need to insert a + // copy. + MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (DefMI->isImplicitDef()) { + ImpDefs.insert(DefMI); + continue; + } + + // Check to make sure we haven't already emitted the copy for this block. + // This can happen because PHI nodes may have multiple entries for the same + // basic block. + if (!MBBsInsertedInto.insert(&opBlock)) + continue; // If the copy has already been emitted, we're done. + + // Find a safe location to insert the copy, this may be the first terminator + // in the block (or end()). + MachineBasicBlock::iterator InsertPos = + findPHICopyInsertPoint(&opBlock, &MBB, SrcReg); + + // Insert the copy. + if (!reusedIncoming && IncomingReg) + BuildMI(opBlock, InsertPos, MPhi->getDebugLoc(), + TII->get(TargetOpcode::COPY), IncomingReg).addReg(SrcReg, 0, SrcSubReg); + + // Now update live variable information if we have it. Otherwise we're done + if (!LV) continue; + + // We want to be able to insert a kill of the register if this PHI (aka, the + // copy we just inserted) is the last use of the source value. Live + // variable analysis conservatively handles this by saying that the value is + // live until the end of the block the PHI entry lives in. If the value + // really is dead at the PHI copy, there will be no successor blocks which + // have the value live-in. + + // Also check to see if this register is in use by another PHI node which + // has not yet been eliminated. If so, it will be killed at an appropriate + // point later. + + // Is it used by any PHI instructions in this block? + bool ValueIsUsed = VRegPHIUseCount[BBVRegPair(opBlock.getNumber(), SrcReg)]; + + // Okay, if we now know that the value is not live out of the block, we can + // add a kill marker in this block saying that it kills the incoming value! + if (!ValueIsUsed && !LV->isLiveOut(SrcReg, opBlock)) { + // In our final twist, we have to decide which instruction kills the + // register. In most cases this is the copy, however, the first + // terminator instruction at the end of the block may also use the value. + // In this case, we should mark *it* as being the killing block, not the + // copy. + MachineBasicBlock::iterator KillInst; + MachineBasicBlock::iterator Term = opBlock.getFirstTerminator(); + if (Term != opBlock.end() && Term->readsRegister(SrcReg)) { + KillInst = Term; + + // Check that no other terminators use values. +#ifndef NDEBUG + for (MachineBasicBlock::iterator TI = llvm::next(Term); + TI != opBlock.end(); ++TI) { + if (TI->isDebugValue()) + continue; + assert(!TI->readsRegister(SrcReg) && + "Terminator instructions cannot use virtual registers unless" + "they are the first terminator in a block!"); + } +#endif + } else if (reusedIncoming || !IncomingReg) { + // We may have to rewind a bit if we didn't insert a copy this time. + KillInst = Term; + while (KillInst != opBlock.begin()) { + --KillInst; + if (KillInst->isDebugValue()) + continue; + if (KillInst->readsRegister(SrcReg)) + break; + } + } else { + // We just inserted this copy. + KillInst = prior(InsertPos); + } + assert(KillInst->readsRegister(SrcReg) && "Cannot find kill instruction"); + + // Finally, mark it killed. + LV->addVirtualRegisterKilled(SrcReg, KillInst); + + // This vreg no longer lives all of the way through opBlock. + unsigned opBlockNum = opBlock.getNumber(); + LV->getVarInfo(SrcReg).AliveBlocks.reset(opBlockNum); + } + } + + // Really delete the PHI instruction now, if it is not in the LoweredPHIs map. + if (reusedIncoming || !IncomingReg) + MF.DeleteMachineInstr(MPhi); +} + +/// analyzePHINodes - Gather information about the PHI nodes in here. In +/// particular, we want to map the number of uses of a virtual register which is +/// used in a PHI node. We map that to the BB the vreg is coming from. This is +/// used later to determine when the vreg is killed in the BB. +/// +void PHIElimination::analyzePHINodes(const MachineFunction& MF) { + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) + for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->isPHI(); ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + ++VRegPHIUseCount[BBVRegPair(BBI->getOperand(i+1).getMBB()->getNumber(), + BBI->getOperand(i).getReg())]; +} + +bool PHIElimination::SplitPHIEdges(MachineFunction &MF, + MachineBasicBlock &MBB, + LiveVariables &LV, + MachineLoopInfo *MLI) { + if (MBB.empty() || !MBB.front().isPHI() || MBB.isLandingPad()) + return false; // Quick exit for basic blocks without PHIs. + + bool Changed = false; + for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + unsigned Reg = BBI->getOperand(i).getReg(); + MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); + // We break edges when registers are live out from the predecessor block + // (not considering PHI nodes). If the register is live in to this block + // anyway, we would gain nothing from splitting. + // Avoid splitting backedges of loops. It would introduce small + // out-of-line blocks into the loop which is very bad for code placement. + if (PreMBB != &MBB && + !LV.isLiveIn(Reg, MBB) && LV.isLiveOut(Reg, *PreMBB)) { + if (!MLI || + !(MLI->getLoopFor(PreMBB) == MLI->getLoopFor(&MBB) && + MLI->isLoopHeader(&MBB))) { + if (PreMBB->SplitCriticalEdge(&MBB, this)) { + Changed = true; + ++NumCriticalEdgesSplit; + } + } + } + } + } + return Changed; +} diff --git a/final/lib/CodeGen/PHIEliminationUtils.cpp b/final/lib/CodeGen/PHIEliminationUtils.cpp new file mode 100644 index 00000000000..10bfdcce676 --- /dev/null +++ b/final/lib/CodeGen/PHIEliminationUtils.cpp @@ -0,0 +1,61 @@ +//===-- PHIEliminationUtils.cpp - Helper functions for PHI elimination ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PHIEliminationUtils.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +// findCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg +// when following the CFG edge to SuccMBB. This needs to be after any def of +// SrcReg, but before any subsequent point where control flow might jump out of +// the basic block. +MachineBasicBlock::iterator +llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB, + unsigned SrcReg) { + // Handle the trivial case trivially. + if (MBB->empty()) + return MBB->begin(); + + // Usually, we just want to insert the copy before the first terminator + // instruction. However, for the edge going to a landing pad, we must insert + // the copy before the call/invoke instruction. + if (!SuccMBB->isLandingPad()) + return MBB->getFirstTerminator(); + + // Discover any defs/uses in this basic block. + SmallPtrSet DefUsesInMBB; + MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo(); + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(SrcReg), + RE = MRI.reg_end(); RI != RE; ++RI) { + MachineInstr* DefUseMI = &*RI; + if (DefUseMI->getParent() == MBB) + DefUsesInMBB.insert(DefUseMI); + } + + MachineBasicBlock::iterator InsertPoint; + if (DefUsesInMBB.empty()) { + // No defs. Insert the copy at the start of the basic block. + InsertPoint = MBB->begin(); + } else if (DefUsesInMBB.size() == 1) { + // Insert the copy immediately after the def/use. + InsertPoint = *DefUsesInMBB.begin(); + ++InsertPoint; + } else { + // Insert the copy immediately after the last def/use. + InsertPoint = MBB->end(); + while (!DefUsesInMBB.count(&*--InsertPoint)) {} + ++InsertPoint; + } + + // Make sure the copy goes after any phi nodes however. + return MBB->SkipPHIsAndLabels(InsertPoint); +} diff --git a/final/lib/CodeGen/PHIEliminationUtils.h b/final/lib/CodeGen/PHIEliminationUtils.h new file mode 100644 index 00000000000..9ac47fb4c50 --- /dev/null +++ b/final/lib/CodeGen/PHIEliminationUtils.h @@ -0,0 +1,25 @@ +//=- PHIEliminationUtils.h - Helper functions for PHI elimination *- C++ -*--=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PHIELIMINATIONUTILS_H +#define LLVM_CODEGEN_PHIELIMINATIONUTILS_H + +#include "llvm/CodeGen/MachineBasicBlock.h" + +namespace llvm { + /// findPHICopyInsertPoint - Find a safe place in MBB to insert a copy from + /// SrcReg when following the CFG edge to SuccMBB. This needs to be after + /// any def of SrcReg, but before any subsequent point where control flow + /// might jump out of the basic block. + MachineBasicBlock::iterator + findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB, + unsigned SrcReg); +} + +#endif diff --git a/final/lib/CodeGen/Passes.cpp b/final/lib/CodeGen/Passes.cpp new file mode 100644 index 00000000000..3489db2e9f4 --- /dev/null +++ b/final/lib/CodeGen/Passes.cpp @@ -0,0 +1,68 @@ +//===-- Passes.cpp - Target independent code generation passes ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces to access the target independent code +// generation passes provided by the LLVM backend. +// +//===---------------------------------------------------------------------===// + +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/Passes.h" + +using namespace llvm; + +//===---------------------------------------------------------------------===// +/// +/// RegisterRegAlloc class - Track the registration of register allocators. +/// +//===---------------------------------------------------------------------===// +MachinePassRegistry RegisterRegAlloc::Registry; + +static FunctionPass *createDefaultRegisterAllocator() { return 0; } +static RegisterRegAlloc +defaultRegAlloc("default", + "pick register allocator based on -O option", + createDefaultRegisterAllocator); + +//===---------------------------------------------------------------------===// +/// +/// RegAlloc command line options. +/// +//===---------------------------------------------------------------------===// +static cl::opt > +RegAlloc("regalloc", + cl::init(&createDefaultRegisterAllocator), + cl::desc("Register allocator to use")); + + +//===---------------------------------------------------------------------===// +/// +/// createRegisterAllocator - choose the appropriate register allocator. +/// +//===---------------------------------------------------------------------===// +FunctionPass *llvm::createRegisterAllocator(CodeGenOpt::Level OptLevel) { + RegisterRegAlloc::FunctionPassCtor Ctor = RegisterRegAlloc::getDefault(); + + if (!Ctor) { + Ctor = RegAlloc; + RegisterRegAlloc::setDefault(RegAlloc); + } + + if (Ctor != createDefaultRegisterAllocator) + return Ctor(); + + // When the 'default' allocator is requested, pick one based on OptLevel. + switch (OptLevel) { + case CodeGenOpt::None: + return createFastRegisterAllocator(); + default: + return createLinearScanRegisterAllocator(); + } +} diff --git a/final/lib/CodeGen/PeepholeOptimizer.cpp b/final/lib/CodeGen/PeepholeOptimizer.cpp new file mode 100644 index 00000000000..5d7123caa01 --- /dev/null +++ b/final/lib/CodeGen/PeepholeOptimizer.cpp @@ -0,0 +1,372 @@ +//===-- PeepholeOptimizer.cpp - Peephole Optimizations --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Perform peephole optimizations on the machine code: +// +// - Optimize Extensions +// +// Optimization of sign / zero extension instructions. It may be extended to +// handle other instructions with similar properties. +// +// On some targets, some instructions, e.g. X86 sign / zero extension, may +// leave the source value in the lower part of the result. This optimization +// will replace some uses of the pre-extension value with uses of the +// sub-register of the results. +// +// - Optimize Comparisons +// +// Optimization of comparison instructions. For instance, in this code: +// +// sub r1, 1 +// cmp r1, 0 +// bz L1 +// +// If the "sub" instruction all ready sets (or could be modified to set) the +// same flag that the "cmp" instruction sets and that "bz" uses, then we can +// eliminate the "cmp" instruction. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "peephole-opt" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +// Optimize Extensions +static cl::opt +Aggressive("aggressive-ext-opt", cl::Hidden, + cl::desc("Aggressive extension optimization")); + +static cl::opt +DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), + cl::desc("Disable the peephole optimizer")); + +STATISTIC(NumReuse, "Number of extension results reused"); +STATISTIC(NumEliminated, "Number of compares eliminated"); +STATISTIC(NumImmFold, "Number of move immediate foled"); + +namespace { + class PeepholeOptimizer : public MachineFunctionPass { + const TargetMachine *TM; + const TargetInstrInfo *TII; + MachineRegisterInfo *MRI; + MachineDominatorTree *DT; // Machine dominator tree + + public: + static char ID; // Pass identification + PeepholeOptimizer() : MachineFunctionPass(ID) { + initializePeepholeOptimizerPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + if (Aggressive) { + AU.addRequired(); + AU.addPreserved(); + } + } + + private: + bool OptimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); + bool OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, + SmallPtrSet &LocalMIs); + bool isMoveImmediate(MachineInstr *MI, + SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs); + bool FoldImmediate(MachineInstr *MI, MachineBasicBlock *MBB, + SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs); + }; +} + +char PeepholeOptimizer::ID = 0; +INITIALIZE_PASS_BEGIN(PeepholeOptimizer, "peephole-opts", + "Peephole Optimizations", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_END(PeepholeOptimizer, "peephole-opts", + "Peephole Optimizations", false, false) + +FunctionPass *llvm::createPeepholeOptimizerPass() { + return new PeepholeOptimizer(); +} + +/// OptimizeExtInstr - If instruction is a copy-like instruction, i.e. it reads +/// a single register and writes a single register and it does not modify the +/// source, and if the source value is preserved as a sub-register of the +/// result, then replace all reachable uses of the source with the subreg of the +/// result. +/// +/// Do not generate an EXTRACT that is used only in a debug use, as this changes +/// the code. Since this code does not currently share EXTRACTs, just ignore all +/// debug uses. +bool PeepholeOptimizer:: +OptimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, + SmallPtrSet &LocalMIs) { + unsigned SrcReg, DstReg, SubIdx; + if (!TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx)) + return false; + + if (TargetRegisterInfo::isPhysicalRegister(DstReg) || + TargetRegisterInfo::isPhysicalRegister(SrcReg)) + return false; + + MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(SrcReg); + if (++UI == MRI->use_nodbg_end()) + // No other uses. + return false; + + // The source has other uses. See if we can replace the other uses with use of + // the result of the extension. + SmallPtrSet ReachedBBs; + UI = MRI->use_nodbg_begin(DstReg); + for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end(); + UI != UE; ++UI) + ReachedBBs.insert(UI->getParent()); + + // Uses that are in the same BB of uses of the result of the instruction. + SmallVector Uses; + + // Uses that the result of the instruction can reach. + SmallVector ExtendedUses; + + bool ExtendLife = true; + UI = MRI->use_nodbg_begin(SrcReg); + for (MachineRegisterInfo::use_nodbg_iterator UE = MRI->use_nodbg_end(); + UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + if (UseMI == MI) + continue; + + if (UseMI->isPHI()) { + ExtendLife = false; + continue; + } + + // It's an error to translate this: + // + // %reg1025 = %reg1024 + // ... + // %reg1026 = SUBREG_TO_REG 0, %reg1024, 4 + // + // into this: + // + // %reg1025 = %reg1024 + // ... + // %reg1027 = COPY %reg1025:4 + // %reg1026 = SUBREG_TO_REG 0, %reg1027, 4 + // + // The problem here is that SUBREG_TO_REG is there to assert that an + // implicit zext occurs. It doesn't insert a zext instruction. If we allow + // the COPY here, it will give us the value after the , not the + // original value of %reg1024 before . + if (UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG) + continue; + + MachineBasicBlock *UseMBB = UseMI->getParent(); + if (UseMBB == MBB) { + // Local uses that come after the extension. + if (!LocalMIs.count(UseMI)) + Uses.push_back(&UseMO); + } else if (ReachedBBs.count(UseMBB)) { + // Non-local uses where the result of the extension is used. Always + // replace these unless it's a PHI. + Uses.push_back(&UseMO); + } else if (Aggressive && DT->dominates(MBB, UseMBB)) { + // We may want to extend the live range of the extension result in order + // to replace these uses. + ExtendedUses.push_back(&UseMO); + } else { + // Both will be live out of the def MBB anyway. Don't extend live range of + // the extension result. + ExtendLife = false; + break; + } + } + + if (ExtendLife && !ExtendedUses.empty()) + // Extend the liveness of the extension result. + std::copy(ExtendedUses.begin(), ExtendedUses.end(), + std::back_inserter(Uses)); + + // Now replace all uses. + bool Changed = false; + if (!Uses.empty()) { + SmallPtrSet PHIBBs; + + // Look for PHI uses of the extended result, we don't want to extend the + // liveness of a PHI input. It breaks all kinds of assumptions down + // stream. A PHI use is expected to be the kill of its source values. + UI = MRI->use_nodbg_begin(DstReg); + for (MachineRegisterInfo::use_nodbg_iterator + UE = MRI->use_nodbg_end(); UI != UE; ++UI) + if (UI->isPHI()) + PHIBBs.insert(UI->getParent()); + + const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); + for (unsigned i = 0, e = Uses.size(); i != e; ++i) { + MachineOperand *UseMO = Uses[i]; + MachineInstr *UseMI = UseMO->getParent(); + MachineBasicBlock *UseMBB = UseMI->getParent(); + if (PHIBBs.count(UseMBB)) + continue; + + unsigned NewVR = MRI->createVirtualRegister(RC); + BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(), + TII->get(TargetOpcode::COPY), NewVR) + .addReg(DstReg, 0, SubIdx); + + UseMO->setReg(NewVR); + ++NumReuse; + Changed = true; + } + } + + return Changed; +} + +/// OptimizeCmpInstr - If the instruction is a compare and the previous +/// instruction it's comparing against all ready sets (or could be modified to +/// set) the same flag as the compare, then we can remove the comparison and use +/// the flag from the previous instruction. +bool PeepholeOptimizer::OptimizeCmpInstr(MachineInstr *MI, + MachineBasicBlock *MBB){ + // If this instruction is a comparison against zero and isn't comparing a + // physical register, we can try to optimize it. + unsigned SrcReg; + int CmpMask, CmpValue; + if (!TII->AnalyzeCompare(MI, SrcReg, CmpMask, CmpValue) || + TargetRegisterInfo::isPhysicalRegister(SrcReg)) + return false; + + // Attempt to optimize the comparison instruction. + if (TII->OptimizeCompareInstr(MI, SrcReg, CmpMask, CmpValue, MRI)) { + ++NumEliminated; + return true; + } + + return false; +} + +bool PeepholeOptimizer::isMoveImmediate(MachineInstr *MI, + SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs) { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isMoveImmediate()) + return false; + if (TID.getNumDefs() != 1) + return false; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + ImmDefMIs.insert(std::make_pair(Reg, MI)); + ImmDefRegs.insert(Reg); + return true; + } + + return false; +} + +/// FoldImmediate - Try folding register operands that are defined by move +/// immediate instructions, i.e. a trivial constant folding optimization, if +/// and only if the def and use are in the same BB. +bool PeepholeOptimizer::FoldImmediate(MachineInstr *MI, MachineBasicBlock *MBB, + SmallSet &ImmDefRegs, + DenseMap &ImmDefMIs) { + for (unsigned i = 0, e = MI->getDesc().getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (ImmDefRegs.count(Reg) == 0) + continue; + DenseMap::iterator II = ImmDefMIs.find(Reg); + assert(II != ImmDefMIs.end()); + if (TII->FoldImmediate(MI, II->second, Reg, MRI)) { + ++NumImmFold; + return true; + } + } + return false; +} + +bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { + if (DisablePeephole) + return false; + + TM = &MF.getTarget(); + TII = TM->getInstrInfo(); + MRI = &MF.getRegInfo(); + DT = Aggressive ? &getAnalysis() : 0; + + bool Changed = false; + + SmallPtrSet LocalMIs; + SmallSet ImmDefRegs; + DenseMap ImmDefMIs; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + MachineBasicBlock *MBB = &*I; + + bool SeenMoveImm = false; + LocalMIs.clear(); + ImmDefRegs.clear(); + ImmDefMIs.clear(); + + bool First = true; + MachineBasicBlock::iterator PMII; + for (MachineBasicBlock::iterator + MII = I->begin(), MIE = I->end(); MII != MIE; ) { + MachineInstr *MI = &*MII; + LocalMIs.insert(MI); + + if (MI->isLabel() || MI->isPHI() || MI->isImplicitDef() || + MI->isKill() || MI->isInlineAsm() || MI->isDebugValue() || + MI->hasUnmodeledSideEffects()) { + ++MII; + continue; + } + + if (MI->getDesc().isCompare()) { + if (OptimizeCmpInstr(MI, MBB)) { + // MI is deleted. + Changed = true; + MII = First ? I->begin() : llvm::next(PMII); + continue; + } + } + + if (isMoveImmediate(MI, ImmDefRegs, ImmDefMIs)) { + SeenMoveImm = true; + } else { + Changed |= OptimizeExtInstr(MI, MBB, LocalMIs); + if (SeenMoveImm) + Changed |= FoldImmediate(MI, MBB, ImmDefRegs, ImmDefMIs); + } + + First = false; + PMII = MII; + ++MII; + } + } + + return Changed; +} diff --git a/final/lib/CodeGen/PostRASchedulerList.cpp b/final/lib/CodeGen/PostRASchedulerList.cpp new file mode 100644 index 00000000000..60c24b71079 --- /dev/null +++ b/final/lib/CodeGen/PostRASchedulerList.cpp @@ -0,0 +1,694 @@ +//===----- SchedulePostRAList.cpp - list scheduler ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a top-down list scheduler, using standard algorithms. +// The basic approach uses a priority queue of available nodes to schedule. +// One at a time, nodes are taken from the priority queue (thus in priority +// order), checked for legality to schedule, and emitted if legal. +// +// Nodes may not be legal to schedule either due to structural hazards (e.g. +// pipeline or resource constraints) or because an input to the instruction has +// not completed execution. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "post-RA-sched" +#include "AntiDepBreaker.h" +#include "AggressiveAntiDepBreaker.h" +#include "CriticalAntiDepBreaker.h" +#include "ScheduleDAGInstrs.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumNoops, "Number of noops inserted"); +STATISTIC(NumStalls, "Number of pipeline stalls"); +STATISTIC(NumFixedAnti, "Number of fixed anti-dependencies"); + +// Post-RA scheduling is enabled with +// TargetSubtarget.enablePostRAScheduler(). This flag can be used to +// override the target. +static cl::opt +EnablePostRAScheduler("post-RA-scheduler", + cl::desc("Enable scheduling after register allocation"), + cl::init(false), cl::Hidden); +static cl::opt +EnableAntiDepBreaking("break-anti-dependencies", + cl::desc("Break post-RA scheduling anti-dependencies: " + "\"critical\", \"all\", or \"none\""), + cl::init("none"), cl::Hidden); + +// If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod +static cl::opt +DebugDiv("postra-sched-debugdiv", + cl::desc("Debug control MBBs that are scheduled"), + cl::init(0), cl::Hidden); +static cl::opt +DebugMod("postra-sched-debugmod", + cl::desc("Debug control MBBs that are scheduled"), + cl::init(0), cl::Hidden); + +AntiDepBreaker::~AntiDepBreaker() { } + +namespace { + class PostRAScheduler : public MachineFunctionPass { + AliasAnalysis *AA; + const TargetInstrInfo *TII; + CodeGenOpt::Level OptLevel; + + public: + static char ID; + PostRAScheduler(CodeGenOpt::Level ol) : + MachineFunctionPass(ID), OptLevel(ol) {} + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + const char *getPassName() const { + return "Post RA top-down list latency scheduler"; + } + + bool runOnMachineFunction(MachineFunction &Fn); + }; + char PostRAScheduler::ID = 0; + + class SchedulePostRATDList : public ScheduleDAGInstrs { + /// AvailableQueue - The priority queue to use for the available SUnits. + /// + LatencyPriorityQueue AvailableQueue; + + /// PendingQueue - This contains all of the instructions whose operands have + /// been issued, but their results are not ready yet (due to the latency of + /// the operation). Once the operands becomes available, the instruction is + /// added to the AvailableQueue. + std::vector PendingQueue; + + /// Topo - A topological ordering for SUnits. + ScheduleDAGTopologicalSort Topo; + + /// HazardRec - The hazard recognizer to use. + ScheduleHazardRecognizer *HazardRec; + + /// AntiDepBreak - Anti-dependence breaking object, or NULL if none + AntiDepBreaker *AntiDepBreak; + + /// AA - AliasAnalysis for making memory reference queries. + AliasAnalysis *AA; + + /// KillIndices - The index of the most recent kill (proceding bottom-up), + /// or ~0u if the register is not live. + std::vector KillIndices; + + public: + SchedulePostRATDList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, + AliasAnalysis *AA, TargetSubtarget::AntiDepBreakMode AntiDepMode, + SmallVectorImpl &CriticalPathRCs); + + ~SchedulePostRATDList(); + + /// StartBlock - Initialize register live-range state for scheduling in + /// this block. + /// + void StartBlock(MachineBasicBlock *BB); + + /// Schedule - Schedule the instruction range using list scheduling. + /// + void Schedule(); + + /// Observe - Update liveness information to account for the current + /// instruction, which will not be scheduled. + /// + void Observe(MachineInstr *MI, unsigned Count); + + /// FinishBlock - Clean up register live-range state. + /// + void FinishBlock(); + + /// FixupKills - Fix register kill flags that have been made + /// invalid due to scheduling + /// + void FixupKills(MachineBasicBlock *MBB); + + private: + void ReleaseSucc(SUnit *SU, SDep *SuccEdge); + void ReleaseSuccessors(SUnit *SU); + void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle); + void ListScheduleTopDown(); + void StartBlockForKills(MachineBasicBlock *BB); + + // ToggleKillFlag - Toggle a register operand kill flag. Other + // adjustments may be made to the instruction if necessary. Return + // true if the operand has been deleted, false if not. + bool ToggleKillFlag(MachineInstr *MI, MachineOperand &MO); + }; +} + +SchedulePostRATDList::SchedulePostRATDList( + MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, + AliasAnalysis *AA, TargetSubtarget::AntiDepBreakMode AntiDepMode, + SmallVectorImpl &CriticalPathRCs) + : ScheduleDAGInstrs(MF, MLI, MDT), Topo(SUnits), AA(AA), + KillIndices(TRI->getNumRegs()) +{ + const TargetMachine &TM = MF.getTarget(); + const InstrItineraryData *InstrItins = TM.getInstrItineraryData(); + HazardRec = + TM.getInstrInfo()->CreateTargetPostRAHazardRecognizer(InstrItins, this); + AntiDepBreak = + ((AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ? + (AntiDepBreaker *)new AggressiveAntiDepBreaker(MF, CriticalPathRCs) : + ((AntiDepMode == TargetSubtarget::ANTIDEP_CRITICAL) ? + (AntiDepBreaker *)new CriticalAntiDepBreaker(MF) : NULL)); +} + +SchedulePostRATDList::~SchedulePostRATDList() { + delete HazardRec; + delete AntiDepBreak; +} + +bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) { + TII = Fn.getTarget().getInstrInfo(); + MachineLoopInfo &MLI = getAnalysis(); + MachineDominatorTree &MDT = getAnalysis(); + AliasAnalysis *AA = &getAnalysis(); + + // Check for explicit enable/disable of post-ra scheduling. + TargetSubtarget::AntiDepBreakMode AntiDepMode = TargetSubtarget::ANTIDEP_NONE; + SmallVector CriticalPathRCs; + if (EnablePostRAScheduler.getPosition() > 0) { + if (!EnablePostRAScheduler) + return false; + } else { + // Check that post-RA scheduling is enabled for this target. + // This may upgrade the AntiDepMode. + const TargetSubtarget &ST = Fn.getTarget().getSubtarget(); + if (!ST.enablePostRAScheduler(OptLevel, AntiDepMode, CriticalPathRCs)) + return false; + } + + // Check for antidep breaking override... + if (EnableAntiDepBreaking.getPosition() > 0) { + AntiDepMode = (EnableAntiDepBreaking == "all") ? + TargetSubtarget::ANTIDEP_ALL : + (EnableAntiDepBreaking == "critical") + ? TargetSubtarget::ANTIDEP_CRITICAL : TargetSubtarget::ANTIDEP_NONE; + } + + DEBUG(dbgs() << "PostRAScheduler\n"); + + SchedulePostRATDList Scheduler(Fn, MLI, MDT, AA, AntiDepMode, + CriticalPathRCs); + + // Loop over all of the basic blocks + for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); + MBB != MBBe; ++MBB) { +#ifndef NDEBUG + // If DebugDiv > 0 then only schedule MBB with (ID % DebugDiv) == DebugMod + if (DebugDiv > 0) { + static int bbcnt = 0; + if (bbcnt++ % DebugDiv != DebugMod) + continue; + dbgs() << "*** DEBUG scheduling " << Fn.getFunction()->getNameStr() << + ":BB#" << MBB->getNumber() << " ***\n"; + } +#endif + + // Initialize register live-range state for scheduling in this block. + Scheduler.StartBlock(MBB); + + // Schedule each sequence of instructions not interrupted by a label + // or anything else that effectively needs to shut down scheduling. + MachineBasicBlock::iterator Current = MBB->end(); + unsigned Count = MBB->size(), CurrentCount = Count; + for (MachineBasicBlock::iterator I = Current; I != MBB->begin(); ) { + MachineInstr *MI = llvm::prior(I); + if (TII->isSchedulingBoundary(MI, MBB, Fn)) { + Scheduler.Run(MBB, I, Current, CurrentCount); + Scheduler.EmitSchedule(); + Current = MI; + CurrentCount = Count - 1; + Scheduler.Observe(MI, CurrentCount); + } + I = MI; + --Count; + } + assert(Count == 0 && "Instruction count mismatch!"); + assert((MBB->begin() == Current || CurrentCount != 0) && + "Instruction count mismatch!"); + Scheduler.Run(MBB, MBB->begin(), Current, CurrentCount); + Scheduler.EmitSchedule(); + + // Clean up register live-range state. + Scheduler.FinishBlock(); + + // Update register kills + Scheduler.FixupKills(MBB); + } + + return true; +} + +/// StartBlock - Initialize register live-range state for scheduling in +/// this block. +/// +void SchedulePostRATDList::StartBlock(MachineBasicBlock *BB) { + // Call the superclass. + ScheduleDAGInstrs::StartBlock(BB); + + // Reset the hazard recognizer and anti-dep breaker. + HazardRec->Reset(); + if (AntiDepBreak != NULL) + AntiDepBreak->StartBlock(BB); +} + +/// Schedule - Schedule the instruction range using list scheduling. +/// +void SchedulePostRATDList::Schedule() { + // Build the scheduling graph. + BuildSchedGraph(AA); + + if (AntiDepBreak != NULL) { + unsigned Broken = + AntiDepBreak->BreakAntiDependencies(SUnits, Begin, InsertPos, + InsertPosIndex); + + if (Broken != 0) { + // We made changes. Update the dependency graph. + // Theoretically we could update the graph in place: + // When a live range is changed to use a different register, remove + // the def's anti-dependence *and* output-dependence edges due to + // that register, and add new anti-dependence and output-dependence + // edges based on the next live range of the register. + SUnits.clear(); + Sequence.clear(); + EntrySU = SUnit(); + ExitSU = SUnit(); + BuildSchedGraph(AA); + + NumFixedAnti += Broken; + } + } + + DEBUG(dbgs() << "********** List Scheduling **********\n"); + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + + AvailableQueue.initNodes(SUnits); + ListScheduleTopDown(); + AvailableQueue.releaseState(); +} + +/// Observe - Update liveness information to account for the current +/// instruction, which will not be scheduled. +/// +void SchedulePostRATDList::Observe(MachineInstr *MI, unsigned Count) { + if (AntiDepBreak != NULL) + AntiDepBreak->Observe(MI, Count, InsertPosIndex); +} + +/// FinishBlock - Clean up register live-range state. +/// +void SchedulePostRATDList::FinishBlock() { + if (AntiDepBreak != NULL) + AntiDepBreak->FinishBlock(); + + // Call the superclass. + ScheduleDAGInstrs::FinishBlock(); +} + +/// StartBlockForKills - Initialize register live-range state for updating kills +/// +void SchedulePostRATDList::StartBlockForKills(MachineBasicBlock *BB) { + // Initialize the indices to indicate that no registers are live. + for (unsigned i = 0; i < TRI->getNumRegs(); ++i) + KillIndices[i] = ~0u; + + // Determine the live-out physregs for this block. + if (!BB->empty() && BB->back().getDesc().isReturn()) { + // In a return block, examine the function live-out regs. + for (MachineRegisterInfo::liveout_iterator I = MRI.liveout_begin(), + E = MRI.liveout_end(); I != E; ++I) { + unsigned Reg = *I; + KillIndices[Reg] = BB->size(); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = BB->size(); + } + } + } + else { + // In a non-return block, examine the live-in regs of all successors. + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) { + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + KillIndices[Reg] = BB->size(); + // Repeat, for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = BB->size(); + } + } + } + } +} + +bool SchedulePostRATDList::ToggleKillFlag(MachineInstr *MI, + MachineOperand &MO) { + // Setting kill flag... + if (!MO.isKill()) { + MO.setIsKill(true); + return false; + } + + // If MO itself is live, clear the kill flag... + if (KillIndices[MO.getReg()] != ~0u) { + MO.setIsKill(false); + return false; + } + + // If any subreg of MO is live, then create an imp-def for that + // subreg and keep MO marked as killed. + MO.setIsKill(false); + bool AllDead = true; + const unsigned SuperReg = MO.getReg(); + for (const unsigned *Subreg = TRI->getSubRegisters(SuperReg); + *Subreg; ++Subreg) { + if (KillIndices[*Subreg] != ~0u) { + MI->addOperand(MachineOperand::CreateReg(*Subreg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + false /*IsDead*/)); + AllDead = false; + } + } + + if(AllDead) + MO.setIsKill(true); + return false; +} + +/// FixupKills - Fix the register kill flags, they may have been made +/// incorrect by instruction reordering. +/// +void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) { + DEBUG(dbgs() << "Fixup kills for BB#" << MBB->getNumber() << '\n'); + + std::set killedRegs; + BitVector ReservedRegs = TRI->getReservedRegs(MF); + + StartBlockForKills(MBB); + + // Examine block from end to start... + unsigned Count = MBB->size(); + for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin(); + I != E; --Count) { + MachineInstr *MI = --I; + if (MI->isDebugValue()) + continue; + + // Update liveness. Registers that are defed but not used in this + // instruction are now dead. Mark register and all subregs as they + // are completely defined. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + if (!MO.isDef()) continue; + // Ignore two-addr defs. + if (MI->isRegTiedToUseOperand(i)) continue; + + KillIndices[Reg] = ~0u; + + // Repeat for all subregs. + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = ~0u; + } + } + + // Examine all used registers and set/clear kill flag. When a + // register is used multiple times we only set the kill flag on + // the first use. + killedRegs.clear(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) continue; + unsigned Reg = MO.getReg(); + if ((Reg == 0) || ReservedRegs.test(Reg)) continue; + + bool kill = false; + if (killedRegs.find(Reg) == killedRegs.end()) { + kill = true; + // A register is not killed if any subregs are live... + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + if (KillIndices[*Subreg] != ~0u) { + kill = false; + break; + } + } + + // If subreg is not live, then register is killed if it became + // live in this instruction + if (kill) + kill = (KillIndices[Reg] == ~0u); + } + + if (MO.isKill() != kill) { + DEBUG(dbgs() << "Fixing " << MO << " in "); + // Warning: ToggleKillFlag may invalidate MO. + ToggleKillFlag(MI, MO); + DEBUG(MI->dump()); + } + + killedRegs.insert(Reg); + } + + // Mark any used register (that is not using undef) and subregs as + // now live... + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue; + unsigned Reg = MO.getReg(); + if ((Reg == 0) || ReservedRegs.test(Reg)) continue; + + KillIndices[Reg] = Count; + + for (const unsigned *Subreg = TRI->getSubRegisters(Reg); + *Subreg; ++Subreg) { + KillIndices[*Subreg] = Count; + } + } + } +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the PendingQueue if the count reaches zero. Also update its cycle bound. +void SchedulePostRATDList::ReleaseSucc(SUnit *SU, SDep *SuccEdge) { + SUnit *SuccSU = SuccEdge->getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + // Compute how many cycles it will be before this actually becomes + // available. This is the max of the start time of all predecessors plus + // their latencies. + SuccSU->setDepthToAtLeast(SU->getDepth() + SuccEdge->getLatency()); + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) + PendingQueue.push_back(SuccSU); +} + +/// ReleaseSuccessors - Call ReleaseSucc on each of SU's successors. +void SchedulePostRATDList::ReleaseSuccessors(SUnit *SU) { + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + ReleaseSucc(SU, &*I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) { + DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + Sequence.push_back(SU); + assert(CurCycle >= SU->getDepth() && + "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue.ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void SchedulePostRATDList::ListScheduleTopDown() { + unsigned CurCycle = 0; + + // We're scheduling top-down but we're visiting the regions in + // bottom-up order, so we don't know the hazards at the start of a + // region. So assume no hazards (this should usually be ok as most + // blocks are a single region). + HazardRec->Reset(); + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // Add all leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + bool available = SUnits[i].Preds.empty(); + if (available) { + AvailableQueue.push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // In any cycle where we can't schedule any instructions, we must + // stall or emit a noop, depending on the target. + bool CycleHasInsts = false; + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + std::vector NotReady; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue.empty() || !PendingQueue.empty()) { + // Check to see if any of the pending instructions are ready to issue. If + // so, add them to the available queue. + unsigned MinDepth = ~0u; + for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { + if (PendingQueue[i]->getDepth() <= CurCycle) { + AvailableQueue.push(PendingQueue[i]); + PendingQueue[i]->isAvailable = true; + PendingQueue[i] = PendingQueue.back(); + PendingQueue.pop_back(); + --i; --e; + } else if (PendingQueue[i]->getDepth() < MinDepth) + MinDepth = PendingQueue[i]->getDepth(); + } + + DEBUG(dbgs() << "\n*** Examining Available\n"; AvailableQueue.dump(this)); + + SUnit *FoundSUnit = 0; + bool HasNoopHazards = false; + while (!AvailableQueue.empty()) { + SUnit *CurSUnit = AvailableQueue.pop(); + + ScheduleHazardRecognizer::HazardType HT = + HazardRec->getHazardType(CurSUnit, 0/*no stalls*/); + if (HT == ScheduleHazardRecognizer::NoHazard) { + FoundSUnit = CurSUnit; + break; + } + + // Remember if this is a noop hazard. + HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard; + + NotReady.push_back(CurSUnit); + } + + // Add the nodes that aren't ready back onto the available list. + if (!NotReady.empty()) { + AvailableQueue.push_all(NotReady); + NotReady.clear(); + } + + // If we found a node to schedule... + if (FoundSUnit) { + // ... schedule the node... + ScheduleNodeTopDown(FoundSUnit, CurCycle); + HazardRec->EmitInstruction(FoundSUnit); + CycleHasInsts = true; + } else { + if (CycleHasInsts) { + DEBUG(dbgs() << "*** Finished cycle " << CurCycle << '\n'); + HazardRec->AdvanceCycle(); + } else if (!HasNoopHazards) { + // Otherwise, we have a pipeline stall, but no other problem, + // just advance the current cycle and try again. + DEBUG(dbgs() << "*** Stall in cycle " << CurCycle << '\n'); + HazardRec->AdvanceCycle(); + ++NumStalls; + } else { + // Otherwise, we have no instructions to issue and we have instructions + // that will fault if we don't do this right. This is the case for + // processors without pipeline interlocks and other cases. + DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n'); + HazardRec->EmitNoop(); + Sequence.push_back(0); // NULL here means noop + ++NumNoops; + } + + ++CurCycle; + CycleHasInsts = false; + } + } + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/false); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createPostRAScheduler(CodeGenOpt::Level OptLevel) { + return new PostRAScheduler(OptLevel); +} diff --git a/final/lib/CodeGen/PreAllocSplitting.cpp b/final/lib/CodeGen/PreAllocSplitting.cpp new file mode 100644 index 00000000000..d6e31dae9d1 --- /dev/null +++ b/final/lib/CodeGen/PreAllocSplitting.cpp @@ -0,0 +1,1430 @@ +//===-- PreAllocSplitting.cpp - Pre-allocation Interval Spltting Pass. ----===// +// +// 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 machine instruction level pre-register allocation +// live interval splitting pass. It finds live interval barriers, i.e. +// instructions which will kill all physical registers in certain register +// classes, and split all live intervals which cross the barrier. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-alloc-split" +#include "VirtRegMap.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +static cl::opt PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden); +static cl::opt DeadSplitLimit("dead-split-limit", cl::init(-1), + cl::Hidden); +static cl::opt RestoreFoldLimit("restore-fold-limit", cl::init(-1), + cl::Hidden); + +STATISTIC(NumSplits, "Number of intervals split"); +STATISTIC(NumRemats, "Number of intervals split by rematerialization"); +STATISTIC(NumFolds, "Number of intervals split with spill folding"); +STATISTIC(NumRestoreFolds, "Number of intervals split with restore folding"); +STATISTIC(NumRenumbers, "Number of intervals renumbered into new registers"); +STATISTIC(NumDeadSpills, "Number of dead spills removed"); + +namespace { + class PreAllocSplitting : public MachineFunctionPass { + MachineFunction *CurrMF; + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetRegisterInfo* TRI; + MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + SlotIndexes *SIs; + LiveIntervals *LIs; + LiveStacks *LSs; + VirtRegMap *VRM; + + // Barrier - Current barrier being processed. + MachineInstr *Barrier; + + // BarrierMBB - Basic block where the barrier resides in. + MachineBasicBlock *BarrierMBB; + + // Barrier - Current barrier index. + SlotIndex BarrierIdx; + + // CurrLI - Current live interval being split. + LiveInterval *CurrLI; + + // CurrSLI - Current stack slot live interval. + LiveInterval *CurrSLI; + + // CurrSValNo - Current val# for the stack slot live interval. + VNInfo *CurrSValNo; + + // IntervalSSMap - A map from live interval to spill slots. + DenseMap IntervalSSMap; + + // Def2SpillMap - A map from a def instruction index to spill index. + DenseMap Def2SpillMap; + + public: + static char ID; + PreAllocSplitting() : MachineFunctionPass(ID) { + initializePreAllocSplittingPass(*PassRegistry::getPassRegistry()); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreservedID(StrongPHIEliminationID); + AU.addPreservedID(PHIEliminationID); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual void releaseMemory() { + IntervalSSMap.clear(); + Def2SpillMap.clear(); + } + + virtual const char *getPassName() const { + return "Pre-Register Allocaton Live Interval Splitting"; + } + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* M = 0) const { + LIs->print(O, M); + } + + + private: + + MachineBasicBlock::iterator + findSpillPoint(MachineBasicBlock*, MachineInstr*, MachineInstr*, + SmallPtrSet&); + + MachineBasicBlock::iterator + findRestorePoint(MachineBasicBlock*, MachineInstr*, SlotIndex, + SmallPtrSet&); + + int CreateSpillStackSlot(unsigned, const TargetRegisterClass *); + + bool IsAvailableInStack(MachineBasicBlock*, unsigned, + SlotIndex, SlotIndex, + SlotIndex&, int&) const; + + void UpdateSpillSlotInterval(VNInfo*, SlotIndex, SlotIndex); + + bool SplitRegLiveInterval(LiveInterval*); + + bool SplitRegLiveIntervals(const TargetRegisterClass **, + SmallPtrSet&); + + bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB, + MachineBasicBlock* BarrierMBB); + bool Rematerialize(unsigned vreg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + SmallPtrSet& RefsInMBB); + MachineInstr* FoldSpill(unsigned vreg, const TargetRegisterClass* RC, + MachineInstr* DefMI, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int& SS, + SmallPtrSet& RefsInMBB); + MachineInstr* FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB); + void RenumberValno(VNInfo* VN); + void ReconstructLiveInterval(LiveInterval* LI); + bool removeDeadSpills(SmallPtrSet& split); + unsigned getNumberOfNonSpills(SmallPtrSet& MIs, + unsigned Reg, int FrameIndex, bool& TwoAddr); + VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator Use, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock); + VNInfo* PerformPHIConstructionFallBack(MachineBasicBlock::iterator Use, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock); +}; +} // end anonymous namespace + +char PreAllocSplitting::ID = 0; + +INITIALIZE_PASS_BEGIN(PreAllocSplitting, "pre-alloc-splitting", + "Pre-Register Allocation Live Interval Splitting", + false, false) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(LiveStacks) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(VirtRegMap) +INITIALIZE_PASS_END(PreAllocSplitting, "pre-alloc-splitting", + "Pre-Register Allocation Live Interval Splitting", + false, false) + +char &llvm::PreAllocSplittingID = PreAllocSplitting::ID; + +/// findSpillPoint - Find a gap as far away from the given MI that's suitable +/// for spilling the current live interval. The index must be before any +/// defs and uses of the live interval register in the mbb. Return begin() if +/// none is found. +MachineBasicBlock::iterator +PreAllocSplitting::findSpillPoint(MachineBasicBlock *MBB, MachineInstr *MI, + MachineInstr *DefMI, + SmallPtrSet &RefsInMBB) { + MachineBasicBlock::iterator Pt = MBB->begin(); + + MachineBasicBlock::iterator MII = MI; + MachineBasicBlock::iterator EndPt = DefMI + ? MachineBasicBlock::iterator(DefMI) : MBB->begin(); + + while (MII != EndPt && !RefsInMBB.count(MII) && + MII->getOpcode() != TRI->getCallFrameSetupOpcode()) + --MII; + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + + while (MII != EndPt && !RefsInMBB.count(MII)) { + // We can't insert the spill between the barrier (a call), and its + // corresponding call frame setup. + if (MII->getOpcode() == TRI->getCallFrameDestroyOpcode()) { + while (MII->getOpcode() != TRI->getCallFrameSetupOpcode()) { + --MII; + if (MII == EndPt) { + return Pt; + } + } + continue; + } else { + Pt = MII; + } + + if (RefsInMBB.count(MII)) + return Pt; + + + --MII; + } + + return Pt; +} + +/// findRestorePoint - Find a gap in the instruction index map that's suitable +/// for restoring the current live interval value. The index must be before any +/// uses of the live interval register in the mbb. Return end() if none is +/// found. +MachineBasicBlock::iterator +PreAllocSplitting::findRestorePoint(MachineBasicBlock *MBB, MachineInstr *MI, + SlotIndex LastIdx, + SmallPtrSet &RefsInMBB) { + // FIXME: Allow spill to be inserted to the beginning of the mbb. Update mbb + // begin index accordingly. + MachineBasicBlock::iterator Pt = MBB->end(); + MachineBasicBlock::iterator EndPt = MBB->getFirstTerminator(); + + // We start at the call, so walk forward until we find the call frame teardown + // since we can't insert restores before that. Bail if we encounter a use + // during this time. + MachineBasicBlock::iterator MII = MI; + if (MII == EndPt) return Pt; + + while (MII != EndPt && !RefsInMBB.count(MII) && + MII->getOpcode() != TRI->getCallFrameDestroyOpcode()) + ++MII; + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + ++MII; + + // FIXME: Limit the number of instructions to examine to reduce + // compile time? + while (MII != EndPt) { + SlotIndex Index = LIs->getInstructionIndex(MII); + if (Index > LastIdx) + break; + + // We can't insert a restore between the barrier (a call) and its + // corresponding call frame teardown. + if (MII->getOpcode() == TRI->getCallFrameSetupOpcode()) { + do { + if (MII == EndPt || RefsInMBB.count(MII)) return Pt; + ++MII; + } while (MII->getOpcode() != TRI->getCallFrameDestroyOpcode()); + } else { + Pt = MII; + } + + if (RefsInMBB.count(MII)) + return Pt; + + ++MII; + } + + return Pt; +} + +/// CreateSpillStackSlot - Create a stack slot for the live interval being +/// split. If the live interval was previously split, just reuse the same +/// slot. +int PreAllocSplitting::CreateSpillStackSlot(unsigned Reg, + const TargetRegisterClass *RC) { + int SS; + DenseMap::iterator I = IntervalSSMap.find(Reg); + if (I != IntervalSSMap.end()) { + SS = I->second; + } else { + SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); + IntervalSSMap[Reg] = SS; + } + + // Create live interval for stack slot. + CurrSLI = &LSs->getOrCreateInterval(SS, RC); + if (CurrSLI->hasAtLeastOneValue()) + CurrSValNo = CurrSLI->getValNumInfo(0); + else + CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, + LSs->getVNInfoAllocator()); + return SS; +} + +/// IsAvailableInStack - Return true if register is available in a split stack +/// slot at the specified index. +bool +PreAllocSplitting::IsAvailableInStack(MachineBasicBlock *DefMBB, + unsigned Reg, SlotIndex DefIndex, + SlotIndex RestoreIndex, + SlotIndex &SpillIndex, + int& SS) const { + if (!DefMBB) + return false; + + DenseMap::const_iterator I = IntervalSSMap.find(Reg); + if (I == IntervalSSMap.end()) + return false; + DenseMap::const_iterator + II = Def2SpillMap.find(DefIndex); + if (II == Def2SpillMap.end()) + return false; + + // If last spill of def is in the same mbb as barrier mbb (where restore will + // be), make sure it's not below the intended restore index. + // FIXME: Undo the previous spill? + assert(LIs->getMBBFromIndex(II->second) == DefMBB); + if (DefMBB == BarrierMBB && II->second >= RestoreIndex) + return false; + + SS = I->second; + SpillIndex = II->second; + return true; +} + +/// UpdateSpillSlotInterval - Given the specified val# of the register live +/// interval being split, and the spill and restore indicies, update the live +/// interval of the spill stack slot. +void +PreAllocSplitting::UpdateSpillSlotInterval(VNInfo *ValNo, SlotIndex SpillIndex, + SlotIndex RestoreIndex) { + assert(LIs->getMBBFromIndex(RestoreIndex) == BarrierMBB && + "Expect restore in the barrier mbb"); + + MachineBasicBlock *MBB = LIs->getMBBFromIndex(SpillIndex); + if (MBB == BarrierMBB) { + // Intra-block spill + restore. We are done. + LiveRange SLR(SpillIndex, RestoreIndex, CurrSValNo); + CurrSLI->addRange(SLR); + return; + } + + SmallPtrSet Processed; + SlotIndex EndIdx = LIs->getMBBEndIdx(MBB); + LiveRange SLR(SpillIndex, EndIdx, CurrSValNo); + CurrSLI->addRange(SLR); + Processed.insert(MBB); + + // Start from the spill mbb, figure out the extend of the spill slot's + // live interval. + SmallVector WorkList; + const LiveRange *LR = CurrLI->getLiveRangeContaining(SpillIndex); + if (LR->end > EndIdx) + // If live range extend beyond end of mbb, add successors to work list. + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + + while (!WorkList.empty()) { + MachineBasicBlock *MBB = WorkList.back(); + WorkList.pop_back(); + if (Processed.count(MBB)) + continue; + SlotIndex Idx = LIs->getMBBStartIdx(MBB); + LR = CurrLI->getLiveRangeContaining(Idx); + if (LR && LR->valno == ValNo) { + EndIdx = LIs->getMBBEndIdx(MBB); + if (Idx <= RestoreIndex && RestoreIndex < EndIdx) { + // Spill slot live interval stops at the restore. + LiveRange SLR(Idx, RestoreIndex, CurrSValNo); + CurrSLI->addRange(SLR); + } else if (LR->end > EndIdx) { + // Live range extends beyond end of mbb, process successors. + LiveRange SLR(Idx, EndIdx.getNextIndex(), CurrSValNo); + CurrSLI->addRange(SLR); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + } else { + LiveRange SLR(Idx, LR->end, CurrSValNo); + CurrSLI->addRange(SLR); + } + Processed.insert(MBB); + } + } +} + +/// PerformPHIConstruction - From properly set up use and def lists, use a PHI +/// construction algorithm to compute the ranges and valnos for an interval. +VNInfo* +PreAllocSplitting::PerformPHIConstruction(MachineBasicBlock::iterator UseI, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock) { + // Return memoized result if it's available. + if (IsTopLevel && Visited.count(UseI) && NewVNs.count(UseI)) + return NewVNs[UseI]; + else if (!IsTopLevel && IsIntraBlock && NewVNs.count(UseI)) + return NewVNs[UseI]; + else if (!IsIntraBlock && LiveOut.count(MBB)) + return LiveOut[MBB]; + + // Check if our block contains any uses or defs. + bool ContainsDefs = Defs.count(MBB); + bool ContainsUses = Uses.count(MBB); + + VNInfo* RetVNI = 0; + + // Enumerate the cases of use/def contaning blocks. + if (!ContainsDefs && !ContainsUses) { + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + } else if (ContainsDefs && !ContainsUses) { + SmallPtrSet& BlockDefs = Defs[MBB]; + + // Search for the def in this block. If we don't find it before the + // instruction we care about, go to the fallback case. Note that that + // should never happen: this cannot be intrablock, so use should + // always be an end() iterator. + assert(UseI == MBB->end() && "No use marked in intrablock"); + + MachineBasicBlock::iterator Walker = UseI; + --Walker; + while (Walker != MBB->begin()) { + if (BlockDefs.count(Walker)) + break; + --Walker; + } + + // Once we've found it, extend its VNInfo to our instruction. + SlotIndex DefIndex = LIs->getInstructionIndex(Walker); + DefIndex = DefIndex.getDefIndex(); + SlotIndex EndIndex = LIs->getMBBEndIdx(MBB); + + RetVNI = NewVNs[Walker]; + LI->addRange(LiveRange(DefIndex, EndIndex, RetVNI)); + } else if (!ContainsDefs && ContainsUses) { + SmallPtrSet& BlockUses = Uses[MBB]; + + // Search for the use in this block that precedes the instruction we care + // about, going to the fallback case if we don't find it. + MachineBasicBlock::iterator Walker = UseI; + bool found = false; + while (Walker != MBB->begin()) { + --Walker; + if (BlockUses.count(Walker)) { + found = true; + break; + } + } + + if (!found) + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + + SlotIndex UseIndex = LIs->getInstructionIndex(Walker); + UseIndex = UseIndex.getUseIndex(); + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + + // Now, recursively phi construct the VNInfo for the use we found, + // and then extend it to include the instruction we care about + RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, false, true); + + LI->addRange(LiveRange(UseIndex, EndIndex, RetVNI)); + + // FIXME: Need to set kills properly for inter-block stuff. + } else if (ContainsDefs && ContainsUses) { + SmallPtrSet& BlockDefs = Defs[MBB]; + SmallPtrSet& BlockUses = Uses[MBB]; + + // This case is basically a merging of the two preceding case, with the + // special note that checking for defs must take precedence over checking + // for uses, because of two-address instructions. + MachineBasicBlock::iterator Walker = UseI; + bool foundDef = false; + bool foundUse = false; + while (Walker != MBB->begin()) { + --Walker; + if (BlockDefs.count(Walker)) { + foundDef = true; + break; + } else if (BlockUses.count(Walker)) { + foundUse = true; + break; + } + } + + if (!foundDef && !foundUse) + return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, + IsTopLevel, IsIntraBlock); + + SlotIndex StartIndex = LIs->getInstructionIndex(Walker); + StartIndex = foundDef ? StartIndex.getDefIndex() : StartIndex.getUseIndex(); + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + + if (foundDef) + RetVNI = NewVNs[Walker]; + else + RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses, + NewVNs, LiveOut, Phis, false, true); + + LI->addRange(LiveRange(StartIndex, EndIndex, RetVNI)); + } + + // Memoize results so we don't have to recompute them. + if (!IsIntraBlock) LiveOut[MBB] = RetVNI; + else { + if (!NewVNs.count(UseI)) + NewVNs[UseI] = RetVNI; + Visited.insert(UseI); + } + + return RetVNI; +} + +/// PerformPHIConstructionFallBack - PerformPHIConstruction fall back path. +/// +VNInfo* +PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator UseI, + MachineBasicBlock* MBB, LiveInterval* LI, + SmallPtrSet& Visited, + DenseMap >& Defs, + DenseMap >& Uses, + DenseMap& NewVNs, + DenseMap& LiveOut, + DenseMap& Phis, + bool IsTopLevel, bool IsIntraBlock) { + // NOTE: Because this is the fallback case from other cases, we do NOT + // assume that we are not intrablock here. + if (Phis.count(MBB)) return Phis[MBB]; + + SlotIndex StartIndex = LIs->getMBBStartIdx(MBB); + VNInfo *RetVNI = Phis[MBB] = + LI->getNextValue(SlotIndex(), /*FIXME*/ 0, + LIs->getVNInfoAllocator()); + + if (!IsIntraBlock) LiveOut[MBB] = RetVNI; + + // If there are no uses or defs between our starting point and the + // beginning of the block, then recursive perform phi construction + // on our predecessors. + DenseMap IncomingVNs; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI, + Visited, Defs, Uses, NewVNs, + LiveOut, Phis, false, false); + if (Incoming != 0) + IncomingVNs[*PI] = Incoming; + } + + if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill()) { + VNInfo* OldVN = RetVNI; + VNInfo* NewVN = IncomingVNs.begin()->second; + VNInfo* MergedVN = LI->MergeValueNumberInto(OldVN, NewVN); + if (MergedVN == OldVN) std::swap(OldVN, NewVN); + + for (DenseMap::iterator LOI = LiveOut.begin(), + LOE = LiveOut.end(); LOI != LOE; ++LOI) + if (LOI->second == OldVN) + LOI->second = MergedVN; + for (DenseMap::iterator NVI = NewVNs.begin(), + NVE = NewVNs.end(); NVI != NVE; ++NVI) + if (NVI->second == OldVN) + NVI->second = MergedVN; + for (DenseMap::iterator PI = Phis.begin(), + PE = Phis.end(); PI != PE; ++PI) + if (PI->second == OldVN) + PI->second = MergedVN; + RetVNI = MergedVN; + } else { + // Otherwise, merge the incoming VNInfos with a phi join. Create a new + // VNInfo to represent the joined value. + for (DenseMap::iterator I = + IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) { + I->second->setHasPHIKill(true); + } + } + + SlotIndex EndIndex; + if (IsIntraBlock) { + EndIndex = LIs->getInstructionIndex(UseI).getDefIndex(); + } else + EndIndex = LIs->getMBBEndIdx(MBB); + LI->addRange(LiveRange(StartIndex, EndIndex, RetVNI)); + + // Memoize results so we don't have to recompute them. + if (!IsIntraBlock) + LiveOut[MBB] = RetVNI; + else { + if (!NewVNs.count(UseI)) + NewVNs[UseI] = RetVNI; + Visited.insert(UseI); + } + + return RetVNI; +} + +/// ReconstructLiveInterval - Recompute a live interval from scratch. +void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) { + VNInfo::Allocator& Alloc = LIs->getVNInfoAllocator(); + + // Clear the old ranges and valnos; + LI->clear(); + + // Cache the uses and defs of the register + typedef DenseMap > RegMap; + RegMap Defs, Uses; + + // Keep track of the new VNs we're creating. + DenseMap NewVNs; + SmallPtrSet PhiVNs; + + // Cache defs, and create a new VNInfo for each def. + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), + DE = MRI->def_end(); DI != DE; ++DI) { + Defs[(*DI).getParent()].insert(&*DI); + + SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); + DefIdx = DefIdx.getDefIndex(); + + assert(!DI->isPHI() && "PHI instr in code during pre-alloc splitting."); + VNInfo* NewVN = LI->getNextValue(DefIdx, 0, Alloc); + + // If the def is a move, set the copy field. + if (DI->isCopyLike() && DI->getOperand(0).getReg() == LI->reg) + NewVN->setCopy(&*DI); + + NewVNs[&*DI] = NewVN; + } + + // Cache uses as a separate pass from actually processing them. + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), + UE = MRI->use_end(); UI != UE; ++UI) + Uses[(*UI).getParent()].insert(&*UI); + + // Now, actually process every use and use a phi construction algorithm + // to walk from it to its reaching definitions, building VNInfos along + // the way. + DenseMap LiveOut; + DenseMap Phis; + SmallPtrSet Visited; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), + UE = MRI->use_end(); UI != UE; ++UI) { + PerformPHIConstruction(&*UI, UI->getParent(), LI, Visited, Defs, + Uses, NewVNs, LiveOut, Phis, true, true); + } + + // Add ranges for dead defs + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg), + DE = MRI->def_end(); DI != DE; ++DI) { + SlotIndex DefIdx = LIs->getInstructionIndex(&*DI); + DefIdx = DefIdx.getDefIndex(); + + if (LI->liveAt(DefIdx)) continue; + + VNInfo* DeadVN = NewVNs[&*DI]; + LI->addRange(LiveRange(DefIdx, DefIdx.getNextSlot(), DeadVN)); + } +} + +/// RenumberValno - Split the given valno out into a new vreg, allowing it to +/// be allocated to a different register. This function creates a new vreg, +/// copies the valno and its live ranges over to the new vreg's interval, +/// removes them from the old interval, and rewrites all uses and defs of +/// the original reg to the new vreg within those ranges. +void PreAllocSplitting::RenumberValno(VNInfo* VN) { + SmallVector Stack; + SmallVector VNsToCopy; + Stack.push_back(VN); + + // Walk through and copy the valno we care about, and any other valnos + // that are two-address redefinitions of the one we care about. These + // will need to be rewritten as well. We also check for safety of the + // renumbering here, by making sure that none of the valno involved has + // phi kills. + while (!Stack.empty()) { + VNInfo* OldVN = Stack.back(); + Stack.pop_back(); + + // Bail out if we ever encounter a valno that has a PHI kill. We can't + // renumber these. + if (OldVN->hasPHIKill()) return; + + VNsToCopy.push_back(OldVN); + + // Locate two-address redefinitions + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(CurrLI->reg), + DE = MRI->def_end(); DI != DE; ++DI) { + if (!DI->isRegTiedToUseOperand(DI.getOperandNo())) continue; + SlotIndex DefIdx = LIs->getInstructionIndex(&*DI).getDefIndex(); + VNInfo* NextVN = CurrLI->findDefinedVNInfoForRegInt(DefIdx); + if (std::find(VNsToCopy.begin(), VNsToCopy.end(), NextVN) != + VNsToCopy.end()) + Stack.push_back(NextVN); + } + } + + // Create the new vreg + unsigned NewVReg = MRI->createVirtualRegister(MRI->getRegClass(CurrLI->reg)); + + // Create the new live interval + LiveInterval& NewLI = LIs->getOrCreateInterval(NewVReg); + + for (SmallVector::iterator OI = VNsToCopy.begin(), OE = + VNsToCopy.end(); OI != OE; ++OI) { + VNInfo* OldVN = *OI; + + // Copy the valno over + VNInfo* NewVN = NewLI.createValueCopy(OldVN, LIs->getVNInfoAllocator()); + NewLI.MergeValueInAsValue(*CurrLI, OldVN, NewVN); + + // Remove the valno from the old interval + CurrLI->removeValNo(OldVN); + } + + // Rewrite defs and uses. This is done in two stages to avoid invalidating + // the reg_iterator. + SmallVector, 8> OpsToChange; + + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand& MO = I.getOperand(); + SlotIndex InstrIdx = LIs->getInstructionIndex(&*I); + + if ((MO.isUse() && NewLI.liveAt(InstrIdx.getUseIndex())) || + (MO.isDef() && NewLI.liveAt(InstrIdx.getDefIndex()))) + OpsToChange.push_back(std::make_pair(&*I, I.getOperandNo())); + } + + for (SmallVector, 8>::iterator I = + OpsToChange.begin(), E = OpsToChange.end(); I != E; ++I) { + MachineInstr* Inst = I->first; + unsigned OpIdx = I->second; + MachineOperand& MO = Inst->getOperand(OpIdx); + MO.setReg(NewVReg); + } + + // Grow the VirtRegMap, since we've created a new vreg. + VRM->grow(); + + // The renumbered vreg shares a stack slot with the old register. + if (IntervalSSMap.count(CurrLI->reg)) + IntervalSSMap[NewVReg] = IntervalSSMap[CurrLI->reg]; + + ++NumRenumbers; +} + +bool PreAllocSplitting::Rematerialize(unsigned VReg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + SmallPtrSet& RefsInMBB) { + MachineBasicBlock& MBB = *RestorePt->getParent(); + + MachineBasicBlock::iterator KillPt = BarrierMBB->end(); + if (!DefMI || DefMI->getParent() == BarrierMBB) + KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); + else + KillPt = llvm::next(MachineBasicBlock::iterator(DefMI)); + + if (KillPt == DefMI->getParent()->end()) + return false; + + TII->reMaterialize(MBB, RestorePt, VReg, 0, DefMI, *TRI); + SlotIndex RematIdx = LIs->InsertMachineInstrInMaps(prior(RestorePt)); + + ReconstructLiveInterval(CurrLI); + RematIdx = RematIdx.getDefIndex(); + RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RematIdx)); + + ++NumSplits; + ++NumRemats; + return true; +} + +MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* DefMI, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int& SS, + SmallPtrSet& RefsInMBB) { + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) + return 0; + + MachineBasicBlock::iterator FoldPt = Barrier; + while (&*FoldPt != DefMI && FoldPt != MBB->begin() && + !RefsInMBB.count(FoldPt)) + --FoldPt; + + int OpIdx = FoldPt->findRegisterDefOperandIdx(vreg); + if (OpIdx == -1) + return 0; + + SmallVector Ops; + Ops.push_back(OpIdx); + + if (!TII->canFoldMemoryOperand(FoldPt, Ops)) + return 0; + + DenseMap::iterator I = IntervalSSMap.find(vreg); + if (I != IntervalSSMap.end()) { + SS = I->second; + } else { + SS = MFI->CreateSpillStackObject(RC->getSize(), RC->getAlignment()); + } + + MachineInstr* FMI = TII->foldMemoryOperand(FoldPt, Ops, SS); + + if (FMI) { + LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); + FoldPt->eraseFromParent(); + ++NumFolds; + + IntervalSSMap[vreg] = SS; + CurrSLI = &LSs->getOrCreateInterval(SS, RC); + if (CurrSLI->hasAtLeastOneValue()) + CurrSValNo = CurrSLI->getValNumInfo(0); + else + CurrSValNo = CurrSLI->getNextValue(SlotIndex(), 0, + LSs->getVNInfoAllocator()); + } + + return FMI; +} + +MachineInstr* PreAllocSplitting::FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB) { + if ((int)RestoreFoldLimit != -1 && RestoreFoldLimit == (int)NumRestoreFolds) + return 0; + + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) + return 0; + + // Can't fold a restore between a call stack setup and teardown. + MachineBasicBlock::iterator FoldPt = Barrier; + + // Advance from barrier to call frame teardown. + while (FoldPt != MBB->getFirstTerminator() && + FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { + if (RefsInMBB.count(FoldPt)) + return 0; + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + else + ++FoldPt; + + // Now find the restore point. + while (FoldPt != MBB->getFirstTerminator() && !RefsInMBB.count(FoldPt)) { + if (FoldPt->getOpcode() == TRI->getCallFrameSetupOpcode()) { + while (FoldPt != MBB->getFirstTerminator() && + FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { + if (RefsInMBB.count(FoldPt)) + return 0; + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + } + + ++FoldPt; + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + + int OpIdx = FoldPt->findRegisterUseOperandIdx(vreg, true); + if (OpIdx == -1) + return 0; + + SmallVector Ops; + Ops.push_back(OpIdx); + + if (!TII->canFoldMemoryOperand(FoldPt, Ops)) + return 0; + + MachineInstr* FMI = TII->foldMemoryOperand(FoldPt, Ops, SS); + + if (FMI) { + LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); + FoldPt->eraseFromParent(); + ++NumRestoreFolds; + } + + return FMI; +} + +/// SplitRegLiveInterval - Split (spill and restore) the given live interval +/// so it would not cross the barrier that's being processed. Shrink wrap +/// (minimize) the live interval to the last uses. +bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { + DEBUG(dbgs() << "Pre-alloc splitting " << LI->reg << " for " << *Barrier + << " result: "); + + CurrLI = LI; + + // Find live range where current interval cross the barrier. + LiveInterval::iterator LR = + CurrLI->FindLiveRangeContaining(BarrierIdx.getUseIndex()); + VNInfo *ValNo = LR->valno; + + assert(!ValNo->isUnused() && "Val# is defined by a dead def?"); + + MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def); + + // If this would create a new join point, do not split. + if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent())) { + DEBUG(dbgs() << "FAILED (would create a new join point).\n"); + return false; + } + + // Find all references in the barrier mbb. + SmallPtrSet RefsInMBB; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), + E = MRI->reg_end(); I != E; ++I) { + MachineInstr *RefMI = &*I; + if (RefMI->getParent() == BarrierMBB) + RefsInMBB.insert(RefMI); + } + + // Find a point to restore the value after the barrier. + MachineBasicBlock::iterator RestorePt = + findRestorePoint(BarrierMBB, Barrier, LR->end, RefsInMBB); + if (RestorePt == BarrierMBB->end()) { + DEBUG(dbgs() << "FAILED (could not find a suitable restore point).\n"); + return false; + } + + if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI)) + if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt, RefsInMBB)) { + DEBUG(dbgs() << "success (remat).\n"); + return true; + } + + // Add a spill either before the barrier or after the definition. + MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL; + const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg); + SlotIndex SpillIndex; + MachineInstr *SpillMI = NULL; + int SS = -1; + if (!DefMI) { + // If we don't know where the def is we must split just before the barrier. + if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier, + BarrierMBB, SS, RefsInMBB))) { + SpillIndex = LIs->getInstructionIndex(SpillMI); + } else { + MachineBasicBlock::iterator SpillPt = + findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB); + if (SpillPt == BarrierMBB->begin()) { + DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + // Add spill. + + SS = CreateSpillStackSlot(CurrLI->reg, RC); + TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC, + TRI); + SpillMI = prior(SpillPt); + SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); + } + } else if (!IsAvailableInStack(DefMBB, CurrLI->reg, ValNo->def, + LIs->getZeroIndex(), SpillIndex, SS)) { + // If it's already split, just restore the value. There is no need to spill + // the def again. + if (!DefMI) { + DEBUG(dbgs() << "FAILED (def is dead).\n"); + return false; // Def is dead. Do nothing. + } + + if ((SpillMI = FoldSpill(LI->reg, RC, DefMI, Barrier, + BarrierMBB, SS, RefsInMBB))) { + SpillIndex = LIs->getInstructionIndex(SpillMI); + } else { + // Check if it's possible to insert a spill after the def MI. + MachineBasicBlock::iterator SpillPt; + if (DefMBB == BarrierMBB) { + // Add spill after the def and the last use before the barrier. + SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI, + RefsInMBB); + if (SpillPt == DefMBB->begin()) { + DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + } else { + SpillPt = llvm::next(MachineBasicBlock::iterator(DefMI)); + if (SpillPt == DefMBB->end()) { + DEBUG(dbgs() << "FAILED (could not find a suitable spill point).\n"); + return false; // No gap to insert spill. + } + } + // Add spill. + SS = CreateSpillStackSlot(CurrLI->reg, RC); + TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, false, SS, RC, + TRI); + SpillMI = prior(SpillPt); + SpillIndex = LIs->InsertMachineInstrInMaps(SpillMI); + } + } + + // Remember def instruction index to spill index mapping. + if (DefMI && SpillMI) + Def2SpillMap[ValNo->def] = SpillIndex; + + // Add restore. + bool FoldedRestore = false; + SlotIndex RestoreIndex; + if (MachineInstr* LMI = FoldRestore(CurrLI->reg, RC, Barrier, + BarrierMBB, SS, RefsInMBB)) { + RestorePt = LMI; + RestoreIndex = LIs->getInstructionIndex(RestorePt); + FoldedRestore = true; + } else { + TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC, TRI); + MachineInstr *LoadMI = prior(RestorePt); + RestoreIndex = LIs->InsertMachineInstrInMaps(LoadMI); + } + + // Update spill stack slot live interval. + UpdateSpillSlotInterval(ValNo, SpillIndex.getUseIndex().getNextSlot(), + RestoreIndex.getDefIndex()); + + ReconstructLiveInterval(CurrLI); + + if (!FoldedRestore) { + SlotIndex RestoreIdx = LIs->getInstructionIndex(prior(RestorePt)); + RestoreIdx = RestoreIdx.getDefIndex(); + RenumberValno(CurrLI->findDefinedVNInfoForRegInt(RestoreIdx)); + } + + ++NumSplits; + DEBUG(dbgs() << "success.\n"); + return true; +} + +/// SplitRegLiveIntervals - Split all register live intervals that cross the +/// barrier that's being processed. +bool +PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs, + SmallPtrSet& Split) { + // First find all the virtual registers whose live intervals are intercepted + // by the current barrier. + SmallVector Intervals; + for (const TargetRegisterClass **RC = RCs; *RC; ++RC) { + // FIXME: If it's not safe to move any instruction that defines the barrier + // register class, then it means there are some special dependencies which + // codegen is not modelling. Ignore these barriers for now. + if (!TII->isSafeToMoveRegClassDefs(*RC)) + continue; + const std::vector &VRs = MRI->getRegClassVirtRegs(*RC); + for (unsigned i = 0, e = VRs.size(); i != e; ++i) { + unsigned Reg = VRs[i]; + if (!LIs->hasInterval(Reg)) + continue; + LiveInterval *LI = &LIs->getInterval(Reg); + if (LI->liveAt(BarrierIdx) && !Barrier->readsRegister(Reg)) + // Virtual register live interval is intercepted by the barrier. We + // should split and shrink wrap its interval if possible. + Intervals.push_back(LI); + } + } + + // Process the affected live intervals. + bool Change = false; + while (!Intervals.empty()) { + if (PreSplitLimit != -1 && (int)NumSplits == PreSplitLimit) + break; + LiveInterval *LI = Intervals.back(); + Intervals.pop_back(); + bool result = SplitRegLiveInterval(LI); + if (result) Split.insert(LI); + Change |= result; + } + + return Change; +} + +unsigned PreAllocSplitting::getNumberOfNonSpills( + SmallPtrSet& MIs, + unsigned Reg, int FrameIndex, + bool& FeedsTwoAddr) { + unsigned NonSpills = 0; + for (SmallPtrSet::iterator UI = MIs.begin(), UE = MIs.end(); + UI != UE; ++UI) { + int StoreFrameIndex; + unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + if (StoreVReg != Reg || StoreFrameIndex != FrameIndex) + ++NonSpills; + + int DefIdx = (*UI)->findRegisterDefOperandIdx(Reg); + if (DefIdx != -1 && (*UI)->isRegTiedToUseOperand(DefIdx)) + FeedsTwoAddr = true; + } + + return NonSpills; +} + +/// removeDeadSpills - After doing splitting, filter through all intervals we've +/// split, and see if any of the spills are unnecessary. If so, remove them. +bool PreAllocSplitting::removeDeadSpills(SmallPtrSet& split) { + bool changed = false; + + // Walk over all of the live intervals that were touched by the splitter, + // and see if we can do any DCE and/or folding. + for (SmallPtrSet::iterator LI = split.begin(), + LE = split.end(); LI != LE; ++LI) { + DenseMap > VNUseCount; + + // First, collect all the uses of the vreg, and sort them by their + // reaching definition (VNInfo). + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin((*LI)->reg), + UE = MRI->use_end(); UI != UE; ++UI) { + SlotIndex index = LIs->getInstructionIndex(&*UI); + index = index.getUseIndex(); + + const LiveRange* LR = (*LI)->getLiveRangeContaining(index); + VNUseCount[LR->valno].insert(&*UI); + } + + // Now, take the definitions (VNInfo's) one at a time and try to DCE + // and/or fold them away. + for (LiveInterval::vni_iterator VI = (*LI)->vni_begin(), + VE = (*LI)->vni_end(); VI != VE; ++VI) { + + if (DeadSplitLimit != -1 && (int)NumDeadSpills == DeadSplitLimit) + return changed; + + VNInfo* CurrVN = *VI; + + // We don't currently try to handle definitions with PHI kills, because + // it would involve processing more than one VNInfo at once. + if (CurrVN->hasPHIKill()) continue; + + // We also don't try to handle the results of PHI joins, since there's + // no defining instruction to analyze. + MachineInstr* DefMI = LIs->getInstructionFromIndex(CurrVN->def); + if (!DefMI || CurrVN->isUnused()) continue; + + // We're only interested in eliminating cruft introduced by the splitter, + // is of the form load-use or load-use-store. First, check that the + // definition is a load, and remember what stack slot we loaded it from. + int FrameIndex; + if (!TII->isLoadFromStackSlot(DefMI, FrameIndex)) continue; + + // If the definition has no uses at all, just DCE it. + if (VNUseCount[CurrVN].size() == 0) { + LIs->RemoveMachineInstrFromMaps(DefMI); + (*LI)->removeValNo(CurrVN); + DefMI->eraseFromParent(); + VNUseCount.erase(CurrVN); + ++NumDeadSpills; + changed = true; + continue; + } + + // Second, get the number of non-store uses of the definition, as well as + // a flag indicating whether it feeds into a later two-address definition. + bool FeedsTwoAddr = false; + unsigned NonSpillCount = getNumberOfNonSpills(VNUseCount[CurrVN], + (*LI)->reg, FrameIndex, + FeedsTwoAddr); + + // If there's one non-store use and it doesn't feed a two-addr, then + // this is a load-use-store case that we can try to fold. + if (NonSpillCount == 1 && !FeedsTwoAddr) { + // Start by finding the non-store use MachineInstr. + SmallPtrSet::iterator UI = VNUseCount[CurrVN].begin(); + int StoreFrameIndex; + unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + while (UI != VNUseCount[CurrVN].end() && + (StoreVReg == (*LI)->reg && StoreFrameIndex == FrameIndex)) { + ++UI; + if (UI != VNUseCount[CurrVN].end()) + StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex); + } + if (UI == VNUseCount[CurrVN].end()) continue; + + MachineInstr* use = *UI; + + // Attempt to fold it away! + int OpIdx = use->findRegisterUseOperandIdx((*LI)->reg, false); + if (OpIdx == -1) continue; + SmallVector Ops; + Ops.push_back(OpIdx); + if (!TII->canFoldMemoryOperand(use, Ops)) continue; + + MachineInstr* NewMI = TII->foldMemoryOperand(use, Ops, FrameIndex); + + if (!NewMI) continue; + + // Update relevant analyses. + LIs->RemoveMachineInstrFromMaps(DefMI); + LIs->ReplaceMachineInstrInMaps(use, NewMI); + (*LI)->removeValNo(CurrVN); + + DefMI->eraseFromParent(); + use->eraseFromParent(); + VNUseCount[CurrVN].erase(use); + + // Remove deleted instructions. Note that we need to remove them from + // the VNInfo->use map as well, just to be safe. + for (SmallPtrSet::iterator II = + VNUseCount[CurrVN].begin(), IE = VNUseCount[CurrVN].end(); + II != IE; ++II) { + for (DenseMap >::iterator + VNI = VNUseCount.begin(), VNE = VNUseCount.end(); VNI != VNE; + ++VNI) + if (VNI->first != CurrVN) + VNI->second.erase(*II); + LIs->RemoveMachineInstrFromMaps(*II); + (*II)->eraseFromParent(); + } + + VNUseCount.erase(CurrVN); + + for (DenseMap >::iterator + VI = VNUseCount.begin(), VE = VNUseCount.end(); VI != VE; ++VI) + if (VI->second.erase(use)) + VI->second.insert(NewMI); + + ++NumDeadSpills; + changed = true; + continue; + } + + // If there's more than one non-store instruction, we can't profitably + // fold it, so bail. + if (NonSpillCount) continue; + + // Otherwise, this is a load-store case, so DCE them. + for (SmallPtrSet::iterator UI = + VNUseCount[CurrVN].begin(), UE = VNUseCount[CurrVN].end(); + UI != UE; ++UI) { + LIs->RemoveMachineInstrFromMaps(*UI); + (*UI)->eraseFromParent(); + } + + VNUseCount.erase(CurrVN); + + LIs->RemoveMachineInstrFromMaps(DefMI); + (*LI)->removeValNo(CurrVN); + DefMI->eraseFromParent(); + ++NumDeadSpills; + changed = true; + } + } + + return changed; +} + +bool PreAllocSplitting::createsNewJoin(LiveRange* LR, + MachineBasicBlock* DefMBB, + MachineBasicBlock* BarrierMBB) { + if (DefMBB == BarrierMBB) + return false; + + if (LR->valno->hasPHIKill()) + return false; + + SlotIndex MBBEnd = LIs->getMBBEndIdx(BarrierMBB); + if (LR->end < MBBEnd) + return false; + + MachineLoopInfo& MLI = getAnalysis(); + if (MLI.getLoopFor(DefMBB) != MLI.getLoopFor(BarrierMBB)) + return true; + + MachineDominatorTree& MDT = getAnalysis(); + SmallPtrSet Visited; + typedef std::pair ItPair; + SmallVector Stack; + Stack.push_back(std::make_pair(BarrierMBB, BarrierMBB->succ_begin())); + + while (!Stack.empty()) { + ItPair P = Stack.back(); + Stack.pop_back(); + + MachineBasicBlock* PredMBB = P.first; + MachineBasicBlock::succ_iterator S = P.second; + + if (S == PredMBB->succ_end()) + continue; + else if (Visited.count(*S)) { + Stack.push_back(std::make_pair(PredMBB, ++S)); + continue; + } else + Stack.push_back(std::make_pair(PredMBB, S+1)); + + MachineBasicBlock* MBB = *S; + Visited.insert(MBB); + + if (MBB == BarrierMBB) + return true; + + MachineDomTreeNode* DefMDTN = MDT.getNode(DefMBB); + MachineDomTreeNode* BarrierMDTN = MDT.getNode(BarrierMBB); + MachineDomTreeNode* MDTN = MDT.getNode(MBB)->getIDom(); + while (MDTN) { + if (MDTN == DefMDTN) + return true; + else if (MDTN == BarrierMDTN) + break; + MDTN = MDTN->getIDom(); + } + + MBBEnd = LIs->getMBBEndIdx(MBB); + if (LR->end > MBBEnd) + Stack.push_back(std::make_pair(MBB, MBB->succ_begin())); + } + + return false; +} + + +bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { + CurrMF = &MF; + TM = &MF.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + SIs = &getAnalysis(); + LIs = &getAnalysis(); + LSs = &getAnalysis(); + VRM = &getAnalysis(); + + bool MadeChange = false; + + // Make sure blocks are numbered in order. + MF.RenumberBlocks(); + + MachineBasicBlock *Entry = MF.begin(); + SmallPtrSet Visited; + + SmallPtrSet Split; + + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + BarrierMBB = *DFI; + for (MachineBasicBlock::iterator I = BarrierMBB->begin(), + E = BarrierMBB->end(); I != E; ++I) { + Barrier = &*I; + const TargetRegisterClass **BarrierRCs = + Barrier->getDesc().getRegClassBarriers(); + if (!BarrierRCs) + continue; + BarrierIdx = LIs->getInstructionIndex(Barrier); + MadeChange |= SplitRegLiveIntervals(BarrierRCs, Split); + } + } + + MadeChange |= removeDeadSpills(Split); + + return MadeChange; +} diff --git a/final/lib/CodeGen/ProcessImplicitDefs.cpp b/final/lib/CodeGen/ProcessImplicitDefs.cpp new file mode 100644 index 00000000000..9cd9941e56b --- /dev/null +++ b/final/lib/CodeGen/ProcessImplicitDefs.cpp @@ -0,0 +1,298 @@ +//===---------------------- ProcessImplicitDefs.cpp -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "processimplicitdefs" + +#include "llvm/CodeGen/ProcessImplicitDefs.h" + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + + +using namespace llvm; + +char ProcessImplicitDefs::ID = 0; +INITIALIZE_PASS_BEGIN(ProcessImplicitDefs, "processimpdefs", + "Process Implicit Definitions", false, false) +INITIALIZE_PASS_DEPENDENCY(LiveVariables) +INITIALIZE_PASS_END(ProcessImplicitDefs, "processimpdefs", + "Process Implicit Definitions", false, false) + +void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + AU.addPreservedID(TwoAddressInstructionPassID); + AU.addPreservedID(PHIEliminationID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool +ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI, + unsigned Reg, unsigned OpIdx, + const TargetInstrInfo *tii_, + SmallSet &ImpDefRegs) { + switch(OpIdx) { + case 1: + return MI->isCopy() && (MI->getOperand(0).getSubReg() == 0 || + ImpDefRegs.count(MI->getOperand(0).getReg())); + case 2: + return MI->isSubregToReg() && (MI->getOperand(0).getSubReg() == 0 || + ImpDefRegs.count(MI->getOperand(0).getReg())); + default: return false; + } +} + +static bool isUndefCopy(MachineInstr *MI, unsigned Reg, + const TargetInstrInfo *tii_, + SmallSet &ImpDefRegs) { + if (MI->isCopy()) { + MachineOperand &MO0 = MI->getOperand(0); + MachineOperand &MO1 = MI->getOperand(1); + if (MO1.getReg() != Reg) + return false; + if (!MO0.getSubReg() || ImpDefRegs.count(MO0.getReg())) + return true; + return false; + } + return false; +} + +/// processImplicitDefs - Process IMPLICIT_DEF instructions and make sure +/// there is one implicit_def for each use. Add isUndef marker to +/// implicit_def defs and their uses. +bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { + + DEBUG(dbgs() << "********** PROCESS IMPLICIT DEFS **********\n" + << "********** Function: " + << ((Value*)fn.getFunction())->getName() << '\n'); + + bool Changed = false; + + const TargetInstrInfo *tii_ = fn.getTarget().getInstrInfo(); + const TargetRegisterInfo *tri_ = fn.getTarget().getRegisterInfo(); + MachineRegisterInfo *mri_ = &fn.getRegInfo(); + + LiveVariables *lv_ = &getAnalysis(); + + SmallSet ImpDefRegs; + SmallVector ImpDefMIs; + SmallVector RUses; + SmallPtrSet Visited; + SmallPtrSet ModInsts; + + MachineBasicBlock *Entry = fn.begin(); + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ) { + MachineInstr *MI = &*I; + ++I; + if (MI->isImplicitDef()) { + if (MI->getOperand(0).getSubReg()) + continue; + unsigned Reg = MI->getOperand(0).getReg(); + ImpDefRegs.insert(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + for (const unsigned *SS = tri_->getSubRegisters(Reg); *SS; ++SS) + ImpDefRegs.insert(*SS); + } + ImpDefMIs.push_back(MI); + continue; + } + + // Eliminate %reg1032:sub = COPY undef. + if (MI->isCopy() && MI->getOperand(0).getSubReg()) { + MachineOperand &MO = MI->getOperand(1); + if (MO.isUndef() || ImpDefRegs.count(MO.getReg())) { + if (MO.isKill()) { + LiveVariables::VarInfo& vi = lv_->getVarInfo(MO.getReg()); + vi.removeKill(MI); + } + MI->eraseFromParent(); + Changed = true; + continue; + } + } + + bool ChangedToImpDef = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || (MO.isDef() && !MO.getSubReg()) || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (!ImpDefRegs.count(Reg)) + continue; + // Use is a copy, just turn it into an implicit_def. + if (CanTurnIntoImplicitDef(MI, Reg, i, tii_, ImpDefRegs)) { + bool isKill = MO.isKill(); + MI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); + for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) + MI->RemoveOperand(j); + if (isKill) { + ImpDefRegs.erase(Reg); + LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + vi.removeKill(MI); + } + ChangedToImpDef = true; + Changed = true; + break; + } + + Changed = true; + MO.setIsUndef(); + // This is a partial register redef of an implicit def. + // Make sure the whole register is defined by the instruction. + if (MO.isDef()) { + MI->addRegisterDefined(Reg); + continue; + } + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) { + // Make sure other uses of + for (unsigned j = i+1; j != e; ++j) { + MachineOperand &MOJ = MI->getOperand(j); + if (MOJ.isReg() && MOJ.isUse() && MOJ.getReg() == Reg) + MOJ.setIsUndef(); + } + ImpDefRegs.erase(Reg); + } + } + + if (ChangedToImpDef) { + // Backtrack to process this new implicit_def. + --I; + } else { + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + ImpDefRegs.erase(MO.getReg()); + } + } + } + + // Any outstanding liveout implicit_def's? + for (unsigned i = 0, e = ImpDefMIs.size(); i != e; ++i) { + MachineInstr *MI = ImpDefMIs[i]; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg) || + !ImpDefRegs.count(Reg)) { + // Delete all "local" implicit_def's. That include those which define + // physical registers since they cannot be liveout. + MI->eraseFromParent(); + Changed = true; + continue; + } + + // If there are multiple defs of the same register and at least one + // is not an implicit_def, do not insert implicit_def's before the + // uses. + bool Skip = false; + SmallVector DeadImpDefs; + for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg), + DE = mri_->def_end(); DI != DE; ++DI) { + MachineInstr *DeadImpDef = &*DI; + if (!DeadImpDef->isImplicitDef()) { + Skip = true; + break; + } + DeadImpDefs.push_back(DeadImpDef); + } + if (Skip) + continue; + + // The only implicit_def which we want to keep are those that are live + // out of its block. + for (unsigned j = 0, ee = DeadImpDefs.size(); j != ee; ++j) + DeadImpDefs[j]->eraseFromParent(); + Changed = true; + + // Process each use instruction once. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), + UE = mri_->use_end(); UI != UE; ++UI) { + if (UI.getOperand().isUndef()) + continue; + MachineInstr *RMI = &*UI; + if (ModInsts.insert(RMI)) + RUses.push_back(RMI); + } + + for (unsigned i = 0, e = RUses.size(); i != e; ++i) { + MachineInstr *RMI = RUses[i]; + + // Turn a copy use into an implicit_def. + if (isUndefCopy(RMI, Reg, tii_, ImpDefRegs)) { + RMI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF)); + + bool isKill = false; + SmallVector Ops; + for (unsigned j = 0, ee = RMI->getNumOperands(); j != ee; ++j) { + MachineOperand &RRMO = RMI->getOperand(j); + if (RRMO.isReg() && RRMO.getReg() == Reg) { + Ops.push_back(j); + if (RRMO.isKill()) + isKill = true; + } + } + // Leave the other operands along. + for (unsigned j = 0, ee = Ops.size(); j != ee; ++j) { + unsigned OpIdx = Ops[j]; + RMI->RemoveOperand(OpIdx-j); + } + + // Update LiveVariables varinfo if the instruction is a kill. + if (isKill) { + LiveVariables::VarInfo& vi = lv_->getVarInfo(Reg); + vi.removeKill(RMI); + } + continue; + } + + // Replace Reg with a new vreg that's marked implicit. + const TargetRegisterClass* RC = mri_->getRegClass(Reg); + unsigned NewVReg = mri_->createVirtualRegister(RC); + bool isKill = true; + for (unsigned j = 0, ee = RMI->getNumOperands(); j != ee; ++j) { + MachineOperand &RRMO = RMI->getOperand(j); + if (RRMO.isReg() && RRMO.getReg() == Reg) { + RRMO.setReg(NewVReg); + RRMO.setIsUndef(); + if (isKill) { + // Only the first operand of NewVReg is marked kill. + RRMO.setIsKill(); + isKill = false; + } + } + } + } + RUses.clear(); + ModInsts.clear(); + } + ImpDefRegs.clear(); + ImpDefMIs.clear(); + } + + return Changed; +} + diff --git a/final/lib/CodeGen/PrologEpilogInserter.cpp b/final/lib/CodeGen/PrologEpilogInserter.cpp new file mode 100644 index 00000000000..92e25e150f5 --- /dev/null +++ b/final/lib/CodeGen/PrologEpilogInserter.cpp @@ -0,0 +1,850 @@ +//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is responsible for finalizing the functions frame layout, saving +// callee saved registers, and for emitting prolog & epilog code for the +// function. +// +// This pass must be run after register allocation. After this pass is +// executed, it is illegal to construct MO_FrameIndex operands. +// +// This pass provides an optional shrink wrapping variant of prolog/epilog +// insertion, enabled via --shrink-wrap. See ShrinkWrapping.cpp. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pei" +#include "PrologEpilogInserter.h" +#include "llvm/InlineAsm.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include + +using namespace llvm; + +char PEI::ID = 0; + +INITIALIZE_PASS_BEGIN(PEI, "prologepilog", + "Prologue/Epilogue Insertion", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_END(PEI, "prologepilog", + "Prologue/Epilogue Insertion", false, false) + +STATISTIC(NumVirtualFrameRegs, "Number of virtual frame regs encountered"); +STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); + +/// createPrologEpilogCodeInserter - This function returns a pass that inserts +/// prolog and epilog code, and eliminates abstract frame references. +/// +FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); } + +/// runOnMachineFunction - Insert prolog/epilog code and replace abstract +/// frame indexes with appropriate references. +/// +bool PEI::runOnMachineFunction(MachineFunction &Fn) { + const Function* F = Fn.getFunction(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); + + RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : NULL; + FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); + + // Calculate the MaxCallFrameSize and AdjustsStack variables for the + // function's frame information. Also eliminates call frame pseudo + // instructions. + calculateCallsInformation(Fn); + + // Allow the target machine to make some adjustments to the function + // e.g. UsedPhysRegs before calculateCalleeSavedRegisters. + TFI->processFunctionBeforeCalleeSavedScan(Fn, RS); + + // Scan the function for modified callee saved registers and insert spill code + // for any callee saved registers that are modified. + calculateCalleeSavedRegisters(Fn); + + // Determine placement of CSR spill/restore code: + // - With shrink wrapping, place spills and restores to tightly + // enclose regions in the Machine CFG of the function where + // they are used. + // - Without shink wrapping (default), place all spills in the + // entry block, all restores in return blocks. + placeCSRSpillsAndRestores(Fn); + + // Add the code to save and restore the callee saved registers + if (!F->hasFnAttr(Attribute::Naked)) + insertCSRSpillsAndRestores(Fn); + + // Allow the target machine to make final modifications to the function + // before the frame layout is finalized. + TFI->processFunctionBeforeFrameFinalized(Fn); + + // Calculate actual frame offsets for all abstract stack objects... + calculateFrameObjectOffsets(Fn); + + // Add prolog and epilog code to the function. This function is required + // to align the stack frame as necessary for any stack variables or + // called functions. Because of this, calculateCalleeSavedRegisters() + // must be called before this function in order to set the AdjustsStack + // and MaxCallFrameSize variables. + if (!F->hasFnAttr(Attribute::Naked)) + insertPrologEpilogCode(Fn); + + // Replace all MO_FrameIndex operands with physical register references + // and actual offsets. + // + replaceFrameIndices(Fn); + + // If register scavenging is needed, as we've enabled doing it as a + // post-pass, scavenge the virtual registers that frame index elimiation + // inserted. + if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) + scavengeFrameVirtualRegs(Fn); + + delete RS; + clearAllSets(); + return true; +} + +#if 0 +void PEI::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + if (ShrinkWrapping || ShrinkWrapFunc != "") { + AU.addRequired(); + AU.addRequired(); + } + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} +#endif + +/// calculateCallsInformation - Calculate the MaxCallFrameSize and AdjustsStack +/// variables for the function's frame information and eliminate call frame +/// pseudo instructions. +void PEI::calculateCallsInformation(MachineFunction &Fn) { + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); + MachineFrameInfo *MFI = Fn.getFrameInfo(); + + unsigned MaxCallFrameSize = 0; + bool AdjustsStack = MFI->adjustsStack(); + + // Get the function call frame set-up and tear-down instruction opcode + int FrameSetupOpcode = RegInfo->getCallFrameSetupOpcode(); + int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode(); + + // Early exit for targets which have no call frame setup/destroy pseudo + // instructions. + if (FrameSetupOpcode == -1 && FrameDestroyOpcode == -1) + return; + + std::vector FrameSDOps; + for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { + assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo" + " instructions should have a single immediate argument!"); + unsigned Size = I->getOperand(0).getImm(); + if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; + AdjustsStack = true; + FrameSDOps.push_back(I); + } else if (I->isInlineAsm()) { + // Some inline asm's need a stack frame, as indicated by operand 1. + unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_IsAlignStack) + AdjustsStack = true; + } + + MFI->setAdjustsStack(AdjustsStack); + MFI->setMaxCallFrameSize(MaxCallFrameSize); + + for (std::vector::iterator + i = FrameSDOps.begin(), e = FrameSDOps.end(); i != e; ++i) { + MachineBasicBlock::iterator I = *i; + + // If call frames are not being included as part of the stack frame, and + // the target doesn't indicate otherwise, remove the call frame pseudos + // here. The sub/add sp instruction pairs are still inserted, but we don't + // need to track the SP adjustment for frame index elimination. + if (TFI->canSimplifyCallFramePseudos(Fn)) + RegInfo->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I); + } +} + + +/// calculateCalleeSavedRegisters - Scan the function for modified callee saved +/// registers. +void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); + MachineFrameInfo *MFI = Fn.getFrameInfo(); + + // Get the callee saved register list... + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn); + + // These are used to keep track the callee-save area. Initialize them. + MinCSFrameIndex = INT_MAX; + MaxCSFrameIndex = 0; + + // Early exit for targets which have no callee saved registers. + if (CSRegs == 0 || CSRegs[0] == 0) + return; + + // In Naked functions we aren't going to save any registers. + if (Fn.getFunction()->hasFnAttr(Attribute::Naked)) + return; + + std::vector CSI; + for (unsigned i = 0; CSRegs[i]; ++i) { + unsigned Reg = CSRegs[i]; + if (Fn.getRegInfo().isPhysRegUsed(Reg)) { + // If the reg is modified, save it! + CSI.push_back(CalleeSavedInfo(Reg)); + } else { + for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); + *AliasSet; ++AliasSet) { // Check alias registers too. + if (Fn.getRegInfo().isPhysRegUsed(*AliasSet)) { + CSI.push_back(CalleeSavedInfo(Reg)); + break; + } + } + } + } + + if (CSI.empty()) + return; // Early exit if no callee saved registers are modified! + + unsigned NumFixedSpillSlots; + const TargetFrameLowering::SpillSlot *FixedSpillSlots = + TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); + + // Now that we know which registers need to be saved and restored, allocate + // stack slots for them. + for (std::vector::iterator + I = CSI.begin(), E = CSI.end(); I != E; ++I) { + unsigned Reg = I->getReg(); + const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); + + int FrameIdx; + if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) { + I->setFrameIdx(FrameIdx); + continue; + } + + // Check to see if this physreg must be spilled to a particular stack slot + // on this target. + const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; + while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots && + FixedSlot->Reg != Reg) + ++FixedSlot; + + if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { + // Nope, just spill it anywhere convenient. + unsigned Align = RC->getAlignment(); + unsigned StackAlign = TFI->getStackAlignment(); + + // We may not be able to satisfy the desired alignment specification of + // the TargetRegisterClass if the stack alignment is smaller. Use the + // min. + Align = std::min(Align, StackAlign); + FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); + if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; + if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; + } else { + // Spill it to the stack where we must. + FrameIdx = MFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, true); + } + + I->setFrameIdx(FrameIdx); + } + + MFI->setCalleeSavedInfo(CSI); +} + +/// insertCSRSpillsAndRestores - Insert spill and restore code for +/// callee saved registers used in the function, handling shrink wrapping. +/// +void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { + // Get callee saved register information. + MachineFrameInfo *MFI = Fn.getFrameInfo(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + + MFI->setCalleeSavedInfoValid(true); + + // Early exit if no callee saved registers are modified! + if (CSI.empty()) + return; + + const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); + const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + MachineBasicBlock::iterator I; + + if (! ShrinkWrapThisFunction) { + // Spill using target interface. + I = EntryBlock->begin(); + if (!TFI->spillCalleeSavedRegisters(*EntryBlock, I, CSI, TRI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + // Add the callee-saved register as live-in. + // It's killed at the spill. + EntryBlock->addLiveIn(CSI[i].getReg()); + + // Insert the spill to the stack frame. + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(*EntryBlock, I, Reg, true, + CSI[i].getFrameIdx(), RC, TRI); + } + } + + // Restore using target interface. + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) { + MachineBasicBlock* MBB = ReturnBlocks[ri]; + I = MBB->end(); --I; + + // Skip over all terminator instructions, which are part of the return + // sequence. + MachineBasicBlock::iterator I2 = I; + while (I2 != MBB->begin() && (--I2)->getDesc().isTerminator()) + I = I2; + + bool AtStart = I == MBB->begin(); + MachineBasicBlock::iterator BeforeI = I; + if (!AtStart) + --BeforeI; + + // Restore all registers immediately before the return and any + // terminators that preceed it. + if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(*MBB, I, Reg, + CSI[i].getFrameIdx(), + RC, TRI); + assert(I != MBB->begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + I = MBB->begin(); + else { + I = BeforeI; + ++I; + } + } + } + } + return; + } + + // Insert spills. + std::vector blockCSI; + for (CSRegBlockMap::iterator BI = CSRSave.begin(), + BE = CSRSave.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet save = BI->second; + + if (save.empty()) + continue; + + blockCSI.clear(); + for (CSRegSet::iterator RI = save.begin(), + RE = save.end(); RI != RE; ++RI) { + blockCSI.push_back(CSI[*RI]); + } + assert(blockCSI.size() > 0 && + "Could not collect callee saved register info"); + + I = MBB->begin(); + + // When shrink wrapping, use stack slot stores/loads. + for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { + // Add the callee-saved register as live-in. + // It's killed at the spill. + MBB->addLiveIn(blockCSI[i].getReg()); + + // Insert the spill to the stack frame. + unsigned Reg = blockCSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(*MBB, I, Reg, + true, + blockCSI[i].getFrameIdx(), + RC, TRI); + } + } + + for (CSRegBlockMap::iterator BI = CSRRestore.begin(), + BE = CSRRestore.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet restore = BI->second; + + if (restore.empty()) + continue; + + blockCSI.clear(); + for (CSRegSet::iterator RI = restore.begin(), + RE = restore.end(); RI != RE; ++RI) { + blockCSI.push_back(CSI[*RI]); + } + assert(blockCSI.size() > 0 && + "Could not find callee saved register info"); + + // If MBB is empty and needs restores, insert at the _beginning_. + if (MBB->empty()) { + I = MBB->begin(); + } else { + I = MBB->end(); + --I; + + // Skip over all terminator instructions, which are part of the + // return sequence. + if (! I->getDesc().isTerminator()) { + ++I; + } else { + MachineBasicBlock::iterator I2 = I; + while (I2 != MBB->begin() && (--I2)->getDesc().isTerminator()) + I = I2; + } + } + + bool AtStart = I == MBB->begin(); + MachineBasicBlock::iterator BeforeI = I; + if (!AtStart) + --BeforeI; + + // Restore all registers immediately before the return and any + // terminators that preceed it. + for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { + unsigned Reg = blockCSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(*MBB, I, Reg, + blockCSI[i].getFrameIdx(), + RC, TRI); + assert(I != MBB->begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + I = MBB->begin(); + else { + I = BeforeI; + ++I; + } + } + } +} + +/// AdjustStackOffset - Helper function used to adjust the stack frame offset. +static inline void +AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, + bool StackGrowsDown, int64_t &Offset, + unsigned &MaxAlign) { + // If the stack grows down, add the object size to find the lowest address. + if (StackGrowsDown) + Offset += MFI->getObjectSize(FrameIdx); + + unsigned Align = MFI->getObjectAlignment(FrameIdx); + + // If the alignment of this object is greater than that of the stack, then + // increase the stack alignment to match. + MaxAlign = std::max(MaxAlign, Align); + + // Adjust to alignment boundary. + Offset = (Offset + Align - 1) / Align * Align; + + if (StackGrowsDown) { + DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n"); + MFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset + } else { + DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n"); + MFI->setObjectOffset(FrameIdx, Offset); + Offset += MFI->getObjectSize(FrameIdx); + } +} + +/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the +/// abstract stack objects. +/// +void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { + const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); + + bool StackGrowsDown = + TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; + + // Loop over all of the stack objects, assigning sequential addresses... + MachineFrameInfo *MFI = Fn.getFrameInfo(); + + // Start at the beginning of the local area. + // The Offset is the distance from the stack top in the direction + // of stack growth -- so it's always nonnegative. + int LocalAreaOffset = TFI.getOffsetOfLocalArea(); + if (StackGrowsDown) + LocalAreaOffset = -LocalAreaOffset; + assert(LocalAreaOffset >= 0 + && "Local area offset should be in direction of stack growth"); + int64_t Offset = LocalAreaOffset; + + // If there are fixed sized objects that are preallocated in the local area, + // non-fixed objects can't be allocated right at the start of local area. + // We currently don't support filling in holes in between fixed sized + // objects, so we adjust 'Offset' to point to the end of last fixed sized + // preallocated object. + for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) { + int64_t FixedOff; + if (StackGrowsDown) { + // The maximum distance from the stack pointer is at lower address of + // the object -- which is given by offset. For down growing stack + // the offset is negative, so we negate the offset to get the distance. + FixedOff = -MFI->getObjectOffset(i); + } else { + // The maximum distance from the start pointer is at the upper + // address of the object. + FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i); + } + if (FixedOff > Offset) Offset = FixedOff; + } + + // First assign frame offsets to stack objects that are used to spill + // callee saved registers. + if (StackGrowsDown) { + for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) { + // If the stack grows down, we need to add the size to find the lowest + // address of the object. + Offset += MFI->getObjectSize(i); + + unsigned Align = MFI->getObjectAlignment(i); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + + MFI->setObjectOffset(i, -Offset); // Set the computed offset + } + } else { + int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; + for (int i = MaxCSFI; i >= MinCSFI ; --i) { + unsigned Align = MFI->getObjectAlignment(i); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + + MFI->setObjectOffset(i, Offset); + Offset += MFI->getObjectSize(i); + } + } + + unsigned MaxAlign = MFI->getMaxAlignment(); + + // Make sure the special register scavenging spill slot is closest to the + // frame pointer if a frame pointer is required. + const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); + if (RS && TFI.hasFP(Fn) && RegInfo->useFPForScavengingIndex(Fn) && + !RegInfo->needsStackRealignment(Fn)) { + int SFI = RS->getScavengingFrameIndex(); + if (SFI >= 0) + AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign); + } + + // FIXME: Once this is working, then enable flag will change to a target + // check for whether the frame is large enough to want to use virtual + // frame index registers. Functions which don't want/need this optimization + // will continue to use the existing code path. + if (MFI->getUseLocalStackAllocationBlock()) { + unsigned Align = MFI->getLocalFrameMaxAlign(); + + // Adjust to alignment boundary. + Offset = (Offset + Align - 1) / Align * Align; + + DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); + + // Resolve offsets for objects in the local block. + for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { + std::pair Entry = MFI->getLocalFrameObjectMap(i); + int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; + DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << + FIOffset << "]\n"); + MFI->setObjectOffset(Entry.first, FIOffset); + } + // Allocate the local block + Offset += MFI->getLocalFrameSize(); + + MaxAlign = std::max(Align, MaxAlign); + } + + // Make sure that the stack protector comes before the local variables on the + // stack. + SmallSet LargeStackObjs; + if (MFI->getStackProtectorIndex() >= 0) { + AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown, + Offset, MaxAlign); + + // Assign large stack objects first. + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isObjectPreAllocated(i) && + MFI->getUseLocalStackAllocationBlock()) + continue; + if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) + continue; + if (RS && (int)i == RS->getScavengingFrameIndex()) + continue; + if (MFI->isDeadObjectIndex(i)) + continue; + if (MFI->getStackProtectorIndex() == (int)i) + continue; + if (!MFI->MayNeedStackProtector(i)) + continue; + + AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign); + LargeStackObjs.insert(i); + } + } + + // Then assign frame offsets to stack objects that are not used to spill + // callee saved registers. + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isObjectPreAllocated(i) && + MFI->getUseLocalStackAllocationBlock()) + continue; + if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) + continue; + if (RS && (int)i == RS->getScavengingFrameIndex()) + continue; + if (MFI->isDeadObjectIndex(i)) + continue; + if (MFI->getStackProtectorIndex() == (int)i) + continue; + if (LargeStackObjs.count(i)) + continue; + + AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign); + } + + // Make sure the special register scavenging spill slot is closest to the + // stack pointer. + if (RS && (!TFI.hasFP(Fn) || RegInfo->needsStackRealignment(Fn) || + !RegInfo->useFPForScavengingIndex(Fn))) { + int SFI = RS->getScavengingFrameIndex(); + if (SFI >= 0) + AdjustStackOffset(MFI, SFI, StackGrowsDown, Offset, MaxAlign); + } + + if (!TFI.targetHandlesStackFrameRounding()) { + // If we have reserved argument space for call sites in the function + // immediately on entry to the current function, count it as part of the + // overall stack size. + if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn)) + Offset += MFI->getMaxCallFrameSize(); + + // Round up the size to a multiple of the alignment. If the function has + // any calls or alloca's, align to the target's StackAlignment value to + // ensure that the callee's frame or the alloca data is suitably aligned; + // otherwise, for leaf functions, align to the TransientStackAlignment + // value. + unsigned StackAlign; + if (MFI->adjustsStack() || MFI->hasVarSizedObjects() || + (RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0)) + StackAlign = TFI.getStackAlignment(); + else + StackAlign = TFI.getTransientStackAlignment(); + + // If the frame pointer is eliminated, all frame offsets will be relative to + // SP not FP. Align to MaxAlign so this works. + StackAlign = std::max(StackAlign, MaxAlign); + unsigned AlignMask = StackAlign - 1; + Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); + } + + // Update frame info to pretend that this is part of the stack... + MFI->setStackSize(Offset - LocalAreaOffset); +} + +/// insertPrologEpilogCode - Scan the function for modified callee saved +/// registers, insert spill code for these callee saved registers, then add +/// prolog and epilog code to the function. +/// +void PEI::insertPrologEpilogCode(MachineFunction &Fn) { + const TargetFrameLowering &TFI = *Fn.getTarget().getFrameLowering(); + + // Add prologue to the function... + TFI.emitPrologue(Fn); + + // Add epilogue to restore the callee-save registers in each exiting block + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { + // If last instruction is a return instruction, add an epilogue + if (!I->empty() && I->back().getDesc().isReturn()) + TFI.emitEpilogue(Fn, *I); + } +} + +/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical +/// register references and actual offsets. +/// +void PEI::replaceFrameIndices(MachineFunction &Fn) { + if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do? + + const TargetMachine &TM = Fn.getTarget(); + assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!"); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + const TargetFrameLowering *TFI = TM.getFrameLowering(); + bool StackGrowsDown = + TFI->getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; + int FrameSetupOpcode = TRI.getCallFrameSetupOpcode(); + int FrameDestroyOpcode = TRI.getCallFrameDestroyOpcode(); + + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { +#ifndef NDEBUG + int SPAdjCount = 0; // frame setup / destroy count. +#endif + int SPAdj = 0; // SP offset due to call frame setup / destroy. + if (RS && !FrameIndexVirtualScavenging) RS->enterBasicBlock(BB); + + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { +#ifndef NDEBUG + // Track whether we see even pairs of them + SPAdjCount += I->getOpcode() == FrameSetupOpcode ? 1 : -1; +#endif + // Remember how much SP has been adjusted to create the call + // frame. + int Size = I->getOperand(0).getImm(); + + if ((!StackGrowsDown && I->getOpcode() == FrameSetupOpcode) || + (StackGrowsDown && I->getOpcode() == FrameDestroyOpcode)) + Size = -Size; + + SPAdj += Size; + + MachineBasicBlock::iterator PrevI = BB->end(); + if (I != BB->begin()) PrevI = prior(I); + TRI.eliminateCallFramePseudoInstr(Fn, *BB, I); + + // Visit the instructions created by eliminateCallFramePseudoInstr(). + if (PrevI == BB->end()) + I = BB->begin(); // The replaced instr was the first in the block. + else + I = llvm::next(PrevI); + continue; + } + + MachineInstr *MI = I; + bool DoIncr = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) + if (MI->getOperand(i).isFI()) { + // Some instructions (e.g. inline asm instructions) can have + // multiple frame indices and/or cause eliminateFrameIndex + // to insert more than one instruction. We need the register + // scavenger to go through all of these instructions so that + // it can update its register information. We keep the + // iterator at the point before insertion so that we can + // revisit them in full. + bool AtBeginning = (I == BB->begin()); + if (!AtBeginning) --I; + + // If this instruction has a FrameIndex operand, we need to + // use that target machine register info object to eliminate + // it. + TRI.eliminateFrameIndex(MI, SPAdj, + FrameIndexVirtualScavenging ? NULL : RS); + + // Reset the iterator if we were at the beginning of the BB. + if (AtBeginning) { + I = BB->begin(); + DoIncr = false; + } + + MI = 0; + break; + } + + if (DoIncr && I != BB->end()) ++I; + + // Update register states. + if (RS && !FrameIndexVirtualScavenging && MI) RS->forward(MI); + } + + // If we have evenly matched pairs of frame setup / destroy instructions, + // make sure the adjustments come out to zero. If we don't have matched + // pairs, we can't be sure the missing bit isn't in another basic block + // due to a custom inserter playing tricks, so just asserting SPAdj==0 + // isn't sufficient. See tMOVCC on Thumb1, for example. + assert((SPAdjCount || SPAdj == 0) && + "Unbalanced call frame setup / destroy pairs?"); + } +} + +/// scavengeFrameVirtualRegs - Replace all frame index virtual registers +/// with physical registers. Use the register scavenger to find an +/// appropriate register to use. +void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { + // Run through the instructions and find any virtual registers. + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { + RS->enterBasicBlock(BB); + + unsigned VirtReg = 0; + unsigned ScratchReg = 0; + int SPAdj = 0; + + // The instruction stream may change in the loop, so check BB->end() + // directly. + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + MachineInstr *MI = I; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).isReg()) { + MachineOperand &MO = MI->getOperand(i); + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + ++NumVirtualFrameRegs; + + // Have we already allocated a scratch register for this virtual? + if (Reg != VirtReg) { + // When we first encounter a new virtual register, it + // must be a definition. + assert(MI->getOperand(i).isDef() && + "frame index virtual missing def!"); + // Scavenge a new scratch register + VirtReg = Reg; + const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg); + ScratchReg = RS->scavengeRegister(RC, I, SPAdj); + ++NumScavengedRegs; + } + // Replace this reference to the virtual register with the + // scratch register. + assert (ScratchReg && "Missing scratch register!"); + MI->getOperand(i).setReg(ScratchReg); + + } + } + RS->forward(I); + ++I; + } + } +} diff --git a/final/lib/CodeGen/PrologEpilogInserter.h b/final/lib/CodeGen/PrologEpilogInserter.h new file mode 100644 index 00000000000..e2391591ad0 --- /dev/null +++ b/final/lib/CodeGen/PrologEpilogInserter.h @@ -0,0 +1,177 @@ +//===-- PrologEpilogInserter.h - Prolog/Epilog code insertion -*- C++ -* --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is responsible for finalizing the functions frame layout, saving +// callee saved registers, and for emitting prolog & epilog code for the +// function. +// +// This pass must be run after register allocation. After this pass is +// executed, it is illegal to construct MO_FrameIndex operands. +// +// This pass also implements a shrink wrapping variant of prolog/epilog +// insertion. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PEI_H +#define LLVM_CODEGEN_PEI_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + class RegScavenger; + class MachineBasicBlock; + + class PEI : public MachineFunctionPass { + public: + static char ID; + PEI() : MachineFunctionPass(ID) { + initializePEIPass(*PassRegistry::getPassRegistry()); + } + + const char *getPassName() const { + return "Prolog/Epilog Insertion & Frame Finalization"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// runOnMachineFunction - Insert prolog/epilog code and replace abstract + /// frame indexes with appropriate references. + /// + bool runOnMachineFunction(MachineFunction &Fn); + + private: + RegScavenger *RS; + + // MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved + // stack frame indexes. + unsigned MinCSFrameIndex, MaxCSFrameIndex; + + // Analysis info for spill/restore placement. + // "CSR": "callee saved register". + + // CSRegSet contains indices into the Callee Saved Register Info + // vector built by calculateCalleeSavedRegisters() and accessed + // via MF.getFrameInfo()->getCalleeSavedInfo(). + typedef SparseBitVector<> CSRegSet; + + // CSRegBlockMap maps MachineBasicBlocks to sets of callee + // saved register indices. + typedef DenseMap CSRegBlockMap; + + // Set and maps for computing CSR spill/restore placement: + // used in function (UsedCSRegs) + // used in a basic block (CSRUsed) + // anticipatable in a basic block (Antic{In,Out}) + // available in a basic block (Avail{In,Out}) + // to be spilled at the entry to a basic block (CSRSave) + // to be restored at the end of a basic block (CSRRestore) + CSRegSet UsedCSRegs; + CSRegBlockMap CSRUsed; + CSRegBlockMap AnticIn, AnticOut; + CSRegBlockMap AvailIn, AvailOut; + CSRegBlockMap CSRSave; + CSRegBlockMap CSRRestore; + + // Entry and return blocks of the current function. + MachineBasicBlock* EntryBlock; + SmallVector ReturnBlocks; + + // Map of MBBs to top level MachineLoops. + DenseMap TLLoops; + + // Flag to control shrink wrapping per-function: + // may choose to skip shrink wrapping for certain + // functions. + bool ShrinkWrapThisFunction; + + // Flag to control whether to use the register scavenger to resolve + // frame index materialization registers. Set according to + // TRI->requiresFrameIndexScavenging() for the curren function. + bool FrameIndexVirtualScavenging; + +#ifndef NDEBUG + // Machine function handle. + MachineFunction* MF; + + // Flag indicating that the current function + // has at least one "short" path in the machine + // CFG from the entry block to an exit block. + bool HasFastExitPath; +#endif + + bool calculateSets(MachineFunction &Fn); + bool calcAnticInOut(MachineBasicBlock* MBB); + bool calcAvailInOut(MachineBasicBlock* MBB); + void calculateAnticAvail(MachineFunction &Fn); + bool addUsesForMEMERegion(MachineBasicBlock* MBB, + SmallVector& blks); + bool addUsesForTopLevelLoops(SmallVector& blks); + bool calcSpillPlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevSpills); + bool calcRestorePlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevRestores); + void placeSpillsAndRestores(MachineFunction &Fn); + void placeCSRSpillsAndRestores(MachineFunction &Fn); + void calculateCallsInformation(MachineFunction &Fn); + void calculateCalleeSavedRegisters(MachineFunction &Fn); + void insertCSRSpillsAndRestores(MachineFunction &Fn); + void calculateFrameObjectOffsets(MachineFunction &Fn); + void replaceFrameIndices(MachineFunction &Fn); + void scavengeFrameVirtualRegs(MachineFunction &Fn); + void insertPrologEpilogCode(MachineFunction &Fn); + + // Initialize DFA sets, called before iterations. + void clearAnticAvailSets(); + // Clear all sets constructed by shrink wrapping. + void clearAllSets(); + + // Initialize all shrink wrapping data. + void initShrinkWrappingInfo(); + + // Convienences for dealing with machine loops. + MachineBasicBlock* getTopLevelLoopPreheader(MachineLoop* LP); + MachineLoop* getTopLevelLoopParent(MachineLoop *LP); + + // Propgate CSRs used in MBB to all MBBs of loop LP. + void propagateUsesAroundLoop(MachineBasicBlock* MBB, MachineLoop* LP); + + // Convenience for recognizing return blocks. + bool isReturnBlock(MachineBasicBlock* MBB); + +#ifndef NDEBUG + // Debugging methods. + + // Mark this function as having fast exit paths. + void findFastExitPath(); + + // Verify placement of spills/restores. + void verifySpillRestorePlacement(); + + std::string getBasicBlockName(const MachineBasicBlock* MBB); + std::string stringifyCSRegSet(const CSRegSet& s); + void dumpSet(const CSRegSet& s); + void dumpUsed(MachineBasicBlock* MBB); + void dumpAllUsed(); + void dumpSets(MachineBasicBlock* MBB); + void dumpSets1(MachineBasicBlock* MBB); + void dumpAllSets(); + void dumpSRSets(); +#endif + + }; +} // End llvm namespace +#endif diff --git a/final/lib/CodeGen/PseudoSourceValue.cpp b/final/lib/CodeGen/PseudoSourceValue.cpp new file mode 100644 index 00000000000..73b66d868f3 --- /dev/null +++ b/final/lib/CodeGen/PseudoSourceValue.cpp @@ -0,0 +1,134 @@ +//===-- llvm/CodeGen/PseudoSourceValue.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PseudoSourceValue class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mutex.h" +#include +using namespace llvm; + +namespace { +struct PSVGlobalsTy { + // PseudoSourceValues are immutable so don't need locking. + const PseudoSourceValue PSVs[4]; + sys::Mutex Lock; // Guards FSValues, but not the values inside it. + std::map FSValues; + + PSVGlobalsTy() : PSVs() {} + ~PSVGlobalsTy() { + for (std::map::iterator + I = FSValues.begin(), E = FSValues.end(); I != E; ++I) { + delete I->second; + } + } +}; + +static ManagedStatic PSVGlobals; + +} // anonymous namespace + +const PseudoSourceValue *PseudoSourceValue::getStack() +{ return &PSVGlobals->PSVs[0]; } +const PseudoSourceValue *PseudoSourceValue::getGOT() +{ return &PSVGlobals->PSVs[1]; } +const PseudoSourceValue *PseudoSourceValue::getJumpTable() +{ return &PSVGlobals->PSVs[2]; } +const PseudoSourceValue *PseudoSourceValue::getConstantPool() +{ return &PSVGlobals->PSVs[3]; } + +static const char *const PSVNames[] = { + "Stack", + "GOT", + "JumpTable", + "ConstantPool" +}; + +// FIXME: THIS IS A HACK!!!! +// Eventually these should be uniqued on LLVMContext rather than in a managed +// static. For now, we can safely use the global context for the time being to +// squeak by. +PseudoSourceValue::PseudoSourceValue(enum ValueTy Subclass) : + Value(Type::getInt8PtrTy(getGlobalContext()), + Subclass) {} + +void PseudoSourceValue::printCustom(raw_ostream &O) const { + O << PSVNames[this - PSVGlobals->PSVs]; +} + +const PseudoSourceValue *PseudoSourceValue::getFixedStack(int FI) { + PSVGlobalsTy &PG = *PSVGlobals; + sys::ScopedLock locked(PG.Lock); + const PseudoSourceValue *&V = PG.FSValues[FI]; + if (!V) + V = new FixedStackPseudoSourceValue(FI); + return V; +} + +bool PseudoSourceValue::isConstant(const MachineFrameInfo *) const { + if (this == getStack()) + return false; + if (this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return true; + llvm_unreachable("Unknown PseudoSourceValue!"); + return false; +} + +bool PseudoSourceValue::isAliased(const MachineFrameInfo *MFI) const { + if (this == getStack() || + this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return false; + llvm_unreachable("Unknown PseudoSourceValue!"); + return true; +} + +bool PseudoSourceValue::mayAlias(const MachineFrameInfo *MFI) const { + if (this == getGOT() || + this == getConstantPool() || + this == getJumpTable()) + return false; + return true; +} + +bool FixedStackPseudoSourceValue::isConstant(const MachineFrameInfo *MFI) const{ + return MFI && MFI->isImmutableObjectIndex(FI); +} + +bool FixedStackPseudoSourceValue::isAliased(const MachineFrameInfo *MFI) const { + // Negative frame indices are used for special things that don't + // appear in LLVM IR. Non-negative indices may be used for things + // like static allocas. + if (!MFI) + return FI >= 0; + // Spill slots should not alias others. + return !MFI->isFixedObjectIndex(FI) && !MFI->isSpillSlotObjectIndex(FI); +} + +bool FixedStackPseudoSourceValue::mayAlias(const MachineFrameInfo *MFI) const { + if (!MFI) + return true; + // Spill slots will not alias any LLVM IR value. + return !MFI->isSpillSlotObjectIndex(FI); +} + +void FixedStackPseudoSourceValue::printCustom(raw_ostream &OS) const { + OS << "FixedStack" << FI; +} diff --git a/final/lib/CodeGen/README.txt b/final/lib/CodeGen/README.txt new file mode 100644 index 00000000000..b655dda4115 --- /dev/null +++ b/final/lib/CodeGen/README.txt @@ -0,0 +1,199 @@ +//===---------------------------------------------------------------------===// + +Common register allocation / spilling problem: + + mul lr, r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + ldr r4, [sp, #+52] + mla r4, r3, lr, r4 + +can be: + + mul lr, r4, lr + mov r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + mla r4, r3, lr, r4 + +and then "merge" mul and mov: + + mul r4, r4, lr + str lr, [sp, #+52] + ldr lr, [r1, #+32] + sxth r3, r3 + mla r4, r3, lr, r4 + +It also increase the likelyhood the store may become dead. + +//===---------------------------------------------------------------------===// + +bb27 ... + ... + %reg1037 = ADDri %reg1039, 1 + %reg1038 = ADDrs %reg1032, %reg1039, %NOREG, 10 + Successors according to CFG: 0x8b03bf0 (#5) + +bb76 (0x8b03bf0, LLVM BB @0x8b032d0, ID#5): + Predecessors according to CFG: 0x8b0c5f0 (#3) 0x8b0a7c0 (#4) + %reg1039 = PHI %reg1070, mbb, %reg1037, mbb + +Note ADDri is not a two-address instruction. However, its result %reg1037 is an +operand of the PHI node in bb76 and its operand %reg1039 is the result of the +PHI node. We should treat it as a two-address code and make sure the ADDri is +scheduled after any node that reads %reg1039. + +//===---------------------------------------------------------------------===// + +Use local info (i.e. register scavenger) to assign it a free register to allow +reuse: + ldr r3, [sp, #+4] + add r3, r3, #3 + ldr r2, [sp, #+8] + add r2, r2, #2 + ldr r1, [sp, #+4] <== + add r1, r1, #1 + ldr r0, [sp, #+4] + add r0, r0, #2 + +//===---------------------------------------------------------------------===// + +LLVM aggressively lift CSE out of loop. Sometimes this can be negative side- +effects: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +load [i + R1] +... +load [i + R2] +... +load [i + R3] + +Suppose there is high register pressure, R1, R2, R3, can be spilled. We need +to implement proper re-materialization to handle this: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +R1 = X + 4 @ re-materialized +load [i + R1] +... +R2 = X + 7 @ re-materialized +load [i + R2] +... +R3 = X + 15 @ re-materialized +load [i + R3] + +Furthermore, with re-association, we can enable sharing: + +R1 = X + 4 +R2 = X + 7 +R3 = X + 15 + +loop: +T = i + X +load [T + 4] +... +load [T + 7] +... +load [T + 15] +//===---------------------------------------------------------------------===// + +It's not always a good idea to choose rematerialization over spilling. If all +the load / store instructions would be folded then spilling is cheaper because +it won't require new live intervals / registers. See 2003-05-31-LongShifts for +an example. + +//===---------------------------------------------------------------------===// + +With a copying garbage collector, derived pointers must not be retained across +collector safe points; the collector could move the objects and invalidate the +derived pointer. This is bad enough in the first place, but safe points can +crop up unpredictably. Consider: + + %array = load { i32, [0 x %obj] }** %array_addr + %nth_el = getelementptr { i32, [0 x %obj] }* %array, i32 0, i32 %n + %old = load %obj** %nth_el + %z = div i64 %x, %y + store %obj* %new, %obj** %nth_el + +If the i64 division is lowered to a libcall, then a safe point will (must) +appear for the call site. If a collection occurs, %array and %nth_el no longer +point into the correct object. + +The fix for this is to copy address calculations so that dependent pointers +are never live across safe point boundaries. But the loads cannot be copied +like this if there was an intervening store, so may be hard to get right. + +Only a concurrent mutator can trigger a collection at the libcall safe point. +So single-threaded programs do not have this requirement, even with a copying +collector. Still, LLVM optimizations would probably undo a front-end's careful +work. + +//===---------------------------------------------------------------------===// + +The ocaml frametable structure supports liveness information. It would be good +to support it. + +//===---------------------------------------------------------------------===// + +The FIXME in ComputeCommonTailLength in BranchFolding.cpp needs to be +revisited. The check is there to work around a misuse of directives in inline +assembly. + +//===---------------------------------------------------------------------===// + +It would be good to detect collector/target compatibility instead of silently +doing the wrong thing. + +//===---------------------------------------------------------------------===// + +It would be really nice to be able to write patterns in .td files for copies, +which would eliminate a bunch of explicit predicates on them (e.g. no side +effects). Once this is in place, it would be even better to have tblgen +synthesize the various copy insertion/inspection methods in TargetInstrInfo. + +//===---------------------------------------------------------------------===// + +Stack coloring improvments: + +1. Do proper LiveStackAnalysis on all stack objects including those which are + not spill slots. +2. Reorder objects to fill in gaps between objects. + e.g. 4, 1, , 4, 1, 1, 1, , 4 => 4, 1, 1, 1, 1, 4, 4 + +//===---------------------------------------------------------------------===// + +The scheduler should be able to sort nearby instructions by their address. For +example, in an expanded memset sequence it's not uncommon to see code like this: + + movl $0, 4(%rdi) + movl $0, 8(%rdi) + movl $0, 12(%rdi) + movl $0, 0(%rdi) + +Each of the stores is independent, and the scheduler is currently making an +arbitrary decision about the order. + +//===---------------------------------------------------------------------===// + +Another opportunitiy in this code is that the $0 could be moved to a register: + + movl $0, 4(%rdi) + movl $0, 8(%rdi) + movl $0, 12(%rdi) + movl $0, 0(%rdi) + +This would save substantial code size, especially for longer sequences like +this. It would be easy to have a rule telling isel to avoid matching MOV32mi +if the immediate has more than some fixed number of uses. It's more involved +to teach the register allocator how to do late folding to recover from +excessive register pressure. + diff --git a/final/lib/CodeGen/RegAllocBase.h b/final/lib/CodeGen/RegAllocBase.h new file mode 100644 index 00000000000..5af0ce79acf --- /dev/null +++ b/final/lib/CodeGen/RegAllocBase.h @@ -0,0 +1,182 @@ +//===-- RegAllocBase.h - basic regalloc interface and driver --*- 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 RegAllocBase class, which is the skeleton of a basic +// register allocation algorithm and interface for extending it. It provides the +// building blocks on which to construct other experimental allocators and test +// the validity of two principles: +// +// - If virtual and physical register liveness is modeled using intervals, then +// on-the-fly interference checking is cheap. Furthermore, interferences can be +// lazily cached and reused. +// +// - Register allocation complexity, and generated code performance is +// determined by the effectiveness of live range splitting rather than optimal +// coloring. +// +// Following the first principle, interfering checking revolves around the +// LiveIntervalUnion data structure. +// +// To fulfill the second principle, the basic allocator provides a driver for +// incremental splitting. It essentially punts on the problem of register +// coloring, instead driving the assignment of virtual to physical registers by +// the cost of splitting. The basic allocator allows for heuristic reassignment +// of registers, if a more sophisticated allocator chooses to do that. +// +// This framework provides a way to engineer the compile time vs. code +// quality trade-off without relying on a particular theoretical solver. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGALLOCBASE +#define LLVM_CODEGEN_REGALLOCBASE + +#include "llvm/ADT/OwningPtr.h" +#include "LiveIntervalUnion.h" + +namespace llvm { + +template class SmallVectorImpl; +class TargetRegisterInfo; +class VirtRegMap; +class LiveIntervals; +class Spiller; + +// Forward declare a priority queue of live virtual registers. If an +// implementation needs to prioritize by anything other than spill weight, then +// this will become an abstract base class with virtual calls to push/get. +class LiveVirtRegQueue; + +/// RegAllocBase provides the register allocation driver and interface that can +/// be extended to add interesting heuristics. +/// +/// Register allocators must override the selectOrSplit() method to implement +/// live range splitting. They must also override enqueue/dequeue to provide an +/// assignment order. +class RegAllocBase { + LiveIntervalUnion::Allocator UnionAllocator; +protected: + // Array of LiveIntervalUnions indexed by physical register. + class LiveUnionArray { + unsigned NumRegs; + LiveIntervalUnion *Array; + public: + LiveUnionArray(): NumRegs(0), Array(0) {} + ~LiveUnionArray() { clear(); } + + unsigned numRegs() const { return NumRegs; } + + void init(LiveIntervalUnion::Allocator &, unsigned NRegs); + + void clear(); + + LiveIntervalUnion& operator[](unsigned PhysReg) { + assert(PhysReg < NumRegs && "physReg out of bounds"); + return Array[PhysReg]; + } + }; + + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + VirtRegMap *VRM; + LiveIntervals *LIS; + LiveUnionArray PhysReg2LiveUnion; + + // Current queries, one per physreg. They must be reinitialized each time we + // query on a new live virtual register. + OwningArrayPtr Queries; + + RegAllocBase(): TRI(0), MRI(0), VRM(0), LIS(0) {} + + virtual ~RegAllocBase() {} + + // A RegAlloc pass should call this before allocatePhysRegs. + void init(VirtRegMap &vrm, LiveIntervals &lis); + + // Get an initialized query to check interferences between lvr and preg. Note + // that Query::init must be called at least once for each physical register + // before querying a new live virtual register. This ties Queries and + // PhysReg2LiveUnion together. + LiveIntervalUnion::Query &query(LiveInterval &VirtReg, unsigned PhysReg) { + Queries[PhysReg].init(&VirtReg, &PhysReg2LiveUnion[PhysReg]); + return Queries[PhysReg]; + } + + // The top-level driver. The output is a VirtRegMap that us updated with + // physical register assignments. + // + // If an implementation wants to override the LiveInterval comparator, we + // should modify this interface to allow passing in an instance derived from + // LiveVirtRegQueue. + void allocatePhysRegs(); + + // Get a temporary reference to a Spiller instance. + virtual Spiller &spiller() = 0; + + /// enqueue - Add VirtReg to the priority queue of unassigned registers. + virtual void enqueue(LiveInterval *LI) = 0; + + /// dequeue - Return the next unassigned register, or NULL. + virtual LiveInterval *dequeue() = 0; + + // A RegAlloc pass should override this to provide the allocation heuristics. + // Each call must guarantee forward progess by returning an available PhysReg + // or new set of split live virtual registers. It is up to the splitter to + // converge quickly toward fully spilled live ranges. + virtual unsigned selectOrSplit(LiveInterval &VirtReg, + SmallVectorImpl &splitLVRs) = 0; + + // A RegAlloc pass should call this when PassManager releases its memory. + virtual void releaseMemory(); + + // Helper for checking interference between a live virtual register and a + // physical register, including all its register aliases. If an interference + // exists, return the interfering register, which may be preg or an alias. + unsigned checkPhysRegInterference(LiveInterval& VirtReg, unsigned PhysReg); + + /// assign - Assign VirtReg to PhysReg. + /// This should not be called from selectOrSplit for the current register. + void assign(LiveInterval &VirtReg, unsigned PhysReg); + + /// unassign - Undo a previous assignment of VirtReg to PhysReg. + /// This can be invoked from selectOrSplit, but be careful to guarantee that + /// allocation is making progress. + void unassign(LiveInterval &VirtReg, unsigned PhysReg); + + // Helper for spilling all live virtual registers currently unified under preg + // that interfere with the most recently queried lvr. Return true if spilling + // was successful, and append any new spilled/split intervals to splitLVRs. + bool spillInterferences(LiveInterval &VirtReg, unsigned PhysReg, + SmallVectorImpl &SplitVRegs); + + /// addMBBLiveIns - Add physreg liveins to basic blocks. + void addMBBLiveIns(MachineFunction *); + +#ifndef NDEBUG + // Verify each LiveIntervalUnion. + void verify(); +#endif + + // Use this group name for NamedRegionTimer. + static const char *TimerGroupName; + +public: + /// VerifyEnabled - True when -verify-regalloc is given. + static bool VerifyEnabled; + +private: + void seedLiveRegs(); + + void spillReg(LiveInterval &VirtReg, unsigned PhysReg, + SmallVectorImpl &SplitVRegs); +}; + +} // end namespace llvm + +#endif // !defined(LLVM_CODEGEN_REGALLOCBASE) diff --git a/final/lib/CodeGen/RegAllocBasic.cpp b/final/lib/CodeGen/RegAllocBasic.cpp new file mode 100644 index 00000000000..6923908a32d --- /dev/null +++ b/final/lib/CodeGen/RegAllocBasic.cpp @@ -0,0 +1,537 @@ +//===-- RegAllocBasic.cpp - basic register allocator ----------------------===// +// +// 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 RABasic function pass, which provides a minimal +// implementation of the basic register allocator. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "LiveIntervalUnion.h" +#include "RegAllocBase.h" +#include "RenderMachineFunction.h" +#include "Spiller.h" +#include "VirtRegMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Function.h" +#include "llvm/PassAnalysisSupport.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegisterInfo.h" +#ifndef NDEBUG +#include "llvm/ADT/SparseBitVector.h" +#endif +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Timer.h" + +#include +#include + +using namespace llvm; + +STATISTIC(NumAssigned , "Number of registers assigned"); +STATISTIC(NumUnassigned , "Number of registers unassigned"); +STATISTIC(NumNewQueued , "Number of new live ranges queued"); + +static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator", + createBasicRegisterAllocator); + +// Temporary verification option until we can put verification inside +// MachineVerifier. +static cl::opt +VerifyRegAlloc("verify-regalloc", cl::location(RegAllocBase::VerifyEnabled), + cl::desc("Verify during register allocation")); + +const char *RegAllocBase::TimerGroupName = "Register Allocation"; +bool RegAllocBase::VerifyEnabled = false; + +namespace { + struct CompSpillWeight { + bool operator()(LiveInterval *A, LiveInterval *B) const { + return A->weight < B->weight; + } + }; +} + +namespace { +/// RABasic provides a minimal implementation of the basic register allocation +/// algorithm. It prioritizes live virtual registers by spill weight and spills +/// whenever a register is unavailable. This is not practical in production but +/// provides a useful baseline both for measuring other allocators and comparing +/// the speed of the basic algorithm against other styles of allocators. +class RABasic : public MachineFunctionPass, public RegAllocBase +{ + // context + MachineFunction *MF; + BitVector ReservedRegs; + + // analyses + LiveStacks *LS; + RenderMachineFunction *RMF; + + // state + std::auto_ptr SpillerInstance; + std::priority_queue, + CompSpillWeight> Queue; +public: + RABasic(); + + /// Return the pass name. + virtual const char* getPassName() const { + return "Basic Register Allocator"; + } + + /// RABasic analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory(); + + virtual Spiller &spiller() { return *SpillerInstance; } + + virtual float getPriority(LiveInterval *LI) { return LI->weight; } + + virtual void enqueue(LiveInterval *LI) { + Queue.push(LI); + } + + virtual LiveInterval *dequeue() { + if (Queue.empty()) + return 0; + LiveInterval *LI = Queue.top(); + Queue.pop(); + return LI; + } + + virtual unsigned selectOrSplit(LiveInterval &VirtReg, + SmallVectorImpl &SplitVRegs); + + /// Perform register allocation. + virtual bool runOnMachineFunction(MachineFunction &mf); + + static char ID; +}; + +char RABasic::ID = 0; + +} // end anonymous namespace + +RABasic::RABasic(): MachineFunctionPass(ID) { + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); +} + +void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + if (StrongPHIElim) + AU.addRequiredID(StrongPHIEliminationID); + AU.addRequiredTransitive(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredID(MachineDominatorsID); + AU.addPreservedID(MachineDominatorsID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + DEBUG(AU.addRequired()); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void RABasic::releaseMemory() { + SpillerInstance.reset(0); + RegAllocBase::releaseMemory(); +} + +#ifndef NDEBUG +// Verify each LiveIntervalUnion. +void RegAllocBase::verify() { + LiveVirtRegBitSet VisitedVRegs; + OwningArrayPtr + unionVRegs(new LiveVirtRegBitSet[PhysReg2LiveUnion.numRegs()]); + + // Verify disjoint unions. + for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) { + DEBUG(PhysReg2LiveUnion[PhysReg].print(dbgs(), TRI)); + LiveVirtRegBitSet &VRegs = unionVRegs[PhysReg]; + PhysReg2LiveUnion[PhysReg].verify(VRegs); + // Union + intersection test could be done efficiently in one pass, but + // don't add a method to SparseBitVector unless we really need it. + assert(!VisitedVRegs.intersects(VRegs) && "vreg in multiple unions"); + VisitedVRegs |= VRegs; + } + + // Verify vreg coverage. + for (LiveIntervals::iterator liItr = LIS->begin(), liEnd = LIS->end(); + liItr != liEnd; ++liItr) { + unsigned reg = liItr->first; + if (TargetRegisterInfo::isPhysicalRegister(reg)) continue; + if (!VRM->hasPhys(reg)) continue; // spilled? + unsigned PhysReg = VRM->getPhys(reg); + if (!unionVRegs[PhysReg].test(reg)) { + dbgs() << "LiveVirtReg " << reg << " not in union " << + TRI->getName(PhysReg) << "\n"; + llvm_unreachable("unallocated live vreg"); + } + } + // FIXME: I'm not sure how to verify spilled intervals. +} +#endif //!NDEBUG + +//===----------------------------------------------------------------------===// +// RegAllocBase Implementation +//===----------------------------------------------------------------------===// + +// Instantiate a LiveIntervalUnion for each physical register. +void RegAllocBase::LiveUnionArray::init(LiveIntervalUnion::Allocator &allocator, + unsigned NRegs) { + NumRegs = NRegs; + Array = + static_cast(malloc(sizeof(LiveIntervalUnion)*NRegs)); + for (unsigned r = 0; r != NRegs; ++r) + new(Array + r) LiveIntervalUnion(r, allocator); +} + +void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis) { + NamedRegionTimer T("Initialize", TimerGroupName, TimePassesIsEnabled); + TRI = &vrm.getTargetRegInfo(); + MRI = &vrm.getRegInfo(); + VRM = &vrm; + LIS = &lis; + PhysReg2LiveUnion.init(UnionAllocator, TRI->getNumRegs()); + // Cache an interferece query for each physical reg + Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]); +} + +void RegAllocBase::LiveUnionArray::clear() { + if (!Array) + return; + for (unsigned r = 0; r != NumRegs; ++r) + Array[r].~LiveIntervalUnion(); + free(Array); + NumRegs = 0; + Array = 0; +} + +void RegAllocBase::releaseMemory() { + PhysReg2LiveUnion.clear(); +} + +// Visit all the live registers. If they are already assigned to a physical +// register, unify them with the corresponding LiveIntervalUnion, otherwise push +// them on the priority queue for later assignment. +void RegAllocBase::seedLiveRegs() { + for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) { + unsigned RegNum = I->first; + LiveInterval &VirtReg = *I->second; + if (TargetRegisterInfo::isPhysicalRegister(RegNum)) + PhysReg2LiveUnion[RegNum].unify(VirtReg); + else + enqueue(&VirtReg); + } +} + +void RegAllocBase::assign(LiveInterval &VirtReg, unsigned PhysReg) { + DEBUG(dbgs() << "assigning " << PrintReg(VirtReg.reg, TRI) + << " to " << PrintReg(PhysReg, TRI) << '\n'); + assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment"); + VRM->assignVirt2Phys(VirtReg.reg, PhysReg); + PhysReg2LiveUnion[PhysReg].unify(VirtReg); + ++NumAssigned; +} + +void RegAllocBase::unassign(LiveInterval &VirtReg, unsigned PhysReg) { + DEBUG(dbgs() << "unassigning " << PrintReg(VirtReg.reg, TRI) + << " from " << PrintReg(PhysReg, TRI) << '\n'); + assert(VRM->getPhys(VirtReg.reg) == PhysReg && "Inconsistent unassign"); + PhysReg2LiveUnion[PhysReg].extract(VirtReg); + VRM->clearVirt(VirtReg.reg); + ++NumUnassigned; +} + +// Top-level driver to manage the queue of unassigned VirtRegs and call the +// selectOrSplit implementation. +void RegAllocBase::allocatePhysRegs() { + seedLiveRegs(); + + // Continue assigning vregs one at a time to available physical registers. + while (LiveInterval *VirtReg = dequeue()) { + // selectOrSplit requests the allocator to return an available physical + // register if possible and populate a list of new live intervals that + // result from splitting. + DEBUG(dbgs() << "\nselectOrSplit " + << MRI->getRegClass(VirtReg->reg)->getName() + << ':' << *VirtReg << '\n'); + typedef SmallVector VirtRegVec; + VirtRegVec SplitVRegs; + unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs); + + if (AvailablePhysReg) + assign(*VirtReg, AvailablePhysReg); + + for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end(); + I != E; ++I) { + LiveInterval *SplitVirtReg = *I; + if (SplitVirtReg->empty()) continue; + DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n"); + assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) && + "expect split value in virtual register"); + enqueue(SplitVirtReg); + ++NumNewQueued; + } + } +} + +// Check if this live virtual register interferes with a physical register. If +// not, then check for interference on each register that aliases with the +// physical register. Return the interfering register. +unsigned RegAllocBase::checkPhysRegInterference(LiveInterval &VirtReg, + unsigned PhysReg) { + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) + if (query(VirtReg, *AliasI).checkInterference()) + return *AliasI; + return 0; +} + +// Helper for spillInteferences() that spills all interfering vregs currently +// assigned to this physical register. +void RegAllocBase::spillReg(LiveInterval& VirtReg, unsigned PhysReg, + SmallVectorImpl &SplitVRegs) { + LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg); + assert(Q.seenAllInterferences() && "need collectInterferences()"); + const SmallVectorImpl &PendingSpills = Q.interferingVRegs(); + + for (SmallVectorImpl::const_iterator I = PendingSpills.begin(), + E = PendingSpills.end(); I != E; ++I) { + LiveInterval &SpilledVReg = **I; + DEBUG(dbgs() << "extracting from " << + TRI->getName(PhysReg) << " " << SpilledVReg << '\n'); + + // Deallocate the interfering vreg by removing it from the union. + // A LiveInterval instance may not be in a union during modification! + unassign(SpilledVReg, PhysReg); + + // Spill the extracted interval. + spiller().spill(&SpilledVReg, SplitVRegs, PendingSpills); + } + // After extracting segments, the query's results are invalid. But keep the + // contents valid until we're done accessing pendingSpills. + Q.clear(); +} + +// Spill or split all live virtual registers currently unified under PhysReg +// that interfere with VirtReg. The newly spilled or split live intervals are +// returned by appending them to SplitVRegs. +bool +RegAllocBase::spillInterferences(LiveInterval &VirtReg, unsigned PhysReg, + SmallVectorImpl &SplitVRegs) { + // Record each interference and determine if all are spillable before mutating + // either the union or live intervals. + unsigned NumInterferences = 0; + // Collect interferences assigned to any alias of the physical register. + for (const unsigned *asI = TRI->getOverlaps(PhysReg); *asI; ++asI) { + LiveIntervalUnion::Query &QAlias = query(VirtReg, *asI); + NumInterferences += QAlias.collectInterferingVRegs(); + if (QAlias.seenUnspillableVReg()) { + return false; + } + } + DEBUG(dbgs() << "spilling " << TRI->getName(PhysReg) << + " interferences with " << VirtReg << "\n"); + assert(NumInterferences > 0 && "expect interference"); + + // Spill each interfering vreg allocated to PhysReg or an alias. + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) + spillReg(VirtReg, *AliasI, SplitVRegs); + return true; +} + +// Add newly allocated physical registers to the MBB live in sets. +void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { + NamedRegionTimer T("MBB Live Ins", TimerGroupName, TimePassesIsEnabled); + typedef SmallVector MBBVec; + MBBVec liveInMBBs; + MachineBasicBlock &entryMBB = *MF->begin(); + + for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) { + LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg]; + if (LiveUnion.empty()) + continue; + for (LiveIntervalUnion::SegmentIter SI = LiveUnion.begin(); SI.valid(); + ++SI) { + + // Find the set of basic blocks which this range is live into... + liveInMBBs.clear(); + if (!LIS->findLiveInMBBs(SI.start(), SI.stop(), liveInMBBs)) continue; + + // And add the physreg for this interval to their live-in sets. + for (MBBVec::iterator I = liveInMBBs.begin(), E = liveInMBBs.end(); + I != E; ++I) { + MachineBasicBlock *MBB = *I; + if (MBB == &entryMBB) continue; + if (MBB->isLiveIn(PhysReg)) continue; + MBB->addLiveIn(PhysReg); + } + } + } +} + + +//===----------------------------------------------------------------------===// +// RABasic Implementation +//===----------------------------------------------------------------------===// + +// Driver for the register assignment and splitting heuristics. +// Manages iteration over the LiveIntervalUnions. +// +// This is a minimal implementation of register assignment and splitting that +// spills whenever we run out of registers. +// +// selectOrSplit can only be called once per live virtual register. We then do a +// single interference test for each register the correct class until we find an +// available register. So, the number of interference tests in the worst case is +// |vregs| * |machineregs|. And since the number of interference tests is +// minimal, there is no value in caching them outside the scope of +// selectOrSplit(). +unsigned RABasic::selectOrSplit(LiveInterval &VirtReg, + SmallVectorImpl &SplitVRegs) { + // Populate a list of physical register spill candidates. + SmallVector PhysRegSpillCands; + + // Check for an available register in this class. + const TargetRegisterClass *TRC = MRI->getRegClass(VirtReg.reg); + + for (TargetRegisterClass::iterator I = TRC->allocation_order_begin(*MF), + E = TRC->allocation_order_end(*MF); + I != E; ++I) { + + unsigned PhysReg = *I; + if (ReservedRegs.test(PhysReg)) continue; + + // Check interference and as a side effect, intialize queries for this + // VirtReg and its aliases. + unsigned interfReg = checkPhysRegInterference(VirtReg, PhysReg); + if (interfReg == 0) { + // Found an available register. + return PhysReg; + } + LiveInterval *interferingVirtReg = + Queries[interfReg].firstInterference().liveUnionPos().value(); + + // The current VirtReg must either be spillable, or one of its interferences + // must have less spill weight. + if (interferingVirtReg->weight < VirtReg.weight ) { + PhysRegSpillCands.push_back(PhysReg); + } + } + // Try to spill another interfering reg with less spill weight. + for (SmallVectorImpl::iterator PhysRegI = PhysRegSpillCands.begin(), + PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) { + + if (!spillInterferences(VirtReg, *PhysRegI, SplitVRegs)) continue; + + assert(checkPhysRegInterference(VirtReg, *PhysRegI) == 0 && + "Interference after spill."); + // Tell the caller to allocate to this newly freed physical register. + return *PhysRegI; + } + // No other spill candidates were found, so spill the current VirtReg. + DEBUG(dbgs() << "spilling: " << VirtReg << '\n'); + SmallVector pendingSpills; + + spiller().spill(&VirtReg, SplitVRegs, pendingSpills); + + // The live virtual register requesting allocation was spilled, so tell + // the caller not to allocate anything during this round. + return 0; +} + +bool RABasic::runOnMachineFunction(MachineFunction &mf) { + DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n" + << "********** Function: " + << ((Value*)mf.getFunction())->getName() << '\n'); + + MF = &mf; + DEBUG(RMF = &getAnalysis()); + + RegAllocBase::init(getAnalysis(), getAnalysis()); + + ReservedRegs = TRI->getReservedRegs(*MF); + + SpillerInstance.reset(createSpiller(*this, *MF, *VRM)); + + allocatePhysRegs(); + + addMBBLiveIns(MF); + + // Diagnostic output before rewriting + DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n"); + + // optional HTML output + DEBUG(RMF->renderMachineFunction("After basic register allocation.", VRM)); + + // FIXME: Verification currently must run before VirtRegRewriter. We should + // make the rewriter a separate pass and override verifyAnalysis instead. When + // that happens, verification naturally falls under VerifyMachineCode. +#ifndef NDEBUG + if (VerifyEnabled) { + // Verify accuracy of LiveIntervals. The standard machine code verifier + // ensures that each LiveIntervals covers all uses of the virtual reg. + + // FIXME: MachineVerifier is badly broken when using the standard + // spiller. Always use -spiller=inline with -verify-regalloc. Even with the + // inline spiller, some tests fail to verify because the coalescer does not + // always generate verifiable code. + MF->verify(this, "In RABasic::verify"); + + // Verify that LiveIntervals are partitioned into unions and disjoint within + // the unions. + verify(); + } +#endif // !NDEBUG + + // Run rewriter + VRM->rewrite(LIS->getSlotIndexes()); + + // The pass output is in VirtRegMap. Release all the transient data. + releaseMemory(); + + return true; +} + +FunctionPass* llvm::createBasicRegisterAllocator() +{ + return new RABasic(); +} diff --git a/final/lib/CodeGen/RegAllocFast.cpp b/final/lib/CodeGen/RegAllocFast.cpp new file mode 100644 index 00000000000..15036e38b89 --- /dev/null +++ b/final/lib/CodeGen/RegAllocFast.cpp @@ -0,0 +1,1076 @@ +//===-- RegAllocFast.cpp - A fast register allocator for debug code -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This register allocator allocates registers to a basic block at a time, +// attempting to keep values in registers and reusing registers as appropriate. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "llvm/BasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +using namespace llvm; + +STATISTIC(NumStores, "Number of stores added"); +STATISTIC(NumLoads , "Number of loads added"); +STATISTIC(NumCopies, "Number of copies coalesced"); + +static RegisterRegAlloc + fastRegAlloc("fast", "fast register allocator", createFastRegisterAllocator); + +namespace { + class RAFast : public MachineFunctionPass { + public: + static char ID; + RAFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1), + isBulkSpilling(false) { + initializePHIEliminationPass(*PassRegistry::getPassRegistry()); + initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry()); + } + private: + const TargetMachine *TM; + MachineFunction *MF; + MachineRegisterInfo *MRI; + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + // Basic block currently being allocated. + MachineBasicBlock *MBB; + + // StackSlotForVirtReg - Maps virtual regs to the frame index where these + // values are spilled. + IndexedMap StackSlotForVirtReg; + + // Everything we know about a live virtual register. + struct LiveReg { + MachineInstr *LastUse; // Last instr to use reg. + unsigned PhysReg; // Currently held here. + unsigned short LastOpNum; // OpNum on LastUse. + bool Dirty; // Register needs spill. + + LiveReg(unsigned p=0) : LastUse(0), PhysReg(p), LastOpNum(0), + Dirty(false) {} + }; + + typedef DenseMap LiveRegMap; + typedef LiveRegMap::value_type LiveRegEntry; + + // LiveVirtRegs - This map contains entries for each virtual register + // that is currently available in a physical register. + LiveRegMap LiveVirtRegs; + + DenseMap LiveDbgValueMap; + + // RegState - Track the state of a physical register. + enum RegState { + // A disabled register is not available for allocation, but an alias may + // be in use. A register can only be moved out of the disabled state if + // all aliases are disabled. + regDisabled, + + // A free register is not currently in use and can be allocated + // immediately without checking aliases. + regFree, + + // A reserved register has been assigned expolicitly (e.g., setting up a + // call parameter), and it remains reserved until it is used. + regReserved + + // A register state may also be a virtual register number, indication that + // the physical register is currently allocated to a virtual register. In + // that case, LiveVirtRegs contains the inverse mapping. + }; + + // PhysRegState - One of the RegState enums, or a virtreg. + std::vector PhysRegState; + + // UsedInInstr - BitVector of physregs that are used in the current + // instruction, and so cannot be allocated. + BitVector UsedInInstr; + + // Allocatable - vector of allocatable physical registers. + BitVector Allocatable; + + // SkippedInstrs - Descriptors of instructions whose clobber list was + // ignored because all registers were spilled. It is still necessary to + // mark all the clobbered registers as used by the function. + SmallPtrSet SkippedInstrs; + + // isBulkSpilling - This flag is set when LiveRegMap will be cleared + // completely after spilling all live registers. LiveRegMap entries should + // not be erased. + bool isBulkSpilling; + + enum { + spillClean = 1, + spillDirty = 100, + spillImpossible = ~0u + }; + public: + virtual const char *getPassName() const { + return "Fast Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequiredID(PHIEliminationID); + AU.addRequiredID(TwoAddressInstructionPassID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + bool runOnMachineFunction(MachineFunction &Fn); + void AllocateBasicBlock(); + void handleThroughOperands(MachineInstr *MI, + SmallVectorImpl &VirtDead); + int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC); + bool isLastUseOfLocalReg(MachineOperand&); + + void addKillFlag(const LiveReg&); + void killVirtReg(LiveRegMap::iterator); + void killVirtReg(unsigned VirtReg); + void spillVirtReg(MachineBasicBlock::iterator MI, LiveRegMap::iterator); + void spillVirtReg(MachineBasicBlock::iterator MI, unsigned VirtReg); + + void usePhysReg(MachineOperand&); + void definePhysReg(MachineInstr *MI, unsigned PhysReg, RegState NewState); + unsigned calcSpillCost(unsigned PhysReg) const; + void assignVirtToPhysReg(LiveRegEntry &LRE, unsigned PhysReg); + void allocVirtReg(MachineInstr *MI, LiveRegEntry &LRE, unsigned Hint); + LiveRegMap::iterator defineVirtReg(MachineInstr *MI, unsigned OpNum, + unsigned VirtReg, unsigned Hint); + LiveRegMap::iterator reloadVirtReg(MachineInstr *MI, unsigned OpNum, + unsigned VirtReg, unsigned Hint); + void spillAll(MachineInstr *MI); + bool setPhysReg(MachineInstr *MI, unsigned OpNum, unsigned PhysReg); + }; + char RAFast::ID = 0; +} + +/// getStackSpaceFor - This allocates space for the specified virtual register +/// to be held on the stack. +int RAFast::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) { + // Find the location Reg would belong... + int SS = StackSlotForVirtReg[VirtReg]; + if (SS != -1) + return SS; // Already has space allocated? + + // Allocate a new stack object for this spill location... + int FrameIdx = MF->getFrameInfo()->CreateSpillStackObject(RC->getSize(), + RC->getAlignment()); + + // Assign the slot. + StackSlotForVirtReg[VirtReg] = FrameIdx; + return FrameIdx; +} + +/// isLastUseOfLocalReg - Return true if MO is the only remaining reference to +/// its virtual register, and it is guaranteed to be a block-local register. +/// +bool RAFast::isLastUseOfLocalReg(MachineOperand &MO) { + // Check for non-debug uses or defs following MO. + // This is the most likely way to fail - fast path it. + MachineOperand *Next = &MO; + while ((Next = Next->getNextOperandForReg())) + if (!Next->isDebug()) + return false; + + // If the register has ever been spilled or reloaded, we conservatively assume + // it is a global register used in multiple blocks. + if (StackSlotForVirtReg[MO.getReg()] != -1) + return false; + + // Check that the use/def chain has exactly one operand - MO. + return &MRI->reg_nodbg_begin(MO.getReg()).getOperand() == &MO; +} + +/// addKillFlag - Set kill flags on last use of a virtual register. +void RAFast::addKillFlag(const LiveReg &LR) { + if (!LR.LastUse) return; + MachineOperand &MO = LR.LastUse->getOperand(LR.LastOpNum); + if (MO.isUse() && !LR.LastUse->isRegTiedToDefOperand(LR.LastOpNum)) { + if (MO.getReg() == LR.PhysReg) + MO.setIsKill(); + else + LR.LastUse->addRegisterKilled(LR.PhysReg, TRI, true); + } +} + +/// killVirtReg - Mark virtreg as no longer available. +void RAFast::killVirtReg(LiveRegMap::iterator LRI) { + addKillFlag(LRI->second); + const LiveReg &LR = LRI->second; + assert(PhysRegState[LR.PhysReg] == LRI->first && "Broken RegState mapping"); + PhysRegState[LR.PhysReg] = regFree; + // Erase from LiveVirtRegs unless we're spilling in bulk. + if (!isBulkSpilling) + LiveVirtRegs.erase(LRI); +} + +/// killVirtReg - Mark virtreg as no longer available. +void RAFast::killVirtReg(unsigned VirtReg) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "killVirtReg needs a virtual register"); + LiveRegMap::iterator LRI = LiveVirtRegs.find(VirtReg); + if (LRI != LiveVirtRegs.end()) + killVirtReg(LRI); +} + +/// spillVirtReg - This method spills the value specified by VirtReg into the +/// corresponding stack slot if needed. +void RAFast::spillVirtReg(MachineBasicBlock::iterator MI, unsigned VirtReg) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Spilling a physical register is illegal!"); + LiveRegMap::iterator LRI = LiveVirtRegs.find(VirtReg); + assert(LRI != LiveVirtRegs.end() && "Spilling unmapped virtual register"); + spillVirtReg(MI, LRI); +} + +/// spillVirtReg - Do the actual work of spilling. +void RAFast::spillVirtReg(MachineBasicBlock::iterator MI, + LiveRegMap::iterator LRI) { + LiveReg &LR = LRI->second; + assert(PhysRegState[LR.PhysReg] == LRI->first && "Broken RegState mapping"); + + if (LR.Dirty) { + // If this physreg is used by the instruction, we want to kill it on the + // instruction, not on the spill. + bool SpillKill = LR.LastUse != MI; + LR.Dirty = false; + DEBUG(dbgs() << "Spilling " << PrintReg(LRI->first, TRI) + << " in " << PrintReg(LR.PhysReg, TRI)); + const TargetRegisterClass *RC = MRI->getRegClass(LRI->first); + int FI = getStackSpaceFor(LRI->first, RC); + DEBUG(dbgs() << " to stack slot #" << FI << "\n"); + TII->storeRegToStackSlot(*MBB, MI, LR.PhysReg, SpillKill, FI, RC, TRI); + ++NumStores; // Update statistics + + // If this register is used by DBG_VALUE then insert new DBG_VALUE to + // identify spilled location as the place to find corresponding variable's + // value. + if (MachineInstr *DBG = LiveDbgValueMap.lookup(LRI->first)) { + const MDNode *MDPtr = + DBG->getOperand(DBG->getNumOperands()-1).getMetadata(); + int64_t Offset = 0; + if (DBG->getOperand(1).isImm()) + Offset = DBG->getOperand(1).getImm(); + DebugLoc DL; + if (MI == MBB->end()) { + // If MI is at basic block end then use last instruction's location. + MachineBasicBlock::iterator EI = MI; + DL = (--EI)->getDebugLoc(); + } + else + DL = MI->getDebugLoc(); + if (MachineInstr *NewDV = + TII->emitFrameIndexDebugValue(*MF, FI, Offset, MDPtr, DL)) { + MachineBasicBlock *MBB = DBG->getParent(); + MBB->insert(MI, NewDV); + DEBUG(dbgs() << "Inserting debug info due to spill:" << "\n" << *NewDV); + LiveDbgValueMap[LRI->first] = NewDV; + } + } + if (SpillKill) + LR.LastUse = 0; // Don't kill register again + } + killVirtReg(LRI); +} + +/// spillAll - Spill all dirty virtregs without killing them. +void RAFast::spillAll(MachineInstr *MI) { + if (LiveVirtRegs.empty()) return; + isBulkSpilling = true; + // The LiveRegMap is keyed by an unsigned (the virtreg number), so the order + // of spilling here is deterministic, if arbitrary. + for (LiveRegMap::iterator i = LiveVirtRegs.begin(), e = LiveVirtRegs.end(); + i != e; ++i) + spillVirtReg(MI, i); + LiveVirtRegs.clear(); + isBulkSpilling = false; +} + +/// usePhysReg - Handle the direct use of a physical register. +/// Check that the register is not used by a virtreg. +/// Kill the physreg, marking it free. +/// This may add implicit kills to MO->getParent() and invalidate MO. +void RAFast::usePhysReg(MachineOperand &MO) { + unsigned PhysReg = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(PhysReg) && + "Bad usePhysReg operand"); + + switch (PhysRegState[PhysReg]) { + case regDisabled: + break; + case regReserved: + PhysRegState[PhysReg] = regFree; + // Fall through + case regFree: + UsedInInstr.set(PhysReg); + MO.setIsKill(); + return; + default: + // The physreg was allocated to a virtual register. That means the value we + // wanted has been clobbered. + llvm_unreachable("Instruction uses an allocated register"); + } + + // Maybe a superregister is reserved? + for (const unsigned *AS = TRI->getAliasSet(PhysReg); + unsigned Alias = *AS; ++AS) { + switch (PhysRegState[Alias]) { + case regDisabled: + break; + case regReserved: + assert(TRI->isSuperRegister(PhysReg, Alias) && + "Instruction is not using a subregister of a reserved register"); + // Leave the superregister in the working set. + PhysRegState[Alias] = regFree; + UsedInInstr.set(Alias); + MO.getParent()->addRegisterKilled(Alias, TRI, true); + return; + case regFree: + if (TRI->isSuperRegister(PhysReg, Alias)) { + // Leave the superregister in the working set. + UsedInInstr.set(Alias); + MO.getParent()->addRegisterKilled(Alias, TRI, true); + return; + } + // Some other alias was in the working set - clear it. + PhysRegState[Alias] = regDisabled; + break; + default: + llvm_unreachable("Instruction uses an alias of an allocated register"); + } + } + + // All aliases are disabled, bring register into working set. + PhysRegState[PhysReg] = regFree; + UsedInInstr.set(PhysReg); + MO.setIsKill(); +} + +/// definePhysReg - Mark PhysReg as reserved or free after spilling any +/// virtregs. This is very similar to defineVirtReg except the physreg is +/// reserved instead of allocated. +void RAFast::definePhysReg(MachineInstr *MI, unsigned PhysReg, + RegState NewState) { + UsedInInstr.set(PhysReg); + switch (unsigned VirtReg = PhysRegState[PhysReg]) { + case regDisabled: + break; + default: + spillVirtReg(MI, VirtReg); + // Fall through. + case regFree: + case regReserved: + PhysRegState[PhysReg] = NewState; + return; + } + + // This is a disabled register, disable all aliases. + PhysRegState[PhysReg] = NewState; + for (const unsigned *AS = TRI->getAliasSet(PhysReg); + unsigned Alias = *AS; ++AS) { + UsedInInstr.set(Alias); + switch (unsigned VirtReg = PhysRegState[Alias]) { + case regDisabled: + break; + default: + spillVirtReg(MI, VirtReg); + // Fall through. + case regFree: + case regReserved: + PhysRegState[Alias] = regDisabled; + if (TRI->isSuperRegister(PhysReg, Alias)) + return; + break; + } + } +} + + +// calcSpillCost - Return the cost of spilling clearing out PhysReg and +// aliases so it is free for allocation. +// Returns 0 when PhysReg is free or disabled with all aliases disabled - it +// can be allocated directly. +// Returns spillImpossible when PhysReg or an alias can't be spilled. +unsigned RAFast::calcSpillCost(unsigned PhysReg) const { + if (UsedInInstr.test(PhysReg)) + return spillImpossible; + switch (unsigned VirtReg = PhysRegState[PhysReg]) { + case regDisabled: + break; + case regFree: + return 0; + case regReserved: + return spillImpossible; + default: + return LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; + } + + // This is a disabled register, add up const of aliases. + unsigned Cost = 0; + for (const unsigned *AS = TRI->getAliasSet(PhysReg); + unsigned Alias = *AS; ++AS) { + if (UsedInInstr.test(Alias)) + return spillImpossible; + switch (unsigned VirtReg = PhysRegState[Alias]) { + case regDisabled: + break; + case regFree: + ++Cost; + break; + case regReserved: + return spillImpossible; + default: + Cost += LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; + break; + } + } + return Cost; +} + + +/// assignVirtToPhysReg - This method updates local state so that we know +/// that PhysReg is the proper container for VirtReg now. The physical +/// register must not be used for anything else when this is called. +/// +void RAFast::assignVirtToPhysReg(LiveRegEntry &LRE, unsigned PhysReg) { + DEBUG(dbgs() << "Assigning " << PrintReg(LRE.first, TRI) << " to " + << PrintReg(PhysReg, TRI) << "\n"); + PhysRegState[PhysReg] = LRE.first; + assert(!LRE.second.PhysReg && "Already assigned a physreg"); + LRE.second.PhysReg = PhysReg; +} + +/// allocVirtReg - Allocate a physical register for VirtReg. +void RAFast::allocVirtReg(MachineInstr *MI, LiveRegEntry &LRE, unsigned Hint) { + const unsigned VirtReg = LRE.first; + + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Can only allocate virtual registers"); + + const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); + + // Ignore invalid hints. + if (Hint && (!TargetRegisterInfo::isPhysicalRegister(Hint) || + !RC->contains(Hint) || !Allocatable.test(Hint))) + Hint = 0; + + // Take hint when possible. + if (Hint) { + switch(calcSpillCost(Hint)) { + default: + definePhysReg(MI, Hint, regFree); + // Fall through. + case 0: + return assignVirtToPhysReg(LRE, Hint); + case spillImpossible: + break; + } + } + + TargetRegisterClass::iterator AOB = RC->allocation_order_begin(*MF); + TargetRegisterClass::iterator AOE = RC->allocation_order_end(*MF); + + // First try to find a completely free register. + for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) { + unsigned PhysReg = *I; + if (PhysRegState[PhysReg] == regFree && !UsedInInstr.test(PhysReg) && + Allocatable.test(PhysReg)) + return assignVirtToPhysReg(LRE, PhysReg); + } + + DEBUG(dbgs() << "Allocating " << PrintReg(VirtReg) << " from " + << RC->getName() << "\n"); + + unsigned BestReg = 0, BestCost = spillImpossible; + for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) { + if (!Allocatable.test(*I)) + continue; + unsigned Cost = calcSpillCost(*I); + // Cost is 0 when all aliases are already disabled. + if (Cost == 0) + return assignVirtToPhysReg(LRE, *I); + if (Cost < BestCost) + BestReg = *I, BestCost = Cost; + } + + if (BestReg) { + definePhysReg(MI, BestReg, regFree); + return assignVirtToPhysReg(LRE, BestReg); + } + + // Nothing we can do. + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Ran out of registers during register allocation!"; + if (MI->isInlineAsm()) { + Msg << "\nPlease check your inline asm statement for " + << "invalid constraints:\n"; + MI->print(Msg, TM); + } + report_fatal_error(Msg.str()); +} + +/// defineVirtReg - Allocate a register for VirtReg and mark it as dirty. +RAFast::LiveRegMap::iterator +RAFast::defineVirtReg(MachineInstr *MI, unsigned OpNum, + unsigned VirtReg, unsigned Hint) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Not a virtual register"); + LiveRegMap::iterator LRI; + bool New; + tie(LRI, New) = LiveVirtRegs.insert(std::make_pair(VirtReg, LiveReg())); + LiveReg &LR = LRI->second; + if (New) { + // If there is no hint, peek at the only use of this register. + if ((!Hint || !TargetRegisterInfo::isPhysicalRegister(Hint)) && + MRI->hasOneNonDBGUse(VirtReg)) { + const MachineInstr &UseMI = *MRI->use_nodbg_begin(VirtReg); + // It's a copy, use the destination register as a hint. + if (UseMI.isCopyLike()) + Hint = UseMI.getOperand(0).getReg(); + } + allocVirtReg(MI, *LRI, Hint); + } else if (LR.LastUse) { + // Redefining a live register - kill at the last use, unless it is this + // instruction defining VirtReg multiple times. + if (LR.LastUse != MI || LR.LastUse->getOperand(LR.LastOpNum).isUse()) + addKillFlag(LR); + } + assert(LR.PhysReg && "Register not assigned"); + LR.LastUse = MI; + LR.LastOpNum = OpNum; + LR.Dirty = true; + UsedInInstr.set(LR.PhysReg); + return LRI; +} + +/// reloadVirtReg - Make sure VirtReg is available in a physreg and return it. +RAFast::LiveRegMap::iterator +RAFast::reloadVirtReg(MachineInstr *MI, unsigned OpNum, + unsigned VirtReg, unsigned Hint) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Not a virtual register"); + LiveRegMap::iterator LRI; + bool New; + tie(LRI, New) = LiveVirtRegs.insert(std::make_pair(VirtReg, LiveReg())); + LiveReg &LR = LRI->second; + MachineOperand &MO = MI->getOperand(OpNum); + if (New) { + allocVirtReg(MI, *LRI, Hint); + const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); + int FrameIndex = getStackSpaceFor(VirtReg, RC); + DEBUG(dbgs() << "Reloading " << PrintReg(VirtReg, TRI) << " into " + << PrintReg(LR.PhysReg, TRI) << "\n"); + TII->loadRegFromStackSlot(*MBB, MI, LR.PhysReg, FrameIndex, RC, TRI); + ++NumLoads; + } else if (LR.Dirty) { + if (isLastUseOfLocalReg(MO)) { + DEBUG(dbgs() << "Killing last use: " << MO << "\n"); + if (MO.isUse()) + MO.setIsKill(); + else + MO.setIsDead(); + } else if (MO.isKill()) { + DEBUG(dbgs() << "Clearing dubious kill: " << MO << "\n"); + MO.setIsKill(false); + } else if (MO.isDead()) { + DEBUG(dbgs() << "Clearing dubious dead: " << MO << "\n"); + MO.setIsDead(false); + } + } else if (MO.isKill()) { + // We must remove kill flags from uses of reloaded registers because the + // register would be killed immediately, and there might be a second use: + // %foo = OR %x, %x + // This would cause a second reload of %x into a different register. + DEBUG(dbgs() << "Clearing clean kill: " << MO << "\n"); + MO.setIsKill(false); + } else if (MO.isDead()) { + DEBUG(dbgs() << "Clearing clean dead: " << MO << "\n"); + MO.setIsDead(false); + } + assert(LR.PhysReg && "Register not assigned"); + LR.LastUse = MI; + LR.LastOpNum = OpNum; + UsedInInstr.set(LR.PhysReg); + return LRI; +} + +// setPhysReg - Change operand OpNum in MI the refer the PhysReg, considering +// subregs. This may invalidate any operand pointers. +// Return true if the operand kills its register. +bool RAFast::setPhysReg(MachineInstr *MI, unsigned OpNum, unsigned PhysReg) { + MachineOperand &MO = MI->getOperand(OpNum); + if (!MO.getSubReg()) { + MO.setReg(PhysReg); + return MO.isKill() || MO.isDead(); + } + + // Handle subregister index. + MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : 0); + MO.setSubReg(0); + + // A kill flag implies killing the full register. Add corresponding super + // register kill. + if (MO.isKill()) { + MI->addRegisterKilled(PhysReg, TRI, true); + return true; + } + return MO.isDead(); +} + +// Handle special instruction operand like early clobbers and tied ops when +// there are additional physreg defines. +void RAFast::handleThroughOperands(MachineInstr *MI, + SmallVectorImpl &VirtDead) { + DEBUG(dbgs() << "Scanning for through registers:"); + SmallSet ThroughRegs; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (MO.isEarlyClobber() || MI->isRegTiedToDefOperand(i) || + (MO.getSubReg() && MI->readsVirtualRegister(Reg))) { + if (ThroughRegs.insert(Reg)) + DEBUG(dbgs() << ' ' << PrintReg(Reg)); + } + } + + // If any physreg defines collide with preallocated through registers, + // we must spill and reallocate. + DEBUG(dbgs() << "\nChecking for physdef collisions.\n"); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + UsedInInstr.set(Reg); + if (ThroughRegs.count(PhysRegState[Reg])) + definePhysReg(MI, Reg, regFree); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + UsedInInstr.set(*AS); + if (ThroughRegs.count(PhysRegState[*AS])) + definePhysReg(MI, *AS, regFree); + } + } + + SmallVector PartialDefs; + DEBUG(dbgs() << "Allocating tied uses and early clobbers.\n"); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; + if (MO.isUse()) { + unsigned DefIdx = 0; + if (!MI->isRegTiedToDefOperand(i, &DefIdx)) continue; + DEBUG(dbgs() << "Operand " << i << "("<< MO << ") is tied to operand " + << DefIdx << ".\n"); + LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, 0); + unsigned PhysReg = LRI->second.PhysReg; + setPhysReg(MI, i, PhysReg); + // Note: we don't update the def operand yet. That would cause the normal + // def-scan to attempt spilling. + } else if (MO.getSubReg() && MI->readsVirtualRegister(Reg)) { + DEBUG(dbgs() << "Partial redefine: " << MO << "\n"); + // Reload the register, but don't assign to the operand just yet. + // That would confuse the later phys-def processing pass. + LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, 0); + PartialDefs.push_back(LRI->second.PhysReg); + } else if (MO.isEarlyClobber()) { + // Note: defineVirtReg may invalidate MO. + LiveRegMap::iterator LRI = defineVirtReg(MI, i, Reg, 0); + unsigned PhysReg = LRI->second.PhysReg; + if (setPhysReg(MI, i, PhysReg)) + VirtDead.push_back(Reg); + } + } + + // Restore UsedInInstr to a state usable for allocating normal virtual uses. + UsedInInstr.reset(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || (MO.isDef() && !MO.isEarlyClobber())) continue; + unsigned Reg = MO.getReg(); + if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + UsedInInstr.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + UsedInInstr.set(*AS); + } + + // Also mark PartialDefs as used to avoid reallocation. + for (unsigned i = 0, e = PartialDefs.size(); i != e; ++i) + UsedInInstr.set(PartialDefs[i]); +} + +void RAFast::AllocateBasicBlock() { + DEBUG(dbgs() << "\nAllocating " << *MBB); + + // FIXME: This should probably be added by instruction selection instead? + // If the last instruction in the block is a return, make sure to mark it as + // using all of the live-out values in the function. Things marked both call + // and return are tail calls; do not do this for them. The tail callee need + // not take the same registers as input that it produces as output, and there + // are dependencies for its input registers elsewhere. + if (!MBB->empty() && MBB->back().getDesc().isReturn() && + !MBB->back().getDesc().isCall()) { + MachineInstr *Ret = &MBB->back(); + + for (MachineRegisterInfo::liveout_iterator + I = MF->getRegInfo().liveout_begin(), + E = MF->getRegInfo().liveout_end(); I != E; ++I) { + assert(TargetRegisterInfo::isPhysicalRegister(*I) && + "Cannot have a live-out virtual register."); + + // Add live-out registers as implicit uses. + Ret->addRegisterKilled(*I, TRI, true); + } + } + + PhysRegState.assign(TRI->getNumRegs(), regDisabled); + assert(LiveVirtRegs.empty() && "Mapping not cleared form last block?"); + + MachineBasicBlock::iterator MII = MBB->begin(); + + // Add live-in registers as live. + for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) + if (Allocatable.test(*I)) + definePhysReg(MII, *I, regReserved); + + SmallVector VirtDead; + SmallVector Coalesced; + + // Otherwise, sequentially allocate each instruction in the MBB. + while (MII != MBB->end()) { + MachineInstr *MI = MII++; + const TargetInstrDesc &TID = MI->getDesc(); + DEBUG({ + dbgs() << "\n>> " << *MI << "Regs:"; + for (unsigned Reg = 1, E = TRI->getNumRegs(); Reg != E; ++Reg) { + if (PhysRegState[Reg] == regDisabled) continue; + dbgs() << " " << TRI->getName(Reg); + switch(PhysRegState[Reg]) { + case regFree: + break; + case regReserved: + dbgs() << "*"; + break; + default: + dbgs() << '=' << PrintReg(PhysRegState[Reg]); + if (LiveVirtRegs[PhysRegState[Reg]].Dirty) + dbgs() << "*"; + assert(LiveVirtRegs[PhysRegState[Reg]].PhysReg == Reg && + "Bad inverse map"); + break; + } + } + dbgs() << '\n'; + // Check that LiveVirtRegs is the inverse. + for (LiveRegMap::iterator i = LiveVirtRegs.begin(), + e = LiveVirtRegs.end(); i != e; ++i) { + assert(TargetRegisterInfo::isVirtualRegister(i->first) && + "Bad map key"); + assert(TargetRegisterInfo::isPhysicalRegister(i->second.PhysReg) && + "Bad map value"); + assert(PhysRegState[i->second.PhysReg] == i->first && + "Bad inverse map"); + } + }); + + // Debug values are not allowed to change codegen in any way. + if (MI->isDebugValue()) { + bool ScanDbgValue = true; + while (ScanDbgValue) { + ScanDbgValue = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; + LiveDbgValueMap[Reg] = MI; + LiveRegMap::iterator LRI = LiveVirtRegs.find(Reg); + if (LRI != LiveVirtRegs.end()) + setPhysReg(MI, i, LRI->second.PhysReg); + else { + int SS = StackSlotForVirtReg[Reg]; + if (SS == -1) { + // We can't allocate a physreg for a DebugValue, sorry! + DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); + MO.setReg(0); + } + else { + // Modify DBG_VALUE now that the value is in a spill slot. + int64_t Offset = MI->getOperand(1).getImm(); + const MDNode *MDPtr = + MI->getOperand(MI->getNumOperands()-1).getMetadata(); + DebugLoc DL = MI->getDebugLoc(); + if (MachineInstr *NewDV = + TII->emitFrameIndexDebugValue(*MF, SS, Offset, MDPtr, DL)) { + DEBUG(dbgs() << "Modifying debug info due to spill:" << + "\t" << *MI); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MBB->erase(MI), NewDV); + // Scan NewDV operands from the beginning. + MI = NewDV; + ScanDbgValue = true; + break; + } else { + // We can't allocate a physreg for a DebugValue; sorry! + DEBUG(dbgs() << "Unable to allocate vreg used by DBG_VALUE"); + MO.setReg(0); + } + } + } + } + } + // Next instruction. + continue; + } + + // If this is a copy, we may be able to coalesce. + unsigned CopySrc = 0, CopyDst = 0, CopySrcSub = 0, CopyDstSub = 0; + if (MI->isCopy()) { + CopyDst = MI->getOperand(0).getReg(); + CopySrc = MI->getOperand(1).getReg(); + CopyDstSub = MI->getOperand(0).getSubReg(); + CopySrcSub = MI->getOperand(1).getSubReg(); + } + + // Track registers used by instruction. + UsedInInstr.reset(); + + // First scan. + // Mark physreg uses and early clobbers as used. + // Find the end of the virtreg operands + unsigned VirtOpEnd = 0; + bool hasTiedOps = false; + bool hasEarlyClobbers = false; + bool hasPartialRedefs = false; + bool hasPhysDefs = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!Reg) continue; + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + VirtOpEnd = i+1; + if (MO.isUse()) { + hasTiedOps = hasTiedOps || + TID.getOperandConstraint(i, TOI::TIED_TO) != -1; + } else { + if (MO.isEarlyClobber()) + hasEarlyClobbers = true; + if (MO.getSubReg() && MI->readsVirtualRegister(Reg)) + hasPartialRedefs = true; + } + continue; + } + if (!Allocatable.test(Reg)) continue; + if (MO.isUse()) { + usePhysReg(MO); + } else if (MO.isEarlyClobber()) { + definePhysReg(MI, Reg, (MO.isImplicit() || MO.isDead()) ? + regFree : regReserved); + hasEarlyClobbers = true; + } else + hasPhysDefs = true; + } + + // The instruction may have virtual register operands that must be allocated + // the same register at use-time and def-time: early clobbers and tied + // operands. If there are also physical defs, these registers must avoid + // both physical defs and uses, making them more constrained than normal + // operands. + // Similarly, if there are multiple defs and tied operands, we must make + // sure the same register is allocated to uses and defs. + // We didn't detect inline asm tied operands above, so just make this extra + // pass for all inline asm. + if (MI->isInlineAsm() || hasEarlyClobbers || hasPartialRedefs || + (hasTiedOps && (hasPhysDefs || TID.getNumDefs() > 1))) { + handleThroughOperands(MI, VirtDead); + // Don't attempt coalescing when we have funny stuff going on. + CopyDst = 0; + // Pretend we have early clobbers so the use operands get marked below. + // This is not necessary for the common case of a single tied use. + hasEarlyClobbers = true; + } + + // Second scan. + // Allocate virtreg uses. + for (unsigned i = 0; i != VirtOpEnd; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) continue; + if (MO.isUse()) { + LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, CopyDst); + unsigned PhysReg = LRI->second.PhysReg; + CopySrc = (CopySrc == Reg || CopySrc == PhysReg) ? PhysReg : 0; + if (setPhysReg(MI, i, PhysReg)) + killVirtReg(LRI); + } + } + + MRI->addPhysRegsUsed(UsedInInstr); + + // Track registers defined by instruction - early clobbers and tied uses at + // this point. + UsedInInstr.reset(); + if (hasEarlyClobbers) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + // Look for physreg defs and tied uses. + if (!MO.isDef() && !MI->isRegTiedToDefOperand(i)) continue; + UsedInInstr.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + UsedInInstr.set(*AS); + } + } + + unsigned DefOpEnd = MI->getNumOperands(); + if (TID.isCall()) { + // Spill all virtregs before a call. This serves two purposes: 1. If an + // exception is thrown, the landing pad is going to expect to find + // registers in their spill slots, and 2. we don't have to wade through + // all the operands on the call instruction. + DefOpEnd = VirtOpEnd; + DEBUG(dbgs() << " Spilling remaining registers before call.\n"); + spillAll(MI); + + // The imp-defs are skipped below, but we still need to mark those + // registers as used by the function. + SkippedInstrs.insert(&TID); + } + + // Third scan. + // Allocate defs and collect dead defs. + for (unsigned i = 0; i != DefOpEnd; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef() || !MO.getReg() || MO.isEarlyClobber()) + continue; + unsigned Reg = MO.getReg(); + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (!Allocatable.test(Reg)) continue; + definePhysReg(MI, Reg, (MO.isImplicit() || MO.isDead()) ? + regFree : regReserved); + continue; + } + LiveRegMap::iterator LRI = defineVirtReg(MI, i, Reg, CopySrc); + unsigned PhysReg = LRI->second.PhysReg; + if (setPhysReg(MI, i, PhysReg)) { + VirtDead.push_back(Reg); + CopyDst = 0; // cancel coalescing; + } else + CopyDst = (CopyDst == Reg || CopyDst == PhysReg) ? PhysReg : 0; + } + + // Kill dead defs after the scan to ensure that multiple defs of the same + // register are allocated identically. We didn't need to do this for uses + // because we are crerating our own kill flags, and they are always at the + // last use. + for (unsigned i = 0, e = VirtDead.size(); i != e; ++i) + killVirtReg(VirtDead[i]); + VirtDead.clear(); + + MRI->addPhysRegsUsed(UsedInInstr); + + if (CopyDst && CopyDst == CopySrc && CopyDstSub == CopySrcSub) { + DEBUG(dbgs() << "-- coalescing: " << *MI); + Coalesced.push_back(MI); + } else { + DEBUG(dbgs() << "<< " << *MI); + } + } + + // Spill all physical registers holding virtual registers now. + DEBUG(dbgs() << "Spilling live registers at end of block.\n"); + spillAll(MBB->getFirstTerminator()); + + // Erase all the coalesced copies. We are delaying it until now because + // LiveVirtRegs might refer to the instrs. + for (unsigned i = 0, e = Coalesced.size(); i != e; ++i) + MBB->erase(Coalesced[i]); + NumCopies += Coalesced.size(); + + DEBUG(MBB->dump()); +} + +/// runOnMachineFunction - Register allocate the whole function +/// +bool RAFast::runOnMachineFunction(MachineFunction &Fn) { + DEBUG(dbgs() << "********** FAST REGISTER ALLOCATION **********\n" + << "********** Function: " + << ((Value*)Fn.getFunction())->getName() << '\n'); + MF = &Fn; + MRI = &MF->getRegInfo(); + TM = &Fn.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + + UsedInInstr.resize(TRI->getNumRegs()); + Allocatable = TRI->getAllocatableSet(*MF); + + // initialize the virtual->physical register map to have a 'null' + // mapping for all virtual registers + StackSlotForVirtReg.resize(MRI->getNumVirtRegs()); + + // Loop over all of the basic blocks, eliminating virtual register references + for (MachineFunction::iterator MBBi = Fn.begin(), MBBe = Fn.end(); + MBBi != MBBe; ++MBBi) { + MBB = &*MBBi; + AllocateBasicBlock(); + } + + // Make sure the set of used physregs is closed under subreg operations. + MRI->closePhysRegsUsed(*TRI); + + // Add the clobber lists for all the instructions we skipped earlier. + for (SmallPtrSet::const_iterator + I = SkippedInstrs.begin(), E = SkippedInstrs.end(); I != E; ++I) + if (const unsigned *Defs = (*I)->getImplicitDefs()) + while (*Defs) + MRI->setPhysRegUsed(*Defs++); + + SkippedInstrs.clear(); + StackSlotForVirtReg.clear(); + LiveDbgValueMap.clear(); + return true; +} + +FunctionPass *llvm::createFastRegisterAllocator() { + return new RAFast(); +} diff --git a/final/lib/CodeGen/RegAllocGreedy.cpp b/final/lib/CodeGen/RegAllocGreedy.cpp new file mode 100644 index 00000000000..917e64049c6 --- /dev/null +++ b/final/lib/CodeGen/RegAllocGreedy.cpp @@ -0,0 +1,1286 @@ +//===-- RegAllocGreedy.cpp - greedy register allocator --------------------===// +// +// 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 RAGreedy function pass for register allocation in +// optimized builds. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "AllocationOrder.h" +#include "LiveIntervalUnion.h" +#include "LiveRangeEdit.h" +#include "RegAllocBase.h" +#include "Spiller.h" +#include "SpillPlacement.h" +#include "SplitKit.h" +#include "VirtRegMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Function.h" +#include "llvm/PassAnalysisSupport.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/EdgeBundles.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineLoopRanges.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Timer.h" + +#include + +using namespace llvm; + +STATISTIC(NumGlobalSplits, "Number of split global live ranges"); +STATISTIC(NumLocalSplits, "Number of split local live ranges"); +STATISTIC(NumReassigned, "Number of interferences reassigned"); +STATISTIC(NumEvicted, "Number of interferences evicted"); + +static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator", + createGreedyRegisterAllocator); + +namespace { +class RAGreedy : public MachineFunctionPass, public RegAllocBase { + // context + MachineFunction *MF; + BitVector ReservedRegs; + + // analyses + SlotIndexes *Indexes; + LiveStacks *LS; + MachineDominatorTree *DomTree; + MachineLoopInfo *Loops; + MachineLoopRanges *LoopRanges; + EdgeBundles *Bundles; + SpillPlacement *SpillPlacer; + + // state + std::auto_ptr SpillerInstance; + std::priority_queue > Queue; + + // Live ranges pass through a number of stages as we try to allocate them. + // Some of the stages may also create new live ranges: + // + // - Region splitting. + // - Per-block splitting. + // - Local splitting. + // - Spilling. + // + // Ranges produced by one of the stages skip the previous stages when they are + // dequeued. This improves performance because we can skip interference checks + // that are unlikely to give any results. It also guarantees that the live + // range splitting algorithm terminates, something that is otherwise hard to + // ensure. + enum LiveRangeStage { + RS_Original, ///< Never seen before, never split. + RS_Second, ///< Second time in the queue. + RS_Region, ///< Produced by region splitting. + RS_Block, ///< Produced by per-block splitting. + RS_Local, ///< Produced by local splitting. + RS_Spill ///< Produced by spilling. + }; + + IndexedMap LRStage; + + LiveRangeStage getStage(const LiveInterval &VirtReg) const { + return LiveRangeStage(LRStage[VirtReg.reg]); + } + + template + void setStage(Iterator Begin, Iterator End, LiveRangeStage NewStage) { + LRStage.resize(MRI->getNumVirtRegs()); + for (;Begin != End; ++Begin) + LRStage[(*Begin)->reg] = NewStage; + } + + // splitting state. + std::auto_ptr SA; + std::auto_ptr SE; + + /// All basic blocks where the current register is live. + SmallVector SplitConstraints; + + typedef std::pair IndexPair; + + /// Global live range splitting candidate info. + struct GlobalSplitCandidate { + unsigned PhysReg; + SmallVector Interference; + BitVector LiveBundles; + }; + + /// Candidate info for for each PhysReg in AllocationOrder. + /// This vector never shrinks, but grows to the size of the largest register + /// class. + SmallVector GlobalCand; + + /// For every instruction in SA->UseSlots, store the previous non-copy + /// instruction. + SmallVector PrevSlot; + +public: + RAGreedy(); + + /// Return the pass name. + virtual const char* getPassName() const { + return "Greedy Register Allocator"; + } + + /// RAGreedy analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + virtual Spiller &spiller() { return *SpillerInstance; } + virtual void enqueue(LiveInterval *LI); + virtual LiveInterval *dequeue(); + virtual unsigned selectOrSplit(LiveInterval&, + SmallVectorImpl&); + + /// Perform register allocation. + virtual bool runOnMachineFunction(MachineFunction &mf); + + static char ID; + +private: + bool checkUncachedInterference(LiveInterval&, unsigned); + LiveInterval *getSingleInterference(LiveInterval&, unsigned); + bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg); + + void mapGlobalInterference(unsigned, SmallVectorImpl&); + float calcSplitConstraints(const SmallVectorImpl&); + + float calcGlobalSplitCost(const BitVector&); + void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, + SmallVectorImpl&); + void calcGapWeights(unsigned, SmallVectorImpl&); + SlotIndex getPrevMappedIndex(const MachineInstr*); + void calcPrevSlots(); + unsigned nextSplitPoint(unsigned); + bool canEvictInterference(LiveInterval&, unsigned, float&); + + unsigned tryReassign(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); + unsigned tryEvict(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); + unsigned tryRegionSplit(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); + unsigned tryLocalSplit(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); + unsigned trySplit(LiveInterval&, AllocationOrder&, + SmallVectorImpl&); +}; +} // end anonymous namespace + +char RAGreedy::ID = 0; + +FunctionPass* llvm::createGreedyRegisterAllocator() { + return new RAGreedy(); +} + +RAGreedy::RAGreedy(): MachineFunctionPass(ID), LRStage(RS_Original) { + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeMachineLoopRangesPass(*PassRegistry::getPassRegistry()); + initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + initializeEdgeBundlesPass(*PassRegistry::getPassRegistry()); + initializeSpillPlacementPass(*PassRegistry::getPassRegistry()); +} + +void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + if (StrongPHIElim) + AU.addRequiredID(StrongPHIEliminationID); + AU.addRequiredTransitive(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +void RAGreedy::releaseMemory() { + SpillerInstance.reset(0); + LRStage.clear(); + RegAllocBase::releaseMemory(); +} + +void RAGreedy::enqueue(LiveInterval *LI) { + // Prioritize live ranges by size, assigning larger ranges first. + // The queue holds (size, reg) pairs. + const unsigned Size = LI->getSize(); + const unsigned Reg = LI->reg; + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Can only enqueue virtual registers"); + unsigned Prio; + + LRStage.grow(Reg); + if (LRStage[Reg] == RS_Original) + // 1st generation ranges are handled first, long -> short. + Prio = (1u << 31) + Size; + else + // Repeat offenders are handled second, short -> long + Prio = (1u << 30) - Size; + + // Boost ranges that have a physical register hint. + const unsigned Hint = VRM->getRegAllocPref(Reg); + if (TargetRegisterInfo::isPhysicalRegister(Hint)) + Prio |= (1u << 30); + + Queue.push(std::make_pair(Prio, Reg)); +} + +LiveInterval *RAGreedy::dequeue() { + if (Queue.empty()) + return 0; + LiveInterval *LI = &LIS->getInterval(Queue.top().second); + Queue.pop(); + return LI; +} + +//===----------------------------------------------------------------------===// +// Register Reassignment +//===----------------------------------------------------------------------===// + +// Check interference without using the cache. +bool RAGreedy::checkUncachedInterference(LiveInterval &VirtReg, + unsigned PhysReg) { + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { + LiveIntervalUnion::Query subQ(&VirtReg, &PhysReg2LiveUnion[*AliasI]); + if (subQ.checkInterference()) + return true; + } + return false; +} + +/// getSingleInterference - Return the single interfering virtual register +/// assigned to PhysReg. Return 0 if more than one virtual register is +/// interfering. +LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg, + unsigned PhysReg) { + // Check physreg and aliases. + LiveInterval *Interference = 0; + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + if (Q.checkInterference()) { + if (Interference) + return 0; + if (Q.collectInterferingVRegs(2) > 1) + return 0; + Interference = Q.interferingVRegs().front(); + } + } + return Interference; +} + +// Attempt to reassign this virtual register to a different physical register. +// +// FIXME: we are not yet caching these "second-level" interferences discovered +// in the sub-queries. These interferences can change with each call to +// selectOrSplit. However, we could implement a "may-interfere" cache that +// could be conservatively dirtied when we reassign or split. +// +// FIXME: This may result in a lot of alias queries. We could summarize alias +// live intervals in their parent register's live union, but it's messy. +bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg, + unsigned WantedPhysReg) { + assert(TargetRegisterInfo::isVirtualRegister(InterferingVReg.reg) && + "Can only reassign virtual registers"); + assert(TRI->regsOverlap(WantedPhysReg, VRM->getPhys(InterferingVReg.reg)) && + "inconsistent phys reg assigment"); + + AllocationOrder Order(InterferingVReg.reg, *VRM, ReservedRegs); + while (unsigned PhysReg = Order.next()) { + // Don't reassign to a WantedPhysReg alias. + if (TRI->regsOverlap(PhysReg, WantedPhysReg)) + continue; + + if (checkUncachedInterference(InterferingVReg, PhysReg)) + continue; + + // Reassign the interfering virtual reg to this physical reg. + unsigned OldAssign = VRM->getPhys(InterferingVReg.reg); + DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " << + TRI->getName(OldAssign) << " to " << TRI->getName(PhysReg) << '\n'); + unassign(InterferingVReg, OldAssign); + assign(InterferingVReg, PhysReg); + ++NumReassigned; + return true; + } + return false; +} + +/// tryReassign - Try to reassign a single interference to a different physreg. +/// @param VirtReg Currently unassigned virtual register. +/// @param Order Physregs to try. +/// @return Physreg to assign VirtReg, or 0. +unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl &NewVRegs){ + NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled); + + Order.rewind(); + while (unsigned PhysReg = Order.next()) { + LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg); + if (!InterferingVReg) + continue; + if (TargetRegisterInfo::isPhysicalRegister(InterferingVReg->reg)) + continue; + if (reassignVReg(*InterferingVReg, PhysReg)) + return PhysReg; + } + return 0; +} + + +//===----------------------------------------------------------------------===// +// Interference eviction +//===----------------------------------------------------------------------===// + +/// canEvict - Return true if all interferences between VirtReg and PhysReg can +/// be evicted. Set maxWeight to the maximal spill weight of an interference. +bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, + float &MaxWeight) { + float Weight = 0; + for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + // If there is 10 or more interferences, chances are one is smaller. + if (Q.collectInterferingVRegs(10) >= 10) + return false; + + // Check if any interfering live range is heavier than VirtReg. + for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { + LiveInterval *Intf = Q.interferingVRegs()[i]; + if (TargetRegisterInfo::isPhysicalRegister(Intf->reg)) + return false; + if (Intf->weight >= VirtReg.weight) + return false; + Weight = std::max(Weight, Intf->weight); + } + } + MaxWeight = Weight; + return true; +} + +/// tryEvict - Try to evict all interferences for a physreg. +/// @param VirtReg Currently unassigned virtual register. +/// @param Order Physregs to try. +/// @return Physreg to assign VirtReg, or 0. +unsigned RAGreedy::tryEvict(LiveInterval &VirtReg, + AllocationOrder &Order, + SmallVectorImpl &NewVRegs){ + NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled); + + // Keep track of the lightest single interference seen so far. + float BestWeight = 0; + unsigned BestPhys = 0; + + Order.rewind(); + while (unsigned PhysReg = Order.next()) { + float Weight = 0; + if (!canEvictInterference(VirtReg, PhysReg, Weight)) + continue; + + // This is an eviction candidate. + DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = " + << Weight << '\n'); + if (BestPhys && Weight >= BestWeight) + continue; + + // Best so far. + BestPhys = PhysReg; + BestWeight = Weight; + // Stop if the hint can be used. + if (Order.isHint(PhysReg)) + break; + } + + if (!BestPhys) + return 0; + + DEBUG(dbgs() << "evicting " << PrintReg(BestPhys, TRI) << " interference\n"); + for (const unsigned *AliasI = TRI->getOverlaps(BestPhys); *AliasI; ++AliasI) { + LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); + assert(Q.seenAllInterferences() && "Didn't check all interfererences."); + for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { + LiveInterval *Intf = Q.interferingVRegs()[i]; + unassign(*Intf, VRM->getPhys(Intf->reg)); + ++NumEvicted; + NewVRegs.push_back(Intf); + } + } + return BestPhys; +} + + +//===----------------------------------------------------------------------===// +// Region Splitting +//===----------------------------------------------------------------------===// + +/// mapGlobalInterference - Compute a map of the interference from PhysReg and +/// its aliases in each block in SA->LiveBlocks. +/// If LiveBlocks[i] is live-in, Ranges[i].first is the first interference. +/// If LiveBlocks[i] is live-out, Ranges[i].second is the last interference. +void RAGreedy::mapGlobalInterference(unsigned PhysReg, + SmallVectorImpl &Ranges) { + Ranges.assign(SA->LiveBlocks.size(), IndexPair()); + LiveInterval &VirtReg = const_cast(SA->getParent()); + for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) { + if (!query(VirtReg, *AI).checkInterference()) + continue; + LiveIntervalUnion::SegmentIter IntI = + PhysReg2LiveUnion[*AI].find(VirtReg.beginIndex()); + if (!IntI.valid()) + continue; + for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { + const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + IndexPair &IP = Ranges[i]; + + // Skip interference-free blocks. + if (IntI.start() >= BI.Stop) + continue; + + // First interference in block. + if (BI.LiveIn) { + IntI.advanceTo(BI.Start); + if (!IntI.valid()) + break; + if (IntI.start() >= BI.Stop) + continue; + if (!IP.first.isValid() || IntI.start() < IP.first) + IP.first = IntI.start(); + } + + // Last interference in block. + if (BI.LiveOut) { + IntI.advanceTo(BI.Stop); + if (!IntI.valid() || IntI.start() >= BI.Stop) + --IntI; + if (IntI.stop() <= BI.Start) + continue; + if (!IP.second.isValid() || IntI.stop() > IP.second) + IP.second = IntI.stop(); + } + } + } +} + +/// calcSplitConstraints - Fill out the SplitConstraints vector based on the +/// interference pattern in Intf. Return the static cost of this split, +/// assuming that all preferences in SplitConstraints are met. +float RAGreedy::calcSplitConstraints(const SmallVectorImpl &Intf) { + // Reset interference dependent info. + SplitConstraints.resize(SA->LiveBlocks.size()); + float StaticCost = 0; + for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { + SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; + IndexPair IP = Intf[i]; + + BC.Number = BI.MBB->getNumber(); + BC.Entry = (BI.Uses && BI.LiveIn) ? + SpillPlacement::PrefReg : SpillPlacement::DontCare; + BC.Exit = (BI.Uses && BI.LiveOut) ? + SpillPlacement::PrefReg : SpillPlacement::DontCare; + + // Number of spill code instructions to insert. + unsigned Ins = 0; + + // Interference for the live-in value. + if (IP.first.isValid()) { + if (IP.first <= BI.Start) + BC.Entry = SpillPlacement::MustSpill, Ins += BI.Uses; + else if (!BI.Uses) + BC.Entry = SpillPlacement::PrefSpill; + else if (IP.first < BI.FirstUse) + BC.Entry = SpillPlacement::PrefSpill, ++Ins; + else if (IP.first < (BI.LiveThrough ? BI.LastUse : BI.Kill)) + ++Ins; + } + + // Interference for the live-out value. + if (IP.second.isValid()) { + if (IP.second >= BI.LastSplitPoint) + BC.Exit = SpillPlacement::MustSpill, Ins += BI.Uses; + else if (!BI.Uses) + BC.Exit = SpillPlacement::PrefSpill; + else if (IP.second > BI.LastUse) + BC.Exit = SpillPlacement::PrefSpill, ++Ins; + else if (IP.second > (BI.LiveThrough ? BI.FirstUse : BI.Def)) + ++Ins; + } + + // Accumulate the total frequency of inserted spill code. + if (Ins) + StaticCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); + } + return StaticCost; +} + + +/// calcGlobalSplitCost - Return the global split cost of following the split +/// pattern in LiveBundles. This cost should be added to the local cost of the +/// interference pattern in SplitConstraints. +/// +float RAGreedy::calcGlobalSplitCost(const BitVector &LiveBundles) { + float GlobalCost = 0; + for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { + SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + SpillPlacement::BlockConstraint &BC = SplitConstraints[i]; + bool RegIn = LiveBundles[Bundles->getBundle(BC.Number, 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BC.Number, 1)]; + unsigned Ins = 0; + + if (!BI.Uses) + Ins += RegIn != RegOut; + else { + if (BI.LiveIn) + Ins += RegIn != (BC.Entry == SpillPlacement::PrefReg); + if (BI.LiveOut) + Ins += RegOut != (BC.Exit == SpillPlacement::PrefReg); + } + if (Ins) + GlobalCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); + } + return GlobalCost; +} + +/// splitAroundRegion - Split VirtReg around the region determined by +/// LiveBundles. Make an effort to avoid interference from PhysReg. +/// +/// The 'register' interval is going to contain as many uses as possible while +/// avoiding interference. The 'stack' interval is the complement constructed by +/// SplitEditor. It will contain the rest. +/// +void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, + const BitVector &LiveBundles, + SmallVectorImpl &NewVRegs) { + DEBUG({ + dbgs() << "Splitting around region for " << PrintReg(PhysReg, TRI) + << " with bundles"; + for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) + dbgs() << " EB#" << i; + dbgs() << ".\n"; + }); + + // First compute interference ranges in the live blocks. + SmallVector InterferenceRanges; + mapGlobalInterference(PhysReg, InterferenceRanges); + + LiveRangeEdit LREdit(VirtReg, NewVRegs); + SE->reset(LREdit); + + // Create the main cross-block interval. + SE->openIntv(); + + // First add all defs that are live out of a block. + for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { + SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + + // Should the register be live out? + if (!BI.LiveOut || !RegOut) + continue; + + IndexPair &IP = InterferenceRanges[i]; + DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " -> EB#" + << Bundles->getBundle(BI.MBB->getNumber(), 1) + << " intf [" << IP.first << ';' << IP.second << ')'); + + // The interference interval should either be invalid or overlap MBB. + assert((!IP.first.isValid() || IP.first < BI.Stop) && "Bad interference"); + assert((!IP.second.isValid() || IP.second > BI.Start) + && "Bad interference"); + + // Check interference leaving the block. + if (!IP.second.isValid()) { + // Block is interference-free. + DEBUG(dbgs() << ", no interference"); + if (!BI.Uses) { + assert(BI.LiveThrough && "No uses, but not live through block?"); + // Block is live-through without interference. + DEBUG(dbgs() << ", no uses" + << (RegIn ? ", live-through.\n" : ", stack in.\n")); + if (!RegIn) + SE->enterIntvAtEnd(*BI.MBB); + continue; + } + if (!BI.LiveThrough) { + DEBUG(dbgs() << ", not live-through.\n"); + SE->useIntv(SE->enterIntvBefore(BI.Def), BI.Stop); + continue; + } + if (!RegIn) { + // Block is live-through, but entry bundle is on the stack. + // Reload just before the first use. + DEBUG(dbgs() << ", not live-in, enter before first use.\n"); + SE->useIntv(SE->enterIntvBefore(BI.FirstUse), BI.Stop); + continue; + } + DEBUG(dbgs() << ", live-through.\n"); + continue; + } + + // Block has interference. + DEBUG(dbgs() << ", interference to " << IP.second); + + if (!BI.LiveThrough && IP.second <= BI.Def) { + // The interference doesn't reach the outgoing segment. + DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n'); + SE->useIntv(BI.Def, BI.Stop); + continue; + } + + + if (!BI.Uses) { + // No uses in block, avoid interference by reloading as late as possible. + DEBUG(dbgs() << ", no uses.\n"); + SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); + assert(SegStart >= IP.second && "Couldn't avoid interference"); + continue; + } + + if (IP.second.getBoundaryIndex() < BI.LastUse) { + // There are interference-free uses at the end of the block. + // Find the first use that can get the live-out register. + SmallVectorImpl::const_iterator UI = + std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), + IP.second.getBoundaryIndex()); + assert(UI != SA->UseSlots.end() && "Couldn't find last use"); + SlotIndex Use = *UI; + assert(Use <= BI.LastUse && "Couldn't find last use"); + // Only attempt a split befroe the last split point. + if (Use.getBaseIndex() <= BI.LastSplitPoint) { + DEBUG(dbgs() << ", free use at " << Use << ".\n"); + SlotIndex SegStart = SE->enterIntvBefore(Use); + assert(SegStart >= IP.second && "Couldn't avoid interference"); + assert(SegStart < BI.LastSplitPoint && "Impossible split point"); + SE->useIntv(SegStart, BI.Stop); + continue; + } + } + + // Interference is after the last use. + DEBUG(dbgs() << " after last use.\n"); + SlotIndex SegStart = SE->enterIntvAtEnd(*BI.MBB); + assert(SegStart >= IP.second && "Couldn't avoid interference"); + } + + // Now all defs leading to live bundles are handled, do everything else. + for (unsigned i = 0, e = SA->LiveBlocks.size(); i != e; ++i) { + SplitAnalysis::BlockInfo &BI = SA->LiveBlocks[i]; + bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; + bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + + // Is the register live-in? + if (!BI.LiveIn || !RegIn) + continue; + + // We have an incoming register. Check for interference. + IndexPair &IP = InterferenceRanges[i]; + + DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0) + << " -> BB#" << BI.MBB->getNumber()); + + // Check interference entering the block. + if (!IP.first.isValid()) { + // Block is interference-free. + DEBUG(dbgs() << ", no interference"); + if (!BI.Uses) { + assert(BI.LiveThrough && "No uses, but not live through block?"); + // Block is live-through without interference. + if (RegOut) { + DEBUG(dbgs() << ", no uses, live-through.\n"); + SE->useIntv(BI.Start, BI.Stop); + } else { + DEBUG(dbgs() << ", no uses, stack-out.\n"); + SE->leaveIntvAtTop(*BI.MBB); + } + continue; + } + if (!BI.LiveThrough) { + DEBUG(dbgs() << ", killed in block.\n"); + SE->useIntv(BI.Start, SE->leaveIntvAfter(BI.Kill)); + continue; + } + if (!RegOut) { + // Block is live-through, but exit bundle is on the stack. + // Spill immediately after the last use. + if (BI.LastUse < BI.LastSplitPoint) { + DEBUG(dbgs() << ", uses, stack-out.\n"); + SE->useIntv(BI.Start, SE->leaveIntvAfter(BI.LastUse)); + continue; + } + // The last use is after the last split point, it is probably an + // indirect jump. + DEBUG(dbgs() << ", uses at " << BI.LastUse << " after split point " + << BI.LastSplitPoint << ", stack-out.\n"); + SlotIndex SegEnd = SE->leaveIntvBefore(BI.LastSplitPoint); + SE->useIntv(BI.Start, SegEnd); + // Run a double interval from the split to the last use. + // This makes it possible to spill the complement without affecting the + // indirect branch. + SE->overlapIntv(SegEnd, BI.LastUse); + continue; + } + // Register is live-through. + DEBUG(dbgs() << ", uses, live-through.\n"); + SE->useIntv(BI.Start, BI.Stop); + continue; + } + + // Block has interference. + DEBUG(dbgs() << ", interference from " << IP.first); + + if (!BI.LiveThrough && IP.first >= BI.Kill) { + // The interference doesn't reach the outgoing segment. + DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n'); + SE->useIntv(BI.Start, BI.Kill); + continue; + } + + if (!BI.Uses) { + // No uses in block, avoid interference by spilling as soon as possible. + DEBUG(dbgs() << ", no uses.\n"); + SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); + assert(SegEnd <= IP.first && "Couldn't avoid interference"); + continue; + } + if (IP.first.getBaseIndex() > BI.FirstUse) { + // There are interference-free uses at the beginning of the block. + // Find the last use that can get the register. + SmallVectorImpl::const_iterator UI = + std::lower_bound(SA->UseSlots.begin(), SA->UseSlots.end(), + IP.first.getBaseIndex()); + assert(UI != SA->UseSlots.begin() && "Couldn't find first use"); + SlotIndex Use = (--UI)->getBoundaryIndex(); + DEBUG(dbgs() << ", free use at " << *UI << ".\n"); + SlotIndex SegEnd = SE->leaveIntvAfter(Use); + assert(SegEnd <= IP.first && "Couldn't avoid interference"); + SE->useIntv(BI.Start, SegEnd); + continue; + } + + // Interference is before the first use. + DEBUG(dbgs() << " before first use.\n"); + SlotIndex SegEnd = SE->leaveIntvAtTop(*BI.MBB); + assert(SegEnd <= IP.first && "Couldn't avoid interference"); + } + + SE->closeIntv(); + + // FIXME: Should we be more aggressive about splitting the stack region into + // per-block segments? The current approach allows the stack region to + // separate into connected components. Some components may be allocatable. + SE->finish(); + ++NumGlobalSplits; + + if (VerifyEnabled) { + MF->verify(this, "After splitting live range around region"); + +#ifndef NDEBUG + // Make sure that at least one of the new intervals can allocate to PhysReg. + // That was the whole point of splitting the live range. + bool found = false; + for (LiveRangeEdit::iterator I = LREdit.begin(), E = LREdit.end(); I != E; + ++I) + if (!checkUncachedInterference(**I, PhysReg)) { + found = true; + break; + } + assert(found && "No allocatable intervals after pointless splitting"); +#endif + } +} + +unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl &NewVRegs) { + BitVector LiveBundles, BestBundles; + float BestCost = 0; + unsigned BestReg = 0; + + Order.rewind(); + for (unsigned Cand = 0; unsigned PhysReg = Order.next(); ++Cand) { + if (GlobalCand.size() <= Cand) + GlobalCand.resize(Cand+1); + GlobalCand[Cand].PhysReg = PhysReg; + + mapGlobalInterference(PhysReg, GlobalCand[Cand].Interference); + float Cost = calcSplitConstraints(GlobalCand[Cand].Interference); + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost); + if (BestReg && Cost >= BestCost) { + DEBUG(dbgs() << " higher.\n"); + continue; + } + + SpillPlacer->placeSpills(SplitConstraints, LiveBundles); + // No live bundles, defer to splitSingleBlocks(). + if (!LiveBundles.any()) { + DEBUG(dbgs() << " no bundles.\n"); + continue; + } + + Cost += calcGlobalSplitCost(LiveBundles); + DEBUG({ + dbgs() << ", total = " << Cost << " with bundles"; + for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) + dbgs() << " EB#" << i; + dbgs() << ".\n"; + }); + if (!BestReg || Cost < BestCost) { + BestReg = PhysReg; + BestCost = 0.98f * Cost; // Prevent rounding effects. + BestBundles.swap(LiveBundles); + } + } + + if (!BestReg) + return 0; + + splitAroundRegion(VirtReg, BestReg, BestBundles, NewVRegs); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Region); + return 0; +} + + +//===----------------------------------------------------------------------===// +// Local Splitting +//===----------------------------------------------------------------------===// + + +/// calcGapWeights - Compute the maximum spill weight that needs to be evicted +/// in order to use PhysReg between two entries in SA->UseSlots. +/// +/// GapWeight[i] represents the gap between UseSlots[i] and UseSlots[i+1]. +/// +void RAGreedy::calcGapWeights(unsigned PhysReg, + SmallVectorImpl &GapWeight) { + assert(SA->LiveBlocks.size() == 1 && "Not a local interval"); + const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks.front(); + const SmallVectorImpl &Uses = SA->UseSlots; + const unsigned NumGaps = Uses.size()-1; + + // Start and end points for the interference check. + SlotIndex StartIdx = BI.LiveIn ? BI.FirstUse.getBaseIndex() : BI.FirstUse; + SlotIndex StopIdx = BI.LiveOut ? BI.LastUse.getBoundaryIndex() : BI.LastUse; + + GapWeight.assign(NumGaps, 0.0f); + + // Add interference from each overlapping register. + for (const unsigned *AI = TRI->getOverlaps(PhysReg); *AI; ++AI) { + if (!query(const_cast(SA->getParent()), *AI) + .checkInterference()) + continue; + + // We know that VirtReg is a continuous interval from FirstUse to LastUse, + // so we don't need InterferenceQuery. + // + // Interference that overlaps an instruction is counted in both gaps + // surrounding the instruction. The exception is interference before + // StartIdx and after StopIdx. + // + LiveIntervalUnion::SegmentIter IntI = PhysReg2LiveUnion[*AI].find(StartIdx); + for (unsigned Gap = 0; IntI.valid() && IntI.start() < StopIdx; ++IntI) { + // Skip the gaps before IntI. + while (Uses[Gap+1].getBoundaryIndex() < IntI.start()) + if (++Gap == NumGaps) + break; + if (Gap == NumGaps) + break; + + // Update the gaps covered by IntI. + const float weight = IntI.value()->weight; + for (; Gap != NumGaps; ++Gap) { + GapWeight[Gap] = std::max(GapWeight[Gap], weight); + if (Uses[Gap+1].getBaseIndex() >= IntI.stop()) + break; + } + if (Gap == NumGaps) + break; + } + } +} + +/// getPrevMappedIndex - Return the slot index of the last non-copy instruction +/// before MI that has a slot index. If MI is the first mapped instruction in +/// its block, return the block start index instead. +/// +SlotIndex RAGreedy::getPrevMappedIndex(const MachineInstr *MI) { + assert(MI && "Missing MachineInstr"); + const MachineBasicBlock *MBB = MI->getParent(); + MachineBasicBlock::const_iterator B = MBB->begin(), I = MI; + while (I != B) + if (!(--I)->isDebugValue() && !I->isCopy()) + return Indexes->getInstructionIndex(I); + return Indexes->getMBBStartIdx(MBB); +} + +/// calcPrevSlots - Fill in the PrevSlot array with the index of the previous +/// real non-copy instruction for each instruction in SA->UseSlots. +/// +void RAGreedy::calcPrevSlots() { + const SmallVectorImpl &Uses = SA->UseSlots; + PrevSlot.clear(); + PrevSlot.reserve(Uses.size()); + for (unsigned i = 0, e = Uses.size(); i != e; ++i) { + const MachineInstr *MI = Indexes->getInstructionFromIndex(Uses[i]); + PrevSlot.push_back(getPrevMappedIndex(MI).getDefIndex()); + } +} + +/// nextSplitPoint - Find the next index into SA->UseSlots > i such that it may +/// be beneficial to split before UseSlots[i]. +/// +/// 0 is always a valid split point +unsigned RAGreedy::nextSplitPoint(unsigned i) { + const SmallVectorImpl &Uses = SA->UseSlots; + const unsigned Size = Uses.size(); + assert(i != Size && "No split points after the end"); + // Allow split before i when Uses[i] is not adjacent to the previous use. + while (++i != Size && PrevSlot[i].getBaseIndex() <= Uses[i-1].getBaseIndex()) + ; + return i; +} + +/// tryLocalSplit - Try to split VirtReg into smaller intervals inside its only +/// basic block. +/// +unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl &NewVRegs) { + assert(SA->LiveBlocks.size() == 1 && "Not a local interval"); + const SplitAnalysis::BlockInfo &BI = SA->LiveBlocks.front(); + + // Note that it is possible to have an interval that is live-in or live-out + // while only covering a single block - A phi-def can use undef values from + // predecessors, and the block could be a single-block loop. + // We don't bother doing anything clever about such a case, we simply assume + // that the interval is continuous from FirstUse to LastUse. We should make + // sure that we don't do anything illegal to such an interval, though. + + const SmallVectorImpl &Uses = SA->UseSlots; + if (Uses.size() <= 2) + return 0; + const unsigned NumGaps = Uses.size()-1; + + DEBUG({ + dbgs() << "tryLocalSplit: "; + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + dbgs() << ' ' << SA->UseSlots[i]; + dbgs() << '\n'; + }); + + // For every use, find the previous mapped non-copy instruction. + // We use this to detect valid split points, and to estimate new interval + // sizes. + calcPrevSlots(); + + unsigned BestBefore = NumGaps; + unsigned BestAfter = 0; + float BestDiff = 0; + + const float blockFreq = SpillPlacer->getBlockFrequency(BI.MBB->getNumber()); + SmallVector GapWeight; + + Order.rewind(); + while (unsigned PhysReg = Order.next()) { + // Keep track of the largest spill weight that would need to be evicted in + // order to make use of PhysReg between UseSlots[i] and UseSlots[i+1]. + calcGapWeights(PhysReg, GapWeight); + + // Try to find the best sequence of gaps to close. + // The new spill weight must be larger than any gap interference. + + // We will split before Uses[SplitBefore] and after Uses[SplitAfter]. + unsigned SplitBefore = 0, SplitAfter = nextSplitPoint(1) - 1; + + // MaxGap should always be max(GapWeight[SplitBefore..SplitAfter-1]). + // It is the spill weight that needs to be evicted. + float MaxGap = GapWeight[0]; + for (unsigned i = 1; i != SplitAfter; ++i) + MaxGap = std::max(MaxGap, GapWeight[i]); + + for (;;) { + // Live before/after split? + const bool LiveBefore = SplitBefore != 0 || BI.LiveIn; + const bool LiveAfter = SplitAfter != NumGaps || BI.LiveOut; + + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << ' ' + << Uses[SplitBefore] << '-' << Uses[SplitAfter] + << " i=" << MaxGap); + + // Stop before the interval gets so big we wouldn't be making progress. + if (!LiveBefore && !LiveAfter) { + DEBUG(dbgs() << " all\n"); + break; + } + // Should the interval be extended or shrunk? + bool Shrink = true; + if (MaxGap < HUGE_VALF) { + // Estimate the new spill weight. + // + // Each instruction reads and writes the register, except the first + // instr doesn't read when !FirstLive, and the last instr doesn't write + // when !LastLive. + // + // We will be inserting copies before and after, so the total number of + // reads and writes is 2 * EstUses. + // + const unsigned EstUses = 2*(SplitAfter - SplitBefore) + + 2*(LiveBefore + LiveAfter); + + // Try to guess the size of the new interval. This should be trivial, + // but the slot index of an inserted copy can be a lot smaller than the + // instruction it is inserted before if there are many dead indexes + // between them. + // + // We measure the distance from the instruction before SplitBefore to + // get a conservative estimate. + // + // The final distance can still be different if inserting copies + // triggers a slot index renumbering. + // + const float EstWeight = normalizeSpillWeight(blockFreq * EstUses, + PrevSlot[SplitBefore].distance(Uses[SplitAfter])); + // Would this split be possible to allocate? + // Never allocate all gaps, we wouldn't be making progress. + float Diff = EstWeight - MaxGap; + DEBUG(dbgs() << " w=" << EstWeight << " d=" << Diff); + if (Diff > 0) { + Shrink = false; + if (Diff > BestDiff) { + DEBUG(dbgs() << " (best)"); + BestDiff = Diff; + BestBefore = SplitBefore; + BestAfter = SplitAfter; + } + } + } + + // Try to shrink. + if (Shrink) { + SplitBefore = nextSplitPoint(SplitBefore); + if (SplitBefore < SplitAfter) { + DEBUG(dbgs() << " shrink\n"); + // Recompute the max when necessary. + if (GapWeight[SplitBefore - 1] >= MaxGap) { + MaxGap = GapWeight[SplitBefore]; + for (unsigned i = SplitBefore + 1; i != SplitAfter; ++i) + MaxGap = std::max(MaxGap, GapWeight[i]); + } + continue; + } + MaxGap = 0; + } + + // Try to extend the interval. + if (SplitAfter >= NumGaps) { + DEBUG(dbgs() << " end\n"); + break; + } + + DEBUG(dbgs() << " extend\n"); + for (unsigned e = nextSplitPoint(SplitAfter + 1) - 1; + SplitAfter != e; ++SplitAfter) + MaxGap = std::max(MaxGap, GapWeight[SplitAfter]); + continue; + } + } + + // Didn't find any candidates? + if (BestBefore == NumGaps) + return 0; + + DEBUG(dbgs() << "Best local split range: " << Uses[BestBefore] + << '-' << Uses[BestAfter] << ", " << BestDiff + << ", " << (BestAfter - BestBefore + 1) << " instrs\n"); + + LiveRangeEdit LREdit(VirtReg, NewVRegs); + SE->reset(LREdit); + + SE->openIntv(); + SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]); + SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]); + SE->useIntv(SegStart, SegStop); + SE->closeIntv(); + SE->finish(); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local); + ++NumLocalSplits; + + return 0; +} + +//===----------------------------------------------------------------------===// +// Live Range Splitting +//===----------------------------------------------------------------------===// + +/// trySplit - Try to split VirtReg or one of its interferences, making it +/// assignable. +/// @return Physreg when VirtReg may be assigned and/or new NewVRegs. +unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order, + SmallVectorImpl&NewVRegs) { + // Local intervals are handled separately. + if (LIS->intervalIsInOneMBB(VirtReg)) { + NamedRegionTimer T("Local Splitting", TimerGroupName, TimePassesIsEnabled); + SA->analyze(&VirtReg); + return tryLocalSplit(VirtReg, Order, NewVRegs); + } + + NamedRegionTimer T("Global Splitting", TimerGroupName, TimePassesIsEnabled); + + // Don't iterate global splitting. + // Move straight to spilling if this range was produced by a global split. + LiveRangeStage Stage = getStage(VirtReg); + if (Stage >= RS_Block) + return 0; + + SA->analyze(&VirtReg); + + // First try to split around a region spanning multiple blocks. + if (Stage < RS_Region) { + unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); + if (PhysReg || !NewVRegs.empty()) + return PhysReg; + } + + // Then isolate blocks with multiple uses. + if (Stage < RS_Block) { + SplitAnalysis::BlockPtrSet Blocks; + if (SA->getMultiUseBlocks(Blocks)) { + LiveRangeEdit LREdit(VirtReg, NewVRegs); + SE->reset(LREdit); + SE->splitSingleBlocks(Blocks); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Block); + if (VerifyEnabled) + MF->verify(this, "After splitting live range around basic blocks"); + } + } + + // Don't assign any physregs. + return 0; +} + + +//===----------------------------------------------------------------------===// +// Main Entry Point +//===----------------------------------------------------------------------===// + +unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg, + SmallVectorImpl &NewVRegs) { + LiveRangeStage Stage = getStage(VirtReg); + if (Stage == RS_Original) + LRStage[VirtReg.reg] = RS_Second; + + // First try assigning a free register. + AllocationOrder Order(VirtReg.reg, *VRM, ReservedRegs); + while (unsigned PhysReg = Order.next()) { + if (!checkPhysRegInterference(VirtReg, PhysReg)) + return PhysReg; + } + + if (unsigned PhysReg = tryReassign(VirtReg, Order, NewVRegs)) + return PhysReg; + + if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) + return PhysReg; + + assert(NewVRegs.empty() && "Cannot append to existing NewVRegs"); + + // The first time we see a live range, don't try to split or spill. + // Wait until the second time, when all smaller ranges have been allocated. + // This gives a better picture of the interference to split around. + if (Stage == RS_Original) { + NewVRegs.push_back(&VirtReg); + return 0; + } + + assert(Stage < RS_Spill && "Cannot allocate after spilling"); + + // Try splitting VirtReg or interferences. + unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs); + if (PhysReg || !NewVRegs.empty()) + return PhysReg; + + // Finally spill VirtReg itself. + NamedRegionTimer T("Spiller", TimerGroupName, TimePassesIsEnabled); + SmallVector pendingSpills; + spiller().spill(&VirtReg, NewVRegs, pendingSpills); + + // The live virtual register requesting allocation was spilled, so tell + // the caller not to allocate anything during this round. + return 0; +} + +bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { + DEBUG(dbgs() << "********** GREEDY REGISTER ALLOCATION **********\n" + << "********** Function: " + << ((Value*)mf.getFunction())->getName() << '\n'); + + MF = &mf; + if (VerifyEnabled) + MF->verify(this, "Before greedy register allocator"); + + RegAllocBase::init(getAnalysis(), getAnalysis()); + Indexes = &getAnalysis(); + DomTree = &getAnalysis(); + ReservedRegs = TRI->getReservedRegs(*MF); + SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM)); + Loops = &getAnalysis(); + LoopRanges = &getAnalysis(); + Bundles = &getAnalysis(); + SpillPlacer = &getAnalysis(); + + SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops)); + SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree)); + LRStage.clear(); + LRStage.resize(MRI->getNumVirtRegs()); + + allocatePhysRegs(); + addMBBLiveIns(MF); + LIS->addKillFlags(); + + // Run rewriter + { + NamedRegionTimer T("Rewriter", TimerGroupName, TimePassesIsEnabled); + VRM->rewrite(Indexes); + } + + // The pass output is in VirtRegMap. Release all the transient data. + releaseMemory(); + + return true; +} diff --git a/final/lib/CodeGen/RegAllocLinearScan.cpp b/final/lib/CodeGen/RegAllocLinearScan.cpp new file mode 100644 index 00000000000..a24fc80cf5e --- /dev/null +++ b/final/lib/CodeGen/RegAllocLinearScan.cpp @@ -0,0 +1,1538 @@ +//===-- RegAllocLinearScan.cpp - Linear Scan register allocator -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a linear scan register allocator. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "LiveDebugVariables.h" +#include "VirtRegMap.h" +#include "VirtRegRewriter.h" +#include "Spiller.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include + +using namespace llvm; + +STATISTIC(NumIters , "Number of iterations performed"); +STATISTIC(NumBacktracks, "Number of times we had to backtrack"); +STATISTIC(NumCoalesce, "Number of copies coalesced"); +STATISTIC(NumDowngrade, "Number of registers downgraded"); + +static cl::opt +NewHeuristic("new-spilling-heuristic", + cl::desc("Use new spilling heuristic"), + cl::init(false), cl::Hidden); + +static cl::opt +PreSplitIntervals("pre-alloc-split", + cl::desc("Pre-register allocation live interval splitting"), + cl::init(false), cl::Hidden); + +static cl::opt +TrivCoalesceEnds("trivial-coalesce-ends", + cl::desc("Attempt trivial coalescing of interval ends"), + cl::init(false), cl::Hidden); + +static RegisterRegAlloc +linearscanRegAlloc("linearscan", "linear scan register allocator", + createLinearScanRegisterAllocator); + +namespace { + // When we allocate a register, add it to a fixed-size queue of + // registers to skip in subsequent allocations. This trades a small + // amount of register pressure and increased spills for flexibility in + // the post-pass scheduler. + // + // Note that in a the number of registers used for reloading spills + // will be one greater than the value of this option. + // + // One big limitation of this is that it doesn't differentiate between + // different register classes. So on x86-64, if there is xmm register + // pressure, it can caused fewer GPRs to be held in the queue. + static cl::opt + NumRecentlyUsedRegs("linearscan-skip-count", + cl::desc("Number of registers for linearscan to remember" + "to skip."), + cl::init(0), + cl::Hidden); + + struct RALinScan : public MachineFunctionPass { + static char ID; + RALinScan() : MachineFunctionPass(ID) { + initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry()); + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerAnalysisGroup( + *PassRegistry::getPassRegistry()); + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + initializePreAllocSplittingPass(*PassRegistry::getPassRegistry()); + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + initializeMachineDominatorTreePass(*PassRegistry::getPassRegistry()); + + // Initialize the queue to record recently-used registers. + if (NumRecentlyUsedRegs > 0) + RecentRegs.resize(NumRecentlyUsedRegs, 0); + RecentNext = RecentRegs.begin(); + } + + typedef std::pair IntervalPtr; + typedef SmallVector IntervalPtrs; + private: + /// RelatedRegClasses - This structure is built the first time a function is + /// compiled, and keeps track of which register classes have registers that + /// belong to multiple classes or have aliases that are in other classes. + EquivalenceClasses RelatedRegClasses; + DenseMap OneClassForEachPhysReg; + + // NextReloadMap - For each register in the map, it maps to the another + // register which is defined by a reload from the same stack slot and + // both reloads are in the same basic block. + DenseMap NextReloadMap; + + // DowngradedRegs - A set of registers which are being "downgraded", i.e. + // un-favored for allocation. + SmallSet DowngradedRegs; + + // DowngradeMap - A map from virtual registers to physical registers being + // downgraded for the virtual registers. + DenseMap DowngradeMap; + + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + BitVector allocatableRegs_; + BitVector reservedRegs_; + LiveIntervals* li_; + MachineLoopInfo *loopInfo; + + /// handled_ - Intervals are added to the handled_ set in the order of their + /// start value. This is uses for backtracking. + std::vector handled_; + + /// fixed_ - Intervals that correspond to machine registers. + /// + IntervalPtrs fixed_; + + /// active_ - Intervals that are currently being processed, and which have a + /// live range active for the current point. + IntervalPtrs active_; + + /// inactive_ - Intervals that are currently being processed, but which have + /// a hold at the current point. + IntervalPtrs inactive_; + + typedef std::priority_queue, + greater_ptr > IntervalHeap; + IntervalHeap unhandled_; + + /// regUse_ - Tracks register usage. + SmallVector regUse_; + SmallVector regUseBackUp_; + + /// vrm_ - Tracks register assignments. + VirtRegMap* vrm_; + + std::auto_ptr rewriter_; + + std::auto_ptr spiller_; + + // The queue of recently-used registers. + SmallVector RecentRegs; + SmallVector::iterator RecentNext; + + // Record that we just picked this register. + void recordRecentlyUsed(unsigned reg) { + assert(reg != 0 && "Recently used register is NOREG!"); + if (!RecentRegs.empty()) { + *RecentNext++ = reg; + if (RecentNext == RecentRegs.end()) + RecentNext = RecentRegs.begin(); + } + } + + public: + virtual const char* getPassName() const { + return "Linear Scan Register Allocator"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + if (StrongPHIElim) + AU.addRequiredID(StrongPHIEliminationID); + // Make sure PassManager knows which analyses to make available + // to coalescing and which analyses coalescing invalidates. + AU.addRequiredTransitive(); + AU.addRequired(); + if (PreSplitIntervals) + AU.addRequiredID(PreAllocSplittingID); + AU.addRequiredID(LiveStacksID); + AU.addPreservedID(LiveStacksID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequiredID(MachineDominatorsID); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - register allocate the whole function + bool runOnMachineFunction(MachineFunction&); + + // Determine if we skip this register due to its being recently used. + bool isRecentlyUsed(unsigned reg) const { + return std::find(RecentRegs.begin(), RecentRegs.end(), reg) != + RecentRegs.end(); + } + + private: + /// linearScan - the linear scan algorithm + void linearScan(); + + /// initIntervalSets - initialize the interval sets. + /// + void initIntervalSets(); + + /// processActiveIntervals - expire old intervals and move non-overlapping + /// ones to the inactive list. + void processActiveIntervals(SlotIndex CurPoint); + + /// processInactiveIntervals - expire old intervals and move overlapping + /// ones to the active list. + void processInactiveIntervals(SlotIndex CurPoint); + + /// hasNextReloadInterval - Return the next liveinterval that's being + /// defined by a reload from the same SS as the specified one. + LiveInterval *hasNextReloadInterval(LiveInterval *cur); + + /// DowngradeRegister - Downgrade a register for allocation. + void DowngradeRegister(LiveInterval *li, unsigned Reg); + + /// UpgradeRegister - Upgrade a register for allocation. + void UpgradeRegister(unsigned Reg); + + /// assignRegOrStackSlotAtInterval - assign a register if one + /// is available, or spill. + void assignRegOrStackSlotAtInterval(LiveInterval* cur); + + void updateSpillWeights(std::vector &Weights, + unsigned reg, float weight, + const TargetRegisterClass *RC); + + /// findIntervalsToSpill - Determine the intervals to spill for the + /// specified interval. It's passed the physical registers whose spill + /// weight is the lowest among all the registers whose live intervals + /// conflict with the interval. + void findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals); + + /// attemptTrivialCoalescing - If a simple interval is defined by a copy, + /// try to allocate the definition to the same register as the source, + /// if the register is not defined during the life time of the interval. + /// This eliminates a copy, and is used to coalesce copies which were not + /// coalesced away before allocation either due to dest and src being in + /// different register classes or because the coalescer was overly + /// conservative. + unsigned attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg); + + /// + /// Register usage / availability tracking helpers. + /// + + void initRegUses() { + regUse_.resize(tri_->getNumRegs(), 0); + regUseBackUp_.resize(tri_->getNumRegs(), 0); + } + + void finalizeRegUses() { +#ifndef NDEBUG + // Verify all the registers are "freed". + bool Error = false; + for (unsigned i = 0, e = tri_->getNumRegs(); i != e; ++i) { + if (regUse_[i] != 0) { + dbgs() << tri_->getName(i) << " is still in use!\n"; + Error = true; + } + } + if (Error) + llvm_unreachable(0); +#endif + regUse_.clear(); + regUseBackUp_.clear(); + } + + void addRegUse(unsigned physReg) { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + ++regUse_[physReg]; + for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as) + ++regUse_[*as]; + } + + void delRegUse(unsigned physReg) { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + assert(regUse_[physReg] != 0); + --regUse_[physReg]; + for (const unsigned* as = tri_->getAliasSet(physReg); *as; ++as) { + assert(regUse_[*as] != 0); + --regUse_[*as]; + } + } + + bool isRegAvail(unsigned physReg) const { + assert(TargetRegisterInfo::isPhysicalRegister(physReg) && + "should be physical register!"); + return regUse_[physReg] == 0; + } + + void backUpRegUses() { + regUseBackUp_ = regUse_; + } + + void restoreRegUses() { + regUse_ = regUseBackUp_; + } + + /// + /// Register handling helpers. + /// + + /// getFreePhysReg - return a free physical register for this virtual + /// register interval if we have one, otherwise return 0. + unsigned getFreePhysReg(LiveInterval* cur); + unsigned getFreePhysReg(LiveInterval* cur, + const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs); + + /// getFirstNonReservedPhysReg - return the first non-reserved physical + /// register in the register class. + unsigned getFirstNonReservedPhysReg(const TargetRegisterClass *RC) { + TargetRegisterClass::iterator aoe = RC->allocation_order_end(*mf_); + TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_); + while (i != aoe && reservedRegs_.test(*i)) + ++i; + assert(i != aoe && "All registers reserved?!"); + return *i; + } + + void ComputeRelatedRegClasses(); + + template + void printIntervals(const char* const str, ItTy i, ItTy e) const { + DEBUG({ + if (str) + dbgs() << str << " intervals:\n"; + + for (; i != e; ++i) { + dbgs() << "\t" << *i->first << " -> "; + + unsigned reg = i->first->reg; + if (TargetRegisterInfo::isVirtualRegister(reg)) + reg = vrm_->getPhys(reg); + + dbgs() << tri_->getName(reg) << '\n'; + } + }); + } + }; + char RALinScan::ID = 0; +} + +INITIALIZE_PASS_BEGIN(RALinScan, "linearscan-regalloc", + "Linear Scan Register Allocator", false, false) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) +INITIALIZE_PASS_DEPENDENCY(CalculateSpillWeights) +INITIALIZE_PASS_DEPENDENCY(PreAllocSplitting) +INITIALIZE_PASS_DEPENDENCY(LiveStacks) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(VirtRegMap) +INITIALIZE_AG_DEPENDENCY(RegisterCoalescer) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(RALinScan, "linearscan-regalloc", + "Linear Scan Register Allocator", false, false) + +void RALinScan::ComputeRelatedRegClasses() { + // First pass, add all reg classes to the union, and determine at least one + // reg class that each register is in. + bool HasAliases = false; + for (TargetRegisterInfo::regclass_iterator RCI = tri_->regclass_begin(), + E = tri_->regclass_end(); RCI != E; ++RCI) { + RelatedRegClasses.insert(*RCI); + for (TargetRegisterClass::iterator I = (*RCI)->begin(), E = (*RCI)->end(); + I != E; ++I) { + HasAliases = HasAliases || *tri_->getAliasSet(*I) != 0; + + const TargetRegisterClass *&PRC = OneClassForEachPhysReg[*I]; + if (PRC) { + // Already processed this register. Just make sure we know that + // multiple register classes share a register. + RelatedRegClasses.unionSets(PRC, *RCI); + } else { + PRC = *RCI; + } + } + } + + // Second pass, now that we know conservatively what register classes each reg + // belongs to, add info about aliases. We don't need to do this for targets + // without register aliases. + if (HasAliases) + for (DenseMap::iterator + I = OneClassForEachPhysReg.begin(), E = OneClassForEachPhysReg.end(); + I != E; ++I) + for (const unsigned *AS = tri_->getAliasSet(I->first); *AS; ++AS) { + const TargetRegisterClass *AliasClass = + OneClassForEachPhysReg.lookup(*AS); + if (AliasClass) + RelatedRegClasses.unionSets(I->second, AliasClass); + } +} + +/// attemptTrivialCoalescing - If a simple interval is defined by a copy, try +/// allocate the definition the same register as the source register if the +/// register is not defined during live time of the interval. If the interval is +/// killed by a copy, try to use the destination register. This eliminates a +/// copy. This is used to coalesce copies which were not coalesced away before +/// allocation either due to dest and src being in different register classes or +/// because the coalescer was overly conservative. +unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { + unsigned Preference = vrm_->getRegAllocPref(cur.reg); + if ((Preference && Preference == Reg) || !cur.containsOneValue()) + return Reg; + + // We cannot handle complicated live ranges. Simple linear stuff only. + if (cur.ranges.size() != 1) + return Reg; + + const LiveRange &range = cur.ranges.front(); + + VNInfo *vni = range.valno; + if (vni->isUnused() || !vni->def.isValid()) + return Reg; + + unsigned CandReg; + { + MachineInstr *CopyMI; + if ((CopyMI = li_->getInstructionFromIndex(vni->def)) && CopyMI->isCopy()) + // Defined by a copy, try to extend SrcReg forward + CandReg = CopyMI->getOperand(1).getReg(); + else if (TrivCoalesceEnds && + (CopyMI = li_->getInstructionFromIndex(range.end.getBaseIndex())) && + CopyMI->isCopy() && cur.reg == CopyMI->getOperand(1).getReg()) + // Only used by a copy, try to extend DstReg backwards + CandReg = CopyMI->getOperand(0).getReg(); + else + return Reg; + + // If the target of the copy is a sub-register then don't coalesce. + if(CopyMI->getOperand(0).getSubReg()) + return Reg; + } + + if (TargetRegisterInfo::isVirtualRegister(CandReg)) { + if (!vrm_->isAssignedReg(CandReg)) + return Reg; + CandReg = vrm_->getPhys(CandReg); + } + if (Reg == CandReg) + return Reg; + + const TargetRegisterClass *RC = mri_->getRegClass(cur.reg); + if (!RC->contains(CandReg)) + return Reg; + + if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg)) + return Reg; + + // Try to coalesce. + DEBUG(dbgs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg) + << '\n'); + vrm_->clearVirt(cur.reg); + vrm_->assignVirt2Phys(cur.reg, CandReg); + + ++NumCoalesce; + return CandReg; +} + +bool RALinScan::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &fn.getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + allocatableRegs_ = tri_->getAllocatableSet(fn); + reservedRegs_ = tri_->getReservedRegs(fn); + li_ = &getAnalysis(); + loopInfo = &getAnalysis(); + + // We don't run the coalescer here because we have no reason to + // interact with it. If the coalescer requires interaction, it + // won't do anything. If it doesn't require interaction, we assume + // it was run as a separate pass. + + // If this is the first function compiled, compute the related reg classes. + if (RelatedRegClasses.empty()) + ComputeRelatedRegClasses(); + + // Also resize register usage trackers. + initRegUses(); + + vrm_ = &getAnalysis(); + if (!rewriter_.get()) rewriter_.reset(createVirtRegRewriter()); + + spiller_.reset(createSpiller(*this, *mf_, *vrm_)); + + initIntervalSets(); + + linearScan(); + + // Rewrite spill code and update the PhysRegsUsed set. + rewriter_->runOnMachineFunction(*mf_, *vrm_, li_); + + // Write out new DBG_VALUE instructions. + getAnalysis().emitDebugValues(vrm_); + + assert(unhandled_.empty() && "Unhandled live intervals remain!"); + + finalizeRegUses(); + + fixed_.clear(); + active_.clear(); + inactive_.clear(); + handled_.clear(); + NextReloadMap.clear(); + DowngradedRegs.clear(); + DowngradeMap.clear(); + spiller_.reset(0); + + return true; +} + +/// initIntervalSets - initialize the interval sets. +/// +void RALinScan::initIntervalSets() +{ + assert(unhandled_.empty() && fixed_.empty() && + active_.empty() && inactive_.empty() && + "interval sets should be empty on initialization"); + + handled_.reserve(li_->getNumIntervals()); + + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { + if (TargetRegisterInfo::isPhysicalRegister(i->second->reg)) { + if (!i->second->empty()) { + mri_->setPhysRegUsed(i->second->reg); + fixed_.push_back(std::make_pair(i->second, i->second->begin())); + } + } else { + if (i->second->empty()) { + assignRegOrStackSlotAtInterval(i->second); + } + else + unhandled_.push(i->second); + } + } +} + +void RALinScan::linearScan() { + // linear scan algorithm + DEBUG({ + dbgs() << "********** LINEAR SCAN **********\n" + << "********** Function: " + << mf_->getFunction()->getName() << '\n'; + printIntervals("fixed", fixed_.begin(), fixed_.end()); + }); + + while (!unhandled_.empty()) { + // pick the interval with the earliest start point + LiveInterval* cur = unhandled_.top(); + unhandled_.pop(); + ++NumIters; + DEBUG(dbgs() << "\n*** CURRENT ***: " << *cur << '\n'); + + assert(!cur->empty() && "Empty interval in unhandled set."); + + processActiveIntervals(cur->beginIndex()); + processInactiveIntervals(cur->beginIndex()); + + assert(TargetRegisterInfo::isVirtualRegister(cur->reg) && + "Can only allocate virtual registers!"); + + // Allocating a virtual register. try to find a free + // physical register or spill an interval (possibly this one) in order to + // assign it one. + assignRegOrStackSlotAtInterval(cur); + + DEBUG({ + printIntervals("active", active_.begin(), active_.end()); + printIntervals("inactive", inactive_.begin(), inactive_.end()); + }); + } + + // Expire any remaining active intervals + while (!active_.empty()) { + IntervalPtr &IP = active_.back(); + unsigned reg = IP.first->reg; + DEBUG(dbgs() << "\tinterval " << *IP.first << " expired\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + active_.pop_back(); + } + + // Expire any remaining inactive intervals + DEBUG({ + for (IntervalPtrs::reverse_iterator + i = inactive_.rbegin(); i != inactive_.rend(); ++i) + dbgs() << "\tinterval " << *i->first << " expired\n"; + }); + inactive_.clear(); + + // Add live-ins to every BB except for entry. Also perform trivial coalescing. + MachineFunction::iterator EntryMBB = mf_->begin(); + SmallVector LiveInMBBs; + for (LiveIntervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { + LiveInterval &cur = *i->second; + unsigned Reg = 0; + bool isPhys = TargetRegisterInfo::isPhysicalRegister(cur.reg); + if (isPhys) + Reg = cur.reg; + else if (vrm_->isAssignedReg(cur.reg)) + Reg = attemptTrivialCoalescing(cur, vrm_->getPhys(cur.reg)); + if (!Reg) + continue; + // Ignore splited live intervals. + if (!isPhys && vrm_->getPreSplitReg(cur.reg)) + continue; + + for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end(); + I != E; ++I) { + const LiveRange &LR = *I; + if (li_->findLiveInMBBs(LR.start, LR.end, LiveInMBBs)) { + for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i) + if (LiveInMBBs[i] != EntryMBB) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg) && + "Adding a virtual register to livein set?"); + LiveInMBBs[i]->addLiveIn(Reg); + } + LiveInMBBs.clear(); + } + } + } + + DEBUG(dbgs() << *vrm_); + + // Look for physical registers that end up not being allocated even though + // register allocator had to spill other registers in its register class. + if (!vrm_->FindUnusedRegisters(li_)) + return; +} + +/// processActiveIntervals - expire old intervals and move non-overlapping ones +/// to the inactive list. +void RALinScan::processActiveIntervals(SlotIndex CurPoint) +{ + DEBUG(dbgs() << "\tprocessing active intervals:\n"); + + for (unsigned i = 0, e = active_.size(); i != e; ++i) { + LiveInterval *Interval = active_[i].first; + LiveInterval::iterator IntervalPos = active_[i].second; + unsigned reg = Interval->reg; + + IntervalPos = Interval->advanceTo(IntervalPos, CurPoint); + + if (IntervalPos == Interval->end()) { // Remove expired intervals. + DEBUG(dbgs() << "\t\tinterval " << *Interval << " expired\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + + // Pop off the end of the list. + active_[i] = active_.back(); + active_.pop_back(); + --i; --e; + + } else if (IntervalPos->start > CurPoint) { + // Move inactive intervals to inactive list. + DEBUG(dbgs() << "\t\tinterval " << *Interval << " inactive\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + delRegUse(reg); + // add to inactive. + inactive_.push_back(std::make_pair(Interval, IntervalPos)); + + // Pop off the end of the list. + active_[i] = active_.back(); + active_.pop_back(); + --i; --e; + } else { + // Otherwise, just update the iterator position. + active_[i].second = IntervalPos; + } + } +} + +/// processInactiveIntervals - expire old intervals and move overlapping +/// ones to the active list. +void RALinScan::processInactiveIntervals(SlotIndex CurPoint) +{ + DEBUG(dbgs() << "\tprocessing inactive intervals:\n"); + + for (unsigned i = 0, e = inactive_.size(); i != e; ++i) { + LiveInterval *Interval = inactive_[i].first; + LiveInterval::iterator IntervalPos = inactive_[i].second; + unsigned reg = Interval->reg; + + IntervalPos = Interval->advanceTo(IntervalPos, CurPoint); + + if (IntervalPos == Interval->end()) { // remove expired intervals. + DEBUG(dbgs() << "\t\tinterval " << *Interval << " expired\n"); + + // Pop off the end of the list. + inactive_[i] = inactive_.back(); + inactive_.pop_back(); + --i; --e; + } else if (IntervalPos->start <= CurPoint) { + // move re-activated intervals in active list + DEBUG(dbgs() << "\t\tinterval " << *Interval << " active\n"); + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + addRegUse(reg); + // add to active + active_.push_back(std::make_pair(Interval, IntervalPos)); + + // Pop off the end of the list. + inactive_[i] = inactive_.back(); + inactive_.pop_back(); + --i; --e; + } else { + // Otherwise, just update the iterator position. + inactive_[i].second = IntervalPos; + } + } +} + +/// updateSpillWeights - updates the spill weights of the specifed physical +/// register and its weight. +void RALinScan::updateSpillWeights(std::vector &Weights, + unsigned reg, float weight, + const TargetRegisterClass *RC) { + SmallSet Processed; + SmallSet SuperAdded; + SmallVector Supers; + Weights[reg] += weight; + Processed.insert(reg); + for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) { + Weights[*as] += weight; + Processed.insert(*as); + if (tri_->isSubRegister(*as, reg) && + SuperAdded.insert(*as) && + RC->contains(*as)) { + Supers.push_back(*as); + } + } + + // If the alias is a super-register, and the super-register is in the + // register class we are trying to allocate. Then add the weight to all + // sub-registers of the super-register even if they are not aliases. + // e.g. allocating for GR32, bh is not used, updating bl spill weight. + // bl should get the same spill weight otherwise it will be choosen + // as a spill candidate since spilling bh doesn't make ebx available. + for (unsigned i = 0, e = Supers.size(); i != e; ++i) { + for (const unsigned *sr = tri_->getSubRegisters(Supers[i]); *sr; ++sr) + if (!Processed.count(*sr)) + Weights[*sr] += weight; + } +} + +static +RALinScan::IntervalPtrs::iterator +FindIntervalInVector(RALinScan::IntervalPtrs &IP, LiveInterval *LI) { + for (RALinScan::IntervalPtrs::iterator I = IP.begin(), E = IP.end(); + I != E; ++I) + if (I->first == LI) return I; + return IP.end(); +} + +static void RevertVectorIteratorsTo(RALinScan::IntervalPtrs &V, + SlotIndex Point){ + for (unsigned i = 0, e = V.size(); i != e; ++i) { + RALinScan::IntervalPtr &IP = V[i]; + LiveInterval::iterator I = std::upper_bound(IP.first->begin(), + IP.second, Point); + if (I != IP.first->begin()) --I; + IP.second = I; + } +} + +/// getConflictWeight - Return the number of conflicts between cur +/// live interval and defs and uses of Reg weighted by loop depthes. +static +float getConflictWeight(LiveInterval *cur, unsigned Reg, LiveIntervals *li_, + MachineRegisterInfo *mri_, + MachineLoopInfo *loopInfo) { + float Conflicts = 0; + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(Reg), + E = mri_->reg_end(); I != E; ++I) { + MachineInstr *MI = &*I; + if (cur->liveAt(li_->getInstructionIndex(MI))) { + unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent()); + Conflicts += std::pow(10.0f, (float)loopDepth); + } + } + return Conflicts; +} + +/// findIntervalsToSpill - Determine the intervals to spill for the +/// specified interval. It's passed the physical registers whose spill +/// weight is the lowest among all the registers whose live intervals +/// conflict with the interval. +void RALinScan::findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals) { + // We have figured out the *best* register to spill. But there are other + // registers that are pretty good as well (spill weight within 3%). Spill + // the one that has fewest defs and uses that conflict with cur. + float Conflicts[3] = { 0.0f, 0.0f, 0.0f }; + SmallVector SLIs[3]; + + DEBUG({ + dbgs() << "\tConsidering " << NumCands << " candidates: "; + for (unsigned i = 0; i != NumCands; ++i) + dbgs() << tri_->getName(Candidates[i].first) << " "; + dbgs() << "\n"; + }); + + // Calculate the number of conflicts of each candidate. + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){ + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second-1)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + // Which is the best candidate? + unsigned BestCandidate = 0; + float MinConflicts = Conflicts[0]; + for (unsigned i = 1; i != NumCands; ++i) { + if (Conflicts[i] < MinConflicts) { + BestCandidate = i; + MinConflicts = Conflicts[i]; + } + } + + std::copy(SLIs[BestCandidate].begin(), SLIs[BestCandidate].end(), + std::back_inserter(SpillIntervals)); +} + +namespace { + struct WeightCompare { + private: + const RALinScan &Allocator; + + public: + WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {} + + typedef std::pair RegWeightPair; + bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const { + return LHS.second < RHS.second && !Allocator.isRecentlyUsed(LHS.first); + } + }; +} + +static bool weightsAreClose(float w1, float w2) { + if (!NewHeuristic) + return false; + + float diff = w1 - w2; + if (diff <= 0.02f) // Within 0.02f + return true; + return (diff / w2) <= 0.05f; // Within 5%. +} + +LiveInterval *RALinScan::hasNextReloadInterval(LiveInterval *cur) { + DenseMap::iterator I = NextReloadMap.find(cur->reg); + if (I == NextReloadMap.end()) + return 0; + return &li_->getInterval(I->second); +} + +void RALinScan::DowngradeRegister(LiveInterval *li, unsigned Reg) { + for (const unsigned *AS = tri_->getOverlaps(Reg); *AS; ++AS) { + bool isNew = DowngradedRegs.insert(*AS); + (void)isNew; // Silence compiler warning. + assert(isNew && "Multiple reloads holding the same register?"); + DowngradeMap.insert(std::make_pair(li->reg, *AS)); + } + ++NumDowngrade; +} + +void RALinScan::UpgradeRegister(unsigned Reg) { + if (Reg) { + DowngradedRegs.erase(Reg); + for (const unsigned *AS = tri_->getAliasSet(Reg); *AS; ++AS) + DowngradedRegs.erase(*AS); + } +} + +namespace { + struct LISorter { + bool operator()(LiveInterval* A, LiveInterval* B) { + return A->beginIndex() < B->beginIndex(); + } + }; +} + +/// assignRegOrStackSlotAtInterval - assign a register if one is available, or +/// spill. +void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) { + const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); + DEBUG(dbgs() << "\tallocating current interval from " + << RC->getName() << ": "); + + // This is an implicitly defined live interval, just assign any register. + if (cur->empty()) { + unsigned physReg = vrm_->getRegAllocPref(cur->reg); + if (!physReg) + physReg = getFirstNonReservedPhysReg(RC); + DEBUG(dbgs() << tri_->getName(physReg) << '\n'); + // Note the register is not really in use. + vrm_->assignVirt2Phys(cur->reg, physReg); + return; + } + + backUpRegUses(); + + std::vector > SpillWeightsToAdd; + SlotIndex StartPosition = cur->beginIndex(); + const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC); + + // If start of this live interval is defined by a move instruction and its + // source is assigned a physical register that is compatible with the target + // register class, then we should try to assign it the same register. + // This can happen when the move is from a larger register class to a smaller + // one, e.g. X86::mov32to32_. These move instructions are not coalescable. + if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) { + VNInfo *vni = cur->begin()->valno; + if (!vni->isUnused() && vni->def.isValid()) { + MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); + if (CopyMI && CopyMI->isCopy()) { + unsigned DstSubReg = CopyMI->getOperand(0).getSubReg(); + unsigned SrcReg = CopyMI->getOperand(1).getReg(); + unsigned SrcSubReg = CopyMI->getOperand(1).getSubReg(); + unsigned Reg = 0; + if (TargetRegisterInfo::isPhysicalRegister(SrcReg)) + Reg = SrcReg; + else if (vrm_->isAssignedReg(SrcReg)) + Reg = vrm_->getPhys(SrcReg); + if (Reg) { + if (SrcSubReg) + Reg = tri_->getSubReg(Reg, SrcSubReg); + if (DstSubReg) + Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC); + if (Reg && allocatableRegs_[Reg] && RC->contains(Reg)) + mri_->setRegAllocationHint(cur->reg, 0, Reg); + } + } + } + } + + // For every interval in inactive we overlap with, mark the + // register as not free and update spill weights. + for (IntervalPtrs::const_iterator i = inactive_.begin(), + e = inactive_.end(); i != e; ++i) { + unsigned Reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(Reg) && + "Can only allocate virtual registers!"); + const TargetRegisterClass *RegRC = mri_->getRegClass(Reg); + // If this is not in a related reg class to the register we're allocating, + // don't check it. + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader && + cur->overlapsFrom(*i->first, i->second-1)) { + Reg = vrm_->getPhys(Reg); + addRegUse(Reg); + SpillWeightsToAdd.push_back(std::make_pair(Reg, i->first->weight)); + } + } + + // Speculatively check to see if we can get a register right now. If not, + // we know we won't be able to by adding more constraints. If so, we can + // check to see if it is valid. Doing an exhaustive search of the fixed_ list + // is very bad (it contains all callee clobbered registers for any functions + // with a call), so we want to avoid doing that if possible. + unsigned physReg = getFreePhysReg(cur); + unsigned BestPhysReg = physReg; + if (physReg) { + // We got a register. However, if it's in the fixed_ list, we might + // conflict with it. Check to see if we conflict with it or any of its + // aliases. + SmallSet RegAliases; + for (const unsigned *AS = tri_->getAliasSet(physReg); *AS; ++AS) + RegAliases.insert(*AS); + + bool ConflictsWithFixed = false; + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + if (physReg == IP.first->reg || RegAliases.count(IP.first->reg)) { + // Okay, this reg is on the fixed list. Check to see if we actually + // conflict. + LiveInterval *I = IP.first; + if (I->endIndex() > StartPosition) { + LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition); + IP.second = II; + if (II != I->begin() && II->start > StartPosition) + --II; + if (cur->overlapsFrom(*I, II)) { + ConflictsWithFixed = true; + break; + } + } + } + } + + // Okay, the register picked by our speculative getFreePhysReg call turned + // out to be in use. Actually add all of the conflicting fixed registers to + // regUse_ so we can do an accurate query. + if (ConflictsWithFixed) { + // For every interval in fixed we overlap with, mark the register as not + // free and update spill weights. + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + LiveInterval *I = IP.first; + + const TargetRegisterClass *RegRC = OneClassForEachPhysReg[I->reg]; + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader && + I->endIndex() > StartPosition) { + LiveInterval::iterator II = I->advanceTo(IP.second, StartPosition); + IP.second = II; + if (II != I->begin() && II->start > StartPosition) + --II; + if (cur->overlapsFrom(*I, II)) { + unsigned reg = I->reg; + addRegUse(reg); + SpillWeightsToAdd.push_back(std::make_pair(reg, I->weight)); + } + } + } + + // Using the newly updated regUse_ object, which includes conflicts in the + // future, see if there are any registers available. + physReg = getFreePhysReg(cur); + } + } + + // Restore the physical register tracker, removing information about the + // future. + restoreRegUses(); + + // If we find a free register, we are done: assign this virtual to + // the free physical register and add this interval to the active + // list. + if (physReg) { + DEBUG(dbgs() << tri_->getName(physReg) << '\n'); + vrm_->assignVirt2Phys(cur->reg, physReg); + addRegUse(physReg); + active_.push_back(std::make_pair(cur, cur->begin())); + handled_.push_back(cur); + + // "Upgrade" the physical register since it has been allocated. + UpgradeRegister(physReg); + if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) { + // "Downgrade" physReg to try to keep physReg from being allocated until + // the next reload from the same SS is allocated. + mri_->setRegAllocationHint(NextReloadLI->reg, 0, physReg); + DowngradeRegister(cur, physReg); + } + return; + } + DEBUG(dbgs() << "no free registers\n"); + + // Compile the spill weights into an array that is better for scanning. + std::vector SpillWeights(tri_->getNumRegs(), 0.0f); + for (std::vector >::iterator + I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I) + updateSpillWeights(SpillWeights, I->first, I->second, RC); + + // for each interval in active, update spill weights. + for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end(); + i != e; ++i) { + unsigned reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + reg = vrm_->getPhys(reg); + updateSpillWeights(SpillWeights, reg, i->first->weight, RC); + } + + DEBUG(dbgs() << "\tassigning stack slot at interval "<< *cur << ":\n"); + + // Find a register to spill. + float minWeight = HUGE_VALF; + unsigned minReg = 0; + + bool Found = false; + std::vector > RegsWeights; + if (!minReg || SpillWeights[minReg] == HUGE_VALF) + for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), + e = RC->allocation_order_end(*mf_); i != e; ++i) { + unsigned reg = *i; + float regWeight = SpillWeights[reg]; + // Don't even consider reserved regs. + if (reservedRegs_.test(reg)) + continue; + // Skip recently allocated registers and reserved registers. + if (minWeight > regWeight && !isRecentlyUsed(reg)) + Found = true; + RegsWeights.push_back(std::make_pair(reg, regWeight)); + } + + // If we didn't find a register that is spillable, try aliases? + if (!Found) { + for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), + e = RC->allocation_order_end(*mf_); i != e; ++i) { + unsigned reg = *i; + if (reservedRegs_.test(reg)) + continue; + // No need to worry about if the alias register size < regsize of RC. + // We are going to spill all registers that alias it anyway. + for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) + RegsWeights.push_back(std::make_pair(*as, SpillWeights[*as])); + } + } + + // Sort all potential spill candidates by weight. + std::sort(RegsWeights.begin(), RegsWeights.end(), WeightCompare(*this)); + minReg = RegsWeights[0].first; + minWeight = RegsWeights[0].second; + if (minWeight == HUGE_VALF) { + // All registers must have inf weight. Just grab one! + minReg = BestPhysReg ? BestPhysReg : getFirstNonReservedPhysReg(RC); + if (cur->weight == HUGE_VALF || + li_->getApproximateInstructionCount(*cur) == 0) { + // Spill a physical register around defs and uses. + if (li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_)) { + // spillPhysRegAroundRegDefsUses may have invalidated iterator stored + // in fixed_. Reset them. + for (unsigned i = 0, e = fixed_.size(); i != e; ++i) { + IntervalPtr &IP = fixed_[i]; + LiveInterval *I = IP.first; + if (I->reg == minReg || tri_->isSubRegister(minReg, I->reg)) + IP.second = I->advanceTo(I->begin(), StartPosition); + } + + DowngradedRegs.clear(); + assignRegOrStackSlotAtInterval(cur); + } else { + assert(false && "Ran out of registers during register allocation!"); + report_fatal_error("Ran out of registers during register allocation!"); + } + return; + } + } + + // Find up to 3 registers to consider as spill candidates. + unsigned LastCandidate = RegsWeights.size() >= 3 ? 3 : 1; + while (LastCandidate > 1) { + if (weightsAreClose(RegsWeights[LastCandidate-1].second, minWeight)) + break; + --LastCandidate; + } + + DEBUG({ + dbgs() << "\t\tregister(s) with min weight(s): "; + + for (unsigned i = 0; i != LastCandidate; ++i) + dbgs() << tri_->getName(RegsWeights[i].first) + << " (" << RegsWeights[i].second << ")\n"; + }); + + // If the current has the minimum weight, we need to spill it and + // add any added intervals back to unhandled, and restart + // linearscan. + if (cur->weight != HUGE_VALF && cur->weight <= minWeight) { + DEBUG(dbgs() << "\t\t\tspilling(c): " << *cur << '\n'); + SmallVector spillIs, added; + spiller_->spill(cur, added, spillIs); + + std::sort(added.begin(), added.end(), LISorter()); + if (added.empty()) + return; // Early exit if all spills were folded. + + // Merge added with unhandled. Note that we have already sorted + // intervals returned by addIntervalsForSpills by their starting + // point. + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + SlotIndex ReloadIdx = ReloadLi->beginIndex(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginIndex() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } + return; + } + + ++NumBacktracks; + + // Push the current interval back to unhandled since we are going + // to re-run at least this iteration. Since we didn't modify it it + // should go back right in the front of the list + unhandled_.push(cur); + + assert(TargetRegisterInfo::isPhysicalRegister(minReg) && + "did not choose a register to spill?"); + + // We spill all intervals aliasing the register with + // minimum weight, rollback to the interval with the earliest + // start point and let the linear scan algorithm run again + SmallVector spillIs; + + // Determine which intervals have to be spilled. + findIntervalsToSpill(cur, RegsWeights, LastCandidate, spillIs); + + // Set of spilled vregs (used later to rollback properly) + SmallSet spilled; + + // The earliest start of a Spilled interval indicates up to where + // in handled we need to roll back + assert(!spillIs.empty() && "No spill intervals?"); + SlotIndex earliestStart = spillIs[0]->beginIndex(); + + // Spill live intervals of virtual regs mapped to the physical register we + // want to clear (and its aliases). We only spill those that overlap with the + // current interval as the rest do not affect its allocation. we also keep + // track of the earliest start of all spilled live intervals since this will + // mark our rollback point. + SmallVector added; + while (!spillIs.empty()) { + LiveInterval *sli = spillIs.back(); + spillIs.pop_back(); + DEBUG(dbgs() << "\t\t\tspilling(a): " << *sli << '\n'); + if (sli->beginIndex() < earliestStart) + earliestStart = sli->beginIndex(); + spiller_->spill(sli, added, spillIs); + spilled.insert(sli->reg); + } + + // Include any added intervals in earliestStart. + for (unsigned i = 0, e = added.size(); i != e; ++i) { + SlotIndex SI = added[i]->beginIndex(); + if (SI < earliestStart) + earliestStart = SI; + } + + DEBUG(dbgs() << "\t\trolling back to: " << earliestStart << '\n'); + + // Scan handled in reverse order up to the earliest start of a + // spilled live interval and undo each one, restoring the state of + // unhandled. + while (!handled_.empty()) { + LiveInterval* i = handled_.back(); + // If this interval starts before t we are done. + if (!i->empty() && i->beginIndex() < earliestStart) + break; + DEBUG(dbgs() << "\t\t\tundo changes for: " << *i << '\n'); + handled_.pop_back(); + + // When undoing a live interval allocation we must know if it is active or + // inactive to properly update regUse_ and the VirtRegMap. + IntervalPtrs::iterator it; + if ((it = FindIntervalInVector(active_, i)) != active_.end()) { + active_.erase(it); + assert(!TargetRegisterInfo::isPhysicalRegister(i->reg)); + if (!spilled.count(i->reg)) + unhandled_.push(i); + delRegUse(vrm_->getPhys(i->reg)); + vrm_->clearVirt(i->reg); + } else if ((it = FindIntervalInVector(inactive_, i)) != inactive_.end()) { + inactive_.erase(it); + assert(!TargetRegisterInfo::isPhysicalRegister(i->reg)); + if (!spilled.count(i->reg)) + unhandled_.push(i); + vrm_->clearVirt(i->reg); + } else { + assert(TargetRegisterInfo::isVirtualRegister(i->reg) && + "Can only allocate virtual registers!"); + vrm_->clearVirt(i->reg); + unhandled_.push(i); + } + + DenseMap::iterator ii = DowngradeMap.find(i->reg); + if (ii == DowngradeMap.end()) + // It interval has a preference, it must be defined by a copy. Clear the + // preference now since the source interval allocation may have been + // undone as well. + mri_->setRegAllocationHint(i->reg, 0, 0); + else { + UpgradeRegister(ii->second); + } + } + + // Rewind the iterators in the active, inactive, and fixed lists back to the + // point we reverted to. + RevertVectorIteratorsTo(active_, earliestStart); + RevertVectorIteratorsTo(inactive_, earliestStart); + RevertVectorIteratorsTo(fixed_, earliestStart); + + // Scan the rest and undo each interval that expired after t and + // insert it in active (the next iteration of the algorithm will + // put it in inactive if required) + for (unsigned i = 0, e = handled_.size(); i != e; ++i) { + LiveInterval *HI = handled_[i]; + if (!HI->expiredAt(earliestStart) && + HI->expiredAt(cur->beginIndex())) { + DEBUG(dbgs() << "\t\t\tundo changes for: " << *HI << '\n'); + active_.push_back(std::make_pair(HI, HI->begin())); + assert(!TargetRegisterInfo::isPhysicalRegister(HI->reg)); + addRegUse(vrm_->getPhys(HI->reg)); + } + } + + // Merge added with unhandled. + // This also update the NextReloadMap. That is, it adds mapping from a + // register defined by a reload from SS to the next reload from SS in the + // same basic block. + MachineBasicBlock *LastReloadMBB = 0; + LiveInterval *LastReload = 0; + int LastReloadSS = VirtRegMap::NO_STACK_SLOT; + std::sort(added.begin(), added.end(), LISorter()); + for (unsigned i = 0, e = added.size(); i != e; ++i) { + LiveInterval *ReloadLi = added[i]; + if (ReloadLi->weight == HUGE_VALF && + li_->getApproximateInstructionCount(*ReloadLi) == 0) { + SlotIndex ReloadIdx = ReloadLi->beginIndex(); + MachineBasicBlock *ReloadMBB = li_->getMBBFromIndex(ReloadIdx); + int ReloadSS = vrm_->getStackSlot(ReloadLi->reg); + if (LastReloadMBB == ReloadMBB && LastReloadSS == ReloadSS) { + // Last reload of same SS is in the same MBB. We want to try to + // allocate both reloads the same register and make sure the reg + // isn't clobbered in between if at all possible. + assert(LastReload->beginIndex() < ReloadIdx); + NextReloadMap.insert(std::make_pair(LastReload->reg, ReloadLi->reg)); + } + LastReloadMBB = ReloadMBB; + LastReload = ReloadLi; + LastReloadSS = ReloadSS; + } + unhandled_.push(ReloadLi); + } +} + +unsigned RALinScan::getFreePhysReg(LiveInterval* cur, + const TargetRegisterClass *RC, + unsigned MaxInactiveCount, + SmallVector &inactiveCounts, + bool SkipDGRegs) { + unsigned FreeReg = 0; + unsigned FreeRegInactiveCount = 0; + + std::pair Hint = mri_->getRegAllocationHint(cur->reg); + // Resolve second part of the hint (if possible) given the current allocation. + unsigned physReg = Hint.second; + if (TargetRegisterInfo::isVirtualRegister(physReg) && vrm_->hasPhys(physReg)) + physReg = vrm_->getPhys(physReg); + + TargetRegisterClass::iterator I, E; + tie(I, E) = tri_->getAllocationOrder(RC, Hint.first, physReg, *mf_); + assert(I != E && "No allocatable register in this register class!"); + + // Scan for the first available register. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + // Skip reserved registers. + if (reservedRegs_.test(Reg)) + continue; + // Skip recently allocated registers. + if (isRegAvail(Reg) && !isRecentlyUsed(Reg)) { + FreeReg = Reg; + if (FreeReg < inactiveCounts.size()) + FreeRegInactiveCount = inactiveCounts[FreeReg]; + else + FreeRegInactiveCount = 0; + break; + } + } + + // If there are no free regs, or if this reg has the max inactive count, + // return this register. + if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount) { + // Remember what register we picked so we can skip it next time. + if (FreeReg != 0) recordRecentlyUsed(FreeReg); + return FreeReg; + } + + // Continue scanning the registers, looking for the one with the highest + // inactive count. Alkis found that this reduced register pressure very + // slightly on X86 (in rev 1.94 of this file), though this should probably be + // reevaluated now. + for (; I != E; ++I) { + unsigned Reg = *I; + // Ignore "downgraded" registers. + if (SkipDGRegs && DowngradedRegs.count(Reg)) + continue; + // Skip reserved registers. + if (reservedRegs_.test(Reg)) + continue; + if (isRegAvail(Reg) && Reg < inactiveCounts.size() && + FreeRegInactiveCount < inactiveCounts[Reg] && !isRecentlyUsed(Reg)) { + FreeReg = Reg; + FreeRegInactiveCount = inactiveCounts[Reg]; + if (FreeRegInactiveCount == MaxInactiveCount) + break; // We found the one with the max inactive count. + } + } + + // Remember what register we picked so we can skip it next time. + recordRecentlyUsed(FreeReg); + + return FreeReg; +} + +/// getFreePhysReg - return a free physical register for this virtual register +/// interval if we have one, otherwise return 0. +unsigned RALinScan::getFreePhysReg(LiveInterval *cur) { + SmallVector inactiveCounts; + unsigned MaxInactiveCount = 0; + + const TargetRegisterClass *RC = mri_->getRegClass(cur->reg); + const TargetRegisterClass *RCLeader = RelatedRegClasses.getLeaderValue(RC); + + for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end(); + i != e; ++i) { + unsigned reg = i->first->reg; + assert(TargetRegisterInfo::isVirtualRegister(reg) && + "Can only allocate virtual registers!"); + + // If this is not in a related reg class to the register we're allocating, + // don't check it. + const TargetRegisterClass *RegRC = mri_->getRegClass(reg); + if (RelatedRegClasses.getLeaderValue(RegRC) == RCLeader) { + reg = vrm_->getPhys(reg); + if (inactiveCounts.size() <= reg) + inactiveCounts.resize(reg+1); + ++inactiveCounts[reg]; + MaxInactiveCount = std::max(MaxInactiveCount, inactiveCounts[reg]); + } + } + + // If copy coalescer has assigned a "preferred" register, check if it's + // available first. + unsigned Preference = vrm_->getRegAllocPref(cur->reg); + if (Preference) { + DEBUG(dbgs() << "(preferred: " << tri_->getName(Preference) << ") "); + if (isRegAvail(Preference) && + RC->contains(Preference)) + return Preference; + } + + if (!DowngradedRegs.empty()) { + unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, + true); + if (FreeReg) + return FreeReg; + } + return getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, false); +} + +FunctionPass* llvm::createLinearScanRegisterAllocator() { + return new RALinScan(); +} diff --git a/final/lib/CodeGen/RegAllocPBQP.cpp b/final/lib/CodeGen/RegAllocPBQP.cpp new file mode 100644 index 00000000000..ea0d1fe0233 --- /dev/null +++ b/final/lib/CodeGen/RegAllocPBQP.cpp @@ -0,0 +1,720 @@ +//===------ RegAllocPBQP.cpp ---- PBQP Register Allocator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a Partitioned Boolean Quadratic Programming (PBQP) based +// register allocator for LLVM. This allocator works by constructing a PBQP +// problem representing the register allocation problem under consideration, +// solving this using a PBQP solver, and mapping the solution back to a +// register assignment. If any variables are selected for spilling then spill +// code is inserted and the process repeated. +// +// The PBQP solver (pbqp.c) provided for this allocator uses a heuristic tuned +// for register allocation. For more information on PBQP for register +// allocation, see the following papers: +// +// (1) Hames, L. and Scholz, B. 2006. Nearly optimal register allocation with +// PBQP. In Proceedings of the 7th Joint Modular Languages Conference +// (JMLC'06). LNCS, vol. 4228. Springer, New York, NY, USA. 346-361. +// +// (2) Scholz, B., Eckstein, E. 2002. Register allocation for irregular +// architectures. In Proceedings of the Joint Conference on Languages, +// Compilers and Tools for Embedded Systems (LCTES'02), ACM Press, New York, +// NY, USA, 139-148. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" + +#include "RenderMachineFunction.h" +#include "Splitter.h" +#include "VirtRegMap.h" +#include "VirtRegRewriter.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/RegAllocPBQP.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PBQP/HeuristicSolver.h" +#include "llvm/CodeGen/PBQP/Graph.h" +#include "llvm/CodeGen/PBQP/Heuristics/Briggs.h" +#include "llvm/CodeGen/RegAllocRegistry.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include +#include +#include +#include + +using namespace llvm; + +static RegisterRegAlloc +registerPBQPRepAlloc("pbqp", "PBQP register allocator", + createDefaultPBQPRegisterAllocator); + +static cl::opt +pbqpCoalescing("pbqp-coalescing", + cl::desc("Attempt coalescing during PBQP register allocation."), + cl::init(false), cl::Hidden); + +static cl::opt +pbqpPreSplitting("pbqp-pre-splitting", + cl::desc("Pre-split before PBQP register allocation."), + cl::init(false), cl::Hidden); + +namespace { + +/// +/// PBQP based allocators solve the register allocation problem by mapping +/// register allocation problems to Partitioned Boolean Quadratic +/// Programming problems. +class RegAllocPBQP : public MachineFunctionPass { +public: + + static char ID; + + /// Construct a PBQP register allocator. + RegAllocPBQP(std::auto_ptr b) + : MachineFunctionPass(ID), builder(b) { + initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); + initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); + initializeRegisterCoalescerAnalysisGroup(*PassRegistry::getPassRegistry()); + initializeCalculateSpillWeightsPass(*PassRegistry::getPassRegistry()); + initializeLiveStacksPass(*PassRegistry::getPassRegistry()); + initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeLoopSplitterPass(*PassRegistry::getPassRegistry()); + initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); + } + + /// Return the pass name. + virtual const char* getPassName() const { + return "PBQP Register Allocator"; + } + + /// PBQP analysis usage. + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + /// Perform register allocation + virtual bool runOnMachineFunction(MachineFunction &MF); + +private: + + typedef std::map LI2NodeMap; + typedef std::vector Node2LIMap; + typedef std::vector AllowedSet; + typedef std::vector AllowedSetMap; + typedef std::pair RegPair; + typedef std::map CoalesceMap; + typedef std::vector NodeVector; + typedef std::set RegSet; + + + std::auto_ptr builder; + + MachineFunction *mf; + const TargetMachine *tm; + const TargetRegisterInfo *tri; + const TargetInstrInfo *tii; + const MachineLoopInfo *loopInfo; + MachineRegisterInfo *mri; + RenderMachineFunction *rmf; + + LiveIntervals *lis; + LiveStacks *lss; + VirtRegMap *vrm; + + RegSet vregsToAlloc, emptyIntervalVRegs; + + /// \brief Finds the initial set of vreg intervals to allocate. + void findVRegIntervalsToAlloc(); + + /// \brief Adds a stack interval if the given live interval has been + /// spilled. Used to support stack slot coloring. + void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri); + + /// \brief Given a solved PBQP problem maps this solution back to a register + /// assignment. + bool mapPBQPToRegAlloc(const PBQPRAProblem &problem, + const PBQP::Solution &solution); + + /// \brief Postprocessing before final spilling. Sets basic block "live in" + /// variables. + void finalizeAlloc() const; + +}; + +char RegAllocPBQP::ID = 0; + +} // End anonymous namespace. + +unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::ConstNodeItr node) const { + Node2VReg::const_iterator vregItr = node2VReg.find(node); + assert(vregItr != node2VReg.end() && "No vreg for node."); + return vregItr->second; +} + +PBQP::Graph::NodeItr PBQPRAProblem::getNodeForVReg(unsigned vreg) const { + VReg2Node::const_iterator nodeItr = vreg2Node.find(vreg); + assert(nodeItr != vreg2Node.end() && "No node for vreg."); + return nodeItr->second; + +} + +const PBQPRAProblem::AllowedSet& + PBQPRAProblem::getAllowedSet(unsigned vreg) const { + AllowedSetMap::const_iterator allowedSetItr = allowedSets.find(vreg); + assert(allowedSetItr != allowedSets.end() && "No pregs for vreg."); + const AllowedSet &allowedSet = allowedSetItr->second; + return allowedSet; +} + +unsigned PBQPRAProblem::getPRegForOption(unsigned vreg, unsigned option) const { + assert(isPRegOption(vreg, option) && "Not a preg option."); + + const AllowedSet& allowedSet = getAllowedSet(vreg); + assert(option <= allowedSet.size() && "Option outside allowed set."); + return allowedSet[option - 1]; +} + +std::auto_ptr PBQPBuilder::build(MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs) { + + typedef std::vector LIVector; + + MachineRegisterInfo *mri = &mf->getRegInfo(); + const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); + + std::auto_ptr p(new PBQPRAProblem()); + PBQP::Graph &g = p->getGraph(); + RegSet pregs; + + // Collect the set of preg intervals, record that they're used in the MF. + for (LiveIntervals::const_iterator itr = lis->begin(), end = lis->end(); + itr != end; ++itr) { + if (TargetRegisterInfo::isPhysicalRegister(itr->first)) { + pregs.insert(itr->first); + mri->setPhysRegUsed(itr->first); + } + } + + BitVector reservedRegs = tri->getReservedRegs(*mf); + + // Iterate over vregs. + for (RegSet::const_iterator vregItr = vregs.begin(), vregEnd = vregs.end(); + vregItr != vregEnd; ++vregItr) { + unsigned vreg = *vregItr; + const TargetRegisterClass *trc = mri->getRegClass(vreg); + const LiveInterval *vregLI = &lis->getInterval(vreg); + + // Compute an initial allowed set for the current vreg. + typedef std::vector VRAllowed; + VRAllowed vrAllowed; + for (TargetRegisterClass::iterator aoItr = trc->allocation_order_begin(*mf), + aoEnd = trc->allocation_order_end(*mf); + aoItr != aoEnd; ++aoItr) { + unsigned preg = *aoItr; + if (!reservedRegs.test(preg)) { + vrAllowed.push_back(preg); + } + } + + // Remove any physical registers which overlap. + for (RegSet::const_iterator pregItr = pregs.begin(), + pregEnd = pregs.end(); + pregItr != pregEnd; ++pregItr) { + unsigned preg = *pregItr; + const LiveInterval *pregLI = &lis->getInterval(preg); + + if (pregLI->empty()) { + continue; + } + + if (!vregLI->overlaps(*pregLI)) { + continue; + } + + // Remove the register from the allowed set. + VRAllowed::iterator eraseItr = + std::find(vrAllowed.begin(), vrAllowed.end(), preg); + + if (eraseItr != vrAllowed.end()) { + vrAllowed.erase(eraseItr); + } + + // Also remove any aliases. + const unsigned *aliasItr = tri->getAliasSet(preg); + if (aliasItr != 0) { + for (; *aliasItr != 0; ++aliasItr) { + VRAllowed::iterator eraseItr = + std::find(vrAllowed.begin(), vrAllowed.end(), *aliasItr); + + if (eraseItr != vrAllowed.end()) { + vrAllowed.erase(eraseItr); + } + } + } + } + + // Construct the node. + PBQP::Graph::NodeItr node = + g.addNode(PBQP::Vector(vrAllowed.size() + 1, 0)); + + // Record the mapping and allowed set in the problem. + p->recordVReg(vreg, node, vrAllowed.begin(), vrAllowed.end()); + + PBQP::PBQPNum spillCost = (vregLI->weight != 0.0) ? + vregLI->weight : std::numeric_limits::min(); + + addSpillCosts(g.getNodeCosts(node), spillCost); + } + + for (RegSet::const_iterator vr1Itr = vregs.begin(), vrEnd = vregs.end(); + vr1Itr != vrEnd; ++vr1Itr) { + unsigned vr1 = *vr1Itr; + const LiveInterval &l1 = lis->getInterval(vr1); + const PBQPRAProblem::AllowedSet &vr1Allowed = p->getAllowedSet(vr1); + + for (RegSet::const_iterator vr2Itr = llvm::next(vr1Itr); + vr2Itr != vrEnd; ++vr2Itr) { + unsigned vr2 = *vr2Itr; + const LiveInterval &l2 = lis->getInterval(vr2); + const PBQPRAProblem::AllowedSet &vr2Allowed = p->getAllowedSet(vr2); + + assert(!l2.empty() && "Empty interval in vreg set?"); + if (l1.overlaps(l2)) { + PBQP::Graph::EdgeItr edge = + g.addEdge(p->getNodeForVReg(vr1), p->getNodeForVReg(vr2), + PBQP::Matrix(vr1Allowed.size()+1, vr2Allowed.size()+1, 0)); + + addInterferenceCosts(g.getEdgeCosts(edge), vr1Allowed, vr2Allowed, tri); + } + } + } + + return p; +} + +void PBQPBuilder::addSpillCosts(PBQP::Vector &costVec, + PBQP::PBQPNum spillCost) { + costVec[0] = spillCost; +} + +void PBQPBuilder::addInterferenceCosts( + PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + const TargetRegisterInfo *tri) { + assert(costMat.getRows() == vr1Allowed.size() + 1 && "Matrix height mismatch."); + assert(costMat.getCols() == vr2Allowed.size() + 1 && "Matrix width mismatch."); + + for (unsigned i = 0; i != vr1Allowed.size(); ++i) { + unsigned preg1 = vr1Allowed[i]; + + for (unsigned j = 0; j != vr2Allowed.size(); ++j) { + unsigned preg2 = vr2Allowed[j]; + + if (tri->regsOverlap(preg1, preg2)) { + costMat[i + 1][j + 1] = std::numeric_limits::infinity(); + } + } + } +} + +std::auto_ptr PBQPBuilderWithCoalescing::build( + MachineFunction *mf, + const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs) { + + std::auto_ptr p = PBQPBuilder::build(mf, lis, loopInfo, vregs); + PBQP::Graph &g = p->getGraph(); + + const TargetMachine &tm = mf->getTarget(); + CoalescerPair cp(*tm.getInstrInfo(), *tm.getRegisterInfo()); + + // Scan the machine function and add a coalescing cost whenever CoalescerPair + // gives the Ok. + for (MachineFunction::const_iterator mbbItr = mf->begin(), + mbbEnd = mf->end(); + mbbItr != mbbEnd; ++mbbItr) { + const MachineBasicBlock *mbb = &*mbbItr; + + for (MachineBasicBlock::const_iterator miItr = mbb->begin(), + miEnd = mbb->end(); + miItr != miEnd; ++miItr) { + const MachineInstr *mi = &*miItr; + + if (!cp.setRegisters(mi)) { + continue; // Not coalescable. + } + + if (cp.getSrcReg() == cp.getDstReg()) { + continue; // Already coalesced. + } + + unsigned dst = cp.getDstReg(), + src = cp.getSrcReg(); + + const float copyFactor = 0.5; // Cost of copy relative to load. Current + // value plucked randomly out of the air. + + PBQP::PBQPNum cBenefit = + copyFactor * LiveIntervals::getSpillWeight(false, true, + loopInfo->getLoopDepth(mbb)); + + if (cp.isPhys()) { + if (!lis->isAllocatable(dst)) { + continue; + } + + const PBQPRAProblem::AllowedSet &allowed = p->getAllowedSet(src); + unsigned pregOpt = 0; + while (pregOpt < allowed.size() && allowed[pregOpt] != dst) { + ++pregOpt; + } + if (pregOpt < allowed.size()) { + ++pregOpt; // +1 to account for spill option. + PBQP::Graph::NodeItr node = p->getNodeForVReg(src); + addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit); + } + } else { + const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst); + const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src); + PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst); + PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src); + PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2); + if (edge == g.edgesEnd()) { + edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1, + allowed2->size() + 1, + 0)); + } else { + if (g.getEdgeNode1(edge) == node2) { + std::swap(node1, node2); + std::swap(allowed1, allowed2); + } + } + + addVirtRegCoalesce(g.getEdgeCosts(edge), *allowed1, *allowed2, + cBenefit); + } + } + } + + return p; +} + +void PBQPBuilderWithCoalescing::addPhysRegCoalesce(PBQP::Vector &costVec, + unsigned pregOption, + PBQP::PBQPNum benefit) { + costVec[pregOption] += -benefit; +} + +void PBQPBuilderWithCoalescing::addVirtRegCoalesce( + PBQP::Matrix &costMat, + const PBQPRAProblem::AllowedSet &vr1Allowed, + const PBQPRAProblem::AllowedSet &vr2Allowed, + PBQP::PBQPNum benefit) { + + assert(costMat.getRows() == vr1Allowed.size() + 1 && "Size mismatch."); + assert(costMat.getCols() == vr2Allowed.size() + 1 && "Size mismatch."); + + for (unsigned i = 0; i != vr1Allowed.size(); ++i) { + unsigned preg1 = vr1Allowed[i]; + for (unsigned j = 0; j != vr2Allowed.size(); ++j) { + unsigned preg2 = vr2Allowed[j]; + + if (preg1 == preg2) { + costMat[i + 1][j + 1] += -benefit; + } + } + } +} + + +void RegAllocPBQP::getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addPreserved(); + au.addRequired(); + //au.addRequiredID(SplitCriticalEdgesID); + au.addRequired(); + au.addRequired(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + if (pbqpPreSplitting) + au.addRequired(); + au.addRequired(); + au.addRequired(); + MachineFunctionPass::getAnalysisUsage(au); +} + +void RegAllocPBQP::findVRegIntervalsToAlloc() { + + // Iterate over all live ranges. + for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); + itr != end; ++itr) { + + // Ignore physical ones. + if (TargetRegisterInfo::isPhysicalRegister(itr->first)) + continue; + + LiveInterval *li = itr->second; + + // If this live interval is non-empty we will use pbqp to allocate it. + // Empty intervals we allocate in a simple post-processing stage in + // finalizeAlloc. + if (!li->empty()) { + vregsToAlloc.insert(li->reg); + } else { + emptyIntervalVRegs.insert(li->reg); + } + } +} + +void RegAllocPBQP::addStackInterval(const LiveInterval *spilled, + MachineRegisterInfo* mri) { + int stackSlot = vrm->getStackSlot(spilled->reg); + + if (stackSlot == VirtRegMap::NO_STACK_SLOT) { + return; + } + + const TargetRegisterClass *RC = mri->getRegClass(spilled->reg); + LiveInterval &stackInterval = lss->getOrCreateInterval(stackSlot, RC); + + VNInfo *vni; + if (stackInterval.getNumValNums() != 0) { + vni = stackInterval.getValNumInfo(0); + } else { + vni = stackInterval.getNextValue( + SlotIndex(), 0, lss->getVNInfoAllocator()); + } + + LiveInterval &rhsInterval = lis->getInterval(spilled->reg); + stackInterval.MergeRangesInAsValue(rhsInterval, vni); +} + +bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem, + const PBQP::Solution &solution) { + // Set to true if we have any spills + bool anotherRoundNeeded = false; + + // Clear the existing allocation. + vrm->clearAllVirt(); + + const PBQP::Graph &g = problem.getGraph(); + // Iterate over the nodes mapping the PBQP solution to a register + // assignment. + for (PBQP::Graph::ConstNodeItr node = g.nodesBegin(), + nodeEnd = g.nodesEnd(); + node != nodeEnd; ++node) { + unsigned vreg = problem.getVRegForNode(node); + unsigned alloc = solution.getSelection(node); + + if (problem.isPRegOption(vreg, alloc)) { + unsigned preg = problem.getPRegForOption(vreg, alloc); + DEBUG(dbgs() << "VREG " << vreg << " -> " << tri->getName(preg) << "\n"); + assert(preg != 0 && "Invalid preg selected."); + vrm->assignVirt2Phys(vreg, preg); + } else if (problem.isSpillOption(vreg, alloc)) { + vregsToAlloc.erase(vreg); + const LiveInterval* spillInterval = &lis->getInterval(vreg); + double oldWeight = spillInterval->weight; + SmallVector spillIs; + rmf->rememberUseDefs(spillInterval); + std::vector newSpills = + lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm); + addStackInterval(spillInterval, mri); + rmf->rememberSpills(spillInterval, newSpills); + + (void) oldWeight; + DEBUG(dbgs() << "VREG " << vreg << " -> SPILLED (Cost: " + << oldWeight << ", New vregs: "); + + // Copy any newly inserted live intervals into the list of regs to + // allocate. + for (std::vector::const_iterator + itr = newSpills.begin(), end = newSpills.end(); + itr != end; ++itr) { + assert(!(*itr)->empty() && "Empty spill range."); + DEBUG(dbgs() << (*itr)->reg << " "); + vregsToAlloc.insert((*itr)->reg); + } + + DEBUG(dbgs() << ")\n"); + + // We need another round if spill intervals were added. + anotherRoundNeeded |= !newSpills.empty(); + } else { + assert(false && "Unknown allocation option."); + } + } + + return !anotherRoundNeeded; +} + + +void RegAllocPBQP::finalizeAlloc() const { + typedef LiveIntervals::iterator LIIterator; + typedef LiveInterval::Ranges::const_iterator LRIterator; + + // First allocate registers for the empty intervals. + for (RegSet::const_iterator + itr = emptyIntervalVRegs.begin(), end = emptyIntervalVRegs.end(); + itr != end; ++itr) { + LiveInterval *li = &lis->getInterval(*itr); + + unsigned physReg = vrm->getRegAllocPref(li->reg); + + if (physReg == 0) { + const TargetRegisterClass *liRC = mri->getRegClass(li->reg); + physReg = *liRC->allocation_order_begin(*mf); + } + + vrm->assignVirt2Phys(li->reg, physReg); + } + + // Finally iterate over the basic blocks to compute and set the live-in sets. + SmallVector liveInMBBs; + MachineBasicBlock *entryMBB = &*mf->begin(); + + for (LIIterator liItr = lis->begin(), liEnd = lis->end(); + liItr != liEnd; ++liItr) { + + const LiveInterval *li = liItr->second; + unsigned reg = 0; + + // Get the physical register for this interval + if (TargetRegisterInfo::isPhysicalRegister(li->reg)) { + reg = li->reg; + } else if (vrm->isAssignedReg(li->reg)) { + reg = vrm->getPhys(li->reg); + } else { + // Ranges which are assigned a stack slot only are ignored. + continue; + } + + if (reg == 0) { + // Filter out zero regs - they're for intervals that were spilled. + continue; + } + + // Iterate over the ranges of the current interval... + for (LRIterator lrItr = li->begin(), lrEnd = li->end(); + lrItr != lrEnd; ++lrItr) { + + // Find the set of basic blocks which this range is live into... + if (lis->findLiveInMBBs(lrItr->start, lrItr->end, liveInMBBs)) { + // And add the physreg for this interval to their live-in sets. + for (unsigned i = 0; i != liveInMBBs.size(); ++i) { + if (liveInMBBs[i] != entryMBB) { + if (!liveInMBBs[i]->isLiveIn(reg)) { + liveInMBBs[i]->addLiveIn(reg); + } + } + } + liveInMBBs.clear(); + } + } + } + +} + +bool RegAllocPBQP::runOnMachineFunction(MachineFunction &MF) { + + mf = &MF; + tm = &mf->getTarget(); + tri = tm->getRegisterInfo(); + tii = tm->getInstrInfo(); + mri = &mf->getRegInfo(); + + lis = &getAnalysis(); + lss = &getAnalysis(); + loopInfo = &getAnalysis(); + rmf = &getAnalysis(); + + vrm = &getAnalysis(); + + + DEBUG(dbgs() << "PBQP Register Allocating for " << mf->getFunction()->getName() << "\n"); + + // Allocator main loop: + // + // * Map current regalloc problem to a PBQP problem + // * Solve the PBQP problem + // * Map the solution back to a register allocation + // * Spill if necessary + // + // This process is continued till no more spills are generated. + + // Find the vreg intervals in need of allocation. + findVRegIntervalsToAlloc(); + + // If there are non-empty intervals allocate them using pbqp. + if (!vregsToAlloc.empty()) { + + bool pbqpAllocComplete = false; + unsigned round = 0; + + while (!pbqpAllocComplete) { + DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n"); + + std::auto_ptr problem = + builder->build(mf, lis, loopInfo, vregsToAlloc); + PBQP::Solution solution = + PBQP::HeuristicSolver::solve( + problem->getGraph()); + + pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution); + + ++round; + } + } + + // Finalise allocation, allocate empty ranges. + finalizeAlloc(); + + rmf->renderMachineFunction("After PBQP register allocation.", vrm); + + vregsToAlloc.clear(); + emptyIntervalVRegs.clear(); + + DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm << "\n"); + + // Run rewriter + std::auto_ptr rewriter(createVirtRegRewriter()); + + rewriter->runOnMachineFunction(*mf, *vrm, lis); + + return true; +} + +FunctionPass* llvm::createPBQPRegisterAllocator( + std::auto_ptr builder) { + return new RegAllocPBQP(builder); +} + +FunctionPass* llvm::createDefaultPBQPRegisterAllocator() { + if (pbqpCoalescing) { + return createPBQPRegisterAllocator( + std::auto_ptr(new PBQPBuilderWithCoalescing())); + } // else + return createPBQPRegisterAllocator( + std::auto_ptr(new PBQPBuilder())); +} + +#undef DEBUG_TYPE diff --git a/final/lib/CodeGen/RegisterCoalescer.cpp b/final/lib/CodeGen/RegisterCoalescer.cpp new file mode 100644 index 00000000000..407559a211a --- /dev/null +++ b/final/lib/CodeGen/RegisterCoalescer.cpp @@ -0,0 +1,197 @@ +//===- RegisterCoalescer.cpp - Generic Register Coalescing Interface -------==// +// +// 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 generic RegisterCoalescer interface which +// is used as the common interface used by all clients and +// implementations of register coalescing. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Pass.h" + +using namespace llvm; + +// Register the RegisterCoalescer interface, providing a nice name to refer to. +INITIALIZE_ANALYSIS_GROUP(RegisterCoalescer, "Register Coalescer", + SimpleRegisterCoalescing) +char RegisterCoalescer::ID = 0; + +// RegisterCoalescer destructor: DO NOT move this to the header file +// for RegisterCoalescer or else clients of the RegisterCoalescer +// class may not depend on the RegisterCoalescer.o file in the current +// .a file, causing alias analysis support to not be included in the +// tool correctly! +// +RegisterCoalescer::~RegisterCoalescer() {} + +unsigned CoalescerPair::compose(unsigned a, unsigned b) const { + if (!a) return b; + if (!b) return a; + return tri_.composeSubRegIndices(a, b); +} + +bool CoalescerPair::isMoveInstr(const MachineInstr *MI, + unsigned &Src, unsigned &Dst, + unsigned &SrcSub, unsigned &DstSub) const { + if (MI->isCopy()) { + Dst = MI->getOperand(0).getReg(); + DstSub = MI->getOperand(0).getSubReg(); + Src = MI->getOperand(1).getReg(); + SrcSub = MI->getOperand(1).getSubReg(); + } else if (MI->isSubregToReg()) { + Dst = MI->getOperand(0).getReg(); + DstSub = compose(MI->getOperand(0).getSubReg(), MI->getOperand(3).getImm()); + Src = MI->getOperand(2).getReg(); + SrcSub = MI->getOperand(2).getSubReg(); + } else + return false; + return true; +} + +bool CoalescerPair::setRegisters(const MachineInstr *MI) { + srcReg_ = dstReg_ = subIdx_ = 0; + newRC_ = 0; + flipped_ = crossClass_ = false; + + unsigned Src, Dst, SrcSub, DstSub; + if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub)) + return false; + partial_ = SrcSub || DstSub; + + // If one register is a physreg, it must be Dst. + if (TargetRegisterInfo::isPhysicalRegister(Src)) { + if (TargetRegisterInfo::isPhysicalRegister(Dst)) + return false; + std::swap(Src, Dst); + std::swap(SrcSub, DstSub); + flipped_ = true; + } + + const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); + + if (TargetRegisterInfo::isPhysicalRegister(Dst)) { + // Eliminate DstSub on a physreg. + if (DstSub) { + Dst = tri_.getSubReg(Dst, DstSub); + if (!Dst) return false; + DstSub = 0; + } + + // Eliminate SrcSub by picking a corresponding Dst superregister. + if (SrcSub) { + Dst = tri_.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src)); + if (!Dst) return false; + SrcSub = 0; + } else if (!MRI.getRegClass(Src)->contains(Dst)) { + return false; + } + } else { + // Both registers are virtual. + + // Both registers have subreg indices. + if (SrcSub && DstSub) { + // For now we only handle the case of identical indices in commensurate + // registers: Dreg:ssub_1 + Dreg:ssub_1 -> Dreg + // FIXME: Handle Qreg:ssub_3 + Dreg:ssub_1 as QReg:dsub_1 + Dreg. + if (SrcSub != DstSub) + return false; + const TargetRegisterClass *SrcRC = MRI.getRegClass(Src); + const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); + if (!getCommonSubClass(DstRC, SrcRC)) + return false; + SrcSub = DstSub = 0; + } + + // There can be no SrcSub. + if (SrcSub) { + std::swap(Src, Dst); + DstSub = SrcSub; + SrcSub = 0; + assert(!flipped_ && "Unexpected flip"); + flipped_ = true; + } + + // Find the new register class. + const TargetRegisterClass *SrcRC = MRI.getRegClass(Src); + const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); + if (DstSub) + newRC_ = tri_.getMatchingSuperRegClass(DstRC, SrcRC, DstSub); + else + newRC_ = getCommonSubClass(DstRC, SrcRC); + if (!newRC_) + return false; + crossClass_ = newRC_ != DstRC || newRC_ != SrcRC; + } + // Check our invariants + assert(TargetRegisterInfo::isVirtualRegister(Src) && "Src must be virtual"); + assert(!(TargetRegisterInfo::isPhysicalRegister(Dst) && DstSub) && + "Cannot have a physical SubIdx"); + srcReg_ = Src; + dstReg_ = Dst; + subIdx_ = DstSub; + return true; +} + +bool CoalescerPair::flip() { + if (subIdx_ || TargetRegisterInfo::isPhysicalRegister(dstReg_)) + return false; + std::swap(srcReg_, dstReg_); + flipped_ = !flipped_; + return true; +} + +bool CoalescerPair::isCoalescable(const MachineInstr *MI) const { + if (!MI) + return false; + unsigned Src, Dst, SrcSub, DstSub; + if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub)) + return false; + + // Find the virtual register that is srcReg_. + if (Dst == srcReg_) { + std::swap(Src, Dst); + std::swap(SrcSub, DstSub); + } else if (Src != srcReg_) { + return false; + } + + // Now check that Dst matches dstReg_. + if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) { + if (!TargetRegisterInfo::isPhysicalRegister(Dst)) + return false; + assert(!subIdx_ && "Inconsistent CoalescerPair state."); + // DstSub could be set for a physreg from INSERT_SUBREG. + if (DstSub) + Dst = tri_.getSubReg(Dst, DstSub); + // Full copy of Src. + if (!SrcSub) + return dstReg_ == Dst; + // This is a partial register copy. Check that the parts match. + return tri_.getSubReg(dstReg_, SrcSub) == Dst; + } else { + // dstReg_ is virtual. + if (dstReg_ != Dst) + return false; + // Registers match, do the subregisters line up? + return compose(subIdx_, SrcSub) == DstSub; + } +} + +// Because of the way .a files work, we must force the SimpleRC +// implementation to be pulled in if the RegisterCoalescer classes are +// pulled in. Otherwise we run the risk of RegisterCoalescer being +// used, but the default implementation not being linked into the tool +// that uses it. +DEFINING_FILE_FOR(RegisterCoalescer) diff --git a/final/lib/CodeGen/RegisterScavenging.cpp b/final/lib/CodeGen/RegisterScavenging.cpp new file mode 100644 index 00000000000..b9dd28e5c78 --- /dev/null +++ b/final/lib/CodeGen/RegisterScavenging.cpp @@ -0,0 +1,389 @@ +//===-- RegisterScavenging.cpp - Machine register scavenging --------------===// +// +// 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 machine register scavenger. It can provide +// information, such as unused registers, at any point in a machine basic block. +// It also provides a mechanism to make registers available by evicting them to +// spill slots. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reg-scavenging" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +/// setUsed - Set the register and its sub-registers as being used. +void RegScavenger::setUsed(unsigned Reg) { + RegsAvailable.reset(Reg); + + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + RegsAvailable.reset(SubReg); +} + +bool RegScavenger::isAliasUsed(unsigned Reg) const { + if (isUsed(Reg)) + return true; + for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R) + if (isUsed(*R)) + return true; + return false; +} + +void RegScavenger::initRegState() { + ScavengedReg = 0; + ScavengedRC = NULL; + ScavengeRestore = NULL; + + // All registers started out unused. + RegsAvailable.set(); + + // Reserved registers are always used. + RegsAvailable ^= ReservedRegs; + + if (!MBB) + return; + + // Live-in registers are in use. + for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(), + E = MBB->livein_end(); I != E; ++I) + setUsed(*I); + + // Pristine CSRs are also unavailable. + BitVector PR = MBB->getParent()->getFrameInfo()->getPristineRegs(MBB); + for (int I = PR.find_first(); I>0; I = PR.find_next(I)) + setUsed(I); +} + +void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) { + MachineFunction &MF = *mbb->getParent(); + const TargetMachine &TM = MF.getTarget(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + MRI = &MF.getRegInfo(); + + assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) && + "Target changed?"); + + // Self-initialize. + if (!MBB) { + NumPhysRegs = TRI->getNumRegs(); + RegsAvailable.resize(NumPhysRegs); + + // Create reserved registers bitvector. + ReservedRegs = TRI->getReservedRegs(MF); + + // Create callee-saved registers bitvector. + CalleeSavedRegs.resize(NumPhysRegs); + const unsigned *CSRegs = TRI->getCalleeSavedRegs(); + if (CSRegs != NULL) + for (unsigned i = 0; CSRegs[i]; ++i) + CalleeSavedRegs.set(CSRegs[i]); + } + + MBB = mbb; + initRegState(); + + Tracking = false; +} + +void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) { + BV.set(Reg); + for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++) + BV.set(*R); +} + +void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) { + BV.set(Reg); + for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++) + BV.set(*R); +} + +void RegScavenger::forward() { + // Move ptr forward. + if (!Tracking) { + MBBI = MBB->begin(); + Tracking = true; + } else { + assert(MBBI != MBB->end() && "Already at the end of the basic block!"); + MBBI = llvm::next(MBBI); + } + + MachineInstr *MI = MBBI; + + if (MI == ScavengeRestore) { + ScavengedReg = 0; + ScavengedRC = NULL; + ScavengeRestore = NULL; + } + + if (MI->isDebugValue()) + return; + + // Find out which registers are early clobbered, killed, defined, and marked + // def-dead in this instruction. + // FIXME: The scavenger is not predication aware. If the instruction is + // predicated, conservatively assume "kill" markers do not actually kill the + // register. Similarly ignores "dead" markers. + bool isPred = TII->isPredicated(MI); + BitVector EarlyClobberRegs(NumPhysRegs); + BitVector KillRegs(NumPhysRegs); + BitVector DefRegs(NumPhysRegs); + BitVector DeadRegs(NumPhysRegs); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || isReserved(Reg)) + continue; + + if (MO.isUse()) { + // Two-address operands implicitly kill. + if (!isPred && (MO.isKill() || MI->isRegTiedToDefOperand(i))) + addRegWithSubRegs(KillRegs, Reg); + } else { + assert(MO.isDef()); + if (!isPred && MO.isDead()) + addRegWithSubRegs(DeadRegs, Reg); + else + addRegWithSubRegs(DefRegs, Reg); + if (MO.isEarlyClobber()) + addRegWithAliases(EarlyClobberRegs, Reg); + } + } + + // Verify uses and defs. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || isReserved(Reg)) + continue; + if (MO.isUse()) { + if (!isUsed(Reg)) { + // Check if it's partial live: e.g. + // D0 = insert_subreg D0, S0 + // ... D0 + // The problem is the insert_subreg could be eliminated. The use of + // D0 is using a partially undef value. This is not *incorrect* since + // S1 is can be freely clobbered. + // Ideally we would like a way to model this, but leaving the + // insert_subreg around causes both correctness and performance issues. + bool SubUsed = false; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + if (isUsed(SubReg)) { + SubUsed = true; + break; + } + assert(SubUsed && "Using an undefined register!"); + } + assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) && + "Using an early clobbered register!"); + } else { + assert(MO.isDef()); +#if 0 + // FIXME: Enable this once we've figured out how to correctly transfer + // implicit kills during codegen passes like the coalescer. + assert((KillRegs.test(Reg) || isUnused(Reg) || + isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) && + "Re-defining a live register!"); +#endif + } + } + + // Commit the changes. + setUnused(KillRegs); + setUnused(DeadRegs); + setUsed(DefRegs); +} + +void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) { + if (includeReserved) + used = ~RegsAvailable; + else + used = ~RegsAvailable & ~ReservedRegs; +} + +unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const { + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) + if (!isAliasUsed(*I)) { + DEBUG(dbgs() << "Scavenger found unused reg: " << TRI->getName(*I) << + "\n"); + return *I; + } + return 0; +} + +/// getRegsAvailable - Return all available registers in the register class +/// in Mask. +BitVector RegScavenger::getRegsAvailable(const TargetRegisterClass *RC) { + BitVector Mask(TRI->getNumRegs()); + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) + if (!isAliasUsed(*I)) + Mask.set(*I); + return Mask; +} + +/// findSurvivorReg - Return the candidate register that is unused for the +/// longest after StargMII. UseMI is set to the instruction where the search +/// stopped. +/// +/// No more than InstrLimit instructions are inspected. +/// +unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator StartMI, + BitVector &Candidates, + unsigned InstrLimit, + MachineBasicBlock::iterator &UseMI) { + int Survivor = Candidates.find_first(); + assert(Survivor > 0 && "No candidates for scavenging"); + + MachineBasicBlock::iterator ME = MBB->getFirstTerminator(); + assert(StartMI != ME && "MI already at terminator"); + MachineBasicBlock::iterator RestorePointMI = StartMI; + MachineBasicBlock::iterator MI = StartMI; + + bool inVirtLiveRange = false; + for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) { + if (MI->isDebugValue()) { + ++InstrLimit; // Don't count debug instructions + continue; + } + bool isVirtKillInsn = false; + bool isVirtDefInsn = false; + // Remove any candidates touched by instruction. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || MO.isUndef() || !MO.getReg()) + continue; + if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + if (MO.isDef()) + isVirtDefInsn = true; + else if (MO.isKill()) + isVirtKillInsn = true; + continue; + } + Candidates.reset(MO.getReg()); + for (const unsigned *R = TRI->getAliasSet(MO.getReg()); *R; R++) + Candidates.reset(*R); + } + // If we're not in a virtual reg's live range, this is a valid + // restore point. + if (!inVirtLiveRange) RestorePointMI = MI; + + // Update whether we're in the live range of a virtual register + if (isVirtKillInsn) inVirtLiveRange = false; + if (isVirtDefInsn) inVirtLiveRange = true; + + // Was our survivor untouched by this instruction? + if (Candidates.test(Survivor)) + continue; + + // All candidates gone? + if (Candidates.none()) + break; + + Survivor = Candidates.find_first(); + } + // If we ran off the end, that's where we want to restore. + if (MI == ME) RestorePointMI = ME; + assert (RestorePointMI != StartMI && + "No available scavenger restore location!"); + + // We ran out of candidates, so stop the search. + UseMI = RestorePointMI; + return Survivor; +} + +unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC, + MachineBasicBlock::iterator I, + int SPAdj) { + // Consider all allocatable registers in the register class initially + BitVector Candidates = + TRI->getAllocatableSet(*I->getParent()->getParent(), RC); + + // Exclude all the registers being used by the instruction. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + MachineOperand &MO = I->getOperand(i); + if (MO.isReg() && MO.getReg() != 0 && + !TargetRegisterInfo::isVirtualRegister(MO.getReg())) + Candidates.reset(MO.getReg()); + } + + // Try to find a register that's unused if there is one, as then we won't + // have to spill. Search explicitly rather than masking out based on + // RegsAvailable, as RegsAvailable does not take aliases into account. + // That's what getRegsAvailable() is for. + BitVector Available = getRegsAvailable(RC); + + if ((Candidates & Available).any()) + Candidates &= Available; + + // Find the register whose use is furthest away. + MachineBasicBlock::iterator UseMI; + unsigned SReg = findSurvivorReg(I, Candidates, 25, UseMI); + + // If we found an unused register there is no reason to spill it. + if (!isAliasUsed(SReg)) { + DEBUG(dbgs() << "Scavenged register: " << TRI->getName(SReg) << "\n"); + return SReg; + } + + assert(ScavengedReg == 0 && + "Scavenger slot is live, unable to scavenge another register!"); + + // Avoid infinite regress + ScavengedReg = SReg; + + // If the target knows how to save/restore the register, let it do so; + // otherwise, use the emergency stack spill slot. + if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) { + // Spill the scavenged register before I. + assert(ScavengingFrameIndex >= 0 && + "Cannot scavenge register without an emergency spill slot!"); + TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC,TRI); + MachineBasicBlock::iterator II = prior(I); + TRI->eliminateFrameIndex(II, SPAdj, this); + + // Restore the scavenged register before its use (or first terminator). + TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC, TRI); + II = prior(UseMI); + TRI->eliminateFrameIndex(II, SPAdj, this); + } + + ScavengeRestore = prior(UseMI); + + // Doing this here leads to infinite regress. + // ScavengedReg = SReg; + ScavengedRC = RC; + + DEBUG(dbgs() << "Scavenged register (with spill): " << TRI->getName(SReg) << + "\n"); + + return SReg; +} diff --git a/final/lib/CodeGen/RenderMachineFunction.cpp b/final/lib/CodeGen/RenderMachineFunction.cpp new file mode 100644 index 00000000000..cbfd5a23d63 --- /dev/null +++ b/final/lib/CodeGen/RenderMachineFunction.cpp @@ -0,0 +1,1014 @@ +//===-- llvm/CodeGen/RenderMachineFunction.cpp - MF->HTML -----s-----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "rendermf" + +#include "RenderMachineFunction.h" + +#include "VirtRegMap.h" + +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" + +#include + +using namespace llvm; + +char RenderMachineFunction::ID = 0; +INITIALIZE_PASS_BEGIN(RenderMachineFunction, "rendermf", + "Render machine functions (and related info) to HTML pages", + false, false) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_END(RenderMachineFunction, "rendermf", + "Render machine functions (and related info) to HTML pages", + false, false) + +static cl::opt +outputFileSuffix("rmf-file-suffix", + cl::desc("Appended to function name to get output file name " + "(default: \".html\")"), + cl::init(".html"), cl::Hidden); + +static cl::opt +machineFuncsToRender("rmf-funcs", + cl::desc("Coma seperated list of functions to render" + ", or \"*\"."), + cl::init(""), cl::Hidden); + +static cl::opt +pressureClasses("rmf-classes", + cl::desc("Register classes to render pressure for."), + cl::init(""), cl::Hidden); + +static cl::opt +showIntervals("rmf-intervals", + cl::desc("Live intervals to show alongside code."), + cl::init(""), cl::Hidden); + +static cl::opt +filterEmpty("rmf-filter-empty-intervals", + cl::desc("Don't display empty intervals."), + cl::init(true), cl::Hidden); + +static cl::opt +showEmptyIndexes("rmf-empty-indexes", + cl::desc("Render indexes not associated with instructions or " + "MBB starts."), + cl::init(false), cl::Hidden); + +static cl::opt +useFancyVerticals("rmf-fancy-verts", + cl::desc("Use SVG for vertical text."), + cl::init(true), cl::Hidden); + +static cl::opt +prettyHTML("rmf-pretty-html", + cl::desc("Pretty print HTML. For debugging the renderer only.."), + cl::init(false), cl::Hidden); + + +namespace llvm { + + bool MFRenderingOptions::renderingOptionsProcessed; + std::set MFRenderingOptions::mfNamesToRender; + bool MFRenderingOptions::renderAllMFs = false; + + std::set MFRenderingOptions::classNamesToRender; + bool MFRenderingOptions::renderAllClasses = false; + + std::set > + MFRenderingOptions::intervalNumsToRender; + unsigned MFRenderingOptions::intervalTypesToRender = ExplicitOnly; + + template + void MFRenderingOptions::splitComaSeperatedList(const std::string &s, + OutputItr outItr) { + std::string::const_iterator curPos = s.begin(); + std::string::const_iterator nextComa = std::find(curPos, s.end(), ','); + while (nextComa != s.end()) { + std::string elem; + std::copy(curPos, nextComa, std::back_inserter(elem)); + *outItr = elem; + ++outItr; + curPos = llvm::next(nextComa); + nextComa = std::find(curPos, s.end(), ','); + } + + if (curPos != s.end()) { + std::string elem; + std::copy(curPos, s.end(), std::back_inserter(elem)); + *outItr = elem; + ++outItr; + } + } + + void MFRenderingOptions::processOptions() { + if (!renderingOptionsProcessed) { + processFuncNames(); + processRegClassNames(); + processIntervalNumbers(); + renderingOptionsProcessed = true; + } + } + + void MFRenderingOptions::processFuncNames() { + if (machineFuncsToRender == "*") { + renderAllMFs = true; + } else { + splitComaSeperatedList(machineFuncsToRender, + std::inserter(mfNamesToRender, + mfNamesToRender.begin())); + } + } + + void MFRenderingOptions::processRegClassNames() { + if (pressureClasses == "*") { + renderAllClasses = true; + } else { + splitComaSeperatedList(pressureClasses, + std::inserter(classNamesToRender, + classNamesToRender.begin())); + } + } + + void MFRenderingOptions::processIntervalNumbers() { + std::set intervalRanges; + splitComaSeperatedList(showIntervals, + std::inserter(intervalRanges, + intervalRanges.begin())); + std::for_each(intervalRanges.begin(), intervalRanges.end(), + processIntervalRange); + } + + void MFRenderingOptions::processIntervalRange( + const std::string &intervalRangeStr) { + if (intervalRangeStr == "*") { + intervalTypesToRender |= All; + } else if (intervalRangeStr == "virt-nospills*") { + intervalTypesToRender |= VirtNoSpills; + } else if (intervalRangeStr == "spills*") { + intervalTypesToRender |= VirtSpills; + } else if (intervalRangeStr == "virt*") { + intervalTypesToRender |= AllVirt; + } else if (intervalRangeStr == "phys*") { + intervalTypesToRender |= AllPhys; + } else { + std::istringstream iss(intervalRangeStr); + unsigned reg1, reg2; + if ((iss >> reg1 >> std::ws)) { + if (iss.eof()) { + intervalNumsToRender.insert(std::make_pair(reg1, reg1 + 1)); + } else { + char c; + iss >> c; + if (c == '-' && (iss >> reg2)) { + intervalNumsToRender.insert(std::make_pair(reg1, reg2 + 1)); + } else { + dbgs() << "Warning: Invalid interval range \"" + << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n"; + } + } + } else { + dbgs() << "Warning: Invalid interval number \"" + << intervalRangeStr << "\" in -rmf-intervals. Skipping.\n"; + } + } + } + + void MFRenderingOptions::setup(MachineFunction *mf, + const TargetRegisterInfo *tri, + LiveIntervals *lis, + const RenderMachineFunction *rmf) { + this->mf = mf; + this->tri = tri; + this->lis = lis; + this->rmf = rmf; + + clear(); + } + + void MFRenderingOptions::clear() { + regClassesTranslatedToCurrentFunction = false; + regClassSet.clear(); + + intervalsTranslatedToCurrentFunction = false; + intervalSet.clear(); + } + + void MFRenderingOptions::resetRenderSpecificOptions() { + intervalSet.clear(); + intervalsTranslatedToCurrentFunction = false; + } + + bool MFRenderingOptions::shouldRenderCurrentMachineFunction() const { + processOptions(); + + return (renderAllMFs || + mfNamesToRender.find(mf->getFunction()->getName()) != + mfNamesToRender.end()); + } + + const MFRenderingOptions::RegClassSet& MFRenderingOptions::regClasses() const{ + translateRegClassNamesToCurrentFunction(); + return regClassSet; + } + + const MFRenderingOptions::IntervalSet& MFRenderingOptions::intervals() const { + translateIntervalNumbersToCurrentFunction(); + return intervalSet; + } + + bool MFRenderingOptions::renderEmptyIndexes() const { + return showEmptyIndexes; + } + + bool MFRenderingOptions::fancyVerticals() const { + return useFancyVerticals; + } + + void MFRenderingOptions::translateRegClassNamesToCurrentFunction() const { + if (!regClassesTranslatedToCurrentFunction) { + processOptions(); + for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(), + rcEnd = tri->regclass_end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + if (renderAllClasses || + classNamesToRender.find(trc->getName()) != + classNamesToRender.end()) { + regClassSet.insert(trc); + } + } + regClassesTranslatedToCurrentFunction = true; + } + } + + void MFRenderingOptions::translateIntervalNumbersToCurrentFunction() const { + if (!intervalsTranslatedToCurrentFunction) { + processOptions(); + + // If we're not just doing explicit then do a copy over all matching + // types. + if (intervalTypesToRender != ExplicitOnly) { + for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end(); + liItr != liEnd; ++liItr) { + LiveInterval *li = liItr->second; + + if (filterEmpty && li->empty()) + continue; + + if ((TargetRegisterInfo::isPhysicalRegister(li->reg) && + (intervalTypesToRender & AllPhys))) { + intervalSet.insert(li); + } else if (TargetRegisterInfo::isVirtualRegister(li->reg)) { + if (((intervalTypesToRender & VirtNoSpills) && !rmf->isSpill(li)) || + ((intervalTypesToRender & VirtSpills) && rmf->isSpill(li))) { + intervalSet.insert(li); + } + } + } + } + + // If we need to process the explicit list... + if (intervalTypesToRender != All) { + for (std::set >::const_iterator + regRangeItr = intervalNumsToRender.begin(), + regRangeEnd = intervalNumsToRender.end(); + regRangeItr != regRangeEnd; ++regRangeItr) { + const std::pair &range = *regRangeItr; + for (unsigned reg = range.first; reg != range.second; ++reg) { + if (lis->hasInterval(reg)) { + intervalSet.insert(&lis->getInterval(reg)); + } + } + } + } + + intervalsTranslatedToCurrentFunction = true; + } + } + + // ---------- TargetRegisterExtraInformation implementation ---------- + + TargetRegisterExtraInfo::TargetRegisterExtraInfo() + : mapsPopulated(false) { + } + + void TargetRegisterExtraInfo::setup(MachineFunction *mf, + MachineRegisterInfo *mri, + const TargetRegisterInfo *tri, + LiveIntervals *lis) { + this->mf = mf; + this->mri = mri; + this->tri = tri; + this->lis = lis; + } + + void TargetRegisterExtraInfo::reset() { + if (!mapsPopulated) { + initWorst(); + //initBounds(); + initCapacity(); + mapsPopulated = true; + } + + resetPressureAndLiveStates(); + } + + void TargetRegisterExtraInfo::clear() { + prWorst.clear(); + vrWorst.clear(); + capacityMap.clear(); + pressureMap.clear(); + //liveStatesMap.clear(); + mapsPopulated = false; + } + + void TargetRegisterExtraInfo::initWorst() { + assert(!mapsPopulated && prWorst.empty() && vrWorst.empty() && + "Worst map already initialised?"); + + // Start with the physical registers. + for (unsigned preg = 1; preg < tri->getNumRegs(); ++preg) { + WorstMapLine &pregLine = prWorst[preg]; + + for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(), + rcEnd = tri->regclass_end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + + unsigned numOverlaps = 0; + for (TargetRegisterClass::iterator rItr = trc->begin(), + rEnd = trc->end(); + rItr != rEnd; ++rItr) { + unsigned trcPReg = *rItr; + if (tri->regsOverlap(preg, trcPReg)) + ++numOverlaps; + } + + pregLine[trc] = numOverlaps; + } + } + + // Now the register classes. + for (TargetRegisterInfo::regclass_iterator rc1Itr = tri->regclass_begin(), + rcEnd = tri->regclass_end(); + rc1Itr != rcEnd; ++rc1Itr) { + const TargetRegisterClass *trc1 = *rc1Itr; + WorstMapLine &classLine = vrWorst[trc1]; + + for (TargetRegisterInfo::regclass_iterator rc2Itr = tri->regclass_begin(); + rc2Itr != rcEnd; ++rc2Itr) { + const TargetRegisterClass *trc2 = *rc2Itr; + + unsigned worst = 0; + + for (TargetRegisterClass::iterator trc1Itr = trc1->begin(), + trc1End = trc1->end(); + trc1Itr != trc1End; ++trc1Itr) { + unsigned trc1Reg = *trc1Itr; + unsigned trc1RegWorst = 0; + + for (TargetRegisterClass::iterator trc2Itr = trc2->begin(), + trc2End = trc2->end(); + trc2Itr != trc2End; ++trc2Itr) { + unsigned trc2Reg = *trc2Itr; + if (tri->regsOverlap(trc1Reg, trc2Reg)) + ++trc1RegWorst; + } + if (trc1RegWorst > worst) { + worst = trc1RegWorst; + } + } + + if (worst != 0) { + classLine[trc2] = worst; + } + } + } + } + + unsigned TargetRegisterExtraInfo::getWorst( + unsigned reg, + const TargetRegisterClass *trc) const { + const WorstMapLine *wml = 0; + if (TargetRegisterInfo::isPhysicalRegister(reg)) { + PRWorstMap::const_iterator prwItr = prWorst.find(reg); + assert(prwItr != prWorst.end() && "Missing prWorst entry."); + wml = &prwItr->second; + } else { + const TargetRegisterClass *regTRC = mri->getRegClass(reg); + VRWorstMap::const_iterator vrwItr = vrWorst.find(regTRC); + assert(vrwItr != vrWorst.end() && "Missing vrWorst entry."); + wml = &vrwItr->second; + } + + WorstMapLine::const_iterator wmlItr = wml->find(trc); + if (wmlItr == wml->end()) + return 0; + + return wmlItr->second; + } + + void TargetRegisterExtraInfo::initCapacity() { + assert(!mapsPopulated && capacityMap.empty() && + "Capacity map already initialised?"); + + for (TargetRegisterInfo::regclass_iterator rcItr = tri->regclass_begin(), + rcEnd = tri->regclass_end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + unsigned capacity = std::distance(trc->allocation_order_begin(*mf), + trc->allocation_order_end(*mf)); + + if (capacity != 0) + capacityMap[trc] = capacity; + } + } + + unsigned TargetRegisterExtraInfo::getCapacity( + const TargetRegisterClass *trc) const { + CapacityMap::const_iterator cmItr = capacityMap.find(trc); + assert(cmItr != capacityMap.end() && + "vreg with unallocable register class"); + return cmItr->second; + } + + void TargetRegisterExtraInfo::resetPressureAndLiveStates() { + pressureMap.clear(); + //liveStatesMap.clear(); + + // Iterate over all slots. + + + // Iterate over all live intervals. + for (LiveIntervals::iterator liItr = lis->begin(), + liEnd = lis->end(); + liItr != liEnd; ++liItr) { + LiveInterval *li = liItr->second; + + if (TargetRegisterInfo::isPhysicalRegister(li->reg)) + continue; + + // For all ranges in the current interal. + for (LiveInterval::iterator lrItr = li->begin(), + lrEnd = li->end(); + lrItr != lrEnd; ++lrItr) { + LiveRange *lr = &*lrItr; + + // For all slots in the current range. + for (SlotIndex i = lr->start; i != lr->end; i = i.getNextSlot()) { + + // Record increased pressure at index for all overlapping classes. + for (TargetRegisterInfo::regclass_iterator + rcItr = tri->regclass_begin(), + rcEnd = tri->regclass_end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + + if (trc->allocation_order_begin(*mf) == + trc->allocation_order_end(*mf)) + continue; + + unsigned worstAtI = getWorst(li->reg, trc); + + if (worstAtI != 0) { + pressureMap[i][trc] += worstAtI; + } + } + } + } + } + } + + unsigned TargetRegisterExtraInfo::getPressureAtSlot( + const TargetRegisterClass *trc, + SlotIndex i) const { + PressureMap::const_iterator pmItr = pressureMap.find(i); + if (pmItr == pressureMap.end()) + return 0; + const PressureMapLine &pmLine = pmItr->second; + PressureMapLine::const_iterator pmlItr = pmLine.find(trc); + if (pmlItr == pmLine.end()) + return 0; + return pmlItr->second; + } + + bool TargetRegisterExtraInfo::classOverCapacityAtSlot( + const TargetRegisterClass *trc, + SlotIndex i) const { + return (getPressureAtSlot(trc, i) > getCapacity(trc)); + } + + // ---------- MachineFunctionRenderer implementation ---------- + + void RenderMachineFunction::Spacer::print(raw_ostream &os) const { + if (!prettyHTML) + return; + for (unsigned i = 0; i < ns; ++i) { + os << " "; + } + } + + RenderMachineFunction::Spacer RenderMachineFunction::s(unsigned ns) const { + return Spacer(ns); + } + + raw_ostream& operator<<(raw_ostream &os, const RenderMachineFunction::Spacer &s) { + s.print(os); + return os; + } + + template + std::string RenderMachineFunction::escapeChars(Iterator sBegin, Iterator sEnd) const { + std::string r; + + for (Iterator sItr = sBegin; sItr != sEnd; ++sItr) { + char c = *sItr; + + switch (c) { + case '<': r.append("<"); break; + case '>': r.append(">"); break; + case '&': r.append("&"); break; + case ' ': r.append(" "); break; + case '\"': r.append("""); break; + default: r.push_back(c); break; + } + } + + return r; + } + + RenderMachineFunction::LiveState + RenderMachineFunction::getLiveStateAt(const LiveInterval *li, + SlotIndex i) const { + const MachineInstr *mi = sis->getInstructionFromIndex(i); + + // For uses/defs recorded use/def indexes override current liveness and + // instruction operands (Only for the interval which records the indexes). + if (i.isUse() || i.isDef()) { + UseDefs::const_iterator udItr = useDefs.find(li); + if (udItr != useDefs.end()) { + const SlotSet &slotSet = udItr->second; + if (slotSet.count(i)) { + if (i.isUse()) { + return Used; + } + // else + return Defined; + } + } + } + + // If the slot is a load/store, or there's no info in the use/def set then + // use liveness and instruction operand info. + if (li->liveAt(i)) { + + if (mi == 0) { + if (vrm == 0 || + (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) { + return AliveReg; + } else { + return AliveStack; + } + } else { + if (i.isDef() && mi->definesRegister(li->reg, tri)) { + return Defined; + } else if (i.isUse() && mi->readsRegister(li->reg)) { + return Used; + } else { + if (vrm == 0 || + (vrm->getStackSlot(li->reg) == VirtRegMap::NO_STACK_SLOT)) { + return AliveReg; + } else { + return AliveStack; + } + } + } + } + return Dead; + } + + RenderMachineFunction::PressureState + RenderMachineFunction::getPressureStateAt(const TargetRegisterClass *trc, + SlotIndex i) const { + if (trei.getPressureAtSlot(trc, i) == 0) { + return Zero; + } else if (trei.classOverCapacityAtSlot(trc, i)){ + return High; + } + return Low; + } + + /// \brief Render a machine instruction. + void RenderMachineFunction::renderMachineInstr(raw_ostream &os, + const MachineInstr *mi) const { + std::string s; + raw_string_ostream oss(s); + oss << *mi; + + os << escapeChars(oss.str()); + } + + template + void RenderMachineFunction::renderVertical(const Spacer &indent, + raw_ostream &os, + const T &t) const { + if (ro.fancyVerticals()) { + os << indent << "\n" + << indent + s(6) << "" << t << "\n" + << indent + s(4) << "\">\n" + << indent << "\n"; + } else { + std::ostringstream oss; + oss << t; + std::string tStr(oss.str()); + + os << indent; + for (std::string::iterator tStrItr = tStr.begin(), tStrEnd = tStr.end(); + tStrItr != tStrEnd; ++tStrItr) { + os << *tStrItr << "
"; + } + os << "\n"; + } + } + + void RenderMachineFunction::insertCSS(const Spacer &indent, + raw_ostream &os) const { + os << indent << "\n"; + } + + void RenderMachineFunction::renderFunctionSummary( + const Spacer &indent, raw_ostream &os, + const char * const renderContextStr) const { + os << indent << "

Function: " << mf->getFunction()->getName() + << "

\n" + << indent << "

Rendering context: " << renderContextStr << "

\n"; + } + + + void RenderMachineFunction::renderPressureTableLegend( + const Spacer &indent, + raw_ostream &os) const { + os << indent << "

Rendering Pressure Legend:

\n" + << indent << "\n" + << indent + s(2) << "\n" + << indent + s(4) << "" + "\n" + << indent + s(2) << "\n" + << indent + s(2) << "\n" + << indent + s(4) << "" + "" + "\n" + << indent + s(2) << "\n" + << indent + s(2) << "\n" + << indent + s(4) << "" + "" + "\n" + << indent + s(2) << "\n" + << indent + s(2) << "\n" + << indent + s(4) << "" + "" + "\n" + << indent + s(2) << "\n" + << indent << "
PressureDescriptionAppearance
No PressureNo physical registers of this class requested.  
Low PressureSufficient physical registers to meet demand.  
High PressurePotentially insufficient physical registers to meet demand.  
\n"; + } + + template + void RenderMachineFunction::renderCellsWithRLE( + const Spacer &indent, raw_ostream &os, + const std::pair &rleAccumulator, + const std::map &cellTypeStrs) const { + + if (rleAccumulator.second == 0) + return; + + typename std::map::const_iterator ctsItr = + cellTypeStrs.find(rleAccumulator.first); + + assert(ctsItr != cellTypeStrs.end() && "No string for given cell type."); + + os << indent + s(4) << "second << "\""; + if (rleAccumulator.second > 1) + os << " colspan=" << rleAccumulator.second; + os << ">\n"; + } + + + void RenderMachineFunction::renderCodeTablePlusPI(const Spacer &indent, + raw_ostream &os) const { + + std::map lsStrs; + lsStrs[Dead] = "l-n"; + lsStrs[Defined] = "l-d"; + lsStrs[Used] = "l-u"; + lsStrs[AliveReg] = "l-r"; + lsStrs[AliveStack] = "l-s"; + + std::map psStrs; + psStrs[Zero] = "p-z"; + psStrs[Low] = "p-l"; + psStrs[High] = "p-h"; + + // Open the table... + + os << indent << "\n" + << indent + s(2) << "\n"; + + // Render the header row... + + os << indent + s(4) << "\n" + << indent + s(4) << "\n"; + + // Render class names if necessary... + if (!ro.regClasses().empty()) { + for (MFRenderingOptions::RegClassSet::const_iterator + rcItr = ro.regClasses().begin(), + rcEnd = ro.regClasses().end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + os << indent + s(4) << "\n"; + } + } + + // FIXME: Is there a nicer way to insert space between columns in HTML? + if (!ro.regClasses().empty() && !ro.intervals().empty()) + os << indent + s(4) << "\n"; + + // Render interval numbers if necessary... + if (!ro.intervals().empty()) { + for (MFRenderingOptions::IntervalSet::const_iterator + liItr = ro.intervals().begin(), + liEnd = ro.intervals().end(); + liItr != liEnd; ++liItr) { + + const LiveInterval *li = *liItr; + os << indent + s(4) << "\n"; + } + } + + os << indent + s(2) << "\n"; + + // End header row, start with the data rows... + + MachineInstr *mi = 0; + + // Data rows: + for (SlotIndex i = sis->getZeroIndex(); i != sis->getLastIndex(); + i = i.getNextSlot()) { + + // Render the slot column. + os << indent + s(2) << "\n"; + + // Render the code column. + if (i.isLoad()) { + MachineBasicBlock *mbb = sis->getMBBFromIndex(i); + mi = sis->getInstructionFromIndex(i); + + if (i == sis->getMBBStartIdx(mbb) || mi != 0 || + ro.renderEmptyIndexes()) { + os << indent + s(4) << "\n" + << indent + s(4) << "\n"; + } else { + i = i.getStoreIndex(); // <- Will be incremented to the next index. + continue; + } + } + + // Render the class columns. + if (!ro.regClasses().empty()) { + std::pair psRLEAccumulator(Zero, 0); + for (MFRenderingOptions::RegClassSet::const_iterator + rcItr = ro.regClasses().begin(), + rcEnd = ro.regClasses().end(); + rcItr != rcEnd; ++rcItr) { + const TargetRegisterClass *trc = *rcItr; + PressureState newPressure = getPressureStateAt(trc, i); + + if (newPressure == psRLEAccumulator.first) { + ++psRLEAccumulator.second; + } else { + renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs); + psRLEAccumulator.first = newPressure; + psRLEAccumulator.second = 1; + } + } + renderCellsWithRLE(indent + s(4), os, psRLEAccumulator, psStrs); + } + + // FIXME: Is there a nicer way to insert space between columns in HTML? + if (!ro.regClasses().empty() && !ro.intervals().empty()) + os << indent + s(4) << "\n"; + + if (!ro.intervals().empty()) { + std::pair lsRLEAccumulator(Dead, 0); + for (MFRenderingOptions::IntervalSet::const_iterator + liItr = ro.intervals().begin(), + liEnd = ro.intervals().end(); + liItr != liEnd; ++liItr) { + const LiveInterval *li = *liItr; + LiveState newLiveness = getLiveStateAt(li, i); + + if (newLiveness == lsRLEAccumulator.first) { + ++lsRLEAccumulator.second; + } else { + renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs); + lsRLEAccumulator.first = newLiveness; + lsRLEAccumulator.second = 1; + } + } + renderCellsWithRLE(indent + s(4), os, lsRLEAccumulator, lsStrs); + } + os << indent + s(2) << "\n"; + } + + os << indent << "
indexinstr\n"; + renderVertical(indent + s(6), os, trc->getName()); + os << indent + s(4) << "  \n"; + renderVertical(indent + s(6), os, li->reg); + os << indent + s(4) << "
" << i << " \n"; + + if (i == sis->getMBBStartIdx(mbb)) { + os << indent + s(6) << "BB#" << mbb->getNumber() << ": \n"; + } else if (mi != 0) { + os << indent + s(6) << "  "; + renderMachineInstr(os, mi); + } else { + // Empty interval - leave blank. + } + os << indent + s(4) << "
\n"; + + if (!ro.regClasses().empty()) + renderPressureTableLegend(indent, os); + } + + void RenderMachineFunction::renderFunctionPage( + raw_ostream &os, + const char * const renderContextStr) const { + os << "\n" + << s(2) << "\n" + << s(4) << "" << fqn << "\n"; + + insertCSS(s(4), os); + + os << s(2) << "\n" + << s(2) << "\n"; + + renderFunctionSummary(s(4), os, renderContextStr); + + os << s(4) << "


\n"; + + //renderLiveIntervalInfoTable(" ", os); + + os << s(4) << "


\n"; + + renderCodeTablePlusPI(s(4), os); + + os << s(2) << "\n" + << "\n"; + } + + void RenderMachineFunction::getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addRequired(); + au.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(au); + } + + bool RenderMachineFunction::runOnMachineFunction(MachineFunction &fn) { + + mf = &fn; + mri = &mf->getRegInfo(); + tri = mf->getTarget().getRegisterInfo(); + lis = &getAnalysis(); + sis = &getAnalysis(); + + trei.setup(mf, mri, tri, lis); + ro.setup(mf, tri, lis, this); + spillIntervals.clear(); + spillFor.clear(); + useDefs.clear(); + + fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." + + mf->getFunction()->getName().str(); + + return false; + } + + void RenderMachineFunction::releaseMemory() { + trei.clear(); + ro.clear(); + spillIntervals.clear(); + spillFor.clear(); + useDefs.clear(); + } + + void RenderMachineFunction::rememberUseDefs(const LiveInterval *li) { + + if (!ro.shouldRenderCurrentMachineFunction()) + return; + + for (MachineRegisterInfo::reg_iterator rItr = mri->reg_begin(li->reg), + rEnd = mri->reg_end(); + rItr != rEnd; ++rItr) { + const MachineInstr *mi = &*rItr; + if (mi->readsRegister(li->reg)) { + useDefs[li].insert(lis->getInstructionIndex(mi).getUseIndex()); + } + if (mi->definesRegister(li->reg)) { + useDefs[li].insert(lis->getInstructionIndex(mi).getDefIndex()); + } + } + } + + void RenderMachineFunction::rememberSpills( + const LiveInterval *li, + const std::vector &spills) { + + if (!ro.shouldRenderCurrentMachineFunction()) + return; + + for (std::vector::const_iterator siItr = spills.begin(), + siEnd = spills.end(); + siItr != siEnd; ++siItr) { + const LiveInterval *spill = *siItr; + spillIntervals[li].insert(spill); + spillFor[spill] = li; + } + } + + bool RenderMachineFunction::isSpill(const LiveInterval *li) const { + SpillForMap::const_iterator sfItr = spillFor.find(li); + if (sfItr == spillFor.end()) + return false; + return true; + } + + void RenderMachineFunction::renderMachineFunction( + const char *renderContextStr, + const VirtRegMap *vrm, + const char *renderSuffix) { + if (!ro.shouldRenderCurrentMachineFunction()) + return; + + this->vrm = vrm; + trei.reset(); + + std::string rpFileName(mf->getFunction()->getName().str() + + (renderSuffix ? renderSuffix : "") + + outputFileSuffix); + + std::string errMsg; + raw_fd_ostream outFile(rpFileName.c_str(), errMsg, raw_fd_ostream::F_Binary); + + renderFunctionPage(outFile, renderContextStr); + + ro.resetRenderSpecificOptions(); + } + + std::string RenderMachineFunction::escapeChars(const std::string &s) const { + return escapeChars(s.begin(), s.end()); + } + +} diff --git a/final/lib/CodeGen/RenderMachineFunction.h b/final/lib/CodeGen/RenderMachineFunction.h new file mode 100644 index 00000000000..85719923c0c --- /dev/null +++ b/final/lib/CodeGen/RenderMachineFunction.h @@ -0,0 +1,338 @@ +//===-- llvm/CodeGen/RenderMachineFunction.h - MF->HTML -*- C++ -*---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_RENDERMACHINEFUNCTION_H +#define LLVM_CODEGEN_RENDERMACHINEFUNCTION_H + +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Target/TargetRegisterInfo.h" + +#include +#include +#include +#include + +namespace llvm { + + class LiveInterval; + class LiveIntervals; + class MachineInstr; + class MachineRegisterInfo; + class RenderMachineFunction; + class TargetRegisterClass; + class TargetRegisterInfo; + class VirtRegMap; + class raw_ostream; + + /// \brief Helper class to process rendering options. Tries to be as lazy as + /// possible. + class MFRenderingOptions { + public: + + struct RegClassComp { + bool operator()(const TargetRegisterClass *trc1, + const TargetRegisterClass *trc2) const { + std::string trc1Name(trc1->getName()), trc2Name(trc2->getName()); + return std::lexicographical_compare(trc1Name.begin(), trc1Name.end(), + trc2Name.begin(), trc2Name.end()); + } + }; + + typedef std::set RegClassSet; + + struct IntervalComp { + bool operator()(const LiveInterval *li1, const LiveInterval *li2) const { + return li1->reg < li2->reg; + } + }; + + typedef std::set IntervalSet; + + /// Initialise the rendering options. + void setup(MachineFunction *mf, const TargetRegisterInfo *tri, + LiveIntervals *lis, const RenderMachineFunction *rmf); + + /// Clear translations of options to the current function. + void clear(); + + /// Reset any options computed for this specific rendering. + void resetRenderSpecificOptions(); + + /// Should we render the current function. + bool shouldRenderCurrentMachineFunction() const; + + /// Return the set of register classes to render pressure for. + const RegClassSet& regClasses() const; + + /// Return the set of live intervals to render liveness for. + const IntervalSet& intervals() const; + + /// Render indexes which are not associated with instructions / MBB starts. + bool renderEmptyIndexes() const; + + /// Return whether or not to render using SVG for fancy vertical text. + bool fancyVerticals() const; + + private: + + static bool renderingOptionsProcessed; + static std::set mfNamesToRender; + static bool renderAllMFs; + + static std::set classNamesToRender; + static bool renderAllClasses; + + + static std::set > intervalNumsToRender; + typedef enum { ExplicitOnly = 0, + AllPhys = 1, + VirtNoSpills = 2, + VirtSpills = 4, + AllVirt = 6, + All = 7 } + IntervalTypesToRender; + static unsigned intervalTypesToRender; + + template + static void splitComaSeperatedList(const std::string &s, OutputItr outItr); + + static void processOptions(); + + static void processFuncNames(); + static void processRegClassNames(); + static void processIntervalNumbers(); + + static void processIntervalRange(const std::string &intervalRangeStr); + + MachineFunction *mf; + const TargetRegisterInfo *tri; + LiveIntervals *lis; + const RenderMachineFunction *rmf; + + mutable bool regClassesTranslatedToCurrentFunction; + mutable RegClassSet regClassSet; + + mutable bool intervalsTranslatedToCurrentFunction; + mutable IntervalSet intervalSet; + + void translateRegClassNamesToCurrentFunction() const; + + void translateIntervalNumbersToCurrentFunction() const; + }; + + /// \brief Provide extra information about the physical and virtual registers + /// in the function being compiled. + class TargetRegisterExtraInfo { + public: + TargetRegisterExtraInfo(); + + /// \brief Set up TargetRegisterExtraInfo with pointers to necessary + /// sources of information. + void setup(MachineFunction *mf, MachineRegisterInfo *mri, + const TargetRegisterInfo *tri, LiveIntervals *lis); + + /// \brief Recompute tables for changed function. + void reset(); + + /// \brief Free all tables in TargetRegisterExtraInfo. + void clear(); + + /// \brief Maximum number of registers from trc which alias reg. + unsigned getWorst(unsigned reg, const TargetRegisterClass *trc) const; + + /// \brief Returns the number of allocable registers in trc. + unsigned getCapacity(const TargetRegisterClass *trc) const; + + /// \brief Return the number of registers of class trc that may be + /// needed at slot i. + unsigned getPressureAtSlot(const TargetRegisterClass *trc, + SlotIndex i) const; + + /// \brief Return true if the number of registers of type trc that may be + /// needed at slot i is greater than the capacity of trc. + bool classOverCapacityAtSlot(const TargetRegisterClass *trc, + SlotIndex i) const; + + private: + + MachineFunction *mf; + MachineRegisterInfo *mri; + const TargetRegisterInfo *tri; + LiveIntervals *lis; + + typedef std::map WorstMapLine; + typedef std::map VRWorstMap; + VRWorstMap vrWorst; + + typedef std::map PRWorstMap; + PRWorstMap prWorst; + + typedef std::map CapacityMap; + CapacityMap capacityMap; + + typedef std::map PressureMapLine; + typedef std::map PressureMap; + PressureMap pressureMap; + + bool mapsPopulated; + + /// \brief Initialise the 'worst' table. + void initWorst(); + + /// \brief Initialise the 'capacity' table. + void initCapacity(); + + /// \brief Initialise/Reset the 'pressure' and live states tables. + void resetPressureAndLiveStates(); + }; + + /// \brief Render MachineFunction objects and related information to a HTML + /// page. + class RenderMachineFunction : public MachineFunctionPass { + public: + static char ID; + + RenderMachineFunction() : MachineFunctionPass(ID) { + initializeRenderMachineFunctionPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + + virtual void releaseMemory(); + + void rememberUseDefs(const LiveInterval *li); + + void rememberSpills(const LiveInterval *li, + const std::vector &spills); + + bool isSpill(const LiveInterval *li) const; + + /// \brief Render this machine function to HTML. + /// + /// @param renderContextStr This parameter will be included in the top of + /// the html file to explain where (in the + /// codegen pipeline) this function was rendered + /// from. Set it to something like + /// "Pre-register-allocation". + /// @param vrm If non-null the VRM will be queried to determine + /// whether a virtual register was allocated to a + /// physical register or spilled. + /// @param renderFilePrefix This string will be appended to the function + /// name (before the output file suffix) to enable + /// multiple renderings from the same function. + void renderMachineFunction(const char *renderContextStr, + const VirtRegMap *vrm = 0, + const char *renderSuffix = 0); + + private: + class Spacer; + friend raw_ostream& operator<<(raw_ostream &os, const Spacer &s); + + std::string fqn; + + MachineFunction *mf; + MachineRegisterInfo *mri; + const TargetRegisterInfo *tri; + LiveIntervals *lis; + SlotIndexes *sis; + const VirtRegMap *vrm; + + TargetRegisterExtraInfo trei; + MFRenderingOptions ro; + + + + // Utilities. + typedef enum { Dead, Defined, Used, AliveReg, AliveStack } LiveState; + LiveState getLiveStateAt(const LiveInterval *li, SlotIndex i) const; + + typedef enum { Zero, Low, High } PressureState; + PressureState getPressureStateAt(const TargetRegisterClass *trc, + SlotIndex i) const; + + typedef std::map > + SpillIntervals; + SpillIntervals spillIntervals; + + typedef std::map SpillForMap; + SpillForMap spillFor; + + typedef std::set SlotSet; + typedef std::map UseDefs; + UseDefs useDefs; + + // ---------- Rendering methods ---------- + + /// For inserting spaces when pretty printing. + class Spacer { + public: + explicit Spacer(unsigned numSpaces) : ns(numSpaces) {} + Spacer operator+(const Spacer &o) const { return Spacer(ns + o.ns); } + void print(raw_ostream &os) const; + private: + unsigned ns; + }; + + Spacer s(unsigned ns) const; + + template + std::string escapeChars(Iterator sBegin, Iterator sEnd) const; + + /// \brief Render a machine instruction. + void renderMachineInstr(raw_ostream &os, + const MachineInstr *mi) const; + + /// \brief Render vertical text. + template + void renderVertical(const Spacer &indent, + raw_ostream &os, + const T &t) const; + + /// \brief Insert CSS layout info. + void insertCSS(const Spacer &indent, + raw_ostream &os) const; + + /// \brief Render a brief summary of the function (including rendering + /// context). + void renderFunctionSummary(const Spacer &indent, + raw_ostream &os, + const char * const renderContextStr) const; + + /// \brief Render a legend for the pressure table. + void renderPressureTableLegend(const Spacer &indent, + raw_ostream &os) const; + + /// \brief Render a consecutive set of HTML cells of the same class using + /// the colspan attribute for run-length encoding. + template + void renderCellsWithRLE( + const Spacer &indent, raw_ostream &os, + const std::pair &rleAccumulator, + const std::map &cellTypeStrs) const; + + /// \brief Render code listing, potentially with register pressure + /// and live intervals shown alongside. + void renderCodeTablePlusPI(const Spacer &indent, + raw_ostream &os) const; + + /// \brief Render the HTML page representing the MachineFunction. + void renderFunctionPage(raw_ostream &os, + const char * const renderContextStr) const; + + std::string escapeChars(const std::string &s) const; + }; +} + +#endif /* LLVM_CODEGEN_RENDERMACHINEFUNCTION_H */ diff --git a/final/lib/CodeGen/ScheduleDAG.cpp b/final/lib/CodeGen/ScheduleDAG.cpp new file mode 100644 index 00000000000..3388889c9e9 --- /dev/null +++ b/final/lib/CodeGen/ScheduleDAG.cpp @@ -0,0 +1,595 @@ +//===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG class, which is a base class used by +// scheduling implementation classes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +ScheduleDAG::ScheduleDAG(MachineFunction &mf) + : TM(mf.getTarget()), + TII(TM.getInstrInfo()), + TRI(TM.getRegisterInfo()), + MF(mf), MRI(mf.getRegInfo()), + EntrySU(), ExitSU() { +} + +ScheduleDAG::~ScheduleDAG() {} + +/// getInstrDesc helper to handle SDNodes. +const TargetInstrDesc *ScheduleDAG::getNodeDesc(const SDNode *Node) const { + if (!Node || !Node->isMachineOpcode()) return NULL; + return &TII->get(Node->getMachineOpcode()); +} + +/// dump - dump the schedule. +void ScheduleDAG::dumpSchedule() const { + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + if (SUnit *SU = Sequence[i]) + SU->dump(this); + else + dbgs() << "**** NOOP ****\n"; + } +} + + +/// Run - perform scheduling. +/// +void ScheduleDAG::Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos) { + BB = bb; + InsertPos = insertPos; + + SUnits.clear(); + Sequence.clear(); + EntrySU = SUnit(); + ExitSU = SUnit(); + + Schedule(); + + DEBUG({ + dbgs() << "*** Final schedule ***\n"; + dumpSchedule(); + dbgs() << '\n'; + }); +} + +/// addPred - This adds the specified edge as a pred of the current node if +/// not already. It also adds the current node as a successor of the +/// specified node. +bool SUnit::addPred(const SDep &D) { + // If this node already has this depenence, don't add a redundant one. + for (SmallVector::const_iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) + if (*I == D) + return false; + // Now add a corresponding succ to N. + SDep P = D; + P.setSUnit(this); + SUnit *N = D.getSUnit(); + // Update the bookkeeping. + if (D.getKind() == SDep::Data) { + assert(NumPreds < UINT_MAX && "NumPreds will overflow!"); + assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!"); + ++NumPreds; + ++N->NumSuccs; + } + if (!N->isScheduled) { + assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!"); + ++NumPredsLeft; + } + if (!isScheduled) { + assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); + ++N->NumSuccsLeft; + } + Preds.push_back(D); + N->Succs.push_back(P); + if (P.getLatency() != 0) { + this->setDepthDirty(); + N->setHeightDirty(); + } + return true; +} + +/// removePred - This removes the specified edge as a pred of the current +/// node if it exists. It also removes the current node as a successor of +/// the specified node. +void SUnit::removePred(const SDep &D) { + // Find the matching predecessor. + for (SmallVector::iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) + if (*I == D) { + bool FoundSucc = false; + // Find the corresponding successor in N. + SDep P = D; + P.setSUnit(this); + SUnit *N = D.getSUnit(); + for (SmallVector::iterator II = N->Succs.begin(), + EE = N->Succs.end(); II != EE; ++II) + if (*II == P) { + FoundSucc = true; + N->Succs.erase(II); + break; + } + assert(FoundSucc && "Mismatching preds / succs lists!"); + Preds.erase(I); + // Update the bookkeeping. + if (P.getKind() == SDep::Data) { + assert(NumPreds > 0 && "NumPreds will underflow!"); + assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); + --NumPreds; + --N->NumSuccs; + } + if (!N->isScheduled) { + assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); + --NumPredsLeft; + } + if (!isScheduled) { + assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); + --N->NumSuccsLeft; + } + if (P.getLatency() != 0) { + this->setDepthDirty(); + N->setHeightDirty(); + } + return; + } +} + +void SUnit::setDepthDirty() { + if (!isDepthCurrent) return; + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *SU = WorkList.pop_back_val(); + SU->isDepthCurrent = false; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), + E = SU->Succs.end(); I != E; ++I) { + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isDepthCurrent) + WorkList.push_back(SuccSU); + } + } while (!WorkList.empty()); +} + +void SUnit::setHeightDirty() { + if (!isHeightCurrent) return; + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *SU = WorkList.pop_back_val(); + SU->isHeightCurrent = false; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), + E = SU->Preds.end(); I != E; ++I) { + SUnit *PredSU = I->getSUnit(); + if (PredSU->isHeightCurrent) + WorkList.push_back(PredSU); + } + } while (!WorkList.empty()); +} + +/// setDepthToAtLeast - Update this node's successors to reflect the +/// fact that this node's depth just increased. +/// +void SUnit::setDepthToAtLeast(unsigned NewDepth) { + if (NewDepth <= getDepth()) + return; + setDepthDirty(); + Depth = NewDepth; + isDepthCurrent = true; +} + +/// setHeightToAtLeast - Update this node's predecessors to reflect the +/// fact that this node's height just increased. +/// +void SUnit::setHeightToAtLeast(unsigned NewHeight) { + if (NewHeight <= getHeight()) + return; + setHeightDirty(); + Height = NewHeight; + isHeightCurrent = true; +} + +/// ComputeDepth - Calculate the maximal path from the node to the exit. +/// +void SUnit::ComputeDepth() { + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *Cur = WorkList.back(); + + bool Done = true; + unsigned MaxPredDepth = 0; + for (SUnit::const_pred_iterator I = Cur->Preds.begin(), + E = Cur->Preds.end(); I != E; ++I) { + SUnit *PredSU = I->getSUnit(); + if (PredSU->isDepthCurrent) + MaxPredDepth = std::max(MaxPredDepth, + PredSU->Depth + I->getLatency()); + else { + Done = false; + WorkList.push_back(PredSU); + } + } + + if (Done) { + WorkList.pop_back(); + if (MaxPredDepth != Cur->Depth) { + Cur->setDepthDirty(); + Cur->Depth = MaxPredDepth; + } + Cur->isDepthCurrent = true; + } + } while (!WorkList.empty()); +} + +/// ComputeHeight - Calculate the maximal path from the node to the entry. +/// +void SUnit::ComputeHeight() { + SmallVector WorkList; + WorkList.push_back(this); + do { + SUnit *Cur = WorkList.back(); + + bool Done = true; + unsigned MaxSuccHeight = 0; + for (SUnit::const_succ_iterator I = Cur->Succs.begin(), + E = Cur->Succs.end(); I != E; ++I) { + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isHeightCurrent) + MaxSuccHeight = std::max(MaxSuccHeight, + SuccSU->Height + I->getLatency()); + else { + Done = false; + WorkList.push_back(SuccSU); + } + } + + if (Done) { + WorkList.pop_back(); + if (MaxSuccHeight != Cur->Height) { + Cur->setHeightDirty(); + Cur->Height = MaxSuccHeight; + } + Cur->isHeightCurrent = true; + } + } while (!WorkList.empty()); +} + +/// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or +/// a group of nodes flagged together. +void SUnit::dump(const ScheduleDAG *G) const { + dbgs() << "SU(" << NodeNum << "): "; + G->dumpNode(this); +} + +void SUnit::dumpAll(const ScheduleDAG *G) const { + dump(G); + + dbgs() << " # preds left : " << NumPredsLeft << "\n"; + dbgs() << " # succs left : " << NumSuccsLeft << "\n"; + dbgs() << " # rdefs left : " << NumRegDefsLeft << "\n"; + dbgs() << " Latency : " << Latency << "\n"; + dbgs() << " Depth : " << Depth << "\n"; + dbgs() << " Height : " << Height << "\n"; + + if (Preds.size() != 0) { + dbgs() << " Predecessors:\n"; + for (SUnit::const_succ_iterator I = Preds.begin(), E = Preds.end(); + I != E; ++I) { + dbgs() << " "; + switch (I->getKind()) { + case SDep::Data: dbgs() << "val "; break; + case SDep::Anti: dbgs() << "anti"; break; + case SDep::Output: dbgs() << "out "; break; + case SDep::Order: dbgs() << "ch "; break; + } + dbgs() << "#"; + dbgs() << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; + if (I->isArtificial()) + dbgs() << " *"; + dbgs() << ": Latency=" << I->getLatency(); + dbgs() << "\n"; + } + } + if (Succs.size() != 0) { + dbgs() << " Successors:\n"; + for (SUnit::const_succ_iterator I = Succs.begin(), E = Succs.end(); + I != E; ++I) { + dbgs() << " "; + switch (I->getKind()) { + case SDep::Data: dbgs() << "val "; break; + case SDep::Anti: dbgs() << "anti"; break; + case SDep::Output: dbgs() << "out "; break; + case SDep::Order: dbgs() << "ch "; break; + } + dbgs() << "#"; + dbgs() << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; + if (I->isArtificial()) + dbgs() << " *"; + dbgs() << ": Latency=" << I->getLatency(); + dbgs() << "\n"; + } + } + dbgs() << "\n"; +} + +#ifndef NDEBUG +/// VerifySchedule - Verify that all SUnits were scheduled and that +/// their state is consistent. +/// +void ScheduleDAG::VerifySchedule(bool isBottomUp) { + bool AnyNotSched = false; + unsigned DeadNodes = 0; + unsigned Noops = 0; + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + if (!SUnits[i].isScheduled) { + if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) { + ++DeadNodes; + continue; + } + if (!AnyNotSched) + dbgs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + dbgs() << "has not been scheduled!\n"; + AnyNotSched = true; + } + if (SUnits[i].isScheduled && + (isBottomUp ? SUnits[i].getHeight() : SUnits[i].getDepth()) > + unsigned(INT_MAX)) { + if (!AnyNotSched) + dbgs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + dbgs() << "has an unexpected " + << (isBottomUp ? "Height" : "Depth") << " value!\n"; + AnyNotSched = true; + } + if (isBottomUp) { + if (SUnits[i].NumSuccsLeft != 0) { + if (!AnyNotSched) + dbgs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + dbgs() << "has successors left!\n"; + AnyNotSched = true; + } + } else { + if (SUnits[i].NumPredsLeft != 0) { + if (!AnyNotSched) + dbgs() << "*** Scheduling failed! ***\n"; + SUnits[i].dump(this); + dbgs() << "has predecessors left!\n"; + AnyNotSched = true; + } + } + } + for (unsigned i = 0, e = Sequence.size(); i != e; ++i) + if (!Sequence[i]) + ++Noops; + assert(!AnyNotSched); + assert(Sequence.size() + DeadNodes - Noops == SUnits.size() && + "The number of nodes scheduled doesn't match the expected number!"); +} +#endif + +/// InitDAGTopologicalSorting - create the initial topological +/// ordering from the DAG to be scheduled. +/// +/// The idea of the algorithm is taken from +/// "Online algorithms for managing the topological order of +/// a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly +/// This is the MNR algorithm, which was first introduced by +/// A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in +/// "Maintaining a topological order under edge insertions". +/// +/// Short description of the algorithm: +/// +/// Topological ordering, ord, of a DAG maps each node to a topological +/// index so that for all edges X->Y it is the case that ord(X) < ord(Y). +/// +/// This means that if there is a path from the node X to the node Z, +/// then ord(X) < ord(Z). +/// +/// This property can be used to check for reachability of nodes: +/// if Z is reachable from X, then an insertion of the edge Z->X would +/// create a cycle. +/// +/// The algorithm first computes a topological ordering for the DAG by +/// initializing the Index2Node and Node2Index arrays and then tries to keep +/// the ordering up-to-date after edge insertions by reordering the DAG. +/// +/// On insertion of the edge X->Y, the algorithm first marks by calling DFS +/// the nodes reachable from Y, and then shifts them using Shift to lie +/// immediately after X in Index2Node. +void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { + unsigned DAGSize = SUnits.size(); + std::vector WorkList; + WorkList.reserve(DAGSize); + + Index2Node.resize(DAGSize); + Node2Index.resize(DAGSize); + + // Initialize the data structures. + for (unsigned i = 0, e = DAGSize; i != e; ++i) { + SUnit *SU = &SUnits[i]; + int NodeNum = SU->NodeNum; + unsigned Degree = SU->Succs.size(); + // Temporarily use the Node2Index array as scratch space for degree counts. + Node2Index[NodeNum] = Degree; + + // Is it a node without dependencies? + if (Degree == 0) { + assert(SU->Succs.empty() && "SUnit should have no successors"); + // Collect leaf nodes. + WorkList.push_back(SU); + } + } + + int Id = DAGSize; + while (!WorkList.empty()) { + SUnit *SU = WorkList.back(); + WorkList.pop_back(); + Allocate(SU->NodeNum, --Id); + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + SUnit *SU = I->getSUnit(); + if (!--Node2Index[SU->NodeNum]) + // If all dependencies of the node are processed already, + // then the node can be computed now. + WorkList.push_back(SU); + } + } + + Visited.resize(DAGSize); + +#ifndef NDEBUG + // Check correctness of the ordering + for (unsigned i = 0, e = DAGSize; i != e; ++i) { + SUnit *SU = &SUnits[i]; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + assert(Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && + "Wrong topological sorting"); + } + } +#endif +} + +/// AddPred - Updates the topological ordering to accomodate an edge +/// to be added from SUnit X to SUnit Y. +void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { + int UpperBound, LowerBound; + LowerBound = Node2Index[Y->NodeNum]; + UpperBound = Node2Index[X->NodeNum]; + bool HasLoop = false; + // Is Ord(X) < Ord(Y) ? + if (LowerBound < UpperBound) { + // Update the topological order. + Visited.reset(); + DFS(Y, UpperBound, HasLoop); + assert(!HasLoop && "Inserted edge creates a loop!"); + // Recompute topological indexes. + Shift(Visited, LowerBound, UpperBound); + } +} + +/// RemovePred - Updates the topological ordering to accomodate an +/// an edge to be removed from the specified node N from the predecessors +/// of the current node M. +void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { + // InitDAGTopologicalSorting(); +} + +/// DFS - Make a DFS traversal to mark all nodes reachable from SU and mark +/// all nodes affected by the edge insertion. These nodes will later get new +/// topological indexes by means of the Shift method. +void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, + bool &HasLoop) { + std::vector WorkList; + WorkList.reserve(SUnits.size()); + + WorkList.push_back(SU); + do { + SU = WorkList.back(); + WorkList.pop_back(); + Visited.set(SU->NodeNum); + for (int I = SU->Succs.size()-1; I >= 0; --I) { + int s = SU->Succs[I].getSUnit()->NodeNum; + if (Node2Index[s] == UpperBound) { + HasLoop = true; + return; + } + // Visit successors if not already and in affected region. + if (!Visited.test(s) && Node2Index[s] < UpperBound) { + WorkList.push_back(SU->Succs[I].getSUnit()); + } + } + } while (!WorkList.empty()); +} + +/// Shift - Renumber the nodes so that the topological ordering is +/// preserved. +void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, + int UpperBound) { + std::vector L; + int shift = 0; + int i; + + for (i = LowerBound; i <= UpperBound; ++i) { + // w is node at topological index i. + int w = Index2Node[i]; + if (Visited.test(w)) { + // Unmark. + Visited.reset(w); + L.push_back(w); + shift = shift + 1; + } else { + Allocate(w, i - shift); + } + } + + for (unsigned j = 0; j < L.size(); ++j) { + Allocate(L[j], i - shift); + i = i + 1; + } +} + + +/// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will +/// create a cycle. +bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *SU, SUnit *TargetSU) { + if (IsReachable(TargetSU, SU)) + return true; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (I->isAssignedRegDep() && + IsReachable(TargetSU, I->getSUnit())) + return true; + return false; +} + +/// IsReachable - Checks if SU is reachable from TargetSU. +bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, + const SUnit *TargetSU) { + // If insertion of the edge SU->TargetSU would create a cycle + // then there is a path from TargetSU to SU. + int UpperBound, LowerBound; + LowerBound = Node2Index[TargetSU->NodeNum]; + UpperBound = Node2Index[SU->NodeNum]; + bool HasLoop = false; + // Is Ord(TargetSU) < Ord(SU) ? + if (LowerBound < UpperBound) { + Visited.reset(); + // There may be a path from TargetSU to SU. Check for it. + DFS(TargetSU, UpperBound, HasLoop); + } + return HasLoop; +} + +/// Allocate - assign the topological index to the node n. +void ScheduleDAGTopologicalSort::Allocate(int n, int index) { + Node2Index[n] = index; + Index2Node[index] = n; +} + +ScheduleDAGTopologicalSort:: +ScheduleDAGTopologicalSort(std::vector &sunits) : SUnits(sunits) {} + +ScheduleHazardRecognizer::~ScheduleHazardRecognizer() {} diff --git a/final/lib/CodeGen/ScheduleDAGEmit.cpp b/final/lib/CodeGen/ScheduleDAGEmit.cpp new file mode 100644 index 00000000000..6b7a8c6491b --- /dev/null +++ b/final/lib/CodeGen/ScheduleDAGEmit.cpp @@ -0,0 +1,67 @@ +//===---- ScheduleDAGEmit.cpp - Emit routines for the ScheduleDAG class ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the Emit routines for the ScheduleDAG class, which creates +// MachineInstrs according to the computed schedule. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +void ScheduleDAG::EmitNoop() { + TII->insertNoop(*BB, InsertPos); +} + +void ScheduleDAG::EmitPhysRegCopy(SUnit *SU, + DenseMap &VRBaseMap) { + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + if (I->getSUnit()->CopyDstRC) { + // Copy to physical register. + DenseMap::iterator VRI = VRBaseMap.find(I->getSUnit()); + assert(VRI != VRBaseMap.end() && "Node emitted out of order - late"); + // Find the destination physical register. + unsigned Reg = 0; + for (SUnit::const_succ_iterator II = SU->Succs.begin(), + EE = SU->Succs.end(); II != EE; ++II) { + if (II->getReg()) { + Reg = II->getReg(); + break; + } + } + BuildMI(*BB, InsertPos, DebugLoc(), TII->get(TargetOpcode::COPY), Reg) + .addReg(VRI->second); + } else { + // Copy from physical register. + assert(I->getReg() && "Unknown physical register!"); + unsigned VRBase = MRI.createVirtualRegister(SU->CopyDstRC); + bool isNew = VRBaseMap.insert(std::make_pair(SU, VRBase)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + BuildMI(*BB, InsertPos, DebugLoc(), TII->get(TargetOpcode::COPY), VRBase) + .addReg(I->getReg()); + } + break; + } +} diff --git a/final/lib/CodeGen/ScheduleDAGInstrs.cpp b/final/lib/CodeGen/ScheduleDAGInstrs.cpp new file mode 100644 index 00000000000..f17023eabb7 --- /dev/null +++ b/final/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -0,0 +1,693 @@ +//===---- ScheduleDAGInstrs.cpp - MachineInstr Rescheduling ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAGInstrs class, which implements re-scheduling +// of MachineInstrs. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sched-instrs" +#include "ScheduleDAGInstrs.h" +#include "llvm/Operator.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +using namespace llvm; + +ScheduleDAGInstrs::ScheduleDAGInstrs(MachineFunction &mf, + const MachineLoopInfo &mli, + const MachineDominatorTree &mdt) + : ScheduleDAG(mf), MLI(mli), MDT(mdt), MFI(mf.getFrameInfo()), + InstrItins(mf.getTarget().getInstrItineraryData()), + Defs(TRI->getNumRegs()), Uses(TRI->getNumRegs()), LoopRegs(MLI, MDT) { + DbgValueVec.clear(); +} + +/// Run - perform scheduling. +/// +void ScheduleDAGInstrs::Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount) { + BB = bb; + Begin = begin; + InsertPosIndex = endcount; + + ScheduleDAG::Run(bb, end); +} + +/// getUnderlyingObjectFromInt - This is the function that does the work of +/// looking through basic ptrtoint+arithmetic+inttoptr sequences. +static const Value *getUnderlyingObjectFromInt(const Value *V) { + do { + if (const Operator *U = dyn_cast(V)) { + // If we find a ptrtoint, we can transfer control back to the + // regular getUnderlyingObjectFromInt. + if (U->getOpcode() == Instruction::PtrToInt) + return U->getOperand(0); + // If we find an add of a constant or a multiplied value, it's + // likely that the other operand will lead us to the base + // object. We don't have to worry about the case where the + // object address is somehow being computed by the multiply, + // because our callers only care when the result is an + // identifibale object. + if (U->getOpcode() != Instruction::Add || + (!isa(U->getOperand(1)) && + Operator::getOpcode(U->getOperand(1)) != Instruction::Mul)) + return V; + V = U->getOperand(0); + } else { + return V; + } + assert(V->getType()->isIntegerTy() && "Unexpected operand type!"); + } while (1); +} + +/// getUnderlyingObject - This is a wrapper around GetUnderlyingObject +/// and adds support for basic ptrtoint+arithmetic+inttoptr sequences. +static const Value *getUnderlyingObject(const Value *V) { + // First just call Value::getUnderlyingObject to let it do what it does. + do { + V = GetUnderlyingObject(V); + // If it found an inttoptr, use special code to continue climing. + if (Operator::getOpcode(V) != Instruction::IntToPtr) + break; + const Value *O = getUnderlyingObjectFromInt(cast(V)->getOperand(0)); + // If that succeeded in finding a pointer, continue the search. + if (!O->getType()->isPointerTy()) + break; + V = O; + } while (1); + return V; +} + +/// getUnderlyingObjectForInstr - If this machine instr has memory reference +/// information and it can be tracked to a normal reference to a known +/// object, return the Value for that object. Otherwise return null. +static const Value *getUnderlyingObjectForInstr(const MachineInstr *MI, + const MachineFrameInfo *MFI, + bool &MayAlias) { + MayAlias = true; + if (!MI->hasOneMemOperand() || + !(*MI->memoperands_begin())->getValue() || + (*MI->memoperands_begin())->isVolatile()) + return 0; + + const Value *V = (*MI->memoperands_begin())->getValue(); + if (!V) + return 0; + + V = getUnderlyingObject(V); + if (const PseudoSourceValue *PSV = dyn_cast(V)) { + // For now, ignore PseudoSourceValues which may alias LLVM IR values + // because the code that uses this function has no way to cope with + // such aliases. + if (PSV->isAliased(MFI)) + return 0; + + MayAlias = PSV->mayAlias(MFI); + return V; + } + + if (isIdentifiedObject(V)) + return V; + + return 0; +} + +void ScheduleDAGInstrs::StartBlock(MachineBasicBlock *BB) { + if (MachineLoop *ML = MLI.getLoopFor(BB)) + if (BB == ML->getLoopLatch()) { + MachineBasicBlock *Header = ML->getHeader(); + for (MachineBasicBlock::livein_iterator I = Header->livein_begin(), + E = Header->livein_end(); I != E; ++I) + LoopLiveInRegs.insert(*I); + LoopRegs.VisitLoop(ML); + } +} + +/// AddSchedBarrierDeps - Add dependencies from instructions in the current +/// list of instructions being scheduled to scheduling barrier by adding +/// the exit SU to the register defs and use list. This is because we want to +/// make sure instructions which define registers that are either used by +/// the terminator or are live-out are properly scheduled. This is +/// especially important when the definition latency of the return value(s) +/// are too high to be hidden by the branch or when the liveout registers +/// used by instructions in the fallthrough block. +void ScheduleDAGInstrs::AddSchedBarrierDeps() { + MachineInstr *ExitMI = InsertPos != BB->end() ? &*InsertPos : 0; + ExitSU.setInstr(ExitMI); + bool AllDepKnown = ExitMI && + (ExitMI->getDesc().isCall() || ExitMI->getDesc().isBarrier()); + if (ExitMI && AllDepKnown) { + // If it's a call or a barrier, add dependencies on the defs and uses of + // instruction. + for (unsigned i = 0, e = ExitMI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = ExitMI->getOperand(i); + if (!MO.isReg() || MO.isDef()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!"); + Uses[Reg].push_back(&ExitSU); + } + } else { + // For others, e.g. fallthrough, conditional branch, assume the exit + // uses all the registers that are livein to the successor blocks. + SmallSet Seen; + for (MachineBasicBlock::succ_iterator SI = BB->succ_begin(), + SE = BB->succ_end(); SI != SE; ++SI) + for (MachineBasicBlock::livein_iterator I = (*SI)->livein_begin(), + E = (*SI)->livein_end(); I != E; ++I) { + unsigned Reg = *I; + if (Seen.insert(Reg)) + Uses[Reg].push_back(&ExitSU); + } + } +} + +void ScheduleDAGInstrs::BuildSchedGraph(AliasAnalysis *AA) { + // We'll be allocating one SUnit for each instruction, plus one for + // the region exit node. + SUnits.reserve(BB->size()); + + // We build scheduling units by walking a block's instruction list from bottom + // to top. + + // Remember where a generic side-effecting instruction is as we procede. + SUnit *BarrierChain = 0, *AliasChain = 0; + + // Memory references to specific known memory locations are tracked + // so that they can be given more precise dependencies. We track + // separately the known memory locations that may alias and those + // that are known not to alias + std::map AliasMemDefs, NonAliasMemDefs; + std::map > AliasMemUses, NonAliasMemUses; + + // Keep track of dangling debug references to registers. + std::vector > + DanglingDebugValue(TRI->getNumRegs(), + std::make_pair(static_cast(0), 0)); + + // Check to see if the scheduler cares about latencies. + bool UnitLatencies = ForceUnitLatencies(); + + // Ask the target if address-backscheduling is desirable, and if so how much. + const TargetSubtarget &ST = TM.getSubtarget(); + unsigned SpecialAddressLatency = ST.getSpecialAddressLatency(); + + // Remove any stale debug info; sometimes BuildSchedGraph is called again + // without emitting the info from the previous call. + DbgValueVec.clear(); + + // Model data dependencies between instructions being scheduled and the + // ExitSU. + AddSchedBarrierDeps(); + + // Walk the list of instructions, from bottom moving up. + for (MachineBasicBlock::iterator MII = InsertPos, MIE = Begin; + MII != MIE; --MII) { + MachineInstr *MI = prior(MII); + // DBG_VALUE does not have SUnit's built, so just remember these for later + // reinsertion. + if (MI->isDebugValue()) { + if (MI->getNumOperands()==3 && MI->getOperand(0).isReg() && + MI->getOperand(0).getReg()) + DanglingDebugValue[MI->getOperand(0).getReg()] = + std::make_pair(MI, DbgValueVec.size()); + DbgValueVec.push_back(MI); + continue; + } + const TargetInstrDesc &TID = MI->getDesc(); + assert(!TID.isTerminator() && !MI->isLabel() && + "Cannot schedule terminators or labels!"); + // Create the SUnit for this MI. + SUnit *SU = NewSUnit(MI); + SU->isCall = TID.isCall(); + SU->isCommutable = TID.isCommutable(); + + // Assign the Latency field of SU using target-provided information. + if (UnitLatencies) + SU->Latency = 1; + else + ComputeLatency(SU); + + // Add register-based dependencies (data, anti, and output). + for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) { + const MachineOperand &MO = MI->getOperand(j); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) continue; + + assert(TRI->isPhysicalRegister(Reg) && "Virtual register encountered!"); + + if (MO.isDef() && DanglingDebugValue[Reg].first!=0) { + SU->DbgInstrList.push_back(DanglingDebugValue[Reg].first); + DbgValueVec[DanglingDebugValue[Reg].second] = 0; + DanglingDebugValue[Reg] = std::make_pair((MachineInstr*)0, 0); + } + + std::vector &UseList = Uses[Reg]; + std::vector &DefList = Defs[Reg]; + // Optionally add output and anti dependencies. For anti + // dependencies we use a latency of 0 because for a multi-issue + // target we want to allow the defining instruction to issue + // in the same cycle as the using instruction. + // TODO: Using a latency of 1 here for output dependencies assumes + // there's no cost for reusing registers. + SDep::Kind Kind = MO.isUse() ? SDep::Anti : SDep::Output; + unsigned AOLatency = (Kind == SDep::Anti) ? 0 : 1; + for (unsigned i = 0, e = DefList.size(); i != e; ++i) { + SUnit *DefSU = DefList[i]; + if (DefSU == &ExitSU) + continue; + if (DefSU != SU && + (Kind != SDep::Output || !MO.isDead() || + !DefSU->getInstr()->registerDefIsDead(Reg))) + DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/Reg)); + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + std::vector &DefList = Defs[*Alias]; + for (unsigned i = 0, e = DefList.size(); i != e; ++i) { + SUnit *DefSU = DefList[i]; + if (DefSU == &ExitSU) + continue; + if (DefSU != SU && + (Kind != SDep::Output || !MO.isDead() || + !DefSU->getInstr()->registerDefIsDead(*Alias))) + DefSU->addPred(SDep(SU, Kind, AOLatency, /*Reg=*/ *Alias)); + } + } + + if (MO.isDef()) { + // Add any data dependencies. + unsigned DataLatency = SU->Latency; + for (unsigned i = 0, e = UseList.size(); i != e; ++i) { + SUnit *UseSU = UseList[i]; + if (UseSU == SU) + continue; + unsigned LDataLatency = DataLatency; + // Optionally add in a special extra latency for nodes that + // feed addresses. + // TODO: Do this for register aliases too. + // TODO: Perhaps we should get rid of + // SpecialAddressLatency and just move this into + // adjustSchedDependency for the targets that care about it. + if (SpecialAddressLatency != 0 && !UnitLatencies && + UseSU != &ExitSU) { + MachineInstr *UseMI = UseSU->getInstr(); + const TargetInstrDesc &UseTID = UseMI->getDesc(); + int RegUseIndex = UseMI->findRegisterUseOperandIdx(Reg); + assert(RegUseIndex >= 0 && "UseMI doesn's use register!"); + if (RegUseIndex >= 0 && + (UseTID.mayLoad() || UseTID.mayStore()) && + (unsigned)RegUseIndex < UseTID.getNumOperands() && + UseTID.OpInfo[RegUseIndex].isLookupPtrRegClass()) + LDataLatency += SpecialAddressLatency; + } + // Adjust the dependence latency using operand def/use + // information (if any), and then allow the target to + // perform its own adjustments. + const SDep& dep = SDep(SU, SDep::Data, LDataLatency, Reg); + if (!UnitLatencies) { + ComputeOperandLatency(SU, UseSU, const_cast(dep)); + ST.adjustSchedDependency(SU, UseSU, const_cast(dep)); + } + UseSU->addPred(dep); + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) { + std::vector &UseList = Uses[*Alias]; + for (unsigned i = 0, e = UseList.size(); i != e; ++i) { + SUnit *UseSU = UseList[i]; + if (UseSU == SU) + continue; + const SDep& dep = SDep(SU, SDep::Data, DataLatency, *Alias); + if (!UnitLatencies) { + ComputeOperandLatency(SU, UseSU, const_cast(dep)); + ST.adjustSchedDependency(SU, UseSU, const_cast(dep)); + } + UseSU->addPred(dep); + } + } + + // If a def is going to wrap back around to the top of the loop, + // backschedule it. + if (!UnitLatencies && DefList.empty()) { + LoopDependencies::LoopDeps::iterator I = LoopRegs.Deps.find(Reg); + if (I != LoopRegs.Deps.end()) { + const MachineOperand *UseMO = I->second.first; + unsigned Count = I->second.second; + const MachineInstr *UseMI = UseMO->getParent(); + unsigned UseMOIdx = UseMO - &UseMI->getOperand(0); + const TargetInstrDesc &UseTID = UseMI->getDesc(); + // TODO: If we knew the total depth of the region here, we could + // handle the case where the whole loop is inside the region but + // is large enough that the isScheduleHigh trick isn't needed. + if (UseMOIdx < UseTID.getNumOperands()) { + // Currently, we only support scheduling regions consisting of + // single basic blocks. Check to see if the instruction is in + // the same region by checking to see if it has the same parent. + if (UseMI->getParent() != MI->getParent()) { + unsigned Latency = SU->Latency; + if (UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) + Latency += SpecialAddressLatency; + // This is a wild guess as to the portion of the latency which + // will be overlapped by work done outside the current + // scheduling region. + Latency -= std::min(Latency, Count); + // Add the artifical edge. + ExitSU.addPred(SDep(SU, SDep::Order, Latency, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + } else if (SpecialAddressLatency > 0 && + UseTID.OpInfo[UseMOIdx].isLookupPtrRegClass()) { + // The entire loop body is within the current scheduling region + // and the latency of this operation is assumed to be greater + // than the latency of the loop. + // TODO: Recursively mark data-edge predecessors as + // isScheduleHigh too. + SU->isScheduleHigh = true; + } + } + LoopRegs.Deps.erase(I); + } + } + + UseList.clear(); + if (!MO.isDead()) + DefList.clear(); + DefList.push_back(SU); + } else { + UseList.push_back(SU); + } + } + + // Add chain dependencies. + // Chain dependencies used to enforce memory order should have + // latency of 0 (except for true dependency of Store followed by + // aliased Load... we estimate that with a single cycle of latency + // assuming the hardware will bypass) + // Note that isStoreToStackSlot and isLoadFromStackSLot are not usable + // after stack slots are lowered to actual addresses. + // TODO: Use an AliasAnalysis and do real alias-analysis queries, and + // produce more precise dependence information. +#define STORE_LOAD_LATENCY 1 + unsigned TrueMemOrderLatency = 0; + if (TID.isCall() || MI->hasUnmodeledSideEffects() || + (MI->hasVolatileMemoryRef() && + (!TID.mayLoad() || !MI->isInvariantLoad(AA)))) { + // Be conservative with these and add dependencies on all memory + // references, even those that are known to not alias. + for (std::map::iterator I = + NonAliasMemDefs.begin(), E = NonAliasMemDefs.end(); I != E; ++I) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + for (std::map >::iterator I = + NonAliasMemUses.begin(), E = NonAliasMemUses.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + I->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + } + NonAliasMemDefs.clear(); + NonAliasMemUses.clear(); + // Add SU to the barrier chain. + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + BarrierChain = SU; + + // fall-through + new_alias_chain: + // Chain all possibly aliasing memory references though SU. + if (AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + AliasChain = SU; + for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k) + PendingLoads[k]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + for (std::map::iterator I = AliasMemDefs.begin(), + E = AliasMemDefs.end(); I != E; ++I) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + for (std::map >::iterator I = + AliasMemUses.begin(), E = AliasMemUses.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + I->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + } + PendingLoads.clear(); + AliasMemDefs.clear(); + AliasMemUses.clear(); + } else if (TID.mayStore()) { + bool MayAlias = true; + TrueMemOrderLatency = STORE_LOAD_LATENCY; + if (const Value *V = getUnderlyingObjectForInstr(MI, MFI, MayAlias)) { + // A store to a specific PseudoSourceValue. Add precise dependencies. + // Record the def in MemDefs, first adding a dep if there is + // an existing def. + std::map::iterator I = + ((MayAlias) ? AliasMemDefs.find(V) : NonAliasMemDefs.find(V)); + std::map::iterator IE = + ((MayAlias) ? AliasMemDefs.end() : NonAliasMemDefs.end()); + if (I != IE) { + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0, /*Reg=*/0, + /*isNormalMemory=*/true)); + I->second = SU; + } else { + if (MayAlias) + AliasMemDefs[V] = SU; + else + NonAliasMemDefs[V] = SU; + } + // Handle the uses in MemUses, if there are any. + std::map >::iterator J = + ((MayAlias) ? AliasMemUses.find(V) : NonAliasMemUses.find(V)); + std::map >::iterator JE = + ((MayAlias) ? AliasMemUses.end() : NonAliasMemUses.end()); + if (J != JE) { + for (unsigned i = 0, e = J->second.size(); i != e; ++i) + J->second[i]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency, + /*Reg=*/0, /*isNormalMemory=*/true)); + J->second.clear(); + } + if (MayAlias) { + // Add dependencies from all the PendingLoads, i.e. loads + // with no underlying object. + for (unsigned k = 0, m = PendingLoads.size(); k != m; ++k) + PendingLoads[k]->addPred(SDep(SU, SDep::Order, TrueMemOrderLatency)); + // Add dependence on alias chain, if needed. + if (AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + // Add dependence on barrier chain, if needed. + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } else { + // Treat all other stores conservatively. + goto new_alias_chain; + } + + if (!ExitSU.isPred(SU)) + // Push store's up a bit to avoid them getting in between cmp + // and branches. + ExitSU.addPred(SDep(SU, SDep::Order, 0, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + } else if (TID.mayLoad()) { + bool MayAlias = true; + TrueMemOrderLatency = 0; + if (MI->isInvariantLoad(AA)) { + // Invariant load, no chain dependencies needed! + } else { + if (const Value *V = + getUnderlyingObjectForInstr(MI, MFI, MayAlias)) { + // A load from a specific PseudoSourceValue. Add precise dependencies. + std::map::iterator I = + ((MayAlias) ? AliasMemDefs.find(V) : NonAliasMemDefs.find(V)); + std::map::iterator IE = + ((MayAlias) ? AliasMemDefs.end() : NonAliasMemDefs.end()); + if (I != IE) + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0, /*Reg=*/0, + /*isNormalMemory=*/true)); + if (MayAlias) + AliasMemUses[V].push_back(SU); + else + NonAliasMemUses[V].push_back(SU); + } else { + // A load with no underlying object. Depend on all + // potentially aliasing stores. + for (std::map::iterator I = + AliasMemDefs.begin(), E = AliasMemDefs.end(); I != E; ++I) + I->second->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + + PendingLoads.push_back(SU); + MayAlias = true; + } + + // Add dependencies on alias and barrier chains, if needed. + if (MayAlias && AliasChain) + AliasChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + if (BarrierChain) + BarrierChain->addPred(SDep(SU, SDep::Order, /*Latency=*/0)); + } + } + } + + for (int i = 0, e = TRI->getNumRegs(); i != e; ++i) { + Defs[i].clear(); + Uses[i].clear(); + } + PendingLoads.clear(); +} + +void ScheduleDAGInstrs::FinishBlock() { + // Nothing to do. +} + +void ScheduleDAGInstrs::ComputeLatency(SUnit *SU) { + // Compute the latency for the node. + if (!InstrItins || InstrItins->isEmpty()) { + SU->Latency = 1; + + // Simplistic target-independent heuristic: assume that loads take + // extra time. + if (SU->getInstr()->getDesc().mayLoad()) + SU->Latency += 2; + } else { + SU->Latency = TII->getInstrLatency(InstrItins, SU->getInstr()); + } +} + +void ScheduleDAGInstrs::ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const { + if (!InstrItins || InstrItins->isEmpty()) + return; + + // For a data dependency with a known register... + if ((dep.getKind() != SDep::Data) || (dep.getReg() == 0)) + return; + + const unsigned Reg = dep.getReg(); + + // ... find the definition of the register in the defining + // instruction + MachineInstr *DefMI = Def->getInstr(); + int DefIdx = DefMI->findRegisterDefOperandIdx(Reg); + if (DefIdx != -1) { + const MachineOperand &MO = DefMI->getOperand(DefIdx); + if (MO.isReg() && MO.isImplicit() && + DefIdx >= (int)DefMI->getDesc().getNumOperands()) { + // This is an implicit def, getOperandLatency() won't return the correct + // latency. e.g. + // %D6, %D7 = VLD1q16 %R2, 0, ..., %Q3 + // %Q1 = VMULv8i16 %Q1, %Q3, ... + // What we want is to compute latency between def of %D6/%D7 and use of + // %Q3 instead. + DefIdx = DefMI->findRegisterDefOperandIdx(Reg, false, true, TRI); + } + MachineInstr *UseMI = Use->getInstr(); + // For all uses of the register, calculate the maxmimum latency + int Latency = -1; + if (UseMI) { + for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = UseMI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (MOReg != Reg) + continue; + + int UseCycle = TII->getOperandLatency(InstrItins, DefMI, DefIdx, + UseMI, i); + Latency = std::max(Latency, UseCycle); + } + } else { + // UseMI is null, then it must be a scheduling barrier. + if (!InstrItins || InstrItins->isEmpty()) + return; + unsigned DefClass = DefMI->getDesc().getSchedClass(); + Latency = InstrItins->getOperandCycle(DefClass, DefIdx); + } + + // If we found a latency, then replace the existing dependence latency. + if (Latency >= 0) + dep.setLatency(Latency); + } +} + +void ScheduleDAGInstrs::dumpNode(const SUnit *SU) const { + SU->getInstr()->dump(); +} + +std::string ScheduleDAGInstrs::getGraphNodeLabel(const SUnit *SU) const { + std::string s; + raw_string_ostream oss(s); + if (SU == &EntrySU) + oss << ""; + else if (SU == &ExitSU) + oss << ""; + else + SU->getInstr()->print(oss); + return oss.str(); +} + +// EmitSchedule - Emit the machine code in scheduled order. +MachineBasicBlock *ScheduleDAGInstrs::EmitSchedule() { + // For MachineInstr-based scheduling, we're rescheduling the instructions in + // the block, so start by removing them from the block. + while (Begin != InsertPos) { + MachineBasicBlock::iterator I = Begin; + ++Begin; + BB->remove(I); + } + + // First reinsert any remaining debug_values; these are either constants, + // or refer to live-in registers. The beginning of the block is the right + // place for the latter. The former might reasonably be placed elsewhere + // using some kind of ordering algorithm, but right now it doesn't matter. + for (int i = DbgValueVec.size()-1; i>=0; --i) + if (DbgValueVec[i]) + BB->insert(InsertPos, DbgValueVec[i]); + + // Then re-insert them according to the given schedule. + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + SUnit *SU = Sequence[i]; + if (!SU) { + // Null SUnit* is a noop. + EmitNoop(); + continue; + } + + BB->insert(InsertPos, SU->getInstr()); + for (unsigned i = 0, e = SU->DbgInstrList.size() ; i < e ; ++i) + BB->insert(InsertPos, SU->DbgInstrList[i]); + } + + // Update the Begin iterator, as the first instruction in the block + // may have been scheduled later. + if (!DbgValueVec.empty()) { + for (int i = DbgValueVec.size()-1; i>=0; --i) + if (DbgValueVec[i]!=0) { + Begin = DbgValueVec[DbgValueVec.size()-1]; + break; + } + } else if (!Sequence.empty()) + Begin = Sequence[0]->getInstr(); + + DbgValueVec.clear(); + return BB; +} diff --git a/final/lib/CodeGen/ScheduleDAGInstrs.h b/final/lib/CodeGen/ScheduleDAGInstrs.h new file mode 100644 index 00000000000..c878287d9c8 --- /dev/null +++ b/final/lib/CodeGen/ScheduleDAGInstrs.h @@ -0,0 +1,207 @@ +//==- ScheduleDAGInstrs.h - MachineInstr Scheduling --------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScheduleDAGInstrs class, which implements +// scheduling for a MachineInstr-based dependency graph. +// +//===----------------------------------------------------------------------===// + +#ifndef SCHEDULEDAGINSTRS_H +#define SCHEDULEDAGINSTRS_H + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallSet.h" +#include + +namespace llvm { + class MachineLoopInfo; + class MachineDominatorTree; + + /// LoopDependencies - This class analyzes loop-oriented register + /// dependencies, which are used to guide scheduling decisions. + /// For example, loop induction variable increments should be + /// scheduled as soon as possible after the variable's last use. + /// + class LLVM_LIBRARY_VISIBILITY LoopDependencies { + const MachineLoopInfo &MLI; + const MachineDominatorTree &MDT; + + public: + typedef std::map > + LoopDeps; + LoopDeps Deps; + + LoopDependencies(const MachineLoopInfo &mli, + const MachineDominatorTree &mdt) : + MLI(mli), MDT(mdt) {} + + /// VisitLoop - Clear out any previous state and analyze the given loop. + /// + void VisitLoop(const MachineLoop *Loop) { + Deps.clear(); + MachineBasicBlock *Header = Loop->getHeader(); + SmallSet LoopLiveIns; + for (MachineBasicBlock::livein_iterator LI = Header->livein_begin(), + LE = Header->livein_end(); LI != LE; ++LI) + LoopLiveIns.insert(*LI); + + const MachineDomTreeNode *Node = MDT.getNode(Header); + const MachineBasicBlock *MBB = Node->getBlock(); + assert(Loop->contains(MBB) && + "Loop does not contain header!"); + VisitRegion(Node, MBB, Loop, LoopLiveIns); + } + + private: + void VisitRegion(const MachineDomTreeNode *Node, + const MachineBasicBlock *MBB, + const MachineLoop *Loop, + const SmallSet &LoopLiveIns) { + unsigned Count = 0; + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + const MachineInstr *MI = I; + if (MI->isDebugValue()) + continue; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned MOReg = MO.getReg(); + if (LoopLiveIns.count(MOReg)) + Deps.insert(std::make_pair(MOReg, std::make_pair(&MO, Count))); + } + ++Count; // Not every iteration due to dbg_value above. + } + + const std::vector &Children = Node->getChildren(); + for (std::vector::const_iterator I = + Children.begin(), E = Children.end(); I != E; ++I) { + const MachineDomTreeNode *ChildNode = *I; + MachineBasicBlock *ChildBlock = ChildNode->getBlock(); + if (Loop->contains(ChildBlock)) + VisitRegion(ChildNode, ChildBlock, Loop, LoopLiveIns); + } + } + }; + + /// ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of + /// MachineInstrs. + class LLVM_LIBRARY_VISIBILITY ScheduleDAGInstrs : public ScheduleDAG { + const MachineLoopInfo &MLI; + const MachineDominatorTree &MDT; + const MachineFrameInfo *MFI; + const InstrItineraryData *InstrItins; + + /// Defs, Uses - Remember where defs and uses of each physical register + /// are as we iterate upward through the instructions. This is allocated + /// here instead of inside BuildSchedGraph to avoid the need for it to be + /// initialized and destructed for each block. + std::vector > Defs; + std::vector > Uses; + + /// DbgValueVec - Remember DBG_VALUEs that refer to a particular + /// register. + std::vectorDbgValueVec; + + /// PendingLoads - Remember where unknown loads are after the most recent + /// unknown store, as we iterate. As with Defs and Uses, this is here + /// to minimize construction/destruction. + std::vector PendingLoads; + + /// LoopRegs - Track which registers are used for loop-carried dependencies. + /// + LoopDependencies LoopRegs; + + /// LoopLiveInRegs - Track which regs are live into a loop, to help guide + /// back-edge-aware scheduling. + /// + SmallSet LoopLiveInRegs; + + public: + MachineBasicBlock::iterator Begin; // The beginning of the range to + // be scheduled. The range extends + // to InsertPos. + unsigned InsertPosIndex; // The index in BB of InsertPos. + + explicit ScheduleDAGInstrs(MachineFunction &mf, + const MachineLoopInfo &mli, + const MachineDominatorTree &mdt); + + virtual ~ScheduleDAGInstrs() {} + + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(MachineInstr *MI) { +#ifndef NDEBUG + const SUnit *Addr = SUnits.empty() ? 0 : &SUnits[0]; +#endif + SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); + assert((Addr == 0 || Addr == &SUnits[0]) && + "SUnits std::vector reallocated on the fly!"); + SUnits.back().OrigNode = &SUnits.back(); + return &SUnits.back(); + } + + /// Run - perform scheduling. + /// + void Run(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endindex); + + /// BuildSchedGraph - Build SUnits from the MachineBasicBlock that we are + /// input. + virtual void BuildSchedGraph(AliasAnalysis *AA); + + /// AddSchedBarrierDeps - Add dependencies from instructions in the current + /// list of instructions being scheduled to scheduling barrier. We want to + /// make sure instructions which define registers that are either used by + /// the terminator or are live-out are properly scheduled. This is + /// especially important when the definition latency of the return value(s) + /// are too high to be hidden by the branch or when the liveout registers + /// used by instructions in the fallthrough block. + void AddSchedBarrierDeps(); + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU); + + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const; + + virtual MachineBasicBlock *EmitSchedule(); + + /// StartBlock - Prepare to perform scheduling in the given block. + /// + virtual void StartBlock(MachineBasicBlock *BB); + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + /// FinishBlock - Clean up after scheduling in the given block. + /// + virtual void FinishBlock(); + + virtual void dumpNode(const SUnit *SU) const; + + virtual std::string getGraphNodeLabel(const SUnit *SU) const; + }; +} + +#endif diff --git a/final/lib/CodeGen/ScheduleDAGPrinter.cpp b/final/lib/CodeGen/ScheduleDAGPrinter.cpp new file mode 100644 index 00000000000..4b55a2284f8 --- /dev/null +++ b/final/lib/CodeGen/ScheduleDAGPrinter.cpp @@ -0,0 +1,99 @@ +//===-- ScheduleDAGPrinter.cpp - Implement ScheduleDAG::viewGraph() -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG::viewGraph method. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +#include +using namespace llvm; + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + static std::string getGraphName(const ScheduleDAG *G) { + return G->MF.getFunction()->getName(); + } + + static bool renderGraphFromBottomUp() { + return true; + } + + static bool hasNodeAddressLabel(const SUnit *Node, + const ScheduleDAG *Graph) { + return true; + } + + /// If you want to override the dot attributes printed for a particular + /// edge, override this method. + static std::string getEdgeAttributes(const SUnit *Node, + SUnitIterator EI, + const ScheduleDAG *Graph) { + if (EI.isArtificialDep()) + return "color=cyan,style=dashed"; + if (EI.isCtrlDep()) + return "color=blue,style=dashed"; + return ""; + } + + + std::string getNodeLabel(const SUnit *Node, const ScheduleDAG *Graph); + static std::string getNodeAttributes(const SUnit *N, + const ScheduleDAG *Graph) { + return "shape=Mrecord"; + } + + static void addCustomGraphFeatures(ScheduleDAG *G, + GraphWriter &GW) { + return G->addCustomGraphFeatures(GW); + } + }; +} + +std::string DOTGraphTraits::getNodeLabel(const SUnit *SU, + const ScheduleDAG *G) { + return G->getGraphNodeLabel(SU); +} + +/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG +/// rendered using 'dot'. +/// +void ScheduleDAG::viewGraph() { +// This code is only for debugging! +#ifndef NDEBUG + if (BB->getBasicBlock()) + ViewGraph(this, "dag." + MF.getFunction()->getNameStr(), false, + "Scheduling-Units Graph for " + MF.getFunction()->getNameStr() + + ":" + BB->getBasicBlock()->getNameStr()); + else + ViewGraph(this, "dag." + MF.getFunction()->getNameStr(), false, + "Scheduling-Units Graph for " + MF.getFunction()->getNameStr()); +#else + errs() << "ScheduleDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} diff --git a/final/lib/CodeGen/ScoreboardHazardRecognizer.cpp b/final/lib/CodeGen/ScoreboardHazardRecognizer.cpp new file mode 100644 index 00000000000..e6d7ded8a78 --- /dev/null +++ b/final/lib/CodeGen/ScoreboardHazardRecognizer.cpp @@ -0,0 +1,243 @@ +//===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===// +// +// 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 ScoreboardHazardRecognizer class, which +// encapsultes hazard-avoidance heuristics for scheduling, based on the +// scheduling itineraries specified for the target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetInstrItineraries.h" + +using namespace llvm; + +#ifndef NDEBUG +const char *ScoreboardHazardRecognizer::DebugType = ""; +#endif + +ScoreboardHazardRecognizer:: +ScoreboardHazardRecognizer(const InstrItineraryData *II, + const ScheduleDAG *SchedDAG, + const char *ParentDebugType) : + ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0), + IssueCount(0) { + +#ifndef NDEBUG + DebugType = ParentDebugType; +#endif + + // Determine the maximum depth of any itinerary. This determines the + // depth of the scoreboard. We always make the scoreboard at least 1 + // cycle deep to avoid dealing with the boundary condition. + unsigned ScoreboardDepth = 1; + if (ItinData && !ItinData->isEmpty()) { + IssueWidth = ItinData->IssueWidth; + + for (unsigned idx = 0; ; ++idx) { + if (ItinData->isEndMarker(idx)) + break; + + const InstrStage *IS = ItinData->beginStage(idx); + const InstrStage *E = ItinData->endStage(idx); + unsigned CurCycle = 0; + unsigned ItinDepth = 0; + for (; IS != E; ++IS) { + unsigned StageDepth = CurCycle + IS->getCycles(); + if (ItinDepth < StageDepth) ItinDepth = StageDepth; + CurCycle += IS->getNextCycles(); + } + + // Find the next power-of-2 >= ItinDepth + while (ItinDepth > ScoreboardDepth) { + ScoreboardDepth *= 2; + } + } + MaxLookAhead = ScoreboardDepth; + } + + ReservedScoreboard.reset(ScoreboardDepth); + RequiredScoreboard.reset(ScoreboardDepth); + + DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = " + << ScoreboardDepth << '\n'); +} + +void ScoreboardHazardRecognizer::Reset() { + IssueCount = 0; + RequiredScoreboard.reset(); + ReservedScoreboard.reset(); +} + +void ScoreboardHazardRecognizer::Scoreboard::dump() const { + dbgs() << "Scoreboard:\n"; + + unsigned last = Depth - 1; + while ((last > 0) && ((*this)[last] == 0)) + last--; + + for (unsigned i = 0; i <= last; i++) { + unsigned FUs = (*this)[i]; + dbgs() << "\t"; + for (int j = 31; j >= 0; j--) + dbgs() << ((FUs & (1 << j)) ? '1' : '0'); + dbgs() << '\n'; + } +} + +bool ScoreboardHazardRecognizer::atIssueLimit() const { + if (IssueWidth == 0) + return false; + + return IssueCount == IssueWidth; +} + +ScheduleHazardRecognizer::HazardType +ScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { + if (!ItinData || ItinData->isEmpty()) + return NoHazard; + + // Note that stalls will be negative for bottom-up scheduling. + int cycle = Stalls; + + // Use the itinerary for the underlying instruction to check for + // free FU's in the scoreboard at the appropriate future cycles. + + const TargetInstrDesc *TID = DAG->getInstrDesc(SU); + if (TID == NULL) { + // Don't check hazards for non-machineinstr Nodes. + return NoHazard; + } + unsigned idx = TID->getSchedClass(); + for (const InstrStage *IS = ItinData->beginStage(idx), + *E = ItinData->endStage(idx); IS != E; ++IS) { + // We must find one of the stage's units free for every cycle the + // stage is occupied. FIXME it would be more accurate to find the + // same unit free in all the cycles. + for (unsigned int i = 0; i < IS->getCycles(); ++i) { + int StageCycle = cycle + (int)i; + if (StageCycle < 0) + continue; + + if (StageCycle >= (int)RequiredScoreboard.getDepth()) { + assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() && + "Scoreboard depth exceeded!"); + // This stage was stalled beyond pipeline depth, so cannot conflict. + break; + } + + unsigned freeUnits = IS->getUnits(); + switch (IS->getReservationKind()) { + default: + assert(0 && "Invalid FU reservation"); + case InstrStage::Required: + // Required FUs conflict with both reserved and required ones + freeUnits &= ~ReservedScoreboard[StageCycle]; + // FALLTHROUGH + case InstrStage::Reserved: + // Reserved FUs can conflict only with required ones. + freeUnits &= ~RequiredScoreboard[StageCycle]; + break; + } + + if (!freeUnits) { + DEBUG(dbgs() << "*** Hazard in cycle " << (cycle + i) << ", "); + DEBUG(dbgs() << "SU(" << SU->NodeNum << "): "); + DEBUG(DAG->dumpNode(SU)); + return Hazard; + } + } + + // Advance the cycle to the next stage. + cycle += IS->getNextCycles(); + } + + return NoHazard; +} + +void ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) { + if (!ItinData || ItinData->isEmpty()) + return; + + // Use the itinerary for the underlying instruction to reserve FU's + // in the scoreboard at the appropriate future cycles. + const TargetInstrDesc *TID = DAG->getInstrDesc(SU); + assert(TID && "The scheduler must filter non-machineinstrs"); + if (DAG->TII->isZeroCost(TID->Opcode)) + return; + + ++IssueCount; + + unsigned cycle = 0; + + unsigned idx = TID->getSchedClass(); + for (const InstrStage *IS = ItinData->beginStage(idx), + *E = ItinData->endStage(idx); IS != E; ++IS) { + // We must reserve one of the stage's units for every cycle the + // stage is occupied. FIXME it would be more accurate to reserve + // the same unit free in all the cycles. + for (unsigned int i = 0; i < IS->getCycles(); ++i) { + assert(((cycle + i) < RequiredScoreboard.getDepth()) && + "Scoreboard depth exceeded!"); + + unsigned freeUnits = IS->getUnits(); + switch (IS->getReservationKind()) { + default: + assert(0 && "Invalid FU reservation"); + case InstrStage::Required: + // Required FUs conflict with both reserved and required ones + freeUnits &= ~ReservedScoreboard[cycle + i]; + // FALLTHROUGH + case InstrStage::Reserved: + // Reserved FUs can conflict only with required ones. + freeUnits &= ~RequiredScoreboard[cycle + i]; + break; + } + + // reduce to a single unit + unsigned freeUnit = 0; + do { + freeUnit = freeUnits; + freeUnits = freeUnit & (freeUnit - 1); + } while (freeUnits); + + assert(freeUnit && "No function unit available!"); + if (IS->getReservationKind() == InstrStage::Required) + RequiredScoreboard[cycle + i] |= freeUnit; + else + ReservedScoreboard[cycle + i] |= freeUnit; + } + + // Advance the cycle to the next stage. + cycle += IS->getNextCycles(); + } + + DEBUG(ReservedScoreboard.dump()); + DEBUG(RequiredScoreboard.dump()); +} + +void ScoreboardHazardRecognizer::AdvanceCycle() { + IssueCount = 0; + ReservedScoreboard[0] = 0; ReservedScoreboard.advance(); + RequiredScoreboard[0] = 0; RequiredScoreboard.advance(); +} + +void ScoreboardHazardRecognizer::RecedeCycle() { + IssueCount = 0; + ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0; + ReservedScoreboard.recede(); + RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0; + RequiredScoreboard.recede(); +} diff --git a/final/lib/CodeGen/SelectionDAG/CMakeLists.txt b/final/lib/CodeGen/SelectionDAG/CMakeLists.txt new file mode 100644 index 00000000000..15932c03a19 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/CMakeLists.txt @@ -0,0 +1,23 @@ +add_llvm_library(LLVMSelectionDAG + DAGCombiner.cpp + FastISel.cpp + FunctionLoweringInfo.cpp + InstrEmitter.cpp + LegalizeDAG.cpp + LegalizeFloatTypes.cpp + LegalizeIntegerTypes.cpp + LegalizeTypes.cpp + LegalizeTypesGeneric.cpp + LegalizeVectorOps.cpp + LegalizeVectorTypes.cpp + ScheduleDAGFast.cpp + ScheduleDAGList.cpp + ScheduleDAGRRList.cpp + ScheduleDAGSDNodes.cpp + SelectionDAG.cpp + SelectionDAGBuilder.cpp + SelectionDAGISel.cpp + SelectionDAGPrinter.cpp + TargetLowering.cpp + TargetSelectionDAGInfo.cpp + ) diff --git a/final/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/final/lib/CodeGen/SelectionDAG/DAGCombiner.cpp new file mode 100644 index 00000000000..4c70bc3e88b --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -0,0 +1,7641 @@ +//===-- DAGCombiner.cpp - Implement a DAG node combiner -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass combines dag nodes to form fewer, simpler DAG nodes. It can be run +// both before and after the DAG is legalized. +// +// This pass is not a substitute for the LLVM IR instcombine pass. This pass is +// primarily intended to handle simplification opportunities that are implicit +// in the LLVM IR and exposed by the various codegen lowering phases. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dagcombine" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +STATISTIC(NodesCombined , "Number of dag nodes combined"); +STATISTIC(PreIndexedNodes , "Number of pre-indexed nodes created"); +STATISTIC(PostIndexedNodes, "Number of post-indexed nodes created"); +STATISTIC(OpsNarrowed , "Number of load/op/store narrowed"); +STATISTIC(LdStFP2Int , "Number of fp load/store pairs transformed to int"); + +namespace { + static cl::opt + CombinerAA("combiner-alias-analysis", cl::Hidden, + cl::desc("Turn on alias analysis during testing")); + + static cl::opt + CombinerGlobalAA("combiner-global-alias-analysis", cl::Hidden, + cl::desc("Include global information in alias analysis")); + +//------------------------------ DAGCombiner ---------------------------------// + + class DAGCombiner { + SelectionDAG &DAG; + const TargetLowering &TLI; + CombineLevel Level; + CodeGenOpt::Level OptLevel; + bool LegalOperations; + bool LegalTypes; + + // Worklist of all of the nodes that need to be simplified. + std::vector WorkList; + + // AA - Used for DAG load/store alias analysis. + AliasAnalysis &AA; + + /// AddUsersToWorkList - When an instruction is simplified, add all users of + /// the instruction to the work lists because they might get more simplified + /// now. + /// + void AddUsersToWorkList(SDNode *N) { + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) + AddToWorkList(*UI); + } + + /// visit - call the node-specific routine that knows how to fold each + /// particular type of node. + SDValue visit(SDNode *N); + + public: + /// AddToWorkList - Add to the work list making sure it's instance is at the + /// the back (next to be processed.) + void AddToWorkList(SDNode *N) { + removeFromWorkList(N); + WorkList.push_back(N); + } + + /// removeFromWorkList - remove all instances of N from the worklist. + /// + void removeFromWorkList(SDNode *N) { + WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), N), + WorkList.end()); + } + + SDValue CombineTo(SDNode *N, const SDValue *To, unsigned NumTo, + bool AddTo = true); + + SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true) { + return CombineTo(N, &Res, 1, AddTo); + } + + SDValue CombineTo(SDNode *N, SDValue Res0, SDValue Res1, + bool AddTo = true) { + SDValue To[] = { Res0, Res1 }; + return CombineTo(N, To, 2, AddTo); + } + + void CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO); + + private: + + /// SimplifyDemandedBits - Check the specified integer node value to see if + /// it can be simplified or if things it uses can be simplified by bit + /// propagation. If so, return true. + bool SimplifyDemandedBits(SDValue Op) { + unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits(); + APInt Demanded = APInt::getAllOnesValue(BitWidth); + return SimplifyDemandedBits(Op, Demanded); + } + + bool SimplifyDemandedBits(SDValue Op, const APInt &Demanded); + + bool CombineToPreIndexedLoadStore(SDNode *N); + bool CombineToPostIndexedLoadStore(SDNode *N); + + void ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad); + SDValue PromoteOperand(SDValue Op, EVT PVT, bool &Replace); + SDValue SExtPromoteOperand(SDValue Op, EVT PVT); + SDValue ZExtPromoteOperand(SDValue Op, EVT PVT); + SDValue PromoteIntBinOp(SDValue Op); + SDValue PromoteIntShiftOp(SDValue Op); + SDValue PromoteExtend(SDValue Op); + bool PromoteLoad(SDValue Op); + + /// combine - call the node-specific routine that knows how to fold each + /// particular type of node. If that doesn't do anything, try the + /// target-specific DAG combines. + SDValue combine(SDNode *N); + + // Visitation implementation - Implement dag node combining for different + // node types. The semantics are as follows: + // Return Value: + // SDValue.getNode() == 0 - No change was made + // SDValue.getNode() == N - N was replaced, is dead and has been handled. + // otherwise - N should be replaced by the returned Operand. + // + SDValue visitTokenFactor(SDNode *N); + SDValue visitMERGE_VALUES(SDNode *N); + SDValue visitADD(SDNode *N); + SDValue visitSUB(SDNode *N); + SDValue visitADDC(SDNode *N); + SDValue visitADDE(SDNode *N); + SDValue visitMUL(SDNode *N); + SDValue visitSDIV(SDNode *N); + SDValue visitUDIV(SDNode *N); + SDValue visitSREM(SDNode *N); + SDValue visitUREM(SDNode *N); + SDValue visitMULHU(SDNode *N); + SDValue visitMULHS(SDNode *N); + SDValue visitSMUL_LOHI(SDNode *N); + SDValue visitUMUL_LOHI(SDNode *N); + SDValue visitSDIVREM(SDNode *N); + SDValue visitUDIVREM(SDNode *N); + SDValue visitAND(SDNode *N); + SDValue visitOR(SDNode *N); + SDValue visitXOR(SDNode *N); + SDValue SimplifyVBinOp(SDNode *N); + SDValue visitSHL(SDNode *N); + SDValue visitSRA(SDNode *N); + SDValue visitSRL(SDNode *N); + SDValue visitCTLZ(SDNode *N); + SDValue visitCTTZ(SDNode *N); + SDValue visitCTPOP(SDNode *N); + SDValue visitSELECT(SDNode *N); + SDValue visitSELECT_CC(SDNode *N); + SDValue visitSETCC(SDNode *N); + SDValue visitSIGN_EXTEND(SDNode *N); + SDValue visitZERO_EXTEND(SDNode *N); + SDValue visitANY_EXTEND(SDNode *N); + SDValue visitSIGN_EXTEND_INREG(SDNode *N); + SDValue visitTRUNCATE(SDNode *N); + SDValue visitBITCAST(SDNode *N); + SDValue visitBUILD_PAIR(SDNode *N); + SDValue visitFADD(SDNode *N); + SDValue visitFSUB(SDNode *N); + SDValue visitFMUL(SDNode *N); + SDValue visitFDIV(SDNode *N); + SDValue visitFREM(SDNode *N); + SDValue visitFCOPYSIGN(SDNode *N); + SDValue visitSINT_TO_FP(SDNode *N); + SDValue visitUINT_TO_FP(SDNode *N); + SDValue visitFP_TO_SINT(SDNode *N); + SDValue visitFP_TO_UINT(SDNode *N); + SDValue visitFP_ROUND(SDNode *N); + SDValue visitFP_ROUND_INREG(SDNode *N); + SDValue visitFP_EXTEND(SDNode *N); + SDValue visitFNEG(SDNode *N); + SDValue visitFABS(SDNode *N); + SDValue visitBRCOND(SDNode *N); + SDValue visitBR_CC(SDNode *N); + SDValue visitLOAD(SDNode *N); + SDValue visitSTORE(SDNode *N); + SDValue visitINSERT_VECTOR_ELT(SDNode *N); + SDValue visitEXTRACT_VECTOR_ELT(SDNode *N); + SDValue visitBUILD_VECTOR(SDNode *N); + SDValue visitCONCAT_VECTORS(SDNode *N); + SDValue visitVECTOR_SHUFFLE(SDNode *N); + SDValue visitMEMBARRIER(SDNode *N); + + SDValue XformToShuffleWithZero(SDNode *N); + SDValue ReassociateOps(unsigned Opc, DebugLoc DL, SDValue LHS, SDValue RHS); + + SDValue visitShiftByConstant(SDNode *N, unsigned Amt); + + bool SimplifySelectOps(SDNode *SELECT, SDValue LHS, SDValue RHS); + SDValue SimplifyBinOpWithSameOpcodeHands(SDNode *N); + SDValue SimplifySelect(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2); + SDValue SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue N2, + SDValue N3, ISD::CondCode CC, + bool NotExtCompare = false); + SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, + DebugLoc DL, bool foldBooleans = true); + SDValue SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, + unsigned HiOp); + SDValue CombineConsecutiveLoads(SDNode *N, EVT VT); + SDValue ConstantFoldBITCASTofBUILD_VECTOR(SDNode *, EVT); + SDValue BuildSDIV(SDNode *N); + SDValue BuildUDIV(SDNode *N); + SDNode *MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL); + SDValue ReduceLoadWidth(SDNode *N); + SDValue ReduceLoadOpStoreWidth(SDNode *N); + SDValue TransformFPLoadStorePair(SDNode *N); + + SDValue GetDemandedBits(SDValue V, const APInt &Mask); + + /// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes, + /// looking for aliasing nodes and adding them to the Aliases vector. + void GatherAllAliases(SDNode *N, SDValue OriginalChain, + SmallVector &Aliases); + + /// isAlias - Return true if there is any possibility that the two addresses + /// overlap. + bool isAlias(SDValue Ptr1, int64_t Size1, + const Value *SrcValue1, int SrcValueOffset1, + unsigned SrcValueAlign1, + const MDNode *TBAAInfo1, + SDValue Ptr2, int64_t Size2, + const Value *SrcValue2, int SrcValueOffset2, + unsigned SrcValueAlign2, + const MDNode *TBAAInfo2) const; + + /// FindAliasInfo - Extracts the relevant alias information from the memory + /// node. Returns true if the operand was a load. + bool FindAliasInfo(SDNode *N, + SDValue &Ptr, int64_t &Size, + const Value *&SrcValue, int &SrcValueOffset, + unsigned &SrcValueAlignment, + const MDNode *&TBAAInfo) const; + + /// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, + /// looking for a better chain (aliasing node.) + SDValue FindBetterChain(SDNode *N, SDValue Chain); + + public: + DAGCombiner(SelectionDAG &D, AliasAnalysis &A, CodeGenOpt::Level OL) + : DAG(D), TLI(D.getTargetLoweringInfo()), Level(Unrestricted), + OptLevel(OL), LegalOperations(false), LegalTypes(false), AA(A) {} + + /// Run - runs the dag combiner on all nodes in the work list + void Run(CombineLevel AtLevel); + + SelectionDAG &getDAG() const { return DAG; } + + /// getShiftAmountTy - Returns a type large enough to hold any valid + /// shift amount - before type legalization these can be huge. + EVT getShiftAmountTy(EVT LHSTy) { + return LegalTypes ? TLI.getShiftAmountTy(LHSTy) : TLI.getPointerTy(); + } + + /// isTypeLegal - This method returns true if we are running before type + /// legalization or if the specified VT is legal. + bool isTypeLegal(const EVT &VT) { + if (!LegalTypes) return true; + return TLI.isTypeLegal(VT); + } + }; +} + + +namespace { +/// WorkListRemover - This class is a DAGUpdateListener that removes any deleted +/// nodes from the worklist. +class WorkListRemover : public SelectionDAG::DAGUpdateListener { + DAGCombiner &DC; +public: + explicit WorkListRemover(DAGCombiner &dc) : DC(dc) {} + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + DC.removeFromWorkList(N); + } + + virtual void NodeUpdated(SDNode *N) { + // Ignore updates. + } +}; +} + +//===----------------------------------------------------------------------===// +// TargetLowering::DAGCombinerInfo implementation +//===----------------------------------------------------------------------===// + +void TargetLowering::DAGCombinerInfo::AddToWorklist(SDNode *N) { + ((DAGCombiner*)DC)->AddToWorkList(N); +} + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, const std::vector &To, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, &To[0], To.size(), AddTo); +} + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, SDValue Res, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, Res, AddTo); +} + + +SDValue TargetLowering::DAGCombinerInfo:: +CombineTo(SDNode *N, SDValue Res0, SDValue Res1, bool AddTo) { + return ((DAGCombiner*)DC)->CombineTo(N, Res0, Res1, AddTo); +} + +void TargetLowering::DAGCombinerInfo:: +CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO) { + return ((DAGCombiner*)DC)->CommitTargetLoweringOpt(TLO); +} + +//===----------------------------------------------------------------------===// +// Helper Functions +//===----------------------------------------------------------------------===// + +/// isNegatibleForFree - Return 1 if we can compute the negated form of the +/// specified expression for the same cost as the expression itself, or 2 if we +/// can compute the negated form more cheaply than the expression itself. +static char isNegatibleForFree(SDValue Op, bool LegalOperations, + unsigned Depth = 0) { + // No compile time optimizations on this type. + if (Op.getValueType() == MVT::ppcf128) + return 0; + + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return 2; + + // Don't allow anything with multiple uses. + if (!Op.hasOneUse()) return 0; + + // Don't recurse exponentially. + if (Depth > 6) return 0; + + switch (Op.getOpcode()) { + default: return false; + case ISD::ConstantFP: + // Don't invert constant FP values after legalize. The negated constant + // isn't necessarily legal. + return LegalOperations ? 0 : 1; + case ISD::FADD: + // FIXME: determine better conditions for this xform. + if (!UnsafeFPMath) return 0; + + // fold (fsub (fadd A, B)) -> (fsub (fneg A), B) + if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return V; + // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) + return isNegatibleForFree(Op.getOperand(1), LegalOperations, Depth+1); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + if (!UnsafeFPMath) return 0; + + // fold (fneg (fsub A, B)) -> (fsub B, A) + return 1; + + case ISD::FMUL: + case ISD::FDIV: + if (HonorSignDependentRoundingFPMath()) return 0; + + // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y)) + if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return V; + + return isNegatibleForFree(Op.getOperand(1), LegalOperations, Depth+1); + + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FSIN: + return isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1); + } +} + +/// GetNegatedExpression - If isNegatibleForFree returns true, this function +/// returns the newly negated expression. +static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG, + bool LegalOperations, unsigned Depth = 0) { + // fneg is removable even if it has multiple uses. + if (Op.getOpcode() == ISD::FNEG) return Op.getOperand(0); + + // Don't allow anything with multiple uses. + assert(Op.hasOneUse() && "Unknown reuse!"); + + assert(Depth <= 6 && "GetNegatedExpression doesn't match isNegatibleForFree"); + switch (Op.getOpcode()) { + default: llvm_unreachable("Unknown code"); + case ISD::ConstantFP: { + APFloat V = cast(Op)->getValueAPF(); + V.changeSign(); + return DAG.getConstantFP(V, Op.getValueType()); + } + case ISD::FADD: + // FIXME: determine better conditions for this xform. + assert(UnsafeFPMath); + + // fold (fneg (fadd A, B)) -> (fsub (fneg A), B) + if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(1), DAG, + LegalOperations, Depth+1), + Op.getOperand(0)); + case ISD::FSUB: + // We can't turn -(A-B) into B-A when we honor signed zeros. + assert(UnsafeFPMath); + + // fold (fneg (fsub 0, B)) -> B + if (ConstantFPSDNode *N0CFP = dyn_cast(Op.getOperand(0))) + if (N0CFP->getValueAPF().isZero()) + return Op.getOperand(1); + + // fold (fneg (fsub A, B)) -> (fsub B, A) + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + Op.getOperand(1), Op.getOperand(0)); + + case ISD::FMUL: + case ISD::FDIV: + assert(!HonorSignDependentRoundingFPMath()); + + // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) + if (isNegatibleForFree(Op.getOperand(0), LegalOperations, Depth+1)) + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + + // fold (fneg (fmul X, Y)) -> (fmul X, (fneg Y)) + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + Op.getOperand(0), + GetNegatedExpression(Op.getOperand(1), DAG, + LegalOperations, Depth+1)); + + case ISD::FP_EXTEND: + case ISD::FSIN: + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1)); + case ISD::FP_ROUND: + return DAG.getNode(ISD::FP_ROUND, Op.getDebugLoc(), Op.getValueType(), + GetNegatedExpression(Op.getOperand(0), DAG, + LegalOperations, Depth+1), + Op.getOperand(1)); + } +} + + +// isSetCCEquivalent - Return true if this node is a setcc, or is a select_cc +// that selects between the values 1 and 0, making it equivalent to a setcc. +// Also, set the incoming LHS, RHS, and CC references to the appropriate +// nodes based on the type of node we are checking. This simplifies life a +// bit for the callers. +static bool isSetCCEquivalent(SDValue N, SDValue &LHS, SDValue &RHS, + SDValue &CC) { + if (N.getOpcode() == ISD::SETCC) { + LHS = N.getOperand(0); + RHS = N.getOperand(1); + CC = N.getOperand(2); + return true; + } + if (N.getOpcode() == ISD::SELECT_CC && + N.getOperand(2).getOpcode() == ISD::Constant && + N.getOperand(3).getOpcode() == ISD::Constant && + cast(N.getOperand(2))->getAPIntValue() == 1 && + cast(N.getOperand(3))->isNullValue()) { + LHS = N.getOperand(0); + RHS = N.getOperand(1); + CC = N.getOperand(4); + return true; + } + return false; +} + +// isOneUseSetCC - Return true if this is a SetCC-equivalent operation with only +// one use. If this is true, it allows the users to invert the operation for +// free when it is profitable to do so. +static bool isOneUseSetCC(SDValue N) { + SDValue N0, N1, N2; + if (isSetCCEquivalent(N, N0, N1, N2) && N.getNode()->hasOneUse()) + return true; + return false; +} + +SDValue DAGCombiner::ReassociateOps(unsigned Opc, DebugLoc DL, + SDValue N0, SDValue N1) { + EVT VT = N0.getValueType(); + if (N0.getOpcode() == Opc && isa(N0.getOperand(1))) { + if (isa(N1)) { + // reassoc. (op (op x, c1), c2) -> (op x, (op c1, c2)) + SDValue OpNode = + DAG.FoldConstantArithmetic(Opc, VT, + cast(N0.getOperand(1)), + cast(N1)); + return DAG.getNode(Opc, DL, VT, N0.getOperand(0), OpNode); + } else if (N0.hasOneUse()) { + // reassoc. (op (op x, c1), y) -> (op (op x, y), c1) iff x+c1 has one use + SDValue OpNode = DAG.getNode(Opc, N0.getDebugLoc(), VT, + N0.getOperand(0), N1); + AddToWorkList(OpNode.getNode()); + return DAG.getNode(Opc, DL, VT, OpNode, N0.getOperand(1)); + } + } + + if (N1.getOpcode() == Opc && isa(N1.getOperand(1))) { + if (isa(N0)) { + // reassoc. (op c2, (op x, c1)) -> (op x, (op c1, c2)) + SDValue OpNode = + DAG.FoldConstantArithmetic(Opc, VT, + cast(N1.getOperand(1)), + cast(N0)); + return DAG.getNode(Opc, DL, VT, N1.getOperand(0), OpNode); + } else if (N1.hasOneUse()) { + // reassoc. (op y, (op x, c1)) -> (op (op x, y), c1) iff x+c1 has one use + SDValue OpNode = DAG.getNode(Opc, N0.getDebugLoc(), VT, + N1.getOperand(0), N0); + AddToWorkList(OpNode.getNode()); + return DAG.getNode(Opc, DL, VT, OpNode, N1.getOperand(1)); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::CombineTo(SDNode *N, const SDValue *To, unsigned NumTo, + bool AddTo) { + assert(N->getNumValues() == NumTo && "Broken CombineTo call!"); + ++NodesCombined; + DEBUG(dbgs() << "\nReplacing.1 "; + N->dump(&DAG); + dbgs() << "\nWith: "; + To[0].getNode()->dump(&DAG); + dbgs() << " and " << NumTo-1 << " other values\n"; + for (unsigned i = 0, e = NumTo; i != e; ++i) + assert((!To[i].getNode() || + N->getValueType(i) == To[i].getValueType()) && + "Cannot combine value to value of different type!")); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesWith(N, To, &DeadNodes); + + if (AddTo) { + // Push the new nodes and any users onto the worklist + for (unsigned i = 0, e = NumTo; i != e; ++i) { + if (To[i].getNode()) { + AddToWorkList(To[i].getNode()); + AddUsersToWorkList(To[i].getNode()); + } + } + } + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (N->use_empty()) { + // Nodes can be reintroduced into the worklist. Make sure we do not + // process a node that has been replaced. + removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + } + return SDValue(N, 0); +} + +void DAGCombiner:: +CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO) { + // Replace all uses. If any nodes become isomorphic to other nodes and + // are deleted, make sure to remove them from our worklist. + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &DeadNodes); + + // Push the new node and any (possibly new) users onto the worklist. + AddToWorkList(TLO.New.getNode()); + AddUsersToWorkList(TLO.New.getNode()); + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (TLO.Old.getNode()->use_empty()) { + removeFromWorkList(TLO.Old.getNode()); + + // If the operands of this node are only used by the node, they will now + // be dead. Make sure to visit them first to delete dead nodes early. + for (unsigned i = 0, e = TLO.Old.getNode()->getNumOperands(); i != e; ++i) + if (TLO.Old.getNode()->getOperand(i).getNode()->hasOneUse()) + AddToWorkList(TLO.Old.getNode()->getOperand(i).getNode()); + + DAG.DeleteNode(TLO.Old.getNode()); + } +} + +/// SimplifyDemandedBits - Check the specified integer node value to see if +/// it can be simplified or if things it uses can be simplified by bit +/// propagation. If so, return true. +bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { + TargetLowering::TargetLoweringOpt TLO(DAG, LegalTypes, LegalOperations); + APInt KnownZero, KnownOne; + if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO)) + return false; + + // Revisit the node. + AddToWorkList(Op.getNode()); + + // Replace the old value with the new one. + ++NodesCombined; + DEBUG(dbgs() << "\nReplacing.2 "; + TLO.Old.getNode()->dump(&DAG); + dbgs() << "\nWith: "; + TLO.New.getNode()->dump(&DAG); + dbgs() << '\n'); + + CommitTargetLoweringOpt(TLO); + return true; +} + +void DAGCombiner::ReplaceLoadWithPromotedLoad(SDNode *Load, SDNode *ExtLoad) { + DebugLoc dl = Load->getDebugLoc(); + EVT VT = Load->getValueType(0); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, VT, SDValue(ExtLoad, 0)); + + DEBUG(dbgs() << "\nReplacing.9 "; + Load->dump(&DAG); + dbgs() << "\nWith: "; + Trunc.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(Load, 0), Trunc, &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(Load, 1), SDValue(ExtLoad, 1), + &DeadNodes); + removeFromWorkList(Load); + DAG.DeleteNode(Load); + AddToWorkList(Trunc.getNode()); +} + +SDValue DAGCombiner::PromoteOperand(SDValue Op, EVT PVT, bool &Replace) { + Replace = false; + DebugLoc dl = Op.getDebugLoc(); + if (LoadSDNode *LD = dyn_cast(Op)) { + EVT MemVT = LD->getMemoryVT(); + ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD) + ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD + : ISD::EXTLOAD) + : LD->getExtensionType(); + Replace = true; + return DAG.getExtLoad(ExtType, dl, PVT, + LD->getChain(), LD->getBasePtr(), + LD->getPointerInfo(), + MemVT, LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + } + + unsigned Opc = Op.getOpcode(); + switch (Opc) { + default: break; + case ISD::AssertSext: + return DAG.getNode(ISD::AssertSext, dl, PVT, + SExtPromoteOperand(Op.getOperand(0), PVT), + Op.getOperand(1)); + case ISD::AssertZext: + return DAG.getNode(ISD::AssertZext, dl, PVT, + ZExtPromoteOperand(Op.getOperand(0), PVT), + Op.getOperand(1)); + case ISD::Constant: { + unsigned ExtOpc = + Op.getValueType().isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + return DAG.getNode(ExtOpc, dl, PVT, Op); + } + } + + if (!TLI.isOperationLegal(ISD::ANY_EXTEND, PVT)) + return SDValue(); + return DAG.getNode(ISD::ANY_EXTEND, dl, PVT, Op); +} + +SDValue DAGCombiner::SExtPromoteOperand(SDValue Op, EVT PVT) { + if (!TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, PVT)) + return SDValue(); + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + bool Replace = false; + SDValue NewOp = PromoteOperand(Op, PVT, Replace); + if (NewOp.getNode() == 0) + return SDValue(); + AddToWorkList(NewOp.getNode()); + + if (Replace) + ReplaceLoadWithPromotedLoad(Op.getNode(), NewOp.getNode()); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NewOp.getValueType(), NewOp, + DAG.getValueType(OldVT)); +} + +SDValue DAGCombiner::ZExtPromoteOperand(SDValue Op, EVT PVT) { + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + bool Replace = false; + SDValue NewOp = PromoteOperand(Op, PVT, Replace); + if (NewOp.getNode() == 0) + return SDValue(); + AddToWorkList(NewOp.getNode()); + + if (Replace) + ReplaceLoadWithPromotedLoad(Op.getNode(), NewOp.getNode()); + return DAG.getZeroExtendInReg(NewOp, dl, OldVT); +} + +/// PromoteIntBinOp - Promote the specified integer binary operation if the +/// target indicates it is beneficial. e.g. On x86, it's usually better to +/// promote i16 operations to i32 since i16 instructions are longer. +SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) { + if (!LegalOperations) + return SDValue(); + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return SDValue(); + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return SDValue(); + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + + bool Replace0 = false; + SDValue N0 = Op.getOperand(0); + SDValue NN0 = PromoteOperand(N0, PVT, Replace0); + if (NN0.getNode() == 0) + return SDValue(); + + bool Replace1 = false; + SDValue N1 = Op.getOperand(1); + SDValue NN1; + if (N0 == N1) + NN1 = NN0; + else { + NN1 = PromoteOperand(N1, PVT, Replace1); + if (NN1.getNode() == 0) + return SDValue(); + } + + AddToWorkList(NN0.getNode()); + if (NN1.getNode()) + AddToWorkList(NN1.getNode()); + + if (Replace0) + ReplaceLoadWithPromotedLoad(N0.getNode(), NN0.getNode()); + if (Replace1) + ReplaceLoadWithPromotedLoad(N1.getNode(), NN1.getNode()); + + DEBUG(dbgs() << "\nPromoting "; + Op.getNode()->dump(&DAG)); + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ISD::TRUNCATE, dl, VT, + DAG.getNode(Opc, dl, PVT, NN0, NN1)); + } + return SDValue(); +} + +/// PromoteIntShiftOp - Promote the specified integer shift operation if the +/// target indicates it is beneficial. e.g. On x86, it's usually better to +/// promote i16 operations to i32 since i16 instructions are longer. +SDValue DAGCombiner::PromoteIntShiftOp(SDValue Op) { + if (!LegalOperations) + return SDValue(); + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return SDValue(); + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return SDValue(); + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + + bool Replace = false; + SDValue N0 = Op.getOperand(0); + if (Opc == ISD::SRA) + N0 = SExtPromoteOperand(Op.getOperand(0), PVT); + else if (Opc == ISD::SRL) + N0 = ZExtPromoteOperand(Op.getOperand(0), PVT); + else + N0 = PromoteOperand(N0, PVT, Replace); + if (N0.getNode() == 0) + return SDValue(); + + AddToWorkList(N0.getNode()); + if (Replace) + ReplaceLoadWithPromotedLoad(Op.getOperand(0).getNode(), N0.getNode()); + + DEBUG(dbgs() << "\nPromoting "; + Op.getNode()->dump(&DAG)); + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ISD::TRUNCATE, dl, VT, + DAG.getNode(Opc, dl, PVT, N0, Op.getOperand(1))); + } + return SDValue(); +} + +SDValue DAGCombiner::PromoteExtend(SDValue Op) { + if (!LegalOperations) + return SDValue(); + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return SDValue(); + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return SDValue(); + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + // fold (aext (aext x)) -> (aext x) + // fold (aext (zext x)) -> (zext x) + // fold (aext (sext x)) -> (sext x) + DEBUG(dbgs() << "\nPromoting "; + Op.getNode()->dump(&DAG)); + return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), VT, Op.getOperand(0)); + } + return SDValue(); +} + +bool DAGCombiner::PromoteLoad(SDValue Op) { + if (!LegalOperations) + return false; + + EVT VT = Op.getValueType(); + if (VT.isVector() || !VT.isInteger()) + return false; + + // If operation type is 'undesirable', e.g. i16 on x86, consider + // promoting it. + unsigned Opc = Op.getOpcode(); + if (TLI.isTypeDesirableForOp(Opc, VT)) + return false; + + EVT PVT = VT; + // Consult target whether it is a good idea to promote this operation and + // what's the right type to promote it to. + if (TLI.IsDesirableToPromoteOp(Op, PVT)) { + assert(PVT != VT && "Don't know what type to promote to!"); + + DebugLoc dl = Op.getDebugLoc(); + SDNode *N = Op.getNode(); + LoadSDNode *LD = cast(N); + EVT MemVT = LD->getMemoryVT(); + ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD) + ? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD + : ISD::EXTLOAD) + : LD->getExtensionType(); + SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT, + LD->getChain(), LD->getBasePtr(), + LD->getPointerInfo(), + MemVT, LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + SDValue Result = DAG.getNode(ISD::TRUNCATE, dl, VT, NewLD); + + DEBUG(dbgs() << "\nPromoting "; + N->dump(&DAG); + dbgs() << "\nTo: "; + Result.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result, &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), NewLD.getValue(1), &DeadNodes); + removeFromWorkList(N); + DAG.DeleteNode(N); + AddToWorkList(Result.getNode()); + return true; + } + return false; +} + + +//===----------------------------------------------------------------------===// +// Main DAG Combiner implementation +//===----------------------------------------------------------------------===// + +void DAGCombiner::Run(CombineLevel AtLevel) { + // set the instance variables, so that the various visit routines may use it. + Level = AtLevel; + LegalOperations = Level >= NoIllegalOperations; + LegalTypes = Level >= NoIllegalTypes; + + // Add all the dag nodes to the worklist. + WorkList.reserve(DAG.allnodes_size()); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) + WorkList.push_back(I); + + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + + // The root of the dag may dangle to deleted nodes until the dag combiner is + // done. Set it to null to avoid confusion. + DAG.setRoot(SDValue()); + + // while the worklist isn't empty, inspect the node on the end of it and + // try and combine it. + while (!WorkList.empty()) { + SDNode *N = WorkList.back(); + WorkList.pop_back(); + + // If N has no uses, it is dead. Make sure to revisit all N's operands once + // N is deleted from the DAG, since they too may now be dead or may have a + // reduced number of uses, allowing other xforms. + if (N->use_empty() && N != &Dummy) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + DAG.DeleteNode(N); + continue; + } + + SDValue RV = combine(N); + + if (RV.getNode() == 0) + continue; + + ++NodesCombined; + + // If we get back the same node we passed in, rather than a new node or + // zero, we know that the node must have defined multiple values and + // CombineTo was used. Since CombineTo takes care of the worklist + // mechanics for us, we have no work to do in this case. + if (RV.getNode() == N) + continue; + + assert(N->getOpcode() != ISD::DELETED_NODE && + RV.getNode()->getOpcode() != ISD::DELETED_NODE && + "Node was deleted but visit returned new node!"); + + DEBUG(dbgs() << "\nReplacing.3 "; + N->dump(&DAG); + dbgs() << "\nWith: "; + RV.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + if (N->getNumValues() == RV.getNode()->getNumValues()) + DAG.ReplaceAllUsesWith(N, RV.getNode(), &DeadNodes); + else { + assert(N->getValueType(0) == RV.getValueType() && + N->getNumValues() == 1 && "Type mismatch"); + SDValue OpV = RV; + DAG.ReplaceAllUsesWith(N, &OpV, &DeadNodes); + } + + // Push the new node and any users onto the worklist + AddToWorkList(RV.getNode()); + AddUsersToWorkList(RV.getNode()); + + // Add any uses of the old node to the worklist in case this node is the + // last one that uses them. They may become dead after this node is + // deleted. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + // Finally, if the node is now dead, remove it from the graph. The node + // may not be dead if the replacement process recursively simplified to + // something else needing this node. + if (N->use_empty()) { + // Nodes can be reintroduced into the worklist. Make sure we do not + // process a node that has been replaced. + removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + } + } + + // If the root changed (e.g. it was a dead load, update the root). + DAG.setRoot(Dummy.getValue()); +} + +SDValue DAGCombiner::visit(SDNode *N) { + switch (N->getOpcode()) { + default: break; + case ISD::TokenFactor: return visitTokenFactor(N); + case ISD::MERGE_VALUES: return visitMERGE_VALUES(N); + case ISD::ADD: return visitADD(N); + case ISD::SUB: return visitSUB(N); + case ISD::ADDC: return visitADDC(N); + case ISD::ADDE: return visitADDE(N); + case ISD::MUL: return visitMUL(N); + case ISD::SDIV: return visitSDIV(N); + case ISD::UDIV: return visitUDIV(N); + case ISD::SREM: return visitSREM(N); + case ISD::UREM: return visitUREM(N); + case ISD::MULHU: return visitMULHU(N); + case ISD::MULHS: return visitMULHS(N); + case ISD::SMUL_LOHI: return visitSMUL_LOHI(N); + case ISD::UMUL_LOHI: return visitUMUL_LOHI(N); + case ISD::SDIVREM: return visitSDIVREM(N); + case ISD::UDIVREM: return visitUDIVREM(N); + case ISD::AND: return visitAND(N); + case ISD::OR: return visitOR(N); + case ISD::XOR: return visitXOR(N); + case ISD::SHL: return visitSHL(N); + case ISD::SRA: return visitSRA(N); + case ISD::SRL: return visitSRL(N); + case ISD::CTLZ: return visitCTLZ(N); + case ISD::CTTZ: return visitCTTZ(N); + case ISD::CTPOP: return visitCTPOP(N); + case ISD::SELECT: return visitSELECT(N); + case ISD::SELECT_CC: return visitSELECT_CC(N); + case ISD::SETCC: return visitSETCC(N); + case ISD::SIGN_EXTEND: return visitSIGN_EXTEND(N); + case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N); + case ISD::ANY_EXTEND: return visitANY_EXTEND(N); + case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); + case ISD::TRUNCATE: return visitTRUNCATE(N); + case ISD::BITCAST: return visitBITCAST(N); + case ISD::BUILD_PAIR: return visitBUILD_PAIR(N); + case ISD::FADD: return visitFADD(N); + case ISD::FSUB: return visitFSUB(N); + case ISD::FMUL: return visitFMUL(N); + case ISD::FDIV: return visitFDIV(N); + case ISD::FREM: return visitFREM(N); + case ISD::FCOPYSIGN: return visitFCOPYSIGN(N); + case ISD::SINT_TO_FP: return visitSINT_TO_FP(N); + case ISD::UINT_TO_FP: return visitUINT_TO_FP(N); + case ISD::FP_TO_SINT: return visitFP_TO_SINT(N); + case ISD::FP_TO_UINT: return visitFP_TO_UINT(N); + case ISD::FP_ROUND: return visitFP_ROUND(N); + case ISD::FP_ROUND_INREG: return visitFP_ROUND_INREG(N); + case ISD::FP_EXTEND: return visitFP_EXTEND(N); + case ISD::FNEG: return visitFNEG(N); + case ISD::FABS: return visitFABS(N); + case ISD::BRCOND: return visitBRCOND(N); + case ISD::BR_CC: return visitBR_CC(N); + case ISD::LOAD: return visitLOAD(N); + case ISD::STORE: return visitSTORE(N); + case ISD::INSERT_VECTOR_ELT: return visitINSERT_VECTOR_ELT(N); + case ISD::EXTRACT_VECTOR_ELT: return visitEXTRACT_VECTOR_ELT(N); + case ISD::BUILD_VECTOR: return visitBUILD_VECTOR(N); + case ISD::CONCAT_VECTORS: return visitCONCAT_VECTORS(N); + case ISD::VECTOR_SHUFFLE: return visitVECTOR_SHUFFLE(N); + case ISD::MEMBARRIER: return visitMEMBARRIER(N); + } + return SDValue(); +} + +SDValue DAGCombiner::combine(SDNode *N) { + SDValue RV = visit(N); + + // If nothing happened, try a target-specific DAG combine. + if (RV.getNode() == 0) { + assert(N->getOpcode() != ISD::DELETED_NODE && + "Node was deleted but visit returned NULL!"); + + if (N->getOpcode() >= ISD::BUILTIN_OP_END || + TLI.hasTargetDAGCombine((ISD::NodeType)N->getOpcode())) { + + // Expose the DAG combiner to the target combiner impls. + TargetLowering::DAGCombinerInfo + DagCombineInfo(DAG, !LegalTypes, !LegalOperations, false, this); + + RV = TLI.PerformDAGCombine(N, DagCombineInfo); + } + } + + // If nothing happened still, try promoting the operation. + if (RV.getNode() == 0) { + switch (N->getOpcode()) { + default: break; + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + RV = PromoteIntBinOp(SDValue(N, 0)); + break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + RV = PromoteIntShiftOp(SDValue(N, 0)); + break; + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + RV = PromoteExtend(SDValue(N, 0)); + break; + case ISD::LOAD: + if (PromoteLoad(SDValue(N, 0))) + RV = SDValue(N, 0); + break; + } + } + + // If N is a commutative binary node, try commuting it to enable more + // sdisel CSE. + if (RV.getNode() == 0 && + SelectionDAG::isCommutativeBinOp(N->getOpcode()) && + N->getNumValues() == 1) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + // Constant operands are canonicalized to RHS. + if (isa(N0) || !isa(N1)) { + SDValue Ops[] = { N1, N0 }; + SDNode *CSENode = DAG.getNodeIfExists(N->getOpcode(), N->getVTList(), + Ops, 2); + if (CSENode) + return SDValue(CSENode, 0); + } + } + + return RV; +} + +/// getInputChainForNode - Given a node, return its input chain if it has one, +/// otherwise return a null sd operand. +static SDValue getInputChainForNode(SDNode *N) { + if (unsigned NumOps = N->getNumOperands()) { + if (N->getOperand(0).getValueType() == MVT::Other) + return N->getOperand(0); + else if (N->getOperand(NumOps-1).getValueType() == MVT::Other) + return N->getOperand(NumOps-1); + for (unsigned i = 1; i < NumOps-1; ++i) + if (N->getOperand(i).getValueType() == MVT::Other) + return N->getOperand(i); + } + return SDValue(); +} + +SDValue DAGCombiner::visitTokenFactor(SDNode *N) { + // If N has two operands, where one has an input chain equal to the other, + // the 'other' chain is redundant. + if (N->getNumOperands() == 2) { + if (getInputChainForNode(N->getOperand(0).getNode()) == N->getOperand(1)) + return N->getOperand(0); + if (getInputChainForNode(N->getOperand(1).getNode()) == N->getOperand(0)) + return N->getOperand(1); + } + + SmallVector TFs; // List of token factors to visit. + SmallVector Ops; // Ops for replacing token factor. + SmallPtrSet SeenOps; + bool Changed = false; // If we should replace this token factor. + + // Start out with this token factor. + TFs.push_back(N); + + // Iterate through token factors. The TFs grows when new token factors are + // encountered. + for (unsigned i = 0; i < TFs.size(); ++i) { + SDNode *TF = TFs[i]; + + // Check each of the operands. + for (unsigned i = 0, ie = TF->getNumOperands(); i != ie; ++i) { + SDValue Op = TF->getOperand(i); + + switch (Op.getOpcode()) { + case ISD::EntryToken: + // Entry tokens don't need to be added to the list. They are + // rededundant. + Changed = true; + break; + + case ISD::TokenFactor: + if (Op.hasOneUse() && + std::find(TFs.begin(), TFs.end(), Op.getNode()) == TFs.end()) { + // Queue up for processing. + TFs.push_back(Op.getNode()); + // Clean up in case the token factor is removed. + AddToWorkList(Op.getNode()); + Changed = true; + break; + } + // Fall thru + + default: + // Only add if it isn't already in the list. + if (SeenOps.insert(Op.getNode())) + Ops.push_back(Op); + else + Changed = true; + break; + } + } + } + + SDValue Result; + + // If we've change things around then replace token factor. + if (Changed) { + if (Ops.empty()) { + // The entry token is the only possible outcome. + Result = DAG.getEntryNode(); + } else { + // New and improved token factor. + Result = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, &Ops[0], Ops.size()); + } + + // Don't add users to work list. + return CombineTo(N, Result, false); + } + + return Result; +} + +/// MERGE_VALUES can always be eliminated. +SDValue DAGCombiner::visitMERGE_VALUES(SDNode *N) { + WorkListRemover DeadNodes(*this); + // Replacing results may cause a different MERGE_VALUES to suddenly + // be CSE'd with N, and carry its uses with it. Iterate until no + // uses remain, to ensure that the node can be safely deleted. + do { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + DAG.ReplaceAllUsesOfValueWith(SDValue(N, i), N->getOperand(i), + &DeadNodes); + } while (!N->use_empty()); + removeFromWorkList(N); + DAG.DeleteNode(N); + return SDValue(N, 0); // Return N so it doesn't get rechecked! +} + +static +SDValue combineShlAddConstant(DebugLoc DL, SDValue N0, SDValue N1, + SelectionDAG &DAG) { + EVT VT = N0.getValueType(); + SDValue N00 = N0.getOperand(0); + SDValue N01 = N0.getOperand(1); + ConstantSDNode *N01C = dyn_cast(N01); + + if (N01C && N00.getOpcode() == ISD::ADD && N00.getNode()->hasOneUse() && + isa(N00.getOperand(1))) { + // fold (add (shl (add x, c1), c2), ) -> (add (add (shl x, c2), c1<(V.getOperand(0)); + return C && C->isNullValue() && V.getOperand(0) == V.getOperand(1); +} + +SDValue DAGCombiner::visitADD(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (add x, undef) -> undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + // fold (add c1, c2) -> c1+c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::ADD, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, N0); + // fold (add x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (add Sym, c) -> Sym+c + if (GlobalAddressSDNode *GA = dyn_cast(N0)) + if (!LegalOperations && TLI.isOffsetFoldingLegal(GA) && N1C && + GA->getOpcode() == ISD::GlobalAddress) + return DAG.getGlobalAddress(GA->getGlobal(), N1C->getDebugLoc(), VT, + GA->getOffset() + + (uint64_t)N1C->getSExtValue()); + // fold ((c1-A)+c2) -> (c1+c2)-A + if (N1C && N0.getOpcode() == ISD::SUB) + if (ConstantSDNode *N0C = dyn_cast(N0.getOperand(0))) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(N1C->getAPIntValue()+ + N0C->getAPIntValue(), VT), + N0.getOperand(1)); + // reassociate add + SDValue RADD = ReassociateOps(ISD::ADD, N->getDebugLoc(), N0, N1); + if (RADD.getNode() != 0) + return RADD; + // fold ((0-A) + B) -> B-A + if (N0.getOpcode() == ISD::SUB && isa(N0.getOperand(0)) && + cast(N0.getOperand(0))->isNullValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1, N0.getOperand(1)); + // fold (A + (0-B)) -> A-B + if (N1.getOpcode() == ISD::SUB && isa(N1.getOperand(0)) && + cast(N1.getOperand(0))->isNullValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, N1.getOperand(1)); + // fold (A+(B-A)) -> B + if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(1)) + return N1.getOperand(0); + // fold ((B-A)+A) -> B + if (N0.getOpcode() == ISD::SUB && N1 == N0.getOperand(1)) + return N0.getOperand(0); + // fold (A+(B-(A+C))) to (B-C) + if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && + N0 == N1.getOperand(1).getOperand(0)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1.getOperand(0), + N1.getOperand(1).getOperand(1)); + // fold (A+(B-(C+A))) to (B-C) + if (N1.getOpcode() == ISD::SUB && N1.getOperand(1).getOpcode() == ISD::ADD && + N0 == N1.getOperand(1).getOperand(1)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1.getOperand(0), + N1.getOperand(1).getOperand(0)); + // fold (A+((B-A)+or-C)) to (B+or-C) + if ((N1.getOpcode() == ISD::SUB || N1.getOpcode() == ISD::ADD) && + N1.getOperand(0).getOpcode() == ISD::SUB && + N0 == N1.getOperand(0).getOperand(1)) + return DAG.getNode(N1.getOpcode(), N->getDebugLoc(), VT, + N1.getOperand(0).getOperand(0), N1.getOperand(1)); + + // fold (A-B)+(C-D) to (A+C)-(B+D) when A or C is constant + if (N0.getOpcode() == ISD::SUB && N1.getOpcode() == ISD::SUB) { + SDValue N00 = N0.getOperand(0); + SDValue N01 = N0.getOperand(1); + SDValue N10 = N1.getOperand(0); + SDValue N11 = N1.getOperand(1); + + if (isa(N00) || isa(N10)) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getNode(ISD::ADD, N0.getDebugLoc(), VT, N00, N10), + DAG.getNode(ISD::ADD, N1.getDebugLoc(), VT, N01, N11)); + } + + if (!VT.isVector() && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (a+b) -> (a|b) iff a and b share no bits. + if (VT.isInteger() && !VT.isVector()) { + APInt LHSZero, LHSOne; + APInt RHSZero, RHSOne; + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); + DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); + + if (LHSZero.getBoolValue()) { + DAG.ComputeMaskedBits(N1, Mask, RHSZero, RHSOne); + + // If all possibly-set bits on the LHS are clear on the RHS, return an OR. + // If all possibly-set bits on the RHS are clear on the LHS, return an OR. + if ((RHSZero & (~LHSZero & Mask)) == (~LHSZero & Mask) || + (LHSZero & (~RHSZero & Mask)) == (~RHSZero & Mask)) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N1); + } + } + + // fold (add (shl (add x, c1), c2), ) -> (add (add (shl x, c2), c1<hasOneUse()) { + SDValue Result = combineShlAddConstant(N->getDebugLoc(), N0, N1, DAG); + if (Result.getNode()) return Result; + } + if (N1.getOpcode() == ISD::SHL && N1.getNode()->hasOneUse()) { + SDValue Result = combineShlAddConstant(N->getDebugLoc(), N1, N0, DAG); + if (Result.getNode()) return Result; + } + + // fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n)) + if (N1.getOpcode() == ISD::SHL && + N1.getOperand(0).getOpcode() == ISD::SUB) + if (ConstantSDNode *C = + dyn_cast(N1.getOperand(0).getOperand(0))) + if (C->getAPIntValue() == 0) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N1.getOperand(0).getOperand(1), + N1.getOperand(1))); + if (N0.getOpcode() == ISD::SHL && + N0.getOperand(0).getOpcode() == ISD::SUB) + if (ConstantSDNode *C = + dyn_cast(N0.getOperand(0).getOperand(0))) + if (C->getAPIntValue() == 0) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N1, + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N0.getOperand(0).getOperand(1), + N0.getOperand(1))); + + if (N1.getOpcode() == ISD::AND) { + SDValue AndOp0 = N1.getOperand(0); + ConstantSDNode *AndOp1 = dyn_cast(N1->getOperand(1)); + unsigned NumSignBits = DAG.ComputeNumSignBits(AndOp0); + unsigned DestBits = VT.getScalarType().getSizeInBits(); + + // (add z, (and (sbbl x, x), 1)) -> (sub z, (sbbl x, x)) + // and similar xforms where the inner op is either ~0 or 0. + if (NumSignBits == DestBits && AndOp1 && AndOp1->isOne()) { + DebugLoc DL = N->getDebugLoc(); + return DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), AndOp0); + } + } + + // add (sext i1), X -> sub X, (zext i1) + if (N0.getOpcode() == ISD::SIGN_EXTEND && + N0.getOperand(0).getValueType() == MVT::i1 && + !TLI.isOperationLegal(ISD::SIGN_EXTEND, MVT::i1)) { + DebugLoc DL = N->getDebugLoc(); + SDValue ZExt = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)); + return DAG.getNode(ISD::SUB, DL, VT, N1, ZExt); + } + + // add (adde 0, 0, glue), X -> adde X, 0, glue + if (N0->hasOneUse() && isCarryMaterialization(N0)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), + DAG.getVTList(VT, MVT::Glue), N1, N0.getOperand(0), + N0.getOperand(2)); + + // add X, (adde 0, 0, glue) -> adde X, 0, glue + if (N1->hasOneUse() && isCarryMaterialization(N1)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), + DAG.getVTList(VT, MVT::Glue), N0, N1.getOperand(0), + N1.getOperand(2)); + + return SDValue(); +} + +SDValue DAGCombiner::visitADDC(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // If the flag result is dead, turn this into an ADD. + if (N->hasNUsesOfValue(0, 1)) + return CombineTo(N, DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, N0), + DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Glue)); + + // canonicalize constant to RHS. + if (N0C && !N1C) + return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0); + + // fold (addc x, 0) -> x + no carry out + if (N1C && N1C->isNullValue()) + return CombineTo(N, N0, DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Glue)); + + // fold (addc a, b) -> (or a, b), CARRY_FALSE iff a and b share no bits. + APInt LHSZero, LHSOne; + APInt RHSZero, RHSOne; + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); + DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); + + if (LHSZero.getBoolValue()) { + DAG.ComputeMaskedBits(N1, Mask, RHSZero, RHSOne); + + // If all possibly-set bits on the LHS are clear on the RHS, return an OR. + // If all possibly-set bits on the RHS are clear on the LHS, return an OR. + if ((RHSZero & (~LHSZero & Mask)) == (~LHSZero & Mask) || + (LHSZero & (~RHSZero & Mask)) == (~RHSZero & Mask)) + return CombineTo(N, DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N1), + DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), MVT::Glue)); + } + + // addc (adde 0, 0, glue), X -> adde X, 0, glue + if (N0->hasOneUse() && isCarryMaterialization(N0)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N1, + DAG.getConstant(0, VT), N0.getOperand(2)); + + // addc X, (adde 0, 0, glue) -> adde X, 0, glue + if (N1->hasOneUse() && isCarryMaterialization(N1)) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), N0, + DAG.getConstant(0, VT), N1.getOperand(2)); + + return SDValue(); +} + +SDValue DAGCombiner::visitADDE(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue CarryIn = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + + // If both operands are null we know that carry out will always be false. + if (N0C && N0C->isNullValue() && N0 == N1) + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), DAG.getNode(ISD::CARRY_FALSE, + N->getDebugLoc(), + MVT::Glue)); + + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::ADDE, N->getDebugLoc(), N->getVTList(), + N1, N0, CarryIn); + + // fold (adde x, y, false) -> (addc x, y) + if (CarryIn.getOpcode() == ISD::CARRY_FALSE) + return DAG.getNode(ISD::ADDC, N->getDebugLoc(), N->getVTList(), N1, N0); + + return SDValue(); +} + +// Since it may not be valid to emit a fold to zero for vector initializers +// check if we can before folding. +static SDValue tryFoldToZero(DebugLoc DL, const TargetLowering &TLI, EVT VT, + SelectionDAG &DAG, bool LegalOperations) { + if (!VT.isVector()) { + return DAG.getConstant(0, VT); + } else if (!LegalOperations || TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) { + // Produce a vector of zeros. + SDValue El = DAG.getConstant(0, VT.getVectorElementType()); + std::vector Ops(VT.getVectorNumElements(), El); + return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, + &Ops[0], Ops.size()); + } + return SDValue(); +} + +SDValue DAGCombiner::visitSUB(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (sub x, x) -> 0 + // FIXME: Refactor this and xor and other similar operations together. + if (N0 == N1) + return tryFoldToZero(N->getDebugLoc(), TLI, VT, DAG, LegalOperations); + // fold (sub c1, c2) -> c1-c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SUB, VT, N0C, N1C); + // fold (sub x, c) -> (add x, -c) + if (N1C) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, + DAG.getConstant(-N1C->getAPIntValue(), VT)); + // Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1) + if (N0C && N0C->isAllOnesValue()) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0); + // fold A-(A-B) -> B + if (N1.getOpcode() == ISD::SUB && N0 == N1.getOperand(0)) + return N1.getOperand(1); + // fold (A+B)-A -> B + if (N0.getOpcode() == ISD::ADD && N0.getOperand(0) == N1) + return N0.getOperand(1); + // fold (A+B)-B -> A + if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1) + return N0.getOperand(0); + // fold ((A+(B+or-C))-B) -> A+or-C + if (N0.getOpcode() == ISD::ADD && + (N0.getOperand(1).getOpcode() == ISD::SUB || + N0.getOperand(1).getOpcode() == ISD::ADD) && + N0.getOperand(1).getOperand(0) == N1) + return DAG.getNode(N0.getOperand(1).getOpcode(), N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(1)); + // fold ((A+(C+B))-B) -> A+C + if (N0.getOpcode() == ISD::ADD && + N0.getOperand(1).getOpcode() == ISD::ADD && + N0.getOperand(1).getOperand(1) == N1) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(0)); + // fold ((A-(B-C))-C) -> A-B + if (N0.getOpcode() == ISD::SUB && + N0.getOperand(1).getOpcode() == ISD::SUB && + N0.getOperand(1).getOperand(1) == N1) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1).getOperand(0)); + + // If either operand of a sub is undef, the result is undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + // If the relocation model supports it, consider symbol offsets. + if (GlobalAddressSDNode *GA = dyn_cast(N0)) + if (!LegalOperations && TLI.isOffsetFoldingLegal(GA)) { + // fold (sub Sym, c) -> Sym-c + if (N1C && GA->getOpcode() == ISD::GlobalAddress) + return DAG.getGlobalAddress(GA->getGlobal(), N1C->getDebugLoc(), VT, + GA->getOffset() - + (uint64_t)N1C->getSExtValue()); + // fold (sub Sym+c1, Sym+c2) -> c1-c2 + if (GlobalAddressSDNode *GB = dyn_cast(N1)) + if (GA->getGlobal() == GB->getGlobal()) + return DAG.getConstant((uint64_t)GA->getOffset() - GB->getOffset(), + VT); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitMUL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (mul x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (mul c1, c2) -> c1*c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::MUL, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, N1, N0); + // fold (mul x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mul x, -1) -> 0-x + if (N1C && N1C->isAllOnesValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), N0); + // fold (mul x, (1 << c)) -> x << c + if (N1C && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue().logBase2(), + getShiftAmountTy(N0.getValueType()))); + // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c + if (N1C && (-N1C->getAPIntValue()).isPowerOf2()) { + unsigned Log2Val = (-N1C->getAPIntValue()).logBase2(); + // FIXME: If the input is something that is easily negated (e.g. a + // single-use add), we should put the negate there. + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), + DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getConstant(Log2Val, + getShiftAmountTy(N0.getValueType())))); + } + // (mul (shl X, c1), c2) -> (mul X, c2 << c1) + if (N1C && N0.getOpcode() == ISD::SHL && + isa(N0.getOperand(1))) { + SDValue C3 = DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + N1, N0.getOperand(1)); + AddToWorkList(C3.getNode()); + return DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + N0.getOperand(0), C3); + } + + // Change (mul (shl X, C), Y) -> (shl (mul X, Y), C) when the shift has one + // use. + { + SDValue Sh(0,0), Y(0,0); + // Check for both (mul (shl X, C), Y) and (mul Y, (shl X, C)). + if (N0.getOpcode() == ISD::SHL && isa(N0.getOperand(1)) && + N0.getNode()->hasOneUse()) { + Sh = N0; Y = N1; + } else if (N1.getOpcode() == ISD::SHL && + isa(N1.getOperand(1)) && + N1.getNode()->hasOneUse()) { + Sh = N1; Y = N0; + } + + if (Sh.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + Sh.getOperand(0), Y); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, + Mul, Sh.getOperand(1)); + } + } + + // fold (mul (add x, c1), c2) -> (add (mul x, c2), c1*c2) + if (N1C && N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse() && + isa(N0.getOperand(1))) + return DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, + DAG.getNode(ISD::MUL, N0.getDebugLoc(), VT, + N0.getOperand(0), N1), + DAG.getNode(ISD::MUL, N1.getDebugLoc(), VT, + N0.getOperand(1), N1)); + + // reassociate mul + SDValue RMUL = ReassociateOps(ISD::MUL, N->getDebugLoc(), N0, N1); + if (RMUL.getNode() != 0) + return RMUL; + + return SDValue(); +} + +SDValue DAGCombiner::visitSDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (sdiv c1, c2) -> c1/c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::SDIV, VT, N0C, N1C); + // fold (sdiv X, 1) -> X + if (N1C && N1C->getSExtValue() == 1LL) + return N0; + // fold (sdiv X, -1) -> 0-X + if (N1C && N1C->isAllOnesValue()) + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), N0); + // If we know the sign bits of both operands are zero, strength reduce to a + // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 + if (!VT.isVector()) { + if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UDIV, N->getDebugLoc(), N1.getValueType(), + N0, N1); + } + // fold (sdiv X, pow2) -> simple ops after legalize + if (N1C && !N1C->isNullValue() && !TLI.isIntDivCheap() && + (isPowerOf2_64(N1C->getSExtValue()) || + isPowerOf2_64(-N1C->getSExtValue()))) { + // If dividing by powers of two is cheap, then don't perform the following + // fold. + if (TLI.isPow2DivCheap()) + return SDValue(); + + int64_t pow2 = N1C->getSExtValue(); + int64_t abs2 = pow2 > 0 ? pow2 : -pow2; + unsigned lg2 = Log2_64(abs2); + + // Splat the sign bit into the register + SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, + DAG.getConstant(VT.getSizeInBits()-1, + getShiftAmountTy(N0.getValueType()))); + AddToWorkList(SGN.getNode()); + + // Add (N0 < 0) ? abs2 - 1 : 0; + SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN, + DAG.getConstant(VT.getSizeInBits() - lg2, + getShiftAmountTy(SGN.getValueType()))); + SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL); + AddToWorkList(SRL.getNode()); + AddToWorkList(ADD.getNode()); // Divide by pow2 + SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD, + DAG.getConstant(lg2, getShiftAmountTy(ADD.getValueType()))); + + // If we're dividing by a positive value, we're done. Otherwise, we must + // negate the result. + if (pow2 > 0) + return SRA; + + AddToWorkList(SRA.getNode()); + return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, + DAG.getConstant(0, VT), SRA); + } + + // if integer divide is expensive and we satisfy the requirements, emit an + // alternate sequence. + if (N1C && (N1C->getSExtValue() < -1 || N1C->getSExtValue() > 1) && + !TLI.isIntDivCheap()) { + SDValue Op = BuildSDIV(N); + if (Op.getNode()) return Op; + } + + // undef / X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X / undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitUDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0.getNode()); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (udiv c1, c2) -> c1/c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::UDIV, VT, N0C, N1C); + // fold (udiv x, (1 << c)) -> x >>u c + if (N1C && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue().logBase2(), + getShiftAmountTy(N0.getValueType()))); + // fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2 + if (N1.getOpcode() == ISD::SHL) { + if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { + if (SHC->getAPIntValue().isPowerOf2()) { + EVT ADDVT = N1.getOperand(1).getValueType(); + SDValue Add = DAG.getNode(ISD::ADD, N->getDebugLoc(), ADDVT, + N1.getOperand(1), + DAG.getConstant(SHC->getAPIntValue() + .logBase2(), + ADDVT)); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, Add); + } + } + } + // fold (udiv x, c) -> alternate + if (N1C && !N1C->isNullValue() && !TLI.isIntDivCheap()) { + SDValue Op = BuildUDIV(N); + if (Op.getNode()) return Op; + } + + // undef / X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X / undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitSREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (srem c1, c2) -> c1%c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::SREM, VT, N0C, N1C); + // If we know the sign bits of both operands are zero, strength reduce to a + // urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15 + if (!VT.isVector()) { + if (DAG.SignBitIsZero(N1) && DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UREM, N->getDebugLoc(), VT, N0, N1); + } + + // If X/C can be simplified by the division-by-constant logic, lower + // X%C to the equivalent of X-X/C*C. + if (N1C && !N1C->isNullValue()) { + SDValue Div = DAG.getNode(ISD::SDIV, N->getDebugLoc(), VT, N0, N1); + AddToWorkList(Div.getNode()); + SDValue OptimizedDiv = combine(Div.getNode()); + if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + OptimizedDiv, N1); + SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul); + AddToWorkList(Mul.getNode()); + return Sub; + } + } + + // undef % X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X % undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitUREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (urem c1, c2) -> c1%c2 + if (N0C && N1C && !N1C->isNullValue()) + return DAG.FoldConstantArithmetic(ISD::UREM, VT, N0C, N1C); + // fold (urem x, pow2) -> (and x, pow2-1) + if (N1C && !N1C->isNullValue() && N1C->getAPIntValue().isPowerOf2()) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, + DAG.getConstant(N1C->getAPIntValue()-1,VT)); + // fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1)) + if (N1.getOpcode() == ISD::SHL) { + if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { + if (SHC->getAPIntValue().isPowerOf2()) { + SDValue Add = + DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N1, + DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), + VT)); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, Add); + } + } + } + + // If X/C can be simplified by the division-by-constant logic, lower + // X%C to the equivalent of X-X/C*C. + if (N1C && !N1C->isNullValue()) { + SDValue Div = DAG.getNode(ISD::UDIV, N->getDebugLoc(), VT, N0, N1); + AddToWorkList(Div.getNode()); + SDValue OptimizedDiv = combine(Div.getNode()); + if (OptimizedDiv.getNode() && OptimizedDiv.getNode() != Div.getNode()) { + SDValue Mul = DAG.getNode(ISD::MUL, N->getDebugLoc(), VT, + OptimizedDiv, N1); + SDValue Sub = DAG.getNode(ISD::SUB, N->getDebugLoc(), VT, N0, Mul); + AddToWorkList(Mul.getNode()); + return Sub; + } + } + + // undef % X -> 0 + if (N0.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // X % undef -> undef + if (N1.getOpcode() == ISD::UNDEF) + return N1; + + return SDValue(); +} + +SDValue DAGCombiner::visitMULHS(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + + // fold (mulhs x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mulhs x, 1) -> (sra x, size(x)-1) + if (N1C && N1C->getAPIntValue() == 1) + return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0, + DAG.getConstant(N0.getValueType().getSizeInBits() - 1, + getShiftAmountTy(N0.getValueType()))); + // fold (mulhs x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + + // If the type twice as wide is legal, transform the mulhs to a wider multiply + // plus a shift. + if (VT.isSimple() && !VT.isVector()) { + MVT Simple = VT.getSimpleVT(); + unsigned SimpleSize = Simple.getSizeInBits(); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); + if (TLI.isOperationLegal(ISD::MUL, NewVT)) { + N0 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N0); + N1 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1); + N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1); + N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1, + DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType()))); + return DAG.getNode(ISD::TRUNCATE, DL, VT, N1); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitMULHU(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + + // fold (mulhu x, 0) -> 0 + if (N1C && N1C->isNullValue()) + return N1; + // fold (mulhu x, 1) -> 0 + if (N1C && N1C->getAPIntValue() == 1) + return DAG.getConstant(0, N0.getValueType()); + // fold (mulhu x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + + // If the type twice as wide is legal, transform the mulhu to a wider multiply + // plus a shift. + if (VT.isSimple() && !VT.isVector()) { + MVT Simple = VT.getSimpleVT(); + unsigned SimpleSize = Simple.getSizeInBits(); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); + if (TLI.isOperationLegal(ISD::MUL, NewVT)) { + N0 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N0); + N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1); + N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1); + N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1, + DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType()))); + return DAG.getNode(ISD::TRUNCATE, DL, VT, N1); + } + } + + return SDValue(); +} + +/// SimplifyNodeWithTwoResults - Perform optimizations common to nodes that +/// compute two values. LoOp and HiOp give the opcodes for the two computations +/// that are being performed. Return true if a simplification was made. +/// +SDValue DAGCombiner::SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, + unsigned HiOp) { + // If the high half is not needed, just compute the low half. + bool HiExists = N->hasAnyUseOfValue(1); + if (!HiExists && + (!LegalOperations || + TLI.isOperationLegal(LoOp, N->getValueType(0)))) { + SDValue Res = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0), + N->op_begin(), N->getNumOperands()); + return CombineTo(N, Res, Res); + } + + // If the low half is not needed, just compute the high half. + bool LoExists = N->hasAnyUseOfValue(0); + if (!LoExists && + (!LegalOperations || + TLI.isOperationLegal(HiOp, N->getValueType(1)))) { + SDValue Res = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1), + N->op_begin(), N->getNumOperands()); + return CombineTo(N, Res, Res); + } + + // If both halves are used, return as it is. + if (LoExists && HiExists) + return SDValue(); + + // If the two computed results can be simplified separately, separate them. + if (LoExists) { + SDValue Lo = DAG.getNode(LoOp, N->getDebugLoc(), N->getValueType(0), + N->op_begin(), N->getNumOperands()); + AddToWorkList(Lo.getNode()); + SDValue LoOpt = combine(Lo.getNode()); + if (LoOpt.getNode() && LoOpt.getNode() != Lo.getNode() && + (!LegalOperations || + TLI.isOperationLegal(LoOpt.getOpcode(), LoOpt.getValueType()))) + return CombineTo(N, LoOpt, LoOpt); + } + + if (HiExists) { + SDValue Hi = DAG.getNode(HiOp, N->getDebugLoc(), N->getValueType(1), + N->op_begin(), N->getNumOperands()); + AddToWorkList(Hi.getNode()); + SDValue HiOpt = combine(Hi.getNode()); + if (HiOpt.getNode() && HiOpt != Hi && + (!LegalOperations || + TLI.isOperationLegal(HiOpt.getOpcode(), HiOpt.getValueType()))) + return CombineTo(N, HiOpt, HiOpt); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS); + if (Res.getNode()) return Res; + + EVT VT = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + + // If the type twice as wide is legal, transform the mulhu to a wider multiply + // plus a shift. + if (VT.isSimple() && !VT.isVector()) { + MVT Simple = VT.getSimpleVT(); + unsigned SimpleSize = Simple.getSizeInBits(); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); + if (TLI.isOperationLegal(ISD::MUL, NewVT)) { + SDValue Lo = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N->getOperand(0)); + SDValue Hi = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N->getOperand(1)); + Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); + // Compute the high part as N1. + Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, + DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType()))); + Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi); + // Compute the low part as N0. + Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo); + return CombineTo(N, Lo, Hi); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU); + if (Res.getNode()) return Res; + + EVT VT = N->getValueType(0); + DebugLoc DL = N->getDebugLoc(); + + // If the type twice as wide is legal, transform the mulhu to a wider multiply + // plus a shift. + if (VT.isSimple() && !VT.isVector()) { + MVT Simple = VT.getSimpleVT(); + unsigned SimpleSize = Simple.getSizeInBits(); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); + if (TLI.isOperationLegal(ISD::MUL, NewVT)) { + SDValue Lo = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N->getOperand(0)); + SDValue Hi = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N->getOperand(1)); + Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); + // Compute the high part as N1. + Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, + DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType()))); + Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi); + // Compute the low part as N0. + Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo); + return CombineTo(N, Lo, Hi); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSDIVREM(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::SDIV, ISD::SREM); + if (Res.getNode()) return Res; + + return SDValue(); +} + +SDValue DAGCombiner::visitUDIVREM(SDNode *N) { + SDValue Res = SimplifyNodeWithTwoResults(N, ISD::UDIV, ISD::UREM); + if (Res.getNode()) return Res; + + return SDValue(); +} + +/// SimplifyBinOpWithSameOpcodeHands - If this is a binary operator with +/// two operands of the same opcode, try to simplify it. +SDValue DAGCombiner::SimplifyBinOpWithSameOpcodeHands(SDNode *N) { + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + EVT VT = N0.getValueType(); + assert(N0.getOpcode() == N1.getOpcode() && "Bad input!"); + + // Bail early if none of these transforms apply. + if (N0.getNode()->getNumOperands() == 0) return SDValue(); + + // For each of OP in AND/OR/XOR: + // fold (OP (zext x), (zext y)) -> (zext (OP x, y)) + // fold (OP (sext x), (sext y)) -> (sext (OP x, y)) + // fold (OP (aext x), (aext y)) -> (aext (OP x, y)) + // fold (OP (trunc x), (trunc y)) -> (trunc (OP x, y)) (if trunc isn't free) + // + // do not sink logical op inside of a vector extend, since it may combine + // into a vsetcc. + EVT Op0VT = N0.getOperand(0).getValueType(); + if ((N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND || + // Avoid infinite looping with PromoteIntBinOp. + (N0.getOpcode() == ISD::ANY_EXTEND && + (!LegalTypes || TLI.isTypeDesirableForOp(N->getOpcode(), Op0VT))) || + (N0.getOpcode() == ISD::TRUNCATE && + (!TLI.isZExtFree(VT, Op0VT) || + !TLI.isTruncateFree(Op0VT, VT)) && + TLI.isTypeLegal(Op0VT))) && + !VT.isVector() && + Op0VT == N1.getOperand(0).getValueType() && + (!LegalOperations || TLI.isOperationLegal(N->getOpcode(), Op0VT))) { + SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(), + N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + AddToWorkList(ORNode.getNode()); + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, ORNode); + } + + // For each of OP in SHL/SRL/SRA/AND... + // fold (and (OP x, z), (OP y, z)) -> (OP (and x, y), z) + // fold (or (OP x, z), (OP y, z)) -> (OP (or x, y), z) + // fold (xor (OP x, z), (OP y, z)) -> (OP (xor x, y), z) + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL || + N0.getOpcode() == ISD::SRA || N0.getOpcode() == ISD::AND) && + N0.getOperand(1) == N1.getOperand(1)) { + SDValue ORNode = DAG.getNode(N->getOpcode(), N0.getDebugLoc(), + N0.getOperand(0).getValueType(), + N0.getOperand(0), N1.getOperand(0)); + AddToWorkList(ORNode.getNode()); + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, + ORNode, N0.getOperand(1)); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitAND(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LL, LR, RL, RR, CC0, CC1; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N1.getValueType(); + unsigned BitWidth = VT.getScalarType().getSizeInBits(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (and x, undef) -> 0 + if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (and c1, c2) -> c1&c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::AND, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N1, N0); + // fold (and x, -1) -> x + if (N1C && N1C->isAllOnesValue()) + return N0; + // if (and x, c) is known to be zero, return 0 + if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(BitWidth))) + return DAG.getConstant(0, VT); + // reassociate and + SDValue RAND = ReassociateOps(ISD::AND, N->getDebugLoc(), N0, N1); + if (RAND.getNode() != 0) + return RAND; + // fold (and (or x, C), D) -> D if (C & D) == D + if (N1C && N0.getOpcode() == ISD::OR) + if (ConstantSDNode *ORI = dyn_cast(N0.getOperand(1))) + if ((ORI->getAPIntValue() & N1C->getAPIntValue()) == N1C->getAPIntValue()) + return N1; + // fold (and (any_ext V), c) -> (zero_ext V) if 'and' only clears top bits. + if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) { + SDValue N0Op0 = N0.getOperand(0); + APInt Mask = ~N1C->getAPIntValue(); + Mask = Mask.trunc(N0Op0.getValueSizeInBits()); + if (DAG.MaskedValueIsZero(N0Op0, Mask)) { + SDValue Zext = DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), + N0.getValueType(), N0Op0); + + // Replace uses of the AND with uses of the Zero extend node. + CombineTo(N, Zext); + + // We actually want to replace all uses of the any_extend with the + // zero_extend, to avoid duplicating things. This will later cause this + // AND to be folded. + CombineTo(N0.getNode(), Zext); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + // fold (and (setcc x), (setcc y)) -> (setcc (and x, y)) + if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){ + ISD::CondCode Op0 = cast(CC0)->get(); + ISD::CondCode Op1 = cast(CC1)->get(); + + if (LR == RR && isa(LR) && Op0 == Op1 && + LL.getValueType().isInteger()) { + // fold (and (seteq X, 0), (seteq Y, 0)) -> (seteq (or X, Y), 0) + if (cast(LR)->isNullValue() && Op1 == ISD::SETEQ) { + SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + // fold (and (seteq X, -1), (seteq Y, -1)) -> (seteq (and X, Y), -1) + if (cast(LR)->isAllOnesValue() && Op1 == ISD::SETEQ) { + SDValue ANDNode = DAG.getNode(ISD::AND, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ANDNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1); + } + // fold (and (setgt X, -1), (setgt Y, -1)) -> (setgt (or X, Y), -1) + if (cast(LR)->isAllOnesValue() && Op1 == ISD::SETGT) { + SDValue ORNode = DAG.getNode(ISD::OR, N0.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + } + // canonicalize equivalent to ll == rl + if (LL == RR && LR == RL) { + Op1 = ISD::getSetCCSwappedOperands(Op1); + std::swap(RL, RR); + } + if (LL == RL && LR == RR) { + bool isInteger = LL.getValueType().isInteger(); + ISD::CondCode Result = ISD::getSetCCAndOperation(Op0, Op1, isInteger); + if (Result != ISD::SETCC_INVALID && + (!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType()))) + return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(), + LL, LR, Result); + } + } + + // Simplify: (and (op x...), (op y...)) -> (op (and x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // fold (and (sign_extend_inreg x, i16 to i32), 1) -> (and x, 1) + // fold (and (sra)) -> (and (srl)) when possible. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (zext_inreg (extload x)) -> (zextload x) + if (ISD::isEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode())) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + // If we zero all the possible extended bits, then we can turn this into + // a zextload if we are running before legalize or the operation is legal. + unsigned BitWidth = N1.getValueType().getScalarType().getSizeInBits(); + if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, + BitWidth - MemVT.getScalarType().getSizeInBits())) && + ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, + LN0->getChain(), LN0->getBasePtr(), + LN0->getPointerInfo(), MemVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + AddToWorkList(N); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + // fold (zext_inreg (sextload x)) -> (zextload x) iff load has one use + if (ISD::isSEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + // If we zero all the possible extended bits, then we can turn this into + // a zextload if we are running before legalize or the operation is legal. + unsigned BitWidth = N1.getValueType().getScalarType().getSizeInBits(); + if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, + BitWidth - MemVT.getScalarType().getSizeInBits())) && + ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + MemVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + AddToWorkList(N); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (and (load x), 255) -> (zextload x, i8) + // fold (and (extload x, i16), 255) -> (zextload x, i8) + // fold (and (any_ext (extload x, i16)), 255) -> (zextload x, i8) + if (N1C && (N0.getOpcode() == ISD::LOAD || + (N0.getOpcode() == ISD::ANY_EXTEND && + N0.getOperand(0).getOpcode() == ISD::LOAD))) { + bool HasAnyExt = N0.getOpcode() == ISD::ANY_EXTEND; + LoadSDNode *LN0 = HasAnyExt + ? cast(N0.getOperand(0)) + : cast(N0); + if (LN0->getExtensionType() != ISD::SEXTLOAD && + LN0->isUnindexed() && N0.hasOneUse() && LN0->hasOneUse()) { + uint32_t ActiveBits = N1C->getAPIntValue().getActiveBits(); + if (ActiveBits > 0 && APIntOps::isMask(ActiveBits, N1C->getAPIntValue())){ + EVT ExtVT = EVT::getIntegerVT(*DAG.getContext(), ActiveBits); + EVT LoadedVT = LN0->getMemoryVT(); + + if (ExtVT == LoadedVT && + (!LegalOperations || TLI.isLoadExtLegal(ISD::ZEXTLOAD, ExtVT))) { + EVT LoadResultTy = HasAnyExt ? LN0->getValueType(0) : VT; + + SDValue NewLoad = + DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, + LN0->getChain(), LN0->getBasePtr(), + LN0->getPointerInfo(), + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + AddToWorkList(N); + CombineTo(LN0, NewLoad, NewLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + // Do not change the width of a volatile load. + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (!LN0->isVolatile() && LoadedVT.bitsGT(ExtVT) && ExtVT.isRound() && + (!LegalOperations || TLI.isLoadExtLegal(ISD::ZEXTLOAD, ExtVT))) { + EVT PtrType = LN0->getOperand(1).getValueType(); + + unsigned Alignment = LN0->getAlignment(); + SDValue NewPtr = LN0->getBasePtr(); + + // For big endian targets, we need to add an offset to the pointer + // to load the correct bytes. For little endian systems, we merely + // need to read fewer bytes from the same pointer. + if (TLI.isBigEndian()) { + unsigned LVTStoreBytes = LoadedVT.getStoreSize(); + unsigned EVTStoreBytes = ExtVT.getStoreSize(); + unsigned PtrOff = LVTStoreBytes - EVTStoreBytes; + NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(), PtrType, + NewPtr, DAG.getConstant(PtrOff, PtrType)); + Alignment = MinAlign(Alignment, PtrOff); + } + + AddToWorkList(NewPtr.getNode()); + + EVT LoadResultTy = HasAnyExt ? LN0->getValueType(0) : VT; + SDValue Load = + DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, + LN0->getChain(), NewPtr, + LN0->getPointerInfo(), + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + Alignment); + AddToWorkList(N); + CombineTo(LN0, Load, Load.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitOR(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LL, LR, RL, RR, CC0, CC1; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N1.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (or x, undef) -> -1 + if (!LegalOperations && + (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)) { + EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + return DAG.getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), VT); + } + // fold (or c1, c2) -> c1|c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::OR, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N1, N0); + // fold (or x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (or x, -1) -> -1 + if (N1C && N1C->isAllOnesValue()) + return N1; + // fold (or x, c) -> c iff (x & ~c) == 0 + if (N1C && DAG.MaskedValueIsZero(N0, ~N1C->getAPIntValue())) + return N1; + // reassociate or + SDValue ROR = ReassociateOps(ISD::OR, N->getDebugLoc(), N0, N1); + if (ROR.getNode() != 0) + return ROR; + // Canonicalize (or (and X, c1), c2) -> (and (or X, c2), c1|c2) + // iff (c1 & c2) == 0. + if (N1C && N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() && + isa(N0.getOperand(1))) { + ConstantSDNode *C1 = cast(N0.getOperand(1)); + if ((C1->getAPIntValue() & N1C->getAPIntValue()) != 0) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, + N0.getOperand(0), N1), + DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1)); + } + // fold (or (setcc x), (setcc y)) -> (setcc (or x, y)) + if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){ + ISD::CondCode Op0 = cast(CC0)->get(); + ISD::CondCode Op1 = cast(CC1)->get(); + + if (LR == RR && isa(LR) && Op0 == Op1 && + LL.getValueType().isInteger()) { + // fold (or (setne X, 0), (setne Y, 0)) -> (setne (or X, Y), 0) + // fold (or (setlt X, 0), (setlt Y, 0)) -> (setne (or X, Y), 0) + if (cast(LR)->isNullValue() && + (Op1 == ISD::SETNE || Op1 == ISD::SETLT)) { + SDValue ORNode = DAG.getNode(ISD::OR, LR.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ORNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ORNode, LR, Op1); + } + // fold (or (setne X, -1), (setne Y, -1)) -> (setne (and X, Y), -1) + // fold (or (setgt X, -1), (setgt Y -1)) -> (setgt (and X, Y), -1) + if (cast(LR)->isAllOnesValue() && + (Op1 == ISD::SETNE || Op1 == ISD::SETGT)) { + SDValue ANDNode = DAG.getNode(ISD::AND, LR.getDebugLoc(), + LR.getValueType(), LL, RL); + AddToWorkList(ANDNode.getNode()); + return DAG.getSetCC(N->getDebugLoc(), VT, ANDNode, LR, Op1); + } + } + // canonicalize equivalent to ll == rl + if (LL == RR && LR == RL) { + Op1 = ISD::getSetCCSwappedOperands(Op1); + std::swap(RL, RR); + } + if (LL == RL && LR == RR) { + bool isInteger = LL.getValueType().isInteger(); + ISD::CondCode Result = ISD::getSetCCOrOperation(Op0, Op1, isInteger); + if (Result != ISD::SETCC_INVALID && + (!LegalOperations || TLI.isCondCodeLegal(Result, LL.getValueType()))) + return DAG.getSetCC(N->getDebugLoc(), N0.getValueType(), + LL, LR, Result); + } + } + + // Simplify: (or (op x...), (op y...)) -> (op (or x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // (or (and X, C1), (and Y, C2)) -> (and (or X, Y), C3) if possible. + if (N0.getOpcode() == ISD::AND && + N1.getOpcode() == ISD::AND && + N0.getOperand(1).getOpcode() == ISD::Constant && + N1.getOperand(1).getOpcode() == ISD::Constant && + // Don't increase # computations. + (N0.getNode()->hasOneUse() || N1.getNode()->hasOneUse())) { + // We can only do this xform if we know that bits from X that are set in C2 + // but not in C1 are already zero. Likewise for Y. + const APInt &LHSMask = + cast(N0.getOperand(1))->getAPIntValue(); + const APInt &RHSMask = + cast(N1.getOperand(1))->getAPIntValue(); + + if (DAG.MaskedValueIsZero(N0.getOperand(0), RHSMask&~LHSMask) && + DAG.MaskedValueIsZero(N1.getOperand(0), LHSMask&~RHSMask)) { + SDValue X = DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, + N0.getOperand(0), N1.getOperand(0)); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, X, + DAG.getConstant(LHSMask | RHSMask, VT)); + } + } + + // See if this is some rotate idiom. + if (SDNode *Rot = MatchRotate(N0, N1, N->getDebugLoc())) + return SDValue(Rot, 0); + + // Simplify the operands using demanded-bits information. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + return SDValue(); +} + +/// MatchRotateHalf - Match "(X shl/srl V1) & V2" where V2 may not be present. +static bool MatchRotateHalf(SDValue Op, SDValue &Shift, SDValue &Mask) { + if (Op.getOpcode() == ISD::AND) { + if (isa(Op.getOperand(1))) { + Mask = Op.getOperand(1); + Op = Op.getOperand(0); + } else { + return false; + } + } + + if (Op.getOpcode() == ISD::SRL || Op.getOpcode() == ISD::SHL) { + Shift = Op; + return true; + } + + return false; +} + +// MatchRotate - Handle an 'or' of two operands. If this is one of the many +// idioms for rotate, and if the target supports rotation instructions, generate +// a rot[lr]. +SDNode *DAGCombiner::MatchRotate(SDValue LHS, SDValue RHS, DebugLoc DL) { + // Must be a legal type. Expanded 'n promoted things won't work with rotates. + EVT VT = LHS.getValueType(); + if (!TLI.isTypeLegal(VT)) return 0; + + // The target must have at least one rotate flavor. + bool HasROTL = TLI.isOperationLegalOrCustom(ISD::ROTL, VT); + bool HasROTR = TLI.isOperationLegalOrCustom(ISD::ROTR, VT); + if (!HasROTL && !HasROTR) return 0; + + // Match "(X shl/srl V1) & V2" where V2 may not be present. + SDValue LHSShift; // The shift. + SDValue LHSMask; // AND value if any. + if (!MatchRotateHalf(LHS, LHSShift, LHSMask)) + return 0; // Not part of a rotate. + + SDValue RHSShift; // The shift. + SDValue RHSMask; // AND value if any. + if (!MatchRotateHalf(RHS, RHSShift, RHSMask)) + return 0; // Not part of a rotate. + + if (LHSShift.getOperand(0) != RHSShift.getOperand(0)) + return 0; // Not shifting the same value. + + if (LHSShift.getOpcode() == RHSShift.getOpcode()) + return 0; // Shifts must disagree. + + // Canonicalize shl to left side in a shl/srl pair. + if (RHSShift.getOpcode() == ISD::SHL) { + std::swap(LHS, RHS); + std::swap(LHSShift, RHSShift); + std::swap(LHSMask , RHSMask ); + } + + unsigned OpSizeInBits = VT.getSizeInBits(); + SDValue LHSShiftArg = LHSShift.getOperand(0); + SDValue LHSShiftAmt = LHSShift.getOperand(1); + SDValue RHSShiftAmt = RHSShift.getOperand(1); + + // fold (or (shl x, C1), (srl x, C2)) -> (rotl x, C1) + // fold (or (shl x, C1), (srl x, C2)) -> (rotr x, C2) + if (LHSShiftAmt.getOpcode() == ISD::Constant && + RHSShiftAmt.getOpcode() == ISD::Constant) { + uint64_t LShVal = cast(LHSShiftAmt)->getZExtValue(); + uint64_t RShVal = cast(RHSShiftAmt)->getZExtValue(); + if ((LShVal + RShVal) != OpSizeInBits) + return 0; + + SDValue Rot; + if (HasROTL) + Rot = DAG.getNode(ISD::ROTL, DL, VT, LHSShiftArg, LHSShiftAmt); + else + Rot = DAG.getNode(ISD::ROTR, DL, VT, LHSShiftArg, RHSShiftAmt); + + // If there is an AND of either shifted operand, apply it to the result. + if (LHSMask.getNode() || RHSMask.getNode()) { + APInt Mask = APInt::getAllOnesValue(OpSizeInBits); + + if (LHSMask.getNode()) { + APInt RHSBits = APInt::getLowBitsSet(OpSizeInBits, LShVal); + Mask &= cast(LHSMask)->getAPIntValue() | RHSBits; + } + if (RHSMask.getNode()) { + APInt LHSBits = APInt::getHighBitsSet(OpSizeInBits, RShVal); + Mask &= cast(RHSMask)->getAPIntValue() | LHSBits; + } + + Rot = DAG.getNode(ISD::AND, DL, VT, Rot, DAG.getConstant(Mask, VT)); + } + + return Rot.getNode(); + } + + // If there is a mask here, and we have a variable shift, we can't be sure + // that we're masking out the right stuff. + if (LHSMask.getNode() || RHSMask.getNode()) + return 0; + + // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotl x, y) + // fold (or (shl x, y), (srl x, (sub 32, y))) -> (rotr x, (sub 32, y)) + if (RHSShiftAmt.getOpcode() == ISD::SUB && + LHSShiftAmt == RHSShiftAmt.getOperand(1)) { + if (ConstantSDNode *SUBC = + dyn_cast(RHSShiftAmt.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + if (HasROTL) + return DAG.getNode(ISD::ROTL, DL, VT, + LHSShiftArg, LHSShiftAmt).getNode(); + else + return DAG.getNode(ISD::ROTR, DL, VT, + LHSShiftArg, RHSShiftAmt).getNode(); + } + } + } + + // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotr x, y) + // fold (or (shl x, (sub 32, y)), (srl x, r)) -> (rotl x, (sub 32, y)) + if (LHSShiftAmt.getOpcode() == ISD::SUB && + RHSShiftAmt == LHSShiftAmt.getOperand(1)) { + if (ConstantSDNode *SUBC = + dyn_cast(LHSShiftAmt.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + if (HasROTR) + return DAG.getNode(ISD::ROTR, DL, VT, + LHSShiftArg, RHSShiftAmt).getNode(); + else + return DAG.getNode(ISD::ROTL, DL, VT, + LHSShiftArg, LHSShiftAmt).getNode(); + } + } + } + + // Look for sign/zext/any-extended or truncate cases: + if ((LHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND + || LHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND + || LHSShiftAmt.getOpcode() == ISD::ANY_EXTEND + || LHSShiftAmt.getOpcode() == ISD::TRUNCATE) && + (RHSShiftAmt.getOpcode() == ISD::SIGN_EXTEND + || RHSShiftAmt.getOpcode() == ISD::ZERO_EXTEND + || RHSShiftAmt.getOpcode() == ISD::ANY_EXTEND + || RHSShiftAmt.getOpcode() == ISD::TRUNCATE)) { + SDValue LExtOp0 = LHSShiftAmt.getOperand(0); + SDValue RExtOp0 = RHSShiftAmt.getOperand(0); + if (RExtOp0.getOpcode() == ISD::SUB && + RExtOp0.getOperand(1) == LExtOp0) { + // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) -> + // (rotl x, y) + // fold (or (shl x, (*ext y)), (srl x, (*ext (sub 32, y)))) -> + // (rotr x, (sub 32, y)) + if (ConstantSDNode *SUBC = + dyn_cast(RExtOp0.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + return DAG.getNode(HasROTL ? ISD::ROTL : ISD::ROTR, DL, VT, + LHSShiftArg, + HasROTL ? LHSShiftAmt : RHSShiftAmt).getNode(); + } + } + } else if (LExtOp0.getOpcode() == ISD::SUB && + RExtOp0 == LExtOp0.getOperand(1)) { + // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -> + // (rotr x, y) + // fold (or (shl x, (*ext (sub 32, y))), (srl x, (*ext y))) -> + // (rotl x, (sub 32, y)) + if (ConstantSDNode *SUBC = + dyn_cast(LExtOp0.getOperand(0))) { + if (SUBC->getAPIntValue() == OpSizeInBits) { + return DAG.getNode(HasROTR ? ISD::ROTR : ISD::ROTL, DL, VT, + LHSShiftArg, + HasROTR ? RHSShiftAmt : LHSShiftAmt).getNode(); + } + } + } + } + + return 0; +} + +SDValue DAGCombiner::visitXOR(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue LHS, RHS, CC; + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (xor undef, undef) -> 0. This is a common idiom (misuse). + if (N0.getOpcode() == ISD::UNDEF && N1.getOpcode() == ISD::UNDEF) + return DAG.getConstant(0, VT); + // fold (xor x, undef) -> undef + if (N0.getOpcode() == ISD::UNDEF) + return N0; + if (N1.getOpcode() == ISD::UNDEF) + return N1; + // fold (xor c1, c2) -> c1^c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::XOR, VT, N0C, N1C); + // canonicalize constant to RHS + if (N0C && !N1C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N1, N0); + // fold (xor x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // reassociate xor + SDValue RXOR = ReassociateOps(ISD::XOR, N->getDebugLoc(), N0, N1); + if (RXOR.getNode() != 0) + return RXOR; + + // fold !(x cc y) -> (x !cc y) + if (N1C && N1C->getAPIntValue() == 1 && isSetCCEquivalent(N0, LHS, RHS, CC)) { + bool isInt = LHS.getValueType().isInteger(); + ISD::CondCode NotCC = ISD::getSetCCInverse(cast(CC)->get(), + isInt); + + if (!LegalOperations || TLI.isCondCodeLegal(NotCC, LHS.getValueType())) { + switch (N0.getOpcode()) { + default: + llvm_unreachable("Unhandled SetCC Equivalent!"); + case ISD::SETCC: + return DAG.getSetCC(N->getDebugLoc(), VT, LHS, RHS, NotCC); + case ISD::SELECT_CC: + return DAG.getSelectCC(N->getDebugLoc(), LHS, RHS, N0.getOperand(2), + N0.getOperand(3), NotCC); + } + } + } + + // fold (not (zext (setcc x, y))) -> (zext (not (setcc x, y))) + if (N1C && N1C->getAPIntValue() == 1 && N0.getOpcode() == ISD::ZERO_EXTEND && + N0.getNode()->hasOneUse() && + isSetCCEquivalent(N0.getOperand(0), LHS, RHS, CC)){ + SDValue V = N0.getOperand(0); + V = DAG.getNode(ISD::XOR, N0.getDebugLoc(), V.getValueType(), V, + DAG.getConstant(1, V.getValueType())); + AddToWorkList(V.getNode()); + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, V); + } + + // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are setcc + if (N1C && N1C->getAPIntValue() == 1 && VT == MVT::i1 && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { + SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1); + if (isOneUseSetCC(RHS) || isOneUseSetCC(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; + LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS + RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS + AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode()); + return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS); + } + } + // fold (not (or x, y)) -> (and (not x), (not y)) iff x or y are constants + if (N1C && N1C->isAllOnesValue() && + (N0.getOpcode() == ISD::OR || N0.getOpcode() == ISD::AND)) { + SDValue LHS = N0.getOperand(0), RHS = N0.getOperand(1); + if (isa(RHS) || isa(LHS)) { + unsigned NewOpcode = N0.getOpcode() == ISD::AND ? ISD::OR : ISD::AND; + LHS = DAG.getNode(ISD::XOR, LHS.getDebugLoc(), VT, LHS, N1); // LHS = ~LHS + RHS = DAG.getNode(ISD::XOR, RHS.getDebugLoc(), VT, RHS, N1); // RHS = ~RHS + AddToWorkList(LHS.getNode()); AddToWorkList(RHS.getNode()); + return DAG.getNode(NewOpcode, N->getDebugLoc(), VT, LHS, RHS); + } + } + // fold (xor (xor x, c1), c2) -> (xor x, (xor c1, c2)) + if (N1C && N0.getOpcode() == ISD::XOR) { + ConstantSDNode *N00C = dyn_cast(N0.getOperand(0)); + ConstantSDNode *N01C = dyn_cast(N0.getOperand(1)); + if (N00C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(1), + DAG.getConstant(N1C->getAPIntValue() ^ + N00C->getAPIntValue(), VT)); + if (N01C) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(N1C->getAPIntValue() ^ + N01C->getAPIntValue(), VT)); + } + // fold (xor x, x) -> 0 + if (N0 == N1) + return tryFoldToZero(N->getDebugLoc(), TLI, VT, DAG, LegalOperations); + + // Simplify: xor (op x...), (op y...) -> (op (xor x, y)) + if (N0.getOpcode() == N1.getOpcode()) { + SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); + if (Tmp.getNode()) return Tmp; + } + + // Simplify the expression using non-local knowledge. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + return SDValue(); +} + +/// visitShiftByConstant - Handle transforms common to the three shifts, when +/// the shift amount is a constant. +SDValue DAGCombiner::visitShiftByConstant(SDNode *N, unsigned Amt) { + SDNode *LHS = N->getOperand(0).getNode(); + if (!LHS->hasOneUse()) return SDValue(); + + // We want to pull some binops through shifts, so that we have (and (shift)) + // instead of (shift (and)), likewise for add, or, xor, etc. This sort of + // thing happens with address calculations, so it's important to canonicalize + // it. + bool HighBitSet = false; // Can we transform this if the high bit is set? + + switch (LHS->getOpcode()) { + default: return SDValue(); + case ISD::OR: + case ISD::XOR: + HighBitSet = false; // We can only transform sra if the high bit is clear. + break; + case ISD::AND: + HighBitSet = true; // We can only transform sra if the high bit is set. + break; + case ISD::ADD: + if (N->getOpcode() != ISD::SHL) + return SDValue(); // only shl(add) not sr[al](add). + HighBitSet = false; // We can only transform sra if the high bit is clear. + break; + } + + // We require the RHS of the binop to be a constant as well. + ConstantSDNode *BinOpCst = dyn_cast(LHS->getOperand(1)); + if (!BinOpCst) return SDValue(); + + // FIXME: disable this unless the input to the binop is a shift by a constant. + // If it is not a shift, it pessimizes some common cases like: + // + // void foo(int *X, int i) { X[i & 1235] = 1; } + // int bar(int *X, int i) { return X[i & 255]; } + SDNode *BinOpLHSVal = LHS->getOperand(0).getNode(); + if ((BinOpLHSVal->getOpcode() != ISD::SHL && + BinOpLHSVal->getOpcode() != ISD::SRA && + BinOpLHSVal->getOpcode() != ISD::SRL) || + !isa(BinOpLHSVal->getOperand(1))) + return SDValue(); + + EVT VT = N->getValueType(0); + + // If this is a signed shift right, and the high bit is modified by the + // logical operation, do not perform the transformation. The highBitSet + // boolean indicates the value of the high bit of the constant which would + // cause it to be modified for this operation. + if (N->getOpcode() == ISD::SRA) { + bool BinOpRHSSignSet = BinOpCst->getAPIntValue().isNegative(); + if (BinOpRHSSignSet != HighBitSet) + return SDValue(); + } + + // Fold the constants, shifting the binop RHS by the shift amount. + SDValue NewRHS = DAG.getNode(N->getOpcode(), LHS->getOperand(1).getDebugLoc(), + N->getValueType(0), + LHS->getOperand(1), N->getOperand(1)); + + // Create the new shift. + SDValue NewShift = DAG.getNode(N->getOpcode(), + LHS->getOperand(0).getDebugLoc(), + VT, LHS->getOperand(0), N->getOperand(1)); + + // Create the new binop. + return DAG.getNode(LHS->getOpcode(), N->getDebugLoc(), VT, NewShift, NewRHS); +} + +SDValue DAGCombiner::visitSHL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); + + // fold (shl c1, c2) -> c1< 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (shl x, c >= size(x)) -> undef + if (N1C && N1C->getZExtValue() >= OpSizeInBits) + return DAG.getUNDEF(VT); + // fold (shl x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // if (shl x, c) is known to be zero, return 0 + if (DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(OpSizeInBits))) + return DAG.getConstant(0, VT); + // fold (shl x, (trunc (and y, c))) -> (shl x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC = TruncC.trunc(TruncVT.getSizeInBits()); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (shl (shl x, c1), c2) -> 0 or (shl x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SHL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + if (c1 + c2 >= OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(c1 + c2, N1.getValueType())); + } + + // fold (shl (ext (shl x, c1)), c2) -> (ext (shl x, (add c1, c2))) + // For this to be valid, the second form must not preserve any of the bits + // that are shifted out by the inner shift in the first form. This means + // the outer shift size must be >= the number of bits added by the ext. + // As a corollary, we don't care what kind of ext it is. + if (N1C && (N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::ANY_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND) && + N0.getOperand(0).getOpcode() == ISD::SHL && + isa(N0.getOperand(0)->getOperand(1))) { + uint64_t c1 = + cast(N0.getOperand(0)->getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + EVT InnerShiftVT = N0.getOperand(0).getValueType(); + uint64_t InnerShiftSize = InnerShiftVT.getScalarType().getSizeInBits(); + if (c2 >= OpSizeInBits - InnerShiftSize) { + if (c1 + c2 >= OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SHL, N0->getDebugLoc(), VT, + DAG.getNode(N0.getOpcode(), N0->getDebugLoc(), VT, + N0.getOperand(0)->getOperand(0)), + DAG.getConstant(c1 + c2, N1.getValueType())); + } + } + + // fold (shl (srl x, c1), c2) -> (shl (and x, (shl -1, c1)), (sub c2, c1)) or + // (srl (and x, (shl -1, c1)), (sub c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + if (c1 < VT.getSizeInBits()) { + uint64_t c2 = N1C->getZExtValue(); + SDValue HiBitsMask = + DAG.getConstant(APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - c1), + VT); + SDValue Mask = DAG.getNode(ISD::AND, N0.getDebugLoc(), VT, + N0.getOperand(0), + HiBitsMask); + if (c2 > c1) + return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, Mask, + DAG.getConstant(c2-c1, N1.getValueType())); + else + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, Mask, + DAG.getConstant(c1-c2, N1.getValueType())); + } + } + // fold (shl (sra x, c1), c1) -> (and x, (shl -1, c1)) + if (N1C && N0.getOpcode() == ISD::SRA && N1 == N0.getOperand(1)) { + SDValue HiBitsMask = + DAG.getConstant(APInt::getHighBitsSet(VT.getSizeInBits(), + VT.getSizeInBits() - + N1C->getZExtValue()), + VT); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0.getOperand(0), + HiBitsMask); + } + + if (N1C) { + SDValue NewSHL = visitShiftByConstant(N, N1C->getZExtValue()); + if (NewSHL.getNode()) + return NewSHL; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSRA(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); + + // fold (sra c1, c2) -> (sra c1, c2) + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SRA, VT, N0C, N1C); + // fold (sra 0, x) -> 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (sra -1, x) -> -1 + if (N0C && N0C->isAllOnesValue()) + return N0; + // fold (sra x, (setge c, size(x))) -> undef + if (N1C && N1C->getZExtValue() >= OpSizeInBits) + return DAG.getUNDEF(VT); + // fold (sra x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target supports + // sext_inreg. + if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) { + unsigned LowBits = OpSizeInBits - (unsigned)N1C->getZExtValue(); + EVT ExtVT = EVT::getIntegerVT(*DAG.getContext(), LowBits); + if (VT.isVector()) + ExtVT = EVT::getVectorVT(*DAG.getContext(), + ExtVT, VT.getVectorNumElements()); + if ((!LegalOperations || + TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, ExtVT))) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, + N0.getOperand(0), DAG.getValueType(ExtVT)); + } + + // fold (sra (sra x, c1), c2) -> (sra x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRA) { + if (ConstantSDNode *C1 = dyn_cast(N0.getOperand(1))) { + unsigned Sum = N1C->getZExtValue() + C1->getZExtValue(); + if (Sum >= OpSizeInBits) Sum = OpSizeInBits-1; + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(Sum, N1C->getValueType(0))); + } + } + + // fold (sra (shl X, m), (sub result_size, n)) + // -> (sign_extend (trunc (shl X, (sub (sub result_size, n), m)))) for + // result_size - n != m. + // If truncate is free for the target sext(shl) is likely to result in better + // code. + if (N0.getOpcode() == ISD::SHL) { + // Get the two constanst of the shifts, CN0 = m, CN = n. + const ConstantSDNode *N01C = dyn_cast(N0.getOperand(1)); + if (N01C && N1C) { + // Determine what the truncate's result bitsize and type would be. + EVT TruncVT = + EVT::getIntegerVT(*DAG.getContext(), + OpSizeInBits - N1C->getZExtValue()); + // Determine the residual right-shift amount. + signed ShiftAmt = N1C->getZExtValue() - N01C->getZExtValue(); + + // If the shift is not a no-op (in which case this should be just a sign + // extend already), the truncated to type is legal, sign_extend is legal + // on that type, and the truncate to that type is both legal and free, + // perform the transform. + if ((ShiftAmt > 0) && + TLI.isOperationLegalOrCustom(ISD::SIGN_EXTEND, TruncVT) && + TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) && + TLI.isTruncateFree(VT, TruncVT)) { + + SDValue Amt = DAG.getConstant(ShiftAmt, + getShiftAmountTy(N0.getOperand(0).getValueType())); + SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, + N0.getOperand(0), Amt); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT, + Shift); + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), + N->getValueType(0), Trunc); + } + } + } + + // fold (sra x, (trunc (and y, c))) -> (sra x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC = TruncC.trunc(TruncVT.getScalarType().getSizeInBits()); + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), + TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + // fold (sra (trunc (sr x, c1)), c2) -> (trunc (sra x, c1+c2)) + // if c1 is equal to the number of bits the trunc removes + if (N0.getOpcode() == ISD::TRUNCATE && + (N0.getOperand(0).getOpcode() == ISD::SRL || + N0.getOperand(0).getOpcode() == ISD::SRA) && + N0.getOperand(0).hasOneUse() && + N0.getOperand(0).getOperand(1).hasOneUse() && + N1C && isa(N0.getOperand(0).getOperand(1))) { + EVT LargeVT = N0.getOperand(0).getValueType(); + ConstantSDNode *LargeShiftAmt = + cast(N0.getOperand(0).getOperand(1)); + + if (LargeVT.getScalarType().getSizeInBits() - OpSizeInBits == + LargeShiftAmt->getZExtValue()) { + SDValue Amt = + DAG.getConstant(LargeShiftAmt->getZExtValue() + N1C->getZExtValue(), + getShiftAmountTy(N0.getOperand(0).getOperand(0).getValueType())); + SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), LargeVT, + N0.getOperand(0).getOperand(0), Amt); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, SRA); + } + } + + // Simplify, based on bits shifted out of the LHS. + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + + // If the sign bit is known to be zero, switch this to a SRL. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, N1); + + if (N1C) { + SDValue NewSRA = visitShiftByConstant(N, N1C->getZExtValue()); + if (NewSRA.getNode()) + return NewSRA; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSRL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); + + // fold (srl c1, c2) -> c1 >>u c2 + if (N0C && N1C) + return DAG.FoldConstantArithmetic(ISD::SRL, VT, N0C, N1C); + // fold (srl 0, x) -> 0 + if (N0C && N0C->isNullValue()) + return N0; + // fold (srl x, c >= size(x)) -> undef + if (N1C && N1C->getZExtValue() >= OpSizeInBits) + return DAG.getUNDEF(VT); + // fold (srl x, 0) -> x + if (N1C && N1C->isNullValue()) + return N0; + // if (srl x, c) is known to be zero, return 0 + if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), + APInt::getAllOnesValue(OpSizeInBits))) + return DAG.getConstant(0, VT); + + // fold (srl (srl x, c1), c2) -> 0 or (srl x, (add c1, c2)) + if (N1C && N0.getOpcode() == ISD::SRL && + N0.getOperand(1).getOpcode() == ISD::Constant) { + uint64_t c1 = cast(N0.getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + if (c1 + c2 >= OpSizeInBits) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(c1 + c2, N1.getValueType())); + } + + // fold (srl (trunc (srl x, c1)), c2) -> 0 or (trunc (srl x, (add c1, c2))) + if (N1C && N0.getOpcode() == ISD::TRUNCATE && + N0.getOperand(0).getOpcode() == ISD::SRL && + isa(N0.getOperand(0)->getOperand(1))) { + uint64_t c1 = + cast(N0.getOperand(0)->getOperand(1))->getZExtValue(); + uint64_t c2 = N1C->getZExtValue(); + EVT InnerShiftVT = N0.getOperand(0).getValueType(); + EVT ShiftCountVT = N0.getOperand(0)->getOperand(1).getValueType(); + uint64_t InnerShiftSize = InnerShiftVT.getScalarType().getSizeInBits(); + // This is only valid if the OpSizeInBits + c1 = size of inner shift. + if (c1 + OpSizeInBits == InnerShiftSize) { + if (c1 + c2 >= InnerShiftSize) + return DAG.getConstant(0, VT); + return DAG.getNode(ISD::TRUNCATE, N0->getDebugLoc(), VT, + DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT, + N0.getOperand(0)->getOperand(0), + DAG.getConstant(c1 + c2, ShiftCountVT))); + } + } + + // fold (srl (shl x, c), c) -> (and x, cst2) + if (N1C && N0.getOpcode() == ISD::SHL && N0.getOperand(1) == N1 && + N0.getValueSizeInBits() <= 64) { + uint64_t ShAmt = N1C->getZExtValue()+64-N0.getValueSizeInBits(); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getConstant(~0ULL >> ShAmt, VT)); + } + + + // fold (srl (anyextend x), c) -> (anyextend (srl x, c)) + if (N1C && N0.getOpcode() == ISD::ANY_EXTEND) { + // Shifting in all undef bits? + EVT SmallVT = N0.getOperand(0).getValueType(); + if (N1C->getZExtValue() >= SmallVT.getSizeInBits()) + return DAG.getUNDEF(VT); + + if (!LegalTypes || TLI.isTypeDesirableForOp(ISD::SRL, SmallVT)) { + SDValue SmallShift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), SmallVT, + N0.getOperand(0), N1); + AddToWorkList(SmallShift.getNode()); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, SmallShift); + } + } + + // fold (srl (sra X, Y), 31) -> (srl X, 31). This srl only looks at the sign + // bit, which is unmodified by sra. + if (N1C && N1C->getZExtValue() + 1 == VT.getSizeInBits()) { + if (N0.getOpcode() == ISD::SRA) + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0.getOperand(0), N1); + } + + // fold (srl (ctlz x), "5") -> x iff x has one bit set (the low bit). + if (N1C && N0.getOpcode() == ISD::CTLZ && + N1C->getAPIntValue() == Log2_32(VT.getSizeInBits())) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); + DAG.ComputeMaskedBits(N0.getOperand(0), Mask, KnownZero, KnownOne); + + // If any of the input bits are KnownOne, then the input couldn't be all + // zeros, thus the result of the srl will always be zero. + if (KnownOne.getBoolValue()) return DAG.getConstant(0, VT); + + // If all of the bits input the to ctlz node are known to be zero, then + // the result of the ctlz is "32" and the result of the shift is one. + APInt UnknownBits = ~KnownZero & Mask; + if (UnknownBits == 0) return DAG.getConstant(1, VT); + + // Otherwise, check to see if there is exactly one bit input to the ctlz. + if ((UnknownBits & (UnknownBits - 1)) == 0) { + // Okay, we know that only that the single bit specified by UnknownBits + // could be set on input to the CTLZ node. If this bit is set, the SRL + // will return 0, if it is clear, it returns 1. Change the CTLZ/SRL pair + // to an SRL/XOR pair, which is likely to simplify more. + unsigned ShAmt = UnknownBits.countTrailingZeros(); + SDValue Op = N0.getOperand(0); + + if (ShAmt) { + Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op, + DAG.getConstant(ShAmt, getShiftAmountTy(Op.getValueType()))); + AddToWorkList(Op.getNode()); + } + + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, + Op, DAG.getConstant(1, VT)); + } + } + + // fold (srl x, (trunc (and y, c))) -> (srl x, (and (trunc y), (trunc c))). + if (N1.getOpcode() == ISD::TRUNCATE && + N1.getOperand(0).getOpcode() == ISD::AND && + N1.hasOneUse() && N1.getOperand(0).hasOneUse()) { + SDValue N101 = N1.getOperand(0).getOperand(1); + if (ConstantSDNode *N101C = dyn_cast(N101)) { + EVT TruncVT = N1.getValueType(); + SDValue N100 = N1.getOperand(0).getOperand(0); + APInt TruncC = N101C->getAPIntValue(); + TruncC = TruncC.trunc(TruncVT.getSizeInBits()); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, + DAG.getNode(ISD::AND, N->getDebugLoc(), + TruncVT, + DAG.getNode(ISD::TRUNCATE, + N->getDebugLoc(), + TruncVT, N100), + DAG.getConstant(TruncC, TruncVT))); + } + } + + // fold operands of srl based on knowledge that the low bits are not + // demanded. + if (N1C && SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + if (N1C) { + SDValue NewSRL = visitShiftByConstant(N, N1C->getZExtValue()); + if (NewSRL.getNode()) + return NewSRL; + } + + // Attempt to convert a srl of a load into a narrower zero-extending load. + SDValue NarrowLoad = ReduceLoadWidth(N); + if (NarrowLoad.getNode()) + return NarrowLoad; + + // Here is a common situation. We want to optimize: + // + // %a = ... + // %b = and i32 %a, 2 + // %c = srl i32 %b, 1 + // brcond i32 %c ... + // + // into + // + // %a = ... + // %b = and %a, 2 + // %c = setcc eq %b, 0 + // brcond %c ... + // + // However when after the source operand of SRL is optimized into AND, the SRL + // itself may not be optimized further. Look for it and add the BRCOND into + // the worklist. + if (N->hasOneUse()) { + SDNode *Use = *N->use_begin(); + if (Use->getOpcode() == ISD::BRCOND) + AddToWorkList(Use); + else if (Use->getOpcode() == ISD::TRUNCATE && Use->hasOneUse()) { + // Also look pass the truncate. + Use = *Use->use_begin(); + if (Use->getOpcode() == ISD::BRCOND) + AddToWorkList(Use); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitCTLZ(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (ctlz c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTLZ, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitCTTZ(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (cttz c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTTZ, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitCTPOP(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (ctpop c1) -> c2 + if (isa(N0)) + return DAG.getNode(ISD::CTPOP, N->getDebugLoc(), VT, N0); + return SDValue(); +} + +SDValue DAGCombiner::visitSELECT(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + ConstantSDNode *N0C = dyn_cast(N0); + ConstantSDNode *N1C = dyn_cast(N1); + ConstantSDNode *N2C = dyn_cast(N2); + EVT VT = N->getValueType(0); + EVT VT0 = N0.getValueType(); + + // fold (select C, X, X) -> X + if (N1 == N2) + return N1; + // fold (select true, X, Y) -> X + if (N0C && !N0C->isNullValue()) + return N1; + // fold (select false, X, Y) -> Y + if (N0C && N0C->isNullValue()) + return N2; + // fold (select C, 1, X) -> (or C, X) + if (VT == MVT::i1 && N1C && N1C->getAPIntValue() == 1) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2); + // fold (select C, 0, 1) -> (xor C, 1) + if (VT.isInteger() && + (VT0 == MVT::i1 || + (VT0.isInteger() && + TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent)) && + N1C && N2C && N1C->isNullValue() && N2C->getAPIntValue() == 1) { + SDValue XORNode; + if (VT == VT0) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT0, + N0, DAG.getConstant(1, VT0)); + XORNode = DAG.getNode(ISD::XOR, N0.getDebugLoc(), VT0, + N0, DAG.getConstant(1, VT0)); + AddToWorkList(XORNode.getNode()); + if (VT.bitsGT(VT0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, XORNode); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, XORNode); + } + // fold (select C, 0, X) -> (and (not C), X) + if (VT == VT0 && VT == MVT::i1 && N1C && N1C->isNullValue()) { + SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT); + AddToWorkList(NOTNode.getNode()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, NOTNode, N2); + } + // fold (select C, X, 1) -> (or (not C), X) + if (VT == VT0 && VT == MVT::i1 && N2C && N2C->getAPIntValue() == 1) { + SDValue NOTNode = DAG.getNOT(N0.getDebugLoc(), N0, VT); + AddToWorkList(NOTNode.getNode()); + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, NOTNode, N1); + } + // fold (select C, X, 0) -> (and C, X) + if (VT == MVT::i1 && N2C && N2C->isNullValue()) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1); + // fold (select X, X, Y) -> (or X, Y) + // fold (select X, 1, Y) -> (or X, Y) + if (VT == MVT::i1 && (N0 == N1 || (N1C && N1C->getAPIntValue() == 1))) + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, N0, N2); + // fold (select X, Y, X) -> (and X, Y) + // fold (select X, Y, 0) -> (and X, Y) + if (VT == MVT::i1 && (N0 == N2 || (N2C && N2C->getAPIntValue() == 0))) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, N0, N1); + + // If we can fold this based on the true/false value, do so. + if (SimplifySelectOps(N, N1, N2)) + return SDValue(N, 0); // Don't revisit N. + + // fold selects based on a setcc into other things, such as min/max/abs + if (N0.getOpcode() == ISD::SETCC) { + // FIXME: + // Check against MVT::Other for SELECT_CC, which is a workaround for targets + // having to say they don't support SELECT_CC on every type the DAG knows + // about, since there is no way to mark an opcode illegal at all value types + if (TLI.isOperationLegalOrCustom(ISD::SELECT_CC, MVT::Other) && + TLI.isOperationLegalOrCustom(ISD::SELECT_CC, VT)) + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1), + N1, N2, N0.getOperand(2)); + return SimplifySelect(N->getDebugLoc(), N0, N1, N2); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSELECT_CC(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + SDValue N3 = N->getOperand(3); + SDValue N4 = N->getOperand(4); + ISD::CondCode CC = cast(N4)->get(); + + // fold select_cc lhs, rhs, x, x, cc -> x + if (N2 == N3) + return N2; + + // Determine if the condition we're dealing with is constant + SDValue SCC = SimplifySetCC(TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC, N->getDebugLoc(), false); + if (SCC.getNode()) AddToWorkList(SCC.getNode()); + + if (ConstantSDNode *SCCC = dyn_cast_or_null(SCC.getNode())) { + if (!SCCC->isNullValue()) + return N2; // cond always true -> true val + else + return N3; // cond always false -> false val + } + + // Fold to a simpler select_cc + if (SCC.getNode() && SCC.getOpcode() == ISD::SETCC) + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), N2.getValueType(), + SCC.getOperand(0), SCC.getOperand(1), N2, N3, + SCC.getOperand(2)); + + // If we can fold this based on the true/false value, do so. + if (SimplifySelectOps(N, N2, N3)) + return SDValue(N, 0); // Don't revisit N. + + // fold select_cc into other things, such as min/max/abs + return SimplifySelectCC(N->getDebugLoc(), N0, N1, N2, N3, CC); +} + +SDValue DAGCombiner::visitSETCC(SDNode *N) { + return SimplifySetCC(N->getValueType(0), N->getOperand(0), N->getOperand(1), + cast(N->getOperand(2))->get(), + N->getDebugLoc()); +} + +// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this: +// "fold ({s|z|a}ext (load x)) -> ({s|z|a}ext (truncate ({s|z|a}extload x)))" +// transformation. Returns true if extension are possible and the above +// mentioned transformation is profitable. +static bool ExtendUsesToFormExtLoad(SDNode *N, SDValue N0, + unsigned ExtOpc, + SmallVector &ExtendNodes, + const TargetLowering &TLI) { + bool HasCopyToRegUses = false; + bool isTruncFree = TLI.isTruncateFree(N->getValueType(0), N0.getValueType()); + for (SDNode::use_iterator UI = N0.getNode()->use_begin(), + UE = N0.getNode()->use_end(); + UI != UE; ++UI) { + SDNode *User = *UI; + if (User == N) + continue; + if (UI.getUse().getResNo() != N0.getResNo()) + continue; + // FIXME: Only extend SETCC N, N and SETCC N, c for now. + if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) { + ISD::CondCode CC = cast(User->getOperand(2))->get(); + if (ExtOpc == ISD::ZERO_EXTEND && ISD::isSignedIntSetCC(CC)) + // Sign bits will be lost after a zext. + return false; + bool Add = false; + for (unsigned i = 0; i != 2; ++i) { + SDValue UseOp = User->getOperand(i); + if (UseOp == N0) + continue; + if (!isa(UseOp)) + return false; + Add = true; + } + if (Add) + ExtendNodes.push_back(User); + continue; + } + // If truncates aren't free and there are users we can't + // extend, it isn't worthwhile. + if (!isTruncFree) + return false; + // Remember if this value is live-out. + if (User->getOpcode() == ISD::CopyToReg) + HasCopyToRegUses = true; + } + + if (HasCopyToRegUses) { + bool BothLiveOut = false; + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) { + BothLiveOut = true; + break; + } + } + if (BothLiveOut) + // Both unextended and extended values are live out. There had better be + // a good reason for the transformation. + return ExtendNodes.size(); + } + return true; +} + +SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (sext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N0); + + // fold (sext (sext x)) -> (sext x) + // fold (sext (aext x)) -> (sext x) + if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, + N0.getOperand(0)); + + if (N0.getOpcode() == ISD::TRUNCATE) { + // fold (sext (truncate (load x))) -> (sext (smaller load x)) + // fold (sext (truncate (srl (load x), c))) -> (sext (smaller load (x+c/n))) + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + SDNode* oye = N0.getNode()->getOperand(0).getNode(); + if (NarrowLoad.getNode() != N0.getNode()) { + CombineTo(N0.getNode(), NarrowLoad); + // CombineTo deleted the truncate, if needed, but not what's under it. + AddToWorkList(oye); + } + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + // See if the value being truncated is already sign extended. If so, just + // eliminate the trunc/sext pair. + SDValue Op = N0.getOperand(0); + unsigned OpBits = Op.getValueType().getScalarType().getSizeInBits(); + unsigned MidBits = N0.getValueType().getScalarType().getSizeInBits(); + unsigned DestBits = VT.getScalarType().getSizeInBits(); + unsigned NumSignBits = DAG.ComputeNumSignBits(Op); + + if (OpBits == DestBits) { + // Op is i32, Mid is i8, and Dest is i32. If Op has more than 24 sign + // bits, it is already ready. + if (NumSignBits > DestBits-MidBits) + return Op; + } else if (OpBits < DestBits) { + // Op is i32, Mid is i8, and Dest is i64. If Op has more than 24 sign + // bits, just sext from i32. + if (NumSignBits > OpBits-MidBits) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, Op); + } else { + // Op is i64, Mid is i8, and Dest is i32. If Op has more than 56 sign + // bits, just truncate to i32. + if (NumSignBits > OpBits-MidBits) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); + } + + // fold (sext (truncate x)) -> (sextinreg x). + if (!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, + N0.getValueType())) { + if (OpBits < DestBits) + Op = DAG.getNode(ISD::ANY_EXTEND, N0.getDebugLoc(), VT, Op); + else if (OpBits > DestBits) + Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, Op, + DAG.getValueType(N0.getValueType())); + } + } + + // fold (sext (load x)) -> (sext (truncate (sextload x))) + // None of the supported targets knows how to perform load and sign extend + // on vectors in one instruction. We only perform this transformation on + // scalars. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::SIGN_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + N0.getValueType(), + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::SIGN_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (sext (sextload x)) -> (sext (truncate (sextload x))) + // fold (sext ( extload x)) -> (sext (truncate (sextload x))) + if ((ISD::isSEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && + ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + if ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, MemVT)) { + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + MemVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + if (N0.getOpcode() == ISD::SETCC) { + // sext(setcc) -> sext_in_reg(vsetcc) for vectors. + // Only do this before legalize for now. + if (VT.isVector() && !LegalOperations) { + EVT N0VT = N0.getOperand(0).getValueType(); + // We know that the # elements of the results is the same as the + // # elements of the compare (and the # elements of the compare result + // for that matter). Check to see that they are the same size. If so, + // we know that the element size of the sext'd result matches the + // element size of the compare operands. + if (VT.getSizeInBits() == N0VT.getSizeInBits()) + return DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + // If the desired elements are smaller or larger than the source + // elements we can use a matching integer vector type and then + // truncate/sign extend + else { + EVT MatchingElementType = + EVT::getIntegerVT(*DAG.getContext(), + N0VT.getScalarType().getSizeInBits()); + EVT MatchingVectorType = + EVT::getVectorVT(*DAG.getContext(), MatchingElementType, + N0VT.getVectorNumElements()); + SDValue VsetCC = + DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + return DAG.getSExtOrTrunc(VsetCC, N->getDebugLoc(), VT); + } + } + + // sext(setcc x, y, cc) -> (select_cc x, y, -1, 0, cc) + unsigned ElementWidth = VT.getScalarType().getSizeInBits(); + SDValue NegOne = + DAG.getConstant(APInt::getAllOnesValue(ElementWidth), VT); + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + NegOne, DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) return SCC; + if (!LegalOperations || + TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultType(VT))) + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, + DAG.getSetCC(N->getDebugLoc(), + TLI.getSetCCResultType(VT), + N0.getOperand(0), N0.getOperand(1), + cast(N0.getOperand(2))->get()), + NegOne, DAG.getConstant(0, VT)); + } + + // fold (sext x) -> (zext x) if the sign bit is known zero. + if ((!LegalOperations || TLI.isOperationLegal(ISD::ZERO_EXTEND, VT)) && + DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (zext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, N0); + // fold (zext (zext x)) -> (zext x) + // fold (zext (aext x)) -> (zext x) + if (N0.getOpcode() == ISD::ZERO_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, + N0.getOperand(0)); + + // fold (zext (truncate (load x))) -> (zext (smaller load x)) + // fold (zext (truncate (srl (load x), c))) -> (zext (small load (x+c/n))) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + SDNode* oye = N0.getNode()->getOperand(0).getNode(); + if (NarrowLoad.getNode() != N0.getNode()) { + CombineTo(N0.getNode(), NarrowLoad); + // CombineTo deleted the truncate, if needed, but not what's under it. + AddToWorkList(oye); + } + return DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + } + } + + // fold (zext (truncate x)) -> (and x, mask) + if (N0.getOpcode() == ISD::TRUNCATE && + (!LegalOperations || TLI.isOperationLegal(ISD::AND, VT))) { + + // fold (zext (truncate (load x))) -> (zext (smaller load x)) + // fold (zext (truncate (srl (load x), c))) -> (zext (smaller load (x+c/n))) + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + SDNode* oye = N0.getNode()->getOperand(0).getNode(); + if (NarrowLoad.getNode() != N0.getNode()) { + CombineTo(N0.getNode(), NarrowLoad); + // CombineTo deleted the truncate, if needed, but not what's under it. + AddToWorkList(oye); + } + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + SDValue Op = N0.getOperand(0); + if (Op.getValueType().bitsLT(VT)) { + Op = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, Op); + } else if (Op.getValueType().bitsGT(VT)) { + Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); + } + return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), + N0.getValueType().getScalarType()); + } + + // Fold (zext (and (trunc x), cst)) -> (and x, cst), + // if either of the casts is not free. + if (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant && + (!TLI.isTruncateFree(N0.getOperand(0).getOperand(0).getValueType(), + N0.getValueType()) || + !TLI.isZExtFree(N0.getValueType(), VT))) { + SDValue X = N0.getOperand(0).getOperand(0); + if (X.getValueType().bitsLT(VT)) { + X = DAG.getNode(ISD::ANY_EXTEND, X.getDebugLoc(), VT, X); + } else if (X.getValueType().bitsGT(VT)) { + X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X); + } + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + Mask = Mask.zext(VT.getSizeInBits()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + X, DAG.getConstant(Mask, VT)); + } + + // fold (zext (load x)) -> (zext (truncate (zextload x))) + // None of the supported targets knows how to perform load and vector_zext + // on vectors in one instruction. We only perform this transformation on + // scalars. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ZERO_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + N0.getValueType(), + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::ZERO_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (zext (zextload x)) -> (zext (truncate (zextload x))) + // fold (zext ( extload x)) -> (zext (truncate (zextload x))) + if ((ISD::isZEXTLoad(N0.getNode()) || ISD::isEXTLoad(N0.getNode())) && + ISD::isUNINDEXEDLoad(N0.getNode()) && N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + if ((!LegalOperations && !LN0->isVolatile()) || + TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT)) { + SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + MemVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), + ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + if (N0.getOpcode() == ISD::SETCC) { + if (!LegalOperations && VT.isVector()) { + // zext(setcc) -> (and (vsetcc), (1, 1, ...) for vectors. + // Only do this before legalize for now. + EVT N0VT = N0.getOperand(0).getValueType(); + EVT EltVT = VT.getVectorElementType(); + SmallVector OneOps(VT.getVectorNumElements(), + DAG.getConstant(1, EltVT)); + if (VT.getSizeInBits() == N0VT.getSizeInBits()) { + // We know that the # elements of the results is the same as the + // # elements of the compare (and the # elements of the compare result + // for that matter). Check to see that they are the same size. If so, + // we know that the element size of the sext'd result matches the + // element size of the compare operands. + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()), + DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, + &OneOps[0], OneOps.size())); + } else { + // If the desired elements are smaller or larger than the source + // elements we can use a matching integer vector type and then + // truncate/sign extend + EVT MatchingElementType = + EVT::getIntegerVT(*DAG.getContext(), + N0VT.getScalarType().getSizeInBits()); + EVT MatchingVectorType = + EVT::getVectorVT(*DAG.getContext(), MatchingElementType, + N0VT.getVectorNumElements()); + SDValue VsetCC = + DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getSExtOrTrunc(VsetCC, N->getDebugLoc(), VT), + DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), VT, + &OneOps[0], OneOps.size())); + } + } + + // zext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + DAG.getConstant(1, VT), DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) return SCC; + } + + // (zext (shl (zext x), cst)) -> (shl (zext x), cst) + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && + isa(N0.getOperand(1)) && + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && + N0.hasOneUse()) { + SDValue ShAmt = N0.getOperand(1); + unsigned ShAmtVal = cast(ShAmt)->getZExtValue(); + if (N0.getOpcode() == ISD::SHL) { + SDValue InnerZExt = N0.getOperand(0); + // If the original shl may be shifting out bits, do not perform this + // transformation. + unsigned KnownZeroBits = InnerZExt.getValueType().getSizeInBits() - + InnerZExt.getOperand(0).getValueType().getSizeInBits(); + if (ShAmtVal > KnownZeroBits) + return SDValue(); + } + + DebugLoc DL = N->getDebugLoc(); + + // Ensure that the shift amount is wide enough for the shifted value. + if (VT.getSizeInBits() >= 256) + ShAmt = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, ShAmt); + + return DAG.getNode(N0.getOpcode(), DL, VT, + DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)), + ShAmt); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // fold (aext c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, N0); + // fold (aext (aext x)) -> (aext x) + // fold (aext (zext x)) -> (zext x) + // fold (aext (sext x)) -> (sext x) + if (N0.getOpcode() == ISD::ANY_EXTEND || + N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, N0.getOperand(0)); + + // fold (aext (truncate (load x))) -> (aext (smaller load x)) + // fold (aext (truncate (srl (load x), c))) -> (aext (small load (x+c/n))) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue NarrowLoad = ReduceLoadWidth(N0.getNode()); + if (NarrowLoad.getNode()) { + SDNode* oye = N0.getNode()->getOperand(0).getNode(); + if (NarrowLoad.getNode() != N0.getNode()) { + CombineTo(N0.getNode(), NarrowLoad); + // CombineTo deleted the truncate, if needed, but not what's under it. + AddToWorkList(oye); + } + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, NarrowLoad); + } + } + + // fold (aext (truncate x)) + if (N0.getOpcode() == ISD::TRUNCATE) { + SDValue TruncOp = N0.getOperand(0); + if (TruncOp.getValueType() == VT) + return TruncOp; // x iff x size == zext size. + if (TruncOp.getValueType().bitsGT(VT)) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, TruncOp); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, TruncOp); + } + + // Fold (aext (and (trunc x), cst)) -> (and x, cst) + // if the trunc is not free. + if (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant && + !TLI.isTruncateFree(N0.getOperand(0).getOperand(0).getValueType(), + N0.getValueType())) { + SDValue X = N0.getOperand(0).getOperand(0); + if (X.getValueType().bitsLT(VT)) { + X = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, X); + } else if (X.getValueType().bitsGT(VT)) { + X = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, X); + } + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + Mask = Mask.zext(VT.getSizeInBits()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + X, DAG.getConstant(Mask, VT)); + } + + // fold (aext (load x)) -> (aext (truncate (extload x))) + // None of the supported targets knows how to perform load and any_ext + // on vectors in one instruction. We only perform this transformation on + // scalars. + if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { + bool DoXform = true; + SmallVector SetCCs; + if (!N0.hasOneUse()) + DoXform = ExtendUsesToFormExtLoad(N, N0, ISD::ANY_EXTEND, SetCCs, TLI); + if (DoXform) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + N0.getValueType(), + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad); + CombineTo(N0.getNode(), Trunc, ExtLoad.getValue(1)); + + // Extend SetCC uses if necessary. + for (unsigned i = 0, e = SetCCs.size(); i != e; ++i) { + SDNode *SetCC = SetCCs[i]; + SmallVector Ops; + + for (unsigned j = 0; j != 2; ++j) { + SDValue SOp = SetCC->getOperand(j); + if (SOp == Trunc) + Ops.push_back(ExtLoad); + else + Ops.push_back(DAG.getNode(ISD::ANY_EXTEND, + N->getDebugLoc(), VT, SOp)); + } + + Ops.push_back(SetCC->getOperand(2)); + CombineTo(SetCC, DAG.getNode(ISD::SETCC, N->getDebugLoc(), + SetCC->getValueType(0), + &Ops[0], Ops.size())); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + + // fold (aext (zextload x)) -> (aext (truncate (zextload x))) + // fold (aext (sextload x)) -> (aext (truncate (sextload x))) + // fold (aext ( extload x)) -> (aext (truncate (extload x))) + if (N0.getOpcode() == ISD::LOAD && + !ISD::isNON_EXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse()) { + LoadSDNode *LN0 = cast(N0); + EVT MemVT = LN0->getMemoryVT(); + SDValue ExtLoad = DAG.getExtLoad(LN0->getExtensionType(), N->getDebugLoc(), + VT, LN0->getChain(), LN0->getBasePtr(), + LN0->getPointerInfo(), MemVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), + N0.getValueType(), ExtLoad), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + if (N0.getOpcode() == ISD::SETCC) { + // aext(setcc) -> sext_in_reg(vsetcc) for vectors. + // Only do this before legalize for now. + if (VT.isVector() && !LegalOperations) { + EVT N0VT = N0.getOperand(0).getValueType(); + // We know that the # elements of the results is the same as the + // # elements of the compare (and the # elements of the compare result + // for that matter). Check to see that they are the same size. If so, + // we know that the element size of the sext'd result matches the + // element size of the compare operands. + if (VT.getSizeInBits() == N0VT.getSizeInBits()) + return DAG.getVSetCC(N->getDebugLoc(), VT, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + // If the desired elements are smaller or larger than the source + // elements we can use a matching integer vector type and then + // truncate/sign extend + else { + EVT MatchingElementType = + EVT::getIntegerVT(*DAG.getContext(), + N0VT.getScalarType().getSizeInBits()); + EVT MatchingVectorType = + EVT::getVectorVT(*DAG.getContext(), MatchingElementType, + N0VT.getVectorNumElements()); + SDValue VsetCC = + DAG.getVSetCC(N->getDebugLoc(), MatchingVectorType, N0.getOperand(0), + N0.getOperand(1), + cast(N0.getOperand(2))->get()); + return DAG.getSExtOrTrunc(VsetCC, N->getDebugLoc(), VT); + } + } + + // aext(setcc x,y,cc) -> select_cc x, y, 1, 0, cc + SDValue SCC = + SimplifySelectCC(N->getDebugLoc(), N0.getOperand(0), N0.getOperand(1), + DAG.getConstant(1, VT), DAG.getConstant(0, VT), + cast(N0.getOperand(2))->get(), true); + if (SCC.getNode()) + return SCC; + } + + return SDValue(); +} + +/// GetDemandedBits - See if the specified operand can be simplified with the +/// knowledge that only the bits specified by Mask are used. If so, return the +/// simpler operand, otherwise return a null SDValue. +SDValue DAGCombiner::GetDemandedBits(SDValue V, const APInt &Mask) { + switch (V.getOpcode()) { + default: break; + case ISD::OR: + case ISD::XOR: + // If the LHS or RHS don't contribute bits to the or, drop them. + if (DAG.MaskedValueIsZero(V.getOperand(0), Mask)) + return V.getOperand(1); + if (DAG.MaskedValueIsZero(V.getOperand(1), Mask)) + return V.getOperand(0); + break; + case ISD::SRL: + // Only look at single-use SRLs. + if (!V.getNode()->hasOneUse()) + break; + if (ConstantSDNode *RHSC = dyn_cast(V.getOperand(1))) { + // See if we can recursively simplify the LHS. + unsigned Amt = RHSC->getZExtValue(); + + // Watch out for shift count overflow though. + if (Amt >= Mask.getBitWidth()) break; + APInt NewMask = Mask << Amt; + SDValue SimplifyLHS = GetDemandedBits(V.getOperand(0), NewMask); + if (SimplifyLHS.getNode()) + return DAG.getNode(ISD::SRL, V.getDebugLoc(), V.getValueType(), + SimplifyLHS, V.getOperand(1)); + } + } + return SDValue(); +} + +/// ReduceLoadWidth - If the result of a wider load is shifted to right of N +/// bits and then truncated to a narrower type and where N is a multiple +/// of number of bits of the narrower type, transform it to a narrower load +/// from address + N / num of bits of new type. If the result is to be +/// extended, also fold the extension to form a extending load. +SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { + unsigned Opc = N->getOpcode(); + + ISD::LoadExtType ExtType = ISD::NON_EXTLOAD; + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + EVT ExtVT = VT; + + // This transformation isn't valid for vector loads. + if (VT.isVector()) + return SDValue(); + + // Special case: SIGN_EXTEND_INREG is basically truncating to ExtVT then + // extended to VT. + if (Opc == ISD::SIGN_EXTEND_INREG) { + ExtType = ISD::SEXTLOAD; + ExtVT = cast(N->getOperand(1))->getVT(); + } else if (Opc == ISD::SRL) { + // Another special-case: SRL is basically zero-extending a narrower value. + ExtType = ISD::ZEXTLOAD; + N0 = SDValue(N, 0); + ConstantSDNode *N01 = dyn_cast(N0.getOperand(1)); + if (!N01) return SDValue(); + ExtVT = EVT::getIntegerVT(*DAG.getContext(), + VT.getSizeInBits() - N01->getZExtValue()); + } + if (LegalOperations && !TLI.isLoadExtLegal(ExtType, ExtVT)) + return SDValue(); + + unsigned EVTBits = ExtVT.getSizeInBits(); + + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (!ExtVT.isRound()) + return SDValue(); + + unsigned ShAmt = 0; + if (N0.getOpcode() == ISD::SRL && N0.hasOneUse()) { + if (ConstantSDNode *N01 = dyn_cast(N0.getOperand(1))) { + ShAmt = N01->getZExtValue(); + // Is the shift amount a multiple of size of VT? + if ((ShAmt & (EVTBits-1)) == 0) { + N0 = N0.getOperand(0); + // Is the load width a multiple of size of VT? + if ((N0.getValueType().getSizeInBits() & (EVTBits-1)) != 0) + return SDValue(); + } + + // At this point, we must have a load or else we can't do the transform. + if (!isa(N0)) return SDValue(); + + // If the shift amount is larger than the input type then we're not + // accessing any of the loaded bytes. If the load was a zextload/extload + // then the result of the shift+trunc is zero/undef (handled elsewhere). + // If the load was a sextload then the result is a splat of the sign bit + // of the extended byte. This is not worth optimizing for. + if (ShAmt >= cast(N0)->getMemoryVT().getSizeInBits()) + return SDValue(); + } + } + + // If the load is shifted left (and the result isn't shifted back right), + // we can fold the truncate through the shift. + unsigned ShLeftAmt = 0; + if (ShAmt == 0 && N0.getOpcode() == ISD::SHL && N0.hasOneUse() && + ExtVT == VT && TLI.isNarrowingProfitable(N0.getValueType(), VT)) { + if (ConstantSDNode *N01 = dyn_cast(N0.getOperand(1))) { + ShLeftAmt = N01->getZExtValue(); + N0 = N0.getOperand(0); + } + } + + // If we haven't found a load, we can't narrow it. Don't transform one with + // multiple uses, this would require adding a new load. + if (!isa(N0) || !N0.hasOneUse() || + // Don't change the width of a volatile load. + cast(N0)->isVolatile()) + return SDValue(); + + // Verify that we are actually reducing a load width here. + if (cast(N0)->getMemoryVT().getSizeInBits() < EVTBits) + return SDValue(); + + LoadSDNode *LN0 = cast(N0); + EVT PtrType = N0.getOperand(1).getValueType(); + + // For big endian targets, we need to adjust the offset to the pointer to + // load the correct bytes. + if (TLI.isBigEndian()) { + unsigned LVTStoreBits = LN0->getMemoryVT().getStoreSizeInBits(); + unsigned EVTStoreBits = ExtVT.getStoreSizeInBits(); + ShAmt = LVTStoreBits - EVTStoreBits - ShAmt; + } + + uint64_t PtrOff = ShAmt / 8; + unsigned NewAlign = MinAlign(LN0->getAlignment(), PtrOff); + SDValue NewPtr = DAG.getNode(ISD::ADD, LN0->getDebugLoc(), + PtrType, LN0->getBasePtr(), + DAG.getConstant(PtrOff, PtrType)); + AddToWorkList(NewPtr.getNode()); + + SDValue Load; + if (ExtType == ISD::NON_EXTLOAD) + Load = DAG.getLoad(VT, N0.getDebugLoc(), LN0->getChain(), NewPtr, + LN0->getPointerInfo().getWithOffset(PtrOff), + LN0->isVolatile(), LN0->isNonTemporal(), NewAlign); + else + Load = DAG.getExtLoad(ExtType, N0.getDebugLoc(), VT, LN0->getChain(),NewPtr, + LN0->getPointerInfo().getWithOffset(PtrOff), + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + NewAlign); + + // Replace the old load's chain with the new load's chain. + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1), + &DeadNodes); + + // Shift the result left, if we've swallowed a left shift. + SDValue Result = Load; + if (ShLeftAmt != 0) { + EVT ShImmTy = getShiftAmountTy(Result.getValueType()); + if (!isUIntN(ShImmTy.getSizeInBits(), ShLeftAmt)) + ShImmTy = VT; + Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, + Result, DAG.getConstant(ShLeftAmt, ShImmTy)); + } + + // Return the new loaded value. + return Result; +} + +SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + EVT VT = N->getValueType(0); + EVT EVT = cast(N1)->getVT(); + unsigned VTBits = VT.getScalarType().getSizeInBits(); + unsigned EVTBits = EVT.getScalarType().getSizeInBits(); + + // fold (sext_in_reg c1) -> c1 + if (isa(N0) || N0.getOpcode() == ISD::UNDEF) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, N0, N1); + + // If the input is already sign extended, just drop the extension. + if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1) + return N0; + + // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, minVT) pt2 + if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && + EVT.bitsLT(cast(N0.getOperand(1))->getVT())) { + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, + N0.getOperand(0), N1); + } + + // fold (sext_in_reg (sext x)) -> (sext x) + // fold (sext_in_reg (aext x)) -> (sext x) + // if x is small enough. + if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == ISD::ANY_EXTEND) { + SDValue N00 = N0.getOperand(0); + if (N00.getValueType().getScalarType().getSizeInBits() <= EVTBits && + (!LegalOperations || TLI.isOperationLegal(ISD::SIGN_EXTEND, VT))) + return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, N1); + } + + // fold (sext_in_reg x) -> (zext_in_reg x) if the sign bit is known zero. + if (DAG.MaskedValueIsZero(N0, APInt::getBitsSet(VTBits, EVTBits-1, EVTBits))) + return DAG.getZeroExtendInReg(N0, N->getDebugLoc(), EVT); + + // fold operands of sext_in_reg based on knowledge that the top bits are not + // demanded. + if (SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + // fold (sext_in_reg (load x)) -> (smaller sextload x) + // fold (sext_in_reg (srl (load x), c)) -> (smaller sextload (x+c/evtbits)) + SDValue NarrowLoad = ReduceLoadWidth(N); + if (NarrowLoad.getNode()) + return NarrowLoad; + + // fold (sext_in_reg (srl X, 24), i8) -> (sra X, 24) + // fold (sext_in_reg (srl X, 23), i8) -> (sra X, 23) iff possible. + // We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" above. + if (N0.getOpcode() == ISD::SRL) { + if (ConstantSDNode *ShAmt = dyn_cast(N0.getOperand(1))) + if (ShAmt->getZExtValue()+EVTBits <= VTBits) { + // We can turn this into an SRA iff the input to the SRL is already sign + // extended enough. + unsigned InSignBits = DAG.ComputeNumSignBits(N0.getOperand(0)); + if (VTBits-(ShAmt->getZExtValue()+EVTBits) < InSignBits) + return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, + N0.getOperand(0), N0.getOperand(1)); + } + } + + // fold (sext_inreg (extload x)) -> (sextload x) + if (ISD::isEXTLoad(N0.getNode()) && + ISD::isUNINDEXEDLoad(N0.getNode()) && + EVT == cast(N0)->getMemoryVT() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + EVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + // fold (sext_inreg (zextload x)) -> (sextload x) iff load has one use + if (ISD::isZEXTLoad(N0.getNode()) && ISD::isUNINDEXEDLoad(N0.getNode()) && + N0.hasOneUse() && + EVT == cast(N0)->getMemoryVT() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::SEXTLOAD, EVT))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::SEXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + EVT, + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + return SDValue(); +} + +SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // noop truncate + if (N0.getValueType() == N->getValueType(0)) + return N0; + // fold (truncate c1) -> c1 + if (isa(N0)) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0); + // fold (truncate (truncate x)) -> (truncate x) + if (N0.getOpcode() == ISD::TRUNCATE) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0)); + // fold (truncate (ext x)) -> (ext x) or (truncate x) or x + if (N0.getOpcode() == ISD::ZERO_EXTEND || + N0.getOpcode() == ISD::SIGN_EXTEND || + N0.getOpcode() == ISD::ANY_EXTEND) { + if (N0.getOperand(0).getValueType().bitsLT(VT)) + // if the source is smaller than the dest, we still need an extend + return DAG.getNode(N0.getOpcode(), N->getDebugLoc(), VT, + N0.getOperand(0)); + else if (N0.getOperand(0).getValueType().bitsGT(VT)) + // if the source is larger than the dest, than we just need the truncate + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, N0.getOperand(0)); + else + // if the source and dest are the same type, we can drop both the extend + // and the truncate. + return N0.getOperand(0); + } + + // See if we can simplify the input to this truncate through knowledge that + // only the low bits are being used. + // For example "trunc (or (shl x, 8), y)" // -> trunc y + // Currently we only perform this optimization on scalars because vectors + // may have different active low bits. + if (!VT.isVector()) { + SDValue Shorter = + GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(), + VT.getSizeInBits())); + if (Shorter.getNode()) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter); + } + // fold (truncate (load x)) -> (smaller load x) + // fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits)) + if (!LegalTypes || TLI.isTypeDesirableForOp(N0.getOpcode(), VT)) { + SDValue Reduced = ReduceLoadWidth(N); + if (Reduced.getNode()) + return Reduced; + } + + // Simplify the operands using demanded-bits information. + if (!VT.isVector() && + SimplifyDemandedBits(SDValue(N, 0))) + return SDValue(N, 0); + + return SDValue(); +} + +static SDNode *getBuildPairElt(SDNode *N, unsigned i) { + SDValue Elt = N->getOperand(i); + if (Elt.getOpcode() != ISD::MERGE_VALUES) + return Elt.getNode(); + return Elt.getOperand(Elt.getResNo()).getNode(); +} + +/// CombineConsecutiveLoads - build_pair (load, load) -> load +/// if load locations are consecutive. +SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, EVT VT) { + assert(N->getOpcode() == ISD::BUILD_PAIR); + + LoadSDNode *LD1 = dyn_cast(getBuildPairElt(N, 0)); + LoadSDNode *LD2 = dyn_cast(getBuildPairElt(N, 1)); + if (!LD1 || !LD2 || !ISD::isNON_EXTLoad(LD1) || !LD1->hasOneUse() || + LD1->getPointerInfo().getAddrSpace() != + LD2->getPointerInfo().getAddrSpace()) + return SDValue(); + EVT LD1VT = LD1->getValueType(0); + + if (ISD::isNON_EXTLoad(LD2) && + LD2->hasOneUse() && + // If both are volatile this would reduce the number of volatile loads. + // If one is volatile it might be ok, but play conservative and bail out. + !LD1->isVolatile() && + !LD2->isVolatile() && + DAG.isConsecutiveLoad(LD2, LD1, LD1VT.getSizeInBits()/8, 1)) { + unsigned Align = LD1->getAlignment(); + unsigned NewAlign = TLI.getTargetData()-> + getABITypeAlignment(VT.getTypeForEVT(*DAG.getContext())); + + if (NewAlign <= Align && + (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) + return DAG.getLoad(VT, N->getDebugLoc(), LD1->getChain(), + LD1->getBasePtr(), LD1->getPointerInfo(), + false, false, Align); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBITCAST(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // If the input is a BUILD_VECTOR with all constant elements, fold this now. + // Only do this before legalize, since afterward the target may be depending + // on the bitconvert. + // First check to see if this is all constant. + if (!LegalTypes && + N0.getOpcode() == ISD::BUILD_VECTOR && N0.getNode()->hasOneUse() && + VT.isVector()) { + bool isSimple = true; + for (unsigned i = 0, e = N0.getNumOperands(); i != e; ++i) + if (N0.getOperand(i).getOpcode() != ISD::UNDEF && + N0.getOperand(i).getOpcode() != ISD::Constant && + N0.getOperand(i).getOpcode() != ISD::ConstantFP) { + isSimple = false; + break; + } + + EVT DestEltVT = N->getValueType(0).getVectorElementType(); + assert(!DestEltVT.isVector() && + "Element type of vector ValueType must not be vector!"); + if (isSimple) + return ConstantFoldBITCASTofBUILD_VECTOR(N0.getNode(), DestEltVT); + } + + // If the input is a constant, let getNode fold it. + if (isa(N0) || isa(N0)) { + SDValue Res = DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, N0); + if (Res.getNode() != N) { + if (!LegalOperations || + TLI.isOperationLegal(Res.getNode()->getOpcode(), VT)) + return Res; + + // Folding it resulted in an illegal node, and it's too late to + // do that. Clean up the old node and forego the transformation. + // Ideally this won't happen very often, because instcombine + // and the earlier dagcombine runs (where illegal nodes are + // permitted) should have folded most of them already. + DAG.DeleteNode(Res.getNode()); + } + } + + // (conv (conv x, t1), t2) -> (conv x, t2) + if (N0.getOpcode() == ISD::BITCAST) + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, + N0.getOperand(0)); + + // fold (conv (load x)) -> (load (conv*)x) + // If the resultant load doesn't need a higher alignment than the original! + if (ISD::isNormalLoad(N0.getNode()) && N0.hasOneUse() && + // Do not change the width of a volatile load. + !cast(N0)->isVolatile() && + (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) { + LoadSDNode *LN0 = cast(N0); + unsigned Align = TLI.getTargetData()-> + getABITypeAlignment(VT.getTypeForEVT(*DAG.getContext())); + unsigned OrigAlign = LN0->getAlignment(); + + if (Align <= OrigAlign) { + SDValue Load = DAG.getLoad(VT, N->getDebugLoc(), LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + LN0->isVolatile(), LN0->isNonTemporal(), + OrigAlign); + AddToWorkList(N); + CombineTo(N0.getNode(), + DAG.getNode(ISD::BITCAST, N0.getDebugLoc(), + N0.getValueType(), Load), + Load.getValue(1)); + return Load; + } + } + + // fold (bitconvert (fneg x)) -> (xor (bitconvert x), signbit) + // fold (bitconvert (fabs x)) -> (and (bitconvert x), (not signbit)) + // This often reduces constant pool loads. + if ((N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FABS) && + N0.getNode()->hasOneUse() && VT.isInteger() && !VT.isVector()) { + SDValue NewConv = DAG.getNode(ISD::BITCAST, N0.getDebugLoc(), VT, + N0.getOperand(0)); + AddToWorkList(NewConv.getNode()); + + APInt SignBit = APInt::getSignBit(VT.getSizeInBits()); + if (N0.getOpcode() == ISD::FNEG) + return DAG.getNode(ISD::XOR, N->getDebugLoc(), VT, + NewConv, DAG.getConstant(SignBit, VT)); + assert(N0.getOpcode() == ISD::FABS); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + NewConv, DAG.getConstant(~SignBit, VT)); + } + + // fold (bitconvert (fcopysign cst, x)) -> + // (or (and (bitconvert x), sign), (and cst, (not sign))) + // Note that we don't handle (copysign x, cst) because this can always be + // folded to an fneg or fabs. + if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse() && + isa(N0.getOperand(0)) && + VT.isInteger() && !VT.isVector()) { + unsigned OrigXWidth = N0.getOperand(1).getValueType().getSizeInBits(); + EVT IntXVT = EVT::getIntegerVT(*DAG.getContext(), OrigXWidth); + if (isTypeLegal(IntXVT)) { + SDValue X = DAG.getNode(ISD::BITCAST, N0.getDebugLoc(), + IntXVT, N0.getOperand(1)); + AddToWorkList(X.getNode()); + + // If X has a different width than the result/lhs, sext it or truncate it. + unsigned VTWidth = VT.getSizeInBits(); + if (OrigXWidth < VTWidth) { + X = DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, X); + AddToWorkList(X.getNode()); + } else if (OrigXWidth > VTWidth) { + // To get the sign bit in the right place, we have to shift it right + // before truncating. + X = DAG.getNode(ISD::SRL, X.getDebugLoc(), + X.getValueType(), X, + DAG.getConstant(OrigXWidth-VTWidth, X.getValueType())); + AddToWorkList(X.getNode()); + X = DAG.getNode(ISD::TRUNCATE, X.getDebugLoc(), VT, X); + AddToWorkList(X.getNode()); + } + + APInt SignBit = APInt::getSignBit(VT.getSizeInBits()); + X = DAG.getNode(ISD::AND, X.getDebugLoc(), VT, + X, DAG.getConstant(SignBit, VT)); + AddToWorkList(X.getNode()); + + SDValue Cst = DAG.getNode(ISD::BITCAST, N0.getDebugLoc(), + VT, N0.getOperand(0)); + Cst = DAG.getNode(ISD::AND, Cst.getDebugLoc(), VT, + Cst, DAG.getConstant(~SignBit, VT)); + AddToWorkList(Cst.getNode()); + + return DAG.getNode(ISD::OR, N->getDebugLoc(), VT, X, Cst); + } + } + + // bitconvert(build_pair(ld, ld)) -> ld iff load locations are consecutive. + if (N0.getOpcode() == ISD::BUILD_PAIR) { + SDValue CombineLD = CombineConsecutiveLoads(N0.getNode(), VT); + if (CombineLD.getNode()) + return CombineLD; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBUILD_PAIR(SDNode *N) { + EVT VT = N->getValueType(0); + return CombineConsecutiveLoads(N, VT); +} + +/// ConstantFoldBITCASTofBUILD_VECTOR - We know that BV is a build_vector +/// node with Constant, ConstantFP or Undef operands. DstEltVT indicates the +/// destination element value type. +SDValue DAGCombiner:: +ConstantFoldBITCASTofBUILD_VECTOR(SDNode *BV, EVT DstEltVT) { + EVT SrcEltVT = BV->getValueType(0).getVectorElementType(); + + // If this is already the right type, we're done. + if (SrcEltVT == DstEltVT) return SDValue(BV, 0); + + unsigned SrcBitSize = SrcEltVT.getSizeInBits(); + unsigned DstBitSize = DstEltVT.getSizeInBits(); + + // If this is a conversion of N elements of one type to N elements of another + // type, convert each element. This handles FP<->INT cases. + if (SrcBitSize == DstBitSize) { + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, + BV->getValueType(0).getVectorNumElements()); + + // Due to the FP element handling below calling this routine recursively, + // we can end up with a scalar-to-vector node here. + if (BV->getOpcode() == ISD::SCALAR_TO_VECTOR) + return DAG.getNode(ISD::SCALAR_TO_VECTOR, BV->getDebugLoc(), VT, + DAG.getNode(ISD::BITCAST, BV->getDebugLoc(), + DstEltVT, BV->getOperand(0))); + + SmallVector Ops; + for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) { + SDValue Op = BV->getOperand(i); + // If the vector element type is not legal, the BUILD_VECTOR operands + // are promoted and implicitly truncated. Make that explicit here. + if (Op.getValueType() != SrcEltVT) + Op = DAG.getNode(ISD::TRUNCATE, BV->getDebugLoc(), SrcEltVT, Op); + Ops.push_back(DAG.getNode(ISD::BITCAST, BV->getDebugLoc(), + DstEltVT, Op)); + AddToWorkList(Ops.back().getNode()); + } + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + + // Otherwise, we're growing or shrinking the elements. To avoid having to + // handle annoying details of growing/shrinking FP values, we convert them to + // int first. + if (SrcEltVT.isFloatingPoint()) { + // Convert the input float vector to a int vector where the elements are the + // same sizes. + assert((SrcEltVT == MVT::f32 || SrcEltVT == MVT::f64) && "Unknown FP VT!"); + EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcEltVT.getSizeInBits()); + BV = ConstantFoldBITCASTofBUILD_VECTOR(BV, IntVT).getNode(); + SrcEltVT = IntVT; + } + + // Now we know the input is an integer vector. If the output is a FP type, + // convert to integer first, then to FP of the right size. + if (DstEltVT.isFloatingPoint()) { + assert((DstEltVT == MVT::f32 || DstEltVT == MVT::f64) && "Unknown FP VT!"); + EVT TmpVT = EVT::getIntegerVT(*DAG.getContext(), DstEltVT.getSizeInBits()); + SDNode *Tmp = ConstantFoldBITCASTofBUILD_VECTOR(BV, TmpVT).getNode(); + + // Next, convert to FP elements of the same size. + return ConstantFoldBITCASTofBUILD_VECTOR(Tmp, DstEltVT); + } + + // Okay, we know the src/dst types are both integers of differing types. + // Handling growing first. + assert(SrcEltVT.isInteger() && DstEltVT.isInteger()); + if (SrcBitSize < DstBitSize) { + unsigned NumInputsPerOutput = DstBitSize/SrcBitSize; + + SmallVector Ops; + for (unsigned i = 0, e = BV->getNumOperands(); i != e; + i += NumInputsPerOutput) { + bool isLE = TLI.isLittleEndian(); + APInt NewBits = APInt(DstBitSize, 0); + bool EltIsUndef = true; + for (unsigned j = 0; j != NumInputsPerOutput; ++j) { + // Shift the previously computed bits over. + NewBits <<= SrcBitSize; + SDValue Op = BV->getOperand(i+ (isLE ? (NumInputsPerOutput-j-1) : j)); + if (Op.getOpcode() == ISD::UNDEF) continue; + EltIsUndef = false; + + NewBits |= cast(Op)->getAPIntValue(). + zextOrTrunc(SrcBitSize).zext(DstBitSize); + } + + if (EltIsUndef) + Ops.push_back(DAG.getUNDEF(DstEltVT)); + else + Ops.push_back(DAG.getConstant(NewBits, DstEltVT)); + } + + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, Ops.size()); + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); + } + + // Finally, this must be the case where we are shrinking elements: each input + // turns into multiple outputs. + bool isS2V = ISD::isScalarToVector(BV); + unsigned NumOutputsPerInput = SrcBitSize/DstBitSize; + EVT VT = EVT::getVectorVT(*DAG.getContext(), DstEltVT, + NumOutputsPerInput*BV->getNumOperands()); + SmallVector Ops; + + for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) { + if (BV->getOperand(i).getOpcode() == ISD::UNDEF) { + for (unsigned j = 0; j != NumOutputsPerInput; ++j) + Ops.push_back(DAG.getUNDEF(DstEltVT)); + continue; + } + + APInt OpVal = cast(BV->getOperand(i))-> + getAPIntValue().zextOrTrunc(SrcBitSize); + + for (unsigned j = 0; j != NumOutputsPerInput; ++j) { + APInt ThisVal = OpVal.trunc(DstBitSize); + Ops.push_back(DAG.getConstant(ThisVal, DstEltVT)); + if (isS2V && i == 0 && j == 0 && ThisVal.zext(SrcBitSize) == OpVal) + // Simply turn this into a SCALAR_TO_VECTOR of the new type. + return DAG.getNode(ISD::SCALAR_TO_VECTOR, BV->getDebugLoc(), VT, + Ops[0]); + OpVal = OpVal.lshr(DstBitSize); + } + + // For big endian targets, swap the order of the pieces of each element. + if (TLI.isBigEndian()) + std::reverse(Ops.end()-NumOutputsPerInput, Ops.end()); + } + + return DAG.getNode(ISD::BUILD_VECTOR, BV->getDebugLoc(), VT, + &Ops[0], Ops.size()); +} + +SDValue DAGCombiner::visitFADD(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fadd c1, c2) -> (fadd c1, c2) + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N1); + // canonicalize constant to RHS + if (N0CFP && !N1CFP) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N1, N0); + // fold (fadd A, 0) -> A + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N0; + // fold (fadd A, (fneg B)) -> (fsub A, B) + if (isNegatibleForFree(N1, LegalOperations) == 2) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0, + GetNegatedExpression(N1, DAG, LegalOperations)); + // fold (fadd (fneg A), B) -> (fsub B, A) + if (isNegatibleForFree(N0, LegalOperations) == 2) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N1, + GetNegatedExpression(N0, DAG, LegalOperations)); + + // If allowed, fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2)) + if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FADD && + N0.getNode()->hasOneUse() && isa(N0.getOperand(1))) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, + N0.getOperand(1), N1)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFSUB(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fsub c1, c2) -> c1-c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0, N1); + // fold (fsub A, 0) -> A + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N0; + // fold (fsub 0, B) -> -B + if (UnsafeFPMath && N0CFP && N0CFP->getValueAPF().isZero()) { + if (isNegatibleForFree(N1, LegalOperations)) + return GetNegatedExpression(N1, DAG, LegalOperations); + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N1); + } + // fold (fsub A, (fneg B)) -> (fadd A, B) + if (isNegatibleForFree(N1, LegalOperations)) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, + GetNegatedExpression(N1, DAG, LegalOperations)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFMUL(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fmul c1, c2) -> c1*c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0, N1); + // canonicalize constant to RHS + if (N0CFP && !N1CFP) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N1, N0); + // fold (fmul A, 0) -> 0 + if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero()) + return N1; + // fold (fmul A, 0) -> 0, vector edition. + if (UnsafeFPMath && ISD::isBuildVectorAllZeros(N1.getNode())) + return N1; + // fold (fmul X, 2.0) -> (fadd X, X) + if (N1CFP && N1CFP->isExactlyValue(+2.0)) + return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N0); + // fold (fmul X, -1.0) -> (fneg X) + if (N1CFP && N1CFP->isExactlyValue(-1.0)) + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N0); + + // fold (fmul (fneg X), (fneg Y)) -> (fmul X, Y) + if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) { + if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, + GetNegatedExpression(N0, DAG, LegalOperations), + GetNegatedExpression(N1, DAG, LegalOperations)); + } + } + + // If allowed, fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2)) + if (UnsafeFPMath && N1CFP && N0.getOpcode() == ISD::FMUL && + N0.getNode()->hasOneUse() && isa(N0.getOperand(1))) + return DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getNode(ISD::FMUL, N->getDebugLoc(), VT, + N0.getOperand(1), N1)); + + return SDValue(); +} + +SDValue DAGCombiner::visitFDIV(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold vector ops + if (VT.isVector()) { + SDValue FoldedVOp = SimplifyVBinOp(N); + if (FoldedVOp.getNode()) return FoldedVOp; + } + + // fold (fdiv c1, c2) -> c1/c2 + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, N0, N1); + + + // (fdiv (fneg X), (fneg Y)) -> (fdiv X, Y) + if (char LHSNeg = isNegatibleForFree(N0, LegalOperations)) { + if (char RHSNeg = isNegatibleForFree(N1, LegalOperations)) { + // Both can be negated for free, check to see if at least one is cheaper + // negated. + if (LHSNeg == 2 || RHSNeg == 2) + return DAG.getNode(ISD::FDIV, N->getDebugLoc(), VT, + GetNegatedExpression(N0, DAG, LegalOperations), + GetNegatedExpression(N1, DAG, LegalOperations)); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFREM(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + // fold (frem c1, c2) -> fmod(c1,c2) + if (N0CFP && N1CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FREM, N->getDebugLoc(), VT, N0, N1); + + return SDValue(); +} + +SDValue DAGCombiner::visitFCOPYSIGN(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + ConstantFPSDNode *N1CFP = dyn_cast(N1); + EVT VT = N->getValueType(0); + + if (N0CFP && N1CFP && VT != MVT::ppcf128) // Constant fold + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, N0, N1); + + if (N1CFP) { + const APFloat& V = N1CFP->getValueAPF(); + // copysign(x, c1) -> fabs(x) iff ispos(c1) + // copysign(x, c1) -> fneg(fabs(x)) iff isneg(c1) + if (!V.isNegative()) { + if (!LegalOperations || TLI.isOperationLegal(ISD::FABS, VT)) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + } else { + if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) + return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, + DAG.getNode(ISD::FABS, N0.getDebugLoc(), VT, N0)); + } + } + + // copysign(fabs(x), y) -> copysign(x, y) + // copysign(fneg(x), y) -> copysign(x, y) + // copysign(copysign(x,z), y) -> copysign(x, y) + if (N0.getOpcode() == ISD::FABS || N0.getOpcode() == ISD::FNEG || + N0.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0.getOperand(0), N1); + + // copysign(x, abs(y)) -> abs(x) + if (N1.getOpcode() == ISD::FABS) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + + // copysign(x, copysign(y,z)) -> copysign(x, z) + if (N1.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0, N1.getOperand(1)); + + // copysign(x, fp_extend(y)) -> copysign(x, y) + // copysign(x, fp_round(y)) -> copysign(x, y) + if (N1.getOpcode() == ISD::FP_EXTEND || N1.getOpcode() == ISD::FP_ROUND) + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + N0, N1.getOperand(0)); + + return SDValue(); +} + +SDValue DAGCombiner::visitSINT_TO_FP(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantSDNode *N0C = dyn_cast(N0); + EVT VT = N->getValueType(0); + EVT OpVT = N0.getValueType(); + + // fold (sint_to_fp c1) -> c1fp + if (N0C && OpVT != MVT::ppcf128 && + // ...but only if the target supports immediate floating-point values + (Level == llvm::Unrestricted || TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT))) + return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0); + + // If the input is a legal type, and SINT_TO_FP is not legal on this target, + // but UINT_TO_FP is legal on this target, try to convert. + if (!TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, OpVT) && + TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, OpVT)) { + // If the sign bit is known to be zero, we can change this to UINT_TO_FP. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitUINT_TO_FP(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantSDNode *N0C = dyn_cast(N0); + EVT VT = N->getValueType(0); + EVT OpVT = N0.getValueType(); + + // fold (uint_to_fp c1) -> c1fp + if (N0C && OpVT != MVT::ppcf128 && + // ...but only if the target supports immediate floating-point values + (Level == llvm::Unrestricted || TLI.isOperationLegalOrCustom(llvm::ISD::ConstantFP, VT))) + return DAG.getNode(ISD::UINT_TO_FP, N->getDebugLoc(), VT, N0); + + // If the input is a legal type, and UINT_TO_FP is not legal on this target, + // but SINT_TO_FP is legal on this target, try to convert. + if (!TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, OpVT) && + TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, OpVT)) { + // If the sign bit is known to be zero, we can change this to SINT_TO_FP. + if (DAG.SignBitIsZero(N0)) + return DAG.getNode(ISD::SINT_TO_FP, N->getDebugLoc(), VT, N0); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_TO_SINT(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_to_sint c1fp) -> c1 + if (N0CFP) + return DAG.getNode(ISD::FP_TO_SINT, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_TO_UINT(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_to_uint c1fp) -> c1 + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FP_TO_UINT, N->getDebugLoc(), VT, N0); + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_ROUND(SDNode *N) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fp_round c1fp) -> c1fp + if (N0CFP && N0.getValueType() != MVT::ppcf128) + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0, N1); + + // fold (fp_round (fp_extend x)) -> x + if (N0.getOpcode() == ISD::FP_EXTEND && VT == N0.getOperand(0).getValueType()) + return N0.getOperand(0); + + // fold (fp_round (fp_round x)) -> (fp_round x) + if (N0.getOpcode() == ISD::FP_ROUND) { + // This is a value preserving truncation if both round's are. + bool IsTrunc = N->getConstantOperandVal(1) == 1 && + N0.getNode()->getConstantOperandVal(1) == 1; + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, N0.getOperand(0), + DAG.getIntPtrConstant(IsTrunc)); + } + + // fold (fp_round (copysign X, Y)) -> (copysign (fp_round X), Y) + if (N0.getOpcode() == ISD::FCOPYSIGN && N0.getNode()->hasOneUse()) { + SDValue Tmp = DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), VT, + N0.getOperand(0), N1); + AddToWorkList(Tmp.getNode()); + return DAG.getNode(ISD::FCOPYSIGN, N->getDebugLoc(), VT, + Tmp, N0.getOperand(1)); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_ROUND_INREG(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + EVT EVT = cast(N->getOperand(1))->getVT(); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + + // fold (fp_round_inreg c1fp) -> c1fp + if (N0CFP && isTypeLegal(EVT)) { + SDValue Round = DAG.getConstantFP(*N0CFP->getConstantFPValue(), EVT); + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, Round); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // If this is fp_round(fpextend), don't fold it, allow ourselves to be folded. + if (N->hasOneUse() && + N->use_begin()->getOpcode() == ISD::FP_ROUND) + return SDValue(); + + // fold (fp_extend c1fp) -> c1fp + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, N0); + + // Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the + // value of X. + if (N0.getOpcode() == ISD::FP_ROUND + && N0.getNode()->getConstantOperandVal(1) == 1) { + SDValue In = N0.getOperand(0); + if (In.getValueType() == VT) return In; + if (VT.bitsLT(In.getValueType())) + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), VT, + In, N0.getOperand(1)); + return DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), VT, In); + } + + // fold (fpext (load x)) -> (fpext (fptrunc (extload x))) + if (ISD::isNON_EXTLoad(N0.getNode()) && N0.hasOneUse() && + ((!LegalOperations && !cast(N0)->isVolatile()) || + TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) { + LoadSDNode *LN0 = cast(N0); + SDValue ExtLoad = DAG.getExtLoad(ISD::EXTLOAD, N->getDebugLoc(), VT, + LN0->getChain(), + LN0->getBasePtr(), LN0->getPointerInfo(), + N0.getValueType(), + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); + CombineTo(N, ExtLoad); + CombineTo(N0.getNode(), + DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), + N0.getValueType(), ExtLoad, DAG.getIntPtrConstant(1)), + ExtLoad.getValue(1)); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFNEG(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + if (isNegatibleForFree(N0, LegalOperations)) + return GetNegatedExpression(N0, DAG, LegalOperations); + + // Transform fneg(bitconvert(x)) -> bitconvert(x^sign) to avoid loading + // constant pool values. + if (N0.getOpcode() == ISD::BITCAST && + !VT.isVector() && + N0.getNode()->hasOneUse() && + N0.getOperand(0).getValueType().isInteger()) { + SDValue Int = N0.getOperand(0); + EVT IntVT = Int.getValueType(); + if (IntVT.isInteger() && !IntVT.isVector()) { + Int = DAG.getNode(ISD::XOR, N0.getDebugLoc(), IntVT, Int, + DAG.getConstant(APInt::getSignBit(IntVT.getSizeInBits()), IntVT)); + AddToWorkList(Int.getNode()); + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), + VT, Int); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitFABS(SDNode *N) { + SDValue N0 = N->getOperand(0); + ConstantFPSDNode *N0CFP = dyn_cast(N0); + EVT VT = N->getValueType(0); + + // fold (fabs c1) -> fabs(c1) + if (N0CFP && VT != MVT::ppcf128) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0); + // fold (fabs (fabs x)) -> (fabs x) + if (N0.getOpcode() == ISD::FABS) + return N->getOperand(0); + // fold (fabs (fneg x)) -> (fabs x) + // fold (fabs (fcopysign x, y)) -> (fabs x) + if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN) + return DAG.getNode(ISD::FABS, N->getDebugLoc(), VT, N0.getOperand(0)); + + // Transform fabs(bitconvert(x)) -> bitconvert(x&~sign) to avoid loading + // constant pool values. + if (N0.getOpcode() == ISD::BITCAST && N0.getNode()->hasOneUse() && + N0.getOperand(0).getValueType().isInteger() && + !N0.getOperand(0).getValueType().isVector()) { + SDValue Int = N0.getOperand(0); + EVT IntVT = Int.getValueType(); + if (IntVT.isInteger() && !IntVT.isVector()) { + Int = DAG.getNode(ISD::AND, N0.getDebugLoc(), IntVT, Int, + DAG.getConstant(~APInt::getSignBit(IntVT.getSizeInBits()), IntVT)); + AddToWorkList(Int.getNode()); + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), + N->getValueType(0), Int); + } + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBRCOND(SDNode *N) { + SDValue Chain = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + + // If N is a constant we could fold this into a fallthrough or unconditional + // branch. However that doesn't happen very often in normal code, because + // Instcombine/SimplifyCFG should have handled the available opportunities. + // If we did this folding here, it would be necessary to update the + // MachineBasicBlock CFG, which is awkward. + + // fold a brcond with a setcc condition into a BR_CC node if BR_CC is legal + // on the target. + if (N1.getOpcode() == ISD::SETCC && + TLI.isOperationLegalOrCustom(ISD::BR_CC, MVT::Other)) { + return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other, + Chain, N1.getOperand(2), + N1.getOperand(0), N1.getOperand(1), N2); + } + + if ((N1.hasOneUse() && N1.getOpcode() == ISD::SRL) || + ((N1.getOpcode() == ISD::TRUNCATE && N1.hasOneUse()) && + (N1.getOperand(0).hasOneUse() && + N1.getOperand(0).getOpcode() == ISD::SRL))) { + SDNode *Trunc = 0; + if (N1.getOpcode() == ISD::TRUNCATE) { + // Look pass the truncate. + Trunc = N1.getNode(); + N1 = N1.getOperand(0); + } + + // Match this pattern so that we can generate simpler code: + // + // %a = ... + // %b = and i32 %a, 2 + // %c = srl i32 %b, 1 + // brcond i32 %c ... + // + // into + // + // %a = ... + // %b = and i32 %a, 2 + // %c = setcc eq %b, 0 + // brcond %c ... + // + // This applies only when the AND constant value has one bit set and the + // SRL constant is equal to the log2 of the AND constant. The back-end is + // smart enough to convert the result into a TEST/JMP sequence. + SDValue Op0 = N1.getOperand(0); + SDValue Op1 = N1.getOperand(1); + + if (Op0.getOpcode() == ISD::AND && + Op1.getOpcode() == ISD::Constant) { + SDValue AndOp1 = Op0.getOperand(1); + + if (AndOp1.getOpcode() == ISD::Constant) { + const APInt &AndConst = cast(AndOp1)->getAPIntValue(); + + if (AndConst.isPowerOf2() && + cast(Op1)->getAPIntValue()==AndConst.logBase2()) { + SDValue SetCC = + DAG.getSetCC(N->getDebugLoc(), + TLI.getSetCCResultType(Op0.getValueType()), + Op0, DAG.getConstant(0, Op0.getValueType()), + ISD::SETNE); + + SDValue NewBRCond = DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, SetCC, N2); + // Don't add the new BRCond into the worklist or else SimplifySelectCC + // will convert it back to (X & C1) >> C2. + CombineTo(N, NewBRCond, false); + // Truncate is dead. + if (Trunc) { + removeFromWorkList(Trunc); + DAG.DeleteNode(Trunc); + } + // Replace the uses of SRL with SETCC + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes); + removeFromWorkList(N1.getNode()); + DAG.DeleteNode(N1.getNode()); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + + if (Trunc) + // Restore N1 if the above transformation doesn't match. + N1 = N->getOperand(1); + } + + // Transform br(xor(x, y)) -> br(x != y) + // Transform br(xor(xor(x,y), 1)) -> br (x == y) + if (N1.hasOneUse() && N1.getOpcode() == ISD::XOR) { + SDNode *TheXor = N1.getNode(); + SDValue Op0 = TheXor->getOperand(0); + SDValue Op1 = TheXor->getOperand(1); + if (Op0.getOpcode() == Op1.getOpcode()) { + // Avoid missing important xor optimizations. + SDValue Tmp = visitXOR(TheXor); + if (Tmp.getNode() && Tmp.getNode() != TheXor) { + DEBUG(dbgs() << "\nReplacing.8 "; + TheXor->dump(&DAG); + dbgs() << "\nWith: "; + Tmp.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, Tmp, &DeadNodes); + removeFromWorkList(TheXor); + DAG.DeleteNode(TheXor); + return DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, Tmp, N2); + } + } + + if (Op0.getOpcode() != ISD::SETCC && Op1.getOpcode() != ISD::SETCC) { + bool Equal = false; + if (ConstantSDNode *RHSCI = dyn_cast(Op0)) + if (RHSCI->getAPIntValue() == 1 && Op0.hasOneUse() && + Op0.getOpcode() == ISD::XOR) { + TheXor = Op0.getNode(); + Equal = true; + } + + EVT SetCCVT = N1.getValueType(); + if (LegalTypes) + SetCCVT = TLI.getSetCCResultType(SetCCVT); + SDValue SetCC = DAG.getSetCC(TheXor->getDebugLoc(), + SetCCVT, + Op0, Op1, + Equal ? ISD::SETEQ : ISD::SETNE); + // Replace the uses of XOR with SETCC + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes); + removeFromWorkList(N1.getNode()); + DAG.DeleteNode(N1.getNode()); + return DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, SetCC, N2); + } + } + + return SDValue(); +} + +// Operand List for BR_CC: Chain, CondCC, CondLHS, CondRHS, DestBB. +// +SDValue DAGCombiner::visitBR_CC(SDNode *N) { + CondCodeSDNode *CC = cast(N->getOperand(1)); + SDValue CondLHS = N->getOperand(2), CondRHS = N->getOperand(3); + + // If N is a constant we could fold this into a fallthrough or unconditional + // branch. However that doesn't happen very often in normal code, because + // Instcombine/SimplifyCFG should have handled the available opportunities. + // If we did this folding here, it would be necessary to update the + // MachineBasicBlock CFG, which is awkward. + + // Use SimplifySetCC to simplify SETCC's. + SDValue Simp = SimplifySetCC(TLI.getSetCCResultType(CondLHS.getValueType()), + CondLHS, CondRHS, CC->get(), N->getDebugLoc(), + false); + if (Simp.getNode()) AddToWorkList(Simp.getNode()); + + // fold to a simpler setcc + if (Simp.getNode() && Simp.getOpcode() == ISD::SETCC) + return DAG.getNode(ISD::BR_CC, N->getDebugLoc(), MVT::Other, + N->getOperand(0), Simp.getOperand(2), + Simp.getOperand(0), Simp.getOperand(1), + N->getOperand(4)); + + return SDValue(); +} + +/// CombineToPreIndexedLoadStore - Try turning a load / store into a +/// pre-indexed load / store when the base pointer is an add or subtract +/// and it has other uses besides the load / store. After the +/// transformation, the new indexed load / store has effectively folded +/// the add / subtract in and all of its other uses are redirected to the +/// new load / store. +bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) { + if (!LegalOperations) + return false; + + bool isLoad = true; + SDValue Ptr; + EVT VT; + if (LoadSDNode *LD = dyn_cast(N)) { + if (LD->isIndexed()) + return false; + VT = LD->getMemoryVT(); + if (!TLI.isIndexedLoadLegal(ISD::PRE_INC, VT) && + !TLI.isIndexedLoadLegal(ISD::PRE_DEC, VT)) + return false; + Ptr = LD->getBasePtr(); + } else if (StoreSDNode *ST = dyn_cast(N)) { + if (ST->isIndexed()) + return false; + VT = ST->getMemoryVT(); + if (!TLI.isIndexedStoreLegal(ISD::PRE_INC, VT) && + !TLI.isIndexedStoreLegal(ISD::PRE_DEC, VT)) + return false; + Ptr = ST->getBasePtr(); + isLoad = false; + } else { + return false; + } + + // If the pointer is not an add/sub, or if it doesn't have multiple uses, bail + // out. There is no reason to make this a preinc/predec. + if ((Ptr.getOpcode() != ISD::ADD && Ptr.getOpcode() != ISD::SUB) || + Ptr.getNode()->hasOneUse()) + return false; + + // Ask the target to do addressing mode selection. + SDValue BasePtr; + SDValue Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (!TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) + return false; + // Don't create a indexed load / store with zero offset. + if (isa(Offset) && + cast(Offset)->isNullValue()) + return false; + + // Try turning it into a pre-indexed load / store except when: + // 1) The new base ptr is a frame index. + // 2) If N is a store and the new base ptr is either the same as or is a + // predecessor of the value being stored. + // 3) Another use of old base ptr is a predecessor of N. If ptr is folded + // that would create a cycle. + // 4) All uses are load / store ops that use it as old base ptr. + + // Check #1. Preinc'ing a frame index would require copying the stack pointer + // (plus the implicit offset) to a register to preinc anyway. + if (isa(BasePtr) || isa(BasePtr)) + return false; + + // Check #2. + if (!isLoad) { + SDValue Val = cast(N)->getValue(); + if (Val == BasePtr || BasePtr.getNode()->isPredecessorOf(Val.getNode())) + return false; + } + + // Now check for #3 and #4. + bool RealUse = false; + for (SDNode::use_iterator I = Ptr.getNode()->use_begin(), + E = Ptr.getNode()->use_end(); I != E; ++I) { + SDNode *Use = *I; + if (Use == N) + continue; + if (Use->isPredecessorOf(N)) + return false; + + if (!((Use->getOpcode() == ISD::LOAD && + cast(Use)->getBasePtr() == Ptr) || + (Use->getOpcode() == ISD::STORE && + cast(Use)->getBasePtr() == Ptr))) + RealUse = true; + } + + if (!RealUse) + return false; + + SDValue Result; + if (isLoad) + Result = DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + else + Result = DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + ++PreIndexedNodes; + ++NodesCombined; + DEBUG(dbgs() << "\nReplacing.4 "; + N->dump(&DAG); + dbgs() << "\nWith: "; + Result.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(0), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Result.getValue(2), + &DeadNodes); + } else { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(1), + &DeadNodes); + } + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + + // Replace the uses of Ptr with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0), + &DeadNodes); + removeFromWorkList(Ptr.getNode()); + DAG.DeleteNode(Ptr.getNode()); + + return true; +} + +/// CombineToPostIndexedLoadStore - Try to combine a load / store with a +/// add / sub of the base pointer node into a post-indexed load / store. +/// The transformation folded the add / subtract into the new indexed +/// load / store effectively and all of its uses are redirected to the +/// new load / store. +bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) { + if (!LegalOperations) + return false; + + bool isLoad = true; + SDValue Ptr; + EVT VT; + if (LoadSDNode *LD = dyn_cast(N)) { + if (LD->isIndexed()) + return false; + VT = LD->getMemoryVT(); + if (!TLI.isIndexedLoadLegal(ISD::POST_INC, VT) && + !TLI.isIndexedLoadLegal(ISD::POST_DEC, VT)) + return false; + Ptr = LD->getBasePtr(); + } else if (StoreSDNode *ST = dyn_cast(N)) { + if (ST->isIndexed()) + return false; + VT = ST->getMemoryVT(); + if (!TLI.isIndexedStoreLegal(ISD::POST_INC, VT) && + !TLI.isIndexedStoreLegal(ISD::POST_DEC, VT)) + return false; + Ptr = ST->getBasePtr(); + isLoad = false; + } else { + return false; + } + + if (Ptr.getNode()->hasOneUse()) + return false; + + for (SDNode::use_iterator I = Ptr.getNode()->use_begin(), + E = Ptr.getNode()->use_end(); I != E; ++I) { + SDNode *Op = *I; + if (Op == N || + (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB)) + continue; + + SDValue BasePtr; + SDValue Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) { + // Don't create a indexed load / store with zero offset. + if (isa(Offset) && + cast(Offset)->isNullValue()) + continue; + + // Try turning it into a post-indexed load / store except when + // 1) All uses are load / store ops that use it as base ptr. + // 2) Op must be independent of N, i.e. Op is neither a predecessor + // nor a successor of N. Otherwise, if Op is folded that would + // create a cycle. + + if (isa(BasePtr) || isa(BasePtr)) + continue; + + // Check for #1. + bool TryNext = false; + for (SDNode::use_iterator II = BasePtr.getNode()->use_begin(), + EE = BasePtr.getNode()->use_end(); II != EE; ++II) { + SDNode *Use = *II; + if (Use == Ptr.getNode()) + continue; + + // If all the uses are load / store addresses, then don't do the + // transformation. + if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){ + bool RealUse = false; + for (SDNode::use_iterator III = Use->use_begin(), + EEE = Use->use_end(); III != EEE; ++III) { + SDNode *UseUse = *III; + if (!((UseUse->getOpcode() == ISD::LOAD && + cast(UseUse)->getBasePtr().getNode() == Use) || + (UseUse->getOpcode() == ISD::STORE && + cast(UseUse)->getBasePtr().getNode() == Use))) + RealUse = true; + } + + if (!RealUse) { + TryNext = true; + break; + } + } + } + + if (TryNext) + continue; + + // Check for #2 + if (!Op->isPredecessorOf(N) && !N->isPredecessorOf(Op)) { + SDValue Result = isLoad + ? DAG.getIndexedLoad(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM) + : DAG.getIndexedStore(SDValue(N,0), N->getDebugLoc(), + BasePtr, Offset, AM); + ++PostIndexedNodes; + ++NodesCombined; + DEBUG(dbgs() << "\nReplacing.5 "; + N->dump(&DAG); + dbgs() << "\nWith: "; + Result.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(0), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Result.getValue(2), + &DeadNodes); + } else { + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result.getValue(1), + &DeadNodes); + } + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + + // Replace the uses of Use with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(SDValue(Op, 0), + Result.getValue(isLoad ? 1 : 0), + &DeadNodes); + removeFromWorkList(Op); + DAG.DeleteNode(Op); + return true; + } + } + } + + return false; +} + +SDValue DAGCombiner::visitLOAD(SDNode *N) { + LoadSDNode *LD = cast(N); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + + // If load is not volatile and there are no uses of the loaded value (and + // the updated indexed value in case of indexed loads), change uses of the + // chain value into uses of the chain input (i.e. delete the dead load). + if (!LD->isVolatile()) { + if (N->getValueType(1) == MVT::Other) { + // Unindexed loads. + if (N->hasNUsesOfValue(0, 0)) { + // It's not safe to use the two value CombineTo variant here. e.g. + // v1, chain2 = load chain1, loc + // v2, chain3 = load chain2, loc + // v3 = add v2, c + // Now we replace use of chain2 with chain1. This makes the second load + // isomorphic to the one we are deleting, and thus makes this load live. + DEBUG(dbgs() << "\nReplacing.6 "; + N->dump(&DAG); + dbgs() << "\nWith chain: "; + Chain.getNode()->dump(&DAG); + dbgs() << "\n"); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), Chain, &DeadNodes); + + if (N->use_empty()) { + removeFromWorkList(N); + DAG.DeleteNode(N); + } + + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } else { + // Indexed loads. + assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?"); + if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) { + SDValue Undef = DAG.getUNDEF(N->getValueType(0)); + DEBUG(dbgs() << "\nReplacing.7 "; + N->dump(&DAG); + dbgs() << "\nWith: "; + Undef.getNode()->dump(&DAG); + dbgs() << " and 2 other values\n"); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Undef, &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), + DAG.getUNDEF(N->getValueType(1)), + &DeadNodes); + DAG.ReplaceAllUsesOfValueWith(SDValue(N, 2), Chain, &DeadNodes); + removeFromWorkList(N); + DAG.DeleteNode(N); + return SDValue(N, 0); // Return N so it doesn't get rechecked! + } + } + } + + // If this load is directly stored, replace the load value with the stored + // value. + // TODO: Handle store large -> read small portion. + // TODO: Handle TRUNCSTORE/LOADEXT + if (LD->getExtensionType() == ISD::NON_EXTLOAD && + !LD->isVolatile()) { + if (ISD::isNON_TRUNCStore(Chain.getNode())) { + StoreSDNode *PrevST = cast(Chain); + if (PrevST->getBasePtr() == Ptr && + PrevST->getValue().getValueType() == N->getValueType(0)) + return CombineTo(N, Chain.getOperand(1), Chain); + } + } + + // Try to infer better alignment information than the load already has. + if (OptLevel != CodeGenOpt::None && LD->isUnindexed()) { + if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { + if (Align > LD->getAlignment()) + return DAG.getExtLoad(LD->getExtensionType(), N->getDebugLoc(), + LD->getValueType(0), + Chain, Ptr, LD->getPointerInfo(), + LD->getMemoryVT(), + LD->isVolatile(), LD->isNonTemporal(), Align); + } + } + + if (CombinerAA) { + // Walk up chain skipping non-aliasing memory nodes. + SDValue BetterChain = FindBetterChain(N, Chain); + + // If there is a better chain. + if (Chain != BetterChain) { + SDValue ReplLoad; + + // Replace the chain to void dependency. + if (LD->getExtensionType() == ISD::NON_EXTLOAD) { + ReplLoad = DAG.getLoad(N->getValueType(0), LD->getDebugLoc(), + BetterChain, Ptr, LD->getPointerInfo(), + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); + } else { + ReplLoad = DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(), + LD->getValueType(0), + BetterChain, Ptr, LD->getPointerInfo(), + LD->getMemoryVT(), + LD->isVolatile(), + LD->isNonTemporal(), + LD->getAlignment()); + } + + // Create token factor to keep old chain connected. + SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, Chain, ReplLoad.getValue(1)); + + // Make sure the new and old chains are cleaned up. + AddToWorkList(Token.getNode()); + + // Replace uses with load result and token factor. Don't add users + // to work list. + return CombineTo(N, ReplLoad.getValue(0), Token, false); + } + } + + // Try transforming N to an indexed load. + if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) + return SDValue(N, 0); + + return SDValue(); +} + +/// CheckForMaskedLoad - Check to see if V is (and load (ptr), imm), where the +/// load is having specific bytes cleared out. If so, return the byte size +/// being masked out and the shift amount. +static std::pair +CheckForMaskedLoad(SDValue V, SDValue Ptr, SDValue Chain) { + std::pair Result(0, 0); + + // Check for the structure we're looking for. + if (V->getOpcode() != ISD::AND || + !isa(V->getOperand(1)) || + !ISD::isNormalLoad(V->getOperand(0).getNode())) + return Result; + + // Check the chain and pointer. + LoadSDNode *LD = cast(V->getOperand(0)); + if (LD->getBasePtr() != Ptr) return Result; // Not from same pointer. + + // The store should be chained directly to the load or be an operand of a + // tokenfactor. + if (LD == Chain.getNode()) + ; // ok. + else if (Chain->getOpcode() != ISD::TokenFactor) + return Result; // Fail. + else { + bool isOk = false; + for (unsigned i = 0, e = Chain->getNumOperands(); i != e; ++i) + if (Chain->getOperand(i).getNode() == LD) { + isOk = true; + break; + } + if (!isOk) return Result; + } + + // This only handles simple types. + if (V.getValueType() != MVT::i16 && + V.getValueType() != MVT::i32 && + V.getValueType() != MVT::i64) + return Result; + + // Check the constant mask. Invert it so that the bits being masked out are + // 0 and the bits being kept are 1. Use getSExtValue so that leading bits + // follow the sign bit for uniformity. + uint64_t NotMask = ~cast(V->getOperand(1))->getSExtValue(); + unsigned NotMaskLZ = CountLeadingZeros_64(NotMask); + if (NotMaskLZ & 7) return Result; // Must be multiple of a byte. + unsigned NotMaskTZ = CountTrailingZeros_64(NotMask); + if (NotMaskTZ & 7) return Result; // Must be multiple of a byte. + if (NotMaskLZ == 64) return Result; // All zero mask. + + // See if we have a continuous run of bits. If so, we have 0*1+0* + if (CountTrailingOnes_64(NotMask >> NotMaskTZ)+NotMaskTZ+NotMaskLZ != 64) + return Result; + + // Adjust NotMaskLZ down to be from the actual size of the int instead of i64. + if (V.getValueType() != MVT::i64 && NotMaskLZ) + NotMaskLZ -= 64-V.getValueSizeInBits(); + + unsigned MaskedBytes = (V.getValueSizeInBits()-NotMaskLZ-NotMaskTZ)/8; + switch (MaskedBytes) { + case 1: + case 2: + case 4: break; + default: return Result; // All one mask, or 5-byte mask. + } + + // Verify that the first bit starts at a multiple of mask so that the access + // is aligned the same as the access width. + if (NotMaskTZ && NotMaskTZ/8 % MaskedBytes) return Result; + + Result.first = MaskedBytes; + Result.second = NotMaskTZ/8; + return Result; +} + + +/// ShrinkLoadReplaceStoreWithStore - Check to see if IVal is something that +/// provides a value as specified by MaskInfo. If so, replace the specified +/// store with a narrower store of truncated IVal. +static SDNode * +ShrinkLoadReplaceStoreWithStore(const std::pair &MaskInfo, + SDValue IVal, StoreSDNode *St, + DAGCombiner *DC) { + unsigned NumBytes = MaskInfo.first; + unsigned ByteShift = MaskInfo.second; + SelectionDAG &DAG = DC->getDAG(); + + // Check to see if IVal is all zeros in the part being masked in by the 'or' + // that uses this. If not, this is not a replacement. + APInt Mask = ~APInt::getBitsSet(IVal.getValueSizeInBits(), + ByteShift*8, (ByteShift+NumBytes)*8); + if (!DAG.MaskedValueIsZero(IVal, Mask)) return 0; + + // Check that it is legal on the target to do this. It is legal if the new + // VT we're shrinking to (i8/i16/i32) is legal or we're still before type + // legalization. + MVT VT = MVT::getIntegerVT(NumBytes*8); + if (!DC->isTypeLegal(VT)) + return 0; + + // Okay, we can do this! Replace the 'St' store with a store of IVal that is + // shifted by ByteShift and truncated down to NumBytes. + if (ByteShift) + IVal = DAG.getNode(ISD::SRL, IVal->getDebugLoc(), IVal.getValueType(), IVal, + DAG.getConstant(ByteShift*8, + DC->getShiftAmountTy(IVal.getValueType()))); + + // Figure out the offset for the store and the alignment of the access. + unsigned StOffset; + unsigned NewAlign = St->getAlignment(); + + if (DAG.getTargetLoweringInfo().isLittleEndian()) + StOffset = ByteShift; + else + StOffset = IVal.getValueType().getStoreSize() - ByteShift - NumBytes; + + SDValue Ptr = St->getBasePtr(); + if (StOffset) { + Ptr = DAG.getNode(ISD::ADD, IVal->getDebugLoc(), Ptr.getValueType(), + Ptr, DAG.getConstant(StOffset, Ptr.getValueType())); + NewAlign = MinAlign(NewAlign, StOffset); + } + + // Truncate down to the new size. + IVal = DAG.getNode(ISD::TRUNCATE, IVal->getDebugLoc(), VT, IVal); + + ++OpsNarrowed; + return DAG.getStore(St->getChain(), St->getDebugLoc(), IVal, Ptr, + St->getPointerInfo().getWithOffset(StOffset), + false, false, NewAlign).getNode(); +} + + +/// ReduceLoadOpStoreWidth - Look for sequence of load / op / store where op is +/// one of 'or', 'xor', and 'and' of immediates. If 'op' is only touching some +/// of the loaded bits, try narrowing the load and store if it would end up +/// being a win for performance or code size. +SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { + StoreSDNode *ST = cast(N); + if (ST->isVolatile()) + return SDValue(); + + SDValue Chain = ST->getChain(); + SDValue Value = ST->getValue(); + SDValue Ptr = ST->getBasePtr(); + EVT VT = Value.getValueType(); + + if (ST->isTruncatingStore() || VT.isVector() || !Value.hasOneUse()) + return SDValue(); + + unsigned Opc = Value.getOpcode(); + + // If this is "store (or X, Y), P" and X is "(and (load P), cst)", where cst + // is a byte mask indicating a consecutive number of bytes, check to see if + // Y is known to provide just those bytes. If so, we try to replace the + // load + replace + store sequence with a single (narrower) store, which makes + // the load dead. + if (Opc == ISD::OR) { + std::pair MaskedLoad; + MaskedLoad = CheckForMaskedLoad(Value.getOperand(0), Ptr, Chain); + if (MaskedLoad.first) + if (SDNode *NewST = ShrinkLoadReplaceStoreWithStore(MaskedLoad, + Value.getOperand(1), ST,this)) + return SDValue(NewST, 0); + + // Or is commutative, so try swapping X and Y. + MaskedLoad = CheckForMaskedLoad(Value.getOperand(1), Ptr, Chain); + if (MaskedLoad.first) + if (SDNode *NewST = ShrinkLoadReplaceStoreWithStore(MaskedLoad, + Value.getOperand(0), ST,this)) + return SDValue(NewST, 0); + } + + if ((Opc != ISD::OR && Opc != ISD::XOR && Opc != ISD::AND) || + Value.getOperand(1).getOpcode() != ISD::Constant) + return SDValue(); + + SDValue N0 = Value.getOperand(0); + if (ISD::isNormalLoad(N0.getNode()) && N0.hasOneUse() && + Chain == SDValue(N0.getNode(), 1)) { + LoadSDNode *LD = cast(N0); + if (LD->getBasePtr() != Ptr || + LD->getPointerInfo().getAddrSpace() != + ST->getPointerInfo().getAddrSpace()) + return SDValue(); + + // Find the type to narrow it the load / op / store to. + SDValue N1 = Value.getOperand(1); + unsigned BitWidth = N1.getValueSizeInBits(); + APInt Imm = cast(N1)->getAPIntValue(); + if (Opc == ISD::AND) + Imm ^= APInt::getAllOnesValue(BitWidth); + if (Imm == 0 || Imm.isAllOnesValue()) + return SDValue(); + unsigned ShAmt = Imm.countTrailingZeros(); + unsigned MSB = BitWidth - Imm.countLeadingZeros() - 1; + unsigned NewBW = NextPowerOf2(MSB - ShAmt); + EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), NewBW); + while (NewBW < BitWidth && + !(TLI.isOperationLegalOrCustom(Opc, NewVT) && + TLI.isNarrowingProfitable(VT, NewVT))) { + NewBW = NextPowerOf2(NewBW); + NewVT = EVT::getIntegerVT(*DAG.getContext(), NewBW); + } + if (NewBW >= BitWidth) + return SDValue(); + + // If the lsb changed does not start at the type bitwidth boundary, + // start at the previous one. + if (ShAmt % NewBW) + ShAmt = (((ShAmt + NewBW - 1) / NewBW) * NewBW) - NewBW; + APInt Mask = APInt::getBitsSet(BitWidth, ShAmt, ShAmt + NewBW); + if ((Imm & Mask) == Imm) { + APInt NewImm = (Imm & Mask).lshr(ShAmt).trunc(NewBW); + if (Opc == ISD::AND) + NewImm ^= APInt::getAllOnesValue(NewBW); + uint64_t PtrOff = ShAmt / 8; + // For big endian targets, we need to adjust the offset to the pointer to + // load the correct bytes. + if (TLI.isBigEndian()) + PtrOff = (BitWidth + 7 - NewBW) / 8 - PtrOff; + + unsigned NewAlign = MinAlign(LD->getAlignment(), PtrOff); + const Type *NewVTTy = NewVT.getTypeForEVT(*DAG.getContext()); + if (NewAlign < TLI.getTargetData()->getABITypeAlignment(NewVTTy)) + return SDValue(); + + SDValue NewPtr = DAG.getNode(ISD::ADD, LD->getDebugLoc(), + Ptr.getValueType(), Ptr, + DAG.getConstant(PtrOff, Ptr.getValueType())); + SDValue NewLD = DAG.getLoad(NewVT, N0.getDebugLoc(), + LD->getChain(), NewPtr, + LD->getPointerInfo().getWithOffset(PtrOff), + LD->isVolatile(), LD->isNonTemporal(), + NewAlign); + SDValue NewVal = DAG.getNode(Opc, Value.getDebugLoc(), NewVT, NewLD, + DAG.getConstant(NewImm, NewVT)); + SDValue NewST = DAG.getStore(Chain, N->getDebugLoc(), + NewVal, NewPtr, + ST->getPointerInfo().getWithOffset(PtrOff), + false, false, NewAlign); + + AddToWorkList(NewPtr.getNode()); + AddToWorkList(NewLD.getNode()); + AddToWorkList(NewVal.getNode()); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), NewLD.getValue(1), + &DeadNodes); + ++OpsNarrowed; + return NewST; + } + } + + return SDValue(); +} + +/// TransformFPLoadStorePair - For a given floating point load / store pair, +/// if the load value isn't used by any other operations, then consider +/// transforming the pair to integer load / store operations if the target +/// deems the transformation profitable. +SDValue DAGCombiner::TransformFPLoadStorePair(SDNode *N) { + StoreSDNode *ST = cast(N); + SDValue Chain = ST->getChain(); + SDValue Value = ST->getValue(); + if (ISD::isNormalStore(ST) && ISD::isNormalLoad(Value.getNode()) && + Value.hasOneUse() && + Chain == SDValue(Value.getNode(), 1)) { + LoadSDNode *LD = cast(Value); + EVT VT = LD->getMemoryVT(); + if (!VT.isFloatingPoint() || + VT != ST->getMemoryVT() || + LD->isNonTemporal() || + ST->isNonTemporal() || + LD->getPointerInfo().getAddrSpace() != 0 || + ST->getPointerInfo().getAddrSpace() != 0) + return SDValue(); + + EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits()); + if (!TLI.isOperationLegal(ISD::LOAD, IntVT) || + !TLI.isOperationLegal(ISD::STORE, IntVT) || + !TLI.isDesirableToTransformToIntegerOp(ISD::LOAD, VT) || + !TLI.isDesirableToTransformToIntegerOp(ISD::STORE, VT)) + return SDValue(); + + unsigned LDAlign = LD->getAlignment(); + unsigned STAlign = ST->getAlignment(); + const Type *IntVTTy = IntVT.getTypeForEVT(*DAG.getContext()); + unsigned ABIAlign = TLI.getTargetData()->getABITypeAlignment(IntVTTy); + if (LDAlign < ABIAlign || STAlign < ABIAlign) + return SDValue(); + + SDValue NewLD = DAG.getLoad(IntVT, Value.getDebugLoc(), + LD->getChain(), LD->getBasePtr(), + LD->getPointerInfo(), + false, false, LDAlign); + + SDValue NewST = DAG.getStore(NewLD.getValue(1), N->getDebugLoc(), + NewLD, ST->getBasePtr(), + ST->getPointerInfo(), + false, false, STAlign); + + AddToWorkList(NewLD.getNode()); + AddToWorkList(NewST.getNode()); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(Value.getValue(1), NewLD.getValue(1), + &DeadNodes); + ++LdStFP2Int; + return NewST; + } + + return SDValue(); +} + +SDValue DAGCombiner::visitSTORE(SDNode *N) { + StoreSDNode *ST = cast(N); + SDValue Chain = ST->getChain(); + SDValue Value = ST->getValue(); + SDValue Ptr = ST->getBasePtr(); + + // If this is a store of a bit convert, store the input value if the + // resultant store does not need a higher alignment than the original. + if (Value.getOpcode() == ISD::BITCAST && !ST->isTruncatingStore() && + ST->isUnindexed()) { + unsigned OrigAlign = ST->getAlignment(); + EVT SVT = Value.getOperand(0).getValueType(); + unsigned Align = TLI.getTargetData()-> + getABITypeAlignment(SVT.getTypeForEVT(*DAG.getContext())); + if (Align <= OrigAlign && + ((!LegalOperations && !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, SVT))) + return DAG.getStore(Chain, N->getDebugLoc(), Value.getOperand(0), + Ptr, ST->getPointerInfo(), ST->isVolatile(), + ST->isNonTemporal(), OrigAlign); + } + + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' + if (ConstantFPSDNode *CFP = dyn_cast(Value)) { + // NOTE: If the original store is volatile, this transform must not increase + // the number of stores. For example, on x86-32 an f64 can be stored in one + // processor operation but an i64 (which is not legal) requires two. So the + // transform should not be done in this case. + if (Value.getOpcode() != ISD::TargetConstantFP) { + SDValue Tmp; + switch (CFP->getValueType(0).getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP type"); + case MVT::f80: // We don't do this for these yet. + case MVT::f128: + case MVT::ppcf128: + break; + case MVT::f32: + if ((isTypeLegal(MVT::i32) && !LegalOperations && !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { + Tmp = DAG.getConstant((uint32_t)CFP->getValueAPF(). + bitcastToAPInt().getZExtValue(), MVT::i32); + return DAG.getStore(Chain, N->getDebugLoc(), Tmp, + Ptr, ST->getPointerInfo(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); + } + break; + case MVT::f64: + if ((TLI.isTypeLegal(MVT::i64) && !LegalOperations && + !ST->isVolatile()) || + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i64)) { + Tmp = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). + getZExtValue(), MVT::i64); + return DAG.getStore(Chain, N->getDebugLoc(), Tmp, + Ptr, ST->getPointerInfo(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); + } else if (!ST->isVolatile() && + TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { + // Many FP stores are not made apparent until after legalize, e.g. for + // argument passing. Since this is so common, custom legalize the + // 64-bit integer store into two 32-bit stores. + uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue(); + SDValue Lo = DAG.getConstant(Val & 0xFFFFFFFF, MVT::i32); + SDValue Hi = DAG.getConstant(Val >> 32, MVT::i32); + if (TLI.isBigEndian()) std::swap(Lo, Hi); + + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + + SDValue St0 = DAG.getStore(Chain, ST->getDebugLoc(), Lo, + Ptr, ST->getPointerInfo(), + isVolatile, isNonTemporal, + ST->getAlignment()); + Ptr = DAG.getNode(ISD::ADD, N->getDebugLoc(), Ptr.getValueType(), Ptr, + DAG.getConstant(4, Ptr.getValueType())); + Alignment = MinAlign(Alignment, 4U); + SDValue St1 = DAG.getStore(Chain, ST->getDebugLoc(), Hi, + Ptr, ST->getPointerInfo().getWithOffset(4), + isVolatile, isNonTemporal, + Alignment); + return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, + St0, St1); + } + + break; + } + } + } + + // Try to infer better alignment information than the store already has. + if (OptLevel != CodeGenOpt::None && ST->isUnindexed()) { + if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { + if (Align > ST->getAlignment()) + return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, + Ptr, ST->getPointerInfo(), ST->getMemoryVT(), + ST->isVolatile(), ST->isNonTemporal(), Align); + } + } + + // Try transforming a pair floating point load / store ops to integer + // load / store ops. + SDValue NewST = TransformFPLoadStorePair(N); + if (NewST.getNode()) + return NewST; + + if (CombinerAA) { + // Walk up chain skipping non-aliasing memory nodes. + SDValue BetterChain = FindBetterChain(N, Chain); + + // If there is a better chain. + if (Chain != BetterChain) { + SDValue ReplStore; + + // Replace the chain to avoid dependency. + if (ST->isTruncatingStore()) { + ReplStore = DAG.getTruncStore(BetterChain, N->getDebugLoc(), Value, Ptr, + ST->getPointerInfo(), + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); + } else { + ReplStore = DAG.getStore(BetterChain, N->getDebugLoc(), Value, Ptr, + ST->getPointerInfo(), + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); + } + + // Create token to keep both nodes around. + SDValue Token = DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), + MVT::Other, Chain, ReplStore); + + // Make sure the new and old chains are cleaned up. + AddToWorkList(Token.getNode()); + + // Don't add users to work list. + return CombineTo(N, Token, false); + } + } + + // Try transforming N to an indexed store. + if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N)) + return SDValue(N, 0); + + // FIXME: is there such a thing as a truncating indexed store? + if (ST->isTruncatingStore() && ST->isUnindexed() && + Value.getValueType().isInteger()) { + // See if we can simplify the input to this truncstore with knowledge that + // only the low bits are being used. For example: + // "truncstore (or (shl x, 8), y), i8" -> "truncstore y, i8" + SDValue Shorter = + GetDemandedBits(Value, + APInt::getLowBitsSet(Value.getValueSizeInBits(), + ST->getMemoryVT().getSizeInBits())); + AddToWorkList(Value.getNode()); + if (Shorter.getNode()) + return DAG.getTruncStore(Chain, N->getDebugLoc(), Shorter, + Ptr, ST->getPointerInfo(), ST->getMemoryVT(), + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); + + // Otherwise, see if we can simplify the operation with + // SimplifyDemandedBits, which only works if the value has a single use. + if (SimplifyDemandedBits(Value, + APInt::getLowBitsSet( + Value.getValueType().getScalarType().getSizeInBits(), + ST->getMemoryVT().getScalarType().getSizeInBits()))) + return SDValue(N, 0); + } + + // If this is a load followed by a store to the same location, then the store + // is dead/noop. + if (LoadSDNode *Ld = dyn_cast(Value)) { + if (Ld->getBasePtr() == Ptr && ST->getMemoryVT() == Ld->getMemoryVT() && + ST->isUnindexed() && !ST->isVolatile() && + // There can't be any side effects between the load and store, such as + // a call or store. + Chain.reachesChainWithoutSideEffects(SDValue(Ld, 1))) { + // The store is dead, remove it. + return Chain; + } + } + + // If this is an FP_ROUND or TRUNC followed by a store, fold this into a + // truncating store. We can do this even if this is already a truncstore. + if ((Value.getOpcode() == ISD::FP_ROUND || Value.getOpcode() == ISD::TRUNCATE) + && Value.getNode()->hasOneUse() && ST->isUnindexed() && + TLI.isTruncStoreLegal(Value.getOperand(0).getValueType(), + ST->getMemoryVT())) { + return DAG.getTruncStore(Chain, N->getDebugLoc(), Value.getOperand(0), + Ptr, ST->getPointerInfo(), ST->getMemoryVT(), + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); + } + + return ReduceLoadOpStoreWidth(N); +} + +SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) { + SDValue InVec = N->getOperand(0); + SDValue InVal = N->getOperand(1); + SDValue EltNo = N->getOperand(2); + + // If the inserted element is an UNDEF, just use the input vector. + if (InVal.getOpcode() == ISD::UNDEF) + return InVec; + + EVT VT = InVec.getValueType(); + + // If we can't generate a legal BUILD_VECTOR, exit + if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) + return SDValue(); + + // If the invec is a BUILD_VECTOR and if EltNo is a constant, build a new + // vector with the inserted element. + if (InVec.getOpcode() == ISD::BUILD_VECTOR && isa(EltNo)) { + unsigned Elt = cast(EltNo)->getZExtValue(); + SmallVector Ops(InVec.getNode()->op_begin(), + InVec.getNode()->op_end()); + if (Elt < Ops.size()) + Ops[Elt] = InVal; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + VT, &Ops[0], Ops.size()); + } + // If the invec is an UNDEF and if EltNo is a constant, create a new + // BUILD_VECTOR with undef elements and the inserted element. + if (InVec.getOpcode() == ISD::UNDEF && + isa(EltNo)) { + EVT EltVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + SmallVector Ops(NElts, DAG.getUNDEF(EltVT)); + + unsigned Elt = cast(EltNo)->getZExtValue(); + if (Elt < Ops.size()) + Ops[Elt] = InVal; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + VT, &Ops[0], Ops.size()); + } + return SDValue(); +} + +SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { + // (vextract (scalar_to_vector val, 0) -> val + SDValue InVec = N->getOperand(0); + + if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) { + // Check if the result type doesn't match the inserted element type. A + // SCALAR_TO_VECTOR may truncate the inserted element and the + // EXTRACT_VECTOR_ELT may widen the extracted vector. + SDValue InOp = InVec.getOperand(0); + EVT NVT = N->getValueType(0); + if (InOp.getValueType() != NVT) { + assert(InOp.getValueType().isInteger() && NVT.isInteger()); + return DAG.getSExtOrTrunc(InOp, InVec.getDebugLoc(), NVT); + } + return InOp; + } + + // Perform only after legalization to ensure build_vector / vector_shuffle + // optimizations have already been done. + if (!LegalOperations) return SDValue(); + + // (vextract (v4f32 load $addr), c) -> (f32 load $addr+c*size) + // (vextract (v4f32 s2v (f32 load $addr)), c) -> (f32 load $addr+c*size) + // (vextract (v4f32 shuffle (load $addr), <1,u,u,u>), 0) -> (f32 load $addr) + SDValue EltNo = N->getOperand(1); + + if (isa(EltNo)) { + int Elt = cast(EltNo)->getZExtValue(); + bool NewLoad = false; + bool BCNumEltsChanged = false; + EVT VT = InVec.getValueType(); + EVT ExtVT = VT.getVectorElementType(); + EVT LVT = ExtVT; + + if (InVec.getOpcode() == ISD::BITCAST) { + EVT BCVT = InVec.getOperand(0).getValueType(); + if (!BCVT.isVector() || ExtVT.bitsGT(BCVT.getVectorElementType())) + return SDValue(); + if (VT.getVectorNumElements() != BCVT.getVectorNumElements()) + BCNumEltsChanged = true; + InVec = InVec.getOperand(0); + ExtVT = BCVT.getVectorElementType(); + NewLoad = true; + } + + LoadSDNode *LN0 = NULL; + const ShuffleVectorSDNode *SVN = NULL; + if (ISD::isNormalLoad(InVec.getNode())) { + LN0 = cast(InVec); + } else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR && + InVec.getOperand(0).getValueType() == ExtVT && + ISD::isNormalLoad(InVec.getOperand(0).getNode())) { + LN0 = cast(InVec.getOperand(0)); + } else if ((SVN = dyn_cast(InVec))) { + // (vextract (vector_shuffle (load $addr), v2, <1, u, u, u>), 1) + // => + // (load $addr+1*size) + + // If the bit convert changed the number of elements, it is unsafe + // to examine the mask. + if (BCNumEltsChanged) + return SDValue(); + + // Select the input vector, guarding against out of range extract vector. + unsigned NumElems = VT.getVectorNumElements(); + int Idx = (Elt > (int)NumElems) ? -1 : SVN->getMaskElt(Elt); + InVec = (Idx < (int)NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); + + if (InVec.getOpcode() == ISD::BITCAST) + InVec = InVec.getOperand(0); + if (ISD::isNormalLoad(InVec.getNode())) { + LN0 = cast(InVec); + Elt = (Idx < (int)NumElems) ? Idx : Idx - (int)NumElems; + } + } + + if (!LN0 || !LN0->hasOneUse() || LN0->isVolatile()) + return SDValue(); + + // If Idx was -1 above, Elt is going to be -1, so just return undef. + if (Elt == -1) + return DAG.getUNDEF(LN0->getBasePtr().getValueType()); + + unsigned Align = LN0->getAlignment(); + if (NewLoad) { + // Check the resultant load doesn't need a higher alignment than the + // original load. + unsigned NewAlign = + TLI.getTargetData() + ->getABITypeAlignment(LVT.getTypeForEVT(*DAG.getContext())); + + if (NewAlign > Align || !TLI.isOperationLegalOrCustom(ISD::LOAD, LVT)) + return SDValue(); + + Align = NewAlign; + } + + SDValue NewPtr = LN0->getBasePtr(); + unsigned PtrOff = 0; + + if (Elt) { + PtrOff = LVT.getSizeInBits() * Elt / 8; + EVT PtrType = NewPtr.getValueType(); + if (TLI.isBigEndian()) + PtrOff = VT.getSizeInBits() / 8 - PtrOff; + NewPtr = DAG.getNode(ISD::ADD, N->getDebugLoc(), PtrType, NewPtr, + DAG.getConstant(PtrOff, PtrType)); + } + + return DAG.getLoad(LVT, N->getDebugLoc(), LN0->getChain(), NewPtr, + LN0->getPointerInfo().getWithOffset(PtrOff), + LN0->isVolatile(), LN0->isNonTemporal(), Align); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { + unsigned NumInScalars = N->getNumOperands(); + EVT VT = N->getValueType(0); + + // Check to see if this is a BUILD_VECTOR of a bunch of EXTRACT_VECTOR_ELT + // operations. If so, and if the EXTRACT_VECTOR_ELT vector inputs come from + // at most two distinct vectors, turn this into a shuffle node. + SDValue VecIn1, VecIn2; + for (unsigned i = 0; i != NumInScalars; ++i) { + // Ignore undef inputs. + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + + // If this input is something other than a EXTRACT_VECTOR_ELT with a + // constant index, bail out. + if (N->getOperand(i).getOpcode() != ISD::EXTRACT_VECTOR_ELT || + !isa(N->getOperand(i).getOperand(1))) { + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + + // If the input vector type disagrees with the result of the build_vector, + // we can't make a shuffle. + SDValue ExtractedFromVec = N->getOperand(i).getOperand(0); + if (ExtractedFromVec.getValueType() != VT) { + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + + // Otherwise, remember this. We allow up to two distinct input vectors. + if (ExtractedFromVec == VecIn1 || ExtractedFromVec == VecIn2) + continue; + + if (VecIn1.getNode() == 0) { + VecIn1 = ExtractedFromVec; + } else if (VecIn2.getNode() == 0) { + VecIn2 = ExtractedFromVec; + } else { + // Too many inputs. + VecIn1 = VecIn2 = SDValue(0, 0); + break; + } + } + + // If everything is good, we can make a shuffle operation. + if (VecIn1.getNode()) { + SmallVector Mask; + for (unsigned i = 0; i != NumInScalars; ++i) { + if (N->getOperand(i).getOpcode() == ISD::UNDEF) { + Mask.push_back(-1); + continue; + } + + // If extracting from the first vector, just use the index directly. + SDValue Extract = N->getOperand(i); + SDValue ExtVal = Extract.getOperand(1); + if (Extract.getOperand(0) == VecIn1) { + unsigned ExtIndex = cast(ExtVal)->getZExtValue(); + if (ExtIndex > VT.getVectorNumElements()) + return SDValue(); + + Mask.push_back(ExtIndex); + continue; + } + + // Otherwise, use InIdx + VecSize + unsigned Idx = cast(ExtVal)->getZExtValue(); + Mask.push_back(Idx+NumInScalars); + } + + // Add count and size info. + if (!isTypeLegal(VT)) + return SDValue(); + + // Return the new VECTOR_SHUFFLE node. + SDValue Ops[2]; + Ops[0] = VecIn1; + Ops[1] = VecIn2.getNode() ? VecIn2 : DAG.getUNDEF(VT); + return DAG.getVectorShuffle(VT, N->getDebugLoc(), Ops[0], Ops[1], &Mask[0]); + } + + return SDValue(); +} + +SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) { + // TODO: Check to see if this is a CONCAT_VECTORS of a bunch of + // EXTRACT_SUBVECTOR operations. If so, and if the EXTRACT_SUBVECTOR vector + // inputs come from at most two distinct vectors, turn this into a shuffle + // node. + + // If we only have one input vector, we don't need to do any concatenation. + if (N->getNumOperands() == 1) + return N->getOperand(0); + + return SDValue(); +} + +SDValue DAGCombiner::visitVECTOR_SHUFFLE(SDNode *N) { + EVT VT = N->getValueType(0); + unsigned NumElts = VT.getVectorNumElements(); + + SDValue N0 = N->getOperand(0); + + assert(N0.getValueType().getVectorNumElements() == NumElts && + "Vector shuffle must be normalized in DAG"); + + // FIXME: implement canonicalizations from DAG.getVectorShuffle() + + // If it is a splat, check if the argument vector is another splat or a + // build_vector with all scalar elements the same. + ShuffleVectorSDNode *SVN = cast(N); + if (SVN->isSplat() && SVN->getSplatIndex() < (int)NumElts) { + SDNode *V = N0.getNode(); + + // If this is a bit convert that changes the element type of the vector but + // not the number of vector elements, look through it. Be careful not to + // look though conversions that change things like v4f32 to v2f64. + if (V->getOpcode() == ISD::BITCAST) { + SDValue ConvInput = V->getOperand(0); + if (ConvInput.getValueType().isVector() && + ConvInput.getValueType().getVectorNumElements() == NumElts) + V = ConvInput.getNode(); + } + + if (V->getOpcode() == ISD::BUILD_VECTOR) { + assert(V->getNumOperands() == NumElts && + "BUILD_VECTOR has wrong number of operands"); + SDValue Base; + bool AllSame = true; + for (unsigned i = 0; i != NumElts; ++i) { + if (V->getOperand(i).getOpcode() != ISD::UNDEF) { + Base = V->getOperand(i); + break; + } + } + // Splat of , return + if (!Base.getNode()) + return N0; + for (unsigned i = 0; i != NumElts; ++i) { + if (V->getOperand(i) != Base) { + AllSame = false; + break; + } + } + // Splat of , return + if (AllSame) + return N0; + } + } + return SDValue(); +} + +SDValue DAGCombiner::visitMEMBARRIER(SDNode* N) { + if (!TLI.getShouldFoldAtomicFences()) + return SDValue(); + + SDValue atomic = N->getOperand(0); + switch (atomic.getOpcode()) { + case ISD::ATOMIC_CMP_SWAP: + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + break; + default: + return SDValue(); + } + + SDValue fence = atomic.getOperand(0); + if (fence.getOpcode() != ISD::MEMBARRIER) + return SDValue(); + + switch (atomic.getOpcode()) { + case ISD::ATOMIC_CMP_SWAP: + return SDValue(DAG.UpdateNodeOperands(atomic.getNode(), + fence.getOperand(0), + atomic.getOperand(1), atomic.getOperand(2), + atomic.getOperand(3)), atomic.getResNo()); + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + return SDValue(DAG.UpdateNodeOperands(atomic.getNode(), + fence.getOperand(0), + atomic.getOperand(1), atomic.getOperand(2)), + atomic.getResNo()); + default: + return SDValue(); + } +} + +/// XformToShuffleWithZero - Returns a vector_shuffle if it able to transform +/// an AND to a vector_shuffle with the destination vector and a zero vector. +/// e.g. AND V, <0xffffffff, 0, 0xffffffff, 0>. ==> +/// vector_shuffle V, Zero, <0, 4, 2, 4> +SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + if (N->getOpcode() == ISD::AND) { + if (RHS.getOpcode() == ISD::BITCAST) + RHS = RHS.getOperand(0); + if (RHS.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Indices; + unsigned NumElts = RHS.getNumOperands(); + for (unsigned i = 0; i != NumElts; ++i) { + SDValue Elt = RHS.getOperand(i); + if (!isa(Elt)) + return SDValue(); + else if (cast(Elt)->isAllOnesValue()) + Indices.push_back(i); + else if (cast(Elt)->isNullValue()) + Indices.push_back(NumElts); + else + return SDValue(); + } + + // Let's see if the target supports this vector_shuffle. + EVT RVT = RHS.getValueType(); + if (!TLI.isVectorClearMaskLegal(Indices, RVT)) + return SDValue(); + + // Return the new VECTOR_SHUFFLE node. + EVT EltVT = RVT.getVectorElementType(); + SmallVector ZeroOps(RVT.getVectorNumElements(), + DAG.getConstant(0, EltVT)); + SDValue Zero = DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + RVT, &ZeroOps[0], ZeroOps.size()); + LHS = DAG.getNode(ISD::BITCAST, dl, RVT, LHS); + SDValue Shuf = DAG.getVectorShuffle(RVT, dl, LHS, Zero, &Indices[0]); + return DAG.getNode(ISD::BITCAST, dl, VT, Shuf); + } + } + + return SDValue(); +} + +/// SimplifyVBinOp - Visit a binary vector operation, like ADD. +SDValue DAGCombiner::SimplifyVBinOp(SDNode *N) { + // After legalize, the target may be depending on adds and other + // binary ops to provide legal ways to construct constants or other + // things. Simplifying them may result in a loss of legality. + if (LegalOperations) return SDValue(); + + assert(N->getValueType(0).isVector() && + "SimplifyVBinOp only works on vectors!"); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + SDValue Shuffle = XformToShuffleWithZero(N); + if (Shuffle.getNode()) return Shuffle; + + // If the LHS and RHS are BUILD_VECTOR nodes, see if we can constant fold + // this operation. + if (LHS.getOpcode() == ISD::BUILD_VECTOR && + RHS.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Ops; + for (unsigned i = 0, e = LHS.getNumOperands(); i != e; ++i) { + SDValue LHSOp = LHS.getOperand(i); + SDValue RHSOp = RHS.getOperand(i); + // If these two elements can't be folded, bail out. + if ((LHSOp.getOpcode() != ISD::UNDEF && + LHSOp.getOpcode() != ISD::Constant && + LHSOp.getOpcode() != ISD::ConstantFP) || + (RHSOp.getOpcode() != ISD::UNDEF && + RHSOp.getOpcode() != ISD::Constant && + RHSOp.getOpcode() != ISD::ConstantFP)) + break; + + // Can't fold divide by zero. + if (N->getOpcode() == ISD::SDIV || N->getOpcode() == ISD::UDIV || + N->getOpcode() == ISD::FDIV) { + if ((RHSOp.getOpcode() == ISD::Constant && + cast(RHSOp.getNode())->isNullValue()) || + (RHSOp.getOpcode() == ISD::ConstantFP && + cast(RHSOp.getNode())->getValueAPF().isZero())) + break; + } + + EVT VT = LHSOp.getValueType(); + assert(RHSOp.getValueType() == VT && + "SimplifyVBinOp with different BUILD_VECTOR element types"); + SDValue FoldOp = DAG.getNode(N->getOpcode(), LHS.getDebugLoc(), VT, + LHSOp, RHSOp); + if (FoldOp.getOpcode() != ISD::UNDEF && + FoldOp.getOpcode() != ISD::Constant && + FoldOp.getOpcode() != ISD::ConstantFP) + break; + Ops.push_back(FoldOp); + AddToWorkList(FoldOp.getNode()); + } + + if (Ops.size() == LHS.getNumOperands()) + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + LHS.getValueType(), &Ops[0], Ops.size()); + } + + return SDValue(); +} + +SDValue DAGCombiner::SimplifySelect(DebugLoc DL, SDValue N0, + SDValue N1, SDValue N2){ + assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!"); + + SDValue SCC = SimplifySelectCC(DL, N0.getOperand(0), N0.getOperand(1), N1, N2, + cast(N0.getOperand(2))->get()); + + // If we got a simplified select_cc node back from SimplifySelectCC, then + // break it down into a new SETCC node, and a new SELECT node, and then return + // the SELECT node, since we were called with a SELECT node. + if (SCC.getNode()) { + // Check to see if we got a select_cc back (to turn into setcc/select). + // Otherwise, just return whatever node we got back, like fabs. + if (SCC.getOpcode() == ISD::SELECT_CC) { + SDValue SETCC = DAG.getNode(ISD::SETCC, N0.getDebugLoc(), + N0.getValueType(), + SCC.getOperand(0), SCC.getOperand(1), + SCC.getOperand(4)); + AddToWorkList(SETCC.getNode()); + return DAG.getNode(ISD::SELECT, SCC.getDebugLoc(), SCC.getValueType(), + SCC.getOperand(2), SCC.getOperand(3), SETCC); + } + + return SCC; + } + return SDValue(); +} + +/// SimplifySelectOps - Given a SELECT or a SELECT_CC node, where LHS and RHS +/// are the two values being selected between, see if we can simplify the +/// select. Callers of this should assume that TheSelect is deleted if this +/// returns true. As such, they should return the appropriate thing (e.g. the +/// node) back to the top-level of the DAG combiner loop to avoid it being +/// looked at. +bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, + SDValue RHS) { + + // Cannot simplify select with vector condition + if (TheSelect->getOperand(0).getValueType().isVector()) return false; + + // If this is a select from two identical things, try to pull the operation + // through the select. + if (LHS.getOpcode() != RHS.getOpcode() || + !LHS.hasOneUse() || !RHS.hasOneUse()) + return false; + + // If this is a load and the token chain is identical, replace the select + // of two loads with a load through a select of the address to load from. + // This triggers in things like "select bool X, 10.0, 123.0" after the FP + // constants have been dropped into the constant pool. + if (LHS.getOpcode() == ISD::LOAD) { + LoadSDNode *LLD = cast(LHS); + LoadSDNode *RLD = cast(RHS); + + // Token chains must be identical. + if (LHS.getOperand(0) != RHS.getOperand(0) || + // Do not let this transformation reduce the number of volatile loads. + LLD->isVolatile() || RLD->isVolatile() || + // If this is an EXTLOAD, the VT's must match. + LLD->getMemoryVT() != RLD->getMemoryVT() || + // If this is an EXTLOAD, the kind of extension must match. + (LLD->getExtensionType() != RLD->getExtensionType() && + // The only exception is if one of the extensions is anyext. + LLD->getExtensionType() != ISD::EXTLOAD && + RLD->getExtensionType() != ISD::EXTLOAD) || + // FIXME: this discards src value information. This is + // over-conservative. It would be beneficial to be able to remember + // both potential memory locations. Since we are discarding + // src value info, don't do the transformation if the memory + // locations are not in the default address space. + LLD->getPointerInfo().getAddrSpace() != 0 || + RLD->getPointerInfo().getAddrSpace() != 0) + return false; + + // Check that the select condition doesn't reach either load. If so, + // folding this will induce a cycle into the DAG. If not, this is safe to + // xform, so create a select of the addresses. + SDValue Addr; + if (TheSelect->getOpcode() == ISD::SELECT) { + SDNode *CondNode = TheSelect->getOperand(0).getNode(); + if ((LLD->hasAnyUseOfValue(1) && LLD->isPredecessorOf(CondNode)) || + (RLD->hasAnyUseOfValue(1) && RLD->isPredecessorOf(CondNode))) + return false; + Addr = DAG.getNode(ISD::SELECT, TheSelect->getDebugLoc(), + LLD->getBasePtr().getValueType(), + TheSelect->getOperand(0), LLD->getBasePtr(), + RLD->getBasePtr()); + } else { // Otherwise SELECT_CC + SDNode *CondLHS = TheSelect->getOperand(0).getNode(); + SDNode *CondRHS = TheSelect->getOperand(1).getNode(); + + if ((LLD->hasAnyUseOfValue(1) && + (LLD->isPredecessorOf(CondLHS) || LLD->isPredecessorOf(CondRHS))) || + (LLD->hasAnyUseOfValue(1) && + (LLD->isPredecessorOf(CondLHS) || LLD->isPredecessorOf(CondRHS)))) + return false; + + Addr = DAG.getNode(ISD::SELECT_CC, TheSelect->getDebugLoc(), + LLD->getBasePtr().getValueType(), + TheSelect->getOperand(0), + TheSelect->getOperand(1), + LLD->getBasePtr(), RLD->getBasePtr(), + TheSelect->getOperand(4)); + } + + SDValue Load; + if (LLD->getExtensionType() == ISD::NON_EXTLOAD) { + Load = DAG.getLoad(TheSelect->getValueType(0), + TheSelect->getDebugLoc(), + // FIXME: Discards pointer info. + LLD->getChain(), Addr, MachinePointerInfo(), + LLD->isVolatile(), LLD->isNonTemporal(), + LLD->getAlignment()); + } else { + Load = DAG.getExtLoad(LLD->getExtensionType() == ISD::EXTLOAD ? + RLD->getExtensionType() : LLD->getExtensionType(), + TheSelect->getDebugLoc(), + TheSelect->getValueType(0), + // FIXME: Discards pointer info. + LLD->getChain(), Addr, MachinePointerInfo(), + LLD->getMemoryVT(), LLD->isVolatile(), + LLD->isNonTemporal(), LLD->getAlignment()); + } + + // Users of the select now use the result of the load. + CombineTo(TheSelect, Load); + + // Users of the old loads now use the new load's chain. We know the + // old-load value is dead now. + CombineTo(LHS.getNode(), Load.getValue(0), Load.getValue(1)); + CombineTo(RHS.getNode(), Load.getValue(0), Load.getValue(1)); + return true; + } + + return false; +} + +/// SimplifySelectCC - Simplify an expression of the form (N0 cond N1) ? N2 : N3 +/// where 'cond' is the comparison specified by CC. +SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, + SDValue N2, SDValue N3, + ISD::CondCode CC, bool NotExtCompare) { + // (x ? y : y) -> y. + if (N2 == N3) return N2; + + EVT VT = N2.getValueType(); + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + ConstantSDNode *N2C = dyn_cast(N2.getNode()); + ConstantSDNode *N3C = dyn_cast(N3.getNode()); + + // Determine if the condition we're dealing with is constant + SDValue SCC = SimplifySetCC(TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC, DL, false); + if (SCC.getNode()) AddToWorkList(SCC.getNode()); + ConstantSDNode *SCCC = dyn_cast_or_null(SCC.getNode()); + + // fold select_cc true, x, y -> x + if (SCCC && !SCCC->isNullValue()) + return N2; + // fold select_cc false, x, y -> y + if (SCCC && SCCC->isNullValue()) + return N3; + + // Check to see if we can simplify the select into an fabs node + if (ConstantFPSDNode *CFP = dyn_cast(N1)) { + // Allow either -0.0 or 0.0 + if (CFP->getValueAPF().isZero()) { + // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs + if ((CC == ISD::SETGE || CC == ISD::SETGT) && + N0 == N2 && N3.getOpcode() == ISD::FNEG && + N2 == N3.getOperand(0)) + return DAG.getNode(ISD::FABS, DL, VT, N0); + + // select (setl[te] X, +/-0.0), fneg(X), X -> fabs + if ((CC == ISD::SETLT || CC == ISD::SETLE) && + N0 == N3 && N2.getOpcode() == ISD::FNEG && + N2.getOperand(0) == N3) + return DAG.getNode(ISD::FABS, DL, VT, N3); + } + } + + // Turn "(a cond b) ? 1.0f : 2.0f" into "load (tmp + ((a cond b) ? 0 : 4)" + // where "tmp" is a constant pool entry containing an array with 1.0 and 2.0 + // in it. This is a win when the constant is not otherwise available because + // it replaces two constant pool loads with one. We only do this if the FP + // type is known to be legal, because if it isn't, then we are before legalize + // types an we want the other legalization to happen first (e.g. to avoid + // messing with soft float) and if the ConstantFP is not legal, because if + // it is legal, we may not need to store the FP constant in a constant pool. + if (ConstantFPSDNode *TV = dyn_cast(N2)) + if (ConstantFPSDNode *FV = dyn_cast(N3)) { + if (TLI.isTypeLegal(N2.getValueType()) && + (TLI.getOperationAction(ISD::ConstantFP, N2.getValueType()) != + TargetLowering::Legal) && + // If both constants have multiple uses, then we won't need to do an + // extra load, they are likely around in registers for other users. + (TV->hasOneUse() || FV->hasOneUse())) { + Constant *Elts[] = { + const_cast(FV->getConstantFPValue()), + const_cast(TV->getConstantFPValue()) + }; + const Type *FPTy = Elts[0]->getType(); + const TargetData &TD = *TLI.getTargetData(); + + // Create a ConstantArray of the two constants. + Constant *CA = ConstantArray::get(ArrayType::get(FPTy, 2), Elts, 2); + SDValue CPIdx = DAG.getConstantPool(CA, TLI.getPointerTy(), + TD.getPrefTypeAlignment(FPTy)); + unsigned Alignment = cast(CPIdx)->getAlignment(); + + // Get the offsets to the 0 and 1 element of the array so that we can + // select between them. + SDValue Zero = DAG.getIntPtrConstant(0); + unsigned EltSize = (unsigned)TD.getTypeAllocSize(Elts[0]->getType()); + SDValue One = DAG.getIntPtrConstant(EltSize); + + SDValue Cond = DAG.getSetCC(DL, + TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC); + SDValue CstOffset = DAG.getNode(ISD::SELECT, DL, Zero.getValueType(), + Cond, One, Zero); + CPIdx = DAG.getNode(ISD::ADD, DL, TLI.getPointerTy(), CPIdx, + CstOffset); + return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), false, + false, Alignment); + + } + } + + // Check to see if we can perform the "gzip trick", transforming + // (select_cc setlt X, 0, A, 0) -> (and (sra X, (sub size(X), 1), A) + if (N1C && N3C && N3C->isNullValue() && CC == ISD::SETLT && + N0.getValueType().isInteger() && + N2.getValueType().isInteger() && + (N1C->isNullValue() || // (a < 0) ? b : 0 + (N1C->getAPIntValue() == 1 && N0 == N2))) { // (a < 1) ? a : 0 + EVT XType = N0.getValueType(); + EVT AType = N2.getValueType(); + if (XType.bitsGE(AType)) { + // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a + // single-bit constant. + if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) { + unsigned ShCtV = N2C->getAPIntValue().logBase2(); + ShCtV = XType.getSizeInBits()-ShCtV-1; + SDValue ShCt = DAG.getConstant(ShCtV, + getShiftAmountTy(N0.getValueType())); + SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), + XType, N0, ShCt); + AddToWorkList(Shift.getNode()); + + if (XType.bitsGT(AType)) { + Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift); + AddToWorkList(Shift.getNode()); + } + + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); + } + + SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), + XType, N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy(N0.getValueType()))); + AddToWorkList(Shift.getNode()); + + if (XType.bitsGT(AType)) { + Shift = DAG.getNode(ISD::TRUNCATE, DL, AType, Shift); + AddToWorkList(Shift.getNode()); + } + + return DAG.getNode(ISD::AND, DL, AType, Shift, N2); + } + } + + // fold (select_cc seteq (and x, y), 0, 0, A) -> (and (shr (shl x)) A) + // where y is has a single bit set. + // A plaintext description would be, we can turn the SELECT_CC into an AND + // when the condition can be materialized as an all-ones register. Any + // single bit-test can be materialized as an all-ones register with + // shift-left and shift-right-arith. + if (CC == ISD::SETEQ && N0->getOpcode() == ISD::AND && + N0->getValueType(0) == VT && + N1C && N1C->isNullValue() && + N2C && N2C->isNullValue()) { + SDValue AndLHS = N0->getOperand(0); + ConstantSDNode *ConstAndRHS = dyn_cast(N0->getOperand(1)); + if (ConstAndRHS && ConstAndRHS->getAPIntValue().countPopulation() == 1) { + // Shift the tested bit over the sign bit. + APInt AndMask = ConstAndRHS->getAPIntValue(); + SDValue ShlAmt = + DAG.getConstant(AndMask.countLeadingZeros(), + getShiftAmountTy(AndLHS.getValueType())); + SDValue Shl = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, AndLHS, ShlAmt); + + // Now arithmetic right shift it all the way over, so the result is either + // all-ones, or zero. + SDValue ShrAmt = + DAG.getConstant(AndMask.getBitWidth()-1, + getShiftAmountTy(Shl.getValueType())); + SDValue Shr = DAG.getNode(ISD::SRA, N0.getDebugLoc(), VT, Shl, ShrAmt); + + return DAG.getNode(ISD::AND, DL, VT, Shr, N3); + } + } + + // fold select C, 16, 0 -> shl C, 4 + if (N2C && N3C && N3C->isNullValue() && N2C->getAPIntValue().isPowerOf2() && + TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent) { + + // If the caller doesn't want us to simplify this into a zext of a compare, + // don't do it. + if (NotExtCompare && N2C->getAPIntValue() == 1) + return SDValue(); + + // Get a SetCC of the condition + // FIXME: Should probably make sure that setcc is legal if we ever have a + // target where it isn't. + SDValue Temp, SCC; + // cast from setcc result type to select result type + if (LegalTypes) { + SCC = DAG.getSetCC(DL, TLI.getSetCCResultType(N0.getValueType()), + N0, N1, CC); + if (N2.getValueType().bitsLT(SCC.getValueType())) + Temp = DAG.getZeroExtendInReg(SCC, N2.getDebugLoc(), N2.getValueType()); + else + Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(), + N2.getValueType(), SCC); + } else { + SCC = DAG.getSetCC(N0.getDebugLoc(), MVT::i1, N0, N1, CC); + Temp = DAG.getNode(ISD::ZERO_EXTEND, N2.getDebugLoc(), + N2.getValueType(), SCC); + } + + AddToWorkList(SCC.getNode()); + AddToWorkList(Temp.getNode()); + + if (N2C->getAPIntValue() == 1) + return Temp; + + // shl setcc result by log2 n2c + return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp, + DAG.getConstant(N2C->getAPIntValue().logBase2(), + getShiftAmountTy(Temp.getValueType()))); + } + + // Check to see if this is the equivalent of setcc + // FIXME: Turn all of these into setcc if setcc if setcc is legal + // otherwise, go ahead with the folds. + if (0 && N3C && N3C->isNullValue() && N2C && (N2C->getAPIntValue() == 1ULL)) { + EVT XType = N0.getValueType(); + if (!LegalOperations || + TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultType(XType))) { + SDValue Res = DAG.getSetCC(DL, TLI.getSetCCResultType(XType), N0, N1, CC); + if (Res.getValueType() != VT) + Res = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Res); + return Res; + } + + // fold (seteq X, 0) -> (srl (ctlz X, log2(size(X)))) + if (N1C && N1C->isNullValue() && CC == ISD::SETEQ && + (!LegalOperations || + TLI.isOperationLegal(ISD::CTLZ, XType))) { + SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0); + return DAG.getNode(ISD::SRL, DL, XType, Ctlz, + DAG.getConstant(Log2_32(XType.getSizeInBits()), + getShiftAmountTy(Ctlz.getValueType()))); + } + // fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1)) + if (N1C && N1C->isNullValue() && CC == ISD::SETGT) { + SDValue NegN0 = DAG.getNode(ISD::SUB, N0.getDebugLoc(), + XType, DAG.getConstant(0, XType), N0); + SDValue NotN0 = DAG.getNOT(N0.getDebugLoc(), N0, XType); + return DAG.getNode(ISD::SRL, DL, XType, + DAG.getNode(ISD::AND, DL, XType, NegN0, NotN0), + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy(XType))); + } + // fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1)) + if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) { + SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy(N0.getValueType()))); + return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType)); + } + } + + // Check to see if this is an integer abs. + // select_cc setg[te] X, 0, X, -X -> + // select_cc setgt X, -1, X, -X -> + // select_cc setl[te] X, 0, -X, X -> + // select_cc setlt X, 1, -X, X -> + // Y = sra (X, size(X)-1); xor (add (X, Y), Y) + if (N1C) { + ConstantSDNode *SubC = NULL; + if (((N1C->isNullValue() && (CC == ISD::SETGT || CC == ISD::SETGE)) || + (N1C->isAllOnesValue() && CC == ISD::SETGT)) && + N0 == N2 && N3.getOpcode() == ISD::SUB && N0 == N3.getOperand(1)) + SubC = dyn_cast(N3.getOperand(0)); + else if (((N1C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE)) || + (N1C->isOne() && CC == ISD::SETLT)) && + N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1)) + SubC = dyn_cast(N2.getOperand(0)); + + EVT XType = N0.getValueType(); + if (SubC && SubC->isNullValue() && XType.isInteger()) { + SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, + N0, + DAG.getConstant(XType.getSizeInBits()-1, + getShiftAmountTy(N0.getValueType()))); + SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), + XType, N0, Shift); + AddToWorkList(Shift.getNode()); + AddToWorkList(Add.getNode()); + return DAG.getNode(ISD::XOR, DL, XType, Add, Shift); + } + } + + return SDValue(); +} + +/// SimplifySetCC - This is a stub for TargetLowering::SimplifySetCC. +SDValue DAGCombiner::SimplifySetCC(EVT VT, SDValue N0, + SDValue N1, ISD::CondCode Cond, + DebugLoc DL, bool foldBooleans) { + TargetLowering::DAGCombinerInfo + DagCombineInfo(DAG, !LegalTypes, !LegalOperations, false, this); + return TLI.SimplifySetCC(VT, N0, N1, Cond, foldBooleans, DagCombineInfo, DL); +} + +/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue DAGCombiner::BuildSDIV(SDNode *N) { + std::vector Built; + SDValue S = TLI.BuildSDIV(N, DAG, &Built); + + for (std::vector::iterator ii = Built.begin(), ee = Built.end(); + ii != ee; ++ii) + AddToWorkList(*ii); + return S; +} + +/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue DAGCombiner::BuildUDIV(SDNode *N) { + std::vector Built; + SDValue S = TLI.BuildUDIV(N, DAG, &Built); + + for (std::vector::iterator ii = Built.begin(), ee = Built.end(); + ii != ee; ++ii) + AddToWorkList(*ii); + return S; +} + +/// FindBaseOffset - Return true if base is a frame index, which is known not +// to alias with anything but itself. Provides base object and offset as +// results. +static bool FindBaseOffset(SDValue Ptr, SDValue &Base, int64_t &Offset, + const GlobalValue *&GV, void *&CV) { + // Assume it is a primitive operation. + Base = Ptr; Offset = 0; GV = 0; CV = 0; + + // If it's an adding a simple constant then integrate the offset. + if (Base.getOpcode() == ISD::ADD) { + if (ConstantSDNode *C = dyn_cast(Base.getOperand(1))) { + Base = Base.getOperand(0); + Offset += C->getZExtValue(); + } + } + + // Return the underlying GlobalValue, and update the Offset. Return false + // for GlobalAddressSDNode since the same GlobalAddress may be represented + // by multiple nodes with different offsets. + if (GlobalAddressSDNode *G = dyn_cast(Base)) { + GV = G->getGlobal(); + Offset += G->getOffset(); + return false; + } + + // Return the underlying Constant value, and update the Offset. Return false + // for ConstantSDNodes since the same constant pool entry may be represented + // by multiple nodes with different offsets. + if (ConstantPoolSDNode *C = dyn_cast(Base)) { + CV = C->isMachineConstantPoolEntry() ? (void *)C->getMachineCPVal() + : (void *)C->getConstVal(); + Offset += C->getOffset(); + return false; + } + // If it's any of the following then it can't alias with anything but itself. + return isa(Base); +} + +/// isAlias - Return true if there is any possibility that the two addresses +/// overlap. +bool DAGCombiner::isAlias(SDValue Ptr1, int64_t Size1, + const Value *SrcValue1, int SrcValueOffset1, + unsigned SrcValueAlign1, + const MDNode *TBAAInfo1, + SDValue Ptr2, int64_t Size2, + const Value *SrcValue2, int SrcValueOffset2, + unsigned SrcValueAlign2, + const MDNode *TBAAInfo2) const { + // If they are the same then they must be aliases. + if (Ptr1 == Ptr2) return true; + + // Gather base node and offset information. + SDValue Base1, Base2; + int64_t Offset1, Offset2; + const GlobalValue *GV1, *GV2; + void *CV1, *CV2; + bool isFrameIndex1 = FindBaseOffset(Ptr1, Base1, Offset1, GV1, CV1); + bool isFrameIndex2 = FindBaseOffset(Ptr2, Base2, Offset2, GV2, CV2); + + // If they have a same base address then check to see if they overlap. + if (Base1 == Base2 || (GV1 && (GV1 == GV2)) || (CV1 && (CV1 == CV2))) + return !((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1); + + // It is possible for different frame indices to alias each other, mostly + // when tail call optimization reuses return address slots for arguments. + // To catch this case, look up the actual index of frame indices to compute + // the real alias relationship. + if (isFrameIndex1 && isFrameIndex2) { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + Offset1 += MFI->getObjectOffset(cast(Base1)->getIndex()); + Offset2 += MFI->getObjectOffset(cast(Base2)->getIndex()); + return !((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1); + } + + // Otherwise, if we know what the bases are, and they aren't identical, then + // we know they cannot alias. + if ((isFrameIndex1 || CV1 || GV1) && (isFrameIndex2 || CV2 || GV2)) + return false; + + // If we know required SrcValue1 and SrcValue2 have relatively large alignment + // compared to the size and offset of the access, we may be able to prove they + // do not alias. This check is conservative for now to catch cases created by + // splitting vector types. + if ((SrcValueAlign1 == SrcValueAlign2) && + (SrcValueOffset1 != SrcValueOffset2) && + (Size1 == Size2) && (SrcValueAlign1 > Size1)) { + int64_t OffAlign1 = SrcValueOffset1 % SrcValueAlign1; + int64_t OffAlign2 = SrcValueOffset2 % SrcValueAlign1; + + // There is no overlap between these relatively aligned accesses of similar + // size, return no alias. + if ((OffAlign1 + Size1) <= OffAlign2 || (OffAlign2 + Size2) <= OffAlign1) + return false; + } + + if (CombinerGlobalAA) { + // Use alias analysis information. + int64_t MinOffset = std::min(SrcValueOffset1, SrcValueOffset2); + int64_t Overlap1 = Size1 + SrcValueOffset1 - MinOffset; + int64_t Overlap2 = Size2 + SrcValueOffset2 - MinOffset; + AliasAnalysis::AliasResult AAResult = + AA.alias(AliasAnalysis::Location(SrcValue1, Overlap1, TBAAInfo1), + AliasAnalysis::Location(SrcValue2, Overlap2, TBAAInfo2)); + if (AAResult == AliasAnalysis::NoAlias) + return false; + } + + // Otherwise we have to assume they alias. + return true; +} + +/// FindAliasInfo - Extracts the relevant alias information from the memory +/// node. Returns true if the operand was a load. +bool DAGCombiner::FindAliasInfo(SDNode *N, + SDValue &Ptr, int64_t &Size, + const Value *&SrcValue, + int &SrcValueOffset, + unsigned &SrcValueAlign, + const MDNode *&TBAAInfo) const { + if (LoadSDNode *LD = dyn_cast(N)) { + Ptr = LD->getBasePtr(); + Size = LD->getMemoryVT().getSizeInBits() >> 3; + SrcValue = LD->getSrcValue(); + SrcValueOffset = LD->getSrcValueOffset(); + SrcValueAlign = LD->getOriginalAlignment(); + TBAAInfo = LD->getTBAAInfo(); + return true; + } else if (StoreSDNode *ST = dyn_cast(N)) { + Ptr = ST->getBasePtr(); + Size = ST->getMemoryVT().getSizeInBits() >> 3; + SrcValue = ST->getSrcValue(); + SrcValueOffset = ST->getSrcValueOffset(); + SrcValueAlign = ST->getOriginalAlignment(); + TBAAInfo = ST->getTBAAInfo(); + } else { + llvm_unreachable("FindAliasInfo expected a memory operand"); + } + + return false; +} + +/// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes, +/// looking for aliasing nodes and adding them to the Aliases vector. +void DAGCombiner::GatherAllAliases(SDNode *N, SDValue OriginalChain, + SmallVector &Aliases) { + SmallVector Chains; // List of chains to visit. + SmallPtrSet Visited; // Visited node set. + + // Get alias information for node. + SDValue Ptr; + int64_t Size; + const Value *SrcValue; + int SrcValueOffset; + unsigned SrcValueAlign; + const MDNode *SrcTBAAInfo; + bool IsLoad = FindAliasInfo(N, Ptr, Size, SrcValue, SrcValueOffset, + SrcValueAlign, SrcTBAAInfo); + + // Starting off. + Chains.push_back(OriginalChain); + unsigned Depth = 0; + + // Look at each chain and determine if it is an alias. If so, add it to the + // aliases list. If not, then continue up the chain looking for the next + // candidate. + while (!Chains.empty()) { + SDValue Chain = Chains.back(); + Chains.pop_back(); + + // For TokenFactor nodes, look at each operand and only continue up the + // chain until we find two aliases. If we've seen two aliases, assume we'll + // find more and revert to original chain since the xform is unlikely to be + // profitable. + // + // FIXME: The depth check could be made to return the last non-aliasing + // chain we found before we hit a tokenfactor rather than the original + // chain. + if (Depth > 6 || Aliases.size() == 2) { + Aliases.clear(); + Aliases.push_back(OriginalChain); + break; + } + + // Don't bother if we've been before. + if (!Visited.insert(Chain.getNode())) + continue; + + switch (Chain.getOpcode()) { + case ISD::EntryToken: + // Entry token is ideal chain operand, but handled in FindBetterChain. + break; + + case ISD::LOAD: + case ISD::STORE: { + // Get alias information for Chain. + SDValue OpPtr; + int64_t OpSize; + const Value *OpSrcValue; + int OpSrcValueOffset; + unsigned OpSrcValueAlign; + const MDNode *OpSrcTBAAInfo; + bool IsOpLoad = FindAliasInfo(Chain.getNode(), OpPtr, OpSize, + OpSrcValue, OpSrcValueOffset, + OpSrcValueAlign, + OpSrcTBAAInfo); + + // If chain is alias then stop here. + if (!(IsLoad && IsOpLoad) && + isAlias(Ptr, Size, SrcValue, SrcValueOffset, SrcValueAlign, + SrcTBAAInfo, + OpPtr, OpSize, OpSrcValue, OpSrcValueOffset, + OpSrcValueAlign, OpSrcTBAAInfo)) { + Aliases.push_back(Chain); + } else { + // Look further up the chain. + Chains.push_back(Chain.getOperand(0)); + ++Depth; + } + break; + } + + case ISD::TokenFactor: + // We have to check each of the operands of the token factor for "small" + // token factors, so we queue them up. Adding the operands to the queue + // (stack) in reverse order maintains the original order and increases the + // likelihood that getNode will find a matching token factor (CSE.) + if (Chain.getNumOperands() > 16) { + Aliases.push_back(Chain); + break; + } + for (unsigned n = Chain.getNumOperands(); n;) + Chains.push_back(Chain.getOperand(--n)); + ++Depth; + break; + + default: + // For all other instructions we will just have to take what we can get. + Aliases.push_back(Chain); + break; + } + } +} + +/// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, looking +/// for a better chain (aliasing node.) +SDValue DAGCombiner::FindBetterChain(SDNode *N, SDValue OldChain) { + SmallVector Aliases; // Ops for replacing token factor. + + // Accumulate all the aliases to this node. + GatherAllAliases(N, OldChain, Aliases); + + if (Aliases.size() == 0) { + // If no operands then chain to entry token. + return DAG.getEntryNode(); + } else if (Aliases.size() == 1) { + // If a single operand then chain to it. We don't need to revisit it. + return Aliases[0]; + } + + // Construct a custom tailored token factor. + return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, + &Aliases[0], Aliases.size()); +} + +// SelectionDAG::Combine - This is the entry point for the file. +// +void SelectionDAG::Combine(CombineLevel Level, AliasAnalysis &AA, + CodeGenOpt::Level OptLevel) { + /// run - This is the main entry point to this class. + /// + DAGCombiner(*this, AA, OptLevel).Run(Level); +} diff --git a/final/lib/CodeGen/SelectionDAG/FastISel.cpp b/final/lib/CodeGen/SelectionDAG/FastISel.cpp new file mode 100644 index 00000000000..490b857b0e9 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -0,0 +1,1251 @@ +//===-- FastISel.cpp - Implementation of the FastISel class ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of the FastISel class. +// +// "Fast" instruction selection is designed to emit very poor code quickly. +// Also, it is not designed to be able to do much lowering, so most illegal +// types (e.g. i64 on 32-bit targets) and operations are not supported. It is +// also not intended to be able to do much optimization, except in a few cases +// where doing optimizations reduces overall compile time. For example, folding +// constants into immediate fields is often done, because it's cheap and it +// reduces the number of instructions later phases have to examine. +// +// "Fast" instruction selection is able to fail gracefully and transfer +// control to the SelectionDAG selector for operations that it doesn't +// support. In many cases, this allows us to avoid duplicating a lot of +// the complicated lowering logic that SelectionDAG currently has. +// +// The intended use for "fast" instruction selection is "-O0" mode +// compilation, where the quality of the generated code is irrelevant when +// weighed against the speed at which the code can be generated. Also, +// at -O0, the LLVM optimizers are not running, and this makes the +// compile time of codegen a much higher portion of the overall compile +// time. Despite its limitations, "fast" instruction selection is able to +// handle enough code on its own to provide noticeable overall speedups +// in -O0 compiles. +// +// Basic operations are supported in a target-independent way, by reading +// the same instruction descriptions that the SelectionDAG selector reads, +// and identifying simple arithmetic operations that can be directly selected +// from simple operators. More complicated operations currently require +// target-specific code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/Loads.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +/// startNewBlock - Set the current block to which generated machine +/// instructions will be appended, and clear the local CSE map. +/// +void FastISel::startNewBlock() { + LocalValueMap.clear(); + + // Start out as null, meaining no local-value instructions have + // been emitted. + LastLocalValue = 0; + + // Advance the last local value past any EH_LABEL instructions. + MachineBasicBlock::iterator + I = FuncInfo.MBB->begin(), E = FuncInfo.MBB->end(); + while (I != E && I->getOpcode() == TargetOpcode::EH_LABEL) { + LastLocalValue = I; + ++I; + } +} + +bool FastISel::hasTrivialKill(const Value *V) const { + // Don't consider constants or arguments to have trivial kills. + const Instruction *I = dyn_cast(V); + if (!I) + return false; + + // No-op casts are trivially coalesced by fast-isel. + if (const CastInst *Cast = dyn_cast(I)) + if (Cast->isNoopCast(TD.getIntPtrType(Cast->getContext())) && + !hasTrivialKill(Cast->getOperand(0))) + return false; + + // Only instructions with a single use in the same basic block are considered + // to have trivial kills. + return I->hasOneUse() && + !(I->getOpcode() == Instruction::BitCast || + I->getOpcode() == Instruction::PtrToInt || + I->getOpcode() == Instruction::IntToPtr) && + cast(*I->use_begin())->getParent() == I->getParent(); +} + +unsigned FastISel::getRegForValue(const Value *V) { + EVT RealVT = TLI.getValueType(V->getType(), /*AllowUnknown=*/true); + // Don't handle non-simple values in FastISel. + if (!RealVT.isSimple()) + return 0; + + // Ignore illegal types. We must do this before looking up the value + // in ValueMap because Arguments are given virtual registers regardless + // of whether FastISel can handle them. + MVT VT = RealVT.getSimpleVT(); + if (!TLI.isTypeLegal(VT)) { + // Promote MVT::i1 to a legal type though, because it's common and easy. + if (VT == MVT::i1) + VT = TLI.getTypeToTransformTo(V->getContext(), VT).getSimpleVT(); + else + return 0; + } + + // Look up the value to see if we already have a register for it. We + // cache values defined by Instructions across blocks, and other values + // only locally. This is because Instructions already have the SSA + // def-dominates-use requirement enforced. + DenseMap::iterator I = FuncInfo.ValueMap.find(V); + if (I != FuncInfo.ValueMap.end()) { + unsigned Reg = I->second; + return Reg; + } + unsigned Reg = LocalValueMap[V]; + if (Reg != 0) + return Reg; + + // In bottom-up mode, just create the virtual register which will be used + // to hold the value. It will be materialized later. + if (isa(V) && + (!isa(V) || + !FuncInfo.StaticAllocaMap.count(cast(V)))) + return FuncInfo.InitializeRegForValue(V); + + SavePoint SaveInsertPt = enterLocalValueArea(); + + // Materialize the value in a register. Emit any instructions in the + // local value area. + Reg = materializeRegForValue(V, VT); + + leaveLocalValueArea(SaveInsertPt); + + return Reg; +} + +/// materializeRegForValue - Helper for getRegForValue. This function is +/// called when the value isn't already available in a register and must +/// be materialized with new instructions. +unsigned FastISel::materializeRegForValue(const Value *V, MVT VT) { + unsigned Reg = 0; + + if (const ConstantInt *CI = dyn_cast(V)) { + if (CI->getValue().getActiveBits() <= 64) + Reg = FastEmit_i(VT, VT, ISD::Constant, CI->getZExtValue()); + } else if (isa(V)) { + Reg = TargetMaterializeAlloca(cast(V)); + } else if (isa(V)) { + // Translate this as an integer zero so that it can be + // local-CSE'd with actual integer zeros. + Reg = + getRegForValue(Constant::getNullValue(TD.getIntPtrType(V->getContext()))); + } else if (const ConstantFP *CF = dyn_cast(V)) { + // Try to emit the constant directly. + Reg = FastEmit_f(VT, VT, ISD::ConstantFP, CF); + + if (!Reg) { + // Try to emit the constant by using an integer constant with a cast. + const APFloat &Flt = CF->getValueAPF(); + EVT IntVT = TLI.getPointerTy(); + + uint64_t x[2]; + uint32_t IntBitWidth = IntVT.getSizeInBits(); + bool isExact; + (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, + APFloat::rmTowardZero, &isExact); + if (isExact) { + APInt IntVal(IntBitWidth, 2, x); + + unsigned IntegerReg = + getRegForValue(ConstantInt::get(V->getContext(), IntVal)); + if (IntegerReg != 0) + Reg = FastEmit_r(IntVT.getSimpleVT(), VT, ISD::SINT_TO_FP, + IntegerReg, /*Kill=*/false); + } + } + } else if (const Operator *Op = dyn_cast(V)) { + if (!SelectOperator(Op, Op->getOpcode())) + if (!isa(Op) || + !TargetSelectInstruction(cast(Op))) + return 0; + Reg = lookUpRegForValue(Op); + } else if (isa(V)) { + Reg = createResultReg(TLI.getRegClassFor(VT)); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::IMPLICIT_DEF), Reg); + } + + // If target-independent code couldn't handle the value, give target-specific + // code a try. + if (!Reg && isa(V)) + Reg = TargetMaterializeConstant(cast(V)); + + // Don't cache constant materializations in the general ValueMap. + // To do so would require tracking what uses they dominate. + if (Reg != 0) { + LocalValueMap[V] = Reg; + LastLocalValue = MRI.getVRegDef(Reg); + } + return Reg; +} + +unsigned FastISel::lookUpRegForValue(const Value *V) { + // Look up the value to see if we already have a register for it. We + // cache values defined by Instructions across blocks, and other values + // only locally. This is because Instructions already have the SSA + // def-dominates-use requirement enforced. + DenseMap::iterator I = FuncInfo.ValueMap.find(V); + if (I != FuncInfo.ValueMap.end()) + return I->second; + return LocalValueMap[V]; +} + +/// UpdateValueMap - Update the value map to include the new mapping for this +/// instruction, or insert an extra copy to get the result in a previous +/// determined register. +/// NOTE: This is only necessary because we might select a block that uses +/// a value before we select the block that defines the value. It might be +/// possible to fix this by selecting blocks in reverse postorder. +unsigned FastISel::UpdateValueMap(const Value *I, unsigned Reg) { + if (!isa(I)) { + LocalValueMap[I] = Reg; + return Reg; + } + + unsigned &AssignedReg = FuncInfo.ValueMap[I]; + if (AssignedReg == 0) + // Use the new register. + AssignedReg = Reg; + else if (Reg != AssignedReg) { + // Arrange for uses of AssignedReg to be replaced by uses of Reg. + FuncInfo.RegFixups[AssignedReg] = Reg; + + AssignedReg = Reg; + } + + return AssignedReg; +} + +std::pair FastISel::getRegForGEPIndex(const Value *Idx) { + unsigned IdxN = getRegForValue(Idx); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return std::pair(0, false); + + bool IdxNIsKill = hasTrivialKill(Idx); + + // If the index is smaller or larger than intptr_t, truncate or extend it. + MVT PtrVT = TLI.getPointerTy(); + EVT IdxVT = EVT::getEVT(Idx->getType(), /*HandleUnknown=*/false); + if (IdxVT.bitsLT(PtrVT)) { + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::SIGN_EXTEND, + IdxN, IdxNIsKill); + IdxNIsKill = true; + } + else if (IdxVT.bitsGT(PtrVT)) { + IdxN = FastEmit_r(IdxVT.getSimpleVT(), PtrVT, ISD::TRUNCATE, + IdxN, IdxNIsKill); + IdxNIsKill = true; + } + return std::pair(IdxN, IdxNIsKill); +} + +void FastISel::recomputeInsertPt() { + if (getLastLocalValue()) { + FuncInfo.InsertPt = getLastLocalValue(); + FuncInfo.MBB = FuncInfo.InsertPt->getParent(); + ++FuncInfo.InsertPt; + } else + FuncInfo.InsertPt = FuncInfo.MBB->getFirstNonPHI(); + + // Now skip past any EH_LABELs, which must remain at the beginning. + while (FuncInfo.InsertPt != FuncInfo.MBB->end() && + FuncInfo.InsertPt->getOpcode() == TargetOpcode::EH_LABEL) + ++FuncInfo.InsertPt; +} + +FastISel::SavePoint FastISel::enterLocalValueArea() { + MachineBasicBlock::iterator OldInsertPt = FuncInfo.InsertPt; + DebugLoc OldDL = DL; + recomputeInsertPt(); + DL = DebugLoc(); + SavePoint SP = { OldInsertPt, OldDL }; + return SP; +} + +void FastISel::leaveLocalValueArea(SavePoint OldInsertPt) { + if (FuncInfo.InsertPt != FuncInfo.MBB->begin()) + LastLocalValue = llvm::prior(FuncInfo.InsertPt); + + // Restore the previous insert position. + FuncInfo.InsertPt = OldInsertPt.InsertPt; + DL = OldInsertPt.DL; +} + +/// SelectBinaryOp - Select and emit code for a binary operator instruction, +/// which has an opcode which directly corresponds to the given ISD opcode. +/// +bool FastISel::SelectBinaryOp(const User *I, unsigned ISDOpcode) { + EVT VT = EVT::getEVT(I->getType(), /*HandleUnknown=*/true); + if (VT == MVT::Other || !VT.isSimple()) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // We only handle legal types. For example, on x86-32 the instruction + // selector contains all of the 64-bit instructions from x86-64, + // under the assumption that i64 won't be used if the target doesn't + // support it. + if (!TLI.isTypeLegal(VT)) { + // MVT::i1 is special. Allow AND, OR, or XOR because they + // don't require additional zeroing, which makes them easy. + if (VT == MVT::i1 && + (ISDOpcode == ISD::AND || ISDOpcode == ISD::OR || + ISDOpcode == ISD::XOR)) + VT = TLI.getTypeToTransformTo(I->getContext(), VT); + else + return false; + } + + unsigned Op0 = getRegForValue(I->getOperand(0)); + if (Op0 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + bool Op0IsKill = hasTrivialKill(I->getOperand(0)); + + // Check if the second operand is a constant and handle it appropriately. + if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { + unsigned ResultReg = FastEmit_ri(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, Op0, Op0IsKill, + CI->getZExtValue()); + if (ResultReg != 0) { + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; + } + } + + // Check if the second operand is a constant float. + if (ConstantFP *CF = dyn_cast(I->getOperand(1))) { + unsigned ResultReg = FastEmit_rf(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, Op0, Op0IsKill, CF); + if (ResultReg != 0) { + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; + } + } + + unsigned Op1 = getRegForValue(I->getOperand(1)); + if (Op1 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + bool Op1IsKill = hasTrivialKill(I->getOperand(1)); + + // Now we have both operands in registers. Emit the instruction. + unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), VT.getSimpleVT(), + ISDOpcode, + Op0, Op0IsKill, + Op1, Op1IsKill); + if (ResultReg == 0) + // Target-specific code wasn't able to find a machine opcode for + // the given ISD opcode and type. Halt "fast" selection and bail. + return false; + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, ResultReg); + return true; +} + +bool FastISel::SelectGetElementPtr(const User *I) { + unsigned N = getRegForValue(I->getOperand(0)); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + bool NIsKill = hasTrivialKill(I->getOperand(0)); + + const Type *Ty = I->getOperand(0)->getType(); + MVT VT = TLI.getPointerTy(); + for (GetElementPtrInst::const_op_iterator OI = I->op_begin()+1, + E = I->op_end(); OI != E; ++OI) { + const Value *Idx = *OI; + if (const StructType *StTy = dyn_cast(Ty)) { + unsigned Field = cast(Idx)->getZExtValue(); + if (Field) { + // N = N + Offset + uint64_t Offs = TD.getStructLayout(StTy)->getElementOffset(Field); + // FIXME: This can be optimized by combining the add with a + // subsequent one. + N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + NIsKill = true; + } + Ty = StTy->getElementType(Field); + } else { + Ty = cast(Ty)->getElementType(); + + // If this is a constant subscript, handle it quickly. + if (const ConstantInt *CI = dyn_cast(Idx)) { + if (CI->isZero()) continue; + uint64_t Offs = + TD.getTypeAllocSize(Ty)*cast(CI)->getSExtValue(); + N = FastEmit_ri_(VT, ISD::ADD, N, NIsKill, Offs, VT); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + NIsKill = true; + continue; + } + + // N = N + Idx * ElementSize; + uint64_t ElementSize = TD.getTypeAllocSize(Ty); + std::pair Pair = getRegForGEPIndex(Idx); + unsigned IdxN = Pair.first; + bool IdxNIsKill = Pair.second; + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + if (ElementSize != 1) { + IdxN = FastEmit_ri_(VT, ISD::MUL, IdxN, IdxNIsKill, ElementSize, VT); + if (IdxN == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + IdxNIsKill = true; + } + N = FastEmit_rr(VT, VT, ISD::ADD, N, NIsKill, IdxN, IdxNIsKill); + if (N == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + } + } + + // We successfully emitted code for the given LLVM Instruction. + UpdateValueMap(I, N); + return true; +} + +bool FastISel::SelectCall(const User *I) { + const Function *F = cast(I)->getCalledFunction(); + if (!F) return false; + + // Handle selected intrinsic function calls. + unsigned IID = F->getIntrinsicID(); + switch (IID) { + default: break; + case Intrinsic::dbg_declare: { + const DbgDeclareInst *DI = cast(I); + if (!DIVariable(DI->getVariable()).Verify() || + !FuncInfo.MF->getMMI().hasDebugInfo()) + return true; + + const Value *Address = DI->getAddress(); + if (!Address || isa(Address) || isa(Address)) + return true; + + unsigned Reg = 0; + unsigned Offset = 0; + if (const Argument *Arg = dyn_cast(Address)) { + if (Arg->hasByValAttr()) { + // Byval arguments' frame index is recorded during argument lowering. + // Use this info directly. + Offset = FuncInfo.getByValArgumentFrameIndex(Arg); + if (Offset) + Reg = TRI.getFrameRegister(*FuncInfo.MF); + } + } + if (!Reg) + Reg = getRegForValue(Address); + + if (Reg) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::DBG_VALUE)) + .addReg(Reg, RegState::Debug).addImm(Offset) + .addMetadata(DI->getVariable()); + return true; + } + case Intrinsic::dbg_value: { + // This form of DBG_VALUE is target-independent. + const DbgValueInst *DI = cast(I); + const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + const Value *V = DI->getValue(); + if (!V) { + // Currently the optimizer can produce this; insert an undef to + // help debugging. Probably the optimizer should not do this. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(0U).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); + } else if (const ConstantInt *CI = dyn_cast(V)) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addImm(CI->getZExtValue()).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); + } else if (const ConstantFP *CF = dyn_cast(V)) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addFPImm(CF).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); + } else if (unsigned Reg = lookUpRegForValue(V)) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Reg, RegState::Debug).addImm(DI->getOffset()) + .addMetadata(DI->getVariable()); + } else { + // We can't yet handle anything else here because it would require + // generating code, thus altering codegen because of debug info. + DEBUG(dbgs() << "Dropping debug info for " << DI); + } + return true; + } + case Intrinsic::eh_exception: { + EVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { + default: break; + case TargetLowering::Expand: { + assert(FuncInfo.MBB->isLandingPad() && + "Call to eh.exception not in landing pad!"); + unsigned Reg = TLI.getExceptionAddressRegister(); + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(Reg); + UpdateValueMap(I, ResultReg); + return true; + } + } + break; + } + case Intrinsic::eh_selector: { + EVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { + default: break; + case TargetLowering::Expand: { + if (FuncInfo.MBB->isLandingPad()) + AddCatchInfo(*cast(I), &FuncInfo.MF->getMMI(), FuncInfo.MBB); + else { +#ifndef NDEBUG + FuncInfo.CatchInfoLost.insert(cast(I)); +#endif + // FIXME: Mark exception selector register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionSelectorRegister(); + if (Reg) FuncInfo.MBB->addLiveIn(Reg); + } + + unsigned Reg = TLI.getExceptionSelectorRegister(); + EVT SrcVT = TLI.getPointerTy(); + const TargetRegisterClass *RC = TLI.getRegClassFor(SrcVT); + unsigned ResultReg = createResultReg(RC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(Reg); + + bool ResultRegIsKill = hasTrivialKill(I); + + // Cast the register to the type of the selector. + if (SrcVT.bitsGT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, ISD::TRUNCATE, + ResultReg, ResultRegIsKill); + else if (SrcVT.bitsLT(MVT::i32)) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), MVT::i32, + ISD::SIGN_EXTEND, ResultReg, ResultRegIsKill); + if (ResultReg == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + UpdateValueMap(I, ResultReg); + + return true; + } + } + break; + } + } + + // An arbitrary call. Bail. + return false; +} + +bool FastISel::SelectCast(const User *I, unsigned Opcode) { + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + + if (SrcVT == MVT::Other || !SrcVT.isSimple() || + DstVT == MVT::Other || !DstVT.isSimple()) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // Check if the destination type is legal. Or as a special case, + // it may be i1 if we're doing a truncate because that's + // easy and somewhat common. + if (!TLI.isTypeLegal(DstVT)) + if (DstVT != MVT::i1 || Opcode != ISD::TRUNCATE) + // Unhandled type. Halt "fast" selection and bail. + return false; + + // Check if the source operand is legal. Or as a special case, + // it may be i1 if we're doing zero-extension because that's + // easy and somewhat common. + if (!TLI.isTypeLegal(SrcVT)) + if (SrcVT != MVT::i1 || Opcode != ISD::ZERO_EXTEND) + // Unhandled type. Halt "fast" selection and bail. + return false; + + unsigned InputReg = getRegForValue(I->getOperand(0)); + if (!InputReg) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + bool InputRegIsKill = hasTrivialKill(I->getOperand(0)); + + // If the operand is i1, arrange for the high bits in the register to be zero. + if (SrcVT == MVT::i1) { + SrcVT = TLI.getTypeToTransformTo(I->getContext(), SrcVT); + InputReg = FastEmitZExtFromI1(SrcVT.getSimpleVT(), InputReg, InputRegIsKill); + if (!InputReg) + return false; + InputRegIsKill = true; + } + // If the result is i1, truncate to the target's type for i1 first. + if (DstVT == MVT::i1) + DstVT = TLI.getTypeToTransformTo(I->getContext(), DstVT); + + unsigned ResultReg = FastEmit_r(SrcVT.getSimpleVT(), + DstVT.getSimpleVT(), + Opcode, + InputReg, InputRegIsKill); + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool FastISel::SelectBitCast(const User *I) { + // If the bitcast doesn't change the type, just use the operand value. + if (I->getType() == I->getOperand(0)->getType()) { + unsigned Reg = getRegForValue(I->getOperand(0)); + if (Reg == 0) + return false; + UpdateValueMap(I, Reg); + return true; + } + + // Bitcasts of other values become reg-reg copies or BITCAST operators. + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + + if (SrcVT == MVT::Other || !SrcVT.isSimple() || + DstVT == MVT::Other || !DstVT.isSimple() || + !TLI.isTypeLegal(SrcVT) || !TLI.isTypeLegal(DstVT)) + // Unhandled type. Halt "fast" selection and bail. + return false; + + unsigned Op0 = getRegForValue(I->getOperand(0)); + if (Op0 == 0) + // Unhandled operand. Halt "fast" selection and bail. + return false; + + bool Op0IsKill = hasTrivialKill(I->getOperand(0)); + + // First, try to perform the bitcast by inserting a reg-reg copy. + unsigned ResultReg = 0; + if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) { + TargetRegisterClass* SrcClass = TLI.getRegClassFor(SrcVT); + TargetRegisterClass* DstClass = TLI.getRegClassFor(DstVT); + // Don't attempt a cross-class copy. It will likely fail. + if (SrcClass == DstClass) { + ResultReg = createResultReg(DstClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(Op0); + } + } + + // If the reg-reg copy failed, select a BITCAST opcode. + if (!ResultReg) + ResultReg = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), + ISD::BITCAST, Op0, Op0IsKill); + + if (!ResultReg) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool +FastISel::SelectInstruction(const Instruction *I) { + // Just before the terminator instruction, insert instructions to + // feed PHI nodes in successor blocks. + if (isa(I)) + if (!HandlePHINodesInSuccessorBlocks(I->getParent())) + return false; + + DL = I->getDebugLoc(); + + // First, try doing target-independent selection. + if (SelectOperator(I, I->getOpcode())) { + DL = DebugLoc(); + return true; + } + + // Next, try calling the target to attempt to handle the instruction. + if (TargetSelectInstruction(I)) { + DL = DebugLoc(); + return true; + } + + DL = DebugLoc(); + return false; +} + +/// FastEmitBranch - Emit an unconditional branch to the given block, +/// unless it is the immediate (fall-through) successor, and update +/// the CFG. +void +FastISel::FastEmitBranch(MachineBasicBlock *MSucc, DebugLoc DL) { + if (FuncInfo.MBB->isLayoutSuccessor(MSucc)) { + // The unconditional fall-through case, which needs no instructions. + } else { + // The unconditional branch case. + TII.InsertBranch(*FuncInfo.MBB, MSucc, NULL, + SmallVector(), DL); + } + FuncInfo.MBB->addSuccessor(MSucc); +} + +/// SelectFNeg - Emit an FNeg operation. +/// +bool +FastISel::SelectFNeg(const User *I) { + unsigned OpReg = getRegForValue(BinaryOperator::getFNegArgument(I)); + if (OpReg == 0) return false; + + bool OpRegIsKill = hasTrivialKill(I); + + // If the target has ISD::FNEG, use it. + EVT VT = TLI.getValueType(I->getType()); + unsigned ResultReg = FastEmit_r(VT.getSimpleVT(), VT.getSimpleVT(), + ISD::FNEG, OpReg, OpRegIsKill); + if (ResultReg != 0) { + UpdateValueMap(I, ResultReg); + return true; + } + + // Bitcast the value to integer, twiddle the sign bit with xor, + // and then bitcast it back to floating-point. + if (VT.getSizeInBits() > 64) return false; + EVT IntVT = EVT::getIntegerVT(I->getContext(), VT.getSizeInBits()); + if (!TLI.isTypeLegal(IntVT)) + return false; + + unsigned IntReg = FastEmit_r(VT.getSimpleVT(), IntVT.getSimpleVT(), + ISD::BITCAST, OpReg, OpRegIsKill); + if (IntReg == 0) + return false; + + unsigned IntResultReg = FastEmit_ri_(IntVT.getSimpleVT(), ISD::XOR, + IntReg, /*Kill=*/true, + UINT64_C(1) << (VT.getSizeInBits()-1), + IntVT.getSimpleVT()); + if (IntResultReg == 0) + return false; + + ResultReg = FastEmit_r(IntVT.getSimpleVT(), VT.getSimpleVT(), + ISD::BITCAST, IntResultReg, /*Kill=*/true); + if (ResultReg == 0) + return false; + + UpdateValueMap(I, ResultReg); + return true; +} + +bool +FastISel::SelectOperator(const User *I, unsigned Opcode) { + switch (Opcode) { + case Instruction::Add: + return SelectBinaryOp(I, ISD::ADD); + case Instruction::FAdd: + return SelectBinaryOp(I, ISD::FADD); + case Instruction::Sub: + return SelectBinaryOp(I, ISD::SUB); + case Instruction::FSub: + // FNeg is currently represented in LLVM IR as a special case of FSub. + if (BinaryOperator::isFNeg(I)) + return SelectFNeg(I); + return SelectBinaryOp(I, ISD::FSUB); + case Instruction::Mul: + return SelectBinaryOp(I, ISD::MUL); + case Instruction::FMul: + return SelectBinaryOp(I, ISD::FMUL); + case Instruction::SDiv: + return SelectBinaryOp(I, ISD::SDIV); + case Instruction::UDiv: + return SelectBinaryOp(I, ISD::UDIV); + case Instruction::FDiv: + return SelectBinaryOp(I, ISD::FDIV); + case Instruction::SRem: + return SelectBinaryOp(I, ISD::SREM); + case Instruction::URem: + return SelectBinaryOp(I, ISD::UREM); + case Instruction::FRem: + return SelectBinaryOp(I, ISD::FREM); + case Instruction::Shl: + return SelectBinaryOp(I, ISD::SHL); + case Instruction::LShr: + return SelectBinaryOp(I, ISD::SRL); + case Instruction::AShr: + return SelectBinaryOp(I, ISD::SRA); + case Instruction::And: + return SelectBinaryOp(I, ISD::AND); + case Instruction::Or: + return SelectBinaryOp(I, ISD::OR); + case Instruction::Xor: + return SelectBinaryOp(I, ISD::XOR); + + case Instruction::GetElementPtr: + return SelectGetElementPtr(I); + + case Instruction::Br: { + const BranchInst *BI = cast(I); + + if (BI->isUnconditional()) { + const BasicBlock *LLVMSucc = BI->getSuccessor(0); + MachineBasicBlock *MSucc = FuncInfo.MBBMap[LLVMSucc]; + FastEmitBranch(MSucc, BI->getDebugLoc()); + return true; + } + + // Conditional branches are not handed yet. + // Halt "fast" selection and bail. + return false; + } + + case Instruction::Unreachable: + // Nothing to emit. + return true; + + case Instruction::Alloca: + // FunctionLowering has the static-sized case covered. + if (FuncInfo.StaticAllocaMap.count(cast(I))) + return true; + + // Dynamic-sized alloca is not handled yet. + return false; + + case Instruction::Call: + return SelectCall(I); + + case Instruction::BitCast: + return SelectBitCast(I); + + case Instruction::FPToSI: + return SelectCast(I, ISD::FP_TO_SINT); + case Instruction::ZExt: + return SelectCast(I, ISD::ZERO_EXTEND); + case Instruction::SExt: + return SelectCast(I, ISD::SIGN_EXTEND); + case Instruction::Trunc: + return SelectCast(I, ISD::TRUNCATE); + case Instruction::SIToFP: + return SelectCast(I, ISD::SINT_TO_FP); + + case Instruction::IntToPtr: // Deliberate fall-through. + case Instruction::PtrToInt: { + EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); + EVT DstVT = TLI.getValueType(I->getType()); + if (DstVT.bitsGT(SrcVT)) + return SelectCast(I, ISD::ZERO_EXTEND); + if (DstVT.bitsLT(SrcVT)) + return SelectCast(I, ISD::TRUNCATE); + unsigned Reg = getRegForValue(I->getOperand(0)); + if (Reg == 0) return false; + UpdateValueMap(I, Reg); + return true; + } + + case Instruction::PHI: + llvm_unreachable("FastISel shouldn't visit PHI nodes!"); + + default: + // Unhandled instruction. Halt "fast" selection and bail. + return false; + } +} + +FastISel::FastISel(FunctionLoweringInfo &funcInfo) + : FuncInfo(funcInfo), + MRI(FuncInfo.MF->getRegInfo()), + MFI(*FuncInfo.MF->getFrameInfo()), + MCP(*FuncInfo.MF->getConstantPool()), + TM(FuncInfo.MF->getTarget()), + TD(*TM.getTargetData()), + TII(*TM.getInstrInfo()), + TLI(*TM.getTargetLowering()), + TRI(*TM.getRegisterInfo()) { +} + +FastISel::~FastISel() {} + +unsigned FastISel::FastEmit_(MVT, MVT, + unsigned) { + return 0; +} + +unsigned FastISel::FastEmit_r(MVT, MVT, + unsigned, + unsigned /*Op0*/, bool /*Op0IsKill*/) { + return 0; +} + +unsigned FastISel::FastEmit_rr(MVT, MVT, + unsigned, + unsigned /*Op0*/, bool /*Op0IsKill*/, + unsigned /*Op1*/, bool /*Op1IsKill*/) { + return 0; +} + +unsigned FastISel::FastEmit_i(MVT, MVT, unsigned, uint64_t /*Imm*/) { + return 0; +} + +unsigned FastISel::FastEmit_f(MVT, MVT, + unsigned, const ConstantFP * /*FPImm*/) { + return 0; +} + +unsigned FastISel::FastEmit_ri(MVT, MVT, + unsigned, + unsigned /*Op0*/, bool /*Op0IsKill*/, + uint64_t /*Imm*/) { + return 0; +} + +unsigned FastISel::FastEmit_rf(MVT, MVT, + unsigned, + unsigned /*Op0*/, bool /*Op0IsKill*/, + const ConstantFP * /*FPImm*/) { + return 0; +} + +unsigned FastISel::FastEmit_rri(MVT, MVT, + unsigned, + unsigned /*Op0*/, bool /*Op0IsKill*/, + unsigned /*Op1*/, bool /*Op1IsKill*/, + uint64_t /*Imm*/) { + return 0; +} + +/// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries +/// to emit an instruction with an immediate operand using FastEmit_ri. +/// If that fails, it materializes the immediate into a register and try +/// FastEmit_rr instead. +unsigned FastISel::FastEmit_ri_(MVT VT, unsigned Opcode, + unsigned Op0, bool Op0IsKill, + uint64_t Imm, MVT ImmType) { + // First check if immediate type is legal. If not, we can't use the ri form. + unsigned ResultReg = FastEmit_ri(VT, VT, Opcode, Op0, Op0IsKill, Imm); + if (ResultReg != 0) + return ResultReg; + unsigned MaterialReg = FastEmit_i(ImmType, ImmType, ISD::Constant, Imm); + if (MaterialReg == 0) + return 0; + return FastEmit_rr(VT, VT, Opcode, + Op0, Op0IsKill, + MaterialReg, /*Kill=*/true); +} + +/// FastEmit_rf_ - This method is a wrapper of FastEmit_ri. It first tries +/// to emit an instruction with a floating-point immediate operand using +/// FastEmit_rf. If that fails, it materializes the immediate into a register +/// and try FastEmit_rr instead. +unsigned FastISel::FastEmit_rf_(MVT VT, unsigned Opcode, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm, MVT ImmType) { + // First check if immediate type is legal. If not, we can't use the rf form. + unsigned ResultReg = FastEmit_rf(VT, VT, Opcode, Op0, Op0IsKill, FPImm); + if (ResultReg != 0) + return ResultReg; + + // Materialize the constant in a register. + unsigned MaterialReg = FastEmit_f(ImmType, ImmType, ISD::ConstantFP, FPImm); + if (MaterialReg == 0) { + // If the target doesn't have a way to directly enter a floating-point + // value into a register, use an alternate approach. + // TODO: The current approach only supports floating-point constants + // that can be constructed by conversion from integer values. This should + // be replaced by code that creates a load from a constant-pool entry, + // which will require some target-specific work. + const APFloat &Flt = FPImm->getValueAPF(); + EVT IntVT = TLI.getPointerTy(); + + uint64_t x[2]; + uint32_t IntBitWidth = IntVT.getSizeInBits(); + bool isExact; + (void) Flt.convertToInteger(x, IntBitWidth, /*isSigned=*/true, + APFloat::rmTowardZero, &isExact); + if (!isExact) + return 0; + APInt IntVal(IntBitWidth, 2, x); + + unsigned IntegerReg = FastEmit_i(IntVT.getSimpleVT(), IntVT.getSimpleVT(), + ISD::Constant, IntVal.getZExtValue()); + if (IntegerReg == 0) + return 0; + MaterialReg = FastEmit_r(IntVT.getSimpleVT(), VT, + ISD::SINT_TO_FP, IntegerReg, /*Kill=*/true); + if (MaterialReg == 0) + return 0; + } + return FastEmit_rr(VT, VT, Opcode, + Op0, Op0IsKill, + MaterialReg, /*Kill=*/true); +} + +unsigned FastISel::createResultReg(const TargetRegisterClass* RC) { + return MRI.createVirtualRegister(RC); +} + +unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass* RC) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg); + return ResultReg; +} + +unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addFPImm(FPImm); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addFPImm(FPImm); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addImm(Imm); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addImm(Imm); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_i(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg).addImm(Imm); + else { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II).addImm(Imm); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(II.ImplicitDefs[0]); + } + return ResultReg; +} + +unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, bool Op0IsKill, + uint32_t Idx) { + unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); + assert(TargetRegisterInfo::isVirtualRegister(Op0) && + "Cannot yet extract from physregs"); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, + DL, TII.get(TargetOpcode::COPY), ResultReg) + .addReg(Op0, getKillRegState(Op0IsKill), Idx); + return ResultReg; +} + +/// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op +/// with all but the least significant bit set to zero. +unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill) { + return FastEmit_ri(VT, VT, ISD::AND, Op0, Op0IsKill, 1); +} + +/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. +/// Emit code to ensure constants are copied into registers when needed. +/// Remember the virtual registers that need to be added to the Machine PHI +/// nodes as input. We cannot just directly add them, because expansion +/// might result in multiple MBB's for one BB. As such, the start of the +/// BB might correspond to a different MBB than the end. +bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) { + const TerminatorInst *TI = LLVMBB->getTerminator(); + + SmallPtrSet SuccsHandled; + unsigned OrigNumPHINodesToUpdate = FuncInfo.PHINodesToUpdate.size(); + + // Check successor nodes' PHI nodes that expect a constant to be available + // from this block. + for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { + const BasicBlock *SuccBB = TI->getSuccessor(succ); + if (!isa(SuccBB->begin())) continue; + MachineBasicBlock *SuccMBB = FuncInfo.MBBMap[SuccBB]; + + // If this terminator has multiple identical successors (common for + // switches), only handle each succ once. + if (!SuccsHandled.insert(SuccMBB)) continue; + + MachineBasicBlock::iterator MBBI = SuccMBB->begin(); + + // At this point we know that there is a 1-1 correspondence between LLVM PHI + // nodes and Machine PHI nodes, but the incoming operands have not been + // emitted yet. + for (BasicBlock::const_iterator I = SuccBB->begin(); + const PHINode *PN = dyn_cast(I); ++I) { + + // Ignore dead phi's. + if (PN->use_empty()) continue; + + // Only handle legal types. Two interesting things to note here. First, + // by bailing out early, we may leave behind some dead instructions, + // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its + // own moves. Second, this check is necessary becuase FastISel doesn't + // use CreateRegs to create registers, so it always creates + // exactly one register for each non-void instruction. + EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true); + if (VT == MVT::Other || !TLI.isTypeLegal(VT)) { + // Promote MVT::i1. + if (VT == MVT::i1) + VT = TLI.getTypeToTransformTo(LLVMBB->getContext(), VT); + else { + FuncInfo.PHINodesToUpdate.resize(OrigNumPHINodesToUpdate); + return false; + } + } + + const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB); + + // Set the DebugLoc for the copy. Prefer the location of the operand + // if there is one; use the location of the PHI otherwise. + DL = PN->getDebugLoc(); + if (const Instruction *Inst = dyn_cast(PHIOp)) + DL = Inst->getDebugLoc(); + + unsigned Reg = getRegForValue(PHIOp); + if (Reg == 0) { + FuncInfo.PHINodesToUpdate.resize(OrigNumPHINodesToUpdate); + return false; + } + FuncInfo.PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg)); + DL = DebugLoc(); + } + } + + return true; +} diff --git a/final/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/final/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp new file mode 100644 index 00000000000..d8a5770d36c --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -0,0 +1,477 @@ +//===-- FunctionLoweringInfo.cpp ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating functions from LLVM IR into +// Machine IR. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "function-lowering-info" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +using namespace llvm; + +/// isUsedOutsideOfDefiningBlock - Return true if this instruction is used by +/// PHI nodes or outside of the basic block that defines it, or used by a +/// switch or atomic instruction, which may expand to multiple basic blocks. +static bool isUsedOutsideOfDefiningBlock(const Instruction *I) { + if (I->use_empty()) return false; + if (isa(I)) return true; + const BasicBlock *BB = I->getParent(); + for (Value::const_use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) { + const User *U = *UI; + if (cast(U)->getParent() != BB || isa(U)) + return true; + } + return false; +} + +/// isOnlyUsedInEntryBlock - If the specified argument is only used in the +/// entry block, return true. This includes arguments used by switches, since +/// the switch may expand into multiple basic blocks. +static bool isOnlyUsedInEntryBlock(const Argument *A, bool EnableFastISel) { + // With FastISel active, we may be splitting blocks, so force creation + // of virtual registers for all non-dead arguments. + if (EnableFastISel) + return A->use_empty(); + + const BasicBlock *Entry = A->getParent()->begin(); + for (Value::const_use_iterator UI = A->use_begin(), E = A->use_end(); + UI != E; ++UI) { + const User *U = *UI; + if (cast(U)->getParent() != Entry || isa(U)) + return false; // Use not in entry block. + } + return true; +} + +FunctionLoweringInfo::FunctionLoweringInfo(const TargetLowering &tli) + : TLI(tli) { +} + +void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) { + Fn = &fn; + MF = &mf; + RegInfo = &MF->getRegInfo(); + + // Check whether the function can return without sret-demotion. + SmallVector Outs; + GetReturnInfo(Fn->getReturnType(), + Fn->getAttributes().getRetAttributes(), Outs, TLI); + CanLowerReturn = TLI.CanLowerReturn(Fn->getCallingConv(), Fn->isVarArg(), + Outs, Fn->getContext()); + + // Create a vreg for each argument register that is not dead and is used + // outside of the entry block for the function. + for (Function::const_arg_iterator AI = Fn->arg_begin(), E = Fn->arg_end(); + AI != E; ++AI) + if (!isOnlyUsedInEntryBlock(AI, EnableFastISel)) + InitializeRegForValue(AI); + + // Initialize the mapping of values to registers. This is only set up for + // instruction values that are used outside of the block that defines + // them. + Function::const_iterator BB = Fn->begin(), EB = Fn->end(); + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (const AllocaInst *AI = dyn_cast(I)) + if (const ConstantInt *CUI = dyn_cast(AI->getArraySize())) { + const Type *Ty = AI->getAllocatedType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), + AI->getAlignment()); + + TySize *= CUI->getZExtValue(); // Get total allocated size. + if (TySize == 0) TySize = 1; // Don't create zero-sized stack objects. + + // The object may need to be placed onto the stack near the stack + // protector if one exists. Determine here if this object is a suitable + // candidate. I.e., it would trigger the creation of a stack protector. + bool MayNeedSP = + (AI->isArrayAllocation() || + (TySize > 8 && isa(Ty) && + cast(Ty)->getElementType()->isIntegerTy(8))); + StaticAllocaMap[AI] = + MF->getFrameInfo()->CreateStackObject(TySize, Align, false, MayNeedSP); + } + + for (; BB != EB; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + // Mark values used outside their block as exported, by allocating + // a virtual register for them. + if (isUsedOutsideOfDefiningBlock(I)) + if (!isa(I) || + !StaticAllocaMap.count(cast(I))) + InitializeRegForValue(I); + + // Collect llvm.dbg.declare information. This is done now instead of + // during the initial isel pass through the IR so that it is done + // in a predictable order. + if (const DbgDeclareInst *DI = dyn_cast(I)) { + MachineModuleInfo &MMI = MF->getMMI(); + if (MMI.hasDebugInfo() && + DIVariable(DI->getVariable()).Verify() && + !DI->getDebugLoc().isUnknown()) { + // Don't handle byval struct arguments or VLAs, for example. + // Non-byval arguments are handled here (they refer to the stack + // temporary alloca at this point). + const Value *Address = DI->getAddress(); + if (Address) { + if (const BitCastInst *BCI = dyn_cast(Address)) + Address = BCI->getOperand(0); + if (const AllocaInst *AI = dyn_cast(Address)) { + DenseMap::iterator SI = + StaticAllocaMap.find(AI); + if (SI != StaticAllocaMap.end()) { // Check for VLAs. + int FI = SI->second; + MMI.setVariableDbgInfo(DI->getVariable(), + FI, DI->getDebugLoc()); + } + } + } + } + } + } + + // Create an initial MachineBasicBlock for each LLVM BasicBlock in F. This + // also creates the initial PHI MachineInstrs, though none of the input + // operands are populated. + for (BB = Fn->begin(); BB != EB; ++BB) { + MachineBasicBlock *MBB = mf.CreateMachineBasicBlock(BB); + MBBMap[BB] = MBB; + MF->push_back(MBB); + + // Transfer the address-taken flag. This is necessary because there could + // be multiple MachineBasicBlocks corresponding to one BasicBlock, and only + // the first one should be marked. + if (BB->hasAddressTaken()) + MBB->setHasAddressTaken(); + + // Create Machine PHI nodes for LLVM PHI nodes, lowering them as + // appropriate. + for (BasicBlock::const_iterator I = BB->begin(); + const PHINode *PN = dyn_cast(I); ++I) { + if (PN->use_empty()) continue; + + DebugLoc DL = PN->getDebugLoc(); + unsigned PHIReg = ValueMap[PN]; + assert(PHIReg && "PHI node does not have an assigned virtual register!"); + + SmallVector ValueVTs; + ComputeValueVTs(TLI, PN->getType(), ValueVTs); + for (unsigned vti = 0, vte = ValueVTs.size(); vti != vte; ++vti) { + EVT VT = ValueVTs[vti]; + unsigned NumRegisters = TLI.getNumRegisters(Fn->getContext(), VT); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + for (unsigned i = 0; i != NumRegisters; ++i) + BuildMI(MBB, DL, TII->get(TargetOpcode::PHI), PHIReg + i); + PHIReg += NumRegisters; + } + } + } + + // Mark landing pad blocks. + for (BB = Fn->begin(); BB != EB; ++BB) + if (const InvokeInst *Invoke = dyn_cast(BB->getTerminator())) + MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); +} + +/// clear - Clear out all the function-specific state. This returns this +/// FunctionLoweringInfo to an empty state, ready to be used for a +/// different function. +void FunctionLoweringInfo::clear() { + assert(CatchInfoFound.size() == CatchInfoLost.size() && + "Not all catch info was assigned to a landing pad!"); + + MBBMap.clear(); + ValueMap.clear(); + StaticAllocaMap.clear(); +#ifndef NDEBUG + CatchInfoLost.clear(); + CatchInfoFound.clear(); +#endif + LiveOutRegInfo.clear(); + VisitedBBs.clear(); + ArgDbgValues.clear(); + ByValArgFrameIndexMap.clear(); + RegFixups.clear(); +} + +/// CreateReg - Allocate a single virtual register for the given type. +unsigned FunctionLoweringInfo::CreateReg(EVT VT) { + return RegInfo->createVirtualRegister(TLI.getRegClassFor(VT)); +} + +/// CreateRegs - Allocate the appropriate number of virtual registers of +/// the correctly promoted or expanded types. Assign these registers +/// consecutive vreg numbers and return the first assigned number. +/// +/// In the case that the given value has struct or array type, this function +/// will assign registers for each member or element. +/// +unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, Ty, ValueVTs); + + unsigned FirstReg = 0; + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + EVT RegisterVT = TLI.getRegisterType(Ty->getContext(), ValueVT); + + unsigned NumRegs = TLI.getNumRegisters(Ty->getContext(), ValueVT); + for (unsigned i = 0; i != NumRegs; ++i) { + unsigned R = CreateReg(RegisterVT); + if (!FirstReg) FirstReg = R; + } + } + return FirstReg; +} + +/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the +/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If +/// the register's LiveOutInfo is for a smaller bit width, it is extended to +/// the larger bit width by zero extension. The bit width must be no smaller +/// than the LiveOutInfo's existing bit width. +const FunctionLoweringInfo::LiveOutInfo * +FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) { + if (!LiveOutRegInfo.inBounds(Reg)) + return NULL; + + LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; + if (!LOI->IsValid) + return NULL; + + if (BitWidth > LOI->KnownZero.getBitWidth()) { + LOI->NumSignBits = 1; + LOI->KnownZero = LOI->KnownZero.zextOrTrunc(BitWidth); + LOI->KnownOne = LOI->KnownOne.zextOrTrunc(BitWidth); + } + + return LOI; +} + +/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination +/// register based on the LiveOutInfo of its operands. +void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) { + const Type *Ty = PN->getType(); + if (!Ty->isIntegerTy() || Ty->isVectorTy()) + return; + + SmallVector ValueVTs; + ComputeValueVTs(TLI, Ty, ValueVTs); + assert(ValueVTs.size() == 1 && + "PHIs with non-vector integer types should have a single VT."); + EVT IntVT = ValueVTs[0]; + + if (TLI.getNumRegisters(PN->getContext(), IntVT) != 1) + return; + IntVT = TLI.getTypeToTransformTo(PN->getContext(), IntVT); + unsigned BitWidth = IntVT.getSizeInBits(); + + unsigned DestReg = ValueMap[PN]; + if (!TargetRegisterInfo::isVirtualRegister(DestReg)) + return; + LiveOutRegInfo.grow(DestReg); + LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg]; + + Value *V = PN->getIncomingValue(0); + if (isa(V) || isa(V)) { + DestLOI.NumSignBits = 1; + APInt Zero(BitWidth, 0); + DestLOI.KnownZero = Zero; + DestLOI.KnownOne = Zero; + return; + } + + if (ConstantInt *CI = dyn_cast(V)) { + APInt Val = CI->getValue().zextOrTrunc(BitWidth); + DestLOI.NumSignBits = Val.getNumSignBits(); + DestLOI.KnownZero = ~Val; + DestLOI.KnownOne = Val; + } else { + assert(ValueMap.count(V) && "V should have been placed in ValueMap when its" + "CopyToReg node was created."); + unsigned SrcReg = ValueMap[V]; + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) { + DestLOI.IsValid = false; + return; + } + const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); + if (!SrcLOI) { + DestLOI.IsValid = false; + return; + } + DestLOI = *SrcLOI; + } + + assert(DestLOI.KnownZero.getBitWidth() == BitWidth && + DestLOI.KnownOne.getBitWidth() == BitWidth && + "Masks should have the same bit width as the type."); + + for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *V = PN->getIncomingValue(i); + if (isa(V) || isa(V)) { + DestLOI.NumSignBits = 1; + APInt Zero(BitWidth, 0); + DestLOI.KnownZero = Zero; + DestLOI.KnownOne = Zero; + return; + } + + if (ConstantInt *CI = dyn_cast(V)) { + APInt Val = CI->getValue().zextOrTrunc(BitWidth); + DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits()); + DestLOI.KnownZero &= ~Val; + DestLOI.KnownOne &= Val; + continue; + } + + assert(ValueMap.count(V) && "V should have been placed in ValueMap when " + "its CopyToReg node was created."); + unsigned SrcReg = ValueMap[V]; + if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) { + DestLOI.IsValid = false; + return; + } + const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth); + if (!SrcLOI) { + DestLOI.IsValid = false; + return; + } + DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits); + DestLOI.KnownZero &= SrcLOI->KnownZero; + DestLOI.KnownOne &= SrcLOI->KnownOne; + } +} + +/// setByValArgumentFrameIndex - Record frame index for the byval +/// argument. This overrides previous frame index entry for this argument, +/// if any. +void FunctionLoweringInfo::setByValArgumentFrameIndex(const Argument *A, + int FI) { + assert (A->hasByValAttr() && "Argument does not have byval attribute!"); + ByValArgFrameIndexMap[A] = FI; +} + +/// getByValArgumentFrameIndex - Get frame index for the byval argument. +/// If the argument does not have any assigned frame index then 0 is +/// returned. +int FunctionLoweringInfo::getByValArgumentFrameIndex(const Argument *A) { + assert (A->hasByValAttr() && "Argument does not have byval attribute!"); + DenseMap::iterator I = + ByValArgFrameIndexMap.find(A); + if (I != ByValArgFrameIndexMap.end()) + return I->second; + DEBUG(dbgs() << "Argument does not have assigned frame index!"); + return 0; +} + +/// AddCatchInfo - Extract the personality and type infos from an eh.selector +/// call, and add them to the specified machine basic block. +void llvm::AddCatchInfo(const CallInst &I, MachineModuleInfo *MMI, + MachineBasicBlock *MBB) { + // Inform the MachineModuleInfo of the personality for this landing pad. + const ConstantExpr *CE = cast(I.getArgOperand(1)); + assert(CE->getOpcode() == Instruction::BitCast && + isa(CE->getOperand(0)) && + "Personality should be a function"); + MMI->addPersonality(MBB, cast(CE->getOperand(0))); + + // Gather all the type infos for this landing pad and pass them along to + // MachineModuleInfo. + std::vector TyInfo; + unsigned N = I.getNumArgOperands(); + + for (unsigned i = N - 1; i > 1; --i) { + if (const ConstantInt *CI = dyn_cast(I.getArgOperand(i))) { + unsigned FilterLength = CI->getZExtValue(); + unsigned FirstCatch = i + FilterLength + !FilterLength; + assert(FirstCatch <= N && "Invalid filter length"); + + if (FirstCatch < N) { + TyInfo.reserve(N - FirstCatch); + for (unsigned j = FirstCatch; j < N; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); + MMI->addCatchTypeInfo(MBB, TyInfo); + TyInfo.clear(); + } + + if (!FilterLength) { + // Cleanup. + MMI->addCleanup(MBB); + } else { + // Filter. + TyInfo.reserve(FilterLength - 1); + for (unsigned j = i + 1; j < FirstCatch; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); + MMI->addFilterTypeInfo(MBB, TyInfo); + TyInfo.clear(); + } + + N = i; + } + } + + if (N > 2) { + TyInfo.reserve(N - 2); + for (unsigned j = 2; j < N; ++j) + TyInfo.push_back(ExtractTypeInfo(I.getArgOperand(j))); + MMI->addCatchTypeInfo(MBB, TyInfo); + } +} + +void llvm::CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, + MachineModuleInfo *MMI, FunctionLoweringInfo &FLI) { + SmallPtrSet Visited; + + // The 'eh.selector' call may not be in the direct successor of a basic block, + // but could be several successors deeper. If we don't find it, try going one + // level further. + while (Visited.insert(SuccBB)) { + for (BasicBlock::const_iterator I = SuccBB->begin(), E = --SuccBB->end(); + I != E; ++I) + if (const EHSelectorInst *EHSel = dyn_cast(I)) { + // Apply the catch info to LPad. + AddCatchInfo(*EHSel, MMI, FLI.MBBMap[LPad]); +#ifndef NDEBUG + if (!FLI.MBBMap[SuccBB]->isLandingPad()) + FLI.CatchInfoFound.insert(EHSel); +#endif + return; + } + + const BranchInst *Br = dyn_cast(SuccBB->getTerminator()); + if (Br && Br->isUnconditional()) + SuccBB = Br->getSuccessor(0); + else + break; + } +} diff --git a/final/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/final/lib/CodeGen/SelectionDAG/InstrEmitter.cpp new file mode 100644 index 00000000000..e309defba20 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -0,0 +1,897 @@ +//==--- InstrEmitter.cpp - Emit MachineInstrs for the SelectionDAG class ---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the Emit routines for the SelectionDAG class, which creates +// MachineInstrs based on the decisions of the SelectionDAG instruction +// selection. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "instr-emitter" +#include "InstrEmitter.h" +#include "SDNodeDbgValue.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +/// CountResults - The results of target nodes have register or immediate +/// operands first, then an optional chain, and optional glue operands (which do +/// not go into the resulting MachineInstr). +unsigned InstrEmitter::CountResults(SDNode *Node) { + unsigned N = Node->getNumValues(); + while (N && Node->getValueType(N - 1) == MVT::Glue) + --N; + if (N && Node->getValueType(N - 1) == MVT::Other) + --N; // Skip over chain result. + return N; +} + +/// CountOperands - The inputs to target nodes have any actual inputs first, +/// followed by an optional chain operand, then an optional glue operand. +/// Compute the number of actual operands that will go into the resulting +/// MachineInstr. +unsigned InstrEmitter::CountOperands(SDNode *Node) { + unsigned N = Node->getNumOperands(); + while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue) + --N; + if (N && Node->getOperand(N - 1).getValueType() == MVT::Other) + --N; // Ignore chain if it exists. + return N; +} + +/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an +/// implicit physical register output. +void InstrEmitter:: +EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned, + unsigned SrcReg, DenseMap &VRBaseMap) { + unsigned VRBase = 0; + if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { + // Just use the input register directly! + SDValue Op(Node, ResNo); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + return; + } + + // If the node is only used by a CopyToReg and the dest reg is a vreg, use + // the CopyToReg'd destination register instead of creating a new vreg. + bool MatchReg = true; + const TargetRegisterClass *UseRC = NULL; + if (!IsClone && !IsCloned) + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + bool Match = true; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == ResNo) { + unsigned DestReg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(DestReg)) { + VRBase = DestReg; + Match = false; + } else if (DestReg != SrcReg) + Match = false; + } else { + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { + SDValue Op = User->getOperand(i); + if (Op.getNode() != Node || Op.getResNo() != ResNo) + continue; + EVT VT = Node->getValueType(Op.getResNo()); + if (VT == MVT::Other || VT == MVT::Glue) + continue; + Match = false; + if (User->isMachineOpcode()) { + const TargetInstrDesc &II = TII->get(User->getMachineOpcode()); + const TargetRegisterClass *RC = 0; + if (i+II.getNumDefs() < II.getNumOperands()) + RC = II.OpInfo[i+II.getNumDefs()].getRegClass(TRI); + if (!UseRC) + UseRC = RC; + else if (RC) { + const TargetRegisterClass *ComRC = getCommonSubClass(UseRC, RC); + // If multiple uses expect disjoint register classes, we emit + // copies in AddRegisterOperand. + if (ComRC) + UseRC = ComRC; + } + } + } + } + MatchReg &= Match; + if (VRBase) + break; + } + + EVT VT = Node->getValueType(ResNo); + const TargetRegisterClass *SrcRC = 0, *DstRC = 0; + SrcRC = TRI->getMinimalPhysRegClass(SrcReg, VT); + + // Figure out the register class to create for the destreg. + if (VRBase) { + DstRC = MRI->getRegClass(VRBase); + } else if (UseRC) { + assert(UseRC->hasType(VT) && "Incompatible phys register def and uses!"); + DstRC = UseRC; + } else { + DstRC = TLI->getRegClassFor(VT); + } + + // If all uses are reading from the src physical register and copying the + // register is either impossible or very expensive, then don't create a copy. + if (MatchReg && SrcRC->getCopyCost() < 0) { + VRBase = SrcReg; + } else { + // Create the reg, emit the copy. + VRBase = MRI->createVirtualRegister(DstRC); + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), + VRBase).addReg(SrcReg); + } + + SDValue Op(Node, ResNo); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// getDstOfCopyToRegUse - If the only use of the specified result number of +/// node is a CopyToReg, return its destination register. Return 0 otherwise. +unsigned InstrEmitter::getDstOfOnlyCopyToRegUse(SDNode *Node, + unsigned ResNo) const { + if (!Node->hasOneUse()) + return 0; + + SDNode *User = *Node->use_begin(); + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == ResNo) { + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return Reg; + } + return 0; +} + +void InstrEmitter::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, + const TargetInstrDesc &II, + bool IsClone, bool IsCloned, + DenseMap &VRBaseMap) { + assert(Node->getMachineOpcode() != TargetOpcode::IMPLICIT_DEF && + "IMPLICIT_DEF should have been handled as a special case elsewhere!"); + + for (unsigned i = 0; i < II.getNumDefs(); ++i) { + // If the specific node value is only used by a CopyToReg and the dest reg + // is a vreg in the same register class, use the CopyToReg'd destination + // register instead of creating a new vreg. + unsigned VRBase = 0; + const TargetRegisterClass *RC = II.OpInfo[i].getRegClass(TRI); + if (II.OpInfo[i].isOptionalDef()) { + // Optional def must be a physical register. + unsigned NumResults = CountResults(Node); + VRBase = cast(Node->getOperand(i-NumResults))->getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(VRBase)); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + } + + if (!VRBase && !IsClone && !IsCloned) + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node && + User->getOperand(2).getResNo() == i) { + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + const TargetRegisterClass *RegRC = MRI->getRegClass(Reg); + if (RegRC == RC) { + VRBase = Reg; + MI->addOperand(MachineOperand::CreateReg(Reg, true)); + break; + } + } + } + } + + // Create the result registers for this node and add the result regs to + // the machine instruction. + if (VRBase == 0) { + assert(RC && "Isn't a register operand!"); + VRBase = MRI->createVirtualRegister(RC); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + } + + SDValue Op(Node, i); + if (IsClone) + VRBaseMap.erase(Op); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); + } +} + +/// getVR - Return the virtual register corresponding to the specified result +/// of the specified node. +unsigned InstrEmitter::getVR(SDValue Op, + DenseMap &VRBaseMap) { + if (Op.isMachineOpcode() && + Op.getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) { + // Add an IMPLICIT_DEF instruction before every use. + unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo()); + // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc + // does not include operand register class info. + if (!VReg) { + const TargetRegisterClass *RC = TLI->getRegClassFor(Op.getValueType()); + VReg = MRI->createVirtualRegister(RC); + } + BuildMI(*MBB, InsertPos, Op.getDebugLoc(), + TII->get(TargetOpcode::IMPLICIT_DEF), VReg); + return VReg; + } + + DenseMap::iterator I = VRBaseMap.find(Op); + assert(I != VRBaseMap.end() && "Node emitted out of order - late"); + return I->second; +} + + +/// AddRegisterOperand - Add the specified register as an operand to the +/// specified machine instr. Insert register copies if the register is +/// not in the required register class. +void +InstrEmitter::AddRegisterOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap, + bool IsDebug, bool IsClone, bool IsCloned) { + assert(Op.getValueType() != MVT::Other && + Op.getValueType() != MVT::Glue && + "Chain and glue operands should occur at end of operand list!"); + // Get/emit the operand. + unsigned VReg = getVR(Op, VRBaseMap); + assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); + + const TargetInstrDesc &TID = MI->getDesc(); + bool isOptDef = IIOpNum < TID.getNumOperands() && + TID.OpInfo[IIOpNum].isOptionalDef(); + + // If the instruction requires a register in a different class, create + // a new virtual register and copy the value into it. + if (II) { + const TargetRegisterClass *SrcRC = MRI->getRegClass(VReg); + const TargetRegisterClass *DstRC = 0; + if (IIOpNum < II->getNumOperands()) + DstRC = II->OpInfo[IIOpNum].getRegClass(TRI); + assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) && + "Don't have operand info for this instruction!"); + if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) { + unsigned NewVReg = MRI->createVirtualRegister(DstRC); + BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(), + TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg); + VReg = NewVReg; + } + } + + // If this value has only one use, that use is a kill. This is a + // conservative approximation. InstrEmitter does trivial coalescing + // with CopyFromReg nodes, so don't emit kill flags for them. + // Avoid kill flags on Schedule cloned nodes, since there will be + // multiple uses. + // Tied operands are never killed, so we need to check that. And that + // means we need to determine the index of the operand. + bool isKill = Op.hasOneUse() && + Op.getNode()->getOpcode() != ISD::CopyFromReg && + !IsDebug && + !(IsClone || IsCloned); + if (isKill) { + unsigned Idx = MI->getNumOperands(); + while (Idx > 0 && + MI->getOperand(Idx-1).isReg() && MI->getOperand(Idx-1).isImplicit()) + --Idx; + bool isTied = MI->getDesc().getOperandConstraint(Idx, TOI::TIED_TO) != -1; + if (isTied) + isKill = false; + } + + MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef, + false/*isImp*/, isKill, + false/*isDead*/, false/*isUndef*/, + false/*isEarlyClobber*/, + 0/*SubReg*/, IsDebug)); +} + +/// AddOperand - Add the specified operand to the specified machine instr. II +/// specifies the instruction information for the node, and IIOpNum is the +/// operand number (in the II) that we are adding. IIOpNum and II are used for +/// assertions only. +void InstrEmitter::AddOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap, + bool IsDebug, bool IsClone, bool IsCloned) { + if (Op.isMachineOpcode()) { + AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap, + IsDebug, IsClone, IsCloned); + } else if (ConstantSDNode *C = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateImm(C->getSExtValue())); + } else if (ConstantFPSDNode *F = dyn_cast(Op)) { + const ConstantFP *CFP = F->getConstantFPValue(); + MI->addOperand(MachineOperand::CreateFPImm(CFP)); + } else if (RegisterSDNode *R = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateReg(R->getReg(), false)); + } else if (GlobalAddressSDNode *TGA = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(), + TGA->getTargetFlags())); + } else if (BasicBlockSDNode *BBNode = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock())); + } else if (FrameIndexSDNode *FI = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateFI(FI->getIndex())); + } else if (JumpTableSDNode *JT = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(), + JT->getTargetFlags())); + } else if (ConstantPoolSDNode *CP = dyn_cast(Op)) { + int Offset = CP->getOffset(); + unsigned Align = CP->getAlignment(); + const Type *Type = CP->getType(); + // MachineConstantPool wants an explicit alignment. + if (Align == 0) { + Align = TM->getTargetData()->getPrefTypeAlignment(Type); + if (Align == 0) { + // Alignment of vector types. FIXME! + Align = TM->getTargetData()->getTypeAllocSize(Type); + } + } + + unsigned Idx; + MachineConstantPool *MCP = MF->getConstantPool(); + if (CP->isMachineConstantPoolEntry()) + Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Align); + else + Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Align); + MI->addOperand(MachineOperand::CreateCPI(Idx, Offset, + CP->getTargetFlags())); + } else if (ExternalSymbolSDNode *ES = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), + ES->getTargetFlags())); + } else if (BlockAddressSDNode *BA = dyn_cast(Op)) { + MI->addOperand(MachineOperand::CreateBA(BA->getBlockAddress(), + BA->getTargetFlags())); + } else { + assert(Op.getValueType() != MVT::Other && + Op.getValueType() != MVT::Glue && + "Chain and glue operands should occur at end of operand list!"); + AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap, + IsDebug, IsClone, IsCloned); + } +} + +/// getSuperRegisterRegClass - Returns the register class of a superreg A whose +/// "SubIdx"'th sub-register class is the specified register class and whose +/// type matches the specified type. +static const TargetRegisterClass* +getSuperRegisterRegClass(const TargetRegisterClass *TRC, + unsigned SubIdx, EVT VT) { + // Pick the register class of the superegister for this type + for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(), + E = TRC->superregclasses_end(); I != E; ++I) + if ((*I)->hasType(VT) && (*I)->getSubRegisterRegClass(SubIdx) == TRC) + return *I; + assert(false && "Couldn't find the register class"); + return 0; +} + +/// EmitSubregNode - Generate machine code for subreg nodes. +/// +void InstrEmitter::EmitSubregNode(SDNode *Node, + DenseMap &VRBaseMap, + bool IsClone, bool IsCloned) { + unsigned VRBase = 0; + unsigned Opc = Node->getMachineOpcode(); + + // If the node is only used by a CopyToReg and the dest reg is a vreg, use + // the CopyToReg'd destination register instead of creating a new vreg. + for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + if (User->getOpcode() == ISD::CopyToReg && + User->getOperand(2).getNode() == Node) { + unsigned DestReg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(DestReg)) { + VRBase = DestReg; + break; + } + } + } + + if (Opc == TargetOpcode::EXTRACT_SUBREG) { + // EXTRACT_SUBREG is lowered as %dst = COPY %src:sub + unsigned SubIdx = cast(Node->getOperand(1))->getZExtValue(); + + // Figure out the register class to create for the destreg. + unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); + MachineInstr *DefMI = MRI->getVRegDef(VReg); + unsigned SrcReg, DstReg, DefSubIdx; + if (DefMI && + TII->isCoalescableExtInstr(*DefMI, SrcReg, DstReg, DefSubIdx) && + SubIdx == DefSubIdx) { + // Optimize these: + // r1025 = s/zext r1024, 4 + // r1026 = extract_subreg r1025, 4 + // to a copy + // r1026 = copy r1024 + const TargetRegisterClass *TRC = MRI->getRegClass(SrcReg); + VRBase = MRI->createVirtualRegister(TRC); + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), + TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg); + } else { + const TargetRegisterClass *TRC = MRI->getRegClass(VReg); + const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx); + assert(SRC && "Invalid subregister index in EXTRACT_SUBREG"); + + // Figure out the register class to create for the destreg. + // Note that if we're going to directly use an existing register, + // it must be precisely the required class, and not a subclass + // thereof. + if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { + // Create the reg + assert(SRC && "Couldn't find source register class"); + VRBase = MRI->createVirtualRegister(SRC); + } + + // Create the extract_subreg machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetOpcode::COPY), VRBase); + + // Add source, and subreg index + AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap, /*IsDebug=*/false, + IsClone, IsCloned); + assert(TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg())&& + "Cannot yet extract from physregs"); + MI->getOperand(1).setSubReg(SubIdx); + MBB->insert(InsertPos, MI); + } + } else if (Opc == TargetOpcode::INSERT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG) { + SDValue N0 = Node->getOperand(0); + SDValue N1 = Node->getOperand(1); + SDValue N2 = Node->getOperand(2); + unsigned SubReg = getVR(N1, VRBaseMap); + unsigned SubIdx = cast(N2)->getZExtValue(); + const TargetRegisterClass *TRC = MRI->getRegClass(SubReg); + const TargetRegisterClass *SRC = + getSuperRegisterRegClass(TRC, SubIdx, Node->getValueType(0)); + + // Figure out the register class to create for the destreg. + // Note that if we're going to directly use an existing register, + // it must be precisely the required class, and not a subclass + // thereof. + if (VRBase == 0 || SRC != MRI->getRegClass(VRBase)) { + // Create the reg + assert(SRC && "Couldn't find source register class"); + VRBase = MRI->createVirtualRegister(SRC); + } + + // Create the insert_subreg or subreg_to_reg machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), TII->get(Opc)); + MI->addOperand(MachineOperand::CreateReg(VRBase, true)); + + // If creating a subreg_to_reg, then the first input operand + // is an implicit value immediate, otherwise it's a register + if (Opc == TargetOpcode::SUBREG_TO_REG) { + const ConstantSDNode *SD = cast(N0); + MI->addOperand(MachineOperand::CreateImm(SD->getZExtValue())); + } else + AddOperand(MI, N0, 0, 0, VRBaseMap, /*IsDebug=*/false, + IsClone, IsCloned); + // Add the subregster being inserted + AddOperand(MI, N1, 0, 0, VRBaseMap, /*IsDebug=*/false, + IsClone, IsCloned); + MI->addOperand(MachineOperand::CreateImm(SubIdx)); + MBB->insert(InsertPos, MI); + } else + llvm_unreachable("Node is not insert_subreg, extract_subreg, or subreg_to_reg"); + + SDValue Op(Node, 0); + bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes. +/// COPY_TO_REGCLASS is just a normal copy, except that the destination +/// register is constrained to be in a particular register class. +/// +void +InstrEmitter::EmitCopyToRegClassNode(SDNode *Node, + DenseMap &VRBaseMap) { + unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); + + // Create the new VReg in the destination class and emit a copy. + unsigned DstRCIdx = cast(Node->getOperand(1))->getZExtValue(); + const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx); + unsigned NewVReg = MRI->createVirtualRegister(DstRC); + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), + NewVReg).addReg(VReg); + + SDValue Op(Node, 0); + bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// EmitRegSequence - Generate machine code for REG_SEQUENCE nodes. +/// +void InstrEmitter::EmitRegSequence(SDNode *Node, + DenseMap &VRBaseMap, + bool IsClone, bool IsCloned) { + const TargetRegisterClass *RC = TLI->getRegClassFor(Node->getValueType(0)); + unsigned NewVReg = MRI->createVirtualRegister(RC); + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetOpcode::REG_SEQUENCE), NewVReg); + unsigned NumOps = Node->getNumOperands(); + assert((NumOps & 1) == 0 && + "REG_SEQUENCE must have an even number of operands!"); + const TargetInstrDesc &II = TII->get(TargetOpcode::REG_SEQUENCE); + for (unsigned i = 0; i != NumOps; ++i) { + SDValue Op = Node->getOperand(i); + if (i & 1) { + unsigned SubIdx = cast(Op)->getZExtValue(); + unsigned SubReg = getVR(Node->getOperand(i-1), VRBaseMap); + const TargetRegisterClass *TRC = MRI->getRegClass(SubReg); + const TargetRegisterClass *SRC = + TRI->getMatchingSuperRegClass(RC, TRC, SubIdx); + if (SRC && SRC != RC) { + MRI->setRegClass(NewVReg, SRC); + RC = SRC; + } + } + AddOperand(MI, Op, i+1, &II, VRBaseMap, /*IsDebug=*/false, + IsClone, IsCloned); + } + + MBB->insert(InsertPos, MI); + SDValue Op(Node, 0); + bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second; + (void)isNew; // Silence compiler warning. + assert(isNew && "Node emitted out of order - early"); +} + +/// EmitDbgValue - Generate machine instruction for a dbg_value node. +/// +MachineInstr * +InstrEmitter::EmitDbgValue(SDDbgValue *SD, + DenseMap &VRBaseMap) { + uint64_t Offset = SD->getOffset(); + MDNode* MDPtr = SD->getMDPtr(); + DebugLoc DL = SD->getDebugLoc(); + + if (SD->getKind() == SDDbgValue::FRAMEIX) { + // Stack address; this needs to be lowered in target-dependent fashion. + // EmitTargetCodeForFrameDebugValue is responsible for allocation. + unsigned FrameIx = SD->getFrameIx(); + return TII->emitFrameIndexDebugValue(*MF, FrameIx, Offset, MDPtr, DL); + } + // Otherwise, we're going to create an instruction here. + const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); + MachineInstrBuilder MIB = BuildMI(*MF, DL, II); + if (SD->getKind() == SDDbgValue::SDNODE) { + SDNode *Node = SD->getSDNode(); + SDValue Op = SDValue(Node, SD->getResNo()); + // It's possible we replaced this SDNode with other(s) and therefore + // didn't generate code for it. It's better to catch these cases where + // they happen and transfer the debug info, but trying to guarantee that + // in all cases would be very fragile; this is a safeguard for any + // that were missed. + DenseMap::iterator I = VRBaseMap.find(Op); + if (I==VRBaseMap.end()) + MIB.addReg(0U); // undef + else + AddOperand(&*MIB, Op, (*MIB).getNumOperands(), &II, VRBaseMap, + /*IsDebug=*/true, /*IsClone=*/false, /*IsCloned=*/false); + } else if (SD->getKind() == SDDbgValue::CONST) { + const Value *V = SD->getConst(); + if (const ConstantInt *CI = dyn_cast(V)) { + // FIXME: SDDbgValue constants aren't updated with legalization, so it's + // possible to have i128 constants in them at this point. Dwarf writer + // does not handle i128 constants at the moment so, as a crude workaround, + // just drop the debug info if this happens. + if (!CI->getValue().isSignedIntN(64)) + MIB.addReg(0U); + else + MIB.addImm(CI->getSExtValue()); + } else if (const ConstantFP *CF = dyn_cast(V)) { + MIB.addFPImm(CF); + } else { + // Could be an Undef. In any case insert an Undef so we can see what we + // dropped. + MIB.addReg(0U); + } + } else { + // Insert an Undef so we can see what we dropped. + MIB.addReg(0U); + } + + MIB.addImm(Offset).addMetadata(MDPtr); + return &*MIB; +} + +/// EmitMachineNode - Generate machine code for a target-specific node and +/// needed dependencies. +/// +void InstrEmitter:: +EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap) { + unsigned Opc = Node->getMachineOpcode(); + + // Handle subreg insert/extract specially + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::INSERT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG) { + EmitSubregNode(Node, VRBaseMap, IsClone, IsCloned); + return; + } + + // Handle COPY_TO_REGCLASS specially. + if (Opc == TargetOpcode::COPY_TO_REGCLASS) { + EmitCopyToRegClassNode(Node, VRBaseMap); + return; + } + + // Handle REG_SEQUENCE specially. + if (Opc == TargetOpcode::REG_SEQUENCE) { + EmitRegSequence(Node, VRBaseMap, IsClone, IsCloned); + return; + } + + if (Opc == TargetOpcode::IMPLICIT_DEF) + // We want a unique VR for each IMPLICIT_DEF use. + return; + + const TargetInstrDesc &II = TII->get(Opc); + unsigned NumResults = CountResults(Node); + unsigned NodeOperands = CountOperands(Node); + bool HasPhysRegOuts = NumResults > II.getNumDefs() && II.getImplicitDefs()!=0; +#ifndef NDEBUG + unsigned NumMIOperands = NodeOperands + NumResults; + if (II.isVariadic()) + assert(NumMIOperands >= II.getNumOperands() && + "Too few operands for a variadic node!"); + else + assert(NumMIOperands >= II.getNumOperands() && + NumMIOperands <= II.getNumOperands()+II.getNumImplicitDefs() && + "#operands for dag node doesn't match .td file!"); +#endif + + // Create the new machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), II); + + // The MachineInstr constructor adds implicit-def operands. Scan through + // these to determine which are dead. + if (MI->getNumOperands() != 0 && + Node->getValueType(Node->getNumValues()-1) == MVT::Glue) { + // First, collect all used registers. + SmallVector UsedRegs; + for (SDNode *F = Node->getGluedUser(); F; F = F->getGluedUser()) + if (F->getOpcode() == ISD::CopyFromReg) + UsedRegs.push_back(cast(F->getOperand(1))->getReg()); + else { + // Collect declared implicit uses. + const TargetInstrDesc &TID = TII->get(F->getMachineOpcode()); + UsedRegs.append(TID.getImplicitUses(), + TID.getImplicitUses() + TID.getNumImplicitUses()); + // In addition to declared implicit uses, we must also check for + // direct RegisterSDNode operands. + for (unsigned i = 0, e = F->getNumOperands(); i != e; ++i) + if (RegisterSDNode *R = dyn_cast(F->getOperand(i))) { + unsigned Reg = R->getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + UsedRegs.push_back(Reg); + } + } + // Then mark unused registers as dead. + MI->setPhysRegsDeadExcept(UsedRegs, *TRI); + } + + // Add result register values for things that are defined by this + // instruction. + if (NumResults) + CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap); + + // Emit all of the actual operands of this instruction, adding them to the + // instruction as appropriate. + bool HasOptPRefs = II.getNumDefs() > NumResults; + assert((!HasOptPRefs || !HasPhysRegOuts) && + "Unable to cope with optional defs and phys regs defs!"); + unsigned NumSkip = HasOptPRefs ? II.getNumDefs() - NumResults : 0; + for (unsigned i = NumSkip; i != NodeOperands; ++i) + AddOperand(MI, Node->getOperand(i), i-NumSkip+II.getNumDefs(), &II, + VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); + + // Transfer all of the memory reference descriptions of this instruction. + MI->setMemRefs(cast(Node)->memoperands_begin(), + cast(Node)->memoperands_end()); + + // Insert the instruction into position in the block. This needs to + // happen before any custom inserter hook is called so that the + // hook knows where in the block to insert the replacement code. + MBB->insert(InsertPos, MI); + + // Additional results must be physical register defs. + if (HasPhysRegOuts) { + for (unsigned i = II.getNumDefs(); i < NumResults; ++i) { + unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()]; + if (Node->hasAnyUseOfValue(i)) + EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap); + // If there are no uses, mark the register as dead now, so that + // MachineLICM/Sink can see that it's dead. Don't do this if the + // node has a Glue value, for the benefit of targets still using + // Glue for values in physregs. + else if (Node->getValueType(Node->getNumValues()-1) != MVT::Glue) + MI->addRegisterDead(Reg, TRI); + } + } + + // If the instruction has implicit defs and the node doesn't, mark the + // implicit def as dead. If the node has any glue outputs, we don't do this + // because we don't know what implicit defs are being used by glued nodes. + if (Node->getValueType(Node->getNumValues()-1) != MVT::Glue) + if (const unsigned *IDList = II.getImplicitDefs()) { + for (unsigned i = NumResults, e = II.getNumDefs()+II.getNumImplicitDefs(); + i != e; ++i) + MI->addRegisterDead(IDList[i-II.getNumDefs()], TRI); + } +} + +/// EmitSpecialNode - Generate machine code for a target-independent node and +/// needed dependencies. +void InstrEmitter:: +EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap) { + switch (Node->getOpcode()) { + default: +#ifndef NDEBUG + Node->dump(); +#endif + llvm_unreachable("This target-independent node should have been selected!"); + break; + case ISD::EntryToken: + llvm_unreachable("EntryToken should have been excluded from the schedule!"); + break; + case ISD::MERGE_VALUES: + case ISD::TokenFactor: // fall thru + break; + case ISD::CopyToReg: { + unsigned SrcReg; + SDValue SrcVal = Node->getOperand(2); + if (RegisterSDNode *R = dyn_cast(SrcVal)) + SrcReg = R->getReg(); + else + SrcReg = getVR(SrcVal, VRBaseMap); + + unsigned DestReg = cast(Node->getOperand(1))->getReg(); + if (SrcReg == DestReg) // Coalesced away the copy? Ignore. + break; + + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), + DestReg).addReg(SrcReg); + break; + } + case ISD::CopyFromReg: { + unsigned SrcReg = cast(Node->getOperand(1))->getReg(); + EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap); + break; + } + case ISD::EH_LABEL: { + MCSymbol *S = cast(Node)->getLabel(); + BuildMI(*MBB, InsertPos, Node->getDebugLoc(), + TII->get(TargetOpcode::EH_LABEL)).addSym(S); + break; + } + + case ISD::INLINEASM: { + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) + --NumOps; // Ignore the glue operand. + + // Create the inline asm machine instruction. + MachineInstr *MI = BuildMI(*MF, Node->getDebugLoc(), + TII->get(TargetOpcode::INLINEASM)); + + // Add the asm string as an external symbol operand. + SDValue AsmStrV = Node->getOperand(InlineAsm::Op_AsmString); + const char *AsmStr = cast(AsmStrV)->getSymbol(); + MI->addOperand(MachineOperand::CreateES(AsmStr)); + + // Add the HasSideEffect and isAlignStack bits. + int64_t ExtraInfo = + cast(Node->getOperand(InlineAsm::Op_ExtraInfo))-> + getZExtValue(); + MI->addOperand(MachineOperand::CreateImm(ExtraInfo)); + + // Add all of the operand registers to the instruction. + for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { + unsigned Flags = + cast(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + + MI->addOperand(MachineOperand::CreateImm(Flags)); + ++i; // Skip the ID value. + + switch (InlineAsm::getKind(Flags)) { + default: llvm_unreachable("Bad flags!"); + case InlineAsm::Kind_RegDef: + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + // FIXME: Add dead flags for physical and virtual registers defined. + // For now, mark physical register defs as implicit to help fast + // regalloc. This makes inline asm look a lot like calls. + MI->addOperand(MachineOperand::CreateReg(Reg, true, + /*isImp=*/ TargetRegisterInfo::isPhysicalRegister(Reg))); + } + break; + case InlineAsm::Kind_RegDefEarlyClobber: + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + MI->addOperand(MachineOperand::CreateReg(Reg, /*isDef=*/ true, + /*isImp=*/ TargetRegisterInfo::isPhysicalRegister(Reg), + /*isKill=*/ false, + /*isDead=*/ false, + /*isUndef=*/false, + /*isEarlyClobber=*/ true)); + } + break; + case InlineAsm::Kind_RegUse: // Use of register. + case InlineAsm::Kind_Imm: // Immediate. + case InlineAsm::Kind_Mem: // Addressing mode. + // The addressing mode has been selected, just add all of the + // operands to the machine instruction. + for (; NumVals; --NumVals, ++i) + AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap, + /*IsDebug=*/false, IsClone, IsCloned); + break; + } + } + + // Get the mdnode from the asm if it exists and add it to the instruction. + SDValue MDV = Node->getOperand(InlineAsm::Op_MDNode); + const MDNode *MD = cast(MDV)->getMD(); + if (MD) + MI->addOperand(MachineOperand::CreateMetadata(MD)); + + MBB->insert(InsertPos, MI); + break; + } + } +} + +/// InstrEmitter - Construct an InstrEmitter and set it to start inserting +/// at the given position in the given block. +InstrEmitter::InstrEmitter(MachineBasicBlock *mbb, + MachineBasicBlock::iterator insertpos) + : MF(mbb->getParent()), + MRI(&MF->getRegInfo()), + TM(&MF->getTarget()), + TII(TM->getInstrInfo()), + TRI(TM->getRegisterInfo()), + TLI(TM->getTargetLowering()), + MBB(mbb), InsertPos(insertpos) { +} diff --git a/final/lib/CodeGen/SelectionDAG/InstrEmitter.h b/final/lib/CodeGen/SelectionDAG/InstrEmitter.h new file mode 100644 index 00000000000..02c044c3f8f --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/InstrEmitter.h @@ -0,0 +1,142 @@ +//===---- InstrEmitter.h - Emit MachineInstrs for the SelectionDAG class ---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This declares the Emit routines for the SelectionDAG class, which creates +// MachineInstrs based on the decisions of the SelectionDAG instruction +// selection. +// +//===----------------------------------------------------------------------===// + +#ifndef INSTREMITTER_H +#define INSTREMITTER_H + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class TargetInstrDesc; +class SDDbgValue; + +class InstrEmitter { + MachineFunction *MF; + MachineRegisterInfo *MRI; + const TargetMachine *TM; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const TargetLowering *TLI; + + MachineBasicBlock *MBB; + MachineBasicBlock::iterator InsertPos; + + /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an + /// implicit physical register output. + void EmitCopyFromReg(SDNode *Node, unsigned ResNo, + bool IsClone, bool IsCloned, + unsigned SrcReg, + DenseMap &VRBaseMap); + + /// getDstOfCopyToRegUse - If the only use of the specified result number of + /// node is a CopyToReg, return its destination register. Return 0 otherwise. + unsigned getDstOfOnlyCopyToRegUse(SDNode *Node, + unsigned ResNo) const; + + void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, + const TargetInstrDesc &II, + bool IsClone, bool IsCloned, + DenseMap &VRBaseMap); + + /// getVR - Return the virtual register corresponding to the specified result + /// of the specified node. + unsigned getVR(SDValue Op, + DenseMap &VRBaseMap); + + /// AddRegisterOperand - Add the specified register as an operand to the + /// specified machine instr. Insert register copies if the register is + /// not in the required register class. + void AddRegisterOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap, + bool IsDebug, bool IsClone, bool IsCloned); + + /// AddOperand - Add the specified operand to the specified machine instr. II + /// specifies the instruction information for the node, and IIOpNum is the + /// operand number (in the II) that we are adding. IIOpNum and II are used for + /// assertions only. + void AddOperand(MachineInstr *MI, SDValue Op, + unsigned IIOpNum, + const TargetInstrDesc *II, + DenseMap &VRBaseMap, + bool IsDebug, bool IsClone, bool IsCloned); + + /// EmitSubregNode - Generate machine code for subreg nodes. + /// + void EmitSubregNode(SDNode *Node, DenseMap &VRBaseMap, + bool IsClone, bool IsCloned); + + /// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes. + /// COPY_TO_REGCLASS is just a normal copy, except that the destination + /// register is constrained to be in a particular register class. + /// + void EmitCopyToRegClassNode(SDNode *Node, + DenseMap &VRBaseMap); + + /// EmitRegSequence - Generate machine code for REG_SEQUENCE nodes. + /// + void EmitRegSequence(SDNode *Node, DenseMap &VRBaseMap, + bool IsClone, bool IsCloned); +public: + /// CountResults - The results of target nodes have register or immediate + /// operands first, then an optional chain, and optional flag operands + /// (which do not go into the machine instrs.) + static unsigned CountResults(SDNode *Node); + + /// CountOperands - The inputs to target nodes have any actual inputs first, + /// followed by an optional chain operand, then flag operands. Compute + /// the number of actual operands that will go into the resulting + /// MachineInstr. + static unsigned CountOperands(SDNode *Node); + + /// EmitDbgValue - Generate machine instruction for a dbg_value node. + /// + MachineInstr *EmitDbgValue(SDDbgValue *SD, + DenseMap &VRBaseMap); + + /// EmitNode - Generate machine code for a node and needed dependencies. + /// + void EmitNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap) { + if (Node->isMachineOpcode()) + EmitMachineNode(Node, IsClone, IsCloned, VRBaseMap); + else + EmitSpecialNode(Node, IsClone, IsCloned, VRBaseMap); + } + + /// getBlock - Return the current basic block. + MachineBasicBlock *getBlock() { return MBB; } + + /// getInsertPos - Return the current insertion position. + MachineBasicBlock::iterator getInsertPos() { return InsertPos; } + + /// InstrEmitter - Construct an InstrEmitter and set it to start inserting + /// at the given position in the given block. + InstrEmitter(MachineBasicBlock *mbb, MachineBasicBlock::iterator insertpos); + +private: + void EmitMachineNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap); + void EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, + DenseMap &VRBaseMap); +}; + +} + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp new file mode 100644 index 00000000000..94080a04e39 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -0,0 +1,3577 @@ +//===-- LegalizeDAG.cpp - Implement SelectionDAG::Legalize ----------------===// +// +// 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 SelectionDAG::Legalize method. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/LLVMContext.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and +/// hacks on it until the target machine can handle it. This involves +/// eliminating value sizes the machine cannot handle (promoting small sizes to +/// large sizes or splitting up large values into small values) as well as +/// eliminating operations the machine cannot handle. +/// +/// This code also does a small amount of optimization and recognition of idioms +/// as part of its processing. For example, if a target does not support a +/// 'setcc' instruction efficiently, but does support 'brcc' instruction, this +/// will attempt merge setcc and brc instructions into brcc's. +/// +namespace { +class SelectionDAGLegalize { + const TargetMachine &TM; + const TargetLowering &TLI; + SelectionDAG &DAG; + CodeGenOpt::Level OptLevel; + + // Libcall insertion helpers. + + /// LastCALLSEQ_END - This keeps track of the CALLSEQ_END node that has been + /// legalized. We use this to ensure that calls are properly serialized + /// against each other, including inserted libcalls. + SDValue LastCALLSEQ_END; + + enum LegalizeAction { + Legal, // The target natively supports this operation. + Promote, // This operation should be executed in a larger type. + Expand // Try to expand this to other ops, otherwise use a libcall. + }; + + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// value type, where the two bits correspond to the LegalizeAction enum. + /// This can be queried with "getTypeAction(VT)". + TargetLowering::ValueTypeActionImpl ValueTypeActions; + + /// LegalizedNodes - For nodes that are of legal width, and that have more + /// than one use, this map indicates what regularized operand to use. This + /// allows us to avoid legalizing the same thing more than once. + DenseMap LegalizedNodes; + + void AddLegalizedOperand(SDValue From, SDValue To) { + LegalizedNodes.insert(std::make_pair(From, To)); + // If someone requests legalization of the new node, return itself. + if (From != To) + LegalizedNodes.insert(std::make_pair(To, To)); + + // Transfer SDDbgValues. + DAG.TransferDbgValues(From, To); + } + +public: + SelectionDAGLegalize(SelectionDAG &DAG, CodeGenOpt::Level ol); + + /// getTypeAction - Return how we should legalize values of this type, either + /// it is already legal or we need to expand it into multiple registers of + /// smaller integer type, or we need to promote it to a larger type. + LegalizeAction getTypeAction(EVT VT) const { + return (LegalizeAction)ValueTypeActions.getTypeAction(VT); + } + + /// isTypeLegal - Return true if this type is legal on this target. + /// + bool isTypeLegal(EVT VT) const { + return getTypeAction(VT) == Legal; + } + + void LegalizeDAG(); + +private: + /// LegalizeOp - We know that the specified value has a legal type. + /// Recursively ensure that the operands have legal types, then return the + /// result. + SDValue LegalizeOp(SDValue O); + + SDValue OptimizeFloatStore(StoreSDNode *ST); + + /// PerformInsertVectorEltInMemory - Some target cannot handle a variable + /// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it + /// is necessary to spill the vector being inserted into to memory, perform + /// the insert there, and then read the result back. + SDValue PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, + SDValue Idx, DebugLoc dl); + SDValue ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, + SDValue Idx, DebugLoc dl); + + /// ShuffleWithNarrowerEltType - Return a vector shuffle operation which + /// performs the same shuffe in terms of order or result bytes, but on a type + /// whose vector element type is narrower than the original shuffle type. + /// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> + SDValue ShuffleWithNarrowerEltType(EVT NVT, EVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + SmallVectorImpl &Mask) const; + + bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, + SmallPtrSet &NodesLeadingTo); + + void LegalizeSetCCCondCode(EVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC, + DebugLoc dl); + + SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned); + std::pair ExpandChainLibCall(RTLIB::Libcall LC, + SDNode *Node, bool isSigned); + SDValue ExpandFPLibCall(SDNode *Node, RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128); + SDValue ExpandIntLibCall(SDNode *Node, bool isSigned, + RTLIB::Libcall Call_I8, + RTLIB::Libcall Call_I16, + RTLIB::Libcall Call_I32, + RTLIB::Libcall Call_I64, + RTLIB::Libcall Call_I128); + + SDValue EmitStackConvert(SDValue SrcOp, EVT SlotVT, EVT DestVT, DebugLoc dl); + SDValue ExpandBUILD_VECTOR(SDNode *Node); + SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node); + void ExpandDYNAMIC_STACKALLOC(SDNode *Node, + SmallVectorImpl &Results); + SDValue ExpandFCOPYSIGN(SDNode *Node); + SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, EVT DestVT, + DebugLoc dl); + SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, EVT DestVT, bool isSigned, + DebugLoc dl); + SDValue PromoteLegalFP_TO_INT(SDValue LegalOp, EVT DestVT, bool isSigned, + DebugLoc dl); + + SDValue ExpandBSWAP(SDValue Op, DebugLoc dl); + SDValue ExpandBitCount(unsigned Opc, SDValue Op, DebugLoc dl); + + SDValue ExpandExtractFromVectorThroughStack(SDValue Op); + SDValue ExpandInsertToVectorThroughStack(SDValue Op); + SDValue ExpandVectorBuildThroughStack(SDNode* Node); + + std::pair ExpandAtomic(SDNode *Node); + + void ExpandNode(SDNode *Node, SmallVectorImpl &Results); + void PromoteNode(SDNode *Node, SmallVectorImpl &Results); +}; +} + +/// ShuffleWithNarrowerEltType - Return a vector shuffle operation which +/// performs the same shuffe in terms of order or result bytes, but on a type +/// whose vector element type is narrower than the original shuffle type. +/// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> +SDValue +SelectionDAGLegalize::ShuffleWithNarrowerEltType(EVT NVT, EVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + SmallVectorImpl &Mask) const { + unsigned NumMaskElts = VT.getVectorNumElements(); + unsigned NumDestElts = NVT.getVectorNumElements(); + unsigned NumEltsGrowth = NumDestElts / NumMaskElts; + + assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); + + if (NumEltsGrowth == 1) + return DAG.getVectorShuffle(NVT, dl, N1, N2, &Mask[0]); + + SmallVector NewMask; + for (unsigned i = 0; i != NumMaskElts; ++i) { + int Idx = Mask[i]; + for (unsigned j = 0; j != NumEltsGrowth; ++j) { + if (Idx < 0) + NewMask.push_back(-1); + else + NewMask.push_back(Idx * NumEltsGrowth + j); + } + } + assert(NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); + assert(TLI.isShuffleMaskLegal(NewMask, NVT) && "Shuffle not legal?"); + return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); +} + +SelectionDAGLegalize::SelectionDAGLegalize(SelectionDAG &dag, + CodeGenOpt::Level ol) + : TM(dag.getTarget()), TLI(dag.getTargetLoweringInfo()), + DAG(dag), OptLevel(ol), + ValueTypeActions(TLI.getValueTypeActions()) { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); +} + +void SelectionDAGLegalize::LegalizeDAG() { + LastCALLSEQ_END = DAG.getEntryNode(); + + // The legalize process is inherently a bottom-up recursive process (users + // legalize their uses before themselves). Given infinite stack space, we + // could just start legalizing on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, compute an ordering of the nodes where each + // node is only legalized after all of its operands are legalized. + DAG.AssignTopologicalOrder(); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = prior(DAG.allnodes_end()); I != llvm::next(E); ++I) + LegalizeOp(SDValue(I, 0)); + + // Finally, it's possible the root changed. Get the new root. + SDValue OldRoot = DAG.getRoot(); + assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?"); + DAG.setRoot(LegalizedNodes[OldRoot]); + + LegalizedNodes.clear(); + + // Remove dead nodes now. + DAG.RemoveDeadNodes(); +} + + +/// FindCallEndFromCallStart - Given a chained node that is part of a call +/// sequence, find the CALLSEQ_END node that terminates the call sequence. +static SDNode *FindCallEndFromCallStart(SDNode *Node, int depth = 0) { + // Nested CALLSEQ_START/END constructs aren't yet legal, + // but we can DTRT and handle them correctly here. + if (Node->getOpcode() == ISD::CALLSEQ_START) + depth++; + else if (Node->getOpcode() == ISD::CALLSEQ_END) { + depth--; + if (depth == 0) + return Node; + } + if (Node->use_empty()) + return 0; // No CallSeqEnd + + // The chain is usually at the end. + SDValue TheChain(Node, Node->getNumValues()-1); + if (TheChain.getValueType() != MVT::Other) { + // Sometimes it's at the beginning. + TheChain = SDValue(Node, 0); + if (TheChain.getValueType() != MVT::Other) { + // Otherwise, hunt for it. + for (unsigned i = 1, e = Node->getNumValues(); i != e; ++i) + if (Node->getValueType(i) == MVT::Other) { + TheChain = SDValue(Node, i); + break; + } + + // Otherwise, we walked into a node without a chain. + if (TheChain.getValueType() != MVT::Other) + return 0; + } + } + + for (SDNode::use_iterator UI = Node->use_begin(), + E = Node->use_end(); UI != E; ++UI) { + + // Make sure to only follow users of our token chain. + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) + if (User->getOperand(i) == TheChain) + if (SDNode *Result = FindCallEndFromCallStart(User, depth)) + return Result; + } + return 0; +} + +/// FindCallStartFromCallEnd - Given a chained node that is part of a call +/// sequence, find the CALLSEQ_START node that initiates the call sequence. +static SDNode *FindCallStartFromCallEnd(SDNode *Node) { + int nested = 0; + assert(Node && "Didn't find callseq_start for a call??"); + while (Node->getOpcode() != ISD::CALLSEQ_START || nested) { + Node = Node->getOperand(0).getNode(); + assert(Node->getOperand(0).getValueType() == MVT::Other && + "Node doesn't have a token chain argument!"); + switch (Node->getOpcode()) { + default: + break; + case ISD::CALLSEQ_START: + if (!nested) + return Node; + nested--; + break; + case ISD::CALLSEQ_END: + nested++; + break; + } + } + return 0; +} + +/// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to +/// see if any uses can reach Dest. If no dest operands can get to dest, +/// legalize them, legalize ourself, and return false, otherwise, return true. +/// +/// Keep track of the nodes we fine that actually do lead to Dest in +/// NodesLeadingTo. This avoids retraversing them exponential number of times. +/// +bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, + SmallPtrSet &NodesLeadingTo) { + if (N == Dest) return true; // N certainly leads to Dest :) + + // If we've already processed this node and it does lead to Dest, there is no + // need to reprocess it. + if (NodesLeadingTo.count(N)) return true; + + // If the first result of this node has been already legalized, then it cannot + // reach N. + if (LegalizedNodes.count(SDValue(N, 0))) return false; + + // Okay, this node has not already been legalized. Check and legalize all + // operands. If none lead to Dest, then we can legalize this node. + bool OperandsLeadToDest = false; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + OperandsLeadToDest |= // If an operand leads to Dest, so do we. + LegalizeAllNodesNotLeadingTo(N->getOperand(i).getNode(), Dest, + NodesLeadingTo); + + if (OperandsLeadToDest) { + NodesLeadingTo.insert(N); + return true; + } + + // Okay, this node looks safe, legalize it and return false. + LegalizeOp(SDValue(N, 0)); + return false; +} + +/// ExpandConstantFP - Expands the ConstantFP node to an integer constant or +/// a load from the constant pool. +static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, + SelectionDAG &DAG, const TargetLowering &TLI) { + bool Extend = false; + DebugLoc dl = CFP->getDebugLoc(); + + // If a FP immediate is precise when represented as a float and if the + // target can do an extending load from float to double, we put it into + // the constant pool as a float, even if it's is statically typed as a + // double. This shrinks FP constants and canonicalizes them for targets where + // an FP extending load is the same cost as a normal load (such as on the x87 + // fp stack or PPC FP unit). + EVT VT = CFP->getValueType(0); + ConstantFP *LLVMC = const_cast(CFP->getConstantFPValue()); + if (!UseCP) { + assert((VT == MVT::f64 || VT == MVT::f32) && "Invalid type expansion"); + return DAG.getConstant(LLVMC->getValueAPF().bitcastToAPInt(), + (VT == MVT::f64) ? MVT::i64 : MVT::i32); + } + + EVT OrigVT = VT; + EVT SVT = VT; + while (SVT != MVT::f32) { + SVT = (MVT::SimpleValueType)(SVT.getSimpleVT().SimpleTy - 1); + if (ConstantFPSDNode::isValueValidForType(SVT, CFP->getValueAPF()) && + // Only do this if the target has a native EXTLOAD instruction from + // smaller type. + TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) && + TLI.ShouldShrinkFPConstant(OrigVT)) { + const Type *SType = SVT.getTypeForEVT(*DAG.getContext()); + LLVMC = cast(ConstantExpr::getFPTrunc(LLVMC, SType)); + VT = SVT; + Extend = true; + } + } + + SDValue CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + if (Extend) + return DAG.getExtLoad(ISD::EXTLOAD, dl, OrigVT, + DAG.getEntryNode(), + CPIdx, MachinePointerInfo::getConstantPool(), + VT, false, false, Alignment); + return DAG.getLoad(OrigVT, dl, DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), false, false, + Alignment); +} + +/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores. +static +SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, + const TargetLowering &TLI) { + SDValue Chain = ST->getChain(); + SDValue Ptr = ST->getBasePtr(); + SDValue Val = ST->getValue(); + EVT VT = Val.getValueType(); + int Alignment = ST->getAlignment(); + DebugLoc dl = ST->getDebugLoc(); + if (ST->getMemoryVT().isFloatingPoint() || + ST->getMemoryVT().isVector()) { + EVT intVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits()); + if (TLI.isTypeLegal(intVT)) { + // Expand to a bitconvert of the value to the integer type of the + // same size, then a (misaligned) int store. + // FIXME: Does not handle truncating floating point stores! + SDValue Result = DAG.getNode(ISD::BITCAST, dl, intVT, Val); + return DAG.getStore(Chain, dl, Result, Ptr, ST->getPointerInfo(), + ST->isVolatile(), ST->isNonTemporal(), Alignment); + } else { + // Do a (aligned) store to a stack slot, then copy from the stack slot + // to the final destination using (unaligned) integer loads and stores. + EVT StoredVT = ST->getMemoryVT(); + EVT RegVT = + TLI.getRegisterType(*DAG.getContext(), + EVT::getIntegerVT(*DAG.getContext(), + StoredVT.getSizeInBits())); + unsigned StoredBytes = StoredVT.getSizeInBits() / 8; + unsigned RegBytes = RegVT.getSizeInBits() / 8; + unsigned NumRegs = (StoredBytes + RegBytes - 1) / RegBytes; + + // Make sure the stack slot is also aligned for the register type. + SDValue StackPtr = DAG.CreateStackTemporary(StoredVT, RegVT); + + // Perform the original store, only redirected to the stack slot. + SDValue Store = DAG.getTruncStore(Chain, dl, + Val, StackPtr, MachinePointerInfo(), + StoredVT, false, false, 0); + SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); + SmallVector Stores; + unsigned Offset = 0; + + // Do all but one copies using the full register width. + for (unsigned i = 1; i < NumRegs; i++) { + // Load one integer register's worth from the stack slot. + SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, + MachinePointerInfo(), + false, false, 0); + // Store it to the final location. Remember the store. + Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, Ptr, + ST->getPointerInfo().getWithOffset(Offset), + ST->isVolatile(), ST->isNonTemporal(), + MinAlign(ST->getAlignment(), Offset))); + // Increment the pointers. + Offset += RegBytes; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + Increment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); + } + + // The last store may be partial. Do a truncating store. On big-endian + // machines this requires an extending load from the stack slot to ensure + // that the bits are in the right place. + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), + 8 * (StoredBytes - Offset)); + + // Load from the stack slot. + SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Store, StackPtr, + MachinePointerInfo(), + MemVT, false, false, 0); + + Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, Ptr, + ST->getPointerInfo() + .getWithOffset(Offset), + MemVT, ST->isVolatile(), + ST->isNonTemporal(), + MinAlign(ST->getAlignment(), Offset))); + // The order of the stores doesn't matter - say it with a TokenFactor. + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], + Stores.size()); + } + } + assert(ST->getMemoryVT().isInteger() && + !ST->getMemoryVT().isVector() && + "Unaligned store of unknown type."); + // Get the half-size VT + EVT NewStoredVT = ST->getMemoryVT().getHalfSizedIntegerVT(*DAG.getContext()); + int NumBits = NewStoredVT.getSizeInBits(); + int IncrementSize = NumBits / 8; + + // Divide the stored value in two parts. + SDValue ShiftAmount = DAG.getConstant(NumBits, + TLI.getShiftAmountTy(Val.getValueType())); + SDValue Lo = Val; + SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount); + + // Store the two parts + SDValue Store1, Store2; + Store1 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Lo:Hi, Ptr, + ST->getPointerInfo(), NewStoredVT, + ST->isVolatile(), ST->isNonTemporal(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Alignment = MinAlign(Alignment, IncrementSize); + Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr, + ST->getPointerInfo().getWithOffset(IncrementSize), + NewStoredVT, ST->isVolatile(), ST->isNonTemporal(), + Alignment); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); +} + +/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads. +static +SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, + const TargetLowering &TLI) { + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + EVT VT = LD->getValueType(0); + EVT LoadedVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + if (VT.isFloatingPoint() || VT.isVector()) { + EVT intVT = EVT::getIntegerVT(*DAG.getContext(), LoadedVT.getSizeInBits()); + if (TLI.isTypeLegal(intVT)) { + // Expand to a (misaligned) integer load of the same size, + // then bitconvert to floating point or vector. + SDValue newLoad = DAG.getLoad(intVT, dl, Chain, Ptr, LD->getPointerInfo(), + LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + SDValue Result = DAG.getNode(ISD::BITCAST, dl, LoadedVT, newLoad); + if (VT.isFloatingPoint() && LoadedVT != VT) + Result = DAG.getNode(ISD::FP_EXTEND, dl, VT, Result); + + SDValue Ops[] = { Result, Chain }; + return DAG.getMergeValues(Ops, 2, dl); + } + + // Copy the value to a (aligned) stack slot using (unaligned) integer + // loads and stores, then do a (aligned) load from the stack slot. + EVT RegVT = TLI.getRegisterType(*DAG.getContext(), intVT); + unsigned LoadedBytes = LoadedVT.getSizeInBits() / 8; + unsigned RegBytes = RegVT.getSizeInBits() / 8; + unsigned NumRegs = (LoadedBytes + RegBytes - 1) / RegBytes; + + // Make sure the stack slot is also aligned for the register type. + SDValue StackBase = DAG.CreateStackTemporary(LoadedVT, RegVT); + + SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); + SmallVector Stores; + SDValue StackPtr = StackBase; + unsigned Offset = 0; + + // Do all but one copies using the full register width. + for (unsigned i = 1; i < NumRegs; i++) { + // Load one integer register's worth from the original location. + SDValue Load = DAG.getLoad(RegVT, dl, Chain, Ptr, + LD->getPointerInfo().getWithOffset(Offset), + LD->isVolatile(), LD->isNonTemporal(), + MinAlign(LD->getAlignment(), Offset)); + // Follow the load with a store to the stack slot. Remember the store. + Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr, + MachinePointerInfo(), false, false, 0)); + // Increment the pointers. + Offset += RegBytes; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + Increment); + } + + // The last copy may be partial. Do an extending load. + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), + 8 * (LoadedBytes - Offset)); + SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Chain, Ptr, + LD->getPointerInfo().getWithOffset(Offset), + MemVT, LD->isVolatile(), + LD->isNonTemporal(), + MinAlign(LD->getAlignment(), Offset)); + // Follow the load with a store to the stack slot. Remember the store. + // On big-endian machines this requires a truncating store to ensure + // that the bits end up in the right place. + Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, StackPtr, + MachinePointerInfo(), MemVT, + false, false, 0)); + + // The order of the stores doesn't matter - say it with a TokenFactor. + SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], + Stores.size()); + + // Finally, perform the original load only redirected to the stack slot. + Load = DAG.getExtLoad(LD->getExtensionType(), dl, VT, TF, StackBase, + MachinePointerInfo(), LoadedVT, false, false, 0); + + // Callers expect a MERGE_VALUES node. + SDValue Ops[] = { Load, TF }; + return DAG.getMergeValues(Ops, 2, dl); + } + assert(LoadedVT.isInteger() && !LoadedVT.isVector() && + "Unaligned load of unsupported type."); + + // Compute the new VT that is half the size of the old one. This is an + // integer MVT. + unsigned NumBits = LoadedVT.getSizeInBits(); + EVT NewLoadedVT; + NewLoadedVT = EVT::getIntegerVT(*DAG.getContext(), NumBits/2); + NumBits >>= 1; + + unsigned Alignment = LD->getAlignment(); + unsigned IncrementSize = NumBits / 8; + ISD::LoadExtType HiExtType = LD->getExtensionType(); + + // If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD. + if (HiExtType == ISD::NON_EXTLOAD) + HiExtType = ISD::ZEXTLOAD; + + // Load the value in two parts + SDValue Lo, Hi; + if (TLI.isLittleEndian()) { + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getPointerInfo(), + NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, + LD->getPointerInfo().getWithOffset(IncrementSize), + NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(Alignment,IncrementSize)); + } else { + Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getPointerInfo(), + NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getConstant(IncrementSize, TLI.getPointerTy())); + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, + LD->getPointerInfo().getWithOffset(IncrementSize), + NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(Alignment,IncrementSize)); + } + + // aggregate the two parts + SDValue ShiftAmount = DAG.getConstant(NumBits, + TLI.getShiftAmountTy(Hi.getValueType())); + SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount); + Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo); + + SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + SDValue Ops[] = { Result, TF }; + return DAG.getMergeValues(Ops, 2, dl); +} + +/// PerformInsertVectorEltInMemory - Some target cannot handle a variable +/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it +/// is necessary to spill the vector being inserted into to memory, perform +/// the insert there, and then read the result back. +SDValue SelectionDAGLegalize:: +PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, + DebugLoc dl) { + SDValue Tmp1 = Vec; + SDValue Tmp2 = Val; + SDValue Tmp3 = Idx; + + // If the target doesn't support this, we have to spill the input vector + // to a temporary stack slot, update the element, then reload it. This is + // badness. We could also load the value into a vector register (either + // with a "move to register" or "extload into register" instruction, then + // permute it into place, if the idx is a constant and if the idx is + // supported by the target. + EVT VT = Tmp1.getValueType(); + EVT EltVT = VT.getVectorElementType(); + EVT IdxVT = Tmp3.getValueType(); + EVT PtrVT = TLI.getPointerTy(); + SDValue StackPtr = DAG.CreateStackTemporary(VT); + + int SPFI = cast(StackPtr.getNode())->getIndex(); + + // Store the vector. + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Tmp1, StackPtr, + MachinePointerInfo::getFixedStack(SPFI), + false, false, 0); + + // Truncate or zero extend offset to target pointer type. + unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + Tmp3 = DAG.getNode(CastOpc, dl, PtrVT, Tmp3); + // Add the offset to the index. + unsigned EltSize = EltVT.getSizeInBits()/8; + Tmp3 = DAG.getNode(ISD::MUL, dl, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT)); + SDValue StackPtr2 = DAG.getNode(ISD::ADD, dl, IdxVT, Tmp3, StackPtr); + // Store the scalar value. + Ch = DAG.getTruncStore(Ch, dl, Tmp2, StackPtr2, MachinePointerInfo(), EltVT, + false, false, 0); + // Load the updated vector. + return DAG.getLoad(VT, dl, Ch, StackPtr, + MachinePointerInfo::getFixedStack(SPFI), false, false, 0); +} + + +SDValue SelectionDAGLegalize:: +ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, DebugLoc dl) { + if (ConstantSDNode *InsertPos = dyn_cast(Idx)) { + // SCALAR_TO_VECTOR requires that the type of the value being inserted + // match the element type of the vector being created, except for + // integers in which case the inserted value can be over width. + EVT EltVT = Vec.getValueType().getVectorElementType(); + if (Val.getValueType() == EltVT || + (EltVT.isInteger() && Val.getValueType().bitsGE(EltVT))) { + SDValue ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, + Vec.getValueType(), Val); + + unsigned NumElts = Vec.getValueType().getVectorNumElements(); + // We generate a shuffle of InVec and ScVec, so the shuffle mask + // should be 0,1,2,3,4,5... with the appropriate element replaced with + // elt 0 of the RHS. + SmallVector ShufOps; + for (unsigned i = 0; i != NumElts; ++i) + ShufOps.push_back(i != InsertPos->getZExtValue() ? i : NumElts); + + return DAG.getVectorShuffle(Vec.getValueType(), dl, Vec, ScVec, + &ShufOps[0]); + } + } + return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl); +} + +SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { + // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' + // FIXME: We shouldn't do this for TargetConstantFP's. + // FIXME: move this to the DAG Combiner! Note that we can't regress due + // to phase ordering between legalized code and the dag combiner. This + // probably means that we need to integrate dag combiner and legalizer + // together. + // We generally can't do this one for long doubles. + SDValue Tmp1 = ST->getChain(); + SDValue Tmp2 = ST->getBasePtr(); + SDValue Tmp3; + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + DebugLoc dl = ST->getDebugLoc(); + if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { + if (CFP->getValueType(0) == MVT::f32 && + getTypeAction(MVT::i32) == Legal) { + Tmp3 = DAG.getConstant(CFP->getValueAPF(). + bitcastToAPInt().zextOrTrunc(32), + MVT::i32); + return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + } + + if (CFP->getValueType(0) == MVT::f64) { + // If this target supports 64-bit registers, do a single 64-bit store. + if (getTypeAction(MVT::i64) == Legal) { + Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). + zextOrTrunc(64), MVT::i64); + return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + } + + if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) { + // Otherwise, if the target supports 32-bit registers, use 2 32-bit + // stores. If the target supports neither 32- nor 64-bits, this + // xform is certainly not worth it. + const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt(); + SDValue Lo = DAG.getConstant(IntVal.trunc(32), MVT::i32); + SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32); + if (TLI.isBigEndian()) std::swap(Lo, Hi); + + Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getPointerInfo(), isVolatile, + isNonTemporal, Alignment); + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(4)); + Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, + ST->getPointerInfo().getWithOffset(4), + isVolatile, isNonTemporal, MinAlign(Alignment, 4U)); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } + } + } + return SDValue(); +} + +/// LegalizeOp - We know that the specified value has a legal type, and +/// that its operands are legal. Now ensure that the operation itself +/// is legal, recursively ensuring that the operands' operations remain +/// legal. +SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { + if (Op.getOpcode() == ISD::TargetConstant) // Allow illegal target nodes. + return Op; + + SDNode *Node = Op.getNode(); + DebugLoc dl = Node->getDebugLoc(); + + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + assert(getTypeAction(Node->getValueType(i)) == Legal && + "Unexpected illegal type!"); + + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + assert((isTypeLegal(Node->getOperand(i).getValueType()) || + Node->getOperand(i).getOpcode() == ISD::TargetConstant) && + "Unexpected illegal type!"); + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + DenseMap::iterator I = LegalizedNodes.find(Op); + if (I != LegalizedNodes.end()) return I->second; + + SDValue Tmp1, Tmp2, Tmp3, Tmp4; + SDValue Result = Op; + bool isCustom = false; + + // Figure out the correct action; the way to query this varies by opcode + TargetLowering::LegalizeAction Action = TargetLowering::Legal; + bool SimpleFinishLegalizing = true; + switch (Node->getOpcode()) { + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + case ISD::VAARG: + case ISD::STACKSAVE: + Action = TLI.getOperationAction(Node->getOpcode(), MVT::Other); + break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::EXTRACT_VECTOR_ELT: + Action = TLI.getOperationAction(Node->getOpcode(), + Node->getOperand(0).getValueType()); + break; + case ISD::FP_ROUND_INREG: + case ISD::SIGN_EXTEND_INREG: { + EVT InnerType = cast(Node->getOperand(1))->getVT(); + Action = TLI.getOperationAction(Node->getOpcode(), InnerType); + break; + } + case ISD::SELECT_CC: + case ISD::SETCC: + case ISD::BR_CC: { + unsigned CCOperand = Node->getOpcode() == ISD::SELECT_CC ? 4 : + Node->getOpcode() == ISD::SETCC ? 2 : 1; + unsigned CompareOperand = Node->getOpcode() == ISD::BR_CC ? 2 : 0; + EVT OpVT = Node->getOperand(CompareOperand).getValueType(); + ISD::CondCode CCCode = + cast(Node->getOperand(CCOperand))->get(); + Action = TLI.getCondCodeAction(CCCode, OpVT); + if (Action == TargetLowering::Legal) { + if (Node->getOpcode() == ISD::SELECT_CC) + Action = TLI.getOperationAction(Node->getOpcode(), + Node->getValueType(0)); + else + Action = TLI.getOperationAction(Node->getOpcode(), OpVT); + } + break; + } + case ISD::LOAD: + case ISD::STORE: + // FIXME: Model these properly. LOAD and STORE are complicated, and + // STORE expects the unlegalized operand in some cases. + SimpleFinishLegalizing = false; + break; + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: + // FIXME: This shouldn't be necessary. These nodes have special properties + // dealing with the recursive nature of legalization. Removing this + // special case should be done as part of making LegalizeDAG non-recursive. + SimpleFinishLegalizing = false; + break; + case ISD::EXTRACT_ELEMENT: + case ISD::FLT_ROUNDS_: + case ISD::SADDO: + case ISD::SSUBO: + case ISD::UADDO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + case ISD::FPOWI: + case ISD::MERGE_VALUES: + case ISD::EH_RETURN: + case ISD::FRAME_TO_ARGS_OFFSET: + case ISD::EH_SJLJ_SETJMP: + case ISD::EH_SJLJ_LONGJMP: + case ISD::EH_SJLJ_DISPATCHSETUP: + // These operations lie about being legal: when they claim to be legal, + // they should actually be expanded. + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + if (Action == TargetLowering::Legal) + Action = TargetLowering::Expand; + break; + case ISD::TRAMPOLINE: + case ISD::FRAMEADDR: + case ISD::RETURNADDR: + // These operations lie about being legal: when they claim to be legal, + // they should actually be custom-lowered. + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + if (Action == TargetLowering::Legal) + Action = TargetLowering::Custom; + break; + case ISD::BUILD_VECTOR: + // A weird case: legalization for BUILD_VECTOR never legalizes the + // operands! + // FIXME: This really sucks... changing it isn't semantically incorrect, + // but it massively pessimizes the code for floating-point BUILD_VECTORs + // because ConstantFP operands get legalized into constant pool loads + // before the BUILD_VECTOR code can see them. It doesn't usually bite, + // though, because BUILD_VECTORS usually get lowered into other nodes + // which get legalized properly. + SimpleFinishLegalizing = false; + break; + default: + if (Node->getOpcode() >= ISD::BUILTIN_OP_END) { + Action = TargetLowering::Legal; + } else { + Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)); + } + break; + } + + if (SimpleFinishLegalizing) { + SmallVector Ops, ResultVals; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Ops.push_back(LegalizeOp(Node->getOperand(i))); + switch (Node->getOpcode()) { + default: break; + case ISD::BR: + case ISD::BRIND: + case ISD::BR_JT: + case ISD::BR_CC: + case ISD::BRCOND: + // Branches tweak the chain to include LastCALLSEQ_END + Ops[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Ops[0], + LastCALLSEQ_END); + Ops[0] = LegalizeOp(Ops[0]); + LastCALLSEQ_END = DAG.getEntryNode(); + break; + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: + case ISD::ROTL: + case ISD::ROTR: + // Legalizing shifts/rotates requires adjusting the shift amount + // to the appropriate width. + if (!Ops[1].getValueType().isVector()) + Ops[1] = LegalizeOp(DAG.getShiftAmountOperand(Ops[0].getValueType(), + Ops[1])); + break; + case ISD::SRL_PARTS: + case ISD::SRA_PARTS: + case ISD::SHL_PARTS: + // Legalizing shifts/rotates requires adjusting the shift amount + // to the appropriate width. + if (!Ops[2].getValueType().isVector()) + Ops[2] = LegalizeOp(DAG.getShiftAmountOperand(Ops[0].getValueType(), + Ops[2])); + break; + } + + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), Ops.data(), + Ops.size()), 0); + switch (Action) { + case TargetLowering::Legal: + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + ResultVals.push_back(Result.getValue(i)); + break; + case TargetLowering::Custom: + // FIXME: The handling for custom lowering with multiple results is + // a complete mess. + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) { + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) { + if (e == 1) + ResultVals.push_back(Tmp1); + else + ResultVals.push_back(Tmp1.getValue(i)); + } + break; + } + + // FALL THROUGH + case TargetLowering::Expand: + ExpandNode(Result.getNode(), ResultVals); + break; + case TargetLowering::Promote: + PromoteNode(Result.getNode(), ResultVals); + break; + } + if (!ResultVals.empty()) { + for (unsigned i = 0, e = ResultVals.size(); i != e; ++i) { + if (ResultVals[i] != SDValue(Node, i)) + ResultVals[i] = LegalizeOp(ResultVals[i]); + AddLegalizedOperand(SDValue(Node, i), ResultVals[i]); + } + return ResultVals[Op.getResNo()]; + } + } + + switch (Node->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "NODE: "; + Node->dump( &DAG); + dbgs() << "\n"; +#endif + assert(0 && "Do not know how to legalize this operator!"); + + case ISD::BUILD_VECTOR: + switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Custom: + Tmp3 = TLI.LowerOperation(Result, DAG); + if (Tmp3.getNode()) { + Result = Tmp3; + break; + } + // FALLTHROUGH + case TargetLowering::Expand: + Result = ExpandBUILD_VECTOR(Result.getNode()); + break; + } + break; + case ISD::CALLSEQ_START: { + static int depth = 0; + SDNode *CallEnd = FindCallEndFromCallStart(Node); + + // Recursively Legalize all of the inputs of the call end that do not lead + // to this call start. This ensures that any libcalls that need be inserted + // are inserted *before* the CALLSEQ_START. + {SmallPtrSet NodesLeadingTo; + for (unsigned i = 0, e = CallEnd->getNumOperands(); i != e; ++i) + LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).getNode(), Node, + NodesLeadingTo); + } + + // Now that we have legalized all of the inputs (which may have inserted + // libcalls), create the new CALLSEQ_START node. + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. + + // Merge in the last call to ensure that this call starts after the last + // call ended. + if (LastCALLSEQ_END.getOpcode() != ISD::EntryToken && depth == 0) { + Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + Tmp1, LastCALLSEQ_END); + Tmp1 = LegalizeOp(Tmp1); + } + + // Do not try to legalize the target-specific arguments (#1+). + if (Tmp1 != Node->getOperand(0)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), &Ops[0], + Ops.size()), Result.getResNo()); + } + + // Remember that the CALLSEQ_START is legalized. + AddLegalizedOperand(Op.getValue(0), Result); + if (Node->getNumValues() == 2) // If this has a flag result, remember it. + AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); + + // Now that the callseq_start and all of the non-call nodes above this call + // sequence have been legalized, legalize the call itself. During this + // process, no libcalls can/will be inserted, guaranteeing that no calls + // can overlap. + + SDValue Saved_LastCALLSEQ_END = LastCALLSEQ_END ; + // Note that we are selecting this call! + LastCALLSEQ_END = SDValue(CallEnd, 0); + + depth++; + // Legalize the call, starting from the CALLSEQ_END. + LegalizeOp(LastCALLSEQ_END); + depth--; + assert(depth >= 0 && "Un-matched CALLSEQ_START?"); + if (depth > 0) + LastCALLSEQ_END = Saved_LastCALLSEQ_END; + return Result; + } + case ISD::CALLSEQ_END: + // If the CALLSEQ_START node hasn't been legalized first, legalize it. This + // will cause this node to be legalized as well as handling libcalls right. + if (LastCALLSEQ_END.getNode() != Node) { + LegalizeOp(SDValue(FindCallStartFromCallEnd(Node), 0)); + DenseMap::iterator I = LegalizedNodes.find(Op); + assert(I != LegalizedNodes.end() && + "Legalizing the call start should have legalized this node!"); + return I->second; + } + + // Otherwise, the call start has been legalized and everything is going + // according to plan. Just legalize ourselves normally here. + Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. + // Do not try to legalize the target-specific arguments (#1+), except for + // an optional flag input. + if (Node->getOperand(Node->getNumOperands()-1).getValueType() != MVT::Glue){ + if (Tmp1 != Node->getOperand(0)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + &Ops[0], Ops.size()), + Result.getResNo()); + } + } else { + Tmp2 = LegalizeOp(Node->getOperand(Node->getNumOperands()-1)); + if (Tmp1 != Node->getOperand(0) || + Tmp2 != Node->getOperand(Node->getNumOperands()-1)) { + SmallVector Ops(Node->op_begin(), Node->op_end()); + Ops[0] = Tmp1; + Ops.back() = Tmp2; + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + &Ops[0], Ops.size()), + Result.getResNo()); + } + } + // This finishes up call legalization. + // If the CALLSEQ_END node has a flag, remember that we legalized it. + AddLegalizedOperand(SDValue(Node, 0), Result.getValue(0)); + if (Node->getNumValues() == 2) + AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1)); + return Result.getValue(Op.getResNo()); + case ISD::LOAD: { + LoadSDNode *LD = cast(Node); + Tmp1 = LegalizeOp(LD->getChain()); // Legalize the chain. + Tmp2 = LegalizeOp(LD->getBasePtr()); // Legalize the base pointer. + + ISD::LoadExtType ExtType = LD->getExtensionType(); + if (ExtType == ISD::NON_EXTLOAD) { + EVT VT = Node->getValueType(0); + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + Tmp1, Tmp2, LD->getOffset()), + Result.getResNo()); + Tmp3 = Result.getValue(0); + Tmp4 = Result.getValue(1); + + switch (TLI.getOperationAction(Node->getOpcode(), VT)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned load and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { + const Type *Ty = LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = TLI.getTargetData()->getABITypeAlignment(Ty); + if (LD->getAlignment() < ABIAlignment){ + Result = ExpandUnalignedLoad(cast(Result.getNode()), + DAG, TLI); + Tmp3 = Result.getOperand(0); + Tmp4 = Result.getOperand(1); + Tmp3 = LegalizeOp(Tmp3); + Tmp4 = LegalizeOp(Tmp4); + } + } + break; + case TargetLowering::Custom: + Tmp1 = TLI.LowerOperation(Tmp3, DAG); + if (Tmp1.getNode()) { + Tmp3 = LegalizeOp(Tmp1); + Tmp4 = LegalizeOp(Tmp1.getValue(1)); + } + break; + case TargetLowering::Promote: { + // Only promote a load of vector type to another. + assert(VT.isVector() && "Cannot promote this load!"); + // Change base type to a different vector type. + EVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), VT); + + Tmp1 = DAG.getLoad(NVT, dl, Tmp1, Tmp2, LD->getPointerInfo(), + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); + Tmp3 = LegalizeOp(DAG.getNode(ISD::BITCAST, dl, VT, Tmp1)); + Tmp4 = LegalizeOp(Tmp1.getValue(1)); + break; + } + } + // Since loads produce two values, make sure to remember that we + // legalized both of them. + AddLegalizedOperand(SDValue(Node, 0), Tmp3); + AddLegalizedOperand(SDValue(Node, 1), Tmp4); + return Op.getResNo() ? Tmp4 : Tmp3; + } + + EVT SrcVT = LD->getMemoryVT(); + unsigned SrcWidth = SrcVT.getSizeInBits(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + + if (SrcWidth != SrcVT.getStoreSizeInBits() && + // Some targets pretend to have an i1 loading operation, and actually + // load an i8. This trick is correct for ZEXTLOAD because the top 7 + // bits are guaranteed to be zero; it helps the optimizers understand + // that these bits are zero. It is also useful for EXTLOAD, since it + // tells the optimizers that those bits are undefined. It would be + // nice to have an effective generic way of getting these benefits... + // Until such a way is found, don't insist on promoting i1 here. + (SrcVT != MVT::i1 || + TLI.getLoadExtAction(ExtType, MVT::i1) == TargetLowering::Promote)) { + // Promote to a byte-sized load if not loading an integral number of + // bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24. + unsigned NewWidth = SrcVT.getStoreSizeInBits(); + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), NewWidth); + SDValue Ch; + + // The extra bits are guaranteed to be zero, since we stored them that + // way. A zext load from NVT thus automatically gives zext from SrcVT. + + ISD::LoadExtType NewExtType = + ExtType == ISD::ZEXTLOAD ? ISD::ZEXTLOAD : ISD::EXTLOAD; + + Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0), + Tmp1, Tmp2, LD->getPointerInfo(), + NVT, isVolatile, isNonTemporal, Alignment); + + Ch = Result.getValue(1); // The chain. + + if (ExtType == ISD::SEXTLOAD) + // Having the top bits zero doesn't help when sign extending. + Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, + Result.getValueType(), + Result, DAG.getValueType(SrcVT)); + else if (ExtType == ISD::ZEXTLOAD || NVT == Result.getValueType()) + // All the top bits are guaranteed to be zero - inform the optimizers. + Result = DAG.getNode(ISD::AssertZext, dl, + Result.getValueType(), Result, + DAG.getValueType(SrcVT)); + + Tmp1 = LegalizeOp(Result); + Tmp2 = LegalizeOp(Ch); + } else if (SrcWidth & (SrcWidth - 1)) { + // If not loading a power-of-2 number of bits, expand as two loads. + assert(!SrcVT.isVector() && "Unsupported extload!"); + unsigned RoundWidth = 1 << Log2_32(SrcWidth); + assert(RoundWidth < SrcWidth); + unsigned ExtraWidth = SrcWidth - RoundWidth; + assert(ExtraWidth < RoundWidth); + assert(!(RoundWidth % 8) && !(ExtraWidth % 8) && + "Load size not an integral number of bytes!"); + EVT RoundVT = EVT::getIntegerVT(*DAG.getContext(), RoundWidth); + EVT ExtraVT = EVT::getIntegerVT(*DAG.getContext(), ExtraWidth); + SDValue Lo, Hi, Ch; + unsigned IncrementSize; + + if (TLI.isLittleEndian()) { + // EXTLOAD:i24 -> ZEXTLOAD:i16 | (shl EXTLOAD@+2:i8, 16) + // Load the bottom RoundWidth bits. + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), + Tmp1, Tmp2, + LD->getPointerInfo(), RoundVT, isVolatile, + isNonTemporal, Alignment); + + // Load the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, + LD->getPointerInfo().getWithOffset(IncrementSize), + ExtraVT, isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of + // the other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Move the top bits to the right place. + Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, + DAG.getConstant(RoundWidth, + TLI.getShiftAmountTy(Hi.getValueType()))); + + // Join the hi and lo parts. + Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); + } else { + // Big endian - avoid unaligned loads. + // EXTLOAD:i24 -> (shl EXTLOAD:i16, 8) | ZEXTLOAD@+2:i8 + // Load the top RoundWidth bits. + Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, + LD->getPointerInfo(), RoundVT, isVolatile, + isNonTemporal, Alignment); + + // Load the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, + dl, Node->getValueType(0), Tmp1, Tmp2, + LD->getPointerInfo().getWithOffset(IncrementSize), + ExtraVT, isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of + // the other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Move the top bits to the right place. + Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi, + DAG.getConstant(ExtraWidth, + TLI.getShiftAmountTy(Hi.getValueType()))); + + // Join the hi and lo parts. + Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi); + } + + Tmp1 = LegalizeOp(Result); + Tmp2 = LegalizeOp(Ch); + } else { + switch (TLI.getLoadExtAction(ExtType, SrcVT)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Custom: + isCustom = true; + // FALLTHROUGH + case TargetLowering::Legal: + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + Tmp1, Tmp2, LD->getOffset()), + Result.getResNo()); + Tmp1 = Result.getValue(0); + Tmp2 = Result.getValue(1); + + if (isCustom) { + Tmp3 = TLI.LowerOperation(Result, DAG); + if (Tmp3.getNode()) { + Tmp1 = LegalizeOp(Tmp3); + Tmp2 = LegalizeOp(Tmp3.getValue(1)); + } + } else { + // If this is an unaligned load and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(LD->getMemoryVT())) { + const Type *Ty = + LD->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment = + TLI.getTargetData()->getABITypeAlignment(Ty); + if (LD->getAlignment() < ABIAlignment){ + Result = ExpandUnalignedLoad(cast(Result.getNode()), + DAG, TLI); + Tmp1 = Result.getOperand(0); + Tmp2 = Result.getOperand(1); + Tmp1 = LegalizeOp(Tmp1); + Tmp2 = LegalizeOp(Tmp2); + } + } + } + break; + case TargetLowering::Expand: + if (!TLI.isLoadExtLegal(ISD::EXTLOAD, SrcVT) && isTypeLegal(SrcVT)) { + SDValue Load = DAG.getLoad(SrcVT, dl, Tmp1, Tmp2, + LD->getPointerInfo(), + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); + unsigned ExtendOp; + switch (ExtType) { + case ISD::EXTLOAD: + ExtendOp = (SrcVT.isFloatingPoint() ? + ISD::FP_EXTEND : ISD::ANY_EXTEND); + break; + case ISD::SEXTLOAD: ExtendOp = ISD::SIGN_EXTEND; break; + case ISD::ZEXTLOAD: ExtendOp = ISD::ZERO_EXTEND; break; + default: llvm_unreachable("Unexpected extend load type!"); + } + Result = DAG.getNode(ExtendOp, dl, Node->getValueType(0), Load); + Tmp1 = LegalizeOp(Result); // Relegalize new nodes. + Tmp2 = LegalizeOp(Load.getValue(1)); + break; + } + // FIXME: This does not work for vectors on most targets. Sign- and + // zero-extend operations are currently folded into extending loads, + // whether they are legal or not, and then we end up here without any + // support for legalizing them. + assert(ExtType != ISD::EXTLOAD && + "EXTLOAD should always be supported!"); + // Turn the unsupported load into an EXTLOAD followed by an explicit + // zero/sign extend inreg. + Result = DAG.getExtLoad(ISD::EXTLOAD, dl, Node->getValueType(0), + Tmp1, Tmp2, LD->getPointerInfo(), SrcVT, + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); + SDValue ValRes; + if (ExtType == ISD::SEXTLOAD) + ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, + Result.getValueType(), + Result, DAG.getValueType(SrcVT)); + else + ValRes = DAG.getZeroExtendInReg(Result, dl, SrcVT.getScalarType()); + Tmp1 = LegalizeOp(ValRes); // Relegalize new nodes. + Tmp2 = LegalizeOp(Result.getValue(1)); // Relegalize new nodes. + break; + } + } + + // Since loads produce two values, make sure to remember that we legalized + // both of them. + AddLegalizedOperand(SDValue(Node, 0), Tmp1); + AddLegalizedOperand(SDValue(Node, 1), Tmp2); + return Op.getResNo() ? Tmp2 : Tmp1; + } + case ISD::STORE: { + StoreSDNode *ST = cast(Node); + Tmp1 = LegalizeOp(ST->getChain()); // Legalize the chain. + Tmp2 = LegalizeOp(ST->getBasePtr()); // Legalize the pointer. + unsigned Alignment = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + + if (!ST->isTruncatingStore()) { + if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) { + Result = SDValue(OptStore, 0); + break; + } + + { + Tmp3 = LegalizeOp(ST->getValue()); + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + Tmp1, Tmp3, Tmp2, + ST->getOffset()), + Result.getResNo()); + + EVT VT = Tmp3.getValueType(); + switch (TLI.getOperationAction(ISD::STORE, VT)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned store and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { + const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment= TLI.getTargetData()->getABITypeAlignment(Ty); + if (ST->getAlignment() < ABIAlignment) + Result = ExpandUnalignedStore(cast(Result.getNode()), + DAG, TLI); + } + break; + case TargetLowering::Custom: + Tmp1 = TLI.LowerOperation(Result, DAG); + if (Tmp1.getNode()) Result = Tmp1; + break; + case TargetLowering::Promote: + assert(VT.isVector() && "Unknown legal promote case!"); + Tmp3 = DAG.getNode(ISD::BITCAST, dl, + TLI.getTypeToPromoteTo(ISD::STORE, VT), Tmp3); + Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, + ST->getPointerInfo(), isVolatile, + isNonTemporal, Alignment); + break; + } + break; + } + } else { + Tmp3 = LegalizeOp(ST->getValue()); + + EVT StVT = ST->getMemoryVT(); + unsigned StWidth = StVT.getSizeInBits(); + + if (StWidth != StVT.getStoreSizeInBits()) { + // Promote to a byte-sized store with upper bits zero if not + // storing an integral number of bytes. For example, promote + // TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1) + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), + StVT.getStoreSizeInBits()); + Tmp3 = DAG.getZeroExtendInReg(Tmp3, dl, StVT); + Result = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getPointerInfo(), + NVT, isVolatile, isNonTemporal, Alignment); + } else if (StWidth & (StWidth - 1)) { + // If not storing a power-of-2 number of bits, expand as two stores. + assert(!StVT.isVector() && "Unsupported truncstore!"); + unsigned RoundWidth = 1 << Log2_32(StWidth); + assert(RoundWidth < StWidth); + unsigned ExtraWidth = StWidth - RoundWidth; + assert(ExtraWidth < RoundWidth); + assert(!(RoundWidth % 8) && !(ExtraWidth % 8) && + "Store size not an integral number of bytes!"); + EVT RoundVT = EVT::getIntegerVT(*DAG.getContext(), RoundWidth); + EVT ExtraVT = EVT::getIntegerVT(*DAG.getContext(), ExtraWidth); + SDValue Lo, Hi; + unsigned IncrementSize; + + if (TLI.isLittleEndian()) { + // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 X, TRUNCSTORE@+2:i8 (srl X, 16) + // Store the bottom RoundWidth bits. + Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getPointerInfo(), + RoundVT, + isVolatile, isNonTemporal, Alignment); + + // Store the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, + DAG.getConstant(RoundWidth, + TLI.getShiftAmountTy(Tmp3.getValueType()))); + Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, + ST->getPointerInfo().getWithOffset(IncrementSize), + ExtraVT, isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + } else { + // Big endian - avoid unaligned stores. + // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X + // Store the top RoundWidth bits. + Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, + DAG.getConstant(ExtraWidth, + TLI.getShiftAmountTy(Tmp3.getValueType()))); + Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getPointerInfo(), + RoundVT, isVolatile, isNonTemporal, Alignment); + + // Store the remaining ExtraWidth bits. + IncrementSize = RoundWidth / 8; + Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, + DAG.getIntPtrConstant(IncrementSize)); + Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, + ST->getPointerInfo().getWithOffset(IncrementSize), + ExtraVT, isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + } + + // The order of the stores doesn't matter. + Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } else { + if (Tmp1 != ST->getChain() || Tmp3 != ST->getValue() || + Tmp2 != ST->getBasePtr()) + Result = SDValue(DAG.UpdateNodeOperands(Result.getNode(), + Tmp1, Tmp3, Tmp2, + ST->getOffset()), + Result.getResNo()); + + switch (TLI.getTruncStoreAction(ST->getValue().getValueType(), StVT)) { + default: assert(0 && "This action is not supported yet!"); + case TargetLowering::Legal: + // If this is an unaligned store and the target doesn't support it, + // expand it. + if (!TLI.allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { + const Type *Ty = ST->getMemoryVT().getTypeForEVT(*DAG.getContext()); + unsigned ABIAlignment= TLI.getTargetData()->getABITypeAlignment(Ty); + if (ST->getAlignment() < ABIAlignment) + Result = ExpandUnalignedStore(cast(Result.getNode()), + DAG, TLI); + } + break; + case TargetLowering::Custom: + Result = TLI.LowerOperation(Result, DAG); + break; + case Expand: + // TRUNCSTORE:i16 i32 -> STORE i16 + assert(isTypeLegal(StVT) && "Do not know how to expand this store!"); + Tmp3 = DAG.getNode(ISD::TRUNCATE, dl, StVT, Tmp3); + Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + break; + } + } + } + break; + } + } + assert(Result.getValueType() == Op.getValueType() && + "Bad legalization!"); + + // Make sure that the generated code is itself legal. + if (Result != Op) + Result = LegalizeOp(Result); + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + AddLegalizedOperand(Op, Result); + return Result; +} + +SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { + SDValue Vec = Op.getOperand(0); + SDValue Idx = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + // Store the value to a temporary stack slot, then LOAD the returned part. + SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType()); + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, + MachinePointerInfo(), false, false, 0); + + // Add the offset to the index. + unsigned EltSize = + Vec.getValueType().getVectorElementType().getSizeInBits()/8; + Idx = DAG.getNode(ISD::MUL, dl, Idx.getValueType(), Idx, + DAG.getConstant(EltSize, Idx.getValueType())); + + if (Idx.getValueType().bitsGT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Idx); + else + Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx); + + StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr); + + if (Op.getValueType().isVector()) + return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr,MachinePointerInfo(), + false, false, 0); + return DAG.getExtLoad(ISD::EXTLOAD, dl, Op.getValueType(), Ch, StackPtr, + MachinePointerInfo(), + Vec.getValueType().getVectorElementType(), + false, false, 0); +} + +SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { + assert(Op.getValueType().isVector() && "Non-vector insert subvector!"); + + SDValue Vec = Op.getOperand(0); + SDValue Part = Op.getOperand(1); + SDValue Idx = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + // Store the value to a temporary stack slot, then LOAD the returned part. + + SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType()); + int FI = cast(StackPtr.getNode())->getIndex(); + MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(FI); + + // First store the whole vector. + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo, + false, false, 0); + + // Then store the inserted part. + + // Add the offset to the index. + unsigned EltSize = + Vec.getValueType().getVectorElementType().getSizeInBits()/8; + + Idx = DAG.getNode(ISD::MUL, dl, Idx.getValueType(), Idx, + DAG.getConstant(EltSize, Idx.getValueType())); + + if (Idx.getValueType().bitsGT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Idx); + else + Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx); + + SDValue SubStackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, + StackPtr); + + // Store the subvector. + Ch = DAG.getStore(DAG.getEntryNode(), dl, Part, SubStackPtr, + MachinePointerInfo(), false, false, 0); + + // Finally, load the updated vector. + return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, PtrInfo, + false, false, 0); +} + +SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { + // We can't handle this case efficiently. Allocate a sufficiently + // aligned object on the stack, store each element into it, then load + // the result as a vector. + // Create the stack frame object. + EVT VT = Node->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = Node->getDebugLoc(); + SDValue FIPtr = DAG.CreateStackTemporary(VT); + int FI = cast(FIPtr.getNode())->getIndex(); + MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(FI); + + // Emit a store of each element to the stack slot. + SmallVector Stores; + unsigned TypeByteSize = EltVT.getSizeInBits() / 8; + // Store (in the right endianness) the elements to memory. + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + // Ignore undef elements. + if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue; + + unsigned Offset = TypeByteSize*i; + + SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType()); + Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx); + + // If the destination vector element type is narrower than the source + // element type, only store the bits necessary. + if (EltVT.bitsLT(Node->getOperand(i).getValueType().getScalarType())) { + Stores.push_back(DAG.getTruncStore(DAG.getEntryNode(), dl, + Node->getOperand(i), Idx, + PtrInfo.getWithOffset(Offset), + EltVT, false, false, 0)); + } else + Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, + Node->getOperand(i), Idx, + PtrInfo.getWithOffset(Offset), + false, false, 0)); + } + + SDValue StoreChain; + if (!Stores.empty()) // Not all undef elements? + StoreChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &Stores[0], Stores.size()); + else + StoreChain = DAG.getEntryNode(); + + // Result is a load from the stack slot. + return DAG.getLoad(VT, dl, StoreChain, FIPtr, PtrInfo, false, false, 0); +} + +SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1 = Node->getOperand(0); + SDValue Tmp2 = Node->getOperand(1); + + // Get the sign bit of the RHS. First obtain a value that has the same + // sign as the sign bit, i.e. negative if and only if the sign bit is 1. + SDValue SignBit; + EVT FloatVT = Tmp2.getValueType(); + EVT IVT = EVT::getIntegerVT(*DAG.getContext(), FloatVT.getSizeInBits()); + if (isTypeLegal(IVT)) { + // Convert to an integer with the same sign bit. + SignBit = DAG.getNode(ISD::BITCAST, dl, IVT, Tmp2); + } else { + // Store the float to memory, then load the sign part out as an integer. + MVT LoadTy = TLI.getPointerTy(); + // First create a temporary that is aligned for both the load and store. + SDValue StackPtr = DAG.CreateStackTemporary(FloatVT, LoadTy); + // Then store the float to it. + SDValue Ch = + DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StackPtr, MachinePointerInfo(), + false, false, 0); + if (TLI.isBigEndian()) { + assert(FloatVT.isByteSized() && "Unsupported floating point type!"); + // Load out a legal integer with the same sign bit as the float. + SignBit = DAG.getLoad(LoadTy, dl, Ch, StackPtr, MachinePointerInfo(), + false, false, 0); + } else { // Little endian + SDValue LoadPtr = StackPtr; + // The float may be wider than the integer we are going to load. Advance + // the pointer so that the loaded integer will contain the sign bit. + unsigned Strides = (FloatVT.getSizeInBits()-1)/LoadTy.getSizeInBits(); + unsigned ByteOffset = (Strides * LoadTy.getSizeInBits()) / 8; + LoadPtr = DAG.getNode(ISD::ADD, dl, LoadPtr.getValueType(), + LoadPtr, DAG.getIntPtrConstant(ByteOffset)); + // Load a legal integer containing the sign bit. + SignBit = DAG.getLoad(LoadTy, dl, Ch, LoadPtr, MachinePointerInfo(), + false, false, 0); + // Move the sign bit to the top bit of the loaded integer. + unsigned BitShift = LoadTy.getSizeInBits() - + (FloatVT.getSizeInBits() - 8 * ByteOffset); + assert(BitShift < LoadTy.getSizeInBits() && "Pointer advanced wrong?"); + if (BitShift) + SignBit = DAG.getNode(ISD::SHL, dl, LoadTy, SignBit, + DAG.getConstant(BitShift, + TLI.getShiftAmountTy(SignBit.getValueType()))); + } + } + // Now get the sign bit proper, by seeing whether the value is negative. + SignBit = DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()), + SignBit, DAG.getConstant(0, SignBit.getValueType()), + ISD::SETLT); + // Get the absolute value of the result. + SDValue AbsVal = DAG.getNode(ISD::FABS, dl, Tmp1.getValueType(), Tmp1); + // Select between the nabs and abs value based on the sign bit of + // the input. + return DAG.getNode(ISD::SELECT, dl, AbsVal.getValueType(), SignBit, + DAG.getNode(ISD::FNEG, dl, AbsVal.getValueType(), AbsVal), + AbsVal); +} + +void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node, + SmallVectorImpl &Results) { + unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore(); + assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and" + " not tell us which reg is the stack pointer!"); + DebugLoc dl = Node->getDebugLoc(); + EVT VT = Node->getValueType(0); + SDValue Tmp1 = SDValue(Node, 0); + SDValue Tmp2 = SDValue(Node, 1); + SDValue Tmp3 = Node->getOperand(2); + SDValue Chain = Tmp1.getOperand(0); + + // Chain the dynamic stack allocation so that it doesn't modify the stack + // pointer when other instructions are using the stack. + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); + + SDValue Size = Tmp2.getOperand(1); + SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT); + Chain = SP.getValue(1); + unsigned Align = cast(Tmp3)->getZExtValue(); + unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); + if (Align > StackAlign) + SP = DAG.getNode(ISD::AND, dl, VT, SP, + DAG.getConstant(-(uint64_t)Align, VT)); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value + Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain + + Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true), + DAG.getIntPtrConstant(0, true), SDValue()); + + Results.push_back(Tmp1); + Results.push_back(Tmp2); +} + +/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and +/// condition code CC on the current target. This routine expands SETCC with +/// illegal condition code into AND / OR of multiple SETCC values. +void SelectionDAGLegalize::LegalizeSetCCCondCode(EVT VT, + SDValue &LHS, SDValue &RHS, + SDValue &CC, + DebugLoc dl) { + EVT OpVT = LHS.getValueType(); + ISD::CondCode CCCode = cast(CC)->get(); + switch (TLI.getCondCodeAction(CCCode, OpVT)) { + default: assert(0 && "Unknown condition code action!"); + case TargetLowering::Legal: + // Nothing to do. + break; + case TargetLowering::Expand: { + ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID; + unsigned Opc = 0; + switch (CCCode) { + default: assert(0 && "Don't know how to expand this condition!"); + case ISD::SETOEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGT: CC1 = ISD::SETGT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOGE: CC1 = ISD::SETGE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLT: CC1 = ISD::SETLT; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETOLE: CC1 = ISD::SETLE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETONE: CC1 = ISD::SETNE; CC2 = ISD::SETO; Opc = ISD::AND; break; + case ISD::SETUEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGT: CC1 = ISD::SETGT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUGE: CC1 = ISD::SETGE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULT: CC1 = ISD::SETLT; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETULE: CC1 = ISD::SETLE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + case ISD::SETUNE: CC1 = ISD::SETNE; CC2 = ISD::SETUO; Opc = ISD::OR; break; + // FIXME: Implement more expansions. + } + + SDValue SetCC1 = DAG.getSetCC(dl, VT, LHS, RHS, CC1); + SDValue SetCC2 = DAG.getSetCC(dl, VT, LHS, RHS, CC2); + LHS = DAG.getNode(Opc, dl, VT, SetCC1, SetCC2); + RHS = SDValue(); + CC = SDValue(); + break; + } + } +} + +/// EmitStackConvert - Emit a store/load combination to the stack. This stores +/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does +/// a load from the stack slot to DestVT, extending it if needed. +/// The resultant code need not be legal. +SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp, + EVT SlotVT, + EVT DestVT, + DebugLoc dl) { + // Create the stack frame object. + unsigned SrcAlign = + TLI.getTargetData()->getPrefTypeAlignment(SrcOp.getValueType(). + getTypeForEVT(*DAG.getContext())); + SDValue FIPtr = DAG.CreateStackTemporary(SlotVT, SrcAlign); + + FrameIndexSDNode *StackPtrFI = cast(FIPtr); + int SPFI = StackPtrFI->getIndex(); + MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(SPFI); + + unsigned SrcSize = SrcOp.getValueType().getSizeInBits(); + unsigned SlotSize = SlotVT.getSizeInBits(); + unsigned DestSize = DestVT.getSizeInBits(); + const Type *DestType = DestVT.getTypeForEVT(*DAG.getContext()); + unsigned DestAlign = TLI.getTargetData()->getPrefTypeAlignment(DestType); + + // Emit a store to the stack slot. Use a truncstore if the input value is + // later than DestVT. + SDValue Store; + + if (SrcSize > SlotSize) + Store = DAG.getTruncStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, + PtrInfo, SlotVT, false, false, SrcAlign); + else { + assert(SrcSize == SlotSize && "Invalid store"); + Store = DAG.getStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, + PtrInfo, false, false, SrcAlign); + } + + // Result is a load from the stack slot. + if (SlotSize == DestSize) + return DAG.getLoad(DestVT, dl, Store, FIPtr, PtrInfo, + false, false, DestAlign); + + assert(SlotSize < DestSize && "Unknown extension!"); + return DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, Store, FIPtr, + PtrInfo, SlotVT, false, false, DestAlign); +} + +SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { + DebugLoc dl = Node->getDebugLoc(); + // Create a vector sized/aligned stack slot, store the value to element #0, + // then load the whole vector back out. + SDValue StackPtr = DAG.CreateStackTemporary(Node->getValueType(0)); + + FrameIndexSDNode *StackPtrFI = cast(StackPtr); + int SPFI = StackPtrFI->getIndex(); + + SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0), + StackPtr, + MachinePointerInfo::getFixedStack(SPFI), + Node->getValueType(0).getVectorElementType(), + false, false, 0); + return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr, + MachinePointerInfo::getFixedStack(SPFI), + false, false, 0); +} + + +/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't +/// support the operation, but do support the resultant vector type. +SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { + unsigned NumElems = Node->getNumOperands(); + SDValue Value1, Value2; + DebugLoc dl = Node->getDebugLoc(); + EVT VT = Node->getValueType(0); + EVT OpVT = Node->getOperand(0).getValueType(); + EVT EltVT = VT.getVectorElementType(); + + // If the only non-undef value is the low element, turn this into a + // SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X. + bool isOnlyLowElement = true; + bool MoreThanTwoValues = false; + bool isConstant = true; + for (unsigned i = 0; i < NumElems; ++i) { + SDValue V = Node->getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + if (i > 0) + isOnlyLowElement = false; + if (!isa(V) && !isa(V)) + isConstant = false; + + if (!Value1.getNode()) { + Value1 = V; + } else if (!Value2.getNode()) { + if (V != Value1) + Value2 = V; + } else if (V != Value1 && V != Value2) { + MoreThanTwoValues = true; + } + } + + if (!Value1.getNode()) + return DAG.getUNDEF(VT); + + if (isOnlyLowElement) + return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Node->getOperand(0)); + + // If all elements are constants, create a load from the constant pool. + if (isConstant) { + std::vector CV; + for (unsigned i = 0, e = NumElems; i != e; ++i) { + if (ConstantFPSDNode *V = + dyn_cast(Node->getOperand(i))) { + CV.push_back(const_cast(V->getConstantFPValue())); + } else if (ConstantSDNode *V = + dyn_cast(Node->getOperand(i))) { + if (OpVT==EltVT) + CV.push_back(const_cast(V->getConstantIntValue())); + else { + // If OpVT and EltVT don't match, EltVT is not legal and the + // element values have been promoted/truncated earlier. Undo this; + // we don't want a v16i8 to become a v16i32 for example. + const ConstantInt *CI = V->getConstantIntValue(); + CV.push_back(ConstantInt::get(EltVT.getTypeForEVT(*DAG.getContext()), + CI->getZExtValue())); + } + } else { + assert(Node->getOperand(i).getOpcode() == ISD::UNDEF); + const Type *OpNTy = EltVT.getTypeForEVT(*DAG.getContext()); + CV.push_back(UndefValue::get(OpNTy)); + } + } + Constant *CP = ConstantVector::get(CV); + SDValue CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + return DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), + false, false, Alignment); + } + + if (!MoreThanTwoValues) { + SmallVector ShuffleVec(NumElems, -1); + for (unsigned i = 0; i < NumElems; ++i) { + SDValue V = Node->getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + ShuffleVec[i] = V == Value1 ? 0 : NumElems; + } + if (TLI.isShuffleMaskLegal(ShuffleVec, Node->getValueType(0))) { + // Get the splatted value into the low element of a vector register. + SDValue Vec1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value1); + SDValue Vec2; + if (Value2.getNode()) + Vec2 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value2); + else + Vec2 = DAG.getUNDEF(VT); + + // Return shuffle(LowValVec, undef, <0,0,0,0>) + return DAG.getVectorShuffle(VT, dl, Vec1, Vec2, ShuffleVec.data()); + } + } + + // Otherwise, we can't handle this case efficiently. + return ExpandVectorBuildThroughStack(Node); +} + +// ExpandLibCall - Expand a node into a call to a libcall. If the result value +// does not fit into a register, return the lo part and set the hi part to the +// by-reg argument. If it does fit into a single register, return the result +// and leave the Hi part unset. +SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, + bool isSigned) { + // The input chain to this libcall is the entry node of the function. + // Legalizing the call will automatically add the previous call to the + // dependence. + SDValue InChain = DAG.getEntryNode(); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + EVT ArgVT = Node->getOperand(i).getValueType(); + const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy; + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + // Splice the libcall in wherever FindInputOutputChains tells us to. + const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + + // isTailCall may be true since the callee does not reference caller stack + // frame. Check if it's in the right position. + bool isTailCall = isInTailCallPosition(DAG, Node, TLI); + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + 0, TLI.getLibcallCallingConv(LC), isTailCall, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, Node->getDebugLoc()); + + if (!CallInfo.second.getNode()) + // It's a tailcall, return the chain (which is the DAG root). + return DAG.getRoot(); + + // Legalize the call sequence, starting with the chain. This will advance + // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that + // was added by LowerCallTo (guaranteeing proper serialization of calls). + LegalizeOp(CallInfo.second); + return CallInfo.first; +} + +// ExpandChainLibCall - Expand a node into a call to a libcall. Similar to +// ExpandLibCall except that the first operand is the in-chain. +std::pair +SelectionDAGLegalize::ExpandChainLibCall(RTLIB::Libcall LC, + SDNode *Node, + bool isSigned) { + SDValue InChain = Node->getOperand(0); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i) { + EVT ArgVT = Node->getOperand(i).getValueType(); + const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Entry.Node = Node->getOperand(i); + Entry.Ty = ArgTy; + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + // Splice the libcall in wherever FindInputOutputChains tells us to. + const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + 0, TLI.getLibcallCallingConv(LC), /*isTailCall=*/false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, Node->getDebugLoc()); + + // Legalize the call sequence, starting with the chain. This will advance + // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that + // was added by LowerCallTo (guaranteeing proper serialization of calls). + LegalizeOp(CallInfo.second); + return CallInfo; +} + +SDValue SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node, + RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, + RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128) { + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: assert(0 && "Unexpected request for libcall!"); + case MVT::f32: LC = Call_F32; break; + case MVT::f64: LC = Call_F64; break; + case MVT::f80: LC = Call_F80; break; + case MVT::ppcf128: LC = Call_PPCF128; break; + } + return ExpandLibCall(LC, Node, false); +} + +SDValue SelectionDAGLegalize::ExpandIntLibCall(SDNode* Node, bool isSigned, + RTLIB::Libcall Call_I8, + RTLIB::Libcall Call_I16, + RTLIB::Libcall Call_I32, + RTLIB::Libcall Call_I64, + RTLIB::Libcall Call_I128) { + RTLIB::Libcall LC; + switch (Node->getValueType(0).getSimpleVT().SimpleTy) { + default: assert(0 && "Unexpected request for libcall!"); + case MVT::i8: LC = Call_I8; break; + case MVT::i16: LC = Call_I16; break; + case MVT::i32: LC = Call_I32; break; + case MVT::i64: LC = Call_I64; break; + case MVT::i128: LC = Call_I128; break; + } + return ExpandLibCall(LC, Node, isSigned); +} + +/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a +/// INT_TO_FP operation of the specified operand when the target requests that +/// we expand it. At this point, we know that the result and operand types are +/// legal for the target. +SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, + SDValue Op0, + EVT DestVT, + DebugLoc dl) { + if (Op0.getValueType() == MVT::i32) { + // simple 32-bit [signed|unsigned] integer to float/double expansion + + // Get the stack frame index of a 8 byte buffer. + SDValue StackSlot = DAG.CreateStackTemporary(MVT::f64); + + // word offset constant for Hi/Lo address computation + SDValue WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy()); + // set up Hi and Lo (into buffer) address based on endian + SDValue Hi = StackSlot; + SDValue Lo = DAG.getNode(ISD::ADD, dl, + TLI.getPointerTy(), StackSlot, WordOff); + if (TLI.isLittleEndian()) + std::swap(Hi, Lo); + + // if signed map to unsigned space + SDValue Op0Mapped; + if (isSigned) { + // constant used to invert sign bit (signed to unsigned mapping) + SDValue SignBit = DAG.getConstant(0x80000000u, MVT::i32); + Op0Mapped = DAG.getNode(ISD::XOR, dl, MVT::i32, Op0, SignBit); + } else { + Op0Mapped = Op0; + } + // store the lo of the constructed double - based on integer input + SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, + Op0Mapped, Lo, MachinePointerInfo(), + false, false, 0); + // initial hi portion of constructed double + SDValue InitialHi = DAG.getConstant(0x43300000u, MVT::i32); + // store the hi of the constructed double - biased exponent + SDValue Store2 = DAG.getStore(Store1, dl, InitialHi, Hi, + MachinePointerInfo(), + false, false, 0); + // load the constructed double + SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, + MachinePointerInfo(), false, false, 0); + // FP constant to bias correct the final result + SDValue Bias = DAG.getConstantFP(isSigned ? + BitsToDouble(0x4330000080000000ULL) : + BitsToDouble(0x4330000000000000ULL), + MVT::f64); + // subtract the bias + SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::f64, Load, Bias); + // final result + SDValue Result; + // handle final rounding + if (DestVT == MVT::f64) { + // do nothing + Result = Sub; + } else if (DestVT.bitsLT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_ROUND, dl, DestVT, Sub, + DAG.getIntPtrConstant(0)); + } else if (DestVT.bitsGT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_EXTEND, dl, DestVT, Sub); + } + return Result; + } + assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); + // Code below here assumes !isSigned without checking again. + + // Implementation of unsigned i64 to f64 following the algorithm in + // __floatundidf in compiler_rt. This implementation has the advantage + // of performing rounding correctly, both in the default rounding mode + // and in all alternate rounding modes. + // TODO: Generalize this for use with other types. + if (Op0.getValueType() == MVT::i64 && DestVT == MVT::f64) { + SDValue TwoP52 = + DAG.getConstant(UINT64_C(0x4330000000000000), MVT::i64); + SDValue TwoP84PlusTwoP52 = + DAG.getConstantFP(BitsToDouble(UINT64_C(0x4530000000100000)), MVT::f64); + SDValue TwoP84 = + DAG.getConstant(UINT64_C(0x4530000000000000), MVT::i64); + + SDValue Lo = DAG.getZeroExtendInReg(Op0, dl, MVT::i32); + SDValue Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, + DAG.getConstant(32, MVT::i64)); + SDValue LoOr = DAG.getNode(ISD::OR, dl, MVT::i64, Lo, TwoP52); + SDValue HiOr = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, TwoP84); + SDValue LoFlt = DAG.getNode(ISD::BITCAST, dl, MVT::f64, LoOr); + SDValue HiFlt = DAG.getNode(ISD::BITCAST, dl, MVT::f64, HiOr); + SDValue HiSub = DAG.getNode(ISD::FSUB, dl, MVT::f64, HiFlt, + TwoP84PlusTwoP52); + return DAG.getNode(ISD::FADD, dl, MVT::f64, LoFlt, HiSub); + } + + // Implementation of unsigned i64 to f32. + // TODO: Generalize this for use with other types. + if (Op0.getValueType() == MVT::i64 && DestVT == MVT::f32) { + // For unsigned conversions, convert them to signed conversions using the + // algorithm from the x86_64 __floatundidf in compiler_rt. + if (!isSigned) { + SDValue Fast = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, Op0); + + SDValue ShiftConst = + DAG.getConstant(1, TLI.getShiftAmountTy(Op0.getValueType())); + SDValue Shr = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, ShiftConst); + SDValue AndConst = DAG.getConstant(1, MVT::i64); + SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, AndConst); + SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i64, And, Shr); + + SDValue SignCvt = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, Or); + SDValue Slow = DAG.getNode(ISD::FADD, dl, MVT::f32, SignCvt, SignCvt); + + // TODO: This really should be implemented using a branch rather than a + // select. We happen to get lucky and machinesink does the right + // thing most of the time. This would be a good candidate for a + //pseudo-op, or, even better, for whole-function isel. + SDValue SignBitTest = DAG.getSetCC(dl, TLI.getSetCCResultType(MVT::i64), + Op0, DAG.getConstant(0, MVT::i64), ISD::SETLT); + return DAG.getNode(ISD::SELECT, dl, MVT::f32, SignBitTest, Slow, Fast); + } + + // Otherwise, implement the fully general conversion. + + SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, + DAG.getConstant(UINT64_C(0xfffffffffffff800), MVT::i64)); + SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i64, And, + DAG.getConstant(UINT64_C(0x800), MVT::i64)); + SDValue And2 = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, + DAG.getConstant(UINT64_C(0x7ff), MVT::i64)); + SDValue Ne = DAG.getSetCC(dl, TLI.getSetCCResultType(MVT::i64), + And2, DAG.getConstant(UINT64_C(0), MVT::i64), ISD::SETNE); + SDValue Sel = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ne, Or, Op0); + SDValue Ge = DAG.getSetCC(dl, TLI.getSetCCResultType(MVT::i64), + Op0, DAG.getConstant(UINT64_C(0x0020000000000000), MVT::i64), + ISD::SETUGE); + SDValue Sel2 = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ge, Sel, Op0); + EVT SHVT = TLI.getShiftAmountTy(Sel2.getValueType()); + + SDValue Sh = DAG.getNode(ISD::SRL, dl, MVT::i64, Sel2, + DAG.getConstant(32, SHVT)); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Sh); + SDValue Fcvt = DAG.getNode(ISD::UINT_TO_FP, dl, MVT::f64, Trunc); + SDValue TwoP32 = + DAG.getConstantFP(BitsToDouble(UINT64_C(0x41f0000000000000)), MVT::f64); + SDValue Fmul = DAG.getNode(ISD::FMUL, dl, MVT::f64, TwoP32, Fcvt); + SDValue Lo = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Sel2); + SDValue Fcvt2 = DAG.getNode(ISD::UINT_TO_FP, dl, MVT::f64, Lo); + SDValue Fadd = DAG.getNode(ISD::FADD, dl, MVT::f64, Fmul, Fcvt2); + return DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Fadd, + DAG.getIntPtrConstant(0)); + } + + SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0); + + SDValue SignSet = DAG.getSetCC(dl, TLI.getSetCCResultType(Op0.getValueType()), + Op0, DAG.getConstant(0, Op0.getValueType()), + ISD::SETLT); + SDValue Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); + SDValue CstOffset = DAG.getNode(ISD::SELECT, dl, Zero.getValueType(), + SignSet, Four, Zero); + + // If the sign bit of the integer is set, the large number will be treated + // as a negative number. To counteract this, the dynamic code adds an + // offset depending on the data type. + uint64_t FF; + switch (Op0.getValueType().getSimpleVT().SimpleTy) { + default: assert(0 && "Unsupported integer type!"); + case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) + case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) + case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) + case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) + } + if (TLI.isLittleEndian()) FF <<= 32; + Constant *FudgeFactor = ConstantInt::get( + Type::getInt64Ty(*DAG.getContext()), FF); + + SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + unsigned Alignment = cast(CPIdx)->getAlignment(); + CPIdx = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), CPIdx, CstOffset); + Alignment = std::min(Alignment, 4u); + SDValue FudgeInReg; + if (DestVT == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, dl, DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), + false, false, Alignment); + else { + FudgeInReg = + LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, + DAG.getEntryNode(), CPIdx, + MachinePointerInfo::getConstantPool(), + MVT::f32, false, false, Alignment)); + } + + return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg); +} + +/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a +/// *INT_TO_FP operation of the specified operand when the target requests that +/// we promote it. At this point, we know that the result and operand types are +/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP +/// operation that takes a larger input. +SDValue SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDValue LegalOp, + EVT DestVT, + bool isSigned, + DebugLoc dl) { + // First step, figure out the appropriate *INT_TO_FP operation to use. + EVT NewInTy = LegalOp.getValueType(); + + unsigned OpToUse = 0; + + // Scan for the appropriate larger type to use. + while (1) { + NewInTy = (MVT::SimpleValueType)(NewInTy.getSimpleVT().SimpleTy+1); + assert(NewInTy.isInteger() && "Ran out of possibilities!"); + + // If the target supports SINT_TO_FP of this type, use it. + if (TLI.isOperationLegalOrCustom(ISD::SINT_TO_FP, NewInTy)) { + OpToUse = ISD::SINT_TO_FP; + break; + } + if (isSigned) continue; + + // If the target supports UINT_TO_FP of this type, use it. + if (TLI.isOperationLegalOrCustom(ISD::UINT_TO_FP, NewInTy)) { + OpToUse = ISD::UINT_TO_FP; + break; + } + + // Otherwise, try a larger type. + } + + // Okay, we found the operation and type to use. Zero extend our input to the + // desired type then run the operation on it. + return DAG.getNode(OpToUse, dl, DestVT, + DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, + dl, NewInTy, LegalOp)); +} + +/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a +/// FP_TO_*INT operation of the specified operand when the target requests that +/// we promote it. At this point, we know that the result and operand types are +/// legal for the target, and that there is a legal FP_TO_UINT or FP_TO_SINT +/// operation that returns a larger result. +SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp, + EVT DestVT, + bool isSigned, + DebugLoc dl) { + // First step, figure out the appropriate FP_TO*INT operation to use. + EVT NewOutTy = DestVT; + + unsigned OpToUse = 0; + + // Scan for the appropriate larger type to use. + while (1) { + NewOutTy = (MVT::SimpleValueType)(NewOutTy.getSimpleVT().SimpleTy+1); + assert(NewOutTy.isInteger() && "Ran out of possibilities!"); + + if (TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NewOutTy)) { + OpToUse = ISD::FP_TO_SINT; + break; + } + + if (TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NewOutTy)) { + OpToUse = ISD::FP_TO_UINT; + break; + } + + // Otherwise, try a larger type. + } + + + // Okay, we found the operation and type to use. + SDValue Operation = DAG.getNode(OpToUse, dl, NewOutTy, LegalOp); + + // Truncate the result of the extended FP_TO_*INT operation to the desired + // size. + return DAG.getNode(ISD::TRUNCATE, dl, DestVT, Operation); +} + +/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation. +/// +SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) { + EVT VT = Op.getValueType(); + EVT SHVT = TLI.getShiftAmountTy(VT); + SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8; + switch (VT.getSimpleVT().SimpleTy) { + default: assert(0 && "Unhandled Expand type in BSWAP!"); + case MVT::i16: + Tmp2 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + return DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + case MVT::i32: + Tmp4 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(0xFF0000, VT)); + Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(0xFF00, VT)); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1); + return DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2); + case MVT::i64: + Tmp8 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(40, SHVT)); + Tmp6 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp5 = DAG.getNode(ISD::SHL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp4 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(8, SHVT)); + Tmp3 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(24, SHVT)); + Tmp2 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(40, SHVT)); + Tmp1 = DAG.getNode(ISD::SRL, dl, VT, Op, DAG.getConstant(56, SHVT)); + Tmp7 = DAG.getNode(ISD::AND, dl, VT, Tmp7, DAG.getConstant(255ULL<<48, VT)); + Tmp6 = DAG.getNode(ISD::AND, dl, VT, Tmp6, DAG.getConstant(255ULL<<40, VT)); + Tmp5 = DAG.getNode(ISD::AND, dl, VT, Tmp5, DAG.getConstant(255ULL<<32, VT)); + Tmp4 = DAG.getNode(ISD::AND, dl, VT, Tmp4, DAG.getConstant(255ULL<<24, VT)); + Tmp3 = DAG.getNode(ISD::AND, dl, VT, Tmp3, DAG.getConstant(255ULL<<16, VT)); + Tmp2 = DAG.getNode(ISD::AND, dl, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT)); + Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp7); + Tmp6 = DAG.getNode(ISD::OR, dl, VT, Tmp6, Tmp5); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp3); + Tmp2 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp1); + Tmp8 = DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp6); + Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp2); + return DAG.getNode(ISD::OR, dl, VT, Tmp8, Tmp4); + } +} + +/// SplatByte - Distribute ByteVal over NumBits bits. +// FIXME: Move this helper to a common place. +static APInt SplatByte(unsigned NumBits, uint8_t ByteVal) { + APInt Val = APInt(NumBits, ByteVal); + unsigned Shift = 8; + for (unsigned i = NumBits; i > 8; i >>= 1) { + Val = (Val << Shift) | Val; + Shift <<= 1; + } + return Val; +} + +/// ExpandBitCount - Expand the specified bitcount instruction into operations. +/// +SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op, + DebugLoc dl) { + switch (Opc) { + default: assert(0 && "Cannot expand this yet!"); + case ISD::CTPOP: { + EVT VT = Op.getValueType(); + EVT ShVT = TLI.getShiftAmountTy(VT); + unsigned Len = VT.getSizeInBits(); + + assert(VT.isInteger() && Len <= 128 && Len % 8 == 0 && + "CTPOP not implemented for this type."); + + // This is the "best" algorithm from + // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + + SDValue Mask55 = DAG.getConstant(SplatByte(Len, 0x55), VT); + SDValue Mask33 = DAG.getConstant(SplatByte(Len, 0x33), VT); + SDValue Mask0F = DAG.getConstant(SplatByte(Len, 0x0F), VT); + SDValue Mask01 = DAG.getConstant(SplatByte(Len, 0x01), VT); + + // v = v - ((v >> 1) & 0x55555555...) + Op = DAG.getNode(ISD::SUB, dl, VT, Op, + DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::SRL, dl, VT, Op, + DAG.getConstant(1, ShVT)), + Mask55)); + // v = (v & 0x33333333...) + ((v >> 2) & 0x33333333...) + Op = DAG.getNode(ISD::ADD, dl, VT, + DAG.getNode(ISD::AND, dl, VT, Op, Mask33), + DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::SRL, dl, VT, Op, + DAG.getConstant(2, ShVT)), + Mask33)); + // v = (v + (v >> 4)) & 0x0F0F0F0F... + Op = DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::ADD, dl, VT, Op, + DAG.getNode(ISD::SRL, dl, VT, Op, + DAG.getConstant(4, ShVT))), + Mask0F); + // v = (v * 0x01010101...) >> (Len - 8) + Op = DAG.getNode(ISD::SRL, dl, VT, + DAG.getNode(ISD::MUL, dl, VT, Op, Mask01), + DAG.getConstant(Len - 8, ShVT)); + + return Op; + } + case ISD::CTLZ: { + // for now, we do this: + // x = x | (x >> 1); + // x = x | (x >> 2); + // ... + // x = x | (x >>16); + // x = x | (x >>32); // for 64-bit input + // return popcount(~x); + // + // but see also: http://www.hackersdelight.org/HDcode/nlz.cc + EVT VT = Op.getValueType(); + EVT ShVT = TLI.getShiftAmountTy(VT); + unsigned len = VT.getSizeInBits(); + for (unsigned i = 0; (1U << i) <= (len / 2); ++i) { + SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT); + Op = DAG.getNode(ISD::OR, dl, VT, Op, + DAG.getNode(ISD::SRL, dl, VT, Op, Tmp3)); + } + Op = DAG.getNOT(dl, Op, VT); + return DAG.getNode(ISD::CTPOP, dl, VT, Op); + } + case ISD::CTTZ: { + // for now, we use: { return popcount(~x & (x - 1)); } + // unless the target has ctlz but not ctpop, in which case we use: + // { return 32 - nlz(~x & (x-1)); } + // see also http://www.hackersdelight.org/HDcode/ntz.cc + EVT VT = Op.getValueType(); + SDValue Tmp3 = DAG.getNode(ISD::AND, dl, VT, + DAG.getNOT(dl, Op, VT), + DAG.getNode(ISD::SUB, dl, VT, Op, + DAG.getConstant(1, VT))); + // If ISD::CTLZ is legal and CTPOP isn't, then do that instead. + if (!TLI.isOperationLegalOrCustom(ISD::CTPOP, VT) && + TLI.isOperationLegalOrCustom(ISD::CTLZ, VT)) + return DAG.getNode(ISD::SUB, dl, VT, + DAG.getConstant(VT.getSizeInBits(), VT), + DAG.getNode(ISD::CTLZ, dl, VT, Tmp3)); + return DAG.getNode(ISD::CTPOP, dl, VT, Tmp3); + } + } +} + +std::pair SelectionDAGLegalize::ExpandAtomic(SDNode *Node) { + unsigned Opc = Node->getOpcode(); + MVT VT = cast(Node)->getMemoryVT().getSimpleVT(); + RTLIB::Libcall LC; + + switch (Opc) { + default: + llvm_unreachable("Unhandled atomic intrinsic Expand!"); + break; + case ISD::ATOMIC_SWAP: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_1; break; + case MVT::i16: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_2; break; + case MVT::i32: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_4; break; + case MVT::i64: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_8; break; + } + break; + case ISD::ATOMIC_CMP_SWAP: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1; break; + case MVT::i16: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2; break; + case MVT::i32: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_4; break; + case MVT::i64: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_8; break; + } + break; + case ISD::ATOMIC_LOAD_ADD: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_ADD_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_ADD_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_ADD_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_ADD_8; break; + } + break; + case ISD::ATOMIC_LOAD_SUB: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_SUB_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_SUB_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_SUB_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_SUB_8; break; + } + break; + case ISD::ATOMIC_LOAD_AND: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_AND_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_AND_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_AND_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_AND_8; break; + } + break; + case ISD::ATOMIC_LOAD_OR: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_OR_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_OR_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_OR_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_OR_8; break; + } + break; + case ISD::ATOMIC_LOAD_XOR: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_XOR_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_XOR_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_XOR_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_XOR_8; break; + } + break; + case ISD::ATOMIC_LOAD_NAND: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_NAND_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_NAND_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_NAND_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_NAND_8; break; + } + break; + } + + return ExpandChainLibCall(LC, Node, false); +} + +void SelectionDAGLegalize::ExpandNode(SDNode *Node, + SmallVectorImpl &Results) { + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1, Tmp2, Tmp3, Tmp4; + switch (Node->getOpcode()) { + case ISD::CTPOP: + case ISD::CTLZ: + case ISD::CTTZ: + Tmp1 = ExpandBitCount(Node->getOpcode(), Node->getOperand(0), dl); + Results.push_back(Tmp1); + break; + case ISD::BSWAP: + Results.push_back(ExpandBSWAP(Node->getOperand(0), dl)); + break; + case ISD::FRAMEADDR: + case ISD::RETURNADDR: + case ISD::FRAME_TO_ARGS_OFFSET: + Results.push_back(DAG.getConstant(0, Node->getValueType(0))); + break; + case ISD::FLT_ROUNDS_: + Results.push_back(DAG.getConstant(1, Node->getValueType(0))); + break; + case ISD::EH_RETURN: + case ISD::EH_LABEL: + case ISD::PREFETCH: + case ISD::VAEND: + case ISD::EH_SJLJ_LONGJMP: + case ISD::EH_SJLJ_DISPATCHSETUP: + // If the target didn't expand these, there's nothing to do, so just + // preserve the chain and be done. + Results.push_back(Node->getOperand(0)); + break; + case ISD::EH_SJLJ_SETJMP: + // If the target didn't expand this, just return 'zero' and preserve the + // chain. + Results.push_back(DAG.getConstant(0, MVT::i32)); + Results.push_back(Node->getOperand(0)); + break; + case ISD::MEMBARRIER: { + // If the target didn't lower this, lower it to '__sync_synchronize()' call + TargetLowering::ArgListTy Args; + std::pair CallResult = + TLI.LowerCallTo(Node->getOperand(0), Type::getVoidTy(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, + /*isTailCall=*/false, + /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("__sync_synchronize", + TLI.getPointerTy()), + Args, DAG, dl); + Results.push_back(CallResult.second); + break; + } + // By default, atomic intrinsics are marked Legal and lowered. Targets + // which don't support them directly, however, may want libcalls, in which + // case they mark them Expand, and we get here. + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + case ISD::ATOMIC_CMP_SWAP: { + std::pair Tmp = ExpandAtomic(Node); + Results.push_back(Tmp.first); + Results.push_back(Tmp.second); + break; + } + case ISD::DYNAMIC_STACKALLOC: + ExpandDYNAMIC_STACKALLOC(Node, Results); + break; + case ISD::MERGE_VALUES: + for (unsigned i = 0; i < Node->getNumValues(); i++) + Results.push_back(Node->getOperand(i)); + break; + case ISD::UNDEF: { + EVT VT = Node->getValueType(0); + if (VT.isInteger()) + Results.push_back(DAG.getConstant(0, VT)); + else { + assert(VT.isFloatingPoint() && "Unknown value type!"); + Results.push_back(DAG.getConstantFP(0, VT)); + } + break; + } + case ISD::TRAP: { + // If this operation is not supported, lower it to 'abort()' call + TargetLowering::ArgListTy Args; + std::pair CallResult = + TLI.LowerCallTo(Node->getOperand(0), Type::getVoidTy(*DAG.getContext()), + false, false, false, false, 0, CallingConv::C, + /*isTailCall=*/false, + /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("abort", TLI.getPointerTy()), + Args, DAG, dl); + Results.push_back(CallResult.second); + break; + } + case ISD::FP_ROUND: + case ISD::BITCAST: + Tmp1 = EmitStackConvert(Node->getOperand(0), Node->getValueType(0), + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::FP_EXTEND: + Tmp1 = EmitStackConvert(Node->getOperand(0), + Node->getOperand(0).getValueType(), + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::SIGN_EXTEND_INREG: { + // NOTE: we could fall back on load/store here too for targets without + // SAR. However, it is doubtful that any exist. + EVT ExtraVT = cast(Node->getOperand(1))->getVT(); + EVT VT = Node->getValueType(0); + EVT ShiftAmountTy = TLI.getShiftAmountTy(VT); + if (VT.isVector()) + ShiftAmountTy = VT; + unsigned BitsDiff = VT.getScalarType().getSizeInBits() - + ExtraVT.getScalarType().getSizeInBits(); + SDValue ShiftCst = DAG.getConstant(BitsDiff, ShiftAmountTy); + Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0), + Node->getOperand(0), ShiftCst); + Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, ShiftCst); + Results.push_back(Tmp1); + break; + } + case ISD::FP_ROUND_INREG: { + // The only way we can lower this is to turn it into a TRUNCSTORE, + // EXTLOAD pair, targetting a temporary location (a stack slot). + + // NOTE: there is a choice here between constantly creating new stack + // slots and always reusing the same one. We currently always create + // new ones, as reuse may inhibit scheduling. + EVT ExtraVT = cast(Node->getOperand(1))->getVT(); + Tmp1 = EmitStackConvert(Node->getOperand(0), ExtraVT, + Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + } + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + Tmp1 = ExpandLegalINT_TO_FP(Node->getOpcode() == ISD::SINT_TO_FP, + Node->getOperand(0), Node->getValueType(0), dl); + Results.push_back(Tmp1); + break; + case ISD::FP_TO_UINT: { + SDValue True, False; + EVT VT = Node->getOperand(0).getValueType(); + EVT NVT = Node->getValueType(0); + APFloat apf(APInt::getNullValue(VT.getSizeInBits())); + APInt x = APInt::getSignBit(NVT.getSizeInBits()); + (void)apf.convertFromAPInt(x, false, APFloat::rmNearestTiesToEven); + Tmp1 = DAG.getConstantFP(apf, VT); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), + Node->getOperand(0), + Tmp1, ISD::SETLT); + True = DAG.getNode(ISD::FP_TO_SINT, dl, NVT, Node->getOperand(0)); + False = DAG.getNode(ISD::FP_TO_SINT, dl, NVT, + DAG.getNode(ISD::FSUB, dl, VT, + Node->getOperand(0), Tmp1)); + False = DAG.getNode(ISD::XOR, dl, NVT, False, + DAG.getConstant(x, NVT)); + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2, True, False); + Results.push_back(Tmp1); + break; + } + case ISD::VAARG: { + const Value *V = cast(Node->getOperand(2))->getValue(); + EVT VT = Node->getValueType(0); + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + unsigned Align = Node->getConstantOperandVal(3); + + SDValue VAListLoad = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, + MachinePointerInfo(V), false, false, 0); + SDValue VAList = VAListLoad; + + if (Align > TLI.getMinStackArgumentAlignment()) { + assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2"); + + VAList = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList, + DAG.getConstant(Align - 1, + TLI.getPointerTy())); + + VAList = DAG.getNode(ISD::AND, dl, TLI.getPointerTy(), VAList, + DAG.getConstant(-(int64_t)Align, + TLI.getPointerTy())); + } + + // Increment the pointer, VAList, to the next vaarg + Tmp3 = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList, + DAG.getConstant(TLI.getTargetData()-> + getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())), + TLI.getPointerTy())); + // Store the incremented VAList to the legalized pointer + Tmp3 = DAG.getStore(VAListLoad.getValue(1), dl, Tmp3, Tmp2, + MachinePointerInfo(V), false, false, 0); + // Load the actual argument out of the pointer VAList + Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, MachinePointerInfo(), + false, false, 0)); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::VACOPY: { + // This defaults to loading a pointer from the input and storing it to the + // output, returning the chain. + const Value *VD = cast(Node->getOperand(3))->getValue(); + const Value *VS = cast(Node->getOperand(4))->getValue(); + Tmp1 = DAG.getLoad(TLI.getPointerTy(), dl, Node->getOperand(0), + Node->getOperand(2), MachinePointerInfo(VS), + false, false, 0); + Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), + MachinePointerInfo(VD), false, false, 0); + Results.push_back(Tmp1); + break; + } + case ISD::EXTRACT_VECTOR_ELT: + if (Node->getOperand(0).getValueType().getVectorNumElements() == 1) + // This must be an access of the only element. Return it. + Tmp1 = DAG.getNode(ISD::BITCAST, dl, Node->getValueType(0), + Node->getOperand(0)); + else + Tmp1 = ExpandExtractFromVectorThroughStack(SDValue(Node, 0)); + Results.push_back(Tmp1); + break; + case ISD::EXTRACT_SUBVECTOR: + Results.push_back(ExpandExtractFromVectorThroughStack(SDValue(Node, 0))); + break; + case ISD::INSERT_SUBVECTOR: + Results.push_back(ExpandInsertToVectorThroughStack(SDValue(Node, 0))); + break; + case ISD::CONCAT_VECTORS: { + Results.push_back(ExpandVectorBuildThroughStack(Node)); + break; + } + case ISD::SCALAR_TO_VECTOR: + Results.push_back(ExpandSCALAR_TO_VECTOR(Node)); + break; + case ISD::INSERT_VECTOR_ELT: + Results.push_back(ExpandINSERT_VECTOR_ELT(Node->getOperand(0), + Node->getOperand(1), + Node->getOperand(2), dl)); + break; + case ISD::VECTOR_SHUFFLE: { + SmallVector Mask; + cast(Node)->getMask(Mask); + + EVT VT = Node->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + if (getTypeAction(EltVT) == Promote) + EltVT = TLI.getTypeToTransformTo(*DAG.getContext(), EltVT); + unsigned NumElems = VT.getVectorNumElements(); + SmallVector Ops; + for (unsigned i = 0; i != NumElems; ++i) { + if (Mask[i] < 0) { + Ops.push_back(DAG.getUNDEF(EltVT)); + continue; + } + unsigned Idx = Mask[i]; + if (Idx < NumElems) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Node->getOperand(0), + DAG.getIntPtrConstant(Idx))); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Node->getOperand(1), + DAG.getIntPtrConstant(Idx - NumElems))); + } + Tmp1 = DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size()); + Results.push_back(Tmp1); + break; + } + case ISD::EXTRACT_ELEMENT: { + EVT OpTy = Node->getOperand(0).getValueType(); + if (cast(Node->getOperand(1))->getZExtValue()) { + // 1 -> Hi + Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0), + DAG.getConstant(OpTy.getSizeInBits()/2, + TLI.getShiftAmountTy(Node->getOperand(0).getValueType()))); + Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1); + } else { + // 0 -> Lo + Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), + Node->getOperand(0)); + } + Results.push_back(Tmp1); + break; + } + case ISD::STACKSAVE: + // Expand to CopyFromReg if the target set + // StackPointerRegisterToSaveRestore. + if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) { + Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, SP, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + } else { + Results.push_back(DAG.getUNDEF(Node->getValueType(0))); + Results.push_back(Node->getOperand(0)); + } + break; + case ISD::STACKRESTORE: + // Expand to CopyToReg if the target set + // StackPointerRegisterToSaveRestore. + if (unsigned SP = TLI.getStackPointerRegisterToSaveRestore()) { + Results.push_back(DAG.getCopyToReg(Node->getOperand(0), dl, SP, + Node->getOperand(1))); + } else { + Results.push_back(Node->getOperand(0)); + } + break; + case ISD::FCOPYSIGN: + Results.push_back(ExpandFCOPYSIGN(Node)); + break; + case ISD::FNEG: + // Expand Y = FNEG(X) -> Y = SUB -0.0, X + Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0)); + Tmp1 = DAG.getNode(ISD::FSUB, dl, Node->getValueType(0), Tmp1, + Node->getOperand(0)); + Results.push_back(Tmp1); + break; + case ISD::FABS: { + // Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X). + EVT VT = Node->getValueType(0); + Tmp1 = Node->getOperand(0); + Tmp2 = DAG.getConstantFP(0.0, VT); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(Tmp1.getValueType()), + Tmp1, Tmp2, ISD::SETUGT); + Tmp3 = DAG.getNode(ISD::FNEG, dl, VT, Tmp1); + Tmp1 = DAG.getNode(ISD::SELECT, dl, VT, Tmp2, Tmp1, Tmp3); + Results.push_back(Tmp1); + break; + } + case ISD::FSQRT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64, + RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128)); + break; + case ISD::FSIN: + Results.push_back(ExpandFPLibCall(Node, RTLIB::SIN_F32, RTLIB::SIN_F64, + RTLIB::SIN_F80, RTLIB::SIN_PPCF128)); + break; + case ISD::FCOS: + Results.push_back(ExpandFPLibCall(Node, RTLIB::COS_F32, RTLIB::COS_F64, + RTLIB::COS_F80, RTLIB::COS_PPCF128)); + break; + case ISD::FLOG: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128)); + break; + case ISD::FLOG2: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128)); + break; + case ISD::FLOG10: + Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64, + RTLIB::LOG10_F80, RTLIB::LOG10_PPCF128)); + break; + case ISD::FEXP: + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128)); + break; + case ISD::FEXP2: + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128)); + break; + case ISD::FTRUNC: + Results.push_back(ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128)); + break; + case ISD::FFLOOR: + Results.push_back(ExpandFPLibCall(Node, RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, RTLIB::FLOOR_PPCF128)); + break; + case ISD::FCEIL: + Results.push_back(ExpandFPLibCall(Node, RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128)); + break; + case ISD::FRINT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128)); + break; + case ISD::FNEARBYINT: + Results.push_back(ExpandFPLibCall(Node, RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128)); + break; + case ISD::FPOWI: + Results.push_back(ExpandFPLibCall(Node, RTLIB::POWI_F32, RTLIB::POWI_F64, + RTLIB::POWI_F80, RTLIB::POWI_PPCF128)); + break; + case ISD::FPOW: + Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64, + RTLIB::POW_F80, RTLIB::POW_PPCF128)); + break; + case ISD::FDIV: + Results.push_back(ExpandFPLibCall(Node, RTLIB::DIV_F32, RTLIB::DIV_F64, + RTLIB::DIV_F80, RTLIB::DIV_PPCF128)); + break; + case ISD::FREM: + Results.push_back(ExpandFPLibCall(Node, RTLIB::REM_F32, RTLIB::REM_F64, + RTLIB::REM_F80, RTLIB::REM_PPCF128)); + break; + case ISD::FP16_TO_FP32: + Results.push_back(ExpandLibCall(RTLIB::FPEXT_F16_F32, Node, false)); + break; + case ISD::FP32_TO_FP16: + Results.push_back(ExpandLibCall(RTLIB::FPROUND_F32_F16, Node, false)); + break; + case ISD::ConstantFP: { + ConstantFPSDNode *CFP = cast(Node); + // Check to see if this FP immediate is already legal. + // If this is a legal constant, turn it into a TargetConstantFP node. + if (TLI.isFPImmLegal(CFP->getValueAPF(), Node->getValueType(0))) + Results.push_back(SDValue(Node, 0)); + else + Results.push_back(ExpandConstantFP(CFP, true, DAG, TLI)); + break; + } + case ISD::EHSELECTION: { + unsigned Reg = TLI.getExceptionSelectorRegister(); + assert(Reg && "Can't expand to unknown register!"); + Results.push_back(DAG.getCopyFromReg(Node->getOperand(1), dl, Reg, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::EXCEPTIONADDR: { + unsigned Reg = TLI.getExceptionAddressRegister(); + assert(Reg && "Can't expand to unknown register!"); + Results.push_back(DAG.getCopyFromReg(Node->getOperand(0), dl, Reg, + Node->getValueType(0))); + Results.push_back(Results[0].getValue(1)); + break; + } + case ISD::SUB: { + EVT VT = Node->getValueType(0); + assert(TLI.isOperationLegalOrCustom(ISD::ADD, VT) && + TLI.isOperationLegalOrCustom(ISD::XOR, VT) && + "Don't know how to expand this subtraction!"); + Tmp1 = DAG.getNode(ISD::XOR, dl, VT, Node->getOperand(1), + DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT)); + Tmp1 = DAG.getNode(ISD::ADD, dl, VT, Tmp2, DAG.getConstant(1, VT)); + Results.push_back(DAG.getNode(ISD::ADD, dl, VT, Node->getOperand(0), Tmp1)); + break; + } + case ISD::UREM: + case ISD::SREM: { + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + bool isSigned = Node->getOpcode() == ISD::SREM; + unsigned DivOpc = isSigned ? ISD::SDIV : ISD::UDIV; + unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; + Tmp2 = Node->getOperand(0); + Tmp3 = Node->getOperand(1); + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) { + Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Tmp2, Tmp3).getValue(1); + } else if (TLI.isOperationLegalOrCustom(DivOpc, VT)) { + // X % Y -> X-X/Y*Y + Tmp1 = DAG.getNode(DivOpc, dl, VT, Tmp2, Tmp3); + Tmp1 = DAG.getNode(ISD::MUL, dl, VT, Tmp1, Tmp3); + Tmp1 = DAG.getNode(ISD::SUB, dl, VT, Tmp2, Tmp1); + } else if (isSigned) { + Tmp1 = ExpandIntLibCall(Node, true, + RTLIB::SREM_I8, + RTLIB::SREM_I16, RTLIB::SREM_I32, + RTLIB::SREM_I64, RTLIB::SREM_I128); + } else { + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::UREM_I8, + RTLIB::UREM_I16, RTLIB::UREM_I32, + RTLIB::UREM_I64, RTLIB::UREM_I128); + } + Results.push_back(Tmp1); + break; + } + case ISD::UDIV: + case ISD::SDIV: { + bool isSigned = Node->getOpcode() == ISD::SDIV; + unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM; + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + if (TLI.isOperationLegalOrCustom(DivRemOpc, VT)) + Tmp1 = DAG.getNode(DivRemOpc, dl, VTs, Node->getOperand(0), + Node->getOperand(1)); + else if (isSigned) + Tmp1 = ExpandIntLibCall(Node, true, + RTLIB::SDIV_I8, + RTLIB::SDIV_I16, RTLIB::SDIV_I32, + RTLIB::SDIV_I64, RTLIB::SDIV_I128); + else + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::UDIV_I8, + RTLIB::UDIV_I16, RTLIB::UDIV_I32, + RTLIB::UDIV_I64, RTLIB::UDIV_I128); + Results.push_back(Tmp1); + break; + } + case ISD::MULHU: + case ISD::MULHS: { + unsigned ExpandOpcode = Node->getOpcode() == ISD::MULHU ? ISD::UMUL_LOHI : + ISD::SMUL_LOHI; + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + assert(TLI.isOperationLegalOrCustom(ExpandOpcode, VT) && + "If this wasn't legal, it shouldn't have been created!"); + Tmp1 = DAG.getNode(ExpandOpcode, dl, VTs, Node->getOperand(0), + Node->getOperand(1)); + Results.push_back(Tmp1.getValue(1)); + break; + } + case ISD::MUL: { + EVT VT = Node->getValueType(0); + SDVTList VTs = DAG.getVTList(VT, VT); + // See if multiply or divide can be lowered using two-result operations. + // We just need the low half of the multiply; try both the signed + // and unsigned forms. If the target supports both SMUL_LOHI and + // UMUL_LOHI, form a preference by checking which forms of plain + // MULH it supports. + bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, VT); + bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, VT); + bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, VT); + bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, VT); + unsigned OpToUse = 0; + if (HasSMUL_LOHI && !HasMULHS) { + OpToUse = ISD::SMUL_LOHI; + } else if (HasUMUL_LOHI && !HasMULHU) { + OpToUse = ISD::UMUL_LOHI; + } else if (HasSMUL_LOHI) { + OpToUse = ISD::SMUL_LOHI; + } else if (HasUMUL_LOHI) { + OpToUse = ISD::UMUL_LOHI; + } + if (OpToUse) { + Results.push_back(DAG.getNode(OpToUse, dl, VTs, Node->getOperand(0), + Node->getOperand(1))); + break; + } + Tmp1 = ExpandIntLibCall(Node, false, + RTLIB::MUL_I8, + RTLIB::MUL_I16, RTLIB::MUL_I32, + RTLIB::MUL_I64, RTLIB::MUL_I128); + Results.push_back(Tmp1); + break; + } + case ISD::SADDO: + case ISD::SSUBO: { + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + Results.push_back(Sum); + EVT OType = Node->getValueType(1); + + SDValue Zero = DAG.getConstant(0, LHS.getValueType()); + + // LHSSign -> LHS >= 0 + // RHSSign -> RHS >= 0 + // SumSign -> Sum >= 0 + // + // Add: + // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) + // Sub: + // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) + // + SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE); + SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE); + SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign, + Node->getOpcode() == ISD::SADDO ? + ISD::SETEQ : ISD::SETNE); + + SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE); + SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE); + + SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE); + Results.push_back(Cmp); + break; + } + case ISD::UADDO: + case ISD::USUBO: { + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::UADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + Results.push_back(Sum); + Results.push_back(DAG.getSetCC(dl, Node->getValueType(1), Sum, LHS, + Node->getOpcode () == ISD::UADDO ? + ISD::SETULT : ISD::SETUGT)); + break; + } + case ISD::UMULO: + case ISD::SMULO: { + EVT VT = Node->getValueType(0); + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + SDValue BottomHalf; + SDValue TopHalf; + static const unsigned Ops[2][3] = + { { ISD::MULHU, ISD::UMUL_LOHI, ISD::ZERO_EXTEND }, + { ISD::MULHS, ISD::SMUL_LOHI, ISD::SIGN_EXTEND }}; + bool isSigned = Node->getOpcode() == ISD::SMULO; + if (TLI.isOperationLegalOrCustom(Ops[isSigned][0], VT)) { + BottomHalf = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS); + TopHalf = DAG.getNode(Ops[isSigned][0], dl, VT, LHS, RHS); + } else if (TLI.isOperationLegalOrCustom(Ops[isSigned][1], VT)) { + BottomHalf = DAG.getNode(Ops[isSigned][1], dl, DAG.getVTList(VT, VT), LHS, + RHS); + TopHalf = BottomHalf.getValue(1); + } else if (TLI.isTypeLegal(EVT::getIntegerVT(*DAG.getContext(), + VT.getSizeInBits() * 2))) { + EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); + LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); + RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); + Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS); + BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1, + DAG.getIntPtrConstant(0)); + TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1, + DAG.getIntPtrConstant(1)); + } else { + // We can fall back to a libcall with an illegal type for the MUL if we + // have a libcall big enough. + // Also, we can fall back to a division in some cases, but that's a big + // performance hit in the general case. + EVT WideVT = EVT::getIntegerVT(*DAG.getContext(), VT.getSizeInBits() * 2); + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (WideVT == MVT::i16) + LC = RTLIB::MUL_I16; + else if (WideVT == MVT::i32) + LC = RTLIB::MUL_I32; + else if (WideVT == MVT::i64) + LC = RTLIB::MUL_I64; + else if (WideVT == MVT::i128) + LC = RTLIB::MUL_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!"); + LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS); + RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS); + + SDValue Ret = ExpandLibCall(LC, Node, isSigned); + BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret); + TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret, + DAG.getConstant(VT.getSizeInBits(), TLI.getPointerTy())); + TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf); + } + if (isSigned) { + Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, + TLI.getShiftAmountTy(BottomHalf.getValueType())); + Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1); + TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1, + ISD::SETNE); + } else { + TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, + DAG.getConstant(0, VT), ISD::SETNE); + } + Results.push_back(BottomHalf); + Results.push_back(TopHalf); + break; + } + case ISD::BUILD_PAIR: { + EVT PairTy = Node->getValueType(0); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0)); + Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1)); + Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2, + DAG.getConstant(PairTy.getSizeInBits()/2, + TLI.getShiftAmountTy(PairTy))); + Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2)); + break; + } + case ISD::SELECT: + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = Node->getOperand(2); + if (Tmp1.getOpcode() == ISD::SETCC) { + Tmp1 = DAG.getSelectCC(dl, Tmp1.getOperand(0), Tmp1.getOperand(1), + Tmp2, Tmp3, + cast(Tmp1.getOperand(2))->get()); + } else { + Tmp1 = DAG.getSelectCC(dl, Tmp1, + DAG.getConstant(0, Tmp1.getValueType()), + Tmp2, Tmp3, ISD::SETNE); + } + Results.push_back(Tmp1); + break; + case ISD::BR_JT: { + SDValue Chain = Node->getOperand(0); + SDValue Table = Node->getOperand(1); + SDValue Index = Node->getOperand(2); + + EVT PTy = TLI.getPointerTy(); + + const TargetData &TD = *TLI.getTargetData(); + unsigned EntrySize = + DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD); + + Index = DAG.getNode(ISD::MUL, dl, PTy, + Index, DAG.getConstant(EntrySize, PTy)); + SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); + + EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); + SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr, + MachinePointerInfo::getJumpTable(), MemVT, + false, false, 0); + Addr = LD; + if (TM.getRelocationModel() == Reloc::PIC_) { + // For PIC, the sequence is: + // BRIND(load(Jumptable + index) + RelocBase) + // RelocBase can be JumpTable, GOT or some sort of global base. + Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, + TLI.getPICJumpTableRelocBase(Table, DAG)); + } + Tmp1 = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr); + Results.push_back(Tmp1); + break; + } + case ISD::BRCOND: + // Expand brcond's setcc into its constituent parts and create a BR_CC + // Node. + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + if (Tmp2.getOpcode() == ISD::SETCC) { + Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other, + Tmp1, Tmp2.getOperand(2), + Tmp2.getOperand(0), Tmp2.getOperand(1), + Node->getOperand(2)); + } else { + Tmp1 = DAG.getNode(ISD::BR_CC, dl, MVT::Other, Tmp1, + DAG.getCondCode(ISD::SETNE), Tmp2, + DAG.getConstant(0, Tmp2.getValueType()), + Node->getOperand(2)); + } + Results.push_back(Tmp1); + break; + case ISD::SETCC: { + Tmp1 = Node->getOperand(0); + Tmp2 = Node->getOperand(1); + Tmp3 = Node->getOperand(2); + LegalizeSetCCCondCode(Node->getValueType(0), Tmp1, Tmp2, Tmp3, dl); + + // If we expanded the SETCC into an AND/OR, return the new node + if (Tmp2.getNode() == 0) { + Results.push_back(Tmp1); + break; + } + + // Otherwise, SETCC for the given comparison type must be completely + // illegal; expand it into a SELECT_CC. + EVT VT = Node->getValueType(0); + Tmp1 = DAG.getNode(ISD::SELECT_CC, dl, VT, Tmp1, Tmp2, + DAG.getConstant(1, VT), DAG.getConstant(0, VT), Tmp3); + Results.push_back(Tmp1); + break; + } + case ISD::SELECT_CC: { + Tmp1 = Node->getOperand(0); // LHS + Tmp2 = Node->getOperand(1); // RHS + Tmp3 = Node->getOperand(2); // True + Tmp4 = Node->getOperand(3); // False + SDValue CC = Node->getOperand(4); + + LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp1.getValueType()), + Tmp1, Tmp2, CC, dl); + + assert(!Tmp2.getNode() && "Can't legalize SELECT_CC with legal condition!"); + Tmp2 = DAG.getConstant(0, Tmp1.getValueType()); + CC = DAG.getCondCode(ISD::SETNE); + Tmp1 = DAG.getNode(ISD::SELECT_CC, dl, Node->getValueType(0), Tmp1, Tmp2, + Tmp3, Tmp4, CC); + Results.push_back(Tmp1); + break; + } + case ISD::BR_CC: { + Tmp1 = Node->getOperand(0); // Chain + Tmp2 = Node->getOperand(2); // LHS + Tmp3 = Node->getOperand(3); // RHS + Tmp4 = Node->getOperand(1); // CC + + LegalizeSetCCCondCode(TLI.getSetCCResultType(Tmp2.getValueType()), + Tmp2, Tmp3, Tmp4, dl); + LastCALLSEQ_END = DAG.getEntryNode(); + + assert(!Tmp3.getNode() && "Can't legalize BR_CC with legal condition!"); + Tmp3 = DAG.getConstant(0, Tmp2.getValueType()); + Tmp4 = DAG.getCondCode(ISD::SETNE); + Tmp1 = DAG.getNode(ISD::BR_CC, dl, Node->getValueType(0), Tmp1, Tmp4, Tmp2, + Tmp3, Node->getOperand(4)); + Results.push_back(Tmp1); + break; + } + case ISD::GLOBAL_OFFSET_TABLE: + case ISD::GlobalAddress: + case ISD::GlobalTLSAddress: + case ISD::ExternalSymbol: + case ISD::ConstantPool: + case ISD::JumpTable: + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + // FIXME: Custom lowering for these operations shouldn't return null! + for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) + Results.push_back(SDValue(Node, i)); + break; + } +} +void SelectionDAGLegalize::PromoteNode(SDNode *Node, + SmallVectorImpl &Results) { + EVT OVT = Node->getValueType(0); + if (Node->getOpcode() == ISD::UINT_TO_FP || + Node->getOpcode() == ISD::SINT_TO_FP || + Node->getOpcode() == ISD::SETCC) { + OVT = Node->getOperand(0).getValueType(); + } + EVT NVT = TLI.getTypeToPromoteTo(Node->getOpcode(), OVT); + DebugLoc dl = Node->getDebugLoc(); + SDValue Tmp1, Tmp2, Tmp3; + switch (Node->getOpcode()) { + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + // Zero extend the argument. + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0)); + // Perform the larger operation. + Tmp1 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1); + if (Node->getOpcode() == ISD::CTTZ) { + //if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT) + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), + Tmp1, DAG.getConstant(NVT.getSizeInBits(), NVT), + ISD::SETEQ); + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp2, + DAG.getConstant(OVT.getSizeInBits(), NVT), Tmp1); + } else if (Node->getOpcode() == ISD::CTLZ) { + // Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT)) + Tmp1 = DAG.getNode(ISD::SUB, dl, NVT, Tmp1, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); + } + Results.push_back(DAG.getNode(ISD::TRUNCATE, dl, OVT, Tmp1)); + break; + case ISD::BSWAP: { + unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits(); + Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0)); + Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1); + Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1, + DAG.getConstant(DiffBits, TLI.getShiftAmountTy(NVT))); + Results.push_back(Tmp1); + break; + } + case ISD::FP_TO_UINT: + case ISD::FP_TO_SINT: + Tmp1 = PromoteLegalFP_TO_INT(Node->getOperand(0), Node->getValueType(0), + Node->getOpcode() == ISD::FP_TO_SINT, dl); + Results.push_back(Tmp1); + break; + case ISD::UINT_TO_FP: + case ISD::SINT_TO_FP: + Tmp1 = PromoteLegalINT_TO_FP(Node->getOperand(0), Node->getValueType(0), + Node->getOpcode() == ISD::SINT_TO_FP, dl); + Results.push_back(Tmp1); + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: { + unsigned ExtOp, TruncOp; + if (OVT.isVector()) { + ExtOp = ISD::BITCAST; + TruncOp = ISD::BITCAST; + } else { + assert(OVT.isInteger() && "Cannot promote logic operation"); + ExtOp = ISD::ANY_EXTEND; + TruncOp = ISD::TRUNCATE; + } + // Promote each of the values to the new type. + Tmp1 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + // Perform the larger operation, then convert back + Tmp1 = DAG.getNode(Node->getOpcode(), dl, NVT, Tmp1, Tmp2); + Results.push_back(DAG.getNode(TruncOp, dl, OVT, Tmp1)); + break; + } + case ISD::SELECT: { + unsigned ExtOp, TruncOp; + if (Node->getValueType(0).isVector()) { + ExtOp = ISD::BITCAST; + TruncOp = ISD::BITCAST; + } else if (Node->getValueType(0).isInteger()) { + ExtOp = ISD::ANY_EXTEND; + TruncOp = ISD::TRUNCATE; + } else { + ExtOp = ISD::FP_EXTEND; + TruncOp = ISD::FP_ROUND; + } + Tmp1 = Node->getOperand(0); + // Promote each of the values to the new type. + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + Tmp3 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(2)); + // Perform the larger operation, then round down. + Tmp1 = DAG.getNode(ISD::SELECT, dl, NVT, Tmp1, Tmp2, Tmp3); + if (TruncOp != ISD::FP_ROUND) + Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1); + else + Tmp1 = DAG.getNode(TruncOp, dl, Node->getValueType(0), Tmp1, + DAG.getIntPtrConstant(0)); + Results.push_back(Tmp1); + break; + } + case ISD::VECTOR_SHUFFLE: { + SmallVector Mask; + cast(Node)->getMask(Mask); + + // Cast the two input vectors. + Tmp1 = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ISD::BITCAST, dl, NVT, Node->getOperand(1)); + + // Convert the shuffle mask to the right # elements. + Tmp1 = ShuffleWithNarrowerEltType(NVT, OVT, dl, Tmp1, Tmp2, Mask); + Tmp1 = DAG.getNode(ISD::BITCAST, dl, OVT, Tmp1); + Results.push_back(Tmp1); + break; + } + case ISD::SETCC: { + unsigned ExtOp = ISD::FP_EXTEND; + if (NVT.isInteger()) { + ISD::CondCode CCCode = + cast(Node->getOperand(2))->get(); + ExtOp = isSignedIntSetCC(CCCode) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + } + Tmp1 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(0)); + Tmp2 = DAG.getNode(ExtOp, dl, NVT, Node->getOperand(1)); + Results.push_back(DAG.getNode(ISD::SETCC, dl, Node->getValueType(0), + Tmp1, Tmp2, Node->getOperand(2))); + break; + } + } +} + +// SelectionDAG::Legalize - This is the entry point for the file. +// +void SelectionDAG::Legalize(CodeGenOpt::Level OptLevel) { + /// run - This is the main entry point to this class. + /// + SelectionDAGLegalize(*this, OptLevel).LegalizeDAG(); +} + diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp new file mode 100644 index 00000000000..27a466b3a92 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -0,0 +1,1428 @@ +//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements float type expansion and softening for LegalizeTypes. +// Softening is the act of turning a computation in an illegal floating point +// type into a computation in an integer type of the same size; also known as +// "soft float". For example, turning f32 arithmetic into operations using i32. +// The resulting integer value is the same as what you would get by performing +// the floating point operation and bitcasting the result to the integer type. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in two identical registers of a smaller type. For example, +// implementing ppcf128 arithmetic in two f64 registers. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// GetFPLibCall - Return the right libcall for the given floating point type. +static RTLIB::Libcall GetFPLibCall(EVT VT, + RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, + RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128) { + return + VT == MVT::f32 ? Call_F32 : + VT == MVT::f64 ? Call_F64 : + VT == MVT::f80 ? Call_F80 : + VT == MVT::ppcf128 ? Call_PPCF128 : + RTLIB::UNKNOWN_LIBCALL; +} + +//===----------------------------------------------------------------------===// +// Result Float to Integer Conversion. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Soften float result " << ResNo << ": "; N->dump(&DAG); + dbgs() << "\n"); + SDValue R = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "SoftenFloatResult #" << ResNo << ": "; + N->dump(&DAG); dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to soften the result of this operator!"); + + case ISD::BITCAST: R = SoftenFloatRes_BITCAST(N); break; + case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break; + case ISD::ConstantFP: + R = SoftenFloatRes_ConstantFP(cast(N)); + break; + case ISD::EXTRACT_VECTOR_ELT: + R = SoftenFloatRes_EXTRACT_VECTOR_ELT(N); break; + case ISD::FABS: R = SoftenFloatRes_FABS(N); break; + case ISD::FADD: R = SoftenFloatRes_FADD(N); break; + case ISD::FCEIL: R = SoftenFloatRes_FCEIL(N); break; + case ISD::FCOPYSIGN: R = SoftenFloatRes_FCOPYSIGN(N); break; + case ISD::FCOS: R = SoftenFloatRes_FCOS(N); break; + case ISD::FDIV: R = SoftenFloatRes_FDIV(N); break; + case ISD::FEXP: R = SoftenFloatRes_FEXP(N); break; + case ISD::FEXP2: R = SoftenFloatRes_FEXP2(N); break; + case ISD::FFLOOR: R = SoftenFloatRes_FFLOOR(N); break; + case ISD::FLOG: R = SoftenFloatRes_FLOG(N); break; + case ISD::FLOG2: R = SoftenFloatRes_FLOG2(N); break; + case ISD::FLOG10: R = SoftenFloatRes_FLOG10(N); break; + case ISD::FMUL: R = SoftenFloatRes_FMUL(N); break; + case ISD::FNEARBYINT: R = SoftenFloatRes_FNEARBYINT(N); break; + case ISD::FNEG: R = SoftenFloatRes_FNEG(N); break; + case ISD::FP_EXTEND: R = SoftenFloatRes_FP_EXTEND(N); break; + case ISD::FP_ROUND: R = SoftenFloatRes_FP_ROUND(N); break; + case ISD::FP16_TO_FP32:R = SoftenFloatRes_FP16_TO_FP32(N); break; + case ISD::FPOW: R = SoftenFloatRes_FPOW(N); break; + case ISD::FPOWI: R = SoftenFloatRes_FPOWI(N); break; + case ISD::FREM: R = SoftenFloatRes_FREM(N); break; + case ISD::FRINT: R = SoftenFloatRes_FRINT(N); break; + case ISD::FSIN: R = SoftenFloatRes_FSIN(N); break; + case ISD::FSQRT: R = SoftenFloatRes_FSQRT(N); break; + case ISD::FSUB: R = SoftenFloatRes_FSUB(N); break; + case ISD::FTRUNC: R = SoftenFloatRes_FTRUNC(N); break; + case ISD::LOAD: R = SoftenFloatRes_LOAD(N); break; + case ISD::SELECT: R = SoftenFloatRes_SELECT(N); break; + case ISD::SELECT_CC: R = SoftenFloatRes_SELECT_CC(N); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: R = SoftenFloatRes_XINT_TO_FP(N); break; + case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break; + case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.getNode()) + SetSoftenedFloat(SDValue(N, ResNo), R); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_BITCAST(SDNode *N) { + return BitConvertToInteger(N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) { + // Convert the inputs to integers, and build a new pair out of them. + return DAG.getNode(ISD::BUILD_PAIR, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), + N->getValueType(0)), + BitConvertToInteger(N->getOperand(0)), + BitConvertToInteger(N->getOperand(1))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_ConstantFP(ConstantFPSDNode *N) { + return DAG.getConstant(N->getValueAPF().bitcastToAPInt(), + TLI.getTypeToTransformTo(*DAG.getContext(), + N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue NewOp = BitConvertVectorToIntegerVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + NewOp.getValueType().getVectorElementType(), + NewOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FABS(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned Size = NVT.getSizeInBits(); + + // Mask = ~(1 << (Size-1)) + APInt API = APInt::getAllOnesValue(Size); + API.clearBit(Size-1); + SDValue Mask = DAG.getConstant(API, NVT); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return DAG.getNode(ISD::AND, N->getDebugLoc(), NVT, Op, Mask); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, + RTLIB::ADD_F64, + RTLIB::ADD_F80, + RTLIB::ADD_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCEIL(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::CEIL_F32, + RTLIB::CEIL_F64, + RTLIB::CEIL_F80, + RTLIB::CEIL_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(0)); + SDValue RHS = BitConvertToInteger(N->getOperand(1)); + DebugLoc dl = N->getDebugLoc(); + + EVT LVT = LHS.getValueType(); + EVT RVT = RHS.getValueType(); + + unsigned LSize = LVT.getSizeInBits(); + unsigned RSize = RVT.getSizeInBits(); + + // First get the sign bit of second operand. + SDValue SignBit = DAG.getNode(ISD::SHL, dl, RVT, DAG.getConstant(1, RVT), + DAG.getConstant(RSize - 1, + TLI.getShiftAmountTy(RVT))); + SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit); + + // Shift right or sign-extend it if the two operands have different types. + int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits(); + if (SizeDiff > 0) { + SignBit = DAG.getNode(ISD::SRL, dl, RVT, SignBit, + DAG.getConstant(SizeDiff, + TLI.getShiftAmountTy(SignBit.getValueType()))); + SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit); + } else if (SizeDiff < 0) { + SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit); + SignBit = DAG.getNode(ISD::SHL, dl, LVT, SignBit, + DAG.getConstant(-SizeDiff, + TLI.getShiftAmountTy(SignBit.getValueType()))); + } + + // Clear the sign bit of the first operand. + SDValue Mask = DAG.getNode(ISD::SHL, dl, LVT, DAG.getConstant(1, LVT), + DAG.getConstant(LSize - 1, + TLI.getShiftAmountTy(LVT))); + Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, LVT)); + LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask); + + // Or the value with the sign bit. + return DAG.getNode(ISD::OR, dl, LVT, LHS, SignBit); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FCOS(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::COS_F32, + RTLIB::COS_F64, + RTLIB::COS_F80, + RTLIB::COS_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FDIV(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::DIV_F32, + RTLIB::DIV_F64, + RTLIB::DIV_F80, + RTLIB::DIV_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::EXP_F32, + RTLIB::EXP_F64, + RTLIB::EXP_F80, + RTLIB::EXP_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FEXP2(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::EXP2_F32, + RTLIB::EXP2_F64, + RTLIB::EXP2_F80, + RTLIB::EXP2_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FFLOOR(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::FLOOR_F32, + RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, + RTLIB::FLOOR_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG_F32, + RTLIB::LOG_F64, + RTLIB::LOG_F80, + RTLIB::LOG_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG2(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG2_F32, + RTLIB::LOG2_F64, + RTLIB::LOG2_F80, + RTLIB::LOG2_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FLOG10(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::LOG10_F32, + RTLIB::LOG10_F64, + RTLIB::LOG10_F80, + RTLIB::LOG10_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::MUL_F32, + RTLIB::MUL_F64, + RTLIB::MUL_F80, + RTLIB::MUL_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FNEARBYINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FNEG(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + // Expand Y = FNEG(X) -> Y = SUB -0.0, X + SDValue Ops[2] = { DAG.getConstantFP(-0.0, N->getValueType(0)), + GetSoftenedFloat(N->getOperand(0)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FP_EXTEND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPEXT(Op.getValueType(), N->getValueType(0)); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_EXTEND!"); + return MakeLibCall(LC, NVT, &Op, 1, false, N->getDebugLoc()); +} + +// FIXME: Should we just use 'normal' FP_EXTEND / FP_TRUNC instead of special +// nodes? +SDValue DAGTypeLegalizer::SoftenFloatRes_FP16_TO_FP32(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = N->getOperand(0); + return MakeLibCall(RTLIB::FPEXT_F16_F32, NVT, &Op, 1, false, + N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FP_ROUND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPROUND(Op.getValueType(), N->getValueType(0)); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND!"); + return MakeLibCall(LC, NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FPOW(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::POW_F32, + RTLIB::POW_F64, + RTLIB::POW_F80, + RTLIB::POW_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FPOWI(SDNode *N) { + assert(N->getOperand(1).getValueType() == MVT::i32 && + "Unsupported power type!"); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), N->getOperand(1) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::POWI_F32, + RTLIB::POWI_F64, + RTLIB::POWI_F80, + RTLIB::POWI_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FREM(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::REM_F32, + RTLIB::REM_F64, + RTLIB::REM_F80, + RTLIB::REM_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FRINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::RINT_F32, + RTLIB::RINT_F64, + RTLIB::RINT_F80, + RTLIB::RINT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSIN(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SIN_F32, + RTLIB::SIN_F64, + RTLIB::SIN_F80, + RTLIB::SIN_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSQRT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SQRT_F32, + RTLIB::SQRT_F64, + RTLIB::SQRT_F80, + RTLIB::SQRT_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + NVT, Ops, 2, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_FTRUNC(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::TRUNC_F32, + RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, + RTLIB::TRUNC_PPCF128), + NVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { + LoadSDNode *L = cast(N); + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + SDValue NewL; + if (L->getExtensionType() == ISD::NON_EXTLOAD) { + NewL = DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), + NVT, dl, L->getChain(), L->getBasePtr(), L->getOffset(), + L->getPointerInfo(), NVT, + L->isVolatile(), L->isNonTemporal(), L->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); + return NewL; + } + + // Do a non-extending load followed by FP_EXTEND. + NewL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, + L->getMemoryVT(), dl, L->getChain(), + L->getBasePtr(), L->getOffset(), L->getPointerInfo(), + L->getMemoryVT(), L->isVolatile(), + L->isNonTemporal(), L->getAlignment()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); + return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, dl, VT, NewL)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(1)); + SDValue RHS = GetSoftenedFloat(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetSoftenedFloat(N->getOperand(2)); + SDValue RHS = GetSoftenedFloat(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(), + N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_VAARG(SDNode *N) { + SDValue Chain = N->getOperand(0); // Get the chain. + SDValue Ptr = N->getOperand(1); // Get the pointer. + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + SDValue NewVAARG; + NewVAARG = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2), + N->getConstantOperandVal(3)); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), NewVAARG.getValue(1)); + return NewVAARG; +} + +SDValue DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) { + bool Signed = N->getOpcode() == ISD::SINT_TO_FP; + EVT SVT = N->getOperand(0).getValueType(); + EVT RVT = N->getValueType(0); + EVT NVT = EVT(); + DebugLoc dl = N->getDebugLoc(); + + // If the input is not legal, eg: i1 -> fp, then it needs to be promoted to + // a larger type, eg: i8 -> fp. Even if it is legal, no libcall may exactly + // match. Look for an appropriate libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + for (unsigned t = MVT::FIRST_INTEGER_VALUETYPE; + t <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; ++t) { + NVT = (MVT::SimpleValueType)t; + // The source needs to big enough to hold the operand. + if (NVT.bitsGE(SVT)) + LC = Signed ? RTLIB::getSINTTOFP(NVT, RVT):RTLIB::getUINTTOFP (NVT, RVT); + } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); + + // Sign/zero extend the argument if the libcall takes a larger type. + SDValue Op = DAG.getNode(Signed ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + NVT, N->getOperand(0)); + return MakeLibCall(LC, TLI.getTypeToTransformTo(*DAG.getContext(), RVT), + &Op, 1, false, dl); +} + + +//===----------------------------------------------------------------------===// +// Operand Float to Integer Conversion.. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Soften float operand " << OpNo << ": "; N->dump(&DAG); + dbgs() << "\n"); + SDValue Res = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "SoftenFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to soften this operator's operand!"); + + case ISD::BITCAST: Res = SoftenFloatOp_BITCAST(N); break; + case ISD::BR_CC: Res = SoftenFloatOp_BR_CC(N); break; + case ISD::FP_ROUND: Res = SoftenFloatOp_FP_ROUND(N); break; + case ISD::FP_TO_SINT: Res = SoftenFloatOp_FP_TO_SINT(N); break; + case ISD::FP_TO_UINT: Res = SoftenFloatOp_FP_TO_UINT(N); break; + case ISD::FP32_TO_FP16:Res = SoftenFloatOp_FP32_TO_FP16(N); break; + case ISD::SELECT_CC: Res = SoftenFloatOp_SELECT_CC(N); break; + case ISD::SETCC: Res = SoftenFloatOp_SETCC(N); break; + case ISD::STORE: Res = SoftenFloatOp_STORE(N, OpNo); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// SoftenSetCCOperands - Soften the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::SoftenSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl) { + SDValue LHSInt = GetSoftenedFloat(NewLHS); + SDValue RHSInt = GetSoftenedFloat(NewRHS); + EVT VT = NewLHS.getValueType(); + + assert((VT == MVT::f32 || VT == MVT::f64) && "Unsupported setcc type!"); + + // Expand into one or more soft-fp libcall(s). + RTLIB::Libcall LC1 = RTLIB::UNKNOWN_LIBCALL, LC2 = RTLIB::UNKNOWN_LIBCALL; + switch (CCCode) { + case ISD::SETEQ: + case ISD::SETOEQ: + LC1 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : RTLIB::OEQ_F64; + break; + case ISD::SETNE: + case ISD::SETUNE: + LC1 = (VT == MVT::f32) ? RTLIB::UNE_F32 : RTLIB::UNE_F64; + break; + case ISD::SETGE: + case ISD::SETOGE: + LC1 = (VT == MVT::f32) ? RTLIB::OGE_F32 : RTLIB::OGE_F64; + break; + case ISD::SETLT: + case ISD::SETOLT: + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + break; + case ISD::SETLE: + case ISD::SETOLE: + LC1 = (VT == MVT::f32) ? RTLIB::OLE_F32 : RTLIB::OLE_F64; + break; + case ISD::SETGT: + case ISD::SETOGT: + LC1 = (VT == MVT::f32) ? RTLIB::OGT_F32 : RTLIB::OGT_F64; + break; + case ISD::SETUO: + LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 : RTLIB::UO_F64; + break; + case ISD::SETO: + LC1 = (VT == MVT::f32) ? RTLIB::O_F32 : RTLIB::O_F64; + break; + default: + LC1 = (VT == MVT::f32) ? RTLIB::UO_F32 : RTLIB::UO_F64; + switch (CCCode) { + case ISD::SETONE: + // SETONE = SETOLT | SETOGT + LC1 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + // Fallthrough + case ISD::SETUGT: + LC2 = (VT == MVT::f32) ? RTLIB::OGT_F32 : RTLIB::OGT_F64; + break; + case ISD::SETUGE: + LC2 = (VT == MVT::f32) ? RTLIB::OGE_F32 : RTLIB::OGE_F64; + break; + case ISD::SETULT: + LC2 = (VT == MVT::f32) ? RTLIB::OLT_F32 : RTLIB::OLT_F64; + break; + case ISD::SETULE: + LC2 = (VT == MVT::f32) ? RTLIB::OLE_F32 : RTLIB::OLE_F64; + break; + case ISD::SETUEQ: + LC2 = (VT == MVT::f32) ? RTLIB::OEQ_F32 : RTLIB::OEQ_F64; + break; + default: assert(false && "Do not know how to soften this setcc!"); + } + } + + // Use the target specific return value for comparions lib calls. + EVT RetVT = TLI.getCmpLibcallReturnType(); + SDValue Ops[2] = { LHSInt, RHSInt }; + NewLHS = MakeLibCall(LC1, RetVT, Ops, 2, false/*sign irrelevant*/, dl); + NewRHS = DAG.getConstant(0, RetVT); + CCCode = TLI.getCmpLibcallCC(LC1); + if (LC2 != RTLIB::UNKNOWN_LIBCALL) { + SDValue Tmp = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(RetVT), + NewLHS, NewRHS, DAG.getCondCode(CCCode)); + NewLHS = MakeLibCall(LC2, RetVT, Ops, 2, false/*sign irrelevant*/, dl); + NewLHS = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(RetVT), NewLHS, + NewRHS, DAG.getCondCode(TLI.getCmpLibcallCC(LC2))); + NewLHS = DAG.getNode(ISD::OR, dl, Tmp.getValueType(), Tmp, NewLHS); + NewRHS = SDValue(); + } +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_BITCAST(SDNode *N) { + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), N->getValueType(0), + GetSoftenedFloat(N->getOperand(0))); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_ROUND(SDNode *N) { + EVT SVT = N->getOperand(0).getValueType(); + EVT RVT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::getFPROUND(SVT, RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_ROUND libcall"); + + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)), + 0); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_SINT(SDNode *N) { + EVT RVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getFPTOSINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_SINT!"); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_UINT(SDNode *N) { + EVT RVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getFPTOUINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_UINT!"); + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_FP32_TO_FP16(SDNode *N) { + EVT RVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::FPROUND_F32_F16; + SDValue Op = GetSoftenedFloat(N->getOperand(0)); + return MakeLibCall(LC, RVT, &Op, 1, false, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)), + 0); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + SoftenSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If SoftenSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + DAG.getCondCode(CCCode)), + 0); +} + +SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) { + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only soften the stored value!"); + StoreSDNode *ST = cast(N); + SDValue Val = ST->getValue(); + DebugLoc dl = N->getDebugLoc(); + + if (ST->isTruncatingStore()) + // Do an FP_ROUND followed by a non-truncating store. + Val = BitConvertToInteger(DAG.getNode(ISD::FP_ROUND, dl, ST->getMemoryVT(), + Val, DAG.getIntPtrConstant(0))); + else + Val = GetSoftenedFloat(Val); + + return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(), + ST->getPointerInfo(), + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); +} + + +//===----------------------------------------------------------------------===// +// Float Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Expand float result: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Lo, Hi; + Lo = Hi = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "ExpandFloatResult #" << ResNo << ": "; + N->dump(&DAG); dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to expand the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + + case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break; + + case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break; + case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break; + case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break; + case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break; + case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break; + case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break; + case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break; + case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break; + case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break; + case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break; + case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break; + case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break; + case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break; + case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break; + case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break; + case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break; + case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break; + case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break; + case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break; + case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break; + case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break; + case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break; + case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break; + case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break; + case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetExpandedFloat(SDValue(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + assert(NVT.getSizeInBits() == integerPartWidth && + "Do not know how to expand this float constant!"); + APInt C = cast(N)->getValueAPF().bitcastToAPInt(); + Lo = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, + &C.getRawData()[1])), NVT); + Hi = DAG.getConstantFP(APFloat(APInt(integerPartWidth, 1, + &C.getRawData()[0])), NVT); +} + +void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(N->getValueType(0) == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + DebugLoc dl = N->getDebugLoc(); + SDValue Tmp; + GetExpandedFloat(N->getOperand(0), Lo, Tmp); + Hi = DAG.getNode(ISD::FABS, dl, Tmp.getValueType(), Tmp); + // Lo = Hi==fabs(Hi) ? Lo : -Lo; + Lo = DAG.getNode(ISD::SELECT_CC, dl, Lo.getValueType(), Tmp, Hi, Lo, + DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo), + DAG.getCondCode(ISD::SETEQ)); +} + +void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, RTLIB::ADD_F64, + RTLIB::ADD_F80, RTLIB::ADD_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::COPYSIGN_F32, + RTLIB::COPYSIGN_F64, + RTLIB::COPYSIGN_F80, + RTLIB::COPYSIGN_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::COS_F32, RTLIB::COS_F64, + RTLIB::COS_F80, RTLIB::COS_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::DIV_F32, + RTLIB::DIV_F64, + RTLIB::DIV_F80, + RTLIB::DIV_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::FLOOR_F32,RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80,RTLIB::FLOOR_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::LOG10_F32,RTLIB::LOG10_F64, + RTLIB::LOG10_F80,RTLIB::LOG10_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::MUL_F32, + RTLIB::MUL_F64, + RTLIB::MUL_F80, + RTLIB::MUL_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedFloat(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(ISD::FNEG, dl, Lo.getValueType(), Lo); + Hi = DAG.getNode(ISD::FNEG, dl, Hi.getValueType(), Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FP_EXTEND(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + Hi = DAG.getNode(ISD::FP_EXTEND, N->getDebugLoc(), NVT, N->getOperand(0)); + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); +} + +void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::POW_F32, RTLIB::POW_F64, + RTLIB::POW_F80, RTLIB::POW_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::POWI_F32, RTLIB::POWI_F64, + RTLIB::POWI_F80, RTLIB::POWI_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::SIN_F32, RTLIB::SIN_F64, + RTLIB::SIN_F80, RTLIB::SIN_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::SQRT_F32, RTLIB::SQRT_F64, + RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SDValue Call = MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + N->getValueType(0), Ops, 2, false, + N->getDebugLoc()); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), + RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_PPCF128), + N, false); + GetPairElements(Call, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, + SDValue &Hi) { + if (ISD::isNormalLoad(N)) { + ExpandRes_NormalLoad(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + LoadSDNode *LD = cast(N); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + DebugLoc dl = N->getDebugLoc(); + + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr, + LD->getPointerInfo(), LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + + // Remember the chain. + Chain = Hi.getValue(1); + + // The low part is zero. + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); + + // Modified the chain - switch anything that used the old chain to use the + // new one. + ReplaceValueWith(SDValue(LD, 1), Chain); +} + +void DAGTypeLegalizer::ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(N->getValueType(0) == MVT::ppcf128 && "Unsupported XINT_TO_FP!"); + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Src = N->getOperand(0); + EVT SrcVT = Src.getValueType(); + bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; + DebugLoc dl = N->getDebugLoc(); + + // First do an SINT_TO_FP, whether the original was signed or unsigned. + // When promoting partial word types to i32 we must honor the signedness, + // though. + if (SrcVT.bitsLE(MVT::i32)) { + // The integer can be represented exactly in an f64. + Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + MVT::i32, Src); + Lo = DAG.getConstantFP(APFloat(APInt(NVT.getSizeInBits(), 0)), NVT); + Hi = DAG.getNode(ISD::SINT_TO_FP, dl, NVT, Src); + } else { + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (SrcVT.bitsLE(MVT::i64)) { + Src = DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, dl, + MVT::i64, Src); + LC = RTLIB::SINTTOFP_I64_PPCF128; + } else if (SrcVT.bitsLE(MVT::i128)) { + Src = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i128, Src); + LC = RTLIB::SINTTOFP_I128_PPCF128; + } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported XINT_TO_FP!"); + + Hi = MakeLibCall(LC, VT, &Src, 1, true, dl); + GetPairElements(Hi, Lo, Hi); + } + + if (isSigned) + return; + + // Unsigned - fix up the SINT_TO_FP value just calculated. + Hi = DAG.getNode(ISD::BUILD_PAIR, dl, VT, Lo, Hi); + SrcVT = Src.getValueType(); + + // x>=0 ? (ppcf128)(iN)x : (ppcf128)(iN)x + 2^N; N=32,64,128. + static const uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 }; + static const uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 }; + static const uint64_t TwoE128[] = { 0x47f0000000000000LL, 0 }; + const uint64_t *Parts = 0; + + switch (SrcVT.getSimpleVT().SimpleTy) { + default: + assert(false && "Unsupported UINT_TO_FP!"); + case MVT::i32: + Parts = TwoE32; + break; + case MVT::i64: + Parts = TwoE64; + break; + case MVT::i128: + Parts = TwoE128; + break; + } + + Lo = DAG.getNode(ISD::FADD, dl, VT, Hi, + DAG.getConstantFP(APFloat(APInt(128, 2, Parts)), + MVT::ppcf128)); + Lo = DAG.getNode(ISD::SELECT_CC, dl, VT, Src, DAG.getConstant(0, SrcVT), + Lo, Hi, DAG.getCondCode(ISD::SETLT)); + GetPairElements(Lo, Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Float Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatOperand - This method is called when the specified operand of the +/// specified node is found to need expansion. At this point, all of the result +/// types of the node are known to be legal, but other operands of the node may +/// need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Expand float operand: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Res = SDValue(); + + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDValue(N, 0), DAG); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + dbgs() << "ExpandFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); dbgs() << "\n"; + #endif + llvm_unreachable("Do not know how to expand this operator's operand!"); + + case ISD::BITCAST: Res = ExpandOp_BITCAST(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + + case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break; + case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break; + case ISD::FP_TO_SINT: Res = ExpandFloatOp_FP_TO_SINT(N); break; + case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_UINT(N); break; + case ISD::SELECT_CC: Res = ExpandFloatOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandFloatOp_SETCC(N); break; + case ISD::STORE: Res = ExpandFloatOp_STORE(cast(N), + OpNo); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// FloatExpandSetCCOperands - Expand the operands of a comparison. This code +/// is shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::FloatExpandSetCCOperands(SDValue &NewLHS, + SDValue &NewRHS, + ISD::CondCode &CCCode, + DebugLoc dl) { + SDValue LHSLo, LHSHi, RHSLo, RHSHi; + GetExpandedFloat(NewLHS, LHSLo, LHSHi); + GetExpandedFloat(NewRHS, RHSLo, RHSHi); + + EVT VT = NewLHS.getValueType(); + assert(VT == MVT::ppcf128 && "Unsupported setcc type!"); + + // FIXME: This generated code sucks. We want to generate + // FCMPU crN, hi1, hi2 + // BNE crN, L: + // FCMPU crN, lo1, lo2 + // The following can be improved, but not that much. + SDValue Tmp1, Tmp2, Tmp3; + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETOEQ); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, CCCode); + Tmp3 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2); + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETUNE); + Tmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, CCCode); + Tmp1 = DAG.getNode(ISD::AND, dl, Tmp1.getValueType(), Tmp1, Tmp2); + NewLHS = DAG.getNode(ISD::OR, dl, Tmp1.getValueType(), Tmp1, Tmp3); + NewRHS = SDValue(); // LHS is the result, not a compare. +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)), 0); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + SDValue Lo, Hi; + GetExpandedFloat(N->getOperand(0), Lo, Hi); + // Round it the rest of the way (e.g. to f32) if needed. + return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(), + N->getValueType(0), Hi, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_SINT(SDNode *N) { + EVT RVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). FIXME: Do this in a less hacky way. + if (RVT == MVT::i32) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + SDValue Res = DAG.getNode(ISD::FP_ROUND_INREG, dl, MVT::ppcf128, + N->getOperand(0), DAG.getValueType(MVT::f64)); + Res = DAG.getNode(ISD::FP_ROUND, dl, MVT::f64, Res, + DAG.getIntPtrConstant(1)); + return DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Res); + } + + RTLIB::Libcall LC = RTLIB::getFPTOSINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_SINT!"); + return MakeLibCall(LC, RVT, &N->getOperand(0), 1, false, dl); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) { + EVT RVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Expand ppcf128 to i32 by hand for the benefit of llvm-gcc bootstrap on + // PPC (the libcall is not available). FIXME: Do this in a less hacky way. + if (RVT == MVT::i32) { + assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + "Logic only correct for ppcf128!"); + const uint64_t TwoE31[] = {0x41e0000000000000LL, 0}; + APFloat APF = APFloat(APInt(128, 2, TwoE31)); + SDValue Tmp = DAG.getConstantFP(APF, MVT::ppcf128); + // X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X + // FIXME: generated code sucks. + return DAG.getNode(ISD::SELECT_CC, dl, MVT::i32, N->getOperand(0), Tmp, + DAG.getNode(ISD::ADD, dl, MVT::i32, + DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, + DAG.getNode(ISD::FSUB, dl, + MVT::ppcf128, + N->getOperand(0), + Tmp)), + DAG.getConstant(0x80000000, MVT::i32)), + DAG.getNode(ISD::FP_TO_SINT, dl, + MVT::i32, N->getOperand(0)), + DAG.getCondCode(ISD::SETGE)); + } + + RTLIB::Libcall LC = RTLIB::getFPTOUINT(N->getOperand(0).getValueType(), RVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_UINT!"); + return MakeLibCall(LC, N->getValueType(0), &N->getOperand(0), 1, false, dl); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)), 0); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + FloatExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + DAG.getCondCode(CCCode)), 0); +} + +SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { + if (ISD::isNormalStore(N)) + return ExpandOp_NormalStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + StoreSDNode *ST = cast(N); + + SDValue Chain = ST->getChain(); + SDValue Ptr = ST->getBasePtr(); + + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), + ST->getValue().getValueType()); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + SDValue Lo, Hi; + GetExpandedOp(ST->getValue(), Lo, Hi); + + return DAG.getTruncStore(Chain, N->getDebugLoc(), Hi, Ptr, + ST->getPointerInfo(), + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); +} diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp new file mode 100644 index 00000000000..935aab0e59a --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -0,0 +1,2615 @@ +//===----- LegalizeIntegerTypes.cpp - Legalization of integer types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements integer type expansion and promotion for LegalizeTypes. +// Promotion is the act of changing a computation in an illegal type into a +// computation in a larger type. For example, implementing i8 arithmetic in an +// i32 register (often needed on powerpc). +// Expansion is the act of changing a computation in an illegal type into a +// computation in two identical registers of a smaller type. For example, +// implementing i64 arithmetic in two i32 registers (often needed on 32-bit +// targets). +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Integer Result Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerResult - This method is called when a result of a node is +/// found to be in need of promotion to a larger type. At this point, the node +/// may also have invalid operands or may have other results that need +/// expansion, we just know that (at least) one result needs promotion. +void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Promote integer result: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Res = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "PromoteIntegerResult #" << ResNo << ": "; + N->dump(&DAG); dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to promote this operator!"); + case ISD::AssertSext: Res = PromoteIntRes_AssertSext(N); break; + case ISD::AssertZext: Res = PromoteIntRes_AssertZext(N); break; + case ISD::BITCAST: Res = PromoteIntRes_BITCAST(N); break; + case ISD::BSWAP: Res = PromoteIntRes_BSWAP(N); break; + case ISD::BUILD_PAIR: Res = PromoteIntRes_BUILD_PAIR(N); break; + case ISD::Constant: Res = PromoteIntRes_Constant(N); break; + case ISD::CONVERT_RNDSAT: + Res = PromoteIntRes_CONVERT_RNDSAT(N); break; + case ISD::CTLZ: Res = PromoteIntRes_CTLZ(N); break; + case ISD::CTPOP: Res = PromoteIntRes_CTPOP(N); break; + case ISD::CTTZ: Res = PromoteIntRes_CTTZ(N); break; + case ISD::EXTRACT_VECTOR_ELT: + Res = PromoteIntRes_EXTRACT_VECTOR_ELT(N); break; + case ISD::LOAD: Res = PromoteIntRes_LOAD(cast(N));break; + case ISD::SELECT: Res = PromoteIntRes_SELECT(N); break; + case ISD::SELECT_CC: Res = PromoteIntRes_SELECT_CC(N); break; + case ISD::SETCC: Res = PromoteIntRes_SETCC(N); break; + case ISD::SHL: Res = PromoteIntRes_SHL(N); break; + case ISD::SIGN_EXTEND_INREG: + Res = PromoteIntRes_SIGN_EXTEND_INREG(N); break; + case ISD::SRA: Res = PromoteIntRes_SRA(N); break; + case ISD::SRL: Res = PromoteIntRes_SRL(N); break; + case ISD::TRUNCATE: Res = PromoteIntRes_TRUNCATE(N); break; + case ISD::UNDEF: Res = PromoteIntRes_UNDEF(N); break; + case ISD::VAARG: Res = PromoteIntRes_VAARG(N); break; + + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: Res = PromoteIntRes_INT_EXTEND(N); break; + + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: Res = PromoteIntRes_FP_TO_XINT(N); break; + + case ISD::FP32_TO_FP16:Res = PromoteIntRes_FP32_TO_FP16(N); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: Res = PromoteIntRes_SimpleIntBinOp(N); break; + + case ISD::SDIV: + case ISD::SREM: Res = PromoteIntRes_SDIV(N); break; + + case ISD::UDIV: + case ISD::UREM: Res = PromoteIntRes_UDIV(N); break; + + case ISD::SADDO: + case ISD::SSUBO: Res = PromoteIntRes_SADDSUBO(N, ResNo); break; + case ISD::UADDO: + case ISD::USUBO: Res = PromoteIntRes_UADDSUBO(N, ResNo); break; + case ISD::SMULO: + case ISD::UMULO: Res = PromoteIntRes_XMULO(N, ResNo); break; + + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + case ISD::ATOMIC_SWAP: + Res = PromoteIntRes_Atomic1(cast(N)); break; + + case ISD::ATOMIC_CMP_SWAP: + Res = PromoteIntRes_Atomic2(cast(N)); break; + } + + // If the result is null then the sub-method took care of registering it. + if (Res.getNode()) + SetPromotedInteger(SDValue(N, ResNo), Res); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_AssertSext(SDNode *N) { + // Sign-extend the new bits, and continue the assertion. + SDValue Op = SExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::AssertSext, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_AssertZext(SDNode *N) { + // Zero the new bits, and continue the assertion. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::AssertZext, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic1(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), + N->getMemoryVT(), + N->getChain(), N->getBasePtr(), + Op2, N->getMemOperand()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Atomic2(AtomicSDNode *N) { + SDValue Op2 = GetPromotedInteger(N->getOperand(2)); + SDValue Op3 = GetPromotedInteger(N->getOperand(3)); + SDValue Res = DAG.getAtomic(N->getOpcode(), N->getDebugLoc(), + N->getMemoryVT(), N->getChain(), N->getBasePtr(), + Op2, Op3, N->getMemOperand()); + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BITCAST(SDNode *N) { + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + EVT NInVT = TLI.getTypeToTransformTo(*DAG.getContext(), InVT); + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + DebugLoc dl = N->getDebugLoc(); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + if (NOutVT.bitsEq(NInVT)) + // The input promotes to the same size. Convert the promoted value. + return DAG.getNode(ISD::BITCAST, dl, NOutVT, GetPromotedInteger(InOp)); + break; + case SoftenFloat: + // Promote the integer operand by hand. + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, GetSoftenedFloat(InOp)); + case ExpandInteger: + case ExpandFloat: + break; + case ScalarizeVector: + // Convert the element to an integer and promote it by hand. + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, + BitConvertToInteger(GetScalarizedVector(InOp))); + case SplitVector: { + // For example, i32 = BITCAST v2i16 on alpha. Convert the split + // pieces of the input into integers and reassemble in the final type. + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + InOp = DAG.getNode(ISD::ANY_EXTEND, dl, + EVT::getIntegerVT(*DAG.getContext(), + NOutVT.getSizeInBits()), + JoinIntegers(Lo, Hi)); + return DAG.getNode(ISD::BITCAST, dl, NOutVT, InOp); + } + case WidenVector: + if (OutVT.bitsEq(NInVT)) + // The input is widened to the same size. Convert to the widened value. + return DAG.getNode(ISD::BITCAST, dl, OutVT, GetWidenedVector(InOp)); + } + + return DAG.getNode(ISD::ANY_EXTEND, dl, NOutVT, + CreateStackStoreLoad(InOp, OutVT)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits(); + return DAG.getNode(ISD::SRL, dl, NVT, DAG.getNode(ISD::BSWAP, dl, NVT, Op), + DAG.getConstant(DiffBits, TLI.getPointerTy())); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) { + // The pair element type may be legal, or may not promote to the same type as + // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), + N->getValueType(0)), JoinIntegers(N->getOperand(0), + N->getOperand(1))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_Constant(SDNode *N) { + EVT VT = N->getValueType(0); + // FIXME there is no actual debug info here + DebugLoc dl = N->getDebugLoc(); + // Zero extend things like i1, sign extend everything else. It shouldn't + // matter in theory which one we pick, but this tends to give better code? + unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDValue Result = DAG.getNode(Opc, dl, + TLI.getTypeToTransformTo(*DAG.getContext(), VT), + SDValue(N, 0)); + assert(isa(Result) && "Didn't constant fold ext?"); + return Result; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CONVERT_RNDSAT(SDNode *N) { + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_SF || CvtCode == ISD::CVT_UF) && + "can only promote integers"); + EVT OutVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getConvertRndSat(OutVT, N->getDebugLoc(), N->getOperand(0), + N->getOperand(1), N->getOperand(2), + N->getOperand(3), N->getOperand(4), CvtCode); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTLZ(SDNode *N) { + // Zero extend to the promoted type and do the count there. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + DebugLoc dl = N->getDebugLoc(); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + Op = DAG.getNode(ISD::CTLZ, dl, NVT, Op); + // Subtract off the extra leading bits in the bigger type. + return DAG.getNode(ISD::SUB, dl, NVT, Op, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTPOP(SDNode *N) { + // Zero extend to the promoted type and do the count there. + SDValue Op = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::CTPOP, N->getDebugLoc(), Op.getValueType(), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + EVT OVT = N->getValueType(0); + EVT NVT = Op.getValueType(); + DebugLoc dl = N->getDebugLoc(); + // The count is the same in the promoted type except if the original + // value was zero. This can be handled by setting the bit just off + // the top of the original type. + APInt TopBit(NVT.getSizeInBits(), 0); + TopBit.setBit(OVT.getSizeInBits()); + Op = DAG.getNode(ISD::OR, dl, NVT, Op, DAG.getConstant(TopBit, NVT)); + return DAG.getNode(ISD::CTTZ, dl, NVT, Op); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NVT, N->getOperand(0), + N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned NewOpc = N->getOpcode(); + DebugLoc dl = N->getDebugLoc(); + + // If we're promoting a UINT to a larger size and the larger FP_TO_UINT is + // not Legal, check to see if we can use FP_TO_SINT instead. (If both UINT + // and SINT conversions are Custom, there is no way to tell which is + // preferable. We choose SINT because that's the right thing on PPC.) + if (N->getOpcode() == ISD::FP_TO_UINT && + !TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && + TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT)) + NewOpc = ISD::FP_TO_SINT; + + SDValue Res = DAG.getNode(NewOpc, dl, NVT, N->getOperand(0)); + + // Assert that the converted value fits in the original type. If it doesn't + // (eg: because the value being converted is too big), then the result of the + // original operation was undefined anyway, so the assert is still correct. + return DAG.getNode(N->getOpcode() == ISD::FP_TO_UINT ? + ISD::AssertZext : ISD::AssertSext, dl, + NVT, Res, DAG.getValueType(N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_FP32_TO_FP16(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + + SDValue Res = DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0)); + + return DAG.getNode(ISD::AssertZext, dl, + NVT, Res, DAG.getValueType(N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + + if (getTypeAction(N->getOperand(0).getValueType()) == PromoteInteger) { + SDValue Res = GetPromotedInteger(N->getOperand(0)); + assert(Res.getValueType().bitsLE(NVT) && "Extension doesn't make sense!"); + + // If the result and operand types are the same after promotion, simplify + // to an in-register extension. + if (NVT == Res.getValueType()) { + // The high bits are not guaranteed to be anything. Insert an extend. + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NVT, Res, + DAG.getValueType(N->getOperand(0).getValueType())); + if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getZeroExtendInReg(Res, dl, N->getOperand(0).getValueType()); + assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); + return Res; + } + } + + // Otherwise, just extend the original operand all the way to the larger type. + return DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); + DebugLoc dl = N->getDebugLoc(); + SDValue Res = DAG.getExtLoad(ExtType, dl, NVT, N->getChain(), N->getBasePtr(), + N->getPointerInfo(), + N->getMemoryVT(), N->isVolatile(), + N->isNonTemporal(), N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); + return Res; +} + +/// Promote the overflow flag of an overflowing arithmetic node. +SDValue DAGTypeLegalizer::PromoteIntRes_Overflow(SDNode *N) { + // Simply change the return type of the boolean result. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(1)); + EVT ValueVTs[] = { N->getValueType(0), NVT }; + SDValue Ops[] = { N->getOperand(0), N->getOperand(1) }; + SDValue Res = DAG.getNode(N->getOpcode(), N->getDebugLoc(), + DAG.getVTList(ValueVTs, 2), Ops, 2); + + // Modified the sum result - switch anything that used the old sum to use + // the new one. + ReplaceValueWith(SDValue(N, 0), Res); + + return SDValue(Res.getNode(), 1); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SADDSUBO(SDNode *N, unsigned ResNo) { + if (ResNo == 1) + return PromoteIntRes_Overflow(N); + + // The operation overflowed iff the result in the larger type is not the + // sign extension of its truncation to the original type. + SDValue LHS = SExtPromotedInteger(N->getOperand(0)); + SDValue RHS = SExtPromotedInteger(N->getOperand(1)); + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = LHS.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Do the arithmetic in the larger type. + unsigned Opcode = N->getOpcode() == ISD::SADDO ? ISD::ADD : ISD::SUB; + SDValue Res = DAG.getNode(Opcode, dl, NVT, LHS, RHS); + + // Calculate the overflow flag: sign extend the arithmetic result from + // the original type. + SDValue Ofl = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NVT, Res, + DAG.getValueType(OVT)); + // Overflowed if and only if this is not equal to Res. + Ofl = DAG.getSetCC(dl, N->getValueType(1), Ofl, Res, ISD::SETNE); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Ofl); + + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SDIV(SDNode *N) { + // Sign extend the input. + SDValue LHS = SExtPromotedInteger(N->getOperand(0)); + SDValue RHS = SExtPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) { + SDValue LHS = GetPromotedInteger(N->getOperand(1)); + SDValue RHS = GetPromotedInteger(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetPromotedInteger(N->getOperand(2)); + SDValue RHS = GetPromotedInteger(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { + EVT SVT = TLI.getSetCCResultType(N->getOperand(0).getValueType()); + assert(isTypeLegal(SVT) && "Illegal SetCC type!"); + DebugLoc dl = N->getDebugLoc(); + + // Get the SETCC result using the canonical SETCC type. + SDValue SetCC = DAG.getNode(ISD::SETCC, dl, SVT, N->getOperand(0), + N->getOperand(1), N->getOperand(2)); + + // Convert to the expected type. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + assert(NVT.bitsLE(SVT) && "Integer type overpromoted?"); + return DAG.getNode(ISD::TRUNCATE, dl, NVT, SetCC); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) { + return DAG.getNode(ISD::SHL, N->getDebugLoc(), + TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)), + GetPromotedInteger(N->getOperand(0)), N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SIGN_EXTEND_INREG(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SimpleIntBinOp(SDNode *N) { + // The input may have strange things in the top bits of the registers, but + // these operations don't care. They may have weird bits going out, but + // that too is okay if they are integer operations. + SDValue LHS = GetPromotedInteger(N->getOperand(0)); + SDValue RHS = GetPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SRA(SDNode *N) { + // The input value must be properly sign extended. + SDValue Res = SExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRA, N->getDebugLoc(), + Res.getValueType(), Res, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_SRL(SDNode *N) { + // The input value must be properly zero extended. + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Res = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRL, N->getDebugLoc(), NVT, Res, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Res; + + switch (getTypeAction(N->getOperand(0).getValueType())) { + default: llvm_unreachable("Unknown type action!"); + case Legal: + case ExpandInteger: + Res = N->getOperand(0); + break; + case PromoteInteger: + Res = GetPromotedInteger(N->getOperand(0)); + break; + } + + // Truncate to NVT instead of VT + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), NVT, Res); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UADDSUBO(SDNode *N, unsigned ResNo) { + if (ResNo == 1) + return PromoteIntRes_Overflow(N); + + // The operation overflowed iff the result in the larger type is not the + // zero extension of its truncation to the original type. + SDValue LHS = ZExtPromotedInteger(N->getOperand(0)); + SDValue RHS = ZExtPromotedInteger(N->getOperand(1)); + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = LHS.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Do the arithmetic in the larger type. + unsigned Opcode = N->getOpcode() == ISD::UADDO ? ISD::ADD : ISD::SUB; + SDValue Res = DAG.getNode(Opcode, dl, NVT, LHS, RHS); + + // Calculate the overflow flag: zero extend the arithmetic result from + // the original type. + SDValue Ofl = DAG.getZeroExtendInReg(Res, dl, OVT); + // Overflowed if and only if this is not equal to Res. + Ofl = DAG.getSetCC(dl, N->getValueType(1), Ofl, Res, ISD::SETNE); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Ofl); + + return Res; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_XMULO(SDNode *N, unsigned ResNo) { + // Promote the overflow bit trivially. + if (ResNo == 1) + return PromoteIntRes_Overflow(N); + + SDValue LHS = N->getOperand(0), RHS = N->getOperand(1); + DebugLoc DL = N->getDebugLoc(); + EVT SmallVT = LHS.getValueType(); + + // To determine if the result overflowed in a larger type, we extend the input + // to the larger type, do the multiply, then check the high bits of the result + // to see if the overflow happened. + if (N->getOpcode() == ISD::SMULO) { + LHS = SExtPromotedInteger(LHS); + RHS = SExtPromotedInteger(RHS); + } else { + LHS = ZExtPromotedInteger(LHS); + RHS = ZExtPromotedInteger(RHS); + } + SDValue Mul = DAG.getNode(ISD::MUL, DL, LHS.getValueType(), LHS, RHS); + + // Overflow occurred iff the high part of the result does not zero/sign-extend + // the low part. + SDValue Overflow; + if (N->getOpcode() == ISD::UMULO) { + // Unsigned overflow occurred iff the high part is non-zero. + SDValue Hi = DAG.getNode(ISD::SRL, DL, Mul.getValueType(), Mul, + DAG.getIntPtrConstant(SmallVT.getSizeInBits())); + Overflow = DAG.getSetCC(DL, N->getValueType(1), Hi, + DAG.getConstant(0, Hi.getValueType()), ISD::SETNE); + } else { + // Signed overflow occurred iff the high part does not sign extend the low. + SDValue SExt = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Mul.getValueType(), + Mul, DAG.getValueType(SmallVT)); + Overflow = DAG.getSetCC(DL, N->getValueType(1), SExt, Mul, ISD::SETNE); + } + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Overflow); + return Mul; +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) { + // Zero extend the input. + SDValue LHS = ZExtPromotedInteger(N->getOperand(0)); + SDValue RHS = ZExtPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(TLI.getTypeToTransformTo(*DAG.getContext(), + N->getValueType(0))); +} + +SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { + SDValue Chain = N->getOperand(0); // Get the chain. + SDValue Ptr = N->getOperand(1); // Get the pointer. + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + EVT RegVT = TLI.getRegisterType(*DAG.getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), VT); + // The argument is passed as NumRegs registers of type RegVT. + + SmallVector Parts(NumRegs); + for (unsigned i = 0; i < NumRegs; ++i) { + Parts[i] = DAG.getVAArg(RegVT, dl, Chain, Ptr, N->getOperand(2), + N->getConstantOperandVal(3)); + Chain = Parts[i].getValue(1); + } + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::reverse(Parts.begin(), Parts.end()); + + // Assemble the parts in the promoted type. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue Res = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Parts[0]); + for (unsigned i = 1; i < NumRegs; ++i) { + SDValue Part = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Parts[i]); + // Shift it to the right position and "or" it in. + Part = DAG.getNode(ISD::SHL, dl, NVT, Part, + DAG.getConstant(i * RegVT.getSizeInBits(), + TLI.getPointerTy())); + Res = DAG.getNode(ISD::OR, dl, NVT, Res, Part); + } + + // Modified the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Chain); + + return Res; +} + +//===----------------------------------------------------------------------===// +// Integer Operand Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need promotion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Promote integer operand: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Res = SDValue(); + + if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) + return false; + + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + dbgs() << "PromoteIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); dbgs() << "\n"; + #endif + llvm_unreachable("Do not know how to promote this operator's operand!"); + + case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; + case ISD::BITCAST: Res = PromoteIntOp_BITCAST(N); break; + case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; + case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; + case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break; + case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break; + case ISD::CONVERT_RNDSAT: + Res = PromoteIntOp_CONVERT_RNDSAT(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);break; + case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; + case ISD::SCALAR_TO_VECTOR: + Res = PromoteIntOp_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; + case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break; + case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; + case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break; + case ISD::SINT_TO_FP: Res = PromoteIntOp_SINT_TO_FP(N); break; + case ISD::STORE: Res = PromoteIntOp_STORE(cast(N), + OpNo); break; + case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break; + case ISD::FP16_TO_FP32: + case ISD::UINT_TO_FP: Res = PromoteIntOp_UINT_TO_FP(N); break; + case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: Res = PromoteIntOp_Shift(N); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// PromoteSetCCOperands - Promote the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::PromoteSetCCOperands(SDValue &NewLHS,SDValue &NewRHS, + ISD::CondCode CCCode) { + // We have to insert explicit sign or zero extends. Note that we could + // insert sign extends for ALL conditions, but zero extend is cheaper on + // many machines (an AND instead of two shifts), so prefer it. + switch (CCCode) { + default: llvm_unreachable("Unknown integer comparison!"); + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + NewLHS = ZExtPromotedInteger(NewLHS); + NewRHS = ZExtPromotedInteger(NewRHS); + break; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + NewLHS = SExtPromotedInteger(NewLHS); + NewRHS = SExtPromotedInteger(NewRHS); + break; + } +} + +SDValue DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BITCAST(SDNode *N) { + // This should only occur in unusual situations like bitcasting to an + // x86_fp80, so just turn it into a store+load + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 2 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(2); + SDValue RHS = N->getOperand(3); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); + + // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always + // legal types. + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)), + 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) { + assert(OpNo == 1 && "only know how to promote condition"); + + // Promote all the way up to the canonical SetCC type. + EVT SVT = TLI.getSetCCResultType(MVT::Other); + SDValue Cond = PromoteTargetBoolean(N->getOperand(1), SVT); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Cond, + N->getOperand(2)), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) { + // Since the result type is legal, the operands must promote to it. + EVT OVT = N->getOperand(0).getValueType(); + SDValue Lo = ZExtPromotedInteger(N->getOperand(0)); + SDValue Hi = GetPromotedInteger(N->getOperand(1)); + assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); + DebugLoc dl = N->getDebugLoc(); + + Hi = DAG.getNode(ISD::SHL, dl, N->getValueType(0), Hi, + DAG.getConstant(OVT.getSizeInBits(), TLI.getPointerTy())); + return DAG.getNode(ISD::OR, dl, N->getValueType(0), Lo, Hi); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type is not. This implies + // that the vector is a power-of-two in length and that the element + // type does not have a strange size (eg: it is not i1). + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + assert(!(NumElts & 1) && "Legal vector of one illegal element?"); + + // Promote the inserted value. The type does not need to match the + // vector element type. Check that any extra bits introduced will be + // truncated away. + assert(N->getOperand(0).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + + SmallVector NewOps; + for (unsigned i = 0; i < NumElts; ++i) + NewOps.push_back(GetPromotedInteger(N->getOperand(i))); + + return SDValue(DAG.UpdateNodeOperands(N, &NewOps[0], NumElts), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_CONVERT_RNDSAT(SDNode *N) { + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + assert ((CvtCode == ISD::CVT_SS || CvtCode == ISD::CVT_SU || + CvtCode == ISD::CVT_US || CvtCode == ISD::CVT_UU || + CvtCode == ISD::CVT_FS || CvtCode == ISD::CVT_FU) && + "can only promote integer arguments"); + SDValue InOp = GetPromotedInteger(N->getOperand(0)); + return DAG.getConvertRndSat(N->getValueType(0), N->getDebugLoc(), InOp, + N->getOperand(1), N->getOperand(2), + N->getOperand(3), N->getOperand(4), CvtCode); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(N->getOperand(1).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + GetPromotedInteger(N->getOperand(1)), + N->getOperand(2)), + 0); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDValue Idx = ZExtPromotedInteger(N->getOperand(2)); + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + N->getOperand(1), Idx), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { + SDValue NewOps[6]; + DebugLoc dl = N->getDebugLoc(); + NewOps[0] = N->getOperand(0); + for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { + SDValue Flag = GetPromotedInteger(N->getOperand(i)); + NewOps[i] = DAG.getZeroExtendInReg(Flag, dl, MVT::i1); + } + return SDValue(DAG.UpdateNodeOperands(N, NewOps, array_lengthof(NewOps)), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N) { + // Integer SCALAR_TO_VECTOR operands are implicitly truncated, so just promote + // the operand in place. + return SDValue(DAG.UpdateNodeOperands(N, + GetPromotedInteger(N->getOperand(0))), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Only know how to promote condition"); + + // Promote all the way up to the canonical SetCC type. + EVT SVT = TLI.getSetCCResultType(N->getOperand(1).getValueType()); + SDValue Cond = PromoteTargetBoolean(N->getOperand(0), SVT); + + return SDValue(DAG.UpdateNodeOperands(N, Cond, + N->getOperand(1), N->getOperand(2)), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(4))->get()); + + // The CC (#4) and the possible return values (#2 and #3) have legal types. + return SDValue(DAG.UpdateNodeOperands(N, LHS, RHS, N->getOperand(2), + N->getOperand(3), N->getOperand(4)), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand!"); + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(2))->get()); + + // The CC (#2) is always legal. + return SDValue(DAG.UpdateNodeOperands(N, LHS, RHS, N->getOperand(2)), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_Shift(SDNode *N) { + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + ZExtPromotedInteger(N->getOperand(1))), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SIGN_EXTEND(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + DebugLoc dl = N->getDebugLoc(); + Op = DAG.getNode(ISD::ANY_EXTEND, dl, N->getValueType(0), Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Op.getValueType(), + Op, DAG.getValueType(N->getOperand(0).getValueType())); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_SINT_TO_FP(SDNode *N) { + return SDValue(DAG.UpdateNodeOperands(N, + SExtPromotedInteger(N->getOperand(0))), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + SDValue Ch = N->getChain(), Ptr = N->getBasePtr(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Val = GetPromotedInteger(N->getValue()); // Get promoted value. + + // Truncate the value and store the result. + return DAG.getTruncStore(Ch, dl, Val, Ptr, N->getPointerInfo(), + N->getMemoryVT(), + isVolatile, isNonTemporal, Alignment); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { + SDValue Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), N->getValueType(0), Op); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_UINT_TO_FP(SDNode *N) { + return SDValue(DAG.UpdateNodeOperands(N, + ZExtPromotedInteger(N->getOperand(0))), 0); +} + +SDValue DAGTypeLegalizer::PromoteIntOp_ZERO_EXTEND(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, dl, N->getValueType(0), Op); + return DAG.getZeroExtendInReg(Op, dl, N->getOperand(0).getValueType()); +} + + +//===----------------------------------------------------------------------===// +// Integer Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Expand integer result: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Lo, Hi; + Lo = Hi = SDValue(); + + // See if the target wants to custom expand this node. + if (CustomLowerNode(N, N->getValueType(ResNo), true)) + return; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "ExpandIntegerResult #" << ResNo << ": "; + N->dump(&DAG); dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to expand the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BITCAST: ExpandRes_BITCAST(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VAARG: ExpandRes_VAARG(N, Lo, Hi); break; + + case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; + case ISD::AssertSext: ExpandIntRes_AssertSext(N, Lo, Hi); break; + case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; + case ISD::BSWAP: ExpandIntRes_BSWAP(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; + case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; + case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; + case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; + case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; + case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; + case ISD::LOAD: ExpandIntRes_LOAD(cast(N), Lo, Hi); break; + case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; + case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; + case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; + case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; + case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; + case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; + case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break; + case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break; + case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; + + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: + case ISD::ATOMIC_SWAP: { + std::pair Tmp = ExpandAtomic(N); + SplitInteger(Tmp.first, Lo, Hi); + ReplaceValueWith(SDValue(N, 1), Tmp.second); + break; + } + + case ISD::AND: + case ISD::OR: + case ISD::XOR: ExpandIntRes_Logical(N, Lo, Hi); break; + + case ISD::ADD: + case ISD::SUB: ExpandIntRes_ADDSUB(N, Lo, Hi); break; + + case ISD::ADDC: + case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; + + case ISD::ADDE: + case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: ExpandIntRes_Shift(N, Lo, Hi); break; + + case ISD::SADDO: + case ISD::SSUBO: ExpandIntRes_SADDSUBO(N, Lo, Hi); break; + case ISD::UADDO: + case ISD::USUBO: ExpandIntRes_UADDSUBO(N, Lo, Hi); break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetExpandedInteger(SDValue(N, ResNo), Lo, Hi); +} + +/// Lower an atomic node to the appropriate builtin call. +std::pair DAGTypeLegalizer::ExpandAtomic(SDNode *Node) { + unsigned Opc = Node->getOpcode(); + MVT VT = cast(Node)->getMemoryVT().getSimpleVT(); + RTLIB::Libcall LC; + + switch (Opc) { + default: + llvm_unreachable("Unhandled atomic intrinsic Expand!"); + break; + case ISD::ATOMIC_SWAP: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_1; break; + case MVT::i16: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_2; break; + case MVT::i32: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_4; break; + case MVT::i64: LC = RTLIB::SYNC_LOCK_TEST_AND_SET_8; break; + } + break; + case ISD::ATOMIC_CMP_SWAP: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1; break; + case MVT::i16: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2; break; + case MVT::i32: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_4; break; + case MVT::i64: LC = RTLIB::SYNC_VAL_COMPARE_AND_SWAP_8; break; + } + break; + case ISD::ATOMIC_LOAD_ADD: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_ADD_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_ADD_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_ADD_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_ADD_8; break; + } + break; + case ISD::ATOMIC_LOAD_SUB: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_SUB_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_SUB_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_SUB_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_SUB_8; break; + } + break; + case ISD::ATOMIC_LOAD_AND: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_AND_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_AND_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_AND_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_AND_8; break; + } + break; + case ISD::ATOMIC_LOAD_OR: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_OR_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_OR_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_OR_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_OR_8; break; + } + break; + case ISD::ATOMIC_LOAD_XOR: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_XOR_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_XOR_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_XOR_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_XOR_8; break; + } + break; + case ISD::ATOMIC_LOAD_NAND: + switch (VT.SimpleTy) { + default: llvm_unreachable("Unexpected value type for atomic!"); + case MVT::i8: LC = RTLIB::SYNC_FETCH_AND_NAND_1; break; + case MVT::i16: LC = RTLIB::SYNC_FETCH_AND_NAND_2; break; + case MVT::i32: LC = RTLIB::SYNC_FETCH_AND_NAND_4; break; + case MVT::i64: LC = RTLIB::SYNC_FETCH_AND_NAND_8; break; + } + break; + } + + return ExpandChainLibCall(LC, Node, false); +} + +/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, +/// and the shift amount is a constant 'Amt'. Expand the operation. +void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, + SDValue &Lo, SDValue &Hi) { + DebugLoc DL = N->getDebugLoc(); + // Expand the incoming operand to be shifted, so that we have its parts + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + EVT NVT = InL.getValueType(); + unsigned VTBits = N->getValueType(0).getSizeInBits(); + unsigned NVTBits = NVT.getSizeInBits(); + EVT ShTy = N->getOperand(1).getValueType(); + + if (N->getOpcode() == ISD::SHL) { + if (Amt > VTBits) { + Lo = Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getNode(ISD::SHL, DL, + NVT, InL, DAG.getConstant(Amt-NVTBits, ShTy)); + } else if (Amt == NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = InL; + } else if (Amt == 1 && + TLI.isOperationLegalOrCustom(ISD::ADDC, + TLI.getTypeToExpandTo(*DAG.getContext(), NVT))) { + // Emit this X << 1 as X+X. + SDVTList VTList = DAG.getVTList(NVT, MVT::Glue); + SDValue LoOps[2] = { InL, InL }; + Lo = DAG.getNode(ISD::ADDC, DL, VTList, LoOps, 2); + SDValue HiOps[3] = { InH, InH, Lo.getValue(1) }; + Hi = DAG.getNode(ISD::ADDE, DL, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SHL, DL, NVT, InL, DAG.getConstant(Amt, ShTy)); + Hi = DAG.getNode(ISD::OR, DL, NVT, + DAG.getNode(ISD::SHL, DL, NVT, InH, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SRL, DL, NVT, InL, + DAG.getConstant(NVTBits-Amt, ShTy))); + } + return; + } + + if (N->getOpcode() == ISD::SRL) { + if (Amt > VTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRL, DL, + NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy)); + Hi = DAG.getConstant(0, NVT); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getConstant(0, NVT); + } else { + Lo = DAG.getNode(ISD::OR, DL, NVT, + DAG.getNode(ISD::SRL, DL, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, DL, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRL, DL, NVT, InH, DAG.getConstant(Amt, ShTy)); + } + return; + } + + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + if (Amt > VTBits) { + Hi = Lo = DAG.getNode(ISD::SRA, DL, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRA, DL, NVT, InH, + DAG.getConstant(Amt-NVTBits, ShTy)); + Hi = DAG.getNode(ISD::SRA, DL, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getNode(ISD::SRA, DL, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else { + Lo = DAG.getNode(ISD::OR, DL, NVT, + DAG.getNode(ISD::SRL, DL, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, DL, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRA, DL, NVT, InH, DAG.getConstant(Amt, ShTy)); + } +} + +/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify +/// this shift based on knowledge of the high bit of the shift amount. If we +/// can tell this, we know that it is >= 32 or < 32, without knowing the actual +/// shift amount. +bool DAGTypeLegalizer:: +ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { + SDValue Amt = N->getOperand(1); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT ShTy = Amt.getValueType(); + unsigned ShBits = ShTy.getScalarType().getSizeInBits(); + unsigned NVTBits = NVT.getScalarType().getSizeInBits(); + assert(isPowerOf2_32(NVTBits) && + "Expanded integer type size not a power of two!"); + DebugLoc dl = N->getDebugLoc(); + + APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits)); + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne); + + // If we don't know anything about the high bits, exit. + if (((KnownZero|KnownOne) & HighBitMask) == 0) + return false; + + // Get the incoming operand to be shifted. + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + // If we know that any of the high bits of the shift amount are one, then we + // can do this as a couple of simple shifts. + if (KnownOne.intersects(HighBitMask)) { + // Mask out the high bit, which we know is set. + Amt = DAG.getNode(ISD::AND, dl, ShTy, Amt, + DAG.getConstant(~HighBitMask, ShTy)); + + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: + Lo = DAG.getConstant(0, NVT); // Low part is zero. + Hi = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); // High part from Lo part. + return true; + case ISD::SRL: + Hi = DAG.getConstant(0, NVT); // Hi part is zero. + Lo = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); // Lo part from Hi part. + return true; + case ISD::SRA: + Hi = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign extend high part. + DAG.getConstant(NVTBits-1, ShTy)); + Lo = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); // Lo part from Hi part. + return true; + } + } + +#if 0 + // FIXME: This code is broken for shifts with a zero amount! + // If we know that all of the high bits of the shift amount are zero, then we + // can do this as a couple of simple shifts. + if ((KnownZero & HighBitMask) == HighBitMask) { + // Compute 32-amt. + SDValue Amt2 = DAG.getNode(ISD::SUB, ShTy, + DAG.getConstant(NVTBits, ShTy), + Amt); + unsigned Op1, Op2; + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break; + case ISD::SRL: + case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break; + } + + Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt); + Hi = DAG.getNode(ISD::OR, NVT, + DAG.getNode(Op1, NVT, InH, Amt), + DAG.getNode(Op2, NVT, InL, Amt2)); + return true; + } +#endif + + return false; +} + +/// ExpandShiftWithUnknownAmountBit - Fully general expansion of integer shift +/// of any size. +bool DAGTypeLegalizer:: +ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { + SDValue Amt = N->getOperand(1); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT ShTy = Amt.getValueType(); + unsigned NVTBits = NVT.getSizeInBits(); + assert(isPowerOf2_32(NVTBits) && + "Expanded integer type size not a power of two!"); + DebugLoc dl = N->getDebugLoc(); + + // Get the incoming operand to be shifted. + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + SDValue NVBitsNode = DAG.getConstant(NVTBits, ShTy); + SDValue AmtExcess = DAG.getNode(ISD::SUB, dl, ShTy, Amt, NVBitsNode); + SDValue AmtLack = DAG.getNode(ISD::SUB, dl, ShTy, NVBitsNode, Amt); + SDValue isShort = DAG.getSetCC(dl, TLI.getSetCCResultType(ShTy), + Amt, NVBitsNode, ISD::SETULT); + + SDValue LoS, HiS, LoL, HiL; + switch (N->getOpcode()) { + default: llvm_unreachable("Unknown shift"); + case ISD::SHL: + // Short: ShAmt < NVTBits + LoS = DAG.getNode(ISD::SHL, dl, NVT, InL, Amt); + HiS = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SHL, dl, NVT, InH, Amt), + // FIXME: If Amt is zero, the following shift generates an undefined result + // on some architectures. + DAG.getNode(ISD::SRL, dl, NVT, InL, AmtLack)); + + // Long: ShAmt >= NVTBits + LoL = DAG.getConstant(0, NVT); // Lo part is zero. + HiL = DAG.getNode(ISD::SHL, dl, NVT, InL, AmtExcess); // Hi from Lo part. + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL); + return true; + case ISD::SRL: + // Short: ShAmt < NVTBits + HiS = DAG.getNode(ISD::SRL, dl, NVT, InH, Amt); + LoS = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), + // FIXME: If Amt is zero, the following shift generates an undefined result + // on some architectures. + DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack)); + + // Long: ShAmt >= NVTBits + HiL = DAG.getConstant(0, NVT); // Hi part is zero. + LoL = DAG.getNode(ISD::SRL, dl, NVT, InH, AmtExcess); // Lo from Hi part. + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL); + return true; + case ISD::SRA: + // Short: ShAmt < NVTBits + HiS = DAG.getNode(ISD::SRA, dl, NVT, InH, Amt); + LoS = DAG.getNode(ISD::OR, dl, NVT, + DAG.getNode(ISD::SRL, dl, NVT, InL, Amt), + // FIXME: If Amt is zero, the following shift generates an undefined result + // on some architectures. + DAG.getNode(ISD::SHL, dl, NVT, InH, AmtLack)); + + // Long: ShAmt >= NVTBits + HiL = DAG.getNode(ISD::SRA, dl, NVT, InH, // Sign of Hi part. + DAG.getConstant(NVTBits-1, ShTy)); + LoL = DAG.getNode(ISD::SRA, dl, NVT, InH, AmtExcess); // Lo from Hi part. + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, isShort, LoS, LoL); + Hi = DAG.getNode(ISD::SELECT, dl, NVT, isShort, HiS, HiL); + return true; + } + + return false; +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + + EVT NVT = LHSL.getValueType(); + SDValue LoOps[2] = { LHSL, RHSL }; + SDValue HiOps[3] = { LHSH, RHSH }; + + // Do not generate ADDC/ADDE or SUBC/SUBE if the target does not support + // them. TODO: Teach operation legalization how to expand unsupported + // ADDC/ADDE/SUBC/SUBE. The problem is that these operations generate + // a carry of type MVT::Glue, but there doesn't seem to be any way to + // generate a value of this type in the expanded code sequence. + bool hasCarry = + TLI.isOperationLegalOrCustom(N->getOpcode() == ISD::ADD ? + ISD::ADDC : ISD::SUBC, + TLI.getTypeToExpandTo(*DAG.getContext(), NVT)); + + if (hasCarry) { + SDVTList VTList = DAG.getVTList(NVT, MVT::Glue); + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, dl, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); + } + return; + } + + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADD, dl, NVT, LoOps, 2); + Hi = DAG.getNode(ISD::ADD, dl, NVT, HiOps, 2); + SDValue Cmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, LoOps[0], + ISD::SETULT); + SDValue Carry1 = DAG.getNode(ISD::SELECT, dl, NVT, Cmp1, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + SDValue Cmp2 = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, LoOps[1], + ISD::SETULT); + SDValue Carry2 = DAG.getNode(ISD::SELECT, dl, NVT, Cmp2, + DAG.getConstant(1, NVT), Carry1); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, Carry2); + } else { + Lo = DAG.getNode(ISD::SUB, dl, NVT, LoOps, 2); + Hi = DAG.getNode(ISD::SUB, dl, NVT, HiOps, 2); + SDValue Cmp = + DAG.getSetCC(dl, TLI.getSetCCResultType(LoOps[0].getValueType()), + LoOps[0], LoOps[1], ISD::SETULT); + SDValue Borrow = DAG.getNode(ISD::SELECT, dl, NVT, Cmp, + DAG.getConstant(1, NVT), + DAG.getConstant(0, NVT)); + Hi = DAG.getNode(ISD::SUB, dl, NVT, Hi, Borrow); + } +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Glue); + SDValue LoOps[2] = { LHSL, RHSL }; + SDValue HiOps[3] = { LHSH, RHSH }; + + if (N->getOpcode() == ISD::ADDC) { + Lo = DAG.getNode(ISD::ADDC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, dl, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, dl, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3); + } + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // Expand the subcomponents. + SDValue LHSL, LHSH, RHSL, RHSH; + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Glue); + SDValue LoOps[3] = { LHSL, RHSL, N->getOperand(2) }; + SDValue HiOps[3] = { LHSH, RHSH }; + + Lo = DAG.getNode(N->getOpcode(), dl, VTList, LoOps, 3); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(N->getOpcode(), dl, VTList, HiOps, 3); + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is any extension of the input (which degenerates to a copy). + Lo = DAG.getNode(ISD::ANY_EXTEND, dl, NVT, Op); + Hi = DAG.getUNDEF(NVT); // The high part is undefined. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + } +} + +void DAGTypeLegalizer::ExpandIntRes_AssertSext(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + EVT EVT = cast(N->getOperand(1))->getVT(); + unsigned NVTBits = NVT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + if (NVTBits < EVTBits) { + Hi = DAG.getNode(ISD::AssertSext, dl, NVT, Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), + EVTBits - NVTBits))); + } else { + Lo = DAG.getNode(ISD::AssertSext, dl, NVT, Lo, DAG.getValueType(EVT)); + // The high part replicates the sign bit of Lo, make it explicit. + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(NVTBits-1, TLI.getPointerTy())); + } +} + +void DAGTypeLegalizer::ExpandIntRes_AssertZext(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + EVT EVT = cast(N->getOperand(1))->getVT(); + unsigned NVTBits = NVT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + if (NVTBits < EVTBits) { + Hi = DAG.getNode(ISD::AssertZext, dl, NVT, Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), + EVTBits - NVTBits))); + } else { + Lo = DAG.getNode(ISD::AssertZext, dl, NVT, Lo, DAG.getValueType(EVT)); + // The high part must be zero, make it explicit. + Hi = DAG.getConstant(0, NVT); + } +} + +void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Hi, Lo); // Note swapped operands. + Lo = DAG.getNode(ISD::BSWAP, dl, Lo.getValueType(), Lo); + Hi = DAG.getNode(ISD::BSWAP, dl, Hi.getValueType(), Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned NBitWidth = NVT.getSizeInBits(); + const APInt &Cst = cast(N)->getAPIntValue(); + Lo = DAG.getConstant(Cst.trunc(NBitWidth), NVT); + Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTLZ(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + + SDValue HiNotZero = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Hi, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDValue LoLZ = DAG.getNode(ISD::CTLZ, dl, NVT, Lo); + SDValue HiLZ = DAG.getNode(ISD::CTLZ, dl, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, HiNotZero, HiLZ, + DAG.getNode(ISD::ADD, dl, NVT, LoLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTPOP(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + Lo = DAG.getNode(ISD::ADD, dl, NVT, DAG.getNode(ISD::CTPOP, dl, NVT, Lo), + DAG.getNode(ISD::CTPOP, dl, NVT, Hi)); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT NVT = Lo.getValueType(); + + SDValue LoNotZero = DAG.getSetCC(dl, TLI.getSetCCResultType(NVT), Lo, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDValue LoLZ = DAG.getNode(ISD::CTTZ, dl, NVT, Lo); + SDValue HiLZ = DAG.getNode(ISD::CTTZ, dl, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, dl, NVT, LoNotZero, LoLZ, + DAG.getNode(ISD::ADD, dl, NVT, HiLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPTOSINT(Op.getValueType(), VT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!"); + SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SDValue Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::getFPTOUINT(Op.getValueType(), VT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!"); + SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, + SDValue &Lo, SDValue &Hi) { + if (ISD::isNormalLoad(N)) { + ExpandRes_NormalLoad(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + ISD::LoadExtType ExtType = N->getExtensionType(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); + DebugLoc dl = N->getDebugLoc(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + if (N->getMemoryVT().bitsLE(NVT)) { + EVT MemVT = N->getMemoryVT(); + + Lo = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getPointerInfo(), + MemVT, isVolatile, isNonTemporal, Alignment); + + // Remember the chain. + Ch = Lo.getValue(1); + + if (ExtType == ISD::SEXTLOAD) { + // The high part is obtained by SRA'ing all but one of the bits of the + // lo part. + unsigned LoSize = Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); + } else if (ExtType == ISD::ZEXTLOAD) { + // The high part is just a zero. + Hi = DAG.getConstant(0, NVT); + } else { + assert(ExtType == ISD::EXTLOAD && "Unknown extload!"); + // The high part is undefined. + Hi = DAG.getUNDEF(NVT); + } + } else if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + Lo = DAG.getLoad(NVT, dl, Ch, Ptr, N->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + EVT NEVT = EVT::getIntegerVT(*DAG.getContext(), ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), NEVT, + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + } else { + // Big-endian - high bits are at low addresses. Favor aligned loads at + // the cost of some bit-fiddling. + EVT MemVT = N->getMemoryVT(); + unsigned EBytes = MemVT.getStoreSize(); + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + + // Load both the high bits and maybe some of the low bits. + Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getPointerInfo(), + EVT::getIntegerVT(*DAG.getContext(), + MemVT.getSizeInBits() - ExcessBits), + isVolatile, isNonTemporal, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Load the rest of the low bits. + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, NVT, Ch, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), + EVT::getIntegerVT(*DAG.getContext(), ExcessBits), + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer low bits from the bottom of Hi to the top of Lo. + Lo = DAG.getNode(ISD::OR, dl, NVT, Lo, + DAG.getNode(ISD::SHL, dl, NVT, Hi, + DAG.getConstant(ExcessBits, + TLI.getPointerTy()))); + // Move high bits to the right position in Hi. + Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, dl, + NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getPointerTy())); + } + } + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Ch); +} + +void DAGTypeLegalizer::ExpandIntRes_Logical(SDNode *N, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + SDValue LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + Lo = DAG.getNode(N->getOpcode(), dl, LL.getValueType(), LL, RL); + Hi = DAG.getNode(N->getOpcode(), dl, LL.getValueType(), LH, RH); +} + +void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + bool HasMULHS = TLI.isOperationLegalOrCustom(ISD::MULHS, NVT); + bool HasMULHU = TLI.isOperationLegalOrCustom(ISD::MULHU, NVT); + bool HasSMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::SMUL_LOHI, NVT); + bool HasUMUL_LOHI = TLI.isOperationLegalOrCustom(ISD::UMUL_LOHI, NVT); + if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) { + SDValue LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + unsigned OuterBitSize = VT.getSizeInBits(); + unsigned InnerBitSize = NVT.getSizeInBits(); + unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0)); + unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1)); + + APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize); + if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) && + DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) { + // The inputs are both zero-extended. + if (HasUMUL_LOHI) { + // We can emit a umul_lohi. + Lo = DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDValue(Lo.getNode(), 1); + return; + } + if (HasMULHU) { + // We can emit a mulhu+mul. + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL); + return; + } + } + if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) { + // The input values are both sign-extended. + if (HasSMUL_LOHI) { + // We can emit a smul_lohi. + Lo = DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDValue(Lo.getNode(), 1); + return; + } + if (HasMULHS) { + // We can emit a mulhs+mul. + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHS, dl, NVT, LL, RL); + return; + } + } + if (HasUMUL_LOHI) { + // Lo,Hi = umul LHS, RHS. + SDValue UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, dl, + DAG.getVTList(NVT, NVT), LL, RL); + Lo = UMulLOHI; + Hi = UMulLOHI.getValue(1); + RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH); + return; + } + if (HasMULHU) { + Lo = DAG.getNode(ISD::MUL, dl, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, dl, NVT, LL, RL); + RH = DAG.getNode(ISD::MUL, dl, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, dl, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, LH); + return; + } + } + + // If nothing else, we can make a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::MUL_I16; + else if (VT == MVT::i32) + LC = RTLIB::MUL_I32; + else if (VT == MVT::i64) + LC = RTLIB::MUL_I64; + else if (VT == MVT::i128) + LC = RTLIB::MUL_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*irrelevant*/, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_SADDSUBO(SDNode *Node, + SDValue &Lo, SDValue &Hi) { + SDValue LHS = Node->getOperand(0); + SDValue RHS = Node->getOperand(1); + DebugLoc dl = Node->getDebugLoc(); + + // Expand the result by simply replacing it with the equivalent + // non-overflow-checking operation. + SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + SplitInteger(Sum, Lo, Hi); + + // Compute the overflow. + // + // LHSSign -> LHS >= 0 + // RHSSign -> RHS >= 0 + // SumSign -> Sum >= 0 + // + // Add: + // Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign) + // Sub: + // Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign) + // + EVT OType = Node->getValueType(1); + SDValue Zero = DAG.getConstant(0, LHS.getValueType()); + + SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE); + SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE); + SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign, + Node->getOpcode() == ISD::SADDO ? + ISD::SETEQ : ISD::SETNE); + + SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE); + SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE); + + SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(Node, 1), Cmp); +} + +void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::SDIV_I16; + else if (VT == MVT::i32) + LC = RTLIB::SDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::SDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::SDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // If we can emit an efficient shift operation, do so now. Check to see if + // the RHS is a constant. + if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) + return ExpandShiftByConstant(N, CN->getZExtValue(), Lo, Hi); + + // If we can determine that the high bit of the shift is zero or one, even if + // the low bits are variable, emit this shift in an optimized form. + if (ExpandShiftWithKnownAmountBit(N, Lo, Hi)) + return; + + // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. + unsigned PartsOpc; + if (N->getOpcode() == ISD::SHL) { + PartsOpc = ISD::SHL_PARTS; + } else if (N->getOpcode() == ISD::SRL) { + PartsOpc = ISD::SRL_PARTS; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + PartsOpc = ISD::SRA_PARTS; + } + + // Next check to see if the target supports this SHL_PARTS operation or if it + // will custom expand it. + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT); + if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) || + Action == TargetLowering::Custom) { + // Expand the subcomponents. + SDValue LHSL, LHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + + SDValue Ops[] = { LHSL, LHSH, N->getOperand(1) }; + EVT VT = LHSL.getValueType(); + Lo = DAG.getNode(PartsOpc, dl, DAG.getVTList(VT, VT), Ops, 3); + Hi = Lo.getValue(1); + return; + } + + // Otherwise, emit a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + bool isSigned; + if (N->getOpcode() == ISD::SHL) { + isSigned = false; /*sign irrelevant*/ + if (VT == MVT::i16) + LC = RTLIB::SHL_I16; + else if (VT == MVT::i32) + LC = RTLIB::SHL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SHL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SHL_I128; + } else if (N->getOpcode() == ISD::SRL) { + isSigned = false; + if (VT == MVT::i16) + LC = RTLIB::SRL_I16; + else if (VT == MVT::i32) + LC = RTLIB::SRL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRL_I128; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + isSigned = true; + if (VT == MVT::i16) + LC = RTLIB::SRA_I16; + else if (VT == MVT::i32) + LC = RTLIB::SRA_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRA_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRA_I128; + } + + if (LC != RTLIB::UNKNOWN_LIBCALL && TLI.getLibcallName(LC)) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned, dl), Lo, Hi); + return; + } + + if (!ExpandShiftWithUnknownAmountBit(N, Lo, Hi)) + llvm_unreachable("Unsupported shift!"); +} + +void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is sign extension of the input (degenerates to a copy). + Lo = DAG.getNode(ISD::SIGN_EXTEND, dl, NVT, N->getOperand(0)); + // The high part is obtained by SRA'ing all but one of the bits of low part. + unsigned LoSize = NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getPointerTy())); + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Hi.getValueType(), Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), + ExcessBits))); + } +} + +void DAGTypeLegalizer:: +ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetExpandedInteger(N->getOperand(0), Lo, Hi); + EVT EVT = cast(N->getOperand(1))->getVT(); + + if (EVT.bitsLE(Lo.getValueType())) { + // sext_inreg the low part if needed. + Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Lo.getValueType(), Lo, + N->getOperand(1)); + + // The high part gets the sign extension from the lo-part. This handles + // things like sextinreg V:i64 from i8. + Hi = DAG.getNode(ISD::SRA, dl, Hi.getValueType(), Lo, + DAG.getConstant(Hi.getValueType().getSizeInBits()-1, + TLI.getPointerTy())); + } else { + // For example, extension of an i48 to an i64. Leave the low part alone, + // sext_inreg the high part. + unsigned ExcessBits = + EVT.getSizeInBits() - Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Hi.getValueType(), Hi, + DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), + ExcessBits))); + } +} + +void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::SREM_I16; + else if (VT == MVT::i32) + LC = RTLIB::SREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::SREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::SREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + Lo = DAG.getNode(ISD::TRUNCATE, dl, NVT, N->getOperand(0)); + Hi = DAG.getNode(ISD::SRL, dl, + N->getOperand(0).getValueType(), N->getOperand(0), + DAG.getConstant(NVT.getSizeInBits(), TLI.getPointerTy())); + Hi = DAG.getNode(ISD::TRUNCATE, dl, NVT, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UADDSUBO(SDNode *N, + SDValue &Lo, SDValue &Hi) { + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + // Expand the result by simply replacing it with the equivalent + // non-overflow-checking operation. + SDValue Sum = DAG.getNode(N->getOpcode() == ISD::UADDO ? + ISD::ADD : ISD::SUB, dl, LHS.getValueType(), + LHS, RHS); + SplitInteger(Sum, Lo, Hi); + + // Calculate the overflow: addition overflows iff a + b < a, and subtraction + // overflows iff a - b > a. + SDValue Ofl = DAG.getSetCC(dl, N->getValueType(1), Sum, LHS, + N->getOpcode () == ISD::UADDO ? + ISD::SETULT : ISD::SETUGT); + + // Use the calculated overflow everywhere. + ReplaceValueWith(SDValue(N, 1), Ofl); +} + +void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::UDIV_I16; + else if (VT == MVT::i32) + LC = RTLIB::UDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::UDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::UDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i16) + LC = RTLIB::UREM_I16; + else if (VT == MVT::i32) + LC = RTLIB::UREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::UREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::UREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!"); + + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false, dl), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N, + SDValue &Lo, SDValue &Hi) { + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is zero extension of the input (degenerates to a copy). + Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, N->getOperand(0)); + Hi = DAG.getConstant(0, NVT); // The high part is just a zero. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDValue Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getZeroExtendInReg(Hi, dl, + EVT::getIntegerVT(*DAG.getContext(), + ExcessBits)); + } +} + + +//===----------------------------------------------------------------------===// +// Integer Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need expansion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Expand integer operand: "; N->dump(&DAG); dbgs() << "\n"); + SDValue Res = SDValue(); + + if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false)) + return false; + + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + dbgs() << "ExpandIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); dbgs() << "\n"; + #endif + llvm_unreachable("Do not know how to expand this operator's operand!"); + + case ISD::BITCAST: Res = ExpandOp_BITCAST(N); break; + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break; + case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break; + case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; + case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break; + case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); break; + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; + case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: Res = ExpandIntOp_Shift(N); break; + case ISD::RETURNADDR: + case ISD::FRAMEADDR: Res = ExpandIntOp_RETURNADDR(N); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// IntegerExpandSetCCOperands - Expand the operands of a comparison. This code +/// is shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDValue &NewLHS, + SDValue &NewRHS, + ISD::CondCode &CCCode, + DebugLoc dl) { + SDValue LHSLo, LHSHi, RHSLo, RHSHi; + GetExpandedInteger(NewLHS, LHSLo, LHSHi); + GetExpandedInteger(NewRHS, RHSLo, RHSHi); + + if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) { + if (RHSLo == RHSHi) { + if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) { + if (RHSCST->isAllOnesValue()) { + // Equality comparison to -1. + NewLHS = DAG.getNode(ISD::AND, dl, + LHSLo.getValueType(), LHSLo, LHSHi); + NewRHS = RHSLo; + return; + } + } + } + + NewLHS = DAG.getNode(ISD::XOR, dl, LHSLo.getValueType(), LHSLo, RHSLo); + NewRHS = DAG.getNode(ISD::XOR, dl, LHSLo.getValueType(), LHSHi, RHSHi); + NewLHS = DAG.getNode(ISD::OR, dl, NewLHS.getValueType(), NewLHS, NewRHS); + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + return; + } + + // If this is a comparison of the sign bit, just look at the top part. + // X > -1, x < 0 + if (ConstantSDNode *CST = dyn_cast(NewRHS)) + if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0 + (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1 + NewLHS = LHSHi; + NewRHS = RHSHi; + return; + } + + // FIXME: This generated code sucks. + ISD::CondCode LowCC; + switch (CCCode) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETLT: + case ISD::SETULT: LowCC = ISD::SETULT; break; + case ISD::SETGT: + case ISD::SETUGT: LowCC = ISD::SETUGT; break; + case ISD::SETLE: + case ISD::SETULE: LowCC = ISD::SETULE; break; + case ISD::SETGE: + case ISD::SETUGE: LowCC = ISD::SETUGE; break; + } + + // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison + // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands + // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; + + // NOTE: on targets without efficient SELECT of bools, we can always use + // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) + TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, true, NULL); + SDValue Tmp1, Tmp2; + Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, LowCC, false, DagCombineInfo, dl); + if (!Tmp1.getNode()) + Tmp1 = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSLo.getValueType()), + LHSLo, RHSLo, LowCC); + Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, CCCode, false, DagCombineInfo, dl); + if (!Tmp2.getNode()) + Tmp2 = DAG.getNode(ISD::SETCC, dl, + TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, DAG.getCondCode(CCCode)); + + ConstantSDNode *Tmp1C = dyn_cast(Tmp1.getNode()); + ConstantSDNode *Tmp2C = dyn_cast(Tmp2.getNode()); + if ((Tmp1C && Tmp1C->isNullValue()) || + (Tmp2C && Tmp2C->isNullValue() && + (CCCode == ISD::SETLE || CCCode == ISD::SETGE || + CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) || + (Tmp2C && Tmp2C->getAPIntValue() == 1 && + (CCCode == ISD::SETLT || CCCode == ISD::SETGT || + CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) { + // low part is known false, returns high part. + // For LE / GE, if high part is known false, ignore the low part. + // For LT / GT, if high part is known true, ignore the low part. + NewLHS = Tmp2; + NewRHS = SDValue(); + return; + } + + NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETEQ, false, + DagCombineInfo, dl); + if (!NewLHS.getNode()) + NewLHS = DAG.getSetCC(dl, TLI.getSetCCResultType(LHSHi.getValueType()), + LHSHi, RHSHi, ISD::SETEQ); + NewLHS = DAG.getNode(ISD::SELECT, dl, Tmp1.getValueType(), + NewLHS, Tmp1, Tmp2); + NewRHS = SDValue(); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)), 0); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SELECT_CC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.getNode() == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)), 0); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) { + SDValue NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode, N->getDebugLoc()); + + // If ExpandSetCCOperands returned a scalar, use it. + if (NewRHS.getNode() == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } + + // Otherwise, update N to have the operands specified. + return SDValue(DAG.UpdateNodeOperands(N, NewLHS, NewRHS, + DAG.getCondCode(CCCode)), 0); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_Shift(SDNode *N) { + // The value being shifted is legal, but the shift amount is too big. + // It follows that either the result of the shift is undefined, or the + // upper half of the shift amount is zero. Just use the lower half. + SDValue Lo, Hi; + GetExpandedInteger(N->getOperand(1), Lo, Hi); + return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Lo), 0); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_RETURNADDR(SDNode *N) { + // The argument of RETURNADDR / FRAMEADDR builtin is 32 bit contant. This + // surely makes pretty nice problems on 8/16 bit targets. Just truncate this + // constant to valid type. + SDValue Lo, Hi; + GetExpandedInteger(N->getOperand(0), Lo, Hi); + return SDValue(DAG.UpdateNodeOperands(N, Lo), 0); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDNode *N) { + SDValue Op = N->getOperand(0); + EVT DstVT = N->getValueType(0); + RTLIB::Libcall LC = RTLIB::getSINTTOFP(Op.getValueType(), DstVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this SINT_TO_FP!"); + return MakeLibCall(LC, DstVT, &Op, 1, true, N->getDebugLoc()); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { + if (ISD::isNormalStore(N)) + return ExpandOp_NormalStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + + EVT VT = N->getOperand(1).getValueType(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); + DebugLoc dl = N->getDebugLoc(); + SDValue Lo, Hi; + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + if (N->getMemoryVT().bitsLE(NVT)) { + GetExpandedInteger(N->getValue(), Lo, Hi); + return DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getPointerInfo(), + N->getMemoryVT(), isVolatile, isNonTemporal, + Alignment); + } + + if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + GetExpandedInteger(N->getValue(), Lo, Hi); + + Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + EVT NEVT = EVT::getIntegerVT(*DAG.getContext(), ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), + NEVT, isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); + } + + // Big-endian - high bits are at low addresses. Favor aligned stores at + // the cost of some bit-fiddling. + GetExpandedInteger(N->getValue(), Lo, Hi); + + EVT ExtVT = N->getMemoryVT(); + unsigned EBytes = ExtVT.getStoreSize(); + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + EVT HiVT = EVT::getIntegerVT(*DAG.getContext(), + ExtVT.getSizeInBits() - ExcessBits); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer high bits from the top of Lo to the bottom of Hi. + Hi = DAG.getNode(ISD::SHL, dl, NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getPointerTy())); + Hi = DAG.getNode(ISD::OR, dl, NVT, Hi, + DAG.getNode(ISD::SRL, dl, NVT, Lo, + DAG.getConstant(ExcessBits, + TLI.getPointerTy()))); + } + + // Store both the high bits and maybe some of the low bits. + Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getPointerInfo(), + HiVT, isVolatile, isNonTemporal, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Store the lowest ExcessBits bits in the second half. + Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), + EVT::getIntegerVT(*DAG.getContext(), ExcessBits), + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); +} + +SDValue DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { + SDValue InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + // Just truncate the low part of the source. + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), N->getValueType(0), InL); +} + +static const fltSemantics *EVTToAPFloatSemantics(EVT VT) { + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP format"); + case MVT::f32: return &APFloat::IEEEsingle; + case MVT::f64: return &APFloat::IEEEdouble; + case MVT::f80: return &APFloat::x87DoubleExtended; + case MVT::f128: return &APFloat::IEEEquad; + case MVT::ppcf128: return &APFloat::PPCDoubleDouble; + } +} + +SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { + SDValue Op = N->getOperand(0); + EVT SrcVT = Op.getValueType(); + EVT DstVT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // The following optimization is valid only if every value in SrcVT (when + // treated as signed) is representable in DstVT. Check that the mantissa + // size of DstVT is >= than the number of bits in SrcVT -1. + const fltSemantics *sem = EVTToAPFloatSemantics(DstVT); + if (APFloat::semanticsPrecision(*sem) >= SrcVT.getSizeInBits()-1 && + TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){ + // Do a signed conversion then adjust the result. + SDValue SignedConv = DAG.getNode(ISD::SINT_TO_FP, dl, DstVT, Op); + SignedConv = TLI.LowerOperation(SignedConv, DAG); + + // The result of the signed conversion needs adjusting if the 'sign bit' of + // the incoming integer was set. To handle this, we dynamically test to see + // if it is set, and, if so, add a fudge factor. + + const uint64_t F32TwoE32 = 0x4F800000ULL; + const uint64_t F32TwoE64 = 0x5F800000ULL; + const uint64_t F32TwoE128 = 0x7F800000ULL; + + APInt FF(32, 0); + if (SrcVT == MVT::i32) + FF = APInt(32, F32TwoE32); + else if (SrcVT == MVT::i64) + FF = APInt(32, F32TwoE64); + else if (SrcVT == MVT::i128) + FF = APInt(32, F32TwoE128); + else + assert(false && "Unsupported UINT_TO_FP!"); + + // Check whether the sign bit is set. + SDValue Lo, Hi; + GetExpandedInteger(Op, Lo, Hi); + SDValue SignSet = DAG.getSetCC(dl, + TLI.getSetCCResultType(Hi.getValueType()), + Hi, DAG.getConstant(0, Hi.getValueType()), + ISD::SETLT); + + // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits. + SDValue FudgePtr = DAG.getConstantPool( + ConstantInt::get(*DAG.getContext(), FF.zext(64)), + TLI.getPointerTy()); + + // Get a pointer to FF if the sign bit was set, or to 0 otherwise. + SDValue Zero = DAG.getIntPtrConstant(0); + SDValue Four = DAG.getIntPtrConstant(4); + if (TLI.isBigEndian()) std::swap(Zero, Four); + SDValue Offset = DAG.getNode(ISD::SELECT, dl, Zero.getValueType(), SignSet, + Zero, Four); + unsigned Alignment = cast(FudgePtr)->getAlignment(); + FudgePtr = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), FudgePtr, Offset); + Alignment = std::min(Alignment, 4u); + + // Load the value out, extending it from f32 to the destination float type. + // FIXME: Avoid the extend by constructing the right constant pool? + SDValue Fudge = DAG.getExtLoad(ISD::EXTLOAD, dl, DstVT, DAG.getEntryNode(), + FudgePtr, + MachinePointerInfo::getConstantPool(), + MVT::f32, + false, false, Alignment); + return DAG.getNode(ISD::FADD, dl, DstVT, SignedConv, Fudge); + } + + // Otherwise, use a libcall. + RTLIB::Libcall LC = RTLIB::getUINTTOFP(SrcVT, DstVT); + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this UINT_TO_FP!"); + return MakeLibCall(LC, DstVT, &Op, 1, true, dl); +} diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp new file mode 100644 index 00000000000..cedda7e7075 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -0,0 +1,1153 @@ +//===-- LegalizeTypes.cpp - Common code for DAG type legalizer ------------===// +// +// 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 SelectionDAG::LegalizeTypes method. It transforms +// an arbitrary well-formed SelectionDAG to only consist of legal types. This +// is common code shared among the LegalizeTypes*.cpp files. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CallingConv.h" +#include "llvm/Target/TargetData.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt +EnableExpensiveChecks("enable-legalize-types-checking", cl::Hidden); + +/// PerformExpensiveChecks - Do extensive, expensive, sanity checking. +void DAGTypeLegalizer::PerformExpensiveChecks() { + // If a node is not processed, then none of its values should be mapped by any + // of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. + + // If a node is processed, then each value with an illegal type must be mapped + // by exactly one of PromotedIntegers, ExpandedIntegers, ..., ReplacedValues. + // Values with a legal type may be mapped by ReplacedValues, but not by any of + // the other maps. + + // Note that these invariants may not hold momentarily when processing a node: + // the node being processed may be put in a map before being marked Processed. + + // Note that it is possible to have nodes marked NewNode in the DAG. This can + // occur in two ways. Firstly, a node may be created during legalization but + // never passed to the legalization core. This is usually due to the implicit + // folding that occurs when using the DAG.getNode operators. Secondly, a new + // node may be passed to the legalization core, but when analyzed may morph + // into a different node, leaving the original node as a NewNode in the DAG. + // A node may morph if one of its operands changes during analysis. Whether + // it actually morphs or not depends on whether, after updating its operands, + // it is equivalent to an existing node: if so, it morphs into that existing + // node (CSE). An operand can change during analysis if the operand is a new + // node that morphs, or it is a processed value that was mapped to some other + // value (as recorded in ReplacedValues) in which case the operand is turned + // into that other value. If a node morphs then the node it morphed into will + // be used instead of it for legalization, however the original node continues + // to live on in the DAG. + // The conclusion is that though there may be nodes marked NewNode in the DAG, + // all uses of such nodes are also marked NewNode: the result is a fungus of + // NewNodes growing on top of the useful nodes, and perhaps using them, but + // not used by them. + + // If a value is mapped by ReplacedValues, then it must have no uses, except + // by nodes marked NewNode (see above). + + // The final node obtained by mapping by ReplacedValues is not marked NewNode. + // Note that ReplacedValues should be applied iteratively. + + // Note that the ReplacedValues map may also map deleted nodes (by iterating + // over the DAG we never dereference deleted nodes). This means that it may + // also map nodes marked NewNode if the deallocated memory was reallocated as + // another node, and that new node was not seen by the LegalizeTypes machinery + // (for example because it was created but not used). In general, we cannot + // distinguish between new nodes and deleted nodes. + SmallVector NewNodes; + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + // Remember nodes marked NewNode - they are subject to extra checking below. + if (I->getNodeId() == NewNode) + NewNodes.push_back(I); + + for (unsigned i = 0, e = I->getNumValues(); i != e; ++i) { + SDValue Res(I, i); + bool Failed = false; + + unsigned Mapped = 0; + if (ReplacedValues.find(Res) != ReplacedValues.end()) { + Mapped |= 1; + // Check that remapped values are only used by nodes marked NewNode. + for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end(); + UI != UE; ++UI) + if (UI.getUse().getResNo() == i) + assert(UI->getNodeId() == NewNode && + "Remapped value has non-trivial use!"); + + // Check that the final result of applying ReplacedValues is not + // marked NewNode. + SDValue NewVal = ReplacedValues[Res]; + DenseMap::iterator I = ReplacedValues.find(NewVal); + while (I != ReplacedValues.end()) { + NewVal = I->second; + I = ReplacedValues.find(NewVal); + } + assert(NewVal.getNode()->getNodeId() != NewNode && + "ReplacedValues maps to a new node!"); + } + if (PromotedIntegers.find(Res) != PromotedIntegers.end()) + Mapped |= 2; + if (SoftenedFloats.find(Res) != SoftenedFloats.end()) + Mapped |= 4; + if (ScalarizedVectors.find(Res) != ScalarizedVectors.end()) + Mapped |= 8; + if (ExpandedIntegers.find(Res) != ExpandedIntegers.end()) + Mapped |= 16; + if (ExpandedFloats.find(Res) != ExpandedFloats.end()) + Mapped |= 32; + if (SplitVectors.find(Res) != SplitVectors.end()) + Mapped |= 64; + if (WidenedVectors.find(Res) != WidenedVectors.end()) + Mapped |= 128; + + if (I->getNodeId() != Processed) { + // Since we allow ReplacedValues to map deleted nodes, it may map nodes + // marked NewNode too, since a deleted node may have been reallocated as + // another node that has not been seen by the LegalizeTypes machinery. + if ((I->getNodeId() == NewNode && Mapped > 1) || + (I->getNodeId() != NewNode && Mapped != 0)) { + dbgs() << "Unprocessed value in a map!"; + Failed = true; + } + } else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(I)) { + if (Mapped > 1) { + dbgs() << "Value with legal type was transformed!"; + Failed = true; + } + } else { + if (Mapped == 0) { + dbgs() << "Processed value not in any map!"; + Failed = true; + } else if (Mapped & (Mapped - 1)) { + dbgs() << "Value in multiple maps!"; + Failed = true; + } + } + + if (Failed) { + if (Mapped & 1) + dbgs() << " ReplacedValues"; + if (Mapped & 2) + dbgs() << " PromotedIntegers"; + if (Mapped & 4) + dbgs() << " SoftenedFloats"; + if (Mapped & 8) + dbgs() << " ScalarizedVectors"; + if (Mapped & 16) + dbgs() << " ExpandedIntegers"; + if (Mapped & 32) + dbgs() << " ExpandedFloats"; + if (Mapped & 64) + dbgs() << " SplitVectors"; + if (Mapped & 128) + dbgs() << " WidenedVectors"; + dbgs() << "\n"; + llvm_unreachable(0); + } + } + } + + // Checked that NewNodes are only used by other NewNodes. + for (unsigned i = 0, e = NewNodes.size(); i != e; ++i) { + SDNode *N = NewNodes[i]; + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) + assert(UI->getNodeId() == NewNode && "NewNode used by non-NewNode!"); + } +} + +/// run - This is the main entry point for the type legalizer. This does a +/// top-down traversal of the dag, legalizing types as it goes. Returns "true" +/// if it made any changes. +bool DAGTypeLegalizer::run() { + bool Changed = false; + + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + Dummy.setNodeId(Unanalyzed); + + // The root of the dag may dangle to deleted nodes until the type legalizer is + // done. Set it to null to avoid confusion. + DAG.setRoot(SDValue()); + + // Walk all nodes in the graph, assigning them a NodeId of 'ReadyToProcess' + // (and remembering them) if they are leaves and assigning 'Unanalyzed' if + // non-leaves. + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + if (I->getNumOperands() == 0) { + I->setNodeId(ReadyToProcess); + Worklist.push_back(I); + } else { + I->setNodeId(Unanalyzed); + } + } + + // Now that we have a set of nodes to process, handle them all. + while (!Worklist.empty()) { +#ifndef XDEBUG + if (EnableExpensiveChecks) +#endif + PerformExpensiveChecks(); + + SDNode *N = Worklist.back(); + Worklist.pop_back(); + assert(N->getNodeId() == ReadyToProcess && + "Node should be ready if on worklist!"); + + if (IgnoreNodeResults(N)) + goto ScanOperands; + + // Scan the values produced by the node, checking to see if any result + // types are illegal. + for (unsigned i = 0, NumResults = N->getNumValues(); i < NumResults; ++i) { + EVT ResultVT = N->getValueType(i); + switch (getTypeAction(ResultVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + break; + // The following calls must take care of *all* of the node's results, + // not just the illegal result they were passed (this includes results + // with a legal type). Results can be remapped using ReplaceValueWith, + // or their promoted/expanded/etc values registered in PromotedIntegers, + // ExpandedIntegers etc. + case PromoteInteger: + PromoteIntegerResult(N, i); + Changed = true; + goto NodeDone; + case ExpandInteger: + ExpandIntegerResult(N, i); + Changed = true; + goto NodeDone; + case SoftenFloat: + SoftenFloatResult(N, i); + Changed = true; + goto NodeDone; + case ExpandFloat: + ExpandFloatResult(N, i); + Changed = true; + goto NodeDone; + case ScalarizeVector: + ScalarizeVectorResult(N, i); + Changed = true; + goto NodeDone; + case SplitVector: + SplitVectorResult(N, i); + Changed = true; + goto NodeDone; + case WidenVector: + WidenVectorResult(N, i); + Changed = true; + goto NodeDone; + } + } + +ScanOperands: + // Scan the operand list for the node, handling any nodes with operands that + // are illegal. + { + unsigned NumOperands = N->getNumOperands(); + bool NeedsReanalyzing = false; + unsigned i; + for (i = 0; i != NumOperands; ++i) { + if (IgnoreNodeResults(N->getOperand(i).getNode())) + continue; + + EVT OpVT = N->getOperand(i).getValueType(); + switch (getTypeAction(OpVT)) { + default: + assert(false && "Unknown action!"); + case Legal: + continue; + // The following calls must either replace all of the node's results + // using ReplaceValueWith, and return "false"; or update the node's + // operands in place, and return "true". + case PromoteInteger: + NeedsReanalyzing = PromoteIntegerOperand(N, i); + Changed = true; + break; + case ExpandInteger: + NeedsReanalyzing = ExpandIntegerOperand(N, i); + Changed = true; + break; + case SoftenFloat: + NeedsReanalyzing = SoftenFloatOperand(N, i); + Changed = true; + break; + case ExpandFloat: + NeedsReanalyzing = ExpandFloatOperand(N, i); + Changed = true; + break; + case ScalarizeVector: + NeedsReanalyzing = ScalarizeVectorOperand(N, i); + Changed = true; + break; + case SplitVector: + NeedsReanalyzing = SplitVectorOperand(N, i); + Changed = true; + break; + case WidenVector: + NeedsReanalyzing = WidenVectorOperand(N, i); + Changed = true; + break; + } + break; + } + + // The sub-method updated N in place. Check to see if any operands are new, + // and if so, mark them. If the node needs revisiting, don't add all users + // to the worklist etc. + if (NeedsReanalyzing) { + assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?"); + N->setNodeId(NewNode); + // Recompute the NodeId and correct processed operands, adding the node to + // the worklist if ready. + SDNode *M = AnalyzeNewNode(N); + if (M == N) + // The node didn't morph - nothing special to do, it will be revisited. + continue; + + // The node morphed - this is equivalent to legalizing by replacing every + // value of N with the corresponding value of M. So do that now. + assert(N->getNumValues() == M->getNumValues() && + "Node morphing changed the number of results!"); + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + // Replacing the value takes care of remapping the new value. + ReplaceValueWith(SDValue(N, i), SDValue(M, i)); + assert(N->getNodeId() == NewNode && "Unexpected node state!"); + // The node continues to live on as part of the NewNode fungus that + // grows on top of the useful nodes. Nothing more needs to be done + // with it - move on to the next node. + continue; + } + + if (i == NumOperands) { + DEBUG(dbgs() << "Legally typed node: "; N->dump(&DAG); dbgs() << "\n"); + } + } +NodeDone: + + // If we reach here, the node was processed, potentially creating new nodes. + // Mark it as processed and add its users to the worklist as appropriate. + assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?"); + N->setNodeId(Processed); + + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); + UI != E; ++UI) { + SDNode *User = *UI; + int NodeId = User->getNodeId(); + + // This node has two options: it can either be a new node or its Node ID + // may be a count of the number of operands it has that are not ready. + if (NodeId > 0) { + User->setNodeId(NodeId-1); + + // If this was the last use it was waiting on, add it to the ready list. + if (NodeId-1 == ReadyToProcess) + Worklist.push_back(User); + continue; + } + + // If this is an unreachable new node, then ignore it. If it ever becomes + // reachable by being used by a newly created node then it will be handled + // by AnalyzeNewNode. + if (NodeId == NewNode) + continue; + + // Otherwise, this node is new: this is the first operand of it that + // became ready. Its new NodeId is the number of operands it has minus 1 + // (as this node is now processed). + assert(NodeId == Unanalyzed && "Unknown node ID!"); + User->setNodeId(User->getNumOperands() - 1); + + // If the node only has a single operand, it is now ready. + if (User->getNumOperands() == 1) + Worklist.push_back(User); + } + } + +#ifndef XDEBUG + if (EnableExpensiveChecks) +#endif + PerformExpensiveChecks(); + + // If the root changed (e.g. it was a dead load) update the root. + DAG.setRoot(Dummy.getValue()); + + // Remove dead nodes. This is important to do for cleanliness but also before + // the checking loop below. Implicit folding by the DAG.getNode operators and + // node morphing can cause unreachable nodes to be around with their flags set + // to new. + DAG.RemoveDeadNodes(); + + // In a debug build, scan all the nodes to make sure we found them all. This + // ensures that there are no cycles and that everything got processed. +#ifndef NDEBUG + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + bool Failed = false; + + // Check that all result types are legal. + if (!IgnoreNodeResults(I)) + for (unsigned i = 0, NumVals = I->getNumValues(); i < NumVals; ++i) + if (!isTypeLegal(I->getValueType(i))) { + dbgs() << "Result type " << i << " illegal!\n"; + Failed = true; + } + + // Check that all operand types are legal. + for (unsigned i = 0, NumOps = I->getNumOperands(); i < NumOps; ++i) + if (!IgnoreNodeResults(I->getOperand(i).getNode()) && + !isTypeLegal(I->getOperand(i).getValueType())) { + dbgs() << "Operand type " << i << " illegal!\n"; + Failed = true; + } + + if (I->getNodeId() != Processed) { + if (I->getNodeId() == NewNode) + dbgs() << "New node not analyzed?\n"; + else if (I->getNodeId() == Unanalyzed) + dbgs() << "Unanalyzed node not noticed?\n"; + else if (I->getNodeId() > 0) + dbgs() << "Operand not processed?\n"; + else if (I->getNodeId() == ReadyToProcess) + dbgs() << "Not added to worklist?\n"; + Failed = true; + } + + if (Failed) { + I->dump(&DAG); dbgs() << "\n"; + llvm_unreachable(0); + } + } +#endif + + return Changed; +} + +/// AnalyzeNewNode - The specified node is the root of a subtree of potentially +/// new nodes. Correct any processed operands (this may change the node) and +/// calculate the NodeId. If the node itself changes to a processed node, it +/// is not remapped - the caller needs to take care of this. +/// Returns the potentially changed node. +SDNode *DAGTypeLegalizer::AnalyzeNewNode(SDNode *N) { + // If this was an existing node that is already done, we're done. + if (N->getNodeId() != NewNode && N->getNodeId() != Unanalyzed) + return N; + + // Remove any stale map entries. + ExpungeNode(N); + + // Okay, we know that this node is new. Recursively walk all of its operands + // to see if they are new also. The depth of this walk is bounded by the size + // of the new tree that was constructed (usually 2-3 nodes), so we don't worry + // about revisiting of nodes. + // + // As we walk the operands, keep track of the number of nodes that are + // processed. If non-zero, this will become the new nodeid of this node. + // Operands may morph when they are analyzed. If so, the node will be + // updated after all operands have been analyzed. Since this is rare, + // the code tries to minimize overhead in the non-morphing case. + + SmallVector NewOps; + unsigned NumProcessed = 0; + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDValue OrigOp = N->getOperand(i); + SDValue Op = OrigOp; + + AnalyzeNewValue(Op); // Op may morph. + + if (Op.getNode()->getNodeId() == Processed) + ++NumProcessed; + + if (!NewOps.empty()) { + // Some previous operand changed. Add this one to the list. + NewOps.push_back(Op); + } else if (Op != OrigOp) { + // This is the first operand to change - add all operands so far. + NewOps.append(N->op_begin(), N->op_begin() + i); + NewOps.push_back(Op); + } + } + + // Some operands changed - update the node. + if (!NewOps.empty()) { + SDNode *M = DAG.UpdateNodeOperands(N, &NewOps[0], NewOps.size()); + if (M != N) { + // The node morphed into a different node. Normally for this to happen + // the original node would have to be marked NewNode. However this can + // in theory momentarily not be the case while ReplaceValueWith is doing + // its stuff. Mark the original node NewNode to help sanity checking. + N->setNodeId(NewNode); + if (M->getNodeId() != NewNode && M->getNodeId() != Unanalyzed) + // It morphed into a previously analyzed node - nothing more to do. + return M; + + // It morphed into a different new node. Do the equivalent of passing + // it to AnalyzeNewNode: expunge it and calculate the NodeId. No need + // to remap the operands, since they are the same as the operands we + // remapped above. + N = M; + ExpungeNode(N); + } + } + + // Calculate the NodeId. + N->setNodeId(N->getNumOperands() - NumProcessed); + if (N->getNodeId() == ReadyToProcess) + Worklist.push_back(N); + + return N; +} + +/// AnalyzeNewValue - Call AnalyzeNewNode, updating the node in Val if needed. +/// If the node changes to a processed node, then remap it. +void DAGTypeLegalizer::AnalyzeNewValue(SDValue &Val) { + Val.setNode(AnalyzeNewNode(Val.getNode())); + if (Val.getNode()->getNodeId() == Processed) + // We were passed a processed node, or it morphed into one - remap it. + RemapValue(Val); +} + +/// ExpungeNode - If N has a bogus mapping in ReplacedValues, eliminate it. +/// This can occur when a node is deleted then reallocated as a new node - +/// the mapping in ReplacedValues applies to the deleted node, not the new +/// one. +/// The only map that can have a deleted node as a source is ReplacedValues. +/// Other maps can have deleted nodes as targets, but since their looked-up +/// values are always immediately remapped using RemapValue, resulting in a +/// not-deleted node, this is harmless as long as ReplacedValues/RemapValue +/// always performs correct mappings. In order to keep the mapping correct, +/// ExpungeNode should be called on any new nodes *before* adding them as +/// either source or target to ReplacedValues (which typically means calling +/// Expunge when a new node is first seen, since it may no longer be marked +/// NewNode by the time it is added to ReplacedValues). +void DAGTypeLegalizer::ExpungeNode(SDNode *N) { + if (N->getNodeId() != NewNode) + return; + + // If N is not remapped by ReplacedValues then there is nothing to do. + unsigned i, e; + for (i = 0, e = N->getNumValues(); i != e; ++i) + if (ReplacedValues.find(SDValue(N, i)) != ReplacedValues.end()) + break; + + if (i == e) + return; + + // Remove N from all maps - this is expensive but rare. + + for (DenseMap::iterator I = PromotedIntegers.begin(), + E = PromotedIntegers.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = SoftenedFloats.begin(), + E = SoftenedFloats.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = ScalarizedVectors.begin(), + E = ScalarizedVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap::iterator I = WidenedVectors.begin(), + E = WidenedVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second); + } + + for (DenseMap >::iterator + I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){ + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap >::iterator + I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap >::iterator + I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) { + assert(I->first.getNode() != N); + RemapValue(I->second.first); + RemapValue(I->second.second); + } + + for (DenseMap::iterator I = ReplacedValues.begin(), + E = ReplacedValues.end(); I != E; ++I) + RemapValue(I->second); + + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) + ReplacedValues.erase(SDValue(N, i)); +} + +/// RemapValue - If the specified value was already legalized to another value, +/// replace it by that value. +void DAGTypeLegalizer::RemapValue(SDValue &N) { + DenseMap::iterator I = ReplacedValues.find(N); + if (I != ReplacedValues.end()) { + // Use path compression to speed up future lookups if values get multiply + // replaced with other values. + RemapValue(I->second); + N = I->second; + assert(N.getNode()->getNodeId() != NewNode && "Mapped to new node!"); + } +} + +namespace { + /// NodeUpdateListener - This class is a DAGUpdateListener that listens for + /// updates to nodes and recomputes their ready state. + class NodeUpdateListener : public SelectionDAG::DAGUpdateListener { + DAGTypeLegalizer &DTL; + SmallSetVector &NodesToAnalyze; + public: + explicit NodeUpdateListener(DAGTypeLegalizer &dtl, + SmallSetVector &nta) + : DTL(dtl), NodesToAnalyze(nta) {} + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + N->getNodeId() != DAGTypeLegalizer::Processed && + "Invalid node ID for RAUW deletion!"); + // It is possible, though rare, for the deleted node N to occur as a + // target in a map, so note the replacement N -> E in ReplacedValues. + assert(E && "Node not replaced?"); + DTL.NoteDeletion(N, E); + + // In theory the deleted node could also have been scheduled for analysis. + // So remove it from the set of nodes which will be analyzed. + NodesToAnalyze.remove(N); + + // In general nothing needs to be done for E, since it didn't change but + // only gained new uses. However N -> E was just added to ReplacedValues, + // and the result of a ReplacedValues mapping is not allowed to be marked + // NewNode. So if E is marked NewNode, then it needs to be analyzed. + if (E->getNodeId() == DAGTypeLegalizer::NewNode) + NodesToAnalyze.insert(E); + } + + virtual void NodeUpdated(SDNode *N) { + // Node updates can mean pretty much anything. It is possible that an + // operand was set to something already processed (f.e.) in which case + // this node could become ready. Recompute its flags. + assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess && + N->getNodeId() != DAGTypeLegalizer::Processed && + "Invalid node ID for RAUW deletion!"); + N->setNodeId(DAGTypeLegalizer::NewNode); + NodesToAnalyze.insert(N); + } + }; +} + + +/// ReplaceValueWith - The specified value was legalized to the specified other +/// value. Update the DAG and NodeIds replacing any uses of From to use To +/// instead. +void DAGTypeLegalizer::ReplaceValueWith(SDValue From, SDValue To) { + assert(From.getNode() != To.getNode() && "Potential legalization loop!"); + + // If expansion produced new nodes, make sure they are properly marked. + ExpungeNode(From.getNode()); + AnalyzeNewValue(To); // Expunges To. + + // Anything that used the old node should now use the new one. Note that this + // can potentially cause recursive merging. + SmallSetVector NodesToAnalyze; + NodeUpdateListener NUL(*this, NodesToAnalyze); + do { + DAG.ReplaceAllUsesOfValueWith(From, To, &NUL); + + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. + ReplacedValues[From] = To; + + // Process the list of nodes that need to be reanalyzed. + while (!NodesToAnalyze.empty()) { + SDNode *N = NodesToAnalyze.back(); + NodesToAnalyze.pop_back(); + if (N->getNodeId() != DAGTypeLegalizer::NewNode) + // The node was analyzed while reanalyzing an earlier node - it is safe + // to skip. Note that this is not a morphing node - otherwise it would + // still be marked NewNode. + continue; + + // Analyze the node's operands and recalculate the node ID. + SDNode *M = AnalyzeNewNode(N); + if (M != N) { + // The node morphed into a different node. Make everyone use the new + // node instead. + assert(M->getNodeId() != NewNode && "Analysis resulted in NewNode!"); + assert(N->getNumValues() == M->getNumValues() && + "Node morphing changed the number of results!"); + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + SDValue OldVal(N, i); + SDValue NewVal(M, i); + if (M->getNodeId() == Processed) + RemapValue(NewVal); + DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal, &NUL); + // OldVal may be a target of the ReplacedValues map which was marked + // NewNode to force reanalysis because it was updated. Ensure that + // anything that ReplacedValues mapped to OldVal will now be mapped + // all the way to NewVal. + ReplacedValues[OldVal] = NewVal; + } + // The original node continues to exist in the DAG, marked NewNode. + } + } + // When recursively update nodes with new nodes, it is possible to have + // new uses of From due to CSE. If this happens, replace the new uses of + // From with To. + } while (!From.use_empty()); +} + +void DAGTypeLegalizer::SetPromotedInteger(SDValue Op, SDValue Result) { + assert(Result.getValueType() == + TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for promoted integer"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = PromotedIntegers[Op]; + assert(OpEntry.getNode() == 0 && "Node is already promoted!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) { + assert(Result.getValueType() == + TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for softened float"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = SoftenedFloats[Op]; + assert(OpEntry.getNode() == 0 && "Node is already converted to integer!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::SetScalarizedVector(SDValue Op, SDValue Result) { + assert(Result.getValueType() == Op.getValueType().getVectorElementType() && + "Invalid type for scalarized vector"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = ScalarizedVectors[Op]; + assert(OpEntry.getNode() == 0 && "Node is already scalarized!"); + OpEntry = Result; +} + +void DAGTypeLegalizer::GetExpandedInteger(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = ExpandedIntegers[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedInteger(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType() == + TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for expanded integer"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedIntegers[Op]; + assert(Entry.first.getNode() == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetExpandedFloat(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = ExpandedFloats[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedFloat(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType() == + TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for expanded float"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedFloats[Op]; + assert(Entry.first.getNode() == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetSplitVector(SDValue Op, SDValue &Lo, + SDValue &Hi) { + std::pair &Entry = SplitVectors[Op]; + RemapValue(Entry.first); + RemapValue(Entry.second); + assert(Entry.first.getNode() && "Operand isn't split"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetSplitVector(SDValue Op, SDValue Lo, + SDValue Hi) { + assert(Lo.getValueType().getVectorElementType() == + Op.getValueType().getVectorElementType() && + 2*Lo.getValueType().getVectorNumElements() == + Op.getValueType().getVectorNumElements() && + Hi.getValueType() == Lo.getValueType() && + "Invalid type for split vector"); + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewValue(Lo); + AnalyzeNewValue(Hi); + + // Remember that this is the result of the node. + std::pair &Entry = SplitVectors[Op]; + assert(Entry.first.getNode() == 0 && "Node already split"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::SetWidenedVector(SDValue Op, SDValue Result) { + assert(Result.getValueType() == + TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && + "Invalid type for widened vector"); + AnalyzeNewValue(Result); + + SDValue &OpEntry = WidenedVectors[Op]; + assert(OpEntry.getNode() == 0 && "Node already widened!"); + OpEntry = Result; +} + + +//===----------------------------------------------------------------------===// +// Utilities. +//===----------------------------------------------------------------------===// + +/// BitConvertToInteger - Convert to an integer of the same size. +SDValue DAGTypeLegalizer::BitConvertToInteger(SDValue Op) { + unsigned BitWidth = Op.getValueType().getSizeInBits(); + return DAG.getNode(ISD::BITCAST, Op.getDebugLoc(), + EVT::getIntegerVT(*DAG.getContext(), BitWidth), Op); +} + +/// BitConvertVectorToIntegerVector - Convert to a vector of integers of the +/// same size. +SDValue DAGTypeLegalizer::BitConvertVectorToIntegerVector(SDValue Op) { + assert(Op.getValueType().isVector() && "Only applies to vectors!"); + unsigned EltWidth = Op.getValueType().getVectorElementType().getSizeInBits(); + EVT EltNVT = EVT::getIntegerVT(*DAG.getContext(), EltWidth); + unsigned NumElts = Op.getValueType().getVectorNumElements(); + return DAG.getNode(ISD::BITCAST, Op.getDebugLoc(), + EVT::getVectorVT(*DAG.getContext(), EltNVT, NumElts), Op); +} + +SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op, + EVT DestVT) { + DebugLoc dl = Op.getDebugLoc(); + // Create the stack frame object. Make sure it is aligned for both + // the source and destination types. + SDValue StackPtr = DAG.CreateStackTemporary(Op.getValueType(), DestVT); + // Emit a store to the stack slot. + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, + MachinePointerInfo(), false, false, 0); + // Result is a load from the stack slot. + return DAG.getLoad(DestVT, dl, Store, StackPtr, MachinePointerInfo(), + false, false, 0); +} + +/// CustomLowerNode - Replace the node's results with custom code provided +/// by the target and return "true", or do nothing and return "false". +/// The last parameter is FALSE if we are dealing with a node with legal +/// result types and illegal operand. The second parameter denotes the type of +/// illegal OperandNo in that case. +/// The last parameter being TRUE means we are dealing with a +/// node with illegal result types. The second parameter denotes the type of +/// illegal ResNo in that case. +bool DAGTypeLegalizer::CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult) { + // See if the target wants to custom lower this node. + if (TLI.getOperationAction(N->getOpcode(), VT) != TargetLowering::Custom) + return false; + + SmallVector Results; + if (LegalizeResult) + TLI.ReplaceNodeResults(N, Results, DAG); + else + TLI.LowerOperationWrapper(N, Results, DAG); + + if (Results.empty()) + // The target didn't want to custom lower it after all. + return false; + + // Make everything that once used N's values now use those in Results instead. + assert(Results.size() == N->getNumValues() && + "Custom lowering returned the wrong number of results!"); + for (unsigned i = 0, e = Results.size(); i != e; ++i) + ReplaceValueWith(SDValue(N, i), Results[i]); + return true; +} + + +/// CustomWidenLowerNode - Widen the node's results with custom code provided +/// by the target and return "true", or do nothing and return "false". +bool DAGTypeLegalizer::CustomWidenLowerNode(SDNode *N, EVT VT) { + // See if the target wants to custom lower this node. + if (TLI.getOperationAction(N->getOpcode(), VT) != TargetLowering::Custom) + return false; + + SmallVector Results; + TLI.ReplaceNodeResults(N, Results, DAG); + + if (Results.empty()) + // The target didn't want to custom widen lower its result after all. + return false; + + // Update the widening map. + assert(Results.size() == N->getNumValues() && + "Custom lowering returned the wrong number of results!"); + for (unsigned i = 0, e = Results.size(); i != e; ++i) + SetWidenedVector(SDValue(N, i), Results[i]); + return true; +} + +/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type +/// which is split into two not necessarily identical pieces. +void DAGTypeLegalizer::GetSplitDestVTs(EVT InVT, EVT &LoVT, EVT &HiVT) { + // Currently all types are split in half. + if (!InVT.isVector()) { + LoVT = HiVT = TLI.getTypeToTransformTo(*DAG.getContext(), InVT); + } else { + unsigned NumElements = InVT.getVectorNumElements(); + assert(!(NumElements & 1) && "Splitting vector, but not in half!"); + LoVT = HiVT = EVT::getVectorVT(*DAG.getContext(), + InVT.getVectorElementType(), NumElements/2); + } +} + +/// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and +/// high parts of the given value. +void DAGTypeLegalizer::GetPairElements(SDValue Pair, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = Pair.getDebugLoc(); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.getValueType()); + Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NVT, Pair, + DAG.getIntPtrConstant(1)); +} + +SDValue DAGTypeLegalizer::GetVectorElementPointer(SDValue VecPtr, EVT EltVT, + SDValue Index) { + DebugLoc dl = Index.getDebugLoc(); + // Make sure the index type is big enough to compute in. + if (Index.getValueType().bitsGT(TLI.getPointerTy())) + Index = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Index); + else + Index = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Index); + + // Calculate the element offset and add it to the pointer. + unsigned EltSize = EltVT.getSizeInBits() / 8; // FIXME: should be ABI size. + + Index = DAG.getNode(ISD::MUL, dl, Index.getValueType(), Index, + DAG.getConstant(EltSize, Index.getValueType())); + return DAG.getNode(ISD::ADD, dl, Index.getValueType(), Index, VecPtr); +} + +/// JoinIntegers - Build an integer with low bits Lo and high bits Hi. +SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) { + // Arbitrarily use dlHi for result DebugLoc + DebugLoc dlHi = Hi.getDebugLoc(); + DebugLoc dlLo = Lo.getDebugLoc(); + EVT LVT = Lo.getValueType(); + EVT HVT = Hi.getValueType(); + EVT NVT = EVT::getIntegerVT(*DAG.getContext(), + LVT.getSizeInBits() + HVT.getSizeInBits()); + + Lo = DAG.getNode(ISD::ZERO_EXTEND, dlLo, NVT, Lo); + Hi = DAG.getNode(ISD::ANY_EXTEND, dlHi, NVT, Hi); + Hi = DAG.getNode(ISD::SHL, dlHi, NVT, Hi, + DAG.getConstant(LVT.getSizeInBits(), TLI.getPointerTy())); + return DAG.getNode(ISD::OR, dlHi, NVT, Lo, Hi); +} + +/// LibCallify - Convert the node into a libcall with the same prototype. +SDValue DAGTypeLegalizer::LibCallify(RTLIB::Libcall LC, SDNode *N, + bool isSigned) { + unsigned NumOps = N->getNumOperands(); + DebugLoc dl = N->getDebugLoc(); + if (NumOps == 0) { + return MakeLibCall(LC, N->getValueType(0), 0, 0, isSigned, dl); + } else if (NumOps == 1) { + SDValue Op = N->getOperand(0); + return MakeLibCall(LC, N->getValueType(0), &Op, 1, isSigned, dl); + } else if (NumOps == 2) { + SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; + return MakeLibCall(LC, N->getValueType(0), Ops, 2, isSigned, dl); + } + SmallVector Ops(NumOps); + for (unsigned i = 0; i < NumOps; ++i) + Ops[i] = N->getOperand(i); + + return MakeLibCall(LC, N->getValueType(0), &Ops[0], NumOps, isSigned, dl); +} + +/// MakeLibCall - Generate a libcall taking the given operands as arguments and +/// returning a result of type RetVT. +SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, + bool isSigned, DebugLoc dl) { + TargetLowering::ArgListTy Args; + Args.reserve(NumOps); + + TargetLowering::ArgListEntry Entry; + for (unsigned i = 0; i != NumOps; ++i) { + Entry.Node = Ops[i]; + Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext()); + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, + false, 0, TLI.getLibcallCallingConv(LC), false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, dl); + return CallInfo.first; +} + +// ExpandChainLibCall - Expand a node into a call to a libcall. Similar to +// ExpandLibCall except that the first operand is the in-chain. +std::pair +DAGTypeLegalizer::ExpandChainLibCall(RTLIB::Libcall LC, + SDNode *Node, + bool isSigned) { + SDValue InChain = Node->getOperand(0); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i) { + EVT ArgVT = Node->getOperand(i).getValueType(); + const Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext()); + Entry.Node = Node->getOperand(i); + Entry.Ty = ArgTy; + Entry.isSExt = isSigned; + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } + SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC), + TLI.getPointerTy()); + + // Splice the libcall in wherever FindInputOutputChains tells us to. + const Type *RetTy = Node->getValueType(0).getTypeForEVT(*DAG.getContext()); + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, + 0, TLI.getLibcallCallingConv(LC), /*isTailCall=*/false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, Node->getDebugLoc()); + + return CallInfo; +} + +/// PromoteTargetBoolean - Promote the given target boolean to a target boolean +/// of the given type. A target boolean is an integer value, not necessarily of +/// type i1, the bits of which conform to getBooleanContents. +SDValue DAGTypeLegalizer::PromoteTargetBoolean(SDValue Bool, EVT VT) { + DebugLoc dl = Bool.getDebugLoc(); + ISD::NodeType ExtendCode; + switch (TLI.getBooleanContents()) { + default: + assert(false && "Unknown BooleanContent!"); + case TargetLowering::UndefinedBooleanContent: + // Extend to VT by adding rubbish bits. + ExtendCode = ISD::ANY_EXTEND; + break; + case TargetLowering::ZeroOrOneBooleanContent: + // Extend to VT by adding zero bits. + ExtendCode = ISD::ZERO_EXTEND; + break; + case TargetLowering::ZeroOrNegativeOneBooleanContent: { + // Extend to VT by copying the sign bit. + ExtendCode = ISD::SIGN_EXTEND; + break; + } + } + return DAG.getNode(ExtendCode, dl, VT, Bool); +} + +/// SplitInteger - Return the lower LoVT bits of Op in Lo and the upper HiVT +/// bits in Hi. +void DAGTypeLegalizer::SplitInteger(SDValue Op, + EVT LoVT, EVT HiVT, + SDValue &Lo, SDValue &Hi) { + DebugLoc dl = Op.getDebugLoc(); + assert(LoVT.getSizeInBits() + HiVT.getSizeInBits() == + Op.getValueType().getSizeInBits() && "Invalid integer splitting!"); + Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Op); + Hi = DAG.getNode(ISD::SRL, dl, Op.getValueType(), Op, + DAG.getConstant(LoVT.getSizeInBits(), TLI.getPointerTy())); + Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi); +} + +/// SplitInteger - Return the lower and upper halves of Op's bits in a value +/// type half the size of Op's. +void DAGTypeLegalizer::SplitInteger(SDValue Op, + SDValue &Lo, SDValue &Hi) { + EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), + Op.getValueType().getSizeInBits()/2); + SplitInteger(Op, HalfVT, HalfVT, Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Entry Point +//===----------------------------------------------------------------------===// + +/// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that +/// only uses types natively supported by the target. Returns "true" if it made +/// any changes. +/// +/// Note that this is an involved process that may invalidate pointers into +/// the graph. +bool SelectionDAG::LegalizeTypes() { + return DAGTypeLegalizer(*this).run(); +} diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/final/lib/CodeGen/SelectionDAG/LegalizeTypes.h new file mode 100644 index 00000000000..ed6c06d5558 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -0,0 +1,747 @@ +//===-- LegalizeTypes.h - Definition of the DAG Type Legalizer class ------===// +// +// 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 DAGTypeLegalizer class. This is a private interface +// shared between the code that implements the SelectionDAG::LegalizeTypes +// method. +// +//===----------------------------------------------------------------------===// + +#ifndef SELECTIONDAG_LEGALIZETYPES_H +#define SELECTIONDAG_LEGALIZETYPES_H + +#define DEBUG_TYPE "legalize-types" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DAGTypeLegalizer - This takes an arbitrary SelectionDAG as input and hacks +/// on it until only value types the target machine can handle are left. This +/// involves promoting small sizes to large sizes or splitting up large values +/// into small values. +/// +class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { + const TargetLowering &TLI; + SelectionDAG &DAG; +public: + // NodeIdFlags - This pass uses the NodeId on the SDNodes to hold information + // about the state of the node. The enum has all the values. + enum NodeIdFlags { + /// ReadyToProcess - All operands have been processed, so this node is ready + /// to be handled. + ReadyToProcess = 0, + + /// NewNode - This is a new node, not before seen, that was created in the + /// process of legalizing some other node. + NewNode = -1, + + /// Unanalyzed - This node's ID needs to be set to the number of its + /// unprocessed operands. + Unanalyzed = -2, + + /// Processed - This is a node that has already been processed. + Processed = -3 + + // 1+ - This is a node which has this many unprocessed operands. + }; +private: + enum LegalizeAction { + Legal, // The target natively supports this type. + PromoteInteger, // Replace this integer type with a larger one. + ExpandInteger, // Split this integer type into two of half the size. + SoftenFloat, // Convert this float type to a same size integer type. + ExpandFloat, // Split this float type into two of half the size. + ScalarizeVector, // Replace this one-element vector with its element type. + SplitVector, // Split this vector type into two of half the size. + WidenVector // This vector type should be widened into a larger vector. + }; + + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// simple value type, where the two bits correspond to the LegalizeAction + /// enum from TargetLowering. This can be queried with "getTypeAction(VT)". + TargetLowering::ValueTypeActionImpl ValueTypeActions; + + /// getTypeAction - Return how we should legalize values of this type. + LegalizeAction getTypeAction(EVT VT) const { + switch (ValueTypeActions.getTypeAction(VT)) { + default: + assert(false && "Unknown legalize action!"); + case TargetLowering::Legal: + return Legal; + case TargetLowering::Promote: + // Promote can mean + // 1) For integers, use a larger integer type (e.g. i8 -> i32). + // 2) For vectors, use a wider vector type (e.g. v3i32 -> v4i32). + if (!VT.isVector()) + return PromoteInteger; + return WidenVector; + case TargetLowering::Expand: + // Expand can mean + // 1) split scalar in half, 2) convert a float to an integer, + // 3) scalarize a single-element vector, 4) split a vector in two. + if (!VT.isVector()) { + if (VT.isInteger()) + return ExpandInteger; + if (VT.getSizeInBits() == + TLI.getTypeToTransformTo(*DAG.getContext(), VT).getSizeInBits()) + return SoftenFloat; + return ExpandFloat; + } + + if (VT.getVectorNumElements() == 1) + return ScalarizeVector; + return SplitVector; + } + } + + /// isTypeLegal - Return true if this type is legal on this target. + bool isTypeLegal(EVT VT) const { + return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal; + } + + /// IgnoreNodeResults - Pretend all of this node's results are legal. + bool IgnoreNodeResults(SDNode *N) const { + return N->getOpcode() == ISD::TargetConstant; + } + + /// PromotedIntegers - For integer nodes that are below legal width, this map + /// indicates what promoted value to use. + DenseMap PromotedIntegers; + + /// ExpandedIntegers - For integer nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedIntegers; + + /// SoftenedFloats - For floating point nodes converted to integers of + /// the same size, this map indicates the converted value to use. + DenseMap SoftenedFloats; + + /// ExpandedFloats - For float nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedFloats; + + /// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the + /// scalar value of type 'ty' to use. + DenseMap ScalarizedVectors; + + /// SplitVectors - For nodes that need to be split this map indicates + /// which operands are the expanded version of the input. + DenseMap > SplitVectors; + + /// WidenedVectors - For vector nodes that need to be widened, indicates + /// the widened value to use. + DenseMap WidenedVectors; + + /// ReplacedValues - For values that have been replaced with another, + /// indicates the replacement value to use. + DenseMap ReplacedValues; + + /// Worklist - This defines a worklist of nodes to process. In order to be + /// pushed onto this worklist, all operands of a node must have already been + /// processed. + SmallVector Worklist; + +public: + explicit DAGTypeLegalizer(SelectionDAG &dag) + : TLI(dag.getTargetLoweringInfo()), DAG(dag), + ValueTypeActions(TLI.getValueTypeActions()) { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); + } + + /// run - This is the main entry point for the type legalizer. This does a + /// top-down traversal of the dag, legalizing types as it goes. Returns + /// "true" if it made any changes. + bool run(); + + void NoteDeletion(SDNode *Old, SDNode *New) { + ExpungeNode(Old); + ExpungeNode(New); + for (unsigned i = 0, e = Old->getNumValues(); i != e; ++i) + ReplacedValues[SDValue(Old, i)] = SDValue(New, i); + } + +private: + SDNode *AnalyzeNewNode(SDNode *N); + void AnalyzeNewValue(SDValue &Val); + void ExpungeNode(SDNode *N); + void PerformExpensiveChecks(); + void RemapValue(SDValue &N); + + // Common routines. + SDValue BitConvertToInteger(SDValue Op); + SDValue BitConvertVectorToIntegerVector(SDValue Op); + SDValue CreateStackStoreLoad(SDValue Op, EVT DestVT); + bool CustomLowerNode(SDNode *N, EVT VT, bool LegalizeResult); + bool CustomWidenLowerNode(SDNode *N, EVT VT); + SDValue GetVectorElementPointer(SDValue VecPtr, EVT EltVT, SDValue Index); + SDValue JoinIntegers(SDValue Lo, SDValue Hi); + SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned); + SDValue MakeLibCall(RTLIB::Libcall LC, EVT RetVT, + const SDValue *Ops, unsigned NumOps, bool isSigned, + DebugLoc dl); + std::pair ExpandChainLibCall(RTLIB::Libcall LC, + SDNode *Node, bool isSigned); + std::pair ExpandAtomic(SDNode *Node); + + SDValue PromoteTargetBoolean(SDValue Bool, EVT VT); + void ReplaceValueWith(SDValue From, SDValue To); + void SplitInteger(SDValue Op, SDValue &Lo, SDValue &Hi); + void SplitInteger(SDValue Op, EVT LoVT, EVT HiVT, + SDValue &Lo, SDValue &Hi); + + //===--------------------------------------------------------------------===// + // Integer Promotion Support: LegalizeIntegerTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetPromotedInteger - Given a processed operand Op which was promoted to a + /// larger integer type, this returns the promoted value. The low bits of the + /// promoted value corresponding to the original type are exactly equal to Op. + /// The extra bits contain rubbish, so the promoted value may need to be zero- + /// or sign-extended from the original type before it is usable (the helpers + /// SExtPromotedInteger and ZExtPromotedInteger can do this for you). + /// For example, if Op is an i16 and was promoted to an i32, then this method + /// returns an i32, the lower 16 bits of which coincide with Op, and the upper + /// 16 bits of which contain rubbish. + SDValue GetPromotedInteger(SDValue Op) { + SDValue &PromotedOp = PromotedIntegers[Op]; + RemapValue(PromotedOp); + assert(PromotedOp.getNode() && "Operand wasn't promoted?"); + return PromotedOp; + } + void SetPromotedInteger(SDValue Op, SDValue Result); + + /// SExtPromotedInteger - Get a promoted operand and sign extend it to the + /// final size. + SDValue SExtPromotedInteger(SDValue Op) { + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + Op = GetPromotedInteger(Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, Op.getValueType(), Op, + DAG.getValueType(OldVT)); + } + + /// ZExtPromotedInteger - Get a promoted operand and zero extend it to the + /// final size. + SDValue ZExtPromotedInteger(SDValue Op) { + EVT OldVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + Op = GetPromotedInteger(Op); + return DAG.getZeroExtendInReg(Op, dl, OldVT); + } + + // Integer Result Promotion. + void PromoteIntegerResult(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_AssertSext(SDNode *N); + SDValue PromoteIntRes_AssertZext(SDNode *N); + SDValue PromoteIntRes_Atomic1(AtomicSDNode *N); + SDValue PromoteIntRes_Atomic2(AtomicSDNode *N); + SDValue PromoteIntRes_BITCAST(SDNode *N); + SDValue PromoteIntRes_BSWAP(SDNode *N); + SDValue PromoteIntRes_BUILD_PAIR(SDNode *N); + SDValue PromoteIntRes_Constant(SDNode *N); + SDValue PromoteIntRes_CONVERT_RNDSAT(SDNode *N); + SDValue PromoteIntRes_CTLZ(SDNode *N); + SDValue PromoteIntRes_CTPOP(SDNode *N); + SDValue PromoteIntRes_CTTZ(SDNode *N); + SDValue PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue PromoteIntRes_FP_TO_XINT(SDNode *N); + SDValue PromoteIntRes_FP32_TO_FP16(SDNode *N); + SDValue PromoteIntRes_INT_EXTEND(SDNode *N); + SDValue PromoteIntRes_LOAD(LoadSDNode *N); + SDValue PromoteIntRes_Overflow(SDNode *N); + SDValue PromoteIntRes_SADDSUBO(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_SDIV(SDNode *N); + SDValue PromoteIntRes_SELECT(SDNode *N); + SDValue PromoteIntRes_SELECT_CC(SDNode *N); + SDValue PromoteIntRes_SETCC(SDNode *N); + SDValue PromoteIntRes_SHL(SDNode *N); + SDValue PromoteIntRes_SimpleIntBinOp(SDNode *N); + SDValue PromoteIntRes_SIGN_EXTEND_INREG(SDNode *N); + SDValue PromoteIntRes_SRA(SDNode *N); + SDValue PromoteIntRes_SRL(SDNode *N); + SDValue PromoteIntRes_TRUNCATE(SDNode *N); + SDValue PromoteIntRes_UADDSUBO(SDNode *N, unsigned ResNo); + SDValue PromoteIntRes_UDIV(SDNode *N); + SDValue PromoteIntRes_UNDEF(SDNode *N); + SDValue PromoteIntRes_VAARG(SDNode *N); + SDValue PromoteIntRes_XMULO(SDNode *N, unsigned ResNo); + + // Integer Operand Promotion. + bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo); + SDValue PromoteIntOp_ANY_EXTEND(SDNode *N); + SDValue PromoteIntOp_BITCAST(SDNode *N); + SDValue PromoteIntOp_BUILD_PAIR(SDNode *N); + SDValue PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_BUILD_VECTOR(SDNode *N); + SDValue PromoteIntOp_CONVERT_RNDSAT(SDNode *N); + SDValue PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_MEMBARRIER(SDNode *N); + SDValue PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N); + SDValue PromoteIntOp_SELECT(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_SETCC(SDNode *N, unsigned OpNo); + SDValue PromoteIntOp_Shift(SDNode *N); + SDValue PromoteIntOp_SIGN_EXTEND(SDNode *N); + SDValue PromoteIntOp_SINT_TO_FP(SDNode *N); + SDValue PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDValue PromoteIntOp_TRUNCATE(SDNode *N); + SDValue PromoteIntOp_UINT_TO_FP(SDNode *N); + SDValue PromoteIntOp_ZERO_EXTEND(SDNode *N); + + void PromoteSetCCOperands(SDValue &LHS,SDValue &RHS, ISD::CondCode Code); + + //===--------------------------------------------------------------------===// + // Integer Expansion Support: LegalizeIntegerTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetExpandedInteger - Given a processed operand Op which was expanded into + /// two integers of half the size, this returns the two halves. The low bits + /// of Op are exactly equal to the bits of Lo; the high bits exactly equal Hi. + /// For example, if Op is an i64 which was expanded into two i32's, then this + /// method returns the two i32's, with Lo being equal to the lower 32 bits of + /// Op, and Hi being equal to the upper 32 bits. + void GetExpandedInteger(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetExpandedInteger(SDValue Op, SDValue Lo, SDValue Hi); + + // Integer Result Expansion. + void ExpandIntegerResult(SDNode *N, unsigned ResNo); + void ExpandIntRes_ANY_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_AssertSext (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_AssertZext (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_Constant (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTLZ (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTPOP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_CTTZ (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_LOAD (LoadSDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_TRUNCATE (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_FP_TO_SINT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_FP_TO_UINT (SDNode *N, SDValue &Lo, SDValue &Hi); + + void ExpandIntRes_Logical (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUB (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUBC (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_ADDSUBE (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_BSWAP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_MUL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_SREM (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_UDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_UREM (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_Shift (SDNode *N, SDValue &Lo, SDValue &Hi); + + void ExpandIntRes_SADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_UADDSUBO (SDNode *N, SDValue &Lo, SDValue &Hi); + + void ExpandShiftByConstant(SDNode *N, unsigned Amt, + SDValue &Lo, SDValue &Hi); + bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); + bool ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi); + + // Integer Operand Expansion. + bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo); + SDValue ExpandIntOp_BITCAST(SDNode *N); + SDValue ExpandIntOp_BR_CC(SDNode *N); + SDValue ExpandIntOp_BUILD_VECTOR(SDNode *N); + SDValue ExpandIntOp_EXTRACT_ELEMENT(SDNode *N); + SDValue ExpandIntOp_SELECT_CC(SDNode *N); + SDValue ExpandIntOp_SETCC(SDNode *N); + SDValue ExpandIntOp_Shift(SDNode *N); + SDValue ExpandIntOp_SINT_TO_FP(SDNode *N); + SDValue ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDValue ExpandIntOp_TRUNCATE(SDNode *N); + SDValue ExpandIntOp_UINT_TO_FP(SDNode *N); + SDValue ExpandIntOp_RETURNADDR(SDNode *N); + + void IntegerExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Float to Integer Conversion Support: LegalizeFloatTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetSoftenedFloat - Given a processed operand Op which was converted to an + /// integer of the same size, this returns the integer. The integer contains + /// exactly the same bits as Op - only the type changed. For example, if Op + /// is an f32 which was softened to an i32, then this method returns an i32, + /// the bits of which coincide with those of Op. + SDValue GetSoftenedFloat(SDValue Op) { + SDValue &SoftenedOp = SoftenedFloats[Op]; + RemapValue(SoftenedOp); + assert(SoftenedOp.getNode() && "Operand wasn't converted to integer?"); + return SoftenedOp; + } + void SetSoftenedFloat(SDValue Op, SDValue Result); + + // Result Float to Integer Conversion. + void SoftenFloatResult(SDNode *N, unsigned OpNo); + SDValue SoftenFloatRes_BITCAST(SDNode *N); + SDValue SoftenFloatRes_BUILD_PAIR(SDNode *N); + SDValue SoftenFloatRes_ConstantFP(ConstantFPSDNode *N); + SDValue SoftenFloatRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue SoftenFloatRes_FABS(SDNode *N); + SDValue SoftenFloatRes_FADD(SDNode *N); + SDValue SoftenFloatRes_FCEIL(SDNode *N); + SDValue SoftenFloatRes_FCOPYSIGN(SDNode *N); + SDValue SoftenFloatRes_FCOS(SDNode *N); + SDValue SoftenFloatRes_FDIV(SDNode *N); + SDValue SoftenFloatRes_FEXP(SDNode *N); + SDValue SoftenFloatRes_FEXP2(SDNode *N); + SDValue SoftenFloatRes_FFLOOR(SDNode *N); + SDValue SoftenFloatRes_FLOG(SDNode *N); + SDValue SoftenFloatRes_FLOG2(SDNode *N); + SDValue SoftenFloatRes_FLOG10(SDNode *N); + SDValue SoftenFloatRes_FMUL(SDNode *N); + SDValue SoftenFloatRes_FNEARBYINT(SDNode *N); + SDValue SoftenFloatRes_FNEG(SDNode *N); + SDValue SoftenFloatRes_FP_EXTEND(SDNode *N); + SDValue SoftenFloatRes_FP16_TO_FP32(SDNode *N); + SDValue SoftenFloatRes_FP_ROUND(SDNode *N); + SDValue SoftenFloatRes_FPOW(SDNode *N); + SDValue SoftenFloatRes_FPOWI(SDNode *N); + SDValue SoftenFloatRes_FREM(SDNode *N); + SDValue SoftenFloatRes_FRINT(SDNode *N); + SDValue SoftenFloatRes_FSIN(SDNode *N); + SDValue SoftenFloatRes_FSQRT(SDNode *N); + SDValue SoftenFloatRes_FSUB(SDNode *N); + SDValue SoftenFloatRes_FTRUNC(SDNode *N); + SDValue SoftenFloatRes_LOAD(SDNode *N); + SDValue SoftenFloatRes_SELECT(SDNode *N); + SDValue SoftenFloatRes_SELECT_CC(SDNode *N); + SDValue SoftenFloatRes_UNDEF(SDNode *N); + SDValue SoftenFloatRes_VAARG(SDNode *N); + SDValue SoftenFloatRes_XINT_TO_FP(SDNode *N); + + // Operand Float to Integer Conversion. + bool SoftenFloatOperand(SDNode *N, unsigned OpNo); + SDValue SoftenFloatOp_BITCAST(SDNode *N); + SDValue SoftenFloatOp_BR_CC(SDNode *N); + SDValue SoftenFloatOp_FP_ROUND(SDNode *N); + SDValue SoftenFloatOp_FP_TO_SINT(SDNode *N); + SDValue SoftenFloatOp_FP_TO_UINT(SDNode *N); + SDValue SoftenFloatOp_FP32_TO_FP16(SDNode *N); + SDValue SoftenFloatOp_SELECT_CC(SDNode *N); + SDValue SoftenFloatOp_SETCC(SDNode *N); + SDValue SoftenFloatOp_STORE(SDNode *N, unsigned OpNo); + + void SoftenSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Float Expansion Support: LegalizeFloatTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetExpandedFloat - Given a processed operand Op which was expanded into + /// two floating point values of half the size, this returns the two halves. + /// The low bits of Op are exactly equal to the bits of Lo; the high bits + /// exactly equal Hi. For example, if Op is a ppcf128 which was expanded + /// into two f64's, then this method returns the two f64's, with Lo being + /// equal to the lower 64 bits of Op, and Hi to the upper 64 bits. + void GetExpandedFloat(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetExpandedFloat(SDValue Op, SDValue Lo, SDValue Hi); + + // Float Result Expansion. + void ExpandFloatResult(SDNode *N, unsigned ResNo); + void ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FABS (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FADD (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FCEIL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FCOPYSIGN (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FCOS (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FDIV (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FEXP (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FEXP2 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FFLOOR (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG2 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FLOG10 (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FMUL (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FNEARBYINT(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FNEG (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FP_EXTEND (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FPOW (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FPOWI (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FRINT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSIN (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSQRT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FSUB (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_FTRUNC (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_LOAD (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_XINT_TO_FP(SDNode *N, SDValue &Lo, SDValue &Hi); + + // Float Operand Expansion. + bool ExpandFloatOperand(SDNode *N, unsigned OperandNo); + SDValue ExpandFloatOp_BR_CC(SDNode *N); + SDValue ExpandFloatOp_FP_ROUND(SDNode *N); + SDValue ExpandFloatOp_FP_TO_SINT(SDNode *N); + SDValue ExpandFloatOp_FP_TO_UINT(SDNode *N); + SDValue ExpandFloatOp_SELECT_CC(SDNode *N); + SDValue ExpandFloatOp_SETCC(SDNode *N); + SDValue ExpandFloatOp_STORE(SDNode *N, unsigned OpNo); + + void FloatExpandSetCCOperands(SDValue &NewLHS, SDValue &NewRHS, + ISD::CondCode &CCCode, DebugLoc dl); + + //===--------------------------------------------------------------------===// + // Scalarization Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetScalarizedVector - Given a processed one-element vector Op which was + /// scalarized to its element type, this returns the element. For example, + /// if Op is a v1i32, Op = < i32 val >, this method returns val, an i32. + SDValue GetScalarizedVector(SDValue Op) { + SDValue &ScalarizedOp = ScalarizedVectors[Op]; + RemapValue(ScalarizedOp); + assert(ScalarizedOp.getNode() && "Operand wasn't scalarized?"); + return ScalarizedOp; + } + void SetScalarizedVector(SDValue Op, SDValue Result); + + // Vector Result Scalarization: <1 x ty> -> ty. + void ScalarizeVectorResult(SDNode *N, unsigned OpNo); + SDValue ScalarizeVecRes_BinOp(SDNode *N); + SDValue ScalarizeVecRes_UnaryOp(SDNode *N); + SDValue ScalarizeVecRes_InregOp(SDNode *N); + + SDValue ScalarizeVecRes_BITCAST(SDNode *N); + SDValue ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N); + SDValue ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N); + SDValue ScalarizeVecRes_FPOWI(SDNode *N); + SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); + SDValue ScalarizeVecRes_LOAD(LoadSDNode *N); + SDValue ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N); + SDValue ScalarizeVecRes_SIGN_EXTEND_INREG(SDNode *N); + SDValue ScalarizeVecRes_SELECT(SDNode *N); + SDValue ScalarizeVecRes_SELECT_CC(SDNode *N); + SDValue ScalarizeVecRes_SETCC(SDNode *N); + SDValue ScalarizeVecRes_UNDEF(SDNode *N); + SDValue ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N); + SDValue ScalarizeVecRes_VSETCC(SDNode *N); + + // Vector Operand Scalarization: <1 x ty> -> ty. + bool ScalarizeVectorOperand(SDNode *N, unsigned OpNo); + SDValue ScalarizeVecOp_BITCAST(SDNode *N); + SDValue ScalarizeVecOp_CONCAT_VECTORS(SDNode *N); + SDValue ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo); + + //===--------------------------------------------------------------------===// + // Vector Splitting Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetSplitVector - Given a processed vector Op which was split into vectors + /// of half the size, this method returns the halves. The first elements of + /// Op coincide with the elements of Lo; the remaining elements of Op coincide + /// with the elements of Hi: Op is what you would get by concatenating Lo and + /// Hi. For example, if Op is a v8i32 that was split into two v4i32's, then + /// this method returns the two v4i32's, with Lo corresponding to the first 4 + /// elements of Op, and Hi to the last 4 elements. + void GetSplitVector(SDValue Op, SDValue &Lo, SDValue &Hi); + void SetSplitVector(SDValue Op, SDValue Lo, SDValue Hi); + + // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>. + void SplitVectorResult(SDNode *N, unsigned OpNo); + void SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_InregOp(SDNode *N, SDValue &Lo, SDValue &Hi); + + void SplitVecRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_BUILD_PAIR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo, + SDValue &Hi); + + // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. + bool SplitVectorOperand(SDNode *N, unsigned OpNo); + SDValue SplitVecOp_UnaryOp(SDNode *N); + + SDValue SplitVecOp_BITCAST(SDNode *N); + SDValue SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N); + SDValue SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo); + SDValue SplitVecOp_CONCAT_VECTORS(SDNode *N); + SDValue SplitVecOp_FP_ROUND(SDNode *N); + + //===--------------------------------------------------------------------===// + // Vector Widening Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// GetWidenedVector - Given a processed vector Op which was widened into a + /// larger vector, this method returns the larger vector. The elements of + /// the returned vector consist of the elements of Op followed by elements + /// containing rubbish. For example, if Op is a v2i32 that was widened to a + /// v4i32, then this method returns a v4i32 for which the first two elements + /// are the same as those of Op, while the last two elements contain rubbish. + SDValue GetWidenedVector(SDValue Op) { + SDValue &WidenedOp = WidenedVectors[Op]; + RemapValue(WidenedOp); + assert(WidenedOp.getNode() && "Operand wasn't widened?"); + return WidenedOp; + } + void SetWidenedVector(SDValue Op, SDValue Result); + + // Widen Vector Result Promotion. + void WidenVectorResult(SDNode *N, unsigned ResNo); + SDValue WidenVecRes_BITCAST(SDNode* N); + SDValue WidenVecRes_BUILD_VECTOR(SDNode* N); + SDValue WidenVecRes_CONCAT_VECTORS(SDNode* N); + SDValue WidenVecRes_CONVERT_RNDSAT(SDNode* N); + SDValue WidenVecRes_EXTRACT_SUBVECTOR(SDNode* N); + SDValue WidenVecRes_INSERT_VECTOR_ELT(SDNode* N); + SDValue WidenVecRes_LOAD(SDNode* N); + SDValue WidenVecRes_SCALAR_TO_VECTOR(SDNode* N); + SDValue WidenVecRes_SIGN_EXTEND_INREG(SDNode* N); + SDValue WidenVecRes_SELECT(SDNode* N); + SDValue WidenVecRes_SELECT_CC(SDNode* N); + SDValue WidenVecRes_SETCC(SDNode* N); + SDValue WidenVecRes_UNDEF(SDNode *N); + SDValue WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N); + SDValue WidenVecRes_VSETCC(SDNode* N); + + SDValue WidenVecRes_Binary(SDNode *N); + SDValue WidenVecRes_Convert(SDNode *N); + SDValue WidenVecRes_POWI(SDNode *N); + SDValue WidenVecRes_Shift(SDNode *N); + SDValue WidenVecRes_Unary(SDNode *N); + SDValue WidenVecRes_InregOp(SDNode *N); + + // Widen Vector Operand. + bool WidenVectorOperand(SDNode *N, unsigned ResNo); + SDValue WidenVecOp_BITCAST(SDNode *N); + SDValue WidenVecOp_CONCAT_VECTORS(SDNode *N); + SDValue WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDValue WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N); + SDValue WidenVecOp_STORE(SDNode* N); + + SDValue WidenVecOp_Convert(SDNode *N); + + //===--------------------------------------------------------------------===// + // Vector Widening Utilities Support: LegalizeVectorTypes.cpp + //===--------------------------------------------------------------------===// + + /// Helper GenWidenVectorLoads - Helper function to generate a set of + /// loads to load a vector with a resulting wider type. It takes + /// LdChain: list of chains for the load to be generated. + /// Ld: load to widen + SDValue GenWidenVectorLoads(SmallVector& LdChain, + LoadSDNode *LD); + + /// GenWidenVectorExtLoads - Helper function to generate a set of extension + /// loads to load a ector with a resulting wider type. It takes + /// LdChain: list of chains for the load to be generated. + /// Ld: load to widen + /// ExtType: extension element type + SDValue GenWidenVectorExtLoads(SmallVector& LdChain, + LoadSDNode *LD, ISD::LoadExtType ExtType); + + /// Helper genWidenVectorStores - Helper function to generate a set of + /// stores to store a widen vector into non widen memory + /// StChain: list of chains for the stores we have generated + /// ST: store of a widen value + void GenWidenVectorStores(SmallVector& StChain, StoreSDNode *ST); + + /// Helper genWidenVectorTruncStores - Helper function to generate a set of + /// stores to store a truncate widen vector into non widen memory + /// StChain: list of chains for the stores we have generated + /// ST: store of a widen value + void GenWidenVectorTruncStores(SmallVector& StChain, + StoreSDNode *ST); + + /// Modifies a vector input (widen or narrows) to a vector of NVT. The + /// input vector must have the same element type as NVT. + SDValue ModifyToType(SDValue InOp, EVT WidenVT); + + + //===--------------------------------------------------------------------===// + // Generic Splitting: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // not necessarily identical types. As such they can be used for splitting + // vectors and expanding integers and floats. + + void GetSplitOp(SDValue Op, SDValue &Lo, SDValue &Hi) { + if (Op.getValueType().isVector()) + GetSplitVector(Op, Lo, Hi); + else if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + void GetSplitDestVTs(EVT InVT, EVT &LoVT, EVT &HiVT); + + /// GetPairElements - Use ISD::EXTRACT_ELEMENT nodes to extract the low and + /// high parts of the given value. + void GetPairElements(SDValue Pair, SDValue &Lo, SDValue &Hi); + + // Generic Result Splitting. + void SplitRes_MERGE_VALUES(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_SELECT (SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_SELECT_CC (SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitRes_UNDEF (SDNode *N, SDValue &Lo, SDValue &Hi); + + //===--------------------------------------------------------------------===// + // Generic Expansion: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // identical types of half the size, and that the Lo/Hi part is stored first + // in memory on little/big-endian machines, followed by the Hi/Lo part. As + // such they can be used for expanding integers and floats. + + void GetExpandedOp(SDValue Op, SDValue &Lo, SDValue &Hi) { + if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + // Generic Result Expansion. + void ExpandRes_BITCAST (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_BUILD_PAIR (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_EXTRACT_ELEMENT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_NormalLoad (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandRes_VAARG (SDNode *N, SDValue &Lo, SDValue &Hi); + + // Generic Operand Expansion. + SDValue ExpandOp_BITCAST (SDNode *N); + SDValue ExpandOp_BUILD_VECTOR (SDNode *N); + SDValue ExpandOp_EXTRACT_ELEMENT (SDNode *N); + SDValue ExpandOp_INSERT_VECTOR_ELT(SDNode *N); + SDValue ExpandOp_SCALAR_TO_VECTOR (SDNode *N); + SDValue ExpandOp_NormalStore (SDNode *N, unsigned OpNo); +}; + +} // end namespace llvm. + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp new file mode 100644 index 00000000000..a75ae87f3cb --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -0,0 +1,480 @@ +//===-------- LegalizeTypesGeneric.cpp - Generic type legalization --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements generic type expansion and splitting for LegalizeTypes. +// The routines here perform legalization when the details of the type (such as +// whether it is an integer or a float) do not matter. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in two identical registers of a smaller type. The Lo/Hi part +// is required to be stored first in memory on little/big-endian machines. +// Splitting is the act of changing a computation in an illegal type to be a +// computation in two not necessarily identical registers of a smaller type. +// There are no requirements on how the type is represented in memory. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/Target/TargetData.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic Result Expansion. +//===----------------------------------------------------------------------===// + +// These routines assume that the Lo/Hi part is stored first in memory on +// little/big-endian machines, followed by the Hi/Lo part. This means that +// they cannot be used as is on vectors, for which Lo is always stored first. + +void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT OutVT = N->getValueType(0); + EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT); + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + break; + case SoftenFloat: + // Convert the integer operand instead. + SplitInteger(GetSoftenedFloat(InOp), Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi); + return; + case ExpandInteger: + case ExpandFloat: + // Convert the expanded pieces of the input. + GetExpandedOp(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi); + return; + case SplitVector: + GetSplitVector(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi); + return; + case ScalarizeVector: + // Convert the element instead. + SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi); + return; + case WidenVector: { + assert(!(InVT.getVectorNumElements() & 1) && "Unsupported BITCAST"); + InOp = GetWidenedVector(InOp); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + InVT.getVectorNumElements()/2); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi); + return; + } + } + + if (InVT.isVector() && OutVT.isInteger()) { + // Handle cases like i64 = BITCAST v1i64 on x86, where the operand + // is legal but the result is not. + EVT NVT = EVT::getVectorVT(*DAG.getContext(), NOutVT, 2); + + if (isTypeLegal(NVT)) { + SDValue CastInOp = DAG.getNode(ISD::BITCAST, dl, NVT, InOp); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp, + DAG.getIntPtrConstant(1)); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + return; + } + } + + // Lower the bit-convert to a store/load from the stack. + assert(NOutVT.isByteSized() && "Expanded type not byte sized!"); + + // Create the stack frame object. Make sure it is aligned for both + // the source and expanded destination types. + unsigned Alignment = + TLI.getTargetData()->getPrefTypeAlignment(NOutVT. + getTypeForEVT(*DAG.getContext())); + SDValue StackPtr = DAG.CreateStackTemporary(InVT, Alignment); + int SPFI = cast(StackPtr.getNode())->getIndex(); + MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(SPFI); + + // Emit a store to the stack slot. + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, PtrInfo, + false, false, 0); + + // Load the first half from the stack slot. + Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, PtrInfo, false, false, 0); + + // Increment the pointer to the other half. + unsigned IncrementSize = NOutVT.getSizeInBits() / 8; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + DAG.getIntPtrConstant(IncrementSize)); + + // Load the second half from the stack slot. + Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr, + PtrInfo.getWithOffset(IncrementSize), false, + false, MinAlign(Alignment, IncrementSize)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_BUILD_PAIR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // Return the operands. + Lo = N->getOperand(0); + Hi = N->getOperand(1); +} + +void DAGTypeLegalizer::ExpandRes_EXTRACT_ELEMENT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + GetExpandedOp(N->getOperand(0), Lo, Hi); + SDValue Part = cast(N->getOperand(1))->getZExtValue() ? + Hi : Lo; + + assert(Part.getValueType() == N->getValueType(0) && + "Type twice as big as expanded type not itself expanded!"); + + GetPairElements(Part, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + DebugLoc dl = N->getDebugLoc(); + + // Convert to a vector of the expanded element type, for example + // <3 x i64> -> <6 x i32>. + EVT OldVT = N->getValueType(0); + EVT NewVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldVT); + + SDValue NewVec = DAG.getNode(ISD::BITCAST, dl, + EVT::getVectorVT(*DAG.getContext(), + NewVT, 2*OldElts), + OldVec); + + // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. + SDValue Idx = N->getOperand(1); + + // Make sure the type of Idx is big enough to hold the new values. + if (Idx.getValueType().bitsLT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Idx); + + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, Idx); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, Idx); + + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, + DAG.getConstant(1, Idx.getValueType())); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, Idx); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(ISD::isNormalLoad(N) && "This routine only for normal loads!"); + DebugLoc dl = N->getDebugLoc(); + + LoadSDNode *LD = cast(N); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), LD->getValueType(0)); + SDValue Chain = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + Lo = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits() / 8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getLoad(NVT, dl, Chain, Ptr, + LD->getPointerInfo().getWithOffset(IncrementSize), + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), Chain); +} + +void DAGTypeLegalizer::ExpandRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT OVT = N->getValueType(0); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT); + SDValue Chain = N->getOperand(0); + SDValue Ptr = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + const unsigned Align = N->getConstantOperandVal(3); + + Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, N->getOperand(2), Align); + Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, N->getOperand(2), 0); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), Hi.getValue(1)); +} + + +//===--------------------------------------------------------------------===// +// Generic Operand Expansion. +//===--------------------------------------------------------------------===// + +SDValue DAGTypeLegalizer::ExpandOp_BITCAST(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + if (N->getValueType(0).isVector()) { + // An illegal expanding type is being converted to a legal vector type. + // Make a two element vector out of the expanded parts and convert that + // instead, but only if the new vector type is legal (otherwise there + // is no point, and it might create expansion loops). For example, on + // x86 this turns v1i64 = BITCAST i64 into v1i64 = BITCAST v2i32. + EVT OVT = N->getOperand(0).getValueType(); + EVT NVT = EVT::getVectorVT(*DAG.getContext(), + TLI.getTypeToTransformTo(*DAG.getContext(), OVT), + 2); + + if (isTypeLegal(NVT)) { + SDValue Parts[2]; + GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]); + + if (TLI.isBigEndian()) + std::swap(Parts[0], Parts[1]); + + SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, NVT, Parts, 2); + return DAG.getNode(ISD::BITCAST, dl, N->getValueType(0), Vec); + } + } + + // Otherwise, store to a temporary and load out again as the new type. + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDValue DAGTypeLegalizer::ExpandOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type needs expansion. + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + EVT OldVT = N->getOperand(0).getValueType(); + EVT NewVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldVT); + DebugLoc dl = N->getDebugLoc(); + + assert(OldVT == VecVT.getVectorElementType() && + "BUILD_VECTOR operand type doesn't match vector element type!"); + + // Build a vector of twice the length out of the expanded elements. + // For example <3 x i64> -> <6 x i32>. + std::vector NewElts; + NewElts.reserve(NumElts*2); + + for (unsigned i = 0; i < NumElts; ++i) { + SDValue Lo, Hi; + GetExpandedOp(N->getOperand(i), Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(Lo); + NewElts.push_back(Hi); + } + + SDValue NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, + EVT::getVectorVT(*DAG.getContext(), + NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BITCAST, dl, VecVT, NewVec); +} + +SDValue DAGTypeLegalizer::ExpandOp_EXTRACT_ELEMENT(SDNode *N) { + SDValue Lo, Hi; + GetExpandedOp(N->getOperand(0), Lo, Hi); + return cast(N->getOperand(1))->getZExtValue() ? Hi : Lo; +} + +SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) { + // The vector type is legal but the element type needs expansion. + EVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + DebugLoc dl = N->getDebugLoc(); + + SDValue Val = N->getOperand(1); + EVT OldEVT = Val.getValueType(); + EVT NewEVT = TLI.getTypeToTransformTo(*DAG.getContext(), OldEVT); + + assert(OldEVT == VecVT.getVectorElementType() && + "Inserted element type doesn't match vector element type!"); + + // Bitconvert to a vector of twice the length with elements of the expanded + // type, insert the expanded vector elements, and then convert back. + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewEVT, NumElts*2); + SDValue NewVec = DAG.getNode(ISD::BITCAST, dl, + NewVecVT, N->getOperand(0)); + + SDValue Lo, Hi; + GetExpandedOp(Val, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + SDValue Idx = N->getOperand(2); + Idx = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, Idx); + NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, NewVec, Lo, Idx); + Idx = DAG.getNode(ISD::ADD, dl, + Idx.getValueType(), Idx, DAG.getIntPtrConstant(1)); + NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, NewVec, Hi, Idx); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BITCAST, dl, VecVT, NewVec); +} + +SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + assert(VT.getVectorElementType() == N->getOperand(0).getValueType() && + "SCALAR_TO_VECTOR operand type doesn't match vector element type!"); + unsigned NumElts = VT.getVectorNumElements(); + SmallVector Ops(NumElts); + Ops[0] = N->getOperand(0); + SDValue UndefVal = DAG.getUNDEF(Ops[0].getValueType()); + for (unsigned i = 1; i < NumElts; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { + assert(ISD::isNormalStore(N) && "This routine only for normal stores!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + DebugLoc dl = N->getDebugLoc(); + + StoreSDNode *St = cast(N); + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), + St->getValue().getValueType()); + SDValue Chain = St->getChain(); + SDValue Ptr = St->getBasePtr(); + unsigned Alignment = St->getAlignment(); + bool isVolatile = St->isVolatile(); + bool isNonTemporal = St->isNonTemporal(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + unsigned IncrementSize = NVT.getSizeInBits() / 8; + + SDValue Lo, Hi; + GetExpandedOp(St->getValue(), Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + Lo = DAG.getStore(Chain, dl, Lo, Ptr, St->getPointerInfo(), + isVolatile, isNonTemporal, Alignment); + + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); + Hi = DAG.getStore(Chain, dl, Hi, Ptr, + St->getPointerInfo().getWithOffset(IncrementSize), + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); +} + + +//===--------------------------------------------------------------------===// +// Generic Result Splitting. +//===--------------------------------------------------------------------===// + +// Be careful to make no assumptions about which of Lo/Hi is stored first in +// memory (for vectors it is always Lo first followed by Hi in the following +// bytes; for integers and floats it is Lo first if and only if the machine is +// little-endian). + +void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, + SDValue &Lo, SDValue &Hi) { + // A MERGE_VALUES node can produce any number of values. We know that the + // first illegal one needs to be expanded into Lo/Hi. + unsigned i; + + // The string of legal results gets turned into input operands, which have + // the same type. + for (i = 0; isTypeLegal(N->getValueType(i)); ++i) + ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); + + // The first illegal result must be the one that needs to be expanded. + GetSplitOp(N->getOperand(i), Lo, Hi); + + // Legalize the rest of the results into the input operands whether they are + // legal or not. + unsigned e = N->getNumValues(); + for (++i; i != e; ++i) + ReplaceValueWith(SDValue(N, i), SDValue(N->getOperand(i))); +} + +void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LL, LH, RL, RH; + DebugLoc dl = N->getDebugLoc(); + GetSplitOp(N->getOperand(1), LL, LH); + GetSplitOp(N->getOperand(2), RL, RH); + + SDValue Cond = N->getOperand(0); + Lo = DAG.getNode(ISD::SELECT, dl, LL.getValueType(), Cond, LL, RL); + Hi = DAG.getNode(ISD::SELECT, dl, LH.getValueType(), Cond, LH, RH); +} + +void DAGTypeLegalizer::SplitRes_SELECT_CC(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LL, LH, RL, RH; + DebugLoc dl = N->getDebugLoc(); + GetSplitOp(N->getOperand(2), LL, LH); + GetSplitOp(N->getOperand(3), RL, RH); + + Lo = DAG.getNode(ISD::SELECT_CC, dl, LL.getValueType(), N->getOperand(0), + N->getOperand(1), LL, RL, N->getOperand(4)); + Hi = DAG.getNode(ISD::SELECT_CC, dl, LH.getValueType(), N->getOperand(0), + N->getOperand(1), LH, RH, N->getOperand(4)); +} + +void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + Lo = DAG.getUNDEF(LoVT); + Hi = DAG.getUNDEF(HiVT); +} diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp new file mode 100644 index 00000000000..167dbe0377b --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp @@ -0,0 +1,290 @@ +//===-- LegalizeVectorOps.cpp - Implement SelectionDAG::LegalizeVectors ---===// +// +// 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 SelectionDAG::LegalizeVectors method. +// +// The vector legalizer looks for vector operations which might need to be +// scalarized and legalizes them. This is a separate step from Legalize because +// scalarizing can introduce illegal types. For example, suppose we have an +// ISD::SDIV of type v2i64 on x86-32. The type is legal (for example, addition +// on a v2i64 is legal), but ISD::SDIV isn't legal, so we have to unroll the +// operation, which introduces nodes with the illegal type i64 which must be +// expanded. Similarly, suppose we have an ISD::SRA of type v16i8 on PowerPC; +// the operation must be unrolled, which introduces nodes with the illegal +// type i8 which must be promoted. +// +// This does not legalize vector manipulations like ISD::BUILD_VECTOR, +// or operations that happen to take a vector which are custom-lowered; +// the legalization for such operations never produces nodes +// with illegal types, so it's okay to put off legalizing them until +// SelectionDAG::Legalize runs. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +namespace { +class VectorLegalizer { + SelectionDAG& DAG; + const TargetLowering &TLI; + bool Changed; // Keep track of whether anything changed + + /// LegalizedNodes - For nodes that are of legal width, and that have more + /// than one use, this map indicates what regularized operand to use. This + /// allows us to avoid legalizing the same thing more than once. + DenseMap LegalizedNodes; + + // Adds a node to the translation cache + void AddLegalizedOperand(SDValue From, SDValue To) { + LegalizedNodes.insert(std::make_pair(From, To)); + // If someone requests legalization of the new node, return itself. + if (From != To) + LegalizedNodes.insert(std::make_pair(To, To)); + } + + // Legalizes the given node + SDValue LegalizeOp(SDValue Op); + // Assuming the node is legal, "legalize" the results + SDValue TranslateLegalizeResults(SDValue Op, SDValue Result); + // Implements unrolling a VSETCC. + SDValue UnrollVSETCC(SDValue Op); + // Implements expansion for FNEG; falls back to UnrollVectorOp if FSUB + // isn't legal. + SDValue ExpandFNEG(SDValue Op); + // Implements vector promotion; this is essentially just bitcasting the + // operands to a different type and bitcasting the result back to the + // original type. + SDValue PromoteVectorOp(SDValue Op); + + public: + bool Run(); + VectorLegalizer(SelectionDAG& dag) : + DAG(dag), TLI(dag.getTargetLoweringInfo()), Changed(false) {} +}; + +bool VectorLegalizer::Run() { + // The legalize process is inherently a bottom-up recursive process (users + // legalize their uses before themselves). Given infinite stack space, we + // could just start legalizing on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, compute an ordering of the nodes where each + // node is only legalized after all of its operands are legalized. + DAG.AssignTopologicalOrder(); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = prior(DAG.allnodes_end()); I != llvm::next(E); ++I) + LegalizeOp(SDValue(I, 0)); + + // Finally, it's possible the root changed. Get the new root. + SDValue OldRoot = DAG.getRoot(); + assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?"); + DAG.setRoot(LegalizedNodes[OldRoot]); + + LegalizedNodes.clear(); + + // Remove dead nodes now. + DAG.RemoveDeadNodes(); + + return Changed; +} + +SDValue VectorLegalizer::TranslateLegalizeResults(SDValue Op, SDValue Result) { + // Generic legalization: just pass the operand through. + for (unsigned i = 0, e = Op.getNode()->getNumValues(); i != e; ++i) + AddLegalizedOperand(Op.getValue(i), Result.getValue(i)); + return Result.getValue(Op.getResNo()); +} + +SDValue VectorLegalizer::LegalizeOp(SDValue Op) { + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + DenseMap::iterator I = LegalizedNodes.find(Op); + if (I != LegalizedNodes.end()) return I->second; + + SDNode* Node = Op.getNode(); + + // Legalize the operands + SmallVector Ops; + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Ops.push_back(LegalizeOp(Node->getOperand(i))); + + SDValue Result = + SDValue(DAG.UpdateNodeOperands(Op.getNode(), Ops.data(), Ops.size()), 0); + + bool HasVectorValue = false; + for (SDNode::value_iterator J = Node->value_begin(), E = Node->value_end(); + J != E; + ++J) + HasVectorValue |= J->isVector(); + if (!HasVectorValue) + return TranslateLegalizeResults(Op, Result); + + EVT QueryType; + switch (Op.getOpcode()) { + default: + return TranslateLegalizeResults(Op, Result); + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::SELECT: + case ISD::SELECT_CC: + case ISD::VSETCC: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + case ISD::FPOWI: + case ISD::FPOW: + case ISD::FLOG: + case ISD::FLOG2: + case ISD::FLOG10: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FCEIL: + case ISD::FTRUNC: + case ISD::FRINT: + case ISD::FNEARBYINT: + case ISD::FFLOOR: + QueryType = Node->getValueType(0); + break; + case ISD::SIGN_EXTEND_INREG: + case ISD::FP_ROUND_INREG: + QueryType = cast(Node->getOperand(1))->getVT(); + break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + QueryType = Node->getOperand(0).getValueType(); + break; + } + + switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) { + case TargetLowering::Promote: + // "Promote" the operation by bitcasting + Result = PromoteVectorOp(Op); + Changed = true; + break; + case TargetLowering::Legal: break; + case TargetLowering::Custom: { + SDValue Tmp1 = TLI.LowerOperation(Op, DAG); + if (Tmp1.getNode()) { + Result = Tmp1; + break; + } + // FALL THROUGH + } + case TargetLowering::Expand: + if (Node->getOpcode() == ISD::FNEG) + Result = ExpandFNEG(Op); + else if (Node->getOpcode() == ISD::VSETCC) + Result = UnrollVSETCC(Op); + else + Result = DAG.UnrollVectorOp(Op.getNode()); + break; + } + + // Make sure that the generated code is itself legal. + if (Result != Op) { + Result = LegalizeOp(Result); + Changed = true; + } + + // Note that LegalizeOp may be reentered even from single-use nodes, which + // means that we always must cache transformed nodes. + AddLegalizedOperand(Op, Result); + return Result; +} + +SDValue VectorLegalizer::PromoteVectorOp(SDValue Op) { + // Vector "promotion" is basically just bitcasting and doing the operation + // in a different type. For example, x86 promotes ISD::AND on v2i32 to + // v1i64. + EVT VT = Op.getValueType(); + assert(Op.getNode()->getNumValues() == 1 && + "Can't promote a vector with multiple results!"); + EVT NVT = TLI.getTypeToPromoteTo(Op.getOpcode(), VT); + DebugLoc dl = Op.getDebugLoc(); + SmallVector Operands(Op.getNumOperands()); + + for (unsigned j = 0; j != Op.getNumOperands(); ++j) { + if (Op.getOperand(j).getValueType().isVector()) + Operands[j] = DAG.getNode(ISD::BITCAST, dl, NVT, Op.getOperand(j)); + else + Operands[j] = Op.getOperand(j); + } + + Op = DAG.getNode(Op.getOpcode(), dl, NVT, &Operands[0], Operands.size()); + + return DAG.getNode(ISD::BITCAST, dl, VT, Op); +} + +SDValue VectorLegalizer::ExpandFNEG(SDValue Op) { + if (TLI.isOperationLegalOrCustom(ISD::FSUB, Op.getValueType())) { + SDValue Zero = DAG.getConstantFP(-0.0, Op.getValueType()); + return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(), + Zero, Op.getOperand(0)); + } + return DAG.UnrollVectorOp(Op.getNode()); +} + +SDValue VectorLegalizer::UnrollVSETCC(SDValue Op) { + EVT VT = Op.getValueType(); + unsigned NumElems = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1), CC = Op.getOperand(2); + EVT TmpEltVT = LHS.getValueType().getVectorElementType(); + DebugLoc dl = Op.getDebugLoc(); + SmallVector Ops(NumElems); + for (unsigned i = 0; i < NumElems; ++i) { + SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS, + DAG.getIntPtrConstant(i)); + SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS, + DAG.getIntPtrConstant(i)); + Ops[i] = DAG.getNode(ISD::SETCC, dl, TLI.getSetCCResultType(TmpEltVT), + LHSElem, RHSElem, CC); + Ops[i] = DAG.getNode(ISD::SELECT, dl, EltVT, Ops[i], + DAG.getConstant(APInt::getAllOnesValue + (EltVT.getSizeInBits()), EltVT), + DAG.getConstant(0, EltVT)); + } + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElems); +} + +} + +bool SelectionDAG::LegalizeVectors() { + return VectorLegalizer(*this).Run(); +} diff --git a/final/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/final/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp new file mode 100644 index 00000000000..be1620599b5 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -0,0 +1,2585 @@ +//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file performs vector type splitting and scalarization for LegalizeTypes. +// Scalarization is the act of changing a computation in an illegal one-element +// vector type to be a computation in its scalar element type. For example, +// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed +// as a base case when scalarizing vector arithmetic like <4 x f32>, which +// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32 +// types. +// Splitting is the act of changing a computation in an invalid vector type to +// be a computation in two vectors of half the size. For example, implementing +// <128 x f32> operations in terms of two <64 x f32> operations. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Result Vector Scalarization: <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Scalarize node result " << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"); + SDValue R = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "ScalarizeVectorResult #" << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to scalarize the result of this operator!"); + + case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break; + case ISD::BUILD_VECTOR: R = N->getOperand(0); break; + case ISD::CONVERT_RNDSAT: R = ScalarizeVecRes_CONVERT_RNDSAT(N); break; + case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break; + case ISD::FP_ROUND_INREG: R = ScalarizeVecRes_InregOp(N); break; + case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; + case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast(N));break; + case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break; + case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break; + case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break; + case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break; + case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break; + case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break; + case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break; + case ISD::VSETCC: R = ScalarizeVecRes_VSETCC(N); break; + + case ISD::ANY_EXTEND: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::FABS: + case ISD::FCEIL: + case ISD::FCOS: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FFLOOR: + case ISD::FLOG: + case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: + case ISD::FNEG: + case ISD::FP_EXTEND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FRINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: + case ISD::SIGN_EXTEND: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::UINT_TO_FP: + case ISD::ZERO_EXTEND: + R = ScalarizeVecRes_UnaryOp(N); + break; + + case ISD::ADD: + case ISD::AND: + case ISD::FADD: + case ISD::FDIV: + case ISD::FMUL: + case ISD::FPOW: + case ISD::FREM: + case ISD::FSUB: + case ISD::MUL: + case ISD::OR: + case ISD::SDIV: + case ISD::SREM: + case ISD::SUB: + case ISD::UDIV: + case ISD::UREM: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + R = ScalarizeVecRes_BinOp(N); + break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.getNode()) + SetScalarizedVector(SDValue(N, ResNo), R); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + LHS.getValueType(), LHS, RHS); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) { + EVT NewVT = N->getValueType(0).getVectorElementType(); + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), + NewVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N) { + EVT NewVT = N->getValueType(0).getVectorElementType(); + SDValue Op0 = GetScalarizedVector(N->getOperand(0)); + return DAG.getConvertRndSat(NewVT, N->getDebugLoc(), + Op0, DAG.getValueType(NewVT), + DAG.getValueType(Op0.getValueType()), + N->getOperand(3), + N->getOperand(4), + cast(N)->getCvtCode()); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) { + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + N->getValueType(0).getVectorElementType(), + N->getOperand(0), N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) { + SDValue Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::FPOWI, N->getDebugLoc(), + Op.getValueType(), Op, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) { + // The value to insert may have a wider type than the vector element type, + // so be sure to truncate it to the element type if necessary. + SDValue Op = N->getOperand(1); + EVT EltVT = N->getValueType(0).getVectorElementType(); + if (Op.getValueType() != EltVT) + // FIXME: Can this happen for floating point types? + Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, Op); + return Op; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) { + assert(N->isUnindexed() && "Indexed vector load?"); + + SDValue Result = DAG.getLoad(ISD::UNINDEXED, + N->getExtensionType(), + N->getValueType(0).getVectorElementType(), + N->getDebugLoc(), + N->getChain(), N->getBasePtr(), + DAG.getUNDEF(N->getBasePtr().getValueType()), + N->getPointerInfo(), + N->getMemoryVT().getVectorElementType(), + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(N, 1), Result.getValue(1)); + return Result; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) { + // Get the dest type - it doesn't always match the input type, e.g. int_to_fp. + EVT DestVT = N->getValueType(0).getVectorElementType(); + SDValue Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), DestVT, Op); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) { + EVT EltVT = N->getValueType(0).getVectorElementType(); + EVT ExtVT = cast(N->getOperand(1))->getVT().getVectorElementType(); + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), EltVT, + LHS, DAG.getValueType(ExtVT)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) { + // If the operand is wider than the vector element type then it is implicitly + // truncated. Make that explicit here. + EVT EltVT = N->getValueType(0).getVectorElementType(); + SDValue InOp = N->getOperand(0); + if (InOp.getValueType() != EltVT) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp); + return InOp; +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + LHS.getValueType(), N->getOperand(0), LHS, + GetScalarizedVector(N->getOperand(2))); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(2)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), LHS.getValueType(), + N->getOperand(0), N->getOperand(1), + LHS, GetScalarizedVector(N->getOperand(3)), + N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + DebugLoc DL = N->getDebugLoc(); + + // Turn it into a scalar SETCC. + return DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS, N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) { + return DAG.getUNDEF(N->getValueType(0).getVectorElementType()); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) { + // Figure out if the scalar is the LHS or RHS and return it. + SDValue Arg = N->getOperand(2).getOperand(0); + if (Arg.getOpcode() == ISD::UNDEF) + return DAG.getUNDEF(N->getValueType(0).getVectorElementType()); + unsigned Op = !cast(Arg)->isNullValue(); + return GetScalarizedVector(N->getOperand(Op)); +} + +SDValue DAGTypeLegalizer::ScalarizeVecRes_VSETCC(SDNode *N) { + SDValue LHS = GetScalarizedVector(N->getOperand(0)); + SDValue RHS = GetScalarizedVector(N->getOperand(1)); + EVT NVT = N->getValueType(0).getVectorElementType(); + EVT SVT = TLI.getSetCCResultType(LHS.getValueType()); + DebugLoc DL = N->getDebugLoc(); + + // Turn it into a scalar SETCC. + SDValue Res = DAG.getNode(ISD::SETCC, DL, SVT, LHS, RHS, N->getOperand(2)); + + // VSETCC always returns a sign-extended value, while SETCC may not. The + // SETCC result type may not match the vector element type. Correct these. + if (NVT.bitsLE(SVT)) { + // The SETCC result type is bigger than the vector element type. + // Ensure the SETCC result is sign-extended. + if (TLI.getBooleanContents() != + TargetLowering::ZeroOrNegativeOneBooleanContent) + Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, SVT, Res, + DAG.getValueType(MVT::i1)); + // Truncate to the final type. + return DAG.getNode(ISD::TRUNCATE, DL, NVT, Res); + } + + // The SETCC result type is smaller than the vector element type. + // If the SetCC result is not sign-extended, chop it down to MVT::i1. + if (TLI.getBooleanContents() != + TargetLowering::ZeroOrNegativeOneBooleanContent) + Res = DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Res); + // Sign extend to the final type. + return DAG.getNode(ISD::SIGN_EXTEND, DL, NVT, Res); +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Scalarization <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": "; + N->dump(&DAG); + dbgs() << "\n"); + SDValue Res = SDValue(); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to scalarize this operator's operand!"); + case ISD::BITCAST: + Res = ScalarizeVecOp_BITCAST(N); + break; + case ISD::CONCAT_VECTORS: + Res = ScalarizeVecOp_CONCAT_VECTORS(N); + break; + case ISD::EXTRACT_VECTOR_ELT: + Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N); + break; + case ISD::STORE: + Res = ScalarizeVecOp_STORE(cast(N), OpNo); + break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +/// ScalarizeVecOp_BITCAST - If the value to convert is a vector that needs +/// to be scalarized, it must be <1 x ty>. Convert the element instead. +SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) { + SDValue Elt = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), + N->getValueType(0), Elt); +} + +/// ScalarizeVecOp_CONCAT_VECTORS - The vectors to concatenate have length one - +/// use a BUILD_VECTOR instead. +SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) { + SmallVector Ops(N->getNumOperands()); + for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i) + Ops[i] = GetScalarizedVector(N->getOperand(i)); + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), N->getValueType(0), + &Ops[0], Ops.size()); +} + +/// ScalarizeVecOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to +/// be scalarized, it must be <1 x ty>, so just return the element, ignoring the +/// index. +SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue Res = GetScalarizedVector(N->getOperand(0)); + if (Res.getValueType() != N->getValueType(0)) + Res = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0), + Res); + return Res; +} + +/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be +/// scalarized, it must be <1 x ty>. Just store the element. +SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ + assert(N->isUnindexed() && "Indexed store of one-element vector?"); + assert(OpNo == 1 && "Do not know how to scalarize this operand!"); + DebugLoc dl = N->getDebugLoc(); + + if (N->isTruncatingStore()) + return DAG.getTruncStore(N->getChain(), dl, + GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), N->getPointerInfo(), + N->getMemoryVT().getVectorElementType(), + N->isVolatile(), N->isNonTemporal(), + N->getAlignment()); + + return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), N->getPointerInfo(), + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); +} + + +//===----------------------------------------------------------------------===// +// Result Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitVectorResult - This method is called when the specified result of the +/// specified node is found to need vector splitting. At this point, the node +/// may also have invalid operands or may have other results that need +/// legalization, we just know that (at least) one result needs vector +/// splitting. +void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Split node result: "; + N->dump(&DAG); + dbgs() << "\n"); + SDValue Lo, Hi; + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "SplitVectorResult #" << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to split the result of this operator!"); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break; + case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break; + case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break; + case ISD::CONVERT_RNDSAT: SplitVecRes_CONVERT_RNDSAT(N, Lo, Hi); break; + case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break; + case ISD::FP_ROUND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break; + case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; + case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break; + case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break; + case ISD::LOAD: + SplitVecRes_LOAD(cast(N), Lo, Hi); + break; + case ISD::SETCC: + case ISD::VSETCC: + SplitVecRes_SETCC(N, Lo, Hi); + break; + case ISD::VECTOR_SHUFFLE: + SplitVecRes_VECTOR_SHUFFLE(cast(N), Lo, Hi); + break; + + case ISD::ANY_EXTEND: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::FABS: + case ISD::FCEIL: + case ISD::FCOS: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FFLOOR: + case ISD::FLOG: + case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: + case ISD::FNEG: + case ISD::FP_EXTEND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::FRINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: + case ISD::SIGN_EXTEND: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::UINT_TO_FP: + case ISD::ZERO_EXTEND: + SplitVecRes_UnaryOp(N, Lo, Hi); + break; + + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::FDIV: + case ISD::FPOW: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::UREM: + case ISD::SREM: + case ISD::FREM: + SplitVecRes_BinOp(N, Lo, Hi); + break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.getNode()) + SetSplitVector(SDValue(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LHSLo, LHSHi; + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); + SDValue RHSLo, RHSHi; + GetSplitVector(N->getOperand(1), RHSLo, RHSHi); + DebugLoc dl = N->getDebugLoc(); + + Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo, RHSLo); + Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi, RHSHi); +} + +void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // We know the result is a vector. The input may be either a vector or a + // scalar value. + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + DebugLoc dl = N->getDebugLoc(); + + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + case SoftenFloat: + case ScalarizeVector: + break; + case ExpandInteger: + case ExpandFloat: + // A scalar to vector conversion, where the scalar needs expansion. + // If the vector is being split in two then we can just convert the + // expanded pieces. + if (LoVT == HiVT) { + GetExpandedOp(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi); + return; + } + break; + case SplitVector: + // If the input is a vector that needs to be split, convert each split + // piece of the input now. + GetSplitVector(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi); + return; + } + + // In the general case, convert the input to an integer and split it by hand. + EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits()); + EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits()); + if (TLI.isBigEndian()) + std::swap(LoIntVT, HiIntVT); + + SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo); + Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + unsigned LoNumElts = LoVT.getVectorNumElements(); + SmallVector LoOps(N->op_begin(), N->op_begin()+LoNumElts); + Lo = DAG.getNode(ISD::BUILD_VECTOR, dl, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+LoNumElts, N->op_end()); + Hi = DAG.getNode(ISD::BUILD_VECTOR, dl, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, + SDValue &Hi) { + assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS"); + DebugLoc dl = N->getDebugLoc(); + unsigned NumSubvectors = N->getNumOperands() / 2; + if (NumSubvectors == 1) { + Lo = N->getOperand(0); + Hi = N->getOperand(1); + return; + } + + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SmallVector LoOps(N->op_begin(), N->op_begin()+NumSubvectors); + Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+NumSubvectors, N->op_end()); + Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitVecRes_CONVERT_RNDSAT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SDValue DTyOpLo = DAG.getValueType(LoVT); + SDValue DTyOpHi = DAG.getValueType(HiVT); + + SDValue RndOp = N->getOperand(3); + SDValue SatOp = N->getOperand(4); + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + + // Split the input. + SDValue VLo, VHi; + EVT InVT = N->getOperand(0).getValueType(); + switch (getTypeAction(InVT)) { + default: llvm_unreachable("Unexpected type action!"); + case Legal: { + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + case SplitVector: + GetSplitVector(N->getOperand(0), VLo, VHi); + break; + case WidenVector: { + // If the result needs to be split and the input needs to be widened, + // the two types must have different lengths. Use the widened result + // and extract from it to do the split. + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + VLo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + VHi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + } + + SDValue STyOpLo = DAG.getValueType(VLo.getValueType()); + SDValue STyOpHi = DAG.getValueType(VHi.getValueType()); + + Lo = DAG.getConvertRndSat(LoVT, dl, VLo, DTyOpLo, STyOpLo, RndOp, SatOp, + CvtCode); + Hi = DAG.getConvertRndSat(HiVT, dl, VHi, DTyOpHi, STyOpHi, RndOp, SatOp, + CvtCode); +} + +void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Vec = N->getOperand(0); + SDValue Idx = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + EVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx); + uint64_t IdxVal = cast(Idx)->getZExtValue(); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec, + DAG.getIntPtrConstant(IdxVal + LoVT.getVectorNumElements())); +} + +void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, + SDValue &Hi) { + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(ISD::FPOWI, dl, Lo.getValueType(), Lo, N->getOperand(1)); + Hi = DAG.getNode(ISD::FPOWI, dl, Hi.getValueType(), Hi, N->getOperand(1)); +} + +void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue LHSLo, LHSHi; + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); + DebugLoc dl = N->getDebugLoc(); + + EVT LoVT, HiVT; + GetSplitDestVTs(cast(N->getOperand(1))->getVT(), LoVT, HiVT); + + Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo, + DAG.getValueType(LoVT)); + Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi, + DAG.getValueType(HiVT)); +} + +void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, + SDValue &Hi) { + SDValue Vec = N->getOperand(0); + SDValue Elt = N->getOperand(1); + SDValue Idx = N->getOperand(2); + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(Vec, Lo, Hi); + + if (ConstantSDNode *CIdx = dyn_cast(Idx)) { + unsigned IdxVal = CIdx->getZExtValue(); + unsigned LoNumElts = Lo.getValueType().getVectorNumElements(); + if (IdxVal < LoNumElts) + Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, + Lo.getValueType(), Lo, Elt, Idx); + else + Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt, + DAG.getIntPtrConstant(IdxVal - LoNumElts)); + return; + } + + // Spill the vector to the stack. + EVT VecVT = Vec.getValueType(); + EVT EltVT = VecVT.getVectorElementType(); + SDValue StackPtr = DAG.CreateStackTemporary(VecVT); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, + MachinePointerInfo(), false, false, 0); + + // Store the new element. This may be larger than the vector element type, + // so use a truncating store. + SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); + const Type *VecType = VecVT.getTypeForEVT(*DAG.getContext()); + unsigned Alignment = + TLI.getTargetData()->getPrefTypeAlignment(VecType); + Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, MachinePointerInfo(), EltVT, + false, false, 0); + + // Load the Lo part from the stack slot. + Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, MachinePointerInfo(), + false, false, 0); + + // Increment the pointer to the other part. + unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8; + StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, + DAG.getIntPtrConstant(IncrementSize)); + + // Load the Hi part from the stack slot. + Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MachinePointerInfo(), + false, false, MinAlign(Alignment, IncrementSize)); +} + +void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, + SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + Lo = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, LoVT, N->getOperand(0)); + Hi = DAG.getUNDEF(HiVT); +} + +void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, + SDValue &Hi) { + assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!"); + EVT LoVT, HiVT; + DebugLoc dl = LD->getDebugLoc(); + GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); + + ISD::LoadExtType ExtType = LD->getExtensionType(); + SDValue Ch = LD->getChain(); + SDValue Ptr = LD->getBasePtr(); + SDValue Offset = DAG.getUNDEF(Ptr.getValueType()); + EVT MemoryVT = LD->getMemoryVT(); + unsigned Alignment = LD->getOriginalAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + + EVT LoMemVT, HiMemVT; + GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); + + Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset, + LD->getPointerInfo(), LoMemVT, isVolatile, isNonTemporal, + Alignment); + + unsigned IncrementSize = LoMemVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, + LD->getPointerInfo().getWithOffset(IncrementSize), + HiMemVT, isVolatile, isNonTemporal, Alignment); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDValue(LD, 1), Ch); +} + +void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) { + EVT LoVT, HiVT; + DebugLoc DL = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + // Split the input. + EVT InVT = N->getOperand(0).getValueType(); + SDValue LL, LH, RL, RH; + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + LL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + LH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + + RL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1), + DAG.getIntPtrConstant(0)); + RH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + + Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2)); + Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2)); +} + +void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, + SDValue &Hi) { + // Get the dest types - they may not match the input types, e.g. int_to_fp. + EVT LoVT, HiVT; + DebugLoc dl = N->getDebugLoc(); + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + // Split the input. + EVT InVT = N->getOperand(0).getValueType(); + switch (getTypeAction(InVT)) { + default: llvm_unreachable("Unexpected type action!"); + case Legal: { + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0), + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + case SplitVector: + GetSplitVector(N->getOperand(0), Lo, Hi); + break; + case WidenVector: { + // If the result needs to be split and the input needs to be widened, + // the two types must have different lengths. Use the widened result + // and extract from it to do the split. + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(), + LoVT.getVectorNumElements()); + Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(0)); + Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, InOp, + DAG.getIntPtrConstant(InNVT.getVectorNumElements())); + break; + } + } + + Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo); + Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi); +} + +void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, + SDValue &Lo, SDValue &Hi) { + // The low and high parts of the original input give four input vectors. + SDValue Inputs[4]; + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]); + GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]); + EVT NewVT = Inputs[0].getValueType(); + unsigned NewElts = NewVT.getVectorNumElements(); + + // If Lo or Hi uses elements from at most two of the four input vectors, then + // express it as a vector shuffle of those two inputs. Otherwise extract the + // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR. + SmallVector Ops; + for (unsigned High = 0; High < 2; ++High) { + SDValue &Output = High ? Hi : Lo; + + // Build a shuffle mask for the output, discovering on the fly which + // input vectors to use as shuffle operands (recorded in InputUsed). + // If building a suitable shuffle vector proves too hard, then bail + // out with useBuildVector set. + unsigned InputUsed[2] = { -1U, -1U }; // Not yet discovered. + unsigned FirstMaskIdx = High * NewElts; + bool useBuildVector = false; + for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + // The mask element. This indexes into the input. + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); + + // The input vector this mask element indexes into. + unsigned Input = (unsigned)Idx / NewElts; + + if (Input >= array_lengthof(Inputs)) { + // The mask element does not index into any input vector. + Ops.push_back(-1); + continue; + } + + // Turn the index into an offset from the start of the input vector. + Idx -= Input * NewElts; + + // Find or create a shuffle vector operand to hold this input. + unsigned OpNo; + for (OpNo = 0; OpNo < array_lengthof(InputUsed); ++OpNo) { + if (InputUsed[OpNo] == Input) { + // This input vector is already an operand. + break; + } else if (InputUsed[OpNo] == -1U) { + // Create a new operand for this input vector. + InputUsed[OpNo] = Input; + break; + } + } + + if (OpNo >= array_lengthof(InputUsed)) { + // More than two input vectors used! Give up on trying to create a + // shuffle vector. Insert all elements into a BUILD_VECTOR instead. + useBuildVector = true; + break; + } + + // Add the mask index for the new shuffle vector. + Ops.push_back(Idx + OpNo * NewElts); + } + + if (useBuildVector) { + EVT EltVT = NewVT.getVectorElementType(); + SmallVector SVOps; + + // Extract the input elements by hand. + for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { + // The mask element. This indexes into the input. + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); + + // The input vector this mask element indexes into. + unsigned Input = (unsigned)Idx / NewElts; + + if (Input >= array_lengthof(Inputs)) { + // The mask element is "undef" or indexes off the end of the input. + SVOps.push_back(DAG.getUNDEF(EltVT)); + continue; + } + + // Turn the index into an offset from the start of the input vector. + Idx -= Input * NewElts; + + // Extract the vector element by hand. + SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + Inputs[Input], DAG.getIntPtrConstant(Idx))); + } + + // Construct the Lo/Hi output using a BUILD_VECTOR. + Output = DAG.getNode(ISD::BUILD_VECTOR,dl,NewVT, &SVOps[0], SVOps.size()); + } else if (InputUsed[0] == -1U) { + // No input vectors were used! The result is undefined. + Output = DAG.getUNDEF(NewVT); + } else { + SDValue Op0 = Inputs[InputUsed[0]]; + // If only one input was used, use an undefined vector for the other. + SDValue Op1 = InputUsed[1] == -1U ? + DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]]; + // At least one input vector was used. Create a new shuffle vector. + Output = DAG.getVectorShuffle(NewVT, dl, Op0, Op1, &Ops[0]); + } + + Ops.clear(); + } +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitVectorOperand - This method is called when the specified operand of the +/// specified node is found to need vector splitting. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need legalization as well as the specified one. +bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) { + DEBUG(dbgs() << "Split node operand: "; + N->dump(&DAG); + dbgs() << "\n"); + SDValue Res = SDValue(); + + if (Res.getNode() == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "SplitVectorOperand Op #" << OpNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to split this operator's operand!"); + + case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break; + case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break; + case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break; + case ISD::STORE: + Res = SplitVecOp_STORE(cast(N), OpNo); + break; + + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::FP_EXTEND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::FTRUNC: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Res = SplitVecOp_UnaryOp(N); + break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) { + // The result has a legal vector type, but the input needs splitting. + EVT ResVT = N->getValueType(0); + SDValue Lo, Hi; + DebugLoc dl = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo, Hi); + EVT InVT = Lo.getValueType(); + + EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(), + InVT.getVectorNumElements()); + + Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo); + Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi); + + return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi); +} + +SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) { + // For example, i64 = BITCAST v4i16 on alpha. Typically the vector will + // end up being split all the way down to individual components. Convert the + // split pieces into integers and reassemble. + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), N->getValueType(0), + JoinIntegers(Lo, Hi)); +} + +SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) { + // We know that the extracted result type is legal. + EVT SubVT = N->getValueType(0); + SDValue Idx = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + SDValue Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + uint64_t IdxVal = cast(Idx)->getZExtValue(); + + if (IdxVal < LoElts) { + assert(IdxVal + SubVT.getVectorNumElements() <= LoElts && + "Extracted subvector crosses vector split!"); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx); + } else { + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi, + DAG.getConstant(IdxVal - LoElts, Idx.getValueType())); + } +} + +SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue Vec = N->getOperand(0); + SDValue Idx = N->getOperand(1); + EVT VecVT = Vec.getValueType(); + + if (isa(Idx)) { + uint64_t IdxVal = cast(Idx)->getZExtValue(); + assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); + + SDValue Lo, Hi; + GetSplitVector(Vec, Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + + if (IdxVal < LoElts) + return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0); + return SDValue(DAG.UpdateNodeOperands(N, Hi, + DAG.getConstant(IdxVal - LoElts, + Idx.getValueType())), 0); + } + + // Store the vector to the stack. + EVT EltVT = VecVT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + SDValue StackPtr = DAG.CreateStackTemporary(VecVT); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, + MachinePointerInfo(), false, false, 0); + + // Load back the required element. + StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); + return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr, + MachinePointerInfo(), EltVT, false, false, 0); +} + +SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { + assert(N->isUnindexed() && "Indexed store of vector?"); + assert(OpNo == 1 && "Can only split the stored value"); + DebugLoc DL = N->getDebugLoc(); + + bool isTruncating = N->isTruncatingStore(); + SDValue Ch = N->getChain(); + SDValue Ptr = N->getBasePtr(); + EVT MemoryVT = N->getMemoryVT(); + unsigned Alignment = N->getOriginalAlignment(); + bool isVol = N->isVolatile(); + bool isNT = N->isNonTemporal(); + SDValue Lo, Hi; + GetSplitVector(N->getOperand(1), Lo, Hi); + + EVT LoMemVT, HiMemVT; + GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); + + unsigned IncrementSize = LoMemVT.getSizeInBits()/8; + + if (isTruncating) + Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), + LoMemVT, isVol, isNT, Alignment); + else + Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), + isVol, isNT, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + + if (isTruncating) + Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), + HiMemVT, isVol, isNT, Alignment); + else + Hi = DAG.getStore(Ch, DL, Hi, Ptr, + N->getPointerInfo().getWithOffset(IncrementSize), + isVol, isNT, Alignment); + + return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi); +} + +SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) { + DebugLoc DL = N->getDebugLoc(); + + // The input operands all must have the same type, and we know the result the + // result type is valid. Convert this to a buildvector which extracts all the + // input elements. + // TODO: If the input elements are power-two vectors, we could convert this to + // a new CONCAT_VECTORS node with elements that are half-wide. + SmallVector Elts; + EVT EltVT = N->getValueType(0).getVectorElementType(); + for (unsigned op = 0, e = N->getNumOperands(); op != e; ++op) { + SDValue Op = N->getOperand(op); + for (unsigned i = 0, e = Op.getValueType().getVectorNumElements(); + i != e; ++i) { + Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, + Op, DAG.getIntPtrConstant(i))); + + } + } + + return DAG.getNode(ISD::BUILD_VECTOR, DL, N->getValueType(0), + &Elts[0], Elts.size()); +} + +SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) { + // The result has a legal vector type, but the input needs splitting. + EVT ResVT = N->getValueType(0); + SDValue Lo, Hi; + DebugLoc DL = N->getDebugLoc(); + GetSplitVector(N->getOperand(0), Lo, Hi); + EVT InVT = Lo.getValueType(); + + EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(), + InVT.getVectorNumElements()); + + Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1)); + Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1)); + + return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi); +} + + + +//===----------------------------------------------------------------------===// +// Result Vector Widening +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Widen node result " << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"); + + // See if the target wants to custom widen this node. + if (CustomWidenLowerNode(N, N->getValueType(ResNo))) + return; + + SDValue Res = SDValue(); + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "WidenVectorResult #" << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to widen the result of this operator!"); + + case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break; + case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break; + case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break; + case ISD::CONVERT_RNDSAT: Res = WidenVecRes_CONVERT_RNDSAT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break; + case ISD::FP_ROUND_INREG: Res = WidenVecRes_InregOp(N); break; + case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break; + case ISD::LOAD: Res = WidenVecRes_LOAD(N); break; + case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); break; + case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break; + case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; + case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; + case ISD::SETCC: Res = WidenVecRes_SETCC(N); break; + case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; + case ISD::VECTOR_SHUFFLE: + Res = WidenVecRes_VECTOR_SHUFFLE(cast(N)); + break; + case ISD::VSETCC: + Res = WidenVecRes_VSETCC(N); + break; + + case ISD::ADD: + case ISD::AND: + case ISD::BSWAP: + case ISD::FADD: + case ISD::FCOPYSIGN: + case ISD::FDIV: + case ISD::FMUL: + case ISD::FPOW: + case ISD::FREM: + case ISD::FSUB: + case ISD::MUL: + case ISD::MULHS: + case ISD::MULHU: + case ISD::OR: + case ISD::SDIV: + case ISD::SREM: + case ISD::UDIV: + case ISD::UREM: + case ISD::SUB: + case ISD::XOR: + Res = WidenVecRes_Binary(N); + break; + + case ISD::FPOWI: + Res = WidenVecRes_POWI(N); + break; + + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + Res = WidenVecRes_Shift(N); + break; + + case ISD::ANY_EXTEND: + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SIGN_EXTEND: + case ISD::SINT_TO_FP: + case ISD::TRUNCATE: + case ISD::UINT_TO_FP: + case ISD::ZERO_EXTEND: + Res = WidenVecRes_Convert(N); + break; + + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::CTTZ: + case ISD::FABS: + case ISD::FCEIL: + case ISD::FCOS: + case ISD::FEXP: + case ISD::FEXP2: + case ISD::FFLOOR: + case ISD::FLOG: + case ISD::FLOG10: + case ISD::FLOG2: + case ISD::FNEARBYINT: + case ISD::FNEG: + case ISD::FRINT: + case ISD::FSIN: + case ISD::FSQRT: + case ISD::FTRUNC: + Res = WidenVecRes_Unary(N); + break; + } + + // If Res is null, the sub-method took care of registering the result. + if (Res.getNode()) + SetWidenedVector(SDValue(N, ResNo), Res); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) { + // Binary op widening. + unsigned Opcode = N->getOpcode(); + DebugLoc dl = N->getDebugLoc(); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT WidenEltVT = WidenVT.getVectorElementType(); + EVT VT = WidenVT; + unsigned NumElts = VT.getVectorNumElements(); + while (!TLI.isTypeLegal(VT) && NumElts != 1) { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } + + if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) { + // Operation doesn't trap so just widen as normal. + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2); + } + + // No legal vector version so unroll the vector operation and then widen. + if (NumElts == 1) + return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements()); + + // Since the operation can trap, apply operation on the original vector. + EVT MaxVT = VT; + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + unsigned CurNumElts = N->getValueType(0).getVectorNumElements(); + + SmallVector ConcatOps(CurNumElts); + unsigned ConcatEnd = 0; // Current ConcatOps index. + int Idx = 0; // Current Idx into input vectors. + + // NumElts := greatest legal vector size (at most WidenVT) + // while (orig. vector has unhandled elements) { + // take munches of size NumElts from the beginning and add to ConcatOps + // NumElts := next smaller supported vector size or 1 + // } + while (CurNumElts != 0) { + while (CurNumElts >= NumElts) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1, + DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2, + DAG.getIntPtrConstant(Idx)); + ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2); + Idx += NumElts; + CurNumElts -= NumElts; + } + do { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } while (!TLI.isTypeLegal(VT) && NumElts != 1); + + if (NumElts == 1) { + for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp1, DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp2, DAG.getIntPtrConstant(Idx)); + ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT, + EOp1, EOp2); + } + CurNumElts = 0; + } + } + + // Check to see if we have a single operation with the widen type. + if (ConcatEnd == 1) { + VT = ConcatOps[0].getValueType(); + if (VT == WidenVT) + return ConcatOps[0]; + } + + // while (Some element of ConcatOps is not of type MaxVT) { + // From the end of ConcatOps, collect elements of the same type and put + // them into an op of the next larger supported type + // } + while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) { + Idx = ConcatEnd - 1; + VT = ConcatOps[Idx--].getValueType(); + while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT) + Idx--; + + int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1; + EVT NextVT; + do { + NextSize *= 2; + NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize); + } while (!TLI.isTypeLegal(NextVT)); + + if (!VT.isVector()) { + // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT + SDValue VecOp = DAG.getUNDEF(NextVT); + unsigned NumToInsert = ConcatEnd - Idx - 1; + for (unsigned i = 0, OpIdx = Idx+1; i < NumToInsert; i++, OpIdx++) { + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NextVT, VecOp, + ConcatOps[OpIdx], DAG.getIntPtrConstant(i)); + } + ConcatOps[Idx+1] = VecOp; + ConcatEnd = Idx + 2; + } else { + // Vector type, create a CONCAT_VECTORS of type NextVT + SDValue undefVec = DAG.getUNDEF(VT); + unsigned OpsToConcat = NextSize/VT.getVectorNumElements(); + SmallVector SubConcatOps(OpsToConcat); + unsigned RealVals = ConcatEnd - Idx - 1; + unsigned SubConcatEnd = 0; + unsigned SubConcatIdx = Idx + 1; + while (SubConcatEnd < RealVals) + SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx]; + while (SubConcatEnd < OpsToConcat) + SubConcatOps[SubConcatEnd++] = undefVec; + ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl, + NextVT, &SubConcatOps[0], + OpsToConcat); + ConcatEnd = SubConcatIdx + 1; + } + } + + // Check to see if we have a single operation with the widen type. + if (ConcatEnd == 1) { + VT = ConcatOps[0].getValueType(); + if (VT == WidenVT) + return ConcatOps[0]; + } + + // add undefs of size MaxVT until ConcatOps grows to length of WidenVT + unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements(); + if (NumOps != ConcatEnd ) { + SDValue UndefVal = DAG.getUNDEF(MaxVT); + for (unsigned j = ConcatEnd; j < NumOps; ++j) + ConcatOps[j] = UndefVal; + } + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], NumOps); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) { + SDValue InOp = N->getOperand(0); + DebugLoc DL = N->getDebugLoc(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts); + + unsigned Opcode = N->getOpcode(); + unsigned InVTNumElts = InVT.getVectorNumElements(); + + if (getTypeAction(InVT) == WidenVector) { + InOp = GetWidenedVector(N->getOperand(0)); + InVT = InOp.getValueType(); + InVTNumElts = InVT.getVectorNumElements(); + if (InVTNumElts == WidenNumElts) { + if (N->getNumOperands() == 1) + return DAG.getNode(Opcode, DL, WidenVT, InOp); + return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1)); + } + } + + if (TLI.isTypeLegal(InWidenVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + if (WidenNumElts % InVTNumElts == 0) { + // Widen the input and call convert on the widened input vector. + unsigned NumConcat = WidenNumElts/InVTNumElts; + SmallVector Ops(NumConcat); + Ops[0] = InOp; + SDValue UndefVal = DAG.getUNDEF(InVT); + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = UndefVal; + SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, + &Ops[0], NumConcat); + if (N->getNumOperands() == 1) + return DAG.getNode(Opcode, DL, WidenVT, InVec); + return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1)); + } + + if (InVTNumElts % WidenNumElts == 0) { + SDValue InVal = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InWidenVT, + InOp, DAG.getIntPtrConstant(0)); + // Extract the input and convert the shorten input vector. + if (N->getNumOperands() == 1) + return DAG.getNode(Opcode, DL, WidenVT, InVal); + return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1)); + } + } + + // Otherwise unroll into some nasty scalar code and rebuild the vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = WidenVT.getVectorElementType(); + unsigned MinElts = std::min(InVTNumElts, WidenNumElts); + unsigned i; + for (i=0; i < MinElts; ++i) { + SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp, + DAG.getIntPtrConstant(i)); + if (N->getNumOperands() == 1) + Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val); + else + Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1)); + } + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::BUILD_VECTOR, DL, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_POWI(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + SDValue ShOp = N->getOperand(1); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp, ShOp); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Shift(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + SDValue ShOp = N->getOperand(1); + + EVT ShVT = ShOp.getValueType(); + if (getTypeAction(ShVT) == WidenVector) { + ShOp = GetWidenedVector(ShOp); + ShVT = ShOp.getValueType(); + } + EVT ShWidenVT = EVT::getVectorVT(*DAG.getContext(), + ShVT.getVectorElementType(), + WidenVT.getVectorNumElements()); + if (ShVT != ShWidenVT) + ShOp = ModifyToType(ShOp, ShWidenVT); + + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp, ShOp); +} + +SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) { + // Unary op widening. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp); +} + +SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + EVT ExtVT = EVT::getVectorVT(*DAG.getContext(), + cast(N->getOperand(1))->getVT() + .getVectorElementType(), + WidenVT.getVectorNumElements()); + SDValue WidenLHS = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), N->getDebugLoc(), + WidenVT, WidenLHS, DAG.getValueType(ExtVT)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) { + SDValue InOp = N->getOperand(0); + EVT InVT = InOp.getValueType(); + EVT VT = N->getValueType(0); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + DebugLoc dl = N->getDebugLoc(); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + // If the InOp is promoted to the same size, convert it. Otherwise, + // fall out of the switch and widen the promoted input. + InOp = GetPromotedInteger(InOp); + InVT = InOp.getValueType(); + if (WidenVT.bitsEq(InVT)) + return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp); + break; + case SoftenFloat: + case ExpandInteger: + case ExpandFloat: + case ScalarizeVector: + case SplitVector: + break; + case WidenVector: + // If the InOp is widened to the same size, convert it. Otherwise, fall + // out of the switch and widen the widened input. + InOp = GetWidenedVector(InOp); + InVT = InOp.getValueType(); + if (WidenVT.bitsEq(InVT)) + // The input widens to the same size. Convert to the widen value. + return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp); + break; + } + + unsigned WidenSize = WidenVT.getSizeInBits(); + unsigned InSize = InVT.getSizeInBits(); + // x86mmx is not an acceptable vector element type, so don't try. + if (WidenSize % InSize == 0 && InVT != MVT::x86mmx) { + // Determine new input vector type. The new input vector type will use + // the same element type (if its a vector) or use the input type as a + // vector. It is the same size as the type to widen to. + EVT NewInVT; + unsigned NewNumElts = WidenSize / InSize; + if (InVT.isVector()) { + EVT InEltVT = InVT.getVectorElementType(); + NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, + WidenSize / InEltVT.getSizeInBits()); + } else { + NewInVT = EVT::getVectorVT(*DAG.getContext(), InVT, NewNumElts); + } + + if (TLI.isTypeLegal(NewInVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + SmallVector Ops(NewNumElts); + SDValue UndefVal = DAG.getUNDEF(InVT); + Ops[0] = InOp; + for (unsigned i = 1; i < NewNumElts; ++i) + Ops[i] = UndefVal; + + SDValue NewVec; + if (InVT.isVector()) + NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, + NewInVT, &Ops[0], NewNumElts); + else + NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, + NewInVT, &Ops[0], NewNumElts); + return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec); + } + } + + return CreateStackStoreLoad(InOp, WidenVT); +} + +SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + // Build a vector with undefined for the new nodes. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + unsigned NumElts = VT.getVectorNumElements(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SmallVector NewOps(N->op_begin(), N->op_end()); + NewOps.reserve(WidenNumElts); + for (unsigned i = NumElts; i < WidenNumElts; ++i) + NewOps.push_back(DAG.getUNDEF(EltVT)); + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &NewOps[0], NewOps.size()); +} + +SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) { + EVT InVT = N->getOperand(0).getValueType(); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + DebugLoc dl = N->getDebugLoc(); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + unsigned NumOperands = N->getNumOperands(); + + bool InputWidened = false; // Indicates we need to widen the input. + if (getTypeAction(InVT) != WidenVector) { + if (WidenVT.getVectorNumElements() % InVT.getVectorNumElements() == 0) { + // Add undef vectors to widen to correct length. + unsigned NumConcat = WidenVT.getVectorNumElements() / + InVT.getVectorNumElements(); + SDValue UndefVal = DAG.getUNDEF(InVT); + SmallVector Ops(NumConcat); + for (unsigned i=0; i < NumOperands; ++i) + Ops[i] = N->getOperand(i); + for (unsigned i = NumOperands; i != NumConcat; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &Ops[0], NumConcat); + } + } else { + InputWidened = true; + if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) { + // The inputs and the result are widen to the same value. + unsigned i; + for (i=1; i < NumOperands; ++i) + if (N->getOperand(i).getOpcode() != ISD::UNDEF) + break; + + if (i > NumOperands) + // Everything but the first operand is an UNDEF so just return the + // widened first operand. + return GetWidenedVector(N->getOperand(0)); + + if (NumOperands == 2) { + // Replace concat of two operands with a shuffle. + SmallVector MaskOps(WidenNumElts); + for (unsigned i=0; i < WidenNumElts/2; ++i) { + MaskOps[i] = i; + MaskOps[i+WidenNumElts/2] = i+WidenNumElts; + } + return DAG.getVectorShuffle(WidenVT, dl, + GetWidenedVector(N->getOperand(0)), + GetWidenedVector(N->getOperand(1)), + &MaskOps[0]); + } + } + } + + // Fall back to use extracts and build vector. + EVT EltVT = WidenVT.getVectorElementType(); + unsigned NumInElts = InVT.getVectorNumElements(); + SmallVector Ops(WidenNumElts); + unsigned Idx = 0; + for (unsigned i=0; i < NumOperands; ++i) { + SDValue InOp = N->getOperand(i); + if (InputWidened) + InOp = GetWidenedVector(InOp); + for (unsigned j=0; j < NumInElts; ++j) + Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(j)); + } + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; Idx < WidenNumElts; ++Idx) + Ops[Idx] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_CONVERT_RNDSAT(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + SDValue InOp = N->getOperand(0); + SDValue RndOp = N->getOperand(3); + SDValue SatOp = N->getOperand(4); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts); + + SDValue DTyOp = DAG.getValueType(WidenVT); + SDValue STyOp = DAG.getValueType(InWidenVT); + ISD::CvtCode CvtCode = cast(N)->getCvtCode(); + + unsigned InVTNumElts = InVT.getVectorNumElements(); + if (getTypeAction(InVT) == WidenVector) { + InOp = GetWidenedVector(InOp); + InVT = InOp.getValueType(); + InVTNumElts = InVT.getVectorNumElements(); + if (InVTNumElts == WidenNumElts) + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + if (TLI.isTypeLegal(InWidenVT)) { + // Because the result and the input are different vector types, widening + // the result could create a legal type but widening the input might make + // it an illegal type that might lead to repeatedly splitting the input + // and then widening it. To avoid this, we widen the input only if + // it results in a legal type. + if (WidenNumElts % InVTNumElts == 0) { + // Widen the input and call convert on the widened input vector. + unsigned NumConcat = WidenNumElts/InVTNumElts; + SmallVector Ops(NumConcat); + Ops[0] = InOp; + SDValue UndefVal = DAG.getUNDEF(InVT); + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = UndefVal; + + InOp = DAG.getNode(ISD::CONCAT_VECTORS, dl, InWidenVT, &Ops[0],NumConcat); + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + if (InVTNumElts % WidenNumElts == 0) { + // Extract the input and convert the shorten input vector. + InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InWidenVT, InOp, + DAG.getIntPtrConstant(0)); + return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + } + + // Otherwise unroll into some nasty scalar code and rebuild the vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = WidenVT.getVectorElementType(); + DTyOp = DAG.getValueType(EltVT); + STyOp = DAG.getValueType(InEltVT); + + unsigned MinElts = std::min(InVTNumElts, WidenNumElts); + unsigned i; + for (i=0; i < MinElts; ++i) { + SDValue ExtVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp, + DAG.getIntPtrConstant(i)); + Ops[i] = DAG.getConvertRndSat(WidenVT, dl, ExtVal, DTyOp, STyOp, RndOp, + SatOp, CvtCode); + } + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) { + EVT VT = N->getValueType(0); + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + SDValue InOp = N->getOperand(0); + SDValue Idx = N->getOperand(1); + DebugLoc dl = N->getDebugLoc(); + + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + + EVT InVT = InOp.getValueType(); + + // Check if we can just return the input vector after widening. + uint64_t IdxVal = cast(Idx)->getZExtValue(); + if (IdxVal == 0 && InVT == WidenVT) + return InOp; + + // Check if we can extract from the vector. + unsigned InNumElts = InVT.getVectorNumElements(); + if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts) + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx); + + // We could try widening the input to the right length but for now, extract + // the original elements, fill the rest with undefs and build a vector. + SmallVector Ops(WidenNumElts); + EVT EltVT = VT.getVectorElementType(); + unsigned NumElts = VT.getVectorNumElements(); + unsigned i; + for (i=0; i < NumElts; ++i) + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(IdxVal+i)); + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i < WidenNumElts; ++i) + Ops[i] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts); +} + +SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::INSERT_VECTOR_ELT, N->getDebugLoc(), + InOp.getValueType(), InOp, + N->getOperand(1), N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) { + LoadSDNode *LD = cast(N); + ISD::LoadExtType ExtType = LD->getExtensionType(); + + SDValue Result; + SmallVector LdChain; // Chain for the series of load + if (ExtType != ISD::NON_EXTLOAD) + Result = GenWidenVectorExtLoads(LdChain, LD, ExtType); + else + Result = GenWidenVectorLoads(LdChain, LD); + + // If we generate a single load, we can use that for the chain. Otherwise, + // build a factor node to remember the multiple loads are independent and + // chain to that. + SDValue NewChain; + if (LdChain.size() == 1) + NewChain = LdChain[0]; + else + NewChain = DAG.getNode(ISD::TokenFactor, LD->getDebugLoc(), MVT::Other, + &LdChain[0], LdChain.size()); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDValue(N, 1), NewChain); + + return Result; +} + +SDValue DAGTypeLegalizer::WidenVecRes_SCALAR_TO_VECTOR(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getNode(ISD::SCALAR_TO_VECTOR, N->getDebugLoc(), + WidenVT, N->getOperand(0)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue Cond1 = N->getOperand(0); + EVT CondVT = Cond1.getValueType(); + if (CondVT.isVector()) { + EVT CondEltVT = CondVT.getVectorElementType(); + EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), + CondEltVT, WidenNumElts); + if (getTypeAction(CondVT) == WidenVector) + Cond1 = GetWidenedVector(Cond1); + + if (Cond1.getValueType() != CondWidenVT) + Cond1 = ModifyToType(Cond1, CondWidenVT); + } + + SDValue InOp1 = GetWidenedVector(N->getOperand(1)); + SDValue InOp2 = GetWidenedVector(N->getOperand(2)); + assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), + WidenVT, Cond1, InOp1, InOp2); +} + +SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) { + SDValue InOp1 = GetWidenedVector(N->getOperand(2)); + SDValue InOp2 = GetWidenedVector(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), + InOp1.getValueType(), N->getOperand(0), + N->getOperand(1), InOp1, InOp2, N->getOperand(4)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(ISD::SETCC, N->getDebugLoc(), WidenVT, + InOp1, InOp2, N->getOperand(2)); +} + +SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + return DAG.getUNDEF(WidenVT); +} + +SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + unsigned NumElts = VT.getVectorNumElements(); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + + // Adjust mask based on new input vector length. + SmallVector NewMask; + for (unsigned i = 0; i != NumElts; ++i) { + int Idx = N->getMaskElt(i); + if (Idx < (int)NumElts) + NewMask.push_back(Idx); + else + NewMask.push_back(Idx - NumElts + WidenNumElts); + } + for (unsigned i = NumElts; i != WidenNumElts; ++i) + NewMask.push_back(-1); + return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]); +} + +SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) { + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + + SDValue InOp1 = N->getOperand(0); + EVT InVT = InOp1.getValueType(); + assert(InVT.isVector() && "can not widen non vector type"); + EVT WidenInVT = EVT::getVectorVT(*DAG.getContext(), + InVT.getVectorElementType(), WidenNumElts); + InOp1 = GetWidenedVector(InOp1); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + + // Assume that the input and output will be widen appropriately. If not, + // we will have to unroll it at some point. + assert(InOp1.getValueType() == WidenInVT && + InOp2.getValueType() == WidenInVT && + "Input not widened to expected type!"); + return DAG.getNode(ISD::VSETCC, N->getDebugLoc(), + WidenVT, InOp1, InOp2, N->getOperand(2)); +} + + +//===----------------------------------------------------------------------===// +// Widen Vector Operand +//===----------------------------------------------------------------------===// +bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned ResNo) { + DEBUG(dbgs() << "Widen node operand " << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"); + SDValue Res = SDValue(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + dbgs() << "WidenVectorOperand op #" << ResNo << ": "; + N->dump(&DAG); + dbgs() << "\n"; +#endif + llvm_unreachable("Do not know how to widen this operator's operand!"); + + case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break; + case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break; + case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::STORE: Res = WidenVecOp_STORE(N); break; + + case ISD::FP_EXTEND: + case ISD::FP_ROUND: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + case ISD::TRUNCATE: + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Res = WidenVecOp_Convert(N); + break; + } + + // If Res is null, the sub-method took care of registering the result. + if (!Res.getNode()) return false; + + // If the result is N, the sub-method updated N in place. Tell the legalizer + // core about this. + if (Res.getNode() == N) + return true; + + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDValue(N, 0), Res); + return false; +} + +SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) { + // Since the result is legal and the input is illegal, it is unlikely + // that we can fix the input to a legal type so unroll the convert + // into some scalar code and create a nasty build vector. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + unsigned NumElts = VT.getVectorNumElements(); + SDValue InOp = N->getOperand(0); + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + EVT InVT = InOp.getValueType(); + EVT InEltVT = InVT.getVectorElementType(); + + unsigned Opcode = N->getOpcode(); + SmallVector Ops(NumElts); + for (unsigned i=0; i < NumElts; ++i) + Ops[i] = DAG.getNode(Opcode, dl, EltVT, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp, + DAG.getIntPtrConstant(i))); + + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) { + EVT VT = N->getValueType(0); + SDValue InOp = GetWidenedVector(N->getOperand(0)); + EVT InWidenVT = InOp.getValueType(); + DebugLoc dl = N->getDebugLoc(); + + // Check if we can convert between two legal vector types and extract. + unsigned InWidenSize = InWidenVT.getSizeInBits(); + unsigned Size = VT.getSizeInBits(); + // x86mmx is not an acceptable vector element type, so don't try. + if (InWidenSize % Size == 0 && !VT.isVector() && VT != MVT::x86mmx) { + unsigned NewNumElts = InWidenSize / Size; + EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts); + if (TLI.isTypeLegal(NewVT)) { + SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp, + DAG.getIntPtrConstant(0)); + } + } + + return CreateStackStoreLoad(InOp, VT); +} + +SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) { + // If the input vector is not legal, it is likely that we will not find a + // legal vector of the same size. Replace the concatenate vector with a + // nasty build vector. + EVT VT = N->getValueType(0); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + unsigned NumElts = VT.getVectorNumElements(); + SmallVector Ops(NumElts); + + EVT InVT = N->getOperand(0).getValueType(); + unsigned NumInElts = InVT.getVectorNumElements(); + + unsigned Idx = 0; + unsigned NumOperands = N->getNumOperands(); + for (unsigned i=0; i < NumOperands; ++i) { + SDValue InOp = N->getOperand(i); + if (getTypeAction(InOp.getValueType()) == WidenVector) + InOp = GetWidenedVector(InOp); + for (unsigned j=0; j < NumInElts; ++j) + Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(j)); + } + return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts); +} + +SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, N->getDebugLoc(), + N->getValueType(0), InOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDValue InOp = GetWidenedVector(N->getOperand(0)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(), + N->getValueType(0), InOp, N->getOperand(1)); +} + +SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) { + // We have to widen the value but we want only to store the original + // vector type. + StoreSDNode *ST = cast(N); + + SmallVector StChain; + if (ST->isTruncatingStore()) + GenWidenVectorTruncStores(StChain, ST); + else + GenWidenVectorStores(StChain, ST); + + if (StChain.size() == 1) + return StChain[0]; + else + return DAG.getNode(ISD::TokenFactor, ST->getDebugLoc(), + MVT::Other,&StChain[0],StChain.size()); +} + +//===----------------------------------------------------------------------===// +// Vector Widening Utilities +//===----------------------------------------------------------------------===// + +// Utility function to find the type to chop up a widen vector for load/store +// TLI: Target lowering used to determine legal types. +// Width: Width left need to load/store. +// WidenVT: The widen vector type to load to/store from +// Align: If 0, don't allow use of a wider type +// WidenEx: If Align is not 0, the amount additional we can load/store from. + +static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI, + unsigned Width, EVT WidenVT, + unsigned Align = 0, unsigned WidenEx = 0) { + EVT WidenEltVT = WidenVT.getVectorElementType(); + unsigned WidenWidth = WidenVT.getSizeInBits(); + unsigned WidenEltWidth = WidenEltVT.getSizeInBits(); + unsigned AlignInBits = Align*8; + + // If we have one element to load/store, return it. + EVT RetVT = WidenEltVT; + if (Width == WidenEltWidth) + return RetVT; + + // See if there is larger legal integer than the element type to load/store + unsigned VT; + for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE; + VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) { + EVT MemVT((MVT::SimpleValueType) VT); + unsigned MemVTWidth = MemVT.getSizeInBits(); + if (MemVT.getSizeInBits() <= WidenEltWidth) + break; + if (TLI.isTypeLegal(MemVT) && (WidenWidth % MemVTWidth) == 0 && + (MemVTWidth <= Width || + (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) { + RetVT = MemVT; + break; + } + } + + // See if there is a larger vector type to load/store that has the same vector + // element type and is evenly divisible with the WidenVT. + for (VT = (unsigned)MVT::LAST_VECTOR_VALUETYPE; + VT >= (unsigned)MVT::FIRST_VECTOR_VALUETYPE; --VT) { + EVT MemVT = (MVT::SimpleValueType) VT; + unsigned MemVTWidth = MemVT.getSizeInBits(); + if (TLI.isTypeLegal(MemVT) && WidenEltVT == MemVT.getVectorElementType() && + (WidenWidth % MemVTWidth) == 0 && + (MemVTWidth <= Width || + (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) { + if (RetVT.getSizeInBits() < MemVTWidth || MemVT == WidenVT) + return MemVT; + } + } + + return RetVT; +} + +// Builds a vector type from scalar loads +// VecTy: Resulting Vector type +// LDOps: Load operators to build a vector type +// [Start,End) the list of loads to use. +static SDValue BuildVectorFromScalar(SelectionDAG& DAG, EVT VecTy, + SmallVector& LdOps, + unsigned Start, unsigned End) { + DebugLoc dl = LdOps[Start].getDebugLoc(); + EVT LdTy = LdOps[Start].getValueType(); + unsigned Width = VecTy.getSizeInBits(); + unsigned NumElts = Width / LdTy.getSizeInBits(); + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts); + + unsigned Idx = 1; + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]); + + for (unsigned i = Start + 1; i != End; ++i) { + EVT NewLdTy = LdOps[i].getValueType(); + if (NewLdTy != LdTy) { + NumElts = Width / NewLdTy.getSizeInBits(); + NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts); + VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp); + // Readjust position and vector position based on new load type + Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits(); + LdTy = NewLdTy; + } + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i], + DAG.getIntPtrConstant(Idx++)); + } + return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp); +} + +SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector &LdChain, + LoadSDNode *LD) { + // The strategy assumes that we can efficiently load powers of two widths. + // The routines chops the vector into the largest vector loads with the same + // element type or scalar loads and then recombines it to the widen vector + // type. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0)); + unsigned WidenWidth = WidenVT.getSizeInBits(); + EVT LdVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + assert(LdVT.isVector() && WidenVT.isVector()); + assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType()); + + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + unsigned Align = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + + int LdWidth = LdVT.getSizeInBits(); + int WidthDiff = WidenWidth - LdWidth; // Difference + unsigned LdAlign = (isVolatile) ? 0 : Align; // Allow wider loads + + // Find the vector type that can load from. + EVT NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff); + int NewVTWidth = NewVT.getSizeInBits(); + SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, LD->getPointerInfo(), + isVolatile, isNonTemporal, Align); + LdChain.push_back(LdOp.getValue(1)); + + // Check if we can load the element with one instruction + if (LdWidth <= NewVTWidth) { + if (!NewVT.isVector()) { + unsigned NumElts = WidenWidth / NewVTWidth; + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts); + SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp); + return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp); + } + if (NewVT == WidenVT) + return LdOp; + + assert(WidenWidth % NewVTWidth == 0); + unsigned NumConcat = WidenWidth / NewVTWidth; + SmallVector ConcatOps(NumConcat); + SDValue UndefVal = DAG.getUNDEF(NewVT); + ConcatOps[0] = LdOp; + for (unsigned i = 1; i != NumConcat; ++i) + ConcatOps[i] = UndefVal; + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], + NumConcat); + } + + // Load vector by using multiple loads from largest vector to scalar + SmallVector LdOps; + LdOps.push_back(LdOp); + + LdWidth -= NewVTWidth; + unsigned Offset = 0; + + while (LdWidth > 0) { + unsigned Increment = NewVTWidth / 8; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + + if (LdWidth < NewVTWidth) { + // Our current type we are using is too large, find a better size + NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff); + NewVTWidth = NewVT.getSizeInBits(); + } + + SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, + LD->getPointerInfo().getWithOffset(Offset), + isVolatile, + isNonTemporal, MinAlign(Align, Increment)); + LdChain.push_back(LdOp.getValue(1)); + LdOps.push_back(LdOp); + + LdWidth -= NewVTWidth; + } + + // Build the vector from the loads operations + unsigned End = LdOps.size(); + if (!LdOps[0].getValueType().isVector()) + // All the loads are scalar loads. + return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End); + + // If the load contains vectors, build the vector using concat vector. + // All of the vectors used to loads are power of 2 and the scalars load + // can be combined to make a power of 2 vector. + SmallVector ConcatOps(End); + int i = End - 1; + int Idx = End; + EVT LdTy = LdOps[i].getValueType(); + // First combine the scalar loads to a vector + if (!LdTy.isVector()) { + for (--i; i >= 0; --i) { + LdTy = LdOps[i].getValueType(); + if (LdTy.isVector()) + break; + } + ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i+1, End); + } + ConcatOps[--Idx] = LdOps[i]; + for (--i; i >= 0; --i) { + EVT NewLdTy = LdOps[i].getValueType(); + if (NewLdTy != LdTy) { + // Create a larger vector + ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy, + &ConcatOps[Idx], End - Idx); + Idx = End - 1; + LdTy = NewLdTy; + } + ConcatOps[--Idx] = LdOps[i]; + } + + if (WidenWidth == LdTy.getSizeInBits()*(End - Idx)) + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, + &ConcatOps[Idx], End - Idx); + + // We need to fill the rest with undefs to build the vector + unsigned NumOps = WidenWidth / LdTy.getSizeInBits(); + SmallVector WidenOps(NumOps); + SDValue UndefVal = DAG.getUNDEF(LdTy); + { + unsigned i = 0; + for (; i != End-Idx; ++i) + WidenOps[i] = ConcatOps[Idx+i]; + for (; i != NumOps; ++i) + WidenOps[i] = UndefVal; + } + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &WidenOps[0],NumOps); +} + +SDValue +DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVector& LdChain, + LoadSDNode * LD, + ISD::LoadExtType ExtType) { + // For extension loads, it may not be more efficient to chop up the vector + // and then extended it. Instead, we unroll the load and build a new vector. + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0)); + EVT LdVT = LD->getMemoryVT(); + DebugLoc dl = LD->getDebugLoc(); + assert(LdVT.isVector() && WidenVT.isVector()); + + // Load information + SDValue Chain = LD->getChain(); + SDValue BasePtr = LD->getBasePtr(); + unsigned Align = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); + + EVT EltVT = WidenVT.getVectorElementType(); + EVT LdEltVT = LdVT.getVectorElementType(); + unsigned NumElts = LdVT.getVectorNumElements(); + + // Load each element and widen + unsigned WidenNumElts = WidenVT.getVectorNumElements(); + SmallVector Ops(WidenNumElts); + unsigned Increment = LdEltVT.getSizeInBits() / 8; + Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, + LD->getPointerInfo(), + LdEltVT, isVolatile, isNonTemporal, Align); + LdChain.push_back(Ops[0].getValue(1)); + unsigned i = 0, Offset = Increment; + for (i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, + LD->getPointerInfo().getWithOffset(Offset), LdEltVT, + isVolatile, isNonTemporal, Align); + LdChain.push_back(Ops[i].getValue(1)); + } + + // Fill the rest with undefs + SDValue UndefVal = DAG.getUNDEF(EltVT); + for (; i != WidenNumElts; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], Ops.size()); +} + + +void DAGTypeLegalizer::GenWidenVectorStores(SmallVector& StChain, + StoreSDNode *ST) { + // The strategy assumes that we can efficiently store powers of two widths. + // The routines chops the vector into the largest vector stores with the same + // element type or scalar stores. + SDValue Chain = ST->getChain(); + SDValue BasePtr = ST->getBasePtr(); + unsigned Align = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + SDValue ValOp = GetWidenedVector(ST->getValue()); + DebugLoc dl = ST->getDebugLoc(); + + EVT StVT = ST->getMemoryVT(); + unsigned StWidth = StVT.getSizeInBits(); + EVT ValVT = ValOp.getValueType(); + unsigned ValWidth = ValVT.getSizeInBits(); + EVT ValEltVT = ValVT.getVectorElementType(); + unsigned ValEltWidth = ValEltVT.getSizeInBits(); + assert(StVT.getVectorElementType() == ValEltVT); + + int Idx = 0; // current index to store + unsigned Offset = 0; // offset from base to store + while (StWidth != 0) { + // Find the largest vector type we can store with + EVT NewVT = FindMemType(DAG, TLI, StWidth, ValVT); + unsigned NewVTWidth = NewVT.getSizeInBits(); + unsigned Increment = NewVTWidth / 8; + if (NewVT.isVector()) { + unsigned NumVTElts = NewVT.getVectorNumElements(); + do { + SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp, + DAG.getIntPtrConstant(Idx)); + StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, + ST->getPointerInfo().getWithOffset(Offset), + isVolatile, isNonTemporal, + MinAlign(Align, Offset))); + StWidth -= NewVTWidth; + Offset += Increment; + Idx += NumVTElts; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + } while (StWidth != 0 && StWidth >= NewVTWidth); + } else { + // Cast the vector to the scalar type we can store + unsigned NumElts = ValWidth / NewVTWidth; + EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts); + SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp); + // Readjust index position based on new vector type + Idx = Idx * ValEltWidth / NewVTWidth; + do { + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp, + DAG.getIntPtrConstant(Idx++)); + StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, + ST->getPointerInfo().getWithOffset(Offset), + isVolatile, isNonTemporal, + MinAlign(Align, Offset))); + StWidth -= NewVTWidth; + Offset += Increment; + BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, + DAG.getIntPtrConstant(Increment)); + } while (StWidth != 0 && StWidth >= NewVTWidth); + // Restore index back to be relative to the original widen element type + Idx = Idx * NewVTWidth / ValEltWidth; + } + } +} + +void +DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector& StChain, + StoreSDNode *ST) { + // For extension loads, it may not be more efficient to truncate the vector + // and then store it. Instead, we extract each element and then store it. + SDValue Chain = ST->getChain(); + SDValue BasePtr = ST->getBasePtr(); + unsigned Align = ST->getAlignment(); + bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); + SDValue ValOp = GetWidenedVector(ST->getValue()); + DebugLoc dl = ST->getDebugLoc(); + + EVT StVT = ST->getMemoryVT(); + EVT ValVT = ValOp.getValueType(); + + // It must be true that we the widen vector type is bigger than where + // we need to store. + assert(StVT.isVector() && ValOp.getValueType().isVector()); + assert(StVT.bitsLT(ValOp.getValueType())); + + // For truncating stores, we can not play the tricks of chopping legal + // vector types and bit cast it to the right type. Instead, we unroll + // the store. + EVT StEltVT = StVT.getVectorElementType(); + EVT ValEltVT = ValVT.getVectorElementType(); + unsigned Increment = ValEltVT.getSizeInBits() / 8; + unsigned NumElts = StVT.getVectorNumElements(); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, + ST->getPointerInfo(), StEltVT, + isVolatile, isNonTemporal, Align)); + unsigned Offset = Increment; + for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { + SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), + BasePtr, DAG.getIntPtrConstant(Offset)); + SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp, + DAG.getIntPtrConstant(0)); + StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, + ST->getPointerInfo().getWithOffset(Offset), + StEltVT, isVolatile, isNonTemporal, + MinAlign(Align, Offset))); + } +} + +/// Modifies a vector input (widen or narrows) to a vector of NVT. The +/// input vector must have the same element type as NVT. +SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT) { + // Note that InOp might have been widened so it might already have + // the right width or it might need be narrowed. + EVT InVT = InOp.getValueType(); + assert(InVT.getVectorElementType() == NVT.getVectorElementType() && + "input and widen element type must match"); + DebugLoc dl = InOp.getDebugLoc(); + + // Check if InOp already has the right width. + if (InVT == NVT) + return InOp; + + unsigned InNumElts = InVT.getVectorNumElements(); + unsigned WidenNumElts = NVT.getVectorNumElements(); + if (WidenNumElts > InNumElts && WidenNumElts % InNumElts == 0) { + unsigned NumConcat = WidenNumElts / InNumElts; + SmallVector Ops(NumConcat); + SDValue UndefVal = DAG.getUNDEF(InVT); + Ops[0] = InOp; + for (unsigned i = 1; i != NumConcat; ++i) + Ops[i] = UndefVal; + + return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, &Ops[0], NumConcat); + } + + if (WidenNumElts < InNumElts && InNumElts % WidenNumElts) + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp, + DAG.getIntPtrConstant(0)); + + // Fall back to extract and build. + SmallVector Ops(WidenNumElts); + EVT EltVT = NVT.getVectorElementType(); + unsigned MinNumElts = std::min(WidenNumElts, InNumElts); + unsigned Idx; + for (Idx = 0; Idx < MinNumElts; ++Idx) + Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp, + DAG.getIntPtrConstant(Idx)); + + SDValue UndefVal = DAG.getUNDEF(EltVT); + for ( ; Idx < WidenNumElts; ++Idx) + Ops[Idx] = UndefVal; + return DAG.getNode(ISD::BUILD_VECTOR, dl, NVT, &Ops[0], WidenNumElts); +} diff --git a/final/lib/CodeGen/SelectionDAG/Makefile b/final/lib/CodeGen/SelectionDAG/Makefile new file mode 100644 index 00000000000..ea716fdaabb --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/Makefile @@ -0,0 +1,13 @@ +##===- lib/CodeGen/SelectionDAG/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMSelectionDAG + +include $(LEVEL)/Makefile.common diff --git a/final/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h b/final/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h new file mode 100644 index 00000000000..2dcb2295732 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h @@ -0,0 +1,114 @@ +//===-- llvm/CodeGen/SDNodeDbgValue.h - SelectionDAG dbg_value --*- 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 SDDbgValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SDNODEDBGVALUE_H +#define LLVM_CODEGEN_SDNODEDBGVALUE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MDNode; +class SDNode; +class Value; + +/// SDDbgValue - Holds the information from a dbg_value node through SDISel. +/// We do not use SDValue here to avoid including its header. + +class SDDbgValue { +public: + enum DbgValueKind { + SDNODE = 0, // value is the result of an expression + CONST = 1, // value is a constant + FRAMEIX = 2 // value is contents of a stack location + }; +private: + enum DbgValueKind kind; + union { + struct { + SDNode *Node; // valid for expressions + unsigned ResNo; // valid for expressions + } s; + const Value *Const; // valid for constants + unsigned FrameIx; // valid for stack objects + } u; + MDNode *mdPtr; + uint64_t Offset; + DebugLoc DL; + unsigned Order; + bool Invalid; +public: + // Constructor for non-constants. + SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl, + unsigned O) : mdPtr(mdP), Offset(off), DL(dl), Order(O), + Invalid(false) { + kind = SDNODE; + u.s.Node = N; + u.s.ResNo = R; + } + + // Constructor for constants. + SDDbgValue(MDNode *mdP, const Value *C, uint64_t off, DebugLoc dl, + unsigned O) : + mdPtr(mdP), Offset(off), DL(dl), Order(O), Invalid(false) { + kind = CONST; + u.Const = C; + } + + // Constructor for frame indices. + SDDbgValue(MDNode *mdP, unsigned FI, uint64_t off, DebugLoc dl, unsigned O) : + mdPtr(mdP), Offset(off), DL(dl), Order(O), Invalid(false) { + kind = FRAMEIX; + u.FrameIx = FI; + } + + // Returns the kind. + DbgValueKind getKind() { return kind; } + + // Returns the MDNode pointer. + MDNode *getMDPtr() { return mdPtr; } + + // Returns the SDNode* for a register ref + SDNode *getSDNode() { assert (kind==SDNODE); return u.s.Node; } + + // Returns the ResNo for a register ref + unsigned getResNo() { assert (kind==SDNODE); return u.s.ResNo; } + + // Returns the Value* for a constant + const Value *getConst() { assert (kind==CONST); return u.Const; } + + // Returns the FrameIx for a stack object + unsigned getFrameIx() { assert (kind==FRAMEIX); return u.FrameIx; } + + // Returns the offset. + uint64_t getOffset() { return Offset; } + + // Returns the DebugLoc. + DebugLoc getDebugLoc() { return DL; } + + // Returns the SDNodeOrder. This is the order of the preceding node in the + // input. + unsigned getOrder() { return Order; } + + // setIsInvalidated / isInvalidated - Setter / getter of the "Invalidated" + // property. A SDDbgValue is invalid if the SDNode that produces the value is + // deleted. + void setIsInvalidated() { Invalid = true; } + bool isInvalidated() { return Invalid; } +}; + +} // end llvm namespace + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/SDNodeOrdering.h b/final/lib/CodeGen/SelectionDAG/SDNodeOrdering.h new file mode 100644 index 00000000000..f88b26d5c42 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SDNodeOrdering.h @@ -0,0 +1,54 @@ +//===-- llvm/CodeGen/SDNodeOrdering.h - SDNode Ordering ---------*- 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 SDNodeOrdering class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SDNODEORDERING_H +#define LLVM_CODEGEN_SDNODEORDERING_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class SDNode; + +/// SDNodeOrdering - Maps a unique (monotonically increasing) value to each +/// SDNode that roughly corresponds to the ordering of the original LLVM +/// instruction. This is used for turning off scheduling, because we'll forgo +/// the normal scheduling algorithms and output the instructions according to +/// this ordering. +class SDNodeOrdering { + DenseMap OrderMap; + + void operator=(const SDNodeOrdering&); // Do not implement. + SDNodeOrdering(const SDNodeOrdering&); // Do not implement. +public: + SDNodeOrdering() {} + + void add(const SDNode *Node, unsigned O) { + OrderMap[Node] = O; + } + void remove(const SDNode *Node) { + DenseMap::iterator Itr = OrderMap.find(Node); + if (Itr != OrderMap.end()) + OrderMap.erase(Itr); + } + void clear() { + OrderMap.clear(); + } + unsigned getOrder(const SDNode *Node) { + return OrderMap[Node]; + } +}; + +} // end llvm namespace + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp b/final/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp new file mode 100644 index 00000000000..e3da2084529 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp @@ -0,0 +1,636 @@ +//===----- ScheduleDAGFast.cpp - Fast poor list scheduler -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a fast scheduler. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/InlineAsm.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(NumUnfolds, "Number of nodes unfolded"); +STATISTIC(NumDups, "Number of duplicated nodes"); +STATISTIC(NumPRCopies, "Number of physical copies"); + +static RegisterScheduler + fastDAGScheduler("fast", "Fast suboptimal list scheduling", + createFastDAGScheduler); + +namespace { + /// FastPriorityQueue - A degenerate priority queue that considers + /// all nodes to have the same priority. + /// + struct FastPriorityQueue { + SmallVector Queue; + + bool empty() const { return Queue.empty(); } + + void push(SUnit *U) { + Queue.push_back(U); + } + + SUnit *pop() { + if (empty()) return NULL; + SUnit *V = Queue.back(); + Queue.pop_back(); + return V; + } + }; + +//===----------------------------------------------------------------------===// +/// ScheduleDAGFast - The actual "fast" list scheduler implementation. +/// +class ScheduleDAGFast : public ScheduleDAGSDNodes { +private: + /// AvailableQueue - The priority queue to use for the available SUnits. + FastPriorityQueue AvailableQueue; + + /// LiveRegDefs - A set of physical registers and their definition + /// that are "live". These nodes must be scheduled before any other nodes that + /// modifies the registers can be scheduled. + unsigned NumLiveRegs; + std::vector LiveRegDefs; + std::vector LiveRegCycles; + +public: + ScheduleDAGFast(MachineFunction &mf) + : ScheduleDAGSDNodes(mf) {} + + void Schedule(); + + /// AddPred - adds a predecessor edge to SUnit SU. + /// This returns true if this is a new predecessor. + void AddPred(SUnit *SU, const SDep &D) { + SU->addPred(D); + } + + /// RemovePred - removes a predecessor edge from SUnit SU. + /// This returns true if an edge was removed. + void RemovePred(SUnit *SU, const SDep &D) { + SU->removePred(D); + } + +private: + void ReleasePred(SUnit *SU, SDep *PredEdge); + void ReleasePredecessors(SUnit *SU, unsigned CurCycle); + void ScheduleNodeBottomUp(SUnit*, unsigned); + SUnit *CopyAndMoveSuccessors(SUnit*); + void InsertCopiesAndMoveSuccs(SUnit*, unsigned, + const TargetRegisterClass*, + const TargetRegisterClass*, + SmallVector&); + bool DelayForLiveRegsBottomUp(SUnit*, SmallVector&); + void ListScheduleBottomUp(); + + /// ForceUnitLatencies - The fast scheduler doesn't care about real latencies. + bool ForceUnitLatencies() const { return true; } +}; +} // end anonymous namespace + + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGFast::Schedule() { + DEBUG(dbgs() << "********** List Scheduling **********\n"); + + NumLiveRegs = 0; + LiveRegDefs.resize(TRI->getNumRegs(), NULL); + LiveRegCycles.resize(TRI->getNumRegs(), 0); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + + // Execute the actual scheduling loop. + ListScheduleBottomUp(); +} + +//===----------------------------------------------------------------------===// +// Bottom-Up Scheduling +//===----------------------------------------------------------------------===// + +/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGFast::ReleasePred(SUnit *SU, SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + +#ifndef NDEBUG + if (PredSU->NumSuccsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + PredSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --PredSU->NumSuccsLeft; + + // If all the node's successors are scheduled, this node is ready + // to be scheduled. Ignore the special EntrySU node. + if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) { + PredSU->isAvailable = true; + AvailableQueue.push(PredSU); + } +} + +void ScheduleDAGFast::ReleasePredecessors(SUnit *SU, unsigned CurCycle) { + // Bottom up: release predecessors + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + ReleasePred(SU, &*I); + if (I->isAssignedRegDep()) { + // This is a physical register dependency and it's impossible or + // expensive to copy the register. Make sure nothing that can + // clobber the register is scheduled between the predecessor and + // this node. + if (!LiveRegDefs[I->getReg()]) { + ++NumLiveRegs; + LiveRegDefs[I->getReg()] = I->getSUnit(); + LiveRegCycles[I->getReg()] = CurCycle; + } + } + } +} + +/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending +/// count of its predecessors. If a predecessor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGFast::ScheduleNodeBottomUp(SUnit *SU, unsigned CurCycle) { + DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + assert(CurCycle >= SU->getHeight() && "Node scheduled below its height!"); + SU->setHeightToAtLeast(CurCycle); + Sequence.push_back(SU); + + ReleasePredecessors(SU, CurCycle); + + // Release all the implicit physical register defs that are live. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + if (LiveRegCycles[I->getReg()] == I->getSUnit()->getHeight()) { + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + assert(LiveRegDefs[I->getReg()] == SU && + "Physical register dependency violated?"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegCycles[I->getReg()] = 0; + } + } + } + + SU->isScheduled = true; +} + +/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled +/// successors to the newly created node. +SUnit *ScheduleDAGFast::CopyAndMoveSuccessors(SUnit *SU) { + if (SU->getNode()->getGluedNode()) + return NULL; + + SDNode *N = SU->getNode(); + if (!N) + return NULL; + + SUnit *NewSU; + bool TryUnfold = false; + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Glue) + return NULL; + else if (VT == MVT::Other) + TryUnfold = true; + } + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDValue &Op = N->getOperand(i); + EVT VT = Op.getNode()->getValueType(Op.getResNo()); + if (VT == MVT::Glue) + return NULL; + } + + if (TryUnfold) { + SmallVector NewNodes; + if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes)) + return NULL; + + DEBUG(dbgs() << "Unfolding SU # " << SU->NodeNum << "\n"); + assert(NewNodes.size() == 2 && "Expected a load folding node!"); + + N = NewNodes[1]; + SDNode *LoadNode = NewNodes[0]; + unsigned NumVals = N->getNumValues(); + unsigned OldNumVals = SU->getNode()->getNumValues(); + for (unsigned i = 0; i != NumVals; ++i) + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i)); + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1), + SDValue(LoadNode, 1)); + + SUnit *NewSU = NewSUnit(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NewSU->NodeNum); + + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + NewSU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + NewSU->isCommutable = true; + + // LoadNode may already exist. This can happen when there is another + // load from the same location and producing the same type of value + // but it has different alignment or volatileness. + bool isNewLoad = true; + SUnit *LoadSU; + if (LoadNode->getNodeId() != -1) { + LoadSU = &SUnits[LoadNode->getNodeId()]; + isNewLoad = false; + } else { + LoadSU = NewSUnit(LoadNode); + LoadNode->setNodeId(LoadSU->NodeNum); + } + + SDep ChainPred; + SmallVector ChainSuccs; + SmallVector LoadPreds; + SmallVector NodePreds; + SmallVector NodeSuccs; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainPred = *I; + else if (I->getSUnit()->getNode() && + I->getSUnit()->getNode()->isOperandOf(LoadNode)) + LoadPreds.push_back(*I); + else + NodePreds.push_back(*I); + } + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainSuccs.push_back(*I); + else + NodeSuccs.push_back(*I); + } + + if (ChainPred.getSUnit()) { + RemovePred(SU, ChainPred); + if (isNewLoad) + AddPred(LoadSU, ChainPred); + } + for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) { + const SDep &Pred = LoadPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) { + AddPred(LoadSU, Pred); + } + } + for (unsigned i = 0, e = NodePreds.size(); i != e; ++i) { + const SDep &Pred = NodePreds[i]; + RemovePred(SU, Pred); + AddPred(NewSU, Pred); + } + for (unsigned i = 0, e = NodeSuccs.size(); i != e; ++i) { + SDep D = NodeSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + D.setSUnit(NewSU); + AddPred(SuccDep, D); + } + for (unsigned i = 0, e = ChainSuccs.size(); i != e; ++i) { + SDep D = ChainSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + if (isNewLoad) { + D.setSUnit(LoadSU); + AddPred(SuccDep, D); + } + } + if (isNewLoad) { + AddPred(NewSU, SDep(LoadSU, SDep::Order, LoadSU->Latency)); + } + + ++NumUnfolds; + + if (NewSU->NumSuccsLeft == 0) { + NewSU->isAvailable = true; + return NewSU; + } + SU = NewSU; + } + + DEBUG(dbgs() << "Duplicating SU # " << SU->NodeNum << "\n"); + NewSU = Clone(SU); + + // New SUnit has the exact same predecessors. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (!I->isArtificial()) + AddPred(NewSU, *I); + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(NewSU); + AddPred(SuccSU, D); + D.setSUnit(SU); + DelDeps.push_back(std::make_pair(SuccSU, D)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + ++NumDups; + return NewSU; +} + +/// InsertCopiesAndMoveSuccs - Insert register copies and move all +/// scheduled successors of the given SUnit to the last copy. +void ScheduleDAGFast::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC, + SmallVector &Copies) { + SUnit *CopyFromSU = NewSUnit(static_cast(NULL)); + CopyFromSU->CopySrcRC = SrcRC; + CopyFromSU->CopyDstRC = DestRC; + + SUnit *CopyToSU = NewSUnit(static_cast(NULL)); + CopyToSU->CopySrcRC = DestRC; + CopyToSU->CopyDstRC = SrcRC; + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(CopyToSU); + AddPred(SuccSU, D); + DelDeps.push_back(std::make_pair(SuccSU, *I)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) { + RemovePred(DelDeps[i].first, DelDeps[i].second); + } + + AddPred(CopyFromSU, SDep(SU, SDep::Data, SU->Latency, Reg)); + AddPred(CopyToSU, SDep(CopyFromSU, SDep::Data, CopyFromSU->Latency, 0)); + + Copies.push_back(CopyFromSU); + Copies.push_back(CopyToSU); + + ++NumPRCopies; +} + +/// getPhysicalRegisterVT - Returns the ValueType of the physical register +/// definition of the specified node. +/// FIXME: Move to SelectionDAG? +static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, + const TargetInstrInfo *TII) { + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = TID.getNumDefs(); + for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + if (Reg == *ImpDef) + break; + ++NumRes; + } + return N->getValueType(NumRes); +} + +/// CheckForLiveRegDef - Return true and update live register vector if the +/// specified register def of the specified SUnit clobbers any "live" registers. +static bool CheckForLiveRegDef(SUnit *SU, unsigned Reg, + std::vector &LiveRegDefs, + SmallSet &RegAdded, + SmallVector &LRegs, + const TargetRegisterInfo *TRI) { + bool Added = false; + if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != SU) { + if (RegAdded.insert(Reg)) { + LRegs.push_back(Reg); + Added = true; + } + } + for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias) + if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != SU) { + if (RegAdded.insert(*Alias)) { + LRegs.push_back(*Alias); + Added = true; + } + } + return Added; +} + +/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay +/// scheduling of the given node to satisfy live physical register dependencies. +/// If the specific node is the last one that's available to schedule, do +/// whatever is necessary (i.e. backtracking or cloning) to make it possible. +bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU, + SmallVector &LRegs){ + if (NumLiveRegs == 0) + return false; + + SmallSet RegAdded; + // If this node would clobber any "live" register, then it's not ready. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + CheckForLiveRegDef(I->getSUnit(), I->getReg(), LiveRegDefs, + RegAdded, LRegs, TRI); + } + } + + for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) { + if (Node->getOpcode() == ISD::INLINEASM) { + // Inline asm can clobber physical defs. + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) + --NumOps; // Ignore the glue operand. + + for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { + unsigned Flags = + cast(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + + ++i; // Skip the ID value. + if (InlineAsm::isRegDefKind(Flags) || + InlineAsm::isRegDefEarlyClobberKind(Flags)) { + // Check for def of register or earlyclobber register. + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + CheckForLiveRegDef(SU, Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + } else + i += NumVals; + } + continue; + } + if (!Node->isMachineOpcode()) + continue; + const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); + if (!TID.ImplicitDefs) + continue; + for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) { + CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + } + return !LRegs.empty(); +} + + +/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up +/// schedulers. +void ScheduleDAGFast::ListScheduleBottomUp() { + unsigned CurCycle = 0; + + // Release any predecessors of the special Exit node. + ReleasePredecessors(&ExitSU, CurCycle); + + // Add root to Available queue. + if (!SUnits.empty()) { + SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()]; + assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); + RootSU->isAvailable = true; + AvailableQueue.push(RootSU); + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + SmallVector NotReady; + DenseMap > LRegsMap; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue.empty()) { + bool Delayed = false; + LRegsMap.clear(); + SUnit *CurSU = AvailableQueue.pop(); + while (CurSU) { + SmallVector LRegs; + if (!DelayForLiveRegsBottomUp(CurSU, LRegs)) + break; + Delayed = true; + LRegsMap.insert(std::make_pair(CurSU, LRegs)); + + CurSU->isPending = true; // This SU is not in AvailableQueue right now. + NotReady.push_back(CurSU); + CurSU = AvailableQueue.pop(); + } + + // All candidates are delayed due to live physical reg dependencies. + // Try code duplication or inserting cross class copies + // to resolve it. + if (Delayed && !CurSU) { + if (!CurSU) { + // Try duplicating the nodes that produces these + // "expensive to copy" values to break the dependency. In case even + // that doesn't work, insert cross class copies. + SUnit *TrySU = NotReady[0]; + SmallVector &LRegs = LRegsMap[TrySU]; + assert(LRegs.size() == 1 && "Can't handle this yet!"); + unsigned Reg = LRegs[0]; + SUnit *LRDef = LiveRegDefs[Reg]; + EVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII); + const TargetRegisterClass *RC = + TRI->getMinimalPhysRegClass(Reg, VT); + const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); + + // If cross copy register class is null, then it must be possible copy + // the value directly. Do not try duplicate the def. + SUnit *NewDef = 0; + if (DestRC) + NewDef = CopyAndMoveSuccessors(LRDef); + else + DestRC = RC; + if (!NewDef) { + // Issue copies, these can be expensive cross register class copies. + SmallVector Copies; + InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies); + DEBUG(dbgs() << "Adding an edge from SU # " << TrySU->NodeNum + << " to SU #" << Copies.front()->NodeNum << "\n"); + AddPred(TrySU, SDep(Copies.front(), SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + NewDef = Copies.back(); + } + + DEBUG(dbgs() << "Adding an edge from SU # " << NewDef->NodeNum + << " to SU #" << TrySU->NodeNum << "\n"); + LiveRegDefs[Reg] = NewDef; + AddPred(NewDef, SDep(TrySU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + TrySU->isAvailable = false; + CurSU = NewDef; + } + + if (!CurSU) { + llvm_unreachable("Unable to resolve live physical register dependencies!"); + } + } + + // Add the nodes that aren't ready back onto the available list. + for (unsigned i = 0, e = NotReady.size(); i != e; ++i) { + NotReady[i]->isPending = false; + // May no longer be available due to backtracking. + if (NotReady[i]->isAvailable) + AvailableQueue.push(NotReady[i]); + } + NotReady.clear(); + + if (CurSU) + ScheduleNodeBottomUp(CurSU, CurCycle); + ++CurCycle; + } + + // Reverse the order since it is bottom up. + std::reverse(Sequence.begin(), Sequence.end()); + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/true); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +llvm::ScheduleDAGSDNodes * +llvm::createFastDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + return new ScheduleDAGFast(*IS->MF); +} diff --git a/final/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp b/final/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp new file mode 100644 index 00000000000..430283d5eff --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp @@ -0,0 +1,265 @@ +//===---- ScheduleDAGList.cpp - Implement a list scheduler for isel DAG ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements a top-down list scheduler, using standard algorithms. +// The basic approach uses a priority queue of available nodes to schedule. +// One at a time, nodes are taken from the priority queue (thus in priority +// order), checked for legality to schedule, and emitted if legal. +// +// Nodes may not be legal to schedule either due to structural hazards (e.g. +// pipeline or resource constraints) or because an input to the instruction has +// not completed execution. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumNoops , "Number of noops inserted"); +STATISTIC(NumStalls, "Number of pipeline stalls"); + +static RegisterScheduler + tdListDAGScheduler("list-td", "Top-down list scheduler", + createTDListDAGScheduler); + +namespace { +//===----------------------------------------------------------------------===// +/// ScheduleDAGList - The actual list scheduler implementation. This supports +/// top-down scheduling. +/// +class ScheduleDAGList : public ScheduleDAGSDNodes { +private: + /// AvailableQueue - The priority queue to use for the available SUnits. + /// + SchedulingPriorityQueue *AvailableQueue; + + /// PendingQueue - This contains all of the instructions whose operands have + /// been issued, but their results are not ready yet (due to the latency of + /// the operation). Once the operands become available, the instruction is + /// added to the AvailableQueue. + std::vector PendingQueue; + + /// HazardRec - The hazard recognizer to use. + ScheduleHazardRecognizer *HazardRec; + +public: + ScheduleDAGList(MachineFunction &mf, + SchedulingPriorityQueue *availqueue) + : ScheduleDAGSDNodes(mf), AvailableQueue(availqueue) { + + const TargetMachine &tm = mf.getTarget(); + HazardRec = tm.getInstrInfo()->CreateTargetHazardRecognizer(&tm, this); + } + + ~ScheduleDAGList() { + delete HazardRec; + delete AvailableQueue; + } + + void Schedule(); + +private: + void ReleaseSucc(SUnit *SU, const SDep &D); + void ReleaseSuccessors(SUnit *SU); + void ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle); + void ListScheduleTopDown(); +}; +} // end anonymous namespace + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGList::Schedule() { + DEBUG(dbgs() << "********** List Scheduling **********\n"); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + AvailableQueue->initNodes(SUnits); + + ListScheduleTopDown(); + + AvailableQueue->releaseState(); +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the PendingQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGList::ReleaseSucc(SUnit *SU, const SDep &D) { + SUnit *SuccSU = D.getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency()); + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) + PendingQueue.push_back(SuccSU); +} + +void ScheduleDAGList::ReleaseSuccessors(SUnit *SU) { + // Top down: release successors. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + assert(!I->isAssignedRegDep() && + "The list-td scheduler doesn't yet support physreg dependencies!"); + + ReleaseSucc(SU, *I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) { + DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + Sequence.push_back(SU); + assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue->ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void ScheduleDAGList::ListScheduleTopDown() { + unsigned CurCycle = 0; + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // All leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + if (SUnits[i].Preds.empty()) { + AvailableQueue->push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + std::vector NotReady; + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty() || !PendingQueue.empty()) { + // Check to see if any of the pending instructions are ready to issue. If + // so, add them to the available queue. + for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { + if (PendingQueue[i]->getDepth() == CurCycle) { + AvailableQueue->push(PendingQueue[i]); + PendingQueue[i]->isAvailable = true; + PendingQueue[i] = PendingQueue.back(); + PendingQueue.pop_back(); + --i; --e; + } else { + assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?"); + } + } + + // If there are no instructions available, don't try to issue anything, and + // don't advance the hazard recognizer. + if (AvailableQueue->empty()) { + ++CurCycle; + continue; + } + + SUnit *FoundSUnit = 0; + + bool HasNoopHazards = false; + while (!AvailableQueue->empty()) { + SUnit *CurSUnit = AvailableQueue->pop(); + + ScheduleHazardRecognizer::HazardType HT = + HazardRec->getHazardType(CurSUnit, 0/*no stalls*/); + if (HT == ScheduleHazardRecognizer::NoHazard) { + FoundSUnit = CurSUnit; + break; + } + + // Remember if this is a noop hazard. + HasNoopHazards |= HT == ScheduleHazardRecognizer::NoopHazard; + + NotReady.push_back(CurSUnit); + } + + // Add the nodes that aren't ready back onto the available list. + if (!NotReady.empty()) { + AvailableQueue->push_all(NotReady); + NotReady.clear(); + } + + // If we found a node to schedule, do it now. + if (FoundSUnit) { + ScheduleNodeTopDown(FoundSUnit, CurCycle); + HazardRec->EmitInstruction(FoundSUnit); + + // If this is a pseudo-op node, we don't want to increment the current + // cycle. + if (FoundSUnit->Latency) // Don't increment CurCycle for pseudo-ops! + ++CurCycle; + } else if (!HasNoopHazards) { + // Otherwise, we have a pipeline stall, but no other problem, just advance + // the current cycle and try again. + DEBUG(dbgs() << "*** Advancing cycle, no work to do\n"); + HazardRec->AdvanceCycle(); + ++NumStalls; + ++CurCycle; + } else { + // Otherwise, we have no instructions to issue and we have instructions + // that will fault if we don't do this right. This is the case for + // processors without pipeline interlocks and other cases. + DEBUG(dbgs() << "*** Emitting noop\n"); + HazardRec->EmitNoop(); + Sequence.push_back(0); // NULL here means noop + ++NumNoops; + ++CurCycle; + } + } + +#ifndef NDEBUG + VerifySchedule(/*isBottomUp=*/false); +#endif +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +/// createTDListDAGScheduler - This creates a top-down list scheduler. +ScheduleDAGSDNodes * +llvm::createTDListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level) { + return new ScheduleDAGList(*IS->MF, new LatencyPriorityQueue()); +} diff --git a/final/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/final/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp new file mode 100644 index 00000000000..42d096e0490 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -0,0 +1,2715 @@ +//===----- ScheduleDAGRRList.cpp - Reg pressure reduction list scheduler --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements bottom-up and top-down register pressure reduction list +// schedulers, using standard algorithms. The basic approach uses a priority +// queue of available nodes to schedule. One at a time, nodes are taken from +// the priority queue (thus in priority order), checked for legality to +// schedule, and emitted if legal. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "ScheduleDAGSDNodes.h" +#include "llvm/InlineAsm.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +STATISTIC(NumBacktracks, "Number of times scheduler backtracked"); +STATISTIC(NumUnfolds, "Number of nodes unfolded"); +STATISTIC(NumDups, "Number of duplicated nodes"); +STATISTIC(NumPRCopies, "Number of physical register copies"); + +static RegisterScheduler + burrListDAGScheduler("list-burr", + "Bottom-up register reduction list scheduling", + createBURRListDAGScheduler); +static RegisterScheduler + tdrListrDAGScheduler("list-tdrr", + "Top-down register reduction list scheduling", + createTDRRListDAGScheduler); +static RegisterScheduler + sourceListDAGScheduler("source", + "Similar to list-burr but schedules in source " + "order when possible", + createSourceListDAGScheduler); + +static RegisterScheduler + hybridListDAGScheduler("list-hybrid", + "Bottom-up register pressure aware list scheduling " + "which tries to balance latency and register pressure", + createHybridListDAGScheduler); + +static RegisterScheduler + ILPListDAGScheduler("list-ilp", + "Bottom-up register pressure aware list scheduling " + "which tries to balance ILP and register pressure", + createILPListDAGScheduler); + +static cl::opt DisableSchedCycles( + "disable-sched-cycles", cl::Hidden, cl::init(false), + cl::desc("Disable cycle-level precision during preRA scheduling")); + +// Temporary sched=list-ilp flags until the heuristics are robust. +static cl::opt DisableSchedRegPressure( + "disable-sched-reg-pressure", cl::Hidden, cl::init(false), + cl::desc("Disable regpressure priority in sched=list-ilp")); +static cl::opt DisableSchedLiveUses( + "disable-sched-live-uses", cl::Hidden, cl::init(true), + cl::desc("Disable live use priority in sched=list-ilp")); +static cl::opt DisableSchedStalls( + "disable-sched-stalls", cl::Hidden, cl::init(true), + cl::desc("Disable no-stall priority in sched=list-ilp")); +static cl::opt DisableSchedCriticalPath( + "disable-sched-critical-path", cl::Hidden, cl::init(false), + cl::desc("Disable critical path priority in sched=list-ilp")); +static cl::opt DisableSchedHeight( + "disable-sched-height", cl::Hidden, cl::init(false), + cl::desc("Disable scheduled-height priority in sched=list-ilp")); + +static cl::opt MaxReorderWindow( + "max-sched-reorder", cl::Hidden, cl::init(6), + cl::desc("Number of instructions to allow ahead of the critical path " + "in sched=list-ilp")); + +static cl::opt AvgIPC( + "sched-avg-ipc", cl::Hidden, cl::init(1), + cl::desc("Average inst/cycle whan no target itinerary exists.")); + +#ifndef NDEBUG +namespace { + // For sched=list-ilp, Count the number of times each factor comes into play. + enum { FactPressureDiff, FactRegUses, FactHeight, FactDepth, FactStatic, + FactOther, NumFactors }; +} +static const char *FactorName[NumFactors] = +{"PressureDiff", "RegUses", "Height", "Depth","Static", "Other"}; +static int FactorCount[NumFactors]; +#endif //!NDEBUG + +namespace { +//===----------------------------------------------------------------------===// +/// ScheduleDAGRRList - The actual register reduction list scheduler +/// implementation. This supports both top-down and bottom-up scheduling. +/// +class ScheduleDAGRRList : public ScheduleDAGSDNodes { +private: + /// isBottomUp - This is true if the scheduling problem is bottom-up, false if + /// it is top-down. + bool isBottomUp; + + /// NeedLatency - True if the scheduler will make use of latency information. + /// + bool NeedLatency; + + /// AvailableQueue - The priority queue to use for the available SUnits. + SchedulingPriorityQueue *AvailableQueue; + + /// PendingQueue - This contains all of the instructions whose operands have + /// been issued, but their results are not ready yet (due to the latency of + /// the operation). Once the operands becomes available, the instruction is + /// added to the AvailableQueue. + std::vector PendingQueue; + + /// HazardRec - The hazard recognizer to use. + ScheduleHazardRecognizer *HazardRec; + + /// CurCycle - The current scheduler state corresponds to this cycle. + unsigned CurCycle; + + /// MinAvailableCycle - Cycle of the soonest available instruction. + unsigned MinAvailableCycle; + + /// IssueCount - Count instructions issued in this cycle + /// Currently valid only for bottom-up scheduling. + unsigned IssueCount; + + /// LiveRegDefs - A set of physical registers and their definition + /// that are "live". These nodes must be scheduled before any other nodes that + /// modifies the registers can be scheduled. + unsigned NumLiveRegs; + std::vector LiveRegDefs; + std::vector LiveRegGens; + + /// Topo - A topological ordering for SUnits which permits fast IsReachable + /// and similar queries. + ScheduleDAGTopologicalSort Topo; + +public: + ScheduleDAGRRList(MachineFunction &mf, bool needlatency, + SchedulingPriorityQueue *availqueue, + CodeGenOpt::Level OptLevel) + : ScheduleDAGSDNodes(mf), isBottomUp(availqueue->isBottomUp()), + NeedLatency(needlatency), AvailableQueue(availqueue), CurCycle(0), + Topo(SUnits) { + + const TargetMachine &tm = mf.getTarget(); + if (DisableSchedCycles || !NeedLatency) + HazardRec = new ScheduleHazardRecognizer(); + else + HazardRec = tm.getInstrInfo()->CreateTargetHazardRecognizer(&tm, this); + } + + ~ScheduleDAGRRList() { + delete HazardRec; + delete AvailableQueue; + } + + void Schedule(); + + ScheduleHazardRecognizer *getHazardRec() { return HazardRec; } + + /// IsReachable - Checks if SU is reachable from TargetSU. + bool IsReachable(const SUnit *SU, const SUnit *TargetSU) { + return Topo.IsReachable(SU, TargetSU); + } + + /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will + /// create a cycle. + bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) { + return Topo.WillCreateCycle(SU, TargetSU); + } + + /// AddPred - adds a predecessor edge to SUnit SU. + /// This returns true if this is a new predecessor. + /// Updates the topological ordering if required. + void AddPred(SUnit *SU, const SDep &D) { + Topo.AddPred(SU, D.getSUnit()); + SU->addPred(D); + } + + /// RemovePred - removes a predecessor edge from SUnit SU. + /// This returns true if an edge was removed. + /// Updates the topological ordering if required. + void RemovePred(SUnit *SU, const SDep &D) { + Topo.RemovePred(SU, D.getSUnit()); + SU->removePred(D); + } + +private: + bool isReady(SUnit *SU) { + return DisableSchedCycles || !AvailableQueue->hasReadyFilter() || + AvailableQueue->isReady(SU); + } + + void ReleasePred(SUnit *SU, const SDep *PredEdge); + void ReleasePredecessors(SUnit *SU); + void ReleaseSucc(SUnit *SU, const SDep *SuccEdge); + void ReleaseSuccessors(SUnit *SU); + void ReleasePending(); + void AdvanceToCycle(unsigned NextCycle); + void AdvancePastStalls(SUnit *SU); + void EmitNode(SUnit *SU); + void ScheduleNodeBottomUp(SUnit*); + void CapturePred(SDep *PredEdge); + void UnscheduleNodeBottomUp(SUnit*); + void RestoreHazardCheckerBottomUp(); + void BacktrackBottomUp(SUnit*, SUnit*); + SUnit *CopyAndMoveSuccessors(SUnit*); + void InsertCopiesAndMoveSuccs(SUnit*, unsigned, + const TargetRegisterClass*, + const TargetRegisterClass*, + SmallVector&); + bool DelayForLiveRegsBottomUp(SUnit*, SmallVector&); + + SUnit *PickNodeToScheduleBottomUp(); + void ListScheduleBottomUp(); + + void ScheduleNodeTopDown(SUnit*); + void ListScheduleTopDown(); + + + /// CreateNewSUnit - Creates a new SUnit and returns a pointer to it. + /// Updates the topological ordering if required. + SUnit *CreateNewSUnit(SDNode *N) { + unsigned NumSUnits = SUnits.size(); + SUnit *NewNode = NewSUnit(N); + // Update the topological ordering. + if (NewNode->NodeNum >= NumSUnits) + Topo.InitDAGTopologicalSorting(); + return NewNode; + } + + /// CreateClone - Creates a new SUnit from an existing one. + /// Updates the topological ordering if required. + SUnit *CreateClone(SUnit *N) { + unsigned NumSUnits = SUnits.size(); + SUnit *NewNode = Clone(N); + // Update the topological ordering. + if (NewNode->NodeNum >= NumSUnits) + Topo.InitDAGTopologicalSorting(); + return NewNode; + } + + /// ForceUnitLatencies - Register-pressure-reducing scheduling doesn't + /// need actual latency information but the hybrid scheduler does. + bool ForceUnitLatencies() const { + return !NeedLatency; + } +}; +} // end anonymous namespace + + +/// Schedule - Schedule the DAG using list scheduling. +void ScheduleDAGRRList::Schedule() { + DEBUG(dbgs() + << "********** List Scheduling BB#" << BB->getNumber() + << " '" << BB->getName() << "' **********\n"); +#ifndef NDEBUG + for (int i = 0; i < NumFactors; ++i) { + FactorCount[i] = 0; + } +#endif //!NDEBUG + + CurCycle = 0; + IssueCount = 0; + MinAvailableCycle = DisableSchedCycles ? 0 : UINT_MAX; + NumLiveRegs = 0; + LiveRegDefs.resize(TRI->getNumRegs(), NULL); + LiveRegGens.resize(TRI->getNumRegs(), NULL); + + // Build the scheduling graph. + BuildSchedGraph(NULL); + + DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + SUnits[su].dumpAll(this)); + Topo.InitDAGTopologicalSorting(); + + AvailableQueue->initNodes(SUnits); + + HazardRec->Reset(); + + // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate. + if (isBottomUp) + ListScheduleBottomUp(); + else + ListScheduleTopDown(); + +#ifndef NDEBUG + for (int i = 0; i < NumFactors; ++i) { + DEBUG(dbgs() << FactorName[i] << "\t" << FactorCount[i] << "\n"); + } +#endif // !NDEBUG + AvailableQueue->releaseState(); +} + +//===----------------------------------------------------------------------===// +// Bottom-Up Scheduling +//===----------------------------------------------------------------------===// + +/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + +#ifndef NDEBUG + if (PredSU->NumSuccsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + PredSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --PredSU->NumSuccsLeft; + + if (!ForceUnitLatencies()) { + // Updating predecessor's height. This is now the cycle when the + // predecessor can be scheduled without causing a pipeline stall. + PredSU->setHeightToAtLeast(SU->getHeight() + PredEdge->getLatency()); + } + + // If all the node's successors are scheduled, this node is ready + // to be scheduled. Ignore the special EntrySU node. + if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) { + PredSU->isAvailable = true; + + unsigned Height = PredSU->getHeight(); + if (Height < MinAvailableCycle) + MinAvailableCycle = Height; + + if (isReady(PredSU)) { + AvailableQueue->push(PredSU); + } + // CapturePred and others may have left the node in the pending queue, avoid + // adding it twice. + else if (!PredSU->isPending) { + PredSU->isPending = true; + PendingQueue.push_back(PredSU); + } + } +} + +/// Call ReleasePred for each predecessor, then update register live def/gen. +/// Always update LiveRegDefs for a register dependence even if the current SU +/// also defines the register. This effectively create one large live range +/// across a sequence of two-address node. This is important because the +/// entire chain must be scheduled together. Example: +/// +/// flags = (3) add +/// flags = (2) addc flags +/// flags = (1) addc flags +/// +/// results in +/// +/// LiveRegDefs[flags] = 3 +/// LiveRegGens[flags] = 1 +/// +/// If (2) addc is unscheduled, then (1) addc must also be unscheduled to avoid +/// interference on flags. +void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) { + // Bottom up: release predecessors + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + ReleasePred(SU, &*I); + if (I->isAssignedRegDep()) { + // This is a physical register dependency and it's impossible or + // expensive to copy the register. Make sure nothing that can + // clobber the register is scheduled between the predecessor and + // this node. + SUnit *RegDef = LiveRegDefs[I->getReg()]; (void)RegDef; + assert((!RegDef || RegDef == SU || RegDef == I->getSUnit()) && + "interference on register dependence"); + LiveRegDefs[I->getReg()] = I->getSUnit(); + if (!LiveRegGens[I->getReg()]) { + ++NumLiveRegs; + LiveRegGens[I->getReg()] = SU; + } + } + } +} + +/// Check to see if any of the pending instructions are ready to issue. If +/// so, add them to the available queue. +void ScheduleDAGRRList::ReleasePending() { + if (DisableSchedCycles) { + assert(PendingQueue.empty() && "pending instrs not allowed in this mode"); + return; + } + + // If the available queue is empty, it is safe to reset MinAvailableCycle. + if (AvailableQueue->empty()) + MinAvailableCycle = UINT_MAX; + + // Check to see if any of the pending instructions are ready to issue. If + // so, add them to the available queue. + for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) { + unsigned ReadyCycle = + isBottomUp ? PendingQueue[i]->getHeight() : PendingQueue[i]->getDepth(); + if (ReadyCycle < MinAvailableCycle) + MinAvailableCycle = ReadyCycle; + + if (PendingQueue[i]->isAvailable) { + if (!isReady(PendingQueue[i])) + continue; + AvailableQueue->push(PendingQueue[i]); + } + PendingQueue[i]->isPending = false; + PendingQueue[i] = PendingQueue.back(); + PendingQueue.pop_back(); + --i; --e; + } +} + +/// Move the scheduler state forward by the specified number of Cycles. +void ScheduleDAGRRList::AdvanceToCycle(unsigned NextCycle) { + if (NextCycle <= CurCycle) + return; + + IssueCount = 0; + AvailableQueue->setCurCycle(NextCycle); + if (!HazardRec->isEnabled()) { + // Bypass lots of virtual calls in case of long latency. + CurCycle = NextCycle; + } + else { + for (; CurCycle != NextCycle; ++CurCycle) { + if (isBottomUp) + HazardRec->RecedeCycle(); + else + HazardRec->AdvanceCycle(); + } + } + // FIXME: Instead of visiting the pending Q each time, set a dirty flag on the + // available Q to release pending nodes at least once before popping. + ReleasePending(); +} + +/// Move the scheduler state forward until the specified node's dependents are +/// ready and can be scheduled with no resource conflicts. +void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) { + if (DisableSchedCycles) + return; + + unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth(); + + // Bump CurCycle to account for latency. We assume the latency of other + // available instructions may be hidden by the stall (not a full pipe stall). + // This updates the hazard recognizer's cycle before reserving resources for + // this instruction. + AdvanceToCycle(ReadyCycle); + + // Calls are scheduled in their preceding cycle, so don't conflict with + // hazards from instructions after the call. EmitNode will reset the + // scoreboard state before emitting the call. + if (isBottomUp && SU->isCall) + return; + + // FIXME: For resource conflicts in very long non-pipelined stages, we + // should probably skip ahead here to avoid useless scoreboard checks. + int Stalls = 0; + while (true) { + ScheduleHazardRecognizer::HazardType HT = + HazardRec->getHazardType(SU, isBottomUp ? -Stalls : Stalls); + + if (HT == ScheduleHazardRecognizer::NoHazard) + break; + + ++Stalls; + } + AdvanceToCycle(CurCycle + Stalls); +} + +/// Record this SUnit in the HazardRecognizer. +/// Does not update CurCycle. +void ScheduleDAGRRList::EmitNode(SUnit *SU) { + if (!HazardRec->isEnabled()) + return; + + // Check for phys reg copy. + if (!SU->getNode()) + return; + + switch (SU->getNode()->getOpcode()) { + default: + assert(SU->getNode()->isMachineOpcode() && + "This target-independent node should not be scheduled."); + break; + case ISD::MERGE_VALUES: + case ISD::TokenFactor: + case ISD::CopyToReg: + case ISD::CopyFromReg: + case ISD::EH_LABEL: + // Noops don't affect the scoreboard state. Copies are likely to be + // removed. + return; + case ISD::INLINEASM: + // For inline asm, clear the pipeline state. + HazardRec->Reset(); + return; + } + if (isBottomUp && SU->isCall) { + // Calls are scheduled with their preceding instructions. For bottom-up + // scheduling, clear the pipeline state before emitting. + HazardRec->Reset(); + } + + HazardRec->EmitInstruction(SU); + + if (!isBottomUp && SU->isCall) { + HazardRec->Reset(); + } +} + +/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending +/// count of its predecessors. If a predecessor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { + DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + +#ifndef NDEBUG + if (CurCycle < SU->getHeight()) + DEBUG(dbgs() << " Height [" << SU->getHeight() << "] pipeline stall!\n"); +#endif + + // FIXME: Do not modify node height. It may interfere with + // backtracking. Instead add a "ready cycle" to SUnit. Before scheduling the + // node it's ready cycle can aid heuristics, and after scheduling it can + // indicate the scheduled cycle. + SU->setHeightToAtLeast(CurCycle); + + // Reserve resources for the scheduled intruction. + EmitNode(SU); + + Sequence.push_back(SU); + + AvailableQueue->ScheduledNode(SU); + + // If HazardRec is disabled, and each inst counts as one cycle, then + // advance CurCycle before ReleasePredecessors to avoid useles pushed to + // PendingQueue for schedulers that implement HasReadyFilter. + if (!HazardRec->isEnabled() && AvgIPC < 2) + AdvanceToCycle(CurCycle + 1); + + // Update liveness of predecessors before successors to avoid treating a + // two-address node as a live range def. + ReleasePredecessors(SU); + + // Release all the implicit physical register defs that are live. + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + // LiveRegDegs[I->getReg()] != SU when SU is a two-address node. + if (I->isAssignedRegDep() && LiveRegDefs[I->getReg()] == SU) { + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegGens[I->getReg()] = NULL; + } + } + + SU->isScheduled = true; + + // Conditions under which the scheduler should eagerly advance the cycle: + // (1) No available instructions + // (2) All pipelines full, so available instructions must have hazards. + // + // If HazardRec is disabled, the cycle was advanced earlier. + // + // Check AvailableQueue after ReleasePredecessors in case of zero latency. + ++IssueCount; + if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) + || (!HazardRec->isEnabled() && AvgIPC > 1 && IssueCount == AvgIPC) + || AvailableQueue->empty()) + AdvanceToCycle(CurCycle + 1); +} + +/// CapturePred - This does the opposite of ReleasePred. Since SU is being +/// unscheduled, incrcease the succ left count of its predecessors. Remove +/// them from AvailableQueue if necessary. +void ScheduleDAGRRList::CapturePred(SDep *PredEdge) { + SUnit *PredSU = PredEdge->getSUnit(); + if (PredSU->isAvailable) { + PredSU->isAvailable = false; + if (!PredSU->isPending) + AvailableQueue->remove(PredSU); + } + + assert(PredSU->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); + ++PredSU->NumSuccsLeft; +} + +/// UnscheduleNodeBottomUp - Remove the node from the schedule, update its and +/// its predecessor states to reflect the change. +void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) { + DEBUG(dbgs() << "*** Unscheduling [" << SU->getHeight() << "]: "); + DEBUG(SU->dump(this)); + + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + CapturePred(&*I); + if (I->isAssignedRegDep() && SU == LiveRegGens[I->getReg()]){ + assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!"); + assert(LiveRegDefs[I->getReg()] == I->getSUnit() && + "Physical register dependency violated?"); + --NumLiveRegs; + LiveRegDefs[I->getReg()] = NULL; + LiveRegGens[I->getReg()] = NULL; + } + } + + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isAssignedRegDep()) { + // This becomes the nearest def. Note that an earlier def may still be + // pending if this is a two-address node. + LiveRegDefs[I->getReg()] = SU; + if (!LiveRegDefs[I->getReg()]) { + ++NumLiveRegs; + } + if (LiveRegGens[I->getReg()] == NULL || + I->getSUnit()->getHeight() < LiveRegGens[I->getReg()]->getHeight()) + LiveRegGens[I->getReg()] = I->getSUnit(); + } + } + if (SU->getHeight() < MinAvailableCycle) + MinAvailableCycle = SU->getHeight(); + + SU->setHeightDirty(); + SU->isScheduled = false; + SU->isAvailable = true; + if (!DisableSchedCycles && AvailableQueue->hasReadyFilter()) { + // Don't make available until backtracking is complete. + SU->isPending = true; + PendingQueue.push_back(SU); + } + else { + AvailableQueue->push(SU); + } + AvailableQueue->UnscheduledNode(SU); +} + +/// After backtracking, the hazard checker needs to be restored to a state +/// corresponding the the current cycle. +void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() { + HazardRec->Reset(); + + unsigned LookAhead = std::min((unsigned)Sequence.size(), + HazardRec->getMaxLookAhead()); + if (LookAhead == 0) + return; + + std::vector::const_iterator I = (Sequence.end() - LookAhead); + unsigned HazardCycle = (*I)->getHeight(); + for (std::vector::const_iterator E = Sequence.end(); I != E; ++I) { + SUnit *SU = *I; + for (; SU->getHeight() > HazardCycle; ++HazardCycle) { + HazardRec->RecedeCycle(); + } + EmitNode(SU); + } +} + +/// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in +/// BTCycle in order to schedule a specific node. +void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) { + SUnit *OldSU = Sequence.back(); + while (true) { + Sequence.pop_back(); + if (SU->isSucc(OldSU)) + // Don't try to remove SU from AvailableQueue. + SU->isAvailable = false; + // FIXME: use ready cycle instead of height + CurCycle = OldSU->getHeight(); + UnscheduleNodeBottomUp(OldSU); + AvailableQueue->setCurCycle(CurCycle); + if (OldSU == BtSU) + break; + OldSU = Sequence.back(); + } + + assert(!SU->isSucc(OldSU) && "Something is wrong!"); + + RestoreHazardCheckerBottomUp(); + + ReleasePending(); + + ++NumBacktracks; +} + +static bool isOperandOf(const SUnit *SU, SDNode *N) { + for (const SDNode *SUNode = SU->getNode(); SUNode; + SUNode = SUNode->getGluedNode()) { + if (SUNode->isOperandOf(N)) + return true; + } + return false; +} + +/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled +/// successors to the newly created node. +SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) { + SDNode *N = SU->getNode(); + if (!N) + return NULL; + + if (SU->getNode()->getGluedNode()) + return NULL; + + SUnit *NewSU; + bool TryUnfold = false; + for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Glue) + return NULL; + else if (VT == MVT::Other) + TryUnfold = true; + } + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDValue &Op = N->getOperand(i); + EVT VT = Op.getNode()->getValueType(Op.getResNo()); + if (VT == MVT::Glue) + return NULL; + } + + if (TryUnfold) { + SmallVector NewNodes; + if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes)) + return NULL; + + DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n"); + assert(NewNodes.size() == 2 && "Expected a load folding node!"); + + N = NewNodes[1]; + SDNode *LoadNode = NewNodes[0]; + unsigned NumVals = N->getNumValues(); + unsigned OldNumVals = SU->getNode()->getNumValues(); + for (unsigned i = 0; i != NumVals; ++i) + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i)); + DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals-1), + SDValue(LoadNode, 1)); + + // LoadNode may already exist. This can happen when there is another + // load from the same location and producing the same type of value + // but it has different alignment or volatileness. + bool isNewLoad = true; + SUnit *LoadSU; + if (LoadNode->getNodeId() != -1) { + LoadSU = &SUnits[LoadNode->getNodeId()]; + isNewLoad = false; + } else { + LoadSU = CreateNewSUnit(LoadNode); + LoadNode->setNodeId(LoadSU->NodeNum); + + InitNumRegDefsLeft(LoadSU); + ComputeLatency(LoadSU); + } + + SUnit *NewSU = CreateNewSUnit(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NewSU->NodeNum); + + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + NewSU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + NewSU->isCommutable = true; + + InitNumRegDefsLeft(NewSU); + ComputeLatency(NewSU); + + // Record all the edges to and from the old SU, by category. + SmallVector ChainPreds; + SmallVector ChainSuccs; + SmallVector LoadPreds; + SmallVector NodePreds; + SmallVector NodeSuccs; + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainPreds.push_back(*I); + else if (isOperandOf(I->getSUnit(), LoadNode)) + LoadPreds.push_back(*I); + else + NodePreds.push_back(*I); + } + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) + ChainSuccs.push_back(*I); + else + NodeSuccs.push_back(*I); + } + + // Now assign edges to the newly-created nodes. + for (unsigned i = 0, e = ChainPreds.size(); i != e; ++i) { + const SDep &Pred = ChainPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) + AddPred(LoadSU, Pred); + } + for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) { + const SDep &Pred = LoadPreds[i]; + RemovePred(SU, Pred); + if (isNewLoad) + AddPred(LoadSU, Pred); + } + for (unsigned i = 0, e = NodePreds.size(); i != e; ++i) { + const SDep &Pred = NodePreds[i]; + RemovePred(SU, Pred); + AddPred(NewSU, Pred); + } + for (unsigned i = 0, e = NodeSuccs.size(); i != e; ++i) { + SDep D = NodeSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + D.setSUnit(NewSU); + AddPred(SuccDep, D); + // Balance register pressure. + if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled + && !D.isCtrl() && NewSU->NumRegDefsLeft > 0) + --NewSU->NumRegDefsLeft; + } + for (unsigned i = 0, e = ChainSuccs.size(); i != e; ++i) { + SDep D = ChainSuccs[i]; + SUnit *SuccDep = D.getSUnit(); + D.setSUnit(SU); + RemovePred(SuccDep, D); + if (isNewLoad) { + D.setSUnit(LoadSU); + AddPred(SuccDep, D); + } + } + + // Add a data dependency to reflect that NewSU reads the value defined + // by LoadSU. + AddPred(NewSU, SDep(LoadSU, SDep::Data, LoadSU->Latency)); + + if (isNewLoad) + AvailableQueue->addNode(LoadSU); + AvailableQueue->addNode(NewSU); + + ++NumUnfolds; + + if (NewSU->NumSuccsLeft == 0) { + NewSU->isAvailable = true; + return NewSU; + } + SU = NewSU; + } + + DEBUG(dbgs() << " Duplicating SU #" << SU->NodeNum << "\n"); + NewSU = CreateClone(SU); + + // New SUnit has the exact same predecessors. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (!I->isArtificial()) + AddPred(NewSU, *I); + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(NewSU); + AddPred(SuccSU, D); + D.setSUnit(SU); + DelDeps.push_back(std::make_pair(SuccSU, D)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + AvailableQueue->updateNode(SU); + AvailableQueue->addNode(NewSU); + + ++NumDups; + return NewSU; +} + +/// InsertCopiesAndMoveSuccs - Insert register copies and move all +/// scheduled successors of the given SUnit to the last copy. +void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC, + SmallVector &Copies) { + SUnit *CopyFromSU = CreateNewSUnit(NULL); + CopyFromSU->CopySrcRC = SrcRC; + CopyFromSU->CopyDstRC = DestRC; + + SUnit *CopyToSU = CreateNewSUnit(NULL); + CopyToSU->CopySrcRC = DestRC; + CopyToSU->CopyDstRC = SrcRC; + + // Only copy scheduled successors. Cut them from old node's successor + // list and move them over. + SmallVector, 4> DelDeps; + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isArtificial()) + continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU->isScheduled) { + SDep D = *I; + D.setSUnit(CopyToSU); + AddPred(SuccSU, D); + DelDeps.push_back(std::make_pair(SuccSU, *I)); + } + } + for (unsigned i = 0, e = DelDeps.size(); i != e; ++i) + RemovePred(DelDeps[i].first, DelDeps[i].second); + + AddPred(CopyFromSU, SDep(SU, SDep::Data, SU->Latency, Reg)); + AddPred(CopyToSU, SDep(CopyFromSU, SDep::Data, CopyFromSU->Latency, 0)); + + AvailableQueue->updateNode(SU); + AvailableQueue->addNode(CopyFromSU); + AvailableQueue->addNode(CopyToSU); + Copies.push_back(CopyFromSU); + Copies.push_back(CopyToSU); + + ++NumPRCopies; +} + +/// getPhysicalRegisterVT - Returns the ValueType of the physical register +/// definition of the specified node. +/// FIXME: Move to SelectionDAG? +static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, + const TargetInstrInfo *TII) { + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!"); + unsigned NumRes = TID.getNumDefs(); + for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) { + if (Reg == *ImpDef) + break; + ++NumRes; + } + return N->getValueType(NumRes); +} + +/// CheckForLiveRegDef - Return true and update live register vector if the +/// specified register def of the specified SUnit clobbers any "live" registers. +static void CheckForLiveRegDef(SUnit *SU, unsigned Reg, + std::vector &LiveRegDefs, + SmallSet &RegAdded, + SmallVector &LRegs, + const TargetRegisterInfo *TRI) { + for (const unsigned *AliasI = TRI->getOverlaps(Reg); *AliasI; ++AliasI) { + + // Check if Ref is live. + if (!LiveRegDefs[Reg]) continue; + + // Allow multiple uses of the same def. + if (LiveRegDefs[Reg] == SU) continue; + + // Add Reg to the set of interfering live regs. + if (RegAdded.insert(Reg)) + LRegs.push_back(Reg); + } +} + +/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay +/// scheduling of the given node to satisfy live physical register dependencies. +/// If the specific node is the last one that's available to schedule, do +/// whatever is necessary (i.e. backtracking or cloning) to make it possible. +bool ScheduleDAGRRList:: +DelayForLiveRegsBottomUp(SUnit *SU, SmallVector &LRegs) { + if (NumLiveRegs == 0) + return false; + + SmallSet RegAdded; + // If this node would clobber any "live" register, then it's not ready. + // + // If SU is the currently live definition of the same register that it uses, + // then we are free to schedule it. + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isAssignedRegDep() && LiveRegDefs[I->getReg()] != SU) + CheckForLiveRegDef(I->getSUnit(), I->getReg(), LiveRegDefs, + RegAdded, LRegs, TRI); + } + + for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) { + if (Node->getOpcode() == ISD::INLINEASM) { + // Inline asm can clobber physical defs. + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) + --NumOps; // Ignore the glue operand. + + for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { + unsigned Flags = + cast(Node->getOperand(i))->getZExtValue(); + unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); + + ++i; // Skip the ID value. + if (InlineAsm::isRegDefKind(Flags) || + InlineAsm::isRegDefEarlyClobberKind(Flags)) { + // Check for def of register or earlyclobber register. + for (; NumVals; --NumVals, ++i) { + unsigned Reg = cast(Node->getOperand(i))->getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + CheckForLiveRegDef(SU, Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + } else + i += NumVals; + } + continue; + } + + if (!Node->isMachineOpcode()) + continue; + const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode()); + if (!TID.ImplicitDefs) + continue; + for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) + CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI); + } + + return !LRegs.empty(); +} + +/// Return a node that can be scheduled in this cycle. Requirements: +/// (1) Ready: latency has been satisfied +/// (2) No Hazards: resources are available +/// (3) No Interferences: may unschedule to break register interferences. +SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() { + SmallVector Interferences; + DenseMap > LRegsMap; + + SUnit *CurSU = AvailableQueue->pop(); + while (CurSU) { + SmallVector LRegs; + if (!DelayForLiveRegsBottomUp(CurSU, LRegs)) + break; + LRegsMap.insert(std::make_pair(CurSU, LRegs)); + + CurSU->isPending = true; // This SU is not in AvailableQueue right now. + Interferences.push_back(CurSU); + CurSU = AvailableQueue->pop(); + } + if (CurSU) { + // Add the nodes that aren't ready back onto the available list. + for (unsigned i = 0, e = Interferences.size(); i != e; ++i) { + Interferences[i]->isPending = false; + assert(Interferences[i]->isAvailable && "must still be available"); + AvailableQueue->push(Interferences[i]); + } + return CurSU; + } + + // All candidates are delayed due to live physical reg dependencies. + // Try backtracking, code duplication, or inserting cross class copies + // to resolve it. + for (unsigned i = 0, e = Interferences.size(); i != e; ++i) { + SUnit *TrySU = Interferences[i]; + SmallVector &LRegs = LRegsMap[TrySU]; + + // Try unscheduling up to the point where it's safe to schedule + // this node. + SUnit *BtSU = NULL; + unsigned LiveCycle = UINT_MAX; + for (unsigned j = 0, ee = LRegs.size(); j != ee; ++j) { + unsigned Reg = LRegs[j]; + if (LiveRegGens[Reg]->getHeight() < LiveCycle) { + BtSU = LiveRegGens[Reg]; + LiveCycle = BtSU->getHeight(); + } + } + if (!WillCreateCycle(TrySU, BtSU)) { + BacktrackBottomUp(TrySU, BtSU); + + // Force the current node to be scheduled before the node that + // requires the physical reg dep. + if (BtSU->isAvailable) { + BtSU->isAvailable = false; + if (!BtSU->isPending) + AvailableQueue->remove(BtSU); + } + AddPred(TrySU, SDep(BtSU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, /*isArtificial=*/true)); + + // If one or more successors has been unscheduled, then the current + // node is no longer avaialable. Schedule a successor that's now + // available instead. + if (!TrySU->isAvailable) { + CurSU = AvailableQueue->pop(); + } + else { + CurSU = TrySU; + TrySU->isPending = false; + Interferences.erase(Interferences.begin()+i); + } + break; + } + } + + if (!CurSU) { + // Can't backtrack. If it's too expensive to copy the value, then try + // duplicate the nodes that produces these "too expensive to copy" + // values to break the dependency. In case even that doesn't work, + // insert cross class copies. + // If it's not too expensive, i.e. cost != -1, issue copies. + SUnit *TrySU = Interferences[0]; + SmallVector &LRegs = LRegsMap[TrySU]; + assert(LRegs.size() == 1 && "Can't handle this yet!"); + unsigned Reg = LRegs[0]; + SUnit *LRDef = LiveRegDefs[Reg]; + EVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII); + const TargetRegisterClass *RC = + TRI->getMinimalPhysRegClass(Reg, VT); + const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC); + + // If cross copy register class is null, then it must be possible copy + // the value directly. Do not try duplicate the def. + SUnit *NewDef = 0; + if (DestRC) + NewDef = CopyAndMoveSuccessors(LRDef); + else + DestRC = RC; + if (!NewDef) { + // Issue copies, these can be expensive cross register class copies. + SmallVector Copies; + InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies); + DEBUG(dbgs() << " Adding an edge from SU #" << TrySU->NodeNum + << " to SU #" << Copies.front()->NodeNum << "\n"); + AddPred(TrySU, SDep(Copies.front(), SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + NewDef = Copies.back(); + } + + DEBUG(dbgs() << " Adding an edge from SU #" << NewDef->NodeNum + << " to SU #" << TrySU->NodeNum << "\n"); + LiveRegDefs[Reg] = NewDef; + AddPred(NewDef, SDep(TrySU, SDep::Order, /*Latency=*/1, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + TrySU->isAvailable = false; + CurSU = NewDef; + } + + assert(CurSU && "Unable to resolve live physical register dependencies!"); + + // Add the nodes that aren't ready back onto the available list. + for (unsigned i = 0, e = Interferences.size(); i != e; ++i) { + Interferences[i]->isPending = false; + // May no longer be available due to backtracking. + if (Interferences[i]->isAvailable) { + AvailableQueue->push(Interferences[i]); + } + } + return CurSU; +} + +/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up +/// schedulers. +void ScheduleDAGRRList::ListScheduleBottomUp() { + // Release any predecessors of the special Exit node. + ReleasePredecessors(&ExitSU); + + // Add root to Available queue. + if (!SUnits.empty()) { + SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()]; + assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); + RootSU->isAvailable = true; + AvailableQueue->push(RootSU); + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty()) { + DEBUG(dbgs() << "\n*** Examining Available\n"; + AvailableQueue->dump(this)); + + // Pick the best node to schedule taking all constraints into + // consideration. + SUnit *SU = PickNodeToScheduleBottomUp(); + + AdvancePastStalls(SU); + + ScheduleNodeBottomUp(SU); + + while (AvailableQueue->empty() && !PendingQueue.empty()) { + // Advance the cycle to free resources. Skip ahead to the next ready SU. + assert(MinAvailableCycle < UINT_MAX && "MinAvailableCycle uninitialized"); + AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle)); + } + } + + // Reverse the order if it is bottom up. + std::reverse(Sequence.begin(), Sequence.end()); + +#ifndef NDEBUG + VerifySchedule(isBottomUp); +#endif +} + +//===----------------------------------------------------------------------===// +// Top-Down Scheduling +//===----------------------------------------------------------------------===// + +/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to +/// the AvailableQueue if the count reaches zero. Also update its cycle bound. +void ScheduleDAGRRList::ReleaseSucc(SUnit *SU, const SDep *SuccEdge) { + SUnit *SuccSU = SuccEdge->getSUnit(); + +#ifndef NDEBUG + if (SuccSU->NumPredsLeft == 0) { + dbgs() << "*** Scheduling failed! ***\n"; + SuccSU->dump(this); + dbgs() << " has been released too many times!\n"; + llvm_unreachable(0); + } +#endif + --SuccSU->NumPredsLeft; + + // If all the node's predecessors are scheduled, this node is ready + // to be scheduled. Ignore the special ExitSU node. + if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) { + SuccSU->isAvailable = true; + AvailableQueue->push(SuccSU); + } +} + +void ScheduleDAGRRList::ReleaseSuccessors(SUnit *SU) { + // Top down: release successors + for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + assert(!I->isAssignedRegDep() && + "The list-tdrr scheduler doesn't yet support physreg dependencies!"); + + ReleaseSucc(SU, &*I); + } +} + +/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending +/// count of its successors. If a successor pending count is zero, add it to +/// the Available queue. +void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU) { + DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(SU->dump(this)); + + assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!"); + SU->setDepthToAtLeast(CurCycle); + Sequence.push_back(SU); + + ReleaseSuccessors(SU); + SU->isScheduled = true; + AvailableQueue->ScheduledNode(SU); +} + +/// ListScheduleTopDown - The main loop of list scheduling for top-down +/// schedulers. +void ScheduleDAGRRList::ListScheduleTopDown() { + AvailableQueue->setCurCycle(CurCycle); + + // Release any successors of the special Entry node. + ReleaseSuccessors(&EntrySU); + + // All leaves to Available queue. + for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { + // It is available if it has no predecessors. + if (SUnits[i].Preds.empty()) { + AvailableQueue->push(&SUnits[i]); + SUnits[i].isAvailable = true; + } + } + + // While Available queue is not empty, grab the node with the highest + // priority. If it is not ready put it back. Schedule the node. + Sequence.reserve(SUnits.size()); + while (!AvailableQueue->empty()) { + SUnit *CurSU = AvailableQueue->pop(); + + if (CurSU) + ScheduleNodeTopDown(CurSU); + ++CurCycle; + AvailableQueue->setCurCycle(CurCycle); + } + +#ifndef NDEBUG + VerifySchedule(isBottomUp); +#endif +} + + +//===----------------------------------------------------------------------===// +// RegReductionPriorityQueue Definition +//===----------------------------------------------------------------------===// +// +// This is a SchedulingPriorityQueue that schedules using Sethi Ullman numbers +// to reduce register pressure. +// +namespace { +class RegReductionPQBase; + +struct queue_sort : public std::binary_function { + bool isReady(SUnit* SU, unsigned CurCycle) const { return true; } +}; + +/// bu_ls_rr_sort - Priority function for bottom up register pressure +// reduction scheduler. +struct bu_ls_rr_sort : public queue_sort { + enum { + IsBottomUp = true, + HasReadyFilter = false + }; + + RegReductionPQBase *SPQ; + bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} + bu_ls_rr_sort(const bu_ls_rr_sort &RHS) : SPQ(RHS.SPQ) {} + + bool operator()(SUnit* left, SUnit* right) const; +}; + +// td_ls_rr_sort - Priority function for top down register pressure reduction +// scheduler. +struct td_ls_rr_sort : public queue_sort { + enum { + IsBottomUp = false, + HasReadyFilter = false + }; + + RegReductionPQBase *SPQ; + td_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {} + td_ls_rr_sort(const td_ls_rr_sort &RHS) : SPQ(RHS.SPQ) {} + + bool operator()(const SUnit* left, const SUnit* right) const; +}; + +// src_ls_rr_sort - Priority function for source order scheduler. +struct src_ls_rr_sort : public queue_sort { + enum { + IsBottomUp = true, + HasReadyFilter = false + }; + + RegReductionPQBase *SPQ; + src_ls_rr_sort(RegReductionPQBase *spq) + : SPQ(spq) {} + src_ls_rr_sort(const src_ls_rr_sort &RHS) + : SPQ(RHS.SPQ) {} + + bool operator()(SUnit* left, SUnit* right) const; +}; + +// hybrid_ls_rr_sort - Priority function for hybrid scheduler. +struct hybrid_ls_rr_sort : public queue_sort { + enum { + IsBottomUp = true, + HasReadyFilter = false + }; + + RegReductionPQBase *SPQ; + hybrid_ls_rr_sort(RegReductionPQBase *spq) + : SPQ(spq) {} + hybrid_ls_rr_sort(const hybrid_ls_rr_sort &RHS) + : SPQ(RHS.SPQ) {} + + bool isReady(SUnit *SU, unsigned CurCycle) const; + + bool operator()(SUnit* left, SUnit* right) const; +}; + +// ilp_ls_rr_sort - Priority function for ILP (instruction level parallelism) +// scheduler. +struct ilp_ls_rr_sort : public queue_sort { + enum { + IsBottomUp = true, + HasReadyFilter = false + }; + + RegReductionPQBase *SPQ; + ilp_ls_rr_sort(RegReductionPQBase *spq) + : SPQ(spq) {} + ilp_ls_rr_sort(const ilp_ls_rr_sort &RHS) + : SPQ(RHS.SPQ) {} + + bool isReady(SUnit *SU, unsigned CurCycle) const; + + bool operator()(SUnit* left, SUnit* right) const; +}; + +class RegReductionPQBase : public SchedulingPriorityQueue { +protected: + std::vector Queue; + unsigned CurQueueId; + bool TracksRegPressure; + + // SUnits - The SUnits for the current graph. + std::vector *SUnits; + + MachineFunction &MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const TargetLowering *TLI; + ScheduleDAGRRList *scheduleDAG; + + // SethiUllmanNumbers - The SethiUllman number for each node. + std::vector SethiUllmanNumbers; + + /// RegPressure - Tracking current reg pressure per register class. + /// + std::vector RegPressure; + + /// RegLimit - Tracking the number of allocatable registers per register + /// class. + std::vector RegLimit; + +public: + RegReductionPQBase(MachineFunction &mf, + bool hasReadyFilter, + bool tracksrp, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + const TargetLowering *tli) + : SchedulingPriorityQueue(hasReadyFilter), + CurQueueId(0), TracksRegPressure(tracksrp), + MF(mf), TII(tii), TRI(tri), TLI(tli), scheduleDAG(NULL) { + if (TracksRegPressure) { + unsigned NumRC = TRI->getNumRegClasses(); + RegLimit.resize(NumRC); + RegPressure.resize(NumRC); + std::fill(RegLimit.begin(), RegLimit.end(), 0); + std::fill(RegPressure.begin(), RegPressure.end(), 0); + for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), + E = TRI->regclass_end(); I != E; ++I) + RegLimit[(*I)->getID()] = tri->getRegPressureLimit(*I, MF); + } + } + + void setScheduleDAG(ScheduleDAGRRList *scheduleDag) { + scheduleDAG = scheduleDag; + } + + ScheduleHazardRecognizer* getHazardRec() { + return scheduleDAG->getHazardRec(); + } + + void initNodes(std::vector &sunits); + + void addNode(const SUnit *SU); + + void updateNode(const SUnit *SU); + + void releaseState() { + SUnits = 0; + SethiUllmanNumbers.clear(); + std::fill(RegPressure.begin(), RegPressure.end(), 0); + } + + unsigned getNodePriority(const SUnit *SU) const; + + unsigned getNodeOrdering(const SUnit *SU) const { + return scheduleDAG->DAG->GetOrdering(SU->getNode()); + } + + bool empty() const { return Queue.empty(); } + + void push(SUnit *U) { + assert(!U->NodeQueueId && "Node in the queue already"); + U->NodeQueueId = ++CurQueueId; + Queue.push_back(U); + } + + void remove(SUnit *SU) { + assert(!Queue.empty() && "Queue is empty!"); + assert(SU->NodeQueueId != 0 && "Not in queue!"); + std::vector::iterator I = std::find(Queue.begin(), Queue.end(), + SU); + if (I != prior(Queue.end())) + std::swap(*I, Queue.back()); + Queue.pop_back(); + SU->NodeQueueId = 0; + } + + bool tracksRegPressure() const { return TracksRegPressure; } + + void dumpRegPressure() const; + + bool HighRegPressure(const SUnit *SU) const; + + bool MayReduceRegPressure(SUnit *SU) const; + + int RegPressureDiff(SUnit *SU, unsigned &LiveUses) const; + + void ScheduledNode(SUnit *SU); + + void UnscheduledNode(SUnit *SU); + +protected: + bool canClobber(const SUnit *SU, const SUnit *Op); + void AddPseudoTwoAddrDeps(); + void PrescheduleNodesWithMultipleUses(); + void CalculateSethiUllmanNumbers(); +}; + +template +class RegReductionPriorityQueue : public RegReductionPQBase { + static SUnit *popFromQueue(std::vector &Q, SF &Picker) { + std::vector::iterator Best = Q.begin(); + for (std::vector::iterator I = llvm::next(Q.begin()), + E = Q.end(); I != E; ++I) + if (Picker(*Best, *I)) + Best = I; + SUnit *V = *Best; + if (Best != prior(Q.end())) + std::swap(*Best, Q.back()); + Q.pop_back(); + return V; + } + + SF Picker; + +public: + RegReductionPriorityQueue(MachineFunction &mf, + bool tracksrp, + const TargetInstrInfo *tii, + const TargetRegisterInfo *tri, + const TargetLowering *tli) + : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, tii, tri, tli), + Picker(this) {} + + bool isBottomUp() const { return SF::IsBottomUp; } + + bool isReady(SUnit *U) const { + return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle()); + } + + SUnit *pop() { + if (Queue.empty()) return NULL; + + SUnit *V = popFromQueue(Queue, Picker); + V->NodeQueueId = 0; + return V; + } + + void dump(ScheduleDAG *DAG) const { + // Emulate pop() without clobbering NodeQueueIds. + std::vector DumpQueue = Queue; + SF DumpPicker = Picker; + while (!DumpQueue.empty()) { + SUnit *SU = popFromQueue(DumpQueue, DumpPicker); + if (isBottomUp()) + dbgs() << "Height " << SU->getHeight() << ": "; + else + dbgs() << "Depth " << SU->getDepth() << ": "; + SU->dump(DAG); + } + } +}; + +typedef RegReductionPriorityQueue +BURegReductionPriorityQueue; + +typedef RegReductionPriorityQueue +TDRegReductionPriorityQueue; + +typedef RegReductionPriorityQueue +SrcRegReductionPriorityQueue; + +typedef RegReductionPriorityQueue +HybridBURRPriorityQueue; + +typedef RegReductionPriorityQueue +ILPBURRPriorityQueue; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Static Node Priority for Register Pressure Reduction +//===----------------------------------------------------------------------===// + +/// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. +/// Smaller number is the higher priority. +static unsigned +CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector &SUNumbers) { + unsigned &SethiUllmanNumber = SUNumbers[SU->NodeNum]; + if (SethiUllmanNumber != 0) + return SethiUllmanNumber; + + unsigned Extra = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + SUnit *PredSU = I->getSUnit(); + unsigned PredSethiUllman = CalcNodeSethiUllmanNumber(PredSU, SUNumbers); + if (PredSethiUllman > SethiUllmanNumber) { + SethiUllmanNumber = PredSethiUllman; + Extra = 0; + } else if (PredSethiUllman == SethiUllmanNumber) + ++Extra; + } + + SethiUllmanNumber += Extra; + + if (SethiUllmanNumber == 0) + SethiUllmanNumber = 1; + + return SethiUllmanNumber; +} + +/// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all +/// scheduling units. +void RegReductionPQBase::CalculateSethiUllmanNumbers() { + SethiUllmanNumbers.assign(SUnits->size(), 0); + + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) + CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); +} + +void RegReductionPQBase::initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + if (!TracksRegPressure) + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); +} + +void RegReductionPQBase::addNode(const SUnit *SU) { + unsigned SUSize = SethiUllmanNumbers.size(); + if (SUnits->size() > SUSize) + SethiUllmanNumbers.resize(SUSize*2, 0); + CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); +} + +void RegReductionPQBase::updateNode(const SUnit *SU) { + SethiUllmanNumbers[SU->NodeNum] = 0; + CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers); +} + +// Lower priority means schedule further down. For bottom-up scheduling, lower +// priority SUs are scheduled before higher priority SUs. +unsigned RegReductionPQBase::getNodePriority(const SUnit *SU) const { + assert(SU->NodeNum < SethiUllmanNumbers.size()); + unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; + if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) + // CopyToReg should be close to its uses to facilitate coalescing and + // avoid spilling. + return 0; + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG || + Opc == TargetOpcode::INSERT_SUBREG) + // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be + // close to their uses to facilitate coalescing. + return 0; + if (SU->NumSuccs == 0 && SU->NumPreds != 0) + // If SU does not have a register use, i.e. it doesn't produce a value + // that would be consumed (e.g. store), then it terminates a chain of + // computation. Give it a large SethiUllman number so it will be + // scheduled right before its predecessors that it doesn't lengthen + // their live ranges. + return 0xffff; + if (SU->NumPreds == 0 && SU->NumSuccs != 0) + // If SU does not have a register def, schedule it close to its uses + // because it does not lengthen any live ranges. + return 0; + return SethiUllmanNumbers[SU->NodeNum]; +} + +//===----------------------------------------------------------------------===// +// Register Pressure Tracking +//===----------------------------------------------------------------------===// + +void RegReductionPQBase::dumpRegPressure() const { + for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), + E = TRI->regclass_end(); I != E; ++I) { + const TargetRegisterClass *RC = *I; + unsigned Id = RC->getID(); + unsigned RP = RegPressure[Id]; + if (!RP) continue; + DEBUG(dbgs() << RC->getName() << ": " << RP << " / " << RegLimit[Id] + << '\n'); + } +} + +bool RegReductionPQBase::HighRegPressure(const SUnit *SU) const { + if (!TLI) + return false; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + continue; + SUnit *PredSU = I->getSUnit(); + // NumRegDefsLeft is zero when enough uses of this node have been scheduled + // to cover the number of registers defined (they are all live). + if (PredSU->NumRegDefsLeft == 0) { + continue; + } + for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); + RegDefPos.IsValid(); RegDefPos.Advance()) { + EVT VT = RegDefPos.GetValue(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + unsigned Cost = TLI->getRepRegClassCostFor(VT); + if ((RegPressure[RCId] + Cost) >= RegLimit[RCId]) + return true; + } + } + return false; +} + +bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) const { + const SDNode *N = SU->getNode(); + + if (!N->isMachineOpcode() || !SU->NumSuccs) + return false; + + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + for (unsigned i = 0; i != NumDefs; ++i) { + EVT VT = N->getValueType(i); + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] >= RegLimit[RCId]) + return true; + } + return false; +} + +// Compute the register pressure contribution by this instruction by count up +// for uses that are not live and down for defs. Only count register classes +// that are already under high pressure. As a side effect, compute the number of +// uses of registers that are already live. +// +// FIXME: This encompasses the logic in HighRegPressure and MayReduceRegPressure +// so could probably be factored. +int RegReductionPQBase::RegPressureDiff(SUnit *SU, unsigned &LiveUses) const { + LiveUses = 0; + int PDiff = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + continue; + SUnit *PredSU = I->getSUnit(); + // NumRegDefsLeft is zero when enough uses of this node have been scheduled + // to cover the number of registers defined (they are all live). + if (PredSU->NumRegDefsLeft == 0) { + if (PredSU->getNode()->isMachineOpcode()) + ++LiveUses; + continue; + } + for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); + RegDefPos.IsValid(); RegDefPos.Advance()) { + EVT VT = RegDefPos.GetValue(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] >= RegLimit[RCId]) + ++PDiff; + } + } + const SDNode *N = SU->getNode(); + + if (!N || !N->isMachineOpcode() || !SU->NumSuccs) + return PDiff; + + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + for (unsigned i = 0; i != NumDefs; ++i) { + EVT VT = N->getValueType(i); + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] >= RegLimit[RCId]) + --PDiff; + } + return PDiff; +} + +void RegReductionPQBase::ScheduledNode(SUnit *SU) { + if (!TracksRegPressure) + return; + + if (!SU->getNode()) + return; + + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + continue; + SUnit *PredSU = I->getSUnit(); + // NumRegDefsLeft is zero when enough uses of this node have been scheduled + // to cover the number of registers defined (they are all live). + if (PredSU->NumRegDefsLeft == 0) { + continue; + } + // FIXME: The ScheduleDAG currently loses information about which of a + // node's values is consumed by each dependence. Consequently, if the node + // defines multiple register classes, we don't know which to pressurize + // here. Instead the following loop consumes the register defs in an + // arbitrary order. At least it handles the common case of clustered loads + // to the same class. For precise liveness, each SDep needs to indicate the + // result number. But that tightly couples the ScheduleDAG with the + // SelectionDAG making updates tricky. A simpler hack would be to attach a + // value type or register class to SDep. + // + // The most important aspect of register tracking is balancing the increase + // here with the reduction further below. Note that this SU may use multiple + // defs in PredSU. The can't be determined here, but we've already + // compensated by reducing NumRegDefsLeft in PredSU during + // ScheduleDAGSDNodes::AddSchedEdges. + --PredSU->NumRegDefsLeft; + unsigned SkipRegDefs = PredSU->NumRegDefsLeft; + for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG); + RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) { + if (SkipRegDefs) + continue; + EVT VT = RegDefPos.GetValue(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + break; + } + } + + // We should have this assert, but there may be dead SDNodes that never + // materialize as SUnits, so they don't appear to generate liveness. + //assert(SU->NumRegDefsLeft == 0 && "not all regdefs have scheduled uses"); + int SkipRegDefs = (int)SU->NumRegDefsLeft; + for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG); + RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) { + if (SkipRegDefs > 0) + continue; + EVT VT = RegDefPos.GetValue(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] < TLI->getRepRegClassCostFor(VT)) { + // Register pressure tracking is imprecise. This can happen. But we try + // hard not to let it happen because it likely results in poor scheduling. + DEBUG(dbgs() << " SU(" << SU->NodeNum << ") has too many regdefs\n"); + RegPressure[RCId] = 0; + } + else { + RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT); + } + } + dumpRegPressure(); +} + +void RegReductionPQBase::UnscheduledNode(SUnit *SU) { + if (!TracksRegPressure) + return; + + const SDNode *N = SU->getNode(); + if (!N) return; + + if (!N->isMachineOpcode()) { + if (N->getOpcode() != ISD::CopyToReg) + return; + } else { + unsigned Opc = N->getMachineOpcode(); + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::INSERT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG || + Opc == TargetOpcode::REG_SEQUENCE || + Opc == TargetOpcode::IMPLICIT_DEF) + return; + } + + for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) + continue; + SUnit *PredSU = I->getSUnit(); + // NumSuccsLeft counts all deps. Don't compare it with NumSuccs which only + // counts data deps. + if (PredSU->NumSuccsLeft != PredSU->Succs.size()) + continue; + const SDNode *PN = PredSU->getNode(); + if (!PN->isMachineOpcode()) { + if (PN->getOpcode() == ISD::CopyFromReg) { + EVT VT = PN->getValueType(0); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + } + continue; + } + unsigned POpc = PN->getMachineOpcode(); + if (POpc == TargetOpcode::IMPLICIT_DEF) + continue; + if (POpc == TargetOpcode::EXTRACT_SUBREG) { + EVT VT = PN->getOperand(0).getValueType(); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + continue; + } else if (POpc == TargetOpcode::INSERT_SUBREG || + POpc == TargetOpcode::SUBREG_TO_REG) { + EVT VT = PN->getValueType(0); + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + continue; + } + unsigned NumDefs = TII->get(PN->getMachineOpcode()).getNumDefs(); + for (unsigned i = 0; i != NumDefs; ++i) { + EVT VT = PN->getValueType(i); + if (!PN->hasAnyUseOfValue(i)) + continue; + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + if (RegPressure[RCId] < TLI->getRepRegClassCostFor(VT)) + // Register pressure tracking is imprecise. This can happen. + RegPressure[RCId] = 0; + else + RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT); + } + } + + // Check for isMachineOpcode() as PrescheduleNodesWithMultipleUses() + // may transfer data dependencies to CopyToReg. + if (SU->NumSuccs && N->isMachineOpcode()) { + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Glue || VT == MVT::Other) + continue; + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned RCId = TLI->getRepRegClassFor(VT)->getID(); + RegPressure[RCId] += TLI->getRepRegClassCostFor(VT); + } + } + + dumpRegPressure(); +} + +//===----------------------------------------------------------------------===// +// Dynamic Node Priority for Register Pressure Reduction +//===----------------------------------------------------------------------===// + +/// closestSucc - Returns the scheduled cycle of the successor which is +/// closest to the current cycle. +static unsigned closestSucc(const SUnit *SU) { + unsigned MaxHeight = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain succs + unsigned Height = I->getSUnit()->getHeight(); + // If there are bunch of CopyToRegs stacked up, they should be considered + // to be at the same position. + if (I->getSUnit()->getNode() && + I->getSUnit()->getNode()->getOpcode() == ISD::CopyToReg) + Height = closestSucc(I->getSUnit())+1; + if (Height > MaxHeight) + MaxHeight = Height; + } + return MaxHeight; +} + +/// calcMaxScratches - Returns an cost estimate of the worse case requirement +/// for scratch registers, i.e. number of data dependencies. +static unsigned calcMaxScratches(const SUnit *SU) { + unsigned Scratches = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + Scratches++; + } + return Scratches; +} + +/// hasOnlyLiveOutUse - Return true if SU has a single value successor that is a +/// CopyToReg to a virtual register. This SU def is probably a liveout and +/// it has no other use. It should be scheduled closer to the terminator. +static bool hasOnlyLiveOutUses(const SUnit *SU) { + bool RetVal = false; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + if (I->isCtrl()) continue; + const SUnit *SuccSU = I->getSUnit(); + if (SuccSU->getNode() && SuccSU->getNode()->getOpcode() == ISD::CopyToReg) { + unsigned Reg = + cast(SuccSU->getNode()->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + RetVal = true; + continue; + } + } + return false; + } + return RetVal; +} + +/// UnitsSharePred - Return true if the two scheduling units share a common +/// data predecessor. +static bool UnitsSharePred(const SUnit *left, const SUnit *right) { + SmallSet Preds; + for (SUnit::const_pred_iterator I = left->Preds.begin(),E = left->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + Preds.insert(I->getSUnit()); + } + for (SUnit::const_pred_iterator I = right->Preds.begin(),E = right->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; // ignore chain preds + if (Preds.count(I->getSUnit())) + return true; + } + return false; +} + +// Check for either a dependence (latency) or resource (hazard) stall. +// +// Note: The ScheduleHazardRecognizer interface requires a non-const SU. +static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ) { + if ((int)SPQ->getCurCycle() < Height) return true; + if (SPQ->getHazardRec()->getHazardType(SU, 0) + != ScheduleHazardRecognizer::NoHazard) + return true; + return false; +} + +// Return -1 if left has higher priority, 1 if right has higher priority. +// Return 0 if latency-based priority is equivalent. +static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, + RegReductionPQBase *SPQ) { + // If the two nodes share an operand and one of them has a single + // use that is a live out copy, favor the one that is live out. Otherwise + // it will be difficult to eliminate the copy if the instruction is a + // loop induction variable update. e.g. + // BB: + // sub r1, r3, #1 + // str r0, [r2, r3] + // mov r3, r1 + // cmp + // bne BB + bool SharePred = UnitsSharePred(left, right); + // FIXME: Only adjust if BB is a loop back edge. + // FIXME: What's the cost of a copy? + int LBonus = (SharePred && hasOnlyLiveOutUses(left)) ? 1 : 0; + int RBonus = (SharePred && hasOnlyLiveOutUses(right)) ? 1 : 0; + int LHeight = (int)left->getHeight() - LBonus; + int RHeight = (int)right->getHeight() - RBonus; + + bool LStall = (!checkPref || left->SchedulingPref == Sched::Latency) && + BUHasStall(left, LHeight, SPQ); + bool RStall = (!checkPref || right->SchedulingPref == Sched::Latency) && + BUHasStall(right, RHeight, SPQ); + + // If scheduling one of the node will cause a pipeline stall, delay it. + // If scheduling either one of the node will cause a pipeline stall, sort + // them according to their height. + if (LStall) { + if (!RStall) + return 1; + if (LHeight != RHeight) + return LHeight > RHeight ? 1 : -1; + } else if (RStall) + return -1; + + // If either node is scheduling for latency, sort them by height/depth + // and latency. + if (!checkPref || (left->SchedulingPref == Sched::Latency || + right->SchedulingPref == Sched::Latency)) { + if (DisableSchedCycles) { + if (LHeight != RHeight) + return LHeight > RHeight ? 1 : -1; + } + else { + // If neither instruction stalls (!LStall && !RStall) then + // its height is already covered so only its depth matters. We also reach + // this if both stall but have the same height. + unsigned LDepth = left->getDepth(); + unsigned RDepth = right->getDepth(); + if (LDepth != RDepth) { + DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum + << ") depth " << LDepth << " vs SU (" << right->NodeNum + << ") depth " << RDepth << "\n"); + return LDepth < RDepth ? 1 : -1; + } + } + if (left->Latency != right->Latency) + return left->Latency > right->Latency ? 1 : -1; + } + return 0; +} + +static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) { + unsigned LPriority = SPQ->getNodePriority(left); + unsigned RPriority = SPQ->getNodePriority(right); + if (LPriority != RPriority) { + DEBUG(++FactorCount[FactStatic]); + return LPriority > RPriority; + } + DEBUG(++FactorCount[FactOther]); + + // Try schedule def + use closer when Sethi-Ullman numbers are the same. + // e.g. + // t1 = op t2, c1 + // t3 = op t4, c2 + // + // and the following instructions are both ready. + // t2 = op c3 + // t4 = op c4 + // + // Then schedule t2 = op first. + // i.e. + // t4 = op c4 + // t2 = op c3 + // t1 = op t2, c1 + // t3 = op t4, c2 + // + // This creates more short live intervals. + unsigned LDist = closestSucc(left); + unsigned RDist = closestSucc(right); + if (LDist != RDist) + return LDist < RDist; + + // How many registers becomes live when the node is scheduled. + unsigned LScratch = calcMaxScratches(left); + unsigned RScratch = calcMaxScratches(right); + if (LScratch != RScratch) + return LScratch > RScratch; + + if (!DisableSchedCycles) { + int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); + if (result != 0) + return result > 0; + } + else { + if (left->getHeight() != right->getHeight()) + return left->getHeight() > right->getHeight(); + + if (left->getDepth() != right->getDepth()) + return left->getDepth() < right->getDepth(); + } + + assert(left->NodeQueueId && right->NodeQueueId && + "NodeQueueId cannot be zero"); + return (left->NodeQueueId > right->NodeQueueId); +} + +// Bottom up +bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + return BURRSort(left, right, SPQ); +} + +// Source order, otherwise bottom up. +bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + unsigned LOrder = SPQ->getNodeOrdering(left); + unsigned ROrder = SPQ->getNodeOrdering(right); + + // Prefer an ordering where the lower the non-zero order number, the higher + // the preference. + if ((LOrder || ROrder) && LOrder != ROrder) + return LOrder != 0 && (LOrder < ROrder || ROrder == 0); + + return BURRSort(left, right, SPQ); +} + +// If the time between now and when the instruction will be ready can cover +// the spill code, then avoid adding it to the ready queue. This gives long +// stalls highest priority and allows hoisting across calls. It should also +// speed up processing the available queue. +bool hybrid_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { + static const unsigned ReadyDelay = 3; + + if (SPQ->MayReduceRegPressure(SU)) return true; + + if (SU->getHeight() > (CurCycle + ReadyDelay)) return false; + + if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay) + != ScheduleHazardRecognizer::NoHazard) + return false; + + return true; +} + +// Return true if right should be scheduled with higher priority than left. +bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (left->isCall || right->isCall) + // No way to compute latency of calls. + return BURRSort(left, right, SPQ); + + bool LHigh = SPQ->HighRegPressure(left); + bool RHigh = SPQ->HighRegPressure(right); + // Avoid causing spills. If register pressure is high, schedule for + // register pressure reduction. + if (LHigh && !RHigh) { + DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" + << right->NodeNum << ")\n"); + return true; + } + else if (!LHigh && RHigh) { + DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" + << left->NodeNum << ")\n"); + return false; + } + else if (!LHigh && !RHigh) { + int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + if (result != 0) + return result > 0; + } + return BURRSort(left, right, SPQ); +} + +// Schedule as many instructions in each cycle as possible. So don't make an +// instruction available unless it is ready in the current cycle. +bool ilp_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const { + if (SU->getHeight() > CurCycle) return false; + + if (SPQ->getHazardRec()->getHazardType(SU, 0) + != ScheduleHazardRecognizer::NoHazard) + return false; + + return true; +} + +bool canEnableCoaelscing(SUnit *SU) { + unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0; + if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg) + // CopyToReg should be close to its uses to facilitate coalescing and + // avoid spilling. + return true; + + if (Opc == TargetOpcode::EXTRACT_SUBREG || + Opc == TargetOpcode::SUBREG_TO_REG || + Opc == TargetOpcode::INSERT_SUBREG) + // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be + // close to their uses to facilitate coalescing. + return true; + + if (SU->NumPreds == 0 && SU->NumSuccs != 0) + // If SU does not have a register def, schedule it close to its uses + // because it does not lengthen any live ranges. + return true; + + return false; +} + +// list-ilp is currently an experimental scheduler that allows various +// heuristics to be enabled prior to the normal register reduction logic. +bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (left->isCall || right->isCall) + // No way to compute latency of calls. + return BURRSort(left, right, SPQ); + + unsigned LLiveUses = 0, RLiveUses = 0; + int LPDiff = 0, RPDiff = 0; + if (!DisableSchedRegPressure || !DisableSchedLiveUses) { + LPDiff = SPQ->RegPressureDiff(left, LLiveUses); + RPDiff = SPQ->RegPressureDiff(right, RLiveUses); + } + if (!DisableSchedRegPressure && LPDiff != RPDiff) { + DEBUG(++FactorCount[FactPressureDiff]); + DEBUG(dbgs() << "RegPressureDiff SU(" << left->NodeNum << "): " << LPDiff + << " != SU(" << right->NodeNum << "): " << RPDiff << "\n"); + return LPDiff > RPDiff; + } + + if (!DisableSchedRegPressure && (LPDiff > 0 || RPDiff > 0)) { + bool LReduce = canEnableCoaelscing(left); + bool RReduce = canEnableCoaelscing(right); + DEBUG(if (LReduce != RReduce) ++FactorCount[FactPressureDiff]); + if (LReduce && !RReduce) return false; + if (RReduce && !LReduce) return true; + } + + if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { + DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses + << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n"); + DEBUG(++FactorCount[FactRegUses]); + return LLiveUses < RLiveUses; + } + + if (!DisableSchedStalls) { + bool LStall = BUHasStall(left, left->getHeight(), SPQ); + bool RStall = BUHasStall(right, right->getHeight(), SPQ); + if (LStall != RStall) { + DEBUG(++FactorCount[FactHeight]); + return left->getHeight() > right->getHeight(); + } + } + + if (!DisableSchedCriticalPath) { + int spread = (int)left->getDepth() - (int)right->getDepth(); + if (std::abs(spread) > MaxReorderWindow) { + DEBUG(dbgs() << "Depth of SU(" << left->NodeNum << "): " + << left->getDepth() << " != SU(" << right->NodeNum << "): " + << right->getDepth() << "\n"); + DEBUG(++FactorCount[FactDepth]); + return left->getDepth() < right->getDepth(); + } + } + + if (!DisableSchedHeight && left->getHeight() != right->getHeight()) { + int spread = (int)left->getHeight() - (int)right->getHeight(); + if (std::abs(spread) > MaxReorderWindow) { + DEBUG(++FactorCount[FactHeight]); + return left->getHeight() > right->getHeight(); + } + } + + return BURRSort(left, right, SPQ); +} + +//===----------------------------------------------------------------------===// +// Preschedule for Register Pressure +//===----------------------------------------------------------------------===// + +bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) { + if (SU->isTwoAddress) { + unsigned Opc = SU->getNode()->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + unsigned NumRes = TID.getNumDefs(); + unsigned NumOps = TID.getNumOperands() - NumRes; + for (unsigned i = 0; i != NumOps; ++i) { + if (TID.getOperandConstraint(i+NumRes, TOI::TIED_TO) != -1) { + SDNode *DU = SU->getNode()->getOperand(i).getNode(); + if (DU->getNodeId() != -1 && + Op->OrigNode == &(*SUnits)[DU->getNodeId()]) + return true; + } + } + } + return false; +} + +/// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's +/// physical register defs. +static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + SDNode *N = SuccSU->getNode(); + unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs(); + const unsigned *ImpDefs = TII->get(N->getMachineOpcode()).getImplicitDefs(); + assert(ImpDefs && "Caller should check hasPhysRegDefs"); + for (const SDNode *SUNode = SU->getNode(); SUNode; + SUNode = SUNode->getGluedNode()) { + if (!SUNode->isMachineOpcode()) + continue; + const unsigned *SUImpDefs = + TII->get(SUNode->getMachineOpcode()).getImplicitDefs(); + if (!SUImpDefs) + return false; + for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Glue || VT == MVT::Other) + continue; + if (!N->hasAnyUseOfValue(i)) + continue; + unsigned Reg = ImpDefs[i - NumDefs]; + for (;*SUImpDefs; ++SUImpDefs) { + unsigned SUReg = *SUImpDefs; + if (TRI->regsOverlap(Reg, SUReg)) + return true; + } + } + } + return false; +} + +/// PrescheduleNodesWithMultipleUses - Nodes with multiple uses +/// are not handled well by the general register pressure reduction +/// heuristics. When presented with code like this: +/// +/// N +/// / | +/// / | +/// U store +/// | +/// ... +/// +/// the heuristics tend to push the store up, but since the +/// operand of the store has another use (U), this would increase +/// the length of that other use (the U->N edge). +/// +/// This function transforms code like the above to route U's +/// dependence through the store when possible, like this: +/// +/// N +/// || +/// || +/// store +/// | +/// U +/// | +/// ... +/// +/// This results in the store being scheduled immediately +/// after N, which shortens the U->N live range, reducing +/// register pressure. +/// +void RegReductionPQBase::PrescheduleNodesWithMultipleUses() { + // Visit all the nodes in topological order, working top-down. + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) { + SUnit *SU = &(*SUnits)[i]; + // For now, only look at nodes with no data successors, such as stores. + // These are especially important, due to the heuristics in + // getNodePriority for nodes with no data successors. + if (SU->NumSuccs != 0) + continue; + // For now, only look at nodes with exactly one data predecessor. + if (SU->NumPreds != 1) + continue; + // Avoid prescheduling copies to virtual registers, which don't behave + // like other nodes from the perspective of scheduling heuristics. + if (SDNode *N = SU->getNode()) + if (N->getOpcode() == ISD::CopyToReg && + TargetRegisterInfo::isVirtualRegister + (cast(N->getOperand(1))->getReg())) + continue; + + // Locate the single data predecessor. + SUnit *PredSU = 0; + for (SUnit::const_pred_iterator II = SU->Preds.begin(), + EE = SU->Preds.end(); II != EE; ++II) + if (!II->isCtrl()) { + PredSU = II->getSUnit(); + break; + } + assert(PredSU); + + // Don't rewrite edges that carry physregs, because that requires additional + // support infrastructure. + if (PredSU->hasPhysRegDefs) + continue; + // Short-circuit the case where SU is PredSU's only data successor. + if (PredSU->NumSuccs == 1) + continue; + // Avoid prescheduling to copies from virtual registers, which don't behave + // like other nodes from the perspective of scheduling heuristics. + if (SDNode *N = SU->getNode()) + if (N->getOpcode() == ISD::CopyFromReg && + TargetRegisterInfo::isVirtualRegister + (cast(N->getOperand(1))->getReg())) + continue; + + // Perform checks on the successors of PredSU. + for (SUnit::const_succ_iterator II = PredSU->Succs.begin(), + EE = PredSU->Succs.end(); II != EE; ++II) { + SUnit *PredSuccSU = II->getSUnit(); + if (PredSuccSU == SU) continue; + // If PredSU has another successor with no data successors, for + // now don't attempt to choose either over the other. + if (PredSuccSU->NumSuccs == 0) + goto outer_loop_continue; + // Don't break physical register dependencies. + if (SU->hasPhysRegClobbers && PredSuccSU->hasPhysRegDefs) + if (canClobberPhysRegDefs(PredSuccSU, SU, TII, TRI)) + goto outer_loop_continue; + // Don't introduce graph cycles. + if (scheduleDAG->IsReachable(SU, PredSuccSU)) + goto outer_loop_continue; + } + + // Ok, the transformation is safe and the heuristics suggest it is + // profitable. Update the graph. + DEBUG(dbgs() << " Prescheduling SU #" << SU->NodeNum + << " next to PredSU #" << PredSU->NodeNum + << " to guide scheduling in the presence of multiple uses\n"); + for (unsigned i = 0; i != PredSU->Succs.size(); ++i) { + SDep Edge = PredSU->Succs[i]; + assert(!Edge.isAssignedRegDep()); + SUnit *SuccSU = Edge.getSUnit(); + if (SuccSU != SU) { + Edge.setSUnit(PredSU); + scheduleDAG->RemovePred(SuccSU, Edge); + scheduleDAG->AddPred(SU, Edge); + Edge.setSUnit(SU); + scheduleDAG->AddPred(SuccSU, Edge); + --i; + } + } + outer_loop_continue:; + } +} + +/// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses +/// it as a def&use operand. Add a pseudo control edge from it to the other +/// node (if it won't create a cycle) so the two-address one will be scheduled +/// first (lower in the schedule). If both nodes are two-address, favor the +/// one that has a CopyToReg use (more likely to be a loop induction update). +/// If both are two-address, but one is commutable while the other is not +/// commutable, favor the one that's not commutable. +void RegReductionPQBase::AddPseudoTwoAddrDeps() { + for (unsigned i = 0, e = SUnits->size(); i != e; ++i) { + SUnit *SU = &(*SUnits)[i]; + if (!SU->isTwoAddress) + continue; + + SDNode *Node = SU->getNode(); + if (!Node || !Node->isMachineOpcode() || SU->getNode()->getGluedNode()) + continue; + + bool isLiveOut = hasOnlyLiveOutUses(SU); + unsigned Opc = Node->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + unsigned NumRes = TID.getNumDefs(); + unsigned NumOps = TID.getNumOperands() - NumRes; + for (unsigned j = 0; j != NumOps; ++j) { + if (TID.getOperandConstraint(j+NumRes, TOI::TIED_TO) == -1) + continue; + SDNode *DU = SU->getNode()->getOperand(j).getNode(); + if (DU->getNodeId() == -1) + continue; + const SUnit *DUSU = &(*SUnits)[DU->getNodeId()]; + if (!DUSU) continue; + for (SUnit::const_succ_iterator I = DUSU->Succs.begin(), + E = DUSU->Succs.end(); I != E; ++I) { + if (I->isCtrl()) continue; + SUnit *SuccSU = I->getSUnit(); + if (SuccSU == SU) + continue; + // Be conservative. Ignore if nodes aren't at roughly the same + // depth and height. + if (SuccSU->getHeight() < SU->getHeight() && + (SU->getHeight() - SuccSU->getHeight()) > 1) + continue; + // Skip past COPY_TO_REGCLASS nodes, so that the pseudo edge + // constrains whatever is using the copy, instead of the copy + // itself. In the case that the copy is coalesced, this + // preserves the intent of the pseudo two-address heurietics. + while (SuccSU->Succs.size() == 1 && + SuccSU->getNode()->isMachineOpcode() && + SuccSU->getNode()->getMachineOpcode() == + TargetOpcode::COPY_TO_REGCLASS) + SuccSU = SuccSU->Succs.front().getSUnit(); + // Don't constrain non-instruction nodes. + if (!SuccSU->getNode() || !SuccSU->getNode()->isMachineOpcode()) + continue; + // Don't constrain nodes with physical register defs if the + // predecessor can clobber them. + if (SuccSU->hasPhysRegDefs && SU->hasPhysRegClobbers) { + if (canClobberPhysRegDefs(SuccSU, SU, TII, TRI)) + continue; + } + // Don't constrain EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG; + // these may be coalesced away. We want them close to their uses. + unsigned SuccOpc = SuccSU->getNode()->getMachineOpcode(); + if (SuccOpc == TargetOpcode::EXTRACT_SUBREG || + SuccOpc == TargetOpcode::INSERT_SUBREG || + SuccOpc == TargetOpcode::SUBREG_TO_REG) + continue; + if ((!canClobber(SuccSU, DUSU) || + (isLiveOut && !hasOnlyLiveOutUses(SuccSU)) || + (!SU->isCommutable && SuccSU->isCommutable)) && + !scheduleDAG->IsReachable(SuccSU, SU)) { + DEBUG(dbgs() << " Adding a pseudo-two-addr edge from SU #" + << SU->NodeNum << " to SU #" << SuccSU->NodeNum << "\n"); + scheduleDAG->AddPred(SU, SDep(SuccSU, SDep::Order, /*Latency=*/0, + /*Reg=*/0, /*isNormalMemory=*/false, + /*isMustAlias=*/false, + /*isArtificial=*/true)); + } + } + } + } +} + +/// LimitedSumOfUnscheduledPredsOfSuccs - Compute the sum of the unscheduled +/// predecessors of the successors of the SUnit SU. Stop when the provided +/// limit is exceeded. +static unsigned LimitedSumOfUnscheduledPredsOfSuccs(const SUnit *SU, + unsigned Limit) { + unsigned Sum = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + const SUnit *SuccSU = I->getSUnit(); + for (SUnit::const_pred_iterator II = SuccSU->Preds.begin(), + EE = SuccSU->Preds.end(); II != EE; ++II) { + SUnit *PredSU = II->getSUnit(); + if (!PredSU->isScheduled) + if (++Sum > Limit) + return Sum; + } + } + return Sum; +} + + +// Top down +bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + unsigned LPriority = SPQ->getNodePriority(left); + unsigned RPriority = SPQ->getNodePriority(right); + bool LIsTarget = left->getNode() && left->getNode()->isMachineOpcode(); + bool RIsTarget = right->getNode() && right->getNode()->isMachineOpcode(); + bool LIsFloater = LIsTarget && left->NumPreds == 0; + bool RIsFloater = RIsTarget && right->NumPreds == 0; + unsigned LBonus = (LimitedSumOfUnscheduledPredsOfSuccs(left,1) == 1) ? 2 : 0; + unsigned RBonus = (LimitedSumOfUnscheduledPredsOfSuccs(right,1) == 1) ? 2 : 0; + + if (left->NumSuccs == 0 && right->NumSuccs != 0) + return false; + else if (left->NumSuccs != 0 && right->NumSuccs == 0) + return true; + + if (LIsFloater) + LBonus -= 2; + if (RIsFloater) + RBonus -= 2; + if (left->NumSuccs == 1) + LBonus += 2; + if (right->NumSuccs == 1) + RBonus += 2; + + if (LPriority+LBonus != RPriority+RBonus) + return LPriority+LBonus < RPriority+RBonus; + + if (left->getDepth() != right->getDepth()) + return left->getDepth() < right->getDepth(); + + if (left->NumSuccsLeft != right->NumSuccsLeft) + return left->NumSuccsLeft > right->NumSuccsLeft; + + assert(left->NodeQueueId && right->NodeQueueId && + "NodeQueueId cannot be zero"); + return (left->NodeQueueId > right->NodeQueueId); +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +llvm::ScheduleDAGSDNodes * +llvm::createBURRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + BURegReductionPriorityQueue *PQ = + new BURegReductionPriorityQueue(*IS->MF, false, TII, TRI, 0); + ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel); + PQ->setScheduleDAG(SD); + return SD; +} + +llvm::ScheduleDAGSDNodes * +llvm::createTDRRListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + TDRegReductionPriorityQueue *PQ = + new TDRegReductionPriorityQueue(*IS->MF, false, TII, TRI, 0); + ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel); + PQ->setScheduleDAG(SD); + return SD; +} + +llvm::ScheduleDAGSDNodes * +llvm::createSourceListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + + SrcRegReductionPriorityQueue *PQ = + new SrcRegReductionPriorityQueue(*IS->MF, false, TII, TRI, 0); + ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel); + PQ->setScheduleDAG(SD); + return SD; +} + +llvm::ScheduleDAGSDNodes * +llvm::createHybridListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetLowering *TLI = &IS->getTargetLowering(); + + HybridBURRPriorityQueue *PQ = + new HybridBURRPriorityQueue(*IS->MF, true, TII, TRI, TLI); + + ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel); + PQ->setScheduleDAG(SD); + return SD; +} + +llvm::ScheduleDAGSDNodes * +llvm::createILPListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetMachine &TM = IS->TM; + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetLowering *TLI = &IS->getTargetLowering(); + + ILPBURRPriorityQueue *PQ = + new ILPBURRPriorityQueue(*IS->MF, true, TII, TRI, TLI); + ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel); + PQ->setScheduleDAG(SD); + return SD; +} diff --git a/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp new file mode 100644 index 00000000000..b762af5ca9b --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -0,0 +1,763 @@ +//===--- ScheduleDAGSDNodes.cpp - Implement the ScheduleDAGSDNodes class --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the ScheduleDAG class, which is a base class used by +// scheduling implementation classes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pre-RA-sched" +#include "SDNodeDbgValue.h" +#include "ScheduleDAGSDNodes.h" +#include "InstrEmitter.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +STATISTIC(LoadsClustered, "Number of loads clustered together"); + +// This allows latency based scheduler to notice high latency instructions +// without a target itinerary. The choise if number here has more to do with +// balancing scheduler heursitics than with the actual machine latency. +static cl::opt HighLatencyCycles( + "sched-high-latency-cycles", cl::Hidden, cl::init(10), + cl::desc("Roughly estimate the number of cycles that 'long latency'" + "instructions take for targets with no itinerary")); + +ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) + : ScheduleDAG(mf), + InstrItins(mf.getTarget().getInstrItineraryData()) {} + +/// Run - perform scheduling. +/// +void ScheduleDAGSDNodes::Run(SelectionDAG *dag, MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos) { + DAG = dag; + ScheduleDAG::Run(bb, insertPos); +} + +/// NewSUnit - Creates a new SUnit and return a ptr to it. +/// +SUnit *ScheduleDAGSDNodes::NewSUnit(SDNode *N) { +#ifndef NDEBUG + const SUnit *Addr = 0; + if (!SUnits.empty()) + Addr = &SUnits[0]; +#endif + SUnits.push_back(SUnit(N, (unsigned)SUnits.size())); + assert((Addr == 0 || Addr == &SUnits[0]) && + "SUnits std::vector reallocated on the fly!"); + SUnits.back().OrigNode = &SUnits.back(); + SUnit *SU = &SUnits.back(); + const TargetLowering &TLI = DAG->getTargetLoweringInfo(); + if (!N || + (N->isMachineOpcode() && + N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF)) + SU->SchedulingPref = Sched::None; + else + SU->SchedulingPref = TLI.getSchedulingPreference(N); + return SU; +} + +SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) { + SUnit *SU = NewSUnit(Old->getNode()); + SU->OrigNode = Old->OrigNode; + SU->Latency = Old->Latency; + SU->isCall = Old->isCall; + SU->isTwoAddress = Old->isTwoAddress; + SU->isCommutable = Old->isCommutable; + SU->hasPhysRegDefs = Old->hasPhysRegDefs; + SU->hasPhysRegClobbers = Old->hasPhysRegClobbers; + SU->SchedulingPref = Old->SchedulingPref; + Old->isCloned = true; + return SU; +} + +/// CheckForPhysRegDependency - Check if the dependency between def and use of +/// a specified operand is a physical register dependency. If so, returns the +/// register and the cost of copying the register. +static void CheckForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, + const TargetRegisterInfo *TRI, + const TargetInstrInfo *TII, + unsigned &PhysReg, int &Cost) { + if (Op != 2 || User->getOpcode() != ISD::CopyToReg) + return; + + unsigned Reg = cast(User->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + return; + + unsigned ResNo = User->getOperand(2).getResNo(); + if (Def->isMachineOpcode()) { + const TargetInstrDesc &II = TII->get(Def->getMachineOpcode()); + if (ResNo >= II.getNumDefs() && + II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) { + PhysReg = Reg; + const TargetRegisterClass *RC = + TRI->getMinimalPhysRegClass(Reg, Def->getValueType(ResNo)); + Cost = RC->getCopyCost(); + } + } +} + +static void AddGlue(SDNode *N, SDValue Glue, bool AddGlue, SelectionDAG *DAG) { + SmallVector VTs; + SDNode *GlueDestNode = Glue.getNode(); + + // Don't add glue from a node to itself. + if (GlueDestNode == N) return; + + // Don't add glue to something which already has glue. + if (N->getValueType(N->getNumValues() - 1) == MVT::Glue) return; + + for (unsigned I = 0, E = N->getNumValues(); I != E; ++I) + VTs.push_back(N->getValueType(I)); + + if (AddGlue) + VTs.push_back(MVT::Glue); + + SmallVector Ops; + for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) + Ops.push_back(N->getOperand(I)); + + if (GlueDestNode) + Ops.push_back(Glue); + + SDVTList VTList = DAG->getVTList(&VTs[0], VTs.size()); + MachineSDNode::mmo_iterator Begin = 0, End = 0; + MachineSDNode *MN = dyn_cast(N); + + // Store memory references. + if (MN) { + Begin = MN->memoperands_begin(); + End = MN->memoperands_end(); + } + + DAG->MorphNodeTo(N, N->getOpcode(), VTList, &Ops[0], Ops.size()); + + // Reset the memory references + if (MN) + MN->setMemRefs(Begin, End); +} + +/// ClusterNeighboringLoads - Force nearby loads together by "gluing" them. +/// This function finds loads of the same base and different offsets. If the +/// offsets are not far apart (target specific), it add MVT::Glue inputs and +/// outputs to ensure they are scheduled together and in order. This +/// optimization may benefit some targets by improving cache locality. +void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) { + SDNode *Chain = 0; + unsigned NumOps = Node->getNumOperands(); + if (Node->getOperand(NumOps-1).getValueType() == MVT::Other) + Chain = Node->getOperand(NumOps-1).getNode(); + if (!Chain) + return; + + // Look for other loads of the same chain. Find loads that are loading from + // the same base pointer and different offsets. + SmallPtrSet Visited; + SmallVector Offsets; + DenseMap O2SMap; // Map from offset to SDNode. + bool Cluster = false; + SDNode *Base = Node; + for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end(); + I != E; ++I) { + SDNode *User = *I; + if (User == Node || !Visited.insert(User)) + continue; + int64_t Offset1, Offset2; + if (!TII->areLoadsFromSameBasePtr(Base, User, Offset1, Offset2) || + Offset1 == Offset2) + // FIXME: Should be ok if they addresses are identical. But earlier + // optimizations really should have eliminated one of the loads. + continue; + if (O2SMap.insert(std::make_pair(Offset1, Base)).second) + Offsets.push_back(Offset1); + O2SMap.insert(std::make_pair(Offset2, User)); + Offsets.push_back(Offset2); + if (Offset2 < Offset1) + Base = User; + Cluster = true; + } + + if (!Cluster) + return; + + // Sort them in increasing order. + std::sort(Offsets.begin(), Offsets.end()); + + // Check if the loads are close enough. + SmallVector Loads; + unsigned NumLoads = 0; + int64_t BaseOff = Offsets[0]; + SDNode *BaseLoad = O2SMap[BaseOff]; + Loads.push_back(BaseLoad); + for (unsigned i = 1, e = Offsets.size(); i != e; ++i) { + int64_t Offset = Offsets[i]; + SDNode *Load = O2SMap[Offset]; + if (!TII->shouldScheduleLoadsNear(BaseLoad, Load, BaseOff, Offset,NumLoads)) + break; // Stop right here. Ignore loads that are further away. + Loads.push_back(Load); + ++NumLoads; + } + + if (NumLoads == 0) + return; + + // Cluster loads by adding MVT::Glue outputs and inputs. This also + // ensure they are scheduled in order of increasing addresses. + SDNode *Lead = Loads[0]; + AddGlue(Lead, SDValue(0, 0), true, DAG); + + SDValue InGlue = SDValue(Lead, Lead->getNumValues() - 1); + for (unsigned I = 1, E = Loads.size(); I != E; ++I) { + bool OutGlue = I < E - 1; + SDNode *Load = Loads[I]; + + AddGlue(Load, InGlue, OutGlue, DAG); + + if (OutGlue) + InGlue = SDValue(Load, Load->getNumValues() - 1); + + ++LoadsClustered; + } +} + +/// ClusterNodes - Cluster certain nodes which should be scheduled together. +/// +void ScheduleDAGSDNodes::ClusterNodes() { + for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), + E = DAG->allnodes_end(); NI != E; ++NI) { + SDNode *Node = &*NI; + if (!Node || !Node->isMachineOpcode()) + continue; + + unsigned Opc = Node->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + if (TID.mayLoad()) + // Cluster loads from "near" addresses into combined SUnits. + ClusterNeighboringLoads(Node); + } +} + +void ScheduleDAGSDNodes::BuildSchedUnits() { + // During scheduling, the NodeId field of SDNode is used to map SDNodes + // to their associated SUnits by holding SUnits table indices. A value + // of -1 means the SDNode does not yet have an associated SUnit. + unsigned NumNodes = 0; + for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), + E = DAG->allnodes_end(); NI != E; ++NI) { + NI->setNodeId(-1); + ++NumNodes; + } + + // Reserve entries in the vector for each of the SUnits we are creating. This + // ensure that reallocation of the vector won't happen, so SUnit*'s won't get + // invalidated. + // FIXME: Multiply by 2 because we may clone nodes during scheduling. + // This is a temporary workaround. + SUnits.reserve(NumNodes * 2); + + // Add all nodes in depth first order. + SmallVector Worklist; + SmallPtrSet Visited; + Worklist.push_back(DAG->getRoot().getNode()); + Visited.insert(DAG->getRoot().getNode()); + + while (!Worklist.empty()) { + SDNode *NI = Worklist.pop_back_val(); + + // Add all operands to the worklist unless they've already been added. + for (unsigned i = 0, e = NI->getNumOperands(); i != e; ++i) + if (Visited.insert(NI->getOperand(i).getNode())) + Worklist.push_back(NI->getOperand(i).getNode()); + + if (isPassiveNode(NI)) // Leaf node, e.g. a TargetImmediate. + continue; + + // If this node has already been processed, stop now. + if (NI->getNodeId() != -1) continue; + + SUnit *NodeSUnit = NewSUnit(NI); + + // See if anything is glued to this node, if so, add them to glued + // nodes. Nodes can have at most one glue input and one glue output. Glue + // is required to be the last operand and result of a node. + + // Scan up to find glued preds. + SDNode *N = NI; + while (N->getNumOperands() && + N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Glue) { + N = N->getOperand(N->getNumOperands()-1).getNode(); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + if (N->isMachineOpcode() && TII->get(N->getMachineOpcode()).isCall()) + NodeSUnit->isCall = true; + } + + // Scan down to find any glued succs. + N = NI; + while (N->getValueType(N->getNumValues()-1) == MVT::Glue) { + SDValue GlueVal(N, N->getNumValues()-1); + + // There are either zero or one users of the Glue result. + bool HasGlueUse = false; + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); + UI != E; ++UI) + if (GlueVal.isOperandOf(*UI)) { + HasGlueUse = true; + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + N = *UI; + if (N->isMachineOpcode() && TII->get(N->getMachineOpcode()).isCall()) + NodeSUnit->isCall = true; + break; + } + if (!HasGlueUse) break; + } + + // If there are glue operands involved, N is now the bottom-most node + // of the sequence of nodes that are glued together. + // Update the SUnit. + NodeSUnit->setNode(N); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); + + // Compute NumRegDefsLeft. This must be done before AddSchedEdges. + InitNumRegDefsLeft(NodeSUnit); + + // Assign the Latency field of NodeSUnit using target-provided information. + ComputeLatency(NodeSUnit); + } +} + +void ScheduleDAGSDNodes::AddSchedEdges() { + const TargetSubtarget &ST = TM.getSubtarget(); + + // Check to see if the scheduler cares about latencies. + bool UnitLatencies = ForceUnitLatencies(); + + // Pass 2: add the preds, succs, etc. + for (unsigned su = 0, e = SUnits.size(); su != e; ++su) { + SUnit *SU = &SUnits[su]; + SDNode *MainNode = SU->getNode(); + + if (MainNode->isMachineOpcode()) { + unsigned Opc = MainNode->getMachineOpcode(); + const TargetInstrDesc &TID = TII->get(Opc); + for (unsigned i = 0; i != TID.getNumOperands(); ++i) { + if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { + SU->isTwoAddress = true; + break; + } + } + if (TID.isCommutable()) + SU->isCommutable = true; + } + + // Find all predecessors and successors of the group. + for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) { + if (N->isMachineOpcode() && + TII->get(N->getMachineOpcode()).getImplicitDefs()) { + SU->hasPhysRegClobbers = true; + unsigned NumUsed = InstrEmitter::CountResults(N); + while (NumUsed != 0 && !N->hasAnyUseOfValue(NumUsed - 1)) + --NumUsed; // Skip over unused values at the end. + if (NumUsed > TII->get(N->getMachineOpcode()).getNumDefs()) + SU->hasPhysRegDefs = true; + } + + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *OpN = N->getOperand(i).getNode(); + if (isPassiveNode(OpN)) continue; // Not scheduled. + SUnit *OpSU = &SUnits[OpN->getNodeId()]; + assert(OpSU && "Node has no SUnit!"); + if (OpSU == SU) continue; // In the same group. + + EVT OpVT = N->getOperand(i).getValueType(); + assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!"); + bool isChain = OpVT == MVT::Other; + + unsigned PhysReg = 0; + int Cost = 1; + // Determine if this is a physical register dependency. + CheckForPhysRegDependency(OpN, N, i, TRI, TII, PhysReg, Cost); + assert((PhysReg == 0 || !isChain) && + "Chain dependence via physreg data?"); + // FIXME: See ScheduleDAGSDNodes::EmitCopyFromReg. For now, scheduler + // emits a copy from the physical register to a virtual register unless + // it requires a cross class copy (cost < 0). That means we are only + // treating "expensive to copy" register dependency as physical register + // dependency. This may change in the future though. + if (Cost >= 0) + PhysReg = 0; + + // If this is a ctrl dep, latency is 1. + unsigned OpLatency = isChain ? 1 : OpSU->Latency; + const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, + OpLatency, PhysReg); + if (!isChain && !UnitLatencies) { + ComputeOperandLatency(OpN, N, i, const_cast(dep)); + ST.adjustSchedDependency(OpSU, SU, const_cast(dep)); + } + + if (!SU->addPred(dep) && !dep.isCtrl() && OpSU->NumRegDefsLeft > 0) { + // Multiple register uses are combined in the same SUnit. For example, + // we could have a set of glued nodes with all their defs consumed by + // another set of glued nodes. Register pressure tracking sees this as + // a single use, so to keep pressure balanced we reduce the defs. + --OpSU->NumRegDefsLeft; + } + } + } + } +} + +/// BuildSchedGraph - Build the SUnit graph from the selection dag that we +/// are input. This SUnit graph is similar to the SelectionDAG, but +/// excludes nodes that aren't interesting to scheduling, and represents +/// glued together nodes with a single SUnit. +void ScheduleDAGSDNodes::BuildSchedGraph(AliasAnalysis *AA) { + // Cluster certain nodes which should be scheduled together. + ClusterNodes(); + // Populate the SUnits array. + BuildSchedUnits(); + // Compute all the scheduling dependencies between nodes. + AddSchedEdges(); +} + +// Initialize NumNodeDefs for the current Node's opcode. +void ScheduleDAGSDNodes::RegDefIter::InitNodeNumDefs() { + // Check for phys reg copy. + if (!Node) + return; + + if (!Node->isMachineOpcode()) { + if (Node->getOpcode() == ISD::CopyFromReg) + NodeNumDefs = 1; + else + NodeNumDefs = 0; + return; + } + unsigned POpc = Node->getMachineOpcode(); + if (POpc == TargetOpcode::IMPLICIT_DEF) { + // No register need be allocated for this. + NodeNumDefs = 0; + return; + } + unsigned NRegDefs = SchedDAG->TII->get(Node->getMachineOpcode()).getNumDefs(); + // Some instructions define regs that are not represented in the selection DAG + // (e.g. unused flags). See tMOVi8. Make sure we don't access past NumValues. + NodeNumDefs = std::min(Node->getNumValues(), NRegDefs); + DefIdx = 0; +} + +// Construct a RegDefIter for this SUnit and find the first valid value. +ScheduleDAGSDNodes::RegDefIter::RegDefIter(const SUnit *SU, + const ScheduleDAGSDNodes *SD) + : SchedDAG(SD), Node(SU->getNode()), DefIdx(0), NodeNumDefs(0) { + InitNodeNumDefs(); + Advance(); +} + +// Advance to the next valid value defined by the SUnit. +void ScheduleDAGSDNodes::RegDefIter::Advance() { + for (;Node;) { // Visit all glued nodes. + for (;DefIdx < NodeNumDefs; ++DefIdx) { + if (!Node->hasAnyUseOfValue(DefIdx)) + continue; + if (Node->isMachineOpcode() && + Node->getMachineOpcode() == TargetOpcode::EXTRACT_SUBREG) { + // Propagate the incoming (full-register) type. I doubt it's needed. + ValueType = Node->getOperand(0).getValueType(); + } + else { + ValueType = Node->getValueType(DefIdx); + } + ++DefIdx; + return; // Found a normal regdef. + } + Node = Node->getGluedNode(); + if (Node == NULL) { + return; // No values left to visit. + } + InitNodeNumDefs(); + } +} + +void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { + assert(SU->NumRegDefsLeft == 0 && "expect a new node"); + for (RegDefIter I(SU, this); I.IsValid(); I.Advance()) { + assert(SU->NumRegDefsLeft < USHRT_MAX && "overflow is ok but unexpected"); + ++SU->NumRegDefsLeft; + } +} + +void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) { + // Check to see if the scheduler cares about latencies. + if (ForceUnitLatencies()) { + SU->Latency = 1; + return; + } + + if (!InstrItins || InstrItins->isEmpty()) { + SDNode *N = SU->getNode(); + if (N && N->isMachineOpcode() && + TII->isHighLatencyDef(N->getMachineOpcode())) + SU->Latency = HighLatencyCycles; + else + SU->Latency = 1; + return; + } + + // Compute the latency for the node. We use the sum of the latencies for + // all nodes glued together into this SUnit. + SU->Latency = 0; + for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) + if (N->isMachineOpcode()) + SU->Latency += TII->getInstrLatency(InstrItins, N); +} + +void ScheduleDAGSDNodes::ComputeOperandLatency(SDNode *Def, SDNode *Use, + unsigned OpIdx, SDep& dep) const{ + // Check to see if the scheduler cares about latencies. + if (ForceUnitLatencies()) + return; + + if (dep.getKind() != SDep::Data) + return; + + unsigned DefIdx = Use->getOperand(OpIdx).getResNo(); + if (Use->isMachineOpcode()) + // Adjust the use operand index by num of defs. + OpIdx += TII->get(Use->getMachineOpcode()).getNumDefs(); + int Latency = TII->getOperandLatency(InstrItins, Def, DefIdx, Use, OpIdx); + if (Latency > 1 && Use->getOpcode() == ISD::CopyToReg && + !BB->succ_empty()) { + unsigned Reg = cast(Use->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + // This copy is a liveout value. It is likely coalesced, so reduce the + // latency so not to penalize the def. + // FIXME: need target specific adjustment here? + Latency = (Latency > 1) ? Latency - 1 : 1; + } + if (Latency >= 0) + dep.setLatency(Latency); +} + +void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const { + if (!SU->getNode()) { + dbgs() << "PHYS REG COPY\n"; + return; + } + + SU->getNode()->dump(DAG); + dbgs() << "\n"; + SmallVector GluedNodes; + for (SDNode *N = SU->getNode()->getGluedNode(); N; N = N->getGluedNode()) + GluedNodes.push_back(N); + while (!GluedNodes.empty()) { + dbgs() << " "; + GluedNodes.back()->dump(DAG); + dbgs() << "\n"; + GluedNodes.pop_back(); + } +} + +namespace { + struct OrderSorter { + bool operator()(const std::pair &A, + const std::pair &B) { + return A.first < B.first; + } + }; +} + +/// ProcessSDDbgValues - Process SDDbgValues assoicated with this node. +static void ProcessSDDbgValues(SDNode *N, SelectionDAG *DAG, + InstrEmitter &Emitter, + SmallVector, 32> &Orders, + DenseMap &VRBaseMap, + unsigned Order) { + if (!N->getHasDebugValue()) + return; + + // Opportunistically insert immediate dbg_value uses, i.e. those with source + // order number right after the N. + MachineBasicBlock *BB = Emitter.getBlock(); + MachineBasicBlock::iterator InsertPos = Emitter.getInsertPos(); + SmallVector &DVs = DAG->GetDbgValues(N); + for (unsigned i = 0, e = DVs.size(); i != e; ++i) { + if (DVs[i]->isInvalidated()) + continue; + unsigned DVOrder = DVs[i]->getOrder(); + if (!Order || DVOrder == ++Order) { + MachineInstr *DbgMI = Emitter.EmitDbgValue(DVs[i], VRBaseMap); + if (DbgMI) { + Orders.push_back(std::make_pair(DVOrder, DbgMI)); + BB->insert(InsertPos, DbgMI); + } + DVs[i]->setIsInvalidated(); + } + } +} + +// ProcessSourceNode - Process nodes with source order numbers. These are added +// to a vector which EmitSchedule uses to determine how to insert dbg_value +// instructions in the right order. +static void ProcessSourceNode(SDNode *N, SelectionDAG *DAG, + InstrEmitter &Emitter, + DenseMap &VRBaseMap, + SmallVector, 32> &Orders, + SmallSet &Seen) { + unsigned Order = DAG->GetOrdering(N); + if (!Order || !Seen.insert(Order)) { + // Process any valid SDDbgValues even if node does not have any order + // assigned. + ProcessSDDbgValues(N, DAG, Emitter, Orders, VRBaseMap, 0); + return; + } + + MachineBasicBlock *BB = Emitter.getBlock(); + if (Emitter.getInsertPos() == BB->begin() || BB->back().isPHI()) { + // Did not insert any instruction. + Orders.push_back(std::make_pair(Order, (MachineInstr*)0)); + return; + } + + Orders.push_back(std::make_pair(Order, prior(Emitter.getInsertPos()))); + ProcessSDDbgValues(N, DAG, Emitter, Orders, VRBaseMap, Order); +} + + +/// EmitSchedule - Emit the machine code in scheduled order. +MachineBasicBlock *ScheduleDAGSDNodes::EmitSchedule() { + InstrEmitter Emitter(BB, InsertPos); + DenseMap VRBaseMap; + DenseMap CopyVRBaseMap; + SmallVector, 32> Orders; + SmallSet Seen; + bool HasDbg = DAG->hasDebugValues(); + + // If this is the first BB, emit byval parameter dbg_value's. + if (HasDbg && BB->getParent()->begin() == MachineFunction::iterator(BB)) { + SDDbgInfo::DbgIterator PDI = DAG->ByvalParmDbgBegin(); + SDDbgInfo::DbgIterator PDE = DAG->ByvalParmDbgEnd(); + for (; PDI != PDE; ++PDI) { + MachineInstr *DbgMI= Emitter.EmitDbgValue(*PDI, VRBaseMap); + if (DbgMI) + BB->insert(InsertPos, DbgMI); + } + } + + for (unsigned i = 0, e = Sequence.size(); i != e; i++) { + SUnit *SU = Sequence[i]; + if (!SU) { + // Null SUnit* is a noop. + EmitNoop(); + continue; + } + + // For pre-regalloc scheduling, create instructions corresponding to the + // SDNode and any glued SDNodes and append them to the block. + if (!SU->getNode()) { + // Emit a copy. + EmitPhysRegCopy(SU, CopyVRBaseMap); + continue; + } + + SmallVector GluedNodes; + for (SDNode *N = SU->getNode()->getGluedNode(); N; + N = N->getGluedNode()) + GluedNodes.push_back(N); + while (!GluedNodes.empty()) { + SDNode *N = GluedNodes.back(); + Emitter.EmitNode(GluedNodes.back(), SU->OrigNode != SU, SU->isCloned, + VRBaseMap); + // Remember the source order of the inserted instruction. + if (HasDbg) + ProcessSourceNode(N, DAG, Emitter, VRBaseMap, Orders, Seen); + GluedNodes.pop_back(); + } + Emitter.EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, + VRBaseMap); + // Remember the source order of the inserted instruction. + if (HasDbg) + ProcessSourceNode(SU->getNode(), DAG, Emitter, VRBaseMap, Orders, + Seen); + } + + // Insert all the dbg_values which have not already been inserted in source + // order sequence. + if (HasDbg) { + MachineBasicBlock::iterator BBBegin = BB->getFirstNonPHI(); + + // Sort the source order instructions and use the order to insert debug + // values. + std::sort(Orders.begin(), Orders.end(), OrderSorter()); + + SDDbgInfo::DbgIterator DI = DAG->DbgBegin(); + SDDbgInfo::DbgIterator DE = DAG->DbgEnd(); + // Now emit the rest according to source order. + unsigned LastOrder = 0; + for (unsigned i = 0, e = Orders.size(); i != e && DI != DE; ++i) { + unsigned Order = Orders[i].first; + MachineInstr *MI = Orders[i].second; + // Insert all SDDbgValue's whose order(s) are before "Order". + if (!MI) + continue; + for (; DI != DE && + (*DI)->getOrder() >= LastOrder && (*DI)->getOrder() < Order; ++DI) { + if ((*DI)->isInvalidated()) + continue; + MachineInstr *DbgMI = Emitter.EmitDbgValue(*DI, VRBaseMap); + if (DbgMI) { + if (!LastOrder) + // Insert to start of the BB (after PHIs). + BB->insert(BBBegin, DbgMI); + else { + // Insert at the instruction, which may be in a different + // block, if the block was split by a custom inserter. + MachineBasicBlock::iterator Pos = MI; + MI->getParent()->insert(llvm::next(Pos), DbgMI); + } + } + } + LastOrder = Order; + } + // Add trailing DbgValue's before the terminator. FIXME: May want to add + // some of them before one or more conditional branches? + while (DI != DE) { + MachineBasicBlock *InsertBB = Emitter.getBlock(); + MachineBasicBlock::iterator Pos= Emitter.getBlock()->getFirstTerminator(); + if (!(*DI)->isInvalidated()) { + MachineInstr *DbgMI= Emitter.EmitDbgValue(*DI, VRBaseMap); + if (DbgMI) + InsertBB->insert(Pos, DbgMI); + } + ++DI; + } + } + + BB = Emitter.getBlock(); + InsertPos = Emitter.getInsertPos(); + return BB; +} diff --git a/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h b/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h new file mode 100644 index 00000000000..cc7310e4ca4 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h @@ -0,0 +1,151 @@ +//===---- ScheduleDAGSDNodes.h - SDNode Scheduling --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScheduleDAGSDNodes class, which implements +// scheduling for an SDNode-based dependency graph. +// +//===----------------------------------------------------------------------===// + +#ifndef SCHEDULEDAGSDNODES_H +#define SCHEDULEDAGSDNODES_H + +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/CodeGen/SelectionDAG.h" + +namespace llvm { + /// ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs. + /// + /// Edges between SUnits are initially based on edges in the SelectionDAG, + /// and additional edges can be added by the schedulers as heuristics. + /// SDNodes such as Constants, Registers, and a few others that are not + /// interesting to schedulers are not allocated SUnits. + /// + /// SDNodes with MVT::Glue operands are grouped along with the flagged + /// nodes into a single SUnit so that they are scheduled together. + /// + /// SDNode-based scheduling graphs do not use SDep::Anti or SDep::Output + /// edges. Physical register dependence information is not carried in + /// the DAG and must be handled explicitly by schedulers. + /// + class ScheduleDAGSDNodes : public ScheduleDAG { + public: + SelectionDAG *DAG; // DAG of the current basic block + const InstrItineraryData *InstrItins; + + explicit ScheduleDAGSDNodes(MachineFunction &mf); + + virtual ~ScheduleDAGSDNodes() {} + + /// Run - perform scheduling. + /// + void Run(SelectionDAG *dag, MachineBasicBlock *bb, + MachineBasicBlock::iterator insertPos); + + /// isPassiveNode - Return true if the node is a non-scheduled leaf. + /// + static bool isPassiveNode(SDNode *Node) { + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (isa(Node)) return true; + if (Node->getOpcode() == ISD::EntryToken || + isa(Node)) return true; + return false; + } + + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(SDNode *N); + + /// Clone - Creates a clone of the specified SUnit. It does not copy the + /// predecessors / successors info nor the temporary scheduling states. + /// + SUnit *Clone(SUnit *N); + + /// BuildSchedGraph - Build the SUnit graph from the selection dag that we + /// are input. This SUnit graph is similar to the SelectionDAG, but + /// excludes nodes that aren't interesting to scheduling, and represents + /// flagged together nodes with a single SUnit. + virtual void BuildSchedGraph(AliasAnalysis *AA); + + /// InitNumRegDefsLeft - Determine the # of regs defined by this node. + /// + void InitNumRegDefsLeft(SUnit *SU); + + /// ComputeLatency - Compute node latency. + /// + virtual void ComputeLatency(SUnit *SU); + + /// ComputeOperandLatency - Override dependence edge latency using + /// operand use/def information + /// + virtual void ComputeOperandLatency(SUnit *Def, SUnit *Use, + SDep& dep) const { } + + virtual void ComputeOperandLatency(SDNode *Def, SDNode *Use, + unsigned OpIdx, SDep& dep) const; + + virtual MachineBasicBlock *EmitSchedule(); + + /// Schedule - Order nodes according to selected style, filling + /// in the Sequence member. + /// + virtual void Schedule() = 0; + + virtual void dumpNode(const SUnit *SU) const; + + virtual std::string getGraphNodeLabel(const SUnit *SU) const; + + virtual void getCustomGraphFeatures(GraphWriter &GW) const; + + /// RegDefIter - In place iteration over the values defined by an + /// SUnit. This does not need copies of the iterator or any other STLisms. + /// The iterator creates itself, rather than being provided by the SchedDAG. + class RegDefIter { + const ScheduleDAGSDNodes *SchedDAG; + const SDNode *Node; + unsigned DefIdx; + unsigned NodeNumDefs; + EVT ValueType; + public: + RegDefIter(const SUnit *SU, const ScheduleDAGSDNodes *SD); + + bool IsValid() const { return Node != NULL; } + + EVT GetValue() const { + assert(IsValid() && "bad iterator"); + return ValueType; + } + + void Advance(); + private: + void InitNodeNumDefs(); + }; + + private: + /// ClusterNeighboringLoads - Cluster loads from "near" addresses into + /// combined SUnits. + void ClusterNeighboringLoads(SDNode *Node); + /// ClusterNodes - Cluster certain nodes which should be scheduled together. + /// + void ClusterNodes(); + + /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph. + void BuildSchedUnits(); + void AddSchedEdges(); + }; +} + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/final/lib/CodeGen/SelectionDAG/SelectionDAG.cpp new file mode 100644 index 00000000000..8deaae935a6 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -0,0 +1,6623 @@ +//===-- SelectionDAG.cpp - Implement the SelectionDAG data structures -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAG class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SelectionDAG.h" +#include "SDNodeOrdering.h" +#include "SDNodeDbgValue.h" +#include "llvm/Constants.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Function.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetSelectionDAGInfo.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mutex.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +/// makeVTList - Return an instance of the SDVTList struct initialized with the +/// specified members. +static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { + SDVTList Res = {VTs, NumVTs}; + return Res; +} + +static const fltSemantics *EVTToAPFloatSemantics(EVT VT) { + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("Unknown FP format"); + case MVT::f32: return &APFloat::IEEEsingle; + case MVT::f64: return &APFloat::IEEEdouble; + case MVT::f80: return &APFloat::x87DoubleExtended; + case MVT::f128: return &APFloat::IEEEquad; + case MVT::ppcf128: return &APFloat::PPCDoubleDouble; + } +} + +SelectionDAG::DAGUpdateListener::~DAGUpdateListener() {} + +//===----------------------------------------------------------------------===// +// ConstantFPSDNode Class +//===----------------------------------------------------------------------===// + +/// isExactlyValue - We don't rely on operator== working on double values, as +/// it returns true for things that are clearly not equal, like -0.0 and 0.0. +/// As such, this method can be used to do an exact bit-for-bit comparison of +/// two floating point values. +bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const { + return getValueAPF().bitwiseIsEqual(V); +} + +bool ConstantFPSDNode::isValueValidForType(EVT VT, + const APFloat& Val) { + assert(VT.isFloatingPoint() && "Can only convert between FP types"); + + // PPC long double cannot be converted to any other type. + if (VT == MVT::ppcf128 || + &Val.getSemantics() == &APFloat::PPCDoubleDouble) + return false; + + // convert modifies in place, so make a copy. + APFloat Val2 = APFloat(Val); + bool losesInfo; + (void) Val2.convert(*EVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven, + &losesInfo); + return !losesInfo; +} + +//===----------------------------------------------------------------------===// +// ISD Namespace +//===----------------------------------------------------------------------===// + +/// isBuildVectorAllOnes - Return true if the specified node is a +/// BUILD_VECTOR where all of the elements are ~0 or undef. +bool ISD::isBuildVectorAllOnes(const SDNode *N) { + // Look through a bit convert. + if (N->getOpcode() == ISD::BITCAST) + N = N->getOperand(0).getNode(); + + if (N->getOpcode() != ISD::BUILD_VECTOR) return false; + + unsigned i = 0, e = N->getNumOperands(); + + // Skip over all of the undef values. + while (i != e && N->getOperand(i).getOpcode() == ISD::UNDEF) + ++i; + + // Do not accept an all-undef vector. + if (i == e) return false; + + // Do not accept build_vectors that aren't all constants or which have non-~0 + // elements. + SDValue NotZero = N->getOperand(i); + if (isa(NotZero)) { + if (!cast(NotZero)->isAllOnesValue()) + return false; + } else if (isa(NotZero)) { + if (!cast(NotZero)->getValueAPF(). + bitcastToAPInt().isAllOnesValue()) + return false; + } else + return false; + + // Okay, we have at least one ~0 value, check to see if the rest match or are + // undefs. + for (++i; i != e; ++i) + if (N->getOperand(i) != NotZero && + N->getOperand(i).getOpcode() != ISD::UNDEF) + return false; + return true; +} + + +/// isBuildVectorAllZeros - Return true if the specified node is a +/// BUILD_VECTOR where all of the elements are 0 or undef. +bool ISD::isBuildVectorAllZeros(const SDNode *N) { + // Look through a bit convert. + if (N->getOpcode() == ISD::BITCAST) + N = N->getOperand(0).getNode(); + + if (N->getOpcode() != ISD::BUILD_VECTOR) return false; + + unsigned i = 0, e = N->getNumOperands(); + + // Skip over all of the undef values. + while (i != e && N->getOperand(i).getOpcode() == ISD::UNDEF) + ++i; + + // Do not accept an all-undef vector. + if (i == e) return false; + + // Do not accept build_vectors that aren't all constants or which have non-0 + // elements. + SDValue Zero = N->getOperand(i); + if (isa(Zero)) { + if (!cast(Zero)->isNullValue()) + return false; + } else if (isa(Zero)) { + if (!cast(Zero)->getValueAPF().isPosZero()) + return false; + } else + return false; + + // Okay, we have at least one 0 value, check to see if the rest match or are + // undefs. + for (++i; i != e; ++i) + if (N->getOperand(i) != Zero && + N->getOperand(i).getOpcode() != ISD::UNDEF) + return false; + return true; +} + +/// isScalarToVector - Return true if the specified node is a +/// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low +/// element is not an undef. +bool ISD::isScalarToVector(const SDNode *N) { + if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) + return true; + + if (N->getOpcode() != ISD::BUILD_VECTOR) + return false; + if (N->getOperand(0).getOpcode() == ISD::UNDEF) + return false; + unsigned NumElems = N->getNumOperands(); + if (NumElems == 1) + return false; + for (unsigned i = 1; i < NumElems; ++i) { + SDValue V = N->getOperand(i); + if (V.getOpcode() != ISD::UNDEF) + return false; + } + return true; +} + +/// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) +/// when given the operation for (X op Y). +ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) { + // To perform this operation, we just need to swap the L and G bits of the + // operation. + unsigned OldL = (Operation >> 2) & 1; + unsigned OldG = (Operation >> 1) & 1; + return ISD::CondCode((Operation & ~6) | // Keep the N, U, E bits + (OldL << 1) | // New G bit + (OldG << 2)); // New L bit. +} + +/// getSetCCInverse - Return the operation corresponding to !(X op Y), where +/// 'op' is a valid SetCC operation. +ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) { + unsigned Operation = Op; + if (isInteger) + Operation ^= 7; // Flip L, G, E bits, but not U. + else + Operation ^= 15; // Flip all of the condition bits. + + if (Operation > ISD::SETTRUE2) + Operation &= ~8; // Don't let N and U bits get set. + + return ISD::CondCode(Operation); +} + + +/// isSignedOp - For an integer comparison, return 1 if the comparison is a +/// signed operation and 2 if the result is an unsigned comparison. Return zero +/// if the operation does not depend on the sign of the input (setne and seteq). +static int isSignedOp(ISD::CondCode Opcode) { + switch (Opcode) { + default: llvm_unreachable("Illegal integer setcc operation!"); + case ISD::SETEQ: + case ISD::SETNE: return 0; + case ISD::SETLT: + case ISD::SETLE: + case ISD::SETGT: + case ISD::SETGE: return 1; + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETUGT: + case ISD::SETUGE: return 2; + } +} + +/// getSetCCOrOperation - Return the result of a logical OR between different +/// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This function +/// returns SETCC_INVALID if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCOrOperation(ISD::CondCode Op1, ISD::CondCode Op2, + bool isInteger) { + if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) + // Cannot fold a signed integer setcc with an unsigned integer setcc. + return ISD::SETCC_INVALID; + + unsigned Op = Op1 | Op2; // Combine all of the condition bits. + + // If the N and U bits get set then the resultant comparison DOES suddenly + // care about orderedness, and is true when ordered. + if (Op > ISD::SETTRUE2) + Op &= ~16; // Clear the U bit if the N bit is set. + + // Canonicalize illegal integer setcc's. + if (isInteger && Op == ISD::SETUNE) // e.g. SETUGT | SETULT + Op = ISD::SETNE; + + return ISD::CondCode(Op); +} + +/// getSetCCAndOperation - Return the result of a logical AND between different +/// comparisons of identical values: ((X op1 Y) & (X op2 Y)). This +/// function returns zero if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2, + bool isInteger) { + if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) + // Cannot fold a signed setcc with an unsigned setcc. + return ISD::SETCC_INVALID; + + // Combine all of the condition bits. + ISD::CondCode Result = ISD::CondCode(Op1 & Op2); + + // Canonicalize illegal integer setcc's. + if (isInteger) { + switch (Result) { + default: break; + case ISD::SETUO : Result = ISD::SETFALSE; break; // SETUGT & SETULT + case ISD::SETOEQ: // SETEQ & SETU[LG]E + case ISD::SETUEQ: Result = ISD::SETEQ ; break; // SETUGE & SETULE + case ISD::SETOLT: Result = ISD::SETULT ; break; // SETULT & SETNE + case ISD::SETOGT: Result = ISD::SETUGT ; break; // SETUGT & SETNE + } + } + + return Result; +} + +//===----------------------------------------------------------------------===// +// SDNode Profile Support +//===----------------------------------------------------------------------===// + +/// AddNodeIDOpcode - Add the node opcode to the NodeID data. +/// +static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC) { + ID.AddInteger(OpC); +} + +/// AddNodeIDValueTypes - Value type lists are intern'd so we can represent them +/// solely with their pointer. +static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) { + ID.AddPointer(VTList.VTs); +} + +/// AddNodeIDOperands - Various routines for adding operands to the NodeID data. +/// +static void AddNodeIDOperands(FoldingSetNodeID &ID, + const SDValue *Ops, unsigned NumOps) { + for (; NumOps; --NumOps, ++Ops) { + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); + } +} + +/// AddNodeIDOperands - Various routines for adding operands to the NodeID data. +/// +static void AddNodeIDOperands(FoldingSetNodeID &ID, + const SDUse *Ops, unsigned NumOps) { + for (; NumOps; --NumOps, ++Ops) { + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); + } +} + +static void AddNodeIDNode(FoldingSetNodeID &ID, + unsigned short OpC, SDVTList VTList, + const SDValue *OpList, unsigned N) { + AddNodeIDOpcode(ID, OpC); + AddNodeIDValueTypes(ID, VTList); + AddNodeIDOperands(ID, OpList, N); +} + +/// AddNodeIDCustom - If this is an SDNode with special info, add this info to +/// the NodeID data. +static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { + switch (N->getOpcode()) { + case ISD::TargetExternalSymbol: + case ISD::ExternalSymbol: + llvm_unreachable("Should only be used on nodes with operands"); + default: break; // Normal nodes don't need extra info. + case ISD::TargetConstant: + case ISD::Constant: + ID.AddPointer(cast(N)->getConstantIntValue()); + break; + case ISD::TargetConstantFP: + case ISD::ConstantFP: { + ID.AddPointer(cast(N)->getConstantFPValue()); + break; + } + case ISD::TargetGlobalAddress: + case ISD::GlobalAddress: + case ISD::TargetGlobalTLSAddress: + case ISD::GlobalTLSAddress: { + const GlobalAddressSDNode *GA = cast(N); + ID.AddPointer(GA->getGlobal()); + ID.AddInteger(GA->getOffset()); + ID.AddInteger(GA->getTargetFlags()); + break; + } + case ISD::BasicBlock: + ID.AddPointer(cast(N)->getBasicBlock()); + break; + case ISD::Register: + ID.AddInteger(cast(N)->getReg()); + break; + + case ISD::SRCVALUE: + ID.AddPointer(cast(N)->getValue()); + break; + case ISD::FrameIndex: + case ISD::TargetFrameIndex: + ID.AddInteger(cast(N)->getIndex()); + break; + case ISD::JumpTable: + case ISD::TargetJumpTable: + ID.AddInteger(cast(N)->getIndex()); + ID.AddInteger(cast(N)->getTargetFlags()); + break; + case ISD::ConstantPool: + case ISD::TargetConstantPool: { + const ConstantPoolSDNode *CP = cast(N); + ID.AddInteger(CP->getAlignment()); + ID.AddInteger(CP->getOffset()); + if (CP->isMachineConstantPoolEntry()) + CP->getMachineCPVal()->AddSelectionDAGCSEId(ID); + else + ID.AddPointer(CP->getConstVal()); + ID.AddInteger(CP->getTargetFlags()); + break; + } + case ISD::LOAD: { + const LoadSDNode *LD = cast(N); + ID.AddInteger(LD->getMemoryVT().getRawBits()); + ID.AddInteger(LD->getRawSubclassData()); + break; + } + case ISD::STORE: { + const StoreSDNode *ST = cast(N); + ID.AddInteger(ST->getMemoryVT().getRawBits()); + ID.AddInteger(ST->getRawSubclassData()); + break; + } + case ISD::ATOMIC_CMP_SWAP: + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_SUB: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_LOAD_NAND: + case ISD::ATOMIC_LOAD_MIN: + case ISD::ATOMIC_LOAD_MAX: + case ISD::ATOMIC_LOAD_UMIN: + case ISD::ATOMIC_LOAD_UMAX: { + const AtomicSDNode *AT = cast(N); + ID.AddInteger(AT->getMemoryVT().getRawBits()); + ID.AddInteger(AT->getRawSubclassData()); + break; + } + case ISD::VECTOR_SHUFFLE: { + const ShuffleVectorSDNode *SVN = cast(N); + for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements(); + i != e; ++i) + ID.AddInteger(SVN->getMaskElt(i)); + break; + } + case ISD::TargetBlockAddress: + case ISD::BlockAddress: { + ID.AddPointer(cast(N)->getBlockAddress()); + ID.AddInteger(cast(N)->getTargetFlags()); + break; + } + } // end switch (N->getOpcode()) +} + +/// AddNodeIDNode - Generic routine for adding a nodes info to the NodeID +/// data. +static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) { + AddNodeIDOpcode(ID, N->getOpcode()); + // Add the return value info. + AddNodeIDValueTypes(ID, N->getVTList()); + // Add the operand info. + AddNodeIDOperands(ID, N->op_begin(), N->getNumOperands()); + + // Handle SDNode leafs with special info. + AddNodeIDCustom(ID, N); +} + +/// encodeMemSDNodeFlags - Generic routine for computing a value for use in +/// the CSE map that carries volatility, temporalness, indexing mode, and +/// extension/truncation information. +/// +static inline unsigned +encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, bool isVolatile, + bool isNonTemporal) { + assert((ConvType & 3) == ConvType && + "ConvType may not require more than 2 bits!"); + assert((AM & 7) == AM && + "AM may not require more than 3 bits!"); + return ConvType | + (AM << 2) | + (isVolatile << 5) | + (isNonTemporal << 6); +} + +//===----------------------------------------------------------------------===// +// SelectionDAG Class +//===----------------------------------------------------------------------===// + +/// doNotCSE - Return true if CSE should not be performed for this node. +static bool doNotCSE(SDNode *N) { + if (N->getValueType(0) == MVT::Glue) + return true; // Never CSE anything that produces a flag. + + switch (N->getOpcode()) { + default: break; + case ISD::HANDLENODE: + case ISD::EH_LABEL: + return true; // Never CSE these nodes. + } + + // Check that remaining values produced are not flags. + for (unsigned i = 1, e = N->getNumValues(); i != e; ++i) + if (N->getValueType(i) == MVT::Glue) + return true; // Never CSE anything that produces a flag. + + return false; +} + +/// RemoveDeadNodes - This method deletes all unreachable nodes in the +/// SelectionDAG. +void SelectionDAG::RemoveDeadNodes() { + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted. + HandleSDNode Dummy(getRoot()); + + SmallVector DeadNodes; + + // Add all obviously-dead nodes to the DeadNodes worklist. + for (allnodes_iterator I = allnodes_begin(), E = allnodes_end(); I != E; ++I) + if (I->use_empty()) + DeadNodes.push_back(I); + + RemoveDeadNodes(DeadNodes); + + // If the root changed (e.g. it was a dead load, update the root). + setRoot(Dummy.getValue()); +} + +/// RemoveDeadNodes - This method deletes the unreachable nodes in the +/// given list, and any nodes that become unreachable as a result. +void SelectionDAG::RemoveDeadNodes(SmallVectorImpl &DeadNodes, + DAGUpdateListener *UpdateListener) { + + // Process the worklist, deleting the nodes and adding their uses to the + // worklist. + while (!DeadNodes.empty()) { + SDNode *N = DeadNodes.pop_back_val(); + + if (UpdateListener) + UpdateListener->NodeDeleted(N, 0); + + // Take the node out of the appropriate CSE map. + RemoveNodeFromCSEMaps(N); + + // Next, brutally remove the operand list. This is safe to do, as there are + // no cycles in the graph. + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Operand = Use.getNode(); + Use.set(SDValue()); + + // Now that we removed this operand, see if there are no uses of it left. + if (Operand->use_empty()) + DeadNodes.push_back(Operand); + } + + DeallocateNode(N); + } +} + +void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ + SmallVector DeadNodes(1, N); + RemoveDeadNodes(DeadNodes, UpdateListener); +} + +void SelectionDAG::DeleteNode(SDNode *N) { + // First take this out of the appropriate CSE map. + RemoveNodeFromCSEMaps(N); + + // Finally, remove uses due to operands of this node, remove from the + // AllNodes list, and delete the node. + DeleteNodeNotInCSEMaps(N); +} + +void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) { + assert(N != AllNodes.begin() && "Cannot delete the entry node!"); + assert(N->use_empty() && "Cannot delete a node that is not dead!"); + + // Drop all of the operands and decrement used node's use counts. + N->DropOperands(); + + DeallocateNode(N); +} + +void SelectionDAG::DeallocateNode(SDNode *N) { + if (N->OperandsNeedDelete) + delete[] N->OperandList; + + // Set the opcode to DELETED_NODE to help catch bugs when node + // memory is reallocated. + N->NodeType = ISD::DELETED_NODE; + + NodeAllocator.Deallocate(AllNodes.remove(N)); + + // Remove the ordering of this node. + Ordering->remove(N); + + // If any of the SDDbgValue nodes refer to this SDNode, invalidate them. + SmallVector &DbgVals = DbgInfo->getSDDbgValues(N); + for (unsigned i = 0, e = DbgVals.size(); i != e; ++i) + DbgVals[i]->setIsInvalidated(); +} + +/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that +/// correspond to it. This is useful when we're about to delete or repurpose +/// the node. We don't want future request for structurally identical nodes +/// to return N anymore. +bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { + bool Erased = false; + switch (N->getOpcode()) { + case ISD::HANDLENODE: return false; // noop. + case ISD::CONDCODE: + assert(CondCodeNodes[cast(N)->get()] && + "Cond code doesn't exist!"); + Erased = CondCodeNodes[cast(N)->get()] != 0; + CondCodeNodes[cast(N)->get()] = 0; + break; + case ISD::ExternalSymbol: + Erased = ExternalSymbols.erase(cast(N)->getSymbol()); + break; + case ISD::TargetExternalSymbol: { + ExternalSymbolSDNode *ESN = cast(N); + Erased = TargetExternalSymbols.erase( + std::pair(ESN->getSymbol(), + ESN->getTargetFlags())); + break; + } + case ISD::VALUETYPE: { + EVT VT = cast(N)->getVT(); + if (VT.isExtended()) { + Erased = ExtendedValueTypeNodes.erase(VT); + } else { + Erased = ValueTypeNodes[VT.getSimpleVT().SimpleTy] != 0; + ValueTypeNodes[VT.getSimpleVT().SimpleTy] = 0; + } + break; + } + default: + // Remove it from the CSE Map. + assert(N->getOpcode() != ISD::DELETED_NODE && "DELETED_NODE in CSEMap!"); + assert(N->getOpcode() != ISD::EntryToken && "EntryToken in CSEMap!"); + Erased = CSEMap.RemoveNode(N); + break; + } +#ifndef NDEBUG + // Verify that the node was actually in one of the CSE maps, unless it has a + // flag result (which cannot be CSE'd) or is one of the special cases that are + // not subject to CSE. + if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Glue && + !N->isMachineOpcode() && !doNotCSE(N)) { + N->dump(this); + dbgs() << "\n"; + llvm_unreachable("Node is not in map!"); + } +#endif + return Erased; +} + +/// AddModifiedNodeToCSEMaps - The specified node has been removed from the CSE +/// maps and modified in place. Add it back to the CSE maps, unless an identical +/// node already exists, in which case transfer all its users to the existing +/// node. This transfer can potentially trigger recursive merging. +/// +void +SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N, + DAGUpdateListener *UpdateListener) { + // For node types that aren't CSE'd, just act as if no identical node + // already exists. + if (!doNotCSE(N)) { + SDNode *Existing = CSEMap.GetOrInsertNode(N); + if (Existing != N) { + // If there was already an existing matching node, use ReplaceAllUsesWith + // to replace the dead one with the existing one. This can cause + // recursive merging of other unrelated nodes down the line. + ReplaceAllUsesWith(N, Existing, UpdateListener); + + // N is now dead. Inform the listener if it exists and delete it. + if (UpdateListener) + UpdateListener->NodeDeleted(N, Existing); + DeleteNodeNotInCSEMaps(N); + return; + } + } + + // If the node doesn't already exist, we updated it. Inform a listener if + // it exists. + if (UpdateListener) + UpdateListener->NodeUpdated(N); +} + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + SDValue Ops[] = { Op }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 1); + AddNodeIDCustom(ID, N); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + return Node; +} + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, + SDValue Op1, SDValue Op2, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + SDValue Ops[] = { Op1, Op2 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 2); + AddNodeIDCustom(ID, N); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + return Node; +} + + +/// FindModifiedNodeSlot - Find a slot for the specified node if its operands +/// were replaced with those specified. If this node is never memoized, +/// return null, otherwise return a pointer to the slot it would take. If a +/// node already exists with these operands, the slot will be non-null. +SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, + const SDValue *Ops,unsigned NumOps, + void *&InsertPos) { + if (doNotCSE(N)) + return 0; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); + AddNodeIDCustom(ID, N); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + return Node; +} + +#ifndef NDEBUG +/// VerifyNodeCommon - Sanity check the given node. Aborts if it is invalid. +static void VerifyNodeCommon(SDNode *N) { + switch (N->getOpcode()) { + default: + break; + case ISD::BUILD_PAIR: { + EVT VT = N->getValueType(0); + assert(N->getNumValues() == 1 && "Too many results!"); + assert(!VT.isVector() && (VT.isInteger() || VT.isFloatingPoint()) && + "Wrong return type!"); + assert(N->getNumOperands() == 2 && "Wrong number of operands!"); + assert(N->getOperand(0).getValueType() == N->getOperand(1).getValueType() && + "Mismatched operand types!"); + assert(N->getOperand(0).getValueType().isInteger() == VT.isInteger() && + "Wrong operand type!"); + assert(VT.getSizeInBits() == 2 * N->getOperand(0).getValueSizeInBits() && + "Wrong return type size"); + break; + } + case ISD::BUILD_VECTOR: { + assert(N->getNumValues() == 1 && "Too many results!"); + assert(N->getValueType(0).isVector() && "Wrong return type!"); + assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() && + "Wrong number of operands!"); + EVT EltVT = N->getValueType(0).getVectorElementType(); + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) + assert((I->getValueType() == EltVT || + (EltVT.isInteger() && I->getValueType().isInteger() && + EltVT.bitsLE(I->getValueType()))) && + "Wrong operand type!"); + break; + } + } +} + +/// VerifySDNode - Sanity check the given SDNode. Aborts if it is invalid. +static void VerifySDNode(SDNode *N) { + // The SDNode allocators cannot be used to allocate nodes with fields that are + // not present in an SDNode! + assert(!isa(N) && "Bad MemSDNode!"); + assert(!isa(N) && "Bad ShuffleVectorSDNode!"); + assert(!isa(N) && "Bad ConstantSDNode!"); + assert(!isa(N) && "Bad ConstantFPSDNode!"); + assert(!isa(N) && "Bad GlobalAddressSDNode!"); + assert(!isa(N) && "Bad FrameIndexSDNode!"); + assert(!isa(N) && "Bad JumpTableSDNode!"); + assert(!isa(N) && "Bad ConstantPoolSDNode!"); + assert(!isa(N) && "Bad BasicBlockSDNode!"); + assert(!isa(N) && "Bad SrcValueSDNode!"); + assert(!isa(N) && "Bad MDNodeSDNode!"); + assert(!isa(N) && "Bad RegisterSDNode!"); + assert(!isa(N) && "Bad BlockAddressSDNode!"); + assert(!isa(N) && "Bad EHLabelSDNode!"); + assert(!isa(N) && "Bad ExternalSymbolSDNode!"); + assert(!isa(N) && "Bad CondCodeSDNode!"); + assert(!isa(N) && "Bad CvtRndSatSDNode!"); + assert(!isa(N) && "Bad VTSDNode!"); + assert(!isa(N) && "Bad MachineSDNode!"); + + VerifyNodeCommon(N); +} + +/// VerifyMachineNode - Sanity check the given MachineNode. Aborts if it is +/// invalid. +static void VerifyMachineNode(SDNode *N) { + // The MachineNode allocators cannot be used to allocate nodes with fields + // that are not present in a MachineNode! + // Currently there are no such nodes. + + VerifyNodeCommon(N); +} +#endif // NDEBUG + +/// getEVTAlignment - Compute the default alignment value for the +/// given type. +/// +unsigned SelectionDAG::getEVTAlignment(EVT VT) const { + const Type *Ty = VT == MVT::iPTR ? + PointerType::get(Type::getInt8Ty(*getContext()), 0) : + VT.getTypeForEVT(*getContext()); + + return TLI.getTargetData()->getABITypeAlignment(Ty); +} + +// EntryNode could meaningfully have debug info if we can find it... +SelectionDAG::SelectionDAG(const TargetMachine &tm) + : TM(tm), TLI(*tm.getTargetLowering()), TSI(*tm.getSelectionDAGInfo()), + EntryNode(ISD::EntryToken, DebugLoc(), getVTList(MVT::Other)), + Root(getEntryNode()), Ordering(0) { + AllNodes.push_back(&EntryNode); + Ordering = new SDNodeOrdering(); + DbgInfo = new SDDbgInfo(); +} + +void SelectionDAG::init(MachineFunction &mf) { + MF = &mf; + Context = &mf.getFunction()->getContext(); +} + +SelectionDAG::~SelectionDAG() { + allnodes_clear(); + delete Ordering; + delete DbgInfo; +} + +void SelectionDAG::allnodes_clear() { + assert(&*AllNodes.begin() == &EntryNode); + AllNodes.remove(AllNodes.begin()); + while (!AllNodes.empty()) + DeallocateNode(AllNodes.begin()); +} + +void SelectionDAG::clear() { + allnodes_clear(); + OperandAllocator.Reset(); + CSEMap.clear(); + + ExtendedValueTypeNodes.clear(); + ExternalSymbols.clear(); + TargetExternalSymbols.clear(); + std::fill(CondCodeNodes.begin(), CondCodeNodes.end(), + static_cast(0)); + std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), + static_cast(0)); + + EntryNode.UseList = 0; + AllNodes.push_back(&EntryNode); + Root = getEntryNode(); + Ordering->clear(); + DbgInfo->clear(); +} + +SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { + return VT.bitsGT(Op.getValueType()) ? + getNode(ISD::SIGN_EXTEND, DL, VT, Op) : + getNode(ISD::TRUNCATE, DL, VT, Op); +} + +SDValue SelectionDAG::getZExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { + return VT.bitsGT(Op.getValueType()) ? + getNode(ISD::ZERO_EXTEND, DL, VT, Op) : + getNode(ISD::TRUNCATE, DL, VT, Op); +} + +SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT VT) { + assert(!VT.isVector() && + "getZeroExtendInReg should use the vector element type instead of " + "the vector type!"); + if (Op.getValueType() == VT) return Op; + unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits(); + APInt Imm = APInt::getLowBitsSet(BitWidth, + VT.getSizeInBits()); + return getNode(ISD::AND, DL, Op.getValueType(), Op, + getConstant(Imm, Op.getValueType())); +} + +/// getNOT - Create a bitwise NOT operation as (XOR Val, -1). +/// +SDValue SelectionDAG::getNOT(DebugLoc DL, SDValue Val, EVT VT) { + EVT EltVT = VT.getScalarType(); + SDValue NegOne = + getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), VT); + return getNode(ISD::XOR, DL, VT, Val, NegOne); +} + +SDValue SelectionDAG::getConstant(uint64_t Val, EVT VT, bool isT) { + EVT EltVT = VT.getScalarType(); + assert((EltVT.getSizeInBits() >= 64 || + (uint64_t)((int64_t)Val >> EltVT.getSizeInBits()) + 1 < 2) && + "getConstant with a uint64_t value that doesn't fit in the type!"); + return getConstant(APInt(EltVT.getSizeInBits(), Val), VT, isT); +} + +SDValue SelectionDAG::getConstant(const APInt &Val, EVT VT, bool isT) { + return getConstant(*ConstantInt::get(*Context, Val), VT, isT); +} + +SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) { + assert(VT.isInteger() && "Cannot create FP integer constant!"); + + EVT EltVT = VT.getScalarType(); + assert(Val.getBitWidth() == EltVT.getSizeInBits() && + "APInt size does not match type size!"); + + unsigned Opc = isT ? ISD::TargetConstant : ISD::Constant; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); + ID.AddPointer(&Val); + void *IP = 0; + SDNode *N = NULL; + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if (!VT.isVector()) + return SDValue(N, 0); + + if (!N) { + N = new (NodeAllocator) ConstantSDNode(isT, &Val, EltVT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + } + + SDValue Result(N, 0); + if (VT.isVector()) { + SmallVector Ops; + Ops.assign(VT.getVectorNumElements(), Result); + Result = getNode(ISD::BUILD_VECTOR, DebugLoc(), VT, &Ops[0], Ops.size()); + } + return Result; +} + +SDValue SelectionDAG::getIntPtrConstant(uint64_t Val, bool isTarget) { + return getConstant(Val, TLI.getPointerTy(), isTarget); +} + + +SDValue SelectionDAG::getConstantFP(const APFloat& V, EVT VT, bool isTarget) { + return getConstantFP(*ConstantFP::get(*getContext(), V), VT, isTarget); +} + +SDValue SelectionDAG::getConstantFP(const ConstantFP& V, EVT VT, bool isTarget){ + assert(VT.isFloatingPoint() && "Cannot create integer FP constant!"); + + EVT EltVT = VT.getScalarType(); + + // Do the map lookup using the actual bit pattern for the floating point + // value, so that we don't have problems with 0.0 comparing equal to -0.0, and + // we don't have issues with SNANs. + unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(EltVT), 0, 0); + ID.AddPointer(&V); + void *IP = 0; + SDNode *N = NULL; + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if (!VT.isVector()) + return SDValue(N, 0); + + if (!N) { + N = new (NodeAllocator) ConstantFPSDNode(isTarget, &V, EltVT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + } + + SDValue Result(N, 0); + if (VT.isVector()) { + SmallVector Ops; + Ops.assign(VT.getVectorNumElements(), Result); + // FIXME DebugLoc info might be appropriate here + Result = getNode(ISD::BUILD_VECTOR, DebugLoc(), VT, &Ops[0], Ops.size()); + } + return Result; +} + +SDValue SelectionDAG::getConstantFP(double Val, EVT VT, bool isTarget) { + EVT EltVT = VT.getScalarType(); + if (EltVT==MVT::f32) + return getConstantFP(APFloat((float)Val), VT, isTarget); + else if (EltVT==MVT::f64) + return getConstantFP(APFloat(Val), VT, isTarget); + else if (EltVT==MVT::f80 || EltVT==MVT::f128) { + bool ignored; + APFloat apf = APFloat(Val); + apf.convert(*EVTToAPFloatSemantics(EltVT), APFloat::rmNearestTiesToEven, + &ignored); + return getConstantFP(apf, VT, isTarget); + } else { + assert(0 && "Unsupported type in getConstantFP"); + return SDValue(); + } +} + +SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, DebugLoc DL, + EVT VT, int64_t Offset, + bool isTargetGA, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTargetGA) && + "Cannot set target flags on target-independent globals"); + + // Truncate (with sign-extension) the offset value to the pointer size. + EVT PTy = TLI.getPointerTy(); + unsigned BitWidth = PTy.getSizeInBits(); + if (BitWidth < 64) + Offset = (Offset << (64 - BitWidth) >> (64 - BitWidth)); + + const GlobalVariable *GVar = dyn_cast(GV); + if (!GVar) { + // If GV is an alias then use the aliasee for determining thread-localness. + if (const GlobalAlias *GA = dyn_cast(GV)) + GVar = dyn_cast_or_null(GA->resolveAliasedGlobal(false)); + } + + unsigned Opc; + if (GVar && GVar->isThreadLocal()) + Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress; + else + Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddPointer(GV); + ID.AddInteger(Offset); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) GlobalAddressSDNode(Opc, DL, GV, VT, + Offset, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) { + unsigned Opc = isTarget ? ISD::TargetFrameIndex : ISD::FrameIndex; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(FI); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) FrameIndexSDNode(FI, VT, isTarget); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getJumpTable(int JTI, EVT VT, bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent jump tables"); + unsigned Opc = isTarget ? ISD::TargetJumpTable : ISD::JumpTable; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(JTI); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) JumpTableSDNode(JTI, VT, isTarget, + TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getConstantPool(const Constant *C, EVT VT, + unsigned Alignment, int Offset, + bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent globals"); + if (Alignment == 0) + Alignment = TLI.getTargetData()->getPrefTypeAlignment(C->getType()); + unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(Alignment); + ID.AddInteger(Offset); + ID.AddPointer(C); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) ConstantPoolSDNode(isTarget, C, VT, Offset, + Alignment, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + + +SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT, + unsigned Alignment, int Offset, + bool isTarget, + unsigned char TargetFlags) { + assert((TargetFlags == 0 || isTarget) && + "Cannot set target flags on target-independent globals"); + if (Alignment == 0) + Alignment = TLI.getTargetData()->getPrefTypeAlignment(C->getType()); + unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddInteger(Alignment); + ID.AddInteger(Offset); + C->AddSelectionDAGCSEId(ID); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) ConstantPoolSDNode(isTarget, C, VT, Offset, + Alignment, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); + ID.AddPointer(MBB); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) BasicBlockSDNode(MBB); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getValueType(EVT VT) { + if (VT.isSimple() && (unsigned)VT.getSimpleVT().SimpleTy >= + ValueTypeNodes.size()) + ValueTypeNodes.resize(VT.getSimpleVT().SimpleTy+1); + + SDNode *&N = VT.isExtended() ? + ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT.getSimpleVT().SimpleTy]; + + if (N) return SDValue(N, 0); + N = new (NodeAllocator) VTSDNode(VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getExternalSymbol(const char *Sym, EVT VT) { + SDNode *&N = ExternalSymbols[Sym]; + if (N) return SDValue(N, 0); + N = new (NodeAllocator) ExternalSymbolSDNode(false, Sym, 0, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, EVT VT, + unsigned char TargetFlags) { + SDNode *&N = + TargetExternalSymbols[std::pair(Sym, + TargetFlags)]; + if (N) return SDValue(N, 0); + N = new (NodeAllocator) ExternalSymbolSDNode(true, Sym, TargetFlags, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) { + if ((unsigned)Cond >= CondCodeNodes.size()) + CondCodeNodes.resize(Cond+1); + + if (CondCodeNodes[Cond] == 0) { + CondCodeSDNode *N = new (NodeAllocator) CondCodeSDNode(Cond); + CondCodeNodes[Cond] = N; + AllNodes.push_back(N); + } + + return SDValue(CondCodeNodes[Cond], 0); +} + +// commuteShuffle - swaps the values of N1 and N2, and swaps all indices in +// the shuffle mask M that point at N1 to point at N2, and indices that point +// N2 to point at N1. +static void commuteShuffle(SDValue &N1, SDValue &N2, SmallVectorImpl &M) { + std::swap(N1, N2); + int NElts = M.size(); + for (int i = 0; i != NElts; ++i) { + if (M[i] >= NElts) + M[i] -= NElts; + else if (M[i] >= 0) + M[i] += NElts; + } +} + +SDValue SelectionDAG::getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1, + SDValue N2, const int *Mask) { + assert(N1.getValueType() == N2.getValueType() && "Invalid VECTOR_SHUFFLE"); + assert(VT.isVector() && N1.getValueType().isVector() && + "Vector Shuffle VTs must be a vectors"); + assert(VT.getVectorElementType() == N1.getValueType().getVectorElementType() + && "Vector Shuffle VTs must have same element type"); + + // Canonicalize shuffle undef, undef -> undef + if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + + // Validate that all indices in Mask are within the range of the elements + // input to the shuffle. + unsigned NElts = VT.getVectorNumElements(); + SmallVector MaskVec; + for (unsigned i = 0; i != NElts; ++i) { + assert(Mask[i] < (int)(NElts * 2) && "Index out of range"); + MaskVec.push_back(Mask[i]); + } + + // Canonicalize shuffle v, v -> v, undef + if (N1 == N2) { + N2 = getUNDEF(VT); + for (unsigned i = 0; i != NElts; ++i) + if (MaskVec[i] >= (int)NElts) MaskVec[i] -= NElts; + } + + // Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask. + if (N1.getOpcode() == ISD::UNDEF) + commuteShuffle(N1, N2, MaskVec); + + // Canonicalize all index into lhs, -> shuffle lhs, undef + // Canonicalize all index into rhs, -> shuffle rhs, undef + bool AllLHS = true, AllRHS = true; + bool N2Undef = N2.getOpcode() == ISD::UNDEF; + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= (int)NElts) { + if (N2Undef) + MaskVec[i] = -1; + else + AllLHS = false; + } else if (MaskVec[i] >= 0) { + AllRHS = false; + } + } + if (AllLHS && AllRHS) + return getUNDEF(VT); + if (AllLHS && !N2Undef) + N2 = getUNDEF(VT); + if (AllRHS) { + N1 = getUNDEF(VT); + commuteShuffle(N1, N2, MaskVec); + } + + // If Identity shuffle, or all shuffle in to undef, return that node. + bool AllUndef = true; + bool Identity = true; + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= 0 && MaskVec[i] != (int)i) Identity = false; + if (MaskVec[i] >= 0) AllUndef = false; + } + if (Identity && NElts == N1.getValueType().getVectorNumElements()) + return N1; + if (AllUndef) + return getUNDEF(VT); + + FoldingSetNodeID ID; + SDValue Ops[2] = { N1, N2 }; + AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), Ops, 2); + for (unsigned i = 0; i != NElts; ++i) + ID.AddInteger(MaskVec[i]); + + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + // Allocate the mask array for the node out of the BumpPtrAllocator, since + // SDNode doesn't have access to it. This memory will be "leaked" when + // the node is deallocated, but recovered when the NodeAllocator is released. + int *MaskAlloc = OperandAllocator.Allocate(NElts); + memcpy(MaskAlloc, &MaskVec[0], NElts * sizeof(int)); + + ShuffleVectorSDNode *N = + new (NodeAllocator) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getConvertRndSat(EVT VT, DebugLoc dl, + SDValue Val, SDValue DTy, + SDValue STy, SDValue Rnd, SDValue Sat, + ISD::CvtCode Code) { + // If the src and dest types are the same and the conversion is between + // integer types of the same sign or two floats, no conversion is necessary. + if (DTy == STy && + (Code == ISD::CVT_UU || Code == ISD::CVT_SS || Code == ISD::CVT_FF)) + return Val; + + FoldingSetNodeID ID; + SDValue Ops[] = { Val, DTy, STy, Rnd, Sat }; + AddNodeIDNode(ID, ISD::CONVERT_RNDSAT, getVTList(VT), &Ops[0], 5); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + CvtRndSatSDNode *N = new (NodeAllocator) CvtRndSatSDNode(VT, dl, Ops, 5, + Code); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getRegister(unsigned RegNo, EVT VT) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::Register, getVTList(VT), 0, 0); + ID.AddInteger(RegNo); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) RegisterSDNode(RegNo, VT); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label) { + FoldingSetNodeID ID; + SDValue Ops[] = { Root }; + AddNodeIDNode(ID, ISD::EH_LABEL, getVTList(MVT::Other), &Ops[0], 1); + ID.AddPointer(Label); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) EHLabelSDNode(dl, Root, Label); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + + +SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT, + bool isTarget, + unsigned char TargetFlags) { + unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); + ID.AddPointer(BA); + ID.AddInteger(TargetFlags); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) BlockAddressSDNode(Opc, VT, BA, TargetFlags); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getSrcValue(const Value *V) { + assert((!V || V->getType()->isPointerTy()) && + "SrcValue is not a pointer?"); + + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::SRCVALUE, getVTList(MVT::Other), 0, 0); + ID.AddPointer(V); + + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) SrcValueSDNode(V); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +/// getMDNode - Return an MDNodeSDNode which holds an MDNode. +SDValue SelectionDAG::getMDNode(const MDNode *MD) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::MDNODE_SDNODE, getVTList(MVT::Other), 0, 0); + ID.AddPointer(MD); + + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) MDNodeSDNode(MD); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + + +/// getShiftAmountOperand - Return the specified value casted to +/// the target's desired shift amount type. +SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) { + EVT OpTy = Op.getValueType(); + MVT ShTy = TLI.getShiftAmountTy(LHSTy); + if (OpTy == ShTy || OpTy.isVector()) return Op; + + ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + return getNode(Opcode, Op.getDebugLoc(), ShTy, Op); +} + +/// CreateStackTemporary - Create a stack temporary, suitable for holding the +/// specified value type. +SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) { + MachineFrameInfo *FrameInfo = getMachineFunction().getFrameInfo(); + unsigned ByteSize = VT.getStoreSize(); + const Type *Ty = VT.getTypeForEVT(*getContext()); + unsigned StackAlign = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), minAlign); + + int FrameIdx = FrameInfo->CreateStackObject(ByteSize, StackAlign, false); + return getFrameIndex(FrameIdx, TLI.getPointerTy()); +} + +/// CreateStackTemporary - Create a stack temporary suitable for holding +/// either of the specified value types. +SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) { + unsigned Bytes = std::max(VT1.getStoreSizeInBits(), + VT2.getStoreSizeInBits())/8; + const Type *Ty1 = VT1.getTypeForEVT(*getContext()); + const Type *Ty2 = VT2.getTypeForEVT(*getContext()); + const TargetData *TD = TLI.getTargetData(); + unsigned Align = std::max(TD->getPrefTypeAlignment(Ty1), + TD->getPrefTypeAlignment(Ty2)); + + MachineFrameInfo *FrameInfo = getMachineFunction().getFrameInfo(); + int FrameIdx = FrameInfo->CreateStackObject(Bytes, Align, false); + return getFrameIndex(FrameIdx, TLI.getPointerTy()); +} + +SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, + SDValue N2, ISD::CondCode Cond, DebugLoc dl) { + // These setcc operations always fold. + switch (Cond) { + default: break; + case ISD::SETFALSE: + case ISD::SETFALSE2: return getConstant(0, VT); + case ISD::SETTRUE: + case ISD::SETTRUE2: return getConstant(1, VT); + + case ISD::SETOEQ: + case ISD::SETOGT: + case ISD::SETOGE: + case ISD::SETOLT: + case ISD::SETOLE: + case ISD::SETONE: + case ISD::SETO: + case ISD::SETUO: + case ISD::SETUEQ: + case ISD::SETUNE: + assert(!N1.getValueType().isInteger() && "Illegal setcc for integer!"); + break; + } + + if (ConstantSDNode *N2C = dyn_cast(N2.getNode())) { + const APInt &C2 = N2C->getAPIntValue(); + if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) { + const APInt &C1 = N1C->getAPIntValue(); + + switch (Cond) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETEQ: return getConstant(C1 == C2, VT); + case ISD::SETNE: return getConstant(C1 != C2, VT); + case ISD::SETULT: return getConstant(C1.ult(C2), VT); + case ISD::SETUGT: return getConstant(C1.ugt(C2), VT); + case ISD::SETULE: return getConstant(C1.ule(C2), VT); + case ISD::SETUGE: return getConstant(C1.uge(C2), VT); + case ISD::SETLT: return getConstant(C1.slt(C2), VT); + case ISD::SETGT: return getConstant(C1.sgt(C2), VT); + case ISD::SETLE: return getConstant(C1.sle(C2), VT); + case ISD::SETGE: return getConstant(C1.sge(C2), VT); + } + } + } + if (ConstantFPSDNode *N1C = dyn_cast(N1.getNode())) { + if (ConstantFPSDNode *N2C = dyn_cast(N2.getNode())) { + // No compile time operations on this type yet. + if (N1C->getValueType(0) == MVT::ppcf128) + return SDValue(); + + APFloat::cmpResult R = N1C->getValueAPF().compare(N2C->getValueAPF()); + switch (Cond) { + default: break; + case ISD::SETEQ: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOEQ: return getConstant(R==APFloat::cmpEqual, VT); + case ISD::SETNE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETONE: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpLessThan, VT); + case ISD::SETLT: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOLT: return getConstant(R==APFloat::cmpLessThan, VT); + case ISD::SETGT: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOGT: return getConstant(R==APFloat::cmpGreaterThan, VT); + case ISD::SETLE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOLE: return getConstant(R==APFloat::cmpLessThan || + R==APFloat::cmpEqual, VT); + case ISD::SETGE: if (R==APFloat::cmpUnordered) + return getUNDEF(VT); + // fall through + case ISD::SETOGE: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpEqual, VT); + case ISD::SETO: return getConstant(R!=APFloat::cmpUnordered, VT); + case ISD::SETUO: return getConstant(R==APFloat::cmpUnordered, VT); + case ISD::SETUEQ: return getConstant(R==APFloat::cmpUnordered || + R==APFloat::cmpEqual, VT); + case ISD::SETUNE: return getConstant(R!=APFloat::cmpEqual, VT); + case ISD::SETULT: return getConstant(R==APFloat::cmpUnordered || + R==APFloat::cmpLessThan, VT); + case ISD::SETUGT: return getConstant(R==APFloat::cmpGreaterThan || + R==APFloat::cmpUnordered, VT); + case ISD::SETULE: return getConstant(R!=APFloat::cmpGreaterThan, VT); + case ISD::SETUGE: return getConstant(R!=APFloat::cmpLessThan, VT); + } + } else { + // Ensure that the constant occurs on the RHS. + return getSetCC(dl, VT, N2, N1, ISD::getSetCCSwappedOperands(Cond)); + } + } + + // Could not fold it. + return SDValue(); +} + +/// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We +/// use this predicate to simplify operations downstream. +bool SelectionDAG::SignBitIsZero(SDValue Op, unsigned Depth) const { + // This predicate is not safe for vector operations. + if (Op.getValueType().isVector()) + return false; + + unsigned BitWidth = Op.getValueType().getScalarType().getSizeInBits(); + return MaskedValueIsZero(Op, APInt::getSignBit(BitWidth), Depth); +} + +/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use +/// this predicate to simplify operations downstream. Mask is known to be zero +/// for bits that V cannot have. +bool SelectionDAG::MaskedValueIsZero(SDValue Op, const APInt &Mask, + unsigned Depth) const { + APInt KnownZero, KnownOne; + ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + return (KnownZero & Mask) == Mask; +} + +/// ComputeMaskedBits - Determine which of the bits specified in Mask are +/// known to be either zero or one and return them in the KnownZero/KnownOne +/// bitsets. This code only analyzes bits in Mask, in order to short-circuit +/// processing. +void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask, + APInt &KnownZero, APInt &KnownOne, + unsigned Depth) const { + unsigned BitWidth = Mask.getBitWidth(); + assert(BitWidth == Op.getValueType().getScalarType().getSizeInBits() && + "Mask size mismatches value type size!"); + + KnownZero = KnownOne = APInt(BitWidth, 0); // Don't know anything. + if (Depth == 6 || Mask == 0) + return; // Limit search depth. + + APInt KnownZero2, KnownOne2; + + switch (Op.getOpcode()) { + case ISD::Constant: + // We know all of the bits for a constant! + KnownOne = cast(Op)->getAPIntValue() & Mask; + KnownZero = ~KnownOne & Mask; + return; + case ISD::AND: + // If either the LHS or the RHS are Zero, the result is zero. + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask & ~KnownZero, + KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + return; + case ISD::OR: + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask & ~KnownOne, + KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + return; + case ISD::XOR: { + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + APInt KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOne = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + KnownZero = KnownZeroOut; + return; + } + case ISD::MUL: { + APInt Mask2 = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(1), Mask2, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If low bits are zero in either operand, output low known-0 bits. + // Also compute a conserative estimate for high known-0 bits. + // More trickiness is possible, but this is sufficient for the + // interesting case of alignment computation. + KnownOne.clearAllBits(); + unsigned TrailZ = KnownZero.countTrailingOnes() + + KnownZero2.countTrailingOnes(); + unsigned LeadZ = std::max(KnownZero.countLeadingOnes() + + KnownZero2.countLeadingOnes(), + BitWidth) - BitWidth; + + TrailZ = std::min(TrailZ, BitWidth); + LeadZ = std::min(LeadZ, BitWidth); + KnownZero = APInt::getLowBitsSet(BitWidth, TrailZ) | + APInt::getHighBitsSet(BitWidth, LeadZ); + KnownZero &= Mask; + return; + } + case ISD::UDIV: { + // For the purposes of computing leading zeros we can conservatively + // treat a udiv as a logical right shift by the power of 2 known to + // be less than the denominator. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(0), + AllOnes, KnownZero2, KnownOne2, Depth+1); + unsigned LeadZ = KnownZero2.countLeadingOnes(); + + KnownOne2.clearAllBits(); + KnownZero2.clearAllBits(); + ComputeMaskedBits(Op.getOperand(1), + AllOnes, KnownZero2, KnownOne2, Depth+1); + unsigned RHSUnknownLeadingOnes = KnownOne2.countLeadingZeros(); + if (RHSUnknownLeadingOnes != BitWidth) + LeadZ = std::min(BitWidth, + LeadZ + BitWidth - RHSUnknownLeadingOnes - 1); + + KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ) & Mask; + return; + } + case ISD::SELECT: + ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case ISD::SELECT_CC: + ComputeMaskedBits(Op.getOperand(3), Mask, KnownZero, KnownOne, Depth+1); + ComputeMaskedBits(Op.getOperand(2), Mask, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + return; + case ISD::SADDO: + case ISD::UADDO: + case ISD::SSUBO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + if (Op.getResNo() != 1) + return; + // The boolean result conforms to getBooleanContents. Fall through. + case ISD::SETCC: + // If we know the result of a setcc has the top bits zero, use this info. + if (TLI.getBooleanContents() == TargetLowering::ZeroOrOneBooleanContent && + BitWidth > 1) + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - 1); + return; + case ISD::SHL: + // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + ComputeMaskedBits(Op.getOperand(0), Mask.lshr(ShAmt), + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero <<= ShAmt; + KnownOne <<= ShAmt; + // low bits known zero. + KnownZero |= APInt::getLowBitsSet(BitWidth, ShAmt); + } + return; + case ISD::SRL: + // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + ComputeMaskedBits(Op.getOperand(0), (Mask << ShAmt), + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt) & Mask; + KnownZero |= HighBits; // High bits known zero. + } + return; + case ISD::SRA: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + return; + + APInt InDemandedMask = (Mask << ShAmt); + // If any of the demanded bits are produced by the sign extension, we also + // demand the input sign bit. + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt) & Mask; + if (HighBits.getBoolValue()) + InDemandedMask |= APInt::getSignBit(BitWidth); + + ComputeMaskedBits(Op.getOperand(0), InDemandedMask, KnownZero, KnownOne, + Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + // Handle the sign bits. + APInt SignBit = APInt::getSignBit(BitWidth); + SignBit = SignBit.lshr(ShAmt); // Adjust to where it is now in the mask. + + if (KnownZero.intersects(SignBit)) { + KnownZero |= HighBits; // New bits are known zero. + } else if (KnownOne.intersects(SignBit)) { + KnownOne |= HighBits; // New bits are known one. + } + } + return; + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(Op.getOperand(1))->getVT(); + unsigned EBits = EVT.getScalarType().getSizeInBits(); + + // Sign extension. Compute the demanded bits in the result that are not + // present in the input. + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - EBits) & Mask; + + APInt InSignBit = APInt::getSignBit(EBits); + APInt InputDemandedBits = Mask & APInt::getLowBitsSet(BitWidth, EBits); + + // If the sign extended bits are demanded, we know that the sign + // bit is demanded. + InSignBit = InSignBit.zext(BitWidth); + if (NewBits.getBoolValue()) + InputDemandedBits |= InSignBit; + + ComputeMaskedBits(Op.getOperand(0), InputDemandedBits, + KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + if (KnownZero.intersects(InSignBit)) { // Input sign bit known clear + KnownZero |= NewBits; + KnownOne &= ~NewBits; + } else if (KnownOne.intersects(InSignBit)) { // Input sign bit known set + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Input sign bit unknown + KnownZero &= ~NewBits; + KnownOne &= ~NewBits; + } + return; + } + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: { + unsigned LowBits = Log2_32(BitWidth)+1; + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); + KnownOne.clearAllBits(); + return; + } + case ISD::LOAD: { + if (ISD::isZEXTLoad(Op.getNode())) { + LoadSDNode *LD = cast(Op); + EVT VT = LD->getMemoryVT(); + unsigned MemBits = VT.getScalarType().getSizeInBits(); + KnownZero |= APInt::getHighBitsSet(BitWidth, BitWidth - MemBits) & Mask; + } + return; + } + case ISD::ZERO_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getScalarType().getSizeInBits(); + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; + APInt InMask = Mask.trunc(InBits); + KnownZero = KnownZero.trunc(InBits); + KnownOne = KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + KnownZero |= NewBits; + return; + } + case ISD::SIGN_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getScalarType().getSizeInBits(); + APInt InSignBit = APInt::getSignBit(InBits); + APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - InBits) & Mask; + APInt InMask = Mask.trunc(InBits); + + // If any of the sign extended bits are demanded, we know that the sign + // bit is demanded. Temporarily set this bit in the mask for our callee. + if (NewBits.getBoolValue()) + InMask |= InSignBit; + + KnownZero = KnownZero.trunc(InBits); + KnownOne = KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + + // Note if the sign bit is known to be zero or one. + bool SignBitKnownZero = KnownZero.isNegative(); + bool SignBitKnownOne = KnownOne.isNegative(); + assert(!(SignBitKnownZero && SignBitKnownOne) && + "Sign bit can't be known to be both zero and one!"); + + // If the sign bit wasn't actually demanded by our caller, we don't + // want it set in the KnownZero and KnownOne result values. Reset the + // mask and reapply it to the result values. + InMask = Mask.trunc(InBits); + KnownZero &= InMask; + KnownOne &= InMask; + + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + + // If the sign bit is known zero or one, the top bits match. + if (SignBitKnownZero) + KnownZero |= NewBits; + else if (SignBitKnownOne) + KnownOne |= NewBits; + return; + } + case ISD::ANY_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getScalarType().getSizeInBits(); + APInt InMask = Mask.trunc(InBits); + KnownZero = KnownZero.trunc(InBits); + KnownOne = KnownOne.trunc(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + return; + } + case ISD::TRUNCATE: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getScalarType().getSizeInBits(); + APInt InMask = Mask.zext(InBits); + KnownZero = KnownZero.zext(InBits); + KnownOne = KnownOne.zext(InBits); + ComputeMaskedBits(Op.getOperand(0), InMask, KnownZero, KnownOne, Depth+1); + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.trunc(BitWidth); + KnownOne = KnownOne.trunc(BitWidth); + break; + } + case ISD::AssertZext: { + EVT VT = cast(Op.getOperand(1))->getVT(); + APInt InMask = APInt::getLowBitsSet(BitWidth, VT.getSizeInBits()); + ComputeMaskedBits(Op.getOperand(0), Mask & InMask, KnownZero, + KnownOne, Depth+1); + KnownZero |= (~InMask) & Mask; + return; + } + case ISD::FGETSIGN: + // All bits are zero except the low bit. + KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - 1); + return; + + case ISD::SUB: { + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + if (CLHS->getAPIntValue().isNonNegative()) { + unsigned NLZ = (CLHS->getAPIntValue()+1).countLeadingZeros(); + // NLZ can't be BitWidth with no sign bit + APInt MaskV = APInt::getHighBitsSet(BitWidth, NLZ+1); + ComputeMaskedBits(Op.getOperand(1), MaskV, KnownZero2, KnownOne2, + Depth+1); + + // If all of the MaskV bits are known to be zero, then we know the + // output top bits are zero, because we now know that the output is + // from [0-C]. + if ((KnownZero2 & MaskV) == MaskV) { + unsigned NLZ2 = CLHS->getAPIntValue().countLeadingZeros(); + // Top bits known zero. + KnownZero = APInt::getHighBitsSet(BitWidth, NLZ2) & Mask; + } + } + } + } + // fall through + case ISD::ADD: + case ISD::ADDE: { + // Output known-0 bits are known if clear or set in both the low clear bits + // common to both LHS & RHS. For example, 8+(X<<3) is known to have the + // low 3 bits clear. + APInt Mask2 = APInt::getLowBitsSet(BitWidth, + BitWidth - Mask.countLeadingZeros()); + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + unsigned KnownZeroOut = KnownZero2.countTrailingOnes(); + + ComputeMaskedBits(Op.getOperand(1), Mask2, KnownZero2, KnownOne2, Depth+1); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + KnownZeroOut = std::min(KnownZeroOut, + KnownZero2.countTrailingOnes()); + + if (Op.getOpcode() == ISD::ADD) { + KnownZero |= APInt::getLowBitsSet(BitWidth, KnownZeroOut); + return; + } + + // With ADDE, a carry bit may be added in, so we can only use this + // information if we know (at least) that the low two bits are clear. We + // then return to the caller that the low bit is unknown but that other bits + // are known zero. + if (KnownZeroOut >= 2) // ADDE + KnownZero |= APInt::getBitsSet(BitWidth, 1, KnownZeroOut); + return; + } + case ISD::SREM: + if (ConstantSDNode *Rem = dyn_cast(Op.getOperand(1))) { + const APInt &RA = Rem->getAPIntValue().abs(); + if (RA.isPowerOf2()) { + APInt LowBits = RA - 1; + APInt Mask2 = LowBits | APInt::getSignBit(BitWidth); + ComputeMaskedBits(Op.getOperand(0), Mask2,KnownZero2,KnownOne2,Depth+1); + + // The low bits of the first operand are unchanged by the srem. + KnownZero = KnownZero2 & LowBits; + KnownOne = KnownOne2 & LowBits; + + // If the first operand is non-negative or has all low bits zero, then + // the upper bits are all zero. + if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits)) + KnownZero |= ~LowBits; + + // If the first operand is negative and not all low bits are zero, then + // the upper bits are all one. + if (KnownOne2[BitWidth-1] && ((KnownOne2 & LowBits) != 0)) + KnownOne |= ~LowBits; + + KnownZero &= Mask; + KnownOne &= Mask; + + assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); + } + } + return; + case ISD::UREM: { + if (ConstantSDNode *Rem = dyn_cast(Op.getOperand(1))) { + const APInt &RA = Rem->getAPIntValue(); + if (RA.isPowerOf2()) { + APInt LowBits = (RA - 1); + APInt Mask2 = LowBits & Mask; + KnownZero |= ~LowBits & Mask; + ComputeMaskedBits(Op.getOperand(0), Mask2, KnownZero, KnownOne,Depth+1); + assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?"); + break; + } + } + + // Since the result is less than or equal to either operand, any leading + // zero bits in either operand must also exist in the result. + APInt AllOnes = APInt::getAllOnesValue(BitWidth); + ComputeMaskedBits(Op.getOperand(0), AllOnes, KnownZero, KnownOne, + Depth+1); + ComputeMaskedBits(Op.getOperand(1), AllOnes, KnownZero2, KnownOne2, + Depth+1); + + uint32_t Leaders = std::max(KnownZero.countLeadingOnes(), + KnownZero2.countLeadingOnes()); + KnownOne.clearAllBits(); + KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & Mask; + return; + } + case ISD::FrameIndex: + case ISD::TargetFrameIndex: + if (unsigned Align = InferPtrAlignment(Op)) { + // The low bits are known zero if the pointer is aligned. + KnownZero = APInt::getLowBitsSet(BitWidth, Log2_32(Align)); + return; + } + break; + + default: + // Allow the target to implement this method for its nodes. + if (Op.getOpcode() >= ISD::BUILTIN_OP_END) { + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_W_CHAIN: + case ISD::INTRINSIC_VOID: + TLI.computeMaskedBitsForTargetNode(Op, Mask, KnownZero, KnownOne, *this, + Depth); + } + return; + } +} + +/// ComputeNumSignBits - Return the number of times the sign bit of the +/// register is replicated into the other bits. We know that at least 1 bit +/// is always equal to the sign bit (itself), but other cases can give us +/// information. For example, immediately after an "SRA X, 2", we know that +/// the top 3 bits are all equal to each other, so we return 3. +unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{ + EVT VT = Op.getValueType(); + assert(VT.isInteger() && "Invalid VT!"); + unsigned VTBits = VT.getScalarType().getSizeInBits(); + unsigned Tmp, Tmp2; + unsigned FirstAnswer = 1; + + if (Depth == 6) + return 1; // Limit search depth. + + switch (Op.getOpcode()) { + default: break; + case ISD::AssertSext: + Tmp = cast(Op.getOperand(1))->getVT().getSizeInBits(); + return VTBits-Tmp+1; + case ISD::AssertZext: + Tmp = cast(Op.getOperand(1))->getVT().getSizeInBits(); + return VTBits-Tmp; + + case ISD::Constant: { + const APInt &Val = cast(Op)->getAPIntValue(); + return Val.getNumSignBits(); + } + + case ISD::SIGN_EXTEND: + Tmp = VTBits-Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); + return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp; + + case ISD::SIGN_EXTEND_INREG: + // Max of the input and what this extends. + Tmp = + cast(Op.getOperand(1))->getVT().getScalarType().getSizeInBits(); + Tmp = VTBits-Tmp+1; + + Tmp2 = ComputeNumSignBits(Op.getOperand(0), Depth+1); + return std::max(Tmp, Tmp2); + + case ISD::SRA: + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + // SRA X, C -> adds C sign bits. + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + Tmp += C->getZExtValue(); + if (Tmp > VTBits) Tmp = VTBits; + } + return Tmp; + case ISD::SHL: + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + // shl destroys sign bits. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (C->getZExtValue() >= VTBits || // Bad shift. + C->getZExtValue() >= Tmp) break; // Shifted all sign bits out. + return Tmp - C->getZExtValue(); + } + break; + case ISD::AND: + case ISD::OR: + case ISD::XOR: // NOT is handled here. + // Logical binary ops preserve the number of sign bits at the worst. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp != 1) { + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + FirstAnswer = std::min(Tmp, Tmp2); + // We computed what we know about the sign bits as our first + // answer. Now proceed to the generic code that uses + // ComputeMaskedBits, and pick whichever answer is better. + } + break; + + case ISD::SELECT: + Tmp = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp == 1) return 1; // Early out. + Tmp2 = ComputeNumSignBits(Op.getOperand(2), Depth+1); + return std::min(Tmp, Tmp2); + + case ISD::SADDO: + case ISD::UADDO: + case ISD::SSUBO: + case ISD::USUBO: + case ISD::SMULO: + case ISD::UMULO: + if (Op.getResNo() != 1) + break; + // The boolean result conforms to getBooleanContents. Fall through. + case ISD::SETCC: + // If setcc returns 0/-1, all bits are sign bits. + if (TLI.getBooleanContents() == + TargetLowering::ZeroOrNegativeOneBooleanContent) + return VTBits; + break; + case ISD::ROTL: + case ISD::ROTR: + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + unsigned RotAmt = C->getZExtValue() & (VTBits-1); + + // Handle rotate right by N like a rotate left by 32-N. + if (Op.getOpcode() == ISD::ROTR) + RotAmt = (VTBits-RotAmt) & (VTBits-1); + + // If we aren't rotating out all of the known-in sign bits, return the + // number that are left. This handles rotl(sext(x), 1) for example. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp > RotAmt+1) return Tmp-RotAmt; + } + break; + case ISD::ADD: + // Add can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp == 1) return 1; // Early out. + + // Special case decrementing a value (ADD X, -1): + if (ConstantSDNode *CRHS = dyn_cast(Op.getOperand(1))) + if (CRHS->isAllOnesValue()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1); + + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(VTBits, 1)) == Mask) + return VTBits; + + // If we are subtracting one from a positive number, there is no carry + // out of the result. + if (KnownZero.isNegative()) + return Tmp; + } + + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp2 == 1) return 1; + return std::min(Tmp, Tmp2)-1; + break; + + case ISD::SUB: + Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1); + if (Tmp2 == 1) return 1; + + // Handle NEG. + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) + if (CLHS->isNullValue()) { + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne, Depth+1); + // If the input is known to be 0 or 1, the output is 0/-1, which is all + // sign bits set. + if ((KnownZero | APInt(VTBits, 1)) == Mask) + return VTBits; + + // If the input is known to be positive (the sign bit is known clear), + // the output of the NEG has the same number of sign bits as the input. + if (KnownZero.isNegative()) + return Tmp2; + + // Otherwise, we treat this like a SUB. + } + + // Sub can have at most one carry bit. Thus we know that the output + // is, at worst, one more bit than the inputs. + Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1); + if (Tmp == 1) return 1; // Early out. + return std::min(Tmp, Tmp2)-1; + break; + case ISD::TRUNCATE: + // FIXME: it's tricky to do anything useful for this, but it is an important + // case for targets like X86. + break; + } + + // Handle LOADX separately here. EXTLOAD case will fallthrough. + if (Op.getOpcode() == ISD::LOAD) { + LoadSDNode *LD = cast(Op); + unsigned ExtType = LD->getExtensionType(); + switch (ExtType) { + default: break; + case ISD::SEXTLOAD: // '17' bits known + Tmp = LD->getMemoryVT().getScalarType().getSizeInBits(); + return VTBits-Tmp+1; + case ISD::ZEXTLOAD: // '16' bits known + Tmp = LD->getMemoryVT().getScalarType().getSizeInBits(); + return VTBits-Tmp; + } + } + + // Allow the target to implement this method for its nodes. + if (Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) { + unsigned NumBits = TLI.ComputeNumSignBitsForTargetNode(Op, Depth); + if (NumBits > 1) FirstAnswer = std::max(FirstAnswer, NumBits); + } + + // Finally, if we can prove that the top bits of the result are 0's or 1's, + // use this information. + APInt KnownZero, KnownOne; + APInt Mask = APInt::getAllOnesValue(VTBits); + ComputeMaskedBits(Op, Mask, KnownZero, KnownOne, Depth); + + if (KnownZero.isNegative()) { // sign bit is 0 + Mask = KnownZero; + } else if (KnownOne.isNegative()) { // sign bit is 1; + Mask = KnownOne; + } else { + // Nothing known. + return FirstAnswer; + } + + // Okay, we know that the sign bit in Mask is set. Use CLZ to determine + // the number of identical bits in the top of the input value. + Mask = ~Mask; + Mask <<= Mask.getBitWidth()-VTBits; + // Return # leading zeros. We use 'min' here in case Val was zero before + // shifting. We don't want to return '64' as for an i32 "0". + return std::max(FirstAnswer, std::min(VTBits, Mask.countLeadingZeros())); +} + +/// isBaseWithConstantOffset - Return true if the specified operand is an +/// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an +/// ISD::OR with a ConstantSDNode that is guaranteed to have the same +/// semantics as an ADD. This handles the equivalence: +/// X|Cst == X+Cst iff X&Cst = 0. +bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const { + if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) || + !isa(Op.getOperand(1))) + return false; + + if (Op.getOpcode() == ISD::OR && + !MaskedValueIsZero(Op.getOperand(0), + cast(Op.getOperand(1))->getAPIntValue())) + return false; + + return true; +} + + +bool SelectionDAG::isKnownNeverNaN(SDValue Op) const { + // If we're told that NaNs won't happen, assume they won't. + if (NoNaNsFPMath) + return true; + + // If the value is a constant, we can obviously see if it is a NaN or not. + if (const ConstantFPSDNode *C = dyn_cast(Op)) + return !C->getValueAPF().isNaN(); + + // TODO: Recognize more cases here. + + return false; +} + +bool SelectionDAG::isKnownNeverZero(SDValue Op) const { + // If the value is a constant, we can obviously see if it is a zero or not. + if (const ConstantFPSDNode *C = dyn_cast(Op)) + return !C->isZero(); + + // TODO: Recognize more cases here. + + return false; +} + +bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const { + // Check the obvious case. + if (A == B) return true; + + // For for negative and positive zero. + if (const ConstantFPSDNode *CA = dyn_cast(A)) + if (const ConstantFPSDNode *CB = dyn_cast(B)) + if (CA->isZero() && CB->isZero()) return true; + + // Otherwise they may not be equal. + return false; +} + +bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { + GlobalAddressSDNode *GA = dyn_cast(Op); + if (!GA) return false; + if (GA->getOffset() != 0) return false; + const GlobalVariable *GV = dyn_cast(GA->getGlobal()); + if (!GV) return false; + return MF->getMMI().hasDebugInfo(); +} + + +/// getNode - Gets or creates the specified node. +/// +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) SDNode(Opcode, DL, getVTList(VT)); + CSEMap.InsertNode(N, IP); + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + EVT VT, SDValue Operand) { + // Constant fold unary operations with an integer constant operand. + if (ConstantSDNode *C = dyn_cast(Operand.getNode())) { + const APInt &Val = C->getAPIntValue(); + switch (Opcode) { + default: break; + case ISD::SIGN_EXTEND: + return getConstant(Val.sextOrTrunc(VT.getSizeInBits()), VT); + case ISD::ANY_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::TRUNCATE: + return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), VT); + case ISD::UINT_TO_FP: + case ISD::SINT_TO_FP: { + // No compile time operations on ppcf128. + if (VT == MVT::ppcf128) break; + APFloat apf(APInt::getNullValue(VT.getSizeInBits())); + (void)apf.convertFromAPInt(Val, + Opcode==ISD::SINT_TO_FP, + APFloat::rmNearestTiesToEven); + return getConstantFP(apf, VT); + } + case ISD::BITCAST: + if (VT == MVT::f32 && C->getValueType(0) == MVT::i32) + return getConstantFP(Val.bitsToFloat(), VT); + else if (VT == MVT::f64 && C->getValueType(0) == MVT::i64) + return getConstantFP(Val.bitsToDouble(), VT); + break; + case ISD::BSWAP: + return getConstant(Val.byteSwap(), VT); + case ISD::CTPOP: + return getConstant(Val.countPopulation(), VT); + case ISD::CTLZ: + return getConstant(Val.countLeadingZeros(), VT); + case ISD::CTTZ: + return getConstant(Val.countTrailingZeros(), VT); + } + } + + // Constant fold unary operations with a floating point constant operand. + if (ConstantFPSDNode *C = dyn_cast(Operand.getNode())) { + APFloat V = C->getValueAPF(); // make copy + if (VT != MVT::ppcf128 && Operand.getValueType() != MVT::ppcf128) { + switch (Opcode) { + case ISD::FNEG: + V.changeSign(); + return getConstantFP(V, VT); + case ISD::FABS: + V.clearSign(); + return getConstantFP(V, VT); + case ISD::FP_ROUND: + case ISD::FP_EXTEND: { + bool ignored; + // This can return overflow, underflow, or inexact; we don't care. + // FIXME need to be more flexible about rounding mode. + (void)V.convert(*EVTToAPFloatSemantics(VT), + APFloat::rmNearestTiesToEven, &ignored); + return getConstantFP(V, VT); + } + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: { + integerPart x[2]; + bool ignored; + assert(integerPartWidth >= 64); + // FIXME need to be more flexible about rounding mode. + APFloat::opStatus s = V.convertToInteger(x, VT.getSizeInBits(), + Opcode==ISD::FP_TO_SINT, + APFloat::rmTowardZero, &ignored); + if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual + break; + APInt api(VT.getSizeInBits(), 2, x); + return getConstant(api, VT); + } + case ISD::BITCAST: + if (VT == MVT::i32 && C->getValueType(0) == MVT::f32) + return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), VT); + else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64) + return getConstant(V.bitcastToAPInt().getZExtValue(), VT); + break; + } + } + } + + unsigned OpOpcode = Operand.getNode()->getOpcode(); + switch (Opcode) { + case ISD::TokenFactor: + case ISD::MERGE_VALUES: + case ISD::CONCAT_VECTORS: + return Operand; // Factor, merge or concat of one node? No need. + case ISD::FP_ROUND: llvm_unreachable("Invalid method to make FP_ROUND node"); + case ISD::FP_EXTEND: + assert(VT.isFloatingPoint() && + Operand.getValueType().isFloatingPoint() && "Invalid FP cast!"); + if (Operand.getValueType() == VT) return Operand; // noop conversion. + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + if (Operand.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + break; + case ISD::SIGN_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid SIGN_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid sext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + break; + case ISD::ZERO_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid ZERO_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid zext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + if (OpOpcode == ISD::ZERO_EXTEND) // (zext (zext x)) -> (zext x) + return getNode(ISD::ZERO_EXTEND, DL, VT, + Operand.getNode()->getOperand(0)); + break; + case ISD::ANY_EXTEND: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid ANY_EXTEND!"); + if (Operand.getValueType() == VT) return Operand; // noop extension + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid anyext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + + if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND || + OpOpcode == ISD::ANY_EXTEND) + // (ext (zext x)) -> (zext x) and (ext (sext x)) -> (sext x) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + + // (ext (trunx x)) -> x + if (OpOpcode == ISD::TRUNCATE) { + SDValue OpOp = Operand.getNode()->getOperand(0); + if (OpOp.getValueType() == VT) + return OpOp; + } + break; + case ISD::TRUNCATE: + assert(VT.isInteger() && Operand.getValueType().isInteger() && + "Invalid TRUNCATE!"); + if (Operand.getValueType() == VT) return Operand; // noop truncate + assert(Operand.getValueType().getScalarType().bitsGT(VT.getScalarType()) && + "Invalid truncate node, src < dst!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + if (OpOpcode == ISD::TRUNCATE) + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); + else if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND || + OpOpcode == ISD::ANY_EXTEND) { + // If the source is smaller than the dest, we still need an extend. + if (Operand.getNode()->getOperand(0).getValueType().getScalarType() + .bitsLT(VT.getScalarType())) + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); + else if (Operand.getNode()->getOperand(0).getValueType().bitsGT(VT)) + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); + else + return Operand.getNode()->getOperand(0); + } + break; + case ISD::BITCAST: + // Basic sanity checking. + assert(VT.getSizeInBits() == Operand.getValueType().getSizeInBits() + && "Cannot BITCAST between types of different sizes!"); + if (VT == Operand.getValueType()) return Operand; // noop conversion. + if (OpOpcode == ISD::BITCAST) // bitconv(bitconv(x)) -> bitconv(x) + return getNode(ISD::BITCAST, DL, VT, Operand.getOperand(0)); + if (OpOpcode == ISD::UNDEF) + return getUNDEF(VT); + break; + case ISD::SCALAR_TO_VECTOR: + assert(VT.isVector() && !Operand.getValueType().isVector() && + (VT.getVectorElementType() == Operand.getValueType() || + (VT.getVectorElementType().isInteger() && + Operand.getValueType().isInteger() && + VT.getVectorElementType().bitsLE(Operand.getValueType()))) && + "Illegal SCALAR_TO_VECTOR node!"); + if (OpOpcode == ISD::UNDEF) + return getUNDEF(VT); + // scalar_to_vector(extract_vector_elt V, 0) -> V, top bits are undefined. + if (OpOpcode == ISD::EXTRACT_VECTOR_ELT && + isa(Operand.getOperand(1)) && + Operand.getConstantOperandVal(1) == 0 && + Operand.getOperand(0).getValueType() == VT) + return Operand.getOperand(0); + break; + case ISD::FNEG: + // -(X-Y) -> (Y-X) is unsafe because when X==Y, -0.0 != +0.0 + if (UnsafeFPMath && OpOpcode == ISD::FSUB) + return getNode(ISD::FSUB, DL, VT, Operand.getNode()->getOperand(1), + Operand.getNode()->getOperand(0)); + if (OpOpcode == ISD::FNEG) // --X -> X + return Operand.getNode()->getOperand(0); + break; + case ISD::FABS: + if (OpOpcode == ISD::FNEG) // abs(-X) -> abs(X) + return getNode(ISD::FABS, DL, VT, Operand.getNode()->getOperand(0)); + break; + } + + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Glue) { // Don't CSE flag producing nodes + FoldingSetNodeID ID; + SDValue Ops[1] = { Operand }; + AddNodeIDNode(ID, Opcode, VTs, Ops, 1); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTs, Operand); + CSEMap.InsertNode(N, IP); + } else { + N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTs, Operand); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, + EVT VT, + ConstantSDNode *Cst1, + ConstantSDNode *Cst2) { + const APInt &C1 = Cst1->getAPIntValue(), &C2 = Cst2->getAPIntValue(); + + switch (Opcode) { + case ISD::ADD: return getConstant(C1 + C2, VT); + case ISD::SUB: return getConstant(C1 - C2, VT); + case ISD::MUL: return getConstant(C1 * C2, VT); + case ISD::UDIV: + if (C2.getBoolValue()) return getConstant(C1.udiv(C2), VT); + break; + case ISD::UREM: + if (C2.getBoolValue()) return getConstant(C1.urem(C2), VT); + break; + case ISD::SDIV: + if (C2.getBoolValue()) return getConstant(C1.sdiv(C2), VT); + break; + case ISD::SREM: + if (C2.getBoolValue()) return getConstant(C1.srem(C2), VT); + break; + case ISD::AND: return getConstant(C1 & C2, VT); + case ISD::OR: return getConstant(C1 | C2, VT); + case ISD::XOR: return getConstant(C1 ^ C2, VT); + case ISD::SHL: return getConstant(C1 << C2, VT); + case ISD::SRL: return getConstant(C1.lshr(C2), VT); + case ISD::SRA: return getConstant(C1.ashr(C2), VT); + case ISD::ROTL: return getConstant(C1.rotl(C2), VT); + case ISD::ROTR: return getConstant(C1.rotr(C2), VT); + default: break; + } + + return SDValue(); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2) { + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + ConstantSDNode *N2C = dyn_cast(N2.getNode()); + switch (Opcode) { + default: break; + case ISD::TokenFactor: + assert(VT == MVT::Other && N1.getValueType() == MVT::Other && + N2.getValueType() == MVT::Other && "Invalid token factor!"); + // Fold trivial token factors. + if (N1.getOpcode() == ISD::EntryToken) return N2; + if (N2.getOpcode() == ISD::EntryToken) return N1; + if (N1 == N2) return N1; + break; + case ISD::CONCAT_VECTORS: + // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to + // one big BUILD_VECTOR. + if (N1.getOpcode() == ISD::BUILD_VECTOR && + N2.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Elts(N1.getNode()->op_begin(), + N1.getNode()->op_end()); + Elts.append(N2.getNode()->op_begin(), N2.getNode()->op_end()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); + } + break; + case ISD::AND: + assert(VT.isInteger() && "This operator does not apply to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + // (X & 0) -> 0. This commonly occurs when legalizing i64 values, so it's + // worth handling here. + if (N2C && N2C->isNullValue()) + return N2; + if (N2C && N2C->isAllOnesValue()) // X & -1 -> X + return N1; + break; + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + assert(VT.isInteger() && "This operator does not apply to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + // (X ^|+- 0) -> X. This commonly occurs when legalizing i64 values, so + // it's worth handling here. + if (N2C && N2C->isNullValue()) + return N1; + break; + case ISD::UDIV: + case ISD::UREM: + case ISD::MULHU: + case ISD::MULHS: + case ISD::MUL: + case ISD::SDIV: + case ISD::SREM: + assert(VT.isInteger() && "This operator does not apply to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + break; + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + if (UnsafeFPMath) { + if (Opcode == ISD::FADD) { + // 0+x --> x + if (ConstantFPSDNode *CFP = dyn_cast(N1)) + if (CFP->getValueAPF().isZero()) + return N2; + // x+0 --> x + if (ConstantFPSDNode *CFP = dyn_cast(N2)) + if (CFP->getValueAPF().isZero()) + return N1; + } else if (Opcode == ISD::FSUB) { + // x-0 --> x + if (ConstantFPSDNode *CFP = dyn_cast(N2)) + if (CFP->getValueAPF().isZero()) + return N1; + } + } + assert(VT.isFloatingPoint() && "This operator only applies to FP types!"); + assert(N1.getValueType() == N2.getValueType() && + N1.getValueType() == VT && "Binary operator types must match!"); + break; + case ISD::FCOPYSIGN: // N1 and result must match. N1/N2 need not match. + assert(N1.getValueType() == VT && + N1.getValueType().isFloatingPoint() && + N2.getValueType().isFloatingPoint() && + "Invalid FCOPYSIGN!"); + break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + assert(VT == N1.getValueType() && + "Shift operators return type must be the same as their first arg"); + assert(VT.isInteger() && N2.getValueType().isInteger() && + "Shifts only work on integers"); + // Verify that the shift amount VT is bit enough to hold valid shift + // amounts. This catches things like trying to shift an i1024 value by an + // i8, which is easy to fall into in generic code that uses + // TLI.getShiftAmount(). + assert(N2.getValueType().getSizeInBits() >= + Log2_32_Ceil(N1.getValueType().getSizeInBits()) && + "Invalid use of small shift amount with oversized value!"); + + // Always fold shifts of i1 values so the code generator doesn't need to + // handle them. Since we know the size of the shift has to be less than the + // size of the value, the shift/rotate count is guaranteed to be zero. + if (VT == MVT::i1) + return N1; + if (N2C && N2C->isNullValue()) + return N1; + break; + case ISD::FP_ROUND_INREG: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg round!"); + assert(VT.isFloatingPoint() && EVT.isFloatingPoint() && + "Cannot FP_ROUND_INREG integer types"); + assert(EVT.isVector() == VT.isVector() && + "FP_ROUND_INREG type should be vector iff the operand " + "type is vector!"); + assert((!EVT.isVector() || + EVT.getVectorNumElements() == VT.getVectorNumElements()) && + "Vector element counts must match in FP_ROUND_INREG"); + assert(EVT.bitsLE(VT) && "Not rounding down!"); + if (cast(N2)->getVT() == VT) return N1; // Not actually rounding. + break; + } + case ISD::FP_ROUND: + assert(VT.isFloatingPoint() && + N1.getValueType().isFloatingPoint() && + VT.bitsLE(N1.getValueType()) && + isa(N2) && "Invalid FP_ROUND!"); + if (N1.getValueType() == VT) return N1; // noop conversion. + break; + case ISD::AssertSext: + case ISD::AssertZext: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg extend!"); + assert(VT.isInteger() && EVT.isInteger() && + "Cannot *_EXTEND_INREG FP types"); + assert(!EVT.isVector() && + "AssertSExt/AssertZExt type should be the vector element type " + "rather than the vector type!"); + assert(EVT.bitsLE(VT) && "Not extending!"); + if (VT == EVT) return N1; // noop assertion. + break; + } + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(N2)->getVT(); + assert(VT == N1.getValueType() && "Not an inreg extend!"); + assert(VT.isInteger() && EVT.isInteger() && + "Cannot *_EXTEND_INREG FP types"); + assert(EVT.isVector() == VT.isVector() && + "SIGN_EXTEND_INREG type should be vector iff the operand " + "type is vector!"); + assert((!EVT.isVector() || + EVT.getVectorNumElements() == VT.getVectorNumElements()) && + "Vector element counts must match in SIGN_EXTEND_INREG"); + assert(EVT.bitsLE(VT) && "Not extending!"); + if (EVT == VT) return N1; // Not actually extending + + if (N1C) { + APInt Val = N1C->getAPIntValue(); + unsigned FromBits = EVT.getScalarType().getSizeInBits(); + Val <<= Val.getBitWidth()-FromBits; + Val = Val.ashr(Val.getBitWidth()-FromBits); + return getConstant(Val, VT); + } + break; + } + case ISD::EXTRACT_VECTOR_ELT: + // EXTRACT_VECTOR_ELT of an UNDEF is an UNDEF. + if (N1.getOpcode() == ISD::UNDEF) + return getUNDEF(VT); + + // EXTRACT_VECTOR_ELT of CONCAT_VECTORS is often formed while lowering is + // expanding copies of large vectors from registers. + if (N2C && + N1.getOpcode() == ISD::CONCAT_VECTORS && + N1.getNumOperands() > 0) { + unsigned Factor = + N1.getOperand(0).getValueType().getVectorNumElements(); + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, + N1.getOperand(N2C->getZExtValue() / Factor), + getConstant(N2C->getZExtValue() % Factor, + N2.getValueType())); + } + + // EXTRACT_VECTOR_ELT of BUILD_VECTOR is often formed while lowering is + // expanding large vector constants. + if (N2C && N1.getOpcode() == ISD::BUILD_VECTOR) { + SDValue Elt = N1.getOperand(N2C->getZExtValue()); + EVT VEltTy = N1.getValueType().getVectorElementType(); + if (Elt.getValueType() != VEltTy) { + // If the vector element type is not legal, the BUILD_VECTOR operands + // are promoted and implicitly truncated. Make that explicit here. + Elt = getNode(ISD::TRUNCATE, DL, VEltTy, Elt); + } + if (VT != VEltTy) { + // If the vector element type is not legal, the EXTRACT_VECTOR_ELT + // result is implicitly extended. + Elt = getNode(ISD::ANY_EXTEND, DL, VT, Elt); + } + return Elt; + } + + // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector + // operations are lowered to scalars. + if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) { + // If the indices are the same, return the inserted element else + // if the indices are known different, extract the element from + // the original vector. + SDValue N1Op2 = N1.getOperand(2); + ConstantSDNode *N1Op2C = dyn_cast(N1Op2.getNode()); + + if (N1Op2C && N2C) { + if (N1Op2C->getZExtValue() == N2C->getZExtValue()) { + if (VT == N1.getOperand(1).getValueType()) + return N1.getOperand(1); + else + return getSExtOrTrunc(N1.getOperand(1), DL, VT); + } + + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0), N2); + } + } + break; + case ISD::EXTRACT_ELEMENT: + assert(N2C && (unsigned)N2C->getZExtValue() < 2 && "Bad EXTRACT_ELEMENT!"); + assert(!N1.getValueType().isVector() && !VT.isVector() && + (N1.getValueType().isInteger() == VT.isInteger()) && + "Wrong types for EXTRACT_ELEMENT!"); + + // EXTRACT_ELEMENT of BUILD_PAIR is often formed while legalize is expanding + // 64-bit integers into 32-bit parts. Instead of building the extract of + // the BUILD_PAIR, only to have legalize rip it apart, just do it now. + if (N1.getOpcode() == ISD::BUILD_PAIR) + return N1.getOperand(N2C->getZExtValue()); + + // EXTRACT_ELEMENT of a constant int is also very common. + if (ConstantSDNode *C = dyn_cast(N1)) { + unsigned ElementSize = VT.getSizeInBits(); + unsigned Shift = ElementSize * N2C->getZExtValue(); + APInt ShiftedVal = C->getAPIntValue().lshr(Shift); + return getConstant(ShiftedVal.trunc(ElementSize), VT); + } + break; + case ISD::EXTRACT_SUBVECTOR: { + SDValue Index = N2; + if (VT.isSimple() && N1.getValueType().isSimple()) { + assert(VT.isVector() && N1.getValueType().isVector() && + "Extract subvector VTs must be a vectors!"); + assert(VT.getVectorElementType() == N1.getValueType().getVectorElementType() && + "Extract subvector VTs must have the same element type!"); + assert(VT.getSimpleVT() <= N1.getValueType().getSimpleVT() && + "Extract subvector must be from larger vector to smaller vector!"); + + if (isa(Index.getNode())) { + assert((VT.getVectorNumElements() + + cast(Index.getNode())->getZExtValue() + <= N1.getValueType().getVectorNumElements()) + && "Extract subvector overflow!"); + } + + // Trivial extraction. + if (VT.getSimpleVT() == N1.getValueType().getSimpleVT()) + return N1; + } + break; + } + } + + if (N1C) { + if (N2C) { + SDValue SV = FoldConstantArithmetic(Opcode, VT, N1C, N2C); + if (SV.getNode()) return SV; + } else { // Cannonicalize constant to RHS if commutative + if (isCommutativeBinOp(Opcode)) { + std::swap(N1C, N2C); + std::swap(N1, N2); + } + } + } + + // Constant fold FP operations. + ConstantFPSDNode *N1CFP = dyn_cast(N1.getNode()); + ConstantFPSDNode *N2CFP = dyn_cast(N2.getNode()); + if (N1CFP) { + if (!N2CFP && isCommutativeBinOp(Opcode)) { + // Cannonicalize constant to RHS if commutative + std::swap(N1CFP, N2CFP); + std::swap(N1, N2); + } else if (N2CFP && VT != MVT::ppcf128) { + APFloat V1 = N1CFP->getValueAPF(), V2 = N2CFP->getValueAPF(); + APFloat::opStatus s; + switch (Opcode) { + case ISD::FADD: + s = V1.add(V2, APFloat::rmNearestTiesToEven); + if (s != APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FSUB: + s = V1.subtract(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FMUL: + s = V1.multiply(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp) + return getConstantFP(V1, VT); + break; + case ISD::FDIV: + s = V1.divide(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); + break; + case ISD::FREM : + s = V1.mod(V2, APFloat::rmNearestTiesToEven); + if (s!=APFloat::opInvalidOp && s!=APFloat::opDivByZero) + return getConstantFP(V1, VT); + break; + case ISD::FCOPYSIGN: + V1.copySign(V2); + return getConstantFP(V1, VT); + default: break; + } + } + } + + // Canonicalize an UNDEF to the RHS, even over a constant. + if (N1.getOpcode() == ISD::UNDEF) { + if (isCommutativeBinOp(Opcode)) { + std::swap(N1, N2); + } else { + switch (Opcode) { + case ISD::FP_ROUND_INREG: + case ISD::SIGN_EXTEND_INREG: + case ISD::SUB: + case ISD::FSUB: + case ISD::FDIV: + case ISD::FREM: + case ISD::SRA: + return N1; // fold op(undef, arg2) -> undef + case ISD::UDIV: + case ISD::SDIV: + case ISD::UREM: + case ISD::SREM: + case ISD::SRL: + case ISD::SHL: + if (!VT.isVector()) + return getConstant(0, VT); // fold op(undef, arg2) -> 0 + // For vectors, we can't easily build an all zero vector, just return + // the LHS. + return N2; + } + } + } + + // Fold a bunch of operators when the RHS is undef. + if (N2.getOpcode() == ISD::UNDEF) { + switch (Opcode) { + case ISD::XOR: + if (N1.getOpcode() == ISD::UNDEF) + // Handle undef ^ undef -> 0 special case. This is a common + // idiom (misuse). + return getConstant(0, VT); + // fallthrough + case ISD::ADD: + case ISD::ADDC: + case ISD::ADDE: + case ISD::SUB: + case ISD::UDIV: + case ISD::SDIV: + case ISD::UREM: + case ISD::SREM: + return N2; // fold op(arg1, undef) -> undef + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::FDIV: + case ISD::FREM: + if (UnsafeFPMath) + return N2; + break; + case ISD::MUL: + case ISD::AND: + case ISD::SRL: + case ISD::SHL: + if (!VT.isVector()) + return getConstant(0, VT); // fold op(arg1, undef) -> 0 + // For vectors, we can't easily build an all zero vector, just return + // the LHS. + return N1; + case ISD::OR: + if (!VT.isVector()) + return getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); + // For vectors, we can't easily build an all one vector, just return + // the LHS. + return N1; + case ISD::SRA: + return N1; + } + } + + // Memoize this node if possible. + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Glue) { + SDValue Ops[] = { N1, N2 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, 2); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTs, N1, N2); + CSEMap.InsertNode(N, IP); + } else { + N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTs, N1, N2); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3) { + // Perform various simplifications. + ConstantSDNode *N1C = dyn_cast(N1.getNode()); + switch (Opcode) { + case ISD::CONCAT_VECTORS: + // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to + // one big BUILD_VECTOR. + if (N1.getOpcode() == ISD::BUILD_VECTOR && + N2.getOpcode() == ISD::BUILD_VECTOR && + N3.getOpcode() == ISD::BUILD_VECTOR) { + SmallVector Elts(N1.getNode()->op_begin(), + N1.getNode()->op_end()); + Elts.append(N2.getNode()->op_begin(), N2.getNode()->op_end()); + Elts.append(N3.getNode()->op_begin(), N3.getNode()->op_end()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); + } + break; + case ISD::SETCC: { + // Use FoldSetCC to simplify SETCC's. + SDValue Simp = FoldSetCC(VT, N1, N2, cast(N3)->get(), DL); + if (Simp.getNode()) return Simp; + break; + } + case ISD::SELECT: + if (N1C) { + if (N1C->getZExtValue()) + return N2; // select true, X, Y -> X + else + return N3; // select false, X, Y -> Y + } + + if (N2 == N3) return N2; // select C, X, X -> X + break; + case ISD::VECTOR_SHUFFLE: + llvm_unreachable("should use getVectorShuffle constructor!"); + break; + case ISD::INSERT_SUBVECTOR: { + SDValue Index = N3; + if (VT.isSimple() && N1.getValueType().isSimple() + && N2.getValueType().isSimple()) { + assert(VT.isVector() && N1.getValueType().isVector() && + N2.getValueType().isVector() && + "Insert subvector VTs must be a vectors"); + assert(VT == N1.getValueType() && + "Dest and insert subvector source types must match!"); + assert(N2.getValueType().getSimpleVT() <= N1.getValueType().getSimpleVT() && + "Insert subvector must be from smaller vector to larger vector!"); + if (isa(Index.getNode())) { + assert((N2.getValueType().getVectorNumElements() + + cast(Index.getNode())->getZExtValue() + <= VT.getVectorNumElements()) + && "Insert subvector overflow!"); + } + + // Trivial insertion. + if (VT.getSimpleVT() == N2.getValueType().getSimpleVT()) + return N2; + } + break; + } + case ISD::BITCAST: + // Fold bit_convert nodes from a type to themselves. + if (N1.getValueType() == VT) + return N1; + break; + } + + // Memoize node if it doesn't produce a flag. + SDNode *N; + SDVTList VTs = getVTList(VT); + if (VT != MVT::Glue) { + SDValue Ops[] = { N1, N2, N3 }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); + CSEMap.InsertNode(N, IP); + } else { + N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { + SDValue Ops[] = { N1, N2, N3, N4 }; + return getNode(Opcode, DL, VT, Ops, 4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { + SDValue Ops[] = { N1, N2, N3, N4, N5 }; + return getNode(Opcode, DL, VT, Ops, 5); +} + +/// getStackArgumentTokenFactor - Compute a TokenFactor to force all +/// the incoming stack arguments to be loaded from the stack. +SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) { + SmallVector ArgChains; + + // Include the original chain at the beginning of the list. When this is + // used by target LowerCall hooks, this helps legalize find the + // CALLSEQ_BEGIN node. + ArgChains.push_back(Chain); + + // Add a chain value for each stack argument. + for (SDNode::use_iterator U = getEntryNode().getNode()->use_begin(), + UE = getEntryNode().getNode()->use_end(); U != UE; ++U) + if (LoadSDNode *L = dyn_cast(*U)) + if (FrameIndexSDNode *FI = dyn_cast(L->getBasePtr())) + if (FI->getIndex() < 0) + ArgChains.push_back(SDValue(L, 1)); + + // Build a tokenfactor for all the chains. + return getNode(ISD::TokenFactor, Chain.getDebugLoc(), MVT::Other, + &ArgChains[0], ArgChains.size()); +} + +/// SplatByte - Distribute ByteVal over NumBits bits. +static APInt SplatByte(unsigned NumBits, uint8_t ByteVal) { + APInt Val = APInt(NumBits, ByteVal); + unsigned Shift = 8; + for (unsigned i = NumBits; i > 8; i >>= 1) { + Val = (Val << Shift) | Val; + Shift <<= 1; + } + return Val; +} + +/// getMemsetValue - Vectorized representation of the memset value +/// operand. +static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG, + DebugLoc dl) { + assert(Value.getOpcode() != ISD::UNDEF); + + unsigned NumBits = VT.getScalarType().getSizeInBits(); + if (ConstantSDNode *C = dyn_cast(Value)) { + APInt Val = SplatByte(NumBits, C->getZExtValue() & 255); + if (VT.isInteger()) + return DAG.getConstant(Val, VT); + return DAG.getConstantFP(APFloat(Val), VT); + } + + Value = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Value); + if (NumBits > 8) { + // Use a multiplication with 0x010101... to extend the input to the + // required length. + APInt Magic = SplatByte(NumBits, 0x01); + Value = DAG.getNode(ISD::MUL, dl, VT, Value, DAG.getConstant(Magic, VT)); + } + + return Value; +} + +/// getMemsetStringVal - Similar to getMemsetValue. Except this is only +/// used when a memcpy is turned into a memset when the source is a constant +/// string ptr. +static SDValue getMemsetStringVal(EVT VT, DebugLoc dl, SelectionDAG &DAG, + const TargetLowering &TLI, + std::string &Str, unsigned Offset) { + // Handle vector with all elements zero. + if (Str.empty()) { + if (VT.isInteger()) + return DAG.getConstant(0, VT); + else if (VT == MVT::f32 || VT == MVT::f64) + return DAG.getConstantFP(0.0, VT); + else if (VT.isVector()) { + unsigned NumElts = VT.getVectorNumElements(); + MVT EltVT = (VT.getVectorElementType() == MVT::f32) ? MVT::i32 : MVT::i64; + return DAG.getNode(ISD::BITCAST, dl, VT, + DAG.getConstant(0, EVT::getVectorVT(*DAG.getContext(), + EltVT, NumElts))); + } else + llvm_unreachable("Expected type!"); + } + + assert(!VT.isVector() && "Can't handle vector type here!"); + unsigned NumBits = VT.getSizeInBits(); + unsigned MSB = NumBits / 8; + uint64_t Val = 0; + if (TLI.isLittleEndian()) + Offset = Offset + MSB - 1; + for (unsigned i = 0; i != MSB; ++i) { + Val = (Val << 8) | (unsigned char)Str[Offset]; + Offset += TLI.isLittleEndian() ? -1 : 1; + } + return DAG.getConstant(Val, VT); +} + +/// getMemBasePlusOffset - Returns base and offset node for the +/// +static SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, + SelectionDAG &DAG) { + EVT VT = Base.getValueType(); + return DAG.getNode(ISD::ADD, Base.getDebugLoc(), + VT, Base, DAG.getConstant(Offset, VT)); +} + +/// isMemSrcFromString - Returns true if memcpy source is a string constant. +/// +static bool isMemSrcFromString(SDValue Src, std::string &Str) { + unsigned SrcDelta = 0; + GlobalAddressSDNode *G = NULL; + if (Src.getOpcode() == ISD::GlobalAddress) + G = cast(Src); + else if (Src.getOpcode() == ISD::ADD && + Src.getOperand(0).getOpcode() == ISD::GlobalAddress && + Src.getOperand(1).getOpcode() == ISD::Constant) { + G = cast(Src.getOperand(0)); + SrcDelta = cast(Src.getOperand(1))->getZExtValue(); + } + if (!G) + return false; + + const GlobalVariable *GV = dyn_cast(G->getGlobal()); + if (GV && GetConstantStringInfo(GV, Str, SrcDelta, false)) + return true; + + return false; +} + +/// FindOptimalMemOpLowering - Determines the optimial series memory ops +/// to replace the memset / memcpy. Return true if the number of memory ops +/// is below the threshold. It returns the types of the sequence of +/// memory ops to perform memset / memcpy by reference. +static bool FindOptimalMemOpLowering(std::vector &MemOps, + unsigned Limit, uint64_t Size, + unsigned DstAlign, unsigned SrcAlign, + bool NonScalarIntSafe, + bool MemcpyStrSrc, + SelectionDAG &DAG, + const TargetLowering &TLI) { + assert((SrcAlign == 0 || SrcAlign >= DstAlign) && + "Expecting memcpy / memset source to meet alignment requirement!"); + // If 'SrcAlign' is zero, that means the memory operation does not need load + // the value, i.e. memset or memcpy from constant string. Otherwise, it's + // the inferred alignment of the source. 'DstAlign', on the other hand, is the + // specified alignment of the memory operation. If it is zero, that means + // it's possible to change the alignment of the destination. 'MemcpyStrSrc' + // indicates whether the memcpy source is constant so it does not need to be + // loaded. + EVT VT = TLI.getOptimalMemOpType(Size, DstAlign, SrcAlign, + NonScalarIntSafe, MemcpyStrSrc, + DAG.getMachineFunction()); + + if (VT == MVT::Other) { + if (DstAlign >= TLI.getTargetData()->getPointerPrefAlignment() || + TLI.allowsUnalignedMemoryAccesses(VT)) { + VT = TLI.getPointerTy(); + } else { + switch (DstAlign & 7) { + case 0: VT = MVT::i64; break; + case 4: VT = MVT::i32; break; + case 2: VT = MVT::i16; break; + default: VT = MVT::i8; break; + } + } + + MVT LVT = MVT::i64; + while (!TLI.isTypeLegal(LVT)) + LVT = (MVT::SimpleValueType)(LVT.SimpleTy - 1); + assert(LVT.isInteger()); + + if (VT.bitsGT(LVT)) + VT = LVT; + } + + unsigned NumMemOps = 0; + while (Size != 0) { + unsigned VTSize = VT.getSizeInBits() / 8; + while (VTSize > Size) { + // For now, only use non-vector load / store's for the left-over pieces. + if (VT.isVector() || VT.isFloatingPoint()) { + VT = MVT::i64; + while (!TLI.isTypeLegal(VT)) + VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1); + VTSize = VT.getSizeInBits() / 8; + } else { + // This can result in a type that is not legal on the target, e.g. + // 1 or 2 bytes on PPC. + VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1); + VTSize >>= 1; + } + } + + if (++NumMemOps > Limit) + return false; + MemOps.push_back(VT); + Size -= VTSize; + } + + return true; +} + +static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, bool isVol, + bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) { + // Turn a memcpy of undef to nop. + if (Src.getOpcode() == ISD::UNDEF) + return Chain; + + // Expand memcpy to a series of load and store ops if the size operand falls + // below a certain threshold. + // TODO: In the AlwaysInline case, if the size is big then generate a loop + // rather than maybe a humongous number of loads and stores. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + std::vector MemOps; + bool DstAlignCanChange = false; + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + bool OptSize = MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize); + FrameIndexSDNode *FI = dyn_cast(Dst); + if (FI && !MFI->isFixedObjectIndex(FI->getIndex())) + DstAlignCanChange = true; + unsigned SrcAlign = DAG.InferPtrAlignment(Src); + if (Align > SrcAlign) + SrcAlign = Align; + std::string Str; + bool CopyFromStr = isMemSrcFromString(Src, Str); + bool isZeroStr = CopyFromStr && Str.empty(); + unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemcpy(OptSize); + + if (!FindOptimalMemOpLowering(MemOps, Limit, Size, + (DstAlignCanChange ? 0 : Align), + (isZeroStr ? 0 : SrcAlign), + true, CopyFromStr, DAG, TLI)) + return SDValue(); + + if (DstAlignCanChange) { + const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); + if (NewAlign > Align) { + // Give the stack frame object a larger alignment if needed. + if (MFI->getObjectAlignment(FI->getIndex()) < NewAlign) + MFI->setObjectAlignment(FI->getIndex(), NewAlign); + Align = NewAlign; + } + } + + SmallVector OutChains; + unsigned NumMemOps = MemOps.size(); + uint64_t SrcOff = 0, DstOff = 0; + for (unsigned i = 0; i != NumMemOps; ++i) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + if (CopyFromStr && + (isZeroStr || (VT.isInteger() && !VT.isVector()))) { + // It's unlikely a store of a vector immediate can be done in a single + // instruction. It would require a load from a constantpool first. + // We only handle zero vectors here. + // FIXME: Handle other cases where store of vector immediate is done in + // a single instruction. + Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); + Store = DAG.getStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstPtrInfo.getWithOffset(DstOff), isVol, + false, Align); + } else { + // The type might not be legal for the target. This should only happen + // if the type is smaller than a legal type, as on PPC, so the right + // thing to do is generate a LoadExt/StoreTrunc pair. These simplify + // to Load/Store if NVT==VT. + // FIXME does the case above also need this? + EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT); + assert(NVT.bitsGE(VT)); + Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, + getMemBasePlusOffset(Src, SrcOff, DAG), + SrcPtrInfo.getWithOffset(SrcOff), VT, isVol, false, + MinAlign(SrcAlign, SrcOff)); + Store = DAG.getTruncStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstPtrInfo.getWithOffset(DstOff), VT, isVol, + false, Align); + } + OutChains.push_back(Store); + SrcOff += VTSize; + DstOff += VTSize; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, bool isVol, + bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) { + // Turn a memmove of undef to nop. + if (Src.getOpcode() == ISD::UNDEF) + return Chain; + + // Expand memmove to a series of load and store ops if the size operand falls + // below a certain threshold. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + std::vector MemOps; + bool DstAlignCanChange = false; + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + bool OptSize = MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize); + FrameIndexSDNode *FI = dyn_cast(Dst); + if (FI && !MFI->isFixedObjectIndex(FI->getIndex())) + DstAlignCanChange = true; + unsigned SrcAlign = DAG.InferPtrAlignment(Src); + if (Align > SrcAlign) + SrcAlign = Align; + unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemmove(OptSize); + + if (!FindOptimalMemOpLowering(MemOps, Limit, Size, + (DstAlignCanChange ? 0 : Align), + SrcAlign, true, false, DAG, TLI)) + return SDValue(); + + if (DstAlignCanChange) { + const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); + if (NewAlign > Align) { + // Give the stack frame object a larger alignment if needed. + if (MFI->getObjectAlignment(FI->getIndex()) < NewAlign) + MFI->setObjectAlignment(FI->getIndex(), NewAlign); + Align = NewAlign; + } + } + + uint64_t SrcOff = 0, DstOff = 0; + SmallVector LoadValues; + SmallVector LoadChains; + SmallVector OutChains; + unsigned NumMemOps = MemOps.size(); + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + Value = DAG.getLoad(VT, dl, Chain, + getMemBasePlusOffset(Src, SrcOff, DAG), + SrcPtrInfo.getWithOffset(SrcOff), isVol, + false, SrcAlign); + LoadValues.push_back(Value); + LoadChains.push_back(Value.getValue(1)); + SrcOff += VTSize; + } + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &LoadChains[0], LoadChains.size()); + OutChains.clear(); + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + unsigned VTSize = VT.getSizeInBits() / 8; + SDValue Value, Store; + + Store = DAG.getStore(Chain, dl, LoadValues[i], + getMemBasePlusOffset(Dst, DstOff, DAG), + DstPtrInfo.getWithOffset(DstOff), isVol, false, Align); + OutChains.push_back(Store); + DstOff += VTSize; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, SDValue Dst, + SDValue Src, uint64_t Size, + unsigned Align, bool isVol, + MachinePointerInfo DstPtrInfo) { + // Turn a memset of undef to nop. + if (Src.getOpcode() == ISD::UNDEF) + return Chain; + + // Expand memset to a series of load/store ops if the size operand + // falls below a certain threshold. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + std::vector MemOps; + bool DstAlignCanChange = false; + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + bool OptSize = MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize); + FrameIndexSDNode *FI = dyn_cast(Dst); + if (FI && !MFI->isFixedObjectIndex(FI->getIndex())) + DstAlignCanChange = true; + bool NonScalarIntSafe = + isa(Src) && cast(Src)->isNullValue(); + if (!FindOptimalMemOpLowering(MemOps, TLI.getMaxStoresPerMemset(OptSize), + Size, (DstAlignCanChange ? 0 : Align), 0, + NonScalarIntSafe, false, DAG, TLI)) + return SDValue(); + + if (DstAlignCanChange) { + const Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext()); + unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); + if (NewAlign > Align) { + // Give the stack frame object a larger alignment if needed. + if (MFI->getObjectAlignment(FI->getIndex()) < NewAlign) + MFI->setObjectAlignment(FI->getIndex(), NewAlign); + Align = NewAlign; + } + } + + SmallVector OutChains; + uint64_t DstOff = 0; + unsigned NumMemOps = MemOps.size(); + + // Find the largest store and generate the bit pattern for it. + EVT LargestVT = MemOps[0]; + for (unsigned i = 1; i < NumMemOps; i++) + if (MemOps[i].bitsGT(LargestVT)) + LargestVT = MemOps[i]; + SDValue MemSetValue = getMemsetValue(Src, LargestVT, DAG, dl); + + for (unsigned i = 0; i < NumMemOps; i++) { + EVT VT = MemOps[i]; + + // If this store is smaller than the largest store see whether we can get + // the smaller value for free with a truncate. + SDValue Value = MemSetValue; + if (VT.bitsLT(LargestVT)) { + if (!LargestVT.isVector() && !VT.isVector() && + TLI.isTruncateFree(LargestVT, VT)) + Value = DAG.getNode(ISD::TRUNCATE, dl, VT, MemSetValue); + else + Value = getMemsetValue(Src, VT, DAG, dl); + } + assert(Value.getValueType() == VT && "Value with wrong type."); + SDValue Store = DAG.getStore(Chain, dl, Value, + getMemBasePlusOffset(Dst, DstOff, DAG), + DstPtrInfo.getWithOffset(DstOff), + isVol, false, Align); + OutChains.push_back(Store); + DstOff += VT.getSizeInBits() / 8; + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); +} + +SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, bool isVol, bool AlwaysInline, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) { + + // Check to see if we should lower the memcpy to loads and stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memcpy with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(),Align, + isVol, false, DstPtrInfo, SrcPtrInfo); + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memcpy with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TSI.EmitTargetCodeForMemcpy(*this, dl, Chain, Dst, Src, Size, Align, + isVol, AlwaysInline, + DstPtrInfo, SrcPtrInfo); + if (Result.getNode()) + return Result; + + // If we really need inline code and the target declined to provide it, + // use a (potentially long) sequence of loads and stores. + if (AlwaysInline) { + assert(ConstantSize && "AlwaysInline requires a constant size!"); + return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(), Align, isVol, + true, DstPtrInfo, SrcPtrInfo); + } + + // FIXME: If the memcpy is volatile (isVol), lowering it to a plain libc + // memcpy is not guaranteed to be safe. libc memcpys aren't required to + // respect volatile, so they may do things like read or write memory + // beyond the given memory regions. But fixing this isn't easy, and most + // people don't care. + + // Emit a library call. + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); + Entry.Node = Dst; Args.push_back(Entry); + Entry.Node = Src; Args.push_back(Entry); + Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMCPY), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMCPY), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, bool isVol, + MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo) { + + // Check to see if we should lower the memmove to loads and stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memmove with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = + getMemmoveLoadsAndStores(*this, dl, Chain, Dst, Src, + ConstantSize->getZExtValue(), Align, isVol, + false, DstPtrInfo, SrcPtrInfo); + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memmove with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TSI.EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size, Align, isVol, + DstPtrInfo, SrcPtrInfo); + if (Result.getNode()) + return Result; + + // FIXME: If the memmove is volatile, lowering it to plain libc memmove may + // not be safe. See memcpy above for more details. + + // Emit a library call. + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Ty = TLI.getTargetData()->getIntPtrType(*getContext()); + Entry.Node = Dst; Args.push_back(Entry); + Entry.Node = Src; Args.push_back(Entry); + Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMMOVE), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMMOVE), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, + SDValue Src, SDValue Size, + unsigned Align, bool isVol, + MachinePointerInfo DstPtrInfo) { + + // Check to see if we should lower the memset to stores first. + // For cases within the target-specified limits, this is the best choice. + ConstantSDNode *ConstantSize = dyn_cast(Size); + if (ConstantSize) { + // Memset with size zero? Just return the original chain. + if (ConstantSize->isNullValue()) + return Chain; + + SDValue Result = + getMemsetStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), + Align, isVol, DstPtrInfo); + + if (Result.getNode()) + return Result; + } + + // Then check to see if we should lower the memset with target-specific + // code. If the target chooses to do this, this is the next best. + SDValue Result = + TSI.EmitTargetCodeForMemset(*this, dl, Chain, Dst, Src, Size, Align, isVol, + DstPtrInfo); + if (Result.getNode()) + return Result; + + // Emit a library call. + const Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*getContext()); + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Node = Dst; Entry.Ty = IntPtrTy; + Args.push_back(Entry); + // Extend or truncate the argument to be an i32 value for the call. + if (Src.getValueType().bitsGT(MVT::i32)) + Src = getNode(ISD::TRUNCATE, dl, MVT::i32, Src); + else + Src = getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); + Entry.Node = Src; + Entry.Ty = Type::getInt32Ty(*getContext()); + Entry.isSExt = true; + Args.push_back(Entry); + Entry.Node = Size; + Entry.Ty = IntPtrTy; + Entry.isSExt = false; + Args.push_back(Entry); + // FIXME: pass in DebugLoc + std::pair CallResult = + TLI.LowerCallTo(Chain, Type::getVoidTy(*getContext()), + false, false, false, false, 0, + TLI.getLibcallCallingConv(RTLIB::MEMSET), false, + /*isReturnValueUsed=*/false, + getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), + TLI.getPointerTy()), + Args, *this, dl); + return CallResult.second; +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, SDValue Ptr, SDValue Cmp, + SDValue Swp, MachinePointerInfo PtrInfo, + unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(MemVT); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; + + // For now, atomics are considered to be volatile always. + Flags |= MachineMemOperand::MOVolatile; + + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Alignment); + + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Cmp, Swp, MMO); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Cmp, + SDValue Swp, MachineMemOperand *MMO) { + assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op"); + assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types"); + + EVT VT = Cmp.getValueType(); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Cmp, Swp}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 4); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, + Ptr, Cmp, Swp, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Val, + const Value* PtrVal, + unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(MemVT); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore; + + // For now, atomics are considered to be volatile always. + Flags |= MachineMemOperand::MOVolatile; + + MachineMemOperand *MMO = + MF.getMachineMemOperand(MachinePointerInfo(PtrVal), Flags, + MemVT.getStoreSize(), Alignment); + + return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Val, MMO); +} + +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO) { + assert((Opcode == ISD::ATOMIC_LOAD_ADD || + Opcode == ISD::ATOMIC_LOAD_SUB || + Opcode == ISD::ATOMIC_LOAD_AND || + Opcode == ISD::ATOMIC_LOAD_OR || + Opcode == ISD::ATOMIC_LOAD_XOR || + Opcode == ISD::ATOMIC_LOAD_NAND || + Opcode == ISD::ATOMIC_LOAD_MIN || + Opcode == ISD::ATOMIC_LOAD_MAX || + Opcode == ISD::ATOMIC_LOAD_UMIN || + Opcode == ISD::ATOMIC_LOAD_UMAX || + Opcode == ISD::ATOMIC_SWAP) && + "Invalid Atomic Op"); + + EVT VT = Val.getValueType(); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Val}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, + Ptr, Val, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +/// getMergeValues - Create a MERGE_VALUES node from the given operands. +SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps, + DebugLoc dl) { + if (NumOps == 1) + return Ops[0]; + + SmallVector VTs; + VTs.reserve(NumOps); + for (unsigned i = 0; i < NumOps; ++i) + VTs.push_back(Ops[i].getValueType()); + return getNode(ISD::MERGE_VALUES, dl, getVTList(&VTs[0], NumOps), + Ops, NumOps); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachinePointerInfo PtrInfo, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + return getMemIntrinsicNode(Opcode, dl, makeVTList(VTs, NumVTs), Ops, NumOps, + MemVT, PtrInfo, Align, Vol, + ReadMem, WriteMem); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachinePointerInfo PtrInfo, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + if (Align == 0) // Ensure that codegen never sees alignment 0 + Align = getEVTAlignment(MemVT); + + MachineFunction &MF = getMachineFunction(); + unsigned Flags = 0; + if (WriteMem) + Flags |= MachineMemOperand::MOStore; + if (ReadMem) + Flags |= MachineMemOperand::MOLoad; + if (Vol) + Flags |= MachineMemOperand::MOVolatile; + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Align); + + return getMemIntrinsicNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); +} + +SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO) { + assert((Opcode == ISD::INTRINSIC_VOID || + Opcode == ISD::INTRINSIC_W_CHAIN || + Opcode == ISD::PREFETCH || + (Opcode <= INT_MAX && + (int)Opcode >= ISD::FIRST_TARGET_MEMORY_OPCODE)) && + "Opcode is not a memory-accessing opcode!"); + + // Memoize the node unless it returns a flag. + MemIntrinsicSDNode *N; + if (VTList.VTs[VTList.NumVTs-1] != MVT::Glue) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + + N = new (NodeAllocator) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, + MemVT, MMO); + CSEMap.InsertNode(N, IP); + } else { + N = new (NodeAllocator) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, + MemVT, MMO); + } + AllNodes.push_back(N); + return SDValue(N, 0); +} + +/// InferPointerInfo - If the specified ptr/offset is a frame index, infer a +/// MachinePointerInfo record from it. This is particularly useful because the +/// code generator has many cases where it doesn't bother passing in a +/// MachinePointerInfo to getLoad or getStore when it has "FI+Cst". +static MachinePointerInfo InferPointerInfo(SDValue Ptr, int64_t Offset = 0) { + // If this is FI+Offset, we can model it. + if (const FrameIndexSDNode *FI = dyn_cast(Ptr)) + return MachinePointerInfo::getFixedStack(FI->getIndex(), Offset); + + // If this is (FI+Offset1)+Offset2, we can model it. + if (Ptr.getOpcode() != ISD::ADD || + !isa(Ptr.getOperand(1)) || + !isa(Ptr.getOperand(0))) + return MachinePointerInfo(); + + int FI = cast(Ptr.getOperand(0))->getIndex(); + return MachinePointerInfo::getFixedStack(FI, Offset+ + cast(Ptr.getOperand(1))->getSExtValue()); +} + +/// InferPointerInfo - If the specified ptr/offset is a frame index, infer a +/// MachinePointerInfo record from it. This is particularly useful because the +/// code generator has many cases where it doesn't bother passing in a +/// MachinePointerInfo to getLoad or getStore when it has "FI+Cst". +static MachinePointerInfo InferPointerInfo(SDValue Ptr, SDValue OffsetOp) { + // If the 'Offset' value isn't a constant, we can't handle this. + if (ConstantSDNode *OffsetNode = dyn_cast(OffsetOp)) + return InferPointerInfo(Ptr, OffsetNode->getSExtValue()); + if (OffsetOp.getOpcode() == ISD::UNDEF) + return InferPointerInfo(Ptr); + return MachinePointerInfo(); +} + + +SDValue +SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, + EVT VT, DebugLoc dl, SDValue Chain, + SDValue Ptr, SDValue Offset, + MachinePointerInfo PtrInfo, EVT MemVT, + bool isVolatile, bool isNonTemporal, + unsigned Alignment, const MDNode *TBAAInfo) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(VT); + + unsigned Flags = MachineMemOperand::MOLoad; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; + + // If we don't have a PtrInfo, infer the trivial frame index case to simplify + // clients. + if (PtrInfo.V == 0) + PtrInfo = InferPointerInfo(Ptr, Offset); + + MachineFunction &MF = getMachineFunction(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrInfo, Flags, MemVT.getStoreSize(), Alignment, + TBAAInfo); + return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, MemVT, MMO); +} + +SDValue +SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, + EVT VT, DebugLoc dl, SDValue Chain, + SDValue Ptr, SDValue Offset, EVT MemVT, + MachineMemOperand *MMO) { + if (VT == MemVT) { + ExtType = ISD::NON_EXTLOAD; + } else if (ExtType == ISD::NON_EXTLOAD) { + assert(VT == MemVT && "Non-extending load from different memory type!"); + } else { + // Extending load. + assert(MemVT.getScalarType().bitsLT(VT.getScalarType()) && + "Should only be an extending load, not truncating!"); + assert(VT.isInteger() == MemVT.isInteger() && + "Cannot convert from FP to Int or Int -> FP!"); + assert(VT.isVector() == MemVT.isVector() && + "Cannot use trunc store to convert to or from a vector!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == MemVT.getVectorNumElements()) && + "Cannot use trunc store to change the number of vector elements!"); + } + + bool Indexed = AM != ISD::UNINDEXED; + assert((Indexed || Offset.getOpcode() == ISD::UNDEF) && + "Unindexed load with an offset!"); + + SDVTList VTs = Indexed ? + getVTList(VT, Ptr.getValueType(), MVT::Other) : getVTList(VT, MVT::Other); + SDValue Ops[] = { Chain, Ptr, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); + ID.AddInteger(MemVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, MMO->isVolatile(), + MMO->isNonTemporal())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) LoadSDNode(Ops, dl, VTs, AM, ExtType, + MemVT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getLoad(EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, + MachinePointerInfo PtrInfo, + bool isVolatile, bool isNonTemporal, + unsigned Alignment, const MDNode *TBAAInfo) { + SDValue Undef = getUNDEF(Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef, + PtrInfo, VT, isVolatile, isNonTemporal, Alignment, TBAAInfo); +} + +SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, + SDValue Chain, SDValue Ptr, + MachinePointerInfo PtrInfo, EVT MemVT, + bool isVolatile, bool isNonTemporal, + unsigned Alignment, const MDNode *TBAAInfo) { + SDValue Undef = getUNDEF(Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef, + PtrInfo, MemVT, isVolatile, isNonTemporal, Alignment, + TBAAInfo); +} + + +SDValue +SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + LoadSDNode *LD = cast(OrigLoad); + assert(LD->getOffset().getOpcode() == ISD::UNDEF && + "Load is already a indexed load!"); + return getLoad(AM, LD->getExtensionType(), OrigLoad.getValueType(), dl, + LD->getChain(), Base, Offset, LD->getPointerInfo(), + LD->getMemoryVT(), + LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment()); +} + +SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, MachinePointerInfo PtrInfo, + bool isVolatile, bool isNonTemporal, + unsigned Alignment, const MDNode *TBAAInfo) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(Val.getValueType()); + + unsigned Flags = MachineMemOperand::MOStore; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; + + if (PtrInfo.V == 0) + PtrInfo = InferPointerInfo(Ptr); + + MachineFunction &MF = getMachineFunction(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrInfo, Flags, + Val.getValueType().getStoreSize(), Alignment, + TBAAInfo); + + return getStore(Chain, dl, Val, Ptr, MMO); +} + +SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, MachineMemOperand *MMO) { + EVT VT = Val.getValueType(); + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getUNDEF(Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(VT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, + false, VT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, MachinePointerInfo PtrInfo, + EVT SVT,bool isVolatile, bool isNonTemporal, + unsigned Alignment, + const MDNode *TBAAInfo) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getEVTAlignment(SVT); + + unsigned Flags = MachineMemOperand::MOStore; + if (isVolatile) + Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; + + if (PtrInfo.V == 0) + PtrInfo = InferPointerInfo(Ptr); + + MachineFunction &MF = getMachineFunction(); + MachineMemOperand *MMO = + MF.getMachineMemOperand(PtrInfo, Flags, SVT.getStoreSize(), Alignment, + TBAAInfo); + + return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO); +} + +SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, EVT SVT, + MachineMemOperand *MMO) { + EVT VT = Val.getValueType(); + + if (VT == SVT) + return getStore(Chain, dl, Val, Ptr, MMO); + + assert(SVT.getScalarType().bitsLT(VT.getScalarType()) && + "Should only be a truncating store, not extending!"); + assert(VT.isInteger() == SVT.isInteger() && + "Can't do FP-INT conversion!"); + assert(VT.isVector() == SVT.isVector() && + "Cannot use trunc store to convert to or from a vector!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == SVT.getVectorNumElements()) && + "Cannot use trunc store to change the number of vector elements!"); + + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getUNDEF(Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(SVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal())); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + cast(E)->refineAlignment(MMO); + return SDValue(E, 0); + } + SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, + true, SVT, MMO); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue +SelectionDAG::getIndexedStore(SDValue OrigStore, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + StoreSDNode *ST = cast(OrigStore); + assert(ST->getOffset().getOpcode() == ISD::UNDEF && + "Store is already a indexed store!"); + SDVTList VTs = getVTList(Base.getValueType(), MVT::Other); + SDValue Ops[] = { ST->getChain(), ST->getValue(), Base, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(ST->getMemoryVT().getRawBits()); + ID.AddInteger(ST->getRawSubclassData()); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, AM, + ST->isTruncatingStore(), + ST->getMemoryVT(), + ST->getMemOperand()); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getVAArg(EVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, + SDValue SV, + unsigned Align) { + SDValue Ops[] = { Chain, Ptr, SV, getTargetConstant(Align, MVT::i32) }; + return getNode(ISD::VAARG, dl, getVTList(VT, MVT::Other), Ops, 4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDUse *Ops, unsigned NumOps) { + switch (NumOps) { + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); + default: break; + } + + // Copy from an SDUse array into an SDValue array for use with + // the regular getNode logic. + SmallVector NewOps(Ops, Ops + NumOps); + return getNode(Opcode, DL, VT, &NewOps[0], NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT, + const SDValue *Ops, unsigned NumOps) { + switch (NumOps) { + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); + default: break; + } + + switch (Opcode) { + default: break; + case ISD::SELECT_CC: { + assert(NumOps == 5 && "SELECT_CC takes 5 operands!"); + assert(Ops[0].getValueType() == Ops[1].getValueType() && + "LHS and RHS of condition must have same type!"); + assert(Ops[2].getValueType() == Ops[3].getValueType() && + "True and False arms of SelectCC must have same type!"); + assert(Ops[2].getValueType() == VT && + "select_cc node must be of same type as true and false value!"); + break; + } + case ISD::BR_CC: { + assert(NumOps == 5 && "BR_CC takes 5 operands!"); + assert(Ops[2].getValueType() == Ops[3].getValueType() && + "LHS/RHS of comparison should match types!"); + break; + } + } + + // Memoize nodes. + SDNode *N; + SDVTList VTs = getVTList(VT); + + if (VT != MVT::Glue) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); + void *IP = 0; + + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = new (NodeAllocator) SDNode(Opcode, DL, VTs, Ops, NumOps); + CSEMap.InsertNode(N, IP); + } else { + N = new (NodeAllocator) SDNode(Opcode, DL, VTs, Ops, NumOps); + } + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DL, getVTList(&ResultTys[0], ResultTys.size()), + Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const EVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps) { + if (NumVTs == 1) + return getNode(Opcode, DL, VTs[0], Ops, NumOps); + return getNode(Opcode, DL, makeVTList(VTs, NumVTs), Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + const SDValue *Ops, unsigned NumOps) { + if (VTList.NumVTs == 1) + return getNode(Opcode, DL, VTList.VTs[0], Ops, NumOps); + +#if 0 + switch (Opcode) { + // FIXME: figure out how to safely handle things like + // int foo(int x) { return 1 << (x & 255); } + // int bar() { return foo(256); } + case ISD::SRA_PARTS: + case ISD::SRL_PARTS: + case ISD::SHL_PARTS: + if (N3.getOpcode() == ISD::SIGN_EXTEND_INREG && + cast(N3.getOperand(1))->getVT() != MVT::i1) + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); + else if (N3.getOpcode() == ISD::AND) + if (ConstantSDNode *AndRHS = dyn_cast(N3.getOperand(1))) { + // If the and is only masking out bits that cannot effect the shift, + // eliminate the and. + unsigned NumBits = VT.getScalarType().getSizeInBits()*2; + if ((AndRHS->getValue() & (NumBits-1)) == NumBits-1) + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); + } + break; + } +#endif + + // Memoize the node unless it returns a flag. + SDNode *N; + if (VTList.VTs[VTList.NumVTs-1] != MVT::Glue) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + if (NumOps == 1) { + N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTList, Ops[0]); + } else if (NumOps == 2) { + N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); + } else if (NumOps == 3) { + N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], + Ops[2]); + } else { + N = new (NodeAllocator) SDNode(Opcode, DL, VTList, Ops, NumOps); + } + CSEMap.InsertNode(N, IP); + } else { + if (NumOps == 1) { + N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTList, Ops[0]); + } else if (NumOps == 2) { + N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); + } else if (NumOps == 3) { + N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], + Ops[2]); + } else { + N = new (NodeAllocator) SDNode(Opcode, DL, VTList, Ops, NumOps); + } + } + AllNodes.push_back(N); +#ifndef NDEBUG + VerifySDNode(N); +#endif + return SDValue(N, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList) { + return getNode(Opcode, DL, VTList, 0, 0); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1) { + SDValue Ops[] = { N1 }; + return getNode(Opcode, DL, VTList, Ops, 1); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2) { + SDValue Ops[] = { N1, N2 }; + return getNode(Opcode, DL, VTList, Ops, 2); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3) { + SDValue Ops[] = { N1, N2, N3 }; + return getNode(Opcode, DL, VTList, Ops, 3); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { + SDValue Ops[] = { N1, N2, N3, N4 }; + return getNode(Opcode, DL, VTList, Ops, 4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { + SDValue Ops[] = { N1, N2, N3, N4, N5 }; + return getNode(Opcode, DL, VTList, Ops, 5); +} + +SDVTList SelectionDAG::getVTList(EVT VT) { + return makeVTList(SDNode::getValueTypeList(VT), 1); +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 2 && I->VTs[0] == VT1 && I->VTs[1] == VT2) + return *I; + + EVT *Array = Allocator.Allocate(2); + Array[0] = VT1; + Array[1] = VT2; + SDVTList Result = makeVTList(Array, 2); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 3 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && + I->VTs[2] == VT3) + return *I; + + EVT *Array = Allocator.Allocate(3); + Array[0] = VT1; + Array[1] = VT2; + Array[2] = VT3; + SDVTList Result = makeVTList(Array, 3); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4) { + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) + if (I->NumVTs == 4 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && + I->VTs[2] == VT3 && I->VTs[3] == VT4) + return *I; + + EVT *Array = Allocator.Allocate(4); + Array[0] = VT1; + Array[1] = VT2; + Array[2] = VT3; + Array[3] = VT4; + SDVTList Result = makeVTList(Array, 4); + VTList.push_back(Result); + return Result; +} + +SDVTList SelectionDAG::getVTList(const EVT *VTs, unsigned NumVTs) { + switch (NumVTs) { + case 0: llvm_unreachable("Cannot have nodes without results!"); + case 1: return getVTList(VTs[0]); + case 2: return getVTList(VTs[0], VTs[1]); + case 3: return getVTList(VTs[0], VTs[1], VTs[2]); + case 4: return getVTList(VTs[0], VTs[1], VTs[2], VTs[3]); + default: break; + } + + for (std::vector::reverse_iterator I = VTList.rbegin(), + E = VTList.rend(); I != E; ++I) { + if (I->NumVTs != NumVTs || VTs[0] != I->VTs[0] || VTs[1] != I->VTs[1]) + continue; + + bool NoMatch = false; + for (unsigned i = 2; i != NumVTs; ++i) + if (VTs[i] != I->VTs[i]) { + NoMatch = true; + break; + } + if (!NoMatch) + return *I; + } + + EVT *Array = Allocator.Allocate(NumVTs); + std::copy(VTs, VTs+NumVTs, Array); + SDVTList Result = makeVTList(Array, NumVTs); + VTList.push_back(Result); + return Result; +} + + +/// UpdateNodeOperands - *Mutate* the specified node in-place to have the +/// specified operands. If the resultant node already exists in the DAG, +/// this does not modify the specified node, instead it returns the node that +/// already exists. If the resultant node does not exist in the DAG, the +/// input node is returned. As a degenerate case, if you specify the same +/// input operands as the node already has, the input node is returned. +SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op) { + assert(N->getNumOperands() == 1 && "Update with wrong number of operands"); + + // Check to see if there is no change. + if (Op == N->getOperand(0)) return N; + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Op, InsertPos)) + return Existing; + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + N->OperandList[0].set(Op); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return N; +} + +SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2) { + assert(N->getNumOperands() == 2 && "Update with wrong number of operands"); + + // Check to see if there is no change. + if (Op1 == N->getOperand(0) && Op2 == N->getOperand(1)) + return N; // No operands changed, just return the input node. + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Op1, Op2, InsertPos)) + return Existing; + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + if (N->OperandList[0] != Op1) + N->OperandList[0].set(Op1); + if (N->OperandList[1] != Op2) + N->OperandList[1].set(Op2); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return N; +} + +SDNode *SelectionDAG:: +UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, SDValue Op3) { + SDValue Ops[] = { Op1, Op2, Op3 }; + return UpdateNodeOperands(N, Ops, 3); +} + +SDNode *SelectionDAG:: +UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4) { + SDValue Ops[] = { Op1, Op2, Op3, Op4 }; + return UpdateNodeOperands(N, Ops, 4); +} + +SDNode *SelectionDAG:: +UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, + SDValue Op3, SDValue Op4, SDValue Op5) { + SDValue Ops[] = { Op1, Op2, Op3, Op4, Op5 }; + return UpdateNodeOperands(N, Ops, 5); +} + +SDNode *SelectionDAG:: +UpdateNodeOperands(SDNode *N, const SDValue *Ops, unsigned NumOps) { + assert(N->getNumOperands() == NumOps && + "Update with wrong number of operands"); + + // Check to see if there is no change. + bool AnyChange = false; + for (unsigned i = 0; i != NumOps; ++i) { + if (Ops[i] != N->getOperand(i)) { + AnyChange = true; + break; + } + } + + // No operands changed, just return the input node. + if (!AnyChange) return N; + + // See if the modified node already exists. + void *InsertPos = 0; + if (SDNode *Existing = FindModifiedNodeSlot(N, Ops, NumOps, InsertPos)) + return Existing; + + // Nope it doesn't. Remove the node from its current place in the maps. + if (InsertPos) + if (!RemoveNodeFromCSEMaps(N)) + InsertPos = 0; + + // Now we update the operands. + for (unsigned i = 0; i != NumOps; ++i) + if (N->OperandList[i] != Ops[i]) + N->OperandList[i].set(Ops[i]); + + // If this gets put into a CSE map, add it. + if (InsertPos) CSEMap.InsertNode(N, InsertPos); + return N; +} + +/// DropOperands - Release the operands and set this node to have +/// zero operands. +void SDNode::DropOperands() { + // Unlike the code in MorphNodeTo that does this, we don't need to + // watch for dead nodes here. + for (op_iterator I = op_begin(), E = op_end(); I != E; ) { + SDUse &Use = *I++; + Use.set(SDValue()); + } +} + +/// SelectNodeTo - These are wrappers around MorphNodeTo that accept a +/// machine opcode. +/// +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT) { + SDVTList VTs = getVTList(VT); + return SelectNodeTo(N, MachineOpc, VTs, 0, 0); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1, + SDValue Op2) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, SDValue Op1, + SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, const SDValue *Ops, + unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2) { + SDVTList VTs = getVTList(VT1, VT2); + return SelectNodeTo(N, MachineOpc, VTs, (SDValue *)0, 0); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, EVT VT4, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3, VT4); + return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 1); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 2); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2, + SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2, + SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2, Op3 }; + return SelectNodeTo(N, MachineOpc, VTs, Ops, 3); +} + +SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, + SDVTList VTs, const SDValue *Ops, + unsigned NumOps) { + N = MorphNodeTo(N, ~MachineOpc, VTs, Ops, NumOps); + // Reset the NodeID to -1. + N->setNodeId(-1); + return N; +} + +/// MorphNodeTo - This *mutates* the specified node to have the specified +/// return type, opcode, and operands. +/// +/// Note that MorphNodeTo returns the resultant node. If there is already a +/// node of the specified opcode and operands, it returns that node instead of +/// the current one. Note that the DebugLoc need not be the same. +/// +/// Using MorphNodeTo is faster than creating a new node and swapping it in +/// with ReplaceAllUsesWith both because it often avoids allocating a new +/// node, and because it doesn't require CSE recalculation for any of +/// the node's users. +/// +SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, + SDVTList VTs, const SDValue *Ops, + unsigned NumOps) { + // If an identical node already exists, use it. + void *IP = 0; + if (VTs.VTs[VTs.NumVTs-1] != MVT::Glue) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opc, VTs, Ops, NumOps); + if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) + return ON; + } + + if (!RemoveNodeFromCSEMaps(N)) + IP = 0; + + // Start the morphing. + N->NodeType = Opc; + N->ValueList = VTs.VTs; + N->NumValues = VTs.NumVTs; + + // Clear the operands list, updating used nodes to remove this from their + // use list. Keep track of any operands that become dead as a result. + SmallPtrSet DeadNodeSet; + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Used = Use.getNode(); + Use.set(SDValue()); + if (Used->use_empty()) + DeadNodeSet.insert(Used); + } + + if (MachineSDNode *MN = dyn_cast(N)) { + // Initialize the memory references information. + MN->setMemRefs(0, 0); + // If NumOps is larger than the # of operands we can have in a + // MachineSDNode, reallocate the operand list. + if (NumOps > MN->NumOperands || !MN->OperandsNeedDelete) { + if (MN->OperandsNeedDelete) + delete[] MN->OperandList; + if (NumOps > array_lengthof(MN->LocalOperands)) + // We're creating a final node that will live unmorphed for the + // remainder of the current SelectionDAG iteration, so we can allocate + // the operands directly out of a pool with no recycling metadata. + MN->InitOperands(OperandAllocator.Allocate(NumOps), + Ops, NumOps); + else + MN->InitOperands(MN->LocalOperands, Ops, NumOps); + MN->OperandsNeedDelete = false; + } else + MN->InitOperands(MN->OperandList, Ops, NumOps); + } else { + // If NumOps is larger than the # of operands we currently have, reallocate + // the operand list. + if (NumOps > N->NumOperands) { + if (N->OperandsNeedDelete) + delete[] N->OperandList; + N->InitOperands(new SDUse[NumOps], Ops, NumOps); + N->OperandsNeedDelete = true; + } else + N->InitOperands(N->OperandList, Ops, NumOps); + } + + // Delete any nodes that are still dead after adding the uses for the + // new operands. + if (!DeadNodeSet.empty()) { + SmallVector DeadNodes; + for (SmallPtrSet::iterator I = DeadNodeSet.begin(), + E = DeadNodeSet.end(); I != E; ++I) + if ((*I)->use_empty()) + DeadNodes.push_back(*I); + RemoveDeadNodes(DeadNodes); + } + + if (IP) + CSEMap.InsertNode(N, IP); // Memoize the new node. + return N; +} + + +/// getMachineNode - These are used for target selectors to create a new node +/// with specified return type(s), MachineInstr opcode, and operands. +/// +/// Note that getMachineNode returns the resultant node. If there is already a +/// node of the specified opcode and operands, it returns that node instead of +/// the current one. +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT) { + SDVTList VTs = getVTList(VT); + return getMachineNode(Opcode, dl, VTs, 0, 0); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDValue Op1) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + SDValue Op1, SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2) { + SDVTList VTs = getVTList(VT1, VT2); + return getMachineNode(Opcode, dl, VTs, 0, 0); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, SDValue Op1, + SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + SDValue Op1, SDValue Op2, SDValue Op3) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops)); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + EVT VT1, EVT VT2, EVT VT3, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, + EVT VT2, EVT VT3, EVT VT4, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(VT1, VT2, VT3, VT4); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, + const std::vector &ResultTys, + const SDValue *Ops, unsigned NumOps) { + SDVTList VTs = getVTList(&ResultTys[0], ResultTys.size()); + return getMachineNode(Opcode, dl, VTs, Ops, NumOps); +} + +MachineSDNode * +SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc DL, SDVTList VTs, + const SDValue *Ops, unsigned NumOps) { + bool DoCSE = VTs.VTs[VTs.NumVTs-1] != MVT::Glue; + MachineSDNode *N; + void *IP = 0; + + if (DoCSE) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps); + IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return cast(E); + } + + // Allocate a new MachineSDNode. + N = new (NodeAllocator) MachineSDNode(~Opcode, DL, VTs); + + // Initialize the operands list. + if (NumOps > array_lengthof(N->LocalOperands)) + // We're creating a final node that will live unmorphed for the + // remainder of the current SelectionDAG iteration, so we can allocate + // the operands directly out of a pool with no recycling metadata. + N->InitOperands(OperandAllocator.Allocate(NumOps), + Ops, NumOps); + else + N->InitOperands(N->LocalOperands, Ops, NumOps); + N->OperandsNeedDelete = false; + + if (DoCSE) + CSEMap.InsertNode(N, IP); + + AllNodes.push_back(N); +#ifndef NDEBUG + VerifyMachineNode(N); +#endif + return N; +} + +/// getTargetExtractSubreg - A convenience function for creating +/// TargetOpcode::EXTRACT_SUBREG nodes. +SDValue +SelectionDAG::getTargetExtractSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand) { + SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); + SDNode *Subreg = getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, + VT, Operand, SRIdxVal); + return SDValue(Subreg, 0); +} + +/// getTargetInsertSubreg - A convenience function for creating +/// TargetOpcode::INSERT_SUBREG nodes. +SDValue +SelectionDAG::getTargetInsertSubreg(int SRIdx, DebugLoc DL, EVT VT, + SDValue Operand, SDValue Subreg) { + SDValue SRIdxVal = getTargetConstant(SRIdx, MVT::i32); + SDNode *Result = getMachineNode(TargetOpcode::INSERT_SUBREG, DL, + VT, Operand, Subreg, SRIdxVal); + return SDValue(Result, 0); +} + +/// getNodeIfExists - Get the specified node if it's already available, or +/// else return NULL. +SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList, + const SDValue *Ops, unsigned NumOps) { + if (VTList.VTs[VTList.NumVTs-1] != MVT::Glue) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return E; + } + return NULL; +} + +/// getDbgValue - Creates a SDDbgValue node. +/// +SDDbgValue * +SelectionDAG::getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, uint64_t Off, + DebugLoc DL, unsigned O) { + return new (Allocator) SDDbgValue(MDPtr, N, R, Off, DL, O); +} + +SDDbgValue * +SelectionDAG::getDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, + DebugLoc DL, unsigned O) { + return new (Allocator) SDDbgValue(MDPtr, C, Off, DL, O); +} + +SDDbgValue * +SelectionDAG::getDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, + DebugLoc DL, unsigned O) { + return new (Allocator) SDDbgValue(MDPtr, FI, Off, DL, O); +} + +namespace { + +/// RAUWUpdateListener - Helper for ReplaceAllUsesWith - When the node +/// pointed to by a use iterator is deleted, increment the use iterator +/// so that it doesn't dangle. +/// +/// This class also manages a "downlink" DAGUpdateListener, to forward +/// messages to ReplaceAllUsesWith's callers. +/// +class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener { + SelectionDAG::DAGUpdateListener *DownLink; + SDNode::use_iterator &UI; + SDNode::use_iterator &UE; + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + // Increment the iterator as needed. + while (UI != UE && N == *UI) + ++UI; + + // Then forward the message. + if (DownLink) DownLink->NodeDeleted(N, E); + } + + virtual void NodeUpdated(SDNode *N) { + // Just forward the message. + if (DownLink) DownLink->NodeUpdated(N); + } + +public: + RAUWUpdateListener(SelectionDAG::DAGUpdateListener *dl, + SDNode::use_iterator &ui, + SDNode::use_iterator &ue) + : DownLink(dl), UI(ui), UE(ue) {} +}; + +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version assumes From has a single result value. +/// +void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, + DAGUpdateListener *UpdateListener) { + SDNode *From = FromN.getNode(); + assert(From->getNumValues() == 1 && FromN.getResNo() == 0 && + "Cannot replace with this method!"); + assert(From != To.getNode() && "Cannot replace uses of with self"); + + // Iterate over all the existing uses of From. New uses will be added + // to the beginning of the use list, which we avoid visiting. + // This specifically avoids visiting uses of From that arise while the + // replacement is happening, because any such uses would be the result + // of CSE: If an existing node looks like From after one of its operands + // is replaced by To, we don't want to replace of all its users with To + // too. See PR3018 for more info. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, &Listener); + } +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version assumes that for each value of From, there is a +/// corresponding value in To in the same position with the same type. +/// +void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, + DAGUpdateListener *UpdateListener) { +#ifndef NDEBUG + for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) + assert((!From->hasAnyUseOfValue(i) || + From->getValueType(i) == To->getValueType(i)) && + "Cannot use this version of ReplaceAllUsesWith!"); +#endif + + // Handle the trivial case. + if (From == To) + return; + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.setNode(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, &Listener); + } +} + +/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. +/// This can cause recursive merging of nodes in the DAG. +/// +/// This version can replace From with any result values. To must match the +/// number and types of values returned by From. +void SelectionDAG::ReplaceAllUsesWith(SDNode *From, + const SDValue *To, + DAGUpdateListener *UpdateListener) { + if (From->getNumValues() == 1) // Handle the simple case efficiently. + return ReplaceAllUsesWith(SDValue(From, 0), To[0], UpdateListener); + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); + while (UI != UE) { + SDNode *User = *UI; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + const SDValue &ToOp = To[Use.getResNo()]; + ++UI; + Use.set(ToOp); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, &Listener); + } +} + +/// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving +/// uses of other values produced by From.getNode() alone. The Deleted +/// vector is handled the same way as for ReplaceAllUsesWith. +void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, + DAGUpdateListener *UpdateListener){ + // Handle the really simple, really trivial case efficiently. + if (From == To) return; + + // Handle the simple, trivial, case efficiently. + if (From.getNode()->getNumValues() == 1) { + ReplaceAllUsesWith(From, To, UpdateListener); + return; + } + + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From.getNode()->use_begin(), + UE = From.getNode()->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); + while (UI != UE) { + SDNode *User = *UI; + bool UserRemovedFromCSEMaps = false; + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + + // Skip uses of different values from the same node. + if (Use.getResNo() != From.getResNo()) { + ++UI; + continue; + } + + // If this node hasn't been modified yet, it's still in the CSE maps, + // so remove its old self from the CSE maps. + if (!UserRemovedFromCSEMaps) { + RemoveNodeFromCSEMaps(User); + UserRemovedFromCSEMaps = true; + } + + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // We are iterating over all uses of the From node, so if a use + // doesn't use the specific value, no changes are made. + if (!UserRemovedFromCSEMaps) + continue; + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, &Listener); + } +} + +namespace { + /// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith + /// to record information about a use. + struct UseMemo { + SDNode *User; + unsigned Index; + SDUse *Use; + }; + + /// operator< - Sort Memos by User. + bool operator<(const UseMemo &L, const UseMemo &R) { + return (intptr_t)L.User < (intptr_t)R.User; + } +} + +/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving +/// uses of other values produced by From.getNode() alone. The same value +/// may appear in both the From and To list. The Deleted vector is +/// handled the same way as for ReplaceAllUsesWith. +void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, + const SDValue *To, + unsigned Num, + DAGUpdateListener *UpdateListener){ + // Handle the simple, trivial case efficiently. + if (Num == 1) + return ReplaceAllUsesOfValueWith(*From, *To, UpdateListener); + + // Read up all the uses and make records of them. This helps + // processing new uses that are introduced during the + // replacement process. + SmallVector Uses; + for (unsigned i = 0; i != Num; ++i) { + unsigned FromResNo = From[i].getResNo(); + SDNode *FromNode = From[i].getNode(); + for (SDNode::use_iterator UI = FromNode->use_begin(), + E = FromNode->use_end(); UI != E; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == FromResNo) { + UseMemo Memo = { *UI, i, &Use }; + Uses.push_back(Memo); + } + } + } + + // Sort the uses, so that all the uses from a given User are together. + std::sort(Uses.begin(), Uses.end()); + + for (unsigned UseIndex = 0, UseIndexEnd = Uses.size(); + UseIndex != UseIndexEnd; ) { + // We know that this user uses some value of From. If it is the right + // value, update it. + SDNode *User = Uses[UseIndex].User; + + // This node is about to morph, remove its old self from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // The Uses array is sorted, so all the uses for a given User + // are next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + unsigned i = Uses[UseIndex].Index; + SDUse &Use = *Uses[UseIndex].Use; + ++UseIndex; + + Use.set(To[i]); + } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG +/// based on their topological order. It returns the maximum id and a vector +/// of the SDNodes* in assigned order by reference. +unsigned SelectionDAG::AssignTopologicalOrder() { + + unsigned DAGSize = 0; + + // SortedPos tracks the progress of the algorithm. Nodes before it are + // sorted, nodes after it are unsorted. When the algorithm completes + // it is at the end of the list. + allnodes_iterator SortedPos = allnodes_begin(); + + // Visit all the nodes. Move nodes with no operands to the front of + // the list immediately. Annotate nodes that do have operands with their + // operand count. Before we do this, the Node Id fields of the nodes + // may contain arbitrary values. After, the Node Id fields for nodes + // before SortedPos will contain the topological sort index, and the + // Node Id fields for nodes At SortedPos and after will contain the + // count of outstanding operands. + for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) { + SDNode *N = I++; + checkForCycles(N); + unsigned Degree = N->getNumOperands(); + if (Degree == 0) { + // A node with no uses, add it to the result array immediately. + N->setNodeId(DAGSize++); + allnodes_iterator Q = N; + if (Q != SortedPos) + SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q)); + assert(SortedPos != AllNodes.end() && "Overran node list"); + ++SortedPos; + } else { + // Temporarily use the Node Id as scratch space for the degree count. + N->setNodeId(Degree); + } + } + + // Visit all the nodes. As we iterate, moves nodes into sorted order, + // such that by the time the end is reached all nodes will be sorted. + for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) { + SDNode *N = I; + checkForCycles(N); + // N is in sorted position, so all its uses have one less operand + // that needs to be sorted. + for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + UI != UE; ++UI) { + SDNode *P = *UI; + unsigned Degree = P->getNodeId(); + assert(Degree != 0 && "Invalid node degree"); + --Degree; + if (Degree == 0) { + // All of P's operands are sorted, so P may sorted now. + P->setNodeId(DAGSize++); + if (P != SortedPos) + SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P)); + assert(SortedPos != AllNodes.end() && "Overran node list"); + ++SortedPos; + } else { + // Update P's outstanding operand count. + P->setNodeId(Degree); + } + } + if (I == SortedPos) { +#ifndef NDEBUG + SDNode *S = ++I; + dbgs() << "Overran sorted position:\n"; + S->dumprFull(); +#endif + llvm_unreachable(0); + } + } + + assert(SortedPos == AllNodes.end() && + "Topological sort incomplete!"); + assert(AllNodes.front().getOpcode() == ISD::EntryToken && + "First node in topological sort is not the entry token!"); + assert(AllNodes.front().getNodeId() == 0 && + "First node in topological sort has non-zero id!"); + assert(AllNodes.front().getNumOperands() == 0 && + "First node in topological sort has operands!"); + assert(AllNodes.back().getNodeId() == (int)DAGSize-1 && + "Last node in topologic sort has unexpected id!"); + assert(AllNodes.back().use_empty() && + "Last node in topologic sort has users!"); + assert(DAGSize == allnodes_size() && "Node count mismatch!"); + return DAGSize; +} + +/// AssignOrdering - Assign an order to the SDNode. +void SelectionDAG::AssignOrdering(const SDNode *SD, unsigned Order) { + assert(SD && "Trying to assign an order to a null node!"); + Ordering->add(SD, Order); +} + +/// GetOrdering - Get the order for the SDNode. +unsigned SelectionDAG::GetOrdering(const SDNode *SD) const { + assert(SD && "Trying to get the order of a null node!"); + return Ordering->getOrder(SD); +} + +/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the +/// value is produced by SD. +void SelectionDAG::AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter) { + DbgInfo->add(DB, SD, isParameter); + if (SD) + SD->setHasDebugValue(true); +} + +/// TransferDbgValues - Transfer SDDbgValues. +void SelectionDAG::TransferDbgValues(SDValue From, SDValue To) { + if (From == To || !From.getNode()->getHasDebugValue()) + return; + SDNode *FromNode = From.getNode(); + SDNode *ToNode = To.getNode(); + SmallVector &DVs = GetDbgValues(FromNode); + SmallVector ClonedDVs; + for (SmallVector::iterator I = DVs.begin(), E = DVs.end(); + I != E; ++I) { + SDDbgValue *Dbg = *I; + if (Dbg->getKind() == SDDbgValue::SDNODE) { + SDDbgValue *Clone = getDbgValue(Dbg->getMDPtr(), ToNode, To.getResNo(), + Dbg->getOffset(), Dbg->getDebugLoc(), + Dbg->getOrder()); + ClonedDVs.push_back(Clone); + } + } + for (SmallVector::iterator I = ClonedDVs.begin(), + E = ClonedDVs.end(); I != E; ++I) + AddDbgValue(*I, ToNode, false); +} + +//===----------------------------------------------------------------------===// +// SDNode Class +//===----------------------------------------------------------------------===// + +HandleSDNode::~HandleSDNode() { + DropOperands(); +} + +GlobalAddressSDNode::GlobalAddressSDNode(unsigned Opc, DebugLoc DL, + const GlobalValue *GA, + EVT VT, int64_t o, unsigned char TF) + : SDNode(Opc, DL, getSDVTList(VT)), Offset(o), TargetFlags(TF) { + TheGlobal = GA; +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT memvt, + MachineMemOperand *mmo) + : SDNode(Opc, dl, VTs), MemoryVT(memvt), MMO(mmo) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal()); + assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); + assert(isNonTemporal() == MMO->isNonTemporal() && + "Non-temporal encoding error!"); + assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps, EVT memvt, + MachineMemOperand *mmo) + : SDNode(Opc, dl, VTs, Ops, NumOps), + MemoryVT(memvt), MMO(mmo) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal()); + assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); + assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); +} + +/// Profile - Gather unique data for the node. +/// +void SDNode::Profile(FoldingSetNodeID &ID) const { + AddNodeIDNode(ID, this); +} + +namespace { + struct EVTArray { + std::vector VTs; + + EVTArray() { + VTs.reserve(MVT::LAST_VALUETYPE); + for (unsigned i = 0; i < MVT::LAST_VALUETYPE; ++i) + VTs.push_back(MVT((MVT::SimpleValueType)i)); + } + }; +} + +static ManagedStatic > EVTs; +static ManagedStatic SimpleVTArray; +static ManagedStatic > VTMutex; + +/// getValueTypeList - Return a pointer to the specified value type. +/// +const EVT *SDNode::getValueTypeList(EVT VT) { + if (VT.isExtended()) { + sys::SmartScopedLock Lock(*VTMutex); + return &(*EVTs->insert(VT).first); + } else { + assert(VT.getSimpleVT() < MVT::LAST_VALUETYPE && + "Value type out of range!"); + return &SimpleVTArray->VTs[VT.getSimpleVT().SimpleTy]; + } +} + +/// hasNUsesOfValue - Return true if there are exactly NUSES uses of the +/// indicated value. This method ignores uses of other values defined by this +/// operation. +bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const { + assert(Value < getNumValues() && "Bad value!"); + + // TODO: Only iterate over uses of a given value of the node + for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) { + if (UI.getUse().getResNo() == Value) { + if (NUses == 0) + return false; + --NUses; + } + } + + // Found exactly the right number of uses? + return NUses == 0; +} + + +/// hasAnyUseOfValue - Return true if there are any use of the indicated +/// value. This method ignores uses of other values defined by this operation. +bool SDNode::hasAnyUseOfValue(unsigned Value) const { + assert(Value < getNumValues() && "Bad value!"); + + for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) + if (UI.getUse().getResNo() == Value) + return true; + + return false; +} + + +/// isOnlyUserOf - Return true if this node is the only use of N. +/// +bool SDNode::isOnlyUserOf(SDNode *N) const { + bool Seen = false; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + SDNode *User = *I; + if (User == this) + Seen = true; + else + return false; + } + + return Seen; +} + +/// isOperand - Return true if this node is an operand of N. +/// +bool SDValue::isOperandOf(SDNode *N) const { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (*this == N->getOperand(i)) + return true; + return false; +} + +bool SDNode::isOperandOf(SDNode *N) const { + for (unsigned i = 0, e = N->NumOperands; i != e; ++i) + if (this == N->OperandList[i].getNode()) + return true; + return false; +} + +/// reachesChainWithoutSideEffects - Return true if this operand (which must +/// be a chain) reaches the specified operand without crossing any +/// side-effecting instructions on any chain path. In practice, this looks +/// through token factors and non-volatile loads. In order to remain efficient, +/// this only looks a couple of nodes in, it does not do an exhaustive search. +bool SDValue::reachesChainWithoutSideEffects(SDValue Dest, + unsigned Depth) const { + if (*this == Dest) return true; + + // Don't search too deeply, we just want to be able to see through + // TokenFactor's etc. + if (Depth == 0) return false; + + // If this is a token factor, all inputs to the TF happen in parallel. If any + // of the operands of the TF does not reach dest, then we cannot do the xform. + if (getOpcode() == ISD::TokenFactor) { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i).reachesChainWithoutSideEffects(Dest, Depth-1)) + return false; + return true; + } + + // Loads don't have side effects, look through them. + if (LoadSDNode *Ld = dyn_cast(*this)) { + if (!Ld->isVolatile()) + return Ld->getChain().reachesChainWithoutSideEffects(Dest, Depth-1); + } + return false; +} + +/// isPredecessorOf - Return true if this node is a predecessor of N. This node +/// is either an operand of N or it can be reached by traversing up the operands. +/// NOTE: this is an expensive method. Use it carefully. +bool SDNode::isPredecessorOf(SDNode *N) const { + SmallPtrSet Visited; + SmallVector Worklist; + Worklist.push_back(N); + + do { + N = Worklist.pop_back_val(); + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *Op = N->getOperand(i).getNode(); + if (Op == this) + return true; + if (Visited.insert(Op)) + Worklist.push_back(Op); + } + } while (!Worklist.empty()); + + return false; +} + +uint64_t SDNode::getConstantOperandVal(unsigned Num) const { + assert(Num < NumOperands && "Invalid child # of SDNode!"); + return cast(OperandList[Num])->getZExtValue(); +} + +std::string SDNode::getOperationName(const SelectionDAG *G) const { + switch (getOpcode()) { + default: + if (getOpcode() < ISD::BUILTIN_OP_END) + return "<>"; + if (isMachineOpcode()) { + if (G) + if (const TargetInstrInfo *TII = G->getTarget().getInstrInfo()) + if (getMachineOpcode() < TII->getNumOpcodes()) + return TII->get(getMachineOpcode()).getName(); + return "<>"; + } + if (G) { + const TargetLowering &TLI = G->getTargetLoweringInfo(); + const char *Name = TLI.getTargetNodeName(getOpcode()); + if (Name) return Name; + return "<>"; + } + return "<>"; + +#ifndef NDEBUG + case ISD::DELETED_NODE: + return "<>"; +#endif + case ISD::PREFETCH: return "Prefetch"; + case ISD::MEMBARRIER: return "MemBarrier"; + case ISD::ATOMIC_CMP_SWAP: return "AtomicCmpSwap"; + case ISD::ATOMIC_SWAP: return "AtomicSwap"; + case ISD::ATOMIC_LOAD_ADD: return "AtomicLoadAdd"; + case ISD::ATOMIC_LOAD_SUB: return "AtomicLoadSub"; + case ISD::ATOMIC_LOAD_AND: return "AtomicLoadAnd"; + case ISD::ATOMIC_LOAD_OR: return "AtomicLoadOr"; + case ISD::ATOMIC_LOAD_XOR: return "AtomicLoadXor"; + case ISD::ATOMIC_LOAD_NAND: return "AtomicLoadNand"; + case ISD::ATOMIC_LOAD_MIN: return "AtomicLoadMin"; + case ISD::ATOMIC_LOAD_MAX: return "AtomicLoadMax"; + case ISD::ATOMIC_LOAD_UMIN: return "AtomicLoadUMin"; + case ISD::ATOMIC_LOAD_UMAX: return "AtomicLoadUMax"; + case ISD::PCMARKER: return "PCMarker"; + case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; + case ISD::SRCVALUE: return "SrcValue"; + case ISD::MDNODE_SDNODE: return "MDNode"; + case ISD::EntryToken: return "EntryToken"; + case ISD::TokenFactor: return "TokenFactor"; + case ISD::AssertSext: return "AssertSext"; + case ISD::AssertZext: return "AssertZext"; + + case ISD::BasicBlock: return "BasicBlock"; + case ISD::VALUETYPE: return "ValueType"; + case ISD::Register: return "Register"; + + case ISD::Constant: return "Constant"; + case ISD::ConstantFP: return "ConstantFP"; + case ISD::GlobalAddress: return "GlobalAddress"; + case ISD::GlobalTLSAddress: return "GlobalTLSAddress"; + case ISD::FrameIndex: return "FrameIndex"; + case ISD::JumpTable: return "JumpTable"; + case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE"; + case ISD::RETURNADDR: return "RETURNADDR"; + case ISD::FRAMEADDR: return "FRAMEADDR"; + case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET"; + case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR"; + case ISD::LSDAADDR: return "LSDAADDR"; + case ISD::EHSELECTION: return "EHSELECTION"; + case ISD::EH_RETURN: return "EH_RETURN"; + case ISD::EH_SJLJ_SETJMP: return "EH_SJLJ_SETJMP"; + case ISD::EH_SJLJ_LONGJMP: return "EH_SJLJ_LONGJMP"; + case ISD::EH_SJLJ_DISPATCHSETUP: return "EH_SJLJ_DISPATCHSETUP"; + case ISD::ConstantPool: return "ConstantPool"; + case ISD::ExternalSymbol: return "ExternalSymbol"; + case ISD::BlockAddress: return "BlockAddress"; + case ISD::INTRINSIC_WO_CHAIN: + case ISD::INTRINSIC_VOID: + case ISD::INTRINSIC_W_CHAIN: { + unsigned OpNo = getOpcode() == ISD::INTRINSIC_WO_CHAIN ? 0 : 1; + unsigned IID = cast(getOperand(OpNo))->getZExtValue(); + if (IID < Intrinsic::num_intrinsics) + return Intrinsic::getName((Intrinsic::ID)IID); + else if (const TargetIntrinsicInfo *TII = G->getTarget().getIntrinsicInfo()) + return TII->getName(IID); + llvm_unreachable("Invalid intrinsic ID"); + } + + case ISD::BUILD_VECTOR: return "BUILD_VECTOR"; + case ISD::TargetConstant: return "TargetConstant"; + case ISD::TargetConstantFP:return "TargetConstantFP"; + case ISD::TargetGlobalAddress: return "TargetGlobalAddress"; + case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress"; + case ISD::TargetFrameIndex: return "TargetFrameIndex"; + case ISD::TargetJumpTable: return "TargetJumpTable"; + case ISD::TargetConstantPool: return "TargetConstantPool"; + case ISD::TargetExternalSymbol: return "TargetExternalSymbol"; + case ISD::TargetBlockAddress: return "TargetBlockAddress"; + + case ISD::CopyToReg: return "CopyToReg"; + case ISD::CopyFromReg: return "CopyFromReg"; + case ISD::UNDEF: return "undef"; + case ISD::MERGE_VALUES: return "merge_values"; + case ISD::INLINEASM: return "inlineasm"; + case ISD::EH_LABEL: return "eh_label"; + case ISD::HANDLENODE: return "handlenode"; + + // Unary operators + case ISD::FABS: return "fabs"; + case ISD::FNEG: return "fneg"; + case ISD::FSQRT: return "fsqrt"; + case ISD::FSIN: return "fsin"; + case ISD::FCOS: return "fcos"; + case ISD::FTRUNC: return "ftrunc"; + case ISD::FFLOOR: return "ffloor"; + case ISD::FCEIL: return "fceil"; + case ISD::FRINT: return "frint"; + case ISD::FNEARBYINT: return "fnearbyint"; + case ISD::FEXP: return "fexp"; + case ISD::FEXP2: return "fexp2"; + case ISD::FLOG: return "flog"; + case ISD::FLOG2: return "flog2"; + case ISD::FLOG10: return "flog10"; + + // Binary operators + case ISD::ADD: return "add"; + case ISD::SUB: return "sub"; + case ISD::MUL: return "mul"; + case ISD::MULHU: return "mulhu"; + case ISD::MULHS: return "mulhs"; + case ISD::SDIV: return "sdiv"; + case ISD::UDIV: return "udiv"; + case ISD::SREM: return "srem"; + case ISD::UREM: return "urem"; + case ISD::SMUL_LOHI: return "smul_lohi"; + case ISD::UMUL_LOHI: return "umul_lohi"; + case ISD::SDIVREM: return "sdivrem"; + case ISD::UDIVREM: return "udivrem"; + case ISD::AND: return "and"; + case ISD::OR: return "or"; + case ISD::XOR: return "xor"; + case ISD::SHL: return "shl"; + case ISD::SRA: return "sra"; + case ISD::SRL: return "srl"; + case ISD::ROTL: return "rotl"; + case ISD::ROTR: return "rotr"; + case ISD::FADD: return "fadd"; + case ISD::FSUB: return "fsub"; + case ISD::FMUL: return "fmul"; + case ISD::FDIV: return "fdiv"; + case ISD::FREM: return "frem"; + case ISD::FCOPYSIGN: return "fcopysign"; + case ISD::FGETSIGN: return "fgetsign"; + case ISD::FPOW: return "fpow"; + + case ISD::FPOWI: return "fpowi"; + case ISD::SETCC: return "setcc"; + case ISD::VSETCC: return "vsetcc"; + case ISD::SELECT: return "select"; + case ISD::SELECT_CC: return "select_cc"; + case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt"; + case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt"; + case ISD::CONCAT_VECTORS: return "concat_vectors"; + case ISD::INSERT_SUBVECTOR: return "insert_subvector"; + case ISD::EXTRACT_SUBVECTOR: return "extract_subvector"; + case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector"; + case ISD::VECTOR_SHUFFLE: return "vector_shuffle"; + case ISD::CARRY_FALSE: return "carry_false"; + case ISD::ADDC: return "addc"; + case ISD::ADDE: return "adde"; + case ISD::SADDO: return "saddo"; + case ISD::UADDO: return "uaddo"; + case ISD::SSUBO: return "ssubo"; + case ISD::USUBO: return "usubo"; + case ISD::SMULO: return "smulo"; + case ISD::UMULO: return "umulo"; + case ISD::SUBC: return "subc"; + case ISD::SUBE: return "sube"; + case ISD::SHL_PARTS: return "shl_parts"; + case ISD::SRA_PARTS: return "sra_parts"; + case ISD::SRL_PARTS: return "srl_parts"; + + // Conversion operators. + case ISD::SIGN_EXTEND: return "sign_extend"; + case ISD::ZERO_EXTEND: return "zero_extend"; + case ISD::ANY_EXTEND: return "any_extend"; + case ISD::SIGN_EXTEND_INREG: return "sign_extend_inreg"; + case ISD::TRUNCATE: return "truncate"; + case ISD::FP_ROUND: return "fp_round"; + case ISD::FLT_ROUNDS_: return "flt_rounds"; + case ISD::FP_ROUND_INREG: return "fp_round_inreg"; + case ISD::FP_EXTEND: return "fp_extend"; + + case ISD::SINT_TO_FP: return "sint_to_fp"; + case ISD::UINT_TO_FP: return "uint_to_fp"; + case ISD::FP_TO_SINT: return "fp_to_sint"; + case ISD::FP_TO_UINT: return "fp_to_uint"; + case ISD::BITCAST: return "bit_convert"; + case ISD::FP16_TO_FP32: return "fp16_to_fp32"; + case ISD::FP32_TO_FP16: return "fp32_to_fp16"; + + case ISD::CONVERT_RNDSAT: { + switch (cast(this)->getCvtCode()) { + default: llvm_unreachable("Unknown cvt code!"); + case ISD::CVT_FF: return "cvt_ff"; + case ISD::CVT_FS: return "cvt_fs"; + case ISD::CVT_FU: return "cvt_fu"; + case ISD::CVT_SF: return "cvt_sf"; + case ISD::CVT_UF: return "cvt_uf"; + case ISD::CVT_SS: return "cvt_ss"; + case ISD::CVT_SU: return "cvt_su"; + case ISD::CVT_US: return "cvt_us"; + case ISD::CVT_UU: return "cvt_uu"; + } + } + + // Control flow instructions + case ISD::BR: return "br"; + case ISD::BRIND: return "brind"; + case ISD::BR_JT: return "br_jt"; + case ISD::BRCOND: return "brcond"; + case ISD::BR_CC: return "br_cc"; + case ISD::CALLSEQ_START: return "callseq_start"; + case ISD::CALLSEQ_END: return "callseq_end"; + + // Other operators + case ISD::LOAD: return "load"; + case ISD::STORE: return "store"; + case ISD::VAARG: return "vaarg"; + case ISD::VACOPY: return "vacopy"; + case ISD::VAEND: return "vaend"; + case ISD::VASTART: return "vastart"; + case ISD::DYNAMIC_STACKALLOC: return "dynamic_stackalloc"; + case ISD::EXTRACT_ELEMENT: return "extract_element"; + case ISD::BUILD_PAIR: return "build_pair"; + case ISD::STACKSAVE: return "stacksave"; + case ISD::STACKRESTORE: return "stackrestore"; + case ISD::TRAP: return "trap"; + + // Bit manipulation + case ISD::BSWAP: return "bswap"; + case ISD::CTPOP: return "ctpop"; + case ISD::CTTZ: return "cttz"; + case ISD::CTLZ: return "ctlz"; + + // Trampolines + case ISD::TRAMPOLINE: return "trampoline"; + + case ISD::CONDCODE: + switch (cast(this)->get()) { + default: llvm_unreachable("Unknown setcc condition!"); + case ISD::SETOEQ: return "setoeq"; + case ISD::SETOGT: return "setogt"; + case ISD::SETOGE: return "setoge"; + case ISD::SETOLT: return "setolt"; + case ISD::SETOLE: return "setole"; + case ISD::SETONE: return "setone"; + + case ISD::SETO: return "seto"; + case ISD::SETUO: return "setuo"; + case ISD::SETUEQ: return "setue"; + case ISD::SETUGT: return "setugt"; + case ISD::SETUGE: return "setuge"; + case ISD::SETULT: return "setult"; + case ISD::SETULE: return "setule"; + case ISD::SETUNE: return "setune"; + + case ISD::SETEQ: return "seteq"; + case ISD::SETGT: return "setgt"; + case ISD::SETGE: return "setge"; + case ISD::SETLT: return "setlt"; + case ISD::SETLE: return "setle"; + case ISD::SETNE: return "setne"; + } + } +} + +const char *SDNode::getIndexedModeName(ISD::MemIndexedMode AM) { + switch (AM) { + default: + return ""; + case ISD::PRE_INC: + return ""; + case ISD::PRE_DEC: + return ""; + case ISD::POST_INC: + return ""; + case ISD::POST_DEC: + return ""; + } +} + +std::string ISD::ArgFlagsTy::getArgFlagsString() { + std::string S = "< "; + + if (isZExt()) + S += "zext "; + if (isSExt()) + S += "sext "; + if (isInReg()) + S += "inreg "; + if (isSRet()) + S += "sret "; + if (isByVal()) + S += "byval "; + if (isNest()) + S += "nest "; + if (getByValAlign()) + S += "byval-align:" + utostr(getByValAlign()) + " "; + if (getOrigAlign()) + S += "orig-align:" + utostr(getOrigAlign()) + " "; + if (getByValSize()) + S += "byval-size:" + utostr(getByValSize()) + " "; + return S + ">"; +} + +void SDNode::dump() const { dump(0); } +void SDNode::dump(const SelectionDAG *G) const { + print(dbgs(), G); + dbgs() << '\n'; +} + +void SDNode::print_types(raw_ostream &OS, const SelectionDAG *G) const { + OS << (void*)this << ": "; + + for (unsigned i = 0, e = getNumValues(); i != e; ++i) { + if (i) OS << ","; + if (getValueType(i) == MVT::Other) + OS << "ch"; + else + OS << getValueType(i).getEVTString(); + } + OS << " = " << getOperationName(G); +} + +void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { + if (const MachineSDNode *MN = dyn_cast(this)) { + if (!MN->memoperands_empty()) { + OS << "<"; + OS << "Mem:"; + for (MachineSDNode::mmo_iterator i = MN->memoperands_begin(), + e = MN->memoperands_end(); i != e; ++i) { + OS << **i; + if (llvm::next(i) != e) + OS << " "; + } + OS << ">"; + } + } else if (const ShuffleVectorSDNode *SVN = + dyn_cast(this)) { + OS << "<"; + for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { + int Idx = SVN->getMaskElt(i); + if (i) OS << ","; + if (Idx < 0) + OS << "u"; + else + OS << Idx; + } + OS << ">"; + } else if (const ConstantSDNode *CSDN = dyn_cast(this)) { + OS << '<' << CSDN->getAPIntValue() << '>'; + } else if (const ConstantFPSDNode *CSDN = dyn_cast(this)) { + if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) + OS << '<' << CSDN->getValueAPF().convertToFloat() << '>'; + else if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEdouble) + OS << '<' << CSDN->getValueAPF().convertToDouble() << '>'; + else { + OS << "getValueAPF().bitcastToAPInt().dump(); + OS << ")>"; + } + } else if (const GlobalAddressSDNode *GADN = + dyn_cast(this)) { + int64_t offset = GADN->getOffset(); + OS << '<'; + WriteAsOperand(OS, GADN->getGlobal()); + OS << '>'; + if (offset > 0) + OS << " + " << offset; + else + OS << " " << offset; + if (unsigned int TF = GADN->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const FrameIndexSDNode *FIDN = dyn_cast(this)) { + OS << "<" << FIDN->getIndex() << ">"; + } else if (const JumpTableSDNode *JTDN = dyn_cast(this)) { + OS << "<" << JTDN->getIndex() << ">"; + if (unsigned int TF = JTDN->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const ConstantPoolSDNode *CP = dyn_cast(this)){ + int offset = CP->getOffset(); + if (CP->isMachineConstantPoolEntry()) + OS << "<" << *CP->getMachineCPVal() << ">"; + else + OS << "<" << *CP->getConstVal() << ">"; + if (offset > 0) + OS << " + " << offset; + else + OS << " " << offset; + if (unsigned int TF = CP->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const BasicBlockSDNode *BBDN = dyn_cast(this)) { + OS << "<"; + const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock(); + if (LBB) + OS << LBB->getName() << " "; + OS << (const void*)BBDN->getBasicBlock() << ">"; + } else if (const RegisterSDNode *R = dyn_cast(this)) { + OS << ' ' << PrintReg(R->getReg(), G ? G->getTarget().getRegisterInfo() :0); + } else if (const ExternalSymbolSDNode *ES = + dyn_cast(this)) { + OS << "'" << ES->getSymbol() << "'"; + if (unsigned int TF = ES->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } else if (const SrcValueSDNode *M = dyn_cast(this)) { + if (M->getValue()) + OS << "<" << M->getValue() << ">"; + else + OS << ""; + } else if (const MDNodeSDNode *MD = dyn_cast(this)) { + if (MD->getMD()) + OS << "<" << MD->getMD() << ">"; + else + OS << ""; + } else if (const VTSDNode *N = dyn_cast(this)) { + OS << ":" << N->getVT().getEVTString(); + } + else if (const LoadSDNode *LD = dyn_cast(this)) { + OS << "<" << *LD->getMemOperand(); + + bool doExt = true; + switch (LD->getExtensionType()) { + default: doExt = false; break; + case ISD::EXTLOAD: OS << ", anyext"; break; + case ISD::SEXTLOAD: OS << ", sext"; break; + case ISD::ZEXTLOAD: OS << ", zext"; break; + } + if (doExt) + OS << " from " << LD->getMemoryVT().getEVTString(); + + const char *AM = getIndexedModeName(LD->getAddressingMode()); + if (*AM) + OS << ", " << AM; + + OS << ">"; + } else if (const StoreSDNode *ST = dyn_cast(this)) { + OS << "<" << *ST->getMemOperand(); + + if (ST->isTruncatingStore()) + OS << ", trunc to " << ST->getMemoryVT().getEVTString(); + + const char *AM = getIndexedModeName(ST->getAddressingMode()); + if (*AM) + OS << ", " << AM; + + OS << ">"; + } else if (const MemSDNode* M = dyn_cast(this)) { + OS << "<" << *M->getMemOperand() << ">"; + } else if (const BlockAddressSDNode *BA = + dyn_cast(this)) { + OS << "<"; + WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); + OS << ", "; + WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); + OS << ">"; + if (unsigned int TF = BA->getTargetFlags()) + OS << " [TF=" << TF << ']'; + } + + if (G) + if (unsigned Order = G->GetOrdering(this)) + OS << " [ORD=" << Order << ']'; + + if (getNodeId() != -1) + OS << " [ID=" << getNodeId() << ']'; + + DebugLoc dl = getDebugLoc(); + if (G && !dl.isUnknown()) { + DIScope + Scope(dl.getScope(G->getMachineFunction().getFunction()->getContext())); + OS << " dbg:"; + // Omit the directory, since it's usually long and uninteresting. + if (Scope.Verify()) + OS << Scope.getFilename(); + else + OS << ""; + OS << ':' << dl.getLine(); + if (dl.getCol() != 0) + OS << ':' << dl.getCol(); + } +} + +void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const { + print_types(OS, G); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + if (i) OS << ", "; else OS << " "; + OS << (void*)getOperand(i).getNode(); + if (unsigned RN = getOperand(i).getResNo()) + OS << ":" << RN; + } + print_details(OS, G); +} + +static void printrWithDepthHelper(raw_ostream &OS, const SDNode *N, + const SelectionDAG *G, unsigned depth, + unsigned indent) +{ + if (depth == 0) + return; + + OS.indent(indent); + + N->print(OS, G); + + if (depth < 1) + return; + + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + // Don't follow chain operands. + if (N->getOperand(i).getValueType() == MVT::Other) + continue; + OS << '\n'; + printrWithDepthHelper(OS, N->getOperand(i).getNode(), G, depth-1, indent+2); + } +} + +void SDNode::printrWithDepth(raw_ostream &OS, const SelectionDAG *G, + unsigned depth) const { + printrWithDepthHelper(OS, this, G, depth, 0); +} + +void SDNode::printrFull(raw_ostream &OS, const SelectionDAG *G) const { + // Don't print impossibly deep things. + printrWithDepth(OS, G, 10); +} + +void SDNode::dumprWithDepth(const SelectionDAG *G, unsigned depth) const { + printrWithDepth(dbgs(), G, depth); +} + +void SDNode::dumprFull(const SelectionDAG *G) const { + // Don't print impossibly deep things. + dumprWithDepth(G, 10); +} + +static void DumpNodes(const SDNode *N, unsigned indent, const SelectionDAG *G) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i).getNode()->hasOneUse()) + DumpNodes(N->getOperand(i).getNode(), indent+2, G); + else + dbgs() << "\n" << std::string(indent+2, ' ') + << (void*)N->getOperand(i).getNode() << ": "; + + + dbgs() << "\n"; + dbgs().indent(indent); + N->dump(G); +} + +SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) { + assert(N->getNumValues() == 1 && + "Can't unroll a vector with multiple results!"); + + EVT VT = N->getValueType(0); + unsigned NE = VT.getVectorNumElements(); + EVT EltVT = VT.getVectorElementType(); + DebugLoc dl = N->getDebugLoc(); + + SmallVector Scalars; + SmallVector Operands(N->getNumOperands()); + + // If ResNE is 0, fully unroll the vector op. + if (ResNE == 0) + ResNE = NE; + else if (NE > ResNE) + NE = ResNE; + + unsigned i; + for (i= 0; i != NE; ++i) { + for (unsigned j = 0, e = N->getNumOperands(); j != e; ++j) { + SDValue Operand = N->getOperand(j); + EVT OperandVT = Operand.getValueType(); + if (OperandVT.isVector()) { + // A vector operand; extract a single element. + EVT OperandEltVT = OperandVT.getVectorElementType(); + Operands[j] = getNode(ISD::EXTRACT_VECTOR_ELT, dl, + OperandEltVT, + Operand, + getConstant(i, MVT::i32)); + } else { + // A scalar operand; just use it as is. + Operands[j] = Operand; + } + } + + switch (N->getOpcode()) { + default: + Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, + &Operands[0], Operands.size())); + break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: + Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, Operands[0], + getShiftAmountOperand(Operands[0].getValueType(), + Operands[1]))); + break; + case ISD::SIGN_EXTEND_INREG: + case ISD::FP_ROUND_INREG: { + EVT ExtVT = cast(Operands[1])->getVT().getVectorElementType(); + Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, + Operands[0], + getValueType(ExtVT))); + } + } + } + + for (; i < ResNE; ++i) + Scalars.push_back(getUNDEF(EltVT)); + + return getNode(ISD::BUILD_VECTOR, dl, + EVT::getVectorVT(*getContext(), EltVT, ResNE), + &Scalars[0], Scalars.size()); +} + + +/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a +/// location that is 'Dist' units away from the location that the 'Base' load +/// is loading from. +bool SelectionDAG::isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, + unsigned Bytes, int Dist) const { + if (LD->getChain() != Base->getChain()) + return false; + EVT VT = LD->getValueType(0); + if (VT.getSizeInBits() / 8 != Bytes) + return false; + + SDValue Loc = LD->getOperand(1); + SDValue BaseLoc = Base->getOperand(1); + if (Loc.getOpcode() == ISD::FrameIndex) { + if (BaseLoc.getOpcode() != ISD::FrameIndex) + return false; + const MachineFrameInfo *MFI = getMachineFunction().getFrameInfo(); + int FI = cast(Loc)->getIndex(); + int BFI = cast(BaseLoc)->getIndex(); + int FS = MFI->getObjectSize(FI); + int BFS = MFI->getObjectSize(BFI); + if (FS != BFS || FS != (int)Bytes) return false; + return MFI->getObjectOffset(FI) == (MFI->getObjectOffset(BFI) + Dist*Bytes); + } + + // Handle X+C + if (isBaseWithConstantOffset(Loc) && Loc.getOperand(0) == BaseLoc && + cast(Loc.getOperand(1))->getSExtValue() == Dist*Bytes) + return true; + + const GlobalValue *GV1 = NULL; + const GlobalValue *GV2 = NULL; + int64_t Offset1 = 0; + int64_t Offset2 = 0; + bool isGA1 = TLI.isGAPlusOffset(Loc.getNode(), GV1, Offset1); + bool isGA2 = TLI.isGAPlusOffset(BaseLoc.getNode(), GV2, Offset2); + if (isGA1 && isGA2 && GV1 == GV2) + return Offset1 == (Offset2 + Dist*Bytes); + return false; +} + + +/// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if +/// it cannot be inferred. +unsigned SelectionDAG::InferPtrAlignment(SDValue Ptr) const { + // If this is a GlobalAddress + cst, return the alignment. + const GlobalValue *GV; + int64_t GVOffset = 0; + if (TLI.isGAPlusOffset(Ptr.getNode(), GV, GVOffset)) { + // If GV has specified alignment, then use it. Otherwise, use the preferred + // alignment. + unsigned Align = GV->getAlignment(); + if (!Align) { + if (const GlobalVariable *GVar = dyn_cast(GV)) { + if (GVar->hasInitializer()) { + const TargetData *TD = TLI.getTargetData(); + Align = TD->getPreferredAlignment(GVar); + } + } + } + return MinAlign(Align, GVOffset); + } + + // If this is a direct reference to a stack slot, use information about the + // stack slot's alignment. + int FrameIdx = 1 << 31; + int64_t FrameOffset = 0; + if (FrameIndexSDNode *FI = dyn_cast(Ptr)) { + FrameIdx = FI->getIndex(); + } else if (isBaseWithConstantOffset(Ptr) && + isa(Ptr.getOperand(0))) { + // Handle FI+Cst + FrameIdx = cast(Ptr.getOperand(0))->getIndex(); + FrameOffset = Ptr.getConstantOperandVal(1); + } + + if (FrameIdx != (1 << 31)) { + const MachineFrameInfo &MFI = *getMachineFunction().getFrameInfo(); + unsigned FIInfoAlign = MinAlign(MFI.getObjectAlignment(FrameIdx), + FrameOffset); + return FIInfoAlign; + } + + return 0; +} + +void SelectionDAG::dump() const { + dbgs() << "SelectionDAG has " << AllNodes.size() << " nodes:"; + + for (allnodes_const_iterator I = allnodes_begin(), E = allnodes_end(); + I != E; ++I) { + const SDNode *N = I; + if (!N->hasOneUse() && N != getRoot().getNode()) + DumpNodes(N, 2, this); + } + + if (getRoot().getNode()) DumpNodes(getRoot().getNode(), 2, this); + + dbgs() << "\n\n"; +} + +void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const { + print_types(OS, G); + print_details(OS, G); +} + +typedef SmallPtrSet VisitedSDNodeSet; +static void DumpNodesr(raw_ostream &OS, const SDNode *N, unsigned indent, + const SelectionDAG *G, VisitedSDNodeSet &once) { + if (!once.insert(N)) // If we've been here before, return now. + return; + + // Dump the current SDNode, but don't end the line yet. + OS << std::string(indent, ' '); + N->printr(OS, G); + + // Having printed this SDNode, walk the children: + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDNode *child = N->getOperand(i).getNode(); + + if (i) OS << ","; + OS << " "; + + if (child->getNumOperands() == 0) { + // This child has no grandchildren; print it inline right here. + child->printr(OS, G); + once.insert(child); + } else { // Just the address. FIXME: also print the child's opcode. + OS << (void*)child; + if (unsigned RN = N->getOperand(i).getResNo()) + OS << ":" << RN; + } + } + + OS << "\n"; + + // Dump children that have grandchildren on their own line(s). + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + const SDNode *child = N->getOperand(i).getNode(); + DumpNodesr(OS, child, indent+2, G, once); + } +} + +void SDNode::dumpr() const { + VisitedSDNodeSet once; + DumpNodesr(dbgs(), this, 0, 0, once); +} + +void SDNode::dumpr(const SelectionDAG *G) const { + VisitedSDNodeSet once; + DumpNodesr(dbgs(), this, 0, G, once); +} + + +// getAddressSpace - Return the address space this GlobalAddress belongs to. +unsigned GlobalAddressSDNode::getAddressSpace() const { + return getGlobal()->getType()->getAddressSpace(); +} + + +const Type *ConstantPoolSDNode::getType() const { + if (isMachineConstantPoolEntry()) + return Val.MachineCPVal->getType(); + return Val.ConstVal->getType(); +} + +bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, + APInt &SplatUndef, + unsigned &SplatBitSize, + bool &HasAnyUndefs, + unsigned MinSplatBits, + bool isBigEndian) { + EVT VT = getValueType(0); + assert(VT.isVector() && "Expected a vector type"); + unsigned sz = VT.getSizeInBits(); + if (MinSplatBits > sz) + return false; + + SplatValue = APInt(sz, 0); + SplatUndef = APInt(sz, 0); + + // Get the bits. Bits with undefined values (when the corresponding element + // of the vector is an ISD::UNDEF value) are set in SplatUndef and cleared + // in SplatValue. If any of the values are not constant, give up and return + // false. + unsigned int nOps = getNumOperands(); + assert(nOps > 0 && "isConstantSplat has 0-size build vector"); + unsigned EltBitSize = VT.getVectorElementType().getSizeInBits(); + + for (unsigned j = 0; j < nOps; ++j) { + unsigned i = isBigEndian ? nOps-1-j : j; + SDValue OpVal = getOperand(i); + unsigned BitPos = j * EltBitSize; + + if (OpVal.getOpcode() == ISD::UNDEF) + SplatUndef |= APInt::getBitsSet(sz, BitPos, BitPos + EltBitSize); + else if (ConstantSDNode *CN = dyn_cast(OpVal)) + SplatValue |= CN->getAPIntValue().zextOrTrunc(EltBitSize). + zextOrTrunc(sz) << BitPos; + else if (ConstantFPSDNode *CN = dyn_cast(OpVal)) + SplatValue |= CN->getValueAPF().bitcastToAPInt().zextOrTrunc(sz) < 8) { + + unsigned HalfSize = sz / 2; + APInt HighValue = SplatValue.lshr(HalfSize).trunc(HalfSize); + APInt LowValue = SplatValue.trunc(HalfSize); + APInt HighUndef = SplatUndef.lshr(HalfSize).trunc(HalfSize); + APInt LowUndef = SplatUndef.trunc(HalfSize); + + // If the two halves do not match (ignoring undef bits), stop here. + if ((HighValue & ~LowUndef) != (LowValue & ~HighUndef) || + MinSplatBits > HalfSize) + break; + + SplatValue = HighValue | LowValue; + SplatUndef = HighUndef & LowUndef; + + sz = HalfSize; + } + + SplatBitSize = sz; + return true; +} + +bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) { + // Find the first non-undef value in the shuffle mask. + unsigned i, e; + for (i = 0, e = VT.getVectorNumElements(); i != e && Mask[i] < 0; ++i) + /* search */; + + assert(i != e && "VECTOR_SHUFFLE node with all undef indices!"); + + // Make sure all remaining elements are either undef or the same as the first + // non-undef value. + for (int Idx = Mask[i]; i != e; ++i) + if (Mask[i] >= 0 && Mask[i] != Idx) + return false; + return true; +} + +#ifdef XDEBUG +static void checkForCyclesHelper(const SDNode *N, + SmallPtrSet &Visited, + SmallPtrSet &Checked) { + // If this node has already been checked, don't check it again. + if (Checked.count(N)) + return; + + // If a node has already been visited on this depth-first walk, reject it as + // a cycle. + if (!Visited.insert(N)) { + dbgs() << "Offending node:\n"; + N->dumprFull(); + errs() << "Detected cycle in SelectionDAG\n"; + abort(); + } + + for(unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + checkForCyclesHelper(N->getOperand(i).getNode(), Visited, Checked); + + Checked.insert(N); + Visited.erase(N); +} +#endif + +void llvm::checkForCycles(const llvm::SDNode *N) { +#ifdef XDEBUG + assert(N && "Checking nonexistant SDNode"); + SmallPtrSet visited; + SmallPtrSet checked; + checkForCyclesHelper(N, visited, checked); +#endif +} + +void llvm::checkForCycles(const llvm::SelectionDAG *DAG) { + checkForCycles(DAG->getRoot().getNode()); +} diff --git a/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp new file mode 100644 index 00000000000..48d9bbb5132 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -0,0 +1,6484 @@ +//===-- SelectionDAGBuilder.cpp - Selection-DAG building ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating from LLVM IR into SelectionDAG IR. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "isel" +#include "SDNodeDbgValue.h" +#include "SelectionDAGBuilder.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Constants.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +/// LimitFloatPrecision - Generate low-precision inline sequences for +/// some float libcalls (6, 8 or 12 bits). +static unsigned LimitFloatPrecision; + +static cl::opt +LimitFPPrecision("limit-float-precision", + cl::desc("Generate low-precision inline sequences " + "for some float libcalls"), + cl::location(LimitFloatPrecision), + cl::init(0)); + +// Limit the width of DAG chains. This is important in general to prevent +// prevent DAG-based analysis from blowing up. For example, alias analysis and +// load clustering may not complete in reasonable time. It is difficult to +// recognize and avoid this situation within each individual analysis, and +// future analyses are likely to have the same behavior. Limiting DAG width is +// the safe approach, and will be especially important with global DAGs. +// +// MaxParallelChains default is arbitrarily high to avoid affecting +// optimization, but could be lowered to improve compile time. Any ld-ld-st-st +// sequence over this should have been converted to llvm.memcpy by the +// frontend. It easy to induce this behavior with .ll code such as: +// %buffer = alloca [4096 x i8] +// %data = load [4096 x i8]* %argPtr +// store [4096 x i8] %data, [4096 x i8]* %buffer +static cl::opt +MaxParallelChains("dag-chain-limit", cl::desc("Max parallel isel dag chains"), + cl::init(64), cl::Hidden); + +static SDValue getCopyFromPartsVector(SelectionDAG &DAG, DebugLoc DL, + const SDValue *Parts, unsigned NumParts, + EVT PartVT, EVT ValueVT); + +/// getCopyFromParts - Create a value that contains the specified legal parts +/// combined into the value they represent. If the parts combine to a type +/// larger then ValueVT then AssertOp can be used to specify whether the extra +/// bits are known to be zero (ISD::AssertZext) or sign extended from ValueVT +/// (ISD::AssertSext). +static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc DL, + const SDValue *Parts, + unsigned NumParts, EVT PartVT, EVT ValueVT, + ISD::NodeType AssertOp = ISD::DELETED_NODE) { + if (ValueVT.isVector()) + return getCopyFromPartsVector(DAG, DL, Parts, NumParts, PartVT, ValueVT); + + assert(NumParts > 0 && "No parts to assemble!"); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue Val = Parts[0]; + + if (NumParts > 1) { + // Assemble the value from multiple parts. + if (ValueVT.isInteger()) { + unsigned PartBits = PartVT.getSizeInBits(); + unsigned ValueBits = ValueVT.getSizeInBits(); + + // Assemble the power of 2 part. + unsigned RoundParts = NumParts & (NumParts - 1) ? + 1 << Log2_32(NumParts) : NumParts; + unsigned RoundBits = PartBits * RoundParts; + EVT RoundVT = RoundBits == ValueBits ? + ValueVT : EVT::getIntegerVT(*DAG.getContext(), RoundBits); + SDValue Lo, Hi; + + EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), RoundBits/2); + + if (RoundParts > 2) { + Lo = getCopyFromParts(DAG, DL, Parts, RoundParts / 2, + PartVT, HalfVT); + Hi = getCopyFromParts(DAG, DL, Parts + RoundParts / 2, + RoundParts / 2, PartVT, HalfVT); + } else { + Lo = DAG.getNode(ISD::BITCAST, DL, HalfVT, Parts[0]); + Hi = DAG.getNode(ISD::BITCAST, DL, HalfVT, Parts[1]); + } + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + Val = DAG.getNode(ISD::BUILD_PAIR, DL, RoundVT, Lo, Hi); + + if (RoundParts < NumParts) { + // Assemble the trailing non-power-of-2 part. + unsigned OddParts = NumParts - RoundParts; + EVT OddVT = EVT::getIntegerVT(*DAG.getContext(), OddParts * PartBits); + Hi = getCopyFromParts(DAG, DL, + Parts + RoundParts, OddParts, PartVT, OddVT); + + // Combine the round and odd parts. + Lo = Val; + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + EVT TotalVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Hi = DAG.getNode(ISD::ANY_EXTEND, DL, TotalVT, Hi); + Hi = DAG.getNode(ISD::SHL, DL, TotalVT, Hi, + DAG.getConstant(Lo.getValueType().getSizeInBits(), + TLI.getPointerTy())); + Lo = DAG.getNode(ISD::ZERO_EXTEND, DL, TotalVT, Lo); + Val = DAG.getNode(ISD::OR, DL, TotalVT, Lo, Hi); + } + } else if (PartVT.isFloatingPoint()) { + // FP split into multiple FP parts (for ppcf128) + assert(ValueVT == EVT(MVT::ppcf128) && PartVT == EVT(MVT::f64) && + "Unexpected split"); + SDValue Lo, Hi; + Lo = DAG.getNode(ISD::BITCAST, DL, EVT(MVT::f64), Parts[0]); + Hi = DAG.getNode(ISD::BITCAST, DL, EVT(MVT::f64), Parts[1]); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Val = DAG.getNode(ISD::BUILD_PAIR, DL, ValueVT, Lo, Hi); + } else { + // FP split into integer parts (soft fp) + assert(ValueVT.isFloatingPoint() && PartVT.isInteger() && + !PartVT.isVector() && "Unexpected split"); + EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), ValueVT.getSizeInBits()); + Val = getCopyFromParts(DAG, DL, Parts, NumParts, PartVT, IntVT); + } + } + + // There is now one part, held in Val. Correct it to match ValueVT. + PartVT = Val.getValueType(); + + if (PartVT == ValueVT) + return Val; + + if (PartVT.isInteger() && ValueVT.isInteger()) { + if (ValueVT.bitsLT(PartVT)) { + // For a truncate, see if we have any information to + // indicate whether the truncated bits will always be + // zero or sign-extension. + if (AssertOp != ISD::DELETED_NODE) + Val = DAG.getNode(AssertOp, DL, PartVT, Val, + DAG.getValueType(ValueVT)); + return DAG.getNode(ISD::TRUNCATE, DL, ValueVT, Val); + } + return DAG.getNode(ISD::ANY_EXTEND, DL, ValueVT, Val); + } + + if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) { + // FP_ROUND's are always exact here. + if (ValueVT.bitsLT(Val.getValueType())) + return DAG.getNode(ISD::FP_ROUND, DL, ValueVT, Val, + DAG.getIntPtrConstant(1)); + + return DAG.getNode(ISD::FP_EXTEND, DL, ValueVT, Val); + } + + if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) + return DAG.getNode(ISD::BITCAST, DL, ValueVT, Val); + + llvm_unreachable("Unknown mismatch!"); + return SDValue(); +} + +/// getCopyFromParts - Create a value that contains the specified legal parts +/// combined into the value they represent. If the parts combine to a type +/// larger then ValueVT then AssertOp can be used to specify whether the extra +/// bits are known to be zero (ISD::AssertZext) or sign extended from ValueVT +/// (ISD::AssertSext). +static SDValue getCopyFromPartsVector(SelectionDAG &DAG, DebugLoc DL, + const SDValue *Parts, unsigned NumParts, + EVT PartVT, EVT ValueVT) { + assert(ValueVT.isVector() && "Not a vector value"); + assert(NumParts > 0 && "No parts to assemble!"); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + SDValue Val = Parts[0]; + + // Handle a multi-element vector. + if (NumParts > 1) { + EVT IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = + TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, IntermediateVT, + NumIntermediates, RegisterVT); + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + NumParts = NumRegs; // Silence a compiler warning. + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + assert(RegisterVT == Parts[0].getValueType() && + "Part type doesn't match part!"); + + // Assemble the parts into intermediate operands. + SmallVector Ops(NumIntermediates); + if (NumIntermediates == NumParts) { + // If the register was not expanded, truncate or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + Ops[i] = getCopyFromParts(DAG, DL, &Parts[i], 1, + PartVT, IntermediateVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, build the intermediate + // operands from the parts. + assert(NumParts % NumIntermediates == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumParts / NumIntermediates; + for (unsigned i = 0; i != NumIntermediates; ++i) + Ops[i] = getCopyFromParts(DAG, DL, &Parts[i * Factor], Factor, + PartVT, IntermediateVT); + } + + // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the + // intermediate operands. + Val = DAG.getNode(IntermediateVT.isVector() ? + ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR, DL, + ValueVT, &Ops[0], NumIntermediates); + } + + // There is now one part, held in Val. Correct it to match ValueVT. + PartVT = Val.getValueType(); + + if (PartVT == ValueVT) + return Val; + + if (PartVT.isVector()) { + // If the element type of the source/dest vectors are the same, but the + // parts vector has more elements than the value vector, then we have a + // vector widening case (e.g. <2 x float> -> <4 x float>). Extract the + // elements we want. + if (PartVT.getVectorElementType() == ValueVT.getVectorElementType()) { + assert(PartVT.getVectorNumElements() > ValueVT.getVectorNumElements() && + "Cannot narrow, it would be a lossy transformation"); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ValueVT, Val, + DAG.getIntPtrConstant(0)); + } + + // Vector/Vector bitcast. + return DAG.getNode(ISD::BITCAST, DL, ValueVT, Val); + } + + assert(ValueVT.getVectorElementType() == PartVT && + ValueVT.getVectorNumElements() == 1 && + "Only trivial scalar-to-vector conversions should get here!"); + return DAG.getNode(ISD::BUILD_VECTOR, DL, ValueVT, Val); +} + + + + +static void getCopyToPartsVector(SelectionDAG &DAG, DebugLoc dl, + SDValue Val, SDValue *Parts, unsigned NumParts, + EVT PartVT); + +/// getCopyToParts - Create a series of nodes that contain the specified value +/// split into legal parts. If the parts contain more bits than Val, then, for +/// integers, ExtendKind can be used to specify how to generate the extra bits. +static void getCopyToParts(SelectionDAG &DAG, DebugLoc DL, + SDValue Val, SDValue *Parts, unsigned NumParts, + EVT PartVT, + ISD::NodeType ExtendKind = ISD::ANY_EXTEND) { + EVT ValueVT = Val.getValueType(); + + // Handle the vector case separately. + if (ValueVT.isVector()) + return getCopyToPartsVector(DAG, DL, Val, Parts, NumParts, PartVT); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned PartBits = PartVT.getSizeInBits(); + unsigned OrigNumParts = NumParts; + assert(TLI.isTypeLegal(PartVT) && "Copying to an illegal type!"); + + if (NumParts == 0) + return; + + assert(!ValueVT.isVector() && "Vector case handled elsewhere"); + if (PartVT == ValueVT) { + assert(NumParts == 1 && "No-op copy with multiple parts!"); + Parts[0] = Val; + return; + } + + if (NumParts * PartBits > ValueVT.getSizeInBits()) { + // If the parts cover more bits than the value has, promote the value. + if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) { + assert(NumParts == 1 && "Do not know what to promote to!"); + Val = DAG.getNode(ISD::FP_EXTEND, DL, PartVT, Val); + } else { + assert(PartVT.isInteger() && ValueVT.isInteger() && + "Unknown mismatch!"); + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ExtendKind, DL, ValueVT, Val); + } + } else if (PartBits == ValueVT.getSizeInBits()) { + // Different types of the same size. + assert(NumParts == 1 && PartVT != ValueVT); + Val = DAG.getNode(ISD::BITCAST, DL, PartVT, Val); + } else if (NumParts * PartBits < ValueVT.getSizeInBits()) { + // If the parts cover less bits than value has, truncate the value. + assert(PartVT.isInteger() && ValueVT.isInteger() && + "Unknown mismatch!"); + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValueVT, Val); + } + + // The value may have changed - recompute ValueVT. + ValueVT = Val.getValueType(); + assert(NumParts * PartBits == ValueVT.getSizeInBits() && + "Failed to tile the value with PartVT!"); + + if (NumParts == 1) { + assert(PartVT == ValueVT && "Type conversion failed!"); + Parts[0] = Val; + return; + } + + // Expand the value into multiple parts. + if (NumParts & (NumParts - 1)) { + // The number of parts is not a power of 2. Split off and copy the tail. + assert(PartVT.isInteger() && ValueVT.isInteger() && + "Do not know what to expand to!"); + unsigned RoundParts = 1 << Log2_32(NumParts); + unsigned RoundBits = RoundParts * PartBits; + unsigned OddParts = NumParts - RoundParts; + SDValue OddVal = DAG.getNode(ISD::SRL, DL, ValueVT, Val, + DAG.getIntPtrConstant(RoundBits)); + getCopyToParts(DAG, DL, OddVal, Parts + RoundParts, OddParts, PartVT); + + if (TLI.isBigEndian()) + // The odd parts were reversed by getCopyToParts - unreverse them. + std::reverse(Parts + RoundParts, Parts + NumParts); + + NumParts = RoundParts; + ValueVT = EVT::getIntegerVT(*DAG.getContext(), NumParts * PartBits); + Val = DAG.getNode(ISD::TRUNCATE, DL, ValueVT, Val); + } + + // The number of parts is a power of 2. Repeatedly bisect the value using + // EXTRACT_ELEMENT. + Parts[0] = DAG.getNode(ISD::BITCAST, DL, + EVT::getIntegerVT(*DAG.getContext(), + ValueVT.getSizeInBits()), + Val); + + for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) { + for (unsigned i = 0; i < NumParts; i += StepSize) { + unsigned ThisBits = StepSize * PartBits / 2; + EVT ThisVT = EVT::getIntegerVT(*DAG.getContext(), ThisBits); + SDValue &Part0 = Parts[i]; + SDValue &Part1 = Parts[i+StepSize/2]; + + Part1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, + ThisVT, Part0, DAG.getIntPtrConstant(1)); + Part0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, + ThisVT, Part0, DAG.getIntPtrConstant(0)); + + if (ThisBits == PartBits && ThisVT != PartVT) { + Part0 = DAG.getNode(ISD::BITCAST, DL, PartVT, Part0); + Part1 = DAG.getNode(ISD::BITCAST, DL, PartVT, Part1); + } + } + } + + if (TLI.isBigEndian()) + std::reverse(Parts, Parts + OrigNumParts); +} + + +/// getCopyToPartsVector - Create a series of nodes that contain the specified +/// value split into legal parts. +static void getCopyToPartsVector(SelectionDAG &DAG, DebugLoc DL, + SDValue Val, SDValue *Parts, unsigned NumParts, + EVT PartVT) { + EVT ValueVT = Val.getValueType(); + assert(ValueVT.isVector() && "Not a vector"); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + if (NumParts == 1) { + if (PartVT == ValueVT) { + // Nothing to do. + } else if (PartVT.getSizeInBits() == ValueVT.getSizeInBits()) { + // Bitconvert vector->vector case. + Val = DAG.getNode(ISD::BITCAST, DL, PartVT, Val); + } else if (PartVT.isVector() && + PartVT.getVectorElementType() == ValueVT.getVectorElementType()&& + PartVT.getVectorNumElements() > ValueVT.getVectorNumElements()) { + EVT ElementVT = PartVT.getVectorElementType(); + // Vector widening case, e.g. <2 x float> -> <4 x float>. Shuffle in + // undef elements. + SmallVector Ops; + for (unsigned i = 0, e = ValueVT.getVectorNumElements(); i != e; ++i) + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, + ElementVT, Val, DAG.getIntPtrConstant(i))); + + for (unsigned i = ValueVT.getVectorNumElements(), + e = PartVT.getVectorNumElements(); i != e; ++i) + Ops.push_back(DAG.getUNDEF(ElementVT)); + + Val = DAG.getNode(ISD::BUILD_VECTOR, DL, PartVT, &Ops[0], Ops.size()); + + // FIXME: Use CONCAT for 2x -> 4x. + + //SDValue UndefElts = DAG.getUNDEF(VectorTy); + //Val = DAG.getNode(ISD::CONCAT_VECTORS, DL, PartVT, Val, UndefElts); + } else { + // Vector -> scalar conversion. + assert(ValueVT.getVectorElementType() == PartVT && + ValueVT.getVectorNumElements() == 1 && + "Only trivial vector-to-scalar conversions should get here!"); + Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, + PartVT, Val, DAG.getIntPtrConstant(0)); + } + + Parts[0] = Val; + return; + } + + // Handle a multi-element vector. + EVT IntermediateVT, RegisterVT; + unsigned NumIntermediates; + unsigned NumRegs = TLI.getVectorTypeBreakdown(*DAG.getContext(), ValueVT, + IntermediateVT, + NumIntermediates, RegisterVT); + unsigned NumElements = ValueVT.getVectorNumElements(); + + assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!"); + NumParts = NumRegs; // Silence a compiler warning. + assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!"); + + // Split the vector into intermediate operands. + SmallVector Ops(NumIntermediates); + for (unsigned i = 0; i != NumIntermediates; ++i) { + if (IntermediateVT.isVector()) + Ops[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, + IntermediateVT, Val, + DAG.getIntPtrConstant(i * (NumElements / NumIntermediates))); + else + Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, + IntermediateVT, Val, DAG.getIntPtrConstant(i)); + } + + // Split the intermediate operands into legal parts. + if (NumParts == NumIntermediates) { + // If the register was not expanded, promote or copy the value, + // as appropriate. + for (unsigned i = 0; i != NumParts; ++i) + getCopyToParts(DAG, DL, Ops[i], &Parts[i], 1, PartVT); + } else if (NumParts > 0) { + // If the intermediate type was expanded, split each the value into + // legal parts. + assert(NumParts % NumIntermediates == 0 && + "Must expand into a divisible number of parts!"); + unsigned Factor = NumParts / NumIntermediates; + for (unsigned i = 0; i != NumIntermediates; ++i) + getCopyToParts(DAG, DL, Ops[i], &Parts[i*Factor], Factor, PartVT); + } +} + + + + +namespace { + /// RegsForValue - This struct represents the registers (physical or virtual) + /// that a particular set of values is assigned, and the type information + /// about the value. The most common situation is to represent one value at a + /// time, but struct or array values are handled element-wise as multiple + /// values. The splitting of aggregates is performed recursively, so that we + /// never have aggregate-typed registers. The values at this point do not + /// necessarily have legal types, so each value may require one or more + /// registers of some legal type. + /// + struct RegsForValue { + /// ValueVTs - The value types of the values, which may not be legal, and + /// may need be promoted or synthesized from one or more registers. + /// + SmallVector ValueVTs; + + /// RegVTs - The value types of the registers. This is the same size as + /// ValueVTs and it records, for each value, what the type of the assigned + /// register or registers are. (Individual values are never synthesized + /// from more than one type of register.) + /// + /// With virtual registers, the contents of RegVTs is redundant with TLI's + /// getRegisterType member function, however when with physical registers + /// it is necessary to have a separate record of the types. + /// + SmallVector RegVTs; + + /// Regs - This list holds the registers assigned to the values. + /// Each legal or promoted value requires one register, and each + /// expanded value requires multiple registers. + /// + SmallVector Regs; + + RegsForValue() {} + + RegsForValue(const SmallVector ®s, + EVT regvt, EVT valuevt) + : ValueVTs(1, valuevt), RegVTs(1, regvt), Regs(regs) {} + + RegsForValue(LLVMContext &Context, const TargetLowering &tli, + unsigned Reg, const Type *Ty) { + ComputeValueVTs(tli, Ty, ValueVTs); + + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + unsigned NumRegs = tli.getNumRegisters(Context, ValueVT); + EVT RegisterVT = tli.getRegisterType(Context, ValueVT); + for (unsigned i = 0; i != NumRegs; ++i) + Regs.push_back(Reg + i); + RegVTs.push_back(RegisterVT); + Reg += NumRegs; + } + } + + /// areValueTypesLegal - Return true if types of all the values are legal. + bool areValueTypesLegal(const TargetLowering &TLI) { + for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT RegisterVT = RegVTs[Value]; + if (!TLI.isTypeLegal(RegisterVT)) + return false; + } + return true; + } + + /// append - Add the specified values to this one. + void append(const RegsForValue &RHS) { + ValueVTs.append(RHS.ValueVTs.begin(), RHS.ValueVTs.end()); + RegVTs.append(RHS.RegVTs.begin(), RHS.RegVTs.end()); + Regs.append(RHS.Regs.begin(), RHS.Regs.end()); + } + + /// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from + /// this value and returns the result as a ValueVTs value. This uses + /// Chain/Flag as the input and updates them for the output Chain/Flag. + /// If the Flag pointer is NULL, no flag is used. + SDValue getCopyFromRegs(SelectionDAG &DAG, FunctionLoweringInfo &FuncInfo, + DebugLoc dl, + SDValue &Chain, SDValue *Flag) const; + + /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the + /// specified value into the registers specified by this object. This uses + /// Chain/Flag as the input and updates them for the output Chain/Flag. + /// If the Flag pointer is NULL, no flag is used. + void getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, SDValue *Flag) const; + + /// AddInlineAsmOperands - Add this value to the specified inlineasm node + /// operand list. This adds the code marker, matching input operand index + /// (if applicable), and includes the number of values added into it. + void AddInlineAsmOperands(unsigned Kind, + bool HasMatching, unsigned MatchingIdx, + SelectionDAG &DAG, + std::vector &Ops) const; + }; +} + +/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from +/// this value and returns the result as a ValueVT value. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +/// If the Flag pointer is NULL, no flag is used. +SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, + FunctionLoweringInfo &FuncInfo, + DebugLoc dl, + SDValue &Chain, SDValue *Flag) const { + // A Value with type {} or [0 x %t] needs no registers. + if (ValueVTs.empty()) + return SDValue(); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Assemble the legal parts into the final values. + SmallVector Values(ValueVTs.size()); + SmallVector Parts; + for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) { + // Copy the legal parts from the registers. + EVT ValueVT = ValueVTs[Value]; + unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), ValueVT); + EVT RegisterVT = RegVTs[Value]; + + Parts.resize(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { + SDValue P; + if (Flag == 0) { + P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT); + } else { + P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT, *Flag); + *Flag = P.getValue(2); + } + + Chain = P.getValue(1); + Parts[i] = P; + + // If the source register was virtual and if we know something about it, + // add an assert node. + if (!TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) || + !RegisterVT.isInteger() || RegisterVT.isVector()) + continue; + + const FunctionLoweringInfo::LiveOutInfo *LOI = + FuncInfo.GetLiveOutRegInfo(Regs[Part+i]); + if (!LOI) + continue; + + unsigned RegSize = RegisterVT.getSizeInBits(); + unsigned NumSignBits = LOI->NumSignBits; + unsigned NumZeroBits = LOI->KnownZero.countLeadingOnes(); + + // FIXME: We capture more information than the dag can represent. For + // now, just use the tightest assertzext/assertsext possible. + bool isSExt = true; + EVT FromVT(MVT::Other); + if (NumSignBits == RegSize) + isSExt = true, FromVT = MVT::i1; // ASSERT SEXT 1 + else if (NumZeroBits >= RegSize-1) + isSExt = false, FromVT = MVT::i1; // ASSERT ZEXT 1 + else if (NumSignBits > RegSize-8) + isSExt = true, FromVT = MVT::i8; // ASSERT SEXT 8 + else if (NumZeroBits >= RegSize-8) + isSExt = false, FromVT = MVT::i8; // ASSERT ZEXT 8 + else if (NumSignBits > RegSize-16) + isSExt = true, FromVT = MVT::i16; // ASSERT SEXT 16 + else if (NumZeroBits >= RegSize-16) + isSExt = false, FromVT = MVT::i16; // ASSERT ZEXT 16 + else if (NumSignBits > RegSize-32) + isSExt = true, FromVT = MVT::i32; // ASSERT SEXT 32 + else if (NumZeroBits >= RegSize-32) + isSExt = false, FromVT = MVT::i32; // ASSERT ZEXT 32 + else + continue; + + // Add an assertion node. + assert(FromVT != MVT::Other); + Parts[i] = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, dl, + RegisterVT, P, DAG.getValueType(FromVT)); + } + + Values[Value] = getCopyFromParts(DAG, dl, Parts.begin(), + NumRegs, RegisterVT, ValueVT); + Part += NumRegs; + Parts.clear(); + } + + return DAG.getNode(ISD::MERGE_VALUES, dl, + DAG.getVTList(&ValueVTs[0], ValueVTs.size()), + &Values[0], ValueVTs.size()); +} + +/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the +/// specified value into the registers specified by this object. This uses +/// Chain/Flag as the input and updates them for the output Chain/Flag. +/// If the Flag pointer is NULL, no flag is used. +void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, + SDValue &Chain, SDValue *Flag) const { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + // Get the list of the values's legal parts. + unsigned NumRegs = Regs.size(); + SmallVector Parts(NumRegs); + for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) { + EVT ValueVT = ValueVTs[Value]; + unsigned NumParts = TLI.getNumRegisters(*DAG.getContext(), ValueVT); + EVT RegisterVT = RegVTs[Value]; + + getCopyToParts(DAG, dl, Val.getValue(Val.getResNo() + Value), + &Parts[Part], NumParts, RegisterVT); + Part += NumParts; + } + + // Copy the parts into the registers. + SmallVector Chains(NumRegs); + for (unsigned i = 0; i != NumRegs; ++i) { + SDValue Part; + if (Flag == 0) { + Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i]); + } else { + Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i], *Flag); + *Flag = Part.getValue(1); + } + + Chains[i] = Part.getValue(0); + } + + if (NumRegs == 1 || Flag) + // If NumRegs > 1 && Flag is used then the use of the last CopyToReg is + // flagged to it. That is the CopyToReg nodes and the user are considered + // a single scheduling unit. If we create a TokenFactor and return it as + // chain, then the TokenFactor is both a predecessor (operand) of the + // user as well as a successor (the TF operands are flagged to the user). + // c1, f1 = CopyToReg + // c2, f2 = CopyToReg + // c3 = TokenFactor c1, c2 + // ... + // = op c3, ..., f2 + Chain = Chains[NumRegs-1]; + else + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], NumRegs); +} + +/// AddInlineAsmOperands - Add this value to the specified inlineasm node +/// operand list. This adds the code marker and includes the number of +/// values added into it. +void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching, + unsigned MatchingIdx, + SelectionDAG &DAG, + std::vector &Ops) const { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + unsigned Flag = InlineAsm::getFlagWord(Code, Regs.size()); + if (HasMatching) + Flag = InlineAsm::getFlagWordForMatchingOp(Flag, MatchingIdx); + SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); + Ops.push_back(Res); + + for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { + unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), ValueVTs[Value]); + EVT RegisterVT = RegVTs[Value]; + for (unsigned i = 0; i != NumRegs; ++i) { + assert(Reg < Regs.size() && "Mismatch in # registers expected"); + Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT)); + } + } +} + +void SelectionDAGBuilder::init(GCFunctionInfo *gfi, AliasAnalysis &aa) { + AA = &aa; + GFI = gfi; + TD = DAG.getTarget().getTargetData(); +} + +/// clear - Clear out the current SelectionDAG and the associated +/// state and prepare this SelectionDAGBuilder object to be used +/// for a new block. This doesn't clear out information about +/// additional blocks that are needed to complete switch lowering +/// or PHI node updating; that information is cleared out as it is +/// consumed. +void SelectionDAGBuilder::clear() { + NodeMap.clear(); + UnusedArgNodeMap.clear(); + PendingLoads.clear(); + PendingExports.clear(); + DanglingDebugInfoMap.clear(); + CurDebugLoc = DebugLoc(); + HasTailCall = false; +} + +/// getRoot - Return the current virtual root of the Selection DAG, +/// flushing any PendingLoad items. This must be done before emitting +/// a store or any other node that may need to be ordered after any +/// prior load instructions. +/// +SDValue SelectionDAGBuilder::getRoot() { + if (PendingLoads.empty()) + return DAG.getRoot(); + + if (PendingLoads.size() == 1) { + SDValue Root = PendingLoads[0]; + DAG.setRoot(Root); + PendingLoads.clear(); + return Root; + } + + // Otherwise, we have to make a token factor node. + SDValue Root = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &PendingLoads[0], PendingLoads.size()); + PendingLoads.clear(); + DAG.setRoot(Root); + return Root; +} + +/// getControlRoot - Similar to getRoot, but instead of flushing all the +/// PendingLoad items, flush all the PendingExports items. It is necessary +/// to do this before emitting a terminator instruction. +/// +SDValue SelectionDAGBuilder::getControlRoot() { + SDValue Root = DAG.getRoot(); + + if (PendingExports.empty()) + return Root; + + // Turn all of the CopyToReg chains into one factored node. + if (Root.getOpcode() != ISD::EntryToken) { + unsigned i = 0, e = PendingExports.size(); + for (; i != e; ++i) { + assert(PendingExports[i].getNode()->getNumOperands() > 1); + if (PendingExports[i].getNode()->getOperand(0) == Root) + break; // Don't add the root if we already indirectly depend on it. + } + + if (i == e) + PendingExports.push_back(Root); + } + + Root = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &PendingExports[0], + PendingExports.size()); + PendingExports.clear(); + DAG.setRoot(Root); + return Root; +} + +void SelectionDAGBuilder::AssignOrderingToNode(const SDNode *Node) { + if (DAG.GetOrdering(Node) != 0) return; // Already has ordering. + DAG.AssignOrdering(Node, SDNodeOrder); + + for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) + AssignOrderingToNode(Node->getOperand(I).getNode()); +} + +void SelectionDAGBuilder::visit(const Instruction &I) { + // Set up outgoing PHI node register values before emitting the terminator. + if (isa(&I)) + HandlePHINodesInSuccessorBlocks(I.getParent()); + + CurDebugLoc = I.getDebugLoc(); + + visit(I.getOpcode(), I); + + if (!isa(&I) && !HasTailCall) + CopyToExportRegsIfNeeded(&I); + + CurDebugLoc = DebugLoc(); +} + +void SelectionDAGBuilder::visitPHI(const PHINode &) { + llvm_unreachable("SelectionDAGBuilder shouldn't visit PHI nodes!"); +} + +void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) { + // Note: this doesn't use InstVisitor, because it has to work with + // ConstantExpr's in addition to instructions. + switch (Opcode) { + default: llvm_unreachable("Unknown instruction type encountered!"); + // Build the switch statement using the Instruction.def file. +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: visit##OPCODE((CLASS&)I); break; +#include "llvm/Instruction.def" + } + + // Assign the ordering to the freshly created DAG nodes. + if (NodeMap.count(&I)) { + ++SDNodeOrder; + AssignOrderingToNode(getValue(&I).getNode()); + } +} + +// resolveDanglingDebugInfo - if we saw an earlier dbg_value referring to V, +// generate the debug data structures now that we've seen its definition. +void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V, + SDValue Val) { + DanglingDebugInfo &DDI = DanglingDebugInfoMap[V]; + if (DDI.getDI()) { + const DbgValueInst *DI = DDI.getDI(); + DebugLoc dl = DDI.getdl(); + unsigned DbgSDNodeOrder = DDI.getSDNodeOrder(); + MDNode *Variable = DI->getVariable(); + uint64_t Offset = DI->getOffset(); + SDDbgValue *SDV; + if (Val.getNode()) { + if (!EmitFuncArgumentDbgValue(V, Variable, Offset, Val)) { + SDV = DAG.getDbgValue(Variable, Val.getNode(), + Val.getResNo(), Offset, dl, DbgSDNodeOrder); + DAG.AddDbgValue(SDV, Val.getNode(), false); + } + } else + DEBUG(dbgs() << "Dropping debug info for " << DI); + DanglingDebugInfoMap[V] = DanglingDebugInfo(); + } +} + +// getValue - Return an SDValue for the given Value. +SDValue SelectionDAGBuilder::getValue(const Value *V) { + // If we already have an SDValue for this value, use it. It's important + // to do this first, so that we don't create a CopyFromReg if we already + // have a regular SDValue. + SDValue &N = NodeMap[V]; + if (N.getNode()) return N; + + // If there's a virtual register allocated and initialized for this + // value, use it. + DenseMap::iterator It = FuncInfo.ValueMap.find(V); + if (It != FuncInfo.ValueMap.end()) { + unsigned InReg = It->second; + RegsForValue RFV(*DAG.getContext(), TLI, InReg, V->getType()); + SDValue Chain = DAG.getEntryNode(); + N = RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain,NULL); + resolveDanglingDebugInfo(V, N); + return N; + } + + // Otherwise create a new SDValue and remember it. + SDValue Val = getValueImpl(V); + NodeMap[V] = Val; + resolveDanglingDebugInfo(V, Val); + return Val; +} + +/// getNonRegisterValue - Return an SDValue for the given Value, but +/// don't look in FuncInfo.ValueMap for a virtual register. +SDValue SelectionDAGBuilder::getNonRegisterValue(const Value *V) { + // If we already have an SDValue for this value, use it. + SDValue &N = NodeMap[V]; + if (N.getNode()) return N; + + // Otherwise create a new SDValue and remember it. + SDValue Val = getValueImpl(V); + NodeMap[V] = Val; + resolveDanglingDebugInfo(V, Val); + return Val; +} + +/// getValueImpl - Helper function for getValue and getNonRegisterValue. +/// Create an SDValue for the given value. +SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { + if (const Constant *C = dyn_cast(V)) { + EVT VT = TLI.getValueType(V->getType(), true); + + if (const ConstantInt *CI = dyn_cast(C)) + return DAG.getConstant(*CI, VT); + + if (const GlobalValue *GV = dyn_cast(C)) + return DAG.getGlobalAddress(GV, getCurDebugLoc(), VT); + + if (isa(C)) + return DAG.getConstant(0, TLI.getPointerTy()); + + if (const ConstantFP *CFP = dyn_cast(C)) + return DAG.getConstantFP(*CFP, VT); + + if (isa(C) && !V->getType()->isAggregateType()) + return DAG.getUNDEF(VT); + + if (const ConstantExpr *CE = dyn_cast(C)) { + visit(CE->getOpcode(), *CE); + SDValue N1 = NodeMap[V]; + assert(N1.getNode() && "visit didn't populate the NodeMap!"); + return N1; + } + + if (isa(C) || isa(C)) { + SmallVector Constants; + for (User::const_op_iterator OI = C->op_begin(), OE = C->op_end(); + OI != OE; ++OI) { + SDNode *Val = getValue(*OI).getNode(); + // If the operand is an empty aggregate, there are no values. + if (!Val) continue; + // Add each leaf value from the operand to the Constants list + // to form a flattened list of all the values. + for (unsigned i = 0, e = Val->getNumValues(); i != e; ++i) + Constants.push_back(SDValue(Val, i)); + } + + return DAG.getMergeValues(&Constants[0], Constants.size(), + getCurDebugLoc()); + } + + if (C->getType()->isStructTy() || C->getType()->isArrayTy()) { + assert((isa(C) || isa(C)) && + "Unknown struct or array constant!"); + + SmallVector ValueVTs; + ComputeValueVTs(TLI, C->getType(), ValueVTs); + unsigned NumElts = ValueVTs.size(); + if (NumElts == 0) + return SDValue(); // empty struct + SmallVector Constants(NumElts); + for (unsigned i = 0; i != NumElts; ++i) { + EVT EltVT = ValueVTs[i]; + if (isa(C)) + Constants[i] = DAG.getUNDEF(EltVT); + else if (EltVT.isFloatingPoint()) + Constants[i] = DAG.getConstantFP(0, EltVT); + else + Constants[i] = DAG.getConstant(0, EltVT); + } + + return DAG.getMergeValues(&Constants[0], NumElts, + getCurDebugLoc()); + } + + if (const BlockAddress *BA = dyn_cast(C)) + return DAG.getBlockAddress(BA, VT); + + const VectorType *VecTy = cast(V->getType()); + unsigned NumElements = VecTy->getNumElements(); + + // Now that we know the number and type of the elements, get that number of + // elements into the Ops array based on what kind of constant it is. + SmallVector Ops; + if (const ConstantVector *CP = dyn_cast(C)) { + for (unsigned i = 0; i != NumElements; ++i) + Ops.push_back(getValue(CP->getOperand(i))); + } else { + assert(isa(C) && "Unknown vector constant!"); + EVT EltVT = TLI.getValueType(VecTy->getElementType()); + + SDValue Op; + if (EltVT.isFloatingPoint()) + Op = DAG.getConstantFP(0, EltVT); + else + Op = DAG.getConstant(0, EltVT); + Ops.assign(NumElements, Op); + } + + // Create a BUILD_VECTOR node. + return NodeMap[V] = DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size()); + } + + // If this is a static alloca, generate it as the frameindex instead of + // computation. + if (const AllocaInst *AI = dyn_cast(V)) { + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) + return DAG.getFrameIndex(SI->second, TLI.getPointerTy()); + } + + // If this is an instruction which fast-isel has deferred, select it now. + if (const Instruction *Inst = dyn_cast(V)) { + unsigned InReg = FuncInfo.InitializeRegForValue(Inst); + RegsForValue RFV(*DAG.getContext(), TLI, InReg, Inst->getType()); + SDValue Chain = DAG.getEntryNode(); + return RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain, NULL); + } + + llvm_unreachable("Can't get register for value!"); + return SDValue(); +} + +void SelectionDAGBuilder::visitRet(const ReturnInst &I) { + SDValue Chain = getControlRoot(); + SmallVector Outs; + SmallVector OutVals; + + if (!FuncInfo.CanLowerReturn) { + unsigned DemoteReg = FuncInfo.DemoteRegister; + const Function *F = I.getParent()->getParent(); + + // Emit a store of the return value through the virtual register. + // Leave Outs empty so that LowerReturn won't try to load return + // registers the usual way. + SmallVector PtrValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F->getReturnType()), + PtrValueVTs); + + SDValue RetPtr = DAG.getRegister(DemoteReg, PtrValueVTs[0]); + SDValue RetOp = getValue(I.getOperand(0)); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, I.getOperand(0)->getType(), ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + + SmallVector Chains(NumValues); + for (unsigned i = 0; i != NumValues; ++i) { + SDValue Add = DAG.getNode(ISD::ADD, getCurDebugLoc(), + RetPtr.getValueType(), RetPtr, + DAG.getIntPtrConstant(Offsets[i])); + Chains[i] = + DAG.getStore(Chain, getCurDebugLoc(), + SDValue(RetOp.getNode(), RetOp.getResNo() + i), + // FIXME: better loc info would be nice. + Add, MachinePointerInfo(), false, false, 0); + } + + Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues); + } else if (I.getNumOperands() != 0) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getOperand(0)->getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues) { + SDValue RetOp = getValue(I.getOperand(0)); + for (unsigned j = 0, f = NumValues; j != f; ++j) { + EVT VT = ValueVTs[j]; + + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + const Function *F = I.getParent()->getParent(); + if (F->paramHasAttr(0, Attribute::SExt)) + ExtendKind = ISD::SIGN_EXTEND; + else if (F->paramHasAttr(0, Attribute::ZExt)) + ExtendKind = ISD::ZERO_EXTEND; + + // FIXME: C calling convention requires the return type to be promoted + // to at least 32-bit. But this is not necessary for non-C calling + // conventions. The frontend should mark functions whose return values + // require promoting with signext or zeroext attributes. + if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { + EVT MinVT = TLI.getRegisterType(*DAG.getContext(), MVT::i32); + if (VT.bitsLT(MinVT)) + VT = MinVT; + } + + unsigned NumParts = TLI.getNumRegisters(*DAG.getContext(), VT); + EVT PartVT = TLI.getRegisterType(*DAG.getContext(), VT); + SmallVector Parts(NumParts); + getCopyToParts(DAG, getCurDebugLoc(), + SDValue(RetOp.getNode(), RetOp.getResNo() + j), + &Parts[0], NumParts, PartVT, ExtendKind); + + // 'inreg' on function refers to return value + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (F->paramHasAttr(0, Attribute::InReg)) + Flags.setInReg(); + + // Propagate extension type if any + if (F->paramHasAttr(0, Attribute::SExt)) + Flags.setSExt(); + else if (F->paramHasAttr(0, Attribute::ZExt)) + Flags.setZExt(); + + for (unsigned i = 0; i < NumParts; ++i) { + Outs.push_back(ISD::OutputArg(Flags, Parts[i].getValueType(), + /*isfixed=*/true)); + OutVals.push_back(Parts[i]); + } + } + } + } + + bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); + CallingConv::ID CallConv = + DAG.getMachineFunction().getFunction()->getCallingConv(); + Chain = TLI.LowerReturn(Chain, CallConv, isVarArg, + Outs, OutVals, getCurDebugLoc(), DAG); + + // Verify that the target's LowerReturn behaved as expected. + assert(Chain.getNode() && Chain.getValueType() == MVT::Other && + "LowerReturn didn't return a valid chain!"); + + // Update the DAG with the new chain value resulting from return lowering. + DAG.setRoot(Chain); +} + +/// CopyToExportRegsIfNeeded - If the given value has virtual registers +/// created for it, emit nodes to copy the value into the virtual +/// registers. +void SelectionDAGBuilder::CopyToExportRegsIfNeeded(const Value *V) { + DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); + if (VMI != FuncInfo.ValueMap.end()) { + assert(!V->use_empty() && "Unused value assigned virtual registers!"); + CopyValueToVirtualRegister(V, VMI->second); + } +} + +/// ExportFromCurrentBlock - If this condition isn't known to be exported from +/// the current basic block, add it to ValueMap now so that we'll get a +/// CopyTo/FromReg. +void SelectionDAGBuilder::ExportFromCurrentBlock(const Value *V) { + // No need to export constants. + if (!isa(V) && !isa(V)) return; + + // Already exported? + if (FuncInfo.isExportedInst(V)) return; + + unsigned Reg = FuncInfo.InitializeRegForValue(V); + CopyValueToVirtualRegister(V, Reg); +} + +bool SelectionDAGBuilder::isExportableFromCurrentBlock(const Value *V, + const BasicBlock *FromBB) { + // The operands of the setcc have to be in this block. We don't know + // how to export them from some other block. + if (const Instruction *VI = dyn_cast(V)) { + // Can export from current BB. + if (VI->getParent() == FromBB) + return true; + + // Is already exported, noop. + return FuncInfo.isExportedInst(V); + } + + // If this is an argument, we can export it if the BB is the entry block or + // if it is already exported. + if (isa(V)) { + if (FromBB == &FromBB->getParent()->getEntryBlock()) + return true; + + // Otherwise, can only export this if it is already exported. + return FuncInfo.isExportedInst(V); + } + + // Otherwise, constants can always be exported. + return true; +} + +static bool InBlock(const Value *V, const BasicBlock *BB) { + if (const Instruction *I = dyn_cast(V)) + return I->getParent() == BB; + return true; +} + +/// EmitBranchForMergedCondition - Helper method for FindMergedConditions. +/// This function emits a branch and is used at the leaves of an OR or an +/// AND operator tree. +/// +void +SelectionDAGBuilder::EmitBranchForMergedCondition(const Value *Cond, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB) { + const BasicBlock *BB = CurBB->getBasicBlock(); + + // If the leaf of the tree is a comparison, merge the condition into + // the caseblock. + if (const CmpInst *BOp = dyn_cast(Cond)) { + // The operands of the cmp have to be in this block. We don't know + // how to export them from some other block. If this is the first block + // of the sequence, no exporting is needed. + if (CurBB == SwitchBB || + (isExportableFromCurrentBlock(BOp->getOperand(0), BB) && + isExportableFromCurrentBlock(BOp->getOperand(1), BB))) { + ISD::CondCode Condition; + if (const ICmpInst *IC = dyn_cast(Cond)) { + Condition = getICmpCondCode(IC->getPredicate()); + } else if (const FCmpInst *FC = dyn_cast(Cond)) { + Condition = getFCmpCondCode(FC->getPredicate()); + } else { + Condition = ISD::SETEQ; // silence warning. + llvm_unreachable("Unknown compare instruction"); + } + + CaseBlock CB(Condition, BOp->getOperand(0), + BOp->getOperand(1), NULL, TBB, FBB, CurBB); + SwitchCases.push_back(CB); + return; + } + } + + // Create a CaseBlock record representing this branch. + CaseBlock CB(ISD::SETEQ, Cond, ConstantInt::getTrue(*DAG.getContext()), + NULL, TBB, FBB, CurBB); + SwitchCases.push_back(CB); +} + +/// FindMergedConditions - If Cond is an expression like +void SelectionDAGBuilder::FindMergedConditions(const Value *Cond, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB, + unsigned Opc) { + // If this node is not part of the or/and tree, emit it as a branch. + const Instruction *BOp = dyn_cast(Cond); + if (!BOp || !(isa(BOp) || isa(BOp)) || + (unsigned)BOp->getOpcode() != Opc || !BOp->hasOneUse() || + BOp->getParent() != CurBB->getBasicBlock() || + !InBlock(BOp->getOperand(0), CurBB->getBasicBlock()) || + !InBlock(BOp->getOperand(1), CurBB->getBasicBlock())) { + EmitBranchForMergedCondition(Cond, TBB, FBB, CurBB, SwitchBB); + return; + } + + // Create TmpBB after CurBB. + MachineFunction::iterator BBI = CurBB; + MachineFunction &MF = DAG.getMachineFunction(); + MachineBasicBlock *TmpBB = MF.CreateMachineBasicBlock(CurBB->getBasicBlock()); + CurBB->getParent()->insert(++BBI, TmpBB); + + if (Opc == Instruction::Or) { + // Codegen X | Y as: + // jmp_if_X TBB + // jmp TmpBB + // TmpBB: + // jmp_if_Y TBB + // jmp FBB + // + + // Emit the LHS condition. + FindMergedConditions(BOp->getOperand(0), TBB, TmpBB, CurBB, SwitchBB, Opc); + + // Emit the RHS condition into TmpBB. + FindMergedConditions(BOp->getOperand(1), TBB, FBB, TmpBB, SwitchBB, Opc); + } else { + assert(Opc == Instruction::And && "Unknown merge op!"); + // Codegen X & Y as: + // jmp_if_X TmpBB + // jmp FBB + // TmpBB: + // jmp_if_Y TBB + // jmp FBB + // + // This requires creation of TmpBB after CurBB. + + // Emit the LHS condition. + FindMergedConditions(BOp->getOperand(0), TmpBB, FBB, CurBB, SwitchBB, Opc); + + // Emit the RHS condition into TmpBB. + FindMergedConditions(BOp->getOperand(1), TBB, FBB, TmpBB, SwitchBB, Opc); + } +} + +/// If the set of cases should be emitted as a series of branches, return true. +/// If we should emit this as a bunch of and/or'd together conditions, return +/// false. +bool +SelectionDAGBuilder::ShouldEmitAsBranches(const std::vector &Cases){ + if (Cases.size() != 2) return true; + + // If this is two comparisons of the same values or'd or and'd together, they + // will get folded into a single comparison, so don't emit two blocks. + if ((Cases[0].CmpLHS == Cases[1].CmpLHS && + Cases[0].CmpRHS == Cases[1].CmpRHS) || + (Cases[0].CmpRHS == Cases[1].CmpLHS && + Cases[0].CmpLHS == Cases[1].CmpRHS)) { + return false; + } + + // Handle: (X != null) | (Y != null) --> (X|Y) != 0 + // Handle: (X == null) & (Y == null) --> (X|Y) == 0 + if (Cases[0].CmpRHS == Cases[1].CmpRHS && + Cases[0].CC == Cases[1].CC && + isa(Cases[0].CmpRHS) && + cast(Cases[0].CmpRHS)->isNullValue()) { + if (Cases[0].CC == ISD::SETEQ && Cases[0].TrueBB == Cases[1].ThisBB) + return false; + if (Cases[0].CC == ISD::SETNE && Cases[0].FalseBB == Cases[1].ThisBB) + return false; + } + + return true; +} + +void SelectionDAGBuilder::visitBr(const BranchInst &I) { + MachineBasicBlock *BrMBB = FuncInfo.MBB; + + // Update machine-CFG edges. + MachineBasicBlock *Succ0MBB = FuncInfo.MBBMap[I.getSuccessor(0)]; + + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = BrMBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + if (I.isUnconditional()) { + // Update machine-CFG edges. + BrMBB->addSuccessor(Succ0MBB); + + // If this is not a fall-through branch, emit the branch. + if (Succ0MBB != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Succ0MBB))); + + return; + } + + // If this condition is one of the special cases we handle, do special stuff + // now. + const Value *CondVal = I.getCondition(); + MachineBasicBlock *Succ1MBB = FuncInfo.MBBMap[I.getSuccessor(1)]; + + // If this is a series of conditions that are or'd or and'd together, emit + // this as a sequence of branches instead of setcc's with and/or operations. + // As long as jumps are not expensive, this should improve performance. + // For example, instead of something like: + // cmp A, B + // C = seteq + // cmp D, E + // F = setle + // or C, F + // jnz foo + // Emit: + // cmp A, B + // je foo + // cmp D, E + // jle foo + // + if (const BinaryOperator *BOp = dyn_cast(CondVal)) { + if (!TLI.isJumpExpensive() && + BOp->hasOneUse() && + (BOp->getOpcode() == Instruction::And || + BOp->getOpcode() == Instruction::Or)) { + FindMergedConditions(BOp, Succ0MBB, Succ1MBB, BrMBB, BrMBB, + BOp->getOpcode()); + // If the compares in later blocks need to use values not currently + // exported from this block, export them now. This block should always + // be the first entry. + assert(SwitchCases[0].ThisBB == BrMBB && "Unexpected lowering!"); + + // Allow some cases to be rejected. + if (ShouldEmitAsBranches(SwitchCases)) { + for (unsigned i = 1, e = SwitchCases.size(); i != e; ++i) { + ExportFromCurrentBlock(SwitchCases[i].CmpLHS); + ExportFromCurrentBlock(SwitchCases[i].CmpRHS); + } + + // Emit the branch for this block. + visitSwitchCase(SwitchCases[0], BrMBB); + SwitchCases.erase(SwitchCases.begin()); + return; + } + + // Okay, we decided not to do this, remove any inserted MBB's and clear + // SwitchCases. + for (unsigned i = 1, e = SwitchCases.size(); i != e; ++i) + FuncInfo.MF->erase(SwitchCases[i].ThisBB); + + SwitchCases.clear(); + } + } + + // Create a CaseBlock record representing this branch. + CaseBlock CB(ISD::SETEQ, CondVal, ConstantInt::getTrue(*DAG.getContext()), + NULL, Succ0MBB, Succ1MBB, BrMBB); + + // Use visitSwitchCase to actually insert the fast branch sequence for this + // cond branch. + visitSwitchCase(CB, BrMBB); +} + +/// visitSwitchCase - Emits the necessary code to represent a single node in +/// the binary search tree resulting from lowering a switch instruction. +void SelectionDAGBuilder::visitSwitchCase(CaseBlock &CB, + MachineBasicBlock *SwitchBB) { + SDValue Cond; + SDValue CondLHS = getValue(CB.CmpLHS); + DebugLoc dl = getCurDebugLoc(); + + // Build the setcc now. + if (CB.CmpMHS == NULL) { + // Fold "(X == true)" to X and "(X == false)" to !X to + // handle common cases produced by branch lowering. + if (CB.CmpRHS == ConstantInt::getTrue(*DAG.getContext()) && + CB.CC == ISD::SETEQ) + Cond = CondLHS; + else if (CB.CmpRHS == ConstantInt::getFalse(*DAG.getContext()) && + CB.CC == ISD::SETEQ) { + SDValue True = DAG.getConstant(1, CondLHS.getValueType()); + Cond = DAG.getNode(ISD::XOR, dl, CondLHS.getValueType(), CondLHS, True); + } else + Cond = DAG.getSetCC(dl, MVT::i1, CondLHS, getValue(CB.CmpRHS), CB.CC); + } else { + assert(CB.CC == ISD::SETLE && "Can handle only LE ranges now"); + + const APInt& Low = cast(CB.CmpLHS)->getValue(); + const APInt& High = cast(CB.CmpRHS)->getValue(); + + SDValue CmpOp = getValue(CB.CmpMHS); + EVT VT = CmpOp.getValueType(); + + if (cast(CB.CmpLHS)->isMinValue(true)) { + Cond = DAG.getSetCC(dl, MVT::i1, CmpOp, DAG.getConstant(High, VT), + ISD::SETLE); + } else { + SDValue SUB = DAG.getNode(ISD::SUB, dl, + VT, CmpOp, DAG.getConstant(Low, VT)); + Cond = DAG.getSetCC(dl, MVT::i1, SUB, + DAG.getConstant(High-Low, VT), ISD::SETULE); + } + } + + // Update successor info + SwitchBB->addSuccessor(CB.TrueBB); + SwitchBB->addSuccessor(CB.FalseBB); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = SwitchBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + // If the lhs block is the next block, invert the condition so that we can + // fall through to the lhs instead of the rhs block. + if (CB.TrueBB == NextBlock) { + std::swap(CB.TrueBB, CB.FalseBB); + SDValue True = DAG.getConstant(1, Cond.getValueType()); + Cond = DAG.getNode(ISD::XOR, dl, Cond.getValueType(), Cond, True); + } + + SDValue BrCond = DAG.getNode(ISD::BRCOND, dl, + MVT::Other, getControlRoot(), Cond, + DAG.getBasicBlock(CB.TrueBB)); + + // Insert the false branch. Do this even if it's a fall through branch, + // this makes it easier to do DAG optimizations which require inverting + // the branch condition. + BrCond = DAG.getNode(ISD::BR, dl, MVT::Other, BrCond, + DAG.getBasicBlock(CB.FalseBB)); + + DAG.setRoot(BrCond); +} + +/// visitJumpTable - Emit JumpTable node in the current MBB +void SelectionDAGBuilder::visitJumpTable(JumpTable &JT) { + // Emit the code for the jump table + assert(JT.Reg != -1U && "Should lower JT Header first!"); + EVT PTy = TLI.getPointerTy(); + SDValue Index = DAG.getCopyFromReg(getControlRoot(), getCurDebugLoc(), + JT.Reg, PTy); + SDValue Table = DAG.getJumpTable(JT.JTI, PTy); + SDValue BrJumpTable = DAG.getNode(ISD::BR_JT, getCurDebugLoc(), + MVT::Other, Index.getValue(1), + Table, Index); + DAG.setRoot(BrJumpTable); +} + +/// visitJumpTableHeader - This function emits necessary code to produce index +/// in the JumpTable from switch case. +void SelectionDAGBuilder::visitJumpTableHeader(JumpTable &JT, + JumpTableHeader &JTH, + MachineBasicBlock *SwitchBB) { + // Subtract the lowest switch case value from the value being switched on and + // conditional branch to default mbb if the result is greater than the + // difference between smallest and largest cases. + SDValue SwitchOp = getValue(JTH.SValue); + EVT VT = SwitchOp.getValueType(); + SDValue Sub = DAG.getNode(ISD::SUB, getCurDebugLoc(), VT, SwitchOp, + DAG.getConstant(JTH.First, VT)); + + // The SDNode we just created, which holds the value being switched on minus + // the smallest case value, needs to be copied to a virtual register so it + // can be used as an index into the jump table in a subsequent basic block. + // This value may be smaller or larger than the target's pointer type, and + // therefore require extension or truncating. + SwitchOp = DAG.getZExtOrTrunc(Sub, getCurDebugLoc(), TLI.getPointerTy()); + + unsigned JumpTableReg = FuncInfo.CreateReg(TLI.getPointerTy()); + SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), + JumpTableReg, SwitchOp); + JT.Reg = JumpTableReg; + + // Emit the range check for the jump table, and branch to the default block + // for the switch statement if the value being switched on exceeds the largest + // case in the switch. + SDValue CMP = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(Sub.getValueType()), Sub, + DAG.getConstant(JTH.Last-JTH.First,VT), + ISD::SETUGT); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = SwitchBB; + + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + SDValue BrCond = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, CopyTo, CMP, + DAG.getBasicBlock(JT.Default)); + + if (JT.MBB != NextBlock) + BrCond = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrCond, + DAG.getBasicBlock(JT.MBB)); + + DAG.setRoot(BrCond); +} + +/// visitBitTestHeader - This function emits necessary code to produce value +/// suitable for "bit tests" +void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B, + MachineBasicBlock *SwitchBB) { + // Subtract the minimum value + SDValue SwitchOp = getValue(B.SValue); + EVT VT = SwitchOp.getValueType(); + SDValue Sub = DAG.getNode(ISD::SUB, getCurDebugLoc(), VT, SwitchOp, + DAG.getConstant(B.First, VT)); + + // Check range + SDValue RangeCmp = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(Sub.getValueType()), + Sub, DAG.getConstant(B.Range, VT), + ISD::SETUGT); + + // Determine the type of the test operands. + bool UsePtrType = false; + if (!TLI.isTypeLegal(VT)) + UsePtrType = true; + else { + for (unsigned i = 0, e = B.Cases.size(); i != e; ++i) + if ((uint64_t)((int64_t)B.Cases[i].Mask >> VT.getSizeInBits()) + 1 >= 2) { + // Switch table case range are encoded into series of masks. + // Just use pointer type, it's guaranteed to fit. + UsePtrType = true; + break; + } + } + if (UsePtrType) { + VT = TLI.getPointerTy(); + Sub = DAG.getZExtOrTrunc(Sub, getCurDebugLoc(), VT); + } + + B.RegVT = VT; + B.Reg = FuncInfo.CreateReg(VT); + SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), getCurDebugLoc(), + B.Reg, Sub); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = SwitchBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + MachineBasicBlock* MBB = B.Cases[0].ThisBB; + + SwitchBB->addSuccessor(B.Default); + SwitchBB->addSuccessor(MBB); + + SDValue BrRange = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, CopyTo, RangeCmp, + DAG.getBasicBlock(B.Default)); + + if (MBB != NextBlock) + BrRange = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, CopyTo, + DAG.getBasicBlock(MBB)); + + DAG.setRoot(BrRange); +} + +/// visitBitTestCase - this function produces one "bit test" +void SelectionDAGBuilder::visitBitTestCase(BitTestBlock &BB, + MachineBasicBlock* NextMBB, + unsigned Reg, + BitTestCase &B, + MachineBasicBlock *SwitchBB) { + EVT VT = BB.RegVT; + SDValue ShiftOp = DAG.getCopyFromReg(getControlRoot(), getCurDebugLoc(), + Reg, VT); + SDValue Cmp; + if (CountPopulation_64(B.Mask) == 1) { + // Testing for a single bit; just compare the shift count with what it + // would need to be to shift a 1 bit in that position. + Cmp = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(VT), + ShiftOp, + DAG.getConstant(CountTrailingZeros_64(B.Mask), VT), + ISD::SETEQ); + } else { + // Make desired shift + SDValue SwitchVal = DAG.getNode(ISD::SHL, getCurDebugLoc(), VT, + DAG.getConstant(1, VT), ShiftOp); + + // Emit bit tests and jumps + SDValue AndOp = DAG.getNode(ISD::AND, getCurDebugLoc(), + VT, SwitchVal, DAG.getConstant(B.Mask, VT)); + Cmp = DAG.getSetCC(getCurDebugLoc(), + TLI.getSetCCResultType(VT), + AndOp, DAG.getConstant(0, VT), + ISD::SETNE); + } + + SwitchBB->addSuccessor(B.TargetBB); + SwitchBB->addSuccessor(NextMBB); + + SDValue BrAnd = DAG.getNode(ISD::BRCOND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + Cmp, DAG.getBasicBlock(B.TargetBB)); + + // Set NextBlock to be the MBB immediately after the current one, if any. + // This is used to avoid emitting unnecessary branches to the next block. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = SwitchBB; + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + if (NextMBB != NextBlock) + BrAnd = DAG.getNode(ISD::BR, getCurDebugLoc(), MVT::Other, BrAnd, + DAG.getBasicBlock(NextMBB)); + + DAG.setRoot(BrAnd); +} + +void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { + MachineBasicBlock *InvokeMBB = FuncInfo.MBB; + + // Retrieve successors. + MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; + MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; + + const Value *Callee(I.getCalledValue()); + if (isa(Callee)) + visitInlineAsm(&I); + else + LowerCallTo(&I, getValue(Callee), false, LandingPad); + + // If the value of the invoke is used outside of its defining block, make it + // available as a virtual register. + CopyToExportRegsIfNeeded(&I); + + // Update successor info + InvokeMBB->addSuccessor(Return); + InvokeMBB->addSuccessor(LandingPad); + + // Drop into normal successor. + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Return))); +} + +void SelectionDAGBuilder::visitUnwind(const UnwindInst &I) { +} + +/// handleSmallSwitchCaseRange - Emit a series of specific tests (suitable for +/// small case ranges). +bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock *Default, + MachineBasicBlock *SwitchBB) { + Case& BackCase = *(CR.Range.second-1); + + // Size is the number of Cases represented by this range. + size_t Size = CR.Range.second - CR.Range.first; + if (Size > 3) + return false; + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + MachineFunction::iterator BBI = CR.CaseBB; + + if (++BBI != FuncInfo.MF->end()) + NextBlock = BBI; + + // If any two of the cases has the same destination, and if one value + // is the same as the other, but has one bit unset that the other has set, + // use bit manipulation to do two compares at once. For example: + // "if (X == 6 || X == 4)" -> "if ((X|2) == 6)" + // TODO: This could be extended to merge any 2 cases in switches with 3 cases. + // TODO: Handle cases where CR.CaseBB != SwitchBB. + if (Size == 2 && CR.CaseBB == SwitchBB) { + Case &Small = *CR.Range.first; + Case &Big = *(CR.Range.second-1); + + if (Small.Low == Small.High && Big.Low == Big.High && Small.BB == Big.BB) { + const APInt& SmallValue = cast(Small.Low)->getValue(); + const APInt& BigValue = cast(Big.Low)->getValue(); + + // Check that there is only one bit different. + if (BigValue.countPopulation() == SmallValue.countPopulation() + 1 && + (SmallValue | BigValue) == BigValue) { + // Isolate the common bit. + APInt CommonBit = BigValue & ~SmallValue; + assert((SmallValue | CommonBit) == BigValue && + CommonBit.countPopulation() == 1 && "Not a common bit?"); + + SDValue CondLHS = getValue(SV); + EVT VT = CondLHS.getValueType(); + DebugLoc DL = getCurDebugLoc(); + + SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS, + DAG.getConstant(CommonBit, VT)); + SDValue Cond = DAG.getSetCC(DL, MVT::i1, + Or, DAG.getConstant(BigValue, VT), + ISD::SETEQ); + + // Update successor info. + SwitchBB->addSuccessor(Small.BB); + SwitchBB->addSuccessor(Default); + + // Insert the true branch. + SDValue BrCond = DAG.getNode(ISD::BRCOND, DL, MVT::Other, + getControlRoot(), Cond, + DAG.getBasicBlock(Small.BB)); + + // Insert the false branch. + BrCond = DAG.getNode(ISD::BR, DL, MVT::Other, BrCond, + DAG.getBasicBlock(Default)); + + DAG.setRoot(BrCond); + return true; + } + } + } + + // Rearrange the case blocks so that the last one falls through if possible. + if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) { + // The last case block won't fall through into 'NextBlock' if we emit the + // branches in this order. See if rearranging a case value would help. + for (CaseItr I = CR.Range.first, E = CR.Range.second-1; I != E; ++I) { + if (I->BB == NextBlock) { + std::swap(*I, BackCase); + break; + } + } + } + + // Create a CaseBlock record representing a conditional branch to + // the Case's target mbb if the value being switched on SV is equal + // to C. + MachineBasicBlock *CurBlock = CR.CaseBB; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++I) { + MachineBasicBlock *FallThrough; + if (I != E-1) { + FallThrough = CurMF->CreateMachineBasicBlock(CurBlock->getBasicBlock()); + CurMF->insert(BBI, FallThrough); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } else { + // If the last case doesn't match, go to the default block. + FallThrough = Default; + } + + const Value *RHS, *LHS, *MHS; + ISD::CondCode CC; + if (I->High == I->Low) { + // This is just small small case range :) containing exactly 1 case + CC = ISD::SETEQ; + LHS = SV; RHS = I->High; MHS = NULL; + } else { + CC = ISD::SETLE; + LHS = I->Low; MHS = SV; RHS = I->High; + } + CaseBlock CB(CC, LHS, RHS, MHS, I->BB, FallThrough, CurBlock); + + // If emitting the first comparison, just call visitSwitchCase to emit the + // code into the current block. Otherwise, push the CaseBlock onto the + // vector to be later processed by SDISel, and insert the node's MBB + // before the next MBB. + if (CurBlock == SwitchBB) + visitSwitchCase(CB, SwitchBB); + else + SwitchCases.push_back(CB); + + CurBlock = FallThrough; + } + + return true; +} + +static inline bool areJTsAllowed(const TargetLowering &TLI) { + return !DisableJumpTables && + (TLI.isOperationLegalOrCustom(ISD::BR_JT, MVT::Other) || + TLI.isOperationLegalOrCustom(ISD::BRIND, MVT::Other)); +} + +static APInt ComputeRange(const APInt &First, const APInt &Last) { + uint32_t BitWidth = std::max(Last.getBitWidth(), First.getBitWidth()) + 1; + APInt LastExt = Last.sext(BitWidth), FirstExt = First.sext(BitWidth); + return (LastExt - FirstExt + 1ULL); +} + +/// handleJTSwitchCase - Emit jumptable for current switch case range +bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB) { + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + + const APInt &First = cast(FrontCase.Low)->getValue(); + const APInt &Last = cast(BackCase.High)->getValue(); + + APInt TSize(First.getBitWidth(), 0); + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) + TSize += I->size(); + + if (!areJTsAllowed(TLI) || TSize.ult(4)) + return false; + + APInt Range = ComputeRange(First, Last); + double Density = TSize.roundToDouble() / Range.roundToDouble(); + if (Density < 0.4) + return false; + + DEBUG(dbgs() << "Lowering jump table\n" + << "First entry: " << First << ". Last entry: " << Last << '\n' + << "Range: " << Range + << ". Size: " << TSize << ". Density: " << Density << "\n\n"); + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + // Create a new basic block to hold the code for loading the address + // of the jump table, and jumping to it. Update successor information; + // we will either branch to the default case for the switch, or the jump + // table. + MachineBasicBlock *JumpTableBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, JumpTableBB); + CR.CaseBB->addSuccessor(Default); + CR.CaseBB->addSuccessor(JumpTableBB); + + // Build a vector of destination BBs, corresponding to each target + // of the jump table. If the value of the jump table slot corresponds to + // a case statement, push the case's BB onto the vector, otherwise, push + // the default BB. + std::vector DestBBs; + APInt TEI = First; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I != E; ++TEI) { + const APInt &Low = cast(I->Low)->getValue(); + const APInt &High = cast(I->High)->getValue(); + + if (Low.sle(TEI) && TEI.sle(High)) { + DestBBs.push_back(I->BB); + if (TEI==High) + ++I; + } else { + DestBBs.push_back(Default); + } + } + + // Update successor info. Add one edge to each unique successor. + BitVector SuccsHandled(CR.CaseBB->getParent()->getNumBlockIDs()); + for (std::vector::iterator I = DestBBs.begin(), + E = DestBBs.end(); I != E; ++I) { + if (!SuccsHandled[(*I)->getNumber()]) { + SuccsHandled[(*I)->getNumber()] = true; + JumpTableBB->addSuccessor(*I); + } + } + + // Create a jump table index for this jump table. + unsigned JTEncoding = TLI.getJumpTableEncoding(); + unsigned JTI = CurMF->getOrCreateJumpTableInfo(JTEncoding) + ->createJumpTableIndex(DestBBs); + + // Set the jump table information so that we can codegen it as a second + // MachineBasicBlock + JumpTable JT(-1U, JTI, JumpTableBB, Default); + JumpTableHeader JTH(First, Last, SV, CR.CaseBB, (CR.CaseBB == SwitchBB)); + if (CR.CaseBB == SwitchBB) + visitJumpTableHeader(JT, JTH, SwitchBB); + + JTCases.push_back(JumpTableBlock(JTH, JT)); + + return true; +} + +/// handleBTSplitSwitchCase - emit comparison and split binary search tree into +/// 2 subtrees. +bool SelectionDAGBuilder::handleBTSplitSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock *Default, + MachineBasicBlock *SwitchBB) { + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + // Size is the number of Cases represented by this range. + unsigned Size = CR.Range.second - CR.Range.first; + + const APInt &First = cast(FrontCase.Low)->getValue(); + const APInt &Last = cast(BackCase.High)->getValue(); + double FMetric = 0; + CaseItr Pivot = CR.Range.first + Size/2; + + // Select optimal pivot, maximizing sum density of LHS and RHS. This will + // (heuristically) allow us to emit JumpTable's later. + APInt TSize(First.getBitWidth(), 0); + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) + TSize += I->size(); + + APInt LSize = FrontCase.size(); + APInt RSize = TSize-LSize; + DEBUG(dbgs() << "Selecting best pivot: \n" + << "First: " << First << ", Last: " << Last <<'\n' + << "LSize: " << LSize << ", RSize: " << RSize << '\n'); + for (CaseItr I = CR.Range.first, J=I+1, E = CR.Range.second; + J!=E; ++I, ++J) { + const APInt &LEnd = cast(I->High)->getValue(); + const APInt &RBegin = cast(J->Low)->getValue(); + APInt Range = ComputeRange(LEnd, RBegin); + assert((Range - 2ULL).isNonNegative() && + "Invalid case distance"); + double LDensity = (double)LSize.roundToDouble() / + (LEnd - First + 1ULL).roundToDouble(); + double RDensity = (double)RSize.roundToDouble() / + (Last - RBegin + 1ULL).roundToDouble(); + double Metric = Range.logBase2()*(LDensity+RDensity); + // Should always split in some non-trivial place + DEBUG(dbgs() <<"=>Step\n" + << "LEnd: " << LEnd << ", RBegin: " << RBegin << '\n' + << "LDensity: " << LDensity + << ", RDensity: " << RDensity << '\n' + << "Metric: " << Metric << '\n'); + if (FMetric < Metric) { + Pivot = J; + FMetric = Metric; + DEBUG(dbgs() << "Current metric set to: " << FMetric << '\n'); + } + + LSize += J->size(); + RSize -= J->size(); + } + if (areJTsAllowed(TLI)) { + // If our case is dense we *really* should handle it earlier! + assert((FMetric > 0) && "Should handle dense range earlier!"); + } else { + Pivot = CR.Range.first + Size/2; + } + + CaseRange LHSR(CR.Range.first, Pivot); + CaseRange RHSR(Pivot, CR.Range.second); + Constant *C = Pivot->Low; + MachineBasicBlock *FalseBB = 0, *TrueBB = 0; + + // We know that we branch to the LHS if the Value being switched on is + // less than the Pivot value, C. We use this to optimize our binary + // tree a bit, by recognizing that if SV is greater than or equal to the + // LHS's Case Value, and that Case Value is exactly one less than the + // Pivot's Value, then we can branch directly to the LHS's Target, + // rather than creating a leaf node for it. + if ((LHSR.second - LHSR.first) == 1 && + LHSR.first->High == CR.GE && + cast(C)->getValue() == + (cast(CR.GE)->getValue() + 1LL)) { + TrueBB = LHSR.first->BB; + } else { + TrueBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, TrueBB); + WorkList.push_back(CaseRec(TrueBB, C, CR.GE, LHSR)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + // Similar to the optimization above, if the Value being switched on is + // known to be less than the Constant CR.LT, and the current Case Value + // is CR.LT - 1, then we can branch directly to the target block for + // the current Case Value, rather than emitting a RHS leaf node for it. + if ((RHSR.second - RHSR.first) == 1 && CR.LT && + cast(RHSR.first->Low)->getValue() == + (cast(CR.LT)->getValue() - 1LL)) { + FalseBB = RHSR.first->BB; + } else { + FalseBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, FalseBB); + WorkList.push_back(CaseRec(FalseBB,CR.LT,C,RHSR)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + // Create a CaseBlock record representing a conditional branch to + // the LHS node if the value being switched on SV is less than C. + // Otherwise, branch to LHS. + CaseBlock CB(ISD::SETLT, SV, C, NULL, TrueBB, FalseBB, CR.CaseBB); + + if (CR.CaseBB == SwitchBB) + visitSwitchCase(CB, SwitchBB); + else + SwitchCases.push_back(CB); + + return true; +} + +/// handleBitTestsSwitchCase - if current case range has few destination and +/// range span less, than machine word bitwidth, encode case range into series +/// of masks and emit bit tests with these masks. +bool SelectionDAGBuilder::handleBitTestsSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB){ + EVT PTy = TLI.getPointerTy(); + unsigned IntPtrBits = PTy.getSizeInBits(); + + Case& FrontCase = *CR.Range.first; + Case& BackCase = *(CR.Range.second-1); + + // Get the MachineFunction which holds the current MBB. This is used when + // inserting any additional MBBs necessary to represent the switch. + MachineFunction *CurMF = FuncInfo.MF; + + // If target does not have legal shift left, do not emit bit tests at all. + if (!TLI.isOperationLegal(ISD::SHL, TLI.getPointerTy())) + return false; + + size_t numCmps = 0; + for (CaseItr I = CR.Range.first, E = CR.Range.second; + I!=E; ++I) { + // Single case counts one, case range - two. + numCmps += (I->Low == I->High ? 1 : 2); + } + + // Count unique destinations + SmallSet Dests; + for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) { + Dests.insert(I->BB); + if (Dests.size() > 3) + // Don't bother the code below, if there are too much unique destinations + return false; + } + DEBUG(dbgs() << "Total number of unique destinations: " + << Dests.size() << '\n' + << "Total number of comparisons: " << numCmps << '\n'); + + // Compute span of values. + const APInt& minValue = cast(FrontCase.Low)->getValue(); + const APInt& maxValue = cast(BackCase.High)->getValue(); + APInt cmpRange = maxValue - minValue; + + DEBUG(dbgs() << "Compare range: " << cmpRange << '\n' + << "Low bound: " << minValue << '\n' + << "High bound: " << maxValue << '\n'); + + if (cmpRange.uge(IntPtrBits) || + (!(Dests.size() == 1 && numCmps >= 3) && + !(Dests.size() == 2 && numCmps >= 5) && + !(Dests.size() >= 3 && numCmps >= 6))) + return false; + + DEBUG(dbgs() << "Emitting bit tests\n"); + APInt lowBound = APInt::getNullValue(cmpRange.getBitWidth()); + + // Optimize the case where all the case values fit in a + // word without having to subtract minValue. In this case, + // we can optimize away the subtraction. + if (minValue.isNonNegative() && maxValue.slt(IntPtrBits)) { + cmpRange = maxValue; + } else { + lowBound = minValue; + } + + CaseBitsVector CasesBits; + unsigned i, count = 0; + + for (CaseItr I = CR.Range.first, E = CR.Range.second; I!=E; ++I) { + MachineBasicBlock* Dest = I->BB; + for (i = 0; i < count; ++i) + if (Dest == CasesBits[i].BB) + break; + + if (i == count) { + assert((count < 3) && "Too much destinations to test!"); + CasesBits.push_back(CaseBits(0, Dest, 0)); + count++; + } + + const APInt& lowValue = cast(I->Low)->getValue(); + const APInt& highValue = cast(I->High)->getValue(); + + uint64_t lo = (lowValue - lowBound).getZExtValue(); + uint64_t hi = (highValue - lowBound).getZExtValue(); + + for (uint64_t j = lo; j <= hi; j++) { + CasesBits[i].Mask |= 1ULL << j; + CasesBits[i].Bits++; + } + + } + std::sort(CasesBits.begin(), CasesBits.end(), CaseBitsCmp()); + + BitTestInfo BTC; + + // Figure out which block is immediately after the current one. + MachineFunction::iterator BBI = CR.CaseBB; + ++BBI; + + const BasicBlock *LLVMBB = CR.CaseBB->getBasicBlock(); + + DEBUG(dbgs() << "Cases:\n"); + for (unsigned i = 0, e = CasesBits.size(); i!=e; ++i) { + DEBUG(dbgs() << "Mask: " << CasesBits[i].Mask + << ", Bits: " << CasesBits[i].Bits + << ", BB: " << CasesBits[i].BB << '\n'); + + MachineBasicBlock *CaseBB = CurMF->CreateMachineBasicBlock(LLVMBB); + CurMF->insert(BBI, CaseBB); + BTC.push_back(BitTestCase(CasesBits[i].Mask, + CaseBB, + CasesBits[i].BB)); + + // Put SV in a virtual register to make it available from the new blocks. + ExportFromCurrentBlock(SV); + } + + BitTestBlock BTB(lowBound, cmpRange, SV, + -1U, MVT::Other, (CR.CaseBB == SwitchBB), + CR.CaseBB, Default, BTC); + + if (CR.CaseBB == SwitchBB) + visitBitTestHeader(BTB, SwitchBB); + + BitTestCases.push_back(BTB); + + return true; +} + +/// Clusterify - Transform simple list of Cases into list of CaseRange's +size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, + const SwitchInst& SI) { + size_t numCmps = 0; + + // Start with "simple" cases + for (size_t i = 1; i < SI.getNumSuccessors(); ++i) { + MachineBasicBlock *SMBB = FuncInfo.MBBMap[SI.getSuccessor(i)]; + Cases.push_back(Case(SI.getSuccessorValue(i), + SI.getSuccessorValue(i), + SMBB)); + } + std::sort(Cases.begin(), Cases.end(), CaseCmp()); + + // Merge case into clusters + if (Cases.size() >= 2) + // Must recompute end() each iteration because it may be + // invalidated by erase if we hold on to it + for (CaseItr I = Cases.begin(), J = llvm::next(Cases.begin()); + J != Cases.end(); ) { + const APInt& nextValue = cast(J->Low)->getValue(); + const APInt& currentValue = cast(I->High)->getValue(); + MachineBasicBlock* nextBB = J->BB; + MachineBasicBlock* currentBB = I->BB; + + // If the two neighboring cases go to the same destination, merge them + // into a single case. + if ((nextValue - currentValue == 1) && (currentBB == nextBB)) { + I->High = J->High; + J = Cases.erase(J); + } else { + I = J++; + } + } + + for (CaseItr I=Cases.begin(), E=Cases.end(); I!=E; ++I, ++numCmps) { + if (I->Low != I->High) + // A range counts double, since it requires two compares. + ++numCmps; + } + + return numCmps; +} + +void SelectionDAGBuilder::UpdateSplitBlock(MachineBasicBlock *First, + MachineBasicBlock *Last) { + // Update JTCases. + for (unsigned i = 0, e = JTCases.size(); i != e; ++i) + if (JTCases[i].first.HeaderBB == First) + JTCases[i].first.HeaderBB = Last; + + // Update BitTestCases. + for (unsigned i = 0, e = BitTestCases.size(); i != e; ++i) + if (BitTestCases[i].Parent == First) + BitTestCases[i].Parent = Last; +} + +void SelectionDAGBuilder::visitSwitch(const SwitchInst &SI) { + MachineBasicBlock *SwitchMBB = FuncInfo.MBB; + + // Figure out which block is immediately after the current one. + MachineBasicBlock *NextBlock = 0; + MachineBasicBlock *Default = FuncInfo.MBBMap[SI.getDefaultDest()]; + + // If there is only the default destination, branch to it if it is not the + // next basic block. Otherwise, just fall through. + if (SI.getNumOperands() == 2) { + // Update machine-CFG edges. + + // If this is not a fall-through branch, emit the branch. + SwitchMBB->addSuccessor(Default); + if (Default != NextBlock) + DAG.setRoot(DAG.getNode(ISD::BR, getCurDebugLoc(), + MVT::Other, getControlRoot(), + DAG.getBasicBlock(Default))); + + return; + } + + // If there are any non-default case statements, create a vector of Cases + // representing each one, and sort the vector so that we can efficiently + // create a binary search tree from them. + CaseVector Cases; + size_t numCmps = Clusterify(Cases, SI); + DEBUG(dbgs() << "Clusterify finished. Total clusters: " << Cases.size() + << ". Total compares: " << numCmps << '\n'); + numCmps = 0; + + // Get the Value to be switched on and default basic blocks, which will be + // inserted into CaseBlock records, representing basic blocks in the binary + // search tree. + const Value *SV = SI.getOperand(0); + + // Push the initial CaseRec onto the worklist + CaseRecVector WorkList; + WorkList.push_back(CaseRec(SwitchMBB,0,0, + CaseRange(Cases.begin(),Cases.end()))); + + while (!WorkList.empty()) { + // Grab a record representing a case range to process off the worklist + CaseRec CR = WorkList.back(); + WorkList.pop_back(); + + if (handleBitTestsSwitchCase(CR, WorkList, SV, Default, SwitchMBB)) + continue; + + // If the range has few cases (two or less) emit a series of specific + // tests. + if (handleSmallSwitchRange(CR, WorkList, SV, Default, SwitchMBB)) + continue; + + // If the switch has more than 5 blocks, and at least 40% dense, and the + // target supports indirect branches, then emit a jump table rather than + // lowering the switch to a binary tree of conditional branches. + if (handleJTSwitchCase(CR, WorkList, SV, Default, SwitchMBB)) + continue; + + // Emit binary tree. We need to pick a pivot, and push left and right ranges + // onto the worklist. Leafs are handled via handleSmallSwitchRange() call. + handleBTSplitSwitchCase(CR, WorkList, SV, Default, SwitchMBB); + } +} + +void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) { + MachineBasicBlock *IndirectBrMBB = FuncInfo.MBB; + + // Update machine-CFG edges with unique successors. + SmallVector succs; + succs.reserve(I.getNumSuccessors()); + for (unsigned i = 0, e = I.getNumSuccessors(); i != e; ++i) + succs.push_back(I.getSuccessor(i)); + array_pod_sort(succs.begin(), succs.end()); + succs.erase(std::unique(succs.begin(), succs.end()), succs.end()); + for (unsigned i = 0, e = succs.size(); i != e; ++i) + IndirectBrMBB->addSuccessor(FuncInfo.MBBMap[succs[i]]); + + DAG.setRoot(DAG.getNode(ISD::BRIND, getCurDebugLoc(), + MVT::Other, getControlRoot(), + getValue(I.getAddress()))); +} + +void SelectionDAGBuilder::visitFSub(const User &I) { + // -0.0 - X --> fneg + const Type *Ty = I.getType(); + if (isa(I.getOperand(0)) && + I.getOperand(0) == ConstantFP::getZeroValueForNegation(Ty)) { + SDValue Op2 = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(), + Op2.getValueType(), Op2)); + return; + } + + visitBinary(I, ISD::FSUB); +} + +void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) { + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(OpCode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); +} + +void SelectionDAGBuilder::visitShift(const User &I, unsigned Opcode) { + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + + MVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType()); + + // Coerce the shift amount to the right type if we can. + if (!I.getType()->isVectorTy() && Op2.getValueType() != ShiftTy) { + unsigned ShiftSize = ShiftTy.getSizeInBits(); + unsigned Op2Size = Op2.getValueType().getSizeInBits(); + DebugLoc DL = getCurDebugLoc(); + + // If the operand is smaller than the shift count type, promote it. + if (ShiftSize > Op2Size) + Op2 = DAG.getNode(ISD::ZERO_EXTEND, DL, ShiftTy, Op2); + + // If the operand is larger than the shift count type but the shift + // count type has enough bits to represent any shift value, truncate + // it now. This is a common case and it exposes the truncate to + // optimization early. + else if (ShiftSize >= Log2_32_Ceil(Op2.getValueType().getSizeInBits())) + Op2 = DAG.getNode(ISD::TRUNCATE, DL, ShiftTy, Op2); + // Otherwise we'll need to temporarily settle for some other convenient + // type. Type legalization will make adjustments once the shiftee is split. + else + Op2 = DAG.getZExtOrTrunc(Op2, DL, MVT::i32); + } + + setValue(&I, DAG.getNode(Opcode, getCurDebugLoc(), + Op1.getValueType(), Op1, Op2)); +} + +void SelectionDAGBuilder::visitICmp(const User &I) { + ICmpInst::Predicate predicate = ICmpInst::BAD_ICMP_PREDICATE; + if (const ICmpInst *IC = dyn_cast(&I)) + predicate = IC->getPredicate(); + else if (const ConstantExpr *IC = dyn_cast(&I)) + predicate = ICmpInst::Predicate(IC->getPredicate()); + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + ISD::CondCode Opcode = getICmpCondCode(predicate); + + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Opcode)); +} + +void SelectionDAGBuilder::visitFCmp(const User &I) { + FCmpInst::Predicate predicate = FCmpInst::BAD_FCMP_PREDICATE; + if (const FCmpInst *FC = dyn_cast(&I)) + predicate = FC->getPredicate(); + else if (const ConstantExpr *FC = dyn_cast(&I)) + predicate = FCmpInst::Predicate(FC->getPredicate()); + SDValue Op1 = getValue(I.getOperand(0)); + SDValue Op2 = getValue(I.getOperand(1)); + ISD::CondCode Condition = getFCmpCondCode(predicate); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getSetCC(getCurDebugLoc(), DestVT, Op1, Op2, Condition)); +} + +void SelectionDAGBuilder::visitSelect(const User &I) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) return; + + SmallVector Values(NumValues); + SDValue Cond = getValue(I.getOperand(0)); + SDValue TrueVal = getValue(I.getOperand(1)); + SDValue FalseVal = getValue(I.getOperand(2)); + + for (unsigned i = 0; i != NumValues; ++i) + Values[i] = DAG.getNode(ISD::SELECT, getCurDebugLoc(), + TrueVal.getNode()->getValueType(TrueVal.getResNo()+i), + Cond, + SDValue(TrueVal.getNode(), + TrueVal.getResNo() + i), + SDValue(FalseVal.getNode(), + FalseVal.getResNo() + i)); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); +} + +void SelectionDAGBuilder::visitTrunc(const User &I) { + // TruncInst cannot be a no-op cast because sizeof(src) > sizeof(dest). + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitZExt(const User &I) { + // ZExt cannot be a no-op cast because sizeof(src) < sizeof(dest). + // ZExt also can't be a cast to bool for same reason. So, nothing much to do + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitSExt(const User &I) { + // SExt cannot be a no-op cast because sizeof(src) < sizeof(dest). + // SExt also can't be a cast to bool for same reason. So, nothing much to do + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPTrunc(const User &I) { + // FPTrunc is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_ROUND, getCurDebugLoc(), + DestVT, N, DAG.getIntPtrConstant(0))); +} + +void SelectionDAGBuilder::visitFPExt(const User &I){ + // FPTrunc is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_EXTEND, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPToUI(const User &I) { + // FPToUI is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_TO_UINT, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitFPToSI(const User &I) { + // FPToSI is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::FP_TO_SINT, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitUIToFP(const User &I) { + // UIToFP is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::UINT_TO_FP, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitSIToFP(const User &I){ + // SIToFP is never a no-op cast, no need to check + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getNode(ISD::SINT_TO_FP, getCurDebugLoc(), DestVT, N)); +} + +void SelectionDAGBuilder::visitPtrToInt(const User &I) { + // What to do depends on the size of the integer and the size of the pointer. + // We can either truncate, zero extend, or no-op, accordingly. + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT)); +} + +void SelectionDAGBuilder::visitIntToPtr(const User &I) { + // What to do depends on the size of the integer and the size of the pointer. + // We can either truncate, zero extend, or no-op, accordingly. + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + setValue(&I, DAG.getZExtOrTrunc(N, getCurDebugLoc(), DestVT)); +} + +void SelectionDAGBuilder::visitBitCast(const User &I) { + SDValue N = getValue(I.getOperand(0)); + EVT DestVT = TLI.getValueType(I.getType()); + + // BitCast assures us that source and destination are the same size so this is + // either a BITCAST or a no-op. + if (DestVT != N.getValueType()) + setValue(&I, DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + DestVT, N)); // convert types. + else + setValue(&I, N); // noop cast. +} + +void SelectionDAGBuilder::visitInsertElement(const User &I) { + SDValue InVec = getValue(I.getOperand(0)); + SDValue InVal = getValue(I.getOperand(1)); + SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), + TLI.getPointerTy(), + getValue(I.getOperand(2))); + setValue(&I, DAG.getNode(ISD::INSERT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), + InVec, InVal, InIdx)); +} + +void SelectionDAGBuilder::visitExtractElement(const User &I) { + SDValue InVec = getValue(I.getOperand(0)); + SDValue InIdx = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), + TLI.getPointerTy(), + getValue(I.getOperand(1))); + setValue(&I, DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + TLI.getValueType(I.getType()), InVec, InIdx)); +} + +// Utility for visitShuffleVector - Returns true if the mask is mask starting +// from SIndx and increasing to the element length (undefs are allowed). +static bool SequentialMask(SmallVectorImpl &Mask, unsigned SIndx) { + unsigned MaskNumElts = Mask.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) + if ((Mask[i] >= 0) && (Mask[i] != (int)(i + SIndx))) + return false; + return true; +} + +void SelectionDAGBuilder::visitShuffleVector(const User &I) { + SmallVector Mask; + SDValue Src1 = getValue(I.getOperand(0)); + SDValue Src2 = getValue(I.getOperand(1)); + + // Convert the ConstantVector mask operand into an array of ints, with -1 + // representing undef values. + SmallVector MaskElts; + cast(I.getOperand(2))->getVectorElements(MaskElts); + unsigned MaskNumElts = MaskElts.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) { + if (isa(MaskElts[i])) + Mask.push_back(-1); + else + Mask.push_back(cast(MaskElts[i])->getSExtValue()); + } + + EVT VT = TLI.getValueType(I.getType()); + EVT SrcVT = Src1.getValueType(); + unsigned SrcNumElts = SrcVT.getVectorNumElements(); + + if (SrcNumElts == MaskNumElts) { + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &Mask[0])); + return; + } + + // Normalize the shuffle vector since mask and vector length don't match. + if (SrcNumElts < MaskNumElts && MaskNumElts % SrcNumElts == 0) { + // Mask is longer than the source vectors and is a multiple of the source + // vectors. We can use concatenate vector to make the mask and vectors + // lengths match. + if (SrcNumElts*2 == MaskNumElts && SequentialMask(Mask, 0)) { + // The shuffle is concatenating two vectors together. + setValue(&I, DAG.getNode(ISD::CONCAT_VECTORS, getCurDebugLoc(), + VT, Src1, Src2)); + return; + } + + // Pad both vectors with undefs to make them the same length as the mask. + unsigned NumConcat = MaskNumElts / SrcNumElts; + bool Src1U = Src1.getOpcode() == ISD::UNDEF; + bool Src2U = Src2.getOpcode() == ISD::UNDEF; + SDValue UndefVal = DAG.getUNDEF(SrcVT); + + SmallVector MOps1(NumConcat, UndefVal); + SmallVector MOps2(NumConcat, UndefVal); + MOps1[0] = Src1; + MOps2[0] = Src2; + + Src1 = Src1U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps1[0], NumConcat); + Src2 = Src2U ? DAG.getUNDEF(VT) : DAG.getNode(ISD::CONCAT_VECTORS, + getCurDebugLoc(), VT, + &MOps2[0], NumConcat); + + // Readjust mask for new input vector length. + SmallVector MappedOps; + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + if (Idx < (int)SrcNumElts) + MappedOps.push_back(Idx); + else + MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); + } + + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); + return; + } + + if (SrcNumElts > MaskNumElts) { + // Analyze the access pattern of the vector to see if we can extract + // two subvectors and do the shuffle. The analysis is done by calculating + // the range of elements the mask access on both vectors. + int MinRange[2] = { SrcNumElts+1, SrcNumElts+1}; + int MaxRange[2] = {-1, -1}; + + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + int Input = 0; + if (Idx < 0) + continue; + + if (Idx >= (int)SrcNumElts) { + Input = 1; + Idx -= SrcNumElts; + } + if (Idx > MaxRange[Input]) + MaxRange[Input] = Idx; + if (Idx < MinRange[Input]) + MinRange[Input] = Idx; + } + + // Check if the access is smaller than the vector size and can we find + // a reasonable extract index. + int RangeUse[2] = { 2, 2 }; // 0 = Unused, 1 = Extract, 2 = Can not + // Extract. + int StartIdx[2]; // StartIdx to extract from + for (int Input=0; Input < 2; ++Input) { + if (MinRange[Input] == (int)(SrcNumElts+1) && MaxRange[Input] == -1) { + RangeUse[Input] = 0; // Unused + StartIdx[Input] = 0; + } else if (MaxRange[Input] - MinRange[Input] < (int)MaskNumElts) { + // Fits within range but we should see if we can find a good + // start index that is a multiple of the mask length. + if (MaxRange[Input] < (int)MaskNumElts) { + RangeUse[Input] = 1; // Extract from beginning of the vector + StartIdx[Input] = 0; + } else { + StartIdx[Input] = (MinRange[Input]/MaskNumElts)*MaskNumElts; + if (MaxRange[Input] - StartIdx[Input] < (int)MaskNumElts && + StartIdx[Input] + MaskNumElts <= SrcNumElts) + RangeUse[Input] = 1; // Extract from a multiple of the mask length. + } + } + } + + if (RangeUse[0] == 0 && RangeUse[1] == 0) { + setValue(&I, DAG.getUNDEF(VT)); // Vectors are not used. + return; + } + else if (RangeUse[0] < 2 && RangeUse[1] < 2) { + // Extract appropriate subvector and generate a vector shuffle + for (int Input=0; Input < 2; ++Input) { + SDValue &Src = Input == 0 ? Src1 : Src2; + if (RangeUse[Input] == 0) + Src = DAG.getUNDEF(VT); + else + Src = DAG.getNode(ISD::EXTRACT_SUBVECTOR, getCurDebugLoc(), VT, + Src, DAG.getIntPtrConstant(StartIdx[Input])); + } + + // Calculate new mask. + SmallVector MappedOps; + for (unsigned i = 0; i != MaskNumElts; ++i) { + int Idx = Mask[i]; + if (Idx < 0) + MappedOps.push_back(Idx); + else if (Idx < (int)SrcNumElts) + MappedOps.push_back(Idx - StartIdx[0]); + else + MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); + } + + setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, + &MappedOps[0])); + return; + } + } + + // We can't use either concat vectors or extract subvectors so fall back to + // replacing the shuffle with extract and build vector. + // to insert and build vector. + EVT EltVT = VT.getVectorElementType(); + EVT PtrVT = TLI.getPointerTy(); + SmallVector Ops; + for (unsigned i = 0; i != MaskNumElts; ++i) { + if (Mask[i] < 0) { + Ops.push_back(DAG.getUNDEF(EltVT)); + } else { + int Idx = Mask[i]; + SDValue Res; + + if (Idx < (int)SrcNumElts) + Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + EltVT, Src1, DAG.getConstant(Idx, PtrVT)); + else + Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), + EltVT, Src2, + DAG.getConstant(Idx - SrcNumElts, PtrVT)); + + Ops.push_back(Res); + } + } + + setValue(&I, DAG.getNode(ISD::BUILD_VECTOR, getCurDebugLoc(), + VT, &Ops[0], Ops.size())); +} + +void SelectionDAGBuilder::visitInsertValue(const InsertValueInst &I) { + const Value *Op0 = I.getOperand(0); + const Value *Op1 = I.getOperand(1); + const Type *AggTy = I.getType(); + const Type *ValTy = Op1->getType(); + bool IntoUndef = isa(Op0); + bool FromUndef = isa(Op1); + + unsigned LinearIndex = ComputeLinearIndex(AggTy, I.idx_begin(), I.idx_end()); + + SmallVector AggValueVTs; + ComputeValueVTs(TLI, AggTy, AggValueVTs); + SmallVector ValValueVTs; + ComputeValueVTs(TLI, ValTy, ValValueVTs); + + unsigned NumAggValues = AggValueVTs.size(); + unsigned NumValValues = ValValueVTs.size(); + SmallVector Values(NumAggValues); + + SDValue Agg = getValue(Op0); + SDValue Val = getValue(Op1); + unsigned i = 0; + // Copy the beginning value(s) from the original aggregate. + for (; i != LinearIndex; ++i) + Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + // Copy values from the inserted value(s). + for (; i != LinearIndex + NumValValues; ++i) + Values[i] = FromUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Val.getNode(), Val.getResNo() + i - LinearIndex); + // Copy remaining value(s) from the original aggregate. + for (; i != NumAggValues; ++i) + Values[i] = IntoUndef ? DAG.getUNDEF(AggValueVTs[i]) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&AggValueVTs[0], NumAggValues), + &Values[0], NumAggValues)); +} + +void SelectionDAGBuilder::visitExtractValue(const ExtractValueInst &I) { + const Value *Op0 = I.getOperand(0); + const Type *AggTy = Op0->getType(); + const Type *ValTy = I.getType(); + bool OutOfUndef = isa(Op0); + + unsigned LinearIndex = ComputeLinearIndex(AggTy, I.idx_begin(), I.idx_end()); + + SmallVector ValValueVTs; + ComputeValueVTs(TLI, ValTy, ValValueVTs); + + unsigned NumValValues = ValValueVTs.size(); + SmallVector Values(NumValValues); + + SDValue Agg = getValue(Op0); + // Copy out the selected value(s). + for (unsigned i = LinearIndex; i != LinearIndex + NumValValues; ++i) + Values[i - LinearIndex] = + OutOfUndef ? + DAG.getUNDEF(Agg.getNode()->getValueType(Agg.getResNo() + i)) : + SDValue(Agg.getNode(), Agg.getResNo() + i); + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValValueVTs[0], NumValValues), + &Values[0], NumValValues)); +} + +void SelectionDAGBuilder::visitGetElementPtr(const User &I) { + SDValue N = getValue(I.getOperand(0)); + const Type *Ty = I.getOperand(0)->getType(); + + for (GetElementPtrInst::const_op_iterator OI = I.op_begin()+1, E = I.op_end(); + OI != E; ++OI) { + const Value *Idx = *OI; + if (const StructType *StTy = dyn_cast(Ty)) { + unsigned Field = cast(Idx)->getZExtValue(); + if (Field) { + // N = N + Offset + uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field); + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, + DAG.getIntPtrConstant(Offset)); + } + + Ty = StTy->getElementType(Field); + } else { + Ty = cast(Ty)->getElementType(); + + // If this is a constant subscript, handle it quickly. + if (const ConstantInt *CI = dyn_cast(Idx)) { + if (CI->isZero()) continue; + uint64_t Offs = + TD->getTypeAllocSize(Ty)*cast(CI)->getSExtValue(); + SDValue OffsVal; + EVT PTy = TLI.getPointerTy(); + unsigned PtrBits = PTy.getSizeInBits(); + if (PtrBits < 64) + OffsVal = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), + TLI.getPointerTy(), + DAG.getConstant(Offs, MVT::i64)); + else + OffsVal = DAG.getIntPtrConstant(Offs); + + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), N.getValueType(), N, + OffsVal); + continue; + } + + // N = N + Idx * ElementSize; + APInt ElementSize = APInt(TLI.getPointerTy().getSizeInBits(), + TD->getTypeAllocSize(Ty)); + SDValue IdxN = getValue(Idx); + + // If the index is smaller or larger than intptr_t, truncate or extend + // it. + IdxN = DAG.getSExtOrTrunc(IdxN, getCurDebugLoc(), N.getValueType()); + + // If this is a multiply by a power of two, turn it into a shl + // immediately. This is a very common case. + if (ElementSize != 1) { + if (ElementSize.isPowerOf2()) { + unsigned Amt = ElementSize.logBase2(); + IdxN = DAG.getNode(ISD::SHL, getCurDebugLoc(), + N.getValueType(), IdxN, + DAG.getConstant(Amt, TLI.getPointerTy())); + } else { + SDValue Scale = DAG.getConstant(ElementSize, TLI.getPointerTy()); + IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(), + N.getValueType(), IdxN, Scale); + } + } + + N = DAG.getNode(ISD::ADD, getCurDebugLoc(), + N.getValueType(), N, IdxN); + } + } + + setValue(&I, N); +} + +void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) { + // If this is a fixed sized alloca in the entry block of the function, + // allocate it statically on the stack. + if (FuncInfo.StaticAllocaMap.count(&I)) + return; // getValue will auto-populate this. + + const Type *Ty = I.getAllocatedType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = + std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty), + I.getAlignment()); + + SDValue AllocSize = getValue(I.getArraySize()); + + EVT IntPtr = TLI.getPointerTy(); + if (AllocSize.getValueType() != IntPtr) + AllocSize = DAG.getZExtOrTrunc(AllocSize, getCurDebugLoc(), IntPtr); + + AllocSize = DAG.getNode(ISD::MUL, getCurDebugLoc(), IntPtr, + AllocSize, + DAG.getConstant(TySize, IntPtr)); + + // Handle alignment. If the requested alignment is less than or equal to + // the stack alignment, ignore it. If the size is greater than or equal to + // the stack alignment, we note this in the DYNAMIC_STACKALLOC node. + unsigned StackAlign = TM.getFrameLowering()->getStackAlignment(); + if (Align <= StackAlign) + Align = 0; + + // Round the size of the allocation up to the stack alignment size + // by add SA-1 to the size. + AllocSize = DAG.getNode(ISD::ADD, getCurDebugLoc(), + AllocSize.getValueType(), AllocSize, + DAG.getIntPtrConstant(StackAlign-1)); + + // Mask out the low bits for alignment purposes. + AllocSize = DAG.getNode(ISD::AND, getCurDebugLoc(), + AllocSize.getValueType(), AllocSize, + DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1))); + + SDValue Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) }; + SDVTList VTs = DAG.getVTList(AllocSize.getValueType(), MVT::Other); + SDValue DSA = DAG.getNode(ISD::DYNAMIC_STACKALLOC, getCurDebugLoc(), + VTs, Ops, 3); + setValue(&I, DSA); + DAG.setRoot(DSA.getValue(1)); + + // Inform the Frame Information that we have just allocated a variable-sized + // object. + FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1); +} + +void SelectionDAGBuilder::visitLoad(const LoadInst &I) { + const Value *SV = I.getOperand(0); + SDValue Ptr = getValue(SV); + + const Type *Ty = I.getType(); + + bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; + unsigned Alignment = I.getAlignment(); + const MDNode *TBAAInfo = I.getMetadata(LLVMContext::MD_tbaa); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, Ty, ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) + return; + + SDValue Root; + bool ConstantMemory = false; + if (I.isVolatile() || NumValues > MaxParallelChains) + // Serialize volatile loads with other side effects. + Root = getRoot(); + else if (AA->pointsToConstantMemory( + AliasAnalysis::Location(SV, AA->getTypeStoreSize(Ty), TBAAInfo))) { + // Do not serialize (non-volatile) loads of constant memory with anything. + Root = DAG.getEntryNode(); + ConstantMemory = true; + } else { + // Do not serialize non-volatile loads against each other. + Root = DAG.getRoot(); + } + + SmallVector Values(NumValues); + SmallVector Chains(std::min(unsigned(MaxParallelChains), + NumValues)); + EVT PtrVT = Ptr.getValueType(); + unsigned ChainI = 0; + for (unsigned i = 0; i != NumValues; ++i, ++ChainI) { + // Serializing loads here may result in excessive register pressure, and + // TokenFactor places arbitrary choke points on the scheduler. SD scheduling + // could recover a bit by hoisting nodes upward in the chain by recognizing + // they are side-effect free or do not alias. The optimizer should really + // avoid this case by converting large object/array copies to llvm.memcpy + // (MaxParallelChains should always remain as failsafe). + if (ChainI == MaxParallelChains) { + assert(PendingLoads.empty() && "PendingLoads must be serialized first"); + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], ChainI); + Root = Chain; + ChainI = 0; + } + SDValue A = DAG.getNode(ISD::ADD, getCurDebugLoc(), + PtrVT, Ptr, + DAG.getConstant(Offsets[i], PtrVT)); + SDValue L = DAG.getLoad(ValueVTs[i], getCurDebugLoc(), Root, + A, MachinePointerInfo(SV, Offsets[i]), isVolatile, + isNonTemporal, Alignment, TBAAInfo); + + Values[i] = L; + Chains[ChainI] = L.getValue(1); + } + + if (!ConstantMemory) { + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], ChainI); + if (isVolatile) + DAG.setRoot(Chain); + else + PendingLoads.push_back(Chain); + } + + setValue(&I, DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&ValueVTs[0], NumValues), + &Values[0], NumValues)); +} + +void SelectionDAGBuilder::visitStore(const StoreInst &I) { + const Value *SrcV = I.getOperand(0); + const Value *PtrV = I.getOperand(1); + + SmallVector ValueVTs; + SmallVector Offsets; + ComputeValueVTs(TLI, SrcV->getType(), ValueVTs, &Offsets); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) + return; + + // Get the lowered operands. Note that we do this after + // checking if NumResults is zero, because with zero results + // the operands won't have values in the map. + SDValue Src = getValue(SrcV); + SDValue Ptr = getValue(PtrV); + + SDValue Root = getRoot(); + SmallVector Chains(std::min(unsigned(MaxParallelChains), + NumValues)); + EVT PtrVT = Ptr.getValueType(); + bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; + unsigned Alignment = I.getAlignment(); + const MDNode *TBAAInfo = I.getMetadata(LLVMContext::MD_tbaa); + + unsigned ChainI = 0; + for (unsigned i = 0; i != NumValues; ++i, ++ChainI) { + // See visitLoad comments. + if (ChainI == MaxParallelChains) { + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], ChainI); + Root = Chain; + ChainI = 0; + } + SDValue Add = DAG.getNode(ISD::ADD, getCurDebugLoc(), PtrVT, Ptr, + DAG.getConstant(Offsets[i], PtrVT)); + SDValue St = DAG.getStore(Root, getCurDebugLoc(), + SDValue(Src.getNode(), Src.getResNo() + i), + Add, MachinePointerInfo(PtrV, Offsets[i]), + isVolatile, isNonTemporal, Alignment, TBAAInfo); + Chains[ChainI] = St; + } + + SDValue StoreNode = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], ChainI); + ++SDNodeOrder; + AssignOrderingToNode(StoreNode.getNode()); + DAG.setRoot(StoreNode); +} + +/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC +/// node. +void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I, + unsigned Intrinsic) { + bool HasChain = !I.doesNotAccessMemory(); + bool OnlyLoad = HasChain && I.onlyReadsMemory(); + + // Build the operand list. + SmallVector Ops; + if (HasChain) { // If this intrinsic has side-effects, chainify it. + if (OnlyLoad) { + // We don't need to serialize loads against other loads. + Ops.push_back(DAG.getRoot()); + } else { + Ops.push_back(getRoot()); + } + } + + // Info is set by getTgtMemInstrinsic + TargetLowering::IntrinsicInfo Info; + bool IsTgtIntrinsic = TLI.getTgtMemIntrinsic(Info, I, Intrinsic); + + // Add the intrinsic ID as an integer operand if it's not a target intrinsic. + if (!IsTgtIntrinsic || Info.opc == ISD::INTRINSIC_VOID || + Info.opc == ISD::INTRINSIC_W_CHAIN) + Ops.push_back(DAG.getConstant(Intrinsic, TLI.getPointerTy())); + + // Add all operands of the call to the operand list. + for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { + SDValue Op = getValue(I.getArgOperand(i)); + assert(TLI.isTypeLegal(Op.getValueType()) && + "Intrinsic uses a non-legal type?"); + Ops.push_back(Op); + } + + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getType(), ValueVTs); +#ifndef NDEBUG + for (unsigned Val = 0, E = ValueVTs.size(); Val != E; ++Val) { + assert(TLI.isTypeLegal(ValueVTs[Val]) && + "Intrinsic uses a non-legal type?"); + } +#endif // NDEBUG + + if (HasChain) + ValueVTs.push_back(MVT::Other); + + SDVTList VTs = DAG.getVTList(ValueVTs.data(), ValueVTs.size()); + + // Create the node. + SDValue Result; + if (IsTgtIntrinsic) { + // This is target intrinsic that touches memory + Result = DAG.getMemIntrinsicNode(Info.opc, getCurDebugLoc(), + VTs, &Ops[0], Ops.size(), + Info.memVT, + MachinePointerInfo(Info.ptrVal, Info.offset), + Info.align, Info.vol, + Info.readMem, Info.writeMem); + } else if (!HasChain) { + Result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + } else if (!I.getType()->isVoidTy()) { + Result = DAG.getNode(ISD::INTRINSIC_W_CHAIN, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + } else { + Result = DAG.getNode(ISD::INTRINSIC_VOID, getCurDebugLoc(), + VTs, &Ops[0], Ops.size()); + } + + if (HasChain) { + SDValue Chain = Result.getValue(Result.getNode()->getNumValues()-1); + if (OnlyLoad) + PendingLoads.push_back(Chain); + else + DAG.setRoot(Chain); + } + + if (!I.getType()->isVoidTy()) { + if (const VectorType *PTy = dyn_cast(I.getType())) { + EVT VT = TLI.getValueType(PTy); + Result = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), VT, Result); + } + + setValue(&I, Result); + } +} + +/// GetSignificand - Get the significand and build it into a floating-point +/// number with exponent of 1: +/// +/// Op = (Op & 0x007fffff) | 0x3f800000; +/// +/// where Op is the hexidecimal representation of floating point value. +static SDValue +GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl) { + SDValue t1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, + DAG.getConstant(0x007fffff, MVT::i32)); + SDValue t2 = DAG.getNode(ISD::OR, dl, MVT::i32, t1, + DAG.getConstant(0x3f800000, MVT::i32)); + return DAG.getNode(ISD::BITCAST, dl, MVT::f32, t2); +} + +/// GetExponent - Get the exponent: +/// +/// (float)(int)(((Op & 0x7f800000) >> 23) - 127); +/// +/// where Op is the hexidecimal representation of floating point value. +static SDValue +GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, + DebugLoc dl) { + SDValue t0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, + DAG.getConstant(0x7f800000, MVT::i32)); + SDValue t1 = DAG.getNode(ISD::SRL, dl, MVT::i32, t0, + DAG.getConstant(23, TLI.getPointerTy())); + SDValue t2 = DAG.getNode(ISD::SUB, dl, MVT::i32, t1, + DAG.getConstant(127, MVT::i32)); + return DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); +} + +/// getF32Constant - Get 32-bit floating point constant. +static SDValue +getF32Constant(SelectionDAG &DAG, unsigned Flt) { + return DAG.getConstantFP(APFloat(APInt(32, Flt)), MVT::f32); +} + +/// Inlined utility function to implement binary input atomic intrinsics for +/// visitIntrinsicCall: I is a call instruction +/// Op is the associated NodeType for I +const char * +SelectionDAGBuilder::implVisitBinaryAtomic(const CallInst& I, + ISD::NodeType Op) { + SDValue Root = getRoot(); + SDValue L = + DAG.getAtomic(Op, getCurDebugLoc(), + getValue(I.getArgOperand(1)).getValueType().getSimpleVT(), + Root, + getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1)), + I.getArgOperand(0)); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; +} + +// implVisitAluOverflow - Lower arithmetic overflow instrinsics. +const char * +SelectionDAGBuilder::implVisitAluOverflow(const CallInst &I, ISD::NodeType Op) { + SDValue Op1 = getValue(I.getArgOperand(0)); + SDValue Op2 = getValue(I.getArgOperand(1)); + + SDVTList VTs = DAG.getVTList(Op1.getValueType(), MVT::i1); + setValue(&I, DAG.getNode(Op, getCurDebugLoc(), VTs, Op1, Op2)); + return 0; +} + +/// visitExp - Lower an exp intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitExp(const CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getArgOperand(0)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(0)); + + // Put the exponent in the right bit position for later addition to the + // final result: + // + // #define LOG2OFe 1.4426950f + // IntegerPartOfX = ((int32_t)(X * LOG2OFe)); + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, Op, + getF32Constant(DAG, 0x3fb8aa3b)); + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, t0); + + // FractionalPartOfX = (X * LOG2OFe) - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // TwoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BITCAST, dl,MVT::i32, t5); + + // Add the exponent into the result in integer domain. + SDValue t6 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, MVT::f32, t6); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // 0.000107046256 error, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BITCAST, dl,MVT::i32, t7); + + // Add the exponent into the result in integer domain. + SDValue t8 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, MVT::f32, t8); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue TwoToFracPartOfX = DAG.getNode(ISD::BITCAST, dl, + MVT::i32, t13); + + // Add the exponent into the result in integer domain. + SDValue t14 = DAG.getNode(ISD::ADD, dl, MVT::i32, + TwoToFracPartOfX, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, MVT::f32, t14); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FEXP, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0))); + } + + setValue(&I, result); +} + +/// visitLog - Lower a log intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog(const CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getArgOperand(0)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(0)); + SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); + + // Scale the exponent by log(2) [0.69314718f]. + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); + SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, + getF32Constant(DAG, 0x3f317218)); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // LogofMantissa = + // -1.1609546f + + // (1.4034025f - 0.23903021f * x) * x; + // + // error 0.0034276066, which is better than 8 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbe74c456)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3fb3a2b1)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f949a29)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // LogOfMantissa = + // -1.7417939f + + // (2.8212026f + + // (-1.4699568f + + // (0.44717955f - 0.56570851e-1f * x) * x) * x) * x; + // + // error 0.000061011436, which is 14 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbd67b6d6)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3ee4f4b8)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fbc278b)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40348e95)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3fdef31a)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // LogOfMantissa = + // -2.1072184f + + // (4.2372794f + + // (-3.7029485f + + // (2.2781945f + + // (-0.87823314f + + // (0.19073739f - 0.17809712e-1f * x) * x) * x) * x) * x)*x; + // + // error 0.0000023660568, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbc91e5ac)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e4350aa)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f60d3e3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x4011cdf0)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x406cfd1c)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x408797cb)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue LogOfMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t10, + getF32Constant(DAG, 0x4006dcab)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, LogOfMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0))); + } + + setValue(&I, result); +} + +/// visitLog2 - Lower a log2 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog2(const CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getArgOperand(0)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(0)); + SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); + + // Get the exponent. + SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + // Different possible minimax approximations of significand in + // floating-point for various degrees of accuracy over [1,2]. + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // Log2ofMantissa = -1.6749035f + (2.0246817f - .34484768f * x) * x; + // + // error 0.0049451742, which is more than 7 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbeb08fe0)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x40019463)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fd6633d)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // Log2ofMantissa = + // -2.51285454f + + // (4.07009056f + + // (-2.12067489f + + // (.645142248f - 0.816157886e-1f * x) * x) * x) * x; + // + // error 0.0000876136000, which is better than 13 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbda7262e)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3f25280b)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x4007b923)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40823e2f)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x4020d29c)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // Log2ofMantissa = + // -3.0400495f + + // (6.1129976f + + // (-5.3420409f + + // (3.2865683f + + // (-1.2669343f + + // (0.27515199f - + // 0.25691327e-1f * x) * x) * x) * x) * x) * x; + // + // error 0.0000018516, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbcd2769e)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e8ce0b9)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3fa22ae7)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x40525723)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t6, + getF32Constant(DAG, 0x40aaf200)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x40c39dad)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue Log2ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t10, + getF32Constant(DAG, 0x4042902c)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log2ofMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG2, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0))); + } + + setValue(&I, result); +} + +/// visitLog10 - Lower a log10 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitLog10(const CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getArgOperand(0)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(0)); + SDValue Op1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); + + // Scale the exponent by log10(2) [0.30102999f]. + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); + SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, + getF32Constant(DAG, 0x3e9a209a)); + + // Get the significand and build it into a floating-point number with + // exponent of 1. + SDValue X = GetSignificand(DAG, Op1, dl); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // Log10ofMantissa = + // -0.50419619f + + // (0.60948995f - 0.10380950f * x) * x; + // + // error 0.0014886165, which is 6 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0xbdd49a13)); + SDValue t1 = DAG.getNode(ISD::FADD, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3f1c0789)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f011300)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // Log10ofMantissa = + // -0.64831180f + + // (0.91751397f + + // (-0.31664806f + 0.47637168e-1f * x) * x) * x; + // + // error 0.00019228036, which is better than 12 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3d431f31)); + SDValue t1 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3ea21fb2)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f6ae232)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f25f7c3)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // Log10ofMantissa = + // -0.84299375f + + // (1.5327582f + + // (-1.0688956f + + // (0.49102474f + + // (-0.12539807f + 0.13508273e-1f * x) * x) * x) * x) * x; + // + // error 0.0000037995730, which is better than 18 bits + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3c5d51ce)); + SDValue t1 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, + getF32Constant(DAG, 0x3e00685a)); + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t1, X); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3efb6798)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FSUB, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f88d192)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3fc4316c)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue Log10ofMantissa = DAG.getNode(ISD::FSUB, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3f57ce70)); + + result = DAG.getNode(ISD::FADD, dl, + MVT::f32, LogOfExponent, Log10ofMantissa); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FLOG10, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0))); + } + + setValue(&I, result); +} + +/// visitExp2 - Lower an exp2 intrinsic. Handles the special sequences for +/// limited-precision mode. +void +SelectionDAGBuilder::visitExp2(const CallInst &I) { + SDValue result; + DebugLoc dl = getCurDebugLoc(); + + if (getValue(I.getArgOperand(0)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(0)); + + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Op); + + // FractionalPartOfX = x - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, Op, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // TwoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue t6 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t5); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t6, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // error 0.000107046256, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue t8 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t7); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t8, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue t14 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t13); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t14, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FEXP2, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0))); + } + + setValue(&I, result); +} + +/// visitPow - Lower a pow intrinsic. Handles the special sequences for +/// limited-precision mode with x == 10.0f. +void +SelectionDAGBuilder::visitPow(const CallInst &I) { + SDValue result; + const Value *Val = I.getArgOperand(0); + DebugLoc dl = getCurDebugLoc(); + bool IsExp10 = false; + + if (getValue(Val).getValueType() == MVT::f32 && + getValue(I.getArgOperand(1)).getValueType() == MVT::f32 && + LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + if (Constant *C = const_cast(dyn_cast(Val))) { + if (ConstantFP *CFP = dyn_cast(C)) { + APFloat Ten(10.0f); + IsExp10 = CFP->getValueAPF().bitwiseIsEqual(Ten); + } + } + } + + if (IsExp10 && LimitFloatPrecision > 0 && LimitFloatPrecision <= 18) { + SDValue Op = getValue(I.getArgOperand(1)); + + // Put the exponent in the right bit position for later addition to the + // final result: + // + // #define LOG2OF10 3.3219281f + // IntegerPartOfX = (int32_t)(x * LOG2OF10); + SDValue t0 = DAG.getNode(ISD::FMUL, dl, MVT::f32, Op, + getF32Constant(DAG, 0x40549a78)); + SDValue IntegerPartOfX = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, t0); + + // FractionalPartOfX = x - (float)IntegerPartOfX; + SDValue t1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, IntegerPartOfX); + SDValue X = DAG.getNode(ISD::FSUB, dl, MVT::f32, t0, t1); + + // IntegerPartOfX <<= 23; + IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, + DAG.getConstant(23, TLI.getPointerTy())); + + if (LimitFloatPrecision <= 6) { + // For floating-point precision of 6: + // + // twoToFractionalPartOfX = + // 0.997535578f + + // (0.735607626f + 0.252464424f * x) * x; + // + // error 0.0144103317, which is 6 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3e814304)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3f3c50c8)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f7f5e7e)); + SDValue t6 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t5); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t6, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } else if (LimitFloatPrecision > 6 && LimitFloatPrecision <= 12) { + // For floating-point precision of 12: + // + // TwoToFractionalPartOfX = + // 0.999892986f + + // (0.696457318f + + // (0.224338339f + 0.792043434e-1f * x) * x) * x; + // + // error 0.000107046256, which is 13 to 14 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3da235e3)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3e65b8f3)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3f324b07)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3f7ff8fd)); + SDValue t8 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t7); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t8, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } else { // LimitFloatPrecision > 12 && LimitFloatPrecision <= 18 + // For floating-point precision of 18: + // + // TwoToFractionalPartOfX = + // 0.999999982f + + // (0.693148872f + + // (0.240227044f + + // (0.554906021e-1f + + // (0.961591928e-2f + + // (0.136028312e-2f + 0.157059148e-3f *x)*x)*x)*x)*x)*x; + // error 2.47208000*10^(-7), which is better than 18 bits + SDValue t2 = DAG.getNode(ISD::FMUL, dl, MVT::f32, X, + getF32Constant(DAG, 0x3924b03e)); + SDValue t3 = DAG.getNode(ISD::FADD, dl, MVT::f32, t2, + getF32Constant(DAG, 0x3ab24b87)); + SDValue t4 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t3, X); + SDValue t5 = DAG.getNode(ISD::FADD, dl, MVT::f32, t4, + getF32Constant(DAG, 0x3c1d8c17)); + SDValue t6 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t5, X); + SDValue t7 = DAG.getNode(ISD::FADD, dl, MVT::f32, t6, + getF32Constant(DAG, 0x3d634a1d)); + SDValue t8 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t7, X); + SDValue t9 = DAG.getNode(ISD::FADD, dl, MVT::f32, t8, + getF32Constant(DAG, 0x3e75fe14)); + SDValue t10 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t9, X); + SDValue t11 = DAG.getNode(ISD::FADD, dl, MVT::f32, t10, + getF32Constant(DAG, 0x3f317234)); + SDValue t12 = DAG.getNode(ISD::FMUL, dl, MVT::f32, t11, X); + SDValue t13 = DAG.getNode(ISD::FADD, dl, MVT::f32, t12, + getF32Constant(DAG, 0x3f800000)); + SDValue t14 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, t13); + SDValue TwoToFractionalPartOfX = + DAG.getNode(ISD::ADD, dl, MVT::i32, t14, IntegerPartOfX); + + result = DAG.getNode(ISD::BITCAST, dl, + MVT::f32, TwoToFractionalPartOfX); + } + } else { + // No special expansion. + result = DAG.getNode(ISD::FPOW, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1))); + } + + setValue(&I, result); +} + + +/// ExpandPowI - Expand a llvm.powi intrinsic. +static SDValue ExpandPowI(DebugLoc DL, SDValue LHS, SDValue RHS, + SelectionDAG &DAG) { + // If RHS is a constant, we can expand this out to a multiplication tree, + // otherwise we end up lowering to a call to __powidf2 (for example). When + // optimizing for size, we only want to do this if the expansion would produce + // a small number of multiplies, otherwise we do the full expansion. + if (ConstantSDNode *RHSC = dyn_cast(RHS)) { + // Get the exponent as a positive value. + unsigned Val = RHSC->getSExtValue(); + if ((int)Val < 0) Val = -Val; + + // powi(x, 0) -> 1.0 + if (Val == 0) + return DAG.getConstantFP(1.0, LHS.getValueType()); + + const Function *F = DAG.getMachineFunction().getFunction(); + if (!F->hasFnAttr(Attribute::OptimizeForSize) || + // If optimizing for size, don't insert too many multiplies. This + // inserts up to 5 multiplies. + CountPopulation_32(Val)+Log2_32(Val) < 7) { + // We use the simple binary decomposition method to generate the multiply + // sequence. There are more optimal ways to do this (for example, + // powi(x,15) generates one more multiply than it should), but this has + // the benefit of being both really simple and much better than a libcall. + SDValue Res; // Logically starts equal to 1.0 + SDValue CurSquare = LHS; + while (Val) { + if (Val & 1) { + if (Res.getNode()) + Res = DAG.getNode(ISD::FMUL, DL,Res.getValueType(), Res, CurSquare); + else + Res = CurSquare; // 1.0*CurSquare. + } + + CurSquare = DAG.getNode(ISD::FMUL, DL, CurSquare.getValueType(), + CurSquare, CurSquare); + Val >>= 1; + } + + // If the original was negative, invert the result, producing 1/(x*x*x). + if (RHSC->getSExtValue() < 0) + Res = DAG.getNode(ISD::FDIV, DL, LHS.getValueType(), + DAG.getConstantFP(1.0, LHS.getValueType()), Res); + return Res; + } + } + + // Otherwise, expand to a libcall. + return DAG.getNode(ISD::FPOWI, DL, LHS.getValueType(), LHS, RHS); +} + +/// EmitFuncArgumentDbgValue - If the DbgValueInst is a dbg_value of a function +/// argument, create the corresponding DBG_VALUE machine instruction for it now. +/// At the end of instruction selection, they will be inserted to the entry BB. +bool +SelectionDAGBuilder::EmitFuncArgumentDbgValue(const Value *V, MDNode *Variable, + int64_t Offset, + const SDValue &N) { + const Argument *Arg = dyn_cast(V); + if (!Arg) + return false; + + MachineFunction &MF = DAG.getMachineFunction(); + const TargetInstrInfo *TII = DAG.getTarget().getInstrInfo(); + const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + + // Ignore inlined function arguments here. + DIVariable DV(Variable); + if (DV.isInlinedFnArgument(MF.getFunction())) + return false; + + MachineBasicBlock *MBB = FuncInfo.MBB; + if (MBB != &MF.front()) + return false; + + unsigned Reg = 0; + if (Arg->hasByValAttr()) { + // Byval arguments' frame index is recorded during argument lowering. + // Use this info directly. + Reg = TRI->getFrameRegister(MF); + Offset = FuncInfo.getByValArgumentFrameIndex(Arg); + // If byval argument ofset is not recorded then ignore this. + if (!Offset) + Reg = 0; + } + + if (N.getNode() && N.getOpcode() == ISD::CopyFromReg) { + Reg = cast(N.getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + unsigned PR = RegInfo.getLiveInPhysReg(Reg); + if (PR) + Reg = PR; + } + } + + if (!Reg) { + // Check if ValueMap has reg number. + DenseMap::iterator VMI = FuncInfo.ValueMap.find(V); + if (VMI != FuncInfo.ValueMap.end()) + Reg = VMI->second; + } + + if (!Reg && N.getNode()) { + // Check if frame index is available. + if (LoadSDNode *LNode = dyn_cast(N.getNode())) + if (FrameIndexSDNode *FINode = + dyn_cast(LNode->getBasePtr().getNode())) { + Reg = TRI->getFrameRegister(MF); + Offset = FINode->getIndex(); + } + } + + if (!Reg) + return false; + + MachineInstrBuilder MIB = BuildMI(MF, getCurDebugLoc(), + TII->get(TargetOpcode::DBG_VALUE)) + .addReg(Reg, RegState::Debug).addImm(Offset).addMetadata(Variable); + FuncInfo.ArgDbgValues.push_back(&*MIB); + return true; +} + +// VisualStudio defines setjmp as _setjmp +#if defined(_MSC_VER) && defined(setjmp) && \ + !defined(setjmp_undefined_for_msvc) +# pragma push_macro("setjmp") +# undef setjmp +# define setjmp_undefined_for_msvc +#endif + +/// visitIntrinsicCall - Lower the call to the specified intrinsic function. If +/// we want to emit this as a call to a named external function, return the name +/// otherwise lower it and return null. +const char * +SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { + DebugLoc dl = getCurDebugLoc(); + SDValue Res; + + switch (Intrinsic) { + default: + // By default, turn this into a target intrinsic node. + visitTargetIntrinsic(I, Intrinsic); + return 0; + case Intrinsic::vastart: visitVAStart(I); return 0; + case Intrinsic::vaend: visitVAEnd(I); return 0; + case Intrinsic::vacopy: visitVACopy(I); return 0; + case Intrinsic::returnaddress: + setValue(&I, DAG.getNode(ISD::RETURNADDR, dl, TLI.getPointerTy(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::frameaddress: + setValue(&I, DAG.getNode(ISD::FRAMEADDR, dl, TLI.getPointerTy(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::setjmp: + return "_setjmp"+!TLI.usesUnderscoreSetJmp(); + case Intrinsic::longjmp: + return "_longjmp"+!TLI.usesUnderscoreLongJmp(); + case Intrinsic::memcpy: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast(I.getArgOperand(0)->getType())->getAddressSpace() + < 256 && + cast(I.getArgOperand(1)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); + SDValue Op1 = getValue(I.getArgOperand(0)); + SDValue Op2 = getValue(I.getArgOperand(1)); + SDValue Op3 = getValue(I.getArgOperand(2)); + unsigned Align = cast(I.getArgOperand(3))->getZExtValue(); + bool isVol = cast(I.getArgOperand(4))->getZExtValue(); + DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, false, + MachinePointerInfo(I.getArgOperand(0)), + MachinePointerInfo(I.getArgOperand(1)))); + return 0; + } + case Intrinsic::memset: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast(I.getArgOperand(0)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); + SDValue Op1 = getValue(I.getArgOperand(0)); + SDValue Op2 = getValue(I.getArgOperand(1)); + SDValue Op3 = getValue(I.getArgOperand(2)); + unsigned Align = cast(I.getArgOperand(3))->getZExtValue(); + bool isVol = cast(I.getArgOperand(4))->getZExtValue(); + DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, isVol, + MachinePointerInfo(I.getArgOperand(0)))); + return 0; + } + case Intrinsic::memmove: { + // Assert for address < 256 since we support only user defined address + // spaces. + assert(cast(I.getArgOperand(0)->getType())->getAddressSpace() + < 256 && + cast(I.getArgOperand(1)->getType())->getAddressSpace() + < 256 && + "Unknown address space"); + SDValue Op1 = getValue(I.getArgOperand(0)); + SDValue Op2 = getValue(I.getArgOperand(1)); + SDValue Op3 = getValue(I.getArgOperand(2)); + unsigned Align = cast(I.getArgOperand(3))->getZExtValue(); + bool isVol = cast(I.getArgOperand(4))->getZExtValue(); + DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, isVol, + MachinePointerInfo(I.getArgOperand(0)), + MachinePointerInfo(I.getArgOperand(1)))); + return 0; + } + case Intrinsic::dbg_declare: { + const DbgDeclareInst &DI = cast(I); + MDNode *Variable = DI.getVariable(); + const Value *Address = DI.getAddress(); + if (!Address || !DIVariable(DI.getVariable()).Verify()) + return 0; + + // Build an entry in DbgOrdering. Debug info input nodes get an SDNodeOrder + // but do not always have a corresponding SDNode built. The SDNodeOrder + // absolute, but not relative, values are different depending on whether + // debug info exists. + ++SDNodeOrder; + + // Check if address has undef value. + if (isa(Address) || + (Address->use_empty() && !isa(Address))) { + DEBUG(dbgs() << "Dropping debug info for " << DI); + return 0; + } + + SDValue &N = NodeMap[Address]; + if (!N.getNode() && isa(Address)) + // Check unused arguments map. + N = UnusedArgNodeMap[Address]; + SDDbgValue *SDV; + if (N.getNode()) { + // Parameters are handled specially. + bool isParameter = + DIVariable(Variable).getTag() == dwarf::DW_TAG_arg_variable; + if (const BitCastInst *BCI = dyn_cast(Address)) + Address = BCI->getOperand(0); + const AllocaInst *AI = dyn_cast(Address); + + if (isParameter && !AI) { + FrameIndexSDNode *FINode = dyn_cast(N.getNode()); + if (FINode) + // Byval parameter. We have a frame index at this point. + SDV = DAG.getDbgValue(Variable, FINode->getIndex(), + 0, dl, SDNodeOrder); + else { + // Can't do anything with other non-AI cases yet. This might be a + // parameter of a callee function that got inlined, for example. + DEBUG(dbgs() << "Dropping debug info for " << DI); + return 0; + } + } else if (AI) + SDV = DAG.getDbgValue(Variable, N.getNode(), N.getResNo(), + 0, dl, SDNodeOrder); + else { + // Can't do anything with other non-AI cases yet. + DEBUG(dbgs() << "Dropping debug info for " << DI); + return 0; + } + DAG.AddDbgValue(SDV, N.getNode(), isParameter); + } else { + // If Address is an argument then try to emit its dbg value using + // virtual register info from the FuncInfo.ValueMap. + if (!EmitFuncArgumentDbgValue(Address, Variable, 0, N)) { + // If variable is pinned by a alloca in dominating bb then + // use StaticAllocaMap. + if (const AllocaInst *AI = dyn_cast(Address)) { + if (AI->getParent() != DI.getParent()) { + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + SDV = DAG.getDbgValue(Variable, SI->second, + 0, dl, SDNodeOrder); + DAG.AddDbgValue(SDV, 0, false); + return 0; + } + } + } + DEBUG(dbgs() << "Dropping debug info for " << DI); + } + } + return 0; + } + case Intrinsic::dbg_value: { + const DbgValueInst &DI = cast(I); + if (!DIVariable(DI.getVariable()).Verify()) + return 0; + + MDNode *Variable = DI.getVariable(); + uint64_t Offset = DI.getOffset(); + const Value *V = DI.getValue(); + if (!V) + return 0; + + // Build an entry in DbgOrdering. Debug info input nodes get an SDNodeOrder + // but do not always have a corresponding SDNode built. The SDNodeOrder + // absolute, but not relative, values are different depending on whether + // debug info exists. + ++SDNodeOrder; + SDDbgValue *SDV; + if (isa(V) || isa(V)) { + SDV = DAG.getDbgValue(Variable, V, Offset, dl, SDNodeOrder); + DAG.AddDbgValue(SDV, 0, false); + } else { + // Do not use getValue() in here; we don't want to generate code at + // this point if it hasn't been done yet. + SDValue N = NodeMap[V]; + if (!N.getNode() && isa(V)) + // Check unused arguments map. + N = UnusedArgNodeMap[V]; + if (N.getNode()) { + if (!EmitFuncArgumentDbgValue(V, Variable, Offset, N)) { + SDV = DAG.getDbgValue(Variable, N.getNode(), + N.getResNo(), Offset, dl, SDNodeOrder); + DAG.AddDbgValue(SDV, N.getNode(), false); + } + } else if (!V->use_empty() ) { + // Do not call getValue(V) yet, as we don't want to generate code. + // Remember it for later. + DanglingDebugInfo DDI(&DI, dl, SDNodeOrder); + DanglingDebugInfoMap[V] = DDI; + } else { + // We may expand this to cover more cases. One case where we have no + // data available is an unreferenced parameter. + DEBUG(dbgs() << "Dropping debug info for " << DI); + } + } + + // Build a debug info table entry. + if (const BitCastInst *BCI = dyn_cast(V)) + V = BCI->getOperand(0); + const AllocaInst *AI = dyn_cast(V); + // Don't handle byval struct arguments or VLAs, for example. + if (!AI) + return 0; + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI == FuncInfo.StaticAllocaMap.end()) + return 0; // VLAs. + int FI = SI->second; + + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (!DI.getDebugLoc().isUnknown() && MMI.hasDebugInfo()) + MMI.setVariableDbgInfo(Variable, FI, DI.getDebugLoc()); + return 0; + } + case Intrinsic::eh_exception: { + // Insert the EXCEPTIONADDR instruction. + assert(FuncInfo.MBB->isLandingPad() && + "Call to eh.exception not in landing pad!"); + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDValue Ops[1]; + Ops[0] = DAG.getRoot(); + SDValue Op = DAG.getNode(ISD::EXCEPTIONADDR, dl, VTs, Ops, 1); + setValue(&I, Op); + DAG.setRoot(Op.getValue(1)); + return 0; + } + + case Intrinsic::eh_selector: { + MachineBasicBlock *CallMBB = FuncInfo.MBB; + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (CallMBB->isLandingPad()) + AddCatchInfo(I, &MMI, CallMBB); + else { +#ifndef NDEBUG + FuncInfo.CatchInfoLost.insert(&I); +#endif + // FIXME: Mark exception selector register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionSelectorRegister(); + if (Reg) FuncInfo.MBB->addLiveIn(Reg); + } + + // Insert the EHSELECTION instruction. + SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); + SDValue Ops[2]; + Ops[0] = getValue(I.getArgOperand(0)); + Ops[1] = getRoot(); + SDValue Op = DAG.getNode(ISD::EHSELECTION, dl, VTs, Ops, 2); + DAG.setRoot(Op.getValue(1)); + setValue(&I, DAG.getSExtOrTrunc(Op, dl, MVT::i32)); + return 0; + } + + case Intrinsic::eh_typeid_for: { + // Find the type id for the given typeinfo. + GlobalVariable *GV = ExtractTypeInfo(I.getArgOperand(0)); + unsigned TypeID = DAG.getMachineFunction().getMMI().getTypeIDFor(GV); + Res = DAG.getConstant(TypeID, MVT::i32); + setValue(&I, Res); + return 0; + } + + case Intrinsic::eh_return_i32: + case Intrinsic::eh_return_i64: + DAG.getMachineFunction().getMMI().setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, dl, + MVT::Other, + getControlRoot(), + getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1)))); + return 0; + case Intrinsic::eh_unwind_init: + DAG.getMachineFunction().getMMI().setCallsUnwindInit(true); + return 0; + case Intrinsic::eh_dwarf_cfa: { + SDValue CfaArg = DAG.getSExtOrTrunc(getValue(I.getArgOperand(0)), dl, + TLI.getPointerTy()); + SDValue Offset = DAG.getNode(ISD::ADD, dl, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET, dl, + TLI.getPointerTy()), + CfaArg); + SDValue FA = DAG.getNode(ISD::FRAMEADDR, dl, + TLI.getPointerTy(), + DAG.getConstant(0, TLI.getPointerTy())); + setValue(&I, DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), + FA, Offset)); + return 0; + } + case Intrinsic::eh_sjlj_callsite: { + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + ConstantInt *CI = dyn_cast(I.getArgOperand(0)); + assert(CI && "Non-constant call site value in eh.sjlj.callsite!"); + assert(MMI.getCurrentCallSite() == 0 && "Overlapping call sites!"); + + MMI.setCurrentCallSite(CI->getZExtValue()); + return 0; + } + case Intrinsic::eh_sjlj_setjmp: { + setValue(&I, DAG.getNode(ISD::EH_SJLJ_SETJMP, dl, MVT::i32, getRoot(), + getValue(I.getArgOperand(0)))); + return 0; + } + case Intrinsic::eh_sjlj_longjmp: { + DAG.setRoot(DAG.getNode(ISD::EH_SJLJ_LONGJMP, dl, MVT::Other, + getRoot(), getValue(I.getArgOperand(0)))); + return 0; + } + case Intrinsic::eh_sjlj_dispatch_setup: { + DAG.setRoot(DAG.getNode(ISD::EH_SJLJ_DISPATCHSETUP, dl, MVT::Other, + getRoot(), getValue(I.getArgOperand(0)))); + return 0; + } + + case Intrinsic::x86_mmx_pslli_w: + case Intrinsic::x86_mmx_pslli_d: + case Intrinsic::x86_mmx_pslli_q: + case Intrinsic::x86_mmx_psrli_w: + case Intrinsic::x86_mmx_psrli_d: + case Intrinsic::x86_mmx_psrli_q: + case Intrinsic::x86_mmx_psrai_w: + case Intrinsic::x86_mmx_psrai_d: { + SDValue ShAmt = getValue(I.getArgOperand(1)); + if (isa(ShAmt)) { + visitTargetIntrinsic(I, Intrinsic); + return 0; + } + unsigned NewIntrinsic = 0; + EVT ShAmtVT = MVT::v2i32; + switch (Intrinsic) { + case Intrinsic::x86_mmx_pslli_w: + NewIntrinsic = Intrinsic::x86_mmx_psll_w; + break; + case Intrinsic::x86_mmx_pslli_d: + NewIntrinsic = Intrinsic::x86_mmx_psll_d; + break; + case Intrinsic::x86_mmx_pslli_q: + NewIntrinsic = Intrinsic::x86_mmx_psll_q; + break; + case Intrinsic::x86_mmx_psrli_w: + NewIntrinsic = Intrinsic::x86_mmx_psrl_w; + break; + case Intrinsic::x86_mmx_psrli_d: + NewIntrinsic = Intrinsic::x86_mmx_psrl_d; + break; + case Intrinsic::x86_mmx_psrli_q: + NewIntrinsic = Intrinsic::x86_mmx_psrl_q; + break; + case Intrinsic::x86_mmx_psrai_w: + NewIntrinsic = Intrinsic::x86_mmx_psra_w; + break; + case Intrinsic::x86_mmx_psrai_d: + NewIntrinsic = Intrinsic::x86_mmx_psra_d; + break; + default: llvm_unreachable("Impossible intrinsic"); // Can't reach here. + } + + // The vector shift intrinsics with scalars uses 32b shift amounts but + // the sse2/mmx shift instructions reads 64 bits. Set the upper 32 bits + // to be zero. + // We must do this early because v2i32 is not a legal type. + DebugLoc dl = getCurDebugLoc(); + SDValue ShOps[2]; + ShOps[0] = ShAmt; + ShOps[1] = DAG.getConstant(0, MVT::i32); + ShAmt = DAG.getNode(ISD::BUILD_VECTOR, dl, ShAmtVT, &ShOps[0], 2); + EVT DestVT = TLI.getValueType(I.getType()); + ShAmt = DAG.getNode(ISD::BITCAST, dl, DestVT, ShAmt); + Res = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, + DAG.getConstant(NewIntrinsic, MVT::i32), + getValue(I.getArgOperand(0)), ShAmt); + setValue(&I, Res); + return 0; + } + case Intrinsic::convertff: + case Intrinsic::convertfsi: + case Intrinsic::convertfui: + case Intrinsic::convertsif: + case Intrinsic::convertuif: + case Intrinsic::convertss: + case Intrinsic::convertsu: + case Intrinsic::convertus: + case Intrinsic::convertuu: { + ISD::CvtCode Code = ISD::CVT_INVALID; + switch (Intrinsic) { + case Intrinsic::convertff: Code = ISD::CVT_FF; break; + case Intrinsic::convertfsi: Code = ISD::CVT_FS; break; + case Intrinsic::convertfui: Code = ISD::CVT_FU; break; + case Intrinsic::convertsif: Code = ISD::CVT_SF; break; + case Intrinsic::convertuif: Code = ISD::CVT_UF; break; + case Intrinsic::convertss: Code = ISD::CVT_SS; break; + case Intrinsic::convertsu: Code = ISD::CVT_SU; break; + case Intrinsic::convertus: Code = ISD::CVT_US; break; + case Intrinsic::convertuu: Code = ISD::CVT_UU; break; + } + EVT DestVT = TLI.getValueType(I.getType()); + const Value *Op1 = I.getArgOperand(0); + Res = DAG.getConvertRndSat(DestVT, getCurDebugLoc(), getValue(Op1), + DAG.getValueType(DestVT), + DAG.getValueType(getValue(Op1).getValueType()), + getValue(I.getArgOperand(1)), + getValue(I.getArgOperand(2)), + Code); + setValue(&I, Res); + return 0; + } + case Intrinsic::sqrt: + setValue(&I, DAG.getNode(ISD::FSQRT, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::powi: + setValue(&I, ExpandPowI(dl, getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1)), DAG)); + return 0; + case Intrinsic::sin: + setValue(&I, DAG.getNode(ISD::FSIN, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::cos: + setValue(&I, DAG.getNode(ISD::FCOS, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::log: + visitLog(I); + return 0; + case Intrinsic::log2: + visitLog2(I); + return 0; + case Intrinsic::log10: + visitLog10(I); + return 0; + case Intrinsic::exp: + visitExp(I); + return 0; + case Intrinsic::exp2: + visitExp2(I); + return 0; + case Intrinsic::pow: + visitPow(I); + return 0; + case Intrinsic::convert_to_fp16: + setValue(&I, DAG.getNode(ISD::FP32_TO_FP16, dl, + MVT::i16, getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::convert_from_fp16: + setValue(&I, DAG.getNode(ISD::FP16_TO_FP32, dl, + MVT::f32, getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::pcmarker: { + SDValue Tmp = getValue(I.getArgOperand(0)); + DAG.setRoot(DAG.getNode(ISD::PCMARKER, dl, MVT::Other, getRoot(), Tmp)); + return 0; + } + case Intrinsic::readcyclecounter: { + SDValue Op = getRoot(); + Res = DAG.getNode(ISD::READCYCLECOUNTER, dl, + DAG.getVTList(MVT::i64, MVT::Other), + &Op, 1); + setValue(&I, Res); + DAG.setRoot(Res.getValue(1)); + return 0; + } + case Intrinsic::bswap: + setValue(&I, DAG.getNode(ISD::BSWAP, dl, + getValue(I.getArgOperand(0)).getValueType(), + getValue(I.getArgOperand(0)))); + return 0; + case Intrinsic::cttz: { + SDValue Arg = getValue(I.getArgOperand(0)); + EVT Ty = Arg.getValueType(); + setValue(&I, DAG.getNode(ISD::CTTZ, dl, Ty, Arg)); + return 0; + } + case Intrinsic::ctlz: { + SDValue Arg = getValue(I.getArgOperand(0)); + EVT Ty = Arg.getValueType(); + setValue(&I, DAG.getNode(ISD::CTLZ, dl, Ty, Arg)); + return 0; + } + case Intrinsic::ctpop: { + SDValue Arg = getValue(I.getArgOperand(0)); + EVT Ty = Arg.getValueType(); + setValue(&I, DAG.getNode(ISD::CTPOP, dl, Ty, Arg)); + return 0; + } + case Intrinsic::stacksave: { + SDValue Op = getRoot(); + Res = DAG.getNode(ISD::STACKSAVE, dl, + DAG.getVTList(TLI.getPointerTy(), MVT::Other), &Op, 1); + setValue(&I, Res); + DAG.setRoot(Res.getValue(1)); + return 0; + } + case Intrinsic::stackrestore: { + Res = getValue(I.getArgOperand(0)); + DAG.setRoot(DAG.getNode(ISD::STACKRESTORE, dl, MVT::Other, getRoot(), Res)); + return 0; + } + case Intrinsic::stackprotector: { + // Emit code into the DAG to store the stack guard onto the stack. + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + EVT PtrTy = TLI.getPointerTy(); + + SDValue Src = getValue(I.getArgOperand(0)); // The guard's value. + AllocaInst *Slot = cast(I.getArgOperand(1)); + + int FI = FuncInfo.StaticAllocaMap[Slot]; + MFI->setStackProtectorIndex(FI); + + SDValue FIN = DAG.getFrameIndex(FI, PtrTy); + + // Store the stack protector onto the stack. + Res = DAG.getStore(getRoot(), getCurDebugLoc(), Src, FIN, + MachinePointerInfo::getFixedStack(FI), + true, false, 0); + setValue(&I, Res); + DAG.setRoot(Res); + return 0; + } + case Intrinsic::objectsize: { + // If we don't know by now, we're never going to know. + ConstantInt *CI = dyn_cast(I.getArgOperand(1)); + + assert(CI && "Non-constant type in __builtin_object_size?"); + + SDValue Arg = getValue(I.getCalledValue()); + EVT Ty = Arg.getValueType(); + + if (CI->isZero()) + Res = DAG.getConstant(-1ULL, Ty); + else + Res = DAG.getConstant(0, Ty); + + setValue(&I, Res); + return 0; + } + case Intrinsic::var_annotation: + // Discard annotate attributes + return 0; + + case Intrinsic::init_trampoline: { + const Function *F = cast(I.getArgOperand(1)->stripPointerCasts()); + + SDValue Ops[6]; + Ops[0] = getRoot(); + Ops[1] = getValue(I.getArgOperand(0)); + Ops[2] = getValue(I.getArgOperand(1)); + Ops[3] = getValue(I.getArgOperand(2)); + Ops[4] = DAG.getSrcValue(I.getArgOperand(0)); + Ops[5] = DAG.getSrcValue(F); + + Res = DAG.getNode(ISD::TRAMPOLINE, dl, + DAG.getVTList(TLI.getPointerTy(), MVT::Other), + Ops, 6); + + setValue(&I, Res); + DAG.setRoot(Res.getValue(1)); + return 0; + } + case Intrinsic::gcroot: + if (GFI) { + const Value *Alloca = I.getArgOperand(0); + const Constant *TypeMap = cast(I.getArgOperand(1)); + + FrameIndexSDNode *FI = cast(getValue(Alloca).getNode()); + GFI->addStackRoot(FI->getIndex(), TypeMap); + } + return 0; + case Intrinsic::gcread: + case Intrinsic::gcwrite: + llvm_unreachable("GC failed to lower gcread/gcwrite intrinsics!"); + return 0; + case Intrinsic::flt_rounds: + setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, dl, MVT::i32)); + return 0; + case Intrinsic::trap: + DAG.setRoot(DAG.getNode(ISD::TRAP, dl,MVT::Other, getRoot())); + return 0; + case Intrinsic::uadd_with_overflow: + return implVisitAluOverflow(I, ISD::UADDO); + case Intrinsic::sadd_with_overflow: + return implVisitAluOverflow(I, ISD::SADDO); + case Intrinsic::usub_with_overflow: + return implVisitAluOverflow(I, ISD::USUBO); + case Intrinsic::ssub_with_overflow: + return implVisitAluOverflow(I, ISD::SSUBO); + case Intrinsic::umul_with_overflow: + return implVisitAluOverflow(I, ISD::UMULO); + case Intrinsic::smul_with_overflow: + return implVisitAluOverflow(I, ISD::SMULO); + + case Intrinsic::prefetch: { + SDValue Ops[4]; + unsigned rw = cast(I.getArgOperand(1))->getZExtValue(); + Ops[0] = getRoot(); + Ops[1] = getValue(I.getArgOperand(0)); + Ops[2] = getValue(I.getArgOperand(1)); + Ops[3] = getValue(I.getArgOperand(2)); + DAG.setRoot(DAG.getMemIntrinsicNode(ISD::PREFETCH, dl, + DAG.getVTList(MVT::Other), + &Ops[0], 4, + EVT::getIntegerVT(*Context, 8), + MachinePointerInfo(I.getArgOperand(0)), + 0, /* align */ + false, /* volatile */ + rw==0, /* read */ + rw==1)); /* write */ + return 0; + } + case Intrinsic::memory_barrier: { + SDValue Ops[6]; + Ops[0] = getRoot(); + for (int x = 1; x < 6; ++x) + Ops[x] = getValue(I.getArgOperand(x - 1)); + + DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, dl, MVT::Other, &Ops[0], 6)); + return 0; + } + case Intrinsic::atomic_cmp_swap: { + SDValue Root = getRoot(); + SDValue L = + DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, getCurDebugLoc(), + getValue(I.getArgOperand(1)).getValueType().getSimpleVT(), + Root, + getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1)), + getValue(I.getArgOperand(2)), + MachinePointerInfo(I.getArgOperand(0))); + setValue(&I, L); + DAG.setRoot(L.getValue(1)); + return 0; + } + case Intrinsic::atomic_load_add: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_ADD); + case Intrinsic::atomic_load_sub: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_SUB); + case Intrinsic::atomic_load_or: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR); + case Intrinsic::atomic_load_xor: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR); + case Intrinsic::atomic_load_and: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_AND); + case Intrinsic::atomic_load_nand: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_NAND); + case Intrinsic::atomic_load_max: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MAX); + case Intrinsic::atomic_load_min: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN); + case Intrinsic::atomic_load_umin: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMIN); + case Intrinsic::atomic_load_umax: + return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMAX); + case Intrinsic::atomic_swap: + return implVisitBinaryAtomic(I, ISD::ATOMIC_SWAP); + + case Intrinsic::invariant_start: + case Intrinsic::lifetime_start: + // Discard region information. + setValue(&I, DAG.getUNDEF(TLI.getPointerTy())); + return 0; + case Intrinsic::invariant_end: + case Intrinsic::lifetime_end: + // Discard region information. + return 0; + } +} + +void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee, + bool isTailCall, + MachineBasicBlock *LandingPad) { + const PointerType *PT = cast(CS.getCalledValue()->getType()); + const FunctionType *FTy = cast(PT->getElementType()); + const Type *RetTy = FTy->getReturnType(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + MCSymbol *BeginLabel = 0; + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Args.reserve(CS.arg_size()); + + // Check whether the function can return without sret-demotion. + SmallVector Outs; + SmallVector Offsets; + GetReturnInfo(RetTy, CS.getAttributes().getRetAttributes(), + Outs, TLI, &Offsets); + + bool CanLowerReturn = TLI.CanLowerReturn(CS.getCallingConv(), + FTy->isVarArg(), Outs, FTy->getContext()); + + SDValue DemoteStackSlot; + int DemoteStackIdx = -100; + + if (!CanLowerReturn) { + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize( + FTy->getReturnType()); + unsigned Align = TLI.getTargetData()->getPrefTypeAlignment( + FTy->getReturnType()); + MachineFunction &MF = DAG.getMachineFunction(); + DemoteStackIdx = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); + const Type *StackSlotPtrType = PointerType::getUnqual(FTy->getReturnType()); + + DemoteStackSlot = DAG.getFrameIndex(DemoteStackIdx, TLI.getPointerTy()); + Entry.Node = DemoteStackSlot; + Entry.Ty = StackSlotPtrType; + Entry.isSExt = false; + Entry.isZExt = false; + Entry.isInReg = false; + Entry.isSRet = true; + Entry.isNest = false; + Entry.isByVal = false; + Entry.Alignment = Align; + Args.push_back(Entry); + RetTy = Type::getVoidTy(FTy->getContext()); + } + + for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); + i != e; ++i) { + SDValue ArgNode = getValue(*i); + Entry.Node = ArgNode; Entry.Ty = (*i)->getType(); + + unsigned attrInd = i - CS.arg_begin() + 1; + Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt); + Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt); + Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg); + Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet); + Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest); + Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal); + Entry.Alignment = CS.getParamAlignment(attrInd); + Args.push_back(Entry); + } + + if (LandingPad) { + // Insert a label before the invoke call to mark the try range. This can be + // used to detect deletion of the invoke via the MachineModuleInfo. + BeginLabel = MMI.getContext().CreateTempSymbol(); + + // For SjLj, keep track of which landing pads go with which invokes + // so as to maintain the ordering of pads in the LSDA. + unsigned CallSiteIndex = MMI.getCurrentCallSite(); + if (CallSiteIndex) { + MMI.setCallSiteBeginLabel(BeginLabel, CallSiteIndex); + // Now that the call site is handled, stop tracking it. + MMI.setCurrentCallSite(0); + } + + // Both PendingLoads and PendingExports must be flushed here; + // this call might not return. + (void)getRoot(); + DAG.setRoot(DAG.getEHLabel(getCurDebugLoc(), getControlRoot(), BeginLabel)); + } + + // Check if target-independent constraints permit a tail call here. + // Target-dependent constraints are checked within TLI.LowerCallTo. + if (isTailCall && + !isInTailCallPosition(CS, CS.getAttributes().getRetAttributes(), TLI)) + isTailCall = false; + + // If there's a possibility that fast-isel has already selected some amount + // of the current basic block, don't emit a tail call. + if (isTailCall && EnableFastISel) + isTailCall = false; + + std::pair Result = + TLI.LowerCallTo(getRoot(), RetTy, + CS.paramHasAttr(0, Attribute::SExt), + CS.paramHasAttr(0, Attribute::ZExt), FTy->isVarArg(), + CS.paramHasAttr(0, Attribute::InReg), FTy->getNumParams(), + CS.getCallingConv(), + isTailCall, + !CS.getInstruction()->use_empty(), + Callee, Args, DAG, getCurDebugLoc()); + assert((isTailCall || Result.second.getNode()) && + "Non-null chain expected with non-tail call!"); + assert((Result.second.getNode() || !Result.first.getNode()) && + "Null value expected with tail call!"); + if (Result.first.getNode()) { + setValue(CS.getInstruction(), Result.first); + } else if (!CanLowerReturn && Result.second.getNode()) { + // The instruction result is the result of loading from the + // hidden sret parameter. + SmallVector PVTs; + const Type *PtrRetTy = PointerType::getUnqual(FTy->getReturnType()); + + ComputeValueVTs(TLI, PtrRetTy, PVTs); + assert(PVTs.size() == 1 && "Pointers should fit in one register"); + EVT PtrVT = PVTs[0]; + unsigned NumValues = Outs.size(); + SmallVector Values(NumValues); + SmallVector Chains(NumValues); + + for (unsigned i = 0; i < NumValues; ++i) { + SDValue Add = DAG.getNode(ISD::ADD, getCurDebugLoc(), PtrVT, + DemoteStackSlot, + DAG.getConstant(Offsets[i], PtrVT)); + SDValue L = DAG.getLoad(Outs[i].VT, getCurDebugLoc(), Result.second, + Add, + MachinePointerInfo::getFixedStack(DemoteStackIdx, Offsets[i]), + false, false, 1); + Values[i] = L; + Chains[i] = L.getValue(1); + } + + SDValue Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), + MVT::Other, &Chains[0], NumValues); + PendingLoads.push_back(Chain); + + // Collect the legal value parts into potentially illegal values + // that correspond to the original function's return values. + SmallVector RetTys; + RetTy = FTy->getReturnType(); + ComputeValueVTs(TLI, RetTy, RetTys); + ISD::NodeType AssertOp = ISD::DELETED_NODE; + SmallVector ReturnValues; + unsigned CurReg = 0; + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = TLI.getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(RetTy->getContext(), VT); + + SDValue ReturnValue = + getCopyFromParts(DAG, getCurDebugLoc(), &Values[CurReg], NumRegs, + RegisterVT, VT, AssertOp); + ReturnValues.push_back(ReturnValue); + CurReg += NumRegs; + } + + setValue(CS.getInstruction(), + DAG.getNode(ISD::MERGE_VALUES, getCurDebugLoc(), + DAG.getVTList(&RetTys[0], RetTys.size()), + &ReturnValues[0], ReturnValues.size())); + + } + + // As a special case, a null chain means that a tail call has been emitted and + // the DAG root is already updated. + if (Result.second.getNode()) + DAG.setRoot(Result.second); + else + HasTailCall = true; + + if (LandingPad) { + // Insert a label at the end of the invoke call to mark the try range. This + // can be used to detect deletion of the invoke via the MachineModuleInfo. + MCSymbol *EndLabel = MMI.getContext().CreateTempSymbol(); + DAG.setRoot(DAG.getEHLabel(getCurDebugLoc(), getRoot(), EndLabel)); + + // Inform MachineModuleInfo of range. + MMI.addInvoke(LandingPad, BeginLabel, EndLabel); + } +} + +/// IsOnlyUsedInZeroEqualityComparison - Return true if it only matters that the +/// value is equal or not-equal to zero. +static bool IsOnlyUsedInZeroEqualityComparison(const Value *V) { + for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); + UI != E; ++UI) { + if (const ICmpInst *IC = dyn_cast(*UI)) + if (IC->isEquality()) + if (const Constant *C = dyn_cast(IC->getOperand(1))) + if (C->isNullValue()) + continue; + // Unknown instruction. + return false; + } + return true; +} + +static SDValue getMemCmpLoad(const Value *PtrVal, MVT LoadVT, + const Type *LoadTy, + SelectionDAGBuilder &Builder) { + + // Check to see if this load can be trivially constant folded, e.g. if the + // input is from a string literal. + if (const Constant *LoadInput = dyn_cast(PtrVal)) { + // Cast pointer to the type we really want to load. + LoadInput = ConstantExpr::getBitCast(const_cast(LoadInput), + PointerType::getUnqual(LoadTy)); + + if (const Constant *LoadCst = + ConstantFoldLoadFromConstPtr(const_cast(LoadInput), + Builder.TD)) + return Builder.getValue(LoadCst); + } + + // Otherwise, we have to emit the load. If the pointer is to unfoldable but + // still constant memory, the input chain can be the entry node. + SDValue Root; + bool ConstantMemory = false; + + // Do not serialize (non-volatile) loads of constant memory with anything. + if (Builder.AA->pointsToConstantMemory(PtrVal)) { + Root = Builder.DAG.getEntryNode(); + ConstantMemory = true; + } else { + // Do not serialize non-volatile loads against each other. + Root = Builder.DAG.getRoot(); + } + + SDValue Ptr = Builder.getValue(PtrVal); + SDValue LoadVal = Builder.DAG.getLoad(LoadVT, Builder.getCurDebugLoc(), Root, + Ptr, MachinePointerInfo(PtrVal), + false /*volatile*/, + false /*nontemporal*/, 1 /* align=1 */); + + if (!ConstantMemory) + Builder.PendingLoads.push_back(LoadVal.getValue(1)); + return LoadVal; +} + + +/// visitMemCmpCall - See if we can lower a call to memcmp in an optimized form. +/// If so, return true and lower it, otherwise return false and it will be +/// lowered like a normal call. +bool SelectionDAGBuilder::visitMemCmpCall(const CallInst &I) { + // Verify that the prototype makes sense. int memcmp(void*,void*,size_t) + if (I.getNumArgOperands() != 3) + return false; + + const Value *LHS = I.getArgOperand(0), *RHS = I.getArgOperand(1); + if (!LHS->getType()->isPointerTy() || !RHS->getType()->isPointerTy() || + !I.getArgOperand(2)->getType()->isIntegerTy() || + !I.getType()->isIntegerTy()) + return false; + + const ConstantInt *Size = dyn_cast(I.getArgOperand(2)); + + // memcmp(S1,S2,2) != 0 -> (*(short*)LHS != *(short*)RHS) != 0 + // memcmp(S1,S2,4) != 0 -> (*(int*)LHS != *(int*)RHS) != 0 + if (Size && IsOnlyUsedInZeroEqualityComparison(&I)) { + bool ActuallyDoIt = true; + MVT LoadVT; + const Type *LoadTy; + switch (Size->getZExtValue()) { + default: + LoadVT = MVT::Other; + LoadTy = 0; + ActuallyDoIt = false; + break; + case 2: + LoadVT = MVT::i16; + LoadTy = Type::getInt16Ty(Size->getContext()); + break; + case 4: + LoadVT = MVT::i32; + LoadTy = Type::getInt32Ty(Size->getContext()); + break; + case 8: + LoadVT = MVT::i64; + LoadTy = Type::getInt64Ty(Size->getContext()); + break; + /* + case 16: + LoadVT = MVT::v4i32; + LoadTy = Type::getInt32Ty(Size->getContext()); + LoadTy = VectorType::get(LoadTy, 4); + break; + */ + } + + // This turns into unaligned loads. We only do this if the target natively + // supports the MVT we'll be loading or if it is small enough (<= 4) that + // we'll only produce a small number of byte loads. + + // Require that we can find a legal MVT, and only do this if the target + // supports unaligned loads of that type. Expanding into byte loads would + // bloat the code. + if (ActuallyDoIt && Size->getZExtValue() > 4) { + // TODO: Handle 5 byte compare as 4-byte + 1 byte. + // TODO: Handle 8 byte compare on x86-32 as two 32-bit loads. + if (!TLI.isTypeLegal(LoadVT) ||!TLI.allowsUnalignedMemoryAccesses(LoadVT)) + ActuallyDoIt = false; + } + + if (ActuallyDoIt) { + SDValue LHSVal = getMemCmpLoad(LHS, LoadVT, LoadTy, *this); + SDValue RHSVal = getMemCmpLoad(RHS, LoadVT, LoadTy, *this); + + SDValue Res = DAG.getSetCC(getCurDebugLoc(), MVT::i1, LHSVal, RHSVal, + ISD::SETNE); + EVT CallVT = TLI.getValueType(I.getType(), true); + setValue(&I, DAG.getZExtOrTrunc(Res, getCurDebugLoc(), CallVT)); + return true; + } + } + + + return false; +} + + +void SelectionDAGBuilder::visitCall(const CallInst &I) { + // Handle inline assembly differently. + if (isa(I.getCalledValue())) { + visitInlineAsm(&I); + return; + } + + // See if any floating point values are being passed to this function. This is + // used to emit an undefined reference to fltused on Windows. + const FunctionType *FT = + cast(I.getCalledValue()->getType()->getContainedType(0)); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + if (FT->isVarArg() && + !MMI.callsExternalVAFunctionWithFloatingPointArguments()) { + for (unsigned i = 0, e = I.getNumArgOperands(); i != e; ++i) { + const Type* T = I.getArgOperand(i)->getType(); + for (po_iterator i = po_begin(T), e = po_end(T); + i != e; ++i) { + if (!i->isFloatingPointTy()) continue; + MMI.setCallsExternalVAFunctionWithFloatingPointArguments(true); + break; + } + } + } + + const char *RenameFn = 0; + if (Function *F = I.getCalledFunction()) { + if (F->isDeclaration()) { + if (const TargetIntrinsicInfo *II = TM.getIntrinsicInfo()) { + if (unsigned IID = II->getIntrinsicID(F)) { + RenameFn = visitIntrinsicCall(I, IID); + if (!RenameFn) + return; + } + } + if (unsigned IID = F->getIntrinsicID()) { + RenameFn = visitIntrinsicCall(I, IID); + if (!RenameFn) + return; + } + } + + // Check for well-known libc/libm calls. If the function is internal, it + // can't be a library call. + if (!F->hasLocalLinkage() && F->hasName()) { + StringRef Name = F->getName(); + if (Name == "copysign" || Name == "copysignf" || Name == "copysignl") { + if (I.getNumArgOperands() == 2 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && + I.getType() == I.getArgOperand(1)->getType()) { + SDValue LHS = getValue(I.getArgOperand(0)); + SDValue RHS = getValue(I.getArgOperand(1)); + setValue(&I, DAG.getNode(ISD::FCOPYSIGN, getCurDebugLoc(), + LHS.getValueType(), LHS, RHS)); + return; + } + } else if (Name == "fabs" || Name == "fabsf" || Name == "fabsl") { + if (I.getNumArgOperands() == 1 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType()) { + SDValue Tmp = getValue(I.getArgOperand(0)); + setValue(&I, DAG.getNode(ISD::FABS, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "sin" || Name == "sinf" || Name == "sinl") { + if (I.getNumArgOperands() == 1 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getArgOperand(0)); + setValue(&I, DAG.getNode(ISD::FSIN, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "cos" || Name == "cosf" || Name == "cosl") { + if (I.getNumArgOperands() == 1 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getArgOperand(0)); + setValue(&I, DAG.getNode(ISD::FCOS, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") { + if (I.getNumArgOperands() == 1 && // Basic sanity checks. + I.getArgOperand(0)->getType()->isFloatingPointTy() && + I.getType() == I.getArgOperand(0)->getType() && + I.onlyReadsMemory()) { + SDValue Tmp = getValue(I.getArgOperand(0)); + setValue(&I, DAG.getNode(ISD::FSQRT, getCurDebugLoc(), + Tmp.getValueType(), Tmp)); + return; + } + } else if (Name == "memcmp") { + if (visitMemCmpCall(I)) + return; + } + } + } + + SDValue Callee; + if (!RenameFn) + Callee = getValue(I.getCalledValue()); + else + Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy()); + + // Check if we can potentially perform a tail call. More detailed checking is + // be done within LowerCallTo, after more information about the call is known. + LowerCallTo(&I, Callee, I.isTailCall()); +} + +namespace llvm { + +/// AsmOperandInfo - This contains information for each constraint that we are +/// lowering. +class LLVM_LIBRARY_VISIBILITY SDISelAsmOperandInfo : + public TargetLowering::AsmOperandInfo { +public: + /// CallOperand - If this is the result output operand or a clobber + /// this is null, otherwise it is the incoming operand to the CallInst. + /// This gets modified as the asm is processed. + SDValue CallOperand; + + /// AssignedRegs - If this is a register or register class operand, this + /// contains the set of register corresponding to the operand. + RegsForValue AssignedRegs; + + explicit SDISelAsmOperandInfo(const TargetLowering::AsmOperandInfo &info) + : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) { + } + + /// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers + /// busy in OutputRegs/InputRegs. + void MarkAllocatedRegs(bool isOutReg, bool isInReg, + std::set &OutputRegs, + std::set &InputRegs, + const TargetRegisterInfo &TRI) const { + if (isOutReg) { + for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i) + MarkRegAndAliases(AssignedRegs.Regs[i], OutputRegs, TRI); + } + if (isInReg) { + for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i) + MarkRegAndAliases(AssignedRegs.Regs[i], InputRegs, TRI); + } + } + + /// getCallOperandValEVT - Return the EVT of the Value* that this operand + /// corresponds to. If there is no Value* for this operand, it returns + /// MVT::Other. + EVT getCallOperandValEVT(LLVMContext &Context, + const TargetLowering &TLI, + const TargetData *TD) const { + if (CallOperandVal == 0) return MVT::Other; + + if (isa(CallOperandVal)) + return TLI.getPointerTy(); + + const llvm::Type *OpTy = CallOperandVal->getType(); + + // If this is an indirect operand, the operand is a pointer to the + // accessed type. + if (isIndirect) { + const llvm::PointerType *PtrTy = dyn_cast(OpTy); + if (!PtrTy) + report_fatal_error("Indirect operand for inline asm not a pointer!"); + OpTy = PtrTy->getElementType(); + } + + // If OpTy is not a single value, it may be a struct/union that we + // can tile with integers. + if (!OpTy->isSingleValueType() && OpTy->isSized()) { + unsigned BitSize = TD->getTypeSizeInBits(OpTy); + switch (BitSize) { + default: break; + case 1: + case 8: + case 16: + case 32: + case 64: + case 128: + OpTy = IntegerType::get(Context, BitSize); + break; + } + } + + return TLI.getValueType(OpTy, true); + } + +private: + /// MarkRegAndAliases - Mark the specified register and all aliases in the + /// specified set. + static void MarkRegAndAliases(unsigned Reg, std::set &Regs, + const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::isPhysicalRegister(Reg) && "Isn't a physreg"); + Regs.insert(Reg); + if (const unsigned *Aliases = TRI.getAliasSet(Reg)) + for (; *Aliases; ++Aliases) + Regs.insert(*Aliases); + } +}; + +typedef SmallVector SDISelAsmOperandInfoVector; + +} // end llvm namespace. + +/// isAllocatableRegister - If the specified register is safe to allocate, +/// i.e. it isn't a stack pointer or some other special register, return the +/// register class for the register. Otherwise, return null. +static const TargetRegisterClass * +isAllocatableRegister(unsigned Reg, MachineFunction &MF, + const TargetLowering &TLI, + const TargetRegisterInfo *TRI) { + EVT FoundVT = MVT::Other; + const TargetRegisterClass *FoundRC = 0; + for (TargetRegisterInfo::regclass_iterator RCI = TRI->regclass_begin(), + E = TRI->regclass_end(); RCI != E; ++RCI) { + EVT ThisVT = MVT::Other; + + const TargetRegisterClass *RC = *RCI; + // If none of the value types for this register class are valid, we + // can't use it. For example, 64-bit reg classes on 32-bit targets. + for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); + I != E; ++I) { + if (TLI.isTypeLegal(*I)) { + // If we have already found this register in a different register class, + // choose the one with the largest VT specified. For example, on + // PowerPC, we favor f64 register classes over f32. + if (FoundVT == MVT::Other || FoundVT.bitsLT(*I)) { + ThisVT = *I; + break; + } + } + } + + if (ThisVT == MVT::Other) continue; + + // NOTE: This isn't ideal. In particular, this might allocate the + // frame pointer in functions that need it (due to them not being taken + // out of allocation, because a variable sized allocation hasn't been seen + // yet). This is a slight code pessimization, but should still work. + for (TargetRegisterClass::iterator I = RC->allocation_order_begin(MF), + E = RC->allocation_order_end(MF); I != E; ++I) + if (*I == Reg) { + // We found a matching register class. Keep looking at others in case + // we find one with larger registers that this physreg is also in. + FoundRC = RC; + FoundVT = ThisVT; + break; + } + } + return FoundRC; +} + +/// GetRegistersForValue - Assign registers (virtual or physical) for the +/// specified operand. We prefer to assign virtual registers, to allow the +/// register allocator to handle the assignment process. However, if the asm +/// uses features that we can't model on machineinstrs, we have SDISel do the +/// allocation. This produces generally horrible, but correct, code. +/// +/// OpInfo describes the operand. +/// Input and OutputRegs are the set of already allocated physical registers. +/// +void SelectionDAGBuilder:: +GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, + std::set &OutputRegs, + std::set &InputRegs) { + LLVMContext &Context = FuncInfo.Fn->getContext(); + + // Compute whether this value requires an input register, an output register, + // or both. + bool isOutReg = false; + bool isInReg = false; + switch (OpInfo.Type) { + case InlineAsm::isOutput: + isOutReg = true; + + // If there is an input constraint that matches this, we need to reserve + // the input register so no other inputs allocate to it. + isInReg = OpInfo.hasMatchingInput(); + break; + case InlineAsm::isInput: + isInReg = true; + isOutReg = false; + break; + case InlineAsm::isClobber: + isOutReg = true; + isInReg = true; + break; + } + + + MachineFunction &MF = DAG.getMachineFunction(); + SmallVector Regs; + + // If this is a constraint for a single physreg, or a constraint for a + // register class, find it. + std::pair PhysReg = + TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode, + OpInfo.ConstraintVT); + + unsigned NumRegs = 1; + if (OpInfo.ConstraintVT != MVT::Other) { + // If this is a FP input in an integer register (or visa versa) insert a bit + // cast of the input value. More generally, handle any case where the input + // value disagrees with the register class we plan to stick this in. + if (OpInfo.Type == InlineAsm::isInput && + PhysReg.second && !PhysReg.second->hasType(OpInfo.ConstraintVT)) { + // Try to convert to the first EVT that the reg class contains. If the + // types are identical size, use a bitcast to convert (e.g. two differing + // vector types). + EVT RegVT = *PhysReg.second->vt_begin(); + if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) { + OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + RegVT, OpInfo.CallOperand); + OpInfo.ConstraintVT = RegVT; + } else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) { + // If the input is a FP value and we want it in FP registers, do a + // bitcast to the corresponding integer type. This turns an f64 value + // into i64, which can be passed with two i32 values on a 32-bit + // machine. + RegVT = EVT::getIntegerVT(Context, + OpInfo.ConstraintVT.getSizeInBits()); + OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + RegVT, OpInfo.CallOperand); + OpInfo.ConstraintVT = RegVT; + } + } + + NumRegs = TLI.getNumRegisters(Context, OpInfo.ConstraintVT); + } + + EVT RegVT; + EVT ValueVT = OpInfo.ConstraintVT; + + // If this is a constraint for a specific physical register, like {r17}, + // assign it now. + if (unsigned AssignedReg = PhysReg.first) { + const TargetRegisterClass *RC = PhysReg.second; + if (OpInfo.ConstraintVT == MVT::Other) + ValueVT = *RC->vt_begin(); + + // Get the actual register value type. This is important, because the user + // may have asked for (e.g.) the AX register in i32 type. We need to + // remember that AX is actually i16 to get the right extension. + RegVT = *RC->vt_begin(); + + // This is a explicit reference to a physical register. + Regs.push_back(AssignedReg); + + // If this is an expanded reference, add the rest of the regs to Regs. + if (NumRegs != 1) { + TargetRegisterClass::iterator I = RC->begin(); + for (; *I != AssignedReg; ++I) + assert(I != RC->end() && "Didn't find reg!"); + + // Already added the first reg. + --NumRegs; ++I; + for (; NumRegs; --NumRegs, ++I) { + assert(I != RC->end() && "Ran out of registers to allocate!"); + Regs.push_back(*I); + } + } + + OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT); + const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); + return; + } + + // Otherwise, if this was a reference to an LLVM register class, create vregs + // for this reference. + if (const TargetRegisterClass *RC = PhysReg.second) { + RegVT = *RC->vt_begin(); + if (OpInfo.ConstraintVT == MVT::Other) + ValueVT = RegVT; + + // Create the appropriate number of virtual registers. + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + for (; NumRegs; --NumRegs) + Regs.push_back(RegInfo.createVirtualRegister(RC)); + + OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT); + return; + } + + // This is a reference to a register class that doesn't directly correspond + // to an LLVM register class. Allocate NumRegs consecutive, available, + // registers from the class. + std::vector RegClassRegs + = TLI.getRegClassForInlineAsmConstraint(OpInfo.ConstraintCode, + OpInfo.ConstraintVT); + + const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo(); + unsigned NumAllocated = 0; + for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) { + unsigned Reg = RegClassRegs[i]; + // See if this register is available. + if ((isOutReg && OutputRegs.count(Reg)) || // Already used. + (isInReg && InputRegs.count(Reg))) { // Already used. + // Make sure we find consecutive registers. + NumAllocated = 0; + continue; + } + + // Check to see if this register is allocatable (i.e. don't give out the + // stack pointer). + const TargetRegisterClass *RC = isAllocatableRegister(Reg, MF, TLI, TRI); + if (!RC) { // Couldn't allocate this register. + // Reset NumAllocated to make sure we return consecutive registers. + NumAllocated = 0; + continue; + } + + // Okay, this register is good, we can use it. + ++NumAllocated; + + // If we allocated enough consecutive registers, succeed. + if (NumAllocated == NumRegs) { + unsigned RegStart = (i-NumAllocated)+1; + unsigned RegEnd = i+1; + // Mark all of the allocated registers used. + for (unsigned i = RegStart; i != RegEnd; ++i) + Regs.push_back(RegClassRegs[i]); + + OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(), + OpInfo.ConstraintVT); + OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI); + return; + } + } + + // Otherwise, we couldn't allocate enough registers for this. +} + +/// visitInlineAsm - Handle a call to an InlineAsm object. +/// +void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { + const InlineAsm *IA = cast(CS.getCalledValue()); + + /// ConstraintOperands - Information about all of the constraints. + SDISelAsmOperandInfoVector ConstraintOperands; + + std::set OutputRegs, InputRegs; + + TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(CS); + bool hasMemory = false; + + unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. + unsigned ResNo = 0; // ResNo - The result number of the next output. + for (unsigned i = 0, e = TargetConstraints.size(); i != e; ++i) { + ConstraintOperands.push_back(SDISelAsmOperandInfo(TargetConstraints[i])); + SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back(); + + EVT OpVT = MVT::Other; + + // Compute the value type for each operand. + switch (OpInfo.Type) { + case InlineAsm::isOutput: + // Indirect outputs just consume an argument. + if (OpInfo.isIndirect) { + OpInfo.CallOperandVal = const_cast(CS.getArgument(ArgNo++)); + break; + } + + // The return value of the call is this value. As such, there is no + // corresponding argument. + assert(!CS.getType()->isVoidTy() && + "Bad inline asm!"); + if (const StructType *STy = dyn_cast(CS.getType())) { + OpVT = TLI.getValueType(STy->getElementType(ResNo)); + } else { + assert(ResNo == 0 && "Asm only has one result!"); + OpVT = TLI.getValueType(CS.getType()); + } + ++ResNo; + break; + case InlineAsm::isInput: + OpInfo.CallOperandVal = const_cast(CS.getArgument(ArgNo++)); + break; + case InlineAsm::isClobber: + // Nothing to do. + break; + } + + // If this is an input or an indirect output, process the call argument. + // BasicBlocks are labels, currently appearing only in asm's. + if (OpInfo.CallOperandVal) { + if (const BasicBlock *BB = dyn_cast(OpInfo.CallOperandVal)) { + OpInfo.CallOperand = DAG.getBasicBlock(FuncInfo.MBBMap[BB]); + } else { + OpInfo.CallOperand = getValue(OpInfo.CallOperandVal); + } + + OpVT = OpInfo.getCallOperandValEVT(*DAG.getContext(), TLI, TD); + } + + OpInfo.ConstraintVT = OpVT; + + // Indirect operand accesses access memory. + if (OpInfo.isIndirect) + hasMemory = true; + else { + for (unsigned j = 0, ee = OpInfo.Codes.size(); j != ee; ++j) { + TargetLowering::ConstraintType CType = TLI.getConstraintType(OpInfo.Codes[j]); + if (CType == TargetLowering::C_Memory) { + hasMemory = true; + break; + } + } + } + } + + SDValue Chain, Flag; + + // We won't need to flush pending loads if this asm doesn't touch + // memory and is nonvolatile. + if (hasMemory || IA->hasSideEffects()) + Chain = getRoot(); + else + Chain = DAG.getRoot(); + + // Second pass over the constraints: compute which constraint option to use + // and assign registers to constraints that want a specific physreg. + for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + // If this is an output operand with a matching input operand, look up the + // matching input. If their types mismatch, e.g. one is an integer, the + // other is floating point, or their sizes are different, flag it as an + // error. + if (OpInfo.hasMatchingInput()) { + SDISelAsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; + + if (OpInfo.ConstraintVT != Input.ConstraintVT) { + if ((OpInfo.ConstraintVT.isInteger() != + Input.ConstraintVT.isInteger()) || + (OpInfo.ConstraintVT.getSizeInBits() != + Input.ConstraintVT.getSizeInBits())) { + report_fatal_error("Unsupported asm: input constraint" + " with a matching output constraint of" + " incompatible type!"); + } + Input.ConstraintVT = OpInfo.ConstraintVT; + } + } + + // Compute the constraint code and ConstraintType to use. + TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG); + + // If this is a memory input, and if the operand is not indirect, do what we + // need to to provide an address for the memory input. + if (OpInfo.ConstraintType == TargetLowering::C_Memory && + !OpInfo.isIndirect) { + assert((OpInfo.isMultipleAlternative || (OpInfo.Type == InlineAsm::isInput)) && + "Can only indirectify direct input operands!"); + + // Memory operands really want the address of the value. If we don't have + // an indirect input, put it in the constpool if we can, otherwise spill + // it to a stack slot. + + // If the operand is a float, integer, or vector constant, spill to a + // constant pool entry to get its address. + const Value *OpVal = OpInfo.CallOperandVal; + if (isa(OpVal) || isa(OpVal) || + isa(OpVal)) { + OpInfo.CallOperand = DAG.getConstantPool(cast(OpVal), + TLI.getPointerTy()); + } else { + // Otherwise, create a stack slot and emit a store to it before the + // asm. + const Type *Ty = OpVal->getType(); + uint64_t TySize = TLI.getTargetData()->getTypeAllocSize(Ty); + unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty); + MachineFunction &MF = DAG.getMachineFunction(); + int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); + SDValue StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); + Chain = DAG.getStore(Chain, getCurDebugLoc(), + OpInfo.CallOperand, StackSlot, + MachinePointerInfo::getFixedStack(SSFI), + false, false, 0); + OpInfo.CallOperand = StackSlot; + } + + // There is no longer a Value* corresponding to this operand. + OpInfo.CallOperandVal = 0; + + // It is now an indirect operand. + OpInfo.isIndirect = true; + } + + // If this constraint is for a specific register, allocate it before + // anything else. + if (OpInfo.ConstraintType == TargetLowering::C_Register) + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + } + + // Second pass - Loop over all of the operands, assigning virtual or physregs + // to register class operands. + for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + // C_Register operands have already been allocated, Other/Memory don't need + // to be. + if (OpInfo.ConstraintType == TargetLowering::C_RegisterClass) + GetRegistersForValue(OpInfo, OutputRegs, InputRegs); + } + + // AsmNodeOperands - The operands for the ISD::INLINEASM node. + std::vector AsmNodeOperands; + AsmNodeOperands.push_back(SDValue()); // reserve space for input chain + AsmNodeOperands.push_back( + DAG.getTargetExternalSymbol(IA->getAsmString().c_str(), + TLI.getPointerTy())); + + // If we have a !srcloc metadata node associated with it, we want to attach + // this to the ultimately generated inline asm machineinstr. To do this, we + // pass in the third operand as this (potentially null) inline asm MDNode. + const MDNode *SrcLoc = CS.getInstruction()->getMetadata("srcloc"); + AsmNodeOperands.push_back(DAG.getMDNode(SrcLoc)); + + // Remember the HasSideEffect and AlignStack bits as operand 3. + unsigned ExtraInfo = 0; + if (IA->hasSideEffects()) + ExtraInfo |= InlineAsm::Extra_HasSideEffects; + if (IA->isAlignStack()) + ExtraInfo |= InlineAsm::Extra_IsAlignStack; + AsmNodeOperands.push_back(DAG.getTargetConstant(ExtraInfo, + TLI.getPointerTy())); + + // Loop over all of the inputs, copying the operand values into the + // appropriate registers and processing the output regs. + RegsForValue RetValRegs; + + // IndirectStoresToEmit - The set of stores to emit after the inline asm node. + std::vector > IndirectStoresToEmit; + + for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) { + SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i]; + + switch (OpInfo.Type) { + case InlineAsm::isOutput: { + if (OpInfo.ConstraintType != TargetLowering::C_RegisterClass && + OpInfo.ConstraintType != TargetLowering::C_Register) { + // Memory output, or 'other' output (e.g. 'X' constraint). + assert(OpInfo.isIndirect && "Memory output must be indirect operand"); + + // Add information to the INLINEASM node to know about this output. + unsigned OpFlags = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1); + AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlags, + TLI.getPointerTy())); + AsmNodeOperands.push_back(OpInfo.CallOperand); + break; + } + + // Otherwise, this is a register or register class output. + + // Copy the output from the appropriate register. Find a register that + // we can use. + if (OpInfo.AssignedRegs.Regs.empty()) + report_fatal_error("Couldn't allocate output reg for constraint '" + + Twine(OpInfo.ConstraintCode) + "'!"); + + // If this is an indirect operand, store through the pointer after the + // asm. + if (OpInfo.isIndirect) { + IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs, + OpInfo.CallOperandVal)); + } else { + // This is the result value of the call. + assert(!CS.getType()->isVoidTy() && "Bad inline asm!"); + // Concatenate this output onto the outputs list. + RetValRegs.append(OpInfo.AssignedRegs); + } + + // Add information to the INLINEASM node to know that this register is + // set. + OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ? + InlineAsm::Kind_RegDefEarlyClobber : + InlineAsm::Kind_RegDef, + false, + 0, + DAG, + AsmNodeOperands); + break; + } + case InlineAsm::isInput: { + SDValue InOperandVal = OpInfo.CallOperand; + + if (OpInfo.isMatchingInputConstraint()) { // Matching constraint? + // If this is required to match an output register we have already set, + // just use its register. + unsigned OperandNo = OpInfo.getMatchedOperand(); + + // Scan until we find the definition we already emitted of this operand. + // When we find it, create a RegsForValue operand. + unsigned CurOp = InlineAsm::Op_FirstOperand; + for (; OperandNo; --OperandNo) { + // Advance to the next operand. + unsigned OpFlag = + cast(AsmNodeOperands[CurOp])->getZExtValue(); + assert((InlineAsm::isRegDefKind(OpFlag) || + InlineAsm::isRegDefEarlyClobberKind(OpFlag) || + InlineAsm::isMemKind(OpFlag)) && "Skipped past definitions?"); + CurOp += InlineAsm::getNumOperandRegisters(OpFlag)+1; + } + + unsigned OpFlag = + cast(AsmNodeOperands[CurOp])->getZExtValue(); + if (InlineAsm::isRegDefKind(OpFlag) || + InlineAsm::isRegDefEarlyClobberKind(OpFlag)) { + // Add (OpFlag&0xffff)>>3 registers to MatchedRegs. + if (OpInfo.isIndirect) { + // This happens on gcc/testsuite/gcc.dg/pr8788-1.c + LLVMContext &Ctx = *DAG.getContext(); + Ctx.emitError(CS.getInstruction(), "inline asm not supported yet:" + " don't know how to handle tied " + "indirect register inputs"); + } + + RegsForValue MatchedRegs; + MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType()); + EVT RegVT = AsmNodeOperands[CurOp+1].getValueType(); + MatchedRegs.RegVTs.push_back(RegVT); + MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo(); + for (unsigned i = 0, e = InlineAsm::getNumOperandRegisters(OpFlag); + i != e; ++i) + MatchedRegs.Regs.push_back + (RegInfo.createVirtualRegister(TLI.getRegClassFor(RegVT))); + + // Use the produced MatchedRegs object to + MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), + Chain, &Flag); + MatchedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse, + true, OpInfo.getMatchedOperand(), + DAG, AsmNodeOperands); + break; + } + + assert(InlineAsm::isMemKind(OpFlag) && "Unknown matching constraint!"); + assert(InlineAsm::getNumOperandRegisters(OpFlag) == 1 && + "Unexpected number of operands"); + // Add information to the INLINEASM node to know about this input. + // See InlineAsm.h isUseOperandTiedToDef. + OpFlag = InlineAsm::getFlagWordForMatchingOp(OpFlag, + OpInfo.getMatchedOperand()); + AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag, + TLI.getPointerTy())); + AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]); + break; + } + + // Treat indirect 'X' constraint as memory. + if (OpInfo.ConstraintType == TargetLowering::C_Other && + OpInfo.isIndirect) + OpInfo.ConstraintType = TargetLowering::C_Memory; + + if (OpInfo.ConstraintType == TargetLowering::C_Other) { + std::vector Ops; + TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode[0], + Ops, DAG); + if (Ops.empty()) + report_fatal_error("Invalid operand for inline asm constraint '" + + Twine(OpInfo.ConstraintCode) + "'!"); + + // Add information to the INLINEASM node to know about this input. + unsigned ResOpType = + InlineAsm::getFlagWord(InlineAsm::Kind_Imm, Ops.size()); + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + TLI.getPointerTy())); + AsmNodeOperands.insert(AsmNodeOperands.end(), Ops.begin(), Ops.end()); + break; + } + + if (OpInfo.ConstraintType == TargetLowering::C_Memory) { + assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!"); + assert(InOperandVal.getValueType() == TLI.getPointerTy() && + "Memory operands expect pointer values"); + + // Add information to the INLINEASM node to know about this input. + unsigned ResOpType = InlineAsm::getFlagWord(InlineAsm::Kind_Mem, 1); + AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType, + TLI.getPointerTy())); + AsmNodeOperands.push_back(InOperandVal); + break; + } + + assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass || + OpInfo.ConstraintType == TargetLowering::C_Register) && + "Unknown constraint type!"); + assert(!OpInfo.isIndirect && + "Don't know how to handle indirect register inputs yet!"); + + // Copy the input into the appropriate registers. + if (OpInfo.AssignedRegs.Regs.empty() || + !OpInfo.AssignedRegs.areValueTypesLegal(TLI)) + report_fatal_error("Couldn't allocate input reg for constraint '" + + Twine(OpInfo.ConstraintCode) + "'!"); + + OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), + Chain, &Flag); + + OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse, false, 0, + DAG, AsmNodeOperands); + break; + } + case InlineAsm::isClobber: { + // Add the clobbered value to the operand list, so that the register + // allocator is aware that the physreg got clobbered. + if (!OpInfo.AssignedRegs.Regs.empty()) + OpInfo.AssignedRegs.AddInlineAsmOperands( + InlineAsm::Kind_RegDefEarlyClobber, + false, 0, DAG, + AsmNodeOperands); + break; + } + } + } + + // Finish up input operands. Set the input chain and add the flag last. + AsmNodeOperands[InlineAsm::Op_InputChain] = Chain; + if (Flag.getNode()) AsmNodeOperands.push_back(Flag); + + Chain = DAG.getNode(ISD::INLINEASM, getCurDebugLoc(), + DAG.getVTList(MVT::Other, MVT::Glue), + &AsmNodeOperands[0], AsmNodeOperands.size()); + Flag = Chain.getValue(1); + + // If this asm returns a register value, copy the result from that register + // and set it as the value of the call. + if (!RetValRegs.Regs.empty()) { + SDValue Val = RetValRegs.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), + Chain, &Flag); + + // FIXME: Why don't we do this for inline asms with MRVs? + if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) { + EVT ResultType = TLI.getValueType(CS.getType()); + + // If any of the results of the inline asm is a vector, it may have the + // wrong width/num elts. This can happen for register classes that can + // contain multiple different value types. The preg or vreg allocated may + // not have the same VT as was expected. Convert it to the right type + // with bit_convert. + if (ResultType != Val.getValueType() && Val.getValueType().isVector()) { + Val = DAG.getNode(ISD::BITCAST, getCurDebugLoc(), + ResultType, Val); + + } else if (ResultType != Val.getValueType() && + ResultType.isInteger() && Val.getValueType().isInteger()) { + // If a result value was tied to an input value, the computed result may + // have a wider width than the expected result. Extract the relevant + // portion. + Val = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), ResultType, Val); + } + + assert(ResultType == Val.getValueType() && "Asm result value mismatch!"); + } + + setValue(CS.getInstruction(), Val); + // Don't need to use this as a chain in this case. + if (!IA->hasSideEffects() && !hasMemory && IndirectStoresToEmit.empty()) + return; + } + + std::vector > StoresToEmit; + + // Process indirect outputs, first output all of the flagged copies out of + // physregs. + for (unsigned i = 0, e = IndirectStoresToEmit.size(); i != e; ++i) { + RegsForValue &OutRegs = IndirectStoresToEmit[i].first; + const Value *Ptr = IndirectStoresToEmit[i].second; + SDValue OutVal = OutRegs.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), + Chain, &Flag); + StoresToEmit.push_back(std::make_pair(OutVal, Ptr)); + } + + // Emit the non-flagged stores from the physregs. + SmallVector OutChains; + for (unsigned i = 0, e = StoresToEmit.size(); i != e; ++i) { + SDValue Val = DAG.getStore(Chain, getCurDebugLoc(), + StoresToEmit[i].first, + getValue(StoresToEmit[i].second), + MachinePointerInfo(StoresToEmit[i].second), + false, false, 0); + OutChains.push_back(Val); + } + + if (!OutChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, + &OutChains[0], OutChains.size()); + + DAG.setRoot(Chain); +} + +void SelectionDAGBuilder::visitVAStart(const CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VASTART, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getArgOperand(0)), + DAG.getSrcValue(I.getArgOperand(0)))); +} + +void SelectionDAGBuilder::visitVAArg(const VAArgInst &I) { + const TargetData &TD = *TLI.getTargetData(); + SDValue V = DAG.getVAArg(TLI.getValueType(I.getType()), getCurDebugLoc(), + getRoot(), getValue(I.getOperand(0)), + DAG.getSrcValue(I.getOperand(0)), + TD.getABITypeAlignment(I.getType())); + setValue(&I, V); + DAG.setRoot(V.getValue(1)); +} + +void SelectionDAGBuilder::visitVAEnd(const CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VAEND, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getArgOperand(0)), + DAG.getSrcValue(I.getArgOperand(0)))); +} + +void SelectionDAGBuilder::visitVACopy(const CallInst &I) { + DAG.setRoot(DAG.getNode(ISD::VACOPY, getCurDebugLoc(), + MVT::Other, getRoot(), + getValue(I.getArgOperand(0)), + getValue(I.getArgOperand(1)), + DAG.getSrcValue(I.getArgOperand(0)), + DAG.getSrcValue(I.getArgOperand(1)))); +} + +/// TargetLowering::LowerCallTo - This is the default LowerCallTo +/// implementation, which just calls LowerCall. +/// FIXME: When all targets are +/// migrated to using LowerCall, this hook should be integrated into SDISel. +std::pair +TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, + bool RetSExt, bool RetZExt, bool isVarArg, + bool isInreg, unsigned NumFixedArgs, + CallingConv::ID CallConv, bool isTailCall, + bool isReturnValueUsed, + SDValue Callee, + ArgListTy &Args, SelectionDAG &DAG, + DebugLoc dl) const { + // Handle all of the outgoing arguments. + SmallVector Outs; + SmallVector OutVals; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + SmallVector ValueVTs; + ComputeValueVTs(*this, Args[i].Ty, ValueVTs); + for (unsigned Value = 0, NumValues = ValueVTs.size(); + Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + const Type *ArgTy = VT.getTypeForEVT(RetTy->getContext()); + SDValue Op = SDValue(Args[i].Node.getNode(), + Args[i].Node.getResNo() + Value); + ISD::ArgFlagsTy Flags; + unsigned OriginalAlignment = + getTargetData()->getABITypeAlignment(ArgTy); + + if (Args[i].isZExt) + Flags.setZExt(); + if (Args[i].isSExt) + Flags.setSExt(); + if (Args[i].isInReg) + Flags.setInReg(); + if (Args[i].isSRet) + Flags.setSRet(); + if (Args[i].isByVal) { + Flags.setByVal(); + const PointerType *Ty = cast(Args[i].Ty); + const Type *ElementTy = Ty->getElementType(); + unsigned FrameAlign = getByValTypeAlignment(ElementTy); + unsigned FrameSize = getTargetData()->getTypeAllocSize(ElementTy); + // For ByVal, alignment should come from FE. BE will guess if this + // info is not there but there are cases it cannot get right. + if (Args[i].Alignment) + FrameAlign = Args[i].Alignment; + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); + } + if (Args[i].isNest) + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); + + EVT PartVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumParts = getNumRegisters(RetTy->getContext(), VT); + SmallVector Parts(NumParts); + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + if (Args[i].isSExt) + ExtendKind = ISD::SIGN_EXTEND; + else if (Args[i].isZExt) + ExtendKind = ISD::ZERO_EXTEND; + + getCopyToParts(DAG, dl, Op, &Parts[0], NumParts, + PartVT, ExtendKind); + + for (unsigned j = 0; j != NumParts; ++j) { + // if it isn't first piece, alignment must be 1 + ISD::OutputArg MyFlags(Flags, Parts[j].getValueType(), + i < NumFixedArgs); + if (NumParts > 1 && j == 0) + MyFlags.Flags.setSplit(); + else if (j != 0) + MyFlags.Flags.setOrigAlign(1); + + Outs.push_back(MyFlags); + OutVals.push_back(Parts[j]); + } + } + } + + // Handle the incoming return values from the call. + SmallVector Ins; + SmallVector RetTys; + ComputeValueVTs(*this, RetTy, RetTys); + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); + for (unsigned i = 0; i != NumRegs; ++i) { + ISD::InputArg MyFlags; + MyFlags.VT = RegisterVT.getSimpleVT(); + MyFlags.Used = isReturnValueUsed; + if (RetSExt) + MyFlags.Flags.setSExt(); + if (RetZExt) + MyFlags.Flags.setZExt(); + if (isInreg) + MyFlags.Flags.setInReg(); + Ins.push_back(MyFlags); + } + } + + SmallVector InVals; + Chain = LowerCall(Chain, Callee, CallConv, isVarArg, isTailCall, + Outs, OutVals, Ins, dl, DAG, InVals); + + // Verify that the target's LowerCall behaved as expected. + assert(Chain.getNode() && Chain.getValueType() == MVT::Other && + "LowerCall didn't return a valid chain!"); + assert((!isTailCall || InVals.empty()) && + "LowerCall emitted a return value for a tail call!"); + assert((isTailCall || InVals.size() == Ins.size()) && + "LowerCall didn't emit the correct number of values!"); + + // For a tail call, the return value is merely live-out and there aren't + // any nodes in the DAG representing it. Return a special value to + // indicate that a tail call has been emitted and no more Instructions + // should be processed in the current block. + if (isTailCall) { + DAG.setRoot(Chain); + return std::make_pair(SDValue(), SDValue()); + } + + DEBUG(for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + assert(InVals[i].getNode() && + "LowerCall emitted a null value!"); + assert(EVT(Ins[i].VT) == InVals[i].getValueType() && + "LowerCall emitted a value with the wrong type!"); + }); + + // Collect the legal value parts into potentially illegal values + // that correspond to the original function's return values. + ISD::NodeType AssertOp = ISD::DELETED_NODE; + if (RetSExt) + AssertOp = ISD::AssertSext; + else if (RetZExt) + AssertOp = ISD::AssertZext; + SmallVector ReturnValues; + unsigned CurReg = 0; + for (unsigned I = 0, E = RetTys.size(); I != E; ++I) { + EVT VT = RetTys[I]; + EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); + unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); + + ReturnValues.push_back(getCopyFromParts(DAG, dl, &InVals[CurReg], + NumRegs, RegisterVT, VT, + AssertOp)); + CurReg += NumRegs; + } + + // For a function returning void, there is no return value. We can't create + // such a node, so we just return a null return value in that case. In + // that case, nothing will actualy look at the value. + if (ReturnValues.empty()) + return std::make_pair(SDValue(), Chain); + + SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, + DAG.getVTList(&RetTys[0], RetTys.size()), + &ReturnValues[0], ReturnValues.size()); + return std::make_pair(Res, Chain); +} + +void TargetLowering::LowerOperationWrapper(SDNode *N, + SmallVectorImpl &Results, + SelectionDAG &DAG) const { + SDValue Res = LowerOperation(SDValue(N, 0), DAG); + if (Res.getNode()) + Results.push_back(Res); +} + +SDValue TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { + llvm_unreachable("LowerOperation not implemented for this target!"); + return SDValue(); +} + +void +SelectionDAGBuilder::CopyValueToVirtualRegister(const Value *V, unsigned Reg) { + SDValue Op = getNonRegisterValue(V); + assert((Op.getOpcode() != ISD::CopyFromReg || + cast(Op.getOperand(1))->getReg() != Reg) && + "Copy from a reg to the same reg!"); + assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Is a physreg"); + + RegsForValue RFV(V->getContext(), TLI, Reg, V->getType()); + SDValue Chain = DAG.getEntryNode(); + RFV.getCopyToRegs(Op, DAG, getCurDebugLoc(), Chain, 0); + PendingExports.push_back(Chain); +} + +#include "llvm/CodeGen/SelectionDAGISel.h" + +void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) { + // If this is the entry block, emit arguments. + const Function &F = *LLVMBB->getParent(); + SelectionDAG &DAG = SDB->DAG; + DebugLoc dl = SDB->getCurDebugLoc(); + const TargetData *TD = TLI.getTargetData(); + SmallVector Ins; + + // Check whether the function can return without sret-demotion. + SmallVector Outs; + GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(), + Outs, TLI); + + if (!FuncInfo->CanLowerReturn) { + // Put in an sret pointer parameter before all the other parameters. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F.getReturnType()), ValueVTs); + + // NOTE: Assuming that a pointer will never break down to more than one VT + // or one register. + ISD::ArgFlagsTy Flags; + Flags.setSRet(); + EVT RegisterVT = TLI.getRegisterType(*DAG.getContext(), ValueVTs[0]); + ISD::InputArg RetArg(Flags, RegisterVT, true); + Ins.push_back(RetArg); + } + + // Set up the incoming argument description vector. + unsigned Idx = 1; + for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); + I != E; ++I, ++Idx) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I->getType(), ValueVTs); + bool isArgValueUsed = !I->use_empty(); + for (unsigned Value = 0, NumValues = ValueVTs.size(); + Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + const Type *ArgTy = VT.getTypeForEVT(*DAG.getContext()); + ISD::ArgFlagsTy Flags; + unsigned OriginalAlignment = + TD->getABITypeAlignment(ArgTy); + + if (F.paramHasAttr(Idx, Attribute::ZExt)) + Flags.setZExt(); + if (F.paramHasAttr(Idx, Attribute::SExt)) + Flags.setSExt(); + if (F.paramHasAttr(Idx, Attribute::InReg)) + Flags.setInReg(); + if (F.paramHasAttr(Idx, Attribute::StructRet)) + Flags.setSRet(); + if (F.paramHasAttr(Idx, Attribute::ByVal)) { + Flags.setByVal(); + const PointerType *Ty = cast(I->getType()); + const Type *ElementTy = Ty->getElementType(); + unsigned FrameAlign = TLI.getByValTypeAlignment(ElementTy); + unsigned FrameSize = TD->getTypeAllocSize(ElementTy); + // For ByVal, alignment should be passed from FE. BE will guess if + // this info is not there but there are cases it cannot get right. + if (F.getParamAlignment(Idx)) + FrameAlign = F.getParamAlignment(Idx); + Flags.setByValAlign(FrameAlign); + Flags.setByValSize(FrameSize); + } + if (F.paramHasAttr(Idx, Attribute::Nest)) + Flags.setNest(); + Flags.setOrigAlign(OriginalAlignment); + + EVT RegisterVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + unsigned NumRegs = TLI.getNumRegisters(*CurDAG->getContext(), VT); + for (unsigned i = 0; i != NumRegs; ++i) { + ISD::InputArg MyFlags(Flags, RegisterVT, isArgValueUsed); + if (NumRegs > 1 && i == 0) + MyFlags.Flags.setSplit(); + // if it isn't first piece, alignment must be 1 + else if (i > 0) + MyFlags.Flags.setOrigAlign(1); + Ins.push_back(MyFlags); + } + } + } + + // Call the target to set up the argument values. + SmallVector InVals; + SDValue NewRoot = TLI.LowerFormalArguments(DAG.getRoot(), F.getCallingConv(), + F.isVarArg(), Ins, + dl, DAG, InVals); + + // Verify that the target's LowerFormalArguments behaved as expected. + assert(NewRoot.getNode() && NewRoot.getValueType() == MVT::Other && + "LowerFormalArguments didn't return a valid chain!"); + assert(InVals.size() == Ins.size() && + "LowerFormalArguments didn't emit the correct number of values!"); + DEBUG({ + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + assert(InVals[i].getNode() && + "LowerFormalArguments emitted a null value!"); + assert(EVT(Ins[i].VT) == InVals[i].getValueType() && + "LowerFormalArguments emitted a value with the wrong type!"); + } + }); + + // Update the DAG with the new chain value resulting from argument lowering. + DAG.setRoot(NewRoot); + + // Set up the argument values. + unsigned i = 0; + Idx = 1; + if (!FuncInfo->CanLowerReturn) { + // Create a virtual register for the sret pointer, and put in a copy + // from the sret argument into it. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PointerType::getUnqual(F.getReturnType()), ValueVTs); + EVT VT = ValueVTs[0]; + EVT RegVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + ISD::NodeType AssertOp = ISD::DELETED_NODE; + SDValue ArgValue = getCopyFromParts(DAG, dl, &InVals[0], 1, + RegVT, VT, AssertOp); + + MachineFunction& MF = SDB->DAG.getMachineFunction(); + MachineRegisterInfo& RegInfo = MF.getRegInfo(); + unsigned SRetReg = RegInfo.createVirtualRegister(TLI.getRegClassFor(RegVT)); + FuncInfo->DemoteRegister = SRetReg; + NewRoot = SDB->DAG.getCopyToReg(NewRoot, SDB->getCurDebugLoc(), + SRetReg, ArgValue); + DAG.setRoot(NewRoot); + + // i indexes lowered arguments. Bump it past the hidden sret argument. + // Idx indexes LLVM arguments. Don't touch it. + ++i; + } + + for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; + ++I, ++Idx) { + SmallVector ArgValues; + SmallVector ValueVTs; + ComputeValueVTs(TLI, I->getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + + // If this argument is unused then remember its value. It is used to generate + // debugging information. + if (I->use_empty() && NumValues) + SDB->setUnusedArgValue(I, InVals[i]); + + for (unsigned Value = 0; Value != NumValues; ++Value) { + EVT VT = ValueVTs[Value]; + EVT PartVT = TLI.getRegisterType(*CurDAG->getContext(), VT); + unsigned NumParts = TLI.getNumRegisters(*CurDAG->getContext(), VT); + + if (!I->use_empty()) { + ISD::NodeType AssertOp = ISD::DELETED_NODE; + if (F.paramHasAttr(Idx, Attribute::SExt)) + AssertOp = ISD::AssertSext; + else if (F.paramHasAttr(Idx, Attribute::ZExt)) + AssertOp = ISD::AssertZext; + + ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], + NumParts, PartVT, VT, + AssertOp)); + } + + i += NumParts; + } + + // Note down frame index for byval arguments. + if (I->hasByValAttr() && !ArgValues.empty()) + if (FrameIndexSDNode *FI = + dyn_cast(ArgValues[0].getNode())) + FuncInfo->setByValArgumentFrameIndex(I, FI->getIndex()); + + if (!I->use_empty()) { + SDValue Res; + if (!ArgValues.empty()) + Res = DAG.getMergeValues(&ArgValues[0], NumValues, + SDB->getCurDebugLoc()); + SDB->setValue(I, Res); + + // If this argument is live outside of the entry block, insert a copy from + // whereever we got it to the vreg that other BB's will reference it as. + SDB->CopyToExportRegsIfNeeded(I); + } + } + + assert(i == InVals.size() && "Argument register count mismatch!"); + + // Finally, if the target has anything special to do, allow it to do so. + // FIXME: this should insert code into the DAG! + EmitFunctionEntryCode(); +} + +/// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to +/// ensure constants are generated when needed. Remember the virtual registers +/// that need to be added to the Machine PHI nodes as input. We cannot just +/// directly add them, because expansion might result in multiple MBB's for one +/// BB. As such, the start of the BB might correspond to a different MBB than +/// the end. +/// +void +SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) { + const TerminatorInst *TI = LLVMBB->getTerminator(); + + SmallPtrSet SuccsHandled; + + // Check successor nodes' PHI nodes that expect a constant to be available + // from this block. + for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { + const BasicBlock *SuccBB = TI->getSuccessor(succ); + if (!isa(SuccBB->begin())) continue; + MachineBasicBlock *SuccMBB = FuncInfo.MBBMap[SuccBB]; + + // If this terminator has multiple identical successors (common for + // switches), only handle each succ once. + if (!SuccsHandled.insert(SuccMBB)) continue; + + MachineBasicBlock::iterator MBBI = SuccMBB->begin(); + + // At this point we know that there is a 1-1 correspondence between LLVM PHI + // nodes and Machine PHI nodes, but the incoming operands have not been + // emitted yet. + for (BasicBlock::const_iterator I = SuccBB->begin(); + const PHINode *PN = dyn_cast(I); ++I) { + // Ignore dead phi's. + if (PN->use_empty()) continue; + + unsigned Reg; + const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB); + + if (const Constant *C = dyn_cast(PHIOp)) { + unsigned &RegOut = ConstantsOut[C]; + if (RegOut == 0) { + RegOut = FuncInfo.CreateRegs(C->getType()); + CopyValueToVirtualRegister(C, RegOut); + } + Reg = RegOut; + } else { + DenseMap::iterator I = + FuncInfo.ValueMap.find(PHIOp); + if (I != FuncInfo.ValueMap.end()) + Reg = I->second; + else { + assert(isa(PHIOp) && + FuncInfo.StaticAllocaMap.count(cast(PHIOp)) && + "Didn't codegen value into a register!??"); + Reg = FuncInfo.CreateRegs(PHIOp->getType()); + CopyValueToVirtualRegister(PHIOp, Reg); + } + } + + // Remember that this register needs to added to the machine PHI node as + // the input for this MBB. + SmallVector ValueVTs; + ComputeValueVTs(TLI, PN->getType(), ValueVTs); + for (unsigned vti = 0, vte = ValueVTs.size(); vti != vte; ++vti) { + EVT VT = ValueVTs[vti]; + unsigned NumRegisters = TLI.getNumRegisters(*DAG.getContext(), VT); + for (unsigned i = 0, e = NumRegisters; i != e; ++i) + FuncInfo.PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg+i)); + Reg += NumRegisters; + } + } + } + ConstantsOut.clear(); +} diff --git a/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h new file mode 100644 index 00000000000..8f466d913bb --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -0,0 +1,543 @@ +//===-- SelectionDAGBuilder.h - Selection-DAG building --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements routines for translating from LLVM IR into SelectionDAG IR. +// +//===----------------------------------------------------------------------===// + +#ifndef SELECTIONDAGBUILDER_H +#define SELECTIONDAGBUILDER_H + +#include "llvm/Constants.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include + +namespace llvm { + +class AliasAnalysis; +class AllocaInst; +class BasicBlock; +class BitCastInst; +class BranchInst; +class CallInst; +class DbgValueInst; +class ExtractElementInst; +class ExtractValueInst; +class FCmpInst; +class FPExtInst; +class FPToSIInst; +class FPToUIInst; +class FPTruncInst; +class Function; +class FunctionLoweringInfo; +class GetElementPtrInst; +class GCFunctionInfo; +class ICmpInst; +class IntToPtrInst; +class IndirectBrInst; +class InvokeInst; +class InsertElementInst; +class InsertValueInst; +class Instruction; +class LoadInst; +class MachineBasicBlock; +class MachineInstr; +class MachineRegisterInfo; +class MDNode; +class PHINode; +class PtrToIntInst; +class ReturnInst; +class SDISelAsmOperandInfo; +class SDDbgValue; +class SExtInst; +class SelectInst; +class ShuffleVectorInst; +class SIToFPInst; +class StoreInst; +class SwitchInst; +class TargetData; +class TargetLowering; +class TruncInst; +class UIToFPInst; +class UnreachableInst; +class UnwindInst; +class VAArgInst; +class ZExtInst; + +//===----------------------------------------------------------------------===// +/// SelectionDAGBuilder - This is the common target-independent lowering +/// implementation that is parameterized by a TargetLowering object. +/// +class SelectionDAGBuilder { + /// CurDebugLoc - current file + line number. Changes as we build the DAG. + DebugLoc CurDebugLoc; + + DenseMap NodeMap; + + /// UnusedArgNodeMap - Maps argument value for unused arguments. This is used + /// to preserve debug information for incoming arguments. + DenseMap UnusedArgNodeMap; + + /// DanglingDebugInfo - Helper type for DanglingDebugInfoMap. + class DanglingDebugInfo { + const DbgValueInst* DI; + DebugLoc dl; + unsigned SDNodeOrder; + public: + DanglingDebugInfo() : DI(0), dl(DebugLoc()), SDNodeOrder(0) { } + DanglingDebugInfo(const DbgValueInst *di, DebugLoc DL, unsigned SDNO) : + DI(di), dl(DL), SDNodeOrder(SDNO) { } + const DbgValueInst* getDI() { return DI; } + DebugLoc getdl() { return dl; } + unsigned getSDNodeOrder() { return SDNodeOrder; } + }; + + /// DanglingDebugInfoMap - Keeps track of dbg_values for which we have not + /// yet seen the referent. We defer handling these until we do see it. + DenseMap DanglingDebugInfoMap; + +public: + /// PendingLoads - Loads are not emitted to the program immediately. We bunch + /// them up and then emit token factor nodes when possible. This allows us to + /// get simple disambiguation between loads without worrying about alias + /// analysis. + SmallVector PendingLoads; +private: + + /// PendingExports - CopyToReg nodes that copy values to virtual registers + /// for export to other blocks need to be emitted before any terminator + /// instruction, but they have no other ordering requirements. We bunch them + /// up and the emit a single tokenfactor for them just before terminator + /// instructions. + SmallVector PendingExports; + + /// SDNodeOrder - A unique monotonically increasing number used to order the + /// SDNodes we create. + unsigned SDNodeOrder; + + /// Case - A struct to record the Value for a switch case, and the + /// case's target basic block. + struct Case { + Constant* Low; + Constant* High; + MachineBasicBlock* BB; + + Case() : Low(0), High(0), BB(0) { } + Case(Constant* low, Constant* high, MachineBasicBlock* bb) : + Low(low), High(high), BB(bb) { } + APInt size() const { + const APInt &rHigh = cast(High)->getValue(); + const APInt &rLow = cast(Low)->getValue(); + return (rHigh - rLow + 1ULL); + } + }; + + struct CaseBits { + uint64_t Mask; + MachineBasicBlock* BB; + unsigned Bits; + + CaseBits(uint64_t mask, MachineBasicBlock* bb, unsigned bits): + Mask(mask), BB(bb), Bits(bits) { } + }; + + typedef std::vector CaseVector; + typedef std::vector CaseBitsVector; + typedef CaseVector::iterator CaseItr; + typedef std::pair CaseRange; + + /// CaseRec - A struct with ctor used in lowering switches to a binary tree + /// of conditional branches. + struct CaseRec { + CaseRec(MachineBasicBlock *bb, const Constant *lt, const Constant *ge, + CaseRange r) : + CaseBB(bb), LT(lt), GE(ge), Range(r) {} + + /// CaseBB - The MBB in which to emit the compare and branch + MachineBasicBlock *CaseBB; + /// LT, GE - If nonzero, we know the current case value must be less-than or + /// greater-than-or-equal-to these Constants. + const Constant *LT; + const Constant *GE; + /// Range - A pair of iterators representing the range of case values to be + /// processed at this point in the binary search tree. + CaseRange Range; + }; + + typedef std::vector CaseRecVector; + + /// The comparison function for sorting the switch case values in the vector. + /// WARNING: Case ranges should be disjoint! + struct CaseCmp { + bool operator()(const Case &C1, const Case &C2) { + assert(isa(C1.Low) && isa(C2.High)); + const ConstantInt* CI1 = cast(C1.Low); + const ConstantInt* CI2 = cast(C2.High); + return CI1->getValue().slt(CI2->getValue()); + } + }; + + struct CaseBitsCmp { + bool operator()(const CaseBits &C1, const CaseBits &C2) { + return C1.Bits > C2.Bits; + } + }; + + size_t Clusterify(CaseVector &Cases, const SwitchInst &SI); + + /// CaseBlock - This structure is used to communicate between + /// SelectionDAGBuilder and SDISel for the code generation of additional basic + /// blocks needed by multi-case switch statements. + struct CaseBlock { + CaseBlock(ISD::CondCode cc, const Value *cmplhs, const Value *cmprhs, + const Value *cmpmiddle, + MachineBasicBlock *truebb, MachineBasicBlock *falsebb, + MachineBasicBlock *me) + : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), + TrueBB(truebb), FalseBB(falsebb), ThisBB(me) {} + // CC - the condition code to use for the case block's setcc node + ISD::CondCode CC; + // CmpLHS/CmpRHS/CmpMHS - The LHS/MHS/RHS of the comparison to emit. + // Emit by default LHS op RHS. MHS is used for range comparisons: + // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). + const Value *CmpLHS, *CmpMHS, *CmpRHS; + // TrueBB/FalseBB - the block to branch to if the setcc is true/false. + MachineBasicBlock *TrueBB, *FalseBB; + // ThisBB - the block into which to emit the code for the setcc and branches + MachineBasicBlock *ThisBB; + }; + struct JumpTable { + JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, + MachineBasicBlock *D): Reg(R), JTI(J), MBB(M), Default(D) {} + + /// Reg - the virtual register containing the index of the jump table entry + //. to jump to. + unsigned Reg; + /// JTI - the JumpTableIndex for this jump table in the function. + unsigned JTI; + /// MBB - the MBB into which to emit the code for the indirect jump. + MachineBasicBlock *MBB; + /// Default - the MBB of the default bb, which is a successor of the range + /// check MBB. This is when updating PHI nodes in successors. + MachineBasicBlock *Default; + }; + struct JumpTableHeader { + JumpTableHeader(APInt F, APInt L, const Value *SV, MachineBasicBlock *H, + bool E = false): + First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {} + APInt First; + APInt Last; + const Value *SValue; + MachineBasicBlock *HeaderBB; + bool Emitted; + }; + typedef std::pair JumpTableBlock; + + struct BitTestCase { + BitTestCase(uint64_t M, MachineBasicBlock* T, MachineBasicBlock* Tr): + Mask(M), ThisBB(T), TargetBB(Tr) { } + uint64_t Mask; + MachineBasicBlock *ThisBB; + MachineBasicBlock *TargetBB; + }; + + typedef SmallVector BitTestInfo; + + struct BitTestBlock { + BitTestBlock(APInt F, APInt R, const Value* SV, + unsigned Rg, EVT RgVT, bool E, + MachineBasicBlock* P, MachineBasicBlock* D, + const BitTestInfo& C): + First(F), Range(R), SValue(SV), Reg(Rg), RegVT(RgVT), Emitted(E), + Parent(P), Default(D), Cases(C) { } + APInt First; + APInt Range; + const Value *SValue; + unsigned Reg; + EVT RegVT; + bool Emitted; + MachineBasicBlock *Parent; + MachineBasicBlock *Default; + BitTestInfo Cases; + }; + +public: + // TLI - This is information that describes the available target features we + // need for lowering. This indicates when operations are unavailable, + // implemented with a libcall, etc. + const TargetMachine &TM; + const TargetLowering &TLI; + SelectionDAG &DAG; + const TargetData *TD; + AliasAnalysis *AA; + + /// SwitchCases - Vector of CaseBlock structures used to communicate + /// SwitchInst code generation information. + std::vector SwitchCases; + /// JTCases - Vector of JumpTable structures used to communicate + /// SwitchInst code generation information. + std::vector JTCases; + /// BitTestCases - Vector of BitTestBlock structures used to communicate + /// SwitchInst code generation information. + std::vector BitTestCases; + + // Emit PHI-node-operand constants only once even if used by multiple + // PHI nodes. + DenseMap ConstantsOut; + + /// FuncInfo - Information about the function as a whole. + /// + FunctionLoweringInfo &FuncInfo; + + /// OptLevel - What optimization level we're generating code for. + /// + CodeGenOpt::Level OptLevel; + + /// GFI - Garbage collection metadata for the function. + GCFunctionInfo *GFI; + + /// HasTailCall - This is set to true if a call in the current + /// block has been translated as a tail call. In this case, + /// no subsequent DAG nodes should be created. + /// + bool HasTailCall; + + LLVMContext *Context; + + SelectionDAGBuilder(SelectionDAG &dag, FunctionLoweringInfo &funcinfo, + CodeGenOpt::Level ol) + : SDNodeOrder(0), TM(dag.getTarget()), TLI(dag.getTargetLoweringInfo()), + DAG(dag), FuncInfo(funcinfo), OptLevel(ol), + HasTailCall(false), Context(dag.getContext()) { + } + + void init(GCFunctionInfo *gfi, AliasAnalysis &aa); + + /// clear - Clear out the current SelectionDAG and the associated + /// state and prepare this SelectionDAGBuilder object to be used + /// for a new block. This doesn't clear out information about + /// additional blocks that are needed to complete switch lowering + /// or PHI node updating; that information is cleared out as it is + /// consumed. + void clear(); + + /// getRoot - Return the current virtual root of the Selection DAG, + /// flushing any PendingLoad items. This must be done before emitting + /// a store or any other node that may need to be ordered after any + /// prior load instructions. + /// + SDValue getRoot(); + + /// getControlRoot - Similar to getRoot, but instead of flushing all the + /// PendingLoad items, flush all the PendingExports items. It is necessary + /// to do this before emitting a terminator instruction. + /// + SDValue getControlRoot(); + + DebugLoc getCurDebugLoc() const { return CurDebugLoc; } + + unsigned getSDNodeOrder() const { return SDNodeOrder; } + + void CopyValueToVirtualRegister(const Value *V, unsigned Reg); + + /// AssignOrderingToNode - Assign an ordering to the node. The order is gotten + /// from how the code appeared in the source. The ordering is used by the + /// scheduler to effectively turn off scheduling. + void AssignOrderingToNode(const SDNode *Node); + + void visit(const Instruction &I); + + void visit(unsigned Opcode, const User &I); + + // resolveDanglingDebugInfo - if we saw an earlier dbg_value referring to V, + // generate the debug data structures now that we've seen its definition. + void resolveDanglingDebugInfo(const Value *V, SDValue Val); + SDValue getValue(const Value *V); + SDValue getNonRegisterValue(const Value *V); + SDValue getValueImpl(const Value *V); + + void setValue(const Value *V, SDValue NewN) { + SDValue &N = NodeMap[V]; + assert(N.getNode() == 0 && "Already set a value for this node!"); + N = NewN; + } + + void setUnusedArgValue(const Value *V, SDValue NewN) { + SDValue &N = UnusedArgNodeMap[V]; + assert(N.getNode() == 0 && "Already set a value for this node!"); + N = NewN; + } + + void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, + std::set &OutputRegs, + std::set &InputRegs); + + void FindMergedConditions(const Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB, unsigned Opc); + void EmitBranchForMergedCondition(const Value *Cond, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + MachineBasicBlock *CurBB, + MachineBasicBlock *SwitchBB); + bool ShouldEmitAsBranches(const std::vector &Cases); + bool isExportableFromCurrentBlock(const Value *V, const BasicBlock *FromBB); + void CopyToExportRegsIfNeeded(const Value *V); + void ExportFromCurrentBlock(const Value *V); + void LowerCallTo(ImmutableCallSite CS, SDValue Callee, bool IsTailCall, + MachineBasicBlock *LandingPad = NULL); + + /// UpdateSplitBlock - When an MBB was split during scheduling, update the + /// references that ned to refer to the last resulting block. + void UpdateSplitBlock(MachineBasicBlock *First, MachineBasicBlock *Last); + +private: + // Terminator instructions. + void visitRet(const ReturnInst &I); + void visitBr(const BranchInst &I); + void visitSwitch(const SwitchInst &I); + void visitIndirectBr(const IndirectBrInst &I); + void visitUnreachable(const UnreachableInst &I) { /* noop */ } + + // Helpers for visitSwitch + bool handleSmallSwitchRange(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB); + bool handleJTSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB); + bool handleBTSplitSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB); + bool handleBitTestsSwitchCase(CaseRec& CR, + CaseRecVector& WorkList, + const Value* SV, + MachineBasicBlock* Default, + MachineBasicBlock *SwitchBB); +public: + void visitSwitchCase(CaseBlock &CB, + MachineBasicBlock *SwitchBB); + void visitBitTestHeader(BitTestBlock &B, MachineBasicBlock *SwitchBB); + void visitBitTestCase(BitTestBlock &BB, + MachineBasicBlock* NextMBB, + unsigned Reg, + BitTestCase &B, + MachineBasicBlock *SwitchBB); + void visitJumpTable(JumpTable &JT); + void visitJumpTableHeader(JumpTable &JT, JumpTableHeader &JTH, + MachineBasicBlock *SwitchBB); + +private: + // These all get lowered before this pass. + void visitInvoke(const InvokeInst &I); + void visitUnwind(const UnwindInst &I); + + void visitBinary(const User &I, unsigned OpCode); + void visitShift(const User &I, unsigned Opcode); + void visitAdd(const User &I) { visitBinary(I, ISD::ADD); } + void visitFAdd(const User &I) { visitBinary(I, ISD::FADD); } + void visitSub(const User &I) { visitBinary(I, ISD::SUB); } + void visitFSub(const User &I); + void visitMul(const User &I) { visitBinary(I, ISD::MUL); } + void visitFMul(const User &I) { visitBinary(I, ISD::FMUL); } + void visitURem(const User &I) { visitBinary(I, ISD::UREM); } + void visitSRem(const User &I) { visitBinary(I, ISD::SREM); } + void visitFRem(const User &I) { visitBinary(I, ISD::FREM); } + void visitUDiv(const User &I) { visitBinary(I, ISD::UDIV); } + void visitSDiv(const User &I) { visitBinary(I, ISD::SDIV); } + void visitFDiv(const User &I) { visitBinary(I, ISD::FDIV); } + void visitAnd (const User &I) { visitBinary(I, ISD::AND); } + void visitOr (const User &I) { visitBinary(I, ISD::OR); } + void visitXor (const User &I) { visitBinary(I, ISD::XOR); } + void visitShl (const User &I) { visitShift(I, ISD::SHL); } + void visitLShr(const User &I) { visitShift(I, ISD::SRL); } + void visitAShr(const User &I) { visitShift(I, ISD::SRA); } + void visitICmp(const User &I); + void visitFCmp(const User &I); + // Visit the conversion instructions + void visitTrunc(const User &I); + void visitZExt(const User &I); + void visitSExt(const User &I); + void visitFPTrunc(const User &I); + void visitFPExt(const User &I); + void visitFPToUI(const User &I); + void visitFPToSI(const User &I); + void visitUIToFP(const User &I); + void visitSIToFP(const User &I); + void visitPtrToInt(const User &I); + void visitIntToPtr(const User &I); + void visitBitCast(const User &I); + + void visitExtractElement(const User &I); + void visitInsertElement(const User &I); + void visitShuffleVector(const User &I); + + void visitExtractValue(const ExtractValueInst &I); + void visitInsertValue(const InsertValueInst &I); + + void visitGetElementPtr(const User &I); + void visitSelect(const User &I); + + void visitAlloca(const AllocaInst &I); + void visitLoad(const LoadInst &I); + void visitStore(const StoreInst &I); + void visitPHI(const PHINode &I); + void visitCall(const CallInst &I); + bool visitMemCmpCall(const CallInst &I); + + void visitInlineAsm(ImmutableCallSite CS); + const char *visitIntrinsicCall(const CallInst &I, unsigned Intrinsic); + void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic); + + void visitPow(const CallInst &I); + void visitExp2(const CallInst &I); + void visitExp(const CallInst &I); + void visitLog(const CallInst &I); + void visitLog2(const CallInst &I); + void visitLog10(const CallInst &I); + + void visitVAStart(const CallInst &I); + void visitVAArg(const VAArgInst &I); + void visitVAEnd(const CallInst &I); + void visitVACopy(const CallInst &I); + + void visitUserOp1(const Instruction &I) { + llvm_unreachable("UserOp1 should not exist at instruction selection time!"); + } + void visitUserOp2(const Instruction &I) { + llvm_unreachable("UserOp2 should not exist at instruction selection time!"); + } + + const char *implVisitBinaryAtomic(const CallInst& I, ISD::NodeType Op); + const char *implVisitAluOverflow(const CallInst &I, ISD::NodeType Op); + + void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + + /// EmitFuncArgumentDbgValue - If V is an function argument then create + /// corresponding DBG_VALUE machine instruction for it now. At the end of + /// instruction selection, they will be inserted to the entry BB. + bool EmitFuncArgumentDbgValue(const Value *V, MDNode *Variable, + int64_t Offset, const SDValue &N); +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/final/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp new file mode 100644 index 00000000000..8387bde46e3 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -0,0 +1,2783 @@ +//===-- SelectionDAGISel.cpp - Implement the SelectionDAGISel class -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAGISel class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "isel" +#include "ScheduleDAGSDNodes.h" +#include "SelectionDAGBuilder.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/CodeGen/GCMetadata.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +STATISTIC(NumFastIselFailures, "Number of instructions fast isel failed on"); +STATISTIC(NumFastIselBlocks, "Number of blocks selected entirely by fast isel"); +STATISTIC(NumDAGBlocks, "Number of blocks selected using DAG"); +STATISTIC(NumDAGIselRetries,"Number of times dag isel has to try another path"); + +#ifndef NDEBUG +STATISTIC(NumBBWithOutOfOrderLineInfo, + "Number of blocks with out of order line number info"); +STATISTIC(NumMBBWithOutOfOrderLineInfo, + "Number of machine blocks with out of order line number info"); +#endif + +static cl::opt +EnableFastISelVerbose("fast-isel-verbose", cl::Hidden, + cl::desc("Enable verbose messages in the \"fast\" " + "instruction selector")); +static cl::opt +EnableFastISelAbort("fast-isel-abort", cl::Hidden, + cl::desc("Enable abort calls when \"fast\" instruction fails")); + +#ifndef NDEBUG +static cl::opt +ViewDAGCombine1("view-dag-combine1-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the first " + "dag combine pass")); +static cl::opt +ViewLegalizeTypesDAGs("view-legalize-types-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before legalize types")); +static cl::opt +ViewLegalizeDAGs("view-legalize-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before legalize")); +static cl::opt +ViewDAGCombine2("view-dag-combine2-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the second " + "dag combine pass")); +static cl::opt +ViewDAGCombineLT("view-dag-combine-lt-dags", cl::Hidden, + cl::desc("Pop up a window to show dags before the post legalize types" + " dag combine pass")); +static cl::opt +ViewISelDAGs("view-isel-dags", cl::Hidden, + cl::desc("Pop up a window to show isel dags as they are selected")); +static cl::opt +ViewSchedDAGs("view-sched-dags", cl::Hidden, + cl::desc("Pop up a window to show sched dags as they are processed")); +static cl::opt +ViewSUnitDAGs("view-sunit-dags", cl::Hidden, + cl::desc("Pop up a window to show SUnit dags after they are processed")); +#else +static const bool ViewDAGCombine1 = false, + ViewLegalizeTypesDAGs = false, ViewLegalizeDAGs = false, + ViewDAGCombine2 = false, + ViewDAGCombineLT = false, + ViewISelDAGs = false, ViewSchedDAGs = false, + ViewSUnitDAGs = false; +#endif + +//===---------------------------------------------------------------------===// +/// +/// RegisterScheduler class - Track the registration of instruction schedulers. +/// +//===---------------------------------------------------------------------===// +MachinePassRegistry RegisterScheduler::Registry; + +//===---------------------------------------------------------------------===// +/// +/// ISHeuristic command line option for instruction schedulers. +/// +//===---------------------------------------------------------------------===// +static cl::opt > +ISHeuristic("pre-RA-sched", + cl::init(&createDefaultScheduler), + cl::desc("Instruction schedulers available (before register" + " allocation):")); + +static RegisterScheduler +defaultListDAGScheduler("default", "Best scheduler for the target", + createDefaultScheduler); + +namespace llvm { + //===--------------------------------------------------------------------===// + /// createDefaultScheduler - This creates an instruction scheduler appropriate + /// for the target. + ScheduleDAGSDNodes* createDefaultScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level OptLevel) { + const TargetLowering &TLI = IS->getTargetLowering(); + + if (OptLevel == CodeGenOpt::None) + return createSourceListDAGScheduler(IS, OptLevel); + if (TLI.getSchedulingPreference() == Sched::Latency) + return createTDListDAGScheduler(IS, OptLevel); + if (TLI.getSchedulingPreference() == Sched::RegPressure) + return createBURRListDAGScheduler(IS, OptLevel); + if (TLI.getSchedulingPreference() == Sched::Hybrid) + return createHybridListDAGScheduler(IS, OptLevel); + assert(TLI.getSchedulingPreference() == Sched::ILP && + "Unknown sched type!"); + return createILPListDAGScheduler(IS, OptLevel); + } +} + +// EmitInstrWithCustomInserter - This method should be implemented by targets +// that mark instructions with the 'usesCustomInserter' flag. These +// instructions are special in various ways, which require special support to +// insert. The specified MachineInstr is created but not inserted into any +// basic blocks, and this method is called to expand it into a sequence of +// instructions, potentially also creating new basic blocks and control flow. +// When new basic blocks are inserted and the edges from MBB to its successors +// are modified, the method should insert pairs of into the +// DenseMap. +MachineBasicBlock * +TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB) const { +#ifndef NDEBUG + dbgs() << "If a target marks an instruction with " + "'usesCustomInserter', it must implement " + "TargetLowering::EmitInstrWithCustomInserter!"; +#endif + llvm_unreachable(0); + return 0; +} + +//===----------------------------------------------------------------------===// +// SelectionDAGISel code +//===----------------------------------------------------------------------===// + +SelectionDAGISel::SelectionDAGISel(const TargetMachine &tm, + CodeGenOpt::Level OL) : + MachineFunctionPass(ID), TM(tm), TLI(*tm.getTargetLowering()), + FuncInfo(new FunctionLoweringInfo(TLI)), + CurDAG(new SelectionDAG(tm)), + SDB(new SelectionDAGBuilder(*CurDAG, *FuncInfo, OL)), + GFI(), + OptLevel(OL), + DAGSize(0) { + initializeGCModuleInfoPass(*PassRegistry::getPassRegistry()); + initializeAliasAnalysisAnalysisGroup(*PassRegistry::getPassRegistry()); + } + +SelectionDAGISel::~SelectionDAGISel() { + delete SDB; + delete CurDAG; + delete FuncInfo; +} + +void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +/// FunctionCallsSetJmp - Return true if the function has a call to setjmp or +/// other function that gcc recognizes as "returning twice". This is used to +/// limit code-gen optimizations on the machine function. +/// +/// FIXME: Remove after is fixed. +static bool FunctionCallsSetJmp(const Function *F) { + const Module *M = F->getParent(); + static const char *ReturnsTwiceFns[] = { + "_setjmp", + "setjmp", + "sigsetjmp", + "setjmp_syscall", + "savectx", + "qsetjmp", + "vfork", + "getcontext" + }; +#define NUM_RETURNS_TWICE_FNS sizeof(ReturnsTwiceFns) / sizeof(const char *) + + for (unsigned I = 0; I < NUM_RETURNS_TWICE_FNS; ++I) + if (const Function *Callee = M->getFunction(ReturnsTwiceFns[I])) { + if (!Callee->use_empty()) + for (Value::const_use_iterator + I = Callee->use_begin(), E = Callee->use_end(); + I != E; ++I) + if (const CallInst *CI = dyn_cast(*I)) + if (CI->getParent()->getParent() == F) + return true; + } + + return false; +#undef NUM_RETURNS_TWICE_FNS +} + +/// SplitCriticalSideEffectEdges - Look for critical edges with a PHI value that +/// may trap on it. In this case we have to split the edge so that the path +/// through the predecessor block that doesn't go to the phi block doesn't +/// execute the possibly trapping instruction. +/// +/// This is required for correctness, so it must be done at -O0. +/// +static void SplitCriticalSideEffectEdges(Function &Fn, Pass *SDISel) { + // Loop for blocks with phi nodes. + for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { + PHINode *PN = dyn_cast(BB->begin()); + if (PN == 0) continue; + + ReprocessBlock: + // For each block with a PHI node, check to see if any of the input values + // are potentially trapping constant expressions. Constant expressions are + // the only potentially trapping value that can occur as the argument to a + // PHI. + for (BasicBlock::iterator I = BB->begin(); (PN = dyn_cast(I)); ++I) + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + ConstantExpr *CE = dyn_cast(PN->getIncomingValue(i)); + if (CE == 0 || !CE->canTrap()) continue; + + // The only case we have to worry about is when the edge is critical. + // Since this block has a PHI Node, we assume it has multiple input + // edges: check to see if the pred has multiple successors. + BasicBlock *Pred = PN->getIncomingBlock(i); + if (Pred->getTerminator()->getNumSuccessors() == 1) + continue; + + // Okay, we have to split this edge. + SplitCriticalEdge(Pred->getTerminator(), + GetSuccessorNumber(Pred, BB), SDISel, true); + goto ReprocessBlock; + } + } +} + +bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { + // Do some sanity-checking on the command-line options. + assert((!EnableFastISelVerbose || EnableFastISel) && + "-fast-isel-verbose requires -fast-isel"); + assert((!EnableFastISelAbort || EnableFastISel) && + "-fast-isel-abort requires -fast-isel"); + + const Function &Fn = *mf.getFunction(); + const TargetInstrInfo &TII = *TM.getInstrInfo(); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + + MF = &mf; + RegInfo = &MF->getRegInfo(); + AA = &getAnalysis(); + GFI = Fn.hasGC() ? &getAnalysis().getFunctionInfo(Fn) : 0; + + DEBUG(dbgs() << "\n\n\n=== " << Fn.getName() << "\n"); + + SplitCriticalSideEffectEdges(const_cast(Fn), this); + + CurDAG->init(*MF); + FuncInfo->set(Fn, *MF); + SDB->init(GFI, *AA); + + SelectAllBasicBlocks(Fn); + + // If the first basic block in the function has live ins that need to be + // copied into vregs, emit the copies into the top of the block before + // emitting the code for the block. + MachineBasicBlock *EntryMBB = MF->begin(); + RegInfo->EmitLiveInCopies(EntryMBB, TRI, TII); + + DenseMap LiveInMap; + if (!FuncInfo->ArgDbgValues.empty()) + for (MachineRegisterInfo::livein_iterator LI = RegInfo->livein_begin(), + E = RegInfo->livein_end(); LI != E; ++LI) + if (LI->second) + LiveInMap.insert(std::make_pair(LI->first, LI->second)); + + // Insert DBG_VALUE instructions for function arguments to the entry block. + for (unsigned i = 0, e = FuncInfo->ArgDbgValues.size(); i != e; ++i) { + MachineInstr *MI = FuncInfo->ArgDbgValues[e-i-1]; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + EntryMBB->insert(EntryMBB->begin(), MI); + else { + MachineInstr *Def = RegInfo->getVRegDef(Reg); + MachineBasicBlock::iterator InsertPos = Def; + // FIXME: VR def may not be in entry block. + Def->getParent()->insert(llvm::next(InsertPos), MI); + } + + // If Reg is live-in then update debug info to track its copy in a vreg. + DenseMap::iterator LDI = LiveInMap.find(Reg); + if (LDI != LiveInMap.end()) { + MachineInstr *Def = RegInfo->getVRegDef(LDI->second); + MachineBasicBlock::iterator InsertPos = Def; + const MDNode *Variable = + MI->getOperand(MI->getNumOperands()-1).getMetadata(); + unsigned Offset = MI->getOperand(1).getImm(); + // Def is never a terminator here, so it is ok to increment InsertPos. + BuildMI(*EntryMBB, ++InsertPos, MI->getDebugLoc(), + TII.get(TargetOpcode::DBG_VALUE)) + .addReg(LDI->second, RegState::Debug) + .addImm(Offset).addMetadata(Variable); + + // If this vreg is directly copied into an exported register then + // that COPY instructions also need DBG_VALUE, if it is the only + // user of LDI->second. + MachineInstr *CopyUseMI = NULL; + for (MachineRegisterInfo::use_iterator + UI = RegInfo->use_begin(LDI->second); + MachineInstr *UseMI = UI.skipInstruction();) { + if (UseMI->isDebugValue()) continue; + if (UseMI->isCopy() && !CopyUseMI && UseMI->getParent() == EntryMBB) { + CopyUseMI = UseMI; continue; + } + // Otherwise this is another use or second copy use. + CopyUseMI = NULL; break; + } + if (CopyUseMI) { + MachineInstr *NewMI = + BuildMI(*MF, CopyUseMI->getDebugLoc(), + TII.get(TargetOpcode::DBG_VALUE)) + .addReg(CopyUseMI->getOperand(0).getReg(), RegState::Debug) + .addImm(Offset).addMetadata(Variable); + EntryMBB->insertAfter(CopyUseMI, NewMI); + } + } + } + + // Determine if there are any calls in this machine function. + MachineFrameInfo *MFI = MF->getFrameInfo(); + if (!MFI->hasCalls()) { + for (MachineFunction::const_iterator + I = MF->begin(), E = MF->end(); I != E; ++I) { + const MachineBasicBlock *MBB = I; + for (MachineBasicBlock::const_iterator + II = MBB->begin(), IE = MBB->end(); II != IE; ++II) { + const TargetInstrDesc &TID = TM.getInstrInfo()->get(II->getOpcode()); + + if ((TID.isCall() && !TID.isReturn()) || + II->isStackAligningInlineAsm()) { + MFI->setHasCalls(true); + goto done; + } + } + } + done:; + } + + // Determine if there is a call to setjmp in the machine function. + MF->setCallsSetJmp(FunctionCallsSetJmp(&Fn)); + + // Replace forward-declared registers with the registers containing + // the desired value. + MachineRegisterInfo &MRI = MF->getRegInfo(); + for (DenseMap::iterator + I = FuncInfo->RegFixups.begin(), E = FuncInfo->RegFixups.end(); + I != E; ++I) { + unsigned From = I->first; + unsigned To = I->second; + // If To is also scheduled to be replaced, find what its ultimate + // replacement is. + for (;;) { + DenseMap::iterator J = + FuncInfo->RegFixups.find(To); + if (J == E) break; + To = J->second; + } + // Replace it. + MRI.replaceRegWith(From, To); + } + + // Release function-specific state. SDB and CurDAG are already cleared + // at this point. + FuncInfo->clear(); + + return true; +} + +void +SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin, + BasicBlock::const_iterator End, + bool &HadTailCall) { + // Lower all of the non-terminator instructions. If a call is emitted + // as a tail call, cease emitting nodes for this block. Terminators + // are handled below. + for (BasicBlock::const_iterator I = Begin; I != End && !SDB->HasTailCall; ++I) + SDB->visit(*I); + + // Make sure the root of the DAG is up-to-date. + CurDAG->setRoot(SDB->getControlRoot()); + HadTailCall = SDB->HasTailCall; + SDB->clear(); + + // Final step, emit the lowered DAG as machine code. + CodeGenAndEmitDAG(); + return; +} + +void SelectionDAGISel::ComputeLiveOutVRegInfo() { + SmallPtrSet VisitedNodes; + SmallVector Worklist; + + Worklist.push_back(CurDAG->getRoot().getNode()); + + APInt Mask; + APInt KnownZero; + APInt KnownOne; + + do { + SDNode *N = Worklist.pop_back_val(); + + // If we've already seen this node, ignore it. + if (!VisitedNodes.insert(N)) + continue; + + // Otherwise, add all chain operands to the worklist. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i).getValueType() == MVT::Other) + Worklist.push_back(N->getOperand(i).getNode()); + + // If this is a CopyToReg with a vreg dest, process it. + if (N->getOpcode() != ISD::CopyToReg) + continue; + + unsigned DestReg = cast(N->getOperand(1))->getReg(); + if (!TargetRegisterInfo::isVirtualRegister(DestReg)) + continue; + + // Ignore non-scalar or non-integer values. + SDValue Src = N->getOperand(2); + EVT SrcVT = Src.getValueType(); + if (!SrcVT.isInteger() || SrcVT.isVector()) + continue; + + unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src); + Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits()); + CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne); + FuncInfo->AddLiveOutRegInfo(DestReg, NumSignBits, KnownZero, KnownOne); + } while (!Worklist.empty()); +} + +void SelectionDAGISel::CodeGenAndEmitDAG() { + std::string GroupName; + if (TimePassesIsEnabled) + GroupName = "Instruction Selection and Scheduling"; + std::string BlockName; + if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs || + ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs || + ViewSUnitDAGs) + BlockName = MF->getFunction()->getNameStr() + ":" + + FuncInfo->MBB->getBasicBlock()->getNameStr(); + + DEBUG(dbgs() << "Initial selection DAG:\n"; CurDAG->dump()); + + if (ViewDAGCombine1) CurDAG->viewGraph("dag-combine1 input for " + BlockName); + + // Run the DAG combiner in pre-legalize mode. + { + NamedRegionTimer T("DAG Combining 1", GroupName, TimePassesIsEnabled); + CurDAG->Combine(Unrestricted, *AA, OptLevel); + } + + DEBUG(dbgs() << "Optimized lowered selection DAG:\n"; CurDAG->dump()); + + // Second step, hack on the DAG until it only uses operations and types that + // the target supports. + if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " + + BlockName); + + bool Changed; + { + NamedRegionTimer T("Type Legalization", GroupName, TimePassesIsEnabled); + Changed = CurDAG->LegalizeTypes(); + } + + DEBUG(dbgs() << "Type-legalized selection DAG:\n"; CurDAG->dump()); + + if (Changed) { + if (ViewDAGCombineLT) + CurDAG->viewGraph("dag-combine-lt input for " + BlockName); + + // Run the DAG combiner in post-type-legalize mode. + { + NamedRegionTimer T("DAG Combining after legalize types", GroupName, + TimePassesIsEnabled); + CurDAG->Combine(NoIllegalTypes, *AA, OptLevel); + } + + DEBUG(dbgs() << "Optimized type-legalized selection DAG:\n"; + CurDAG->dump()); + } + + { + NamedRegionTimer T("Vector Legalization", GroupName, TimePassesIsEnabled); + Changed = CurDAG->LegalizeVectors(); + } + + if (Changed) { + { + NamedRegionTimer T("Type Legalization 2", GroupName, TimePassesIsEnabled); + CurDAG->LegalizeTypes(); + } + + if (ViewDAGCombineLT) + CurDAG->viewGraph("dag-combine-lv input for " + BlockName); + + // Run the DAG combiner in post-type-legalize mode. + { + NamedRegionTimer T("DAG Combining after legalize vectors", GroupName, + TimePassesIsEnabled); + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } + + DEBUG(dbgs() << "Optimized vector-legalized selection DAG:\n"; + CurDAG->dump()); + } + + if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName); + + { + NamedRegionTimer T("DAG Legalization", GroupName, TimePassesIsEnabled); + CurDAG->Legalize(OptLevel); + } + + DEBUG(dbgs() << "Legalized selection DAG:\n"; CurDAG->dump()); + + if (ViewDAGCombine2) CurDAG->viewGraph("dag-combine2 input for " + BlockName); + + // Run the DAG combiner in post-legalize mode. + { + NamedRegionTimer T("DAG Combining 2", GroupName, TimePassesIsEnabled); + CurDAG->Combine(NoIllegalOperations, *AA, OptLevel); + } + + DEBUG(dbgs() << "Optimized legalized selection DAG:\n"; CurDAG->dump()); + + if (OptLevel != CodeGenOpt::None) + ComputeLiveOutVRegInfo(); + + if (ViewISelDAGs) CurDAG->viewGraph("isel input for " + BlockName); + + // Third, instruction select all of the operations to machine code, adding the + // code to the MachineBasicBlock. + { + NamedRegionTimer T("Instruction Selection", GroupName, TimePassesIsEnabled); + DoInstructionSelection(); + } + + DEBUG(dbgs() << "Selected selection DAG:\n"; CurDAG->dump()); + + if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName); + + // Schedule machine code. + ScheduleDAGSDNodes *Scheduler = CreateScheduler(); + { + NamedRegionTimer T("Instruction Scheduling", GroupName, + TimePassesIsEnabled); + Scheduler->Run(CurDAG, FuncInfo->MBB, FuncInfo->InsertPt); + } + + if (ViewSUnitDAGs) Scheduler->viewGraph(); + + // Emit machine code to BB. This can change 'BB' to the last block being + // inserted into. + MachineBasicBlock *FirstMBB = FuncInfo->MBB, *LastMBB; + { + NamedRegionTimer T("Instruction Creation", GroupName, TimePassesIsEnabled); + + LastMBB = FuncInfo->MBB = Scheduler->EmitSchedule(); + FuncInfo->InsertPt = Scheduler->InsertPos; + } + + // If the block was split, make sure we update any references that are used to + // update PHI nodes later on. + if (FirstMBB != LastMBB) + SDB->UpdateSplitBlock(FirstMBB, LastMBB); + + // Free the scheduler state. + { + NamedRegionTimer T("Instruction Scheduling Cleanup", GroupName, + TimePassesIsEnabled); + delete Scheduler; + } + + // Free the SelectionDAG state, now that we're finished with it. + CurDAG->clear(); +} + +void SelectionDAGISel::DoInstructionSelection() { + DEBUG(errs() << "===== Instruction selection begins:\n"); + + PreprocessISelDAG(); + + // Select target instructions for the DAG. + { + // Number all nodes with a topological order and set DAGSize. + DAGSize = CurDAG->AssignTopologicalOrder(); + + // Create a dummy node (which is not added to allnodes), that adds + // a reference to the root node, preventing it from being deleted, + // and tracking any changes of the root. + HandleSDNode Dummy(CurDAG->getRoot()); + ISelPosition = SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()); + ++ISelPosition; + + // The AllNodes list is now topological-sorted. Visit the + // nodes by starting at the end of the list (the root of the + // graph) and preceding back toward the beginning (the entry + // node). + while (ISelPosition != CurDAG->allnodes_begin()) { + SDNode *Node = --ISelPosition; + // Skip dead nodes. DAGCombiner is expected to eliminate all dead nodes, + // but there are currently some corner cases that it misses. Also, this + // makes it theoretically possible to disable the DAGCombiner. + if (Node->use_empty()) + continue; + + SDNode *ResNode = Select(Node); + + // FIXME: This is pretty gross. 'Select' should be changed to not return + // anything at all and this code should be nuked with a tactical strike. + + // If node should not be replaced, continue with the next one. + if (ResNode == Node || Node->getOpcode() == ISD::DELETED_NODE) + continue; + // Replace node. + if (ResNode) + ReplaceUses(Node, ResNode); + + // If after the replacement this node is not used any more, + // remove this dead node. + if (Node->use_empty()) { // Don't delete EntryToken, etc. + ISelUpdater ISU(ISelPosition); + CurDAG->RemoveDeadNode(Node, &ISU); + } + } + + CurDAG->setRoot(Dummy.getValue()); + } + + DEBUG(errs() << "===== Instruction selection ends:\n"); + + PostprocessISelDAG(); +} + +/// PrepareEHLandingPad - Emit an EH_LABEL, set up live-in registers, and +/// do other setup for EH landing-pad blocks. +void SelectionDAGISel::PrepareEHLandingPad() { + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + MCSymbol *Label = MF->getMMI().addLandingPad(FuncInfo->MBB); + + const TargetInstrDesc &II = TM.getInstrInfo()->get(TargetOpcode::EH_LABEL); + BuildMI(*FuncInfo->MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) + .addSym(Label); + + // Mark exception register as live in. + unsigned Reg = TLI.getExceptionAddressRegister(); + if (Reg) FuncInfo->MBB->addLiveIn(Reg); + + // Mark exception selector register as live in. + Reg = TLI.getExceptionSelectorRegister(); + if (Reg) FuncInfo->MBB->addLiveIn(Reg); + + // FIXME: Hack around an exception handling flaw (PR1508): the personality + // function and list of typeids logically belong to the invoke (or, if you + // like, the basic block containing the invoke), and need to be associated + // with it in the dwarf exception handling tables. Currently however the + // information is provided by an intrinsic (eh.selector) that can be moved + // to unexpected places by the optimizers: if the unwind edge is critical, + // then breaking it can result in the intrinsics being in the successor of + // the landing pad, not the landing pad itself. This results + // in exceptions not being caught because no typeids are associated with + // the invoke. This may not be the only way things can go wrong, but it + // is the only way we try to work around for the moment. + const BasicBlock *LLVMBB = FuncInfo->MBB->getBasicBlock(); + const BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); + + if (Br && Br->isUnconditional()) { // Critical edge? + BasicBlock::const_iterator I, E; + for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) + if (isa(I)) + break; + + if (I == E) + // No catch info found - try to extract some from the successor. + CopyCatchInfo(Br->getSuccessor(0), LLVMBB, &MF->getMMI(), *FuncInfo); + } +} + + + + +bool SelectionDAGISel::TryToFoldFastISelLoad(const LoadInst *LI, + FastISel *FastIS) { + // Don't try to fold volatile loads. Target has to deal with alignment + // constraints. + if (LI->isVolatile()) return false; + + // Figure out which vreg this is going into. + unsigned LoadReg = FastIS->getRegForValue(LI); + assert(LoadReg && "Load isn't already assigned a vreg? "); + + // Check to see what the uses of this vreg are. If it has no uses, or more + // than one use (at the machine instr level) then we can't fold it. + MachineRegisterInfo::reg_iterator RI = RegInfo->reg_begin(LoadReg); + if (RI == RegInfo->reg_end()) + return false; + + // See if there is exactly one use of the vreg. If there are multiple uses, + // then the instruction got lowered to multiple machine instructions or the + // use of the loaded value ended up being multiple operands of the result, in + // either case, we can't fold this. + MachineRegisterInfo::reg_iterator PostRI = RI; ++PostRI; + if (PostRI != RegInfo->reg_end()) + return false; + + assert(RI.getOperand().isUse() && + "The only use of the vreg must be a use, we haven't emitted the def!"); + + MachineInstr *User = &*RI; + + // Set the insertion point properly. Folding the load can cause generation of + // other random instructions (like sign extends) for addressing modes, make + // sure they get inserted in a logical place before the new instruction. + FuncInfo->InsertPt = User; + FuncInfo->MBB = User->getParent(); + + // Ask the target to try folding the load. + return FastIS->TryToFoldLoad(User, RI.getOperandNo(), LI); +} + +#ifndef NDEBUG +/// CheckLineNumbers - Check if basic block instructions follow source order +/// or not. +static void CheckLineNumbers(const BasicBlock *BB) { + unsigned Line = 0; + unsigned Col = 0; + for (BasicBlock::const_iterator BI = BB->begin(), + BE = BB->end(); BI != BE; ++BI) { + const DebugLoc DL = BI->getDebugLoc(); + if (DL.isUnknown()) continue; + unsigned L = DL.getLine(); + unsigned C = DL.getCol(); + if (L < Line || (L == Line && C < Col)) { + ++NumBBWithOutOfOrderLineInfo; + return; + } + Line = L; + Col = C; + } +} + +/// CheckLineNumbers - Check if machine basic block instructions follow source +/// order or not. +static void CheckLineNumbers(const MachineBasicBlock *MBB) { + unsigned Line = 0; + unsigned Col = 0; + for (MachineBasicBlock::const_iterator MBI = MBB->begin(), + MBE = MBB->end(); MBI != MBE; ++MBI) { + const DebugLoc DL = MBI->getDebugLoc(); + if (DL.isUnknown()) continue; + unsigned L = DL.getLine(); + unsigned C = DL.getCol(); + if (L < Line || (L == Line && C < Col)) { + ++NumMBBWithOutOfOrderLineInfo; + return; + } + Line = L; + Col = C; + } +} +#endif + +void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { + // Initialize the Fast-ISel state, if needed. + FastISel *FastIS = 0; + if (EnableFastISel) + FastIS = TLI.createFastISel(*FuncInfo); + + // Iterate over all basic blocks in the function. + ReversePostOrderTraversal RPOT(&Fn); + for (ReversePostOrderTraversal::rpo_iterator + I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { + const BasicBlock *LLVMBB = *I; +#ifndef NDEBUG + CheckLineNumbers(LLVMBB); +#endif + + if (OptLevel != CodeGenOpt::None) { + bool AllPredsVisited = true; + for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB); + PI != PE; ++PI) { + if (!FuncInfo->VisitedBBs.count(*PI)) { + AllPredsVisited = false; + break; + } + } + + if (AllPredsVisited) { + for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); + I != E && isa(I); ++I) { + FuncInfo->ComputePHILiveOutRegInfo(cast(I)); + } + } else { + for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end(); + I != E && isa(I); ++I) { + FuncInfo->InvalidatePHILiveOutRegInfo(cast(I)); + } + } + + FuncInfo->VisitedBBs.insert(LLVMBB); + } + + FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB]; + FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI(); + + BasicBlock::const_iterator const Begin = LLVMBB->getFirstNonPHI(); + BasicBlock::const_iterator const End = LLVMBB->end(); + BasicBlock::const_iterator BI = End; + + FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI(); + + // Setup an EH landing-pad block. + if (FuncInfo->MBB->isLandingPad()) + PrepareEHLandingPad(); + + // Lower any arguments needed in this block if this is the entry block. + if (LLVMBB == &Fn.getEntryBlock()) + LowerArguments(LLVMBB); + + // Before doing SelectionDAG ISel, see if FastISel has been requested. + if (FastIS) { + FastIS->startNewBlock(); + + // Emit code for any incoming arguments. This must happen before + // beginning FastISel on the entry block. + if (LLVMBB == &Fn.getEntryBlock()) { + CurDAG->setRoot(SDB->getControlRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + + // If we inserted any instructions at the beginning, make a note of + // where they are, so we can be sure to emit subsequent instructions + // after them. + if (FuncInfo->InsertPt != FuncInfo->MBB->begin()) + FastIS->setLastLocalValue(llvm::prior(FuncInfo->InsertPt)); + else + FastIS->setLastLocalValue(0); + } + + // Do FastISel on as many instructions as possible. + for (; BI != Begin; --BI) { + const Instruction *Inst = llvm::prior(BI); + + // If we no longer require this instruction, skip it. + if (!Inst->mayWriteToMemory() && + !isa(Inst) && + !isa(Inst) && + !FuncInfo->isExportedInst(Inst)) + continue; + + // Bottom-up: reset the insert pos at the top, after any local-value + // instructions. + FastIS->recomputeInsertPt(); + + // Try to select the instruction with FastISel. + if (FastIS->SelectInstruction(Inst)) { + // If fast isel succeeded, check to see if there is a single-use + // non-volatile load right before the selected instruction, and see if + // the load is used by the instruction. If so, try to fold it. + const Instruction *BeforeInst = 0; + if (Inst != Begin) + BeforeInst = llvm::prior(llvm::prior(BI)); + if (BeforeInst && isa(BeforeInst) && + BeforeInst->hasOneUse() && *BeforeInst->use_begin() == Inst && + TryToFoldFastISelLoad(cast(BeforeInst), FastIS)) + --BI; // If we succeeded, don't re-select the load. + continue; + } + + // Then handle certain instructions as single-LLVM-Instruction blocks. + if (isa(Inst)) { + ++NumFastIselFailures; + if (EnableFastISelVerbose || EnableFastISelAbort) { + dbgs() << "FastISel missed call: "; + Inst->dump(); + } + + if (!Inst->getType()->isVoidTy() && !Inst->use_empty()) { + unsigned &R = FuncInfo->ValueMap[Inst]; + if (!R) + R = FuncInfo->CreateRegs(Inst->getType()); + } + + bool HadTailCall = false; + SelectBasicBlock(Inst, BI, HadTailCall); + + // If the call was emitted as a tail call, we're done with the block. + if (HadTailCall) { + --BI; + break; + } + + continue; + } + + // Otherwise, give up on FastISel for the rest of the block. + // For now, be a little lenient about non-branch terminators. + if (!isa(Inst) || isa(Inst)) { + ++NumFastIselFailures; + if (EnableFastISelVerbose || EnableFastISelAbort) { + dbgs() << "FastISel miss: "; + Inst->dump(); + } + if (EnableFastISelAbort) + // The "fast" selector couldn't handle something and bailed. + // For the purpose of debugging, just abort. + llvm_unreachable("FastISel didn't select the entire block"); + } + break; + } + + FastIS->recomputeInsertPt(); + } + + if (Begin != BI) + ++NumDAGBlocks; + else + ++NumFastIselBlocks; + + // Run SelectionDAG instruction selection on the remainder of the block + // not handled by FastISel. If FastISel is not run, this is the entire + // block. + bool HadTailCall; + SelectBasicBlock(Begin, BI, HadTailCall); + + FinishBasicBlock(); + FuncInfo->PHINodesToUpdate.clear(); + } + + delete FastIS; +#ifndef NDEBUG + for (MachineFunction::const_iterator MBI = MF->begin(), MBE = MF->end(); + MBI != MBE; ++MBI) + CheckLineNumbers(MBI); +#endif +} + +void +SelectionDAGISel::FinishBasicBlock() { + + DEBUG(dbgs() << "Total amount of phi nodes to update: " + << FuncInfo->PHINodesToUpdate.size() << "\n"; + for (unsigned i = 0, e = FuncInfo->PHINodesToUpdate.size(); i != e; ++i) + dbgs() << "Node " << i << " : (" + << FuncInfo->PHINodesToUpdate[i].first + << ", " << FuncInfo->PHINodesToUpdate[i].second << ")\n"); + + // Next, now that we know what the last MBB the LLVM BB expanded is, update + // PHI nodes in successors. + if (SDB->SwitchCases.empty() && + SDB->JTCases.empty() && + SDB->BitTestCases.empty()) { + for (unsigned i = 0, e = FuncInfo->PHINodesToUpdate.size(); i != e; ++i) { + MachineInstr *PHI = FuncInfo->PHINodesToUpdate[i].first; + assert(PHI->isPHI() && + "This is not a machine PHI node that we are updating!"); + if (!FuncInfo->MBB->isSuccessor(PHI->getParent())) + continue; + PHI->addOperand( + MachineOperand::CreateReg(FuncInfo->PHINodesToUpdate[i].second, false)); + PHI->addOperand(MachineOperand::CreateMBB(FuncInfo->MBB)); + } + return; + } + + for (unsigned i = 0, e = SDB->BitTestCases.size(); i != e; ++i) { + // Lower header first, if it wasn't already lowered + if (!SDB->BitTestCases[i].Emitted) { + // Set the current basic block to the mbb we wish to insert the code into + FuncInfo->MBB = SDB->BitTestCases[i].Parent; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + // Emit the code + SDB->visitBitTestHeader(SDB->BitTestCases[i], FuncInfo->MBB); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + } + + for (unsigned j = 0, ej = SDB->BitTestCases[i].Cases.size(); j != ej; ++j) { + // Set the current basic block to the mbb we wish to insert the code into + FuncInfo->MBB = SDB->BitTestCases[i].Cases[j].ThisBB; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + // Emit the code + if (j+1 != ej) + SDB->visitBitTestCase(SDB->BitTestCases[i], + SDB->BitTestCases[i].Cases[j+1].ThisBB, + SDB->BitTestCases[i].Reg, + SDB->BitTestCases[i].Cases[j], + FuncInfo->MBB); + else + SDB->visitBitTestCase(SDB->BitTestCases[i], + SDB->BitTestCases[i].Default, + SDB->BitTestCases[i].Reg, + SDB->BitTestCases[i].Cases[j], + FuncInfo->MBB); + + + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + } + + // Update PHI Nodes + for (unsigned pi = 0, pe = FuncInfo->PHINodesToUpdate.size(); + pi != pe; ++pi) { + MachineInstr *PHI = FuncInfo->PHINodesToUpdate[pi].first; + MachineBasicBlock *PHIBB = PHI->getParent(); + assert(PHI->isPHI() && + "This is not a machine PHI node that we are updating!"); + // This is "default" BB. We have two jumps to it. From "header" BB and + // from last "case" BB. + if (PHIBB == SDB->BitTestCases[i].Default) { + PHI->addOperand(MachineOperand:: + CreateReg(FuncInfo->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(SDB->BitTestCases[i].Parent)); + PHI->addOperand(MachineOperand:: + CreateReg(FuncInfo->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(SDB->BitTestCases[i].Cases. + back().ThisBB)); + } + // One of "cases" BB. + for (unsigned j = 0, ej = SDB->BitTestCases[i].Cases.size(); + j != ej; ++j) { + MachineBasicBlock* cBB = SDB->BitTestCases[i].Cases[j].ThisBB; + if (cBB->isSuccessor(PHIBB)) { + PHI->addOperand(MachineOperand:: + CreateReg(FuncInfo->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(cBB)); + } + } + } + } + SDB->BitTestCases.clear(); + + // If the JumpTable record is filled in, then we need to emit a jump table. + // Updating the PHI nodes is tricky in this case, since we need to determine + // whether the PHI is a successor of the range check MBB or the jump table MBB + for (unsigned i = 0, e = SDB->JTCases.size(); i != e; ++i) { + // Lower header first, if it wasn't already lowered + if (!SDB->JTCases[i].first.Emitted) { + // Set the current basic block to the mbb we wish to insert the code into + FuncInfo->MBB = SDB->JTCases[i].first.HeaderBB; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + // Emit the code + SDB->visitJumpTableHeader(SDB->JTCases[i].second, SDB->JTCases[i].first, + FuncInfo->MBB); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + } + + // Set the current basic block to the mbb we wish to insert the code into + FuncInfo->MBB = SDB->JTCases[i].second.MBB; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + // Emit the code + SDB->visitJumpTable(SDB->JTCases[i].second); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + + // Update PHI Nodes + for (unsigned pi = 0, pe = FuncInfo->PHINodesToUpdate.size(); + pi != pe; ++pi) { + MachineInstr *PHI = FuncInfo->PHINodesToUpdate[pi].first; + MachineBasicBlock *PHIBB = PHI->getParent(); + assert(PHI->isPHI() && + "This is not a machine PHI node that we are updating!"); + // "default" BB. We can go there only from header BB. + if (PHIBB == SDB->JTCases[i].second.Default) { + PHI->addOperand + (MachineOperand::CreateReg(FuncInfo->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand + (MachineOperand::CreateMBB(SDB->JTCases[i].first.HeaderBB)); + } + // JT BB. Just iterate over successors here + if (FuncInfo->MBB->isSuccessor(PHIBB)) { + PHI->addOperand + (MachineOperand::CreateReg(FuncInfo->PHINodesToUpdate[pi].second, + false)); + PHI->addOperand(MachineOperand::CreateMBB(FuncInfo->MBB)); + } + } + } + SDB->JTCases.clear(); + + // If the switch block involved a branch to one of the actual successors, we + // need to update PHI nodes in that block. + for (unsigned i = 0, e = FuncInfo->PHINodesToUpdate.size(); i != e; ++i) { + MachineInstr *PHI = FuncInfo->PHINodesToUpdate[i].first; + assert(PHI->isPHI() && + "This is not a machine PHI node that we are updating!"); + if (FuncInfo->MBB->isSuccessor(PHI->getParent())) { + PHI->addOperand( + MachineOperand::CreateReg(FuncInfo->PHINodesToUpdate[i].second, false)); + PHI->addOperand(MachineOperand::CreateMBB(FuncInfo->MBB)); + } + } + + // If we generated any switch lowering information, build and codegen any + // additional DAGs necessary. + for (unsigned i = 0, e = SDB->SwitchCases.size(); i != e; ++i) { + // Set the current basic block to the mbb we wish to insert the code into + FuncInfo->MBB = SDB->SwitchCases[i].ThisBB; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + + // Determine the unique successors. + SmallVector Succs; + Succs.push_back(SDB->SwitchCases[i].TrueBB); + if (SDB->SwitchCases[i].TrueBB != SDB->SwitchCases[i].FalseBB) + Succs.push_back(SDB->SwitchCases[i].FalseBB); + + // Emit the code. Note that this could result in FuncInfo->MBB being split. + SDB->visitSwitchCase(SDB->SwitchCases[i], FuncInfo->MBB); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + + // Remember the last block, now that any splitting is done, for use in + // populating PHI nodes in successors. + MachineBasicBlock *ThisBB = FuncInfo->MBB; + + // Handle any PHI nodes in successors of this chunk, as if we were coming + // from the original BB before switch expansion. Note that PHI nodes can + // occur multiple times in PHINodesToUpdate. We have to be very careful to + // handle them the right number of times. + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + FuncInfo->MBB = Succs[i]; + FuncInfo->InsertPt = FuncInfo->MBB->end(); + // FuncInfo->MBB may have been removed from the CFG if a branch was + // constant folded. + if (ThisBB->isSuccessor(FuncInfo->MBB)) { + for (MachineBasicBlock::iterator Phi = FuncInfo->MBB->begin(); + Phi != FuncInfo->MBB->end() && Phi->isPHI(); + ++Phi) { + // This value for this PHI node is recorded in PHINodesToUpdate. + for (unsigned pn = 0; ; ++pn) { + assert(pn != FuncInfo->PHINodesToUpdate.size() && + "Didn't find PHI entry!"); + if (FuncInfo->PHINodesToUpdate[pn].first == Phi) { + Phi->addOperand(MachineOperand:: + CreateReg(FuncInfo->PHINodesToUpdate[pn].second, + false)); + Phi->addOperand(MachineOperand::CreateMBB(ThisBB)); + break; + } + } + } + } + } + } + SDB->SwitchCases.clear(); +} + + +/// Create the scheduler. If a specific scheduler was specified +/// via the SchedulerRegistry, use it, otherwise select the +/// one preferred by the target. +/// +ScheduleDAGSDNodes *SelectionDAGISel::CreateScheduler() { + RegisterScheduler::FunctionPassCtor Ctor = RegisterScheduler::getDefault(); + + if (!Ctor) { + Ctor = ISHeuristic; + RegisterScheduler::setDefault(Ctor); + } + + return Ctor(this, OptLevel); +} + +//===----------------------------------------------------------------------===// +// Helper functions used by the generated instruction selector. +//===----------------------------------------------------------------------===// +// Calls to these methods are generated by tblgen. + +/// CheckAndMask - The isel is trying to match something like (and X, 255). If +/// the dag combiner simplified the 255, we still want to match. RHS is the +/// actual value in the DAG on the RHS of an AND, and DesiredMaskS is the value +/// specified in the .td file (e.g. 255). +bool SelectionDAGISel::CheckAndMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const { + const APInt &ActualMask = RHS->getAPIntValue(); + const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS); + + // If the actual mask exactly matches, success! + if (ActualMask == DesiredMask) + return true; + + // If the actual AND mask is allowing unallowed bits, this doesn't match. + if (ActualMask.intersects(~DesiredMask)) + return false; + + // Otherwise, the DAG Combiner may have proven that the value coming in is + // either already zero or is not demanded. Check for known zero input bits. + APInt NeededMask = DesiredMask & ~ActualMask; + if (CurDAG->MaskedValueIsZero(LHS, NeededMask)) + return true; + + // TODO: check to see if missing bits are just not demanded. + + // Otherwise, this pattern doesn't match. + return false; +} + +/// CheckOrMask - The isel is trying to match something like (or X, 255). If +/// the dag combiner simplified the 255, we still want to match. RHS is the +/// actual value in the DAG on the RHS of an OR, and DesiredMaskS is the value +/// specified in the .td file (e.g. 255). +bool SelectionDAGISel::CheckOrMask(SDValue LHS, ConstantSDNode *RHS, + int64_t DesiredMaskS) const { + const APInt &ActualMask = RHS->getAPIntValue(); + const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS); + + // If the actual mask exactly matches, success! + if (ActualMask == DesiredMask) + return true; + + // If the actual AND mask is allowing unallowed bits, this doesn't match. + if (ActualMask.intersects(~DesiredMask)) + return false; + + // Otherwise, the DAG Combiner may have proven that the value coming in is + // either already zero or is not demanded. Check for known zero input bits. + APInt NeededMask = DesiredMask & ~ActualMask; + + APInt KnownZero, KnownOne; + CurDAG->ComputeMaskedBits(LHS, NeededMask, KnownZero, KnownOne); + + // If all the missing bits in the or are already known to be set, match! + if ((NeededMask & KnownOne) == NeededMask) + return true; + + // TODO: check to see if missing bits are just not demanded. + + // Otherwise, this pattern doesn't match. + return false; +} + + +/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated +/// by tblgen. Others should not call it. +void SelectionDAGISel:: +SelectInlineAsmMemoryOperands(std::vector &Ops) { + std::vector InOps; + std::swap(InOps, Ops); + + Ops.push_back(InOps[InlineAsm::Op_InputChain]); // 0 + Ops.push_back(InOps[InlineAsm::Op_AsmString]); // 1 + Ops.push_back(InOps[InlineAsm::Op_MDNode]); // 2, !srcloc + Ops.push_back(InOps[InlineAsm::Op_ExtraInfo]); // 3 (SideEffect, AlignStack) + + unsigned i = InlineAsm::Op_FirstOperand, e = InOps.size(); + if (InOps[e-1].getValueType() == MVT::Glue) + --e; // Don't process a glue operand if it is here. + + while (i != e) { + unsigned Flags = cast(InOps[i])->getZExtValue(); + if (!InlineAsm::isMemKind(Flags)) { + // Just skip over this operand, copying the operands verbatim. + Ops.insert(Ops.end(), InOps.begin()+i, + InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1); + i += InlineAsm::getNumOperandRegisters(Flags) + 1; + } else { + assert(InlineAsm::getNumOperandRegisters(Flags) == 1 && + "Memory operand with multiple values?"); + // Otherwise, this is a memory operand. Ask the target to select it. + std::vector SelOps; + if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) + report_fatal_error("Could not match memory address. Inline asm" + " failure!"); + + // Add this to the output node. + unsigned NewFlags = + InlineAsm::getFlagWord(InlineAsm::Kind_Mem, SelOps.size()); + Ops.push_back(CurDAG->getTargetConstant(NewFlags, MVT::i32)); + Ops.insert(Ops.end(), SelOps.begin(), SelOps.end()); + i += 2; + } + } + + // Add the glue input back if present. + if (e != InOps.size()) + Ops.push_back(InOps.back()); +} + +/// findGlueUse - Return use of MVT::Glue value produced by the specified +/// SDNode. +/// +static SDNode *findGlueUse(SDNode *N) { + unsigned FlagResNo = N->getNumValues()-1; + for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { + SDUse &Use = I.getUse(); + if (Use.getResNo() == FlagResNo) + return Use.getUser(); + } + return NULL; +} + +/// findNonImmUse - Return true if "Use" is a non-immediate use of "Def". +/// This function recursively traverses up the operand chain, ignoring +/// certain nodes. +static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, + SDNode *Root, SmallPtrSet &Visited, + bool IgnoreChains) { + // The NodeID's are given uniques ID's where a node ID is guaranteed to be + // greater than all of its (recursive) operands. If we scan to a point where + // 'use' is smaller than the node we're scanning for, then we know we will + // never find it. + // + // The Use may be -1 (unassigned) if it is a newly allocated node. This can + // happen because we scan down to newly selected nodes in the case of glue + // uses. + if ((Use->getNodeId() < Def->getNodeId() && Use->getNodeId() != -1)) + return false; + + // Don't revisit nodes if we already scanned it and didn't fail, we know we + // won't fail if we scan it again. + if (!Visited.insert(Use)) + return false; + + for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) { + // Ignore chain uses, they are validated by HandleMergeInputChains. + if (Use->getOperand(i).getValueType() == MVT::Other && IgnoreChains) + continue; + + SDNode *N = Use->getOperand(i).getNode(); + if (N == Def) { + if (Use == ImmedUse || Use == Root) + continue; // We are not looking for immediate use. + assert(N != Root); + return true; + } + + // Traverse up the operand chain. + if (findNonImmUse(N, Def, ImmedUse, Root, Visited, IgnoreChains)) + return true; + } + return false; +} + +/// IsProfitableToFold - Returns true if it's profitable to fold the specific +/// operand node N of U during instruction selection that starts at Root. +bool SelectionDAGISel::IsProfitableToFold(SDValue N, SDNode *U, + SDNode *Root) const { + if (OptLevel == CodeGenOpt::None) return false; + return N.hasOneUse(); +} + +/// IsLegalToFold - Returns true if the specific operand node N of +/// U can be folded during instruction selection that starts at Root. +bool SelectionDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, + CodeGenOpt::Level OptLevel, + bool IgnoreChains) { + if (OptLevel == CodeGenOpt::None) return false; + + // If Root use can somehow reach N through a path that that doesn't contain + // U then folding N would create a cycle. e.g. In the following + // diagram, Root can reach N through X. If N is folded into into Root, then + // X is both a predecessor and a successor of U. + // + // [N*] // + // ^ ^ // + // / \ // + // [U*] [X]? // + // ^ ^ // + // \ / // + // \ / // + // [Root*] // + // + // * indicates nodes to be folded together. + // + // If Root produces glue, then it gets (even more) interesting. Since it + // will be "glued" together with its glue use in the scheduler, we need to + // check if it might reach N. + // + // [N*] // + // ^ ^ // + // / \ // + // [U*] [X]? // + // ^ ^ // + // \ \ // + // \ | // + // [Root*] | // + // ^ | // + // f | // + // | / // + // [Y] / // + // ^ / // + // f / // + // | / // + // [GU] // + // + // If GU (glue use) indirectly reaches N (the load), and Root folds N + // (call it Fold), then X is a predecessor of GU and a successor of + // Fold. But since Fold and GU are glued together, this will create + // a cycle in the scheduling graph. + + // If the node has glue, walk down the graph to the "lowest" node in the + // glueged set. + EVT VT = Root->getValueType(Root->getNumValues()-1); + while (VT == MVT::Glue) { + SDNode *GU = findGlueUse(Root); + if (GU == NULL) + break; + Root = GU; + VT = Root->getValueType(Root->getNumValues()-1); + + // If our query node has a glue result with a use, we've walked up it. If + // the user (which has already been selected) has a chain or indirectly uses + // the chain, our WalkChainUsers predicate will not consider it. Because of + // this, we cannot ignore chains in this predicate. + IgnoreChains = false; + } + + + SmallPtrSet Visited; + return !findNonImmUse(Root, N.getNode(), U, Root, Visited, IgnoreChains); +} + +SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) { + std::vector Ops(N->op_begin(), N->op_end()); + SelectInlineAsmMemoryOperands(Ops); + + std::vector VTs; + VTs.push_back(MVT::Other); + VTs.push_back(MVT::Glue); + SDValue New = CurDAG->getNode(ISD::INLINEASM, N->getDebugLoc(), + VTs, &Ops[0], Ops.size()); + New->setNodeId(-1); + return New.getNode(); +} + +SDNode *SelectionDAGISel::Select_UNDEF(SDNode *N) { + return CurDAG->SelectNodeTo(N, TargetOpcode::IMPLICIT_DEF,N->getValueType(0)); +} + +/// GetVBR - decode a vbr encoding whose top bit is set. +LLVM_ATTRIBUTE_ALWAYS_INLINE static uint64_t +GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) { + assert(Val >= 128 && "Not a VBR"); + Val &= 127; // Remove first vbr bit. + + unsigned Shift = 7; + uint64_t NextBits; + do { + NextBits = MatcherTable[Idx++]; + Val |= (NextBits&127) << Shift; + Shift += 7; + } while (NextBits & 128); + + return Val; +} + + +/// UpdateChainsAndGlue - When a match is complete, this method updates uses of +/// interior glue and chain results to use the new glue and chain results. +void SelectionDAGISel:: +UpdateChainsAndGlue(SDNode *NodeToMatch, SDValue InputChain, + const SmallVectorImpl &ChainNodesMatched, + SDValue InputGlue, + const SmallVectorImpl &GlueResultNodesMatched, + bool isMorphNodeTo) { + SmallVector NowDeadNodes; + + ISelUpdater ISU(ISelPosition); + + // Now that all the normal results are replaced, we replace the chain and + // glue results if present. + if (!ChainNodesMatched.empty()) { + assert(InputChain.getNode() != 0 && + "Matched input chains but didn't produce a chain"); + // Loop over all of the nodes we matched that produced a chain result. + // Replace all the chain results with the final chain we ended up with. + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + SDNode *ChainNode = ChainNodesMatched[i]; + + // If this node was already deleted, don't look at it. + if (ChainNode->getOpcode() == ISD::DELETED_NODE) + continue; + + // Don't replace the results of the root node if we're doing a + // MorphNodeTo. + if (ChainNode == NodeToMatch && isMorphNodeTo) + continue; + + SDValue ChainVal = SDValue(ChainNode, ChainNode->getNumValues()-1); + if (ChainVal.getValueType() == MVT::Glue) + ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2); + assert(ChainVal.getValueType() == MVT::Other && "Not a chain?"); + CurDAG->ReplaceAllUsesOfValueWith(ChainVal, InputChain, &ISU); + + // If the node became dead and we haven't already seen it, delete it. + if (ChainNode->use_empty() && + !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), ChainNode)) + NowDeadNodes.push_back(ChainNode); + } + } + + // If the result produces glue, update any glue results in the matched + // pattern with the glue result. + if (InputGlue.getNode() != 0) { + // Handle any interior nodes explicitly marked. + for (unsigned i = 0, e = GlueResultNodesMatched.size(); i != e; ++i) { + SDNode *FRN = GlueResultNodesMatched[i]; + + // If this node was already deleted, don't look at it. + if (FRN->getOpcode() == ISD::DELETED_NODE) + continue; + + assert(FRN->getValueType(FRN->getNumValues()-1) == MVT::Glue && + "Doesn't have a glue result"); + CurDAG->ReplaceAllUsesOfValueWith(SDValue(FRN, FRN->getNumValues()-1), + InputGlue, &ISU); + + // If the node became dead and we haven't already seen it, delete it. + if (FRN->use_empty() && + !std::count(NowDeadNodes.begin(), NowDeadNodes.end(), FRN)) + NowDeadNodes.push_back(FRN); + } + } + + if (!NowDeadNodes.empty()) + CurDAG->RemoveDeadNodes(NowDeadNodes, &ISU); + + DEBUG(errs() << "ISEL: Match complete!\n"); +} + +enum ChainResult { + CR_Simple, + CR_InducesCycle, + CR_LeadsToInteriorNode +}; + +/// WalkChainUsers - Walk down the users of the specified chained node that is +/// part of the pattern we're matching, looking at all of the users we find. +/// This determines whether something is an interior node, whether we have a +/// non-pattern node in between two pattern nodes (which prevent folding because +/// it would induce a cycle) and whether we have a TokenFactor node sandwiched +/// between pattern nodes (in which case the TF becomes part of the pattern). +/// +/// The walk we do here is guaranteed to be small because we quickly get down to +/// already selected nodes "below" us. +static ChainResult +WalkChainUsers(SDNode *ChainedNode, + SmallVectorImpl &ChainedNodesInPattern, + SmallVectorImpl &InteriorChainedNodes) { + ChainResult Result = CR_Simple; + + for (SDNode::use_iterator UI = ChainedNode->use_begin(), + E = ChainedNode->use_end(); UI != E; ++UI) { + // Make sure the use is of the chain, not some other value we produce. + if (UI.getUse().getValueType() != MVT::Other) continue; + + SDNode *User = *UI; + + // If we see an already-selected machine node, then we've gone beyond the + // pattern that we're selecting down into the already selected chunk of the + // DAG. + if (User->isMachineOpcode() || + User->getOpcode() == ISD::HANDLENODE) // Root of the graph. + continue; + + if (User->getOpcode() == ISD::CopyToReg || + User->getOpcode() == ISD::CopyFromReg || + User->getOpcode() == ISD::INLINEASM || + User->getOpcode() == ISD::EH_LABEL) { + // If their node ID got reset to -1 then they've already been selected. + // Treat them like a MachineOpcode. + if (User->getNodeId() == -1) + continue; + } + + // If we have a TokenFactor, we handle it specially. + if (User->getOpcode() != ISD::TokenFactor) { + // If the node isn't a token factor and isn't part of our pattern, then it + // must be a random chained node in between two nodes we're selecting. + // This happens when we have something like: + // x = load ptr + // call + // y = x+4 + // store y -> ptr + // Because we structurally match the load/store as a read/modify/write, + // but the call is chained between them. We cannot fold in this case + // because it would induce a cycle in the graph. + if (!std::count(ChainedNodesInPattern.begin(), + ChainedNodesInPattern.end(), User)) + return CR_InducesCycle; + + // Otherwise we found a node that is part of our pattern. For example in: + // x = load ptr + // y = x+4 + // store y -> ptr + // This would happen when we're scanning down from the load and see the + // store as a user. Record that there is a use of ChainedNode that is + // part of the pattern and keep scanning uses. + Result = CR_LeadsToInteriorNode; + InteriorChainedNodes.push_back(User); + continue; + } + + // If we found a TokenFactor, there are two cases to consider: first if the + // TokenFactor is just hanging "below" the pattern we're matching (i.e. no + // uses of the TF are in our pattern) we just want to ignore it. Second, + // the TokenFactor can be sandwiched in between two chained nodes, like so: + // [Load chain] + // ^ + // | + // [Load] + // ^ ^ + // | \ DAG's like cheese + // / \ do you? + // / | + // [TokenFactor] [Op] + // ^ ^ + // | | + // \ / + // \ / + // [Store] + // + // In this case, the TokenFactor becomes part of our match and we rewrite it + // as a new TokenFactor. + // + // To distinguish these two cases, do a recursive walk down the uses. + switch (WalkChainUsers(User, ChainedNodesInPattern, InteriorChainedNodes)) { + case CR_Simple: + // If the uses of the TokenFactor are just already-selected nodes, ignore + // it, it is "below" our pattern. + continue; + case CR_InducesCycle: + // If the uses of the TokenFactor lead to nodes that are not part of our + // pattern that are not selected, folding would turn this into a cycle, + // bail out now. + return CR_InducesCycle; + case CR_LeadsToInteriorNode: + break; // Otherwise, keep processing. + } + + // Okay, we know we're in the interesting interior case. The TokenFactor + // is now going to be considered part of the pattern so that we rewrite its + // uses (it may have uses that are not part of the pattern) with the + // ultimate chain result of the generated code. We will also add its chain + // inputs as inputs to the ultimate TokenFactor we create. + Result = CR_LeadsToInteriorNode; + ChainedNodesInPattern.push_back(User); + InteriorChainedNodes.push_back(User); + continue; + } + + return Result; +} + +/// HandleMergeInputChains - This implements the OPC_EmitMergeInputChains +/// operation for when the pattern matched at least one node with a chains. The +/// input vector contains a list of all of the chained nodes that we match. We +/// must determine if this is a valid thing to cover (i.e. matching it won't +/// induce cycles in the DAG) and if so, creating a TokenFactor node. that will +/// be used as the input node chain for the generated nodes. +static SDValue +HandleMergeInputChains(SmallVectorImpl &ChainNodesMatched, + SelectionDAG *CurDAG) { + // Walk all of the chained nodes we've matched, recursively scanning down the + // users of the chain result. This adds any TokenFactor nodes that are caught + // in between chained nodes to the chained and interior nodes list. + SmallVector InteriorChainedNodes; + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + if (WalkChainUsers(ChainNodesMatched[i], ChainNodesMatched, + InteriorChainedNodes) == CR_InducesCycle) + return SDValue(); // Would induce a cycle. + } + + // Okay, we have walked all the matched nodes and collected TokenFactor nodes + // that we are interested in. Form our input TokenFactor node. + SmallVector InputChains; + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + // Add the input chain of this node to the InputChains list (which will be + // the operands of the generated TokenFactor) if it's not an interior node. + SDNode *N = ChainNodesMatched[i]; + if (N->getOpcode() != ISD::TokenFactor) { + if (std::count(InteriorChainedNodes.begin(),InteriorChainedNodes.end(),N)) + continue; + + // Otherwise, add the input chain. + SDValue InChain = ChainNodesMatched[i]->getOperand(0); + assert(InChain.getValueType() == MVT::Other && "Not a chain"); + InputChains.push_back(InChain); + continue; + } + + // If we have a token factor, we want to add all inputs of the token factor + // that are not part of the pattern we're matching. + for (unsigned op = 0, e = N->getNumOperands(); op != e; ++op) { + if (!std::count(ChainNodesMatched.begin(), ChainNodesMatched.end(), + N->getOperand(op).getNode())) + InputChains.push_back(N->getOperand(op)); + } + } + + SDValue Res; + if (InputChains.size() == 1) + return InputChains[0]; + return CurDAG->getNode(ISD::TokenFactor, ChainNodesMatched[0]->getDebugLoc(), + MVT::Other, &InputChains[0], InputChains.size()); +} + +/// MorphNode - Handle morphing a node in place for the selector. +SDNode *SelectionDAGISel:: +MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo) { + // It is possible we're using MorphNodeTo to replace a node with no + // normal results with one that has a normal result (or we could be + // adding a chain) and the input could have glue and chains as well. + // In this case we need to shift the operands down. + // FIXME: This is a horrible hack and broken in obscure cases, no worse + // than the old isel though. + int OldGlueResultNo = -1, OldChainResultNo = -1; + + unsigned NTMNumResults = Node->getNumValues(); + if (Node->getValueType(NTMNumResults-1) == MVT::Glue) { + OldGlueResultNo = NTMNumResults-1; + if (NTMNumResults != 1 && + Node->getValueType(NTMNumResults-2) == MVT::Other) + OldChainResultNo = NTMNumResults-2; + } else if (Node->getValueType(NTMNumResults-1) == MVT::Other) + OldChainResultNo = NTMNumResults-1; + + // Call the underlying SelectionDAG routine to do the transmogrification. Note + // that this deletes operands of the old node that become dead. + SDNode *Res = CurDAG->MorphNodeTo(Node, ~TargetOpc, VTList, Ops, NumOps); + + // MorphNodeTo can operate in two ways: if an existing node with the + // specified operands exists, it can just return it. Otherwise, it + // updates the node in place to have the requested operands. + if (Res == Node) { + // If we updated the node in place, reset the node ID. To the isel, + // this should be just like a newly allocated machine node. + Res->setNodeId(-1); + } + + unsigned ResNumResults = Res->getNumValues(); + // Move the glue if needed. + if ((EmitNodeInfo & OPFL_GlueOutput) && OldGlueResultNo != -1 && + (unsigned)OldGlueResultNo != ResNumResults-1) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldGlueResultNo), + SDValue(Res, ResNumResults-1)); + + if ((EmitNodeInfo & OPFL_GlueOutput) != 0) + --ResNumResults; + + // Move the chain reference if needed. + if ((EmitNodeInfo & OPFL_Chain) && OldChainResultNo != -1 && + (unsigned)OldChainResultNo != ResNumResults-1) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldChainResultNo), + SDValue(Res, ResNumResults-1)); + + // Otherwise, no replacement happened because the node already exists. Replace + // Uses of the old node with the new one. + if (Res != Node) + CurDAG->ReplaceAllUsesWith(Node, Res); + + return Res; +} + +/// CheckPatternPredicate - Implements OP_CheckPatternPredicate. +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckSame(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, + const SmallVectorImpl > &RecordedNodes) { + // Accept if it is exactly the same as a previously recorded node. + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + return N == RecordedNodes[RecNo].first; +} + +/// CheckPatternPredicate - Implements OP_CheckPatternPredicate. +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckPatternPredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SelectionDAGISel &SDISel) { + return SDISel.CheckPatternPredicate(MatcherTable[MatcherIndex++]); +} + +/// CheckNodePredicate - Implements OP_CheckNodePredicate. +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckNodePredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SelectionDAGISel &SDISel, SDNode *N) { + return SDISel.CheckNodePredicate(N, MatcherTable[MatcherIndex++]); +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckOpcode(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDNode *N) { + uint16_t Opc = MatcherTable[MatcherIndex++]; + Opc |= (unsigned short)MatcherTable[MatcherIndex++] << 8; + return N->getOpcode() == Opc; +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI) { + MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (N.getValueType() == VT) return true; + + // Handle the case when VT is iPTR. + return VT == MVT::iPTR && N.getValueType() == TLI.getPointerTy(); +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckChildType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI, + unsigned ChildNo) { + if (ChildNo >= N.getNumOperands()) + return false; // Match fails if out of range child #. + return ::CheckType(MatcherTable, MatcherIndex, N.getOperand(ChildNo), TLI); +} + + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckCondCode(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N) { + return cast(N)->get() == + (ISD::CondCode)MatcherTable[MatcherIndex++]; +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckValueType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI) { + MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (cast(N)->getVT() == VT) + return true; + + // Handle the case when VT is iPTR. + return VT == MVT::iPTR && cast(N)->getVT() == TLI.getPointerTy(); +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckInteger(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + ConstantSDNode *C = dyn_cast(N); + return C != 0 && C->getSExtValue() == Val; +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckAndImm(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, SelectionDAGISel &SDISel) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + if (N->getOpcode() != ISD::AND) return false; + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + return C != 0 && SDISel.CheckAndMask(N.getOperand(0), C, Val); +} + +LLVM_ATTRIBUTE_ALWAYS_INLINE static bool +CheckOrImm(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, SelectionDAGISel &SDISel) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + if (N->getOpcode() != ISD::OR) return false; + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + return C != 0 && SDISel.CheckOrMask(N.getOperand(0), C, Val); +} + +/// IsPredicateKnownToFail - If we know how and can do so without pushing a +/// scope, evaluate the current node. If the current predicate is known to +/// fail, set Result=true and return anything. If the current predicate is +/// known to pass, set Result=false and return the MatcherIndex to continue +/// with. If the current predicate is unknown, set Result=false and return the +/// MatcherIndex to continue with. +static unsigned IsPredicateKnownToFail(const unsigned char *Table, + unsigned Index, SDValue N, + bool &Result, SelectionDAGISel &SDISel, + SmallVectorImpl > &RecordedNodes) { + switch (Table[Index++]) { + default: + Result = false; + return Index-1; // Could not evaluate this predicate. + case SelectionDAGISel::OPC_CheckSame: + Result = !::CheckSame(Table, Index, N, RecordedNodes); + return Index; + case SelectionDAGISel::OPC_CheckPatternPredicate: + Result = !::CheckPatternPredicate(Table, Index, SDISel); + return Index; + case SelectionDAGISel::OPC_CheckPredicate: + Result = !::CheckNodePredicate(Table, Index, SDISel, N.getNode()); + return Index; + case SelectionDAGISel::OPC_CheckOpcode: + Result = !::CheckOpcode(Table, Index, N.getNode()); + return Index; + case SelectionDAGISel::OPC_CheckType: + Result = !::CheckType(Table, Index, N, SDISel.TLI); + return Index; + case SelectionDAGISel::OPC_CheckChild0Type: + case SelectionDAGISel::OPC_CheckChild1Type: + case SelectionDAGISel::OPC_CheckChild2Type: + case SelectionDAGISel::OPC_CheckChild3Type: + case SelectionDAGISel::OPC_CheckChild4Type: + case SelectionDAGISel::OPC_CheckChild5Type: + case SelectionDAGISel::OPC_CheckChild6Type: + case SelectionDAGISel::OPC_CheckChild7Type: + Result = !::CheckChildType(Table, Index, N, SDISel.TLI, + Table[Index-1] - SelectionDAGISel::OPC_CheckChild0Type); + return Index; + case SelectionDAGISel::OPC_CheckCondCode: + Result = !::CheckCondCode(Table, Index, N); + return Index; + case SelectionDAGISel::OPC_CheckValueType: + Result = !::CheckValueType(Table, Index, N, SDISel.TLI); + return Index; + case SelectionDAGISel::OPC_CheckInteger: + Result = !::CheckInteger(Table, Index, N); + return Index; + case SelectionDAGISel::OPC_CheckAndImm: + Result = !::CheckAndImm(Table, Index, N, SDISel); + return Index; + case SelectionDAGISel::OPC_CheckOrImm: + Result = !::CheckOrImm(Table, Index, N, SDISel); + return Index; + } +} + +namespace { + +struct MatchScope { + /// FailIndex - If this match fails, this is the index to continue with. + unsigned FailIndex; + + /// NodeStack - The node stack when the scope was formed. + SmallVector NodeStack; + + /// NumRecordedNodes - The number of recorded nodes when the scope was formed. + unsigned NumRecordedNodes; + + /// NumMatchedMemRefs - The number of matched memref entries. + unsigned NumMatchedMemRefs; + + /// InputChain/InputGlue - The current chain/glue + SDValue InputChain, InputGlue; + + /// HasChainNodesMatched - True if the ChainNodesMatched list is non-empty. + bool HasChainNodesMatched, HasGlueResultNodesMatched; +}; + +} + +SDNode *SelectionDAGISel:: +SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, + unsigned TableSize) { + // FIXME: Should these even be selected? Handle these cases in the caller? + switch (NodeToMatch->getOpcode()) { + default: + break; + case ISD::EntryToken: // These nodes remain the same. + case ISD::BasicBlock: + case ISD::Register: + //case ISD::VALUETYPE: + //case ISD::CONDCODE: + case ISD::HANDLENODE: + case ISD::MDNODE_SDNODE: + case ISD::TargetConstant: + case ISD::TargetConstantFP: + case ISD::TargetConstantPool: + case ISD::TargetFrameIndex: + case ISD::TargetExternalSymbol: + case ISD::TargetBlockAddress: + case ISD::TargetJumpTable: + case ISD::TargetGlobalTLSAddress: + case ISD::TargetGlobalAddress: + case ISD::TokenFactor: + case ISD::CopyFromReg: + case ISD::CopyToReg: + case ISD::EH_LABEL: + NodeToMatch->setNodeId(-1); // Mark selected. + return 0; + case ISD::AssertSext: + case ISD::AssertZext: + CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, 0), + NodeToMatch->getOperand(0)); + return 0; + case ISD::INLINEASM: return Select_INLINEASM(NodeToMatch); + case ISD::UNDEF: return Select_UNDEF(NodeToMatch); + } + + assert(!NodeToMatch->isMachineOpcode() && "Node already selected!"); + + // Set up the node stack with NodeToMatch as the only node on the stack. + SmallVector NodeStack; + SDValue N = SDValue(NodeToMatch, 0); + NodeStack.push_back(N); + + // MatchScopes - Scopes used when matching, if a match failure happens, this + // indicates where to continue checking. + SmallVector MatchScopes; + + // RecordedNodes - This is the set of nodes that have been recorded by the + // state machine. The second value is the parent of the node, or null if the + // root is recorded. + SmallVector, 8> RecordedNodes; + + // MatchedMemRefs - This is the set of MemRef's we've seen in the input + // pattern. + SmallVector MatchedMemRefs; + + // These are the current input chain and glue for use when generating nodes. + // Various Emit operations change these. For example, emitting a copytoreg + // uses and updates these. + SDValue InputChain, InputGlue; + + // ChainNodesMatched - If a pattern matches nodes that have input/output + // chains, the OPC_EmitMergeInputChains operation is emitted which indicates + // which ones they are. The result is captured into this list so that we can + // update the chain results when the pattern is complete. + SmallVector ChainNodesMatched; + SmallVector GlueResultNodesMatched; + + DEBUG(errs() << "ISEL: Starting pattern match on root node: "; + NodeToMatch->dump(CurDAG); + errs() << '\n'); + + // Determine where to start the interpreter. Normally we start at opcode #0, + // but if the state machine starts with an OPC_SwitchOpcode, then we + // accelerate the first lookup (which is guaranteed to be hot) with the + // OpcodeOffset table. + unsigned MatcherIndex = 0; + + if (!OpcodeOffset.empty()) { + // Already computed the OpcodeOffset table, just index into it. + if (N.getOpcode() < OpcodeOffset.size()) + MatcherIndex = OpcodeOffset[N.getOpcode()]; + DEBUG(errs() << " Initial Opcode index to " << MatcherIndex << "\n"); + + } else if (MatcherTable[0] == OPC_SwitchOpcode) { + // Otherwise, the table isn't computed, but the state machine does start + // with an OPC_SwitchOpcode instruction. Populate the table now, since this + // is the first time we're selecting an instruction. + unsigned Idx = 1; + while (1) { + // Get the size of this case. + unsigned CaseSize = MatcherTable[Idx++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, Idx); + if (CaseSize == 0) break; + + // Get the opcode, add the index to the table. + uint16_t Opc = MatcherTable[Idx++]; + Opc |= (unsigned short)MatcherTable[Idx++] << 8; + if (Opc >= OpcodeOffset.size()) + OpcodeOffset.resize((Opc+1)*2); + OpcodeOffset[Opc] = Idx; + Idx += CaseSize; + } + + // Okay, do the lookup for the first opcode. + if (N.getOpcode() < OpcodeOffset.size()) + MatcherIndex = OpcodeOffset[N.getOpcode()]; + } + + while (1) { + assert(MatcherIndex < TableSize && "Invalid index"); +#ifndef NDEBUG + unsigned CurrentOpcodeIndex = MatcherIndex; +#endif + BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++]; + switch (Opcode) { + case OPC_Scope: { + // Okay, the semantics of this operation are that we should push a scope + // then evaluate the first child. However, pushing a scope only to have + // the first check fail (which then pops it) is inefficient. If we can + // determine immediately that the first check (or first several) will + // immediately fail, don't even bother pushing a scope for them. + unsigned FailIndex; + + while (1) { + unsigned NumToSkip = MatcherTable[MatcherIndex++]; + if (NumToSkip & 128) + NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex); + // Found the end of the scope with no match. + if (NumToSkip == 0) { + FailIndex = 0; + break; + } + + FailIndex = MatcherIndex+NumToSkip; + + unsigned MatcherIndexOfPredicate = MatcherIndex; + (void)MatcherIndexOfPredicate; // silence warning. + + // If we can't evaluate this predicate without pushing a scope (e.g. if + // it is a 'MoveParent') or if the predicate succeeds on this node, we + // push the scope and evaluate the full predicate chain. + bool Result; + MatcherIndex = IsPredicateKnownToFail(MatcherTable, MatcherIndex, N, + Result, *this, RecordedNodes); + if (!Result) + break; + + DEBUG(errs() << " Skipped scope entry (due to false predicate) at " + << "index " << MatcherIndexOfPredicate + << ", continuing at " << FailIndex << "\n"); + ++NumDAGIselRetries; + + // Otherwise, we know that this case of the Scope is guaranteed to fail, + // move to the next case. + MatcherIndex = FailIndex; + } + + // If the whole scope failed to match, bail. + if (FailIndex == 0) break; + + // Push a MatchScope which indicates where to go if the first child fails + // to match. + MatchScope NewEntry; + NewEntry.FailIndex = FailIndex; + NewEntry.NodeStack.append(NodeStack.begin(), NodeStack.end()); + NewEntry.NumRecordedNodes = RecordedNodes.size(); + NewEntry.NumMatchedMemRefs = MatchedMemRefs.size(); + NewEntry.InputChain = InputChain; + NewEntry.InputGlue = InputGlue; + NewEntry.HasChainNodesMatched = !ChainNodesMatched.empty(); + NewEntry.HasGlueResultNodesMatched = !GlueResultNodesMatched.empty(); + MatchScopes.push_back(NewEntry); + continue; + } + case OPC_RecordNode: { + // Remember this node, it may end up being an operand in the pattern. + SDNode *Parent = 0; + if (NodeStack.size() > 1) + Parent = NodeStack[NodeStack.size()-2].getNode(); + RecordedNodes.push_back(std::make_pair(N, Parent)); + continue; + } + + case OPC_RecordChild0: case OPC_RecordChild1: + case OPC_RecordChild2: case OPC_RecordChild3: + case OPC_RecordChild4: case OPC_RecordChild5: + case OPC_RecordChild6: case OPC_RecordChild7: { + unsigned ChildNo = Opcode-OPC_RecordChild0; + if (ChildNo >= N.getNumOperands()) + break; // Match fails if out of range child #. + + RecordedNodes.push_back(std::make_pair(N->getOperand(ChildNo), + N.getNode())); + continue; + } + case OPC_RecordMemRef: + MatchedMemRefs.push_back(cast(N)->getMemOperand()); + continue; + + case OPC_CaptureGlueInput: + // If the current node has an input glue, capture it in InputGlue. + if (N->getNumOperands() != 0 && + N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Glue) + InputGlue = N->getOperand(N->getNumOperands()-1); + continue; + + case OPC_MoveChild: { + unsigned ChildNo = MatcherTable[MatcherIndex++]; + if (ChildNo >= N.getNumOperands()) + break; // Match fails if out of range child #. + N = N.getOperand(ChildNo); + NodeStack.push_back(N); + continue; + } + + case OPC_MoveParent: + // Pop the current node off the NodeStack. + NodeStack.pop_back(); + assert(!NodeStack.empty() && "Node stack imbalance!"); + N = NodeStack.back(); + continue; + + case OPC_CheckSame: + if (!::CheckSame(MatcherTable, MatcherIndex, N, RecordedNodes)) break; + continue; + case OPC_CheckPatternPredicate: + if (!::CheckPatternPredicate(MatcherTable, MatcherIndex, *this)) break; + continue; + case OPC_CheckPredicate: + if (!::CheckNodePredicate(MatcherTable, MatcherIndex, *this, + N.getNode())) + break; + continue; + case OPC_CheckComplexPat: { + unsigned CPNum = MatcherTable[MatcherIndex++]; + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckComplexPat"); + if (!CheckComplexPattern(NodeToMatch, RecordedNodes[RecNo].second, + RecordedNodes[RecNo].first, CPNum, + RecordedNodes)) + break; + continue; + } + case OPC_CheckOpcode: + if (!::CheckOpcode(MatcherTable, MatcherIndex, N.getNode())) break; + continue; + + case OPC_CheckType: + if (!::CheckType(MatcherTable, MatcherIndex, N, TLI)) break; + continue; + + case OPC_SwitchOpcode: { + unsigned CurNodeOpcode = N.getOpcode(); + unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart; + unsigned CaseSize; + while (1) { + // Get the size of this case. + CaseSize = MatcherTable[MatcherIndex++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, MatcherIndex); + if (CaseSize == 0) break; + + uint16_t Opc = MatcherTable[MatcherIndex++]; + Opc |= (unsigned short)MatcherTable[MatcherIndex++] << 8; + + // If the opcode matches, then we will execute this case. + if (CurNodeOpcode == Opc) + break; + + // Otherwise, skip over this case. + MatcherIndex += CaseSize; + } + + // If no cases matched, bail out. + if (CaseSize == 0) break; + + // Otherwise, execute the case we found. + DEBUG(errs() << " OpcodeSwitch from " << SwitchStart + << " to " << MatcherIndex << "\n"); + continue; + } + + case OPC_SwitchType: { + MVT CurNodeVT = N.getValueType().getSimpleVT(); + unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart; + unsigned CaseSize; + while (1) { + // Get the size of this case. + CaseSize = MatcherTable[MatcherIndex++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, MatcherIndex); + if (CaseSize == 0) break; + + MVT CaseVT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (CaseVT == MVT::iPTR) + CaseVT = TLI.getPointerTy(); + + // If the VT matches, then we will execute this case. + if (CurNodeVT == CaseVT) + break; + + // Otherwise, skip over this case. + MatcherIndex += CaseSize; + } + + // If no cases matched, bail out. + if (CaseSize == 0) break; + + // Otherwise, execute the case we found. + DEBUG(errs() << " TypeSwitch[" << EVT(CurNodeVT).getEVTString() + << "] from " << SwitchStart << " to " << MatcherIndex<<'\n'); + continue; + } + case OPC_CheckChild0Type: case OPC_CheckChild1Type: + case OPC_CheckChild2Type: case OPC_CheckChild3Type: + case OPC_CheckChild4Type: case OPC_CheckChild5Type: + case OPC_CheckChild6Type: case OPC_CheckChild7Type: + if (!::CheckChildType(MatcherTable, MatcherIndex, N, TLI, + Opcode-OPC_CheckChild0Type)) + break; + continue; + case OPC_CheckCondCode: + if (!::CheckCondCode(MatcherTable, MatcherIndex, N)) break; + continue; + case OPC_CheckValueType: + if (!::CheckValueType(MatcherTable, MatcherIndex, N, TLI)) break; + continue; + case OPC_CheckInteger: + if (!::CheckInteger(MatcherTable, MatcherIndex, N)) break; + continue; + case OPC_CheckAndImm: + if (!::CheckAndImm(MatcherTable, MatcherIndex, N, *this)) break; + continue; + case OPC_CheckOrImm: + if (!::CheckOrImm(MatcherTable, MatcherIndex, N, *this)) break; + continue; + + case OPC_CheckFoldableChainNode: { + assert(NodeStack.size() != 1 && "No parent node"); + // Verify that all intermediate nodes between the root and this one have + // a single use. + bool HasMultipleUses = false; + for (unsigned i = 1, e = NodeStack.size()-1; i != e; ++i) + if (!NodeStack[i].hasOneUse()) { + HasMultipleUses = true; + break; + } + if (HasMultipleUses) break; + + // Check to see that the target thinks this is profitable to fold and that + // we can fold it without inducing cycles in the graph. + if (!IsProfitableToFold(N, NodeStack[NodeStack.size()-2].getNode(), + NodeToMatch) || + !IsLegalToFold(N, NodeStack[NodeStack.size()-2].getNode(), + NodeToMatch, OptLevel, + true/*We validate our own chains*/)) + break; + + continue; + } + case OPC_EmitInteger: { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + RecordedNodes.push_back(std::pair( + CurDAG->getTargetConstant(Val, VT), (SDNode*)0)); + continue; + } + case OPC_EmitRegister: { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + unsigned RegNo = MatcherTable[MatcherIndex++]; + RecordedNodes.push_back(std::pair( + CurDAG->getRegister(RegNo, VT), (SDNode*)0)); + continue; + } + case OPC_EmitRegister2: { + // For targets w/ more than 256 register names, the register enum + // values are stored in two bytes in the matcher table (just like + // opcodes). + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + unsigned RegNo = MatcherTable[MatcherIndex++]; + RegNo |= MatcherTable[MatcherIndex++] << 8; + RecordedNodes.push_back(std::pair( + CurDAG->getRegister(RegNo, VT), (SDNode*)0)); + continue; + } + + case OPC_EmitConvertToTarget: { + // Convert from IMM/FPIMM to target version. + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Imm = RecordedNodes[RecNo].first; + + if (Imm->getOpcode() == ISD::Constant) { + int64_t Val = cast(Imm)->getZExtValue(); + Imm = CurDAG->getTargetConstant(Val, Imm.getValueType()); + } else if (Imm->getOpcode() == ISD::ConstantFP) { + const ConstantFP *Val=cast(Imm)->getConstantFPValue(); + Imm = CurDAG->getTargetConstantFP(*Val, Imm.getValueType()); + } + + RecordedNodes.push_back(std::make_pair(Imm, RecordedNodes[RecNo].second)); + continue; + } + + case OPC_EmitMergeInputChains1_0: // OPC_EmitMergeInputChains, 1, 0 + case OPC_EmitMergeInputChains1_1: { // OPC_EmitMergeInputChains, 1, 1 + // These are space-optimized forms of OPC_EmitMergeInputChains. + assert(InputChain.getNode() == 0 && + "EmitMergeInputChains should be the first chain producing node"); + assert(ChainNodesMatched.empty() && + "Should only have one EmitMergeInputChains per match"); + + // Read all of the chained nodes. + unsigned RecNo = Opcode == OPC_EmitMergeInputChains1_1; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + ChainNodesMatched.push_back(RecordedNodes[RecNo].first.getNode()); + + // FIXME: What if other value results of the node have uses not matched + // by this pattern? + if (ChainNodesMatched.back() != NodeToMatch && + !RecordedNodes[RecNo].first.hasOneUse()) { + ChainNodesMatched.clear(); + break; + } + + // Merge the input chains if they are not intra-pattern references. + InputChain = HandleMergeInputChains(ChainNodesMatched, CurDAG); + + if (InputChain.getNode() == 0) + break; // Failed to merge. + continue; + } + + case OPC_EmitMergeInputChains: { + assert(InputChain.getNode() == 0 && + "EmitMergeInputChains should be the first chain producing node"); + // This node gets a list of nodes we matched in the input that have + // chains. We want to token factor all of the input chains to these nodes + // together. However, if any of the input chains is actually one of the + // nodes matched in this pattern, then we have an intra-match reference. + // Ignore these because the newly token factored chain should not refer to + // the old nodes. + unsigned NumChains = MatcherTable[MatcherIndex++]; + assert(NumChains != 0 && "Can't TF zero chains"); + + assert(ChainNodesMatched.empty() && + "Should only have one EmitMergeInputChains per match"); + + // Read all of the chained nodes. + for (unsigned i = 0; i != NumChains; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + ChainNodesMatched.push_back(RecordedNodes[RecNo].first.getNode()); + + // FIXME: What if other value results of the node have uses not matched + // by this pattern? + if (ChainNodesMatched.back() != NodeToMatch && + !RecordedNodes[RecNo].first.hasOneUse()) { + ChainNodesMatched.clear(); + break; + } + } + + // If the inner loop broke out, the match fails. + if (ChainNodesMatched.empty()) + break; + + // Merge the input chains if they are not intra-pattern references. + InputChain = HandleMergeInputChains(ChainNodesMatched, CurDAG); + + if (InputChain.getNode() == 0) + break; // Failed to merge. + + continue; + } + + case OPC_EmitCopyToReg: { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + unsigned DestPhysReg = MatcherTable[MatcherIndex++]; + + if (InputChain.getNode() == 0) + InputChain = CurDAG->getEntryNode(); + + InputChain = CurDAG->getCopyToReg(InputChain, NodeToMatch->getDebugLoc(), + DestPhysReg, RecordedNodes[RecNo].first, + InputGlue); + + InputGlue = InputChain.getValue(1); + continue; + } + + case OPC_EmitNodeXForm: { + unsigned XFormNo = MatcherTable[MatcherIndex++]; + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Res = RunSDNodeXForm(RecordedNodes[RecNo].first, XFormNo); + RecordedNodes.push_back(std::pair(Res, (SDNode*) 0)); + continue; + } + + case OPC_EmitNode: + case OPC_MorphNodeTo: { + uint16_t TargetOpc = MatcherTable[MatcherIndex++]; + TargetOpc |= (unsigned short)MatcherTable[MatcherIndex++] << 8; + unsigned EmitNodeInfo = MatcherTable[MatcherIndex++]; + // Get the result VT list. + unsigned NumVTs = MatcherTable[MatcherIndex++]; + SmallVector VTs; + for (unsigned i = 0; i != NumVTs; ++i) { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (VT == MVT::iPTR) VT = TLI.getPointerTy().SimpleTy; + VTs.push_back(VT); + } + + if (EmitNodeInfo & OPFL_Chain) + VTs.push_back(MVT::Other); + if (EmitNodeInfo & OPFL_GlueOutput) + VTs.push_back(MVT::Glue); + + // This is hot code, so optimize the two most common cases of 1 and 2 + // results. + SDVTList VTList; + if (VTs.size() == 1) + VTList = CurDAG->getVTList(VTs[0]); + else if (VTs.size() == 2) + VTList = CurDAG->getVTList(VTs[0], VTs[1]); + else + VTList = CurDAG->getVTList(VTs.data(), VTs.size()); + + // Get the operand list. + unsigned NumOps = MatcherTable[MatcherIndex++]; + SmallVector Ops; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + if (RecNo & 128) + RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex); + + assert(RecNo < RecordedNodes.size() && "Invalid EmitNode"); + Ops.push_back(RecordedNodes[RecNo].first); + } + + // If there are variadic operands to add, handle them now. + if (EmitNodeInfo & OPFL_VariadicInfo) { + // Determine the start index to copy from. + unsigned FirstOpToCopy = getNumFixedFromVariadicInfo(EmitNodeInfo); + FirstOpToCopy += (EmitNodeInfo & OPFL_Chain) ? 1 : 0; + assert(NodeToMatch->getNumOperands() >= FirstOpToCopy && + "Invalid variadic node"); + // Copy all of the variadic operands, not including a potential glue + // input. + for (unsigned i = FirstOpToCopy, e = NodeToMatch->getNumOperands(); + i != e; ++i) { + SDValue V = NodeToMatch->getOperand(i); + if (V.getValueType() == MVT::Glue) break; + Ops.push_back(V); + } + } + + // If this has chain/glue inputs, add them. + if (EmitNodeInfo & OPFL_Chain) + Ops.push_back(InputChain); + if ((EmitNodeInfo & OPFL_GlueInput) && InputGlue.getNode() != 0) + Ops.push_back(InputGlue); + + // Create the node. + SDNode *Res = 0; + if (Opcode != OPC_MorphNodeTo) { + // If this is a normal EmitNode command, just create the new node and + // add the results to the RecordedNodes list. + Res = CurDAG->getMachineNode(TargetOpc, NodeToMatch->getDebugLoc(), + VTList, Ops.data(), Ops.size()); + + // Add all the non-glue/non-chain results to the RecordedNodes list. + for (unsigned i = 0, e = VTs.size(); i != e; ++i) { + if (VTs[i] == MVT::Other || VTs[i] == MVT::Glue) break; + RecordedNodes.push_back(std::pair(SDValue(Res, i), + (SDNode*) 0)); + } + + } else { + Res = MorphNode(NodeToMatch, TargetOpc, VTList, Ops.data(), Ops.size(), + EmitNodeInfo); + } + + // If the node had chain/glue results, update our notion of the current + // chain and glue. + if (EmitNodeInfo & OPFL_GlueOutput) { + InputGlue = SDValue(Res, VTs.size()-1); + if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-2); + } else if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-1); + + // If the OPFL_MemRefs glue is set on this node, slap all of the + // accumulated memrefs onto it. + // + // FIXME: This is vastly incorrect for patterns with multiple outputs + // instructions that access memory and for ComplexPatterns that match + // loads. + if (EmitNodeInfo & OPFL_MemRefs) { + MachineSDNode::mmo_iterator MemRefs = + MF->allocateMemRefsArray(MatchedMemRefs.size()); + std::copy(MatchedMemRefs.begin(), MatchedMemRefs.end(), MemRefs); + cast(Res) + ->setMemRefs(MemRefs, MemRefs + MatchedMemRefs.size()); + } + + DEBUG(errs() << " " + << (Opcode == OPC_MorphNodeTo ? "Morphed" : "Created") + << " node: "; Res->dump(CurDAG); errs() << "\n"); + + // If this was a MorphNodeTo then we're completely done! + if (Opcode == OPC_MorphNodeTo) { + // Update chain and glue uses. + UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched, + InputGlue, GlueResultNodesMatched, true); + return Res; + } + + continue; + } + + case OPC_MarkGlueResults: { + unsigned NumNodes = MatcherTable[MatcherIndex++]; + + // Read and remember all the glue-result nodes. + for (unsigned i = 0; i != NumNodes; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + if (RecNo & 128) + RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex); + + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + GlueResultNodesMatched.push_back(RecordedNodes[RecNo].first.getNode()); + } + continue; + } + + case OPC_CompleteMatch: { + // The match has been completed, and any new nodes (if any) have been + // created. Patch up references to the matched dag to use the newly + // created nodes. + unsigned NumResults = MatcherTable[MatcherIndex++]; + + for (unsigned i = 0; i != NumResults; ++i) { + unsigned ResSlot = MatcherTable[MatcherIndex++]; + if (ResSlot & 128) + ResSlot = GetVBR(ResSlot, MatcherTable, MatcherIndex); + + assert(ResSlot < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Res = RecordedNodes[ResSlot].first; + + assert(i < NodeToMatch->getNumValues() && + NodeToMatch->getValueType(i) != MVT::Other && + NodeToMatch->getValueType(i) != MVT::Glue && + "Invalid number of results to complete!"); + assert((NodeToMatch->getValueType(i) == Res.getValueType() || + NodeToMatch->getValueType(i) == MVT::iPTR || + Res.getValueType() == MVT::iPTR || + NodeToMatch->getValueType(i).getSizeInBits() == + Res.getValueType().getSizeInBits()) && + "invalid replacement"); + CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, i), Res); + } + + // If the root node defines glue, add it to the glue nodes to update list. + if (NodeToMatch->getValueType(NodeToMatch->getNumValues()-1) == MVT::Glue) + GlueResultNodesMatched.push_back(NodeToMatch); + + // Update chain and glue uses. + UpdateChainsAndGlue(NodeToMatch, InputChain, ChainNodesMatched, + InputGlue, GlueResultNodesMatched, false); + + assert(NodeToMatch->use_empty() && + "Didn't replace all uses of the node?"); + + // FIXME: We just return here, which interacts correctly with SelectRoot + // above. We should fix this to not return an SDNode* anymore. + return 0; + } + } + + // If the code reached this point, then the match failed. See if there is + // another child to try in the current 'Scope', otherwise pop it until we + // find a case to check. + DEBUG(errs() << " Match failed at index " << CurrentOpcodeIndex << "\n"); + ++NumDAGIselRetries; + while (1) { + if (MatchScopes.empty()) { + CannotYetSelect(NodeToMatch); + return 0; + } + + // Restore the interpreter state back to the point where the scope was + // formed. + MatchScope &LastScope = MatchScopes.back(); + RecordedNodes.resize(LastScope.NumRecordedNodes); + NodeStack.clear(); + NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end()); + N = NodeStack.back(); + + if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size()) + MatchedMemRefs.resize(LastScope.NumMatchedMemRefs); + MatcherIndex = LastScope.FailIndex; + + DEBUG(errs() << " Continuing at " << MatcherIndex << "\n"); + + InputChain = LastScope.InputChain; + InputGlue = LastScope.InputGlue; + if (!LastScope.HasChainNodesMatched) + ChainNodesMatched.clear(); + if (!LastScope.HasGlueResultNodesMatched) + GlueResultNodesMatched.clear(); + + // Check to see what the offset is at the new MatcherIndex. If it is zero + // we have reached the end of this scope, otherwise we have another child + // in the current scope to try. + unsigned NumToSkip = MatcherTable[MatcherIndex++]; + if (NumToSkip & 128) + NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex); + + // If we have another child in this scope to match, update FailIndex and + // try it. + if (NumToSkip != 0) { + LastScope.FailIndex = MatcherIndex+NumToSkip; + break; + } + + // End of this scope, pop it and try the next child in the containing + // scope. + MatchScopes.pop_back(); + } + } +} + + + +void SelectionDAGISel::CannotYetSelect(SDNode *N) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Cannot select: "; + + if (N->getOpcode() != ISD::INTRINSIC_W_CHAIN && + N->getOpcode() != ISD::INTRINSIC_WO_CHAIN && + N->getOpcode() != ISD::INTRINSIC_VOID) { + N->printrFull(Msg, CurDAG); + } else { + bool HasInputChain = N->getOperand(0).getValueType() == MVT::Other; + unsigned iid = + cast(N->getOperand(HasInputChain))->getZExtValue(); + if (iid < Intrinsic::num_intrinsics) + Msg << "intrinsic %" << Intrinsic::getName((Intrinsic::ID)iid); + else if (const TargetIntrinsicInfo *TII = TM.getIntrinsicInfo()) + Msg << "target intrinsic %" << TII->getName(iid); + else + Msg << "unknown intrinsic #" << iid; + } + report_fatal_error(Msg.str()); +} + +char SelectionDAGISel::ID = 0; diff --git a/final/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/final/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp new file mode 100644 index 00000000000..cd1647b17b9 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp @@ -0,0 +1,302 @@ +//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the SelectionDAG::viewGraph method. +// +//===----------------------------------------------------------------------===// + +#include "ScheduleDAGSDNodes.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" +using namespace llvm; + +namespace llvm { + template<> + struct DOTGraphTraits : public DefaultDOTGraphTraits { + + explicit DOTGraphTraits(bool isSimple=false) : + DefaultDOTGraphTraits(isSimple) {} + + static bool hasEdgeDestLabels() { + return true; + } + + static unsigned numEdgeDestLabels(const void *Node) { + return ((const SDNode *) Node)->getNumValues(); + } + + static std::string getEdgeDestLabel(const void *Node, unsigned i) { + return ((const SDNode *) Node)->getValueType(i).getEVTString(); + } + + template + static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { + return itostr(I - SDNodeIterator::begin((SDNode *) Node)); + } + + /// edgeTargetsEdgeSource - This method returns true if this outgoing edge + /// should actually target another edge source, not a node. If this method + /// is implemented, getEdgeTarget should be implemented. + template + static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { + return true; + } + + /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is + /// called to determine which outgoing edge of Node is the target of this + /// edge. + template + static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { + SDNode *TargetNode = *I; + SDNodeIterator NI = SDNodeIterator::begin(TargetNode); + std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo()); + return NI; + } + + static std::string getGraphName(const SelectionDAG *G) { + return G->getMachineFunction().getFunction()->getName(); + } + + static bool renderGraphFromBottomUp() { + return true; + } + + static bool hasNodeAddressLabel(const SDNode *Node, + const SelectionDAG *Graph) { + return true; + } + + /// If you want to override the dot attributes printed for a particular + /// edge, override this method. + template + static std::string getEdgeAttributes(const void *Node, EdgeIter EI, + const SelectionDAG *Graph) { + SDValue Op = EI.getNode()->getOperand(EI.getOperand()); + EVT VT = Op.getValueType(); + if (VT == MVT::Glue) + return "color=red,style=bold"; + else if (VT == MVT::Other) + return "color=blue,style=dashed"; + return ""; + } + + + static std::string getSimpleNodeLabel(const SDNode *Node, + const SelectionDAG *G) { + std::string Result = Node->getOperationName(G); + { + raw_string_ostream OS(Result); + Node->print_details(OS, G); + } + return Result; + } + std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph); + static std::string getNodeAttributes(const SDNode *N, + const SelectionDAG *Graph) { +#ifndef NDEBUG + const std::string &Attrs = Graph->getGraphAttrs(N); + if (!Attrs.empty()) { + if (Attrs.find("shape=") == std::string::npos) + return std::string("shape=Mrecord,") + Attrs; + else + return Attrs; + } +#endif + return "shape=Mrecord"; + } + + static void addCustomGraphFeatures(SelectionDAG *G, + GraphWriter &GW) { + GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); + if (G->getRoot().getNode()) + GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(), + "color=blue,style=dashed"); + } + }; +} + +std::string DOTGraphTraits::getNodeLabel(const SDNode *Node, + const SelectionDAG *G) { + return DOTGraphTraits::getSimpleNodeLabel(Node, G); +} + + +/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG +/// rendered using 'dot'. +/// +void SelectionDAG::viewGraph(const std::string &Title) { +// This code is only for debugging! +#ifndef NDEBUG + ViewGraph(this, "dag." + getMachineFunction().getFunction()->getNameStr(), + false, Title); +#else + errs() << "SelectionDAG::viewGraph is only available in debug builds on " + << "systems with Graphviz or gv!\n"; +#endif // NDEBUG +} + +// This overload is defined out-of-line here instead of just using a +// default parameter because this is easiest for gdb to call. +void SelectionDAG::viewGraph() { + viewGraph(""); +} + +/// clearGraphAttrs - Clear all previously defined node graph attributes. +/// Intended to be used from a debugging tool (eg. gdb). +void SelectionDAG::clearGraphAttrs() { +#ifndef NDEBUG + NodeGraphAttrs.clear(); +#else + errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + + +/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) +/// +void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) { +#ifndef NDEBUG + NodeGraphAttrs[N] = Attrs; +#else + errs() << "SelectionDAG::setGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + + +/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) +/// Used from getNodeAttributes. +const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const { +#ifndef NDEBUG + std::map::const_iterator I = + NodeGraphAttrs.find(N); + + if (I != NodeGraphAttrs.end()) + return I->second; + else + return ""; +#else + errs() << "SelectionDAG::getGraphAttrs is only available in debug builds" + << " on systems with Graphviz or gv!\n"; + return std::string(); +#endif +} + +/// setGraphColor - Convenience for setting node color attribute. +/// +void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) { +#ifndef NDEBUG + NodeGraphAttrs[N] = std::string("color=") + Color; +#else + errs() << "SelectionDAG::setGraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + +/// setSubgraphColorHelper - Implement setSubgraphColor. Return +/// whether we truncated the search. +/// +bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet &visited, + int level, bool &printed) { + bool hit_limit = false; + +#ifndef NDEBUG + if (level >= 20) { + if (!printed) { + printed = true; + DEBUG(dbgs() << "setSubgraphColor hit max level\n"); + } + return true; + } + + unsigned oldSize = visited.size(); + visited.insert(N); + if (visited.size() != oldSize) { + setGraphColor(N, Color); + for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N); + i != iend; + ++i) { + hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit; + } + } +#else + errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif + return hit_limit; +} + +/// setSubgraphColor - Convenience for setting subgraph color attribute. +/// +void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) { +#ifndef NDEBUG + DenseSet visited; + bool printed = false; + if (setSubgraphColorHelper(N, Color, visited, 0, printed)) { + // Visually mark that we hit the limit + if (strcmp(Color, "red") == 0) { + setSubgraphColorHelper(N, "blue", visited, 0, printed); + } else if (strcmp(Color, "yellow") == 0) { + setSubgraphColorHelper(N, "green", visited, 0, printed); + } + } + +#else + errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" + << " on systems with Graphviz or gv!\n"; +#endif +} + +std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const { + std::string s; + raw_string_ostream O(s); + O << "SU(" << SU->NodeNum << "): "; + if (SU->getNode()) { + SmallVector GluedNodes; + for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) + GluedNodes.push_back(N); + while (!GluedNodes.empty()) { + O << DOTGraphTraits + ::getSimpleNodeLabel(GluedNodes.back(), DAG); + GluedNodes.pop_back(); + if (!GluedNodes.empty()) + O << "\n "; + } + } else { + O << "CROSS RC COPY"; + } + return O.str(); +} + +void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter &GW) const { + if (DAG) { + // Draw a special "GraphRoot" node to indicate the root of the graph. + GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); + const SDNode *N = DAG->getRoot().getNode(); + if (N && N->getNodeId() != -1) + GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1, + "color=blue,style=dashed"); + } +} diff --git a/final/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/final/lib/CodeGen/SelectionDAG/TargetLowering.cpp new file mode 100644 index 00000000000..35b847ccabf --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -0,0 +1,3214 @@ +//===-- TargetLowering.cpp - Implement the TargetLowering class -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the TargetLowering class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetLowering.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/GlobalVariable.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +using namespace llvm; + +namespace llvm { +TLSModel::Model getTLSModel(const GlobalValue *GV, Reloc::Model reloc) { + bool isLocal = GV->hasLocalLinkage(); + bool isDeclaration = GV->isDeclaration(); + // FIXME: what should we do for protected and internal visibility? + // For variables, is internal different from hidden? + bool isHidden = GV->hasHiddenVisibility(); + + if (reloc == Reloc::PIC_) { + if (isLocal || isHidden) + return TLSModel::LocalDynamic; + else + return TLSModel::GeneralDynamic; + } else { + if (!isDeclaration || isHidden) + return TLSModel::LocalExec; + else + return TLSModel::InitialExec; + } +} +} + +/// InitLibcallNames - Set default libcall names. +/// +static void InitLibcallNames(const char **Names) { + Names[RTLIB::SHL_I16] = "__ashlhi3"; + Names[RTLIB::SHL_I32] = "__ashlsi3"; + Names[RTLIB::SHL_I64] = "__ashldi3"; + Names[RTLIB::SHL_I128] = "__ashlti3"; + Names[RTLIB::SRL_I16] = "__lshrhi3"; + Names[RTLIB::SRL_I32] = "__lshrsi3"; + Names[RTLIB::SRL_I64] = "__lshrdi3"; + Names[RTLIB::SRL_I128] = "__lshrti3"; + Names[RTLIB::SRA_I16] = "__ashrhi3"; + Names[RTLIB::SRA_I32] = "__ashrsi3"; + Names[RTLIB::SRA_I64] = "__ashrdi3"; + Names[RTLIB::SRA_I128] = "__ashrti3"; + Names[RTLIB::MUL_I8] = "__mulqi3"; + Names[RTLIB::MUL_I16] = "__mulhi3"; + Names[RTLIB::MUL_I32] = "__mulsi3"; + Names[RTLIB::MUL_I64] = "__muldi3"; + Names[RTLIB::MUL_I128] = "__multi3"; + Names[RTLIB::SDIV_I8] = "__divqi3"; + Names[RTLIB::SDIV_I16] = "__divhi3"; + Names[RTLIB::SDIV_I32] = "__divsi3"; + Names[RTLIB::SDIV_I64] = "__divdi3"; + Names[RTLIB::SDIV_I128] = "__divti3"; + Names[RTLIB::UDIV_I8] = "__udivqi3"; + Names[RTLIB::UDIV_I16] = "__udivhi3"; + Names[RTLIB::UDIV_I32] = "__udivsi3"; + Names[RTLIB::UDIV_I64] = "__udivdi3"; + Names[RTLIB::UDIV_I128] = "__udivti3"; + Names[RTLIB::SREM_I8] = "__modqi3"; + Names[RTLIB::SREM_I16] = "__modhi3"; + Names[RTLIB::SREM_I32] = "__modsi3"; + Names[RTLIB::SREM_I64] = "__moddi3"; + Names[RTLIB::SREM_I128] = "__modti3"; + Names[RTLIB::UREM_I8] = "__umodqi3"; + Names[RTLIB::UREM_I16] = "__umodhi3"; + Names[RTLIB::UREM_I32] = "__umodsi3"; + Names[RTLIB::UREM_I64] = "__umoddi3"; + Names[RTLIB::UREM_I128] = "__umodti3"; + Names[RTLIB::NEG_I32] = "__negsi2"; + Names[RTLIB::NEG_I64] = "__negdi2"; + Names[RTLIB::ADD_F32] = "__addsf3"; + Names[RTLIB::ADD_F64] = "__adddf3"; + Names[RTLIB::ADD_F80] = "__addxf3"; + Names[RTLIB::ADD_PPCF128] = "__gcc_qadd"; + Names[RTLIB::SUB_F32] = "__subsf3"; + Names[RTLIB::SUB_F64] = "__subdf3"; + Names[RTLIB::SUB_F80] = "__subxf3"; + Names[RTLIB::SUB_PPCF128] = "__gcc_qsub"; + Names[RTLIB::MUL_F32] = "__mulsf3"; + Names[RTLIB::MUL_F64] = "__muldf3"; + Names[RTLIB::MUL_F80] = "__mulxf3"; + Names[RTLIB::MUL_PPCF128] = "__gcc_qmul"; + Names[RTLIB::DIV_F32] = "__divsf3"; + Names[RTLIB::DIV_F64] = "__divdf3"; + Names[RTLIB::DIV_F80] = "__divxf3"; + Names[RTLIB::DIV_PPCF128] = "__gcc_qdiv"; + Names[RTLIB::REM_F32] = "fmodf"; + Names[RTLIB::REM_F64] = "fmod"; + Names[RTLIB::REM_F80] = "fmodl"; + Names[RTLIB::REM_PPCF128] = "fmodl"; + Names[RTLIB::POWI_F32] = "__powisf2"; + Names[RTLIB::POWI_F64] = "__powidf2"; + Names[RTLIB::POWI_F80] = "__powixf2"; + Names[RTLIB::POWI_PPCF128] = "__powitf2"; + Names[RTLIB::SQRT_F32] = "sqrtf"; + Names[RTLIB::SQRT_F64] = "sqrt"; + Names[RTLIB::SQRT_F80] = "sqrtl"; + Names[RTLIB::SQRT_PPCF128] = "sqrtl"; + Names[RTLIB::LOG_F32] = "logf"; + Names[RTLIB::LOG_F64] = "log"; + Names[RTLIB::LOG_F80] = "logl"; + Names[RTLIB::LOG_PPCF128] = "logl"; + Names[RTLIB::LOG2_F32] = "log2f"; + Names[RTLIB::LOG2_F64] = "log2"; + Names[RTLIB::LOG2_F80] = "log2l"; + Names[RTLIB::LOG2_PPCF128] = "log2l"; + Names[RTLIB::LOG10_F32] = "log10f"; + Names[RTLIB::LOG10_F64] = "log10"; + Names[RTLIB::LOG10_F80] = "log10l"; + Names[RTLIB::LOG10_PPCF128] = "log10l"; + Names[RTLIB::EXP_F32] = "expf"; + Names[RTLIB::EXP_F64] = "exp"; + Names[RTLIB::EXP_F80] = "expl"; + Names[RTLIB::EXP_PPCF128] = "expl"; + Names[RTLIB::EXP2_F32] = "exp2f"; + Names[RTLIB::EXP2_F64] = "exp2"; + Names[RTLIB::EXP2_F80] = "exp2l"; + Names[RTLIB::EXP2_PPCF128] = "exp2l"; + Names[RTLIB::SIN_F32] = "sinf"; + Names[RTLIB::SIN_F64] = "sin"; + Names[RTLIB::SIN_F80] = "sinl"; + Names[RTLIB::SIN_PPCF128] = "sinl"; + Names[RTLIB::COS_F32] = "cosf"; + Names[RTLIB::COS_F64] = "cos"; + Names[RTLIB::COS_F80] = "cosl"; + Names[RTLIB::COS_PPCF128] = "cosl"; + Names[RTLIB::POW_F32] = "powf"; + Names[RTLIB::POW_F64] = "pow"; + Names[RTLIB::POW_F80] = "powl"; + Names[RTLIB::POW_PPCF128] = "powl"; + Names[RTLIB::CEIL_F32] = "ceilf"; + Names[RTLIB::CEIL_F64] = "ceil"; + Names[RTLIB::CEIL_F80] = "ceill"; + Names[RTLIB::CEIL_PPCF128] = "ceill"; + Names[RTLIB::TRUNC_F32] = "truncf"; + Names[RTLIB::TRUNC_F64] = "trunc"; + Names[RTLIB::TRUNC_F80] = "truncl"; + Names[RTLIB::TRUNC_PPCF128] = "truncl"; + Names[RTLIB::RINT_F32] = "rintf"; + Names[RTLIB::RINT_F64] = "rint"; + Names[RTLIB::RINT_F80] = "rintl"; + Names[RTLIB::RINT_PPCF128] = "rintl"; + Names[RTLIB::NEARBYINT_F32] = "nearbyintf"; + Names[RTLIB::NEARBYINT_F64] = "nearbyint"; + Names[RTLIB::NEARBYINT_F80] = "nearbyintl"; + Names[RTLIB::NEARBYINT_PPCF128] = "nearbyintl"; + Names[RTLIB::FLOOR_F32] = "floorf"; + Names[RTLIB::FLOOR_F64] = "floor"; + Names[RTLIB::FLOOR_F80] = "floorl"; + Names[RTLIB::FLOOR_PPCF128] = "floorl"; + Names[RTLIB::COPYSIGN_F32] = "copysignf"; + Names[RTLIB::COPYSIGN_F64] = "copysign"; + Names[RTLIB::COPYSIGN_F80] = "copysignl"; + Names[RTLIB::COPYSIGN_PPCF128] = "copysignl"; + Names[RTLIB::FPEXT_F32_F64] = "__extendsfdf2"; + Names[RTLIB::FPEXT_F16_F32] = "__gnu_h2f_ieee"; + Names[RTLIB::FPROUND_F32_F16] = "__gnu_f2h_ieee"; + Names[RTLIB::FPROUND_F64_F32] = "__truncdfsf2"; + Names[RTLIB::FPROUND_F80_F32] = "__truncxfsf2"; + Names[RTLIB::FPROUND_PPCF128_F32] = "__trunctfsf2"; + Names[RTLIB::FPROUND_F80_F64] = "__truncxfdf2"; + Names[RTLIB::FPROUND_PPCF128_F64] = "__trunctfdf2"; + Names[RTLIB::FPTOSINT_F32_I8] = "__fixsfqi"; + Names[RTLIB::FPTOSINT_F32_I16] = "__fixsfhi"; + Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi"; + Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi"; + Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti"; + Names[RTLIB::FPTOSINT_F64_I8] = "__fixdfqi"; + Names[RTLIB::FPTOSINT_F64_I16] = "__fixdfhi"; + Names[RTLIB::FPTOSINT_F64_I32] = "__fixdfsi"; + Names[RTLIB::FPTOSINT_F64_I64] = "__fixdfdi"; + Names[RTLIB::FPTOSINT_F64_I128] = "__fixdfti"; + Names[RTLIB::FPTOSINT_F80_I32] = "__fixxfsi"; + Names[RTLIB::FPTOSINT_F80_I64] = "__fixxfdi"; + Names[RTLIB::FPTOSINT_F80_I128] = "__fixxfti"; + Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi"; + Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi"; + Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti"; + Names[RTLIB::FPTOUINT_F32_I8] = "__fixunssfqi"; + Names[RTLIB::FPTOUINT_F32_I16] = "__fixunssfhi"; + Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi"; + Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi"; + Names[RTLIB::FPTOUINT_F32_I128] = "__fixunssfti"; + Names[RTLIB::FPTOUINT_F64_I8] = "__fixunsdfqi"; + Names[RTLIB::FPTOUINT_F64_I16] = "__fixunsdfhi"; + Names[RTLIB::FPTOUINT_F64_I32] = "__fixunsdfsi"; + Names[RTLIB::FPTOUINT_F64_I64] = "__fixunsdfdi"; + Names[RTLIB::FPTOUINT_F64_I128] = "__fixunsdfti"; + Names[RTLIB::FPTOUINT_F80_I32] = "__fixunsxfsi"; + Names[RTLIB::FPTOUINT_F80_I64] = "__fixunsxfdi"; + Names[RTLIB::FPTOUINT_F80_I128] = "__fixunsxfti"; + Names[RTLIB::FPTOUINT_PPCF128_I32] = "__fixunstfsi"; + Names[RTLIB::FPTOUINT_PPCF128_I64] = "__fixunstfdi"; + Names[RTLIB::FPTOUINT_PPCF128_I128] = "__fixunstfti"; + Names[RTLIB::SINTTOFP_I32_F32] = "__floatsisf"; + Names[RTLIB::SINTTOFP_I32_F64] = "__floatsidf"; + Names[RTLIB::SINTTOFP_I32_F80] = "__floatsixf"; + Names[RTLIB::SINTTOFP_I32_PPCF128] = "__floatsitf"; + Names[RTLIB::SINTTOFP_I64_F32] = "__floatdisf"; + Names[RTLIB::SINTTOFP_I64_F64] = "__floatdidf"; + Names[RTLIB::SINTTOFP_I64_F80] = "__floatdixf"; + Names[RTLIB::SINTTOFP_I64_PPCF128] = "__floatditf"; + Names[RTLIB::SINTTOFP_I128_F32] = "__floattisf"; + Names[RTLIB::SINTTOFP_I128_F64] = "__floattidf"; + Names[RTLIB::SINTTOFP_I128_F80] = "__floattixf"; + Names[RTLIB::SINTTOFP_I128_PPCF128] = "__floattitf"; + Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf"; + Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf"; + Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf"; + Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf"; + Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf"; + Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf"; + Names[RTLIB::UINTTOFP_I64_F80] = "__floatundixf"; + Names[RTLIB::UINTTOFP_I64_PPCF128] = "__floatunditf"; + Names[RTLIB::UINTTOFP_I128_F32] = "__floatuntisf"; + Names[RTLIB::UINTTOFP_I128_F64] = "__floatuntidf"; + Names[RTLIB::UINTTOFP_I128_F80] = "__floatuntixf"; + Names[RTLIB::UINTTOFP_I128_PPCF128] = "__floatuntitf"; + Names[RTLIB::OEQ_F32] = "__eqsf2"; + Names[RTLIB::OEQ_F64] = "__eqdf2"; + Names[RTLIB::UNE_F32] = "__nesf2"; + Names[RTLIB::UNE_F64] = "__nedf2"; + Names[RTLIB::OGE_F32] = "__gesf2"; + Names[RTLIB::OGE_F64] = "__gedf2"; + Names[RTLIB::OLT_F32] = "__ltsf2"; + Names[RTLIB::OLT_F64] = "__ltdf2"; + Names[RTLIB::OLE_F32] = "__lesf2"; + Names[RTLIB::OLE_F64] = "__ledf2"; + Names[RTLIB::OGT_F32] = "__gtsf2"; + Names[RTLIB::OGT_F64] = "__gtdf2"; + Names[RTLIB::UO_F32] = "__unordsf2"; + Names[RTLIB::UO_F64] = "__unorddf2"; + Names[RTLIB::O_F32] = "__unordsf2"; + Names[RTLIB::O_F64] = "__unorddf2"; + Names[RTLIB::MEMCPY] = "memcpy"; + Names[RTLIB::MEMMOVE] = "memmove"; + Names[RTLIB::MEMSET] = "memset"; + Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume"; + Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1] = "__sync_val_compare_and_swap_1"; + Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2] = "__sync_val_compare_and_swap_2"; + Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_4] = "__sync_val_compare_and_swap_4"; + Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_8] = "__sync_val_compare_and_swap_8"; + Names[RTLIB::SYNC_LOCK_TEST_AND_SET_1] = "__sync_lock_test_and_set_1"; + Names[RTLIB::SYNC_LOCK_TEST_AND_SET_2] = "__sync_lock_test_and_set_2"; + Names[RTLIB::SYNC_LOCK_TEST_AND_SET_4] = "__sync_lock_test_and_set_4"; + Names[RTLIB::SYNC_LOCK_TEST_AND_SET_8] = "__sync_lock_test_and_set_8"; + Names[RTLIB::SYNC_FETCH_AND_ADD_1] = "__sync_fetch_and_add_1"; + Names[RTLIB::SYNC_FETCH_AND_ADD_2] = "__sync_fetch_and_add_2"; + Names[RTLIB::SYNC_FETCH_AND_ADD_4] = "__sync_fetch_and_add_4"; + Names[RTLIB::SYNC_FETCH_AND_ADD_8] = "__sync_fetch_and_add_8"; + Names[RTLIB::SYNC_FETCH_AND_SUB_1] = "__sync_fetch_and_sub_1"; + Names[RTLIB::SYNC_FETCH_AND_SUB_2] = "__sync_fetch_and_sub_2"; + Names[RTLIB::SYNC_FETCH_AND_SUB_4] = "__sync_fetch_and_sub_4"; + Names[RTLIB::SYNC_FETCH_AND_SUB_8] = "__sync_fetch_and_sub_8"; + Names[RTLIB::SYNC_FETCH_AND_AND_1] = "__sync_fetch_and_and_1"; + Names[RTLIB::SYNC_FETCH_AND_AND_2] = "__sync_fetch_and_and_2"; + Names[RTLIB::SYNC_FETCH_AND_AND_4] = "__sync_fetch_and_and_4"; + Names[RTLIB::SYNC_FETCH_AND_AND_8] = "__sync_fetch_and_and_8"; + Names[RTLIB::SYNC_FETCH_AND_OR_1] = "__sync_fetch_and_or_1"; + Names[RTLIB::SYNC_FETCH_AND_OR_2] = "__sync_fetch_and_or_2"; + Names[RTLIB::SYNC_FETCH_AND_OR_4] = "__sync_fetch_and_or_4"; + Names[RTLIB::SYNC_FETCH_AND_OR_8] = "__sync_fetch_and_or_8"; + Names[RTLIB::SYNC_FETCH_AND_XOR_1] = "__sync_fetch_and_xor_1"; + Names[RTLIB::SYNC_FETCH_AND_XOR_2] = "__sync_fetch_and_xor_2"; + Names[RTLIB::SYNC_FETCH_AND_XOR_4] = "__sync_fetch_and-xor_4"; + Names[RTLIB::SYNC_FETCH_AND_XOR_8] = "__sync_fetch_and_xor_8"; + Names[RTLIB::SYNC_FETCH_AND_NAND_1] = "__sync_fetch_and_nand_1"; + Names[RTLIB::SYNC_FETCH_AND_NAND_2] = "__sync_fetch_and_nand_2"; + Names[RTLIB::SYNC_FETCH_AND_NAND_4] = "__sync_fetch_and_nand_4"; + Names[RTLIB::SYNC_FETCH_AND_NAND_8] = "__sync_fetch_and_nand_8"; +} + +/// InitLibcallCallingConvs - Set default libcall CallingConvs. +/// +static void InitLibcallCallingConvs(CallingConv::ID *CCs) { + for (int i = 0; i < RTLIB::UNKNOWN_LIBCALL; ++i) { + CCs[i] = CallingConv::C; + } +} + +/// getFPEXT - Return the FPEXT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPEXT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::f64) + return FPEXT_F32_F64; + } + + return UNKNOWN_LIBCALL; +} + +/// getFPROUND - Return the FPROUND_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPROUND(EVT OpVT, EVT RetVT) { + if (RetVT == MVT::f32) { + if (OpVT == MVT::f64) + return FPROUND_F64_F32; + if (OpVT == MVT::f80) + return FPROUND_F80_F32; + if (OpVT == MVT::ppcf128) + return FPROUND_PPCF128_F32; + } else if (RetVT == MVT::f64) { + if (OpVT == MVT::f80) + return FPROUND_F80_F64; + if (OpVT == MVT::ppcf128) + return FPROUND_PPCF128_F64; + } + + return UNKNOWN_LIBCALL; +} + +/// getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPTOSINT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::i8) + return FPTOSINT_F32_I8; + if (RetVT == MVT::i16) + return FPTOSINT_F32_I16; + if (RetVT == MVT::i32) + return FPTOSINT_F32_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F32_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F32_I128; + } else if (OpVT == MVT::f64) { + if (RetVT == MVT::i8) + return FPTOSINT_F64_I8; + if (RetVT == MVT::i16) + return FPTOSINT_F64_I16; + if (RetVT == MVT::i32) + return FPTOSINT_F64_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F64_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F64_I128; + } else if (OpVT == MVT::f80) { + if (RetVT == MVT::i32) + return FPTOSINT_F80_I32; + if (RetVT == MVT::i64) + return FPTOSINT_F80_I64; + if (RetVT == MVT::i128) + return FPTOSINT_F80_I128; + } else if (OpVT == MVT::ppcf128) { + if (RetVT == MVT::i32) + return FPTOSINT_PPCF128_I32; + if (RetVT == MVT::i64) + return FPTOSINT_PPCF128_I64; + if (RetVT == MVT::i128) + return FPTOSINT_PPCF128_I128; + } + return UNKNOWN_LIBCALL; +} + +/// getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getFPTOUINT(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::f32) { + if (RetVT == MVT::i8) + return FPTOUINT_F32_I8; + if (RetVT == MVT::i16) + return FPTOUINT_F32_I16; + if (RetVT == MVT::i32) + return FPTOUINT_F32_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F32_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F32_I128; + } else if (OpVT == MVT::f64) { + if (RetVT == MVT::i8) + return FPTOUINT_F64_I8; + if (RetVT == MVT::i16) + return FPTOUINT_F64_I16; + if (RetVT == MVT::i32) + return FPTOUINT_F64_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F64_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F64_I128; + } else if (OpVT == MVT::f80) { + if (RetVT == MVT::i32) + return FPTOUINT_F80_I32; + if (RetVT == MVT::i64) + return FPTOUINT_F80_I64; + if (RetVT == MVT::i128) + return FPTOUINT_F80_I128; + } else if (OpVT == MVT::ppcf128) { + if (RetVT == MVT::i32) + return FPTOUINT_PPCF128_I32; + if (RetVT == MVT::i64) + return FPTOUINT_PPCF128_I64; + if (RetVT == MVT::i128) + return FPTOUINT_PPCF128_I128; + } + return UNKNOWN_LIBCALL; +} + +/// getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getSINTTOFP(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::i32) { + if (RetVT == MVT::f32) + return SINTTOFP_I32_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I32_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I32_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I32_PPCF128; + } else if (OpVT == MVT::i64) { + if (RetVT == MVT::f32) + return SINTTOFP_I64_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I64_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I64_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I64_PPCF128; + } else if (OpVT == MVT::i128) { + if (RetVT == MVT::f32) + return SINTTOFP_I128_F32; + else if (RetVT == MVT::f64) + return SINTTOFP_I128_F64; + else if (RetVT == MVT::f80) + return SINTTOFP_I128_F80; + else if (RetVT == MVT::ppcf128) + return SINTTOFP_I128_PPCF128; + } + return UNKNOWN_LIBCALL; +} + +/// getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or +/// UNKNOWN_LIBCALL if there is none. +RTLIB::Libcall RTLIB::getUINTTOFP(EVT OpVT, EVT RetVT) { + if (OpVT == MVT::i32) { + if (RetVT == MVT::f32) + return UINTTOFP_I32_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I32_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I32_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I32_PPCF128; + } else if (OpVT == MVT::i64) { + if (RetVT == MVT::f32) + return UINTTOFP_I64_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I64_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I64_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I64_PPCF128; + } else if (OpVT == MVT::i128) { + if (RetVT == MVT::f32) + return UINTTOFP_I128_F32; + else if (RetVT == MVT::f64) + return UINTTOFP_I128_F64; + else if (RetVT == MVT::f80) + return UINTTOFP_I128_F80; + else if (RetVT == MVT::ppcf128) + return UINTTOFP_I128_PPCF128; + } + return UNKNOWN_LIBCALL; +} + +/// InitCmpLibcallCCs - Set default comparison libcall CC. +/// +static void InitCmpLibcallCCs(ISD::CondCode *CCs) { + memset(CCs, ISD::SETCC_INVALID, sizeof(ISD::CondCode)*RTLIB::UNKNOWN_LIBCALL); + CCs[RTLIB::OEQ_F32] = ISD::SETEQ; + CCs[RTLIB::OEQ_F64] = ISD::SETEQ; + CCs[RTLIB::UNE_F32] = ISD::SETNE; + CCs[RTLIB::UNE_F64] = ISD::SETNE; + CCs[RTLIB::OGE_F32] = ISD::SETGE; + CCs[RTLIB::OGE_F64] = ISD::SETGE; + CCs[RTLIB::OLT_F32] = ISD::SETLT; + CCs[RTLIB::OLT_F64] = ISD::SETLT; + CCs[RTLIB::OLE_F32] = ISD::SETLE; + CCs[RTLIB::OLE_F64] = ISD::SETLE; + CCs[RTLIB::OGT_F32] = ISD::SETGT; + CCs[RTLIB::OGT_F64] = ISD::SETGT; + CCs[RTLIB::UO_F32] = ISD::SETNE; + CCs[RTLIB::UO_F64] = ISD::SETNE; + CCs[RTLIB::O_F32] = ISD::SETEQ; + CCs[RTLIB::O_F64] = ISD::SETEQ; +} + +/// NOTE: The constructor takes ownership of TLOF. +TargetLowering::TargetLowering(const TargetMachine &tm, + const TargetLoweringObjectFile *tlof) + : TM(tm), TD(TM.getTargetData()), TLOF(*tlof) { + // All operations default to being supported. + memset(OpActions, 0, sizeof(OpActions)); + memset(LoadExtActions, 0, sizeof(LoadExtActions)); + memset(TruncStoreActions, 0, sizeof(TruncStoreActions)); + memset(IndexedModeActions, 0, sizeof(IndexedModeActions)); + memset(CondCodeActions, 0, sizeof(CondCodeActions)); + + // Set default actions for various operations. + for (unsigned VT = 0; VT != (unsigned)MVT::LAST_VALUETYPE; ++VT) { + // Default all indexed load / store to expand. + for (unsigned IM = (unsigned)ISD::PRE_INC; + IM != (unsigned)ISD::LAST_INDEXED_MODE; ++IM) { + setIndexedLoadAction(IM, (MVT::SimpleValueType)VT, Expand); + setIndexedStoreAction(IM, (MVT::SimpleValueType)VT, Expand); + } + + // These operations default to expand. + setOperationAction(ISD::FGETSIGN, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::CONCAT_VECTORS, (MVT::SimpleValueType)VT, Expand); + } + + // Most targets ignore the @llvm.prefetch intrinsic. + setOperationAction(ISD::PREFETCH, MVT::Other, Expand); + + // ConstantFP nodes default to expand. Targets can either change this to + // Legal, in which case all fp constants are legal, or use isFPImmLegal() + // to optimize expansions for certain constants. + setOperationAction(ISD::ConstantFP, MVT::f32, Expand); + setOperationAction(ISD::ConstantFP, MVT::f64, Expand); + setOperationAction(ISD::ConstantFP, MVT::f80, Expand); + + // These library functions default to expand. + setOperationAction(ISD::FLOG , MVT::f64, Expand); + setOperationAction(ISD::FLOG2, MVT::f64, Expand); + setOperationAction(ISD::FLOG10,MVT::f64, Expand); + setOperationAction(ISD::FEXP , MVT::f64, Expand); + setOperationAction(ISD::FEXP2, MVT::f64, Expand); + setOperationAction(ISD::FLOG , MVT::f32, Expand); + setOperationAction(ISD::FLOG2, MVT::f32, Expand); + setOperationAction(ISD::FLOG10,MVT::f32, Expand); + setOperationAction(ISD::FEXP , MVT::f32, Expand); + setOperationAction(ISD::FEXP2, MVT::f32, Expand); + + // Default ISD::TRAP to expand (which turns it into abort). + setOperationAction(ISD::TRAP, MVT::Other, Expand); + + IsLittleEndian = TD->isLittleEndian(); + PointerTy = MVT::getIntegerVT(8*TD->getPointerSize()); + memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*)); + memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray)); + maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8; + maxStoresPerMemsetOptSize = maxStoresPerMemcpyOptSize + = maxStoresPerMemmoveOptSize = 4; + benefitFromCodePlacementOpt = false; + UseUnderscoreSetJmp = false; + UseUnderscoreLongJmp = false; + SelectIsExpensive = false; + IntDivIsCheap = false; + Pow2DivIsCheap = false; + JumpIsExpensive = false; + StackPointerRegisterToSaveRestore = 0; + ExceptionPointerRegister = 0; + ExceptionSelectorRegister = 0; + BooleanContents = UndefinedBooleanContent; + SchedPreferenceInfo = Sched::Latency; + JumpBufSize = 0; + JumpBufAlignment = 0; + PrefLoopAlignment = 0; + MinStackArgumentAlignment = 1; + ShouldFoldAtomicFences = false; + + InitLibcallNames(LibcallRoutineNames); + InitCmpLibcallCCs(CmpLibcallCCs); + InitLibcallCallingConvs(LibcallCallingConvs); +} + +TargetLowering::~TargetLowering() { + delete &TLOF; +} + +MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const { + return MVT::getIntegerVT(8*TD->getPointerSize()); +} + +/// canOpTrap - Returns true if the operation can trap for the value type. +/// VT must be a legal type. +bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const { + assert(isTypeLegal(VT)); + switch (Op) { + default: + return false; + case ISD::FDIV: + case ISD::FREM: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + return true; + } +} + + +static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT, + TargetLowering *TLI) { + // Figure out the right, legal destination reg to copy into. + unsigned NumElts = VT.getVectorNumElements(); + MVT EltTy = VT.getVectorElementType(); + + unsigned NumVectorRegs = 1; + + // FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we + // could break down into LHS/RHS like LegalizeDAG does. + if (!isPowerOf2_32(NumElts)) { + NumVectorRegs = NumElts; + NumElts = 1; + } + + // Divide the input until we get to a supported size. This will always + // end with a scalar if the target doesn't support vectors. + while (NumElts > 1 && !TLI->isTypeLegal(MVT::getVectorVT(EltTy, NumElts))) { + NumElts >>= 1; + NumVectorRegs <<= 1; + } + + NumIntermediates = NumVectorRegs; + + MVT NewVT = MVT::getVectorVT(EltTy, NumElts); + if (!TLI->isTypeLegal(NewVT)) + NewVT = EltTy; + IntermediateVT = NewVT; + + EVT DestVT = TLI->getRegisterType(NewVT); + RegisterVT = DestVT; + if (EVT(DestVT).bitsLT(NewVT)) // Value is expanded, e.g. i64 -> i16. + return NumVectorRegs*(NewVT.getSizeInBits()/DestVT.getSizeInBits()); + + // Otherwise, promotion or legal types use the same number of registers as + // the vector decimated to the appropriate level. + return NumVectorRegs; +} + +/// isLegalRC - Return true if the value types that can be represented by the +/// specified register class are all legal. +bool TargetLowering::isLegalRC(const TargetRegisterClass *RC) const { + for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); + I != E; ++I) { + if (isTypeLegal(*I)) + return true; + } + return false; +} + +/// hasLegalSuperRegRegClasses - Return true if the specified register class +/// has one or more super-reg register classes that are legal. +bool +TargetLowering::hasLegalSuperRegRegClasses(const TargetRegisterClass *RC) const{ + if (*RC->superregclasses_begin() == 0) + return false; + for (TargetRegisterInfo::regclass_iterator I = RC->superregclasses_begin(), + E = RC->superregclasses_end(); I != E; ++I) { + const TargetRegisterClass *RRC = *I; + if (isLegalRC(RRC)) + return true; + } + return false; +} + +/// findRepresentativeClass - Return the largest legal super-reg register class +/// of the register class for the specified type and its associated "cost". +std::pair +TargetLowering::findRepresentativeClass(EVT VT) const { + const TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT().SimpleTy]; + if (!RC) + return std::make_pair(RC, 0); + const TargetRegisterClass *BestRC = RC; + for (TargetRegisterInfo::regclass_iterator I = RC->superregclasses_begin(), + E = RC->superregclasses_end(); I != E; ++I) { + const TargetRegisterClass *RRC = *I; + if (RRC->isASubClass() || !isLegalRC(RRC)) + continue; + if (!hasLegalSuperRegRegClasses(RRC)) + return std::make_pair(RRC, 1); + BestRC = RRC; + } + return std::make_pair(BestRC, 1); +} + + +/// computeRegisterProperties - Once all of the register classes are added, +/// this allows us to compute derived properties we expose. +void TargetLowering::computeRegisterProperties() { + assert(MVT::LAST_VALUETYPE <= MVT::MAX_ALLOWED_VALUETYPE && + "Too many value types for ValueTypeActions to hold!"); + + // Everything defaults to needing one register. + for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) { + NumRegistersForVT[i] = 1; + RegisterTypeForVT[i] = TransformToType[i] = (MVT::SimpleValueType)i; + } + // ...except isVoid, which doesn't need any registers. + NumRegistersForVT[MVT::isVoid] = 0; + + // Find the largest integer register class. + unsigned LargestIntReg = MVT::LAST_INTEGER_VALUETYPE; + for (; RegClassForVT[LargestIntReg] == 0; --LargestIntReg) + assert(LargestIntReg != MVT::i1 && "No integer registers defined!"); + + // Every integer value type larger than this largest register takes twice as + // many registers to represent as the previous ValueType. + for (unsigned ExpandedReg = LargestIntReg + 1; ; ++ExpandedReg) { + EVT ExpandedVT = (MVT::SimpleValueType)ExpandedReg; + if (!ExpandedVT.isInteger()) + break; + NumRegistersForVT[ExpandedReg] = 2*NumRegistersForVT[ExpandedReg-1]; + RegisterTypeForVT[ExpandedReg] = (MVT::SimpleValueType)LargestIntReg; + TransformToType[ExpandedReg] = (MVT::SimpleValueType)(ExpandedReg - 1); + ValueTypeActions.setTypeAction(ExpandedVT, Expand); + } + + // Inspect all of the ValueType's smaller than the largest integer + // register to see which ones need promotion. + unsigned LegalIntReg = LargestIntReg; + for (unsigned IntReg = LargestIntReg - 1; + IntReg >= (unsigned)MVT::i1; --IntReg) { + EVT IVT = (MVT::SimpleValueType)IntReg; + if (isTypeLegal(IVT)) { + LegalIntReg = IntReg; + } else { + RegisterTypeForVT[IntReg] = TransformToType[IntReg] = + (MVT::SimpleValueType)LegalIntReg; + ValueTypeActions.setTypeAction(IVT, Promote); + } + } + + // ppcf128 type is really two f64's. + if (!isTypeLegal(MVT::ppcf128)) { + NumRegistersForVT[MVT::ppcf128] = 2*NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::ppcf128] = MVT::f64; + TransformToType[MVT::ppcf128] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::ppcf128, Expand); + } + + // Decide how to handle f64. If the target does not have native f64 support, + // expand it to i64 and we will be generating soft float library calls. + if (!isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64]; + RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64]; + TransformToType[MVT::f64] = MVT::i64; + ValueTypeActions.setTypeAction(MVT::f64, Expand); + } + + // Decide how to handle f32. If the target does not have native support for + // f32, promote it to f64 if it is legal. Otherwise, expand it to i32. + if (!isTypeLegal(MVT::f32)) { + if (isTypeLegal(MVT::f64)) { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::f64]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::f64]; + TransformToType[MVT::f32] = MVT::f64; + ValueTypeActions.setTypeAction(MVT::f32, Promote); + } else { + NumRegistersForVT[MVT::f32] = NumRegistersForVT[MVT::i32]; + RegisterTypeForVT[MVT::f32] = RegisterTypeForVT[MVT::i32]; + TransformToType[MVT::f32] = MVT::i32; + ValueTypeActions.setTypeAction(MVT::f32, Expand); + } + } + + // Loop over all of the vector value types to see which need transformations. + for (unsigned i = MVT::FIRST_VECTOR_VALUETYPE; + i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { + MVT VT = (MVT::SimpleValueType)i; + if (isTypeLegal(VT)) continue; + + // Determine if there is a legal wider type. If so, we should promote to + // that wider vector type. + EVT EltVT = VT.getVectorElementType(); + unsigned NElts = VT.getVectorNumElements(); + if (NElts != 1) { + bool IsLegalWiderType = false; + for (unsigned nVT = i+1; nVT <= MVT::LAST_VECTOR_VALUETYPE; ++nVT) { + EVT SVT = (MVT::SimpleValueType)nVT; + if (SVT.getVectorElementType() == EltVT && + SVT.getVectorNumElements() > NElts && + isTypeLegal(SVT)) { + TransformToType[i] = SVT; + RegisterTypeForVT[i] = SVT; + NumRegistersForVT[i] = 1; + ValueTypeActions.setTypeAction(VT, Promote); + IsLegalWiderType = true; + break; + } + } + if (IsLegalWiderType) continue; + } + + MVT IntermediateVT; + EVT RegisterVT; + unsigned NumIntermediates; + NumRegistersForVT[i] = + getVectorTypeBreakdownMVT(VT, IntermediateVT, NumIntermediates, + RegisterVT, this); + RegisterTypeForVT[i] = RegisterVT; + + EVT NVT = VT.getPow2VectorType(); + if (NVT == VT) { + // Type is already a power of 2. The default action is to split. + TransformToType[i] = MVT::Other; + ValueTypeActions.setTypeAction(VT, Expand); + } else { + TransformToType[i] = NVT; + ValueTypeActions.setTypeAction(VT, Promote); + } + } + + // Determine the 'representative' register class for each value type. + // An representative register class is the largest (meaning one which is + // not a sub-register class / subreg register class) legal register class for + // a group of value types. For example, on i386, i8, i16, and i32 + // representative would be GR32; while on x86_64 it's GR64. + for (unsigned i = 0; i != MVT::LAST_VALUETYPE; ++i) { + const TargetRegisterClass* RRC; + uint8_t Cost; + tie(RRC, Cost) = findRepresentativeClass((MVT::SimpleValueType)i); + RepRegClassForVT[i] = RRC; + RepRegClassCostForVT[i] = Cost; + } +} + +const char *TargetLowering::getTargetNodeName(unsigned Opcode) const { + return NULL; +} + + +MVT::SimpleValueType TargetLowering::getSetCCResultType(EVT VT) const { + return PointerTy.SimpleTy; +} + +MVT::SimpleValueType TargetLowering::getCmpLibcallReturnType() const { + return MVT::i32; // return the default value +} + +/// getVectorTypeBreakdown - Vector types are broken down into some number of +/// legal first class types. For example, MVT::v8f32 maps to 2 MVT::v4f32 +/// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack. +/// Similarly, MVT::v2i64 turns into 4 MVT::i32 values with both PPC and X86. +/// +/// This method returns the number of registers needed, and the VT for each +/// register. It also returns the VT and quantity of the intermediate values +/// before they are promoted/expanded. +/// +unsigned TargetLowering::getVectorTypeBreakdown(LLVMContext &Context, EVT VT, + EVT &IntermediateVT, + unsigned &NumIntermediates, + EVT &RegisterVT) const { + unsigned NumElts = VT.getVectorNumElements(); + + // If there is a wider vector type with the same element type as this one, + // we should widen to that legal vector type. This handles things like + // <2 x float> -> <4 x float>. + if (NumElts != 1 && getTypeAction(VT) == Promote) { + RegisterVT = getTypeToTransformTo(Context, VT); + if (isTypeLegal(RegisterVT)) { + IntermediateVT = RegisterVT; + NumIntermediates = 1; + return 1; + } + } + + // Figure out the right, legal destination reg to copy into. + EVT EltTy = VT.getVectorElementType(); + + unsigned NumVectorRegs = 1; + + // FIXME: We don't support non-power-of-2-sized vectors for now. Ideally we + // could break down into LHS/RHS like LegalizeDAG does. + if (!isPowerOf2_32(NumElts)) { + NumVectorRegs = NumElts; + NumElts = 1; + } + + // Divide the input until we get to a supported size. This will always + // end with a scalar if the target doesn't support vectors. + while (NumElts > 1 && !isTypeLegal( + EVT::getVectorVT(Context, EltTy, NumElts))) { + NumElts >>= 1; + NumVectorRegs <<= 1; + } + + NumIntermediates = NumVectorRegs; + + EVT NewVT = EVT::getVectorVT(Context, EltTy, NumElts); + if (!isTypeLegal(NewVT)) + NewVT = EltTy; + IntermediateVT = NewVT; + + EVT DestVT = getRegisterType(Context, NewVT); + RegisterVT = DestVT; + if (DestVT.bitsLT(NewVT)) // Value is expanded, e.g. i64 -> i16. + return NumVectorRegs*(NewVT.getSizeInBits()/DestVT.getSizeInBits()); + + // Otherwise, promotion or legal types use the same number of registers as + // the vector decimated to the appropriate level. + return NumVectorRegs; +} + +/// Get the EVTs and ArgFlags collections that represent the legalized return +/// type of the given function. This does not require a DAG or a return value, +/// and is suitable for use before any DAGs for the function are constructed. +/// TODO: Move this out of TargetLowering.cpp. +void llvm::GetReturnInfo(const Type* ReturnType, Attributes attr, + SmallVectorImpl &Outs, + const TargetLowering &TLI, + SmallVectorImpl *Offsets) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, ReturnType, ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues == 0) return; + unsigned Offset = 0; + + for (unsigned j = 0, f = NumValues; j != f; ++j) { + EVT VT = ValueVTs[j]; + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + if (attr & Attribute::SExt) + ExtendKind = ISD::SIGN_EXTEND; + else if (attr & Attribute::ZExt) + ExtendKind = ISD::ZERO_EXTEND; + + // FIXME: C calling convention requires the return type to be promoted to + // at least 32-bit. But this is not necessary for non-C calling + // conventions. The frontend should mark functions whose return values + // require promoting with signext or zeroext attributes. + if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) { + EVT MinVT = TLI.getRegisterType(ReturnType->getContext(), MVT::i32); + if (VT.bitsLT(MinVT)) + VT = MinVT; + } + + unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT); + EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT); + unsigned PartSize = TLI.getTargetData()->getTypeAllocSize( + PartVT.getTypeForEVT(ReturnType->getContext())); + + // 'inreg' on function refers to return value + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (attr & Attribute::InReg) + Flags.setInReg(); + + // Propagate extension type if any + if (attr & Attribute::SExt) + Flags.setSExt(); + else if (attr & Attribute::ZExt) + Flags.setZExt(); + + for (unsigned i = 0; i < NumParts; ++i) { + Outs.push_back(ISD::OutputArg(Flags, PartVT, /*isFixed=*/true)); + if (Offsets) { + Offsets->push_back(Offset); + Offset += PartSize; + } + } + } +} + +/// getByValTypeAlignment - Return the desired alignment for ByVal aggregate +/// function arguments in the caller parameter area. This is the actual +/// alignment, not its logarithm. +unsigned TargetLowering::getByValTypeAlignment(const Type *Ty) const { + return TD->getCallFrameTypeAlignment(Ty); +} + +/// getJumpTableEncoding - Return the entry encoding for a jump table in the +/// current function. The returned value is a member of the +/// MachineJumpTableInfo::JTEntryKind enum. +unsigned TargetLowering::getJumpTableEncoding() const { + // In non-pic modes, just use the address of a block. + if (getTargetMachine().getRelocationModel() != Reloc::PIC_) + return MachineJumpTableInfo::EK_BlockAddress; + + // In PIC mode, if the target supports a GPRel32 directive, use it. + if (getTargetMachine().getMCAsmInfo()->getGPRel32Directive() != 0) + return MachineJumpTableInfo::EK_GPRel32BlockAddress; + + // Otherwise, use a label difference. + return MachineJumpTableInfo::EK_LabelDifference32; +} + +SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table, + SelectionDAG &DAG) const { + // If our PIC model is GP relative, use the global offset table as the base. + if (getJumpTableEncoding() == MachineJumpTableInfo::EK_GPRel32BlockAddress) + return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy()); + return Table; +} + +/// getPICJumpTableRelocBaseExpr - This returns the relocation base for the +/// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an +/// MCExpr. +const MCExpr * +TargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF, + unsigned JTI,MCContext &Ctx) const{ + // The normal PIC reloc base is the label at the start of the jump table. + return MCSymbolRefExpr::Create(MF->getJTISymbol(JTI, Ctx), Ctx); +} + +bool +TargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // Assume that everything is safe in static mode. + if (getTargetMachine().getRelocationModel() == Reloc::Static) + return true; + + // In dynamic-no-pic mode, assume that known defined values are safe. + if (getTargetMachine().getRelocationModel() == Reloc::DynamicNoPIC && + GA && + !GA->getGlobal()->isDeclaration() && + !GA->getGlobal()->isWeakForLinker()) + return true; + + // Otherwise assume nothing is safe. + return false; +} + +//===----------------------------------------------------------------------===// +// Optimization Methods +//===----------------------------------------------------------------------===// + +/// ShrinkDemandedConstant - Check to see if the specified operand of the +/// specified instruction is a constant integer. If so, check to see if there +/// are any bits set in the constant that are not demanded. If so, shrink the +/// constant and return true. +bool TargetLowering::TargetLoweringOpt::ShrinkDemandedConstant(SDValue Op, + const APInt &Demanded) { + DebugLoc dl = Op.getDebugLoc(); + + // FIXME: ISD::SELECT, ISD::SELECT_CC + switch (Op.getOpcode()) { + default: break; + case ISD::XOR: + case ISD::AND: + case ISD::OR: { + ConstantSDNode *C = dyn_cast(Op.getOperand(1)); + if (!C) return false; + + if (Op.getOpcode() == ISD::XOR && + (C->getAPIntValue() | (~Demanded)).isAllOnesValue()) + return false; + + // if we can expand it to have all bits set, do it + if (C->getAPIntValue().intersects(~Demanded)) { + EVT VT = Op.getValueType(); + SDValue New = DAG.getNode(Op.getOpcode(), dl, VT, Op.getOperand(0), + DAG.getConstant(Demanded & + C->getAPIntValue(), + VT)); + return CombineTo(Op, New); + } + + break; + } + } + + return false; +} + +/// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the +/// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening +/// cast, but it could be generalized for targets with other types of +/// implicit widening casts. +bool +TargetLowering::TargetLoweringOpt::ShrinkDemandedOp(SDValue Op, + unsigned BitWidth, + const APInt &Demanded, + DebugLoc dl) { + assert(Op.getNumOperands() == 2 && + "ShrinkDemandedOp only supports binary operators!"); + assert(Op.getNode()->getNumValues() == 1 && + "ShrinkDemandedOp only supports nodes with one result!"); + + // Don't do this if the node has another user, which may require the + // full value. + if (!Op.getNode()->hasOneUse()) + return false; + + // Search for the smallest integer type with free casts to and from + // Op's type. For expedience, just check power-of-2 integer types. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned SmallVTBits = BitWidth - Demanded.countLeadingZeros(); + if (!isPowerOf2_32(SmallVTBits)) + SmallVTBits = NextPowerOf2(SmallVTBits); + for (; SmallVTBits < BitWidth; SmallVTBits = NextPowerOf2(SmallVTBits)) { + EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), SmallVTBits); + if (TLI.isTruncateFree(Op.getValueType(), SmallVT) && + TLI.isZExtFree(SmallVT, Op.getValueType())) { + // We found a type with free casts. + SDValue X = DAG.getNode(Op.getOpcode(), dl, SmallVT, + DAG.getNode(ISD::TRUNCATE, dl, SmallVT, + Op.getNode()->getOperand(0)), + DAG.getNode(ISD::TRUNCATE, dl, SmallVT, + Op.getNode()->getOperand(1))); + SDValue Z = DAG.getNode(ISD::ZERO_EXTEND, dl, Op.getValueType(), X); + return CombineTo(Op, Z); + } + } + return false; +} + +/// SimplifyDemandedBits - Look at Op. At this point, we know that only the +/// DemandedMask bits of the result of Op are ever used downstream. If we can +/// use this information to simplify Op, create a new simplified DAG node and +/// return true, returning the original and new nodes in Old and New. Otherwise, +/// analyze the expression and return a mask of KnownOne and KnownZero bits for +/// the expression (used to simplify the caller). The KnownZero/One bits may +/// only be accurate for those bits in the DemandedMask. +bool TargetLowering::SimplifyDemandedBits(SDValue Op, + const APInt &DemandedMask, + APInt &KnownZero, + APInt &KnownOne, + TargetLoweringOpt &TLO, + unsigned Depth) const { + unsigned BitWidth = DemandedMask.getBitWidth(); + assert(Op.getValueType().getScalarType().getSizeInBits() == BitWidth && + "Mask size mismatches value type size!"); + APInt NewMask = DemandedMask; + DebugLoc dl = Op.getDebugLoc(); + + // Don't know anything. + KnownZero = KnownOne = APInt(BitWidth, 0); + + // Other users may use these bits. + if (!Op.getNode()->hasOneUse()) { + if (Depth != 0) { + // If not at the root, Just compute the KnownZero/KnownOne bits to + // simplify things downstream. + TLO.DAG.ComputeMaskedBits(Op, DemandedMask, KnownZero, KnownOne, Depth); + return false; + } + // If this is the root being simplified, allow it to have multiple uses, + // just set the NewMask to all bits. + NewMask = APInt::getAllOnesValue(BitWidth); + } else if (DemandedMask == 0) { + // Not demanding any bits from Op. + if (Op.getOpcode() != ISD::UNDEF) + return TLO.CombineTo(Op, TLO.DAG.getUNDEF(Op.getValueType())); + return false; + } else if (Depth == 6) { // Limit search depth. + return false; + } + + APInt KnownZero2, KnownOne2, KnownZeroOut, KnownOneOut; + switch (Op.getOpcode()) { + case ISD::Constant: + // We know all of the bits for a constant! + KnownOne = cast(Op)->getAPIntValue() & NewMask; + KnownZero = ~KnownOne & NewMask; + return false; // Don't fall through, will infinitely loop. + case ISD::AND: + // If the RHS is a constant, check to see if the LHS would be zero without + // using the bits from the RHS. Below, we use knowledge about the RHS to + // simplify the LHS, here we're using information from the LHS to simplify + // the RHS. + if (ConstantSDNode *RHSC = dyn_cast(Op.getOperand(1))) { + APInt LHSZero, LHSOne; + // Do not increment Depth here; that can cause an infinite loop. + TLO.DAG.ComputeMaskedBits(Op.getOperand(0), NewMask, + LHSZero, LHSOne, Depth); + // If the LHS already has zeros where RHSC does, this and is dead. + if ((LHSZero & NewMask) == (~RHSC->getAPIntValue() & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + // If any of the set bits in the RHS are known zero on the LHS, shrink + // the constant. + if (TLO.ShrinkDemandedConstant(Op, ~LHSZero & NewMask)) + return true; + } + + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), ~KnownZero & NewMask, + KnownZero2, KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known one on one side, return the other. + // These bits cannot contribute to the result of the 'and'. + if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If all of the demanded bits in the inputs are known zeros, return zero. + if ((NewMask & (KnownZero|KnownZero2)) == NewMask) + return TLO.CombineTo(Op, TLO.DAG.getConstant(0, Op.getValueType())); + // If the RHS is a constant, see if we can simplify it. + if (TLO.ShrinkDemandedConstant(Op, ~KnownZero2 & NewMask)) + return true; + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // Output known-1 bits are only known if set in both the LHS & RHS. + KnownOne &= KnownOne2; + // Output known-0 are known to be clear if zero in either the LHS | RHS. + KnownZero |= KnownZero2; + break; + case ISD::OR: + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), ~KnownOne & NewMask, + KnownZero2, KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'or'. + if ((NewMask & ~KnownOne2 & KnownZero) == (~KnownOne2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownOne & KnownZero2) == (~KnownOne & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If all of the potentially set bits on one side are known to be set on + // the other side, just use the 'other' side. + if ((NewMask & ~KnownZero & KnownOne2) == (~KnownZero & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((NewMask & ~KnownZero2 & KnownOne) == (~KnownZero2 & NewMask)) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If the RHS is a constant, see if we can simplify it. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // Output known-0 bits are only known if clear in both the LHS & RHS. + KnownZero &= KnownZero2; + // Output known-1 are known to be set if set in either the LHS | RHS. + KnownOne |= KnownOne2; + break; + case ISD::XOR: + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + if (SimplifyDemandedBits(Op.getOperand(0), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If all of the demanded bits are known zero on one side, return the other. + // These bits cannot contribute to the result of the 'xor'. + if ((KnownZero & NewMask) == NewMask) + return TLO.CombineTo(Op, Op.getOperand(0)); + if ((KnownZero2 & NewMask) == NewMask) + return TLO.CombineTo(Op, Op.getOperand(1)); + // If the operation can be done in a smaller type, do so. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + + // If all of the unknown bits are known to be zero on one side or the other + // (but not both) turn this into an *inclusive* or. + // e.g. (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0 + if ((NewMask & ~KnownZero & ~KnownZero2) == 0) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, Op.getValueType(), + Op.getOperand(0), + Op.getOperand(1))); + + // Output known-0 bits are known if clear or set in both the LHS & RHS. + KnownZeroOut = (KnownZero & KnownZero2) | (KnownOne & KnownOne2); + // Output known-1 are known to be set if set in only one of the LHS, RHS. + KnownOneOut = (KnownZero & KnownOne2) | (KnownOne & KnownZero2); + + // If all of the demanded bits on one side are known, and all of the set + // bits on that side are also known to be set on the other side, turn this + // into an AND, as we know the bits will be cleared. + // e.g. (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2 + if ((NewMask & (KnownZero|KnownOne)) == NewMask) { // all known + if ((KnownOne & KnownOne2) == KnownOne) { + EVT VT = Op.getValueType(); + SDValue ANDC = TLO.DAG.getConstant(~KnownOne & NewMask, VT); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::AND, dl, VT, + Op.getOperand(0), ANDC)); + } + } + + // If the RHS is a constant, see if we can simplify it. + // for XOR, we prefer to force bits to 1 if they will make a -1. + // if we can't force bits, try to shrink constant + if (ConstantSDNode *C = dyn_cast(Op.getOperand(1))) { + APInt Expanded = C->getAPIntValue() | (~NewMask); + // if we can expand it to have all bits set, do it + if (Expanded.isAllOnesValue()) { + if (Expanded != C->getAPIntValue()) { + EVT VT = Op.getValueType(); + SDValue New = TLO.DAG.getNode(Op.getOpcode(), dl,VT, Op.getOperand(0), + TLO.DAG.getConstant(Expanded, VT)); + return TLO.CombineTo(Op, New); + } + // if it already has all the bits set, nothing to change + // but don't shrink either! + } else if (TLO.ShrinkDemandedConstant(Op, NewMask)) { + return true; + } + } + + KnownZero = KnownZeroOut; + KnownOne = KnownOneOut; + break; + case ISD::SELECT: + if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(1), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If the operands are constants, see if we can simplify them. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + break; + case ISD::SELECT_CC: + if (SimplifyDemandedBits(Op.getOperand(3), NewMask, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(2), NewMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?"); + + // If the operands are constants, see if we can simplify them. + if (TLO.ShrinkDemandedConstant(Op, NewMask)) + return true; + + // Only known if known in both the LHS and RHS. + KnownOne &= KnownOne2; + KnownZero &= KnownZero2; + break; + case ISD::SHL: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + unsigned ShAmt = SA->getZExtValue(); + SDValue InOp = Op.getOperand(0); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + // If this is ((X >>u C1) << ShAmt), see if we can simplify this into a + // single shift. We can do this if the bottom bits (which are shifted + // out) are never demanded. + if (InOp.getOpcode() == ISD::SRL && + isa(InOp.getOperand(1))) { + if (ShAmt && (NewMask & APInt::getLowBitsSet(BitWidth, ShAmt)) == 0) { + unsigned C1= cast(InOp.getOperand(1))->getZExtValue(); + unsigned Opc = ISD::SHL; + int Diff = ShAmt-C1; + if (Diff < 0) { + Diff = -Diff; + Opc = ISD::SRL; + } + + SDValue NewSA = + TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType()); + EVT VT = Op.getValueType(); + return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, VT, + InOp.getOperand(0), NewSA)); + } + } + + if (SimplifyDemandedBits(InOp, NewMask.lshr(ShAmt), + KnownZero, KnownOne, TLO, Depth+1)) + return true; + + // Convert (shl (anyext x, c)) to (anyext (shl x, c)) if the high bits + // are not demanded. This will likely allow the anyext to be folded away. + if (InOp.getNode()->getOpcode() == ISD::ANY_EXTEND) { + SDValue InnerOp = InOp.getNode()->getOperand(0); + EVT InnerVT = InnerOp.getValueType(); + if ((APInt::getHighBitsSet(BitWidth, + BitWidth - InnerVT.getSizeInBits()) & + DemandedMask) == 0 && + isTypeDesirableForOp(ISD::SHL, InnerVT)) { + EVT ShTy = getShiftAmountTy(InnerVT); + if (!APInt(BitWidth, ShAmt).isIntN(ShTy.getSizeInBits())) + ShTy = InnerVT; + SDValue NarrowShl = + TLO.DAG.getNode(ISD::SHL, dl, InnerVT, InnerOp, + TLO.DAG.getConstant(ShAmt, ShTy)); + return + TLO.CombineTo(Op, + TLO.DAG.getNode(ISD::ANY_EXTEND, dl, Op.getValueType(), + NarrowShl)); + } + } + + KnownZero <<= SA->getZExtValue(); + KnownOne <<= SA->getZExtValue(); + // low bits known zero. + KnownZero |= APInt::getLowBitsSet(BitWidth, SA->getZExtValue()); + } + break; + case ISD::SRL: + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + EVT VT = Op.getValueType(); + unsigned ShAmt = SA->getZExtValue(); + unsigned VTSize = VT.getSizeInBits(); + SDValue InOp = Op.getOperand(0); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + // If this is ((X << C1) >>u ShAmt), see if we can simplify this into a + // single shift. We can do this if the top bits (which are shifted out) + // are never demanded. + if (InOp.getOpcode() == ISD::SHL && + isa(InOp.getOperand(1))) { + if (ShAmt && (NewMask & APInt::getHighBitsSet(VTSize, ShAmt)) == 0) { + unsigned C1= cast(InOp.getOperand(1))->getZExtValue(); + unsigned Opc = ISD::SRL; + int Diff = ShAmt-C1; + if (Diff < 0) { + Diff = -Diff; + Opc = ISD::SHL; + } + + SDValue NewSA = + TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType()); + return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, dl, VT, + InOp.getOperand(0), NewSA)); + } + } + + // Compute the new bits that are at the top now. + if (SimplifyDemandedBits(InOp, (NewMask << ShAmt), + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); + KnownZero |= HighBits; // High bits known zero. + } + break; + case ISD::SRA: + // If this is an arithmetic shift right and only the low-bit is set, we can + // always convert this into a logical shr, even if the shift amount is + // variable. The low bit of the shift cannot be an input sign bit unless + // the shift amount is >= the size of the datatype, which is undefined. + if (DemandedMask == 1) + return TLO.CombineTo(Op, + TLO.DAG.getNode(ISD::SRL, dl, Op.getValueType(), + Op.getOperand(0), Op.getOperand(1))); + + if (ConstantSDNode *SA = dyn_cast(Op.getOperand(1))) { + EVT VT = Op.getValueType(); + unsigned ShAmt = SA->getZExtValue(); + + // If the shift count is an invalid immediate, don't do anything. + if (ShAmt >= BitWidth) + break; + + APInt InDemandedMask = (NewMask << ShAmt); + + // If any of the demanded bits are produced by the sign extension, we also + // demand the input sign bit. + APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); + if (HighBits.intersects(NewMask)) + InDemandedMask |= APInt::getSignBit(VT.getScalarType().getSizeInBits()); + + if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.lshr(ShAmt); + KnownOne = KnownOne.lshr(ShAmt); + + // Handle the sign bit, adjusted to where it is now in the mask. + APInt SignBit = APInt::getSignBit(BitWidth).lshr(ShAmt); + + // If the input sign bit is known to be zero, or if none of the top bits + // are demanded, turn this into an unsigned shift right. + if (KnownZero.intersects(SignBit) || (HighBits & ~NewMask) == HighBits) { + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, VT, + Op.getOperand(0), + Op.getOperand(1))); + } else if (KnownOne.intersects(SignBit)) { // New bits are known one. + KnownOne |= HighBits; + } + } + break; + case ISD::SIGN_EXTEND_INREG: { + EVT EVT = cast(Op.getOperand(1))->getVT(); + + // Sign extension. Compute the demanded bits in the result that are not + // present in the input. + APInt NewBits = + APInt::getHighBitsSet(BitWidth, + BitWidth - EVT.getScalarType().getSizeInBits()); + + // If none of the extended bits are demanded, eliminate the sextinreg. + if ((NewBits & NewMask) == 0) + return TLO.CombineTo(Op, Op.getOperand(0)); + + APInt InSignBit = + APInt::getSignBit(EVT.getScalarType().getSizeInBits()).zext(BitWidth); + APInt InputDemandedBits = + APInt::getLowBitsSet(BitWidth, + EVT.getScalarType().getSizeInBits()) & + NewMask; + + // Since the sign extended bits are demanded, we know that the sign + // bit is demanded. + InputDemandedBits |= InSignBit; + + if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + + // If the sign bit of the input is known set or clear, then we know the + // top bits of the result. + + // If the input sign bit is known zero, convert this into a zero extension. + if (KnownZero.intersects(InSignBit)) + return TLO.CombineTo(Op, + TLO.DAG.getZeroExtendInReg(Op.getOperand(0),dl,EVT)); + + if (KnownOne.intersects(InSignBit)) { // Input sign bit known set + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Input sign bit unknown + KnownZero &= ~NewBits; + KnownOne &= ~NewBits; + } + break; + } + case ISD::ZERO_EXTEND: { + unsigned OperandBitWidth = + Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); + APInt InMask = NewMask.trunc(OperandBitWidth); + + // If none of the top bits are demanded, convert this into an any_extend. + APInt NewBits = + APInt::getHighBitsSet(BitWidth, BitWidth - OperandBitWidth) & NewMask; + if (!NewBits.intersects(NewMask)) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ANY_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + if (SimplifyDemandedBits(Op.getOperand(0), InMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + KnownZero |= NewBits; + break; + } + case ISD::SIGN_EXTEND: { + EVT InVT = Op.getOperand(0).getValueType(); + unsigned InBits = InVT.getScalarType().getSizeInBits(); + APInt InMask = APInt::getLowBitsSet(BitWidth, InBits); + APInt InSignBit = APInt::getBitsSet(BitWidth, InBits - 1, InBits); + APInt NewBits = ~InMask & NewMask; + + // If none of the top bits are demanded, convert this into an any_extend. + if (NewBits == 0) + return TLO.CombineTo(Op,TLO.DAG.getNode(ISD::ANY_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + // Since some of the sign extended bits are demanded, we know that the sign + // bit is demanded. + APInt InDemandedBits = InMask & NewMask; + InDemandedBits |= InSignBit; + InDemandedBits = InDemandedBits.trunc(InBits); + + if (SimplifyDemandedBits(Op.getOperand(0), InDemandedBits, KnownZero, + KnownOne, TLO, Depth+1)) + return true; + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + + // If the sign bit is known zero, convert this to a zero extend. + if (KnownZero.intersects(InSignBit)) + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::ZERO_EXTEND, dl, + Op.getValueType(), + Op.getOperand(0))); + + // If the sign bit is known one, the top bits match. + if (KnownOne.intersects(InSignBit)) { + KnownOne |= NewBits; + KnownZero &= ~NewBits; + } else { // Otherwise, top bits aren't known. + KnownOne &= ~NewBits; + KnownZero &= ~NewBits; + } + break; + } + case ISD::ANY_EXTEND: { + unsigned OperandBitWidth = + Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); + APInt InMask = NewMask.trunc(OperandBitWidth); + if (SimplifyDemandedBits(Op.getOperand(0), InMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + KnownZero = KnownZero.zext(BitWidth); + KnownOne = KnownOne.zext(BitWidth); + break; + } + case ISD::TRUNCATE: { + // Simplify the input, using demanded bit information, and compute the known + // zero/one bits live out. + unsigned OperandBitWidth = + Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); + APInt TruncMask = NewMask.zext(OperandBitWidth); + if (SimplifyDemandedBits(Op.getOperand(0), TruncMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + KnownZero = KnownZero.trunc(BitWidth); + KnownOne = KnownOne.trunc(BitWidth); + + // If the input is only used by this truncate, see if we can shrink it based + // on the known demanded bits. + if (Op.getOperand(0).getNode()->hasOneUse()) { + SDValue In = Op.getOperand(0); + switch (In.getOpcode()) { + default: break; + case ISD::SRL: + // Shrink SRL by a constant if none of the high bits shifted in are + // demanded. + if (TLO.LegalTypes() && + !isTypeDesirableForOp(ISD::SRL, Op.getValueType())) + // Do not turn (vt1 truncate (vt2 srl)) into (vt1 srl) if vt1 is + // undesirable. + break; + ConstantSDNode *ShAmt = dyn_cast(In.getOperand(1)); + if (!ShAmt) + break; + APInt HighBits = APInt::getHighBitsSet(OperandBitWidth, + OperandBitWidth - BitWidth); + HighBits = HighBits.lshr(ShAmt->getZExtValue()).trunc(BitWidth); + + if (ShAmt->getZExtValue() < BitWidth && !(HighBits & NewMask)) { + // None of the shifted in bits are needed. Add a truncate of the + // shift input, then shift it. + SDValue NewTrunc = TLO.DAG.getNode(ISD::TRUNCATE, dl, + Op.getValueType(), + In.getOperand(0)); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, + Op.getValueType(), + NewTrunc, + In.getOperand(1))); + } + break; + } + } + + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + break; + } + case ISD::AssertZext: { + // Demand all the bits of the input that are demanded in the output. + // The low bits are obvious; the high bits are demanded because we're + // asserting that they're zero here. + if (SimplifyDemandedBits(Op.getOperand(0), NewMask, + KnownZero, KnownOne, TLO, Depth+1)) + return true; + assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?"); + + EVT VT = cast(Op.getOperand(1))->getVT(); + APInt InMask = APInt::getLowBitsSet(BitWidth, + VT.getSizeInBits()); + KnownZero |= ~InMask & NewMask; + break; + } + case ISD::BITCAST: +#if 0 + // If this is an FP->Int bitcast and if the sign bit is the only thing that + // is demanded, turn this into a FGETSIGN. + if (NewMask == EVT::getIntegerVTSignBit(Op.getValueType()) && + MVT::isFloatingPoint(Op.getOperand(0).getValueType()) && + !MVT::isVector(Op.getOperand(0).getValueType())) { + // Only do this xform if FGETSIGN is valid or if before legalize. + if (!TLO.AfterLegalize || + isOperationLegal(ISD::FGETSIGN, Op.getValueType())) { + // Make a FGETSIGN + SHL to move the sign bit into the appropriate + // place. We expect the SHL to be eliminated by other optimizations. + SDValue Sign = TLO.DAG.getNode(ISD::FGETSIGN, Op.getValueType(), + Op.getOperand(0)); + unsigned ShVal = Op.getValueType().getSizeInBits()-1; + SDValue ShAmt = TLO.DAG.getConstant(ShVal, getShiftAmountTy()); + return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SHL, Op.getValueType(), + Sign, ShAmt)); + } + } +#endif + break; + case ISD::ADD: + case ISD::MUL: + case ISD::SUB: { + // Add, Sub, and Mul don't demand any bits in positions beyond that + // of the highest bit demanded of them. + APInt LoMask = APInt::getLowBitsSet(BitWidth, + BitWidth - NewMask.countLeadingZeros()); + if (SimplifyDemandedBits(Op.getOperand(0), LoMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + if (SimplifyDemandedBits(Op.getOperand(1), LoMask, KnownZero2, + KnownOne2, TLO, Depth+1)) + return true; + // See if the operation should be performed at a smaller bit width. + if (TLO.ShrinkDemandedOp(Op, BitWidth, NewMask, dl)) + return true; + } + // FALL THROUGH + default: + // Just use ComputeMaskedBits to compute output bits. + TLO.DAG.ComputeMaskedBits(Op, NewMask, KnownZero, KnownOne, Depth); + break; + } + + // If we know the value of all of the demanded bits, return this as a + // constant. + if ((NewMask & (KnownZero|KnownOne)) == NewMask) + return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType())); + + return false; +} + +/// computeMaskedBitsForTargetNode - Determine which of the bits specified +/// in Mask are known to be either zero or one and return them in the +/// KnownZero/KnownOne bitsets. +void TargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + assert((Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) && + "Should use MaskedValueIsZero if you don't know whether Op" + " is a target node!"); + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); +} + +/// ComputeNumSignBitsForTargetNode - This method can be implemented by +/// targets that want to expose additional information about sign bits to the +/// DAG Combiner. +unsigned TargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op, + unsigned Depth) const { + assert((Op.getOpcode() >= ISD::BUILTIN_OP_END || + Op.getOpcode() == ISD::INTRINSIC_WO_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_W_CHAIN || + Op.getOpcode() == ISD::INTRINSIC_VOID) && + "Should use ComputeNumSignBits if you don't know whether Op" + " is a target node!"); + return 1; +} + +/// ValueHasExactlyOneBitSet - Test if the given value is known to have exactly +/// one bit set. This differs from ComputeMaskedBits in that it doesn't need to +/// determine which bit is set. +/// +static bool ValueHasExactlyOneBitSet(SDValue Val, const SelectionDAG &DAG) { + // A left-shift of a constant one will have exactly one bit set, because + // shifting the bit off the end is undefined. + if (Val.getOpcode() == ISD::SHL) + if (ConstantSDNode *C = + dyn_cast(Val.getNode()->getOperand(0))) + if (C->getAPIntValue() == 1) + return true; + + // Similarly, a right-shift of a constant sign-bit will have exactly + // one bit set. + if (Val.getOpcode() == ISD::SRL) + if (ConstantSDNode *C = + dyn_cast(Val.getNode()->getOperand(0))) + if (C->getAPIntValue().isSignBit()) + return true; + + // More could be done here, though the above checks are enough + // to handle some common cases. + + // Fall back to ComputeMaskedBits to catch other known cases. + EVT OpVT = Val.getValueType(); + unsigned BitWidth = OpVT.getScalarType().getSizeInBits(); + APInt Mask = APInt::getAllOnesValue(BitWidth); + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(Val, Mask, KnownZero, KnownOne); + return (KnownZero.countPopulation() == BitWidth - 1) && + (KnownOne.countPopulation() == 1); +} + +/// SimplifySetCC - Try to simplify a setcc built with the specified operands +/// and cc. If it is unable to simplify it, return a null SDValue. +SDValue +TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI, DebugLoc dl) const { + SelectionDAG &DAG = DCI.DAG; + LLVMContext &Context = *DAG.getContext(); + + // These setcc operations always fold. + switch (Cond) { + default: break; + case ISD::SETFALSE: + case ISD::SETFALSE2: return DAG.getConstant(0, VT); + case ISD::SETTRUE: + case ISD::SETTRUE2: return DAG.getConstant(1, VT); + } + + if (isa(N0.getNode())) { + // Ensure that the constant occurs on the RHS, and fold constant + // comparisons. + return DAG.getSetCC(dl, VT, N1, N0, ISD::getSetCCSwappedOperands(Cond)); + } + + if (ConstantSDNode *N1C = dyn_cast(N1.getNode())) { + const APInt &C1 = N1C->getAPIntValue(); + + // If the LHS is '(srl (ctlz x), 5)', the RHS is 0/1, and this is an + // equality comparison, then we're just comparing whether X itself is + // zero. + if (N0.getOpcode() == ISD::SRL && (C1 == 0 || C1 == 1) && + N0.getOperand(0).getOpcode() == ISD::CTLZ && + N0.getOperand(1).getOpcode() == ISD::Constant) { + const APInt &ShAmt + = cast(N0.getOperand(1))->getAPIntValue(); + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + ShAmt == Log2_32(N0.getValueType().getSizeInBits())) { + if ((C1 == 0) == (Cond == ISD::SETEQ)) { + // (srl (ctlz x), 5) == 0 -> X != 0 + // (srl (ctlz x), 5) != 1 -> X != 0 + Cond = ISD::SETNE; + } else { + // (srl (ctlz x), 5) != 0 -> X == 0 + // (srl (ctlz x), 5) == 1 -> X == 0 + Cond = ISD::SETEQ; + } + SDValue Zero = DAG.getConstant(0, N0.getValueType()); + return DAG.getSetCC(dl, VT, N0.getOperand(0).getOperand(0), + Zero, Cond); + } + } + + SDValue CTPOP = N0; + // Look through truncs that don't change the value of a ctpop. + if (N0.hasOneUse() && N0.getOpcode() == ISD::TRUNCATE) + CTPOP = N0.getOperand(0); + + if (CTPOP.hasOneUse() && CTPOP.getOpcode() == ISD::CTPOP && + (N0 == CTPOP || N0.getValueType().getSizeInBits() > + Log2_32_Ceil(CTPOP.getValueType().getSizeInBits()))) { + EVT CTVT = CTPOP.getValueType(); + SDValue CTOp = CTPOP.getOperand(0); + + // (ctpop x) u< 2 -> (x & x-1) == 0 + // (ctpop x) u> 1 -> (x & x-1) != 0 + if ((Cond == ISD::SETULT && C1 == 2) || (Cond == ISD::SETUGT && C1 == 1)){ + SDValue Sub = DAG.getNode(ISD::SUB, dl, CTVT, CTOp, + DAG.getConstant(1, CTVT)); + SDValue And = DAG.getNode(ISD::AND, dl, CTVT, CTOp, Sub); + ISD::CondCode CC = Cond == ISD::SETULT ? ISD::SETEQ : ISD::SETNE; + return DAG.getSetCC(dl, VT, And, DAG.getConstant(0, CTVT), CC); + } + + // TODO: (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal. + } + + // If the LHS is '(and load, const)', the RHS is 0, + // the test is for equality or unsigned, and all 1 bits of the const are + // in the same partial word, see if we can shorten the load. + if (DCI.isBeforeLegalize() && + N0.getOpcode() == ISD::AND && C1 == 0 && + N0.getNode()->hasOneUse() && + isa(N0.getOperand(0)) && + N0.getOperand(0).getNode()->hasOneUse() && + isa(N0.getOperand(1))) { + LoadSDNode *Lod = cast(N0.getOperand(0)); + APInt bestMask; + unsigned bestWidth = 0, bestOffset = 0; + if (!Lod->isVolatile() && Lod->isUnindexed()) { + unsigned origWidth = N0.getValueType().getSizeInBits(); + unsigned maskWidth = origWidth; + // We can narrow (e.g.) 16-bit extending loads on 32-bit target to + // 8 bits, but have to be careful... + if (Lod->getExtensionType() != ISD::NON_EXTLOAD) + origWidth = Lod->getMemoryVT().getSizeInBits(); + const APInt &Mask = + cast(N0.getOperand(1))->getAPIntValue(); + for (unsigned width = origWidth / 2; width>=8; width /= 2) { + APInt newMask = APInt::getLowBitsSet(maskWidth, width); + for (unsigned offset=0; offsetisLittleEndian()) + bestOffset = (origWidth/width - offset - 1) * (width/8); + else + bestOffset = (uint64_t)offset * (width/8); + bestMask = Mask.lshr(offset * (width/8) * 8); + bestWidth = width; + break; + } + newMask = newMask << width; + } + } + } + if (bestWidth) { + EVT newVT = EVT::getIntegerVT(Context, bestWidth); + if (newVT.isRound()) { + EVT PtrType = Lod->getOperand(1).getValueType(); + SDValue Ptr = Lod->getBasePtr(); + if (bestOffset != 0) + Ptr = DAG.getNode(ISD::ADD, dl, PtrType, Lod->getBasePtr(), + DAG.getConstant(bestOffset, PtrType)); + unsigned NewAlign = MinAlign(Lod->getAlignment(), bestOffset); + SDValue NewLoad = DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, + Lod->getPointerInfo().getWithOffset(bestOffset), + false, false, NewAlign); + return DAG.getSetCC(dl, VT, + DAG.getNode(ISD::AND, dl, newVT, NewLoad, + DAG.getConstant(bestMask.trunc(bestWidth), + newVT)), + DAG.getConstant(0LL, newVT), Cond); + } + } + } + + // If the LHS is a ZERO_EXTEND, perform the comparison on the input. + if (N0.getOpcode() == ISD::ZERO_EXTEND) { + unsigned InSize = N0.getOperand(0).getValueType().getSizeInBits(); + + // If the comparison constant has bits in the upper part, the + // zero-extended value could never match. + if (C1.intersects(APInt::getHighBitsSet(C1.getBitWidth(), + C1.getBitWidth() - InSize))) { + switch (Cond) { + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETEQ: return DAG.getConstant(0, VT); + case ISD::SETULT: + case ISD::SETULE: + case ISD::SETNE: return DAG.getConstant(1, VT); + case ISD::SETGT: + case ISD::SETGE: + // True if the sign bit of C1 is set. + return DAG.getConstant(C1.isNegative(), VT); + case ISD::SETLT: + case ISD::SETLE: + // True if the sign bit of C1 isn't set. + return DAG.getConstant(C1.isNonNegative(), VT); + default: + break; + } + } + + // Otherwise, we can perform the comparison with the low bits. + switch (Cond) { + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGT: + case ISD::SETUGE: + case ISD::SETULT: + case ISD::SETULE: { + EVT newVT = N0.getOperand(0).getValueType(); + if (DCI.isBeforeLegalizeOps() || + (isOperationLegal(ISD::SETCC, newVT) && + getCondCodeAction(Cond, newVT)==Legal)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(C1.trunc(InSize), newVT), + Cond); + break; + } + default: + break; // todo, be more careful with signed comparisons + } + } else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + EVT ExtSrcTy = cast(N0.getOperand(1))->getVT(); + unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits(); + EVT ExtDstTy = N0.getValueType(); + unsigned ExtDstTyBits = ExtDstTy.getSizeInBits(); + + // If the constant doesn't fit into the number of bits for the source of + // the sign extension, it is impossible for both sides to be equal. + if (C1.getMinSignedBits() > ExtSrcTyBits) + return DAG.getConstant(Cond == ISD::SETNE, VT); + + SDValue ZextOp; + EVT Op0Ty = N0.getOperand(0).getValueType(); + if (Op0Ty == ExtSrcTy) { + ZextOp = N0.getOperand(0); + } else { + APInt Imm = APInt::getLowBitsSet(ExtDstTyBits, ExtSrcTyBits); + ZextOp = DAG.getNode(ISD::AND, dl, Op0Ty, N0.getOperand(0), + DAG.getConstant(Imm, Op0Ty)); + } + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(ZextOp.getNode()); + // Otherwise, make this a use of a zext. + return DAG.getSetCC(dl, VT, ZextOp, + DAG.getConstant(C1 & APInt::getLowBitsSet( + ExtDstTyBits, + ExtSrcTyBits), + ExtDstTy), + Cond); + } else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) && + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + // SETCC (SETCC), [0|1], [EQ|NE] -> SETCC + if (N0.getOpcode() == ISD::SETCC && + isTypeLegal(VT) && VT.bitsLE(N0.getValueType())) { + bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1); + if (TrueWhenTrue) + return DAG.getNode(ISD::TRUNCATE, dl, VT, N0); + // Invert the condition. + ISD::CondCode CC = cast(N0.getOperand(2))->get(); + CC = ISD::getSetCCInverse(CC, + N0.getOperand(0).getValueType().isInteger()); + return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC); + } + + if ((N0.getOpcode() == ISD::XOR || + (N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::XOR && + N0.getOperand(1) == N0.getOperand(0).getOperand(1))) && + isa(N0.getOperand(1)) && + cast(N0.getOperand(1))->getAPIntValue() == 1) { + // If this is (X^1) == 0/1, swap the RHS and eliminate the xor. We + // can only do this if the top bits are known zero. + unsigned BitWidth = N0.getValueSizeInBits(); + if (DAG.MaskedValueIsZero(N0, + APInt::getHighBitsSet(BitWidth, + BitWidth-1))) { + // Okay, get the un-inverted input value. + SDValue Val; + if (N0.getOpcode() == ISD::XOR) + Val = N0.getOperand(0); + else { + assert(N0.getOpcode() == ISD::AND && + N0.getOperand(0).getOpcode() == ISD::XOR); + // ((X^1)&1)^1 -> X & 1 + Val = DAG.getNode(ISD::AND, dl, N0.getValueType(), + N0.getOperand(0).getOperand(0), + N0.getOperand(1)); + } + + return DAG.getSetCC(dl, VT, Val, N1, + Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ); + } + } else if (N1C->getAPIntValue() == 1 && + (VT == MVT::i1 || + getBooleanContents() == ZeroOrOneBooleanContent)) { + SDValue Op0 = N0; + if (Op0.getOpcode() == ISD::TRUNCATE) + Op0 = Op0.getOperand(0); + + if ((Op0.getOpcode() == ISD::XOR) && + Op0.getOperand(0).getOpcode() == ISD::SETCC && + Op0.getOperand(1).getOpcode() == ISD::SETCC) { + // (xor (setcc), (setcc)) == / != 1 -> (setcc) != / == (setcc) + Cond = (Cond == ISD::SETEQ) ? ISD::SETNE : ISD::SETEQ; + return DAG.getSetCC(dl, VT, Op0.getOperand(0), Op0.getOperand(1), + Cond); + } else if (Op0.getOpcode() == ISD::AND && + isa(Op0.getOperand(1)) && + cast(Op0.getOperand(1))->getAPIntValue() == 1) { + // If this is (X&1) == / != 1, normalize it to (X&1) != / == 0. + if (Op0.getValueType().bitsGT(VT)) + Op0 = DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::TRUNCATE, dl, VT, Op0.getOperand(0)), + DAG.getConstant(1, VT)); + else if (Op0.getValueType().bitsLT(VT)) + Op0 = DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::ANY_EXTEND, dl, VT, Op0.getOperand(0)), + DAG.getConstant(1, VT)); + + return DAG.getSetCC(dl, VT, Op0, + DAG.getConstant(0, Op0.getValueType()), + Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ); + } + } + } + + APInt MinVal, MaxVal; + unsigned OperandBitSize = N1C->getValueType(0).getSizeInBits(); + if (ISD::isSignedIntSetCC(Cond)) { + MinVal = APInt::getSignedMinValue(OperandBitSize); + MaxVal = APInt::getSignedMaxValue(OperandBitSize); + } else { + MinVal = APInt::getMinValue(OperandBitSize); + MaxVal = APInt::getMaxValue(OperandBitSize); + } + + // Canonicalize GE/LE comparisons to use GT/LT comparisons. + if (Cond == ISD::SETGE || Cond == ISD::SETUGE) { + if (C1 == MinVal) return DAG.getConstant(1, VT); // X >= MIN --> true + // X >= C0 --> X > (C0-1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(C1-1, N1.getValueType()), + (Cond == ISD::SETGE) ? ISD::SETGT : ISD::SETUGT); + } + + if (Cond == ISD::SETLE || Cond == ISD::SETULE) { + if (C1 == MaxVal) return DAG.getConstant(1, VT); // X <= MAX --> true + // X <= C0 --> X < (C0+1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(C1+1, N1.getValueType()), + (Cond == ISD::SETLE) ? ISD::SETLT : ISD::SETULT); + } + + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal) + return DAG.getConstant(0, VT); // X < MIN --> false + if ((Cond == ISD::SETGE || Cond == ISD::SETUGE) && C1 == MinVal) + return DAG.getConstant(1, VT); // X >= MIN --> true + if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal) + return DAG.getConstant(0, VT); // X > MAX --> false + if ((Cond == ISD::SETLE || Cond == ISD::SETULE) && C1 == MaxVal) + return DAG.getConstant(1, VT); // X <= MAX --> true + + // Canonicalize setgt X, Min --> setne X, Min + if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MinVal) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETNE); + // Canonicalize setlt X, Max --> setne X, Max + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MaxVal) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETNE); + + // If we have setult X, 1, turn it into seteq X, 0 + if ((Cond == ISD::SETLT || Cond == ISD::SETULT) && C1 == MinVal+1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(MinVal, N0.getValueType()), + ISD::SETEQ); + // If we have setugt X, Max-1, turn it into seteq X, Max + else if ((Cond == ISD::SETGT || Cond == ISD::SETUGT) && C1 == MaxVal-1) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(MaxVal, N0.getValueType()), + ISD::SETEQ); + + // If we have "setcc X, C0", check to see if we can shrink the immediate + // by changing cc. + + // SETUGT X, SINTMAX -> SETLT X, 0 + if (Cond == ISD::SETUGT && + C1 == APInt::getSignedMaxValue(OperandBitSize)) + return DAG.getSetCC(dl, VT, N0, + DAG.getConstant(0, N1.getValueType()), + ISD::SETLT); + + // SETULT X, SINTMIN -> SETGT X, -1 + if (Cond == ISD::SETULT && + C1 == APInt::getSignedMinValue(OperandBitSize)) { + SDValue ConstMinusOne = + DAG.getConstant(APInt::getAllOnesValue(OperandBitSize), + N1.getValueType()); + return DAG.getSetCC(dl, VT, N0, ConstMinusOne, ISD::SETGT); + } + + // Fold bit comparisons when we can. + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + (VT == N0.getValueType() || + (isTypeLegal(VT) && VT.bitsLE(N0.getValueType()))) && + N0.getOpcode() == ISD::AND) + if (ConstantSDNode *AndRHS = + dyn_cast(N0.getOperand(1))) { + EVT ShiftTy = DCI.isBeforeLegalize() ? + getPointerTy() : getShiftAmountTy(N0.getValueType()); + if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 + // Perform the xform if the AND RHS is a single bit. + if (AndRHS->getAPIntValue().isPowerOf2()) { + return DAG.getNode(ISD::TRUNCATE, dl, VT, + DAG.getNode(ISD::SRL, dl, N0.getValueType(), N0, + DAG.getConstant(AndRHS->getAPIntValue().logBase2(), ShiftTy))); + } + } else if (Cond == ISD::SETEQ && C1 == AndRHS->getAPIntValue()) { + // (X & 8) == 8 --> (X & 8) >> 3 + // Perform the xform if C1 is a single bit. + if (C1.isPowerOf2()) { + return DAG.getNode(ISD::TRUNCATE, dl, VT, + DAG.getNode(ISD::SRL, dl, N0.getValueType(), N0, + DAG.getConstant(C1.logBase2(), ShiftTy))); + } + } + } + } + + if (isa(N0.getNode())) { + // Constant fold or commute setcc. + SDValue O = DAG.FoldSetCC(VT, N0, N1, Cond, dl); + if (O.getNode()) return O; + } else if (ConstantFPSDNode *CFP = dyn_cast(N1.getNode())) { + // If the RHS of an FP comparison is a constant, simplify it away in + // some cases. + if (CFP->getValueAPF().isNaN()) { + // If an operand is known to be a nan, we can fold it. + switch (ISD::getUnorderedFlavor(Cond)) { + default: llvm_unreachable("Unknown flavor!"); + case 0: // Known false. + return DAG.getConstant(0, VT); + case 1: // Known true. + return DAG.getConstant(1, VT); + case 2: // Undefined. + return DAG.getUNDEF(VT); + } + } + + // Otherwise, we know the RHS is not a NaN. Simplify the node to drop the + // constant if knowing that the operand is non-nan is enough. We prefer to + // have SETO(x,x) instead of SETO(x, 0.0) because this avoids having to + // materialize 0.0. + if (Cond == ISD::SETO || Cond == ISD::SETUO) + return DAG.getSetCC(dl, VT, N0, N0, Cond); + + // If the condition is not legal, see if we can find an equivalent one + // which is legal. + if (!isCondCodeLegal(Cond, N0.getValueType())) { + // If the comparison was an awkward floating-point == or != and one of + // the comparison operands is infinity or negative infinity, convert the + // condition to a less-awkward <= or >=. + if (CFP->getValueAPF().isInfinity()) { + if (CFP->getValueAPF().isNegative()) { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOLE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETUGT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGT); + } else { + if (Cond == ISD::SETOEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOGE); + if (Cond == ISD::SETUEQ && + isCondCodeLegal(ISD::SETOGE, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETUGE); + if (Cond == ISD::SETUNE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETULT); + if (Cond == ISD::SETONE && + isCondCodeLegal(ISD::SETULT, N0.getValueType())) + return DAG.getSetCC(dl, VT, N0, N1, ISD::SETOLT); + } + } + } + } + + if (N0 == N1) { + // We can always fold X == X for integer setcc's. + if (N0.getValueType().isInteger()) + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + unsigned UOF = ISD::getUnorderedFlavor(Cond); + if (UOF == 2) // FP operators that are undefined on NaNs. + return DAG.getConstant(ISD::isTrueWhenEqual(Cond), VT); + if (UOF == unsigned(ISD::isTrueWhenEqual(Cond))) + return DAG.getConstant(UOF, VT); + // Otherwise, we can't fold it. However, we can simplify it to SETUO/SETO + // if it is not already. + ISD::CondCode NewCond = UOF == 0 ? ISD::SETO : ISD::SETUO; + if (NewCond != Cond) + return DAG.getSetCC(dl, VT, N0, N1, NewCond); + } + + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + N0.getValueType().isInteger()) { + if (N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::SUB || + N0.getOpcode() == ISD::XOR) { + // Simplify (X+Y) == (X+Z) --> Y == Z + if (N0.getOpcode() == N1.getOpcode()) { + if (N0.getOperand(0) == N1.getOperand(0)) + return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(1), Cond); + if (N0.getOperand(1) == N1.getOperand(1)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(0), Cond); + if (DAG.isCommutativeBinOp(N0.getOpcode())) { + // If X op Y == Y op X, try other combinations. + if (N0.getOperand(0) == N1.getOperand(1)) + return DAG.getSetCC(dl, VT, N0.getOperand(1), N1.getOperand(0), + Cond); + if (N0.getOperand(1) == N1.getOperand(0)) + return DAG.getSetCC(dl, VT, N0.getOperand(0), N1.getOperand(1), + Cond); + } + } + + if (ConstantSDNode *RHSC = dyn_cast(N1)) { + if (ConstantSDNode *LHSR = dyn_cast(N0.getOperand(1))) { + // Turn (X+C1) == C2 --> X == C2-C1 + if (N0.getOpcode() == ISD::ADD && N0.getNode()->hasOneUse()) { + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(RHSC->getAPIntValue()- + LHSR->getAPIntValue(), + N0.getValueType()), Cond); + } + + // Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0. + if (N0.getOpcode() == ISD::XOR) + // If we know that all of the inverted bits are zero, don't bother + // performing the inversion. + if (DAG.MaskedValueIsZero(N0.getOperand(0), ~LHSR->getAPIntValue())) + return + DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(LHSR->getAPIntValue() ^ + RHSC->getAPIntValue(), + N0.getValueType()), + Cond); + } + + // Turn (C1-X) == C2 --> X == C1-C2 + if (ConstantSDNode *SUBC = dyn_cast(N0.getOperand(0))) { + if (N0.getOpcode() == ISD::SUB && N0.getNode()->hasOneUse()) { + return + DAG.getSetCC(dl, VT, N0.getOperand(1), + DAG.getConstant(SUBC->getAPIntValue() - + RHSC->getAPIntValue(), + N0.getValueType()), + Cond); + } + } + } + + // Simplify (X+Z) == X --> Z == 0 + if (N0.getOperand(0) == N1) + return DAG.getSetCC(dl, VT, N0.getOperand(1), + DAG.getConstant(0, N0.getValueType()), Cond); + if (N0.getOperand(1) == N1) { + if (DAG.isCommutativeBinOp(N0.getOpcode())) + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(0, N0.getValueType()), Cond); + else if (N0.getNode()->hasOneUse()) { + assert(N0.getOpcode() == ISD::SUB && "Unexpected operation!"); + // (Z-X) == X --> Z == X<<1 + SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), + N1, + DAG.getConstant(1, getShiftAmountTy(N1.getValueType()))); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(SH.getNode()); + return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond); + } + } + } + + if (N1.getOpcode() == ISD::ADD || N1.getOpcode() == ISD::SUB || + N1.getOpcode() == ISD::XOR) { + // Simplify X == (X+Z) --> Z == 0 + if (N1.getOperand(0) == N0) { + return DAG.getSetCC(dl, VT, N1.getOperand(1), + DAG.getConstant(0, N1.getValueType()), Cond); + } else if (N1.getOperand(1) == N0) { + if (DAG.isCommutativeBinOp(N1.getOpcode())) { + return DAG.getSetCC(dl, VT, N1.getOperand(0), + DAG.getConstant(0, N1.getValueType()), Cond); + } else if (N1.getNode()->hasOneUse()) { + assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!"); + // X == (Z-X) --> X<<1 == Z + SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0, + DAG.getConstant(1, getShiftAmountTy(N0.getValueType()))); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(SH.getNode()); + return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond); + } + } + } + + // Simplify x&y == y to x&y != 0 if y has exactly one bit set. + // Note that where y is variable and is known to have at most + // one bit set (for example, if it is z&1) we cannot do this; + // the expressions are not equivalent when y==0. + if (N0.getOpcode() == ISD::AND) + if (N0.getOperand(0) == N1 || N0.getOperand(1) == N1) { + if (ValueHasExactlyOneBitSet(N1, DAG)) { + Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); + SDValue Zero = DAG.getConstant(0, N1.getValueType()); + return DAG.getSetCC(dl, VT, N0, Zero, Cond); + } + } + if (N1.getOpcode() == ISD::AND) + if (N1.getOperand(0) == N0 || N1.getOperand(1) == N0) { + if (ValueHasExactlyOneBitSet(N0, DAG)) { + Cond = ISD::getSetCCInverse(Cond, /*isInteger=*/true); + SDValue Zero = DAG.getConstant(0, N0.getValueType()); + return DAG.getSetCC(dl, VT, N1, Zero, Cond); + } + } + } + + // Fold away ALL boolean setcc's. + SDValue Temp; + if (N0.getValueType() == MVT::i1 && foldBooleans) { + switch (Cond) { + default: llvm_unreachable("Unknown integer setcc!"); + case ISD::SETEQ: // X == Y -> ~(X^Y) + Temp = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1); + N0 = DAG.getNOT(dl, Temp, MVT::i1); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETNE: // X != Y --> (X^Y) + N0 = DAG.getNode(ISD::XOR, dl, MVT::i1, N0, N1); + break; + case ISD::SETGT: // X >s Y --> X == 0 & Y == 1 --> ~X & Y + case ISD::SETULT: // X X == 0 & Y == 1 --> ~X & Y + Temp = DAG.getNOT(dl, N0, MVT::i1); + N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N1, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETLT: // X X == 1 & Y == 0 --> ~Y & X + case ISD::SETUGT: // X >u Y --> X == 1 & Y == 0 --> ~Y & X + Temp = DAG.getNOT(dl, N1, MVT::i1); + N0 = DAG.getNode(ISD::AND, dl, MVT::i1, N0, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETULE: // X <=u Y --> X == 0 | Y == 1 --> ~X | Y + case ISD::SETGE: // X >=s Y --> X == 0 | Y == 1 --> ~X | Y + Temp = DAG.getNOT(dl, N0, MVT::i1); + N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N1, Temp); + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(Temp.getNode()); + break; + case ISD::SETUGE: // X >=u Y --> X == 1 | Y == 0 --> ~Y | X + case ISD::SETLE: // X <=s Y --> X == 1 | Y == 0 --> ~Y | X + Temp = DAG.getNOT(dl, N1, MVT::i1); + N0 = DAG.getNode(ISD::OR, dl, MVT::i1, N0, Temp); + break; + } + if (VT != MVT::i1) { + if (!DCI.isCalledByLegalizer()) + DCI.AddToWorklist(N0.getNode()); + // FIXME: If running after legalize, we probably can't do this. + N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0); + } + return N0; + } + + // Could not fold it. + return SDValue(); +} + +/// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the +/// node is a GlobalAddress + offset. +bool TargetLowering::isGAPlusOffset(SDNode *N, const GlobalValue *&GA, + int64_t &Offset) const { + if (isa(N)) { + GlobalAddressSDNode *GASD = cast(N); + GA = GASD->getGlobal(); + Offset += GASD->getOffset(); + return true; + } + + if (N->getOpcode() == ISD::ADD) { + SDValue N1 = N->getOperand(0); + SDValue N2 = N->getOperand(1); + if (isGAPlusOffset(N1.getNode(), GA, Offset)) { + ConstantSDNode *V = dyn_cast(N2); + if (V) { + Offset += V->getSExtValue(); + return true; + } + } else if (isGAPlusOffset(N2.getNode(), GA, Offset)) { + ConstantSDNode *V = dyn_cast(N1); + if (V) { + Offset += V->getSExtValue(); + return true; + } + } + } + + return false; +} + + +SDValue TargetLowering:: +PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { + // Default implementation: no optimization. + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// Inline Assembler Implementation Methods +//===----------------------------------------------------------------------===// + + +TargetLowering::ConstraintType +TargetLowering::getConstraintType(const std::string &Constraint) const { + // FIXME: lots more standard ones to handle. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'r': return C_RegisterClass; + case 'm': // memory + case 'o': // offsetable + case 'V': // not offsetable + return C_Memory; + case 'i': // Simple Integer or Relocatable Constant + case 'n': // Simple Integer + case 'E': // Floating Point Constant + case 'F': // Floating Point Constant + case 's': // Relocatable Constant + case 'p': // Address. + case 'X': // Allow ANY value. + case 'I': // Target registers. + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case '<': + case '>': + return C_Other; + } + } + + if (Constraint.size() > 1 && Constraint[0] == '{' && + Constraint[Constraint.size()-1] == '}') + return C_Register; + return C_Unknown; +} + +/// LowerXConstraint - try to replace an X constraint, which matches anything, +/// with another that has more specific requirements based on the type of the +/// corresponding operand. +const char *TargetLowering::LowerXConstraint(EVT ConstraintVT) const{ + if (ConstraintVT.isInteger()) + return "r"; + if (ConstraintVT.isFloatingPoint()) + return "f"; // works for many targets + return 0; +} + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void TargetLowering::LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + std::vector &Ops, + SelectionDAG &DAG) const { + switch (ConstraintLetter) { + default: break; + case 'X': // Allows any operand; labels (basic block) use this. + if (Op.getOpcode() == ISD::BasicBlock) { + Ops.push_back(Op); + return; + } + // fall through + case 'i': // Simple Integer or Relocatable Constant + case 'n': // Simple Integer + case 's': { // Relocatable Constant + // These operands are interested in values of the form (GV+C), where C may + // be folded in as an offset of GV, or it may be explicitly added. Also, it + // is possible and fine if either GV or C are missing. + ConstantSDNode *C = dyn_cast(Op); + GlobalAddressSDNode *GA = dyn_cast(Op); + + // If we have "(add GV, C)", pull out GV/C + if (Op.getOpcode() == ISD::ADD) { + C = dyn_cast(Op.getOperand(1)); + GA = dyn_cast(Op.getOperand(0)); + if (C == 0 || GA == 0) { + C = dyn_cast(Op.getOperand(0)); + GA = dyn_cast(Op.getOperand(1)); + } + if (C == 0 || GA == 0) + C = 0, GA = 0; + } + + // If we find a valid operand, map to the TargetXXX version so that the + // value itself doesn't get selected. + if (GA) { // Either &GV or &GV+C + if (ConstraintLetter != 'n') { + int64_t Offs = GA->getOffset(); + if (C) Offs += C->getZExtValue(); + Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(), + C ? C->getDebugLoc() : DebugLoc(), + Op.getValueType(), Offs)); + return; + } + } + if (C) { // just C, no GV. + // Simple constants are not allowed for 's'. + if (ConstraintLetter != 's') { + // gcc prints these as sign extended. Sign extend value to 64 bits + // now; without this it would get ZExt'd later in + // ScheduleDAGSDNodes::EmitNode, which is very generic. + Ops.push_back(DAG.getTargetConstant(C->getAPIntValue().getSExtValue(), + MVT::i64)); + return; + } + } + break; + } + } +} + +std::vector TargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + return std::vector(); +} + + +std::pair TargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint[0] != '{') + return std::make_pair(0u, static_cast(0)); + assert(*(Constraint.end()-1) == '}' && "Not a brace enclosed constraint?"); + + // Remove the braces from around the name. + StringRef RegName(Constraint.data()+1, Constraint.size()-2); + + // Figure out which register class contains this reg. + const TargetRegisterInfo *RI = TM.getRegisterInfo(); + for (TargetRegisterInfo::regclass_iterator RCI = RI->regclass_begin(), + E = RI->regclass_end(); RCI != E; ++RCI) { + const TargetRegisterClass *RC = *RCI; + + // If none of the value types for this register class are valid, we + // can't use it. For example, 64-bit reg classes on 32-bit targets. + bool isLegal = false; + for (TargetRegisterClass::vt_iterator I = RC->vt_begin(), E = RC->vt_end(); + I != E; ++I) { + if (isTypeLegal(*I)) { + isLegal = true; + break; + } + } + + if (!isLegal) continue; + + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) { + if (RegName.equals_lower(RI->getName(*I))) + return std::make_pair(*I, RC); + } + } + + return std::make_pair(0u, static_cast(0)); +} + +//===----------------------------------------------------------------------===// +// Constraint Selection. + +/// isMatchingInputConstraint - Return true of this is an input operand that is +/// a matching constraint like "4". +bool TargetLowering::AsmOperandInfo::isMatchingInputConstraint() const { + assert(!ConstraintCode.empty() && "No known constraint!"); + return isdigit(ConstraintCode[0]); +} + +/// getMatchedOperand - If this is an input matching constraint, this method +/// returns the output operand it matches. +unsigned TargetLowering::AsmOperandInfo::getMatchedOperand() const { + assert(!ConstraintCode.empty() && "No known constraint!"); + return atoi(ConstraintCode.c_str()); +} + + +/// ParseConstraints - Split up the constraint string from the inline +/// assembly value into the specific constraints and their prefixes, +/// and also tie in the associated operand values. +/// If this returns an empty vector, and if the constraint string itself +/// isn't empty, there was an error parsing. +TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints( + ImmutableCallSite CS) const { + /// ConstraintOperands - Information about all of the constraints. + AsmOperandInfoVector ConstraintOperands; + const InlineAsm *IA = cast(CS.getCalledValue()); + unsigned maCount = 0; // Largest number of multiple alternative constraints. + + // Do a prepass over the constraints, canonicalizing them, and building up the + // ConstraintOperands list. + InlineAsm::ConstraintInfoVector + ConstraintInfos = IA->ParseConstraints(); + + unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. + unsigned ResNo = 0; // ResNo - The result number of the next output. + + for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { + ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i])); + AsmOperandInfo &OpInfo = ConstraintOperands.back(); + + // Update multiple alternative constraint count. + if (OpInfo.multipleAlternatives.size() > maCount) + maCount = OpInfo.multipleAlternatives.size(); + + OpInfo.ConstraintVT = MVT::Other; + + // Compute the value type for each operand. + switch (OpInfo.Type) { + case InlineAsm::isOutput: + // Indirect outputs just consume an argument. + if (OpInfo.isIndirect) { + OpInfo.CallOperandVal = const_cast(CS.getArgument(ArgNo++)); + break; + } + + // The return value of the call is this value. As such, there is no + // corresponding argument. + assert(!CS.getType()->isVoidTy() && + "Bad inline asm!"); + if (const StructType *STy = dyn_cast(CS.getType())) { + OpInfo.ConstraintVT = getValueType(STy->getElementType(ResNo)); + } else { + assert(ResNo == 0 && "Asm only has one result!"); + OpInfo.ConstraintVT = getValueType(CS.getType()); + } + ++ResNo; + break; + case InlineAsm::isInput: + OpInfo.CallOperandVal = const_cast(CS.getArgument(ArgNo++)); + break; + case InlineAsm::isClobber: + // Nothing to do. + break; + } + + if (OpInfo.CallOperandVal) { + const llvm::Type *OpTy = OpInfo.CallOperandVal->getType(); + if (OpInfo.isIndirect) { + const llvm::PointerType *PtrTy = dyn_cast(OpTy); + if (!PtrTy) + report_fatal_error("Indirect operand for inline asm not a pointer!"); + OpTy = PtrTy->getElementType(); + } + // If OpTy is not a single value, it may be a struct/union that we + // can tile with integers. + if (!OpTy->isSingleValueType() && OpTy->isSized()) { + unsigned BitSize = TD->getTypeSizeInBits(OpTy); + switch (BitSize) { + default: break; + case 1: + case 8: + case 16: + case 32: + case 64: + case 128: + OpInfo.ConstraintVT = + EVT::getEVT(IntegerType::get(OpTy->getContext(), BitSize), true); + break; + } + } else if (dyn_cast(OpTy)) { + OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize()); + } else { + OpInfo.ConstraintVT = EVT::getEVT(OpTy, true); + } + } + } + + // If we have multiple alternative constraints, select the best alternative. + if (ConstraintInfos.size()) { + if (maCount) { + unsigned bestMAIndex = 0; + int bestWeight = -1; + // weight: -1 = invalid match, and 0 = so-so match to 5 = good match. + int weight = -1; + unsigned maIndex; + // Compute the sums of the weights for each alternative, keeping track + // of the best (highest weight) one so far. + for (maIndex = 0; maIndex < maCount; ++maIndex) { + int weightSum = 0; + for (unsigned cIndex = 0, eIndex = ConstraintOperands.size(); + cIndex != eIndex; ++cIndex) { + AsmOperandInfo& OpInfo = ConstraintOperands[cIndex]; + if (OpInfo.Type == InlineAsm::isClobber) + continue; + + // If this is an output operand with a matching input operand, + // look up the matching input. If their types mismatch, e.g. one + // is an integer, the other is floating point, or their sizes are + // different, flag it as an maCantMatch. + if (OpInfo.hasMatchingInput()) { + AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; + if (OpInfo.ConstraintVT != Input.ConstraintVT) { + if ((OpInfo.ConstraintVT.isInteger() != + Input.ConstraintVT.isInteger()) || + (OpInfo.ConstraintVT.getSizeInBits() != + Input.ConstraintVT.getSizeInBits())) { + weightSum = -1; // Can't match. + break; + } + } + } + weight = getMultipleConstraintMatchWeight(OpInfo, maIndex); + if (weight == -1) { + weightSum = -1; + break; + } + weightSum += weight; + } + // Update best. + if (weightSum > bestWeight) { + bestWeight = weightSum; + bestMAIndex = maIndex; + } + } + + // Now select chosen alternative in each constraint. + for (unsigned cIndex = 0, eIndex = ConstraintOperands.size(); + cIndex != eIndex; ++cIndex) { + AsmOperandInfo& cInfo = ConstraintOperands[cIndex]; + if (cInfo.Type == InlineAsm::isClobber) + continue; + cInfo.selectAlternative(bestMAIndex); + } + } + } + + // Check and hook up tied operands, choose constraint code to use. + for (unsigned cIndex = 0, eIndex = ConstraintOperands.size(); + cIndex != eIndex; ++cIndex) { + AsmOperandInfo& OpInfo = ConstraintOperands[cIndex]; + + // If this is an output operand with a matching input operand, look up the + // matching input. If their types mismatch, e.g. one is an integer, the + // other is floating point, or their sizes are different, flag it as an + // error. + if (OpInfo.hasMatchingInput()) { + AsmOperandInfo &Input = ConstraintOperands[OpInfo.MatchingInput]; + + if (OpInfo.ConstraintVT != Input.ConstraintVT) { + if ((OpInfo.ConstraintVT.isInteger() != + Input.ConstraintVT.isInteger()) || + (OpInfo.ConstraintVT.getSizeInBits() != + Input.ConstraintVT.getSizeInBits())) { + report_fatal_error("Unsupported asm: input constraint" + " with a matching output constraint of" + " incompatible type!"); + } + } + + } + } + + return ConstraintOperands; +} + + +/// getConstraintGenerality - Return an integer indicating how general CT +/// is. +static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { + switch (CT) { + default: llvm_unreachable("Unknown constraint type!"); + case TargetLowering::C_Other: + case TargetLowering::C_Unknown: + return 0; + case TargetLowering::C_Register: + return 1; + case TargetLowering::C_RegisterClass: + return 2; + case TargetLowering::C_Memory: + return 3; + } +} + +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight + TargetLowering::getMultipleConstraintMatchWeight( + AsmOperandInfo &info, int maIndex) const { + InlineAsm::ConstraintCodeVector *rCodes; + if (maIndex >= (int)info.multipleAlternatives.size()) + rCodes = &info.Codes; + else + rCodes = &info.multipleAlternatives[maIndex].Codes; + ConstraintWeight BestWeight = CW_Invalid; + + // Loop over the options, keeping track of the most general one. + for (unsigned i = 0, e = rCodes->size(); i != e; ++i) { + ConstraintWeight weight = + getSingleConstraintMatchWeight(info, (*rCodes)[i].c_str()); + if (weight > BestWeight) + BestWeight = weight; + } + + return BestWeight; +} + +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight + TargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + // Look at the constraint type. + switch (*constraint) { + case 'i': // immediate integer. + case 'n': // immediate integer with a known value. + if (isa(CallOperandVal)) + weight = CW_Constant; + break; + case 's': // non-explicit intregal immediate. + if (isa(CallOperandVal)) + weight = CW_Constant; + break; + case 'E': // immediate float if host format. + case 'F': // immediate float. + if (isa(CallOperandVal)) + weight = CW_Constant; + break; + case '<': // memory operand with autodecrement. + case '>': // memory operand with autoincrement. + case 'm': // memory operand. + case 'o': // offsettable memory operand + case 'V': // non-offsettable memory operand + weight = CW_Memory; + break; + case 'r': // general register. + case 'g': // general register, memory operand or immediate integer. + // note: Clang converts "g" to "imr". + if (CallOperandVal->getType()->isIntegerTy()) + weight = CW_Register; + break; + case 'X': // any operand. + default: + weight = CW_Default; + break; + } + return weight; +} + +/// ChooseConstraint - If there are multiple different constraints that we +/// could pick for this operand (e.g. "imr") try to pick the 'best' one. +/// This is somewhat tricky: constraints fall into four classes: +/// Other -> immediates and magic values +/// Register -> one specific register +/// RegisterClass -> a group of regs +/// Memory -> memory +/// Ideally, we would pick the most specific constraint possible: if we have +/// something that fits into a register, we would pick it. The problem here +/// is that if we have something that could either be in a register or in +/// memory that use of the register could cause selection of *other* +/// operands to fail: they might only succeed if we pick memory. Because of +/// this the heuristic we use is: +/// +/// 1) If there is an 'other' constraint, and if the operand is valid for +/// that constraint, use it. This makes us take advantage of 'i' +/// constraints when available. +/// 2) Otherwise, pick the most general constraint present. This prefers +/// 'm' over 'r', for example. +/// +static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, + const TargetLowering &TLI, + SDValue Op, SelectionDAG *DAG) { + assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options"); + unsigned BestIdx = 0; + TargetLowering::ConstraintType BestType = TargetLowering::C_Unknown; + int BestGenerality = -1; + + // Loop over the options, keeping track of the most general one. + for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) { + TargetLowering::ConstraintType CType = + TLI.getConstraintType(OpInfo.Codes[i]); + + // If this is an 'other' constraint, see if the operand is valid for it. + // For example, on X86 we might have an 'rI' constraint. If the operand + // is an integer in the range [0..31] we want to use I (saving a load + // of a register), otherwise we must use 'r'. + if (CType == TargetLowering::C_Other && Op.getNode()) { + assert(OpInfo.Codes[i].size() == 1 && + "Unhandled multi-letter 'other' constraint"); + std::vector ResultOps; + TLI.LowerAsmOperandForConstraint(Op, OpInfo.Codes[i][0], + ResultOps, *DAG); + if (!ResultOps.empty()) { + BestType = CType; + BestIdx = i; + break; + } + } + + // Things with matching constraints can only be registers, per gcc + // documentation. This mainly affects "g" constraints. + if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput()) + continue; + + // This constraint letter is more general than the previous one, use it. + int Generality = getConstraintGenerality(CType); + if (Generality > BestGenerality) { + BestType = CType; + BestIdx = i; + BestGenerality = Generality; + } + } + + OpInfo.ConstraintCode = OpInfo.Codes[BestIdx]; + OpInfo.ConstraintType = BestType; +} + +/// ComputeConstraintToUse - Determines the constraint code and constraint +/// type to use for the specific AsmOperandInfo, setting +/// OpInfo.ConstraintCode and OpInfo.ConstraintType. +void TargetLowering::ComputeConstraintToUse(AsmOperandInfo &OpInfo, + SDValue Op, + SelectionDAG *DAG) const { + assert(!OpInfo.Codes.empty() && "Must have at least one constraint"); + + // Single-letter constraints ('r') are very common. + if (OpInfo.Codes.size() == 1) { + OpInfo.ConstraintCode = OpInfo.Codes[0]; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } else { + ChooseConstraint(OpInfo, *this, Op, DAG); + } + + // 'X' matches anything. + if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) { + // Labels and constants are handled elsewhere ('X' is the only thing + // that matches labels). For Functions, the type here is the type of + // the result, which is not what we want to look at; leave them alone. + Value *v = OpInfo.CallOperandVal; + if (isa(v) || isa(v) || isa(v)) { + OpInfo.CallOperandVal = v; + return; + } + + // Otherwise, try to resolve it to something we know about by looking at + // the actual operand type. + if (const char *Repl = LowerXConstraint(OpInfo.ConstraintVT)) { + OpInfo.ConstraintCode = Repl; + OpInfo.ConstraintType = getConstraintType(OpInfo.ConstraintCode); + } + } +} + +//===----------------------------------------------------------------------===// +// Loop Strength Reduction hooks +//===----------------------------------------------------------------------===// + +/// isLegalAddressingMode - Return true if the addressing mode represented +/// by AM is legal for this target, for a load/store of the specified type. +bool TargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + // The default implementation of this implements a conservative RISCy, r+r and + // r+i addr mode. + + // Allows a sign-extended 16-bit immediate field. + if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) + return false; + + // No global is ever allowed as a base. + if (AM.BaseGV) + return false; + + // Only support r+r, + switch (AM.Scale) { + case 0: // "r+i" or just "i", depending on HasBaseReg. + break; + case 1: + if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed. + return false; + // Otherwise we have r+r or r+i. + break; + case 2: + if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed. + return false; + // Allow 2*r as r+r. + break; + } + + return true; +} + +/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const { + EVT VT = N->getValueType(0); + DebugLoc dl= N->getDebugLoc(); + + // Check to see if we can do this. + // FIXME: We should be more aggressive here. + if (!isTypeLegal(VT)) + return SDValue(); + + APInt d = cast(N->getOperand(1))->getAPIntValue(); + APInt::ms magics = d.magic(); + + // Multiply the numerator (operand 0) by the magic value + // FIXME: We should support doing a MUL in a wider type + SDValue Q; + if (isOperationLegalOrCustom(ISD::MULHS, VT)) + Q = DAG.getNode(ISD::MULHS, dl, VT, N->getOperand(0), + DAG.getConstant(magics.m, VT)); + else if (isOperationLegalOrCustom(ISD::SMUL_LOHI, VT)) + Q = SDValue(DAG.getNode(ISD::SMUL_LOHI, dl, DAG.getVTList(VT, VT), + N->getOperand(0), + DAG.getConstant(magics.m, VT)).getNode(), 1); + else + return SDValue(); // No mulhs or equvialent + // If d > 0 and m < 0, add the numerator + if (d.isStrictlyPositive() && magics.m.isNegative()) { + Q = DAG.getNode(ISD::ADD, dl, VT, Q, N->getOperand(0)); + if (Created) + Created->push_back(Q.getNode()); + } + // If d < 0 and m > 0, subtract the numerator. + if (d.isNegative() && magics.m.isStrictlyPositive()) { + Q = DAG.getNode(ISD::SUB, dl, VT, Q, N->getOperand(0)); + if (Created) + Created->push_back(Q.getNode()); + } + // Shift right algebraic if shift value is nonzero + if (magics.s > 0) { + Q = DAG.getNode(ISD::SRA, dl, VT, Q, + DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType()))); + if (Created) + Created->push_back(Q.getNode()); + } + // Extract the sign bit and add it to the quotient + SDValue T = + DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1, + getShiftAmountTy(Q.getValueType()))); + if (Created) + Created->push_back(T.getNode()); + return DAG.getNode(ISD::ADD, dl, VT, Q, T); +} + +/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, + std::vector* Created) const { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // Check to see if we can do this. + // FIXME: We should be more aggressive here. + if (!isTypeLegal(VT)) + return SDValue(); + + // FIXME: We should use a narrower constant when the upper + // bits are known to be zero. + ConstantSDNode *N1C = cast(N->getOperand(1)); + APInt::mu magics = N1C->getAPIntValue().magicu(); + + // Multiply the numerator (operand 0) by the magic value + // FIXME: We should support doing a MUL in a wider type + SDValue Q; + if (isOperationLegalOrCustom(ISD::MULHU, VT)) + Q = DAG.getNode(ISD::MULHU, dl, VT, N->getOperand(0), + DAG.getConstant(magics.m, VT)); + else if (isOperationLegalOrCustom(ISD::UMUL_LOHI, VT)) + Q = SDValue(DAG.getNode(ISD::UMUL_LOHI, dl, DAG.getVTList(VT, VT), + N->getOperand(0), + DAG.getConstant(magics.m, VT)).getNode(), 1); + else + return SDValue(); // No mulhu or equvialent + if (Created) + Created->push_back(Q.getNode()); + + if (magics.a == 0) { + assert(magics.s < N1C->getAPIntValue().getBitWidth() && + "We shouldn't generate an undefined shift!"); + return DAG.getNode(ISD::SRL, dl, VT, Q, + DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType()))); + } else { + SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q); + if (Created) + Created->push_back(NPQ.getNode()); + NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ, + DAG.getConstant(1, getShiftAmountTy(NPQ.getValueType()))); + if (Created) + Created->push_back(NPQ.getNode()); + NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q); + if (Created) + Created->push_back(NPQ.getNode()); + return DAG.getNode(ISD::SRL, dl, VT, NPQ, + DAG.getConstant(magics.s-1, getShiftAmountTy(NPQ.getValueType()))); + } +} diff --git a/final/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp b/final/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp new file mode 100644 index 00000000000..a081e3cd493 --- /dev/null +++ b/final/lib/CodeGen/SelectionDAG/TargetSelectionDAGInfo.cpp @@ -0,0 +1,23 @@ +//===-- TargetSelectionDAGInfo.cpp - SelectionDAG Info --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the TargetSelectionDAGInfo class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetSelectionDAGInfo.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +TargetSelectionDAGInfo::TargetSelectionDAGInfo(const TargetMachine &TM) + : TD(TM.getTargetData()) { +} + +TargetSelectionDAGInfo::~TargetSelectionDAGInfo() { +} diff --git a/final/lib/CodeGen/ShadowStackGC.cpp b/final/lib/CodeGen/ShadowStackGC.cpp new file mode 100644 index 00000000000..6ab0cb03c06 --- /dev/null +++ b/final/lib/CodeGen/ShadowStackGC.cpp @@ -0,0 +1,451 @@ +//===-- ShadowStackGC.cpp - GC support for uncooperative targets ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements lowering for the llvm.gc* intrinsics for targets that do +// not natively support them (which includes the C backend). Note that the code +// generated is not quite as efficient as algorithms which generate stack maps +// to identify roots. +// +// This pass implements the code transformation described in this paper: +// "Accurate Garbage Collection in an Uncooperative Environment" +// Fergus Henderson, ISMM, 2002 +// +// In runtime/GC/SemiSpace.cpp is a prototype runtime which is compatible with +// ShadowStackGC. +// +// In order to support this particular transformation, all stack roots are +// coallocated in the stack. This allows a fully target-independent stack map +// while introducing only minor runtime overhead. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "shadowstackgc" +#include "llvm/CodeGen/GCs.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/GCStrategy.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/IRBuilder.h" + +using namespace llvm; + +namespace { + + class ShadowStackGC : public GCStrategy { + /// RootChain - This is the global linked-list that contains the chain of GC + /// roots. + GlobalVariable *Head; + + /// StackEntryTy - Abstract type of a link in the shadow stack. + /// + const StructType *StackEntryTy; + + /// Roots - GC roots in the current function. Each is a pair of the + /// intrinsic call and its corresponding alloca. + std::vector > Roots; + + public: + ShadowStackGC(); + + bool initializeCustomLowering(Module &M); + bool performCustomLowering(Function &F); + + private: + bool IsNullValue(Value *V); + Constant *GetFrameMap(Function &F); + const Type* GetConcreteStackEntryType(Function &F); + void CollectRoots(Function &F); + static GetElementPtrInst *CreateGEP(LLVMContext &Context, + IRBuilder<> &B, Value *BasePtr, + int Idx1, const char *Name); + static GetElementPtrInst *CreateGEP(LLVMContext &Context, + IRBuilder<> &B, Value *BasePtr, + int Idx1, int Idx2, const char *Name); + }; + +} + +static GCRegistry::Add +X("shadow-stack", "Very portable GC for uncooperative code generators"); + +namespace { + /// EscapeEnumerator - This is a little algorithm to find all escape points + /// from a function so that "finally"-style code can be inserted. In addition + /// to finding the existing return and unwind instructions, it also (if + /// necessary) transforms any call instructions into invokes and sends them to + /// a landing pad. + /// + /// It's wrapped up in a state machine using the same transform C# uses for + /// 'yield return' enumerators, This transform allows it to be non-allocating. + class EscapeEnumerator { + Function &F; + const char *CleanupBBName; + + // State. + int State; + Function::iterator StateBB, StateE; + IRBuilder<> Builder; + + public: + EscapeEnumerator(Function &F, const char *N = "cleanup") + : F(F), CleanupBBName(N), State(0), Builder(F.getContext()) {} + + IRBuilder<> *Next() { + switch (State) { + default: + return 0; + + case 0: + StateBB = F.begin(); + StateE = F.end(); + State = 1; + + case 1: + // Find all 'return' and 'unwind' instructions. + while (StateBB != StateE) { + BasicBlock *CurBB = StateBB++; + + // Branches and invokes do not escape, only unwind and return do. + TerminatorInst *TI = CurBB->getTerminator(); + if (!isa(TI) && !isa(TI)) + continue; + + Builder.SetInsertPoint(TI->getParent(), TI); + return &Builder; + } + + State = 2; + + // Find all 'call' instructions. + SmallVector Calls; + for (Function::iterator BB = F.begin(), + E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), + EE = BB->end(); II != EE; ++II) + if (CallInst *CI = dyn_cast(II)) + if (!CI->getCalledFunction() || + !CI->getCalledFunction()->getIntrinsicID()) + Calls.push_back(CI); + + if (Calls.empty()) + return 0; + + // Create a cleanup block. + BasicBlock *CleanupBB = BasicBlock::Create(F.getContext(), + CleanupBBName, &F); + UnwindInst *UI = new UnwindInst(F.getContext(), CleanupBB); + + // Transform the 'call' instructions into 'invoke's branching to the + // cleanup block. Go in reverse order to make prettier BB names. + SmallVector Args; + for (unsigned I = Calls.size(); I != 0; ) { + CallInst *CI = cast(Calls[--I]); + + // Split the basic block containing the function call. + BasicBlock *CallBB = CI->getParent(); + BasicBlock *NewBB = + CallBB->splitBasicBlock(CI, CallBB->getName() + ".cont"); + + // Remove the unconditional branch inserted at the end of CallBB. + CallBB->getInstList().pop_back(); + NewBB->getInstList().remove(CI); + + // Create a new invoke instruction. + Args.clear(); + CallSite CS(CI); + Args.append(CS.arg_begin(), CS.arg_end()); + + InvokeInst *II = InvokeInst::Create(CI->getCalledValue(), + NewBB, CleanupBB, + Args.begin(), Args.end(), + CI->getName(), CallBB); + II->setCallingConv(CI->getCallingConv()); + II->setAttributes(CI->getAttributes()); + CI->replaceAllUsesWith(II); + delete CI; + } + + Builder.SetInsertPoint(UI->getParent(), UI); + return &Builder; + } + } + }; +} + +// ----------------------------------------------------------------------------- + +void llvm::linkShadowStackGC() { } + +ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) { + InitRoots = true; + CustomRoots = true; +} + +Constant *ShadowStackGC::GetFrameMap(Function &F) { + // doInitialization creates the abstract type of this value. + const Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); + + // Truncate the ShadowStackDescriptor if some metadata is null. + unsigned NumMeta = 0; + SmallVector Metadata; + for (unsigned I = 0; I != Roots.size(); ++I) { + Constant *C = cast(Roots[I].first->getArgOperand(1)); + if (!C->isNullValue()) + NumMeta = I + 1; + Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr)); + } + + Constant *BaseElts[] = { + ConstantInt::get(Type::getInt32Ty(F.getContext()), Roots.size(), false), + ConstantInt::get(Type::getInt32Ty(F.getContext()), NumMeta, false), + }; + + Constant *DescriptorElts[] = { + ConstantStruct::get(F.getContext(), BaseElts, 2, false), + ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), + Metadata.begin(), NumMeta) + }; + + Constant *FrameMap = ConstantStruct::get(F.getContext(), DescriptorElts, 2, + false); + + std::string TypeName("gc_map."); + TypeName += utostr(NumMeta); + F.getParent()->addTypeName(TypeName, FrameMap->getType()); + + // FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems + // that, short of multithreaded LLVM, it should be safe; all that is + // necessary is that a simple Module::iterator loop not be invalidated. + // Appending to the GlobalVariable list is safe in that sense. + // + // All of the output passes emit globals last. The ExecutionEngine + // explicitly supports adding globals to the module after + // initialization. + // + // Still, if it isn't deemed acceptable, then this transformation needs + // to be a ModulePass (which means it cannot be in the 'llc' pipeline + // (which uses a FunctionPassManager (which segfaults (not asserts) if + // provided a ModulePass))). + Constant *GV = new GlobalVariable(*F.getParent(), FrameMap->getType(), true, + GlobalVariable::InternalLinkage, + FrameMap, "__gc_" + F.getName()); + + Constant *GEPIndices[2] = { + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), + ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) + }; + return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2); +} + +const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) { + // doInitialization creates the generic version of this type. + std::vector EltTys; + EltTys.push_back(StackEntryTy); + for (size_t I = 0; I != Roots.size(); I++) + EltTys.push_back(Roots[I].second->getAllocatedType()); + Type *Ty = StructType::get(F.getContext(), EltTys); + + std::string TypeName("gc_stackentry."); + TypeName += F.getName(); + F.getParent()->addTypeName(TypeName, Ty); + + return Ty; +} + +/// doInitialization - If this module uses the GC intrinsics, find them now. If +/// not, exit fast. +bool ShadowStackGC::initializeCustomLowering(Module &M) { + // struct FrameMap { + // int32_t NumRoots; // Number of roots in stack frame. + // int32_t NumMeta; // Number of metadata descriptors. May be < NumRoots. + // void *Meta[]; // May be absent for roots without metadata. + // }; + std::vector EltTys; + // 32 bits is ok up to a 32GB stack frame. :) + EltTys.push_back(Type::getInt32Ty(M.getContext())); + // Specifies length of variable length array. + EltTys.push_back(Type::getInt32Ty(M.getContext())); + StructType *FrameMapTy = StructType::get(M.getContext(), EltTys); + M.addTypeName("gc_map", FrameMapTy); + PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy); + + // struct StackEntry { + // ShadowStackEntry *Next; // Caller's stack entry. + // FrameMap *Map; // Pointer to constant FrameMap. + // void *Roots[]; // Stack roots (in-place array, so we pretend). + // }; + OpaqueType *RecursiveTy = OpaqueType::get(M.getContext()); + + EltTys.clear(); + EltTys.push_back(PointerType::getUnqual(RecursiveTy)); + EltTys.push_back(FrameMapPtrTy); + PATypeHolder LinkTyH = StructType::get(M.getContext(), EltTys); + + RecursiveTy->refineAbstractTypeTo(LinkTyH.get()); + StackEntryTy = cast(LinkTyH.get()); + const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy); + M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from + // a FunctionPass? + + // Get the root chain if it already exists. + Head = M.getGlobalVariable("llvm_gc_root_chain"); + if (!Head) { + // If the root chain does not exist, insert a new one with linkonce + // linkage! + Head = new GlobalVariable(M, StackEntryPtrTy, false, + GlobalValue::LinkOnceAnyLinkage, + Constant::getNullValue(StackEntryPtrTy), + "llvm_gc_root_chain"); + } else if (Head->hasExternalLinkage() && Head->isDeclaration()) { + Head->setInitializer(Constant::getNullValue(StackEntryPtrTy)); + Head->setLinkage(GlobalValue::LinkOnceAnyLinkage); + } + + return true; +} + +bool ShadowStackGC::IsNullValue(Value *V) { + if (Constant *C = dyn_cast(V)) + return C->isNullValue(); + return false; +} + +void ShadowStackGC::CollectRoots(Function &F) { + // FIXME: Account for original alignment. Could fragment the root array. + // Approach 1: Null initialize empty slots at runtime. Yuck. + // Approach 2: Emit a map of the array instead of just a count. + + assert(Roots.empty() && "Not cleaned up?"); + + SmallVector, 16> MetaRoots; + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) + if (IntrinsicInst *CI = dyn_cast(II++)) + if (Function *F = CI->getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::gcroot) { + std::pair Pair = std::make_pair( + CI, cast(CI->getArgOperand(0)->stripPointerCasts())); + if (IsNullValue(CI->getArgOperand(1))) + Roots.push_back(Pair); + else + MetaRoots.push_back(Pair); + } + + // Number roots with metadata (usually empty) at the beginning, so that the + // FrameMap::Meta array can be elided. + Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end()); +} + +GetElementPtrInst * +ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, + int Idx, int Idx2, const char *Name) { + Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), Idx), + ConstantInt::get(Type::getInt32Ty(Context), Idx2) }; + Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name); + + assert(isa(Val) && "Unexpected folded constant"); + + return dyn_cast(Val); +} + +GetElementPtrInst * +ShadowStackGC::CreateGEP(LLVMContext &Context, IRBuilder<> &B, Value *BasePtr, + int Idx, const char *Name) { + Value *Indices[] = { ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), Idx) }; + Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name); + + assert(isa(Val) && "Unexpected folded constant"); + + return dyn_cast(Val); +} + +/// runOnFunction - Insert code to maintain the shadow stack. +bool ShadowStackGC::performCustomLowering(Function &F) { + LLVMContext &Context = F.getContext(); + + // Find calls to llvm.gcroot. + CollectRoots(F); + + // If there are no roots in this function, then there is no need to add a + // stack map entry for it. + if (Roots.empty()) + return false; + + // Build the constant map and figure the type of the shadow stack entry. + Value *FrameMap = GetFrameMap(F); + const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F); + + // Build the shadow stack entry at the very start of the function. + BasicBlock::iterator IP = F.getEntryBlock().begin(); + IRBuilder<> AtEntry(IP->getParent(), IP); + + Instruction *StackEntry = AtEntry.CreateAlloca(ConcreteStackEntryTy, 0, + "gc_frame"); + + while (isa(IP)) ++IP; + AtEntry.SetInsertPoint(IP->getParent(), IP); + + // Initialize the map pointer and load the current head of the shadow stack. + Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead"); + Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, StackEntry, + 0,1,"gc_frame.map"); + AtEntry.CreateStore(FrameMap, EntryMapPtr); + + // After all the allocas... + for (unsigned I = 0, E = Roots.size(); I != E; ++I) { + // For each root, find the corresponding slot in the aggregate... + Value *SlotPtr = CreateGEP(Context, AtEntry, StackEntry, 1 + I, "gc_root"); + + // And use it in lieu of the alloca. + AllocaInst *OriginalAlloca = Roots[I].second; + SlotPtr->takeName(OriginalAlloca); + OriginalAlloca->replaceAllUsesWith(SlotPtr); + } + + // Move past the original stores inserted by GCStrategy::InitRoots. This isn't + // really necessary (the collector would never see the intermediate state at + // runtime), but it's nicer not to push the half-initialized entry onto the + // shadow stack. + while (isa(IP)) ++IP; + AtEntry.SetInsertPoint(IP->getParent(), IP); + + // Push the entry onto the shadow stack. + Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, + StackEntry,0,0,"gc_frame.next"); + Instruction *NewHeadVal = CreateGEP(Context, AtEntry, + StackEntry, 0, "gc_newhead"); + AtEntry.CreateStore(CurrentHead, EntryNextPtr); + AtEntry.CreateStore(NewHeadVal, Head); + + // For each instruction that escapes... + EscapeEnumerator EE(F, "gc_cleanup"); + while (IRBuilder<> *AtExit = EE.Next()) { + // Pop the entry from the shadow stack. Don't reuse CurrentHead from + // AtEntry, since that would make the value live for the entire function. + Instruction *EntryNextPtr2 = CreateGEP(Context, *AtExit, StackEntry, 0, 0, + "gc_frame.next"); + Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead"); + AtExit->CreateStore(SavedHead, Head); + } + + // Delete the original allocas (which are no longer used) and the intrinsic + // calls (which are no longer valid). Doing this last avoids invalidating + // iterators. + for (unsigned I = 0, E = Roots.size(); I != E; ++I) { + Roots[I].first->eraseFromParent(); + Roots[I].second->eraseFromParent(); + } + + Roots.clear(); + return true; +} diff --git a/final/lib/CodeGen/ShrinkWrapping.cpp b/final/lib/CodeGen/ShrinkWrapping.cpp new file mode 100644 index 00000000000..7b5bca49520 --- /dev/null +++ b/final/lib/CodeGen/ShrinkWrapping.cpp @@ -0,0 +1,1152 @@ +//===-- ShrinkWrapping.cpp - Reduce spills/restores of callee-saved regs --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a shrink wrapping variant of prolog/epilog insertion: +// - Spills and restores of callee-saved registers (CSRs) are placed in the +// machine CFG to tightly surround their uses so that execution paths that +// do not use CSRs do not pay the spill/restore penalty. +// +// - Avoiding placment of spills/restores in loops: if a CSR is used inside a +// loop the spills are placed in the loop preheader, and restores are +// placed in the loop exit nodes (the successors of loop _exiting_ nodes). +// +// - Covering paths without CSR uses: +// If a region in a CFG uses CSRs and has multiple entry and/or exit points, +// the use info for the CSRs inside the region is propagated outward in the +// CFG to ensure validity of the spill/restore placements. This decreases +// the effectiveness of shrink wrapping but does not require edge splitting +// in the machine CFG. +// +// This shrink wrapping implementation uses an iterative analysis to determine +// which basic blocks require spills and restores for CSRs. +// +// This pass uses MachineDominators and MachineLoopInfo. Loop information +// is used to prevent placement of callee-saved register spills/restores +// in the bodies of loops. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "shrink-wrap" + +#include "PrologEpilogInserter.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SparseBitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include + +using namespace llvm; + +STATISTIC(numSRReduced, "Number of CSR spills+restores reduced."); + +// Shrink Wrapping: +static cl::opt +ShrinkWrapping("shrink-wrap", + cl::desc("Shrink wrap callee-saved register spills/restores")); + +// Shrink wrap only the specified function, a debugging aid. +static cl::opt +ShrinkWrapFunc("shrink-wrap-func", cl::Hidden, + cl::desc("Shrink wrap the specified function"), + cl::value_desc("funcname"), + cl::init("")); + +// Debugging level for shrink wrapping. +enum ShrinkWrapDebugLevel { + None, BasicInfo, Iterations, Details +}; + +static cl::opt +ShrinkWrapDebugging("shrink-wrap-dbg", cl::Hidden, + cl::desc("Print shrink wrapping debugging information"), + cl::values( + clEnumVal(None , "disable debug output"), + clEnumVal(BasicInfo , "print basic DF sets"), + clEnumVal(Iterations, "print SR sets for each iteration"), + clEnumVal(Details , "print all DF sets"), + clEnumValEnd)); + + +void PEI::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + if (ShrinkWrapping || ShrinkWrapFunc != "") { + AU.addRequired(); + AU.addRequired(); + } + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +//===----------------------------------------------------------------------===// +// ShrinkWrapping implementation +//===----------------------------------------------------------------------===// + +// Convienences for dealing with machine loops. +MachineBasicBlock* PEI::getTopLevelLoopPreheader(MachineLoop* LP) { + assert(LP && "Machine loop is NULL."); + MachineBasicBlock* PHDR = LP->getLoopPreheader(); + MachineLoop* PLP = LP->getParentLoop(); + while (PLP) { + PHDR = PLP->getLoopPreheader(); + PLP = PLP->getParentLoop(); + } + return PHDR; +} + +MachineLoop* PEI::getTopLevelLoopParent(MachineLoop *LP) { + if (LP == 0) + return 0; + MachineLoop* PLP = LP->getParentLoop(); + while (PLP) { + LP = PLP; + PLP = PLP->getParentLoop(); + } + return LP; +} + +bool PEI::isReturnBlock(MachineBasicBlock* MBB) { + return (MBB && !MBB->empty() && MBB->back().getDesc().isReturn()); +} + +// Initialize shrink wrapping DFA sets, called before iterations. +void PEI::clearAnticAvailSets() { + AnticIn.clear(); + AnticOut.clear(); + AvailIn.clear(); + AvailOut.clear(); +} + +// Clear all sets constructed by shrink wrapping. +void PEI::clearAllSets() { + ReturnBlocks.clear(); + clearAnticAvailSets(); + UsedCSRegs.clear(); + CSRUsed.clear(); + TLLoops.clear(); + CSRSave.clear(); + CSRRestore.clear(); +} + +// Initialize all shrink wrapping data. +void PEI::initShrinkWrappingInfo() { + clearAllSets(); + EntryBlock = 0; +#ifndef NDEBUG + HasFastExitPath = false; +#endif + ShrinkWrapThisFunction = ShrinkWrapping; + // DEBUG: enable or disable shrink wrapping for the current function + // via --shrink-wrap-func=. +#ifndef NDEBUG + if (ShrinkWrapFunc != "") { + std::string MFName = MF->getFunction()->getNameStr(); + ShrinkWrapThisFunction = (MFName == ShrinkWrapFunc); + } +#endif +} + + +/// placeCSRSpillsAndRestores - determine which MBBs of the function +/// need save, restore code for callee-saved registers by doing a DF analysis +/// similar to the one used in code motion (GVNPRE). This produces maps of MBBs +/// to sets of registers (CSRs) for saves and restores. MachineLoopInfo +/// is used to ensure that CSR save/restore code is not placed inside loops. +/// This function computes the maps of MBBs -> CSRs to spill and restore +/// in CSRSave, CSRRestore. +/// +/// If shrink wrapping is not being performed, place all spills in +/// the entry block, all restores in return blocks. In this case, +/// CSRSave has a single mapping, CSRRestore has mappings for each +/// return block. +/// +void PEI::placeCSRSpillsAndRestores(MachineFunction &Fn) { + + DEBUG(MF = &Fn); + + initShrinkWrappingInfo(); + + DEBUG(if (ShrinkWrapThisFunction) { + dbgs() << "Place CSR spills/restores for " + << MF->getFunction()->getName() << "\n"; + }); + + if (calculateSets(Fn)) + placeSpillsAndRestores(Fn); +} + +/// calcAnticInOut - calculate the anticipated in/out reg sets +/// for the given MBB by looking forward in the MCFG at MBB's +/// successors. +/// +bool PEI::calcAnticInOut(MachineBasicBlock* MBB) { + bool changed = false; + + // AnticOut[MBB] = INTERSECT(AnticIn[S] for S in SUCCESSORS(MBB)) + SmallVector successors; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC != MBB) + successors.push_back(SUCC); + } + + unsigned i = 0, e = successors.size(); + if (i != e) { + CSRegSet prevAnticOut = AnticOut[MBB]; + MachineBasicBlock* SUCC = successors[i]; + + AnticOut[MBB] = AnticIn[SUCC]; + for (++i; i != e; ++i) { + SUCC = successors[i]; + AnticOut[MBB] &= AnticIn[SUCC]; + } + if (prevAnticOut != AnticOut[MBB]) + changed = true; + } + + // AnticIn[MBB] = UNION(CSRUsed[MBB], AnticOut[MBB]); + CSRegSet prevAnticIn = AnticIn[MBB]; + AnticIn[MBB] = CSRUsed[MBB] | AnticOut[MBB]; + if (prevAnticIn != AnticIn[MBB]) + changed = true; + return changed; +} + +/// calcAvailInOut - calculate the available in/out reg sets +/// for the given MBB by looking backward in the MCFG at MBB's +/// predecessors. +/// +bool PEI::calcAvailInOut(MachineBasicBlock* MBB) { + bool changed = false; + + // AvailIn[MBB] = INTERSECT(AvailOut[P] for P in PREDECESSORS(MBB)) + SmallVector predecessors; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED != MBB) + predecessors.push_back(PRED); + } + + unsigned i = 0, e = predecessors.size(); + if (i != e) { + CSRegSet prevAvailIn = AvailIn[MBB]; + MachineBasicBlock* PRED = predecessors[i]; + + AvailIn[MBB] = AvailOut[PRED]; + for (++i; i != e; ++i) { + PRED = predecessors[i]; + AvailIn[MBB] &= AvailOut[PRED]; + } + if (prevAvailIn != AvailIn[MBB]) + changed = true; + } + + // AvailOut[MBB] = UNION(CSRUsed[MBB], AvailIn[MBB]); + CSRegSet prevAvailOut = AvailOut[MBB]; + AvailOut[MBB] = CSRUsed[MBB] | AvailIn[MBB]; + if (prevAvailOut != AvailOut[MBB]) + changed = true; + return changed; +} + +/// calculateAnticAvail - build the sets anticipated and available +/// registers in the MCFG of the current function iteratively, +/// doing a combined forward and backward analysis. +/// +void PEI::calculateAnticAvail(MachineFunction &Fn) { + // Initialize data flow sets. + clearAnticAvailSets(); + + // Calulate Antic{In,Out} and Avail{In,Out} iteratively on the MCFG. + bool changed = true; + unsigned iterations = 0; + while (changed) { + changed = false; + ++iterations; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + + // Calculate anticipated in, out regs at MBB from + // anticipated at successors of MBB. + changed |= calcAnticInOut(MBB); + + // Calculate available in, out regs at MBB from + // available at predecessors of MBB. + changed |= calcAvailInOut(MBB); + } + } + + DEBUG({ + if (ShrinkWrapDebugging >= Details) { + dbgs() + << "-----------------------------------------------------------\n" + << " Antic/Avail Sets:\n" + << "-----------------------------------------------------------\n" + << "iterations = " << iterations << "\n" + << "-----------------------------------------------------------\n" + << "MBB | USED | ANTIC_IN | ANTIC_OUT | AVAIL_IN | AVAIL_OUT\n" + << "-----------------------------------------------------------\n"; + + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpSets(MBB); + } + + dbgs() + << "-----------------------------------------------------------\n"; + } + }); +} + +/// propagateUsesAroundLoop - copy used register info from MBB to all blocks +/// of the loop given by LP and its parent loops. This prevents spills/restores +/// from being placed in the bodies of loops. +/// +void PEI::propagateUsesAroundLoop(MachineBasicBlock* MBB, MachineLoop* LP) { + if (! MBB || !LP) + return; + + std::vector loopBlocks = LP->getBlocks(); + for (unsigned i = 0, e = loopBlocks.size(); i != e; ++i) { + MachineBasicBlock* LBB = loopBlocks[i]; + if (LBB == MBB) + continue; + if (CSRUsed[LBB].contains(CSRUsed[MBB])) + continue; + CSRUsed[LBB] |= CSRUsed[MBB]; + } +} + +/// calculateSets - collect the CSRs used in this function, compute +/// the DF sets that describe the initial minimal regions in the +/// Machine CFG around which CSR spills and restores must be placed. +/// +/// Additionally, this function decides if shrink wrapping should +/// be disabled for the current function, checking the following: +/// 1. the current function has more than 500 MBBs: heuristic limit +/// on function size to reduce compile time impact of the current +/// iterative algorithm. +/// 2. all CSRs are used in the entry block. +/// 3. all CSRs are used in all immediate successors of the entry block. +/// 4. all CSRs are used in a subset of blocks, each of which dominates +/// all return blocks. These blocks, taken as a subgraph of the MCFG, +/// are equivalent to the entry block since all execution paths pass +/// through them. +/// +bool PEI::calculateSets(MachineFunction &Fn) { + // Sets used to compute spill, restore placement sets. + const std::vector CSI = + Fn.getFrameInfo()->getCalleeSavedInfo(); + + // If no CSRs used, we are done. + if (CSI.empty()) { + DEBUG(if (ShrinkWrapThisFunction) + dbgs() << "DISABLED: " << Fn.getFunction()->getName() + << ": uses no callee-saved registers\n"); + return false; + } + + // Save refs to entry and return blocks. + EntryBlock = Fn.begin(); + for (MachineFunction::iterator MBB = Fn.begin(), E = Fn.end(); + MBB != E; ++MBB) + if (isReturnBlock(MBB)) + ReturnBlocks.push_back(MBB); + + // Determine if this function has fast exit paths. + DEBUG(if (ShrinkWrapThisFunction) + findFastExitPath()); + + // Limit shrink wrapping via the current iterative bit vector + // implementation to functions with <= 500 MBBs. + if (Fn.size() > 500) { + DEBUG(if (ShrinkWrapThisFunction) + dbgs() << "DISABLED: " << Fn.getFunction()->getName() + << ": too large (" << Fn.size() << " MBBs)\n"); + ShrinkWrapThisFunction = false; + } + + // Return now if not shrink wrapping. + if (! ShrinkWrapThisFunction) + return false; + + // Collect set of used CSRs. + for (unsigned inx = 0, e = CSI.size(); inx != e; ++inx) { + UsedCSRegs.set(inx); + } + + // Walk instructions in all MBBs, create CSRUsed[] sets, choose + // whether or not to shrink wrap this function. + MachineLoopInfo &LI = getAnalysis(); + MachineDominatorTree &DT = getAnalysis(); + const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); + + bool allCSRUsesInEntryBlock = true; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + for (MachineBasicBlock::iterator I = MBB->begin(); I != MBB->end(); ++I) { + for (unsigned inx = 0, e = CSI.size(); inx != e; ++inx) { + unsigned Reg = CSI[inx].getReg(); + // If instruction I reads or modifies Reg, add it to UsedCSRegs, + // CSRUsed map for the current block. + for (unsigned opInx = 0, opEnd = I->getNumOperands(); + opInx != opEnd; ++opInx) { + const MachineOperand &MO = I->getOperand(opInx); + if (! (MO.isReg() && (MO.isUse() || MO.isDef()))) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MOReg == Reg || + (TargetRegisterInfo::isPhysicalRegister(MOReg) && + TargetRegisterInfo::isPhysicalRegister(Reg) && + TRI->isSubRegister(Reg, MOReg))) { + // CSR Reg is defined/used in block MBB. + CSRUsed[MBB].set(inx); + // Check for uses in EntryBlock. + if (MBB != EntryBlock) + allCSRUsesInEntryBlock = false; + } + } + } + } + + if (CSRUsed[MBB].empty()) + continue; + + // Propagate CSRUsed[MBB] in loops + if (MachineLoop* LP = LI.getLoopFor(MBB)) { + // Add top level loop to work list. + MachineBasicBlock* HDR = getTopLevelLoopPreheader(LP); + MachineLoop* PLP = getTopLevelLoopParent(LP); + + if (! HDR) { + HDR = PLP->getHeader(); + assert(HDR->pred_size() > 0 && "Loop header has no predecessors?"); + MachineBasicBlock::pred_iterator PI = HDR->pred_begin(); + HDR = *PI; + } + TLLoops[HDR] = PLP; + + // Push uses from inside loop to its parent loops, + // or to all other MBBs in its loop. + if (LP->getLoopDepth() > 1) { + for (MachineLoop* PLP = LP->getParentLoop(); PLP; + PLP = PLP->getParentLoop()) { + propagateUsesAroundLoop(MBB, PLP); + } + } else { + propagateUsesAroundLoop(MBB, LP); + } + } + } + + if (allCSRUsesInEntryBlock) { + DEBUG(dbgs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in EntryBlock\n"); + ShrinkWrapThisFunction = false; + } else { + bool allCSRsUsedInEntryFanout = true; + for (MachineBasicBlock::succ_iterator SI = EntryBlock->succ_begin(), + SE = EntryBlock->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (CSRUsed[SUCC] != UsedCSRegs) + allCSRsUsedInEntryFanout = false; + } + if (allCSRsUsedInEntryFanout) { + DEBUG(dbgs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in imm successors of EntryBlock\n"); + ShrinkWrapThisFunction = false; + } + } + + if (ShrinkWrapThisFunction) { + // Check if MBB uses CSRs and dominates all exit nodes. + // Such nodes are equiv. to the entry node w.r.t. + // CSR uses: every path through the function must + // pass through this node. If each CSR is used at least + // once by these nodes, shrink wrapping is disabled. + CSRegSet CSRUsedInChokePoints; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + if (MBB == EntryBlock || CSRUsed[MBB].empty() || MBB->succ_size() < 1) + continue; + bool dominatesExitNodes = true; + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) + if (! DT.dominates(MBB, ReturnBlocks[ri])) { + dominatesExitNodes = false; + break; + } + if (dominatesExitNodes) { + CSRUsedInChokePoints |= CSRUsed[MBB]; + if (CSRUsedInChokePoints == UsedCSRegs) { + DEBUG(dbgs() << "DISABLED: " << Fn.getFunction()->getName() + << ": all CSRs used in choke point(s) at " + << getBasicBlockName(MBB) << "\n"); + ShrinkWrapThisFunction = false; + break; + } + } + } + } + + // Return now if we have decided not to apply shrink wrapping + // to the current function. + if (! ShrinkWrapThisFunction) + return false; + + DEBUG({ + dbgs() << "ENABLED: " << Fn.getFunction()->getName(); + if (HasFastExitPath) + dbgs() << " (fast exit path)"; + dbgs() << "\n"; + if (ShrinkWrapDebugging >= BasicInfo) { + dbgs() << "------------------------------" + << "-----------------------------\n"; + dbgs() << "UsedCSRegs = " << stringifyCSRegSet(UsedCSRegs) << "\n"; + if (ShrinkWrapDebugging >= Details) { + dbgs() << "------------------------------" + << "-----------------------------\n"; + dumpAllUsed(); + } + } + }); + + // Build initial DF sets to determine minimal regions in the + // Machine CFG around which CSRs must be spilled and restored. + calculateAnticAvail(Fn); + + return true; +} + +/// addUsesForMEMERegion - add uses of CSRs spilled or restored in +/// multi-entry, multi-exit (MEME) regions so spill and restore +/// placement will not break code that enters or leaves a +/// shrink-wrapped region by inducing spills with no matching +/// restores or restores with no matching spills. A MEME region +/// is a subgraph of the MCFG with multiple entry edges, multiple +/// exit edges, or both. This code propagates use information +/// through the MCFG until all paths requiring spills and restores +/// _outside_ the computed minimal placement regions have been covered. +/// +bool PEI::addUsesForMEMERegion(MachineBasicBlock* MBB, + SmallVector& blks) { + if (MBB->succ_size() < 2 && MBB->pred_size() < 2) { + bool processThisBlock = false; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC->pred_size() > 1) { + processThisBlock = true; + break; + } + } + if (!CSRRestore[MBB].empty() && MBB->succ_size() > 0) { + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED->succ_size() > 1) { + processThisBlock = true; + break; + } + } + } + if (! processThisBlock) + return false; + } + + CSRegSet prop; + if (!CSRSave[MBB].empty()) + prop = CSRSave[MBB]; + else if (!CSRRestore[MBB].empty()) + prop = CSRRestore[MBB]; + else + prop = CSRUsed[MBB]; + if (prop.empty()) + return false; + + // Propagate selected bits to successors, predecessors of MBB. + bool addedUses = false; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + // Self-loop + if (SUCC == MBB) + continue; + if (! CSRUsed[SUCC].contains(prop)) { + CSRUsed[SUCC] |= prop; + addedUses = true; + blks.push_back(SUCC); + DEBUG(if (ShrinkWrapDebugging >= Iterations) + dbgs() << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(prop) << ")->" + << "successor " << getBasicBlockName(SUCC) << "\n"); + } + } + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + // Self-loop + if (PRED == MBB) + continue; + if (! CSRUsed[PRED].contains(prop)) { + CSRUsed[PRED] |= prop; + addedUses = true; + blks.push_back(PRED); + DEBUG(if (ShrinkWrapDebugging >= Iterations) + dbgs() << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(prop) << ")->" + << "predecessor " << getBasicBlockName(PRED) << "\n"); + } + } + return addedUses; +} + +/// addUsesForTopLevelLoops - add uses for CSRs used inside top +/// level loops to the exit blocks of those loops. +/// +bool PEI::addUsesForTopLevelLoops(SmallVector& blks) { + bool addedUses = false; + + // Place restores for top level loops where needed. + for (DenseMap::iterator + I = TLLoops.begin(), E = TLLoops.end(); I != E; ++I) { + MachineBasicBlock* MBB = I->first; + MachineLoop* LP = I->second; + MachineBasicBlock* HDR = LP->getHeader(); + SmallVector exitBlocks; + CSRegSet loopSpills; + + loopSpills = CSRSave[MBB]; + if (CSRSave[MBB].empty()) { + loopSpills = CSRUsed[HDR]; + assert(!loopSpills.empty() && "No CSRs used in loop?"); + } else if (CSRRestore[MBB].contains(CSRSave[MBB])) + continue; + + LP->getExitBlocks(exitBlocks); + assert(exitBlocks.size() > 0 && "Loop has no top level exit blocks?"); + for (unsigned i = 0, e = exitBlocks.size(); i != e; ++i) { + MachineBasicBlock* EXB = exitBlocks[i]; + if (! CSRUsed[EXB].contains(loopSpills)) { + CSRUsed[EXB] |= loopSpills; + addedUses = true; + DEBUG(if (ShrinkWrapDebugging >= Iterations) + dbgs() << "LOOP " << getBasicBlockName(MBB) + << "(" << stringifyCSRegSet(loopSpills) << ")->" + << getBasicBlockName(EXB) << "\n"); + if (EXB->succ_size() > 1 || EXB->pred_size() > 1) + blks.push_back(EXB); + } + } + } + return addedUses; +} + +/// calcSpillPlacements - determine which CSRs should be spilled +/// in MBB using AnticIn sets of MBB's predecessors, keeping track +/// of changes to spilled reg sets. Add MBB to the set of blocks +/// that need to be processed for propagating use info to cover +/// multi-entry/exit regions. +/// +bool PEI::calcSpillPlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevSpills) { + bool placedSpills = false; + // Intersect (CSRegs - AnticIn[P]) for P in Predecessors(MBB) + CSRegSet anticInPreds; + SmallVector predecessors; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock* PRED = *PI; + if (PRED != MBB) + predecessors.push_back(PRED); + } + unsigned i = 0, e = predecessors.size(); + if (i != e) { + MachineBasicBlock* PRED = predecessors[i]; + anticInPreds = UsedCSRegs - AnticIn[PRED]; + for (++i; i != e; ++i) { + PRED = predecessors[i]; + anticInPreds &= (UsedCSRegs - AnticIn[PRED]); + } + } else { + // Handle uses in entry blocks (which have no predecessors). + // This is necessary because the DFA formulation assumes the + // entry and (multiple) exit nodes cannot have CSR uses, which + // is not the case in the real world. + anticInPreds = UsedCSRegs; + } + // Compute spills required at MBB: + CSRSave[MBB] |= (AnticIn[MBB] - AvailIn[MBB]) & anticInPreds; + + if (! CSRSave[MBB].empty()) { + if (MBB == EntryBlock) { + for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) + CSRRestore[ReturnBlocks[ri]] |= CSRSave[MBB]; + } else { + // Reset all regs spilled in MBB that are also spilled in EntryBlock. + if (CSRSave[EntryBlock].intersects(CSRSave[MBB])) { + CSRSave[MBB] = CSRSave[MBB] - CSRSave[EntryBlock]; + } + } + } + placedSpills = (CSRSave[MBB] != prevSpills[MBB]); + prevSpills[MBB] = CSRSave[MBB]; + // Remember this block for adding restores to successor + // blocks for multi-entry region. + if (placedSpills) + blks.push_back(MBB); + + DEBUG(if (! CSRSave[MBB].empty() && ShrinkWrapDebugging >= Iterations) + dbgs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]) << "\n"); + + return placedSpills; +} + +/// calcRestorePlacements - determine which CSRs should be restored +/// in MBB using AvailOut sets of MBB's succcessors, keeping track +/// of changes to restored reg sets. Add MBB to the set of blocks +/// that need to be processed for propagating use info to cover +/// multi-entry/exit regions. +/// +bool PEI::calcRestorePlacements(MachineBasicBlock* MBB, + SmallVector &blks, + CSRegBlockMap &prevRestores) { + bool placedRestores = false; + // Intersect (CSRegs - AvailOut[S]) for S in Successors(MBB) + CSRegSet availOutSucc; + SmallVector successors; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + if (SUCC != MBB) + successors.push_back(SUCC); + } + unsigned i = 0, e = successors.size(); + if (i != e) { + MachineBasicBlock* SUCC = successors[i]; + availOutSucc = UsedCSRegs - AvailOut[SUCC]; + for (++i; i != e; ++i) { + SUCC = successors[i]; + availOutSucc &= (UsedCSRegs - AvailOut[SUCC]); + } + } else { + if (! CSRUsed[MBB].empty() || ! AvailOut[MBB].empty()) { + // Handle uses in return blocks (which have no successors). + // This is necessary because the DFA formulation assumes the + // entry and (multiple) exit nodes cannot have CSR uses, which + // is not the case in the real world. + availOutSucc = UsedCSRegs; + } + } + // Compute restores required at MBB: + CSRRestore[MBB] |= (AvailOut[MBB] - AnticOut[MBB]) & availOutSucc; + + // Postprocess restore placements at MBB. + // Remove the CSRs that are restored in the return blocks. + // Lest this be confusing, note that: + // CSRSave[EntryBlock] == CSRRestore[B] for all B in ReturnBlocks. + if (MBB->succ_size() && ! CSRRestore[MBB].empty()) { + if (! CSRSave[EntryBlock].empty()) + CSRRestore[MBB] = CSRRestore[MBB] - CSRSave[EntryBlock]; + } + placedRestores = (CSRRestore[MBB] != prevRestores[MBB]); + prevRestores[MBB] = CSRRestore[MBB]; + // Remember this block for adding saves to predecessor + // blocks for multi-entry region. + if (placedRestores) + blks.push_back(MBB); + + DEBUG(if (! CSRRestore[MBB].empty() && ShrinkWrapDebugging >= Iterations) + dbgs() << "RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"); + + return placedRestores; +} + +/// placeSpillsAndRestores - place spills and restores of CSRs +/// used in MBBs in minimal regions that contain the uses. +/// +void PEI::placeSpillsAndRestores(MachineFunction &Fn) { + CSRegBlockMap prevCSRSave; + CSRegBlockMap prevCSRRestore; + SmallVector cvBlocks, ncvBlocks; + bool changed = true; + unsigned iterations = 0; + + // Iterate computation of spill and restore placements in the MCFG until: + // 1. CSR use info has been fully propagated around the MCFG, and + // 2. computation of CSRSave[], CSRRestore[] reach fixed points. + while (changed) { + changed = false; + ++iterations; + + DEBUG(if (ShrinkWrapDebugging >= Iterations) + dbgs() << "iter " << iterations + << " --------------------------------------------------\n"); + + // Calculate CSR{Save,Restore} sets using Antic, Avail on the MCFG, + // which determines the placements of spills and restores. + // Keep track of changes to spills, restores in each iteration to + // minimize the total iterations. + bool SRChanged = false; + for (MachineFunction::iterator MBBI = Fn.begin(), MBBE = Fn.end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + + // Place spills for CSRs in MBB. + SRChanged |= calcSpillPlacements(MBB, cvBlocks, prevCSRSave); + + // Place restores for CSRs in MBB. + SRChanged |= calcRestorePlacements(MBB, cvBlocks, prevCSRRestore); + } + + // Add uses of CSRs used inside loops where needed. + changed |= addUsesForTopLevelLoops(cvBlocks); + + // Add uses for CSRs spilled or restored at branch, join points. + if (changed || SRChanged) { + while (! cvBlocks.empty()) { + MachineBasicBlock* MBB = cvBlocks.pop_back_val(); + changed |= addUsesForMEMERegion(MBB, ncvBlocks); + } + if (! ncvBlocks.empty()) { + cvBlocks = ncvBlocks; + ncvBlocks.clear(); + } + } + + if (changed) { + calculateAnticAvail(Fn); + CSRSave.clear(); + CSRRestore.clear(); + } + } + + // Check for effectiveness: + // SR0 = {r | r in CSRSave[EntryBlock], CSRRestore[RB], RB in ReturnBlocks} + // numSRReduced = |(UsedCSRegs - SR0)|, approx. SR0 by CSRSave[EntryBlock] + // Gives a measure of how many CSR spills have been moved from EntryBlock + // to minimal regions enclosing their uses. + CSRegSet notSpilledInEntryBlock = (UsedCSRegs - CSRSave[EntryBlock]); + unsigned numSRReducedThisFunc = notSpilledInEntryBlock.count(); + numSRReduced += numSRReducedThisFunc; + DEBUG(if (ShrinkWrapDebugging >= BasicInfo) { + dbgs() << "-----------------------------------------------------------\n"; + dbgs() << "total iterations = " << iterations << " ( " + << Fn.getFunction()->getName() + << " " << numSRReducedThisFunc + << " " << Fn.size() + << " )\n"; + dbgs() << "-----------------------------------------------------------\n"; + dumpSRSets(); + dbgs() << "-----------------------------------------------------------\n"; + if (numSRReducedThisFunc) + verifySpillRestorePlacement(); + }); +} + +// Debugging methods. +#ifndef NDEBUG +/// findFastExitPath - debugging method used to detect functions +/// with at least one path from the entry block to a return block +/// directly or which has a very small number of edges. +/// +void PEI::findFastExitPath() { + if (! EntryBlock) + return; + // Fina a path from EntryBlock to any return block that does not branch: + // Entry + // | ... + // v | + // B1<-----+ + // | + // v + // Return + for (MachineBasicBlock::succ_iterator SI = EntryBlock->succ_begin(), + SE = EntryBlock->succ_end(); SI != SE; ++SI) { + MachineBasicBlock* SUCC = *SI; + + // Assume positive, disprove existence of fast path. + HasFastExitPath = true; + + // Check the immediate successors. + if (isReturnBlock(SUCC)) { + if (ShrinkWrapDebugging >= BasicInfo) + dbgs() << "Fast exit path: " << getBasicBlockName(EntryBlock) + << "->" << getBasicBlockName(SUCC) << "\n"; + break; + } + // Traverse df from SUCC, look for a branch block. + std::string exitPath = getBasicBlockName(SUCC); + for (df_iterator BI = df_begin(SUCC), + BE = df_end(SUCC); BI != BE; ++BI) { + MachineBasicBlock* SBB = *BI; + // Reject paths with branch nodes. + if (SBB->succ_size() > 1) { + HasFastExitPath = false; + break; + } + exitPath += "->" + getBasicBlockName(SBB); + } + if (HasFastExitPath) { + if (ShrinkWrapDebugging >= BasicInfo) + dbgs() << "Fast exit path: " << getBasicBlockName(EntryBlock) + << "->" << exitPath << "\n"; + break; + } + } +} + +/// verifySpillRestorePlacement - check the current spill/restore +/// sets for safety. Attempt to find spills without restores or +/// restores without spills. +/// Spills: walk df from each MBB in spill set ensuring that +/// all CSRs spilled at MMBB are restored on all paths +/// from MBB to all exit blocks. +/// Restores: walk idf from each MBB in restore set ensuring that +/// all CSRs restored at MBB are spilled on all paths +/// reaching MBB. +/// +void PEI::verifySpillRestorePlacement() { + unsigned numReturnBlocks = 0; + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + if (isReturnBlock(MBB) || MBB->succ_size() == 0) + ++numReturnBlocks; + } + for (CSRegBlockMap::iterator BI = CSRSave.begin(), + BE = CSRSave.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet spilled = BI->second; + CSRegSet restored; + + if (spilled.empty()) + continue; + + DEBUG(dbgs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(spilled) + << " RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"); + + if (CSRRestore[MBB].intersects(spilled)) { + restored |= (CSRRestore[MBB] & spilled); + } + + // Walk depth first from MBB to find restores of all CSRs spilled at MBB: + // we must find restores for all spills w/no intervening spills on all + // paths from MBB to all return blocks. + for (df_iterator BI = df_begin(MBB), + BE = df_end(MBB); BI != BE; ++BI) { + MachineBasicBlock* SBB = *BI; + if (SBB == MBB) + continue; + // Stop when we encounter spills of any CSRs spilled at MBB that + // have not yet been seen to be restored. + if (CSRSave[SBB].intersects(spilled) && + !restored.contains(CSRSave[SBB] & spilled)) + break; + // Collect the CSRs spilled at MBB that are restored + // at this DF successor of MBB. + if (CSRRestore[SBB].intersects(spilled)) + restored |= (CSRRestore[SBB] & spilled); + // If we are at a retun block, check that the restores + // we have seen so far exhaust the spills at MBB, then + // reset the restores. + if (isReturnBlock(SBB) || SBB->succ_size() == 0) { + if (restored != spilled) { + CSRegSet notRestored = (spilled - restored); + DEBUG(dbgs() << MF->getFunction()->getName() << ": " + << stringifyCSRegSet(notRestored) + << " spilled at " << getBasicBlockName(MBB) + << " are never restored on path to return " + << getBasicBlockName(SBB) << "\n"); + } + restored.clear(); + } + } + } + + // Check restore placements. + for (CSRegBlockMap::iterator BI = CSRRestore.begin(), + BE = CSRRestore.end(); BI != BE; ++BI) { + MachineBasicBlock* MBB = BI->first; + CSRegSet restored = BI->second; + CSRegSet spilled; + + if (restored.empty()) + continue; + + DEBUG(dbgs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]) + << " RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(restored) << "\n"); + + if (CSRSave[MBB].intersects(restored)) { + spilled |= (CSRSave[MBB] & restored); + } + // Walk inverse depth first from MBB to find spills of all + // CSRs restored at MBB: + for (idf_iterator BI = idf_begin(MBB), + BE = idf_end(MBB); BI != BE; ++BI) { + MachineBasicBlock* PBB = *BI; + if (PBB == MBB) + continue; + // Stop when we encounter restores of any CSRs restored at MBB that + // have not yet been seen to be spilled. + if (CSRRestore[PBB].intersects(restored) && + !spilled.contains(CSRRestore[PBB] & restored)) + break; + // Collect the CSRs restored at MBB that are spilled + // at this DF predecessor of MBB. + if (CSRSave[PBB].intersects(restored)) + spilled |= (CSRSave[PBB] & restored); + } + if (spilled != restored) { + CSRegSet notSpilled = (restored - spilled); + DEBUG(dbgs() << MF->getFunction()->getName() << ": " + << stringifyCSRegSet(notSpilled) + << " restored at " << getBasicBlockName(MBB) + << " are never spilled\n"); + } + } +} + +// Debugging print methods. +std::string PEI::getBasicBlockName(const MachineBasicBlock* MBB) { + if (!MBB) + return ""; + + if (MBB->getBasicBlock()) + return MBB->getBasicBlock()->getNameStr(); + + std::ostringstream name; + name << "_MBB_" << MBB->getNumber(); + return name.str(); +} + +std::string PEI::stringifyCSRegSet(const CSRegSet& s) { + const TargetRegisterInfo* TRI = MF->getTarget().getRegisterInfo(); + const std::vector CSI = + MF->getFrameInfo()->getCalleeSavedInfo(); + + std::ostringstream srep; + if (CSI.size() == 0) { + srep << "[]"; + return srep.str(); + } + srep << "["; + CSRegSet::iterator I = s.begin(), E = s.end(); + if (I != E) { + unsigned reg = CSI[*I].getReg(); + srep << TRI->getName(reg); + for (++I; I != E; ++I) { + reg = CSI[*I].getReg(); + srep << ","; + srep << TRI->getName(reg); + } + } + srep << "]"; + return srep.str(); +} + +void PEI::dumpSet(const CSRegSet& s) { + DEBUG(dbgs() << stringifyCSRegSet(s) << "\n"); +} + +void PEI::dumpUsed(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + dbgs() << "CSRUsed[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRUsed[MBB]) << "\n"; + }); +} + +void PEI::dumpAllUsed() { + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpUsed(MBB); + } +} + +void PEI::dumpSets(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + dbgs() << getBasicBlockName(MBB) << " | " + << stringifyCSRegSet(CSRUsed[MBB]) << " | " + << stringifyCSRegSet(AnticIn[MBB]) << " | " + << stringifyCSRegSet(AnticOut[MBB]) << " | " + << stringifyCSRegSet(AvailIn[MBB]) << " | " + << stringifyCSRegSet(AvailOut[MBB]) << "\n"; + }); +} + +void PEI::dumpSets1(MachineBasicBlock* MBB) { + DEBUG({ + if (MBB) + dbgs() << getBasicBlockName(MBB) << " | " + << stringifyCSRegSet(CSRUsed[MBB]) << " | " + << stringifyCSRegSet(AnticIn[MBB]) << " | " + << stringifyCSRegSet(AnticOut[MBB]) << " | " + << stringifyCSRegSet(AvailIn[MBB]) << " | " + << stringifyCSRegSet(AvailOut[MBB]) << " | " + << stringifyCSRegSet(CSRSave[MBB]) << " | " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"; + }); +} + +void PEI::dumpAllSets() { + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + MachineBasicBlock* MBB = MBBI; + dumpSets1(MBB); + } +} + +void PEI::dumpSRSets() { + DEBUG({ + for (MachineFunction::iterator MBB = MF->begin(), E = MF->end(); + MBB != E; ++MBB) { + if (!CSRSave[MBB].empty()) { + dbgs() << "SAVE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRSave[MBB]); + if (CSRRestore[MBB].empty()) + dbgs() << '\n'; + } + + if (!CSRRestore[MBB].empty() && !CSRSave[MBB].empty()) + dbgs() << " " + << "RESTORE[" << getBasicBlockName(MBB) << "] = " + << stringifyCSRegSet(CSRRestore[MBB]) << "\n"; + } + }); +} +#endif diff --git a/final/lib/CodeGen/SimpleRegisterCoalescing.cpp b/final/lib/CodeGen/SimpleRegisterCoalescing.cpp new file mode 100644 index 00000000000..8a102702ef3 --- /dev/null +++ b/final/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -0,0 +1,1789 @@ +//===-- SimpleRegisterCoalescing.cpp - Register Coalescing ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple register coalescing pass that attempts to +// aggressively coalesce every register copy that it can. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regcoalescing" +#include "SimpleRegisterCoalescing.h" +#include "VirtRegMap.h" +#include "LiveDebugVariables.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/Value.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(numJoins , "Number of interval joins performed"); +STATISTIC(numCrossRCs , "Number of cross class joins performed"); +STATISTIC(numCommutes , "Number of instruction commuting performed"); +STATISTIC(numExtends , "Number of copies extended"); +STATISTIC(NumReMats , "Number of instructions re-materialized"); +STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); +STATISTIC(numAborts , "Number of times interval joining aborted"); +STATISTIC(numDeadValNo, "Number of valno def marked dead"); + +char SimpleRegisterCoalescing::ID = 0; +static cl::opt +EnableJoining("join-liveintervals", + cl::desc("Coalesce copies (default=true)"), + cl::init(true)); + +static cl::opt +DisableCrossClassJoin("disable-cross-class-join", + cl::desc("Avoid coalescing cross register class copies"), + cl::init(false), cl::Hidden); + +static cl::opt +DisablePhysicalJoin("disable-physical-join", + cl::desc("Avoid coalescing physical register copies"), + cl::init(false), cl::Hidden); + +static cl::opt +VerifyCoalescing("verify-coalescing", + cl::desc("Verify machine instrs before and after register coalescing"), + cl::Hidden); + +INITIALIZE_AG_PASS_BEGIN(SimpleRegisterCoalescing, RegisterCoalescer, + "simple-register-coalescing", "Simple Register Coalescing", + false, false, true) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(StrongPHIElimination) +INITIALIZE_PASS_DEPENDENCY(PHIElimination) +INITIALIZE_PASS_DEPENDENCY(TwoAddressInstructionPass) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_AG_PASS_END(SimpleRegisterCoalescing, RegisterCoalescer, + "simple-register-coalescing", "Simple Register Coalescing", + false, false, true) + +char &llvm::SimpleRegisterCoalescingID = SimpleRegisterCoalescing::ID; + +void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + AU.addPreservedID(StrongPHIEliminationID); + AU.addPreservedID(PHIEliminationID); + AU.addPreservedID(TwoAddressInstructionPassID); + MachineFunctionPass::getAnalysisUsage(AU); +} + +/// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy with IntA +/// being the source and IntB being the dest, thus this defines a value number +/// in IntB. If the source value number (in IntA) is defined by a copy from B, +/// see if we can merge these two pieces of B into a single value number, +/// eliminating a copy. For example: +/// +/// A3 = B0 +/// ... +/// B1 = A3 <- this copy +/// +/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 +/// value number to be replaced with B0 (which simplifies the B liveinterval). +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(const CoalescerPair &CP, + MachineInstr *CopyMI) { + // Bail if there is no dst interval - can happen when merging physical subreg + // operations. + if (!li_->hasInterval(CP.getDstReg())) + return false; + + LiveInterval &IntA = + li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LiveInterval &IntB = + li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); + if (BLR == IntB.end()) return false; + VNInfo *BValNo = BLR->valno; + + // Get the location that B is defined at. Two options: either this value has + // an unknown definition point or it is defined at CopyIdx. If unknown, we + // can't process it. + if (!BValNo->isDefByCopy()) return false; + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + SlotIndex CopyUseIdx = CopyIdx.getUseIndex(); + LiveInterval::iterator ALR = IntA.FindLiveRangeContaining(CopyUseIdx); + // The live range might not exist after fun with physreg coalescing. + if (ALR == IntA.end()) return false; + VNInfo *AValNo = ALR->valno; + // If it's re-defined by an early clobber somewhere in the live range, then + // it's not safe to eliminate the copy. FIXME: This is a temporary workaround. + // See PR3149: + // 172 %ECX = MOV32rr %reg1039 + // 180 INLINEASM , 10, %EAX, 14, %ECX, 9, + // %EAX, + // 36, , 1, %reg0, 0, 9, %ECX, 36, , 1, %reg0, 0 + // 188 %EAX = MOV32rr %EAX + // 196 %ECX = MOV32rr %ECX + // 204 %ECX = MOV32rr %ECX + // 212 %EAX = MOV32rr %EAX + // 220 %EAX = MOV32rr %EAX + // 228 %reg1039 = MOV32rr %ECX + // The early clobber operand ties ECX input to the ECX def. + // + // The live interval of ECX is represented as this: + // %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47) + // The coalescer has no idea there was a def in the middle of [174,230]. + if (AValNo->hasRedefByEC()) + return false; + + // If AValNo is defined as a copy from IntB, we can potentially process this. + // Get the instruction that defines this value number. + if (!CP.isCoalescable(AValNo->getCopy())) + return false; + + // Get the LiveRange in IntB that this value number starts with. + LiveInterval::iterator ValLR = + IntB.FindLiveRangeContaining(AValNo->def.getPrevSlot()); + if (ValLR == IntB.end()) + return false; + + // Make sure that the end of the live range is inside the same block as + // CopyMI. + MachineInstr *ValLREndInst = + li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); + if (!ValLREndInst || ValLREndInst->getParent() != CopyMI->getParent()) + return false; + + // Okay, we now know that ValLR ends in the same block that the CopyMI + // live-range starts. If there are no intervening live ranges between them in + // IntB, we can merge them. + if (ValLR+1 != BLR) return false; + + // If a live interval is a physical register, conservatively check if any + // of its sub-registers is overlapping the live interval of the virtual + // register. If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg) && + *tri_->getSubRegisters(IntB.reg)) { + for (const unsigned* SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && IntA.overlaps(li_->getInterval(*SR))) { + DEBUG({ + dbgs() << "\t\tInterfere with sub-register "; + li_->getInterval(*SR).print(dbgs(), tri_); + }); + return false; + } + } + + DEBUG({ + dbgs() << "Extending: "; + IntB.print(dbgs(), tri_); + }); + + SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; + // We are about to delete CopyMI, so need to remove it as the 'instruction + // that defines this value #'. Update the valnum with the new defining + // instruction #. + BValNo->def = FillerStart; + BValNo->setCopy(0); + + // Okay, we can merge them. We need to insert a new liverange: + // [ValLR.end, BLR.begin) of either value number, then we merge the + // two value numbers. + IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); + + // If the IntB live range is assigned to a physical register, and if that + // physreg has sub-registers, update their live intervals as well. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &SRLI = li_->getInterval(*SR); + SRLI.addRange(LiveRange(FillerStart, FillerEnd, + SRLI.getNextValue(FillerStart, 0, + li_->getVNInfoAllocator()))); + } + } + + // Okay, merge "B1" into the same value number as "B0". + if (BValNo != ValLR->valno) { + IntB.MergeValueNumberInto(BValNo, ValLR->valno); + } + DEBUG({ + dbgs() << " result = "; + IntB.print(dbgs(), tri_); + dbgs() << "\n"; + }); + + // If the source instruction was killing the source register before the + // merge, unset the isKill marker given the live range has been extended. + int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); + if (UIdx != -1) { + ValLREndInst->getOperand(UIdx).setIsKill(false); + } + + // If the copy instruction was killing the destination register before the + // merge, find the last use and trim the live range. That will also add the + // isKill marker. + if (ALR->end == CopyIdx) + TrimLiveIntervalToLastUse(CopyUseIdx, CopyMI->getParent(), IntA, ALR); + + ++numExtends; + return true; +} + +/// HasOtherReachingDefs - Return true if there are definitions of IntB +/// other than BValNo val# that can reach uses of AValno val# of IntA. +bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA, + LiveInterval &IntB, + VNInfo *AValNo, + VNInfo *BValNo) { + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + LiveInterval::Ranges::iterator BI = + std::upper_bound(IntB.ranges.begin(), IntB.ranges.end(), AI->start); + if (BI != IntB.ranges.begin()) + --BI; + for (; BI != IntB.ranges.end() && AI->end >= BI->start; ++BI) { + if (BI->valno == BValNo) + continue; + if (BI->start <= AI->start && BI->end > AI->start) + return true; + if (BI->start > AI->start && BI->start < AI->end) + return true; + } + } + return false; +} + +/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with +/// IntA being the source and IntB being the dest, thus this defines a value +/// number in IntB. If the source value number (in IntA) is defined by a +/// commutable instruction and its other operand is coalesced to the copy dest +/// register, see if we can transform the copy into a noop by commuting the +/// definition. For example, +/// +/// A3 = op A2 B0 +/// ... +/// B1 = A3 <- this copy +/// ... +/// = op A3 <- more uses +/// +/// ==> +/// +/// B2 = op B0 A2 +/// ... +/// B1 = B2 <- now an identify copy +/// ... +/// = op B2 <- more uses +/// +/// This returns true if an interval was modified. +/// +bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(const CoalescerPair &CP, + MachineInstr *CopyMI) { + // FIXME: For now, only eliminate the copy by commuting its def when the + // source register is a virtual register. We want to guard against cases + // where the copy is a back edge copy and commuting the def lengthen the + // live interval of the source register to the entire loop. + if (CP.isPhys() && CP.isFlipped()) + return false; + + // Bail if there is no dst interval. + if (!li_->hasInterval(CP.getDstReg())) + return false; + + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + + LiveInterval &IntA = + li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LiveInterval &IntB = + li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + VNInfo *BValNo = IntB.getVNInfoAt(CopyIdx); + if (!BValNo || !BValNo->isDefByCopy()) + return false; + + assert(BValNo->def == CopyIdx && "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A3 in the example. + VNInfo *AValNo = IntA.getVNInfoAt(CopyIdx.getUseIndex()); + assert(AValNo && "COPY source not live"); + + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. + if (AValNo->isPHIDef() || AValNo->isUnused() || AValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); + if (!DefMI) + return false; + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isCommutable()) + return false; + // If DefMI is a two-address instruction then commuting it will change the + // destination register. + int DefIdx = DefMI->findRegisterDefOperandIdx(IntA.reg); + assert(DefIdx != -1); + unsigned UseOpIdx; + if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) + return false; + unsigned Op1, Op2, NewDstIdx; + if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) + return false; + if (Op1 == UseOpIdx) + NewDstIdx = Op2; + else if (Op2 == UseOpIdx) + NewDstIdx = Op1; + else + return false; + + MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); + unsigned NewReg = NewDstMO.getReg(); + if (NewReg != IntB.reg || !NewDstMO.isKill()) + return false; + + // Make sure there are no other definitions of IntB that would reach the + // uses which the new definition can reach. + if (HasOtherReachingDefs(IntA, IntB, AValNo, BValNo)) + return false; + + // Abort if the aliases of IntB.reg have values that are not simply the + // clobbers from the superreg. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) + for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) + if (li_->hasInterval(*AS) && + HasOtherReachingDefs(IntA, li_->getInterval(*AS), AValNo, 0)) + return false; + + // If some of the uses of IntA.reg is already coalesced away, return false. + // It's not possible to determine whether it's safe to perform the coalescing. + for (MachineRegisterInfo::use_nodbg_iterator UI = + mri_->use_nodbg_begin(IntA.reg), + UE = mri_->use_nodbg_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + SlotIndex UseIdx = li_->getInstructionIndex(UseMI); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end()) + continue; + if (ULR->valno == AValNo && JoinedCopies.count(UseMI)) + return false; + } + + DEBUG(dbgs() << "\tRemoveCopyByCommutingDef: " << AValNo->def << '\t' + << *DefMI); + + // At this point we have decided that it is legal to do this + // transformation. Start by commuting the instruction. + MachineBasicBlock *MBB = DefMI->getParent(); + MachineInstr *NewMI = tii_->commuteInstruction(DefMI); + if (!NewMI) + return false; + if (NewMI != DefMI) { + li_->ReplaceMachineInstrInMaps(DefMI, NewMI); + MBB->insert(DefMI, NewMI); + MBB->erase(DefMI); + } + unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false); + NewMI->getOperand(OpIdx).setIsKill(); + + // If ALR and BLR overlaps and end of BLR extends beyond end of ALR, e.g. + // A = or A, B + // ... + // B = A + // ... + // C = A + // ... + // = B + + // Update uses of IntA of the specific Val# with IntB. + for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), + UE = mri_->use_end(); UI != UE;) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + ++UI; + if (JoinedCopies.count(UseMI)) + continue; + if (UseMI->isDebugValue()) { + // FIXME These don't have an instruction index. Not clear we have enough + // info to decide whether to do this replacement or not. For now do it. + UseMO.setReg(NewReg); + continue; + } + SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); + LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); + if (ULR == IntA.end() || ULR->valno != AValNo) + continue; + if (TargetRegisterInfo::isPhysicalRegister(NewReg)) + UseMO.substPhysReg(NewReg, *tri_); + else + UseMO.setReg(NewReg); + if (UseMI == CopyMI) + continue; + if (!UseMI->isCopy()) + continue; + if (UseMI->getOperand(0).getReg() != IntB.reg || + UseMI->getOperand(0).getSubReg()) + continue; + + // This copy will become a noop. If it's defining a new val#, merge it into + // BValNo. + SlotIndex DefIdx = UseIdx.getDefIndex(); + VNInfo *DVNI = IntB.getVNInfoAt(DefIdx); + if (!DVNI) + continue; + DEBUG(dbgs() << "\t\tnoop: " << DefIdx << '\t' << *UseMI); + assert(DVNI->def == DefIdx); + BValNo = IntB.MergeValueNumberInto(BValNo, DVNI); + JoinedCopies.insert(UseMI); + } + + // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition + // is updated. + VNInfo *ValNo = BValNo; + ValNo->def = AValNo->def; + ValNo->setCopy(0); + for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); + AI != AE; ++AI) { + if (AI->valno != AValNo) continue; + IntB.addRange(LiveRange(AI->start, AI->end, ValNo)); + } + DEBUG(dbgs() << "\t\textended: " << IntB << '\n'); + + IntA.removeValNo(AValNo); + DEBUG(dbgs() << "\t\ttrimmed: " << IntA << '\n'); + ++numCommutes; + return true; +} + +/// isSameOrFallThroughBB - Return true if MBB == SuccMBB or MBB simply +/// fallthoughs to SuccMBB. +static bool isSameOrFallThroughBB(MachineBasicBlock *MBB, + MachineBasicBlock *SuccMBB, + const TargetInstrInfo *tii_) { + if (MBB == SuccMBB) + return true; + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + return !tii_->AnalyzeBranch(*MBB, TBB, FBB, Cond) && !TBB && !FBB && + MBB->isSuccessor(SuccMBB); +} + +/// removeRange - Wrapper for LiveInterval::removeRange. This removes a range +/// from a physical register live interval as well as from the live intervals +/// of its sub-registers. +static void removeRange(LiveInterval &li, + SlotIndex Start, SlotIndex End, + LiveIntervals *li_, const TargetRegisterInfo *tri_) { + li.removeRange(Start, End, true); + if (TargetRegisterInfo::isPhysicalRegister(li.reg)) { + for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &sli = li_->getInterval(*SR); + SlotIndex RemoveStart = Start; + SlotIndex RemoveEnd = Start; + + while (RemoveEnd != End) { + LiveInterval::iterator LR = sli.FindLiveRangeContaining(RemoveStart); + if (LR == sli.end()) + break; + RemoveEnd = (LR->end < End) ? LR->end : End; + sli.removeRange(RemoveStart, RemoveEnd, true); + RemoveStart = RemoveEnd; + } + } + } +} + +/// TrimLiveIntervalToLastUse - If there is a last use in the same basic block +/// as the copy instruction, trim the live interval to the last use and return +/// true. +bool +SimpleRegisterCoalescing::TrimLiveIntervalToLastUse(SlotIndex CopyIdx, + MachineBasicBlock *CopyMBB, + LiveInterval &li, + const LiveRange *LR) { + SlotIndex MBBStart = li_->getMBBStartIdx(CopyMBB); + SlotIndex LastUseIdx; + MachineOperand *LastUse = + lastRegisterUse(LR->start, CopyIdx.getPrevSlot(), li.reg, LastUseIdx); + if (LastUse) { + MachineInstr *LastUseMI = LastUse->getParent(); + if (!isSameOrFallThroughBB(LastUseMI->getParent(), CopyMBB, tii_)) { + // r1024 = op + // ... + // BB1: + // = r1024 + // + // BB2: + // r1025 = r1024 + if (MBBStart < LR->end) + removeRange(li, MBBStart, LR->end, li_, tri_); + return true; + } + + // There are uses before the copy, just shorten the live range to the end + // of last use. + LastUse->setIsKill(); + removeRange(li, LastUseIdx.getDefIndex(), LR->end, li_, tri_); + if (LastUseMI->isCopy()) { + MachineOperand &DefMO = LastUseMI->getOperand(0); + if (DefMO.getReg() == li.reg && !DefMO.getSubReg()) + DefMO.setIsDead(); + } + return true; + } + + // Is it livein? + if (LR->start <= MBBStart && LR->end > MBBStart) { + if (LR->start == li_->getZeroIndex()) { + assert(TargetRegisterInfo::isPhysicalRegister(li.reg)); + // Live-in to the function but dead. Remove it from entry live-in set. + mf_->begin()->removeLiveIn(li.reg); + } + // FIXME: Shorten intervals in BBs that reaches this BB. + } + + return false; +} + +/// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial +/// computation, replace the copy by rematerialize the definition. +bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, + bool preserveSrcInt, + unsigned DstReg, + unsigned DstSubIdx, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); + LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); + assert(SrcLR != SrcInt.end() && "Live range not found!"); + VNInfo *ValNo = SrcLR->valno; + // If other defs can reach uses of this def, then it's not safe to perform + // the optimization. + if (ValNo->isPHIDef() || ValNo->isUnused() || ValNo->hasPHIKill()) + return false; + MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); + if (!DefMI) + return false; + assert(DefMI && "Defining instruction disappeared"); + const TargetInstrDesc &TID = DefMI->getDesc(); + if (!TID.isAsCheapAsAMove()) + return false; + if (!tii_->isTriviallyReMaterializable(DefMI, AA)) + return false; + bool SawStore = false; + if (!DefMI->isSafeToMove(tii_, AA, SawStore)) + return false; + if (TID.getNumDefs() != 1) + return false; + if (!DefMI->isImplicitDef()) { + // Make sure the copy destination register class fits the instruction + // definition register class. The mismatch can happen as a result of earlier + // extract_subreg, insert_subreg, subreg_to_reg coalescing. + const TargetRegisterClass *RC = TID.OpInfo[0].getRegClass(tri_); + if (TargetRegisterInfo::isVirtualRegister(DstReg)) { + if (mri_->getRegClass(DstReg) != RC) + return false; + } else if (!RC->contains(DstReg)) + return false; + } + + // If destination register has a sub-register index on it, make sure it + // matches the instruction register class. + if (DstSubIdx) { + const TargetInstrDesc &TID = DefMI->getDesc(); + if (TID.getNumDefs() != 1) + return false; + const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); + const TargetRegisterClass *DstSubRC = + DstRC->getSubRegisterRegClass(DstSubIdx); + const TargetRegisterClass *DefRC = TID.OpInfo[0].getRegClass(tri_); + if (DefRC == DstRC) + DstSubIdx = 0; + else if (DefRC != DstSubRC) + return false; + } + + RemoveCopyFlag(DstReg, CopyMI); + + MachineBasicBlock *MBB = CopyMI->getParent(); + MachineBasicBlock::iterator MII = + llvm::next(MachineBasicBlock::iterator(CopyMI)); + tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *tri_); + MachineInstr *NewMI = prior(MII); + + // CopyMI may have implicit operands, transfer them over to the newly + // rematerialized instruction. And update implicit def interval valnos. + for (unsigned i = CopyMI->getDesc().getNumOperands(), + e = CopyMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = CopyMI->getOperand(i); + if (MO.isReg() && MO.isImplicit()) + NewMI->addOperand(MO); + if (MO.isDef()) + RemoveCopyFlag(MO.getReg(), CopyMI); + } + + NewMI->copyImplicitOps(CopyMI); + li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); + CopyMI->eraseFromParent(); + ReMatCopies.insert(CopyMI); + ReMatDefs.insert(DefMI); + DEBUG(dbgs() << "Remat: " << *NewMI); + ++NumReMats; + + // The source interval can become smaller because we removed a use. + if (preserveSrcInt) + li_->shrinkToUses(&SrcInt); + + return true; +} + +/// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and +/// update the subregister number if it is not zero. If DstReg is a +/// physical register and the existing subregister number of the def / use +/// being updated is not zero, make sure to set it to the correct physical +/// subregister. +void +SimpleRegisterCoalescing::UpdateRegDefsUses(const CoalescerPair &CP) { + bool DstIsPhys = CP.isPhys(); + unsigned SrcReg = CP.getSrcReg(); + unsigned DstReg = CP.getDstReg(); + unsigned SubIdx = CP.getSubIdx(); + + // Update LiveDebugVariables. + ldv_->renameRegister(SrcReg, DstReg, SubIdx); + + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg); + MachineInstr *UseMI = I.skipInstruction();) { + // A PhysReg copy that won't be coalesced can perhaps be rematerialized + // instead. + if (DstIsPhys) { + if (UseMI->isCopy() && + !UseMI->getOperand(1).getSubReg() && + !UseMI->getOperand(0).getSubReg() && + UseMI->getOperand(1).getReg() == SrcReg && + UseMI->getOperand(0).getReg() != SrcReg && + UseMI->getOperand(0).getReg() != DstReg && + !JoinedCopies.count(UseMI) && + ReMaterializeTrivialDef(li_->getInterval(SrcReg), false, + UseMI->getOperand(0).getReg(), 0, UseMI)) + continue; + } + + SmallVector Ops; + bool Reads, Writes; + tie(Reads, Writes) = UseMI->readsWritesVirtualRegister(SrcReg, &Ops); + bool Kills = false, Deads = false; + + // Replace SrcReg with DstReg in all UseMI operands. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(Ops[i]); + Kills |= MO.isKill(); + Deads |= MO.isDead(); + + if (DstIsPhys) + MO.substPhysReg(DstReg, *tri_); + else + MO.substVirtReg(DstReg, SubIdx, *tri_); + } + + // This instruction is a copy that will be removed. + if (JoinedCopies.count(UseMI)) + continue; + + if (SubIdx) { + // If UseMI was a simple SrcReg def, make sure we didn't turn it into a + // read-modify-write of DstReg. + if (Deads) + UseMI->addRegisterDead(DstReg, tri_); + else if (!Reads && Writes) + UseMI->addRegisterDefined(DstReg, tri_); + + // Kill flags apply to the whole physical register. + if (DstIsPhys && Kills) + UseMI->addRegisterKilled(DstReg, tri_); + } + + DEBUG({ + dbgs() << "\t\tupdated: "; + if (!UseMI->isDebugValue()) + dbgs() << li_->getInstructionIndex(UseMI) << "\t"; + dbgs() << *UseMI; + }); + } +} + +/// removeIntervalIfEmpty - Check if the live interval of a physical register +/// is empty, if so remove it and also remove the empty intervals of its +/// sub-registers. Return true if live interval is removed. +static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, + const TargetRegisterInfo *tri_) { + if (li.empty()) { + if (TargetRegisterInfo::isPhysicalRegister(li.reg)) + for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + LiveInterval &sli = li_->getInterval(*SR); + if (sli.empty()) + li_->removeInterval(*SR); + } + li_->removeInterval(li.reg); + return true; + } + return false; +} + +/// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy. +/// Return true if live interval is removed. +bool SimpleRegisterCoalescing::ShortenDeadCopyLiveRange(LiveInterval &li, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI); + LiveInterval::iterator MLR = + li.FindLiveRangeContaining(CopyIdx.getDefIndex()); + if (MLR == li.end()) + return false; // Already removed by ShortenDeadCopySrcLiveRange. + SlotIndex RemoveStart = MLR->start; + SlotIndex RemoveEnd = MLR->end; + SlotIndex DefIdx = CopyIdx.getDefIndex(); + // Remove the liverange that's defined by this. + if (RemoveStart == DefIdx && RemoveEnd == DefIdx.getStoreIndex()) { + removeRange(li, RemoveStart, RemoveEnd, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); + } + return false; +} + +/// RemoveDeadDef - If a def of a live interval is now determined dead, remove +/// the val# it defines. If the live interval becomes empty, remove it as well. +bool SimpleRegisterCoalescing::RemoveDeadDef(LiveInterval &li, + MachineInstr *DefMI) { + SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); + LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); + if (DefIdx != MLR->valno->def) + return false; + li.removeValNo(MLR->valno); + return removeIntervalIfEmpty(li, li_, tri_); +} + +void SimpleRegisterCoalescing::RemoveCopyFlag(unsigned DstReg, + const MachineInstr *CopyMI) { + SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + if (li_->hasInterval(DstReg)) { + LiveInterval &LI = li_->getInterval(DstReg); + if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) + if (LR->valno->def == DefIdx) + LR->valno->setCopy(0); + } + if (!TargetRegisterInfo::isPhysicalRegister(DstReg)) + return; + for (const unsigned* AS = tri_->getAliasSet(DstReg); *AS; ++AS) { + if (!li_->hasInterval(*AS)) + continue; + LiveInterval &LI = li_->getInterval(*AS); + if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) + if (LR->valno->def == DefIdx) + LR->valno->setCopy(0); + } +} + +/// PropagateDeadness - Propagate the dead marker to the instruction which +/// defines the val#. +static void PropagateDeadness(LiveInterval &li, MachineInstr *CopyMI, + SlotIndex &LRStart, LiveIntervals *li_, + const TargetRegisterInfo* tri_) { + MachineInstr *DefMI = + li_->getInstructionFromIndex(LRStart.getDefIndex()); + if (DefMI && DefMI != CopyMI) { + int DeadIdx = DefMI->findRegisterDefOperandIdx(li.reg); + if (DeadIdx != -1) + DefMI->getOperand(DeadIdx).setIsDead(); + else + DefMI->addOperand(MachineOperand::CreateReg(li.reg, + /*def*/true, /*implicit*/true, /*kill*/false, /*dead*/true)); + LRStart = LRStart.getNextSlot(); + } +} + +/// ShortenDeadCopySrcLiveRange - Shorten a live range as it's artificially +/// extended by a dead copy. Mark the last use (if any) of the val# as kill as +/// ends the live range there. If there isn't another use, then this live range +/// is dead. Return true if live interval is removed. +bool +SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li, + MachineInstr *CopyMI) { + SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI); + if (CopyIdx == SlotIndex()) { + // FIXME: special case: function live in. It can be a general case if the + // first instruction index starts at > 0 value. + assert(TargetRegisterInfo::isPhysicalRegister(li.reg)); + // Live-in to the function but dead. Remove it from entry live-in set. + if (mf_->begin()->isLiveIn(li.reg)) + mf_->begin()->removeLiveIn(li.reg); + if (const LiveRange *LR = li.getLiveRangeContaining(CopyIdx)) + removeRange(li, LR->start, LR->end, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); + } + + LiveInterval::iterator LR = + li.FindLiveRangeContaining(CopyIdx.getPrevIndex().getStoreIndex()); + if (LR == li.end()) + // Livein but defined by a phi. + return false; + + SlotIndex RemoveStart = LR->start; + SlotIndex RemoveEnd = CopyIdx.getStoreIndex(); + if (LR->end > RemoveEnd) + // More uses past this copy? Nothing to do. + return false; + + // If there is a last use in the same bb, we can't remove the live range. + // Shorten the live interval and return. + MachineBasicBlock *CopyMBB = CopyMI->getParent(); + if (TrimLiveIntervalToLastUse(CopyIdx, CopyMBB, li, LR)) + return false; + + // There are other kills of the val#. Nothing to do. + if (!li.isOnlyLROfValNo(LR)) + return false; + + MachineBasicBlock *StartMBB = li_->getMBBFromIndex(RemoveStart); + if (!isSameOrFallThroughBB(StartMBB, CopyMBB, tii_)) + // If the live range starts in another mbb and the copy mbb is not a fall + // through mbb, then we can only cut the range from the beginning of the + // copy mbb. + RemoveStart = li_->getMBBStartIdx(CopyMBB).getNextIndex().getBaseIndex(); + + if (LR->valno->def == RemoveStart) { + // If the def MI defines the val# and this copy is the only kill of the + // val#, then propagate the dead marker. + PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_); + ++numDeadValNo; + } + + removeRange(li, RemoveStart, RemoveEnd, li_, tri_); + return removeIntervalIfEmpty(li, li_, tri_); +} + + +/// isWinToJoinCrossClass - Return true if it's profitable to coalesce +/// two virtual registers from different register classes. +bool +SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC) { + unsigned NewRCCount = allocatableRCRegs_[NewRC].count(); + // This heuristics is good enough in practice, but it's obviously not *right*. + // 4 is a magic number that works well enough for x86, ARM, etc. It filter + // out all but the most restrictive register classes. + if (NewRCCount > 4 || + // Early exit if the function is fairly small, coalesce aggressively if + // that's the case. For really special register classes with 3 or + // fewer registers, be a bit more careful. + (li_->getFuncInstructionCount() / NewRCCount) < 8) + return true; + LiveInterval &SrcInt = li_->getInterval(SrcReg); + LiveInterval &DstInt = li_->getInterval(DstReg); + unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); + unsigned DstSize = li_->getApproximateInstructionCount(DstInt); + if (SrcSize <= NewRCCount && DstSize <= NewRCCount) + return true; + // Estimate *register use density*. If it doubles or more, abort. + unsigned SrcUses = std::distance(mri_->use_nodbg_begin(SrcReg), + mri_->use_nodbg_end()); + unsigned DstUses = std::distance(mri_->use_nodbg_begin(DstReg), + mri_->use_nodbg_end()); + unsigned NewUses = SrcUses + DstUses; + unsigned NewSize = SrcSize + DstSize; + if (SrcRC != NewRC && SrcSize > NewRCCount) { + unsigned SrcRCCount = allocatableRCRegs_[SrcRC].count(); + if (NewUses*SrcSize*SrcRCCount > 2*SrcUses*NewSize*NewRCCount) + return false; + } + if (DstRC != NewRC && DstSize > NewRCCount) { + unsigned DstRCCount = allocatableRCRegs_[DstRC].count(); + if (NewUses*DstSize*DstRCCount > 2*DstUses*NewSize*NewRCCount) + return false; + } + return true; +} + + +/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, +/// which are the src/dst of the copy instruction CopyMI. This returns true +/// if the copy was successfully coalesced away. If it is not currently +/// possible to coalesce this interval, but it may be possible if other +/// things get coalesced, then it returns true by reference in 'Again'. +bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { + MachineInstr *CopyMI = TheCopy.MI; + + Again = false; + if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) + return false; // Already done. + + DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); + + CoalescerPair CP(*tii_, *tri_); + if (!CP.setRegisters(CopyMI)) { + DEBUG(dbgs() << "\tNot coalescable.\n"); + return false; + } + + // If they are already joined we continue. + if (CP.getSrcReg() == CP.getDstReg()) { + DEBUG(dbgs() << "\tCopy already coalesced.\n"); + return false; // Not coalescable. + } + + if (DisablePhysicalJoin && CP.isPhys()) { + DEBUG(dbgs() << "\tPhysical joins disabled.\n"); + return false; + } + + DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_)); + + // Enforce policies. + if (CP.isPhys()) { + DEBUG(dbgs() <<" with physreg " << PrintReg(CP.getDstReg(), tri_) << "\n"); + // Only coalesce to allocatable physreg. + if (!li_->isAllocatable(CP.getDstReg())) { + DEBUG(dbgs() << "\tRegister is an unallocatable physreg.\n"); + return false; // Not coalescable. + } + } else { + DEBUG(dbgs() << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) + << " to " << CP.getNewRC()->getName() << "\n"); + + // Avoid constraining virtual register regclass too much. + if (CP.isCrossClass()) { + if (DisableCrossClassJoin) { + DEBUG(dbgs() << "\tCross-class joins disabled.\n"); + return false; + } + if (!isWinToJoinCrossClass(CP.getSrcReg(), CP.getDstReg(), + mri_->getRegClass(CP.getSrcReg()), + mri_->getRegClass(CP.getDstReg()), + CP.getNewRC())) { + DEBUG(dbgs() << "\tAvoid coalescing to constrained register class: " + << CP.getNewRC()->getName() << ".\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } + + // When possible, let DstReg be the larger interval. + if (!CP.getSubIdx() && li_->getInterval(CP.getSrcReg()).ranges.size() > + li_->getInterval(CP.getDstReg()).ranges.size()) + CP.flip(); + } + + // We need to be careful about coalescing a source physical register with a + // virtual register. Once the coalescing is done, it cannot be broken and + // these are not spillable! If the destination interval uses are far away, + // think twice about coalescing them! + // FIXME: Why are we skipping this test for partial copies? + // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. + if (!CP.isPartial() && CP.isPhys()) { + LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); + + // Don't join with physregs that have a ridiculous number of live + // ranges. The data structure performance is really bad when that + // happens. + if (li_->hasInterval(CP.getDstReg()) && + li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { + ++numAborts; + DEBUG(dbgs() + << "\tPhysical register live interval too complicated, abort!\n"); + return false; + } + + const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + if (Length > Threshold) { + // Before giving up coalescing, if definition of source is defined by + // trivial computation, try rematerializing it. + if (!CP.isFlipped() && + ReMaterializeTrivialDef(JoinVInt, true, CP.getDstReg(), 0, CopyMI)) + return true; + + ++numAborts; + DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + } + + // Okay, attempt to join these two intervals. On failure, this returns false. + // Otherwise, if one of the intervals being joined is a physreg, this method + // always canonicalizes DstInt to be it. The output "SrcInt" will not have + // been modified, so we can use this information below to update aliases. + if (!JoinIntervals(CP)) { + // Coalescing failed. + + // If definition of source is defined by trivial computation, try + // rematerializing it. + if (!CP.isFlipped() && + ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + CP.getDstReg(), 0, CopyMI)) + return true; + + // If we can eliminate the copy without merging the live ranges, do so now. + if (!CP.isPartial()) { + if (AdjustCopiesBackFrom(CP, CopyMI) || + RemoveCopyByCommutingDef(CP, CopyMI)) { + JoinedCopies.insert(CopyMI); + DEBUG(dbgs() << "\tTrivial!\n"); + return true; + } + } + + // Otherwise, we are unable to join the intervals. + DEBUG(dbgs() << "\tInterference!\n"); + Again = true; // May be possible to coalesce later. + return false; + } + + // Coalescing to a virtual register that is of a sub-register class of the + // other. Make sure the resulting register is set to the right register class. + if (CP.isCrossClass()) { + ++numCrossRCs; + mri_->setRegClass(CP.getDstReg(), CP.getNewRC()); + } + + // Remember to delete the copy instruction. + JoinedCopies.insert(CopyMI); + + UpdateRegDefsUses(CP); + + // If we have extended the live range of a physical register, make sure we + // update live-in lists as well. + if (CP.isPhys()) { + SmallVector BlockSeq; + // JoinIntervals invalidates the VNInfos in SrcInt, but we only need the + // ranges for this, and they are preserved. + LiveInterval &SrcInt = li_->getInterval(CP.getSrcReg()); + for (LiveInterval::const_iterator I = SrcInt.begin(), E = SrcInt.end(); + I != E; ++I ) { + li_->findLiveInMBBs(I->start, I->end, BlockSeq); + for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { + MachineBasicBlock &block = *BlockSeq[idx]; + if (!block.isLiveIn(CP.getDstReg())) + block.addLiveIn(CP.getDstReg()); + } + BlockSeq.clear(); + } + } + + // SrcReg is guarateed to be the register whose live interval that is + // being merged. + li_->removeInterval(CP.getSrcReg()); + + // Update regalloc hint. + tri_->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *mf_); + + DEBUG({ + LiveInterval &DstInt = li_->getInterval(CP.getDstReg()); + dbgs() << "\tJoined. Result = "; + DstInt.print(dbgs(), tri_); + dbgs() << "\n"; + }); + + ++numJoins; + return true; +} + +/// ComputeUltimateVN - Assuming we are going to join two live intervals, +/// compute what the resultant value numbers for each value in the input two +/// ranges will be. This is complicated by copies between the two which can +/// and will commonly cause multiple value numbers to be merged into one. +/// +/// VN is the value number that we're trying to resolve. InstDefiningValue +/// keeps track of the new InstDefiningValue assignment for the result +/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of +/// whether a value in this or other is a copy from the opposite set. +/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have +/// already been assigned. +/// +/// ThisFromOther[x] - If x is defined as a copy from the other interval, this +/// contains the value number the copy is from. +/// +static unsigned ComputeUltimateVN(VNInfo *VNI, + SmallVector &NewVNInfo, + DenseMap &ThisFromOther, + DenseMap &OtherFromThis, + SmallVector &ThisValNoAssignments, + SmallVector &OtherValNoAssignments) { + unsigned VN = VNI->id; + + // If the VN has already been computed, just return it. + if (ThisValNoAssignments[VN] >= 0) + return ThisValNoAssignments[VN]; + assert(ThisValNoAssignments[VN] != -2 && "Cyclic value numbers"); + + // If this val is not a copy from the other val, then it must be a new value + // number in the destination. + DenseMap::iterator I = ThisFromOther.find(VNI); + if (I == ThisFromOther.end()) { + NewVNInfo.push_back(VNI); + return ThisValNoAssignments[VN] = NewVNInfo.size()-1; + } + VNInfo *OtherValNo = I->second; + + // Otherwise, this *is* a copy from the RHS. If the other side has already + // been computed, return it. + if (OtherValNoAssignments[OtherValNo->id] >= 0) + return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo->id]; + + // Mark this value number as currently being computed, then ask what the + // ultimate value # of the other value is. + ThisValNoAssignments[VN] = -2; + unsigned UltimateVN = + ComputeUltimateVN(OtherValNo, NewVNInfo, OtherFromThis, ThisFromOther, + OtherValNoAssignments, ThisValNoAssignments); + return ThisValNoAssignments[VN] = UltimateVN; +} + +/// JoinIntervals - Attempt to join these two intervals. On failure, this +/// returns false. +bool SimpleRegisterCoalescing::JoinIntervals(CoalescerPair &CP) { + LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); + DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); + + // If a live interval is a physical register, check for interference with any + // aliases. The interference check implemented here is a bit more conservative + // than the full interfeence check below. We allow overlapping live ranges + // only when one is a copy of the other. + if (CP.isPhys()) { + for (const unsigned *AS = tri_->getAliasSet(CP.getDstReg()); *AS; ++AS){ + if (!li_->hasInterval(*AS)) + continue; + const LiveInterval &LHS = li_->getInterval(*AS); + LiveInterval::const_iterator LI = LHS.begin(); + for (LiveInterval::const_iterator RI = RHS.begin(), RE = RHS.end(); + RI != RE; ++RI) { + LI = std::lower_bound(LI, LHS.end(), RI->start); + // Does LHS have an overlapping live range starting before RI? + if ((LI != LHS.begin() && LI[-1].end > RI->start) && + (RI->start != RI->valno->def || + !CP.isCoalescable(li_->getInstructionFromIndex(RI->start)))) { + DEBUG({ + dbgs() << "\t\tInterference from alias: "; + LHS.print(dbgs(), tri_); + dbgs() << "\n\t\tOverlap at " << RI->start << " and no copy.\n"; + }); + return false; + } + + // Check that LHS ranges beginning in this range are copies. + for (; LI != LHS.end() && LI->start < RI->end; ++LI) { + if (LI->start != LI->valno->def || + !CP.isCoalescable(li_->getInstructionFromIndex(LI->start))) { + DEBUG({ + dbgs() << "\t\tInterference from alias: "; + LHS.print(dbgs(), tri_); + dbgs() << "\n\t\tDef at " << LI->start << " is not a copy.\n"; + }); + return false; + } + } + } + } + } + + // Compute the final value assignment, assuming that the live ranges can be + // coalesced. + SmallVector LHSValNoAssignments; + SmallVector RHSValNoAssignments; + DenseMap LHSValsDefinedFromRHS; + DenseMap RHSValsDefinedFromLHS; + SmallVector NewVNInfo; + + LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); + DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); + + // Loop over the value numbers of the LHS, seeing if any are defined from + // the RHS. + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? + continue; + + // Never join with a register that has EarlyClobber redefs. + if (VNI->hasRedefByEC()) + return false; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + if (!CP.isCoalescable(VNI->getCopy())) + continue; + + // Figure out the value # from the RHS. + LiveRange *lr = RHS.getLiveRangeContaining(VNI->def.getPrevSlot()); + // The copy could be to an aliased physreg. + if (!lr) continue; + LHSValsDefinedFromRHS[VNI] = lr->valno; + } + + // Loop over the value numbers of the RHS, seeing if any are defined from + // the LHS. + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + if (VNI->isUnused() || !VNI->isDefByCopy()) // Src not defined by a copy? + continue; + + // Never join with a register that has EarlyClobber redefs. + if (VNI->hasRedefByEC()) + return false; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + if (!CP.isCoalescable(VNI->getCopy())) + continue; + + // Figure out the value # from the LHS. + LiveRange *lr = LHS.getLiveRangeContaining(VNI->def.getPrevSlot()); + // The copy could be to an aliased physreg. + if (!lr) continue; + RHSValsDefinedFromLHS[VNI] = lr->valno; + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + NewVNInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); + + for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (LHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + ComputeUltimateVN(VNI, NewVNInfo, + LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, + LHSValNoAssignments, RHSValNoAssignments); + } + for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end(); + i != e; ++i) { + VNInfo *VNI = *i; + unsigned VN = VNI->id; + if (RHSValNoAssignments[VN] >= 0 || VNI->isUnused()) + continue; + // If this value number isn't a copy from the LHS, it's a new number. + if (RHSValsDefinedFromLHS.find(VNI) == RHSValsDefinedFromLHS.end()) { + NewVNInfo.push_back(VNI); + RHSValNoAssignments[VN] = NewVNInfo.size()-1; + continue; + } + + ComputeUltimateVN(VNI, NewVNInfo, + RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, + RHSValNoAssignments, LHSValNoAssignments); + } + + // Armed with the mappings of LHS/RHS values to ultimate values, walk the + // interval lists to see if these intervals are coalescable. + LiveInterval::const_iterator I = LHS.begin(); + LiveInterval::const_iterator IE = LHS.end(); + LiveInterval::const_iterator J = RHS.begin(); + LiveInterval::const_iterator JE = RHS.end(); + + // Skip ahead until the first place of potential sharing. + if (I != IE && J != JE) { + if (I->start < J->start) { + I = std::upper_bound(I, IE, J->start); + if (I != LHS.begin()) --I; + } else if (J->start < I->start) { + J = std::upper_bound(J, JE, I->start); + if (J != RHS.begin()) --J; + } + } + + while (I != IE && J != JE) { + // Determine if these two live ranges overlap. + bool Overlaps; + if (I->start < J->start) { + Overlaps = I->end > J->start; + } else { + Overlaps = J->end > I->start; + } + + // If so, check value # info to determine if they are really different. + if (Overlaps) { + // If the live range overlap will map to the same value number in the + // result liverange, we can still coalesce them. If not, we can't. + if (LHSValNoAssignments[I->valno->id] != + RHSValNoAssignments[J->valno->id]) + return false; + // If it's re-defined by an early clobber somewhere in the live range, + // then conservatively abort coalescing. + if (NewVNInfo[LHSValNoAssignments[I->valno->id]]->hasRedefByEC()) + return false; + } + + if (I->end < J->end) + ++I; + else + ++J; + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = LHSValsDefinedFromRHS.begin(), + E = LHSValsDefinedFromRHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned LHSValID = LHSValNoAssignments[VNI->id]; + if (VNI->hasPHIKill()) + NewVNInfo[LHSValID]->setHasPHIKill(true); + } + + // Update kill info. Some live ranges are extended due to copy coalescing. + for (DenseMap::iterator I = RHSValsDefinedFromLHS.begin(), + E = RHSValsDefinedFromLHS.end(); I != E; ++I) { + VNInfo *VNI = I->first; + unsigned RHSValID = RHSValNoAssignments[VNI->id]; + if (VNI->hasPHIKill()) + NewVNInfo[RHSValID]->setHasPHIKill(true); + } + + if (LHSValNoAssignments.empty()) + LHSValNoAssignments.push_back(-1); + if (RHSValNoAssignments.empty()) + RHSValNoAssignments.push_back(-1); + + // If we get here, we know that we can coalesce the live ranges. Ask the + // intervals to coalesce themselves now. + LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, + mri_); + return true; +} + +namespace { + // DepthMBBCompare - Comparison predicate that sort first based on the loop + // depth of the basic block (the unsigned), and then on the MBB number. + struct DepthMBBCompare { + typedef std::pair DepthMBBPair; + bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { + // Deeper loops first + if (LHS.first != RHS.first) + return LHS.first > RHS.first; + + // Prefer blocks that are more connected in the CFG. This takes care of + // the most difficult copies first while intervals are short. + unsigned cl = LHS.second->pred_size() + LHS.second->succ_size(); + unsigned cr = RHS.second->pred_size() + RHS.second->succ_size(); + if (cl != cr) + return cl > cr; + + // As a last resort, sort by block number. + return LHS.second->getNumber() < RHS.second->getNumber(); + } + }; +} + +void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain) { + DEBUG(dbgs() << MBB->getName() << ":\n"); + + SmallVector VirtCopies; + SmallVector PhysCopies; + SmallVector ImpDefCopies; + for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); + MII != E;) { + MachineInstr *Inst = MII++; + + // If this isn't a copy nor a extract_subreg, we can't join intervals. + unsigned SrcReg, DstReg; + if (Inst->isCopy()) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(1).getReg(); + } else if (Inst->isSubregToReg()) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(2).getReg(); + } else + continue; + + bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) + ImpDefCopies.push_back(CopyRec(Inst, 0)); + else if (SrcIsPhys || DstIsPhys) + PhysCopies.push_back(CopyRec(Inst, 0)); + else + VirtCopies.push_back(CopyRec(Inst, 0)); + } + + // Try coalescing implicit copies and insert_subreg first, + // followed by copies to / from physical registers, then finally copies + // from virtual registers to virtual registers. + for (unsigned i = 0, e = ImpDefCopies.size(); i != e; ++i) { + CopyRec &TheCopy = ImpDefCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = PhysCopies.size(); i != e; ++i) { + CopyRec &TheCopy = PhysCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } + for (unsigned i = 0, e = VirtCopies.size(); i != e; ++i) { + CopyRec &TheCopy = VirtCopies[i]; + bool Again = false; + if (!JoinCopy(TheCopy, Again)) + if (Again) + TryAgain.push_back(TheCopy); + } +} + +void SimpleRegisterCoalescing::joinIntervals() { + DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); + + std::vector TryAgainList; + if (loopInfo->empty()) { + // If there are no loops in the function, join intervals in function order. + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + I != E; ++I) + CopyCoalesceInMBB(I, TryAgainList); + } else { + // Otherwise, join intervals in inner loops before other intervals. + // Unfortunately we can't just iterate over loop hierarchy here because + // there may be more MBB's than BB's. Collect MBB's for sorting. + + // Join intervals in the function prolog first. We want to join physical + // registers with virtual registers before the intervals got too long. + std::vector > MBBs; + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ + MachineBasicBlock *MBB = I; + MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); + } + + // Sort by loop depth. + std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); + + // Finally, join intervals in loop nest order. + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) + CopyCoalesceInMBB(MBBs[i].second, TryAgainList); + } + + // Joining intervals can allow other intervals to be joined. Iteratively join + // until we make no progress. + bool ProgressMade = true; + while (ProgressMade) { + ProgressMade = false; + + for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { + CopyRec &TheCopy = TryAgainList[i]; + if (!TheCopy.MI) + continue; + + bool Again = false; + bool Success = JoinCopy(TheCopy, Again); + if (Success || !Again) { + TheCopy.MI = 0; // Mark this one as done. + ProgressMade = true; + } + } + } +} + +/// Return true if the two specified registers belong to different register +/// classes. The registers may be either phys or virt regs. +bool +SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, + unsigned RegB) const { + // Get the register classes for the first reg. + if (TargetRegisterInfo::isPhysicalRegister(RegA)) { + assert(TargetRegisterInfo::isVirtualRegister(RegB) && + "Shouldn't consider two physregs!"); + return !mri_->getRegClass(RegB)->contains(RegA); + } + + // Compare against the regclass for the second reg. + const TargetRegisterClass *RegClassA = mri_->getRegClass(RegA); + if (TargetRegisterInfo::isVirtualRegister(RegB)) { + const TargetRegisterClass *RegClassB = mri_->getRegClass(RegB); + return RegClassA != RegClassB; + } + return !RegClassA->contains(RegB); +} + +/// lastRegisterUse - Returns the last (non-debug) use of the specific register +/// between cycles Start and End or NULL if there are no uses. +MachineOperand * +SimpleRegisterCoalescing::lastRegisterUse(SlotIndex Start, + SlotIndex End, + unsigned Reg, + SlotIndex &UseIdx) const{ + UseIdx = SlotIndex(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + MachineOperand *LastUse = NULL; + for (MachineRegisterInfo::use_nodbg_iterator I = mri_->use_nodbg_begin(Reg), + E = mri_->use_nodbg_end(); I != E; ++I) { + MachineOperand &Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + if (UseMI->isIdentityCopy()) + continue; + SlotIndex Idx = li_->getInstructionIndex(UseMI); + if (Idx >= Start && Idx < End && (!UseIdx.isValid() || Idx >= UseIdx)) { + LastUse = &Use; + UseIdx = Idx.getUseIndex(); + } + } + return LastUse; + } + + SlotIndex s = Start; + SlotIndex e = End.getPrevSlot().getBaseIndex(); + while (e >= s) { + // Skip deleted instructions + MachineInstr *MI = li_->getInstructionFromIndex(e); + while (e != SlotIndex() && e.getPrevIndex() >= s && !MI) { + e = e.getPrevIndex(); + MI = li_->getInstructionFromIndex(e); + } + if (e < s || MI == NULL) + return NULL; + + // Ignore identity copies. + if (!MI->isIdentityCopy()) + for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { + MachineOperand &Use = MI->getOperand(i); + if (Use.isReg() && Use.isUse() && Use.getReg() && + tri_->regsOverlap(Use.getReg(), Reg)) { + UseIdx = e.getUseIndex(); + return &Use; + } + } + + e = e.getPrevIndex(); + } + + return NULL; +} + +void SimpleRegisterCoalescing::releaseMemory() { + JoinedCopies.clear(); + ReMatCopies.clear(); + ReMatDefs.clear(); +} + +bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + mri_ = &fn.getRegInfo(); + tm_ = &fn.getTarget(); + tri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + li_ = &getAnalysis(); + ldv_ = &getAnalysis(); + AA = &getAnalysis(); + loopInfo = &getAnalysis(); + + DEBUG(dbgs() << "********** SIMPLE REGISTER COALESCING **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'); + + if (VerifyCoalescing) + mf_->verify(this, "Before register coalescing"); + + for (TargetRegisterInfo::regclass_iterator I = tri_->regclass_begin(), + E = tri_->regclass_end(); I != E; ++I) + allocatableRCRegs_.insert(std::make_pair(*I, + tri_->getAllocatableSet(fn, *I))); + + // Join (coalesce) intervals if requested. + if (EnableJoining) { + joinIntervals(); + DEBUG({ + dbgs() << "********** INTERVALS POST JOINING **********\n"; + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); + I != E; ++I){ + I->second->print(dbgs(), tri_); + dbgs() << "\n"; + } + }); + } + + // Perform a final pass over the instructions and compute spill weights + // and remove identity moves. + SmallVector DeadDefs; + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ) { + MachineInstr *MI = mii; + if (JoinedCopies.count(MI)) { + // Delete all coalesced copies. + bool DoDelete = true; + assert(MI->isCopyLike() && "Unrecognized copy instruction"); + unsigned SrcReg = MI->getOperand(MI->isSubregToReg() ? 2 : 1).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && + MI->getNumOperands() > 2) + // Do not delete extract_subreg, insert_subreg of physical + // registers unless the definition is dead. e.g. + // %DO = INSERT_SUBREG %D0, %S0, 1 + // or else the scavenger may complain. LowerSubregs will + // delete them later. + DoDelete = false; + + if (MI->allDefsAreDead()) { + if (li_->hasInterval(SrcReg)) { + LiveInterval &li = li_->getInterval(SrcReg); + if (!ShortenDeadCopySrcLiveRange(li, MI)) + ShortenDeadCopyLiveRange(li, MI); + } + DoDelete = true; + } + if (!DoDelete) { + // We need the instruction to adjust liveness, so make it a KILL. + if (MI->isSubregToReg()) { + MI->RemoveOperand(3); + MI->RemoveOperand(1); + } + MI->setDesc(tii_->get(TargetOpcode::KILL)); + mii = llvm::next(mii); + } else { + li_->RemoveMachineInstrFromMaps(MI); + mii = mbbi->erase(mii); + ++numPeep; + } + continue; + } + + // Now check if this is a remat'ed def instruction which is now dead. + if (ReMatDefs.count(MI)) { + bool isDead = true; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + DeadDefs.push_back(Reg); + if (MO.isDead()) + continue; + if (TargetRegisterInfo::isPhysicalRegister(Reg) || + !mri_->use_nodbg_empty(Reg)) { + isDead = false; + break; + } + } + if (isDead) { + while (!DeadDefs.empty()) { + unsigned DeadDef = DeadDefs.back(); + DeadDefs.pop_back(); + RemoveDeadDef(li_->getInterval(DeadDef), MI); + } + li_->RemoveMachineInstrFromMaps(mii); + mii = mbbi->erase(mii); + continue; + } else + DeadDefs.clear(); + } + + // If the move will be an identity move delete it + if (MI->isIdentityCopy()) { + unsigned SrcReg = MI->getOperand(1).getReg(); + if (li_->hasInterval(SrcReg)) { + LiveInterval &RegInt = li_->getInterval(SrcReg); + // If def of this move instruction is dead, remove its live range + // from the destination register's live interval. + if (MI->allDefsAreDead()) { + if (!ShortenDeadCopySrcLiveRange(RegInt, MI)) + ShortenDeadCopyLiveRange(RegInt, MI); + } + } + li_->RemoveMachineInstrFromMaps(MI); + mii = mbbi->erase(mii); + ++numPeep; + continue; + } + + ++mii; + + // Check for now unnecessary kill flags. + if (li_->isNotInMIMap(MI)) continue; + SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isKill()) continue; + unsigned reg = MO.getReg(); + if (!reg || !li_->hasInterval(reg)) continue; + if (!li_->getInterval(reg).killedAt(DefIdx)) { + MO.setIsKill(false); + continue; + } + // When leaving a kill flag on a physreg, check if any subregs should + // remain alive. + if (!TargetRegisterInfo::isPhysicalRegister(reg)) + continue; + for (const unsigned *SR = tri_->getSubRegisters(reg); + unsigned S = *SR; ++SR) + if (li_->hasInterval(S) && li_->getInterval(S).liveAt(DefIdx)) + MI->addRegisterDefined(S, tri_); + } + } + } + + DEBUG(dump()); + DEBUG(ldv_->dump()); + if (VerifyCoalescing) + mf_->verify(this, "After register coalescing"); + return true; +} + +/// print - Implement the dump method. +void SimpleRegisterCoalescing::print(raw_ostream &O, const Module* m) const { + li_->print(O, m); +} + +RegisterCoalescer* llvm::createSimpleRegisterCoalescer() { + return new SimpleRegisterCoalescing(); +} + +// Make sure that anything that uses RegisterCoalescer pulls in this file... +DEFINING_FILE_FOR(SimpleRegisterCoalescing) diff --git a/final/lib/CodeGen/SimpleRegisterCoalescing.h b/final/lib/CodeGen/SimpleRegisterCoalescing.h new file mode 100644 index 00000000000..56703dfa2dd --- /dev/null +++ b/final/lib/CodeGen/SimpleRegisterCoalescing.h @@ -0,0 +1,193 @@ +//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple register copy coalescing phase. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H +#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + class SimpleRegisterCoalescing; + class LiveDebugVariables; + class TargetRegisterInfo; + class TargetInstrInfo; + class VirtRegMap; + class MachineLoopInfo; + + /// CopyRec - Representation for copy instructions in coalescer queue. + /// + struct CopyRec { + MachineInstr *MI; + unsigned LoopDepth; + CopyRec(MachineInstr *mi, unsigned depth) + : MI(mi), LoopDepth(depth) {} + }; + + class SimpleRegisterCoalescing : public MachineFunctionPass, + public RegisterCoalescer { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveDebugVariables *ldv_; + const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; + + DenseMap allocatableRCRegs_; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass(ID) { + initializeSimpleRegisterCoalescingPass(*PassRegistry::getPassRegistry()); + } + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + bool coalesceFunction(MachineFunction &mf, RegallocQuery &) { + // This runs as an independent pass, so don't do anything. + return false; + } + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coalesced away. If it is not currently + /// possible to coalesce this interval, but it may be possible if other + /// things get coalesced, then it returns true by reference in 'Again'. + bool JoinCopy(CopyRec &TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. The output "SrcInt" will not have been modified, so we can + /// use this information below to update aliases. + bool JoinIntervals(CoalescerPair &CP); + + /// Return true if the two specified registers belong to different register + /// classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); + + /// TrimLiveIntervalToLastUse - If there is a last use in the same basic + /// block as the copy instruction, trim the ive interval to the last use + /// and return true. + bool TrimLiveIntervalToLastUse(SlotIndex CopyIdx, + MachineBasicBlock *CopyMBB, + LiveInterval &li, const LiveRange *LR); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial + /// computation, replace the copy by rematerialize the definition. + /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, + unsigned DstReg, unsigned DstSubIdx, + MachineInstr *CopyMI); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(const CoalescerPair &CP); + + /// ShortenDeadCopyLiveRange - Shorten a live range defined by a dead copy. + /// Return true if live interval is removed. + bool ShortenDeadCopyLiveRange(LiveInterval &li, MachineInstr *CopyMI); + + /// ShortenDeadCopyLiveRange - Shorten a live range as it's artificially + /// extended by a dead copy. Mark the last use (if any) of the val# as kill + /// as ends the live range there. If there isn't another use, then this + /// live range is dead. Return true if live interval is removed. + bool ShortenDeadCopySrcLiveRange(LiveInterval &li, MachineInstr *CopyMI); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the + /// VNInfo copy flag for DstReg and all aliases. + void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End or NULL if there are no uses. + MachineOperand *lastRegisterUse(SlotIndex Start, SlotIndex End, + unsigned Reg, SlotIndex &LastUseIdx) const; + }; + +} // End llvm namespace + +#endif diff --git a/final/lib/CodeGen/SjLjEHPrepare.cpp b/final/lib/CodeGen/SjLjEHPrepare.cpp new file mode 100644 index 00000000000..13e1454fa5f --- /dev/null +++ b/final/lib/CodeGen/SjLjEHPrepare.cpp @@ -0,0 +1,592 @@ +//===- SjLjEHPass.cpp - Eliminate Invoke & Unwind instructions -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This transformation is designed for use by code generators which use SjLj +// based exception handling. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "sjljehprepare" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" +#include +using namespace llvm; + +STATISTIC(NumInvokes, "Number of invokes replaced"); +STATISTIC(NumUnwinds, "Number of unwinds replaced"); +STATISTIC(NumSpilled, "Number of registers live across unwind edges"); + +namespace { + class SjLjEHPass : public FunctionPass { + + const TargetLowering *TLI; + + const Type *FunctionContextTy; + Constant *RegisterFn; + Constant *UnregisterFn; + Constant *BuiltinSetjmpFn; + Constant *FrameAddrFn; + Constant *StackAddrFn; + Constant *StackRestoreFn; + Constant *LSDAAddrFn; + Value *PersonalityFn; + Constant *SelectorFn; + Constant *ExceptionFn; + Constant *CallSiteFn; + Constant *DispatchSetupFn; + + Value *CallSite; + public: + static char ID; // Pass identification, replacement for typeid + explicit SjLjEHPass(const TargetLowering *tli = NULL) + : FunctionPass(ID), TLI(tli) { } + bool doInitialization(Module &M); + bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { } + const char *getPassName() const { + return "SJLJ Exception Handling preparation"; + } + + private: + void insertCallSiteStore(Instruction *I, int Number, Value *CallSite); + void markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite, + SwitchInst *CatchSwitch); + void splitLiveRangesAcrossInvokes(SmallVector &Invokes); + bool insertSjLjEHSupport(Function &F); + }; +} // end anonymous namespace + +char SjLjEHPass::ID = 0; + +// Public Interface To the SjLjEHPass pass. +FunctionPass *llvm::createSjLjEHPass(const TargetLowering *TLI) { + return new SjLjEHPass(TLI); +} +// doInitialization - Set up decalarations and types needed to process +// exceptions. +bool SjLjEHPass::doInitialization(Module &M) { + // Build the function context structure. + // builtin_setjmp uses a five word jbuf + const Type *VoidPtrTy = + Type::getInt8PtrTy(M.getContext()); + const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + FunctionContextTy = + StructType::get(M.getContext(), + VoidPtrTy, // __prev + Int32Ty, // call_site + ArrayType::get(Int32Ty, 4), // __data + VoidPtrTy, // __personality + VoidPtrTy, // __lsda + ArrayType::get(VoidPtrTy, 5), // __jbuf + NULL); + RegisterFn = M.getOrInsertFunction("_Unwind_SjLj_Register", + Type::getVoidTy(M.getContext()), + PointerType::getUnqual(FunctionContextTy), + (Type *)0); + UnregisterFn = + M.getOrInsertFunction("_Unwind_SjLj_Unregister", + Type::getVoidTy(M.getContext()), + PointerType::getUnqual(FunctionContextTy), + (Type *)0); + FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress); + StackAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::stacksave); + StackRestoreFn = Intrinsic::getDeclaration(&M, Intrinsic::stackrestore); + BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp); + LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); + SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector); + ExceptionFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_exception); + CallSiteFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_callsite); + DispatchSetupFn + = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_dispatch_setup); + PersonalityFn = 0; + + return true; +} + +/// insertCallSiteStore - Insert a store of the call-site value to the +/// function context +void SjLjEHPass::insertCallSiteStore(Instruction *I, int Number, + Value *CallSite) { + ConstantInt *CallSiteNoC = ConstantInt::get(Type::getInt32Ty(I->getContext()), + Number); + // Insert a store of the call-site number + new StoreInst(CallSiteNoC, CallSite, true, I); // volatile +} + +/// markInvokeCallSite - Insert code to mark the call_site for this invoke +void SjLjEHPass::markInvokeCallSite(InvokeInst *II, int InvokeNo, + Value *CallSite, + SwitchInst *CatchSwitch) { + ConstantInt *CallSiteNoC= ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo); + // The runtime comes back to the dispatcher with the call_site - 1 in + // the context. Odd, but there it is. + ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()), + InvokeNo - 1); + + // If the unwind edge has phi nodes, split the edge. + if (isa(II->getUnwindDest()->begin())) { + SplitCriticalEdge(II, 1, this); + + // If there are any phi nodes left, they must have a single predecessor. + while (PHINode *PN = dyn_cast(II->getUnwindDest()->begin())) { + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + PN->eraseFromParent(); + } + } + + // Insert the store of the call site value + insertCallSiteStore(II, InvokeNo, CallSite); + + // Record the call site value for the back end so it stays associated with + // the invoke. + CallInst::Create(CallSiteFn, CallSiteNoC, "", II); + + // Add a switch case to our unwind block. + CatchSwitch->addCase(SwitchValC, II->getUnwindDest()); + // We still want this to look like an invoke so we emit the LSDA properly, + // so we don't transform the invoke into a call here. +} + +/// MarkBlocksLiveIn - Insert BB and all of its predescessors into LiveBBs until +/// we reach blocks we've already seen. +static void MarkBlocksLiveIn(BasicBlock *BB, std::set &LiveBBs) { + if (!LiveBBs.insert(BB).second) return; // already been here. + + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + MarkBlocksLiveIn(*PI, LiveBBs); +} + +/// splitLiveRangesAcrossInvokes - Each value that is live across an unwind edge +/// we spill into a stack location, guaranteeing that there is nothing live +/// across the unwind edge. This process also splits all critical edges +/// coming out of invoke's. +/// FIXME: Move this function to a common utility file (Local.cpp?) so +/// both SjLj and LowerInvoke can use it. +void SjLjEHPass:: +splitLiveRangesAcrossInvokes(SmallVector &Invokes) { + // First step, split all critical edges from invoke instructions. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + InvokeInst *II = Invokes[i]; + SplitCriticalEdge(II, 0, this); + SplitCriticalEdge(II, 1, this); + assert(!isa(II->getNormalDest()) && + !isa(II->getUnwindDest()) && + "critical edge splitting left single entry phi nodes?"); + } + + Function *F = Invokes.back()->getParent()->getParent(); + + // To avoid having to handle incoming arguments specially, we lower each arg + // to a copy instruction in the entry block. This ensures that the argument + // value itself cannot be live across the entry block. + BasicBlock::iterator AfterAllocaInsertPt = F->begin()->begin(); + while (isa(AfterAllocaInsertPt) && + isa(cast(AfterAllocaInsertPt)->getArraySize())) + ++AfterAllocaInsertPt; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI) { + const Type *Ty = AI->getType(); + // Aggregate types can't be cast, but are legal argument types, so we have + // to handle them differently. We use an extract/insert pair as a + // lightweight method to achieve the same goal. + if (isa(Ty) || isa(Ty) || isa(Ty)) { + Instruction *EI = ExtractValueInst::Create(AI, 0, "",AfterAllocaInsertPt); + Instruction *NI = InsertValueInst::Create(AI, EI, 0); + NI->insertAfter(EI); + AI->replaceAllUsesWith(NI); + // Set the operand of the instructions back to the AllocaInst. + EI->setOperand(0, AI); + NI->setOperand(0, AI); + } else { + // This is always a no-op cast because we're casting AI to AI->getType() + // so src and destination types are identical. BitCast is the only + // possibility. + CastInst *NC = new BitCastInst( + AI, AI->getType(), AI->getName()+".tmp", AfterAllocaInsertPt); + AI->replaceAllUsesWith(NC); + // Set the operand of the cast instruction back to the AllocaInst. + // Normally it's forbidden to replace a CastInst's operand because it + // could cause the opcode to reflect an illegal conversion. However, + // we're replacing it here with the same value it was constructed with. + // We do this because the above replaceAllUsesWith() clobbered the + // operand, but we want this one to remain. + NC->setOperand(0, AI); + } + } + + // Finally, scan the code looking for instructions with bad live ranges. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { + // Ignore obvious cases we don't have to handle. In particular, most + // instructions either have no uses or only have a single use inside the + // current block. Ignore them quickly. + Instruction *Inst = II; + if (Inst->use_empty()) continue; + if (Inst->hasOneUse() && + cast(Inst->use_back())->getParent() == BB && + !isa(Inst->use_back())) continue; + + // If this is an alloca in the entry block, it's not a real register + // value. + if (AllocaInst *AI = dyn_cast(Inst)) + if (isa(AI->getArraySize()) && BB == F->begin()) + continue; + + // Avoid iterator invalidation by copying users to a temporary vector. + SmallVector Users; + for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); + UI != E; ++UI) { + Instruction *User = cast(*UI); + if (User->getParent() != BB || isa(User)) + Users.push_back(User); + } + + // Find all of the blocks that this value is live in. + std::set LiveBBs; + LiveBBs.insert(Inst->getParent()); + while (!Users.empty()) { + Instruction *U = Users.back(); + Users.pop_back(); + + if (!isa(U)) { + MarkBlocksLiveIn(U->getParent(), LiveBBs); + } else { + // Uses for a PHI node occur in their predecessor block. + PHINode *PN = cast(U); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == Inst) + MarkBlocksLiveIn(PN->getIncomingBlock(i), LiveBBs); + } + } + + // Now that we know all of the blocks that this thing is live in, see if + // it includes any of the unwind locations. + bool NeedsSpill = false; + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) { + BasicBlock *UnwindBlock = Invokes[i]->getUnwindDest(); + if (UnwindBlock != BB && LiveBBs.count(UnwindBlock)) { + NeedsSpill = true; + } + } + + // If we decided we need a spill, do it. + // FIXME: Spilling this way is overkill, as it forces all uses of + // the value to be reloaded from the stack slot, even those that aren't + // in the unwind blocks. We should be more selective. + if (NeedsSpill) { + ++NumSpilled; + DemoteRegToStack(*Inst, true); + } + } +} + +bool SjLjEHPass::insertSjLjEHSupport(Function &F) { + SmallVector Returns; + SmallVector Unwinds; + SmallVector Invokes; + + // Look through the terminators of the basic blocks to find invokes, returns + // and unwinds. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + // Remember all return instructions in case we insert an invoke into this + // function. + Returns.push_back(RI); + } else if (InvokeInst *II = dyn_cast(BB->getTerminator())) { + Invokes.push_back(II); + } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { + Unwinds.push_back(UI); + } + } + + NumInvokes += Invokes.size(); + NumUnwinds += Unwinds.size(); + + // If we don't have any invokes, there's nothing to do. + if (Invokes.empty()) return false; + + // Find the eh.selector.*, eh.exception and alloca calls. + // + // Remember any allocas() that aren't in the entry block, as the + // jmpbuf saved SP will need to be updated for them. + // + // We'll use the first eh.selector to determine the right personality + // function to use. For SJLJ, we always use the same personality for the + // whole function, not on a per-selector basis. + // FIXME: That's a bit ugly. Better way? + SmallVector EH_Selectors; + SmallVector EH_Exceptions; + SmallVector JmpbufUpdatePoints; + + // Note: Skip the entry block since there's nothing there that interests + // us. eh.selector and eh.exception shouldn't ever be there, and we + // want to disregard any allocas that are there. + for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) { + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { + if (CallInst *CI = dyn_cast(I)) { + if (CI->getCalledFunction() == SelectorFn) { + if (!PersonalityFn) PersonalityFn = CI->getArgOperand(1); + EH_Selectors.push_back(CI); + } else if (CI->getCalledFunction() == ExceptionFn) { + EH_Exceptions.push_back(CI); + } else if (CI->getCalledFunction() == StackRestoreFn) { + JmpbufUpdatePoints.push_back(CI); + } + } else if (AllocaInst *AI = dyn_cast(I)) { + JmpbufUpdatePoints.push_back(AI); + } + } + } + + // If we don't have any eh.selector calls, we can't determine the personality + // function. Without a personality function, we can't process exceptions. + if (!PersonalityFn) return false; + + // We have invokes, so we need to add register/unregister calls to get this + // function onto the global unwind stack. + // + // First thing we need to do is scan the whole function for values that are + // live across unwind edges. Each value that is live across an unwind edge we + // spill into a stack location, guaranteeing that there is nothing live across + // the unwind edge. This process also splits all critical edges coming out of + // invoke's. + splitLiveRangesAcrossInvokes(Invokes); + + BasicBlock *EntryBB = F.begin(); + // Create an alloca for the incoming jump buffer ptr and the new jump buffer + // that needs to be restored on all exits from the function. This is an + // alloca because the value needs to be added to the global context list. + unsigned Align = 4; // FIXME: Should be a TLI check? + AllocaInst *FunctionContext = + new AllocaInst(FunctionContextTy, 0, Align, + "fcn_context", F.begin()->begin()); + + Value *Idxs[2]; + const Type *Int32Ty = Type::getInt32Ty(F.getContext()); + Value *Zero = ConstantInt::get(Int32Ty, 0); + // We need to also keep around a reference to the call_site field + Idxs[0] = Zero; + Idxs[1] = ConstantInt::get(Int32Ty, 1); + CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "call_site", + EntryBB->getTerminator()); + + // The exception selector comes back in context->data[1] + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "fc_data", + EntryBB->getTerminator()); + Idxs[1] = ConstantInt::get(Int32Ty, 1); + Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + "exc_selector_gep", + EntryBB->getTerminator()); + // The exception value comes back in context->data[0] + Idxs[1] = Zero; + Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, Idxs+2, + "exception_gep", + EntryBB->getTerminator()); + + // The result of the eh.selector call will be replaced with a a reference to + // the selector value returned in the function context. We leave the selector + // itself so the EH analysis later can use it. + for (int i = 0, e = EH_Selectors.size(); i < e; ++i) { + CallInst *I = EH_Selectors[i]; + Value *SelectorVal = new LoadInst(SelectorAddr, "select_val", true, I); + I->replaceAllUsesWith(SelectorVal); + } + + // eh.exception calls are replaced with references to the proper location in + // the context. Unlike eh.selector, the eh.exception calls are removed + // entirely. + for (int i = 0, e = EH_Exceptions.size(); i < e; ++i) { + CallInst *I = EH_Exceptions[i]; + // Possible for there to be duplicates, so check to make sure the + // instruction hasn't already been removed. + if (!I->getParent()) continue; + Value *Val = new LoadInst(ExceptionAddr, "exception", true, I); + const Type *Ty = Type::getInt8PtrTy(F.getContext()); + Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I); + + I->replaceAllUsesWith(Val); + I->eraseFromParent(); + } + + // The entry block changes to have the eh.sjlj.setjmp, with a conditional + // branch to a dispatch block for non-zero returns. If we return normally, + // we're not handling an exception and just register the function context and + // continue. + + // Create the dispatch block. The dispatch block is basically a big switch + // statement that goes to all of the invoke landing pads. + BasicBlock *DispatchBlock = + BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); + + // Add a call to dispatch_setup at the start of the dispatch block. This is + // expanded to any target-specific setup that needs to be done. + Value *SetupArg = + CastInst::Create(Instruction::BitCast, FunctionContext, + Type::getInt8PtrTy(F.getContext()), "", + DispatchBlock); + CallInst::Create(DispatchSetupFn, SetupArg, "", DispatchBlock); + + // Insert a load of the callsite in the dispatch block, and a switch on its + // value. By default, we go to a block that just does an unwind (which is the + // correct action for a standard call). + BasicBlock *UnwindBlock = + BasicBlock::Create(F.getContext(), "unwindbb", &F); + Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock)); + + Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, + DispatchBlock); + SwitchInst *DispatchSwitch = + SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(), + DispatchBlock); + // Split the entry block to insert the conditional branch for the setjmp. + BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), + "eh.sjlj.setjmp.cont"); + + // Populate the Function Context + // 1. LSDA address + // 2. Personality function address + // 3. jmpbuf (save SP, FP and call eh.sjlj.setjmp) + + // LSDA address + Idxs[0] = Zero; + Idxs[1] = ConstantInt::get(Int32Ty, 4); + Value *LSDAFieldPtr = + GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "lsda_gep", + EntryBB->getTerminator()); + Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", + EntryBB->getTerminator()); + new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); + + Idxs[1] = ConstantInt::get(Int32Ty, 3); + Value *PersonalityFieldPtr = + GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "lsda_gep", + EntryBB->getTerminator()); + new StoreInst(PersonalityFn, PersonalityFieldPtr, true, + EntryBB->getTerminator()); + + // Save the frame pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 5); + Value *JBufPtr + = GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2, + "jbuf_gep", + EntryBB->getTerminator()); + Idxs[1] = ConstantInt::get(Int32Ty, 0); + Value *FramePtr = + GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_fp_gep", + EntryBB->getTerminator()); + + Value *Val = CallInst::Create(FrameAddrFn, + ConstantInt::get(Int32Ty, 0), + "fp", + EntryBB->getTerminator()); + new StoreInst(Val, FramePtr, true, EntryBB->getTerminator()); + + // Save the stack pointer. + Idxs[1] = ConstantInt::get(Int32Ty, 2); + Value *StackPtr = + GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_sp_gep", + EntryBB->getTerminator()); + + Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); + new StoreInst(Val, StackPtr, true, EntryBB->getTerminator()); + + // Call the setjmp instrinsic. It fills in the rest of the jmpbuf. + Value *SetjmpArg = + CastInst::Create(Instruction::BitCast, JBufPtr, + Type::getInt8PtrTy(F.getContext()), "", + EntryBB->getTerminator()); + Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, + "dispatch", + EntryBB->getTerminator()); + // check the return value of the setjmp. non-zero goes to dispatcher. + Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), + ICmpInst::ICMP_EQ, DispatchVal, Zero, + "notunwind"); + // Nuke the uncond branch. + EntryBB->getTerminator()->eraseFromParent(); + + // Put in a new condbranch in its place. + BranchInst::Create(ContBlock, DispatchBlock, IsNormal, EntryBB); + + // Register the function context and make sure it's known to not throw + CallInst *Register = + CallInst::Create(RegisterFn, FunctionContext, "", + ContBlock->getTerminator()); + Register->setDoesNotThrow(); + + // At this point, we are all set up, update the invoke instructions to mark + // their call_site values, and fill in the dispatch switch accordingly. + for (unsigned i = 0, e = Invokes.size(); i != e; ++i) + markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch); + + // Mark call instructions that aren't nounwind as no-action (call_site == + // -1). Skip the entry block, as prior to then, no function context has been + // created for this function and any unexpected exceptions thrown will go + // directly to the caller's context, which is what we want anyway, so no need + // to do anything here. + for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) { + for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I) + if (CallInst *CI = dyn_cast(I)) { + // Ignore calls to the EH builtins (eh.selector, eh.exception) + Constant *Callee = CI->getCalledFunction(); + if (Callee != SelectorFn && Callee != ExceptionFn + && !CI->doesNotThrow()) + insertCallSiteStore(CI, -1, CallSite); + } + } + + // Replace all unwinds with a branch to the unwind handler. + // ??? Should this ever happen with sjlj exceptions? + for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { + BranchInst::Create(UnwindBlock, Unwinds[i]); + Unwinds[i]->eraseFromParent(); + } + + // Following any allocas not in the entry block, update the saved SP in the + // jmpbuf to the new value. + for (unsigned i = 0, e = JmpbufUpdatePoints.size(); i != e; ++i) { + Instruction *AI = JmpbufUpdatePoints[i]; + Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp"); + StackAddr->insertAfter(AI); + Instruction *StoreStackAddr = new StoreInst(StackAddr, StackPtr, true); + StoreStackAddr->insertAfter(StackAddr); + } + + // Finally, for any returns from this function, if this function contains an + // invoke, add a call to unregister the function context. + for (unsigned i = 0, e = Returns.size(); i != e; ++i) + CallInst::Create(UnregisterFn, FunctionContext, "", Returns[i]); + + return true; +} + +bool SjLjEHPass::runOnFunction(Function &F) { + bool Res = insertSjLjEHSupport(F); + return Res; +} diff --git a/final/lib/CodeGen/SlotIndexes.cpp b/final/lib/CodeGen/SlotIndexes.cpp new file mode 100644 index 00000000000..c0ae34301dc --- /dev/null +++ b/final/lib/CodeGen/SlotIndexes.cpp @@ -0,0 +1,181 @@ +//===-- SlotIndexes.cpp - Slot Indexes Pass ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "slotindexes" + +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" + +using namespace llvm; + +char SlotIndexes::ID = 0; +INITIALIZE_PASS(SlotIndexes, "slotindexes", + "Slot index numbering", false, false) + +STATISTIC(NumLocalRenum, "Number of local renumberings"); +STATISTIC(NumGlobalRenum, "Number of global renumberings"); + +void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { + au.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(au); +} + +void SlotIndexes::releaseMemory() { + mi2iMap.clear(); + mbb2IdxMap.clear(); + idx2MBBMap.clear(); + clearList(); +} + +bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { + + // Compute numbering as follows: + // Grab an iterator to the start of the index list. + // Iterate over all MBBs, and within each MBB all MIs, keeping the MI + // iterator in lock-step (though skipping it over indexes which have + // null pointers in the instruction field). + // At each iteration assert that the instruction pointed to in the index + // is the same one pointed to by the MI iterator. This + + // FIXME: This can be simplified. The mi2iMap_, Idx2MBBMap, etc. should + // only need to be set up once after the first numbering is computed. + + mf = &fn; + initList(); + + // Check that the list contains only the sentinal. + assert(indexListHead->getNext() == 0 && + "Index list non-empty at initial numbering?"); + assert(idx2MBBMap.empty() && + "Index -> MBB mapping non-empty at initial numbering?"); + assert(mbb2IdxMap.empty() && + "MBB -> Index mapping non-empty at initial numbering?"); + assert(mi2iMap.empty() && + "MachineInstr -> Index mapping non-empty at initial numbering?"); + + functionSize = 0; + unsigned index = 0; + + push_back(createEntry(0, index)); + + // Iterate over the function. + for (MachineFunction::iterator mbbItr = mf->begin(), mbbEnd = mf->end(); + mbbItr != mbbEnd; ++mbbItr) { + MachineBasicBlock *mbb = &*mbbItr; + + // Insert an index for the MBB start. + SlotIndex blockStartIndex(back(), SlotIndex::LOAD); + + for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end(); + miItr != miEnd; ++miItr) { + MachineInstr *mi = miItr; + if (mi->isDebugValue()) + continue; + + // Insert a store index for the instr. + push_back(createEntry(mi, index += SlotIndex::InstrDist)); + + // Save this base index in the maps. + mi2iMap.insert(std::make_pair(mi, SlotIndex(back(), SlotIndex::LOAD))); + + ++functionSize; + } + + // We insert one blank instructions between basic blocks. + push_back(createEntry(0, index += SlotIndex::InstrDist)); + + SlotIndex blockEndIndex(back(), SlotIndex::LOAD); + mbb2IdxMap.insert( + std::make_pair(mbb, std::make_pair(blockStartIndex, blockEndIndex))); + + idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, mbb)); + } + + // Sort the Idx2MBBMap + std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); + + DEBUG(dump()); + + // And we're done! + return false; +} + +void SlotIndexes::renumberIndexes() { + // Renumber updates the index of every element of the index list. + DEBUG(dbgs() << "\n*** Renumbering SlotIndexes ***\n"); + ++NumGlobalRenum; + + unsigned index = 0; + + for (IndexListEntry *curEntry = front(); curEntry != getTail(); + curEntry = curEntry->getNext()) { + curEntry->setIndex(index); + index += SlotIndex::InstrDist; + } +} + +// Renumber indexes locally after curEntry was inserted, but failed to get a new +// index. +void SlotIndexes::renumberIndexes(IndexListEntry *curEntry) { + // Number indexes with half the default spacing so we can catch up quickly. + const unsigned Space = SlotIndex::InstrDist/2; + assert((Space & 3) == 0 && "InstrDist must be a multiple of 2*NUM"); + + IndexListEntry *start = curEntry->getPrev(); + unsigned index = start->getIndex(); + IndexListEntry *tail = getTail(); + do { + curEntry->setIndex(index += Space); + curEntry = curEntry->getNext(); + // If the next index is bigger, we have caught up. + } while (curEntry != tail && curEntry->getIndex() <= index); + + DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << start->getIndex() << '-' + << index << " ***\n"); + ++NumLocalRenum; +} + + +void SlotIndexes::dump() const { + for (const IndexListEntry *itr = front(); itr != getTail(); + itr = itr->getNext()) { + dbgs() << itr->getIndex() << " "; + + if (itr->getInstr() != 0) { + dbgs() << *itr->getInstr(); + } else { + dbgs() << "\n"; + } + } + + for (MBB2IdxMap::const_iterator itr = mbb2IdxMap.begin(); + itr != mbb2IdxMap.end(); ++itr) { + dbgs() << "MBB " << itr->first->getNumber() << " (" << itr->first << ") - [" + << itr->second.first << ", " << itr->second.second << "]\n"; + } +} + +// Print a SlotIndex to a raw_ostream. +void SlotIndex::print(raw_ostream &os) const { + if (isValid()) + os << entry().getIndex() << "LudS"[getSlot()]; + else + os << "invalid"; +} + +// Dump a SlotIndex to stderr. +void SlotIndex::dump() const { + print(dbgs()); + dbgs() << "\n"; +} + diff --git a/final/lib/CodeGen/SpillPlacement.cpp b/final/lib/CodeGen/SpillPlacement.cpp new file mode 100644 index 00000000000..57951ed8068 --- /dev/null +++ b/final/lib/CodeGen/SpillPlacement.cpp @@ -0,0 +1,324 @@ +//===-- SpillPlacement.cpp - Optimal Spill Code Placement -----------------===// +// +// 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 spill code placement analysis. +// +// Each edge bundle corresponds to a node in a Hopfield network. Constraints on +// basic blocks are weighted by the block frequency and added to become the node +// bias. +// +// Transparent basic blocks have the variable live through, but don't care if it +// is spilled or in a register. These blocks become connections in the Hopfield +// network, again weighted by block frequency. +// +// The Hopfield network minimizes (possibly locally) its energy function: +// +// E = -sum_n V_n * ( B_n + sum_{n, m linked by b} V_m * F_b ) +// +// The energy function represents the expected spill code execution frequency, +// or the cost of spilling. This is a Lyapunov function which never increases +// when a node is updated. It is guaranteed to converge to a local minimum. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "spillplacement" +#include "SpillPlacement.h" +#include "llvm/CodeGen/EdgeBundles.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +char SpillPlacement::ID = 0; +INITIALIZE_PASS_BEGIN(SpillPlacement, "spill-code-placement", + "Spill Code Placement Analysis", true, true) +INITIALIZE_PASS_DEPENDENCY(EdgeBundles) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(SpillPlacement, "spill-code-placement", + "Spill Code Placement Analysis", true, true) + +char &llvm::SpillPlacementID = SpillPlacement::ID; + +void SpillPlacement::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +/// Node - Each edge bundle corresponds to a Hopfield node. +/// +/// The node contains precomputed frequency data that only depends on the CFG, +/// but Bias and Links are computed each time placeSpills is called. +/// +/// The node Value is positive when the variable should be in a register. The +/// value can change when linked nodes change, but convergence is very fast +/// because all weights are positive. +/// +struct SpillPlacement::Node { + /// Frequency - Total block frequency feeding into[0] or out of[1] the bundle. + /// Ideally, these two numbers should be identical, but inaccuracies in the + /// block frequency estimates means that we need to normalize ingoing and + /// outgoing frequencies separately so they are commensurate. + float Frequency[2]; + + /// Bias - Normalized contributions from non-transparent blocks. + /// A bundle connected to a MustSpill block has a huge negative bias, + /// otherwise it is a number in the range [-2;2]. + float Bias; + + /// Value - Output value of this node computed from the Bias and links. + /// This is always in the range [-1;1]. A positive number means the variable + /// should go in a register through this bundle. + float Value; + + typedef SmallVector, 4> LinkVector; + + /// Links - (Weight, BundleNo) for all transparent blocks connecting to other + /// bundles. The weights are all positive and add up to at most 2, weights + /// from ingoing and outgoing nodes separately add up to a most 1. The weight + /// sum can be less than 2 when the variable is not live into / out of some + /// connected basic blocks. + LinkVector Links; + + /// preferReg - Return true when this node prefers to be in a register. + bool preferReg() const { + // Undecided nodes (Value==0) go on the stack. + return Value > 0; + } + + /// mustSpill - Return True if this node is so biased that it must spill. + bool mustSpill() const { + // Actually, we must spill if Bias < sum(weights). + // It may be worth it to compute the weight sum here? + return Bias < -2.0f; + } + + /// Node - Create a blank Node. + Node() { + Frequency[0] = Frequency[1] = 0; + } + + /// clear - Reset per-query data, but preserve frequencies that only depend on + // the CFG. + void clear() { + Bias = Value = 0; + Links.clear(); + } + + /// addLink - Add a link to bundle b with weight w. + /// out=0 for an ingoing link, and 1 for an outgoing link. + void addLink(unsigned b, float w, bool out) { + // Normalize w relative to all connected blocks from that direction. + w /= Frequency[out]; + + // There can be multiple links to the same bundle, add them up. + for (LinkVector::iterator I = Links.begin(), E = Links.end(); I != E; ++I) + if (I->second == b) { + I->first += w; + return; + } + // This must be the first link to b. + Links.push_back(std::make_pair(w, b)); + } + + /// addBias - Bias this node from an ingoing[0] or outgoing[1] link. + void addBias(float w, bool out) { + // Normalize w relative to all connected blocks from that direction. + w /= Frequency[out]; + Bias += w; + } + + /// update - Recompute Value from Bias and Links. Return true when node + /// preference changes. + bool update(const Node nodes[]) { + // Compute the weighted sum of inputs. + float Sum = Bias; + for (LinkVector::iterator I = Links.begin(), E = Links.end(); I != E; ++I) + Sum += I->first * nodes[I->second].Value; + + // The weighted sum is going to be in the range [-2;2]. Ideally, we should + // simply set Value = sign(Sum), but we will add a dead zone around 0 for + // two reasons: + // 1. It avoids arbitrary bias when all links are 0 as is possible during + // initial iterations. + // 2. It helps tame rounding errors when the links nominally sum to 0. + const float Thres = 1e-4f; + bool Before = preferReg(); + if (Sum < -Thres) + Value = -1; + else if (Sum > Thres) + Value = 1; + else + Value = 0; + return Before != preferReg(); + } +}; + +bool SpillPlacement::runOnMachineFunction(MachineFunction &mf) { + MF = &mf; + bundles = &getAnalysis(); + loops = &getAnalysis(); + + assert(!nodes && "Leaking node array"); + nodes = new Node[bundles->getNumBundles()]; + + // Compute total ingoing and outgoing block frequencies for all bundles. + BlockFrequency.resize(mf.getNumBlockIDs()); + for (MachineFunction::iterator I = mf.begin(), E = mf.end(); I != E; ++I) { + float Freq = LiveIntervals::getSpillWeight(true, false, + loops->getLoopDepth(I)); + unsigned Num = I->getNumber(); + BlockFrequency[Num] = Freq; + nodes[bundles->getBundle(Num, 1)].Frequency[0] += Freq; + nodes[bundles->getBundle(Num, 0)].Frequency[1] += Freq; + } + + // We never change the function. + return false; +} + +void SpillPlacement::releaseMemory() { + delete[] nodes; + nodes = 0; +} + +/// activate - mark node n as active if it wasn't already. +void SpillPlacement::activate(unsigned n) { + if (ActiveNodes->test(n)) + return; + ActiveNodes->set(n); + nodes[n].clear(); +} + + +/// prepareNodes - Compute node biases and weights from a set of constraints. +/// Set a bit in NodeMask for each active node. +void SpillPlacement:: +prepareNodes(const SmallVectorImpl &LiveBlocks) { + for (SmallVectorImpl::const_iterator I = LiveBlocks.begin(), + E = LiveBlocks.end(); I != E; ++I) { + float Freq = getBlockFrequency(I->Number); + + // Is this a transparent block? Link ingoing and outgoing bundles. + if (I->Entry == DontCare && I->Exit == DontCare) { + unsigned ib = bundles->getBundle(I->Number, 0); + unsigned ob = bundles->getBundle(I->Number, 1); + + // Ignore self-loops. + if (ib == ob) + continue; + activate(ib); + activate(ob); + nodes[ib].addLink(ob, Freq, 1); + nodes[ob].addLink(ib, Freq, 0); + continue; + } + + // This block is not transparent, but it can still add bias. + const float Bias[] = { + 0, // DontCare, + 1, // PrefReg, + -1, // PrefSpill + -HUGE_VALF // MustSpill + }; + + // Live-in to block? + if (I->Entry != DontCare) { + unsigned ib = bundles->getBundle(I->Number, 0); + activate(ib); + nodes[ib].addBias(Freq * Bias[I->Entry], 1); + } + + // Live-out from block? + if (I->Exit != DontCare) { + unsigned ob = bundles->getBundle(I->Number, 1); + activate(ob); + nodes[ob].addBias(Freq * Bias[I->Exit], 0); + } + } +} + +/// iterate - Repeatedly update the Hopfield nodes until stability or the +/// maximum number of iterations is reached. +/// @param Linked - Numbers of linked nodes that need updating. +void SpillPlacement::iterate(const SmallVectorImpl &Linked) { + if (Linked.empty()) + return; + + // Run up to 10 iterations. The edge bundle numbering is closely related to + // basic block numbering, so there is a strong tendency towards chains of + // linked nodes with sequential numbers. By scanning the linked nodes + // backwards and forwards, we make it very likely that a single node can + // affect the entire network in a single iteration. That means very fast + // convergence, usually in a single iteration. + for (unsigned iteration = 0; iteration != 10; ++iteration) { + // Scan backwards, skipping the last node which was just updated. + bool Changed = false; + for (SmallVectorImpl::const_reverse_iterator I = + llvm::next(Linked.rbegin()), E = Linked.rend(); I != E; ++I) { + unsigned n = *I; + bool C = nodes[n].update(nodes); + Changed |= C; + } + if (!Changed) + return; + + // Scan forwards, skipping the first node which was just updated. + Changed = false; + for (SmallVectorImpl::const_iterator I = + llvm::next(Linked.begin()), E = Linked.end(); I != E; ++I) { + unsigned n = *I; + bool C = nodes[n].update(nodes); + Changed |= C; + } + if (!Changed) + return; + } +} + +bool +SpillPlacement::placeSpills(const SmallVectorImpl &LiveBlocks, + BitVector &RegBundles) { + // Reuse RegBundles as our ActiveNodes vector. + ActiveNodes = &RegBundles; + ActiveNodes->clear(); + ActiveNodes->resize(bundles->getNumBundles()); + + // Compute active nodes, links and biases. + prepareNodes(LiveBlocks); + + // Update all active nodes, and find the ones that are actually linked to + // something so their value may change when iterating. + SmallVector Linked; + for (int n = RegBundles.find_first(); n>=0; n = RegBundles.find_next(n)) { + nodes[n].update(nodes); + // A node that must spill, or a node without any links is not going to + // change its value ever again, so exclude it from iterations. + if (!nodes[n].Links.empty() && !nodes[n].mustSpill()) + Linked.push_back(n); + } + + // Iterate the network to convergence. + iterate(Linked); + + // Write preferences back to RegBundles. + bool Perfect = true; + for (int n = RegBundles.find_first(); n>=0; n = RegBundles.find_next(n)) + if (!nodes[n].preferReg()) { + RegBundles.reset(n); + Perfect = false; + } + return Perfect; +} diff --git a/final/lib/CodeGen/SpillPlacement.h b/final/lib/CodeGen/SpillPlacement.h new file mode 100644 index 00000000000..b0135cbc365 --- /dev/null +++ b/final/lib/CodeGen/SpillPlacement.h @@ -0,0 +1,113 @@ +//===-- SpillPlacement.h - Optimal Spill Code Placement --------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This analysis computes the optimal spill code placement between basic blocks. +// +// The runOnMachineFunction() method only precomputes some profiling information +// about the CFG. The real work is done by placeSpills() which is called by the +// register allocator. +// +// Given a variable that is live across multiple basic blocks, and given +// constraints on the basic blocks where the variable is live, determine which +// edge bundles should have the variable in a register and which edge bundles +// should have the variable in a stack slot. +// +// The returned bit vector can be used to place optimal spill code at basic +// block entries and exits. Spill code placement inside a basic block is not +// considered. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPILLPLACEMENT_H +#define LLVM_CODEGEN_SPILLPLACEMENT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class BitVector; +class EdgeBundles; +class MachineBasicBlock; +class MachineLoopInfo; + +class SpillPlacement : public MachineFunctionPass { + struct Node; + const MachineFunction *MF; + const EdgeBundles *bundles; + const MachineLoopInfo *loops; + Node *nodes; + + // Nodes that are active in the current computation. Owned by the placeSpills + // caller. + BitVector *ActiveNodes; + + // Block frequencies are computed once. Indexed by block number. + SmallVector BlockFrequency; + +public: + static char ID; // Pass identification, replacement for typeid. + + SpillPlacement() : MachineFunctionPass(ID), nodes(0) {} + ~SpillPlacement() { releaseMemory(); } + + /// BorderConstraint - A basic block has separate constraints for entry and + /// exit. + enum BorderConstraint { + DontCare, ///< Block doesn't care / variable not live. + PrefReg, ///< Block entry/exit prefers a register. + PrefSpill, ///< Block entry/exit prefers a stack slot. + MustSpill ///< A register is impossible, variable must be spilled. + }; + + /// BlockConstraint - Entry and exit constraints for a basic block. + struct BlockConstraint { + unsigned Number; ///< Basic block number (from MBB::getNumber()). + BorderConstraint Entry : 8; ///< Constraint on block entry. + BorderConstraint Exit : 8; ///< Constraint on block exit. + }; + + /// placeSpills - Compute the optimal spill code placement given the + /// constraints. No MustSpill constraints will be violated, and the smallest + /// possible number of PrefX constraints will be violated, weighted by + /// expected execution frequencies. + /// @param LiveBlocks Constraints for blocks that have the variable live in or + /// live out. DontCare/DontCare means the variable is live + /// through the block. DontCare/X means the variable is live + /// out, but not live in. + /// @param RegBundles Bit vector to receive the edge bundles where the + /// variable should be kept in a register. Each bit + /// corresponds to an edge bundle, a set bit means the + /// variable should be kept in a register through the + /// bundle. A clear bit means the variable should be + /// spilled. + /// @return True if a perfect solution was found, allowing the variable to be + /// in a register through all relevant bundles. + bool placeSpills(const SmallVectorImpl &LiveBlocks, + BitVector &RegBundles); + + /// getBlockFrequency - Return the estimated block execution frequency per + /// function invocation. + float getBlockFrequency(unsigned Number) const { + return BlockFrequency[Number]; + } + +private: + virtual bool runOnMachineFunction(MachineFunction&); + virtual void getAnalysisUsage(AnalysisUsage&) const; + virtual void releaseMemory(); + + void activate(unsigned); + void prepareNodes(const SmallVectorImpl&); + void iterate(const SmallVectorImpl&); +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/CodeGen/Spiller.cpp b/final/lib/CodeGen/Spiller.cpp new file mode 100644 index 00000000000..fd385824aff --- /dev/null +++ b/final/lib/CodeGen/Spiller.cpp @@ -0,0 +1,243 @@ +//===-- llvm/CodeGen/Spiller.cpp - Spiller -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "spiller" + +#include "Spiller.h" +#include "VirtRegMap.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +namespace { + enum SpillerName { trivial, standard, inline_ }; +} + +static cl::opt +spillerOpt("spiller", + cl::desc("Spiller to use: (default: standard)"), + cl::Prefix, + cl::values(clEnumVal(trivial, "trivial spiller"), + clEnumVal(standard, "default spiller"), + clEnumValN(inline_, "inline", "inline spiller"), + clEnumValEnd), + cl::init(standard)); + +// Spiller virtual destructor implementation. +Spiller::~Spiller() {} + +namespace { + +/// Utility class for spillers. +class SpillerBase : public Spiller { +protected: + MachineFunctionPass *pass; + MachineFunction *mf; + VirtRegMap *vrm; + LiveIntervals *lis; + MachineFrameInfo *mfi; + MachineRegisterInfo *mri; + const TargetInstrInfo *tii; + const TargetRegisterInfo *tri; + + /// Construct a spiller base. + SpillerBase(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm) + : pass(&pass), mf(&mf), vrm(&vrm) + { + lis = &pass.getAnalysis(); + mfi = mf.getFrameInfo(); + mri = &mf.getRegInfo(); + tii = mf.getTarget().getInstrInfo(); + tri = mf.getTarget().getRegisterInfo(); + } + + /// Add spill ranges for every use/def of the live interval, inserting loads + /// immediately before each use, and stores after each def. No folding or + /// remat is attempted. + void trivialSpillEverywhere(LiveInterval *li, + SmallVectorImpl &newIntervals) { + DEBUG(dbgs() << "Spilling everywhere " << *li << "\n"); + + assert(li->weight != HUGE_VALF && + "Attempting to spill already spilled value."); + + assert(!TargetRegisterInfo::isStackSlot(li->reg) && + "Trying to spill a stack slot."); + + DEBUG(dbgs() << "Trivial spill everywhere of reg" << li->reg << "\n"); + + const TargetRegisterClass *trc = mri->getRegClass(li->reg); + unsigned ss = vrm->assignVirt2StackSlot(li->reg); + + // Iterate over reg uses/defs. + for (MachineRegisterInfo::reg_iterator + regItr = mri->reg_begin(li->reg); regItr != mri->reg_end();) { + + // Grab the use/def instr. + MachineInstr *mi = &*regItr; + + DEBUG(dbgs() << " Processing " << *mi); + + // Step regItr to the next use/def instr. + do { + ++regItr; + } while (regItr != mri->reg_end() && (&*regItr == mi)); + + // Collect uses & defs for this instr. + SmallVector indices; + bool hasUse = false; + bool hasDef = false; + for (unsigned i = 0; i != mi->getNumOperands(); ++i) { + MachineOperand &op = mi->getOperand(i); + if (!op.isReg() || op.getReg() != li->reg) + continue; + hasUse |= mi->getOperand(i).isUse(); + hasDef |= mi->getOperand(i).isDef(); + indices.push_back(i); + } + + // Create a new vreg & interval for this instr. + unsigned newVReg = mri->createVirtualRegister(trc); + vrm->grow(); + vrm->assignVirt2StackSlot(newVReg, ss); + LiveInterval *newLI = &lis->getOrCreateInterval(newVReg); + newLI->weight = HUGE_VALF; + + // Update the reg operands & kill flags. + for (unsigned i = 0; i < indices.size(); ++i) { + unsigned mopIdx = indices[i]; + MachineOperand &mop = mi->getOperand(mopIdx); + mop.setReg(newVReg); + if (mop.isUse() && !mi->isRegTiedToDefOperand(mopIdx)) { + mop.setIsKill(true); + } + } + assert(hasUse || hasDef); + + // Insert reload if necessary. + MachineBasicBlock::iterator miItr(mi); + if (hasUse) { + tii->loadRegFromStackSlot(*mi->getParent(), miItr, newVReg, ss, trc, + tri); + MachineInstr *loadInstr(prior(miItr)); + SlotIndex loadIndex = + lis->InsertMachineInstrInMaps(loadInstr).getDefIndex(); + vrm->addSpillSlotUse(ss, loadInstr); + SlotIndex endIndex = loadIndex.getNextIndex(); + VNInfo *loadVNI = + newLI->getNextValue(loadIndex, 0, lis->getVNInfoAllocator()); + newLI->addRange(LiveRange(loadIndex, endIndex, loadVNI)); + } + + // Insert store if necessary. + if (hasDef) { + tii->storeRegToStackSlot(*mi->getParent(), llvm::next(miItr), newVReg, + true, ss, trc, tri); + MachineInstr *storeInstr(llvm::next(miItr)); + SlotIndex storeIndex = + lis->InsertMachineInstrInMaps(storeInstr).getDefIndex(); + vrm->addSpillSlotUse(ss, storeInstr); + SlotIndex beginIndex = storeIndex.getPrevIndex(); + VNInfo *storeVNI = + newLI->getNextValue(beginIndex, 0, lis->getVNInfoAllocator()); + newLI->addRange(LiveRange(beginIndex, storeIndex, storeVNI)); + } + + newIntervals.push_back(newLI); + } + } +}; + +} // end anonymous namespace + +namespace { + +/// Spills any live range using the spill-everywhere method with no attempt at +/// folding. +class TrivialSpiller : public SpillerBase { +public: + + TrivialSpiller(MachineFunctionPass &pass, MachineFunction &mf, + VirtRegMap &vrm) + : SpillerBase(pass, mf, vrm) {} + + void spill(LiveInterval *li, + SmallVectorImpl &newIntervals, + const SmallVectorImpl &) { + // Ignore spillIs - we don't use it. + trivialSpillEverywhere(li, newIntervals); + } +}; + +} // end anonymous namespace + +namespace { + +/// Falls back on LiveIntervals::addIntervalsForSpills. +class StandardSpiller : public Spiller { +protected: + MachineFunction *mf; + LiveIntervals *lis; + LiveStacks *lss; + MachineLoopInfo *loopInfo; + VirtRegMap *vrm; +public: + StandardSpiller(MachineFunctionPass &pass, MachineFunction &mf, + VirtRegMap &vrm) + : mf(&mf), + lis(&pass.getAnalysis()), + lss(&pass.getAnalysis()), + loopInfo(pass.getAnalysisIfAvailable()), + vrm(&vrm) {} + + /// Falls back on LiveIntervals::addIntervalsForSpills. + void spill(LiveInterval *li, + SmallVectorImpl &newIntervals, + const SmallVectorImpl &spillIs) { + std::vector added = + lis->addIntervalsForSpills(*li, spillIs, loopInfo, *vrm); + newIntervals.insert(newIntervals.end(), added.begin(), added.end()); + + // Update LiveStacks. + int SS = vrm->getStackSlot(li->reg); + if (SS == VirtRegMap::NO_STACK_SLOT) + return; + const TargetRegisterClass *RC = mf->getRegInfo().getRegClass(li->reg); + LiveInterval &SI = lss->getOrCreateInterval(SS, RC); + if (!SI.hasAtLeastOneValue()) + SI.getNextValue(SlotIndex(), 0, lss->getVNInfoAllocator()); + SI.MergeRangesInAsValue(*li, SI.getValNumInfo(0)); + } +}; + +} // end anonymous namespace + +llvm::Spiller* llvm::createSpiller(MachineFunctionPass &pass, + MachineFunction &mf, + VirtRegMap &vrm) { + switch (spillerOpt) { + default: assert(0 && "unknown spiller"); + case trivial: return new TrivialSpiller(pass, mf, vrm); + case standard: return new StandardSpiller(pass, mf, vrm); + case inline_: return createInlineSpiller(pass, mf, vrm); + } +} diff --git a/final/lib/CodeGen/Spiller.h b/final/lib/CodeGen/Spiller.h new file mode 100644 index 00000000000..f017583494e --- /dev/null +++ b/final/lib/CodeGen/Spiller.h @@ -0,0 +1,56 @@ +//===-- llvm/CodeGen/Spiller.h - Spiller -*- C++ -*------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPILLER_H +#define LLVM_CODEGEN_SPILLER_H + +namespace llvm { + + class LiveInterval; + class MachineFunction; + class MachineFunctionPass; + class SlotIndex; + template class SmallVectorImpl; + class VirtRegMap; + + /// Spiller interface. + /// + /// Implementations are utility classes which insert spill or remat code on + /// demand. + class Spiller { + public: + virtual ~Spiller() = 0; + + /// spill - Spill the given live interval. The method used will depend on + /// the Spiller implementation selected. + /// + /// @param li The live interval to be spilled. + /// @param spillIs A list of intervals that are about to be spilled, + /// and so cannot be used for remat etc. + /// @param newIntervals The newly created intervals will be appended here. + virtual void spill(LiveInterval *li, + SmallVectorImpl &newIntervals, + const SmallVectorImpl &spillIs) = 0; + + }; + + /// Create and return a spiller object, as specified on the command line. + Spiller* createSpiller(MachineFunctionPass &pass, + MachineFunction &mf, + VirtRegMap &vrm); + + /// Create and return a spiller that will insert spill code directly instead + /// of deferring though VirtRegMap. + Spiller *createInlineSpiller(MachineFunctionPass &pass, + MachineFunction &mf, + VirtRegMap &vrm); + +} + +#endif diff --git a/final/lib/CodeGen/SplitKit.cpp b/final/lib/CodeGen/SplitKit.cpp new file mode 100644 index 00000000000..c4ae8c474c5 --- /dev/null +++ b/final/lib/CodeGen/SplitKit.cpp @@ -0,0 +1,921 @@ +//===---------- SplitKit.cpp - Toolkit for splitting live ranges ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the SplitAnalysis class as well as mutator functions for +// live range splitting. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "regalloc" +#include "SplitKit.h" +#include "LiveRangeEdit.h" +#include "VirtRegMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +static cl::opt +AllowSplit("spiller-splits-edges", + cl::desc("Allow critical edge splitting during spilling")); + +STATISTIC(NumFinished, "Number of splits finished"); +STATISTIC(NumSimple, "Number of splits that were simple"); + +//===----------------------------------------------------------------------===// +// Split Analysis +//===----------------------------------------------------------------------===// + +SplitAnalysis::SplitAnalysis(const VirtRegMap &vrm, + const LiveIntervals &lis, + const MachineLoopInfo &mli) + : MF(vrm.getMachineFunction()), + VRM(vrm), + LIS(lis), + Loops(mli), + TII(*MF.getTarget().getInstrInfo()), + CurLI(0) {} + +void SplitAnalysis::clear() { + UseSlots.clear(); + UsingInstrs.clear(); + UsingBlocks.clear(); + LiveBlocks.clear(); + CurLI = 0; +} + +bool SplitAnalysis::canAnalyzeBranch(const MachineBasicBlock *MBB) { + MachineBasicBlock *T, *F; + SmallVector Cond; + return !TII.AnalyzeBranch(const_cast(*MBB), T, F, Cond); +} + +/// analyzeUses - Count instructions, basic blocks, and loops using CurLI. +void SplitAnalysis::analyzeUses() { + const MachineRegisterInfo &MRI = MF.getRegInfo(); + for (MachineRegisterInfo::reg_iterator I = MRI.reg_begin(CurLI->reg), + E = MRI.reg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + if (MO.isUse() && MO.isUndef()) + continue; + MachineInstr *MI = MO.getParent(); + if (MI->isDebugValue() || !UsingInstrs.insert(MI)) + continue; + UseSlots.push_back(LIS.getInstructionIndex(MI).getDefIndex()); + MachineBasicBlock *MBB = MI->getParent(); + UsingBlocks[MBB]++; + } + array_pod_sort(UseSlots.begin(), UseSlots.end()); + + // Compute per-live block info. + if (!calcLiveBlockInfo()) { + // FIXME: calcLiveBlockInfo found inconsistencies in the live range. + // I am looking at you, SimpleRegisterCoalescing! + DEBUG(dbgs() << "*** Fixing inconsistent live interval! ***\n"); + const_cast(LIS) + .shrinkToUses(const_cast(CurLI)); + LiveBlocks.clear(); + bool fixed = calcLiveBlockInfo(); + (void)fixed; + assert(fixed && "Couldn't fix broken live interval"); + } + + DEBUG(dbgs() << " counted " + << UsingInstrs.size() << " instrs, " + << UsingBlocks.size() << " blocks.\n"); +} + +/// calcLiveBlockInfo - Fill the LiveBlocks array with information about blocks +/// where CurLI is live. +bool SplitAnalysis::calcLiveBlockInfo() { + if (CurLI->empty()) + return true; + + LiveInterval::const_iterator LVI = CurLI->begin(); + LiveInterval::const_iterator LVE = CurLI->end(); + + SmallVectorImpl::const_iterator UseI, UseE; + UseI = UseSlots.begin(); + UseE = UseSlots.end(); + + // Loop over basic blocks where CurLI is live. + MachineFunction::iterator MFI = LIS.getMBBFromIndex(LVI->start); + for (;;) { + BlockInfo BI; + BI.MBB = MFI; + tie(BI.Start, BI.Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB); + + // The last split point is the latest possible insertion point that dominates + // all successor blocks. If interference reaches LastSplitPoint, it is not + // possible to insert a split or reload that makes CurLI live in the + // outgoing bundle. + MachineBasicBlock::iterator LSP = LIS.getLastSplitPoint(*CurLI, BI.MBB); + if (LSP == BI.MBB->end()) + BI.LastSplitPoint = BI.Stop; + else + BI.LastSplitPoint = LIS.getInstructionIndex(LSP); + + // LVI is the first live segment overlapping MBB. + BI.LiveIn = LVI->start <= BI.Start; + if (!BI.LiveIn) + BI.Def = LVI->start; + + // Find the first and last uses in the block. + BI.Uses = hasUses(MFI); + if (BI.Uses && UseI != UseE) { + BI.FirstUse = *UseI; + assert(BI.FirstUse >= BI.Start); + do ++UseI; + while (UseI != UseE && *UseI < BI.Stop); + BI.LastUse = UseI[-1]; + assert(BI.LastUse < BI.Stop); + } + + // Look for gaps in the live range. + bool hasGap = false; + BI.LiveOut = true; + while (LVI->end < BI.Stop) { + SlotIndex LastStop = LVI->end; + if (++LVI == LVE || LVI->start >= BI.Stop) { + BI.Kill = LastStop; + BI.LiveOut = false; + break; + } + if (LastStop < LVI->start) { + hasGap = true; + BI.Kill = LastStop; + BI.Def = LVI->start; + } + } + + // Don't set LiveThrough when the block has a gap. + BI.LiveThrough = !hasGap && BI.LiveIn && BI.LiveOut; + LiveBlocks.push_back(BI); + + // FIXME: This should never happen. The live range stops or starts without a + // corresponding use. An earlier pass did something wrong. + if (!BI.LiveThrough && !BI.Uses) + return false; + + // LVI is now at LVE or LVI->end >= Stop. + if (LVI == LVE) + break; + + // Live segment ends exactly at Stop. Move to the next segment. + if (LVI->end == BI.Stop && ++LVI == LVE) + break; + + // Pick the next basic block. + if (LVI->start < BI.Stop) + ++MFI; + else + MFI = LIS.getMBBFromIndex(LVI->start); + } + return true; +} + +bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const { + unsigned OrigReg = VRM.getOriginal(CurLI->reg); + const LiveInterval &Orig = LIS.getInterval(OrigReg); + assert(!Orig.empty() && "Splitting empty interval?"); + LiveInterval::const_iterator I = Orig.find(Idx); + + // Range containing Idx should begin at Idx. + if (I != Orig.end() && I->start <= Idx) + return I->start == Idx; + + // Range does not contain Idx, previous must end at Idx. + return I != Orig.begin() && (--I)->end == Idx; +} + +void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const { + for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) { + unsigned count = UsingBlocks.lookup(*I); + OS << " BB#" << (*I)->getNumber(); + if (count) + OS << '(' << count << ')'; + } +} + +void SplitAnalysis::analyze(const LiveInterval *li) { + clear(); + CurLI = li; + analyzeUses(); +} + + +//===----------------------------------------------------------------------===// +// Split Editor +//===----------------------------------------------------------------------===// + +/// Create a new SplitEditor for editing the LiveInterval analyzed by SA. +SplitEditor::SplitEditor(SplitAnalysis &sa, + LiveIntervals &lis, + VirtRegMap &vrm, + MachineDominatorTree &mdt) + : SA(sa), LIS(lis), VRM(vrm), + MRI(vrm.getMachineFunction().getRegInfo()), + MDT(mdt), + TII(*vrm.getMachineFunction().getTarget().getInstrInfo()), + TRI(*vrm.getMachineFunction().getTarget().getRegisterInfo()), + Edit(0), + OpenIdx(0), + RegAssign(Allocator) +{} + +void SplitEditor::reset(LiveRangeEdit &lre) { + Edit = &lre; + OpenIdx = 0; + RegAssign.clear(); + Values.clear(); + + // We don't need to clear LiveOutCache, only LiveOutSeen entries are read. + LiveOutSeen.clear(); + + // We don't need an AliasAnalysis since we will only be performing + // cheap-as-a-copy remats anyway. + Edit->anyRematerializable(LIS, TII, 0); +} + +void SplitEditor::dump() const { + if (RegAssign.empty()) { + dbgs() << " empty\n"; + return; + } + + for (RegAssignMap::const_iterator I = RegAssign.begin(); I.valid(); ++I) + dbgs() << " [" << I.start() << ';' << I.stop() << "):" << I.value(); + dbgs() << '\n'; +} + +VNInfo *SplitEditor::defValue(unsigned RegIdx, + const VNInfo *ParentVNI, + SlotIndex Idx) { + assert(ParentVNI && "Mapping NULL value"); + assert(Idx.isValid() && "Invalid SlotIndex"); + assert(Edit->getParent().getVNInfoAt(Idx) == ParentVNI && "Bad Parent VNI"); + LiveInterval *LI = Edit->get(RegIdx); + + // Create a new value. + VNInfo *VNI = LI->getNextValue(Idx, 0, LIS.getVNInfoAllocator()); + + // Preserve the PHIDef bit. + if (ParentVNI->isPHIDef() && Idx == ParentVNI->def) + VNI->setIsPHIDef(true); + + // Use insert for lookup, so we can add missing values with a second lookup. + std::pair InsP = + Values.insert(std::make_pair(std::make_pair(RegIdx, ParentVNI->id), VNI)); + + // This was the first time (RegIdx, ParentVNI) was mapped. + // Keep it as a simple def without any liveness. + if (InsP.second) + return VNI; + + // If the previous value was a simple mapping, add liveness for it now. + if (VNInfo *OldVNI = InsP.first->second) { + SlotIndex Def = OldVNI->def; + LI->addRange(LiveRange(Def, Def.getNextSlot(), OldVNI)); + // No longer a simple mapping. + InsP.first->second = 0; + } + + // This is a complex mapping, add liveness for VNI + SlotIndex Def = VNI->def; + LI->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); + + return VNI; +} + +void SplitEditor::markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI) { + assert(ParentVNI && "Mapping NULL value"); + VNInfo *&VNI = Values[std::make_pair(RegIdx, ParentVNI->id)]; + + // ParentVNI was either unmapped or already complex mapped. Either way. + if (!VNI) + return; + + // This was previously a single mapping. Make sure the old def is represented + // by a trivial live range. + SlotIndex Def = VNI->def; + Edit->get(RegIdx)->addRange(LiveRange(Def, Def.getNextSlot(), VNI)); + VNI = 0; +} + +// extendRange - Extend the live range to reach Idx. +// Potentially create phi-def values. +void SplitEditor::extendRange(unsigned RegIdx, SlotIndex Idx) { + assert(Idx.isValid() && "Invalid SlotIndex"); + MachineBasicBlock *IdxMBB = LIS.getMBBFromIndex(Idx); + assert(IdxMBB && "No MBB at Idx"); + LiveInterval *LI = Edit->get(RegIdx); + + // Is there a def in the same MBB we can extend? + if (LI->extendInBlock(LIS.getMBBStartIdx(IdxMBB), Idx)) + return; + + // Now for the fun part. We know that ParentVNI potentially has multiple defs, + // and we may need to create even more phi-defs to preserve VNInfo SSA form. + // Perform a search for all predecessor blocks where we know the dominating + // VNInfo. Insert phi-def VNInfos along the path back to IdxMBB. + + // Initialize the live-out cache the first time it is needed. + if (LiveOutSeen.empty()) { + unsigned N = VRM.getMachineFunction().getNumBlockIDs(); + LiveOutSeen.resize(N); + LiveOutCache.resize(N); + } + + // Blocks where LI should be live-in. + SmallVector LiveIn; + LiveIn.push_back(MDT[IdxMBB]); + + // Remember if we have seen more than one value. + bool UniqueVNI = true; + VNInfo *IdxVNI = 0; + + // Using LiveOutCache as a visited set, perform a BFS for all reaching defs. + for (unsigned i = 0; i != LiveIn.size(); ++i) { + MachineBasicBlock *MBB = LiveIn[i]->getBlock(); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *Pred = *PI; + LiveOutPair &LOP = LiveOutCache[Pred]; + + // Is this a known live-out block? + if (LiveOutSeen.test(Pred->getNumber())) { + if (VNInfo *VNI = LOP.first) { + if (IdxVNI && IdxVNI != VNI) + UniqueVNI = false; + IdxVNI = VNI; + } + continue; + } + + // First time. LOP is garbage and must be cleared below. + LiveOutSeen.set(Pred->getNumber()); + + // Does Pred provide a live-out value? + SlotIndex Start, Last; + tie(Start, Last) = LIS.getSlotIndexes()->getMBBRange(Pred); + Last = Last.getPrevSlot(); + VNInfo *VNI = LI->extendInBlock(Start, Last); + LOP.first = VNI; + if (VNI) { + LOP.second = MDT[LIS.getMBBFromIndex(VNI->def)]; + if (IdxVNI && IdxVNI != VNI) + UniqueVNI = false; + IdxVNI = VNI; + continue; + } + LOP.second = 0; + + // No, we need a live-in value for Pred as well + if (Pred != IdxMBB) + LiveIn.push_back(MDT[Pred]); + else + UniqueVNI = false; // Loopback to IdxMBB, ask updateSSA() for help. + } + } + + // We may need to add phi-def values to preserve the SSA form. + if (UniqueVNI) { + LiveOutPair LOP(IdxVNI, MDT[LIS.getMBBFromIndex(IdxVNI->def)]); + // Update LiveOutCache, but skip IdxMBB at LiveIn[0]. + for (unsigned i = 1, e = LiveIn.size(); i != e; ++i) + LiveOutCache[LiveIn[i]->getBlock()] = LOP; + } else + IdxVNI = updateSSA(RegIdx, LiveIn, Idx, IdxMBB); + + // Since we went through the trouble of a full BFS visiting all reaching defs, + // the values in LiveIn are now accurate. No more phi-defs are needed + // for these blocks, so we can color the live ranges. + for (unsigned i = 0, e = LiveIn.size(); i != e; ++i) { + MachineBasicBlock *MBB = LiveIn[i]->getBlock(); + SlotIndex Start = LIS.getMBBStartIdx(MBB); + VNInfo *VNI = LiveOutCache[MBB].first; + + // Anything in LiveIn other than IdxMBB is live-through. + // In IdxMBB, we should stop at Idx unless the same value is live-out. + if (MBB == IdxMBB && IdxVNI != VNI) + LI->addRange(LiveRange(Start, Idx.getNextSlot(), IdxVNI)); + else + LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); + } +} + +VNInfo *SplitEditor::updateSSA(unsigned RegIdx, + SmallVectorImpl &LiveIn, + SlotIndex Idx, + const MachineBasicBlock *IdxMBB) { + // This is essentially the same iterative algorithm that SSAUpdater uses, + // except we already have a dominator tree, so we don't have to recompute it. + LiveInterval *LI = Edit->get(RegIdx); + VNInfo *IdxVNI = 0; + unsigned Changes; + do { + Changes = 0; + // Propagate live-out values down the dominator tree, inserting phi-defs + // when necessary. Since LiveIn was created by a BFS, going backwards makes + // it more likely for us to visit immediate dominators before their + // children. + for (unsigned i = LiveIn.size(); i; --i) { + MachineDomTreeNode *Node = LiveIn[i-1]; + MachineBasicBlock *MBB = Node->getBlock(); + MachineDomTreeNode *IDom = Node->getIDom(); + LiveOutPair IDomValue; + + // We need a live-in value to a block with no immediate dominator? + // This is probably an unreachable block that has survived somehow. + bool needPHI = !IDom || !LiveOutSeen.test(IDom->getBlock()->getNumber()); + + // IDom dominates all of our predecessors, but it may not be the immediate + // dominator. Check if any of them have live-out values that are properly + // dominated by IDom. If so, we need a phi-def here. + if (!needPHI) { + IDomValue = LiveOutCache[IDom->getBlock()]; + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + LiveOutPair Value = LiveOutCache[*PI]; + if (!Value.first || Value.first == IDomValue.first) + continue; + // This predecessor is carrying something other than IDomValue. + // It could be because IDomValue hasn't propagated yet, or it could be + // because MBB is in the dominance frontier of that value. + if (MDT.dominates(IDom, Value.second)) { + needPHI = true; + break; + } + } + } + + // Create a phi-def if required. + if (needPHI) { + ++Changes; + SlotIndex Start = LIS.getMBBStartIdx(MBB); + VNInfo *VNI = LI->getNextValue(Start, 0, LIS.getVNInfoAllocator()); + VNI->setIsPHIDef(true); + // We no longer need LI to be live-in. + LiveIn.erase(LiveIn.begin()+(i-1)); + // Blocks in LiveIn are either IdxMBB, or have a value live-through. + if (MBB == IdxMBB) + IdxVNI = VNI; + // Check if we need to update live-out info. + LiveOutPair &LOP = LiveOutCache[MBB]; + if (LOP.second == Node || !LiveOutSeen.test(MBB->getNumber())) { + // We already have a live-out defined in MBB, so this must be IdxMBB. + assert(MBB == IdxMBB && "Adding phi-def to known live-out"); + LI->addRange(LiveRange(Start, Idx.getNextSlot(), VNI)); + } else { + // This phi-def is also live-out, so color the whole block. + LI->addRange(LiveRange(Start, LIS.getMBBEndIdx(MBB), VNI)); + LOP = LiveOutPair(VNI, Node); + } + } else if (IDomValue.first) { + // No phi-def here. Remember incoming value for IdxMBB. + if (MBB == IdxMBB) { + IdxVNI = IDomValue.first; + // IdxMBB need not be live-out. + if (!LiveOutSeen.test(MBB->getNumber())) + continue; + } + assert(LiveOutSeen.test(MBB->getNumber()) && "Expected live-out block"); + // Propagate IDomValue if needed: + // MBB is live-out and doesn't define its own value. + LiveOutPair &LOP = LiveOutCache[MBB]; + if (LOP.second != Node && LOP.first != IDomValue.first) { + ++Changes; + LOP = IDomValue; + } + } + } + } while (Changes); + + assert(IdxVNI && "Didn't find value for Idx"); + return IdxVNI; +} + +VNInfo *SplitEditor::defFromParent(unsigned RegIdx, + VNInfo *ParentVNI, + SlotIndex UseIdx, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) { + MachineInstr *CopyMI = 0; + SlotIndex Def; + LiveInterval *LI = Edit->get(RegIdx); + + // Attempt cheap-as-a-copy rematerialization. + LiveRangeEdit::Remat RM(ParentVNI); + if (Edit->canRematerializeAt(RM, UseIdx, true, LIS)) { + Def = Edit->rematerializeAt(MBB, I, LI->reg, RM, LIS, TII, TRI); + } else { + // Can't remat, just insert a copy from parent. + CopyMI = BuildMI(MBB, I, DebugLoc(), TII.get(TargetOpcode::COPY), LI->reg) + .addReg(Edit->getReg()); + Def = LIS.InsertMachineInstrInMaps(CopyMI).getDefIndex(); + } + + // Define the value in Reg. + VNInfo *VNI = defValue(RegIdx, ParentVNI, Def); + VNI->setCopy(CopyMI); + return VNI; +} + +/// Create a new virtual register and live interval. +void SplitEditor::openIntv() { + assert(!OpenIdx && "Previous LI not closed before openIntv"); + + // Create the complement as index 0. + if (Edit->empty()) + Edit->create(MRI, LIS, VRM); + + // Create the open interval. + OpenIdx = Edit->size(); + Edit->create(MRI, LIS, VRM); +} + +SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { + assert(OpenIdx && "openIntv not called before enterIntvBefore"); + DEBUG(dbgs() << " enterIntvBefore " << Idx); + Idx = Idx.getBaseIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Idx; + } + DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); + MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + assert(MI && "enterIntvBefore called with invalid index"); + + VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Idx, *MI->getParent(), MI); + return VNI->def; +} + +SlotIndex SplitEditor::enterIntvAtEnd(MachineBasicBlock &MBB) { + assert(OpenIdx && "openIntv not called before enterIntvAtEnd"); + SlotIndex End = LIS.getMBBEndIdx(&MBB); + SlotIndex Last = End.getPrevSlot(); + DEBUG(dbgs() << " enterIntvAtEnd BB#" << MBB.getNumber() << ", " << Last); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Last); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return End; + } + DEBUG(dbgs() << ": valno " << ParentVNI->id); + VNInfo *VNI = defFromParent(OpenIdx, ParentVNI, Last, MBB, + LIS.getLastSplitPoint(Edit->getParent(), &MBB)); + RegAssign.insert(VNI->def, End, OpenIdx); + DEBUG(dump()); + return VNI->def; +} + +/// useIntv - indicate that all instructions in MBB should use OpenLI. +void SplitEditor::useIntv(const MachineBasicBlock &MBB) { + useIntv(LIS.getMBBStartIdx(&MBB), LIS.getMBBEndIdx(&MBB)); +} + +void SplitEditor::useIntv(SlotIndex Start, SlotIndex End) { + assert(OpenIdx && "openIntv not called before useIntv"); + DEBUG(dbgs() << " useIntv [" << Start << ';' << End << "):"); + RegAssign.insert(Start, End, OpenIdx); + DEBUG(dump()); +} + +SlotIndex SplitEditor::leaveIntvAfter(SlotIndex Idx) { + assert(OpenIdx && "openIntv not called before leaveIntvAfter"); + DEBUG(dbgs() << " leaveIntvAfter " << Idx); + + // The interval must be live beyond the instruction at Idx. + Idx = Idx.getBoundaryIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Idx.getNextSlot(); + } + DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); + + MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + assert(MI && "No instruction at index"); + VNInfo *VNI = defFromParent(0, ParentVNI, Idx, *MI->getParent(), + llvm::next(MachineBasicBlock::iterator(MI))); + return VNI->def; +} + +SlotIndex SplitEditor::leaveIntvBefore(SlotIndex Idx) { + assert(OpenIdx && "openIntv not called before leaveIntvBefore"); + DEBUG(dbgs() << " leaveIntvBefore " << Idx); + + // The interval must be live into the instruction at Idx. + Idx = Idx.getBoundaryIndex(); + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Idx); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Idx.getNextSlot(); + } + DEBUG(dbgs() << ": valno " << ParentVNI->id << '\n'); + + MachineInstr *MI = LIS.getInstructionFromIndex(Idx); + assert(MI && "No instruction at index"); + VNInfo *VNI = defFromParent(0, ParentVNI, Idx, *MI->getParent(), MI); + return VNI->def; +} + +SlotIndex SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) { + assert(OpenIdx && "openIntv not called before leaveIntvAtTop"); + SlotIndex Start = LIS.getMBBStartIdx(&MBB); + DEBUG(dbgs() << " leaveIntvAtTop BB#" << MBB.getNumber() << ", " << Start); + + VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Start); + if (!ParentVNI) { + DEBUG(dbgs() << ": not live\n"); + return Start; + } + + VNInfo *VNI = defFromParent(0, ParentVNI, Start, MBB, + MBB.SkipPHIsAndLabels(MBB.begin())); + RegAssign.insert(Start, VNI->def, OpenIdx); + DEBUG(dump()); + return VNI->def; +} + +void SplitEditor::overlapIntv(SlotIndex Start, SlotIndex End) { + assert(OpenIdx && "openIntv not called before overlapIntv"); + const VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Start); + assert(ParentVNI == Edit->getParent().getVNInfoAt(End.getPrevSlot()) && + "Parent changes value in extended range"); + assert(LIS.getMBBFromIndex(Start) == LIS.getMBBFromIndex(End) && + "Range cannot span basic blocks"); + + // The complement interval will be extended as needed by extendRange(). + markComplexMapped(0, ParentVNI); + DEBUG(dbgs() << " overlapIntv [" << Start << ';' << End << "):"); + RegAssign.insert(Start, End, OpenIdx); + DEBUG(dump()); +} + +/// closeIntv - Indicate that we are done editing the currently open +/// LiveInterval, and ranges can be trimmed. +void SplitEditor::closeIntv() { + assert(OpenIdx && "openIntv not called before closeIntv"); + OpenIdx = 0; +} + +/// transferSimpleValues - Transfer all simply defined values to the new live +/// ranges. +/// Values that were rematerialized or that have multiple defs are left alone. +bool SplitEditor::transferSimpleValues() { + bool Skipped = false; + RegAssignMap::const_iterator AssignI = RegAssign.begin(); + for (LiveInterval::const_iterator ParentI = Edit->getParent().begin(), + ParentE = Edit->getParent().end(); ParentI != ParentE; ++ParentI) { + DEBUG(dbgs() << " blit " << *ParentI << ':'); + VNInfo *ParentVNI = ParentI->valno; + // RegAssign has holes where RegIdx 0 should be used. + SlotIndex Start = ParentI->start; + AssignI.advanceTo(Start); + do { + unsigned RegIdx; + SlotIndex End = ParentI->end; + if (!AssignI.valid()) { + RegIdx = 0; + } else if (AssignI.start() <= Start) { + RegIdx = AssignI.value(); + if (AssignI.stop() < End) { + End = AssignI.stop(); + ++AssignI; + } + } else { + RegIdx = 0; + End = std::min(End, AssignI.start()); + } + DEBUG(dbgs() << " [" << Start << ';' << End << ")=" << RegIdx); + if (VNInfo *VNI = Values.lookup(std::make_pair(RegIdx, ParentVNI->id))) { + DEBUG(dbgs() << ':' << VNI->id); + Edit->get(RegIdx)->addRange(LiveRange(Start, End, VNI)); + } else + Skipped = true; + Start = End; + } while (Start != ParentI->end); + DEBUG(dbgs() << '\n'); + } + return Skipped; +} + +void SplitEditor::extendPHIKillRanges() { + // Extend live ranges to be live-out for successor PHI values. + for (LiveInterval::const_vni_iterator I = Edit->getParent().vni_begin(), + E = Edit->getParent().vni_end(); I != E; ++I) { + const VNInfo *PHIVNI = *I; + if (PHIVNI->isUnused() || !PHIVNI->isPHIDef()) + continue; + unsigned RegIdx = RegAssign.lookup(PHIVNI->def); + MachineBasicBlock *MBB = LIS.getMBBFromIndex(PHIVNI->def); + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + SlotIndex End = LIS.getMBBEndIdx(*PI).getPrevSlot(); + // The predecessor may not have a live-out value. That is OK, like an + // undef PHI operand. + if (Edit->getParent().liveAt(End)) { + assert(RegAssign.lookup(End) == RegIdx && + "Different register assignment in phi predecessor"); + extendRange(RegIdx, End); + } + } + } +} + +/// rewriteAssigned - Rewrite all uses of Edit->getReg(). +void SplitEditor::rewriteAssigned(bool ExtendRanges) { + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit->getReg()), + RE = MRI.reg_end(); RI != RE;) { + MachineOperand &MO = RI.getOperand(); + MachineInstr *MI = MO.getParent(); + ++RI; + // LiveDebugVariables should have handled all DBG_VALUE instructions. + if (MI->isDebugValue()) { + DEBUG(dbgs() << "Zapping " << *MI); + MO.setReg(0); + continue; + } + + // operands don't really read the register, so just assign them to + // the complement. + if (MO.isUse() && MO.isUndef()) { + MO.setReg(Edit->get(0)->reg); + continue; + } + + SlotIndex Idx = LIS.getInstructionIndex(MI); + Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); + + // Rewrite to the mapped register at Idx. + unsigned RegIdx = RegAssign.lookup(Idx); + MO.setReg(Edit->get(RegIdx)->reg); + DEBUG(dbgs() << " rewr BB#" << MI->getParent()->getNumber() << '\t' + << Idx << ':' << RegIdx << '\t' << *MI); + + // Extend liveness to Idx. + if (ExtendRanges) + extendRange(RegIdx, Idx); + } +} + +/// rewriteSplit - Rewrite uses of Intvs[0] according to the ConEQ mapping. +void SplitEditor::rewriteComponents(const SmallVectorImpl &Intvs, + const ConnectedVNInfoEqClasses &ConEq) { + for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Intvs[0]->reg), + RE = MRI.reg_end(); RI != RE;) { + MachineOperand &MO = RI.getOperand(); + MachineInstr *MI = MO.getParent(); + ++RI; + if (MO.isUse() && MO.isUndef()) + continue; + // DBG_VALUE instructions should have been eliminated earlier. + SlotIndex Idx = LIS.getInstructionIndex(MI); + Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); + DEBUG(dbgs() << " rewr BB#" << MI->getParent()->getNumber() << '\t' + << Idx << ':'); + const VNInfo *VNI = Intvs[0]->getVNInfoAt(Idx); + assert(VNI && "Interval not live at use."); + MO.setReg(Intvs[ConEq.getEqClass(VNI)]->reg); + DEBUG(dbgs() << VNI->id << '\t' << *MI); + } +} + +void SplitEditor::finish() { + assert(OpenIdx == 0 && "Previous LI not closed before rewrite"); + ++NumFinished; + + // At this point, the live intervals in Edit contain VNInfos corresponding to + // the inserted copies. + + // Add the original defs from the parent interval. + for (LiveInterval::const_vni_iterator I = Edit->getParent().vni_begin(), + E = Edit->getParent().vni_end(); I != E; ++I) { + const VNInfo *ParentVNI = *I; + if (ParentVNI->isUnused()) + continue; + unsigned RegIdx = RegAssign.lookup(ParentVNI->def); + defValue(RegIdx, ParentVNI, ParentVNI->def); + // Mark rematted values as complex everywhere to force liveness computation. + // The new live ranges may be truncated. + if (Edit->didRematerialize(ParentVNI)) + for (unsigned i = 0, e = Edit->size(); i != e; ++i) + markComplexMapped(i, ParentVNI); + } + +#ifndef NDEBUG + // Every new interval must have a def by now, otherwise the split is bogus. + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) + assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); +#endif + + // Transfer the simply mapped values, check if any are complex. + bool Complex = transferSimpleValues(); + if (Complex) + extendPHIKillRanges(); + else + ++NumSimple; + + // Rewrite virtual registers, possibly extending ranges. + rewriteAssigned(Complex); + + // FIXME: Delete defs that were rematted everywhere. + + // Get rid of unused values and set phi-kill flags. + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I) + (*I)->RenumberValues(LIS); + + // Now check if any registers were separated into multiple components. + ConnectedVNInfoEqClasses ConEQ(LIS); + for (unsigned i = 0, e = Edit->size(); i != e; ++i) { + // Don't use iterators, they are invalidated by create() below. + LiveInterval *li = Edit->get(i); + unsigned NumComp = ConEQ.Classify(li); + if (NumComp <= 1) + continue; + DEBUG(dbgs() << " " << NumComp << " components: " << *li << '\n'); + SmallVector dups; + dups.push_back(li); + for (unsigned i = 1; i != NumComp; ++i) + dups.push_back(&Edit->create(MRI, LIS, VRM)); + rewriteComponents(dups, ConEQ); + ConEQ.Distribute(&dups[0]); + } + + // Calculate spill weight and allocation hints for new intervals. + VirtRegAuxInfo vrai(VRM.getMachineFunction(), LIS, SA.Loops); + for (LiveRangeEdit::iterator I = Edit->begin(), E = Edit->end(); I != E; ++I){ + LiveInterval &li = **I; + vrai.CalculateRegClass(li.reg); + vrai.CalculateWeightAndHint(li); + DEBUG(dbgs() << " new interval " << MRI.getRegClass(li.reg)->getName() + << ":" << li << '\n'); + } +} + + +//===----------------------------------------------------------------------===// +// Single Block Splitting +//===----------------------------------------------------------------------===// + +/// getMultiUseBlocks - if CurLI has more than one use in a basic block, it +/// may be an advantage to split CurLI for the duration of the block. +bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) { + // If CurLI is local to one block, there is no point to splitting it. + if (LiveBlocks.size() <= 1) + return false; + // Add blocks with multiple uses. + for (unsigned i = 0, e = LiveBlocks.size(); i != e; ++i) { + const BlockInfo &BI = LiveBlocks[i]; + if (!BI.Uses) + continue; + unsigned Instrs = UsingBlocks.lookup(BI.MBB); + if (Instrs <= 1) + continue; + if (Instrs == 2 && BI.LiveIn && BI.LiveOut && !BI.LiveThrough) + continue; + Blocks.insert(BI.MBB); + } + return !Blocks.empty(); +} + +/// splitSingleBlocks - Split CurLI into a separate live interval inside each +/// basic block in Blocks. +void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) { + DEBUG(dbgs() << " splitSingleBlocks for " << Blocks.size() << " blocks.\n"); + + for (unsigned i = 0, e = SA.LiveBlocks.size(); i != e; ++i) { + const SplitAnalysis::BlockInfo &BI = SA.LiveBlocks[i]; + if (!BI.Uses || !Blocks.count(BI.MBB)) + continue; + + openIntv(); + SlotIndex SegStart = enterIntvBefore(BI.FirstUse); + if (!BI.LiveOut || BI.LastUse < BI.LastSplitPoint) { + useIntv(SegStart, leaveIntvAfter(BI.LastUse)); + } else { + // The last use is after the last valid split point. + SlotIndex SegStop = leaveIntvBefore(BI.LastSplitPoint); + useIntv(SegStart, SegStop); + overlapIntv(SegStop, BI.LastUse); + } + closeIntv(); + } + finish(); +} diff --git a/final/lib/CodeGen/SplitKit.h b/final/lib/CodeGen/SplitKit.h new file mode 100644 index 00000000000..0e35df0ed6c --- /dev/null +++ b/final/lib/CodeGen/SplitKit.h @@ -0,0 +1,346 @@ +//===-------- SplitKit.h - Toolkit for splitting live ranges ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the SplitAnalysis class as well as mutator functions for +// live range splitting. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/SlotIndexes.h" + +namespace llvm { + +class ConnectedVNInfoEqClasses; +class LiveInterval; +class LiveIntervals; +class LiveRangeEdit; +class MachineInstr; +class MachineLoopInfo; +class MachineRegisterInfo; +class TargetInstrInfo; +class TargetRegisterInfo; +class VirtRegMap; +class VNInfo; +class raw_ostream; + +/// At some point we should just include MachineDominators.h: +class MachineDominatorTree; +template class DomTreeNodeBase; +typedef DomTreeNodeBase MachineDomTreeNode; + + +/// SplitAnalysis - Analyze a LiveInterval, looking for live range splitting +/// opportunities. +class SplitAnalysis { +public: + const MachineFunction &MF; + const VirtRegMap &VRM; + const LiveIntervals &LIS; + const MachineLoopInfo &Loops; + const TargetInstrInfo &TII; + + // Instructions using the the current register. + typedef SmallPtrSet InstrPtrSet; + InstrPtrSet UsingInstrs; + + // Sorted slot indexes of using instructions. + SmallVector UseSlots; + + // The number of instructions using CurLI in each basic block. + typedef DenseMap BlockCountMap; + BlockCountMap UsingBlocks; + + /// Additional information about basic blocks where the current variable is + /// live. Such a block will look like one of these templates: + /// + /// 1. | o---x | Internal to block. Variable is only live in this block. + /// 2. |---x | Live-in, kill. + /// 3. | o---| Def, live-out. + /// 4. |---x o---| Live-in, kill, def, live-out. + /// 5. |---o---o---| Live-through with uses or defs. + /// 6. |-----------| Live-through without uses. Transparent. + /// + struct BlockInfo { + MachineBasicBlock *MBB; + SlotIndex Start; ///< Beginining of block. + SlotIndex Stop; ///< End of block. + SlotIndex FirstUse; ///< First instr using current reg. + SlotIndex LastUse; ///< Last instr using current reg. + SlotIndex Kill; ///< Interval end point inside block. + SlotIndex Def; ///< Interval start point inside block. + /// Last possible point for splitting live ranges. + SlotIndex LastSplitPoint; + bool Uses; ///< Current reg has uses or defs in block. + bool LiveThrough; ///< Live in whole block (Templ 5. or 6. above). + bool LiveIn; ///< Current reg is live in. + bool LiveOut; ///< Current reg is live out. + + // Per-interference pattern scratch data. + bool OverlapEntry; ///< Interference overlaps entering interval. + bool OverlapExit; ///< Interference overlaps exiting interval. + }; + + /// Basic blocks where var is live. This array is parallel to + /// SpillConstraints. + SmallVector LiveBlocks; + +private: + // Current live interval. + const LiveInterval *CurLI; + + // Sumarize statistics by counting instructions using CurLI. + void analyzeUses(); + + /// calcLiveBlockInfo - Compute per-block information about CurLI. + bool calcLiveBlockInfo(); + + /// canAnalyzeBranch - Return true if MBB ends in a branch that can be + /// analyzed. + bool canAnalyzeBranch(const MachineBasicBlock *MBB); + +public: + SplitAnalysis(const VirtRegMap &vrm, const LiveIntervals &lis, + const MachineLoopInfo &mli); + + /// analyze - set CurLI to the specified interval, and analyze how it may be + /// split. + void analyze(const LiveInterval *li); + + /// clear - clear all data structures so SplitAnalysis is ready to analyze a + /// new interval. + void clear(); + + /// getParent - Return the last analyzed interval. + const LiveInterval &getParent() const { return *CurLI; } + + /// hasUses - Return true if MBB has any uses of CurLI. + bool hasUses(const MachineBasicBlock *MBB) const { + return UsingBlocks.lookup(MBB); + } + + /// isOriginalEndpoint - Return true if the original live range was killed or + /// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def, + /// and 'use' for an early-clobber def. + /// This can be used to recognize code inserted by earlier live range + /// splitting. + bool isOriginalEndpoint(SlotIndex Idx) const; + + typedef SmallPtrSet BlockPtrSet; + + // Print a set of blocks with use counts. + void print(const BlockPtrSet&, raw_ostream&) const; + + /// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from + /// having CurLI split to a new live interval. Return true if Blocks can be + /// passed to SplitEditor::splitSingleBlocks. + bool getMultiUseBlocks(BlockPtrSet &Blocks); +}; + + +/// SplitEditor - Edit machine code and LiveIntervals for live range +/// splitting. +/// +/// - Create a SplitEditor from a SplitAnalysis. +/// - Start a new live interval with openIntv. +/// - Mark the places where the new interval is entered using enterIntv* +/// - Mark the ranges where the new interval is used with useIntv* +/// - Mark the places where the interval is exited with exitIntv*. +/// - Finish the current interval with closeIntv and repeat from 2. +/// - Rewrite instructions with finish(). +/// +class SplitEditor { + SplitAnalysis &SA; + LiveIntervals &LIS; + VirtRegMap &VRM; + MachineRegisterInfo &MRI; + MachineDominatorTree &MDT; + const TargetInstrInfo &TII; + const TargetRegisterInfo &TRI; + + /// Edit - The current parent register and new intervals created. + LiveRangeEdit *Edit; + + /// Index into Edit of the currently open interval. + /// The index 0 is used for the complement, so the first interval started by + /// openIntv will be 1. + unsigned OpenIdx; + + typedef IntervalMap RegAssignMap; + + /// Allocator for the interval map. This will eventually be shared with + /// SlotIndexes and LiveIntervals. + RegAssignMap::Allocator Allocator; + + /// RegAssign - Map of the assigned register indexes. + /// Edit.get(RegAssign.lookup(Idx)) is the register that should be live at + /// Idx. + RegAssignMap RegAssign; + + typedef DenseMap, VNInfo*> ValueMap; + + /// Values - keep track of the mapping from parent values to values in the new + /// intervals. Given a pair (RegIdx, ParentVNI->id), Values contains: + /// + /// 1. No entry - the value is not mapped to Edit.get(RegIdx). + /// 2. Null - the value is mapped to multiple values in Edit.get(RegIdx). + /// Each value is represented by a minimal live range at its def. + /// 3. A non-null VNInfo - the value is mapped to a single new value. + /// The new value has no live ranges anywhere. + ValueMap Values; + + typedef std::pair LiveOutPair; + typedef IndexedMap LiveOutMap; + + // LiveOutCache - Map each basic block where a new register is live out to the + // live-out value and its defining block. + // One of these conditions shall be true: + // + // 1. !LiveOutCache.count(MBB) + // 2. LiveOutCache[MBB].second.getNode() == MBB + // 3. forall P in preds(MBB): LiveOutCache[P] == LiveOutCache[MBB] + // + // This is only a cache, the values can be computed as: + // + // VNI = Edit.get(RegIdx)->getVNInfoAt(LIS.getMBBEndIdx(MBB)) + // Node = mbt_[LIS.getMBBFromIndex(VNI->def)] + // + // The cache is also used as a visited set by extendRange(). It can be shared + // by all the new registers because at most one is live out of each block. + LiveOutMap LiveOutCache; + + // LiveOutSeen - Indexed by MBB->getNumber(), a bit is set for each valid + // entry in LiveOutCache. + BitVector LiveOutSeen; + + /// defValue - define a value in RegIdx from ParentVNI at Idx. + /// Idx does not have to be ParentVNI->def, but it must be contained within + /// ParentVNI's live range in ParentLI. The new value is added to the value + /// map. + /// Return the new LI value. + VNInfo *defValue(unsigned RegIdx, const VNInfo *ParentVNI, SlotIndex Idx); + + /// markComplexMapped - Mark ParentVNI as complex mapped in RegIdx regardless + /// of the number of defs. + void markComplexMapped(unsigned RegIdx, const VNInfo *ParentVNI); + + /// defFromParent - Define Reg from ParentVNI at UseIdx using either + /// rematerialization or a COPY from parent. Return the new value. + VNInfo *defFromParent(unsigned RegIdx, + VNInfo *ParentVNI, + SlotIndex UseIdx, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I); + + /// extendRange - Extend the live range of Edit.get(RegIdx) so it reaches Idx. + /// Insert PHIDefs as needed to preserve SSA form. + void extendRange(unsigned RegIdx, SlotIndex Idx); + + /// updateSSA - Insert PHIDefs as necessary and update LiveOutCache such that + /// Edit.get(RegIdx) is live-in to all the blocks in LiveIn. + /// Return the value that is eventually live-in to IdxMBB. + VNInfo *updateSSA(unsigned RegIdx, + SmallVectorImpl &LiveIn, + SlotIndex Idx, + const MachineBasicBlock *IdxMBB); + + /// transferSimpleValues - Transfer simply defined values to the new ranges. + /// Return true if any complex ranges were skipped. + bool transferSimpleValues(); + + /// extendPHIKillRanges - Extend the ranges of all values killed by original + /// parent PHIDefs. + void extendPHIKillRanges(); + + /// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers. + void rewriteAssigned(bool ExtendRanges); + + /// rewriteComponents - Rewrite all uses of Intv[0] according to the eq + /// classes in ConEQ. + /// This must be done when Intvs[0] is styill live at all uses, before calling + /// ConEq.Distribute(). + void rewriteComponents(const SmallVectorImpl &Intvs, + const ConnectedVNInfoEqClasses &ConEq); + +public: + /// Create a new SplitEditor for editing the LiveInterval analyzed by SA. + /// Newly created intervals will be appended to newIntervals. + SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&, + MachineDominatorTree&); + + /// reset - Prepare for a new split. + void reset(LiveRangeEdit&); + + /// Create a new virtual register and live interval. + void openIntv(); + + /// enterIntvBefore - Enter the open interval before the instruction at Idx. + /// If the parent interval is not live before Idx, a COPY is not inserted. + /// Return the beginning of the new live range. + SlotIndex enterIntvBefore(SlotIndex Idx); + + /// enterIntvAtEnd - Enter the open interval at the end of MBB. + /// Use the open interval from he inserted copy to the MBB end. + /// Return the beginning of the new live range. + SlotIndex enterIntvAtEnd(MachineBasicBlock &MBB); + + /// useIntv - indicate that all instructions in MBB should use OpenLI. + void useIntv(const MachineBasicBlock &MBB); + + /// useIntv - indicate that all instructions in range should use OpenLI. + void useIntv(SlotIndex Start, SlotIndex End); + + /// leaveIntvAfter - Leave the open interval after the instruction at Idx. + /// Return the end of the live range. + SlotIndex leaveIntvAfter(SlotIndex Idx); + + /// leaveIntvBefore - Leave the open interval before the instruction at Idx. + /// Return the end of the live range. + SlotIndex leaveIntvBefore(SlotIndex Idx); + + /// leaveIntvAtTop - Leave the interval at the top of MBB. + /// Add liveness from the MBB top to the copy. + /// Return the end of the live range. + SlotIndex leaveIntvAtTop(MachineBasicBlock &MBB); + + /// overlapIntv - Indicate that all instructions in range should use the open + /// interval, but also let the complement interval be live. + /// + /// This doubles the register pressure, but is sometimes required to deal with + /// register uses after the last valid split point. + /// + /// The Start index should be a return value from a leaveIntv* call, and End + /// should be in the same basic block. The parent interval must have the same + /// value across the range. + /// + void overlapIntv(SlotIndex Start, SlotIndex End); + + /// closeIntv - Indicate that we are done editing the currently open + /// LiveInterval, and ranges can be trimmed. + void closeIntv(); + + /// finish - after all the new live ranges have been created, compute the + /// remaining live range, and rewrite instructions to use the new registers. + void finish(); + + /// dump - print the current interval maping to dbgs(). + void dump() const; + + // ===--- High level methods ---=== + + /// splitSingleBlocks - Split CurLI into a separate live interval inside each + /// basic block in Blocks. + void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks); +}; + +} diff --git a/final/lib/CodeGen/Splitter.cpp b/final/lib/CodeGen/Splitter.cpp new file mode 100644 index 00000000000..08aee82b8c5 --- /dev/null +++ b/final/lib/CodeGen/Splitter.cpp @@ -0,0 +1,827 @@ +//===-- llvm/CodeGen/Splitter.cpp - Splitter -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "loopsplitter" + +#include "Splitter.h" + +#include "SimpleRegisterCoalescing.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" + +using namespace llvm; + +char LoopSplitter::ID = 0; +INITIALIZE_PASS_BEGIN(LoopSplitter, "loop-splitting", + "Split virtual regists across loop boundaries.", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_END(LoopSplitter, "loop-splitting", + "Split virtual regists across loop boundaries.", false, false) + +namespace llvm { + + class StartSlotComparator { + public: + StartSlotComparator(LiveIntervals &lis) : lis(lis) {} + bool operator()(const MachineBasicBlock *mbb1, + const MachineBasicBlock *mbb2) const { + return lis.getMBBStartIdx(mbb1) < lis.getMBBStartIdx(mbb2); + } + private: + LiveIntervals &lis; + }; + + class LoopSplit { + public: + LoopSplit(LoopSplitter &ls, LiveInterval &li, MachineLoop &loop) + : ls(ls), li(li), loop(loop), valid(true), inSplit(false), newLI(0) { + assert(TargetRegisterInfo::isVirtualRegister(li.reg) && + "Cannot split physical registers."); + } + + LiveInterval& getLI() const { return li; } + + MachineLoop& getLoop() const { return loop; } + + bool isValid() const { return valid; } + + bool isWorthwhile() const { return valid && (inSplit || !outSplits.empty()); } + + void invalidate() { valid = false; } + + void splitIncoming() { inSplit = true; } + + void splitOutgoing(MachineLoop::Edge &edge) { outSplits.insert(edge); } + + void addLoopInstr(MachineInstr *i) { loopInstrs.push_back(i); } + + void apply() { + assert(valid && "Attempt to apply invalid split."); + applyIncoming(); + applyOutgoing(); + copyRanges(); + renameInside(); + } + + private: + LoopSplitter &ls; + LiveInterval &li; + MachineLoop &loop; + bool valid, inSplit; + std::set outSplits; + std::vector loopInstrs; + + LiveInterval *newLI; + std::map vniMap; + + LiveInterval* getNewLI() { + if (newLI == 0) { + const TargetRegisterClass *trc = ls.mri->getRegClass(li.reg); + unsigned vreg = ls.mri->createVirtualRegister(trc); + newLI = &ls.lis->getOrCreateInterval(vreg); + } + return newLI; + } + + VNInfo* getNewVNI(VNInfo *oldVNI) { + VNInfo *newVNI = vniMap[oldVNI]; + + if (newVNI == 0) { + newVNI = getNewLI()->createValueCopy(oldVNI, + ls.lis->getVNInfoAllocator()); + vniMap[oldVNI] = newVNI; + } + + return newVNI; + } + + void applyIncoming() { + if (!inSplit) { + return; + } + + MachineBasicBlock *preHeader = loop.getLoopPreheader(); + if (preHeader == 0) { + assert(ls.canInsertPreHeader(loop) && + "Can't insert required preheader."); + preHeader = &ls.insertPreHeader(loop); + } + + LiveRange *preHeaderRange = + ls.lis->findExitingRange(li, preHeader); + assert(preHeaderRange != 0 && "Range not live into preheader."); + + // Insert the new copy. + MachineInstr *copy = BuildMI(*preHeader, + preHeader->getFirstTerminator(), + DebugLoc(), + ls.tii->get(TargetOpcode::COPY)) + .addReg(getNewLI()->reg, RegState::Define) + .addReg(li.reg, RegState::Kill); + + ls.lis->InsertMachineInstrInMaps(copy); + + SlotIndex copyDefIdx = ls.lis->getInstructionIndex(copy).getDefIndex(); + + VNInfo *newVal = getNewVNI(preHeaderRange->valno); + newVal->def = copyDefIdx; + newVal->setCopy(copy); + li.removeRange(copyDefIdx, ls.lis->getMBBEndIdx(preHeader), true); + + getNewLI()->addRange(LiveRange(copyDefIdx, + ls.lis->getMBBEndIdx(preHeader), + newVal)); + } + + void applyOutgoing() { + + for (std::set::iterator osItr = outSplits.begin(), + osEnd = outSplits.end(); + osItr != osEnd; ++osItr) { + MachineLoop::Edge edge = *osItr; + MachineBasicBlock *outBlock = edge.second; + if (ls.isCriticalEdge(edge)) { + assert(ls.canSplitEdge(edge) && "Unsplitable critical edge."); + outBlock = &ls.splitEdge(edge, loop); + } + LiveRange *outRange = ls.lis->findEnteringRange(li, outBlock); + assert(outRange != 0 && "No exiting range?"); + + MachineInstr *copy = BuildMI(*outBlock, outBlock->begin(), + DebugLoc(), + ls.tii->get(TargetOpcode::COPY)) + .addReg(li.reg, RegState::Define) + .addReg(getNewLI()->reg, RegState::Kill); + + ls.lis->InsertMachineInstrInMaps(copy); + + SlotIndex copyDefIdx = ls.lis->getInstructionIndex(copy).getDefIndex(); + + // Blow away output range definition. + outRange->valno->def = ls.lis->getInvalidIndex(); + li.removeRange(ls.lis->getMBBStartIdx(outBlock), copyDefIdx); + + SlotIndex newDefIdx = ls.lis->getMBBStartIdx(outBlock); + assert(ls.lis->getInstructionFromIndex(newDefIdx) == 0 && + "PHI def index points at actual instruction."); + VNInfo *newVal = + getNewLI()->getNextValue(newDefIdx, 0, ls.lis->getVNInfoAllocator()); + + getNewLI()->addRange(LiveRange(ls.lis->getMBBStartIdx(outBlock), + copyDefIdx, newVal)); + + } + } + + void copyRange(LiveRange &lr) { + std::pair lsr = + ls.getLoopSubRange(lr, loop); + + if (!lsr.first) + return; + + LiveRange loopRange(lsr.second.first, lsr.second.second, + getNewVNI(lr.valno)); + + li.removeRange(loopRange.start, loopRange.end, true); + + getNewLI()->addRange(loopRange); + } + + void copyRanges() { + for (std::vector::iterator iItr = loopInstrs.begin(), + iEnd = loopInstrs.end(); + iItr != iEnd; ++iItr) { + MachineInstr &instr = **iItr; + SlotIndex instrIdx = ls.lis->getInstructionIndex(&instr); + if (instr.modifiesRegister(li.reg, 0)) { + LiveRange *defRange = + li.getLiveRangeContaining(instrIdx.getDefIndex()); + if (defRange != 0) // May have caught this already. + copyRange(*defRange); + } + if (instr.readsRegister(li.reg, 0)) { + LiveRange *useRange = + li.getLiveRangeContaining(instrIdx.getUseIndex()); + if (useRange != 0) { // May have caught this already. + copyRange(*useRange); + } + } + } + + for (MachineLoop::block_iterator bbItr = loop.block_begin(), + bbEnd = loop.block_end(); + bbItr != bbEnd; ++bbItr) { + MachineBasicBlock &loopBlock = **bbItr; + LiveRange *enteringRange = + ls.lis->findEnteringRange(li, &loopBlock); + if (enteringRange != 0) { + copyRange(*enteringRange); + } + } + } + + void renameInside() { + for (std::vector::iterator iItr = loopInstrs.begin(), + iEnd = loopInstrs.end(); + iItr != iEnd; ++iItr) { + MachineInstr &instr = **iItr; + for (unsigned i = 0; i < instr.getNumOperands(); ++i) { + MachineOperand &mop = instr.getOperand(i); + if (mop.isReg() && mop.getReg() == li.reg) { + mop.setReg(getNewLI()->reg); + } + } + } + } + + }; + + void LoopSplitter::getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + au.addPreserved(); + au.addPreserved(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + au.addRequired(); + au.addPreserved(); + MachineFunctionPass::getAnalysisUsage(au); + } + + bool LoopSplitter::runOnMachineFunction(MachineFunction &fn) { + + mf = &fn; + mri = &mf->getRegInfo(); + tii = mf->getTarget().getInstrInfo(); + tri = mf->getTarget().getRegisterInfo(); + sis = &getAnalysis(); + lis = &getAnalysis(); + mli = &getAnalysis(); + mdt = &getAnalysis(); + + fqn = mf->getFunction()->getParent()->getModuleIdentifier() + "." + + mf->getFunction()->getName().str(); + + dbgs() << "Splitting " << mf->getFunction()->getName() << "."; + + dumpOddTerminators(); + +// dbgs() << "----------------------------------------\n"; +// lis->dump(); +// dbgs() << "----------------------------------------\n"; + +// std::deque loops; +// std::copy(mli->begin(), mli->end(), std::back_inserter(loops)); +// dbgs() << "Loops:\n"; +// while (!loops.empty()) { +// MachineLoop &loop = *loops.front(); +// loops.pop_front(); +// std::copy(loop.begin(), loop.end(), std::back_inserter(loops)); + +// dumpLoopInfo(loop); +// } + + //lis->dump(); + //exit(0); + + // Setup initial intervals. + for (LiveIntervals::iterator liItr = lis->begin(), liEnd = lis->end(); + liItr != liEnd; ++liItr) { + LiveInterval *li = liItr->second; + + if (TargetRegisterInfo::isVirtualRegister(li->reg) && + !lis->intervalIsInOneMBB(*li)) { + intervals.push_back(li); + } + } + + processIntervals(); + + intervals.clear(); + +// dbgs() << "----------------------------------------\n"; +// lis->dump(); +// dbgs() << "----------------------------------------\n"; + + dumpOddTerminators(); + + //exit(1); + + return false; + } + + void LoopSplitter::releaseMemory() { + fqn.clear(); + intervals.clear(); + loopRangeMap.clear(); + } + + void LoopSplitter::dumpOddTerminators() { + for (MachineFunction::iterator bbItr = mf->begin(), bbEnd = mf->end(); + bbItr != bbEnd; ++bbItr) { + MachineBasicBlock *mbb = &*bbItr; + MachineBasicBlock *a = 0, *b = 0; + SmallVector c; + if (tii->AnalyzeBranch(*mbb, a, b, c)) { + dbgs() << "MBB#" << mbb->getNumber() << " has multiway terminator.\n"; + dbgs() << " Terminators:\n"; + for (MachineBasicBlock::iterator iItr = mbb->begin(), iEnd = mbb->end(); + iItr != iEnd; ++iItr) { + MachineInstr *instr= &*iItr; + dbgs() << " " << *instr << ""; + } + dbgs() << "\n Listed successors: [ "; + for (MachineBasicBlock::succ_iterator sItr = mbb->succ_begin(), sEnd = mbb->succ_end(); + sItr != sEnd; ++sItr) { + MachineBasicBlock *succMBB = *sItr; + dbgs() << succMBB->getNumber() << " "; + } + dbgs() << "]\n\n"; + } + } + } + + void LoopSplitter::dumpLoopInfo(MachineLoop &loop) { + MachineBasicBlock &headerBlock = *loop.getHeader(); + typedef SmallVector ExitEdgesList; + ExitEdgesList exitEdges; + loop.getExitEdges(exitEdges); + + dbgs() << " Header: BB#" << headerBlock.getNumber() << ", Contains: [ "; + for (std::vector::const_iterator + subBlockItr = loop.getBlocks().begin(), + subBlockEnd = loop.getBlocks().end(); + subBlockItr != subBlockEnd; ++subBlockItr) { + MachineBasicBlock &subBlock = **subBlockItr; + dbgs() << "BB#" << subBlock.getNumber() << " "; + } + dbgs() << "], Exit edges: [ "; + for (ExitEdgesList::iterator exitEdgeItr = exitEdges.begin(), + exitEdgeEnd = exitEdges.end(); + exitEdgeItr != exitEdgeEnd; ++exitEdgeItr) { + MachineLoop::Edge &exitEdge = *exitEdgeItr; + dbgs() << "(MBB#" << exitEdge.first->getNumber() + << ", MBB#" << exitEdge.second->getNumber() << ") "; + } + dbgs() << "], Sub-Loop Headers: [ "; + for (MachineLoop::iterator subLoopItr = loop.begin(), + subLoopEnd = loop.end(); + subLoopItr != subLoopEnd; ++subLoopItr) { + MachineLoop &subLoop = **subLoopItr; + MachineBasicBlock &subLoopBlock = *subLoop.getHeader(); + dbgs() << "BB#" << subLoopBlock.getNumber() << " "; + } + dbgs() << "]\n"; + } + + void LoopSplitter::updateTerminators(MachineBasicBlock &mbb) { + mbb.updateTerminator(); + + for (MachineBasicBlock::iterator miItr = mbb.begin(), miEnd = mbb.end(); + miItr != miEnd; ++miItr) { + if (lis->isNotInMIMap(miItr)) { + lis->InsertMachineInstrInMaps(miItr); + } + } + } + + bool LoopSplitter::canInsertPreHeader(MachineLoop &loop) { + MachineBasicBlock *header = loop.getHeader(); + MachineBasicBlock *a = 0, *b = 0; + SmallVector c; + + for (MachineBasicBlock::pred_iterator pbItr = header->pred_begin(), + pbEnd = header->pred_end(); + pbItr != pbEnd; ++pbItr) { + MachineBasicBlock *predBlock = *pbItr; + if (!!tii->AnalyzeBranch(*predBlock, a, b, c)) { + return false; + } + } + + MachineFunction::iterator headerItr(header); + if (headerItr == mf->begin()) + return true; + MachineBasicBlock *headerLayoutPred = llvm::prior(headerItr); + assert(headerLayoutPred != 0 && "Header should have layout pred."); + + return (!tii->AnalyzeBranch(*headerLayoutPred, a, b, c)); + } + + MachineBasicBlock& LoopSplitter::insertPreHeader(MachineLoop &loop) { + assert(loop.getLoopPreheader() == 0 && "Loop already has preheader."); + + MachineBasicBlock &header = *loop.getHeader(); + + // Save the preds - we'll need to update them once we insert the preheader. + typedef std::set HeaderPreds; + HeaderPreds headerPreds; + + for (MachineBasicBlock::pred_iterator predItr = header.pred_begin(), + predEnd = header.pred_end(); + predItr != predEnd; ++predItr) { + if (!loop.contains(*predItr)) + headerPreds.insert(*predItr); + } + + assert(!headerPreds.empty() && "No predecessors for header?"); + + //dbgs() << fqn << " MBB#" << header.getNumber() << " inserting preheader..."; + + MachineBasicBlock *preHeader = + mf->CreateMachineBasicBlock(header.getBasicBlock()); + + assert(preHeader != 0 && "Failed to create pre-header."); + + mf->insert(header, preHeader); + + for (HeaderPreds::iterator hpItr = headerPreds.begin(), + hpEnd = headerPreds.end(); + hpItr != hpEnd; ++hpItr) { + assert(*hpItr != 0 && "How'd a null predecessor get into this set?"); + MachineBasicBlock &hp = **hpItr; + hp.ReplaceUsesOfBlockWith(&header, preHeader); + } + preHeader->addSuccessor(&header); + + MachineBasicBlock *oldLayoutPred = + llvm::prior(MachineFunction::iterator(preHeader)); + if (oldLayoutPred != 0) { + updateTerminators(*oldLayoutPred); + } + + lis->InsertMBBInMaps(preHeader); + + if (MachineLoop *parentLoop = loop.getParentLoop()) { + assert(parentLoop->getHeader() != loop.getHeader() && + "Parent loop has same header?"); + parentLoop->addBasicBlockToLoop(preHeader, mli->getBase()); + + // Invalidate all parent loop ranges. + while (parentLoop != 0) { + loopRangeMap.erase(parentLoop); + parentLoop = parentLoop->getParentLoop(); + } + } + + for (LiveIntervals::iterator liItr = lis->begin(), + liEnd = lis->end(); + liItr != liEnd; ++liItr) { + LiveInterval &li = *liItr->second; + + // Is this safe for physregs? + // TargetRegisterInfo::isPhysicalRegister(li.reg) || + if (!lis->isLiveInToMBB(li, &header)) + continue; + + if (lis->isLiveInToMBB(li, preHeader)) { + assert(lis->isLiveOutOfMBB(li, preHeader) && + "Range terminates in newly added preheader?"); + continue; + } + + bool insertRange = false; + + for (MachineBasicBlock::pred_iterator predItr = preHeader->pred_begin(), + predEnd = preHeader->pred_end(); + predItr != predEnd; ++predItr) { + MachineBasicBlock *predMBB = *predItr; + if (lis->isLiveOutOfMBB(li, predMBB)) { + insertRange = true; + break; + } + } + + if (!insertRange) + continue; + + SlotIndex newDefIdx = lis->getMBBStartIdx(preHeader); + assert(lis->getInstructionFromIndex(newDefIdx) == 0 && + "PHI def index points at actual instruction."); + VNInfo *newVal = li.getNextValue(newDefIdx, 0, lis->getVNInfoAllocator()); + li.addRange(LiveRange(lis->getMBBStartIdx(preHeader), + lis->getMBBEndIdx(preHeader), + newVal)); + } + + + //dbgs() << "Dumping SlotIndexes:\n"; + //sis->dump(); + + //dbgs() << "done. (Added MBB#" << preHeader->getNumber() << ")\n"; + + return *preHeader; + } + + bool LoopSplitter::isCriticalEdge(MachineLoop::Edge &edge) { + assert(edge.first->succ_size() > 1 && "Non-sensical edge."); + if (edge.second->pred_size() > 1) + return true; + return false; + } + + bool LoopSplitter::canSplitEdge(MachineLoop::Edge &edge) { + MachineFunction::iterator outBlockItr(edge.second); + if (outBlockItr == mf->begin()) + return true; + MachineBasicBlock *outBlockLayoutPred = llvm::prior(outBlockItr); + assert(outBlockLayoutPred != 0 && "Should have a layout pred if out!=begin."); + MachineBasicBlock *a = 0, *b = 0; + SmallVector c; + return (!tii->AnalyzeBranch(*outBlockLayoutPred, a, b, c) && + !tii->AnalyzeBranch(*edge.first, a, b, c)); + } + + MachineBasicBlock& LoopSplitter::splitEdge(MachineLoop::Edge &edge, + MachineLoop &loop) { + + MachineBasicBlock &inBlock = *edge.first; + MachineBasicBlock &outBlock = *edge.second; + + assert((inBlock.succ_size() > 1) && (outBlock.pred_size() > 1) && + "Splitting non-critical edge?"); + + //dbgs() << fqn << " Splitting edge (MBB#" << inBlock.getNumber() + // << " -> MBB#" << outBlock.getNumber() << ")..."; + + MachineBasicBlock *splitBlock = + mf->CreateMachineBasicBlock(); + + assert(splitBlock != 0 && "Failed to create split block."); + + mf->insert(&outBlock, splitBlock); + + inBlock.ReplaceUsesOfBlockWith(&outBlock, splitBlock); + splitBlock->addSuccessor(&outBlock); + + MachineBasicBlock *oldLayoutPred = + llvm::prior(MachineFunction::iterator(splitBlock)); + if (oldLayoutPred != 0) { + updateTerminators(*oldLayoutPred); + } + + lis->InsertMBBInMaps(splitBlock); + + loopRangeMap.erase(&loop); + + MachineLoop *splitParentLoop = loop.getParentLoop(); + while (splitParentLoop != 0 && + !splitParentLoop->contains(&outBlock)) { + splitParentLoop = splitParentLoop->getParentLoop(); + } + + if (splitParentLoop != 0) { + assert(splitParentLoop->contains(&loop) && + "Split-block parent doesn't contain original loop?"); + splitParentLoop->addBasicBlockToLoop(splitBlock, mli->getBase()); + + // Invalidate all parent loop ranges. + while (splitParentLoop != 0) { + loopRangeMap.erase(splitParentLoop); + splitParentLoop = splitParentLoop->getParentLoop(); + } + } + + + for (LiveIntervals::iterator liItr = lis->begin(), + liEnd = lis->end(); + liItr != liEnd; ++liItr) { + LiveInterval &li = *liItr->second; + bool intersects = lis->isLiveOutOfMBB(li, &inBlock) && + lis->isLiveInToMBB(li, &outBlock); + if (lis->isLiveInToMBB(li, splitBlock)) { + if (!intersects) { + li.removeRange(lis->getMBBStartIdx(splitBlock), + lis->getMBBEndIdx(splitBlock), true); + } + } else if (intersects) { + SlotIndex newDefIdx = lis->getMBBStartIdx(splitBlock); + assert(lis->getInstructionFromIndex(newDefIdx) == 0 && + "PHI def index points at actual instruction."); + VNInfo *newVal = li.getNextValue(newDefIdx, 0, + lis->getVNInfoAllocator()); + li.addRange(LiveRange(lis->getMBBStartIdx(splitBlock), + lis->getMBBEndIdx(splitBlock), + newVal)); + } + } + + //dbgs() << "done. (Added MBB#" << splitBlock->getNumber() << ")\n"; + + return *splitBlock; + } + + LoopSplitter::LoopRanges& LoopSplitter::getLoopRanges(MachineLoop &loop) { + typedef std::set LoopMBBSet; + LoopRangeMap::iterator lrItr = loopRangeMap.find(&loop); + if (lrItr == loopRangeMap.end()) { + LoopMBBSet loopMBBs((StartSlotComparator(*lis))); + std::copy(loop.block_begin(), loop.block_end(), + std::inserter(loopMBBs, loopMBBs.begin())); + + assert(!loopMBBs.empty() && "No blocks in loop?"); + + LoopRanges &loopRanges = loopRangeMap[&loop]; + assert(loopRanges.empty() && "Loop encountered but not processed?"); + SlotIndex oldEnd = lis->getMBBEndIdx(*loopMBBs.begin()); + loopRanges.push_back( + std::make_pair(lis->getMBBStartIdx(*loopMBBs.begin()), + lis->getInvalidIndex())); + for (LoopMBBSet::iterator curBlockItr = llvm::next(loopMBBs.begin()), + curBlockEnd = loopMBBs.end(); + curBlockItr != curBlockEnd; ++curBlockItr) { + SlotIndex newStart = lis->getMBBStartIdx(*curBlockItr); + if (newStart != oldEnd) { + loopRanges.back().second = oldEnd; + loopRanges.push_back(std::make_pair(newStart, + lis->getInvalidIndex())); + } + oldEnd = lis->getMBBEndIdx(*curBlockItr); + } + + loopRanges.back().second = + lis->getMBBEndIdx(*llvm::prior(loopMBBs.end())); + + return loopRanges; + } + return lrItr->second; + } + + std::pair LoopSplitter::getLoopSubRange( + const LiveRange &lr, + MachineLoop &loop) { + LoopRanges &loopRanges = getLoopRanges(loop); + LoopRanges::iterator lrItr = loopRanges.begin(), + lrEnd = loopRanges.end(); + while (lrItr != lrEnd && lr.start >= lrItr->second) { + ++lrItr; + } + + if (lrItr == lrEnd) { + SlotIndex invalid = lis->getInvalidIndex(); + return std::make_pair(false, SlotPair(invalid, invalid)); + } + + SlotIndex srStart(lr.start < lrItr->first ? lrItr->first : lr.start); + SlotIndex srEnd(lr.end > lrItr->second ? lrItr->second : lr.end); + + return std::make_pair(true, SlotPair(srStart, srEnd)); + } + + void LoopSplitter::dumpLoopRanges(MachineLoop &loop) { + LoopRanges &loopRanges = getLoopRanges(loop); + dbgs() << "For loop MBB#" << loop.getHeader()->getNumber() << ", subranges are: [ "; + for (LoopRanges::iterator lrItr = loopRanges.begin(), lrEnd = loopRanges.end(); + lrItr != lrEnd; ++lrItr) { + dbgs() << "[" << lrItr->first << ", " << lrItr->second << ") "; + } + dbgs() << "]\n"; + } + + void LoopSplitter::processHeader(LoopSplit &split) { + MachineBasicBlock &header = *split.getLoop().getHeader(); + //dbgs() << " Processing loop header BB#" << header.getNumber() << "\n"; + + if (!lis->isLiveInToMBB(split.getLI(), &header)) + return; // Not live in, but nothing wrong so far. + + MachineBasicBlock *preHeader = split.getLoop().getLoopPreheader(); + if (!preHeader) { + + if (!canInsertPreHeader(split.getLoop())) { + split.invalidate(); + return; // Couldn't insert a pre-header. Bail on this interval. + } + + for (MachineBasicBlock::pred_iterator predItr = header.pred_begin(), + predEnd = header.pred_end(); + predItr != predEnd; ++predItr) { + if (lis->isLiveOutOfMBB(split.getLI(), *predItr)) { + split.splitIncoming(); + break; + } + } + } else if (lis->isLiveOutOfMBB(split.getLI(), preHeader)) { + split.splitIncoming(); + } + } + + void LoopSplitter::processLoopExits(LoopSplit &split) { + typedef SmallVector ExitEdgesList; + ExitEdgesList exitEdges; + split.getLoop().getExitEdges(exitEdges); + + //dbgs() << " Processing loop exits:\n"; + + for (ExitEdgesList::iterator exitEdgeItr = exitEdges.begin(), + exitEdgeEnd = exitEdges.end(); + exitEdgeItr != exitEdgeEnd; ++exitEdgeItr) { + MachineLoop::Edge exitEdge = *exitEdgeItr; + + LiveRange *outRange = + split.getLI().getLiveRangeContaining(lis->getMBBStartIdx(exitEdge.second)); + + if (outRange != 0) { + if (isCriticalEdge(exitEdge) && !canSplitEdge(exitEdge)) { + split.invalidate(); + return; + } + + split.splitOutgoing(exitEdge); + } + } + } + + void LoopSplitter::processLoopUses(LoopSplit &split) { + std::set processed; + + for (MachineRegisterInfo::reg_iterator + rItr = mri->reg_begin(split.getLI().reg), + rEnd = mri->reg_end(); + rItr != rEnd; ++rItr) { + MachineInstr &instr = *rItr; + if (split.getLoop().contains(&instr) && processed.count(&instr) == 0) { + split.addLoopInstr(&instr); + processed.insert(&instr); + } + } + + //dbgs() << " Rewriting reg" << li.reg << " to reg" << newLI->reg + // << " in blocks [ "; + //dbgs() << "]\n"; + } + + bool LoopSplitter::splitOverLoop(LiveInterval &li, MachineLoop &loop) { + assert(TargetRegisterInfo::isVirtualRegister(li.reg) && + "Attempt to split physical register."); + + LoopSplit split(*this, li, loop); + processHeader(split); + if (split.isValid()) + processLoopExits(split); + if (split.isValid()) + processLoopUses(split); + if (split.isValid() /* && split.isWorthwhile() */) { + split.apply(); + DEBUG(dbgs() << "Success.\n"); + return true; + } + DEBUG(dbgs() << "Failed.\n"); + return false; + } + + void LoopSplitter::processInterval(LiveInterval &li) { + std::deque loops; + std::copy(mli->begin(), mli->end(), std::back_inserter(loops)); + + while (!loops.empty()) { + MachineLoop &loop = *loops.front(); + loops.pop_front(); + DEBUG( + dbgs() << fqn << " reg" << li.reg << " " << li.weight << " BB#" + << loop.getHeader()->getNumber() << " "; + ); + if (!splitOverLoop(li, loop)) { + // Couldn't split over outer loop, schedule sub-loops to be checked. + std::copy(loop.begin(), loop.end(), std::back_inserter(loops)); + } + } + } + + void LoopSplitter::processIntervals() { + while (!intervals.empty()) { + LiveInterval &li = *intervals.front(); + intervals.pop_front(); + + assert(!lis->intervalIsInOneMBB(li) && + "Single interval in process worklist."); + + processInterval(li); + } + } + +} diff --git a/final/lib/CodeGen/Splitter.h b/final/lib/CodeGen/Splitter.h new file mode 100644 index 00000000000..9fb1b8b3013 --- /dev/null +++ b/final/lib/CodeGen/Splitter.h @@ -0,0 +1,101 @@ +//===-- llvm/CodeGen/Splitter.h - Splitter -*- C++ -*----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SPLITTER_H +#define LLVM_CODEGEN_SPLITTER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" + +#include +#include +#include +#include + +namespace llvm { + + class LiveInterval; + class LiveIntervals; + struct LiveRange; + class LoopSplit; + class MachineDominatorTree; + class MachineRegisterInfo; + class SlotIndexes; + class TargetInstrInfo; + class VNInfo; + + class LoopSplitter : public MachineFunctionPass { + friend class LoopSplit; + public: + static char ID; + + LoopSplitter() : MachineFunctionPass(ID) { + initializeLoopSplitterPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + + virtual void releaseMemory(); + + + private: + + MachineFunction *mf; + LiveIntervals *lis; + MachineLoopInfo *mli; + MachineRegisterInfo *mri; + MachineDominatorTree *mdt; + SlotIndexes *sis; + const TargetInstrInfo *tii; + const TargetRegisterInfo *tri; + + std::string fqn; + std::deque intervals; + + typedef std::pair SlotPair; + typedef std::vector LoopRanges; + typedef std::map LoopRangeMap; + LoopRangeMap loopRangeMap; + + void dumpLoopInfo(MachineLoop &loop); + + void dumpOddTerminators(); + + void updateTerminators(MachineBasicBlock &mbb); + + bool canInsertPreHeader(MachineLoop &loop); + MachineBasicBlock& insertPreHeader(MachineLoop &loop); + + bool isCriticalEdge(MachineLoop::Edge &edge); + bool canSplitEdge(MachineLoop::Edge &edge); + MachineBasicBlock& splitEdge(MachineLoop::Edge &edge, MachineLoop &loop); + + LoopRanges& getLoopRanges(MachineLoop &loop); + std::pair getLoopSubRange(const LiveRange &lr, + MachineLoop &loop); + + void dumpLoopRanges(MachineLoop &loop); + + void processHeader(LoopSplit &split); + void processLoopExits(LoopSplit &split); + void processLoopUses(LoopSplit &split); + + bool splitOverLoop(LiveInterval &li, MachineLoop &loop); + + void processInterval(LiveInterval &li); + + void processIntervals(); + }; + +} + +#endif diff --git a/final/lib/CodeGen/StackProtector.cpp b/final/lib/CodeGen/StackProtector.cpp new file mode 100644 index 00000000000..fcaee4208ba --- /dev/null +++ b/final/lib/CodeGen/StackProtector.cpp @@ -0,0 +1,262 @@ +//===-- StackProtector.cpp - Stack Protector Insertion --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass inserts stack protectors into functions which need them. A variable +// with a random value in it is stored onto the stack before the local variables +// are allocated. Upon exiting the block, the stored value is checked. If it's +// changed, then there was some sort of violation and the program aborts. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "stack-protector" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Attributes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +// SSPBufferSize - The lower bound for a buffer to be considered for stack +// smashing protection. +static cl::opt +SSPBufferSize("stack-protector-buffer-size", cl::init(8), + cl::desc("Lower bound for a buffer to be considered for " + "stack protection")); + +namespace { + class StackProtector : public FunctionPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLowering *TLI; + + Function *F; + Module *M; + + DominatorTree* DT; + + /// InsertStackProtectors - Insert code into the prologue and epilogue of + /// the function. + /// + /// - The prologue code loads and stores the stack guard onto the stack. + /// - The epilogue checks the value stored in the prologue against the + /// original value. It calls __stack_chk_fail if they differ. + bool InsertStackProtectors(); + + /// CreateFailBB - Create a basic block to jump to when the stack protector + /// check fails. + BasicBlock *CreateFailBB(); + + /// RequiresStackProtector - Check whether or not this function needs a + /// stack protector based upon the stack protector level. + bool RequiresStackProtector() const; + public: + static char ID; // Pass identification, replacement for typeid. + StackProtector() : FunctionPass(ID), TLI(0) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + StackProtector(const TargetLowering *tli) + : FunctionPass(ID), TLI(tli) { + initializeStackProtectorPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + } + + virtual bool runOnFunction(Function &Fn); + }; +} // end anonymous namespace + +char StackProtector::ID = 0; +INITIALIZE_PASS(StackProtector, "stack-protector", + "Insert stack protectors", false, false) + +FunctionPass *llvm::createStackProtectorPass(const TargetLowering *tli) { + return new StackProtector(tli); +} + +bool StackProtector::runOnFunction(Function &Fn) { + F = &Fn; + M = F->getParent(); + DT = getAnalysisIfAvailable(); + + if (!RequiresStackProtector()) return false; + + return InsertStackProtectors(); +} + +/// RequiresStackProtector - Check whether or not this function needs a stack +/// protector based upon the stack protector level. The heuristic we use is to +/// add a guard variable to functions that call alloca, and functions with +/// buffers larger than SSPBufferSize bytes. +bool StackProtector::RequiresStackProtector() const { + if (F->hasFnAttr(Attribute::StackProtectReq)) + return true; + + if (!F->hasFnAttr(Attribute::StackProtect)) + return false; + + const TargetData *TD = TLI->getTargetData(); + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { + BasicBlock *BB = I; + + for (BasicBlock::iterator + II = BB->begin(), IE = BB->end(); II != IE; ++II) + if (AllocaInst *AI = dyn_cast(II)) { + if (AI->isArrayAllocation()) + // This is a call to alloca with a variable size. Emit stack + // protectors. + return true; + + if (const ArrayType *AT = dyn_cast(AI->getAllocatedType())) { + // We apparently only care about character arrays. + if (!AT->getElementType()->isIntegerTy(8)) + continue; + + // If an array has more than SSPBufferSize bytes of allocated space, + // then we emit stack protectors. + if (SSPBufferSize <= TD->getTypeAllocSize(AT)) + return true; + } + } + } + + return false; +} + +/// InsertStackProtectors - Insert code into the prologue and epilogue of the +/// function. +/// +/// - The prologue code loads and stores the stack guard onto the stack. +/// - The epilogue checks the value stored in the prologue against the original +/// value. It calls __stack_chk_fail if they differ. +bool StackProtector::InsertStackProtectors() { + BasicBlock *FailBB = 0; // The basic block to jump to if check fails. + BasicBlock *FailBBDom = 0; // FailBB's dominator. + AllocaInst *AI = 0; // Place on stack that stores the stack guard. + Value *StackGuardVar = 0; // The stack guard variable. + + for (Function::iterator I = F->begin(), E = F->end(); I != E; ) { + BasicBlock *BB = I++; + + ReturnInst *RI = dyn_cast(BB->getTerminator()); + if (!RI) continue; + + if (!FailBB) { + // Insert code into the entry block that stores the __stack_chk_guard + // variable onto the stack: + // + // entry: + // StackGuardSlot = alloca i8* + // StackGuard = load __stack_chk_guard + // call void @llvm.stackprotect.create(StackGuard, StackGuardSlot) + // + const PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); + unsigned AddressSpace, Offset; + if (TLI->getStackCookieLocation(AddressSpace, Offset)) { + Constant *OffsetVal = + ConstantInt::get(Type::getInt32Ty(RI->getContext()), Offset); + + StackGuardVar = ConstantExpr::getIntToPtr(OffsetVal, + PointerType::get(PtrTy, AddressSpace)); + } else { + StackGuardVar = M->getOrInsertGlobal("__stack_chk_guard", PtrTy); + } + + BasicBlock &Entry = F->getEntryBlock(); + Instruction *InsPt = &Entry.front(); + + AI = new AllocaInst(PtrTy, "StackGuardSlot", InsPt); + LoadInst *LI = new LoadInst(StackGuardVar, "StackGuard", false, InsPt); + + Value *Args[] = { LI, AI }; + CallInst:: + Create(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), + &Args[0], array_endof(Args), "", InsPt); + + // Create the basic block to jump to when the guard check fails. + FailBB = CreateFailBB(); + if (DT) + FailBBDom = DT->isReachableFromEntry(BB) ? BB : 0; + } + + // For each block with a return instruction, convert this: + // + // return: + // ... + // ret ... + // + // into this: + // + // return: + // ... + // %1 = load __stack_chk_guard + // %2 = load StackGuardSlot + // %3 = cmp i1 %1, %2 + // br i1 %3, label %SP_return, label %CallStackCheckFailBlk + // + // SP_return: + // ret ... + // + // CallStackCheckFailBlk: + // call void @__stack_chk_fail() + // unreachable + + // Split the basic block before the return instruction. + BasicBlock *NewBB = BB->splitBasicBlock(RI, "SP_return"); + if (DT) { + DT->addNewBlock(NewBB, DT->isReachableFromEntry(BB) ? BB : 0); + FailBBDom = DT->findNearestCommonDominator(FailBBDom, BB); + } + + // Remove default branch instruction to the new BB. + BB->getTerminator()->eraseFromParent(); + + // Move the newly created basic block to the point right after the old basic + // block so that it's in the "fall through" position. + NewBB->moveAfter(BB); + + // Generate the stack protector instructions in the old basic block. + LoadInst *LI1 = new LoadInst(StackGuardVar, "", false, BB); + LoadInst *LI2 = new LoadInst(AI, "", true, BB); + ICmpInst *Cmp = new ICmpInst(*BB, CmpInst::ICMP_EQ, LI1, LI2, ""); + BranchInst::Create(NewBB, FailBB, Cmp, BB); + } + + // Return if we didn't modify any basic blocks. I.e., there are no return + // statements in the function. + if (!FailBB) return false; + + if (DT) + DT->addNewBlock(FailBB, FailBBDom); + + return true; +} + +/// CreateFailBB - Create a basic block to jump to when the stack protector +/// check fails. +BasicBlock *StackProtector::CreateFailBB() { + BasicBlock *FailBB = BasicBlock::Create(F->getContext(), + "CallStackCheckFailBlk", F); + Constant *StackChkFail = + M->getOrInsertFunction("__stack_chk_fail", + Type::getVoidTy(F->getContext()), NULL); + CallInst::Create(StackChkFail, "", FailBB); + new UnreachableInst(F->getContext(), FailBB); + return FailBB; +} diff --git a/final/lib/CodeGen/StackSlotColoring.cpp b/final/lib/CodeGen/StackSlotColoring.cpp new file mode 100644 index 00000000000..01f5b5627f4 --- /dev/null +++ b/final/lib/CodeGen/StackSlotColoring.cpp @@ -0,0 +1,768 @@ +//===-- StackSlotColoring.cpp - Stack slot coloring pass. -----------------===// +// +// 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 stack slot coloring pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "stackcoloring" +#include "VirtRegMap.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include +using namespace llvm; + +static cl::opt +DisableSharing("no-stack-slot-sharing", + cl::init(false), cl::Hidden, + cl::desc("Suppress slot sharing during stack coloring")); + +static cl::opt +ColorWithRegsOpt("color-ss-with-regs", + cl::init(false), cl::Hidden, + cl::desc("Color stack slots with free registers")); + + +static cl::opt DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden); + +STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring"); +STATISTIC(NumRegRepl, "Number of stack slot refs replaced with reg refs"); +STATISTIC(NumLoadElim, "Number of loads eliminated"); +STATISTIC(NumStoreElim, "Number of stores eliminated"); +STATISTIC(NumDead, "Number of trivially dead stack accesses eliminated"); + +namespace { + class StackSlotColoring : public MachineFunctionPass { + bool ColorWithRegs; + LiveStacks* LS; + VirtRegMap* VRM; + MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + const MachineLoopInfo *loopInfo; + + // SSIntervals - Spill slot intervals. + std::vector SSIntervals; + + // SSRefs - Keep a list of frame index references for each spill slot. + SmallVector, 16> SSRefs; + + // OrigAlignments - Alignments of stack objects before coloring. + SmallVector OrigAlignments; + + // OrigSizes - Sizess of stack objects before coloring. + SmallVector OrigSizes; + + // AllColors - If index is set, it's a spill slot, i.e. color. + // FIXME: This assumes PEI locate spill slot with smaller indices + // closest to stack pointer / frame pointer. Therefore, smaller + // index == better color. + BitVector AllColors; + + // NextColor - Next "color" that's not yet used. + int NextColor; + + // UsedColors - "Colors" that have been assigned. + BitVector UsedColors; + + // Assignments - Color to intervals mapping. + SmallVector, 16> Assignments; + + public: + static char ID; // Pass identification + StackSlotColoring() : + MachineFunctionPass(ID), ColorWithRegs(false), NextColor(-1) { + initializeStackSlotColoringPass(*PassRegistry::getPassRegistry()); + } + StackSlotColoring(bool RegColor) : + MachineFunctionPass(ID), ColorWithRegs(RegColor), NextColor(-1) { + initializeStackSlotColoringPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineDominatorsID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char* getPassName() const { + return "Stack Slot Coloring"; + } + + private: + void InitializeSlots(); + void ScanForSpillSlotRefs(MachineFunction &MF); + bool OverlapWithAssignments(LiveInterval *li, int Color) const; + int ColorSlot(LiveInterval *li); + bool ColorSlots(MachineFunction &MF); + bool ColorSlotsWithFreeRegs(SmallVector &SlotMapping, + SmallVector, 16> &RevMap, + BitVector &SlotIsReg); + void RewriteInstruction(MachineInstr *MI, int OldFI, int NewFI, + MachineFunction &MF); + bool PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); + bool PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); + void UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, + unsigned Reg, const TargetRegisterClass *RC, + SmallSet &Defs, + MachineFunction &MF); + bool AllMemRefsCanBeUnfolded(int SS); + bool RemoveDeadStores(MachineBasicBlock* MBB); + }; +} // end anonymous namespace + +char StackSlotColoring::ID = 0; + +INITIALIZE_PASS_BEGIN(StackSlotColoring, "stack-slot-coloring", + "Stack Slot Coloring", false, false) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveStacks) +INITIALIZE_PASS_DEPENDENCY(VirtRegMap) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(StackSlotColoring, "stack-slot-coloring", + "Stack Slot Coloring", false, false) + +FunctionPass *llvm::createStackSlotColoringPass(bool RegColor) { + return new StackSlotColoring(RegColor); +} + +namespace { + // IntervalSorter - Comparison predicate that sort live intervals by + // their weight. + struct IntervalSorter { + bool operator()(LiveInterval* LHS, LiveInterval* RHS) const { + return LHS->weight > RHS->weight; + } + }; +} + +/// ScanForSpillSlotRefs - Scan all the machine instructions for spill slot +/// references and update spill slot weights. +void StackSlotColoring::ScanForSpillSlotRefs(MachineFunction &MF) { + SSRefs.resize(MFI->getObjectIndexEnd()); + + // FIXME: Need the equivalent of MachineRegisterInfo for frameindex operands. + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = &*MBBI; + unsigned loopDepth = loopInfo->getLoopDepth(MBB); + for (MachineBasicBlock::iterator MII = MBB->begin(), EE = MBB->end(); + MII != EE; ++MII) { + MachineInstr *MI = &*MII; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (FI < 0) + continue; + if (!LS->hasInterval(FI)) + continue; + LiveInterval &li = LS->getInterval(FI); + if (!MI->isDebugValue()) + li.weight += LiveIntervals::getSpillWeight(false, true, loopDepth); + SSRefs[FI].push_back(MI); + } + } + } +} + +/// InitializeSlots - Process all spill stack slot liveintervals and add them +/// to a sorted (by weight) list. +void StackSlotColoring::InitializeSlots() { + int LastFI = MFI->getObjectIndexEnd(); + OrigAlignments.resize(LastFI); + OrigSizes.resize(LastFI); + AllColors.resize(LastFI); + UsedColors.resize(LastFI); + Assignments.resize(LastFI); + + // Gather all spill slots into a list. + DEBUG(dbgs() << "Spill slot intervals:\n"); + for (LiveStacks::iterator i = LS->begin(), e = LS->end(); i != e; ++i) { + LiveInterval &li = i->second; + DEBUG(li.dump()); + int FI = TargetRegisterInfo::stackSlot2Index(li.reg); + if (MFI->isDeadObjectIndex(FI)) + continue; + SSIntervals.push_back(&li); + OrigAlignments[FI] = MFI->getObjectAlignment(FI); + OrigSizes[FI] = MFI->getObjectSize(FI); + AllColors.set(FI); + } + DEBUG(dbgs() << '\n'); + + // Sort them by weight. + std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter()); + + // Get first "color". + NextColor = AllColors.find_first(); +} + +/// OverlapWithAssignments - Return true if LiveInterval overlaps with any +/// LiveIntervals that have already been assigned to the specified color. +bool +StackSlotColoring::OverlapWithAssignments(LiveInterval *li, int Color) const { + const SmallVector &OtherLIs = Assignments[Color]; + for (unsigned i = 0, e = OtherLIs.size(); i != e; ++i) { + LiveInterval *OtherLI = OtherLIs[i]; + if (OtherLI->overlaps(*li)) + return true; + } + return false; +} + +/// ColorSlotsWithFreeRegs - If there are any free registers available, try +/// replacing spill slots references with registers instead. +bool +StackSlotColoring::ColorSlotsWithFreeRegs(SmallVector &SlotMapping, + SmallVector, 16> &RevMap, + BitVector &SlotIsReg) { + if (!(ColorWithRegs || ColorWithRegsOpt) || !VRM->HasUnusedRegisters()) + return false; + + bool Changed = false; + DEBUG(dbgs() << "Assigning unused registers to spill slots:\n"); + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = TargetRegisterInfo::stackSlot2Index(li->reg); + if (!UsedColors[SS] || li->weight < 20) + // If the weight is < 20, i.e. two references in a loop with depth 1, + // don't bother with it. + continue; + + // These slots allow to share the same registers. + bool AllColored = true; + SmallVector ColoredRegs; + for (unsigned j = 0, ee = RevMap[SS].size(); j != ee; ++j) { + int RSS = RevMap[SS][j]; + const TargetRegisterClass *RC = LS->getIntervalRegClass(RSS); + // If it's not colored to another stack slot, try coloring it + // to a "free" register. + if (!RC) { + AllColored = false; + continue; + } + unsigned Reg = VRM->getFirstUnusedRegister(RC); + if (!Reg) { + AllColored = false; + continue; + } + if (!AllMemRefsCanBeUnfolded(RSS)) { + AllColored = false; + continue; + } else { + DEBUG(dbgs() << "Assigning fi#" << RSS << " to " + << TRI->getName(Reg) << '\n'); + ColoredRegs.push_back(Reg); + SlotMapping[RSS] = Reg; + SlotIsReg.set(RSS); + Changed = true; + } + } + + // Register and its sub-registers are no longer free. + while (!ColoredRegs.empty()) { + unsigned Reg = ColoredRegs.back(); + ColoredRegs.pop_back(); + VRM->setRegisterUsed(Reg); + // If reg is a callee-saved register, it will have to be spilled in + // the prologue. + MRI->setPhysRegUsed(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + VRM->setRegisterUsed(*AS); + MRI->setPhysRegUsed(*AS); + } + } + // This spill slot is dead after the rewrites + if (AllColored) { + MFI->RemoveStackObject(SS); + ++NumEliminated; + } + } + DEBUG(dbgs() << '\n'); + + return Changed; +} + +/// ColorSlot - Assign a "color" (stack slot) to the specified stack slot. +/// +int StackSlotColoring::ColorSlot(LiveInterval *li) { + int Color = -1; + bool Share = false; + if (!DisableSharing) { + // Check if it's possible to reuse any of the used colors. + Color = UsedColors.find_first(); + while (Color != -1) { + if (!OverlapWithAssignments(li, Color)) { + Share = true; + ++NumEliminated; + break; + } + Color = UsedColors.find_next(Color); + } + } + + // Assign it to the first available color (assumed to be the best) if it's + // not possible to share a used color with other objects. + if (!Share) { + assert(NextColor != -1 && "No more spill slots?"); + Color = NextColor; + UsedColors.set(Color); + NextColor = AllColors.find_next(NextColor); + } + + // Record the assignment. + Assignments[Color].push_back(li); + int FI = TargetRegisterInfo::stackSlot2Index(li->reg); + DEBUG(dbgs() << "Assigning fi#" << FI << " to fi#" << Color << "\n"); + + // Change size and alignment of the allocated slot. If there are multiple + // objects sharing the same slot, then make sure the size and alignment + // are large enough for all. + unsigned Align = OrigAlignments[FI]; + if (!Share || Align > MFI->getObjectAlignment(Color)) + MFI->setObjectAlignment(Color, Align); + int64_t Size = OrigSizes[FI]; + if (!Share || Size > MFI->getObjectSize(Color)) + MFI->setObjectSize(Color, Size); + return Color; +} + +/// Colorslots - Color all spill stack slots and rewrite all frameindex machine +/// operands in the function. +bool StackSlotColoring::ColorSlots(MachineFunction &MF) { + unsigned NumObjs = MFI->getObjectIndexEnd(); + SmallVector SlotMapping(NumObjs, -1); + SmallVector SlotWeights(NumObjs, 0.0); + SmallVector, 16> RevMap(NumObjs); + BitVector SlotIsReg(NumObjs); + BitVector UsedColors(NumObjs); + + DEBUG(dbgs() << "Color spill slot intervals:\n"); + bool Changed = false; + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = TargetRegisterInfo::stackSlot2Index(li->reg); + int NewSS = ColorSlot(li); + assert(NewSS >= 0 && "Stack coloring failed?"); + SlotMapping[SS] = NewSS; + RevMap[NewSS].push_back(SS); + SlotWeights[NewSS] += li->weight; + UsedColors.set(NewSS); + Changed |= (SS != NewSS); + } + + DEBUG(dbgs() << "\nSpill slots after coloring:\n"); + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) { + LiveInterval *li = SSIntervals[i]; + int SS = TargetRegisterInfo::stackSlot2Index(li->reg); + li->weight = SlotWeights[SS]; + } + // Sort them by new weight. + std::stable_sort(SSIntervals.begin(), SSIntervals.end(), IntervalSorter()); + +#ifndef NDEBUG + for (unsigned i = 0, e = SSIntervals.size(); i != e; ++i) + DEBUG(SSIntervals[i]->dump()); + DEBUG(dbgs() << '\n'); +#endif + + // Can we "color" a stack slot with a unused register? + Changed |= ColorSlotsWithFreeRegs(SlotMapping, RevMap, SlotIsReg); + + if (!Changed) + return false; + + // Rewrite all MO_FrameIndex operands. + SmallVector, 4> NewDefs(MF.getNumBlockIDs()); + for (unsigned SS = 0, SE = SSRefs.size(); SS != SE; ++SS) { + bool isReg = SlotIsReg[SS]; + int NewFI = SlotMapping[SS]; + if (NewFI == -1 || (NewFI == (int)SS && !isReg)) + continue; + + const TargetRegisterClass *RC = LS->getIntervalRegClass(SS); + SmallVector &RefMIs = SSRefs[SS]; + for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) + if (!isReg) + RewriteInstruction(RefMIs[i], SS, NewFI, MF); + else { + // Rewrite to use a register instead. + unsigned MBBId = RefMIs[i]->getParent()->getNumber(); + SmallSet &Defs = NewDefs[MBBId]; + UnfoldAndRewriteInstruction(RefMIs[i], SS, NewFI, RC, Defs, MF); + } + } + + // Delete unused stack slots. + while (NextColor != -1) { + DEBUG(dbgs() << "Removing unused stack object fi#" << NextColor << "\n"); + MFI->RemoveStackObject(NextColor); + NextColor = AllColors.find_next(NextColor); + } + + return true; +} + +/// AllMemRefsCanBeUnfolded - Return true if all references of the specified +/// spill slot index can be unfolded. +bool StackSlotColoring::AllMemRefsCanBeUnfolded(int SS) { + SmallVector &RefMIs = SSRefs[SS]; + for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) { + MachineInstr *MI = RefMIs[i]; + if (TII->isLoadFromStackSlot(MI, SS) || + TII->isStoreToStackSlot(MI, SS)) + // Restore and spill will become copies. + return true; + if (!TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), false, false)) + return false; + for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = MI->getOperand(j); + if (MO.isFI() && MO.getIndex() != SS) + // If it uses another frameindex, we can, currently* unfold it. + return false; + } + } + return true; +} + +/// RewriteInstruction - Rewrite specified instruction by replacing references +/// to old frame index with new one. +void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI, + int NewFI, MachineFunction &MF) { + // Update the operands. + for (unsigned i = 0, ee = MI->getNumOperands(); i != ee; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (FI != OldFI) + continue; + MO.setIndex(NewFI); + } + + // Update the memory references. This changes the MachineMemOperands + // directly. They may be in use by multiple instructions, however all + // instructions using OldFI are being rewritten to use NewFI. + const Value *OldSV = PseudoSourceValue::getFixedStack(OldFI); + const Value *NewSV = PseudoSourceValue::getFixedStack(NewFI); + for (MachineInstr::mmo_iterator I = MI->memoperands_begin(), + E = MI->memoperands_end(); I != E; ++I) + if ((*I)->getValue() == OldSV) + (*I)->setValue(NewSV); +} + +/// PropagateBackward - Traverse backward and look for the definition of +/// OldReg. If it can successfully update all of the references with NewReg, +/// do so and return true. +bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + if (MII == MBB->begin()) + return false; + + SmallVector Uses; + SmallVector Refs; + while (--MII != MBB->begin()) { + bool FoundDef = false; // Not counting 2address def. + + Uses.clear(); + const TargetInstrDesc &TID = MII->getDesc(); + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isImplicit()) + return false; + + // Abort the use is actually a sub-register def. We don't have enough + // information to figure out if it is really legal. + if (MO.getSubReg() || MII->isSubregToReg()) + return false; + + const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + if (RC && !RC->contains(NewReg)) + return false; + + if (MO.isUse()) { + Uses.push_back(&MO); + } else { + Refs.push_back(&MO); + if (!MII->isRegTiedToUseOperand(i)) + FoundDef = true; + } + } else if (TRI->regsOverlap(Reg, NewReg)) { + return false; + } else if (TRI->regsOverlap(Reg, OldReg)) { + if (!MO.isUse() || !MO.isKill()) + return false; + } + } + + if (FoundDef) { + // Found non-two-address def. Stop here. + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + Refs[i]->setReg(NewReg); + return true; + } + + // Two-address uses must be updated as well. + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + Refs.push_back(Uses[i]); + } + return false; +} + +/// PropagateForward - Traverse forward and look for the kill of OldReg. If +/// it can successfully update all of the uses with NewReg, do so and +/// return true. +bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + if (MII == MBB->end()) + return false; + + SmallVector Uses; + while (++MII != MBB->end()) { + bool FoundKill = false; + const TargetInstrDesc &TID = MII->getDesc(); + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isDef() || MO.isImplicit()) + return false; + + // Abort the use is actually a sub-register use. We don't have enough + // information to figure out if it is really legal. + if (MO.getSubReg()) + return false; + + const TargetRegisterClass *RC = TID.OpInfo[i].getRegClass(TRI); + if (RC && !RC->contains(NewReg)) + return false; + if (MO.isKill()) + FoundKill = true; + + Uses.push_back(&MO); + } else if (TRI->regsOverlap(Reg, NewReg) || + TRI->regsOverlap(Reg, OldReg)) + return false; + } + if (FoundKill) { + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + Uses[i]->setReg(NewReg); + return true; + } + } + return false; +} + +/// UnfoldAndRewriteInstruction - Rewrite specified instruction by unfolding +/// folded memory references and replacing those references with register +/// references instead. +void +StackSlotColoring::UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, + unsigned Reg, + const TargetRegisterClass *RC, + SmallSet &Defs, + MachineFunction &MF) { + MachineBasicBlock *MBB = MI->getParent(); + if (unsigned DstReg = TII->isLoadFromStackSlot(MI, OldFI)) { + if (PropagateForward(MI, MBB, DstReg, Reg)) { + DEBUG(dbgs() << "Eliminated load: "); + DEBUG(MI->dump()); + ++NumLoadElim; + } else { + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(TargetOpcode::COPY), + DstReg).addReg(Reg); + ++NumRegRepl; + } + + if (!Defs.count(Reg)) { + // If this is the first use of Reg in this MBB and it wasn't previously + // defined in MBB, add it to livein. + MBB->addLiveIn(Reg); + Defs.insert(Reg); + } + } else if (unsigned SrcReg = TII->isStoreToStackSlot(MI, OldFI)) { + if (MI->killsRegister(SrcReg) && PropagateBackward(MI, MBB, SrcReg, Reg)) { + DEBUG(dbgs() << "Eliminated store: "); + DEBUG(MI->dump()); + ++NumStoreElim; + } else { + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(TargetOpcode::COPY), Reg) + .addReg(SrcReg); + ++NumRegRepl; + } + + // Remember reg has been defined in MBB. + Defs.insert(Reg); + } else { + SmallVector NewMIs; + bool Success = TII->unfoldMemoryOperand(MF, MI, Reg, false, false, NewMIs); + (void)Success; // Silence compiler warning. + assert(Success && "Failed to unfold!"); + MachineInstr *NewMI = NewMIs[0]; + MBB->insert(MI, NewMI); + ++NumRegRepl; + + if (NewMI->readsRegister(Reg)) { + if (!Defs.count(Reg)) + // If this is the first use of Reg in this MBB and it wasn't previously + // defined in MBB, add it to livein. + MBB->addLiveIn(Reg); + Defs.insert(Reg); + } + } + MBB->erase(MI); +} + +/// RemoveDeadStores - Scan through a basic block and look for loads followed +/// by stores. If they're both using the same stack slot, then the store is +/// definitely dead. This could obviously be much more aggressive (consider +/// pairs with instructions between them), but such extensions might have a +/// considerable compile time impact. +bool StackSlotColoring::RemoveDeadStores(MachineBasicBlock* MBB) { + // FIXME: This could be much more aggressive, but we need to investigate + // the compile time impact of doing so. + bool changed = false; + + SmallVector toErase; + + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (DCELimit != -1 && (int)NumDead >= DCELimit) + break; + + MachineBasicBlock::iterator NextMI = llvm::next(I); + if (NextMI == MBB->end()) continue; + + int FirstSS, SecondSS; + unsigned LoadReg = 0; + unsigned StoreReg = 0; + if (!(LoadReg = TII->isLoadFromStackSlot(I, FirstSS))) continue; + if (!(StoreReg = TII->isStoreToStackSlot(NextMI, SecondSS))) continue; + if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1) continue; + + ++NumDead; + changed = true; + + if (NextMI->findRegisterUseOperandIdx(LoadReg, true, 0) != -1) { + ++NumDead; + toErase.push_back(I); + } + + toErase.push_back(NextMI); + ++I; + } + + for (SmallVector::iterator I = toErase.begin(), + E = toErase.end(); I != E; ++I) + (*I)->eraseFromParent(); + + return changed; +} + + +bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { + DEBUG({ + dbgs() << "********** Stack Slot Coloring **********\n" + << "********** Function: " + << MF.getFunction()->getName() << '\n'; + }); + + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + LS = &getAnalysis(); + VRM = &getAnalysis(); + loopInfo = &getAnalysis(); + + bool Changed = false; + + unsigned NumSlots = LS->getNumIntervals(); + if (NumSlots < 2) { + if (NumSlots == 0 || !VRM->HasUnusedRegisters()) + // Nothing to do! + return false; + } + + // If there are calls to setjmp or sigsetjmp, don't perform stack slot + // coloring. The stack could be modified before the longjmp is executed, + // resulting in the wrong value being used afterwards. (See + // .) + if (MF.callsSetJmp()) + return false; + + // Gather spill slot references + ScanForSpillSlotRefs(MF); + InitializeSlots(); + Changed = ColorSlots(MF); + + NextColor = -1; + SSIntervals.clear(); + for (unsigned i = 0, e = SSRefs.size(); i != e; ++i) + SSRefs[i].clear(); + SSRefs.clear(); + OrigAlignments.clear(); + OrigSizes.clear(); + AllColors.clear(); + UsedColors.clear(); + for (unsigned i = 0, e = Assignments.size(); i != e; ++i) + Assignments[i].clear(); + Assignments.clear(); + + if (Changed) { + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= RemoveDeadStores(I); + } + + return Changed; +} diff --git a/final/lib/CodeGen/StrongPHIElimination.cpp b/final/lib/CodeGen/StrongPHIElimination.cpp new file mode 100644 index 00000000000..ec7829ec39f --- /dev/null +++ b/final/lib/CodeGen/StrongPHIElimination.cpp @@ -0,0 +1,829 @@ +//===- StrongPHIElimination.cpp - Eliminate PHI nodes by inserting copies -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass eliminates PHI instructions by aggressively coalescing the copies +// that would be inserted by a naive algorithm and only inserting the copies +// that are necessary. The coalescing technique initially assumes that all +// registers appearing in a PHI instruction do not interfere. It then eliminates +// proven interferences, using dominators to only perform a linear number of +// interference tests instead of the quadratic number of interference tests +// that this would naively require. This is a technique derived from: +// +// Budimlic, et al. Fast copy coalescing and live-range identification. +// In Proceedings of the ACM SIGPLAN 2002 Conference on Programming Language +// Design and Implementation (Berlin, Germany, June 17 - 19, 2002). +// PLDI '02. ACM, New York, NY, 25-32. +// +// The original implementation constructs a data structure they call a dominance +// forest for this purpose. The dominance forest was shown to be unnecessary, +// as it is possible to emulate the creation and traversal of a dominance forest +// by directly using the dominator tree, rather than actually constructing the +// dominance forest. This technique is explained in: +// +// Boissinot, et al. Revisiting Out-of-SSA Translation for Correctness, Code +// Quality and Efficiency, +// In Proceedings of the 7th annual IEEE/ACM International Symposium on Code +// Generation and Optimization (Seattle, Washington, March 22 - 25, 2009). +// CGO '09. IEEE, Washington, DC, 114-125. +// +// Careful implementation allows for all of the dominator forest interference +// checks to be performed at once in a single depth-first traversal of the +// dominator tree, which is what is implemented here. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "strongphielim" +#include "PHIEliminationUtils.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace { + class StrongPHIElimination : public MachineFunctionPass { + public: + static char ID; // Pass identification, replacement for typeid + StrongPHIElimination() : MachineFunctionPass(ID) { + initializeStrongPHIEliminationPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage&) const; + bool runOnMachineFunction(MachineFunction&); + + private: + /// This struct represents a single node in the union-find data structure + /// representing the variable congruence classes. There is one difference + /// from a normal union-find data structure. We steal two bits from the parent + /// pointer . One of these bits is used to represent whether the register + /// itself has been isolated, and the other is used to represent whether the + /// PHI with that register as its destination has been isolated. + /// + /// Note that this leads to the strange situation where the leader of a + /// congruence class may no longer logically be a member, due to being + /// isolated. + struct Node { + enum Flags { + kRegisterIsolatedFlag = 1, + kPHIIsolatedFlag = 2 + }; + Node(unsigned v) : value(v), rank(0) { parent.setPointer(this); } + + Node *getLeader(); + + PointerIntPair parent; + unsigned value; + unsigned rank; + }; + + /// Add a register in a new congruence class containing only itself. + void addReg(unsigned); + + /// Join the congruence classes of two registers. This function is biased + /// towards the left argument, i.e. after + /// + /// addReg(r2); + /// unionRegs(r1, r2); + /// + /// the leader of the unioned congruence class is the same as the leader of + /// r1's congruence class prior to the union. This is actually relied upon + /// in the copy insertion code. + void unionRegs(unsigned, unsigned); + + /// Get the color of a register. The color is 0 if the register has been + /// isolated. + unsigned getRegColor(unsigned); + + // Isolate a register. + void isolateReg(unsigned); + + /// Get the color of a PHI. The color of a PHI is 0 if the PHI has been + /// isolated. Otherwise, it is the original color of its destination and + /// all of its operands (before they were isolated, if they were). + unsigned getPHIColor(MachineInstr*); + + /// Isolate a PHI. + void isolatePHI(MachineInstr*); + + /// Traverses a basic block, splitting any interferences found between + /// registers in the same congruence class. It takes two DenseMaps as + /// arguments that it also updates: CurrentDominatingParent, which maps + /// a color to the register in that congruence class whose definition was + /// most recently seen, and ImmediateDominatingParent, which maps a register + /// to the register in the same congruence class that most immediately + /// dominates it. + /// + /// This function assumes that it is being called in a depth-first traversal + /// of the dominator tree. + void SplitInterferencesForBasicBlock( + MachineBasicBlock&, + DenseMap &CurrentDominatingParent, + DenseMap &ImmediateDominatingParent); + + // Lowers a PHI instruction, inserting copies of the source and destination + // registers as necessary. + void InsertCopiesForPHI(MachineInstr*, MachineBasicBlock*); + + // Merges the live interval of Reg into NewReg and renames Reg to NewReg + // everywhere that Reg appears. Requires Reg and NewReg to have non- + // overlapping lifetimes. + void MergeLIsAndRename(unsigned Reg, unsigned NewReg); + + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + MachineDominatorTree *DT; + LiveIntervals *LI; + + BumpPtrAllocator Allocator; + + DenseMap RegNodeMap; + + // Maps a basic block to a list of its defs of registers that appear as PHI + // sources. + DenseMap > PHISrcDefs; + + // Maps a color to a pair of a MachineInstr* and a virtual register, which + // is the operand of that PHI corresponding to the current basic block. + DenseMap > CurrentPHIForColor; + + // FIXME: Can these two data structures be combined? Would a std::multimap + // be any better? + + // Stores pairs of predecessor basic blocks and the source registers of + // inserted copy instructions. + typedef DenseSet > SrcCopySet; + SrcCopySet InsertedSrcCopySet; + + // Maps pairs of predecessor basic blocks and colors to their defining copy + // instructions. + typedef DenseMap, MachineInstr*> + SrcCopyMap; + SrcCopyMap InsertedSrcCopyMap; + + // Maps inserted destination copy registers to their defining copy + // instructions. + typedef DenseMap DestCopyMap; + DestCopyMap InsertedDestCopies; + }; + + struct MIIndexCompare { + MIIndexCompare(LiveIntervals *LiveIntervals) : LI(LiveIntervals) { } + + bool operator()(const MachineInstr *LHS, const MachineInstr *RHS) const { + return LI->getInstructionIndex(LHS) < LI->getInstructionIndex(RHS); + } + + LiveIntervals *LI; + }; +} // namespace + +STATISTIC(NumPHIsLowered, "Number of PHIs lowered"); +STATISTIC(NumDestCopiesInserted, "Number of destination copies inserted"); +STATISTIC(NumSrcCopiesInserted, "Number of source copies inserted"); + +char StrongPHIElimination::ID = 0; +INITIALIZE_PASS_BEGIN(StrongPHIElimination, "strong-phi-node-elimination", + "Eliminate PHI nodes for register allocation, intelligently", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) +INITIALIZE_PASS_DEPENDENCY(SlotIndexes) +INITIALIZE_PASS_DEPENDENCY(LiveIntervals) +INITIALIZE_PASS_END(StrongPHIElimination, "strong-phi-node-elimination", + "Eliminate PHI nodes for register allocation, intelligently", false, false) + +char &llvm::StrongPHIEliminationID = StrongPHIElimination::ID; + +void StrongPHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +static MachineOperand *findLastUse(MachineBasicBlock *MBB, unsigned Reg) { + // FIXME: This only needs to check from the first terminator, as only the + // first terminator can use a virtual register. + for (MachineBasicBlock::reverse_iterator RI = MBB->rbegin(); ; ++RI) { + assert (RI != MBB->rend()); + MachineInstr *MI = &*RI; + + for (MachineInstr::mop_iterator OI = MI->operands_begin(), + OE = MI->operands_end(); OI != OE; ++OI) { + MachineOperand &MO = *OI; + if (MO.isReg() && MO.isUse() && MO.getReg() == Reg) + return &MO; + } + } + return NULL; +} + +bool StrongPHIElimination::runOnMachineFunction(MachineFunction &MF) { + MRI = &MF.getRegInfo(); + TII = MF.getTarget().getInstrInfo(); + DT = &getAnalysis(); + LI = &getAnalysis(); + + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + unsigned DestReg = BBI->getOperand(0).getReg(); + addReg(DestReg); + PHISrcDefs[I].push_back(BBI); + + for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) { + MachineOperand &SrcMO = BBI->getOperand(i); + unsigned SrcReg = SrcMO.getReg(); + addReg(SrcReg); + unionRegs(DestReg, SrcReg); + + MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (DefMI) + PHISrcDefs[DefMI->getParent()].push_back(DefMI); + } + } + } + + // Perform a depth-first traversal of the dominator tree, splitting + // interferences amongst PHI-congruence classes. + DenseMap CurrentDominatingParent; + DenseMap ImmediateDominatingParent; + for (df_iterator DI = df_begin(DT->getRootNode()), + DE = df_end(DT->getRootNode()); DI != DE; ++DI) { + SplitInterferencesForBasicBlock(*DI->getBlock(), + CurrentDominatingParent, + ImmediateDominatingParent); + } + + // Insert copies for all PHI source and destination registers. + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + InsertCopiesForPHI(BBI, I); + } + } + + // FIXME: Preserve the equivalence classes during copy insertion and use + // the preversed equivalence classes instead of recomputing them. + RegNodeMap.clear(); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + unsigned DestReg = BBI->getOperand(0).getReg(); + addReg(DestReg); + + for (unsigned i = 1; i < BBI->getNumOperands(); i += 2) { + unsigned SrcReg = BBI->getOperand(i).getReg(); + addReg(SrcReg); + unionRegs(DestReg, SrcReg); + } + } + } + + DenseMap RegRenamingMap; + bool Changed = false; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); + while (BBI != BBE && BBI->isPHI()) { + MachineInstr *PHI = BBI; + + assert(PHI->getNumOperands() > 0); + + unsigned SrcReg = PHI->getOperand(1).getReg(); + unsigned SrcColor = getRegColor(SrcReg); + unsigned NewReg = RegRenamingMap[SrcColor]; + if (!NewReg) { + NewReg = SrcReg; + RegRenamingMap[SrcColor] = SrcReg; + } + MergeLIsAndRename(SrcReg, NewReg); + + unsigned DestReg = PHI->getOperand(0).getReg(); + if (!InsertedDestCopies.count(DestReg)) + MergeLIsAndRename(DestReg, NewReg); + + for (unsigned i = 3; i < PHI->getNumOperands(); i += 2) { + unsigned SrcReg = PHI->getOperand(i).getReg(); + MergeLIsAndRename(SrcReg, NewReg); + } + + ++BBI; + LI->RemoveMachineInstrFromMaps(PHI); + PHI->eraseFromParent(); + Changed = true; + } + } + + // Due to the insertion of copies to split live ranges, the live intervals are + // guaranteed to not overlap, except in one case: an original PHI source and a + // PHI destination copy. In this case, they have the same value and thus don't + // truly intersect, so we merge them into the value live at that point. + // FIXME: Is there some better way we can handle this? + for (DestCopyMap::iterator I = InsertedDestCopies.begin(), + E = InsertedDestCopies.end(); I != E; ++I) { + unsigned DestReg = I->first; + unsigned DestColor = getRegColor(DestReg); + unsigned NewReg = RegRenamingMap[DestColor]; + + LiveInterval &DestLI = LI->getInterval(DestReg); + LiveInterval &NewLI = LI->getInterval(NewReg); + + assert(DestLI.ranges.size() == 1 + && "PHI destination copy's live interval should be a single live " + "range from the beginning of the BB to the copy instruction."); + LiveRange *DestLR = DestLI.begin(); + VNInfo *NewVNI = NewLI.getVNInfoAt(DestLR->start); + if (!NewVNI) { + NewVNI = NewLI.createValueCopy(DestLR->valno, LI->getVNInfoAllocator()); + MachineInstr *CopyInstr = I->second; + CopyInstr->getOperand(1).setIsKill(true); + } + + LiveRange NewLR(DestLR->start, DestLR->end, NewVNI); + NewLI.addRange(NewLR); + + LI->removeInterval(DestReg); + MRI->replaceRegWith(DestReg, NewReg); + } + + // Adjust the live intervals of all PHI source registers to handle the case + // where the PHIs in successor blocks were the only later uses of the source + // register. + for (SrcCopySet::iterator I = InsertedSrcCopySet.begin(), + E = InsertedSrcCopySet.end(); I != E; ++I) { + MachineBasicBlock *MBB = I->first; + unsigned SrcReg = I->second; + if (unsigned RenamedRegister = RegRenamingMap[getRegColor(SrcReg)]) + SrcReg = RenamedRegister; + + LiveInterval &SrcLI = LI->getInterval(SrcReg); + + bool isLiveOut = false; + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + if (SrcLI.liveAt(LI->getMBBStartIdx(*SI))) { + isLiveOut = true; + break; + } + } + + if (isLiveOut) + continue; + + MachineOperand *LastUse = findLastUse(MBB, SrcReg); + assert(LastUse); + SlotIndex LastUseIndex = LI->getInstructionIndex(LastUse->getParent()); + SrcLI.removeRange(LastUseIndex.getDefIndex(), LI->getMBBEndIdx(MBB)); + LastUse->setIsKill(true); + } + + LI->renumber(); + + Allocator.Reset(); + RegNodeMap.clear(); + PHISrcDefs.clear(); + InsertedSrcCopySet.clear(); + InsertedSrcCopyMap.clear(); + InsertedDestCopies.clear(); + + return Changed; +} + +void StrongPHIElimination::addReg(unsigned Reg) { + if (RegNodeMap.count(Reg)) + return; + RegNodeMap[Reg] = new (Allocator) Node(Reg); +} + +StrongPHIElimination::Node* +StrongPHIElimination::Node::getLeader() { + Node *N = this; + Node *Parent = parent.getPointer(); + Node *Grandparent = Parent->parent.getPointer(); + + while (Parent != Grandparent) { + N->parent.setPointer(Grandparent); + N = Grandparent; + Parent = Parent->parent.getPointer(); + Grandparent = Parent->parent.getPointer(); + } + + return Parent; +} + +unsigned StrongPHIElimination::getRegColor(unsigned Reg) { + DenseMap::iterator RI = RegNodeMap.find(Reg); + if (RI == RegNodeMap.end()) + return 0; + Node *Node = RI->second; + if (Node->parent.getInt() & Node::kRegisterIsolatedFlag) + return 0; + return Node->getLeader()->value; +} + +void StrongPHIElimination::unionRegs(unsigned Reg1, unsigned Reg2) { + Node *Node1 = RegNodeMap[Reg1]->getLeader(); + Node *Node2 = RegNodeMap[Reg2]->getLeader(); + + if (Node1->rank > Node2->rank) { + Node2->parent.setPointer(Node1->getLeader()); + } else if (Node1->rank < Node2->rank) { + Node1->parent.setPointer(Node2->getLeader()); + } else if (Node1 != Node2) { + Node2->parent.setPointer(Node1->getLeader()); + Node1->rank++; + } +} + +void StrongPHIElimination::isolateReg(unsigned Reg) { + Node *Node = RegNodeMap[Reg]; + Node->parent.setInt(Node->parent.getInt() | Node::kRegisterIsolatedFlag); +} + +unsigned StrongPHIElimination::getPHIColor(MachineInstr *PHI) { + assert(PHI->isPHI()); + + unsigned DestReg = PHI->getOperand(0).getReg(); + Node *DestNode = RegNodeMap[DestReg]; + if (DestNode->parent.getInt() & Node::kPHIIsolatedFlag) + return 0; + + for (unsigned i = 1; i < PHI->getNumOperands(); i += 2) { + unsigned SrcColor = getRegColor(PHI->getOperand(i).getReg()); + if (SrcColor) + return SrcColor; + } + return 0; +} + +void StrongPHIElimination::isolatePHI(MachineInstr *PHI) { + assert(PHI->isPHI()); + Node *Node = RegNodeMap[PHI->getOperand(0).getReg()]; + Node->parent.setInt(Node->parent.getInt() | Node::kPHIIsolatedFlag); +} + +/// SplitInterferencesForBasicBlock - traverses a basic block, splitting any +/// interferences found between registers in the same congruence class. It +/// takes two DenseMaps as arguments that it also updates: +/// +/// 1) CurrentDominatingParent, which maps a color to the register in that +/// congruence class whose definition was most recently seen. +/// +/// 2) ImmediateDominatingParent, which maps a register to the register in the +/// same congruence class that most immediately dominates it. +/// +/// This function assumes that it is being called in a depth-first traversal +/// of the dominator tree. +/// +/// The algorithm used here is a generalization of the dominance-based SSA test +/// for two variables. If there are variables a_1, ..., a_n such that +/// +/// def(a_1) dom ... dom def(a_n), +/// +/// then we can test for an interference between any two a_i by only using O(n) +/// interference tests between pairs of variables. If i < j and a_i and a_j +/// interfere, then a_i is alive at def(a_j), so it is also alive at def(a_i+1). +/// Thus, in order to test for an interference involving a_i, we need only check +/// for a potential interference with a_i+1. +/// +/// This method can be generalized to arbitrary sets of variables by performing +/// a depth-first traversal of the dominator tree. As we traverse down a branch +/// of the dominator tree, we keep track of the current dominating variable and +/// only perform an interference test with that variable. However, when we go to +/// another branch of the dominator tree, the definition of the current dominating +/// variable may no longer dominate the current block. In order to correct this, +/// we need to use a stack of past choices of the current dominating variable +/// and pop from this stack until we find a variable whose definition actually +/// dominates the current block. +/// +/// There will be one push on this stack for each variable that has become the +/// current dominating variable, so instead of using an explicit stack we can +/// simply associate the previous choice for a current dominating variable with +/// the new choice. This works better in our implementation, where we test for +/// interference in multiple distinct sets at once. +void +StrongPHIElimination::SplitInterferencesForBasicBlock( + MachineBasicBlock &MBB, + DenseMap &CurrentDominatingParent, + DenseMap &ImmediateDominatingParent) { + // Sort defs by their order in the original basic block, as the code below + // assumes that it is processing definitions in dominance order. + std::vector &DefInstrs = PHISrcDefs[&MBB]; + std::sort(DefInstrs.begin(), DefInstrs.end(), MIIndexCompare(LI)); + + for (std::vector::const_iterator BBI = DefInstrs.begin(), + BBE = DefInstrs.end(); BBI != BBE; ++BBI) { + for (MachineInstr::const_mop_iterator I = (*BBI)->operands_begin(), + E = (*BBI)->operands_end(); I != E; ++I) { + const MachineOperand &MO = *I; + + // FIXME: This would be faster if it were possible to bail out of checking + // an instruction's operands after the explicit defs, but this is incorrect + // for variadic instructions, which may appear before register allocation + // in the future. + if (!MO.isReg() || !MO.isDef()) + continue; + + unsigned DestReg = MO.getReg(); + if (!DestReg || !TargetRegisterInfo::isVirtualRegister(DestReg)) + continue; + + // If the virtual register being defined is not used in any PHI or has + // already been isolated, then there are no more interferences to check. + unsigned DestColor = getRegColor(DestReg); + if (!DestColor) + continue; + + // The input to this pass sometimes is not in SSA form in every basic + // block, as some virtual registers have redefinitions. We could eliminate + // this by fixing the passes that generate the non-SSA code, or we could + // handle it here by tracking defining machine instructions rather than + // virtual registers. For now, we just handle the situation conservatively + // in a way that will possibly lead to false interferences. + unsigned &CurrentParent = CurrentDominatingParent[DestColor]; + unsigned NewParent = CurrentParent; + if (NewParent == DestReg) + continue; + + // Pop registers from the stack represented by ImmediateDominatingParent + // until we find a parent that dominates the current instruction. + while (NewParent && (!DT->dominates(MRI->getVRegDef(NewParent), *BBI) + || !getRegColor(NewParent))) + NewParent = ImmediateDominatingParent[NewParent]; + + // If NewParent is nonzero, then its definition dominates the current + // instruction, so it is only necessary to check for the liveness of + // NewParent in order to check for an interference. + if (NewParent + && LI->getInterval(NewParent).liveAt(LI->getInstructionIndex(*BBI))) { + // If there is an interference, always isolate the new register. This + // could be improved by using a heuristic that decides which of the two + // registers to isolate. + isolateReg(DestReg); + CurrentParent = NewParent; + } else { + // If there is no interference, update ImmediateDominatingParent and set + // the CurrentDominatingParent for this color to the current register. + ImmediateDominatingParent[DestReg] = NewParent; + CurrentParent = DestReg; + } + } + } + + // We now walk the PHIs in successor blocks and check for interferences. This + // is necesary because the use of a PHI's operands are logically contained in + // the predecessor block. The def of a PHI's destination register is processed + // along with the other defs in a basic block. + + CurrentPHIForColor.clear(); + + for (MachineBasicBlock::succ_iterator SI = MBB.succ_begin(), + SE = MBB.succ_end(); SI != SE; ++SI) { + for (MachineBasicBlock::iterator BBI = (*SI)->begin(), BBE = (*SI)->end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + MachineInstr *PHI = BBI; + + // If a PHI is already isolated, either by being isolated directly or + // having all of its operands isolated, ignore it. + unsigned Color = getPHIColor(PHI); + if (!Color) + continue; + + // Find the index of the PHI operand that corresponds to this basic block. + unsigned PredIndex; + for (PredIndex = 1; PredIndex < PHI->getNumOperands(); PredIndex += 2) { + if (PHI->getOperand(PredIndex + 1).getMBB() == &MBB) + break; + } + assert(PredIndex < PHI->getNumOperands()); + unsigned PredOperandReg = PHI->getOperand(PredIndex).getReg(); + + // Pop registers from the stack represented by ImmediateDominatingParent + // until we find a parent that dominates the current instruction. + unsigned &CurrentParent = CurrentDominatingParent[Color]; + unsigned NewParent = CurrentParent; + while (NewParent + && (!DT->dominates(MRI->getVRegDef(NewParent)->getParent(), &MBB) + || !getRegColor(NewParent))) + NewParent = ImmediateDominatingParent[NewParent]; + CurrentParent = NewParent; + + // If there is an interference with a register, always isolate the + // register rather than the PHI. It is also possible to isolate the + // PHI, but that introduces copies for all of the registers involved + // in that PHI. + if (NewParent && LI->isLiveOutOfMBB(LI->getInterval(NewParent), &MBB) + && NewParent != PredOperandReg) + isolateReg(NewParent); + + std::pair + &CurrentPHI = CurrentPHIForColor[Color]; + + // If two PHIs have the same operand from every shared predecessor, then + // they don't actually interfere. Otherwise, isolate the current PHI. This + // could possibly be improved, e.g. we could isolate the PHI with the + // fewest operands. + if (CurrentPHI.first && CurrentPHI.second != PredOperandReg) + isolatePHI(PHI); + else + CurrentPHI = std::make_pair(PHI, PredOperandReg); + } + } +} + +void StrongPHIElimination::InsertCopiesForPHI(MachineInstr *PHI, + MachineBasicBlock *MBB) { + assert(PHI->isPHI()); + ++NumPHIsLowered; + unsigned PHIColor = getPHIColor(PHI); + + for (unsigned i = 1; i < PHI->getNumOperands(); i += 2) { + MachineOperand &SrcMO = PHI->getOperand(i); + + // If a source is defined by an implicit def, there is no need to insert a + // copy in the predecessor. + if (SrcMO.isUndef()) + continue; + + unsigned SrcReg = SrcMO.getReg(); + assert(TargetRegisterInfo::isVirtualRegister(SrcReg) && + "Machine PHI Operands must all be virtual registers!"); + + MachineBasicBlock *PredBB = PHI->getOperand(i + 1).getMBB(); + unsigned SrcColor = getRegColor(SrcReg); + + // If neither the PHI nor the operand were isolated, then we only need to + // set the phi-kill flag on the VNInfo at this PHI. + if (PHIColor && SrcColor == PHIColor) { + LiveInterval &SrcInterval = LI->getInterval(SrcReg); + SlotIndex PredIndex = LI->getMBBEndIdx(PredBB); + VNInfo *SrcVNI = SrcInterval.getVNInfoAt(PredIndex.getPrevIndex()); + assert(SrcVNI); + SrcVNI->setHasPHIKill(true); + continue; + } + + unsigned CopyReg = 0; + if (PHIColor) { + SrcCopyMap::const_iterator I + = InsertedSrcCopyMap.find(std::make_pair(PredBB, PHIColor)); + CopyReg + = I != InsertedSrcCopyMap.end() ? I->second->getOperand(0).getReg() : 0; + } + + if (!CopyReg) { + const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); + CopyReg = MRI->createVirtualRegister(RC); + + MachineBasicBlock::iterator + CopyInsertPoint = findPHICopyInsertPoint(PredBB, MBB, SrcReg); + unsigned SrcSubReg = SrcMO.getSubReg(); + MachineInstr *CopyInstr = BuildMI(*PredBB, + CopyInsertPoint, + PHI->getDebugLoc(), + TII->get(TargetOpcode::COPY), + CopyReg).addReg(SrcReg, 0, SrcSubReg); + LI->InsertMachineInstrInMaps(CopyInstr); + ++NumSrcCopiesInserted; + + // addLiveRangeToEndOfBlock() also adds the phikill flag to the VNInfo for + // the newly added range. + LI->addLiveRangeToEndOfBlock(CopyReg, CopyInstr); + InsertedSrcCopySet.insert(std::make_pair(PredBB, SrcReg)); + + addReg(CopyReg); + if (PHIColor) { + unionRegs(PHIColor, CopyReg); + assert(getRegColor(CopyReg) != CopyReg); + } else { + PHIColor = CopyReg; + assert(getRegColor(CopyReg) == CopyReg); + } + + if (!InsertedSrcCopyMap.count(std::make_pair(PredBB, PHIColor))) + InsertedSrcCopyMap[std::make_pair(PredBB, PHIColor)] = CopyInstr; + } + + SrcMO.setReg(CopyReg); + + // If SrcReg is not live beyond the PHI, trim its interval so that it is no + // longer live-in to MBB. Note that SrcReg may appear in other PHIs that are + // processed later, but this is still correct to do at this point because we + // never rely on LiveIntervals being correct while inserting copies. + // FIXME: Should this just count uses at PHIs like the normal PHIElimination + // pass does? + LiveInterval &SrcLI = LI->getInterval(SrcReg); + SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); + SlotIndex PHIIndex = LI->getInstructionIndex(PHI); + SlotIndex NextInstrIndex = PHIIndex.getNextIndex(); + if (SrcLI.liveAt(MBBStartIndex) && SrcLI.expiredAt(NextInstrIndex)) + SrcLI.removeRange(MBBStartIndex, PHIIndex, true); + } + + unsigned DestReg = PHI->getOperand(0).getReg(); + unsigned DestColor = getRegColor(DestReg); + + if (PHIColor && DestColor == PHIColor) { + LiveInterval &DestLI = LI->getInterval(DestReg); + + // Set the phi-def flag for the VN at this PHI. + SlotIndex PHIIndex = LI->getInstructionIndex(PHI); + VNInfo *DestVNI = DestLI.getVNInfoAt(PHIIndex.getDefIndex()); + assert(DestVNI); + DestVNI->setIsPHIDef(true); + + // Prior to PHI elimination, the live ranges of PHIs begin at their defining + // instruction. After PHI elimination, PHI instructions are replaced by VNs + // with the phi-def flag set, and the live ranges of these VNs start at the + // beginning of the basic block. + SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); + DestVNI->def = MBBStartIndex; + DestLI.addRange(LiveRange(MBBStartIndex, + PHIIndex.getDefIndex(), + DestVNI)); + return; + } + + const TargetRegisterClass *RC = MRI->getRegClass(DestReg); + unsigned CopyReg = MRI->createVirtualRegister(RC); + + MachineInstr *CopyInstr = BuildMI(*MBB, + MBB->SkipPHIsAndLabels(MBB->begin()), + PHI->getDebugLoc(), + TII->get(TargetOpcode::COPY), + DestReg).addReg(CopyReg); + LI->InsertMachineInstrInMaps(CopyInstr); + PHI->getOperand(0).setReg(CopyReg); + ++NumDestCopiesInserted; + + // Add the region from the beginning of MBB to the copy instruction to + // CopyReg's live interval, and give the VNInfo the phidef flag. + LiveInterval &CopyLI = LI->getOrCreateInterval(CopyReg); + SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB); + SlotIndex DestCopyIndex = LI->getInstructionIndex(CopyInstr); + VNInfo *CopyVNI = CopyLI.getNextValue(MBBStartIndex, + CopyInstr, + LI->getVNInfoAllocator()); + CopyVNI->setIsPHIDef(true); + CopyLI.addRange(LiveRange(MBBStartIndex, + DestCopyIndex.getDefIndex(), + CopyVNI)); + + // Adjust DestReg's live interval to adjust for its new definition at + // CopyInstr. + LiveInterval &DestLI = LI->getOrCreateInterval(DestReg); + SlotIndex PHIIndex = LI->getInstructionIndex(PHI); + DestLI.removeRange(PHIIndex.getDefIndex(), DestCopyIndex.getDefIndex()); + + VNInfo *DestVNI = DestLI.getVNInfoAt(DestCopyIndex.getDefIndex()); + assert(DestVNI); + DestVNI->def = DestCopyIndex.getDefIndex(); + + InsertedDestCopies[CopyReg] = CopyInstr; +} + +void StrongPHIElimination::MergeLIsAndRename(unsigned Reg, unsigned NewReg) { + if (Reg == NewReg) + return; + + LiveInterval &OldLI = LI->getInterval(Reg); + LiveInterval &NewLI = LI->getInterval(NewReg); + + // Merge the live ranges of the two registers. + DenseMap VNMap; + for (LiveInterval::iterator LRI = OldLI.begin(), LRE = OldLI.end(); + LRI != LRE; ++LRI) { + LiveRange OldLR = *LRI; + VNInfo *OldVN = OldLR.valno; + + VNInfo *&NewVN = VNMap[OldVN]; + if (!NewVN) { + NewVN = NewLI.createValueCopy(OldVN, LI->getVNInfoAllocator()); + VNMap[OldVN] = NewVN; + } + + LiveRange LR(OldLR.start, OldLR.end, NewVN); + NewLI.addRange(LR); + } + + // Remove the LiveInterval for the register being renamed and replace all + // of its defs and uses with the new register. + LI->removeInterval(Reg); + MRI->replaceRegWith(Reg, NewReg); +} diff --git a/final/lib/CodeGen/TailDuplication.cpp b/final/lib/CodeGen/TailDuplication.cpp new file mode 100644 index 00000000000..04d3d311b41 --- /dev/null +++ b/final/lib/CodeGen/TailDuplication.cpp @@ -0,0 +1,658 @@ +//===-- TailDuplication.cpp - Duplicate blocks into predecessors' tails ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass duplicates basic blocks ending in unconditional branches into +// the tails of their predecessors. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "tailduplication" +#include "llvm/Function.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/MachineSSAUpdater.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumTails , "Number of tails duplicated"); +STATISTIC(NumTailDups , "Number of tail duplicated blocks"); +STATISTIC(NumInstrDups , "Additional instructions due to tail duplication"); +STATISTIC(NumDeadBlocks, "Number of dead blocks removed"); + +// Heuristic for tail duplication. +static cl::opt +TailDuplicateSize("tail-dup-size", + cl::desc("Maximum instructions to consider tail duplicating"), + cl::init(2), cl::Hidden); + +static cl::opt +TailDupVerify("tail-dup-verify", + cl::desc("Verify sanity of PHI instructions during taildup"), + cl::init(false), cl::Hidden); + +static cl::opt +TailDupLimit("tail-dup-limit", cl::init(~0U), cl::Hidden); + +typedef std::vector > AvailableValsTy; + +namespace { + /// TailDuplicatePass - Perform tail duplication. + class TailDuplicatePass : public MachineFunctionPass { + bool PreRegAlloc; + const TargetInstrInfo *TII; + MachineModuleInfo *MMI; + MachineRegisterInfo *MRI; + + // SSAUpdateVRs - A list of virtual registers for which to update SSA form. + SmallVector SSAUpdateVRs; + + // SSAUpdateVals - For each virtual register in SSAUpdateVals keep a list of + // source virtual registers. + DenseMap SSAUpdateVals; + + public: + static char ID; + explicit TailDuplicatePass(bool PreRA) : + MachineFunctionPass(ID), PreRegAlloc(PreRA) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + virtual const char *getPassName() const { return "Tail Duplication"; } + + private: + void AddSSAUpdateEntry(unsigned OrigReg, unsigned NewReg, + MachineBasicBlock *BB); + void ProcessPHI(MachineInstr *MI, MachineBasicBlock *TailBB, + MachineBasicBlock *PredBB, + DenseMap &LocalVRMap, + SmallVector, 4> &Copies); + void DuplicateInstruction(MachineInstr *MI, + MachineBasicBlock *TailBB, + MachineBasicBlock *PredBB, + MachineFunction &MF, + DenseMap &LocalVRMap); + void UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, + SmallVector &TDBBs, + SmallSetVector &Succs); + bool TailDuplicateBlocks(MachineFunction &MF); + bool TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, + SmallVector &TDBBs, + SmallVector &Copies); + void RemoveDeadBlock(MachineBasicBlock *MBB); + }; + + char TailDuplicatePass::ID = 0; +} + +FunctionPass *llvm::createTailDuplicatePass(bool PreRegAlloc) { + return new TailDuplicatePass(PreRegAlloc); +} + +bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + MRI = &MF.getRegInfo(); + MMI = getAnalysisIfAvailable(); + + bool MadeChange = false; + while (TailDuplicateBlocks(MF)) + MadeChange = true; + + return MadeChange; +} + +static void VerifyPHIs(MachineFunction &MF, bool CheckExtra) { + for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ++I) { + MachineBasicBlock *MBB = I; + SmallSetVector Preds(MBB->pred_begin(), + MBB->pred_end()); + MachineBasicBlock::iterator MI = MBB->begin(); + while (MI != MBB->end()) { + if (!MI->isPHI()) + break; + for (SmallSetVector::iterator PI = Preds.begin(), + PE = Preds.end(); PI != PE; ++PI) { + MachineBasicBlock *PredBB = *PI; + bool Found = false; + for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) { + MachineBasicBlock *PHIBB = MI->getOperand(i+1).getMBB(); + if (PHIBB == PredBB) { + Found = true; + break; + } + } + if (!Found) { + dbgs() << "Malformed PHI in BB#" << MBB->getNumber() << ": " << *MI; + dbgs() << " missing input from predecessor BB#" + << PredBB->getNumber() << '\n'; + llvm_unreachable(0); + } + } + + for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) { + MachineBasicBlock *PHIBB = MI->getOperand(i+1).getMBB(); + if (CheckExtra && !Preds.count(PHIBB)) { + // This is not a hard error. + dbgs() << "Warning: malformed PHI in BB#" << MBB->getNumber() + << ": " << *MI; + dbgs() << " extra input from predecessor BB#" + << PHIBB->getNumber() << '\n'; + } + if (PHIBB->getNumber() < 0) { + dbgs() << "Malformed PHI in BB#" << MBB->getNumber() << ": " << *MI; + dbgs() << " non-existing BB#" << PHIBB->getNumber() << '\n'; + llvm_unreachable(0); + } + } + ++MI; + } + } +} + +/// TailDuplicateBlocks - Look for small blocks that are unconditionally +/// branched to and do not fall through. Tail-duplicate their instructions +/// into their predecessors to eliminate (dynamic) branches. +bool TailDuplicatePass::TailDuplicateBlocks(MachineFunction &MF) { + bool MadeChange = false; + + if (PreRegAlloc && TailDupVerify) { + DEBUG(dbgs() << "\n*** Before tail-duplicating\n"); + VerifyPHIs(MF, true); + } + + SmallVector NewPHIs; + MachineSSAUpdater SSAUpdate(MF, &NewPHIs); + + for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { + MachineBasicBlock *MBB = I++; + + if (NumTails == TailDupLimit) + break; + + // Only duplicate blocks that end with unconditional branches. + if (MBB->canFallThrough()) + continue; + + // Save the successors list. + SmallSetVector Succs(MBB->succ_begin(), + MBB->succ_end()); + + SmallVector TDBBs; + SmallVector Copies; + if (TailDuplicate(MBB, MF, TDBBs, Copies)) { + ++NumTails; + + // TailBB's immediate successors are now successors of those predecessors + // which duplicated TailBB. Add the predecessors as sources to the PHI + // instructions. + bool isDead = MBB->pred_empty(); + if (PreRegAlloc) + UpdateSuccessorsPHIs(MBB, isDead, TDBBs, Succs); + + // If it is dead, remove it. + if (isDead) { + NumInstrDups -= MBB->size(); + RemoveDeadBlock(MBB); + ++NumDeadBlocks; + } + + // Update SSA form. + if (!SSAUpdateVRs.empty()) { + for (unsigned i = 0, e = SSAUpdateVRs.size(); i != e; ++i) { + unsigned VReg = SSAUpdateVRs[i]; + SSAUpdate.Initialize(VReg); + + // If the original definition is still around, add it as an available + // value. + MachineInstr *DefMI = MRI->getVRegDef(VReg); + MachineBasicBlock *DefBB = 0; + if (DefMI) { + DefBB = DefMI->getParent(); + SSAUpdate.AddAvailableValue(DefBB, VReg); + } + + // Add the new vregs as available values. + DenseMap::iterator LI = + SSAUpdateVals.find(VReg); + for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) { + MachineBasicBlock *SrcBB = LI->second[j].first; + unsigned SrcReg = LI->second[j].second; + SSAUpdate.AddAvailableValue(SrcBB, SrcReg); + } + + // Rewrite uses that are outside of the original def's block. + MachineRegisterInfo::use_iterator UI = MRI->use_begin(VReg); + while (UI != MRI->use_end()) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + ++UI; + if (UseMI->getParent() == DefBB) + continue; + SSAUpdate.RewriteUse(UseMO); + } + } + + SSAUpdateVRs.clear(); + SSAUpdateVals.clear(); + } + + // Eliminate some of the copies inserted by tail duplication to maintain + // SSA form. + for (unsigned i = 0, e = Copies.size(); i != e; ++i) { + MachineInstr *Copy = Copies[i]; + if (!Copy->isCopy()) + continue; + unsigned Dst = Copy->getOperand(0).getReg(); + unsigned Src = Copy->getOperand(1).getReg(); + MachineRegisterInfo::use_iterator UI = MRI->use_begin(Src); + if (++UI == MRI->use_end()) { + // Copy is the only use. Do trivial copy propagation here. + MRI->replaceRegWith(Dst, Src); + Copy->eraseFromParent(); + } + } + + if (PreRegAlloc && TailDupVerify) + VerifyPHIs(MF, false); + MadeChange = true; + } + } + + return MadeChange; +} + +static bool isDefLiveOut(unsigned Reg, MachineBasicBlock *BB, + const MachineRegisterInfo *MRI) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (UseMI->getParent() != BB) + return true; + } + return false; +} + +static unsigned getPHISrcRegOpIdx(MachineInstr *MI, MachineBasicBlock *SrcBB) { + for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) + if (MI->getOperand(i+1).getMBB() == SrcBB) + return i; + return 0; +} + +/// AddSSAUpdateEntry - Add a definition and source virtual registers pair for +/// SSA update. +void TailDuplicatePass::AddSSAUpdateEntry(unsigned OrigReg, unsigned NewReg, + MachineBasicBlock *BB) { + DenseMap::iterator LI= SSAUpdateVals.find(OrigReg); + if (LI != SSAUpdateVals.end()) + LI->second.push_back(std::make_pair(BB, NewReg)); + else { + AvailableValsTy Vals; + Vals.push_back(std::make_pair(BB, NewReg)); + SSAUpdateVals.insert(std::make_pair(OrigReg, Vals)); + SSAUpdateVRs.push_back(OrigReg); + } +} + +/// ProcessPHI - Process PHI node in TailBB by turning it into a copy in PredBB. +/// Remember the source register that's contributed by PredBB and update SSA +/// update map. +void TailDuplicatePass::ProcessPHI(MachineInstr *MI, + MachineBasicBlock *TailBB, + MachineBasicBlock *PredBB, + DenseMap &LocalVRMap, + SmallVector, 4> &Copies) { + unsigned DefReg = MI->getOperand(0).getReg(); + unsigned SrcOpIdx = getPHISrcRegOpIdx(MI, PredBB); + assert(SrcOpIdx && "Unable to find matching PHI source?"); + unsigned SrcReg = MI->getOperand(SrcOpIdx).getReg(); + const TargetRegisterClass *RC = MRI->getRegClass(DefReg); + LocalVRMap.insert(std::make_pair(DefReg, SrcReg)); + + // Insert a copy from source to the end of the block. The def register is the + // available value liveout of the block. + unsigned NewDef = MRI->createVirtualRegister(RC); + Copies.push_back(std::make_pair(NewDef, SrcReg)); + if (isDefLiveOut(DefReg, TailBB, MRI)) + AddSSAUpdateEntry(DefReg, NewDef, PredBB); + + // Remove PredBB from the PHI node. + MI->RemoveOperand(SrcOpIdx+1); + MI->RemoveOperand(SrcOpIdx); + if (MI->getNumOperands() == 1) + MI->eraseFromParent(); +} + +/// DuplicateInstruction - Duplicate a TailBB instruction to PredBB and update +/// the source operands due to earlier PHI translation. +void TailDuplicatePass::DuplicateInstruction(MachineInstr *MI, + MachineBasicBlock *TailBB, + MachineBasicBlock *PredBB, + MachineFunction &MF, + DenseMap &LocalVRMap) { + MachineInstr *NewMI = TII->duplicate(MI, MF); + for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = NewMI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (MO.isDef()) { + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + unsigned NewReg = MRI->createVirtualRegister(RC); + MO.setReg(NewReg); + LocalVRMap.insert(std::make_pair(Reg, NewReg)); + if (isDefLiveOut(Reg, TailBB, MRI)) + AddSSAUpdateEntry(Reg, NewReg, PredBB); + } else { + DenseMap::iterator VI = LocalVRMap.find(Reg); + if (VI != LocalVRMap.end()) + MO.setReg(VI->second); + } + } + PredBB->insert(PredBB->end(), NewMI); +} + +/// UpdateSuccessorsPHIs - After FromBB is tail duplicated into its predecessor +/// blocks, the successors have gained new predecessors. Update the PHI +/// instructions in them accordingly. +void +TailDuplicatePass::UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, + SmallVector &TDBBs, + SmallSetVector &Succs) { + for (SmallSetVector::iterator SI = Succs.begin(), + SE = Succs.end(); SI != SE; ++SI) { + MachineBasicBlock *SuccBB = *SI; + for (MachineBasicBlock::iterator II = SuccBB->begin(), EE = SuccBB->end(); + II != EE; ++II) { + if (!II->isPHI()) + break; + unsigned Idx = 0; + for (unsigned i = 1, e = II->getNumOperands(); i != e; i += 2) { + MachineOperand &MO = II->getOperand(i+1); + if (MO.getMBB() == FromBB) { + Idx = i; + break; + } + } + + assert(Idx != 0); + MachineOperand &MO0 = II->getOperand(Idx); + unsigned Reg = MO0.getReg(); + if (isDead) { + // Folded into the previous BB. + // There could be duplicate phi source entries. FIXME: Should sdisel + // or earlier pass fixed this? + for (unsigned i = II->getNumOperands()-2; i != Idx; i -= 2) { + MachineOperand &MO = II->getOperand(i+1); + if (MO.getMBB() == FromBB) { + II->RemoveOperand(i+1); + II->RemoveOperand(i); + } + } + } else + Idx = 0; + + // If Idx is set, the operands at Idx and Idx+1 must be removed. + // We reuse the location to avoid expensive RemoveOperand calls. + + DenseMap::iterator LI=SSAUpdateVals.find(Reg); + if (LI != SSAUpdateVals.end()) { + // This register is defined in the tail block. + for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) { + MachineBasicBlock *SrcBB = LI->second[j].first; + unsigned SrcReg = LI->second[j].second; + if (Idx != 0) { + II->getOperand(Idx).setReg(SrcReg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(SrcReg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } + } + } else { + // Live in tail block, must also be live in predecessors. + for (unsigned j = 0, ee = TDBBs.size(); j != ee; ++j) { + MachineBasicBlock *SrcBB = TDBBs[j]; + if (Idx != 0) { + II->getOperand(Idx).setReg(Reg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(Reg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } + } + } + if (Idx != 0) { + II->RemoveOperand(Idx+1); + II->RemoveOperand(Idx); + } + } + } +} + +/// TailDuplicate - If it is profitable, duplicate TailBB's contents in each +/// of its predecessors. +bool +TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, + SmallVector &TDBBs, + SmallVector &Copies) { + // Set the limit on the number of instructions to duplicate, with a default + // of one less than the tail-merge threshold. When optimizing for size, + // duplicate only one, because one branch instruction can be eliminated to + // compensate for the duplication. + unsigned MaxDuplicateCount; + if (TailDuplicateSize.getNumOccurrences() == 0 && + MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize)) + MaxDuplicateCount = 1; + else + MaxDuplicateCount = TailDuplicateSize; + + if (PreRegAlloc) { + if (TailBB->empty()) + return false; + const TargetInstrDesc &TID = TailBB->back().getDesc(); + // Pre-regalloc tail duplication hurts compile time and doesn't help + // much except for indirect branches and returns. + if (!TID.isIndirectBranch() && !TID.isReturn()) + return false; + // If the target has hardware branch prediction that can handle indirect + // branches, duplicating them can often make them predictable when there + // are common paths through the code. The limit needs to be high enough + // to allow undoing the effects of tail merging and other optimizations + // that rearrange the predecessors of the indirect branch. + MaxDuplicateCount = 20; + } + + // Don't try to tail-duplicate single-block loops. + if (TailBB->isSuccessor(TailBB)) + return false; + + // Check the instructions in the block to determine whether tail-duplication + // is invalid or unlikely to be profitable. + unsigned InstrCount = 0; + bool HasCall = false; + for (MachineBasicBlock::iterator I = TailBB->begin(); + I != TailBB->end(); ++I) { + // Non-duplicable things shouldn't be tail-duplicated. + if (I->getDesc().isNotDuplicable()) return false; + // Do not duplicate 'return' instructions if this is a pre-regalloc run. + // A return may expand into a lot more instructions (e.g. reload of callee + // saved registers) after PEI. + if (PreRegAlloc && I->getDesc().isReturn()) return false; + // Don't duplicate more than the threshold. + if (InstrCount == MaxDuplicateCount) return false; + // Remember if we saw a call. + if (I->getDesc().isCall()) HasCall = true; + if (!I->isPHI() && !I->isDebugValue()) + InstrCount += 1; + } + // Don't tail-duplicate calls before register allocation. Calls presents a + // barrier to register allocation so duplicating them may end up increasing + // spills. + if (InstrCount > 1 && (PreRegAlloc && HasCall)) + return false; + + DEBUG(dbgs() << "\n*** Tail-duplicating BB#" << TailBB->getNumber() << '\n'); + + // Iterate through all the unique predecessors and tail-duplicate this + // block into them, if possible. Copying the list ahead of time also + // avoids trouble with the predecessor list reallocating. + bool Changed = false; + SmallSetVector Preds(TailBB->pred_begin(), + TailBB->pred_end()); + for (SmallSetVector::iterator PI = Preds.begin(), + PE = Preds.end(); PI != PE; ++PI) { + MachineBasicBlock *PredBB = *PI; + + assert(TailBB != PredBB && + "Single-block loop should have been rejected earlier!"); + if (PredBB->succ_size() > 1) continue; + + MachineBasicBlock *PredTBB, *PredFBB; + SmallVector PredCond; + if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) + continue; + if (!PredCond.empty()) + continue; + // EH edges are ignored by AnalyzeBranch. + if (PredBB->succ_size() != 1) + continue; + // Don't duplicate into a fall-through predecessor (at least for now). + if (PredBB->isLayoutSuccessor(TailBB) && PredBB->canFallThrough()) + continue; + + DEBUG(dbgs() << "\nTail-duplicating into PredBB: " << *PredBB + << "From Succ: " << *TailBB); + + TDBBs.push_back(PredBB); + + // Remove PredBB's unconditional branch. + TII->RemoveBranch(*PredBB); + + // Clone the contents of TailBB into PredBB. + DenseMap LocalVRMap; + SmallVector, 4> CopyInfos; + MachineBasicBlock::iterator I = TailBB->begin(); + while (I != TailBB->end()) { + MachineInstr *MI = &*I; + ++I; + if (MI->isPHI()) { + // Replace the uses of the def of the PHI with the register coming + // from PredBB. + ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos); + } else { + // Replace def of virtual registers with new registers, and update + // uses with PHI source register or the new registers. + DuplicateInstruction(MI, TailBB, PredBB, MF, LocalVRMap); + } + } + MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); + for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { + Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(), + TII->get(TargetOpcode::COPY), + CopyInfos[i].first).addReg(CopyInfos[i].second)); + } + NumInstrDups += TailBB->size() - 1; // subtract one for removed branch + + // Update the CFG. + PredBB->removeSuccessor(PredBB->succ_begin()); + assert(PredBB->succ_empty() && + "TailDuplicate called on block with multiple successors!"); + for (MachineBasicBlock::succ_iterator I = TailBB->succ_begin(), + E = TailBB->succ_end(); I != E; ++I) + PredBB->addSuccessor(*I); + + Changed = true; + ++NumTailDups; + } + + // If TailBB was duplicated into all its predecessors except for the prior + // block, which falls through unconditionally, move the contents of this + // block into the prior block. + MachineBasicBlock *PrevBB = prior(MachineFunction::iterator(TailBB)); + MachineBasicBlock *PriorTBB = 0, *PriorFBB = 0; + SmallVector PriorCond; + bool PriorUnAnalyzable = + TII->AnalyzeBranch(*PrevBB, PriorTBB, PriorFBB, PriorCond, true); + // This has to check PrevBB->succ_size() because EH edges are ignored by + // AnalyzeBranch. + if (!PriorUnAnalyzable && PriorCond.empty() && !PriorTBB && + TailBB->pred_size() == 1 && PrevBB->succ_size() == 1 && + !TailBB->hasAddressTaken()) { + DEBUG(dbgs() << "\nMerging into block: " << *PrevBB + << "From MBB: " << *TailBB); + if (PreRegAlloc) { + DenseMap LocalVRMap; + SmallVector, 4> CopyInfos; + MachineBasicBlock::iterator I = TailBB->begin(); + // Process PHI instructions first. + while (I != TailBB->end() && I->isPHI()) { + // Replace the uses of the def of the PHI with the register coming + // from PredBB. + MachineInstr *MI = &*I++; + ProcessPHI(MI, TailBB, PrevBB, LocalVRMap, CopyInfos); + if (MI->getParent()) + MI->eraseFromParent(); + } + + // Now copy the non-PHI instructions. + while (I != TailBB->end()) { + // Replace def of virtual registers with new registers, and update + // uses with PHI source register or the new registers. + MachineInstr *MI = &*I++; + DuplicateInstruction(MI, TailBB, PrevBB, MF, LocalVRMap); + MI->eraseFromParent(); + } + MachineBasicBlock::iterator Loc = PrevBB->getFirstTerminator(); + for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { + Copies.push_back(BuildMI(*PrevBB, Loc, DebugLoc(), + TII->get(TargetOpcode::COPY), + CopyInfos[i].first) + .addReg(CopyInfos[i].second)); + } + } else { + // No PHIs to worry about, just splice the instructions over. + PrevBB->splice(PrevBB->end(), TailBB, TailBB->begin(), TailBB->end()); + } + PrevBB->removeSuccessor(PrevBB->succ_begin()); + assert(PrevBB->succ_empty()); + PrevBB->transferSuccessors(TailBB); + TDBBs.push_back(PrevBB); + Changed = true; + } + + return Changed; +} + +/// RemoveDeadBlock - Remove the specified dead machine basic block from the +/// function, updating the CFG. +void TailDuplicatePass::RemoveDeadBlock(MachineBasicBlock *MBB) { + assert(MBB->pred_empty() && "MBB must be dead!"); + DEBUG(dbgs() << "\nRemoving MBB: " << *MBB); + + // Remove all successors. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_end()-1); + + // Remove the block. + MBB->eraseFromParent(); +} + diff --git a/final/lib/CodeGen/TargetInstrInfoImpl.cpp b/final/lib/CodeGen/TargetInstrInfoImpl.cpp new file mode 100644 index 00000000000..15340a3f108 --- /dev/null +++ b/final/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -0,0 +1,449 @@ +//===-- TargetInstrInfoImpl.cpp - Target Instruction Information ----------===// +// +// 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 TargetInstrInfoImpl class, it just provides default +// implementations of various methods. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +static cl::opt DisableHazardRecognizer( + "disable-sched-hazard", cl::Hidden, cl::init(false), + cl::desc("Disable hazard detection during preRA scheduling")); + +/// ReplaceTailWithBranchTo - Delete the instruction OldInst and everything +/// after it, replacing it with an unconditional branch to NewDest. +void +TargetInstrInfoImpl::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, + MachineBasicBlock *NewDest) const { + MachineBasicBlock *MBB = Tail->getParent(); + + // Remove all the old successors of MBB from the CFG. + while (!MBB->succ_empty()) + MBB->removeSuccessor(MBB->succ_begin()); + + // Remove all the dead instructions from the end of MBB. + MBB->erase(Tail, MBB->end()); + + // If MBB isn't immediately before MBB, insert a branch to it. + if (++MachineFunction::iterator(MBB) != MachineFunction::iterator(NewDest)) + InsertBranch(*MBB, NewDest, 0, SmallVector(), + Tail->getDebugLoc()); + MBB->addSuccessor(NewDest); +} + +// commuteInstruction - The default implementation of this method just exchanges +// the two operands returned by findCommutedOpIndices. +MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, + bool NewMI) const { + const TargetInstrDesc &TID = MI->getDesc(); + bool HasDef = TID.getNumDefs(); + if (HasDef && !MI->getOperand(0).isReg()) + // No idea how to commute this instruction. Target should implement its own. + return 0; + unsigned Idx1, Idx2; + if (!findCommutedOpIndices(MI, Idx1, Idx2)) { + std::string msg; + raw_string_ostream Msg(msg); + Msg << "Don't know how to commute: " << *MI; + report_fatal_error(Msg.str()); + } + + assert(MI->getOperand(Idx1).isReg() && MI->getOperand(Idx2).isReg() && + "This only knows how to commute register operands so far"); + unsigned Reg1 = MI->getOperand(Idx1).getReg(); + unsigned Reg2 = MI->getOperand(Idx2).getReg(); + bool Reg1IsKill = MI->getOperand(Idx1).isKill(); + bool Reg2IsKill = MI->getOperand(Idx2).isKill(); + bool ChangeReg0 = false; + if (HasDef && MI->getOperand(0).getReg() == Reg1) { + // Must be two address instruction! + assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && + "Expecting a two-address instruction!"); + Reg2IsKill = false; + ChangeReg0 = true; + } + + if (NewMI) { + // Create a new instruction. + unsigned Reg0 = HasDef + ? (ChangeReg0 ? Reg2 : MI->getOperand(0).getReg()) : 0; + bool Reg0IsDead = HasDef ? MI->getOperand(0).isDead() : false; + MachineFunction &MF = *MI->getParent()->getParent(); + if (HasDef) + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg0, RegState::Define | getDeadRegState(Reg0IsDead)) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); + else + return BuildMI(MF, MI->getDebugLoc(), MI->getDesc()) + .addReg(Reg2, getKillRegState(Reg2IsKill)) + .addReg(Reg1, getKillRegState(Reg2IsKill)); + } + + if (ChangeReg0) + MI->getOperand(0).setReg(Reg2); + MI->getOperand(Idx2).setReg(Reg1); + MI->getOperand(Idx1).setReg(Reg2); + MI->getOperand(Idx2).setIsKill(Reg1IsKill); + MI->getOperand(Idx1).setIsKill(Reg2IsKill); + return MI; +} + +/// findCommutedOpIndices - If specified MI is commutable, return the two +/// operand indices that would swap value. Return true if the instruction +/// is not in a form which this routine understands. +bool TargetInstrInfoImpl::findCommutedOpIndices(MachineInstr *MI, + unsigned &SrcOpIdx1, + unsigned &SrcOpIdx2) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isCommutable()) + return false; + // This assumes v0 = op v1, v2 and commuting would swap v1 and v2. If this + // is not true, then the target must implement this. + SrcOpIdx1 = TID.getNumDefs(); + SrcOpIdx2 = SrcOpIdx1 + 1; + if (!MI->getOperand(SrcOpIdx1).isReg() || + !MI->getOperand(SrcOpIdx2).isReg()) + // No idea. + return false; + return true; +} + + +bool TargetInstrInfoImpl::PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const { + bool MadeChange = false; + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return false; + + for (unsigned j = 0, i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (TID.OpInfo[i].isPredicate()) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg()) { + MO.setReg(Pred[j].getReg()); + MadeChange = true; + } else if (MO.isImm()) { + MO.setImm(Pred[j].getImm()); + MadeChange = true; + } else if (MO.isMBB()) { + MO.setMBB(Pred[j].getMBB()); + MadeChange = true; + } + ++j; + } + } + return MadeChange; +} + +void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, + unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo &TRI) const { + MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); + MI->substituteRegister(MI->getOperand(0).getReg(), DestReg, SubIdx, TRI); + MBB.insert(I, MI); +} + +bool +TargetInstrInfoImpl::produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const { + return MI0->isIdenticalTo(MI1, MachineInstr::IgnoreVRegDefs); +} + +MachineInstr *TargetInstrInfoImpl::duplicate(MachineInstr *Orig, + MachineFunction &MF) const { + assert(!Orig->getDesc().isNotDuplicable() && + "Instruction cannot be duplicated"); + return MF.CloneMachineInstr(Orig); +} + +// If the COPY instruction in MI can be folded to a stack operation, return +// the register class to use. +static const TargetRegisterClass *canFoldCopy(const MachineInstr *MI, + unsigned FoldIdx) { + assert(MI->isCopy() && "MI must be a COPY instruction"); + if (MI->getNumOperands() != 2) + return 0; + assert(FoldIdx<2 && "FoldIdx refers no nonexistent operand"); + + const MachineOperand &FoldOp = MI->getOperand(FoldIdx); + const MachineOperand &LiveOp = MI->getOperand(1-FoldIdx); + + if (FoldOp.getSubReg() || LiveOp.getSubReg()) + return 0; + + unsigned FoldReg = FoldOp.getReg(); + unsigned LiveReg = LiveOp.getReg(); + + assert(TargetRegisterInfo::isVirtualRegister(FoldReg) && + "Cannot fold physregs"); + + const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); + const TargetRegisterClass *RC = MRI.getRegClass(FoldReg); + + if (TargetRegisterInfo::isPhysicalRegister(LiveOp.getReg())) + return RC->contains(LiveOp.getReg()) ? RC : 0; + + const TargetRegisterClass *LiveRC = MRI.getRegClass(LiveReg); + if (RC == LiveRC || RC->hasSubClass(LiveRC)) + return RC; + + // FIXME: Allow folding when register classes are memory compatible. + return 0; +} + +bool TargetInstrInfoImpl:: +canFoldMemoryOperand(const MachineInstr *MI, + const SmallVectorImpl &Ops) const { + return MI->isCopy() && Ops.size() == 1 && canFoldCopy(MI, Ops[0]); +} + +/// foldMemoryOperand - Attempt to fold a load or store of the specified stack +/// slot into the specified machine instruction for the specified operand(s). +/// If this is possible, a new instruction is returned with the specified +/// operand folded, otherwise NULL is returned. The client is responsible for +/// removing the old instruction and adding the new one in the instruction +/// stream. +MachineInstr* +TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + int FI) const { + unsigned Flags = 0; + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (MI->getOperand(Ops[i]).isDef()) + Flags |= MachineMemOperand::MOStore; + else + Flags |= MachineMemOperand::MOLoad; + + MachineBasicBlock *MBB = MI->getParent(); + assert(MBB && "foldMemoryOperand needs an inserted instruction"); + MachineFunction &MF = *MBB->getParent(); + + // Ask the target to do the actual folding. + if (MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, FI)) { + // Add a memory operand, foldMemoryOperandImpl doesn't do that. + assert((!(Flags & MachineMemOperand::MOStore) || + NewMI->getDesc().mayStore()) && + "Folded a def to a non-store!"); + assert((!(Flags & MachineMemOperand::MOLoad) || + NewMI->getDesc().mayLoad()) && + "Folded a use to a non-load!"); + const MachineFrameInfo &MFI = *MF.getFrameInfo(); + assert(MFI.getObjectOffset(FI) != -1); + MachineMemOperand *MMO = + MF.getMachineMemOperand( + MachinePointerInfo(PseudoSourceValue::getFixedStack(FI)), + Flags, MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + NewMI->addMemOperand(MF, MMO); + + // FIXME: change foldMemoryOperandImpl semantics to also insert NewMI. + return MBB->insert(MI, NewMI); + } + + // Straight COPY may fold as load/store. + if (!MI->isCopy() || Ops.size() != 1) + return 0; + + const TargetRegisterClass *RC = canFoldCopy(MI, Ops[0]); + if (!RC) + return 0; + + const MachineOperand &MO = MI->getOperand(1-Ops[0]); + MachineBasicBlock::iterator Pos = MI; + const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); + + if (Flags == MachineMemOperand::MOStore) + storeRegToStackSlot(*MBB, Pos, MO.getReg(), MO.isKill(), FI, RC, TRI); + else + loadRegFromStackSlot(*MBB, Pos, MO.getReg(), FI, RC, TRI); + return --Pos; +} + +/// foldMemoryOperand - Same as the previous version except it allows folding +/// of any load and store from / to any address, not just from a specific +/// stack slot. +MachineInstr* +TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + assert(LoadMI->getDesc().canFoldAsLoad() && "LoadMI isn't foldable!"); +#ifndef NDEBUG + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + assert(MI->getOperand(Ops[i]).isUse() && "Folding load into def!"); +#endif + MachineBasicBlock &MBB = *MI->getParent(); + MachineFunction &MF = *MBB.getParent(); + + // Ask the target to do the actual folding. + MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, LoadMI); + if (!NewMI) return 0; + + NewMI = MBB.insert(MI, NewMI); + + // Copy the memoperands from the load to the folded instruction. + NewMI->setMemRefs(LoadMI->memoperands_begin(), + LoadMI->memoperands_end()); + + return NewMI; +} + +bool TargetInstrInfo:: +isReallyTriviallyReMaterializableGeneric(const MachineInstr *MI, + AliasAnalysis *AA) const { + const MachineFunction &MF = *MI->getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const TargetMachine &TM = MF.getTarget(); + const TargetInstrInfo &TII = *TM.getInstrInfo(); + const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); + + // A load from a fixed stack slot can be rematerialized. This may be + // redundant with subsequent checks, but it's target-independent, + // simple, and a common case. + int FrameIdx = 0; + if (TII.isLoadFromStackSlot(MI, FrameIdx) && + MF.getFrameInfo()->isImmutableObjectIndex(FrameIdx)) + return true; + + const TargetInstrDesc &TID = MI->getDesc(); + + // Avoid instructions obviously unsafe for remat. + if (TID.isNotDuplicable() || TID.mayStore() || + MI->hasUnmodeledSideEffects()) + return false; + + // Don't remat inline asm. We have no idea how expensive it is + // even if it's side effect free. + if (MI->isInlineAsm()) + return false; + + // Avoid instructions which load from potentially varying memory. + if (TID.mayLoad() && !MI->isInvariantLoad(AA)) + return false; + + // If any of the registers accessed are non-constant, conservatively assume + // the instruction is not rematerializable. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + + // Check for a well-behaved physical register. + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) { + // If the physreg has no defs anywhere, it's just an ambient register + // and we can freely move its uses. Alternatively, if it's allocatable, + // it could get allocated to something with a def during allocation. + if (!MRI.def_empty(Reg)) + return false; + BitVector AllocatableRegs = TRI.getAllocatableSet(MF, 0); + if (AllocatableRegs.test(Reg)) + return false; + // Check for a def among the register's aliases too. + for (const unsigned *Alias = TRI.getAliasSet(Reg); *Alias; ++Alias) { + unsigned AliasReg = *Alias; + if (!MRI.def_empty(AliasReg)) + return false; + if (AllocatableRegs.test(AliasReg)) + return false; + } + } else { + // A physreg def. We can't remat it. + return false; + } + continue; + } + + // Only allow one virtual-register def, and that in the first operand. + if (MO.isDef() != (i == 0)) + return false; + + // For the def, it should be the only def of that register. + if (MO.isDef() && (llvm::next(MRI.def_begin(Reg)) != MRI.def_end() || + MRI.isLiveIn(Reg))) + return false; + + // Don't allow any virtual-register uses. Rematting an instruction with + // virtual register uses would length the live ranges of the uses, which + // is not necessarily a good idea, certainly not "trivial". + if (MO.isUse()) + return false; + } + + // Everything checked out. + return true; +} + +/// isSchedulingBoundary - Test if the given instruction should be +/// considered a scheduling boundary. This primarily includes labels +/// and terminators. +bool TargetInstrInfoImpl::isSchedulingBoundary(const MachineInstr *MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const{ + // Terminators and labels can't be scheduled around. + if (MI->getDesc().isTerminator() || MI->isLabel()) + return true; + + // Don't attempt to schedule around any instruction that defines + // a stack-oriented pointer, as it's unlikely to be profitable. This + // saves compile time, because it doesn't require every single + // stack slot reference to depend on the instruction that does the + // modification. + const TargetLowering &TLI = *MF.getTarget().getTargetLowering(); + if (MI->definesRegister(TLI.getStackPointerRegisterToSaveRestore())) + return true; + + return false; +} + +// Provide a global flag for disabling the PreRA hazard recognizer that targets +// may choose to honor. +bool TargetInstrInfoImpl::usePreRAHazardRecognizer() const { + return !DisableHazardRecognizer; +} + +// Default implementation of CreateTargetRAHazardRecognizer. +ScheduleHazardRecognizer *TargetInstrInfoImpl:: +CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const { + // Dummy hazard recognizer allows all instructions to issue. + return new ScheduleHazardRecognizer(); +} + +// Default implementation of CreateTargetPostRAHazardRecognizer. +ScheduleHazardRecognizer *TargetInstrInfoImpl:: +CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, + const ScheduleDAG *DAG) const { + return (ScheduleHazardRecognizer *) + new ScoreboardHazardRecognizer(II, DAG, "post-RA-sched"); +} diff --git a/final/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/final/lib/CodeGen/TargetLoweringObjectFileImpl.cpp new file mode 100644 index 00000000000..fa311dc5d66 --- /dev/null +++ b/final/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -0,0 +1,1026 @@ +//===-- llvm/CodeGen/TargetLoweringObjectFileImpl.cpp - Object File Info --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Triple.h" +using namespace llvm; +using namespace dwarf; + +//===----------------------------------------------------------------------===// +// ELF +//===----------------------------------------------------------------------===// + +void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFile::Initialize(Ctx, TM); + + BSSSection = + getContext().getELFSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getBSS()); + + TextSection = + getContext().getELFSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + getContext().getELFSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + getContext().getELFSection(".rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + getContext().getELFSection(".tdata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHF_TLS | + ELF::SHF_WRITE, + SectionKind::getThreadData()); + + TLSBSSSection = + getContext().getELFSection(".tbss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | ELF::SHF_TLS | + ELF::SHF_WRITE, + SectionKind::getThreadBSS()); + + DataRelSection = + getContext().getELFSection(".data.rel", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + getContext().getELFSection(".data.rel.local", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + getContext().getELFSection(".data.rel.ro", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + getContext().getELFSection(".data.rel.ro.local", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + + MergeableConst4Section = + getContext().getELFSection(".rodata.cst4", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + getContext().getELFSection(".rodata.cst8", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + getContext().getELFSection(".rodata.cst16", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_MERGE, + SectionKind::getMergeableConst16()); + + StaticCtorSection = + getContext().getELFSection(".ctors", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + StaticDtorSection = + getContext().getELFSection(".dtors", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC |ELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Exception Handling Sections. + + // FIXME: We're emitting LSDA info into a readonly section on ELF, even though + // it contains relocatable pointers. In PIC mode, this is probably a big + // runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getContext().getELFSection(".gcc_except_table", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + // Debug Info Sections. + DwarfAbbrevSection = + getContext().getELFSection(".debug_abbrev", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfInfoSection = + getContext().getELFSection(".debug_info", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLineSection = + getContext().getELFSection(".debug_line", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfFrameSection = + getContext().getELFSection(".debug_frame", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getContext().getELFSection(".debug_pubnames", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getContext().getELFSection(".debug_pubtypes", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfStrSection = + getContext().getELFSection(".debug_str", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLocSection = + getContext().getELFSection(".debug_loc", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfARangesSection = + getContext().getELFSection(".debug_aranges", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfRangesSection = + getContext().getELFSection(".debug_ranges", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getContext().getELFSection(".debug_macinfo", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const { + return getContext().getELFSection(".eh_frame", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getDataRel()); +} + +static SectionKind +getELFKindForNamedSection(StringRef Name, SectionKind K) { + // FIXME: Why is this here? Codegen is should not be in the business + // of figuring section flags. If the user wrote section(".eh_frame"), + // we should just pass that to MC which will defer to the assembly + // or use its default if producing an object file. + if (Name.empty() || Name[0] != '.') return K; + + // Some lame default implementation based on some magic section names. + if (Name == ".bss" || + Name.startswith(".bss.") || + Name.startswith(".gnu.linkonce.b.") || + Name.startswith(".llvm.linkonce.b.") || + Name == ".sbss" || + Name.startswith(".sbss.") || + Name.startswith(".gnu.linkonce.sb.") || + Name.startswith(".llvm.linkonce.sb.")) + return SectionKind::getBSS(); + + if (Name == ".tdata" || + Name.startswith(".tdata.") || + Name.startswith(".gnu.linkonce.td.") || + Name.startswith(".llvm.linkonce.td.")) + return SectionKind::getThreadData(); + + if (Name == ".tbss" || + Name.startswith(".tbss.") || + Name.startswith(".gnu.linkonce.tb.") || + Name.startswith(".llvm.linkonce.tb.")) + return SectionKind::getThreadBSS(); + + if (Name == ".eh_frame") + return SectionKind::getDataRel(); + + return K; +} + + +static unsigned getELFSectionType(StringRef Name, SectionKind K) { + + if (Name == ".init_array") + return ELF::SHT_INIT_ARRAY; + + if (Name == ".fini_array") + return ELF::SHT_FINI_ARRAY; + + if (Name == ".preinit_array") + return ELF::SHT_PREINIT_ARRAY; + + if (K.isBSS() || K.isThreadBSS()) + return ELF::SHT_NOBITS; + + return ELF::SHT_PROGBITS; +} + + +static unsigned +getELFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= ELF::SHF_ALLOC; + + if (K.isText()) + Flags |= ELF::SHF_EXECINSTR; + + if (K.isWriteable()) + Flags |= ELF::SHF_WRITE; + + if (K.isThreadLocal()) + Flags |= ELF::SHF_TLS; + + // K.isMergeableConst() is left out to honour PR4650 + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= ELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= ELF::SHF_STRINGS; + + return Flags; +} + + +const MCSection *TargetLoweringObjectFileELF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + StringRef SectionName = GV->getSection(); + + // Infer section flags from the section name if we can. + Kind = getELFKindForNamedSection(SectionName, Kind); + + return getContext().getELFSection(SectionName, + getELFSectionType(SectionName, Kind), + getELFSectionFlags(Kind), Kind); +} + +/// getSectionPrefixForGlobal - Return the section prefix name used by options +/// FunctionsSections and DataSections. +static const char *getSectionPrefixForGlobal(SectionKind Kind) { + if (Kind.isText()) return ".text."; + if (Kind.isReadOnly()) return ".rodata."; + + if (Kind.isThreadData()) return ".tdata."; + if (Kind.isThreadBSS()) return ".tbss."; + + if (Kind.isDataNoRel()) return ".data."; + if (Kind.isDataRelLocal()) return ".data.rel.local."; + if (Kind.isDataRel()) return ".data.rel."; + if (Kind.isReadOnlyWithRelLocal()) return ".data.rel.ro.local."; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return ".data.rel.ro."; +} + + +const MCSection *TargetLoweringObjectFileELF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // If we have -ffunction-section or -fdata-section then we should emit the + // global value to a uniqued section specifically for it. + bool EmitUniquedSection; + if (Kind.isText()) + EmitUniquedSection = TM.getFunctionSections(); + else + EmitUniquedSection = TM.getDataSections(); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if ((GV->isWeakForLinker() || EmitUniquedSection) && + !Kind.isCommon() && !Kind.isBSS()) { + const char *Prefix; + Prefix = getSectionPrefixForGlobal(Kind); + + SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); + MCSymbol *Sym = Mang->getSymbol(GV); + Name.append(Sym->getName().begin(), Sym->getName().end()); + StringRef Group = ""; + unsigned Flags = getELFSectionFlags(Kind); + if (GV->isWeakForLinker()) { + Group = Sym->getName(); + Flags |= ELF::SHF_GROUP; + } + + return getContext().getELFSection(Name.str(), + getELFSectionType(Name.str(), Kind), + Flags, Kind, 0, Group); + } + + if (Kind.isText()) return TextSection; + + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString() || + Kind.isMergeable4ByteCString()) { + + // We also need alignment here. + // FIXME: this is getting the alignment of the character, not the + // alignment of the global! + unsigned Align = + TM.getTargetData()->getPreferredAlignment(cast(GV)); + + const char *SizeSpec = ".rodata.str1."; + if (Kind.isMergeable2ByteCString()) + SizeSpec = ".rodata.str2."; + else if (Kind.isMergeable4ByteCString()) + SizeSpec = ".rodata.str4."; + else + assert(Kind.isMergeable1ByteCString() && "unknown string width"); + + + std::string Name = SizeSpec + utostr(Align); + return getContext().getELFSection(Name, ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_MERGE | + ELF::SHF_STRINGS, + Kind); + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + return ReadOnlySection; // .const + } + + if (Kind.isReadOnly()) return ReadOnlySection; + + if (Kind.isThreadData()) return TLSDataSection; + if (Kind.isThreadBSS()) return TLSBSSSection; + + // Note: we claim that common symbols are put in BSSSection, but they are + // really emitted with the magic .comm directive, which creates a symbol table + // entry but not a section. + if (Kind.isBSS() || Kind.isCommon()) return BSSSection; + + if (Kind.isDataNoRel()) return DataSection; + if (Kind.isDataRelLocal()) return DataRelLocalSection; + if (Kind.isDataRel()) return DataRelSection; + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +/// getSectionForConstant - Given a mergeable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const MCSection *TargetLoweringObjectFileELF:: +getSectionForConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + if (Kind.isReadOnly()) + return ReadOnlySection; + + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +const MCExpr *TargetLoweringObjectFileELF:: +getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, + unsigned Encoding, MCStreamer &Streamer) const { + + if (Encoding & dwarf::DW_EH_PE_indirect) { + MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += ".DW.stub"; + + // Add information about the stub reference to ELFMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str()); + MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym); + if (StubSym.getPointer() == 0) { + MCSymbol *Sym = Mang->getSymbol(GV); + StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage()); + } + + return TargetLoweringObjectFile:: + getExprForDwarfReference(SSym, Mang, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); + } + + return TargetLoweringObjectFile:: + getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, Streamer); +} + +//===----------------------------------------------------------------------===// +// MachO +//===----------------------------------------------------------------------===// + +void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + // _foo.eh symbols are currently always exported so that the linker knows + // about them. This is not necessary on 10.6 and later, but it + // doesn't hurt anything. + // FIXME: I need to get this from Triple. + IsFunctionEHSymbolGlobal = true; + IsFunctionEHFrameSymbolPrivate = false; + SupportsWeakOmittedEHFrame = false; + + Triple T(((LLVMTargetMachine&)TM).getTargetTriple()); + if (T.getOS() == Triple::Darwin) { + switch (T.getDarwinMajorNumber()) { + case 7: // 10.3 Panther. + case 8: // 10.4 Tiger. + CommDirectiveSupportsAlignment = false; + break; + case 9: // 10.5 Leopard. + case 10: // 10.6 SnowLeopard. + break; + } + } + + TargetLoweringObjectFile::Initialize(Ctx, TM); + + TextSection // .text + = getContext().getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = getContext().getMachOSection("__DATA", "__data", 0, + SectionKind::getDataRel()); + + TLSDataSection // .tdata + = getContext().getMachOSection("__DATA", "__thread_data", + MCSectionMachO::S_THREAD_LOCAL_REGULAR, + SectionKind::getDataRel()); + TLSBSSSection // .tbss + = getContext().getMachOSection("__DATA", "__thread_bss", + MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, + SectionKind::getThreadBSS()); + + // TODO: Verify datarel below. + TLSTLVSection // .tlv + = getContext().getMachOSection("__DATA", "__thread_vars", + MCSectionMachO::S_THREAD_LOCAL_VARIABLES, + SectionKind::getDataRel()); + + TLSThreadInitSection + = getContext().getMachOSection("__DATA", "__thread_init", + MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, + SectionKind::getDataRel()); + + CStringSection // .cstring + = getContext().getMachOSection("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = getContext().getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = getContext().getMachOSection("__TEXT", "__literal4", + MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = getContext().getMachOSection("__TEXT", "__literal8", + MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); + + // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back + // to using it in -static mode. + SixteenByteConstantSection = 0; + if (TM.getRelocationModel() != Reloc::Static && + TM.getTargetData()->getPointerSize() == 32) + SixteenByteConstantSection = // .literal16 + getContext().getMachOSection("__TEXT", "__literal16", + MCSectionMachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); + + ReadOnlySection // .const + = getContext().getMachOSection("__TEXT", "__const", 0, + SectionKind::getReadOnly()); + + TextCoalSection + = getContext().getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = getContext().getMachOSection("__TEXT", "__const_coal", + MCSectionMachO::S_COALESCED, + SectionKind::getReadOnly()); + ConstDataSection // .const_data + = getContext().getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = getContext().getMachOSection("__DATA","__datacoal_nt", + MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); + DataCommonSection + = getContext().getMachOSection("__DATA","__common", + MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + DataBSSSection + = getContext().getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + + + LazySymbolPointerSection + = getContext().getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + NonLazySymbolPointerSection + = getContext().getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + + if (TM.getRelocationModel() == Reloc::Static) { + StaticCtorSection + = getContext().getMachOSection("__TEXT", "__constructor", 0, + SectionKind::getDataRel()); + StaticDtorSection + = getContext().getMachOSection("__TEXT", "__destructor", 0, + SectionKind::getDataRel()); + } else { + StaticCtorSection + = getContext().getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = getContext().getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); + } + + // Exception Handling. + LSDASection = getContext().getMachOSection("__TEXT", "__gcc_except_tab", 0, + SectionKind::getReadOnlyWithRel()); + // Debug Information. + DwarfAbbrevSection = + getContext().getMachOSection("__DWARF", "__debug_abbrev", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfInfoSection = + getContext().getMachOSection("__DWARF", "__debug_info", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLineSection = + getContext().getMachOSection("__DWARF", "__debug_line", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfFrameSection = + getContext().getMachOSection("__DWARF", "__debug_frame", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getContext().getMachOSection("__DWARF", "__debug_pubnames", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getContext().getMachOSection("__DWARF", "__debug_pubtypes", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfStrSection = + getContext().getMachOSection("__DWARF", "__debug_str", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLocSection = + getContext().getMachOSection("__DWARF", "__debug_loc", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfARangesSection = + getContext().getMachOSection("__DWARF", "__debug_aranges", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfRangesSection = + getContext().getMachOSection("__DWARF", "__debug_ranges", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getContext().getMachOSection("__DWARF", "__debug_macinfo", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfDebugInlineSection = + getContext().getMachOSection("__DWARF", "__debug_inlined", + MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + + TLSExtraDataSection = TLSTLVSection; +} + +const MCSection *TargetLoweringObjectFileMachO::getEHFrameSection() const { + return getContext().getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); +} + +const MCSection *TargetLoweringObjectFileMachO:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // Parse the section specifier and create it if valid. + StringRef Segment, Section; + unsigned TAA = (unsigned)MCSectionMachO::SECTION_ATTRIBUTES, StubSize = 0; + std::string ErrorCode = + MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, + TAA, StubSize); + if (!ErrorCode.empty()) { + // If invalid, report the error with report_fatal_error. + report_fatal_error("Global variable '" + GV->getNameStr() + + "' has an invalid section specifier '" + GV->getSection()+ + "': " + ErrorCode + "."); + // Fall back to dropping it into the data section. + return DataSection; + } + + bool TAAWasSet = (TAA != MCSectionMachO::SECTION_ATTRIBUTES); + if (!TAAWasSet) + TAA = 0; // Sensible default if this is a new section. + + // Get the section. + const MCSectionMachO *S = + getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind); + + // If TAA wasn't set by ParseSectionSpecifier() above, + // use the value returned by getMachOSection() as a default. + if (!TAAWasSet) + TAA = S->getTypeAndAttributes(); + + // Okay, now that we got the section, verify that the TAA & StubSize agree. + // If the user declared multiple globals with different section flags, we need + // to reject it here. + if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) { + // If invalid, report the error with report_fatal_error. + report_fatal_error("Global variable '" + GV->getNameStr() + + "' section type or attributes does not match previous" + " section specifier"); + } + + return S; +} + +const MCSection *TargetLoweringObjectFileMachO:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + // Handle thread local data. + if (Kind.isThreadBSS()) return TLSBSSSection; + if (Kind.isThreadData()) return TLSDataSection; + + if (Kind.isText()) + return GV->isWeakForLinker() ? TextCoalSection : TextSection; + + // If this is weak/linkonce, put this in a coalescable section, either in text + // or data depending on if it is writable. + if (GV->isWeakForLinker()) { + if (Kind.isReadOnly()) + return ConstTextCoalSection; + return DataCoalSection; + } + + // FIXME: Alignment check should be handled by section classifier. + if (Kind.isMergeable1ByteCString() && + TM.getTargetData()->getPreferredAlignment(cast(GV)) < 32) + return CStringSection; + + // Do not put 16-bit arrays in the UString section if they have an + // externally visible label, this runs into issues with certain linker + // versions. + if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() && + TM.getTargetData()->getPreferredAlignment(cast(GV)) < 32) + return UStringSection; + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + } + + // Otherwise, if it is readonly, but not something we can specially optimize, + // just drop it in .const. + if (Kind.isReadOnly()) + return ReadOnlySection; + + // If this is marked const, put it into a const section. But if the dynamic + // linker needs to write to it, put it in the data segment. + if (Kind.isReadOnlyWithRel()) + return ConstDataSection; + + // Put zero initialized globals with strong external linkage in the + // DATA, __common section with the .zerofill directive. + if (Kind.isBSSExtern()) + return DataCommonSection; + + // Put zero initialized globals with local linkage in __DATA,__bss directive + // with the .zerofill directive (aka .lcomm). + if (Kind.isBSSLocal()) + return DataBSSSection; + + // Otherwise, just drop the variable in the normal data section. + return DataSection; +} + +const MCSection * +TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const { + // If this constant requires a relocation, we have to put it in the data + // segment, not in the text segment. + if (Kind.isDataRel() || Kind.isReadOnlyWithRel()) + return ConstDataSection; + + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + return ReadOnlySection; // .const +} + +/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide +/// not to emit the UsedDirective for some symbols in llvm.used. +// FIXME: REMOVE this (rdar://7071300) +bool TargetLoweringObjectFileMachO:: +shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { + /// On Darwin, internally linked data beginning with "L" or "l" does not have + /// the directive emitted (this occurs in ObjC metadata). + if (!GV) return false; + + // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. + if (GV->hasLocalLinkage() && !isa(GV)) { + // FIXME: ObjC metadata is currently emitted as internal symbols that have + // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and + // this horrible hack can go away. + MCSymbol *Sym = Mang->getSymbol(GV); + if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l') + return false; + } + + return true; +} + +const MCExpr *TargetLoweringObjectFileMachO:: +getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding, + MCStreamer &Streamer) const { + // The mach-o version of this method defaults to returning a stub reference. + + if (Encoding & DW_EH_PE_indirect) { + MachineModuleInfoMachO &MachOMMI = + MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + + // Add information about the stub reference to MachOMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str()); + MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym); + if (StubSym.getPointer() == 0) { + MCSymbol *Sym = Mang->getSymbol(GV); + StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage()); + } + + return TargetLoweringObjectFile:: + getExprForDwarfReference(SSym, Mang, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect, Streamer); + } + + return TargetLoweringObjectFile:: + getExprForDwarfGlobalReference(GV, Mang, MMI, Encoding, Streamer); +} + +unsigned TargetLoweringObjectFileMachO::getPersonalityEncoding() const { + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; +} + +unsigned TargetLoweringObjectFileMachO::getLSDAEncoding() const { + return DW_EH_PE_pcrel; +} + +unsigned TargetLoweringObjectFileMachO::getFDEEncoding() const { + return DW_EH_PE_pcrel; +} + +unsigned TargetLoweringObjectFileMachO::getTTypeEncoding() const { + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; +} + +//===----------------------------------------------------------------------===// +// COFF +//===----------------------------------------------------------------------===// + +void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + TargetLoweringObjectFile::Initialize(Ctx, TM); + TextSection = + getContext().getCOFFSection(".text", + COFF::IMAGE_SCN_CNT_CODE | + COFF::IMAGE_SCN_MEM_EXECUTE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getText()); + DataSection = + getContext().getCOFFSection(".data", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + ReadOnlySection = + getContext().getCOFFSection(".rdata", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + StaticCtorSection = + getContext().getCOFFSection(".ctors", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + StaticDtorSection = + getContext().getCOFFSection(".dtors", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + + // FIXME: We're emitting LSDA info into a readonly section on COFF, even + // though it contains relocatable pointers. In PIC mode, this is probably a + // big runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getContext().getCOFFSection(".gcc_except_table", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getReadOnly()); + // Debug info. + DwarfAbbrevSection = + getContext().getCOFFSection(".debug_abbrev", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfInfoSection = + getContext().getCOFFSection(".debug_info", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLineSection = + getContext().getCOFFSection(".debug_line", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfFrameSection = + getContext().getCOFFSection(".debug_frame", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getContext().getCOFFSection(".debug_pubnames", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getContext().getCOFFSection(".debug_pubtypes", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfStrSection = + getContext().getCOFFSection(".debug_str", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfLocSection = + getContext().getCOFFSection(".debug_loc", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfARangesSection = + getContext().getCOFFSection(".debug_aranges", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfRangesSection = + getContext().getCOFFSection(".debug_ranges", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getContext().getCOFFSection(".debug_macinfo", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + + DrectveSection = + getContext().getCOFFSection(".drectve", + COFF::IMAGE_SCN_LNK_INFO, + SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileCOFF::getEHFrameSection() const { + return getContext().getCOFFSection(".eh_frame", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); +} + + +static unsigned +getCOFFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (K.isMetadata()) + Flags |= + COFF::IMAGE_SCN_MEM_DISCARDABLE; + else if (K.isText()) + Flags |= + COFF::IMAGE_SCN_MEM_EXECUTE | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_CNT_CODE; + else if (K.isBSS ()) + Flags |= + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + else if (K.isReadOnly()) + Flags |= + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ; + else if (K.isWriteable()) + Flags |= + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + + return Flags; +} + +const MCSection *TargetLoweringObjectFileCOFF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + return getContext().getCOFFSection(GV->getSection(), + getCOFFSectionFlags(Kind), + Kind); +} + +static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) + return ".text$"; + if (Kind.isBSS ()) + return ".bss$"; + if (Kind.isWriteable()) + return ".data$"; + return ".rdata$"; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker()) { + const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); + SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); + MCSymbol *Sym = Mang->getSymbol(GV); + Name.append(Sym->getName().begin() + 1, Sym->getName().end()); + + unsigned Characteristics = getCOFFSectionFlags(Kind); + + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + + return getContext().getCOFFSection(Name.str(), Characteristics, + COFF::IMAGE_COMDAT_SELECT_ANY, Kind); + } + + if (Kind.isText()) + return getTextSection(); + + return getDataSection(); +} + diff --git a/final/lib/CodeGen/TwoAddressInstructionPass.cpp b/final/lib/CodeGen/TwoAddressInstructionPass.cpp new file mode 100644 index 00000000000..52ea87231cc --- /dev/null +++ b/final/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -0,0 +1,1527 @@ +//===-- TwoAddressInstructionPass.cpp - Two-Address instruction pass ------===// +// +// 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 TwoAddress instruction pass which is used +// by most register allocators. Two-Address instructions are rewritten +// from: +// +// A = B op C +// +// to: +// +// A = B +// A op= C +// +// Note that if a register allocator chooses to use this pass, that it +// has to be capable of handling the non-SSA nature of these rewritten +// virtual registers. +// +// It is also worth noting that the duplicate operand of the two +// address instruction is removed. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "twoaddrinstr" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions"); +STATISTIC(NumCommuted , "Number of instructions commuted to coalesce"); +STATISTIC(NumAggrCommuted , "Number of instructions aggressively commuted"); +STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address"); +STATISTIC(Num3AddrSunk, "Number of 3-address instructions sunk"); +STATISTIC(NumReMats, "Number of instructions re-materialized"); +STATISTIC(NumDeletes, "Number of dead instructions deleted"); + +namespace { + class TwoAddressInstructionPass : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + LiveVariables *LV; + AliasAnalysis *AA; + + // DistanceMap - Keep track the distance of a MI from the start of the + // current basic block. + DenseMap DistanceMap; + + // SrcRegMap - A map from virtual registers to physical registers which + // are likely targets to be coalesced to due to copies from physical + // registers to virtual registers. e.g. v1024 = move r0. + DenseMap SrcRegMap; + + // DstRegMap - A map from virtual registers to physical registers which + // are likely targets to be coalesced to due to copies to physical + // registers from virtual registers. e.g. r1 = move v1024. + DenseMap DstRegMap; + + /// RegSequences - Keep track the list of REG_SEQUENCE instructions seen + /// during the initial walk of the machine function. + SmallVector RegSequences; + + bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI, + unsigned Reg, + MachineBasicBlock::iterator OldPos); + + bool isProfitableToReMat(unsigned Reg, const TargetRegisterClass *RC, + MachineInstr *MI, MachineInstr *DefMI, + MachineBasicBlock *MBB, unsigned Loc); + + bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist, + unsigned &LastDef); + + MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB, + unsigned Dist); + + bool isProfitableToCommute(unsigned regB, unsigned regC, + MachineInstr *MI, MachineBasicBlock *MBB, + unsigned Dist); + + bool CommuteInstruction(MachineBasicBlock::iterator &mi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned RegC, unsigned Dist); + + bool isProfitableToConv3Addr(unsigned RegA, unsigned RegB); + + bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned RegA, unsigned RegB, unsigned Dist); + + typedef std::pair, MachineInstr*> NewKill; + bool canUpdateDeletedKills(SmallVector &Kills, + SmallVector &NewKills, + MachineBasicBlock *MBB, unsigned Dist); + bool DeleteUnusedInstr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, unsigned Dist); + + bool TryInstructionTransform(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned SrcIdx, unsigned DstIdx, + unsigned Dist, + SmallPtrSet &Processed); + + void ScanUses(unsigned DstReg, MachineBasicBlock *MBB, + SmallPtrSet &Processed); + + void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB, + SmallPtrSet &Processed); + + void CoalesceExtSubRegs(SmallVector &Srcs, unsigned DstReg); + + /// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as part + /// of the de-ssa process. This replaces sources of REG_SEQUENCE as + /// sub-register references of the register defined by REG_SEQUENCE. + bool EliminateRegSequences(); + + public: + static char ID; // Pass identification, replacement for typeid + TwoAddressInstructionPass() : MachineFunctionPass(ID) { + initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + AU.addPreservedID(PHIEliminationID); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// runOnMachineFunction - Pass entry point. + bool runOnMachineFunction(MachineFunction&); + }; +} + +char TwoAddressInstructionPass::ID = 0; +INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, "twoaddressinstruction", + "Two-Address instruction pass", false, false) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_END(TwoAddressInstructionPass, "twoaddressinstruction", + "Two-Address instruction pass", false, false) + +char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID; + +/// Sink3AddrInstruction - A two-address instruction has been converted to a +/// three-address instruction to avoid clobbering a register. Try to sink it +/// past the instruction that would kill the above mentioned register to reduce +/// register pressure. +bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, + MachineInstr *MI, unsigned SavedReg, + MachineBasicBlock::iterator OldPos) { + // Check if it's safe to move this instruction. + bool SeenStore = true; // Be conservative. + if (!MI->isSafeToMove(TII, AA, SeenStore)) + return false; + + unsigned DefReg = 0; + SmallSet UseRegs; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (MO.isUse() && MOReg != SavedReg) + UseRegs.insert(MO.getReg()); + if (!MO.isDef()) + continue; + if (MO.isImplicit()) + // Don't try to move it if it implicitly defines a register. + return false; + if (DefReg) + // For now, don't move any instructions that define multiple registers. + return false; + DefReg = MO.getReg(); + } + + // Find the instruction that kills SavedReg. + MachineInstr *KillMI = NULL; + for (MachineRegisterInfo::use_nodbg_iterator + UI = MRI->use_nodbg_begin(SavedReg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + if (!UseMO.isKill()) + continue; + KillMI = UseMO.getParent(); + break; + } + + if (!KillMI || KillMI->getParent() != MBB || KillMI == MI) + return false; + + // If any of the definitions are used by another instruction between the + // position and the kill use, then it's not safe to sink it. + // + // FIXME: This can be sped up if there is an easy way to query whether an + // instruction is before or after another instruction. Then we can use + // MachineRegisterInfo def / use instead. + MachineOperand *KillMO = NULL; + MachineBasicBlock::iterator KillPos = KillMI; + ++KillPos; + + unsigned NumVisited = 0; + for (MachineBasicBlock::iterator I = llvm::next(OldPos); I != KillPos; ++I) { + MachineInstr *OtherMI = I; + // DBG_VALUE cannot be counted against the limit. + if (OtherMI->isDebugValue()) + continue; + if (NumVisited > 30) // FIXME: Arbitrary limit to reduce compile time cost. + return false; + ++NumVisited; + for (unsigned i = 0, e = OtherMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = OtherMI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned MOReg = MO.getReg(); + if (!MOReg) + continue; + if (DefReg == MOReg) + return false; + + if (MO.isKill()) { + if (OtherMI == KillMI && MOReg == SavedReg) + // Save the operand that kills the register. We want to unset the kill + // marker if we can sink MI past it. + KillMO = &MO; + else if (UseRegs.count(MOReg)) + // One of the uses is killed before the destination. + return false; + } + } + } + + // Update kill and LV information. + KillMO->setIsKill(false); + KillMO = MI->findRegisterUseOperand(SavedReg, false, TRI); + KillMO->setIsKill(true); + + if (LV) + LV->replaceKillInstruction(SavedReg, KillMI, MI); + + // Move instruction to its destination. + MBB->remove(MI); + MBB->insert(KillPos, MI); + + ++Num3AddrSunk; + return true; +} + +/// isTwoAddrUse - Return true if the specified MI is using the specified +/// register as a two-address operand. +static bool isTwoAddrUse(MachineInstr *UseMI, unsigned Reg) { + const TargetInstrDesc &TID = UseMI->getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(i); + if (MO.isReg() && MO.getReg() == Reg && + (MO.isDef() || UseMI->isRegTiedToDefOperand(i))) + // Earlier use is a two-address one. + return true; + } + return false; +} + +/// isProfitableToReMat - Return true if the heuristics determines it is likely +/// to be profitable to re-materialize the definition of Reg rather than copy +/// the register. +bool +TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg, + const TargetRegisterClass *RC, + MachineInstr *MI, MachineInstr *DefMI, + MachineBasicBlock *MBB, unsigned Loc) { + bool OtherUse = false; + for (MachineRegisterInfo::use_nodbg_iterator UI = MRI->use_nodbg_begin(Reg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = UseMO.getParent(); + MachineBasicBlock *UseMBB = UseMI->getParent(); + if (UseMBB == MBB) { + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end() && DI->second == Loc) + continue; // Current use. + OtherUse = true; + // There is at least one other use in the MBB that will clobber the + // register. + if (isTwoAddrUse(UseMI, Reg)) + return true; + } + } + + // If other uses in MBB are not two-address uses, then don't remat. + if (OtherUse) + return false; + + // No other uses in the same block, remat if it's defined in the same + // block so it does not unnecessarily extend the live range. + return MBB == DefMI->getParent(); +} + +/// NoUseAfterLastDef - Return true if there are no intervening uses between the +/// last instruction in the MBB that defines the specified register and the +/// two-address instruction which is being processed. It also returns the last +/// def location by reference +bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg, + MachineBasicBlock *MBB, unsigned Dist, + unsigned &LastDef) { + LastDef = 0; + unsigned LastUse = Dist; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + MachineInstr *MI = MO.getParent(); + if (MI->getParent() != MBB || MI->isDebugValue()) + continue; + DenseMap::iterator DI = DistanceMap.find(MI); + if (DI == DistanceMap.end()) + continue; + if (MO.isUse() && DI->second < LastUse) + LastUse = DI->second; + if (MO.isDef() && DI->second > LastDef) + LastDef = DI->second; + } + + return !(LastUse > LastDef && LastUse < Dist); +} + +MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg, + MachineBasicBlock *MBB, + unsigned Dist) { + unsigned LastUseDist = 0; + MachineInstr *LastUse = 0; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg), + E = MRI->reg_end(); I != E; ++I) { + MachineOperand &MO = I.getOperand(); + MachineInstr *MI = MO.getParent(); + if (MI->getParent() != MBB || MI->isDebugValue()) + continue; + DenseMap::iterator DI = DistanceMap.find(MI); + if (DI == DistanceMap.end()) + continue; + if (DI->second >= Dist) + continue; + + if (MO.isUse() && DI->second > LastUseDist) { + LastUse = DI->first; + LastUseDist = DI->second; + } + } + return LastUse; +} + +/// isCopyToReg - Return true if the specified MI is a copy instruction or +/// a extract_subreg instruction. It also returns the source and destination +/// registers and whether they are physical registers by reference. +static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII, + unsigned &SrcReg, unsigned &DstReg, + bool &IsSrcPhys, bool &IsDstPhys) { + SrcReg = 0; + DstReg = 0; + if (MI.isCopy()) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + } else if (MI.isInsertSubreg() || MI.isSubregToReg()) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(2).getReg(); + } else + return false; + + IsSrcPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); + IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + return true; +} + +/// isKilled - Test if the given register value, which is used by the given +/// instruction, is killed by the given instruction. This looks through +/// coalescable copies to see if the original value is potentially not killed. +/// +/// For example, in this code: +/// +/// %reg1034 = copy %reg1024 +/// %reg1035 = copy %reg1025 +/// %reg1036 = add %reg1034, %reg1035 +/// +/// %reg1034 is not considered to be killed, since it is copied from a +/// register which is not killed. Treating it as not killed lets the +/// normal heuristics commute the (two-address) add, which lets +/// coalescing eliminate the extra copy. +/// +static bool isKilled(MachineInstr &MI, unsigned Reg, + const MachineRegisterInfo *MRI, + const TargetInstrInfo *TII) { + MachineInstr *DefMI = &MI; + for (;;) { + if (!DefMI->killsRegister(Reg)) + return false; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return true; + MachineRegisterInfo::def_iterator Begin = MRI->def_begin(Reg); + // If there are multiple defs, we can't do a simple analysis, so just + // go with what the kill flag says. + if (llvm::next(Begin) != MRI->def_end()) + return true; + DefMI = &*Begin; + bool IsSrcPhys, IsDstPhys; + unsigned SrcReg, DstReg; + // If the def is something other than a copy, then it isn't going to + // be coalesced, so follow the kill flag. + if (!isCopyToReg(*DefMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + return true; + Reg = SrcReg; + } +} + +/// isTwoAddrUse - Return true if the specified MI uses the specified register +/// as a two-address use. If so, return the destination register by reference. +static bool isTwoAddrUse(MachineInstr &MI, unsigned Reg, unsigned &DstReg) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned NumOps = MI.isInlineAsm() ? MI.getNumOperands():TID.getNumOperands(); + for (unsigned i = 0; i != NumOps; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.getReg() != Reg) + continue; + unsigned ti; + if (MI.isRegTiedToDefOperand(i, &ti)) { + DstReg = MI.getOperand(ti).getReg(); + return true; + } + } + return false; +} + +/// findOnlyInterestingUse - Given a register, if has a single in-basic block +/// use, return the use instruction if it's a copy or a two-address use. +static +MachineInstr *findOnlyInterestingUse(unsigned Reg, MachineBasicBlock *MBB, + MachineRegisterInfo *MRI, + const TargetInstrInfo *TII, + bool &IsCopy, + unsigned &DstReg, bool &IsDstPhys) { + if (!MRI->hasOneNonDBGUse(Reg)) + // None or more than one use. + return 0; + MachineInstr &UseMI = *MRI->use_nodbg_begin(Reg); + if (UseMI.getParent() != MBB) + return 0; + unsigned SrcReg; + bool IsSrcPhys; + if (isCopyToReg(UseMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) { + IsCopy = true; + return &UseMI; + } + IsDstPhys = false; + if (isTwoAddrUse(UseMI, Reg, DstReg)) { + IsDstPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); + return &UseMI; + } + return 0; +} + +/// getMappedReg - Return the physical register the specified virtual register +/// might be mapped to. +static unsigned +getMappedReg(unsigned Reg, DenseMap &RegMap) { + while (TargetRegisterInfo::isVirtualRegister(Reg)) { + DenseMap::iterator SI = RegMap.find(Reg); + if (SI == RegMap.end()) + return 0; + Reg = SI->second; + } + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return Reg; + return 0; +} + +/// regsAreCompatible - Return true if the two registers are equal or aliased. +/// +static bool +regsAreCompatible(unsigned RegA, unsigned RegB, const TargetRegisterInfo *TRI) { + if (RegA == RegB) + return true; + if (!RegA || !RegB) + return false; + return TRI->regsOverlap(RegA, RegB); +} + + +/// isProfitableToReMat - Return true if it's potentially profitable to commute +/// the two-address instruction that's being processed. +bool +TwoAddressInstructionPass::isProfitableToCommute(unsigned regB, unsigned regC, + MachineInstr *MI, MachineBasicBlock *MBB, + unsigned Dist) { + // Determine if it's profitable to commute this two address instruction. In + // general, we want no uses between this instruction and the definition of + // the two-address register. + // e.g. + // %reg1028 = EXTRACT_SUBREG %reg1027, 1 + // %reg1029 = MOV8rr %reg1028 + // %reg1029 = SHR8ri %reg1029, 7, %EFLAGS + // insert => %reg1030 = MOV8rr %reg1028 + // %reg1030 = ADD8rr %reg1028, %reg1029, %EFLAGS + // In this case, it might not be possible to coalesce the second MOV8rr + // instruction if the first one is coalesced. So it would be profitable to + // commute it: + // %reg1028 = EXTRACT_SUBREG %reg1027, 1 + // %reg1029 = MOV8rr %reg1028 + // %reg1029 = SHR8ri %reg1029, 7, %EFLAGS + // insert => %reg1030 = MOV8rr %reg1029 + // %reg1030 = ADD8rr %reg1029, %reg1028, %EFLAGS + + if (!MI->killsRegister(regC)) + return false; + + // Ok, we have something like: + // %reg1030 = ADD8rr %reg1028, %reg1029, %EFLAGS + // let's see if it's worth commuting it. + + // Look for situations like this: + // %reg1024 = MOV r1 + // %reg1025 = MOV r0 + // %reg1026 = ADD %reg1024, %reg1025 + // r0 = MOV %reg1026 + // Commute the ADD to hopefully eliminate an otherwise unavoidable copy. + unsigned FromRegB = getMappedReg(regB, SrcRegMap); + unsigned FromRegC = getMappedReg(regC, SrcRegMap); + unsigned ToRegB = getMappedReg(regB, DstRegMap); + unsigned ToRegC = getMappedReg(regC, DstRegMap); + if ((FromRegB && ToRegB && !regsAreCompatible(FromRegB, ToRegB, TRI)) && + ((!FromRegC && !ToRegC) || + regsAreCompatible(FromRegB, ToRegC, TRI) || + regsAreCompatible(FromRegC, ToRegB, TRI))) + return true; + + // If there is a use of regC between its last def (could be livein) and this + // instruction, then bail. + unsigned LastDefC = 0; + if (!NoUseAfterLastDef(regC, MBB, Dist, LastDefC)) + return false; + + // If there is a use of regB between its last def (could be livein) and this + // instruction, then go ahead and make this transformation. + unsigned LastDefB = 0; + if (!NoUseAfterLastDef(regB, MBB, Dist, LastDefB)) + return true; + + // Since there are no intervening uses for both registers, then commute + // if the def of regC is closer. Its live interval is shorter. + return LastDefB && LastDefC && LastDefC > LastDefB; +} + +/// CommuteInstruction - Commute a two-address instruction and update the basic +/// block, distance map, and live variables if needed. Return true if it is +/// successful. +bool +TwoAddressInstructionPass::CommuteInstruction(MachineBasicBlock::iterator &mi, + MachineFunction::iterator &mbbi, + unsigned RegB, unsigned RegC, unsigned Dist) { + MachineInstr *MI = mi; + DEBUG(dbgs() << "2addr: COMMUTING : " << *MI); + MachineInstr *NewMI = TII->commuteInstruction(MI); + + if (NewMI == 0) { + DEBUG(dbgs() << "2addr: COMMUTING FAILED!\n"); + return false; + } + + DEBUG(dbgs() << "2addr: COMMUTED TO: " << *NewMI); + // If the instruction changed to commute it, update livevar. + if (NewMI != MI) { + if (LV) + // Update live variables + LV->replaceKillInstruction(RegC, MI, NewMI); + + mbbi->insert(mi, NewMI); // Insert the new inst + mbbi->erase(mi); // Nuke the old inst. + mi = NewMI; + DistanceMap.insert(std::make_pair(NewMI, Dist)); + } + + // Update source register map. + unsigned FromRegC = getMappedReg(RegC, SrcRegMap); + if (FromRegC) { + unsigned RegA = MI->getOperand(0).getReg(); + SrcRegMap[RegA] = FromRegC; + } + + return true; +} + +/// isProfitableToConv3Addr - Return true if it is profitable to convert the +/// given 2-address instruction to a 3-address one. +bool +TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA,unsigned RegB){ + // Look for situations like this: + // %reg1024 = MOV r1 + // %reg1025 = MOV r0 + // %reg1026 = ADD %reg1024, %reg1025 + // r2 = MOV %reg1026 + // Turn ADD into a 3-address instruction to avoid a copy. + unsigned FromRegB = getMappedReg(RegB, SrcRegMap); + if (!FromRegB) + return false; + unsigned ToRegA = getMappedReg(RegA, DstRegMap); + return (ToRegA && !regsAreCompatible(FromRegB, ToRegA, TRI)); +} + +/// ConvertInstTo3Addr - Convert the specified two-address instruction into a +/// three address one. Return true if this transformation was successful. +bool +TwoAddressInstructionPass::ConvertInstTo3Addr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned RegA, unsigned RegB, + unsigned Dist) { + MachineInstr *NewMI = TII->convertToThreeAddress(mbbi, mi, LV); + if (NewMI) { + DEBUG(dbgs() << "2addr: CONVERTING 2-ADDR: " << *mi); + DEBUG(dbgs() << "2addr: TO 3-ADDR: " << *NewMI); + bool Sunk = false; + + if (NewMI->findRegisterUseOperand(RegB, false, TRI)) + // FIXME: Temporary workaround. If the new instruction doesn't + // uses RegB, convertToThreeAddress must have created more + // then one instruction. + Sunk = Sink3AddrInstruction(mbbi, NewMI, RegB, mi); + + mbbi->erase(mi); // Nuke the old inst. + + if (!Sunk) { + DistanceMap.insert(std::make_pair(NewMI, Dist)); + mi = NewMI; + nmi = llvm::next(mi); + } + + // Update source and destination register maps. + SrcRegMap.erase(RegA); + DstRegMap.erase(RegB); + return true; + } + + return false; +} + +/// ScanUses - Scan forward recursively for only uses, update maps if the use +/// is a copy or a two-address instruction. +void +TwoAddressInstructionPass::ScanUses(unsigned DstReg, MachineBasicBlock *MBB, + SmallPtrSet &Processed) { + SmallVector VirtRegPairs; + bool IsDstPhys; + bool IsCopy = false; + unsigned NewReg = 0; + unsigned Reg = DstReg; + while (MachineInstr *UseMI = findOnlyInterestingUse(Reg, MBB, MRI, TII,IsCopy, + NewReg, IsDstPhys)) { + if (IsCopy && !Processed.insert(UseMI)) + break; + + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end()) + // Earlier in the same MBB.Reached via a back edge. + break; + + if (IsDstPhys) { + VirtRegPairs.push_back(NewReg); + break; + } + bool isNew = SrcRegMap.insert(std::make_pair(NewReg, Reg)).second; + if (!isNew) + assert(SrcRegMap[NewReg] == Reg && "Can't map to two src registers!"); + VirtRegPairs.push_back(NewReg); + Reg = NewReg; + } + + if (!VirtRegPairs.empty()) { + unsigned ToReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + while (!VirtRegPairs.empty()) { + unsigned FromReg = VirtRegPairs.back(); + VirtRegPairs.pop_back(); + bool isNew = DstRegMap.insert(std::make_pair(FromReg, ToReg)).second; + if (!isNew) + assert(DstRegMap[FromReg] == ToReg &&"Can't map to two dst registers!"); + ToReg = FromReg; + } + bool isNew = DstRegMap.insert(std::make_pair(DstReg, ToReg)).second; + if (!isNew) + assert(DstRegMap[DstReg] == ToReg && "Can't map to two dst registers!"); + } +} + +/// ProcessCopy - If the specified instruction is not yet processed, process it +/// if it's a copy. For a copy instruction, we find the physical registers the +/// source and destination registers might be mapped to. These are kept in +/// point-to maps used to determine future optimizations. e.g. +/// v1024 = mov r0 +/// v1025 = mov r1 +/// v1026 = add v1024, v1025 +/// r1 = mov r1026 +/// If 'add' is a two-address instruction, v1024, v1026 are both potentially +/// coalesced to r0 (from the input side). v1025 is mapped to r1. v1026 is +/// potentially joined with r1 on the output side. It's worthwhile to commute +/// 'add' to eliminate a copy. +void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI, + MachineBasicBlock *MBB, + SmallPtrSet &Processed) { + if (Processed.count(MI)) + return; + + bool IsSrcPhys, IsDstPhys; + unsigned SrcReg, DstReg; + if (!isCopyToReg(*MI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + return; + + if (IsDstPhys && !IsSrcPhys) + DstRegMap.insert(std::make_pair(SrcReg, DstReg)); + else if (!IsDstPhys && IsSrcPhys) { + bool isNew = SrcRegMap.insert(std::make_pair(DstReg, SrcReg)).second; + if (!isNew) + assert(SrcRegMap[DstReg] == SrcReg && + "Can't map to two src physical registers!"); + + ScanUses(DstReg, MBB, Processed); + } + + Processed.insert(MI); + return; +} + +/// isSafeToDelete - If the specified instruction does not produce any side +/// effects and all of its defs are dead, then it's safe to delete. +static bool isSafeToDelete(MachineInstr *MI, + const TargetInstrInfo *TII, + SmallVector &Kills) { + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayStore() || TID.isCall()) + return false; + if (TID.isTerminator() || MI->hasUnmodeledSideEffects()) + return false; + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + if (MO.isDef() && !MO.isDead()) + return false; + if (MO.isUse() && MO.isKill()) + Kills.push_back(MO.getReg()); + } + return true; +} + +/// canUpdateDeletedKills - Check if all the registers listed in Kills are +/// killed by instructions in MBB preceding the current instruction at +/// position Dist. If so, return true and record information about the +/// preceding kills in NewKills. +bool TwoAddressInstructionPass:: +canUpdateDeletedKills(SmallVector &Kills, + SmallVector &NewKills, + MachineBasicBlock *MBB, unsigned Dist) { + while (!Kills.empty()) { + unsigned Kill = Kills.back(); + Kills.pop_back(); + if (TargetRegisterInfo::isPhysicalRegister(Kill)) + return false; + + MachineInstr *LastKill = FindLastUseInMBB(Kill, MBB, Dist); + if (!LastKill) + return false; + + bool isModRef = LastKill->definesRegister(Kill); + NewKills.push_back(std::make_pair(std::make_pair(Kill, isModRef), + LastKill)); + } + return true; +} + +/// DeleteUnusedInstr - If an instruction with a tied register operand can +/// be safely deleted, just delete it. +bool +TwoAddressInstructionPass::DeleteUnusedInstr(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned Dist) { + // Check if the instruction has no side effects and if all its defs are dead. + SmallVector Kills; + if (!isSafeToDelete(mi, TII, Kills)) + return false; + + // If this instruction kills some virtual registers, we need to + // update the kill information. If it's not possible to do so, + // then bail out. + SmallVector NewKills; + if (!canUpdateDeletedKills(Kills, NewKills, &*mbbi, Dist)) + return false; + + if (LV) { + while (!NewKills.empty()) { + MachineInstr *NewKill = NewKills.back().second; + unsigned Kill = NewKills.back().first.first; + bool isDead = NewKills.back().first.second; + NewKills.pop_back(); + if (LV->removeVirtualRegisterKilled(Kill, mi)) { + if (isDead) + LV->addVirtualRegisterDead(Kill, NewKill); + else + LV->addVirtualRegisterKilled(Kill, NewKill); + } + } + } + + mbbi->erase(mi); // Nuke the old inst. + mi = nmi; + return true; +} + +/// TryInstructionTransform - For the case where an instruction has a single +/// pair of tied register operands, attempt some transformations that may +/// either eliminate the tied operands or improve the opportunities for +/// coalescing away the register copy. Returns true if the tied operands +/// are eliminated altogether. +bool TwoAddressInstructionPass:: +TryInstructionTransform(MachineBasicBlock::iterator &mi, + MachineBasicBlock::iterator &nmi, + MachineFunction::iterator &mbbi, + unsigned SrcIdx, unsigned DstIdx, unsigned Dist, + SmallPtrSet &Processed) { + const TargetInstrDesc &TID = mi->getDesc(); + unsigned regA = mi->getOperand(DstIdx).getReg(); + unsigned regB = mi->getOperand(SrcIdx).getReg(); + + assert(TargetRegisterInfo::isVirtualRegister(regB) && + "cannot make instruction into two-address form"); + + // If regA is dead and the instruction can be deleted, just delete + // it so it doesn't clobber regB. + bool regBKilled = isKilled(*mi, regB, MRI, TII); + if (!regBKilled && mi->getOperand(DstIdx).isDead() && + DeleteUnusedInstr(mi, nmi, mbbi, Dist)) { + ++NumDeletes; + return true; // Done with this instruction. + } + + // Check if it is profitable to commute the operands. + unsigned SrcOp1, SrcOp2; + unsigned regC = 0; + unsigned regCIdx = ~0U; + bool TryCommute = false; + bool AggressiveCommute = false; + if (TID.isCommutable() && mi->getNumOperands() >= 3 && + TII->findCommutedOpIndices(mi, SrcOp1, SrcOp2)) { + if (SrcIdx == SrcOp1) + regCIdx = SrcOp2; + else if (SrcIdx == SrcOp2) + regCIdx = SrcOp1; + + if (regCIdx != ~0U) { + regC = mi->getOperand(regCIdx).getReg(); + if (!regBKilled && isKilled(*mi, regC, MRI, TII)) + // If C dies but B does not, swap the B and C operands. + // This makes the live ranges of A and C joinable. + TryCommute = true; + else if (isProfitableToCommute(regB, regC, mi, mbbi, Dist)) { + TryCommute = true; + AggressiveCommute = true; + } + } + } + + // If it's profitable to commute, try to do so. + if (TryCommute && CommuteInstruction(mi, mbbi, regB, regC, Dist)) { + ++NumCommuted; + if (AggressiveCommute) + ++NumAggrCommuted; + return false; + } + + if (TargetRegisterInfo::isVirtualRegister(regA)) + ScanUses(regA, &*mbbi, Processed); + + if (TID.isConvertibleTo3Addr()) { + // This instruction is potentially convertible to a true + // three-address instruction. Check if it is profitable. + if (!regBKilled || isProfitableToConv3Addr(regA, regB)) { + // Try to convert it. + if (ConvertInstTo3Addr(mi, nmi, mbbi, regA, regB, Dist)) { + ++NumConvertedTo3Addr; + return true; // Done with this instruction. + } + } + } + + // If this is an instruction with a load folded into it, try unfolding + // the load, e.g. avoid this: + // movq %rdx, %rcx + // addq (%rax), %rcx + // in favor of this: + // movq (%rax), %rcx + // addq %rdx, %rcx + // because it's preferable to schedule a load than a register copy. + if (TID.mayLoad() && !regBKilled) { + // Determine if a load can be unfolded. + unsigned LoadRegIndex; + unsigned NewOpc = + TII->getOpcodeAfterMemoryUnfold(mi->getOpcode(), + /*UnfoldLoad=*/true, + /*UnfoldStore=*/false, + &LoadRegIndex); + if (NewOpc != 0) { + const TargetInstrDesc &UnfoldTID = TII->get(NewOpc); + if (UnfoldTID.getNumDefs() == 1) { + MachineFunction &MF = *mbbi->getParent(); + + // Unfold the load. + DEBUG(dbgs() << "2addr: UNFOLDING: " << *mi); + const TargetRegisterClass *RC = + UnfoldTID.OpInfo[LoadRegIndex].getRegClass(TRI); + unsigned Reg = MRI->createVirtualRegister(RC); + SmallVector NewMIs; + if (!TII->unfoldMemoryOperand(MF, mi, Reg, + /*UnfoldLoad=*/true,/*UnfoldStore=*/false, + NewMIs)) { + DEBUG(dbgs() << "2addr: ABANDONING UNFOLD\n"); + return false; + } + assert(NewMIs.size() == 2 && + "Unfolded a load into multiple instructions!"); + // The load was previously folded, so this is the only use. + NewMIs[1]->addRegisterKilled(Reg, TRI); + + // Tentatively insert the instructions into the block so that they + // look "normal" to the transformation logic. + mbbi->insert(mi, NewMIs[0]); + mbbi->insert(mi, NewMIs[1]); + + DEBUG(dbgs() << "2addr: NEW LOAD: " << *NewMIs[0] + << "2addr: NEW INST: " << *NewMIs[1]); + + // Transform the instruction, now that it no longer has a load. + unsigned NewDstIdx = NewMIs[1]->findRegisterDefOperandIdx(regA); + unsigned NewSrcIdx = NewMIs[1]->findRegisterUseOperandIdx(regB); + MachineBasicBlock::iterator NewMI = NewMIs[1]; + bool TransformSuccess = + TryInstructionTransform(NewMI, mi, mbbi, + NewSrcIdx, NewDstIdx, Dist, Processed); + if (TransformSuccess || + NewMIs[1]->getOperand(NewSrcIdx).isKill()) { + // Success, or at least we made an improvement. Keep the unfolded + // instructions and discard the original. + if (LV) { + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO = mi->getOperand(i); + if (MO.isReg() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + if (MO.isUse()) { + if (MO.isKill()) { + if (NewMIs[0]->killsRegister(MO.getReg())) + LV->replaceKillInstruction(MO.getReg(), mi, NewMIs[0]); + else { + assert(NewMIs[1]->killsRegister(MO.getReg()) && + "Kill missing after load unfold!"); + LV->replaceKillInstruction(MO.getReg(), mi, NewMIs[1]); + } + } + } else if (LV->removeVirtualRegisterDead(MO.getReg(), mi)) { + if (NewMIs[1]->registerDefIsDead(MO.getReg())) + LV->addVirtualRegisterDead(MO.getReg(), NewMIs[1]); + else { + assert(NewMIs[0]->registerDefIsDead(MO.getReg()) && + "Dead flag missing after load unfold!"); + LV->addVirtualRegisterDead(MO.getReg(), NewMIs[0]); + } + } + } + } + LV->addVirtualRegisterKilled(Reg, NewMIs[1]); + } + mi->eraseFromParent(); + mi = NewMIs[1]; + if (TransformSuccess) + return true; + } else { + // Transforming didn't eliminate the tie and didn't lead to an + // improvement. Clean up the unfolded instructions and keep the + // original. + DEBUG(dbgs() << "2addr: ABANDONING UNFOLD\n"); + NewMIs[0]->eraseFromParent(); + NewMIs[1]->eraseFromParent(); + } + } + } + } + + return false; +} + +/// runOnMachineFunction - Reduce two-address instructions to two operands. +/// +bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "Machine Function\n"); + const TargetMachine &TM = MF.getTarget(); + MRI = &MF.getRegInfo(); + TII = TM.getInstrInfo(); + TRI = TM.getRegisterInfo(); + LV = getAnalysisIfAvailable(); + AA = &getAnalysis(); + + bool MadeChange = false; + + DEBUG(dbgs() << "********** REWRITING TWO-ADDR INSTRS **********\n"); + DEBUG(dbgs() << "********** Function: " + << MF.getFunction()->getName() << '\n'); + + // ReMatRegs - Keep track of the registers whose def's are remat'ed. + BitVector ReMatRegs(MRI->getNumVirtRegs()); + + typedef DenseMap, 4> > + TiedOperandMap; + TiedOperandMap TiedOperands(4); + + SmallPtrSet Processed; + for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end(); + mbbi != mbbe; ++mbbi) { + unsigned Dist = 0; + DistanceMap.clear(); + SrcRegMap.clear(); + DstRegMap.clear(); + Processed.clear(); + for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); + mi != me; ) { + MachineBasicBlock::iterator nmi = llvm::next(mi); + if (mi->isDebugValue()) { + mi = nmi; + continue; + } + + // Remember REG_SEQUENCE instructions, we'll deal with them later. + if (mi->isRegSequence()) + RegSequences.push_back(&*mi); + + const TargetInstrDesc &TID = mi->getDesc(); + bool FirstTied = true; + + DistanceMap.insert(std::make_pair(mi, ++Dist)); + + ProcessCopy(&*mi, &*mbbi, Processed); + + // First scan through all the tied register uses in this instruction + // and record a list of pairs of tied operands for each register. + unsigned NumOps = mi->isInlineAsm() + ? mi->getNumOperands() : TID.getNumOperands(); + for (unsigned SrcIdx = 0; SrcIdx < NumOps; ++SrcIdx) { + unsigned DstIdx = 0; + if (!mi->isRegTiedToDefOperand(SrcIdx, &DstIdx)) + continue; + + if (FirstTied) { + FirstTied = false; + ++NumTwoAddressInstrs; + DEBUG(dbgs() << '\t' << *mi); + } + + assert(mi->getOperand(SrcIdx).isReg() && + mi->getOperand(SrcIdx).getReg() && + mi->getOperand(SrcIdx).isUse() && + "two address instruction invalid"); + + unsigned regB = mi->getOperand(SrcIdx).getReg(); + TiedOperandMap::iterator OI = TiedOperands.find(regB); + if (OI == TiedOperands.end()) { + SmallVector, 4> TiedPair; + OI = TiedOperands.insert(std::make_pair(regB, TiedPair)).first; + } + OI->second.push_back(std::make_pair(SrcIdx, DstIdx)); + } + + // Now iterate over the information collected above. + for (TiedOperandMap::iterator OI = TiedOperands.begin(), + OE = TiedOperands.end(); OI != OE; ++OI) { + SmallVector, 4> &TiedPairs = OI->second; + + // If the instruction has a single pair of tied operands, try some + // transformations that may either eliminate the tied operands or + // improve the opportunities for coalescing away the register copy. + if (TiedOperands.size() == 1 && TiedPairs.size() == 1) { + unsigned SrcIdx = TiedPairs[0].first; + unsigned DstIdx = TiedPairs[0].second; + + // If the registers are already equal, nothing needs to be done. + if (mi->getOperand(SrcIdx).getReg() == + mi->getOperand(DstIdx).getReg()) + break; // Done with this instruction. + + if (TryInstructionTransform(mi, nmi, mbbi, SrcIdx, DstIdx, Dist, + Processed)) + break; // The tied operands have been eliminated. + } + + bool RemovedKillFlag = false; + bool AllUsesCopied = true; + unsigned LastCopiedReg = 0; + unsigned regB = OI->first; + for (unsigned tpi = 0, tpe = TiedPairs.size(); tpi != tpe; ++tpi) { + unsigned SrcIdx = TiedPairs[tpi].first; + unsigned DstIdx = TiedPairs[tpi].second; + unsigned regA = mi->getOperand(DstIdx).getReg(); + // Grab regB from the instruction because it may have changed if the + // instruction was commuted. + regB = mi->getOperand(SrcIdx).getReg(); + + if (regA == regB) { + // The register is tied to multiple destinations (or else we would + // not have continued this far), but this use of the register + // already matches the tied destination. Leave it. + AllUsesCopied = false; + continue; + } + LastCopiedReg = regA; + + assert(TargetRegisterInfo::isVirtualRegister(regB) && + "cannot make instruction into two-address form"); + +#ifndef NDEBUG + // First, verify that we don't have a use of "a" in the instruction + // (a = b + a for example) because our transformation will not + // work. This should never occur because we are in SSA form. + for (unsigned i = 0; i != mi->getNumOperands(); ++i) + assert(i == DstIdx || + !mi->getOperand(i).isReg() || + mi->getOperand(i).getReg() != regA); +#endif + + // Emit a copy or rematerialize the definition. + const TargetRegisterClass *rc = MRI->getRegClass(regB); + MachineInstr *DefMI = MRI->getVRegDef(regB); + // If it's safe and profitable, remat the definition instead of + // copying it. + if (DefMI && + DefMI->getDesc().isAsCheapAsAMove() && + DefMI->isSafeToReMat(TII, AA, regB) && + isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){ + DEBUG(dbgs() << "2addr: REMATTING : " << *DefMI << "\n"); + unsigned regASubIdx = mi->getOperand(DstIdx).getSubReg(); + TII->reMaterialize(*mbbi, mi, regA, regASubIdx, DefMI, *TRI); + ReMatRegs.set(TargetRegisterInfo::virtReg2Index(regB)); + ++NumReMats; + } else { + BuildMI(*mbbi, mi, mi->getDebugLoc(), TII->get(TargetOpcode::COPY), + regA).addReg(regB); + } + + MachineBasicBlock::iterator prevMI = prior(mi); + // Update DistanceMap. + DistanceMap.insert(std::make_pair(prevMI, Dist)); + DistanceMap[mi] = ++Dist; + + DEBUG(dbgs() << "\t\tprepend:\t" << *prevMI); + + MachineOperand &MO = mi->getOperand(SrcIdx); + assert(MO.isReg() && MO.getReg() == regB && MO.isUse() && + "inconsistent operand info for 2-reg pass"); + if (MO.isKill()) { + MO.setIsKill(false); + RemovedKillFlag = true; + } + MO.setReg(regA); + } + + if (AllUsesCopied) { + // Replace other (un-tied) uses of regB with LastCopiedReg. + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO = mi->getOperand(i); + if (MO.isReg() && MO.getReg() == regB && MO.isUse()) { + if (MO.isKill()) { + MO.setIsKill(false); + RemovedKillFlag = true; + } + MO.setReg(LastCopiedReg); + } + } + + // Update live variables for regB. + if (RemovedKillFlag && LV && LV->getVarInfo(regB).removeKill(mi)) + LV->addVirtualRegisterKilled(regB, prior(mi)); + + } else if (RemovedKillFlag) { + // Some tied uses of regB matched their destination registers, so + // regB is still used in this instruction, but a kill flag was + // removed from a different tied use of regB, so now we need to add + // a kill flag to one of the remaining uses of regB. + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + MachineOperand &MO = mi->getOperand(i); + if (MO.isReg() && MO.getReg() == regB && MO.isUse()) { + MO.setIsKill(true); + break; + } + } + } + + // Schedule the source copy / remat inserted to form two-address + // instruction. FIXME: Does it matter the distance map may not be + // accurate after it's scheduled? + TII->scheduleTwoAddrSource(prior(mi), mi, *TRI); + + MadeChange = true; + + DEBUG(dbgs() << "\t\trewrite to:\t" << *mi); + } + + // Rewrite INSERT_SUBREG as COPY now that we no longer need SSA form. + if (mi->isInsertSubreg()) { + // From %reg = INSERT_SUBREG %reg, %subreg, subidx + // To %reg:subidx = COPY %subreg + unsigned SubIdx = mi->getOperand(3).getImm(); + mi->RemoveOperand(3); + assert(mi->getOperand(0).getSubReg() == 0 && "Unexpected subreg idx"); + mi->getOperand(0).setSubReg(SubIdx); + mi->RemoveOperand(1); + mi->setDesc(TII->get(TargetOpcode::COPY)); + DEBUG(dbgs() << "\t\tconvert to:\t" << *mi); + } + + // Clear TiedOperands here instead of at the top of the loop + // since most instructions do not have tied operands. + TiedOperands.clear(); + mi = nmi; + } + } + + // Some remat'ed instructions are dead. + for (int i = ReMatRegs.find_first(); i != -1; i = ReMatRegs.find_next(i)) { + unsigned VReg = TargetRegisterInfo::index2VirtReg(i); + if (MRI->use_nodbg_empty(VReg)) { + MachineInstr *DefMI = MRI->getVRegDef(VReg); + DefMI->eraseFromParent(); + } + } + + // Eliminate REG_SEQUENCE instructions. Their whole purpose was to preseve + // SSA form. It's now safe to de-SSA. + MadeChange |= EliminateRegSequences(); + + return MadeChange; +} + +static void UpdateRegSequenceSrcs(unsigned SrcReg, + unsigned DstReg, unsigned SubIdx, + MachineRegisterInfo *MRI, + const TargetRegisterInfo &TRI) { + for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg), + RE = MRI->reg_end(); RI != RE; ) { + MachineOperand &MO = RI.getOperand(); + ++RI; + MO.substVirtReg(DstReg, SubIdx, TRI); + } +} + +/// CoalesceExtSubRegs - If a number of sources of the REG_SEQUENCE are +/// EXTRACT_SUBREG from the same register and to the same virtual register +/// with different sub-register indices, attempt to combine the +/// EXTRACT_SUBREGs and pre-coalesce them. e.g. +/// %reg1026 = VLDMQ %reg1025, 260, pred:14, pred:%reg0 +/// %reg1029:6 = EXTRACT_SUBREG %reg1026, 6 +/// %reg1029:5 = EXTRACT_SUBREG %reg1026, 5 +/// Since D subregs 5, 6 can combine to a Q register, we can coalesce +/// reg1026 to reg1029. +void +TwoAddressInstructionPass::CoalesceExtSubRegs(SmallVector &Srcs, + unsigned DstReg) { + SmallSet Seen; + for (unsigned i = 0, e = Srcs.size(); i != e; ++i) { + unsigned SrcReg = Srcs[i]; + if (!Seen.insert(SrcReg)) + continue; + + // Check that the instructions are all in the same basic block. + MachineInstr *SrcDefMI = MRI->getVRegDef(SrcReg); + MachineInstr *DstDefMI = MRI->getVRegDef(DstReg); + if (SrcDefMI->getParent() != DstDefMI->getParent()) + continue; + + // If there are no other uses than copies which feed into + // the reg_sequence, then we might be able to coalesce them. + bool CanCoalesce = true; + SmallVector SrcSubIndices, DstSubIndices; + for (MachineRegisterInfo::use_nodbg_iterator + UI = MRI->use_nodbg_begin(SrcReg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (!UseMI->isCopy() || UseMI->getOperand(0).getReg() != DstReg) { + CanCoalesce = false; + break; + } + SrcSubIndices.push_back(UseMI->getOperand(1).getSubReg()); + DstSubIndices.push_back(UseMI->getOperand(0).getSubReg()); + } + + if (!CanCoalesce || SrcSubIndices.size() < 2) + continue; + + // Check that the source subregisters can be combined. + std::sort(SrcSubIndices.begin(), SrcSubIndices.end()); + unsigned NewSrcSubIdx = 0; + if (!TRI->canCombineSubRegIndices(MRI->getRegClass(SrcReg), SrcSubIndices, + NewSrcSubIdx)) + continue; + + // Check that the destination subregisters can also be combined. + std::sort(DstSubIndices.begin(), DstSubIndices.end()); + unsigned NewDstSubIdx = 0; + if (!TRI->canCombineSubRegIndices(MRI->getRegClass(DstReg), DstSubIndices, + NewDstSubIdx)) + continue; + + // If neither source nor destination can be combined to the full register, + // just give up. This could be improved if it ever matters. + if (NewSrcSubIdx != 0 && NewDstSubIdx != 0) + continue; + + // Now that we know that all the uses are extract_subregs and that those + // subregs can somehow be combined, scan all the extract_subregs again to + // make sure the subregs are in the right order and can be composed. + MachineInstr *SomeMI = 0; + CanCoalesce = true; + for (MachineRegisterInfo::use_nodbg_iterator + UI = MRI->use_nodbg_begin(SrcReg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + assert(UseMI->isCopy()); + unsigned DstSubIdx = UseMI->getOperand(0).getSubReg(); + unsigned SrcSubIdx = UseMI->getOperand(1).getSubReg(); + assert(DstSubIdx != 0 && "missing subreg from RegSequence elimination"); + if ((NewDstSubIdx == 0 && + TRI->composeSubRegIndices(NewSrcSubIdx, DstSubIdx) != SrcSubIdx) || + (NewSrcSubIdx == 0 && + TRI->composeSubRegIndices(NewDstSubIdx, SrcSubIdx) != DstSubIdx)) { + CanCoalesce = false; + break; + } + // Keep track of one of the uses. + SomeMI = UseMI; + } + if (!CanCoalesce) + continue; + + // Insert a copy to replace the original. + MachineInstr *CopyMI = BuildMI(*SomeMI->getParent(), SomeMI, + SomeMI->getDebugLoc(), + TII->get(TargetOpcode::COPY)) + .addReg(DstReg, RegState::Define, NewDstSubIdx) + .addReg(SrcReg, 0, NewSrcSubIdx); + + // Remove all the old extract instructions. + for (MachineRegisterInfo::use_nodbg_iterator + UI = MRI->use_nodbg_begin(SrcReg), + UE = MRI->use_nodbg_end(); UI != UE; ) { + MachineInstr *UseMI = &*UI; + ++UI; + if (UseMI == CopyMI) + continue; + assert(UseMI->isCopy()); + // Move any kills to the new copy or extract instruction. + if (UseMI->getOperand(1).isKill()) { + CopyMI->getOperand(1).setIsKill(); + if (LV) + // Update live variables + LV->replaceKillInstruction(SrcReg, UseMI, &*CopyMI); + } + UseMI->eraseFromParent(); + } + } +} + +static bool HasOtherRegSequenceUses(unsigned Reg, MachineInstr *RegSeq, + MachineRegisterInfo *MRI) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineInstr *UseMI = &*UI; + if (UseMI != RegSeq && UseMI->isRegSequence()) + return true; + } + return false; +} + +/// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as part +/// of the de-ssa process. This replaces sources of REG_SEQUENCE as +/// sub-register references of the register defined by REG_SEQUENCE. e.g. +/// +/// %reg1029, %reg1030 = VLD1q16 %reg1024, ... +/// %reg1031 = REG_SEQUENCE %reg1029, 5, %reg1030, 6 +/// => +/// %reg1031:5, %reg1031:6 = VLD1q16 %reg1024, ... +bool TwoAddressInstructionPass::EliminateRegSequences() { + if (RegSequences.empty()) + return false; + + for (unsigned i = 0, e = RegSequences.size(); i != e; ++i) { + MachineInstr *MI = RegSequences[i]; + unsigned DstReg = MI->getOperand(0).getReg(); + if (MI->getOperand(0).getSubReg() || + TargetRegisterInfo::isPhysicalRegister(DstReg) || + !(MI->getNumOperands() & 1)) { + DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << *MI); + llvm_unreachable(0); + } + + bool IsImpDef = true; + SmallVector RealSrcs; + SmallSet Seen; + for (unsigned i = 1, e = MI->getNumOperands(); i < e; i += 2) { + unsigned SrcReg = MI->getOperand(i).getReg(); + unsigned SubIdx = MI->getOperand(i+1).getImm(); + if (MI->getOperand(i).getSubReg() || + TargetRegisterInfo::isPhysicalRegister(SrcReg)) { + DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << *MI); + llvm_unreachable(0); + } + + MachineInstr *DefMI = MRI->getVRegDef(SrcReg); + if (DefMI->isImplicitDef()) { + DefMI->eraseFromParent(); + continue; + } + IsImpDef = false; + + // Remember COPY sources. These might be candidate for coalescing. + if (DefMI->isCopy() && DefMI->getOperand(1).getSubReg()) + RealSrcs.push_back(DefMI->getOperand(1).getReg()); + + bool isKill = MI->getOperand(i).isKill(); + if (!Seen.insert(SrcReg) || MI->getParent() != DefMI->getParent() || + !isKill || HasOtherRegSequenceUses(SrcReg, MI, MRI) || + !TRI->getMatchingSuperRegClass(MRI->getRegClass(DstReg), + MRI->getRegClass(SrcReg), SubIdx)) { + // REG_SEQUENCE cannot have duplicated operands, add a copy. + // Also add an copy if the source is live-in the block. We don't want + // to end up with a partial-redef of a livein, e.g. + // BB0: + // reg1051:10 = + // ... + // BB1: + // ... = reg1051:10 + // BB2: + // reg1051:9 = + // LiveIntervalAnalysis won't like it. + // + // If the REG_SEQUENCE doesn't kill its source, keeping live variables + // correctly up to date becomes very difficult. Insert a copy. + + // Defer any kill flag to the last operand using SrcReg. Otherwise, we + // might insert a COPY that uses SrcReg after is was killed. + if (isKill) + for (unsigned j = i + 2; j < e; j += 2) + if (MI->getOperand(j).getReg() == SrcReg) { + MI->getOperand(j).setIsKill(); + isKill = false; + break; + } + + MachineBasicBlock::iterator InsertLoc = MI; + MachineInstr *CopyMI = BuildMI(*MI->getParent(), InsertLoc, + MI->getDebugLoc(), TII->get(TargetOpcode::COPY)) + .addReg(DstReg, RegState::Define, SubIdx) + .addReg(SrcReg, getKillRegState(isKill)); + MI->getOperand(i).setReg(0); + if (LV && isKill) + LV->replaceKillInstruction(SrcReg, MI, CopyMI); + DEBUG(dbgs() << "Inserted: " << *CopyMI); + } + } + + for (unsigned i = 1, e = MI->getNumOperands(); i < e; i += 2) { + unsigned SrcReg = MI->getOperand(i).getReg(); + if (!SrcReg) continue; + unsigned SubIdx = MI->getOperand(i+1).getImm(); + UpdateRegSequenceSrcs(SrcReg, DstReg, SubIdx, MRI, *TRI); + } + + if (IsImpDef) { + DEBUG(dbgs() << "Turned: " << *MI << " into an IMPLICIT_DEF"); + MI->setDesc(TII->get(TargetOpcode::IMPLICIT_DEF)); + for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j) + MI->RemoveOperand(j); + } else { + DEBUG(dbgs() << "Eliminated: " << *MI); + MI->eraseFromParent(); + } + + // Try coalescing some EXTRACT_SUBREG instructions. This can create + // INSERT_SUBREG instructions that must have flags added by + // LiveIntervalAnalysis, so only run it when LiveVariables is available. + if (LV) + CoalesceExtSubRegs(RealSrcs, DstReg); + } + + RegSequences.clear(); + return true; +} diff --git a/final/lib/CodeGen/UnreachableBlockElim.cpp b/final/lib/CodeGen/UnreachableBlockElim.cpp new file mode 100644 index 00000000000..48d8ab1658d --- /dev/null +++ b/final/lib/CodeGen/UnreachableBlockElim.cpp @@ -0,0 +1,212 @@ +//===-- UnreachableBlockElim.cpp - Remove unreachable blocks for codegen --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is an extremely simple version of the SimplifyCFG pass. Its sole +// job is to delete LLVM basic blocks that are not reachable from the entry +// node. To do this, it performs a simple depth first traversal of the CFG, +// then deletes any unvisited nodes. +// +// Note that this pass is really a hack. In particular, the instruction +// selectors for various targets should just not generate code for unreachable +// blocks. Until LLVM has a more systematic way of defining instruction +// selectors, however, we cannot really expect them to handle additional +// complexity. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Constant.h" +#include "llvm/Instructions.h" +#include "llvm/Function.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Analysis/ProfileInfo.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CFG.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallPtrSet.h" +using namespace llvm; + +namespace { + class UnreachableBlockElim : public FunctionPass { + virtual bool runOnFunction(Function &F); + public: + static char ID; // Pass identification, replacement for typeid + UnreachableBlockElim() : FunctionPass(ID) { + initializeUnreachableBlockElimPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + } + }; +} +char UnreachableBlockElim::ID = 0; +INITIALIZE_PASS(UnreachableBlockElim, "unreachableblockelim", + "Remove unreachable blocks from the CFG", false, false) + +FunctionPass *llvm::createUnreachableBlockEliminationPass() { + return new UnreachableBlockElim(); +} + +bool UnreachableBlockElim::runOnFunction(Function &F) { + SmallPtrSet Reachable; + + // Mark all reachable blocks. + for (df_ext_iterator > I = + df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); I != E; ++I) + /* Mark all reachable blocks */; + + // Loop over all dead blocks, remembering them and deleting all instructions + // in them. + std::vector DeadBlocks; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + if (!Reachable.count(I)) { + BasicBlock *BB = I; + DeadBlocks.push_back(BB); + while (PHINode *PN = dyn_cast(BB->begin())) { + PN->replaceAllUsesWith(Constant::getNullValue(PN->getType())); + BB->getInstList().pop_front(); + } + for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI) + (*SI)->removePredecessor(BB); + BB->dropAllReferences(); + } + + // Actually remove the blocks now. + ProfileInfo *PI = getAnalysisIfAvailable(); + for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) { + if (PI) PI->removeBlock(DeadBlocks[i]); + DeadBlocks[i]->eraseFromParent(); + } + + return DeadBlocks.size(); +} + + +namespace { + class UnreachableMachineBlockElim : public MachineFunctionPass { + virtual bool runOnMachineFunction(MachineFunction &F); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + MachineModuleInfo *MMI; + public: + static char ID; // Pass identification, replacement for typeid + UnreachableMachineBlockElim() : MachineFunctionPass(ID) {} + }; +} +char UnreachableMachineBlockElim::ID = 0; + +INITIALIZE_PASS(UnreachableMachineBlockElim, "unreachable-mbb-elimination", + "Remove unreachable machine basic blocks", false, false) + +char &llvm::UnreachableMachineBlockElimID = UnreachableMachineBlockElim::ID; + +void UnreachableMachineBlockElim::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); + AU.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool UnreachableMachineBlockElim::runOnMachineFunction(MachineFunction &F) { + SmallPtrSet Reachable; + bool ModifiedPHI = false; + + MMI = getAnalysisIfAvailable(); + MachineDominatorTree *MDT = getAnalysisIfAvailable(); + MachineLoopInfo *MLI = getAnalysisIfAvailable(); + + // Mark all reachable blocks. + for (df_ext_iterator > + I = df_ext_begin(&F, Reachable), E = df_ext_end(&F, Reachable); + I != E; ++I) + /* Mark all reachable blocks */; + + // Loop over all dead blocks, remembering them and deleting all instructions + // in them. + std::vector DeadBlocks; + for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { + MachineBasicBlock *BB = I; + + // Test for deadness. + if (!Reachable.count(BB)) { + DeadBlocks.push_back(BB); + + // Update dominator and loop info. + if (MLI) MLI->removeBlock(BB); + if (MDT && MDT->getNode(BB)) MDT->eraseNode(BB); + + while (BB->succ_begin() != BB->succ_end()) { + MachineBasicBlock* succ = *BB->succ_begin(); + + MachineBasicBlock::iterator start = succ->begin(); + while (start != succ->end() && start->isPHI()) { + for (unsigned i = start->getNumOperands() - 1; i >= 2; i-=2) + if (start->getOperand(i).isMBB() && + start->getOperand(i).getMBB() == BB) { + start->RemoveOperand(i); + start->RemoveOperand(i-1); + } + + start++; + } + + BB->removeSuccessor(BB->succ_begin()); + } + } + } + + // Actually remove the blocks now. + for (unsigned i = 0, e = DeadBlocks.size(); i != e; ++i) + DeadBlocks[i]->eraseFromParent(); + + // Cleanup PHI nodes. + for (MachineFunction::iterator I = F.begin(), E = F.end(); I != E; ++I) { + MachineBasicBlock *BB = I; + // Prune unneeded PHI entries. + SmallPtrSet preds(BB->pred_begin(), + BB->pred_end()); + MachineBasicBlock::iterator phi = BB->begin(); + while (phi != BB->end() && phi->isPHI()) { + for (unsigned i = phi->getNumOperands() - 1; i >= 2; i-=2) + if (!preds.count(phi->getOperand(i).getMBB())) { + phi->RemoveOperand(i); + phi->RemoveOperand(i-1); + ModifiedPHI = true; + } + + if (phi->getNumOperands() == 3) { + unsigned Input = phi->getOperand(1).getReg(); + unsigned Output = phi->getOperand(0).getReg(); + + MachineInstr* temp = phi; + ++phi; + temp->eraseFromParent(); + ModifiedPHI = true; + + if (Input != Output) + F.getRegInfo().replaceRegWith(Output, Input); + + continue; + } + + ++phi; + } + } + + F.RenumberBlocks(); + + return (DeadBlocks.size() || ModifiedPHI); +} diff --git a/final/lib/CodeGen/VirtRegMap.cpp b/final/lib/CodeGen/VirtRegMap.cpp new file mode 100644 index 00000000000..734b87e62f6 --- /dev/null +++ b/final/lib/CodeGen/VirtRegMap.cpp @@ -0,0 +1,354 @@ +//===-- llvm/CodeGen/VirtRegMap.cpp - Virtual Register Map ----------------===// +// +// 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 VirtRegMap class. +// +// It also contains implementations of the Spiller interface, which, given a +// virtual register map and a machine function, eliminates all virtual +// references by replacing them with physical register references - adding spill +// code as necessary. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "virtregmap" +#include "VirtRegMap.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" +#include +using namespace llvm; + +STATISTIC(NumSpills , "Number of register spills"); + +//===----------------------------------------------------------------------===// +// VirtRegMap implementation +//===----------------------------------------------------------------------===// + +char VirtRegMap::ID = 0; + +INITIALIZE_PASS(VirtRegMap, "virtregmap", "Virtual Register Map", false, false) + +bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) { + MRI = &mf.getRegInfo(); + TII = mf.getTarget().getInstrInfo(); + TRI = mf.getTarget().getRegisterInfo(); + MF = &mf; + + ReMatId = MAX_STACK_SLOT+1; + LowSpillSlot = HighSpillSlot = NO_STACK_SLOT; + + Virt2PhysMap.clear(); + Virt2StackSlotMap.clear(); + Virt2ReMatIdMap.clear(); + Virt2SplitMap.clear(); + Virt2SplitKillMap.clear(); + ReMatMap.clear(); + ImplicitDefed.clear(); + SpillSlotToUsesMap.clear(); + MI2VirtMap.clear(); + SpillPt2VirtMap.clear(); + RestorePt2VirtMap.clear(); + EmergencySpillMap.clear(); + EmergencySpillSlots.clear(); + + SpillSlotToUsesMap.resize(8); + ImplicitDefed.resize(MF->getRegInfo().getNumVirtRegs()); + + allocatableRCRegs.clear(); + for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), + E = TRI->regclass_end(); I != E; ++I) + allocatableRCRegs.insert(std::make_pair(*I, + TRI->getAllocatableSet(mf, *I))); + + grow(); + + return false; +} + +void VirtRegMap::grow() { + unsigned NumRegs = MF->getRegInfo().getNumVirtRegs(); + Virt2PhysMap.resize(NumRegs); + Virt2StackSlotMap.resize(NumRegs); + Virt2ReMatIdMap.resize(NumRegs); + Virt2SplitMap.resize(NumRegs); + Virt2SplitKillMap.resize(NumRegs); + ReMatMap.resize(NumRegs); + ImplicitDefed.resize(NumRegs); +} + +unsigned VirtRegMap::createSpillSlot(const TargetRegisterClass *RC) { + int SS = MF->getFrameInfo()->CreateSpillStackObject(RC->getSize(), + RC->getAlignment()); + if (LowSpillSlot == NO_STACK_SLOT) + LowSpillSlot = SS; + if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot) + HighSpillSlot = SS; + assert(SS >= LowSpillSlot && "Unexpected low spill slot"); + unsigned Idx = SS-LowSpillSlot; + while (Idx >= SpillSlotToUsesMap.size()) + SpillSlotToUsesMap.resize(SpillSlotToUsesMap.size()*2); + return SS; +} + +unsigned VirtRegMap::getRegAllocPref(unsigned virtReg) { + std::pair Hint = MRI->getRegAllocationHint(virtReg); + unsigned physReg = Hint.second; + if (TargetRegisterInfo::isVirtualRegister(physReg) && hasPhys(physReg)) + physReg = getPhys(physReg); + if (Hint.first == 0) + return (TargetRegisterInfo::isPhysicalRegister(physReg)) + ? physReg : 0; + return TRI->ResolveRegAllocHint(Hint.first, physReg, *MF); +} + +int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && + "attempt to assign stack slot to already spilled register"); + const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(virtReg); + ++NumSpills; + return Virt2StackSlotMap[virtReg] = createSpillSlot(RC); +} + +void VirtRegMap::assignVirt2StackSlot(unsigned virtReg, int SS) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT && + "attempt to assign stack slot to already spilled register"); + assert((SS >= 0 || + (SS >= MF->getFrameInfo()->getObjectIndexBegin())) && + "illegal fixed frame index"); + Virt2StackSlotMap[virtReg] = SS; +} + +int VirtRegMap::assignVirtReMatId(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2ReMatIdMap[virtReg] == NO_STACK_SLOT && + "attempt to assign re-mat id to already spilled register"); + Virt2ReMatIdMap[virtReg] = ReMatId; + return ReMatId++; +} + +void VirtRegMap::assignVirtReMatId(unsigned virtReg, int id) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2ReMatIdMap[virtReg] == NO_STACK_SLOT && + "attempt to assign re-mat id to already spilled register"); + Virt2ReMatIdMap[virtReg] = id; +} + +int VirtRegMap::getEmergencySpillSlot(const TargetRegisterClass *RC) { + std::map::iterator I = + EmergencySpillSlots.find(RC); + if (I != EmergencySpillSlots.end()) + return I->second; + return EmergencySpillSlots[RC] = createSpillSlot(RC); +} + +void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) { + if (!MF->getFrameInfo()->isFixedObjectIndex(FI)) { + // If FI < LowSpillSlot, this stack reference was produced by + // instruction selection and is not a spill + if (FI >= LowSpillSlot) { + assert(FI >= 0 && "Spill slot index should not be negative!"); + assert((unsigned)FI-LowSpillSlot < SpillSlotToUsesMap.size() + && "Invalid spill slot"); + SpillSlotToUsesMap[FI-LowSpillSlot].insert(MI); + } + } +} + +void VirtRegMap::virtFolded(unsigned VirtReg, MachineInstr *OldMI, + MachineInstr *NewMI, ModRef MRInfo) { + // Move previous memory references folded to new instruction. + MI2VirtMapTy::iterator IP = MI2VirtMap.lower_bound(NewMI); + for (MI2VirtMapTy::iterator I = MI2VirtMap.lower_bound(OldMI), + E = MI2VirtMap.end(); I != E && I->first == OldMI; ) { + MI2VirtMap.insert(IP, std::make_pair(NewMI, I->second)); + MI2VirtMap.erase(I++); + } + + // add new memory reference + MI2VirtMap.insert(IP, std::make_pair(NewMI, std::make_pair(VirtReg, MRInfo))); +} + +void VirtRegMap::virtFolded(unsigned VirtReg, MachineInstr *MI, ModRef MRInfo) { + MI2VirtMapTy::iterator IP = MI2VirtMap.lower_bound(MI); + MI2VirtMap.insert(IP, std::make_pair(MI, std::make_pair(VirtReg, MRInfo))); +} + +void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isFI()) + continue; + int FI = MO.getIndex(); + if (MF->getFrameInfo()->isFixedObjectIndex(FI)) + continue; + // This stack reference was produced by instruction selection and + // is not a spill + if (FI < LowSpillSlot) + continue; + assert((unsigned)FI-LowSpillSlot < SpillSlotToUsesMap.size() + && "Invalid spill slot"); + SpillSlotToUsesMap[FI-LowSpillSlot].erase(MI); + } + MI2VirtMap.erase(MI); + SpillPt2VirtMap.erase(MI); + RestorePt2VirtMap.erase(MI); + EmergencySpillMap.erase(MI); +} + +/// FindUnusedRegisters - Gather a list of allocatable registers that +/// have not been allocated to any virtual register. +bool VirtRegMap::FindUnusedRegisters(LiveIntervals* LIs) { + unsigned NumRegs = TRI->getNumRegs(); + UnusedRegs.reset(); + UnusedRegs.resize(NumRegs); + + BitVector Used(NumRegs); + for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + if (Virt2PhysMap[Reg] != (unsigned)VirtRegMap::NO_PHYS_REG) + Used.set(Virt2PhysMap[Reg]); + } + + BitVector Allocatable = TRI->getAllocatableSet(*MF); + bool AnyUnused = false; + for (unsigned Reg = 1; Reg < NumRegs; ++Reg) { + if (Allocatable[Reg] && !Used[Reg] && !LIs->hasInterval(Reg)) { + bool ReallyUnused = true; + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + if (Used[*AS] || LIs->hasInterval(*AS)) { + ReallyUnused = false; + break; + } + } + if (ReallyUnused) { + AnyUnused = true; + UnusedRegs.set(Reg); + } + } + } + + return AnyUnused; +} + +void VirtRegMap::rewrite(SlotIndexes *Indexes) { + DEBUG(dbgs() << "********** REWRITE VIRTUAL REGISTERS **********\n" + << "********** Function: " + << MF->getFunction()->getName() << '\n'); + + SmallVector SuperKills; + + for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); + MBBI != MBBE; ++MBBI) { + DEBUG(MBBI->print(dbgs(), Indexes)); + for (MachineBasicBlock::iterator MII = MBBI->begin(), MIE = MBBI->end(); + MII != MIE;) { + MachineInstr *MI = MII; + ++MII; + + for (MachineInstr::mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + MachineOperand &MO = *MOI; + if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg())) + continue; + unsigned VirtReg = MO.getReg(); + unsigned PhysReg = getPhys(VirtReg); + assert(PhysReg != NO_PHYS_REG && "Instruction uses unmapped VirtReg"); + + // Preserve semantics of sub-register operands. + if (MO.getSubReg()) { + // A virtual register kill refers to the whole register, so we may + // have to add operands for the super-register. + if (MO.isUse() && MO.isKill() && !MO.isUndef()) + SuperKills.push_back(PhysReg); + + // We don't have to deal with sub-register defs because + // LiveIntervalAnalysis already added the necessary + // operands. + + // PhysReg operands cannot have subregister indexes. + PhysReg = TRI->getSubReg(PhysReg, MO.getSubReg()); + assert(PhysReg && "Invalid SubReg for physical register"); + MO.setSubReg(0); + } + // Rewrite. Note we could have used MachineOperand::substPhysReg(), but + // we need the inlining here. + MO.setReg(PhysReg); + } + + // Add any missing super-register kills after rewriting the whole + // instruction. + while (!SuperKills.empty()) + MI->addRegisterKilled(SuperKills.pop_back_val(), TRI, true); + + DEBUG(dbgs() << "> " << *MI); + + // Finally, remove any identity copies. + if (MI->isIdentityCopy()) { + DEBUG(dbgs() << "Deleting identity copy.\n"); + RemoveMachineInstrFromMaps(MI); + if (Indexes) + Indexes->removeMachineInstrFromMaps(MI); + // It's safe to erase MI because MII has already been incremented. + MI->eraseFromParent(); + } + } + } + + // Tell MRI about physical registers in use. + for (unsigned Reg = 1, RegE = TRI->getNumRegs(); Reg != RegE; ++Reg) + if (!MRI->reg_nodbg_empty(Reg)) + MRI->setPhysRegUsed(Reg); +} + +void VirtRegMap::print(raw_ostream &OS, const Module* M) const { + const TargetRegisterInfo* TRI = MF->getTarget().getRegisterInfo(); + const MachineRegisterInfo &MRI = MF->getRegInfo(); + + OS << "********** REGISTER MAP **********\n"; + for (unsigned i = 0, e = MRI.getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + if (Virt2PhysMap[Reg] != (unsigned)VirtRegMap::NO_PHYS_REG) { + OS << '[' << PrintReg(Reg, TRI) << " -> " + << PrintReg(Virt2PhysMap[Reg], TRI) << "] " + << MRI.getRegClass(Reg)->getName() << "\n"; + } + } + + for (unsigned i = 0, e = MRI.getNumVirtRegs(); i != e; ++i) { + unsigned Reg = TargetRegisterInfo::index2VirtReg(i); + if (Virt2StackSlotMap[Reg] != VirtRegMap::NO_STACK_SLOT) { + OS << '[' << PrintReg(Reg, TRI) << " -> fi#" << Virt2StackSlotMap[Reg] + << "] " << MRI.getRegClass(Reg)->getName() << "\n"; + } + } + OS << '\n'; +} + +void VirtRegMap::dump() const { + print(dbgs()); +} diff --git a/final/lib/CodeGen/VirtRegMap.h b/final/lib/CodeGen/VirtRegMap.h new file mode 100644 index 00000000000..ba50f4e4230 --- /dev/null +++ b/final/lib/CodeGen/VirtRegMap.h @@ -0,0 +1,523 @@ +//===-- llvm/CodeGen/VirtRegMap.h - Virtual Register Map -*- C++ -*--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a virtual register map. This maps virtual registers to +// physical registers and virtual registers to stack slots. It is created and +// updated by a register allocator and then used by a machine code rewriter that +// adds spill code and rewrites virtual into physical register references. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VIRTREGMAP_H +#define LLVM_CODEGEN_VIRTREGMAP_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + class LiveIntervals; + class MachineInstr; + class MachineFunction; + class MachineRegisterInfo; + class TargetInstrInfo; + class TargetRegisterInfo; + class raw_ostream; + class SlotIndexes; + + class VirtRegMap : public MachineFunctionPass { + public: + enum { + NO_PHYS_REG = 0, + NO_STACK_SLOT = (1L << 30)-1, + MAX_STACK_SLOT = (1L << 18)-1 + }; + + enum ModRef { isRef = 1, isMod = 2, isModRef = 3 }; + typedef std::multimap > MI2VirtMapTy; + + private: + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineFunction *MF; + + DenseMap allocatableRCRegs; + + /// Virt2PhysMap - This is a virtual to physical register + /// mapping. Each virtual register is required to have an entry in + /// it; even spilled virtual registers (the register mapped to a + /// spilled register is the temporary used to load it from the + /// stack). + IndexedMap Virt2PhysMap; + + /// Virt2StackSlotMap - This is virtual register to stack slot + /// mapping. Each spilled virtual register has an entry in it + /// which corresponds to the stack slot this register is spilled + /// at. + IndexedMap Virt2StackSlotMap; + + /// Virt2ReMatIdMap - This is virtual register to rematerialization id + /// mapping. Each spilled virtual register that should be remat'd has an + /// entry in it which corresponds to the remat id. + IndexedMap Virt2ReMatIdMap; + + /// Virt2SplitMap - This is virtual register to splitted virtual register + /// mapping. + IndexedMap Virt2SplitMap; + + /// Virt2SplitKillMap - This is splitted virtual register to its last use + /// (kill) index mapping. + IndexedMap Virt2SplitKillMap; + + /// ReMatMap - This is virtual register to re-materialized instruction + /// mapping. Each virtual register whose definition is going to be + /// re-materialized has an entry in it. + IndexedMap ReMatMap; + + /// MI2VirtMap - This is MachineInstr to virtual register + /// mapping. In the case of memory spill code being folded into + /// instructions, we need to know which virtual register was + /// read/written by this instruction. + MI2VirtMapTy MI2VirtMap; + + /// SpillPt2VirtMap - This records the virtual registers which should + /// be spilled right after the MachineInstr due to live interval + /// splitting. + std::map > > + SpillPt2VirtMap; + + /// RestorePt2VirtMap - This records the virtual registers which should + /// be restored right before the MachineInstr due to live interval + /// splitting. + std::map > RestorePt2VirtMap; + + /// EmergencySpillMap - This records the physical registers that should + /// be spilled / restored around the MachineInstr since the register + /// allocator has run out of registers. + std::map > EmergencySpillMap; + + /// EmergencySpillSlots - This records emergency spill slots used to + /// spill physical registers when the register allocator runs out of + /// registers. Ideally only one stack slot is used per function per + /// register class. + std::map EmergencySpillSlots; + + /// ReMatId - Instead of assigning a stack slot to a to be rematerialized + /// virtual register, an unique id is being assigned. This keeps track of + /// the highest id used so far. Note, this starts at (1<<18) to avoid + /// conflicts with stack slot numbers. + int ReMatId; + + /// LowSpillSlot, HighSpillSlot - Lowest and highest spill slot indexes. + int LowSpillSlot, HighSpillSlot; + + /// SpillSlotToUsesMap - Records uses for each register spill slot. + SmallVector, 8> SpillSlotToUsesMap; + + /// ImplicitDefed - One bit for each virtual register. If set it indicates + /// the register is implicitly defined. + BitVector ImplicitDefed; + + /// UnusedRegs - A list of physical registers that have not been used. + BitVector UnusedRegs; + + /// createSpillSlot - Allocate a spill slot for RC from MFI. + unsigned createSpillSlot(const TargetRegisterClass *RC); + + VirtRegMap(const VirtRegMap&); // DO NOT IMPLEMENT + void operator=(const VirtRegMap&); // DO NOT IMPLEMENT + + public: + static char ID; + VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), + Virt2StackSlotMap(NO_STACK_SLOT), + Virt2ReMatIdMap(NO_STACK_SLOT), Virt2SplitMap(0), + Virt2SplitKillMap(SlotIndex()), ReMatMap(NULL), + ReMatId(MAX_STACK_SLOT+1), + LowSpillSlot(NO_STACK_SLOT), HighSpillSlot(NO_STACK_SLOT) { } + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + MachineFunction &getMachineFunction() const { + assert(MF && "getMachineFunction called before runOnMachineFunction"); + return *MF; + } + + MachineRegisterInfo &getRegInfo() const { return *MRI; } + const TargetRegisterInfo &getTargetRegInfo() const { return *TRI; } + + void grow(); + + /// @brief returns true if the specified virtual register is + /// mapped to a physical register + bool hasPhys(unsigned virtReg) const { + return getPhys(virtReg) != NO_PHYS_REG; + } + + /// @brief returns the physical register mapped to the specified + /// virtual register + unsigned getPhys(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2PhysMap[virtReg]; + } + + /// @brief creates a mapping for the specified virtual register to + /// the specified physical register + void assignVirt2Phys(unsigned virtReg, unsigned physReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg) && + TargetRegisterInfo::isPhysicalRegister(physReg)); + assert(Virt2PhysMap[virtReg] == NO_PHYS_REG && + "attempt to assign physical register to already mapped " + "virtual register"); + Virt2PhysMap[virtReg] = physReg; + } + + /// @brief clears the specified virtual register's, physical + /// register mapping + void clearVirt(unsigned virtReg) { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + assert(Virt2PhysMap[virtReg] != NO_PHYS_REG && + "attempt to clear a not assigned virtual register"); + Virt2PhysMap[virtReg] = NO_PHYS_REG; + } + + /// @brief clears all virtual to physical register mappings + void clearAllVirt() { + Virt2PhysMap.clear(); + grow(); + } + + /// @brief returns the register allocation preference. + unsigned getRegAllocPref(unsigned virtReg); + + /// @brief records virtReg is a split live interval from SReg. + void setIsSplitFromReg(unsigned virtReg, unsigned SReg) { + Virt2SplitMap[virtReg] = SReg; + } + + /// @brief returns the live interval virtReg is split from. + unsigned getPreSplitReg(unsigned virtReg) const { + return Virt2SplitMap[virtReg]; + } + + /// getOriginal - Return the original virtual register that VirtReg descends + /// from through splitting. + /// A register that was not created by splitting is its own original. + /// This operation is idempotent. + unsigned getOriginal(unsigned VirtReg) const { + unsigned Orig = getPreSplitReg(VirtReg); + return Orig ? Orig : VirtReg; + } + + /// @brief returns true if the specified virtual register is not + /// mapped to a stack slot or rematerialized. + bool isAssignedReg(unsigned virtReg) const { + if (getStackSlot(virtReg) == NO_STACK_SLOT && + getReMatId(virtReg) == NO_STACK_SLOT) + return true; + // Split register can be assigned a physical register as well as a + // stack slot or remat id. + return (Virt2SplitMap[virtReg] && Virt2PhysMap[virtReg] != NO_PHYS_REG); + } + + /// @brief returns the stack slot mapped to the specified virtual + /// register + int getStackSlot(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2StackSlotMap[virtReg]; + } + + /// @brief returns the rematerialization id mapped to the specified virtual + /// register + int getReMatId(unsigned virtReg) const { + assert(TargetRegisterInfo::isVirtualRegister(virtReg)); + return Virt2ReMatIdMap[virtReg]; + } + + /// @brief create a mapping for the specifed virtual register to + /// the next available stack slot + int assignVirt2StackSlot(unsigned virtReg); + /// @brief create a mapping for the specified virtual register to + /// the specified stack slot + void assignVirt2StackSlot(unsigned virtReg, int frameIndex); + + /// @brief assign an unique re-materialization id to the specified + /// virtual register. + int assignVirtReMatId(unsigned virtReg); + /// @brief assign an unique re-materialization id to the specified + /// virtual register. + void assignVirtReMatId(unsigned virtReg, int id); + + /// @brief returns true if the specified virtual register is being + /// re-materialized. + bool isReMaterialized(unsigned virtReg) const { + return ReMatMap[virtReg] != NULL; + } + + /// @brief returns the original machine instruction being re-issued + /// to re-materialize the specified virtual register. + MachineInstr *getReMaterializedMI(unsigned virtReg) const { + return ReMatMap[virtReg]; + } + + /// @brief records the specified virtual register will be + /// re-materialized and the original instruction which will be re-issed + /// for this purpose. If parameter all is true, then all uses of the + /// registers are rematerialized and it's safe to delete the definition. + void setVirtIsReMaterialized(unsigned virtReg, MachineInstr *def) { + ReMatMap[virtReg] = def; + } + + /// @brief record the last use (kill) of a split virtual register. + void addKillPoint(unsigned virtReg, SlotIndex index) { + Virt2SplitKillMap[virtReg] = index; + } + + SlotIndex getKillPoint(unsigned virtReg) const { + return Virt2SplitKillMap[virtReg]; + } + + /// @brief remove the last use (kill) of a split virtual register. + void removeKillPoint(unsigned virtReg) { + Virt2SplitKillMap[virtReg] = SlotIndex(); + } + + /// @brief returns true if the specified MachineInstr is a spill point. + bool isSpillPt(MachineInstr *Pt) const { + return SpillPt2VirtMap.find(Pt) != SpillPt2VirtMap.end(); + } + + /// @brief returns the virtual registers that should be spilled due to + /// splitting right after the specified MachineInstr. + std::vector > &getSpillPtSpills(MachineInstr *Pt) { + return SpillPt2VirtMap[Pt]; + } + + /// @brief records the specified MachineInstr as a spill point for virtReg. + void addSpillPoint(unsigned virtReg, bool isKill, MachineInstr *Pt) { + std::map > >::iterator + I = SpillPt2VirtMap.find(Pt); + if (I != SpillPt2VirtMap.end()) + I->second.push_back(std::make_pair(virtReg, isKill)); + else { + std::vector > Virts; + Virts.push_back(std::make_pair(virtReg, isKill)); + SpillPt2VirtMap.insert(std::make_pair(Pt, Virts)); + } + } + + /// @brief - transfer spill point information from one instruction to + /// another. + void transferSpillPts(MachineInstr *Old, MachineInstr *New) { + std::map > >::iterator + I = SpillPt2VirtMap.find(Old); + if (I == SpillPt2VirtMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back().first; + bool isKill = I->second.back().second; + I->second.pop_back(); + addSpillPoint(virtReg, isKill, New); + } + SpillPt2VirtMap.erase(I); + } + + /// @brief returns true if the specified MachineInstr is a restore point. + bool isRestorePt(MachineInstr *Pt) const { + return RestorePt2VirtMap.find(Pt) != RestorePt2VirtMap.end(); + } + + /// @brief returns the virtual registers that should be restoreed due to + /// splitting right after the specified MachineInstr. + std::vector &getRestorePtRestores(MachineInstr *Pt) { + return RestorePt2VirtMap[Pt]; + } + + /// @brief records the specified MachineInstr as a restore point for virtReg. + void addRestorePoint(unsigned virtReg, MachineInstr *Pt) { + std::map >::iterator I = + RestorePt2VirtMap.find(Pt); + if (I != RestorePt2VirtMap.end()) + I->second.push_back(virtReg); + else { + std::vector Virts; + Virts.push_back(virtReg); + RestorePt2VirtMap.insert(std::make_pair(Pt, Virts)); + } + } + + /// @brief - transfer restore point information from one instruction to + /// another. + void transferRestorePts(MachineInstr *Old, MachineInstr *New) { + std::map >::iterator I = + RestorePt2VirtMap.find(Old); + if (I == RestorePt2VirtMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back(); + I->second.pop_back(); + addRestorePoint(virtReg, New); + } + RestorePt2VirtMap.erase(I); + } + + /// @brief records that the specified physical register must be spilled + /// around the specified machine instr. + void addEmergencySpill(unsigned PhysReg, MachineInstr *MI) { + if (EmergencySpillMap.find(MI) != EmergencySpillMap.end()) + EmergencySpillMap[MI].push_back(PhysReg); + else { + std::vector PhysRegs; + PhysRegs.push_back(PhysReg); + EmergencySpillMap.insert(std::make_pair(MI, PhysRegs)); + } + } + + /// @brief returns true if one or more physical registers must be spilled + /// around the specified instruction. + bool hasEmergencySpills(MachineInstr *MI) const { + return EmergencySpillMap.find(MI) != EmergencySpillMap.end(); + } + + /// @brief returns the physical registers to be spilled and restored around + /// the instruction. + std::vector &getEmergencySpills(MachineInstr *MI) { + return EmergencySpillMap[MI]; + } + + /// @brief - transfer emergency spill information from one instruction to + /// another. + void transferEmergencySpills(MachineInstr *Old, MachineInstr *New) { + std::map >::iterator I = + EmergencySpillMap.find(Old); + if (I == EmergencySpillMap.end()) + return; + while (!I->second.empty()) { + unsigned virtReg = I->second.back(); + I->second.pop_back(); + addEmergencySpill(virtReg, New); + } + EmergencySpillMap.erase(I); + } + + /// @brief return or get a emergency spill slot for the register class. + int getEmergencySpillSlot(const TargetRegisterClass *RC); + + /// @brief Return lowest spill slot index. + int getLowSpillSlot() const { + return LowSpillSlot; + } + + /// @brief Return highest spill slot index. + int getHighSpillSlot() const { + return HighSpillSlot; + } + + /// @brief Records a spill slot use. + void addSpillSlotUse(int FrameIndex, MachineInstr *MI); + + /// @brief Returns true if spill slot has been used. + bool isSpillSlotUsed(int FrameIndex) const { + assert(FrameIndex >= 0 && "Spill slot index should not be negative!"); + return !SpillSlotToUsesMap[FrameIndex-LowSpillSlot].empty(); + } + + /// @brief Mark the specified register as being implicitly defined. + void setIsImplicitlyDefined(unsigned VirtReg) { + ImplicitDefed.set(TargetRegisterInfo::virtReg2Index(VirtReg)); + } + + /// @brief Returns true if the virtual register is implicitly defined. + bool isImplicitlyDefined(unsigned VirtReg) const { + return ImplicitDefed[TargetRegisterInfo::virtReg2Index(VirtReg)]; + } + + /// @brief Updates information about the specified virtual register's value + /// folded into newMI machine instruction. + void virtFolded(unsigned VirtReg, MachineInstr *OldMI, MachineInstr *NewMI, + ModRef MRInfo); + + /// @brief Updates information about the specified virtual register's value + /// folded into the specified machine instruction. + void virtFolded(unsigned VirtReg, MachineInstr *MI, ModRef MRInfo); + + /// @brief returns the virtual registers' values folded in memory + /// operands of this instruction + std::pair + getFoldedVirts(MachineInstr* MI) const { + return MI2VirtMap.equal_range(MI); + } + + /// RemoveMachineInstrFromMaps - MI is being erased, remove it from the + /// the folded instruction map and spill point map. + void RemoveMachineInstrFromMaps(MachineInstr *MI); + + /// FindUnusedRegisters - Gather a list of allocatable registers that + /// have not been allocated to any virtual register. + bool FindUnusedRegisters(LiveIntervals* LIs); + + /// HasUnusedRegisters - Return true if there are any allocatable registers + /// that have not been allocated to any virtual register. + bool HasUnusedRegisters() const { + return !UnusedRegs.none(); + } + + /// setRegisterUsed - Remember the physical register is now used. + void setRegisterUsed(unsigned Reg) { + UnusedRegs.reset(Reg); + } + + /// isRegisterUnused - Return true if the physical register has not been + /// used. + bool isRegisterUnused(unsigned Reg) const { + return UnusedRegs[Reg]; + } + + /// getFirstUnusedRegister - Return the first physical register that has not + /// been used. + unsigned getFirstUnusedRegister(const TargetRegisterClass *RC) { + int Reg = UnusedRegs.find_first(); + while (Reg != -1) { + if (allocatableRCRegs[RC][Reg]) + return (unsigned)Reg; + Reg = UnusedRegs.find_next(Reg); + } + return 0; + } + + /// rewrite - Rewrite all instructions in MF to use only physical registers + /// by mapping all virtual register operands to their assigned physical + /// registers. + /// + /// @param Indexes Optionally remove deleted instructions from indexes. + void rewrite(SlotIndexes *Indexes); + + void print(raw_ostream &OS, const Module* M = 0) const; + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const VirtRegMap &VRM) { + VRM.print(OS); + return OS; + } +} // End llvm namespace + +#endif diff --git a/final/lib/CodeGen/VirtRegRewriter.cpp b/final/lib/CodeGen/VirtRegRewriter.cpp new file mode 100644 index 00000000000..ec149dddc1d --- /dev/null +++ b/final/lib/CodeGen/VirtRegRewriter.cpp @@ -0,0 +1,2604 @@ +//===-- llvm/CodeGen/Rewriter.cpp - Rewriter -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "virtregrewriter" +#include "VirtRegRewriter.h" +#include "VirtRegMap.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumDSE , "Number of dead stores elided"); +STATISTIC(NumDSS , "Number of dead spill slots removed"); +STATISTIC(NumCommutes, "Number of instructions commuted"); +STATISTIC(NumDRM , "Number of re-materializable defs elided"); +STATISTIC(NumStores , "Number of stores added"); +STATISTIC(NumPSpills , "Number of physical register spills"); +STATISTIC(NumOmitted , "Number of reloads omited"); +STATISTIC(NumAvoided , "Number of reloads deemed unnecessary"); +STATISTIC(NumCopified, "Number of available reloads turned into copies"); +STATISTIC(NumReMats , "Number of re-materialization"); +STATISTIC(NumLoads , "Number of loads added"); +STATISTIC(NumReused , "Number of values reused"); +STATISTIC(NumDCE , "Number of copies elided"); +STATISTIC(NumSUnfold , "Number of stores unfolded"); +STATISTIC(NumModRefUnfold, "Number of modref unfolded"); + +namespace { + enum RewriterName { local, trivial }; +} + +static cl::opt +RewriterOpt("rewriter", + cl::desc("Rewriter to use (default=local)"), + cl::Prefix, + cl::values(clEnumVal(local, "local rewriter"), + clEnumVal(trivial, "trivial rewriter"), + clEnumValEnd), + cl::init(local)); + +static cl::opt +ScheduleSpills("schedule-spills", + cl::desc("Schedule spill code"), + cl::init(false)); + +VirtRegRewriter::~VirtRegRewriter() {} + +/// substitutePhysReg - Replace virtual register in MachineOperand with a +/// physical register. Do the right thing with the sub-register index. +/// Note that operands may be added, so the MO reference is no longer valid. +static void substitutePhysReg(MachineOperand &MO, unsigned Reg, + const TargetRegisterInfo &TRI) { + if (MO.getSubReg()) { + MO.substPhysReg(Reg, TRI); + + // Any kill flags apply to the full virtual register, so they also apply to + // the full physical register. + // We assume that partial defs have already been decorated with a super-reg + // operand by LiveIntervals. + MachineInstr &MI = *MO.getParent(); + if (MO.isUse() && !MO.isUndef() && + (MO.isKill() || MI.isRegTiedToDefOperand(&MO-&MI.getOperand(0)))) + MI.addRegisterKilled(Reg, &TRI, /*AddIfNotFound=*/ true); + } else { + MO.setReg(Reg); + } +} + +namespace { + +/// This class is intended for use with the new spilling framework only. It +/// rewrites vreg def/uses to use the assigned preg, but does not insert any +/// spill code. +struct TrivialRewriter : public VirtRegRewriter { + + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { + DEBUG(dbgs() << "********** REWRITE MACHINE CODE **********\n"); + DEBUG(dbgs() << "********** Function: " + << MF.getFunction()->getName() << '\n'); + DEBUG(dbgs() << "**** Machine Instrs" + << "(NOTE! Does not include spills and reloads!) ****\n"); + DEBUG(MF.dump()); + + MachineRegisterInfo *mri = &MF.getRegInfo(); + const TargetRegisterInfo *tri = MF.getTarget().getRegisterInfo(); + + bool changed = false; + + for (LiveIntervals::iterator liItr = LIs->begin(), liEnd = LIs->end(); + liItr != liEnd; ++liItr) { + + const LiveInterval *li = liItr->second; + unsigned reg = li->reg; + + if (TargetRegisterInfo::isPhysicalRegister(reg)) { + if (!li->empty()) + mri->setPhysRegUsed(reg); + } + else { + if (!VRM.hasPhys(reg)) + continue; + unsigned pReg = VRM.getPhys(reg); + mri->setPhysRegUsed(pReg); + // Copy the register use-list before traversing it. + SmallVector, 32> reglist; + for (MachineRegisterInfo::reg_iterator I = mri->reg_begin(reg), + E = mri->reg_end(); I != E; ++I) + reglist.push_back(std::make_pair(&*I, I.getOperandNo())); + for (unsigned N=0; N != reglist.size(); ++N) + substitutePhysReg(reglist[N].first->getOperand(reglist[N].second), + pReg, *tri); + changed |= !reglist.empty(); + } + } + + DEBUG(dbgs() << "**** Post Machine Instrs ****\n"); + DEBUG(MF.dump()); + + return changed; + } + +}; + +} + +// ************************************************************************ // + +namespace { + +/// AvailableSpills - As the local rewriter is scanning and rewriting an MBB +/// from top down, keep track of which spill slots or remat are available in +/// each register. +/// +/// Note that not all physregs are created equal here. In particular, some +/// physregs are reloads that we are allowed to clobber or ignore at any time. +/// Other physregs are values that the register allocated program is using +/// that we cannot CHANGE, but we can read if we like. We keep track of this +/// on a per-stack-slot / remat id basis as the low bit in the value of the +/// SpillSlotsAvailable entries. The predicate 'canClobberPhysReg()' checks +/// this bit and addAvailable sets it if. +class AvailableSpills { + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + + // SpillSlotsOrReMatsAvailable - This map keeps track of all of the spilled + // or remat'ed virtual register values that are still available, due to + // being loaded or stored to, but not invalidated yet. + std::map SpillSlotsOrReMatsAvailable; + + // PhysRegsAvailable - This is the inverse of SpillSlotsOrReMatsAvailable, + // indicating which stack slot values are currently held by a physreg. This + // is used to invalidate entries in SpillSlotsOrReMatsAvailable when a + // physreg is modified. + std::multimap PhysRegsAvailable; + + void disallowClobberPhysRegOnly(unsigned PhysReg); + + void ClobberPhysRegOnly(unsigned PhysReg); +public: + AvailableSpills(const TargetRegisterInfo *tri, const TargetInstrInfo *tii) + : TRI(tri), TII(tii) { + } + + /// clear - Reset the state. + void clear() { + SpillSlotsOrReMatsAvailable.clear(); + PhysRegsAvailable.clear(); + } + + const TargetRegisterInfo *getRegInfo() const { return TRI; } + + /// getSpillSlotOrReMatPhysReg - If the specified stack slot or remat is + /// available in a physical register, return that PhysReg, otherwise + /// return 0. + unsigned getSpillSlotOrReMatPhysReg(int Slot) const { + std::map::const_iterator I = + SpillSlotsOrReMatsAvailable.find(Slot); + if (I != SpillSlotsOrReMatsAvailable.end()) { + return I->second >> 1; // Remove the CanClobber bit. + } + return 0; + } + + /// addAvailable - Mark that the specified stack slot / remat is available + /// in the specified physreg. If CanClobber is true, the physreg can be + /// modified at any time without changing the semantics of the program. + void addAvailable(int SlotOrReMat, unsigned Reg, bool CanClobber = true) { + // If this stack slot is thought to be available in some other physreg, + // remove its record. + ModifyStackSlotOrReMat(SlotOrReMat); + + PhysRegsAvailable.insert(std::make_pair(Reg, SlotOrReMat)); + SpillSlotsOrReMatsAvailable[SlotOrReMat]= (Reg << 1) | + (unsigned)CanClobber; + + if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT) + DEBUG(dbgs() << "Remembering RM#" + << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(dbgs() << "Remembering SS#" << SlotOrReMat); + DEBUG(dbgs() << " in physreg " << TRI->getName(Reg) + << (CanClobber ? " canclobber" : "") << "\n"); + } + + /// canClobberPhysRegForSS - Return true if the spiller is allowed to change + /// the value of the specified stackslot register if it desires. The + /// specified stack slot must be available in a physreg for this query to + /// make sense. + bool canClobberPhysRegForSS(int SlotOrReMat) const { + assert(SpillSlotsOrReMatsAvailable.count(SlotOrReMat) && + "Value not available!"); + return SpillSlotsOrReMatsAvailable.find(SlotOrReMat)->second & 1; + } + + /// canClobberPhysReg - Return true if the spiller is allowed to clobber the + /// physical register where values for some stack slot(s) might be + /// available. + bool canClobberPhysReg(unsigned PhysReg) const { + std::multimap::const_iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + I++; + if (!canClobberPhysRegForSS(SlotOrReMat)) + return false; + } + return true; + } + + /// disallowClobberPhysReg - Unset the CanClobber bit of the specified + /// stackslot register. The register is still available but is no longer + /// allowed to be modifed. + void disallowClobberPhysReg(unsigned PhysReg); + + /// ClobberPhysReg - This is called when the specified physreg changes + /// value. We use this to invalidate any info about stuff that lives in + /// it and any of its aliases. + void ClobberPhysReg(unsigned PhysReg); + + /// ModifyStackSlotOrReMat - This method is called when the value in a stack + /// slot changes. This removes information about which register the + /// previous value for this slot lives in (as the previous value is dead + /// now). + void ModifyStackSlotOrReMat(int SlotOrReMat); + + /// AddAvailableRegsToLiveIn - Availability information is being kept coming + /// into the specified MBB. Add available physical registers as potential + /// live-in's. If they are reused in the MBB, they will be added to the + /// live-in set to make register scavenger and post-allocation scheduler. + void AddAvailableRegsToLiveIn(MachineBasicBlock &MBB, BitVector &RegKills, + std::vector &KillOps); +}; + +} + +// ************************************************************************ // + +// Given a location where a reload of a spilled register or a remat of +// a constant is to be inserted, attempt to find a safe location to +// insert the load at an earlier point in the basic-block, to hide +// latency of the load and to avoid address-generation interlock +// issues. +static MachineBasicBlock::iterator +ComputeReloadLoc(MachineBasicBlock::iterator const InsertLoc, + MachineBasicBlock::iterator const Begin, + unsigned PhysReg, + const TargetRegisterInfo *TRI, + bool DoReMat, + int SSorRMId, + const TargetInstrInfo *TII, + const MachineFunction &MF) +{ + if (!ScheduleSpills) + return InsertLoc; + + // Spill backscheduling is of primary interest to addresses, so + // don't do anything if the register isn't in the register class + // used for pointers. + + const TargetLowering *TL = MF.getTarget().getTargetLowering(); + + if (!TL->isTypeLegal(TL->getPointerTy())) + // Believe it or not, this is true on 16-bit targets like PIC16. + return InsertLoc; + + const TargetRegisterClass *ptrRegClass = + TL->getRegClassFor(TL->getPointerTy()); + if (!ptrRegClass->contains(PhysReg)) + return InsertLoc; + + // Scan upwards through the preceding instructions. If an instruction doesn't + // reference the stack slot or the register we're loading, we can + // backschedule the reload up past it. + MachineBasicBlock::iterator NewInsertLoc = InsertLoc; + while (NewInsertLoc != Begin) { + MachineBasicBlock::iterator Prev = prior(NewInsertLoc); + for (unsigned i = 0; i < Prev->getNumOperands(); ++i) { + MachineOperand &Op = Prev->getOperand(i); + if (!DoReMat && Op.isFI() && Op.getIndex() == SSorRMId) + goto stop; + } + if (Prev->findRegisterUseOperandIdx(PhysReg) != -1 || + Prev->findRegisterDefOperand(PhysReg)) + goto stop; + for (const unsigned *Alias = TRI->getAliasSet(PhysReg); *Alias; ++Alias) + if (Prev->findRegisterUseOperandIdx(*Alias) != -1 || + Prev->findRegisterDefOperand(*Alias)) + goto stop; + NewInsertLoc = Prev; + } +stop:; + + // If we made it to the beginning of the block, turn around and move back + // down just past any existing reloads. They're likely to be reloads/remats + // for instructions earlier than what our current reload/remat is for, so + // they should be scheduled earlier. + if (NewInsertLoc == Begin) { + int FrameIdx; + while (InsertLoc != NewInsertLoc && + (TII->isLoadFromStackSlot(NewInsertLoc, FrameIdx) || + TII->isTriviallyReMaterializable(NewInsertLoc))) + ++NewInsertLoc; + } + + return NewInsertLoc; +} + +namespace { + +// ReusedOp - For each reused operand, we keep track of a bit of information, +// in case we need to rollback upon processing a new operand. See comments +// below. +struct ReusedOp { + // The MachineInstr operand that reused an available value. + unsigned Operand; + + // StackSlotOrReMat - The spill slot or remat id of the value being reused. + unsigned StackSlotOrReMat; + + // PhysRegReused - The physical register the value was available in. + unsigned PhysRegReused; + + // AssignedPhysReg - The physreg that was assigned for use by the reload. + unsigned AssignedPhysReg; + + // VirtReg - The virtual register itself. + unsigned VirtReg; + + ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr, + unsigned vreg) + : Operand(o), StackSlotOrReMat(ss), PhysRegReused(prr), + AssignedPhysReg(apr), VirtReg(vreg) {} +}; + +/// ReuseInfo - This maintains a collection of ReuseOp's for each operand that +/// is reused instead of reloaded. +class ReuseInfo { + MachineInstr &MI; + std::vector Reuses; + BitVector PhysRegsClobbered; +public: + ReuseInfo(MachineInstr &mi, const TargetRegisterInfo *tri) : MI(mi) { + PhysRegsClobbered.resize(tri->getNumRegs()); + } + + bool hasReuses() const { + return !Reuses.empty(); + } + + /// addReuse - If we choose to reuse a virtual register that is already + /// available instead of reloading it, remember that we did so. + void addReuse(unsigned OpNo, unsigned StackSlotOrReMat, + unsigned PhysRegReused, unsigned AssignedPhysReg, + unsigned VirtReg) { + // If the reload is to the assigned register anyway, no undo will be + // required. + if (PhysRegReused == AssignedPhysReg) return; + + // Otherwise, remember this. + Reuses.push_back(ReusedOp(OpNo, StackSlotOrReMat, PhysRegReused, + AssignedPhysReg, VirtReg)); + } + + void markClobbered(unsigned PhysReg) { + PhysRegsClobbered.set(PhysReg); + } + + bool isClobbered(unsigned PhysReg) const { + return PhysRegsClobbered.test(PhysReg); + } + + /// GetRegForReload - We are about to emit a reload into PhysReg. If there + /// is some other operand that is using the specified register, either pick + /// a new register to use, or evict the previous reload and use this reg. + unsigned GetRegForReload(const TargetRegisterClass *RC, unsigned PhysReg, + MachineFunction &MF, MachineInstr *MI, + AvailableSpills &Spills, + std::vector &MaybeDeadStores, + SmallSet &Rejected, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM); + + /// GetRegForReload - Helper for the above GetRegForReload(). Add a + /// 'Rejected' set to remember which registers have been considered and + /// rejected for the reload. This avoids infinite looping in case like + /// this: + /// t1 := op t2, t3 + /// t2 <- assigned r0 for use by the reload but ended up reuse r1 + /// t3 <- assigned r1 for use by the reload but ended up reuse r0 + /// t1 <- desires r1 + /// sees r1 is taken by t2, tries t2's reload register r0 + /// sees r0 is taken by t3, tries t3's reload register r1 + /// sees r1 is taken by t2, tries t2's reload register r0 ... + unsigned GetRegForReload(unsigned VirtReg, unsigned PhysReg, MachineInstr *MI, + AvailableSpills &Spills, + std::vector &MaybeDeadStores, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + SmallSet Rejected; + MachineFunction &MF = *MI->getParent()->getParent(); + const TargetRegisterClass* RC = MF.getRegInfo().getRegClass(VirtReg); + return GetRegForReload(RC, PhysReg, MF, MI, Spills, MaybeDeadStores, + Rejected, RegKills, KillOps, VRM); + } +}; + +} + +// ****************** // +// Utility Functions // +// ****************** // + +/// findSinglePredSuccessor - Return via reference a vector of machine basic +/// blocks each of which is a successor of the specified BB and has no other +/// predecessor. +static void findSinglePredSuccessor(MachineBasicBlock *MBB, + SmallVectorImpl &Succs){ + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + if (SuccMBB->pred_size() == 1) + Succs.push_back(SuccMBB); + } +} + +/// ResurrectConfirmedKill - Helper for ResurrectKill. This register is killed +/// but not re-defined and it's being reused. Remove the kill flag for the +/// register and unset the kill's marker and last kill operand. +static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps) { + DEBUG(dbgs() << "Resurrect " << TRI->getName(Reg) << "\n"); + + MachineOperand *KillOp = KillOps[Reg]; + KillOp->setIsKill(false); + // KillOps[Reg] might be a def of a super-register. + unsigned KReg = KillOp->getReg(); + if (!RegKills[KReg]) + return; + + assert(KillOps[KReg]->getParent() == KillOp->getParent() && + "invalid superreg kill flags"); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + + // If it's a def of a super-register. Its other sub-regsters are no + // longer killed as well. + for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { + DEBUG(dbgs() << " Resurrect subreg " << TRI->getName(*SR) << "\n"); + + assert(KillOps[*SR]->getParent() == KillOp->getParent() && + "invalid subreg kill flags"); + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } +} + +/// ResurrectKill - Invalidate kill info associated with a previous MI. An +/// optimization may have decided that it's safe to reuse a previously killed +/// register. If we fail to erase the invalid kill flags, then the register +/// scavenger may later clobber the register used by this MI. Note that this +/// must be done even if this MI is being deleted! Consider: +/// +/// USE $r1 (vreg1) +/// ... +/// $r1(vreg3) = COPY $r1 (vreg2) +/// +/// RegAlloc has smartly assigned all three vregs to the same physreg. Initially +/// vreg1's only use is a kill. The rewriter doesn't know it should be live +/// until it rewrites vreg2. At that points it sees that the copy is dead and +/// deletes it. However, deleting the copy implicitly forwards liveness of $r1 +/// (it's copy coalescing). We must resurrect $r1 by removing the kill flag at +/// vreg1 before deleting the copy. +static void ResurrectKill(MachineInstr &MI, unsigned Reg, + const TargetRegisterInfo* TRI, BitVector &RegKills, + std::vector &KillOps) { + if (RegKills[Reg] && KillOps[Reg]->getParent() != &MI) { + ResurrectConfirmedKill(Reg, TRI, RegKills, KillOps); + return; + } + // No previous kill for this reg. Check for subreg kills as well. + // d4 = + // store d4, fi#0 + // ... + // = s8 + // ... + // = d4 + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + unsigned SReg = *SR; + if (RegKills[SReg] && KillOps[SReg]->getParent() != &MI) + ResurrectConfirmedKill(SReg, TRI, RegKills, KillOps); + } +} + +/// InvalidateKills - MI is going to be deleted. If any of its operands are +/// marked kill, then invalidate the information. +static void InvalidateKills(MachineInstr &MI, + const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps, + SmallVector *KillRegs = NULL) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + if (KillRegs) + KillRegs->push_back(Reg); + assert(Reg < KillOps.size()); + if (KillOps[Reg] == &MO) { + // This operand was the kill, now no longer. + KillOps[Reg] = NULL; + RegKills.reset(Reg); + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + if (RegKills[*SR]) { + assert(KillOps[*SR] == &MO && "bad subreg kill flags"); + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } + } + } + else { + // This operand may have reused a previously killed reg. Keep it live in + // case it continues to be used after erasing this instruction. + ResurrectKill(MI, Reg, TRI, RegKills, KillOps); + } + } +} + +/// InvalidateRegDef - If the def operand of the specified def MI is now dead +/// (since its spill instruction is removed), mark it isDead. Also checks if +/// the def MI has other definition operands that are not dead. Returns it by +/// reference. +static bool InvalidateRegDef(MachineBasicBlock::iterator I, + MachineInstr &NewDef, unsigned Reg, + bool &HasLiveDef, + const TargetRegisterInfo *TRI) { + // Due to remat, it's possible this reg isn't being reused. That is, + // the def of this reg (by prev MI) is now dead. + MachineInstr *DefMI = I; + MachineOperand *DefOp = NULL; + for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = DefMI->getOperand(i); + if (!MO.isReg() || !MO.isDef() || !MO.isKill() || MO.isUndef()) + continue; + if (MO.getReg() == Reg) + DefOp = &MO; + else if (!MO.isDead()) + HasLiveDef = true; + } + if (!DefOp) + return false; + + bool FoundUse = false, Done = false; + MachineBasicBlock::iterator E = &NewDef; + ++I; ++E; + for (; !Done && I != E; ++I) { + MachineInstr *NMI = I; + for (unsigned j = 0, ee = NMI->getNumOperands(); j != ee; ++j) { + MachineOperand &MO = NMI->getOperand(j); + if (!MO.isReg() || MO.getReg() == 0 || + (MO.getReg() != Reg && !TRI->isSubRegister(Reg, MO.getReg()))) + continue; + if (MO.isUse()) + FoundUse = true; + Done = true; // Stop after scanning all the operands of this MI. + } + } + if (!FoundUse) { + // Def is dead! + DefOp->setIsDead(); + return true; + } + return false; +} + +/// UpdateKills - Track and update kill info. If a MI reads a register that is +/// marked kill, then it must be due to register reuse. Transfer the kill info +/// over. +static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI, + BitVector &RegKills, + std::vector &KillOps) { + // These do not affect kill info at all. + if (MI.isDebugValue()) + return; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + + // This operand may have reused a previously killed reg. Keep it live. + ResurrectKill(MI, Reg, TRI, RegKills, KillOps); + + if (MO.isKill()) { + RegKills.set(Reg); + KillOps[Reg] = &MO; + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + RegKills.set(*SR); + KillOps[*SR] = &MO; + } + } + } + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.getReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + RegKills.reset(Reg); + KillOps[Reg] = NULL; + // It also defines (or partially define) aliases. + for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + RegKills.reset(*SR); + KillOps[*SR] = NULL; + } + for (const unsigned *SR = TRI->getSuperRegisters(Reg); *SR; ++SR) { + RegKills.reset(*SR); + KillOps[*SR] = NULL; + } + } +} + +/// ReMaterialize - Re-materialize definition for Reg targetting DestReg. +/// +static void ReMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MII, + unsigned DestReg, unsigned Reg, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI, + VirtRegMap &VRM) { + MachineInstr *ReMatDefMI = VRM.getReMaterializedMI(Reg); +#ifndef NDEBUG + const TargetInstrDesc &TID = ReMatDefMI->getDesc(); + assert(TID.getNumDefs() == 1 && + "Don't know how to remat instructions that define > 1 values!"); +#endif + TII->reMaterialize(MBB, MII, DestReg, 0, ReMatDefMI, *TRI); + MachineInstr *NewMI = prior(MII); + for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = NewMI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned VirtReg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(VirtReg)) + continue; + assert(MO.isUse()); + unsigned Phys = VRM.getPhys(VirtReg); + assert(Phys && "Virtual register is not assigned a register?"); + substitutePhysReg(MO, Phys, *TRI); + } + ++NumReMats; +} + +/// findSuperReg - Find the SubReg's super-register of given register class +/// where its SubIdx sub-register is SubReg. +static unsigned findSuperReg(const TargetRegisterClass *RC, unsigned SubReg, + unsigned SubIdx, const TargetRegisterInfo *TRI) { + for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end(); + I != E; ++I) { + unsigned Reg = *I; + if (TRI->getSubReg(Reg, SubIdx) == SubReg) + return Reg; + } + return 0; +} + +// ******************************** // +// Available Spills Implementation // +// ******************************** // + +/// disallowClobberPhysRegOnly - Unset the CanClobber bit of the specified +/// stackslot register. The register is still available but is no longer +/// allowed to be modifed. +void AvailableSpills::disallowClobberPhysRegOnly(unsigned PhysReg) { + std::multimap::iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + I++; + assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg && + "Bidirectional map mismatch!"); + SpillSlotsOrReMatsAvailable[SlotOrReMat] &= ~1; + DEBUG(dbgs() << "PhysReg " << TRI->getName(PhysReg) + << " copied, it is available for use but can no longer be modified\n"); + } +} + +/// disallowClobberPhysReg - Unset the CanClobber bit of the specified +/// stackslot register and its aliases. The register and its aliases may +/// still available but is no longer allowed to be modifed. +void AvailableSpills::disallowClobberPhysReg(unsigned PhysReg) { + for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS) + disallowClobberPhysRegOnly(*AS); + disallowClobberPhysRegOnly(PhysReg); +} + +/// ClobberPhysRegOnly - This is called when the specified physreg changes +/// value. We use this to invalidate any info about stuff we thing lives in it. +void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) { + std::multimap::iterator I = + PhysRegsAvailable.lower_bound(PhysReg); + while (I != PhysRegsAvailable.end() && I->first == PhysReg) { + int SlotOrReMat = I->second; + PhysRegsAvailable.erase(I++); + assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg && + "Bidirectional map mismatch!"); + SpillSlotsOrReMatsAvailable.erase(SlotOrReMat); + DEBUG(dbgs() << "PhysReg " << TRI->getName(PhysReg) + << " clobbered, invalidating "); + if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT) + DEBUG(dbgs() << "RM#" << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1 <<"\n"); + else + DEBUG(dbgs() << "SS#" << SlotOrReMat << "\n"); + } +} + +/// ClobberPhysReg - This is called when the specified physreg changes +/// value. We use this to invalidate any info about stuff we thing lives in +/// it and any of its aliases. +void AvailableSpills::ClobberPhysReg(unsigned PhysReg) { + for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS) + ClobberPhysRegOnly(*AS); + ClobberPhysRegOnly(PhysReg); +} + +/// AddAvailableRegsToLiveIn - Availability information is being kept coming +/// into the specified MBB. Add available physical registers as potential +/// live-in's. If they are reused in the MBB, they will be added to the +/// live-in set to make register scavenger and post-allocation scheduler. +void AvailableSpills::AddAvailableRegsToLiveIn(MachineBasicBlock &MBB, + BitVector &RegKills, + std::vector &KillOps) { + std::set NotAvailable; + for (std::multimap::iterator + I = PhysRegsAvailable.begin(), E = PhysRegsAvailable.end(); + I != E; ++I) { + unsigned Reg = I->first; + const TargetRegisterClass* RC = TRI->getMinimalPhysRegClass(Reg); + // FIXME: A temporary workaround. We can't reuse available value if it's + // not safe to move the def of the virtual register's class. e.g. + // X86::RFP* register classes. Do not add it as a live-in. + if (!TII->isSafeToMoveRegClassDefs(RC)) + // This is no longer available. + NotAvailable.insert(Reg); + else { + MBB.addLiveIn(Reg); + if (RegKills[Reg]) + ResurrectConfirmedKill(Reg, TRI, RegKills, KillOps); + } + + // Skip over the same register. + std::multimap::iterator NI = llvm::next(I); + while (NI != E && NI->first == Reg) { + ++I; + ++NI; + } + } + + for (std::set::iterator I = NotAvailable.begin(), + E = NotAvailable.end(); I != E; ++I) { + ClobberPhysReg(*I); + for (const unsigned *SubRegs = TRI->getSubRegisters(*I); + *SubRegs; ++SubRegs) + ClobberPhysReg(*SubRegs); + } +} + +/// ModifyStackSlotOrReMat - This method is called when the value in a stack +/// slot changes. This removes information about which register the previous +/// value for this slot lives in (as the previous value is dead now). +void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) { + std::map::iterator It = + SpillSlotsOrReMatsAvailable.find(SlotOrReMat); + if (It == SpillSlotsOrReMatsAvailable.end()) return; + unsigned Reg = It->second >> 1; + SpillSlotsOrReMatsAvailable.erase(It); + + // This register may hold the value of multiple stack slots, only remove this + // stack slot from the set of values the register contains. + std::multimap::iterator I = PhysRegsAvailable.lower_bound(Reg); + for (; ; ++I) { + assert(I != PhysRegsAvailable.end() && I->first == Reg && + "Map inverse broken!"); + if (I->second == SlotOrReMat) break; + } + PhysRegsAvailable.erase(I); +} + +// ************************** // +// Reuse Info Implementation // +// ************************** // + +/// GetRegForReload - We are about to emit a reload into PhysReg. If there +/// is some other operand that is using the specified register, either pick +/// a new register to use, or evict the previous reload and use this reg. +unsigned ReuseInfo::GetRegForReload(const TargetRegisterClass *RC, + unsigned PhysReg, + MachineFunction &MF, + MachineInstr *MI, AvailableSpills &Spills, + std::vector &MaybeDeadStores, + SmallSet &Rejected, + BitVector &RegKills, + std::vector &KillOps, + VirtRegMap &VRM) { + const TargetInstrInfo* TII = MF.getTarget().getInstrInfo(); + const TargetRegisterInfo *TRI = Spills.getRegInfo(); + + if (Reuses.empty()) return PhysReg; // This is most often empty. + + for (unsigned ro = 0, e = Reuses.size(); ro != e; ++ro) { + ReusedOp &Op = Reuses[ro]; + // If we find some other reuse that was supposed to use this register + // exactly for its reload, we can change this reload to use ITS reload + // register. That is, unless its reload register has already been + // considered and subsequently rejected because it has also been reused + // by another operand. + if (Op.PhysRegReused == PhysReg && + Rejected.count(Op.AssignedPhysReg) == 0 && + RC->contains(Op.AssignedPhysReg)) { + // Yup, use the reload register that we didn't use before. + unsigned NewReg = Op.AssignedPhysReg; + Rejected.insert(PhysReg); + return GetRegForReload(RC, NewReg, MF, MI, Spills, MaybeDeadStores, + Rejected, RegKills, KillOps, VRM); + } else { + // Otherwise, we might also have a problem if a previously reused + // value aliases the new register. If so, codegen the previous reload + // and use this one. + unsigned PRRU = Op.PhysRegReused; + if (TRI->regsOverlap(PRRU, PhysReg)) { + // Okay, we found out that an alias of a reused register + // was used. This isn't good because it means we have + // to undo a previous reuse. + MachineBasicBlock *MBB = MI->getParent(); + const TargetRegisterClass *AliasRC = + MBB->getParent()->getRegInfo().getRegClass(Op.VirtReg); + + // Copy Op out of the vector and remove it, we're going to insert an + // explicit load for it. + ReusedOp NewOp = Op; + Reuses.erase(Reuses.begin()+ro); + + // MI may be using only a sub-register of PhysRegUsed. + unsigned RealPhysRegUsed = MI->getOperand(NewOp.Operand).getReg(); + unsigned SubIdx = 0; + assert(TargetRegisterInfo::isPhysicalRegister(RealPhysRegUsed) && + "A reuse cannot be a virtual register"); + if (PRRU != RealPhysRegUsed) { + // What was the sub-register index? + SubIdx = TRI->getSubRegIndex(PRRU, RealPhysRegUsed); + assert(SubIdx && + "Operand physreg is not a sub-register of PhysRegUsed"); + } + + // Ok, we're going to try to reload the assigned physreg into the + // slot that we were supposed to in the first place. However, that + // register could hold a reuse. Check to see if it conflicts or + // would prefer us to use a different register. + unsigned NewPhysReg = GetRegForReload(RC, NewOp.AssignedPhysReg, + MF, MI, Spills, MaybeDeadStores, + Rejected, RegKills, KillOps, VRM); + + bool DoReMat = NewOp.StackSlotOrReMat > VirtRegMap::MAX_STACK_SLOT; + int SSorRMId = DoReMat + ? VRM.getReMatId(NewOp.VirtReg) : (int) NewOp.StackSlotOrReMat; + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MI, MBB->begin(), PhysReg, TRI, + DoReMat, SSorRMId, TII, MF); + + if (DoReMat) { + ReMaterialize(*MBB, InsertLoc, NewPhysReg, NewOp.VirtReg, TII, + TRI, VRM); + } else { + TII->loadRegFromStackSlot(*MBB, InsertLoc, NewPhysReg, + NewOp.StackSlotOrReMat, AliasRC, TRI); + MachineInstr *LoadMI = prior(InsertLoc); + VRM.addSpillSlotUse(NewOp.StackSlotOrReMat, LoadMI); + // Any stores to this stack slot are not dead anymore. + MaybeDeadStores[NewOp.StackSlotOrReMat] = NULL; + ++NumLoads; + } + Spills.ClobberPhysReg(NewPhysReg); + Spills.ClobberPhysReg(NewOp.PhysRegReused); + + unsigned RReg = SubIdx ? TRI->getSubReg(NewPhysReg, SubIdx) :NewPhysReg; + MI->getOperand(NewOp.Operand).setReg(RReg); + MI->getOperand(NewOp.Operand).setSubReg(0); + + Spills.addAvailable(NewOp.StackSlotOrReMat, NewPhysReg); + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(dbgs() << '\t' << *prior(InsertLoc)); + + DEBUG(dbgs() << "Reuse undone!\n"); + --NumReused; + + // Finally, PhysReg is now available, go ahead and use it. + return PhysReg; + } + } + } + return PhysReg; +} + +// ************************************************************************ // + +/// FoldsStackSlotModRef - Return true if the specified MI folds the specified +/// stack slot mod/ref. It also checks if it's possible to unfold the +/// instruction by having it define a specified physical register instead. +static bool FoldsStackSlotModRef(MachineInstr &MI, int SS, unsigned PhysReg, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI, + VirtRegMap &VRM) { + if (VRM.hasEmergencySpills(&MI) || VRM.isSpillPt(&MI)) + return false; + + bool Found = false; + VirtRegMap::MI2VirtMapTy::const_iterator I, End; + for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ++I) { + unsigned VirtReg = I->second.first; + VirtRegMap::ModRef MR = I->second.second; + if (MR & VirtRegMap::isModRef) + if (VRM.getStackSlot(VirtReg) == SS) { + Found= TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(), true, true) != 0; + break; + } + } + if (!Found) + return false; + + // Does the instruction uses a register that overlaps the scratch register? + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned Reg = MO.getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + if (!VRM.hasPhys(Reg)) + continue; + Reg = VRM.getPhys(Reg); + } + if (TRI->regsOverlap(PhysReg, Reg)) + return false; + } + return true; +} + +/// FindFreeRegister - Find a free register of a given register class by looking +/// at (at most) the last two machine instructions. +static unsigned FindFreeRegister(MachineBasicBlock::iterator MII, + MachineBasicBlock &MBB, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI, + BitVector &AllocatableRegs) { + BitVector Defs(TRI->getNumRegs()); + BitVector Uses(TRI->getNumRegs()); + SmallVector LocalUses; + SmallVector Kills; + + // Take a look at 2 instructions at most. + unsigned Count = 0; + while (Count < 2) { + if (MII == MBB.begin()) + break; + MachineInstr *PrevMI = prior(MII); + MII = PrevMI; + + if (PrevMI->isDebugValue()) + continue; // Skip over dbg_value instructions. + ++Count; + + for (unsigned i = 0, e = PrevMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = PrevMI->getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; + unsigned Reg = MO.getReg(); + if (MO.isDef()) { + Defs.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + Defs.set(*AS); + } else { + LocalUses.push_back(Reg); + if (MO.isKill() && AllocatableRegs[Reg]) + Kills.push_back(Reg); + } + } + + for (unsigned i = 0, e = Kills.size(); i != e; ++i) { + unsigned Kill = Kills[i]; + if (!Defs[Kill] && !Uses[Kill] && + RC->contains(Kill)) + return Kill; + } + for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) { + unsigned Reg = LocalUses[i]; + Uses.set(Reg); + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + Uses.set(*AS); + } + } + + return 0; +} + +static +void AssignPhysToVirtReg(MachineInstr *MI, unsigned VirtReg, unsigned PhysReg, + const TargetRegisterInfo &TRI) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == VirtReg) + substitutePhysReg(MO, PhysReg, TRI); + } +} + +namespace { + +struct RefSorter { + bool operator()(const std::pair &A, + const std::pair &B) { + return A.second < B.second; + } +}; + +// ***************************** // +// Local Spiller Implementation // +// ***************************** // + +class LocalRewriter : public VirtRegRewriter { + MachineRegisterInfo *MRI; + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + VirtRegMap *VRM; + LiveIntervals *LIs; + BitVector AllocatableRegs; + DenseMap DistanceMap; + DenseMap > Slot2DbgValues; + + MachineBasicBlock *MBB; // Basic block currently being processed. + +public: + + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs); + +private: + void EraseInstr(MachineInstr *MI) { + VRM->RemoveMachineInstrFromMaps(MI); + LIs->RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + } + + bool OptimizeByUnfold2(unsigned VirtReg, int SS, + MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps); + + bool OptimizeByUnfold(MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps); + + bool CommuteToFoldReload(MachineBasicBlock::iterator &MII, + unsigned VirtReg, unsigned SrcReg, int SS, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps, + const TargetRegisterInfo *TRI); + + void SpillRegToStackSlot(MachineBasicBlock::iterator &MII, + int Idx, unsigned PhysReg, int StackSlot, + const TargetRegisterClass *RC, + bool isAvailable, MachineInstr *&LastStore, + AvailableSpills &Spills, + SmallSet &ReMatDefs, + BitVector &RegKills, + std::vector &KillOps); + + void TransferDeadness(unsigned Reg, BitVector &RegKills, + std::vector &KillOps); + + bool InsertEmergencySpills(MachineInstr *MI); + + bool InsertRestores(MachineInstr *MI, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps); + + bool InsertSpills(MachineInstr *MI); + + void ProcessUses(MachineInstr &MI, AvailableSpills &Spills, + std::vector &MaybeDeadStores, + BitVector &RegKills, + ReuseInfo &ReusedOperands, + std::vector &KillOps); + + void RewriteMBB(LiveIntervals *LIs, + AvailableSpills &Spills, BitVector &RegKills, + std::vector &KillOps); +}; +} + +bool LocalRewriter::runOnMachineFunction(MachineFunction &MF, VirtRegMap &vrm, + LiveIntervals* lis) { + MRI = &MF.getRegInfo(); + TRI = MF.getTarget().getRegisterInfo(); + TII = MF.getTarget().getInstrInfo(); + VRM = &vrm; + LIs = lis; + AllocatableRegs = TRI->getAllocatableSet(MF); + DEBUG(dbgs() << "\n**** Local spiller rewriting function '" + << MF.getFunction()->getName() << "':\n"); + DEBUG(dbgs() << "**** Machine Instrs (NOTE! Does not include spills and" + " reloads!) ****\n"); + DEBUG(MF.print(dbgs(), LIs->getSlotIndexes())); + + // Spills - Keep track of which spilled values are available in physregs + // so that we can choose to reuse the physregs instead of emitting + // reloads. This is usually refreshed per basic block. + AvailableSpills Spills(TRI, TII); + + // Keep track of kill information. + BitVector RegKills(TRI->getNumRegs()); + std::vector KillOps; + KillOps.resize(TRI->getNumRegs(), NULL); + + // SingleEntrySuccs - Successor blocks which have a single predecessor. + SmallVector SinglePredSuccs; + SmallPtrSet EarlyVisited; + + // Traverse the basic blocks depth first. + MachineBasicBlock *Entry = MF.begin(); + SmallPtrSet Visited; + for (df_ext_iterator > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MBB = *DFI; + if (!EarlyVisited.count(MBB)) + RewriteMBB(LIs, Spills, RegKills, KillOps); + + // If this MBB is the only predecessor of a successor. Keep the + // availability information and visit it next. + do { + // Keep visiting single predecessor successor as long as possible. + SinglePredSuccs.clear(); + findSinglePredSuccessor(MBB, SinglePredSuccs); + if (SinglePredSuccs.empty()) + MBB = 0; + else { + // FIXME: More than one successors, each of which has MBB has + // the only predecessor. + MBB = SinglePredSuccs[0]; + if (!Visited.count(MBB) && EarlyVisited.insert(MBB)) { + Spills.AddAvailableRegsToLiveIn(*MBB, RegKills, KillOps); + RewriteMBB(LIs, Spills, RegKills, KillOps); + } + } + } while (MBB); + + // Clear the availability info. + Spills.clear(); + } + + DEBUG(dbgs() << "**** Post Machine Instrs ****\n"); + DEBUG(MF.print(dbgs(), LIs->getSlotIndexes())); + + // Mark unused spill slots. + MachineFrameInfo *MFI = MF.getFrameInfo(); + int SS = VRM->getLowSpillSlot(); + if (SS != VirtRegMap::NO_STACK_SLOT) { + for (int e = VRM->getHighSpillSlot(); SS <= e; ++SS) { + SmallVector &DbgValues = Slot2DbgValues[SS]; + if (!VRM->isSpillSlotUsed(SS)) { + MFI->RemoveStackObject(SS); + for (unsigned j = 0, ee = DbgValues.size(); j != ee; ++j) { + MachineInstr *DVMI = DbgValues[j]; + DEBUG(dbgs() << "Removing debug info referencing FI#" << SS << '\n'); + EraseInstr(DVMI); + } + ++NumDSS; + } + DbgValues.clear(); + } + } + Slot2DbgValues.clear(); + + return true; +} + +/// OptimizeByUnfold2 - Unfold a series of load / store folding instructions if +/// a scratch register is available. +/// xorq %r12, %r13 +/// addq %rax, -184(%rbp) +/// addq %r13, -184(%rbp) +/// ==> +/// xorq %r12, %r13 +/// movq -184(%rbp), %r12 +/// addq %rax, %r12 +/// addq %r13, %r12 +/// movq %r12, -184(%rbp) +bool LocalRewriter:: +OptimizeByUnfold2(unsigned VirtReg, int SS, + MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps) { + + MachineBasicBlock::iterator NextMII = llvm::next(MII); + // Skip over dbg_value instructions. + while (NextMII != MBB->end() && NextMII->isDebugValue()) + NextMII = llvm::next(NextMII); + if (NextMII == MBB->end()) + return false; + + if (TII->getOpcodeAfterMemoryUnfold(MII->getOpcode(), true, true) == 0) + return false; + + // Now let's see if the last couple of instructions happens to have freed up + // a register. + const TargetRegisterClass* RC = MRI->getRegClass(VirtReg); + unsigned PhysReg = FindFreeRegister(MII, *MBB, RC, TRI, AllocatableRegs); + if (!PhysReg) + return false; + + MachineFunction &MF = *MBB->getParent(); + TRI = MF.getTarget().getRegisterInfo(); + MachineInstr &MI = *MII; + if (!FoldsStackSlotModRef(MI, SS, PhysReg, TII, TRI, *VRM)) + return false; + + // If the next instruction also folds the same SS modref and can be unfoled, + // then it's worthwhile to issue a load from SS into the free register and + // then unfold these instructions. + if (!FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, *VRM)) + return false; + + // Back-schedule reloads and remats. + ComputeReloadLoc(MII, MBB->begin(), PhysReg, TRI, false, SS, TII, MF); + + // Load from SS to the spare physical register. + TII->loadRegFromStackSlot(*MBB, MII, PhysReg, SS, RC, TRI); + // This invalidates Phys. + Spills.ClobberPhysReg(PhysReg); + // Remember it's available. + Spills.addAvailable(SS, PhysReg); + MaybeDeadStores[SS] = NULL; + + // Unfold current MI. + SmallVector NewMIs; + if (!TII->unfoldMemoryOperand(MF, &MI, VirtReg, false, false, NewMIs)) + llvm_unreachable("Unable unfold the load / store folding instruction!"); + assert(NewMIs.size() == 1); + AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg, *TRI); + VRM->transferRestorePts(&MI, NewMIs[0]); + MII = MBB->insert(MII, NewMIs[0]); + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + ++NumModRefUnfold; + + // Unfold next instructions that fold the same SS. + do { + MachineInstr &NextMI = *NextMII; + NextMII = llvm::next(NextMII); + NewMIs.clear(); + if (!TII->unfoldMemoryOperand(MF, &NextMI, VirtReg, false, false, NewMIs)) + llvm_unreachable("Unable unfold the load / store folding instruction!"); + assert(NewMIs.size() == 1); + AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg, *TRI); + VRM->transferRestorePts(&NextMI, NewMIs[0]); + MBB->insert(NextMII, NewMIs[0]); + InvalidateKills(NextMI, TRI, RegKills, KillOps); + EraseInstr(&NextMI); + ++NumModRefUnfold; + // Skip over dbg_value instructions. + while (NextMII != MBB->end() && NextMII->isDebugValue()) + NextMII = llvm::next(NextMII); + if (NextMII == MBB->end()) + break; + } while (FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, *VRM)); + + // Store the value back into SS. + TII->storeRegToStackSlot(*MBB, NextMII, PhysReg, true, SS, RC, TRI); + MachineInstr *StoreMI = prior(NextMII); + VRM->addSpillSlotUse(SS, StoreMI); + VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + + return true; +} + +/// OptimizeByUnfold - Turn a store folding instruction into a load folding +/// instruction. e.g. +/// xorl %edi, %eax +/// movl %eax, -32(%ebp) +/// movl -36(%ebp), %eax +/// orl %eax, -32(%ebp) +/// ==> +/// xorl %edi, %eax +/// orl -36(%ebp), %eax +/// mov %eax, -32(%ebp) +/// This enables unfolding optimization for a subsequent instruction which will +/// also eliminate the newly introduced store instruction. +bool LocalRewriter:: +OptimizeByUnfold(MachineBasicBlock::iterator &MII, + std::vector &MaybeDeadStores, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps) { + MachineFunction &MF = *MBB->getParent(); + MachineInstr &MI = *MII; + unsigned UnfoldedOpc = 0; + unsigned UnfoldPR = 0; + unsigned UnfoldVR = 0; + int FoldedSS = VirtRegMap::NO_STACK_SLOT; + VirtRegMap::MI2VirtMapTy::const_iterator I, End; + for (tie(I, End) = VRM->getFoldedVirts(&MI); I != End; ) { + // Only transform a MI that folds a single register. + if (UnfoldedOpc) + return false; + UnfoldVR = I->second.first; + VirtRegMap::ModRef MR = I->second.second; + // MI2VirtMap be can updated which invalidate the iterator. + // Increment the iterator first. + ++I; + if (VRM->isAssignedReg(UnfoldVR)) + continue; + // If this reference is not a use, any previous store is now dead. + // Otherwise, the store to this stack slot is not dead anymore. + FoldedSS = VRM->getStackSlot(UnfoldVR); + MachineInstr* DeadStore = MaybeDeadStores[FoldedSS]; + if (DeadStore && (MR & VirtRegMap::isModRef)) { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(FoldedSS); + if (!PhysReg || !DeadStore->readsRegister(PhysReg)) + continue; + UnfoldPR = PhysReg; + UnfoldedOpc = TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(), + false, true); + } + } + + if (!UnfoldedOpc) { + if (!UnfoldVR) + return false; + + // Look for other unfolding opportunities. + return OptimizeByUnfold2(UnfoldVR, FoldedSS, MII, MaybeDeadStores, Spills, + RegKills, KillOps); + } + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0 || !MO.isUse()) + continue; + unsigned VirtReg = MO.getReg(); + if (TargetRegisterInfo::isPhysicalRegister(VirtReg) || MO.getSubReg()) + continue; + if (VRM->isAssignedReg(VirtReg)) { + unsigned PhysReg = VRM->getPhys(VirtReg); + if (PhysReg && TRI->regsOverlap(PhysReg, UnfoldPR)) + return false; + } else if (VRM->isReMaterialized(VirtReg)) + continue; + int SS = VRM->getStackSlot(VirtReg); + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + if (PhysReg) { + if (TRI->regsOverlap(PhysReg, UnfoldPR)) + return false; + continue; + } + if (VRM->hasPhys(VirtReg)) { + PhysReg = VRM->getPhys(VirtReg); + if (!TRI->regsOverlap(PhysReg, UnfoldPR)) + continue; + } + + // Ok, we'll need to reload the value into a register which makes + // it impossible to perform the store unfolding optimization later. + // Let's see if it is possible to fold the load if the store is + // unfolded. This allows us to perform the store unfolding + // optimization. + SmallVector NewMIs; + if (TII->unfoldMemoryOperand(MF, &MI, UnfoldVR, false, false, NewMIs)) { + assert(NewMIs.size() == 1); + MachineInstr *NewMI = NewMIs.back(); + MBB->insert(MII, NewMI); + NewMIs.clear(); + int Idx = NewMI->findRegisterUseOperandIdx(VirtReg, false); + assert(Idx != -1); + SmallVector Ops; + Ops.push_back(Idx); + MachineInstr *FoldedMI = TII->foldMemoryOperand(NewMI, Ops, SS); + NewMI->eraseFromParent(); + if (FoldedMI) { + VRM->addSpillSlotUse(SS, FoldedMI); + if (!VRM->hasPhys(UnfoldVR)) + VRM->assignVirt2Phys(UnfoldVR, UnfoldPR); + VRM->virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef); + MII = FoldedMI; + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + return true; + } + } + } + + return false; +} + +/// CommuteChangesDestination - We are looking for r0 = op r1, r2 and +/// where SrcReg is r1 and it is tied to r0. Return true if after +/// commuting this instruction it will be r0 = op r2, r1. +static bool CommuteChangesDestination(MachineInstr *DefMI, + const TargetInstrDesc &TID, + unsigned SrcReg, + const TargetInstrInfo *TII, + unsigned &DstIdx) { + if (TID.getNumDefs() != 1 && TID.getNumOperands() != 3) + return false; + if (!DefMI->getOperand(1).isReg() || + DefMI->getOperand(1).getReg() != SrcReg) + return false; + unsigned DefIdx; + if (!DefMI->isRegTiedToDefOperand(1, &DefIdx) || DefIdx != 0) + return false; + unsigned SrcIdx1, SrcIdx2; + if (!TII->findCommutedOpIndices(DefMI, SrcIdx1, SrcIdx2)) + return false; + if (SrcIdx1 == 1 && SrcIdx2 == 2) { + DstIdx = 2; + return true; + } + return false; +} + +/// CommuteToFoldReload - +/// Look for +/// r1 = load fi#1 +/// r1 = op r1, r2 +/// store r1, fi#1 +/// +/// If op is commutable and r2 is killed, then we can xform these to +/// r2 = op r2, fi#1 +/// store r2, fi#1 +bool LocalRewriter:: +CommuteToFoldReload(MachineBasicBlock::iterator &MII, + unsigned VirtReg, unsigned SrcReg, int SS, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps, + const TargetRegisterInfo *TRI) { + if (MII == MBB->begin() || !MII->killsRegister(SrcReg)) + return false; + + MachineInstr &MI = *MII; + MachineBasicBlock::iterator DefMII = prior(MII); + MachineInstr *DefMI = DefMII; + const TargetInstrDesc &TID = DefMI->getDesc(); + unsigned NewDstIdx; + if (DefMII != MBB->begin() && + TID.isCommutable() && + CommuteChangesDestination(DefMI, TID, SrcReg, TII, NewDstIdx)) { + MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx); + unsigned NewReg = NewDstMO.getReg(); + if (!NewDstMO.isKill() || TRI->regsOverlap(NewReg, SrcReg)) + return false; + MachineInstr *ReloadMI = prior(DefMII); + int FrameIdx; + unsigned DestReg = TII->isLoadFromStackSlot(ReloadMI, FrameIdx); + if (DestReg != SrcReg || FrameIdx != SS) + return false; + int UseIdx = DefMI->findRegisterUseOperandIdx(DestReg, false); + if (UseIdx == -1) + return false; + unsigned DefIdx; + if (!MI.isRegTiedToDefOperand(UseIdx, &DefIdx)) + return false; + assert(DefMI->getOperand(DefIdx).isReg() && + DefMI->getOperand(DefIdx).getReg() == SrcReg); + + // Now commute def instruction. + MachineInstr *CommutedMI = TII->commuteInstruction(DefMI, true); + if (!CommutedMI) + return false; + MBB->insert(MII, CommutedMI); + SmallVector Ops; + Ops.push_back(NewDstIdx); + MachineInstr *FoldedMI = TII->foldMemoryOperand(CommutedMI, Ops, SS); + // Not needed since foldMemoryOperand returns new MI. + CommutedMI->eraseFromParent(); + if (!FoldedMI) + return false; + + VRM->addSpillSlotUse(SS, FoldedMI); + VRM->virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef); + // Insert new def MI and spill MI. + const TargetRegisterClass* RC = MRI->getRegClass(VirtReg); + TII->storeRegToStackSlot(*MBB, &MI, NewReg, true, SS, RC, TRI); + MII = prior(MII); + MachineInstr *StoreMI = MII; + VRM->addSpillSlotUse(SS, StoreMI); + VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + MII = FoldedMI; // Update MII to backtrack. + + // Delete all 3 old instructions. + InvalidateKills(*ReloadMI, TRI, RegKills, KillOps); + EraseInstr(ReloadMI); + InvalidateKills(*DefMI, TRI, RegKills, KillOps); + EraseInstr(DefMI); + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + + // If NewReg was previously holding value of some SS, it's now clobbered. + // This has to be done now because it's a physical register. When this + // instruction is re-visited, it's ignored. + Spills.ClobberPhysReg(NewReg); + + ++NumCommutes; + return true; + } + + return false; +} + +/// SpillRegToStackSlot - Spill a register to a specified stack slot. Check if +/// the last store to the same slot is now dead. If so, remove the last store. +void LocalRewriter:: +SpillRegToStackSlot(MachineBasicBlock::iterator &MII, + int Idx, unsigned PhysReg, int StackSlot, + const TargetRegisterClass *RC, + bool isAvailable, MachineInstr *&LastStore, + AvailableSpills &Spills, + SmallSet &ReMatDefs, + BitVector &RegKills, + std::vector &KillOps) { + + MachineBasicBlock::iterator oldNextMII = llvm::next(MII); + TII->storeRegToStackSlot(*MBB, llvm::next(MII), PhysReg, true, StackSlot, RC, + TRI); + MachineInstr *StoreMI = prior(oldNextMII); + VRM->addSpillSlotUse(StackSlot, StoreMI); + DEBUG(dbgs() << "Store:\t" << *StoreMI); + + // If there is a dead store to this stack slot, nuke it now. + if (LastStore) { + DEBUG(dbgs() << "Removed dead store:\t" << *LastStore); + ++NumDSE; + SmallVector KillRegs; + InvalidateKills(*LastStore, TRI, RegKills, KillOps, &KillRegs); + MachineBasicBlock::iterator PrevMII = LastStore; + bool CheckDef = PrevMII != MBB->begin(); + if (CheckDef) + --PrevMII; + EraseInstr(LastStore); + if (CheckDef) { + // Look at defs of killed registers on the store. Mark the defs + // as dead since the store has been deleted and they aren't + // being reused. + for (unsigned j = 0, ee = KillRegs.size(); j != ee; ++j) { + bool HasOtherDef = false; + if (InvalidateRegDef(PrevMII, *MII, KillRegs[j], HasOtherDef, TRI)) { + MachineInstr *DeadDef = PrevMII; + if (ReMatDefs.count(DeadDef) && !HasOtherDef) { + // FIXME: This assumes a remat def does not have side effects. + EraseInstr(DeadDef); + ++NumDRM; + } + } + } + } + } + + // Allow for multi-instruction spill sequences, as on PPC Altivec. Presume + // the last of multiple instructions is the actual store. + LastStore = prior(oldNextMII); + + // If the stack slot value was previously available in some other + // register, change it now. Otherwise, make the register available, + // in PhysReg. + Spills.ModifyStackSlotOrReMat(StackSlot); + Spills.ClobberPhysReg(PhysReg); + Spills.addAvailable(StackSlot, PhysReg, isAvailable); + ++NumStores; +} + +/// isSafeToDelete - Return true if this instruction doesn't produce any side +/// effect and all of its defs are dead. +static bool isSafeToDelete(MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + if (TID.mayLoad() || TID.mayStore() || TID.isTerminator() || + TID.isCall() || TID.isBarrier() || TID.isReturn() || + MI.isLabel() || MI.isDebugValue() || + MI.hasUnmodeledSideEffects()) + return false; + + // Technically speaking inline asm without side effects and no defs can still + // be deleted. But there is so much bad inline asm code out there, we should + // let them be. + if (MI.isInlineAsm()) + return false; + + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + if (MO.isDef() && !MO.isDead()) + return false; + if (MO.isUse() && MO.isKill()) + // FIXME: We can't remove kill markers or else the scavenger will assert. + // An alternative is to add a ADD pseudo instruction to replace kill + // markers. + return false; + } + return true; +} + +/// TransferDeadness - A identity copy definition is dead and it's being +/// removed. Find the last def or use and mark it as dead / kill. +void LocalRewriter:: +TransferDeadness(unsigned Reg, BitVector &RegKills, + std::vector &KillOps) { + SmallPtrSet Seens; + SmallVector,8> Refs; + for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(Reg), + RE = MRI->reg_end(); RI != RE; ++RI) { + MachineInstr *UDMI = &*RI; + if (UDMI->isDebugValue() || UDMI->getParent() != MBB) + continue; + DenseMap::iterator DI = DistanceMap.find(UDMI); + if (DI == DistanceMap.end()) + continue; + if (Seens.insert(UDMI)) + Refs.push_back(std::make_pair(UDMI, DI->second)); + } + + if (Refs.empty()) + return; + std::sort(Refs.begin(), Refs.end(), RefSorter()); + + while (!Refs.empty()) { + MachineInstr *LastUDMI = Refs.back().first; + Refs.pop_back(); + + MachineOperand *LastUD = NULL; + for (unsigned i = 0, e = LastUDMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = LastUDMI->getOperand(i); + if (!MO.isReg() || MO.getReg() != Reg) + continue; + if (!LastUD || (LastUD->isUse() && MO.isDef())) + LastUD = &MO; + if (LastUDMI->isRegTiedToDefOperand(i)) + break; + } + if (LastUD->isDef()) { + // If the instruction has no side effect, delete it and propagate + // backward further. Otherwise, mark is dead and we are done. + if (!isSafeToDelete(*LastUDMI)) { + LastUD->setIsDead(); + break; + } + EraseInstr(LastUDMI); + } else { + LastUD->setIsKill(); + RegKills.set(Reg); + KillOps[Reg] = LastUD; + break; + } + } +} + +/// InsertEmergencySpills - Insert emergency spills before MI if requested by +/// VRM. Return true if spills were inserted. +bool LocalRewriter::InsertEmergencySpills(MachineInstr *MI) { + if (!VRM->hasEmergencySpills(MI)) + return false; + MachineBasicBlock::iterator MII = MI; + SmallSet UsedSS; + std::vector &EmSpills = VRM->getEmergencySpills(MI); + for (unsigned i = 0, e = EmSpills.size(); i != e; ++i) { + unsigned PhysReg = EmSpills[i]; + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(PhysReg); + assert(RC && "Unable to determine register class!"); + int SS = VRM->getEmergencySpillSlot(RC); + if (UsedSS.count(SS)) + llvm_unreachable("Need to spill more than one physical registers!"); + UsedSS.insert(SS); + TII->storeRegToStackSlot(*MBB, MII, PhysReg, true, SS, RC, TRI); + MachineInstr *StoreMI = prior(MII); + VRM->addSpillSlotUse(SS, StoreMI); + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(llvm::next(MII), MBB->begin(), PhysReg, TRI, false, SS, + TII, *MBB->getParent()); + + TII->loadRegFromStackSlot(*MBB, InsertLoc, PhysReg, SS, RC, TRI); + + MachineInstr *LoadMI = prior(InsertLoc); + VRM->addSpillSlotUse(SS, LoadMI); + ++NumPSpills; + DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size())); + } + return true; +} + +/// InsertRestores - Restore registers before MI is requested by VRM. Return +/// true is any instructions were inserted. +bool LocalRewriter::InsertRestores(MachineInstr *MI, + AvailableSpills &Spills, + BitVector &RegKills, + std::vector &KillOps) { + if (!VRM->isRestorePt(MI)) + return false; + MachineBasicBlock::iterator MII = MI; + std::vector &RestoreRegs = VRM->getRestorePtRestores(MI); + for (unsigned i = 0, e = RestoreRegs.size(); i != e; ++i) { + unsigned VirtReg = RestoreRegs[e-i-1]; // Reverse order. + if (!VRM->getPreSplitReg(VirtReg)) + continue; // Split interval spilled again. + unsigned Phys = VRM->getPhys(VirtReg); + MRI->setPhysRegUsed(Phys); + + // Check if the value being restored if available. If so, it must be + // from a predecessor BB that fallthrough into this BB. We do not + // expect: + // BB1: + // r1 = load fi#1 + // ... + // = r1 + // ... # r1 not clobbered + // ... + // = load fi#1 + bool DoReMat = VRM->isReMaterialized(VirtReg); + int SSorRMId = DoReMat + ? VRM->getReMatId(VirtReg) : VRM->getStackSlot(VirtReg); + unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId); + if (InReg == Phys) { + // If the value is already available in the expected register, save + // a reload / remat. + if (SSorRMId) + DEBUG(dbgs() << "Reusing RM#" + << SSorRMId-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(dbgs() << "Reusing SS#" << SSorRMId); + DEBUG(dbgs() << " from physreg " + << TRI->getName(InReg) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << TRI->getName(Phys) << '\n'); + + // Reusing a physreg may resurrect it. But we expect ProcessUses to update + // the kill flags for the current instruction after processing it. + + ++NumOmitted; + continue; + } else if (InReg && InReg != Phys) { + if (SSorRMId) + DEBUG(dbgs() << "Reusing RM#" + << SSorRMId-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(dbgs() << "Reusing SS#" << SSorRMId); + DEBUG(dbgs() << " from physreg " + << TRI->getName(InReg) << " for vreg" + << VirtReg <<" by copying it into physreg " + << TRI->getName(Phys) << '\n'); + + // If the reloaded / remat value is available in another register, + // copy it to the desired register. + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MII, MBB->begin(), Phys, TRI, DoReMat, SSorRMId, TII, + *MBB->getParent()); + MachineInstr *CopyMI = BuildMI(*MBB, InsertLoc, MI->getDebugLoc(), + TII->get(TargetOpcode::COPY), Phys) + .addReg(InReg, RegState::Kill); + + // This invalidates Phys. + Spills.ClobberPhysReg(Phys); + // Remember it's available. + Spills.addAvailable(SSorRMId, Phys); + + CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse); + UpdateKills(*CopyMI, TRI, RegKills, KillOps); + + DEBUG(dbgs() << '\t' << *CopyMI); + ++NumCopified; + continue; + } + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MII, MBB->begin(), Phys, TRI, DoReMat, SSorRMId, TII, + *MBB->getParent()); + + if (VRM->isReMaterialized(VirtReg)) { + ReMaterialize(*MBB, InsertLoc, Phys, VirtReg, TII, TRI, *VRM); + } else { + const TargetRegisterClass* RC = MRI->getRegClass(VirtReg); + TII->loadRegFromStackSlot(*MBB, InsertLoc, Phys, SSorRMId, RC, TRI); + MachineInstr *LoadMI = prior(InsertLoc); + VRM->addSpillSlotUse(SSorRMId, LoadMI); + ++NumLoads; + DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size())); + } + + // This invalidates Phys. + Spills.ClobberPhysReg(Phys); + // Remember it's available. + Spills.addAvailable(SSorRMId, Phys); + + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(dbgs() << '\t' << *prior(MII)); + } + return true; +} + +/// InsertSpills - Insert spills after MI if requested by VRM. Return +/// true if spills were inserted. +bool LocalRewriter::InsertSpills(MachineInstr *MI) { + if (!VRM->isSpillPt(MI)) + return false; + MachineBasicBlock::iterator MII = MI; + std::vector > &SpillRegs = + VRM->getSpillPtSpills(MI); + for (unsigned i = 0, e = SpillRegs.size(); i != e; ++i) { + unsigned VirtReg = SpillRegs[i].first; + bool isKill = SpillRegs[i].second; + if (!VRM->getPreSplitReg(VirtReg)) + continue; // Split interval spilled again. + const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); + unsigned Phys = VRM->getPhys(VirtReg); + int StackSlot = VRM->getStackSlot(VirtReg); + MachineBasicBlock::iterator oldNextMII = llvm::next(MII); + TII->storeRegToStackSlot(*MBB, llvm::next(MII), Phys, isKill, StackSlot, + RC, TRI); + MachineInstr *StoreMI = prior(oldNextMII); + VRM->addSpillSlotUse(StackSlot, StoreMI); + DEBUG(dbgs() << "Store:\t" << *StoreMI); + VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod); + } + return true; +} + + +/// ProcessUses - Process all of MI's spilled operands and all available +/// operands. +void LocalRewriter::ProcessUses(MachineInstr &MI, AvailableSpills &Spills, + std::vector &MaybeDeadStores, + BitVector &RegKills, + ReuseInfo &ReusedOperands, + std::vector &KillOps) { + // Clear kill info. + SmallSet KilledMIRegs; + SmallVector VirtUseOps; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.getReg() == 0) + continue; // Ignore non-register operands. + + unsigned VirtReg = MO.getReg(); + + if (TargetRegisterInfo::isPhysicalRegister(VirtReg)) { + // Ignore physregs for spilling, but remember that it is used by this + // function. + MRI->setPhysRegUsed(VirtReg); + continue; + } + + // We want to process implicit virtual register uses first. + if (MO.isImplicit()) + // If the virtual register is implicitly defined, emit a implicit_def + // before so scavenger knows it's "defined". + // FIXME: This is a horrible hack done the by register allocator to + // remat a definition with virtual register operand. + VirtUseOps.insert(VirtUseOps.begin(), i); + else + VirtUseOps.push_back(i); + + // A partial def causes problems because the same operand both reads and + // writes the register. This rewriter is designed to rewrite uses and defs + // separately, so a partial def would already have been rewritten to a + // physreg by the time we get to processing defs. + // Add an implicit use operand to model the partial def. + if (MO.isDef() && MO.getSubReg() && MI.readsVirtualRegister(VirtReg) && + MI.findRegisterUseOperandIdx(VirtReg) == -1) { + VirtUseOps.insert(VirtUseOps.begin(), MI.getNumOperands()); + MI.addOperand(MachineOperand::CreateReg(VirtReg, + false, // isDef + true)); // isImplicit + DEBUG(dbgs() << "Partial redef: " << MI); + } + } + + // Process all of the spilled uses and all non spilled reg references. + SmallVector PotentialDeadStoreSlots; + KilledMIRegs.clear(); + for (unsigned j = 0, e = VirtUseOps.size(); j != e; ++j) { + unsigned i = VirtUseOps[j]; + unsigned VirtReg = MI.getOperand(i).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && + "Not a virtual register?"); + + unsigned SubIdx = MI.getOperand(i).getSubReg(); + if (VRM->isAssignedReg(VirtReg)) { + // This virtual register was assigned a physreg! + unsigned Phys = VRM->getPhys(VirtReg); + MRI->setPhysRegUsed(Phys); + if (MI.getOperand(i).isDef()) + ReusedOperands.markClobbered(Phys); + substitutePhysReg(MI.getOperand(i), Phys, *TRI); + if (VRM->isImplicitlyDefined(VirtReg)) + // FIXME: Is this needed? + BuildMI(*MBB, &MI, MI.getDebugLoc(), + TII->get(TargetOpcode::IMPLICIT_DEF), Phys); + continue; + } + + // This virtual register is now known to be a spilled value. + if (!MI.getOperand(i).isUse()) + continue; // Handle defs in the loop below (handle use&def here though) + + bool AvoidReload = MI.getOperand(i).isUndef(); + // Check if it is defined by an implicit def. It should not be spilled. + // Note, this is for correctness reason. e.g. + // 8 %reg1024 = IMPLICIT_DEF + // 12 %reg1024 = INSERT_SUBREG %reg1024, %reg1025, 2 + // The live range [12, 14) are not part of the r1024 live interval since + // it's defined by an implicit def. It will not conflicts with live + // interval of r1025. Now suppose both registers are spilled, you can + // easily see a situation where both registers are reloaded before + // the INSERT_SUBREG and both target registers that would overlap. + bool DoReMat = VRM->isReMaterialized(VirtReg); + int SSorRMId = DoReMat + ? VRM->getReMatId(VirtReg) : VRM->getStackSlot(VirtReg); + int ReuseSlot = SSorRMId; + + // Check to see if this stack slot is available. + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId); + + // If this is a sub-register use, make sure the reuse register is in the + // right register class. For example, for x86 not all of the 32-bit + // registers have accessible sub-registers. + // Similarly so for EXTRACT_SUBREG. Consider this: + // EDI = op + // MOV32_mr fi#1, EDI + // ... + // = EXTRACT_SUBREG fi#1 + // fi#1 is available in EDI, but it cannot be reused because it's not in + // the right register file. + if (PhysReg && !AvoidReload && SubIdx) { + const TargetRegisterClass* RC = MRI->getRegClass(VirtReg); + if (!RC->contains(PhysReg)) + PhysReg = 0; + } + + if (PhysReg && !AvoidReload) { + // This spilled operand might be part of a two-address operand. If this + // is the case, then changing it will necessarily require changing the + // def part of the instruction as well. However, in some cases, we + // aren't allowed to modify the reused register. If none of these cases + // apply, reuse it. + bool CanReuse = true; + bool isTied = MI.isRegTiedToDefOperand(i); + if (isTied) { + // Okay, we have a two address operand. We can reuse this physreg as + // long as we are allowed to clobber the value and there isn't an + // earlier def that has already clobbered the physreg. + CanReuse = !ReusedOperands.isClobbered(PhysReg) && + Spills.canClobberPhysReg(PhysReg); + } + // If this is an asm, and a PhysReg alias is used elsewhere as an + // earlyclobber operand, we can't also use it as an input. + if (MI.isInlineAsm()) { + for (unsigned k = 0, e = MI.getNumOperands(); k != e; ++k) { + MachineOperand &MOk = MI.getOperand(k); + if (MOk.isReg() && MOk.isEarlyClobber() && + TRI->regsOverlap(MOk.getReg(), PhysReg)) { + CanReuse = false; + DEBUG(dbgs() << "Not reusing physreg " << TRI->getName(PhysReg) + << " for vreg" << VirtReg << ": " << MOk << '\n'); + break; + } + } + } + + if (CanReuse) { + // If this stack slot value is already available, reuse it! + if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT) + DEBUG(dbgs() << "Reusing RM#" + << ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(dbgs() << "Reusing SS#" << ReuseSlot); + DEBUG(dbgs() << " from physreg " + << TRI->getName(PhysReg) << " for vreg" + << VirtReg <<" instead of reloading into physreg " + << TRI->getName(VRM->getPhys(VirtReg)) << '\n'); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + + // Reusing a physreg may resurrect it. But we expect ProcessUses to + // update the kill flags for the current instr after processing it. + + // The only technical detail we have is that we don't know that + // PhysReg won't be clobbered by a reloaded stack slot that occurs + // later in the instruction. In particular, consider 'op V1, V2'. + // If V1 is available in physreg R0, we would choose to reuse it + // here, instead of reloading it into the register the allocator + // indicated (say R1). However, V2 might have to be reloaded + // later, and it might indicate that it needs to live in R0. When + // this occurs, we need to have information available that + // indicates it is safe to use R1 for the reload instead of R0. + // + // To further complicate matters, we might conflict with an alias, + // or R0 and R1 might not be compatible with each other. In this + // case, we actually insert a reload for V1 in R1, ensuring that + // we can get at R0 or its alias. + ReusedOperands.addReuse(i, ReuseSlot, PhysReg, + VRM->getPhys(VirtReg), VirtReg); + if (isTied) + // Only mark it clobbered if this is a use&def operand. + ReusedOperands.markClobbered(PhysReg); + ++NumReused; + + if (MI.getOperand(i).isKill() && + ReuseSlot <= VirtRegMap::MAX_STACK_SLOT) { + + // The store of this spilled value is potentially dead, but we + // won't know for certain until we've confirmed that the re-use + // above is valid, which means waiting until the other operands + // are processed. For now we just track the spill slot, we'll + // remove it after the other operands are processed if valid. + + PotentialDeadStoreSlots.push_back(ReuseSlot); + } + + // Mark is isKill if it's there no other uses of the same virtual + // register and it's not a two-address operand. IsKill will be + // unset if reg is reused. + if (!isTied && KilledMIRegs.count(VirtReg) == 0) { + MI.getOperand(i).setIsKill(); + KilledMIRegs.insert(VirtReg); + } + continue; + } // CanReuse + + // Otherwise we have a situation where we have a two-address instruction + // whose mod/ref operand needs to be reloaded. This reload is already + // available in some register "PhysReg", but if we used PhysReg as the + // operand to our 2-addr instruction, the instruction would modify + // PhysReg. This isn't cool if something later uses PhysReg and expects + // to get its initial value. + // + // To avoid this problem, and to avoid doing a load right after a store, + // we emit a copy from PhysReg into the designated register for this + // operand. + // + // This case also applies to an earlyclobber'd PhysReg. + unsigned DesignatedReg = VRM->getPhys(VirtReg); + assert(DesignatedReg && "Must map virtreg to physreg!"); + + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (ReusedOperands.hasReuses()) + DesignatedReg = ReusedOperands. + GetRegForReload(VirtReg, DesignatedReg, &MI, Spills, + MaybeDeadStores, RegKills, KillOps, *VRM); + + // If the mapped designated register is actually the physreg we have + // incoming, we don't need to inserted a dead copy. + if (DesignatedReg == PhysReg) { + // If this stack slot value is already available, reuse it! + if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT) + DEBUG(dbgs() << "Reusing RM#" + << ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1); + else + DEBUG(dbgs() << "Reusing SS#" << ReuseSlot); + DEBUG(dbgs() << " from physreg " << TRI->getName(PhysReg) + << " for vreg" << VirtReg + << " instead of reloading into same physreg.\n"); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + ReusedOperands.markClobbered(RReg); + ++NumReused; + continue; + } + + MRI->setPhysRegUsed(DesignatedReg); + ReusedOperands.markClobbered(DesignatedReg); + + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(&MI, MBB->begin(), PhysReg, TRI, DoReMat, + SSorRMId, TII, *MBB->getParent()); + MachineInstr *CopyMI = BuildMI(*MBB, InsertLoc, MI.getDebugLoc(), + TII->get(TargetOpcode::COPY), + DesignatedReg).addReg(PhysReg); + CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse); + UpdateKills(*CopyMI, TRI, RegKills, KillOps); + + // This invalidates DesignatedReg. + Spills.ClobberPhysReg(DesignatedReg); + + Spills.addAvailable(ReuseSlot, DesignatedReg); + unsigned RReg = + SubIdx ? TRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + DEBUG(dbgs() << '\t' << *prior(InsertLoc)); + ++NumReused; + continue; + } // if (PhysReg) + + // Otherwise, reload it and remember that we have it. + PhysReg = VRM->getPhys(VirtReg); + assert(PhysReg && "Must map virtreg to physreg!"); + + // Note that, if we reused a register for a previous operand, the + // register we want to reload into might not actually be + // available. If this occurs, use the register indicated by the + // reuser. + if (ReusedOperands.hasReuses()) + PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI, + Spills, MaybeDeadStores, RegKills, KillOps, *VRM); + + MRI->setPhysRegUsed(PhysReg); + ReusedOperands.markClobbered(PhysReg); + if (AvoidReload) + ++NumAvoided; + else { + // Back-schedule reloads and remats. + MachineBasicBlock::iterator InsertLoc = + ComputeReloadLoc(MI, MBB->begin(), PhysReg, TRI, DoReMat, + SSorRMId, TII, *MBB->getParent()); + + if (DoReMat) { + ReMaterialize(*MBB, InsertLoc, PhysReg, VirtReg, TII, TRI, *VRM); + } else { + const TargetRegisterClass* RC = MRI->getRegClass(VirtReg); + TII->loadRegFromStackSlot(*MBB, InsertLoc, PhysReg, SSorRMId, RC,TRI); + MachineInstr *LoadMI = prior(InsertLoc); + VRM->addSpillSlotUse(SSorRMId, LoadMI); + ++NumLoads; + DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size())); + } + // This invalidates PhysReg. + Spills.ClobberPhysReg(PhysReg); + + // Any stores to this stack slot are not dead anymore. + if (!DoReMat) + MaybeDeadStores[SSorRMId] = NULL; + Spills.addAvailable(SSorRMId, PhysReg); + // Assumes this is the last use. IsKill will be unset if reg is reused + // unless it's a two-address operand. + if (!MI.isRegTiedToDefOperand(i) && + KilledMIRegs.count(VirtReg) == 0) { + MI.getOperand(i).setIsKill(); + KilledMIRegs.insert(VirtReg); + } + + UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps); + DEBUG(dbgs() << '\t' << *prior(InsertLoc)); + } + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + } + + // Ok - now we can remove stores that have been confirmed dead. + for (unsigned j = 0, e = PotentialDeadStoreSlots.size(); j != e; ++j) { + // This was the last use and the spilled value is still available + // for reuse. That means the spill was unnecessary! + int PDSSlot = PotentialDeadStoreSlots[j]; + MachineInstr* DeadStore = MaybeDeadStores[PDSSlot]; + if (DeadStore) { + DEBUG(dbgs() << "Removed dead store:\t" << *DeadStore); + InvalidateKills(*DeadStore, TRI, RegKills, KillOps); + EraseInstr(DeadStore); + MaybeDeadStores[PDSSlot] = NULL; + ++NumDSE; + } + } +} + +/// rewriteMBB - Keep track of which spills are available even after the +/// register allocator is done with them. If possible, avoid reloading vregs. +void +LocalRewriter::RewriteMBB(LiveIntervals *LIs, + AvailableSpills &Spills, BitVector &RegKills, + std::vector &KillOps) { + + DEBUG(dbgs() << "\n**** Local spiller rewriting MBB '" + << MBB->getName() << "':\n"); + + MachineFunction &MF = *MBB->getParent(); + + // MaybeDeadStores - When we need to write a value back into a stack slot, + // keep track of the inserted store. If the stack slot value is never read + // (because the value was used from some available register, for example), and + // subsequently stored to, the original store is dead. This map keeps track + // of inserted stores that are not used. If we see a subsequent store to the + // same stack slot, the original store is deleted. + std::vector MaybeDeadStores; + MaybeDeadStores.resize(MF.getFrameInfo()->getObjectIndexEnd(), NULL); + + // ReMatDefs - These are rematerializable def MIs which are not deleted. + SmallSet ReMatDefs; + + // Keep track of the registers we have already spilled in case there are + // multiple defs of the same register in MI. + SmallSet SpilledMIRegs; + + RegKills.reset(); + KillOps.clear(); + KillOps.resize(TRI->getNumRegs(), NULL); + + DistanceMap.clear(); + for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); + MII != E; ) { + MachineBasicBlock::iterator NextMII = llvm::next(MII); + + if (OptimizeByUnfold(MII, MaybeDeadStores, Spills, RegKills, KillOps)) + NextMII = llvm::next(MII); + + if (InsertEmergencySpills(MII)) + NextMII = llvm::next(MII); + + InsertRestores(MII, Spills, RegKills, KillOps); + + if (InsertSpills(MII)) + NextMII = llvm::next(MII); + + bool Erased = false; + bool BackTracked = false; + MachineInstr &MI = *MII; + + // Remember DbgValue's which reference stack slots. + if (MI.isDebugValue() && MI.getOperand(0).isFI()) + Slot2DbgValues[MI.getOperand(0).getIndex()].push_back(&MI); + + /// ReusedOperands - Keep track of operand reuse in case we need to undo + /// reuse. + ReuseInfo ReusedOperands(MI, TRI); + + ProcessUses(MI, Spills, MaybeDeadStores, RegKills, ReusedOperands, KillOps); + + DEBUG(dbgs() << '\t' << MI); + + + // If we have folded references to memory operands, make sure we clear all + // physical registers that may contain the value of the spilled virtual + // register + + // Copy the folded virts to a small vector, we may change MI2VirtMap. + SmallVector, 4> FoldedVirts; + // C++0x FTW! + for (std::pair FVRange = + VRM->getFoldedVirts(&MI); + FVRange.first != FVRange.second; ++FVRange.first) + FoldedVirts.push_back(FVRange.first->second); + + SmallSet FoldedSS; + for (unsigned FVI = 0, FVE = FoldedVirts.size(); FVI != FVE; ++FVI) { + unsigned VirtReg = FoldedVirts[FVI].first; + VirtRegMap::ModRef MR = FoldedVirts[FVI].second; + DEBUG(dbgs() << "Folded vreg: " << VirtReg << " MR: " << MR); + + int SS = VRM->getStackSlot(VirtReg); + if (SS == VirtRegMap::NO_STACK_SLOT) + continue; + FoldedSS.insert(SS); + DEBUG(dbgs() << " - StackSlot: " << SS << "\n"); + + // If this folded instruction is just a use, check to see if it's a + // straight load from the virt reg slot. + if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) { + int FrameIdx; + unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx); + if (DestReg && FrameIdx == SS) { + // If this spill slot is available, turn it into a copy (or nothing) + // instead of leaving it as a load! + if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) { + DEBUG(dbgs() << "Promoted Load To Copy: " << MI); + if (DestReg != InReg) { + MachineOperand *DefMO = MI.findRegisterDefOperand(DestReg); + MachineInstr *CopyMI = BuildMI(*MBB, &MI, MI.getDebugLoc(), + TII->get(TargetOpcode::COPY)) + .addReg(DestReg, RegState::Define, DefMO->getSubReg()) + .addReg(InReg, RegState::Kill); + // Revisit the copy so we make sure to notice the effects of the + // operation on the destreg (either needing to RA it if it's + // virtual or needing to clobber any values if it's physical). + NextMII = CopyMI; + NextMII->setAsmPrinterFlag(MachineInstr::ReloadReuse); + BackTracked = true; + } else { + DEBUG(dbgs() << "Removing now-noop copy: " << MI); + // InvalidateKills resurrects any prior kill of the copy's source + // allowing the source reg to be reused in place of the copy. + Spills.disallowClobberPhysReg(InReg); + } + + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + Erased = true; + goto ProcessNextInst; + } + } else { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + SmallVector NewMIs; + if (PhysReg && + TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, false, NewMIs)){ + MBB->insert(MII, NewMIs[0]); + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + Erased = true; + --NextMII; // backtrack to the unfolded instruction. + BackTracked = true; + goto ProcessNextInst; + } + } + } + + // If this reference is not a use, any previous store is now dead. + // Otherwise, the store to this stack slot is not dead anymore. + MachineInstr* DeadStore = MaybeDeadStores[SS]; + if (DeadStore) { + bool isDead = !(MR & VirtRegMap::isRef); + MachineInstr *NewStore = NULL; + if (MR & VirtRegMap::isModRef) { + unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS); + SmallVector NewMIs; + // We can reuse this physreg as long as we are allowed to clobber + // the value and there isn't an earlier def that has already clobbered + // the physreg. + if (PhysReg && + !ReusedOperands.isClobbered(PhysReg) && + Spills.canClobberPhysReg(PhysReg) && + !TII->isStoreToStackSlot(&MI, SS)) { // Not profitable! + MachineOperand *KillOpnd = + DeadStore->findRegisterUseOperand(PhysReg, true); + // Note, if the store is storing a sub-register, it's possible the + // super-register is needed below. + if (KillOpnd && !KillOpnd->getSubReg() && + TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, true,NewMIs)){ + MBB->insert(MII, NewMIs[0]); + NewStore = NewMIs[1]; + MBB->insert(MII, NewStore); + VRM->addSpillSlotUse(SS, NewStore); + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + Erased = true; + --NextMII; + --NextMII; // backtrack to the unfolded instruction. + BackTracked = true; + isDead = true; + ++NumSUnfold; + } + } + } + + if (isDead) { // Previous store is dead. + // If we get here, the store is dead, nuke it now. + DEBUG(dbgs() << "Removed dead store:\t" << *DeadStore); + InvalidateKills(*DeadStore, TRI, RegKills, KillOps); + EraseInstr(DeadStore); + if (!NewStore) + ++NumDSE; + } + + MaybeDeadStores[SS] = NULL; + if (NewStore) { + // Treat this store as a spill merged into a copy. That makes the + // stack slot value available. + VRM->virtFolded(VirtReg, NewStore, VirtRegMap::isMod); + goto ProcessNextInst; + } + } + + // If the spill slot value is available, and this is a new definition of + // the value, the value is not available anymore. + if (MR & VirtRegMap::isMod) { + // Notice that the value in this stack slot has been modified. + Spills.ModifyStackSlotOrReMat(SS); + + // If this is *just* a mod of the value, check to see if this is just a + // store to the spill slot (i.e. the spill got merged into the copy). If + // so, realize that the vreg is available now, and add the store to the + // MaybeDeadStore info. + int StackSlot; + if (!(MR & VirtRegMap::isRef)) { + if (unsigned SrcReg = TII->isStoreToStackSlot(&MI, StackSlot)) { + assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) && + "Src hasn't been allocated yet?"); + + if (CommuteToFoldReload(MII, VirtReg, SrcReg, StackSlot, + Spills, RegKills, KillOps, TRI)) { + NextMII = llvm::next(MII); + BackTracked = true; + goto ProcessNextInst; + } + + // Okay, this is certainly a store of SrcReg to [StackSlot]. Mark + // this as a potentially dead store in case there is a subsequent + // store into the stack slot without a read from it. + MaybeDeadStores[StackSlot] = &MI; + + // If the stack slot value was previously available in some other + // register, change it now. Otherwise, make the register + // available in PhysReg. + Spills.addAvailable(StackSlot, SrcReg, MI.killsRegister(SrcReg)); + } + } + } + } + + // Process all of the spilled defs. + SpilledMIRegs.clear(); + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI.getOperand(i); + if (!(MO.isReg() && MO.getReg() && MO.isDef())) + continue; + + unsigned VirtReg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(VirtReg)) { + // Check to see if this is a noop copy. If so, eliminate the + // instruction before considering the dest reg to be changed. + // Also check if it's copying from an "undef", if so, we can't + // eliminate this or else the undef marker is lost and it will + // confuses the scavenger. This is extremely rare. + if (MI.isIdentityCopy() && !MI.getOperand(1).isUndef() && + MI.getNumOperands() == 2) { + ++NumDCE; + DEBUG(dbgs() << "Removing now-noop copy: " << MI); + SmallVector KillRegs; + InvalidateKills(MI, TRI, RegKills, KillOps, &KillRegs); + if (MO.isDead() && !KillRegs.empty()) { + // Source register or an implicit super/sub-register use is killed. + assert(TRI->regsOverlap(KillRegs[0], MI.getOperand(0).getReg())); + // Last def is now dead. + TransferDeadness(MI.getOperand(1).getReg(), RegKills, KillOps); + } + EraseInstr(&MI); + Erased = true; + Spills.disallowClobberPhysReg(VirtReg); + goto ProcessNextInst; + } + + // If it's not a no-op copy, it clobbers the value in the destreg. + Spills.ClobberPhysReg(VirtReg); + ReusedOperands.markClobbered(VirtReg); + + // Check to see if this instruction is a load from a stack slot into + // a register. If so, this provides the stack slot value in the reg. + int FrameIdx; + if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) { + assert(DestReg == VirtReg && "Unknown load situation!"); + + // If it is a folded reference, then it's not safe to clobber. + bool Folded = FoldedSS.count(FrameIdx); + // Otherwise, if it wasn't available, remember that it is now! + Spills.addAvailable(FrameIdx, DestReg, !Folded); + goto ProcessNextInst; + } + + continue; + } + + unsigned SubIdx = MO.getSubReg(); + bool DoReMat = VRM->isReMaterialized(VirtReg); + if (DoReMat) + ReMatDefs.insert(&MI); + + // The only vregs left are stack slot definitions. + int StackSlot = VRM->getStackSlot(VirtReg); + const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); + + // If this def is part of a two-address operand, make sure to execute + // the store from the correct physical register. + unsigned PhysReg; + unsigned TiedOp; + if (MI.isRegTiedToUseOperand(i, &TiedOp)) { + PhysReg = MI.getOperand(TiedOp).getReg(); + if (SubIdx) { + unsigned SuperReg = findSuperReg(RC, PhysReg, SubIdx, TRI); + assert(SuperReg && TRI->getSubReg(SuperReg, SubIdx) == PhysReg && + "Can't find corresponding super-register!"); + PhysReg = SuperReg; + } + } else { + PhysReg = VRM->getPhys(VirtReg); + if (ReusedOperands.isClobbered(PhysReg)) { + // Another def has taken the assigned physreg. It must have been a + // use&def which got it due to reuse. Undo the reuse! + PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI, + Spills, MaybeDeadStores, RegKills, KillOps, *VRM); + } + } + + assert(PhysReg && "VR not assigned a physical register?"); + MRI->setPhysRegUsed(PhysReg); + unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg; + ReusedOperands.markClobbered(RReg); + MI.getOperand(i).setReg(RReg); + MI.getOperand(i).setSubReg(0); + + if (!MO.isDead() && SpilledMIRegs.insert(VirtReg)) { + MachineInstr *&LastStore = MaybeDeadStores[StackSlot]; + SpillRegToStackSlot(MII, -1, PhysReg, StackSlot, RC, true, + LastStore, Spills, ReMatDefs, RegKills, KillOps); + NextMII = llvm::next(MII); + + // Check to see if this is a noop copy. If so, eliminate the + // instruction before considering the dest reg to be changed. + if (MI.isIdentityCopy()) { + ++NumDCE; + DEBUG(dbgs() << "Removing now-noop copy: " << MI); + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + Erased = true; + UpdateKills(*LastStore, TRI, RegKills, KillOps); + goto ProcessNextInst; + } + } + } + ProcessNextInst: + // Delete dead instructions without side effects. + if (!Erased && !BackTracked && isSafeToDelete(MI)) { + InvalidateKills(MI, TRI, RegKills, KillOps); + EraseInstr(&MI); + Erased = true; + } + if (!Erased) + DistanceMap.insert(std::make_pair(&MI, DistanceMap.size())); + if (!Erased && !BackTracked) { + for (MachineBasicBlock::iterator II = &MI; II != NextMII; ++II) + UpdateKills(*II, TRI, RegKills, KillOps); + } + MII = NextMII; + } + +} + +llvm::VirtRegRewriter* llvm::createVirtRegRewriter() { + switch (RewriterOpt) { + default: llvm_unreachable("Unreachable!"); + case local: + return new LocalRewriter(); + case trivial: + return new TrivialRewriter(); + } +} diff --git a/final/lib/CodeGen/VirtRegRewriter.h b/final/lib/CodeGen/VirtRegRewriter.h new file mode 100644 index 00000000000..93474e0d7ff --- /dev/null +++ b/final/lib/CodeGen/VirtRegRewriter.h @@ -0,0 +1,32 @@ +//===-- llvm/CodeGen/VirtRegRewriter.h - VirtRegRewriter -*- C++ -*--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VIRTREGREWRITER_H +#define LLVM_CODEGEN_VIRTREGREWRITER_H + +namespace llvm { + class LiveIntervals; + class MachineFunction; + class VirtRegMap; + + /// VirtRegRewriter interface: Implementations of this interface assign + /// spilled virtual registers to stack slots, rewriting the code. + struct VirtRegRewriter { + virtual ~VirtRegRewriter(); + virtual bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) = 0; + }; + + /// createVirtRegRewriter - Create an return a rewriter object, as specified + /// on the command line. + VirtRegRewriter* createVirtRegRewriter(); + +} + +#endif diff --git a/final/lib/CompilerDriver/Action.cpp b/final/lib/CompilerDriver/Action.cpp new file mode 100644 index 00000000000..a8d625c7ac0 --- /dev/null +++ b/final/lib/CompilerDriver/Action.cpp @@ -0,0 +1,134 @@ +//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Action class - implementation and auxiliary functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/Action.h" +#include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/Error.h" +#include "llvm/CompilerDriver/Main.h" + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/TimeValue.h" + +#include +#include + +using namespace llvm; +using namespace llvmc; + +namespace llvmc { + +extern const char* ProgramName; + +} + +namespace { + + void PrintString (const std::string& str) { + errs() << str << ' '; + } + + void PrintCommand (const std::string& Cmd, const StrVector& Args) { + errs() << Cmd << ' '; + std::for_each(Args.begin(), Args.end(), &PrintString); + errs() << '\n'; + } + + bool IsSegmentationFault (int returnCode) { +#ifdef LLVM_ON_WIN32 + return (returnCode >= 0xc0000000UL) +#else + return (returnCode < 0); +#endif + } + + int ExecuteProgram (const std::string& name, const StrVector& args) { + sys::Path prog(name); + + if (sys::path::is_relative(prog.str())) { + prog = PrependMainExecutablePath(name, ProgramName, + (void *)(intptr_t)&Main); + + if (!prog.canExecute()) { + prog = sys::Program::FindProgramByName(name); + if (prog.isEmpty()) { + PrintError("Can't find program '" + name + "'"); + return -1; + } + } + } + if (!prog.canExecute()) { + PrintError("Program '" + name + "' is not executable."); + return -1; + } + + // Build the command line vector and the redirects array. + const sys::Path* redirects[3] = {0,0,0}; + sys::Path stdout_redirect; + + std::vector argv; + argv.reserve((args.size()+2)); + argv.push_back(name.c_str()); + + for (StrVector::const_iterator B = args.begin(), E = args.end(); + B!=E; ++B) { + if (*B == ">") { + ++B; + stdout_redirect.set(*B); + redirects[1] = &stdout_redirect; + } + else { + argv.push_back((*B).c_str()); + } + } + argv.push_back(0); // null terminate list. + + // Invoke the program. + int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]); + + if (IsSegmentationFault(ret)) { + errs() << "Segmentation fault: "; + PrintCommand(name, args); + } + + return ret; + } +} + +namespace llvmc { + void AppendToGlobalTimeLog (const std::string& cmd, double time); +} + +int llvmc::Action::Execute () const { + if (DryRun || VerboseMode) + PrintCommand(Command_, Args_); + + if (!DryRun) { + if (Time) { + sys::TimeValue now = sys::TimeValue::now(); + int ret = ExecuteProgram(Command_, Args_); + sys::TimeValue now2 = sys::TimeValue::now(); + now2 -= now; + double elapsed = now2.seconds() + now2.microseconds() / 1000000.0; + AppendToGlobalTimeLog(Command_, elapsed); + + return ret; + } + else { + return ExecuteProgram(Command_, Args_); + } + } + + return 0; +} diff --git a/final/lib/CompilerDriver/BuiltinOptions.cpp b/final/lib/CompilerDriver/BuiltinOptions.cpp new file mode 100644 index 00000000000..38442038d73 --- /dev/null +++ b/final/lib/CompilerDriver/BuiltinOptions.cpp @@ -0,0 +1,61 @@ +//===--- BuiltinOptions.cpp - The LLVM Compiler Driver ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Definitions of all global command-line option variables. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/BuiltinOptions.h" + +#ifdef ENABLE_LLVMC_DYNAMIC_PLUGINS +#include "llvm/Support/PluginLoader.h" +#endif + +namespace cl = llvm::cl; + +namespace llvmc { + +cl::list InputFilenames(cl::Positional, cl::desc(""), + cl::ZeroOrMore); +cl::opt OutputFilename("o", cl::desc("Output file name"), + cl::value_desc("file"), cl::Prefix); +cl::opt TempDirname("temp-dir", cl::desc("Temp dir name"), + cl::value_desc(""), cl::Prefix); +cl::list Languages("x", + cl::desc("Specify the language of the following input files"), + cl::ZeroOrMore); + +cl::opt DryRun("dry-run", + cl::desc("Only pretend to run commands")); +cl::opt Time("time", cl::desc("Time individual commands")); +cl::opt VerboseMode("v", + cl::desc("Enable verbose mode")); + +cl::opt CheckGraph("check-graph", + cl::desc("Check the compilation graph for errors"), + cl::Hidden); +cl::opt WriteGraph("write-graph", + cl::desc("Write compilation-graph.dot file"), + cl::Hidden); +cl::opt ViewGraph("view-graph", + cl::desc("Show compilation graph in GhostView"), + cl::Hidden); + +cl::opt SaveTemps +("save-temps", cl::desc("Keep temporary files"), + cl::init(SaveTempsEnum::Unset), + cl::values(clEnumValN(SaveTempsEnum::Obj, "obj", + "Save files in the directory specified with -o"), + clEnumValN(SaveTempsEnum::Cwd, "cwd", + "Use current working directory"), + clEnumValN(SaveTempsEnum::Obj, "", "Same as 'cwd'"), + clEnumValEnd), + cl::ValueOptional); + +} // End namespace llvmc. diff --git a/final/lib/CompilerDriver/CMakeLists.txt b/final/lib/CompilerDriver/CMakeLists.txt new file mode 100644 index 00000000000..2248de01b95 --- /dev/null +++ b/final/lib/CompilerDriver/CMakeLists.txt @@ -0,0 +1,10 @@ +set(LLVM_LINK_COMPONENTS support) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvmc + Action.cpp + CompilationGraph.cpp + llvmc.cpp + Plugin.cpp + Tool.cpp + ) diff --git a/final/lib/CompilerDriver/CompilationGraph.cpp b/final/lib/CompilerDriver/CompilationGraph.cpp new file mode 100644 index 00000000000..33c6566499b --- /dev/null +++ b/final/lib/CompilerDriver/CompilationGraph.cpp @@ -0,0 +1,655 @@ +//===--- CompilationGraph.cpp - The LLVM Compiler Driver --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Compilation graph - implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/CompilationGraph.h" +#include "llvm/CompilerDriver/Error.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvmc; + +namespace llvmc { + + const std::string* LanguageMap::GetLanguage(const sys::Path& File) const { + // Remove the '.'. + StringRef suf = sys::path::extension(File.str()).substr(1); + LanguageMap::const_iterator Lang = + this->find(suf.empty() ? "*empty*" : suf); + if (Lang == this->end()) { + PrintError("File '" + File.str() + "' has unknown suffix '" + + suf.str() + '\''); + return 0; + } + return &Lang->second; + } +} + +namespace { + + /// ChooseEdge - Return the edge with the maximum weight. Returns 0 on error. + template + const Edge* ChooseEdge(const C& EdgesContainer, + const InputLanguagesSet& InLangs, + const std::string& NodeName = "root") { + const Edge* MaxEdge = 0; + int MaxWeight = 0; + bool SingleMax = true; + + // TODO: fix calculation of SingleMax. + for (typename C::const_iterator B = EdgesContainer.begin(), + E = EdgesContainer.end(); B != E; ++B) { + const Edge* e = B->getPtr(); + int EW = e->Weight(InLangs); + if (EW < 0) { + // (error) invocation in TableGen -> we don't need to print an error + // message. + return 0; + } + if (EW > MaxWeight) { + MaxEdge = e; + MaxWeight = EW; + SingleMax = true; + } else if (EW == MaxWeight) { + SingleMax = false; + } + } + + if (!SingleMax) { + PrintError("Node " + NodeName + ": multiple maximal outward edges found!" + " Most probably a specification error."); + return 0; + } + if (!MaxEdge) { + PrintError("Node " + NodeName + ": no maximal outward edge found!" + " Most probably a specification error."); + return 0; + } + return MaxEdge; + } + +} + +void Node::AddEdge(Edge* Edg) { + // If there already was an edge between two nodes, modify it instead + // of adding a new edge. + const std::string& ToolName = Edg->ToolName(); + for (container_type::iterator B = OutEdges.begin(), E = OutEdges.end(); + B != E; ++B) { + if ((*B)->ToolName() == ToolName) { + llvm::IntrusiveRefCntPtr(Edg).swap(*B); + return; + } + } + OutEdges.push_back(llvm::IntrusiveRefCntPtr(Edg)); +} + +CompilationGraph::CompilationGraph() { + NodesMap["root"] = Node(this); +} + +Node* CompilationGraph::getNode(const std::string& ToolName) { + nodes_map_type::iterator I = NodesMap.find(ToolName); + if (I == NodesMap.end()) { + PrintError("Node " + ToolName + " is not in the graph"); + return 0; + } + return &I->second; +} + +const Node* CompilationGraph::getNode(const std::string& ToolName) const { + nodes_map_type::const_iterator I = NodesMap.find(ToolName); + if (I == NodesMap.end()) { + PrintError("Node " + ToolName + " is not in the graph!"); + return 0; + } + return &I->second; +} + +// Find the tools list corresponding to the given language name. +const CompilationGraph::tools_vector_type* +CompilationGraph::getToolsVector(const std::string& LangName) const +{ + tools_map_type::const_iterator I = ToolsMap.find(LangName); + if (I == ToolsMap.end()) { + PrintError("No tool corresponding to the language " + LangName + " found"); + return 0; + } + return &I->second; +} + +void CompilationGraph::insertNode(Tool* V) { + if (NodesMap.count(V->Name()) == 0) + NodesMap[V->Name()] = Node(this, V); +} + +int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { + Node* B = getNode(Edg->ToolName()); + if (B == 0) + return 1; + + if (A == "root") { + const char** InLangs = B->ToolPtr->InputLanguages(); + for (;*InLangs; ++InLangs) + ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg)); + NodesMap["root"].AddEdge(Edg); + } + else { + Node* N = getNode(A); + if (N == 0) + return 1; + + N->AddEdge(Edg); + } + // Increase the inward edge counter. + B->IncrInEdges(); + + return 0; +} + +// Pass input file through the chain until we bump into a Join node or +// a node that says that it is the last. +int CompilationGraph::PassThroughGraph (const sys::Path& InFile, + const Node* StartNode, + const InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) const { + sys::Path In = InFile; + const Node* CurNode = StartNode; + + while(true) { + Tool* CurTool = CurNode->ToolPtr.getPtr(); + + if (CurTool->IsJoin()) { + JoinTool& JT = static_cast(*CurTool); + JT.AddToJoinList(In); + break; + } + + Action CurAction; + if (int ret = CurTool->GenerateAction(CurAction, In, CurNode->HasChildren(), + TempDir, InLangs, LangMap)) { + return ret; + } + + if (int ret = CurAction.Execute()) + return ret; + + if (CurAction.StopCompilation()) + return 0; + + const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); + if (Edg == 0) + return 1; + + CurNode = getNode(Edg->ToolName()); + if (CurNode == 0) + return 1; + + In = CurAction.OutFile(); + } + + return 0; +} + +// Find the head of the toolchain corresponding to the given file. +// Also, insert an input language into InLangs. +const Node* CompilationGraph:: +FindToolChain(const sys::Path& In, const std::string* ForceLanguage, + InputLanguagesSet& InLangs, const LanguageMap& LangMap) const { + + // Determine the input language. + const std::string* InLang = (ForceLanguage ? ForceLanguage + : LangMap.GetLanguage(In)); + if (InLang == 0) + return 0; + const std::string& InLanguage = *InLang; + + // Add the current input language to the input language set. + InLangs.insert(InLanguage); + + // Find the toolchain for the input language. + const tools_vector_type* pTV = getToolsVector(InLanguage); + if (pTV == 0) + return 0; + + const tools_vector_type& TV = *pTV; + if (TV.empty()) { + PrintError("No toolchain corresponding to language " + + InLanguage + " found"); + return 0; + } + + const Edge* Edg = ChooseEdge(TV, InLangs); + if (Edg == 0) + return 0; + + return getNode(Edg->ToolName()); +} + +// Helper function used by Build(). +// Traverses initial portions of the toolchains (up to the first Join node). +// This function is also responsible for handling the -x option. +int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) { + // This is related to -x option handling. + cl::list::const_iterator xIter = Languages.begin(), + xBegin = xIter, xEnd = Languages.end(); + bool xEmpty = true; + const std::string* xLanguage = 0; + unsigned xPos = 0, xPosNext = 0, filePos = 0; + + if (xIter != xEnd) { + xEmpty = false; + xPos = Languages.getPosition(xIter - xBegin); + cl::list::const_iterator xNext = llvm::next(xIter); + xPosNext = (xNext == xEnd) ? std::numeric_limits::max() + : Languages.getPosition(xNext - xBegin); + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + + // For each input file: + for (cl::list::const_iterator B = InputFilenames.begin(), + CB = B, E = InputFilenames.end(); B != E; ++B) { + sys::Path In = sys::Path(*B); + + // Code for handling the -x option. + // Output: std::string* xLanguage (can be NULL). + if (!xEmpty) { + filePos = InputFilenames.getPosition(B - CB); + + if (xPos < filePos) { + if (filePos < xPosNext) { + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + else { // filePos >= xPosNext + // Skip xIters while filePos > xPosNext + while (filePos > xPosNext) { + ++xIter; + xPos = xPosNext; + + cl::list::const_iterator xNext = llvm::next(xIter); + if (xNext == xEnd) + xPosNext = std::numeric_limits::max(); + else + xPosNext = Languages.getPosition(xNext - xBegin); + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + } + } + } + + // Find the toolchain corresponding to this file. + const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap); + if (N == 0) + return 1; + // Pass file through the chain starting at head. + if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap)) + return ret; + } + + return 0; +} + +// Sort the nodes in topological order. +int CompilationGraph::TopologicalSort(std::vector& Out) { + std::queue Q; + + Node* Root = getNode("root"); + if (Root == 0) + return 1; + + Q.push(Root); + + while (!Q.empty()) { + const Node* A = Q.front(); + Q.pop(); + Out.push_back(A); + for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); + EB != EE; ++EB) { + Node* B = getNode((*EB)->ToolName()); + if (B == 0) + return 1; + + B->DecrInEdges(); + if (B->HasNoInEdges()) + Q.push(B); + } + } + + return 0; +} + +namespace { + bool NotJoinNode(const Node* N) { + return N->ToolPtr ? !N->ToolPtr->IsJoin() : true; + } +} + +// Call TopologicalSort and filter the resulting list to include +// only Join nodes. +int CompilationGraph:: +TopologicalSortFilterJoinNodes(std::vector& Out) { + std::vector TopSorted; + if (int ret = TopologicalSort(TopSorted)) + return ret; + std::remove_copy_if(TopSorted.begin(), TopSorted.end(), + std::back_inserter(Out), NotJoinNode); + + return 0; +} + +int CompilationGraph::Build (const sys::Path& TempDir, + const LanguageMap& LangMap) { + InputLanguagesSet InLangs; + bool WasSomeActionGenerated = !InputFilenames.empty(); + + // Traverse initial parts of the toolchains and fill in InLangs. + if (int ret = BuildInitial(InLangs, TempDir, LangMap)) + return ret; + + std::vector JTV; + if (int ret = TopologicalSortFilterJoinNodes(JTV)) + return ret; + + // For all join nodes in topological order: + for (std::vector::iterator B = JTV.begin(), E = JTV.end(); + B != E; ++B) { + + const Node* CurNode = *B; + JoinTool* JT = &static_cast(*CurNode->ToolPtr.getPtr()); + + // Are there any files in the join list? + if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty())) + continue; + + WasSomeActionGenerated = true; + Action CurAction; + if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(), + TempDir, InLangs, LangMap)) { + return ret; + } + + if (int ret = CurAction.Execute()) + return ret; + + if (CurAction.StopCompilation()) + return 0; + + const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name()); + if (Edg == 0) + return 1; + + const Node* NextNode = getNode(Edg->ToolName()); + if (NextNode == 0) + return 1; + + if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode, + InLangs, TempDir, LangMap)) { + return ret; + } + } + + if (!WasSomeActionGenerated) { + PrintError("no input files"); + return 1; + } + + return 0; +} + +int CompilationGraph::CheckLanguageNames() const { + int ret = 0; + + // Check that names for output and input languages on all edges do match. + for (const_nodes_iterator B = this->NodesMap.begin(), + E = this->NodesMap.end(); B != E; ++B) { + + const Node & N1 = B->second; + if (N1.ToolPtr) { + for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd(); + EB != EE; ++EB) { + const Node* N2 = this->getNode((*EB)->ToolName()); + if (N2 == 0) + return 1; + + if (!N2->ToolPtr) { + ++ret; + errs() << "Error: there is an edge from '" << N1.ToolPtr->Name() + << "' back to the root!\n\n"; + continue; + } + + const char** OutLangs = N1.ToolPtr->OutputLanguages(); + const char** InLangs = N2->ToolPtr->InputLanguages(); + bool eq = false; + const char* OutLang = 0; + for (;*OutLangs; ++OutLangs) { + OutLang = *OutLangs; + for (;*InLangs; ++InLangs) { + if (std::strcmp(OutLang, *InLangs) == 0) { + eq = true; + break; + } + } + } + + if (!eq) { + ++ret; + errs() << "Error: Output->input language mismatch in the edge '" + << N1.ToolPtr->Name() << "' -> '" << N2->ToolPtr->Name() + << "'!\n" + << "Expected one of { "; + + InLangs = N2->ToolPtr->InputLanguages(); + for (;*InLangs; ++InLangs) { + errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'"); + } + + errs() << " }, but got '" << OutLang << "'!\n\n"; + } + + } + } + } + + return ret; +} + +int CompilationGraph::CheckMultipleDefaultEdges() const { + int ret = 0; + InputLanguagesSet Dummy; + + // For all nodes, just iterate over the outgoing edges and check if there is + // more than one edge with maximum weight. + for (const_nodes_iterator B = this->NodesMap.begin(), + E = this->NodesMap.end(); B != E; ++B) { + const Node& N = B->second; + int MaxWeight = -1024; + + // Ignore the root node. + if (!N.ToolPtr) + continue; + + for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd(); + EB != EE; ++EB) { + int EdgeWeight = (*EB)->Weight(Dummy); + if (EdgeWeight > MaxWeight) { + MaxWeight = EdgeWeight; + } + else if (EdgeWeight == MaxWeight) { + ++ret; + errs() << "Error: there are multiple maximal edges stemming from the '" + << N.ToolPtr->Name() << "' node!\n\n"; + break; + } + } + } + + return ret; +} + +int CompilationGraph::CheckCycles() { + unsigned deleted = 0; + std::queue Q; + + Node* Root = getNode("root"); + if (Root == 0) + return 1; + + Q.push(Root); + + // Try to delete all nodes that have no ingoing edges, starting from the + // root. If there are any nodes left after this operation, then we have a + // cycle. This relies on '--check-graph' not performing the topological sort. + while (!Q.empty()) { + Node* A = Q.front(); + Q.pop(); + ++deleted; + + for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); + EB != EE; ++EB) { + Node* B = getNode((*EB)->ToolName()); + if (B == 0) + return 1; + + B->DecrInEdges(); + if (B->HasNoInEdges()) + Q.push(B); + } + } + + if (deleted != NodesMap.size()) { + errs() << "Error: there are cycles in the compilation graph!\n" + << "Try inspecting the diagram produced by " + << "'llvmc --view-graph'.\n\n"; + return 1; + } + + return 0; +} + +int CompilationGraph::Check () { + // We try to catch as many errors as we can in one go. + int errs = 0; + int ret = 0; + + // Check that output/input language names match. + ret = this->CheckLanguageNames(); + if (ret < 0) + return 1; + errs += ret; + + // Check for multiple default edges. + ret = this->CheckMultipleDefaultEdges(); + if (ret < 0) + return 1; + errs += ret; + + // Check for cycles. + ret = this->CheckCycles(); + if (ret < 0) + return 1; + errs += ret; + + return errs; +} + +// Code related to graph visualization. + +namespace { + +std::string SquashStrArray (const char** StrArr) { + std::string ret; + + for (; *StrArr; ++StrArr) { + if (*(StrArr + 1)) { + ret += *StrArr; + ret += ", "; + } + else { + ret += *StrArr; + } + } + + return ret; +} + +} // End anonymous namespace. + +namespace llvm { + template <> + struct DOTGraphTraits + : public DefaultDOTGraphTraits + { + DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} + + template + static std::string getNodeLabel(const Node* N, const GraphType&) + { + if (N->ToolPtr) + if (N->ToolPtr->IsJoin()) + return N->Name() + "\n (join" + + (N->HasChildren() ? ")" + : std::string(": ") + + SquashStrArray(N->ToolPtr->OutputLanguages()) + ')'); + else + return N->Name(); + else + return "root"; + } + + template + static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) { + if (N->ToolPtr) { + return SquashStrArray(N->ToolPtr->OutputLanguages()); + } + else { + return SquashStrArray(I->ToolPtr->InputLanguages()); + } + } + }; + +} // End namespace llvm + +int CompilationGraph::writeGraph(const std::string& OutputFilename) { + std::string ErrorInfo; + raw_fd_ostream O(OutputFilename.c_str(), ErrorInfo); + + if (ErrorInfo.empty()) { + errs() << "Writing '"<< OutputFilename << "' file..."; + llvm::WriteGraph(O, this); + errs() << "done.\n"; + } + else { + PrintError("Error opening file '" + OutputFilename + "' for writing!"); + return 1; + } + + return 0; +} + +void CompilationGraph::viewGraph() { + llvm::ViewGraph(this, "compilation-graph"); +} diff --git a/final/lib/CompilerDriver/Main.cpp b/final/lib/CompilerDriver/Main.cpp new file mode 100644 index 00000000000..7120027f7ce --- /dev/null +++ b/final/lib/CompilerDriver/Main.cpp @@ -0,0 +1,146 @@ +//===--- Main.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// llvmc::Main function - driver entry point. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/AutoGenerated.h" +#include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/CompilationGraph.h" +#include "llvm/CompilerDriver/Error.h" + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Path.h" + +#include +#include + +namespace cl = llvm::cl; +namespace sys = llvm::sys; +using namespace llvmc; + +namespace { + + std::stringstream* GlobalTimeLog; + + /// GetTempDir - Get the temporary directory location. Returns non-zero value + /// on error. + int GetTempDir(sys::Path& tempDir) { + // The --temp-dir option. + if (!TempDirname.empty()) { + tempDir = TempDirname; + } + // GCC 4.5-style -save-temps handling. + else if (SaveTemps == SaveTempsEnum::Unset) { + tempDir = sys::Path::GetTemporaryDirectory(); + return 0; + } + else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) { + tempDir = sys::path::parent_path(OutputFilename); + } + else { + // SaveTemps == Cwd --> use current dir (leave tempDir empty). + return 0; + } + + bool Exists; + if (llvm::sys::fs::exists(tempDir.str(), Exists) || !Exists) { + std::string ErrMsg; + if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) { + PrintError(ErrMsg); + return 1; + } + } + + return 0; + } + + /// BuildTargets - A small wrapper for CompilationGraph::Build. Returns + /// non-zero value in case of error. + int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { + int ret; + sys::Path tempDir; + bool toDelete = (SaveTemps == SaveTempsEnum::Unset); + + if (int ret = GetTempDir(tempDir)) + return ret; + + ret = graph.Build(tempDir, langMap); + + if (toDelete) + tempDir.eraseFromDisk(true); + + return ret; + } +} + +namespace llvmc { + +// Used to implement -time option. External linkage is intentional. +void AppendToGlobalTimeLog(const std::string& cmd, double time) { + *GlobalTimeLog << "# " << cmd << ' ' << time << '\n'; +} + +// Sometimes user code wants to access the argv[0] value. +const char* ProgramName; + +int Main(int argc, char** argv) { + int ret = 0; + LanguageMap langMap; + CompilationGraph graph; + + ProgramName = argv[0]; + + cl::ParseCommandLineOptions + (argc, argv, + /* Overview = */ "LLVM Compiler Driver (Work In Progress)", + /* ReadResponseFiles = */ false); + + if (int ret = autogenerated::RunInitialization(langMap, graph)) + return ret; + + if (CheckGraph) { + ret = graph.Check(); + if (!ret) + llvm::errs() << "check-graph: no errors found.\n"; + + return ret; + } + + if (ViewGraph) { + graph.viewGraph(); + if (!WriteGraph) + return 0; + } + + if (WriteGraph) { + const std::string& Out = (OutputFilename.empty() + ? std::string("compilation-graph.dot") + : OutputFilename); + return graph.writeGraph(Out); + } + + if (Time) { + GlobalTimeLog = new std::stringstream; + GlobalTimeLog->precision(2); + } + + ret = BuildTargets(graph, langMap); + + if (Time) { + llvm::errs() << GlobalTimeLog->str(); + delete GlobalTimeLog; + } + + return ret; +} + +} // end namespace llvmc diff --git a/final/lib/CompilerDriver/Makefile b/final/lib/CompilerDriver/Makefile new file mode 100644 index 00000000000..10cfa4f0292 --- /dev/null +++ b/final/lib/CompilerDriver/Makefile @@ -0,0 +1,20 @@ +##===- lib/CompilerDriver/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +# We don't want this library to appear in `llvm-config --libs` output, so its +# name doesn't start with "LLVM" and NO_LLVM_CONFIG is set. + +LIBRARYNAME = CompilerDriver +LINK_COMPONENTS = support +NO_LLVM_CONFIG = 1 + + +include $(LEVEL)/Makefile.common diff --git a/final/lib/CompilerDriver/Tool.cpp b/final/lib/CompilerDriver/Tool.cpp new file mode 100644 index 00000000000..876759aa72b --- /dev/null +++ b/final/lib/CompilerDriver/Tool.cpp @@ -0,0 +1,95 @@ +//===--- Tool.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Tool base class - implementation details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/BuiltinOptions.h" +#include "llvm/CompilerDriver/Tool.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Path.h" + +#include + +using namespace llvm; +using namespace llvmc; + +namespace { + sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName, + const std::string& Suffix) { + sys::Path Out; + + // Make sure we don't end up with path names like '/file.o' if the + // TempDir is empty. + if (TempDir.empty()) { + Out.set(BaseName); + } + else { + Out = TempDir; + Out.appendComponent(BaseName); + } + Out.appendSuffix(Suffix); + // NOTE: makeUnique always *creates* a unique temporary file, + // which is good, since there will be no races. However, some + // tools do not like it when the output file already exists, so + // they need to be placated with -f or something like that. + Out.makeUnique(true, NULL); + return Out; + } +} + +sys::Path Tool::OutFilename(const sys::Path& In, + const sys::Path& TempDir, + bool StopCompilation, + const char* OutputSuffix) const { + sys::Path Out; + + if (StopCompilation) { + if (!OutputFilename.empty()) { + Out.set(OutputFilename); + } + else if (IsJoin()) { + Out.set("a"); + Out.appendSuffix(OutputSuffix); + } + else { + Out.set(sys::path::stem(In.str())); + Out.appendSuffix(OutputSuffix); + } + } + else { + if (IsJoin()) + Out = MakeTempFile(TempDir, "tmp", OutputSuffix); + else + Out = MakeTempFile(TempDir, sys::path::stem(In.str()), OutputSuffix); + } + return Out; +} + +namespace { + template + bool CompareFirst (std::pair p1, std::pair p2) { + return std::less
()(p1.first, p2.first); + } +} + +StrVector Tool::SortArgs(ArgsVector& Args) const { + StrVector Out; + + // HACK: this won't be needed when we'll migrate away from CommandLine. + std::stable_sort(Args.begin(), Args.end(), + &CompareFirst); + for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) { + Out.push_back(B->second); + } + + return Out; +} diff --git a/final/lib/ExecutionEngine/CMakeLists.txt b/final/lib/ExecutionEngine/CMakeLists.txt new file mode 100644 index 00000000000..b5632d2bc5c --- /dev/null +++ b/final/lib/ExecutionEngine/CMakeLists.txt @@ -0,0 +1,8 @@ +add_llvm_library(LLVMExecutionEngine + ExecutionEngine.cpp + ExecutionEngineBindings.cpp + ) + +add_subdirectory(Interpreter) +add_subdirectory(JIT) +add_subdirectory(MCJIT) diff --git a/final/lib/ExecutionEngine/ExecutionEngine.cpp b/final/lib/ExecutionEngine/ExecutionEngine.cpp new file mode 100644 index 00000000000..25a61c02890 --- /dev/null +++ b/final/lib/ExecutionEngine/ExecutionEngine.cpp @@ -0,0 +1,1103 @@ +//===-- ExecutionEngine.cpp - Common Implementation shared by EEs ---------===// +// +// 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 common interface used by the various execution engine +// subclasses. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm/ExecutionEngine/ExecutionEngine.h" + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Host.h" +#include "llvm/Target/TargetData.h" +#include +#include +using namespace llvm; + +STATISTIC(NumInitBytes, "Number of bytes of global vars initialized"); +STATISTIC(NumGlobals , "Number of global vars initialized"); + +ExecutionEngine *(*ExecutionEngine::JITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs) = 0; +ExecutionEngine *(*ExecutionEngine::MCJITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs) = 0; +ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M, + std::string *ErrorStr) = 0; + +ExecutionEngine::ExecutionEngine(Module *M) + : EEState(*this), + LazyFunctionCreator(0), + ExceptionTableRegister(0), + ExceptionTableDeregister(0) { + CompilingLazily = false; + GVCompilationDisabled = false; + SymbolSearchingDisabled = false; + Modules.push_back(M); + assert(M && "Module is null?"); +} + +ExecutionEngine::~ExecutionEngine() { + clearAllGlobalMappings(); + for (unsigned i = 0, e = Modules.size(); i != e; ++i) + delete Modules[i]; +} + +void ExecutionEngine::DeregisterAllTables() { + if (ExceptionTableDeregister) { + DenseMap::iterator it = AllExceptionTables.begin(); + DenseMap::iterator ite = AllExceptionTables.end(); + for (; it != ite; ++it) + ExceptionTableDeregister(it->second); + AllExceptionTables.clear(); + } +} + +namespace { +/// \brief Helper class which uses a value handler to automatically deletes the +/// memory block when the GlobalVariable is destroyed. +class GVMemoryBlock : public CallbackVH { + GVMemoryBlock(const GlobalVariable *GV) + : CallbackVH(const_cast(GV)) {} + +public: + /// \brief Returns the address the GlobalVariable should be written into. The + /// GVMemoryBlock object prefixes that. + static char *Create(const GlobalVariable *GV, const TargetData& TD) { + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy); + void *RawMemory = ::operator new( + TargetData::RoundUpAlignment(sizeof(GVMemoryBlock), + TD.getPreferredAlignment(GV)) + + GVSize); + new(RawMemory) GVMemoryBlock(GV); + return static_cast(RawMemory) + sizeof(GVMemoryBlock); + } + + virtual void deleted() { + // We allocated with operator new and with some extra memory hanging off the + // end, so don't just delete this. I'm not sure if this is actually + // required. + this->~GVMemoryBlock(); + ::operator delete(this); + } +}; +} // anonymous namespace + +char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) { + return GVMemoryBlock::Create(GV, *getTargetData()); +} + +bool ExecutionEngine::removeModule(Module *M) { + for(SmallVector::iterator I = Modules.begin(), + E = Modules.end(); I != E; ++I) { + Module *Found = *I; + if (Found == M) { + Modules.erase(I); + clearGlobalMappingsFromModule(M); + return true; + } + } + return false; +} + +Function *ExecutionEngine::FindFunctionNamed(const char *FnName) { + for (unsigned i = 0, e = Modules.size(); i != e; ++i) { + if (Function *F = Modules[i]->getFunction(FnName)) + return F; + } + return 0; +} + + +void *ExecutionEngineState::RemoveMapping(const MutexGuard &, + const GlobalValue *ToUnmap) { + GlobalAddressMapTy::iterator I = GlobalAddressMap.find(ToUnmap); + void *OldVal; + + // FIXME: This is silly, we shouldn't end up with a mapping -> 0 in the + // GlobalAddressMap. + if (I == GlobalAddressMap.end()) + OldVal = 0; + else { + OldVal = I->second; + GlobalAddressMap.erase(I); + } + + GlobalAddressReverseMap.erase(OldVal); + return OldVal; +} + +void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) { + MutexGuard locked(lock); + + DEBUG(dbgs() << "JIT: Map \'" << GV->getName() + << "\' to [" << Addr << "]\n";); + void *&CurVal = EEState.getGlobalAddressMap(locked)[GV]; + assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!"); + CurVal = Addr; + + // If we are using the reverse mapping, add it too. + if (!EEState.getGlobalAddressReverseMap(locked).empty()) { + AssertingVH &V = + EEState.getGlobalAddressReverseMap(locked)[Addr]; + assert((V == 0 || GV == 0) && "GlobalMapping already established!"); + V = GV; + } +} + +void ExecutionEngine::clearAllGlobalMappings() { + MutexGuard locked(lock); + + EEState.getGlobalAddressMap(locked).clear(); + EEState.getGlobalAddressReverseMap(locked).clear(); +} + +void ExecutionEngine::clearGlobalMappingsFromModule(Module *M) { + MutexGuard locked(lock); + + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) + EEState.RemoveMapping(locked, FI); + for (Module::global_iterator GI = M->global_begin(), GE = M->global_end(); + GI != GE; ++GI) + EEState.RemoveMapping(locked, GI); +} + +void *ExecutionEngine::updateGlobalMapping(const GlobalValue *GV, void *Addr) { + MutexGuard locked(lock); + + ExecutionEngineState::GlobalAddressMapTy &Map = + EEState.getGlobalAddressMap(locked); + + // Deleting from the mapping? + if (Addr == 0) + return EEState.RemoveMapping(locked, GV); + + void *&CurVal = Map[GV]; + void *OldVal = CurVal; + + if (CurVal && !EEState.getGlobalAddressReverseMap(locked).empty()) + EEState.getGlobalAddressReverseMap(locked).erase(CurVal); + CurVal = Addr; + + // If we are using the reverse mapping, add it too. + if (!EEState.getGlobalAddressReverseMap(locked).empty()) { + AssertingVH &V = + EEState.getGlobalAddressReverseMap(locked)[Addr]; + assert((V == 0 || GV == 0) && "GlobalMapping already established!"); + V = GV; + } + return OldVal; +} + +void *ExecutionEngine::getPointerToGlobalIfAvailable(const GlobalValue *GV) { + MutexGuard locked(lock); + + ExecutionEngineState::GlobalAddressMapTy::iterator I = + EEState.getGlobalAddressMap(locked).find(GV); + return I != EEState.getGlobalAddressMap(locked).end() ? I->second : 0; +} + +const GlobalValue *ExecutionEngine::getGlobalValueAtAddress(void *Addr) { + MutexGuard locked(lock); + + // If we haven't computed the reverse mapping yet, do so first. + if (EEState.getGlobalAddressReverseMap(locked).empty()) { + for (ExecutionEngineState::GlobalAddressMapTy::iterator + I = EEState.getGlobalAddressMap(locked).begin(), + E = EEState.getGlobalAddressMap(locked).end(); I != E; ++I) + EEState.getGlobalAddressReverseMap(locked).insert(std::make_pair( + I->second, I->first)); + } + + std::map >::iterator I = + EEState.getGlobalAddressReverseMap(locked).find(Addr); + return I != EEState.getGlobalAddressReverseMap(locked).end() ? I->second : 0; +} + +namespace { +class ArgvArray { + char *Array; + std::vector Values; +public: + ArgvArray() : Array(NULL) {} + ~ArgvArray() { clear(); } + void clear() { + delete[] Array; + Array = NULL; + for (size_t I = 0, E = Values.size(); I != E; ++I) { + delete[] Values[I]; + } + Values.clear(); + } + /// Turn a vector of strings into a nice argv style array of pointers to null + /// terminated strings. + void *reset(LLVMContext &C, ExecutionEngine *EE, + const std::vector &InputArgv); +}; +} // anonymous namespace +void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE, + const std::vector &InputArgv) { + clear(); // Free the old contents. + unsigned PtrSize = EE->getTargetData()->getPointerSize(); + Array = new char[(InputArgv.size()+1)*PtrSize]; + + DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n"); + const Type *SBytePtr = Type::getInt8PtrTy(C); + + for (unsigned i = 0; i != InputArgv.size(); ++i) { + unsigned Size = InputArgv[i].size()+1; + char *Dest = new char[Size]; + Values.push_back(Dest); + DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest << "\n"); + + std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest); + Dest[Size-1] = 0; + + // Endian safe: Array[i] = (PointerTy)Dest; + EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Array+i*PtrSize), + SBytePtr); + } + + // Null terminate it + EE->StoreValueToMemory(PTOGV(0), + (GenericValue*)(Array+InputArgv.size()*PtrSize), + SBytePtr); + return Array; +} + +void ExecutionEngine::runStaticConstructorsDestructors(Module *module, + bool isDtors) { + const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors"; + GlobalVariable *GV = module->getNamedGlobal(Name); + + // If this global has internal linkage, or if it has a use, then it must be + // an old-style (llvmgcc3) static ctor with __main linked in and in use. If + // this is the case, don't execute any of the global ctors, __main will do + // it. + if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return; + + // Should be an array of '{ int, void ()* }' structs. The first value is + // the init priority, which we ignore. + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (!InitList) return; + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + ConstantStruct *CS = + dyn_cast(InitList->getOperand(i)); + if (!CS) continue; + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. + + Constant *FP = CS->getOperand(1); + if (FP->isNullValue()) + break; // Found a null terminator, exit. + + // Strip off constant expression casts. + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) + FP = CE->getOperand(0); + + // Execute the ctor/dtor function! + if (Function *F = dyn_cast(FP)) + runFunction(F, std::vector()); + + // FIXME: It is marginally lame that we just do nothing here if we see an + // entry we don't recognize. It might not be unreasonable for the verifier + // to not even allow this and just assert here. + } +} + +void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) { + // Execute global ctors/dtors for each module in the program. + for (unsigned i = 0, e = Modules.size(); i != e; ++i) + runStaticConstructorsDestructors(Modules[i], isDtors); +} + +#ifndef NDEBUG +/// isTargetNullPtr - Return whether the target pointer stored at Loc is null. +static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) { + unsigned PtrSize = EE->getTargetData()->getPointerSize(); + for (unsigned i = 0; i < PtrSize; ++i) + if (*(i + (uint8_t*)Loc)) + return false; + return true; +} +#endif + +int ExecutionEngine::runFunctionAsMain(Function *Fn, + const std::vector &argv, + const char * const * envp) { + std::vector GVArgs; + GenericValue GVArgc; + GVArgc.IntVal = APInt(32, argv.size()); + + // Check main() type + unsigned NumArgs = Fn->getFunctionType()->getNumParams(); + const FunctionType *FTy = Fn->getFunctionType(); + const Type* PPInt8Ty = Type::getInt8PtrTy(Fn->getContext())->getPointerTo(); + + // Check the argument types. + if (NumArgs > 3) + report_fatal_error("Invalid number of arguments of main() supplied"); + if (NumArgs >= 3 && FTy->getParamType(2) != PPInt8Ty) + report_fatal_error("Invalid type for third argument of main() supplied"); + if (NumArgs >= 2 && FTy->getParamType(1) != PPInt8Ty) + report_fatal_error("Invalid type for second argument of main() supplied"); + if (NumArgs >= 1 && !FTy->getParamType(0)->isIntegerTy(32)) + report_fatal_error("Invalid type for first argument of main() supplied"); + if (!FTy->getReturnType()->isIntegerTy() && + !FTy->getReturnType()->isVoidTy()) + report_fatal_error("Invalid return type of main() supplied"); + + ArgvArray CArgv; + ArgvArray CEnv; + if (NumArgs) { + GVArgs.push_back(GVArgc); // Arg #0 = argc. + if (NumArgs > 1) { + // Arg #1 = argv. + GVArgs.push_back(PTOGV(CArgv.reset(Fn->getContext(), this, argv))); + assert(!isTargetNullPtr(this, GVTOP(GVArgs[1])) && + "argv[0] was null after CreateArgv"); + if (NumArgs > 2) { + std::vector EnvVars; + for (unsigned i = 0; envp[i]; ++i) + EnvVars.push_back(envp[i]); + // Arg #2 = envp. + GVArgs.push_back(PTOGV(CEnv.reset(Fn->getContext(), this, EnvVars))); + } + } + } + + return runFunction(Fn, GVArgs).IntVal.getZExtValue(); +} + +ExecutionEngine *ExecutionEngine::create(Module *M, + bool ForceInterpreter, + std::string *ErrorStr, + CodeGenOpt::Level OptLevel, + bool GVsWithCode) { + return EngineBuilder(M) + .setEngineKind(ForceInterpreter + ? EngineKind::Interpreter + : EngineKind::JIT) + .setErrorStr(ErrorStr) + .setOptLevel(OptLevel) + .setAllocateGVsWithCode(GVsWithCode) + .create(); +} + +ExecutionEngine *EngineBuilder::create() { + // Make sure we can resolve symbols in the program as well. The zero arg + // to the function tells DynamicLibrary to load the program, not a library. + if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) + return 0; + + // If the user specified a memory manager but didn't specify which engine to + // create, we assume they only want the JIT, and we fail if they only want + // the interpreter. + if (JMM) { + if (WhichEngine & EngineKind::JIT) + WhichEngine = EngineKind::JIT; + else { + if (ErrorStr) + *ErrorStr = "Cannot create an interpreter with a memory manager."; + return 0; + } + } + + // Unless the interpreter was explicitly selected or the JIT is not linked, + // try making a JIT. + if (WhichEngine & EngineKind::JIT) { + if (UseMCJIT && ExecutionEngine::MCJITCtor) { + ExecutionEngine *EE = + ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, OptLevel, + AllocateGVsWithCode, CMModel, + MArch, MCPU, MAttrs); + if (EE) return EE; + } else if (ExecutionEngine::JITCtor) { + ExecutionEngine *EE = + ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, + AllocateGVsWithCode, CMModel, + MArch, MCPU, MAttrs); + if (EE) return EE; + } + } + + // If we can't make a JIT and we didn't request one specifically, try making + // an interpreter instead. + if (WhichEngine & EngineKind::Interpreter) { + if (ExecutionEngine::InterpCtor) + return ExecutionEngine::InterpCtor(M, ErrorStr); + if (ErrorStr) + *ErrorStr = "Interpreter has not been linked in."; + return 0; + } + + if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0) { + if (ErrorStr) + *ErrorStr = "JIT has not been linked in."; + } + + return 0; +} + +void *ExecutionEngine::getPointerToGlobal(const GlobalValue *GV) { + if (Function *F = const_cast(dyn_cast(GV))) + return getPointerToFunction(F); + + MutexGuard locked(lock); + if (void *P = EEState.getGlobalAddressMap(locked)[GV]) + return P; + + // Global variable might have been added since interpreter started. + if (GlobalVariable *GVar = + const_cast(dyn_cast(GV))) + EmitGlobalVariable(GVar); + else + llvm_unreachable("Global hasn't had an address allocated yet!"); + + return EEState.getGlobalAddressMap(locked)[GV]; +} + +/// \brief Converts a Constant* into a GenericValue, including handling of +/// ConstantExpr values. +GenericValue ExecutionEngine::getConstantValue(const Constant *C) { + // If its undefined, return the garbage. + if (isa(C)) { + GenericValue Result; + switch (C->getType()->getTypeID()) { + case Type::IntegerTyID: + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + // Although the value is undefined, we still have to construct an APInt + // with the correct bit width. + Result.IntVal = APInt(C->getType()->getPrimitiveSizeInBits(), 0); + break; + default: + break; + } + return Result; + } + + // Otherwise, if the value is a ConstantExpr... + if (const ConstantExpr *CE = dyn_cast(C)) { + Constant *Op0 = CE->getOperand(0); + switch (CE->getOpcode()) { + case Instruction::GetElementPtr: { + // Compute the index + GenericValue Result = getConstantValue(Op0); + SmallVector Indices(CE->op_begin()+1, CE->op_end()); + uint64_t Offset = + TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); + + char* tmp = (char*) Result.PointerVal; + Result = PTOGV(tmp + Offset); + return Result; + } + case Instruction::Trunc: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.trunc(BitWidth); + return GV; + } + case Instruction::ZExt: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.zext(BitWidth); + return GV; + } + case Instruction::SExt: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + GV.IntVal = GV.IntVal.sext(BitWidth); + return GV; + } + case Instruction::FPTrunc: { + // FIXME long double + GenericValue GV = getConstantValue(Op0); + GV.FloatVal = float(GV.DoubleVal); + return GV; + } + case Instruction::FPExt:{ + // FIXME long double + GenericValue GV = getConstantValue(Op0); + GV.DoubleVal = double(GV.FloatVal); + return GV; + } + case Instruction::UIToFP: { + GenericValue GV = getConstantValue(Op0); + if (CE->getType()->isFloatTy()) + GV.FloatVal = float(GV.IntVal.roundToDouble()); + else if (CE->getType()->isDoubleTy()) + GV.DoubleVal = GV.IntVal.roundToDouble(); + else if (CE->getType()->isX86_FP80Ty()) { + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + (void)apf.convertFromAPInt(GV.IntVal, + false, + APFloat::rmNearestTiesToEven); + GV.IntVal = apf.bitcastToAPInt(); + } + return GV; + } + case Instruction::SIToFP: { + GenericValue GV = getConstantValue(Op0); + if (CE->getType()->isFloatTy()) + GV.FloatVal = float(GV.IntVal.signedRoundToDouble()); + else if (CE->getType()->isDoubleTy()) + GV.DoubleVal = GV.IntVal.signedRoundToDouble(); + else if (CE->getType()->isX86_FP80Ty()) { + APFloat apf = APFloat::getZero(APFloat::x87DoubleExtended); + (void)apf.convertFromAPInt(GV.IntVal, + true, + APFloat::rmNearestTiesToEven); + GV.IntVal = apf.bitcastToAPInt(); + } + return GV; + } + case Instruction::FPToUI: // double->APInt conversion handles sign + case Instruction::FPToSI: { + GenericValue GV = getConstantValue(Op0); + uint32_t BitWidth = cast(CE->getType())->getBitWidth(); + if (Op0->getType()->isFloatTy()) + GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth); + else if (Op0->getType()->isDoubleTy()) + GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); + else if (Op0->getType()->isX86_FP80Ty()) { + APFloat apf = APFloat(GV.IntVal); + uint64_t v; + bool ignored; + (void)apf.convertToInteger(&v, BitWidth, + CE->getOpcode()==Instruction::FPToSI, + APFloat::rmTowardZero, &ignored); + GV.IntVal = v; // endian? + } + return GV; + } + case Instruction::PtrToInt: { + GenericValue GV = getConstantValue(Op0); + uint32_t PtrWidth = TD->getPointerSizeInBits(); + GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); + return GV; + } + case Instruction::IntToPtr: { + GenericValue GV = getConstantValue(Op0); + uint32_t PtrWidth = TD->getPointerSizeInBits(); + if (PtrWidth != GV.IntVal.getBitWidth()) + GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); + assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); + GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); + return GV; + } + case Instruction::BitCast: { + GenericValue GV = getConstantValue(Op0); + const Type* DestTy = CE->getType(); + switch (Op0->getType()->getTypeID()) { + default: llvm_unreachable("Invalid bitcast operand"); + case Type::IntegerTyID: + assert(DestTy->isFloatingPointTy() && "invalid bitcast"); + if (DestTy->isFloatTy()) + GV.FloatVal = GV.IntVal.bitsToFloat(); + else if (DestTy->isDoubleTy()) + GV.DoubleVal = GV.IntVal.bitsToDouble(); + break; + case Type::FloatTyID: + assert(DestTy->isIntegerTy(32) && "Invalid bitcast"); + GV.IntVal = APInt::floatToBits(GV.FloatVal); + break; + case Type::DoubleTyID: + assert(DestTy->isIntegerTy(64) && "Invalid bitcast"); + GV.IntVal = APInt::doubleToBits(GV.DoubleVal); + break; + case Type::PointerTyID: + assert(DestTy->isPointerTy() && "Invalid bitcast"); + break; // getConstantValue(Op0) above already converted it + } + return GV; + } + case Instruction::Add: + case Instruction::FAdd: + case Instruction::Sub: + case Instruction::FSub: + case Instruction::Mul: + case Instruction::FMul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: { + GenericValue LHS = getConstantValue(Op0); + GenericValue RHS = getConstantValue(CE->getOperand(1)); + GenericValue GV; + switch (CE->getOperand(0)->getType()->getTypeID()) { + default: llvm_unreachable("Bad add type!"); + case Type::IntegerTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid integer opcode"); + case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break; + case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break; + case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break; + case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break; + case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break; + case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break; + case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break; + case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break; + case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break; + case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break; + } + break; + case Type::FloatTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid float opcode"); + case Instruction::FAdd: + GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break; + case Instruction::FSub: + GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break; + case Instruction::FMul: + GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break; + case Instruction::FDiv: + GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break; + case Instruction::FRem: + GV.FloatVal = std::fmod(LHS.FloatVal,RHS.FloatVal); break; + } + break; + case Type::DoubleTyID: + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid double opcode"); + case Instruction::FAdd: + GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break; + case Instruction::FSub: + GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break; + case Instruction::FMul: + GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break; + case Instruction::FDiv: + GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break; + case Instruction::FRem: + GV.DoubleVal = std::fmod(LHS.DoubleVal,RHS.DoubleVal); break; + } + break; + case Type::X86_FP80TyID: + case Type::PPC_FP128TyID: + case Type::FP128TyID: { + APFloat apfLHS = APFloat(LHS.IntVal); + switch (CE->getOpcode()) { + default: llvm_unreachable("Invalid long double opcode"); + case Instruction::FAdd: + apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FSub: + apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FMul: + apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FDiv: + apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + case Instruction::FRem: + apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); + GV.IntVal = apfLHS.bitcastToAPInt(); + break; + } + } + break; + } + return GV; + } + default: + break; + } + + SmallString<256> Msg; + raw_svector_ostream OS(Msg); + OS << "ConstantExpr not handled: " << *CE; + report_fatal_error(OS.str()); + } + + // Otherwise, we have a simple constant. + GenericValue Result; + switch (C->getType()->getTypeID()) { + case Type::FloatTyID: + Result.FloatVal = cast(C)->getValueAPF().convertToFloat(); + break; + case Type::DoubleTyID: + Result.DoubleVal = cast(C)->getValueAPF().convertToDouble(); + break; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + Result.IntVal = cast (C)->getValueAPF().bitcastToAPInt(); + break; + case Type::IntegerTyID: + Result.IntVal = cast(C)->getValue(); + break; + case Type::PointerTyID: + if (isa(C)) + Result.PointerVal = 0; + else if (const Function *F = dyn_cast(C)) + Result = PTOGV(getPointerToFunctionOrStub(const_cast(F))); + else if (const GlobalVariable *GV = dyn_cast(C)) + Result = PTOGV(getOrEmitGlobalVariable(const_cast(GV))); + else if (const BlockAddress *BA = dyn_cast(C)) + Result = PTOGV(getPointerToBasicBlock(const_cast( + BA->getBasicBlock()))); + else + llvm_unreachable("Unknown constant pointer type!"); + break; + default: + SmallString<256> Msg; + raw_svector_ostream OS(Msg); + OS << "ERROR: Constant unimplemented for type: " << *C->getType(); + report_fatal_error(OS.str()); + } + + return Result; +} + +/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst +/// with the integer held in IntVal. +static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, + unsigned StoreBytes) { + assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!"); + uint8_t *Src = (uint8_t *)IntVal.getRawData(); + + if (sys::isLittleEndianHost()) { + // Little-endian host - the source is ordered from LSB to MSB. Order the + // destination from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, StoreBytes); + } else { + // Big-endian host - the source is an array of 64 bit words ordered from + // LSW to MSW. Each word is ordered from MSB to LSB. Order the destination + // from MSB to LSB: Reverse the word order, but not the bytes in a word. + while (StoreBytes > sizeof(uint64_t)) { + StoreBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst + StoreBytes, Src, sizeof(uint64_t)); + Src += sizeof(uint64_t); + } + + memcpy(Dst, Src + sizeof(uint64_t) - StoreBytes, StoreBytes); + } +} + +void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, + GenericValue *Ptr, const Type *Ty) { + const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty); + + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + StoreIntToMemory(Val.IntVal, (uint8_t*)Ptr, StoreBytes); + break; + case Type::FloatTyID: + *((float*)Ptr) = Val.FloatVal; + break; + case Type::DoubleTyID: + *((double*)Ptr) = Val.DoubleVal; + break; + case Type::X86_FP80TyID: + memcpy(Ptr, Val.IntVal.getRawData(), 10); + break; + case Type::PointerTyID: + // Ensure 64 bit target pointers are fully initialized on 32 bit hosts. + if (StoreBytes != sizeof(PointerTy)) + memset(Ptr, 0, StoreBytes); + + *((PointerTy*)Ptr) = Val.PointerVal; + break; + default: + dbgs() << "Cannot store value of type " << *Ty << "!\n"; + } + + if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian()) + // Host and target are different endian - reverse the stored bytes. + std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); +} + +/// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting +/// from Src into IntVal, which is assumed to be wide enough and to hold zero. +static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) { + assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!"); + uint8_t *Dst = (uint8_t *)IntVal.getRawData(); + + if (sys::isLittleEndianHost()) + // Little-endian host - the destination must be ordered from LSB to MSB. + // The source is ordered from LSB to MSB: Do a straight copy. + memcpy(Dst, Src, LoadBytes); + else { + // Big-endian - the destination is an array of 64 bit words ordered from + // LSW to MSW. Each word must be ordered from MSB to LSB. The source is + // ordered from MSB to LSB: Reverse the word order, but not the bytes in + // a word. + while (LoadBytes > sizeof(uint64_t)) { + LoadBytes -= sizeof(uint64_t); + // May not be aligned so use memcpy. + memcpy(Dst, Src + LoadBytes, sizeof(uint64_t)); + Dst += sizeof(uint64_t); + } + + memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes); + } +} + +/// FIXME: document +/// +void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, + GenericValue *Ptr, + const Type *Ty) { + const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty); + + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + // An APInt with all words initially zero. + Result.IntVal = APInt(cast(Ty)->getBitWidth(), 0); + LoadIntFromMemory(Result.IntVal, (uint8_t*)Ptr, LoadBytes); + break; + case Type::FloatTyID: + Result.FloatVal = *((float*)Ptr); + break; + case Type::DoubleTyID: + Result.DoubleVal = *((double*)Ptr); + break; + case Type::PointerTyID: + Result.PointerVal = *((PointerTy*)Ptr); + break; + case Type::X86_FP80TyID: { + // This is endian dependent, but it will only work on x86 anyway. + // FIXME: Will not trap if loading a signaling NaN. + uint64_t y[2]; + memcpy(y, Ptr, 10); + Result.IntVal = APInt(80, 2, y); + break; + } + default: + SmallString<256> Msg; + raw_svector_ostream OS(Msg); + OS << "Cannot load value of type " << *Ty << "!"; + report_fatal_error(OS.str()); + } +} + +void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { + DEBUG(dbgs() << "JIT: Initializing " << Addr << " "); + DEBUG(Init->dump()); + if (isa(Init)) { + return; + } else if (const ConstantVector *CP = dyn_cast(Init)) { + unsigned ElementSize = + getTargetData()->getTypeAllocSize(CP->getType()->getElementType()); + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) + InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); + return; + } else if (isa(Init)) { + memset(Addr, 0, (size_t)getTargetData()->getTypeAllocSize(Init->getType())); + return; + } else if (const ConstantArray *CPA = dyn_cast(Init)) { + unsigned ElementSize = + getTargetData()->getTypeAllocSize(CPA->getType()->getElementType()); + for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) + InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); + return; + } else if (const ConstantStruct *CPS = dyn_cast(Init)) { + const StructLayout *SL = + getTargetData()->getStructLayout(cast(CPS->getType())); + for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) + InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i)); + return; + } else if (Init->getType()->isFirstClassType()) { + GenericValue Val = getConstantValue(Init); + StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType()); + return; + } + + DEBUG(dbgs() << "Bad Type: " << *Init->getType() << "\n"); + llvm_unreachable("Unknown constant type to initialize memory with!"); +} + +/// EmitGlobals - Emit all of the global variables to memory, storing their +/// addresses into GlobalAddress. This must make sure to copy the contents of +/// their initializers into the memory. +void ExecutionEngine::emitGlobals() { + // Loop over all of the global variables in the program, allocating the memory + // to hold them. If there is more than one module, do a prepass over globals + // to figure out how the different modules should link together. + std::map, + const GlobalValue*> LinkedGlobalsMap; + + if (Modules.size() != 1) { + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]; + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + const GlobalValue *GV = I; + if (GV->hasLocalLinkage() || GV->isDeclaration() || + GV->hasAppendingLinkage() || !GV->hasName()) + continue;// Ignore external globals and globals with internal linkage. + + const GlobalValue *&GVEntry = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + + // If this is the first time we've seen this global, it is the canonical + // version. + if (!GVEntry) { + GVEntry = GV; + continue; + } + + // If the existing global is strong, never replace it. + if (GVEntry->hasExternalLinkage() || + GVEntry->hasDLLImportLinkage() || + GVEntry->hasDLLExportLinkage()) + continue; + + // Otherwise, we know it's linkonce/weak, replace it if this is a strong + // symbol. FIXME is this right for common? + if (GV->hasExternalLinkage() || GVEntry->hasExternalWeakLinkage()) + GVEntry = GV; + } + } + } + + std::vector NonCanonicalGlobals; + for (unsigned m = 0, e = Modules.size(); m != e; ++m) { + Module &M = *Modules[m]; + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + // In the multi-module case, see what this global maps to. + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) { + // If something else is the canonical global, ignore this one. + if (GVEntry != &*I) { + NonCanonicalGlobals.push_back(I); + continue; + } + } + } + + if (!I->isDeclaration()) { + addGlobalMapping(I, getMemoryForGV(I)); + } else { + // External variable reference. Try to use the dynamic loader to + // get a pointer to it. + if (void *SymAddr = + sys::DynamicLibrary::SearchForAddressOfSymbol(I->getName())) + addGlobalMapping(I, SymAddr); + else { + report_fatal_error("Could not resolve external global address: " + +I->getName()); + } + } + } + + // If there are multiple modules, map the non-canonical globals to their + // canonical location. + if (!NonCanonicalGlobals.empty()) { + for (unsigned i = 0, e = NonCanonicalGlobals.size(); i != e; ++i) { + const GlobalValue *GV = NonCanonicalGlobals[i]; + const GlobalValue *CGV = + LinkedGlobalsMap[std::make_pair(GV->getName(), GV->getType())]; + void *Ptr = getPointerToGlobalIfAvailable(CGV); + assert(Ptr && "Canonical global wasn't codegen'd!"); + addGlobalMapping(GV, Ptr); + } + } + + // Now that all of the globals are set up in memory, loop through them all + // and initialize their contents. + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->isDeclaration()) { + if (!LinkedGlobalsMap.empty()) { + if (const GlobalValue *GVEntry = + LinkedGlobalsMap[std::make_pair(I->getName(), I->getType())]) + if (GVEntry != &*I) // Not the canonical variable. + continue; + } + EmitGlobalVariable(I); + } + } + } +} + +// EmitGlobalVariable - This method emits the specified global variable to the +// address specified in GlobalAddresses, or allocates new memory if it's not +// already in the map. +void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) { + void *GA = getPointerToGlobalIfAvailable(GV); + + if (GA == 0) { + // If it's not already specified, allocate memory for the global. + GA = getMemoryForGV(GV); + addGlobalMapping(GV, GA); + } + + // Don't initialize if it's thread local, let the client do it. + if (!GV->isThreadLocal()) + InitializeMemory(GV->getInitializer(), GA); + + const Type *ElTy = GV->getType()->getElementType(); + size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy); + NumInitBytes += (unsigned)GVSize; + ++NumGlobals; +} + +ExecutionEngineState::ExecutionEngineState(ExecutionEngine &EE) + : EE(EE), GlobalAddressMap(this) { +} + +sys::Mutex * +ExecutionEngineState::AddressMapConfig::getMutex(ExecutionEngineState *EES) { + return &EES->EE.lock; +} + +void ExecutionEngineState::AddressMapConfig::onDelete(ExecutionEngineState *EES, + const GlobalValue *Old) { + void *OldVal = EES->GlobalAddressMap.lookup(Old); + EES->GlobalAddressReverseMap.erase(OldVal); +} + +void ExecutionEngineState::AddressMapConfig::onRAUW(ExecutionEngineState *, + const GlobalValue *, + const GlobalValue *) { + assert(false && "The ExecutionEngine doesn't know how to handle a" + " RAUW on a value it has a global mapping for."); +} diff --git a/final/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/final/lib/ExecutionEngine/ExecutionEngineBindings.cpp new file mode 100644 index 00000000000..f8f1f4a78ee --- /dev/null +++ b/final/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -0,0 +1,254 @@ +//===-- ExecutionEngineBindings.cpp - C bindings for EEs ------------------===// +// +// 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 C bindings for the ExecutionEngine library. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm-c/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/ErrorHandling.h" +#include + +using namespace llvm; + +/*===-- Operations on generic values --------------------------------------===*/ + +LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, + unsigned long long N, + LLVMBool IsSigned) { + GenericValue *GenVal = new GenericValue(); + GenVal->IntVal = APInt(unwrap(Ty)->getBitWidth(), N, IsSigned); + return wrap(GenVal); +} + +LLVMGenericValueRef LLVMCreateGenericValueOfPointer(void *P) { + GenericValue *GenVal = new GenericValue(); + GenVal->PointerVal = P; + return wrap(GenVal); +} + +LLVMGenericValueRef LLVMCreateGenericValueOfFloat(LLVMTypeRef TyRef, double N) { + GenericValue *GenVal = new GenericValue(); + switch (unwrap(TyRef)->getTypeID()) { + case Type::FloatTyID: + GenVal->FloatVal = N; + break; + case Type::DoubleTyID: + GenVal->DoubleVal = N; + break; + default: + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); + } + return wrap(GenVal); +} + +unsigned LLVMGenericValueIntWidth(LLVMGenericValueRef GenValRef) { + return unwrap(GenValRef)->IntVal.getBitWidth(); +} + +unsigned long long LLVMGenericValueToInt(LLVMGenericValueRef GenValRef, + LLVMBool IsSigned) { + GenericValue *GenVal = unwrap(GenValRef); + if (IsSigned) + return GenVal->IntVal.getSExtValue(); + else + return GenVal->IntVal.getZExtValue(); +} + +void *LLVMGenericValueToPointer(LLVMGenericValueRef GenVal) { + return unwrap(GenVal)->PointerVal; +} + +double LLVMGenericValueToFloat(LLVMTypeRef TyRef, LLVMGenericValueRef GenVal) { + switch (unwrap(TyRef)->getTypeID()) { + case Type::FloatTyID: + return unwrap(GenVal)->FloatVal; + case Type::DoubleTyID: + return unwrap(GenVal)->DoubleVal; + default: + llvm_unreachable("LLVMGenericValueToFloat supports only float and double."); + break; + } + return 0; // Not reached +} + +void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { + delete unwrap(GenVal); +} + +/*===-- Operations on execution engines -----------------------------------===*/ + +LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, + LLVMModuleRef M, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::Either) + .setErrorStr(&Error); + if (ExecutionEngine *EE = builder.create()){ + *OutEE = wrap(EE); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, + LLVMModuleRef M, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::Interpreter) + .setErrorStr(&Error); + if (ExecutionEngine *Interp = builder.create()) { + *OutInterp = wrap(Interp); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + unsigned OptLevel, + char **OutError) { + std::string Error; + EngineBuilder builder(unwrap(M)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setOptLevel((CodeGenOpt::Level)OptLevel); + if (ExecutionEngine *JIT = builder.create()) { + *OutJIT = wrap(JIT); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, + LLVMModuleProviderRef MP, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateExecutionEngineForModule(OutEE, + reinterpret_cast(MP), + OutError); +} + +LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateInterpreterForModule(OutInterp, + reinterpret_cast(MP), + OutError); +} + +LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, + LLVMModuleProviderRef MP, + unsigned OptLevel, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateJITCompilerForModule(OutJIT, + reinterpret_cast(MP), + OptLevel, OutError); +} + + +void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { + delete unwrap(EE); +} + +void LLVMRunStaticConstructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->runStaticConstructorsDestructors(false); +} + +void LLVMRunStaticDestructors(LLVMExecutionEngineRef EE) { + unwrap(EE)->runStaticConstructorsDestructors(true); +} + +int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned ArgC, const char * const *ArgV, + const char * const *EnvP) { + std::vector ArgVec; + for (unsigned I = 0; I != ArgC; ++I) + ArgVec.push_back(ArgV[I]); + + return unwrap(EE)->runFunctionAsMain(unwrap(F), ArgVec, EnvP); +} + +LLVMGenericValueRef LLVMRunFunction(LLVMExecutionEngineRef EE, LLVMValueRef F, + unsigned NumArgs, + LLVMGenericValueRef *Args) { + std::vector ArgVec; + ArgVec.reserve(NumArgs); + for (unsigned I = 0; I != NumArgs; ++I) + ArgVec.push_back(*unwrap(Args[I])); + + GenericValue *Result = new GenericValue(); + *Result = unwrap(EE)->runFunction(unwrap(F), ArgVec); + return wrap(Result); +} + +void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { + unwrap(EE)->freeMachineCodeForFunction(unwrap(F)); +} + +void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){ + unwrap(EE)->addModule(unwrap(M)); +} + +void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP){ + /* The module provider is now actually a module. */ + LLVMAddModule(EE, reinterpret_cast(MP)); +} + +LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, + LLVMModuleRef *OutMod, char **OutError) { + Module *Mod = unwrap(M); + unwrap(EE)->removeModule(Mod); + *OutMod = wrap(Mod); + return 0; +} + +LLVMBool LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, + LLVMModuleProviderRef MP, + LLVMModuleRef *OutMod, char **OutError) { + /* The module provider is now actually a module. */ + return LLVMRemoveModule(EE, reinterpret_cast(MP), OutMod, + OutError); +} + +LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, + LLVMValueRef *OutFn) { + if (Function *F = unwrap(EE)->FindFunctionNamed(Name)) { + *OutFn = wrap(F); + return 0; + } + return 1; +} + +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn) { + return unwrap(EE)->recompileAndRelinkFunction(unwrap(Fn)); +} + +LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { + return wrap(unwrap(EE)->getTargetData()); +} + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr) { + unwrap(EE)->addGlobalMapping(unwrap(Global), Addr); +} + +void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global) { + return unwrap(EE)->getPointerToGlobal(unwrap(Global)); +} diff --git a/final/lib/ExecutionEngine/Interpreter/CMakeLists.txt b/final/lib/ExecutionEngine/Interpreter/CMakeLists.txt new file mode 100644 index 00000000000..d331f830b62 --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/CMakeLists.txt @@ -0,0 +1,17 @@ +# Make sure that the path to libffi headers is on the command +# line. That path can be a compiler's non-default path even when +# FFI_INCLUDE_DIR was not used, because cmake has its own paths for +# searching for headers (CMAKE_SYSTEM_INCLUDE_PATH, for instance): +if( FFI_INCLUDE_PATH ) + include_directories( ${FFI_INCLUDE_PATH} ) +endif() + +add_llvm_library(LLVMInterpreter + Execution.cpp + ExternalFunctions.cpp + Interpreter.cpp + ) + +if( LLVM_ENABLE_FFI ) + target_link_libraries( LLVMInterpreter ${FFI_LIBRARY_PATH} ) +endif() diff --git a/final/lib/ExecutionEngine/Interpreter/Execution.cpp b/final/lib/ExecutionEngine/Interpreter/Execution.cpp new file mode 100644 index 00000000000..498063bf655 --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -0,0 +1,1350 @@ +//===-- Execution.cpp - Implement code to simulate the program ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the actual instruction interpreter. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "interpreter" +#include "Interpreter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(NumDynamicInsts, "Number of dynamic instructions executed"); + +static cl::opt PrintVolatile("interpreter-print-volatile", cl::Hidden, + cl::desc("make the interpreter print every volatile load and store")); + +//===----------------------------------------------------------------------===// +// Various Helper Functions +//===----------------------------------------------------------------------===// + +static void SetValue(Value *V, GenericValue Val, ExecutionContext &SF) { + SF.Values[V] = Val; +} + +//===----------------------------------------------------------------------===// +// Binary Instruction Implementations +//===----------------------------------------------------------------------===// + +#define IMPLEMENT_BINARY_OPERATOR(OP, TY) \ + case Type::TY##TyID: \ + Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; \ + break + +static void executeFAddInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(+, Float); + IMPLEMENT_BINARY_OPERATOR(+, Double); + default: + dbgs() << "Unhandled type for FAdd instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFSubInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(-, Float); + IMPLEMENT_BINARY_OPERATOR(-, Double); + default: + dbgs() << "Unhandled type for FSub instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFMulInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(*, Float); + IMPLEMENT_BINARY_OPERATOR(*, Double); + default: + dbgs() << "Unhandled type for FMul instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFDivInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + IMPLEMENT_BINARY_OPERATOR(/, Float); + IMPLEMENT_BINARY_OPERATOR(/, Double); + default: + dbgs() << "Unhandled type for FDiv instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +static void executeFRemInst(GenericValue &Dest, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::FloatTyID: + Dest.FloatVal = fmod(Src1.FloatVal, Src2.FloatVal); + break; + case Type::DoubleTyID: + Dest.DoubleVal = fmod(Src1.DoubleVal, Src2.DoubleVal); + break; + default: + dbgs() << "Unhandled type for Rem instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } +} + +#define IMPLEMENT_INTEGER_ICMP(OP, TY) \ + case Type::IntegerTyID: \ + Dest.IntVal = APInt(1,Src1.IntVal.OP(Src2.IntVal)); \ + break; + +// Handle pointers specially because they must be compared with only as much +// width as the host has. We _do not_ want to be comparing 64 bit values when +// running on a 32-bit target, otherwise the upper 32 bits might mess up +// comparisons if they contain garbage. +#define IMPLEMENT_POINTER_ICMP(OP) \ + case Type::PointerTyID: \ + Dest.IntVal = APInt(1,(void*)(intptr_t)Src1.PointerVal OP \ + (void*)(intptr_t)Src2.PointerVal); \ + break; + +static GenericValue executeICMP_EQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(eq,Ty); + IMPLEMENT_POINTER_ICMP(==); + default: + dbgs() << "Unhandled type for ICMP_EQ predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_NE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ne,Ty); + IMPLEMENT_POINTER_ICMP(!=); + default: + dbgs() << "Unhandled type for ICMP_NE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_ULT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ult,Ty); + IMPLEMENT_POINTER_ICMP(<); + default: + dbgs() << "Unhandled type for ICMP_ULT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SLT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(slt,Ty); + IMPLEMENT_POINTER_ICMP(<); + default: + dbgs() << "Unhandled type for ICMP_SLT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_UGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ugt,Ty); + IMPLEMENT_POINTER_ICMP(>); + default: + dbgs() << "Unhandled type for ICMP_UGT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sgt,Ty); + IMPLEMENT_POINTER_ICMP(>); + default: + dbgs() << "Unhandled type for ICMP_SGT predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_ULE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(ule,Ty); + IMPLEMENT_POINTER_ICMP(<=); + default: + dbgs() << "Unhandled type for ICMP_ULE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SLE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sle,Ty); + IMPLEMENT_POINTER_ICMP(<=); + default: + dbgs() << "Unhandled type for ICMP_SLE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_UGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(uge,Ty); + IMPLEMENT_POINTER_ICMP(>=); + default: + dbgs() << "Unhandled type for ICMP_UGE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeICMP_SGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_INTEGER_ICMP(sge,Ty); + IMPLEMENT_POINTER_ICMP(>=); + default: + dbgs() << "Unhandled type for ICMP_SGE predicate: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +void Interpreter::visitICmpInst(ICmpInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getPredicate()) { + case ICmpInst::ICMP_EQ: R = executeICMP_EQ(Src1, Src2, Ty); break; + case ICmpInst::ICMP_NE: R = executeICMP_NE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_ULT: R = executeICMP_ULT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SLT: R = executeICMP_SLT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_UGT: R = executeICMP_UGT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SGT: R = executeICMP_SGT(Src1, Src2, Ty); break; + case ICmpInst::ICMP_ULE: R = executeICMP_ULE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SLE: R = executeICMP_SLE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_UGE: R = executeICMP_UGE(Src1, Src2, Ty); break; + case ICmpInst::ICMP_SGE: R = executeICMP_SGE(Src1, Src2, Ty); break; + default: + dbgs() << "Don't know how to handle this ICmp predicate!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +#define IMPLEMENT_FCMP(OP, TY) \ + case Type::TY##TyID: \ + Dest.IntVal = APInt(1,Src1.TY##Val OP Src2.TY##Val); \ + break + +static GenericValue executeFCMP_OEQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(==, Float); + IMPLEMENT_FCMP(==, Double); + default: + dbgs() << "Unhandled type for FCmp EQ instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_ONE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(!=, Float); + IMPLEMENT_FCMP(!=, Double); + + default: + dbgs() << "Unhandled type for FCmp NE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OLE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(<=, Float); + IMPLEMENT_FCMP(<=, Double); + default: + dbgs() << "Unhandled type for FCmp LE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(>=, Float); + IMPLEMENT_FCMP(>=, Double); + default: + dbgs() << "Unhandled type for FCmp GE instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OLT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(<, Float); + IMPLEMENT_FCMP(<, Double); + default: + dbgs() << "Unhandled type for FCmp LT instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +static GenericValue executeFCMP_OGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + switch (Ty->getTypeID()) { + IMPLEMENT_FCMP(>, Float); + IMPLEMENT_FCMP(>, Double); + default: + dbgs() << "Unhandled type for FCmp GT instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + return Dest; +} + +#define IMPLEMENT_UNORDERED(TY, X,Y) \ + if (TY->isFloatTy()) { \ + if (X.FloatVal != X.FloatVal || Y.FloatVal != Y.FloatVal) { \ + Dest.IntVal = APInt(1,true); \ + return Dest; \ + } \ + } else if (X.DoubleVal != X.DoubleVal || Y.DoubleVal != Y.DoubleVal) { \ + Dest.IntVal = APInt(1,true); \ + return Dest; \ + } + + +static GenericValue executeFCMP_UEQ(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OEQ(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UNE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_ONE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ULE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OLE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UGE(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OGE(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ULT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OLT(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_UGT(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + IMPLEMENT_UNORDERED(Ty, Src1, Src2) + return executeFCMP_OGT(Src1, Src2, Ty); +} + +static GenericValue executeFCMP_ORD(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + if (Ty->isFloatTy()) + Dest.IntVal = APInt(1,(Src1.FloatVal == Src1.FloatVal && + Src2.FloatVal == Src2.FloatVal)); + else + Dest.IntVal = APInt(1,(Src1.DoubleVal == Src1.DoubleVal && + Src2.DoubleVal == Src2.DoubleVal)); + return Dest; +} + +static GenericValue executeFCMP_UNO(GenericValue Src1, GenericValue Src2, + const Type *Ty) { + GenericValue Dest; + if (Ty->isFloatTy()) + Dest.IntVal = APInt(1,(Src1.FloatVal != Src1.FloatVal || + Src2.FloatVal != Src2.FloatVal)); + else + Dest.IntVal = APInt(1,(Src1.DoubleVal != Src1.DoubleVal || + Src2.DoubleVal != Src2.DoubleVal)); + return Dest; +} + +void Interpreter::visitFCmpInst(FCmpInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getPredicate()) { + case FCmpInst::FCMP_FALSE: R.IntVal = APInt(1,false); break; + case FCmpInst::FCMP_TRUE: R.IntVal = APInt(1,true); break; + case FCmpInst::FCMP_ORD: R = executeFCMP_ORD(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UNO: R = executeFCMP_UNO(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UEQ: R = executeFCMP_UEQ(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OEQ: R = executeFCMP_OEQ(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UNE: R = executeFCMP_UNE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ONE: R = executeFCMP_ONE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ULT: R = executeFCMP_ULT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OLT: R = executeFCMP_OLT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UGT: R = executeFCMP_UGT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OGT: R = executeFCMP_OGT(Src1, Src2, Ty); break; + case FCmpInst::FCMP_ULE: R = executeFCMP_ULE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OLE: R = executeFCMP_OLE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_UGE: R = executeFCMP_UGE(Src1, Src2, Ty); break; + case FCmpInst::FCMP_OGE: R = executeFCMP_OGE(Src1, Src2, Ty); break; + default: + dbgs() << "Don't know how to handle this FCmp predicate!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +static GenericValue executeCmpInst(unsigned predicate, GenericValue Src1, + GenericValue Src2, const Type *Ty) { + GenericValue Result; + switch (predicate) { + case ICmpInst::ICMP_EQ: return executeICMP_EQ(Src1, Src2, Ty); + case ICmpInst::ICMP_NE: return executeICMP_NE(Src1, Src2, Ty); + case ICmpInst::ICMP_UGT: return executeICMP_UGT(Src1, Src2, Ty); + case ICmpInst::ICMP_SGT: return executeICMP_SGT(Src1, Src2, Ty); + case ICmpInst::ICMP_ULT: return executeICMP_ULT(Src1, Src2, Ty); + case ICmpInst::ICMP_SLT: return executeICMP_SLT(Src1, Src2, Ty); + case ICmpInst::ICMP_UGE: return executeICMP_UGE(Src1, Src2, Ty); + case ICmpInst::ICMP_SGE: return executeICMP_SGE(Src1, Src2, Ty); + case ICmpInst::ICMP_ULE: return executeICMP_ULE(Src1, Src2, Ty); + case ICmpInst::ICMP_SLE: return executeICMP_SLE(Src1, Src2, Ty); + case FCmpInst::FCMP_ORD: return executeFCMP_ORD(Src1, Src2, Ty); + case FCmpInst::FCMP_UNO: return executeFCMP_UNO(Src1, Src2, Ty); + case FCmpInst::FCMP_OEQ: return executeFCMP_OEQ(Src1, Src2, Ty); + case FCmpInst::FCMP_UEQ: return executeFCMP_UEQ(Src1, Src2, Ty); + case FCmpInst::FCMP_ONE: return executeFCMP_ONE(Src1, Src2, Ty); + case FCmpInst::FCMP_UNE: return executeFCMP_UNE(Src1, Src2, Ty); + case FCmpInst::FCMP_OLT: return executeFCMP_OLT(Src1, Src2, Ty); + case FCmpInst::FCMP_ULT: return executeFCMP_ULT(Src1, Src2, Ty); + case FCmpInst::FCMP_OGT: return executeFCMP_OGT(Src1, Src2, Ty); + case FCmpInst::FCMP_UGT: return executeFCMP_UGT(Src1, Src2, Ty); + case FCmpInst::FCMP_OLE: return executeFCMP_OLE(Src1, Src2, Ty); + case FCmpInst::FCMP_ULE: return executeFCMP_ULE(Src1, Src2, Ty); + case FCmpInst::FCMP_OGE: return executeFCMP_OGE(Src1, Src2, Ty); + case FCmpInst::FCMP_UGE: return executeFCMP_UGE(Src1, Src2, Ty); + case FCmpInst::FCMP_FALSE: { + GenericValue Result; + Result.IntVal = APInt(1, false); + return Result; + } + case FCmpInst::FCMP_TRUE: { + GenericValue Result; + Result.IntVal = APInt(1, true); + return Result; + } + default: + dbgs() << "Unhandled Cmp predicate\n"; + llvm_unreachable(0); + } +} + +void Interpreter::visitBinaryOperator(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + const Type *Ty = I.getOperand(0)->getType(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue R; // Result + + switch (I.getOpcode()) { + case Instruction::Add: R.IntVal = Src1.IntVal + Src2.IntVal; break; + case Instruction::Sub: R.IntVal = Src1.IntVal - Src2.IntVal; break; + case Instruction::Mul: R.IntVal = Src1.IntVal * Src2.IntVal; break; + case Instruction::FAdd: executeFAddInst(R, Src1, Src2, Ty); break; + case Instruction::FSub: executeFSubInst(R, Src1, Src2, Ty); break; + case Instruction::FMul: executeFMulInst(R, Src1, Src2, Ty); break; + case Instruction::FDiv: executeFDivInst(R, Src1, Src2, Ty); break; + case Instruction::FRem: executeFRemInst(R, Src1, Src2, Ty); break; + case Instruction::UDiv: R.IntVal = Src1.IntVal.udiv(Src2.IntVal); break; + case Instruction::SDiv: R.IntVal = Src1.IntVal.sdiv(Src2.IntVal); break; + case Instruction::URem: R.IntVal = Src1.IntVal.urem(Src2.IntVal); break; + case Instruction::SRem: R.IntVal = Src1.IntVal.srem(Src2.IntVal); break; + case Instruction::And: R.IntVal = Src1.IntVal & Src2.IntVal; break; + case Instruction::Or: R.IntVal = Src1.IntVal | Src2.IntVal; break; + case Instruction::Xor: R.IntVal = Src1.IntVal ^ Src2.IntVal; break; + default: + dbgs() << "Don't know how to handle this binary operator!\n-->" << I; + llvm_unreachable(0); + } + + SetValue(&I, R, SF); +} + +static GenericValue executeSelectInst(GenericValue Src1, GenericValue Src2, + GenericValue Src3) { + return Src1.IntVal == 0 ? Src3 : Src2; +} + +void Interpreter::visitSelectInst(SelectInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Src3 = getOperandValue(I.getOperand(2), SF); + GenericValue R = executeSelectInst(Src1, Src2, Src3); + SetValue(&I, R, SF); +} + + +//===----------------------------------------------------------------------===// +// Terminator Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::exitCalled(GenericValue GV) { + // runAtExitHandlers() assumes there are no stack frames, but + // if exit() was called, then it had a stack frame. Blow away + // the stack before interpreting atexit handlers. + ECStack.clear(); + runAtExitHandlers(); + exit(GV.IntVal.zextOrTrunc(32).getZExtValue()); +} + +/// Pop the last stack frame off of ECStack and then copy the result +/// back into the result variable if we are not returning void. The +/// result variable may be the ExitValue, or the Value of the calling +/// CallInst if there was a previous stack frame. This method may +/// invalidate any ECStack iterators you have. This method also takes +/// care of switching to the normal destination BB, if we are returning +/// from an invoke. +/// +void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy, + GenericValue Result) { + // Pop the current stack frame. + ECStack.pop_back(); + + if (ECStack.empty()) { // Finished main. Put result into exit code... + if (RetTy && !RetTy->isVoidTy()) { // Nonvoid return type? + ExitValue = Result; // Capture the exit value of the program + } else { + memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); + } + } else { + // If we have a previous stack frame, and we have a previous call, + // fill in the return value... + ExecutionContext &CallingSF = ECStack.back(); + if (Instruction *I = CallingSF.Caller.getInstruction()) { + // Save result... + if (!CallingSF.Caller.getType()->isVoidTy()) + SetValue(I, Result, CallingSF); + if (InvokeInst *II = dyn_cast (I)) + SwitchToNewBasicBlock (II->getNormalDest (), CallingSF); + CallingSF.Caller = CallSite(); // We returned from the call... + } + } +} + +void Interpreter::visitReturnInst(ReturnInst &I) { + ExecutionContext &SF = ECStack.back(); + const Type *RetTy = Type::getVoidTy(I.getContext()); + GenericValue Result; + + // Save away the return value... (if we are not 'ret void') + if (I.getNumOperands()) { + RetTy = I.getReturnValue()->getType(); + Result = getOperandValue(I.getReturnValue(), SF); + } + + popStackAndReturnValueToCaller(RetTy, Result); +} + +void Interpreter::visitUnwindInst(UnwindInst &I) { + // Unwind stack + Instruction *Inst; + do { + ECStack.pop_back(); + if (ECStack.empty()) + report_fatal_error("Empty stack during unwind!"); + Inst = ECStack.back().Caller.getInstruction(); + } while (!(Inst && isa(Inst))); + + // Return from invoke + ExecutionContext &InvokingSF = ECStack.back(); + InvokingSF.Caller = CallSite(); + + // Go to exceptional destination BB of invoke instruction + SwitchToNewBasicBlock(cast(Inst)->getUnwindDest(), InvokingSF); +} + +void Interpreter::visitUnreachableInst(UnreachableInst &I) { + report_fatal_error("Program executed an 'unreachable' instruction!"); +} + +void Interpreter::visitBranchInst(BranchInst &I) { + ExecutionContext &SF = ECStack.back(); + BasicBlock *Dest; + + Dest = I.getSuccessor(0); // Uncond branches have a fixed dest... + if (!I.isUnconditional()) { + Value *Cond = I.getCondition(); + if (getOperandValue(Cond, SF).IntVal == 0) // If false cond... + Dest = I.getSuccessor(1); + } + SwitchToNewBasicBlock(Dest, SF); +} + +void Interpreter::visitSwitchInst(SwitchInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue CondVal = getOperandValue(I.getOperand(0), SF); + const Type *ElTy = I.getOperand(0)->getType(); + + // Check to see if any of the cases match... + BasicBlock *Dest = 0; + for (unsigned i = 2, e = I.getNumOperands(); i != e; i += 2) + if (executeICMP_EQ(CondVal, getOperandValue(I.getOperand(i), SF), ElTy) + .IntVal != 0) { + Dest = cast(I.getOperand(i+1)); + break; + } + + if (!Dest) Dest = I.getDefaultDest(); // No cases matched: use default + SwitchToNewBasicBlock(Dest, SF); +} + +void Interpreter::visitIndirectBrInst(IndirectBrInst &I) { + ExecutionContext &SF = ECStack.back(); + void *Dest = GVTOP(getOperandValue(I.getAddress(), SF)); + SwitchToNewBasicBlock((BasicBlock*)Dest, SF); +} + + +// SwitchToNewBasicBlock - This method is used to jump to a new basic block. +// This function handles the actual updating of block and instruction iterators +// as well as execution of all of the PHI nodes in the destination block. +// +// This method does this because all of the PHI nodes must be executed +// atomically, reading their inputs before any of the results are updated. Not +// doing this can cause problems if the PHI nodes depend on other PHI nodes for +// their inputs. If the input PHI node is updated before it is read, incorrect +// results can happen. Thus we use a two phase approach. +// +void Interpreter::SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF){ + BasicBlock *PrevBB = SF.CurBB; // Remember where we came from... + SF.CurBB = Dest; // Update CurBB to branch destination + SF.CurInst = SF.CurBB->begin(); // Update new instruction ptr... + + if (!isa(SF.CurInst)) return; // Nothing fancy to do + + // Loop over all of the PHI nodes in the current block, reading their inputs. + std::vector ResultValues; + + for (; PHINode *PN = dyn_cast(SF.CurInst); ++SF.CurInst) { + // Search for the value corresponding to this previous bb... + int i = PN->getBasicBlockIndex(PrevBB); + assert(i != -1 && "PHINode doesn't contain entry for predecessor??"); + Value *IncomingValue = PN->getIncomingValue(i); + + // Save the incoming value for this PHI node... + ResultValues.push_back(getOperandValue(IncomingValue, SF)); + } + + // Now loop over all of the PHI nodes setting their values... + SF.CurInst = SF.CurBB->begin(); + for (unsigned i = 0; isa(SF.CurInst); ++SF.CurInst, ++i) { + PHINode *PN = cast(SF.CurInst); + SetValue(PN, ResultValues[i], SF); + } +} + +//===----------------------------------------------------------------------===// +// Memory Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::visitAllocaInst(AllocaInst &I) { + ExecutionContext &SF = ECStack.back(); + + const Type *Ty = I.getType()->getElementType(); // Type to be allocated + + // Get the number of elements being allocated by the array... + unsigned NumElements = + getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue(); + + unsigned TypeSize = (size_t)TD.getTypeAllocSize(Ty); + + // Avoid malloc-ing zero bytes, use max()... + unsigned MemToAlloc = std::max(1U, NumElements * TypeSize); + + // Allocate enough memory to hold the type... + void *Memory = malloc(MemToAlloc); + + DEBUG(dbgs() << "Allocated Type: " << *Ty << " (" << TypeSize << " bytes) x " + << NumElements << " (Total: " << MemToAlloc << ") at " + << uintptr_t(Memory) << '\n'); + + GenericValue Result = PTOGV(Memory); + assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); + SetValue(&I, Result, SF); + + if (I.getOpcode() == Instruction::Alloca) + ECStack.back().Allocas.add(Memory); +} + +// getElementOffset - The workhorse for getelementptr. +// +GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, + ExecutionContext &SF) { + assert(Ptr->getType()->isPointerTy() && + "Cannot getElementOffset of a nonpointer type!"); + + uint64_t Total = 0; + + for (; I != E; ++I) { + if (const StructType *STy = dyn_cast(*I)) { + const StructLayout *SLO = TD.getStructLayout(STy); + + const ConstantInt *CPU = cast(I.getOperand()); + unsigned Index = unsigned(CPU->getZExtValue()); + + Total += SLO->getElementOffset(Index); + } else { + const SequentialType *ST = cast(*I); + // Get the index number for the array... which must be long type... + GenericValue IdxGV = getOperandValue(I.getOperand(), SF); + + int64_t Idx; + unsigned BitWidth = + cast(I.getOperand()->getType())->getBitWidth(); + if (BitWidth == 32) + Idx = (int64_t)(int32_t)IdxGV.IntVal.getZExtValue(); + else { + assert(BitWidth == 64 && "Invalid index type for getelementptr"); + Idx = (int64_t)IdxGV.IntVal.getZExtValue(); + } + Total += TD.getTypeAllocSize(ST->getElementType())*Idx; + } + } + + GenericValue Result; + Result.PointerVal = ((char*)getOperandValue(Ptr, SF).PointerVal) + Total; + DEBUG(dbgs() << "GEP Index " << Total << " bytes.\n"); + return Result; +} + +void Interpreter::visitGetElementPtrInst(GetElementPtrInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeGEPOperation(I.getPointerOperand(), + gep_type_begin(I), gep_type_end(I), SF), SF); +} + +void Interpreter::visitLoadInst(LoadInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); + GenericValue *Ptr = (GenericValue*)GVTOP(SRC); + GenericValue Result; + LoadValueFromMemory(Result, Ptr, I.getType()); + SetValue(&I, Result, SF); + if (I.isVolatile() && PrintVolatile) + dbgs() << "Volatile load " << I; +} + +void Interpreter::visitStoreInst(StoreInst &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Val = getOperandValue(I.getOperand(0), SF); + GenericValue SRC = getOperandValue(I.getPointerOperand(), SF); + StoreValueToMemory(Val, (GenericValue *)GVTOP(SRC), + I.getOperand(0)->getType()); + if (I.isVolatile() && PrintVolatile) + dbgs() << "Volatile store: " << I; +} + +//===----------------------------------------------------------------------===// +// Miscellaneous Instruction Implementations +//===----------------------------------------------------------------------===// + +void Interpreter::visitCallSite(CallSite CS) { + ExecutionContext &SF = ECStack.back(); + + // Check to see if this is an intrinsic function call... + Function *F = CS.getCalledFunction(); + if (F && F->isDeclaration()) + switch (F->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + break; + case Intrinsic::vastart: { // va_start + GenericValue ArgIndex; + ArgIndex.UIntPairVal.first = ECStack.size() - 1; + ArgIndex.UIntPairVal.second = 0; + SetValue(CS.getInstruction(), ArgIndex, SF); + return; + } + case Intrinsic::vaend: // va_end is a noop for the interpreter + return; + case Intrinsic::vacopy: // va_copy: dest = src + SetValue(CS.getInstruction(), getOperandValue(*CS.arg_begin(), SF), SF); + return; + default: + // If it is an unknown intrinsic function, use the intrinsic lowering + // class to transform it into hopefully tasty LLVM code. + // + BasicBlock::iterator me(CS.getInstruction()); + BasicBlock *Parent = CS.getInstruction()->getParent(); + bool atBegin(Parent->begin() == me); + if (!atBegin) + --me; + IL->LowerIntrinsicCall(cast(CS.getInstruction())); + + // Restore the CurInst pointer to the first instruction newly inserted, if + // any. + if (atBegin) { + SF.CurInst = Parent->begin(); + } else { + SF.CurInst = me; + ++SF.CurInst; + } + return; + } + + + SF.Caller = CS; + std::vector ArgVals; + const unsigned NumArgs = SF.Caller.arg_size(); + ArgVals.reserve(NumArgs); + uint16_t pNum = 1; + for (CallSite::arg_iterator i = SF.Caller.arg_begin(), + e = SF.Caller.arg_end(); i != e; ++i, ++pNum) { + Value *V = *i; + ArgVals.push_back(getOperandValue(V, SF)); + } + + // To handle indirect calls, we must get the pointer value from the argument + // and treat it as a function pointer. + GenericValue SRC = getOperandValue(SF.Caller.getCalledValue(), SF); + callFunction((Function*)GVTOP(SRC), ArgVals); +} + +void Interpreter::visitShl(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.shl(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +void Interpreter::visitLShr(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.lshr(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +void Interpreter::visitAShr(BinaryOperator &I) { + ExecutionContext &SF = ECStack.back(); + GenericValue Src1 = getOperandValue(I.getOperand(0), SF); + GenericValue Src2 = getOperandValue(I.getOperand(1), SF); + GenericValue Dest; + if (Src2.IntVal.getZExtValue() < Src1.IntVal.getBitWidth()) + Dest.IntVal = Src1.IntVal.ashr(Src2.IntVal.getZExtValue()); + else + Dest.IntVal = Src1.IntVal; + + SetValue(&I, Dest, SF); +} + +GenericValue Interpreter::executeTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.trunc(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeSExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.sext(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeZExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + const IntegerType *DITy = cast(DstTy); + unsigned DBitWidth = DITy->getBitWidth(); + Dest.IntVal = Src.IntVal.zext(DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeFPTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcVal->getType()->isDoubleTy() && DstTy->isFloatTy() && + "Invalid FPTrunc instruction"); + Dest.FloatVal = (float) Src.DoubleVal; + return Dest; +} + +GenericValue Interpreter::executeFPExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcVal->getType()->isFloatTy() && DstTy->isDoubleTy() && + "Invalid FPTrunc instruction"); + Dest.DoubleVal = (double) Src.FloatVal; + return Dest; +} + +GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToUI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + const Type *SrcTy = SrcVal->getType(); + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToSI instruction"); + + if (SrcTy->getTypeID() == Type::FloatTyID) + Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); + else + Dest.IntVal = APIntOps::RoundDoubleToAPInt(Src.DoubleVal, DBitWidth); + return Dest; +} + +GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(DstTy->isFloatingPointTy() && "Invalid UIToFP instruction"); + + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundAPIntToFloat(Src.IntVal); + else + Dest.DoubleVal = APIntOps::RoundAPIntToDouble(Src.IntVal); + return Dest; +} + +GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(DstTy->isFloatingPointTy() && "Invalid SIToFP instruction"); + + if (DstTy->getTypeID() == Type::FloatTyID) + Dest.FloatVal = APIntOps::RoundSignedAPIntToFloat(Src.IntVal); + else + Dest.DoubleVal = APIntOps::RoundSignedAPIntToDouble(Src.IntVal); + return Dest; + +} + +GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + uint32_t DBitWidth = cast(DstTy)->getBitWidth(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(SrcVal->getType()->isPointerTy() && "Invalid PtrToInt instruction"); + + Dest.IntVal = APInt(DBitWidth, (intptr_t) Src.PointerVal); + return Dest; +} + +GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + assert(DstTy->isPointerTy() && "Invalid PtrToInt instruction"); + + uint32_t PtrSize = TD.getPointerSizeInBits(); + if (PtrSize != Src.IntVal.getBitWidth()) + Src.IntVal = Src.IntVal.zextOrTrunc(PtrSize); + + Dest.PointerVal = PointerTy(intptr_t(Src.IntVal.getZExtValue())); + return Dest; +} + +GenericValue Interpreter::executeBitCastInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF) { + + const Type *SrcTy = SrcVal->getType(); + GenericValue Dest, Src = getOperandValue(SrcVal, SF); + if (DstTy->isPointerTy()) { + assert(SrcTy->isPointerTy() && "Invalid BitCast"); + Dest.PointerVal = Src.PointerVal; + } else if (DstTy->isIntegerTy()) { + if (SrcTy->isFloatTy()) { + Dest.IntVal = APInt::floatToBits(Src.FloatVal); + } else if (SrcTy->isDoubleTy()) { + Dest.IntVal = APInt::doubleToBits(Src.DoubleVal); + } else if (SrcTy->isIntegerTy()) { + Dest.IntVal = Src.IntVal; + } else + llvm_unreachable("Invalid BitCast"); + } else if (DstTy->isFloatTy()) { + if (SrcTy->isIntegerTy()) + Dest.FloatVal = Src.IntVal.bitsToFloat(); + else + Dest.FloatVal = Src.FloatVal; + } else if (DstTy->isDoubleTy()) { + if (SrcTy->isIntegerTy()) + Dest.DoubleVal = Src.IntVal.bitsToDouble(); + else + Dest.DoubleVal = Src.DoubleVal; + } else + llvm_unreachable("Invalid Bitcast"); + + return Dest; +} + +void Interpreter::visitTruncInst(TruncInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeTruncInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitSExtInst(SExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeSExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitZExtInst(ZExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeZExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPTruncInst(FPTruncInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPTruncInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPExtInst(FPExtInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPExtInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitUIToFPInst(UIToFPInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeUIToFPInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitSIToFPInst(SIToFPInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeSIToFPInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPToUIInst(FPToUIInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPToUIInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitFPToSIInst(FPToSIInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeFPToSIInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitPtrToIntInst(PtrToIntInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executePtrToIntInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitIntToPtrInst(IntToPtrInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeIntToPtrInst(I.getOperand(0), I.getType(), SF), SF); +} + +void Interpreter::visitBitCastInst(BitCastInst &I) { + ExecutionContext &SF = ECStack.back(); + SetValue(&I, executeBitCastInst(I.getOperand(0), I.getType(), SF), SF); +} + +#define IMPLEMENT_VAARG(TY) \ + case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break + +void Interpreter::visitVAArgInst(VAArgInst &I) { + ExecutionContext &SF = ECStack.back(); + + // Get the incoming valist parameter. LLI treats the valist as a + // (ec-stack-depth var-arg-index) pair. + GenericValue VAList = getOperandValue(I.getOperand(0), SF); + GenericValue Dest; + GenericValue Src = ECStack[VAList.UIntPairVal.first] + .VarArgs[VAList.UIntPairVal.second]; + const Type *Ty = I.getType(); + switch (Ty->getTypeID()) { + case Type::IntegerTyID: Dest.IntVal = Src.IntVal; + IMPLEMENT_VAARG(Pointer); + IMPLEMENT_VAARG(Float); + IMPLEMENT_VAARG(Double); + default: + dbgs() << "Unhandled dest type for vaarg instruction: " << *Ty << "\n"; + llvm_unreachable(0); + } + + // Set the Value of this Instruction. + SetValue(&I, Dest, SF); + + // Move the pointer to the next vararg. + ++VAList.UIntPairVal.second; +} + +GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE, + ExecutionContext &SF) { + switch (CE->getOpcode()) { + case Instruction::Trunc: + return executeTruncInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::ZExt: + return executeZExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::SExt: + return executeSExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPTrunc: + return executeFPTruncInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPExt: + return executeFPExtInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::UIToFP: + return executeUIToFPInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::SIToFP: + return executeSIToFPInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPToUI: + return executeFPToUIInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::FPToSI: + return executeFPToSIInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::PtrToInt: + return executePtrToIntInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::IntToPtr: + return executeIntToPtrInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::BitCast: + return executeBitCastInst(CE->getOperand(0), CE->getType(), SF); + case Instruction::GetElementPtr: + return executeGEPOperation(CE->getOperand(0), gep_type_begin(CE), + gep_type_end(CE), SF); + case Instruction::FCmp: + case Instruction::ICmp: + return executeCmpInst(CE->getPredicate(), + getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + CE->getOperand(0)->getType()); + case Instruction::Select: + return executeSelectInst(getOperandValue(CE->getOperand(0), SF), + getOperandValue(CE->getOperand(1), SF), + getOperandValue(CE->getOperand(2), SF)); + default : + break; + } + + // The cases below here require a GenericValue parameter for the result + // so we initialize one, compute it and then return it. + GenericValue Op0 = getOperandValue(CE->getOperand(0), SF); + GenericValue Op1 = getOperandValue(CE->getOperand(1), SF); + GenericValue Dest; + const Type * Ty = CE->getOperand(0)->getType(); + switch (CE->getOpcode()) { + case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break; + case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break; + case Instruction::Mul: Dest.IntVal = Op0.IntVal * Op1.IntVal; break; + case Instruction::FAdd: executeFAddInst(Dest, Op0, Op1, Ty); break; + case Instruction::FSub: executeFSubInst(Dest, Op0, Op1, Ty); break; + case Instruction::FMul: executeFMulInst(Dest, Op0, Op1, Ty); break; + case Instruction::FDiv: executeFDivInst(Dest, Op0, Op1, Ty); break; + case Instruction::FRem: executeFRemInst(Dest, Op0, Op1, Ty); break; + case Instruction::SDiv: Dest.IntVal = Op0.IntVal.sdiv(Op1.IntVal); break; + case Instruction::UDiv: Dest.IntVal = Op0.IntVal.udiv(Op1.IntVal); break; + case Instruction::URem: Dest.IntVal = Op0.IntVal.urem(Op1.IntVal); break; + case Instruction::SRem: Dest.IntVal = Op0.IntVal.srem(Op1.IntVal); break; + case Instruction::And: Dest.IntVal = Op0.IntVal & Op1.IntVal; break; + case Instruction::Or: Dest.IntVal = Op0.IntVal | Op1.IntVal; break; + case Instruction::Xor: Dest.IntVal = Op0.IntVal ^ Op1.IntVal; break; + case Instruction::Shl: + Dest.IntVal = Op0.IntVal.shl(Op1.IntVal.getZExtValue()); + break; + case Instruction::LShr: + Dest.IntVal = Op0.IntVal.lshr(Op1.IntVal.getZExtValue()); + break; + case Instruction::AShr: + Dest.IntVal = Op0.IntVal.ashr(Op1.IntVal.getZExtValue()); + break; + default: + dbgs() << "Unhandled ConstantExpr: " << *CE << "\n"; + llvm_unreachable(0); + return GenericValue(); + } + return Dest; +} + +GenericValue Interpreter::getOperandValue(Value *V, ExecutionContext &SF) { + if (ConstantExpr *CE = dyn_cast(V)) { + return getConstantExprValue(CE, SF); + } else if (Constant *CPV = dyn_cast(V)) { + return getConstantValue(CPV); + } else if (GlobalValue *GV = dyn_cast(V)) { + return PTOGV(getPointerToGlobal(GV)); + } else { + return SF.Values[V]; + } +} + +//===----------------------------------------------------------------------===// +// Dispatch and Execution Code +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// callFunction - Execute the specified function... +// +void Interpreter::callFunction(Function *F, + const std::vector &ArgVals) { + assert((ECStack.empty() || ECStack.back().Caller.getInstruction() == 0 || + ECStack.back().Caller.arg_size() == ArgVals.size()) && + "Incorrect number of arguments passed into function call!"); + // Make a new stack frame... and fill it in. + ECStack.push_back(ExecutionContext()); + ExecutionContext &StackFrame = ECStack.back(); + StackFrame.CurFunction = F; + + // Special handling for external functions. + if (F->isDeclaration()) { + GenericValue Result = callExternalFunction (F, ArgVals); + // Simulate a 'ret' instruction of the appropriate type. + popStackAndReturnValueToCaller (F->getReturnType (), Result); + return; + } + + // Get pointers to first LLVM BB & Instruction in function. + StackFrame.CurBB = F->begin(); + StackFrame.CurInst = StackFrame.CurBB->begin(); + + // Run through the function arguments and initialize their values... + assert((ArgVals.size() == F->arg_size() || + (ArgVals.size() > F->arg_size() && F->getFunctionType()->isVarArg()))&& + "Invalid number of values passed to function invocation!"); + + // Handle non-varargs arguments... + unsigned i = 0; + for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); + AI != E; ++AI, ++i) + SetValue(AI, ArgVals[i], StackFrame); + + // Handle varargs arguments... + StackFrame.VarArgs.assign(ArgVals.begin()+i, ArgVals.end()); +} + + +void Interpreter::run() { + while (!ECStack.empty()) { + // Interpret a single instruction & increment the "PC". + ExecutionContext &SF = ECStack.back(); // Current stack frame + Instruction &I = *SF.CurInst++; // Increment before execute + + // Track the number of dynamic instructions executed. + ++NumDynamicInsts; + + DEBUG(dbgs() << "About to interpret: " << I); + visit(I); // Dispatch to one of the visit* methods... +#if 0 + // This is not safe, as visiting the instruction could lower it and free I. +DEBUG( + if (!isa(I) && !isa(I) && + I.getType() != Type::VoidTy) { + dbgs() << " --> "; + const GenericValue &Val = SF.Values[&I]; + switch (I.getType()->getTypeID()) { + default: llvm_unreachable("Invalid GenericValue Type"); + case Type::VoidTyID: dbgs() << "void"; break; + case Type::FloatTyID: dbgs() << "float " << Val.FloatVal; break; + case Type::DoubleTyID: dbgs() << "double " << Val.DoubleVal; break; + case Type::PointerTyID: dbgs() << "void* " << intptr_t(Val.PointerVal); + break; + case Type::IntegerTyID: + dbgs() << "i" << Val.IntVal.getBitWidth() << " " + << Val.IntVal.toStringUnsigned(10) + << " (0x" << Val.IntVal.toStringUnsigned(16) << ")\n"; + break; + } + }); +#endif + } +} diff --git a/final/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/final/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp new file mode 100644 index 00000000000..062256a2ac7 --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -0,0 +1,492 @@ +//===-- ExternalFunctions.cpp - Implement External Functions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains both code to deal with invoking "external" functions, but +// also contains code that implements "exported" external functions. +// +// There are currently two mechanisms for handling external functions in the +// Interpreter. The first is to implement lle_* wrapper functions that are +// specific to well-known library functions which manually translate the +// arguments from GenericValues and make the call. If such a wrapper does +// not exist, and libffi is available, then the Interpreter will attempt to +// invoke the function using libffi, after finding its address. +// +//===----------------------------------------------------------------------===// + +#include "Interpreter.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/Config/config.h" // Detect libffi +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/Mutex.h" +#include +#include +#include +#include +#include + +#ifdef HAVE_FFI_CALL +#ifdef HAVE_FFI_H +#include +#define USE_LIBFFI +#elif HAVE_FFI_FFI_H +#include +#define USE_LIBFFI +#endif +#endif + +using namespace llvm; + +static ManagedStatic FunctionsLock; + +typedef GenericValue (*ExFunc)(const FunctionType *, + const std::vector &); +static ManagedStatic > ExportedFunctions; +static std::map FuncNames; + +#ifdef USE_LIBFFI +typedef void (*RawFunc)(); +static ManagedStatic > RawFunctions; +#endif + +static Interpreter *TheInterpreter; + +static char getTypeID(const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return 'V'; + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 1: return 'o'; + case 8: return 'B'; + case 16: return 'S'; + case 32: return 'I'; + case 64: return 'L'; + default: return 'N'; + } + case Type::FloatTyID: return 'F'; + case Type::DoubleTyID: return 'D'; + case Type::PointerTyID: return 'P'; + case Type::FunctionTyID:return 'M'; + case Type::StructTyID: return 'T'; + case Type::ArrayTyID: return 'A'; + case Type::OpaqueTyID: return 'O'; + default: return 'U'; + } +} + +// Try to find address of external function given a Function object. +// Please note, that interpreter doesn't know how to assemble a +// real call in general case (this is JIT job), that's why it assumes, +// that all external functions has the same (and pretty "general") signature. +// The typical example of such functions are "lle_X_" ones. +static ExFunc lookupFunction(const Function *F) { + // Function not found, look it up... start by figuring out what the + // composite function name should be. + std::string ExtName = "lle_"; + const FunctionType *FT = F->getFunctionType(); + for (unsigned i = 0, e = FT->getNumContainedTypes(); i != e; ++i) + ExtName += getTypeID(FT->getContainedType(i)); + ExtName + "_" + F->getNameStr(); + + sys::ScopedLock Writer(*FunctionsLock); + ExFunc FnPtr = FuncNames[ExtName]; + if (FnPtr == 0) + FnPtr = FuncNames["lle_X_" + F->getNameStr()]; + if (FnPtr == 0) // Try calling a generic function... if it exists... + FnPtr = (ExFunc)(intptr_t) + sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_"+F->getNameStr()); + if (FnPtr != 0) + ExportedFunctions->insert(std::make_pair(F, FnPtr)); // Cache for later + return FnPtr; +} + +#ifdef USE_LIBFFI +static ffi_type *ffiTypeFor(const Type *Ty) { + switch (Ty->getTypeID()) { + case Type::VoidTyID: return &ffi_type_void; + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 8: return &ffi_type_sint8; + case 16: return &ffi_type_sint16; + case 32: return &ffi_type_sint32; + case 64: return &ffi_type_sint64; + } + case Type::FloatTyID: return &ffi_type_float; + case Type::DoubleTyID: return &ffi_type_double; + case Type::PointerTyID: return &ffi_type_pointer; + default: break; + } + // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. + report_fatal_error("Type could not be mapped for use with libffi."); + return NULL; +} + +static void *ffiValueFor(const Type *Ty, const GenericValue &AV, + void *ArgDataPtr) { + switch (Ty->getTypeID()) { + case Type::IntegerTyID: + switch (cast(Ty)->getBitWidth()) { + case 8: { + int8_t *I8Ptr = (int8_t *) ArgDataPtr; + *I8Ptr = (int8_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 16: { + int16_t *I16Ptr = (int16_t *) ArgDataPtr; + *I16Ptr = (int16_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 32: { + int32_t *I32Ptr = (int32_t *) ArgDataPtr; + *I32Ptr = (int32_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + case 64: { + int64_t *I64Ptr = (int64_t *) ArgDataPtr; + *I64Ptr = (int64_t) AV.IntVal.getZExtValue(); + return ArgDataPtr; + } + } + case Type::FloatTyID: { + float *FloatPtr = (float *) ArgDataPtr; + *FloatPtr = AV.FloatVal; + return ArgDataPtr; + } + case Type::DoubleTyID: { + double *DoublePtr = (double *) ArgDataPtr; + *DoublePtr = AV.DoubleVal; + return ArgDataPtr; + } + case Type::PointerTyID: { + void **PtrPtr = (void **) ArgDataPtr; + *PtrPtr = GVTOP(AV); + return ArgDataPtr; + } + default: break; + } + // TODO: Support other types such as StructTyID, ArrayTyID, OpaqueTyID, etc. + report_fatal_error("Type value could not be mapped for use with libffi."); + return NULL; +} + +static bool ffiInvoke(RawFunc Fn, Function *F, + const std::vector &ArgVals, + const TargetData *TD, GenericValue &Result) { + ffi_cif cif; + const FunctionType *FTy = F->getFunctionType(); + const unsigned NumArgs = F->arg_size(); + + // TODO: We don't have type information about the remaining arguments, because + // this information is never passed into ExecutionEngine::runFunction(). + if (ArgVals.size() > NumArgs && F->isVarArg()) { + report_fatal_error("Calling external var arg function '" + F->getName() + + "' is not supported by the Interpreter."); + } + + unsigned ArgBytes = 0; + + std::vector args(NumArgs); + for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); + A != E; ++A) { + const unsigned ArgNo = A->getArgNo(); + const Type *ArgTy = FTy->getParamType(ArgNo); + args[ArgNo] = ffiTypeFor(ArgTy); + ArgBytes += TD->getTypeStoreSize(ArgTy); + } + + SmallVector ArgData; + ArgData.resize(ArgBytes); + uint8_t *ArgDataPtr = ArgData.data(); + SmallVector values(NumArgs); + for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); + A != E; ++A) { + const unsigned ArgNo = A->getArgNo(); + const Type *ArgTy = FTy->getParamType(ArgNo); + values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); + ArgDataPtr += TD->getTypeStoreSize(ArgTy); + } + + const Type *RetTy = FTy->getReturnType(); + ffi_type *rtype = ffiTypeFor(RetTy); + + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, &args[0]) == FFI_OK) { + SmallVector ret; + if (RetTy->getTypeID() != Type::VoidTyID) + ret.resize(TD->getTypeStoreSize(RetTy)); + ffi_call(&cif, Fn, ret.data(), values.data()); + switch (RetTy->getTypeID()) { + case Type::IntegerTyID: + switch (cast(RetTy)->getBitWidth()) { + case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break; + case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break; + case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break; + case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break; + } + break; + case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break; + case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break; + case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break; + default: break; + } + return true; + } + + return false; +} +#endif // USE_LIBFFI + +GenericValue Interpreter::callExternalFunction(Function *F, + const std::vector &ArgVals) { + TheInterpreter = this; + + FunctionsLock->acquire(); + + // Do a lookup to see if the function is in our cache... this should just be a + // deferred annotation! + std::map::iterator FI = ExportedFunctions->find(F); + if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F) + : FI->second) { + FunctionsLock->release(); + return Fn(F->getFunctionType(), ArgVals); + } + +#ifdef USE_LIBFFI + std::map::iterator RF = RawFunctions->find(F); + RawFunc RawFn; + if (RF == RawFunctions->end()) { + RawFn = (RawFunc)(intptr_t) + sys::DynamicLibrary::SearchForAddressOfSymbol(F->getName()); + if (!RawFn) + RawFn = (RawFunc)(intptr_t)getPointerToGlobalIfAvailable(F); + if (RawFn != 0) + RawFunctions->insert(std::make_pair(F, RawFn)); // Cache for later + } else { + RawFn = RF->second; + } + + FunctionsLock->release(); + + GenericValue Result; + if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getTargetData(), Result)) + return Result; +#endif // USE_LIBFFI + + if (F->getName() == "__main") + errs() << "Tried to execute an unknown external function: " + << F->getType()->getDescription() << " __main\n"; + else + report_fatal_error("Tried to execute an unknown external function: " + + F->getType()->getDescription() + " " +F->getName()); +#ifndef USE_LIBFFI + errs() << "Recompiling LLVM with --enable-libffi might help.\n"; +#endif + return GenericValue(); +} + + +//===----------------------------------------------------------------------===// +// Functions "exported" to the running application... +// + +// Visual Studio warns about returning GenericValue in extern "C" linkage +#ifdef _MSC_VER + #pragma warning(disable : 4190) +#endif + +extern "C" { // Don't add C++ manglings to llvm mangling :) + +// void atexit(Function*) +GenericValue lle_X_atexit(const FunctionType *FT, + const std::vector &Args) { + assert(Args.size() == 1); + TheInterpreter->addAtExitHandler((Function*)GVTOP(Args[0])); + GenericValue GV; + GV.IntVal = 0; + return GV; +} + +// void exit(int) +GenericValue lle_X_exit(const FunctionType *FT, + const std::vector &Args) { + TheInterpreter->exitCalled(Args[0]); + return GenericValue(); +} + +// void abort(void) +GenericValue lle_X_abort(const FunctionType *FT, + const std::vector &Args) { + //FIXME: should we report or raise here? + //report_fatal_error("Interpreted program raised SIGABRT"); + raise (SIGABRT); + return GenericValue(); +} + +// int sprintf(char *, const char *, ...) - a very rough implementation to make +// output useful. +GenericValue lle_X_sprintf(const FunctionType *FT, + const std::vector &Args) { + char *OutputBuffer = (char *)GVTOP(Args[0]); + const char *FmtStr = (const char *)GVTOP(Args[1]); + unsigned ArgNo = 2; + + // printf should return # chars printed. This is completely incorrect, but + // close enough for now. + GenericValue GV; + GV.IntVal = APInt(32, strlen(FmtStr)); + while (1) { + switch (*FmtStr) { + case 0: return GV; // Null terminator... + default: // Normal nonspecial character + sprintf(OutputBuffer++, "%c", *FmtStr++); + break; + case '\\': { // Handle escape codes + sprintf(OutputBuffer, "%c%c", *FmtStr, *(FmtStr+1)); + FmtStr += 2; OutputBuffer += 2; + break; + } + case '%': { // Handle format specifiers + char FmtBuf[100] = "", Buffer[1000] = ""; + char *FB = FmtBuf; + *FB++ = *FmtStr++; + char Last = *FB++ = *FmtStr++; + unsigned HowLong = 0; + while (Last != 'c' && Last != 'd' && Last != 'i' && Last != 'u' && + Last != 'o' && Last != 'x' && Last != 'X' && Last != 'e' && + Last != 'E' && Last != 'g' && Last != 'G' && Last != 'f' && + Last != 'p' && Last != 's' && Last != '%') { + if (Last == 'l' || Last == 'L') HowLong++; // Keep track of l's + Last = *FB++ = *FmtStr++; + } + *FB = 0; + + switch (Last) { + case '%': + memcpy(Buffer, "%", 2); break; + case 'c': + sprintf(Buffer, FmtBuf, uint32_t(Args[ArgNo++].IntVal.getZExtValue())); + break; + case 'd': case 'i': + case 'u': case 'o': + case 'x': case 'X': + if (HowLong >= 1) { + if (HowLong == 1 && + TheInterpreter->getTargetData()->getPointerSizeInBits() == 64 && + sizeof(long) < sizeof(int64_t)) { + // Make sure we use %lld with a 64 bit argument because we might be + // compiling LLI on a 32 bit compiler. + unsigned Size = strlen(FmtBuf); + FmtBuf[Size] = FmtBuf[Size-1]; + FmtBuf[Size+1] = 0; + FmtBuf[Size-1] = 'l'; + } + sprintf(Buffer, FmtBuf, Args[ArgNo++].IntVal.getZExtValue()); + } else + sprintf(Buffer, FmtBuf,uint32_t(Args[ArgNo++].IntVal.getZExtValue())); + break; + case 'e': case 'E': case 'g': case 'G': case 'f': + sprintf(Buffer, FmtBuf, Args[ArgNo++].DoubleVal); break; + case 'p': + sprintf(Buffer, FmtBuf, (void*)GVTOP(Args[ArgNo++])); break; + case 's': + sprintf(Buffer, FmtBuf, (char*)GVTOP(Args[ArgNo++])); break; + default: + errs() << ""; + ArgNo++; break; + } + size_t Len = strlen(Buffer); + memcpy(OutputBuffer, Buffer, Len + 1); + OutputBuffer += Len; + } + break; + } + } + return GV; +} + +// int printf(const char *, ...) - a very rough implementation to make output +// useful. +GenericValue lle_X_printf(const FunctionType *FT, + const std::vector &Args) { + char Buffer[10000]; + std::vector NewArgs; + NewArgs.push_back(PTOGV((void*)&Buffer[0])); + NewArgs.insert(NewArgs.end(), Args.begin(), Args.end()); + GenericValue GV = lle_X_sprintf(FT, NewArgs); + outs() << Buffer; + return GV; +} + +// int sscanf(const char *format, ...); +GenericValue lle_X_sscanf(const FunctionType *FT, + const std::vector &args) { + assert(args.size() < 10 && "Only handle up to 10 args to sscanf right now!"); + + char *Args[10]; + for (unsigned i = 0; i < args.size(); ++i) + Args[i] = (char*)GVTOP(args[i]); + + GenericValue GV; + GV.IntVal = APInt(32, sscanf(Args[0], Args[1], Args[2], Args[3], Args[4], + Args[5], Args[6], Args[7], Args[8], Args[9])); + return GV; +} + +// int scanf(const char *format, ...); +GenericValue lle_X_scanf(const FunctionType *FT, + const std::vector &args) { + assert(args.size() < 10 && "Only handle up to 10 args to scanf right now!"); + + char *Args[10]; + for (unsigned i = 0; i < args.size(); ++i) + Args[i] = (char*)GVTOP(args[i]); + + GenericValue GV; + GV.IntVal = APInt(32, scanf( Args[0], Args[1], Args[2], Args[3], Args[4], + Args[5], Args[6], Args[7], Args[8], Args[9])); + return GV; +} + +// int fprintf(FILE *, const char *, ...) - a very rough implementation to make +// output useful. +GenericValue lle_X_fprintf(const FunctionType *FT, + const std::vector &Args) { + assert(Args.size() >= 2); + char Buffer[10000]; + std::vector NewArgs; + NewArgs.push_back(PTOGV(Buffer)); + NewArgs.insert(NewArgs.end(), Args.begin()+1, Args.end()); + GenericValue GV = lle_X_sprintf(FT, NewArgs); + + fputs(Buffer, (FILE *) GVTOP(Args[0])); + return GV; +} + +} // End extern "C" + +// Done with externals; turn the warning back on +#ifdef _MSC_VER + #pragma warning(default: 4190) +#endif + + +void Interpreter::initializeExternalFunctions() { + sys::ScopedLock Writer(*FunctionsLock); + FuncNames["lle_X_atexit"] = lle_X_atexit; + FuncNames["lle_X_exit"] = lle_X_exit; + FuncNames["lle_X_abort"] = lle_X_abort; + + FuncNames["lle_X_printf"] = lle_X_printf; + FuncNames["lle_X_sprintf"] = lle_X_sprintf; + FuncNames["lle_X_sscanf"] = lle_X_sscanf; + FuncNames["lle_X_scanf"] = lle_X_scanf; + FuncNames["lle_X_fprintf"] = lle_X_fprintf; +} diff --git a/final/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/final/lib/ExecutionEngine/Interpreter/Interpreter.cpp new file mode 100644 index 00000000000..43e34533c7b --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -0,0 +1,98 @@ +//===- Interpreter.cpp - Top-Level LLVM Interpreter Implementation --------===// +// +// 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 top-level functionality for the LLVM interpreter. +// This interpreter is designed to be a very simple, portable, inefficient +// interpreter. +// +//===----------------------------------------------------------------------===// + +#include "Interpreter.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include +using namespace llvm; + +namespace { + +static struct RegisterInterp { + RegisterInterp() { Interpreter::Register(); } +} InterpRegistrator; + +} + +extern "C" void LLVMLinkInInterpreter() { } + +/// create - Create a new interpreter object. This can never fail. +/// +ExecutionEngine *Interpreter::create(Module *M, std::string* ErrStr) { + // Tell this Module to materialize everything and release the GVMaterializer. + if (M->MaterializeAllPermanently(ErrStr)) + // We got an error, just return 0 + return 0; + + return new Interpreter(M); +} + +//===----------------------------------------------------------------------===// +// Interpreter ctor - Initialize stuff +// +Interpreter::Interpreter(Module *M) + : ExecutionEngine(M), TD(M) { + + memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); + setTargetData(&TD); + // Initialize the "backend" + initializeExecutionEngine(); + initializeExternalFunctions(); + emitGlobals(); + + IL = new IntrinsicLowering(TD); +} + +Interpreter::~Interpreter() { + delete IL; +} + +void Interpreter::runAtExitHandlers () { + while (!AtExitHandlers.empty()) { + callFunction(AtExitHandlers.back(), std::vector()); + AtExitHandlers.pop_back(); + run(); + } +} + +/// run - Start execution with the specified function and arguments. +/// +GenericValue +Interpreter::runFunction(Function *F, + const std::vector &ArgValues) { + assert (F && "Function *F was null at entry to run()"); + + // Try extra hard not to pass extra args to a function that isn't + // expecting them. C programmers frequently bend the rules and + // declare main() with fewer parameters than it actually gets + // passed, and the interpreter barfs if you pass a function more + // parameters than it is declared to take. This does not attempt to + // take into account gratuitous differences in declared types, + // though. + std::vector ActualArgs; + const unsigned ArgCount = F->getFunctionType()->getNumParams(); + for (unsigned i = 0; i < ArgCount; ++i) + ActualArgs.push_back(ArgValues[i]); + + // Set up the function call. + callFunction(F, ActualArgs); + + // Start executing the function. + run(); + + return ExitValue; +} diff --git a/final/lib/ExecutionEngine/Interpreter/Interpreter.h b/final/lib/ExecutionEngine/Interpreter/Interpreter.h new file mode 100644 index 00000000000..bfebe3debfc --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -0,0 +1,242 @@ +//===-- Interpreter.h ------------------------------------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines the interpreter structure +// +//===----------------------------------------------------------------------===// + +#ifndef LLI_INTERPRETER_H +#define LLI_INTERPRETER_H + +#include "llvm/Function.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/InstVisitor.h" +#include "llvm/Support/raw_ostream.h" +namespace llvm { + +class IntrinsicLowering; +struct FunctionInfo; +template class generic_gep_type_iterator; +class ConstantExpr; +typedef generic_gep_type_iterator gep_type_iterator; + + +// AllocaHolder - Object to track all of the blocks of memory allocated by +// alloca. When the function returns, this object is popped off the execution +// stack, which causes the dtor to be run, which frees all the alloca'd memory. +// +class AllocaHolder { + friend class AllocaHolderHandle; + std::vector Allocations; + unsigned RefCnt; +public: + AllocaHolder() : RefCnt(0) {} + void add(void *mem) { Allocations.push_back(mem); } + ~AllocaHolder() { + for (unsigned i = 0; i < Allocations.size(); ++i) + free(Allocations[i]); + } +}; + +// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into +// a vector... +// +class AllocaHolderHandle { + AllocaHolder *H; +public: + AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } + AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } + ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } + + void add(void *mem) { H->add(mem); } +}; + +typedef std::vector ValuePlaneTy; + +// ExecutionContext struct - This struct represents one stack frame currently +// executing. +// +struct ExecutionContext { + Function *CurFunction;// The currently executing function + BasicBlock *CurBB; // The currently executing BB + BasicBlock::iterator CurInst; // The next instruction to execute + std::map Values; // LLVM values used in this invocation + std::vector VarArgs; // Values passed through an ellipsis + CallSite Caller; // Holds the call that called subframes. + // NULL if main func or debugger invoked fn + AllocaHolderHandle Allocas; // Track memory allocated by alloca +}; + +// Interpreter - This class represents the entirety of the interpreter. +// +class Interpreter : public ExecutionEngine, public InstVisitor { + GenericValue ExitValue; // The return value of the called function + TargetData TD; + IntrinsicLowering *IL; + + // The runtime stack of executing code. The top of the stack is the current + // function record. + std::vector ECStack; + + // AtExitHandlers - List of functions to call when the program exits, + // registered with the atexit() library function. + std::vector AtExitHandlers; + +public: + explicit Interpreter(Module *M); + ~Interpreter(); + + /// runAtExitHandlers - Run any functions registered by the program's calls to + /// atexit(3), which we intercept and store in AtExitHandlers. + /// + void runAtExitHandlers(); + + static void Register() { + InterpCtor = create; + } + + /// create - Create an interpreter ExecutionEngine. This can never fail. + /// + static ExecutionEngine *create(Module *M, std::string *ErrorStr = 0); + + /// run - Start execution with the specified function and arguments. + /// + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues); + + /// recompileAndRelinkFunction - For the interpreter, functions are always + /// up-to-date. + /// + virtual void *recompileAndRelinkFunction(Function *F) { + return getPointerToFunction(F); + } + + /// freeMachineCodeForFunction - The interpreter does not generate any code. + /// + void freeMachineCodeForFunction(Function *F) { } + + // Methods used to execute code: + // Place a call on the stack + void callFunction(Function *F, const std::vector &ArgVals); + void run(); // Execute instructions until nothing left to do + + // Opcode Implementations + void visitReturnInst(ReturnInst &I); + void visitBranchInst(BranchInst &I); + void visitSwitchInst(SwitchInst &I); + void visitIndirectBrInst(IndirectBrInst &I); + + void visitBinaryOperator(BinaryOperator &I); + void visitICmpInst(ICmpInst &I); + void visitFCmpInst(FCmpInst &I); + void visitAllocaInst(AllocaInst &I); + void visitLoadInst(LoadInst &I); + void visitStoreInst(StoreInst &I); + void visitGetElementPtrInst(GetElementPtrInst &I); + void visitPHINode(PHINode &PN) { + llvm_unreachable("PHI nodes already handled!"); + } + void visitTruncInst(TruncInst &I); + void visitZExtInst(ZExtInst &I); + void visitSExtInst(SExtInst &I); + void visitFPTruncInst(FPTruncInst &I); + void visitFPExtInst(FPExtInst &I); + void visitUIToFPInst(UIToFPInst &I); + void visitSIToFPInst(SIToFPInst &I); + void visitFPToUIInst(FPToUIInst &I); + void visitFPToSIInst(FPToSIInst &I); + void visitPtrToIntInst(PtrToIntInst &I); + void visitIntToPtrInst(IntToPtrInst &I); + void visitBitCastInst(BitCastInst &I); + void visitSelectInst(SelectInst &I); + + + void visitCallSite(CallSite CS); + void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } + void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } + void visitUnwindInst(UnwindInst &I); + void visitUnreachableInst(UnreachableInst &I); + + void visitShl(BinaryOperator &I); + void visitLShr(BinaryOperator &I); + void visitAShr(BinaryOperator &I); + + void visitVAArgInst(VAArgInst &I); + void visitInstruction(Instruction &I) { + errs() << I; + llvm_unreachable("Instruction not interpretable yet!"); + } + + GenericValue callExternalFunction(Function *F, + const std::vector &ArgVals); + void exitCalled(GenericValue GV); + + void addAtExitHandler(Function *F) { + AtExitHandlers.push_back(F); + } + + GenericValue *getFirstVarArg () { + return &(ECStack.back ().VarArgs[0]); + } + +private: // Helper functions + GenericValue executeGEPOperation(Value *Ptr, gep_type_iterator I, + gep_type_iterator E, ExecutionContext &SF); + + // SwitchToNewBasicBlock - Start execution in a new basic block and run any + // PHI nodes in the top of the block. This is used for intraprocedural + // control flow. + // + void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); + + void *getPointerToFunction(Function *F) { return (void*)F; } + void *getPointerToBasicBlock(BasicBlock *BB) { return (void*)BB; } + + void initializeExecutionEngine() { } + void initializeExternalFunctions(); + GenericValue getConstantExprValue(ConstantExpr *CE, ExecutionContext &SF); + GenericValue getOperandValue(Value *V, ExecutionContext &SF); + GenericValue executeTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeSExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeZExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPTruncInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPExtInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToUIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeFPToSIInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeUIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeSIToFPInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executePtrToIntInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeIntToPtrInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeBitCastInst(Value *SrcVal, const Type *DstTy, + ExecutionContext &SF); + GenericValue executeCastOperation(Instruction::CastOps opcode, Value *SrcVal, + const Type *Ty, ExecutionContext &SF); + void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result); + +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/ExecutionEngine/Interpreter/Makefile b/final/lib/ExecutionEngine/Interpreter/Makefile new file mode 100644 index 00000000000..5def1365c61 --- /dev/null +++ b/final/lib/ExecutionEngine/Interpreter/Makefile @@ -0,0 +1,13 @@ +##===- lib/ExecutionEngine/Interpreter/Makefile ------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMInterpreter + +include $(LEVEL)/Makefile.common diff --git a/final/lib/ExecutionEngine/JIT/CMakeLists.txt b/final/lib/ExecutionEngine/JIT/CMakeLists.txt new file mode 100644 index 00000000000..42020d69af0 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/CMakeLists.txt @@ -0,0 +1,13 @@ +# TODO: Support other architectures. See Makefile. +add_definitions(-DENABLE_X86_JIT) + +add_llvm_library(LLVMJIT + Intercept.cpp + JIT.cpp + JITDebugRegisterer.cpp + JITDwarfEmitter.cpp + JITEmitter.cpp + JITMemoryManager.cpp + OProfileJITEventListener.cpp + TargetSelect.cpp + ) diff --git a/final/lib/ExecutionEngine/JIT/Intercept.cpp b/final/lib/ExecutionEngine/JIT/Intercept.cpp new file mode 100644 index 00000000000..169e1bae547 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/Intercept.cpp @@ -0,0 +1,161 @@ +//===-- Intercept.cpp - System function interception routines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// If a function call occurs to an external function, the JIT is designed to use +// the dynamic loader interface to find a function to call. This is useful for +// calling system calls and library functions that are not available in LLVM. +// Some system calls, however, need to be handled specially. For this reason, +// we intercept some of them here and use our own stubs to handle them. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Config/config.h" +using namespace llvm; + +// AtExitHandlers - List of functions to call when the program exits, +// registered with the atexit() library function. +static std::vector AtExitHandlers; + +/// runAtExitHandlers - Run any functions registered by the program's +/// calls to atexit(3), which we intercept and store in +/// AtExitHandlers. +/// +static void runAtExitHandlers() { + while (!AtExitHandlers.empty()) { + void (*Fn)() = AtExitHandlers.back(); + AtExitHandlers.pop_back(); + Fn(); + } +} + +//===----------------------------------------------------------------------===// +// Function stubs that are invoked instead of certain library calls +//===----------------------------------------------------------------------===// + +// Force the following functions to be linked in to anything that uses the +// JIT. This is a hack designed to work around the all-too-clever Glibc +// strategy of making these functions work differently when inlined vs. when +// not inlined, and hiding their real definitions in a separate archive file +// that the dynamic linker can't see. For more info, search for +// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274. +#if defined(__linux__) +#if defined(HAVE_SYS_STAT_H) +#include +#endif +#include +/* stat functions are redirecting to __xstat with a version number. On x86-64 + * linking with libc_nonshared.a and -Wl,--export-dynamic doesn't make 'stat' + * available as an exported symbol, so we have to add it explicitly. + */ +namespace { +class StatSymbols { +public: + StatSymbols() { + sys::DynamicLibrary::AddSymbol("stat", (void*)(intptr_t)stat); + sys::DynamicLibrary::AddSymbol("fstat", (void*)(intptr_t)fstat); + sys::DynamicLibrary::AddSymbol("lstat", (void*)(intptr_t)lstat); + sys::DynamicLibrary::AddSymbol("stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1stat64", (void*)(intptr_t)stat64); + sys::DynamicLibrary::AddSymbol("\x1open64", (void*)(intptr_t)open64); + sys::DynamicLibrary::AddSymbol("\x1lseek64", (void*)(intptr_t)lseek64); + sys::DynamicLibrary::AddSymbol("fstat64", (void*)(intptr_t)fstat64); + sys::DynamicLibrary::AddSymbol("lstat64", (void*)(intptr_t)lstat64); + sys::DynamicLibrary::AddSymbol("atexit", (void*)(intptr_t)atexit); + sys::DynamicLibrary::AddSymbol("mknod", (void*)(intptr_t)mknod); + } +}; +} +static StatSymbols initStatSymbols; +#endif // __linux__ + +// jit_exit - Used to intercept the "exit" library call. +static void jit_exit(int Status) { + runAtExitHandlers(); // Run atexit handlers... + exit(Status); +} + +// jit_atexit - Used to intercept the "atexit" library call. +static int jit_atexit(void (*Fn)()) { + AtExitHandlers.push_back(Fn); // Take note of atexit handler... + return 0; // Always successful +} + +static int jit_noop() { + return 0; +} + +//===----------------------------------------------------------------------===// +// +/// getPointerToNamedFunction - This method returns the address of the specified +/// function by using the dynamic loader interface. As such it is only useful +/// for resolving library symbols, not code generated symbols. +/// +void *JIT::getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure) { + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + + // We should not invoke parent's ctors/dtors from generated main()! + // On Mingw and Cygwin, the symbol __main is resolved to + // callee's(eg. tools/lli) one, to invoke wrong duplicated ctors + // (and register wrong callee's dtors with atexit(3)). + // We expect ExecutionEngine::runStaticConstructorsDestructors() + // is called before ExecutionEngine::runFunctionAsMain() is called. + if (Name == "__main") return (void*)(intptr_t)&jit_noop; + + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); + if (Ptr) return Ptr; + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. +#if defined(__APPLE__) && defined(__ppc__) + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128", false)) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix, false)) + return Ptr; + } +#endif + } + + /// If a LazyFunctionCreator is installed, use it to get/create the function. + if (LazyFunctionCreator) + if (void *RP = LazyFunctionCreator(Name)) + return RP; + + if (AbortOnFailure) { + report_fatal_error("Program used external function '"+Name+ + "' which could not be resolved!"); + } + return 0; +} diff --git a/final/lib/ExecutionEngine/JIT/JIT.cpp b/final/lib/ExecutionEngine/JIT/JIT.cpp new file mode 100644 index 00000000000..cc76b138a8a --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JIT.cpp @@ -0,0 +1,843 @@ +//===-- JIT.cpp - LLVM Just in Time Compiler ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool implements a just-in-time compiler for LLVM, allowing direct +// execution of LLVM bitcode in an efficient manner. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Config/config.h" + +using namespace llvm; + +#ifdef __APPLE__ +// Apple gcc defaults to -fuse-cxa-atexit (i.e. calls __cxa_atexit instead +// of atexit). It passes the address of linker generated symbol __dso_handle +// to the function. +// This configuration change happened at version 5330. +# include +# if defined(MAC_OS_X_VERSION_10_4) && \ + ((MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4) || \ + (MAC_OS_X_VERSION_MIN_REQUIRED == MAC_OS_X_VERSION_10_4 && \ + __APPLE_CC__ >= 5330)) +# ifndef HAVE___DSO_HANDLE +# define HAVE___DSO_HANDLE 1 +# endif +# endif +#endif + +#if HAVE___DSO_HANDLE +extern void *__dso_handle __attribute__ ((__visibility__ ("hidden"))); +#endif + +namespace { + +static struct RegisterJIT { + RegisterJIT() { JIT::Register(); } +} JITRegistrator; + +} + +extern "C" void LLVMLinkInJIT() { +} + +// Determine whether we can register EH tables. +#if (defined(__GNUC__) && !defined(__ARM_EABI__) && \ + !defined(__USING_SJLJ_EXCEPTIONS__)) +#define HAVE_EHTABLE_SUPPORT 1 +#else +#define HAVE_EHTABLE_SUPPORT 0 +#endif + +#if HAVE_EHTABLE_SUPPORT + +// libgcc defines the __register_frame function to dynamically register new +// dwarf frames for exception handling. This functionality is not portable +// across compilers and is only provided by GCC. We use the __register_frame +// function here so that code generated by the JIT cooperates with the unwinding +// runtime of libgcc. When JITting with exception handling enable, LLVM +// generates dwarf frames and registers it to libgcc with __register_frame. +// +// The __register_frame function works with Linux. +// +// Unfortunately, this functionality seems to be in libgcc after the unwinding +// library of libgcc for darwin was written. The code for darwin overwrites the +// value updated by __register_frame with a value fetched with "keymgr". +// "keymgr" is an obsolete functionality, which should be rewritten some day. +// In the meantime, since "keymgr" is on all libgccs shipped with apple-gcc, we +// need a workaround in LLVM which uses the "keymgr" to dynamically modify the +// values of an opaque key, used by libgcc to find dwarf tables. + +extern "C" void __register_frame(void*); +extern "C" void __deregister_frame(void*); + +#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 +# define USE_KEYMGR 1 +#else +# define USE_KEYMGR 0 +#endif + +#if USE_KEYMGR + +namespace { + +// LibgccObject - This is the structure defined in libgcc. There is no #include +// provided for this structure, so we also define it here. libgcc calls it +// "struct object". The structure is undocumented in libgcc. +struct LibgccObject { + void *unused1; + void *unused2; + void *unused3; + + /// frame - Pointer to the exception table. + void *frame; + + /// encoding - The encoding of the object? + union { + struct { + unsigned long sorted : 1; + unsigned long from_array : 1; + unsigned long mixed_encoding : 1; + unsigned long encoding : 8; + unsigned long count : 21; + } b; + size_t i; + } encoding; + + /// fde_end - libgcc defines this field only if some macro is defined. We + /// include this field even if it may not there, to make libgcc happy. + char *fde_end; + + /// next - At least we know it's a chained list! + struct LibgccObject *next; +}; + +// "kemgr" stuff. Apparently, all frame tables are stored there. +extern "C" void _keymgr_set_and_unlock_processwide_ptr(int, void *); +extern "C" void *_keymgr_get_and_lock_processwide_ptr(int); +#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */ + +/// LibgccObjectInfo - libgcc defines this struct as km_object_info. It +/// probably contains all dwarf tables that are loaded. +struct LibgccObjectInfo { + + /// seenObjects - LibgccObjects already parsed by the unwinding runtime. + /// + struct LibgccObject* seenObjects; + + /// unseenObjects - LibgccObjects not parsed yet by the unwinding runtime. + /// + struct LibgccObject* unseenObjects; + + unsigned unused[2]; +}; + +/// darwin_register_frame - Since __register_frame does not work with darwin's +/// libgcc,we provide our own function, which "tricks" libgcc by modifying the +/// "Dwarf2 object list" key. +void DarwinRegisterFrame(void* FrameBegin) { + // Get the key. + LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) + _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); + assert(LOI && "This should be preallocated by the runtime"); + + // Allocate a new LibgccObject to represent this frame. Deallocation of this + // object may be impossible: since darwin code in libgcc was written after + // the ability to dynamically register frames, things may crash if we + // deallocate it. + struct LibgccObject* ob = (struct LibgccObject*) + malloc(sizeof(struct LibgccObject)); + + // Do like libgcc for the values of the field. + ob->unused1 = (void *)-1; + ob->unused2 = 0; + ob->unused3 = 0; + ob->frame = FrameBegin; + ob->encoding.i = 0; + ob->encoding.b.encoding = llvm::dwarf::DW_EH_PE_omit; + + // Put the info on both places, as libgcc uses the first or the second + // field. Note that we rely on having two pointers here. If fde_end was a + // char, things would get complicated. + ob->fde_end = (char*)LOI->unseenObjects; + ob->next = LOI->unseenObjects; + + // Update the key's unseenObjects list. + LOI->unseenObjects = ob; + + // Finally update the "key". Apparently, libgcc requires it. + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, + LOI); + +} + +} +#endif // __APPLE__ +#endif // HAVE_EHTABLE_SUPPORT + +/// createJIT - This is the factory method for creating a JIT for the current +/// machine, it does not fall back to the interpreter. This takes ownership +/// of the module. +ExecutionEngine *ExecutionEngine::createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM) { + // Use the defaults for extra parameters. Users can use EngineBuilder to + // set them. + StringRef MArch = ""; + StringRef MCPU = ""; + SmallVector MAttrs; + return JIT::createJIT(M, ErrorStr, JMM, OptLevel, GVsWithCode, CMM, + MArch, MCPU, MAttrs); +} + +ExecutionEngine *JIT::createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs) { + // Try to register the program as a source of symbols to resolve against. + sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); + + // Pick a target either via -march or by guessing the native arch. + TargetMachine *TM = JIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); + if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; + TM->setCodeModel(CMM); + + // If the target supports JIT code generation, create a the JIT. + if (TargetJITInfo *TJ = TM->getJITInfo()) { + return new JIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode); + } else { + if (ErrorStr) + *ErrorStr = "target does not support JIT code generation"; + return 0; + } +} + +namespace { +/// This class supports the global getPointerToNamedFunction(), which allows +/// bugpoint or gdb users to search for a function by name without any context. +class JitPool { + SmallPtrSet JITs; // Optimize for process containing just 1 JIT. + mutable sys::Mutex Lock; +public: + void Add(JIT *jit) { + MutexGuard guard(Lock); + JITs.insert(jit); + } + void Remove(JIT *jit) { + MutexGuard guard(Lock); + JITs.erase(jit); + } + void *getPointerToNamedFunction(const char *Name) const { + MutexGuard guard(Lock); + assert(JITs.size() != 0 && "No Jit registered"); + //search function in every instance of JIT + for (SmallPtrSet::const_iterator Jit = JITs.begin(), + end = JITs.end(); + Jit != end; ++Jit) { + if (Function *F = (*Jit)->FindFunctionNamed(Name)) + return (*Jit)->getPointerToFunction(F); + } + // The function is not available : fallback on the first created (will + // search in symbol of the current program/library) + return (*JITs.begin())->getPointerToNamedFunction(Name); + } +}; +ManagedStatic AllJits; +} +extern "C" { + // getPointerToNamedFunction - This function is used as a global wrapper to + // JIT::getPointerToNamedFunction for the purpose of resolving symbols when + // bugpoint is debugging the JIT. In that scenario, we are loading an .so and + // need to resolve function(s) that are being mis-codegenerated, so we need to + // resolve their addresses at runtime, and this is the way to do it. + void *getPointerToNamedFunction(const char *Name) { + return AllJits->getPointerToNamedFunction(Name); + } +} + +JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode) + : ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode), + isAlreadyCodeGenerating(false) { + setTargetData(TM.getTargetData()); + + jitstate = new JITState(M); + + // Initialize JCE + JCE = createEmitter(*this, JMM, TM); + + // Register in global list of all JITs. + AllJits->Add(this); + + // Add target data + MutexGuard locked(lock); + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory that + // may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, OptLevel)) { + report_fatal_error("Target does not support machine code emission!"); + } + + // Register routine for informing unwinding runtime about new EH frames +#if HAVE_EHTABLE_SUPPORT +#if USE_KEYMGR + struct LibgccObjectInfo* LOI = (struct LibgccObjectInfo*) + _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); + + // The key is created on demand, and libgcc creates it the first time an + // exception occurs. Since we need the key to register frames, we create + // it now. + if (!LOI) + LOI = (LibgccObjectInfo*)calloc(sizeof(struct LibgccObjectInfo), 1); + _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, LOI); + InstallExceptionTableRegister(DarwinRegisterFrame); + // Not sure about how to deregister on Darwin. +#else + InstallExceptionTableRegister(__register_frame); + InstallExceptionTableDeregister(__deregister_frame); +#endif // __APPLE__ +#endif // HAVE_EHTABLE_SUPPORT + + // Initialize passes. + PM.doInitialization(); +} + +JIT::~JIT() { + // Unregister all exception tables registered by this JIT. + DeregisterAllTables(); + // Cleanup. + AllJits->Remove(this); + delete jitstate; + delete JCE; + delete &TM; +} + +/// addModule - Add a new Module to the JIT. If we previously removed the last +/// Module, we need re-initialize jitstate with a valid Module. +void JIT::addModule(Module *M) { + MutexGuard locked(lock); + + if (Modules.empty()) { + assert(!jitstate && "jitstate should be NULL if Modules vector is empty!"); + + jitstate = new JITState(M); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { + report_fatal_error("Target does not support machine code emission!"); + } + + // Initialize passes. + PM.doInitialization(); + } + + ExecutionEngine::addModule(M); +} + +/// removeModule - If we are removing the last Module, invalidate the jitstate +/// since the PassManager it contains references a released Module. +bool JIT::removeModule(Module *M) { + bool result = ExecutionEngine::removeModule(M); + + MutexGuard locked(lock); + + if (jitstate->getModule() == M) { + delete jitstate; + jitstate = 0; + } + + if (!jitstate && !Modules.empty()) { + jitstate = new JITState(Modules[0]); + + FunctionPassManager &PM = jitstate->getPM(locked); + PM.add(new TargetData(*TM.getTargetData())); + + // Turn the machine code intermediate representation into bytes in memory + // that may be executed. + if (TM.addPassesToEmitMachineCode(PM, *JCE, CodeGenOpt::Default)) { + report_fatal_error("Target does not support machine code emission!"); + } + + // Initialize passes. + PM.doInitialization(); + } + return result; +} + +/// run - Start execution with the specified function and arguments. +/// +GenericValue JIT::runFunction(Function *F, + const std::vector &ArgValues) { + assert(F && "Function *F was null at entry to run()"); + + void *FPtr = getPointerToFunction(F); + assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); + const FunctionType *FTy = F->getFunctionType(); + const Type *RetTy = FTy->getReturnType(); + + assert((FTy->getNumParams() == ArgValues.size() || + (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && + "Wrong number of arguments passed into function!"); + assert(FTy->getNumParams() == ArgValues.size() && + "This doesn't support passing arguments through varargs (yet)!"); + + // Handle some common cases first. These cases correspond to common `main' + // prototypes. + if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { + switch (ArgValues.size()) { + case 3: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy() && + FTy->getParamType(2)->isPointerTy()) { + int (*PF)(int, char **, const char **) = + (int(*)(int, char **, const char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]), + (const char **)GVTOP(ArgValues[2]))); + return rv; + } + break; + case 2: + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy()) { + int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; + + // Call the function. + GenericValue rv; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), + (char **)GVTOP(ArgValues[1]))); + return rv; + } + break; + case 1: + if (FTy->getNumParams() == 1 && + FTy->getParamType(0)->isIntegerTy(32)) { + GenericValue rv; + int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; + rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); + return rv; + } + break; + } + } + + // Handle cases where no arguments are passed first. + if (ArgValues.empty()) { + GenericValue rv; + switch (RetTy->getTypeID()) { + default: llvm_unreachable("Unknown return type for function call!"); + case Type::IntegerTyID: { + unsigned BitWidth = cast(RetTy)->getBitWidth(); + if (BitWidth == 1) + rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 8) + rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 16) + rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 32) + rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); + else if (BitWidth <= 64) + rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); + else + llvm_unreachable("Integer types > 64 bits not supported"); + return rv; + } + case Type::VoidTyID: + rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); + return rv; + case Type::FloatTyID: + rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); + return rv; + case Type::DoubleTyID: + rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); + return rv; + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + llvm_unreachable("long double not supported yet"); + return rv; + case Type::PointerTyID: + return PTOGV(((void*(*)())(intptr_t)FPtr)()); + } + } + + // Okay, this is not one of our quick and easy cases. Because we don't have a + // full FFI, we have to codegen a nullary stub function that just calls the + // function we are interested in, passing in constants for all of the + // arguments. Make this function and return. + + // First, create the function. + FunctionType *STy=FunctionType::get(RetTy, false); + Function *Stub = Function::Create(STy, Function::InternalLinkage, "", + F->getParent()); + + // Insert a basic block. + BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub); + + // Convert all of the GenericValue arguments over to constants. Note that we + // currently don't support varargs. + SmallVector Args; + for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) { + Constant *C = 0; + const Type *ArgTy = FTy->getParamType(i); + const GenericValue &AV = ArgValues[i]; + switch (ArgTy->getTypeID()) { + default: llvm_unreachable("Unknown argument type for function call!"); + case Type::IntegerTyID: + C = ConstantInt::get(F->getContext(), AV.IntVal); + break; + case Type::FloatTyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal)); + break; + case Type::DoubleTyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal)); + break; + case Type::PPC_FP128TyID: + case Type::X86_FP80TyID: + case Type::FP128TyID: + C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal)); + break; + case Type::PointerTyID: + void *ArgPtr = GVTOP(AV); + if (sizeof(void*) == 4) + C = ConstantInt::get(Type::getInt32Ty(F->getContext()), + (int)(intptr_t)ArgPtr); + else + C = ConstantInt::get(Type::getInt64Ty(F->getContext()), + (intptr_t)ArgPtr); + // Cast the integer to pointer + C = ConstantExpr::getIntToPtr(C, ArgTy); + break; + } + Args.push_back(C); + } + + CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(), + "", StubBB); + TheCall->setCallingConv(F->getCallingConv()); + TheCall->setTailCall(); + if (!TheCall->getType()->isVoidTy()) + // Return result of the call. + ReturnInst::Create(F->getContext(), TheCall, StubBB); + else + ReturnInst::Create(F->getContext(), StubBB); // Just return void. + + // Finally, call our nullary stub function. + GenericValue Result = runFunction(Stub, std::vector()); + // Erase it, since no other function can have a reference to it. + Stub->eraseFromParent(); + // And return the result. + return Result; +} + +void JIT::RegisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + EventListeners.push_back(L); +} +void JIT::UnregisterJITEventListener(JITEventListener *L) { + if (L == NULL) + return; + MutexGuard locked(lock); + std::vector::reverse_iterator I= + std::find(EventListeners.rbegin(), EventListeners.rend(), L); + if (I != EventListeners.rend()) { + std::swap(*I, EventListeners.back()); + EventListeners.pop_back(); + } +} +void JIT::NotifyFunctionEmitted( + const Function &F, + void *Code, size_t Size, + const JITEvent_EmittedFunctionDetails &Details) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFunctionEmitted(F, Code, Size, Details); + } +} + +void JIT::NotifyFreeingMachineCode(void *OldPtr) { + MutexGuard locked(lock); + for (unsigned I = 0, S = EventListeners.size(); I < S; ++I) { + EventListeners[I]->NotifyFreeingMachineCode(OldPtr); + } +} + +/// runJITOnFunction - Run the FunctionPassManager full of +/// just-in-time compilation passes on F, hopefully filling in +/// GlobalAddress[F] with the address of F's machine code. +/// +void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { + MutexGuard locked(lock); + + class MCIListener : public JITEventListener { + MachineCodeInfo *const MCI; + public: + MCIListener(MachineCodeInfo *mci) : MCI(mci) {} + virtual void NotifyFunctionEmitted(const Function &, + void *Code, size_t Size, + const EmittedFunctionDetails &) { + MCI->setAddress(Code); + MCI->setSize(Size); + } + }; + MCIListener MCIL(MCI); + if (MCI) + RegisterJITEventListener(&MCIL); + + runJITOnFunctionUnlocked(F, locked); + + if (MCI) + UnregisterJITEventListener(&MCIL); +} + +void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { + assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); + + jitTheFunction(F, locked); + + // If the function referred to another function that had not yet been + // read from bitcode, and we are jitting non-lazily, emit it now. + while (!jitstate->getPendingFunctions(locked).empty()) { + Function *PF = jitstate->getPendingFunctions(locked).back(); + jitstate->getPendingFunctions(locked).pop_back(); + + assert(!PF->hasAvailableExternallyLinkage() && + "Externally-defined function should not be in pending list."); + + jitTheFunction(PF, locked); + + // Now that the function has been jitted, ask the JITEmitter to rewrite + // the stub with real address of the function. + updateFunctionStub(PF); + } +} + +void JIT::jitTheFunction(Function *F, const MutexGuard &locked) { + isAlreadyCodeGenerating = true; + jitstate->getPM(locked).run(*F); + isAlreadyCodeGenerating = false; + + // clear basic block addresses after this function is done + getBasicBlockAddressMap(locked).clear(); +} + +/// getPointerToFunction - This method is used to get the address of the +/// specified function, compiling it if neccesary. +/// +void *JIT::getPointerToFunction(Function *F) { + + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; // Check if function already code gen'd + + MutexGuard locked(lock); + + // Now that this thread owns the lock, make sure we read in the function if it + // exists in this Module. + std::string ErrorMsg; + if (F->Materialize(&ErrorMsg)) { + report_fatal_error("Error reading function '" + F->getName()+ + "' from bitcode file: " + ErrorMsg); + } + + // ... and check if another thread has already code gen'd the function. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + + if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) { + bool AbortOnFailure = !F->hasExternalWeakLinkage(); + void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure); + addGlobalMapping(F, Addr); + return Addr; + } + + runJITOnFunctionUnlocked(F, locked); + + void *Addr = getPointerToGlobalIfAvailable(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + return Addr; +} + +void JIT::addPointerToBasicBlock(const BasicBlock *BB, void *Addr) { + MutexGuard locked(lock); + + BasicBlockAddressMapTy::iterator I = + getBasicBlockAddressMap(locked).find(BB); + if (I == getBasicBlockAddressMap(locked).end()) { + getBasicBlockAddressMap(locked)[BB] = Addr; + } else { + // ignore repeats: some BBs can be split into few MBBs? + } +} + +void JIT::clearPointerToBasicBlock(const BasicBlock *BB) { + MutexGuard locked(lock); + getBasicBlockAddressMap(locked).erase(BB); +} + +void *JIT::getPointerToBasicBlock(BasicBlock *BB) { + // make sure it's function is compiled by JIT + (void)getPointerToFunction(BB->getParent()); + + // resolve basic block address + MutexGuard locked(lock); + + BasicBlockAddressMapTy::iterator I = + getBasicBlockAddressMap(locked).find(BB); + if (I != getBasicBlockAddressMap(locked).end()) { + return I->second; + } else { + assert(0 && "JIT does not have BB address for address-of-label, was" + " it eliminated by optimizer?"); + return 0; + } +} + +/// getOrEmitGlobalVariable - Return the address of the specified global +/// variable, possibly emitting it to memory if needed. This is used by the +/// Emitter. +void *JIT::getOrEmitGlobalVariable(const GlobalVariable *GV) { + MutexGuard locked(lock); + + void *Ptr = getPointerToGlobalIfAvailable(GV); + if (Ptr) return Ptr; + + // If the global is external, just remember the address. + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) { +#if HAVE___DSO_HANDLE + if (GV->getName() == "__dso_handle") + return (void*)&__dso_handle; +#endif + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName()); + if (Ptr == 0) { + report_fatal_error("Could not resolve external global address: " + +GV->getName()); + } + addGlobalMapping(GV, Ptr); + } else { + // If the global hasn't been emitted to memory yet, allocate space and + // emit it into memory. + Ptr = getMemoryForGV(GV); + addGlobalMapping(GV, Ptr); + EmitGlobalVariable(GV); // Initialize the variable. + } + return Ptr; +} + +/// recompileAndRelinkFunction - This method is used to force a function +/// which has already been compiled, to be compiled again, possibly +/// after it has been modified. Then the entry to the old copy is overwritten +/// with a branch to the new copy. If there was no old copy, this acts +/// just like JIT::getPointerToFunction(). +/// +void *JIT::recompileAndRelinkFunction(Function *F) { + void *OldAddr = getPointerToGlobalIfAvailable(F); + + // If it's not already compiled there is no reason to patch it up. + if (OldAddr == 0) { return getPointerToFunction(F); } + + // Delete the old function mapping. + addGlobalMapping(F, 0); + + // Recodegen the function + runJITOnFunction(F); + + // Update state, forward the old function to the new function. + void *Addr = getPointerToGlobalIfAvailable(F); + assert(Addr && "Code generation didn't add function to GlobalAddress table!"); + TJI.replaceMachineCodeForFunction(OldAddr, Addr); + return Addr; +} + +/// getMemoryForGV - This method abstracts memory allocation of global +/// variable so that the JIT can allocate thread local variables depending +/// on the target. +/// +char* JIT::getMemoryForGV(const GlobalVariable* GV) { + char *Ptr; + + // GlobalVariable's which are not "constant" will cause trouble in a server + // situation. It's returned in the same block of memory as code which may + // not be writable. + if (isGVCompilationDisabled() && !GV->isConstant()) { + report_fatal_error("Compilation of non-internal GlobalValue is disabled!"); + } + + // Some applications require globals and code to live together, so they may + // be allocated into the same buffer, but in general globals are allocated + // through the memory manager which puts them near the code but not in the + // same buffer. + const Type *GlobalType = GV->getType()->getElementType(); + size_t S = getTargetData()->getTypeAllocSize(GlobalType); + size_t A = getTargetData()->getPreferredAlignment(GV); + if (GV->isThreadLocal()) { + MutexGuard locked(lock); + Ptr = TJI.allocateThreadLocalMemory(S); + } else if (TJI.allocateSeparateGVMemory()) { + if (A <= 8) { + Ptr = (char*)malloc(S); + } else { + // Allocate S+A bytes of memory, then use an aligned pointer within that + // space. + Ptr = (char*)malloc(S+A); + unsigned MisAligned = ((intptr_t)Ptr & (A-1)); + Ptr = Ptr + (MisAligned ? (A-MisAligned) : 0); + } + } else if (AllocateGVsWithCode) { + Ptr = (char*)JCE->allocateSpace(S, A); + } else { + Ptr = (char*)JCE->allocateGlobal(S, A); + } + return Ptr; +} + +void JIT::addPendingFunction(Function *F) { + MutexGuard locked(lock); + jitstate->getPendingFunctions(locked).push_back(F); +} + + +JITEventListener::~JITEventListener() {} diff --git a/final/lib/ExecutionEngine/JIT/JIT.h b/final/lib/ExecutionEngine/JIT/JIT.h new file mode 100644 index 00000000000..1d1763edd4d --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JIT.h @@ -0,0 +1,237 @@ +//===-- JIT.h - Class definition for the JIT --------------------*- 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 top-level JIT data structure. +// +//===----------------------------------------------------------------------===// + +#ifndef JIT_H +#define JIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/PassManager.h" +#include "llvm/Support/ValueHandle.h" + +namespace llvm { + +class Function; +struct JITEvent_EmittedFunctionDetails; +class MachineCodeEmitter; +class MachineCodeInfo; +class TargetJITInfo; +class TargetMachine; + +class JITState { +private: + FunctionPassManager PM; // Passes to compile a function + Module *M; // Module used to create the PM + + /// PendingFunctions - Functions which have not been code generated yet, but + /// were called from a function being code generated. + std::vector > PendingFunctions; + +public: + explicit JITState(Module *M) : PM(M), M(M) {} + + FunctionPassManager &getPM(const MutexGuard &L) { + return PM; + } + + Module *getModule() const { return M; } + std::vector > &getPendingFunctions(const MutexGuard &L){ + return PendingFunctions; + } +}; + + +class JIT : public ExecutionEngine { + /// types + typedef ValueMap + BasicBlockAddressMapTy; + /// data + TargetMachine &TM; // The current target we are compiling to + TargetJITInfo &TJI; // The JITInfo for the target we are compiling to + JITCodeEmitter *JCE; // JCE object + std::vector EventListeners; + + /// AllocateGVsWithCode - Some applications require that global variables and + /// code be allocated into the same region of memory, in which case this flag + /// should be set to true. Doing so breaks freeMachineCodeForFunction. + bool AllocateGVsWithCode; + + /// True while the JIT is generating code. Used to assert against recursive + /// entry. + bool isAlreadyCodeGenerating; + + JITState *jitstate; + + /// BasicBlockAddressMap - A mapping between LLVM basic blocks and their + /// actualized version, only filled for basic blocks that have their address + /// taken. + BasicBlockAddressMapTy BasicBlockAddressMap; + + + JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, + bool AllocateGVsWithCode); +public: + ~JIT(); + + static void Register() { + JITCtor = createJIT; + } + + /// getJITInfo - Return the target JIT information structure. + /// + TargetJITInfo &getJITInfo() const { return TJI; } + + /// create - Create an return a new JIT compiler if there is one available + /// for the current target. Otherwise, return null. + /// + static ExecutionEngine *create(Module *M, + std::string *Err, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true, + CodeModel::Model CMM = CodeModel::Default) { + return ExecutionEngine::createJIT(M, Err, JMM, OptLevel, GVsWithCode, + CMM); + } + + virtual void addModule(Module *M); + + /// removeModule - Remove a Module from the list of modules. Returns true if + /// M is found. + virtual bool removeModule(Module *M); + + /// runFunction - Start execution with the specified function and arguments. + /// + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues); + + /// getPointerToNamedFunction - This method returns the address of the + /// specified function by using the dlsym function call. As such it is only + /// useful for resolving library symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function silently returns a null pointer. Otherwise, + /// it prints a message to stderr and aborts. + /// + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true); + + // CompilationCallback - Invoked the first time that a call site is found, + // which causes lazy compilation of the target function. + // + static void CompilationCallback(); + + /// getPointerToFunction - This returns the address of the specified function, + /// compiling it if necessary. + /// + void *getPointerToFunction(Function *F); + + /// addPointerToBasicBlock - Adds address of the specific basic block. + void addPointerToBasicBlock(const BasicBlock *BB, void *Addr); + + /// clearPointerToBasicBlock - Removes address of specific basic block. + void clearPointerToBasicBlock(const BasicBlock *BB); + + /// getPointerToBasicBlock - This returns the address of the specified basic + /// block, assuming function is compiled. + void *getPointerToBasicBlock(BasicBlock *BB); + + /// getOrEmitGlobalVariable - Return the address of the specified global + /// variable, possibly emitting it to memory if needed. This is used by the + /// Emitter. + void *getOrEmitGlobalVariable(const GlobalVariable *GV); + + /// getPointerToFunctionOrStub - If the specified function has been + /// code-gen'd, return a pointer to the function. If not, compile it, or use + /// a stub to implement lazy compilation if available. + /// + void *getPointerToFunctionOrStub(Function *F); + + /// recompileAndRelinkFunction - This method is used to force a function + /// which has already been compiled, to be compiled again, possibly + /// after it has been modified. Then the entry to the old copy is overwritten + /// with a branch to the new copy. If there was no old copy, this acts + /// just like JIT::getPointerToFunction(). + /// + void *recompileAndRelinkFunction(Function *F); + + /// freeMachineCodeForFunction - deallocate memory used to code-generate this + /// Function. + /// + void freeMachineCodeForFunction(Function *F); + + /// addPendingFunction - while jitting non-lazily, a called but non-codegen'd + /// function was encountered. Add it to a pending list to be processed after + /// the current function. + /// + void addPendingFunction(Function *F); + + /// getCodeEmitter - Return the code emitter this JIT is emitting into. + /// + JITCodeEmitter *getCodeEmitter() const { return JCE; } + + /// selectTarget - Pick a target either via -march or by guessing the native + /// arch. Add any CPU features specified via -mcpu or -mattr. + static TargetMachine *selectTarget(Module *M, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs, + std::string *Err); + + static ExecutionEngine *createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs); + + // Run the JIT on F and return information about the generated code + void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0); + + virtual void RegisterJITEventListener(JITEventListener *L); + virtual void UnregisterJITEventListener(JITEventListener *L); + /// These functions correspond to the methods on JITEventListener. They + /// iterate over the registered listeners and call the corresponding method on + /// each. + void NotifyFunctionEmitted( + const Function &F, void *Code, size_t Size, + const JITEvent_EmittedFunctionDetails &Details); + void NotifyFreeingMachineCode(void *OldPtr); + + BasicBlockAddressMapTy & + getBasicBlockAddressMap(const MutexGuard &) { + return BasicBlockAddressMap; + } + + +private: + static JITCodeEmitter *createEmitter(JIT &J, JITMemoryManager *JMM, + TargetMachine &tm); + void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked); + void updateFunctionStub(Function *F); + void jitTheFunction(Function *F, const MutexGuard &locked); + +protected: + + /// getMemoryforGV - Allocate memory for a global variable. + virtual char* getMemoryForGV(const GlobalVariable* GV); + +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp b/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp new file mode 100644 index 00000000000..3b5acb7ecc4 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp @@ -0,0 +1,212 @@ +//===-- JITDebugRegisterer.cpp - Register debug symbols for JIT -----------===// +// +// 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 JITDebugRegisterer object that is used by the JIT to +// register debug info with debuggers like GDB. +// +//===----------------------------------------------------------------------===// + +#include "JITDebugRegisterer.h" +#include "../../CodeGen/ELF.h" +#include "../../CodeGen/ELFWriter.h" +#include "llvm/LLVMContext.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mutex.h" +#include +#include + +namespace llvm { + +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + // Debuggers puts a breakpoint in this function. + LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { } + + // We put information about the JITed function in this global, which the + // debugger reads. Make sure to specify the version statically, because the + // debugger checks the version before we can set it during runtime. + struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; + +} + +namespace { + + /// JITDebugLock - Used to serialize all code registration events, since they + /// modify global variables. + sys::Mutex JITDebugLock; + +} + +JITDebugRegisterer::JITDebugRegisterer(TargetMachine &tm) : TM(tm), FnMap() { } + +JITDebugRegisterer::~JITDebugRegisterer() { + // Free all ELF memory. + for (RegisteredFunctionsMap::iterator I = FnMap.begin(), E = FnMap.end(); + I != E; ++I) { + // Call the private method that doesn't update the map so our iterator + // doesn't break. + UnregisterFunctionInternal(I); + } + FnMap.clear(); +} + +std::string JITDebugRegisterer::MakeELF(const Function *F, DebugInfo &I) { + // Stack allocate an empty module with an empty LLVMContext for the ELFWriter + // API. We don't use the real module because then the ELFWriter would write + // out unnecessary GlobalValues during finalization. + LLVMContext Context; + Module M("", Context); + + // Make a buffer for the ELF in memory. + std::string Buffer; + raw_string_ostream O(Buffer); + ELFWriter EW(O, TM); + EW.doInitialization(M); + + // Copy the binary into the .text section. This isn't necessary, but it's + // useful to be able to disassemble the ELF by hand. + ELFSection &Text = EW.getTextSection(const_cast(F)); + Text.Addr = (uint64_t)I.FnStart; + // TODO: We could eliminate this copy if we somehow used a pointer/size pair + // instead of a vector. + Text.getData().assign(I.FnStart, I.FnEnd); + + // Copy the exception handling call frame information into the .eh_frame + // section. This allows GDB to get a good stack trace, particularly on + // linux x86_64. Mark this as a PROGBITS section that needs to be loaded + // into memory at runtime. + ELFSection &EH = EW.getSection(".eh_frame", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC); + // Pointers in the DWARF EH info are all relative to the EH frame start, + // which is stored here. + EH.Addr = (uint64_t)I.EhStart; + // TODO: We could eliminate this copy if we somehow used a pointer/size pair + // instead of a vector. + EH.getData().assign(I.EhStart, I.EhEnd); + + // Add this single function to the symbol table, so the debugger prints the + // name instead of '???'. We give the symbol default global visibility. + ELFSym *FnSym = ELFSym::getGV(F, + ELF::STB_GLOBAL, + ELF::STT_FUNC, + ELF::STV_DEFAULT); + FnSym->SectionIdx = Text.SectionIdx; + FnSym->Size = I.FnEnd - I.FnStart; + FnSym->Value = 0; // Offset from start of section. + EW.SymbolList.push_back(FnSym); + + EW.doFinalization(M); + O.flush(); + + // When trying to debug why GDB isn't getting the debug info right, it's + // awfully helpful to write the object file to disk so that it can be + // inspected with readelf and objdump. + if (JITEmitDebugInfoToDisk) { + std::string Filename; + raw_string_ostream O2(Filename); + O2 << "/tmp/llvm_function_" << I.FnStart << "_" << F->getNameStr() << ".o"; + O2.flush(); + std::string Errors; + raw_fd_ostream O3(Filename.c_str(), Errors); + O3 << Buffer; + O3.close(); + } + + return Buffer; +} + +void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) { + // TODO: Support non-ELF platforms. + if (!TM.getELFWriterInfo()) + return; + + std::string Buffer = MakeELF(F, I); + + jit_code_entry *JITCodeEntry = new jit_code_entry(); + JITCodeEntry->symfile_addr = Buffer.c_str(); + JITCodeEntry->symfile_size = Buffer.size(); + + // Add a mapping from F to the entry and buffer, so we can delete this + // info later. + FnMap[F] = std::make_pair(Buffer, JITCodeEntry); + + // Acquire the lock and do the registration. + { + MutexGuard locked(JITDebugLock); + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + + // Insert this entry at the head of the list. + JITCodeEntry->prev_entry = NULL; + jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry; + JITCodeEntry->next_entry = NextEntry; + if (NextEntry != NULL) { + NextEntry->prev_entry = JITCodeEntry; + } + __jit_debug_descriptor.first_entry = JITCodeEntry; + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); + } +} + +void JITDebugRegisterer::UnregisterFunctionInternal( + RegisteredFunctionsMap::iterator I) { + jit_code_entry *&JITCodeEntry = I->second.second; + + // Acquire the lock and do the unregistration. + { + MutexGuard locked(JITDebugLock); + __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; + + // Remove the jit_code_entry from the linked list. + jit_code_entry *PrevEntry = JITCodeEntry->prev_entry; + jit_code_entry *NextEntry = JITCodeEntry->next_entry; + if (NextEntry) { + NextEntry->prev_entry = PrevEntry; + } + if (PrevEntry) { + PrevEntry->next_entry = NextEntry; + } else { + assert(__jit_debug_descriptor.first_entry == JITCodeEntry); + __jit_debug_descriptor.first_entry = NextEntry; + } + + // Tell GDB which entry we removed, and unregister the code. + __jit_debug_descriptor.relevant_entry = JITCodeEntry; + __jit_debug_register_code(); + } + + delete JITCodeEntry; + JITCodeEntry = NULL; + + // Free the ELF file in memory. + std::string &Buffer = I->second.first; + Buffer.clear(); +} + +void JITDebugRegisterer::UnregisterFunction(const Function *F) { + // TODO: Support non-ELF platforms. + if (!TM.getELFWriterInfo()) + return; + + RegisteredFunctionsMap::iterator I = FnMap.find(F); + if (I == FnMap.end()) return; + UnregisterFunctionInternal(I); + FnMap.erase(I); +} + +} // end namespace llvm diff --git a/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.h b/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.h new file mode 100644 index 00000000000..dce506bbfef --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITDebugRegisterer.h @@ -0,0 +1,116 @@ +//===-- JITDebugRegisterer.h - Register debug symbols for JIT -------------===// +// +// 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 JITDebugRegisterer object that is used by the JIT to +// register debug info with debuggers like GDB. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H +#define LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/DataTypes.h" +#include + +// This must be kept in sync with gdb/gdb/jit.h . +extern "C" { + + typedef enum { + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN + } jit_actions_t; + + struct jit_code_entry { + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + const char *symfile_addr; + uint64_t symfile_size; + }; + + struct jit_descriptor { + uint32_t version; + // This should be jit_actions_t, but we want to be specific about the + // bit-width. + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; + }; + +} + +namespace llvm { + +class ELFSection; +class Function; +class TargetMachine; + + +/// This class encapsulates information we want to send to the debugger. +/// +struct DebugInfo { + uint8_t *FnStart; + uint8_t *FnEnd; + uint8_t *EhStart; + uint8_t *EhEnd; + + DebugInfo() : FnStart(0), FnEnd(0), EhStart(0), EhEnd(0) {} +}; + +typedef DenseMap< const Function*, std::pair > + RegisteredFunctionsMap; + +/// This class registers debug info for JITed code with an attached debugger. +/// Without proper debug info, GDB can't do things like source level debugging +/// or even produce a proper stack trace on linux-x86_64. To use this class, +/// whenever a function is JITed, create a DebugInfo struct and pass it to the +/// RegisterFunction method. The method will then do whatever is necessary to +/// inform the debugger about the JITed function. +class JITDebugRegisterer { + + TargetMachine &TM; + + /// FnMap - A map of functions that have been registered to the associated + /// temporary files. Used for cleanup. + RegisteredFunctionsMap FnMap; + + /// MakeELF - Builds the ELF file in memory and returns a std::string that + /// contains the ELF. + std::string MakeELF(const Function *F, DebugInfo &I); + +public: + JITDebugRegisterer(TargetMachine &tm); + + /// ~JITDebugRegisterer - Unregisters all code and frees symbol files. + /// + ~JITDebugRegisterer(); + + /// RegisterFunction - Register debug info for the given function with an + /// attached debugger. Clients must call UnregisterFunction on all + /// registered functions before deleting them to free the associated symbol + /// file and unregister it from the debugger. + void RegisterFunction(const Function *F, DebugInfo &I); + + /// UnregisterFunction - Unregister the debug info for the given function + /// from the debugger and free associated memory. + void UnregisterFunction(const Function *F); + +private: + /// UnregisterFunctionInternal - Unregister the debug info for the given + /// function from the debugger and delete any temporary files. The private + /// version of this method does not remove the function from FnMap so that it + /// can be called while iterating over FnMap. + void UnregisterFunctionInternal(RegisteredFunctionsMap::iterator I); + +}; + +} // end namespace llvm + +#endif // LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H diff --git a/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp new file mode 100644 index 00000000000..f54cccadea6 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -0,0 +1,598 @@ +//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===// +// +// 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 JITDwarfEmitter object that is used by the JIT to +// write dwarf tables to memory. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "JITDwarfEmitter.h" +#include "llvm/Function.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +using namespace llvm; + +JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : MMI(0), Jit(theJit) {} + + +unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F, + JITCodeEmitter& jce, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* &EHFramePtr) { + assert(MMI && "MachineModuleInfo not registered!"); + + const TargetMachine& TM = F.getTarget(); + TD = TM.getTargetData(); + stackGrowthDirection = TM.getFrameLowering()->getStackGrowthDirection(); + RI = TM.getRegisterInfo(); + TFI = TM.getFrameLowering(); + JCE = &jce; + + unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction, + EndFunction); + + unsigned char* Result = 0; + + const std::vector Personalities = MMI->getPersonalities(); + EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]); + + Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr, + StartFunction, EndFunction, ExceptionTable); + + return Result; +} + + +void +JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr, + const std::vector &Moves) const { + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ? + PointerSize : -PointerSize; + MCSymbol *BaseLabel = 0; + + for (unsigned i = 0, N = Moves.size(); i < N; ++i) { + const MachineMove &Move = Moves[i]; + MCSymbol *Label = Move.getLabel(); + + // Throw out move if the label is invalid. + if (Label && (*JCE->getLabelLocations())[Label] == 0) + continue; + + intptr_t LabelPtr = 0; + if (Label) LabelPtr = JCE->getLabelAddress(Label); + + const MachineLocation &Dst = Move.getDestination(); + const MachineLocation &Src = Move.getSource(); + + // Advance row if new location. + if (BaseLabelPtr && Label && BaseLabel != Label) { + JCE->emitByte(dwarf::DW_CFA_advance_loc4); + JCE->emitInt32(LabelPtr - BaseLabelPtr); + + BaseLabel = Label; + BaseLabelPtr = LabelPtr; + } + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (!Src.isReg()) { + if (Src.getReg() == MachineLocation::VirtualFP) { + JCE->emitByte(dwarf::DW_CFA_def_cfa_offset); + } else { + JCE->emitByte(dwarf::DW_CFA_def_cfa); + JCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getReg(), true)); + } + + JCE->emitULEB128Bytes(-Src.getOffset()); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else if (Src.isReg() && + Src.getReg() == MachineLocation::VirtualFP) { + if (Dst.isReg()) { + JCE->emitByte(dwarf::DW_CFA_def_cfa_register); + JCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), true)); + } else { + llvm_unreachable("Machine move not supported yet."); + } + } else { + unsigned Reg = RI->getDwarfRegNum(Src.getReg(), true); + int Offset = Dst.getOffset() / stackGrowth; + + if (Offset < 0) { + JCE->emitByte(dwarf::DW_CFA_offset_extended_sf); + JCE->emitULEB128Bytes(Reg); + JCE->emitSLEB128Bytes(Offset); + } else if (Reg < 64) { + JCE->emitByte(dwarf::DW_CFA_offset + Reg); + JCE->emitULEB128Bytes(Offset); + } else { + JCE->emitByte(dwarf::DW_CFA_offset_extended); + JCE->emitULEB128Bytes(Reg); + JCE->emitULEB128Bytes(Offset); + } + } + } +} + +/// SharedTypeIds - How many leading type ids two landing pads have in common. +static unsigned SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + unsigned Count = 0; + + for (; Count != MinSize; ++Count) + if (LIds[Count] != RIds[Count]) + return Count; + + return Count; +} + + +/// PadLT - Order landing pads lexicographically by type id. +static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; + unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + + for (unsigned i = 0; i != MinSize; ++i) + if (LIds[i] != RIds[i]) + return LIds[i] < RIds[i]; + + return LSize < RSize; +} + +namespace { + +/// ActionEntry - Structure describing an entry in the actions table. +struct ActionEntry { + int ValueForTypeID; // The value to write - may not be equal to the type id. + int NextAction; + struct ActionEntry *Previous; +}; + +/// PadRange - Structure holding a try-range and the associated landing pad. +struct PadRange { + // The index of the landing pad. + unsigned PadIndex; + // The index of the begin and end labels in the landing pad's label lists. + unsigned RangeIndex; +}; + +typedef DenseMap RangeMapType; + +/// CallSiteEntry - Structure describing an entry in the call-site table. +struct CallSiteEntry { + MCSymbol *BeginLabel; // zero indicates the start of the function. + MCSymbol *EndLabel; // zero indicates the end of the function. + MCSymbol *PadLabel; // zero indicates that there is no landing pad. + unsigned Action; +}; + +} + +unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, + unsigned char* StartFunction, + unsigned char* EndFunction) const { + assert(MMI && "MachineModuleInfo not registered!"); + + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(JCE->getLabelLocations()); + + const std::vector &TypeInfos = MMI->getTypeInfos(); + const std::vector &FilterIds = MMI->getFilterIds(); + const std::vector &PadInfos = MMI->getLandingPads(); + if (PadInfos.empty()) return 0; + + // Sort the landing pads in order of their type ids. This is used to fold + // duplicate actions. + SmallVector LandingPads; + LandingPads.reserve(PadInfos.size()); + for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) + LandingPads.push_back(&PadInfos[i]); + std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + + // Negative type ids index into FilterIds, positive type ids index into + // TypeInfos. The value written for a positive type id is just the type + // id itself. For a negative type id, however, the value written is the + // (negative) byte offset of the corresponding FilterIds entry. The byte + // offset is usually equal to the type id, because the FilterIds entries + // are written using a variable width encoding which outputs one byte per + // entry as long as the value written is not too large, but can differ. + // This kind of complication does not occur for positive type ids because + // type infos are output using a fixed width encoding. + // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i]. + SmallVector FilterOffsets; + FilterOffsets.reserve(FilterIds.size()); + int Offset = -1; + for(std::vector::const_iterator I = FilterIds.begin(), + E = FilterIds.end(); I != E; ++I) { + FilterOffsets.push_back(Offset); + Offset -= MCAsmInfo::getULEB128Size(*I); + } + + // Compute the actions table and gather the first action index for each + // landing pad site. + SmallVector Actions; + SmallVector FirstActions; + FirstActions.reserve(LandingPads.size()); + + int FirstAction = 0; + unsigned SizeActions = 0; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LP = LandingPads[i]; + const std::vector &TypeIds = LP->TypeIds; + const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; + unsigned SizeSiteActions = 0; + + if (NumShared < TypeIds.size()) { + unsigned SizeAction = 0; + ActionEntry *PrevAction = 0; + + if (NumShared) { + const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + assert(Actions.size()); + PrevAction = &Actions.back(); + SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + SizeAction += -PrevAction->NextAction; + PrevAction = PrevAction->Previous; + } + } + + // Compute the actions. + for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { + int TypeID = TypeIds[I]; + assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); + int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; + unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; + Actions.push_back(Action); + + PrevAction = &Actions.back(); + } + + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + FirstActions.push_back(FirstAction); + + // Compute this sites contribution to size. + SizeActions += SizeSiteActions; + } + + // Compute the call-site table. Entries must be ordered by address. + SmallVector CallSites; + + RangeMapType PadMap; + for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { + const LandingPadInfo *LandingPad = LandingPads[i]; + for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { + MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; + assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); + PadRange P = { i, j }; + PadMap[BeginLabel] = P; + } + } + + bool MayThrow = false; + MCSymbol *LastLabel = 0; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); + MI != E; ++MI) { + if (!MI->isLabel()) { + MayThrow |= MI->getDesc().isCall(); + continue; + } + + MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); + assert(BeginLabel && "Invalid label!"); + + if (BeginLabel == LastLabel) + MayThrow = false; + + RangeMapType::iterator L = PadMap.find(BeginLabel); + + if (L == PadMap.end()) + continue; + + PadRange P = L->second; + const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; + + assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && + "Inconsistent landing pad map!"); + + // If some instruction between the previous try-range and this one may + // throw, create a call-site entry with no landing pad for the region + // between the try-ranges. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; + CallSites.push_back(Site); + } + + LastLabel = LandingPad->EndLabels[P.RangeIndex]; + CallSiteEntry Site = {BeginLabel, LastLabel, + LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; + + assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && + "Invalid landing pad!"); + + // Try to merge with the previous call-site. + if (CallSites.size()) { + CallSiteEntry &Prev = CallSites.back(); + if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { + // Extend the range of the previous entry. + Prev.EndLabel = Site.EndLabel; + continue; + } + } + + // Otherwise, create a new call-site. + CallSites.push_back(Site); + } + } + // If some instruction between the previous try-range and the end of the + // function may throw, create a call-site entry with no landing pad for the + // region following the try-range. + if (MayThrow) { + CallSiteEntry Site = {LastLabel, 0, 0, 0}; + CallSites.push_back(Site); + } + + // Final tallies. + unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. + sizeof(int32_t) + // Site length. + sizeof(int32_t)); // Landing pad. + for (unsigned i = 0, e = CallSites.size(); i < e; ++i) + SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + + unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); + + unsigned TypeOffset = sizeof(int8_t) + // Call site format + // Call-site table length + MCAsmInfo::getULEB128Size(SizeSites) + + SizeSites + SizeActions + SizeTypes; + + // Begin the exception table. + JCE->emitAlignmentWithFill(4, 0); + // Asm->EOL("Padding"); + + unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue(); + + // Emit the header. + JCE->emitByte(dwarf::DW_EH_PE_omit); + // Asm->EOL("LPStart format (DW_EH_PE_omit)"); + JCE->emitByte(dwarf::DW_EH_PE_absptr); + // Asm->EOL("TType format (DW_EH_PE_absptr)"); + JCE->emitULEB128Bytes(TypeOffset); + // Asm->EOL("TType base offset"); + JCE->emitByte(dwarf::DW_EH_PE_udata4); + // Asm->EOL("Call site format (DW_EH_PE_udata4)"); + JCE->emitULEB128Bytes(SizeSites); + // Asm->EOL("Call-site table length"); + + // Emit the landing pad site information. + for (unsigned i = 0; i < CallSites.size(); ++i) { + CallSiteEntry &S = CallSites[i]; + intptr_t BeginLabelPtr = 0; + intptr_t EndLabelPtr = 0; + + if (!S.BeginLabel) { + BeginLabelPtr = (intptr_t)StartFunction; + JCE->emitInt32(0); + } else { + BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel); + JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction); + } + + // Asm->EOL("Region start"); + + if (!S.EndLabel) + EndLabelPtr = (intptr_t)EndFunction; + else + EndLabelPtr = JCE->getLabelAddress(S.EndLabel); + + JCE->emitInt32(EndLabelPtr - BeginLabelPtr); + //Asm->EOL("Region length"); + + if (!S.PadLabel) { + JCE->emitInt32(0); + } else { + unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel); + JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction); + } + // Asm->EOL("Landing pad"); + + JCE->emitULEB128Bytes(S.Action); + // Asm->EOL("Action"); + } + + // Emit the actions. + for (unsigned I = 0, N = Actions.size(); I != N; ++I) { + ActionEntry &Action = Actions[I]; + + JCE->emitSLEB128Bytes(Action.ValueForTypeID); + //Asm->EOL("TypeInfo index"); + JCE->emitSLEB128Bytes(Action.NextAction); + //Asm->EOL("Next action"); + } + + // Emit the type ids. + for (unsigned M = TypeInfos.size(); M; --M) { + const GlobalVariable *GV = TypeInfos[M - 1]; + + if (GV) { + if (TD->getPointerSize() == sizeof(int32_t)) + JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV)); + else + JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV)); + } else { + if (TD->getPointerSize() == sizeof(int32_t)) + JCE->emitInt32(0); + else + JCE->emitInt64(0); + } + // Asm->EOL("TypeInfo"); + } + + // Emit the filter typeids. + for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { + unsigned TypeID = FilterIds[j]; + JCE->emitULEB128Bytes(TypeID); + //Asm->EOL("Filter TypeInfo index"); + } + + JCE->emitAlignmentWithFill(4, 0); + + return DwarfExceptionTable; +} + +unsigned char* +JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { + unsigned PointerSize = TD->getPointerSize(); + int stackGrowth = stackGrowthDirection == TargetFrameLowering::StackGrowsUp ? + PointerSize : -PointerSize; + + unsigned char* StartCommonPtr = (unsigned char*)JCE->getCurrentPCValue(); + // EH Common Frame header + JCE->allocateSpace(4, 0); + unsigned char* FrameCommonBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); + JCE->emitInt32((int)0); + JCE->emitByte(dwarf::DW_CIE_VERSION); + JCE->emitString(Personality ? "zPLR" : "zR"); + JCE->emitULEB128Bytes(1); + JCE->emitSLEB128Bytes(stackGrowth); + JCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true)); + + if (Personality) { + // Augmentation Size: 3 small ULEBs of one byte each, and the personality + // function which size is PointerSize. + JCE->emitULEB128Bytes(3 + PointerSize); + + // We set the encoding of the personality as direct encoding because we use + // the function pointer. The encoding is not relative because the current + // PC value may be bigger than the personality function pointer. + if (PointerSize == 4) { + JCE->emitByte(dwarf::DW_EH_PE_sdata4); + JCE->emitInt32(((intptr_t)Jit.getPointerToGlobal(Personality))); + } else { + JCE->emitByte(dwarf::DW_EH_PE_sdata8); + JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality))); + } + + // LSDA encoding: This must match the encoding used in EmitEHFrame () + if (PointerSize == 4) + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + else + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8); + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + } else { + JCE->emitULEB128Bytes(1); + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + } + + std::vector Moves; + TFI->getInitialFrameState(Moves); + EmitFrameMoves(0, Moves); + + JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); + + JCE->emitInt32At((uintptr_t*)StartCommonPtr, + (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - + FrameCommonBeginPtr)); + + return StartCommonPtr; +} + + +unsigned char* +JITDwarfEmitter::EmitEHFrame(const Function* Personality, + unsigned char* StartCommonPtr, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* ExceptionTable) const { + unsigned PointerSize = TD->getPointerSize(); + + // EH frame header. + unsigned char* StartEHPtr = (unsigned char*)JCE->getCurrentPCValue(); + JCE->allocateSpace(4, 0); + unsigned char* FrameBeginPtr = (unsigned char*)JCE->getCurrentPCValue(); + // FDE CIE Offset + JCE->emitInt32(FrameBeginPtr - StartCommonPtr); + JCE->emitInt32(StartFunction - (unsigned char*)JCE->getCurrentPCValue()); + JCE->emitInt32(EndFunction - StartFunction); + + // If there is a personality and landing pads then point to the language + // specific data area in the exception table. + if (Personality) { + JCE->emitULEB128Bytes(PointerSize == 4 ? 4 : 8); + + if (PointerSize == 4) { + if (!MMI->getLandingPads().empty()) + JCE->emitInt32(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); + else + JCE->emitInt32((int)0); + } else { + if (!MMI->getLandingPads().empty()) + JCE->emitInt64(ExceptionTable-(unsigned char*)JCE->getCurrentPCValue()); + else + JCE->emitInt64((int)0); + } + } else { + JCE->emitULEB128Bytes(0); + } + + // Indicate locations of function specific callee saved registers in + // frame. + EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves()); + + JCE->emitAlignmentWithFill(PointerSize, dwarf::DW_CFA_nop); + + // Indicate the size of the table + JCE->emitInt32At((uintptr_t*)StartEHPtr, + (uintptr_t)((unsigned char*)JCE->getCurrentPCValue() - + StartEHPtr)); + + // Double zeroes for the unwind runtime + if (PointerSize == 8) { + JCE->emitInt64(0); + JCE->emitInt64(0); + } else { + JCE->emitInt32(0); + JCE->emitInt32(0); + } + + return StartEHPtr; +} diff --git a/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.h b/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.h new file mode 100644 index 00000000000..9495697a1aa --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITDwarfEmitter.h @@ -0,0 +1,73 @@ +//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===// +// +// 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 JITDwarfEmitter object that is used by the JIT to +// write dwarf tables to memory. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H +#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H + +namespace llvm { + +class Function; +class JITCodeEmitter; +class MachineFunction; +class MachineModuleInfo; +class MachineMove; +class TargetData; +class TargetFrameLowering; +class TargetMachine; +class TargetRegisterInfo; + +class JITDwarfEmitter { + const TargetData* TD; + JITCodeEmitter* JCE; + const TargetRegisterInfo* RI; + const TargetFrameLowering *TFI; + MachineModuleInfo* MMI; + JIT& Jit; + bool stackGrowthDirection; + + unsigned char* EmitExceptionTable(MachineFunction* MF, + unsigned char* StartFunction, + unsigned char* EndFunction) const; + + void EmitFrameMoves(intptr_t BaseLabelPtr, + const std::vector &Moves) const; + + unsigned char* EmitCommonEHFrame(const Function* Personality) const; + + unsigned char* EmitEHFrame(const Function* Personality, + unsigned char* StartBufferPtr, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* ExceptionTable) const; + +public: + + JITDwarfEmitter(JIT& jit); + + unsigned char* EmitDwarfTable(MachineFunction& F, + JITCodeEmitter& JCE, + unsigned char* StartFunction, + unsigned char* EndFunction, + unsigned char* &EHFramePtr); + + + void setModuleInfo(MachineModuleInfo* Info) { + MMI = Info; + } +}; + + +} // end namespace llvm + +#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H diff --git a/final/lib/ExecutionEngine/JIT/JITEmitter.cpp b/final/lib/ExecutionEngine/JIT/JITEmitter.cpp new file mode 100644 index 00000000000..fa3c5a01c1e --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -0,0 +1,1305 @@ +//===-- JITEmitter.cpp - Write machine code to executable memory ----------===// +// +// 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 MachineCodeEmitter object that is used by the JIT to +// write machine code to memory and remember where relocatable values are. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "JIT.h" +#include "JITDebugRegisterer.h" +#include "JITDwarfEmitter.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineCodeInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetJITInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Disassembler.h" +#include "llvm/Support/Memory.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ValueMap.h" +#include +#ifndef NDEBUG +#include +#endif +using namespace llvm; + +STATISTIC(NumBytes, "Number of bytes of machine code compiled"); +STATISTIC(NumRelos, "Number of relocations applied"); +STATISTIC(NumRetries, "Number of retries with more memory"); + + +// A declaration may stop being a declaration once it's fully read from bitcode. +// This function returns true if F is fully read and is still a declaration. +static bool isNonGhostDeclaration(const Function *F) { + return F->isDeclaration() && !F->isMaterializable(); +} + +//===----------------------------------------------------------------------===// +// JIT lazy compilation code. +// +namespace { + class JITEmitter; + class JITResolverState; + + template + struct NoRAUWValueMapConfig : public ValueMapConfig { + typedef JITResolverState *ExtraData; + static void onRAUW(JITResolverState *, Value *Old, Value *New) { + assert(false && "The JIT doesn't know how to handle a" + " RAUW on a value it has emitted."); + } + }; + + struct CallSiteValueMapConfig : public NoRAUWValueMapConfig { + typedef JITResolverState *ExtraData; + static void onDelete(JITResolverState *JRS, Function *F); + }; + + class JITResolverState { + public: + typedef ValueMap > + FunctionToLazyStubMapTy; + typedef std::map > CallSiteToFunctionMapTy; + typedef ValueMap, + CallSiteValueMapConfig> FunctionToCallSitesMapTy; + typedef std::map, void*> GlobalToIndirectSymMapTy; + private: + /// FunctionToLazyStubMap - Keep track of the lazy stub created for a + /// particular function so that we can reuse them if necessary. + FunctionToLazyStubMapTy FunctionToLazyStubMap; + + /// CallSiteToFunctionMap - Keep track of the function that each lazy call + /// site corresponds to, and vice versa. + CallSiteToFunctionMapTy CallSiteToFunctionMap; + FunctionToCallSitesMapTy FunctionToCallSitesMap; + + /// GlobalToIndirectSymMap - Keep track of the indirect symbol created for a + /// particular GlobalVariable so that we can reuse them if necessary. + GlobalToIndirectSymMapTy GlobalToIndirectSymMap; + + /// Instance of the JIT this ResolverState serves. + JIT *TheJIT; + + public: + JITResolverState(JIT *jit) : FunctionToLazyStubMap(this), + FunctionToCallSitesMap(this), + TheJIT(jit) {} + + FunctionToLazyStubMapTy& getFunctionToLazyStubMap( + const MutexGuard& locked) { + assert(locked.holds(TheJIT->lock)); + return FunctionToLazyStubMap; + } + + GlobalToIndirectSymMapTy& getGlobalToIndirectSymMap(const MutexGuard& locked) { + assert(locked.holds(TheJIT->lock)); + return GlobalToIndirectSymMap; + } + + pair LookupFunctionFromCallSite( + const MutexGuard &locked, void *CallSite) const { + assert(locked.holds(TheJIT->lock)); + + // The address given to us for the stub may not be exactly right, it might be + // a little bit after the stub. As such, use upper_bound to find it. + CallSiteToFunctionMapTy::const_iterator I = + CallSiteToFunctionMap.upper_bound(CallSite); + assert(I != CallSiteToFunctionMap.begin() && + "This is not a known call site!"); + --I; + return *I; + } + + void AddCallSite(const MutexGuard &locked, void *CallSite, Function *F) { + assert(locked.holds(TheJIT->lock)); + + bool Inserted = CallSiteToFunctionMap.insert( + std::make_pair(CallSite, F)).second; + (void)Inserted; + assert(Inserted && "Pair was already in CallSiteToFunctionMap"); + FunctionToCallSitesMap[F].insert(CallSite); + } + + void EraseAllCallSitesForPrelocked(Function *F); + + // Erases _all_ call sites regardless of their function. This is used to + // unregister the stub addresses from the StubToResolverMap in + // ~JITResolver(). + void EraseAllCallSitesPrelocked(); + }; + + /// JITResolver - Keep track of, and resolve, call sites for functions that + /// have not yet been compiled. + class JITResolver { + typedef JITResolverState::FunctionToLazyStubMapTy FunctionToLazyStubMapTy; + typedef JITResolverState::CallSiteToFunctionMapTy CallSiteToFunctionMapTy; + typedef JITResolverState::GlobalToIndirectSymMapTy GlobalToIndirectSymMapTy; + + /// LazyResolverFn - The target lazy resolver function that we actually + /// rewrite instructions to use. + TargetJITInfo::LazyResolverFn LazyResolverFn; + + JITResolverState state; + + /// ExternalFnToStubMap - This is the equivalent of FunctionToLazyStubMap + /// for external functions. TODO: Of course, external functions don't need + /// a lazy stub. It's actually here to make it more likely that far calls + /// succeed, but no single stub can guarantee that. I'll remove this in a + /// subsequent checkin when I actually fix far calls. + std::map ExternalFnToStubMap; + + /// revGOTMap - map addresses to indexes in the GOT + std::map revGOTMap; + unsigned nextGOTIndex; + + JITEmitter &JE; + + /// Instance of JIT corresponding to this Resolver. + JIT *TheJIT; + + public: + explicit JITResolver(JIT &jit, JITEmitter &je) + : state(&jit), nextGOTIndex(0), JE(je), TheJIT(&jit) { + LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); + } + + ~JITResolver(); + + /// getLazyFunctionStubIfAvailable - This returns a pointer to a function's + /// lazy-compilation stub if it has already been created. + void *getLazyFunctionStubIfAvailable(Function *F); + + /// getLazyFunctionStub - This returns a pointer to a function's + /// lazy-compilation stub, creating one on demand as needed. + void *getLazyFunctionStub(Function *F); + + /// getExternalFunctionStub - Return a stub for the function at the + /// specified address, created lazily on demand. + void *getExternalFunctionStub(void *FnAddr); + + /// getGlobalValueIndirectSym - Return an indirect symbol containing the + /// specified GV address. + void *getGlobalValueIndirectSym(GlobalValue *V, void *GVAddress); + + /// getGOTIndexForAddress - Return a new or existing index in the GOT for + /// an address. This function only manages slots, it does not manage the + /// contents of the slots or the memory associated with the GOT. + unsigned getGOTIndexForAddr(void *addr); + + /// JITCompilerFn - This function is called to resolve a stub to a compiled + /// address. If the LLVM Function corresponding to the stub has not yet + /// been compiled, this function compiles it first. + static void *JITCompilerFn(void *Stub); + }; + + class StubToResolverMapTy { + /// Map a stub address to a specific instance of a JITResolver so that + /// lazily-compiled functions can find the right resolver to use. + /// + /// Guarded by Lock. + std::map Map; + + /// Guards Map from concurrent accesses. + mutable sys::Mutex Lock; + + public: + /// Registers a Stub to be resolved by Resolver. + void RegisterStubResolver(void *Stub, JITResolver *Resolver) { + MutexGuard guard(Lock); + Map.insert(std::make_pair(Stub, Resolver)); + } + /// Unregisters the Stub when it's invalidated. + void UnregisterStubResolver(void *Stub) { + MutexGuard guard(Lock); + Map.erase(Stub); + } + /// Returns the JITResolver instance that owns the Stub. + JITResolver *getResolverFromStub(void *Stub) const { + MutexGuard guard(Lock); + // The address given to us for the stub may not be exactly right, it might + // be a little bit after the stub. As such, use upper_bound to find it. + // This is the same trick as in LookupFunctionFromCallSite from + // JITResolverState. + std::map::const_iterator I = Map.upper_bound(Stub); + assert(I != Map.begin() && "This is not a known stub!"); + --I; + return I->second; + } + /// True if any stubs refer to the given resolver. Only used in an assert(). + /// O(N) + bool ResolverHasStubs(JITResolver* Resolver) const { + MutexGuard guard(Lock); + for (std::map::const_iterator I = Map.begin(), + E = Map.end(); I != E; ++I) { + if (I->second == Resolver) + return true; + } + return false; + } + }; + /// This needs to be static so that a lazy call stub can access it with no + /// context except the address of the stub. + ManagedStatic StubToResolverMap; + + /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is + /// used to output functions to memory for execution. + class JITEmitter : public JITCodeEmitter { + JITMemoryManager *MemMgr; + + // When outputting a function stub in the context of some other function, we + // save BufferBegin/BufferEnd/CurBufferPtr here. + uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; + + // When reattempting to JIT a function after running out of space, we store + // the estimated size of the function we're trying to JIT here, so we can + // ask the memory manager for at least this much space. When we + // successfully emit the function, we reset this back to zero. + uintptr_t SizeEstimate; + + /// Relocations - These are the relocations that the function needs, as + /// emitted. + std::vector Relocations; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector MBBLocations; + + /// ConstantPool - The constant pool for the current function. + /// + MachineConstantPool *ConstantPool; + + /// ConstantPoolBase - A pointer to the first entry in the constant pool. + /// + void *ConstantPoolBase; + + /// ConstPoolAddresses - Addresses of individual constant pool entries. + /// + SmallVector ConstPoolAddresses; + + /// JumpTable - The jump tables for the current function. + /// + MachineJumpTableInfo *JumpTable; + + /// JumpTableBase - A pointer to the first entry in the jump table. + /// + void *JumpTableBase; + + /// Resolver - This contains info about the currently resolved functions. + JITResolver Resolver; + + /// DE - The dwarf emitter for the jit. + OwningPtr DE; + + /// DR - The debug registerer for the jit. + OwningPtr DR; + + /// LabelLocations - This vector is a mapping from Label ID's to their + /// address. + DenseMap LabelLocations; + + /// MMI - Machine module info for exception informations + MachineModuleInfo* MMI; + + // CurFn - The llvm function being emitted. Only valid during + // finishFunction(). + const Function *CurFn; + + /// Information about emitted code, which is passed to the + /// JITEventListeners. This is reset in startFunction and used in + /// finishFunction. + JITEvent_EmittedFunctionDetails EmissionDetails; + + struct EmittedCode { + void *FunctionBody; // Beginning of the function's allocation. + void *Code; // The address the function's code actually starts at. + void *ExceptionTable; + EmittedCode() : FunctionBody(0), Code(0), ExceptionTable(0) {} + }; + struct EmittedFunctionConfig : public ValueMapConfig { + typedef JITEmitter *ExtraData; + static void onDelete(JITEmitter *, const Function*); + static void onRAUW(JITEmitter *, const Function*, const Function*); + }; + ValueMap EmittedFunctions; + + DebugLoc PrevDL; + + /// Instance of the JIT + JIT *TheJIT; + + public: + JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) + : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), + EmittedFunctions(this), TheJIT(&jit) { + MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); + if (jit.getJITInfo().needsGOT()) { + MemMgr->AllocateGOT(); + DEBUG(dbgs() << "JIT is managing a GOT\n"); + } + + if (JITExceptionHandling || JITEmitDebugInfo) { + DE.reset(new JITDwarfEmitter(jit)); + } + if (JITEmitDebugInfo) { + DR.reset(new JITDebugRegisterer(TM)); + } + } + ~JITEmitter() { + delete MemMgr; + } + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const MachineCodeEmitter*) { return true; } + + JITResolver &getJITResolver() { return Resolver; } + + virtual void startFunction(MachineFunction &F); + virtual bool finishFunction(MachineFunction &F); + + void emitConstantPool(MachineConstantPool *MCP); + void initJumpTableInfo(MachineJumpTableInfo *MJTI); + void emitJumpTableInfo(MachineJumpTableInfo *MJTI); + + void startGVStub(const GlobalValue* GV, + unsigned StubSize, unsigned Alignment = 1); + void startGVStub(void *Buffer, unsigned StubSize); + void finishGVStub(); + virtual void *allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment); + + /// allocateSpace - Reserves space in the current block if any, or + /// allocate a new one of the given size. + virtual void *allocateSpace(uintptr_t Size, unsigned Alignment); + + /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, + /// this method does not allocate memory in the current output buffer, + /// because a global may live longer than the current function. + virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment); + + virtual void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCValue(); + if (MBB->hasAddressTaken()) + TheJIT->addPointerToBasicBlock(MBB->getBasicBlock(), + (void*)getCurrentPCValue()); + DEBUG(dbgs() << "JIT: Emitting BB" << MBB->getNumber() << " at [" + << (void*) getCurrentPCValue() << "]\n"); + } + + virtual uintptr_t getConstantPoolEntryAddress(unsigned Entry) const; + virtual uintptr_t getJumpTableEntryAddress(unsigned Entry) const; + + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const{ + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; + } + + /// retryWithMoreMemory - Log a retry and deallocate all memory for the + /// given function. Increase the minimum allocation size so that we get + /// more memory next time. + void retryWithMoreMemory(MachineFunction &F); + + /// deallocateMemForFunction - Deallocate all memory for the specified + /// function body. + void deallocateMemForFunction(const Function *F); + + virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn); + + virtual void emitLabel(MCSymbol *Label) { + LabelLocations[Label] = getCurrentPCValue(); + } + + virtual DenseMap *getLabelLocations() { + return &LabelLocations; + } + + virtual uintptr_t getLabelAddress(MCSymbol *Label) const { + assert(LabelLocations.count(Label) && "Label not emitted!"); + return LabelLocations.find(Label)->second; + } + + virtual void setModuleInfo(MachineModuleInfo* Info) { + MMI = Info; + if (DE.get()) DE->setModuleInfo(Info); + } + + private: + void *getPointerToGlobal(GlobalValue *GV, void *Reference, + bool MayNeedFarStub); + void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference); + }; +} + +void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) { + JRS->EraseAllCallSitesForPrelocked(F); +} + +void JITResolverState::EraseAllCallSitesForPrelocked(Function *F) { + FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F); + if (F2C == FunctionToCallSitesMap.end()) + return; + StubToResolverMapTy &S2RMap = *StubToResolverMap; + for (SmallPtrSet::const_iterator I = F2C->second.begin(), + E = F2C->second.end(); I != E; ++I) { + S2RMap.UnregisterStubResolver(*I); + bool Erased = CallSiteToFunctionMap.erase(*I); + (void)Erased; + assert(Erased && "Missing call site->function mapping"); + } + FunctionToCallSitesMap.erase(F2C); +} + +void JITResolverState::EraseAllCallSitesPrelocked() { + StubToResolverMapTy &S2RMap = *StubToResolverMap; + for (CallSiteToFunctionMapTy::const_iterator + I = CallSiteToFunctionMap.begin(), + E = CallSiteToFunctionMap.end(); I != E; ++I) { + S2RMap.UnregisterStubResolver(I->first); + } + CallSiteToFunctionMap.clear(); + FunctionToCallSitesMap.clear(); +} + +JITResolver::~JITResolver() { + // No need to lock because we're in the destructor, and state isn't shared. + state.EraseAllCallSitesPrelocked(); + assert(!StubToResolverMap->ResolverHasStubs(this) && + "Resolver destroyed with stubs still alive."); +} + +/// getLazyFunctionStubIfAvailable - This returns a pointer to a function stub +/// if it has already been created. +void *JITResolver::getLazyFunctionStubIfAvailable(Function *F) { + MutexGuard locked(TheJIT->lock); + + // If we already have a stub for this function, recycle it. + return state.getFunctionToLazyStubMap(locked).lookup(F); +} + +/// getFunctionStub - This returns a pointer to a function stub, creating +/// one on demand as needed. +void *JITResolver::getLazyFunctionStub(Function *F) { + MutexGuard locked(TheJIT->lock); + + // If we already have a lazy stub for this function, recycle it. + void *&Stub = state.getFunctionToLazyStubMap(locked)[F]; + if (Stub) return Stub; + + // Call the lazy resolver function if we are JIT'ing lazily. Otherwise we + // must resolve the symbol now. + void *Actual = TheJIT->isCompilingLazily() + ? (void *)(intptr_t)LazyResolverFn : (void *)0; + + // If this is an external declaration, attempt to resolve the address now + // to place in the stub. + if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage()) { + Actual = TheJIT->getPointerToFunction(F); + + // If we resolved the symbol to a null address (eg. a weak external) + // don't emit a stub. Return a null pointer to the application. + if (!Actual) return 0; + } + + TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); + JE.startGVStub(F, SL.Size, SL.Alignment); + // Codegen a new stub, calling the lazy resolver or the actual address of the + // external function, if it was resolved. + Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, JE); + JE.finishGVStub(); + + if (Actual != (void*)(intptr_t)LazyResolverFn) { + // If we are getting the stub for an external function, we really want the + // address of the stub in the GlobalAddressMap for the JIT, not the address + // of the external function. + TheJIT->updateGlobalMapping(F, Stub); + } + + DEBUG(dbgs() << "JIT: Lazy stub emitted at [" << Stub << "] for function '" + << F->getName() << "'\n"); + + if (TheJIT->isCompilingLazily()) { + // Register this JITResolver as the one corresponding to this call site so + // JITCompilerFn will be able to find it. + StubToResolverMap->RegisterStubResolver(Stub, this); + + // Finally, keep track of the stub-to-Function mapping so that the + // JITCompilerFn knows which function to compile! + state.AddCallSite(locked, Stub, F); + } else if (!Actual) { + // If we are JIT'ing non-lazily but need to call a function that does not + // exist yet, add it to the JIT's work list so that we can fill in the + // stub address later. + assert(!isNonGhostDeclaration(F) && !F->hasAvailableExternallyLinkage() && + "'Actual' should have been set above."); + TheJIT->addPendingFunction(F); + } + + return Stub; +} + +/// getGlobalValueIndirectSym - Return a lazy pointer containing the specified +/// GV address. +void *JITResolver::getGlobalValueIndirectSym(GlobalValue *GV, void *GVAddress) { + MutexGuard locked(TheJIT->lock); + + // If we already have a stub for this global variable, recycle it. + void *&IndirectSym = state.getGlobalToIndirectSymMap(locked)[GV]; + if (IndirectSym) return IndirectSym; + + // Otherwise, codegen a new indirect symbol. + IndirectSym = TheJIT->getJITInfo().emitGlobalValueIndirectSym(GV, GVAddress, + JE); + + DEBUG(dbgs() << "JIT: Indirect symbol emitted at [" << IndirectSym + << "] for GV '" << GV->getName() << "'\n"); + + return IndirectSym; +} + +/// getExternalFunctionStub - Return a stub for the function at the +/// specified address, created lazily on demand. +void *JITResolver::getExternalFunctionStub(void *FnAddr) { + // If we already have a stub for this function, recycle it. + void *&Stub = ExternalFnToStubMap[FnAddr]; + if (Stub) return Stub; + + TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); + JE.startGVStub(0, SL.Size, SL.Alignment); + Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, JE); + JE.finishGVStub(); + + DEBUG(dbgs() << "JIT: Stub emitted at [" << Stub + << "] for external function at '" << FnAddr << "'\n"); + return Stub; +} + +unsigned JITResolver::getGOTIndexForAddr(void* addr) { + unsigned idx = revGOTMap[addr]; + if (!idx) { + idx = ++nextGOTIndex; + revGOTMap[addr] = idx; + DEBUG(dbgs() << "JIT: Adding GOT entry " << idx << " for addr [" + << addr << "]\n"); + } + return idx; +} + +/// JITCompilerFn - This function is called when a lazy compilation stub has +/// been entered. It looks up which function this stub corresponds to, compiles +/// it if necessary, then returns the resultant function pointer. +void *JITResolver::JITCompilerFn(void *Stub) { + JITResolver *JR = StubToResolverMap->getResolverFromStub(Stub); + assert(JR && "Unable to find the corresponding JITResolver to the call site"); + + Function* F = 0; + void* ActualPtr = 0; + + { + // Only lock for getting the Function. The call getPointerToFunction made + // in this function might trigger function materializing, which requires + // JIT lock to be unlocked. + MutexGuard locked(JR->TheJIT->lock); + + // The address given to us for the stub may not be exactly right, it might + // be a little bit after the stub. As such, use upper_bound to find it. + pair I = + JR->state.LookupFunctionFromCallSite(locked, Stub); + F = I.second; + ActualPtr = I.first; + } + + // If we have already code generated the function, just return the address. + void *Result = JR->TheJIT->getPointerToGlobalIfAvailable(F); + + if (!Result) { + // Otherwise we don't have it, do lazy compilation now. + + // If lazy compilation is disabled, emit a useful error message and abort. + if (!JR->TheJIT->isCompilingLazily()) { + report_fatal_error("LLVM JIT requested to do lazy compilation of function '" + + F->getName() + "' when lazy compiles are disabled!"); + } + + DEBUG(dbgs() << "JIT: Lazily resolving function '" << F->getName() + << "' In stub ptr = " << Stub << " actual ptr = " + << ActualPtr << "\n"); + + Result = JR->TheJIT->getPointerToFunction(F); + } + + // Reacquire the lock to update the GOT map. + MutexGuard locked(JR->TheJIT->lock); + + // We might like to remove the call site from the CallSiteToFunction map, but + // we can't do that! Multiple threads could be stuck, waiting to acquire the + // lock above. As soon as the 1st function finishes compiling the function, + // the next one will be released, and needs to be able to find the function it + // needs to call. + + // FIXME: We could rewrite all references to this stub if we knew them. + + // What we will do is set the compiled function address to map to the + // same GOT entry as the stub so that later clients may update the GOT + // if they see it still using the stub address. + // Note: this is done so the Resolver doesn't have to manage GOT memory + // Do this without allocating map space if the target isn't using a GOT + if(JR->revGOTMap.find(Stub) != JR->revGOTMap.end()) + JR->revGOTMap[Result] = JR->revGOTMap[Stub]; + + return Result; +} + +//===----------------------------------------------------------------------===// +// JITEmitter code. +// +void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, + bool MayNeedFarStub) { + if (GlobalVariable *GV = dyn_cast(V)) + return TheJIT->getOrEmitGlobalVariable(GV); + + if (GlobalAlias *GA = dyn_cast(V)) + return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false)); + + // If we have already compiled the function, return a pointer to its body. + Function *F = cast(V); + + void *FnStub = Resolver.getLazyFunctionStubIfAvailable(F); + if (FnStub) { + // Return the function stub if it's already created. We do this first so + // that we're returning the same address for the function as any previous + // call. TODO: Yes, this is wrong. The lazy stub isn't guaranteed to be + // close enough to call. + return FnStub; + } + + // If we know the target can handle arbitrary-distance calls, try to + // return a direct pointer. + if (!MayNeedFarStub) { + // If we have code, go ahead and return that. + void *ResultPtr = TheJIT->getPointerToGlobalIfAvailable(F); + if (ResultPtr) return ResultPtr; + + // If this is an external function pointer, we can force the JIT to + // 'compile' it, which really just adds it to the map. + if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage()) + return TheJIT->getPointerToFunction(F); + } + + // Otherwise, we may need a to emit a stub, and, conservatively, we always do + // so. Note that it's possible to return null from getLazyFunctionStub in the + // case of a weak extern that fails to resolve. + return Resolver.getLazyFunctionStub(F); +} + +void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { + // Make sure GV is emitted first, and create a stub containing the fully + // resolved address. + void *GVAddress = getPointerToGlobal(V, Reference, false); + void *StubAddr = Resolver.getGlobalValueIndirectSym(V, GVAddress); + return StubAddr; +} + +void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { + if (DL.isUnknown()) return; + if (!BeforePrintingInsn) return; + + const LLVMContext &Context = EmissionDetails.MF->getFunction()->getContext(); + + if (DL.getScope(Context) != 0 && PrevDL != DL) { + JITEvent_EmittedFunctionDetails::LineStart NextLine; + NextLine.Address = getCurrentPCValue(); + NextLine.Loc = DL; + EmissionDetails.LineStarts.push_back(NextLine); + } + + PrevDL = DL; +} + +static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, + const TargetData *TD) { + const std::vector &Constants = MCP->getConstants(); + if (Constants.empty()) return 0; + + unsigned Size = 0; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = Constants[i]; + unsigned AlignMask = CPE.getAlignment() - 1; + Size = (Size + AlignMask) & ~AlignMask; + const Type *Ty = CPE.getType(); + Size += TD->getTypeAllocSize(Ty); + } + return Size; +} + +void JITEmitter::startFunction(MachineFunction &F) { + DEBUG(dbgs() << "JIT: Starting CodeGen of Function " + << F.getFunction()->getName() << "\n"); + + uintptr_t ActualSize = 0; + // Set the memory writable, if it's not already + MemMgr->setMemoryWritable(); + + if (SizeEstimate > 0) { + // SizeEstimate will be non-zero on reallocation attempts. + ActualSize = SizeEstimate; + } + + BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(), + ActualSize); + BufferEnd = BufferBegin+ActualSize; + EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin; + + // Ensure the constant pool/jump table info is at least 4-byte aligned. + emitAlignment(16); + + emitConstantPool(F.getConstantPool()); + if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) + initJumpTableInfo(MJTI); + + // About to start emitting the machine code for the function. + emitAlignment(std::max(F.getFunction()->getAlignment(), 8U)); + TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr); + EmittedFunctions[F.getFunction()].Code = CurBufferPtr; + + MBBLocations.clear(); + + EmissionDetails.MF = &F; + EmissionDetails.LineStarts.clear(); +} + +bool JITEmitter::finishFunction(MachineFunction &F) { + if (CurBufferPtr == BufferEnd) { + // We must call endFunctionBody before retrying, because + // deallocateMemForFunction requires it. + MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); + retryWithMoreMemory(F); + return true; + } + + if (MachineJumpTableInfo *MJTI = F.getJumpTableInfo()) + emitJumpTableInfo(MJTI); + + // FnStart is the start of the text, not the start of the constant pool and + // other per-function data. + uint8_t *FnStart = + (uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction()); + + // FnEnd is the end of the function's machine code. + uint8_t *FnEnd = CurBufferPtr; + + if (!Relocations.empty()) { + CurFn = F.getFunction(); + NumRelos += Relocations.size(); + + // Resolve the relocations to concrete pointers. + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + void *ResultPtr = 0; + if (!MR.letTargetResolve()) { + if (MR.isExternalSymbol()) { + ResultPtr = TheJIT->getPointerToNamedFunction(MR.getExternalSymbol(), + false); + DEBUG(dbgs() << "JIT: Map \'" << MR.getExternalSymbol() << "\' to [" + << ResultPtr << "]\n"); + + // If the target REALLY wants a stub for this function, emit it now. + if (MR.mayNeedFarStub()) { + ResultPtr = Resolver.getExternalFunctionStub(ResultPtr); + } + } else if (MR.isGlobalValue()) { + ResultPtr = getPointerToGlobal(MR.getGlobalValue(), + BufferBegin+MR.getMachineCodeOffset(), + MR.mayNeedFarStub()); + } else if (MR.isIndirectSymbol()) { + ResultPtr = getPointerToGVIndirectSym( + MR.getGlobalValue(), BufferBegin+MR.getMachineCodeOffset()); + } else if (MR.isBasicBlock()) { + ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock()); + } else if (MR.isConstantPoolIndex()) { + ResultPtr = (void*)getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + } else { + assert(MR.isJumpTableIndex()); + ResultPtr=(void*)getJumpTableEntryAddress(MR.getJumpTableIndex()); + } + + MR.setResultPointer(ResultPtr); + } + + // if we are managing the GOT and the relocation wants an index, + // give it one + if (MR.isGOTRelative() && MemMgr->isManagingGOT()) { + unsigned idx = Resolver.getGOTIndexForAddr(ResultPtr); + MR.setGOTIndex(idx); + if (((void**)MemMgr->getGOTBase())[idx] != ResultPtr) { + DEBUG(dbgs() << "JIT: GOT was out of date for " << ResultPtr + << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] + << "\n"); + ((void**)MemMgr->getGOTBase())[idx] = ResultPtr; + } + } + } + + CurFn = 0; + TheJIT->getJITInfo().relocate(BufferBegin, &Relocations[0], + Relocations.size(), MemMgr->getGOTBase()); + } + + // Update the GOT entry for F to point to the new code. + if (MemMgr->isManagingGOT()) { + unsigned idx = Resolver.getGOTIndexForAddr((void*)BufferBegin); + if (((void**)MemMgr->getGOTBase())[idx] != (void*)BufferBegin) { + DEBUG(dbgs() << "JIT: GOT was out of date for " << (void*)BufferBegin + << " pointing at " << ((void**)MemMgr->getGOTBase())[idx] + << "\n"); + ((void**)MemMgr->getGOTBase())[idx] = (void*)BufferBegin; + } + } + + // CurBufferPtr may have moved beyond FnEnd, due to memory allocation for + // global variables that were referenced in the relocations. + MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr); + + if (CurBufferPtr == BufferEnd) { + retryWithMoreMemory(F); + return true; + } else { + // Now that we've succeeded in emitting the function, reset the + // SizeEstimate back down to zero. + SizeEstimate = 0; + } + + BufferBegin = CurBufferPtr = 0; + NumBytes += FnEnd-FnStart; + + // Invalidate the icache if necessary. + sys::Memory::InvalidateInstructionCache(FnStart, FnEnd-FnStart); + + TheJIT->NotifyFunctionEmitted(*F.getFunction(), FnStart, FnEnd-FnStart, + EmissionDetails); + + // Reset the previous debug location. + PrevDL = DebugLoc(); + + DEBUG(dbgs() << "JIT: Finished CodeGen of [" << (void*)FnStart + << "] Function: " << F.getFunction()->getName() + << ": " << (FnEnd-FnStart) << " bytes of text, " + << Relocations.size() << " relocations\n"); + + Relocations.clear(); + ConstPoolAddresses.clear(); + + // Mark code region readable and executable if it's not so already. + MemMgr->setMemoryExecutable(); + + DEBUG({ + if (sys::hasDisassembler()) { + dbgs() << "JIT: Disassembled code:\n"; + dbgs() << sys::disassembleBuffer(FnStart, FnEnd-FnStart, + (uintptr_t)FnStart); + } else { + dbgs() << "JIT: Binary code:\n"; + uint8_t* q = FnStart; + for (int i = 0; q < FnEnd; q += 4, ++i) { + if (i == 4) + i = 0; + if (i == 0) + dbgs() << "JIT: " << (long)(q - FnStart) << ": "; + bool Done = false; + for (int j = 3; j >= 0; --j) { + if (q + j >= FnEnd) + Done = true; + else + dbgs() << (unsigned short)q[j]; + } + if (Done) + break; + dbgs() << ' '; + if (i == 3) + dbgs() << '\n'; + } + dbgs()<< '\n'; + } + }); + + if (JITExceptionHandling || JITEmitDebugInfo) { + uintptr_t ActualSize = 0; + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; + + BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(), + ActualSize); + BufferEnd = BufferBegin+ActualSize; + EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin; + uint8_t *EhStart; + uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd, + EhStart); + MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, + FrameRegister); + uint8_t *EhEnd = CurBufferPtr; + BufferBegin = SavedBufferBegin; + BufferEnd = SavedBufferEnd; + CurBufferPtr = SavedCurBufferPtr; + + if (JITExceptionHandling) { + TheJIT->RegisterTable(F.getFunction(), FrameRegister); + } + + if (JITEmitDebugInfo) { + DebugInfo I; + I.FnStart = FnStart; + I.FnEnd = FnEnd; + I.EhStart = EhStart; + I.EhEnd = EhEnd; + DR->RegisterFunction(F.getFunction(), I); + } + } + + if (MMI) + MMI->EndFunction(); + + return false; +} + +void JITEmitter::retryWithMoreMemory(MachineFunction &F) { + DEBUG(dbgs() << "JIT: Ran out of space for native code. Reattempting.\n"); + Relocations.clear(); // Clear the old relocations or we'll reapply them. + ConstPoolAddresses.clear(); + ++NumRetries; + deallocateMemForFunction(F.getFunction()); + // Try again with at least twice as much free space. + SizeEstimate = (uintptr_t)(2 * (BufferEnd - BufferBegin)); + + for (MachineFunction::iterator MBB = F.begin(), E = F.end(); MBB != E; ++MBB){ + if (MBB->hasAddressTaken()) + TheJIT->clearPointerToBasicBlock(MBB->getBasicBlock()); + } +} + +/// deallocateMemForFunction - Deallocate all memory for the specified +/// function body. Also drop any references the function has to stubs. +/// May be called while the Function is being destroyed inside ~Value(). +void JITEmitter::deallocateMemForFunction(const Function *F) { + ValueMap::iterator + Emitted = EmittedFunctions.find(F); + if (Emitted != EmittedFunctions.end()) { + MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody); + MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable); + TheJIT->NotifyFreeingMachineCode(Emitted->second.Code); + + EmittedFunctions.erase(Emitted); + } + + if(JITExceptionHandling) { + TheJIT->DeregisterTable(F); + } + + if (JITEmitDebugInfo) { + DR->UnregisterFunction(F); + } +} + + +void* JITEmitter::allocateSpace(uintptr_t Size, unsigned Alignment) { + if (BufferBegin) + return JITCodeEmitter::allocateSpace(Size, Alignment); + + // create a new memory block if there is no active one. + // care must be taken so that BufferBegin is invalidated when a + // block is trimmed + BufferBegin = CurBufferPtr = MemMgr->allocateSpace(Size, Alignment); + BufferEnd = BufferBegin+Size; + return CurBufferPtr; +} + +void* JITEmitter::allocateGlobal(uintptr_t Size, unsigned Alignment) { + // Delegate this call through the memory manager. + return MemMgr->allocateGlobal(Size, Alignment); +} + +void JITEmitter::emitConstantPool(MachineConstantPool *MCP) { + if (TheJIT->getJITInfo().hasCustomConstantPool()) + return; + + const std::vector &Constants = MCP->getConstants(); + if (Constants.empty()) return; + + unsigned Size = GetConstantPoolSizeInBytes(MCP, TheJIT->getTargetData()); + unsigned Align = MCP->getConstantPoolAlignment(); + ConstantPoolBase = allocateSpace(Size, Align); + ConstantPool = MCP; + + if (ConstantPoolBase == 0) return; // Buffer overflow. + + DEBUG(dbgs() << "JIT: Emitted constant pool at [" << ConstantPoolBase + << "] (size: " << Size << ", alignment: " << Align << ")\n"); + + // Initialize the memory for all of the constant pool entries. + unsigned Offset = 0; + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + MachineConstantPoolEntry CPE = Constants[i]; + unsigned AlignMask = CPE.getAlignment() - 1; + Offset = (Offset + AlignMask) & ~AlignMask; + + uintptr_t CAddr = (uintptr_t)ConstantPoolBase + Offset; + ConstPoolAddresses.push_back(CAddr); + if (CPE.isMachineConstantPoolEntry()) { + // FIXME: add support to lower machine constant pool values into bytes! + report_fatal_error("Initialize memory with machine specific constant pool" + "entry has not been implemented!"); + } + TheJIT->InitializeMemory(CPE.Val.ConstVal, (void*)CAddr); + DEBUG(dbgs() << "JIT: CP" << i << " at [0x"; + dbgs().write_hex(CAddr) << "]\n"); + + const Type *Ty = CPE.Val.ConstVal->getType(); + Offset += TheJIT->getTargetData()->getTypeAllocSize(Ty); + } +} + +void JITEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) { + if (TheJIT->getJITInfo().hasCustomJumpTables()) + return; + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) + return; + + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + unsigned NumEntries = 0; + for (unsigned i = 0, e = JT.size(); i != e; ++i) + NumEntries += JT[i].MBBs.size(); + + unsigned EntrySize = MJTI->getEntrySize(*TheJIT->getTargetData()); + + // Just allocate space for all the jump tables now. We will fix up the actual + // MBB entries in the tables after we emit the code for each block, since then + // we will know the final locations of the MBBs in memory. + JumpTable = MJTI; + JumpTableBase = allocateSpace(NumEntries * EntrySize, + MJTI->getEntryAlignment(*TheJIT->getTargetData())); +} + +void JITEmitter::emitJumpTableInfo(MachineJumpTableInfo *MJTI) { + if (TheJIT->getJITInfo().hasCustomJumpTables()) + return; + + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty() || JumpTableBase == 0) return; + + + switch (MJTI->getEntryKind()) { + case MachineJumpTableInfo::EK_Inline: + return; + case MachineJumpTableInfo::EK_BlockAddress: { + // EK_BlockAddress - Each entry is a plain address of block, e.g.: + // .word LBB123 + assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == sizeof(void*) && + "Cross JIT'ing?"); + + // For each jump table, map each target in the jump table to the address of + // an emitted MachineBasicBlock. + intptr_t *SlotPtr = (intptr_t*)JumpTableBase; + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + // Store the address of the basic block for this jump table slot in the + // memory we allocated for the jump table in 'initJumpTableInfo' + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) + *SlotPtr++ = getMachineBasicBlockAddress(MBBs[mi]); + } + break; + } + + case MachineJumpTableInfo::EK_Custom32: + case MachineJumpTableInfo::EK_GPRel32BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference32: { + assert(MJTI->getEntrySize(*TheJIT->getTargetData()) == 4&&"Cross JIT'ing?"); + // For each jump table, place the offset from the beginning of the table + // to the target address. + int *SlotPtr = (int*)JumpTableBase; + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + const std::vector &MBBs = JT[i].MBBs; + // Store the offset of the basic block for this jump table slot in the + // memory we allocated for the jump table in 'initJumpTableInfo' + uintptr_t Base = (uintptr_t)SlotPtr; + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + uintptr_t MBBAddr = getMachineBasicBlockAddress(MBBs[mi]); + /// FIXME: USe EntryKind instead of magic "getPICJumpTableEntry" hook. + *SlotPtr++ = TheJIT->getJITInfo().getPICJumpTableEntry(MBBAddr, Base); + } + } + break; + } + } +} + +void JITEmitter::startGVStub(const GlobalValue* GV, + unsigned StubSize, unsigned Alignment) { + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; + + BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); + BufferEnd = BufferBegin+StubSize+1; +} + +void JITEmitter::startGVStub(void *Buffer, unsigned StubSize) { + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; + + BufferBegin = CurBufferPtr = (uint8_t *)Buffer; + BufferEnd = BufferBegin+StubSize+1; +} + +void JITEmitter::finishGVStub() { + assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space."); + NumBytes += getCurrentPCOffset(); + BufferBegin = SavedBufferBegin; + BufferEnd = SavedBufferEnd; + CurBufferPtr = SavedCurBufferPtr; +} + +void *JITEmitter::allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment) { + uint8_t *IndGV = MemMgr->allocateStub(GV, Size, Alignment); + memcpy(IndGV, Buffer, Size); + return IndGV; +} + +// getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry +// in the constant pool that was last emitted with the 'emitConstantPool' +// method. +// +uintptr_t JITEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const { + assert(ConstantNum < ConstantPool->getConstants().size() && + "Invalid ConstantPoolIndex!"); + return ConstPoolAddresses[ConstantNum]; +} + +// getJumpTableEntryAddress - Return the address of the JumpTable with index +// 'Index' in the jumpp table that was last initialized with 'initJumpTableInfo' +// +uintptr_t JITEmitter::getJumpTableEntryAddress(unsigned Index) const { + const std::vector &JT = JumpTable->getJumpTables(); + assert(Index < JT.size() && "Invalid jump table index!"); + + unsigned EntrySize = JumpTable->getEntrySize(*TheJIT->getTargetData()); + + unsigned Offset = 0; + for (unsigned i = 0; i < Index; ++i) + Offset += JT[i].MBBs.size(); + + Offset *= EntrySize; + + return (uintptr_t)((char *)JumpTableBase + Offset); +} + +void JITEmitter::EmittedFunctionConfig::onDelete( + JITEmitter *Emitter, const Function *F) { + Emitter->deallocateMemForFunction(F); +} +void JITEmitter::EmittedFunctionConfig::onRAUW( + JITEmitter *, const Function*, const Function*) { + llvm_unreachable("The JIT doesn't know how to handle a" + " RAUW on a value it has emitted."); +} + + +//===----------------------------------------------------------------------===// +// Public interface to this file +//===----------------------------------------------------------------------===// + +JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM, + TargetMachine &tm) { + return new JITEmitter(jit, JMM, tm); +} + +// getPointerToFunctionOrStub - If the specified function has been +// code-gen'd, return a pointer to the function. If not, compile it, or use +// a stub to implement lazy compilation if available. +// +void *JIT::getPointerToFunctionOrStub(Function *F) { + // If we have already code generated the function, just return the address. + if (void *Addr = getPointerToGlobalIfAvailable(F)) + return Addr; + + // Get a stub if the target supports it. + assert(isa(JCE) && "Unexpected MCE?"); + JITEmitter *JE = cast(getCodeEmitter()); + return JE->getJITResolver().getLazyFunctionStub(F); +} + +void JIT::updateFunctionStub(Function *F) { + // Get the empty stub we generated earlier. + assert(isa(JCE) && "Unexpected MCE?"); + JITEmitter *JE = cast(getCodeEmitter()); + void *Stub = JE->getJITResolver().getLazyFunctionStub(F); + void *Addr = getPointerToGlobalIfAvailable(F); + assert(Addr != Stub && "Function must have non-stub address to be updated."); + + // Tell the target jit info to rewrite the stub at the specified address, + // rather than creating a new one. + TargetJITInfo::StubLayout layout = getJITInfo().getStubLayout(); + JE->startGVStub(Stub, layout.Size); + getJITInfo().emitFunctionStub(F, Addr, *getCodeEmitter()); + JE->finishGVStub(); +} + +/// freeMachineCodeForFunction - release machine code memory for given Function. +/// +void JIT::freeMachineCodeForFunction(Function *F) { + // Delete translation for this from the ExecutionEngine, so it will get + // retranslated next time it is used. + updateGlobalMapping(F, 0); + + // Free the actual memory for the function body and related stuff. + assert(isa(JCE) && "Unexpected MCE?"); + cast(JCE)->deallocateMemForFunction(F); +} diff --git a/final/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/final/lib/ExecutionEngine/JIT/JITMemoryManager.cpp new file mode 100644 index 00000000000..eec23cec0af --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -0,0 +1,727 @@ +//===-- JITMemoryManager.cpp - Memory Allocator for JIT'd code ------------===// +// +// 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 DefaultJITMemoryManager class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/Twine.h" +#include "llvm/GlobalValue.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Memory.h" +#include +#include +#include +#include +using namespace llvm; + +STATISTIC(NumSlabs, "Number of slabs of memory allocated by the JIT"); + +JITMemoryManager::~JITMemoryManager() {} + +//===----------------------------------------------------------------------===// +// Memory Block Implementation. +//===----------------------------------------------------------------------===// + +namespace { + /// MemoryRangeHeader - For a range of memory, this is the header that we put + /// on the block of memory. It is carefully crafted to be one word of memory. + /// Allocated blocks have just this header, free'd blocks have FreeRangeHeader + /// which starts with this. + struct FreeRangeHeader; + struct MemoryRangeHeader { + /// ThisAllocated - This is true if this block is currently allocated. If + /// not, this can be converted to a FreeRangeHeader. + unsigned ThisAllocated : 1; + + /// PrevAllocated - Keep track of whether the block immediately before us is + /// allocated. If not, the word immediately before this header is the size + /// of the previous block. + unsigned PrevAllocated : 1; + + /// BlockSize - This is the size in bytes of this memory block, + /// including this header. + uintptr_t BlockSize : (sizeof(intptr_t)*CHAR_BIT - 2); + + + /// getBlockAfter - Return the memory block immediately after this one. + /// + MemoryRangeHeader &getBlockAfter() const { + return *(MemoryRangeHeader*)((char*)this+BlockSize); + } + + /// getFreeBlockBefore - If the block before this one is free, return it, + /// otherwise return null. + FreeRangeHeader *getFreeBlockBefore() const { + if (PrevAllocated) return 0; + intptr_t PrevSize = ((intptr_t *)this)[-1]; + return (FreeRangeHeader*)((char*)this-PrevSize); + } + + /// FreeBlock - Turn an allocated block into a free block, adjusting + /// bits in the object headers, and adding an end of region memory block. + FreeRangeHeader *FreeBlock(FreeRangeHeader *FreeList); + + /// TrimAllocationToSize - If this allocated block is significantly larger + /// than NewSize, split it into two pieces (where the former is NewSize + /// bytes, including the header), and add the new block to the free list. + FreeRangeHeader *TrimAllocationToSize(FreeRangeHeader *FreeList, + uint64_t NewSize); + }; + + /// FreeRangeHeader - For a memory block that isn't already allocated, this + /// keeps track of the current block and has a pointer to the next free block. + /// Free blocks are kept on a circularly linked list. + struct FreeRangeHeader : public MemoryRangeHeader { + FreeRangeHeader *Prev; + FreeRangeHeader *Next; + + /// getMinBlockSize - Get the minimum size for a memory block. Blocks + /// smaller than this size cannot be created. + static unsigned getMinBlockSize() { + return sizeof(FreeRangeHeader)+sizeof(intptr_t); + } + + /// SetEndOfBlockSizeMarker - The word at the end of every free block is + /// known to be the size of the free block. Set it for this block. + void SetEndOfBlockSizeMarker() { + void *EndOfBlock = (char*)this + BlockSize; + ((intptr_t *)EndOfBlock)[-1] = BlockSize; + } + + FreeRangeHeader *RemoveFromFreeList() { + assert(Next->Prev == this && Prev->Next == this && "Freelist broken!"); + Next->Prev = Prev; + return Prev->Next = Next; + } + + void AddToFreeList(FreeRangeHeader *FreeList) { + Next = FreeList; + Prev = FreeList->Prev; + Prev->Next = this; + Next->Prev = this; + } + + /// GrowBlock - The block after this block just got deallocated. Merge it + /// into the current block. + void GrowBlock(uintptr_t NewSize); + + /// AllocateBlock - Mark this entire block allocated, updating freelists + /// etc. This returns a pointer to the circular free-list. + FreeRangeHeader *AllocateBlock(); + }; +} + + +/// AllocateBlock - Mark this entire block allocated, updating freelists +/// etc. This returns a pointer to the circular free-list. +FreeRangeHeader *FreeRangeHeader::AllocateBlock() { + assert(!ThisAllocated && !getBlockAfter().PrevAllocated && + "Cannot allocate an allocated block!"); + // Mark this block allocated. + ThisAllocated = 1; + getBlockAfter().PrevAllocated = 1; + + // Remove it from the free list. + return RemoveFromFreeList(); +} + +/// FreeBlock - Turn an allocated block into a free block, adjusting +/// bits in the object headers, and adding an end of region memory block. +/// If possible, coalesce this block with neighboring blocks. Return the +/// FreeRangeHeader to allocate from. +FreeRangeHeader *MemoryRangeHeader::FreeBlock(FreeRangeHeader *FreeList) { + MemoryRangeHeader *FollowingBlock = &getBlockAfter(); + assert(ThisAllocated && "This block is already free!"); + assert(FollowingBlock->PrevAllocated && "Flags out of sync!"); + + FreeRangeHeader *FreeListToReturn = FreeList; + + // If the block after this one is free, merge it into this block. + if (!FollowingBlock->ThisAllocated) { + FreeRangeHeader &FollowingFreeBlock = *(FreeRangeHeader *)FollowingBlock; + // "FreeList" always needs to be a valid free block. If we're about to + // coalesce with it, update our notion of what the free list is. + if (&FollowingFreeBlock == FreeList) { + FreeList = FollowingFreeBlock.Next; + FreeListToReturn = 0; + assert(&FollowingFreeBlock != FreeList && "No tombstone block?"); + } + FollowingFreeBlock.RemoveFromFreeList(); + + // Include the following block into this one. + BlockSize += FollowingFreeBlock.BlockSize; + FollowingBlock = &FollowingFreeBlock.getBlockAfter(); + + // Tell the block after the block we are coalescing that this block is + // allocated. + FollowingBlock->PrevAllocated = 1; + } + + assert(FollowingBlock->ThisAllocated && "Missed coalescing?"); + + if (FreeRangeHeader *PrevFreeBlock = getFreeBlockBefore()) { + PrevFreeBlock->GrowBlock(PrevFreeBlock->BlockSize + BlockSize); + return FreeListToReturn ? FreeListToReturn : PrevFreeBlock; + } + + // Otherwise, mark this block free. + FreeRangeHeader &FreeBlock = *(FreeRangeHeader*)this; + FollowingBlock->PrevAllocated = 0; + FreeBlock.ThisAllocated = 0; + + // Link this into the linked list of free blocks. + FreeBlock.AddToFreeList(FreeList); + + // Add a marker at the end of the block, indicating the size of this free + // block. + FreeBlock.SetEndOfBlockSizeMarker(); + return FreeListToReturn ? FreeListToReturn : &FreeBlock; +} + +/// GrowBlock - The block after this block just got deallocated. Merge it +/// into the current block. +void FreeRangeHeader::GrowBlock(uintptr_t NewSize) { + assert(NewSize > BlockSize && "Not growing block?"); + BlockSize = NewSize; + SetEndOfBlockSizeMarker(); + getBlockAfter().PrevAllocated = 0; +} + +/// TrimAllocationToSize - If this allocated block is significantly larger +/// than NewSize, split it into two pieces (where the former is NewSize +/// bytes, including the header), and add the new block to the free list. +FreeRangeHeader *MemoryRangeHeader:: +TrimAllocationToSize(FreeRangeHeader *FreeList, uint64_t NewSize) { + assert(ThisAllocated && getBlockAfter().PrevAllocated && + "Cannot deallocate part of an allocated block!"); + + // Don't allow blocks to be trimmed below minimum required size + NewSize = std::max(FreeRangeHeader::getMinBlockSize(), NewSize); + + // Round up size for alignment of header. + unsigned HeaderAlign = __alignof(FreeRangeHeader); + NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1); + + // Size is now the size of the block we will remove from the start of the + // current block. + assert(NewSize <= BlockSize && + "Allocating more space from this block than exists!"); + + // If splitting this block will cause the remainder to be too small, do not + // split the block. + if (BlockSize <= NewSize+FreeRangeHeader::getMinBlockSize()) + return FreeList; + + // Otherwise, we splice the required number of bytes out of this block, form + // a new block immediately after it, then mark this block allocated. + MemoryRangeHeader &FormerNextBlock = getBlockAfter(); + + // Change the size of this block. + BlockSize = NewSize; + + // Get the new block we just sliced out and turn it into a free block. + FreeRangeHeader &NewNextBlock = (FreeRangeHeader &)getBlockAfter(); + NewNextBlock.BlockSize = (char*)&FormerNextBlock - (char*)&NewNextBlock; + NewNextBlock.ThisAllocated = 0; + NewNextBlock.PrevAllocated = 1; + NewNextBlock.SetEndOfBlockSizeMarker(); + FormerNextBlock.PrevAllocated = 0; + NewNextBlock.AddToFreeList(FreeList); + return &NewNextBlock; +} + +//===----------------------------------------------------------------------===// +// Memory Block Implementation. +//===----------------------------------------------------------------------===// + +namespace { + + class DefaultJITMemoryManager; + + class JITSlabAllocator : public SlabAllocator { + DefaultJITMemoryManager &JMM; + public: + JITSlabAllocator(DefaultJITMemoryManager &jmm) : JMM(jmm) { } + virtual ~JITSlabAllocator() { } + virtual MemSlab *Allocate(size_t Size); + virtual void Deallocate(MemSlab *Slab); + }; + + /// DefaultJITMemoryManager - Manage memory for the JIT code generation. + /// This splits a large block of MAP_NORESERVE'd memory into two + /// sections, one for function stubs, one for the functions themselves. We + /// have to do this because we may need to emit a function stub while in the + /// middle of emitting a function, and we don't know how large the function we + /// are emitting is. + class DefaultJITMemoryManager : public JITMemoryManager { + + // Whether to poison freed memory. + bool PoisonMemory; + + /// LastSlab - This points to the last slab allocated and is used as the + /// NearBlock parameter to AllocateRWX so that we can attempt to lay out all + /// stubs, data, and code contiguously in memory. In general, however, this + /// is not possible because the NearBlock parameter is ignored on Windows + /// platforms and even on Unix it works on a best-effort pasis. + sys::MemoryBlock LastSlab; + + // Memory slabs allocated by the JIT. We refer to them as slabs so we don't + // confuse them with the blocks of memory described above. + std::vector CodeSlabs; + JITSlabAllocator BumpSlabAllocator; + BumpPtrAllocator StubAllocator; + BumpPtrAllocator DataAllocator; + + // Circular list of free blocks. + FreeRangeHeader *FreeMemoryList; + + // When emitting code into a memory block, this is the block. + MemoryRangeHeader *CurBlock; + + uint8_t *GOTBase; // Target Specific reserved memory + public: + DefaultJITMemoryManager(); + ~DefaultJITMemoryManager(); + + /// allocateNewSlab - Allocates a new MemoryBlock and remembers it as the + /// last slab it allocated, so that subsequent allocations follow it. + sys::MemoryBlock allocateNewSlab(size_t size); + + /// DefaultCodeSlabSize - When we have to go map more memory, we allocate at + /// least this much unless more is requested. + static const size_t DefaultCodeSlabSize; + + /// DefaultSlabSize - Allocate data into slabs of this size unless we get + /// an allocation above SizeThreshold. + static const size_t DefaultSlabSize; + + /// DefaultSizeThreshold - For any allocation larger than this threshold, we + /// should allocate a separate slab. + static const size_t DefaultSizeThreshold; + + void AllocateGOT(); + + // Testing methods. + virtual bool CheckInvariants(std::string &ErrorStr); + size_t GetDefaultCodeSlabSize() { return DefaultCodeSlabSize; } + size_t GetDefaultDataSlabSize() { return DefaultSlabSize; } + size_t GetDefaultStubSlabSize() { return DefaultSlabSize; } + unsigned GetNumCodeSlabs() { return CodeSlabs.size(); } + unsigned GetNumDataSlabs() { return DataAllocator.GetNumSlabs(); } + unsigned GetNumStubSlabs() { return StubAllocator.GetNumSlabs(); } + + /// startFunctionBody - When a function starts, allocate a block of free + /// executable memory, returning a pointer to it and its actual size. + uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) { + + FreeRangeHeader* candidateBlock = FreeMemoryList; + FreeRangeHeader* head = FreeMemoryList; + FreeRangeHeader* iter = head->Next; + + uintptr_t largest = candidateBlock->BlockSize; + + // Search for the largest free block + while (iter != head) { + if (iter->BlockSize > largest) { + largest = iter->BlockSize; + candidateBlock = iter; + } + iter = iter->Next; + } + + largest = largest - sizeof(MemoryRangeHeader); + + // If this block isn't big enough for the allocation desired, allocate + // another block of memory and add it to the free list. + if (largest < ActualSize || + largest <= FreeRangeHeader::getMinBlockSize()) { + DEBUG(dbgs() << "JIT: Allocating another slab of memory for function."); + candidateBlock = allocateNewCodeSlab((size_t)ActualSize); + } + + // Select this candidate block for allocation + CurBlock = candidateBlock; + + // Allocate the entire memory block. + FreeMemoryList = candidateBlock->AllocateBlock(); + ActualSize = CurBlock->BlockSize - sizeof(MemoryRangeHeader); + return (uint8_t *)(CurBlock + 1); + } + + /// allocateNewCodeSlab - Helper method to allocate a new slab of code + /// memory from the OS and add it to the free list. Returns the new + /// FreeRangeHeader at the base of the slab. + FreeRangeHeader *allocateNewCodeSlab(size_t MinSize) { + // If the user needs at least MinSize free memory, then we account for + // two MemoryRangeHeaders: the one in the user's block, and the one at the + // end of the slab. + size_t PaddedMin = MinSize + 2 * sizeof(MemoryRangeHeader); + size_t SlabSize = std::max(DefaultCodeSlabSize, PaddedMin); + sys::MemoryBlock B = allocateNewSlab(SlabSize); + CodeSlabs.push_back(B); + char *MemBase = (char*)(B.base()); + + // Put a tiny allocated block at the end of the memory chunk, so when + // FreeBlock calls getBlockAfter it doesn't fall off the end. + MemoryRangeHeader *EndBlock = + (MemoryRangeHeader*)(MemBase + B.size()) - 1; + EndBlock->ThisAllocated = 1; + EndBlock->PrevAllocated = 0; + EndBlock->BlockSize = sizeof(MemoryRangeHeader); + + // Start out with a vast new block of free memory. + FreeRangeHeader *NewBlock = (FreeRangeHeader*)MemBase; + NewBlock->ThisAllocated = 0; + // Make sure getFreeBlockBefore doesn't look into unmapped memory. + NewBlock->PrevAllocated = 1; + NewBlock->BlockSize = (uintptr_t)EndBlock - (uintptr_t)NewBlock; + NewBlock->SetEndOfBlockSizeMarker(); + NewBlock->AddToFreeList(FreeMemoryList); + + assert(NewBlock->BlockSize - sizeof(MemoryRangeHeader) >= MinSize && + "The block was too small!"); + return NewBlock; + } + + /// endFunctionBody - The function F is now allocated, and takes the memory + /// in the range [FunctionStart,FunctionEnd). + void endFunctionBody(const Function *F, uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + assert(FunctionEnd > FunctionStart); + assert(FunctionStart == (uint8_t *)(CurBlock+1) && + "Mismatched function start/end!"); + + uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock; + + // Release the memory at the end of this block that isn't needed. + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + } + + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. + uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { + CurBlock = FreeMemoryList; + FreeMemoryList = FreeMemoryList->AllocateBlock(); + + uint8_t *result = (uint8_t *)(CurBlock + 1); + + if (Alignment == 0) Alignment = 1; + result = (uint8_t*)(((intptr_t)result+Alignment-1) & + ~(intptr_t)(Alignment-1)); + + uintptr_t BlockSize = result + Size - (uint8_t *)CurBlock; + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + + return result; + } + + /// allocateStub - Allocate memory for a function stub. + uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment) { + return (uint8_t*)StubAllocator.Allocate(StubSize, Alignment); + } + + /// allocateGlobal - Allocate memory for a global. + uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { + return (uint8_t*)DataAllocator.Allocate(Size, Alignment); + } + + /// startExceptionTable - Use startFunctionBody to allocate memory for the + /// function's exception table. + uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) { + return startFunctionBody(F, ActualSize); + } + + /// endExceptionTable - The exception table of F is now allocated, + /// and takes the memory in the range [TableStart,TableEnd). + void endExceptionTable(const Function *F, uint8_t *TableStart, + uint8_t *TableEnd, uint8_t* FrameRegister) { + assert(TableEnd > TableStart); + assert(TableStart == (uint8_t *)(CurBlock+1) && + "Mismatched table start/end!"); + + uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock; + + // Release the memory at the end of this block that isn't needed. + FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); + } + + uint8_t *getGOTBase() const { + return GOTBase; + } + + void deallocateBlock(void *Block) { + // Find the block that is allocated for this function. + MemoryRangeHeader *MemRange = static_cast(Block) - 1; + assert(MemRange->ThisAllocated && "Block isn't allocated!"); + + // Fill the buffer with garbage! + if (PoisonMemory) { + memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange)); + } + + // Free the memory. + FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); + } + + /// deallocateFunctionBody - Deallocate all memory for the specified + /// function body. + void deallocateFunctionBody(void *Body) { + if (Body) deallocateBlock(Body); + } + + /// deallocateExceptionTable - Deallocate memory for the specified + /// exception table. + void deallocateExceptionTable(void *ET) { + if (ET) deallocateBlock(ET); + } + + /// setMemoryWritable - When code generation is in progress, + /// the code pages may need permissions changed. + void setMemoryWritable() + { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::setWritable(CodeSlabs[i]); + } + /// setMemoryExecutable - When code generation is done and we're ready to + /// start execution, the code pages may need permissions changed. + void setMemoryExecutable() + { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::setExecutable(CodeSlabs[i]); + } + + /// setPoisonMemory - Controls whether we write garbage over freed memory. + /// + void setPoisonMemory(bool poison) { + PoisonMemory = poison; + } + }; +} + +MemSlab *JITSlabAllocator::Allocate(size_t Size) { + sys::MemoryBlock B = JMM.allocateNewSlab(Size); + MemSlab *Slab = (MemSlab*)B.base(); + Slab->Size = B.size(); + Slab->NextPtr = 0; + return Slab; +} + +void JITSlabAllocator::Deallocate(MemSlab *Slab) { + sys::MemoryBlock B(Slab, Slab->Size); + sys::Memory::ReleaseRWX(B); +} + +DefaultJITMemoryManager::DefaultJITMemoryManager() + : +#ifdef NDEBUG + PoisonMemory(false), +#else + PoisonMemory(true), +#endif + LastSlab(0, 0), + BumpSlabAllocator(*this), + StubAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator), + DataAllocator(DefaultSlabSize, DefaultSizeThreshold, BumpSlabAllocator) { + + // Allocate space for code. + sys::MemoryBlock MemBlock = allocateNewSlab(DefaultCodeSlabSize); + CodeSlabs.push_back(MemBlock); + uint8_t *MemBase = (uint8_t*)MemBlock.base(); + + // We set up the memory chunk with 4 mem regions, like this: + // [ START + // [ Free #0 ] -> Large space to allocate functions from. + // [ Allocated #1 ] -> Tiny space to separate regions. + // [ Free #2 ] -> Tiny space so there is always at least 1 free block. + // [ Allocated #3 ] -> Tiny space to prevent looking past end of block. + // END ] + // + // The last three blocks are never deallocated or touched. + + // Add MemoryRangeHeader to the end of the memory region, indicating that + // the space after the block of memory is allocated. This is block #3. + MemoryRangeHeader *Mem3 = (MemoryRangeHeader*)(MemBase+MemBlock.size())-1; + Mem3->ThisAllocated = 1; + Mem3->PrevAllocated = 0; + Mem3->BlockSize = sizeof(MemoryRangeHeader); + + /// Add a tiny free region so that the free list always has one entry. + FreeRangeHeader *Mem2 = + (FreeRangeHeader *)(((char*)Mem3)-FreeRangeHeader::getMinBlockSize()); + Mem2->ThisAllocated = 0; + Mem2->PrevAllocated = 1; + Mem2->BlockSize = FreeRangeHeader::getMinBlockSize(); + Mem2->SetEndOfBlockSizeMarker(); + Mem2->Prev = Mem2; // Mem2 *is* the free list for now. + Mem2->Next = Mem2; + + /// Add a tiny allocated region so that Mem2 is never coalesced away. + MemoryRangeHeader *Mem1 = (MemoryRangeHeader*)Mem2-1; + Mem1->ThisAllocated = 1; + Mem1->PrevAllocated = 0; + Mem1->BlockSize = sizeof(MemoryRangeHeader); + + // Add a FreeRangeHeader to the start of the function body region, indicating + // that the space is free. Mark the previous block allocated so we never look + // at it. + FreeRangeHeader *Mem0 = (FreeRangeHeader*)MemBase; + Mem0->ThisAllocated = 0; + Mem0->PrevAllocated = 1; + Mem0->BlockSize = (char*)Mem1-(char*)Mem0; + Mem0->SetEndOfBlockSizeMarker(); + Mem0->AddToFreeList(Mem2); + + // Start out with the freelist pointing to Mem0. + FreeMemoryList = Mem0; + + GOTBase = NULL; +} + +void DefaultJITMemoryManager::AllocateGOT() { + assert(GOTBase == 0 && "Cannot allocate the got multiple times"); + GOTBase = new uint8_t[sizeof(void*) * 8192]; + HasGOT = true; +} + +DefaultJITMemoryManager::~DefaultJITMemoryManager() { + for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i) + sys::Memory::ReleaseRWX(CodeSlabs[i]); + + delete[] GOTBase; +} + +sys::MemoryBlock DefaultJITMemoryManager::allocateNewSlab(size_t size) { + // Allocate a new block close to the last one. + std::string ErrMsg; + sys::MemoryBlock *LastSlabPtr = LastSlab.base() ? &LastSlab : 0; + sys::MemoryBlock B = sys::Memory::AllocateRWX(size, LastSlabPtr, &ErrMsg); + if (B.base() == 0) { + report_fatal_error("Allocation failed when allocating new memory in the" + " JIT\n" + Twine(ErrMsg)); + } + LastSlab = B; + ++NumSlabs; + // Initialize the slab to garbage when debugging. + if (PoisonMemory) { + memset(B.base(), 0xCD, B.size()); + } + return B; +} + +/// CheckInvariants - For testing only. Return "" if all internal invariants +/// are preserved, and a helpful error message otherwise. For free and +/// allocated blocks, make sure that adding BlockSize gives a valid block. +/// For free blocks, make sure they're in the free list and that their end of +/// block size marker is correct. This function should return an error before +/// accessing bad memory. This function is defined here instead of in +/// JITMemoryManagerTest.cpp so that we don't have to expose all of the +/// implementation details of DefaultJITMemoryManager. +bool DefaultJITMemoryManager::CheckInvariants(std::string &ErrorStr) { + raw_string_ostream Err(ErrorStr); + + // Construct a the set of FreeRangeHeader pointers so we can query it + // efficiently. + llvm::SmallPtrSet FreeHdrSet; + FreeRangeHeader* FreeHead = FreeMemoryList; + FreeRangeHeader* FreeRange = FreeHead; + + do { + // Check that the free range pointer is in the blocks we've allocated. + bool Found = false; + for (std::vector::iterator I = CodeSlabs.begin(), + E = CodeSlabs.end(); I != E && !Found; ++I) { + char *Start = (char*)I->base(); + char *End = Start + I->size(); + Found = (Start <= (char*)FreeRange && (char*)FreeRange < End); + } + if (!Found) { + Err << "Corrupt free list; points to " << FreeRange; + return false; + } + + if (FreeRange->Next->Prev != FreeRange) { + Err << "Next and Prev pointers do not match."; + return false; + } + + // Otherwise, add it to the set. + FreeHdrSet.insert(FreeRange); + FreeRange = FreeRange->Next; + } while (FreeRange != FreeHead); + + // Go over each block, and look at each MemoryRangeHeader. + for (std::vector::iterator I = CodeSlabs.begin(), + E = CodeSlabs.end(); I != E; ++I) { + char *Start = (char*)I->base(); + char *End = Start + I->size(); + + // Check each memory range. + for (MemoryRangeHeader *Hdr = (MemoryRangeHeader*)Start, *LastHdr = NULL; + Start <= (char*)Hdr && (char*)Hdr < End; + Hdr = &Hdr->getBlockAfter()) { + if (Hdr->ThisAllocated == 0) { + // Check that this range is in the free list. + if (!FreeHdrSet.count(Hdr)) { + Err << "Found free header at " << Hdr << " that is not in free list."; + return false; + } + + // Now make sure the size marker at the end of the block is correct. + uintptr_t *Marker = ((uintptr_t*)&Hdr->getBlockAfter()) - 1; + if (!(Start <= (char*)Marker && (char*)Marker < End)) { + Err << "Block size in header points out of current MemoryBlock."; + return false; + } + if (Hdr->BlockSize != *Marker) { + Err << "End of block size marker (" << *Marker << ") " + << "and BlockSize (" << Hdr->BlockSize << ") don't match."; + return false; + } + } + + if (LastHdr && LastHdr->ThisAllocated != Hdr->PrevAllocated) { + Err << "Hdr->PrevAllocated (" << Hdr->PrevAllocated << ") != " + << "LastHdr->ThisAllocated (" << LastHdr->ThisAllocated << ")"; + return false; + } else if (!LastHdr && !Hdr->PrevAllocated) { + Err << "The first header should have PrevAllocated true."; + return false; + } + + // Remember the last header. + LastHdr = Hdr; + } + } + + // All invariants are preserved. + return true; +} + +JITMemoryManager *JITMemoryManager::CreateDefaultMemManager() { + return new DefaultJITMemoryManager(); +} + +// Allocate memory for code in 512K slabs. +const size_t DefaultJITMemoryManager::DefaultCodeSlabSize = 512 * 1024; + +// Allocate globals and stubs in slabs of 64K. (probably 16 pages) +const size_t DefaultJITMemoryManager::DefaultSlabSize = 64 * 1024; + +// Waste at most 16K at the end of each bump slab. (probably 4 pages) +const size_t DefaultJITMemoryManager::DefaultSizeThreshold = 16 * 1024; diff --git a/final/lib/ExecutionEngine/JIT/Makefile b/final/lib/ExecutionEngine/JIT/Makefile new file mode 100644 index 00000000000..aafa3d9d420 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/Makefile @@ -0,0 +1,38 @@ +##===- lib/ExecutionEngine/JIT/Makefile --------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMJIT + +# Get the $(ARCH) setting +include $(LEVEL)/Makefile.config + +# Enable the X86 JIT if compiling on X86 +ifeq ($(ARCH), x86) + ENABLE_X86_JIT = 1 +endif + +# This flag can also be used on the command line to force inclusion +# of the X86 JIT on non-X86 hosts +ifdef ENABLE_X86_JIT + CPPFLAGS += -DENABLE_X86_JIT +endif + +# Enable the Sparc JIT if compiling on Sparc +ifeq ($(ARCH), Sparc) + ENABLE_SPARC_JIT = 1 +endif + +# This flag can also be used on the command line to force inclusion +# of the Sparc JIT on non-Sparc hosts +ifdef ENABLE_SPARC_JIT + CPPFLAGS += -DENABLE_SPARC_JIT +endif + +include $(LEVEL)/Makefile.common diff --git a/final/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp b/final/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp new file mode 100644 index 00000000000..670fa7da1fe --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp @@ -0,0 +1,192 @@ +//===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===// +// +// 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 JITEventListener object that calls into OProfile to tell +// it about JITted functions. For now, we only record function names and sizes, +// but eventually we'll also record line number information. +// +// See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the +// definition of the interface we're using. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "oprofile-jit-event-listener" +#include "llvm/Function.h" +#include "llvm/Metadata.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ExecutionEngine/JITEventListener.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ValueHandle.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Errno.h" +#include "llvm/Config/config.h" +#include +using namespace llvm; + +#if USE_OPROFILE + +#include + +namespace { + +class OProfileJITEventListener : public JITEventListener { + op_agent_t Agent; +public: + OProfileJITEventListener(); + ~OProfileJITEventListener(); + + virtual void NotifyFunctionEmitted(const Function &F, + void *FnStart, size_t FnSize, + const EmittedFunctionDetails &Details); + virtual void NotifyFreeingMachineCode(void *OldPtr); +}; + +OProfileJITEventListener::OProfileJITEventListener() + : Agent(op_open_agent()) { + if (Agent == NULL) { + const std::string err_str = sys::StrError(); + DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n"); + } else { + DEBUG(dbgs() << "Connected to OProfile agent.\n"); + } +} + +OProfileJITEventListener::~OProfileJITEventListener() { + if (Agent != NULL) { + if (op_close_agent(Agent) == -1) { + const std::string err_str = sys::StrError(); + DEBUG(dbgs() << "Failed to disconnect from OProfile agent: " + << err_str << "\n"); + } else { + DEBUG(dbgs() << "Disconnected from OProfile agent.\n"); + } + } +} + +class FilenameCache { + // Holds the filename of each Scope, so that we can pass a null-terminated + // string into oprofile. Use an AssertingVH rather than a ValueMap because we + // shouldn't be modifying any MDNodes while this map is alive. + DenseMap, std::string> Filenames; + + public: + const char *getFilename(MDNode *Scope) { + std::string &Filename = Filenames[Scope]; + if (Filename.empty()) { + Filename = DIScope(Scope).getFilename(); + } + return Filename.c_str(); + } +}; + +static debug_line_info LineStartToOProfileFormat( + const MachineFunction &MF, FilenameCache &Filenames, + uintptr_t Address, DebugLoc Loc) { + debug_line_info Result; + Result.vma = Address; + Result.lineno = Loc.getLine(); + Result.filename = Filenames.getFilename( + Loc.getScope(MF.getFunction()->getContext())); + DEBUG(dbgs() << "Mapping " << reinterpret_cast(Result.vma) << " to " + << Result.filename << ":" << Result.lineno << "\n"); + return Result; +} + +// Adds the just-emitted function to the symbol table. +void OProfileJITEventListener::NotifyFunctionEmitted( + const Function &F, void *FnStart, size_t FnSize, + const EmittedFunctionDetails &Details) { + assert(F.hasName() && FnStart != 0 && "Bad symbol to add"); + if (op_write_native_code(Agent, F.getName().data(), + reinterpret_cast(FnStart), + FnStart, FnSize) == -1) { + DEBUG(dbgs() << "Failed to tell OProfile about native function " + << F.getName() << " at [" + << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); + return; + } + + if (!Details.LineStarts.empty()) { + // Now we convert the line number information from the address/DebugLoc + // format in Details to the address/filename/lineno format that OProfile + // expects. Note that OProfile 0.9.4 has a bug that causes it to ignore + // line numbers for addresses above 4G. + FilenameCache Filenames; + std::vector LineInfo; + LineInfo.reserve(1 + Details.LineStarts.size()); + + DebugLoc FirstLoc = Details.LineStarts[0].Loc; + assert(!FirstLoc.isUnknown() + && "LineStarts should not contain unknown DebugLocs"); + MDNode *FirstLocScope = FirstLoc.getScope(F.getContext()); + DISubprogram FunctionDI = getDISubprogram(FirstLocScope); + if (FunctionDI.Verify()) { + // If we have debug info for the function itself, use that as the line + // number of the first several instructions. Otherwise, after filling + // LineInfo, we'll adjust the address of the first line number to point at + // the start of the function. + debug_line_info line_info; + line_info.vma = reinterpret_cast(FnStart); + line_info.lineno = FunctionDI.getLineNumber(); + line_info.filename = Filenames.getFilename(FirstLocScope); + LineInfo.push_back(line_info); + } + + for (std::vector::const_iterator + I = Details.LineStarts.begin(), E = Details.LineStarts.end(); + I != E; ++I) { + LineInfo.push_back(LineStartToOProfileFormat( + *Details.MF, Filenames, I->Address, I->Loc)); + } + + // In case the function didn't have line info of its own, adjust the first + // line info's address to include the start of the function. + LineInfo[0].vma = reinterpret_cast(FnStart); + + if (op_write_debug_line_info(Agent, FnStart, + LineInfo.size(), &*LineInfo.begin()) == -1) { + DEBUG(dbgs() + << "Failed to tell OProfile about line numbers for native function " + << F.getName() << " at [" + << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n"); + } + } +} + +// Removes the being-deleted function from the symbol table. +void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) { + assert(FnStart && "Invalid function pointer"); + if (op_unload_native_code(Agent, reinterpret_cast(FnStart)) == -1) { + DEBUG(dbgs() + << "Failed to tell OProfile about unload of native function at " + << FnStart << "\n"); + } +} + +} // anonymous namespace. + +namespace llvm { +JITEventListener *createOProfileJITEventListener() { + return new OProfileJITEventListener; +} +} + +#else // USE_OPROFILE + +namespace llvm { +// By defining this to return NULL, we can let clients call it unconditionally, +// even if they haven't configured with the OProfile libraries. +JITEventListener *createOProfileJITEventListener() { + return NULL; +} +} // namespace llvm + +#endif // USE_OPROFILE diff --git a/final/lib/ExecutionEngine/JIT/TargetSelect.cpp b/final/lib/ExecutionEngine/JIT/TargetSelect.cpp new file mode 100644 index 00000000000..6b7173cece1 --- /dev/null +++ b/final/lib/ExecutionEngine/JIT/TargetSelect.cpp @@ -0,0 +1,91 @@ +//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This just asks the TargetRegistry for the appropriate JIT to use, and allows +// the user to specify a specific one on the commandline with -march=x. Clients +// should initialize targets prior to calling createJIT. +// +//===----------------------------------------------------------------------===// + +#include "JIT.h" +#include "llvm/Module.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Host.h" +#include "llvm/Target/SubtargetFeature.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +/// selectTarget - Pick a target either via -march or by guessing the native +/// arch. Add any CPU features specified via -mcpu or -mattr. +TargetMachine *JIT::selectTarget(Module *Mod, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs, + std::string *ErrorStr) { + Triple TheTriple(Mod->getTargetTriple()); + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + // Adjust the triple to match what the user requested. + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + *ErrorStr = "No available targets are compatible with this -march, " + "see -version for the available targets.\n"; + return 0; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + std::string Error; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); + if (TheTarget == 0) { + if (ErrorStr) + *ErrorStr = Error; + return 0; + } + } + + if (!TheTarget->hasJIT()) { + errs() << "WARNING: This target JIT is not designed for the host you are" + << " running. If bad things happen, please choose a different " + << "-march switch.\n"; + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (!MCPU.empty() || !MAttrs.empty()) { + SubtargetFeatures Features; + Features.setCPU(MCPU); + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + // Allocate a target... + TargetMachine *Target = + TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); + assert(Target && "Could not allocate target machine!"); + return Target; +} diff --git a/final/lib/ExecutionEngine/MCJIT/CMakeLists.txt b/final/lib/ExecutionEngine/MCJIT/CMakeLists.txt new file mode 100644 index 00000000000..f7ed176fef7 --- /dev/null +++ b/final/lib/ExecutionEngine/MCJIT/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMMCJIT + MCJIT.cpp + TargetSelect.cpp + ) diff --git a/final/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/final/lib/ExecutionEngine/MCJIT/MCJIT.cpp new file mode 100644 index 00000000000..f1e9dab250b --- /dev/null +++ b/final/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -0,0 +1,92 @@ +//===-- JIT.cpp - MC-based Just-in-Time Compiler --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCJIT.h" +#include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/DynamicLibrary.h" + +using namespace llvm; + +namespace { + +static struct RegisterJIT { + RegisterJIT() { MCJIT::Register(); } +} JITRegistrator; + +} + +extern "C" void LLVMLinkInMCJIT() { +} + +ExecutionEngine *MCJIT::createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs) { + // Try to register the program as a source of symbols to resolve against. + // + // FIXME: Don't do this here. + sys::DynamicLibrary::LoadLibraryPermanently(0, NULL); + + // Pick a target either via -march or by guessing the native arch. + // + // FIXME: This should be lifted out of here, it isn't something which should + // be part of the JIT policy, rather the burden for this selection should be + // pushed to clients. + TargetMachine *TM = MCJIT::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr); + if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0; + TM->setCodeModel(CMM); + + // If the target supports JIT code generation, create the JIT. + if (TargetJITInfo *TJ = TM->getJITInfo()) + return new MCJIT(M, *TM, *TJ, JMM, OptLevel, GVsWithCode); + + if (ErrorStr) + *ErrorStr = "target does not support JIT code generation"; + return 0; +} + +MCJIT::MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, + bool AllocateGVsWithCode) + : ExecutionEngine(M) { +} + +MCJIT::~MCJIT() { +} + +void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) { + report_fatal_error("not yet implemented"); + return 0; +} + +void *MCJIT::getPointerToFunction(Function *F) { + report_fatal_error("not yet implemented"); + return 0; +} + +void *MCJIT::recompileAndRelinkFunction(Function *F) { + report_fatal_error("not yet implemented"); +} + +void MCJIT::freeMachineCodeForFunction(Function *F) { + report_fatal_error("not yet implemented"); +} + +GenericValue MCJIT::runFunction(Function *F, + const std::vector &ArgValues) { + report_fatal_error("not yet implemented"); + return GenericValue(); +} diff --git a/final/lib/ExecutionEngine/MCJIT/MCJIT.h b/final/lib/ExecutionEngine/MCJIT/MCJIT.h new file mode 100644 index 00000000000..cd1f989b10c --- /dev/null +++ b/final/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -0,0 +1,68 @@ +//===-- MCJIT.h - Class definition for the MCJIT ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_H +#define LLVM_LIB_EXECUTIONENGINE_MCJIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" + +namespace llvm { + +class MCJIT : public ExecutionEngine { + MCJIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, + JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, + bool AllocateGVsWithCode); +public: + ~MCJIT(); + + /// @name ExecutionEngine interface implementation + /// @{ + + virtual void *getPointerToBasicBlock(BasicBlock *BB); + + virtual void *getPointerToFunction(Function *F); + + virtual void *recompileAndRelinkFunction(Function *F); + + virtual void freeMachineCodeForFunction(Function *F); + + virtual GenericValue runFunction(Function *F, + const std::vector &ArgValues); + + /// @} + /// @name (Private) Registration Interfaces + /// @{ + + static void Register() { + MCJITCtor = createJIT; + } + + // FIXME: This routine is scheduled for termination. Do not use it. + static TargetMachine *selectTarget(Module *M, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs, + std::string *Err); + + static ExecutionEngine *createJIT(Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode, + CodeModel::Model CMM, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs); + + // @} +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/ExecutionEngine/MCJIT/Makefile b/final/lib/ExecutionEngine/MCJIT/Makefile new file mode 100644 index 00000000000..967efbc0efa --- /dev/null +++ b/final/lib/ExecutionEngine/MCJIT/Makefile @@ -0,0 +1,13 @@ +##===- lib/ExecutionEngine/MCJIT/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCJIT + +include $(LEVEL)/Makefile.common diff --git a/final/lib/ExecutionEngine/MCJIT/TargetSelect.cpp b/final/lib/ExecutionEngine/MCJIT/TargetSelect.cpp new file mode 100644 index 00000000000..50f65938bb0 --- /dev/null +++ b/final/lib/ExecutionEngine/MCJIT/TargetSelect.cpp @@ -0,0 +1,91 @@ +//===-- TargetSelect.cpp - Target Chooser Code ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This just asks the TargetRegistry for the appropriate JIT to use, and allows +// the user to specify a specific one on the commandline with -march=x. Clients +// should initialize targets prior to calling createJIT. +// +//===----------------------------------------------------------------------===// + +#include "MCJIT.h" +#include "llvm/Module.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Host.h" +#include "llvm/Target/SubtargetFeature.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +/// selectTarget - Pick a target either via -march or by guessing the native +/// arch. Add any CPU features specified via -mcpu or -mattr. +TargetMachine *MCJIT::selectTarget(Module *Mod, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs, + std::string *ErrorStr) { + Triple TheTriple(Mod->getTargetTriple()); + if (TheTriple.getTriple().empty()) + TheTriple.setTriple(sys::getHostTriple()); + + // Adjust the triple to match what the user requested. + const Target *TheTarget = 0; + if (!MArch.empty()) { + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + if (MArch == it->getName()) { + TheTarget = &*it; + break; + } + } + + if (!TheTarget) { + *ErrorStr = "No available targets are compatible with this -march, " + "see -version for the available targets.\n"; + return 0; + } + + // Adjust the triple to match (if known), otherwise stick with the + // module/host triple. + Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); + if (Type != Triple::UnknownArch) + TheTriple.setArch(Type); + } else { + std::string Error; + TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); + if (TheTarget == 0) { + if (ErrorStr) + *ErrorStr = Error; + return 0; + } + } + + if (!TheTarget->hasJIT()) { + errs() << "WARNING: This target JIT is not designed for the host you are" + << " running. If bad things happen, please choose a different " + << "-march switch.\n"; + } + + // Package up features to be passed to target/subtarget + std::string FeaturesStr; + if (!MCPU.empty() || !MAttrs.empty()) { + SubtargetFeatures Features; + Features.setCPU(MCPU); + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + FeaturesStr = Features.getString(); + } + + // Allocate a target... + TargetMachine *Target = + TheTarget->createTargetMachine(TheTriple.getTriple(), FeaturesStr); + assert(Target && "Could not allocate target machine!"); + return Target; +} diff --git a/final/lib/ExecutionEngine/Makefile b/final/lib/ExecutionEngine/Makefile new file mode 100644 index 00000000000..1858d776616 --- /dev/null +++ b/final/lib/ExecutionEngine/Makefile @@ -0,0 +1,13 @@ +##===- lib/ExecutionEngine/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../.. +LIBRARYNAME = LLVMExecutionEngine +PARALLEL_DIRS = Interpreter JIT MCJIT + +include $(LEVEL)/Makefile.common diff --git a/final/lib/Linker/CMakeLists.txt b/final/lib/Linker/CMakeLists.txt new file mode 100644 index 00000000000..0b6d2f4218e --- /dev/null +++ b/final/lib/Linker/CMakeLists.txt @@ -0,0 +1,6 @@ +add_llvm_library(LLVMLinker + LinkArchives.cpp + LinkItems.cpp + LinkModules.cpp + Linker.cpp + ) diff --git a/final/lib/Linker/LinkArchives.cpp b/final/lib/Linker/LinkArchives.cpp new file mode 100644 index 00000000000..2c4ed7fdc17 --- /dev/null +++ b/final/lib/Linker/LinkArchives.cpp @@ -0,0 +1,198 @@ +//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines to handle linking together LLVM bitcode files, +// and to handle annoying things like static libraries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/Module.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/Bitcode/Archive.h" +#include "llvm/Config/config.h" +#include +#include +using namespace llvm; + +/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still +/// exist in an LLVM module. This is a bit tricky because there may be two +/// symbols with the same name but different LLVM types that will be resolved to +/// each other but aren't currently (thus we need to treat it as resolved). +/// +/// Inputs: +/// M - The module in which to find undefined symbols. +/// +/// Outputs: +/// UndefinedSymbols - A set of C++ strings containing the name of all +/// undefined symbols. +/// +static void +GetAllUndefinedSymbols(Module *M, std::set &UndefinedSymbols) { + std::set DefinedSymbols; + UndefinedSymbols.clear(); + + // If the program doesn't define a main, try pulling one in from a .a file. + // This is needed for programs where the main function is defined in an + // archive, such f2c'd programs. + Function *Main = M->getFunction("main"); + if (Main == 0 || Main->isDeclaration()) + UndefinedSymbols.insert("main"); + + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + if (I->hasName()) { + if (I->isDeclaration()) + UndefinedSymbols.insert(I->getName()); + else if (!I->hasLocalLinkage()) { + assert(!I->hasDLLImportLinkage() + && "Found dllimported non-external symbol!"); + DefinedSymbols.insert(I->getName()); + } + } + + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) + if (I->hasName()) { + if (I->isDeclaration()) + UndefinedSymbols.insert(I->getName()); + else if (!I->hasLocalLinkage()) { + assert(!I->hasDLLImportLinkage() + && "Found dllimported non-external symbol!"); + DefinedSymbols.insert(I->getName()); + } + } + + for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); + I != E; ++I) + if (I->hasName()) + DefinedSymbols.insert(I->getName()); + + // Prune out any defined symbols from the undefined symbols set... + for (std::set::iterator I = UndefinedSymbols.begin(); + I != UndefinedSymbols.end(); ) + if (DefinedSymbols.count(*I)) + UndefinedSymbols.erase(I++); // This symbol really is defined! + else + ++I; // Keep this symbol in the undefined symbols list +} + +/// LinkInArchive - opens an archive library and link in all objects which +/// provide symbols that are currently undefined. +/// +/// Inputs: +/// Filename - The pathname of the archive. +/// +/// Return Value: +/// TRUE - An error occurred. +/// FALSE - No errors. +bool +Linker::LinkInArchive(const sys::Path &Filename, bool &is_native) { + // Make sure this is an archive file we're dealing with + if (!Filename.isArchive()) + return error("File '" + Filename.str() + "' is not an archive."); + + // Open the archive file + verbose("Linking archive file '" + Filename.str() + "'"); + + // Find all of the symbols currently undefined in the bitcode program. + // If all the symbols are defined, the program is complete, and there is + // no reason to link in any archive files. + std::set UndefinedSymbols; + GetAllUndefinedSymbols(Composite, UndefinedSymbols); + + if (UndefinedSymbols.empty()) { + verbose("No symbols undefined, skipping library '" + Filename.str() + "'"); + return false; // No need to link anything in! + } + + std::string ErrMsg; + std::auto_ptr AutoArch ( + Archive::OpenAndLoadSymbols(Filename, Context, &ErrMsg)); + + Archive* arch = AutoArch.get(); + + if (!arch) + return error("Cannot read archive '" + Filename.str() + + "': " + ErrMsg); + if (!arch->isBitcodeArchive()) { + is_native = true; + return false; + } + is_native = false; + + // Save a set of symbols that are not defined by the archive. Since we're + // entering a loop, there's no point searching for these multiple times. This + // variable is used to "set_subtract" from the set of undefined symbols. + std::set NotDefinedByArchive; + + // Save the current set of undefined symbols, because we may have to make + // multiple passes over the archive: + std::set CurrentlyUndefinedSymbols; + + do { + CurrentlyUndefinedSymbols = UndefinedSymbols; + + // Find the modules we need to link into the target module. Note that arch + // keeps ownership of these modules and may return the same Module* from a + // subsequent call. + std::set Modules; + if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg)) + return error("Cannot find symbols in '" + Filename.str() + + "': " + ErrMsg); + + // If we didn't find any more modules to link this time, we are done + // searching this archive. + if (Modules.empty()) + break; + + // Any symbols remaining in UndefinedSymbols after + // findModulesDefiningSymbols are ones that the archive does not define. So + // we add them to the NotDefinedByArchive variable now. + NotDefinedByArchive.insert(UndefinedSymbols.begin(), + UndefinedSymbols.end()); + + // Loop over all the Modules that we got back from the archive + for (std::set::iterator I=Modules.begin(), E=Modules.end(); + I != E; ++I) { + + // Get the module we must link in. + std::string moduleErrorMsg; + Module* aModule = *I; + if (aModule != NULL) { + if (aModule->MaterializeAll(&moduleErrorMsg)) + return error("Could not load a module: " + moduleErrorMsg); + + verbose(" Linking in module: " + aModule->getModuleIdentifier()); + + // Link it in + if (LinkInModule(aModule, &moduleErrorMsg)) + return error("Cannot link in module '" + + aModule->getModuleIdentifier() + "': " + moduleErrorMsg); + } + } + + // Get the undefined symbols from the aggregate module. This recomputes the + // symbols we still need after the new modules have been linked in. + GetAllUndefinedSymbols(Composite, UndefinedSymbols); + + // At this point we have two sets of undefined symbols: UndefinedSymbols + // which holds the undefined symbols from all the modules, and + // NotDefinedByArchive which holds symbols we know the archive doesn't + // define. There's no point searching for symbols that we won't find in the + // archive so we subtract these sets. + set_subtract(UndefinedSymbols, NotDefinedByArchive); + + // If there's no symbols left, no point in continuing to search the + // archive. + if (UndefinedSymbols.empty()) + break; + } while (CurrentlyUndefinedSymbols != UndefinedSymbols); + + return false; +} diff --git a/final/lib/Linker/LinkItems.cpp b/final/lib/Linker/LinkItems.cpp new file mode 100644 index 00000000000..52a0d175a5c --- /dev/null +++ b/final/lib/Linker/LinkItems.cpp @@ -0,0 +1,241 @@ +//===- lib/Linker/LinkItems.cpp - Link LLVM objects and libraries ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains routines to handle linking together LLVM bitcode files, +// and to handle annoying things like static libraries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/Module.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/system_error.h" +using namespace llvm; + +// LinkItems - This function is the main entry point into linking. It takes a +// list of LinkItem which indicates the order the files should be linked and +// how each file should be treated (plain file or with library search). The +// function only links bitcode and produces a result list of items that are +// native objects. +bool +Linker::LinkInItems(const ItemList& Items, ItemList& NativeItems) { + // Clear the NativeItems just in case + NativeItems.clear(); + + // For each linkage item ... + for (ItemList::const_iterator I = Items.begin(), E = Items.end(); + I != E; ++I) { + if (I->second) { + // Link in the library suggested. + bool is_native = false; + if (LinkInLibrary(I->first, is_native)) + return true; + if (is_native) + NativeItems.push_back(*I); + } else { + // Link in the file suggested + bool is_native = false; + if (LinkInFile(sys::Path(I->first), is_native)) + return true; + if (is_native) + NativeItems.push_back(*I); + } + } + + // At this point we have processed all the link items provided to us. Since + // we have an aggregated module at this point, the dependent libraries in + // that module should also be aggregated with duplicates eliminated. This is + // now the time to process the dependent libraries to resolve any remaining + // symbols. + bool is_native; + for (Module::lib_iterator I = Composite->lib_begin(), + E = Composite->lib_end(); I != E; ++I) { + if(LinkInLibrary(*I, is_native)) + return true; + if (is_native) + NativeItems.push_back(std::make_pair(*I, true)); + } + + return false; +} + + +/// LinkInLibrary - links one library into the HeadModule. +/// +bool Linker::LinkInLibrary(StringRef Lib, bool& is_native) { + is_native = false; + // Determine where this library lives. + sys::Path Pathname = FindLib(Lib); + if (Pathname.isEmpty()) + return error("Cannot find library '" + Lib.str() + "'"); + + // If its an archive, try to link it in + std::string Magic; + Pathname.getMagicNumber(Magic, 64); + switch (sys::IdentifyFileType(Magic.c_str(), 64)) { + default: llvm_unreachable("Bad file type identification"); + case sys::Unknown_FileType: + return warning("Supposed library '" + Lib.str() + "' isn't a library."); + + case sys::Bitcode_FileType: + // LLVM ".so" file. + if (LinkInFile(Pathname, is_native)) + return true; + break; + + case sys::Archive_FileType: + if (LinkInArchive(Pathname, is_native)) + return error("Cannot link archive '" + Pathname.str() + "'"); + break; + + case sys::ELF_Relocatable_FileType: + case sys::ELF_SharedObject_FileType: + case sys::Mach_O_Object_FileType: + case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: + case sys::COFF_FileType: + is_native = true; + break; + } + return false; +} + +/// LinkLibraries - takes the specified library files and links them into the +/// main bitcode object file. +/// +/// Inputs: +/// Libraries - The list of libraries to link into the module. +/// +/// Return value: +/// FALSE - No error. +/// TRUE - Error. +/// +bool Linker::LinkInLibraries(const std::vector &Libraries) { + + // Process the set of libraries we've been provided. + bool is_native = false; + for (unsigned i = 0; i < Libraries.size(); ++i) + if (LinkInLibrary(Libraries[i], is_native)) + return true; + + // At this point we have processed all the libraries provided to us. Since + // we have an aggregated module at this point, the dependent libraries in + // that module should also be aggregated with duplicates eliminated. This is + // now the time to process the dependent libraries to resolve any remaining + // symbols. + const Module::LibraryListType& DepLibs = Composite->getLibraries(); + for (Module::LibraryListType::const_iterator I = DepLibs.begin(), + E = DepLibs.end(); I != E; ++I) + if (LinkInLibrary(*I, is_native)) + return true; + + return false; +} + +/// LinkInFile - opens a bitcode file and links in all objects which +/// provide symbols that are currently undefined. +/// +/// Inputs: +/// File - The pathname of the bitcode file. +/// +/// Outputs: +/// ErrorMessage - A C++ string detailing what error occurred, if any. +/// +/// Return Value: +/// TRUE - An error occurred. +/// FALSE - No errors. +/// +bool Linker::LinkInFile(const sys::Path &File, bool &is_native) { + is_native = false; + + // Check for a file of name "-", which means "read standard input" + if (File.str() == "-") { + std::auto_ptr M; + OwningPtr Buffer; + error_code ec; + if (!(ec = MemoryBuffer::getSTDIN(Buffer))) { + if (!Buffer->getBufferSize()) { + Error = "standard input is empty"; + } else { + M.reset(ParseBitcodeFile(Buffer.get(), Context, &Error)); + if (M.get()) + if (!LinkInModule(M.get(), &Error)) + return false; + } + } + return error("Cannot link stdin: " + ec.message()); + } + + // Determine what variety of file it is. + std::string Magic; + if (!File.getMagicNumber(Magic, 64)) + return error("Cannot find linker input '" + File.str() + "'"); + + switch (sys::IdentifyFileType(Magic.c_str(), 64)) { + default: llvm_unreachable("Bad file type identification"); + case sys::Unknown_FileType: + return warning("Ignoring file '" + File.str() + + "' because does not contain bitcode."); + + case sys::Archive_FileType: + // A user may specify an ar archive without -l, perhaps because it + // is not installed as a library. Detect that and link the archive. + if (LinkInArchive(File, is_native)) + return true; + break; + + case sys::Bitcode_FileType: { + verbose("Linking bitcode file '" + File.str() + "'"); + std::auto_ptr M(LoadObject(File)); + if (M.get() == 0) + return error("Cannot load file '" + File.str() + "': " + Error); + if (LinkInModule(M.get(), &Error)) + return error("Cannot link file '" + File.str() + "': " + Error); + + verbose("Linked in file '" + File.str() + "'"); + break; + } + + case sys::ELF_Relocatable_FileType: + case sys::ELF_SharedObject_FileType: + case sys::Mach_O_Object_FileType: + case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: + case sys::COFF_FileType: + is_native = true; + break; + } + return false; +} + +/// LinkFiles - takes a module and a list of files and links them all together. +/// It locates the file either in the current directory, as its absolute +/// or relative pathname, or as a file somewhere in LLVM_LIB_SEARCH_PATH. +/// +/// Inputs: +/// Files - A vector of sys::Path indicating the LLVM bitcode filenames +/// to be linked. The names can refer to a mixture of pure LLVM +/// bitcode files and archive (ar) formatted files. +/// +/// Return value: +/// FALSE - No errors. +/// TRUE - Some error occurred. +/// +bool Linker::LinkInFiles(const std::vector &Files) { + bool is_native; + for (unsigned i = 0; i < Files.size(); ++i) + if (LinkInFile(Files[i], is_native)) + return true; + return false; +} diff --git a/final/lib/Linker/LinkModules.cpp b/final/lib/Linker/LinkModules.cpp new file mode 100644 index 00000000000..5aa06abdd98 --- /dev/null +++ b/final/lib/Linker/LinkModules.cpp @@ -0,0 +1,1301 @@ +//===- lib/Linker/LinkModules.cpp - Module Linker Implementation ----------===// +// +// 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 LLVM module linker. +// +// Specifically, this: +// * Merges global variables between the two modules +// * Uninit + Uninit = Init, Init + Uninit = Init, Init + Init = Error if != +// * Merges functions between two modules +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/TypeSymbolTable.h" +#include "llvm/ValueSymbolTable.h" +#include "llvm/Instructions.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Path.h" +#include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/ADT/DenseMap.h" +using namespace llvm; + +// Error - Simple wrapper function to conditionally assign to E and return true. +// This just makes error return conditions a little bit simpler... +static inline bool Error(std::string *E, const Twine &Message) { + if (E) *E = Message.str(); + return true; +} + +// Function: ResolveTypes() +// +// Description: +// Attempt to link the two specified types together. +// +// Inputs: +// DestTy - The type to which we wish to resolve. +// SrcTy - The original type which we want to resolve. +// +// Outputs: +// DestST - The symbol table in which the new type should be placed. +// +// Return value: +// true - There is an error and the types cannot yet be linked. +// false - No errors. +// +static bool ResolveTypes(const Type *DestTy, const Type *SrcTy) { + if (DestTy == SrcTy) return false; // If already equal, noop + assert(DestTy && SrcTy && "Can't handle null types"); + + if (const OpaqueType *OT = dyn_cast(DestTy)) { + // Type _is_ in module, just opaque... + const_cast(OT)->refineAbstractTypeTo(SrcTy); + } else if (const OpaqueType *OT = dyn_cast(SrcTy)) { + const_cast(OT)->refineAbstractTypeTo(DestTy); + } else { + return true; // Cannot link types... not-equal and neither is opaque. + } + return false; +} + +/// LinkerTypeMap - This implements a map of types that is stable +/// even if types are resolved/refined to other types. This is not a general +/// purpose map, it is specific to the linker's use. +namespace { +class LinkerTypeMap : public AbstractTypeUser { + typedef DenseMap TheMapTy; + TheMapTy TheMap; + + LinkerTypeMap(const LinkerTypeMap&); // DO NOT IMPLEMENT + void operator=(const LinkerTypeMap&); // DO NOT IMPLEMENT +public: + LinkerTypeMap() {} + ~LinkerTypeMap() { + for (DenseMap::iterator I = TheMap.begin(), + E = TheMap.end(); I != E; ++I) + I->first->removeAbstractTypeUser(this); + } + + /// lookup - Return the value for the specified type or null if it doesn't + /// exist. + const Type *lookup(const Type *Ty) const { + TheMapTy::const_iterator I = TheMap.find(Ty); + if (I != TheMap.end()) return I->second; + return 0; + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(const Type *Src, const Type *Dst) { + if (!TheMap.insert(std::make_pair(Src, PATypeHolder(Dst))).second) + return false; // Already in map. + if (Src->isAbstract()) + Src->addAbstractTypeUser(this); + return true; + } + +protected: + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) { + TheMapTy::iterator I = TheMap.find(OldTy); + const Type *DstTy = I->second; + + TheMap.erase(I); + if (OldTy->isAbstract()) + OldTy->removeAbstractTypeUser(this); + + // Don't reinsert into the map if the key is concrete now. + if (NewTy->isAbstract()) + insert(NewTy, DstTy); + } + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on it's + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + virtual void typeBecameConcrete(const DerivedType *AbsTy) { + TheMap.erase(AbsTy); + AbsTy->removeAbstractTypeUser(this); + } + + // for debugging... + virtual void dump() const { + dbgs() << "AbstractTypeSet!\n"; + } +}; +} + + +// RecursiveResolveTypes - This is just like ResolveTypes, except that it +// recurses down into derived types, merging the used types if the parent types +// are compatible. +static bool RecursiveResolveTypesI(const Type *DstTy, const Type *SrcTy, + LinkerTypeMap &Pointers) { + if (DstTy == SrcTy) return false; // If already equal, noop + + // If we found our opaque type, resolve it now! + if (DstTy->isOpaqueTy() || SrcTy->isOpaqueTy()) + return ResolveTypes(DstTy, SrcTy); + + // Two types cannot be resolved together if they are of different primitive + // type. For example, we cannot resolve an int to a float. + if (DstTy->getTypeID() != SrcTy->getTypeID()) return true; + + // If neither type is abstract, then they really are just different types. + if (!DstTy->isAbstract() && !SrcTy->isAbstract()) + return true; + + // Otherwise, resolve the used type used by this derived type... + switch (DstTy->getTypeID()) { + default: + return true; + case Type::FunctionTyID: { + const FunctionType *DstFT = cast(DstTy); + const FunctionType *SrcFT = cast(SrcTy); + if (DstFT->isVarArg() != SrcFT->isVarArg() || + DstFT->getNumContainedTypes() != SrcFT->getNumContainedTypes()) + return true; + + // Use TypeHolder's so recursive resolution won't break us. + PATypeHolder ST(SrcFT), DT(DstFT); + for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) { + const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i); + if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers)) + return true; + } + return false; + } + case Type::StructTyID: { + const StructType *DstST = cast(DstTy); + const StructType *SrcST = cast(SrcTy); + if (DstST->getNumContainedTypes() != SrcST->getNumContainedTypes()) + return true; + + PATypeHolder ST(SrcST), DT(DstST); + for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) { + const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i); + if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers)) + return true; + } + return false; + } + case Type::ArrayTyID: { + const ArrayType *DAT = cast(DstTy); + const ArrayType *SAT = cast(SrcTy); + if (DAT->getNumElements() != SAT->getNumElements()) return true; + return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(), + Pointers); + } + case Type::VectorTyID: { + const VectorType *DVT = cast(DstTy); + const VectorType *SVT = cast(SrcTy); + if (DVT->getNumElements() != SVT->getNumElements()) return true; + return RecursiveResolveTypesI(DVT->getElementType(), SVT->getElementType(), + Pointers); + } + case Type::PointerTyID: { + const PointerType *DstPT = cast(DstTy); + const PointerType *SrcPT = cast(SrcTy); + + if (DstPT->getAddressSpace() != SrcPT->getAddressSpace()) + return true; + + // If this is a pointer type, check to see if we have already seen it. If + // so, we are in a recursive branch. Cut off the search now. We cannot use + // an associative container for this search, because the type pointers (keys + // in the container) change whenever types get resolved. + if (SrcPT->isAbstract()) + if (const Type *ExistingDestTy = Pointers.lookup(SrcPT)) + return ExistingDestTy != DstPT; + + if (DstPT->isAbstract()) + if (const Type *ExistingSrcTy = Pointers.lookup(DstPT)) + return ExistingSrcTy != SrcPT; + // Otherwise, add the current pointers to the vector to stop recursion on + // this pair. + if (DstPT->isAbstract()) + Pointers.insert(DstPT, SrcPT); + if (SrcPT->isAbstract()) + Pointers.insert(SrcPT, DstPT); + + return RecursiveResolveTypesI(DstPT->getElementType(), + SrcPT->getElementType(), Pointers); + } + } +} + +static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy) { + LinkerTypeMap PointerTypes; + return RecursiveResolveTypesI(DestTy, SrcTy, PointerTypes); +} + + +// LinkTypes - Go through the symbol table of the Src module and see if any +// types are named in the src module that are not named in the Dst module. +// Make sure there are no type name conflicts. +static bool LinkTypes(Module *Dest, const Module *Src, std::string *Err) { + TypeSymbolTable *DestST = &Dest->getTypeSymbolTable(); + const TypeSymbolTable *SrcST = &Src->getTypeSymbolTable(); + + // Look for a type plane for Type's... + TypeSymbolTable::const_iterator TI = SrcST->begin(); + TypeSymbolTable::const_iterator TE = SrcST->end(); + if (TI == TE) return false; // No named types, do nothing. + + // Some types cannot be resolved immediately because they depend on other + // types being resolved to each other first. This contains a list of types we + // are waiting to recheck. + std::vector DelayedTypesToResolve; + + for ( ; TI != TE; ++TI ) { + const std::string &Name = TI->first; + const Type *RHS = TI->second; + + // Check to see if this type name is already in the dest module. + Type *Entry = DestST->lookup(Name); + + // If the name is just in the source module, bring it over to the dest. + if (Entry == 0) { + if (!Name.empty()) + DestST->insert(Name, const_cast(RHS)); + } else if (ResolveTypes(Entry, RHS)) { + // They look different, save the types 'till later to resolve. + DelayedTypesToResolve.push_back(Name); + } + } + + // Iteratively resolve types while we can... + while (!DelayedTypesToResolve.empty()) { + // Loop over all of the types, attempting to resolve them if possible... + unsigned OldSize = DelayedTypesToResolve.size(); + + // Try direct resolution by name... + for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + Type *T1 = SrcST->lookup(Name); + Type *T2 = DestST->lookup(Name); + if (!ResolveTypes(T2, T1)) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + --i; + } + } + + // Did we not eliminate any types? + if (DelayedTypesToResolve.size() == OldSize) { + // Attempt to resolve subelements of types. This allows us to merge these + // two types: { int* } and { opaque* } + for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { + const std::string &Name = DelayedTypesToResolve[i]; + if (!RecursiveResolveTypes(SrcST->lookup(Name), DestST->lookup(Name))) { + // We are making progress! + DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); + + // Go back to the main loop, perhaps we can resolve directly by name + // now... + break; + } + } + + // If we STILL cannot resolve the types, then there is something wrong. + if (DelayedTypesToResolve.size() == OldSize) { + // Remove the symbol name from the destination. + DelayedTypesToResolve.pop_back(); + } + } + } + + + return false; +} + +/// ForceRenaming - The LLVM SymbolTable class autorenames globals that conflict +/// in the symbol table. This is good for all clients except for us. Go +/// through the trouble to force this back. +static void ForceRenaming(GlobalValue *GV, const std::string &Name) { + assert(GV->getName() != Name && "Can't force rename to self"); + ValueSymbolTable &ST = GV->getParent()->getValueSymbolTable(); + + // If there is a conflict, rename the conflict. + if (GlobalValue *ConflictGV = cast_or_null(ST.lookup(Name))) { + assert(ConflictGV->hasLocalLinkage() && + "Not conflicting with a static global, should link instead!"); + GV->takeName(ConflictGV); + ConflictGV->setName(Name); // This will cause ConflictGV to get renamed + assert(ConflictGV->getName() != Name && "ForceRenaming didn't work"); + } else { + GV->setName(Name); // Force the name back + } +} + +/// CopyGVAttributes - copy additional attributes (those not needed to construct +/// a GlobalValue) from the SrcGV to the DestGV. +static void CopyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) { + // Use the maximum alignment, rather than just copying the alignment of SrcGV. + unsigned Alignment = std::max(DestGV->getAlignment(), SrcGV->getAlignment()); + DestGV->copyAttributesFrom(SrcGV); + DestGV->setAlignment(Alignment); +} + +/// GetLinkageResult - This analyzes the two global values and determines what +/// the result will look like in the destination module. In particular, it +/// computes the resultant linkage type, computes whether the global in the +/// source should be copied over to the destination (replacing the existing +/// one), and computes whether this linkage is an error or not. It also performs +/// visibility checks: we cannot link together two symbols with different +/// visibilities. +static bool GetLinkageResult(GlobalValue *Dest, const GlobalValue *Src, + GlobalValue::LinkageTypes <, bool &LinkFromSrc, + std::string *Err) { + assert((!Dest || !Src->hasLocalLinkage()) && + "If Src has internal linkage, Dest shouldn't be set!"); + if (!Dest) { + // Linking something to nothing. + LinkFromSrc = true; + LT = Src->getLinkage(); + } else if (Src->isDeclaration()) { + // If Src is external or if both Src & Dest are external.. Just link the + // external globals, we aren't adding anything. + if (Src->hasDLLImportLinkage()) { + // If one of GVs has DLLImport linkage, result should be dllimport'ed. + if (Dest->isDeclaration()) { + LinkFromSrc = true; + LT = Src->getLinkage(); + } + } else if (Dest->hasExternalWeakLinkage()) { + // If the Dest is weak, use the source linkage. + LinkFromSrc = true; + LT = Src->getLinkage(); + } else { + LinkFromSrc = false; + LT = Dest->getLinkage(); + } + } else if (Dest->isDeclaration() && !Dest->hasDLLImportLinkage()) { + // If Dest is external but Src is not: + LinkFromSrc = true; + LT = Src->getLinkage(); + } else if (Src->hasAppendingLinkage() || Dest->hasAppendingLinkage()) { + if (Src->getLinkage() != Dest->getLinkage()) + return Error(Err, "Linking globals named '" + Src->getName() + + "': can only link appending global with another appending global!"); + LinkFromSrc = true; // Special cased. + LT = Src->getLinkage(); + } else if (Src->isWeakForLinker()) { + // At this point we know that Dest has LinkOnce, External*, Weak, Common, + // or DLL* linkage. + if (Dest->hasExternalWeakLinkage() || + Dest->hasAvailableExternallyLinkage() || + (Dest->hasLinkOnceLinkage() && + (Src->hasWeakLinkage() || Src->hasCommonLinkage()))) { + LinkFromSrc = true; + LT = Src->getLinkage(); + } else { + LinkFromSrc = false; + LT = Dest->getLinkage(); + } + } else if (Dest->isWeakForLinker()) { + // At this point we know that Src has External* or DLL* linkage. + if (Src->hasExternalWeakLinkage()) { + LinkFromSrc = false; + LT = Dest->getLinkage(); + } else { + LinkFromSrc = true; + LT = GlobalValue::ExternalLinkage; + } + } else { + assert((Dest->hasExternalLinkage() || + Dest->hasDLLImportLinkage() || + Dest->hasDLLExportLinkage() || + Dest->hasExternalWeakLinkage()) && + (Src->hasExternalLinkage() || + Src->hasDLLImportLinkage() || + Src->hasDLLExportLinkage() || + Src->hasExternalWeakLinkage()) && + "Unexpected linkage type!"); + return Error(Err, "Linking globals named '" + Src->getName() + + "': symbol multiply defined!"); + } + + // Check visibility + if (Dest && Src->getVisibility() != Dest->getVisibility() && + !Src->isDeclaration() && !Dest->isDeclaration() && + !Src->hasAvailableExternallyLinkage() && + !Dest->hasAvailableExternallyLinkage()) + return Error(Err, "Linking globals named '" + Src->getName() + + "': symbols have different visibilities!"); + return false; +} + +// Insert all of the named mdnoes in Src into the Dest module. +static void LinkNamedMDNodes(Module *Dest, Module *Src, + ValueToValueMapTy &ValueMap) { + for (Module::const_named_metadata_iterator I = Src->named_metadata_begin(), + E = Src->named_metadata_end(); I != E; ++I) { + const NamedMDNode *SrcNMD = I; + NamedMDNode *DestNMD = Dest->getOrInsertNamedMetadata(SrcNMD->getName()); + // Add Src elements into Dest node. + for (unsigned i = 0, e = SrcNMD->getNumOperands(); i != e; ++i) + DestNMD->addOperand(cast(MapValue(SrcNMD->getOperand(i), + ValueMap))); + } +} + +// LinkGlobals - Loop through the global variables in the src module and merge +// them into the dest module. +static bool LinkGlobals(Module *Dest, const Module *Src, + ValueToValueMapTy &ValueMap, + std::multimap &AppendingVars, + std::string *Err) { + ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable(); + + // Loop over all of the globals in the src module, mapping them over as we go + for (Module::const_global_iterator I = Src->global_begin(), + E = Src->global_end(); I != E; ++I) { + const GlobalVariable *SGV = I; + GlobalValue *DGV = 0; + + // Check to see if may have to link the global with the global, alias or + // function. + if (SGV->hasName() && !SGV->hasLocalLinkage()) + DGV = cast_or_null(DestSymTab.lookup(SGV->getName())); + + // If we found a global with the same name in the dest module, but it has + // internal linkage, we are really not doing any linkage here. + if (DGV && DGV->hasLocalLinkage()) + DGV = 0; + + // If types don't agree due to opaque types, try to resolve them. + if (DGV && DGV->getType() != SGV->getType()) + RecursiveResolveTypes(SGV->getType(), DGV->getType()); + + assert((SGV->hasInitializer() || SGV->hasExternalWeakLinkage() || + SGV->hasExternalLinkage() || SGV->hasDLLImportLinkage()) && + "Global must either be external or have an initializer!"); + + GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage; + bool LinkFromSrc = false; + if (GetLinkageResult(DGV, SGV, NewLinkage, LinkFromSrc, Err)) + return true; + + if (DGV == 0) { + // No linking to be performed, simply create an identical version of the + // symbol over in the dest module... the initializer will be filled in + // later by LinkGlobalInits. + GlobalVariable *NewDGV = + new GlobalVariable(*Dest, SGV->getType()->getElementType(), + SGV->isConstant(), SGV->getLinkage(), /*init*/0, + SGV->getName(), 0, false, + SGV->getType()->getAddressSpace()); + // Propagate alignment, visibility and section info. + CopyGVAttributes(NewDGV, SGV); + + // If the LLVM runtime renamed the global, but it is an externally visible + // symbol, DGV must be an existing global with internal linkage. Rename + // it. + if (!NewDGV->hasLocalLinkage() && NewDGV->getName() != SGV->getName()) + ForceRenaming(NewDGV, SGV->getName()); + + // Make sure to remember this mapping. + ValueMap[SGV] = NewDGV; + + // Keep track that this is an appending variable. + if (SGV->hasAppendingLinkage()) + AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV)); + continue; + } + + bool HasUnnamedAddr = SGV->hasUnnamedAddr() && DGV->hasUnnamedAddr(); + + // If the visibilities of the symbols disagree and the destination is a + // prototype, take the visibility of its input. + if (DGV->isDeclaration()) + DGV->setVisibility(SGV->getVisibility()); + + if (DGV->hasAppendingLinkage()) { + // No linking is performed yet. Just insert a new copy of the global, and + // keep track of the fact that it is an appending variable in the + // AppendingVars map. The name is cleared out so that no linkage is + // performed. + GlobalVariable *NewDGV = + new GlobalVariable(*Dest, SGV->getType()->getElementType(), + SGV->isConstant(), SGV->getLinkage(), /*init*/0, + "", 0, false, + SGV->getType()->getAddressSpace()); + + // Set alignment allowing CopyGVAttributes merge it with alignment of SGV. + NewDGV->setAlignment(DGV->getAlignment()); + // Propagate alignment, section and visibility info. + CopyGVAttributes(NewDGV, SGV); + + // Make sure to remember this mapping... + ValueMap[SGV] = NewDGV; + + // Keep track that this is an appending variable... + AppendingVars.insert(std::make_pair(SGV->getName(), NewDGV)); + continue; + } + + if (LinkFromSrc) { + if (isa(DGV)) + return Error(Err, "Global-Alias Collision on '" + SGV->getName() + + "': symbol multiple defined"); + + // If the types don't match, and if we are to link from the source, nuke + // DGV and create a new one of the appropriate type. Note that the thing + // we are replacing may be a function (if a prototype, weak, etc) or a + // global variable. + GlobalVariable *NewDGV = + new GlobalVariable(*Dest, SGV->getType()->getElementType(), + SGV->isConstant(), NewLinkage, /*init*/0, + DGV->getName(), 0, false, + SGV->getType()->getAddressSpace()); + + // Set the unnamed_addr. + NewDGV->setUnnamedAddr(HasUnnamedAddr); + + // Propagate alignment, section, and visibility info. + CopyGVAttributes(NewDGV, SGV); + DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, + DGV->getType())); + + // DGV will conflict with NewDGV because they both had the same + // name. We must erase this now so ForceRenaming doesn't assert + // because DGV might not have internal linkage. + if (GlobalVariable *Var = dyn_cast(DGV)) + Var->eraseFromParent(); + else + cast(DGV)->eraseFromParent(); + + // If the symbol table renamed the global, but it is an externally visible + // symbol, DGV must be an existing global with internal linkage. Rename. + if (NewDGV->getName() != SGV->getName() && !NewDGV->hasLocalLinkage()) + ForceRenaming(NewDGV, SGV->getName()); + + // Inherit const as appropriate. + NewDGV->setConstant(SGV->isConstant()); + + // Make sure to remember this mapping. + ValueMap[SGV] = NewDGV; + continue; + } + + // Not "link from source", keep the one in the DestModule and remap the + // input onto it. + + // Special case for const propagation. + if (GlobalVariable *DGVar = dyn_cast(DGV)) + if (DGVar->isDeclaration() && SGV->isConstant() && !DGVar->isConstant()) + DGVar->setConstant(true); + + // SGV is global, but DGV is alias. + if (isa(DGV)) { + // The only valid mappings are: + // - SGV is external declaration, which is effectively a no-op. + // - SGV is weak, when we just need to throw SGV out. + if (!SGV->isDeclaration() && !SGV->isWeakForLinker()) + return Error(Err, "Global-Alias Collision on '" + SGV->getName() + + "': symbol multiple defined"); + } + + // Set calculated linkage and unnamed_addr + DGV->setLinkage(NewLinkage); + DGV->setUnnamedAddr(HasUnnamedAddr); + + // Make sure to remember this mapping... + ValueMap[SGV] = ConstantExpr::getBitCast(DGV, SGV->getType()); + } + return false; +} + +static GlobalValue::LinkageTypes +CalculateAliasLinkage(const GlobalValue *SGV, const GlobalValue *DGV) { + GlobalValue::LinkageTypes SL = SGV->getLinkage(); + GlobalValue::LinkageTypes DL = DGV->getLinkage(); + if (SL == GlobalValue::ExternalLinkage || DL == GlobalValue::ExternalLinkage) + return GlobalValue::ExternalLinkage; + else if (SL == GlobalValue::WeakAnyLinkage || + DL == GlobalValue::WeakAnyLinkage) + return GlobalValue::WeakAnyLinkage; + else if (SL == GlobalValue::WeakODRLinkage || + DL == GlobalValue::WeakODRLinkage) + return GlobalValue::WeakODRLinkage; + else if (SL == GlobalValue::InternalLinkage && + DL == GlobalValue::InternalLinkage) + return GlobalValue::InternalLinkage; + else if (SL == GlobalValue::LinkerPrivateLinkage && + DL == GlobalValue::LinkerPrivateLinkage) + return GlobalValue::LinkerPrivateLinkage; + else if (SL == GlobalValue::LinkerPrivateWeakLinkage && + DL == GlobalValue::LinkerPrivateWeakLinkage) + return GlobalValue::LinkerPrivateWeakLinkage; + else if (SL == GlobalValue::LinkerPrivateWeakDefAutoLinkage && + DL == GlobalValue::LinkerPrivateWeakDefAutoLinkage) + return GlobalValue::LinkerPrivateWeakDefAutoLinkage; + else { + assert (SL == GlobalValue::PrivateLinkage && + DL == GlobalValue::PrivateLinkage && "Unexpected linkage type"); + return GlobalValue::PrivateLinkage; + } +} + +// LinkAlias - Loop through the alias in the src module and link them into the +// dest module. We're assuming, that all functions/global variables were already +// linked in. +static bool LinkAlias(Module *Dest, const Module *Src, + ValueToValueMapTy &ValueMap, + std::string *Err) { + // Loop over all alias in the src module + for (Module::const_alias_iterator I = Src->alias_begin(), + E = Src->alias_end(); I != E; ++I) { + const GlobalAlias *SGA = I; + const GlobalValue *SAliasee = SGA->getAliasedGlobal(); + GlobalAlias *NewGA = NULL; + + // Globals were already linked, thus we can just query ValueMap for variant + // of SAliasee in Dest. + ValueToValueMapTy::const_iterator VMI = ValueMap.find(SAliasee); + assert(VMI != ValueMap.end() && "Aliasee not linked"); + GlobalValue* DAliasee = cast(VMI->second); + GlobalValue* DGV = NULL; + + // Fixup aliases to bitcasts. Note that aliases to GEPs are still broken + // by this, but aliases to GEPs are broken to a lot of other things, so + // it's less important. + Constant *DAliaseeConst = DAliasee; + if (SGA->getType() != DAliasee->getType()) + DAliaseeConst = ConstantExpr::getBitCast(DAliasee, SGA->getType()); + + // Try to find something 'similar' to SGA in destination module. + if (!DGV && !SGA->hasLocalLinkage()) { + DGV = Dest->getNamedAlias(SGA->getName()); + + // If types don't agree due to opaque types, try to resolve them. + if (DGV && DGV->getType() != SGA->getType()) + RecursiveResolveTypes(SGA->getType(), DGV->getType()); + } + + if (!DGV && !SGA->hasLocalLinkage()) { + DGV = Dest->getGlobalVariable(SGA->getName()); + + // If types don't agree due to opaque types, try to resolve them. + if (DGV && DGV->getType() != SGA->getType()) + RecursiveResolveTypes(SGA->getType(), DGV->getType()); + } + + if (!DGV && !SGA->hasLocalLinkage()) { + DGV = Dest->getFunction(SGA->getName()); + + // If types don't agree due to opaque types, try to resolve them. + if (DGV && DGV->getType() != SGA->getType()) + RecursiveResolveTypes(SGA->getType(), DGV->getType()); + } + + // No linking to be performed on internal stuff. + if (DGV && DGV->hasLocalLinkage()) + DGV = NULL; + + if (GlobalAlias *DGA = dyn_cast_or_null(DGV)) { + // Types are known to be the same, check whether aliasees equal. As + // globals are already linked we just need query ValueMap to find the + // mapping. + if (DAliasee == DGA->getAliasedGlobal()) { + // This is just two copies of the same alias. Propagate linkage, if + // necessary. + DGA->setLinkage(CalculateAliasLinkage(SGA, DGA)); + + NewGA = DGA; + // Proceed to 'common' steps + } else + return Error(Err, "Alias Collision on '" + SGA->getName()+ + "': aliases have different aliasees"); + } else if (GlobalVariable *DGVar = dyn_cast_or_null(DGV)) { + // The only allowed way is to link alias with external declaration or weak + // symbol.. + if (DGVar->isDeclaration() || DGVar->isWeakForLinker()) { + // But only if aliasee is global too... + if (!isa(DAliasee)) + return Error(Err, "Global-Alias Collision on '" + SGA->getName() + + "': aliasee is not global variable"); + + NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(), + SGA->getName(), DAliaseeConst, Dest); + CopyGVAttributes(NewGA, SGA); + + // Any uses of DGV need to change to NewGA, with cast, if needed. + if (SGA->getType() != DGVar->getType()) + DGVar->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA, + DGVar->getType())); + else + DGVar->replaceAllUsesWith(NewGA); + + // DGVar will conflict with NewGA because they both had the same + // name. We must erase this now so ForceRenaming doesn't assert + // because DGV might not have internal linkage. + DGVar->eraseFromParent(); + + // Proceed to 'common' steps + } else + return Error(Err, "Global-Alias Collision on '" + SGA->getName() + + "': symbol multiple defined"); + } else if (Function *DF = dyn_cast_or_null(DGV)) { + // The only allowed way is to link alias with external declaration or weak + // symbol... + if (DF->isDeclaration() || DF->isWeakForLinker()) { + // But only if aliasee is function too... + if (!isa(DAliasee)) + return Error(Err, "Function-Alias Collision on '" + SGA->getName() + + "': aliasee is not function"); + + NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(), + SGA->getName(), DAliaseeConst, Dest); + CopyGVAttributes(NewGA, SGA); + + // Any uses of DF need to change to NewGA, with cast, if needed. + if (SGA->getType() != DF->getType()) + DF->replaceAllUsesWith(ConstantExpr::getBitCast(NewGA, + DF->getType())); + else + DF->replaceAllUsesWith(NewGA); + + // DF will conflict with NewGA because they both had the same + // name. We must erase this now so ForceRenaming doesn't assert + // because DF might not have internal linkage. + DF->eraseFromParent(); + + // Proceed to 'common' steps + } else + return Error(Err, "Function-Alias Collision on '" + SGA->getName() + + "': symbol multiple defined"); + } else { + // No linking to be performed, simply create an identical version of the + // alias over in the dest module... + NewGA = new GlobalAlias(SGA->getType(), SGA->getLinkage(), + SGA->getName(), DAliaseeConst, Dest); + CopyGVAttributes(NewGA, SGA); + + // Proceed to 'common' steps + } + + assert(NewGA && "No alias was created in destination module!"); + + // If the symbol table renamed the alias, but it is an externally visible + // symbol, DGA must be an global value with internal linkage. Rename it. + if (NewGA->getName() != SGA->getName() && + !NewGA->hasLocalLinkage()) + ForceRenaming(NewGA, SGA->getName()); + + // Remember this mapping so uses in the source module get remapped + // later by MapValue. + ValueMap[SGA] = NewGA; + } + + return false; +} + + +// LinkGlobalInits - Update the initializers in the Dest module now that all +// globals that may be referenced are in Dest. +static bool LinkGlobalInits(Module *Dest, const Module *Src, + ValueToValueMapTy &ValueMap, + std::string *Err) { + // Loop over all of the globals in the src module, mapping them over as we go + for (Module::const_global_iterator I = Src->global_begin(), + E = Src->global_end(); I != E; ++I) { + const GlobalVariable *SGV = I; + + if (SGV->hasInitializer()) { // Only process initialized GV's + // Figure out what the initializer looks like in the dest module. + Constant *SInit = + cast(MapValue(SGV->getInitializer(), ValueMap)); + // Grab destination global variable or alias. + GlobalValue *DGV = cast(ValueMap[SGV]->stripPointerCasts()); + + // If dest if global variable, check that initializers match. + if (GlobalVariable *DGVar = dyn_cast(DGV)) { + if (DGVar->hasInitializer()) { + if (SGV->hasExternalLinkage()) { + if (DGVar->getInitializer() != SInit) + return Error(Err, "Global Variable Collision on '" + + SGV->getName() + + "': global variables have different initializers"); + } else if (DGVar->isWeakForLinker()) { + // Nothing is required, mapped values will take the new global + // automatically. + } else if (SGV->isWeakForLinker()) { + // Nothing is required, mapped values will take the new global + // automatically. + } else if (DGVar->hasAppendingLinkage()) { + llvm_unreachable("Appending linkage unimplemented!"); + } else { + llvm_unreachable("Unknown linkage!"); + } + } else { + // Copy the initializer over now... + DGVar->setInitializer(SInit); + } + } else { + // Destination is alias, the only valid situation is when source is + // weak. Also, note, that we already checked linkage in LinkGlobals(), + // thus we assert here. + // FIXME: Should we weaken this assumption, 'dereference' alias and + // check for initializer of aliasee? + assert(SGV->isWeakForLinker()); + } + } + } + return false; +} + +// LinkFunctionProtos - Link the functions together between the two modules, +// without doing function bodies... this just adds external function prototypes +// to the Dest function... +// +static bool LinkFunctionProtos(Module *Dest, const Module *Src, + ValueToValueMapTy &ValueMap, + std::string *Err) { + ValueSymbolTable &DestSymTab = Dest->getValueSymbolTable(); + + // Loop over all of the functions in the src module, mapping them over + for (Module::const_iterator I = Src->begin(), E = Src->end(); I != E; ++I) { + const Function *SF = I; // SrcFunction + GlobalValue *DGV = 0; + + // Check to see if may have to link the function with the global, alias or + // function. + if (SF->hasName() && !SF->hasLocalLinkage()) + DGV = cast_or_null(DestSymTab.lookup(SF->getName())); + + // If we found a global with the same name in the dest module, but it has + // internal linkage, we are really not doing any linkage here. + if (DGV && DGV->hasLocalLinkage()) + DGV = 0; + + // If types don't agree due to opaque types, try to resolve them. + if (DGV && DGV->getType() != SF->getType()) + RecursiveResolveTypes(SF->getType(), DGV->getType()); + + GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage; + bool LinkFromSrc = false; + if (GetLinkageResult(DGV, SF, NewLinkage, LinkFromSrc, Err)) + return true; + + // If there is no linkage to be performed, just bring over SF without + // modifying it. + if (DGV == 0) { + // Function does not already exist, simply insert an function signature + // identical to SF into the dest module. + Function *NewDF = Function::Create(SF->getFunctionType(), + SF->getLinkage(), + SF->getName(), Dest); + CopyGVAttributes(NewDF, SF); + + // If the LLVM runtime renamed the function, but it is an externally + // visible symbol, DF must be an existing function with internal linkage. + // Rename it. + if (!NewDF->hasLocalLinkage() && NewDF->getName() != SF->getName()) + ForceRenaming(NewDF, SF->getName()); + + // ... and remember this mapping... + ValueMap[SF] = NewDF; + continue; + } + + // If the visibilities of the symbols disagree and the destination is a + // prototype, take the visibility of its input. + if (DGV->isDeclaration()) + DGV->setVisibility(SF->getVisibility()); + + if (LinkFromSrc) { + if (isa(DGV)) + return Error(Err, "Function-Alias Collision on '" + SF->getName() + + "': symbol multiple defined"); + + // We have a definition of the same name but different type in the + // source module. Copy the prototype to the destination and replace + // uses of the destination's prototype with the new prototype. + Function *NewDF = Function::Create(SF->getFunctionType(), NewLinkage, + SF->getName(), Dest); + CopyGVAttributes(NewDF, SF); + + // Any uses of DF need to change to NewDF, with cast + DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDF, + DGV->getType())); + + // DF will conflict with NewDF because they both had the same. We must + // erase this now so ForceRenaming doesn't assert because DF might + // not have internal linkage. + if (GlobalVariable *Var = dyn_cast(DGV)) + Var->eraseFromParent(); + else + cast(DGV)->eraseFromParent(); + + // If the symbol table renamed the function, but it is an externally + // visible symbol, DF must be an existing function with internal + // linkage. Rename it. + if (NewDF->getName() != SF->getName() && !NewDF->hasLocalLinkage()) + ForceRenaming(NewDF, SF->getName()); + + // Remember this mapping so uses in the source module get remapped + // later by MapValue. + ValueMap[SF] = NewDF; + continue; + } + + // Not "link from source", keep the one in the DestModule and remap the + // input onto it. + + if (isa(DGV)) { + // The only valid mappings are: + // - SF is external declaration, which is effectively a no-op. + // - SF is weak, when we just need to throw SF out. + if (!SF->isDeclaration() && !SF->isWeakForLinker()) + return Error(Err, "Function-Alias Collision on '" + SF->getName() + + "': symbol multiple defined"); + } + + // Set calculated linkage + DGV->setLinkage(NewLinkage); + + // Make sure to remember this mapping. + ValueMap[SF] = ConstantExpr::getBitCast(DGV, SF->getType()); + } + return false; +} + +// LinkFunctionBody - Copy the source function over into the dest function and +// fix up references to values. At this point we know that Dest is an external +// function, and that Src is not. +static bool LinkFunctionBody(Function *Dest, Function *Src, + ValueToValueMapTy &ValueMap, + std::string *Err) { + assert(Src && Dest && Dest->isDeclaration() && !Src->isDeclaration()); + + // Go through and convert function arguments over, remembering the mapping. + Function::arg_iterator DI = Dest->arg_begin(); + for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); + I != E; ++I, ++DI) { + DI->setName(I->getName()); // Copy the name information over... + + // Add a mapping to our local map + ValueMap[I] = DI; + } + + // Splice the body of the source function into the dest function. + Dest->getBasicBlockList().splice(Dest->end(), Src->getBasicBlockList()); + + // At this point, all of the instructions and values of the function are now + // copied over. The only problem is that they are still referencing values in + // the Source function as operands. Loop through all of the operands of the + // functions and patch them up to point to the local versions. + for (Function::iterator BB = Dest->begin(), BE = Dest->end(); BB != BE; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries); + + // There is no need to map the arguments anymore. + for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); + I != E; ++I) + ValueMap.erase(I); + + return false; +} + + +// LinkFunctionBodies - Link in the function bodies that are defined in the +// source module into the DestModule. This consists basically of copying the +// function over and fixing up references to values. +static bool LinkFunctionBodies(Module *Dest, Module *Src, + ValueToValueMapTy &ValueMap, + std::string *Err) { + + // Loop over all of the functions in the src module, mapping them over as we + // go + for (Module::iterator SF = Src->begin(), E = Src->end(); SF != E; ++SF) { + if (!SF->isDeclaration()) { // No body if function is external + Function *DF = dyn_cast(ValueMap[SF]); // Destination function + + // DF not external SF external? + if (DF && DF->isDeclaration()) + // Only provide the function body if there isn't one already. + if (LinkFunctionBody(DF, SF, ValueMap, Err)) + return true; + } + } + return false; +} + +// LinkAppendingVars - If there were any appending global variables, link them +// together now. Return true on error. +static bool LinkAppendingVars(Module *M, + std::multimap &AppendingVars, + std::string *ErrorMsg) { + if (AppendingVars.empty()) return false; // Nothing to do. + + // Loop over the multimap of appending vars, processing any variables with the + // same name, forming a new appending global variable with both of the + // initializers merged together, then rewrite references to the old variables + // and delete them. + std::vector Inits; + while (AppendingVars.size() > 1) { + // Get the first two elements in the map... + std::multimap::iterator Second = AppendingVars.begin(), First=Second++; + + // If the first two elements are for different names, there is no pair... + // Otherwise there is a pair, so link them together... + if (First->first == Second->first) { + GlobalVariable *G1 = First->second, *G2 = Second->second; + const ArrayType *T1 = cast(G1->getType()->getElementType()); + const ArrayType *T2 = cast(G2->getType()->getElementType()); + + // Check to see that they two arrays agree on type... + if (T1->getElementType() != T2->getElementType()) + return Error(ErrorMsg, + "Appending variables with different element types need to be linked!"); + if (G1->isConstant() != G2->isConstant()) + return Error(ErrorMsg, + "Appending variables linked with different const'ness!"); + + if (G1->getAlignment() != G2->getAlignment()) + return Error(ErrorMsg, + "Appending variables with different alignment need to be linked!"); + + if (G1->getVisibility() != G2->getVisibility()) + return Error(ErrorMsg, + "Appending variables with different visibility need to be linked!"); + + if (G1->getSection() != G2->getSection()) + return Error(ErrorMsg, + "Appending variables with different section name need to be linked!"); + + unsigned NewSize = T1->getNumElements() + T2->getNumElements(); + ArrayType *NewType = ArrayType::get(T1->getElementType(), + NewSize); + + G1->setName(""); // Clear G1's name in case of a conflict! + + // Create the new global variable... + GlobalVariable *NG = + new GlobalVariable(*M, NewType, G1->isConstant(), G1->getLinkage(), + /*init*/0, First->first, 0, G1->isThreadLocal(), + G1->getType()->getAddressSpace()); + + // Propagate alignment, visibility and section info. + CopyGVAttributes(NG, G1); + + // Merge the initializer... + Inits.reserve(NewSize); + if (ConstantArray *I = dyn_cast(G1->getInitializer())) { + for (unsigned i = 0, e = T1->getNumElements(); i != e; ++i) + Inits.push_back(I->getOperand(i)); + } else { + assert(isa(G1->getInitializer())); + Constant *CV = Constant::getNullValue(T1->getElementType()); + for (unsigned i = 0, e = T1->getNumElements(); i != e; ++i) + Inits.push_back(CV); + } + if (ConstantArray *I = dyn_cast(G2->getInitializer())) { + for (unsigned i = 0, e = T2->getNumElements(); i != e; ++i) + Inits.push_back(I->getOperand(i)); + } else { + assert(isa(G2->getInitializer())); + Constant *CV = Constant::getNullValue(T2->getElementType()); + for (unsigned i = 0, e = T2->getNumElements(); i != e; ++i) + Inits.push_back(CV); + } + NG->setInitializer(ConstantArray::get(NewType, Inits)); + Inits.clear(); + + // Replace any uses of the two global variables with uses of the new + // global... + + // FIXME: This should rewrite simple/straight-forward uses such as + // getelementptr instructions to not use the Cast! + G1->replaceAllUsesWith(ConstantExpr::getBitCast(NG, + G1->getType())); + G2->replaceAllUsesWith(ConstantExpr::getBitCast(NG, + G2->getType())); + + // Remove the two globals from the module now... + M->getGlobalList().erase(G1); + M->getGlobalList().erase(G2); + + // Put the new global into the AppendingVars map so that we can handle + // linking of more than two vars... + Second->second = NG; + } + AppendingVars.erase(First); + } + + return false; +} + +static bool ResolveAliases(Module *Dest) { + for (Module::alias_iterator I = Dest->alias_begin(), E = Dest->alias_end(); + I != E; ++I) + // We can't sue resolveGlobalAlias here because we need to preserve + // bitcasts and GEPs. + if (const Constant *C = I->getAliasee()) { + while (dyn_cast(C)) + C = cast(C)->getAliasee(); + const GlobalValue *GV = dyn_cast(C); + if (C != I && !(GV && GV->isDeclaration())) + I->replaceAllUsesWith(const_cast(C)); + } + + return false; +} + +// LinkModules - This function links two modules together, with the resulting +// left module modified to be the composite of the two input modules. If an +// error occurs, true is returned and ErrorMsg (if not null) is set to indicate +// the problem. Upon failure, the Dest module could be in a modified state, and +// shouldn't be relied on to be consistent. +bool +Linker::LinkModules(Module *Dest, Module *Src, std::string *ErrorMsg) { + assert(Dest != 0 && "Invalid Destination module"); + assert(Src != 0 && "Invalid Source Module"); + + if (Dest->getDataLayout().empty()) { + if (!Src->getDataLayout().empty()) { + Dest->setDataLayout(Src->getDataLayout()); + } else { + std::string DataLayout; + + if (Dest->getEndianness() == Module::AnyEndianness) { + if (Src->getEndianness() == Module::BigEndian) + DataLayout.append("E"); + else if (Src->getEndianness() == Module::LittleEndian) + DataLayout.append("e"); + } + + if (Dest->getPointerSize() == Module::AnyPointerSize) { + if (Src->getPointerSize() == Module::Pointer64) + DataLayout.append(DataLayout.length() == 0 ? "p:64:64" : "-p:64:64"); + else if (Src->getPointerSize() == Module::Pointer32) + DataLayout.append(DataLayout.length() == 0 ? "p:32:32" : "-p:32:32"); + } + Dest->setDataLayout(DataLayout); + } + } + + // Copy the target triple from the source to dest if the dest's is empty. + if (Dest->getTargetTriple().empty() && !Src->getTargetTriple().empty()) + Dest->setTargetTriple(Src->getTargetTriple()); + + if (!Src->getDataLayout().empty() && !Dest->getDataLayout().empty() && + Src->getDataLayout() != Dest->getDataLayout()) + errs() << "WARNING: Linking two modules of different data layouts!\n"; + if (!Src->getTargetTriple().empty() && + Dest->getTargetTriple() != Src->getTargetTriple()) { + errs() << "WARNING: Linking two modules of different target triples: "; + if (!Src->getModuleIdentifier().empty()) + errs() << Src->getModuleIdentifier() << ": "; + errs() << "'" << Src->getTargetTriple() << "' and '" + << Dest->getTargetTriple() << "'\n"; + } + + // Append the module inline asm string. + if (!Src->getModuleInlineAsm().empty()) { + if (Dest->getModuleInlineAsm().empty()) + Dest->setModuleInlineAsm(Src->getModuleInlineAsm()); + else + Dest->setModuleInlineAsm(Dest->getModuleInlineAsm()+"\n"+ + Src->getModuleInlineAsm()); + } + + // Update the destination module's dependent libraries list with the libraries + // from the source module. There's no opportunity for duplicates here as the + // Module ensures that duplicate insertions are discarded. + for (Module::lib_iterator SI = Src->lib_begin(), SE = Src->lib_end(); + SI != SE; ++SI) + Dest->addLibrary(*SI); + + // LinkTypes - Go through the symbol table of the Src module and see if any + // types are named in the src module that are not named in the Dst module. + // Make sure there are no type name conflicts. + if (LinkTypes(Dest, Src, ErrorMsg)) + return true; + + // ValueMap - Mapping of values from what they used to be in Src, to what they + // are now in Dest. ValueToValueMapTy is a ValueMap, which involves some + // overhead due to the use of Value handles which the Linker doesn't actually + // need, but this allows us to reuse the ValueMapper code. + ValueToValueMapTy ValueMap; + + // AppendingVars - Keep track of global variables in the destination module + // with appending linkage. After the module is linked together, they are + // appended and the module is rewritten. + std::multimap AppendingVars; + for (Module::global_iterator I = Dest->global_begin(), E = Dest->global_end(); + I != E; ++I) { + // Add all of the appending globals already in the Dest module to + // AppendingVars. + if (I->hasAppendingLinkage()) + AppendingVars.insert(std::make_pair(I->getName(), I)); + } + + // Insert all of the globals in src into the Dest module... without linking + // initializers (which could refer to functions not yet mapped over). + if (LinkGlobals(Dest, Src, ValueMap, AppendingVars, ErrorMsg)) + return true; + + // Link the functions together between the two modules, without doing function + // bodies... this just adds external function prototypes to the Dest + // function... We do this so that when we begin processing function bodies, + // all of the global values that may be referenced are available in our + // ValueMap. + if (LinkFunctionProtos(Dest, Src, ValueMap, ErrorMsg)) + return true; + + // If there were any alias, link them now. We really need to do this now, + // because all of the aliases that may be referenced need to be available in + // ValueMap + if (LinkAlias(Dest, Src, ValueMap, ErrorMsg)) return true; + + // Update the initializers in the Dest module now that all globals that may + // be referenced are in Dest. + if (LinkGlobalInits(Dest, Src, ValueMap, ErrorMsg)) return true; + + // Link in the function bodies that are defined in the source module into the + // DestModule. This consists basically of copying the function over and + // fixing up references to values. + if (LinkFunctionBodies(Dest, Src, ValueMap, ErrorMsg)) return true; + + // If there were any appending global variables, link them together now. + if (LinkAppendingVars(Dest, AppendingVars, ErrorMsg)) return true; + + // Resolve all uses of aliases with aliasees + if (ResolveAliases(Dest)) return true; + + // Remap all of the named mdnoes in Src into the Dest module. We do this + // after linking GlobalValues so that MDNodes that reference GlobalValues + // are properly remapped. + LinkNamedMDNodes(Dest, Src, ValueMap); + + // If the source library's module id is in the dependent library list of the + // destination library, remove it since that module is now linked in. + const std::string &modId = Src->getModuleIdentifier(); + if (!modId.empty()) + Dest->removeLibrary(sys::path::stem(modId)); + + return false; +} + +// vim: sw=2 diff --git a/final/lib/Linker/Linker.cpp b/final/lib/Linker/Linker.cpp new file mode 100644 index 00000000000..fba91da5ddd --- /dev/null +++ b/final/lib/Linker/Linker.cpp @@ -0,0 +1,174 @@ +//===- lib/Linker/Linker.cpp - Basic Linker functionality ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains basic Linker functionality that all usages will need. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Linker.h" +#include "llvm/Module.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Config/config.h" +#include "llvm/Support/system_error.h" +using namespace llvm; + +Linker::Linker(StringRef progname, StringRef modname, + LLVMContext& C, unsigned flags): + Context(C), + Composite(new Module(modname, C)), + LibPaths(), + Flags(flags), + Error(), + ProgramName(progname) { } + +Linker::Linker(StringRef progname, Module* aModule, unsigned flags) : + Context(aModule->getContext()), + Composite(aModule), + LibPaths(), + Flags(flags), + Error(), + ProgramName(progname) { } + +Linker::~Linker() { + delete Composite; +} + +bool +Linker::error(StringRef message) { + Error = message; + if (!(Flags&QuietErrors)) + errs() << ProgramName << ": error: " << message << "\n"; + return true; +} + +bool +Linker::warning(StringRef message) { + Error = message; + if (!(Flags&QuietWarnings)) + errs() << ProgramName << ": warning: " << message << "\n"; + return false; +} + +void +Linker::verbose(StringRef message) { + if (Flags&Verbose) + errs() << " " << message << "\n"; +} + +void +Linker::addPath(const sys::Path& path) { + LibPaths.push_back(path); +} + +void +Linker::addPaths(const std::vector& paths) { + for (unsigned i = 0, e = paths.size(); i != e; ++i) + LibPaths.push_back(sys::Path(paths[i])); +} + +void +Linker::addSystemPaths() { + sys::Path::GetBitcodeLibraryPaths(LibPaths); + LibPaths.insert(LibPaths.begin(),sys::Path("./")); +} + +Module* +Linker::releaseModule() { + Module* result = Composite; + LibPaths.clear(); + Error.clear(); + Composite = 0; + Flags = 0; + return result; +} + +// LoadObject - Read in and parse the bitcode file named by FN and return the +// module it contains (wrapped in an auto_ptr), or auto_ptr() and set +// Error if an error occurs. +std::auto_ptr +Linker::LoadObject(const sys::Path &FN) { + std::string ParseErrorMessage; + Module *Result = 0; + + OwningPtr Buffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(FN.c_str(), Buffer)) + ParseErrorMessage = "Error reading file '" + FN.str() + "'" + ": " + + ec.message(); + else + Result = ParseBitcodeFile(Buffer.get(), Context, &ParseErrorMessage); + + if (Result) + return std::auto_ptr(Result); + Error = "Bitcode file '" + FN.str() + "' could not be loaded"; + if (ParseErrorMessage.size()) + Error += ": " + ParseErrorMessage; + return std::auto_ptr(); +} + +// IsLibrary - Determine if "Name" is a library in "Directory". Return +// a non-empty sys::Path if its found, an empty one otherwise. +static inline sys::Path IsLibrary(StringRef Name, + const sys::Path &Directory) { + + sys::Path FullPath(Directory); + + // Try the libX.a form + FullPath.appendComponent(("lib" + Name).str()); + FullPath.appendSuffix("a"); + if (FullPath.isArchive()) + return FullPath; + + // Try the libX.bca form + FullPath.eraseSuffix(); + FullPath.appendSuffix("bca"); + if (FullPath.isArchive()) + return FullPath; + + // Try the libX.so (or .dylib) form + FullPath.eraseSuffix(); + FullPath.appendSuffix(sys::Path::GetDLLSuffix()); + if (FullPath.isDynamicLibrary()) // Native shared library? + return FullPath; + if (FullPath.isBitcodeFile()) // .so file containing bitcode? + return FullPath; + + // Not found .. fall through + + // Indicate that the library was not found in the directory. + FullPath.clear(); + return FullPath; +} + +/// FindLib - Try to convert Filename into the name of a file that we can open, +/// if it does not already name a file we can open, by first trying to open +/// Filename, then libFilename.[suffix] for each of a set of several common +/// library suffixes, in each of the directories in LibPaths. Returns an empty +/// Path if no matching file can be found. +/// +sys::Path +Linker::FindLib(StringRef Filename) { + // Determine if the pathname can be found as it stands. + sys::Path FilePath(Filename); + if (FilePath.canRead() && + (FilePath.isArchive() || FilePath.isDynamicLibrary())) + return FilePath; + + // Iterate over the directories in Paths to see if we can find the library + // there. + for (unsigned Index = 0; Index != LibPaths.size(); ++Index) { + sys::Path Directory(LibPaths[Index]); + sys::Path FullPath = IsLibrary(Filename, Directory); + if (!FullPath.isEmpty()) + return FullPath; + } + return sys::Path(); +} diff --git a/final/lib/Linker/Makefile b/final/lib/Linker/Makefile new file mode 100644 index 00000000000..19e646b7483 --- /dev/null +++ b/final/lib/Linker/Makefile @@ -0,0 +1,15 @@ +##===- lib/Linker/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMLinker +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/MC/CMakeLists.txt b/final/lib/MC/CMakeLists.txt new file mode 100644 index 00000000000..6aed059f0f4 --- /dev/null +++ b/final/lib/MC/CMakeLists.txt @@ -0,0 +1,40 @@ +add_llvm_library(LLVMMC + ELFObjectWriter.cpp + MCAsmInfo.cpp + MCAsmInfoCOFF.cpp + MCAsmInfoDarwin.cpp + MCAsmStreamer.cpp + MCAssembler.cpp + MCCodeEmitter.cpp + MCContext.cpp + MCDisassembler.cpp + MCELF.cpp + MCELFObjectTargetWriter.cpp + MCELFStreamer.cpp + MCExpr.cpp + MCInst.cpp + MCInstPrinter.cpp + MCLabel.cpp + MCDwarf.cpp + MCLoggingStreamer.cpp + MCMachOStreamer.cpp + MCMachObjectTargetWriter.cpp + MCNullStreamer.cpp + MCObjectStreamer.cpp + MCObjectWriter.cpp + MCPureStreamer.cpp + MCSection.cpp + MCSectionCOFF.cpp + MCSectionELF.cpp + MCSectionMachO.cpp + MCStreamer.cpp + MCSymbol.cpp + MCValue.cpp + MachObjectWriter.cpp + WinCOFFStreamer.cpp + WinCOFFObjectWriter.cpp + TargetAsmBackend.cpp + ) + +add_subdirectory(MCParser) +add_subdirectory(MCDisassembler) diff --git a/final/lib/MC/ELFObjectWriter.cpp b/final/lib/MC/ELFObjectWriter.cpp new file mode 100644 index 00000000000..3492cbc55d6 --- /dev/null +++ b/final/lib/MC/ELFObjectWriter.cpp @@ -0,0 +1,1494 @@ +//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF object file writer information. +// +//===----------------------------------------------------------------------===// + +#include "ELFObjectWriter.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ELF.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/ADT/StringSwitch.h" + +#include "../Target/X86/X86FixupKinds.h" +#include "../Target/ARM/ARMFixupKinds.h" + +#include +using namespace llvm; + +bool ELFObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = + Asm.getBackend().getFixupKindInfo((MCFixupKind) Kind); + + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; +} + +bool ELFObjectWriter::RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant) { + switch (Variant) { + default: + return false; + case MCSymbolRefExpr::VK_GOT: + case MCSymbolRefExpr::VK_PLT: + case MCSymbolRefExpr::VK_GOTPCREL: + case MCSymbolRefExpr::VK_TPOFF: + case MCSymbolRefExpr::VK_TLSGD: + case MCSymbolRefExpr::VK_GOTTPOFF: + case MCSymbolRefExpr::VK_INDNTPOFF: + case MCSymbolRefExpr::VK_NTPOFF: + case MCSymbolRefExpr::VK_GOTNTPOFF: + case MCSymbolRefExpr::VK_TLSLDM: + case MCSymbolRefExpr::VK_DTPOFF: + case MCSymbolRefExpr::VK_TLSLD: + return true; + } +} + +ELFObjectWriter::~ELFObjectWriter() +{} + +// Emit the ELF header. +void ELFObjectWriter::WriteHeader(uint64_t SectionDataSize, + unsigned NumberOfSections) { + // ELF Header + // ---------- + // + // Note + // ---- + // emitWord method behaves differently for ELF32 and ELF64, writing + // 4 bytes in the former and 8 in the latter. + + Write8(0x7f); // e_ident[EI_MAG0] + Write8('E'); // e_ident[EI_MAG1] + Write8('L'); // e_ident[EI_MAG2] + Write8('F'); // e_ident[EI_MAG3] + + Write8(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS] + + // e_ident[EI_DATA] + Write8(isLittleEndian() ? ELF::ELFDATA2LSB : ELF::ELFDATA2MSB); + + Write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] + // e_ident[EI_OSABI] + switch (TargetObjectWriter->getOSType()) { + case Triple::FreeBSD: Write8(ELF::ELFOSABI_FREEBSD); break; + case Triple::Linux: Write8(ELF::ELFOSABI_LINUX); break; + default: Write8(ELF::ELFOSABI_NONE); break; + } + Write8(0); // e_ident[EI_ABIVERSION] + + WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD); + + Write16(ELF::ET_REL); // e_type + + Write16(TargetObjectWriter->getEMachine()); // e_machine = target + + Write32(ELF::EV_CURRENT); // e_version + WriteWord(0); // e_entry, no entry point in .o file + WriteWord(0); // e_phoff, no program header for .o + WriteWord(SectionDataSize + (is64Bit() ? sizeof(ELF::Elf64_Ehdr) : + sizeof(ELF::Elf32_Ehdr))); // e_shoff = sec hdr table off in bytes + + // e_flags = whatever the target wants + WriteEFlags(); + + // e_ehsize = ELF header size + Write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr) : sizeof(ELF::Elf32_Ehdr)); + + Write16(0); // e_phentsize = prog header entry size + Write16(0); // e_phnum = # prog header entries = 0 + + // e_shentsize = Section header entry size + Write16(is64Bit() ? sizeof(ELF::Elf64_Shdr) : sizeof(ELF::Elf32_Shdr)); + + // e_shnum = # of section header ents + if (NumberOfSections >= ELF::SHN_LORESERVE) + Write16(0); + else + Write16(NumberOfSections); + + // e_shstrndx = Section # of '.shstrtab' + if (NumberOfSections >= ELF::SHN_LORESERVE) + Write16(ELF::SHN_XINDEX); + else + Write16(ShstrtabIndex); +} + +void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, + MCDataFragment *ShndxF, + uint64_t name, + uint8_t info, uint64_t value, + uint64_t size, uint8_t other, + uint32_t shndx, + bool Reserved) { + if (ShndxF) { + if (shndx >= ELF::SHN_LORESERVE && !Reserved) + String32(*ShndxF, shndx); + else + String32(*ShndxF, 0); + } + + uint16_t Index = (shndx >= ELF::SHN_LORESERVE && !Reserved) ? + uint16_t(ELF::SHN_XINDEX) : shndx; + + if (is64Bit()) { + String32(*SymtabF, name); // st_name + String8(*SymtabF, info); // st_info + String8(*SymtabF, other); // st_other + String16(*SymtabF, Index); // st_shndx + String64(*SymtabF, value); // st_value + String64(*SymtabF, size); // st_size + } else { + String32(*SymtabF, name); // st_name + String32(*SymtabF, value); // st_value + String32(*SymtabF, size); // st_size + String8(*SymtabF, info); // st_info + String8(*SymtabF, other); // st_other + String16(*SymtabF, Index); // st_shndx + } +} + +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, + const MCAsmLayout &Layout) { + if (Data.isCommon() && Data.isExternal()) + return Data.getCommonAlignment(); + + const MCSymbol &Symbol = Data.getSymbol(); + + if (Symbol.isAbsolute() && Symbol.isVariable()) { + if (const MCExpr *Value = Symbol.getVariableValue()) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue, Layout)) + return (uint64_t)IntValue; + } + } + + if (!Symbol.isInSection()) + return 0; + + if (Data.getFragment()) + return Layout.getSymbolOffset(&Data); + + return 0; +} + +void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { + // The presence of symbol versions causes undefined symbols and + // versions declared with @@@ to be renamed. + + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Alias = it->getSymbol(); + const MCSymbol &Symbol = Alias.AliasedSymbol(); + MCSymbolData &SD = Asm.getSymbolData(Symbol); + + // Not an alias. + if (&Symbol == &Alias) + continue; + + StringRef AliasName = Alias.getName(); + size_t Pos = AliasName.find('@'); + if (Pos == StringRef::npos) + continue; + + // Aliases defined with .symvar copy the binding from the symbol they alias. + // This is the first place we are able to copy this information. + it->setExternal(SD.isExternal()); + MCELF::SetBinding(*it, MCELF::GetBinding(SD)); + + StringRef Rest = AliasName.substr(Pos); + if (!Symbol.isUndefined() && !Rest.startswith("@@@")) + continue; + + // FIXME: produce a better error message. + if (Symbol.isUndefined() && Rest.startswith("@@") && + !Rest.startswith("@@@")) + report_fatal_error("A @@ version cannot be undefined"); + + Renames.insert(std::make_pair(&Symbol, &Alias)); + } +} + +void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, + MCDataFragment *ShndxF, + ELFSymbolData &MSD, + const MCAsmLayout &Layout) { + MCSymbolData &OrigData = *MSD.SymbolData; + MCSymbolData &Data = + Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol()); + + bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() || + Data.getSymbol().isVariable(); + + uint8_t Binding = MCELF::GetBinding(OrigData); + uint8_t Visibility = MCELF::GetVisibility(OrigData); + uint8_t Type = MCELF::GetType(Data); + + uint8_t Info = (Binding << ELF_STB_Shift) | (Type << ELF_STT_Shift); + uint8_t Other = Visibility; + + uint64_t Value = SymbolValue(Data, Layout); + uint64_t Size = 0; + + assert(!(Data.isCommon() && !Data.isExternal())); + + const MCExpr *ESize = Data.getSize(); + if (ESize) { + int64_t Res; + if (!ESize->EvaluateAsAbsolute(Res, Layout)) + report_fatal_error("Size expression must be absolute."); + Size = Res; + } + + // Write out the symbol table entry + WriteSymbolEntry(SymtabF, ShndxF, MSD.StringIndex, Info, Value, + Size, Other, MSD.SectionIndex, IsReserved); +} + +void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, + MCDataFragment *ShndxF, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap) { + // The string table must be emitted first because we need the index + // into the string table for all the symbol names. + assert(StringTable.size() && "Missing string table"); + + // FIXME: Make sure the start of the symbol table is aligned. + + // The first entry is the undefined symbol entry. + WriteSymbolEntry(SymtabF, ShndxF, 0, 0, 0, 0, 0, 0, false); + + // Write the symbol table entries. + LastLocalSymbolIndex = LocalSymbolData.size() + 1; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) { + ELFSymbolData &MSD = LocalSymbolData[i]; + WriteSymbol(SymtabF, ShndxF, MSD, Layout); + } + + // Write out a symbol table entry for each regular section. + for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; + ++i) { + const MCSectionELF &Section = + static_cast(i->getSection()); + if (Section.getType() == ELF::SHT_RELA || + Section.getType() == ELF::SHT_REL || + Section.getType() == ELF::SHT_STRTAB || + Section.getType() == ELF::SHT_SYMTAB) + continue; + WriteSymbolEntry(SymtabF, ShndxF, 0, ELF::STT_SECTION, 0, 0, + ELF::STV_DEFAULT, SectionIndexMap.lookup(&Section), false); + LastLocalSymbolIndex++; + } + + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) { + ELFSymbolData &MSD = ExternalSymbolData[i]; + MCSymbolData &Data = *MSD.SymbolData; + assert(((Data.getFlags() & ELF_STB_Global) || + (Data.getFlags() & ELF_STB_Weak)) && + "External symbol requires STB_GLOBAL or STB_WEAK flag"); + WriteSymbol(SymtabF, ShndxF, MSD, Layout); + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) + LastLocalSymbolIndex++; + } + + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) { + ELFSymbolData &MSD = UndefinedSymbolData[i]; + MCSymbolData &Data = *MSD.SymbolData; + WriteSymbol(SymtabF, ShndxF, MSD, Layout); + if (MCELF::GetBinding(Data) == ELF::STB_LOCAL) + LastLocalSymbolIndex++; + } +} + +const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F) const { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + const MCSymbol *Renamed = Renames.lookup(&Symbol); + const MCSymbolData &SD = Asm.getSymbolData(Symbol); + + if (ASymbol.isUndefined()) { + if (Renamed) + return Renamed; + return &ASymbol; + } + + if (SD.isExternal()) { + if (Renamed) + return Renamed; + return &Symbol; + } + + const MCSectionELF &Section = + static_cast(ASymbol.getSection()); + const SectionKind secKind = Section.getKind(); + + if (secKind.isBSS()) + return ExplicitRelSym(Asm, Target, F, true); + + if (secKind.isThreadLocal()) { + if (Renamed) + return Renamed; + return &Symbol; + } + + MCSymbolRefExpr::VariantKind Kind = Target.getSymA()->getKind(); + const MCSectionELF &Sec2 = + static_cast(F.getParent()->getSection()); + + if (&Sec2 != &Section && + (Kind == MCSymbolRefExpr::VK_PLT || + Kind == MCSymbolRefExpr::VK_GOTPCREL || + Kind == MCSymbolRefExpr::VK_GOTOFF)) { + if (Renamed) + return Renamed; + return &Symbol; + } + + if (Section.getFlags() & ELF::SHF_MERGE) { + if (Target.getConstant() == 0) + return NULL; + if (Renamed) + return Renamed; + return &Symbol; + } + + return ExplicitRelSym(Asm, Target, F, false); +} + + +void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + int64_t Addend = 0; + int Index = 0; + int64_t Value = Target.getConstant(); + const MCSymbol *RelocSymbol = NULL; + + bool IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + if (!Target.isAbsolute()) { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + RelocSymbol = SymbolToReloc(Asm, Target, *Fragment); + + if (const MCSymbolRefExpr *RefB = Target.getSymB()) { + const MCSymbol &SymbolB = RefB->getSymbol(); + MCSymbolData &SDB = Asm.getSymbolData(SymbolB); + IsPCRel = true; + + // Offset of the symbol in the section + int64_t a = Layout.getSymbolOffset(&SDB); + + // Ofeset of the relocation in the section + int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + Value += b - a; + } + + if (!RelocSymbol) { + MCSymbolData &SD = Asm.getSymbolData(ASymbol); + MCFragment *F = SD.getFragment(); + + Index = F->getParent()->getOrdinal() + 1; + + // Offset of the symbol in the section + Value += Layout.getSymbolOffset(&SD); + } else { + if (Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) + WeakrefUsedInReloc.insert(RelocSymbol); + else + UsedInReloc.insert(RelocSymbol); + Index = -1; + } + Addend = Value; + // Compensate for the addend on i386. + if (is64Bit()) + Value = 0; + } + + FixedValue = Value; + unsigned Type = GetRelocType(Target, Fixup, IsPCRel, + (RelocSymbol != 0), Addend); + + uint64_t RelocOffset = Layout.getFragmentOffset(Fragment) + + Fixup.getOffset(); + + if (!hasRelocationAddend()) + Addend = 0; + ELFRelocationEntry ERE(RelocOffset, Index, Type, RelocSymbol, Addend); + Relocations[Fragment->getParent()].push_back(ERE); +} + + +uint64_t +ELFObjectWriter::getSymbolIndexInSymbolTable(const MCAssembler &Asm, + const MCSymbol *S) { + MCSymbolData &SD = Asm.getSymbolData(*S); + return SD.getIndex(); +} + +bool ELFObjectWriter::isInSymtab(const MCAssembler &Asm, + const MCSymbolData &Data, + bool Used, bool Renamed) { + if (Data.getFlags() & ELF_Other_Weakref) + return false; + + if (Used) + return true; + + if (Renamed) + return false; + + const MCSymbol &Symbol = Data.getSymbol(); + + if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_") + return true; + + const MCSymbol &A = Symbol.AliasedSymbol(); + if (Symbol.isVariable() && !A.isVariable() && A.isUndefined()) + return false; + + bool IsGlobal = MCELF::GetBinding(Data) == ELF::STB_GLOBAL; + if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal) + return false; + + if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined()) + return false; + + if (Symbol.isTemporary()) + return false; + + return true; +} + +bool ELFObjectWriter::isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc) { + if (Data.isExternal()) + return false; + + const MCSymbol &Symbol = Data.getSymbol(); + const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); + + if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) { + if (isSignature && !isUsedInReloc) + return true; + + return false; + } + + return true; +} + +void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, + SectionIndexMapTy &SectionIndexMap) { + unsigned Index = 1; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (Section.getType() != ELF::SHT_GROUP) + continue; + SectionIndexMap[&Section] = Index++; + } + + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (Section.getType() == ELF::SHT_GROUP) + continue; + SectionIndexMap[&Section] = Index++; + } +} + +void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap) { + // FIXME: Is this the correct place to do this? + if (NeedsGOT) { + llvm::StringRef Name = "_GLOBAL_OFFSET_TABLE_"; + MCSymbol *Sym = Asm.getContext().GetOrCreateSymbol(Name); + MCSymbolData &Data = Asm.getOrCreateSymbolData(*Sym); + Data.setExternal(true); + MCELF::SetBinding(Data, ELF::STB_GLOBAL); + } + + // Build section lookup table. + int NumRegularSections = Asm.size(); + + // Index 0 is always the empty string. + StringMap StringIndexMap; + StringTable += '\x00'; + + // Add the data for the symbols. + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Symbol = it->getSymbol(); + + bool Used = UsedInReloc.count(&Symbol); + bool WeakrefUsed = WeakrefUsedInReloc.count(&Symbol); + bool isSignature = RevGroupMap.count(&Symbol); + + if (!isInSymtab(Asm, *it, + Used || WeakrefUsed || isSignature, + Renames.count(&Symbol))) + continue; + + ELFSymbolData MSD; + MSD.SymbolData = it; + const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); + + // Undefined symbols are global, but this is the first place we + // are able to set it. + bool Local = isLocal(*it, isSignature, Used); + if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { + MCSymbolData &SD = Asm.getSymbolData(RefSymbol); + MCELF::SetBinding(*it, ELF::STB_GLOBAL); + MCELF::SetBinding(SD, ELF::STB_GLOBAL); + } + + if (RefSymbol.isUndefined() && !Used && WeakrefUsed) + MCELF::SetBinding(*it, ELF::STB_WEAK); + + if (it->isCommon()) { + assert(!Local); + MSD.SectionIndex = ELF::SHN_COMMON; + } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) { + MSD.SectionIndex = ELF::SHN_ABS; + } else if (RefSymbol.isUndefined()) { + if (isSignature && !Used) + MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); + else + MSD.SectionIndex = ELF::SHN_UNDEF; + } else { + const MCSectionELF &Section = + static_cast(RefSymbol.getSection()); + MSD.SectionIndex = SectionIndexMap.lookup(&Section); + if (MSD.SectionIndex >= ELF::SHN_LORESERVE) + NeedsSymtabShndx = true; + assert(MSD.SectionIndex && "Invalid section index!"); + } + + // The @@@ in symbol version is replaced with @ in undefined symbols and + // @@ in defined ones. + StringRef Name = Symbol.getName(); + SmallString<32> Buf; + + size_t Pos = Name.find("@@@"); + if (Pos != StringRef::npos) { + Buf += Name.substr(0, Pos); + unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 2 : 1; + Buf += Name.substr(Pos + Skip); + Name = Buf; + } + + uint64_t &Entry = StringIndexMap[Name]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Name; + StringTable += '\x00'; + } + MSD.StringIndex = Entry; + if (MSD.SectionIndex == ELF::SHN_UNDEF) + UndefinedSymbolData.push_back(MSD); + else if (Local) + LocalSymbolData.push_back(MSD); + else + ExternalSymbolData.push_back(MSD); + } + + // Symbols are required to be in lexicographic order. + array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); + array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); + array_pod_sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); + + // Set the symbol indices. Local symbols must come before all other + // symbols with non-local bindings. + unsigned Index = 1; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) + LocalSymbolData[i].SymbolData->setIndex(Index++); + + Index += NumRegularSections; + + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) + ExternalSymbolData[i].SymbolData->setIndex(Index++); + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) + UndefinedSymbolData[i].SymbolData->setIndex(Index++); +} + +void ELFObjectWriter::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, + const MCSectionData &SD) { + if (!Relocations[&SD].empty()) { + MCContext &Ctx = Asm.getContext(); + const MCSectionELF *RelaSection; + const MCSectionELF &Section = + static_cast(SD.getSection()); + + const StringRef SectionName = Section.getSectionName(); + std::string RelaSectionName = hasRelocationAddend() ? ".rela" : ".rel"; + RelaSectionName += SectionName; + + unsigned EntrySize; + if (hasRelocationAddend()) + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); + else + EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); + + RelaSection = Ctx.getELFSection(RelaSectionName, hasRelocationAddend() ? + ELF::SHT_RELA : ELF::SHT_REL, 0, + SectionKind::getReadOnly(), + EntrySize, ""); + + MCSectionData &RelaSD = Asm.getOrCreateSectionData(*RelaSection); + RelaSD.setAlignment(is64Bit() ? 8 : 4); + + MCDataFragment *F = new MCDataFragment(&RelaSD); + + WriteRelocationsFragment(Asm, F, &SD); + } +} + +void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, + uint64_t Flags, uint64_t Address, + uint64_t Offset, uint64_t Size, + uint32_t Link, uint32_t Info, + uint64_t Alignment, + uint64_t EntrySize) { + Write32(Name); // sh_name: index into string table + Write32(Type); // sh_type + WriteWord(Flags); // sh_flags + WriteWord(Address); // sh_addr + WriteWord(Offset); // sh_offset + WriteWord(Size); // sh_size + Write32(Link); // sh_link + Write32(Info); // sh_info + WriteWord(Alignment); // sh_addralign + WriteWord(EntrySize); // sh_entsize +} + +void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, + MCDataFragment *F, + const MCSectionData *SD) { + std::vector &Relocs = Relocations[SD]; + // sort by the r_offset just like gnu as does + array_pod_sort(Relocs.begin(), Relocs.end()); + + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + ELFRelocationEntry entry = Relocs[e - i - 1]; + + if (!entry.Index) + ; + else if (entry.Index < 0) + entry.Index = getSymbolIndexInSymbolTable(Asm, entry.Symbol); + else + entry.Index += LocalSymbolData.size(); + if (is64Bit()) { + String64(*F, entry.r_offset); + + struct ELF::Elf64_Rela ERE64; + ERE64.setSymbolAndType(entry.Index, entry.Type); + String64(*F, ERE64.r_info); + + if (hasRelocationAddend()) + String64(*F, entry.r_addend); + } else { + String32(*F, entry.r_offset); + + struct ELF::Elf32_Rela ERE32; + ERE32.setSymbolAndType(entry.Index, entry.Type); + String32(*F, ERE32.r_info); + + if (hasRelocationAddend()) + String32(*F, entry.r_addend); + } + } +} + +void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, + MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap) { + MCContext &Ctx = Asm.getContext(); + MCDataFragment *F; + + unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32; + + // We construct .shstrtab, .symtab and .strtab in this order to match gnu as. + const MCSectionELF *ShstrtabSection = + Ctx.getELFSection(".shstrtab", ELF::SHT_STRTAB, 0, + SectionKind::getReadOnly()); + MCSectionData &ShstrtabSD = Asm.getOrCreateSectionData(*ShstrtabSection); + ShstrtabSD.setAlignment(1); + ShstrtabIndex = Asm.size(); + + const MCSectionELF *SymtabSection = + Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, + SectionKind::getReadOnly(), + EntrySize, ""); + MCSectionData &SymtabSD = Asm.getOrCreateSectionData(*SymtabSection); + SymtabSD.setAlignment(is64Bit() ? 8 : 4); + SymbolTableIndex = Asm.size(); + + MCSectionData *SymtabShndxSD = NULL; + + if (NeedsSymtabShndx) { + const MCSectionELF *SymtabShndxSection = + Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, + SectionKind::getReadOnly(), 4, ""); + SymtabShndxSD = &Asm.getOrCreateSectionData(*SymtabShndxSection); + SymtabShndxSD->setAlignment(4); + } + + const MCSection *StrtabSection; + StrtabSection = Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0, + SectionKind::getReadOnly()); + MCSectionData &StrtabSD = Asm.getOrCreateSectionData(*StrtabSection); + StrtabSD.setAlignment(1); + StringTableIndex = Asm.size(); + + WriteRelocations(Asm, Layout); + + // Symbol table + F = new MCDataFragment(&SymtabSD); + MCDataFragment *ShndxF = NULL; + if (NeedsSymtabShndx) { + ShndxF = new MCDataFragment(SymtabShndxSD); + } + WriteSymbolTable(F, ShndxF, Asm, Layout, SectionIndexMap); + + F = new MCDataFragment(&StrtabSD); + F->getContents().append(StringTable.begin(), StringTable.end()); + + F = new MCDataFragment(&ShstrtabSD); + + // Section header string table. + // + // The first entry of a string table holds a null character so skip + // section 0. + uint64_t Index = 1; + F->getContents() += '\x00'; + + StringMap SecStringMap; + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + // FIXME: We could merge suffixes like in .text and .rela.text. + + StringRef Name = Section.getSectionName(); + if (SecStringMap.count(Name)) { + SectionStringTableIndex[&Section] = SecStringMap[Name]; + continue; + } + // Remember the index into the string table so we can write it + // into the sh_name field of the section header table. + SectionStringTableIndex[&Section] = Index; + SecStringMap[Name] = Index; + + Index += Name.size() + 1; + F->getContents() += Name; + F->getContents() += '\x00'; + } +} + +void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, + MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap) { + // Create the .note.GNU-stack section if needed. + MCContext &Ctx = Asm.getContext(); + if (Asm.getNoExecStack()) { + const MCSectionELF *GnuStackSection = + Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, + SectionKind::getReadOnly()); + Asm.getOrCreateSectionData(*GnuStackSection); + } + + // Build the groups + for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); + it != ie; ++it) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (!(Section.getFlags() & ELF::SHF_GROUP)) + continue; + + const MCSymbol *SignatureSymbol = Section.getGroup(); + Asm.getOrCreateSymbolData(*SignatureSymbol); + const MCSectionELF *&Group = RevGroupMap[SignatureSymbol]; + if (!Group) { + Group = Ctx.CreateELFGroupSection(); + MCSectionData &Data = Asm.getOrCreateSectionData(*Group); + Data.setAlignment(4); + MCDataFragment *F = new MCDataFragment(&Data); + String32(*F, ELF::GRP_COMDAT); + } + GroupMap[Group] = SignatureSymbol; + } + + // Add sections to the groups + unsigned Index = 1; + unsigned NumGroups = RevGroupMap.size(); + for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); + it != ie; ++it, ++Index) { + const MCSectionELF &Section = + static_cast(it->getSection()); + if (!(Section.getFlags() & ELF::SHF_GROUP)) + continue; + const MCSectionELF *Group = RevGroupMap[Section.getGroup()]; + MCSectionData &Data = Asm.getOrCreateSectionData(*Group); + // FIXME: we could use the previous fragment + MCDataFragment *F = new MCDataFragment(&Data); + String32(*F, NumGroups + Index); + } +} + +void ELFObjectWriter::WriteSection(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, + uint64_t Offset, uint64_t Size, + uint64_t Alignment, + const MCSectionELF &Section) { + uint64_t sh_link = 0; + uint64_t sh_info = 0; + + switch(Section.getType()) { + case ELF::SHT_DYNAMIC: + sh_link = SectionStringTableIndex[&Section]; + sh_info = 0; + break; + + case ELF::SHT_REL: + case ELF::SHT_RELA: { + const MCSectionELF *SymtabSection; + const MCSectionELF *InfoSection; + SymtabSection = Asm.getContext().getELFSection(".symtab", ELF::SHT_SYMTAB, + 0, + SectionKind::getReadOnly()); + sh_link = SectionIndexMap.lookup(SymtabSection); + assert(sh_link && ".symtab not found"); + + // Remove ".rel" and ".rela" prefixes. + unsigned SecNameLen = (Section.getType() == ELF::SHT_REL) ? 4 : 5; + StringRef SectionName = Section.getSectionName().substr(SecNameLen); + + InfoSection = Asm.getContext().getELFSection(SectionName, + ELF::SHT_PROGBITS, 0, + SectionKind::getReadOnly()); + sh_info = SectionIndexMap.lookup(InfoSection); + break; + } + + case ELF::SHT_SYMTAB: + case ELF::SHT_DYNSYM: + sh_link = StringTableIndex; + sh_info = LastLocalSymbolIndex; + break; + + case ELF::SHT_SYMTAB_SHNDX: + sh_link = SymbolTableIndex; + break; + + case ELF::SHT_PROGBITS: + case ELF::SHT_STRTAB: + case ELF::SHT_NOBITS: + case ELF::SHT_NOTE: + case ELF::SHT_NULL: + case ELF::SHT_ARM_ATTRIBUTES: + case ELF::SHT_INIT_ARRAY: + case ELF::SHT_FINI_ARRAY: + case ELF::SHT_PREINIT_ARRAY: + case ELF::SHT_X86_64_UNWIND: + // Nothing to do. + break; + + case ELF::SHT_GROUP: { + sh_link = SymbolTableIndex; + sh_info = GroupSymbolIndex; + break; + } + + default: + assert(0 && "FIXME: sh_type value not supported!"); + break; + } + + WriteSecHdrEntry(SectionStringTableIndex[&Section], Section.getType(), + Section.getFlags(), 0, Offset, Size, sh_link, sh_info, + Alignment, Section.getEntrySize()); +} + +bool ELFObjectWriter::IsELFMetaDataSection(const MCSectionData &SD) { + return SD.getOrdinal() == ~UINT32_C(0) && + !SD.getSection().isVirtualSection(); +} + +uint64_t ELFObjectWriter::DataSectionSize(const MCSectionData &SD) { + uint64_t Ret = 0; + for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; + ++i) { + const MCFragment &F = *i; + assert(F.getKind() == MCFragment::FT_Data); + Ret += cast(F).getContents().size(); + } + return Ret; +} + +uint64_t ELFObjectWriter::GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { + if (IsELFMetaDataSection(SD)) + return DataSectionSize(SD); + return Layout.getSectionFileSize(&SD); +} + +uint64_t ELFObjectWriter::GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD) { + if (IsELFMetaDataSection(SD)) + return DataSectionSize(SD); + return Layout.getSectionAddressSize(&SD); +} + +void ELFObjectWriter::WriteDataSectionData(ELFObjectWriter *W, + const MCSectionData &SD) { + for (MCSectionData::const_iterator i = SD.begin(), e = SD.end(); i != e; + ++i) { + const MCFragment &F = *i; + assert(F.getKind() == MCFragment::FT_Data); + W->WriteBytes(cast(F).getContents().str()); + } +} + +void ELFObjectWriter::WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + GroupMapTy GroupMap; + RevGroupMapTy RevGroupMap; + CreateIndexedSections(Asm, const_cast(Layout), GroupMap, + RevGroupMap); + + SectionIndexMapTy SectionIndexMap; + + ComputeIndexMap(Asm, SectionIndexMap); + + // Compute symbol table information. + ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap); + + CreateMetadataSections(const_cast(Asm), + const_cast(Layout), + SectionIndexMap); + + // Update to include the metadata sections. + ComputeIndexMap(Asm, SectionIndexMap); + + // Add 1 for the null section. + unsigned NumSections = Asm.size() + 1; + uint64_t NaturalAlignment = is64Bit() ? 8 : 4; + uint64_t HeaderSize = is64Bit() ? sizeof(ELF::Elf64_Ehdr) : + sizeof(ELF::Elf32_Ehdr); + uint64_t FileOff = HeaderSize; + + std::vector Sections; + Sections.resize(NumSections); + + for (SectionIndexMapTy::const_iterator i= + SectionIndexMap.begin(), e = SectionIndexMap.end(); i != e; ++i) { + const std::pair &p = *i; + Sections[p.second] = p.first; + } + + for (unsigned i = 1; i < NumSections; ++i) { + const MCSectionELF &Section = *Sections[i]; + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + + FileOff = RoundUpToAlignment(FileOff, SD.getAlignment()); + + // Get the size of the section in the output file (including padding). + FileOff += GetSectionFileSize(Layout, SD); + } + + FileOff = RoundUpToAlignment(FileOff, NaturalAlignment); + + // Write out the ELF header ... + WriteHeader(FileOff - HeaderSize, NumSections); + + FileOff = HeaderSize; + + // ... then all of the sections ... + DenseMap SectionOffsetMap; + + for (unsigned i = 1; i < NumSections; ++i) { + const MCSectionELF &Section = *Sections[i]; + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + + uint64_t Padding = OffsetToAlignment(FileOff, SD.getAlignment()); + WriteZeros(Padding); + FileOff += Padding; + + // Remember the offset into the file for this section. + SectionOffsetMap[&Section] = FileOff; + + FileOff += GetSectionFileSize(Layout, SD); + + if (IsELFMetaDataSection(SD)) + WriteDataSectionData(this, SD); + else + Asm.WriteSectionData(&SD, Layout); + } + + uint64_t Padding = OffsetToAlignment(FileOff, NaturalAlignment); + WriteZeros(Padding); + FileOff += Padding; + + // ... and then the section header table. + // Should we align the section header table? + // + // Null section first. + uint64_t FirstSectionSize = + NumSections >= ELF::SHN_LORESERVE ? NumSections : 0; + uint32_t FirstSectionLink = + ShstrtabIndex >= ELF::SHN_LORESERVE ? ShstrtabIndex : 0; + WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, FirstSectionLink, 0, 0, 0); + + for (unsigned i = 1; i < NumSections; ++i) { + const MCSectionELF &Section = *Sections[i]; + const MCSectionData &SD = Asm.getOrCreateSectionData(Section); + uint32_t GroupSymbolIndex; + if (Section.getType() != ELF::SHT_GROUP) + GroupSymbolIndex = 0; + else + GroupSymbolIndex = getSymbolIndexInSymbolTable(Asm, GroupMap[&Section]); + + uint64_t Size = GetSectionAddressSize(Layout, SD); + + WriteSection(Asm, SectionIndexMap, GroupSymbolIndex, + SectionOffsetMap[&Section], Size, + SD.getAlignment(), Section); + } +} + +bool +ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + if (DataA.getFlags() & ELF_STB_Weak) + return false; + return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + Asm, DataA, FB,InSet, IsPCRel); +} + +MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &OS, + bool IsLittleEndian) { + switch (MOTW->getEMachine()) { + case ELF::EM_386: + case ELF::EM_X86_64: + return new X86ELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_ARM: + return new ARMELFObjectWriter(MOTW, OS, IsLittleEndian); break; + case ELF::EM_MBLAZE: + return new MBlazeELFObjectWriter(MOTW, OS, IsLittleEndian); break; + default: llvm_unreachable("Unsupported architecture"); break; + } +} + + +/// START OF SUBCLASSES for ELFObjectWriter +//===- ARMELFObjectWriter -------------------------------------------===// + +ARMELFObjectWriter::ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) +{} + +ARMELFObjectWriter::~ARMELFObjectWriter() +{} + +// FIXME: get the real EABI Version from the Triple. +void ARMELFObjectWriter::WriteEFlags() { + Write32(ELF::EF_ARM_EABIMASK & DefaultEABIVersion); +} + +// In ARM, _MergedGlobals and other most symbols get emitted directly. +// I.e. not as an offset to a section symbol. +// This code is a first-cut approximation of what ARM/gcc does. + +const MCSymbol *ARMELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const { + const MCSymbol &Symbol = Target.getSymA()->getSymbol(); + bool EmitThisSym = false; + + if (IsBSS) { + EmitThisSym = StringSwitch(Symbol.getName()) + .Case("_MergedGlobals", true) + .Default(false); + } else { + EmitThisSym = StringSwitch(Symbol.getName()) + .Case("_MergedGlobals", true) + .StartsWith(".L.str", true) + .Default(false); + } + if (EmitThisSym) + return &Symbol; + if (! Symbol.isTemporary()) + return &Symbol; + return NULL; +} + +unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + + unsigned Type = 0; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: assert(0 && "Unimplemented"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_BASE_PREL; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + assert(0 && "unimplemented"); + break; + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + } + break; + case ARM::fixup_arm_uncondbranch: + switch (Modifier) { + case MCSymbolRefExpr::VK_ARM_PLT: + Type = ELF::R_ARM_PLT32; + break; + default: + Type = ELF::R_ARM_CALL; + break; + } + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + Type = ELF::R_ARM_MOVT_PREL; + break; + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + Type = ELF::R_ARM_MOVW_PREL_NC; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + Type = ELF::R_ARM_THM_MOVT_PREL; + break; + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + Type = ELF::R_ARM_THM_MOVW_PREL_NC; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + switch (Modifier) { + default: llvm_unreachable("Unsupported Modifier"); break; + case MCSymbolRefExpr::VK_ARM_GOT: + Type = ELF::R_ARM_GOT_BREL; + break; + case MCSymbolRefExpr::VK_ARM_TLSGD: + Type = ELF::R_ARM_TLS_GD32; + break; + case MCSymbolRefExpr::VK_ARM_TPOFF: + Type = ELF::R_ARM_TLS_LE32; + break; + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + Type = ELF::R_ARM_TLS_IE32; + break; + case MCSymbolRefExpr::VK_None: + Type = ELF::R_ARM_ABS32; + break; + case MCSymbolRefExpr::VK_ARM_GOTOFF: + Type = ELF::R_ARM_GOTOFF32; + break; + } + break; + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_cb: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_arm_thumb_br: + assert(0 && "Unimplemented"); + break; + case ARM::fixup_arm_uncondbranch: + Type = ELF::R_ARM_CALL; + break; + case ARM::fixup_arm_condbranch: + Type = ELF::R_ARM_JUMP24; + break; + case ARM::fixup_arm_movt_hi16: + Type = ELF::R_ARM_MOVT_ABS; + break; + case ARM::fixup_arm_movw_lo16: + Type = ELF::R_ARM_MOVW_ABS_NC; + break; + case ARM::fixup_t2_movt_hi16: + Type = ELF::R_ARM_THM_MOVT_ABS; + break; + case ARM::fixup_t2_movw_lo16: + Type = ELF::R_ARM_THM_MOVW_ABS_NC; + break; + } + } + + if (RelocNeedsGOT(Modifier)) + NeedsGOT = true; + + return Type; +} + +//===- MBlazeELFObjectWriter -------------------------------------------===// + +MBlazeELFObjectWriter::MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) { +} + +MBlazeELFObjectWriter::~MBlazeELFObjectWriter() { +} + +unsigned MBlazeELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // determine the type of the relocation + unsigned Type; + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("Unimplemented"); + case FK_PCRel_4: + Type = ELF::R_MICROBLAZE_64_PCREL; + break; + case FK_PCRel_2: + Type = ELF::R_MICROBLAZE_32_PCREL; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_4: + Type = ((IsRelocWithSymbol || Addend !=0) + ? ELF::R_MICROBLAZE_32 + : ELF::R_MICROBLAZE_64); + break; + case FK_Data_2: + Type = ELF::R_MICROBLAZE_32; + break; + } + } + return Type; +} + +//===- X86ELFObjectWriter -------------------------------------------===// + + +X86ELFObjectWriter::X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian) + : ELFObjectWriter(MOTW, _OS, IsLittleEndian) +{} + +X86ELFObjectWriter::~X86ELFObjectWriter() +{} + +unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel, + bool IsRelocWithSymbol, + int64_t Addend) { + // determine the type of the relocation + + MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? + MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); + unsigned Type; + if (is64Bit()) { + if (IsPCRel) { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_8: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC64; + break; + case X86::reloc_signed_4byte: + case X86::reloc_riprel_4byte_movq_load: + case FK_Data_4: // FIXME? + case X86::reloc_riprel_4byte: + case FK_PCRel_4: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_X86_64_PC32; + break; + case MCSymbolRefExpr::VK_PLT: + Type = ELF::R_X86_64_PLT32; + break; + case MCSymbolRefExpr::VK_GOTPCREL: + Type = ELF::R_X86_64_GOTPCREL; + break; + case MCSymbolRefExpr::VK_GOTTPOFF: + Type = ELF::R_X86_64_GOTTPOFF; + break; + case MCSymbolRefExpr::VK_TLSGD: + Type = ELF::R_X86_64_TLSGD; + break; + case MCSymbolRefExpr::VK_TLSLD: + Type = ELF::R_X86_64_TLSLD; + break; + } + break; + case FK_PCRel_2: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC16; + break; + case FK_PCRel_1: + assert(Modifier == MCSymbolRefExpr::VK_None); + Type = ELF::R_X86_64_PC8; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + case FK_Data_8: Type = ELF::R_X86_64_64; break; + case X86::reloc_signed_4byte: + assert(isInt<32>(Target.getConstant())); + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_X86_64_32S; + break; + case MCSymbolRefExpr::VK_GOT: + Type = ELF::R_X86_64_GOT32; + break; + case MCSymbolRefExpr::VK_GOTPCREL: + Type = ELF::R_X86_64_GOTPCREL; + break; + case MCSymbolRefExpr::VK_TPOFF: + Type = ELF::R_X86_64_TPOFF32; + break; + case MCSymbolRefExpr::VK_DTPOFF: + Type = ELF::R_X86_64_DTPOFF32; + break; + } + break; + case FK_Data_4: + Type = ELF::R_X86_64_32; + break; + case FK_Data_2: Type = ELF::R_X86_64_16; break; + case FK_PCRel_1: + case FK_Data_1: Type = ELF::R_X86_64_8; break; + } + } + } else { + if (IsPCRel) { + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_386_PC32; + break; + case MCSymbolRefExpr::VK_PLT: + Type = ELF::R_386_PLT32; + break; + } + } else { + switch ((unsigned)Fixup.getKind()) { + default: llvm_unreachable("invalid fixup kind!"); + + case X86::reloc_global_offset_table: + Type = ELF::R_386_GOTPC; + break; + + // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode + // instead? + case X86::reloc_signed_4byte: + case FK_PCRel_4: + case FK_Data_4: + switch (Modifier) { + default: + llvm_unreachable("Unimplemented"); + case MCSymbolRefExpr::VK_None: + Type = ELF::R_386_32; + break; + case MCSymbolRefExpr::VK_GOT: + Type = ELF::R_386_GOT32; + break; + case MCSymbolRefExpr::VK_GOTOFF: + Type = ELF::R_386_GOTOFF; + break; + case MCSymbolRefExpr::VK_TLSGD: + Type = ELF::R_386_TLS_GD; + break; + case MCSymbolRefExpr::VK_TPOFF: + Type = ELF::R_386_TLS_LE_32; + break; + case MCSymbolRefExpr::VK_INDNTPOFF: + Type = ELF::R_386_TLS_IE; + break; + case MCSymbolRefExpr::VK_NTPOFF: + Type = ELF::R_386_TLS_LE; + break; + case MCSymbolRefExpr::VK_GOTNTPOFF: + Type = ELF::R_386_TLS_GOTIE; + break; + case MCSymbolRefExpr::VK_TLSLDM: + Type = ELF::R_386_TLS_LDM; + break; + case MCSymbolRefExpr::VK_DTPOFF: + Type = ELF::R_386_TLS_LDO_32; + break; + } + break; + case FK_Data_2: Type = ELF::R_386_16; break; + case FK_PCRel_1: + case FK_Data_1: Type = ELF::R_386_8; break; + } + } + } + + if (RelocNeedsGOT(Modifier)) + NeedsGOT = true; + + return Type; +} diff --git a/final/lib/MC/ELFObjectWriter.h b/final/lib/MC/ELFObjectWriter.h new file mode 100644 index 00000000000..9457623556d --- /dev/null +++ b/final/lib/MC/ELFObjectWriter.h @@ -0,0 +1,391 @@ +//===- lib/MC/ELFObjectWriter.h - ELF File Writer -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF object file writer information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_ELFOBJECTWRITER_H +#define LLVM_MC_ELFOBJECTWRITER_H + +#include "MCELF.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" + +#include + +namespace llvm { + +class MCSection; +class MCDataFragment; +class MCSectionELF; + +class ELFObjectWriter : public MCObjectWriter { + protected: + + static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); + static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); + static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); + static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, + bool Used, bool Renamed); + static bool isLocal(const MCSymbolData &Data, bool isSignature, + bool isUsedInReloc); + static bool IsELFMetaDataSection(const MCSectionData &SD); + static uint64_t DataSectionSize(const MCSectionData &SD); + static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, + const MCSectionData &SD); + static void WriteDataSectionData(ELFObjectWriter *W, + const MCSectionData &SD); + + /*static bool isFixupKindX86RIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; + }*/ + + /// ELFSymbolData - Helper struct for containing some precomputed + /// information on symbols. + struct ELFSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint32_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const ELFSymbolData &RHS) const { + if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) + return true; + if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) + return false; + return SymbolData->getSymbol().getName() < + RHS.SymbolData->getSymbol().getName(); + } + }; + + /// @name Relocation Data + /// @{ + + struct ELFRelocationEntry { + // Make these big enough for both 32-bit and 64-bit + uint64_t r_offset; + int Index; + unsigned Type; + const MCSymbol *Symbol; + uint64_t r_addend; + + ELFRelocationEntry() + : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} + + ELFRelocationEntry(uint64_t RelocOffset, int Idx, + unsigned RelType, const MCSymbol *Sym, + uint64_t Addend) + : r_offset(RelocOffset), Index(Idx), Type(RelType), + Symbol(Sym), r_addend(Addend) {} + + // Support lexicographic sorting. + bool operator<(const ELFRelocationEntry &RE) const { + return RE.r_offset < r_offset; + } + }; + + /// The target specific ELF writer instance. + llvm::OwningPtr TargetObjectWriter; + + SmallPtrSet UsedInReloc; + SmallPtrSet WeakrefUsedInReloc; + DenseMap Renames; + + llvm::DenseMap > Relocations; + DenseMap SectionStringTableIndex; + + /// @} + /// @name Symbol Table Data + /// @{ + + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + + /// @} + + bool NeedsGOT; + + bool NeedsSymtabShndx; + + // This holds the symbol table index of the last local symbol. + unsigned LastLocalSymbolIndex; + // This holds the .strtab section index. + unsigned StringTableIndex; + // This holds the .symtab section index. + unsigned SymbolTableIndex; + + unsigned ShstrtabIndex; + + + const MCSymbol *SymbolToReloc(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F) const; + + // For arch-specific emission of explicit reloc symbol + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const { + return NULL; + } + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool hasRelocationAddend() const { + return TargetObjectWriter->hasRelocationAddend(); + } + + public: + ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, bool IsLittleEndian) + : MCObjectWriter(_OS, IsLittleEndian), + TargetObjectWriter(MOTW), + NeedsGOT(false), NeedsSymtabShndx(false){ + } + + virtual ~ELFObjectWriter(); + + void WriteWord(uint64_t W) { + if (is64Bit()) + Write64(W); + else + Write32(W); + } + + void StringLE16(char *buf, uint16_t Value) { + buf[0] = char(Value >> 0); + buf[1] = char(Value >> 8); + } + + void StringLE32(char *buf, uint32_t Value) { + StringLE16(buf, uint16_t(Value >> 0)); + StringLE16(buf + 2, uint16_t(Value >> 16)); + } + + void StringLE64(char *buf, uint64_t Value) { + StringLE32(buf, uint32_t(Value >> 0)); + StringLE32(buf + 4, uint32_t(Value >> 32)); + } + + void StringBE16(char *buf ,uint16_t Value) { + buf[0] = char(Value >> 8); + buf[1] = char(Value >> 0); + } + + void StringBE32(char *buf, uint32_t Value) { + StringBE16(buf, uint16_t(Value >> 16)); + StringBE16(buf + 2, uint16_t(Value >> 0)); + } + + void StringBE64(char *buf, uint64_t Value) { + StringBE32(buf, uint32_t(Value >> 32)); + StringBE32(buf + 4, uint32_t(Value >> 0)); + } + + void String8(MCDataFragment &F, uint8_t Value) { + char buf[1]; + buf[0] = Value; + F.getContents() += StringRef(buf, 1); + } + + void String16(MCDataFragment &F, uint16_t Value) { + char buf[2]; + if (isLittleEndian()) + StringLE16(buf, Value); + else + StringBE16(buf, Value); + F.getContents() += StringRef(buf, 2); + } + + void String32(MCDataFragment &F, uint32_t Value) { + char buf[4]; + if (isLittleEndian()) + StringLE32(buf, Value); + else + StringBE32(buf, Value); + F.getContents() += StringRef(buf, 4); + } + + void String64(MCDataFragment &F, uint64_t Value) { + char buf[8]; + if (isLittleEndian()) + StringLE64(buf, Value); + else + StringBE64(buf, Value); + F.getContents() += StringRef(buf, 8); + } + + virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); + + /// Default e_flags = 0 + virtual void WriteEFlags() { Write32(0); } + + virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + uint64_t name, uint8_t info, + uint64_t value, uint64_t size, + uint8_t other, uint32_t shndx, + bool Reserved); + + virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + ELFSymbolData &MSD, + const MCAsmLayout &Layout); + + typedef DenseMap SectionIndexMapTy; + virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap); + + virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + + virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, + const MCSymbol *S); + + // Map from a group section to the signature symbol + typedef DenseMap GroupMapTy; + // Map from a signature symbol to the group section + typedef DenseMap RevGroupMapTy; + + /// ComputeSymbolTable - Compute the symbol table data + /// + /// \param StringTable [out] - The string table data. + /// \param StringIndexMap [out] - Map from symbol names to offsets in the + /// string table. + virtual void ComputeSymbolTable(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap); + + virtual void ComputeIndexMap(MCAssembler &Asm, + SectionIndexMapTy &SectionIndexMap); + + virtual void WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, + const MCSectionData &SD); + + virtual void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout) { + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + WriteRelocation(Asm, Layout, *it); + } + } + + virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap); + + // Create the sections that show up in the symbol table. Currently + // those are the .note.GNU-stack section and the group sections. + virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, + GroupMapTy &GroupMap, + RevGroupMapTy &RevGroupMap); + + virtual void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout); + + virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, + uint64_t Address, uint64_t Offset, + uint64_t Size, uint32_t Link, uint32_t Info, + uint64_t Alignment, uint64_t EntrySize); + + virtual void WriteRelocationsFragment(const MCAssembler &Asm, + MCDataFragment *F, + const MCSectionData *SD); + + virtual bool + IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; + + virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + virtual void WriteSection(MCAssembler &Asm, + const SectionIndexMapTy &SectionIndexMap, + uint32_t GroupSymbolIndex, + uint64_t Offset, uint64_t Size, uint64_t Alignment, + const MCSectionELF &Section); + + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend) = 0; + }; + + //===- X86ELFObjectWriter -------------------------------------------===// + + class X86ELFObjectWriter : public ELFObjectWriter { + public: + X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~X86ELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; + + + //===- ARMELFObjectWriter -------------------------------------------===// + + class ARMELFObjectWriter : public ELFObjectWriter { + public: + // FIXME: MCAssembler can't yet return the Subtarget, + enum { DefaultEABIVersion = 0x05000000U }; + + ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~ARMELFObjectWriter(); + + virtual void WriteEFlags(); + protected: + virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, + const MCValue &Target, + const MCFragment &F, + bool IsBSS) const; + + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; + + //===- MBlazeELFObjectWriter -------------------------------------------===// + + class MBlazeELFObjectWriter : public ELFObjectWriter { + public: + MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, + raw_ostream &_OS, + bool IsLittleEndian); + + virtual ~MBlazeELFObjectWriter(); + protected: + virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel, bool IsRelocWithSymbol, + int64_t Addend); + }; +} + +#endif diff --git a/final/lib/MC/MCAsmInfo.cpp b/final/lib/MC/MCAsmInfo.cpp new file mode 100644 index 00000000000..8199fb2e158 --- /dev/null +++ b/final/lib/MC/MCAsmInfo.cpp @@ -0,0 +1,108 @@ +//===-- MCAsmInfo.cpp - Asm Info -------------------------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target asm properties related what form asm statements +// should take. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/DataTypes.h" +#include +#include +using namespace llvm; + +MCAsmInfo::MCAsmInfo() { + HasSubsectionsViaSymbols = false; + HasMachoZeroFillDirective = false; + HasMachoTBSSDirective = false; + HasStaticCtorDtorReferenceInStaticMode = false; + LinkerRequiresNonEmptyDwarfLines = false; + MaxInstLength = 4; + PCSymbol = "$"; + SeparatorChar = ';'; + CommentColumn = 40; + CommentString = "#"; + LabelSuffix = ":"; + GlobalPrefix = ""; + PrivateGlobalPrefix = "."; + LinkerPrivateGlobalPrefix = ""; + InlineAsmStart = "APP"; + InlineAsmEnd = "NO_APP"; + AssemblerDialect = 0; + AllowQuotesInName = false; + AllowNameToStartWithDigit = false; + AllowPeriodsInName = true; + ZeroDirective = "\t.zero\t"; + AsciiDirective = "\t.ascii\t"; + AscizDirective = "\t.asciz\t"; + Data8bitsDirective = "\t.byte\t"; + Data16bitsDirective = "\t.short\t"; + Data32bitsDirective = "\t.long\t"; + Data64bitsDirective = "\t.quad\t"; + SunStyleELFSectionSwitchSyntax = false; + UsesELFSectionDirectiveForBSS = false; + AlignDirective = "\t.align\t"; + AlignmentIsInBytes = true; + TextAlignFillValue = 0; + GPRel32Directive = 0; + GlobalDirective = "\t.globl\t"; + HasSetDirective = true; + HasAggressiveSymbolFolding = true; + HasLCOMMDirective = false; + COMMDirectiveAlignmentIsInBytes = true; + HasDotTypeDotSizeDirective = true; + HasSingleParameterDotFile = true; + HasNoDeadStrip = false; + HasSymbolResolver = false; + WeakRefDirective = 0; + WeakDefDirective = 0; + LinkOnceDirective = 0; + HiddenVisibilityAttr = MCSA_Hidden; + HiddenDeclarationVisibilityAttr = MCSA_Hidden; + ProtectedVisibilityAttr = MCSA_Protected; + HasLEB128 = false; + SupportsDebugInformation = false; + ExceptionsType = ExceptionHandling::None; + DwarfRequiresFrameSection = true; + DwarfUsesInlineInfoSection = false; + DwarfUsesAbsoluteLabelForStmtList = true; + DwarfSectionOffsetDirective = 0; + DwarfUsesLabelOffsetForRanges = true; + HasMicrosoftFastStdCallMangling = false; + + AsmTransCBE = 0; +} + +MCAsmInfo::~MCAsmInfo() { +} + + +unsigned MCAsmInfo::getULEB128Size(unsigned Value) { + unsigned Size = 0; + do { + Value >>= 7; + Size += sizeof(int8_t); + } while (Value); + return Size; +} + +unsigned MCAsmInfo::getSLEB128Size(int Value) { + unsigned Size = 0; + int Sign = Value >> (8 * sizeof(Value) - 1); + bool IsMore; + + do { + unsigned Byte = Value & 0x7f; + Value >>= 7; + IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; + Size += sizeof(int8_t); + } while (IsMore); + return Size; +} diff --git a/final/lib/MC/MCAsmInfoCOFF.cpp b/final/lib/MC/MCAsmInfoCOFF.cpp new file mode 100644 index 00000000000..7fc7d7abb23 --- /dev/null +++ b/final/lib/MC/MCAsmInfoCOFF.cpp @@ -0,0 +1,37 @@ +//===-- MCAsmInfoCOFF.cpp - COFF asm properties -----------------*- 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 target asm properties related what form asm statements +// should take in general on COFF-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoCOFF.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +MCAsmInfoCOFF::MCAsmInfoCOFF() { + GlobalPrefix = "_"; + COMMDirectiveAlignmentIsInBytes = false; + HasLCOMMDirective = true; + HasDotTypeDotSizeDirective = false; + HasSingleParameterDotFile = false; + PrivateGlobalPrefix = "L"; // Prefix for private global symbols + WeakRefDirective = "\t.weak\t"; + LinkOnceDirective = "\t.linkonce discard\n"; + + // Doesn't support visibility: + HiddenVisibilityAttr = ProtectedVisibilityAttr = MCSA_Invalid; + + // Set up DWARF directives + HasLEB128 = true; // Target asm supports leb128 directives (little-endian) + SupportsDebugInformation = true; + DwarfSectionOffsetDirective = "\t.secrel32\t"; + HasMicrosoftFastStdCallMangling = true; +} diff --git a/final/lib/MC/MCAsmInfoDarwin.cpp b/final/lib/MC/MCAsmInfoDarwin.cpp new file mode 100644 index 00000000000..526ad0da42a --- /dev/null +++ b/final/lib/MC/MCAsmInfoDarwin.cpp @@ -0,0 +1,59 @@ +//===-- MCAsmInfoDarwin.cpp - Darwin asm properties -------------*- 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 target asm properties related what form asm statements +// should take in general on Darwin-based targets +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfoDarwin.h" +using namespace llvm; + +MCAsmInfoDarwin::MCAsmInfoDarwin() { + // Common settings for all Darwin targets. + // Syntax: + GlobalPrefix = "_"; + PrivateGlobalPrefix = "L"; + LinkerPrivateGlobalPrefix = "l"; + AllowQuotesInName = true; + HasSingleParameterDotFile = false; + HasSubsectionsViaSymbols = true; + + AlignmentIsInBytes = false; + COMMDirectiveAlignmentIsInBytes = false; + InlineAsmStart = " InlineAsm Start"; + InlineAsmEnd = " InlineAsm End"; + + // Directives: + WeakDefDirective = "\t.weak_definition "; + WeakRefDirective = "\t.weak_reference "; + ZeroDirective = "\t.space\t"; // ".space N" emits N zeros. + HasMachoZeroFillDirective = true; // Uses .zerofill + HasMachoTBSSDirective = true; // Uses .tbss + HasStaticCtorDtorReferenceInStaticMode = true; + + // FIXME: Darwin 10 and newer don't need this. + LinkerRequiresNonEmptyDwarfLines = true; + + // FIXME: Change this once MC is the system assembler. + HasAggressiveSymbolFolding = false; + + HiddenVisibilityAttr = MCSA_PrivateExtern; + HiddenDeclarationVisibilityAttr = MCSA_Invalid; + // Doesn't support protected visibility. + ProtectedVisibilityAttr = MCSA_Global; + + HasDotTypeDotSizeDirective = false; + HasNoDeadStrip = true; + HasSymbolResolver = true; + + DwarfUsesAbsoluteLabelForStmtList = false; + DwarfUsesLabelOffsetForRanges = false; +} + diff --git a/final/lib/MC/MCAsmStreamer.cpp b/final/lib/MC/MCAsmStreamer.cpp new file mode 100644 index 00000000000..c7ecf53c7f3 --- /dev/null +++ b/final/lib/MC/MCAsmStreamer.cpp @@ -0,0 +1,974 @@ +//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include +using namespace llvm; + +namespace { + +class MCAsmStreamer : public MCStreamer { + formatted_raw_ostream &OS; + const MCAsmInfo &MAI; + OwningPtr InstPrinter; + OwningPtr Emitter; + OwningPtr AsmBackend; + + SmallString<128> CommentToEmit; + raw_svector_ostream CommentStream; + + unsigned IsVerboseAsm : 1; + unsigned ShowInst : 1; + unsigned UseLoc : 1; + + bool needsSet(const MCExpr *Value); + +public: + MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, + bool isVerboseAsm, + bool useLoc, + MCInstPrinter *printer, MCCodeEmitter *emitter, + TargetAsmBackend *asmbackend, + bool showInst) + : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), + InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend), + CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), + ShowInst(showInst), UseLoc(useLoc) { + if (InstPrinter && IsVerboseAsm) + InstPrinter->setCommentStream(CommentStream); + } + ~MCAsmStreamer() {} + + inline void EmitEOL() { + // If we don't have any comments, just emit a \n. + if (!IsVerboseAsm) { + OS << '\n'; + return; + } + EmitCommentsAndEOL(); + } + void EmitCommentsAndEOL(); + + /// isVerboseAsm - Return true if this streamer supports verbose assembly at + /// all. + virtual bool isVerboseAsm() const { return IsVerboseAsm; } + + /// hasRawTextSupport - We support EmitRawText. + virtual bool hasRawTextSupport() const { return true; } + + /// AddComment - Add a comment that can be emitted to the generated .s + /// file if applicable as a QoI issue to make the output of the compiler + /// more readable. This only affects the MCAsmStreamer, and only when + /// verbose assembly output is enabled. + virtual void AddComment(const Twine &T); + + /// AddEncodingComment - Add a comment showing the encoding of an instruction. + virtual void AddEncodingComment(const MCInst &Inst); + + /// GetCommentOS - Return a raw_ostream that comments can be written to. + /// Unlike AddComment, you are required to terminate comments with \n if you + /// use this method. + virtual raw_ostream &GetCommentOS() { + if (!IsVerboseAsm) + return nulls(); // Discard comments unless in verbose asm mode. + return CommentStream; + } + + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. + virtual void AddBlankLine() { + EmitEOL(); + } + + /// @name MCStreamer Interface + /// @{ + + virtual void ChangeSection(const MCSection *Section); + + virtual void InitSections() { + // FIXME, this is MachO specific, but the testsuite + // expects this. + SwitchSection(getContext().getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText())); + } + + virtual void EmitLabel(MCSymbol *Symbol); + + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label); + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); + virtual void EmitCOFFSymbolStorageClass(int StorageClass); + virtual void EmitCOFFSymbolType(int Type); + virtual void EndCOFFSymbolDef(); + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + + /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// + /// @param Symbol - The common symbol to emit. + /// @param Size - The size of the common symbol. + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0); + + virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0); + + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace); + virtual void EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace = 0); + + virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + + virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); + + virtual void EmitGPRel32Value(const MCExpr *Value); + + + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace); + + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0); + + virtual void EmitFileDirective(StringRef Filename); + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator); + + virtual bool EmitCFIStartProc(); + virtual bool EmitCFIEndProc(); + virtual bool EmitCFIDefCfaOffset(int64_t Offset); + virtual bool EmitCFIDefCfaRegister(int64_t Register); + virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); + virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + + virtual void EmitFnStart(); + virtual void EmitFnEnd(); + virtual void EmitCantUnwind(); + virtual void EmitPersonality(const MCSymbol *Personality); + virtual void EmitHandlerData(); + virtual void EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); + virtual void EmitPad(int64_t Offset); + virtual void EmitRegSave(const SmallVectorImpl &RegList, bool); + + + virtual void EmitInstruction(const MCInst &Inst); + + /// EmitRawText - If this file is backed by an assembly streamer, this dumps + /// the specified string in the output .s file. This capability is + /// indicated by the hasRawTextSupport() predicate. + virtual void EmitRawText(StringRef String); + + virtual void Finish(); + + /// @} +}; + +} // end anonymous namespace. + +/// AddComment - Add a comment that can be emitted to the generated .s +/// file if applicable as a QoI issue to make the output of the compiler +/// more readable. This only affects the MCAsmStreamer, and only when +/// verbose assembly output is enabled. +void MCAsmStreamer::AddComment(const Twine &T) { + if (!IsVerboseAsm) return; + + // Make sure that CommentStream is flushed. + CommentStream.flush(); + + T.toVector(CommentToEmit); + // Each comment goes on its own line. + CommentToEmit.push_back('\n'); + + // Tell the comment stream that the vector changed underneath it. + CommentStream.resync(); +} + +void MCAsmStreamer::EmitCommentsAndEOL() { + if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { + OS << '\n'; + return; + } + + CommentStream.flush(); + StringRef Comments = CommentToEmit.str(); + + assert(Comments.back() == '\n' && + "Comment array not newline terminated"); + do { + // Emit a line of comments. + OS.PadToColumn(MAI.getCommentColumn()); + size_t Position = Comments.find('\n'); + OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; + + Comments = Comments.substr(Position+1); + } while (!Comments.empty()); + + CommentToEmit.clear(); + // Tell the comment stream that the vector changed underneath it. + CommentStream.resync(); +} + +static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { + assert(Bytes && "Invalid size!"); + return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); +} + +void MCAsmStreamer::ChangeSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + Section->PrintSwitchToSection(MAI, OS); +} + +void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); + assert(getCurrentSection() && "Cannot emit before setting section!"); + + OS << *Symbol << MAI.getLabelSuffix(); + EmitEOL(); + Symbol->setSection(*getCurrentSection()); +} + +void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + switch (Flag) { + default: assert(0 && "Invalid flag!"); + case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; + case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; + case MCAF_Code16: OS << "\t.code\t16"; break; + case MCAF_Code32: OS << "\t.code\t32"; break; + } + EmitEOL(); +} + +void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { + // This needs to emit to a temporary string to get properly quoted + // MCSymbols when they have spaces in them. + OS << "\t.thumb_func"; + if (Func) + OS << '\t' << *Func; + EmitEOL(); +} + +void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + OS << *Symbol << " = " << *Value; + EmitEOL(); + + // FIXME: Lift context changes into super class. + Symbol->setVariableValue(Value); +} + +void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + OS << ".weakref " << *Alias << ", " << *Symbol; + EmitEOL(); +} + +void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) { + EmitDwarfSetLineAddr(LineDelta, Label, + getContext().getTargetAsmInfo().getPointerSize()); +} + +void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + switch (Attribute) { + case MCSA_Invalid: assert(0 && "Invalid symbol attribute"); + case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function + case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC + case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object + case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object + case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common + case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype + case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object + assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); + OS << "\t.type\t" << *Symbol << ',' + << ((MAI.getCommentString()[0] != '@') ? '@' : '%'); + switch (Attribute) { + default: assert(0 && "Unknown ELF .type"); + case MCSA_ELF_TypeFunction: OS << "function"; break; + case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; + case MCSA_ELF_TypeObject: OS << "object"; break; + case MCSA_ELF_TypeTLS: OS << "tls_object"; break; + case MCSA_ELF_TypeCommon: OS << "common"; break; + case MCSA_ELF_TypeNoType: OS << "no_type"; break; + case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; + } + EmitEOL(); + return; + case MCSA_Global: // .globl/.global + OS << MAI.getGlobalDirective(); + break; + case MCSA_Hidden: OS << "\t.hidden\t"; break; + case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; + case MCSA_Internal: OS << "\t.internal\t"; break; + case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; + case MCSA_Local: OS << "\t.local\t"; break; + case MCSA_NoDeadStrip: OS << "\t.no_dead_strip\t"; break; + case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; + case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; + case MCSA_Protected: OS << "\t.protected\t"; break; + case MCSA_Reference: OS << "\t.reference\t"; break; + case MCSA_Weak: OS << "\t.weak\t"; break; + case MCSA_WeakDefinition: OS << "\t.weak_definition\t"; break; + // .weak_reference + case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; + case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; + } + + OS << *Symbol; + EmitEOL(); +} + +void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + OS << ".desc" << ' ' << *Symbol << ',' << DescValue; + EmitEOL(); +} + +void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { + OS << "\t.def\t " << *Symbol << ';'; + EmitEOL(); +} + +void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { + OS << "\t.scl\t" << StorageClass << ';'; + EmitEOL(); +} + +void MCAsmStreamer::EmitCOFFSymbolType (int Type) { + OS << "\t.type\t" << Type << ';'; + EmitEOL(); +} + +void MCAsmStreamer::EndCOFFSymbolDef() { + OS << "\t.endef"; + EmitEOL(); +} + +void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + assert(MAI.hasDotTypeDotSizeDirective()); + OS << "\t.size\t" << *Symbol << ", " << *Value << '\n'; +} + +void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + OS << "\t.comm\t" << *Symbol << ',' << Size; + if (ByteAlignment != 0) { + if (MAI.getCOMMDirectiveAlignmentIsInBytes()) + OS << ',' << ByteAlignment; + else + OS << ',' << Log2_32(ByteAlignment); + } + EmitEOL(); +} + +/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. +/// +/// @param Symbol - The common symbol to emit. +/// @param Size - The size of the common symbol. +void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!"); + OS << "\t.lcomm\t" << *Symbol << ',' << Size; + EmitEOL(); +} + +void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned ByteAlignment) { + // Note: a .zerofill directive does not switch sections. + OS << ".zerofill "; + + // This is a mach-o specific directive. + const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); + OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); + + if (Symbol != NULL) { + OS << ',' << *Symbol << ',' << Size; + if (ByteAlignment != 0) + OS << ',' << Log2_32(ByteAlignment); + } + EmitEOL(); +} + +// .tbss sym, size, align +// This depends that the symbol has already been mangled from the original, +// e.g. _a. +void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + assert(Symbol != NULL && "Symbol shouldn't be NULL!"); + // Instead of using the Section we'll just use the shortcut. + // This is a mach-o specific directive and section. + OS << ".tbss " << *Symbol << ", " << Size; + + // Output align if we have it. We default to 1 so don't bother printing + // that. + if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); + + EmitEOL(); +} + +static inline char toOctal(int X) { return (X&7)+'0'; } + +static void PrintQuotedString(StringRef Data, raw_ostream &OS) { + OS << '"'; + + for (unsigned i = 0, e = Data.size(); i != e; ++i) { + unsigned char C = Data[i]; + if (C == '"' || C == '\\') { + OS << '\\' << (char)C; + continue; + } + + if (isprint((unsigned char)C)) { + OS << (char)C; + continue; + } + + switch (C) { + case '\b': OS << "\\b"; break; + case '\f': OS << "\\f"; break; + case '\n': OS << "\\n"; break; + case '\r': OS << "\\r"; break; + case '\t': OS << "\\t"; break; + default: + OS << '\\'; + OS << toOctal(C >> 6); + OS << toOctal(C >> 3); + OS << toOctal(C >> 0); + break; + } + } + + OS << '"'; +} + + +void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + assert(getCurrentSection() && "Cannot emit contents before setting section!"); + if (Data.empty()) return; + + if (Data.size() == 1) { + OS << MAI.getData8bitsDirective(AddrSpace); + OS << (unsigned)(unsigned char)Data[0]; + EmitEOL(); + return; + } + + // If the data ends with 0 and the target supports .asciz, use it, otherwise + // use .ascii + if (MAI.getAscizDirective() && Data.back() == 0) { + OS << MAI.getAscizDirective(); + Data = Data.substr(0, Data.size()-1); + } else { + OS << MAI.getAsciiDirective(); + } + + OS << ' '; + PrintQuotedString(Data, OS); + EmitEOL(); +} + +void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace) { + EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); +} + +void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) { + assert(getCurrentSection() && "Cannot emit contents before setting section!"); + assert(!isPCRel && "Cannot emit pc relative relocations!"); + const char *Directive = 0; + switch (Size) { + default: break; + case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; + case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; + case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; + case 8: + Directive = MAI.getData64bitsDirective(AddrSpace); + // If the target doesn't support 64-bit data, emit as two 32-bit halves. + if (Directive) break; + int64_t IntValue; + if (!Value->EvaluateAsAbsolute(IntValue)) + report_fatal_error("Don't know how to emit this value."); + if (getContext().getTargetAsmInfo().isLittleEndian()) { + EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); + } else { + EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); + EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); + } + return; + } + + assert(Directive && "Invalid size for machine code value!"); + OS << Directive << *Value; + EmitEOL(); +} + +void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue)) { + EmitULEB128IntValue(IntValue, AddrSpace); + return; + } + assert(MAI.hasLEB128() && "Cannot print a .uleb"); + OS << ".uleb128 " << *Value; + EmitEOL(); +} + +void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue)) { + EmitSLEB128IntValue(IntValue, AddrSpace); + return; + } + assert(MAI.hasLEB128() && "Cannot print a .sleb"); + OS << ".sleb128 " << *Value; + EmitEOL(); +} + +void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { + assert(MAI.getGPRel32Directive() != 0); + OS << MAI.getGPRel32Directive() << *Value; + EmitEOL(); +} + + +/// EmitFill - Emit NumBytes bytes worth of the value specified by +/// FillValue. This implements directives such as '.space'. +void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace) { + if (NumBytes == 0) return; + + if (AddrSpace == 0) + if (const char *ZeroDirective = MAI.getZeroDirective()) { + OS << ZeroDirective << NumBytes; + if (FillValue != 0) + OS << ',' << (int)FillValue; + EmitEOL(); + return; + } + + // Emit a byte at a time. + MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); +} + +void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + // Some assemblers don't support non-power of two alignments, so we always + // emit alignments as a power of two if possible. + if (isPowerOf2_32(ByteAlignment)) { + switch (ValueSize) { + default: llvm_unreachable("Invalid size for machine code value!"); + case 1: OS << MAI.getAlignDirective(); break; + // FIXME: use MAI for this! + case 2: OS << ".p2alignw "; break; + case 4: OS << ".p2alignl "; break; + case 8: llvm_unreachable("Unsupported alignment size!"); + } + + if (MAI.getAlignmentIsInBytes()) + OS << ByteAlignment; + else + OS << Log2_32(ByteAlignment); + + if (Value || MaxBytesToEmit) { + OS << ", 0x"; + OS.write_hex(truncateToSize(Value, ValueSize)); + + if (MaxBytesToEmit) + OS << ", " << MaxBytesToEmit; + } + EmitEOL(); + return; + } + + // Non-power of two alignment. This is not widely supported by assemblers. + // FIXME: Parameterize this based on MAI. + switch (ValueSize) { + default: llvm_unreachable("Invalid size for machine code value!"); + case 1: OS << ".balign"; break; + case 2: OS << ".balignw"; break; + case 4: OS << ".balignl"; break; + case 8: llvm_unreachable("Unsupported alignment size!"); + } + + OS << ' ' << ByteAlignment; + OS << ", " << truncateToSize(Value, ValueSize); + if (MaxBytesToEmit) + OS << ", " << MaxBytesToEmit; + EmitEOL(); +} + +void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // Emit with a text fill value. + EmitValueToAlignment(ByteAlignment, MAI.getTextAlignFillValue(), + 1, MaxBytesToEmit); +} + +void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, + unsigned char Value) { + // FIXME: Verify that Offset is associated with the current section. + OS << ".org " << *Offset << ", " << (unsigned) Value; + EmitEOL(); +} + + +void MCAsmStreamer::EmitFileDirective(StringRef Filename) { + assert(MAI.hasSingleParameterDotFile()); + OS << "\t.file\t"; + PrintQuotedString(Filename, OS); + EmitEOL(); +} + +bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ + if (UseLoc) { + OS << "\t.file\t" << FileNo << ' '; + PrintQuotedString(Filename, OS); + EmitEOL(); + } + return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename); +} + +void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator) { + this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator); + if (!UseLoc) + return; + + OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; + if (Flags & DWARF2_FLAG_BASIC_BLOCK) + OS << " basic_block"; + if (Flags & DWARF2_FLAG_PROLOGUE_END) + OS << " prologue_end"; + if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) + OS << " epilogue_begin"; + + unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); + if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { + OS << " is_stmt "; + + if (Flags & DWARF2_FLAG_IS_STMT) + OS << "1"; + else + OS << "0"; + } + + if (Isa) + OS << "isa " << Isa; + if (Discriminator) + OS << "discriminator " << Discriminator; + EmitEOL(); +} + +bool MCAsmStreamer::EmitCFIStartProc() { + if (this->MCStreamer::EmitCFIStartProc()) + return true; + + OS << "\t.cfi_startproc"; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIEndProc() { + if (this->MCStreamer::EmitCFIEndProc()) + return true; + + OS << "\t.cfi_endproc"; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + if (this->MCStreamer::EmitCFIDefCfaOffset(Offset)) + return true; + + OS << "\t.cfi_def_cfa_offset " << Offset; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { + if (this->MCStreamer::EmitCFIDefCfaRegister(Register)) + return true; + + OS << "\t.cfi_def_cfa_register " << Register; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + if (this->MCStreamer::EmitCFIOffset(Register, Offset)) + return true; + + OS << "\t.cfi_offset " << Register << ", " << Offset; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, + unsigned Encoding) { + if (this->MCStreamer::EmitCFIPersonality(Sym, Encoding)) + return true; + + OS << "\t.cfi_personality " << Encoding << ", " << *Sym; + EmitEOL(); + + return false; +} + +bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { + if (this->MCStreamer::EmitCFILsda(Sym, Encoding)) + return true; + + OS << "\t.cfi_lsda " << Encoding << ", " << *Sym; + EmitEOL(); + + return false; +} + +void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { + raw_ostream &OS = GetCommentOS(); + SmallString<256> Code; + SmallVector Fixups; + raw_svector_ostream VecOS(Code); + Emitter->EncodeInstruction(Inst, VecOS, Fixups); + VecOS.flush(); + + // If we are showing fixups, create symbolic markers in the encoded + // representation. We do this by making a per-bit map to the fixup item index, + // then trying to display it as nicely as possible. + SmallVector FixupMap; + FixupMap.resize(Code.size() * 8); + for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) + FixupMap[i] = 0; + + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + MCFixup &F = Fixups[i]; + const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); + for (unsigned j = 0; j != Info.TargetSize; ++j) { + unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; + assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); + FixupMap[Index] = 1 + i; + } + } + + // FIXME: Node the fixup comments for Thumb2 are completely bogus since the + // high order halfword of a 32-bit Thumb2 instruction is emitted first. + OS << "encoding: ["; + for (unsigned i = 0, e = Code.size(); i != e; ++i) { + if (i) + OS << ','; + + // See if all bits are the same map entry. + uint8_t MapEntry = FixupMap[i * 8 + 0]; + for (unsigned j = 1; j != 8; ++j) { + if (FixupMap[i * 8 + j] == MapEntry) + continue; + + MapEntry = uint8_t(~0U); + break; + } + + if (MapEntry != uint8_t(~0U)) { + if (MapEntry == 0) { + OS << format("0x%02x", uint8_t(Code[i])); + } else { + if (Code[i]) { + // FIXME: Some of the 8 bits require fix up. + OS << format("0x%02x", uint8_t(Code[i])) << '\'' + << char('A' + MapEntry - 1) << '\''; + } else + OS << char('A' + MapEntry - 1); + } + } else { + // Otherwise, write out in binary. + OS << "0b"; + for (unsigned j = 8; j--;) { + unsigned Bit = (Code[i] >> j) & 1; + + unsigned FixupBit; + if (getContext().getTargetAsmInfo().isLittleEndian()) + FixupBit = i * 8 + j; + else + FixupBit = i * 8 + (7-j); + + if (uint8_t MapEntry = FixupMap[FixupBit]) { + assert(Bit == 0 && "Encoder wrote into fixed up bit!"); + OS << char('A' + MapEntry - 1); + } else + OS << Bit; + } + } + } + OS << "]\n"; + + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + MCFixup &F = Fixups[i]; + const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); + OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() + << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; + } +} + +void MCAsmStreamer::EmitFnStart() { + OS << "\t.fnstart"; + EmitEOL(); +} + +void MCAsmStreamer::EmitFnEnd() { + OS << "\t.fnend"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCantUnwind() { + OS << "\t.cantunwind"; + EmitEOL(); +} + +void MCAsmStreamer::EmitHandlerData() { + OS << "\t.handlerdata"; + EmitEOL(); +} + +void MCAsmStreamer::EmitPersonality(const MCSymbol *Personality) { + OS << "\t.personality " << Personality->getName(); + EmitEOL(); +} + +void MCAsmStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { + OS << "\t.setfp\t" << InstPrinter->getRegName(FpReg) + << ", " << InstPrinter->getRegName(SpReg); + if (Offset) + OS << ", #" << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitPad(int64_t Offset) { + OS << "\t.pad\t#" << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitRegSave(const SmallVectorImpl &RegList, + bool isVector) { + assert(RegList.size() && "RegList should not be empty"); + if (isVector) + OS << "\t.vsave\t{"; + else + OS << "\t.save\t{"; + + OS << InstPrinter->getRegName(RegList[0]); + + for (unsigned i = 1, e = RegList.size(); i != e; ++i) + OS << ", " << InstPrinter->getRegName(RegList[i]); + + OS << "}"; + EmitEOL(); +} + +void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { + assert(getCurrentSection() && "Cannot emit contents before setting section!"); + + if (!UseLoc) + MCLineEntry::Make(this, getCurrentSection()); + + // Show the encoding in a comment if we have a code emitter. + if (Emitter) + AddEncodingComment(Inst); + + // Show the MCInst if enabled. + if (ShowInst) { + Inst.dump_pretty(GetCommentOS(), &MAI, InstPrinter.get(), "\n "); + GetCommentOS() << "\n"; + } + + // If we have an AsmPrinter, use that to print, otherwise print the MCInst. + if (InstPrinter) + InstPrinter->printInst(&Inst, OS); + else + Inst.print(OS, &MAI); + EmitEOL(); +} + +/// EmitRawText - If this file is backed by an assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCAsmStreamer::EmitRawText(StringRef String) { + if (!String.empty() && String.back() == '\n') + String = String.substr(0, String.size()-1); + OS << String; + EmitEOL(); +} + +void MCAsmStreamer::Finish() { + // Dump out the dwarf file & directory tables and line tables. + if (getContext().hasDwarfFiles() && !UseLoc) + MCDwarfFileTable::Emit(this); +} + +MCStreamer *llvm::createAsmStreamer(MCContext &Context, + formatted_raw_ostream &OS, + bool isVerboseAsm, bool useLoc, + MCInstPrinter *IP, MCCodeEmitter *CE, + TargetAsmBackend *TAB, bool ShowInst) { + return new MCAsmStreamer(Context, OS, isVerboseAsm, useLoc, + IP, CE, TAB, ShowInst); +} diff --git a/final/lib/MC/MCAssembler.cpp b/final/lib/MC/MCAssembler.cpp new file mode 100644 index 00000000000..99926460422 --- /dev/null +++ b/final/lib/MC/MCAssembler.cpp @@ -0,0 +1,949 @@ +//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "assembler" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" + +#include +using namespace llvm; + +namespace { +namespace stats { +STATISTIC(EmittedFragments, "Number of emitted assembler fragments"); +STATISTIC(EvaluateFixup, "Number of evaluated fixups"); +STATISTIC(FragmentLayouts, "Number of fragment layouts"); +STATISTIC(ObjectBytes, "Number of emitted object file bytes"); +STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); +STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); +} +} + +// FIXME FIXME FIXME: There are number of places in this file where we convert +// what is a 64-bit assembler value used for computation into a value in the +// object file, which may truncate it. We should detect that truncation where +// invalid and report errors back. + +/* *** */ + +MCAsmLayout::MCAsmLayout(MCAssembler &Asm) + : Assembler(Asm), LastValidFragment() + { + // Compute the section layout order. Virtual sections must go last. + for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) + if (!it->getSection().isVirtualSection()) + SectionOrder.push_back(&*it); + for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) + if (it->getSection().isVirtualSection()) + SectionOrder.push_back(&*it); +} + +bool MCAsmLayout::isFragmentUpToDate(const MCFragment *F) const { + const MCSectionData &SD = *F->getParent(); + const MCFragment *LastValid = LastValidFragment.lookup(&SD); + if (!LastValid) + return false; + assert(LastValid->getParent() == F->getParent()); + return F->getLayoutOrder() <= LastValid->getLayoutOrder(); +} + +void MCAsmLayout::Invalidate(MCFragment *F) { + // If this fragment wasn't already up-to-date, we don't need to do anything. + if (!isFragmentUpToDate(F)) + return; + + // Otherwise, reset the last valid fragment to this fragment. + const MCSectionData &SD = *F->getParent(); + LastValidFragment[&SD] = F; +} + +void MCAsmLayout::EnsureValid(const MCFragment *F) const { + MCSectionData &SD = *F->getParent(); + + MCFragment *Cur = LastValidFragment[&SD]; + if (!Cur) + Cur = &*SD.begin(); + else + Cur = Cur->getNextNode(); + + // Advance the layout position until the fragment is up-to-date. + while (!isFragmentUpToDate(F)) { + const_cast(this)->LayoutFragment(Cur); + Cur = Cur->getNextNode(); + } +} + +uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { + EnsureValid(F); + assert(F->Offset != ~UINT64_C(0) && "Address not set!"); + return F->Offset; +} + +uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { + assert(SD->getFragment() && "Invalid getOffset() on undefined symbol!"); + return getFragmentOffset(SD->getFragment()) + SD->getOffset(); +} + +uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { + // The size is the last fragment's end offset. + const MCFragment &F = SD->getFragmentList().back(); + return getFragmentOffset(&F) + getAssembler().ComputeFragmentSize(*this, F); +} + +uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { + // Virtual sections have no file size. + if (SD->getSection().isVirtualSection()) + return 0; + + // Otherwise, the file size is the same as the address space size. + return getSectionAddressSize(SD); +} + +/* *** */ + +MCFragment::MCFragment() : Kind(FragmentType(~0)) { +} + +MCFragment::~MCFragment() { +} + +MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent) + : Kind(_Kind), Parent(_Parent), Atom(0), Offset(~UINT64_C(0)) +{ + if (Parent) + Parent->getFragmentList().push_back(this); +} + +/* *** */ + +MCSectionData::MCSectionData() : Section(0) {} + +MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) + : Section(&_Section), + Ordinal(~UINT32_C(0)), + Alignment(1), + HasInstructions(false) +{ + if (A) + A->getSectionList().push_back(this); +} + +/* *** */ + +MCSymbolData::MCSymbolData() : Symbol(0) {} + +MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, + uint64_t _Offset, MCAssembler *A) + : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), + IsExternal(false), IsPrivateExtern(false), + CommonSize(0), SymbolSize(0), CommonAlign(0), + Flags(0), Index(0) +{ + if (A) + A->getSymbolList().push_back(this); +} + +/* *** */ + +MCAssembler::MCAssembler(MCContext &Context_, TargetAsmBackend &Backend_, + MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, + raw_ostream &OS_) + : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), + OS(OS_), RelaxAll(false), NoExecStack(false), SubsectionsViaSymbols(false) +{ +} + +MCAssembler::~MCAssembler() { +} + +bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { + // Non-temporary labels should always be visible to the linker. + if (!Symbol.isTemporary()) + return true; + + // Absolute temporary labels are never visible. + if (!Symbol.isInSection()) + return false; + + // Otherwise, check if the section requires symbols even for temporary labels. + return getBackend().doesSectionRequireSymbols(Symbol.getSection()); +} + +const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { + // Linker visible symbols define atoms. + if (isSymbolLinkerVisible(SD->getSymbol())) + return SD; + + // Absolute and undefined symbols have no defining atom. + if (!SD->getFragment()) + return 0; + + // Non-linker visible symbols in sections which can't be atomized have no + // defining atom. + if (!getBackend().isSectionAtomizable( + SD->getFragment()->getParent()->getSection())) + return 0; + + // Otherwise, return the atom for the containing fragment. + return SD->getFragment()->getAtom(); +} + +bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value) const { + ++stats::EvaluateFixup; + + if (!Fixup.getValue()->EvaluateAsRelocatable(Target, Layout)) + report_fatal_error("expected relocatable expression"); + + bool IsPCRel = Backend.getFixupKindInfo( + Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; + + bool IsResolved; + if (IsPCRel) { + if (Target.getSymB()) { + IsResolved = false; + } else if (!Target.getSymA()) { + IsResolved = false; + } else { + const MCSymbolRefExpr *A = Target.getSymA(); + const MCSymbol &SA = A->getSymbol(); + if (A->getKind() != MCSymbolRefExpr::VK_None || + SA.AliasedSymbol().isUndefined()) { + IsResolved = false; + } else { + const MCSymbolData &DataA = getSymbolData(SA); + IsResolved = + getWriter().IsSymbolRefDifferenceFullyResolvedImpl(*this, DataA, + *DF, false, true); + } + } + } else { + IsResolved = Target.isAbsolute(); + } + + Value = Target.getConstant(); + + bool IsThumb = false; + if (const MCSymbolRefExpr *A = Target.getSymA()) { + const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); + if (Sym.isDefined()) + Value += Layout.getSymbolOffset(&getSymbolData(Sym)); + if (isThumbFunc(&Sym)) + IsThumb = true; + } + if (const MCSymbolRefExpr *B = Target.getSymB()) { + const MCSymbol &Sym = B->getSymbol().AliasedSymbol(); + if (Sym.isDefined()) + Value -= Layout.getSymbolOffset(&getSymbolData(Sym)); + } + + + bool ShouldAlignPC = Backend.getFixupKindInfo(Fixup.getKind()).Flags & + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits; + assert((ShouldAlignPC ? IsPCRel : true) && + "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!"); + + if (IsPCRel) { + uint32_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset(); + + // A number of ARM fixups in Thumb mode require that the effective PC + // address be determined as the 32-bit aligned version of the actual offset. + if (ShouldAlignPC) Offset &= ~0x3; + Value -= Offset; + } + + // ARM fixups based from a thumb function address need to have the low + // bit set. The actual value is always at least 16-bit aligned, so the + // low bit is normally clear and available for use as an ISA flag for + // interworking. + if (IsThumb) + Value |= 1; + + return IsResolved; +} + +uint64_t MCAssembler::ComputeFragmentSize(const MCAsmLayout &Layout, + const MCFragment &F) const { + switch (F.getKind()) { + case MCFragment::FT_Data: + return cast(F).getContents().size(); + case MCFragment::FT_Fill: + return cast(F).getSize(); + case MCFragment::FT_Inst: + return cast(F).getInstSize(); + + case MCFragment::FT_LEB: + return cast(F).getContents().size(); + + case MCFragment::FT_Align: { + const MCAlignFragment &AF = cast(F); + unsigned Offset = Layout.getFragmentOffset(&AF); + unsigned Size = OffsetToAlignment(Offset, AF.getAlignment()); + if (Size > AF.getMaxBytesToEmit()) + return 0; + return Size; + } + + case MCFragment::FT_Org: { + MCOrgFragment &OF = cast(F); + int64_t TargetLocation; + if (!OF.getOffset().EvaluateAsAbsolute(TargetLocation, Layout)) + report_fatal_error("expected assembly-time absolute expression"); + + // FIXME: We need a way to communicate this error. + uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); + int64_t Size = TargetLocation - FragmentOffset; + if (Size < 0 || Size >= 0x40000000) + report_fatal_error("invalid .org offset '" + Twine(TargetLocation) + + "' (at offset '" + Twine(FragmentOffset) + "')"); + return Size; + } + + case MCFragment::FT_Dwarf: + return cast(F).getContents().size(); + case MCFragment::FT_DwarfFrame: + return cast(F).getContents().size(); + } + + assert(0 && "invalid fragment kind"); + return 0; +} + +void MCAsmLayout::LayoutFragment(MCFragment *F) { + MCFragment *Prev = F->getPrevNode(); + + // We should never try to recompute something which is up-to-date. + assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!"); + // We should never try to compute the fragment layout if it's predecessor + // isn't up-to-date. + assert((!Prev || isFragmentUpToDate(Prev)) && + "Attempt to compute fragment before it's predecessor!"); + + ++stats::FragmentLayouts; + + // Compute fragment offset and size. + uint64_t Offset = 0; + if (Prev) + Offset += Prev->Offset + getAssembler().ComputeFragmentSize(*this, *Prev); + + F->Offset = Offset; + LastValidFragment[F->getParent()] = F; +} + +/// WriteFragmentData - Write the \arg F data to the output file. +static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment &F) { + MCObjectWriter *OW = &Asm.getWriter(); + uint64_t Start = OW->getStream().tell(); + (void) Start; + + ++stats::EmittedFragments; + + // FIXME: Embed in fragments instead? + uint64_t FragmentSize = Asm.ComputeFragmentSize(Layout, F); + switch (F.getKind()) { + case MCFragment::FT_Align: { + MCAlignFragment &AF = cast(F); + uint64_t Count = FragmentSize / AF.getValueSize(); + + assert(AF.getValueSize() && "Invalid virtual align in concrete fragment!"); + + // FIXME: This error shouldn't actually occur (the front end should emit + // multiple .align directives to enforce the semantics it wants), but is + // severe enough that we want to report it. How to handle this? + if (Count * AF.getValueSize() != FragmentSize) + report_fatal_error("undefined .align directive, value size '" + + Twine(AF.getValueSize()) + + "' is not a divisor of padding size '" + + Twine(FragmentSize) + "'"); + + // See if we are aligning with nops, and if so do that first to try to fill + // the Count bytes. Then if that did not fill any bytes or there are any + // bytes left to fill use the the Value and ValueSize to fill the rest. + // If we are aligning with nops, ask that target to emit the right data. + if (AF.hasEmitNops()) { + if (!Asm.getBackend().WriteNopData(Count, OW)) + report_fatal_error("unable to write nop sequence of " + + Twine(Count) + " bytes"); + break; + } + + // Otherwise, write out in multiples of the value size. + for (uint64_t i = 0; i != Count; ++i) { + switch (AF.getValueSize()) { + default: + assert(0 && "Invalid size!"); + case 1: OW->Write8 (uint8_t (AF.getValue())); break; + case 2: OW->Write16(uint16_t(AF.getValue())); break; + case 4: OW->Write32(uint32_t(AF.getValue())); break; + case 8: OW->Write64(uint64_t(AF.getValue())); break; + } + } + break; + } + + case MCFragment::FT_Data: { + MCDataFragment &DF = cast(F); + assert(FragmentSize == DF.getContents().size() && "Invalid size!"); + OW->WriteBytes(DF.getContents().str()); + break; + } + + case MCFragment::FT_Fill: { + MCFillFragment &FF = cast(F); + + assert(FF.getValueSize() && "Invalid virtual align in concrete fragment!"); + + for (uint64_t i = 0, e = FF.getSize() / FF.getValueSize(); i != e; ++i) { + switch (FF.getValueSize()) { + default: + assert(0 && "Invalid size!"); + case 1: OW->Write8 (uint8_t (FF.getValue())); break; + case 2: OW->Write16(uint16_t(FF.getValue())); break; + case 4: OW->Write32(uint32_t(FF.getValue())); break; + case 8: OW->Write64(uint64_t(FF.getValue())); break; + } + } + break; + } + + case MCFragment::FT_Inst: { + MCInstFragment &IF = cast(F); + OW->WriteBytes(StringRef(IF.getCode().begin(), IF.getCode().size())); + break; + } + + case MCFragment::FT_LEB: { + MCLEBFragment &LF = cast(F); + OW->WriteBytes(LF.getContents().str()); + break; + } + + case MCFragment::FT_Org: { + MCOrgFragment &OF = cast(F); + + for (uint64_t i = 0, e = FragmentSize; i != e; ++i) + OW->Write8(uint8_t(OF.getValue())); + + break; + } + + case MCFragment::FT_Dwarf: { + const MCDwarfLineAddrFragment &OF = cast(F); + OW->WriteBytes(OF.getContents().str()); + break; + } + case MCFragment::FT_DwarfFrame: { + const MCDwarfCallFrameFragment &CF = cast(F); + OW->WriteBytes(CF.getContents().str()); + break; + } + } + + assert(OW->getStream().tell() - Start == FragmentSize); +} + +void MCAssembler::WriteSectionData(const MCSectionData *SD, + const MCAsmLayout &Layout) const { + // Ignore virtual sections. + if (SD->getSection().isVirtualSection()) { + assert(Layout.getSectionFileSize(SD) == 0 && "Invalid size for section!"); + + // Check that contents are only things legal inside a virtual section. + for (MCSectionData::const_iterator it = SD->begin(), + ie = SD->end(); it != ie; ++it) { + switch (it->getKind()) { + default: + assert(0 && "Invalid fragment in virtual section!"); + case MCFragment::FT_Data: { + // Check that we aren't trying to write a non-zero contents (or fixups) + // into a virtual section. This is to support clients which use standard + // directives to fill the contents of virtual sections. + MCDataFragment &DF = cast(*it); + assert(DF.fixup_begin() == DF.fixup_end() && + "Cannot have fixups in virtual section!"); + for (unsigned i = 0, e = DF.getContents().size(); i != e; ++i) + assert(DF.getContents()[i] == 0 && + "Invalid data value for virtual section!"); + break; + } + case MCFragment::FT_Align: + // Check that we aren't trying to write a non-zero value into a virtual + // section. + assert((!cast(it)->getValueSize() || + !cast(it)->getValue()) && + "Invalid align in virtual section!"); + break; + case MCFragment::FT_Fill: + assert(!cast(it)->getValueSize() && + "Invalid fill in virtual section!"); + break; + } + } + + return; + } + + uint64_t Start = getWriter().getStream().tell(); + (void) Start; + + for (MCSectionData::const_iterator it = SD->begin(), + ie = SD->end(); it != ie; ++it) + WriteFragmentData(*this, Layout, *it); + + assert(getWriter().getStream().tell() - Start == + Layout.getSectionAddressSize(SD)); +} + + +uint64_t MCAssembler::HandleFixup(const MCAsmLayout &Layout, + MCFragment &F, + const MCFixup &Fixup) { + // Evaluate the fixup. + MCValue Target; + uint64_t FixedValue; + if (!EvaluateFixup(Layout, Fixup, &F, Target, FixedValue)) { + // The fixup was unresolved, we need a relocation. Inform the object + // writer of the relocation, and give it an opportunity to adjust the + // fixup value if need be. + getWriter().RecordRelocation(*this, Layout, &F, Fixup, Target, FixedValue); + } + return FixedValue; + } + +void MCAssembler::Finish() { + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - pre-layout\n--\n"; + dump(); }); + + // Create the layout object. + MCAsmLayout Layout(*this); + + // Create dummy fragments and assign section ordinals. + unsigned SectionIndex = 0; + for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { + // Create dummy fragments to eliminate any empty sections, this simplifies + // layout. + if (it->getFragmentList().empty()) + new MCDataFragment(it); + + it->setOrdinal(SectionIndex++); + } + + // Assign layout order indices to sections and fragments. + for (unsigned i = 0, e = Layout.getSectionOrder().size(); i != e; ++i) { + MCSectionData *SD = Layout.getSectionOrder()[i]; + SD->setLayoutOrder(i); + + unsigned FragmentIndex = 0; + for (MCSectionData::iterator it2 = SD->begin(), + ie2 = SD->end(); it2 != ie2; ++it2) + it2->setLayoutOrder(FragmentIndex++); + } + + // Layout until everything fits. + while (LayoutOnce(Layout)) + continue; + + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - post-relaxation\n--\n"; + dump(); }); + + // Finalize the layout, including fragment lowering. + FinishLayout(Layout); + + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - final-layout\n--\n"; + dump(); }); + + uint64_t StartOffset = OS.tell(); + + // Allow the object writer a chance to perform post-layout binding (for + // example, to set the index fields in the symbol data). + getWriter().ExecutePostLayoutBinding(*this, Layout); + + // Evaluate and apply the fixups, generating relocation entries as necessary. + for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) { + for (MCSectionData::iterator it2 = it->begin(), + ie2 = it->end(); it2 != ie2; ++it2) { + MCDataFragment *DF = dyn_cast(it2); + if (DF) { + for (MCDataFragment::fixup_iterator it3 = DF->fixup_begin(), + ie3 = DF->fixup_end(); it3 != ie3; ++it3) { + MCFixup &Fixup = *it3; + uint64_t FixedValue = HandleFixup(Layout, *DF, Fixup); + getBackend().ApplyFixup(Fixup, DF->getContents().data(), + DF->getContents().size(), FixedValue); + } + } + MCInstFragment *IF = dyn_cast(it2); + if (IF) { + for (MCInstFragment::fixup_iterator it3 = IF->fixup_begin(), + ie3 = IF->fixup_end(); it3 != ie3; ++it3) { + MCFixup &Fixup = *it3; + uint64_t FixedValue = HandleFixup(Layout, *IF, Fixup); + getBackend().ApplyFixup(Fixup, IF->getCode().data(), + IF->getCode().size(), FixedValue); + } + } + } + } + + // Write the object file. + getWriter().WriteObject(*this, Layout); + + stats::ObjectBytes += OS.tell() - StartOffset; +} + +bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, + const MCFragment *DF, + const MCAsmLayout &Layout) const { + if (getRelaxAll()) + return true; + + // If we cannot resolve the fixup value, it requires relaxation. + MCValue Target; + uint64_t Value; + if (!EvaluateFixup(Layout, Fixup, DF, Target, Value)) + return true; + + // Otherwise, relax if the value is too big for a (signed) i8. + // + // FIXME: This is target dependent! + return int64_t(Value) != int64_t(int8_t(Value)); +} + +bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, + const MCAsmLayout &Layout) const { + // If this inst doesn't ever need relaxation, ignore it. This occurs when we + // are intentionally pushing out inst fragments, or because we relaxed a + // previous instruction to one that doesn't need relaxation. + if (!getBackend().MayNeedRelaxation(IF->getInst())) + return false; + + for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(), + ie = IF->fixup_end(); it != ie; ++it) + if (FixupNeedsRelaxation(*it, IF, Layout)) + return true; + + return false; +} + +bool MCAssembler::RelaxInstruction(MCAsmLayout &Layout, + MCInstFragment &IF) { + if (!FragmentNeedsRelaxation(&IF, Layout)) + return false; + + ++stats::RelaxedInstructions; + + // FIXME-PERF: We could immediately lower out instructions if we can tell + // they are fully resolved, to avoid retesting on later passes. + + // Relax the fragment. + + MCInst Relaxed; + getBackend().RelaxInstruction(IF.getInst(), Relaxed); + + // Encode the new instruction. + // + // FIXME-PERF: If it matters, we could let the target do this. It can + // probably do so more efficiently in many cases. + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups); + VecOS.flush(); + + // Update the instruction fragment. + IF.setInst(Relaxed); + IF.getCode() = Code; + IF.getFixups().clear(); + // FIXME: Eliminate copy. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) + IF.getFixups().push_back(Fixups[i]); + + return true; +} + +bool MCAssembler::RelaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { + int64_t Value = 0; + uint64_t OldSize = LF.getContents().size(); + LF.getValue().EvaluateAsAbsolute(Value, Layout); + SmallString<8> &Data = LF.getContents(); + Data.clear(); + raw_svector_ostream OSE(Data); + if (LF.isSigned()) + MCObjectWriter::EncodeSLEB128(Value, OSE); + else + MCObjectWriter::EncodeULEB128(Value, OSE); + OSE.flush(); + return OldSize != LF.getContents().size(); +} + +bool MCAssembler::RelaxDwarfLineAddr(MCAsmLayout &Layout, + MCDwarfLineAddrFragment &DF) { + int64_t AddrDelta = 0; + uint64_t OldSize = DF.getContents().size(); + bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); + (void)IsAbs; + assert(IsAbs); + int64_t LineDelta; + LineDelta = DF.getLineDelta(); + SmallString<8> &Data = DF.getContents(); + Data.clear(); + raw_svector_ostream OSE(Data); + MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OSE); + OSE.flush(); + return OldSize != Data.size(); +} + +bool MCAssembler::RelaxDwarfCallFrameFragment(MCAsmLayout &Layout, + MCDwarfCallFrameFragment &DF) { + int64_t AddrDelta = 0; + uint64_t OldSize = DF.getContents().size(); + bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); + (void)IsAbs; + assert(IsAbs); + SmallString<8> &Data = DF.getContents(); + Data.clear(); + raw_svector_ostream OSE(Data); + MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OSE); + OSE.flush(); + return OldSize != Data.size(); +} + +bool MCAssembler::LayoutSectionOnce(MCAsmLayout &Layout, + MCSectionData &SD) { + MCFragment *FirstInvalidFragment = NULL; + // Scan for fragments that need relaxation. + for (MCSectionData::iterator it2 = SD.begin(), + ie2 = SD.end(); it2 != ie2; ++it2) { + // Check if this is an fragment that needs relaxation. + bool relaxedFrag = false; + switch(it2->getKind()) { + default: + break; + case MCFragment::FT_Inst: + relaxedFrag = RelaxInstruction(Layout, *cast(it2)); + break; + case MCFragment::FT_Dwarf: + relaxedFrag = RelaxDwarfLineAddr(Layout, + *cast(it2)); + break; + case MCFragment::FT_DwarfFrame: + relaxedFrag = + RelaxDwarfCallFrameFragment(Layout, + *cast(it2)); + break; + case MCFragment::FT_LEB: + relaxedFrag = RelaxLEB(Layout, *cast(it2)); + break; + } + // Update the layout, and remember that we relaxed. + if (relaxedFrag && !FirstInvalidFragment) + FirstInvalidFragment = it2; + } + if (FirstInvalidFragment) { + Layout.Invalidate(FirstInvalidFragment); + return true; + } + return false; +} + +bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { + ++stats::RelaxationSteps; + + bool WasRelaxed = false; + for (iterator it = begin(), ie = end(); it != ie; ++it) { + MCSectionData &SD = *it; + while(LayoutSectionOnce(Layout, SD)) + WasRelaxed = true; + } + + return WasRelaxed; +} + +void MCAssembler::FinishLayout(MCAsmLayout &Layout) { + // The layout is done. Mark every fragment as valid. + for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { + Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin()); + } +} + +// Debugging methods + +namespace llvm { + +raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { + OS << ""; + return OS; +} + +} + +void MCFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "<"; + switch (getKind()) { + case MCFragment::FT_Align: OS << "MCAlignFragment"; break; + case MCFragment::FT_Data: OS << "MCDataFragment"; break; + case MCFragment::FT_Fill: OS << "MCFillFragment"; break; + case MCFragment::FT_Inst: OS << "MCInstFragment"; break; + case MCFragment::FT_Org: OS << "MCOrgFragment"; break; + case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break; + case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; + case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; + } + + OS << ""; + + switch (getKind()) { + case MCFragment::FT_Align: { + const MCAlignFragment *AF = cast(this); + if (AF->hasEmitNops()) + OS << " (emit nops)"; + OS << "\n "; + OS << " Alignment:" << AF->getAlignment() + << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize() + << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">"; + break; + } + case MCFragment::FT_Data: { + const MCDataFragment *DF = cast(this); + OS << "\n "; + OS << " Contents:["; + const SmallVectorImpl &Contents = DF->getContents(); + for (unsigned i = 0, e = Contents.size(); i != e; ++i) { + if (i) OS << ","; + OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); + } + OS << "] (" << Contents.size() << " bytes)"; + + if (!DF->getFixups().empty()) { + OS << ",\n "; + OS << " Fixups:["; + for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(), + ie = DF->fixup_end(); it != ie; ++it) { + if (it != DF->fixup_begin()) OS << ",\n "; + OS << *it; + } + OS << "]"; + } + break; + } + case MCFragment::FT_Fill: { + const MCFillFragment *FF = cast(this); + OS << " Value:" << FF->getValue() << " ValueSize:" << FF->getValueSize() + << " Size:" << FF->getSize(); + break; + } + case MCFragment::FT_Inst: { + const MCInstFragment *IF = cast(this); + OS << "\n "; + OS << " Inst:"; + IF->getInst().dump_pretty(OS); + break; + } + case MCFragment::FT_Org: { + const MCOrgFragment *OF = cast(this); + OS << "\n "; + OS << " Offset:" << OF->getOffset() << " Value:" << OF->getValue(); + break; + } + case MCFragment::FT_Dwarf: { + const MCDwarfLineAddrFragment *OF = cast(this); + OS << "\n "; + OS << " AddrDelta:" << OF->getAddrDelta() + << " LineDelta:" << OF->getLineDelta(); + break; + } + case MCFragment::FT_DwarfFrame: { + const MCDwarfCallFrameFragment *CF = cast(this); + OS << "\n "; + OS << " AddrDelta:" << CF->getAddrDelta(); + break; + } + case MCFragment::FT_LEB: { + const MCLEBFragment *LF = cast(this); + OS << "\n "; + OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned(); + break; + } + } + OS << ">"; +} + +void MCSectionData::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "dump(); + } + OS << "]>"; +} + +void MCSymbolData::dump() { + raw_ostream &OS = llvm::errs(); + + OS << ""; +} + +void MCAssembler::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "dump(); + } + OS << "],\n"; + OS << " Symbols:["; + + for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { + if (it != symbol_begin()) OS << ",\n "; + it->dump(); + } + OS << "]>\n"; +} diff --git a/final/lib/MC/MCCodeEmitter.cpp b/final/lib/MC/MCCodeEmitter.cpp new file mode 100644 index 00000000000..c122763b2fe --- /dev/null +++ b/final/lib/MC/MCCodeEmitter.cpp @@ -0,0 +1,18 @@ +//===-- MCCodeEmitter.cpp - Instruction Encoding --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCCodeEmitter.h" + +using namespace llvm; + +MCCodeEmitter::MCCodeEmitter() { +} + +MCCodeEmitter::~MCCodeEmitter() { +} diff --git a/final/lib/MC/MCContext.cpp b/final/lib/MC/MCContext.cpp new file mode 100644 index 00000000000..018f00c08f6 --- /dev/null +++ b/final/lib/MC/MCContext.cpp @@ -0,0 +1,312 @@ +//===- lib/MC/MCContext.cpp - Machine Code Context ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCLabel.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ELF.h" +using namespace llvm; + +typedef StringMap MachOUniqueMapTy; +typedef StringMap ELFUniqueMapTy; +typedef StringMap COFFUniqueMapTy; + + +MCContext::MCContext(const MCAsmInfo &mai, const TargetAsmInfo *tai) : + MAI(mai), TAI(tai), NextUniqueID(0), + CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0) { + MachOUniquingMap = 0; + ELFUniquingMap = 0; + COFFUniquingMap = 0; + + SecureLogFile = getenv("AS_SECURE_LOG_FILE"); + SecureLog = 0; + SecureLogUsed = false; + + DwarfLocSeen = false; +} + +MCContext::~MCContext() { + // NOTE: The symbols are all allocated out of a bump pointer allocator, + // we don't need to free them here. + + // If we have the MachO uniquing map, free it. + delete (MachOUniqueMapTy*)MachOUniquingMap; + delete (ELFUniqueMapTy*)ELFUniquingMap; + delete (COFFUniqueMapTy*)COFFUniquingMap; + + // If the stream for the .secure_log_unique directive was created free it. + delete (raw_ostream*)SecureLog; + + delete TAI; +} + +//===----------------------------------------------------------------------===// +// Symbol Manipulation +//===----------------------------------------------------------------------===// + +MCSymbol *MCContext::GetOrCreateSymbol(StringRef Name) { + assert(!Name.empty() && "Normal symbols cannot be unnamed!"); + + // Do the lookup and get the entire StringMapEntry. We want access to the + // key if we are creating the entry. + StringMapEntry &Entry = Symbols.GetOrCreateValue(Name); + MCSymbol *Sym = Entry.getValue(); + + if (Sym) + return Sym; + + Sym = CreateSymbol(Name); + Entry.setValue(Sym); + return Sym; +} + +MCSymbol *MCContext::CreateSymbol(StringRef Name) { + // Determine whether this is an assembler temporary or normal label. + bool isTemporary = Name.startswith(MAI.getPrivateGlobalPrefix()); + + StringMapEntry *NameEntry = &UsedNames.GetOrCreateValue(Name); + if (NameEntry->getValue()) { + assert(isTemporary && "Cannot rename non temporary symbols"); + SmallString<128> NewName; + do { + Twine T = Name + Twine(NextUniqueID++); + T.toVector(NewName); + StringRef foo = NewName; + NameEntry = &UsedNames.GetOrCreateValue(foo); + } while (NameEntry->getValue()); + } + NameEntry->setValue(true); + + // Ok, the entry doesn't already exist. Have the MCSymbol object itself refer + // to the copy of the string that is embedded in the UsedNames entry. + MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary); + + return Result; +} + +MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { + SmallString<128> NameSV; + Name.toVector(NameSV); + return GetOrCreateSymbol(NameSV.str()); +} + +MCSymbol *MCContext::CreateTempSymbol() { + SmallString<128> NameSV; + Twine Name = Twine(MAI.getPrivateGlobalPrefix()) + "tmp" + + Twine(NextUniqueID++); + Name.toVector(NameSV); + return CreateSymbol(NameSV); +} + +unsigned MCContext::NextInstance(int64_t LocalLabelVal) { + MCLabel *&Label = Instances[LocalLabelVal]; + if (!Label) + Label = new (*this) MCLabel(0); + return Label->incInstance(); +} + +unsigned MCContext::GetInstance(int64_t LocalLabelVal) { + MCLabel *&Label = Instances[LocalLabelVal]; + if (!Label) + Label = new (*this) MCLabel(0); + return Label->getInstance(); +} + +MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { + return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + Twine(LocalLabelVal) + + "\2" + + Twine(NextInstance(LocalLabelVal))); +} +MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal, + int bORf) { + return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + Twine(LocalLabelVal) + + "\2" + + Twine(GetInstance(LocalLabelVal) + bORf)); +} + +MCSymbol *MCContext::LookupSymbol(StringRef Name) const { + return Symbols.lookup(Name); +} + +//===----------------------------------------------------------------------===// +// Section Management +//===----------------------------------------------------------------------===// + +const MCSectionMachO *MCContext:: +getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind Kind) { + + // We unique sections by their segment/section pair. The returned section + // may not have the same flags as the requested section, if so this should be + // diagnosed by the client as an error. + + // Create the map if it doesn't already exist. + if (MachOUniquingMap == 0) + MachOUniquingMap = new MachOUniqueMapTy(); + MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)MachOUniquingMap; + + // Form the name to look up. + SmallString<64> Name; + Name += Segment; + Name.push_back(','); + Name += Section; + + // Do the lookup, if we have a hit, return it. + const MCSectionMachO *&Entry = Map[Name.str()]; + if (Entry) return Entry; + + // Otherwise, return a new section. + return Entry = new (*this) MCSectionMachO(Segment, Section, TypeAndAttributes, + Reserved2, Kind); +} + +const MCSectionELF *MCContext:: +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + return getELFSection(Section, Type, Flags, Kind, 0, ""); +} + +const MCSectionELF *MCContext:: +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind, unsigned EntrySize, StringRef Group) { + if (ELFUniquingMap == 0) + ELFUniquingMap = new ELFUniqueMapTy(); + ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap; + + // Do the lookup, if we have a hit, return it. + StringMapEntry &Entry = Map.GetOrCreateValue(Section); + if (Entry.getValue()) return Entry.getValue(); + + // Possibly refine the entry size first. + if (!EntrySize) { + EntrySize = MCSectionELF::DetermineEntrySize(Kind); + } + + MCSymbol *GroupSym = NULL; + if (!Group.empty()) + GroupSym = GetOrCreateSymbol(Group); + + MCSectionELF *Result = new (*this) MCSectionELF(Entry.getKey(), Type, Flags, + Kind, EntrySize, GroupSym); + Entry.setValue(Result); + return Result; +} + +const MCSectionELF *MCContext::CreateELFGroupSection() { + MCSectionELF *Result = + new (*this) MCSectionELF(".group", ELF::SHT_GROUP, 0, + SectionKind::getReadOnly(), 4, NULL); + return Result; +} + +const MCSection *MCContext::getCOFFSection(StringRef Section, + unsigned Characteristics, + int Selection, + SectionKind Kind) { + if (COFFUniquingMap == 0) + COFFUniquingMap = new COFFUniqueMapTy(); + COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)COFFUniquingMap; + + // Do the lookup, if we have a hit, return it. + StringMapEntry &Entry = Map.GetOrCreateValue(Section); + if (Entry.getValue()) return Entry.getValue(); + + MCSectionCOFF *Result = new (*this) MCSectionCOFF(Entry.getKey(), + Characteristics, + Selection, Kind); + + Entry.setValue(Result); + return Result; +} + +//===----------------------------------------------------------------------===// +// Dwarf Management +//===----------------------------------------------------------------------===// + +/// GetDwarfFile - takes a file name an number to place in the dwarf file and +/// directory tables. If the file number has already been allocated it is an +/// error and zero is returned and the client reports the error, else the +/// allocated file number is returned. The file numbers may be in any order. +unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) { + // TODO: a FileNumber of zero says to use the next available file number. + // Note: in GenericAsmParser::ParseDirectiveFile() FileNumber was checked + // to not be less than one. This needs to be change to be not less than zero. + + // Make space for this FileNumber in the MCDwarfFiles vector if needed. + if (FileNumber >= MCDwarfFiles.size()) { + MCDwarfFiles.resize(FileNumber + 1); + } else { + MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber]; + if (ExistingFile) + // It is an error to use see the same number more than once. + return 0; + } + + // Get the new MCDwarfFile slot for this FileNumber. + MCDwarfFile *&File = MCDwarfFiles[FileNumber]; + + // Separate the directory part from the basename of the FileName. + std::pair Slash = FileName.rsplit('/'); + + // Find or make a entry in the MCDwarfDirs vector for this Directory. + StringRef Name; + unsigned DirIndex; + // Capture directory name. + if (Slash.second.empty()) { + Name = Slash.first; + DirIndex = 0; // For FileNames with no directories a DirIndex of 0 is used. + } else { + StringRef Directory = Slash.first; + Name = Slash.second; + for (DirIndex = 0; DirIndex < MCDwarfDirs.size(); DirIndex++) { + if (Directory == MCDwarfDirs[DirIndex]) + break; + } + if (DirIndex >= MCDwarfDirs.size()) { + char *Buf = static_cast(Allocate(Directory.size())); + memcpy(Buf, Directory.data(), Directory.size()); + MCDwarfDirs.push_back(StringRef(Buf, Directory.size())); + } + // The DirIndex is one based, as DirIndex of 0 is used for FileNames with + // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the + // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames are + // stored at MCDwarfFiles[FileNumber].Name . + DirIndex++; + } + + // Now make the MCDwarfFile entry and place it in the slot in the MCDwarfFiles + // vector. + char *Buf = static_cast(Allocate(Name.size())); + memcpy(Buf, Name.data(), Name.size()); + File = new (*this) MCDwarfFile(StringRef(Buf, Name.size()), DirIndex); + + // return the allocated FileNumber. + return FileNumber; +} + +/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it +/// currently is assigned and false otherwise. +bool MCContext::isValidDwarfFileNumber(unsigned FileNumber) { + if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size()) + return false; + + return MCDwarfFiles[FileNumber] != 0; +} diff --git a/final/lib/MC/MCDisassembler.cpp b/final/lib/MC/MCDisassembler.cpp new file mode 100644 index 00000000000..08096906462 --- /dev/null +++ b/final/lib/MC/MCDisassembler.cpp @@ -0,0 +1,14 @@ +//===-- lib/MC/MCDisassembler.cpp - Disassembler interface ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCDisassembler.h" +using namespace llvm; + +MCDisassembler::~MCDisassembler() { +} diff --git a/final/lib/MC/MCDisassembler/CMakeLists.txt b/final/lib/MC/MCDisassembler/CMakeLists.txt new file mode 100644 index 00000000000..5fa7b70194b --- /dev/null +++ b/final/lib/MC/MCDisassembler/CMakeLists.txt @@ -0,0 +1,7 @@ + +add_llvm_library(LLVMMCDisassembler + EDDisassembler.cpp + EDOperand.cpp + EDInst.cpp + EDToken.cpp + ) diff --git a/final/lib/MC/MCDisassembler/EDDisassembler.cpp b/final/lib/MC/MCDisassembler/EDDisassembler.cpp new file mode 100644 index 00000000000..2fd14db2a45 --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDDisassembler.cpp @@ -0,0 +1,402 @@ +//===-EDDisassembler.cpp - LLVM Enhanced Disassembler ---------------------===// +// +// 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 Enhanced Disassembly library's disassembler class. +// The disassembler is responsible for vending individual instructions according +// to a given architecture and disassembly syntax. +// +//===----------------------------------------------------------------------===// + +#include "EDDisassembler.h" +#include "EDInst.h" +#include "llvm/MC/EDInstInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Target/TargetAsmLexer.h" +#include "llvm/Target/TargetAsmParser.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSelect.h" +using namespace llvm; + +bool EDDisassembler::sInitialized = false; +EDDisassembler::DisassemblerMap_t EDDisassembler::sDisassemblers; + +struct TripleMap { + Triple::ArchType Arch; + const char *String; +}; + +static struct TripleMap triplemap[] = { + { Triple::x86, "i386-unknown-unknown" }, + { Triple::x86_64, "x86_64-unknown-unknown" }, + { Triple::arm, "arm-unknown-unknown" }, + { Triple::thumb, "thumb-unknown-unknown" }, + { Triple::InvalidArch, NULL, } +}; + +/// infoFromArch - Returns the TripleMap corresponding to a given architecture, +/// or NULL if there is an error +/// +/// @arg arch - The Triple::ArchType for the desired architecture +static const char *tripleFromArch(Triple::ArchType arch) { + unsigned int infoIndex; + + for (infoIndex = 0; triplemap[infoIndex].String != NULL; ++infoIndex) { + if (arch == triplemap[infoIndex].Arch) + return triplemap[infoIndex].String; + } + + return NULL; +} + +/// getLLVMSyntaxVariant - gets the constant to use to get an assembly printer +/// for the desired assembly syntax, suitable for passing to +/// Target::createMCInstPrinter() +/// +/// @arg arch - The target architecture +/// @arg syntax - The assembly syntax in sd form +static int getLLVMSyntaxVariant(Triple::ArchType arch, + EDDisassembler::AssemblySyntax syntax) { + switch (syntax) { + default: + return -1; + // Mappings below from X86AsmPrinter.cpp + case EDDisassembler::kEDAssemblySyntaxX86ATT: + if (arch == Triple::x86 || arch == Triple::x86_64) + return 0; + else + return -1; + case EDDisassembler::kEDAssemblySyntaxX86Intel: + if (arch == Triple::x86 || arch == Triple::x86_64) + return 1; + else + return -1; + case EDDisassembler::kEDAssemblySyntaxARMUAL: + if (arch == Triple::arm || arch == Triple::thumb) + return 0; + else + return -1; + } +} + +void EDDisassembler::initialize() { + if (sInitialized) + return; + + sInitialized = true; + + InitializeAllTargetInfos(); + InitializeAllTargets(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + InitializeAllDisassemblers(); +} + +#undef BRINGUP_TARGET + +EDDisassembler *EDDisassembler::getDisassembler(Triple::ArchType arch, + AssemblySyntax syntax) { + CPUKey key; + key.Arch = arch; + key.Syntax = syntax; + + EDDisassembler::DisassemblerMap_t::iterator i = sDisassemblers.find(key); + + if (i != sDisassemblers.end()) { + return i->second; + } else { + EDDisassembler* sdd = new EDDisassembler(key); + if (!sdd->valid()) { + delete sdd; + return NULL; + } + + sDisassemblers[key] = sdd; + + return sdd; + } + + return NULL; +} + +EDDisassembler *EDDisassembler::getDisassembler(StringRef str, + AssemblySyntax syntax) { + return getDisassembler(Triple(str).getArch(), syntax); +} + +EDDisassembler::EDDisassembler(CPUKey &key) : + Valid(false), + HasSemantics(false), + ErrorStream(nulls()), + Key(key) { + const char *triple = tripleFromArch(key.Arch); + + if (!triple) + return; + + LLVMSyntaxVariant = getLLVMSyntaxVariant(key.Arch, key.Syntax); + + if (LLVMSyntaxVariant < 0) + return; + + std::string tripleString(triple); + std::string errorString; + + Tgt = TargetRegistry::lookupTarget(tripleString, + errorString); + + if (!Tgt) + return; + + std::string featureString; + + TargetMachine.reset(Tgt->createTargetMachine(tripleString, + featureString)); + + const TargetRegisterInfo *registerInfo = TargetMachine->getRegisterInfo(); + + if (!registerInfo) + return; + + initMaps(*registerInfo); + + AsmInfo.reset(Tgt->createAsmInfo(tripleString)); + + if (!AsmInfo) + return; + + Disassembler.reset(Tgt->createMCDisassembler()); + + if (!Disassembler) + return; + + InstInfos = Disassembler->getEDInfo(); + + InstString.reset(new std::string); + InstStream.reset(new raw_string_ostream(*InstString)); + InstPrinter.reset(Tgt->createMCInstPrinter(LLVMSyntaxVariant, *AsmInfo)); + + if (!InstPrinter) + return; + + GenericAsmLexer.reset(new AsmLexer(*AsmInfo)); + SpecificAsmLexer.reset(Tgt->createAsmLexer(*AsmInfo)); + SpecificAsmLexer->InstallLexer(*GenericAsmLexer); + + initMaps(*TargetMachine->getRegisterInfo()); + + Valid = true; +} + +EDDisassembler::~EDDisassembler() { + if (!valid()) + return; +} + +namespace { + /// EDMemoryObject - a subclass of MemoryObject that allows use of a callback + /// as provided by the sd interface. See MemoryObject. + class EDMemoryObject : public llvm::MemoryObject { + private: + EDByteReaderCallback Callback; + void *Arg; + public: + EDMemoryObject(EDByteReaderCallback callback, + void *arg) : Callback(callback), Arg(arg) { } + ~EDMemoryObject() { } + uint64_t getBase() const { return 0x0; } + uint64_t getExtent() const { return (uint64_t)-1; } + int readByte(uint64_t address, uint8_t *ptr) const { + if (!Callback) + return -1; + + if (Callback(ptr, address, Arg)) + return -1; + + return 0; + } + }; +} + +EDInst *EDDisassembler::createInst(EDByteReaderCallback byteReader, + uint64_t address, + void *arg) { + EDMemoryObject memoryObject(byteReader, arg); + + MCInst* inst = new MCInst; + uint64_t byteSize; + + if (!Disassembler->getInstruction(*inst, + byteSize, + memoryObject, + address, + ErrorStream)) { + delete inst; + return NULL; + } else { + const llvm::EDInstInfo *thisInstInfo; + + thisInstInfo = &InstInfos[inst->getOpcode()]; + + EDInst* sdInst = new EDInst(inst, byteSize, *this, thisInstInfo); + return sdInst; + } +} + +void EDDisassembler::initMaps(const TargetRegisterInfo ®isterInfo) { + unsigned numRegisters = registerInfo.getNumRegs(); + unsigned registerIndex; + + for (registerIndex = 0; registerIndex < numRegisters; ++registerIndex) { + const char* registerName = registerInfo.get(registerIndex).Name; + + RegVec.push_back(registerName); + RegRMap[registerName] = registerIndex; + } + + switch (Key.Arch) { + default: + break; + case Triple::x86: + case Triple::x86_64: + stackPointers.insert(registerIDWithName("SP")); + stackPointers.insert(registerIDWithName("ESP")); + stackPointers.insert(registerIDWithName("RSP")); + + programCounters.insert(registerIDWithName("IP")); + programCounters.insert(registerIDWithName("EIP")); + programCounters.insert(registerIDWithName("RIP")); + break; + case Triple::arm: + case Triple::thumb: + stackPointers.insert(registerIDWithName("SP")); + + programCounters.insert(registerIDWithName("PC")); + break; + } +} + +const char *EDDisassembler::nameWithRegisterID(unsigned registerID) const { + if (registerID >= RegVec.size()) + return NULL; + else + return RegVec[registerID].c_str(); +} + +unsigned EDDisassembler::registerIDWithName(const char *name) const { + regrmap_t::const_iterator iter = RegRMap.find(std::string(name)); + if (iter == RegRMap.end()) + return 0; + else + return (*iter).second; +} + +bool EDDisassembler::registerIsStackPointer(unsigned registerID) { + return (stackPointers.find(registerID) != stackPointers.end()); +} + +bool EDDisassembler::registerIsProgramCounter(unsigned registerID) { + return (programCounters.find(registerID) != programCounters.end()); +} + +int EDDisassembler::printInst(std::string &str, MCInst &inst) { + PrinterMutex.acquire(); + + InstPrinter->printInst(&inst, *InstStream); + InstStream->flush(); + str = *InstString; + InstString->clear(); + + PrinterMutex.release(); + + return 0; +} + +int EDDisassembler::parseInst(SmallVectorImpl &operands, + SmallVectorImpl &tokens, + const std::string &str) { + int ret = 0; + + switch (Key.Arch) { + default: + return -1; + case Triple::x86: + case Triple::x86_64: + case Triple::arm: + case Triple::thumb: + break; + } + + const char *cStr = str.c_str(); + MemoryBuffer *buf = MemoryBuffer::getMemBuffer(cStr, cStr + strlen(cStr)); + + StringRef instName; + SMLoc instLoc; + + SourceMgr sourceMgr; + sourceMgr.AddNewSourceBuffer(buf, SMLoc()); // ownership of buf handed over + MCContext context(*AsmInfo, NULL); + OwningPtr streamer(createNullStreamer(context)); + OwningPtr genericParser(createMCAsmParser(*Tgt, sourceMgr, + context, *streamer, + *AsmInfo)); + OwningPtr TargetParser(Tgt->createAsmParser(*genericParser, + *TargetMachine)); + + AsmToken OpcodeToken = genericParser->Lex(); + AsmToken NextToken = genericParser->Lex(); // consume next token, because specificParser expects us to + + if (OpcodeToken.is(AsmToken::Identifier)) { + instName = OpcodeToken.getString(); + instLoc = OpcodeToken.getLoc(); + + if (NextToken.isNot(AsmToken::Eof) && + TargetParser->ParseInstruction(instName, instLoc, operands)) + ret = -1; + } else { + ret = -1; + } + + ParserMutex.acquire(); + + if (!ret) { + GenericAsmLexer->setBuffer(buf); + + while (SpecificAsmLexer->Lex(), + SpecificAsmLexer->isNot(AsmToken::Eof) && + SpecificAsmLexer->isNot(AsmToken::EndOfStatement)) { + if (SpecificAsmLexer->is(AsmToken::Error)) { + ret = -1; + break; + } + tokens.push_back(SpecificAsmLexer->getTok()); + } + } + + ParserMutex.release(); + + return ret; +} + +int EDDisassembler::llvmSyntaxVariant() const { + return LLVMSyntaxVariant; +} diff --git a/final/lib/MC/MCDisassembler/EDDisassembler.h b/final/lib/MC/MCDisassembler/EDDisassembler.h new file mode 100644 index 00000000000..71e45f0b042 --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDDisassembler.h @@ -0,0 +1,273 @@ +//===-- EDDisassembler.h - LLVM Enhanced Disassembler -----------*- 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 interface for the Enhanced Disassembly library's +// disassembler class. The disassembler is responsible for vending individual +// instructions according to a given architecture and disassembly syntax. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EDDISASSEMBLER_H +#define LLVM_EDDISASSEMBLER_H + +#include "EDInfo.h" + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mutex.h" + +#include +#include +#include + +namespace llvm { +class AsmLexer; +class AsmToken; +class MCContext; +class MCAsmInfo; +class MCAsmLexer; +class AsmParser; +class TargetAsmLexer; +class TargetAsmParser; +class MCDisassembler; +class MCInstPrinter; +class MCInst; +class MCParsedAsmOperand; +class MCStreamer; +template class SmallVectorImpl; +class SourceMgr; +class Target; +class TargetMachine; +class TargetRegisterInfo; + +struct EDInstInfo; +struct EDInst; +struct EDOperand; +struct EDToken; + +typedef int (*EDByteReaderCallback)(uint8_t *byte, uint64_t address, void *arg); + +/// EDDisassembler - Encapsulates a disassembler for a single architecture and +/// disassembly syntax. Also manages the static disassembler registry. +struct EDDisassembler { + typedef enum { + /*! @constant kEDAssemblySyntaxX86Intel Intel syntax for i386 and x86_64. */ + kEDAssemblySyntaxX86Intel = 0, + /*! @constant kEDAssemblySyntaxX86ATT AT&T syntax for i386 and x86_64. */ + kEDAssemblySyntaxX86ATT = 1, + kEDAssemblySyntaxARMUAL = 2 + } AssemblySyntax; + + + //////////////////// + // Static members // + //////////////////// + + /// CPUKey - Encapsulates the descriptor of an architecture/disassembly-syntax + /// pair + struct CPUKey { + /// The architecture type + llvm::Triple::ArchType Arch; + + /// The assembly syntax + AssemblySyntax Syntax; + + /// operator== - Equality operator + bool operator==(const CPUKey &key) const { + return (Arch == key.Arch && + Syntax == key.Syntax); + } + + /// operator< - Less-than operator + bool operator<(const CPUKey &key) const { + if(Arch > key.Arch) + return false; + else if (Arch == key.Arch) { + if(Syntax > key.Syntax) + return false; + } + return true; + } + }; + + typedef std::map DisassemblerMap_t; + + /// True if the disassembler registry has been initialized; false if not + static bool sInitialized; + /// A map from disassembler specifications to disassemblers. Populated + /// lazily. + static DisassemblerMap_t sDisassemblers; + + /// getDisassembler - Returns the specified disassemble, or NULL on failure + /// + /// @arg arch - The desired architecture + /// @arg syntax - The desired disassembly syntax + static EDDisassembler *getDisassembler(llvm::Triple::ArchType arch, + AssemblySyntax syntax); + + /// getDisassembler - Returns the disassembler for a given combination of + /// CPU type, CPU subtype, and assembly syntax, or NULL on failure + /// + /// @arg str - The string representation of the architecture triple, e.g., + /// "x86_64-apple-darwin" + /// @arg syntax - The disassembly syntax for the required disassembler + static EDDisassembler *getDisassembler(llvm::StringRef str, + AssemblySyntax syntax); + + /// initialize - Initializes the disassembler registry and the LLVM backend + static void initialize(); + + //////////////////////// + // Per-object members // + //////////////////////// + + /// True only if the object has been successfully initialized + bool Valid; + /// True if the disassembler can provide semantic information + bool HasSemantics; + + /// The stream to write errors to + llvm::raw_ostream &ErrorStream; + + /// The architecture/syntax pair for the current architecture + CPUKey Key; + /// The LLVM target corresponding to the disassembler + const llvm::Target *Tgt; + /// The target machine instance. + llvm::OwningPtr TargetMachine; + /// The assembly information for the target architecture + llvm::OwningPtr AsmInfo; + /// The disassembler for the target architecture + llvm::OwningPtr Disassembler; + /// The output string for the instruction printer; must be guarded with + /// PrinterMutex + llvm::OwningPtr InstString; + /// The output stream for the disassembler; must be guarded with + /// PrinterMutex + llvm::OwningPtr InstStream; + /// The instruction printer for the target architecture; must be guarded with + /// PrinterMutex when printing + llvm::OwningPtr InstPrinter; + /// The mutex that guards the instruction printer's printing functions, which + /// use a shared stream + llvm::sys::Mutex PrinterMutex; + /// The array of instruction information provided by the TableGen backend for + /// the target architecture + const llvm::EDInstInfo *InstInfos; + /// The target-specific lexer for use in tokenizing strings, in + /// target-independent and target-specific portions + llvm::OwningPtr GenericAsmLexer; + llvm::OwningPtr SpecificAsmLexer; + /// The guard for the above + llvm::sys::Mutex ParserMutex; + /// The LLVM number used for the target disassembly syntax variant + int LLVMSyntaxVariant; + + typedef std::vector regvec_t; + typedef std::map regrmap_t; + + /// A vector of registers for quick mapping from LLVM register IDs to names + regvec_t RegVec; + /// A map of registers for quick mapping from register names to LLVM IDs + regrmap_t RegRMap; + + /// A set of register IDs for aliases of the stack pointer for the current + /// architecture + std::set stackPointers; + /// A set of register IDs for aliases of the program counter for the current + /// architecture + std::set programCounters; + + /// Constructor - initializes a disassembler with all the necessary objects, + /// which come pre-allocated from the registry accessor function + /// + /// @arg key - the architecture and disassembly syntax for the + /// disassembler + EDDisassembler(CPUKey& key); + + /// valid - reports whether there was a failure in the constructor. + bool valid() { + return Valid; + } + + /// hasSemantics - reports whether the disassembler can provide operands and + /// tokens. + bool hasSemantics() { + return HasSemantics; + } + + ~EDDisassembler(); + + /// createInst - creates and returns an instruction given a callback and + /// memory address, or NULL on failure + /// + /// @arg byteReader - A callback function that provides machine code bytes + /// @arg address - The address of the first byte of the instruction, + /// suitable for passing to byteReader + /// @arg arg - An opaque argument for byteReader + EDInst *createInst(EDByteReaderCallback byteReader, + uint64_t address, + void *arg); + + /// initMaps - initializes regVec and regRMap using the provided register + /// info + /// + /// @arg registerInfo - the register information to use as a source + void initMaps(const llvm::TargetRegisterInfo ®isterInfo); + /// nameWithRegisterID - Returns the name (owned by the EDDisassembler) of a + /// register for a given register ID, or NULL on failure + /// + /// @arg registerID - the ID of the register to be queried + const char *nameWithRegisterID(unsigned registerID) const; + /// registerIDWithName - Returns the ID of a register for a given register + /// name, or (unsigned)-1 on failure + /// + /// @arg name - The name of the register + unsigned registerIDWithName(const char *name) const; + + /// registerIsStackPointer - reports whether a register ID is an alias for the + /// stack pointer register + /// + /// @arg registerID - The LLVM register ID + bool registerIsStackPointer(unsigned registerID); + /// registerIsStackPointer - reports whether a register ID is an alias for the + /// stack pointer register + /// + /// @arg registerID - The LLVM register ID + bool registerIsProgramCounter(unsigned registerID); + + /// printInst - prints an MCInst to a string, returning 0 on success, or -1 + /// otherwise + /// + /// @arg str - A reference to a string which is filled in with the string + /// representation of the instruction + /// @arg inst - A reference to the MCInst to be printed + int printInst(std::string& str, + llvm::MCInst& inst); + + /// parseInst - extracts operands and tokens from a string for use in + /// tokenizing the string. Returns 0 on success, or -1 otherwise. + /// + /// @arg operands - A reference to a vector that will be filled in with the + /// parsed operands + /// @arg tokens - A reference to a vector that will be filled in with the + /// tokens + /// @arg str - The string representation of the instruction + int parseInst(llvm::SmallVectorImpl &operands, + llvm::SmallVectorImpl &tokens, + const std::string &str); + + /// llvmSyntaxVariant - returns the LLVM syntax variant for this disassembler + int llvmSyntaxVariant() const; +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/MC/MCDisassembler/EDInfo.h b/final/lib/MC/MCDisassembler/EDInfo.h new file mode 100644 index 00000000000..627c06641db --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDInfo.h @@ -0,0 +1,73 @@ +//===-- EDInfo.h - LLVM Enhanced Disassembler -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EDINFO_H +#define LLVM_EDINFO_H + +enum { + EDIS_MAX_OPERANDS = 13, + EDIS_MAX_SYNTAXES = 2 +}; + +enum OperandTypes { + kOperandTypeNone, + kOperandTypeImmediate, + kOperandTypeRegister, + kOperandTypeX86Memory, + kOperandTypeX86EffectiveAddress, + kOperandTypeX86PCRelative, + kOperandTypeARMBranchTarget, + kOperandTypeARMSoReg, + kOperandTypeARMSoImm, + kOperandTypeARMSoImm2Part, + kOperandTypeARMPredicate, + kOperandTypeARMAddrMode2, + kOperandTypeARMAddrMode2Offset, + kOperandTypeARMAddrMode3, + kOperandTypeARMAddrMode3Offset, + kOperandTypeARMAddrMode4, + kOperandTypeARMAddrMode5, + kOperandTypeARMAddrMode6, + kOperandTypeARMAddrMode6Offset, + kOperandTypeARMAddrModePC, + kOperandTypeARMRegisterList, + kOperandTypeARMTBAddrMode, + kOperandTypeThumbITMask, + kOperandTypeThumbAddrModeS1, + kOperandTypeThumbAddrModeS2, + kOperandTypeThumbAddrModeS4, + kOperandTypeThumbAddrModeRR, + kOperandTypeThumbAddrModeSP, + kOperandTypeThumb2SoReg, + kOperandTypeThumb2SoImm, + kOperandTypeThumb2AddrModeImm8, + kOperandTypeThumb2AddrModeImm8Offset, + kOperandTypeThumb2AddrModeImm12, + kOperandTypeThumb2AddrModeSoReg, + kOperandTypeThumb2AddrModeImm8s4, + kOperandTypeThumb2AddrModeImm8s4Offset +}; + +enum OperandFlags { + kOperandFlagSource = 0x1, + kOperandFlagTarget = 0x2 +}; + +enum InstructionTypes { + kInstructionTypeNone, + kInstructionTypeMove, + kInstructionTypeBranch, + kInstructionTypePush, + kInstructionTypePop, + kInstructionTypeCall, + kInstructionTypeReturn +}; + + +#endif diff --git a/final/lib/MC/MCDisassembler/EDInst.cpp b/final/lib/MC/MCDisassembler/EDInst.cpp new file mode 100644 index 00000000000..63b049fe40f --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDInst.cpp @@ -0,0 +1,209 @@ +//===-EDInst.cpp - LLVM Enhanced Disassembler -----------------------------===// +// +// 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 Enhanced Disassembly library's instruction class. +// The instruction is responsible for vending the string representation, +// individual tokens, and operands for a single instruction. +// +//===----------------------------------------------------------------------===// + +#include "EDInst.h" +#include "EDDisassembler.h" +#include "EDOperand.h" +#include "EDToken.h" + +#include "llvm/MC/EDInstInfo.h" +#include "llvm/MC/MCInst.h" + +using namespace llvm; + +EDInst::EDInst(llvm::MCInst *inst, + uint64_t byteSize, + EDDisassembler &disassembler, + const llvm::EDInstInfo *info) : + Disassembler(disassembler), + Inst(inst), + ThisInstInfo(info), + ByteSize(byteSize), + BranchTarget(-1), + MoveSource(-1), + MoveTarget(-1) { + OperandOrder = ThisInstInfo->operandOrders[Disassembler.llvmSyntaxVariant()]; +} + +EDInst::~EDInst() { + unsigned int index; + unsigned int numOperands = Operands.size(); + + for (index = 0; index < numOperands; ++index) + delete Operands[index]; + + unsigned int numTokens = Tokens.size(); + + for (index = 0; index < numTokens; ++index) + delete Tokens[index]; + + delete Inst; +} + +uint64_t EDInst::byteSize() { + return ByteSize; +} + +int EDInst::stringify() { + if (StringifyResult.valid()) + return StringifyResult.result(); + + if (Disassembler.printInst(String, *Inst)) + return StringifyResult.setResult(-1); + + String.push_back('\n'); + + return StringifyResult.setResult(0); +} + +int EDInst::getString(const char*& str) { + if (stringify()) + return -1; + + str = String.c_str(); + + return 0; +} + +unsigned EDInst::instID() { + return Inst->getOpcode(); +} + +bool EDInst::isBranch() { + if (ThisInstInfo) + return + ThisInstInfo->instructionType == kInstructionTypeBranch || + ThisInstInfo->instructionType == kInstructionTypeCall; + else + return false; +} + +bool EDInst::isMove() { + if (ThisInstInfo) + return ThisInstInfo->instructionType == kInstructionTypeMove; + else + return false; +} + +int EDInst::parseOperands() { + if (ParseResult.valid()) + return ParseResult.result(); + + if (!ThisInstInfo) + return ParseResult.setResult(-1); + + unsigned int opIndex; + unsigned int mcOpIndex = 0; + + for (opIndex = 0; opIndex < ThisInstInfo->numOperands; ++opIndex) { + if (isBranch() && + (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget)) { + BranchTarget = opIndex; + } + else if (isMove()) { + if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagSource) + MoveSource = opIndex; + else if (ThisInstInfo->operandFlags[opIndex] & kOperandFlagTarget) + MoveTarget = opIndex; + } + + EDOperand *operand = new EDOperand(Disassembler, *this, opIndex, mcOpIndex); + + Operands.push_back(operand); + } + + return ParseResult.setResult(0); +} + +int EDInst::branchTargetID() { + if (parseOperands()) + return -1; + return BranchTarget; +} + +int EDInst::moveSourceID() { + if (parseOperands()) + return -1; + return MoveSource; +} + +int EDInst::moveTargetID() { + if (parseOperands()) + return -1; + return MoveTarget; +} + +int EDInst::numOperands() { + if (parseOperands()) + return -1; + return Operands.size(); +} + +int EDInst::getOperand(EDOperand *&operand, unsigned int index) { + if (parseOperands()) + return -1; + + if (index >= Operands.size()) + return -1; + + operand = Operands[index]; + return 0; +} + +int EDInst::tokenize() { + if (TokenizeResult.valid()) + return TokenizeResult.result(); + + if (stringify()) + return TokenizeResult.setResult(-1); + + return TokenizeResult.setResult(EDToken::tokenize(Tokens, + String, + OperandOrder, + Disassembler)); + +} + +int EDInst::numTokens() { + if (tokenize()) + return -1; + return Tokens.size(); +} + +int EDInst::getToken(EDToken *&token, unsigned int index) { + if (tokenize()) + return -1; + token = Tokens[index]; + return 0; +} + +#ifdef __BLOCKS__ +int EDInst::visitTokens(EDTokenVisitor_t visitor) { + if (tokenize()) + return -1; + + tokvec_t::iterator iter; + + for (iter = Tokens.begin(); iter != Tokens.end(); ++iter) { + int ret = visitor(*iter); + if (ret == 1) + return 0; + if (ret != 0) + return -1; + } + + return 0; +} +#endif diff --git a/final/lib/MC/MCDisassembler/EDInst.h b/final/lib/MC/MCDisassembler/EDInst.h new file mode 100644 index 00000000000..ceb9505028d --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDInst.h @@ -0,0 +1,182 @@ +//===-- EDInst.h - LLVM Enhanced Disassembler -------------------*- 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 interface for the Enhanced Disassembly library's +// instruction class. The instruction is responsible for vending the string +// representation, individual tokens and operands for a single instruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EDINST_H +#define LLVM_EDINST_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include +#include + +namespace llvm { + class MCInst; + struct EDInstInfo; + struct EDToken; + struct EDDisassembler; + struct EDOperand; + +#ifdef __BLOCKS__ + typedef int (^EDTokenVisitor_t)(EDToken *token); +#endif + +/// CachedResult - Encapsulates the result of a function along with the validity +/// of that result, so that slow functions don't need to run twice +struct CachedResult { + /// True if the result has been obtained by executing the function + bool Valid; + /// The result last obtained from the function + int Result; + + /// Constructor - Initializes an invalid result + CachedResult() : Valid(false) { } + /// valid - Returns true if the result has been obtained by executing the + /// function and false otherwise + bool valid() { return Valid; } + /// result - Returns the result of the function or an undefined value if + /// valid() is false + int result() { return Result; } + /// setResult - Sets the result of the function and declares it valid + /// returning the result (so that setResult() can be called from inside a + /// return statement) + /// @arg result - The result of the function + int setResult(int result) { Result = result; Valid = true; return result; } +}; + +/// EDInst - Encapsulates a single instruction, which can be queried for its +/// string representation, as well as its operands and tokens +struct EDInst { + /// The parent disassembler + EDDisassembler &Disassembler; + /// The containing MCInst + llvm::MCInst *Inst; + /// The instruction information provided by TableGen for this instruction + const llvm::EDInstInfo *ThisInstInfo; + /// The number of bytes for the machine code representation of the instruction + uint64_t ByteSize; + + /// The result of the stringify() function + CachedResult StringifyResult; + /// The string representation of the instruction + std::string String; + /// The order in which operands from the InstInfo's operand information appear + /// in String + const char* OperandOrder; + + /// The result of the parseOperands() function + CachedResult ParseResult; + typedef llvm::SmallVector opvec_t; + /// The instruction's operands + opvec_t Operands; + /// The operand corresponding to the target, if the instruction is a branch + int BranchTarget; + /// The operand corresponding to the source, if the instruction is a move + int MoveSource; + /// The operand corresponding to the target, if the instruction is a move + int MoveTarget; + + /// The result of the tokenize() function + CachedResult TokenizeResult; + typedef std::vector tokvec_t; + /// The instruction's tokens + tokvec_t Tokens; + + /// Constructor - initializes an instruction given the output of the LLVM + /// C++ disassembler + /// + /// @arg inst - The MCInst, which will now be owned by this object + /// @arg byteSize - The size of the consumed instruction, in bytes + /// @arg disassembler - The parent disassembler + /// @arg instInfo - The instruction information produced by the table + /// generator for this instruction + EDInst(llvm::MCInst *inst, + uint64_t byteSize, + EDDisassembler &disassembler, + const llvm::EDInstInfo *instInfo); + ~EDInst(); + + /// byteSize - returns the number of bytes consumed by the machine code + /// representation of the instruction + uint64_t byteSize(); + /// instID - returns the LLVM instruction ID of the instruction + unsigned instID(); + + /// stringify - populates the String and AsmString members of the instruction, + /// returning 0 on success or -1 otherwise + int stringify(); + /// getString - retrieves a pointer to the string representation of the + /// instructinon, returning 0 on success or -1 otherwise + /// + /// @arg str - A reference to a pointer that, on success, is set to point to + /// the string representation of the instruction; this string is still owned + /// by the instruction and will be deleted when it is + int getString(const char *&str); + + /// isBranch - Returns true if the instruction is a branch + bool isBranch(); + /// isMove - Returns true if the instruction is a move + bool isMove(); + + /// parseOperands - populates the Operands member of the instruction, + /// returning 0 on success or -1 otherwise + int parseOperands(); + /// branchTargetID - returns the ID (suitable for use with getOperand()) of + /// the target operand if the instruction is a branch, or -1 otherwise + int branchTargetID(); + /// moveSourceID - returns the ID of the source operand if the instruction + /// is a move, or -1 otherwise + int moveSourceID(); + /// moveTargetID - returns the ID of the target operand if the instruction + /// is a move, or -1 otherwise + int moveTargetID(); + + /// numOperands - returns the number of operands available to retrieve, or -1 + /// on error + int numOperands(); + /// getOperand - retrieves an operand from the instruction's operand list by + /// index, returning 0 on success or -1 on error + /// + /// @arg operand - A reference whose target is pointed at the operand on + /// success, although the operand is still owned by the EDInst + /// @arg index - The index of the operand in the instruction + int getOperand(EDOperand *&operand, unsigned int index); + + /// tokenize - populates the Tokens member of the instruction, returning 0 on + /// success or -1 otherwise + int tokenize(); + /// numTokens - returns the number of tokens in the instruction, or -1 on + /// error + int numTokens(); + /// getToken - retrieves a token from the instruction's token list by index, + /// returning 0 on success or -1 on error + /// + /// @arg token - A reference whose target is pointed at the token on success, + /// although the token is still owned by the EDInst + /// @arg index - The index of the token in the instrcutino + int getToken(EDToken *&token, unsigned int index); + +#ifdef __BLOCKS__ + /// visitTokens - Visits each token in turn and applies a block to it, + /// returning 0 if all blocks are visited and/or the block signals + /// termination by returning 1; returns -1 on error + /// + /// @arg visitor - The visitor block to apply to all tokens. + int visitTokens(EDTokenVisitor_t visitor); +#endif +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/MC/MCDisassembler/EDOperand.cpp b/final/lib/MC/MCDisassembler/EDOperand.cpp new file mode 100644 index 00000000000..2b0c73e8059 --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDOperand.cpp @@ -0,0 +1,293 @@ +//===-- EDOperand.cpp - LLVM Enhanced Disassembler ------------------------===// +// +// 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 Enhanced Disassembly library's operand class. The +// operand is responsible for allowing evaluation given a particular register +// context. +// +//===----------------------------------------------------------------------===// + +#include "EDOperand.h" +#include "EDDisassembler.h" +#include "EDInst.h" +#include "llvm/MC/EDInstInfo.h" +#include "llvm/MC/MCInst.h" +using namespace llvm; + +EDOperand::EDOperand(const EDDisassembler &disassembler, + const EDInst &inst, + unsigned int opIndex, + unsigned int &mcOpIndex) : + Disassembler(disassembler), + Inst(inst), + OpIndex(opIndex), + MCOpIndex(mcOpIndex) { + unsigned int numMCOperands = 0; + + if (Disassembler.Key.Arch == Triple::x86 || + Disassembler.Key.Arch == Triple::x86_64) { + uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; + + switch (operandType) { + default: + break; + case kOperandTypeImmediate: + numMCOperands = 1; + break; + case kOperandTypeRegister: + numMCOperands = 1; + break; + case kOperandTypeX86Memory: + numMCOperands = 5; + break; + case kOperandTypeX86EffectiveAddress: + numMCOperands = 4; + break; + case kOperandTypeX86PCRelative: + numMCOperands = 1; + break; + } + } + else if (Disassembler.Key.Arch == Triple::arm || + Disassembler.Key.Arch == Triple::thumb) { + uint8_t operandType = inst.ThisInstInfo->operandTypes[opIndex]; + + switch (operandType) { + default: + case kOperandTypeARMRegisterList: + break; + case kOperandTypeImmediate: + case kOperandTypeRegister: + case kOperandTypeARMBranchTarget: + case kOperandTypeARMSoImm: + case kOperandTypeThumb2SoImm: + case kOperandTypeARMSoImm2Part: + case kOperandTypeARMPredicate: + case kOperandTypeThumbITMask: + case kOperandTypeThumb2AddrModeImm8Offset: + case kOperandTypeARMTBAddrMode: + case kOperandTypeThumb2AddrModeImm8s4Offset: + numMCOperands = 1; + break; + case kOperandTypeThumb2SoReg: + case kOperandTypeARMAddrMode2Offset: + case kOperandTypeARMAddrMode3Offset: + case kOperandTypeARMAddrMode4: + case kOperandTypeARMAddrMode5: + case kOperandTypeARMAddrModePC: + case kOperandTypeThumb2AddrModeImm8: + case kOperandTypeThumb2AddrModeImm12: + case kOperandTypeThumb2AddrModeImm8s4: + case kOperandTypeThumbAddrModeRR: + case kOperandTypeThumbAddrModeSP: + numMCOperands = 2; + break; + case kOperandTypeARMSoReg: + case kOperandTypeARMAddrMode2: + case kOperandTypeARMAddrMode3: + case kOperandTypeThumb2AddrModeSoReg: + case kOperandTypeThumbAddrModeS1: + case kOperandTypeThumbAddrModeS2: + case kOperandTypeThumbAddrModeS4: + case kOperandTypeARMAddrMode6Offset: + numMCOperands = 3; + break; + case kOperandTypeARMAddrMode6: + numMCOperands = 4; + break; + } + } + + mcOpIndex += numMCOperands; +} + +EDOperand::~EDOperand() { +} + +int EDOperand::evaluate(uint64_t &result, + EDRegisterReaderCallback callback, + void *arg) { + uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; + + switch (Disassembler.Key.Arch) { + default: + return -1; + case Triple::x86: + case Triple::x86_64: + switch (operandType) { + default: + return -1; + case kOperandTypeImmediate: + result = Inst.Inst->getOperand(MCOpIndex).getImm(); + return 0; + case kOperandTypeRegister: + { + unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); + return callback(&result, reg, arg); + } + case kOperandTypeX86PCRelative: + { + int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); + + uint64_t ripVal; + + // TODO fix how we do this + + if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg)) + return -1; + + result = ripVal + displacement; + return 0; + } + case kOperandTypeX86Memory: + case kOperandTypeX86EffectiveAddress: + { + unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg(); + uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); + unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); + int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); + + uint64_t addr = 0; + + unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); + + if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) { + unsigned fsID = Disassembler.registerIDWithName("FS"); + unsigned gsID = Disassembler.registerIDWithName("GS"); + + if (segmentReg == fsID || + segmentReg == gsID) { + uint64_t segmentBase; + if (!callback(&segmentBase, segmentReg, arg)) + addr += segmentBase; + } + } + + if (baseReg) { + uint64_t baseVal; + if (callback(&baseVal, baseReg, arg)) + return -1; + addr += baseVal; + } + + if (indexReg) { + uint64_t indexVal; + if (callback(&indexVal, indexReg, arg)) + return -1; + addr += (scaleAmount * indexVal); + } + + addr += displacement; + + result = addr; + return 0; + } + } // switch (operandType) + break; + case Triple::arm: + case Triple::thumb: + switch (operandType) { + default: + return -1; + case kOperandTypeImmediate: + result = Inst.Inst->getOperand(MCOpIndex).getImm(); + return 0; + case kOperandTypeRegister: + { + unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); + return callback(&result, reg, arg); + } + case kOperandTypeARMBranchTarget: + { + int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); + + uint64_t pcVal; + + if (callback(&pcVal, Disassembler.registerIDWithName("PC"), arg)) + return -1; + + result = pcVal + displacement; + return 0; + } + } + break; + } + + return -1; +} + +int EDOperand::isRegister() { + return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeRegister); +} + +unsigned EDOperand::regVal() { + return Inst.Inst->getOperand(MCOpIndex).getReg(); +} + +int EDOperand::isImmediate() { + return(Inst.ThisInstInfo->operandFlags[OpIndex] == kOperandTypeImmediate); +} + +uint64_t EDOperand::immediateVal() { + return Inst.Inst->getOperand(MCOpIndex).getImm(); +} + +int EDOperand::isMemory() { + uint8_t operandType = Inst.ThisInstInfo->operandTypes[OpIndex]; + + switch (operandType) { + default: + return 0; + case kOperandTypeX86Memory: + case kOperandTypeX86PCRelative: + case kOperandTypeX86EffectiveAddress: + case kOperandTypeARMSoReg: + case kOperandTypeARMSoImm: + case kOperandTypeARMAddrMode2: + case kOperandTypeARMAddrMode2Offset: + case kOperandTypeARMAddrMode3: + case kOperandTypeARMAddrMode3Offset: + case kOperandTypeARMAddrMode4: + case kOperandTypeARMAddrMode5: + case kOperandTypeARMAddrMode6: + case kOperandTypeARMAddrModePC: + case kOperandTypeARMBranchTarget: + case kOperandTypeThumbAddrModeS1: + case kOperandTypeThumbAddrModeS2: + case kOperandTypeThumbAddrModeS4: + case kOperandTypeThumbAddrModeRR: + case kOperandTypeThumbAddrModeSP: + case kOperandTypeThumb2SoImm: + case kOperandTypeThumb2AddrModeImm8: + case kOperandTypeThumb2AddrModeImm8Offset: + case kOperandTypeThumb2AddrModeImm12: + case kOperandTypeThumb2AddrModeSoReg: + case kOperandTypeThumb2AddrModeImm8s4: + return 1; + } +} + +#ifdef __BLOCKS__ +namespace { + struct RegisterReaderWrapper { + EDOperand::EDRegisterBlock_t regBlock; + }; +} + +static int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) { + RegisterReaderWrapper *wrapper = (RegisterReaderWrapper *)arg; + return wrapper->regBlock(value, regID); +} + +int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) { + RegisterReaderWrapper wrapper; + wrapper.regBlock = regBlock; + return evaluate(result, readerWrapperCallback, (void*)&wrapper); +} +#endif diff --git a/final/lib/MC/MCDisassembler/EDOperand.h b/final/lib/MC/MCDisassembler/EDOperand.h new file mode 100644 index 00000000000..50260ec965a --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDOperand.h @@ -0,0 +1,91 @@ +//===-EDOperand.h - LLVM Enhanced Disassembler ------------------*- 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 interface for the Enhanced Disassembly library's +// operand class. The operand is responsible for allowing evaluation given a +// particular register context. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EDOPERAND_H +#define LLVM_EDOPERAND_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +struct EDDisassembler; +struct EDInst; + +typedef int (*EDRegisterReaderCallback)(uint64_t *value, unsigned regID, + void* arg); + + +/// EDOperand - Encapsulates a single operand, which can be evaluated by the +/// client +struct EDOperand { + /// The parent disassembler + const EDDisassembler &Disassembler; + /// The parent instruction + const EDInst &Inst; + + /// The index of the operand in the EDInst + unsigned int OpIndex; + /// The index of the first component of the operand in the MCInst + unsigned int MCOpIndex; + + /// Constructor - Initializes an EDOperand + /// + /// @arg disassembler - The disassembler responsible for the operand + /// @arg inst - The instruction containing this operand + /// @arg opIndex - The index of the operand in inst + /// @arg mcOpIndex - The index of the operand in the original MCInst + EDOperand(const EDDisassembler &disassembler, + const EDInst &inst, + unsigned int opIndex, + unsigned int &mcOpIndex); + ~EDOperand(); + + /// evaluate - Returns the numeric value of an operand to the extent possible, + /// returning 0 on success or -1 if there was some problem (such as a + /// register not being readable) + /// + /// @arg result - A reference whose target is filled in with the value of + /// the operand (the address if it is a memory operand) + /// @arg callback - A function to call to obtain register values + /// @arg arg - An opaque argument to pass to callback + int evaluate(uint64_t &result, + EDRegisterReaderCallback callback, + void *arg); + + /// isRegister - Returns 1 if the operand is a register or 0 otherwise + int isRegister(); + /// regVal - Returns the register value. + unsigned regVal(); + + /// isImmediate - Returns 1 if the operand is an immediate or 0 otherwise + int isImmediate(); + /// immediateVal - Returns the immediate value. + uint64_t immediateVal(); + + /// isMemory - Returns 1 if the operand is a memory location or 0 otherwise + int isMemory(); + +#ifdef __BLOCKS__ + typedef int (^EDRegisterBlock_t)(uint64_t *value, unsigned regID); + + /// evaluate - Like evaluate for a callback, but uses a block instead + int evaluate(uint64_t &result, + EDRegisterBlock_t regBlock); +#endif +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/MC/MCDisassembler/EDToken.cpp b/final/lib/MC/MCDisassembler/EDToken.cpp new file mode 100644 index 00000000000..de770b41ef3 --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDToken.cpp @@ -0,0 +1,210 @@ +//===-- EDToken.cpp - LLVM Enhanced Disassembler --------------------------===// +// +// 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 Enhanced Disassembler library's token class. The +// token is responsible for vending information about the token, such as its +// type and logical value. +// +//===----------------------------------------------------------------------===// + +#include "EDToken.h" +#include "EDDisassembler.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +EDToken::EDToken(StringRef str, + enum tokenType type, + uint64_t localType, + EDDisassembler &disassembler) : + Disassembler(disassembler), + Str(str), + Type(type), + LocalType(localType), + OperandID(-1) { +} + +EDToken::~EDToken() { +} + +void EDToken::makeLiteral(bool sign, uint64_t absoluteValue) { + Type = kTokenLiteral; + LiteralSign = sign; + LiteralAbsoluteValue = absoluteValue; +} + +void EDToken::makeRegister(unsigned registerID) { + Type = kTokenRegister; + RegisterID = registerID; +} + +void EDToken::setOperandID(int operandID) { + OperandID = operandID; +} + +enum EDToken::tokenType EDToken::type() const { + return Type; +} + +uint64_t EDToken::localType() const { + return LocalType; +} + +StringRef EDToken::string() const { + return Str; +} + +int EDToken::operandID() const { + return OperandID; +} + +int EDToken::literalSign() const { + if (Type != kTokenLiteral) + return -1; + return (LiteralSign ? 1 : 0); +} + +int EDToken::literalAbsoluteValue(uint64_t &value) const { + if (Type != kTokenLiteral) + return -1; + value = LiteralAbsoluteValue; + return 0; +} + +int EDToken::registerID(unsigned ®isterID) const { + if (Type != kTokenRegister) + return -1; + registerID = RegisterID; + return 0; +} + +int EDToken::tokenize(std::vector &tokens, + std::string &str, + const char *operandOrder, + EDDisassembler &disassembler) { + SmallVector parsedOperands; + SmallVector asmTokens; + + if (disassembler.parseInst(parsedOperands, asmTokens, str)) + return -1; + + SmallVectorImpl::iterator operandIterator; + unsigned int operandIndex; + SmallVectorImpl::iterator tokenIterator; + + operandIterator = parsedOperands.begin(); + operandIndex = 0; + + bool readOpcode = false; + + const char *wsPointer = asmTokens.begin()->getLoc().getPointer(); + + for (tokenIterator = asmTokens.begin(); + tokenIterator != asmTokens.end(); + ++tokenIterator) { + SMLoc tokenLoc = tokenIterator->getLoc(); + + const char *tokenPointer = tokenLoc.getPointer(); + + if (tokenPointer > wsPointer) { + unsigned long wsLength = tokenPointer - wsPointer; + + EDToken *whitespaceToken = new EDToken(StringRef(wsPointer, wsLength), + EDToken::kTokenWhitespace, + 0, + disassembler); + + tokens.push_back(whitespaceToken); + } + + wsPointer = tokenPointer + tokenIterator->getString().size(); + + while (operandIterator != parsedOperands.end() && + tokenLoc.getPointer() > + (*operandIterator)->getEndLoc().getPointer()) { + ++operandIterator; + ++operandIndex; + } + + EDToken *token; + + switch (tokenIterator->getKind()) { + case AsmToken::Identifier: + if (!readOpcode) { + token = new EDToken(tokenIterator->getString(), + EDToken::kTokenOpcode, + (uint64_t)tokenIterator->getKind(), + disassembler); + readOpcode = true; + break; + } + // any identifier that isn't an opcode is mere punctuation; so we fall + // through + default: + token = new EDToken(tokenIterator->getString(), + EDToken::kTokenPunctuation, + (uint64_t)tokenIterator->getKind(), + disassembler); + break; + case AsmToken::Integer: + { + token = new EDToken(tokenIterator->getString(), + EDToken::kTokenLiteral, + (uint64_t)tokenIterator->getKind(), + disassembler); + + int64_t intVal = tokenIterator->getIntVal(); + + if (intVal < 0) + token->makeLiteral(true, -intVal); + else + token->makeLiteral(false, intVal); + break; + } + case AsmToken::Register: + { + token = new EDToken(tokenIterator->getString(), + EDToken::kTokenLiteral, + (uint64_t)tokenIterator->getKind(), + disassembler); + + token->makeRegister((unsigned)tokenIterator->getRegVal()); + break; + } + } + + if (operandIterator != parsedOperands.end() && + tokenLoc.getPointer() >= + (*operandIterator)->getStartLoc().getPointer()) { + /// operandIndex == 0 means the operand is the instruction (which the + /// AsmParser treats as an operand but edis does not). We therefore skip + /// operandIndex == 0 and subtract 1 from all other operand indices. + + if (operandIndex > 0) + token->setOperandID(operandOrder[operandIndex - 1]); + } + + tokens.push_back(token); + } + + // Free any parsed operands. + for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i) + delete parsedOperands[i]; + + return 0; +} + +int EDToken::getString(const char*& buf) { + if (PermStr.length() == 0) { + PermStr = Str.str(); + } + buf = PermStr.c_str(); + return 0; +} diff --git a/final/lib/MC/MCDisassembler/EDToken.h b/final/lib/MC/MCDisassembler/EDToken.h new file mode 100644 index 00000000000..ba467078686 --- /dev/null +++ b/final/lib/MC/MCDisassembler/EDToken.h @@ -0,0 +1,139 @@ +//===-EDToken.h - LLVM Enhanced Disassembler --------------------*- 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 interface for the Enhanced Disassembly library's token +// class. The token is responsible for vending information about the token, +// such as its type and logical value. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EDTOKEN_H +#define LLVM_EDTOKEN_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include +#include + +namespace llvm { + +struct EDDisassembler; + +/// EDToken - Encapsulates a single token, which can provide a string +/// representation of itself or interpret itself in various ways, depending +/// on the token type. +struct EDToken { + enum tokenType { + kTokenWhitespace, + kTokenOpcode, + kTokenLiteral, + kTokenRegister, + kTokenPunctuation + }; + + /// The parent disassembler + EDDisassembler &Disassembler; + + /// The token's string representation + llvm::StringRef Str; + /// The token's string representation, but in a form suitable for export + std::string PermStr; + /// The type of the token, as exposed through the external API + enum tokenType Type; + /// The type of the token, as recorded by the syntax-specific tokenizer + uint64_t LocalType; + /// The operand corresponding to the token, or (unsigned int)-1 if not + /// part of an operand. + int OperandID; + + /// The sign if the token is a literal (1 if negative, 0 otherwise) + bool LiteralSign; + /// The absolute value if the token is a literal + uint64_t LiteralAbsoluteValue; + /// The LLVM register ID if the token is a register name + unsigned RegisterID; + + /// Constructor - Initializes an EDToken with the information common to all + /// tokens + /// + /// @arg str - The string corresponding to the token + /// @arg type - The token's type as exposed through the public API + /// @arg localType - The token's type as recorded by the tokenizer + /// @arg disassembler - The disassembler responsible for the token + EDToken(llvm::StringRef str, + enum tokenType type, + uint64_t localType, + EDDisassembler &disassembler); + + /// makeLiteral - Adds the information specific to a literal + /// @arg sign - The sign of the literal (1 if negative, 0 + /// otherwise) + /// + /// @arg absoluteValue - The absolute value of the literal + void makeLiteral(bool sign, uint64_t absoluteValue); + /// makeRegister - Adds the information specific to a register + /// + /// @arg registerID - The LLVM register ID + void makeRegister(unsigned registerID); + + /// setOperandID - Links the token to a numbered operand + /// + /// @arg operandID - The operand ID to link to + void setOperandID(int operandID); + + ~EDToken(); + + /// type - Returns the public type of the token + enum tokenType type() const; + /// localType - Returns the tokenizer-specific type of the token + uint64_t localType() const; + /// string - Returns the string representation of the token + llvm::StringRef string() const; + /// operandID - Returns the operand ID of the token + int operandID() const; + + /// literalSign - Returns the sign of the token + /// (1 if negative, 0 if positive or unsigned, -1 if it is not a literal) + int literalSign() const; + /// literalAbsoluteValue - Retrieves the absolute value of the token, and + /// returns -1 if the token is not a literal + /// @arg value - A reference to a value that is filled in with the absolute + /// value, if it is valid + int literalAbsoluteValue(uint64_t &value) const; + /// registerID - Retrieves the register ID of the token, and returns -1 if the + /// token is not a register + /// + /// @arg registerID - A reference to a value that is filled in with the + /// register ID, if it is valid + int registerID(unsigned ®isterID) const; + + /// tokenize - Tokenizes a string using the platform- and syntax-specific + /// tokenizer, and returns 0 on success (-1 on failure) + /// + /// @arg tokens - A vector that will be filled in with pointers to + /// allocated tokens + /// @arg str - The string, as outputted by the AsmPrinter + /// @arg operandOrder - The order of the operands from the operandFlags array + /// as they appear in str + /// @arg disassembler - The disassembler for the desired target and + // assembly syntax + static int tokenize(std::vector &tokens, + std::string &str, + const char *operandOrder, + EDDisassembler &disassembler); + + /// getString - Directs a character pointer to the string, returning 0 on + /// success (-1 on failure) + /// @arg buf - A reference to a pointer that is set to point to the string. + /// The string is still owned by the token. + int getString(const char*& buf); +}; + +} // end namespace llvm +#endif diff --git a/final/lib/MC/MCDisassembler/Makefile b/final/lib/MC/MCDisassembler/Makefile new file mode 100644 index 00000000000..7d71cd381a7 --- /dev/null +++ b/final/lib/MC/MCDisassembler/Makefile @@ -0,0 +1,14 @@ +##===- lib/MC/MCDisassembler/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCDisassembler + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/MC/MCDwarf.cpp b/final/lib/MC/MCDwarf.cpp new file mode 100644 index 00000000000..112d7d887a2 --- /dev/null +++ b/final/lib/MC/MCDwarf.cpp @@ -0,0 +1,814 @@ +//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" +using namespace llvm; + +// Given a special op, return the address skip amount (in units of +// DWARF2_LINE_MIN_INSN_LENGTH. +#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) + +// The maximum address skip amount that can be encoded with a special op. +#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) + +// First special line opcode - leave room for the standard opcodes. +// Note: If you want to change this, you'll have to update the +// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). +#define DWARF2_LINE_OPCODE_BASE 13 + +// Minimum line offset in a special line info. opcode. This value +// was chosen to give a reasonable range of values. +#define DWARF2_LINE_BASE -5 + +// Range of line offsets in a special line info. opcode. +# define DWARF2_LINE_RANGE 14 + +// Define the architecture-dependent minimum instruction length (in bytes). +// This value should be rather too small than too big. +# define DWARF2_LINE_MIN_INSN_LENGTH 1 + +// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, +// this routine is a nop and will be optimized away. +static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) +{ + if (DWARF2_LINE_MIN_INSN_LENGTH == 1) + return AddrDelta; + if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { + // TODO: report this error, but really only once. + ; + } + return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; +} + +// +// This is called when an instruction is assembled into the specified section +// and if there is information from the last .loc directive that has yet to have +// a line entry made for it is made. +// +void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { + if (!MCOS->getContext().getDwarfLocSeen()) + return; + + // Create a symbol at in the current section for use in the line entry. + MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); + // Set the value of the symbol to use for the MCLineEntry. + MCOS->EmitLabel(LineSym); + + // Get the current .loc info saved in the context. + const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); + + // Create a (local) line entry with the symbol and the current .loc info. + MCLineEntry LineEntry(LineSym, DwarfLoc); + + // clear DwarfLocSeen saying the current .loc info is now used. + MCOS->getContext().ClearDwarfLocSeen(); + + // Get the MCLineSection for this section, if one does not exist for this + // section create it. + const DenseMap &MCLineSections = + MCOS->getContext().getMCLineSections(); + MCLineSection *LineSection = MCLineSections.lookup(Section); + if (!LineSection) { + // Create a new MCLineSection. This will be deleted after the dwarf line + // table is created using it by iterating through the MCLineSections + // DenseMap. + LineSection = new MCLineSection; + // Save a pointer to the new LineSection into the MCLineSections DenseMap. + MCOS->getContext().addMCLineSection(Section, LineSection); + } + + // Add the line entry to this section's entries. + LineSection->addLineEntry(LineEntry); +} + +// +// This helper routine returns an expression of End - Start + IntVal . +// +static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, + const MCSymbol &Start, + const MCSymbol &End, + int IntVal) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *Res = + MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext()); + const MCExpr *RHS = + MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext()); + const MCExpr *Res1 = + MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); + const MCExpr *Res2 = + MCConstantExpr::Create(IntVal, MCOS.getContext()); + const MCExpr *Res3 = + MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); + return Res3; +} + +// +// This emits the Dwarf line table for the specified section from the entries +// in the LineSection. +// +static inline void EmitDwarfLineTable(MCStreamer *MCOS, + const MCSection *Section, + const MCLineSection *LineSection) { + unsigned FileNum = 1; + unsigned LastLine = 1; + unsigned Column = 0; + unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; + unsigned Isa = 0; + MCSymbol *LastLabel = NULL; + + // Loop through each MCLineEntry and encode the dwarf line number table. + for (MCLineSection::const_iterator + it = LineSection->getMCLineEntries()->begin(), + ie = LineSection->getMCLineEntries()->end(); it != ie; ++it) { + + if (FileNum != it->getFileNum()) { + FileNum = it->getFileNum(); + MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); + MCOS->EmitULEB128IntValue(FileNum); + } + if (Column != it->getColumn()) { + Column = it->getColumn(); + MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); + MCOS->EmitULEB128IntValue(Column); + } + if (Isa != it->getIsa()) { + Isa = it->getIsa(); + MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); + MCOS->EmitULEB128IntValue(Isa); + } + if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { + Flags = it->getFlags(); + MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); + } + if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) + MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); + if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) + MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); + if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) + MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); + + int64_t LineDelta = static_cast(it->getLine()) - LastLine; + MCSymbol *Label = it->getLabel(); + + // At this point we want to emit/create the sequence to encode the delta in + // line numbers and the increment of the address from the previous Label + // and the current Label. + MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label); + + LastLine = it->getLine(); + LastLabel = Label; + } + + // Emit a DW_LNE_end_sequence for the end of the section. + // Using the pointer Section create a temporary label at the end of the + // section and use that and the LastLabel to compute the address delta + // and use INT64_MAX as the line delta which is the signal that this is + // actually a DW_LNE_end_sequence. + + // Switch to the section to be able to create a symbol at its end. + MCOS->SwitchSection(Section); + + MCContext &context = MCOS->getContext(); + // Create a symbol at the end of the section. + MCSymbol *SectionEnd = context.CreateTempSymbol(); + // Set the value of the symbol, as we are at the end of the section. + MCOS->EmitLabel(SectionEnd); + + // Switch back the the dwarf line section. + MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); + + MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd); +} + +// +// This emits the Dwarf file and the line tables. +// +void MCDwarfFileTable::Emit(MCStreamer *MCOS) { + MCContext &context = MCOS->getContext(); + // Switch to the section where the table will be emitted into. + MCOS->SwitchSection(context.getTargetAsmInfo().getDwarfLineSection()); + + // Create a symbol at the beginning of this section. + MCSymbol *LineStartSym = context.CreateTempSymbol(); + // Set the value of the symbol, as we are at the start of the section. + MCOS->EmitLabel(LineStartSym); + + // Create a symbol for the end of the section (to be set when we get there). + MCSymbol *LineEndSym = context.CreateTempSymbol(); + + // The first 4 bytes is the total length of the information for this + // compilation unit (not including these 4 bytes for the length). + MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4), + 4); + + // Next 2 bytes is the Version, which is Dwarf 2. + MCOS->EmitIntValue(2, 2); + + // Create a symbol for the end of the prologue (to be set when we get there). + MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end + + // Length of the prologue, is the next 4 bytes. Which is the start of the + // section to the end of the prologue. Not including the 4 bytes for the + // total length, the 2 bytes for the version, and these 4 bytes for the + // length of the prologue. + MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, + (4 + 2 + 4)), + 4, 0); + + // Parameters of the state machine, are next. + MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); + MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); + MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); + MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); + MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); + + // Standard opcode lengths + MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy + MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc + MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line + MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file + MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column + MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt + MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block + MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc + MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc + MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end + MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin + MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa + + // Put out the directory and file tables. + + // First the directory table. + const std::vector &MCDwarfDirs = + context.getMCDwarfDirs(); + for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { + MCOS->EmitBytes(MCDwarfDirs[i], 0); // the DirectoryName + MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string + } + MCOS->EmitIntValue(0, 1); // Terminate the directory list + + // Second the file table. + const std::vector &MCDwarfFiles = + MCOS->getContext().getMCDwarfFiles(); + for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { + MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName + MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string + // the Directory num + MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); + MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) + MCOS->EmitIntValue(0, 1); // filesize (always 0) + } + MCOS->EmitIntValue(0, 1); // Terminate the file list + + // This is the end of the prologue, so set the value of the symbol at the + // end of the prologue (that was used in a previous expression). + MCOS->EmitLabel(ProEndSym); + + // Put out the line tables. + const DenseMap &MCLineSections = + MCOS->getContext().getMCLineSections(); + const std::vector &MCLineSectionOrder = + MCOS->getContext().getMCLineSectionOrder(); + for (std::vector::const_iterator it = + MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; + ++it) { + const MCSection *Sec = *it; + const MCLineSection *Line = MCLineSections.lookup(Sec); + EmitDwarfLineTable(MCOS, Sec, Line); + + // Now delete the MCLineSections that were created in MCLineEntry::Make() + // and used to emit the line table. + delete Line; + } + + if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() + && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { + // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures + // it requires: + // total_length >= prologue_length + 10 + // We are 4 bytes short, since we have total_length = 51 and + // prologue_length = 45 + + // The regular end_sequence should be sufficient. + MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); + } + + // This is the end of the section, so set the value of the symbol at the end + // of this section (that was used in a previous expression). + MCOS->EmitLabel(LineEndSym); +} + +/// Utility function to write the encoding to an object writer. +void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, + uint64_t AddrDelta) { + SmallString<256> Tmp; + raw_svector_ostream OS(Tmp); + MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); + OW->WriteBytes(OS.str()); +} + +/// Utility function to emit the encoding to a streamer. +void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, + uint64_t AddrDelta) { + SmallString<256> Tmp; + raw_svector_ostream OS(Tmp); + MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); + MCOS->EmitBytes(OS.str(), /*AddrSpace=*/0); +} + +/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. +void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, + raw_ostream &OS) { + uint64_t Temp, Opcode; + bool NeedCopy = false; + + // Scale the address delta by the minimum instruction length. + AddrDelta = ScaleAddrDelta(AddrDelta); + + // A LineDelta of INT64_MAX is a signal that this is actually a + // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the + // end_sequence to emit the matrix entry. + if (LineDelta == INT64_MAX) { + if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) + OS << char(dwarf::DW_LNS_const_add_pc); + else { + OS << char(dwarf::DW_LNS_advance_pc); + SmallString<32> Tmp; + raw_svector_ostream OSE(Tmp); + MCObjectWriter::EncodeULEB128(AddrDelta, OSE); + OS << OSE.str(); + } + OS << char(dwarf::DW_LNS_extended_op); + OS << char(1); + OS << char(dwarf::DW_LNE_end_sequence); + return; + } + + // Bias the line delta by the base. + Temp = LineDelta - DWARF2_LINE_BASE; + + // If the line increment is out of range of a special opcode, we must encode + // it with DW_LNS_advance_line. + if (Temp >= DWARF2_LINE_RANGE) { + OS << char(dwarf::DW_LNS_advance_line); + SmallString<32> Tmp; + raw_svector_ostream OSE(Tmp); + MCObjectWriter::EncodeSLEB128(LineDelta, OSE); + OS << OSE.str(); + + LineDelta = 0; + Temp = 0 - DWARF2_LINE_BASE; + NeedCopy = true; + } + + // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. + if (LineDelta == 0 && AddrDelta == 0) { + OS << char(dwarf::DW_LNS_copy); + return; + } + + // Bias the opcode by the special opcode base. + Temp += DWARF2_LINE_OPCODE_BASE; + + // Avoid overflow when addr_delta is large. + if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { + // Try using a special opcode. + Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; + if (Opcode <= 255) { + OS << char(Opcode); + return; + } + + // Try using DW_LNS_const_add_pc followed by special op. + Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; + if (Opcode <= 255) { + OS << char(dwarf::DW_LNS_const_add_pc); + OS << char(Opcode); + return; + } + } + + // Otherwise use DW_LNS_advance_pc. + OS << char(dwarf::DW_LNS_advance_pc); + SmallString<32> Tmp; + raw_svector_ostream OSE(Tmp); + MCObjectWriter::EncodeULEB128(AddrDelta, OSE); + OS << OSE.str(); + + if (NeedCopy) + OS << char(dwarf::DW_LNS_copy); + else + OS << char(Temp); +} + +void MCDwarfFile::print(raw_ostream &OS) const { + OS << '"' << getName() << '"'; +} + +void MCDwarfFile::dump() const { + print(dbgs()); +} + +static int getDataAlignmentFactor(MCStreamer &streamer) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + int size = asmInfo.getPointerSize(); + if (asmInfo.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp) + return size; + else + return -size; +} + +static void EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr) { + int dataAlignmentFactor = getDataAlignmentFactor(Streamer); + + switch (Instr.getOperation()) { + case MCCFIInstruction::Move: { + const MachineLocation &Dst = Instr.getDestination(); + const MachineLocation &Src = Instr.getSource(); + + // If advancing cfa. + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + assert(!Src.isReg() && "Machine move not supported yet."); + + if (Src.getReg() == MachineLocation::VirtualFP) { + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); + } else { + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); + Streamer.EmitULEB128IntValue(Src.getReg()); + } + + Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + return; + } + + if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + assert(Dst.isReg() && "Machine move not supported yet."); + Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); + Streamer.EmitULEB128IntValue(Dst.getReg()); + return; + } + + unsigned Reg = Src.getReg(); + int Offset = Dst.getOffset() / dataAlignmentFactor; + + if (Offset < 0) { + Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); + Streamer.EmitULEB128IntValue(Reg); + Streamer.EmitSLEB128IntValue(Offset); + } else if (Reg < 64) { + Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); + Streamer.EmitULEB128IntValue(Offset, 1); + } else { + Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); + Streamer.EmitULEB128IntValue(Reg, 1); + Streamer.EmitULEB128IntValue(Offset, 1); + } + return; + } + case MCCFIInstruction::Remember: + Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); + return; + case MCCFIInstruction::Restore: + Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); + return; + } + llvm_unreachable("Unhandled case in switch"); +} + +/// EmitFrameMoves - Emit frame instructions to describe the layout of the +/// frame. +static void EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel) { + for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { + const MCCFIInstruction &Instr = Instrs[i]; + MCSymbol *Label = Instr.getLabel(); + // Throw out move if the label is invalid. + if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. + + // Advance row if new location. + if (BaseLabel && Label) { + MCSymbol *ThisSym = Label; + if (ThisSym != BaseLabel) { + streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); + BaseLabel = ThisSym; + } + } + + EmitCFIInstruction(streamer, Instr); + } +} + +static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + unsigned format = symbolEncoding & 0x0f; + unsigned application = symbolEncoding & 0x70; + unsigned size; + switch (format) { + default: + assert(0 && "Unknown Encoding"); + case dwarf::DW_EH_PE_absptr: + case dwarf::DW_EH_PE_signed: + size = asmInfo.getPointerSize(); + break; + case dwarf::DW_EH_PE_udata2: + case dwarf::DW_EH_PE_sdata2: + size = 2; + break; + case dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_sdata4: + size = 4; + break; + case dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_sdata8: + size = 8; + break; + } + switch (application) { + default: + assert(0 && "Unknown Encoding"); + break; + case 0: + streamer.EmitSymbolValue(&symbol, size); + break; + case dwarf::DW_EH_PE_pcrel: + streamer.EmitPCRelSymbolValue(&symbol, size); + break; + } +} + +static const MachineLocation TranslateMachineLocation( + const TargetAsmInfo &AsmInfo, + const MachineLocation &Loc) { + unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? + MachineLocation::VirtualFP : + unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); + const MachineLocation &NewLoc = Loc.isReg() ? + MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); + return NewLoc; +} + +static const MCSymbol &EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + const MCSection §ion = *asmInfo.getEHFrameSection(); + streamer.SwitchSection(§ion); + MCSymbol *sectionStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol(); + + // Length + const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, + *sectionEnd, 4); + streamer.EmitLabel(sectionStart); + streamer.EmitValue(Length, 4); + + // CIE ID + streamer.EmitIntValue(0, 4); + + // Version + streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); + + // Augmentation String + SmallString<8> Augmentation; + Augmentation += "z"; + if (personality) + Augmentation += "P"; + if (lsda) + Augmentation += "L"; + Augmentation += "R"; + streamer.EmitBytes(Augmentation.str(), 0); + streamer.EmitIntValue(0, 1); + + // Code Alignment Factor + streamer.EmitULEB128IntValue(1); + + // Data Alignment Factor + streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); + + // Return Address Register + streamer.EmitULEB128IntValue(asmInfo.getDwarfRARegNum(true)); + + // Augmentation Data Length (optional) + MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); + const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, + *augmentationStart, + *augmentationEnd, 0); + streamer.EmitULEB128Value(augmentationLength); + + // Augmentation Data (optional) + streamer.EmitLabel(augmentationStart); + if (personality) { + // Personality Encoding + streamer.EmitIntValue(personalityEncoding, 1); + // Personality + EmitSymbol(streamer, *personality, personalityEncoding); + } + if (lsda) { + // LSDA Encoding + streamer.EmitIntValue(lsdaEncoding, 1); + } + // Encoding of the FDE pointers + streamer.EmitIntValue(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4, 1); + streamer.EmitLabel(augmentationEnd); + + // Initial Instructions + + const std::vector Moves = asmInfo.getInitialFrameState(); + std::vector Instructions; + + for (int i = 0, n = Moves.size(); i != n; ++i) { + MCSymbol *Label = Moves[i].getLabel(); + const MachineLocation &Dst = + TranslateMachineLocation(asmInfo, Moves[i].getDestination()); + const MachineLocation &Src = + TranslateMachineLocation(asmInfo, Moves[i].getSource()); + MCCFIInstruction Inst(Label, Dst, Src); + Instructions.push_back(Inst); + } + + EmitCFIInstructions(streamer, Instructions, NULL); + + // Padding + streamer.EmitValueToAlignment(4); + + streamer.EmitLabel(sectionEnd); + return *sectionStart; +} + +static MCSymbol *EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame) { + MCContext &context = streamer.getContext(); + MCSymbol *fdeStart = context.CreateTempSymbol(); + MCSymbol *fdeEnd = context.CreateTempSymbol(); + + // Length + const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); + streamer.EmitValue(Length, 4); + + streamer.EmitLabel(fdeStart); + // CIE Pointer + const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, + 0); + streamer.EmitValue(offset, 4); + + // PC Begin + streamer.EmitPCRelSymbolValue(frame.Begin, 4); + + // PC Range + const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, + *frame.End, 0); + streamer.EmitValue(Range, 4); + + // Augmentation Data Length + MCSymbol *augmentationStart = streamer.getContext().CreateTempSymbol(); + MCSymbol *augmentationEnd = streamer.getContext().CreateTempSymbol(); + const MCExpr *augmentationLength = MakeStartMinusEndExpr(streamer, + *augmentationStart, + *augmentationEnd, 0); + streamer.EmitULEB128Value(augmentationLength); + + // Augmentation Data + streamer.EmitLabel(augmentationStart); + if (frame.Lsda) + EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding); + streamer.EmitLabel(augmentationEnd); + // Call Frame Instructions + + EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); + + // Padding + streamer.EmitValueToAlignment(4); + + return fdeEnd; +} + +namespace { + struct CIEKey { + static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1); } + static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0); } + + CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, + unsigned LsdaEncoding_) : Personality(Personality_), + PersonalityEncoding(PersonalityEncoding_), + LsdaEncoding(LsdaEncoding_) { + } + const MCSymbol* Personality; + unsigned PersonalityEncoding; + unsigned LsdaEncoding; + }; +} + +namespace llvm { + template <> + struct DenseMapInfo { + static CIEKey getEmptyKey() { + return CIEKey::getEmptyKey(); + } + static CIEKey getTombstoneKey() { + return CIEKey::getTombstoneKey(); + } + static unsigned getHashValue(const CIEKey &Key) { + FoldingSetNodeID ID; + ID.AddPointer(Key.Personality); + ID.AddInteger(Key.PersonalityEncoding); + ID.AddInteger(Key.LsdaEncoding); + return ID.ComputeHash(); + } + static bool isEqual(const CIEKey &LHS, + const CIEKey &RHS) { + return LHS.Personality == RHS.Personality && + LHS.PersonalityEncoding == RHS.PersonalityEncoding && + LHS.LsdaEncoding == RHS.LsdaEncoding; + } + }; +} + +void MCDwarfFrameEmitter::Emit(MCStreamer &streamer) { + const MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + MCSymbol *fdeEnd = NULL; + DenseMap CIEStarts; + + for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { + const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); + CIEKey key(frame.Personality, frame.PersonalityEncoding, + frame.LsdaEncoding); + const MCSymbol *&cieStart = CIEStarts[key]; + if (!cieStart) + cieStart = &EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + fdeEnd = EmitFDE(streamer, *cieStart, frame); + if (i != n - 1) + streamer.EmitLabel(fdeEnd); + } + + streamer.EmitValueToAlignment(asmInfo.getPointerSize()); + if (fdeEnd) + streamer.EmitLabel(fdeEnd); +} + +void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, + uint64_t AddrDelta) { + SmallString<256> Tmp; + raw_svector_ostream OS(Tmp); + MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); + Streamer.EmitBytes(OS.str(), /*AddrSpace=*/0); +} + +void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, + raw_ostream &OS) { + // FIXME: Assumes the code alignment factor is 1. + if (AddrDelta == 0) { + } else if (isUIntN(6, AddrDelta)) { + uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; + OS << Opcode; + } else if (isUInt<8>(AddrDelta)) { + OS << uint8_t(dwarf::DW_CFA_advance_loc1); + OS << uint8_t(AddrDelta); + } else if (isUInt<16>(AddrDelta)) { + // FIXME: check what is the correct behavior on a big endian machine. + OS << uint8_t(dwarf::DW_CFA_advance_loc2); + OS << uint8_t( AddrDelta & 0xff); + OS << uint8_t((AddrDelta >> 8) & 0xff); + } else { + // FIXME: check what is the correct behavior on a big endian machine. + assert(isUInt<32>(AddrDelta)); + OS << uint8_t(dwarf::DW_CFA_advance_loc4); + OS << uint8_t( AddrDelta & 0xff); + OS << uint8_t((AddrDelta >> 8) & 0xff); + OS << uint8_t((AddrDelta >> 16) & 0xff); + OS << uint8_t((AddrDelta >> 24) & 0xff); + + } +} diff --git a/final/lib/MC/MCELF.cpp b/final/lib/MC/MCELF.cpp new file mode 100644 index 00000000000..ce7783e2862 --- /dev/null +++ b/final/lib/MC/MCELF.cpp @@ -0,0 +1,72 @@ +//===- lib/MC/MCELF.cpp - MC ELF ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF object file writer information. +// +//===----------------------------------------------------------------------===// + +#include "MCELF.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/Support/ELF.h" +#include "llvm/Target/TargetAsmBackend.h" + +namespace llvm { + +void MCELF::SetBinding(MCSymbolData &SD, unsigned Binding) { + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STB_Shift); + SD.setFlags(OtherFlags | (Binding << ELF_STB_Shift)); +} + +unsigned MCELF::GetBinding(const MCSymbolData &SD) { + uint32_t Binding = (SD.getFlags() & (0xf << ELF_STB_Shift)) >> ELF_STB_Shift; + assert(Binding == ELF::STB_LOCAL || Binding == ELF::STB_GLOBAL || + Binding == ELF::STB_WEAK); + return Binding; +} + +void MCELF::SetType(MCSymbolData &SD, unsigned Type) { + assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || + Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || + Type == ELF::STT_FILE || Type == ELF::STT_COMMON || + Type == ELF::STT_TLS); + + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STT_Shift); + SD.setFlags(OtherFlags | (Type << ELF_STT_Shift)); +} + +unsigned MCELF::GetType(const MCSymbolData &SD) { + uint32_t Type = (SD.getFlags() & (0xf << ELF_STT_Shift)) >> ELF_STT_Shift; + assert(Type == ELF::STT_NOTYPE || Type == ELF::STT_OBJECT || + Type == ELF::STT_FUNC || Type == ELF::STT_SECTION || + Type == ELF::STT_FILE || Type == ELF::STT_COMMON || + Type == ELF::STT_TLS); + return Type; +} + +void MCELF::SetVisibility(MCSymbolData &SD, unsigned Visibility) { + assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || + Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); + + uint32_t OtherFlags = SD.getFlags() & ~(0xf << ELF_STV_Shift); + SD.setFlags(OtherFlags | (Visibility << ELF_STV_Shift)); +} + +unsigned MCELF::GetVisibility(MCSymbolData &SD) { + unsigned Visibility = + (SD.getFlags() & (0xf << ELF_STV_Shift)) >> ELF_STV_Shift; + assert(Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_INTERNAL || + Visibility == ELF::STV_HIDDEN || Visibility == ELF::STV_PROTECTED); + return Visibility; +} + +} diff --git a/final/lib/MC/MCELF.h b/final/lib/MC/MCELF.h new file mode 100644 index 00000000000..e08f1e65429 --- /dev/null +++ b/final/lib/MC/MCELF.h @@ -0,0 +1,35 @@ +//===- lib/MC/MCELF.h - ELF MC --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some support functions used by the ELF Streamer and +// ObjectWriter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELF_H +#define LLVM_MC_MCELF_H + +#include "llvm/MC/MCExpr.h" + +namespace llvm { +class MCSymbolData; + +class MCELF { + public: + static void SetBinding(MCSymbolData &SD, unsigned Binding); + static unsigned GetBinding(const MCSymbolData &SD); + static void SetType(MCSymbolData &SD, unsigned Type); + static unsigned GetType(const MCSymbolData &SD); + static void SetVisibility(MCSymbolData &SD, unsigned Visibility); + static unsigned GetVisibility(MCSymbolData &SD); +}; + +} + +#endif diff --git a/final/lib/MC/MCELFObjectTargetWriter.cpp b/final/lib/MC/MCELFObjectTargetWriter.cpp new file mode 100644 index 00000000000..12a02a9e974 --- /dev/null +++ b/final/lib/MC/MCELFObjectTargetWriter.cpp @@ -0,0 +1,23 @@ +//===-- MCELFObjectTargetWriter.cpp - ELF Target Writer Subclass ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCELFObjectWriter.h" + +using namespace llvm; + +MCELFObjectTargetWriter::MCELFObjectTargetWriter(bool Is64Bit_, + Triple::OSType OSType_, + uint16_t EMachine_, + bool HasRelocationAddend_) + : OSType(OSType_), EMachine(EMachine_), + HasRelocationAddend(HasRelocationAddend_), Is64Bit(Is64Bit_) { +} + +MCELFObjectTargetWriter::~MCELFObjectTargetWriter() { +} diff --git a/final/lib/MC/MCELFStreamer.cpp b/final/lib/MC/MCELFStreamer.cpp new file mode 100644 index 00000000000..9fc9173914d --- /dev/null +++ b/final/lib/MC/MCELFStreamer.cpp @@ -0,0 +1,383 @@ +//===- lib/MC/MCELFStreamer.cpp - ELF Object Output ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits ELF .o object files. +// +//===----------------------------------------------------------------------===// + +#include "MCELFStreamer.h" +#include "MCELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCELFSymbolFlags.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" + +using namespace llvm; + +void MCELFStreamer::InitSections() { + // This emulates the same behavior of GNU as. This makes it easier + // to compare the output as the major sections are in the same order. + SetSectionText(); + SetSectionData(); + SetSectionBss(); + SetSectionText(); +} + +void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + MCObjectStreamer::EmitLabel(Symbol); + + const MCSectionELF &Section = + static_cast(Symbol->getSection()); + MCSymbolData &SD = getAssembler().getSymbolData(*Symbol); + if (Section.getFlags() & ELF::SHF_TLS) + MCELF::SetType(SD, ELF::STT_TLS); +} + +void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + switch (Flag) { + case MCAF_SyntaxUnified: return; // no-op here. + case MCAF_Code16: return; // no-op here. + case MCAF_Code32: return; // no-op here. + case MCAF_SubsectionsViaSymbols: + getAssembler().setSubsectionsViaSymbols(true); + return; + } + + assert(0 && "invalid assembler flag!"); +} + +void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { + // FIXME: Anything needed here to flag the function as thumb? +} + +void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + // FIXME: Lift context changes into super class. + getAssembler().getOrCreateSymbolData(*Symbol); + Symbol->setVariableValue(AddValueSymbols(Value)); +} + +void MCELFStreamer::ChangeSection(const MCSection *Section) { + const MCSymbol *Grp = static_cast(Section)->getGroup(); + if (Grp) + getAssembler().getOrCreateSymbolData(*Grp); + this->MCObjectStreamer::ChangeSection(Section); +} + +void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + getAssembler().getOrCreateSymbolData(*Symbol); + MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias); + AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref); + const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext()); + Alias->setVariableValue(Value); +} + +void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + // Indirect symbols are handled differently, to match how 'as' handles + // them. This makes writing matching .o files easier. + if (Attribute == MCSA_IndirectSymbol) { + // Note that we intentionally cannot use the symbol data here; this is + // important for matching the string table that 'as' generates. + IndirectSymbolData ISD; + ISD.Symbol = Symbol; + ISD.SectionData = getCurrentSectionData(); + getAssembler().getIndirectSymbols().push_back(ISD); + return; + } + + // Adding a symbol attribute always introduces the symbol, note that an + // important side effect of calling getOrCreateSymbolData here is to register + // the symbol with the assembler. + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // The implementation of symbol attributes is designed to match 'as', but it + // leaves much to desired. It doesn't really make sense to arbitrarily add and + // remove flags, but 'as' allows this (in particular, see .desc). + // + // In the future it might be worth trying to make these operations more well + // defined. + switch (Attribute) { + case MCSA_LazyReference: + case MCSA_Reference: + case MCSA_NoDeadStrip: + case MCSA_SymbolResolver: + case MCSA_PrivateExtern: + case MCSA_WeakDefinition: + case MCSA_WeakDefAutoPrivate: + case MCSA_Invalid: + case MCSA_ELF_TypeIndFunction: + case MCSA_IndirectSymbol: + assert(0 && "Invalid symbol attribute for ELF!"); + break; + + case MCSA_ELF_TypeGnuUniqueObject: + // Ignore for now. + break; + + case MCSA_Global: + MCELF::SetBinding(SD, ELF::STB_GLOBAL); + SD.setExternal(true); + BindingExplicitlySet.insert(Symbol); + break; + + case MCSA_WeakReference: + case MCSA_Weak: + MCELF::SetBinding(SD, ELF::STB_WEAK); + SD.setExternal(true); + BindingExplicitlySet.insert(Symbol); + break; + + case MCSA_Local: + MCELF::SetBinding(SD, ELF::STB_LOCAL); + SD.setExternal(false); + BindingExplicitlySet.insert(Symbol); + break; + + case MCSA_ELF_TypeFunction: + MCELF::SetType(SD, ELF::STT_FUNC); + break; + + case MCSA_ELF_TypeObject: + MCELF::SetType(SD, ELF::STT_OBJECT); + break; + + case MCSA_ELF_TypeTLS: + MCELF::SetType(SD, ELF::STT_TLS); + break; + + case MCSA_ELF_TypeCommon: + MCELF::SetType(SD, ELF::STT_COMMON); + break; + + case MCSA_ELF_TypeNoType: + MCELF::SetType(SD, ELF::STT_NOTYPE); + break; + + case MCSA_Protected: + MCELF::SetVisibility(SD, ELF::STV_PROTECTED); + break; + + case MCSA_Hidden: + MCELF::SetVisibility(SD, ELF::STV_HIDDEN); + break; + + case MCSA_Internal: + MCELF::SetVisibility(SD, ELF::STV_INTERNAL); + break; + } +} + +void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + if (!BindingExplicitlySet.count(Symbol)) { + MCELF::SetBinding(SD, ELF::STB_GLOBAL); + SD.setExternal(true); + } + + MCELF::SetType(SD, ELF::STT_OBJECT); + + if (MCELF::GetBinding(SD) == ELF_STB_Local) { + const MCSection *Section = getAssembler().getContext().getELFSection(".bss", + ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, + SectionKind::getBSS()); + Symbol->setSection(*Section); + + struct LocalCommon L = {&SD, Size, ByteAlignment}; + LocalCommons.push_back(L); + } else { + SD.setCommon(Size, ByteAlignment); + } + + SD.setSize(MCConstantExpr::Create(Size, getContext())); +} + +void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + // FIXME: Should this be caught and done earlier? + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + MCELF::SetBinding(SD, ELF::STB_LOCAL); + SD.setExternal(false); + BindingExplicitlySet.insert(Symbol); + // FIXME: ByteAlignment is not needed here, but is required. + EmitCommonSymbol(Symbol, Size, 1); +} + +void MCELFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); +} + +void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, + getCurrentSectionData()); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void MCELFStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, + getCurrentSectionData()); + F->setEmitNops(true); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +// Add a symbol for the file name of this module. This is the second +// entry in the module's symbol table (the first being the null symbol). +void MCELFStreamer::EmitFileDirective(StringRef Filename) { + MCSymbol *Symbol = getAssembler().getContext().GetOrCreateSymbol(Filename); + Symbol->setSection(*getCurrentSection()); + Symbol->setAbsolute(); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + SD.setFlags(ELF_STT_File | ELF_STB_Local | ELF_STV_Default); +} + +void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { + switch (expr->getKind()) { + case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *be = cast(expr); + fixSymbolsInTLSFixups(be->getLHS()); + fixSymbolsInTLSFixups(be->getRHS()); + break; + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &symRef = *cast(expr); + switch (symRef.getKind()) { + default: + return; + case MCSymbolRefExpr::VK_GOTTPOFF: + case MCSymbolRefExpr::VK_INDNTPOFF: + case MCSymbolRefExpr::VK_NTPOFF: + case MCSymbolRefExpr::VK_GOTNTPOFF: + case MCSymbolRefExpr::VK_TLSGD: + case MCSymbolRefExpr::VK_TLSLD: + case MCSymbolRefExpr::VK_TLSLDM: + case MCSymbolRefExpr::VK_TPOFF: + case MCSymbolRefExpr::VK_DTPOFF: + case MCSymbolRefExpr::VK_ARM_TLSGD: + case MCSymbolRefExpr::VK_ARM_TPOFF: + case MCSymbolRefExpr::VK_ARM_GOTTPOFF: + break; + } + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol()); + MCELF::SetType(SD, ELF::STT_TLS); + break; + } + + case MCExpr::Unary: + fixSymbolsInTLSFixups(cast(expr)->getSubExpr()); + break; + } +} + +void MCELFStreamer::EmitInstToFragment(const MCInst &Inst) { + this->MCObjectStreamer::EmitInstToFragment(Inst); + MCInstFragment &F = *cast(getCurrentFragment()); + + for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) + fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); +} + +void MCELFStreamer::EmitInstToData(const MCInst &Inst) { + MCDataFragment *DF = getOrCreateDataFragment(); + + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + VecOS.flush(); + + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) + fixSymbolsInTLSFixups(Fixups[i].getValue()); + + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->addFixup(Fixups[i]); + } + DF->getContents().append(Code.begin(), Code.end()); +} + +void MCELFStreamer::Finish() { + if (getNumFrameInfos()) + MCDwarfFrameEmitter::Emit(*this); + + for (std::vector::const_iterator i = LocalCommons.begin(), + e = LocalCommons.end(); + i != e; ++i) { + MCSymbolData *SD = i->SD; + uint64_t Size = i->Size; + unsigned ByteAlignment = i->ByteAlignment; + const MCSymbol &Symbol = SD->getSymbol(); + const MCSection &Section = Symbol.getSection(); + + MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section); + new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData); + + MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); + SD->setFragment(F); + + // Update the maximum alignment of the section if necessary. + if (ByteAlignment > SectData.getAlignment()) + SectData.setAlignment(ByteAlignment); + } + + this->MCObjectStreamer::Finish(); +} + +MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool NoExecStack) { + MCELFStreamer *S = new MCELFStreamer(Context, TAB, OS, CE); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + if (NoExecStack) + S->getAssembler().setNoExecStack(true); + return S; +} diff --git a/final/lib/MC/MCELFStreamer.h b/final/lib/MC/MCELFStreamer.h new file mode 100644 index 00000000000..091101dceba --- /dev/null +++ b/final/lib/MC/MCELFStreamer.h @@ -0,0 +1,268 @@ +//===- lib/MC/MCELFStreamer.h - ELF Object Output -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits ELF .o object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + ~MCELFStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolType(int Type) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EndCOFFSymbolDef() { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setSize(Value); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + + virtual void EmitFileDirective(StringRef Filename); + + virtual void Finish(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector LocalCommons; + + SmallPtrSet BindingExplicitlySet; + /// @} + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); + } + + void SetSectionData() { + SetSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + void SetSectionText() { + SetSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + void SetSectionBss() { + SetSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } +}; + +} // end llvm namespace + +#endif +//===- lib/MC/MCELFStreamer.h - ELF Object Output -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file assembles .s files and emits ELF .o object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCELFSTREAMER_H +#define LLVM_MC_MCELFSTREAMER_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSectionELF.h" + +namespace llvm { + +class MCELFStreamer : public MCObjectStreamer { +public: + MCELFStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + ~MCELFStreamer() {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void ChangeSection(const MCSection *Section); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitCOFFSymbolType(int Type) { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EndCOFFSymbolDef() { + assert(0 && "ELF doesn't support this directive"); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setSize(Value); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + assert(0 && "ELF doesn't support this directive"); + } + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + + virtual void EmitFileDirective(StringRef Filename); + + virtual void Finish(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + + void fixSymbolsInTLSFixups(const MCExpr *expr); + + struct LocalCommon { + MCSymbolData *SD; + uint64_t Size; + unsigned ByteAlignment; + }; + std::vector LocalCommons; + + SmallPtrSet BindingExplicitlySet; + /// @} + void SetSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind) { + SwitchSection(getContext().getELFSection(Section, Type, Flags, Kind)); + } + + void SetSectionData() { + SetSection(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + void SetSectionText() { + SetSection(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + void SetSectionBss() { + SetSection(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } +}; + +} // end llvm namespace + +#endif diff --git a/final/lib/MC/MCExpr.cpp b/final/lib/MC/MCExpr.cpp new file mode 100644 index 00000000000..54d3743e68e --- /dev/null +++ b/final/lib/MC/MCExpr.cpp @@ -0,0 +1,556 @@ +//===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mcexpr" +#include "llvm/MC/MCExpr.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +namespace { +namespace stats { +STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations"); +} +} + +void MCExpr::print(raw_ostream &OS) const { + switch (getKind()) { + case MCExpr::Target: + return cast(this)->PrintImpl(OS); + case MCExpr::Constant: + OS << cast(*this).getValue(); + return; + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SRE = cast(*this); + const MCSymbol &Sym = SRE.getSymbol(); + // Parenthesize names that start with $ so that they don't look like + // absolute names. + bool UseParens = Sym.getName()[0] == '$'; + + if (SRE.getKind() == MCSymbolRefExpr::VK_PPC_HA16 || + SRE.getKind() == MCSymbolRefExpr::VK_PPC_LO16) { + OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + UseParens = true; + } + + if (UseParens) + OS << '(' << Sym << ')'; + else + OS << Sym; + + if (SRE.getKind() == MCSymbolRefExpr::VK_ARM_PLT || + SRE.getKind() == MCSymbolRefExpr::VK_ARM_TLSGD || + SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOT || + SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTOFF || + SRE.getKind() == MCSymbolRefExpr::VK_ARM_TPOFF || + SRE.getKind() == MCSymbolRefExpr::VK_ARM_GOTTPOFF) + OS << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + else if (SRE.getKind() != MCSymbolRefExpr::VK_None && + SRE.getKind() != MCSymbolRefExpr::VK_PPC_HA16 && + SRE.getKind() != MCSymbolRefExpr::VK_PPC_LO16) + OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); + + return; + } + + case MCExpr::Unary: { + const MCUnaryExpr &UE = cast(*this); + switch (UE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCUnaryExpr::LNot: OS << '!'; break; + case MCUnaryExpr::Minus: OS << '-'; break; + case MCUnaryExpr::Not: OS << '~'; break; + case MCUnaryExpr::Plus: OS << '+'; break; + } + OS << *UE.getSubExpr(); + return; + } + + case MCExpr::Binary: { + const MCBinaryExpr &BE = cast(*this); + + // Only print parens around the LHS if it is non-trivial. + if (isa(BE.getLHS()) || isa(BE.getLHS())) { + OS << *BE.getLHS(); + } else { + OS << '(' << *BE.getLHS() << ')'; + } + + switch (BE.getOpcode()) { + default: assert(0 && "Invalid opcode!"); + case MCBinaryExpr::Add: + // Print "X-42" instead of "X+-42". + if (const MCConstantExpr *RHSC = dyn_cast(BE.getRHS())) { + if (RHSC->getValue() < 0) { + OS << RHSC->getValue(); + return; + } + } + + OS << '+'; + break; + case MCBinaryExpr::And: OS << '&'; break; + case MCBinaryExpr::Div: OS << '/'; break; + case MCBinaryExpr::EQ: OS << "=="; break; + case MCBinaryExpr::GT: OS << '>'; break; + case MCBinaryExpr::GTE: OS << ">="; break; + case MCBinaryExpr::LAnd: OS << "&&"; break; + case MCBinaryExpr::LOr: OS << "||"; break; + case MCBinaryExpr::LT: OS << '<'; break; + case MCBinaryExpr::LTE: OS << "<="; break; + case MCBinaryExpr::Mod: OS << '%'; break; + case MCBinaryExpr::Mul: OS << '*'; break; + case MCBinaryExpr::NE: OS << "!="; break; + case MCBinaryExpr::Or: OS << '|'; break; + case MCBinaryExpr::Shl: OS << "<<"; break; + case MCBinaryExpr::Shr: OS << ">>"; break; + case MCBinaryExpr::Sub: OS << '-'; break; + case MCBinaryExpr::Xor: OS << '^'; break; + } + + // Only print parens around the LHS if it is non-trivial. + if (isa(BE.getRHS()) || isa(BE.getRHS())) { + OS << *BE.getRHS(); + } else { + OS << '(' << *BE.getRHS() << ')'; + } + return; + } + } + + assert(0 && "Invalid expression kind!"); +} + +void MCExpr::dump() const { + print(dbgs()); + dbgs() << '\n'; +} + +/* *** */ + +const MCBinaryExpr *MCBinaryExpr::Create(Opcode Opc, const MCExpr *LHS, + const MCExpr *RHS, MCContext &Ctx) { + return new (Ctx) MCBinaryExpr(Opc, LHS, RHS); +} + +const MCUnaryExpr *MCUnaryExpr::Create(Opcode Opc, const MCExpr *Expr, + MCContext &Ctx) { + return new (Ctx) MCUnaryExpr(Opc, Expr); +} + +const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { + return new (Ctx) MCConstantExpr(Value); +} + +/* *** */ + +const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, + VariantKind Kind, + MCContext &Ctx) { + return new (Ctx) MCSymbolRefExpr(Sym, Kind); +} + +const MCSymbolRefExpr *MCSymbolRefExpr::Create(StringRef Name, VariantKind Kind, + MCContext &Ctx) { + return Create(Ctx.GetOrCreateSymbol(Name), Kind, Ctx); +} + +StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { + switch (Kind) { + default: + case VK_Invalid: return "<>"; + case VK_None: return "<>"; + + case VK_GOT: return "GOT"; + case VK_GOTOFF: return "GOTOFF"; + case VK_GOTPCREL: return "GOTPCREL"; + case VK_GOTTPOFF: return "GOTTPOFF"; + case VK_INDNTPOFF: return "INDNTPOFF"; + case VK_NTPOFF: return "NTPOFF"; + case VK_GOTNTPOFF: return "GOTNTPOFF"; + case VK_PLT: return "PLT"; + case VK_TLSGD: return "TLSGD"; + case VK_TLSLD: return "TLSLD"; + case VK_TLSLDM: return "TLSLDM"; + case VK_TPOFF: return "TPOFF"; + case VK_DTPOFF: return "DTPOFF"; + case VK_TLVP: return "TLVP"; + case VK_ARM_PLT: return "(PLT)"; + case VK_ARM_GOT: return "(GOT)"; + case VK_ARM_GOTOFF: return "(GOTOFF)"; + case VK_ARM_TPOFF: return "(tpoff)"; + case VK_ARM_GOTTPOFF: return "(gottpoff)"; + case VK_ARM_TLSGD: return "(tlsgd)"; + case VK_PPC_TOC: return "toc"; + case VK_PPC_HA16: return "ha16"; + case VK_PPC_LO16: return "lo16"; + } +} + +MCSymbolRefExpr::VariantKind +MCSymbolRefExpr::getVariantKindForName(StringRef Name) { + return StringSwitch(Name) + .Case("GOT", VK_GOT) + .Case("got", VK_GOT) + .Case("GOTOFF", VK_GOTOFF) + .Case("gotoff", VK_GOTOFF) + .Case("GOTPCREL", VK_GOTPCREL) + .Case("gotpcrel", VK_GOTPCREL) + .Case("GOTTPOFF", VK_GOTTPOFF) + .Case("gottpoff", VK_GOTTPOFF) + .Case("INDNTPOFF", VK_INDNTPOFF) + .Case("indntpoff", VK_INDNTPOFF) + .Case("NTPOFF", VK_NTPOFF) + .Case("ntpoff", VK_NTPOFF) + .Case("GOTNTPOFF", VK_GOTNTPOFF) + .Case("gotntpoff", VK_GOTNTPOFF) + .Case("PLT", VK_PLT) + .Case("plt", VK_PLT) + .Case("TLSGD", VK_TLSGD) + .Case("tlsgd", VK_TLSGD) + .Case("TLSLD", VK_TLSLD) + .Case("tlsld", VK_TLSLD) + .Case("TLSLDM", VK_TLSLDM) + .Case("tlsldm", VK_TLSLDM) + .Case("TPOFF", VK_TPOFF) + .Case("tpoff", VK_TPOFF) + .Case("DTPOFF", VK_DTPOFF) + .Case("dtpoff", VK_DTPOFF) + .Case("TLVP", VK_TLVP) + .Case("tlvp", VK_TLVP) + .Default(VK_Invalid); +} + +/* *** */ + +void MCTargetExpr::Anchor() {} + +/* *** */ + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res) const { + return EvaluateAsAbsolute(Res, 0, 0, 0); +} + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, + const MCAsmLayout &Layout) const { + return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, 0); +} + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, + const MCAsmLayout &Layout, + const SectionAddrMap &Addrs) const { + return EvaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs); +} + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { + return EvaluateAsAbsolute(Res, &Asm, 0, 0); +} + +bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs) const { + MCValue Value; + + // Fast path constants. + if (const MCConstantExpr *CE = dyn_cast(this)) { + Res = CE->getValue(); + return true; + } + + // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us + // absolutize differences across sections and that is what the MachO writer + // uses Addrs for. + bool IsRelocatable = + EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs); + + // Record the current value. + Res = Value.getConstant(); + + return IsRelocatable && Value.isAbsolute(); +} + +/// \brief Helper method for \see EvaluateSymbolAdd(). +static void AttemptToFoldSymbolOffsetDifference(const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, + bool InSet, + const MCSymbolRefExpr *&A, + const MCSymbolRefExpr *&B, + int64_t &Addend) { + if (!A || !B) + return; + + const MCSymbol &SA = A->getSymbol(); + const MCSymbol &SB = B->getSymbol(); + + if (SA.isUndefined() || SB.isUndefined()) + return; + + if (!Asm->getWriter().IsSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) + return; + + MCSymbolData &AD = Asm->getSymbolData(SA); + MCSymbolData &BD = Asm->getSymbolData(SB); + + if (AD.getFragment() == BD.getFragment()) { + Addend += (AD.getOffset() - BD.getOffset()); + + // Clear the symbol expr pointers to indicate we have folded these + // operands. + A = B = 0; + return; + } + + if (!Layout) + return; + + const MCSectionData &SecA = *AD.getFragment()->getParent(); + const MCSectionData &SecB = *BD.getFragment()->getParent(); + + if ((&SecA != &SecB) && !Addrs) + return; + + // Eagerly evaluate. + Addend += (Layout->getSymbolOffset(&Asm->getSymbolData(A->getSymbol())) - + Layout->getSymbolOffset(&Asm->getSymbolData(B->getSymbol()))); + if (Addrs && (&SecA != &SecB)) + Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); + + // Clear the symbol expr pointers to indicate we have folded these + // operands. + A = B = 0; +} + +/// \brief Evaluate the result of an add between (conceptually) two MCValues. +/// +/// This routine conceptually attempts to construct an MCValue: +/// Result = (Result_A - Result_B + Result_Cst) +/// from two MCValue's LHS and RHS where +/// Result = LHS + RHS +/// and +/// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). +/// +/// This routine attempts to aggresively fold the operands such that the result +/// is representable in an MCValue, but may not always succeed. +/// +/// \returns True on success, false if the result is not representable in an +/// MCValue. + +/// NOTE: It is really important to have both the Asm and Layout arguments. +/// They might look redundant, but this function can be used before layout +/// is done (see the object streamer for example) and having the Asm argument +/// lets us avoid relaxations early. +static bool EvaluateSymbolicAdd(const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, + bool InSet, + const MCValue &LHS,const MCSymbolRefExpr *RHS_A, + const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst, + MCValue &Res) { + // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy + // about dealing with modifiers. This will ultimately bite us, one day. + const MCSymbolRefExpr *LHS_A = LHS.getSymA(); + const MCSymbolRefExpr *LHS_B = LHS.getSymB(); + int64_t LHS_Cst = LHS.getConstant(); + + // Fold the result constant immediately. + int64_t Result_Cst = LHS_Cst + RHS_Cst; + + assert((!Layout || Asm) && + "Must have an assembler object if layout is given!"); + + // If we have a layout, we can fold resolved differences. + if (Asm) { + // First, fold out any differences which are fully resolved. By + // reassociating terms in + // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). + // we have the four possible differences: + // (LHS_A - LHS_B), + // (LHS_A - RHS_B), + // (RHS_A - LHS_B), + // (RHS_A - RHS_B). + // Since we are attempting to be as aggresive as possible about folding, we + // attempt to evaluate each possible alternative. + AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, + Result_Cst); + AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, + Result_Cst); + AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, + Result_Cst); + AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, + Result_Cst); + } + + // We can't represent the addition or subtraction of two symbols. + if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) + return false; + + // At this point, we have at most one additive symbol and one subtractive + // symbol -- find them. + const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; + const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; + + // If we have a negated symbol, then we must have also have a non-negated + // symbol in order to encode the expression. + if (B && !A) + return false; + + Res = MCValue::get(A, B, Result_Cst); + return true; +} + +bool MCExpr::EvaluateAsRelocatable(MCValue &Res, + const MCAsmLayout &Layout) const { + return EvaluateAsRelocatableImpl(Res, &Layout.getAssembler(), &Layout, + 0, false); +} + +bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, + const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, + bool InSet) const { + ++stats::MCExprEvaluate; + + switch (getKind()) { + case Target: + return cast(this)->EvaluateAsRelocatableImpl(Res, Layout); + + case Constant: + Res = MCValue::get(cast(this)->getValue()); + return true; + + case SymbolRef: { + const MCSymbolRefExpr *SRE = cast(this); + const MCSymbol &Sym = SRE->getSymbol(); + + // Evaluate recursively if this is a variable. + if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { + bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Asm, + Layout, + Addrs, + true); + // If we failed to simplify this to a constant, let the target + // handle it. + if (Ret && !Res.getSymA() && !Res.getSymB()) + return true; + } + + Res = MCValue::get(SRE, 0, 0); + return true; + } + + case Unary: { + const MCUnaryExpr *AUE = cast(this); + MCValue Value; + + if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, + Addrs, InSet)) + return false; + + switch (AUE->getOpcode()) { + case MCUnaryExpr::LNot: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(!Value.getConstant()); + break; + case MCUnaryExpr::Minus: + /// -(a - b + const) ==> (b - a - const) + if (Value.getSymA() && !Value.getSymB()) + return false; + Res = MCValue::get(Value.getSymB(), Value.getSymA(), + -Value.getConstant()); + break; + case MCUnaryExpr::Not: + if (!Value.isAbsolute()) + return false; + Res = MCValue::get(~Value.getConstant()); + break; + case MCUnaryExpr::Plus: + Res = Value; + break; + } + + return true; + } + + case Binary: { + const MCBinaryExpr *ABE = cast(this); + MCValue LHSValue, RHSValue; + + if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, + Addrs, InSet) || + !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, + Addrs, InSet)) + return false; + + // We only support a few operations on non-constant expressions, handle + // those first. + if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { + switch (ABE->getOpcode()) { + default: + return false; + case MCBinaryExpr::Sub: + // Negate RHS and add. + return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, + RHSValue.getSymB(), RHSValue.getSymA(), + -RHSValue.getConstant(), + Res); + + case MCBinaryExpr::Add: + return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, + RHSValue.getSymA(), RHSValue.getSymB(), + RHSValue.getConstant(), + Res); + } + } + + // FIXME: We need target hooks for the evaluation. It may be limited in + // width, and gas defines the result of comparisons and right shifts + // differently from Apple as. + int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); + int64_t Result = 0; + switch (ABE->getOpcode()) { + case MCBinaryExpr::Add: Result = LHS + RHS; break; + case MCBinaryExpr::And: Result = LHS & RHS; break; + case MCBinaryExpr::Div: Result = LHS / RHS; break; + case MCBinaryExpr::EQ: Result = LHS == RHS; break; + case MCBinaryExpr::GT: Result = LHS > RHS; break; + case MCBinaryExpr::GTE: Result = LHS >= RHS; break; + case MCBinaryExpr::LAnd: Result = LHS && RHS; break; + case MCBinaryExpr::LOr: Result = LHS || RHS; break; + case MCBinaryExpr::LT: Result = LHS < RHS; break; + case MCBinaryExpr::LTE: Result = LHS <= RHS; break; + case MCBinaryExpr::Mod: Result = LHS % RHS; break; + case MCBinaryExpr::Mul: Result = LHS * RHS; break; + case MCBinaryExpr::NE: Result = LHS != RHS; break; + case MCBinaryExpr::Or: Result = LHS | RHS; break; + case MCBinaryExpr::Shl: Result = LHS << RHS; break; + case MCBinaryExpr::Shr: Result = LHS >> RHS; break; + case MCBinaryExpr::Sub: Result = LHS - RHS; break; + case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; + } + + Res = MCValue::get(Result); + return true; + } + } + + assert(0 && "Invalid assembly expression kind!"); + return false; +} diff --git a/final/lib/MC/MCInst.cpp b/final/lib/MC/MCInst.cpp new file mode 100644 index 00000000000..4cb628b395c --- /dev/null +++ b/final/lib/MC/MCInst.cpp @@ -0,0 +1,66 @@ +//===- lib/MC/MCInst.cpp - MCInst implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void MCOperand::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + OS << ""; +} + +void MCOperand::dump() const { + print(dbgs(), 0); + dbgs() << "\n"; +} + +void MCInst::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + OS << ""; +} + +void MCInst::dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI, + const MCInstPrinter *Printer, + StringRef Separator) const { + OS << "getOpcodeName(getOpcode()); + + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + OS << Separator; + getOperand(i).print(OS, MAI); + } + OS << ">"; +} + +void MCInst::dump() const { + print(dbgs(), 0); + dbgs() << "\n"; +} diff --git a/final/lib/MC/MCInstPrinter.cpp b/final/lib/MC/MCInstPrinter.cpp new file mode 100644 index 00000000000..212b85eb1fe --- /dev/null +++ b/final/lib/MC/MCInstPrinter.cpp @@ -0,0 +1,26 @@ +//===-- MCInstPrinter.cpp - Convert an MCInst to target assembly syntax ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/ADT/StringRef.h" +using namespace llvm; + +MCInstPrinter::~MCInstPrinter() { +} + +/// getOpcodeName - Return the name of the specified opcode enum (e.g. +/// "MOV32ri") or empty if we can't resolve it. +StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const { + return ""; +} + +StringRef MCInstPrinter::getRegName(unsigned RegNo) const { + assert(0 && "Target should implement this"); + return ""; +} diff --git a/final/lib/MC/MCLabel.cpp b/final/lib/MC/MCLabel.cpp new file mode 100644 index 00000000000..9c0fc92e6c0 --- /dev/null +++ b/final/lib/MC/MCLabel.cpp @@ -0,0 +1,21 @@ +//===- lib/MC/MCLabel.cpp - MCLabel implementation ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCLabel.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +void MCLabel::print(raw_ostream &OS) const { + OS << '"' << getInstance() << '"'; +} + +void MCLabel::dump() const { + print(dbgs()); +} diff --git a/final/lib/MC/MCLoggingStreamer.cpp b/final/lib/MC/MCLoggingStreamer.cpp new file mode 100644 index 00000000000..012c7f62f8a --- /dev/null +++ b/final/lib/MC/MCLoggingStreamer.cpp @@ -0,0 +1,248 @@ +//===- lib/MC/MCLoggingStreamer.cpp - API Logging Streamer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { + +class MCLoggingStreamer : public MCStreamer { + llvm::OwningPtr Child; + + raw_ostream &OS; + +public: + MCLoggingStreamer(MCStreamer *_Child, raw_ostream &_OS) + : MCStreamer(_Child->getContext()), Child(_Child), OS(_OS) {} + + void LogCall(const char *Function) { + OS << Function << "\n"; + } + + void LogCall(const char *Function, const Twine &Message) { + OS << Function << ": " << Message << "\n"; + } + + virtual bool isVerboseAsm() const { return Child->isVerboseAsm(); } + + virtual bool hasRawTextSupport() const { return Child->hasRawTextSupport(); } + + virtual raw_ostream &GetCommentOS() { return Child->GetCommentOS(); } + + virtual void AddComment(const Twine &T) { + LogCall("AddComment", T); + return Child->AddComment(T); + } + + virtual void AddBlankLine() { + LogCall("AddBlankLine"); + return Child->AddBlankLine(); + } + + virtual void ChangeSection(const MCSection *Section) { + LogCall("ChangeSection"); + return Child->ChangeSection(Section); + } + + virtual void InitSections() { + LogCall("InitSections"); + return Child->InitSections(); + } + + virtual void EmitLabel(MCSymbol *Symbol) { + LogCall("EmitLabel"); + return Child->EmitLabel(Symbol); + } + + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { + LogCall("EmitAssemblerFlag"); + return Child->EmitAssemblerFlag(Flag); + } + + virtual void EmitThumbFunc(MCSymbol *Func) { + LogCall("EmitThumbFunc"); + return Child->EmitThumbFunc(Func); + } + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + LogCall("EmitAssignment"); + return Child->EmitAssignment(Symbol, Value); + } + + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { + LogCall("EmitWeakReference"); + return Child->EmitWeakReference(Alias, Symbol); + } + + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) { + LogCall("EmitDwarfAdvanceLineAddr"); + return Child->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label); + } + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { + LogCall("EmitSymbolAttribute"); + return Child->EmitSymbolAttribute(Symbol, Attribute); + } + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + LogCall("EmitSymbolDesc"); + return Child->EmitSymbolDesc(Symbol, DescValue); + } + + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + LogCall("BeginCOFFSymbolDef"); + return Child->BeginCOFFSymbolDef(Symbol); + } + + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + LogCall("EmitCOFFSymbolStorageClass"); + return Child->EmitCOFFSymbolStorageClass(StorageClass); + } + + virtual void EmitCOFFSymbolType(int Type) { + LogCall("EmitCOFFSymbolType"); + return Child->EmitCOFFSymbolType(Type); + } + + virtual void EndCOFFSymbolDef() { + LogCall("EndCOFFSymbolDef"); + return Child->EndCOFFSymbolDef(); + } + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + LogCall("EmitELFSize"); + return Child->EmitELFSize(Symbol, Value); + } + + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + LogCall("EmitCommonSymbol"); + return Child->EmitCommonSymbol(Symbol, Size, ByteAlignment); + } + + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + LogCall("EmitLocalCommonSymbol"); + return Child->EmitLocalCommonSymbol(Symbol, Size); + } + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) { + LogCall("EmitZerofill"); + return Child->EmitZerofill(Section, Symbol, Size, ByteAlignment); + } + + virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + LogCall("EmitTBSSSymbol"); + return Child->EmitTBSSSymbol(Section, Symbol, Size, ByteAlignment); + } + + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) { + LogCall("EmitBytes"); + return Child->EmitBytes(Data, AddrSpace); + } + + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace){ + LogCall("EmitValue"); + return Child->EmitValueImpl(Value, Size, isPCRel, AddrSpace); + } + + virtual void EmitULEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) { + LogCall("EmitULEB128Value"); + return Child->EmitULEB128Value(Value, AddrSpace); + } + + virtual void EmitSLEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) { + LogCall("EmitSLEB128Value"); + return Child->EmitSLEB128Value(Value, AddrSpace); + } + + virtual void EmitGPRel32Value(const MCExpr *Value) { + LogCall("EmitGPRel32Value"); + return Child->EmitGPRel32Value(Value); + } + + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace) { + LogCall("EmitFill"); + return Child->EmitFill(NumBytes, FillValue, AddrSpace); + } + + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) { + LogCall("EmitValueToAlignment"); + return Child->EmitValueToAlignment(ByteAlignment, Value, + ValueSize, MaxBytesToEmit); + } + + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) { + LogCall("EmitCodeAlignment"); + return Child->EmitCodeAlignment(ByteAlignment, MaxBytesToEmit); + } + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) { + LogCall("EmitValueToOffset"); + return Child->EmitValueToOffset(Offset, Value); + } + + virtual void EmitFileDirective(StringRef Filename) { + LogCall("EmitFileDirective", "FileName:" + Filename); + return Child->EmitFileDirective(Filename); + } + + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename) { + LogCall("EmitDwarfFileDirective", + "FileNo:" + Twine(FileNo) + " Filename:" + Filename); + return Child->EmitDwarfFileDirective(FileNo, Filename); + } + + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator) { + LogCall("EmitDwarfLocDirective", + "FileNo:" + Twine(FileNo) + " Line:" + Twine(Line) + + " Column:" + Twine(Column) + " Flags:" + Twine(Flags) + + " Isa:" + Twine(Isa) + " Discriminator:" + Twine(Discriminator)); + return Child->EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator); + } + + virtual void EmitInstruction(const MCInst &Inst) { + LogCall("EmitInstruction"); + return Child->EmitInstruction(Inst); + } + + virtual void EmitRawText(StringRef String) { + LogCall("EmitRawText", "\"" + String + "\""); + return Child->EmitRawText(String); + } + + virtual void Finish() { + LogCall("Finish"); + return Child->Finish(); + } + +}; + +} // end anonymous namespace. + +MCStreamer *llvm::createLoggingStreamer(MCStreamer *Child, raw_ostream &OS) { + return new MCLoggingStreamer(Child, OS); +} diff --git a/final/lib/MC/MCMachOStreamer.cpp b/final/lib/MC/MCMachOStreamer.cpp new file mode 100644 index 00000000000..d1f9f5cd568 --- /dev/null +++ b/final/lib/MC/MCMachOStreamer.cpp @@ -0,0 +1,405 @@ +//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" + +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCMachOSymbolFlags.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" + +using namespace llvm; + +namespace { + +class MCMachOStreamer : public MCObjectStreamer { +private: + virtual void EmitInstToData(const MCInst &Inst); + +public: + MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + assert(0 && "macho doesn't support this directive"); + } + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + assert(0 && "macho doesn't support this directive"); + } + virtual void EmitCOFFSymbolType(int Type) { + assert(0 && "macho doesn't support this directive"); + } + virtual void EndCOFFSymbolDef() { + assert(0 && "macho doesn't support this directive"); + } + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + assert(0 && "macho doesn't support this directive"); + } + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + assert(0 && "macho doesn't support this directive"); + } + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0); + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + + virtual void EmitFileDirective(StringRef Filename) { + // FIXME: Just ignore the .file; it isn't important enough to fail the + // entire assembly. + + //report_fatal_error("unsupported directive: '.file'"); + } + + virtual void Finish(); + + /// @} +}; + +} // end anonymous namespace. + +void MCMachOStreamer::InitSections() { + SwitchSection(getContext().getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText())); + +} + +void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + // isSymbolLinkerVisible uses the section. + Symbol->setSection(*getCurrentSection()); + // We have to create a new fragment if this is an atom defining symbol, + // fragments cannot span atoms. + if (getAssembler().isSymbolLinkerVisible(*Symbol)) + new MCDataFragment(getCurrentSectionData()); + + MCObjectStreamer::EmitLabel(Symbol); + + MCSymbolData &SD = getAssembler().getSymbolData(*Symbol); + // This causes the reference type flag to be cleared. Darwin 'as' was "trying" + // to clear the weak reference and weak definition bits too, but the + // implementation was buggy. For now we just try to match 'as', for + // diffability. + // + // FIXME: Cleanup this code, these bits should be emitted based on semantic + // properties, not on the order of definition, etc. + SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask); +} + +void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + // Let the target do whatever target specific stuff it needs to do. + getAssembler().getBackend().HandleAssemblerFlag(Flag); + // Do any generic stuff we need to do. + switch (Flag) { + case MCAF_SyntaxUnified: return; // no-op here. + case MCAF_Code16: return; // no-op here. + case MCAF_Code32: return; // no-op here. + case MCAF_SubsectionsViaSymbols: + getAssembler().setSubsectionsViaSymbols(true); + return; + default: + llvm_unreachable("invalid assembler flag!"); + } +} + +void MCMachOStreamer::EmitThumbFunc(MCSymbol *Symbol) { + // FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa. + + // Remember that the function is a thumb function. Fixup and relocation + // values will need adjusted. + getAssembler().setIsThumbFunc(Symbol); + + // Mark the thumb bit on the symbol. + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setFlags(SD.getFlags() | SF_ThumbFunc); +} + +void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + // FIXME: Lift context changes into super class. + getAssembler().getOrCreateSymbolData(*Symbol); + Symbol->setVariableValue(AddValueSymbols(Value)); +} + +void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + // Indirect symbols are handled differently, to match how 'as' handles + // them. This makes writing matching .o files easier. + if (Attribute == MCSA_IndirectSymbol) { + // Note that we intentionally cannot use the symbol data here; this is + // important for matching the string table that 'as' generates. + IndirectSymbolData ISD; + ISD.Symbol = Symbol; + ISD.SectionData = getCurrentSectionData(); + getAssembler().getIndirectSymbols().push_back(ISD); + return; + } + + // Adding a symbol attribute always introduces the symbol, note that an + // important side effect of calling getOrCreateSymbolData here is to register + // the symbol with the assembler. + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // The implementation of symbol attributes is designed to match 'as', but it + // leaves much to desired. It doesn't really make sense to arbitrarily add and + // remove flags, but 'as' allows this (in particular, see .desc). + // + // In the future it might be worth trying to make these operations more well + // defined. + switch (Attribute) { + case MCSA_Invalid: + case MCSA_ELF_TypeFunction: + case MCSA_ELF_TypeIndFunction: + case MCSA_ELF_TypeObject: + case MCSA_ELF_TypeTLS: + case MCSA_ELF_TypeCommon: + case MCSA_ELF_TypeNoType: + case MCSA_ELF_TypeGnuUniqueObject: + case MCSA_IndirectSymbol: + case MCSA_Hidden: + case MCSA_Internal: + case MCSA_Protected: + case MCSA_Weak: + case MCSA_Local: + assert(0 && "Invalid symbol attribute for Mach-O!"); + break; + + case MCSA_Global: + SD.setExternal(true); + // This effectively clears the undefined lazy bit, in Darwin 'as', although + // it isn't very consistent because it implements this as part of symbol + // lookup. + // + // FIXME: Cleanup this code, these bits should be emitted based on semantic + // properties, not on the order of definition, etc. + SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeUndefinedLazy); + break; + + case MCSA_LazyReference: + // FIXME: This requires -dynamic. + SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + if (Symbol->isUndefined()) + SD.setFlags(SD.getFlags() | SF_ReferenceTypeUndefinedLazy); + break; + + // Since .reference sets the no dead strip bit, it is equivalent to + // .no_dead_strip in practice. + case MCSA_Reference: + case MCSA_NoDeadStrip: + SD.setFlags(SD.getFlags() | SF_NoDeadStrip); + break; + + case MCSA_SymbolResolver: + SD.setFlags(SD.getFlags() | SF_SymbolResolver); + break; + + case MCSA_PrivateExtern: + SD.setExternal(true); + SD.setPrivateExtern(true); + break; + + case MCSA_WeakReference: + // FIXME: This requires -dynamic. + if (Symbol->isUndefined()) + SD.setFlags(SD.getFlags() | SF_WeakReference); + break; + + case MCSA_WeakDefinition: + // FIXME: 'as' enforces that this is defined and global. The manual claims + // it has to be in a coalesced section, but this isn't enforced. + SD.setFlags(SD.getFlags() | SF_WeakDefinition); + break; + + case MCSA_WeakDefAutoPrivate: + SD.setFlags(SD.getFlags() | SF_WeakDefinition | SF_WeakReference); + break; + } +} + +void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + // Encode the 'desc' value into the lowest implementation defined bits. + assert(DescValue == (DescValue & SF_DescFlagsMask) && + "Invalid .desc value!"); + getAssembler().getOrCreateSymbolData(*Symbol).setFlags( + DescValue & SF_DescFlagsMask); +} + +void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.setExternal(true); + SD.setCommon(Size, ByteAlignment); +} + +void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned ByteAlignment) { + MCSectionData &SectData = getAssembler().getOrCreateSectionData(*Section); + + // The symbol may not be present, which only creates the section. + if (!Symbol) + return; + + // FIXME: Assert that this section has the zerofill type. + + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // Emit an align fragment if necessary. + if (ByteAlignment != 1) + new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectData); + + MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); + SD.setFragment(F); + + Symbol->setSection(*Section); + + // Update the maximum alignment on the zero fill section if necessary. + if (ByteAlignment > SectData.getAlignment()) + SectData.setAlignment(ByteAlignment); +} + +// This should always be called with the thread local bss section. Like the +// .zerofill directive this doesn't actually switch sections on us. +void MCMachOStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + EmitZerofill(Section, Symbol, Size, ByteAlignment); + return; +} + +void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); +} + +void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, + getCurrentSectionData()); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, + getCurrentSectionData()); + F->setEmitNops(true); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitInstToData(const MCInst &Inst) { + MCDataFragment *DF = getOrCreateDataFragment(); + + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + VecOS.flush(); + + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->addFixup(Fixups[i]); + } + DF->getContents().append(Code.begin(), Code.end()); +} + +void MCMachOStreamer::Finish() { + // We have to set the fragment atom associations so we can relax properly for + // Mach-O. + + // First, scan the symbol table to build a lookup table from fragments to + // defining symbols. + DenseMap DefiningSymbolMap; + for (MCAssembler::symbol_iterator it = getAssembler().symbol_begin(), + ie = getAssembler().symbol_end(); it != ie; ++it) { + if (getAssembler().isSymbolLinkerVisible(it->getSymbol()) && + it->getFragment()) { + // An atom defining symbol should never be internal to a fragment. + assert(it->getOffset() == 0 && "Invalid offset in atom defining symbol!"); + DefiningSymbolMap[it->getFragment()] = it; + } + } + + // Set the fragment atom associations by tracking the last seen atom defining + // symbol. + for (MCAssembler::iterator it = getAssembler().begin(), + ie = getAssembler().end(); it != ie; ++it) { + MCSymbolData *CurrentAtom = 0; + for (MCSectionData::iterator it2 = it->begin(), + ie2 = it->end(); it2 != ie2; ++it2) { + if (MCSymbolData *SD = DefiningSymbolMap.lookup(it2)) + CurrentAtom = SD; + it2->setAtom(CurrentAtom); + } + } + + this->MCObjectStreamer::Finish(); +} + +MCStreamer *llvm::createMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll) { + MCMachOStreamer *S = new MCMachOStreamer(Context, TAB, OS, CE); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; +} diff --git a/final/lib/MC/MCMachObjectTargetWriter.cpp b/final/lib/MC/MCMachObjectTargetWriter.cpp new file mode 100644 index 00000000000..146cebf01a3 --- /dev/null +++ b/final/lib/MC/MCMachObjectTargetWriter.cpp @@ -0,0 +1,22 @@ +//===-- MCMachObjectTargetWriter.cpp - Mach-O Target Writer Subclass ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCMachObjectWriter.h" + +using namespace llvm; + +MCMachObjectTargetWriter::MCMachObjectTargetWriter( + bool Is64Bit_, uint32_t CPUType_, uint32_t CPUSubtype_, + bool UseAggressiveSymbolFolding_) + : Is64Bit(Is64Bit_), CPUType(CPUType_), CPUSubtype(CPUSubtype_), + UseAggressiveSymbolFolding(UseAggressiveSymbolFolding_) { +} + +MCMachObjectTargetWriter::~MCMachObjectTargetWriter() { +} diff --git a/final/lib/MC/MCNullStreamer.cpp b/final/lib/MC/MCNullStreamer.cpp new file mode 100644 index 00000000000..08ddf01d1a3 --- /dev/null +++ b/final/lib/MC/MCNullStreamer.cpp @@ -0,0 +1,104 @@ +//===- lib/MC/MCNullStreamer.cpp - Dummy Streamer Implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" + +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" + +using namespace llvm; + +namespace { + + class MCNullStreamer : public MCStreamer { + public: + MCNullStreamer(MCContext &Context) : MCStreamer(Context) {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections() { + } + + virtual void ChangeSection(const MCSection *Section) { + } + + virtual void EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + assert(getCurrentSection() && "Cannot emit before setting section!"); + Symbol->setSection(*getCurrentSection()); + } + + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {} + virtual void EmitThumbFunc(MCSymbol *Func) {} + + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {} + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol){} + virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) {} + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute){} + + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {} + + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) {} + virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} + virtual void EmitCOFFSymbolType(int Type) {} + virtual void EndCOFFSymbolDef() {} + + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) {} + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {} + + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0) {} + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) {} + virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} + + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) {} + virtual void EmitULEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) {} + virtual void EmitSLEB128Value(const MCExpr *Value, + unsigned AddrSpace = 0) {} + virtual void EmitGPRel32Value(const MCExpr *Value) {} + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) {} + + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) {} + + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0) {} + + virtual void EmitFileDirective(StringRef Filename) {} + virtual bool EmitDwarfFileDirective(unsigned FileNo,StringRef Filename) { + return false; + } + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator) {} + virtual void EmitInstruction(const MCInst &Inst) {} + + virtual void Finish() {} + + /// @} + }; + +} + +MCStreamer *llvm::createNullStreamer(MCContext &Context) { + return new MCNullStreamer(Context); +} diff --git a/final/lib/MC/MCObjectStreamer.cpp b/final/lib/MC/MCObjectStreamer.cpp new file mode 100644 index 00000000000..e67d9b03a95 --- /dev/null +++ b/final/lib/MC/MCObjectStreamer.cpp @@ -0,0 +1,270 @@ +//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCObjectStreamer.h" + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetAsmInfo.h" +using namespace llvm; + +MCObjectStreamer::MCObjectStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter_) + : MCStreamer(Context), + Assembler(new MCAssembler(Context, TAB, + *Emitter_, *TAB.createObjectWriter(OS), + OS)), + CurSectionData(0) +{ +} + +MCObjectStreamer::~MCObjectStreamer() { + delete &Assembler->getBackend(); + delete &Assembler->getEmitter(); + delete &Assembler->getWriter(); + delete Assembler; +} + +MCFragment *MCObjectStreamer::getCurrentFragment() const { + assert(getCurrentSectionData() && "No current section!"); + + if (!getCurrentSectionData()->empty()) + return &getCurrentSectionData()->getFragmentList().back(); + + return 0; +} + +MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { + MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); + if (!F) + F = new MCDataFragment(getCurrentSectionData()); + return F; +} + +const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { + switch (Value->getKind()) { + case MCExpr::Target: + cast(Value)->AddValueSymbols(Assembler); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Value); + AddValueSymbols(BE->getLHS()); + AddValueSymbols(BE->getRHS()); + break; + } + + case MCExpr::SymbolRef: + Assembler->getOrCreateSymbolData(cast(Value)->getSymbol()); + break; + + case MCExpr::Unary: + AddValueSymbols(cast(Value)->getSubExpr()); + break; + } + + return Value; +} + +void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, + bool isPCRel, unsigned AddrSpace) { + assert(AddrSpace == 0 && "Address space must be 0!"); + MCDataFragment *DF = getOrCreateDataFragment(); + + // Avoid fixups when possible. + int64_t AbsValue; + if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue, getAssembler())) { + EmitIntValue(AbsValue, Size, AddrSpace); + return; + } + DF->addFixup(MCFixup::Create(DF->getContents().size(), + Value, + MCFixup::getKindForSize(Size, isPCRel))); + DF->getContents().resize(DF->getContents().size() + Size, 0); +} + +void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { + assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); + assert(getCurrentSection() && "Cannot emit before setting section!"); + + Symbol->setSection(*getCurrentSection()); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // FIXME: This is wasteful, we don't necessarily need to create a data + // fragment. Instead, we should mark the symbol as pointing into the data + // fragment if it exists, otherwise we should just queue the label and set its + // fragment pointer when we emit the next fragment. + MCDataFragment *F = getOrCreateDataFragment(); + assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); + SD.setFragment(F); + SD.setOffset(F->getContents().size()); +} + +void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value, + unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { + EmitULEB128IntValue(IntValue, AddrSpace); + return; + } + new MCLEBFragment(*Value, false, getCurrentSectionData()); +} + +void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value, + unsigned AddrSpace) { + int64_t IntValue; + if (Value->EvaluateAsAbsolute(IntValue, getAssembler())) { + EmitSLEB128IntValue(IntValue, AddrSpace); + return; + } + new MCLEBFragment(*Value, true, getCurrentSectionData()); +} + +void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, + const MCSymbol *Symbol) { + report_fatal_error("This file format doesn't support weak aliases."); +} + +void MCObjectStreamer::ChangeSection(const MCSection *Section) { + assert(Section && "Cannot switch to a null section!"); + + CurSectionData = &getAssembler().getOrCreateSectionData(*Section); +} + +void MCObjectStreamer::EmitInstruction(const MCInst &Inst) { + // Scan for values. + for (unsigned i = Inst.getNumOperands(); i--; ) + if (Inst.getOperand(i).isExpr()) + AddValueSymbols(Inst.getOperand(i).getExpr()); + + getCurrentSectionData()->setHasInstructions(true); + + // Now that a machine instruction has been assembled into this section, make + // a line entry for any .loc directive that has been seen. + MCLineEntry::Make(this, getCurrentSection()); + + // If this instruction doesn't need relaxation, just emit it as data. + if (!getAssembler().getBackend().MayNeedRelaxation(Inst)) { + EmitInstToData(Inst); + return; + } + + // Otherwise, if we are relaxing everything, relax the instruction as much as + // possible and emit it as data. + if (getAssembler().getRelaxAll()) { + MCInst Relaxed; + getAssembler().getBackend().RelaxInstruction(Inst, Relaxed); + while (getAssembler().getBackend().MayNeedRelaxation(Relaxed)) + getAssembler().getBackend().RelaxInstruction(Relaxed, Relaxed); + EmitInstToData(Relaxed); + return; + } + + // Otherwise emit to a separate fragment. + EmitInstToFragment(Inst); +} + +void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst) { + MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData()); + + raw_svector_ostream VecOS(IF->getCode()); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, IF->getFixups()); +} + +static const MCExpr *BuildSymbolDiff(MCContext &Context, + const MCSymbol *A, const MCSymbol *B) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *ARef = + MCSymbolRefExpr::Create(A, Variant, Context); + const MCExpr *BRef = + MCSymbolRefExpr::Create(B, Variant, Context); + const MCExpr *AddrDelta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); + return AddrDelta; +} + +static const MCExpr *ForceExpAbs(MCObjectStreamer *Streamer, + MCContext &Context, const MCExpr* Expr) { + if (Context.getAsmInfo().hasAggressiveSymbolFolding()) + return Expr; + + MCSymbol *ABS = Context.CreateTempSymbol(); + Streamer->EmitAssignment(ABS, Expr); + return MCSymbolRefExpr::Create(ABS, Context); +} + +void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, + const MCSymbol *LastLabel, + const MCSymbol *Label) { + if (!LastLabel) { + int PointerSize = getContext().getTargetAsmInfo().getPointerSize(); + EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); + return; + } + const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); + int64_t Res; + if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { + MCDwarfLineAddr::Emit(this, LineDelta, Res); + return; + } + AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); + new MCDwarfLineAddrFragment(LineDelta, *AddrDelta, getCurrentSectionData()); +} + +void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) { + const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); + int64_t Res; + if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { + MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res); + return; + } + AddrDelta = ForceExpAbs(this, getContext(), AddrDelta); + new MCDwarfCallFrameFragment(*AddrDelta, getCurrentSectionData()); +} + +void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset, + unsigned char Value) { + int64_t Res; + if (Offset->EvaluateAsAbsolute(Res, getAssembler())) { + new MCOrgFragment(*Offset, Value, getCurrentSectionData()); + return; + } + + MCSymbol *CurrentPos = getContext().CreateTempSymbol(); + EmitLabel(CurrentPos); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *Ref = + MCSymbolRefExpr::Create(CurrentPos, Variant, getContext()); + const MCExpr *Delta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext()); + + if (!Delta->EvaluateAsAbsolute(Res, getAssembler())) + report_fatal_error("expected assembly-time absolute expression"); + EmitFill(Res, Value, 0); +} + +void MCObjectStreamer::Finish() { + // Dump out the dwarf file & directory tables and line tables. + if (getContext().hasDwarfFiles()) + MCDwarfFileTable::Emit(this); + + getAssembler().Finish(); +} diff --git a/final/lib/MC/MCObjectWriter.cpp b/final/lib/MC/MCObjectWriter.cpp new file mode 100644 index 00000000000..efe9f68ee22 --- /dev/null +++ b/final/lib/MC/MCObjectWriter.cpp @@ -0,0 +1,80 @@ +//===- lib/MC/MCObjectWriter.cpp - MCObjectWriter implementation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSymbol.h" + +using namespace llvm; + +MCObjectWriter::~MCObjectWriter() { +} + +/// Utility function to encode a SLEB128 value. +void MCObjectWriter::EncodeSLEB128(int64_t Value, raw_ostream &OS) { + bool More; + do { + uint8_t Byte = Value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + Value >>= 7; + More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || + ((Value == -1) && ((Byte & 0x40) != 0)))); + if (More) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (More); +} + +/// Utility function to encode a ULEB128 value. +void MCObjectWriter::EncodeULEB128(uint64_t Value, raw_ostream &OS) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value != 0) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (Value != 0); +} + +bool +MCObjectWriter::IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm, + const MCSymbolRefExpr *A, + const MCSymbolRefExpr *B, + bool InSet) const { + // Modified symbol references cannot be resolved. + if (A->getKind() != MCSymbolRefExpr::VK_None || + B->getKind() != MCSymbolRefExpr::VK_None) + return false; + + const MCSymbol &SA = A->getSymbol(); + const MCSymbol &SB = B->getSymbol(); + if (SA.AliasedSymbol().isUndefined() || SB.AliasedSymbol().isUndefined()) + return false; + + const MCSymbolData &DataA = Asm.getSymbolData(SA); + const MCSymbolData &DataB = Asm.getSymbolData(SB); + + return IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, + *DataB.getFragment(), + InSet, + false); +} + +bool +MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + const MCSection &SecA = DataA.getSymbol().AliasedSymbol().getSection(); + const MCSection &SecB = FB.getParent()->getSection(); + // On ELF and COFF A - B is absolute if A and B are in the same section. + return &SecA == &SecB; +} diff --git a/final/lib/MC/MCParser/AsmLexer.cpp b/final/lib/MC/MCParser/AsmLexer.cpp new file mode 100644 index 00000000000..89374d0c3fb --- /dev/null +++ b/final/lib/MC/MCParser/AsmLexer.cpp @@ -0,0 +1,430 @@ +//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the lexer for assembly files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/MC/MCAsmInfo.h" +#include +#include +#include +#include +using namespace llvm; + +AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { + CurBuf = NULL; + CurPtr = NULL; +} + +AsmLexer::~AsmLexer() { +} + +void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { + CurBuf = buf; + + if (ptr) + CurPtr = ptr; + else + CurPtr = CurBuf->getBufferStart(); + + TokStart = 0; +} + +/// ReturnError - Set the error to the specified string at the specified +/// location. This is defined to always return AsmToken::Error. +AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { + SetError(SMLoc::getFromPointer(Loc), Msg); + + return AsmToken(AsmToken::Error, StringRef(Loc, 0)); +} + +int AsmLexer::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. + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } +} + +/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)? +/// +/// The leading integral digit sequence and dot should have already been +/// consumed, some or all of the fractional digit sequence *can* have been +/// consumed. +AsmToken AsmLexer::LexFloatLiteral() { + // Skip the fractional digit sequence. + while (isdigit(*CurPtr)) + ++CurPtr; + + // Check for exponent; we intentionally accept a slighlty wider set of + // literals here and rely on the upstream client to reject invalid ones (e.g., + // "1e+"). + if (*CurPtr == 'e' || *CurPtr == 'E') { + ++CurPtr; + if (*CurPtr == '-' || *CurPtr == '+') + ++CurPtr; + while (isdigit(*CurPtr)) + ++CurPtr; + } + + return AsmToken(AsmToken::Real, + StringRef(TokStart, CurPtr - TokStart)); +} + +/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* +static bool IsIdentifierChar(char c) { + return isalnum(c) || c == '_' || c == '$' || c == '.' || c == '@'; +} +AsmToken AsmLexer::LexIdentifier() { + // Check for floating point literals. + if (CurPtr[-1] == '.' && isdigit(*CurPtr)) { + // Disambiguate a .1243foo identifier from a floating literal. + while (isdigit(*CurPtr)) + ++CurPtr; + if (*CurPtr == 'e' || *CurPtr == 'E' || !IsIdentifierChar(*CurPtr)) + return LexFloatLiteral(); + } + + while (IsIdentifierChar(*CurPtr)) + ++CurPtr; + + // Handle . as a special case. + if (CurPtr == TokStart+1 && TokStart[0] == '.') + return AsmToken(AsmToken::Dot, StringRef(TokStart, 1)); + + return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart)); +} + +/// LexSlash: Slash: / +/// C-Style Comment: /* ... */ +AsmToken AsmLexer::LexSlash() { + switch (*CurPtr) { + case '*': break; // C style comment. + case '/': return ++CurPtr, LexLineComment(); + default: return AsmToken(AsmToken::Slash, StringRef(CurPtr-1, 1)); + } + + // C Style comment. + ++CurPtr; // skip the star. + while (1) { + int CurChar = getNextChar(); + switch (CurChar) { + case EOF: + return ReturnError(TokStart, "unterminated comment"); + case '*': + // End of the comment? + if (CurPtr[0] != '/') break; + + ++CurPtr; // End the */. + return LexToken(); + } + } +} + +/// LexLineComment: Comment: #[^\n]* +/// : //[^\n]* +AsmToken AsmLexer::LexLineComment() { + // FIXME: This is broken if we happen to a comment at the end of a file, which + // was .included, and which doesn't end with a newline. + int CurChar = getNextChar(); + while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF) + CurChar = getNextChar(); + + if (CurChar == EOF) + return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0)); + return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0)); +} + +static void SkipIgnoredIntegerSuffix(const char *&CurPtr) { + if (CurPtr[0] == 'L' && CurPtr[1] == 'L') + CurPtr += 2; + if (CurPtr[0] == 'U' && CurPtr[1] == 'L' && CurPtr[2] == 'L') + CurPtr += 3; +} + +/// LexDigit: First character is [0-9]. +/// Local Label: [0-9][:] +/// Forward/Backward Label: [0-9][fb] +/// Binary integer: 0b[01]+ +/// Octal integer: 0[0-7]+ +/// Hex integer: 0x[0-9a-fA-F]+ +/// Decimal integer: [1-9][0-9]* +AsmToken AsmLexer::LexDigit() { + // Decimal integer: [1-9][0-9]* + if (CurPtr[-1] != '0' || CurPtr[0] == '.') { + while (isdigit(*CurPtr)) + ++CurPtr; + + // Check for floating point literals. + if (*CurPtr == '.' || *CurPtr == 'e') { + ++CurPtr; + return LexFloatLiteral(); + } + + StringRef Result(TokStart, CurPtr - TokStart); + + long long Value; + if (Result.getAsInteger(10, Value)) { + // Allow positive values that are too large to fit into a signed 64-bit + // integer, but that do fit in an unsigned one, we just convert them over. + unsigned long long UValue; + if (Result.getAsInteger(10, UValue)) + return ReturnError(TokStart, "invalid decimal number"); + Value = (long long)UValue; + } + + // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL + // suffixes on integer literals. + SkipIgnoredIntegerSuffix(CurPtr); + + return AsmToken(AsmToken::Integer, Result, Value); + } + + if (*CurPtr == 'b') { + ++CurPtr; + // See if we actually have "0b" as part of something like "jmp 0b\n" + if (!isdigit(CurPtr[0])) { + --CurPtr; + StringRef Result(TokStart, CurPtr - TokStart); + return AsmToken(AsmToken::Integer, Result, 0); + } + const char *NumStart = CurPtr; + while (CurPtr[0] == '0' || CurPtr[0] == '1') + ++CurPtr; + + // Requires at least one binary digit. + if (CurPtr == NumStart) + return ReturnError(TokStart, "Invalid binary number"); + + StringRef Result(TokStart, CurPtr - TokStart); + + long long Value; + if (Result.substr(2).getAsInteger(2, Value)) + return ReturnError(TokStart, "Invalid binary number"); + + // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL + // suffixes on integer literals. + SkipIgnoredIntegerSuffix(CurPtr); + + return AsmToken(AsmToken::Integer, Result, Value); + } + + if (*CurPtr == 'x') { + ++CurPtr; + const char *NumStart = CurPtr; + while (isxdigit(CurPtr[0])) + ++CurPtr; + + // Requires at least one hex digit. + if (CurPtr == NumStart) + return ReturnError(CurPtr-2, "Invalid hexadecimal number"); + + unsigned long long Result; + if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) + return ReturnError(TokStart, "Invalid hexadecimal number"); + + // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL + // suffixes on integer literals. + SkipIgnoredIntegerSuffix(CurPtr); + + return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), + (int64_t)Result); + } + + // Must be an octal number, it starts with 0. + while (*CurPtr >= '0' && *CurPtr <= '7') + ++CurPtr; + + StringRef Result(TokStart, CurPtr - TokStart); + long long Value; + if (Result.getAsInteger(8, Value)) + return ReturnError(TokStart, "Invalid octal number"); + + // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL + // suffixes on integer literals. + SkipIgnoredIntegerSuffix(CurPtr); + + return AsmToken(AsmToken::Integer, Result, Value); +} + +/// LexSingleQuote: Integer: 'b' +AsmToken AsmLexer::LexSingleQuote() { + int CurChar = getNextChar(); + + if (CurChar == '\\') + CurChar = getNextChar(); + + if (CurChar == EOF) + return ReturnError(TokStart, "unterminated single quote"); + + CurChar = getNextChar(); + + if (CurChar != '\'') + return ReturnError(TokStart, "single quote way too long"); + + // The idea here being that 'c' is basically just an integral + // constant. + StringRef Res = StringRef(TokStart,CurPtr - TokStart); + long long Value; + + if (Res.startswith("\'\\")) { + char theChar = Res[2]; + switch (theChar) { + default: Value = theChar; break; + case '\'': Value = '\''; break; + case 't': Value = '\t'; break; + case 'n': Value = '\n'; break; + case 'b': Value = '\b'; break; + } + } else + Value = TokStart[1]; + + return AsmToken(AsmToken::Integer, Res, Value); +} + + +/// LexQuote: String: "..." +AsmToken AsmLexer::LexQuote() { + int CurChar = getNextChar(); + // TODO: does gas allow multiline string constants? + while (CurChar != '"') { + if (CurChar == '\\') { + // Allow \", etc. + CurChar = getNextChar(); + } + + if (CurChar == EOF) + return ReturnError(TokStart, "unterminated string constant"); + + CurChar = getNextChar(); + } + + return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); +} + +StringRef AsmLexer::LexUntilEndOfStatement() { + TokStart = CurPtr; + + while (!isAtStartOfComment(*CurPtr) && // Start of line comment. + *CurPtr != ';' && // End of statement marker. + *CurPtr != '\n' && + *CurPtr != '\r' && + (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { + ++CurPtr; + } + return StringRef(TokStart, CurPtr-TokStart); +} + +bool AsmLexer::isAtStartOfComment(char Char) { + // FIXME: This won't work for multi-character comment indicators like "//". + return Char == *MAI.getCommentString(); +} + +AsmToken AsmLexer::LexToken() { + TokStart = CurPtr; + // This always consumes at least one character. + int CurChar = getNextChar(); + + if (isAtStartOfComment(CurChar)) + return LexLineComment(); + + switch (CurChar) { + default: + // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* + if (isalpha(CurChar) || CurChar == '_' || CurChar == '.') + return LexIdentifier(); + + // Unknown character, emit an error. + return ReturnError(TokStart, "invalid character in input"); + case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); + case 0: + case ' ': + case '\t': + // Ignore whitespace. + return LexToken(); + case '\n': // FALL THROUGH. + case '\r': // FALL THROUGH. + case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); + case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); + case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); + case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1)); + case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1)); + case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1)); + case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1)); + case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1)); + case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1)); + case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1)); + case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1)); + case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1)); + case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1)); + case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1)); + case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1)); + case '=': + if (*CurPtr == '=') + return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Equal, StringRef(TokStart, 1)); + case '|': + if (*CurPtr == '|') + return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1)); + case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1)); + case '&': + if (*CurPtr == '&') + return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Amp, StringRef(TokStart, 1)); + case '!': + if (*CurPtr == '=') + return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); + return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); + case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); + case '/': return LexSlash(); + case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); + case '\'': return LexSingleQuote(); + case '"': return LexQuote(); + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + return LexDigit(); + case '<': + switch (*CurPtr) { + case '<': return ++CurPtr, AsmToken(AsmToken::LessLess, + StringRef(TokStart, 2)); + case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual, + StringRef(TokStart, 2)); + case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater, + StringRef(TokStart, 2)); + default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); + } + case '>': + switch (*CurPtr) { + case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater, + StringRef(TokStart, 2)); + case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual, + StringRef(TokStart, 2)); + default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); + } + + // TODO: Quoted identifiers (objc methods etc) + // local labels: [0-9][:] + // Forward/backward labels: [0-9][fb] + // Integers, fp constants, character constants. + } +} diff --git a/final/lib/MC/MCParser/AsmParser.cpp b/final/lib/MC/MCParser/AsmParser.cpp new file mode 100644 index 00000000000..a84917ffb86 --- /dev/null +++ b/final/lib/MC/MCParser/AsmParser.cpp @@ -0,0 +1,2497 @@ +//===- AsmParser.cpp - Parser for Assembly Files --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements the parser for assembly files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCParser/AsmCond.h" +#include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetAsmParser.h" +#include +#include +using namespace llvm; + +namespace { + +/// \brief Helper class for tracking macro definitions. +struct Macro { + StringRef Name; + StringRef Body; + +public: + Macro(StringRef N, StringRef B) : Name(N), Body(B) {} +}; + +/// \brief Helper class for storing information about an active macro +/// instantiation. +struct MacroInstantiation { + /// The macro being instantiated. + const Macro *TheMacro; + + /// The macro instantiation with substitutions. + MemoryBuffer *Instantiation; + + /// The location of the instantiation. + SMLoc InstantiationLoc; + + /// The location where parsing should resume upon instantiation completion. + SMLoc ExitLoc; + +public: + MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, + const std::vector > &A); +}; + +/// \brief The concrete assembly parser instance. +class AsmParser : public MCAsmParser { + friend class GenericAsmParser; + + AsmParser(const AsmParser &); // DO NOT IMPLEMENT + void operator=(const AsmParser &); // DO NOT IMPLEMENT +private: + AsmLexer Lexer; + MCContext &Ctx; + MCStreamer &Out; + SourceMgr &SrcMgr; + MCAsmParserExtension *GenericParser; + MCAsmParserExtension *PlatformParser; + + /// This is the current buffer index we're lexing from as managed by the + /// SourceMgr object. + int CurBuffer; + + AsmCond TheCondState; + std::vector TheCondStack; + + /// DirectiveMap - This is a table handlers for directives. Each handler is + /// invoked after the directive identifier is read and is responsible for + /// parsing and validating the rest of the directive. The handler is passed + /// in the directive name and the location of the directive keyword. + StringMap > DirectiveMap; + + /// MacroMap - Map of currently defined macros. + StringMap MacroMap; + + /// ActiveMacros - Stack of active macro instantiations. + std::vector ActiveMacros; + + /// Boolean tracking whether macro substitution is enabled. + unsigned MacrosEnabled : 1; + + /// Flag tracking whether any errors have been encountered. + unsigned HadError : 1; + +public: + AsmParser(const Target &T, SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, + const MCAsmInfo &MAI); + ~AsmParser(); + + virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false); + + void AddDirectiveHandler(MCAsmParserExtension *Object, + StringRef Directive, + DirectiveHandler Handler) { + DirectiveMap[Directive] = std::make_pair(Object, Handler); + } + +public: + /// @name MCAsmParser Interface + /// { + + virtual SourceMgr &getSourceManager() { return SrcMgr; } + virtual MCAsmLexer &getLexer() { return Lexer; } + virtual MCContext &getContext() { return Ctx; } + virtual MCStreamer &getStreamer() { return Out; } + + virtual void Warning(SMLoc L, const Twine &Meg); + virtual bool Error(SMLoc L, const Twine &Msg); + + const AsmToken &Lex(); + + bool ParseExpression(const MCExpr *&Res); + virtual bool ParseExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); + virtual bool ParseAbsoluteExpression(int64_t &Res); + + /// } + +private: + void CheckForValidSection(); + + bool ParseStatement(); + + bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); + void HandleMacroExit(); + + void PrintMacroInstantiations(); + void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type) const { + SrcMgr.PrintMessage(Loc, Msg, Type); + } + + /// EnterIncludeFile - Enter the specified file. This returns true on failure. + bool EnterIncludeFile(const std::string &Filename); + + /// \brief Reset the current lexer position to that given by \arg Loc. The + /// current token is not set; clients should ensure Lex() is called + /// subsequently. + void JumpToLoc(SMLoc Loc); + + void EatToEndOfStatement(); + + /// \brief Parse up to the end of statement and a return the contents from the + /// current token until the end of the statement; the current token on exit + /// will be either the EndOfStatement or EOF. + StringRef ParseStringToEndOfStatement(); + + bool ParseAssignment(StringRef Name, bool allow_redef); + + bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc); + bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); + bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); + + /// ParseIdentifier - Parse an identifier or string (as a quoted identifier) + /// and set \arg Res to the identifier contents. + bool ParseIdentifier(StringRef &Res); + + // Directive Parsing. + + // ".ascii", ".asciiz", ".string" + bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); + bool ParseDirectiveValue(unsigned Size); // ".byte", ".long", ... + bool ParseDirectiveRealValue(const fltSemantics &); // ".single", ... + bool ParseDirectiveFill(); // ".fill" + bool ParseDirectiveSpace(); // ".space" + bool ParseDirectiveZero(); // ".zero" + bool ParseDirectiveSet(StringRef IDVal, bool allow_redef); // ".set", ".equ", ".equiv" + bool ParseDirectiveOrg(); // ".org" + // ".align{,32}", ".p2align{,w,l}" + bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which + /// accepts a single symbol (which should be a label or an external). + bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); + + bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" + + bool ParseDirectiveAbort(); // ".abort" + bool ParseDirectiveInclude(); // ".include" + + bool ParseDirectiveIf(SMLoc DirectiveLoc); // ".if" + // ".ifdef" or ".ifndef", depending on expect_defined + bool ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); + bool ParseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" + bool ParseDirectiveElse(SMLoc DirectiveLoc); // ".else" + bool ParseDirectiveEndIf(SMLoc DirectiveLoc); // .endif + + /// ParseEscapedString - Parse the current token as a string which may include + /// escaped characters and return the string contents. + bool ParseEscapedString(std::string &Data); + + const MCExpr *ApplyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind Variant); +}; + +/// \brief Generic implementations of directive handling, etc. which is shared +/// (or the default, at least) for all assembler parser. +class GenericAsmParser : public MCAsmParserExtension { + template + void AddDirectiveHandler(StringRef Directive) { + getParser().AddDirectiveHandler(this, Directive, + HandleDirective); + } +public: + GenericAsmParser() {} + + AsmParser &getParser() { + return (AsmParser&) this->MCAsmParserExtension::getParser(); + } + + virtual void Initialize(MCAsmParser &Parser) { + // Call the base implementation. + this->MCAsmParserExtension::Initialize(Parser); + + // Debugging directives. + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveFile>(".file"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLine>(".line"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLoc>(".loc"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs"); + + // CFI directives. + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>( + ".cfi_startproc"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( + ".cfi_endproc"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfa>( + ".cfi_def_cfa"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( + ".cfi_def_cfa_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( + ".cfi_def_cfa_register"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( + ".cfi_offset"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_lsda"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); + + // Macro directives. + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( + ".macros_on"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( + ".macros_off"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacro>(".macro"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endm"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endmacro"); + + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".sleb128"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".uleb128"); + } + + bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); + + bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); + + bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc); + + bool ParseDirectiveLEB128(StringRef, SMLoc); +}; + +} + +namespace llvm { + +extern MCAsmParserExtension *createDarwinAsmParser(); +extern MCAsmParserExtension *createELFAsmParser(); +extern MCAsmParserExtension *createCOFFAsmParser(); + +} + +enum { DEFAULT_ADDRSPACE = 0 }; + +AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, + MCStreamer &_Out, const MCAsmInfo &_MAI) + : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), + GenericParser(new GenericAsmParser), PlatformParser(0), + CurBuffer(0), MacrosEnabled(true) { + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + + // Initialize the generic parser. + GenericParser->Initialize(*this); + + // Initialize the platform / file format parser. + // + // FIXME: This is a hack, we need to (majorly) cleanup how these objects are + // created. + if (_MAI.hasMicrosoftFastStdCallMangling()) { + PlatformParser = createCOFFAsmParser(); + PlatformParser->Initialize(*this); + } else if (_MAI.hasSubsectionsViaSymbols()) { + PlatformParser = createDarwinAsmParser(); + PlatformParser->Initialize(*this); + } else { + PlatformParser = createELFAsmParser(); + PlatformParser->Initialize(*this); + } +} + +AsmParser::~AsmParser() { + assert(ActiveMacros.empty() && "Unexpected active macro instantiation!"); + + // Destroy any macros. + for (StringMap::iterator it = MacroMap.begin(), + ie = MacroMap.end(); it != ie; ++it) + delete it->getValue(); + + delete PlatformParser; + delete GenericParser; +} + +void AsmParser::PrintMacroInstantiations() { + // Print the active macro instantiation stack. + for (std::vector::const_reverse_iterator + it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it) + PrintMessage((*it)->InstantiationLoc, "while in macro instantiation", + "note"); +} + +void AsmParser::Warning(SMLoc L, const Twine &Msg) { + PrintMessage(L, Msg, "warning"); + PrintMacroInstantiations(); +} + +bool AsmParser::Error(SMLoc L, const Twine &Msg) { + HadError = true; + PrintMessage(L, Msg, "error"); + PrintMacroInstantiations(); + return true; +} + +bool AsmParser::EnterIncludeFile(const std::string &Filename) { + int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); + if (NewBuf == -1) + return true; + + CurBuffer = NewBuf; + + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + + return false; +} + +void AsmParser::JumpToLoc(SMLoc Loc) { + CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), Loc.getPointer()); +} + +const AsmToken &AsmParser::Lex() { + const AsmToken *tok = &Lexer.Lex(); + + if (tok->is(AsmToken::Eof)) { + // 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()) { + JumpToLoc(ParentIncludeLoc); + tok = &Lexer.Lex(); + } + } + + if (tok->is(AsmToken::Error)) + Error(Lexer.getErrLoc(), Lexer.getErr()); + + return *tok; +} + +bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { + // Create the initial section, if requested. + if (!NoInitialTextSection) + Out.InitSections(); + + // Prime the lexer. + Lex(); + + HadError = false; + AsmCond StartingCondState = TheCondState; + + // While we have input, parse each statement. + while (Lexer.isNot(AsmToken::Eof)) { + if (!ParseStatement()) continue; + + // We had an error, validate that one was emitted and recover by skipping to + // the next line. + assert(HadError && "Parse statement returned an error, but none emitted!"); + EatToEndOfStatement(); + } + + if (TheCondState.TheCond != StartingCondState.TheCond || + TheCondState.Ignore != StartingCondState.Ignore) + return TokError("unmatched .ifs or .elses"); + + // Check to see there are no empty DwarfFile slots. + const std::vector &MCDwarfFiles = + getContext().getMCDwarfFiles(); + for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { + if (!MCDwarfFiles[i]) + TokError("unassigned file number: " + Twine(i) + " for .file directives"); + } + + // Finalize the output stream if there are no errors and if the client wants + // us to. + if (!HadError && !NoFinalize) + Out.Finish(); + + return HadError; +} + +void AsmParser::CheckForValidSection() { + if (!getStreamer().getCurrentSection()) { + TokError("expected section directive before assembly directive"); + Out.SwitchSection(Ctx.getMachOSection( + "__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText())); + } +} + +/// EatToEndOfStatement - Throw away the rest of the line for testing purposes. +void AsmParser::EatToEndOfStatement() { + while (Lexer.isNot(AsmToken::EndOfStatement) && + Lexer.isNot(AsmToken::Eof)) + Lex(); + + // Eat EOL. + if (Lexer.is(AsmToken::EndOfStatement)) + Lex(); +} + +StringRef AsmParser::ParseStringToEndOfStatement() { + const char *Start = getTok().getLoc().getPointer(); + + while (Lexer.isNot(AsmToken::EndOfStatement) && + Lexer.isNot(AsmToken::Eof)) + Lex(); + + const char *End = getTok().getLoc().getPointer(); + return StringRef(Start, End - Start); +} + +/// ParseParenExpr - Parse a paren expression and return it. +/// NOTE: This assumes the leading '(' has already been consumed. +/// +/// parenexpr ::= expr) +/// +bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { + if (ParseExpression(Res)) return true; + if (Lexer.isNot(AsmToken::RParen)) + return TokError("expected ')' in parentheses expression"); + EndLoc = Lexer.getLoc(); + Lex(); + return false; +} + +/// ParseBracketExpr - Parse a bracket expression and return it. +/// NOTE: This assumes the leading '[' has already been consumed. +/// +/// bracketexpr ::= expr] +/// +bool AsmParser::ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) { + if (ParseExpression(Res)) return true; + if (Lexer.isNot(AsmToken::RBrac)) + return TokError("expected ']' in brackets expression"); + EndLoc = Lexer.getLoc(); + Lex(); + return false; +} + +/// ParsePrimaryExpr - Parse a primary expression and return it. +/// primaryexpr ::= (parenexpr +/// primaryexpr ::= symbol +/// primaryexpr ::= number +/// primaryexpr ::= '.' +/// primaryexpr ::= ~,+,- primaryexpr +bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { + switch (Lexer.getKind()) { + default: + return TokError("unknown token in expression"); + case AsmToken::Exclaim: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateLNot(Res, getContext()); + return false; + case AsmToken::Dollar: + case AsmToken::String: + case AsmToken::Identifier: { + EndLoc = Lexer.getLoc(); + + StringRef Identifier; + if (ParseIdentifier(Identifier)) + return false; + + // This is a symbol reference. + std::pair Split = Identifier.split('@'); + MCSymbol *Sym = getContext().GetOrCreateSymbol(Split.first); + + // Lookup the symbol variant if used. + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + if (Split.first.size() != Identifier.size()) { + Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); + if (Variant == MCSymbolRefExpr::VK_Invalid) { + Variant = MCSymbolRefExpr::VK_None; + return TokError("invalid variant '" + Split.second + "'"); + } + } + + // If this is an absolute variable reference, substitute it now to preserve + // semantics in the face of reassignment. + if (Sym->isVariable() && isa(Sym->getVariableValue())) { + if (Variant) + return Error(EndLoc, "unexpected modifier on variable reference"); + + Res = Sym->getVariableValue(); + return false; + } + + // Otherwise create a symbol ref. + Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); + return false; + } + case AsmToken::Integer: { + SMLoc Loc = getTok().getLoc(); + int64_t IntVal = getTok().getIntVal(); + Res = MCConstantExpr::Create(IntVal, getContext()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat token. + // Look for 'b' or 'f' following an Integer as a directional label + if (Lexer.getKind() == AsmToken::Identifier) { + StringRef IDVal = getTok().getString(); + if (IDVal == "f" || IDVal == "b"){ + MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal, + IDVal == "f" ? 1 : 0); + Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + getContext()); + if(IDVal == "b" && Sym->isUndefined()) + return Error(Loc, "invalid reference to undefined symbol"); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. + } + } + return false; + } + case AsmToken::Real: { + APFloat RealVal(APFloat::IEEEdouble, getTok().getString()); + uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); + Res = MCConstantExpr::Create(IntVal, getContext()); + Lex(); // Eat token. + return false; + } + case AsmToken::Dot: { + // This is a '.' reference, which references the current PC. Emit a + // temporary label to the streamer and refer to it. + MCSymbol *Sym = Ctx.CreateTempSymbol(); + Out.EmitLabel(Sym); + Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. + return false; + } + case AsmToken::LParen: + Lex(); // Eat the '('. + return ParseParenExpr(Res, EndLoc); + case AsmToken::LBrac: + if (!PlatformParser->HasBracketExpressions()) + return TokError("brackets expression not supported on this target"); + Lex(); // Eat the '['. + return ParseBracketExpr(Res, EndLoc); + case AsmToken::Minus: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateMinus(Res, getContext()); + return false; + case AsmToken::Plus: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreatePlus(Res, getContext()); + return false; + case AsmToken::Tilde: + Lex(); // Eat the operator. + if (ParsePrimaryExpr(Res, EndLoc)) + return true; + Res = MCUnaryExpr::CreateNot(Res, getContext()); + return false; + } +} + +bool AsmParser::ParseExpression(const MCExpr *&Res) { + SMLoc EndLoc; + return ParseExpression(Res, EndLoc); +} + +const MCExpr * +AsmParser::ApplyModifierToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind Variant) { + // Recurse over the given expression, rebuilding it to apply the given variant + // if there is exactly one symbol. + switch (E->getKind()) { + case MCExpr::Target: + case MCExpr::Constant: + return 0; + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr *SRE = cast(E); + + if (SRE->getKind() != MCSymbolRefExpr::VK_None) { + TokError("invalid variant on expression '" + + getTok().getIdentifier() + "' (already modified)"); + return E; + } + + return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext()); + } + + case MCExpr::Unary: { + const MCUnaryExpr *UE = cast(E); + const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant); + if (!Sub) + return 0; + return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext()); + } + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(E); + const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant); + const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant); + + if (!LHS && !RHS) + return 0; + + if (!LHS) LHS = BE->getLHS(); + if (!RHS) RHS = BE->getRHS(); + + return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext()); + } + } + + assert(0 && "Invalid expression kind!"); + return 0; +} + +/// ParseExpression - Parse an expression and return it. +/// +/// expr ::= expr +,- expr -> lowest. +/// expr ::= expr |,^,&,! expr -> middle. +/// expr ::= expr *,/,%,<<,>> expr -> highest. +/// expr ::= primaryexpr +/// +bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { + // Parse the expression. + Res = 0; + if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc)) + return true; + + // As a special case, we support 'a op b @ modifier' by rewriting the + // expression to include the modifier. This is inefficient, but in general we + // expect users to use 'a@modifier op b'. + if (Lexer.getKind() == AsmToken::At) { + Lex(); + + if (Lexer.isNot(AsmToken::Identifier)) + return TokError("unexpected symbol modifier following '@'"); + + MCSymbolRefExpr::VariantKind Variant = + MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier()); + if (Variant == MCSymbolRefExpr::VK_Invalid) + return TokError("invalid variant '" + getTok().getIdentifier() + "'"); + + const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant); + if (!ModifiedRes) { + return TokError("invalid modifier '" + getTok().getIdentifier() + + "' (no symbols present)"); + return true; + } + + Res = ModifiedRes; + Lex(); + } + + // Try to constant fold it up front, if possible. + int64_t Value; + if (Res->EvaluateAsAbsolute(Value)) + Res = MCConstantExpr::Create(Value, getContext()); + + return false; +} + +bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { + Res = 0; + return ParseParenExpr(Res, EndLoc) || + ParseBinOpRHS(1, Res, EndLoc); +} + +bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { + const MCExpr *Expr; + + SMLoc StartLoc = Lexer.getLoc(); + if (ParseExpression(Expr)) + return true; + + if (!Expr->EvaluateAsAbsolute(Res)) + return Error(StartLoc, "expected absolute expression"); + + return false; +} + +static unsigned getBinOpPrecedence(AsmToken::TokenKind K, + MCBinaryExpr::Opcode &Kind) { + switch (K) { + default: + return 0; // not a binop. + + // Lowest Precedence: &&, ||, @ + case AsmToken::AmpAmp: + Kind = MCBinaryExpr::LAnd; + return 1; + case AsmToken::PipePipe: + Kind = MCBinaryExpr::LOr; + return 1; + + + // Low Precedence: |, &, ^ + // + // FIXME: gas seems to support '!' as an infix operator? + case AsmToken::Pipe: + Kind = MCBinaryExpr::Or; + return 2; + case AsmToken::Caret: + Kind = MCBinaryExpr::Xor; + return 2; + case AsmToken::Amp: + Kind = MCBinaryExpr::And; + return 2; + + // Low Intermediate Precedence: ==, !=, <>, <, <=, >, >= + case AsmToken::EqualEqual: + Kind = MCBinaryExpr::EQ; + return 3; + case AsmToken::ExclaimEqual: + case AsmToken::LessGreater: + Kind = MCBinaryExpr::NE; + return 3; + case AsmToken::Less: + Kind = MCBinaryExpr::LT; + return 3; + case AsmToken::LessEqual: + Kind = MCBinaryExpr::LTE; + return 3; + case AsmToken::Greater: + Kind = MCBinaryExpr::GT; + return 3; + case AsmToken::GreaterEqual: + Kind = MCBinaryExpr::GTE; + return 3; + + // High Intermediate Precedence: +, - + case AsmToken::Plus: + Kind = MCBinaryExpr::Add; + return 4; + case AsmToken::Minus: + Kind = MCBinaryExpr::Sub; + return 4; + + // Highest Precedence: *, /, %, <<, >> + case AsmToken::Star: + Kind = MCBinaryExpr::Mul; + return 5; + case AsmToken::Slash: + Kind = MCBinaryExpr::Div; + return 5; + case AsmToken::Percent: + Kind = MCBinaryExpr::Mod; + return 5; + case AsmToken::LessLess: + Kind = MCBinaryExpr::Shl; + return 5; + case AsmToken::GreaterGreater: + Kind = MCBinaryExpr::Shr; + return 5; + } +} + + +/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. +/// Res contains the LHS of the expression on input. +bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, + SMLoc &EndLoc) { + while (1) { + MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; + unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); + + // If the next token is lower precedence than we are allowed to eat, return + // successfully with what we ate already. + if (TokPrec < Precedence) + return false; + + Lex(); + + // Eat the next primary expression. + const MCExpr *RHS; + if (ParsePrimaryExpr(RHS, EndLoc)) return true; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + MCBinaryExpr::Opcode Dummy; + unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); + if (TokPrec < NextTokPrec) { + if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; + } + + // Merge LHS and RHS according to operator. + Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext()); + } +} + + + + +/// ParseStatement: +/// ::= EndOfStatement +/// ::= Label* Directive ...Operands... EndOfStatement +/// ::= Label* Identifier OperandList* EndOfStatement +bool AsmParser::ParseStatement() { + if (Lexer.is(AsmToken::EndOfStatement)) { + Out.AddBlankLine(); + Lex(); + return false; + } + + // Statements always start with an identifier or are a full line comment. + AsmToken ID = getTok(); + SMLoc IDLoc = ID.getLoc(); + StringRef IDVal; + int64_t LocalLabelVal = -1; + // A full line comment is a '#' as the first token. + if (Lexer.is(AsmToken::Hash)) { + EatToEndOfStatement(); + return false; + } + // Allow an integer followed by a ':' as a directional local label. + if (Lexer.is(AsmToken::Integer)) { + LocalLabelVal = getTok().getIntVal(); + if (LocalLabelVal < 0) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + IDVal = ""; + } + else { + IDVal = getTok().getString(); + Lex(); // Consume the integer token to be used as an identifier token. + if (Lexer.getKind() != AsmToken::Colon) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + } + } + } + else if (ParseIdentifier(IDVal)) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + IDVal = ""; + } + + // Handle conditional assembly here before checking for skipping. We + // have to do this so that .endif isn't skipped in a ".if 0" block for + // example. + if (IDVal == ".if") + return ParseDirectiveIf(IDLoc); + if (IDVal == ".ifdef") + return ParseDirectiveIfdef(IDLoc, true); + if (IDVal == ".ifndef" || IDVal == ".ifnotdef") + return ParseDirectiveIfdef(IDLoc, false); + if (IDVal == ".elseif") + return ParseDirectiveElseIf(IDLoc); + if (IDVal == ".else") + return ParseDirectiveElse(IDLoc); + if (IDVal == ".endif") + return ParseDirectiveEndIf(IDLoc); + + // If we are in a ".if 0" block, ignore this statement. + if (TheCondState.Ignore) { + EatToEndOfStatement(); + return false; + } + + // FIXME: Recurse on local labels? + + // See what kind of statement we have. + switch (Lexer.getKind()) { + case AsmToken::Colon: { + CheckForValidSection(); + + // identifier ':' -> Label. + Lex(); + + // Diagnose attempt to use a variable as a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: This doesn't diagnose assignment to a symbol which has been + // implicitly marked as external. + MCSymbol *Sym; + if (LocalLabelVal == -1) + Sym = getContext().GetOrCreateSymbol(IDVal); + else + Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal); + if (!Sym->isUndefined() || Sym->isVariable()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Emit the label. + Out.EmitLabel(Sym); + + // Consume any end of statement token, if present, to avoid spurious + // AddBlankLine calls(). + if (Lexer.is(AsmToken::EndOfStatement)) { + Lex(); + if (Lexer.is(AsmToken::Eof)) + return false; + } + + return ParseStatement(); + } + + case AsmToken::Equal: + // identifier '=' ... -> assignment statement + Lex(); + + return ParseAssignment(IDVal, true); + + default: // Normal instruction or directive. + break; + } + + // If macros are enabled, check to see if this is a macro instantiation. + if (MacrosEnabled) + if (const Macro *M = MacroMap.lookup(IDVal)) + return HandleMacroEntry(IDVal, IDLoc, M); + + // Otherwise, we have a normal instruction or directive. + if (IDVal[0] == '.') { + // Assembler features + if (IDVal == ".set" || IDVal == ".equ") + return ParseDirectiveSet(IDVal, true); + if (IDVal == ".equiv") + return ParseDirectiveSet(IDVal, false); + + // Data directives + + if (IDVal == ".ascii") + return ParseDirectiveAscii(IDVal, false); + if (IDVal == ".asciz" || IDVal == ".string") + return ParseDirectiveAscii(IDVal, true); + + if (IDVal == ".byte") + return ParseDirectiveValue(1); + if (IDVal == ".short") + return ParseDirectiveValue(2); + if (IDVal == ".value") + return ParseDirectiveValue(2); + if (IDVal == ".2byte") + return ParseDirectiveValue(2); + if (IDVal == ".long") + return ParseDirectiveValue(4); + if (IDVal == ".int") + return ParseDirectiveValue(4); + if (IDVal == ".4byte") + return ParseDirectiveValue(4); + if (IDVal == ".quad") + return ParseDirectiveValue(8); + if (IDVal == ".8byte") + return ParseDirectiveValue(8); + if (IDVal == ".single" || IDVal == ".float") + return ParseDirectiveRealValue(APFloat::IEEEsingle); + if (IDVal == ".double") + return ParseDirectiveRealValue(APFloat::IEEEdouble); + + if (IDVal == ".align") { + bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes(); + return ParseDirectiveAlign(IsPow2, /*ExprSize=*/1); + } + if (IDVal == ".align32") { + bool IsPow2 = !getContext().getAsmInfo().getAlignmentIsInBytes(); + return ParseDirectiveAlign(IsPow2, /*ExprSize=*/4); + } + if (IDVal == ".balign") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1); + if (IDVal == ".balignw") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2); + if (IDVal == ".balignl") + return ParseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4); + if (IDVal == ".p2align") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1); + if (IDVal == ".p2alignw") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2); + if (IDVal == ".p2alignl") + return ParseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4); + + if (IDVal == ".org") + return ParseDirectiveOrg(); + + if (IDVal == ".fill") + return ParseDirectiveFill(); + if (IDVal == ".space") + return ParseDirectiveSpace(); + if (IDVal == ".zero") + return ParseDirectiveZero(); + + // Symbol attribute directives + + if (IDVal == ".globl" || IDVal == ".global") + return ParseDirectiveSymbolAttribute(MCSA_Global); + // ELF only? Should it be here? + if (IDVal == ".local") + return ParseDirectiveSymbolAttribute(MCSA_Local); + if (IDVal == ".hidden") + return ParseDirectiveSymbolAttribute(MCSA_Hidden); + if (IDVal == ".indirect_symbol") + return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); + if (IDVal == ".internal") + return ParseDirectiveSymbolAttribute(MCSA_Internal); + if (IDVal == ".lazy_reference") + return ParseDirectiveSymbolAttribute(MCSA_LazyReference); + if (IDVal == ".no_dead_strip") + return ParseDirectiveSymbolAttribute(MCSA_NoDeadStrip); + if (IDVal == ".symbol_resolver") + return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver); + if (IDVal == ".private_extern") + return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); + if (IDVal == ".protected") + return ParseDirectiveSymbolAttribute(MCSA_Protected); + if (IDVal == ".reference") + return ParseDirectiveSymbolAttribute(MCSA_Reference); + if (IDVal == ".weak") + return ParseDirectiveSymbolAttribute(MCSA_Weak); + if (IDVal == ".weak_definition") + return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); + if (IDVal == ".weak_reference") + return ParseDirectiveSymbolAttribute(MCSA_WeakReference); + if (IDVal == ".weak_def_can_be_hidden") + return ParseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate); + + if (IDVal == ".comm") + return ParseDirectiveComm(/*IsLocal=*/false); + if (IDVal == ".lcomm") + return ParseDirectiveComm(/*IsLocal=*/true); + + if (IDVal == ".abort") + return ParseDirectiveAbort(); + if (IDVal == ".include") + return ParseDirectiveInclude(); + + if (IDVal == ".code16" || IDVal == ".code32" || IDVal == ".code64") + return TokError(Twine(IDVal) + " not supported yet"); + + // Look up the handler in the handler table. + std::pair Handler = + DirectiveMap.lookup(IDVal); + if (Handler.first) + return (*Handler.second)(Handler.first, IDVal, IDLoc); + + // Target hook for parsing target specific directives. + if (!getTargetParser().ParseDirective(ID)) + return false; + + Warning(IDLoc, "ignoring directive for now"); + EatToEndOfStatement(); + return false; + } + + CheckForValidSection(); + + // Canonicalize the opcode to lower case. + SmallString<128> Opcode; + for (unsigned i = 0, e = IDVal.size(); i != e; ++i) + Opcode.push_back(tolower(IDVal[i])); + + SmallVector ParsedOperands; + bool HadError = getTargetParser().ParseInstruction(Opcode.str(), IDLoc, + ParsedOperands); + + // Dump the parsed representation, if requested. + if (getShowParsedOperands()) { + SmallString<256> Str; + raw_svector_ostream OS(Str); + OS << "parsed instruction: ["; + for (unsigned i = 0; i != ParsedOperands.size(); ++i) { + if (i != 0) + OS << ", "; + ParsedOperands[i]->dump(OS); + } + OS << "]"; + + PrintMessage(IDLoc, OS.str(), "note"); + } + + // If parsing succeeded, match the instruction. + if (!HadError) + HadError = getTargetParser().MatchAndEmitInstruction(IDLoc, ParsedOperands, + Out); + + // Free any parsed operands. + for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) + delete ParsedOperands[i]; + + // Don't skip the rest of the line, the instruction parser is responsible for + // that. + return false; +} + +MacroInstantiation::MacroInstantiation(const Macro *M, SMLoc IL, SMLoc EL, + const std::vector > &A) + : TheMacro(M), InstantiationLoc(IL), ExitLoc(EL) +{ + // Macro instantiation is lexical, unfortunately. We construct a new buffer + // to hold the macro body with substitutions. + SmallString<256> Buf; + raw_svector_ostream OS(Buf); + + StringRef Body = M->Body; + while (!Body.empty()) { + // Scan for the next substitution. + std::size_t End = Body.size(), Pos = 0; + for (; Pos != End; ++Pos) { + // Check for a substitution or escape. + if (Body[Pos] != '$' || Pos + 1 == End) + continue; + + char Next = Body[Pos + 1]; + if (Next == '$' || Next == 'n' || isdigit(Next)) + break; + } + + // Add the prefix. + OS << Body.slice(0, Pos); + + // Check if we reached the end. + if (Pos == End) + break; + + switch (Body[Pos+1]) { + // $$ => $ + case '$': + OS << '$'; + break; + + // $n => number of arguments + case 'n': + OS << A.size(); + break; + + // $[0-9] => argument + default: { + // Missing arguments are ignored. + unsigned Index = Body[Pos+1] - '0'; + if (Index >= A.size()) + break; + + // Otherwise substitute with the token values, with spaces eliminated. + for (std::vector::const_iterator it = A[Index].begin(), + ie = A[Index].end(); it != ie; ++it) + OS << it->getString(); + break; + } + } + + // Update the scan point. + Body = Body.substr(Pos + 2); + } + + // We include the .endmacro in the buffer as our queue to exit the macro + // instantiation. + OS << ".endmacro\n"; + + Instantiation = MemoryBuffer::getMemBufferCopy(OS.str(), ""); +} + +bool AsmParser::HandleMacroEntry(StringRef Name, SMLoc NameLoc, + const Macro *M) { + // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate + // this, although we should protect against infinite loops. + if (ActiveMacros.size() == 20) + return TokError("macros cannot be nested more than 20 levels deep"); + + // Parse the macro instantiation arguments. + std::vector > MacroArguments; + MacroArguments.push_back(std::vector()); + unsigned ParenLevel = 0; + for (;;) { + if (Lexer.is(AsmToken::Eof)) + return TokError("unexpected token in macro instantiation"); + if (Lexer.is(AsmToken::EndOfStatement)) + break; + + // If we aren't inside parentheses and this is a comma, start a new token + // list. + if (ParenLevel == 0 && Lexer.is(AsmToken::Comma)) { + MacroArguments.push_back(std::vector()); + } else { + // Adjust the current parentheses level. + if (Lexer.is(AsmToken::LParen)) + ++ParenLevel; + else if (Lexer.is(AsmToken::RParen) && ParenLevel) + --ParenLevel; + + // Append the token to the current argument list. + MacroArguments.back().push_back(getTok()); + } + Lex(); + } + + // Create the macro instantiation object and add to the current macro + // instantiation stack. + MacroInstantiation *MI = new MacroInstantiation(M, NameLoc, + getTok().getLoc(), + MacroArguments); + ActiveMacros.push_back(MI); + + // Jump to the macro instantiation and prime the lexer. + CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); + Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); + Lex(); + + return false; +} + +void AsmParser::HandleMacroExit() { + // Jump to the EndOfStatement we should return to, and consume it. + JumpToLoc(ActiveMacros.back()->ExitLoc); + Lex(); + + // Pop the instantiation entry. + delete ActiveMacros.back(); + ActiveMacros.pop_back(); +} + +static void MarkUsed(const MCExpr *Value) { + switch (Value->getKind()) { + case MCExpr::Binary: + MarkUsed(static_cast(Value)->getLHS()); + MarkUsed(static_cast(Value)->getRHS()); + break; + case MCExpr::Target: + case MCExpr::Constant: + break; + case MCExpr::SymbolRef: { + static_cast(Value)->getSymbol().setUsed(true); + break; + } + case MCExpr::Unary: + MarkUsed(static_cast(Value)->getSubExpr()); + break; + } +} + +bool AsmParser::ParseAssignment(StringRef Name, bool allow_redef) { + // FIXME: Use better location, we should use proper tokens. + SMLoc EqualLoc = Lexer.getLoc(); + + const MCExpr *Value; + if (ParseExpression(Value)) + return true; + + MarkUsed(Value); + + if (Lexer.isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in assignment"); + + // Eat the end of statement marker. + Lex(); + + // Validate that the LHS is allowed to be a variable (either it has not been + // used as a symbol, or it is an absolute symbol). + MCSymbol *Sym = getContext().LookupSymbol(Name); + if (Sym) { + // Diagnose assignment to a label. + // + // FIXME: Diagnostics. Note the location of the definition as a label. + // FIXME: Diagnose assignment to protected identifier (e.g., register name). + if (Sym->isUndefined() && !Sym->isUsed() && !Sym->isVariable()) + ; // Allow redefinitions of undefined symbols only used in directives. + else if (!Sym->isUndefined() && (!Sym->isAbsolute() || !allow_redef)) + return Error(EqualLoc, "redefinition of '" + Name + "'"); + else if (!Sym->isVariable()) + return Error(EqualLoc, "invalid assignment to '" + Name + "'"); + else if (!isa(Sym->getVariableValue())) + return Error(EqualLoc, "invalid reassignment of non-absolute variable '" + + Name + "'"); + + // Don't count these checks as uses. + Sym->setUsed(false); + } else + Sym = getContext().GetOrCreateSymbol(Name); + + // FIXME: Handle '.'. + + // Do the assignment. + Out.EmitAssignment(Sym, Value); + + return false; +} + +/// ParseIdentifier: +/// ::= identifier +/// ::= string +bool AsmParser::ParseIdentifier(StringRef &Res) { + // The assembler has relaxed rules for accepting identifiers, in particular we + // allow things like '.globl $foo', which would normally be separate + // tokens. At this level, we have already lexed so we cannot (currently) + // handle this as a context dependent token, instead we detect adjacent tokens + // and return the combined identifier. + if (Lexer.is(AsmToken::Dollar)) { + SMLoc DollarLoc = getLexer().getLoc(); + + // Consume the dollar sign, and check for a following identifier. + Lex(); + if (Lexer.isNot(AsmToken::Identifier)) + return true; + + // We have a '$' followed by an identifier, make sure they are adjacent. + if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer()) + return true; + + // Construct the joined identifier and consume the token. + Res = StringRef(DollarLoc.getPointer(), + getTok().getIdentifier().size() + 1); + Lex(); + return false; + } + + if (Lexer.isNot(AsmToken::Identifier) && + Lexer.isNot(AsmToken::String)) + return true; + + Res = getTok().getIdentifier(); + + Lex(); // Consume the identifier token. + + return false; +} + +/// ParseDirectiveSet: +/// ::= .equ identifier ',' expression +/// ::= .equiv identifier ',' expression +/// ::= .set identifier ',' expression +bool AsmParser::ParseDirectiveSet(StringRef IDVal, bool allow_redef) { + StringRef Name; + + if (ParseIdentifier(Name)) + return TokError("expected identifier after '" + Twine(IDVal) + "'"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '" + Twine(IDVal) + "'"); + Lex(); + + return ParseAssignment(Name, allow_redef); +} + +bool AsmParser::ParseEscapedString(std::string &Data) { + assert(getLexer().is(AsmToken::String) && "Unexpected current token!"); + + Data = ""; + StringRef Str = getTok().getStringContents(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + if (Str[i] != '\\') { + Data += Str[i]; + continue; + } + + // Recognize escaped characters. Note that this escape semantics currently + // loosely follows Darwin 'as'. Notably, it doesn't support hex escapes. + ++i; + if (i == e) + return TokError("unexpected backslash at end of string"); + + // Recognize octal sequences. + if ((unsigned) (Str[i] - '0') <= 7) { + // Consume up to three octal characters. + unsigned Value = Str[i] - '0'; + + if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + ++i; + Value = Value * 8 + (Str[i] - '0'); + + if (i + 1 != e && ((unsigned) (Str[i + 1] - '0')) <= 7) { + ++i; + Value = Value * 8 + (Str[i] - '0'); + } + } + + if (Value > 255) + return TokError("invalid octal escape sequence (out of range)"); + + Data += (unsigned char) Value; + continue; + } + + // Otherwise recognize individual escapes. + switch (Str[i]) { + default: + // Just reject invalid escape sequences for now. + return TokError("invalid escape sequence (unrecognized character)"); + + case 'b': Data += '\b'; break; + case 'f': Data += '\f'; break; + case 'n': Data += '\n'; break; + case 'r': Data += '\r'; break; + case 't': Data += '\t'; break; + case '"': Data += '"'; break; + case '\\': Data += '\\'; break; + } + } + + return false; +} + +/// ParseDirectiveAscii: +/// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] +bool AsmParser::ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + CheckForValidSection(); + + for (;;) { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '" + Twine(IDVal) + "' directive"); + + std::string Data; + if (ParseEscapedString(Data)) + return true; + + getStreamer().EmitBytes(Data, DEFAULT_ADDRSPACE); + if (ZeroTerminated) + getStreamer().EmitBytes(StringRef("\0", 1), DEFAULT_ADDRSPACE); + + Lex(); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveValue +/// ::= (.byte | .short | ... ) [ expression (, expression)* ] +bool AsmParser::ParseDirectiveValue(unsigned Size) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + CheckForValidSection(); + + for (;;) { + const MCExpr *Value; + if (ParseExpression(Value)) + return true; + + // Special case constant expressions to match code generator. + if (const MCConstantExpr *MCE = dyn_cast(Value)) + getStreamer().EmitIntValue(MCE->getValue(), Size, DEFAULT_ADDRSPACE); + else + getStreamer().EmitValue(Value, Size, DEFAULT_ADDRSPACE); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + // FIXME: Improve diagnostic. + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveRealValue +/// ::= (.single | .double) [ expression (, expression)* ] +bool AsmParser::ParseDirectiveRealValue(const fltSemantics &Semantics) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + CheckForValidSection(); + + for (;;) { + // We don't truly support arithmetic on floating point expressions, so we + // have to manually parse unary prefixes. + bool IsNeg = false; + if (getLexer().is(AsmToken::Minus)) { + Lex(); + IsNeg = true; + } else if (getLexer().is(AsmToken::Plus)) + Lex(); + + if (getLexer().isNot(AsmToken::Integer) && + getLexer().isNot(AsmToken::Real)) + return TokError("unexpected token in directive"); + + // Convert to an APFloat. + APFloat Value(Semantics); + if (Value.convertFromString(getTok().getString(), + APFloat::rmNearestTiesToEven) == + APFloat::opInvalidOp) + return TokError("invalid floating point literal"); + if (IsNeg) + Value.changeSign(); + + // Consume the numeric token. + Lex(); + + // Emit the value as an integer. + APInt AsInt = Value.bitcastToAPInt(); + getStreamer().EmitIntValue(AsInt.getLimitedValue(), + AsInt.getBitWidth() / 8, DEFAULT_ADDRSPACE); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveSpace +/// ::= .space expression [ , expression ] +bool AsmParser::ParseDirectiveSpace() { + CheckForValidSection(); + + int64_t NumBytes; + if (ParseAbsoluteExpression(NumBytes)) + return true; + + int64_t FillExpr = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.space' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.space' directive"); + } + + Lex(); + + if (NumBytes <= 0) + return TokError("invalid number of bytes in '.space' directive"); + + // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. + getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveZero +/// ::= .zero expression +bool AsmParser::ParseDirectiveZero() { + CheckForValidSection(); + + int64_t NumBytes; + if (ParseAbsoluteExpression(NumBytes)) + return true; + + int64_t Val = 0; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + if (ParseAbsoluteExpression(Val)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.zero' directive"); + + Lex(); + + getStreamer().EmitFill(NumBytes, Val, DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveFill +/// ::= .fill expression , expression , expression +bool AsmParser::ParseDirectiveFill() { + CheckForValidSection(); + + int64_t NumValues; + if (ParseAbsoluteExpression(NumValues)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); + + int64_t FillSize; + if (ParseAbsoluteExpression(FillSize)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.fill' directive"); + Lex(); + + int64_t FillExpr; + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.fill' directive"); + + Lex(); + + if (FillSize != 1 && FillSize != 2 && FillSize != 4 && FillSize != 8) + return TokError("invalid '.fill' size, expected 1, 2, 4, or 8"); + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitIntValue(FillExpr, FillSize, DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveOrg +/// ::= .org expression [ , expression ] +bool AsmParser::ParseDirectiveOrg() { + CheckForValidSection(); + + const MCExpr *Offset; + if (ParseExpression(Offset)) + return true; + + // Parse optional fill expression. + int64_t FillExpr = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.org' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.org' directive"); + } + + Lex(); + + // FIXME: Only limited forms of relocatable expressions are accepted here, it + // has to be relative to the current section. + getStreamer().EmitValueToOffset(Offset, FillExpr); + + return false; +} + +/// ParseDirectiveAlign +/// ::= {.align, ...} expression [ , expression [ , expression ]] +bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { + CheckForValidSection(); + + SMLoc AlignmentLoc = getLexer().getLoc(); + int64_t Alignment; + if (ParseAbsoluteExpression(Alignment)) + return true; + + SMLoc MaxBytesLoc; + bool HasFillExpr = false; + int64_t FillExpr = 0; + int64_t MaxBytesToFill = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + // The fill expression can be omitted while specifying a maximum number of + // alignment bytes, e.g: + // .align 3,,4 + if (getLexer().isNot(AsmToken::Comma)) { + HasFillExpr = true; + if (ParseAbsoluteExpression(FillExpr)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + MaxBytesLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(MaxBytesToFill)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + } + } + + Lex(); + + if (!HasFillExpr) + FillExpr = 0; + + // Compute alignment in bytes. + if (IsPow2) { + // FIXME: Diagnose overflow. + if (Alignment >= 32) { + Error(AlignmentLoc, "invalid alignment value"); + Alignment = 31; + } + + Alignment = 1ULL << Alignment; + } + + // Diagnose non-sensical max bytes to align. + if (MaxBytesLoc.isValid()) { + if (MaxBytesToFill < 1) { + Error(MaxBytesLoc, "alignment directive can never be satisfied in this " + "many bytes, ignoring maximum bytes expression"); + MaxBytesToFill = 0; + } + + if (MaxBytesToFill >= Alignment) { + Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and " + "has no effect"); + MaxBytesToFill = 0; + } + } + + // Check whether we should use optimal code alignment for this .align + // directive. + bool UseCodeAlign = getStreamer().getCurrentSection()->UseCodeAlign(); + if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && + ValueSize == 1 && UseCodeAlign) { + getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill); + } else { + // FIXME: Target specific behavior about how the "extra" bytes are filled. + getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize, + MaxBytesToFill); + } + + return false; +} + +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveComm +/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] +bool AsmParser::ParseDirectiveComm(bool IsLocal) { + CheckForValidSection(); + + SMLoc IDLoc = getLexer().getLoc(); + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + + // If this target takes alignments in bytes (not log) validate and convert. + if (Lexer.getMAI().getAlignmentIsInBytes()) { + if (!isPowerOf2_64(Pow2Alignment)) + return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); + Pow2Alignment = Log2_64(Pow2Alignment); + } + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.comm' or '.lcomm' directive"); + + Lex(); + + // NOTE: a size of zero for a .comm should create a undefined symbol + // but a size of .lcomm creates a bss symbol of size zero. + if (Size < 0) + return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " + "be less than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assembler + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " + "alignment, can't be less than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // '.lcomm' is equivalent to '.zerofill'. + // Create the Symbol as a common or local common with Size and Pow2Alignment + if (IsLocal) { + getStreamer().EmitZerofill(Ctx.getMachOSection( + "__DATA", "__bss", MCSectionMachO::S_ZEROFILL, + 0, SectionKind::getBSS()), + Sym, Size, 1 << Pow2Alignment); + return false; + } + + getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; +} + +/// ParseDirectiveAbort +/// ::= .abort [... message ...] +bool AsmParser::ParseDirectiveAbort() { + // FIXME: Use loc from directive. + SMLoc Loc = getLexer().getLoc(); + + StringRef Str = ParseStringToEndOfStatement(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.abort' directive"); + + Lex(); + + if (Str.empty()) + Error(Loc, ".abort detected. Assembly stopping."); + else + Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); + // FIXME: Actually abort assembly here. + + return false; +} + +/// ParseDirectiveInclude +/// ::= .include "filename" +bool AsmParser::ParseDirectiveInclude() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.include' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncludeLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.include' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to switch the lexer to the included file before consuming the end + // of statement to avoid losing it when we switch. + if (EnterIncludeFile(Filename)) { + Error(IncludeLoc, "Could not find include file '" + Filename + "'"); + return true; + } + + return false; +} + +/// ParseDirectiveIf +/// ::= .if expression +bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + if(TheCondState.Ignore) { + EatToEndOfStatement(); + } + else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.if' directive"); + + Lex(); + + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { + StringRef Name; + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + if (ParseIdentifier(Name)) + return TokError("expected identifier after '.ifdef'"); + + Lex(); + + MCSymbol *Sym = getContext().LookupSymbol(Name); + + if (expect_defined) + TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); + else + TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElseIf +/// ::= .elseif expression +bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " + " an .elseif"); + TheCondState.TheCond = AsmCond::ElseIfCond; + + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) { + TheCondState.Ignore = true; + EatToEndOfStatement(); + } + else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.elseif' directive"); + + Lex(); + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElse +/// ::= .else +bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.else' directive"); + + Lex(); + + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " + ".elseif"); + TheCondState.TheCond = AsmCond::ElseCond; + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) + TheCondState.Ignore = true; + else + TheCondState.Ignore = false; + + return false; +} + +/// ParseDirectiveEndIf +/// ::= .endif +bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.endif' directive"); + + Lex(); + + if ((TheCondState.TheCond == AsmCond::NoCond) || + TheCondStack.empty()) + Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " + ".else"); + if (!TheCondStack.empty()) { + TheCondState = TheCondStack.back(); + TheCondStack.pop_back(); + } + + return false; +} + +/// ParseDirectiveFile +/// ::= .file [number] string +bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { + // FIXME: I'm not sure what this is. + int64_t FileNumber = -1; + SMLoc FileNumberLoc = getLexer().getLoc(); + if (getLexer().is(AsmToken::Integer)) { + FileNumber = getTok().getIntVal(); + Lex(); + + if (FileNumber < 1) + return TokError("file number less than one"); + } + + if (getLexer().isNot(AsmToken::String)) + return TokError("unexpected token in '.file' directive"); + + StringRef Filename = getTok().getString(); + Filename = Filename.substr(1, Filename.size()-2); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.file' directive"); + + if (FileNumber == -1) + getStreamer().EmitFileDirective(Filename); + else { + if (getStreamer().EmitDwarfFileDirective(FileNumber, Filename)) + Error(FileNumberLoc, "file number already allocated"); + } + + return false; +} + +/// ParseDirectiveLine +/// ::= .line [number] +bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Integer)) + return TokError("unexpected token in '.line' directive"); + + int64_t LineNumber = getTok().getIntVal(); + (void) LineNumber; + Lex(); + + // FIXME: Do something with the .line. + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.line' directive"); + + return false; +} + + +/// ParseDirectiveLoc +/// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] +/// [epilogue_begin] [is_stmt VALUE] [isa VALUE] +/// The first number is a file number, must have been previously assigned with +/// a .file directive, the second number is the line number and optionally the +/// third number is a column position (zero if not specified). The remaining +/// optional items are .loc sub-directives. +bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { + + if (getLexer().isNot(AsmToken::Integer)) + return TokError("unexpected token in '.loc' directive"); + int64_t FileNumber = getTok().getIntVal(); + if (FileNumber < 1) + return TokError("file number less than one in '.loc' directive"); + if (!getContext().isValidDwarfFileNumber(FileNumber)) + return TokError("unassigned file number in '.loc' directive"); + Lex(); + + int64_t LineNumber = 0; + if (getLexer().is(AsmToken::Integer)) { + LineNumber = getTok().getIntVal(); + if (LineNumber < 1) + return TokError("line number less than one in '.loc' directive"); + Lex(); + } + + int64_t ColumnPos = 0; + if (getLexer().is(AsmToken::Integer)) { + ColumnPos = getTok().getIntVal(); + if (ColumnPos < 0) + return TokError("column position less than zero in '.loc' directive"); + Lex(); + } + + unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; + unsigned Isa = 0; + int64_t Discriminator = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + StringRef Name; + SMLoc Loc = getTok().getLoc(); + if (getParser().ParseIdentifier(Name)) + return TokError("unexpected token in '.loc' directive"); + + if (Name == "basic_block") + Flags |= DWARF2_FLAG_BASIC_BLOCK; + else if (Name == "prologue_end") + Flags |= DWARF2_FLAG_PROLOGUE_END; + else if (Name == "epilogue_begin") + Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; + else if (Name == "is_stmt") { + SMLoc Loc = getTok().getLoc(); + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + // The expression must be the constant 0 or 1. + if (const MCConstantExpr *MCE = dyn_cast(Value)) { + int Value = MCE->getValue(); + if (Value == 0) + Flags &= ~DWARF2_FLAG_IS_STMT; + else if (Value == 1) + Flags |= DWARF2_FLAG_IS_STMT; + else + return Error(Loc, "is_stmt value not 0 or 1"); + } + else { + return Error(Loc, "is_stmt value not the constant value of 0 or 1"); + } + } + else if (Name == "isa") { + SMLoc Loc = getTok().getLoc(); + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + // The expression must be a constant greater or equal to 0. + if (const MCConstantExpr *MCE = dyn_cast(Value)) { + int Value = MCE->getValue(); + if (Value < 0) + return Error(Loc, "isa number less than zero"); + Isa = Value; + } + else { + return Error(Loc, "isa number not a constant value"); + } + } + else if (Name == "discriminator") { + if (getParser().ParseAbsoluteExpression(Discriminator)) + return true; + } + else { + return Error(Loc, "unknown sub-directive in '.loc' directive"); + } + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + } + } + + getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, + Isa, Discriminator); + + return false; +} + +/// ParseDirectiveStabs +/// ::= .stabs string, number, number, number +bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive, + SMLoc DirectiveLoc) { + return TokError("unsupported directive '" + Directive + "'"); +} + +/// ParseDirectiveCFIStartProc +/// ::= .cfi_startproc +bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, + SMLoc DirectiveLoc) { + return getStreamer().EmitCFIStartProc(); +} + +/// ParseDirectiveCFIEndProc +/// ::= .cfi_endproc +bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { + return getStreamer().EmitCFIEndProc(); +} + +/// ParseRegisterOrRegisterNumber - parse register name or number. +bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, + SMLoc DirectiveLoc) { + unsigned RegNo; + + if (getLexer().is(AsmToken::Percent)) { + if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc, + DirectiveLoc)) + return true; + Register = getContext().getTargetAsmInfo().getDwarfRegNum(RegNo, true); + } else + return getParser().ParseAbsoluteExpression(Register); + + return false; +} + +/// ParseDirectiveCFIDefCfa +/// ::= .cfi_def_cfa register, offset +bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + return getStreamer().EmitCFIDefCfa(Register, Offset); +} + +/// ParseDirectiveCFIDefCfaOffset +/// ::= .cfi_def_cfa_offset offset +bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + return getStreamer().EmitCFIDefCfaOffset(Offset); +} + +/// ParseDirectiveCFIDefCfaRegister +/// ::= .cfi_def_cfa_register register +bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + return getStreamer().EmitCFIDefCfaRegister(Register); +} + +/// ParseDirectiveCFIOffset +/// ::= .cfi_off register, offset +bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { + int64_t Register = 0; + int64_t Offset = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + return getStreamer().EmitCFIOffset(Register, Offset); +} + +static bool isValidEncoding(int64_t Encoding) { + if (Encoding & ~0xff) + return false; + + if (Encoding == dwarf::DW_EH_PE_omit) + return true; + + const unsigned Format = Encoding & 0xf; + if (Format != dwarf::DW_EH_PE_absptr && Format != dwarf::DW_EH_PE_udata2 && + Format != dwarf::DW_EH_PE_udata4 && Format != dwarf::DW_EH_PE_udata8 && + Format != dwarf::DW_EH_PE_sdata2 && Format != dwarf::DW_EH_PE_sdata4 && + Format != dwarf::DW_EH_PE_sdata8 && Format != dwarf::DW_EH_PE_signed) + return false; + + const unsigned Application = Encoding & 0x70; + if (Application != dwarf::DW_EH_PE_absptr && + Application != dwarf::DW_EH_PE_pcrel) + return false; + + return true; +} + +/// ParseDirectiveCFIPersonalityOrLsda +/// ::= .cfi_personality encoding, [symbol_name] +/// ::= .cfi_lsda encoding, [symbol_name] +bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, + SMLoc DirectiveLoc) { + int64_t Encoding = 0; + if (getParser().ParseAbsoluteExpression(Encoding)) + return true; + if (Encoding == dwarf::DW_EH_PE_omit) + return false; + + if (!isValidEncoding(Encoding)) + return TokError("unsupported encoding."); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (IDVal == ".cfi_personality") + return getStreamer().EmitCFIPersonality(Sym, Encoding); + else { + assert(IDVal == ".cfi_lsda"); + return getStreamer().EmitCFILsda(Sym, Encoding); + } +} + +/// ParseDirectiveCFIRememberState +/// ::= .cfi_remember_state +bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, + SMLoc DirectiveLoc) { + return getStreamer().EmitCFIRememberState(); +} + +/// ParseDirectiveCFIRestoreState +/// ::= .cfi_remember_state +bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, + SMLoc DirectiveLoc) { + return getStreamer().EmitCFIRestoreState(); +} + +/// ParseDirectiveMacrosOnOff +/// ::= .macros_on +/// ::= .macros_off +bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive, + SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(getLexer().getLoc(), + "unexpected token in '" + Directive + "' directive"); + + getParser().MacrosEnabled = Directive == ".macros_on"; + + return false; +} + +/// ParseDirectiveMacro +/// ::= .macro name +bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, + SMLoc DirectiveLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.macro' directive"); + + // Eat the end of statement. + Lex(); + + AsmToken EndToken, StartToken = getTok(); + + // Lex the macro definition. + for (;;) { + // Check whether we have reached the end of the file. + if (getLexer().is(AsmToken::Eof)) + return Error(DirectiveLoc, "no matching '.endmacro' in definition"); + + // Otherwise, check whether we have reach the .endmacro. + if (getLexer().is(AsmToken::Identifier) && + (getTok().getIdentifier() == ".endm" || + getTok().getIdentifier() == ".endmacro")) { + EndToken = getTok(); + Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + EndToken.getIdentifier() + + "' directive"); + break; + } + + // Otherwise, scan til the end of the statement. + getParser().EatToEndOfStatement(); + } + + if (getParser().MacroMap.lookup(Name)) { + return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); + } + + const char *BodyStart = StartToken.getLoc().getPointer(); + const char *BodyEnd = EndToken.getLoc().getPointer(); + StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); + getParser().MacroMap[Name] = new Macro(Name, Body); + return false; +} + +/// ParseDirectiveEndMacro +/// ::= .endm +/// ::= .endmacro +bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive, + SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Directive + "' directive"); + + // If we are inside a macro instantiation, terminate the current + // instantiation. + if (!getParser().ActiveMacros.empty()) { + getParser().HandleMacroExit(); + return false; + } + + // Otherwise, this .endmacro is a stray entry in the file; well formed + // .endmacro directives are handled during the macro definition parsing. + return TokError("unexpected '" + Directive + "' in file, " + "no current macro definition"); +} + +bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { + getParser().CheckForValidSection(); + + const MCExpr *Value; + + if (getParser().ParseExpression(Value)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + if (DirName[1] == 's') + getStreamer().EmitSLEB128Value(Value); + else + getStreamer().EmitULEB128Value(Value); + + return false; +} + + +/// \brief Create an MCAsmParser instance. +MCAsmParser *llvm::createMCAsmParser(const Target &T, SourceMgr &SM, + MCContext &C, MCStreamer &Out, + const MCAsmInfo &MAI) { + return new AsmParser(T, SM, C, Out, MAI); +} diff --git a/final/lib/MC/MCParser/CMakeLists.txt b/final/lib/MC/MCParser/CMakeLists.txt new file mode 100644 index 00000000000..eaea9f6cd3c --- /dev/null +++ b/final/lib/MC/MCParser/CMakeLists.txt @@ -0,0 +1,11 @@ +add_llvm_library(LLVMMCParser + AsmLexer.cpp + AsmParser.cpp + COFFAsmParser.cpp + DarwinAsmParser.cpp + ELFAsmParser.cpp + MCAsmLexer.cpp + MCAsmParser.cpp + MCAsmParserExtension.cpp + TargetAsmParser.cpp + ) diff --git a/final/lib/MC/MCParser/COFFAsmParser.cpp b/final/lib/MC/MCParser/COFFAsmParser.cpp new file mode 100644 index 00000000000..5ecab03b00f --- /dev/null +++ b/final/lib/MC/MCParser/COFFAsmParser.cpp @@ -0,0 +1,144 @@ +//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/COFF.h" +using namespace llvm; + +namespace { + +class COFFAsmParser : public MCAsmParserExtension { + template + void AddDirectiveHandler(StringRef Directive) { + getParser().AddDirectiveHandler(this, Directive, + HandleDirective); + } + + bool ParseSectionSwitch(StringRef Section, + unsigned Characteristics, + SectionKind Kind); + + virtual void Initialize(MCAsmParser &Parser) { + // Call the base implementation. + MCAsmParserExtension::Initialize(Parser); + + AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text"); + AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data"); + AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + } + + bool ParseSectionDirectiveText(StringRef, SMLoc) { + return ParseSectionSwitch(".text", + COFF::IMAGE_SCN_CNT_CODE + | COFF::IMAGE_SCN_MEM_EXECUTE + | COFF::IMAGE_SCN_MEM_READ, + SectionKind::getText()); + } + bool ParseSectionDirectiveData(StringRef, SMLoc) { + return ParseSectionSwitch(".data", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + } + bool ParseSectionDirectiveBSS(StringRef, SMLoc) { + return ParseSectionSwitch(".bss", + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getBSS()); + } + + bool ParseDirectiveDef(StringRef, SMLoc); + bool ParseDirectiveScl(StringRef, SMLoc); + bool ParseDirectiveType(StringRef, SMLoc); + bool ParseDirectiveEndef(StringRef, SMLoc); + +public: + COFFAsmParser() {} +}; + +} // end annonomous namespace. + +bool COFFAsmParser::ParseSectionSwitch(StringRef Section, + unsigned Characteristics, + SectionKind Kind) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in section switching directive"); + Lex(); + + getStreamer().SwitchSection(getContext().getCOFFSection( + Section, Characteristics, Kind)); + + return false; +} + +bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) { + StringRef SymbolName; + + if (getParser().ParseIdentifier(SymbolName)) + return TokError("expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); + + getStreamer().BeginCOFFSymbolDef(Sym); + + Lex(); + return false; +} + +bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) { + int64_t SymbolStorageClass; + if (getParser().ParseAbsoluteExpression(SymbolStorageClass)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + Lex(); + getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass); + return false; +} + +bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) { + int64_t Type; + if (getParser().ParseAbsoluteExpression(Type)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + Lex(); + getStreamer().EmitCOFFSymbolType(Type); + return false; +} + +bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { + Lex(); + getStreamer().EndCOFFSymbolDef(); + return false; +} + +namespace llvm { + +MCAsmParserExtension *createCOFFAsmParser() { + return new COFFAsmParser; +} + +} diff --git a/final/lib/MC/MCParser/DarwinAsmParser.cpp b/final/lib/MC/MCParser/DarwinAsmParser.cpp new file mode 100644 index 00000000000..44f234566af --- /dev/null +++ b/final/lib/MC/MCParser/DarwinAsmParser.cpp @@ -0,0 +1,661 @@ +//===- DarwinAsmParser.cpp - Darwin (Mach-O) Assembly Parser --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +using namespace llvm; + +namespace { + +/// \brief Implementation of directive handling which is shared across all +/// Darwin targets. +class DarwinAsmParser : public MCAsmParserExtension { + template + void AddDirectiveHandler(StringRef Directive) { + getParser().AddDirectiveHandler(this, Directive, + HandleDirective); + } + + bool ParseSectionSwitch(const char *Segment, const char *Section, + unsigned TAA = 0, unsigned ImplicitAlign = 0, + unsigned StubSize = 0); + +public: + DarwinAsmParser() {} + + virtual void Initialize(MCAsmParser &Parser) { + // Call the base implementation. + this->MCAsmParserExtension::Initialize(Parser); + + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDesc>(".desc"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveLsym>(".lsym"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols>( + ".subsections_via_symbols"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( + ".secure_log_unique"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( + ".secure_log_reset"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill"); + + // Special section directives. + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstData>(".const_data"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConstructor>(".constructor"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveCString>(".cstring"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveData>(".data"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDestructor>(".destructor"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveDyld>(".dyld"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit0>(".fvmlib_init0"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveFVMLibInit1>(".fvmlib_init1"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLazySymbolPointers>(".lazy_symbol_pointer"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral16>(".literal16"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral4>(".literal4"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveLiteral8>(".literal8"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModInitFunc>(".mod_init_func"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveModTermFunc>(".mod_term_func"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveNonLazySymbolPointers>(".non_lazy_symbol_pointer"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatClsMeth>(".objc_cat_cls_meth"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCatInstMeth>(".objc_cat_inst_meth"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCCategory>(".objc_category"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClass>(".objc_class"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassNames>(".objc_class_names"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClassVars>(".objc_class_vars"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsMeth>(".objc_cls_meth"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCClsRefs>(".objc_cls_refs"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstMeth>(".objc_inst_meth"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCInstanceVars>(".objc_instance_vars"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMessageRefs>(".objc_message_refs"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMetaClass>(".objc_meta_class"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarNames>(".objc_meth_var_names"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCMethVarTypes>(".objc_meth_var_types"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCModuleInfo>(".objc_module_info"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCProtocol>(".objc_protocol"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSelectorStrs>(".objc_selector_strs"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCStringObject>(".objc_string_object"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveObjCSymbols>(".objc_symbols"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectivePICSymbolStub>(".picsymbol_stub"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticConst>(".static_const"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveStaticData>(".static_data"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveSymbolStub>(".symbol_stub"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTData>(".tdata"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveText>(".text"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveThreadInitFunc>(".thread_init_func"); + AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveTLV>(".tlv"); + } + + bool ParseDirectiveDesc(StringRef, SMLoc); + bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); + bool ParseDirectiveLsym(StringRef, SMLoc); + bool ParseDirectiveSection(StringRef, SMLoc); + bool ParseDirectiveSecureLogReset(StringRef, SMLoc); + bool ParseDirectiveSecureLogUnique(StringRef, SMLoc); + bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); + bool ParseDirectiveTBSS(StringRef, SMLoc); + bool ParseDirectiveZerofill(StringRef, SMLoc); + + // Named Section Directive + bool ParseSectionDirectiveConst(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__const"); + } + bool ParseSectionDirectiveStaticConst(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__static_const"); + } + bool ParseSectionDirectiveCString(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + } + bool ParseSectionDirectiveLiteral4(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__literal4", + MCSectionMachO::S_4BYTE_LITERALS, 4); + } + bool ParseSectionDirectiveLiteral8(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__literal8", + MCSectionMachO::S_8BYTE_LITERALS, 8); + } + bool ParseSectionDirectiveLiteral16(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__literal16", + MCSectionMachO::S_16BYTE_LITERALS, 16); + } + bool ParseSectionDirectiveConstructor(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__constructor"); + } + bool ParseSectionDirectiveDestructor(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__destructor"); + } + bool ParseSectionDirectiveFVMLibInit0(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__fvmlib_init0"); + } + bool ParseSectionDirectiveFVMLibInit1(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__fvmlib_init1"); + } + bool ParseSectionDirectiveSymbolStub(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__symbol_stub", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + // FIXME: Different on PPC and ARM. + 0, 16); + } + bool ParseSectionDirectivePICSymbolStub(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT","__picsymbol_stub", + MCSectionMachO::S_SYMBOL_STUBS | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, 26); + } + bool ParseSectionDirectiveData(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__data"); + } + bool ParseSectionDirectiveStaticData(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__static_data"); + } + bool ParseSectionDirectiveNonLazySymbolPointers(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, 4); + } + bool ParseSectionDirectiveLazySymbolPointers(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, 4); + } + bool ParseSectionDirectiveDyld(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__dyld"); + } + bool ParseSectionDirectiveModInitFunc(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, 4); + } + bool ParseSectionDirectiveModTermFunc(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, 4); + } + bool ParseSectionDirectiveConstData(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__const"); + } + bool ParseSectionDirectiveObjCClass(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__class", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCMetaClass(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__meta_class", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCCatClsMeth(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__cat_cls_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCCatInstMeth(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__cat_inst_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCProtocol(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__protocol", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCStringObject(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__string_object", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCClsMeth(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__cls_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCInstMeth(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__inst_meth", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCClsRefs(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__cls_refs", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP | + MCSectionMachO::S_LITERAL_POINTERS, 4); + } + bool ParseSectionDirectiveObjCMessageRefs(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__message_refs", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP | + MCSectionMachO::S_LITERAL_POINTERS, 4); + } + bool ParseSectionDirectiveObjCSymbols(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__symbols", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCCategory(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__category", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCClassVars(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__class_vars", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCInstanceVars(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__instance_vars", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCModuleInfo(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__module_info", + MCSectionMachO::S_ATTR_NO_DEAD_STRIP); + } + bool ParseSectionDirectiveObjCClassNames(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + } + bool ParseSectionDirectiveObjCMethVarTypes(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + } + bool ParseSectionDirectiveObjCMethVarNames(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__cstring", + MCSectionMachO::S_CSTRING_LITERALS); + } + bool ParseSectionDirectiveObjCSelectorStrs(StringRef, SMLoc) { + return ParseSectionSwitch("__OBJC", "__selector_strs", + MCSectionMachO::S_CSTRING_LITERALS); + } + bool ParseSectionDirectiveTData(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__thread_data", + MCSectionMachO::S_THREAD_LOCAL_REGULAR); + } + bool ParseSectionDirectiveText(StringRef, SMLoc) { + return ParseSectionSwitch("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); + } + bool ParseSectionDirectiveTLV(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__thread_vars", + MCSectionMachO::S_THREAD_LOCAL_VARIABLES); + } + bool ParseSectionDirectiveThreadInitFunc(StringRef, SMLoc) { + return ParseSectionSwitch("__DATA", "__thread_init", + MCSectionMachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS); + } + +}; + +} + +bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, + const char *Section, + unsigned TAA, unsigned Align, + unsigned StubSize) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in section switching directive"); + Lex(); + + // FIXME: Arch specific. + bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack. + getStreamer().SwitchSection(getContext().getMachOSection( + Segment, Section, TAA, StubSize, + isText ? SectionKind::getText() + : SectionKind::getDataRel())); + + // Set the implicit alignment, if any. + // + // FIXME: This isn't really what 'as' does; I think it just uses the implicit + // alignment on the section (e.g., if one manually inserts bytes into the + // section, then just issuing the section switch directive will not realign + // the section. However, this is arguably more reasonable behavior, and there + // is no good reason for someone to intentionally emit incorrectly sized + // values into the implicitly aligned sections. + if (Align) + getStreamer().EmitValueToAlignment(Align, 0, 1, 0); + + return false; +} + +/// ParseDirectiveDesc +/// ::= .desc identifier , expression +bool DarwinAsmParser::ParseDirectiveDesc(StringRef, SMLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.desc' directive"); + Lex(); + + int64_t DescValue; + if (getParser().ParseAbsoluteExpression(DescValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.desc' directive"); + + Lex(); + + // Set the n_desc field of this Symbol to this DescValue + getStreamer().EmitSymbolDesc(Sym, DescValue); + + return false; +} + +/// ParseDirectiveDumpOrLoad +/// ::= ( .dump | .load ) "filename" +bool DarwinAsmParser::ParseDirectiveDumpOrLoad(StringRef Directive, + SMLoc IDLoc) { + bool IsDump = Directive == ".dump"; + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.dump' or '.load' directive"); + + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.dump' or '.load' directive"); + + Lex(); + + // FIXME: If/when .dump and .load are implemented they will be done in the + // the assembly parser and not have any need for an MCStreamer API. + if (IsDump) + Warning(IDLoc, "ignoring directive .dump for now"); + else + Warning(IDLoc, "ignoring directive .load for now"); + + return false; +} + +/// ParseDirectiveLsym +/// ::= .lsym identifier , expression +bool DarwinAsmParser::ParseDirectiveLsym(StringRef, SMLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.lsym' directive"); + Lex(); + + const MCExpr *Value; + if (getParser().ParseExpression(Value)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.lsym' directive"); + + Lex(); + + // We don't currently support this directive. + // + // FIXME: Diagnostic location! + (void) Sym; + return TokError("directive '.lsym' is unsupported"); +} + +/// ParseDirectiveSection: +/// ::= .section identifier (',' identifier)* +bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + SMLoc Loc = getLexer().getLoc(); + + StringRef SectionName; + if (getParser().ParseIdentifier(SectionName)) + return Error(Loc, "expected identifier after '.section' directive"); + + // Verify there is a following comma. + if (!getLexer().is(AsmToken::Comma)) + return TokError("unexpected token in '.section' directive"); + + std::string SectionSpec = SectionName; + SectionSpec += ","; + + // Add all the tokens until the end of the line, ParseSectionSpecifier will + // handle this. + StringRef EOL = getLexer().LexUntilEndOfStatement(); + SectionSpec.append(EOL.begin(), EOL.end()); + + Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.section' directive"); + Lex(); + + + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorStr = + MCSectionMachO::ParseSectionSpecifier(SectionSpec, Segment, Section, + TAA, StubSize); + + if (!ErrorStr.empty()) + return Error(Loc, ErrorStr.c_str()); + + // FIXME: Arch specific. + bool isText = Segment == "__TEXT"; // FIXME: Hack. + getStreamer().SwitchSection(getContext().getMachOSection( + Segment, Section, TAA, StubSize, + isText ? SectionKind::getText() + : SectionKind::getDataRel())); + return false; +} + +/// ParseDirectiveSecureLogUnique +/// ::= .secure_log_unique ... message ... +bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { + StringRef LogMessage = getParser().ParseStringToEndOfStatement(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.secure_log_unique' directive"); + + if (getContext().getSecureLogUsed() != false) + return Error(IDLoc, ".secure_log_unique specified multiple times"); + + // Get the secure log path. + const char *SecureLogFile = getContext().getSecureLogFile(); + if (SecureLogFile == NULL) + return Error(IDLoc, ".secure_log_unique used but AS_SECURE_LOG_FILE " + "environment variable unset."); + + // Open the secure log file if we haven't already. + raw_ostream *OS = getContext().getSecureLog(); + if (OS == NULL) { + std::string Err; + OS = new raw_fd_ostream(SecureLogFile, Err, raw_fd_ostream::F_Append); + if (!Err.empty()) { + delete OS; + return Error(IDLoc, Twine("can't open secure log file: ") + + SecureLogFile + " (" + Err + ")"); + } + getContext().setSecureLog(OS); + } + + // Write the message. + int CurBuf = getSourceManager().FindBufferContainingLoc(IDLoc); + *OS << getSourceManager().getBufferInfo(CurBuf).Buffer->getBufferIdentifier() + << ":" << getSourceManager().FindLineNumber(IDLoc, CurBuf) << ":" + << LogMessage + "\n"; + + getContext().setSecureLogUsed(true); + + return false; +} + +/// ParseDirectiveSecureLogReset +/// ::= .secure_log_reset +bool DarwinAsmParser::ParseDirectiveSecureLogReset(StringRef, SMLoc IDLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.secure_log_reset' directive"); + + Lex(); + + getContext().setSecureLogUsed(false); + + return false; +} + +/// ParseDirectiveSubsectionsViaSymbols +/// ::= .subsections_via_symbols +bool DarwinAsmParser::ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.subsections_via_symbols' directive"); + + Lex(); + + getStreamer().EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); + + return false; +} + +/// ParseDirectiveTBSS +/// ::= .tbss identifier, size, align +bool DarwinAsmParser::ParseDirectiveTBSS(StringRef, SMLoc) { + SMLoc IDLoc = getLexer().getLoc(); + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = getLexer().getLoc(); + if (getParser().ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = getLexer().getLoc(); + if (getParser().ParseAbsoluteExpression(Pow2Alignment)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.tbss' directive"); + + Lex(); + + if (Size < 0) + return Error(SizeLoc, "invalid '.tbss' directive size, can't be less than" + "zero"); + + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.tbss' alignment, can't be less" + "than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + getStreamer().EmitTBSSSymbol(getContext().getMachOSection( + "__DATA", "__thread_bss", + MCSectionMachO::S_THREAD_LOCAL_ZEROFILL, + 0, SectionKind::getThreadBSS()), + Sym, Size, 1 << Pow2Alignment); + + return false; +} + +/// ParseDirectiveZerofill +/// ::= .zerofill segname , sectname [, identifier , size_expression [ +/// , align_expression ]] +bool DarwinAsmParser::ParseDirectiveZerofill(StringRef, SMLoc) { + StringRef Segment; + if (getParser().ParseIdentifier(Segment)) + return TokError("expected segment name after '.zerofill' directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + StringRef Section; + if (getParser().ParseIdentifier(Section)) + return TokError("expected section name after comma in '.zerofill' " + "directive"); + + // If this is the end of the line all that was wanted was to create the + // the section but with no symbol. + if (getLexer().is(AsmToken::EndOfStatement)) { + // Create the zerofill section but no symbol + getStreamer().EmitZerofill(getContext().getMachOSection( + Segment, Section, MCSectionMachO::S_ZEROFILL, + 0, SectionKind::getBSS())); + return false; + } + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + SMLoc IDLoc = getLexer().getLoc(); + StringRef IDStr; + if (getParser().ParseIdentifier(IDStr)) + return TokError("expected identifier in directive"); + + // handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(IDStr); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = getLexer().getLoc(); + if (getParser().ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = getLexer().getLoc(); + if (getParser().ParseAbsoluteExpression(Pow2Alignment)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.zerofill' directive"); + + Lex(); + + if (Size < 0) + return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " + "than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assembler + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " + "can't be less than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Create the zerofill Symbol with Size and Pow2Alignment + // + // FIXME: Arch specific. + getStreamer().EmitZerofill(getContext().getMachOSection( + Segment, Section, MCSectionMachO::S_ZEROFILL, + 0, SectionKind::getBSS()), + Sym, Size, 1 << Pow2Alignment); + + return false; +} + +namespace llvm { + +MCAsmParserExtension *createDarwinAsmParser() { + return new DarwinAsmParser; +} + +} diff --git a/final/lib/MC/MCParser/ELFAsmParser.cpp b/final/lib/MC/MCParser/ELFAsmParser.cpp new file mode 100644 index 00000000000..dcf689a6f0e --- /dev/null +++ b/final/lib/MC/MCParser/ELFAsmParser.cpp @@ -0,0 +1,533 @@ +//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/ELF.h" +using namespace llvm; + +namespace { + +class ELFAsmParser : public MCAsmParserExtension { + template + void AddDirectiveHandler(StringRef Directive) { + getParser().AddDirectiveHandler(this, Directive, + HandleDirective); + } + + bool ParseSectionSwitch(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind); + bool SeenIdent; + +public: + ELFAsmParser() : SeenIdent(false) { + BracketExpressionsSupported = true; + } + + virtual void Initialize(MCAsmParser &Parser) { + // Call the base implementation. + this->MCAsmParserExtension::Initialize(Parser); + + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveData>(".data"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveText>(".text"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveBSS>(".bss"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveRoData>(".rodata"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTData>(".tdata"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveTBSS>(".tbss"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRel>(".data.rel"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRo>(".data.rel.ro"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveDataRelRoLocal>(".data.rel.ro.local"); + AddDirectiveHandler<&ELFAsmParser::ParseSectionDirectiveEhFrame>(".eh_frame"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSection>(".section"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectivePushSection>(".pushsection"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectivePopSection>(".popsection"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSize>(".size"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectivePrevious>(".previous"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveType>(".type"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveIdent>(".ident"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveSymver>(".symver"); + AddDirectiveHandler<&ELFAsmParser::ParseDirectiveWeakref>(".weakref"); + } + + // FIXME: Part of this logic is duplicated in the MCELFStreamer. What is + // the best way for us to get access to it? + bool ParseSectionDirectiveData(StringRef, SMLoc) { + return ParseSectionSwitch(".data", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, + SectionKind::getDataRel()); + } + bool ParseSectionDirectiveText(StringRef, SMLoc) { + return ParseSectionSwitch(".text", ELF::SHT_PROGBITS, + ELF::SHF_EXECINSTR | + ELF::SHF_ALLOC, SectionKind::getText()); + } + bool ParseSectionDirectiveBSS(StringRef, SMLoc) { + return ParseSectionSwitch(".bss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | + ELF::SHF_ALLOC, SectionKind::getBSS()); + } + bool ParseSectionDirectiveRoData(StringRef, SMLoc) { + return ParseSectionSwitch(".rodata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getReadOnly()); + } + bool ParseSectionDirectiveTData(StringRef, SMLoc) { + return ParseSectionSwitch(".tdata", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_TLS | ELF::SHF_WRITE, + SectionKind::getThreadData()); + } + bool ParseSectionDirectiveTBSS(StringRef, SMLoc) { + return ParseSectionSwitch(".tbss", ELF::SHT_NOBITS, + ELF::SHF_ALLOC | + ELF::SHF_TLS | ELF::SHF_WRITE, + SectionKind::getThreadBSS()); + } + bool ParseSectionDirectiveDataRel(StringRef, SMLoc) { + return ParseSectionSwitch(".data.rel", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_WRITE, + SectionKind::getDataRel()); + } + bool ParseSectionDirectiveDataRelRo(StringRef, SMLoc) { + return ParseSectionSwitch(".data.rel.ro", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + } + bool ParseSectionDirectiveDataRelRoLocal(StringRef, SMLoc) { + return ParseSectionSwitch(".data.rel.ro.local", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + } + bool ParseSectionDirectiveEhFrame(StringRef, SMLoc) { + return ParseSectionSwitch(".eh_frame", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | + ELF::SHF_WRITE, + SectionKind::getDataRel()); + } + bool ParseDirectivePushSection(StringRef, SMLoc); + bool ParseDirectivePopSection(StringRef, SMLoc); + bool ParseDirectiveSection(StringRef, SMLoc); + bool ParseDirectiveSize(StringRef, SMLoc); + bool ParseDirectivePrevious(StringRef, SMLoc); + bool ParseDirectiveType(StringRef, SMLoc); + bool ParseDirectiveIdent(StringRef, SMLoc); + bool ParseDirectiveSymver(StringRef, SMLoc); + bool ParseDirectiveWeakref(StringRef, SMLoc); + +private: + bool ParseSectionName(StringRef &SectionName); +}; + +} + +bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, + unsigned Flags, SectionKind Kind) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in section switching directive"); + Lex(); + + getStreamer().SwitchSection(getContext().getELFSection( + Section, Type, Flags, Kind)); + + return false; +} + +bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + const MCExpr *Expr; + if (getParser().ParseExpression(Expr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + getStreamer().EmitELFSize(Sym, Expr); + return false; +} + +bool ELFAsmParser::ParseSectionName(StringRef &SectionName) { + // A section name can contain -, so we cannot just use + // ParseIdentifier. + SMLoc FirstLoc = getLexer().getLoc(); + unsigned Size = 0; + + if (getLexer().is(AsmToken::String)) { + SectionName = getTok().getIdentifier(); + Lex(); + return false; + } + + for (;;) { + StringRef Tmp; + unsigned CurSize; + + SMLoc PrevLoc = getLexer().getLoc(); + if (getLexer().is(AsmToken::Minus)) { + CurSize = 1; + Lex(); // Consume the "-". + } else if (getLexer().is(AsmToken::String)) { + CurSize = getTok().getIdentifier().size() + 2; + Lex(); + } else if (getLexer().is(AsmToken::Identifier)) { + CurSize = getTok().getIdentifier().size(); + Lex(); + } else { + break; + } + + Size += CurSize; + SectionName = StringRef(FirstLoc.getPointer(), Size); + + // Make sure the following token is adjacent. + if (PrevLoc.getPointer() + CurSize != getTok().getLoc().getPointer()) + break; + } + if (Size == 0) + return true; + + return false; +} + +static SectionKind computeSectionKind(unsigned Flags) { + if (Flags & ELF::SHF_EXECINSTR) + return SectionKind::getText(); + if (Flags & ELF::SHF_TLS) + return SectionKind::getThreadData(); + return SectionKind::getDataRel(); +} + +static int parseSectionFlags(StringRef flagsStr) { + int flags = 0; + + for (unsigned i = 0; i < flagsStr.size(); i++) { + switch (flagsStr[i]) { + case 'a': + flags |= ELF::SHF_ALLOC; + break; + case 'x': + flags |= ELF::SHF_EXECINSTR; + break; + case 'w': + flags |= ELF::SHF_WRITE; + break; + case 'M': + flags |= ELF::SHF_MERGE; + break; + case 'S': + flags |= ELF::SHF_STRINGS; + break; + case 'T': + flags |= ELF::SHF_TLS; + break; + case 'c': + flags |= ELF::XCORE_SHF_CP_SECTION; + break; + case 'd': + flags |= ELF::XCORE_SHF_DP_SECTION; + break; + case 'G': + flags |= ELF::SHF_GROUP; + break; + default: + return -1; + } + } + + return flags; +} + +bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { + getStreamer().PushSection(); + + if (ParseDirectiveSection(s, loc)) { + getStreamer().PopSection(); + return true; + } + + return false; +} + +bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { + if (!getStreamer().PopSection()) + return TokError(".popsection without corresponding .pushsection"); + return false; +} + +// FIXME: This is a work in progress. +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + StringRef SectionName; + + if (ParseSectionName(SectionName)) + return TokError("expected identifier in directive"); + + StringRef TypeName; + int64_t Size = 0; + StringRef GroupName; + unsigned Flags = 0; + + // Set the defaults first. + if (SectionName == ".fini" || SectionName == ".init" || + SectionName == ".rodata") + Flags |= ELF::SHF_ALLOC; + if (SectionName == ".fini" || SectionName == ".init") + Flags |= ELF::SHF_EXECINSTR; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in directive"); + + StringRef FlagsStr = getTok().getStringContents(); + Lex(); + + int extraFlags = parseSectionFlags(FlagsStr); + if (extraFlags < 0) + return TokError("unknown flag"); + Flags |= extraFlags; + + bool Mergeable = Flags & ELF::SHF_MERGE; + bool Group = Flags & ELF::SHF_GROUP; + + if (getLexer().isNot(AsmToken::Comma)) { + if (Mergeable) + return TokError("Mergeable section must specify the type"); + if (Group) + return TokError("Group section must specify the type"); + } else { + Lex(); + if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) + return TokError("expected '@' or '%' before type"); + + Lex(); + if (getParser().ParseIdentifier(TypeName)) + return TokError("expected identifier in directive"); + + if (Mergeable) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected the entry size"); + Lex(); + if (getParser().ParseAbsoluteExpression(Size)) + return true; + if (Size <= 0) + return TokError("entry size must be positive"); + } + + if (Group) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected group name"); + Lex(); + if (getParser().ParseIdentifier(GroupName)) + return true; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + StringRef Linkage; + if (getParser().ParseIdentifier(Linkage)) + return true; + if (Linkage != "comdat") + return TokError("Linkage must be 'comdat'"); + } + } + } + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + unsigned Type = ELF::SHT_PROGBITS; + + if (!TypeName.empty()) { + if (TypeName == "init_array") + Type = ELF::SHT_INIT_ARRAY; + else if (TypeName == "fini_array") + Type = ELF::SHT_FINI_ARRAY; + else if (TypeName == "preinit_array") + Type = ELF::SHT_PREINIT_ARRAY; + else if (TypeName == "nobits") + Type = ELF::SHT_NOBITS; + else if (TypeName == "progbits") + Type = ELF::SHT_PROGBITS; + else if (TypeName == "note") + Type = ELF::SHT_NOTE; + else if (TypeName == "unwind") + Type = ELF::SHT_X86_64_UNWIND; + else + return TokError("unknown section type"); + } + + SectionKind Kind = computeSectionKind(Flags); + getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, + Flags, Kind, Size, + GroupName)); + return false; +} + +bool ELFAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { + const MCSection *PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection == NULL) + return TokError(".previous without corresponding .section"); + getStreamer().SwitchSection(PreviousSection); + + return false; +} + +/// ParseDirectiveELFType +/// ::= .type identifier , @attribute +bool ELFAsmParser::ParseDirectiveType(StringRef, SMLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.type' directive"); + Lex(); + + if (getLexer().isNot(AsmToken::Percent) && getLexer().isNot(AsmToken::At)) + return TokError("expected '@' or '%' before type"); + Lex(); + + StringRef Type; + SMLoc TypeLoc; + + TypeLoc = getLexer().getLoc(); + if (getParser().ParseIdentifier(Type)) + return TokError("expected symbol type in directive"); + + MCSymbolAttr Attr = StringSwitch(Type) + .Case("function", MCSA_ELF_TypeFunction) + .Case("object", MCSA_ELF_TypeObject) + .Case("tls_object", MCSA_ELF_TypeTLS) + .Case("common", MCSA_ELF_TypeCommon) + .Case("notype", MCSA_ELF_TypeNoType) + .Case("gnu_unique_object", MCSA_ELF_TypeGnuUniqueObject) + .Default(MCSA_Invalid); + + if (Attr == MCSA_Invalid) + return Error(TypeLoc, "unsupported attribute in '.type' directive"); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.type' directive"); + + Lex(); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + return false; +} + +/// ParseDirectiveIdent +/// ::= .ident string +bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) { + if (getLexer().isNot(AsmToken::String)) + return TokError("unexpected token in '.ident' directive"); + + StringRef Data = getTok().getIdentifier(); + + Lex(); + + const MCSection *Comment = + getContext().getELFSection(".comment", ELF::SHT_PROGBITS, + ELF::SHF_MERGE | + ELF::SHF_STRINGS, + SectionKind::getReadOnly(), + 1, ""); + + getStreamer().PushSection(); + getStreamer().SwitchSection(Comment); + if (!SeenIdent) { + getStreamer().EmitIntValue(0, 1); + SeenIdent = true; + } + getStreamer().EmitBytes(Data, 0); + getStreamer().EmitIntValue(0, 1); + getStreamer().PopSection(); + return false; +} + +/// ParseDirectiveSymver +/// ::= .symver foo, bar2@zed +bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) { + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + + Lex(); + + StringRef AliasName; + if (getParser().ParseIdentifier(AliasName)) + return TokError("expected identifier in directive"); + + if (AliasName.find('@') == StringRef::npos) + return TokError("expected a '@' in the name"); + + MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + const MCExpr *Value = MCSymbolRefExpr::Create(Sym, getContext()); + + getStreamer().EmitAssignment(Alias, Value); + return false; +} + +/// ParseDirectiveWeakref +/// ::= .weakref foo, bar +bool ELFAsmParser::ParseDirectiveWeakref(StringRef, SMLoc) { + // FIXME: Share code with the other alias building directives. + + StringRef AliasName; + if (getParser().ParseIdentifier(AliasName)) + return TokError("expected identifier in directive"); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("expected a comma"); + + Lex(); + + StringRef Name; + if (getParser().ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + MCSymbol *Alias = getContext().GetOrCreateSymbol(AliasName); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + getStreamer().EmitWeakReference(Alias, Sym); + return false; +} + +namespace llvm { + +MCAsmParserExtension *createELFAsmParser() { + return new ELFAsmParser; +} + +} diff --git a/final/lib/MC/MCParser/MCAsmLexer.cpp b/final/lib/MC/MCParser/MCAsmLexer.cpp new file mode 100644 index 00000000000..dceece78ba1 --- /dev/null +++ b/final/lib/MC/MCParser/MCAsmLexer.cpp @@ -0,0 +1,27 @@ +//===-- MCAsmLexer.cpp - Abstract Asm Lexer Interface ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/Support/SourceMgr.h" + +using namespace llvm; + +MCAsmLexer::MCAsmLexer() : CurTok(AsmToken::Error, StringRef()), TokStart(0) { +} + +MCAsmLexer::~MCAsmLexer() { +} + +SMLoc MCAsmLexer::getLoc() const { + return SMLoc::getFromPointer(TokStart); +} + +SMLoc AsmToken::getLoc() const { + return SMLoc::getFromPointer(Str.data()); +} diff --git a/final/lib/MC/MCParser/MCAsmParser.cpp b/final/lib/MC/MCParser/MCAsmParser.cpp new file mode 100644 index 00000000000..70295efc613 --- /dev/null +++ b/final/lib/MC/MCParser/MCAsmParser.cpp @@ -0,0 +1,44 @@ +//===-- MCAsmParser.cpp - Abstract Asm Parser Interface -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + +MCAsmParser::MCAsmParser() : TargetParser(0), ShowParsedOperands(0) { +} + +MCAsmParser::~MCAsmParser() { +} + +void MCAsmParser::setTargetParser(TargetAsmParser &P) { + assert(!TargetParser && "Target parser is already initialized!"); + TargetParser = &P; + TargetParser->Initialize(*this); +} + +const AsmToken &MCAsmParser::getTok() { + return getLexer().getTok(); +} + +bool MCAsmParser::TokError(const Twine &Msg) { + Error(getLexer().getLoc(), Msg); + return true; +} + +bool MCAsmParser::ParseExpression(const MCExpr *&Res) { + SMLoc L; + return ParseExpression(Res, L); +} + + diff --git a/final/lib/MC/MCParser/MCAsmParserExtension.cpp b/final/lib/MC/MCParser/MCAsmParserExtension.cpp new file mode 100644 index 00000000000..3f25a14926b --- /dev/null +++ b/final/lib/MC/MCParser/MCAsmParserExtension.cpp @@ -0,0 +1,22 @@ +//===-- MCAsmParserExtension.cpp - Asm Parser Hooks -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +using namespace llvm; + +MCAsmParserExtension::MCAsmParserExtension() : + BracketExpressionsSupported(false) { +} + +MCAsmParserExtension::~MCAsmParserExtension() { +} + +void MCAsmParserExtension::Initialize(MCAsmParser &Parser) { + this->Parser = &Parser; +} diff --git a/final/lib/MC/MCParser/Makefile b/final/lib/MC/MCParser/Makefile new file mode 100644 index 00000000000..4477757657c --- /dev/null +++ b/final/lib/MC/MCParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/MC/MCParser/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMMCParser +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/MC/MCParser/TargetAsmParser.cpp b/final/lib/MC/MCParser/TargetAsmParser.cpp new file mode 100644 index 00000000000..8d43c21f4bc --- /dev/null +++ b/final/lib/MC/MCParser/TargetAsmParser.cpp @@ -0,0 +1,19 @@ +//===-- TargetAsmParser.cpp - Target Assembly Parser -----------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmParser.h" +using namespace llvm; + +TargetAsmParser::TargetAsmParser(const Target &T) + : TheTarget(T), AvailableFeatures(0) +{ +} + +TargetAsmParser::~TargetAsmParser() { +} diff --git a/final/lib/MC/MCPureStreamer.cpp b/final/lib/MC/MCPureStreamer.cpp new file mode 100644 index 00000000000..6098e6b8f38 --- /dev/null +++ b/final/lib/MC/MCPureStreamer.cpp @@ -0,0 +1,234 @@ +//===- lib/MC/MCPureStreamer.cpp - MC "Pure" Object Output ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectStreamer.h" +// FIXME: Remove this. +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { + +class MCPureStreamer : public MCObjectStreamer { +private: + virtual void EmitInstToFragment(const MCInst &Inst); + virtual void EmitInstToData(const MCInst &Inst); + +public: + MCPureStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter) {} + + /// @name MCStreamer Interface + /// @{ + + virtual void InitSections(); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0, unsigned ByteAlignment = 0); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + virtual void EmitValueToOffset(const MCExpr *Offset, + unsigned char Value = 0); + virtual void Finish(); + + + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitThumbFunc(MCSymbol *Func) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitCOFFSymbolStorageClass(int StorageClass) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitCOFFSymbolType(int Type) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EndCOFFSymbolDef() { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual void EmitFileDirective(StringRef Filename) { + report_fatal_error("unsupported directive in pure streamer"); + } + virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename) { + report_fatal_error("unsupported directive in pure streamer"); + return false; + } + + /// @} +}; + +} // end anonymous namespace. + +void MCPureStreamer::InitSections() { + // FIMXE: To what!? + SwitchSection(getContext().getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + 0, SectionKind::getText())); + +} + +void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); + assert(getCurrentSection() && "Cannot emit before setting section!"); + + Symbol->setSection(*getCurrentSection()); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // We have to create a new fragment if this is an atom defining symbol, + // fragments cannot span atoms. + if (getAssembler().isSymbolLinkerVisible(SD.getSymbol())) + new MCDataFragment(getCurrentSectionData()); + + // FIXME: This is wasteful, we don't necessarily need to create a data + // fragment. Instead, we should mark the symbol as pointing into the data + // fragment if it exists, otherwise we should just queue the label and set its + // fragment pointer when we emit the next fragment. + MCDataFragment *F = getOrCreateDataFragment(); + assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); + SD.setFragment(F); + SD.setOffset(F->getContents().size()); +} + +void MCPureStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + // FIXME: Lift context changes into super class. + getAssembler().getOrCreateSymbolData(*Symbol); + Symbol->setVariableValue(AddValueSymbols(Value)); +} + +void MCPureStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned ByteAlignment) { + report_fatal_error("not yet implemented in pure streamer"); +} + +void MCPureStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); +} + +void MCPureStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, unsigned ValueSize, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, + getCurrentSectionData()); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void MCPureStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // TODO: This is exactly the same as WinCOFFStreamer. Consider merging into + // MCObjectStreamer. + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, + getCurrentSectionData()); + F->setEmitNops(true); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void MCPureStreamer::EmitValueToOffset(const MCExpr *Offset, + unsigned char Value) { + new MCOrgFragment(*Offset, Value, getCurrentSectionData()); +} + +void MCPureStreamer::EmitInstToFragment(const MCInst &Inst) { + MCInstFragment *IF = new MCInstFragment(Inst, getCurrentSectionData()); + + // Add the fixups and data. + // + // FIXME: Revisit this design decision when relaxation is done, we may be + // able to get away with not storing any extra data in the MCInst. + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + VecOS.flush(); + + IF->getCode() = Code; + IF->getFixups() = Fixups; +} + +void MCPureStreamer::EmitInstToData(const MCInst &Inst) { + MCDataFragment *DF = getOrCreateDataFragment(); + + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); + VecOS.flush(); + + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->addFixup(Fixups[i]); + } + DF->getContents().append(Code.begin(), Code.end()); +} + +void MCPureStreamer::Finish() { + // FIXME: Handle DWARF tables? + + this->MCObjectStreamer::Finish(); +} + +MCStreamer *llvm::createPureStreamer(MCContext &Context, TargetAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE) { + return new MCPureStreamer(Context, TAB, OS, CE); +} diff --git a/final/lib/MC/MCSection.cpp b/final/lib/MC/MCSection.cpp new file mode 100644 index 00000000000..a792d563179 --- /dev/null +++ b/final/lib/MC/MCSection.cpp @@ -0,0 +1,22 @@ +//===- lib/MC/MCSection.cpp - Machine Code Section Representation ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// MCSection +//===----------------------------------------------------------------------===// + +MCSection::~MCSection() { +} + diff --git a/final/lib/MC/MCSectionCOFF.cpp b/final/lib/MC/MCSectionCOFF.cpp new file mode 100644 index 00000000000..90091f06e9a --- /dev/null +++ b/final/lib/MC/MCSectionCOFF.cpp @@ -0,0 +1,84 @@ +//===- lib/MC/MCSectionCOFF.cpp - COFF Code Section Representation --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +MCSectionCOFF::~MCSectionCOFF() {} // anchor. + +// ShouldOmitSectionDirective - Decides whether a '.section' directive +// should be printed before the section name +bool MCSectionCOFF::ShouldOmitSectionDirective(StringRef Name, + const MCAsmInfo &MAI) const { + + // FIXME: Does .section .bss/.data/.text work everywhere?? + if (Name == ".text" || Name == ".data" || Name == ".bss") + return true; + + return false; +} + +void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + + // standard sections don't require the '.section' + if (ShouldOmitSectionDirective(SectionName, MAI)) { + OS << '\t' << getSectionName() << '\n'; + return; + } + + OS << "\t.section\t" << getSectionName() << ",\""; + if (getKind().isText()) + OS << 'x'; + if (getKind().isWriteable()) + OS << 'w'; + else + OS << 'r'; + if (getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) + OS << 'n'; + OS << "\"\n"; + + if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { + switch (Selection) { + case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: + OS << "\t.linkonce one_only\n"; + break; + case COFF::IMAGE_COMDAT_SELECT_ANY: + OS << "\t.linkonce discard\n"; + break; + case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: + OS << "\t.linkonce same_size\n"; + break; + case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH: + OS << "\t.linkonce same_contents\n"; + break; + //NOTE: as of binutils 2.20, there is no way to specifiy select largest + // with the .linkonce directive. For now, we treat it as an invalid + // comdat selection value. + case COFF::IMAGE_COMDAT_SELECT_LARGEST: + // OS << "\t.linkonce largest\n"; + // break; + default: + assert (0 && "unsupported COFF selection type"); + break; + } + } +} + +bool MCSectionCOFF::UseCodeAlign() const { + return getKind().isText(); +} + +bool MCSectionCOFF::isVirtualSection() const { + return getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; +} diff --git a/final/lib/MC/MCSectionELF.cpp b/final/lib/MC/MCSectionELF.cpp new file mode 100644 index 00000000000..dfd77c3fe81 --- /dev/null +++ b/final/lib/MC/MCSectionELF.cpp @@ -0,0 +1,150 @@ +//===- lib/MC/MCSectionELF.cpp - ELF Code Section Representation ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MCSectionELF::~MCSectionELF() {} // anchor. + +// ShouldOmitSectionDirective - Decides whether a '.section' directive +// should be printed before the section name +bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, + const MCAsmInfo &MAI) const { + + // FIXME: Does .section .bss/.data/.text work everywhere?? + if (Name == ".text" || Name == ".data" || + (Name == ".bss" && !MAI.usesELFSectionDirectiveForBSS())) + return true; + + return false; +} + +void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + + if (ShouldOmitSectionDirective(SectionName, MAI)) { + OS << '\t' << getSectionName() << '\n'; + return; + } + + StringRef name = getSectionName(); + if (name.find_first_not_of("0123456789_." + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == name.npos) { + OS << "\t.section\t" << name; + } else { + OS << "\t.section\t\""; + for (const char *b = name.begin(), *e = name.end(); b < e; ++b) { + if (*b == '"') // Unquoted " + OS << "\\\""; + else if (*b != '\\') // Neither " or backslash + OS << *b; + else if (b + 1 == e) // Trailing backslash + OS << "\\\\"; + else { + OS << b[0] << b[1]; // Quoted character + ++b; + } + } + OS << '"'; + } + + // Handle the weird solaris syntax if desired. + if (MAI.usesSunStyleELFSectionSwitchSyntax() && + !(Flags & ELF::SHF_MERGE)) { + if (Flags & ELF::SHF_ALLOC) + OS << ",#alloc"; + if (Flags & ELF::SHF_EXECINSTR) + OS << ",#execinstr"; + if (Flags & ELF::SHF_WRITE) + OS << ",#write"; + if (Flags & ELF::SHF_TLS) + OS << ",#tls"; + OS << '\n'; + return; + } + + OS << ",\""; + if (Flags & ELF::SHF_ALLOC) + OS << 'a'; + if (Flags & ELF::SHF_EXECINSTR) + OS << 'x'; + if (Flags & ELF::SHF_GROUP) + OS << 'G'; + if (Flags & ELF::SHF_WRITE) + OS << 'w'; + if (Flags & ELF::SHF_MERGE) + OS << 'M'; + if (Flags & ELF::SHF_STRINGS) + OS << 'S'; + if (Flags & ELF::SHF_TLS) + OS << 'T'; + + // If there are target-specific flags, print them. + if (Flags & ELF::XCORE_SHF_CP_SECTION) + OS << 'c'; + if (Flags & ELF::XCORE_SHF_DP_SECTION) + OS << 'd'; + + OS << '"'; + + OS << ','; + + // If comment string is '@', e.g. as on ARM - use '%' instead + if (MAI.getCommentString()[0] == '@') + OS << '%'; + else + OS << '@'; + + if (Type == ELF::SHT_INIT_ARRAY) + OS << "init_array"; + else if (Type == ELF::SHT_FINI_ARRAY) + OS << "fini_array"; + else if (Type == ELF::SHT_PREINIT_ARRAY) + OS << "preinit_array"; + else if (Type == ELF::SHT_NOBITS) + OS << "nobits"; + else if (Type == ELF::SHT_NOTE) + OS << "note"; + else if (Type == ELF::SHT_PROGBITS) + OS << "progbits"; + + if (EntrySize) { + assert(Flags & ELF::SHF_MERGE); + OS << "," << EntrySize; + } + + if (Flags & ELF::SHF_GROUP) + OS << "," << Group->getName() << ",comdat"; + OS << '\n'; +} + +bool MCSectionELF::UseCodeAlign() const { + return getFlags() & ELF::SHF_EXECINSTR; +} + +bool MCSectionELF::isVirtualSection() const { + return getType() == ELF::SHT_NOBITS; +} + +unsigned MCSectionELF::DetermineEntrySize(SectionKind Kind) { + if (Kind.isMergeable1ByteCString()) return 1; + if (Kind.isMergeable2ByteCString()) return 2; + if (Kind.isMergeable4ByteCString()) return 4; + if (Kind.isMergeableConst4()) return 4; + if (Kind.isMergeableConst8()) return 8; + if (Kind.isMergeableConst16()) return 16; + return 0; +} diff --git a/final/lib/MC/MCSectionMachO.cpp b/final/lib/MC/MCSectionMachO.cpp new file mode 100644 index 00000000000..577e93aed6b --- /dev/null +++ b/final/lib/MC/MCSectionMachO.cpp @@ -0,0 +1,299 @@ +//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +/// SectionTypeDescriptors - These are strings that describe the various section +/// types. This *must* be kept in order with and stay synchronized with the +/// section type list. +static const struct { + const char *AssemblerName, *EnumName; +} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = { + { "regular", "S_REGULAR" }, // 0x00 + { 0, "S_ZEROFILL" }, // 0x01 + { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 + { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 + { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 + { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05 + { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06 + { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07 + { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08 + { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 + { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A + { "coalesced", "S_COALESCED" }, // 0x0B + { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C + { "interposing", "S_INTERPOSING" }, // 0x0D + { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E + { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F + { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 + { "thread_local_regular", "S_THREAD_LOCAL_REGULAR" }, // 0x11 + { "thread_local_zerofill", "S_THREAD_LOCAL_ZEROFILL" }, // 0x12 + { "thread_local_variables", "S_THREAD_LOCAL_VARIABLES" }, // 0x13 + { "thread_local_variable_pointers", + "S_THREAD_LOCAL_VARIABLE_POINTERS" }, // 0x14 + { "thread_local_init_function_pointers", + "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"}, // 0x15 +}; + + +/// SectionAttrDescriptors - This is an array of descriptors for section +/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed +/// by attribute, instead it is searched. The last entry has an AttrFlagEnd +/// AttrFlag value. +static const struct { + unsigned AttrFlag; + const char *AssemblerName, *EnumName; +} SectionAttrDescriptors[] = { +#define ENTRY(ASMNAME, ENUM) \ + { MCSectionMachO::ENUM, ASMNAME, #ENUM }, +ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) +ENTRY("no_toc", S_ATTR_NO_TOC) +ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) +ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) +ENTRY("live_support", S_ATTR_LIVE_SUPPORT) +ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) +ENTRY("debug", S_ATTR_DEBUG) +ENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) +ENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC) +ENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC) +#undef ENTRY + { 0, "none", 0 }, // used if section has no attributes but has a stub size +#define AttrFlagEnd 0xffffffff // non legal value, multiple attribute bits set + { AttrFlagEnd, 0, 0 } +}; + +MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, + unsigned TAA, unsigned reserved2, SectionKind K) + : MCSection(SV_MachO, K), TypeAndAttributes(TAA), Reserved2(reserved2) { + assert(Segment.size() <= 16 && Section.size() <= 16 && + "Segment or section string too long"); + for (unsigned i = 0; i != 16; ++i) { + if (i < Segment.size()) + SegmentName[i] = Segment[i]; + else + SegmentName[i] = 0; + + if (i < Section.size()) + SectionName[i] = Section[i]; + else + SectionName[i] = 0; + } +} + +void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); + + // Get the section type and attributes. + unsigned TAA = getTypeAndAttributes(); + if (TAA == 0) { + OS << '\n'; + return; + } + + unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; + assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && + "Invalid SectionType specified!"); + + if (SectionTypeDescriptors[SectionType].AssemblerName) { + OS << ','; + OS << SectionTypeDescriptors[SectionType].AssemblerName; + } else { + // If we have no name for the attribute, stop here. + OS << '\n'; + return; + } + + // If we don't have any attributes, we're done. + unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; + if (SectionAttrs == 0) { + // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as + // the attribute specifier. + if (Reserved2 != 0) + OS << ",none," << Reserved2; + OS << '\n'; + return; + } + + // Check each attribute to see if we have it. + char Separator = ','; + for (unsigned i = 0; + SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag; + ++i) { + // Check to see if we have this attribute. + if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) + continue; + + // Yep, clear it and print it. + SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; + + OS << Separator; + if (SectionAttrDescriptors[i].AssemblerName) + OS << SectionAttrDescriptors[i].AssemblerName; + else + OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; + Separator = '+'; + } + + assert(SectionAttrs == 0 && "Unknown section attributes!"); + + // If we have a S_SYMBOL_STUBS size specified, print it. + if (Reserved2 != 0) + OS << ',' << Reserved2; + OS << '\n'; +} + +bool MCSectionMachO::UseCodeAlign() const { + return hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); +} + +bool MCSectionMachO::isVirtualSection() const { + return (getType() == MCSectionMachO::S_ZEROFILL || + getType() == MCSectionMachO::S_GB_ZEROFILL || + getType() == MCSectionMachO::S_THREAD_LOCAL_ZEROFILL); +} + +/// StripSpaces - This removes leading and trailing spaces from the StringRef. +static void StripSpaces(StringRef &Str) { + while (!Str.empty() && isspace(Str[0])) + Str = Str.substr(1); + while (!Str.empty() && isspace(Str.back())) + Str = Str.substr(0, Str.size()-1); +} + +/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". +/// This is a string that can appear after a .section directive in a mach-o +/// flavored .s file. If successful, this fills in the specified Out +/// parameters and returns an empty string. When an invalid section +/// specifier is present, this returns a string indicating the problem. +std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. + StringRef &Segment, // Out. + StringRef &Section, // Out. + unsigned &TAA, // Out. + unsigned &StubSize) { // Out. + // Find the first comma. + std::pair Comma = Spec.split(','); + + // If there is no comma, we fail. + if (Comma.second.empty()) + return "mach-o section specifier requires a segment and section " + "separated by a comma"; + + // Capture segment, remove leading and trailing whitespace. + Segment = Comma.first; + StripSpaces(Segment); + + // Verify that the segment is present and not too long. + if (Segment.empty() || Segment.size() > 16) + return "mach-o section specifier requires a segment whose length is " + "between 1 and 16 characters"; + + // Split the section name off from any attributes if present. + Comma = Comma.second.split(','); + + // Capture section, remove leading and trailing whitespace. + Section = Comma.first; + StripSpaces(Section); + + // Verify that the section is present and not too long. + if (Section.empty() || Section.size() > 16) + return "mach-o section specifier requires a section whose length is " + "between 1 and 16 characters"; + + // If there is no comma after the section, we're done. + StubSize = 0; + if (Comma.second.empty()) + return ""; + + // Otherwise, we need to parse the section type and attributes. + Comma = Comma.second.split(','); + + // Get the section type. + StringRef SectionType = Comma.first; + StripSpaces(SectionType); + + // Figure out which section type it is. + unsigned TypeID; + for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID) + if (SectionTypeDescriptors[TypeID].AssemblerName && + SectionType == SectionTypeDescriptors[TypeID].AssemblerName) + break; + + // If we didn't find the section type, reject it. + if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE) + return "mach-o section specifier uses an unknown section type"; + + // Remember the TypeID. + TAA = TypeID; + + // If we have no comma after the section type, there are no attributes. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // Otherwise, we do have some attributes. Split off the size specifier if + // present. + Comma = Comma.second.split(','); + StringRef Attrs = Comma.first; + + // The attribute list is a '+' separated list of attributes. + std::pair Plus = Attrs.split('+'); + + while (1) { + StringRef Attr = Plus.first; + StripSpaces(Attr); + + // Look up the attribute. + for (unsigned i = 0; ; ++i) { + if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd) + return "mach-o section specifier has invalid attribute"; + + if (SectionAttrDescriptors[i].AssemblerName && + Attr == SectionAttrDescriptors[i].AssemblerName) { + TAA |= SectionAttrDescriptors[i].AttrFlag; + break; + } + } + + if (Plus.second.empty()) break; + Plus = Plus.second.split('+'); + }; + + // Okay, we've parsed the section attributes, see if we have a stub size spec. + if (Comma.second.empty()) { + // S_SYMBOL_STUBS always require a symbol stub size specifier. + if (TAA == MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier of type 'symbol_stubs' requires a size " + "specifier"; + return ""; + } + + // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. + if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS) + return "mach-o section specifier cannot have a stub size specified because " + "it does not have type 'symbol_stubs'"; + + // Okay, if we do, it must be a number. + StringRef StubSizeStr = Comma.second; + StripSpaces(StubSizeStr); + + // Convert the stub size from a string to an integer. + if (StubSizeStr.getAsInteger(0, StubSize)) + return "mach-o section specifier has a malformed stub size"; + + return ""; +} diff --git a/final/lib/MC/MCStreamer.cpp b/final/lib/MC/MCStreamer.cpp new file mode 100644 index 00000000000..1bd287b2b5b --- /dev/null +++ b/final/lib/MC/MCStreamer.cpp @@ -0,0 +1,315 @@ +//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include +using namespace llvm; + +MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) { + const MCSection *section = NULL; + SectionStack.push_back(std::make_pair(section, section)); +} + +MCStreamer::~MCStreamer() { +} + +raw_ostream &MCStreamer::GetCommentOS() { + // By default, discard comments. + return nulls(); +} + +void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, + const MCSymbol *Label, int PointerSize) { + // emit the sequence to set the address + EmitIntValue(dwarf::DW_LNS_extended_op, 1); + EmitULEB128IntValue(PointerSize + 1); + EmitIntValue(dwarf::DW_LNE_set_address, 1); + EmitSymbolValue(Label, PointerSize); + + // emit the sequence for the LineDelta (from 1) and a zero address delta. + MCDwarfLineAddr::Emit(this, LineDelta, 0); +} + +/// EmitIntValue - Special case of EmitValue that avoids the client having to +/// pass in a MCExpr for constant integers. +void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, + unsigned AddrSpace) { + assert(Size <= 8 && "Invalid size"); + assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && + "Invalid size"); + char buf[8]; + // FIXME: Endianness assumption. + for (unsigned i = 0; i != Size; ++i) + buf[i] = uint8_t(Value >> (i * 8)); + EmitBytes(StringRef(buf, Size), AddrSpace); +} + +/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the +/// client having to pass in a MCExpr for constant integers. +void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) { + SmallString<32> Tmp; + raw_svector_ostream OSE(Tmp); + MCObjectWriter::EncodeULEB128(Value, OSE); + EmitBytes(OSE.str(), AddrSpace); +} + +/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the +/// client having to pass in a MCExpr for constant integers. +void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) { + SmallString<32> Tmp; + raw_svector_ostream OSE(Tmp); + MCObjectWriter::EncodeSLEB128(Value, OSE); + EmitBytes(OSE.str(), AddrSpace); +} + +void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) { + EmitValue(Value, Size, AddrSpace); + return; + } + MCSymbol *ABS = getContext().CreateTempSymbol(); + EmitAssignment(ABS, Value); + EmitSymbolValue(ABS, Size, AddrSpace); +} + + +void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + EmitValueImpl(Value, Size, false, AddrSpace); +} + +void MCStreamer::EmitPCRelValue(const MCExpr *Value, unsigned Size, + unsigned AddrSpace) { + EmitValueImpl(Value, Size, true, AddrSpace); +} + +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool isPCRel, unsigned AddrSpace) { + EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, isPCRel, + AddrSpace); +} + +void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace) { + EmitSymbolValue(Sym, Size, false, AddrSpace); +} + +void MCStreamer::EmitPCRelSymbolValue(const MCSymbol *Sym, unsigned Size, + unsigned AddrSpace) { + EmitSymbolValue(Sym, Size, true, AddrSpace); +} + +void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { + report_fatal_error("unsupported directive in streamer"); +} + +/// EmitFill - Emit NumBytes bytes worth of the value specified by +/// FillValue. This implements directives such as '.space'. +void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, + unsigned AddrSpace) { + const MCExpr *E = MCConstantExpr::Create(FillValue, getContext()); + for (uint64_t i = 0, e = NumBytes; i != e; ++i) + EmitValue(E, 1, AddrSpace); +} + +bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo, + StringRef Filename) { + return getContext().GetDwarfFile(Filename, FileNo) == 0; +} + +void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, + unsigned Discriminator) { + getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa, + Discriminator); +} + +MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() { + if (FrameInfos.empty()) + return NULL; + return &FrameInfos.back(); +} + +void MCStreamer::EnsureValidFrame() { + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + if (!CurFrame || CurFrame->End) + report_fatal_error("No open frame"); +} + +bool MCStreamer::EmitCFIStartProc() { + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + if (CurFrame && !CurFrame->End) { + report_fatal_error("Starting a frame before finishing the previous one!"); + return true; + } + MCDwarfFrameInfo Frame; + Frame.Begin = getContext().CreateTempSymbol(); + EmitLabel(Frame.Begin); + FrameInfos.push_back(Frame); + return false; +} + +bool MCStreamer::EmitCFIEndProc() { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->End = getContext().CreateTempSymbol(); + EmitLabel(CurFrame->End); + return false; +} + +bool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(MachineLocation::VirtualFP); + MachineLocation Source(Register, -Offset); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(MachineLocation::VirtualFP); + MachineLocation Source(MachineLocation::VirtualFP, -Offset); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(Register); + MachineLocation Source(MachineLocation::VirtualFP); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(Register, Offset); + MachineLocation Source(Register, Offset); + MCCFIInstruction Instruction(Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, + unsigned Encoding) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->Personality = Sym; + CurFrame->PersonalityEncoding = Encoding; + return false; +} + +bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + CurFrame->Lsda = Sym; + CurFrame->LsdaEncoding = Encoding; + return false; +} + +bool MCStreamer::EmitCFIRememberState() { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +bool MCStreamer::EmitCFIRestoreState() { + // FIXME: Error if there is no matching cfi_remember_state. + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label); + CurFrame->Instructions.push_back(Instruction); + return false; +} + +void MCStreamer::EmitFnStart() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitFnEnd() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitCantUnwind() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitHandlerData() { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitPersonality(const MCSymbol *Personality) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitPad(int64_t Offset) { + errs() << "Not implemented yet\n"; + abort(); +} + +void MCStreamer::EmitRegSave(const SmallVectorImpl &RegList, bool) { + errs() << "Not implemented yet\n"; + abort(); +} + +/// EmitRawText - If this file is backed by an assembly streamer, this dumps +/// the specified string in the output .s file. This capability is +/// indicated by the hasRawTextSupport() predicate. +void MCStreamer::EmitRawText(StringRef String) { + errs() << "EmitRawText called on an MCStreamer that doesn't support it, " + " something must not be fully mc'ized\n"; + abort(); +} + +void MCStreamer::EmitRawText(const Twine &T) { + SmallString<128> Str; + T.toVector(Str); + EmitRawText(Str.str()); +} diff --git a/final/lib/MC/MCSymbol.cpp b/final/lib/MC/MCSymbol.cpp new file mode 100644 index 00000000000..1c71f267a4b --- /dev/null +++ b/final/lib/MC/MCSymbol.cpp @@ -0,0 +1,80 @@ +//===- lib/MC/MCSymbol.cpp - MCSymbol implementation ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +// Sentinel value for the absolute pseudo section. +const MCSection *MCSymbol::AbsolutePseudoSection = + reinterpret_cast(1); + +static bool isAcceptableChar(char C) { + if ((C < 'a' || C > 'z') && + (C < 'A' || C > 'Z') && + (C < '0' || C > '9') && + C != '_' && C != '$' && C != '.' && C != '@') + return false; + return true; +} + +/// NameNeedsQuoting - Return true if the identifier \arg Str needs quotes to be +/// syntactically correct. +static bool NameNeedsQuoting(StringRef Str) { + assert(!Str.empty() && "Cannot create an empty MCSymbol"); + + // If any of the characters in the string is an unacceptable character, force + // quotes. + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isAcceptableChar(Str[i])) + return true; + return false; +} + +const MCSymbol &MCSymbol::AliasedSymbol() const { + const MCSymbol *S = this; + while (S->isVariable()) { + const MCExpr *Value = S->getVariableValue(); + if (Value->getKind() != MCExpr::SymbolRef) + return *S; + const MCSymbolRefExpr *Ref = static_cast(Value); + S = &Ref->getSymbol(); + } + return *S; +} + +void MCSymbol::setVariableValue(const MCExpr *Value) { + assert(!IsUsed && "Cannot set a variable that has already been used."); + assert(Value && "Invalid variable value!"); + assert((isUndefined() || (isAbsolute() && isa(Value))) && + "Invalid redefinition!"); + this->Value = Value; + + // Mark the variable as absolute as appropriate. + if (isa(Value)) + setAbsolute(); +} + +void MCSymbol::print(raw_ostream &OS) const { + // The name for this MCSymbol is required to be a valid target name. However, + // some targets support quoting names with funny characters. If the name + // contains a funny character, then print it quoted. + if (!NameNeedsQuoting(getName())) { + OS << getName(); + return; + } + + OS << '"' << getName() << '"'; +} + +void MCSymbol::dump() const { + print(dbgs()); +} diff --git a/final/lib/MC/MCValue.cpp b/final/lib/MC/MCValue.cpp new file mode 100644 index 00000000000..c6ea16ce7b4 --- /dev/null +++ b/final/lib/MC/MCValue.cpp @@ -0,0 +1,36 @@ +//===- lib/MC/MCValue.cpp - MCValue implementation ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const { + if (isAbsolute()) { + OS << getConstant(); + return; + } + + getSymA()->print(OS); + + if (getSymB()) { + OS << " - "; + getSymB()->print(OS); + } + + if (getConstant()) + OS << " + " << getConstant(); +} + +void MCValue::dump() const { + print(dbgs(), 0); +} diff --git a/final/lib/MC/MachObjectWriter.cpp b/final/lib/MC/MachObjectWriter.cpp new file mode 100644 index 00000000000..de5349459d1 --- /dev/null +++ b/final/lib/MC/MachObjectWriter.cpp @@ -0,0 +1,1598 @@ +//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCMachOSymbolFlags.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetAsmBackend.h" + +// FIXME: Gross. +#include "../Target/ARM/ARMFixupKinds.h" +#include "../Target/X86/X86FixupKinds.h" + +#include +using namespace llvm; +using namespace llvm::object; + +// FIXME: this has been copied from (or to) X86AsmBackend.cpp +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_PCRel_1: + case FK_Data_1: return 0; + case FK_PCRel_2: + case FK_Data_2: return 1; + case FK_PCRel_4: + // FIXME: Remove these!!! + case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_movq_load: + case X86::reloc_signed_4byte: + case FK_Data_4: return 2; + case FK_Data_8: return 3; + } +} + +static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { + // Undefined symbols are always extern. + if (SD->Symbol->isUndefined()) + return true; + + // References to weak definitions require external relocation entries; the + // definition may not always be the one in the same object file. + if (SD->getFlags() & SF_WeakDefinition) + return true; + + // Otherwise, we can use an internal relocation. + return false; +} + +namespace { + +class MachObjectWriter : public MCObjectWriter { + /// MachSymbolData - Helper struct for containing some precomputed information + /// on symbols. + struct MachSymbolData { + MCSymbolData *SymbolData; + uint64_t StringIndex; + uint8_t SectionIndex; + + // Support lexicographic sorting. + bool operator<(const MachSymbolData &RHS) const { + return SymbolData->getSymbol().getName() < + RHS.SymbolData->getSymbol().getName(); + } + }; + + /// The target specific Mach-O writer instance. + llvm::OwningPtr TargetObjectWriter; + + /// @name Relocation Data + /// @{ + + llvm::DenseMap > Relocations; + llvm::DenseMap IndirectSymBase; + + /// @} + /// @name Symbol Table Data + /// @{ + + SmallString<256> StringTable; + std::vector LocalSymbolData; + std::vector ExternalSymbolData; + std::vector UndefinedSymbolData; + + /// @} + +private: + /// @name Utility Methods + /// @{ + + bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) { + const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo( + (MCFixupKind) Kind); + + return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel; + } + + /// @} + + SectionAddrMap SectionAddress; + uint64_t getSectionAddress(const MCSectionData* SD) const { + return SectionAddress.lookup(SD); + } + uint64_t getSymbolAddress(const MCSymbolData* SD, + const MCAsmLayout &Layout) const { + return getSectionAddress(SD->getFragment()->getParent()) + + Layout.getSymbolOffset(SD); + } + uint64_t getFragmentAddress(const MCFragment *Fragment, + const MCAsmLayout &Layout) const { + return getSectionAddress(Fragment->getParent()) + + Layout.getFragmentOffset(Fragment); + } + + uint64_t getPaddingSize(const MCSectionData *SD, + const MCAsmLayout &Layout) const { + uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD); + unsigned Next = SD->getLayoutOrder() + 1; + if (Next >= Layout.getSectionOrder().size()) + return 0; + + const MCSectionData &NextSD = *Layout.getSectionOrder()[Next]; + if (NextSD.getSection().isVirtualSection()) + return 0; + return OffsetToAlignment(EndAddr, NextSD.getAlignment()); + } + +public: + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, + bool _IsLittleEndian) + : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { + } + + /// @name Target Writer Proxy Accessors + /// @{ + + bool is64Bit() const { return TargetObjectWriter->is64Bit(); } + bool isARM() const { + uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask; + return CPUType == mach::CTM_ARM; + } + + /// @} + + void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, + bool SubsectionsViaSymbols) { + uint32_t Flags = 0; + + if (SubsectionsViaSymbols) + Flags |= macho::HF_SubsectionsViaSymbols; + + // struct mach_header (28 bytes) or + // struct mach_header_64 (32 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32); + + Write32(TargetObjectWriter->getCPUType()); + Write32(TargetObjectWriter->getCPUSubtype()); + + Write32(macho::HFT_Object); + Write32(NumLoadCommands); + Write32(LoadCommandsSize); + Write32(Flags); + if (is64Bit()) + Write32(0); // reserved + + assert(OS.tell() - Start == + (is64Bit() ? macho::Header64Size : macho::Header32Size)); + } + + /// WriteSegmentLoadCommand - Write a segment load command. + /// + /// \arg NumSections - The number of sections in this segment. + /// \arg SectionDataSize - The total size of the sections. + void WriteSegmentLoadCommand(unsigned NumSections, + uint64_t VMSize, + uint64_t SectionDataStartOffset, + uint64_t SectionDataSize) { + // struct segment_command (56 bytes) or + // struct segment_command_64 (72 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + unsigned SegmentLoadCommandSize = + is64Bit() ? macho::SegmentLoadCommand64Size: + macho::SegmentLoadCommand32Size; + Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment); + Write32(SegmentLoadCommandSize + + NumSections * (is64Bit() ? macho::Section64Size : + macho::Section32Size)); + + WriteBytes("", 16); + if (is64Bit()) { + Write64(0); // vmaddr + Write64(VMSize); // vmsize + Write64(SectionDataStartOffset); // file offset + Write64(SectionDataSize); // file size + } else { + Write32(0); // vmaddr + Write32(VMSize); // vmsize + Write32(SectionDataStartOffset); // file offset + Write32(SectionDataSize); // file size + } + Write32(0x7); // maxprot + Write32(0x7); // initprot + Write32(NumSections); + Write32(0); // flags + + assert(OS.tell() - Start == SegmentLoadCommandSize); + } + + void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCSectionData &SD, uint64_t FileOffset, + uint64_t RelocationsStart, unsigned NumRelocations) { + uint64_t SectionSize = Layout.getSectionAddressSize(&SD); + + // The offset is unused for virtual sections. + if (SD.getSection().isVirtualSection()) { + assert(Layout.getSectionFileSize(&SD) == 0 && "Invalid file size!"); + FileOffset = 0; + } + + // struct section (68 bytes) or + // struct section_64 (80 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + const MCSectionMachO &Section = cast(SD.getSection()); + WriteBytes(Section.getSectionName(), 16); + WriteBytes(Section.getSegmentName(), 16); + if (is64Bit()) { + Write64(getSectionAddress(&SD)); // address + Write64(SectionSize); // size + } else { + Write32(getSectionAddress(&SD)); // address + Write32(SectionSize); // size + } + Write32(FileOffset); + + unsigned Flags = Section.getTypeAndAttributes(); + if (SD.hasInstructions()) + Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS; + + assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!"); + Write32(Log2_32(SD.getAlignment())); + Write32(NumRelocations ? RelocationsStart : 0); + Write32(NumRelocations); + Write32(Flags); + Write32(IndirectSymBase.lookup(&SD)); // reserved1 + Write32(Section.getStubSize()); // reserved2 + if (is64Bit()) + Write32(0); // reserved3 + + assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size : + macho::Section32Size)); + } + + void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, + uint32_t StringTableOffset, + uint32_t StringTableSize) { + // struct symtab_command (24 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(macho::LCT_Symtab); + Write32(macho::SymtabLoadCommandSize); + Write32(SymbolOffset); + Write32(NumSymbols); + Write32(StringTableOffset); + Write32(StringTableSize); + + assert(OS.tell() - Start == macho::SymtabLoadCommandSize); + } + + void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, + uint32_t NumLocalSymbols, + uint32_t FirstExternalSymbol, + uint32_t NumExternalSymbols, + uint32_t FirstUndefinedSymbol, + uint32_t NumUndefinedSymbols, + uint32_t IndirectSymbolOffset, + uint32_t NumIndirectSymbols) { + // struct dysymtab_command (80 bytes) + + uint64_t Start = OS.tell(); + (void) Start; + + Write32(macho::LCT_Dysymtab); + Write32(macho::DysymtabLoadCommandSize); + Write32(FirstLocalSymbol); + Write32(NumLocalSymbols); + Write32(FirstExternalSymbol); + Write32(NumExternalSymbols); + Write32(FirstUndefinedSymbol); + Write32(NumUndefinedSymbols); + Write32(0); // tocoff + Write32(0); // ntoc + Write32(0); // modtaboff + Write32(0); // nmodtab + Write32(0); // extrefsymoff + Write32(0); // nextrefsyms + Write32(IndirectSymbolOffset); + Write32(NumIndirectSymbols); + Write32(0); // extreloff + Write32(0); // nextrel + Write32(0); // locreloff + Write32(0); // nlocrel + + assert(OS.tell() - Start == macho::DysymtabLoadCommandSize); + } + + void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) { + MCSymbolData &Data = *MSD.SymbolData; + const MCSymbol &Symbol = Data.getSymbol(); + uint8_t Type = 0; + uint16_t Flags = Data.getFlags(); + uint32_t Address = 0; + + // Set the N_TYPE bits. See . + // + // FIXME: Are the prebound or indirect fields possible here? + if (Symbol.isUndefined()) + Type = macho::STT_Undefined; + else if (Symbol.isAbsolute()) + Type = macho::STT_Absolute; + else + Type = macho::STT_Section; + + // FIXME: Set STAB bits. + + if (Data.isPrivateExtern()) + Type |= macho::STF_PrivateExtern; + + // Set external bit. + if (Data.isExternal() || Symbol.isUndefined()) + Type |= macho::STF_External; + + // Compute the symbol address. + if (Symbol.isDefined()) { + if (Symbol.isAbsolute()) { + Address = cast(Symbol.getVariableValue())->getValue(); + } else { + Address = getSymbolAddress(&Data, Layout); + } + } else if (Data.isCommon()) { + // Common symbols are encoded with the size in the address + // field, and their alignment in the flags. + Address = Data.getCommonSize(); + + // Common alignment is packed into the 'desc' bits. + if (unsigned Align = Data.getCommonAlignment()) { + unsigned Log2Size = Log2_32(Align); + assert((1U << Log2Size) == Align && "Invalid 'common' alignment!"); + if (Log2Size > 15) + report_fatal_error("invalid 'common' alignment '" + + Twine(Align) + "'"); + // FIXME: Keep this mask with the SymbolFlags enumeration. + Flags = (Flags & 0xF0FF) | (Log2Size << 8); + } + } + + // struct nlist (12 bytes) + + Write32(MSD.StringIndex); + Write8(Type); + Write8(MSD.SectionIndex); + + // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc' + // value. + Write16(Flags); + if (is64Bit()) + Write64(Address); + else + Write32(Address); + } + + // FIXME: We really need to improve the relocation validation. Basically, we + // want to implement a separate computation which evaluates the relocation + // entry as the linker would, and verifies that the resultant fixup value is + // exactly what the encoder wanted. This will catch several classes of + // problems: + // + // - Relocation entry bugs, the two algorithms are unlikely to have the same + // exact bug. + // + // - Relaxation issues, where we forget to relax something. + // + // - Input errors, where something cannot be correctly encoded. 'as' allows + // these through in many cases. + + static bool isFixupKindRIPRel(unsigned Kind) { + return Kind == X86::reloc_riprel_4byte || + Kind == X86::reloc_riprel_4byte_movq_load; + } + void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // See . + uint32_t FixupOffset = + Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + uint32_t FixupAddress = + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + int64_t Value = 0; + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + Value = Target.getConstant(); + + if (IsPCRel) { + // Compensate for the relocation offset, Darwin x86_64 relocations only + // have the addend and appear to have attempted to define it to be the + // actual expression addend without the PCrel bias. However, instructions + // with data following the relocation are not accomodated for (see comment + // below regarding SIGNED{1,2,4}), so it isn't exactly that either. + Value += 1LL << Log2Size; + } + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + Type = macho::RIT_X86_64_Unsigned; + Index = 0; + + // FIXME: I believe this is broken, I don't think the linker can + // understand it. I think it would require a local relocation, but I'm not + // sure if that would work either. The official way to get an absolute + // PCrel relocation is to use an absolute symbol (which we don't support + // yet). + if (IsPCRel) { + IsExtern = 1; + Type = macho::RIT_X86_64_Branch; + } + } else if (Target.getSymB()) { // A - B + constant + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData &A_SD = Asm.getSymbolData(*A); + const MCSymbolData *A_Base = Asm.getAtom(&A_SD); + + const MCSymbol *B = &Target.getSymB()->getSymbol(); + MCSymbolData &B_SD = Asm.getSymbolData(*B); + const MCSymbolData *B_Base = Asm.getAtom(&B_SD); + + // Neither symbol can be modified. + if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None || + Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported relocation of modified symbol"); + + // We don't support PCrel relocations of differences. Darwin 'as' doesn't + // implement most of these correctly. + if (IsPCRel) + report_fatal_error("unsupported pc-relative relocation of difference"); + + // The support for the situation where one or both of the symbols would + // require a local relocation is handled just like if the symbols were + // external. This is certainly used in the case of debug sections where + // the section has only temporary symbols and thus the symbols don't have + // base symbols. This is encoded using the section ordinal and + // non-extern relocation entries. + + // Darwin 'as' doesn't emit correct relocations for this (it ends up with + // a single SIGNED relocation); reject it for now. Except the case where + // both symbols don't have a base, equal but both NULL. + if (A_Base == B_Base && A_Base) + report_fatal_error("unsupported relocation with identical base"); + + Value += getSymbolAddress(&A_SD, Layout) - + (A_Base == NULL ? 0 : getSymbolAddress(A_Base, Layout)); + Value -= getSymbolAddress(&B_SD, Layout) - + (B_Base == NULL ? 0 : getSymbolAddress(B_Base, Layout)); + + if (A_Base) { + Index = A_Base->getIndex(); + IsExtern = 1; + } + else { + Index = A_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Unsigned; + + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Relocations[Fragment->getParent()].push_back(MRE); + + if (B_Base) { + Index = B_Base->getIndex(); + IsExtern = 1; + } + else { + Index = B_SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + } + Type = macho::RIT_X86_64_Subtractor; + } else { + const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); + MCSymbolData &SD = Asm.getSymbolData(*Symbol); + const MCSymbolData *Base = Asm.getAtom(&SD); + + // Relocations inside debug sections always use local relocations when + // possible. This seems to be done because the debugger doesn't fully + // understand x86_64 relocation entries, and expects to find values that + // have already been fixed up. + if (Symbol->isInSection()) { + const MCSectionMachO &Section = static_cast( + Fragment->getParent()->getSection()); + if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG)) + Base = 0; + } + + // x86_64 almost always uses external relocations, except when there is no + // symbol to use as a base address (a local symbol with no preceeding + // non-local symbol). + if (Base) { + Index = Base->getIndex(); + IsExtern = 1; + + // Add the local offset, if needed. + if (Base != &SD) + Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base); + } else if (Symbol->isInSection()) { + // The index is the section ordinal (1-based). + Index = SD.getFragment()->getParent()->getOrdinal() + 1; + IsExtern = 0; + Value += getSymbolAddress(&SD, Layout); + + if (IsPCRel) + Value -= FixupAddress + (1 << Log2Size); + } else if (Symbol->isVariable()) { + const MCExpr *Value = Symbol->getVariableValue(); + int64_t Res; + bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress); + if (isAbs) { + FixedValue = Res; + return; + } else { + report_fatal_error("unsupported relocation of variable '" + + Symbol->getName() + "'"); + } + } else { + report_fatal_error("unsupported relocation of undefined symbol '" + + Symbol->getName() + "'"); + } + + MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); + if (IsPCRel) { + if (IsRIPRel) { + if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // x86_64 distinguishes movq foo@GOTPCREL so that the linker can + // rewrite the movq to an leaq at link time if the symbol ends up in + // the same linkage unit. + if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) + Type = macho::RIT_X86_64_GOTLoad; + else + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + Type = macho::RIT_X86_64_TLV; + } else if (Modifier != MCSymbolRefExpr::VK_None) { + report_fatal_error("unsupported symbol modifier in relocation"); + } else { + Type = macho::RIT_X86_64_Signed; + + // The Darwin x86_64 relocation format has a problem where it cannot + // encode an address (L + ) which is outside the atom + // containing L. Generally, this shouldn't occur but it does + // happen when we have a RIPrel instruction with data following the + // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel + // adjustment Darwin x86_64 uses, the offset is still negative and + // the linker has no way to recognize this. + // + // To work around this, Darwin uses several special relocation types + // to indicate the offsets. However, the specification or + // implementation of these seems to also be incomplete; they should + // adjust the addend as well based on the actual encoded instruction + // (the additional bias), but instead appear to just look at the + // final offset. + switch (-(Target.getConstant() + (1LL << Log2Size))) { + case 1: Type = macho::RIT_X86_64_Signed1; break; + case 2: Type = macho::RIT_X86_64_Signed2; break; + case 4: Type = macho::RIT_X86_64_Signed4; break; + } + } + } else { + if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in branch " + "relocation"); + + Type = macho::RIT_X86_64_Branch; + } + } else { + if (Modifier == MCSymbolRefExpr::VK_GOT) { + Type = macho::RIT_X86_64_GOT; + } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { + // GOTPCREL is allowed as a modifier on non-PCrel instructions, in + // which case all we do is set the PCrel bit in the relocation entry; + // this is used with exception handling, for example. The source is + // required to include any necessary offset directly. + Type = macho::RIT_X86_64_GOT; + IsPCRel = 1; + } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { + report_fatal_error("TLVP symbol modifier should have been rip-rel"); + } else if (Modifier != MCSymbolRefExpr::VK_None) + report_fatal_error("unsupported symbol modifier in relocation"); + else + Type = macho::RIT_X86_64_Unsigned; + } + } + + // x86_64 always writes custom values into the fixups. + FixedValue = Value; + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + // + // Note that there is no longer any semantic difference between these two + // relocation types from the linkers point of view, this is done solely + // for pedantic compatibility with 'as'. + Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference : + (unsigned)macho::RIT_Generic_LocalDifference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Relocations[Fragment->getParent()].push_back(MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordARMScatteredRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_Vanilla; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_Difference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_Difference || + Type == macho::RIT_Generic_LocalDifference) { + macho::RelocationEntry MRE; + MRE.Word0 = ((0 << 0) | + (macho::RIT_Pair << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Relocations[Fragment->getParent()].push_back(MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (Log2Size << 28) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordARMMovwMovtRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Type = macho::RIT_ARM_Half; + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = getSymbolAddress(A_SD, Layout); + uint32_t Value2 = 0; + uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // Select the appropriate difference relocation type. + Type = macho::RIT_ARM_HalfDifference; + Value2 = getSymbolAddress(B_SD, Layout); + FixedValue -= getSectionAddress(B_SD->getFragment()->getParent()); + } + + // Relocations are written out in reverse order, so the PAIR comes first. + // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: + // + // For these two r_type relocations they always have a pair following them + // and the r_length bits are used differently. The encoding of the + // r_length is as follows: + // low bit of r_length: + // 0 - :lower16: for movw instructions + // 1 - :upper16: for movt instructions + // high bit of r_length: + // 0 - arm instructions + // 1 - thumb instructions + // the other half of the relocated expression is in the following pair + // relocation entry in the the low 16 bits of r_address field. + unsigned ThumbBit = 0; + unsigned MovtBit = 0; + switch (Fixup.getKind()) { + default: break; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + MovtBit = 1; + break; + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + MovtBit = 1; + // Fallthrough + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + ThumbBit = 1; + break; + } + + + if (Type == macho::RIT_ARM_HalfDifference) { + uint32_t OtherHalf = MovtBit + ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); + + macho::RelocationEntry MRE; + MRE.Word0 = ((OtherHalf << 0) | + (macho::RIT_Pair << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; + Relocations[Fragment->getParent()].push_back(MRE); + } + + macho::RelocationEntry MRE; + MRE.Word0 = ((FixupOffset << 0) | + (Type << 24) | + (MovtBit << 28) | + (ThumbBit << 29) | + (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value; + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordTLVPRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && + !is64Bit() && + "Should only be called with a 32-bit TLVP relocation!"); + + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned IsPCRel = 0; + + // Get the symbol data. + MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + unsigned Index = SD_A->getIndex(); + + // We're only going to have a second symbol in pic mode and it'll be a + // subtraction from the picbase. For 32-bit pic the addend is the difference + // between the picbase and the next address. For 32-bit static the addend + // is zero. + if (Target.getSymB()) { + // If this is a subtraction then we're pcrel. + uint32_t FixupAddress = + getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); + MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol()); + IsPCRel = 1; + FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) + + Target.getConstant()); + FixedValue += 1ULL << Log2Size; + } else { + FixedValue = 0; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = Value; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (1 << 27) | // Extern + (macho::RIT_Generic_TLV << 28)); // Type + Relocations[Fragment->getParent()].push_back(MRE); + } + + static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, + unsigned &Log2Size) { + RelocType = unsigned(macho::RIT_Vanilla); + Log2Size = ~0U; + + switch (Kind) { + default: + return false; + + case FK_Data_1: + Log2Size = llvm::Log2_32(1); + return true; + case FK_Data_2: + Log2Size = llvm::Log2_32(2); + return true; + case FK_Data_4: + Log2Size = llvm::Log2_32(4); + return true; + case FK_Data_8: + Log2Size = llvm::Log2_32(8); + return true; + + // Handle 24-bit branch kinds. + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + RelocType = unsigned(macho::RIT_ARM_Branch24Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + // Handle Thumb branches. + case ARM::fixup_arm_thumb_br: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + Log2Size = llvm::Log2_32(2); + return true; + + case ARM::fixup_arm_thumb_bl: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch32Bit); + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_thumb_blx: + RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + RelocType = unsigned(macho::RIT_ARM_HalfDifference); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: + RelocType = unsigned(macho::RIT_ARM_Half); + // Report as 'long', even though that is not quite accurate. + Log2Size = llvm::Log2_32(4); + return true; + } + } + void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) { + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size; + unsigned RelocType = macho::RIT_Vanilla; + if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) { + report_fatal_error("unknown ARM fixup kind!"); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need + // a scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB()) { + if (RelocType == macho::RIT_ARM_Half || + RelocType == macho::RIT_ARM_HalfDifference) + return RecordARMMovwMovtRelocation(Asm, Layout, Fragment, Fixup, + Target, FixedValue); + return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + } + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // FIXME: For other platforms, we need to use scattered relocations for + // internal relocations with offsets. If this is an internal relocation + // with an offset, it also needs a scattered relocation entry. + // + // Is this right for ARM? + uint32_t Offset = Target.getConstant(); + if (IsPCRel && RelocType == macho::RIT_Vanilla) + Offset += 1 << Log2Size; + if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) + return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, Target, + Log2Size, FixedValue); + + // See . + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // FIXME! + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + } else if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } + + report_fatal_error("unsupported relocation of variable '" + + SD->getSymbol().getName() + "'"); + } else { + // Check whether we need an external or internal relocation. + if (doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + Index = SD->getFragment()->getParent()->getOrdinal() + 1; + FixedValue += getSectionAddress(SD->getFragment()->getParent()); + } + if (IsPCRel) + FixedValue -= getSectionAddress(Fragment->getParent()); + + // The type is determined by the fixup kind. + Type = RelocType; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Relocations[Fragment->getParent()].push_back(MRE); + } + + void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue) { + // FIXME: These needs to be factored into the target Mach-O writer. + if (isARM()) { + RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); + return; + } + if (is64Bit()) { + RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); + return; + } + + unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind()); + unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); + + // If this is a 32-bit TLVP reloc it's handled a bit differently. + if (Target.getSymA() && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { + RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue); + return; + } + + // If this is a difference or a defined symbol plus an offset, then we need + // a scattered relocation entry. + // Differences always require scattered relocations. + if (Target.getSymB()) + return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // If this is an internal relocation with an offset, it also needs a + // scattered relocation entry. + uint32_t Offset = Target.getConstant(); + if (IsPCRel) + Offset += 1 << Log2Size; + if (Offset && SD && !doesSymbolRequireExternRelocation(SD)) + return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup, + Target, Log2Size, FixedValue); + + // See . + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = 0; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + // + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. + Type = macho::RIT_Vanilla; + } else if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, SectionAddress)) { + FixedValue = Res; + return; + } + + report_fatal_error("unsupported relocation of variable '" + + SD->getSymbol().getName() + "'"); + } else { + // Check whether we need an external or internal relocation. + if (doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + Index = SD->getFragment()->getParent()->getOrdinal() + 1; + FixedValue += getSectionAddress(SD->getFragment()->getParent()); + } + if (IsPCRel) + FixedValue -= getSectionAddress(Fragment->getParent()); + + Type = macho::RIT_Vanilla; + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + MRE.Word0 = FixupOffset; + MRE.Word1 = ((Index << 0) | + (IsPCRel << 24) | + (Log2Size << 25) | + (IsExtern << 27) | + (Type << 28)); + Relocations[Fragment->getParent()].push_back(MRE); + } + + void BindIndirectSymbols(MCAssembler &Asm) { + // This is the point where 'as' creates actual symbols for indirect symbols + // (in the following two passes). It would be easier for us to do this + // sooner when we see the attribute, but that makes getting the order in the + // symbol table much more complicated than it is worth. + // + // FIXME: Revisit this when the dust settles. + + // Bind non lazy symbol pointers first. + unsigned IndirectIndex = 0; + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { + const MCSectionMachO &Section = + cast(it->SectionData->getSection()); + + if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) + continue; + + // Initialize the section indirect symbol base, if necessary. + if (!IndirectSymBase.count(it->SectionData)) + IndirectSymBase[it->SectionData] = IndirectIndex; + + Asm.getOrCreateSymbolData(*it->Symbol); + } + + // Then lazy symbol pointers and symbol stubs. + IndirectIndex = 0; + for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) { + const MCSectionMachO &Section = + cast(it->SectionData->getSection()); + + if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS && + Section.getType() != MCSectionMachO::S_SYMBOL_STUBS) + continue; + + // Initialize the section indirect symbol base, if necessary. + if (!IndirectSymBase.count(it->SectionData)) + IndirectSymBase[it->SectionData] = IndirectIndex; + + // Set the symbol type to undefined lazy, but only on construction. + // + // FIXME: Do not hardcode. + bool Created; + MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created); + if (Created) + Entry.setFlags(Entry.getFlags() | 0x0001); + } + } + + /// ComputeSymbolTable - Compute the symbol table data + /// + /// \param StringTable [out] - The string table data. + /// \param StringIndexMap [out] - Map from symbol names to offsets in the + /// string table. + void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + std::vector &LocalSymbolData, + std::vector &ExternalSymbolData, + std::vector &UndefinedSymbolData) { + // Build section lookup table. + DenseMap SectionIndexMap; + unsigned Index = 1; + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it, ++Index) + SectionIndexMap[&it->getSection()] = Index; + assert(Index <= 256 && "Too many sections!"); + + // Index 0 is always the empty string. + StringMap StringIndexMap; + StringTable += '\x00'; + + // Build the symbol arrays and the string table, but only for non-local + // symbols. + // + // The particular order that we collect the symbols and create the string + // table, then sort the symbols is chosen to match 'as'. Even though it + // doesn't matter for correctness, this is important for letting us diff .o + // files. + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Symbol = it->getSymbol(); + + // Ignore non-linker visible symbols. + if (!Asm.isSymbolLinkerVisible(it->getSymbol())) + continue; + + if (!it->isExternal() && !Symbol.isUndefined()) + continue; + + uint64_t &Entry = StringIndexMap[Symbol.getName()]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Symbol.getName(); + StringTable += '\x00'; + } + + MachSymbolData MSD; + MSD.SymbolData = it; + MSD.StringIndex = Entry; + + if (Symbol.isUndefined()) { + MSD.SectionIndex = 0; + UndefinedSymbolData.push_back(MSD); + } else if (Symbol.isAbsolute()) { + MSD.SectionIndex = 0; + ExternalSymbolData.push_back(MSD); + } else { + MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); + assert(MSD.SectionIndex && "Invalid section index!"); + ExternalSymbolData.push_back(MSD); + } + } + + // Now add the data for local symbols. + for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), + ie = Asm.symbol_end(); it != ie; ++it) { + const MCSymbol &Symbol = it->getSymbol(); + + // Ignore non-linker visible symbols. + if (!Asm.isSymbolLinkerVisible(it->getSymbol())) + continue; + + if (it->isExternal() || Symbol.isUndefined()) + continue; + + uint64_t &Entry = StringIndexMap[Symbol.getName()]; + if (!Entry) { + Entry = StringTable.size(); + StringTable += Symbol.getName(); + StringTable += '\x00'; + } + + MachSymbolData MSD; + MSD.SymbolData = it; + MSD.StringIndex = Entry; + + if (Symbol.isAbsolute()) { + MSD.SectionIndex = 0; + LocalSymbolData.push_back(MSD); + } else { + MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); + assert(MSD.SectionIndex && "Invalid section index!"); + LocalSymbolData.push_back(MSD); + } + } + + // External and undefined symbols are required to be in lexicographic order. + std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); + std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); + + // Set the symbol indices. + Index = 0; + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) + LocalSymbolData[i].SymbolData->setIndex(Index++); + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) + ExternalSymbolData[i].SymbolData->setIndex(Index++); + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) + UndefinedSymbolData[i].SymbolData->setIndex(Index++); + + // The string table is padded to a multiple of 4. + while (StringTable.size() % 4) + StringTable += '\x00'; + } + + void computeSectionAddresses(const MCAssembler &Asm, + const MCAsmLayout &Layout) { + uint64_t StartAddress = 0; + const SmallVectorImpl &Order = Layout.getSectionOrder(); + for (int i = 0, n = Order.size(); i != n ; ++i) { + const MCSectionData *SD = Order[i]; + StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment()); + SectionAddress[SD] = StartAddress; + StartAddress += Layout.getSectionAddressSize(SD); + // Explicitly pad the section to match the alignment requirements of the + // following one. This is for 'gas' compatibility, it shouldn't + /// strictly be necessary. + StartAddress += getPaddingSize(SD, Layout); + } + } + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { + computeSectionAddresses(Asm, Layout); + + // Create symbol data for any indirect symbols. + BindIndirectSymbols(Asm); + + // Compute symbol table information and bind symbol indices. + ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData, + UndefinedSymbolData); + } + + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const { + if (InSet) + return true; + + // The effective address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) == 0. + const MCSymbolData *A_Base = 0, *B_Base = 0; + + const MCSymbol &SA = DataA.getSymbol().AliasedSymbol(); + const MCSection &SecA = SA.getSection(); + const MCSection &SecB = FB.getParent()->getSection(); + + if (IsPCRel) { + // The simple (Darwin, except on x86_64) way of dealing with this was to + // assume that any reference to a temporary symbol *must* be a temporary + // symbol in the same atom, unless the sections differ. Therefore, any + // PCrel relocation to a temporary symbol (in the same section) is fully + // resolved. This also works in conjunction with absolutized .set, which + // requires the compiler to use .set to absolutize the differences between + // symbols which the compiler knows to be assembly time constants, so we + // don't need to worry about considering symbol differences fully + // resolved. + + if (!Asm.getBackend().hasReliableSymbolDifference()) { + if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB) + return false; + return true; + } + } else { + if (!TargetObjectWriter->useAggressiveSymbolFolding()) + return false; + } + + const MCFragment &FA = *Asm.getSymbolData(SA).getFragment(); + + A_Base = FA.getAtom(); + if (!A_Base) + return false; + + B_Base = FB.getAtom(); + if (!B_Base) + return false; + + // If the atoms are the same, they are guaranteed to have the same address. + if (A_Base == B_Base) + return true; + + // Otherwise, we can't prove this is fully resolved. + return false; + } + + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { + unsigned NumSections = Asm.size(); + + // The section data starts after the header, the segment load command (and + // section headers) and the symbol table. + unsigned NumLoadCommands = 1; + uint64_t LoadCommandsSize = is64Bit() ? + macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : + macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; + + // Add the symbol table load command sizes, if used. + unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + + UndefinedSymbolData.size(); + if (NumSymbols) { + NumLoadCommands += 2; + LoadCommandsSize += (macho::SymtabLoadCommandSize + + macho::DysymtabLoadCommandSize); + } + + // Compute the total size of the section data, as well as its file size and + // vm size. + uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : + macho::Header32Size) + LoadCommandsSize; + uint64_t SectionDataSize = 0; + uint64_t SectionDataFileSize = 0; + uint64_t VMSize = 0; + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + const MCSectionData &SD = *it; + uint64_t Address = getSectionAddress(&SD); + uint64_t Size = Layout.getSectionAddressSize(&SD); + uint64_t FileSize = Layout.getSectionFileSize(&SD); + FileSize += getPaddingSize(&SD, Layout); + + VMSize = std::max(VMSize, Address + Size); + + if (SD.getSection().isVirtualSection()) + continue; + + SectionDataSize = std::max(SectionDataSize, Address + Size); + SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize); + } + + // The section data is padded to 4 bytes. + // + // FIXME: Is this machine dependent? + unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); + SectionDataFileSize += SectionDataPadding; + + // Write the prolog, starting with the header and load command... + WriteHeader(NumLoadCommands, LoadCommandsSize, + Asm.getSubsectionsViaSymbols()); + WriteSegmentLoadCommand(NumSections, VMSize, + SectionDataStart, SectionDataSize); + + // ... and then the section headers. + uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + std::vector &Relocs = Relocations[it]; + unsigned NumRelocs = Relocs.size(); + uint64_t SectionStart = SectionDataStart + getSectionAddress(it); + WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); + RelocTableEnd += NumRelocs * macho::RelocationInfoSize; + } + + // Write the symbol table load command, if used. + if (NumSymbols) { + unsigned FirstLocalSymbol = 0; + unsigned NumLocalSymbols = LocalSymbolData.size(); + unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; + unsigned NumExternalSymbols = ExternalSymbolData.size(); + unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; + unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); + unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); + unsigned NumSymTabSymbols = + NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; + uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; + uint64_t IndirectSymbolOffset = 0; + + // If used, the indirect symbols are written after the section data. + if (NumIndirectSymbols) + IndirectSymbolOffset = RelocTableEnd; + + // The symbol table is written after the indirect symbol data. + uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize; + + // The string table is written after symbol table. + uint64_t StringTableOffset = + SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : + macho::Nlist32Size); + WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, + StringTableOffset, StringTable.size()); + + WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, + FirstExternalSymbol, NumExternalSymbols, + FirstUndefinedSymbol, NumUndefinedSymbols, + IndirectSymbolOffset, NumIndirectSymbols); + } + + // Write the actual section data. + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + Asm.WriteSectionData(it, Layout); + + uint64_t Pad = getPaddingSize(it, Layout); + for (unsigned int i = 0; i < Pad; ++i) + Write8(0); + } + + // Write the extra padding. + WriteZeros(SectionDataPadding); + + // Write the relocation entries. + for (MCAssembler::const_iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { + // Write the section relocation entries, in reverse order to match 'as' + // (approximately, the exact algorithm is more complicated than this). + std::vector &Relocs = Relocations[it]; + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + Write32(Relocs[e - i - 1].Word0); + Write32(Relocs[e - i - 1].Word1); + } + } + + // Write the symbol table data, if used. + if (NumSymbols) { + // Write the indirect symbol entries. + for (MCAssembler::const_indirect_symbol_iterator + it = Asm.indirect_symbol_begin(), + ie = Asm.indirect_symbol_end(); it != ie; ++it) { + // Indirect symbols in the non lazy symbol pointer section have some + // special handling. + const MCSectionMachO &Section = + static_cast(it->SectionData->getSection()); + if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { + // If this symbol is defined and internal, mark it as such. + if (it->Symbol->isDefined() && + !Asm.getSymbolData(*it->Symbol).isExternal()) { + uint32_t Flags = macho::ISF_Local; + if (it->Symbol->isAbsolute()) + Flags |= macho::ISF_Absolute; + Write32(Flags); + continue; + } + } + + Write32(Asm.getSymbolData(*it->Symbol).getIndex()); + } + + // FIXME: Check that offsets match computed ones. + + // Write the symbol table entries. + for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) + WriteNlist(LocalSymbolData[i], Layout); + for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) + WriteNlist(ExternalSymbolData[i], Layout); + for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) + WriteNlist(UndefinedSymbolData[i], Layout); + + // Write the string table. + OS << StringTable.str(); + } + } +}; + +} + +MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW, + raw_ostream &OS, + bool IsLittleEndian) { + return new MachObjectWriter(MOTW, OS, IsLittleEndian); +} diff --git a/final/lib/MC/Makefile b/final/lib/MC/Makefile new file mode 100644 index 00000000000..bf8b7c0e783 --- /dev/null +++ b/final/lib/MC/Makefile @@ -0,0 +1,16 @@ +##===- lib/MC/Makefile -------------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMMC +BUILD_ARCHIVE := 1 +PARALLEL_DIRS := MCParser MCDisassembler + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/MC/TargetAsmBackend.cpp b/final/lib/MC/TargetAsmBackend.cpp new file mode 100644 index 00000000000..19275574253 --- /dev/null +++ b/final/lib/MC/TargetAsmBackend.cpp @@ -0,0 +1,37 @@ +//===-- TargetAsmBackend.cpp - Target Assembly Backend ---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +TargetAsmBackend::TargetAsmBackend() + : HasReliableSymbolDifference(false) +{ +} + +TargetAsmBackend::~TargetAsmBackend() { +} + +const MCFixupKindInfo & +TargetAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + static const MCFixupKindInfo Builtins[] = { + { "FK_Data_1", 0, 8, 0 }, + { "FK_Data_2", 0, 16, 0 }, + { "FK_Data_4", 0, 32, 0 }, + { "FK_Data_8", 0, 64, 0 }, + { "FK_PCRel_1", 0, 8, MCFixupKindInfo::FKF_IsPCRel }, + { "FK_PCRel_2", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, + { "FK_PCRel_4", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, + { "FK_PCRel_8", 0, 64, MCFixupKindInfo::FKF_IsPCRel } + }; + + assert((size_t)Kind <= sizeof(Builtins) / sizeof(Builtins[0]) && + "Unknown fixup kind"); + return Builtins[Kind]; +} diff --git a/final/lib/MC/WinCOFFObjectWriter.cpp b/final/lib/MC/WinCOFFObjectWriter.cpp new file mode 100644 index 00000000000..6ca5d37fc32 --- /dev/null +++ b/final/lib/MC/WinCOFFObjectWriter.cpp @@ -0,0 +1,877 @@ +//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an implementation of a Win32 COFF object file writer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "WinCOFFObjectWriter" + +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCSectionCOFF.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" + +#include "llvm/Support/COFF.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" + +#include "llvm/Support/TimeValue.h" + +#include "../Target/X86/X86FixupKinds.h" + +#include + +using namespace llvm; + +namespace { +typedef llvm::SmallString name; + +enum AuxiliaryType { + ATFunctionDefinition, + ATbfAndefSymbol, + ATWeakExternal, + ATFile, + ATSectionDefinition +}; + +struct AuxSymbol { + AuxiliaryType AuxType; + COFF::Auxiliary Aux; +}; + +class COFFSymbol; +class COFFSection; + +class COFFSymbol { +public: + COFF::symbol Data; + + typedef llvm::SmallVector AuxiliarySymbols; + + name Name; + int Index; + AuxiliarySymbols Aux; + COFFSymbol *Other; + COFFSection *Section; + int Relocations; + + MCSymbolData const *MCData; + + COFFSymbol(llvm::StringRef name); + size_t size() const; + void set_name_offset(uint32_t Offset); + + bool should_keep() const; +}; + +// This class contains staging data for a COFF relocation entry. +struct COFFRelocation { + COFF::relocation Data; + COFFSymbol *Symb; + + COFFRelocation() : Symb(NULL) {} + static size_t size() { return COFF::RelocationSize; } +}; + +typedef std::vector relocations; + +class COFFSection { +public: + COFF::section Header; + + std::string Name; + int Number; + MCSectionData const *MCData; + COFFSymbol *Symbol; + relocations Relocations; + + COFFSection(llvm::StringRef name); + static size_t size(); +}; + +// This class holds the COFF string table. +class StringTable { + typedef llvm::StringMap map; + map Map; + + void update_length(); +public: + std::vector Data; + + StringTable(); + size_t size() const; + size_t insert(llvm::StringRef String); +}; + +class WinCOFFObjectWriter : public MCObjectWriter { +public: + + typedef std::vector symbols; + typedef std::vector sections; + + typedef DenseMap symbol_map; + typedef DenseMap section_map; + + // Root level file contents. + bool Is64Bit; + COFF::header Header; + sections Sections; + symbols Symbols; + StringTable Strings; + + // Maps used during object file creation. + section_map SectionMap; + symbol_map SymbolMap; + + WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); + ~WinCOFFObjectWriter(); + + COFFSymbol *createSymbol(StringRef Name); + COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); + COFFSection *createSection(StringRef Name); + + template + object_t *createCOFFEntity(llvm::StringRef Name, list_t &List); + + void DefineSection(MCSectionData const &SectionData); + void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler); + + void MakeSymbolReal(COFFSymbol &S, size_t Index); + void MakeSectionReal(COFFSection &S, size_t Number); + + bool ExportSection(COFFSection const *S); + bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm); + + bool IsPhysicalSection(COFFSection *S); + + // Entity writing methods. + + void WriteFileHeader(const COFF::header &Header); + void WriteSymbol(const COFFSymbol *S); + void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); + void WriteSectionHeader(const COFF::section &S); + void WriteRelocation(const COFF::relocation &R); + + // MCObjectWriter interface implementation. + + void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); + + void RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue); + + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); +}; +} + +static inline void write_uint32_le(void *Data, uint32_t const &Value) { + uint8_t *Ptr = reinterpret_cast(Data); + Ptr[0] = (Value & 0x000000FF) >> 0; + Ptr[1] = (Value & 0x0000FF00) >> 8; + Ptr[2] = (Value & 0x00FF0000) >> 16; + Ptr[3] = (Value & 0xFF000000) >> 24; +} + +static inline void write_uint16_le(void *Data, uint16_t const &Value) { + uint8_t *Ptr = reinterpret_cast(Data); + Ptr[0] = (Value & 0x00FF) >> 0; + Ptr[1] = (Value & 0xFF00) >> 8; +} + +static inline void write_uint8_le(void *Data, uint8_t const &Value) { + uint8_t *Ptr = reinterpret_cast(Data); + Ptr[0] = (Value & 0xFF) >> 0; +} + +//------------------------------------------------------------------------------ +// Symbol class implementation + +COFFSymbol::COFFSymbol(llvm::StringRef name) + : Name(name.begin(), name.end()) + , Other(NULL) + , Section(NULL) + , Relocations(0) + , MCData(NULL) { + memset(&Data, 0, sizeof(Data)); +} + +size_t COFFSymbol::size() const { + return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize); +} + +// In the case that the name does not fit within 8 bytes, the offset +// into the string table is stored in the last 4 bytes instead, leaving +// the first 4 bytes as 0. +void COFFSymbol::set_name_offset(uint32_t Offset) { + write_uint32_le(Data.Name + 0, 0); + write_uint32_le(Data.Name + 4, Offset); +} + +/// logic to decide if the symbol should be reported in the symbol table +bool COFFSymbol::should_keep() const { + // no section means its external, keep it + if (Section == NULL) + return true; + + // if it has relocations pointing at it, keep it + if (Relocations > 0) { + assert(Section->Number != -1 && "Sections with relocations must be real!"); + return true; + } + + // if the section its in is being droped, drop it + if (Section->Number == -1) + return false; + + // if it is the section symbol, keep it + if (Section->Symbol == this) + return true; + + // if its temporary, drop it + if (MCData && MCData->getSymbol().isTemporary()) + return false; + + // otherwise, keep it + return true; +} + +//------------------------------------------------------------------------------ +// Section class implementation + +COFFSection::COFFSection(llvm::StringRef name) + : Name(name) + , MCData(NULL) + , Symbol(NULL) { + memset(&Header, 0, sizeof(Header)); +} + +size_t COFFSection::size() { + return COFF::SectionSize; +} + +//------------------------------------------------------------------------------ +// StringTable class implementation + +/// Write the length of the string table into Data. +/// The length of the string table includes uint32 length header. +void StringTable::update_length() { + write_uint32_le(&Data.front(), Data.size()); +} + +StringTable::StringTable() { + // The string table data begins with the length of the entire string table + // including the length header. Allocate space for this header. + Data.resize(4); +} + +size_t StringTable::size() const { + return Data.size(); +} + +/// Add String to the table iff it is not already there. +/// @returns the index into the string table where the string is now located. +size_t StringTable::insert(llvm::StringRef String) { + map::iterator i = Map.find(String); + + if (i != Map.end()) + return i->second; + + size_t Offset = Data.size(); + + // Insert string data into string table. + Data.insert(Data.end(), String.begin(), String.end()); + Data.push_back('\0'); + + // Put a reference to it in the map. + Map[String] = Offset; + + // Update the internal length field. + update_length(); + + return Offset; +} + +//------------------------------------------------------------------------------ +// WinCOFFObjectWriter class implementation + +WinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit) + : MCObjectWriter(OS, true) + , Is64Bit(is64Bit) { + memset(&Header, 0, sizeof(Header)); + + Is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64 + : Header.Machine = COFF::IMAGE_FILE_MACHINE_I386; +} + +WinCOFFObjectWriter::~WinCOFFObjectWriter() { + for (symbols::iterator I = Symbols.begin(), E = Symbols.end(); I != E; ++I) + delete *I; + for (sections::iterator I = Sections.begin(), E = Sections.end(); I != E; ++I) + delete *I; +} + +COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { + return createCOFFEntity(Name, Symbols); +} + +COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){ + symbol_map::iterator i = SymbolMap.find(Symbol); + if (i != SymbolMap.end()) + return i->second; + COFFSymbol *RetSymbol + = createCOFFEntity(Symbol->getName(), Symbols); + SymbolMap[Symbol] = RetSymbol; + return RetSymbol; +} + +COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) { + return createCOFFEntity(Name, Sections); +} + +/// A template used to lookup or create a symbol/section, and initialize it if +/// needed. +template +object_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name, + list_t &List) { + object_t *Object = new object_t(Name); + + List.push_back(Object); + + return Object; +} + +/// This function takes a section data object from the assembler +/// and creates the associated COFF section staging object. +void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { + assert(SectionData.getSection().getVariant() == MCSection::SV_COFF + && "Got non COFF section in the COFF backend!"); + // FIXME: Not sure how to verify this (at least in a debug build). + MCSectionCOFF const &Sec = + static_cast(SectionData.getSection()); + + COFFSection *coff_section = createSection(Sec.getSectionName()); + COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName()); + + coff_section->Symbol = coff_symbol; + coff_symbol->Section = coff_section; + coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC; + + // In this case the auxiliary symbol is a Section Definition. + coff_symbol->Aux.resize(1); + memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); + coff_symbol->Aux[0].AuxType = ATSectionDefinition; + coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection(); + + coff_section->Header.Characteristics = Sec.getCharacteristics(); + + uint32_t &Characteristics = coff_section->Header.Characteristics; + switch (SectionData.getAlignment()) { + case 1: Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES; break; + case 2: Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES; break; + case 4: Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES; break; + case 8: Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES; break; + case 16: Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES; break; + case 32: Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES; break; + case 64: Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES; break; + case 128: Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES; break; + case 256: Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES; break; + case 512: Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES; break; + case 1024: Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES; break; + case 2048: Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES; break; + case 4096: Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES; break; + case 8192: Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES; break; + default: + llvm_unreachable("unsupported section alignment"); + } + + // Bind internal COFF section to MC section. + coff_section->MCData = &SectionData; + SectionMap[&SectionData.getSection()] = coff_section; +} + +/// This function takes a section data object from the assembler +/// and creates the associated COFF symbol staging object. +void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, + MCAssembler &Assembler) { + COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&SymbolData.getSymbol()); + + coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; + coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; + + if (SymbolData.getFlags() & COFF::SF_WeakExternal) { + coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + + if (SymbolData.getSymbol().isVariable()) { + coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); + + // FIXME: This assert message isn't very good. + assert(Value->getKind() == MCExpr::SymbolRef && + "Value must be a SymbolRef!"); + + const MCSymbolRefExpr *SymbolRef = + static_cast(Value); + coff_symbol->Other = GetOrCreateCOFFSymbol(&SymbolRef->getSymbol()); + } else { + std::string WeakName = std::string(".weak.") + + SymbolData.getSymbol().getName().str() + + ".default"; + COFFSymbol *WeakDefault = createSymbol(WeakName); + WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; + WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; + WeakDefault->Data.Type = 0; + WeakDefault->Data.Value = 0; + coff_symbol->Other = WeakDefault; + } + + // Setup the Weak External auxiliary symbol. + coff_symbol->Aux.resize(1); + memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); + coff_symbol->Aux[0].AuxType = ATWeakExternal; + coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; + coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = + COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; + } + + // If no storage class was specified in the streamer, define it here. + if (coff_symbol->Data.StorageClass == 0) { + bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); + + coff_symbol->Data.StorageClass = + external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; + } + + if (SymbolData.Fragment != NULL) + coff_symbol->Section = + SectionMap[&SymbolData.Fragment->getParent()->getSection()]; + + // Bind internal COFF symbol to MC symbol. + coff_symbol->MCData = &SymbolData; + SymbolMap[&SymbolData.getSymbol()] = coff_symbol; +} + +/// making a section real involves assigned it a number and putting +/// name into the string table if needed +void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) { + if (S.Name.size() > COFF::NameSize) { + size_t StringTableEntry = Strings.insert(S.Name.c_str()); + + // FIXME: Why is this number 999999? This number is never mentioned in the + // spec. I'm assuming this is due to the printed value needing to fit into + // the S.Header.Name field. In which case why not 9999999 (7 9's instead of + // 6)? The spec does not state if this entry should be null terminated in + // this case, and thus this seems to be the best way to do it. I think I + // just solved my own FIXME... + if (StringTableEntry > 999999) + report_fatal_error("COFF string table is greater than 999999 bytes."); + + std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); + } else + std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); + + S.Number = Number; + S.Symbol->Data.SectionNumber = S.Number; + S.Symbol->Aux[0].Aux.SectionDefinition.Number = S.Number; +} + +void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) { + if (S.Name.size() > COFF::NameSize) { + size_t StringTableEntry = Strings.insert(S.Name.c_str()); + + S.set_name_offset(StringTableEntry); + } else + std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); + S.Index = Index; +} + +bool WinCOFFObjectWriter::ExportSection(COFFSection const *S) { + return !S->MCData->getFragmentList().empty(); +} + +bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, + MCAssembler &Asm) { + // This doesn't seem to be right. Strings referred to from the .data section + // need symbols so they can be linked to code in the .text section right? + + // return Asm.isSymbolLinkerVisible (&SymbolData); + + // For now, all non-variable symbols are exported, + // the linker will sort the rest out for us. + return SymbolData.isExternal() || !SymbolData.getSymbol().isVariable(); +} + +bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { + return (S->Header.Characteristics + & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0; +} + +//------------------------------------------------------------------------------ +// entity writing methods + +void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { + WriteLE16(Header.Machine); + WriteLE16(Header.NumberOfSections); + WriteLE32(Header.TimeDateStamp); + WriteLE32(Header.PointerToSymbolTable); + WriteLE32(Header.NumberOfSymbols); + WriteLE16(Header.SizeOfOptionalHeader); + WriteLE16(Header.Characteristics); +} + +void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol *S) { + WriteBytes(StringRef(S->Data.Name, COFF::NameSize)); + WriteLE32(S->Data.Value); + WriteLE16(S->Data.SectionNumber); + WriteLE16(S->Data.Type); + Write8(S->Data.StorageClass); + Write8(S->Data.NumberOfAuxSymbols); + WriteAuxiliarySymbols(S->Aux); +} + +void WinCOFFObjectWriter::WriteAuxiliarySymbols( + const COFFSymbol::AuxiliarySymbols &S) { + for(COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end(); + i != e; ++i) { + switch(i->AuxType) { + case ATFunctionDefinition: + WriteLE32(i->Aux.FunctionDefinition.TagIndex); + WriteLE32(i->Aux.FunctionDefinition.TotalSize); + WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber); + WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction); + WriteZeros(sizeof(i->Aux.FunctionDefinition.unused)); + break; + case ATbfAndefSymbol: + WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1)); + WriteLE16(i->Aux.bfAndefSymbol.Linenumber); + WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2)); + WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction); + WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3)); + break; + case ATWeakExternal: + WriteLE32(i->Aux.WeakExternal.TagIndex); + WriteLE32(i->Aux.WeakExternal.Characteristics); + WriteZeros(sizeof(i->Aux.WeakExternal.unused)); + break; + case ATFile: + WriteBytes(StringRef(reinterpret_cast(i->Aux.File.FileName), + sizeof(i->Aux.File.FileName))); + break; + case ATSectionDefinition: + WriteLE32(i->Aux.SectionDefinition.Length); + WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations); + WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers); + WriteLE32(i->Aux.SectionDefinition.CheckSum); + WriteLE16(i->Aux.SectionDefinition.Number); + Write8(i->Aux.SectionDefinition.Selection); + WriteZeros(sizeof(i->Aux.SectionDefinition.unused)); + break; + } + } +} + +void WinCOFFObjectWriter::WriteSectionHeader(const COFF::section &S) { + WriteBytes(StringRef(S.Name, COFF::NameSize)); + + WriteLE32(S.VirtualSize); + WriteLE32(S.VirtualAddress); + WriteLE32(S.SizeOfRawData); + WriteLE32(S.PointerToRawData); + WriteLE32(S.PointerToRelocations); + WriteLE32(S.PointerToLineNumbers); + WriteLE16(S.NumberOfRelocations); + WriteLE16(S.NumberOfLineNumbers); + WriteLE32(S.Characteristics); +} + +void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { + WriteLE32(R.VirtualAddress); + WriteLE32(R.SymbolTableIndex); + WriteLE16(R.Type); +} + +//////////////////////////////////////////////////////////////////////////////// +// MCObjectWriter interface implementations + +void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) { + // "Define" each section & symbol. This creates section & symbol + // entries in the staging area. + + for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) + DefineSection(*i); + + for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), + e = Asm.symbol_end(); i != e; i++) { + if (ExportSymbol(*i, Asm)) + DefineSymbol(*i, Asm); + } +} + +void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, + MCValue Target, + uint64_t &FixedValue) { + assert(Target.getSymA() != NULL && "Relocation must reference a symbol!"); + + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData &A_SD = Asm.getSymbolData(*A); + + MCSectionData const *SectionData = Fragment->getParent(); + + // Mark this symbol as requiring an entry in the symbol table. + assert(SectionMap.find(&SectionData->getSection()) != SectionMap.end() && + "Section must already have been defined in ExecutePostLayoutBinding!"); + assert(SymbolMap.find(&A_SD.getSymbol()) != SymbolMap.end() && + "Symbol must already have been defined in ExecutePostLayoutBinding!"); + + COFFSection *coff_section = SectionMap[&SectionData->getSection()]; + COFFSymbol *coff_symbol = SymbolMap[&A_SD.getSymbol()]; + + if (Target.getSymB()) { + if (&Target.getSymA()->getSymbol().getSection() + != &Target.getSymB()->getSymbol().getSection()) { + llvm_unreachable("Symbol relative relocations are only allowed between " + "symbols in the same section"); + } + const MCSymbol *B = &Target.getSymB()->getSymbol(); + MCSymbolData &B_SD = Asm.getSymbolData(*B); + + FixedValue = Layout.getSymbolOffset(&A_SD) - Layout.getSymbolOffset(&B_SD); + + // In the case where we have SymbA and SymB, we just need to store the delta + // between the two symbols. Update FixedValue to account for the delta, and + // skip recording the relocation. + return; + } else { + FixedValue = Target.getConstant(); + } + + COFFRelocation Reloc; + + Reloc.Data.SymbolTableIndex = 0; + Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); + + // Turn relocations for temporary symbols into section relocations. + if (coff_symbol->MCData->getSymbol().isTemporary()) { + Reloc.Symb = coff_symbol->Section->Symbol; + FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment) + + coff_symbol->MCData->getOffset(); + } else + Reloc.Symb = coff_symbol; + + ++Reloc.Symb->Relocations; + + Reloc.Data.VirtualAddress += Fixup.getOffset(); + + switch ((unsigned)Fixup.getKind()) { + case FK_PCRel_4: + case X86::reloc_riprel_4byte: + case X86::reloc_riprel_4byte_movq_load: + Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32 + : COFF::IMAGE_REL_I386_REL32; + // FIXME: Can anyone explain what this does other than adjust for the size + // of the offset? + FixedValue += 4; + break; + case FK_Data_4: + case X86::reloc_signed_4byte: + Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32 + : COFF::IMAGE_REL_I386_DIR32; + break; + case FK_Data_8: + if (Is64Bit) + Reloc.Data.Type = COFF::IMAGE_REL_AMD64_ADDR64; + else + llvm_unreachable("unsupported relocation type"); + break; + default: + llvm_unreachable("unsupported relocation type"); + } + + coff_section->Relocations.push_back(Reloc); +} + +void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + // Assign symbol and section indexes and offsets. + Header.NumberOfSections = 0; + + for (sections::iterator i = Sections.begin(), + e = Sections.end(); i != e; i++) { + if (Layout.getSectionAddressSize((*i)->MCData) > 0) { + MakeSectionReal(**i, ++Header.NumberOfSections); + } else { + (*i)->Number = -1; + } + } + + Header.NumberOfSymbols = 0; + + for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { + COFFSymbol *coff_symbol = *i; + MCSymbolData const *SymbolData = coff_symbol->MCData; + + // Update section number & offset for symbols that have them. + if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) { + assert(coff_symbol->Section != NULL); + + coff_symbol->Data.SectionNumber = coff_symbol->Section->Number; + coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment) + + SymbolData->Offset; + } + + if (coff_symbol->should_keep()) { + MakeSymbolReal(*coff_symbol, Header.NumberOfSymbols++); + + // Update auxiliary symbol info. + coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size(); + Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols; + } else + coff_symbol->Index = -1; + } + + // Fixup weak external references. + for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { + COFFSymbol *coff_symbol = *i; + if (coff_symbol->Other != NULL) { + assert(coff_symbol->Index != -1); + assert(coff_symbol->Aux.size() == 1 && + "Symbol must contain one aux symbol!"); + assert(coff_symbol->Aux[0].AuxType == ATWeakExternal && + "Symbol's aux symbol must be a Weak External!"); + coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = coff_symbol->Other->Index; + } + } + + // Assign file offsets to COFF object file structures. + + unsigned offset = 0; + + offset += COFF::HeaderSize; + offset += COFF::SectionSize * Header.NumberOfSections; + + for (MCAssembler::const_iterator i = Asm.begin(), + e = Asm.end(); + i != e; i++) { + COFFSection *Sec = SectionMap[&i->getSection()]; + + if (Sec->Number == -1) + continue; + + Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i); + + if (IsPhysicalSection(Sec)) { + Sec->Header.PointerToRawData = offset; + + offset += Sec->Header.SizeOfRawData; + } + + if (Sec->Relocations.size() > 0) { + Sec->Header.NumberOfRelocations = Sec->Relocations.size(); + Sec->Header.PointerToRelocations = offset; + + offset += COFF::RelocationSize * Sec->Relocations.size(); + + for (relocations::iterator cr = Sec->Relocations.begin(), + er = Sec->Relocations.end(); + cr != er; ++cr) { + assert((*cr).Symb->Index != -1); + (*cr).Data.SymbolTableIndex = (*cr).Symb->Index; + } + } + + assert(Sec->Symbol->Aux.size() == 1 + && "Section's symbol must have one aux!"); + AuxSymbol &Aux = Sec->Symbol->Aux[0]; + assert(Aux.AuxType == ATSectionDefinition && + "Section's symbol's aux symbol must be a Section Definition!"); + Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; + Aux.Aux.SectionDefinition.NumberOfRelocations = + Sec->Header.NumberOfRelocations; + Aux.Aux.SectionDefinition.NumberOfLinenumbers = + Sec->Header.NumberOfLineNumbers; + } + + Header.PointerToSymbolTable = offset; + + Header.TimeDateStamp = sys::TimeValue::now().toEpochTime(); + + // Write it all to disk... + WriteFileHeader(Header); + + { + sections::iterator i, ie; + MCAssembler::const_iterator j, je; + + for (i = Sections.begin(), ie = Sections.end(); i != ie; i++) + if ((*i)->Number != -1) + WriteSectionHeader((*i)->Header); + + for (i = Sections.begin(), ie = Sections.end(), + j = Asm.begin(), je = Asm.end(); + (i != ie) && (j != je); ++i, ++j) { + + if ((*i)->Number == -1) + continue; + + if ((*i)->Header.PointerToRawData != 0) { + assert(OS.tell() == (*i)->Header.PointerToRawData && + "Section::PointerToRawData is insane!"); + + Asm.WriteSectionData(j, Layout); + } + + if ((*i)->Relocations.size() > 0) { + assert(OS.tell() == (*i)->Header.PointerToRelocations && + "Section::PointerToRelocations is insane!"); + + for (relocations::const_iterator k = (*i)->Relocations.begin(), + ke = (*i)->Relocations.end(); + k != ke; k++) { + WriteRelocation(k->Data); + } + } else + assert((*i)->Header.PointerToRelocations == 0 && + "Section::PointerToRelocations is insane!"); + } + } + + assert(OS.tell() == Header.PointerToSymbolTable && + "Header::PointerToSymbolTable is insane!"); + + for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) + if ((*i)->Index != -1) + WriteSymbol(*i); + + OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); +} + +//------------------------------------------------------------------------------ +// WinCOFFObjectWriter factory function + +namespace llvm { + MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit) { + return new WinCOFFObjectWriter(OS, is64Bit); + } +} diff --git a/final/lib/MC/WinCOFFStreamer.cpp b/final/lib/MC/WinCOFFStreamer.cpp new file mode 100644 index 00000000000..46968e601be --- /dev/null +++ b/final/lib/MC/WinCOFFStreamer.cpp @@ -0,0 +1,395 @@ +//===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an implementation of a Win32 COFF object file streamer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "WinCOFFStreamer" + +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/ADT/StringMap.h" + +#include "llvm/Support/COFF.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +namespace { +class WinCOFFStreamer : public MCObjectStreamer { +public: + MCSymbol const *CurSymbol; + + WinCOFFStreamer(MCContext &Context, + TargetAsmBackend &TAB, + MCCodeEmitter &CE, + raw_ostream &OS); + + void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, bool External); + + // MCStreamer interface + + virtual void InitSections(); + virtual void EmitLabel(MCSymbol *Symbol); + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); + virtual void EmitThumbFunc(MCSymbol *Func); + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); + virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); + virtual void EmitCOFFSymbolStorageClass(int StorageClass); + virtual void EmitCOFFSymbolType(int Type); + virtual void EndCOFFSymbolDef(); + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment); + virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); + virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size,unsigned ByteAlignment); + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment); + virtual void EmitBytes(StringRef Data, unsigned AddrSpace); + virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, + unsigned ValueSize, unsigned MaxBytesToEmit); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit); + virtual void EmitFileDirective(StringRef Filename); + virtual void EmitInstruction(const MCInst &Instruction); + virtual void Finish(); + +private: + virtual void EmitInstToFragment(const MCInst &Inst) { + llvm_unreachable("Not used by WinCOFF."); + } + virtual void EmitInstToData(const MCInst &Inst) { + llvm_unreachable("Not used by WinCOFF."); + } + + void SetSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind) { + SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind)); + } + + void SetSectionText() { + SetSection(".text", + COFF::IMAGE_SCN_CNT_CODE + | COFF::IMAGE_SCN_MEM_EXECUTE + | COFF::IMAGE_SCN_MEM_READ, + SectionKind::getText()); + EmitCodeAlignment(4, 0); + } + + void SetSectionData() { + SetSection(".data", + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getDataRel()); + EmitCodeAlignment(4, 0); + } + + void SetSectionBSS() { + SetSection(".bss", + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA + | COFF::IMAGE_SCN_MEM_READ + | COFF::IMAGE_SCN_MEM_WRITE, + SectionKind::getBSS()); + EmitCodeAlignment(4, 0); + } + +}; +} // end anonymous namespace. + +WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, + TargetAsmBackend &TAB, + MCCodeEmitter &CE, + raw_ostream &OS) + : MCObjectStreamer(Context, TAB, OS, &CE) + , CurSymbol(NULL) { +} + +void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment, bool External) { + assert(!Symbol->isInSection() && "Symbol must not already have a section!"); + + std::string SectionName(".bss$linkonce"); + SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); + + MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); + + unsigned Characteristics = + COFF::IMAGE_SCN_LNK_COMDAT | + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + + int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; + + const MCSection *Section = MCStreamer::getContext().getCOFFSection( + SectionName, Characteristics, Selection, SectionKind::getBSS()); + + MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); + + if (SectionData.getAlignment() < ByteAlignment) + SectionData.setAlignment(ByteAlignment); + + SymbolData.setExternal(External); + + Symbol->setSection(*Section); + + if (ByteAlignment != 1) + new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); + + SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); +} + +// MCStreamer interface + +void WinCOFFStreamer::InitSections() { + SetSectionText(); + SetSectionData(); + SetSectionBSS(); + SetSectionText(); +} + +void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { + assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + MCObjectStreamer::EmitLabel(Symbol); +} + +void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + assert((Symbol->isInSection() + ? Symbol->getSection().getVariant() == MCSection::SV_COFF + : true) && "Got non COFF section in the COFF backend!"); + // FIXME: This is all very ugly and depressing. What needs to happen here + // depends on quite a few things that are all part of relaxation, which we + // don't really even do. + + if (Value->getKind() != MCExpr::SymbolRef) { + // TODO: This is exactly the same as MachOStreamer. Consider merging into + // MCObjectStreamer. + getAssembler().getOrCreateSymbolData(*Symbol); + AddValueSymbols(Value); + Symbol->setVariableValue(Value); + } else { + // FIXME: This is a horrible way to do this :(. This should really be + // handled after we are done with the MC* objects and immediately before + // writing out the object file when we know exactly what the symbol should + // look like in the coff symbol table. I'm not doing that now because the + // COFF object writer doesn't have a clearly defined separation between MC + // data structures, the object writers data structures, and the raw, POD, + // data structures that get written to disk. + + // Copy over the aliased data. + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData( + dyn_cast(Value)->getSymbol()); + + // FIXME: This is particularly nasty because it breaks as soon as any data + // members of MCSymbolData change. + SD.CommonAlign = RealSD.CommonAlign; + SD.CommonSize = RealSD.CommonSize; + SD.Flags = RealSD.Flags; + SD.Fragment = RealSD.Fragment; + SD.Index = RealSD.Index; + SD.IsExternal = RealSD.IsExternal; + SD.IsPrivateExtern = RealSD.IsPrivateExtern; + SD.Offset = RealSD.Offset; + SD.SymbolSize = RealSD.SymbolSize; + } +} + +void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + assert(Symbol && "Symbol must be non-null!"); + assert((Symbol->isInSection() + ? Symbol->getSection().getVariant() == MCSection::SV_COFF + : true) && "Got non COFF section in the COFF backend!"); + switch (Attribute) { + case MCSA_WeakReference: + case MCSA_Weak: { + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); + SD.setExternal(true); + } + break; + + case MCSA_Global: + getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); + break; + + default: + llvm_unreachable("unsupported attribute"); + break; + } +} + +void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { + assert((Symbol->isInSection() + ? Symbol->getSection().getVariant() == MCSection::SV_COFF + : true) && "Got non COFF section in the COFF backend!"); + assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " + "to BeginCOFFSymbolDef!"); + CurSymbol = Symbol; +} + +void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { + assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); + assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " + "the first byte!"); + + getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( + StorageClass << COFF::SF_ClassShift, + COFF::SF_ClassMask); +} + +void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { + assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); + assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " + "bytes"); + + getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( + Type << COFF::SF_TypeShift, + COFF::SF_TypeMask); +} + +void WinCOFFStreamer::EndCOFFSymbolDef() { + assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); + CurSymbol = NULL; +} + +void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + assert((Symbol->isInSection() + ? Symbol->getSection().getVariant() == MCSection::SV_COFF + : true) && "Got non COFF section in the COFF backend!"); + AddCommonSymbol(Symbol, Size, ByteAlignment, true); +} + +void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { + assert((Symbol->isInSection() + ? Symbol->getSection().getVariant() == MCSection::SV_COFF + : true) && "Got non COFF section in the COFF backend!"); + AddCommonSymbol(Symbol, Size, 1, false); +} + +void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + unsigned Size,unsigned ByteAlignment) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + llvm_unreachable("not implemented"); +} + +void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { + // TODO: This is copied exactly from the MachOStreamer. Consider merging into + // MCObjectStreamer? + getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end()); +} + +void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment, + int64_t Value, + unsigned ValueSize, + unsigned MaxBytesToEmit) { + // TODO: This is copied exactly from the MachOStreamer. Consider merging into + // MCObjectStreamer? + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, + getCurrentSectionData()); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // TODO: This is copied exactly from the MachOStreamer. Consider merging into + // MCObjectStreamer? + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit, + getCurrentSectionData()); + F->setEmitNops(true); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > getCurrentSectionData()->getAlignment()) + getCurrentSectionData()->setAlignment(ByteAlignment); +} + +void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { + // Ignore for now, linkers don't care, and proper debug + // info will be a much large effort. +} + +void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) { + for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i) + if (Instruction.getOperand(i).isExpr()) + AddValueSymbols(Instruction.getOperand(i).getExpr()); + + getCurrentSectionData()->setHasInstructions(true); + + MCInstFragment *Fragment = + new MCInstFragment(Instruction, getCurrentSectionData()); + + raw_svector_ostream VecOS(Fragment->getCode()); + + getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS, + Fragment->getFixups()); +} + +void WinCOFFStreamer::Finish() { + MCObjectStreamer::Finish(); +} + +namespace llvm +{ + MCStreamer *createWinCOFFStreamer(MCContext &Context, + TargetAsmBackend &TAB, + MCCodeEmitter &CE, + raw_ostream &OS, + bool RelaxAll) { + WinCOFFStreamer *S = new WinCOFFStreamer(Context, TAB, CE, OS); + S->getAssembler().setRelaxAll(RelaxAll); + return S; + } +} diff --git a/final/lib/Makefile b/final/lib/Makefile new file mode 100644 index 00000000000..ed27854f22c --- /dev/null +++ b/final/lib/Makefile @@ -0,0 +1,17 @@ +##===- lib/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 + +PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \ + Target ExecutionEngine Linker MC CompilerDriver Object + +include $(LEVEL)/Makefile.common + diff --git a/final/lib/Object/CMakeLists.txt b/final/lib/Object/CMakeLists.txt new file mode 100644 index 00000000000..6a6814fd37d --- /dev/null +++ b/final/lib/Object/CMakeLists.txt @@ -0,0 +1,6 @@ +add_llvm_library(LLVMObject + MachOObject.cpp + ObjectFile.cpp + COFFObjectFile.cpp + ELFObjectFile.cpp + ) diff --git a/final/lib/Object/COFFObjectFile.cpp b/final/lib/Object/COFFObjectFile.cpp new file mode 100644 index 00000000000..cfee82a0b21 --- /dev/null +++ b/final/lib/Object/COFFObjectFile.cpp @@ -0,0 +1,375 @@ +//===- COFFObjectFile.cpp - COFF object file implementation -----*- 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 COFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace object; + +namespace { +using support::ulittle8_t; +using support::ulittle16_t; +using support::ulittle32_t; +using support::little16_t; +} + +namespace { +struct coff_file_header { + ulittle16_t Machine; + ulittle16_t NumberOfSections; + ulittle32_t TimeDateStamp; + ulittle32_t PointerToSymbolTable; + ulittle32_t NumberOfSymbols; + ulittle16_t SizeOfOptionalHeader; + ulittle16_t Characteristics; +}; +} + +extern char coff_file_header_layout_static_assert + [sizeof(coff_file_header) == 20 ? 1 : -1]; + +namespace { +struct coff_symbol { + struct StringTableOffset { + ulittle32_t Zeroes; + ulittle32_t Offset; + }; + + union { + char ShortName[8]; + StringTableOffset Offset; + } Name; + + ulittle32_t Value; + little16_t SectionNumber; + + struct { + ulittle8_t BaseType; + ulittle8_t ComplexType; + } Type; + + ulittle8_t StorageClass; + ulittle8_t NumberOfAuxSymbols; +}; +} + +extern char coff_coff_symbol_layout_static_assert + [sizeof(coff_symbol) == 18 ? 1 : -1]; + +namespace { +struct coff_section { + char Name[8]; + ulittle32_t VirtualSize; + ulittle32_t VirtualAddress; + ulittle32_t SizeOfRawData; + ulittle32_t PointerToRawData; + ulittle32_t PointerToRelocations; + ulittle32_t PointerToLinenumbers; + ulittle16_t NumberOfRelocations; + ulittle16_t NumberOfLinenumbers; + ulittle32_t Characteristics; +}; +} + +extern char coff_coff_section_layout_static_assert + [sizeof(coff_section) == 40 ? 1 : -1]; + +namespace { +class COFFObjectFile : public ObjectFile { +private: + const coff_file_header *Header; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + + const coff_section *getSection(std::size_t index) const; + const char *getString(std::size_t offset) const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +public: + COFFObjectFile(MemoryBuffer *Object); + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; +}; +} // end namespace + +SymbolRef COFFObjectFile::getSymbolNext(DataRefImpl Symb) const { + const coff_symbol *symb = reinterpret_cast(Symb.p); + symb += 1 + symb->NumberOfAuxSymbols; + Symb.p = reinterpret_cast(symb); + return SymbolRef(Symb, this); +} + +StringRef COFFObjectFile::getSymbolName(DataRefImpl Symb) const { + const coff_symbol *symb = reinterpret_cast(Symb.p); + // Check for string table entry. First 4 bytes are 0. + if (symb->Name.Offset.Zeroes == 0) { + uint32_t Offset = symb->Name.Offset.Offset; + return StringRef(getString(Offset)); + } + + if (symb->Name.ShortName[7] == 0) + // Null terminated, let ::strlen figure out the length. + return StringRef(symb->Name.ShortName); + // Not null terminated, use all 8 bytes. + return StringRef(symb->Name.ShortName, 8); +} + +uint64_t COFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { + const coff_symbol *symb = reinterpret_cast(Symb.p); + const coff_section *Section = getSection(symb->SectionNumber); + char Type = getSymbolNMTypeChar(Symb); + if (Type == 'U' || Type == 'w') + return UnknownAddressOrSize; + if (Section) + return Section->VirtualAddress + symb->Value; + return symb->Value; +} + +uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Symb) const { + // FIXME: Return the correct size. This requires looking at all the symbols + // in the same section as this symbol, and looking for either the next + // symbol, or the end of the section. + const coff_symbol *symb = reinterpret_cast(Symb.p); + const coff_section *Section = getSection(symb->SectionNumber); + char Type = getSymbolNMTypeChar(Symb); + if (Type == 'U' || Type == 'w') + return UnknownAddressOrSize; + if (Section) + return Section->SizeOfRawData - symb->Value; + return 0; +} + +char COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb) const { + const coff_symbol *symb = reinterpret_cast(Symb.p); + char ret = StringSwitch(getSymbolName(Symb)) + .StartsWith(".debug", 'N') + .StartsWith(".sxdata", 'N') + .Default('?'); + + if (ret != '?') + return ret; + + uint32_t Characteristics = 0; + uint32_t PointerToRawData = 0; + const coff_section *Section = getSection(symb->SectionNumber); + if (Section) { + Characteristics = Section->Characteristics; + PointerToRawData = Section->PointerToRawData; + } + + switch (symb->SectionNumber) { + case COFF::IMAGE_SYM_UNDEFINED: + // Check storage classes. + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + return 'w'; // Don't do ::toupper. + else + ret = 'u'; + break; + case COFF::IMAGE_SYM_ABSOLUTE: + ret = 'a'; + break; + case COFF::IMAGE_SYM_DEBUG: + ret = 'n'; + break; + default: + // Check section type. + if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) + ret = 't'; + else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ + && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. + ret = 'r'; + else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + ret = 'd'; + else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + ret = 'b'; + else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) + ret = 'i'; + + // Check for section symbol. + else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC + && symb->Value == 0) + ret = 's'; + } + + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) + ret = ::toupper(ret); + + return ret; +} + +bool COFFObjectFile::isSymbolInternal(DataRefImpl Symb) const { + return false; +} + +SectionRef COFFObjectFile::getSectionNext(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + sec += 1; + Sec.p = reinterpret_cast(sec); + return SectionRef(Sec, this); +} + +StringRef COFFObjectFile::getSectionName(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + StringRef name; + if (sec->Name[7] == 0) + // Null terminated, let ::strlen figure out the length. + name = sec->Name; + else + // Not null terminated, use all 8 bytes. + name = StringRef(sec->Name, 8); + + // Check for string table entry. First byte is '/'. + if (name[0] == '/') { + uint32_t Offset; + name.getAsInteger(10, Offset); + return StringRef(getString(Offset)); + } + + // It's just a normal name. + return name; +} + +uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + return sec->VirtualAddress; +} + +uint64_t COFFObjectFile::getSectionSize(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + return sec->SizeOfRawData; +} + +StringRef COFFObjectFile::getSectionContents(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + return StringRef(reinterpret_cast(base + sec->PointerToRawData), + sec->SizeOfRawData); +} + +bool COFFObjectFile::isSectionText(DataRefImpl Sec) const { + const coff_section *sec = reinterpret_cast(Sec.p); + return sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; +} + +COFFObjectFile::COFFObjectFile(MemoryBuffer *Object) + : ObjectFile(Object) { + Header = reinterpret_cast(base); + SectionTable = + reinterpret_cast( base + + sizeof(coff_file_header) + + Header->SizeOfOptionalHeader); + SymbolTable = + reinterpret_cast(base + Header->PointerToSymbolTable); + + // Find string table. + StringTable = reinterpret_cast(base) + + Header->PointerToSymbolTable + + Header->NumberOfSymbols * 18; +} + +ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const { + DataRefImpl ret; + ret.p = reinterpret_cast(SymbolTable); + return symbol_iterator(SymbolRef(ret, this)); +} + +ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const { + // The symbol table ends where the string table begins. + DataRefImpl ret; + ret.p = reinterpret_cast(StringTable); + return symbol_iterator(SymbolRef(ret, this)); +} + +ObjectFile::section_iterator COFFObjectFile::begin_sections() const { + DataRefImpl ret; + ret.p = reinterpret_cast(SectionTable); + return section_iterator(SectionRef(ret, this)); +} + +ObjectFile::section_iterator COFFObjectFile::end_sections() const { + DataRefImpl ret; + ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections); + return section_iterator(SectionRef(ret, this)); +} + +uint8_t COFFObjectFile::getBytesInAddress() const { + return getArch() == Triple::x86_64 ? 8 : 4; +} + +StringRef COFFObjectFile::getFileFormatName() const { + switch(Header->Machine) { + case COFF::IMAGE_FILE_MACHINE_I386: + return "COFF-i386"; + case COFF::IMAGE_FILE_MACHINE_AMD64: + return "COFF-x86-64"; + default: + return "COFF-"; + } +} + +unsigned COFFObjectFile::getArch() const { + switch(Header->Machine) { + case COFF::IMAGE_FILE_MACHINE_I386: + return Triple::x86; + case COFF::IMAGE_FILE_MACHINE_AMD64: + return Triple::x86_64; + default: + return Triple::UnknownArch; + } +} + +const coff_section *COFFObjectFile::getSection(std::size_t index) const { + if (index > 0 && index <= Header->NumberOfSections) + return SectionTable + (index - 1); + return 0; +} + +const char *COFFObjectFile::getString(std::size_t offset) const { + const ulittle32_t *StringTableSize = + reinterpret_cast(StringTable); + if (offset < *StringTableSize) + return StringTable + offset; + return 0; +} + +namespace llvm { + + ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { + return new COFFObjectFile(Object); + } + +} // end namespace llvm diff --git a/final/lib/Object/ELFObjectFile.cpp b/final/lib/Object/ELFObjectFile.cpp new file mode 100644 index 00000000000..682be770f48 --- /dev/null +++ b/final/lib/Object/ELFObjectFile.cpp @@ -0,0 +1,686 @@ +//===- ELFObjectFile.cpp - ELF object file implementation -------*- 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 ELFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include +#include + +using namespace llvm; +using namespace object; + +// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. +namespace { +template +struct ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral + Elf_Half; + typedef support::detail::packed_endian_specific_integral + Elf_Word; + typedef support::detail::packed_endian_specific_integral + Elf_Sword; + typedef support::detail::packed_endian_specific_integral + Elf_Xword; + typedef support::detail::packed_endian_specific_integral + Elf_Sxword; +}; +} + +namespace { +template +struct ELFDataTypeTypedefHelper; + +/// ELF 32bit types. +template +struct ELFDataTypeTypedefHelper + : ELFDataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral + Elf_Addr; + typedef support::detail::packed_endian_specific_integral + Elf_Off; +}; + +/// ELF 64bit types. +template +struct ELFDataTypeTypedefHelper + : ELFDataTypeTypedefHelperCommon{ + typedef support::detail::packed_endian_specific_integral + Elf_Addr; + typedef support::detail::packed_endian_specific_integral + Elf_Off; +}; +} + +// I really don't like doing this, but the alternative is copypasta. +#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Addr Elf_Addr; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Off Elf_Off; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Half Elf_Half; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Word Elf_Word; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Sword Elf_Sword; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Xword Elf_Xword; \ +typedef typename \ + ELFDataTypeTypedefHelper::Elf_Sxword Elf_Sxword; + + // Section header. +namespace { +template +struct Elf_Shdr_Base; + +template +struct Elf_Shdr_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Word sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Word sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Word sh_addralign;// Section address alignment + Elf_Word sh_entsize; // Size of records contained within the section +}; + +template +struct Elf_Shdr_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + Elf_Word sh_name; // Section name (index into string table) + Elf_Word sh_type; // Section type (SHT_*) + Elf_Xword sh_flags; // Section flags (SHF_*) + Elf_Addr sh_addr; // Address where section is to be loaded + Elf_Off sh_offset; // File offset of section data, in bytes + Elf_Xword sh_size; // Size of section, in bytes + Elf_Word sh_link; // Section type-specific header table index link + Elf_Word sh_info; // Section type-specific extra information + Elf_Xword sh_addralign;// Section address alignment + Elf_Xword sh_entsize; // Size of records contained within the section +}; + +template +struct Elf_Shdr_Impl : Elf_Shdr_Base { + using Elf_Shdr_Base::sh_entsize; + using Elf_Shdr_Base::sh_size; + + /// @brief Get the number of entities this section contains if it has any. + unsigned getEntityCount() const { + if (sh_entsize == 0) + return 0; + return sh_size / sh_entsize; + } +}; +} + +namespace { +template +struct Elf_Sym_Base; + +template +struct Elf_Sym_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, false) + Elf_Word st_name; // Symbol name (index into string table) + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in +}; + +template +struct Elf_Sym_Base { + LLVM_ELF_IMPORT_TYPES(target_endianness, true) + Elf_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf_Half st_shndx; // Which section (header table index) it's defined in + Elf_Addr st_value; // Value or address associated with the symbol + Elf_Xword st_size; // Size of the symbol +}; + +template +struct Elf_Sym_Impl : Elf_Sym_Base { + using Elf_Sym_Base::st_info; + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; +} + +namespace { +template +class ELFObjectFile : public ObjectFile { + LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) + + typedef Elf_Shdr_Impl Elf_Shdr; + typedef Elf_Sym_Impl Elf_Sym; + + struct Elf_Ehdr { + unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes + Elf_Half e_type; // Type of file (see ET_*) + Elf_Half e_machine; // Required architecture for this file (see EM_*) + Elf_Word e_version; // Must be equal to 1 + Elf_Addr e_entry; // Address to jump to in order to start program + Elf_Off e_phoff; // Program header table's file offset, in bytes + Elf_Off e_shoff; // Section header table's file offset, in bytes + Elf_Word e_flags; // Processor-specific flags + Elf_Half e_ehsize; // Size of ELF header, in bytes + Elf_Half e_phentsize;// Size of an entry in the program header table + Elf_Half e_phnum; // Number of entries in the program header table + Elf_Half e_shentsize;// Size of an entry in the section header table + Elf_Half e_shnum; // Number of entries in the section header table + Elf_Half e_shstrndx; // Section header table index of section name + // string table + bool checkMagic() const { + return (memcmp(e_ident, ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[ELF::EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } + }; + + typedef SmallVector SymbolTableSections_t; + + const Elf_Ehdr *Header; + const Elf_Shdr *SectionHeaderTable; + const Elf_Shdr *dot_shstrtab_sec; // Section header string table. + const Elf_Shdr *dot_strtab_sec; // Symbol header string table. + SymbolTableSections_t SymbolTableSections; + + void validateSymbol(DataRefImpl Symb) const; + const Elf_Sym *getSymbol(DataRefImpl Symb) const; + const Elf_Shdr *getSection(DataRefImpl index) const; + const Elf_Shdr *getSection(uint16_t index) const; + const char *getString(uint16_t section, uint32_t offset) const; + const char *getString(const Elf_Shdr *section, uint32_t offset) const; + +protected: + virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; + virtual StringRef getSymbolName(DataRefImpl Symb) const; + virtual uint64_t getSymbolAddress(DataRefImpl Symb) const; + virtual uint64_t getSymbolSize(DataRefImpl Symb) const; + virtual char getSymbolNMTypeChar(DataRefImpl Symb) const; + virtual bool isSymbolInternal(DataRefImpl Symb) const; + + virtual SectionRef getSectionNext(DataRefImpl Sec) const; + virtual StringRef getSectionName(DataRefImpl Sec) const; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const; + virtual uint64_t getSectionSize(DataRefImpl Sec) const; + virtual StringRef getSectionContents(DataRefImpl Sec) const; + virtual bool isSectionText(DataRefImpl Sec) const; + +public: + ELFObjectFile(MemoryBuffer *Object); + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual uint8_t getBytesInAddress() const; + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; +}; +} // end namespace + +template +void ELFObjectFile + ::validateSymbol(DataRefImpl Symb) const { + const Elf_Sym *symb = getSymbol(Symb); + const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; + // FIXME: We really need to do proper error handling in the case of an invalid + // input file. Because we don't use exceptions, I think we'll just pass + // an error object around. + if (!( symb + && SymbolTableSection + && symb >= (const Elf_Sym*)(base + + SymbolTableSection->sh_offset) + && symb < (const Elf_Sym*)(base + + SymbolTableSection->sh_offset + + SymbolTableSection->sh_size))) + // FIXME: Proper error handling. + report_fatal_error("Symb must point to a valid symbol!"); +} + +template +SymbolRef ELFObjectFile + ::getSymbolNext(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; + + ++Symb.d.a; + // Check to see if we are at the end of this symbol table. + if (Symb.d.a >= SymbolTableSection->getEntityCount()) { + // We are at the end. If there are other symbol tables, jump to them. + ++Symb.d.b; + Symb.d.a = 1; // The 0th symbol in ELF is fake. + // Otherwise return the terminator. + if (Symb.d.b >= SymbolTableSections.size()) { + Symb.d.a = std::numeric_limits::max(); + Symb.d.b = std::numeric_limits::max(); + } + } + + return SymbolRef(Symb, this); +} + +template +StringRef ELFObjectFile + ::getSymbolName(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + if (symb->st_name == 0) { + const Elf_Shdr *section = getSection(symb->st_shndx); + if (!section) + return ""; + return getString(dot_shstrtab_sec, section->sh_name); + } + + // Use the default symbol table name section. + return getString(dot_strtab_sec, symb->st_name); +} + +template +uint64_t ELFObjectFile + ::getSymbolAddress(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + const Elf_Shdr *Section; + switch (symb->st_shndx) { + case ELF::SHN_COMMON: + // Undefined symbols have no address yet. + case ELF::SHN_UNDEF: return UnknownAddressOrSize; + case ELF::SHN_ABS: return symb->st_value; + default: Section = getSection(symb->st_shndx); + } + + switch (symb->getType()) { + case ELF::STT_SECTION: return Section ? Section->sh_addr + : UnknownAddressOrSize; + case ELF::STT_FUNC: + case ELF::STT_OBJECT: + case ELF::STT_NOTYPE: + return symb->st_value; + default: return UnknownAddressOrSize; + } +} + +template +uint64_t ELFObjectFile + ::getSymbolSize(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + if (symb->st_size == 0) + return UnknownAddressOrSize; + return symb->st_size; +} + +template +char ELFObjectFile + ::getSymbolNMTypeChar(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + const Elf_Shdr *Section = getSection(symb->st_shndx); + + char ret = '?'; + + if (Section) { + switch (Section->sh_type) { + case ELF::SHT_PROGBITS: + case ELF::SHT_DYNAMIC: + switch (Section->sh_flags) { + case (ELF::SHF_ALLOC | ELF::SHF_EXECINSTR): + ret = 't'; break; + case (ELF::SHF_ALLOC | ELF::SHF_WRITE): + ret = 'd'; break; + case ELF::SHF_ALLOC: + case (ELF::SHF_ALLOC | ELF::SHF_MERGE): + case (ELF::SHF_ALLOC | ELF::SHF_MERGE | ELF::SHF_STRINGS): + ret = 'r'; break; + } + break; + case ELF::SHT_NOBITS: ret = 'b'; + } + } + + switch (symb->st_shndx) { + case ELF::SHN_UNDEF: + if (ret == '?') + ret = 'U'; + break; + case ELF::SHN_ABS: ret = 'a'; break; + case ELF::SHN_COMMON: ret = 'c'; break; + } + + switch (symb->getBinding()) { + case ELF::STB_GLOBAL: ret = ::toupper(ret); break; + case ELF::STB_WEAK: + if (symb->st_shndx == ELF::SHN_UNDEF) + ret = 'w'; + else + if (symb->getType() == ELF::STT_OBJECT) + ret = 'V'; + else + ret = 'W'; + } + + if (ret == '?' && symb->getType() == ELF::STT_SECTION) + return StringSwitch(getSymbolName(Symb)) + .StartsWith(".debug", 'N') + .StartsWith(".note", 'n'); + + return ret; +} + +template +bool ELFObjectFile + ::isSymbolInternal(DataRefImpl Symb) const { + validateSymbol(Symb); + const Elf_Sym *symb = getSymbol(Symb); + + if ( symb->getType() == ELF::STT_FILE + || symb->getType() == ELF::STT_SECTION) + return true; + return false; +} + +template +SectionRef ELFObjectFile + ::getSectionNext(DataRefImpl Sec) const { + const uint8_t *sec = reinterpret_cast(Sec.p); + sec += Header->e_shentsize; + Sec.p = reinterpret_cast(sec); + return SectionRef(Sec, this); +} + +template +StringRef ELFObjectFile + ::getSectionName(DataRefImpl Sec) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); +} + +template +uint64_t ELFObjectFile + ::getSectionAddress(DataRefImpl Sec) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + return sec->sh_addr; +} + +template +uint64_t ELFObjectFile + ::getSectionSize(DataRefImpl Sec) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + return sec->sh_size; +} + +template +StringRef ELFObjectFile + ::getSectionContents(DataRefImpl Sec) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + const char *start = (char*)base + sec->sh_offset; + return StringRef(start, sec->sh_size); +} + +template +bool ELFObjectFile + ::isSectionText(DataRefImpl Sec) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + if (sec->sh_flags & ELF::SHF_EXECINSTR) + return true; + return false; +} + +template +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object) + : ObjectFile(Object) + , SectionHeaderTable(0) + , dot_shstrtab_sec(0) + , dot_strtab_sec(0) { + Header = reinterpret_cast(base); + + if (Header->e_shoff == 0) + return; + + SectionHeaderTable = + reinterpret_cast(base + Header->e_shoff); + uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize; + if (!( (const uint8_t *)SectionHeaderTable + SectionTableSize + <= base + MapFile->getBufferSize())) + // FIXME: Proper error handling. + report_fatal_error("Section table goes past end of file!"); + + + // To find the symbol tables we walk the section table to find SHT_STMTAB. + for (const char *i = reinterpret_cast(SectionHeaderTable), + *e = i + Header->e_shnum * Header->e_shentsize; + i != e; i += Header->e_shentsize) { + const Elf_Shdr *sh = reinterpret_cast(i); + if (sh->sh_type == ELF::SHT_SYMTAB) { + SymbolTableSections.push_back(sh); + } + } + + // Get string table sections. + dot_shstrtab_sec = getSection(Header->e_shstrndx); + if (dot_shstrtab_sec) { + // Verify that the last byte in the string table in a null. + if (((const char*)base + dot_shstrtab_sec->sh_offset) + [dot_shstrtab_sec->sh_size - 1] != 0) + // FIXME: Proper error handling. + report_fatal_error("String table must end with a null terminator!"); + } + + // Merge this into the above loop. + for (const char *i = reinterpret_cast(SectionHeaderTable), + *e = i + Header->e_shnum * Header->e_shentsize; + i != e; i += Header->e_shentsize) { + const Elf_Shdr *sh = reinterpret_cast(i); + if (sh->sh_type == ELF::SHT_STRTAB) { + StringRef SectionName(getString(dot_shstrtab_sec, sh->sh_name)); + if (SectionName == ".strtab") { + if (dot_strtab_sec != 0) + // FIXME: Proper error handling. + report_fatal_error("Already found section named .strtab!"); + dot_strtab_sec = sh; + const char *dot_strtab = (const char*)base + sh->sh_offset; + if (dot_strtab[sh->sh_size - 1] != 0) + // FIXME: Proper error handling. + report_fatal_error("String table must end with a null terminator!"); + } + } + } +} + +template +ObjectFile::symbol_iterator ELFObjectFile + ::begin_symbols() const { + DataRefImpl SymbolData; + memset(&SymbolData, 0, sizeof(SymbolData)); + if (SymbolTableSections.size() == 0) { + SymbolData.d.a = std::numeric_limits::max(); + SymbolData.d.b = std::numeric_limits::max(); + } else { + SymbolData.d.a = 1; // The 0th symbol in ELF is fake. + SymbolData.d.b = 0; + } + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template +ObjectFile::symbol_iterator ELFObjectFile + ::end_symbols() const { + DataRefImpl SymbolData; + memset(&SymbolData, 0, sizeof(SymbolData)); + SymbolData.d.a = std::numeric_limits::max(); + SymbolData.d.b = std::numeric_limits::max(); + return symbol_iterator(SymbolRef(SymbolData, this)); +} + +template +ObjectFile::section_iterator ELFObjectFile + ::begin_sections() const { + DataRefImpl ret; + ret.p = reinterpret_cast(base + Header->e_shoff); + return section_iterator(SectionRef(ret, this)); +} + +template +ObjectFile::section_iterator ELFObjectFile + ::end_sections() const { + DataRefImpl ret; + ret.p = reinterpret_cast(base + + Header->e_shoff + + (Header->e_shentsize * Header->e_shnum)); + return section_iterator(SectionRef(ret, this)); +} + +template +uint8_t ELFObjectFile::getBytesInAddress() const { + return is64Bits ? 8 : 4; +} + +template +StringRef ELFObjectFile + ::getFileFormatName() const { + switch(Header->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + switch(Header->e_machine) { + case ELF::EM_386: + return "ELF32-i386"; + case ELF::EM_X86_64: + return "ELF32-x86-64"; + default: + return "ELF32-unknown"; + } + case ELF::ELFCLASS64: + switch(Header->e_machine) { + case ELF::EM_386: + return "ELF64-i386"; + case ELF::EM_X86_64: + return "ELF64-x86-64"; + default: + return "ELF64-unknown"; + } + default: + // FIXME: Proper error handling. + report_fatal_error("Invalid ELFCLASS!"); + } +} + +template +unsigned ELFObjectFile::getArch() const { + switch(Header->e_machine) { + case ELF::EM_386: + return Triple::x86; + case ELF::EM_X86_64: + return Triple::x86_64; + default: + return Triple::UnknownArch; + } +} + +template +const typename ELFObjectFile::Elf_Sym * +ELFObjectFile::getSymbol(DataRefImpl Symb) const { + const Elf_Shdr *sec = SymbolTableSections[Symb.d.b]; + return reinterpret_cast( + base + + sec->sh_offset + + (Symb.d.a * sec->sh_entsize)); +} + +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getSection(DataRefImpl Symb) const { + const Elf_Shdr *sec = getSection(Symb.d.b); + if (sec->sh_type != ELF::SHT_SYMTAB) + // FIXME: Proper error handling. + report_fatal_error("Invalid symbol table section!"); + return sec; +} + +template +const typename ELFObjectFile::Elf_Shdr * +ELFObjectFile::getSection(uint16_t index) const { + if (index == 0 || index >= ELF::SHN_LORESERVE) + return 0; + if (!SectionHeaderTable || index >= Header->e_shnum) + // FIXME: Proper error handling. + report_fatal_error("Invalid section index!"); + + return reinterpret_cast( + reinterpret_cast(SectionHeaderTable) + + (index * Header->e_shentsize)); +} + +template +const char *ELFObjectFile + ::getString(uint16_t section, + ELF::Elf32_Word offset) const { + return getString(getSection(section), offset); +} + +template +const char *ELFObjectFile + ::getString(const Elf_Shdr *section, + ELF::Elf32_Word offset) const { + assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); + if (offset >= section->sh_size) + // FIXME: Proper error handling. + report_fatal_error("Sybol name offset outside of string table!"); + return (const char *)base + section->sh_offset + offset; +} + +// EI_CLASS, EI_DATA. +static std::pair +getElfArchType(MemoryBuffer *Object) { + if (Object->getBufferSize() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); + return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] + , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); +} + +namespace llvm { + + ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { + std::pair Ident = getElfArchType(Object); + if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) + return new ELFObjectFile(Object); + else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) + return new ELFObjectFile(Object); + else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) + return new ELFObjectFile(Object); + else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) + return new ELFObjectFile(Object); + // FIXME: Proper error handling. + report_fatal_error("Not an ELF object file!"); + } + +} // end namespace llvm diff --git a/final/lib/Object/MachOObject.cpp b/final/lib/Object/MachOObject.cpp new file mode 100644 index 00000000000..5e64d632328 --- /dev/null +++ b/final/lib/Object/MachOObject.cpp @@ -0,0 +1,342 @@ +//===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MachOObject.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/SwapByteOrder.h" + +using namespace llvm; +using namespace llvm::object; + +/* Translation Utilities */ + +template +static void SwapValue(T &Value) { + Value = sys::SwapByteOrder(Value); +} + +template +static void SwapStruct(T &Value); + +template +static void ReadInMemoryStruct(const MachOObject &MOO, + StringRef Buffer, uint64_t Base, + InMemoryStruct &Res) { + typedef T struct_type; + uint64_t Size = sizeof(struct_type); + + // Check that the buffer contains the expected data. + if (Base + Size > Buffer.size()) { + Res = 0; + return; + } + + // Check whether we can return a direct pointer. + struct_type *Ptr = (struct_type *) (Buffer.data() + Base); + if (!MOO.isSwappedEndian()) { + Res = Ptr; + return; + } + + // Otherwise, copy the struct and translate the values. + Res = *Ptr; + SwapStruct(*Res); +} + +/* *** */ + +MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_, + bool Is64Bit_) + : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_), + IsSwappedEndian(IsLittleEndian != sys::isLittleEndianHost()), + HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) { + // Load the common header. + memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header)); + if (IsSwappedEndian) { + SwapValue(Header.Magic); + SwapValue(Header.CPUType); + SwapValue(Header.CPUSubtype); + SwapValue(Header.FileType); + SwapValue(Header.NumLoadCommands); + SwapValue(Header.SizeOfLoadCommands); + SwapValue(Header.Flags); + } + + if (is64Bit()) { + memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header), + sizeof(Header64Ext)); + if (IsSwappedEndian) { + SwapValue(Header64Ext.Reserved); + } + } + + // Create the load command array if sane. + if (getHeader().NumLoadCommands < (1 << 20)) + LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands]; +} + +MachOObject::~MachOObject() { + delete [] LoadCommands; +} + +MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer, + std::string *ErrorStr) { + // First, check the magic value and initialize the basic object info. + bool IsLittleEndian = false, Is64Bit = false; + StringRef Magic = Buffer->getBuffer().slice(0, 4); + if (Magic == "\xFE\xED\xFA\xCE") { + } else if (Magic == "\xCE\xFA\xED\xFE") { + IsLittleEndian = true; + } else if (Magic == "\xFE\xED\xFA\xCF") { + Is64Bit = true; + } else if (Magic == "\xCF\xFA\xED\xFE") { + IsLittleEndian = true; + Is64Bit = true; + } else { + if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)"; + return 0; + } + + // Ensure that the at least the full header is present. + unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size; + if (Buffer->getBufferSize() < HeaderSize) { + if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)"; + return 0; + } + + OwningPtr Object(new MachOObject(Buffer, IsLittleEndian, + Is64Bit)); + + // Check for bogus number of load commands. + if (Object->getHeader().NumLoadCommands >= (1 << 20)) { + if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)"; + return 0; + } + + if (ErrorStr) *ErrorStr = ""; + return Object.take(); +} + +StringRef MachOObject::getData(size_t Offset, size_t Size) const { + return Buffer->getBuffer().substr(Offset,Size); +} + +void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) { + HasStringTable = true; + StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset, + SLC.StringTableSize); +} + +const MachOObject::LoadCommandInfo & +MachOObject::getLoadCommandInfo(unsigned Index) const { + assert(Index < getHeader().NumLoadCommands && "Invalid index!"); + + // Load the command, if necessary. + if (Index >= NumLoadedCommands) { + uint64_t Offset; + if (Index == 0) { + Offset = getHeaderSize(); + } else { + const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1); + Offset = Prev.Offset + Prev.Command.Size; + } + + LoadCommandInfo &Info = LoadCommands[Index]; + memcpy(&Info.Command, Buffer->getBuffer().data() + Offset, + sizeof(macho::LoadCommand)); + if (IsSwappedEndian) { + SwapValue(Info.Command.Type); + SwapValue(Info.Command.Size); + } + Info.Offset = Offset; + NumLoadedCommands = Index + 1; + } + + return LoadCommands[Index]; +} + +template<> +void SwapStruct(macho::SegmentLoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.VMAddress); + SwapValue(Value.VMSize); + SwapValue(Value.FileOffset); + SwapValue(Value.FileSize); + SwapValue(Value.MaxVMProtection); + SwapValue(Value.InitialVMProtection); + SwapValue(Value.NumSections); + SwapValue(Value.Flags); +} +void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + +template<> +void SwapStruct(macho::Segment64LoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.VMAddress); + SwapValue(Value.VMSize); + SwapValue(Value.FileOffset); + SwapValue(Value.FileSize); + SwapValue(Value.MaxVMProtection); + SwapValue(Value.InitialVMProtection); + SwapValue(Value.NumSections); + SwapValue(Value.Flags); +} +void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + +template<> +void SwapStruct(macho::SymtabLoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.SymbolTableOffset); + SwapValue(Value.NumSymbolTableEntries); + SwapValue(Value.StringTableOffset); + SwapValue(Value.StringTableSize); +} +void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + +template<> +void SwapStruct(macho::DysymtabLoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.LocalSymbolsIndex); + SwapValue(Value.NumLocalSymbols); + SwapValue(Value.ExternalSymbolsIndex); + SwapValue(Value.NumExternalSymbols); + SwapValue(Value.UndefinedSymbolsIndex); + SwapValue(Value.NumUndefinedSymbols); + SwapValue(Value.TOCOffset); + SwapValue(Value.NumTOCEntries); + SwapValue(Value.ModuleTableOffset); + SwapValue(Value.NumModuleTableEntries); + SwapValue(Value.ReferenceSymbolTableOffset); + SwapValue(Value.NumReferencedSymbolTableEntries); + SwapValue(Value.IndirectSymbolTableOffset); + SwapValue(Value.NumIndirectSymbolTableEntries); + SwapValue(Value.ExternalRelocationTableOffset); + SwapValue(Value.NumExternalRelocationTableEntries); + SwapValue(Value.LocalRelocationTableOffset); + SwapValue(Value.NumLocalRelocationTableEntries); +} +void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + +template<> +void SwapStruct(macho::IndirectSymbolTableEntry &Value) { + SwapValue(Value.Index); +} +void +MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (DLC.IndirectSymbolTableOffset + + Index * sizeof(macho::IndirectSymbolTableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + + +template<> +void SwapStruct(macho::Section &Value) { + SwapValue(Value.Address); + SwapValue(Value.Size); + SwapValue(Value.Offset); + SwapValue(Value.Align); + SwapValue(Value.RelocationTableOffset); + SwapValue(Value.NumRelocationTableEntries); + SwapValue(Value.Flags); + SwapValue(Value.Reserved1); + SwapValue(Value.Reserved2); +} +void MachOObject::ReadSection(const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const { + assert(LCI.Command.Type == macho::LCT_Segment && + "Unexpected load command info!"); + uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) + + Index * sizeof(macho::Section)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::Section64 &Value) { + SwapValue(Value.Address); + SwapValue(Value.Size); + SwapValue(Value.Offset); + SwapValue(Value.Align); + SwapValue(Value.RelocationTableOffset); + SwapValue(Value.NumRelocationTableEntries); + SwapValue(Value.Flags); + SwapValue(Value.Reserved1); + SwapValue(Value.Reserved2); + SwapValue(Value.Reserved3); +} +void MachOObject::ReadSection64(const LoadCommandInfo &LCI, + unsigned Index, + InMemoryStruct &Res) const { + assert(LCI.Command.Type == macho::LCT_Segment64 && + "Unexpected load command info!"); + uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) + + Index * sizeof(macho::Section64)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::RelocationEntry &Value) { + SwapValue(Value.Word0); + SwapValue(Value.Word1); +} +void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (RelocationTableOffset + + Index * sizeof(macho::RelocationEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::SymbolTableEntry &Value) { + SwapValue(Value.StringIndex); + SwapValue(Value.Flags); + SwapValue(Value.Value); +} +void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::SymbolTableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} + +template<> +void SwapStruct(macho::Symbol64TableEntry &Value) { + SwapValue(Value.StringIndex); + SwapValue(Value.Flags); + SwapValue(Value.Value); +} +void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, + unsigned Index, + InMemoryStruct &Res) const { + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::Symbol64TableEntry)); + ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); +} diff --git a/final/lib/Object/Makefile b/final/lib/Object/Makefile new file mode 100644 index 00000000000..79388dc97f1 --- /dev/null +++ b/final/lib/Object/Makefile @@ -0,0 +1,14 @@ +##===- lib/Object/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMObject +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/final/lib/Object/ObjectFile.cpp b/final/lib/Object/ObjectFile.cpp new file mode 100644 index 00000000000..161ae3a083f --- /dev/null +++ b/final/lib/Object/ObjectFile.cpp @@ -0,0 +1,71 @@ +//===- ObjectFile.cpp - File format independent object 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 defines a file format independent ObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ObjectFile.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/system_error.h" + +using namespace llvm; +using namespace object; + +ObjectFile::ObjectFile(MemoryBuffer *Object) + : MapFile(Object) { + assert(MapFile && "Must be a valid MemoryBuffer!"); + base = reinterpret_cast(MapFile->getBufferStart()); +} + +ObjectFile::~ObjectFile() { + delete MapFile; +} + +StringRef ObjectFile::getFilename() const { + return MapFile->getBufferIdentifier(); +} + +ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { + if (!Object || Object->getBufferSize() < 64) + return 0; + sys::LLVMFileType type = sys::IdentifyFileType(Object->getBufferStart(), + static_cast(Object->getBufferSize())); + switch (type) { + case sys::ELF_Relocatable_FileType: + case sys::ELF_Executable_FileType: + case sys::ELF_SharedObject_FileType: + case sys::ELF_Core_FileType: + return createELFObjectFile(Object); + case sys::Mach_O_Object_FileType: + case sys::Mach_O_Executable_FileType: + case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: + case sys::Mach_O_Core_FileType: + case sys::Mach_O_PreloadExecutable_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: + case sys::Mach_O_DynamicLinker_FileType: + case sys::Mach_O_Bundle_FileType: + case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: + return 0; + case sys::COFF_FileType: + return createCOFFObjectFile(Object); + default: + llvm_unreachable("Unknown Object File Type"); + } +} + +ObjectFile *ObjectFile::createObjectFile(StringRef ObjectPath) { + OwningPtr File; + if (error_code ec = MemoryBuffer::getFile(ObjectPath, File)) + return NULL; + return createObjectFile(File.take()); +} diff --git a/final/lib/Support/APFloat.cpp b/final/lib/Support/APFloat.cpp new file mode 100644 index 00000000000..93806facff0 --- /dev/null +++ b/final/lib/Support/APFloat.cpp @@ -0,0 +1,3564 @@ +//===-- APFloat.cpp - Implement APFloat class -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision floating +// point values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include +#include + +using namespace llvm; + +#define convolve(lhs, rhs) ((lhs) * 4 + (rhs)) + +/* Assumed in hexadecimal significand parsing, and conversion to + hexadecimal strings. */ +#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] +COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0); + +namespace llvm { + + /* Represents floating point arithmetic semantics. */ + struct fltSemantics { + /* The largest E such that 2^E is representable; this matches the + definition of IEEE 754. */ + exponent_t maxExponent; + + /* The smallest E such that 2^E is a normalized number; this + matches the definition of IEEE 754. */ + exponent_t minExponent; + + /* Number of bits in the significand. This includes the integer + bit. */ + unsigned int precision; + + /* True if arithmetic is supported. */ + unsigned int arithmeticOK; + }; + + const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true }; + const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true }; + const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true }; + const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true }; + const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, true }; + const fltSemantics APFloat::Bogus = { 0, 0, 0, true }; + + // The PowerPC format consists of two doubles. It does not map cleanly + // onto the usual format above. For now only storage of constants of + // this type is supported, no arithmetic. + const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022, 106, false }; + + /* A tight upper bound on number of parts required to hold the value + pow(5, power) is + + power * 815 / (351 * integerPartWidth) + 1 + + However, whilst the result may require only this many parts, + because we are multiplying two values to get it, the + multiplication may require an extra part with the excess part + being zero (consider the trivial case of 1 * 1, tcFullMultiply + requires two parts to hold the single-part result). So we add an + extra one to guarantee enough space whilst multiplying. */ + const unsigned int maxExponent = 16383; + const unsigned int maxPrecision = 113; + const unsigned int maxPowerOfFiveExponent = maxExponent + maxPrecision - 1; + const unsigned int maxPowerOfFiveParts = 2 + ((maxPowerOfFiveExponent * 815) + / (351 * integerPartWidth)); +} + +/* A bunch of private, handy routines. */ + +static inline unsigned int +partCountForBits(unsigned int bits) +{ + return ((bits) + integerPartWidth - 1) / integerPartWidth; +} + +/* Returns 0U-9U. Return values >= 10U are not digits. */ +static inline unsigned int +decDigitValue(unsigned int c) +{ + return c - '0'; +} + +static unsigned int +hexDigitValue(unsigned int c) +{ + unsigned int r; + + r = c - '0'; + if (r <= 9) + return r; + + r = c - 'A'; + if (r <= 5) + return r + 10; + + r = c - 'a'; + if (r <= 5) + return r + 10; + + return -1U; +} + +static inline void +assertArithmeticOK(const llvm::fltSemantics &semantics) { + assert(semantics.arithmeticOK && + "Compile-time arithmetic does not support these semantics"); +} + +/* Return the value of a decimal exponent of the form + [+-]ddddddd. + + If the exponent overflows, returns a large exponent with the + appropriate sign. */ +static int +readExponent(StringRef::iterator begin, StringRef::iterator end) +{ + bool isNegative; + unsigned int absExponent; + const unsigned int overlargeExponent = 24000; /* FIXME. */ + StringRef::iterator p = begin; + + assert(p != end && "Exponent has no digits"); + + isNegative = (*p == '-'); + if (*p == '-' || *p == '+') { + p++; + assert(p != end && "Exponent has no digits"); + } + + absExponent = decDigitValue(*p++); + assert(absExponent < 10U && "Invalid character in exponent"); + + for (; p != end; ++p) { + unsigned int value; + + value = decDigitValue(*p); + assert(value < 10U && "Invalid character in exponent"); + + value += absExponent * 10; + if (absExponent >= overlargeExponent) { + absExponent = overlargeExponent; + p = end; /* outwit assert below */ + break; + } + absExponent = value; + } + + assert(p == end && "Invalid exponent in exponent"); + + if (isNegative) + return -(int) absExponent; + else + return (int) absExponent; +} + +/* This is ugly and needs cleaning up, but I don't immediately see + how whilst remaining safe. */ +static int +totalExponent(StringRef::iterator p, StringRef::iterator end, + int exponentAdjustment) +{ + int unsignedExponent; + bool negative, overflow; + int exponent = 0; + + assert(p != end && "Exponent has no digits"); + + negative = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + assert(p != end && "Exponent has no digits"); + } + + unsignedExponent = 0; + overflow = false; + for (; p != end; ++p) { + unsigned int value; + + value = decDigitValue(*p); + assert(value < 10U && "Invalid character in exponent"); + + unsignedExponent = unsignedExponent * 10 + value; + if (unsignedExponent > 32767) + overflow = true; + } + + if (exponentAdjustment > 32767 || exponentAdjustment < -32768) + overflow = true; + + if (!overflow) { + exponent = unsignedExponent; + if (negative) + exponent = -exponent; + exponent += exponentAdjustment; + if (exponent > 32767 || exponent < -32768) + overflow = true; + } + + if (overflow) + exponent = negative ? -32768: 32767; + + return exponent; +} + +static StringRef::iterator +skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, + StringRef::iterator *dot) +{ + StringRef::iterator p = begin; + *dot = end; + while (*p == '0' && p != end) + p++; + + if (*p == '.') { + *dot = p++; + + assert(end - begin != 1 && "Significand has no digits"); + + while (*p == '0' && p != end) + p++; + } + + return p; +} + +/* Given a normal decimal floating point number of the form + + dddd.dddd[eE][+-]ddd + + where the decimal point and exponent are optional, fill out the + structure D. Exponent is appropriate if the significand is + treated as an integer, and normalizedExponent if the significand + is taken to have the decimal point after a single leading + non-zero digit. + + If the value is zero, V->firstSigDigit points to a non-digit, and + the return exponent is zero. +*/ +struct decimalInfo { + const char *firstSigDigit; + const char *lastSigDigit; + int exponent; + int normalizedExponent; +}; + +static void +interpretDecimal(StringRef::iterator begin, StringRef::iterator end, + decimalInfo *D) +{ + StringRef::iterator dot = end; + StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot); + + D->firstSigDigit = p; + D->exponent = 0; + D->normalizedExponent = 0; + + for (; p != end; ++p) { + if (*p == '.') { + assert(dot == end && "String contains multiple dots"); + dot = p++; + if (p == end) + break; + } + if (decDigitValue(*p) >= 10U) + break; + } + + if (p != end) { + assert((*p == 'e' || *p == 'E') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); + + /* p points to the first non-digit in the string */ + D->exponent = readExponent(p + 1, end); + + /* Implied decimal point? */ + if (dot == end) + dot = p; + } + + /* If number is all zeroes accept any exponent. */ + if (p != D->firstSigDigit) { + /* Drop insignificant trailing zeroes. */ + if (p != begin) { + do + do + p--; + while (p != begin && *p == '0'); + while (p != begin && *p == '.'); + } + + /* Adjust the exponents for any decimal point. */ + D->exponent += static_cast((dot - p) - (dot > p)); + D->normalizedExponent = (D->exponent + + static_cast((p - D->firstSigDigit) + - (dot > D->firstSigDigit && dot < p))); + } + + D->lastSigDigit = p; +} + +/* Return the trailing fraction of a hexadecimal number. + DIGITVALUE is the first hex digit of the fraction, P points to + the next digit. */ +static lostFraction +trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end, + unsigned int digitValue) +{ + unsigned int hexDigit; + + /* If the first trailing digit isn't 0 or 8 we can work out the + fraction immediately. */ + if (digitValue > 8) + return lfMoreThanHalf; + else if (digitValue < 8 && digitValue > 0) + return lfLessThanHalf; + + /* Otherwise we need to find the first non-zero digit. */ + while (*p == '0') + p++; + + assert(p != end && "Invalid trailing hexadecimal fraction!"); + + hexDigit = hexDigitValue(*p); + + /* If we ran off the end it is exactly zero or one-half, otherwise + a little more. */ + if (hexDigit == -1U) + return digitValue == 0 ? lfExactlyZero: lfExactlyHalf; + else + return digitValue == 0 ? lfLessThanHalf: lfMoreThanHalf; +} + +/* Return the fraction lost were a bignum truncated losing the least + significant BITS bits. */ +static lostFraction +lostFractionThroughTruncation(const integerPart *parts, + unsigned int partCount, + unsigned int bits) +{ + unsigned int lsb; + + lsb = APInt::tcLSB(parts, partCount); + + /* Note this is guaranteed true if bits == 0, or LSB == -1U. */ + if (bits <= lsb) + return lfExactlyZero; + if (bits == lsb + 1) + return lfExactlyHalf; + if (bits <= partCount * integerPartWidth && + APInt::tcExtractBit(parts, bits - 1)) + return lfMoreThanHalf; + + return lfLessThanHalf; +} + +/* Shift DST right BITS bits noting lost fraction. */ +static lostFraction +shiftRight(integerPart *dst, unsigned int parts, unsigned int bits) +{ + lostFraction lost_fraction; + + lost_fraction = lostFractionThroughTruncation(dst, parts, bits); + + APInt::tcShiftRight(dst, parts, bits); + + return lost_fraction; +} + +/* Combine the effect of two lost fractions. */ +static lostFraction +combineLostFractions(lostFraction moreSignificant, + lostFraction lessSignificant) +{ + if (lessSignificant != lfExactlyZero) { + if (moreSignificant == lfExactlyZero) + moreSignificant = lfLessThanHalf; + else if (moreSignificant == lfExactlyHalf) + moreSignificant = lfMoreThanHalf; + } + + return moreSignificant; +} + +/* The error from the true value, in half-ulps, on multiplying two + floating point numbers, which differ from the value they + approximate by at most HUE1 and HUE2 half-ulps, is strictly less + than the returned value. + + See "How to Read Floating Point Numbers Accurately" by William D + Clinger. */ +static unsigned int +HUerrBound(bool inexactMultiply, unsigned int HUerr1, unsigned int HUerr2) +{ + assert(HUerr1 < 2 || HUerr2 < 2 || (HUerr1 + HUerr2 < 8)); + + if (HUerr1 + HUerr2 == 0) + return inexactMultiply * 2; /* <= inexactMultiply half-ulps. */ + else + return inexactMultiply + 2 * (HUerr1 + HUerr2); +} + +/* The number of ulps from the boundary (zero, or half if ISNEAREST) + when the least significant BITS are truncated. BITS cannot be + zero. */ +static integerPart +ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest) +{ + unsigned int count, partBits; + integerPart part, boundary; + + assert(bits != 0); + + bits--; + count = bits / integerPartWidth; + partBits = bits % integerPartWidth + 1; + + part = parts[count] & (~(integerPart) 0 >> (integerPartWidth - partBits)); + + if (isNearest) + boundary = (integerPart) 1 << (partBits - 1); + else + boundary = 0; + + if (count == 0) { + if (part - boundary <= boundary - part) + return part - boundary; + else + return boundary - part; + } + + if (part == boundary) { + while (--count) + if (parts[count]) + return ~(integerPart) 0; /* A lot. */ + + return parts[0]; + } else if (part == boundary - 1) { + while (--count) + if (~parts[count]) + return ~(integerPart) 0; /* A lot. */ + + return -parts[0]; + } + + return ~(integerPart) 0; /* A lot. */ +} + +/* Place pow(5, power) in DST, and return the number of parts used. + DST must be at least one part larger than size of the answer. */ +static unsigned int +powerOf5(integerPart *dst, unsigned int power) +{ + static const integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, + 15625, 78125 }; + integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; + pow5s[0] = 78125 * 5; + + unsigned int partsCount[16] = { 1 }; + integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; + unsigned int result; + assert(power <= maxExponent); + + p1 = dst; + p2 = scratch; + + *p1 = firstEightPowers[power & 7]; + power >>= 3; + + result = 1; + pow5 = pow5s; + + for (unsigned int n = 0; power; power >>= 1, n++) { + unsigned int pc; + + pc = partsCount[n]; + + /* Calculate pow(5,pow(2,n+3)) if we haven't yet. */ + if (pc == 0) { + pc = partsCount[n - 1]; + APInt::tcFullMultiply(pow5, pow5 - pc, pow5 - pc, pc, pc); + pc *= 2; + if (pow5[pc - 1] == 0) + pc--; + partsCount[n] = pc; + } + + if (power & 1) { + integerPart *tmp; + + APInt::tcFullMultiply(p2, p1, pow5, result, pc); + result += pc; + if (p2[result - 1] == 0) + result--; + + /* Now result is in p1 with partsCount parts and p2 is scratch + space. */ + tmp = p1, p1 = p2, p2 = tmp; + } + + pow5 += pc; + } + + if (p1 != dst) + APInt::tcAssign(dst, p1, result); + + return result; +} + +/* Zero at the end to avoid modular arithmetic when adding one; used + when rounding up during hexadecimal output. */ +static const char hexDigitsLower[] = "0123456789abcdef0"; +static const char hexDigitsUpper[] = "0123456789ABCDEF0"; +static const char infinityL[] = "infinity"; +static const char infinityU[] = "INFINITY"; +static const char NaNL[] = "nan"; +static const char NaNU[] = "NAN"; + +/* Write out an integerPart in hexadecimal, starting with the most + significant nibble. Write out exactly COUNT hexdigits, return + COUNT. */ +static unsigned int +partAsHex (char *dst, integerPart part, unsigned int count, + const char *hexDigitChars) +{ + unsigned int result = count; + + assert(count != 0 && count <= integerPartWidth / 4); + + part >>= (integerPartWidth - 4 * count); + while (count--) { + dst[count] = hexDigitChars[part & 0xf]; + part >>= 4; + } + + return result; +} + +/* Write out an unsigned decimal integer. */ +static char * +writeUnsignedDecimal (char *dst, unsigned int n) +{ + char buff[40], *p; + + p = buff; + do + *p++ = '0' + n % 10; + while (n /= 10); + + do + *dst++ = *--p; + while (p != buff); + + return dst; +} + +/* Write out a signed decimal integer. */ +static char * +writeSignedDecimal (char *dst, int value) +{ + if (value < 0) { + *dst++ = '-'; + dst = writeUnsignedDecimal(dst, -(unsigned) value); + } else + dst = writeUnsignedDecimal(dst, value); + + return dst; +} + +/* Constructors. */ +void +APFloat::initialize(const fltSemantics *ourSemantics) +{ + unsigned int count; + + semantics = ourSemantics; + count = partCount(); + if (count > 1) + significand.parts = new integerPart[count]; +} + +void +APFloat::freeSignificand() +{ + if (partCount() > 1) + delete [] significand.parts; +} + +void +APFloat::assign(const APFloat &rhs) +{ + assert(semantics == rhs.semantics); + + sign = rhs.sign; + category = rhs.category; + exponent = rhs.exponent; + sign2 = rhs.sign2; + exponent2 = rhs.exponent2; + if (category == fcNormal || category == fcNaN) + copySignificand(rhs); +} + +void +APFloat::copySignificand(const APFloat &rhs) +{ + assert(category == fcNormal || category == fcNaN); + assert(rhs.partCount() >= partCount()); + + APInt::tcAssign(significandParts(), rhs.significandParts(), + partCount()); +} + +/* Make this number a NaN, with an arbitrary but deterministic value + for the significand. If double or longer, this is a signalling NaN, + which may not be ideal. If float, this is QNaN(0). */ +void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) +{ + category = fcNaN; + sign = Negative; + + integerPart *significand = significandParts(); + unsigned numParts = partCount(); + + // Set the significand bits to the fill. + if (!fill || fill->getNumWords() < numParts) + APInt::tcSet(significand, 0, numParts); + if (fill) { + APInt::tcAssign(significand, fill->getRawData(), + std::min(fill->getNumWords(), numParts)); + + // Zero out the excess bits of the significand. + unsigned bitsToPreserve = semantics->precision - 1; + unsigned part = bitsToPreserve / 64; + bitsToPreserve %= 64; + significand[part] &= ((1ULL << bitsToPreserve) - 1); + for (part++; part != numParts; ++part) + significand[part] = 0; + } + + unsigned QNaNBit = semantics->precision - 2; + + if (SNaN) { + // We always have to clear the QNaN bit to make it an SNaN. + APInt::tcClearBit(significand, QNaNBit); + + // If there are no bits set in the payload, we have to set + // *something* to make it a NaN instead of an infinity; + // conventionally, this is the next bit down from the QNaN bit. + if (APInt::tcIsZero(significand, numParts)) + APInt::tcSetBit(significand, QNaNBit - 1); + } else { + // We always have to set the QNaN bit to make it a QNaN. + APInt::tcSetBit(significand, QNaNBit); + } + + // For x87 extended precision, we want to make a NaN, not a + // pseudo-NaN. Maybe we should expose the ability to make + // pseudo-NaNs? + if (semantics == &APFloat::x87DoubleExtended) + APInt::tcSetBit(significand, QNaNBit + 1); +} + +APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill) { + APFloat value(Sem, uninitialized); + value.makeNaN(SNaN, Negative, fill); + return value; +} + +APFloat & +APFloat::operator=(const APFloat &rhs) +{ + if (this != &rhs) { + if (semantics != rhs.semantics) { + freeSignificand(); + initialize(rhs.semantics); + } + assign(rhs); + } + + return *this; +} + +bool +APFloat::bitwiseIsEqual(const APFloat &rhs) const { + if (this == &rhs) + return true; + if (semantics != rhs.semantics || + category != rhs.category || + sign != rhs.sign) + return false; + if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && + sign2 != rhs.sign2) + return false; + if (category==fcZero || category==fcInfinity) + return true; + else if (category==fcNormal && exponent!=rhs.exponent) + return false; + else if (semantics==(const llvm::fltSemantics*)&PPCDoubleDouble && + exponent2!=rhs.exponent2) + return false; + else { + int i= partCount(); + const integerPart* p=significandParts(); + const integerPart* q=rhs.significandParts(); + for (; i>0; i--, p++, q++) { + if (*p != *q) + return false; + } + return true; + } +} + +APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) + : exponent2(0), sign2(0) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + sign = 0; + zeroSignificand(); + exponent = ourSemantics.precision - 1; + significandParts()[0] = value; + normalize(rmNearestTiesToEven, lfExactlyZero); +} + +APFloat::APFloat(const fltSemantics &ourSemantics) : exponent2(0), sign2(0) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + category = fcZero; + sign = false; +} + +APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) + : exponent2(0), sign2(0) { + assertArithmeticOK(ourSemantics); + // Allocates storage if necessary but does not initialize it. + initialize(&ourSemantics); +} + +APFloat::APFloat(const fltSemantics &ourSemantics, + fltCategory ourCategory, bool negative) + : exponent2(0), sign2(0) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + category = ourCategory; + sign = negative; + if (category == fcNormal) + category = fcZero; + else if (ourCategory == fcNaN) + makeNaN(); +} + +APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text) + : exponent2(0), sign2(0) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + convertFromString(text, rmNearestTiesToEven); +} + +APFloat::APFloat(const APFloat &rhs) : exponent2(0), sign2(0) { + initialize(rhs.semantics); + assign(rhs); +} + +APFloat::~APFloat() +{ + freeSignificand(); +} + +// Profile - This method 'profiles' an APFloat for use with FoldingSet. +void APFloat::Profile(FoldingSetNodeID& ID) const { + ID.Add(bitcastToAPInt()); +} + +unsigned int +APFloat::partCount() const +{ + return partCountForBits(semantics->precision + 1); +} + +unsigned int +APFloat::semanticsPrecision(const fltSemantics &semantics) +{ + return semantics.precision; +} + +const integerPart * +APFloat::significandParts() const +{ + return const_cast(this)->significandParts(); +} + +integerPart * +APFloat::significandParts() +{ + assert(category == fcNormal || category == fcNaN); + + if (partCount() > 1) + return significand.parts; + else + return &significand.part; +} + +void +APFloat::zeroSignificand() +{ + category = fcNormal; + APInt::tcSet(significandParts(), 0, partCount()); +} + +/* Increment an fcNormal floating point number's significand. */ +void +APFloat::incrementSignificand() +{ + integerPart carry; + + carry = APInt::tcIncrement(significandParts(), partCount()); + + /* Our callers should never cause us to overflow. */ + assert(carry == 0); +} + +/* Add the significand of the RHS. Returns the carry flag. */ +integerPart +APFloat::addSignificand(const APFloat &rhs) +{ + integerPart *parts; + + parts = significandParts(); + + assert(semantics == rhs.semantics); + assert(exponent == rhs.exponent); + + return APInt::tcAdd(parts, rhs.significandParts(), 0, partCount()); +} + +/* Subtract the significand of the RHS with a borrow flag. Returns + the borrow flag. */ +integerPart +APFloat::subtractSignificand(const APFloat &rhs, integerPart borrow) +{ + integerPart *parts; + + parts = significandParts(); + + assert(semantics == rhs.semantics); + assert(exponent == rhs.exponent); + + return APInt::tcSubtract(parts, rhs.significandParts(), borrow, + partCount()); +} + +/* Multiply the significand of the RHS. If ADDEND is non-NULL, add it + on to the full-precision result of the multiplication. Returns the + lost fraction. */ +lostFraction +APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) +{ + unsigned int omsb; // One, not zero, based MSB. + unsigned int partsCount, newPartsCount, precision; + integerPart *lhsSignificand; + integerPart scratch[4]; + integerPart *fullSignificand; + lostFraction lost_fraction; + bool ignored; + + assert(semantics == rhs.semantics); + + precision = semantics->precision; + newPartsCount = partCountForBits(precision * 2); + + if (newPartsCount > 4) + fullSignificand = new integerPart[newPartsCount]; + else + fullSignificand = scratch; + + lhsSignificand = significandParts(); + partsCount = partCount(); + + APInt::tcFullMultiply(fullSignificand, lhsSignificand, + rhs.significandParts(), partsCount, partsCount); + + lost_fraction = lfExactlyZero; + omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1; + exponent += rhs.exponent; + + if (addend) { + Significand savedSignificand = significand; + const fltSemantics *savedSemantics = semantics; + fltSemantics extendedSemantics; + opStatus status; + unsigned int extendedPrecision; + + /* Normalize our MSB. */ + extendedPrecision = precision + precision - 1; + if (omsb != extendedPrecision) { + APInt::tcShiftLeft(fullSignificand, newPartsCount, + extendedPrecision - omsb); + exponent -= extendedPrecision - omsb; + } + + /* Create new semantics. */ + extendedSemantics = *semantics; + extendedSemantics.precision = extendedPrecision; + + if (newPartsCount == 1) + significand.part = fullSignificand[0]; + else + significand.parts = fullSignificand; + semantics = &extendedSemantics; + + APFloat extendedAddend(*addend); + status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); + assert(status == opOK); + lost_fraction = addOrSubtractSignificand(extendedAddend, false); + + /* Restore our state. */ + if (newPartsCount == 1) + fullSignificand[0] = significand.part; + significand = savedSignificand; + semantics = savedSemantics; + + omsb = APInt::tcMSB(fullSignificand, newPartsCount) + 1; + } + + exponent -= (precision - 1); + + if (omsb > precision) { + unsigned int bits, significantParts; + lostFraction lf; + + bits = omsb - precision; + significantParts = partCountForBits(omsb); + lf = shiftRight(fullSignificand, significantParts, bits); + lost_fraction = combineLostFractions(lf, lost_fraction); + exponent += bits; + } + + APInt::tcAssign(lhsSignificand, fullSignificand, partsCount); + + if (newPartsCount > 4) + delete [] fullSignificand; + + return lost_fraction; +} + +/* Multiply the significands of LHS and RHS to DST. */ +lostFraction +APFloat::divideSignificand(const APFloat &rhs) +{ + unsigned int bit, i, partsCount; + const integerPart *rhsSignificand; + integerPart *lhsSignificand, *dividend, *divisor; + integerPart scratch[4]; + lostFraction lost_fraction; + + assert(semantics == rhs.semantics); + + lhsSignificand = significandParts(); + rhsSignificand = rhs.significandParts(); + partsCount = partCount(); + + if (partsCount > 2) + dividend = new integerPart[partsCount * 2]; + else + dividend = scratch; + + divisor = dividend + partsCount; + + /* Copy the dividend and divisor as they will be modified in-place. */ + for (i = 0; i < partsCount; i++) { + dividend[i] = lhsSignificand[i]; + divisor[i] = rhsSignificand[i]; + lhsSignificand[i] = 0; + } + + exponent -= rhs.exponent; + + unsigned int precision = semantics->precision; + + /* Normalize the divisor. */ + bit = precision - APInt::tcMSB(divisor, partsCount) - 1; + if (bit) { + exponent += bit; + APInt::tcShiftLeft(divisor, partsCount, bit); + } + + /* Normalize the dividend. */ + bit = precision - APInt::tcMSB(dividend, partsCount) - 1; + if (bit) { + exponent -= bit; + APInt::tcShiftLeft(dividend, partsCount, bit); + } + + /* Ensure the dividend >= divisor initially for the loop below. + Incidentally, this means that the division loop below is + guaranteed to set the integer bit to one. */ + if (APInt::tcCompare(dividend, divisor, partsCount) < 0) { + exponent--; + APInt::tcShiftLeft(dividend, partsCount, 1); + assert(APInt::tcCompare(dividend, divisor, partsCount) >= 0); + } + + /* Long division. */ + for (bit = precision; bit; bit -= 1) { + if (APInt::tcCompare(dividend, divisor, partsCount) >= 0) { + APInt::tcSubtract(dividend, divisor, 0, partsCount); + APInt::tcSetBit(lhsSignificand, bit - 1); + } + + APInt::tcShiftLeft(dividend, partsCount, 1); + } + + /* Figure out the lost fraction. */ + int cmp = APInt::tcCompare(dividend, divisor, partsCount); + + if (cmp > 0) + lost_fraction = lfMoreThanHalf; + else if (cmp == 0) + lost_fraction = lfExactlyHalf; + else if (APInt::tcIsZero(dividend, partsCount)) + lost_fraction = lfExactlyZero; + else + lost_fraction = lfLessThanHalf; + + if (partsCount > 2) + delete [] dividend; + + return lost_fraction; +} + +unsigned int +APFloat::significandMSB() const +{ + return APInt::tcMSB(significandParts(), partCount()); +} + +unsigned int +APFloat::significandLSB() const +{ + return APInt::tcLSB(significandParts(), partCount()); +} + +/* Note that a zero result is NOT normalized to fcZero. */ +lostFraction +APFloat::shiftSignificandRight(unsigned int bits) +{ + /* Our exponent should not overflow. */ + assert((exponent_t) (exponent + bits) >= exponent); + + exponent += bits; + + return shiftRight(significandParts(), partCount(), bits); +} + +/* Shift the significand left BITS bits, subtract BITS from its exponent. */ +void +APFloat::shiftSignificandLeft(unsigned int bits) +{ + assert(bits < semantics->precision); + + if (bits) { + unsigned int partsCount = partCount(); + + APInt::tcShiftLeft(significandParts(), partsCount, bits); + exponent -= bits; + + assert(!APInt::tcIsZero(significandParts(), partsCount)); + } +} + +APFloat::cmpResult +APFloat::compareAbsoluteValue(const APFloat &rhs) const +{ + int compare; + + assert(semantics == rhs.semantics); + assert(category == fcNormal); + assert(rhs.category == fcNormal); + + compare = exponent - rhs.exponent; + + /* If exponents are equal, do an unsigned bignum comparison of the + significands. */ + if (compare == 0) + compare = APInt::tcCompare(significandParts(), rhs.significandParts(), + partCount()); + + if (compare > 0) + return cmpGreaterThan; + else if (compare < 0) + return cmpLessThan; + else + return cmpEqual; +} + +/* Handle overflow. Sign is preserved. We either become infinity or + the largest finite number. */ +APFloat::opStatus +APFloat::handleOverflow(roundingMode rounding_mode) +{ + /* Infinity? */ + if (rounding_mode == rmNearestTiesToEven || + rounding_mode == rmNearestTiesToAway || + (rounding_mode == rmTowardPositive && !sign) || + (rounding_mode == rmTowardNegative && sign)) { + category = fcInfinity; + return (opStatus) (opOverflow | opInexact); + } + + /* Otherwise we become the largest finite number. */ + category = fcNormal; + exponent = semantics->maxExponent; + APInt::tcSetLeastSignificantBits(significandParts(), partCount(), + semantics->precision); + + return opInexact; +} + +/* Returns TRUE if, when truncating the current number, with BIT the + new LSB, with the given lost fraction and rounding mode, the result + would need to be rounded away from zero (i.e., by increasing the + signficand). This routine must work for fcZero of both signs, and + fcNormal numbers. */ +bool +APFloat::roundAwayFromZero(roundingMode rounding_mode, + lostFraction lost_fraction, + unsigned int bit) const +{ + /* NaNs and infinities should not have lost fractions. */ + assert(category == fcNormal || category == fcZero); + + /* Current callers never pass this so we don't handle it. */ + assert(lost_fraction != lfExactlyZero); + + switch (rounding_mode) { + default: + llvm_unreachable(0); + + case rmNearestTiesToAway: + return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf; + + case rmNearestTiesToEven: + if (lost_fraction == lfMoreThanHalf) + return true; + + /* Our zeroes don't have a significand to test. */ + if (lost_fraction == lfExactlyHalf && category != fcZero) + return APInt::tcExtractBit(significandParts(), bit); + + return false; + + case rmTowardZero: + return false; + + case rmTowardPositive: + return sign == false; + + case rmTowardNegative: + return sign == true; + } +} + +APFloat::opStatus +APFloat::normalize(roundingMode rounding_mode, + lostFraction lost_fraction) +{ + unsigned int omsb; /* One, not zero, based MSB. */ + int exponentChange; + + if (category != fcNormal) + return opOK; + + /* Before rounding normalize the exponent of fcNormal numbers. */ + omsb = significandMSB() + 1; + + if (omsb) { + /* OMSB is numbered from 1. We want to place it in the integer + bit numbered PRECISON if possible, with a compensating change in + the exponent. */ + exponentChange = omsb - semantics->precision; + + /* If the resulting exponent is too high, overflow according to + the rounding mode. */ + if (exponent + exponentChange > semantics->maxExponent) + return handleOverflow(rounding_mode); + + /* Subnormal numbers have exponent minExponent, and their MSB + is forced based on that. */ + if (exponent + exponentChange < semantics->minExponent) + exponentChange = semantics->minExponent - exponent; + + /* Shifting left is easy as we don't lose precision. */ + if (exponentChange < 0) { + assert(lost_fraction == lfExactlyZero); + + shiftSignificandLeft(-exponentChange); + + return opOK; + } + + if (exponentChange > 0) { + lostFraction lf; + + /* Shift right and capture any new lost fraction. */ + lf = shiftSignificandRight(exponentChange); + + lost_fraction = combineLostFractions(lf, lost_fraction); + + /* Keep OMSB up-to-date. */ + if (omsb > (unsigned) exponentChange) + omsb -= exponentChange; + else + omsb = 0; + } + } + + /* Now round the number according to rounding_mode given the lost + fraction. */ + + /* As specified in IEEE 754, since we do not trap we do not report + underflow for exact results. */ + if (lost_fraction == lfExactlyZero) { + /* Canonicalize zeroes. */ + if (omsb == 0) + category = fcZero; + + return opOK; + } + + /* Increment the significand if we're rounding away from zero. */ + if (roundAwayFromZero(rounding_mode, lost_fraction, 0)) { + if (omsb == 0) + exponent = semantics->minExponent; + + incrementSignificand(); + omsb = significandMSB() + 1; + + /* Did the significand increment overflow? */ + if (omsb == (unsigned) semantics->precision + 1) { + /* Renormalize by incrementing the exponent and shifting our + significand right one. However if we already have the + maximum exponent we overflow to infinity. */ + if (exponent == semantics->maxExponent) { + category = fcInfinity; + + return (opStatus) (opOverflow | opInexact); + } + + shiftSignificandRight(1); + + return opInexact; + } + } + + /* The normal case - we were and are not denormal, and any + significand increment above didn't overflow. */ + if (omsb == semantics->precision) + return opInexact; + + /* We have a non-zero denormal. */ + assert(omsb < semantics->precision); + + /* Canonicalize zeroes. */ + if (omsb == 0) + category = fcZero; + + /* The fcZero case is a denormal that underflowed to zero. */ + return (opStatus) (opUnderflow | opInexact); +} + +APFloat::opStatus +APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcNormal, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcZero): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + case convolve(fcZero, fcInfinity): + category = fcInfinity; + sign = rhs.sign ^ subtract; + return opOK; + + case convolve(fcZero, fcNormal): + assign(rhs); + sign = rhs.sign ^ subtract; + return opOK; + + case convolve(fcZero, fcZero): + /* Sign depends on rounding mode; handled by caller. */ + return opOK; + + case convolve(fcInfinity, fcInfinity): + /* Differently signed infinities can only be validly + subtracted. */ + if (((sign ^ rhs.sign)!=0) != subtract) { + makeNaN(); + return opInvalidOp; + } + + return opOK; + + case convolve(fcNormal, fcNormal): + return opDivByZero; + } +} + +/* Add or subtract two normal numbers. */ +lostFraction +APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) +{ + integerPart carry; + lostFraction lost_fraction; + int bits; + + /* Determine if the operation on the absolute values is effectively + an addition or subtraction. */ + subtract ^= (sign ^ rhs.sign) ? true : false; + + /* Are we bigger exponent-wise than the RHS? */ + bits = exponent - rhs.exponent; + + /* Subtraction is more subtle than one might naively expect. */ + if (subtract) { + APFloat temp_rhs(rhs); + bool reverse; + + if (bits == 0) { + reverse = compareAbsoluteValue(temp_rhs) == cmpLessThan; + lost_fraction = lfExactlyZero; + } else if (bits > 0) { + lost_fraction = temp_rhs.shiftSignificandRight(bits - 1); + shiftSignificandLeft(1); + reverse = false; + } else { + lost_fraction = shiftSignificandRight(-bits - 1); + temp_rhs.shiftSignificandLeft(1); + reverse = true; + } + + if (reverse) { + carry = temp_rhs.subtractSignificand + (*this, lost_fraction != lfExactlyZero); + copySignificand(temp_rhs); + sign = !sign; + } else { + carry = subtractSignificand + (temp_rhs, lost_fraction != lfExactlyZero); + } + + /* Invert the lost fraction - it was on the RHS and + subtracted. */ + if (lost_fraction == lfLessThanHalf) + lost_fraction = lfMoreThanHalf; + else if (lost_fraction == lfMoreThanHalf) + lost_fraction = lfLessThanHalf; + + /* The code above is intended to ensure that no borrow is + necessary. */ + assert(!carry); + } else { + if (bits > 0) { + APFloat temp_rhs(rhs); + + lost_fraction = temp_rhs.shiftSignificandRight(bits); + carry = addSignificand(temp_rhs); + } else { + lost_fraction = shiftSignificandRight(-bits); + carry = addSignificand(rhs); + } + + /* We have a guard bit; generating a carry cannot happen. */ + assert(!carry); + } + + return lost_fraction; +} + +APFloat::opStatus +APFloat::multiplySpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcInfinity): + category = fcInfinity; + return opOK; + + case convolve(fcZero, fcNormal): + case convolve(fcNormal, fcZero): + case convolve(fcZero, fcZero): + category = fcZero; + return opOK; + + case convolve(fcZero, fcInfinity): + case convolve(fcInfinity, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +APFloat::opStatus +APFloat::divideSpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcInfinity, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcInfinity): + category = fcZero; + return opOK; + + case convolve(fcNormal, fcZero): + category = fcInfinity; + return opDivByZero; + + case convolve(fcInfinity, fcInfinity): + case convolve(fcZero, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +APFloat::opStatus +APFloat::modSpecials(const APFloat &rhs) +{ + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + case convolve(fcNormal, fcInfinity): + return opOK; + + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + category = fcNaN; + copySignificand(rhs); + return opOK; + + case convolve(fcNormal, fcZero): + case convolve(fcInfinity, fcZero): + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcInfinity): + case convolve(fcZero, fcZero): + makeNaN(); + return opInvalidOp; + + case convolve(fcNormal, fcNormal): + return opOK; + } +} + +/* Change sign. */ +void +APFloat::changeSign() +{ + /* Look mummy, this one's easy. */ + sign = !sign; +} + +void +APFloat::clearSign() +{ + /* So is this one. */ + sign = 0; +} + +void +APFloat::copySign(const APFloat &rhs) +{ + /* And this one. */ + sign = rhs.sign; +} + +/* Normalized addition or subtraction. */ +APFloat::opStatus +APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode, + bool subtract) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + + fs = addOrSubtractSpecials(rhs, subtract); + + /* This return code means it was not a simple case. */ + if (fs == opDivByZero) { + lostFraction lost_fraction; + + lost_fraction = addOrSubtractSignificand(rhs, subtract); + fs = normalize(rounding_mode, lost_fraction); + + /* Can only be zero if we lost no fraction. */ + assert(category != fcZero || lost_fraction == lfExactlyZero); + } + + /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a + positive zero unless rounding to minus infinity, except that + adding two like-signed zeroes gives that zero. */ + if (category == fcZero) { + if (rhs.category != fcZero || (sign == rhs.sign) == subtract) + sign = (rounding_mode == rmTowardNegative); + } + + return fs; +} + +/* Normalized addition. */ +APFloat::opStatus +APFloat::add(const APFloat &rhs, roundingMode rounding_mode) +{ + return addOrSubtract(rhs, rounding_mode, false); +} + +/* Normalized subtraction. */ +APFloat::opStatus +APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode) +{ + return addOrSubtract(rhs, rounding_mode, true); +} + +/* Normalized multiply. */ +APFloat::opStatus +APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + sign ^= rhs.sign; + fs = multiplySpecials(rhs); + + if (category == fcNormal) { + lostFraction lost_fraction = multiplySignificand(rhs, 0); + fs = normalize(rounding_mode, lost_fraction); + if (lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + } + + return fs; +} + +/* Normalized divide. */ +APFloat::opStatus +APFloat::divide(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + sign ^= rhs.sign; + fs = divideSpecials(rhs); + + if (category == fcNormal) { + lostFraction lost_fraction = divideSignificand(rhs); + fs = normalize(rounding_mode, lost_fraction); + if (lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + } + + return fs; +} + +/* Normalized remainder. This is not currently correct in all cases. */ +APFloat::opStatus +APFloat::remainder(const APFloat &rhs) +{ + opStatus fs; + APFloat V = *this; + unsigned int origSign = sign; + + assertArithmeticOK(*semantics); + fs = V.divide(rhs, rmNearestTiesToEven); + if (fs == opDivByZero) + return fs; + + int parts = partCount(); + integerPart *x = new integerPart[parts]; + bool ignored; + fs = V.convertToInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven, &ignored); + if (fs==opInvalidOp) + return fs; + + fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven); + assert(fs==opOK); // should always work + + fs = V.multiply(rhs, rmNearestTiesToEven); + assert(fs==opOK || fs==opInexact); // should not overflow or underflow + + fs = subtract(V, rmNearestTiesToEven); + assert(fs==opOK || fs==opInexact); // likewise + + if (isZero()) + sign = origSign; // IEEE754 requires this + delete[] x; + return fs; +} + +/* Normalized llvm frem (C fmod). + This is not currently correct in all cases. */ +APFloat::opStatus +APFloat::mod(const APFloat &rhs, roundingMode rounding_mode) +{ + opStatus fs; + assertArithmeticOK(*semantics); + fs = modSpecials(rhs); + + if (category == fcNormal && rhs.category == fcNormal) { + APFloat V = *this; + unsigned int origSign = sign; + + fs = V.divide(rhs, rmNearestTiesToEven); + if (fs == opDivByZero) + return fs; + + int parts = partCount(); + integerPart *x = new integerPart[parts]; + bool ignored; + fs = V.convertToInteger(x, parts * integerPartWidth, true, + rmTowardZero, &ignored); + if (fs==opInvalidOp) + return fs; + + fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true, + rmNearestTiesToEven); + assert(fs==opOK); // should always work + + fs = V.multiply(rhs, rounding_mode); + assert(fs==opOK || fs==opInexact); // should not overflow or underflow + + fs = subtract(V, rounding_mode); + assert(fs==opOK || fs==opInexact); // likewise + + if (isZero()) + sign = origSign; // IEEE754 requires this + delete[] x; + } + return fs; +} + +/* Normalized fused-multiply-add. */ +APFloat::opStatus +APFloat::fusedMultiplyAdd(const APFloat &multiplicand, + const APFloat &addend, + roundingMode rounding_mode) +{ + opStatus fs; + + assertArithmeticOK(*semantics); + + /* Post-multiplication sign, before addition. */ + sign ^= multiplicand.sign; + + /* If and only if all arguments are normal do we need to do an + extended-precision calculation. */ + if (category == fcNormal && + multiplicand.category == fcNormal && + addend.category == fcNormal) { + lostFraction lost_fraction; + + lost_fraction = multiplySignificand(multiplicand, &addend); + fs = normalize(rounding_mode, lost_fraction); + if (lost_fraction != lfExactlyZero) + fs = (opStatus) (fs | opInexact); + + /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a + positive zero unless rounding to minus infinity, except that + adding two like-signed zeroes gives that zero. */ + if (category == fcZero && sign != addend.sign) + sign = (rounding_mode == rmTowardNegative); + } else { + fs = multiplySpecials(multiplicand); + + /* FS can only be opOK or opInvalidOp. There is no more work + to do in the latter case. The IEEE-754R standard says it is + implementation-defined in this case whether, if ADDEND is a + quiet NaN, we raise invalid op; this implementation does so. + + If we need to do the addition we can do so with normal + precision. */ + if (fs == opOK) + fs = addOrSubtract(addend, rounding_mode, false); + } + + return fs; +} + +/* Comparison requires normalized numbers. */ +APFloat::cmpResult +APFloat::compare(const APFloat &rhs) const +{ + cmpResult result; + + assertArithmeticOK(*semantics); + assert(semantics == rhs.semantics); + + switch (convolve(category, rhs.category)) { + default: + llvm_unreachable(0); + + case convolve(fcNaN, fcZero): + case convolve(fcNaN, fcNormal): + case convolve(fcNaN, fcInfinity): + case convolve(fcNaN, fcNaN): + case convolve(fcZero, fcNaN): + case convolve(fcNormal, fcNaN): + case convolve(fcInfinity, fcNaN): + return cmpUnordered; + + case convolve(fcInfinity, fcNormal): + case convolve(fcInfinity, fcZero): + case convolve(fcNormal, fcZero): + if (sign) + return cmpLessThan; + else + return cmpGreaterThan; + + case convolve(fcNormal, fcInfinity): + case convolve(fcZero, fcInfinity): + case convolve(fcZero, fcNormal): + if (rhs.sign) + return cmpGreaterThan; + else + return cmpLessThan; + + case convolve(fcInfinity, fcInfinity): + if (sign == rhs.sign) + return cmpEqual; + else if (sign) + return cmpLessThan; + else + return cmpGreaterThan; + + case convolve(fcZero, fcZero): + return cmpEqual; + + case convolve(fcNormal, fcNormal): + break; + } + + /* Two normal numbers. Do they have the same sign? */ + if (sign != rhs.sign) { + if (sign) + result = cmpLessThan; + else + result = cmpGreaterThan; + } else { + /* Compare absolute values; invert result if negative. */ + result = compareAbsoluteValue(rhs); + + if (sign) { + if (result == cmpLessThan) + result = cmpGreaterThan; + else if (result == cmpGreaterThan) + result = cmpLessThan; + } + } + + return result; +} + +/// APFloat::convert - convert a value of one floating point type to another. +/// The return value corresponds to the IEEE754 exceptions. *losesInfo +/// records whether the transformation lost information, i.e. whether +/// converting the result back to the original type will produce the +/// original value (this is almost the same as return value==fsOK, but there +/// are edge cases where this is not so). + +APFloat::opStatus +APFloat::convert(const fltSemantics &toSemantics, + roundingMode rounding_mode, bool *losesInfo) +{ + lostFraction lostFraction; + unsigned int newPartCount, oldPartCount; + opStatus fs; + + assertArithmeticOK(*semantics); + assertArithmeticOK(toSemantics); + lostFraction = lfExactlyZero; + newPartCount = partCountForBits(toSemantics.precision + 1); + oldPartCount = partCount(); + + /* Handle storage complications. If our new form is wider, + re-allocate our bit pattern into wider storage. If it is + narrower, we ignore the excess parts, but if narrowing to a + single part we need to free the old storage. + Be careful not to reference significandParts for zeroes + and infinities, since it aborts. */ + if (newPartCount > oldPartCount) { + integerPart *newParts; + newParts = new integerPart[newPartCount]; + APInt::tcSet(newParts, 0, newPartCount); + if (category==fcNormal || category==fcNaN) + APInt::tcAssign(newParts, significandParts(), oldPartCount); + freeSignificand(); + significand.parts = newParts; + } else if (newPartCount < oldPartCount) { + /* Capture any lost fraction through truncation of parts so we get + correct rounding whilst normalizing. */ + if (category==fcNormal) + lostFraction = lostFractionThroughTruncation + (significandParts(), oldPartCount, toSemantics.precision); + if (newPartCount == 1) { + integerPart newPart = 0; + if (category==fcNormal || category==fcNaN) + newPart = significandParts()[0]; + freeSignificand(); + significand.part = newPart; + } + } + + if (category == fcNormal) { + /* Re-interpret our bit-pattern. */ + exponent += toSemantics.precision - semantics->precision; + semantics = &toSemantics; + fs = normalize(rounding_mode, lostFraction); + *losesInfo = (fs != opOK); + } else if (category == fcNaN) { + int shift = toSemantics.precision - semantics->precision; + // Do this now so significandParts gets the right answer + const fltSemantics *oldSemantics = semantics; + semantics = &toSemantics; + *losesInfo = false; + // No normalization here, just truncate + if (shift>0) + APInt::tcShiftLeft(significandParts(), newPartCount, shift); + else if (shift < 0) { + unsigned ushift = -shift; + // Figure out if we are losing information. This happens + // if are shifting out something other than 0s, or if the x87 long + // double input did not have its integer bit set (pseudo-NaN), or if the + // x87 long double input did not have its QNan bit set (because the x87 + // hardware sets this bit when converting a lower-precision NaN to + // x87 long double). + if (APInt::tcLSB(significandParts(), newPartCount) < ushift) + *losesInfo = true; + if (oldSemantics == &APFloat::x87DoubleExtended && + (!(*significandParts() & 0x8000000000000000ULL) || + !(*significandParts() & 0x4000000000000000ULL))) + *losesInfo = true; + APInt::tcShiftRight(significandParts(), newPartCount, ushift); + } + // gcc forces the Quiet bit on, which means (float)(double)(float_sNan) + // does not give you back the same bits. This is dubious, and we + // don't currently do it. You're really supposed to get + // an invalid operation signal at runtime, but nobody does that. + fs = opOK; + } else { + semantics = &toSemantics; + fs = opOK; + *losesInfo = false; + } + + return fs; +} + +/* Convert a floating point number to an integer according to the + rounding mode. If the rounded integer value is out of range this + returns an invalid operation exception and the contents of the + destination parts are unspecified. If the rounded value is in + range but the floating point number is not the exact integer, the C + standard doesn't require an inexact exception to be raised. IEEE + 854 does require it so we do that. + + Note that for conversions to integer type the C standard requires + round-to-zero to always be used. */ +APFloat::opStatus +APFloat::convertToSignExtendedInteger(integerPart *parts, unsigned int width, + bool isSigned, + roundingMode rounding_mode, + bool *isExact) const +{ + lostFraction lost_fraction; + const integerPart *src; + unsigned int dstPartsCount, truncatedBits; + + assertArithmeticOK(*semantics); + + *isExact = false; + + /* Handle the three special cases first. */ + if (category == fcInfinity || category == fcNaN) + return opInvalidOp; + + dstPartsCount = partCountForBits(width); + + if (category == fcZero) { + APInt::tcSet(parts, 0, dstPartsCount); + // Negative zero can't be represented as an int. + *isExact = !sign; + return opOK; + } + + src = significandParts(); + + /* Step 1: place our absolute value, with any fraction truncated, in + the destination. */ + if (exponent < 0) { + /* Our absolute value is less than one; truncate everything. */ + APInt::tcSet(parts, 0, dstPartsCount); + /* For exponent -1 the integer bit represents .5, look at that. + For smaller exponents leftmost truncated bit is 0. */ + truncatedBits = semantics->precision -1U - exponent; + } else { + /* We want the most significant (exponent + 1) bits; the rest are + truncated. */ + unsigned int bits = exponent + 1U; + + /* Hopelessly large in magnitude? */ + if (bits > width) + return opInvalidOp; + + if (bits < semantics->precision) { + /* We truncate (semantics->precision - bits) bits. */ + truncatedBits = semantics->precision - bits; + APInt::tcExtract(parts, dstPartsCount, src, bits, truncatedBits); + } else { + /* We want at least as many bits as are available. */ + APInt::tcExtract(parts, dstPartsCount, src, semantics->precision, 0); + APInt::tcShiftLeft(parts, dstPartsCount, bits - semantics->precision); + truncatedBits = 0; + } + } + + /* Step 2: work out any lost fraction, and increment the absolute + value if we would round away from zero. */ + if (truncatedBits) { + lost_fraction = lostFractionThroughTruncation(src, partCount(), + truncatedBits); + if (lost_fraction != lfExactlyZero && + roundAwayFromZero(rounding_mode, lost_fraction, truncatedBits)) { + if (APInt::tcIncrement(parts, dstPartsCount)) + return opInvalidOp; /* Overflow. */ + } + } else { + lost_fraction = lfExactlyZero; + } + + /* Step 3: check if we fit in the destination. */ + unsigned int omsb = APInt::tcMSB(parts, dstPartsCount) + 1; + + if (sign) { + if (!isSigned) { + /* Negative numbers cannot be represented as unsigned. */ + if (omsb != 0) + return opInvalidOp; + } else { + /* It takes omsb bits to represent the unsigned integer value. + We lose a bit for the sign, but care is needed as the + maximally negative integer is a special case. */ + if (omsb == width && APInt::tcLSB(parts, dstPartsCount) + 1 != omsb) + return opInvalidOp; + + /* This case can happen because of rounding. */ + if (omsb > width) + return opInvalidOp; + } + + APInt::tcNegate (parts, dstPartsCount); + } else { + if (omsb >= width + !isSigned) + return opInvalidOp; + } + + if (lost_fraction == lfExactlyZero) { + *isExact = true; + return opOK; + } else + return opInexact; +} + +/* Same as convertToSignExtendedInteger, except we provide + deterministic values in case of an invalid operation exception, + namely zero for NaNs and the minimal or maximal value respectively + for underflow or overflow. + The *isExact output tells whether the result is exact, in the sense + that converting it back to the original floating point type produces + the original value. This is almost equivalent to result==opOK, + except for negative zeroes. +*/ +APFloat::opStatus +APFloat::convertToInteger(integerPart *parts, unsigned int width, + bool isSigned, + roundingMode rounding_mode, bool *isExact) const +{ + opStatus fs; + + fs = convertToSignExtendedInteger(parts, width, isSigned, rounding_mode, + isExact); + + if (fs == opInvalidOp) { + unsigned int bits, dstPartsCount; + + dstPartsCount = partCountForBits(width); + + if (category == fcNaN) + bits = 0; + else if (sign) + bits = isSigned; + else + bits = width - isSigned; + + APInt::tcSetLeastSignificantBits(parts, dstPartsCount, bits); + if (sign && isSigned) + APInt::tcShiftLeft(parts, dstPartsCount, width - 1); + } + + return fs; +} + +/* Convert an unsigned integer SRC to a floating point number, + rounding according to ROUNDING_MODE. The sign of the floating + point number is not modified. */ +APFloat::opStatus +APFloat::convertFromUnsignedParts(const integerPart *src, + unsigned int srcCount, + roundingMode rounding_mode) +{ + unsigned int omsb, precision, dstCount; + integerPart *dst; + lostFraction lost_fraction; + + assertArithmeticOK(*semantics); + category = fcNormal; + omsb = APInt::tcMSB(src, srcCount) + 1; + dst = significandParts(); + dstCount = partCount(); + precision = semantics->precision; + + /* We want the most significant PRECISON bits of SRC. There may not + be that many; extract what we can. */ + if (precision <= omsb) { + exponent = omsb - 1; + lost_fraction = lostFractionThroughTruncation(src, srcCount, + omsb - precision); + APInt::tcExtract(dst, dstCount, src, precision, omsb - precision); + } else { + exponent = precision - 1; + lost_fraction = lfExactlyZero; + APInt::tcExtract(dst, dstCount, src, omsb, 0); + } + + return normalize(rounding_mode, lost_fraction); +} + +APFloat::opStatus +APFloat::convertFromAPInt(const APInt &Val, + bool isSigned, + roundingMode rounding_mode) +{ + unsigned int partCount = Val.getNumWords(); + APInt api = Val; + + sign = false; + if (isSigned && api.isNegative()) { + sign = true; + api = -api; + } + + return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); +} + +/* Convert a two's complement integer SRC to a floating point number, + rounding according to ROUNDING_MODE. ISSIGNED is true if the + integer is signed, in which case it must be sign-extended. */ +APFloat::opStatus +APFloat::convertFromSignExtendedInteger(const integerPart *src, + unsigned int srcCount, + bool isSigned, + roundingMode rounding_mode) +{ + opStatus status; + + assertArithmeticOK(*semantics); + if (isSigned && + APInt::tcExtractBit(src, srcCount * integerPartWidth - 1)) { + integerPart *copy; + + /* If we're signed and negative negate a copy. */ + sign = true; + copy = new integerPart[srcCount]; + APInt::tcAssign(copy, src, srcCount); + APInt::tcNegate(copy, srcCount); + status = convertFromUnsignedParts(copy, srcCount, rounding_mode); + delete [] copy; + } else { + sign = false; + status = convertFromUnsignedParts(src, srcCount, rounding_mode); + } + + return status; +} + +/* FIXME: should this just take a const APInt reference? */ +APFloat::opStatus +APFloat::convertFromZeroExtendedInteger(const integerPart *parts, + unsigned int width, bool isSigned, + roundingMode rounding_mode) +{ + unsigned int partCount = partCountForBits(width); + APInt api = APInt(width, partCount, parts); + + sign = false; + if (isSigned && APInt::tcExtractBit(parts, width - 1)) { + sign = true; + api = -api; + } + + return convertFromUnsignedParts(api.getRawData(), partCount, rounding_mode); +} + +APFloat::opStatus +APFloat::convertFromHexadecimalString(StringRef s, roundingMode rounding_mode) +{ + lostFraction lost_fraction = lfExactlyZero; + integerPart *significand; + unsigned int bitPos, partsCount; + StringRef::iterator dot, firstSignificantDigit; + + zeroSignificand(); + exponent = 0; + category = fcNormal; + + significand = significandParts(); + partsCount = partCount(); + bitPos = partsCount * integerPartWidth; + + /* Skip leading zeroes and any (hexa)decimal point. */ + StringRef::iterator begin = s.begin(); + StringRef::iterator end = s.end(); + StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot); + firstSignificantDigit = p; + + for (; p != end;) { + integerPart hex_value; + + if (*p == '.') { + assert(dot == end && "String contains multiple dots"); + dot = p++; + if (p == end) { + break; + } + } + + hex_value = hexDigitValue(*p); + if (hex_value == -1U) { + break; + } + + p++; + + if (p == end) { + break; + } else { + /* Store the number whilst 4-bit nibbles remain. */ + if (bitPos) { + bitPos -= 4; + hex_value <<= bitPos % integerPartWidth; + significand[bitPos / integerPartWidth] |= hex_value; + } else { + lost_fraction = trailingHexadecimalFraction(p, end, hex_value); + while (p != end && hexDigitValue(*p) != -1U) + p++; + break; + } + } + } + + /* Hex floats require an exponent but not a hexadecimal point. */ + assert(p != end && "Hex strings require an exponent"); + assert((*p == 'p' || *p == 'P') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); + + /* Ignore the exponent if we are zero. */ + if (p != firstSignificantDigit) { + int expAdjustment; + + /* Implicit hexadecimal point? */ + if (dot == end) + dot = p; + + /* Calculate the exponent adjustment implicit in the number of + significant digits. */ + expAdjustment = static_cast(dot - firstSignificantDigit); + if (expAdjustment < 0) + expAdjustment++; + expAdjustment = expAdjustment * 4 - 1; + + /* Adjust for writing the significand starting at the most + significant nibble. */ + expAdjustment += semantics->precision; + expAdjustment -= partsCount * integerPartWidth; + + /* Adjust for the given exponent. */ + exponent = totalExponent(p + 1, end, expAdjustment); + } + + return normalize(rounding_mode, lost_fraction); +} + +APFloat::opStatus +APFloat::roundSignificandWithExponent(const integerPart *decSigParts, + unsigned sigPartCount, int exp, + roundingMode rounding_mode) +{ + unsigned int parts, pow5PartCount; + fltSemantics calcSemantics = { 32767, -32767, 0, true }; + integerPart pow5Parts[maxPowerOfFiveParts]; + bool isNearest; + + isNearest = (rounding_mode == rmNearestTiesToEven || + rounding_mode == rmNearestTiesToAway); + + parts = partCountForBits(semantics->precision + 11); + + /* Calculate pow(5, abs(exp)). */ + pow5PartCount = powerOf5(pow5Parts, exp >= 0 ? exp: -exp); + + for (;; parts *= 2) { + opStatus sigStatus, powStatus; + unsigned int excessPrecision, truncatedBits; + + calcSemantics.precision = parts * integerPartWidth - 1; + excessPrecision = calcSemantics.precision - semantics->precision; + truncatedBits = excessPrecision; + + APFloat decSig(calcSemantics, fcZero, sign); + APFloat pow5(calcSemantics, fcZero, false); + + sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, + rmNearestTiesToEven); + powStatus = pow5.convertFromUnsignedParts(pow5Parts, pow5PartCount, + rmNearestTiesToEven); + /* Add exp, as 10^n = 5^n * 2^n. */ + decSig.exponent += exp; + + lostFraction calcLostFraction; + integerPart HUerr, HUdistance; + unsigned int powHUerr; + + if (exp >= 0) { + /* multiplySignificand leaves the precision-th bit set to 1. */ + calcLostFraction = decSig.multiplySignificand(pow5, NULL); + powHUerr = powStatus != opOK; + } else { + calcLostFraction = decSig.divideSignificand(pow5); + /* Denormal numbers have less precision. */ + if (decSig.exponent < semantics->minExponent) { + excessPrecision += (semantics->minExponent - decSig.exponent); + truncatedBits = excessPrecision; + if (excessPrecision > calcSemantics.precision) + excessPrecision = calcSemantics.precision; + } + /* Extra half-ulp lost in reciprocal of exponent. */ + powHUerr = (powStatus == opOK && calcLostFraction == lfExactlyZero) ? 0:2; + } + + /* Both multiplySignificand and divideSignificand return the + result with the integer bit set. */ + assert(APInt::tcExtractBit + (decSig.significandParts(), calcSemantics.precision - 1) == 1); + + HUerr = HUerrBound(calcLostFraction != lfExactlyZero, sigStatus != opOK, + powHUerr); + HUdistance = 2 * ulpsFromBoundary(decSig.significandParts(), + excessPrecision, isNearest); + + /* Are we guaranteed to round correctly if we truncate? */ + if (HUdistance >= HUerr) { + APInt::tcExtract(significandParts(), partCount(), decSig.significandParts(), + calcSemantics.precision - excessPrecision, + excessPrecision); + /* Take the exponent of decSig. If we tcExtract-ed less bits + above we must adjust our exponent to compensate for the + implicit right shift. */ + exponent = (decSig.exponent + semantics->precision + - (calcSemantics.precision - excessPrecision)); + calcLostFraction = lostFractionThroughTruncation(decSig.significandParts(), + decSig.partCount(), + truncatedBits); + return normalize(rounding_mode, calcLostFraction); + } + } +} + +APFloat::opStatus +APFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode) +{ + decimalInfo D; + opStatus fs; + + /* Scan the text. */ + StringRef::iterator p = str.begin(); + interpretDecimal(p, str.end(), &D); + + /* Handle the quick cases. First the case of no significant digits, + i.e. zero, and then exponents that are obviously too large or too + small. Writing L for log 10 / log 2, a number d.ddddd*10^exp + definitely overflows if + + (exp - 1) * L >= maxExponent + + and definitely underflows to zero where + + (exp + 1) * L <= minExponent - precision + + With integer arithmetic the tightest bounds for L are + + 93/28 < L < 196/59 [ numerator <= 256 ] + 42039/12655 < L < 28738/8651 [ numerator <= 65536 ] + */ + + if (decDigitValue(*D.firstSigDigit) >= 10U) { + category = fcZero; + fs = opOK; + + /* Check whether the normalized exponent is high enough to overflow + max during the log-rebasing in the max-exponent check below. */ + } else if (D.normalizedExponent - 1 > INT_MAX / 42039) { + fs = handleOverflow(rounding_mode); + + /* If it wasn't, then it also wasn't high enough to overflow max + during the log-rebasing in the min-exponent check. Check that it + won't overflow min in either check, then perform the min-exponent + check. */ + } else if (D.normalizedExponent - 1 < INT_MIN / 42039 || + (D.normalizedExponent + 1) * 28738 <= + 8651 * (semantics->minExponent - (int) semantics->precision)) { + /* Underflow to zero and round. */ + zeroSignificand(); + fs = normalize(rounding_mode, lfLessThanHalf); + + /* We can finally safely perform the max-exponent check. */ + } else if ((D.normalizedExponent - 1) * 42039 + >= 12655 * semantics->maxExponent) { + /* Overflow and round. */ + fs = handleOverflow(rounding_mode); + } else { + integerPart *decSignificand; + unsigned int partCount; + + /* A tight upper bound on number of bits required to hold an + N-digit decimal integer is N * 196 / 59. Allocate enough space + to hold the full significand, and an extra part required by + tcMultiplyPart. */ + partCount = static_cast(D.lastSigDigit - D.firstSigDigit) + 1; + partCount = partCountForBits(1 + 196 * partCount / 59); + decSignificand = new integerPart[partCount + 1]; + partCount = 0; + + /* Convert to binary efficiently - we do almost all multiplication + in an integerPart. When this would overflow do we do a single + bignum multiplication, and then revert again to multiplication + in an integerPart. */ + do { + integerPart decValue, val, multiplier; + + val = 0; + multiplier = 1; + + do { + if (*p == '.') { + p++; + if (p == str.end()) { + break; + } + } + decValue = decDigitValue(*p++); + assert(decValue < 10U && "Invalid character in significand"); + multiplier *= 10; + val = val * 10 + decValue; + /* The maximum number that can be multiplied by ten with any + digit added without overflowing an integerPart. */ + } while (p <= D.lastSigDigit && multiplier <= (~ (integerPart) 0 - 9) / 10); + + /* Multiply out the current part. */ + APInt::tcMultiplyPart(decSignificand, decSignificand, multiplier, val, + partCount, partCount + 1, false); + + /* If we used another part (likely but not guaranteed), increase + the count. */ + if (decSignificand[partCount]) + partCount++; + } while (p <= D.lastSigDigit); + + category = fcNormal; + fs = roundSignificandWithExponent(decSignificand, partCount, + D.exponent, rounding_mode); + + delete [] decSignificand; + } + + return fs; +} + +APFloat::opStatus +APFloat::convertFromString(StringRef str, roundingMode rounding_mode) +{ + assertArithmeticOK(*semantics); + assert(!str.empty() && "Invalid string length"); + + /* Handle a leading minus sign. */ + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + sign = *p == '-' ? 1 : 0; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String has no digits"); + } + + if (slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + assert(slen - 2 && "Invalid string"); + return convertFromHexadecimalString(StringRef(p + 2, slen - 2), + rounding_mode); + } + + return convertFromDecimalString(StringRef(p, slen), rounding_mode); +} + +/* Write out a hexadecimal representation of the floating point value + to DST, which must be of sufficient size, in the C99 form + [-]0xh.hhhhp[+-]d. Return the number of characters written, + excluding the terminating NUL. + + If UPPERCASE, the output is in upper case, otherwise in lower case. + + HEXDIGITS digits appear altogether, rounding the value if + necessary. If HEXDIGITS is 0, the minimal precision to display the + number precisely is used instead. If nothing would appear after + the decimal point it is suppressed. + + The decimal exponent is always printed and has at least one digit. + Zero values display an exponent of zero. Infinities and NaNs + appear as "infinity" or "nan" respectively. + + The above rules are as specified by C99. There is ambiguity about + what the leading hexadecimal digit should be. This implementation + uses whatever is necessary so that the exponent is displayed as + stored. This implies the exponent will fall within the IEEE format + range, and the leading hexadecimal digit will be 0 (for denormals), + 1 (normal numbers) or 2 (normal numbers rounded-away-from-zero with + any other digits zero). +*/ +unsigned int +APFloat::convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode rounding_mode) const +{ + char *p; + + assertArithmeticOK(*semantics); + + p = dst; + if (sign) + *dst++ = '-'; + + switch (category) { + case fcInfinity: + memcpy (dst, upperCase ? infinityU: infinityL, sizeof infinityU - 1); + dst += sizeof infinityL - 1; + break; + + case fcNaN: + memcpy (dst, upperCase ? NaNU: NaNL, sizeof NaNU - 1); + dst += sizeof NaNU - 1; + break; + + case fcZero: + *dst++ = '0'; + *dst++ = upperCase ? 'X': 'x'; + *dst++ = '0'; + if (hexDigits > 1) { + *dst++ = '.'; + memset (dst, '0', hexDigits - 1); + dst += hexDigits - 1; + } + *dst++ = upperCase ? 'P': 'p'; + *dst++ = '0'; + break; + + case fcNormal: + dst = convertNormalToHexString (dst, hexDigits, upperCase, rounding_mode); + break; + } + + *dst = 0; + + return static_cast(dst - p); +} + +/* Does the hard work of outputting the correctly rounded hexadecimal + form of a normal floating point number with the specified number of + hexadecimal digits. If HEXDIGITS is zero the minimum number of + digits necessary to print the value precisely is output. */ +char * +APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, + bool upperCase, + roundingMode rounding_mode) const +{ + unsigned int count, valueBits, shift, partsCount, outputDigits; + const char *hexDigitChars; + const integerPart *significand; + char *p; + bool roundUp; + + *dst++ = '0'; + *dst++ = upperCase ? 'X': 'x'; + + roundUp = false; + hexDigitChars = upperCase ? hexDigitsUpper: hexDigitsLower; + + significand = significandParts(); + partsCount = partCount(); + + /* +3 because the first digit only uses the single integer bit, so + we have 3 virtual zero most-significant-bits. */ + valueBits = semantics->precision + 3; + shift = integerPartWidth - valueBits % integerPartWidth; + + /* The natural number of digits required ignoring trailing + insignificant zeroes. */ + outputDigits = (valueBits - significandLSB () + 3) / 4; + + /* hexDigits of zero means use the required number for the + precision. Otherwise, see if we are truncating. If we are, + find out if we need to round away from zero. */ + if (hexDigits) { + if (hexDigits < outputDigits) { + /* We are dropping non-zero bits, so need to check how to round. + "bits" is the number of dropped bits. */ + unsigned int bits; + lostFraction fraction; + + bits = valueBits - hexDigits * 4; + fraction = lostFractionThroughTruncation (significand, partsCount, bits); + roundUp = roundAwayFromZero(rounding_mode, fraction, bits); + } + outputDigits = hexDigits; + } + + /* Write the digits consecutively, and start writing in the location + of the hexadecimal point. We move the most significant digit + left and add the hexadecimal point later. */ + p = ++dst; + + count = (valueBits + integerPartWidth - 1) / integerPartWidth; + + while (outputDigits && count) { + integerPart part; + + /* Put the most significant integerPartWidth bits in "part". */ + if (--count == partsCount) + part = 0; /* An imaginary higher zero part. */ + else + part = significand[count] << shift; + + if (count && shift) + part |= significand[count - 1] >> (integerPartWidth - shift); + + /* Convert as much of "part" to hexdigits as we can. */ + unsigned int curDigits = integerPartWidth / 4; + + if (curDigits > outputDigits) + curDigits = outputDigits; + dst += partAsHex (dst, part, curDigits, hexDigitChars); + outputDigits -= curDigits; + } + + if (roundUp) { + char *q = dst; + + /* Note that hexDigitChars has a trailing '0'. */ + do { + q--; + *q = hexDigitChars[hexDigitValue (*q) + 1]; + } while (*q == '0'); + assert(q >= p); + } else { + /* Add trailing zeroes. */ + memset (dst, '0', outputDigits); + dst += outputDigits; + } + + /* Move the most significant digit to before the point, and if there + is something after the decimal point add it. This must come + after rounding above. */ + p[-1] = p[0]; + if (dst -1 == p) + dst--; + else + p[0] = '.'; + + /* Finally output the exponent. */ + *dst++ = upperCase ? 'P': 'p'; + + return writeSignedDecimal (dst, exponent); +} + +// For good performance it is desirable for different APFloats +// to produce different integers. +uint32_t +APFloat::getHashValue() const +{ + if (category==fcZero) return sign<<8 | semantics->precision ; + else if (category==fcInfinity) return sign<<9 | semantics->precision; + else if (category==fcNaN) return 1<<10 | semantics->precision; + else { + uint32_t hash = sign<<11 | semantics->precision | exponent<<12; + const integerPart* p = significandParts(); + for (int i=partCount(); i>0; i--, p++) + hash ^= ((uint32_t)*p) ^ (uint32_t)((*p)>>32); + return hash; + } +} + +// Conversion from APFloat to/from host float/double. It may eventually be +// possible to eliminate these and have everybody deal with APFloats, but that +// will take a while. This approach will not easily extend to long double. +// Current implementation requires integerPartWidth==64, which is correct at +// the moment but could be made more general. + +// Denormals have exponent minExponent in APFloat, but minExponent-1 in +// the actual IEEE respresentations. We compensate for that here. + +APInt +APFloat::convertF80LongDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended); + assert(partCount()==2); + + uint64_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = significandParts()[0]; + if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = 0x8000000000000000ULL; + } else { + assert(category == fcNaN && "Unknown category"); + myexponent = 0x7fff; + mysignificand = significandParts()[0]; + } + + uint64_t words[2]; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 15) | + (myexponent & 0x7fffLL); + return APInt(80, 2, words); +} + +APInt +APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); + assert(partCount()==2); + + uint64_t myexponent, mysignificand, myexponent2, mysignificand2; + + if (category==fcNormal) { + myexponent = exponent + 1023; //bias + myexponent2 = exponent2 + 1023; + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + if (myexponent==1 && !(mysignificand & 0x10000000000000LL)) + myexponent = 0; // denormal + if (myexponent2==1 && !(mysignificand2 & 0x10000000000000LL)) + myexponent2 = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + myexponent2 = 0; + mysignificand2 = 0; + } else if (category==fcInfinity) { + myexponent = 0x7ff; + myexponent2 = 0; + mysignificand = 0; + mysignificand2 = 0; + } else { + assert(category == fcNaN && "Unknown category"); + myexponent = 0x7ff; + mysignificand = significandParts()[0]; + myexponent2 = exponent2; + mysignificand2 = significandParts()[1]; + } + + uint64_t words[2]; + words[0] = ((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL); + words[1] = ((uint64_t)(sign2 & 1) << 63) | + ((myexponent2 & 0x7ff) << 52) | + (mysignificand2 & 0xfffffffffffffLL); + return APInt(128, 2, words); +} + +APInt +APFloat::convertQuadrupleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEquad); + assert(partCount()==2); + + uint64_t myexponent, mysignificand, mysignificand2; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + if (myexponent==1 && !(mysignificand2 & 0x1000000000000LL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = mysignificand2 = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = mysignificand2 = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x7fff; + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + } + + uint64_t words[2]; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7fff) << 48) | + (mysignificand2 & 0xffffffffffffLL); + + return APInt(128, 2, words); +} + +APInt +APFloat::convertDoubleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEdouble); + assert(partCount()==1); + + uint64_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+1023; //bias + mysignificand = *significandParts(); + if (myexponent==1 && !(mysignificand & 0x10000000000000LL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x7ff; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x7ff; + mysignificand = *significandParts(); + } + + return APInt(64, ((((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7ff) << 52) | + (mysignificand & 0xfffffffffffffLL)))); +} + +APInt +APFloat::convertFloatAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEsingle); + assert(partCount()==1); + + uint32_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+127; //bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x800000)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0xff; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0xff; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) | + (mysignificand & 0x7fffff))); +} + +APInt +APFloat::convertHalfAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEhalf); + assert(partCount()==1); + + uint32_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+15; //bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x400)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x1f; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x1f; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) | + (mysignificand & 0x3ff))); +} + +// This function creates an APInt that is just a bit map of the floating +// point constant as it would appear in memory. It is not a conversion, +// and treating the result as a normal integer is unlikely to be useful. + +APInt +APFloat::bitcastToAPInt() const +{ + if (semantics == (const llvm::fltSemantics*)&IEEEhalf) + return convertHalfAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEsingle) + return convertFloatAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEdouble) + return convertDoubleAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&IEEEquad) + return convertQuadrupleAPFloatToAPInt(); + + if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) + return convertPPCDoubleDoubleAPFloatToAPInt(); + + assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended && + "unknown format!"); + return convertF80LongDoubleAPFloatToAPInt(); +} + +float +APFloat::convertToFloat() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEsingle && + "Float semantics are not IEEEsingle"); + APInt api = bitcastToAPInt(); + return api.bitsToFloat(); +} + +double +APFloat::convertToDouble() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEdouble && + "Float semantics are not IEEEdouble"); + APInt api = bitcastToAPInt(); + return api.bitsToDouble(); +} + +/// Integer bit is explicit in this format. Intel hardware (387 and later) +/// does not support these bit patterns: +/// exponent = all 1's, integer bit 0, significand 0 ("pseudoinfinity") +/// exponent = all 1's, integer bit 0, significand nonzero ("pseudoNaN") +/// exponent = 0, integer bit 1 ("pseudodenormal") +/// exponent!=0 nor all 1's, integer bit 0 ("unnormal") +/// At the moment, the first two are treated as NaNs, the second two as Normal. +void +APFloat::initFromF80LongDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==80); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i2 & 0x7fff); + uint64_t mysignificand = i1; + + initialize(&APFloat::x87DoubleExtended); + assert(partCount()==2); + + sign = static_cast(i2>>15); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && mysignificand!=0x8000000000000000ULL) { + // exponent meaningless + category = fcNaN; + significandParts()[0] = mysignificand; + significandParts()[1] = 0; + } else { + category = fcNormal; + exponent = myexponent - 16383; + significandParts()[0] = mysignificand; + significandParts()[1] = 0; + if (myexponent==0) // denormal + exponent = -16382; + } +} + +void +APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==128); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i1 >> 52) & 0x7ff; + uint64_t mysignificand = i1 & 0xfffffffffffffLL; + uint64_t myexponent2 = (i2 >> 52) & 0x7ff; + uint64_t mysignificand2 = i2 & 0xfffffffffffffLL; + + initialize(&APFloat::PPCDoubleDouble); + assert(partCount()==2); + + sign = static_cast(i1>>63); + sign2 = static_cast(i2>>63); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + // exponent2 and significand2 are required to be 0; we don't check + category = fcZero; + } else if (myexponent==0x7ff && mysignificand==0) { + // exponent, significand meaningless + // exponent2 and significand2 are required to be 0; we don't check + category = fcInfinity; + } else if (myexponent==0x7ff && mysignificand!=0) { + // exponent meaningless. So is the whole second word, but keep it + // for determinism. + category = fcNaN; + exponent2 = myexponent2; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + } else { + category = fcNormal; + // Note there is no category2; the second word is treated as if it is + // fcNormal, although it might be something else considered by itself. + exponent = myexponent - 1023; + exponent2 = myexponent2 - 1023; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + if (myexponent==0) // denormal + exponent = -1022; + else + significandParts()[0] |= 0x10000000000000LL; // integer bit + if (myexponent2==0) + exponent2 = -1022; + else + significandParts()[1] |= 0x10000000000000LL; // integer bit + } +} + +void +APFloat::initFromQuadrupleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==128); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i2 >> 48) & 0x7fff; + uint64_t mysignificand = i1; + uint64_t mysignificand2 = i2 & 0xffffffffffffLL; + + initialize(&APFloat::IEEEquad); + assert(partCount()==2); + + sign = static_cast(i2>>63); + if (myexponent==0 && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && + (mysignificand!=0 || mysignificand2 !=0)) { + // exponent meaningless + category = fcNaN; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + } else { + category = fcNormal; + exponent = myexponent - 16383; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + if (myexponent==0) // denormal + exponent = -16382; + else + significandParts()[1] |= 0x1000000000000LL; // integer bit + } +} + +void +APFloat::initFromDoubleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==64); + uint64_t i = *api.getRawData(); + uint64_t myexponent = (i >> 52) & 0x7ff; + uint64_t mysignificand = i & 0xfffffffffffffLL; + + initialize(&APFloat::IEEEdouble); + assert(partCount()==1); + + sign = static_cast(i>>63); + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7ff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7ff && mysignificand!=0) { + // exponent meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 1023; + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -1022; + else + *significandParts() |= 0x10000000000000LL; // integer bit + } +} + +void +APFloat::initFromFloatAPInt(const APInt & api) +{ + assert(api.getBitWidth()==32); + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 23) & 0xff; + uint32_t mysignificand = i & 0x7fffff; + + initialize(&APFloat::IEEEsingle); + assert(partCount()==1); + + sign = i >> 31; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0xff && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0xff && mysignificand!=0) { + // sign, exponent, significand meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 127; //bias + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -126; + else + *significandParts() |= 0x800000; // integer bit + } +} + +void +APFloat::initFromHalfAPInt(const APInt & api) +{ + assert(api.getBitWidth()==16); + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 10) & 0x1f; + uint32_t mysignificand = i & 0x3ff; + + initialize(&APFloat::IEEEhalf); + assert(partCount()==1); + + sign = i >> 15; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x1f && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x1f && mysignificand!=0) { + // sign, exponent, significand meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 15; //bias + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -14; + else + *significandParts() |= 0x400; // integer bit + } +} + +/// Treat api as containing the bits of a floating point number. Currently +/// we infer the floating point type from the size of the APInt. The +/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful +/// when the size is anything else). +void +APFloat::initFromAPInt(const APInt& api, bool isIEEE) +{ + if (api.getBitWidth() == 16) + return initFromHalfAPInt(api); + else if (api.getBitWidth() == 32) + return initFromFloatAPInt(api); + else if (api.getBitWidth()==64) + return initFromDoubleAPInt(api); + else if (api.getBitWidth()==80) + return initFromF80LongDoubleAPInt(api); + else if (api.getBitWidth()==128) + return (isIEEE ? + initFromQuadrupleAPInt(api) : initFromPPCDoubleDoubleAPInt(api)); + else + llvm_unreachable(0); +} + +APFloat +APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) +{ + return APFloat(APInt::getAllOnesValue(BitWidth), isIEEE); +} + +APFloat APFloat::getLargest(const fltSemantics &Sem, bool Negative) { + APFloat Val(Sem, fcNormal, Negative); + + // We want (in interchange format): + // sign = {Negative} + // exponent = 1..10 + // significand = 1..1 + + Val.exponent = Sem.maxExponent; // unbiased + + // 1-initialize all bits.... + Val.zeroSignificand(); + integerPart *significand = Val.significandParts(); + unsigned N = partCountForBits(Sem.precision); + for (unsigned i = 0; i != N; ++i) + significand[i] = ~((integerPart) 0); + + // ...and then clear the top bits for internal consistency. + significand[N-1] &= + (((integerPart) 1) << ((Sem.precision % integerPartWidth) - 1)) - 1; + + return Val; +} + +APFloat APFloat::getSmallest(const fltSemantics &Sem, bool Negative) { + APFloat Val(Sem, fcNormal, Negative); + + // We want (in interchange format): + // sign = {Negative} + // exponent = 0..0 + // significand = 0..01 + + Val.exponent = Sem.minExponent; // unbiased + Val.zeroSignificand(); + Val.significandParts()[0] = 1; + return Val; +} + +APFloat APFloat::getSmallestNormalized(const fltSemantics &Sem, bool Negative) { + APFloat Val(Sem, fcNormal, Negative); + + // We want (in interchange format): + // sign = {Negative} + // exponent = 0..0 + // significand = 10..0 + + Val.exponent = Sem.minExponent; + Val.zeroSignificand(); + Val.significandParts()[partCountForBits(Sem.precision)-1] |= + (((integerPart) 1) << ((Sem.precision % integerPartWidth) - 1)); + + return Val; +} + +APFloat::APFloat(const APInt& api, bool isIEEE) : exponent2(0), sign2(0) { + initFromAPInt(api, isIEEE); +} + +APFloat::APFloat(float f) : exponent2(0), sign2(0) { + initFromAPInt(APInt::floatToBits(f)); +} + +APFloat::APFloat(double d) : exponent2(0), sign2(0) { + initFromAPInt(APInt::doubleToBits(d)); +} + +namespace { + static void append(SmallVectorImpl &Buffer, + unsigned N, const char *Str) { + unsigned Start = Buffer.size(); + Buffer.set_size(Start + N); + memcpy(&Buffer[Start], Str, N); + } + + template + void append(SmallVectorImpl &Buffer, const char (&Str)[N]) { + append(Buffer, N, Str); + } + + /// Removes data from the given significand until it is no more + /// precise than is required for the desired precision. + void AdjustToPrecision(APInt &significand, + int &exp, unsigned FormatPrecision) { + unsigned bits = significand.getActiveBits(); + + // 196/59 is a very slight overestimate of lg_2(10). + unsigned bitsRequired = (FormatPrecision * 196 + 58) / 59; + + if (bits <= bitsRequired) return; + + unsigned tensRemovable = (bits - bitsRequired) * 59 / 196; + if (!tensRemovable) return; + + exp += tensRemovable; + + APInt divisor(significand.getBitWidth(), 1); + APInt powten(significand.getBitWidth(), 10); + while (true) { + if (tensRemovable & 1) + divisor *= powten; + tensRemovable >>= 1; + if (!tensRemovable) break; + powten *= powten; + } + + significand = significand.udiv(divisor); + + // Truncate the significand down to its active bit count, but + // don't try to drop below 32. + unsigned newPrecision = std::max(32U, significand.getActiveBits()); + significand = significand.trunc(newPrecision); + } + + + void AdjustToPrecision(SmallVectorImpl &buffer, + int &exp, unsigned FormatPrecision) { + unsigned N = buffer.size(); + if (N <= FormatPrecision) return; + + // The most significant figures are the last ones in the buffer. + unsigned FirstSignificant = N - FormatPrecision; + + // Round. + // FIXME: this probably shouldn't use 'round half up'. + + // Rounding down is just a truncation, except we also want to drop + // trailing zeros from the new result. + if (buffer[FirstSignificant - 1] < '5') { + while (buffer[FirstSignificant] == '0') + FirstSignificant++; + + exp += FirstSignificant; + buffer.erase(&buffer[0], &buffer[FirstSignificant]); + return; + } + + // Rounding up requires a decimal add-with-carry. If we continue + // the carry, the newly-introduced zeros will just be truncated. + for (unsigned I = FirstSignificant; I != N; ++I) { + if (buffer[I] == '9') { + FirstSignificant++; + } else { + buffer[I]++; + break; + } + } + + // If we carried through, we have exactly one digit of precision. + if (FirstSignificant == N) { + exp += FirstSignificant; + buffer.clear(); + buffer.push_back('1'); + return; + } + + exp += FirstSignificant; + buffer.erase(&buffer[0], &buffer[FirstSignificant]); + } +} + +void APFloat::toString(SmallVectorImpl &Str, + unsigned FormatPrecision, + unsigned FormatMaxPadding) const { + switch (category) { + case fcInfinity: + if (isNegative()) + return append(Str, "-Inf"); + else + return append(Str, "+Inf"); + + case fcNaN: return append(Str, "NaN"); + + case fcZero: + if (isNegative()) + Str.push_back('-'); + + if (!FormatMaxPadding) + append(Str, "0.0E+0"); + else + Str.push_back('0'); + return; + + case fcNormal: + break; + } + + if (isNegative()) + Str.push_back('-'); + + // Decompose the number into an APInt and an exponent. + int exp = exponent - ((int) semantics->precision - 1); + APInt significand(semantics->precision, + partCountForBits(semantics->precision), + significandParts()); + + // Set FormatPrecision if zero. We want to do this before we + // truncate trailing zeros, as those are part of the precision. + if (!FormatPrecision) { + // It's an interesting question whether to use the nominal + // precision or the active precision here for denormals. + + // FormatPrecision = ceil(significandBits / lg_2(10)) + FormatPrecision = (semantics->precision * 59 + 195) / 196; + } + + // Ignore trailing binary zeros. + int trailingZeros = significand.countTrailingZeros(); + exp += trailingZeros; + significand = significand.lshr(trailingZeros); + + // Change the exponent from 2^e to 10^e. + if (exp == 0) { + // Nothing to do. + } else if (exp > 0) { + // Just shift left. + significand = significand.zext(semantics->precision + exp); + significand <<= exp; + exp = 0; + } else { /* exp < 0 */ + int texp = -exp; + + // We transform this using the identity: + // (N)(2^-e) == (N)(5^e)(10^-e) + // This means we have to multiply N (the significand) by 5^e. + // To avoid overflow, we have to operate on numbers large + // enough to store N * 5^e: + // log2(N * 5^e) == log2(N) + e * log2(5) + // <= semantics->precision + e * 137 / 59 + // (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59) + + unsigned precision = semantics->precision + 137 * texp / 59; + + // Multiply significand by 5^e. + // N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8) + significand = significand.zext(precision); + APInt five_to_the_i(precision, 5); + while (true) { + if (texp & 1) significand *= five_to_the_i; + + texp >>= 1; + if (!texp) break; + five_to_the_i *= five_to_the_i; + } + } + + AdjustToPrecision(significand, exp, FormatPrecision); + + llvm::SmallVector buffer; + + // Fill the buffer. + unsigned precision = significand.getBitWidth(); + APInt ten(precision, 10); + APInt digit(precision, 0); + + bool inTrail = true; + while (significand != 0) { + // digit <- significand % 10 + // significand <- significand / 10 + APInt::udivrem(significand, ten, significand, digit); + + unsigned d = digit.getZExtValue(); + + // Drop trailing zeros. + if (inTrail && !d) exp++; + else { + buffer.push_back((char) ('0' + d)); + inTrail = false; + } + } + + assert(!buffer.empty() && "no characters in buffer!"); + + // Drop down to FormatPrecision. + // TODO: don't do more precise calculations above than are required. + AdjustToPrecision(buffer, exp, FormatPrecision); + + unsigned NDigits = buffer.size(); + + // Check whether we should use scientific notation. + bool FormatScientific; + if (!FormatMaxPadding) + FormatScientific = true; + else { + if (exp >= 0) { + // 765e3 --> 765000 + // ^^^ + // But we shouldn't make the number look more precise than it is. + FormatScientific = ((unsigned) exp > FormatMaxPadding || + NDigits + (unsigned) exp > FormatPrecision); + } else { + // Power of the most significant digit. + int MSD = exp + (int) (NDigits - 1); + if (MSD >= 0) { + // 765e-2 == 7.65 + FormatScientific = false; + } else { + // 765e-5 == 0.00765 + // ^ ^^ + FormatScientific = ((unsigned) -MSD) > FormatMaxPadding; + } + } + } + + // Scientific formatting is pretty straightforward. + if (FormatScientific) { + exp += (NDigits - 1); + + Str.push_back(buffer[NDigits-1]); + Str.push_back('.'); + if (NDigits == 1) + Str.push_back('0'); + else + for (unsigned I = 1; I != NDigits; ++I) + Str.push_back(buffer[NDigits-1-I]); + Str.push_back('E'); + + Str.push_back(exp >= 0 ? '+' : '-'); + if (exp < 0) exp = -exp; + SmallVector expbuf; + do { + expbuf.push_back((char) ('0' + (exp % 10))); + exp /= 10; + } while (exp); + for (unsigned I = 0, E = expbuf.size(); I != E; ++I) + Str.push_back(expbuf[E-1-I]); + return; + } + + // Non-scientific, positive exponents. + if (exp >= 0) { + for (unsigned I = 0; I != NDigits; ++I) + Str.push_back(buffer[NDigits-1-I]); + for (unsigned I = 0; I != (unsigned) exp; ++I) + Str.push_back('0'); + return; + } + + // Non-scientific, negative exponents. + + // The number of digits to the left of the decimal point. + int NWholeDigits = exp + (int) NDigits; + + unsigned I = 0; + if (NWholeDigits > 0) { + for (; I != (unsigned) NWholeDigits; ++I) + Str.push_back(buffer[NDigits-I-1]); + Str.push_back('.'); + } else { + unsigned NZeros = 1 + (unsigned) -NWholeDigits; + + Str.push_back('0'); + Str.push_back('.'); + for (unsigned Z = 1; Z != NZeros; ++Z) + Str.push_back('0'); + } + + for (; I != NDigits; ++I) + Str.push_back(buffer[NDigits-I-1]); +} diff --git a/final/lib/Support/APInt.cpp b/final/lib/Support/APInt.cpp new file mode 100644 index 00000000000..08f36d2af3a --- /dev/null +++ b/final/lib/Support/APInt.cpp @@ -0,0 +1,2904 @@ +//===-- APInt.cpp - Implement APInt class ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integer +// constant values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "apint" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +using namespace llvm; + +/// A utility function for allocating memory, checking for allocation failures, +/// and ensuring the contents are zeroed. +inline static uint64_t* getClearedMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + memset(result, 0, numWords * sizeof(uint64_t)); + return result; +} + +/// A utility function for allocating memory and checking for allocation +/// failure. The content is not zeroed. +inline static uint64_t* getMemory(unsigned numWords) { + uint64_t * result = new uint64_t[numWords]; + assert(result && "APInt memory allocation fails!"); + return result; +} + +/// A utility function that converts a character to a digit. +inline static unsigned getDigit(char cdigit, uint8_t radix) { + unsigned r; + + if (radix == 16) { + r = cdigit - '0'; + if (r <= 9) + return r; + + r = cdigit - 'A'; + if (r <= 5) + return r + 10; + + r = cdigit - 'a'; + if (r <= 5) + return r + 10; + } + + r = cdigit - '0'; + if (r < radix) + return r; + + return -1U; +} + + +void APInt::initSlowCase(unsigned numBits, uint64_t val, bool isSigned) { + pVal = getClearedMemory(getNumWords()); + pVal[0] = val; + if (isSigned && int64_t(val) < 0) + for (unsigned i = 1; i < getNumWords(); ++i) + pVal[i] = -1ULL; +} + +void APInt::initSlowCase(const APInt& that) { + pVal = getMemory(getNumWords()); + memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); +} + + +APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "Bitwidth too small"); + assert(bigVal && "Null pointer detected!"); + if (isSingleWord()) + VAL = bigVal[0]; + else { + // Get memory, cleared to 0 + pVal = getClearedMemory(getNumWords()); + // Calculate the number of words to copy + unsigned words = std::min(numWords, getNumWords()); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); + } + // Make sure unused high bits are cleared + clearUnusedBits(); +} + +APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix) + : BitWidth(numbits), VAL(0) { + assert(BitWidth && "Bitwidth too small"); + fromString(numbits, Str, radix); +} + +APInt& APInt::AssignSlowCase(const APInt& RHS) { + // Don't do anything for X = X + if (this == &RHS) + return *this; + + if (BitWidth == RHS.getBitWidth()) { + // assume same bit-width single-word case is already handled + assert(!isSingleWord()); + memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + if (isSingleWord()) { + // assume case where both are single words is already handled + assert(!RHS.isSingleWord()); + VAL = 0; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } else if (getNumWords() == RHS.getNumWords()) + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + else if (RHS.isSingleWord()) { + delete [] pVal; + VAL = RHS.VAL; + } else { + delete [] pVal; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } + BitWidth = RHS.BitWidth; + return clearUnusedBits(); +} + +APInt& APInt::operator=(uint64_t RHS) { + if (isSingleWord()) + VAL = RHS; + else { + pVal[0] = RHS; + memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); + } + return clearUnusedBits(); +} + +/// Profile - This method 'profiles' an APInt for use with FoldingSet. +void APInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger(BitWidth); + + if (isSingleWord()) { + ID.AddInteger(VAL); + return; + } + + unsigned NumWords = getNumWords(); + for (unsigned i = 0; i < NumWords; ++i) + ID.AddInteger(pVal[i]); +} + +/// add_1 - This function adds a single "digit" integer, y, to the multiple +/// "digit" integer array, x[]. x[] is modified to reflect the addition and +/// 1 is returned if there is a carry out, otherwise 0 is returned. +/// @returns the carry of the addition. +static bool add_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + dest[i] = y + x[i]; + if (dest[i] < y) + y = 1; // Carry one to next digit. + else { + y = 0; // No need to carry so exit early + break; + } + } + return y; +} + +/// @brief Prefix increment operator. Increments the APInt by one. +APInt& APInt::operator++() { + if (isSingleWord()) + ++VAL; + else + add_1(pVal, pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from +/// the multi-digit integer array, x[], propagating the borrowed 1 value until +/// no further borrowing is neeeded or it runs out of "digits" in x. The result +/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. +/// In other words, if y > x then this function returns 1, otherwise 0. +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], unsigned len, uint64_t y) { + for (unsigned i = 0; i < len; ++i) { + uint64_t X = x[i]; + x[i] -= y; + if (y > X) + y = 1; // We have to "borrow 1" from next "digit" + else { + y = 0; // No need to borrow + break; // Remaining digits are unchanged so exit early + } + } + return bool(y); +} + +/// @brief Prefix decrement operator. Decrements the APInt by one. +APInt& APInt::operator--() { + if (isSingleWord()) + --VAL; + else + sub_1(pVal, getNumWords(), 1); + return clearUnusedBits(); +} + +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool carry = false; + for (unsigned i = 0; i< len; ++i) { + uint64_t limit = std::min(x[i],y[i]); // must come first in case dest == x + dest[i] = x[i] + y[i] + carry; + carry = dest[i] < limit || (carry && dest[i] == limit); + } + return carry; +} + +/// Adds the RHS APint to this APInt. +/// @returns this, after addition of RHS. +/// @brief Addition assignment operator. +APInt& APInt::operator+=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL += RHS.VAL; + else { + add(pVal, pVal, RHS.pVal, getNumWords()); + } + return clearUnusedBits(); +} + +/// Subtracts the integer array y from the integer array x +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + unsigned len) { + bool borrow = false; + for (unsigned i = 0; i < len; ++i) { + uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; + borrow = y[i] > x_tmp || (borrow && x[i] == 0); + dest[i] = x_tmp - y[i]; + } + return borrow; +} + +/// Subtracts the RHS APInt from this APInt +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. +APInt& APInt::operator-=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + VAL -= RHS.VAL; + else + sub(pVal, pVal, RHS.pVal, getNumWords()); + return clearUnusedBits(); +} + +/// Multiplies an integer array, x, by a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) + uint64_t ly = y & 0xffffffffULL, hy = y >> 32; + uint64_t carry = 0; + + // For each digit of x. + for (unsigned i = 0; i < len; ++i) { + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = x[i] >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + dest[i] = carry + lx * ly; + // Determine if the add above introduces carry. + hasCarry = (dest[i] < carry) ? 1 : 0; + carry = hx * ly + (dest[i] >> 32) + (hasCarry ? (1ULL << 32) : 0); + // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + + // (2^32 - 1) + 2^32 = 2^64. + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + dest[i] = (carry << 32) | (dest[i] & 0xffffffffULL); + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) + + (carry >> 32) + ((lx * hy) >> 32) + hx * hy; + } + return carry; +} + +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], uint64_t x[], unsigned xlen, uint64_t y[], + unsigned ylen) { + dest[xlen] = mul_1(dest, x, xlen, y[0]); + for (unsigned i = 1; i < ylen; ++i) { + uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32; + uint64_t carry = 0, lx = 0, hx = 0; + for (unsigned j = 0; j < xlen; ++j) { + lx = x[j] & 0xffffffffULL; + hx = x[j] >> 32; + // hasCarry - A flag to indicate if has carry. + // hasCarry == 0, no carry + // hasCarry == 1, has carry + // hasCarry == 2, no carry and the calculation result == 0. + uint8_t hasCarry = 0; + uint64_t resul = carry + lx * ly; + hasCarry = (resul < carry) ? 1 : 0; + carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + (resul >> 32); + hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); + + carry += (lx * hy) & 0xffffffffULL; + resul = (carry << 32) | (resul & 0xffffffffULL); + dest[i+j] += resul; + carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+ + (carry >> 32) + (dest[i+j] < resul ? 1 : 0) + + ((lx * hy) >> 32) + hx * hy; + } + dest[i+xlen] = carry; + } +} + +APInt& APInt::operator*=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL *= RHS.VAL; + clearUnusedBits(); + return *this; + } + + // Get some bit facts about LHS and check for zero + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; + if (!lhsWords) + // 0 * X ===> 0 + return *this; + + // Get some bit facts about RHS and check for zero + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; + if (!rhsWords) { + // X * 0 ===> 0 + clearAllBits(); + return *this; + } + + // Allocate space for the result + unsigned destWords = rhsWords + lhsWords; + uint64_t *dest = getMemory(destWords); + + // Perform the long multiply + mul(dest, pVal, lhsWords, RHS.pVal, rhsWords); + + // Copy result back into *this + clearAllBits(); + unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords; + memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); + + // delete dest array and return + delete[] dest; + return *this; +} + +APInt& APInt::operator&=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL &= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] &= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator|=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL |= RHS.VAL; + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] |= RHS.pVal[i]; + return *this; +} + +APInt& APInt::operator^=(const APInt& RHS) { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + VAL ^= RHS.VAL; + this->clearUnusedBits(); + return *this; + } + unsigned numWords = getNumWords(); + for (unsigned i = 0; i < numWords; ++i) + pVal[i] ^= RHS.pVal[i]; + return clearUnusedBits(); +} + +APInt APInt::AndSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t* val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] & RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::OrSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] | RHS.pVal[i]; + return APInt(val, getBitWidth()); +} + +APInt APInt::XorSlowCase(const APInt& RHS) const { + unsigned numWords = getNumWords(); + uint64_t *val = getMemory(numWords); + for (unsigned i = 0; i < numWords; ++i) + val[i] = pVal[i] ^ RHS.pVal[i]; + + // 0^0==1 so clear the high bits in case they got set. + return APInt(val, getBitWidth()).clearUnusedBits(); +} + +bool APInt::operator !() const { + if (isSingleWord()) + return !VAL; + + for (unsigned i = 0; i < getNumWords(); ++i) + if (pVal[i]) + return false; + return true; +} + +APInt APInt::operator*(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL * RHS.VAL); + APInt Result(*this); + Result *= RHS; + return Result.clearUnusedBits(); +} + +APInt APInt::operator+(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL + RHS.VAL); + APInt Result(BitWidth, 0); + add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); + return Result.clearUnusedBits(); +} + +APInt APInt::operator-(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL - RHS.VAL); + APInt Result(BitWidth, 0); + sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); + return Result.clearUnusedBits(); +} + +bool APInt::operator[](unsigned bitPosition) const { + assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); + return (maskBit(bitPosition) & + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; +} + +bool APInt::EqualSlowCase(const APInt& RHS) const { + // Get some facts about the number of bits used in the two operands. + unsigned n1 = getActiveBits(); + unsigned n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal + if (n1 != n2) + return false; + + // If the number of bits fits in a word, we only need to compare the low word. + if (n1 <= APINT_BITS_PER_WORD) + return pVal[0] == RHS.pVal[0]; + + // Otherwise, compare everything + for (int i = whichWord(n1 - 1); i >= 0; --i) + if (pVal[i] != RHS.pVal[i]) + return false; + return true; +} + +bool APInt::EqualSlowCase(uint64_t Val) const { + unsigned n = getActiveBits(); + if (n <= APINT_BITS_PER_WORD) + return pVal[0] == Val; + else + return false; +} + +bool APInt::ult(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) + return VAL < RHS.VAL; + + // Get active bit length of both operands + unsigned n1 = getActiveBits(); + unsigned n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + unsigned topWord = whichWord(std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) + return false; + if (pVal[i] < RHS.pVal[i]) + return true; + } + return false; +} + +bool APInt::slt(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); + if (isSingleWord()) { + int64_t lhsSext = (int64_t(VAL) << (64-BitWidth)) >> (64-BitWidth); + int64_t rhsSext = (int64_t(RHS.VAL) << (64-BitWidth)) >> (64-BitWidth); + return lhsSext < rhsSext; + } + + APInt lhs(*this); + APInt rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive + lhs.flipAllBits(); + lhs++; + } + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive + rhs.flipAllBits(); + rhs++; + } + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); + else + return true; + else if (rhsNeg) + return false; + else + return lhs.ult(rhs); +} + +void APInt::setBit(unsigned bitPosition) { + if (isSingleWord()) + VAL |= maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); +} + +/// Set the given bit to 0 whose position is given as "bitPosition". +/// @brief Set a given bit to 0. +void APInt::clearBit(unsigned bitPosition) { + if (isSingleWord()) + VAL &= ~maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); +} + +/// @brief Toggle every bit to its opposite value. + +/// Toggle a given bit to its opposite value whose position is given +/// as "bitPosition". +/// @brief Toggles a given bit to its opposite value. +void APInt::flipBit(unsigned bitPosition) { + assert(bitPosition < BitWidth && "Out of the bit-width range!"); + if ((*this)[bitPosition]) clearBit(bitPosition); + else setBit(bitPosition); +} + +unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + size_t slen = str.size(); + + // Each computation below needs to know if it's negative. + StringRef::iterator p = str.begin(); + unsigned isNegative = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + + // For radixes of power-of-two values, the bits required is accurately and + // easily computed + if (radix == 2) + return slen + isNegative; + if (radix == 8) + return slen * 3 + isNegative; + if (radix == 16) + return slen * 4 + isNegative; + + // This is grossly inefficient but accurate. We could probably do something + // with a computation of roughly slen*64/20 and then adjust by the value of + // the first few digits. But, I'm not sure how accurate that could be. + + // Compute a sufficient number of bits that is always large enough but might + // be too large. This avoids the assertion in the constructor. This + // calculation doesn't work appropriately for the numbers 0-9, so just use 4 + // bits in that case. + unsigned sufficient = slen == 1 ? 4 : slen * 64/18; + + // Convert to the actual binary value. + APInt tmp(sufficient, StringRef(p, slen), radix); + + // Compute how many bits are required. If the log is infinite, assume we need + // just bit. + unsigned log = tmp.logBase2(); + if (log == (unsigned)-1) { + return isNegative + 1; + } else { + return isNegative + log + 1; + } +} + +// From http://www.burtleburtle.net, byBob Jenkins. +// When targeting x86, both GCC and LLVM seem to recognize this as a +// rotate instruction. +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +// From http://www.burtleburtle.net, by Bob Jenkins. +#define mix(a,b,c) \ + { \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ + } + +// From http://www.burtleburtle.net, by Bob Jenkins. +#define final(a,b,c) \ + { \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ + } + +// hashword() was adapted from http://www.burtleburtle.net, by Bob +// Jenkins. k is a pointer to an array of uint32_t values; length is +// the length of the key, in 32-bit chunks. This version only handles +// keys that are a multiple of 32 bits in size. +static inline uint32_t hashword(const uint64_t *k64, size_t length) +{ + const uint32_t *k = reinterpret_cast(k64); + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((uint32_t)length)<<2); + + /*------------------------------------------------- handle most of the key */ + while (length > 3) { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch (length) { /* all the case statements fall through */ + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + +// hashword8() was adapted from http://www.burtleburtle.net, by Bob +// Jenkins. This computes a 32-bit hash from one 64-bit word. When +// targeting x86 (32 or 64 bit), both LLVM and GCC compile this +// function into about 35 instructions when inlined. +static inline uint32_t hashword8(const uint64_t k64) +{ + uint32_t a,b,c; + a = b = c = 0xdeadbeef + 4; + b += k64 >> 32; + a += k64 & 0xffffffff; + final(a,b,c); + return c; +} +#undef final +#undef mix +#undef rot + +uint64_t APInt::getHashValue() const { + uint64_t hash; + if (isSingleWord()) + hash = hashword8(VAL); + else + hash = hashword(pVal, getNumWords()*2); + return hash; +} + +/// HiBits - This function returns the high "numBits" bits of this APInt. +APInt APInt::getHiBits(unsigned numBits) const { + return APIntOps::lshr(*this, BitWidth - numBits); +} + +/// LoBits - This function returns the low "numBits" bits of this APInt. +APInt APInt::getLoBits(unsigned numBits) const { + return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits), + BitWidth - numBits); +} + +unsigned APInt::countLeadingZerosSlowCase() const { + // Treat the most significand word differently because it might have + // meaningless bits set beyond the precision. + unsigned BitsInMSW = BitWidth % APINT_BITS_PER_WORD; + integerPart MSWMask; + if (BitsInMSW) MSWMask = (integerPart(1) << BitsInMSW) - 1; + else { + MSWMask = ~integerPart(0); + BitsInMSW = APINT_BITS_PER_WORD; + } + + unsigned i = getNumWords(); + integerPart MSW = pVal[i-1] & MSWMask; + if (MSW) + return CountLeadingZeros_64(MSW) - (APINT_BITS_PER_WORD - BitsInMSW); + + unsigned Count = BitsInMSW; + for (--i; i > 0u; --i) { + if (pVal[i-1] == 0) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; + } + } + return Count; +} + +static unsigned countLeadingOnes_64(uint64_t V, unsigned skip) { + unsigned Count = 0; + if (skip) + V <<= skip; + while (V && (V & (1ULL << 63))) { + Count++; + V <<= 1; + } + return Count; +} + +unsigned APInt::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + unsigned highWordBits = BitWidth % APINT_BITS_PER_WORD; + unsigned shift; + if (!highWordBits) { + highWordBits = APINT_BITS_PER_WORD; + shift = 0; + } else { + shift = APINT_BITS_PER_WORD - highWordBits; + } + int i = getNumWords() - 1; + unsigned Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == -1ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + +unsigned APInt::countTrailingZeros() const { + if (isSingleWord()) + return std::min(unsigned(CountTrailingZeros_64(VAL)), BitWidth); + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == 0; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += CountTrailingZeros_64(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countTrailingOnesSlowCase() const { + unsigned Count = 0; + unsigned i = 0; + for (; i < getNumWords() && pVal[i] == -1ULL; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += CountTrailingOnes_64(pVal[i]); + return std::min(Count, BitWidth); +} + +unsigned APInt::countPopulationSlowCase() const { + unsigned Count = 0; + for (unsigned i = 0; i < getNumWords(); ++i) + Count += CountPopulation_64(pVal[i]); + return Count; +} + +APInt APInt::byteSwap() const { + assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); + if (BitWidth == 16) + return APInt(BitWidth, ByteSwap_16(uint16_t(VAL))); + else if (BitWidth == 32) + return APInt(BitWidth, ByteSwap_32(unsigned(VAL))); + else if (BitWidth == 48) { + unsigned Tmp1 = unsigned(VAL >> 16); + Tmp1 = ByteSwap_32(Tmp1); + uint16_t Tmp2 = uint16_t(VAL); + Tmp2 = ByteSwap_16(Tmp2); + return APInt(BitWidth, (uint64_t(Tmp2) << 32) | Tmp1); + } else if (BitWidth == 64) + return APInt(BitWidth, ByteSwap_64(VAL)); + else { + APInt Result(BitWidth, 0); + char *pByte = (char*)Result.pVal; + for (unsigned i = 0; i < BitWidth / APINT_WORD_SIZE / 2; ++i) { + char Tmp = pByte[i]; + pByte[i] = pByte[BitWidth / APINT_WORD_SIZE - 1 - i]; + pByte[BitWidth / APINT_WORD_SIZE - i - 1] = Tmp; + } + return Result; + } +} + +APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, + const APInt& API2) { + APInt A = API1, B = API2; + while (!!B) { + APInt T = B; + B = APIntOps::urem(A, B); + A = T; + } + return A; +} + +APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) { + union { + double D; + uint64_t I; + } T; + T.D = Double; + + // Get the sign bit from the highest order bit + bool isNeg = T.I >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias + int64_t exp = ((T.I >> 52) & 0x7ff) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. + if (exp < 0) + return APInt(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa + if (exp < 52) + return isNeg ? -APInt(width, mantissa >> (52 - exp)) : + APInt(width, mantissa >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return APInt(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + APInt Tmp(width, mantissa); + Tmp = Tmp.shl((unsigned)exp - 52); + return isNeg ? -Tmp : Tmp; +} + +/// RoundToDouble - This function converts this APInt to a double. +/// The layout for double is as following (IEEE Standard 754): +/// -------------------------------------- +/// | Sign Exponent Fraction Bias | +/// |-------------------------------------- | +/// | 1[63] 11[62-52] 52[51-00] 1023 | +/// -------------------------------------- +double APInt::roundToDouble(bool isSigned) const { + + // Handle the simple case where the value is contained in one uint64_t. + // It is wrong to optimize getWord(0) to VAL; there might be more than one word. + if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { + if (isSigned) { + int64_t sext = (int64_t(getWord(0)) << (64-BitWidth)) >> (64-BitWidth); + return double(sext); + } else + return double(getWord(0)); + } + + // Determine if the value is negative. + bool isNeg = isSigned ? (*this)[BitWidth-1] : false; + + // Construct the absolute value if we're negative. + APInt Tmp(isNeg ? -(*this) : (*this)); + + // Figure out how many bits we're using. + unsigned n = Tmp.getActiveBits(); + + // The exponent (without bias normalization) is just the number of bits + // we are using. Note that the sign bit is gone since we constructed the + // absolute value. + uint64_t exp = n; + + // Return infinity for exponent overflow + if (exp > 1023) { + if (!isSigned || !isNeg) + return std::numeric_limits::infinity(); + else + return -std::numeric_limits::infinity(); + } + exp += 1023; // Increment for 1023 bias + + // Number of bits in mantissa is 52. To obtain the mantissa value, we must + // extract the high 52 bits from the correct words in pVal. + uint64_t mantissa; + unsigned hiWord = whichWord(n-1); + if (hiWord == 0) { + mantissa = Tmp.pVal[0]; + if (n > 52) + mantissa >>= n - 52; // shift down, we want the top 52 bits. + } else { + assert(hiWord > 0 && "huh?"); + uint64_t hibits = Tmp.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD); + uint64_t lobits = Tmp.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD); + mantissa = hibits | lobits; + } + + // The leading bit of mantissa is implicit, so get rid of it. + uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; + union { + double D; + uint64_t I; + } T; + T.I = sign | (exp << 52) | mantissa; + return T.D; +} + +// Truncate to new width. +APInt APInt::trunc(unsigned width) const { + assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width && "Can't truncate to 0 bits"); + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, getRawData()[0]); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + for (i = 0; i != width / APINT_BITS_PER_WORD; i++) + Result.pVal[i] = pVal[i]; + + // Truncate and copy any partial word. + unsigned bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = pVal[i] << bits >> bits; + + return Result; +} + +// Sign extend to a new width. +APInt APInt::sext(unsigned width) const { + assert(width > BitWidth && "Invalid APInt SignExtend request"); + + if (width <= APINT_BITS_PER_WORD) { + uint64_t val = VAL << (APINT_BITS_PER_WORD - BitWidth); + val = (int64_t)val >> (width - BitWidth); + return APInt(width, val >> (APINT_BITS_PER_WORD - width)); + } + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + uint64_t word = 0; + for (i = 0; i != BitWidth / APINT_BITS_PER_WORD; i++) { + word = getRawData()[i]; + Result.pVal[i] = word; + } + + // Read and sign-extend any partial word. + unsigned bits = (0 - BitWidth) % APINT_BITS_PER_WORD; + if (bits != 0) + word = (int64_t)getRawData()[i] << bits >> bits; + else + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); + + // Write remaining full words. + for (; i != width / APINT_BITS_PER_WORD; i++) { + Result.pVal[i] = word; + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); + } + + // Write any partial word. + bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = word << bits >> bits; + + return Result; +} + +// Zero extend to a new width. +APInt APInt::zext(unsigned width) const { + assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, VAL); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy words. + unsigned i; + for (i = 0; i != getNumWords(); i++) + Result.pVal[i] = getRawData()[i]; + + // Zero remaining words. + memset(&Result.pVal[i], 0, (Result.getNumWords() - i) * APINT_WORD_SIZE); + + return Result; +} + +APInt APInt::zextOrTrunc(unsigned width) const { + if (BitWidth < width) + return zext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +APInt APInt::sextOrTrunc(unsigned width) const { + if (BitWidth < width) + return sext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(const APInt &shiftAmt) const { + return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; + + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // undefined + else { + unsigned SignBit = APINT_BITS_PER_WORD - BitWidth; + return APInt(BitWidth, + (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt)); + } + } + + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return APInt(BitWidth, -1ULL, true); + else + return APInt(BitWidth, 0); + } + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // Compute some values needed by the following shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + unsigned breakWord = getNumWords() - 1 - offset; // last word affected + unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (unsigned i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= ~0ULL << bitsInWord; // set high bits + } else { + // Shift the low order words + for (unsigned i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Deal with sign extenstion in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= ~0ULL; + } else + val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); + } + } + + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? -1ULL : 0); + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = fillValue; + return APInt(val, BitWidth).clearUnusedBits(); +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(const APInt &shiftAmt) const { + return lshr((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(unsigned shiftAmt) const { + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + else + return APInt(BitWidth, this->VAL >> shiftAmt); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids + // issues with shifting by the size of the integer type, which produces + // undefined results in the code below. This is also an optimization. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = getNumWords()-1; i >= 0; --i) { + val[i] = (pVal[i] >> shiftAmt) | carry; + carry = pVal[i] << (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < getNumWords() - offset; ++i) + val[i] = pVal[i+offset]; + for (unsigned i = getNumWords()-offset; i < getNumWords(); i++) + val[i] = 0; + return APInt(val,BitWidth).clearUnusedBits(); + } + + // Shift the low order words + unsigned breakWord = getNumWords() - offset -1; + for (unsigned i = 0; i < breakWord; ++i) + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Remaining words are 0 + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); +} + +/// Left-shift this APInt by shiftAmt. +/// @brief Left-shift function. +APInt APInt::shl(const APInt &shiftAmt) const { + // It's undefined behavior in C to shift by BitWidth or greater. + return shl((unsigned)shiftAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::shlSlowCase(unsigned shiftAmt) const { + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // If none of the bits are shifted out, the result is *this. This avoids a + // lshr by the words size in the loop below which can produce incorrect + // results. It also avoids the expensive computation below for a common case. + if (shiftAmt == 0) + return *this; + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (unsigned i = 0; i < getNumWords(); i++) { + val[i] = pVal[i] << shiftAmt | carry; + carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (unsigned i = 0; i < offset; i++) + val[i] = 0; + for (unsigned i = offset; i < getNumWords(); i++) + val[i] = pVal[i-offset]; + return APInt(val,BitWidth).clearUnusedBits(); + } + + // Copy whole words from this to Result. + unsigned i = getNumWords() - 1; + for (; i > offset; --i) + val[i] = pVal[i-offset] << wordShift | + pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = pVal[0] << wordShift; + for (i = 0; i < offset; ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); +} + +APInt APInt::rotl(const APInt &rotateAmt) const { + return rotl((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotl(unsigned rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + APInt hi(*this); + APInt lo(*this); + hi.shl(rotateAmt); + lo.lshr(BitWidth - rotateAmt); + return hi | lo; +} + +APInt APInt::rotr(const APInt &rotateAmt) const { + return rotr((unsigned)rotateAmt.getLimitedValue(BitWidth)); +} + +APInt APInt::rotr(unsigned rotateAmt) const { + if (rotateAmt == 0) + return *this; + // Don't get too fancy, just use existing shift/or facilities + APInt hi(*this); + APInt lo(*this); + lo.lshr(rotateAmt); + hi.shl(BitWidth - rotateAmt); + return hi | lo; +} + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +APInt APInt::sqrt() const { + + // Determine the magnitude of the value. + unsigned magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return APInt(BitWidth, results[ (isSingleWord() ? VAL : pVal[0]) ]); + } + + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) { +#if HAVE_ROUND + return APInt(BitWidth, + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); +#else + return APInt(BitWidth, + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); +#endif + } + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + unsigned nbits = BitWidth, i = 4; + APInt testy(BitWidth, 16); + APInt x_old(BitWidth, 1); + APInt x_new(BitWidth, 0); + APInt two(BitWidth, 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } + + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } + + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + APInt square(x_old * x_old); + APInt nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + APInt midpoint((nextSquare - square).udiv(two)); + APInt offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + llvm_unreachable("Error in APInt::sqrt computation"); + return x_old + 1; +} + +/// Computes the multiplicative inverse of this APInt for a given modulo. The +/// iterative extended Euclidean algorithm is used to solve for this value, +/// however we simplify it to speed up calculating only the inverse, and take +/// advantage of div+rem calculations. We also use some tricks to avoid copying +/// (potentially large) APInts around. +APInt APInt::multiplicativeInverse(const APInt& modulo) const { + assert(ult(modulo) && "This APInt must be smaller than the modulo"); + + // Using the properties listed at the following web page (accessed 06/21/08): + // http://www.numbertheory.org/php/euclid.html + // (especially the properties numbered 3, 4 and 9) it can be proved that + // BitWidth bits suffice for all the computations in the algorithm implemented + // below. More precisely, this number of bits suffice if the multiplicative + // inverse exists, but may not suffice for the general extended Euclidean + // algorithm. + + APInt r[2] = { modulo, *this }; + APInt t[2] = { APInt(BitWidth, 0), APInt(BitWidth, 1) }; + APInt q(BitWidth, 0); + + unsigned i; + for (i = 0; r[i^1] != 0; i ^= 1) { + // An overview of the math without the confusing bit-flipping: + // q = r[i-2] / r[i-1] + // r[i] = r[i-2] % r[i-1] + // t[i] = t[i-2] - t[i-1] * q + udivrem(r[i], r[i^1], q, r[i]); + t[i] -= t[i^1] * q; + } + + // If this APInt and the modulo are not coprime, there is no multiplicative + // inverse, so return 0. We check this by looking at the next-to-last + // remainder, which is the gcd(*this,modulo) as calculated by the Euclidean + // algorithm. + if (r[i] != 1) + return APInt(BitWidth, 0); + + // The next-to-last t is the multiplicative inverse. However, we are + // interested in a positive inverse. Calcuate a positive one from a negative + // one if necessary. A simple addition of the modulo suffices because + // abs(t[i]) is known to be less than *this/2 (see the link above). + return t[i].isNegative() ? t[i] + modulo : t[i]; +} + +/// Calculate the magic numbers required to implement a signed integer division +/// by a constant as a sequence of multiplies, adds and shifts. Requires that +/// the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S. +/// Warren, Jr., chapter 10. +APInt::ms APInt::magic() const { + const APInt& d = *this; + unsigned p; + APInt ad, anc, delta, q1, r1, q2, r2, t; + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + struct ms mag; + + ad = d.abs(); + t = signedMin + (d.lshr(d.getBitWidth() - 1)); + anc = t - 1 - t.urem(ad); // absolute value of nc + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc) + r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc)) + q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d) + r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d)) + do { + p = p + 1; + q1 = q1<<1; // update q1 = 2p/abs(nc) + r1 = r1<<1; // update r1 = rem(2p/abs(nc)) + if (r1.uge(anc)) { // must be unsigned comparison + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = q2<<1; // update q2 = 2p/abs(d) + r2 = r2<<1; // update r2 = rem(2p/abs(d)) + if (r2.uge(ad)) { // must be unsigned comparison + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1.ult(delta) || (q1 == delta && r1 == 0)); + + mag.m = q2 + 1; + if (d.isNegative()) mag.m = -mag.m; // resulting magic number + mag.s = p - d.getBitWidth(); // resulting shift + return mag; +} + +/// Calculate the magic numbers required to implement an unsigned integer +/// division by a constant as a sequence of multiplies, adds and shifts. +/// Requires that the divisor not be 0. Taken from "Hacker's Delight", Henry +/// S. Warren, Jr., chapter 10. +APInt::mu APInt::magicu() const { + const APInt& d = *this; + unsigned p; + APInt nc, delta, q1, r1, q2, r2; + struct mu magu; + magu.a = 0; // initialize "add" indicator + APInt allOnes = APInt::getAllOnesValue(d.getBitWidth()); + APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); + APInt signedMax = APInt::getSignedMaxValue(d.getBitWidth()); + + nc = allOnes - (-d).urem(d); + p = d.getBitWidth() - 1; // initialize p + q1 = signedMin.udiv(nc); // initialize q1 = 2p/nc + r1 = signedMin - q1*nc; // initialize r1 = rem(2p,nc) + q2 = signedMax.udiv(d); // initialize q2 = (2p-1)/d + r2 = signedMax - q2*d; // initialize r2 = rem((2p-1),d) + do { + p = p + 1; + if (r1.uge(nc - r1)) { + q1 = q1 + q1 + 1; // update q1 + r1 = r1 + r1 - nc; // update r1 + } + else { + q1 = q1+q1; // update q1 + r1 = r1+r1; // update r1 + } + if ((r2 + 1).uge(d - r2)) { + if (q2.uge(signedMax)) magu.a = 1; + q2 = q2+q2 + 1; // update q2 + r2 = r2+r2 + 1 - d; // update r2 + } + else { + if (q2.uge(signedMin)) magu.a = 1; + q2 = q2+q2; // update q2 + r2 = r2+r2 + 1; // update r2 + } + delta = d - 1 - r2; + } while (p < d.getBitWidth()*2 && + (q1.ult(delta) || (q1 == delta && r1 == 0))); + magu.m = q2 + 1; // resulting magic number + magu.s = p - d.getBitWidth(); // resulting shift + return magu; +} + +/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) +/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The +/// variables here have the same names as in the algorithm. Comments explain +/// the algorithm and any deviation from it. +static void KnuthDiv(unsigned *u, unsigned *v, unsigned *q, unsigned* r, + unsigned m, unsigned n) { + assert(u && "Must provide dividend"); + assert(v && "Must provide divisor"); + assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); + assert(n>1 && "n must be > 1"); + + // Knuth uses the value b as the base of the number system. In our case b + // is 2^31 so we just set it to -1u. + uint64_t b = uint64_t(1) << 32; + +#if 0 + DEBUG(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n'); + DEBUG(dbgs() << "KnuthDiv: original:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << " by"); + DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]); + DEBUG(dbgs() << '\n'); +#endif + // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of + // u and v by d. Note that we have taken Knuth's advice here to use a power + // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of + // 2 allows us to shift instead of multiply and it is easy to determine the + // shift amount from the leading zeros. We are basically normalizing the u + // and v so that its high bits are shifted to the top of v's range without + // overflow. Note that this can require an extra word in u so that u must + // be of length m+n+1. + unsigned shift = CountLeadingZeros_32(v[n-1]); + unsigned v_carry = 0; + unsigned u_carry = 0; + if (shift) { + for (unsigned i = 0; i < m+n; ++i) { + unsigned u_tmp = u[i] >> (32 - shift); + u[i] = (u[i] << shift) | u_carry; + u_carry = u_tmp; + } + for (unsigned i = 0; i < n; ++i) { + unsigned v_tmp = v[i] >> (32 - shift); + v[i] = (v[i] << shift) | v_carry; + v_carry = v_tmp; + } + } + u[m+n] = u_carry; +#if 0 + DEBUG(dbgs() << "KnuthDiv: normal:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << " by"); + DEBUG(for (int i = n; i >0; i--) dbgs() << " " << v[i-1]); + DEBUG(dbgs() << '\n'); +#endif + + // D2. [Initialize j.] Set j to m. This is the loop counter over the places. + int j = m; + do { + DEBUG(dbgs() << "KnuthDiv: quotient digit #" << j << '\n'); + // D3. [Calculate q'.]. + // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') + // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') + // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease + // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test + // on v[n-2] determines at high speed most of the cases in which the trial + // value qp is one too large, and it eliminates all cases where qp is two + // too large. + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + DEBUG(dbgs() << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; + if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + qp--; + rp += v[n-1]; + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) + qp--; + } + DEBUG(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); + + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (unsigned i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + DEBUG(dbgs() << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n'); + + uint64_t result = u_tmp - subtrahend; + unsigned k = j + i; + u[k++] = (unsigned)(result & (b-1)); // subtract low word + u[k++] = (unsigned)(result >> 32); // subtract high word + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + DEBUG(dbgs() << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n'); + } + DEBUG(dbgs() << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << '\n'); + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (unsigned i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; + } + } + DEBUG(dbgs() << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() << " " << u[i]); + DEBUG(dbgs() << '\n'); + + // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was + // negative, go to step D6; otherwise go on to step D7. + q[j] = (unsigned)qp; + if (isNeg) { + // D6. [Add back]. The probability that this step is necessary is very + // small, on the order of only 2/b. Make sure that test data accounts for + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; + for (unsigned i = 0; i < n; i++) { + unsigned limit = std::min(u[j+i],v[i]); + u[j+i] += v[i] + carry; + carry = u[j+i] < limit || (carry && u[j+i] == limit); + } + u[j+n] += carry; + } + DEBUG(dbgs() << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) dbgs() <<" " << u[i]); + DEBUG(dbgs() << "\nKnuthDiv: digit result = " << q[j] << '\n'); + + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + DEBUG(dbgs() << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) dbgs() <<" " << q[i]); + DEBUG(dbgs() << '\n'); + + // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired + // remainder may be obtained by dividing u[...] by d. If r is non-null we + // compute the remainder (urem uses this). + if (r) { + // The value d is expressed by the "shift" value above since we avoided + // multiplication by d by using a shift left. So, all we have to do is + // shift right here. In order to mak + if (shift) { + unsigned carry = 0; + DEBUG(dbgs() << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = (u[i] >> shift) | carry; + carry = u[i] << (32 - shift); + DEBUG(dbgs() << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + DEBUG(dbgs() << " " << r[i]); + } + } + DEBUG(dbgs() << '\n'); + } +#if 0 + DEBUG(dbgs() << '\n'); +#endif +} + +void APInt::divide(const APInt LHS, unsigned lhsWords, + const APInt &RHS, unsigned rhsWords, + APInt *Quotient, APInt *Remainder) +{ + assert(lhsWords >= rhsWords && "Fractional result"); + + // First, compose the values into an array of 32-bit words instead of + // 64-bit words. This is a necessity of both the "short division" algorithm + // and the Knuth "classical algorithm" which requires there to be native + // operations for +, -, and * on an m bit value with an m*2 bit result. We + // can't use 64-bit operands here because we don't have native results of + // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't + // work on large-endian machines. + uint64_t mask = ~0ull >> (sizeof(unsigned)*CHAR_BIT); + unsigned n = rhsWords * 2; + unsigned m = (lhsWords * 2) - n; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + unsigned SPACE[128]; + unsigned *U = 0; + unsigned *V = 0; + unsigned *Q = 0; + unsigned *R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + U = &SPACE[0]; + V = &SPACE[m+n+1]; + Q = &SPACE[(m+n+1) + n]; + if (Remainder) + R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + U = new unsigned[m + n + 1]; + V = new unsigned[n]; + Q = new unsigned[m+n]; + if (Remainder) + R = new unsigned[n]; + } + + // Initialize the dividend + memset(U, 0, (m+n+1)*sizeof(unsigned)); + for (unsigned i = 0; i < lhsWords; ++i) { + uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); + U[i * 2] = (unsigned)(tmp & mask); + U[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. + + // Initialize the divisor + memset(V, 0, (n)*sizeof(unsigned)); + for (unsigned i = 0; i < rhsWords; ++i) { + uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); + V[i * 2] = (unsigned)(tmp & mask); + V[i * 2 + 1] = (unsigned)(tmp >> (sizeof(unsigned)*CHAR_BIT)); + } + + // initialize the quotient and remainder + memset(Q, 0, (m+n) * sizeof(unsigned)); + if (Remainder) + memset(R, 0, n * sizeof(unsigned)); + + // Now, adjust m and n for the Knuth division. n is the number of words in + // the divisor. m is the number of words by which the dividend exceeds the + // divisor (i.e. m+n is the length of the dividend). These sizes must not + // contain any zero words or the Knuth algorithm fails. + for (unsigned i = n; i > 0 && V[i-1] == 0; i--) { + n--; + m++; + } + for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--) + m--; + + // If we're left with only a single word for the divisor, Knuth doesn't work + // so we implement the short division algorithm here. This is much simpler + // and faster because we are certain that we can divide a 64-bit quantity + // by a 32-bit quantity at hardware speed and short division is simply a + // series of such operations. This is just like doing short division but we + // are using base 2^32 instead of base 10. + assert(n != 0 && "Divide by zero?"); + if (n == 1) { + unsigned divisor = V[0]; + unsigned remainder = 0; + for (int i = m+n-1; i >= 0; i--) { + uint64_t partial_dividend = uint64_t(remainder) << 32 | U[i]; + if (partial_dividend == 0) { + Q[i] = 0; + remainder = 0; + } else if (partial_dividend < divisor) { + Q[i] = 0; + remainder = (unsigned)partial_dividend; + } else if (partial_dividend == divisor) { + Q[i] = 1; + remainder = 0; + } else { + Q[i] = (unsigned)(partial_dividend / divisor); + remainder = (unsigned)(partial_dividend - (Q[i] * divisor)); + } + } + if (R) + R[0] = remainder; + } else { + // Now we're ready to invoke the Knuth classical divide algorithm. In this + // case n > 1. + KnuthDiv(U, V, Q, R, m, n); + } + + // If the caller wants the quotient + if (Quotient) { + // Set up the Quotient value's memory. + if (Quotient->BitWidth != LHS.BitWidth) { + if (Quotient->isSingleWord()) + Quotient->VAL = 0; + else + delete [] Quotient->pVal; + Quotient->BitWidth = LHS.BitWidth; + if (!Quotient->isSingleWord()) + Quotient->pVal = getClearedMemory(Quotient->getNumWords()); + } else + Quotient->clearAllBits(); + + // The quotient is in Q. Reconstitute the quotient into Quotient's low + // order words. + if (lhsWords == 1) { + uint64_t tmp = + uint64_t(Q[0]) | (uint64_t(Q[1]) << (APINT_BITS_PER_WORD / 2)); + if (Quotient->isSingleWord()) + Quotient->VAL = tmp; + else + Quotient->pVal[0] = tmp; + } else { + assert(!Quotient->isSingleWord() && "Quotient APInt not large enough"); + for (unsigned i = 0; i < lhsWords; ++i) + Quotient->pVal[i] = + uint64_t(Q[i*2]) | (uint64_t(Q[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // If the caller wants the remainder + if (Remainder) { + // Set up the Remainder value's memory. + if (Remainder->BitWidth != RHS.BitWidth) { + if (Remainder->isSingleWord()) + Remainder->VAL = 0; + else + delete [] Remainder->pVal; + Remainder->BitWidth = RHS.BitWidth; + if (!Remainder->isSingleWord()) + Remainder->pVal = getClearedMemory(Remainder->getNumWords()); + } else + Remainder->clearAllBits(); + + // The remainder is in R. Reconstitute the remainder into Remainder's low + // order words. + if (rhsWords == 1) { + uint64_t tmp = + uint64_t(R[0]) | (uint64_t(R[1]) << (APINT_BITS_PER_WORD / 2)); + if (Remainder->isSingleWord()) + Remainder->VAL = tmp; + else + Remainder->pVal[0] = tmp; + } else { + assert(!Remainder->isSingleWord() && "Remainder APInt not large enough"); + for (unsigned i = 0; i < rhsWords; ++i) + Remainder->pVal[i] = + uint64_t(R[i*2]) | (uint64_t(R[i*2+1]) << (APINT_BITS_PER_WORD / 2)); + } + } + + // Clean up the memory we allocated. + if (U != &SPACE[0]) { + delete [] U; + delete [] V; + delete [] Q; + delete [] R; + } +} + +APInt APInt::udiv(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + return APInt(BitWidth, VAL / RHS.VAL); + } + + // Get some facts about the LHS and RHS number of bits and words + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Divided by zero???"); + unsigned lhsBits = this->getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + + // Deal with some degenerate cases + if (!lhsWords) + // 0 / X ===> 0 + return APInt(BitWidth, 0); + else if (lhsWords < rhsWords || this->ult(RHS)) { + // X / Y ===> 0, iff X < Y + return APInt(BitWidth, 0); + } else if (*this == RHS) { + // X / X ===> 1 + return APInt(BitWidth, 1); + } else if (lhsWords == 1 && rhsWords == 1) { + // All high words are zero, just use native divide + return APInt(BitWidth, this->pVal[0] / RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Quotient(1,0); // to hold result. + divide(*this, lhsWords, RHS, rhsWords, &Quotient, 0); + return Quotient; +} + +APInt APInt::urem(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) { + assert(RHS.VAL != 0 && "Remainder by zero?"); + return APInt(BitWidth, VAL % RHS.VAL); + } + + // Get some facts about the LHS + unsigned lhsBits = getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); + + // Get some facts about the RHS + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + assert(rhsWords && "Performing remainder operation by zero ???"); + + // Check the degenerate cases + if (lhsWords == 0) { + // 0 % Y ===> 0 + return APInt(BitWidth, 0); + } else if (lhsWords < rhsWords || this->ult(RHS)) { + // X % Y ===> X, iff X < Y + return *this; + } else if (*this == RHS) { + // X % X == 0; + return APInt(BitWidth, 0); + } else if (lhsWords == 1) { + // All high words are zero, just use native remainder + return APInt(BitWidth, pVal[0] % RHS.pVal[0]); + } + + // We have to compute it the hard way. Invoke the Knuth divide algorithm. + APInt Remainder(1,0); + divide(*this, lhsWords, RHS, rhsWords, 0, &Remainder); + return Remainder; +} + +void APInt::udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) { + // Get some size facts about the dividend and divisor + unsigned lhsBits = LHS.getActiveBits(); + unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); + unsigned rhsBits = RHS.getActiveBits(); + unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1); + + // Check the degenerate cases + if (lhsWords == 0) { + Quotient = 0; // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 + return; + } + + if (lhsWords < rhsWords || LHS.ult(RHS)) { + Remainder = LHS; // X % Y ===> X, iff X < Y + Quotient = 0; // X / Y ===> 0, iff X < Y + return; + } + + if (LHS == RHS) { + Quotient = 1; // X / X ===> 1 + Remainder = 0; // X % X ===> 0; + return; + } + + if (lhsWords == 1 && rhsWords == 1) { + // There is only one word to consider so use the native versions. + uint64_t lhsValue = LHS.isSingleWord() ? LHS.VAL : LHS.pVal[0]; + uint64_t rhsValue = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; + Quotient = APInt(LHS.getBitWidth(), lhsValue / rhsValue); + Remainder = APInt(LHS.getBitWidth(), lhsValue % rhsValue); + return; + } + + // Okay, lets do it the long way + divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); +} + +APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = isNonNegative() == RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::uadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = Res.ult(RHS); + return Res; +} + +APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this - RHS; + Overflow = isNonNegative() != RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::usub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this-RHS; + Overflow = Res.ugt(*this); + return Res; +} + +APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) const { + // MININT/-1 --> overflow. + Overflow = isMinSignedValue() && RHS.isAllOnesValue(); + return sdiv(RHS); +} + +APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this * RHS; + + if (*this != 0 && RHS != 0) + Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS; + else + Overflow = false; + return Res; +} + +APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { + Overflow = ShAmt >= getBitWidth(); + if (Overflow) + ShAmt = getBitWidth()-1; + + if (isNonNegative()) // Don't allow sign change. + Overflow = ShAmt >= countLeadingZeros(); + else + Overflow = ShAmt >= countLeadingOnes(); + + return *this << ShAmt; +} + + + + +void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { + // Check our assumptions here + assert(!str.empty() && "Invalid string length"); + assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + bool isNeg = *p == '-'; + if (*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String is only a sign, needs a value."); + } + assert((slen <= numbits || radix != 2) && "Insufficient bit width"); + assert(((slen-1)*3 <= numbits || radix != 8) && "Insufficient bit width"); + assert(((slen-1)*4 <= numbits || radix != 16) && "Insufficient bit width"); + assert((((slen-1)*64)/22 <= numbits || radix != 10) && + "Insufficient bit width"); + + // Allocate memory + if (!isSingleWord()) + pVal = getClearedMemory(getNumWords()); + + // Figure out if we can shift instead of multiply + unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); + + // Set up an APInt for the digit to add outside the loop so we don't + // constantly construct/destruct it. + APInt apdigit(getBitWidth(), 0); + APInt apradix(getBitWidth(), radix); + + // Enter digit traversal loop + for (StringRef::iterator e = str.end(); p != e; ++p) { + unsigned digit = getDigit(*p, radix); + assert(digit < radix && "Invalid character in digit string"); + + // Shift or multiply the value by the radix + if (slen > 1) { + if (shift) + *this <<= shift; + else + *this *= apradix; + } + + // Add in the digit we just interpreted + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; + *this += apdigit; + } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flipAllBits(); + } +} + +void APInt::toString(SmallVectorImpl &Str, unsigned Radix, + bool Signed) const { + assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2) && + "Radix should be 2, 8, 10, or 16!"); + + // First, check for a zero value and just short circuit the logic below. + if (*this == 0) { + Str.push_back('0'); + return; + } + + static const char Digits[] = "0123456789ABCDEF"; + + if (isSingleWord()) { + char Buffer[65]; + char *BufPtr = Buffer+65; + + uint64_t N; + if (!Signed) { + N = getZExtValue(); + } else { + int64_t I = getSExtValue(); + if (I >= 0) { + N = I; + } else { + Str.push_back('-'); + N = -(uint64_t)I; + } + } + + while (N) { + *--BufPtr = Digits[N % Radix]; + N /= Radix; + } + Str.append(BufPtr, Buffer+65); + return; + } + + APInt Tmp(*this); + + if (Signed && isNegative()) { + // They want to print the signed version and it is a negative value + // Flip the bits and add one to turn it into the equivalent positive + // value and put a '-' in the result. + Tmp.flipAllBits(); + Tmp++; + Str.push_back('-'); + } + + // We insert the digits backward, then reverse them to get the right order. + unsigned StartDig = Str.size(); + + // For the 2, 8 and 16 bit cases, we can just shift instead of divide + // because the number of bits per digit (1, 3 and 4 respectively) divides + // equaly. We just shift until the value is zero. + if (Radix != 10) { + // Just shift tmp right for each digit width until it becomes zero + unsigned ShiftAmt = (Radix == 16 ? 4 : (Radix == 8 ? 3 : 1)); + unsigned MaskAmt = Radix - 1; + + while (Tmp != 0) { + unsigned Digit = unsigned(Tmp.getRawData()[0]) & MaskAmt; + Str.push_back(Digits[Digit]); + Tmp = Tmp.lshr(ShiftAmt); + } + } else { + APInt divisor(4, 10); + while (Tmp != 0) { + APInt APdigit(1, 0); + APInt tmp2(Tmp.getBitWidth(), 0); + divide(Tmp, Tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, + &APdigit); + unsigned Digit = (unsigned)APdigit.getZExtValue(); + assert(Digit < Radix && "divide failed"); + Str.push_back(Digits[Digit]); + Tmp = tmp2; + } + } + + // Reverse the digits before returning. + std::reverse(Str.begin()+StartDig, Str.end()); +} + +/// toString - This returns the APInt as a std::string. Note that this is an +/// inefficient method. It is better to pass in a SmallVector/SmallString +/// to the methods above. +std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const { + SmallString<40> S; + toString(S, Radix, Signed); + return S.str(); +} + + +void APInt::dump() const { + SmallString<40> S, U; + this->toStringUnsigned(U); + this->toStringSigned(S); + dbgs() << "APInt(" << BitWidth << "b, " + << U.str() << "u " << S.str() << "s)"; +} + +void APInt::print(raw_ostream &OS, bool isSigned) const { + SmallString<40> S; + this->toString(S, 10, isSigned); + OS << S.str(); +} + +// This implements a variety of operations on a representation of +// arbitrary precision, two's-complement, bignum integer values. + +// Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe +// and unrestricting assumption. +#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] +COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); + +/* Some handy functions local to this file. */ +namespace { + + /* Returns the integer part with the least significant BITS set. + BITS cannot be zero. */ + static inline integerPart + lowBitMask(unsigned int bits) + { + assert(bits != 0 && bits <= integerPartWidth); + + return ~(integerPart) 0 >> (integerPartWidth - bits); + } + + /* Returns the value of the lower half of PART. */ + static inline integerPart + lowHalf(integerPart part) + { + return part & lowBitMask(integerPartWidth / 2); + } + + /* Returns the value of the upper half of PART. */ + static inline integerPart + highHalf(integerPart part) + { + return part >> (integerPartWidth / 2); + } + + /* Returns the bit number of the most significant set bit of a part. + If the input number has no bits set -1U is returned. */ + static unsigned int + partMSB(integerPart value) + { + unsigned int n, msb; + + if (value == 0) + return -1U; + + n = integerPartWidth / 2; + + msb = 0; + do { + if (value >> n) { + value >>= n; + msb += n; + } + + n >>= 1; + } while (n); + + return msb; + } + + /* Returns the bit number of the least significant set bit of a + part. If the input number has no bits set -1U is returned. */ + static unsigned int + partLSB(integerPart value) + { + unsigned int n, lsb; + + if (value == 0) + return -1U; + + lsb = integerPartWidth - 1; + n = integerPartWidth / 2; + + do { + if (value << n) { + value <<= n; + lsb -= n; + } + + n >>= 1; + } while (n); + + return lsb; + } +} + +/* Sets the least significant part of a bignum to the input value, and + zeroes out higher parts. */ +void +APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts) +{ + unsigned int i; + + assert(parts > 0); + + dst[0] = part; + for (i = 1; i < parts; i++) + dst[i] = 0; +} + +/* Assign one bignum to another. */ +void +APInt::tcAssign(integerPart *dst, const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] = src[i]; +} + +/* Returns true if a bignum is zero, false otherwise. */ +bool +APInt::tcIsZero(const integerPart *src, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + if (src[i]) + return false; + + return true; +} + +/* Extract the given bit of a bignum; returns 0 or 1. */ +int +APInt::tcExtractBit(const integerPart *parts, unsigned int bit) +{ + return (parts[bit / integerPartWidth] & + ((integerPart) 1 << bit % integerPartWidth)) != 0; +} + +/* Set the given bit of a bignum. */ +void +APInt::tcSetBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth); +} + +/* Clears the given bit of a bignum. */ +void +APInt::tcClearBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] &= + ~((integerPart) 1 << (bit % integerPartWidth)); +} + +/* Returns the bit number of the least significant set bit of a + number. If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcLSB(const integerPart *parts, unsigned int n) +{ + unsigned int i, lsb; + + for (i = 0; i < n; i++) { + if (parts[i] != 0) { + lsb = partLSB(parts[i]); + + return lsb + i * integerPartWidth; + } + } + + return -1U; +} + +/* Returns the bit number of the most significant set bit of a number. + If the input number has no bits set -1U is returned. */ +unsigned int +APInt::tcMSB(const integerPart *parts, unsigned int n) +{ + unsigned int msb; + + do { + --n; + + if (parts[n] != 0) { + msb = partMSB(parts[n]); + + return msb + n * integerPartWidth; + } + } while (n); + + return -1U; +} + +/* Copy the bit vector of width srcBITS from SRC, starting at bit + srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes + the least significant bit of DST. All high bits above srcBITS in + DST are zero-filled. */ +void +APInt::tcExtract(integerPart *dst, unsigned int dstCount,const integerPart *src, + unsigned int srcBits, unsigned int srcLSB) +{ + unsigned int firstSrcPart, dstParts, shift, n; + + dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth; + assert(dstParts <= dstCount); + + firstSrcPart = srcLSB / integerPartWidth; + tcAssign (dst, src + firstSrcPart, dstParts); + + shift = srcLSB % integerPartWidth; + tcShiftRight (dst, dstParts, shift); + + /* We now have (dstParts * integerPartWidth - shift) bits from SRC + in DST. If this is less that srcBits, append the rest, else + clear the high bits. */ + n = dstParts * integerPartWidth - shift; + if (n < srcBits) { + integerPart mask = lowBitMask (srcBits - n); + dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask) + << n % integerPartWidth); + } else if (n > srcBits) { + if (srcBits % integerPartWidth) + dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth); + } + + /* Clear high parts. */ + while (dstParts < dstCount) + dst[dstParts++] = 0; +} + +/* DST += RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcAdd(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for (i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] += rhs[i] + 1; + c = (dst[i] <= l); + } else { + dst[i] += rhs[i]; + c = (dst[i] < l); + } + } + + return c; +} + +/* DST -= RHS + C where C is zero or one. Returns the carry flag. */ +integerPart +APInt::tcSubtract(integerPart *dst, const integerPart *rhs, + integerPart c, unsigned int parts) +{ + unsigned int i; + + assert(c <= 1); + + for (i = 0; i < parts; i++) { + integerPart l; + + l = dst[i]; + if (c) { + dst[i] -= rhs[i] + 1; + c = (dst[i] >= l); + } else { + dst[i] -= rhs[i]; + c = (dst[i] > l); + } + } + + return c; +} + +/* Negate a bignum in-place. */ +void +APInt::tcNegate(integerPart *dst, unsigned int parts) +{ + tcComplement(dst, parts); + tcIncrement(dst, parts); +} + +/* DST += SRC * MULTIPLIER + CARRY if add is true + DST = SRC * MULTIPLIER + CARRY if add is false + + Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + they must start at the same point, i.e. DST == SRC. + + If DSTPARTS == SRCPARTS + 1 no overflow occurs and zero is + returned. Otherwise DST is filled with the least significant + DSTPARTS parts of the result, and if all of the omitted higher + parts were zero return zero, otherwise overflow occurred and + return one. */ +int +APInt::tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add) +{ + unsigned int i, n; + + /* Otherwise our writes of DST kill our later reads of SRC. */ + assert(dst <= src || dst >= src + srcParts); + assert(dstParts <= srcParts + 1); + + /* N loops; minimum of dstParts and srcParts. */ + n = dstParts < srcParts ? dstParts: srcParts; + + for (i = 0; i < n; i++) { + integerPart low, mid, high, srcPart; + + /* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY. + + This cannot overflow, because + + (n - 1) * (n - 1) + 2 (n - 1) = (n - 1) * (n + 1) + + which is less than n^2. */ + + srcPart = src[i]; + + if (multiplier == 0 || srcPart == 0) { + low = carry; + high = 0; + } else { + low = lowHalf(srcPart) * lowHalf(multiplier); + high = highHalf(srcPart) * highHalf(multiplier); + + mid = lowHalf(srcPart) * highHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + mid = highHalf(srcPart) * lowHalf(multiplier); + high += highHalf(mid); + mid <<= integerPartWidth / 2; + if (low + mid < low) + high++; + low += mid; + + /* Now add carry. */ + if (low + carry < low) + high++; + low += carry; + } + + if (add) { + /* And now DST[i], and store the new low part there. */ + if (low + dst[i] < low) + high++; + dst[i] += low; + } else + dst[i] = low; + + carry = high; + } + + if (i < dstParts) { + /* Full multiplication, there is no overflow. */ + assert(i + 1 == dstParts); + dst[i] = carry; + return 0; + } else { + /* We overflowed if there is carry. */ + if (carry) + return 1; + + /* We would overflow if any significant unwritten parts would be + non-zero. This is true if any remaining src parts are non-zero + and the multiplier is non-zero. */ + if (multiplier) + for (; i < srcParts; i++) + if (src[i]) + return 1; + + /* We fitted in the narrow destination. */ + return 0; + } +} + +/* DST = LHS * RHS, where DST has the same width as the operands and + is filled with the least significant parts of the result. Returns + one if overflow occurred, otherwise zero. DST must be disjoint + from both operands. */ +int +APInt::tcMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + int overflow; + + assert(dst != lhs && dst != rhs); + + overflow = 0; + tcSet(dst, 0, parts); + + for (i = 0; i < parts; i++) + overflow |= tcMultiplyPart(&dst[i], lhs, rhs[i], 0, parts, + parts - i, true); + + return overflow; +} + +/* DST = LHS * RHS, where DST has width the sum of the widths of the + operands. No overflow occurs. DST must be disjoint from both + operands. Returns the number of parts required to hold the + result. */ +unsigned int +APInt::tcFullMultiply(integerPart *dst, const integerPart *lhs, + const integerPart *rhs, unsigned int lhsParts, + unsigned int rhsParts) +{ + /* Put the narrower number on the LHS for less loops below. */ + if (lhsParts > rhsParts) { + return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts); + } else { + unsigned int n; + + assert(dst != lhs && dst != rhs); + + tcSet(dst, 0, rhsParts); + + for (n = 0; n < lhsParts; n++) + tcMultiplyPart(&dst[n], rhs, lhs[n], 0, rhsParts, rhsParts + 1, true); + + n = lhsParts + rhsParts; + + return n - (dst[n - 1] == 0); + } +} + +/* If RHS is zero LHS and REMAINDER are left unchanged, return one. + Otherwise set LHS to LHS / RHS with the fractional part discarded, + set REMAINDER to the remainder, return zero. i.e. + + OLD_LHS = RHS * LHS + REMAINDER + + SCRATCH is a bignum of the same size as the operands and result for + use by the routine; its contents need not be initialized and are + destroyed. LHS, REMAINDER and SCRATCH must be distinct. +*/ +int +APInt::tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *srhs, + unsigned int parts) +{ + unsigned int n, shiftCount; + integerPart mask; + + assert(lhs != remainder && lhs != srhs && remainder != srhs); + + shiftCount = tcMSB(rhs, parts) + 1; + if (shiftCount == 0) + return true; + + shiftCount = parts * integerPartWidth - shiftCount; + n = shiftCount / integerPartWidth; + mask = (integerPart) 1 << (shiftCount % integerPartWidth); + + tcAssign(srhs, rhs, parts); + tcShiftLeft(srhs, parts, shiftCount); + tcAssign(remainder, lhs, parts); + tcSet(lhs, 0, parts); + + /* Loop, subtracting SRHS if REMAINDER is greater and adding that to + the total. */ + for (;;) { + int compare; + + compare = tcCompare(remainder, srhs, parts); + if (compare >= 0) { + tcSubtract(remainder, srhs, 0, parts); + lhs[n] |= mask; + } + + if (shiftCount == 0) + break; + shiftCount--; + tcShiftRight(srhs, parts, 1); + if ((mask >>= 1) == 0) + mask = (integerPart) 1 << (integerPartWidth - 1), n--; + } + + return false; +} + +/* Shift a bignum left COUNT bits in-place. Shifted in bits are zero. + There are no restrictions on COUNT. */ +void +APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + while (parts > jump) { + integerPart part; + + parts--; + + /* dst[i] comes from the two parts src[i - jump] and, if we have + an intra-part shift, src[i - jump - 1]. */ + part = dst[parts - jump]; + if (shift) { + part <<= shift; + if (parts >= jump + 1) + part |= dst[parts - jump - 1] >> (integerPartWidth - shift); + } + + dst[parts] = part; + } + + while (parts > 0) + dst[--parts] = 0; + } +} + +/* Shift a bignum right COUNT bits in-place. Shifted in bits are + zero. There are no restrictions on COUNT. */ +void +APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count) +{ + if (count) { + unsigned int i, jump, shift; + + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; + + /* Perform the shift. This leaves the most significant COUNT bits + of the result at zero. */ + for (i = 0; i < parts; i++) { + integerPart part; + + if (i + jump >= parts) { + part = 0; + } else { + part = dst[i + jump]; + if (shift) { + part >>= shift; + if (i + jump + 1 < parts) + part |= dst[i + jump + 1] << (integerPartWidth - shift); + } + } + + dst[i] = part; + } + } +} + +/* Bitwise and of two bignums. */ +void +APInt::tcAnd(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] &= rhs[i]; +} + +/* Bitwise inclusive or of two bignums. */ +void +APInt::tcOr(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] |= rhs[i]; +} + +/* Bitwise exclusive or of two bignums. */ +void +APInt::tcXor(integerPart *dst, const integerPart *rhs, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] ^= rhs[i]; +} + +/* Complement a bignum in-place. */ +void +APInt::tcComplement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + dst[i] = ~dst[i]; +} + +/* Comparison (unsigned) of two bignums. */ +int +APInt::tcCompare(const integerPart *lhs, const integerPart *rhs, + unsigned int parts) +{ + while (parts) { + parts--; + if (lhs[parts] == rhs[parts]) + continue; + + if (lhs[parts] > rhs[parts]) + return 1; + else + return -1; + } + + return 0; +} + +/* Increment a bignum in-place, return the carry flag. */ +integerPart +APInt::tcIncrement(integerPart *dst, unsigned int parts) +{ + unsigned int i; + + for (i = 0; i < parts; i++) + if (++dst[i] != 0) + break; + + return i == parts; +} + +/* Set the least significant BITS bits of a bignum, clear the + rest. */ +void +APInt::tcSetLeastSignificantBits(integerPart *dst, unsigned int parts, + unsigned int bits) +{ + unsigned int i; + + i = 0; + while (bits > integerPartWidth) { + dst[i++] = ~(integerPart) 0; + bits -= integerPartWidth; + } + + if (bits) + dst[i++] = ~(integerPart) 0 >> (integerPartWidth - bits); + + while (i < parts) + dst[i++] = 0; +} diff --git a/final/lib/Support/APSInt.cpp b/final/lib/Support/APSInt.cpp new file mode 100644 index 00000000000..73acafa690c --- /dev/null +++ b/final/lib/Support/APSInt.cpp @@ -0,0 +1,23 @@ +//===-- llvm/ADT/APSInt.cpp - Arbitrary Precision Signed Int ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" + +using namespace llvm; + +void APSInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger((unsigned) (IsUnsigned ? 1 : 0)); + APInt::Profile(ID); +} diff --git a/final/lib/Support/Allocator.cpp b/final/lib/Support/Allocator.cpp new file mode 100644 index 00000000000..5e27df6628e --- /dev/null +++ b/final/lib/Support/Allocator.cpp @@ -0,0 +1,180 @@ +//===--- Allocator.cpp - Simple memory allocation abstraction -------------===// +// +// 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 BumpPtrAllocator interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Recycler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Memory.h" +#include + +namespace llvm { + +BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold, + SlabAllocator &allocator) + : SlabSize(size), SizeThreshold(threshold), Allocator(allocator), + CurSlab(0), BytesAllocated(0) { } + +BumpPtrAllocator::~BumpPtrAllocator() { + DeallocateSlabs(CurSlab); +} + +/// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should +/// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and +/// AlignPtr(8, 4) == 8. +char *BumpPtrAllocator::AlignPtr(char *Ptr, size_t Alignment) { + assert(Alignment && (Alignment & (Alignment - 1)) == 0 && + "Alignment is not a power of two!"); + + // Do the alignment. + return (char*)(((uintptr_t)Ptr + Alignment - 1) & + ~(uintptr_t)(Alignment - 1)); +} + +/// StartNewSlab - Allocate a new slab and move the bump pointers over into +/// the new slab. Modifies CurPtr and End. +void BumpPtrAllocator::StartNewSlab() { + // If we allocated a big number of slabs already it's likely that we're going + // to allocate more. Increase slab size to reduce mallocs and possibly memory + // overhead. The factors are chosen conservatively to avoid overallocation. + if (BytesAllocated >= SlabSize * 128) + SlabSize *= 2; + + MemSlab *NewSlab = Allocator.Allocate(SlabSize); + NewSlab->NextPtr = CurSlab; + CurSlab = NewSlab; + CurPtr = (char*)(CurSlab + 1); + End = ((char*)CurSlab) + CurSlab->Size; +} + +/// DeallocateSlabs - Deallocate all memory slabs after and including this +/// one. +void BumpPtrAllocator::DeallocateSlabs(MemSlab *Slab) { + while (Slab) { + MemSlab *NextSlab = Slab->NextPtr; +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(Slab + 1, Slab->Size - sizeof(MemSlab)); + memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab)); +#endif + Allocator.Deallocate(Slab); + Slab = NextSlab; + } +} + +/// Reset - Deallocate all but the current slab and reset the current pointer +/// to the beginning of it, freeing all memory allocated so far. +void BumpPtrAllocator::Reset() { + if (!CurSlab) + return; + DeallocateSlabs(CurSlab->NextPtr); + CurSlab->NextPtr = 0; + CurPtr = (char*)(CurSlab + 1); + End = ((char*)CurSlab) + CurSlab->Size; +} + +/// Allocate - Allocate space at the specified alignment. +/// +void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) { + if (!CurSlab) // Start a new slab if we haven't allocated one already. + StartNewSlab(); + + // Keep track of how many bytes we've allocated. + BytesAllocated += Size; + + // 0-byte alignment means 1-byte alignment. + if (Alignment == 0) Alignment = 1; + + // Allocate the aligned space, going forwards from CurPtr. + char *Ptr = AlignPtr(CurPtr, Alignment); + + // Check if we can hold it. + if (Ptr + Size <= End) { + CurPtr = Ptr + Size; + return Ptr; + } + + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1; + if (PaddedSize > SizeThreshold) { + MemSlab *NewSlab = Allocator.Allocate(PaddedSize); + + // Put the new slab after the current slab, since we are not allocating + // into it. + NewSlab->NextPtr = CurSlab->NextPtr; + CurSlab->NextPtr = NewSlab; + + Ptr = AlignPtr((char*)(NewSlab + 1), Alignment); + assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + NewSlab->Size); + return Ptr; + } + + // Otherwise, start a new slab and try again. + StartNewSlab(); + Ptr = AlignPtr(CurPtr, Alignment); + CurPtr = Ptr + Size; + assert(CurPtr <= End && "Unable to allocate memory!"); + return Ptr; +} + +unsigned BumpPtrAllocator::GetNumSlabs() const { + unsigned NumSlabs = 0; + for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) { + ++NumSlabs; + } + return NumSlabs; +} + +void BumpPtrAllocator::PrintStats() const { + unsigned NumSlabs = 0; + size_t TotalMemory = 0; + for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) { + TotalMemory += Slab->Size; + ++NumSlabs; + } + + errs() << "\nNumber of memory regions: " << NumSlabs << '\n' + << "Bytes used: " << BytesAllocated << '\n' + << "Bytes allocated: " << TotalMemory << '\n' + << "Bytes wasted: " << (TotalMemory - BytesAllocated) + << " (includes alignment, etc)\n"; +} + +MallocSlabAllocator BumpPtrAllocator::DefaultSlabAllocator = + MallocSlabAllocator(); + +SlabAllocator::~SlabAllocator() { } + +MallocSlabAllocator::~MallocSlabAllocator() { } + +MemSlab *MallocSlabAllocator::Allocate(size_t Size) { + MemSlab *Slab = (MemSlab*)Allocator.Allocate(Size, 0); + Slab->Size = Size; + Slab->NextPtr = 0; + return Slab; +} + +void MallocSlabAllocator::Deallocate(MemSlab *Slab) { + Allocator.Deallocate(Slab); +} + +void PrintRecyclerStats(size_t Size, + size_t Align, + size_t FreeListSize) { + errs() << "Recycler element size: " << Size << '\n' + << "Recycler element alignment: " << Align << '\n' + << "Number of elements free for recycling: " << FreeListSize << '\n'; +} + +} diff --git a/final/lib/Support/Atomic.cpp b/final/lib/Support/Atomic.cpp new file mode 100644 index 00000000000..c7b4bff2794 --- /dev/null +++ b/final/lib/Support/Atomic.cpp @@ -0,0 +1,112 @@ +//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements atomic operations. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Atomic.h" +#include "llvm/Config/config.h" + +using namespace llvm; + +#if defined(_MSC_VER) +#include +#undef MemoryFence +#endif + +void sys::MemoryFence() { +#if LLVM_MULTITHREADED==0 + return; +#else +# if defined(__GNUC__) + __sync_synchronize(); +# elif defined(_MSC_VER) + MemoryBarrier(); +# else +# error No memory fence implementation for your platform! +# endif +#endif +} + +sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, + sys::cas_flag new_value, + sys::cas_flag old_value) { +#if LLVM_MULTITHREADED==0 + sys::cas_flag result = *ptr; + if (result == old_value) + *ptr = new_value; + return result; +#elif defined(__GNUC__) + return __sync_val_compare_and_swap(ptr, old_value, new_value); +#elif defined(_MSC_VER) + return InterlockedCompareExchange(ptr, new_value, old_value); +#else +# error No compare-and-swap implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + ++(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_add_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedIncrement(ptr); +#else +# error No atomic increment implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) { +#if LLVM_MULTITHREADED==0 + --(*ptr); + return *ptr; +#elif defined(__GNUC__) + return __sync_sub_and_fetch(ptr, 1); +#elif defined(_MSC_VER) + return InterlockedDecrement(ptr); +#else +# error No atomic decrement implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) { +#if LLVM_MULTITHREADED==0 + *ptr += val; + return *ptr; +#elif defined(__GNUC__) + return __sync_add_and_fetch(ptr, val); +#elif defined(_MSC_VER) + return InterlockedExchangeAdd(ptr, val) + val; +#else +# error No atomic add implementation for your platform! +#endif +} + +sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) { + sys::cas_flag original, result; + do { + original = *ptr; + result = original * val; + } while (sys::CompareAndSwap(ptr, result, original) != original); + + return result; +} + +sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) { + sys::cas_flag original, result; + do { + original = *ptr; + result = original / val; + } while (sys::CompareAndSwap(ptr, result, original) != original); + + return result; +} diff --git a/final/lib/Support/CMakeLists.txt b/final/lib/Support/CMakeLists.txt new file mode 100644 index 00000000000..a0e997d349f --- /dev/null +++ b/final/lib/Support/CMakeLists.txt @@ -0,0 +1,103 @@ +## FIXME: This only requires RTTI because tblgen uses it. Fix that. +set(LLVM_REQUIRES_RTTI 1) +if( MINGW ) + set(LLVM_REQUIRES_EH 1) +endif() + +add_llvm_library(LLVMSupport + APFloat.cpp + APInt.cpp + APSInt.cpp + Allocator.cpp + circular_raw_ostream.cpp + CommandLine.cpp + ConstantRange.cpp + CrashRecoveryContext.cpp + Debug.cpp + DeltaAlgorithm.cpp + DAGDeltaAlgorithm.cpp + Dwarf.cpp + ErrorHandling.cpp + FileUtilities.cpp + FoldingSet.cpp + FormattedStream.cpp + GraphWriter.cpp + IntEqClasses.cpp + IntervalMap.cpp + IsInf.cpp + IsNAN.cpp + ManagedStatic.cpp + MemoryBuffer.cpp + MemoryObject.cpp + PluginLoader.cpp + PrettyStackTrace.cpp + Regex.cpp + SmallPtrSet.cpp + SmallVector.cpp + SourceMgr.cpp + Statistic.cpp + StringExtras.cpp + StringMap.cpp + StringPool.cpp + StringRef.cpp + SystemUtils.cpp + TargetRegistry.cpp + Timer.cpp + ToolOutputFile.cpp + Triple.cpp + Twine.cpp + raw_os_ostream.cpp + raw_ostream.cpp + regcomp.c + regerror.c + regexec.c + regfree.c + regstrlcpy.c + +# System + Atomic.cpp + Disassembler.cpp + DynamicLibrary.cpp + Errno.cpp + Host.cpp + IncludeFile.cpp + Memory.cpp + Mutex.cpp + Path.cpp + PathV2.cpp + Process.cpp + Program.cpp + RWMutex.cpp + SearchForAddressOfSpecialSymbol.cpp + Signals.cpp + system_error.cpp + ThreadLocal.cpp + Threading.cpp + TimeValue.cpp + Valgrind.cpp + Unix/Host.inc + Unix/Memory.inc + Unix/Mutex.inc + Unix/Path.inc + Unix/PathV2.inc + Unix/Process.inc + Unix/Program.inc + Unix/RWMutex.inc + Unix/Signals.inc + Unix/system_error.inc + Unix/ThreadLocal.inc + Unix/TimeValue.inc + Windows/DynamicLibrary.inc + Windows/Host.inc + Windows/Memory.inc + Windows/Mutex.inc + Windows/Path.inc + Windows/PathV2.inc + Windows/Process.inc + Windows/Program.inc + Windows/RWMutex.inc + Windows/Signals.inc + Windows/system_error.inc + Windows/ThreadLocal.inc + Windows/TimeValue.inc + ) diff --git a/final/lib/Support/COPYRIGHT.regex b/final/lib/Support/COPYRIGHT.regex new file mode 100644 index 00000000000..a6392fd37c3 --- /dev/null +++ b/final/lib/Support/COPYRIGHT.regex @@ -0,0 +1,54 @@ +$OpenBSD: COPYRIGHT,v 1.3 2003/06/02 20:18:36 millert Exp $ + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94 + */ diff --git a/final/lib/Support/CommandLine.cpp b/final/lib/Support/CommandLine.cpp new file mode 100644 index 00000000000..7e744993a7c --- /dev/null +++ b/final/lib/Support/CommandLine.cpp @@ -0,0 +1,1295 @@ +//===-- CommandLine.cpp - Command line parser implementation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you could try +// reading the library documentation located in docs/CommandLine.html +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Path.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include +#include +using namespace llvm; +using namespace cl; + +//===----------------------------------------------------------------------===// +// Template instantiations and anchors. +// +namespace llvm { namespace cl { +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); +TEMPLATE_INSTANTIATION(class basic_parser); + +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +TEMPLATE_INSTANTIATION(class opt); +} } // end namespace llvm::cl + +void Option::anchor() {} +void basic_parser_impl::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} +void parser::anchor() {} + +//===----------------------------------------------------------------------===// + +// Globals for name and overview of program. Program name is not a string to +// avoid static ctor/dtor issues. +static char ProgramName[80] = ""; +static const char *ProgramOverview = 0; + +// This collects additional help to be printed. +static ManagedStatic > MoreHelp; + +extrahelp::extrahelp(const char *Help) + : morehelp(Help) { + MoreHelp->push_back(Help); +} + +static bool OptionListChanged = false; + +// MarkOptionsChanged - Internal helper function. +void cl::MarkOptionsChanged() { + OptionListChanged = true; +} + +/// RegisteredOptionList - This is the list of the command line options that +/// have statically constructed themselves. +static Option *RegisteredOptionList = 0; + +void Option::addArgument() { + assert(NextRegistered == 0 && "argument multiply registered!"); + + NextRegistered = RegisteredOptionList; + RegisteredOptionList = this; + MarkOptionsChanged(); +} + + +//===----------------------------------------------------------------------===// +// Basic, shared command line option processing machinery. +// + +/// GetOptionInfo - Scan the list of registered options, turning them into data +/// structures that are easier to handle. +static void GetOptionInfo(SmallVectorImpl &PositionalOpts, + SmallVectorImpl &SinkOpts, + StringMap &OptionsMap) { + SmallVector OptionNames; + Option *CAOpt = 0; // The ConsumeAfter option if it exists. + for (Option *O = RegisteredOptionList; O; O = O->getNextRegisteredOption()) { + // If this option wants to handle multiple option names, get the full set. + // This handles enum options like "-O1 -O2" etc. + O->getExtraOptionNames(OptionNames); + if (O->ArgStr[0]) + OptionNames.push_back(O->ArgStr); + + // Handle named options. + for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { + // Add argument to the argument map! + if (OptionsMap.GetOrCreateValue(OptionNames[i], O).second != O) { + errs() << ProgramName << ": CommandLine Error: Argument '" + << OptionNames[i] << "' defined more than once!\n"; + } + } + + OptionNames.clear(); + + // Remember information about positional options. + if (O->getFormattingFlag() == cl::Positional) + PositionalOpts.push_back(O); + else if (O->getMiscFlags() & cl::Sink) // Remember sink options + SinkOpts.push_back(O); + else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { + if (CAOpt) + O->error("Cannot specify more than one option with cl::ConsumeAfter!"); + CAOpt = O; + } + } + + if (CAOpt) + PositionalOpts.push_back(CAOpt); + + // Make sure that they are in order of registration not backwards. + std::reverse(PositionalOpts.begin(), PositionalOpts.end()); +} + + +/// LookupOption - Lookup the option specified by the specified option on the +/// command line. If there is a value specified (after an equal sign) return +/// that as well. This assumes that leading dashes have already been stripped. +static Option *LookupOption(StringRef &Arg, StringRef &Value, + const StringMap &OptionsMap) { + // Reject all dashes. + if (Arg.empty()) return 0; + + size_t EqualPos = Arg.find('='); + + // If we have an equals sign, remember the value. + if (EqualPos == StringRef::npos) { + // Look up the option. + StringMap::const_iterator I = OptionsMap.find(Arg); + return I != OptionsMap.end() ? I->second : 0; + } + + // If the argument before the = is a valid option name, we match. If not, + // return Arg unmolested. + StringMap::const_iterator I = + OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == OptionsMap.end()) return 0; + + Value = Arg.substr(EqualPos+1); + Arg = Arg.substr(0, EqualPos); + return I->second; +} + +/// LookupNearestOption - Lookup the closest match to the option specified by +/// the specified option on the command line. If there is a value specified +/// (after an equal sign) return that as well. This assumes that leading dashes +/// have already been stripped. +static Option *LookupNearestOption(StringRef Arg, + const StringMap &OptionsMap, + const char *&NearestString) { + // Reject all dashes. + if (Arg.empty()) return 0; + + // Split on any equal sign. + StringRef LHS = Arg.split('=').first; + + // Find the closest match. + Option *Best = 0; + unsigned BestDistance = 0; + for (StringMap::const_iterator it = OptionsMap.begin(), + ie = OptionsMap.end(); it != ie; ++it) { + Option *O = it->second; + SmallVector OptionNames; + O->getExtraOptionNames(OptionNames); + if (O->ArgStr[0]) + OptionNames.push_back(O->ArgStr); + + for (size_t i = 0, e = OptionNames.size(); i != e; ++i) { + StringRef Name = OptionNames[i]; + unsigned Distance = StringRef(Name).edit_distance( + Arg, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance); + if (!Best || Distance < BestDistance) { + Best = O; + NearestString = OptionNames[i]; + BestDistance = Distance; + } + } + } + + return Best; +} + +/// CommaSeparateAndAddOccurence - A wrapper around Handler->addOccurence() that +/// does special handling of cl::CommaSeparated options. +static bool CommaSeparateAndAddOccurence(Option *Handler, unsigned pos, + StringRef ArgName, + StringRef Value, bool MultiArg = false) +{ + // Check to see if this option accepts a comma separated list of values. If + // it does, we have to split up the value into multiple values. + if (Handler->getMiscFlags() & CommaSeparated) { + StringRef Val(Value); + StringRef::size_type Pos = Val.find(','); + + while (Pos != StringRef::npos) { + // Process the portion before the comma. + if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg)) + return true; + // Erase the portion before the comma, AND the comma. + Val = Val.substr(Pos+1); + Value.substr(Pos+1); // Increment the original value pointer as well. + // Check for another comma. + Pos = Val.find(','); + } + + Value = Val; + } + + if (Handler->addOccurrence(pos, ArgName, Value, MultiArg)) + return true; + + return false; +} + +/// ProvideOption - For Value, this differentiates between an empty value ("") +/// and a null value (StringRef()). The later is accepted for arguments that +/// don't allow a value (-foo) the former is rejected (-foo=). +static inline bool ProvideOption(Option *Handler, StringRef ArgName, + StringRef Value, int argc, char **argv, + int &i) { + // Is this a multi-argument option? + unsigned NumAdditionalVals = Handler->getNumAdditionalVals(); + + // Enforce value requirements + switch (Handler->getValueExpectedFlag()) { + case ValueRequired: + if (Value.data() == 0) { // No value specified? + if (i+1 >= argc) + return Handler->error("requires a value!"); + // Steal the next argument, like for '-o filename' + Value = argv[++i]; + } + break; + case ValueDisallowed: + if (NumAdditionalVals > 0) + return Handler->error("multi-valued option specified" + " with ValueDisallowed modifier!"); + + if (Value.data()) + return Handler->error("does not allow a value! '" + + Twine(Value) + "' specified."); + break; + case ValueOptional: + break; + + default: + errs() << ProgramName + << ": Bad ValueMask flag! CommandLine usage error:" + << Handler->getValueExpectedFlag() << "\n"; + llvm_unreachable(0); + } + + // If this isn't a multi-arg option, just run the handler. + if (NumAdditionalVals == 0) + return CommaSeparateAndAddOccurence(Handler, i, ArgName, Value); + + // If it is, run the handle several times. + bool MultiArg = false; + + if (Value.data()) { + if (CommaSeparateAndAddOccurence(Handler, i, ArgName, Value, MultiArg)) + return true; + --NumAdditionalVals; + MultiArg = true; + } + + while (NumAdditionalVals > 0) { + if (i+1 >= argc) + return Handler->error("not enough values!"); + Value = argv[++i]; + + if (CommaSeparateAndAddOccurence(Handler, i, ArgName, Value, MultiArg)) + return true; + MultiArg = true; + --NumAdditionalVals; + } + return false; +} + +static bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i) { + int Dummy = i; + return ProvideOption(Handler, Handler->ArgStr, Arg, 0, 0, Dummy); +} + + +// Option predicates... +static inline bool isGrouping(const Option *O) { + return O->getFormattingFlag() == cl::Grouping; +} +static inline bool isPrefixedOrGrouping(const Option *O) { + return isGrouping(O) || O->getFormattingFlag() == cl::Prefix; +} + +// getOptionPred - Check to see if there are any options that satisfy the +// specified predicate with names that are the prefixes in Name. This is +// checked by progressively stripping characters off of the name, checking to +// see if there options that satisfy the predicate. If we find one, return it, +// otherwise return null. +// +static Option *getOptionPred(StringRef Name, size_t &Length, + bool (*Pred)(const Option*), + const StringMap &OptionsMap) { + + StringMap::const_iterator OMI = OptionsMap.find(Name); + + // Loop while we haven't found an option and Name still has at least two + // characters in it (so that the next iteration will not be the empty + // string. + while (OMI == OptionsMap.end() && Name.size() > 1) { + Name = Name.substr(0, Name.size()-1); // Chop off the last character. + OMI = OptionsMap.find(Name); + } + + if (OMI != OptionsMap.end() && Pred(OMI->second)) { + Length = Name.size(); + return OMI->second; // Found one! + } + return 0; // No option found! +} + +/// HandlePrefixedOrGroupedOption - The specified argument string (which started +/// with at least one '-') does not fully match an available option. Check to +/// see if this is a prefix or grouped option. If so, split arg into output an +/// Arg/Value pair and return the Option to parse it with. +static Option *HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value, + bool &ErrorParsing, + const StringMap &OptionsMap) { + if (Arg.size() == 1) return 0; + + // Do the lookup! + size_t Length = 0; + Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap); + if (PGOpt == 0) return 0; + + // If the option is a prefixed option, then the value is simply the + // rest of the name... so fall through to later processing, by + // setting up the argument name flags and value fields. + if (PGOpt->getFormattingFlag() == cl::Prefix) { + Value = Arg.substr(Length); + Arg = Arg.substr(0, Length); + assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt); + return PGOpt; + } + + // This must be a grouped option... handle them now. Grouping options can't + // have values. + assert(isGrouping(PGOpt) && "Broken getOptionPred!"); + + do { + // Move current arg name out of Arg into OneArgName. + StringRef OneArgName = Arg.substr(0, Length); + Arg = Arg.substr(Length); + + // Because ValueRequired is an invalid flag for grouped arguments, + // we don't need to pass argc/argv in. + assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && + "Option can not be cl::Grouping AND cl::ValueRequired!"); + int Dummy = 0; + ErrorParsing |= ProvideOption(PGOpt, OneArgName, + StringRef(), 0, 0, Dummy); + + // Get the next grouping option. + PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap); + } while (PGOpt && Length != Arg.size()); + + // Return the last option with Arg cut down to just the last one. + return PGOpt; +} + + + +static bool RequiresValue(const Option *O) { + return O->getNumOccurrencesFlag() == cl::Required || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +static bool EatsUnboundedNumberOfValues(const Option *O) { + return O->getNumOccurrencesFlag() == cl::ZeroOrMore || + O->getNumOccurrencesFlag() == cl::OneOrMore; +} + +/// ParseCStringVector - Break INPUT up wherever one or more +/// whitespace characters are found, and store the resulting tokens in +/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated +/// using strdup(), so it is the caller's responsibility to free() +/// them later. +/// +static void ParseCStringVector(std::vector &OutputVector, + const char *Input) { + // Characters which will be treated as token separators: + StringRef Delims = " \v\f\t\r\n"; + + StringRef WorkStr(Input); + while (!WorkStr.empty()) { + // If the first character is a delimiter, strip them off. + if (Delims.find(WorkStr[0]) != StringRef::npos) { + size_t Pos = WorkStr.find_first_not_of(Delims); + if (Pos == StringRef::npos) Pos = WorkStr.size(); + WorkStr = WorkStr.substr(Pos); + continue; + } + + // Find position of first delimiter. + size_t Pos = WorkStr.find_first_of(Delims); + if (Pos == StringRef::npos) Pos = WorkStr.size(); + + // Everything from 0 to Pos is the next word to copy. + char *NewStr = (char*)malloc(Pos+1); + memcpy(NewStr, WorkStr.data(), Pos); + NewStr[Pos] = 0; + OutputVector.push_back(NewStr); + + WorkStr = WorkStr.substr(Pos); + } +} + +/// ParseEnvironmentOptions - An alternative entry point to the +/// CommandLine library, which allows you to read the program's name +/// from the caller (as PROGNAME) and its command-line arguments from +/// an environment variable (whose name is given in ENVVAR). +/// +void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, + const char *Overview, bool ReadResponseFiles) { + // Check args. + assert(progName && "Program name not specified"); + assert(envVar && "Environment variable name missing"); + + // Get the environment variable they want us to parse options out of. + const char *envValue = getenv(envVar); + if (!envValue) + return; + + // Get program's "name", which we wouldn't know without the caller + // telling us. + std::vector newArgv; + newArgv.push_back(strdup(progName)); + + // Parse the value of the environment variable into a "command line" + // and hand it off to ParseCommandLineOptions(). + ParseCStringVector(newArgv, envValue); + int newArgc = static_cast(newArgv.size()); + ParseCommandLineOptions(newArgc, &newArgv[0], Overview, ReadResponseFiles); + + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin(), e = newArgv.end(); + i != e; ++i) + free(*i); +} + + +/// ExpandResponseFiles - Copy the contents of argv into newArgv, +/// substituting the contents of the response files for the arguments +/// of type @file. +static void ExpandResponseFiles(unsigned argc, char** argv, + std::vector& newArgv) { + for (unsigned i = 1; i != argc; ++i) { + char *arg = argv[i]; + + if (arg[0] == '@') { + sys::PathWithStatus respFile(++arg); + + // Check that the response file is not empty (mmap'ing empty + // files can be problematic). + const sys::FileStatus *FileStat = respFile.getFileStatus(); + if (FileStat && FileStat->getSize() != 0) { + + // If we could open the file, parse its contents, otherwise + // pass the @file option verbatim. + + // TODO: we should also support recursive loading of response files, + // since this is how gcc behaves. (From their man page: "The file may + // itself contain additional @file options; any such options will be + // processed recursively.") + + // Mmap the response file into memory. + OwningPtr respFilePtr; + if (!MemoryBuffer::getFile(respFile.c_str(), respFilePtr)) { + ParseCStringVector(newArgv, respFilePtr->getBufferStart()); + continue; + } + } + } + newArgv.push_back(strdup(arg)); + } +} + +void cl::ParseCommandLineOptions(int argc, char **argv, + const char *Overview, bool ReadResponseFiles) { + // Process all registered options. + SmallVector PositionalOpts; + SmallVector SinkOpts; + StringMap Opts; + GetOptionInfo(PositionalOpts, SinkOpts, Opts); + + assert((!Opts.empty() || !PositionalOpts.empty()) && + "No options specified!"); + + // Expand response files. + std::vector newArgv; + if (ReadResponseFiles) { + newArgv.push_back(strdup(argv[0])); + ExpandResponseFiles(argc, argv, newArgv); + argv = &newArgv[0]; + argc = static_cast(newArgv.size()); + } + + // Copy the program name into ProgName, making sure not to overflow it. + std::string ProgName = sys::path::filename(argv[0]); + size_t Len = std::min(ProgName.size(), size_t(79)); + memcpy(ProgramName, ProgName.data(), Len); + ProgramName[Len] = '\0'; + + ProgramOverview = Overview; + bool ErrorParsing = false; + + // Check out the positional arguments to collect information about them. + unsigned NumPositionalRequired = 0; + + // Determine whether or not there are an unlimited number of positionals + bool HasUnlimitedPositionals = false; + + Option *ConsumeAfterOpt = 0; + if (!PositionalOpts.empty()) { + if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) { + assert(PositionalOpts.size() > 1 && + "Cannot specify cl::ConsumeAfter without a positional argument!"); + ConsumeAfterOpt = PositionalOpts[0]; + } + + // Calculate how many positional values are _required_. + bool UnboundedFound = false; + for (size_t i = ConsumeAfterOpt != 0, e = PositionalOpts.size(); + i != e; ++i) { + Option *Opt = PositionalOpts[i]; + if (RequiresValue(Opt)) + ++NumPositionalRequired; + else if (ConsumeAfterOpt) { + // ConsumeAfter cannot be combined with "optional" positional options + // unless there is only one positional argument... + if (PositionalOpts.size() > 2) + ErrorParsing |= + Opt->error("error - this positional option will never be matched, " + "because it does not Require a value, and a " + "cl::ConsumeAfter option is active!"); + } else if (UnboundedFound && !Opt->ArgStr[0]) { + // This option does not "require" a value... Make sure this option is + // not specified after an option that eats all extra arguments, or this + // one will never get any! + // + ErrorParsing |= Opt->error("error - option can never match, because " + "another positional argument will match an " + "unbounded number of values, and this option" + " does not require a value!"); + } + UnboundedFound |= EatsUnboundedNumberOfValues(Opt); + } + HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt; + } + + // PositionalVals - A vector of "positional" arguments we accumulate into + // the process at the end. + // + SmallVector, 4> PositionalVals; + + // If the program has named positional arguments, and the name has been run + // across, keep track of which positional argument was named. Otherwise put + // the positional args into the PositionalVals list... + Option *ActivePositionalArg = 0; + + // Loop over all of the arguments... processing them. + bool DashDashFound = false; // Have we read '--'? + for (int i = 1; i < argc; ++i) { + Option *Handler = 0; + Option *NearestHandler = 0; + const char *NearestHandlerString = 0; + StringRef Value; + StringRef ArgName = ""; + + // If the option list changed, this means that some command line + // option has just been registered or deregistered. This can occur in + // response to things like -load, etc. If this happens, rescan the options. + if (OptionListChanged) { + PositionalOpts.clear(); + SinkOpts.clear(); + Opts.clear(); + GetOptionInfo(PositionalOpts, SinkOpts, Opts); + OptionListChanged = false; + } + + // Check to see if this is a positional argument. This argument is + // considered to be positional if it doesn't start with '-', if it is "-" + // itself, or if we have seen "--" already. + // + if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { + // Positional argument! + if (ActivePositionalArg) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + if (!PositionalOpts.empty()) { + PositionalVals.push_back(std::make_pair(argv[i],i)); + + // All of the positional arguments have been fulfulled, give the rest to + // the consume after option... if it's specified... + // + if (PositionalVals.size() >= NumPositionalRequired && + ConsumeAfterOpt != 0) { + for (++i; i < argc; ++i) + PositionalVals.push_back(std::make_pair(argv[i],i)); + break; // Handle outside of the argument processing loop... + } + + // Delay processing positional arguments until the end... + continue; + } + } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 && + !DashDashFound) { + DashDashFound = true; // This is the mythical "--"? + continue; // Don't try to process it as an argument itself. + } else if (ActivePositionalArg && + (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) { + // If there is a positional argument eating options, check to see if this + // option is another positional argument. If so, treat it as an argument, + // otherwise feed it to the eating positional. + ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(ArgName, Value, Opts); + if (!Handler || Handler->getFormattingFlag() != cl::Positional) { + ProvidePositionalOption(ActivePositionalArg, argv[i], i); + continue; // We are done! + } + + } else { // We start with a '-', must be an argument. + ArgName = argv[i]+1; + // Eat leading dashes. + while (!ArgName.empty() && ArgName[0] == '-') + ArgName = ArgName.substr(1); + + Handler = LookupOption(ArgName, Value, Opts); + + // Check to see if this "option" is really a prefixed or grouped argument. + if (Handler == 0) + Handler = HandlePrefixedOrGroupedOption(ArgName, Value, + ErrorParsing, Opts); + + // Otherwise, look for the closest available option to report to the user + // in the upcoming error. + if (Handler == 0 && SinkOpts.empty()) + NearestHandler = LookupNearestOption(ArgName, Opts, + NearestHandlerString); + } + + if (Handler == 0) { + if (SinkOpts.empty()) { + errs() << ProgramName << ": Unknown command line argument '" + << argv[i] << "'. Try: '" << argv[0] << " -help'\n"; + + if (NearestHandler) { + // If we know a near match, report it as well. + errs() << ProgramName << ": Did you mean '-" + << NearestHandlerString << "'?\n"; + } + + ErrorParsing = true; + } else { + for (SmallVectorImpl::iterator I = SinkOpts.begin(), + E = SinkOpts.end(); I != E ; ++I) + (*I)->addOccurrence(i, "", argv[i]); + } + continue; + } + + // If this is a named positional argument, just remember that it is the + // active one... + if (Handler->getFormattingFlag() == cl::Positional) + ActivePositionalArg = Handler; + else + ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); + } + + // Check and handle positional arguments now... + if (NumPositionalRequired > PositionalVals.size()) { + errs() << ProgramName + << ": Not enough positional command line arguments specified!\n" + << "Must specify at least " << NumPositionalRequired + << " positional arguments: See: " << argv[0] << " -help\n"; + + ErrorParsing = true; + } else if (!HasUnlimitedPositionals && + PositionalVals.size() > PositionalOpts.size()) { + errs() << ProgramName + << ": Too many positional arguments specified!\n" + << "Can specify at most " << PositionalOpts.size() + << " positional arguments: See: " << argv[0] << " -help\n"; + ErrorParsing = true; + + } else if (ConsumeAfterOpt == 0) { + // Positional args have already been handled if ConsumeAfter is specified. + unsigned ValNo = 0, NumVals = static_cast(PositionalVals.size()); + for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) { + if (RequiresValue(PositionalOpts[i])) { + ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + --NumPositionalRequired; // We fulfilled our duty... + } + + // If we _can_ give this option more arguments, do so now, as long as we + // do not give it values that others need. 'Done' controls whether the + // option even _WANTS_ any more. + // + bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; + while (NumVals-ValNo > NumPositionalRequired && !Done) { + switch (PositionalOpts[i]->getNumOccurrencesFlag()) { + case cl::Optional: + Done = true; // Optional arguments want _at most_ one value + // FALL THROUGH + case cl::ZeroOrMore: // Zero or more will take all they can get... + case cl::OneOrMore: // One or more will take all they can get... + ProvidePositionalOption(PositionalOpts[i], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + break; + default: + llvm_unreachable("Internal error, unexpected NumOccurrences flag in " + "positional argument processing!"); + } + } + } + } else { + assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); + unsigned ValNo = 0; + for (size_t j = 1, e = PositionalOpts.size(); j != e; ++j) + if (RequiresValue(PositionalOpts[j])) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[j], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle the case where there is just one positional option, and it's + // optional. In this case, we want to give JUST THE FIRST option to the + // positional option and keep the rest for the consume after. The above + // loop would have assigned no values to positional options in this case. + // + if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) { + ErrorParsing |= ProvidePositionalOption(PositionalOpts[1], + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + ValNo++; + } + + // Handle over all of the rest of the arguments to the + // cl::ConsumeAfter command line option... + for (; ValNo != PositionalVals.size(); ++ValNo) + ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt, + PositionalVals[ValNo].first, + PositionalVals[ValNo].second); + } + + // Loop over args and make sure all required args are specified! + for (StringMap::iterator I = Opts.begin(), + E = Opts.end(); I != E; ++I) { + switch (I->second->getNumOccurrencesFlag()) { + case Required: + case OneOrMore: + if (I->second->getNumOccurrences() == 0) { + I->second->error("must be specified at least once!"); + ErrorParsing = true; + } + // Fall through + default: + break; + } + } + + // Now that we know if -debug is specified, we can use it. + // Note that if ReadResponseFiles == true, this must be done before the + // memory allocated for the expanded command line is free()d below. + DEBUG(dbgs() << "Args: "; + for (int i = 0; i < argc; ++i) + dbgs() << argv[i] << ' '; + dbgs() << '\n'; + ); + + // Free all of the memory allocated to the map. Command line options may only + // be processed once! + Opts.clear(); + PositionalOpts.clear(); + MoreHelp->clear(); + + // Free the memory allocated by ExpandResponseFiles. + if (ReadResponseFiles) { + // Free all the strdup()ed strings. + for (std::vector::iterator i = newArgv.begin(), e = newArgv.end(); + i != e; ++i) + free(*i); + } + + // If we had an error processing our arguments, don't let the program execute + if (ErrorParsing) exit(1); +} + +//===----------------------------------------------------------------------===// +// Option Base class implementation +// + +bool Option::error(const Twine &Message, StringRef ArgName) { + if (ArgName.data() == 0) ArgName = ArgStr; + if (ArgName.empty()) + errs() << HelpStr; // Be nice for positional arguments + else + errs() << ProgramName << ": for the -" << ArgName; + + errs() << " option: " << Message << "\n"; + return true; +} + +bool Option::addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg) { + if (!MultiArg) + NumOccurrences++; // Increment the number of times we have been seen + + switch (getNumOccurrencesFlag()) { + case Optional: + if (NumOccurrences > 1) + return error("may only occur zero or one times!", ArgName); + break; + case Required: + if (NumOccurrences > 1) + return error("must occur exactly one time!", ArgName); + // Fall through + case OneOrMore: + case ZeroOrMore: + case ConsumeAfter: break; + default: return error("bad num occurrences flag value!"); + } + + return handleOccurrence(pos, ArgName, Value); +} + + +// getValueStr - Get the value description string, using "DefaultMsg" if nothing +// has been specified yet. +// +static const char *getValueStr(const Option &O, const char *DefaultMsg) { + if (O.ValueStr[0] == 0) return DefaultMsg; + return O.ValueStr; +} + +//===----------------------------------------------------------------------===// +// cl::alias class implementation +// + +// Return the width of the option tag for printing... +size_t alias::getOptionWidth() const { + return std::strlen(ArgStr)+6; +} + +// Print out the option for the alias. +void alias::printOptionInfo(size_t GlobalWidth) const { + size_t L = std::strlen(ArgStr); + errs() << " -" << ArgStr; + errs().indent(GlobalWidth-L-6) << " - " << HelpStr << "\n"; +} + + + +//===----------------------------------------------------------------------===// +// Parser Implementation code... +// + +// basic_parser implementation +// + +// Return the width of the option tag for printing... +size_t basic_parser_impl::getOptionWidth(const Option &O) const { + size_t Len = std::strlen(O.ArgStr); + if (const char *ValName = getValueName()) + Len += std::strlen(getValueStr(O, ValName))+3; + + return Len + 6; +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void basic_parser_impl::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + outs() << " -" << O.ArgStr; + + if (const char *ValName = getValueName()) + outs() << "=<" << getValueStr(O, ValName) << '>'; + + outs().indent(GlobalWidth-getOptionWidth(O)) << " - " << O.HelpStr << '\n'; +} + + + + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, bool &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = true; + return false; + } + + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = false; + return false; + } + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, boolOrDefault &Value) { + if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || + Arg == "1") { + Value = BOU_TRUE; + return false; + } + if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { + Value = BOU_FALSE; + return false; + } + + return O.error("'" + Arg + + "' is invalid value for boolean argument! Try 0 or 1"); +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, int &Value) { + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for integer argument!"); + return false; +} + +// parser implementation +// +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, unsigned &Value) { + + if (Arg.getAsInteger(0, Value)) + return O.error("'" + Arg + "' value invalid for uint argument!"); + return false; +} + +// parser/parser implementation +// +static bool parseDouble(Option &O, StringRef Arg, double &Value) { + SmallString<32> TmpStr(Arg.begin(), Arg.end()); + const char *ArgStart = TmpStr.c_str(); + char *End; + Value = strtod(ArgStart, &End); + if (*End != 0) + return O.error("'" + Arg + "' value invalid for floating point argument!"); + return false; +} + +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, double &Val) { + return parseDouble(O, Arg, Val); +} + +bool parser::parse(Option &O, StringRef ArgName, + StringRef Arg, float &Val) { + double dVal; + if (parseDouble(O, Arg, dVal)) + return true; + Val = (float)dVal; + return false; +} + + + +// generic_parser_base implementation +// + +// findOption - Return the option number corresponding to the specified +// argument string. If the option is not found, getNumOptions() is returned. +// +unsigned generic_parser_base::findOption(const char *Name) { + unsigned e = getNumOptions(); + + for (unsigned i = 0; i != e; ++i) { + if (strcmp(getOption(i), Name) == 0) + return i; + } + return e; +} + + +// Return the width of the option tag for printing... +size_t generic_parser_base::getOptionWidth(const Option &O) const { + if (O.hasArgStr()) { + size_t Size = std::strlen(O.ArgStr)+6; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + Size = std::max(Size, std::strlen(getOption(i))+8); + return Size; + } else { + size_t BaseSize = 0; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + BaseSize = std::max(BaseSize, std::strlen(getOption(i))+8); + return BaseSize; + } +} + +// printOptionInfo - Print out information about this option. The +// to-be-maintained width is specified. +// +void generic_parser_base::printOptionInfo(const Option &O, + size_t GlobalWidth) const { + if (O.hasArgStr()) { + size_t L = std::strlen(O.ArgStr); + outs() << " -" << O.ArgStr; + outs().indent(GlobalWidth-L-6) << " - " << O.HelpStr << '\n'; + + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + size_t NumSpaces = GlobalWidth-strlen(getOption(i))-8; + outs() << " =" << getOption(i); + outs().indent(NumSpaces) << " - " << getDescription(i) << '\n'; + } + } else { + if (O.HelpStr[0]) + outs() << " " << O.HelpStr << '\n'; + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { + size_t L = std::strlen(getOption(i)); + outs() << " -" << getOption(i); + outs().indent(GlobalWidth-L-8) << " - " << getDescription(i) << '\n'; + } + } +} + + +//===----------------------------------------------------------------------===// +// -help and -help-hidden option implementation +// + +static int OptNameCompare(const void *LHS, const void *RHS) { + typedef std::pair pair_ty; + + return strcmp(((pair_ty*)LHS)->first, ((pair_ty*)RHS)->first); +} + +namespace { + +class HelpPrinter { + size_t MaxArgLen; + const Option *EmptyArg; + const bool ShowHidden; + +public: + explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) { + EmptyArg = 0; + } + + void operator=(bool Value) { + if (Value == false) return; + + // Get all the options. + SmallVector PositionalOpts; + SmallVector SinkOpts; + StringMap OptMap; + GetOptionInfo(PositionalOpts, SinkOpts, OptMap); + + // Copy Options into a vector so we can sort them as we like. + SmallVector, 128> Opts; + SmallPtrSet OptionSet; // Duplicate option detection. + + for (StringMap::iterator I = OptMap.begin(), E = OptMap.end(); + I != E; ++I) { + // Ignore really-hidden options. + if (I->second->getOptionHiddenFlag() == ReallyHidden) + continue; + + // Unless showhidden is set, ignore hidden flags. + if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden) + continue; + + // If we've already seen this option, don't add it to the list again. + if (!OptionSet.insert(I->second)) + continue; + + Opts.push_back(std::pair(I->getKey().data(), + I->second)); + } + + // Sort the options list alphabetically. + qsort(Opts.data(), Opts.size(), sizeof(Opts[0]), OptNameCompare); + + if (ProgramOverview) + outs() << "OVERVIEW: " << ProgramOverview << "\n"; + + outs() << "USAGE: " << ProgramName << " [options]"; + + // Print out the positional options. + Option *CAOpt = 0; // The cl::ConsumeAfter option, if it exists... + if (!PositionalOpts.empty() && + PositionalOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) + CAOpt = PositionalOpts[0]; + + for (size_t i = CAOpt != 0, e = PositionalOpts.size(); i != e; ++i) { + if (PositionalOpts[i]->ArgStr[0]) + outs() << " --" << PositionalOpts[i]->ArgStr; + outs() << " " << PositionalOpts[i]->HelpStr; + } + + // Print the consume after option info if it exists... + if (CAOpt) outs() << " " << CAOpt->HelpStr; + + outs() << "\n\n"; + + // Compute the maximum argument length... + MaxArgLen = 0; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); + + outs() << "OPTIONS:\n"; + for (size_t i = 0, e = Opts.size(); i != e; ++i) + Opts[i].second->printOptionInfo(MaxArgLen); + + // Print any extra help the user has declared. + for (std::vector::iterator I = MoreHelp->begin(), + E = MoreHelp->end(); I != E; ++I) + outs() << *I; + MoreHelp->clear(); + + // Halt the program since help information was printed + exit(1); + } +}; +} // End anonymous namespace + +// Define the two HelpPrinter instances that are used to print out help, or +// help-hidden... +// +static HelpPrinter NormalPrinter(false); +static HelpPrinter HiddenPrinter(true); + +static cl::opt > +HOp("help", cl::desc("Display available options (-help-hidden for more)"), + cl::location(NormalPrinter), cl::ValueDisallowed); + +static cl::opt > +HHOp("help-hidden", cl::desc("Display all available options"), + cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); + +static void (*OverrideVersionPrinter)() = 0; + +static int TargetArraySortFn(const void *LHS, const void *RHS) { + typedef std::pair pair_ty; + return strcmp(((const pair_ty*)LHS)->first, ((const pair_ty*)RHS)->first); +} + +namespace { +class VersionPrinter { +public: + void print() { + raw_ostream &OS = outs(); + OS << "Low Level Virtual Machine (http://llvm.org/):\n" + << " " << PACKAGE_NAME << " version " << PACKAGE_VERSION; +#ifdef LLVM_VERSION_INFO + OS << LLVM_VERSION_INFO; +#endif + OS << "\n "; +#ifndef __OPTIMIZE__ + OS << "DEBUG build"; +#else + OS << "Optimized build"; +#endif +#ifndef NDEBUG + OS << " with assertions"; +#endif + std::string CPU = sys::getHostCPUName(); + if (CPU == "generic") CPU = "(unknown)"; + OS << ".\n" +#if (ENABLE_TIMESTAMPS == 1) + << " Built " << __DATE__ << " (" << __TIME__ << ").\n" +#endif + << " Host: " << sys::getHostTriple() << '\n' + << " Host CPU: " << CPU << '\n' + << '\n' + << " Registered Targets:\n"; + + std::vector > Targets; + size_t Width = 0; + for (TargetRegistry::iterator it = TargetRegistry::begin(), + ie = TargetRegistry::end(); it != ie; ++it) { + Targets.push_back(std::make_pair(it->getName(), &*it)); + Width = std::max(Width, strlen(Targets.back().first)); + } + if (!Targets.empty()) + qsort(&Targets[0], Targets.size(), sizeof(Targets[0]), + TargetArraySortFn); + + for (unsigned i = 0, e = Targets.size(); i != e; ++i) { + OS << " " << Targets[i].first; + OS.indent(Width - strlen(Targets[i].first)) << " - " + << Targets[i].second->getShortDescription() << '\n'; + } + if (Targets.empty()) + OS << " (none)\n"; + } + void operator=(bool OptionWasSpecified) { + if (!OptionWasSpecified) return; + + if (OverrideVersionPrinter == 0) { + print(); + exit(1); + } + (*OverrideVersionPrinter)(); + exit(1); + } +}; +} // End anonymous namespace + + +// Define the --version option that prints out the LLVM version for the tool +static VersionPrinter VersionPrinterInstance; + +static cl::opt > +VersOp("version", cl::desc("Display the version of this program"), + cl::location(VersionPrinterInstance), cl::ValueDisallowed); + +// Utility function for printing the help message. +void cl::PrintHelpMessage() { + // This looks weird, but it actually prints the help message. The + // NormalPrinter variable is a HelpPrinter and the help gets printed when + // its operator= is invoked. That's because the "normal" usages of the + // help printer is to be assigned true/false depending on whether the + // -help option was given or not. Since we're circumventing that we have + // to make it look like -help was given, so we assign true. + NormalPrinter = true; +} + +/// Utility function for printing version number. +void cl::PrintVersionMessage() { + VersionPrinterInstance.print(); +} + +void cl::SetVersionPrinter(void (*func)()) { + OverrideVersionPrinter = func; +} diff --git a/final/lib/Support/ConstantRange.cpp b/final/lib/Support/ConstantRange.cpp new file mode 100644 index 00000000000..493f7083dbb --- /dev/null +++ b/final/lib/Support/ConstantRange.cpp @@ -0,0 +1,702 @@ +//===-- ConstantRange.cpp - ConstantRange implementation ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges (other integral ranges use min/max values for special range values): +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +//===----------------------------------------------------------------------===// + +#include "llvm/Constants.h" +#include "llvm/Support/ConstantRange.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Instructions.h" +using namespace llvm; + +/// Initialize a full (the default) or empty set for the specified type. +/// +ConstantRange::ConstantRange(uint32_t BitWidth, bool Full) { + if (Full) + Lower = Upper = APInt::getMaxValue(BitWidth); + else + Lower = Upper = APInt::getMinValue(BitWidth); +} + +/// Initialize a range to hold the single specified value. +/// +ConstantRange::ConstantRange(const APInt &V) : Lower(V), Upper(V + 1) {} + +ConstantRange::ConstantRange(const APInt &L, const APInt &U) : + Lower(L), Upper(U) { + assert(L.getBitWidth() == U.getBitWidth() && + "ConstantRange with unequal bit widths"); + assert((L != U || (L.isMaxValue() || L.isMinValue())) && + "Lower == Upper, but they aren't min or max value!"); +} + +ConstantRange ConstantRange::makeICmpRegion(unsigned Pred, + const ConstantRange &CR) { + if (CR.isEmptySet()) + return CR; + + uint32_t W = CR.getBitWidth(); + switch (Pred) { + default: assert(!"Invalid ICmp predicate to makeICmpRegion()"); + case ICmpInst::ICMP_EQ: + return CR; + case ICmpInst::ICMP_NE: + if (CR.isSingleElement()) + return ConstantRange(CR.getUpper(), CR.getLower()); + return ConstantRange(W); + case ICmpInst::ICMP_ULT: { + APInt UMax(CR.getUnsignedMax()); + if (UMax.isMinValue()) + return ConstantRange(W, /* empty */ false); + return ConstantRange(APInt::getMinValue(W), UMax); + } + case ICmpInst::ICMP_SLT: { + APInt SMax(CR.getSignedMax()); + if (SMax.isMinSignedValue()) + return ConstantRange(W, /* empty */ false); + return ConstantRange(APInt::getSignedMinValue(W), SMax); + } + case ICmpInst::ICMP_ULE: { + APInt UMax(CR.getUnsignedMax()); + if (UMax.isMaxValue()) + return ConstantRange(W); + return ConstantRange(APInt::getMinValue(W), UMax + 1); + } + case ICmpInst::ICMP_SLE: { + APInt SMax(CR.getSignedMax()); + if (SMax.isMaxSignedValue()) + return ConstantRange(W); + return ConstantRange(APInt::getSignedMinValue(W), SMax + 1); + } + case ICmpInst::ICMP_UGT: { + APInt UMin(CR.getUnsignedMin()); + if (UMin.isMaxValue()) + return ConstantRange(W, /* empty */ false); + return ConstantRange(UMin + 1, APInt::getNullValue(W)); + } + case ICmpInst::ICMP_SGT: { + APInt SMin(CR.getSignedMin()); + if (SMin.isMaxSignedValue()) + return ConstantRange(W, /* empty */ false); + return ConstantRange(SMin + 1, APInt::getSignedMinValue(W)); + } + case ICmpInst::ICMP_UGE: { + APInt UMin(CR.getUnsignedMin()); + if (UMin.isMinValue()) + return ConstantRange(W); + return ConstantRange(UMin, APInt::getNullValue(W)); + } + case ICmpInst::ICMP_SGE: { + APInt SMin(CR.getSignedMin()); + if (SMin.isMinSignedValue()) + return ConstantRange(W); + return ConstantRange(SMin, APInt::getSignedMinValue(W)); + } + } +} + +/// isFullSet - Return true if this set contains all of the elements possible +/// for this data-type +bool ConstantRange::isFullSet() const { + return Lower == Upper && Lower.isMaxValue(); +} + +/// isEmptySet - Return true if this set contains no members. +/// +bool ConstantRange::isEmptySet() const { + return Lower == Upper && Lower.isMinValue(); +} + +/// isWrappedSet - Return true if this set wraps around the top of the range, +/// for example: [100, 8) +/// +bool ConstantRange::isWrappedSet() const { + return Lower.ugt(Upper); +} + +/// isSignWrappedSet - Return true if this set wraps around the INT_MIN of +/// its bitwidth, for example: i8 [120, 140). +/// +bool ConstantRange::isSignWrappedSet() const { + return contains(APInt::getSignedMaxValue(getBitWidth())) && + contains(APInt::getSignedMinValue(getBitWidth())); +} + +/// getSetSize - Return the number of elements in this set. +/// +APInt ConstantRange::getSetSize() const { + if (isEmptySet()) + return APInt(getBitWidth(), 0); + if (getBitWidth() == 1) { + if (Lower != Upper) // One of T or F in the set... + return APInt(2, 1); + return APInt(2, 2); // Must be full set... + } + + // Simply subtract the bounds... + return Upper - Lower; +} + +/// getUnsignedMax - Return the largest unsigned value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getUnsignedMax() const { + if (isFullSet() || isWrappedSet()) + return APInt::getMaxValue(getBitWidth()); + else + return getUpper() - 1; +} + +/// getUnsignedMin - Return the smallest unsigned value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getUnsignedMin() const { + if (isFullSet() || (isWrappedSet() && getUpper() != 0)) + return APInt::getMinValue(getBitWidth()); + else + return getLower(); +} + +/// getSignedMax - Return the largest signed value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getSignedMax() const { + APInt SignedMax(APInt::getSignedMaxValue(getBitWidth())); + if (!isWrappedSet()) { + if (getLower().sle(getUpper() - 1)) + return getUpper() - 1; + else + return SignedMax; + } else { + if (getLower().isNegative() == getUpper().isNegative()) + return SignedMax; + else + return getUpper() - 1; + } +} + +/// getSignedMin - Return the smallest signed value contained in the +/// ConstantRange. +/// +APInt ConstantRange::getSignedMin() const { + APInt SignedMin(APInt::getSignedMinValue(getBitWidth())); + if (!isWrappedSet()) { + if (getLower().sle(getUpper() - 1)) + return getLower(); + else + return SignedMin; + } else { + if ((getUpper() - 1).slt(getLower())) { + if (getUpper() != SignedMin) + return SignedMin; + else + return getLower(); + } else { + return getLower(); + } + } +} + +/// contains - Return true if the specified value is in the set. +/// +bool ConstantRange::contains(const APInt &V) const { + if (Lower == Upper) + return isFullSet(); + + if (!isWrappedSet()) + return Lower.ule(V) && V.ult(Upper); + else + return Lower.ule(V) || V.ult(Upper); +} + +/// contains - Return true if the argument is a subset of this range. +/// Two equal sets contain each other. The empty set contained by all other +/// sets. +/// +bool ConstantRange::contains(const ConstantRange &Other) const { + if (isFullSet() || Other.isEmptySet()) return true; + if (isEmptySet() || Other.isFullSet()) return false; + + if (!isWrappedSet()) { + if (Other.isWrappedSet()) + return false; + + return Lower.ule(Other.getLower()) && Other.getUpper().ule(Upper); + } + + if (!Other.isWrappedSet()) + return Other.getUpper().ule(Upper) || + Lower.ule(Other.getLower()); + + return Other.getUpper().ule(Upper) && Lower.ule(Other.getLower()); +} + +/// subtract - Subtract the specified constant from the endpoints of this +/// constant range. +ConstantRange ConstantRange::subtract(const APInt &Val) const { + assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width"); + // If the set is empty or full, don't modify the endpoints. + if (Lower == Upper) + return *this; + return ConstantRange(Lower - Val, Upper - Val); +} + +/// intersectWith - Return the range that results from the intersection of this +/// range with another range. The resultant range is guaranteed to include all +/// elements contained in both input ranges, and to have the smallest possible +/// set size that does so. Because there may be two intersections with the +/// same set size, A.intersectWith(B) might not be equal to B.intersectWith(A). +ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { + assert(getBitWidth() == CR.getBitWidth() && + "ConstantRange types don't agree!"); + + // Handle common cases. + if ( isEmptySet() || CR.isFullSet()) return *this; + if (CR.isEmptySet() || isFullSet()) return CR; + + if (!isWrappedSet() && CR.isWrappedSet()) + return CR.intersectWith(*this); + + if (!isWrappedSet() && !CR.isWrappedSet()) { + if (Lower.ult(CR.Lower)) { + if (Upper.ule(CR.Lower)) + return ConstantRange(getBitWidth(), false); + + if (Upper.ult(CR.Upper)) + return ConstantRange(CR.Lower, Upper); + + return CR; + } else { + if (Upper.ult(CR.Upper)) + return *this; + + if (Lower.ult(CR.Upper)) + return ConstantRange(Lower, CR.Upper); + + return ConstantRange(getBitWidth(), false); + } + } + + if (isWrappedSet() && !CR.isWrappedSet()) { + if (CR.Lower.ult(Upper)) { + if (CR.Upper.ult(Upper)) + return CR; + + if (CR.Upper.ult(Lower)) + return ConstantRange(CR.Lower, Upper); + + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; + } else if (CR.Lower.ult(Lower)) { + if (CR.Upper.ule(Lower)) + return ConstantRange(getBitWidth(), false); + + return ConstantRange(Lower, CR.Upper); + } + return CR; + } + + if (CR.Upper.ult(Upper)) { + if (CR.Lower.ult(Upper)) { + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; + } + + if (CR.Lower.ult(Lower)) + return ConstantRange(Lower, CR.Upper); + + return CR; + } else if (CR.Upper.ult(Lower)) { + if (CR.Lower.ult(Lower)) + return *this; + + return ConstantRange(CR.Lower, Upper); + } + if (getSetSize().ult(CR.getSetSize())) + return *this; + else + return CR; +} + + +/// unionWith - Return the range that results from the union of this range with +/// another range. The resultant range is guaranteed to include the elements of +/// both sets, but may contain more. For example, [3, 9) union [12,15) is +/// [3, 15), which includes 9, 10, and 11, which were not included in either +/// set before. +/// +ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { + assert(getBitWidth() == CR.getBitWidth() && + "ConstantRange types don't agree!"); + + if ( isFullSet() || CR.isEmptySet()) return *this; + if (CR.isFullSet() || isEmptySet()) return CR; + + if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this); + + if (!isWrappedSet() && !CR.isWrappedSet()) { + if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) { + // If the two ranges are disjoint, find the smaller gap and bridge it. + APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; + if (d1.ult(d2)) + return ConstantRange(Lower, CR.Upper); + else + return ConstantRange(CR.Lower, Upper); + } + + APInt L = Lower, U = Upper; + if (CR.Lower.ult(L)) + L = CR.Lower; + if ((CR.Upper - 1).ugt(U - 1)) + U = CR.Upper; + + if (L == 0 && U == 0) + return ConstantRange(getBitWidth()); + + return ConstantRange(L, U); + } + + if (!CR.isWrappedSet()) { + // ------U L----- and ------U L----- : this + // L--U L--U : CR + if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower)) + return *this; + + // ------U L----- : this + // L---------U : CR + if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper)) + return ConstantRange(getBitWidth()); + + // ----U L---- : this + // L---U : CR + // + if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) { + APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper; + if (d1.ult(d2)) + return ConstantRange(Lower, CR.Upper); + else + return ConstantRange(CR.Lower, Upper); + } + + // ----U L----- : this + // L----U : CR + if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper)) + return ConstantRange(CR.Lower, Upper); + + // ------U L---- : this + // L-----U : CR + if (CR.Lower.ult(Upper) && CR.Upper.ult(Lower)) + return ConstantRange(Lower, CR.Upper); + } + + assert(isWrappedSet() && CR.isWrappedSet() && + "ConstantRange::unionWith missed wrapped union unwrapped case"); + + // ------U L---- and ------U L---- : this + // -U L----------- and ------------U L : CR + if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper)) + return ConstantRange(getBitWidth()); + + APInt L = Lower, U = Upper; + if (CR.Upper.ugt(U)) + U = CR.Upper; + if (CR.Lower.ult(L)) + L = CR.Lower; + + return ConstantRange(L, U); +} + +/// zeroExtend - Return a new range in the specified integer type, which must +/// be strictly larger than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// zero extended. +ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const { + if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false); + + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize < DstTySize && "Not a value extension"); + if (isFullSet() || isWrappedSet()) + // Change into [0, 1 << src bit width) + return ConstantRange(APInt(DstTySize,0), APInt(DstTySize,1).shl(SrcTySize)); + + return ConstantRange(Lower.zext(DstTySize), Upper.zext(DstTySize)); +} + +/// signExtend - Return a new range in the specified integer type, which must +/// be strictly larger than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// sign extended. +ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const { + if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false); + + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize < DstTySize && "Not a value extension"); + if (isFullSet() || isSignWrappedSet()) { + return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1), + APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1); + } + + return ConstantRange(Lower.sext(DstTySize), Upper.sext(DstTySize)); +} + +/// truncate - Return a new range in the specified integer type, which must be +/// strictly smaller than the current type. The returned range will +/// correspond to the possible range of values as if the source range had been +/// truncated to the specified type. +ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + assert(SrcTySize > DstTySize && "Not a value truncation"); + APInt Size(APInt::getLowBitsSet(SrcTySize, DstTySize)); + if (isFullSet() || getSetSize().ugt(Size)) + return ConstantRange(DstTySize, /*isFullSet=*/true); + + return ConstantRange(Lower.trunc(DstTySize), Upper.trunc(DstTySize)); +} + +/// zextOrTrunc - make this range have the bit width given by \p DstTySize. The +/// value is zero extended, truncated, or left alone to make it that width. +ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + if (SrcTySize > DstTySize) + return truncate(DstTySize); + else if (SrcTySize < DstTySize) + return zeroExtend(DstTySize); + else + return *this; +} + +/// sextOrTrunc - make this range have the bit width given by \p DstTySize. The +/// value is sign extended, truncated, or left alone to make it that width. +ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const { + unsigned SrcTySize = getBitWidth(); + if (SrcTySize > DstTySize) + return truncate(DstTySize); + else if (SrcTySize < DstTySize) + return signExtend(DstTySize); + else + return *this; +} + +ConstantRange +ConstantRange::add(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (isFullSet() || Other.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize(); + APInt NewLower = getLower() + Other.getLower(); + APInt NewUpper = getUpper() + Other.getUpper() - 1; + if (NewLower == NewUpper) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + ConstantRange X = ConstantRange(NewLower, NewUpper); + if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y)) + // We've wrapped, therefore, full set. + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return X; +} + +ConstantRange +ConstantRange::sub(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (isFullSet() || Other.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize(); + APInt NewLower = getLower() - Other.getLower(); + APInt NewUpper = getUpper() - Other.getUpper() + 1; + if (NewLower == NewUpper) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + ConstantRange X = ConstantRange(NewLower, NewUpper); + if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y)) + // We've wrapped, therefore, full set. + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return X; +} + +ConstantRange +ConstantRange::multiply(const ConstantRange &Other) const { + // TODO: If either operand is a single element and the multiply is known to + // be non-wrapping, round the result min and max value to the appropriate + // multiple of that element. If wrapping is possible, at least adjust the + // range according to the greatest power-of-two factor of the single element. + + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (isFullSet() || Other.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt this_min = getUnsignedMin().zext(getBitWidth() * 2); + APInt this_max = getUnsignedMax().zext(getBitWidth() * 2); + APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2); + APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2); + + ConstantRange Result_zext = ConstantRange(this_min * Other_min, + this_max * Other_max + 1); + return Result_zext.truncate(getBitWidth()); +} + +ConstantRange +ConstantRange::smax(const ConstantRange &Other) const { + // X smax Y is: range(smax(X_smin, Y_smin), + // smax(X_smax, Y_smax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin()); + APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange +ConstantRange::umax(const ConstantRange &Other) const { + // X umax Y is: range(umax(X_umin, Y_umin), + // umax(X_umax, Y_umax)) + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); + APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1; + if (NewU == NewL) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(NewL, NewU); +} + +ConstantRange +ConstantRange::udiv(const ConstantRange &RHS) const { + if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax() == 0) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + if (RHS.isFullSet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax()); + + APInt RHS_umin = RHS.getUnsignedMin(); + if (RHS_umin == 0) { + // We want the lowest value in RHS excluding zero. Usually that would be 1 + // except for a range in the form of [X, 1) in which case it would be X. + if (RHS.getUpper() == 1) + RHS_umin = RHS.getLower(); + else + RHS_umin = APInt(getBitWidth(), 1); + } + + APInt Upper = getUnsignedMax().udiv(RHS_umin) + 1; + + // If the LHS is Full and the RHS is a wrapped interval containing 1 then + // this could occur. + if (Lower == Upper) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return ConstantRange(Lower, Upper); +} + +ConstantRange +ConstantRange::binaryAnd(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + + // TODO: replace this with something less conservative + + APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); + if (umin.isAllOnesValue()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(APInt::getNullValue(getBitWidth()), umin + 1); +} + +ConstantRange +ConstantRange::binaryOr(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + + // TODO: replace this with something less conservative + + APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); + if (umax.isMinValue()) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + return ConstantRange(umax, APInt::getNullValue(getBitWidth())); +} + +ConstantRange +ConstantRange::shl(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + + APInt min = getUnsignedMin().shl(Other.getUnsignedMin()); + APInt max = getUnsignedMax().shl(Other.getUnsignedMax()); + + // there's no overflow! + APInt Zeros(getBitWidth(), getUnsignedMax().countLeadingZeros()); + if (Zeros.ugt(Other.getUnsignedMax())) + return ConstantRange(min, max + 1); + + // FIXME: implement the other tricky cases + return ConstantRange(getBitWidth(), /*isFullSet=*/true); +} + +ConstantRange +ConstantRange::lshr(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + + APInt max = getUnsignedMax().lshr(Other.getUnsignedMin()); + APInt min = getUnsignedMin().lshr(Other.getUnsignedMax()); + if (min == max + 1) + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + + return ConstantRange(min, max + 1); +} + +ConstantRange ConstantRange::inverse() const { + if (isFullSet()) { + return ConstantRange(getBitWidth(), /*isFullSet=*/false); + } else if (isEmptySet()) { + return ConstantRange(getBitWidth(), /*isFullSet=*/true); + } + return ConstantRange(Upper, Lower); +} + +/// print - Print out the bounds to a stream... +/// +void ConstantRange::print(raw_ostream &OS) const { + if (isFullSet()) + OS << "full-set"; + else if (isEmptySet()) + OS << "empty-set"; + else + OS << "[" << Lower << "," << Upper << ")"; +} + +/// dump - Allow printing from a debugger easily... +/// +void ConstantRange::dump() const { + print(dbgs()); +} diff --git a/final/lib/Support/CrashRecoveryContext.cpp b/final/lib/Support/CrashRecoveryContext.cpp new file mode 100644 index 00000000000..bf8ca3f844b --- /dev/null +++ b/final/lib/Support/CrashRecoveryContext.cpp @@ -0,0 +1,230 @@ +//===--- CrashRecoveryContext.cpp - Crash Recovery ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/ThreadLocal.h" +#include +#include +using namespace llvm; + +namespace { + +struct CrashRecoveryContextImpl; + +static sys::ThreadLocal CurrentContext; + +struct CrashRecoveryContextImpl { + CrashRecoveryContext *CRC; + std::string Backtrace; + ::jmp_buf JumpBuffer; + volatile unsigned Failed : 1; + +public: + CrashRecoveryContextImpl(CrashRecoveryContext *CRC) : CRC(CRC), + Failed(false) { + CurrentContext.set(this); + } + ~CrashRecoveryContextImpl() { + CurrentContext.erase(); + } + + void HandleCrash() { + // Eliminate the current context entry, to avoid re-entering in case the + // cleanup code crashes. + CurrentContext.erase(); + + assert(!Failed && "Crash recovery context already failed!"); + Failed = true; + + // FIXME: Stash the backtrace. + + // Jump back to the RunSafely we were called under. + longjmp(JumpBuffer, 1); + } +}; + +} + +static sys::Mutex gCrashRecoveryContexMutex; +static bool gCrashRecoveryEnabled = false; + +CrashRecoveryContext::~CrashRecoveryContext() { + CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; + delete CRCI; +} + +CrashRecoveryContext *CrashRecoveryContext::GetCurrent() { + const CrashRecoveryContextImpl *CRCI = CurrentContext.get(); + if (!CRCI) + return 0; + + return CRCI->CRC; +} + +#ifdef LLVM_ON_WIN32 + +// FIXME: No real Win32 implementation currently. + +void CrashRecoveryContext::Enable() { + sys::ScopedLock L(gCrashRecoveryContexMutex); + + if (gCrashRecoveryEnabled) + return; + + gCrashRecoveryEnabled = true; +} + +void CrashRecoveryContext::Disable() { + sys::ScopedLock L(gCrashRecoveryContexMutex); + + if (!gCrashRecoveryEnabled) + return; + + gCrashRecoveryEnabled = false; +} + +#else + +// Generic POSIX implementation. +// +// This implementation relies on synchronous signals being delivered to the +// current thread. We use a thread local object to keep track of the active +// crash recovery context, and install signal handlers to invoke HandleCrash on +// the active object. +// +// This implementation does not to attempt to chain signal handlers in any +// reliable fashion -- if we get a signal outside of a crash recovery context we +// simply disable crash recovery and raise the signal again. + +#include + +static int Signals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP }; +static const unsigned NumSignals = sizeof(Signals) / sizeof(Signals[0]); +static struct sigaction PrevActions[NumSignals]; + +static void CrashRecoverySignalHandler(int Signal) { + // Lookup the current thread local recovery object. + const CrashRecoveryContextImpl *CRCI = CurrentContext.get(); + + if (!CRCI) { + // We didn't find a crash recovery context -- this means either we got a + // signal on a thread we didn't expect it on, the application got a signal + // outside of a crash recovery context, or something else went horribly + // wrong. + // + // Disable crash recovery and raise the signal again. The assumption here is + // that the enclosing application will terminate soon, and we won't want to + // attempt crash recovery again. + // + // This call of Disable isn't thread safe, but it doesn't actually matter. + CrashRecoveryContext::Disable(); + raise(Signal); + + // The signal will be thrown once the signal mask is restored. + return; + } + + // Unblock the signal we received. + sigset_t SigMask; + sigemptyset(&SigMask); + sigaddset(&SigMask, Signal); + sigprocmask(SIG_UNBLOCK, &SigMask, 0); + + if (CRCI) + const_cast(CRCI)->HandleCrash(); +} + +void CrashRecoveryContext::Enable() { + sys::ScopedLock L(gCrashRecoveryContexMutex); + + if (gCrashRecoveryEnabled) + return; + + gCrashRecoveryEnabled = true; + + // Setup the signal handler. + struct sigaction Handler; + Handler.sa_handler = CrashRecoverySignalHandler; + Handler.sa_flags = 0; + sigemptyset(&Handler.sa_mask); + + for (unsigned i = 0; i != NumSignals; ++i) { + sigaction(Signals[i], &Handler, &PrevActions[i]); + } +} + +void CrashRecoveryContext::Disable() { + sys::ScopedLock L(gCrashRecoveryContexMutex); + + if (!gCrashRecoveryEnabled) + return; + + gCrashRecoveryEnabled = false; + + // Restore the previous signal handlers. + for (unsigned i = 0; i != NumSignals; ++i) + sigaction(Signals[i], &PrevActions[i], 0); +} + +#endif + +bool CrashRecoveryContext::RunSafely(void (*Fn)(void*), void *UserData) { + // If crash recovery is disabled, do nothing. + if (gCrashRecoveryEnabled) { + assert(!Impl && "Crash recovery context already initialized!"); + CrashRecoveryContextImpl *CRCI = new CrashRecoveryContextImpl(this); + Impl = CRCI; + + if (setjmp(CRCI->JumpBuffer) != 0) { + return false; + } + } + + Fn(UserData); + return true; +} + +void CrashRecoveryContext::HandleCrash() { + CrashRecoveryContextImpl *CRCI = (CrashRecoveryContextImpl *) Impl; + assert(CRCI && "Crash recovery context never initialized!"); + CRCI->HandleCrash(); +} + +const std::string &CrashRecoveryContext::getBacktrace() const { + CrashRecoveryContextImpl *CRC = (CrashRecoveryContextImpl *) Impl; + assert(CRC && "Crash recovery context never initialized!"); + assert(CRC->Failed && "No crash was detected!"); + return CRC->Backtrace; +} + +// + +namespace { +struct RunSafelyOnThreadInfo { + void (*UserFn)(void*); + void *UserData; + CrashRecoveryContext *CRC; + bool Result; +}; +} + +static void RunSafelyOnThread_Dispatch(void *UserData) { + RunSafelyOnThreadInfo *Info = + reinterpret_cast(UserData); + Info->Result = Info->CRC->RunSafely(Info->UserFn, Info->UserData); +} +bool CrashRecoveryContext::RunSafelyOnThread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + RunSafelyOnThreadInfo Info = { Fn, UserData, this, false }; + llvm_execute_on_thread(RunSafelyOnThread_Dispatch, &Info, RequestedStackSize); + return Info.Result; +} diff --git a/final/lib/Support/DAGDeltaAlgorithm.cpp b/final/lib/Support/DAGDeltaAlgorithm.cpp new file mode 100644 index 00000000000..814566494d3 --- /dev/null +++ b/final/lib/Support/DAGDeltaAlgorithm.cpp @@ -0,0 +1,357 @@ +//===--- DAGDeltaAlgorithm.cpp - A DAG Minimization Algorithm --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// The algorithm we use attempts to exploit the dependency information by +// minimizing top-down. We start by constructing an initial root set R, and +// then iteratively: +// +// 1. Minimize the set R using the test predicate: +// P'(S) = P(S union pred*(S)) +// +// 2. Extend R to R' = R union pred(R). +// +// until a fixed point is reached. +// +// The idea is that we want to quickly prune entire portions of the graph, so we +// try to find high-level nodes that can be eliminated with all of their +// dependents. +// +// FIXME: The current algorithm doesn't actually provide a strong guarantee +// about the minimality of the result. The problem is that after adding nodes to +// the required set, we no longer consider them for elimination. For strictly +// well formed predicates, this doesn't happen, but it commonly occurs in +// practice when there are unmodelled dependencies. I believe we can resolve +// this by allowing the required set to be minimized as well, but need more test +// cases first. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DAGDeltaAlgorithm.h" +#include "llvm/ADT/DeltaAlgorithm.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +using namespace llvm; + +namespace { + +class DAGDeltaAlgorithmImpl { + friend class DeltaActiveSetHelper; + +public: + typedef DAGDeltaAlgorithm::change_ty change_ty; + typedef DAGDeltaAlgorithm::changeset_ty changeset_ty; + typedef DAGDeltaAlgorithm::changesetlist_ty changesetlist_ty; + typedef DAGDeltaAlgorithm::edge_ty edge_ty; + +private: + typedef std::vector::iterator pred_iterator_ty; + typedef std::vector::iterator succ_iterator_ty; + typedef std::set::iterator pred_closure_iterator_ty; + typedef std::set::iterator succ_closure_iterator_ty; + + DAGDeltaAlgorithm &DDA; + + const changeset_ty &Changes; + const std::vector &Dependencies; + + std::vector Roots; + + /// Cache of failed test results. Successful test results are never cached + /// since we always reduce following a success. We maintain an independent + /// cache from that used by the individual delta passes because we may get + /// hits across multiple individual delta invocations. + mutable std::set FailedTestsCache; + + // FIXME: Gross. + std::map > Predecessors; + std::map > Successors; + + std::map > PredClosure; + std::map > SuccClosure; + +private: + pred_iterator_ty pred_begin(change_ty Node) { + assert(Predecessors.count(Node) && "Invalid node!"); + return Predecessors[Node].begin(); + } + pred_iterator_ty pred_end(change_ty Node) { + assert(Predecessors.count(Node) && "Invalid node!"); + return Predecessors[Node].end(); + } + + pred_closure_iterator_ty pred_closure_begin(change_ty Node) { + assert(PredClosure.count(Node) && "Invalid node!"); + return PredClosure[Node].begin(); + } + pred_closure_iterator_ty pred_closure_end(change_ty Node) { + assert(PredClosure.count(Node) && "Invalid node!"); + return PredClosure[Node].end(); + } + + succ_iterator_ty succ_begin(change_ty Node) { + assert(Successors.count(Node) && "Invalid node!"); + return Successors[Node].begin(); + } + succ_iterator_ty succ_end(change_ty Node) { + assert(Successors.count(Node) && "Invalid node!"); + return Successors[Node].end(); + } + + succ_closure_iterator_ty succ_closure_begin(change_ty Node) { + assert(SuccClosure.count(Node) && "Invalid node!"); + return SuccClosure[Node].begin(); + } + succ_closure_iterator_ty succ_closure_end(change_ty Node) { + assert(SuccClosure.count(Node) && "Invalid node!"); + return SuccClosure[Node].end(); + } + + void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets, + const changeset_ty &Required) { + DDA.UpdatedSearchState(Changes, Sets, Required); + } + + /// ExecuteOneTest - Execute a single test predicate on the change set \arg S. + bool ExecuteOneTest(const changeset_ty &S) { + // Check dependencies invariant. + DEBUG({ + for (changeset_ty::const_iterator it = S.begin(), + ie = S.end(); it != ie; ++it) + for (succ_iterator_ty it2 = succ_begin(*it), + ie2 = succ_end(*it); it2 != ie2; ++it2) + assert(S.count(*it2) && "Attempt to run invalid changeset!"); + }); + + return DDA.ExecuteOneTest(S); + } + +public: + DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA, + const changeset_ty &_Changes, + const std::vector &_Dependencies); + + changeset_ty Run(); + + /// GetTestResult - Get the test result for the active set \arg Changes with + /// \arg Required changes from the cache, executing the test if necessary. + /// + /// \param Changes - The set of active changes being minimized, which should + /// have their pred closure included in the test. + /// \param Required - The set of changes which have previously been + /// established to be required. + /// \return - The test result. + bool GetTestResult(const changeset_ty &Changes, const changeset_ty &Required); +}; + +/// Helper object for minimizing an active set of changes. +class DeltaActiveSetHelper : public DeltaAlgorithm { + DAGDeltaAlgorithmImpl &DDAI; + + const changeset_ty &Required; + +protected: + /// UpdatedSearchState - Callback used when the search state changes. + virtual void UpdatedSearchState(const changeset_ty &Changes, + const changesetlist_ty &Sets) { + DDAI.UpdatedSearchState(Changes, Sets, Required); + } + + virtual bool ExecuteOneTest(const changeset_ty &S) { + return DDAI.GetTestResult(S, Required); + } + +public: + DeltaActiveSetHelper(DAGDeltaAlgorithmImpl &_DDAI, + const changeset_ty &_Required) + : DDAI(_DDAI), Required(_Required) {} +}; + +} + +DAGDeltaAlgorithmImpl::DAGDeltaAlgorithmImpl(DAGDeltaAlgorithm &_DDA, + const changeset_ty &_Changes, + const std::vector + &_Dependencies) + : DDA(_DDA), + Changes(_Changes), + Dependencies(_Dependencies) +{ + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) { + Predecessors.insert(std::make_pair(*it, std::vector())); + Successors.insert(std::make_pair(*it, std::vector())); + } + for (std::vector::const_iterator it = Dependencies.begin(), + ie = Dependencies.end(); it != ie; ++it) { + Predecessors[it->second].push_back(it->first); + Successors[it->first].push_back(it->second); + } + + // Compute the roots. + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) + if (succ_begin(*it) == succ_end(*it)) + Roots.push_back(*it); + + // Pre-compute the closure of the successor relation. + std::vector Worklist(Roots.begin(), Roots.end()); + while (!Worklist.empty()) { + change_ty Change = Worklist.back(); + Worklist.pop_back(); + + std::set &ChangeSuccs = SuccClosure[Change]; + for (pred_iterator_ty it = pred_begin(Change), + ie = pred_end(Change); it != ie; ++it) { + SuccClosure[*it].insert(Change); + SuccClosure[*it].insert(ChangeSuccs.begin(), ChangeSuccs.end()); + Worklist.push_back(*it); + } + } + + // Invert to form the predecessor closure map. + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) + PredClosure.insert(std::make_pair(*it, std::set())); + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) + for (succ_closure_iterator_ty it2 = succ_closure_begin(*it), + ie2 = succ_closure_end(*it); it2 != ie2; ++it2) + PredClosure[*it2].insert(*it); + + // Dump useful debug info. + DEBUG({ + llvm::errs() << "-- DAGDeltaAlgorithmImpl --\n"; + llvm::errs() << "Changes: ["; + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) { + if (it != Changes.begin()) llvm::errs() << ", "; + llvm::errs() << *it; + + if (succ_begin(*it) != succ_end(*it)) { + llvm::errs() << "("; + for (succ_iterator_ty it2 = succ_begin(*it), + ie2 = succ_end(*it); it2 != ie2; ++it2) { + if (it2 != succ_begin(*it)) llvm::errs() << ", "; + llvm::errs() << "->" << *it2; + } + llvm::errs() << ")"; + } + } + llvm::errs() << "]\n"; + + llvm::errs() << "Roots: ["; + for (std::vector::const_iterator it = Roots.begin(), + ie = Roots.end(); it != ie; ++it) { + if (it != Roots.begin()) llvm::errs() << ", "; + llvm::errs() << *it; + } + llvm::errs() << "]\n"; + + llvm::errs() << "Predecessor Closure:\n"; + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) { + llvm::errs() << format(" %-4d: [", *it); + for (pred_closure_iterator_ty it2 = pred_closure_begin(*it), + ie2 = pred_closure_end(*it); it2 != ie2; ++it2) { + if (it2 != pred_closure_begin(*it)) llvm::errs() << ", "; + llvm::errs() << *it2; + } + llvm::errs() << "]\n"; + } + + llvm::errs() << "Successor Closure:\n"; + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) { + llvm::errs() << format(" %-4d: [", *it); + for (succ_closure_iterator_ty it2 = succ_closure_begin(*it), + ie2 = succ_closure_end(*it); it2 != ie2; ++it2) { + if (it2 != succ_closure_begin(*it)) llvm::errs() << ", "; + llvm::errs() << *it2; + } + llvm::errs() << "]\n"; + } + + llvm::errs() << "\n\n"; + }); +} + +bool DAGDeltaAlgorithmImpl::GetTestResult(const changeset_ty &Changes, + const changeset_ty &Required) { + changeset_ty Extended(Required); + Extended.insert(Changes.begin(), Changes.end()); + for (changeset_ty::const_iterator it = Changes.begin(), + ie = Changes.end(); it != ie; ++it) + Extended.insert(pred_closure_begin(*it), pred_closure_end(*it)); + + if (FailedTestsCache.count(Extended)) + return false; + + bool Result = ExecuteOneTest(Extended); + if (!Result) + FailedTestsCache.insert(Extended); + + return Result; +} + +DAGDeltaAlgorithm::changeset_ty +DAGDeltaAlgorithmImpl::Run() { + // The current set of changes we are minimizing, starting at the roots. + changeset_ty CurrentSet(Roots.begin(), Roots.end()); + + // The set of required changes. + changeset_ty Required; + + // Iterate until the active set of changes is empty. Convergence is guaranteed + // assuming input was a DAG. + // + // Invariant: CurrentSet intersect Required == {} + // Invariant: Required == (Required union succ*(Required)) + while (!CurrentSet.empty()) { + DEBUG({ + llvm::errs() << "DAG_DD - " << CurrentSet.size() << " active changes, " + << Required.size() << " required changes\n"; + }); + + // Minimize the current set of changes. + DeltaActiveSetHelper Helper(*this, Required); + changeset_ty CurrentMinSet = Helper.Run(CurrentSet); + + // Update the set of required changes. Since + // CurrentMinSet subset CurrentSet + // and after the last iteration, + // succ(CurrentSet) subset Required + // then + // succ(CurrentMinSet) subset Required + // and our invariant on Required is maintained. + Required.insert(CurrentMinSet.begin(), CurrentMinSet.end()); + + // Replace the current set with the predecssors of the minimized set of + // active changes. + CurrentSet.clear(); + for (changeset_ty::const_iterator it = CurrentMinSet.begin(), + ie = CurrentMinSet.end(); it != ie; ++it) + CurrentSet.insert(pred_begin(*it), pred_end(*it)); + + // FIXME: We could enforce CurrentSet intersect Required == {} here if we + // wanted to protect against cyclic graphs. + } + + return Required; +} + +DAGDeltaAlgorithm::changeset_ty +DAGDeltaAlgorithm::Run(const changeset_ty &Changes, + const std::vector &Dependencies) { + return DAGDeltaAlgorithmImpl(*this, Changes, Dependencies).Run(); +} diff --git a/final/lib/Support/Debug.cpp b/final/lib/Support/Debug.cpp new file mode 100644 index 00000000000..9fdb12ecfdc --- /dev/null +++ b/final/lib/Support/Debug.cpp @@ -0,0 +1,134 @@ +//===-- Debug.cpp - An easy way to add debug output to your code ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handle way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling in release mode, the -debug-* options and all code in DEBUG() +// statements disappears, so it does not effect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/circular_raw_ostream.h" +#include "llvm/Support/Signals.h" + +using namespace llvm; + +// All Debug.h functionality is a no-op in NDEBUG mode. +#ifndef NDEBUG +bool llvm::DebugFlag; // DebugFlag - Exported boolean set by the -debug option + +// -debug - Command line option to enable the DEBUG statements in the passes. +// This flag may only be enabled in debug builds. +static cl::opt +Debug("debug", cl::desc("Enable debug output"), cl::Hidden, + cl::location(DebugFlag)); + +// -debug-buffer-size - Buffer the last N characters of debug output +//until program termination. +static cl::opt +DebugBufferSize("debug-buffer-size", + cl::desc("Buffer the last N characters of debug output" + "until program termination. " + "[default 0 -- immediate print-out]"), + cl::Hidden, + cl::init(0)); + +static std::string CurrentDebugType; + +namespace { + +struct DebugOnlyOpt { + void operator=(const std::string &Val) const { + DebugFlag |= !Val.empty(); + CurrentDebugType = Val; + } +}; + +} + +static DebugOnlyOpt DebugOnlyOptLoc; + +static cl::opt > +DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), + cl::Hidden, cl::value_desc("debug string"), + cl::location(DebugOnlyOptLoc), cl::ValueRequired); + +// Signal handlers - dump debug output on termination. +static void debug_user_sig_handler(void *Cookie) { + // This is a bit sneaky. Since this is under #ifndef NDEBUG, we + // know that debug mode is enabled and dbgs() really is a + // circular_raw_ostream. If NDEBUG is defined, then dbgs() == + // errs() but this will never be invoked. + llvm::circular_raw_ostream *dbgout = + static_cast(&llvm::dbgs()); + dbgout->flushBufferWithBanner(); +} + +// isCurrentDebugType - Return true if the specified string is the debug type +// specified on the command line, or if none was specified on the command line +// with the -debug-only=X option. +// +bool llvm::isCurrentDebugType(const char *DebugType) { + return CurrentDebugType.empty() || DebugType == CurrentDebugType; +} + +/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// option were specified. Note that DebugFlag also needs to be set to true for +/// debug output to be produced. +/// +void llvm::SetCurrentDebugType(const char *Type) { + CurrentDebugType = Type; +} + +/// dbgs - Return a circular-buffered debug stream. +raw_ostream &llvm::dbgs() { + // Do one-time initialization in a thread-safe way. + static struct dbgstream { + circular_raw_ostream strm; + + dbgstream() : + strm(errs(), "*** Debug Log Output ***\n", + (!EnableDebugBuffering || !DebugFlag) ? 0 : DebugBufferSize) { + if (EnableDebugBuffering && DebugFlag && DebugBufferSize != 0) + // TODO: Add a handler for SIGUSER1-type signals so the user can + // force a debug dump. + sys::AddSignalHandler(&debug_user_sig_handler, 0); + // Otherwise we've already set the debug stream buffer size to + // zero, disabling buffering so it will output directly to errs(). + } + } thestrm; + + return thestrm.strm; +} + +#else +// Avoid "has no symbols" warning. +namespace llvm { + /// dbgs - Return errs(). + raw_ostream &dbgs() { + return errs(); + } +} + +#endif + +/// EnableDebugBuffering - Turn on signal handler installation. +/// +bool llvm::EnableDebugBuffering = false; diff --git a/final/lib/Support/DeltaAlgorithm.cpp b/final/lib/Support/DeltaAlgorithm.cpp new file mode 100644 index 00000000000..9e52874de83 --- /dev/null +++ b/final/lib/Support/DeltaAlgorithm.cpp @@ -0,0 +1,114 @@ +//===--- DeltaAlgorithm.cpp - A Set Minimization Algorithm -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DeltaAlgorithm.h" +#include +#include +using namespace llvm; + +DeltaAlgorithm::~DeltaAlgorithm() { +} + +bool DeltaAlgorithm::GetTestResult(const changeset_ty &Changes) { + if (FailedTestsCache.count(Changes)) + return false; + + bool Result = ExecuteOneTest(Changes); + if (!Result) + FailedTestsCache.insert(Changes); + + return Result; +} + +void DeltaAlgorithm::Split(const changeset_ty &S, changesetlist_ty &Res) { + // FIXME: Allow clients to provide heuristics for improved splitting. + + // FIXME: This is really slow. + changeset_ty LHS, RHS; + unsigned idx = 0, N = S.size() / 2; + for (changeset_ty::const_iterator it = S.begin(), + ie = S.end(); it != ie; ++it, ++idx) + ((idx < N) ? LHS : RHS).insert(*it); + if (!LHS.empty()) + Res.push_back(LHS); + if (!RHS.empty()) + Res.push_back(RHS); +} + +DeltaAlgorithm::changeset_ty +DeltaAlgorithm::Delta(const changeset_ty &Changes, + const changesetlist_ty &Sets) { + // Invariant: union(Res) == Changes + UpdatedSearchState(Changes, Sets); + + // If there is nothing left we can remove, we are done. + if (Sets.size() <= 1) + return Changes; + + // Look for a passing subset. + changeset_ty Res; + if (Search(Changes, Sets, Res)) + return Res; + + // Otherwise, partition the sets if possible; if not we are done. + changesetlist_ty SplitSets; + for (changesetlist_ty::const_iterator it = Sets.begin(), + ie = Sets.end(); it != ie; ++it) + Split(*it, SplitSets); + if (SplitSets.size() == Sets.size()) + return Changes; + + return Delta(Changes, SplitSets); +} + +bool DeltaAlgorithm::Search(const changeset_ty &Changes, + const changesetlist_ty &Sets, + changeset_ty &Res) { + // FIXME: Parallelize. + for (changesetlist_ty::const_iterator it = Sets.begin(), + ie = Sets.end(); it != ie; ++it) { + // If the test passes on this subset alone, recurse. + if (GetTestResult(*it)) { + changesetlist_ty Sets; + Split(*it, Sets); + Res = Delta(*it, Sets); + return true; + } + + // Otherwise, if we have more than two sets, see if test passes on the + // complement. + if (Sets.size() > 2) { + // FIXME: This is really slow. + changeset_ty Complement; + std::set_difference( + Changes.begin(), Changes.end(), it->begin(), it->end(), + std::insert_iterator(Complement, Complement.begin())); + if (GetTestResult(Complement)) { + changesetlist_ty ComplementSets; + ComplementSets.insert(ComplementSets.end(), Sets.begin(), it); + ComplementSets.insert(ComplementSets.end(), it + 1, Sets.end()); + Res = Delta(Complement, ComplementSets); + return true; + } + } + } + + return false; +} + +DeltaAlgorithm::changeset_ty DeltaAlgorithm::Run(const changeset_ty &Changes) { + // Check empty set first to quickly find poor test functions. + if (GetTestResult(changeset_ty())) + return changeset_ty(); + + // Otherwise run the real delta algorithm. + changesetlist_ty Sets; + Split(Changes, Sets); + + return Delta(Changes, Sets); +} diff --git a/final/lib/Support/Disassembler.cpp b/final/lib/Support/Disassembler.cpp new file mode 100644 index 00000000000..6362aff43a9 --- /dev/null +++ b/final/lib/Support/Disassembler.cpp @@ -0,0 +1,75 @@ +//===- lib/System/Disassembler.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/Support/Disassembler.h" + +#include +#include +#include +#include + +#if USE_UDIS86 +#include +#endif + +using namespace llvm; + +bool llvm::sys::hasDisassembler() +{ +#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) + // We have option to enable udis86 library. +# if USE_UDIS86 + return true; +#else + return false; +#endif +#else + return false; +#endif +} + +std::string llvm::sys::disassembleBuffer(uint8_t* start, size_t length, + uint64_t pc) { + std::stringstream res; + +#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) \ + && USE_UDIS86 + unsigned bits; +# if defined(__i386__) + bits = 32; +# else + bits = 64; +# endif + + ud_t ud_obj; + + ud_init(&ud_obj); + ud_set_input_buffer(&ud_obj, start, length); + ud_set_mode(&ud_obj, bits); + ud_set_pc(&ud_obj, pc); + ud_set_syntax(&ud_obj, UD_SYN_ATT); + + res << std::setbase(16) + << std::setw(bits/4); + + while (ud_disassemble(&ud_obj)) { + res << ud_insn_off(&ud_obj) << ":\t" << ud_insn_asm(&ud_obj) << "\n"; + } +#else + res << "No disassembler available. See configure help for options.\n"; +#endif + + return res.str(); +} diff --git a/final/lib/Support/Dwarf.cpp b/final/lib/Support/Dwarf.cpp new file mode 100644 index 00000000000..9799ef54792 --- /dev/null +++ b/final/lib/Support/Dwarf.cpp @@ -0,0 +1,652 @@ +//===-- llvm/Support/Dwarf.cpp - Dwarf Framework ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for generic dwarf information. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Dwarf.h" +using namespace llvm; +using namespace dwarf; + +/// TagString - Return the string for the specified tag. +/// +const char *llvm::dwarf::TagString(unsigned Tag) { + switch (Tag) { + case DW_TAG_array_type: return "DW_TAG_array_type"; + case DW_TAG_class_type: return "DW_TAG_class_type"; + case DW_TAG_entry_point: return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; + case DW_TAG_label: return "DW_TAG_label"; + case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; + case DW_TAG_member: return "DW_TAG_member"; + case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; + case DW_TAG_string_type: return "DW_TAG_string_type"; + case DW_TAG_structure_type: return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: return "DW_TAG_typedef"; + case DW_TAG_union_type: return "DW_TAG_union_type"; + case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; + case DW_TAG_variant: return "DW_TAG_variant"; + case DW_TAG_common_block: return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: return "DW_TAG_set_type"; + case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; + case DW_TAG_base_type: return "DW_TAG_base_type"; + case DW_TAG_catch_block: return "DW_TAG_catch_block"; + case DW_TAG_const_type: return "DW_TAG_const_type"; + case DW_TAG_constant: return "DW_TAG_constant"; + case DW_TAG_enumerator: return "DW_TAG_enumerator"; + case DW_TAG_file_type: return "DW_TAG_file_type"; + case DW_TAG_friend: return "DW_TAG_friend"; + case DW_TAG_namelist: return "DW_TAG_namelist"; + case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: return "DW_TAG_packed_type"; + case DW_TAG_subprogram: return "DW_TAG_subprogram"; + case DW_TAG_template_type_parameter: return "DW_TAG_template_type_parameter"; + case DW_TAG_template_value_parameter:return "DW_TAG_template_value_parameter"; + case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; + case DW_TAG_try_block: return "DW_TAG_try_block"; + case DW_TAG_variant_part: return "DW_TAG_variant_part"; + case DW_TAG_variable: return "DW_TAG_variable"; + case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: return "DW_TAG_interface_type"; + case DW_TAG_namespace: return "DW_TAG_namespace"; + case DW_TAG_imported_module: return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; + case DW_TAG_condition: return "DW_TAG_condition"; + case DW_TAG_shared_type: return "DW_TAG_shared_type"; + case DW_TAG_lo_user: return "DW_TAG_lo_user"; + case DW_TAG_hi_user: return "DW_TAG_hi_user"; + case DW_TAG_auto_variable: return "DW_TAG_auto_variable"; + case DW_TAG_arg_variable: return "DW_TAG_arg_variable"; + case DW_TAG_return_variable: return "DW_TAG_return_variable"; + case DW_TAG_vector_type: return "DW_TAG_vector_type"; + } + return 0; +} + +/// ChildrenString - Return the string for the specified children flag. +/// +const char *llvm::dwarf::ChildrenString(unsigned Children) { + switch (Children) { + case DW_CHILDREN_no: return "DW_CHILDREN_no"; + case DW_CHILDREN_yes: return "DW_CHILDREN_yes"; + } + return 0; +} + +/// AttributeString - Return the string for the specified attribute. +/// +const char *llvm::dwarf::AttributeString(unsigned Attribute) { + switch (Attribute) { + case DW_AT_sibling: return "DW_AT_sibling"; + case DW_AT_location: return "DW_AT_location"; + case DW_AT_name: return "DW_AT_name"; + case DW_AT_ordering: return "DW_AT_ordering"; + case DW_AT_byte_size: return "DW_AT_byte_size"; + case DW_AT_bit_offset: return "DW_AT_bit_offset"; + case DW_AT_bit_size: return "DW_AT_bit_size"; + case DW_AT_stmt_list: return "DW_AT_stmt_list"; + case DW_AT_low_pc: return "DW_AT_low_pc"; + case DW_AT_high_pc: return "DW_AT_high_pc"; + case DW_AT_language: return "DW_AT_language"; + case DW_AT_discr: return "DW_AT_discr"; + case DW_AT_discr_value: return "DW_AT_discr_value"; + case DW_AT_visibility: return "DW_AT_visibility"; + case DW_AT_import: return "DW_AT_import"; + case DW_AT_string_length: return "DW_AT_string_length"; + case DW_AT_common_reference: return "DW_AT_common_reference"; + case DW_AT_comp_dir: return "DW_AT_comp_dir"; + case DW_AT_const_value: return "DW_AT_const_value"; + case DW_AT_containing_type: return "DW_AT_containing_type"; + case DW_AT_default_value: return "DW_AT_default_value"; + case DW_AT_inline: return "DW_AT_inline"; + case DW_AT_is_optional: return "DW_AT_is_optional"; + case DW_AT_lower_bound: return "DW_AT_lower_bound"; + case DW_AT_producer: return "DW_AT_producer"; + case DW_AT_prototyped: return "DW_AT_prototyped"; + case DW_AT_return_addr: return "DW_AT_return_addr"; + case DW_AT_start_scope: return "DW_AT_start_scope"; + case DW_AT_bit_stride: return "DW_AT_bit_stride"; + case DW_AT_upper_bound: return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; + case DW_AT_accessibility: return "DW_AT_accessibility"; + case DW_AT_address_class: return "DW_AT_address_class"; + case DW_AT_artificial: return "DW_AT_artificial"; + case DW_AT_base_types: return "DW_AT_base_types"; + case DW_AT_calling_convention: return "DW_AT_calling_convention"; + case DW_AT_count: return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; + case DW_AT_decl_column: return "DW_AT_decl_column"; + case DW_AT_decl_file: return "DW_AT_decl_file"; + case DW_AT_decl_line: return "DW_AT_decl_line"; + case DW_AT_declaration: return "DW_AT_declaration"; + case DW_AT_discr_list: return "DW_AT_discr_list"; + case DW_AT_encoding: return "DW_AT_encoding"; + case DW_AT_external: return "DW_AT_external"; + case DW_AT_frame_base: return "DW_AT_frame_base"; + case DW_AT_friend: return "DW_AT_friend"; + case DW_AT_identifier_case: return "DW_AT_identifier_case"; + case DW_AT_macro_info: return "DW_AT_macro_info"; + case DW_AT_namelist_item: return "DW_AT_namelist_item"; + case DW_AT_priority: return "DW_AT_priority"; + case DW_AT_segment: return "DW_AT_segment"; + case DW_AT_specification: return "DW_AT_specification"; + case DW_AT_static_link: return "DW_AT_static_link"; + case DW_AT_type: return "DW_AT_type"; + case DW_AT_use_location: return "DW_AT_use_location"; + case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; + case DW_AT_virtuality: return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; + case DW_AT_allocated: return "DW_AT_allocated"; + case DW_AT_associated: return "DW_AT_associated"; + case DW_AT_data_location: return "DW_AT_data_location"; + case DW_AT_byte_stride: return "DW_AT_byte_stride"; + case DW_AT_entry_pc: return "DW_AT_entry_pc"; + case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; + case DW_AT_extension: return "DW_AT_extension"; + case DW_AT_ranges: return "DW_AT_ranges"; + case DW_AT_trampoline: return "DW_AT_trampoline"; + case DW_AT_call_column: return "DW_AT_call_column"; + case DW_AT_call_file: return "DW_AT_call_file"; + case DW_AT_call_line: return "DW_AT_call_line"; + case DW_AT_description: return "DW_AT_description"; + case DW_AT_binary_scale: return "DW_AT_binary_scale"; + case DW_AT_decimal_scale: return "DW_AT_decimal_scale"; + case DW_AT_small: return "DW_AT_small"; + case DW_AT_decimal_sign: return "DW_AT_decimal_sign"; + case DW_AT_digit_count: return "DW_AT_digit_count"; + case DW_AT_picture_string: return "DW_AT_picture_string"; + case DW_AT_mutable: return "DW_AT_mutable"; + case DW_AT_threads_scaled: return "DW_AT_threads_scaled"; + case DW_AT_explicit: return "DW_AT_explicit"; + case DW_AT_object_pointer: return "DW_AT_object_pointer"; + case DW_AT_endianity: return "DW_AT_endianity"; + case DW_AT_elemental: return "DW_AT_elemental"; + case DW_AT_pure: return "DW_AT_pure"; + case DW_AT_recursive: return "DW_AT_recursive"; + case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_sf_names: return "DW_AT_sf_names"; + case DW_AT_src_info: return "DW_AT_src_info"; + case DW_AT_mac_info: return "DW_AT_mac_info"; + case DW_AT_src_coords: return "DW_AT_src_coords"; + case DW_AT_body_begin: return "DW_AT_body_begin"; + case DW_AT_body_end: return "DW_AT_body_end"; + case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_lo_user: return "DW_AT_lo_user"; + case DW_AT_hi_user: return "DW_AT_hi_user"; + case DW_AT_APPLE_optimized: return "DW_AT_APPLE_optimized"; + case DW_AT_APPLE_flags: return "DW_AT_APPLE_flags"; + case DW_AT_APPLE_isa: return "DW_AT_APPLE_isa"; + case DW_AT_APPLE_block: return "DW_AT_APPLE_block"; + case DW_AT_APPLE_major_runtime_vers: return "DW_AT_APPLE_major_runtime_vers"; + case DW_AT_APPLE_runtime_class: return "DW_AT_APPLE_runtime_class"; + case DW_AT_APPLE_omit_frame_ptr: return "DW_AT_APPLE_omit_frame_ptr"; + } + return 0; +} + +/// FormEncodingString - Return the string for the specified form encoding. +/// +const char *llvm::dwarf::FormEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_FORM_addr: return "DW_FORM_addr"; + case DW_FORM_block2: return "DW_FORM_block2"; + case DW_FORM_block4: return "DW_FORM_block4"; + case DW_FORM_data2: return "DW_FORM_data2"; + case DW_FORM_data4: return "DW_FORM_data4"; + case DW_FORM_data8: return "DW_FORM_data8"; + case DW_FORM_string: return "DW_FORM_string"; + case DW_FORM_block: return "DW_FORM_block"; + case DW_FORM_block1: return "DW_FORM_block1"; + case DW_FORM_data1: return "DW_FORM_data1"; + case DW_FORM_flag: return "DW_FORM_flag"; + case DW_FORM_sdata: return "DW_FORM_sdata"; + case DW_FORM_strp: return "DW_FORM_strp"; + case DW_FORM_udata: return "DW_FORM_udata"; + case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; + case DW_FORM_ref1: return "DW_FORM_ref1"; + case DW_FORM_ref2: return "DW_FORM_ref2"; + case DW_FORM_ref4: return "DW_FORM_ref4"; + case DW_FORM_ref8: return "DW_FORM_ref8"; + case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; + case DW_FORM_indirect: return "DW_FORM_indirect"; + } + return 0; +} + +/// OperationEncodingString - Return the string for the specified operation +/// encoding. +const char *llvm::dwarf::OperationEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_OP_addr: return "DW_OP_addr"; + case DW_OP_deref: return "DW_OP_deref"; + case DW_OP_const1u: return "DW_OP_const1u"; + case DW_OP_const1s: return "DW_OP_const1s"; + case DW_OP_const2u: return "DW_OP_const2u"; + case DW_OP_const2s: return "DW_OP_const2s"; + case DW_OP_const4u: return "DW_OP_const4u"; + case DW_OP_const4s: return "DW_OP_const4s"; + case DW_OP_const8u: return "DW_OP_const8u"; + case DW_OP_const8s: return "DW_OP_const8s"; + case DW_OP_constu: return "DW_OP_constu"; + case DW_OP_consts: return "DW_OP_consts"; + case DW_OP_dup: return "DW_OP_dup"; + case DW_OP_drop: return "DW_OP_drop"; + case DW_OP_over: return "DW_OP_over"; + case DW_OP_pick: return "DW_OP_pick"; + case DW_OP_swap: return "DW_OP_swap"; + case DW_OP_rot: return "DW_OP_rot"; + case DW_OP_xderef: return "DW_OP_xderef"; + case DW_OP_abs: return "DW_OP_abs"; + case DW_OP_and: return "DW_OP_and"; + case DW_OP_div: return "DW_OP_div"; + case DW_OP_minus: return "DW_OP_minus"; + case DW_OP_mod: return "DW_OP_mod"; + case DW_OP_mul: return "DW_OP_mul"; + case DW_OP_neg: return "DW_OP_neg"; + case DW_OP_not: return "DW_OP_not"; + case DW_OP_or: return "DW_OP_or"; + case DW_OP_plus: return "DW_OP_plus"; + case DW_OP_plus_uconst: return "DW_OP_plus_uconst"; + case DW_OP_shl: return "DW_OP_shl"; + case DW_OP_shr: return "DW_OP_shr"; + case DW_OP_shra: return "DW_OP_shra"; + case DW_OP_xor: return "DW_OP_xor"; + case DW_OP_skip: return "DW_OP_skip"; + case DW_OP_bra: return "DW_OP_bra"; + case DW_OP_eq: return "DW_OP_eq"; + case DW_OP_ge: return "DW_OP_ge"; + case DW_OP_gt: return "DW_OP_gt"; + case DW_OP_le: return "DW_OP_le"; + case DW_OP_lt: return "DW_OP_lt"; + case DW_OP_ne: return "DW_OP_ne"; + case DW_OP_lit0: return "DW_OP_lit0"; + case DW_OP_lit1: return "DW_OP_lit1"; + case DW_OP_lit2: return "DW_OP_lit2"; + case DW_OP_lit3: return "DW_OP_lit3"; + case DW_OP_lit4: return "DW_OP_lit4"; + case DW_OP_lit5: return "DW_OP_lit5"; + case DW_OP_lit6: return "DW_OP_lit6"; + case DW_OP_lit7: return "DW_OP_lit7"; + case DW_OP_lit8: return "DW_OP_lit8"; + case DW_OP_lit9: return "DW_OP_lit9"; + case DW_OP_lit10: return "DW_OP_lit10"; + case DW_OP_lit11: return "DW_OP_lit11"; + case DW_OP_lit12: return "DW_OP_lit12"; + case DW_OP_lit13: return "DW_OP_lit13"; + case DW_OP_lit14: return "DW_OP_lit14"; + case DW_OP_lit15: return "DW_OP_lit15"; + case DW_OP_lit16: return "DW_OP_lit16"; + case DW_OP_lit17: return "DW_OP_lit17"; + case DW_OP_lit18: return "DW_OP_lit18"; + case DW_OP_lit19: return "DW_OP_lit19"; + case DW_OP_lit20: return "DW_OP_lit20"; + case DW_OP_lit21: return "DW_OP_lit21"; + case DW_OP_lit22: return "DW_OP_lit22"; + case DW_OP_lit23: return "DW_OP_lit23"; + case DW_OP_lit24: return "DW_OP_lit24"; + case DW_OP_lit25: return "DW_OP_lit25"; + case DW_OP_lit26: return "DW_OP_lit26"; + case DW_OP_lit27: return "DW_OP_lit27"; + case DW_OP_lit28: return "DW_OP_lit28"; + case DW_OP_lit29: return "DW_OP_lit29"; + case DW_OP_lit30: return "DW_OP_lit30"; + case DW_OP_lit31: return "DW_OP_lit31"; + case DW_OP_reg0: return "DW_OP_reg0"; + case DW_OP_reg1: return "DW_OP_reg1"; + case DW_OP_reg2: return "DW_OP_reg2"; + case DW_OP_reg3: return "DW_OP_reg3"; + case DW_OP_reg4: return "DW_OP_reg4"; + case DW_OP_reg5: return "DW_OP_reg5"; + case DW_OP_reg6: return "DW_OP_reg6"; + case DW_OP_reg7: return "DW_OP_reg7"; + case DW_OP_reg8: return "DW_OP_reg8"; + case DW_OP_reg9: return "DW_OP_reg9"; + case DW_OP_reg10: return "DW_OP_reg10"; + case DW_OP_reg11: return "DW_OP_reg11"; + case DW_OP_reg12: return "DW_OP_reg12"; + case DW_OP_reg13: return "DW_OP_reg13"; + case DW_OP_reg14: return "DW_OP_reg14"; + case DW_OP_reg15: return "DW_OP_reg15"; + case DW_OP_reg16: return "DW_OP_reg16"; + case DW_OP_reg17: return "DW_OP_reg17"; + case DW_OP_reg18: return "DW_OP_reg18"; + case DW_OP_reg19: return "DW_OP_reg19"; + case DW_OP_reg20: return "DW_OP_reg20"; + case DW_OP_reg21: return "DW_OP_reg21"; + case DW_OP_reg22: return "DW_OP_reg22"; + case DW_OP_reg23: return "DW_OP_reg23"; + case DW_OP_reg24: return "DW_OP_reg24"; + case DW_OP_reg25: return "DW_OP_reg25"; + case DW_OP_reg26: return "DW_OP_reg26"; + case DW_OP_reg27: return "DW_OP_reg27"; + case DW_OP_reg28: return "DW_OP_reg28"; + case DW_OP_reg29: return "DW_OP_reg29"; + case DW_OP_reg30: return "DW_OP_reg30"; + case DW_OP_reg31: return "DW_OP_reg31"; + case DW_OP_breg0: return "DW_OP_breg0"; + case DW_OP_breg1: return "DW_OP_breg1"; + case DW_OP_breg2: return "DW_OP_breg2"; + case DW_OP_breg3: return "DW_OP_breg3"; + case DW_OP_breg4: return "DW_OP_breg4"; + case DW_OP_breg5: return "DW_OP_breg5"; + case DW_OP_breg6: return "DW_OP_breg6"; + case DW_OP_breg7: return "DW_OP_breg7"; + case DW_OP_breg8: return "DW_OP_breg8"; + case DW_OP_breg9: return "DW_OP_breg9"; + case DW_OP_breg10: return "DW_OP_breg10"; + case DW_OP_breg11: return "DW_OP_breg11"; + case DW_OP_breg12: return "DW_OP_breg12"; + case DW_OP_breg13: return "DW_OP_breg13"; + case DW_OP_breg14: return "DW_OP_breg14"; + case DW_OP_breg15: return "DW_OP_breg15"; + case DW_OP_breg16: return "DW_OP_breg16"; + case DW_OP_breg17: return "DW_OP_breg17"; + case DW_OP_breg18: return "DW_OP_breg18"; + case DW_OP_breg19: return "DW_OP_breg19"; + case DW_OP_breg20: return "DW_OP_breg20"; + case DW_OP_breg21: return "DW_OP_breg21"; + case DW_OP_breg22: return "DW_OP_breg22"; + case DW_OP_breg23: return "DW_OP_breg23"; + case DW_OP_breg24: return "DW_OP_breg24"; + case DW_OP_breg25: return "DW_OP_breg25"; + case DW_OP_breg26: return "DW_OP_breg26"; + case DW_OP_breg27: return "DW_OP_breg27"; + case DW_OP_breg28: return "DW_OP_breg28"; + case DW_OP_breg29: return "DW_OP_breg29"; + case DW_OP_breg30: return "DW_OP_breg30"; + case DW_OP_breg31: return "DW_OP_breg31"; + case DW_OP_regx: return "DW_OP_regx"; + case DW_OP_fbreg: return "DW_OP_fbreg"; + case DW_OP_bregx: return "DW_OP_bregx"; + case DW_OP_piece: return "DW_OP_piece"; + case DW_OP_deref_size: return "DW_OP_deref_size"; + case DW_OP_xderef_size: return "DW_OP_xderef_size"; + case DW_OP_nop: return "DW_OP_nop"; + case DW_OP_push_object_address: return "DW_OP_push_object_address"; + case DW_OP_call2: return "DW_OP_call2"; + case DW_OP_call4: return "DW_OP_call4"; + case DW_OP_call_ref: return "DW_OP_call_ref"; + case DW_OP_form_tls_address: return "DW_OP_form_tls_address"; + case DW_OP_call_frame_cfa: return "DW_OP_call_frame_cfa"; + case DW_OP_lo_user: return "DW_OP_lo_user"; + case DW_OP_hi_user: return "DW_OP_hi_user"; + } + return 0; +} + +/// AttributeEncodingString - Return the string for the specified attribute +/// encoding. +const char *llvm::dwarf::AttributeEncodingString(unsigned Encoding) { + switch (Encoding) { + case DW_ATE_address: return "DW_ATE_address"; + case DW_ATE_boolean: return "DW_ATE_boolean"; + case DW_ATE_complex_float: return "DW_ATE_complex_float"; + case DW_ATE_float: return "DW_ATE_float"; + case DW_ATE_signed: return "DW_ATE_signed"; + case DW_ATE_signed_char: return "DW_ATE_signed_char"; + case DW_ATE_unsigned: return "DW_ATE_unsigned"; + case DW_ATE_unsigned_char: return "DW_ATE_unsigned_char"; + case DW_ATE_imaginary_float: return "DW_ATE_imaginary_float"; + case DW_ATE_packed_decimal: return "DW_ATE_packed_decimal"; + case DW_ATE_numeric_string: return "DW_ATE_numeric_string"; + case DW_ATE_edited: return "DW_ATE_edited"; + case DW_ATE_signed_fixed: return "DW_ATE_signed_fixed"; + case DW_ATE_unsigned_fixed: return "DW_ATE_unsigned_fixed"; + case DW_ATE_decimal_float: return "DW_ATE_decimal_float"; + case DW_ATE_lo_user: return "DW_ATE_lo_user"; + case DW_ATE_hi_user: return "DW_ATE_hi_user"; + } + return 0; +} + +/// DecimalSignString - Return the string for the specified decimal sign +/// attribute. +const char *llvm::dwarf::DecimalSignString(unsigned Sign) { + switch (Sign) { + case DW_DS_unsigned: return "DW_DS_unsigned"; + case DW_DS_leading_overpunch: return "DW_DS_leading_overpunch"; + case DW_DS_trailing_overpunch: return "DW_DS_trailing_overpunch"; + case DW_DS_leading_separate: return "DW_DS_leading_separate"; + case DW_DS_trailing_separate: return "DW_DS_trailing_separate"; + } + return 0; +} + +/// EndianityString - Return the string for the specified endianity. +/// +const char *llvm::dwarf::EndianityString(unsigned Endian) { + switch (Endian) { + case DW_END_default: return "DW_END_default"; + case DW_END_big: return "DW_END_big"; + case DW_END_little: return "DW_END_little"; + case DW_END_lo_user: return "DW_END_lo_user"; + case DW_END_hi_user: return "DW_END_hi_user"; + } + return 0; +} + +/// AccessibilityString - Return the string for the specified accessibility. +/// +const char *llvm::dwarf::AccessibilityString(unsigned Access) { + switch (Access) { + // Accessibility codes + case DW_ACCESS_public: return "DW_ACCESS_public"; + case DW_ACCESS_protected: return "DW_ACCESS_protected"; + case DW_ACCESS_private: return "DW_ACCESS_private"; + } + return 0; +} + +/// VisibilityString - Return the string for the specified visibility. +/// +const char *llvm::dwarf::VisibilityString(unsigned Visibility) { + switch (Visibility) { + case DW_VIS_local: return "DW_VIS_local"; + case DW_VIS_exported: return "DW_VIS_exported"; + case DW_VIS_qualified: return "DW_VIS_qualified"; + } + return 0; +} + +/// VirtualityString - Return the string for the specified virtuality. +/// +const char *llvm::dwarf::VirtualityString(unsigned Virtuality) { + switch (Virtuality) { + case DW_VIRTUALITY_none: return "DW_VIRTUALITY_none"; + case DW_VIRTUALITY_virtual: return "DW_VIRTUALITY_virtual"; + case DW_VIRTUALITY_pure_virtual: return "DW_VIRTUALITY_pure_virtual"; + } + return 0; +} + +/// LanguageString - Return the string for the specified language. +/// +const char *llvm::dwarf::LanguageString(unsigned Language) { + switch (Language) { + case DW_LANG_C89: return "DW_LANG_C89"; + case DW_LANG_C: return "DW_LANG_C"; + case DW_LANG_Ada83: return "DW_LANG_Ada83"; + case DW_LANG_C_plus_plus: return "DW_LANG_C_plus_plus"; + case DW_LANG_Cobol74: return "DW_LANG_Cobol74"; + case DW_LANG_Cobol85: return "DW_LANG_Cobol85"; + case DW_LANG_Fortran77: return "DW_LANG_Fortran77"; + case DW_LANG_Fortran90: return "DW_LANG_Fortran90"; + case DW_LANG_Pascal83: return "DW_LANG_Pascal83"; + case DW_LANG_Modula2: return "DW_LANG_Modula2"; + case DW_LANG_Java: return "DW_LANG_Java"; + case DW_LANG_C99: return "DW_LANG_C99"; + case DW_LANG_Ada95: return "DW_LANG_Ada95"; + case DW_LANG_Fortran95: return "DW_LANG_Fortran95"; + case DW_LANG_PLI: return "DW_LANG_PLI"; + case DW_LANG_ObjC: return "DW_LANG_ObjC"; + case DW_LANG_ObjC_plus_plus: return "DW_LANG_ObjC_plus_plus"; + case DW_LANG_UPC: return "DW_LANG_UPC"; + case DW_LANG_D: return "DW_LANG_D"; + case DW_LANG_lo_user: return "DW_LANG_lo_user"; + case DW_LANG_hi_user: return "DW_LANG_hi_user"; + } + return 0; +} + +/// CaseString - Return the string for the specified identifier case. +/// +const char *llvm::dwarf::CaseString(unsigned Case) { + switch (Case) { + case DW_ID_case_sensitive: return "DW_ID_case_sensitive"; + case DW_ID_up_case: return "DW_ID_up_case"; + case DW_ID_down_case: return "DW_ID_down_case"; + case DW_ID_case_insensitive: return "DW_ID_case_insensitive"; + } + return 0; +} + +/// ConventionString - Return the string for the specified calling convention. +/// +const char *llvm::dwarf::ConventionString(unsigned Convention) { + switch (Convention) { + case DW_CC_normal: return "DW_CC_normal"; + case DW_CC_program: return "DW_CC_program"; + case DW_CC_nocall: return "DW_CC_nocall"; + case DW_CC_lo_user: return "DW_CC_lo_user"; + case DW_CC_hi_user: return "DW_CC_hi_user"; + } + return 0; +} + +/// InlineCodeString - Return the string for the specified inline code. +/// +const char *llvm::dwarf::InlineCodeString(unsigned Code) { + switch (Code) { + case DW_INL_not_inlined: return "DW_INL_not_inlined"; + case DW_INL_inlined: return "DW_INL_inlined"; + case DW_INL_declared_not_inlined: return "DW_INL_declared_not_inlined"; + case DW_INL_declared_inlined: return "DW_INL_declared_inlined"; + } + return 0; +} + +/// ArrayOrderString - Return the string for the specified array order. +/// +const char *llvm::dwarf::ArrayOrderString(unsigned Order) { + switch (Order) { + case DW_ORD_row_major: return "DW_ORD_row_major"; + case DW_ORD_col_major: return "DW_ORD_col_major"; + } + return 0; +} + +/// DiscriminantString - Return the string for the specified discriminant +/// descriptor. +const char *llvm::dwarf::DiscriminantString(unsigned Discriminant) { + switch (Discriminant) { + case DW_DSC_label: return "DW_DSC_label"; + case DW_DSC_range: return "DW_DSC_range"; + } + return 0; +} + +/// LNStandardString - Return the string for the specified line number standard. +/// +const char *llvm::dwarf::LNStandardString(unsigned Standard) { + switch (Standard) { + case DW_LNS_copy: return "DW_LNS_copy"; + case DW_LNS_advance_pc: return "DW_LNS_advance_pc"; + case DW_LNS_advance_line: return "DW_LNS_advance_line"; + case DW_LNS_set_file: return "DW_LNS_set_file"; + case DW_LNS_set_column: return "DW_LNS_set_column"; + case DW_LNS_negate_stmt: return "DW_LNS_negate_stmt"; + case DW_LNS_set_basic_block: return "DW_LNS_set_basic_block"; + case DW_LNS_const_add_pc: return "DW_LNS_const_add_pc"; + case DW_LNS_fixed_advance_pc: return "DW_LNS_fixed_advance_pc"; + case DW_LNS_set_prologue_end: return "DW_LNS_set_prologue_end"; + case DW_LNS_set_epilogue_begin: return "DW_LNS_set_epilogue_begin"; + case DW_LNS_set_isa: return "DW_LNS_set_isa"; + } + return 0; +} + +/// LNExtendedString - Return the string for the specified line number extended +/// opcode encodings. +const char *llvm::dwarf::LNExtendedString(unsigned Encoding) { + switch (Encoding) { + // Line Number Extended Opcode Encodings + case DW_LNE_end_sequence: return "DW_LNE_end_sequence"; + case DW_LNE_set_address: return "DW_LNE_set_address"; + case DW_LNE_define_file: return "DW_LNE_define_file"; + case DW_LNE_lo_user: return "DW_LNE_lo_user"; + case DW_LNE_hi_user: return "DW_LNE_hi_user"; + } + return 0; +} + +/// MacinfoString - Return the string for the specified macinfo type encodings. +/// +const char *llvm::dwarf::MacinfoString(unsigned Encoding) { + switch (Encoding) { + // Macinfo Type Encodings + case DW_MACINFO_define: return "DW_MACINFO_define"; + case DW_MACINFO_undef: return "DW_MACINFO_undef"; + case DW_MACINFO_start_file: return "DW_MACINFO_start_file"; + case DW_MACINFO_end_file: return "DW_MACINFO_end_file"; + case DW_MACINFO_vendor_ext: return "DW_MACINFO_vendor_ext"; + } + return 0; +} + +/// CallFrameString - Return the string for the specified call frame instruction +/// encodings. +const char *llvm::dwarf::CallFrameString(unsigned Encoding) { + switch (Encoding) { + case DW_CFA_advance_loc: return "DW_CFA_advance_loc"; + case DW_CFA_offset: return "DW_CFA_offset"; + case DW_CFA_restore: return "DW_CFA_restore"; + case DW_CFA_set_loc: return "DW_CFA_set_loc"; + case DW_CFA_advance_loc1: return "DW_CFA_advance_loc1"; + case DW_CFA_advance_loc2: return "DW_CFA_advance_loc2"; + case DW_CFA_advance_loc4: return "DW_CFA_advance_loc4"; + case DW_CFA_offset_extended: return "DW_CFA_offset_extended"; + case DW_CFA_restore_extended: return "DW_CFA_restore_extended"; + case DW_CFA_undefined: return "DW_CFA_undefined"; + case DW_CFA_same_value: return "DW_CFA_same_value"; + case DW_CFA_register: return "DW_CFA_register"; + case DW_CFA_remember_state: return "DW_CFA_remember_state"; + case DW_CFA_restore_state: return "DW_CFA_restore_state"; + case DW_CFA_def_cfa: return "DW_CFA_def_cfa"; + case DW_CFA_def_cfa_register: return "DW_CFA_def_cfa_register"; + case DW_CFA_def_cfa_offset: return "DW_CFA_def_cfa_offset"; + case DW_CFA_def_cfa_expression: return "DW_CFA_def_cfa_expression"; + case DW_CFA_expression: return "DW_CFA_expression"; + case DW_CFA_offset_extended_sf: return "DW_CFA_offset_extended_sf"; + case DW_CFA_def_cfa_sf: return "DW_CFA_def_cfa_sf"; + case DW_CFA_def_cfa_offset_sf: return "DW_CFA_def_cfa_offset_sf"; + case DW_CFA_val_offset: return "DW_CFA_val_offset"; + case DW_CFA_val_offset_sf: return "DW_CFA_val_offset_sf"; + case DW_CFA_val_expression: return "DW_CFA_val_expression"; + case DW_CFA_lo_user: return "DW_CFA_lo_user"; + case DW_CFA_hi_user: return "DW_CFA_hi_user"; + } + return 0; +} diff --git a/final/lib/Support/DynamicLibrary.cpp b/final/lib/Support/DynamicLibrary.cpp new file mode 100644 index 00000000000..455c3801cc6 --- /dev/null +++ b/final/lib/Support/DynamicLibrary.cpp @@ -0,0 +1,170 @@ +//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system DynamicLibrary concept. +// +// FIXME: This file leaks the ExplicitSymbols and OpenedHandles vector, and is +// not thread safe! +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Config/config.h" +#include +#include +#include +#include + +// Collection of symbol name/value pairs to be searched prior to any libraries. +static std::map *ExplicitSymbols = 0; + +namespace { + +struct ExplicitSymbolsDeleter { + ~ExplicitSymbolsDeleter() { + if (ExplicitSymbols) + delete ExplicitSymbols; + } +}; + +} + +static ExplicitSymbolsDeleter Dummy; + +void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName, + void *symbolValue) { + if (ExplicitSymbols == 0) + ExplicitSymbols = new std::map(); + (*ExplicitSymbols)[symbolName] = symbolValue; +} + +#ifdef LLVM_ON_WIN32 + +#include "Windows/DynamicLibrary.inc" + +#else + +#if HAVE_DLFCN_H +#include +using namespace llvm; +using namespace llvm::sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +static std::vector *OpenedHandles = 0; + + +static SmartMutex& getMutex() { + static SmartMutex HandlesMutex; + return HandlesMutex; +} + + +bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, + std::string *ErrMsg) { + void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL); + if (H == 0) { + if (ErrMsg) *ErrMsg = dlerror(); + return true; + } +#ifdef __CYGWIN__ + // Cygwin searches symbols only in the main + // with the handle of dlopen(NULL, RTLD_GLOBAL). + if (Filename == NULL) + H = RTLD_DEFAULT; +#endif + SmartScopedLock Lock(getMutex()); + if (OpenedHandles == 0) + OpenedHandles = new std::vector(); + OpenedHandles->push_back(H); + return false; +} +#else + +using namespace llvm; +using namespace llvm::sys; + +bool DynamicLibrary::LoadLibraryPermanently(const char *Filename, + std::string *ErrMsg) { + if (ErrMsg) *ErrMsg = "dlopen() not supported on this platform"; + return true; +} +#endif + +namespace llvm { +void *SearchForAddressOfSpecialSymbol(const char* symbolName); +} + +void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { + // First check symbols added via AddSymbol(). + if (ExplicitSymbols) { + std::map::iterator I = + ExplicitSymbols->find(symbolName); + std::map::iterator E = ExplicitSymbols->end(); + + if (I != E) + return I->second; + } + +#if HAVE_DLFCN_H + // Now search the libraries. + SmartScopedLock Lock(getMutex()); + if (OpenedHandles) { + for (std::vector::iterator I = OpenedHandles->begin(), + E = OpenedHandles->end(); I != E; ++I) { + //lt_ptr ptr = lt_dlsym(*I, symbolName); + void *ptr = dlsym(*I, symbolName); + if (ptr) { + return ptr; + } + } + } +#endif + + if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName)) + return Result; + +// This macro returns the address of a well-known, explicit symbol +#define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) return &SYM + +// On linux we have a weird situation. The stderr/out/in symbols are both +// macros and global variables because of standards requirements. So, we +// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first. +#if defined(__linux__) + { + EXPLICIT_SYMBOL(stderr); + EXPLICIT_SYMBOL(stdout); + EXPLICIT_SYMBOL(stdin); + } +#else + // For everything else, we want to check to make sure the symbol isn't defined + // as a macro before using EXPLICIT_SYMBOL. + { +#ifndef stdin + EXPLICIT_SYMBOL(stdin); +#endif +#ifndef stdout + EXPLICIT_SYMBOL(stdout); +#endif +#ifndef stderr + EXPLICIT_SYMBOL(stderr); +#endif + } +#endif +#undef EXPLICIT_SYMBOL + + return 0; +} + +#endif // LLVM_ON_WIN32 diff --git a/final/lib/Support/Errno.cpp b/final/lib/Support/Errno.cpp new file mode 100644 index 00000000000..18c658173a7 --- /dev/null +++ b/final/lib/Support/Errno.cpp @@ -0,0 +1,74 @@ +//===- Errno.cpp - errno support --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the errno wrappers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Errno.h" +#include "llvm/Config/config.h" // Get autoconf configuration settings + +#if HAVE_STRING_H +#include + +#if HAVE_ERRNO_H +#include +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +namespace llvm { +namespace sys { + +#if HAVE_ERRNO_H +std::string StrError() { + return StrError(errno); +} +#endif // HAVE_ERRNO_H + +std::string StrError(int errnum) { + const int MaxErrStrLen = 2000; + char buffer[MaxErrStrLen]; + buffer[0] = '\0'; + char* str = buffer; +#ifdef HAVE_STRERROR_R + // strerror_r is thread-safe. + if (errnum) +# if defined(__GLIBC__) && defined(_GNU_SOURCE) + // glibc defines its own incompatible version of strerror_r + // which may not use the buffer supplied. + str = strerror_r(errnum,buffer,MaxErrStrLen-1); +# else + strerror_r(errnum,buffer,MaxErrStrLen-1); +# endif +#elif HAVE_DECL_STRERROR_S // "Windows Secure API" + if (errnum) + strerror_s(buffer, errnum); +#elif defined(HAVE_STRERROR) + // Copy the thread un-safe result of strerror into + // the buffer as fast as possible to minimize impact + // of collision of strerror in multiple threads. + if (errnum) + strncpy(buffer,strerror(errnum),MaxErrStrLen-1); + buffer[MaxErrStrLen-1] = '\0'; +#else + // Strange that this system doesn't even have strerror + // but, oh well, just use a generic message + sprintf(buffer, "Error #%d", errnum); +#endif + return str; +} + +} // namespace sys +} // namespace llvm + +#endif // HAVE_STRING_H diff --git a/final/lib/Support/ErrorHandling.cpp b/final/lib/Support/ErrorHandling.cpp new file mode 100644 index 00000000000..3579546d757 --- /dev/null +++ b/final/lib/Support/ErrorHandling.cpp @@ -0,0 +1,100 @@ +//===- lib/Support/ErrorHandling.cpp - Callbacks for errors ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to indicate fatal error conditions. Non-fatal +// errors (most of them) should be handled through LLVMContext. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/Threading.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Config/config.h" +#include +#include + +#if defined(HAVE_UNISTD_H) +# include +#endif +#if defined(_MSC_VER) +# include +# include +#endif + +using namespace llvm; +using namespace std; + +static fatal_error_handler_t ErrorHandler = 0; +static void *ErrorHandlerUserData = 0; + +void llvm::install_fatal_error_handler(fatal_error_handler_t handler, + void *user_data) { + assert(!llvm_is_multithreaded() && + "Cannot register error handlers after starting multithreaded mode!\n"); + assert(!ErrorHandler && "Error handler already registered!\n"); + ErrorHandler = handler; + ErrorHandlerUserData = user_data; +} + +void llvm::remove_fatal_error_handler() { + ErrorHandler = 0; +} + +void llvm::report_fatal_error(const char *Reason) { + report_fatal_error(Twine(Reason)); +} + +void llvm::report_fatal_error(const std::string &Reason) { + report_fatal_error(Twine(Reason)); +} + +void llvm::report_fatal_error(StringRef Reason) { + report_fatal_error(Twine(Reason)); +} + +void llvm::report_fatal_error(const Twine &Reason) { + if (ErrorHandler) { + ErrorHandler(ErrorHandlerUserData, Reason.str()); + } else { + // Blast the result out to stderr. We don't try hard to make sure this + // succeeds (e.g. handling EINTR) and we can't use errs() here because + // raw ostreams can call report_fatal_error. + SmallVector Buffer; + raw_svector_ostream OS(Buffer); + OS << "LLVM ERROR: " << Reason << "\n"; + StringRef MessageStr = OS.str(); + ssize_t written = ::write(2, MessageStr.data(), MessageStr.size()); + (void)written; // If something went wrong, we deliberately just give up. + } + + // If we reached here, we are failing ungracefully. Run the interrupt handlers + // to make sure any special cleanups get done, in particular that we remove + // files registered with RemoveFileOnSignal. + sys::RunInterruptHandlers(); + + exit(1); +} + +void llvm::llvm_unreachable_internal(const char *msg, const char *file, + unsigned line) { + // This code intentionally doesn't call the ErrorHandler callback, because + // llvm_unreachable is intended to be used to indicate "impossible" + // situations, and not legitimate runtime errors. + if (msg) + dbgs() << msg << "\n"; + dbgs() << "UNREACHABLE executed"; + if (file) + dbgs() << " at " << file << ":" << line; + dbgs() << "!\n"; + abort(); +} diff --git a/final/lib/Support/FileUtilities.cpp b/final/lib/Support/FileUtilities.cpp new file mode 100644 index 00000000000..5dbabee7a7e --- /dev/null +++ b/final/lib/Support/FileUtilities.cpp @@ -0,0 +1,281 @@ +//===- Support/FileUtilities.cpp - File System Utilities ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/system_error.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include +#include +#include +using namespace llvm; + +static bool isSignedChar(char C) { + return (C == '+' || C == '-'); +} + +static bool isExponentChar(char C) { + switch (C) { + case 'D': // Strange exponential notation. + case 'd': // Strange exponential notation. + case 'e': + case 'E': return true; + default: return false; + } +} + +static bool isNumberChar(char C) { + switch (C) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '.': return true; + default: return isSignedChar(C) || isExponentChar(C); + } +} + +static const char *BackupNumber(const char *Pos, const char *FirstChar) { + // If we didn't stop in the middle of a number, don't backup. + if (!isNumberChar(*Pos)) return Pos; + + // Otherwise, return to the start of the number. + bool HasPeriod = false; + while (Pos > FirstChar && isNumberChar(Pos[-1])) { + // Backup over at most one period. + if (Pos[-1] == '.') { + if (HasPeriod) + break; + HasPeriod = true; + } + + --Pos; + if (Pos > FirstChar && isSignedChar(Pos[0]) && !isExponentChar(Pos[-1])) + break; + } + return Pos; +} + +/// EndOfNumber - Return the first character that is not part of the specified +/// number. This assumes that the buffer is null terminated, so it won't fall +/// off the end. +static const char *EndOfNumber(const char *Pos) { + while (isNumberChar(*Pos)) + ++Pos; + return Pos; +} + +/// CompareNumbers - compare two numbers, returning true if they are different. +static bool CompareNumbers(const char *&F1P, const char *&F2P, + const char *F1End, const char *F2End, + double AbsTolerance, double RelTolerance, + std::string *ErrorMsg) { + const char *F1NumEnd, *F2NumEnd; + double V1 = 0.0, V2 = 0.0; + + // If one of the positions is at a space and the other isn't, chomp up 'til + // the end of the space. + while (isspace(*F1P) && F1P != F1End) + ++F1P; + while (isspace(*F2P) && F2P != F2End) + ++F2P; + + // If we stop on numbers, compare their difference. + if (!isNumberChar(*F1P) || !isNumberChar(*F2P)) { + // The diff failed. + F1NumEnd = F1P; + F2NumEnd = F2P; + } else { + // Note that some ugliness is built into this to permit support for numbers + // that use "D" or "d" as their exponential marker, e.g. "1.234D45". This + // occurs in 200.sixtrack in spec2k. + V1 = strtod(F1P, const_cast(&F1NumEnd)); + V2 = strtod(F2P, const_cast(&F2NumEnd)); + + if (*F1NumEnd == 'D' || *F1NumEnd == 'd') { + // Copy string into tmp buffer to replace the 'D' with an 'e'. + SmallString<200> StrTmp(F1P, EndOfNumber(F1NumEnd)+1); + // Strange exponential notation! + StrTmp[static_cast(F1NumEnd-F1P)] = 'e'; + + V1 = strtod(&StrTmp[0], const_cast(&F1NumEnd)); + F1NumEnd = F1P + (F1NumEnd-&StrTmp[0]); + } + + if (*F2NumEnd == 'D' || *F2NumEnd == 'd') { + // Copy string into tmp buffer to replace the 'D' with an 'e'. + SmallString<200> StrTmp(F2P, EndOfNumber(F2NumEnd)+1); + // Strange exponential notation! + StrTmp[static_cast(F2NumEnd-F2P)] = 'e'; + + V2 = strtod(&StrTmp[0], const_cast(&F2NumEnd)); + F2NumEnd = F2P + (F2NumEnd-&StrTmp[0]); + } + } + + if (F1NumEnd == F1P || F2NumEnd == F2P) { + if (ErrorMsg) { + *ErrorMsg = "FP Comparison failed, not a numeric difference between '"; + *ErrorMsg += F1P[0]; + *ErrorMsg += "' and '"; + *ErrorMsg += F2P[0]; + *ErrorMsg += "'"; + } + return true; + } + + // Check to see if these are inside the absolute tolerance + if (AbsTolerance < std::abs(V1-V2)) { + // Nope, check the relative tolerance... + double Diff; + if (V2) + Diff = std::abs(V1/V2 - 1.0); + else if (V1) + Diff = std::abs(V2/V1 - 1.0); + else + Diff = 0; // Both zero. + if (Diff > RelTolerance) { + if (ErrorMsg) { + raw_string_ostream(*ErrorMsg) + << "Compared: " << V1 << " and " << V2 << '\n' + << "abs. diff = " << std::abs(V1-V2) << " rel.diff = " << Diff << '\n' + << "Out of tolerance: rel/abs: " << RelTolerance << '/' + << AbsTolerance; + } + return true; + } + } + + // Otherwise, advance our read pointers to the end of the numbers. + F1P = F1NumEnd; F2P = F2NumEnd; + return false; +} + +/// DiffFilesWithTolerance - Compare the two files specified, returning 0 if the +/// files match, 1 if they are different, and 2 if there is a file error. This +/// function differs from DiffFiles in that you can specify an absolete and +/// relative FP error that is allowed to exist. If you specify a string to fill +/// in for the error option, it will set the string to an error message if an +/// error occurs, allowing the caller to distinguish between a failed diff and a +/// file system error. +/// +int llvm::DiffFilesWithTolerance(const sys::PathWithStatus &FileA, + const sys::PathWithStatus &FileB, + double AbsTol, double RelTol, + std::string *Error) { + const sys::FileStatus *FileAStat = FileA.getFileStatus(false, Error); + if (!FileAStat) + return 2; + const sys::FileStatus *FileBStat = FileB.getFileStatus(false, Error); + if (!FileBStat) + return 2; + + // Check for zero length files because some systems croak when you try to + // mmap an empty file. + size_t A_size = FileAStat->getSize(); + size_t B_size = FileBStat->getSize(); + + // If they are both zero sized then they're the same + if (A_size == 0 && B_size == 0) + return 0; + + // If only one of them is zero sized then they can't be the same + if ((A_size == 0 || B_size == 0)) { + if (Error) + *Error = "Files differ: one is zero-sized, the other isn't"; + return 1; + } + + // Now its safe to mmap the files into memory becasue both files + // have a non-zero size. + error_code ec; + OwningPtr F1; + if (error_code ec = MemoryBuffer::getFile(FileA.c_str(), F1)) { + if (Error) + *Error = ec.message(); + return 2; + } + OwningPtr F2; + if (error_code ec = MemoryBuffer::getFile(FileB.c_str(), F2)) { + if (Error) + *Error = ec.message(); + return 2; + } + + // Okay, now that we opened the files, scan them for the first difference. + const char *File1Start = F1->getBufferStart(); + const char *File2Start = F2->getBufferStart(); + const char *File1End = F1->getBufferEnd(); + const char *File2End = F2->getBufferEnd(); + const char *F1P = File1Start; + const char *F2P = File2Start; + + // Are the buffers identical? Common case: Handle this efficiently. + if (A_size == B_size && + std::memcmp(File1Start, File2Start, A_size) == 0) + return 0; + + // Otherwise, we are done a tolerances are set. + if (AbsTol == 0 && RelTol == 0) { + if (Error) + *Error = "Files differ without tolerance allowance"; + return 1; // Files different! + } + + bool CompareFailed = false; + while (1) { + // Scan for the end of file or next difference. + while (F1P < File1End && F2P < File2End && *F1P == *F2P) + ++F1P, ++F2P; + + if (F1P >= File1End || F2P >= File2End) break; + + // Okay, we must have found a difference. Backup to the start of the + // current number each stream is at so that we can compare from the + // beginning. + F1P = BackupNumber(F1P, File1Start); + F2P = BackupNumber(F2P, File2Start); + + // Now that we are at the start of the numbers, compare them, exiting if + // they don't match. + if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) { + CompareFailed = true; + break; + } + } + + // Okay, we reached the end of file. If both files are at the end, we + // succeeded. + bool F1AtEnd = F1P >= File1End; + bool F2AtEnd = F2P >= File2End; + if (!CompareFailed && (!F1AtEnd || !F2AtEnd)) { + // Else, we might have run off the end due to a number: backup and retry. + if (F1AtEnd && isNumberChar(F1P[-1])) --F1P; + if (F2AtEnd && isNumberChar(F2P[-1])) --F2P; + F1P = BackupNumber(F1P, File1Start); + F2P = BackupNumber(F2P, File2Start); + + // Now that we are at the start of the numbers, compare them, exiting if + // they don't match. + if (CompareNumbers(F1P, F2P, File1End, File2End, AbsTol, RelTol, Error)) + CompareFailed = true; + + // If we found the end, we succeeded. + if (F1P < File1End || F2P < File2End) + CompareFailed = true; + } + + return CompareFailed; +} diff --git a/final/lib/Support/FoldingSet.cpp b/final/lib/Support/FoldingSet.cpp new file mode 100644 index 00000000000..a4f80a90d6d --- /dev/null +++ b/final/lib/Support/FoldingSet.cpp @@ -0,0 +1,421 @@ +//===-- Support/FoldingSet.cpp - Uniquing Hash Set --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a hash set that can be used to remove duplication of +// nodes in a graph. This code was originally created by Chris Lattner for use +// with SelectionDAGCSEMap, but was isolated to provide use across the llvm code +// set. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Host.h" +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// FoldingSetNodeIDRef Implementation + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, +/// used to lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeIDRef::ComputeHash() const { + // This is adapted from SuperFastHash by Paul Hsieh. + unsigned Hash = static_cast(Size); + for (const unsigned *BP = Data, *E = BP+Size; BP != E; ++BP) { + unsigned Data = *BP; + Hash += Data & 0xFFFF; + unsigned Tmp = ((Data >> 16) << 11) ^ Hash; + Hash = (Hash << 16) ^ Tmp; + Hash += Hash >> 11; + } + + // Force "avalanching" of final 127 bits. + Hash ^= Hash << 3; + Hash += Hash >> 5; + Hash ^= Hash << 4; + Hash += Hash >> 17; + Hash ^= Hash << 25; + Hash += Hash >> 6; + return Hash; +} + +bool FoldingSetNodeIDRef::operator==(FoldingSetNodeIDRef RHS) const { + if (Size != RHS.Size) return false; + return memcmp(Data, RHS.Data, Size*sizeof(*Data)) == 0; +} + +//===----------------------------------------------------------------------===// +// FoldingSetNodeID Implementation + +/// Add* - Add various data types to Bit data. +/// +void FoldingSetNodeID::AddPointer(const void *Ptr) { + // Note: this adds pointers to the hash using sizes and endianness that + // depend on the host. It doesn't matter however, because hashing on + // pointer values in inherently unstable. Nothing should depend on the + // ordering of nodes in the folding set. + intptr_t PtrI = (intptr_t)Ptr; + Bits.push_back(unsigned(PtrI)); + if (sizeof(intptr_t) > sizeof(unsigned)) + Bits.push_back(unsigned(uint64_t(PtrI) >> 32)); +} +void FoldingSetNodeID::AddInteger(signed I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(unsigned I) { + Bits.push_back(I); +} +void FoldingSetNodeID::AddInteger(long I) { + AddInteger((unsigned long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long I) { + if (sizeof(long) == sizeof(int)) + AddInteger(unsigned(I)); + else if (sizeof(long) == sizeof(long long)) { + AddInteger((unsigned long long)I); + } else { + llvm_unreachable("unexpected sizeof(long)"); + } +} +void FoldingSetNodeID::AddInteger(long long I) { + AddInteger((unsigned long long)I); +} +void FoldingSetNodeID::AddInteger(unsigned long long I) { + AddInteger(unsigned(I)); + if ((uint64_t)(int)I != I) + Bits.push_back(unsigned(I >> 32)); +} + +void FoldingSetNodeID::AddString(StringRef String) { + unsigned Size = String.size(); + Bits.push_back(Size); + if (!Size) return; + + unsigned Units = Size / 4; + unsigned Pos = 0; + const unsigned *Base = (const unsigned*) String.data(); + + // If the string is aligned do a bulk transfer. + if (!((intptr_t)Base & 3)) { + Bits.append(Base, Base + Units); + Pos = (Units + 1) * 4; + } else { + // Otherwise do it the hard way. + // To be compatible with above bulk transfer, we need to take endianness + // into account. + if (sys::isBigEndianHost()) { + for (Pos += 4; Pos <= Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 4] << 24) | + ((unsigned char)String[Pos - 3] << 16) | + ((unsigned char)String[Pos - 2] << 8) | + (unsigned char)String[Pos - 1]; + Bits.push_back(V); + } + } else { + assert(sys::isLittleEndianHost() && "Unexpected host endianness"); + for (Pos += 4; Pos <= Size; Pos += 4) { + unsigned V = ((unsigned char)String[Pos - 1] << 24) | + ((unsigned char)String[Pos - 2] << 16) | + ((unsigned char)String[Pos - 3] << 8) | + (unsigned char)String[Pos - 4]; + Bits.push_back(V); + } + } + } + + // With the leftover bits. + unsigned V = 0; + // Pos will have overshot size by 4 - #bytes left over. + // No need to take endianness into account here - this is always executed. + switch (Pos - Size) { + case 1: V = (V << 8) | (unsigned char)String[Size - 3]; // Fall thru. + case 2: V = (V << 8) | (unsigned char)String[Size - 2]; // Fall thru. + case 3: V = (V << 8) | (unsigned char)String[Size - 1]; break; + default: return; // Nothing left. + } + + Bits.push_back(V); +} + +/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to +/// lookup the node in the FoldingSetImpl. +unsigned FoldingSetNodeID::ComputeHash() const { + return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash(); +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{ + return *this == FoldingSetNodeIDRef(RHS.Bits.data(), RHS.Bits.size()); +} + +/// operator== - Used to compare two nodes to each other. +/// +bool FoldingSetNodeID::operator==(FoldingSetNodeIDRef RHS) const { + return FoldingSetNodeIDRef(Bits.data(), Bits.size()) == RHS; +} + +/// Intern - Copy this node's data to a memory region allocated from the +/// given allocator and return a FoldingSetNodeIDRef describing the +/// interned data. +FoldingSetNodeIDRef +FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const { + unsigned *New = Allocator.Allocate(Bits.size()); + std::uninitialized_copy(Bits.begin(), Bits.end(), New); + return FoldingSetNodeIDRef(New, Bits.size()); +} + +//===----------------------------------------------------------------------===// +/// Helper functions for FoldingSetImpl. + +/// GetNextPtr - In order to save space, each bucket is a +/// singly-linked-list. In order to make deletion more efficient, we make +/// the list circular, so we can delete a node without computing its hash. +/// The problem with this is that the start of the hash buckets are not +/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null: +/// use GetBucketPtr when this happens. +static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) { + // The low bit is set if this is the pointer back to the bucket. + if (reinterpret_cast(NextInBucketPtr) & 1) + return 0; + + return static_cast(NextInBucketPtr); +} + + +/// testing. +static void **GetBucketPtr(void *NextInBucketPtr) { + intptr_t Ptr = reinterpret_cast(NextInBucketPtr); + assert((Ptr & 1) && "Not a bucket pointer"); + return reinterpret_cast(Ptr & ~intptr_t(1)); +} + +/// GetBucketFor - Hash the specified node ID and return the hash bucket for +/// the specified ID. +static void **GetBucketFor(unsigned Hash, void **Buckets, unsigned NumBuckets) { + // NumBuckets is always a power of 2. + unsigned BucketNum = Hash & (NumBuckets-1); + return Buckets + BucketNum; +} + +/// AllocateBuckets - Allocated initialized bucket memory. +static void **AllocateBuckets(unsigned NumBuckets) { + void **Buckets = static_cast(calloc(NumBuckets+1, sizeof(void*))); + // Set the very last bucket to be a non-null "pointer". + Buckets[NumBuckets] = reinterpret_cast(-1); + return Buckets; +} + +//===----------------------------------------------------------------------===// +// FoldingSetImpl Implementation + +FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) { + assert(5 < Log2InitSize && Log2InitSize < 32 && + "Initial hash table size out of range"); + NumBuckets = 1 << Log2InitSize; + Buckets = AllocateBuckets(NumBuckets); + NumNodes = 0; +} +FoldingSetImpl::~FoldingSetImpl() { + free(Buckets); +} +void FoldingSetImpl::clear() { + // Set all but the last bucket to null pointers. + memset(Buckets, 0, NumBuckets*sizeof(void*)); + + // Set the very last bucket to be a non-null "pointer". + Buckets[NumBuckets] = reinterpret_cast(-1); + + // Reset the node count to zero. + NumNodes = 0; +} + +/// GrowHashTable - Double the size of the hash table and rehash everything. +/// +void FoldingSetImpl::GrowHashTable() { + void **OldBuckets = Buckets; + unsigned OldNumBuckets = NumBuckets; + NumBuckets <<= 1; + + // Clear out new buckets. + Buckets = AllocateBuckets(NumBuckets); + NumNodes = 0; + + // Walk the old buckets, rehashing nodes into their new place. + FoldingSetNodeID TempID; + for (unsigned i = 0; i != OldNumBuckets; ++i) { + void *Probe = OldBuckets[i]; + if (!Probe) continue; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + // Figure out the next link, remove NodeInBucket from the old link. + Probe = NodeInBucket->getNextInBucket(); + NodeInBucket->SetNextInBucket(0); + + // Insert the node into the new bucket, after recomputing the hash. + InsertNode(NodeInBucket, + GetBucketFor(ComputeNodeHash(NodeInBucket, TempID), + Buckets, NumBuckets)); + TempID.clear(); + } + } + + free(OldBuckets); +} + +/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, +/// return it. If not, return the insertion token that will make insertion +/// faster. +FoldingSetImpl::Node +*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID, + void *&InsertPos) { + + void **Bucket = GetBucketFor(ID.ComputeHash(), Buckets, NumBuckets); + void *Probe = *Bucket; + + InsertPos = 0; + + FoldingSetNodeID TempID; + while (Node *NodeInBucket = GetNextPtr(Probe)) { + if (NodeEquals(NodeInBucket, ID, TempID)) + return NodeInBucket; + TempID.clear(); + + Probe = NodeInBucket->getNextInBucket(); + } + + // Didn't find the node, return null with the bucket as the InsertPos. + InsertPos = Bucket; + return 0; +} + +/// InsertNode - Insert the specified node into the folding set, knowing that it +/// is not already in the map. InsertPos must be obtained from +/// FindNodeOrInsertPos. +void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) { + assert(N->getNextInBucket() == 0); + // Do we need to grow the hashtable? + if (NumNodes+1 > NumBuckets*2) { + GrowHashTable(); + FoldingSetNodeID TempID; + InsertPos = GetBucketFor(ComputeNodeHash(N, TempID), Buckets, NumBuckets); + } + + ++NumNodes; + + /// The insert position is actually a bucket pointer. + void **Bucket = static_cast(InsertPos); + + void *Next = *Bucket; + + // If this is the first insertion into this bucket, its next pointer will be + // null. Pretend as if it pointed to itself, setting the low bit to indicate + // that it is a pointer to the bucket. + if (Next == 0) + Next = reinterpret_cast(reinterpret_cast(Bucket)|1); + + // Set the node's next pointer, and make the bucket point to the node. + N->SetNextInBucket(Next); + *Bucket = N; +} + +/// RemoveNode - Remove a node from the folding set, returning true if one was +/// removed or false if the node was not in the folding set. +bool FoldingSetImpl::RemoveNode(Node *N) { + // Because each bucket is a circular list, we don't need to compute N's hash + // to remove it. + void *Ptr = N->getNextInBucket(); + if (Ptr == 0) return false; // Not in folding set. + + --NumNodes; + N->SetNextInBucket(0); + + // Remember what N originally pointed to, either a bucket or another node. + void *NodeNextPtr = Ptr; + + // Chase around the list until we find the node (or bucket) which points to N. + while (true) { + if (Node *NodeInBucket = GetNextPtr(Ptr)) { + // Advance pointer. + Ptr = NodeInBucket->getNextInBucket(); + + // We found a node that points to N, change it to point to N's next node, + // removing N from the list. + if (Ptr == N) { + NodeInBucket->SetNextInBucket(NodeNextPtr); + return true; + } + } else { + void **Bucket = GetBucketPtr(Ptr); + Ptr = *Bucket; + + // If we found that the bucket points to N, update the bucket to point to + // whatever is next. + if (Ptr == N) { + *Bucket = NodeNextPtr; + return true; + } + } + } +} + +/// GetOrInsertNode - If there is an existing simple Node exactly +/// equal to the specified node, return it. Otherwise, insert 'N' and it +/// instead. +FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) { + FoldingSetNodeID ID; + GetNodeProfile(N, ID); + void *IP; + if (Node *E = FindNodeOrInsertPos(ID, IP)) + return E; + InsertNode(N, IP); + return N; +} + +//===----------------------------------------------------------------------===// +// FoldingSetIteratorImpl Implementation + +FoldingSetIteratorImpl::FoldingSetIteratorImpl(void **Bucket) { + // Skip to the first non-null non-self-cycle bucket. + while (*Bucket != reinterpret_cast(-1) && + (*Bucket == 0 || GetNextPtr(*Bucket) == 0)) + ++Bucket; + + NodePtr = static_cast(*Bucket); +} + +void FoldingSetIteratorImpl::advance() { + // If there is another link within this bucket, go to it. + void *Probe = NodePtr->getNextInBucket(); + + if (FoldingSetNode *NextNodeInBucket = GetNextPtr(Probe)) + NodePtr = NextNodeInBucket; + else { + // Otherwise, this is the last link in this bucket. + void **Bucket = GetBucketPtr(Probe); + + // Skip to the next non-null non-self-cycle bucket. + do { + ++Bucket; + } while (*Bucket != reinterpret_cast(-1) && + (*Bucket == 0 || GetNextPtr(*Bucket) == 0)); + + NodePtr = static_cast(*Bucket); + } +} + +//===----------------------------------------------------------------------===// +// FoldingSetBucketIteratorImpl Implementation + +FoldingSetBucketIteratorImpl::FoldingSetBucketIteratorImpl(void **Bucket) { + Ptr = (*Bucket == 0 || GetNextPtr(*Bucket) == 0) ? (void*) Bucket : *Bucket; +} diff --git a/final/lib/Support/FormattedStream.cpp b/final/lib/Support/FormattedStream.cpp new file mode 100644 index 00000000000..231ae48759e --- /dev/null +++ b/final/lib/Support/FormattedStream.cpp @@ -0,0 +1,101 @@ +//===-- llvm/Support/FormattedStream.cpp - Formatted streams ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation of formatted_raw_ostream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include + +using namespace llvm; + +/// CountColumns - Examine the given char sequence and figure out which +/// column we end up in after output. +/// +static unsigned CountColumns(unsigned Column, const char *Ptr, size_t Size) { + // Keep track of the current column by scanning the string for + // special characters + + for (const char *End = Ptr + Size; Ptr != End; ++Ptr) { + ++Column; + if (*Ptr == '\n' || *Ptr == '\r') + Column = 0; + else if (*Ptr == '\t') + // Assumes tab stop = 8 characters. + Column += (8 - (Column & 0x7)) & 0x7; + } + + return Column; +} + +/// ComputeColumn - Examine the current output and figure out which +/// column we end up in after output. +void formatted_raw_ostream::ComputeColumn(const char *Ptr, size_t Size) { + // If our previous scan pointer is inside the buffer, assume we already + // scanned those bytes. This depends on raw_ostream to not change our buffer + // in unexpected ways. + if (Ptr <= Scanned && Scanned <= Ptr + Size) { + // Scan all characters added since our last scan to determine the new + // column. + ColumnScanned = CountColumns(ColumnScanned, Scanned, + Size - (Scanned - Ptr)); + } else + ColumnScanned = CountColumns(ColumnScanned, Ptr, Size); + + // Update the scanning pointer. + Scanned = Ptr + Size; +} + +/// PadToColumn - Align the output to some column number. +/// +/// \param NewCol - The column to move to. +/// +formatted_raw_ostream &formatted_raw_ostream::PadToColumn(unsigned NewCol) { + // Figure out what's in the buffer and add it to the column count. + ComputeColumn(getBufferStart(), GetNumBytesInBuffer()); + + // Output spaces until we reach the desired column. + indent(std::max(int(NewCol - ColumnScanned), 1)); + return *this; +} + +void formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) { + // Figure out what's in the buffer and add it to the column count. + ComputeColumn(Ptr, Size); + + // Write the data to the underlying stream (which is unbuffered, so + // the data will be immediately written out). + TheStream->write(Ptr, Size); + + // Reset the scanning pointer. + Scanned = 0; +} + +/// fouts() - This returns a reference to a formatted_raw_ostream for +/// standard output. Use it like: fouts() << "foo" << "bar"; +formatted_raw_ostream &llvm::fouts() { + static formatted_raw_ostream S(outs()); + return S; +} + +/// ferrs() - This returns a reference to a formatted_raw_ostream for +/// standard error. Use it like: ferrs() << "foo" << "bar"; +formatted_raw_ostream &llvm::ferrs() { + static formatted_raw_ostream S(errs()); + return S; +} + +/// fdbgs() - This returns a reference to a formatted_raw_ostream for +/// the debug stream. Use it like: fdbgs() << "foo" << "bar"; +formatted_raw_ostream &llvm::fdbgs() { + static formatted_raw_ostream S(dbgs()); + return S; +} diff --git a/final/lib/Support/GraphWriter.cpp b/final/lib/Support/GraphWriter.cpp new file mode 100644 index 00000000000..0dba28a2530 --- /dev/null +++ b/final/lib/Support/GraphWriter.cpp @@ -0,0 +1,200 @@ +//===-- GraphWriter.cpp - Implements GraphWriter support routines ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements misc. GraphWriter support routines. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/GraphWriter.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/Config/config.h" +using namespace llvm; + +std::string llvm::DOT::EscapeString(const std::string &Label) { + std::string Str(Label); + for (unsigned i = 0; i != Str.length(); ++i) + switch (Str[i]) { + case '\n': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; + Str[i] = 'n'; + break; + case '\t': + Str.insert(Str.begin()+i, ' '); // Convert to two spaces + ++i; + Str[i] = ' '; + break; + case '\\': + if (i+1 != Str.length()) + switch (Str[i+1]) { + case 'l': continue; // don't disturb \l + case '|': case '{': case '}': + Str.erase(Str.begin()+i); continue; + default: break; + } + case '{': case '}': + case '<': case '>': + case '|': case '"': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; // don't infinite loop + break; + } + return Str; +} + + + +void llvm::DisplayGraph(const sys::Path &Filename, bool wait, + GraphProgram::Name program) { + std::string ErrMsg; +#if HAVE_GRAPHVIZ + sys::Path Graphviz(LLVM_PATH_GRAPHVIZ); + + std::vector args; + args.push_back(Graphviz.c_str()); + args.push_back(Filename.c_str()); + args.push_back(0); + + errs() << "Running 'Graphviz' program... "; + if (sys::Program::ExecuteAndWait(Graphviz, &args[0],0,0,0,0,&ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + return; + } + Filename.eraseFromDisk(); + errs() << " done. \n"; + +#elif HAVE_XDOT_PY + std::vector args; + args.push_back(LLVM_PATH_XDOT_PY); + args.push_back(Filename.c_str()); + + switch (program) { + case GraphProgram::DOT: args.push_back("-f"); args.push_back("dot"); break; + case GraphProgram::FDP: args.push_back("-f"); args.push_back("fdp"); break; + case GraphProgram::NEATO: args.push_back("-f"); args.push_back("neato");break; + case GraphProgram::TWOPI: args.push_back("-f"); args.push_back("twopi");break; + case GraphProgram::CIRCO: args.push_back("-f"); args.push_back("circo");break; + default: errs() << "Unknown graph layout name; using default.\n"; + } + + args.push_back(0); + + errs() << "Running 'xdot.py' program... "; + if (sys::Program::ExecuteAndWait(sys::Path(LLVM_PATH_XDOT_PY), + &args[0],0,0,0,0,&ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + return; + } + Filename.eraseFromDisk(); + errs() << " done. \n"; + +#elif (HAVE_GV && (HAVE_DOT || HAVE_FDP || HAVE_NEATO || \ + HAVE_TWOPI || HAVE_CIRCO)) + sys::Path PSFilename = Filename; + PSFilename.appendSuffix("ps"); + + sys::Path prog; + + // Set default grapher +#if HAVE_CIRCO + prog = sys::Path(LLVM_PATH_CIRCO); +#endif +#if HAVE_TWOPI + prog = sys::Path(LLVM_PATH_TWOPI); +#endif +#if HAVE_NEATO + prog = sys::Path(LLVM_PATH_NEATO); +#endif +#if HAVE_FDP + prog = sys::Path(LLVM_PATH_FDP); +#endif +#if HAVE_DOT + prog = sys::Path(LLVM_PATH_DOT); +#endif + + // Find which program the user wants +#if HAVE_DOT + if (program == GraphProgram::DOT) + prog = sys::Path(LLVM_PATH_DOT); +#endif +#if (HAVE_FDP) + if (program == GraphProgram::FDP) + prog = sys::Path(LLVM_PATH_FDP); +#endif +#if (HAVE_NEATO) + if (program == GraphProgram::NEATO) + prog = sys::Path(LLVM_PATH_NEATO); +#endif +#if (HAVE_TWOPI) + if (program == GraphProgram::TWOPI) + prog = sys::Path(LLVM_PATH_TWOPI); +#endif +#if (HAVE_CIRCO) + if (program == GraphProgram::CIRCO) + prog = sys::Path(LLVM_PATH_CIRCO); +#endif + + std::vector args; + args.push_back(prog.c_str()); + args.push_back("-Tps"); + args.push_back("-Nfontname=Courier"); + args.push_back("-Gsize=7.5,10"); + args.push_back(Filename.c_str()); + args.push_back("-o"); + args.push_back(PSFilename.c_str()); + args.push_back(0); + + errs() << "Running '" << prog.str() << "' program... "; + + if (sys::Program::ExecuteAndWait(prog, &args[0], 0, 0, 0, 0, &ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + return; + } + errs() << " done. \n"; + + sys::Path gv(LLVM_PATH_GV); + args.clear(); + args.push_back(gv.c_str()); + args.push_back(PSFilename.c_str()); + args.push_back("--spartan"); + args.push_back(0); + + ErrMsg.clear(); + if (wait) { + if (sys::Program::ExecuteAndWait(gv, &args[0],0,0,0,0,&ErrMsg)) + errs() << "Error: " << ErrMsg << "\n"; + Filename.eraseFromDisk(); + PSFilename.eraseFromDisk(); + } + else { + sys::Program::ExecuteNoWait(gv, &args[0],0,0,0,&ErrMsg); + errs() << "Remember to erase graph files: " << Filename.str() << " " + << PSFilename.str() << "\n"; + } +#elif HAVE_DOTTY + sys::Path dotty(LLVM_PATH_DOTTY); + + std::vector args; + args.push_back(dotty.c_str()); + args.push_back(Filename.c_str()); + args.push_back(0); + + errs() << "Running 'dotty' program... "; + if (sys::Program::ExecuteAndWait(dotty, &args[0],0,0,0,0,&ErrMsg)) { + errs() << "Error: " << ErrMsg << "\n"; + } else { +// Dotty spawns another app and doesn't wait until it returns +#if defined (__MINGW32__) || defined (_WINDOWS) + return; +#endif + Filename.eraseFromDisk(); + } +#endif +} diff --git a/final/lib/Support/Host.cpp b/final/lib/Support/Host.cpp new file mode 100644 index 00000000000..4dacf9691d6 --- /dev/null +++ b/final/lib/Support/Host.cpp @@ -0,0 +1,307 @@ +//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Host concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Host.h" +#include "llvm/Config/config.h" +#include + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Host.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Host.inc" +#endif +#ifdef _MSC_VER +#include +#endif + +//===----------------------------------------------------------------------===// +// +// Implementations of the CPU detection routines +// +//===----------------------------------------------------------------------===// + +using namespace llvm; + +#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ + || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + +/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the +/// specified arguments. If we can't run cpuid on the host, return true. +static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, + unsigned *rEBX, unsigned *rECX, unsigned *rEDX) { +#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) + #if defined(__GNUC__) + // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. + asm ("movq\t%%rbx, %%rsi\n\t" + "cpuid\n\t" + "xchgq\t%%rbx, %%rsi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + int registers[4]; + __cpuid(registers, value); + *rEAX = registers[0]; + *rEBX = registers[1]; + *rECX = registers[2]; + *rEDX = registers[3]; + return false; + #endif +#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) + #if defined(__GNUC__) + asm ("movl\t%%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl\t%%ebx, %%esi\n\t" + : "=a" (*rEAX), + "=S" (*rEBX), + "=c" (*rECX), + "=d" (*rEDX) + : "a" (value)); + return false; + #elif defined(_MSC_VER) + __asm { + mov eax,value + cpuid + mov esi,rEAX + mov dword ptr [esi],eax + mov esi,rEBX + mov dword ptr [esi],ebx + mov esi,rECX + mov dword ptr [esi],ecx + mov esi,rEDX + mov dword ptr [esi],edx + } + return false; + #endif +#endif + return true; +} + +static void DetectX86FamilyModel(unsigned EAX, unsigned &Family, + unsigned &Model) { + Family = (EAX >> 8) & 0xf; // Bits 8 - 11 + Model = (EAX >> 4) & 0xf; // Bits 4 - 7 + if (Family == 6 || Family == 0xf) { + if (Family == 0xf) + // Examine extended family ID if family ID is F. + Family += (EAX >> 20) & 0xff; // Bits 20 - 27 + // Examine extended model ID if family ID is 6 or F. + Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 + } +} + +std::string sys::getHostCPUName() { + unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; + if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) + return "generic"; + unsigned Family = 0; + unsigned Model = 0; + DetectX86FamilyModel(EAX, Family, Model); + + bool HasSSE3 = (ECX & 0x1); + GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); + bool Em64T = (EDX >> 29) & 0x1; + + union { + unsigned u[3]; + char c[12]; + } text; + + GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1); + if (memcmp(text.c, "GenuineIntel", 12) == 0) { + switch (Family) { + case 3: + return "i386"; + case 4: + switch (Model) { + case 0: // Intel486 DX processors + case 1: // Intel486 DX processors + case 2: // Intel486 SX processors + case 3: // Intel487 processors, IntelDX2 OverDrive processors, + // IntelDX2 processors + case 4: // Intel486 SL processor + case 5: // IntelSX2 processors + case 7: // Write-Back Enhanced IntelDX2 processors + case 8: // IntelDX4 OverDrive processors, IntelDX4 processors + default: return "i486"; + } + case 5: + switch (Model) { + case 1: // Pentium OverDrive processor for Pentium processor (60, 66), + // Pentium processors (60, 66) + case 2: // Pentium OverDrive processor for Pentium processor (75, 90, + // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, + // 150, 166, 200) + case 3: // Pentium OverDrive processors for Intel486 processor-based + // systems + return "pentium"; + + case 4: // Pentium OverDrive processor with MMX technology for Pentium + // processor (75, 90, 100, 120, 133), Pentium processor with + // MMX technology (166, 200) + return "pentium-mmx"; + + default: return "pentium"; + } + case 6: + switch (Model) { + case 1: // Pentium Pro processor + return "pentiumpro"; + + case 3: // Intel Pentium II OverDrive processor, Pentium II processor, + // model 03 + case 5: // Pentium II processor, model 05, Pentium II Xeon processor, + // model 05, and Intel Celeron processor, model 05 + case 6: // Celeron processor, model 06 + return "pentium2"; + + case 7: // Pentium III processor, model 07, and Pentium III Xeon + // processor, model 07 + case 8: // Pentium III processor, model 08, Pentium III Xeon processor, + // model 08, and Celeron processor, model 08 + case 10: // Pentium III Xeon processor, model 0Ah + case 11: // Pentium III processor, model 0Bh + return "pentium3"; + + case 9: // Intel Pentium M processor, Intel Celeron M processor model 09. + case 13: // Intel Pentium M processor, Intel Celeron M processor, model + // 0Dh. All processors are manufactured using the 90 nm process. + return "pentium-m"; + + case 14: // Intel Core Duo processor, Intel Core Solo processor, model + // 0Eh. All processors are manufactured using the 65 nm process. + return "yonah"; + + case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile + // processor, Intel Core 2 Quad processor, Intel Core 2 Quad + // mobile processor, Intel Core 2 Extreme processor, Intel + // Pentium Dual-Core processor, Intel Xeon processor, model + // 0Fh. All processors are manufactured using the 65 nm process. + case 22: // Intel Celeron processor model 16h. All processors are + // manufactured using the 65 nm process + return "core2"; + + case 21: // Intel EP80579 Integrated Processor and Intel EP80579 + // Integrated Processor with Intel QuickAssist Technology + return "i686"; // FIXME: ??? + + case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model + // 17h. All processors are manufactured using the 45 nm process. + // + // 45nm: Penryn , Wolfdale, Yorkfield (XE) + return "penryn"; + + case 26: // Intel Core i7 processor and Intel Xeon processor. All + // processors are manufactured using the 45 nm process. + case 29: // Intel Xeon processor MP. All processors are manufactured using + // the 45 nm process. + case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. + // As found in a Summer 2010 model iMac. + case 37: // Intel Core i7, laptop version. + return "corei7"; + + case 28: // Intel Atom processor. All processors are manufactured using + // the 45 nm process + return "atom"; + + default: return "i686"; + } + case 15: { + switch (Model) { + case 0: // Pentium 4 processor, Intel Xeon processor. All processors are + // model 00h and manufactured using the 0.18 micron process. + case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon + // processor MP, and Intel Celeron processor. All processors are + // model 01h and manufactured using the 0.18 micron process. + case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, + // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron + // processor, and Mobile Intel Celeron processor. All processors + // are model 02h and manufactured using the 0.13 micron process. + return (Em64T) ? "x86-64" : "pentium4"; + + case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D + // processor. All processors are model 03h and manufactured using + // the 90 nm process. + case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, + // Pentium D processor, Intel Xeon processor, Intel Xeon + // processor MP, Intel Celeron D processor. All processors are + // model 04h and manufactured using the 90 nm process. + case 6: // Pentium 4 processor, Pentium D processor, Pentium processor + // Extreme Edition, Intel Xeon processor, Intel Xeon processor + // MP, Intel Celeron D processor. All processors are model 06h + // and manufactured using the 65 nm process. + return (Em64T) ? "nocona" : "prescott"; + + default: + return (Em64T) ? "x86-64" : "pentium4"; + } + } + + default: + return "generic"; + } + } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { + // FIXME: this poorly matches the generated SubtargetFeatureKV table. There + // appears to be no way to generate the wide variety of AMD-specific targets + // from the information returned from CPUID. + switch (Family) { + case 4: + return "i486"; + case 5: + switch (Model) { + case 6: + case 7: return "k6"; + case 8: return "k6-2"; + case 9: + case 13: return "k6-3"; + default: return "pentium"; + } + case 6: + switch (Model) { + case 4: return "athlon-tbird"; + case 6: + case 7: + case 8: return "athlon-mp"; + case 10: return "athlon-xp"; + default: return "athlon"; + } + case 15: + if (HasSSE3) + return "k8-sse3"; + switch (Model) { + case 1: return "opteron"; + case 5: return "athlon-fx"; // also opteron + default: return "athlon64"; + } + case 16: + return "amdfam10"; + default: + return "generic"; + } + } + return "generic"; +} +#else +std::string sys::getHostCPUName() { + return "generic"; +} +#endif + +bool sys::getHostCPUFeatures(StringMap &Features){ + return false; +} diff --git a/final/lib/Support/IncludeFile.cpp b/final/lib/Support/IncludeFile.cpp new file mode 100644 index 00000000000..5da88261ce5 --- /dev/null +++ b/final/lib/Support/IncludeFile.cpp @@ -0,0 +1,20 @@ +//===- lib/System/IncludeFile.cpp - Ensure Linking Of Implementation -----===// +// +// 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 IncludeFile constructor. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/IncludeFile.h" + +using namespace llvm; + +// This constructor is used to ensure linking of other modules. See the +// llvm/Support/IncludeFile.h header for details. +IncludeFile::IncludeFile(const void*) {} diff --git a/final/lib/Support/IntEqClasses.cpp b/final/lib/Support/IntEqClasses.cpp new file mode 100644 index 00000000000..11344956e4c --- /dev/null +++ b/final/lib/Support/IntEqClasses.cpp @@ -0,0 +1,70 @@ +//===-- llvm/ADT/IntEqClasses.cpp - Equivalence Classes of Integers -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Equivalence classes for small integers. This is a mapping of the integers +// 0 .. N-1 into M equivalence classes numbered 0 .. M-1. +// +// Initially each integer has its own equivalence class. Classes are joined by +// passing a representative member of each class to join(). +// +// Once the classes are built, compress() will number them 0 .. M-1 and prevent +// further changes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/IntEqClasses.h" + +using namespace llvm; + +void IntEqClasses::grow(unsigned N) { + assert(NumClasses == 0 && "grow() called after compress()."); + EC.reserve(N); + while (EC.size() < N) + EC.push_back(EC.size()); +} + +void IntEqClasses::join(unsigned a, unsigned b) { + assert(NumClasses == 0 && "join() called after compress()."); + unsigned eca = EC[a]; + unsigned ecb = EC[b]; + // Update pointers while searching for the leaders, compressing the paths + // incrementally. The larger leader will eventually be updated, joining the + // classes. + while (eca != ecb) + if (eca < ecb) + EC[b] = eca, b = ecb, ecb = EC[b]; + else + EC[a] = ecb, a = eca, eca = EC[a]; +} + +unsigned IntEqClasses::findLeader(unsigned a) const { + assert(NumClasses == 0 && "findLeader() called after compress()."); + while (a != EC[a]) + a = EC[a]; + return a; +} + +void IntEqClasses::compress() { + if (NumClasses) + return; + for (unsigned i = 0, e = EC.size(); i != e; ++i) + EC[i] = (EC[i] == i) ? NumClasses++ : EC[EC[i]]; +} + +void IntEqClasses::uncompress() { + if (!NumClasses) + return; + SmallVector Leader; + for (unsigned i = 0, e = EC.size(); i != e; ++i) + if (EC[i] < Leader.size()) + EC[i] = Leader[EC[i]]; + else + Leader.push_back(EC[i] = i); + NumClasses = 0; +} diff --git a/final/lib/Support/IntervalMap.cpp b/final/lib/Support/IntervalMap.cpp new file mode 100644 index 00000000000..4dfcc404ca4 --- /dev/null +++ b/final/lib/Support/IntervalMap.cpp @@ -0,0 +1,161 @@ +//===- lib/Support/IntervalMap.cpp - A sorted interval map ----------------===// +// +// 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 few non-templated functions in IntervalMap. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/IntervalMap.h" + +namespace llvm { +namespace IntervalMapImpl { + +void Path::replaceRoot(void *Root, unsigned Size, IdxPair Offsets) { + assert(!path.empty() && "Can't replace missing root"); + path.front() = Entry(Root, Size, Offsets.first); + path.insert(path.begin() + 1, Entry(subtree(0), Offsets.second)); +} + +NodeRef Path::getLeftSibling(unsigned Level) const { + // The root has no siblings. + if (Level == 0) + return NodeRef(); + + // Go up the tree until we can go left. + unsigned l = Level - 1; + while (l && path[l].offset == 0) + --l; + + // We can't go left. + if (path[l].offset == 0) + return NodeRef(); + + // NR is the subtree containing our left sibling. + NodeRef NR = path[l].subtree(path[l].offset - 1); + + // Keep right all the way down. + for (++l; l != Level; ++l) + NR = NR.subtree(NR.size() - 1); + return NR; +} + +void Path::moveLeft(unsigned Level) { + assert(Level != 0 && "Cannot move the root node"); + + // Go up the tree until we can go left. + unsigned l = 0; + if (valid()) { + l = Level - 1; + while (path[l].offset == 0) { + assert(l != 0 && "Cannot move beyond begin()"); + --l; + } + } else if (height() < Level) + // end() may have created a height=0 path. + path.resize(Level + 1, Entry(0, 0, 0)); + + // NR is the subtree containing our left sibling. + --path[l].offset; + NodeRef NR = subtree(l); + + // Get the rightmost node in the subtree. + for (++l; l != Level; ++l) { + path[l] = Entry(NR, NR.size() - 1); + NR = NR.subtree(NR.size() - 1); + } + path[l] = Entry(NR, NR.size() - 1); +} + +NodeRef Path::getRightSibling(unsigned Level) const { + // The root has no siblings. + if (Level == 0) + return NodeRef(); + + // Go up the tree until we can go right. + unsigned l = Level - 1; + while (l && atLastEntry(l)) + --l; + + // We can't go right. + if (atLastEntry(l)) + return NodeRef(); + + // NR is the subtree containing our right sibling. + NodeRef NR = path[l].subtree(path[l].offset + 1); + + // Keep left all the way down. + for (++l; l != Level; ++l) + NR = NR.subtree(0); + return NR; +} + +void Path::moveRight(unsigned Level) { + assert(Level != 0 && "Cannot move the root node"); + + // Go up the tree until we can go right. + unsigned l = Level - 1; + while (l && atLastEntry(l)) + --l; + + // NR is the subtree containing our right sibling. If we hit end(), we have + // offset(0) == node(0).size(). + if (++path[l].offset == path[l].size) + return; + NodeRef NR = subtree(l); + + for (++l; l != Level; ++l) { + path[l] = Entry(NR, 0); + NR = NR.subtree(0); + } + path[l] = Entry(NR, 0); +} + + +IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, + const unsigned *CurSize, unsigned NewSize[], + unsigned Position, bool Grow) { + assert(Elements + Grow <= Nodes * Capacity && "Not enough room for elements"); + assert(Position <= Elements && "Invalid position"); + if (!Nodes) + return IdxPair(); + + // Trivial algorithm: left-leaning even distribution. + const unsigned PerNode = (Elements + Grow) / Nodes; + const unsigned Extra = (Elements + Grow) % Nodes; + IdxPair PosPair = IdxPair(Nodes, 0); + unsigned Sum = 0; + for (unsigned n = 0; n != Nodes; ++n) { + Sum += NewSize[n] = PerNode + (n < Extra); + if (PosPair.first == Nodes && Sum > Position) + PosPair = IdxPair(n, Position - (Sum - NewSize[n])); + } + assert(Sum == Elements + Grow && "Bad distribution sum"); + + // Subtract the Grow element that was added. + if (Grow) { + assert(PosPair.first < Nodes && "Bad algebra"); + assert(NewSize[PosPair.first] && "Too few elements to need Grow"); + --NewSize[PosPair.first]; + } + +#ifndef NDEBUG + Sum = 0; + for (unsigned n = 0; n != Nodes; ++n) { + assert(NewSize[n] <= Capacity && "Overallocated node"); + Sum += NewSize[n]; + } + assert(Sum == Elements && "Bad distribution sum"); +#endif + + return PosPair; +} + +} // namespace IntervalMapImpl +} // namespace llvm + diff --git a/final/lib/Support/IsInf.cpp b/final/lib/Support/IsInf.cpp new file mode 100644 index 00000000000..d6da0c99e8d --- /dev/null +++ b/final/lib/Support/IsInf.cpp @@ -0,0 +1,49 @@ +//===-- IsInf.cpp - Platform-independent wrapper around C99 isinf() -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Platform-independent wrapper around C99 isinf() +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" + +#if HAVE_ISINF_IN_MATH_H +# include +#elif HAVE_ISINF_IN_CMATH +# include +#elif HAVE_STD_ISINF_IN_CMATH +# include +using std::isinf; +#elif HAVE_FINITE_IN_IEEEFP_H +// A handy workaround I found at http://www.unixguide.net/sun/faq ... +// apparently this has been a problem with Solaris for years. +# include +static int isinf(double x) { return !finite(x) && x==x; } +#elif defined(_MSC_VER) +#include +#define isinf(X) (!_finite(X)) +#elif defined(_AIX) && defined(__GNUC__) +// GCC's fixincludes seems to be removing the isinf() declaration from the +// system header /usr/include/math.h +# include +static int isinf(double x) { return !finite(x) && x==x; } +#elif defined(__hpux) +// HP-UX is "special" +#include +static int isinf(double x) { return ((x) == INFINITY) || ((x) == -INFINITY); } +#else +# error "Don't know how to get isinf()" +#endif + +namespace llvm { + +int IsInf(float f) { return isinf(f); } +int IsInf(double d) { return isinf(d); } + +} // end namespace llvm; diff --git a/final/lib/Support/IsNAN.cpp b/final/lib/Support/IsNAN.cpp new file mode 100644 index 00000000000..bdfdfbf3155 --- /dev/null +++ b/final/lib/Support/IsNAN.cpp @@ -0,0 +1,33 @@ +//===-- IsNAN.cpp ---------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Platform-independent wrapper around C99 isnan(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" + +#if HAVE_ISNAN_IN_MATH_H +# include +#elif HAVE_ISNAN_IN_CMATH +# include +#elif HAVE_STD_ISNAN_IN_CMATH +# include +using std::isnan; +#elif defined(_MSC_VER) +#include +#define isnan _isnan +#else +# error "Don't know how to get isnan()" +#endif + +namespace llvm { + int IsNAN(float f) { return isnan(f); } + int IsNAN(double d) { return isnan(d); } +} // end namespace llvm; diff --git a/final/lib/Support/Makefile b/final/lib/Support/Makefile new file mode 100644 index 00000000000..d68e500ca5f --- /dev/null +++ b/final/lib/Support/Makefile @@ -0,0 +1,22 @@ +##===- lib/Support/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMSupport +BUILD_ARCHIVE = 1 + +## FIXME: This only requires RTTI because tblgen uses it. Fix that. +REQUIRES_RTTI = 1 + +EXTRA_DIST = Unix Win32 README.txt + +include $(LEVEL)/Makefile.common + +CompileCommonOpts := $(filter-out -pedantic,$(CompileCommonOpts)) +CompileCommonOpts := $(filter-out -Wno-long-long,$(CompileCommonOpts)) diff --git a/final/lib/Support/ManagedStatic.cpp b/final/lib/Support/ManagedStatic.cpp new file mode 100644 index 00000000000..c767c15e71c --- /dev/null +++ b/final/lib/Support/ManagedStatic.cpp @@ -0,0 +1,75 @@ +//===-- ManagedStatic.cpp - Static Global 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 ManagedStatic class and llvm_shutdown(). +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Atomic.h" +#include +using namespace llvm; + +static const ManagedStaticBase *StaticList = 0; + +void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), + void (*Deleter)(void*)) const { + if (llvm_is_multithreaded()) { + llvm_acquire_global_lock(); + + if (Ptr == 0) { + void* tmp = Creator ? Creator() : 0; + + sys::MemoryFence(); + Ptr = tmp; + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } + + llvm_release_global_lock(); + } else { + assert(Ptr == 0 && DeleterFn == 0 && Next == 0 && + "Partially initialized ManagedStatic!?"); + Ptr = Creator ? Creator() : 0; + DeleterFn = Deleter; + + // Add to list of managed statics. + Next = StaticList; + StaticList = this; + } +} + +void ManagedStaticBase::destroy() const { + assert(DeleterFn && "ManagedStatic not initialized correctly!"); + assert(StaticList == this && + "Not destroyed in reverse order of construction?"); + // Unlink from list. + StaticList = Next; + Next = 0; + + // Destroy memory. + DeleterFn(Ptr); + + // Cleanup. + Ptr = 0; + DeleterFn = 0; +} + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm::llvm_shutdown() { + while (StaticList) + StaticList->destroy(); + + if (llvm_is_multithreaded()) llvm_stop_multithreaded(); +} + diff --git a/final/lib/Support/Memory.cpp b/final/lib/Support/Memory.cpp new file mode 100644 index 00000000000..a9689b2c39f --- /dev/null +++ b/final/lib/Support/Memory.cpp @@ -0,0 +1,74 @@ +//===- Memory.cpp - Memory Handling Support ---------------------*- 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 some helpful functions for allocating memory and dealing +// with memory mapped files +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Memory.h" +#include "llvm/Support/Valgrind.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Memory.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Memory.inc" +#endif + +extern "C" void sys_icache_invalidate(const void *Addr, size_t len); + +/// InvalidateInstructionCache - Before the JIT can run a block of code +/// that has been emitted it must invalidate the instruction cache on some +/// platforms. +void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr, + size_t Len) { + +// icache invalidation for PPC and ARM. +#if defined(__APPLE__) + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__) + sys_icache_invalidate(Addr, Len); +# endif + +#else + +# if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__) + const size_t LineSize = 32; + + const intptr_t Mask = ~(LineSize - 1); + const intptr_t StartLine = ((intptr_t) Addr) & Mask; + const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask; + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("dcbf 0, %0" : : "r"(Line)); + asm volatile("sync"); + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); +# elif defined(__arm__) && defined(__GNUC__) + // FIXME: Can we safely always call this for __GNUC__ everywhere? + char *Start = (char*) Addr; + char *End = Start + Len; + __clear_cache(Start, End); +# endif + +#endif // end apple + + ValgrindDiscardTranslations(Addr, Len); +} diff --git a/final/lib/Support/MemoryBuffer.cpp b/final/lib/Support/MemoryBuffer.cpp new file mode 100644 index 00000000000..a0c650d6820 --- /dev/null +++ b/final/lib/Support/MemoryBuffer.cpp @@ -0,0 +1,298 @@ +//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===// +// +// 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 MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/system_error.h" +#include +#include +#include +#include +#include +#include +#include +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include +#include +#else +#include +#endif +#include +using namespace llvm; + +namespace { const llvm::error_code success; } + +//===----------------------------------------------------------------------===// +// MemoryBuffer implementation itself. +//===----------------------------------------------------------------------===// + +MemoryBuffer::~MemoryBuffer() { } + +/// init - Initialize this MemoryBuffer as a reference to externally allocated +/// memory, memory that we know is already null terminated. +void MemoryBuffer::init(const char *BufStart, const char *BufEnd) { + assert(BufEnd[0] == 0 && "Buffer is not null terminated!"); + BufferStart = BufStart; + BufferEnd = BufEnd; +} + +//===----------------------------------------------------------------------===// +// MemoryBufferMem implementation. +//===----------------------------------------------------------------------===// + +/// CopyStringRef - Copies contents of a StringRef into a block of memory and +/// null-terminates it. +static void CopyStringRef(char *Memory, StringRef Data) { + memcpy(Memory, Data.data(), Data.size()); + Memory[Data.size()] = 0; // Null terminate string. +} + +/// GetNamedBuffer - Allocates a new MemoryBuffer with Name copied after it. +template +static T* GetNamedBuffer(StringRef Buffer, StringRef Name) { + char *Mem = static_cast(operator new(sizeof(T) + Name.size() + 1)); + CopyStringRef(Mem + sizeof(T), Name); + return new (Mem) T(Buffer); +} + +namespace { +/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory. +class MemoryBufferMem : public MemoryBuffer { +public: + MemoryBufferMem(StringRef InputData) { + init(InputData.begin(), InputData.end()); + } + + virtual const char *getBufferIdentifier() const { + // The name is stored after the class itself. + return reinterpret_cast(this + 1); + } +}; +} + +/// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note +/// that EndPtr[0] must be a null byte and be accessible! +MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData, + StringRef BufferName) { + return GetNamedBuffer(InputData, BufferName); +} + +/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, +/// copying the contents and taking ownership of it. This has no requirements +/// on EndPtr[0]. +MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData, + StringRef BufferName) { + MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName); + if (!Buf) return 0; + memcpy(const_cast(Buf->getBufferStart()), InputData.data(), + InputData.size()); + return Buf; +} + +/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size +/// that is not initialized. Note that the caller should initialize the +/// memory allocated by this method. The memory is owned by the MemoryBuffer +/// object. +MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size, + StringRef BufferName) { + // Allocate space for the MemoryBuffer, the data and the name. It is important + // that MemoryBuffer and data are aligned so PointerIntPair works with them. + size_t AlignedStringLen = + RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1, + sizeof(void*)); // TODO: Is sizeof(void*) enough? + size_t RealLen = AlignedStringLen + Size + 1; + char *Mem = static_cast(operator new(RealLen, std::nothrow)); + if (!Mem) return 0; + + // The name is stored after the class itself. + CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName); + + // The buffer begins after the name and must be aligned. + char *Buf = Mem + AlignedStringLen; + Buf[Size] = 0; // Null terminate buffer. + + return new (Mem) MemoryBufferMem(StringRef(Buf, Size)); +} + +/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that +/// is completely initialized to zeros. Note that the caller should +/// initialize the memory allocated by this method. The memory is owned by +/// the MemoryBuffer object. +MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) { + MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName); + if (!SB) return 0; + memset(const_cast(SB->getBufferStart()), 0, Size); + return SB; +} + + +/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin +/// if the Filename is "-". If an error occurs, this returns null and fills +/// in *ErrStr with a reason. If stdin is empty, this API (unlike getSTDIN) +/// returns an empty buffer. +error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename, + OwningPtr &result, + int64_t FileSize) { + if (Filename == "-") + return getSTDIN(result); + return getFile(Filename, result, FileSize); +} + +error_code MemoryBuffer::getFileOrSTDIN(const char *Filename, + OwningPtr &result, + int64_t FileSize) { + if (strcmp(Filename, "-") == 0) + return getSTDIN(result); + return getFile(Filename, result, FileSize); +} + +//===----------------------------------------------------------------------===// +// MemoryBuffer::getFile implementation. +//===----------------------------------------------------------------------===// + +namespace { +/// MemoryBufferMMapFile - This represents a file that was mapped in with the +/// sys::Path::MapInFilePages method. When destroyed, it calls the +/// sys::Path::UnMapFilePages method. +class MemoryBufferMMapFile : public MemoryBufferMem { +public: + MemoryBufferMMapFile(StringRef Buffer) + : MemoryBufferMem(Buffer) { } + + ~MemoryBufferMMapFile() { + sys::Path::UnMapFilePages(getBufferStart(), getBufferSize()); + } +}; +} + +error_code MemoryBuffer::getFile(StringRef Filename, + OwningPtr &result, + int64_t FileSize) { + // Ensure the path is null terminated. + SmallString<256> PathBuf(Filename.begin(), Filename.end()); + return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize); +} + +error_code MemoryBuffer::getFile(const char *Filename, + OwningPtr &result, + int64_t FileSize) { + int OpenFlags = O_RDONLY; +#ifdef O_BINARY + OpenFlags |= O_BINARY; // Open input file in binary mode on win32. +#endif + int FD = ::open(Filename, OpenFlags); + if (FD == -1) { + return error_code(errno, posix_category()); + } + error_code ret = getOpenFile(FD, Filename, result, FileSize); + close(FD); + return ret; +} + +error_code MemoryBuffer::getOpenFile(int FD, const char *Filename, + OwningPtr &result, + int64_t FileSize) { + // If we don't know the file size, use fstat to find out. fstat on an open + // file descriptor is cheaper than stat on a random path. + if (FileSize == -1) { + struct stat FileInfo; + // TODO: This should use fstat64 when available. + if (fstat(FD, &FileInfo) == -1) { + return error_code(errno, posix_category()); + } + FileSize = FileInfo.st_size; + } + + + // If the file is large, try to use mmap to read it in. We don't use mmap + // for small files, because this can severely fragment our address space. Also + // don't try to map files that are exactly a multiple of the system page size, + // as the file would not have the required null terminator. + // + // FIXME: Can we just mmap an extra page in the latter case? + if (FileSize >= 4096*4 && + (FileSize & (sys::Process::GetPageSize()-1)) != 0) { + if (const char *Pages = sys::Path::MapInFilePages(FD, FileSize)) { + result.reset(GetNamedBuffer( + StringRef(Pages, FileSize), Filename)); + return success; + } + } + + MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(FileSize, Filename); + if (!Buf) { + // Failed to create a buffer. The only way it can fail is if + // new(std::nothrow) returns 0. + return make_error_code(errc::not_enough_memory); + } + + OwningPtr SB(Buf); + char *BufPtr = const_cast(SB->getBufferStart()); + + size_t BytesLeft = FileSize; + while (BytesLeft) { + ssize_t NumRead = ::read(FD, BufPtr, BytesLeft); + if (NumRead == -1) { + if (errno == EINTR) + continue; + // Error while reading. + return error_code(errno, posix_category()); + } else if (NumRead == 0) { + // We hit EOF early, truncate and terminate buffer. + Buf->BufferEnd = BufPtr; + *BufPtr = 0; + result.swap(SB); + return success; + } + BytesLeft -= NumRead; + BufPtr += NumRead; + } + + result.swap(SB); + return success; +} + +//===----------------------------------------------------------------------===// +// MemoryBuffer::getSTDIN implementation. +//===----------------------------------------------------------------------===// + +error_code MemoryBuffer::getSTDIN(OwningPtr &result) { + // Read in all of the data from stdin, we cannot mmap stdin. + // + // FIXME: That isn't necessarily true, we should try to mmap stdin and + // fallback if it fails. + sys::Program::ChangeStdinToBinary(); + + const ssize_t ChunkSize = 4096*4; + SmallString Buffer; + ssize_t ReadBytes; + // Read into Buffer until we hit EOF. + do { + Buffer.reserve(Buffer.size() + ChunkSize); + ReadBytes = read(0, Buffer.end(), ChunkSize); + if (ReadBytes == -1) { + if (errno == EINTR) continue; + return error_code(errno, posix_category()); + } + Buffer.set_size(Buffer.size() + ReadBytes); + } while (ReadBytes != 0); + + result.reset(getMemBufferCopy(Buffer, "")); + return success; +} diff --git a/final/lib/Support/MemoryObject.cpp b/final/lib/Support/MemoryObject.cpp new file mode 100644 index 00000000000..91e3ecd23a2 --- /dev/null +++ b/final/lib/Support/MemoryObject.cpp @@ -0,0 +1,34 @@ +//===- MemoryObject.cpp - Abstract memory interface -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/MemoryObject.h" +using namespace llvm; + +MemoryObject::~MemoryObject() { +} + +int MemoryObject::readBytes(uint64_t address, + uint64_t size, + uint8_t* buf, + uint64_t* copied) const { + uint64_t current = address; + uint64_t limit = getBase() + getExtent(); + + while (current - address < size && current < limit) { + if (readByte(current, &buf[(current - address)])) + return -1; + + current++; + } + + if (copied) + *copied = current - address; + + return 0; +} diff --git a/final/lib/Support/Mutex.cpp b/final/lib/Support/Mutex.cpp new file mode 100644 index 00000000000..b408973bbad --- /dev/null +++ b/final/lib/Support/Mutex.cpp @@ -0,0 +1,157 @@ +//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/Support/Mutex.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +MutexImpl::MutexImpl( bool recursive) { } +MutexImpl::~MutexImpl() { } +bool MutexImpl::acquire() { return true; } +bool MutexImpl::release() { return true; } +bool MutexImpl::tryacquire() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK) + +#include +#include +#include + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_mutex_init does have an address, then mutex support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_mutex_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a Mutex using pthread calls +MutexImpl::MutexImpl( bool recursive) + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_mutex data structures + pthread_mutex_t* mutex = + static_cast(malloc(sizeof(pthread_mutex_t))); + pthread_mutexattr_t attr; + + // Initialize the mutex attributes + int errorcode = pthread_mutexattr_init(&attr); + assert(errorcode == 0); + + // Initialize the mutex as a recursive mutex, if requested, or normal + // otherwise. + int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL ); + errorcode = pthread_mutexattr_settype(&attr, kind); + assert(errorcode == 0); + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) + // Make it a process local mutex + errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); + assert(errorcode == 0); +#endif + + // Initialize the mutex + errorcode = pthread_mutex_init(mutex, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_mutexattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = mutex; + } +} + +// Destruct a Mutex +MutexImpl::~MutexImpl() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + pthread_mutex_destroy(mutex); + free(mutex); + } +} + +bool +MutexImpl::acquire() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_lock(mutex); + return errorcode == 0; + } else return false; +} + +bool +MutexImpl::release() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_unlock(mutex); + return errorcode == 0; + } else return false; +} + +bool +MutexImpl::tryacquire() +{ + if (pthread_enabled) + { + pthread_mutex_t* mutex = static_cast(data_); + assert(mutex != 0); + + int errorcode = pthread_mutex_trylock(mutex); + return errorcode == 0; + } else return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/Mutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Windows/Mutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif diff --git a/final/lib/Support/Path.cpp b/final/lib/Support/Path.cpp new file mode 100644 index 00000000000..e5e875bc54d --- /dev/null +++ b/final/lib/Support/Path.cpp @@ -0,0 +1,283 @@ +//===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Path concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Path.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Config/config.h" +#include "llvm/Support/FileSystem.h" +#include +#include +#include +using namespace llvm; +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +bool Path::operator==(const Path &that) const { + return path == that.path; +} + +bool Path::operator<(const Path& that) const { + return path < that.path; +} + +Path +Path::GetLLVMConfigDir() { + Path result; +#ifdef LLVM_ETCDIR + if (result.set(LLVM_ETCDIR)) + return result; +#endif + return GetLLVMDefaultConfigDir(); +} + +LLVMFileType +sys::IdentifyFileType(const char *magic, unsigned length) { + assert(magic && "Invalid magic number string"); + assert(length >=4 && "Invalid magic number length"); + switch ((unsigned char)magic[0]) { + case 0xDE: // 0x0B17C0DE = BC wraper + if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 && + magic[3] == (char)0x0B) + return Bitcode_FileType; + break; + case 'B': + if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE) + return Bitcode_FileType; + break; + case '!': + if (length >= 8) + if (memcmp(magic,"!\n",8) == 0) + return Archive_FileType; + break; + + case '\177': + if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') { + if (length >= 18 && magic[17] == 0) + switch (magic[16]) { + default: break; + case 1: return ELF_Relocatable_FileType; + case 2: return ELF_Executable_FileType; + case 3: return ELF_SharedObject_FileType; + case 4: return ELF_Core_FileType; + } + } + break; + + case 0xCA: + if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && + magic[3] == char(0xBE)) { + // This is complicated by an overlap with Java class files. + // See the Mach-O section in /usr/share/file/magic for details. + if (length >= 8 && magic[7] < 43) + // FIXME: Universal Binary of any type. + return Mach_O_DynamicallyLinkedSharedLib_FileType; + } + break; + + case 0xFE: + case 0xCE: { + uint16_t type = 0; + if (magic[0] == char(0xFE) && magic[1] == char(0xED) && + magic[2] == char(0xFA) && magic[3] == char(0xCE)) { + /* Native endian */ + if (length >= 16) type = magic[14] << 8 | magic[15]; + } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) && + magic[2] == char(0xED) && magic[3] == char(0xFE)) { + /* Reverse endian */ + if (length >= 14) type = magic[13] << 8 | magic[12]; + } + switch (type) { + default: break; + case 1: return Mach_O_Object_FileType; + case 2: return Mach_O_Executable_FileType; + case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType; + case 4: return Mach_O_Core_FileType; + case 5: return Mach_O_PreloadExecutable_FileType; + case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType; + case 7: return Mach_O_DynamicLinker_FileType; + case 8: return Mach_O_Bundle_FileType; + case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType; + case 10: break; // FIXME: MH_DSYM companion file with only debug. + } + break; + } + case 0xF0: // PowerPC Windows + case 0x83: // Alpha 32-bit + case 0x84: // Alpha 64-bit + case 0x66: // MPS R4000 Windows + case 0x50: // mc68K + case 0x4c: // 80386 Windows + if (magic[1] == 0x01) + return COFF_FileType; + + case 0x90: // PA-RISC Windows + case 0x68: // mc68K Windows + if (magic[1] == 0x02) + return COFF_FileType; + break; + case 0x64: // x86-64 Windows. + if (magic[1] == char(0x86)) + return COFF_FileType; + break; + + default: + break; + } + return Unknown_FileType; +} + +bool +Path::isArchive() const { + LLVMFileType type; + if (fs::identify_magic(str(), type)) + return false; + return type == Archive_FileType; +} + +bool +Path::isDynamicLibrary() const { + LLVMFileType type; + if (fs::identify_magic(str(), type)) + return false; + switch (type) { + default: return false; + case Mach_O_FixedVirtualMemorySharedLib_FileType: + case Mach_O_DynamicallyLinkedSharedLib_FileType: + case Mach_O_DynamicallyLinkedSharedLibStub_FileType: + case ELF_SharedObject_FileType: + case COFF_FileType: return true; + } +} + +bool +Path::isObjectFile() const { + LLVMFileType type; + if (fs::identify_magic(str(), type) || type == Unknown_FileType) + return false; + return true; +} + +Path +Path::FindLibrary(std::string& name) { + std::vector LibPaths; + GetSystemLibraryPaths(LibPaths); + for (unsigned i = 0; i < LibPaths.size(); ++i) { + sys::Path FullPath(LibPaths[i]); + FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT); + if (FullPath.isDynamicLibrary()) + return FullPath; + FullPath.eraseSuffix(); + FullPath.appendSuffix("a"); + if (FullPath.isArchive()) + return FullPath; + } + return sys::Path(); +} + +StringRef Path::GetDLLSuffix() { + return &(LTDL_SHLIB_EXT[1]); +} + +void +Path::appendSuffix(StringRef suffix) { + if (!suffix.empty()) { + path.append("."); + path.append(suffix); + } +} + +bool +Path::isBitcodeFile() const { + LLVMFileType type; + if (fs::identify_magic(str(), type)) + return false; + return type == Bitcode_FileType; +} + +bool Path::hasMagicNumber(StringRef Magic) const { + std::string actualMagic; + if (getMagicNumber(actualMagic, static_cast(Magic.size()))) + return Magic == actualMagic; + return false; +} + +static void getPathList(const char*path, std::vector& Paths) { + const char* at = path; + const char* delim = strchr(at, PathSeparator); + Path tmpPath; + while (delim != 0) { + std::string tmp(at, size_t(delim-at)); + if (tmpPath.set(tmp)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + at = delim + 1; + delim = strchr(at, PathSeparator); + } + + if (*at != 0) + if (tmpPath.set(std::string(at))) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); +} + +static StringRef getDirnameCharSep(StringRef path, const char *Sep) { + assert(Sep[0] != '\0' && Sep[1] == '\0' && + "Sep must be a 1-character string literal."); + if (path.empty()) + return "."; + + // If the path is all slashes, return a single slash. + // Otherwise, remove all trailing slashes. + + signed pos = static_cast(path.size()) - 1; + + while (pos >= 0 && path[pos] == Sep[0]) + --pos; + + if (pos < 0) + return path[0] == Sep[0] ? Sep : "."; + + // Any slashes left? + signed i = 0; + + while (i < pos && path[i] != Sep[0]) + ++i; + + if (i == pos) // No slashes? Return "." + return "."; + + // There is at least one slash left. Remove all trailing non-slashes. + while (pos >= 0 && path[pos] != Sep[0]) + --pos; + + // Remove any trailing slashes. + while (pos >= 0 && path[pos] == Sep[0]) + --pos; + + if (pos < 0) + return path[0] == Sep[0] ? Sep : "."; + + return path.substr(0, pos+1); +} + +// Include the truly platform-specific parts of this class. +#if defined(LLVM_ON_UNIX) +#include "Unix/Path.inc" +#endif +#if defined(LLVM_ON_WIN32) +#include "Windows/Path.inc" +#endif diff --git a/final/lib/Support/PathV2.cpp b/final/lib/Support/PathV2.cpp new file mode 100644 index 00000000000..896c94c071b --- /dev/null +++ b/final/lib/Support/PathV2.cpp @@ -0,0 +1,774 @@ +//===-- PathV2.cpp - Implement OS Path Concept ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system PathV2 API. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PathV2.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ErrorHandling.h" +#include +#include +#include + +namespace { + using llvm::StringRef; + using llvm::sys::path::is_separator; + +#ifdef LLVM_ON_WIN32 + const StringRef separators = "\\/"; + const char prefered_separator = '\\'; +#else + const StringRef separators = "/"; + const char prefered_separator = '/'; +#endif + + const llvm::error_code success; + + StringRef find_first_component(StringRef path) { + // Look for this first component in the following order. + // * empty (in this case we return an empty string) + // * either C: or {//,\\}net. + // * {/,\} + // * {.,..} + // * {file,directory}name + + if (path.empty()) + return path; + +#ifdef LLVM_ON_WIN32 + // C: + if (path.size() >= 2 && std::isalpha(path[0]) && path[1] == ':') + return path.substr(0, 2); +#endif + + // //net + if ((path.size() > 2) && + is_separator(path[0]) && + path[0] == path[1] && + !is_separator(path[2])) { + // Find the next directory separator. + size_t end = path.find_first_of(separators, 2); + return path.substr(0, end); + } + + // {/,\} + if (is_separator(path[0])) + return path.substr(0, 1); + + if (path.startswith("..")) + return path.substr(0, 2); + + if (path[0] == '.') + return path.substr(0, 1); + + // * {file,directory}name + size_t end = path.find_first_of(separators, 2); + return path.substr(0, end); + } + + size_t filename_pos(StringRef str) { + if (str.size() == 2 && + is_separator(str[0]) && + str[0] == str[1]) + return 0; + + if (str.size() > 0 && is_separator(str[str.size() - 1])) + return str.size() - 1; + + size_t pos = str.find_last_of(separators, str.size() - 1); + +#ifdef LLVM_ON_WIN32 + if (pos == StringRef::npos) + pos = str.find_last_of(':', str.size() - 2); +#endif + + if (pos == StringRef::npos || + (pos == 1 && is_separator(str[0]))) + return 0; + + return pos + 1; + } + + size_t root_dir_start(StringRef str) { + // case "c:/" +#ifdef LLVM_ON_WIN32 + if (str.size() > 2 && + str[1] == ':' && + is_separator(str[2])) + return 2; +#endif + + // case "//" + if (str.size() == 2 && + is_separator(str[0]) && + str[0] == str[1]) + return StringRef::npos; + + // case "//net" + if (str.size() > 3 && + is_separator(str[0]) && + str[0] == str[1] && + !is_separator(str[2])) { + return str.find_first_of(separators, 2); + } + + // case "/" + if (str.size() > 0 && is_separator(str[0])) + return 0; + + return StringRef::npos; + } + + size_t parent_path_end(StringRef path) { + size_t end_pos = filename_pos(path); + + bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]); + + // Skip separators except for root dir. + size_t root_dir_pos = root_dir_start(path.substr(0, end_pos)); + + while(end_pos > 0 && + (end_pos - 1) != root_dir_pos && + is_separator(path[end_pos - 1])) + --end_pos; + + if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep) + return StringRef::npos; + + return end_pos; + } +} // end unnamed namespace + +namespace llvm { +namespace sys { +namespace path { + +const_iterator begin(StringRef path) { + const_iterator i; + i.Path = path; + i.Component = find_first_component(path); + i.Position = 0; + return i; +} + +const_iterator end(StringRef path) { + const_iterator i; + i.Path = path; + i.Position = path.size(); + return i; +} + +const_iterator &const_iterator::operator++() { + assert(Position < Path.size() && "Tried to increment past end!"); + + // Increment Position to past the current component + Position += Component.size(); + + // Check for end. + if (Position == Path.size()) { + Component = StringRef(); + return *this; + } + + // Both POSIX and Windows treat paths that begin with exactly two separators + // specially. + bool was_net = Component.size() > 2 && + is_separator(Component[0]) && + Component[1] == Component[0] && + !is_separator(Component[2]); + + // Handle separators. + if (is_separator(Path[Position])) { + // Root dir. + if (was_net +#ifdef LLVM_ON_WIN32 + // c:/ + || Component.endswith(":") +#endif + ) { + Component = Path.substr(Position, 1); + return *this; + } + + // Skip extra separators. + while (Position != Path.size() && + is_separator(Path[Position])) { + ++Position; + } + + // Treat trailing '/' as a '.'. + if (Position == Path.size()) { + --Position; + Component = "."; + return *this; + } + } + + // Find next component. + size_t end_pos = Path.find_first_of(separators, Position); + Component = Path.slice(Position, end_pos); + + return *this; +} + +const_iterator &const_iterator::operator--() { + // If we're at the end and the previous char was a '/', return '.'. + if (Position == Path.size() && + Path.size() > 1 && + is_separator(Path[Position - 1]) +#ifdef LLVM_ON_WIN32 + && Path[Position - 2] != ':' +#endif + ) { + --Position; + Component = "."; + return *this; + } + + // Skip separators unless it's the root directory. + size_t root_dir_pos = root_dir_start(Path); + size_t end_pos = Position; + + while(end_pos > 0 && + (end_pos - 1) != root_dir_pos && + is_separator(Path[end_pos - 1])) + --end_pos; + + // Find next separator. + size_t start_pos = filename_pos(Path.substr(0, end_pos)); + Component = Path.slice(start_pos, end_pos); + Position = start_pos; + return *this; +} + +bool const_iterator::operator==(const const_iterator &RHS) const { + return Path.begin() == RHS.Path.begin() && + Position == RHS.Position; +} + +bool const_iterator::operator!=(const const_iterator &RHS) const { + return !(*this == RHS); +} + +ptrdiff_t const_iterator::operator-(const const_iterator &RHS) const { + return Position - RHS.Position; +} + +const StringRef root_path(StringRef path) { + const_iterator b = begin(path), + pos = b, + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if (has_net || has_drive) { + if ((++pos != e) && is_separator((*pos)[0])) { + // {C:/,//net/}, so get the first two components. + return path.substr(0, b->size() + pos->size()); + } else { + // just {C:,//net}, return the first component. + return *b; + } + } + + // POSIX style root directory. + if (is_separator((*b)[0])) { + return *b; + } + } + + return StringRef(); +} + +const StringRef root_name(StringRef path) { + const_iterator b = begin(path), + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if (has_net || has_drive) { + // just {C:,//net}, return the first component. + return *b; + } + } + + // No path or no name. + return StringRef(); +} + +const StringRef root_directory(StringRef path) { + const_iterator b = begin(path), + pos = b, + e = end(path); + if (b != e) { + bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0]; + bool has_drive = +#ifdef LLVM_ON_WIN32 + b->endswith(":"); +#else + false; +#endif + + if ((has_net || has_drive) && + // {C:,//net}, skip to the next component. + (++pos != e) && is_separator((*pos)[0])) { + return *pos; + } + + // POSIX style root directory. + if (!has_net && is_separator((*b)[0])) { + return *b; + } + } + + // No path or no root. + return StringRef(); +} + +const StringRef relative_path(StringRef path) { + StringRef root = root_path(path); + return root.substr(root.size()); +} + +void append(SmallVectorImpl &path, const Twine &a, + const Twine &b, + const Twine &c, + const Twine &d) { + SmallString<32> a_storage; + SmallString<32> b_storage; + SmallString<32> c_storage; + SmallString<32> d_storage; + + SmallVector components; + if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage)); + if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage)); + if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage)); + if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage)); + + for (SmallVectorImpl::const_iterator i = components.begin(), + e = components.end(); + i != e; ++i) { + bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]); + bool component_has_sep = !i->empty() && is_separator((*i)[0]); + bool is_root_name = has_root_name(*i); + + if (path_has_sep) { + // Strip separators from beginning of component. + size_t loc = i->find_first_not_of(separators); + StringRef c = i->substr(loc); + + // Append it. + path.append(c.begin(), c.end()); + continue; + } + + if (!component_has_sep && !(path.empty() || is_root_name)) { + // Add a separator. + path.push_back(prefered_separator); + } + + path.append(i->begin(), i->end()); + } +} + +void append(SmallVectorImpl &path, + const_iterator begin, const_iterator end) { + for (; begin != end; ++begin) + path::append(path, *begin); +} + +const StringRef parent_path(StringRef path) { + size_t end_pos = parent_path_end(path); + if (end_pos == StringRef::npos) + return StringRef(); + else + return path.substr(0, end_pos); +} + +void remove_filename(SmallVectorImpl &path) { + size_t end_pos = parent_path_end(StringRef(path.begin(), path.size())); + if (end_pos != StringRef::npos) + path.set_size(end_pos); +} + +void replace_extension(SmallVectorImpl &path, const Twine &extension) { + StringRef p(path.begin(), path.size()); + SmallString<32> ext_storage; + StringRef ext = extension.toStringRef(ext_storage); + + // Erase existing extension. + size_t pos = p.find_last_of('.'); + if (pos != StringRef::npos && pos >= filename_pos(p)) + path.set_size(pos); + + // Append '.' if needed. + if (ext.size() > 0 && ext[0] != '.') + path.push_back('.'); + + // Append extension. + path.append(ext.begin(), ext.end()); +} + +void native(const Twine &path, SmallVectorImpl &result) { + // Clear result. + result.clear(); +#ifdef LLVM_ON_WIN32 + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + result.reserve(p.size()); + for (StringRef::const_iterator i = p.begin(), + e = p.end(); + i != e; + ++i) { + if (*i == '/') + result.push_back('\\'); + else + result.push_back(*i); + } +#else + path.toVector(result); +#endif +} + +const StringRef filename(StringRef path) { + return *(--end(path)); +} + +const StringRef stem(StringRef path) { + StringRef fname = filename(path); + size_t pos = fname.find_last_of('.'); + if (pos == StringRef::npos) + return fname; + else + if ((fname.size() == 1 && fname == ".") || + (fname.size() == 2 && fname == "..")) + return fname; + else + return fname.substr(0, pos); +} + +const StringRef extension(StringRef path) { + StringRef fname = filename(path); + size_t pos = fname.find_last_of('.'); + if (pos == StringRef::npos) + return StringRef(); + else + if ((fname.size() == 1 && fname == ".") || + (fname.size() == 2 && fname == "..")) + return StringRef(); + else + return fname.substr(pos); +} + +bool is_separator(char value) { + switch(value) { +#ifdef LLVM_ON_WIN32 + case '\\': // fall through +#endif + case '/': return true; + default: return false; + } +} + +bool has_root_name(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_name(p).empty(); +} + +bool has_root_directory(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_directory(p).empty(); +} + +bool has_root_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !root_path(p).empty(); +} + +bool has_relative_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !relative_path(p).empty(); +} + +bool has_filename(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !filename(p).empty(); +} + +bool has_parent_path(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !parent_path(p).empty(); +} + +bool has_stem(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !stem(p).empty(); +} + +bool has_extension(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + return !extension(p).empty(); +} + +bool is_absolute(const Twine &path) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + bool rootDir = has_root_directory(p), +#ifdef LLVM_ON_WIN32 + rootName = has_root_name(p); +#else + rootName = true; +#endif + + return rootDir && rootName; +} + +bool is_relative(const Twine &path) { + return !is_absolute(path); +} + +} // end namespace path + +namespace fs { + +error_code make_absolute(SmallVectorImpl &path) { + StringRef p(path.data(), path.size()); + + bool rootName = path::has_root_name(p), + rootDirectory = path::has_root_directory(p); + + // Already absolute. + if (rootName && rootDirectory) + return success; + + // All of the following conditions will need the current directory. + SmallString<128> current_dir; + if (error_code ec = current_path(current_dir)) return ec; + + // Relative path. Prepend the current directory. + if (!rootName && !rootDirectory) { + // Append path to the current directory. + path::append(current_dir, p); + // Set path to the result. + path.swap(current_dir); + return success; + } + + if (!rootName && rootDirectory) { + StringRef cdrn = path::root_name(current_dir); + SmallString<128> curDirRootName(cdrn.begin(), cdrn.end()); + path::append(curDirRootName, p); + // Set path to the result. + path.swap(curDirRootName); + return success; + } + + if (rootName && !rootDirectory) { + StringRef pRootName = path::root_name(p); + StringRef bRootDirectory = path::root_directory(current_dir); + StringRef bRelativePath = path::relative_path(current_dir); + StringRef pRelativePath = path::relative_path(p); + + SmallString<128> res; + path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath); + path.swap(res); + return success; + } + + llvm_unreachable("All rootName and rootDirectory combinations should have " + "occurred above!"); +} + +error_code create_directories(const Twine &path, bool &existed) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + StringRef parent = path::parent_path(p); + bool parent_exists; + + if (error_code ec = fs::exists(parent, parent_exists)) return ec; + + if (!parent_exists) + return create_directories(parent, existed); + + return create_directory(p, existed); +} + +bool exists(file_status status) { + return status_known(status) && status.type() != file_type::file_not_found; +} + +bool status_known(file_status s) { + return s.type() != file_type::status_error; +} + +bool is_directory(file_status status) { + return status.type() == file_type::directory_file; +} + +error_code is_directory(const Twine &path, bool &result) { + file_status st; + if (error_code ec = status(path, st)) + return ec; + result = is_directory(st); + return success; +} + +bool is_regular_file(file_status status) { + return status.type() == file_type::regular_file; +} + +error_code is_regular_file(const Twine &path, bool &result) { + file_status st; + if (error_code ec = status(path, st)) + return ec; + result = is_regular_file(st); + return success; +} + +bool is_symlink(file_status status) { + return status.type() == file_type::symlink_file; +} + +error_code is_symlink(const Twine &path, bool &result) { + file_status st; + if (error_code ec = status(path, st)) + return ec; + result = is_symlink(st); + return success; +} + +bool is_other(file_status status) { + return exists(status) && + !is_regular_file(status) && + !is_directory(status) && + !is_symlink(status); +} + +void directory_entry::replace_filename(const Twine &filename, file_status st, + file_status symlink_st) { + SmallString<128> path(Path.begin(), Path.end()); + path::remove_filename(path); + path::append(path, filename); + Path = path.str(); + Status = st; + SymlinkStatus = symlink_st; +} + +error_code has_magic(const Twine &path, const Twine &magic, bool &result) { + SmallString<32> MagicStorage; + StringRef Magic = magic.toStringRef(MagicStorage); + SmallString<32> Buffer; + + if (error_code ec = get_magic(path, Magic.size(), Buffer)) { + if (ec == errc::value_too_large) { + // Magic.size() > file_size(Path). + result = false; + return success; + } + return ec; + } + + result = Magic == Buffer; + return success; +} + +error_code identify_magic(const Twine &path, LLVMFileType &result) { + SmallString<32> Magic; + error_code ec = get_magic(path, Magic.capacity(), Magic); + if (ec && ec != errc::value_too_large) + return ec; + + result = IdentifyFileType(Magic.data(), Magic.size()); + return success; +} + +namespace { +error_code remove_all_r(StringRef path, file_type ft, uint32_t &count) { + if (ft == file_type::directory_file) { + // This code would be a lot better with exceptions ;/. + error_code ec; + for (directory_iterator i(path, ec), e; i != e; i.increment(ec)) { + if (ec) return ec; + file_status st; + if (error_code ec = i->status(st)) return ec; + if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec; + } + bool obviously_this_exists; + if (error_code ec = remove(path, obviously_this_exists)) return ec; + assert(obviously_this_exists); + ++count; // Include the directory itself in the items removed. + } else { + bool obviously_this_exists; + if (error_code ec = remove(path, obviously_this_exists)) return ec; + assert(obviously_this_exists); + ++count; + } + + return success; +} +} // end unnamed namespace + +error_code remove_all(const Twine &path, uint32_t &num_removed) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + file_status fs; + if (error_code ec = status(path, fs)) + return ec; + num_removed = 0; + return remove_all_r(p, fs.type(), num_removed); +} + +error_code directory_entry::status(file_status &result) const { + return fs::status(Path, result); +} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +// Include the truly platform-specific parts. +#if defined(LLVM_ON_UNIX) +#include "Unix/PathV2.inc" +#endif +#if defined(LLVM_ON_WIN32) +#include "Windows/PathV2.inc" +#endif diff --git a/final/lib/Support/PluginLoader.cpp b/final/lib/Support/PluginLoader.cpp new file mode 100644 index 00000000000..2924cfa3889 --- /dev/null +++ b/final/lib/Support/PluginLoader.cpp @@ -0,0 +1,47 @@ +//===-- PluginLoader.cpp - Implement -load command line option ------------===// +// +// 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 -load command line option handler. +// +//===----------------------------------------------------------------------===// + +#define DONT_GET_PLUGIN_LOADER_OPTION +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PluginLoader.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Mutex.h" +#include +using namespace llvm; + +static ManagedStatic > Plugins; +static ManagedStatic > PluginsLock; + +void PluginLoader::operator=(const std::string &Filename) { + sys::SmartScopedLock Lock(*PluginsLock); + std::string Error; + if (sys::DynamicLibrary::LoadLibraryPermanently(Filename.c_str(), &Error)) { + errs() << "Error opening '" << Filename << "': " << Error + << "\n -load request ignored.\n"; + } else { + Plugins->push_back(Filename); + } +} + +unsigned PluginLoader::getNumPlugins() { + sys::SmartScopedLock Lock(*PluginsLock); + return Plugins.isConstructed() ? Plugins->size() : 0; +} + +std::string &PluginLoader::getPlugin(unsigned num) { + sys::SmartScopedLock Lock(*PluginsLock); + assert(Plugins.isConstructed() && num < Plugins->size() && + "Asking for an out of bounds plugin"); + return (*Plugins)[num]; +} diff --git a/final/lib/Support/PrettyStackTrace.cpp b/final/lib/Support/PrettyStackTrace.cpp new file mode 100644 index 00000000000..a9f4709e4b9 --- /dev/null +++ b/final/lib/Support/PrettyStackTrace.cpp @@ -0,0 +1,133 @@ +//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/ThreadLocal.h" +#include "llvm/ADT/SmallString.h" + +#ifdef HAVE_CRASHREPORTERCLIENT_H +#include +#endif + +using namespace llvm; + +namespace llvm { + bool DisablePrettyStackTrace = false; +} + +// FIXME: This should be thread local when llvm supports threads. +static sys::ThreadLocal PrettyStackTraceHead; + +static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ + unsigned NextID = 0; + if (Entry->getNextEntry()) + NextID = PrintStack(Entry->getNextEntry(), OS); + OS << NextID << ".\t"; + Entry->print(OS); + + return NextID+1; +} + +/// PrintCurStackTrace - Print the current stack trace to the specified stream. +static void PrintCurStackTrace(raw_ostream &OS) { + // Don't print an empty trace. + if (PrettyStackTraceHead.get() == 0) return; + + // If there are pretty stack frames registered, walk and emit them. + OS << "Stack dump:\n"; + + PrintStack(PrettyStackTraceHead.get(), OS); + OS.flush(); +} + +// Integrate with crash reporter libraries. +#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H +// If any clients of llvm try to link to libCrashReporterClient.a themselves, +// only one crash info struct will be used. +extern "C" { +CRASH_REPORTER_CLIENT_HIDDEN +struct crashreporter_annotations_t gCRAnnotations + __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) + = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0 }; +} +#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO +static const char *__crashreporter_info__ = 0; +asm(".desc ___crashreporter_info__, 0x10"); +#endif + + +/// CrashHandler - This callback is run if a fatal signal is delivered to the +/// process, it prints the pretty stack trace. +static void CrashHandler(void *) { +#ifndef __APPLE__ + // On non-apple systems, just emit the crash stack trace to stderr. + PrintCurStackTrace(errs()); +#else + // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also + // put it into __crashreporter_info__. + SmallString<2048> TmpStr; + { + raw_svector_ostream Stream(TmpStr); + PrintCurStackTrace(Stream); + } + + if (!TmpStr.empty()) { +#ifdef HAVE_CRASHREPORTERCLIENT_H + // Cast to void to avoid warning. + (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str()); +#elif HAVE_CRASHREPORTER_INFO + __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); +#endif + errs() << TmpStr.str(); + } + +#endif +} + +static bool RegisterCrashPrinter() { + if (!DisablePrettyStackTrace) + sys::AddSignalHandler(CrashHandler, 0); + return false; +} + +PrettyStackTraceEntry::PrettyStackTraceEntry() { + // The first time this is called, we register the crash printer. + static bool HandlerRegistered = RegisterCrashPrinter(); + (void)HandlerRegistered; + + // Link ourselves. + NextEntry = PrettyStackTraceHead.get(); + PrettyStackTraceHead.set(this); +} + +PrettyStackTraceEntry::~PrettyStackTraceEntry() { + assert(PrettyStackTraceHead.get() == this && + "Pretty stack trace entry destruction is out of order"); + PrettyStackTraceHead.set(getNextEntry()); +} + +void PrettyStackTraceString::print(raw_ostream &OS) const { + OS << Str << "\n"; +} + +void PrettyStackTraceProgram::print(raw_ostream &OS) const { + OS << "Program arguments: "; + // Print the argument list. + for (unsigned i = 0, e = ArgC; i != e; ++i) + OS << ArgV[i] << ' '; + OS << '\n'; +} diff --git a/final/lib/Support/Process.cpp b/final/lib/Support/Process.cpp new file mode 100644 index 00000000000..88ca7c3f220 --- /dev/null +++ b/final/lib/Support/Process.cpp @@ -0,0 +1,33 @@ +//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Process concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Process.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Process.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Process.inc" +#endif diff --git a/final/lib/Support/Program.cpp b/final/lib/Support/Program.cpp new file mode 100644 index 00000000000..01860b082d6 --- /dev/null +++ b/final/lib/Support/Program.cpp @@ -0,0 +1,56 @@ +//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file implements the operating system Program concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Program.h" +#include "llvm/Config/config.h" +using namespace llvm; +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +int +Program::ExecuteAndWait(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned secondsToWait, + unsigned memoryLimit, + std::string* ErrMsg) { + Program prg; + if (prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg)) + return prg.Wait(path, secondsToWait, ErrMsg); + else + return -1; +} + +void +Program::ExecuteNoWait(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned memoryLimit, + std::string* ErrMsg) { + Program prg; + prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg); +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Program.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Program.inc" +#endif diff --git a/final/lib/Support/README.txt.system b/final/lib/Support/README.txt.system new file mode 100644 index 00000000000..7a906b8dba4 --- /dev/null +++ b/final/lib/Support/README.txt.system @@ -0,0 +1,43 @@ +Design Of lib/System +==================== + +The software in this directory is designed to completely shield LLVM from any +and all operating system specific functionality. It is not intended to be a +complete operating system wrapper (such as ACE), but only to provide the +functionality necessary to support LLVM. + +The software located here, of necessity, has very specific and stringent design +rules. Violation of these rules means that cracks in the shield could form and +the primary goal of the library is defeated. By consistently using this library, +LLVM becomes more easily ported to new platforms since the only thing requiring +porting is this library. + +Complete documentation for the library can be found in the file: + llvm/docs/SystemLibrary.html +or at this URL: + http://llvm.org/docs/SystemLibrary.html + +While we recommend that you read the more detailed documentation, for the +impatient, here's a high level summary of the library's requirements. + + 1. No system header files are to be exposed through the interface. + 2. Std C++ and Std C header files are okay to be exposed through the interface. + 3. No exposed system-specific functions. + 4. No exposed system-specific data. + 5. Data in lib/System classes must use only simple C++ intrinsic types. + 6. Errors are handled by returning "true" and setting an optional std::string + 7. Library must not throw any exceptions, period. + 8. Interface functions must not have throw() specifications. + 9. No duplicate function impementations are permitted within an operating + system class. + +To accomplish these requirements, the library has numerous design criteria that +must be satisfied. Here's a high level summary of the library's design criteria: + + 1. No unused functionality (only what LLVM needs) + 2. High-Level Interfaces + 3. Use Opaque Classes + 4. Common Implementations + 5. Multiple Implementations + 6. Minimize Memory Allocation + 7. No Virtual Methods diff --git a/final/lib/Support/RWMutex.cpp b/final/lib/Support/RWMutex.cpp new file mode 100644 index 00000000000..fc02f9cf7c1 --- /dev/null +++ b/final/lib/Support/RWMutex.cpp @@ -0,0 +1,157 @@ +//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/Support/RWMutex.h" +#include + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +RWMutexImpl::RWMutexImpl() { } +RWMutexImpl::~RWMutexImpl() { } +bool RWMutexImpl::reader_acquire() { return true; } +bool RWMutexImpl::reader_release() { return true; } +bool RWMutexImpl::writer_acquire() { return true; } +bool RWMutexImpl::writer_release() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) + +#include +#include +#include + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_rwlock_init does have an address, then rwlock support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_rwlock_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a RWMutex using pthread calls +RWMutexImpl::RWMutexImpl() + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_rwlock data structures + pthread_rwlock_t* rwlock = + static_cast(malloc(sizeof(pthread_rwlock_t))); + +#ifdef __APPLE__ + // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. + bzero(rwlock, sizeof(pthread_rwlock_t)); +#endif + + // Initialize the rwlock + int errorcode = pthread_rwlock_init(rwlock, NULL); + (void)errorcode; + assert(errorcode == 0); + + // Assign the data member + data_ = rwlock; + } +} + +// Destruct a RWMutex +RWMutexImpl::~RWMutexImpl() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + pthread_rwlock_destroy(rwlock); + free(rwlock); + } +} + +bool +RWMutexImpl::reader_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_rdlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::reader_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::writer_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_wrlock(rwlock); + return errorcode == 0; + } else return false; +} + +bool +RWMutexImpl::writer_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } else return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/RWMutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Windows/RWMutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif diff --git a/final/lib/Support/Regex.cpp b/final/lib/Support/Regex.cpp new file mode 100644 index 00000000000..309ffb02dec --- /dev/null +++ b/final/lib/Support/Regex.cpp @@ -0,0 +1,168 @@ +//===-- Regex.cpp - Regular Expression matcher implementation -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a POSIX regular expression matcher. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Regex.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallVector.h" +#include "regex_impl.h" +#include +using namespace llvm; + +Regex::Regex(StringRef regex, unsigned Flags) { + unsigned flags = 0; + preg = new llvm_regex(); + preg->re_endp = regex.end(); + if (Flags & IgnoreCase) + flags |= REG_ICASE; + if (Flags & Newline) + flags |= REG_NEWLINE; + error = llvm_regcomp(preg, regex.data(), flags|REG_EXTENDED|REG_PEND); +} + +Regex::~Regex() { + llvm_regfree(preg); + delete preg; +} + +bool Regex::isValid(std::string &Error) { + if (!error) + return true; + + size_t len = llvm_regerror(error, preg, NULL, 0); + + Error.resize(len); + llvm_regerror(error, preg, &Error[0], len); + return false; +} + +/// getNumMatches - In a valid regex, return the number of parenthesized +/// matches it contains. +unsigned Regex::getNumMatches() const { + return preg->re_nsub; +} + +bool Regex::match(StringRef String, SmallVectorImpl *Matches){ + unsigned nmatch = Matches ? preg->re_nsub+1 : 0; + + // pmatch needs to have at least one element. + SmallVector pm; + pm.resize(nmatch > 0 ? nmatch : 1); + pm[0].rm_so = 0; + pm[0].rm_eo = String.size(); + + int rc = llvm_regexec(preg, String.data(), nmatch, pm.data(), REG_STARTEND); + + if (rc == REG_NOMATCH) + return false; + if (rc != 0) { + // regexec can fail due to invalid pattern or running out of memory. + error = rc; + return false; + } + + // There was a match. + + if (Matches) { // match position requested + Matches->clear(); + + for (unsigned i = 0; i != nmatch; ++i) { + if (pm[i].rm_so == -1) { + // this group didn't match + Matches->push_back(StringRef()); + continue; + } + assert(pm[i].rm_eo > pm[i].rm_so); + Matches->push_back(StringRef(String.data()+pm[i].rm_so, + pm[i].rm_eo-pm[i].rm_so)); + } + } + + return true; +} + +std::string Regex::sub(StringRef Repl, StringRef String, + std::string *Error) { + SmallVector Matches; + + // Reset error, if given. + if (Error && !Error->empty()) *Error = ""; + + // Return the input if there was no match. + if (!match(String, &Matches)) + return String; + + // Otherwise splice in the replacement string, starting with the prefix before + // the match. + std::string Res(String.begin(), Matches[0].begin()); + + // Then the replacement string, honoring possible substitutions. + while (!Repl.empty()) { + // Skip to the next escape. + std::pair Split = Repl.split('\\'); + + // Add the skipped substring. + Res += Split.first; + + // Check for terminimation and trailing backslash. + if (Split.second.empty()) { + if (Repl.size() != Split.first.size() && + Error && Error->empty()) + *Error = "replacement string contained trailing backslash"; + break; + } + + // Otherwise update the replacement string and interpret escapes. + Repl = Split.second; + + // FIXME: We should have a StringExtras function for mapping C99 escapes. + switch (Repl[0]) { + // Treat all unrecognized characters as self-quoting. + default: + Res += Repl[0]; + Repl = Repl.substr(1); + break; + + // Single character escapes. + case 't': + Res += '\t'; + Repl = Repl.substr(1); + break; + case 'n': + Res += '\n'; + Repl = Repl.substr(1); + break; + + // Decimal escapes are backreferences. + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + // Extract the backreference number. + StringRef Ref = Repl.slice(0, Repl.find_first_not_of("0123456789")); + Repl = Repl.substr(Ref.size()); + + unsigned RefValue; + if (!Ref.getAsInteger(10, RefValue) && + RefValue < Matches.size()) + Res += Matches[RefValue]; + else if (Error && Error->empty()) + *Error = "invalid backreference string '" + Ref.str() + "'"; + break; + } + } + } + + // And finally the suffix. + Res += StringRef(Matches[0].end(), String.end() - Matches[0].end()); + + return Res; +} diff --git a/final/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/final/lib/Support/SearchForAddressOfSpecialSymbol.cpp new file mode 100644 index 00000000000..d63830185c3 --- /dev/null +++ b/final/lib/Support/SearchForAddressOfSpecialSymbol.cpp @@ -0,0 +1,73 @@ +//===- SearchForAddressOfSpecialSymbol.cpp - Function addresses -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file pulls the addresses of certain symbols out of the linker. It must +// include as few header files as possible because it declares the symbols as +// void*, which would conflict with the actual symbol type if any header +// declared it. +// +//===----------------------------------------------------------------------===// + +#include + +// Must declare the symbols in the global namespace. +static void *DoSearch(const char* symbolName) { +#define EXPLICIT_SYMBOL(SYM) \ + extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM + + // If this is darwin, it has some funky issues, try to solve them here. Some + // important symbols are marked 'private external' which doesn't allow + // SearchForAddressOfSymbol to find them. As such, we special case them here, + // there is only a small handful of them. + +#ifdef __APPLE__ + { + EXPLICIT_SYMBOL(__ashldi3); + EXPLICIT_SYMBOL(__ashrdi3); + EXPLICIT_SYMBOL(__cmpdi2); + EXPLICIT_SYMBOL(__divdi3); + EXPLICIT_SYMBOL(__fixdfdi); + EXPLICIT_SYMBOL(__fixsfdi); + EXPLICIT_SYMBOL(__fixunsdfdi); + EXPLICIT_SYMBOL(__fixunssfdi); + EXPLICIT_SYMBOL(__floatdidf); + EXPLICIT_SYMBOL(__floatdisf); + EXPLICIT_SYMBOL(__lshrdi3); + EXPLICIT_SYMBOL(__moddi3); + EXPLICIT_SYMBOL(__udivdi3); + EXPLICIT_SYMBOL(__umoddi3); + + // __eprintf is sometimes used for assert() handling on x86. + // + // FIXME: Currently disabled when using Clang, as we don't always have our + // runtime support libraries available. +#ifndef __clang__ +#ifdef __i386__ + EXPLICIT_SYMBOL(__eprintf); +#endif +#endif + } +#endif + +#ifdef __CYGWIN__ + { + EXPLICIT_SYMBOL(_alloca); + EXPLICIT_SYMBOL(__main); + } +#endif + +#undef EXPLICIT_SYMBOL + return 0; +} + +namespace llvm { +void *SearchForAddressOfSpecialSymbol(const char* symbolName) { + return DoSearch(symbolName); +} +} // namespace llvm diff --git a/final/lib/Support/Signals.cpp b/final/lib/Support/Signals.cpp new file mode 100644 index 00000000000..a3af37d5fe6 --- /dev/null +++ b/final/lib/Support/Signals.cpp @@ -0,0 +1,34 @@ +//===- Signals.cpp - Signal Handling support --------------------*- 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 some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Signals.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +} + +// Include the platform-specific parts of this class. +#ifdef LLVM_ON_UNIX +#include "Unix/Signals.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/Signals.inc" +#endif diff --git a/final/lib/Support/SmallPtrSet.cpp b/final/lib/Support/SmallPtrSet.cpp new file mode 100644 index 00000000000..504e6497a3c --- /dev/null +++ b/final/lib/Support/SmallPtrSet.cpp @@ -0,0 +1,226 @@ +//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===// +// +// 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 SmallPtrSet class. See SmallPtrSet.h for an +// overview of the algorithm. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/MathExtras.h" +#include + +using namespace llvm; + +void SmallPtrSetImpl::shrink_and_clear() { + assert(!isSmall() && "Can't shrink a small set!"); + free(CurArray); + + // Reduce the number of buckets. + CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32; + NumElements = NumTombstones = 0; + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * (CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + memset(CurArray, -1, CurArraySize*sizeof(void*)); + + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[CurArraySize] = 0; +} + +bool SmallPtrSetImpl::insert_imp(const void * Ptr) { + if (isSmall()) { + // Check to see if it is already in the set. + for (const void **APtr = SmallArray, **E = SmallArray+NumElements; + APtr != E; ++APtr) + if (*APtr == Ptr) + return false; + + // Nope, there isn't. If we stay small, just 'pushback' now. + if (NumElements < CurArraySize-1) { + SmallArray[NumElements++] = Ptr; + return true; + } + // Otherwise, hit the big set case, which will call grow. + } + + // If more than 3/4 of the array is full, grow. + if (NumElements*4 >= CurArraySize*3 || + CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) + Grow(); + + // Okay, we know we have space. Find a hash bucket. + const void **Bucket = const_cast(FindBucketFor(Ptr)); + if (*Bucket == Ptr) return false; // Already inserted, good. + + // Otherwise, insert it! + if (*Bucket == getTombstoneMarker()) + --NumTombstones; + *Bucket = Ptr; + ++NumElements; // Track density. + return true; +} + +bool SmallPtrSetImpl::erase_imp(const void * Ptr) { + if (isSmall()) { + // Check to see if it is in the set. + for (const void **APtr = SmallArray, **E = SmallArray+NumElements; + APtr != E; ++APtr) + if (*APtr == Ptr) { + // If it is in the set, replace this element. + *APtr = E[-1]; + E[-1] = getEmptyMarker(); + --NumElements; + return true; + } + + return false; + } + + // Okay, we know we have space. Find a hash bucket. + void **Bucket = const_cast(FindBucketFor(Ptr)); + if (*Bucket != Ptr) return false; // Not in the set? + + // Set this as a tombstone. + *Bucket = getTombstoneMarker(); + --NumElements; + ++NumTombstones; + return true; +} + +const void * const *SmallPtrSetImpl::FindBucketFor(const void *Ptr) const { + unsigned Bucket = Hash(Ptr); + unsigned ArraySize = CurArraySize; + unsigned ProbeAmt = 1; + const void *const *Array = CurArray; + const void *const *Tombstone = 0; + while (1) { + // Found Ptr's bucket? + if (Array[Bucket] == Ptr) + return Array+Bucket; + + // If we found an empty bucket, the pointer doesn't exist in the set. + // Return a tombstone if we've seen one so far, or the empty bucket if + // not. + if (Array[Bucket] == getEmptyMarker()) + return Tombstone ? Tombstone : Array+Bucket; + + // If this is a tombstone, remember it. If Ptr ends up not in the set, we + // prefer to return it than something that would require more probing. + if (Array[Bucket] == getTombstoneMarker() && !Tombstone) + Tombstone = Array+Bucket; // Remember the first tombstone found. + + // It's a hash collision or a tombstone. Reprobe. + Bucket = (Bucket + ProbeAmt++) & (ArraySize-1); + } +} + +/// Grow - Allocate a larger backing store for the buckets and move it over. +/// +void SmallPtrSetImpl::Grow() { + // Allocate at twice as many buckets, but at least 128. + unsigned OldSize = CurArraySize; + unsigned NewSize = OldSize < 64 ? 128 : OldSize*2; + + const void **OldBuckets = CurArray; + bool WasSmall = isSmall(); + + // Install the new array. Clear all the buckets to empty. + CurArray = (const void**)malloc(sizeof(void*) * (NewSize+1)); + assert(CurArray && "Failed to allocate memory?"); + CurArraySize = NewSize; + memset(CurArray, -1, NewSize*sizeof(void*)); + + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[NewSize] = 0; + + // Copy over all the elements. + if (WasSmall) { + // Small sets store their elements in order. + for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements; + BucketPtr != E; ++BucketPtr) { + const void *Elt = *BucketPtr; + *const_cast(FindBucketFor(Elt)) = const_cast(Elt); + } + } else { + // Copy over all valid entries. + for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize; + BucketPtr != E; ++BucketPtr) { + // Copy over the element if it is valid. + const void *Elt = *BucketPtr; + if (Elt != getTombstoneMarker() && Elt != getEmptyMarker()) + *const_cast(FindBucketFor(Elt)) = const_cast(Elt); + } + + free(OldBuckets); + NumTombstones = 0; + } +} + +SmallPtrSetImpl::SmallPtrSetImpl(const void **SmallStorage, + const SmallPtrSetImpl& that) { + SmallArray = SmallStorage; + + // If we're becoming small, prepare to insert into our stack space + if (that.isSmall()) { + CurArray = SmallArray; + // Otherwise, allocate new heap space (unless we were the same size) + } else { + CurArray = (const void**)malloc(sizeof(void*) * (that.CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + } + + // Copy over the new array size + CurArraySize = that.CurArraySize; + + // Copy over the contents from the other set + memcpy(CurArray, that.CurArray, sizeof(void*)*(CurArraySize+1)); + + NumElements = that.NumElements; + NumTombstones = that.NumTombstones; +} + +/// CopyFrom - implement operator= from a smallptrset that has the same pointer +/// type, but may have a different small size. +void SmallPtrSetImpl::CopyFrom(const SmallPtrSetImpl &RHS) { + if (isSmall() && RHS.isSmall()) + assert(CurArraySize == RHS.CurArraySize && + "Cannot assign sets with different small sizes"); + + // If we're becoming small, prepare to insert into our stack space + if (RHS.isSmall()) { + if (!isSmall()) + free(CurArray); + CurArray = SmallArray; + // Otherwise, allocate new heap space (unless we were the same size) + } else if (CurArraySize != RHS.CurArraySize) { + if (isSmall()) + CurArray = (const void**)malloc(sizeof(void*) * (RHS.CurArraySize+1)); + else + CurArray = (const void**)realloc(CurArray, sizeof(void*)*(RHS.CurArraySize+1)); + assert(CurArray && "Failed to allocate memory?"); + } + + // Copy over the new array size + CurArraySize = RHS.CurArraySize; + + // Copy over the contents from the other set + memcpy(CurArray, RHS.CurArray, sizeof(void*)*(CurArraySize+1)); + + NumElements = RHS.NumElements; + NumTombstones = RHS.NumTombstones; +} + +SmallPtrSetImpl::~SmallPtrSetImpl() { + if (!isSmall()) + free(CurArray); +} diff --git a/final/lib/Support/SmallVector.cpp b/final/lib/Support/SmallVector.cpp new file mode 100644 index 00000000000..a89f1495763 --- /dev/null +++ b/final/lib/Support/SmallVector.cpp @@ -0,0 +1,40 @@ +//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===// +// +// 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 SmallVector class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +/// grow_pod - This is an implementation of the grow() method which only works +/// on POD-like datatypes and is out of line to reduce code duplication. +void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) { + size_t CurSizeBytes = size_in_bytes(); + size_t NewCapacityInBytes = 2 * capacity_in_bytes() + TSize; // Always grow. + if (NewCapacityInBytes < MinSizeInBytes) + NewCapacityInBytes = MinSizeInBytes; + + void *NewElts; + if (this->isSmall()) { + NewElts = malloc(NewCapacityInBytes); + + // Copy the elements over. No need to run dtors on PODs. + memcpy(NewElts, this->BeginX, CurSizeBytes); + } else { + // If this wasn't grown from the inline copy, grow the allocated space. + NewElts = realloc(this->BeginX, NewCapacityInBytes); + } + + this->EndX = (char*)NewElts+CurSizeBytes; + this->BeginX = NewElts; + this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; +} + diff --git a/final/lib/Support/SourceMgr.cpp b/final/lib/Support/SourceMgr.cpp new file mode 100644 index 00000000000..ef099163c22 --- /dev/null +++ b/final/lib/Support/SourceMgr.cpp @@ -0,0 +1,230 @@ +//===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===// +// +// 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 SourceMgr class. This class is used as a simple +// substrate for diagnostics, #include handling, and other low level things for +// simple parsers. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +using namespace llvm; + +namespace { + struct LineNoCacheTy { + int LastQueryBufferID; + const char *LastQuery; + unsigned LineNoOfQuery; + }; +} + +static LineNoCacheTy *getCache(void *Ptr) { + return (LineNoCacheTy*)Ptr; +} + + +SourceMgr::~SourceMgr() { + // Delete the line # cache if allocated. + if (LineNoCacheTy *Cache = getCache(LineNoCache)) + delete Cache; + + while (!Buffers.empty()) { + delete Buffers.back().Buffer; + Buffers.pop_back(); + } +} + +/// AddIncludeFile - Search for a file with the specified name in the current +/// directory or in one of the IncludeDirs. If no file is found, this returns +/// ~0, otherwise it returns the buffer ID of the stacked file. +unsigned SourceMgr::AddIncludeFile(const std::string &Filename, + SMLoc IncludeLoc) { + OwningPtr NewBuf; + MemoryBuffer::getFile(Filename.c_str(), NewBuf); + + // If the file didn't exist directly, see if it's in an include path. + for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBuf; ++i) { + std::string IncFile = IncludeDirectories[i] + "/" + Filename; + MemoryBuffer::getFile(IncFile.c_str(), NewBuf); + } + + if (NewBuf == 0) return ~0U; + + return AddNewSourceBuffer(NewBuf.take(), IncludeLoc); +} + + +/// FindBufferContainingLoc - Return the ID of the buffer containing the +/// specified location, returning -1 if not found. +int SourceMgr::FindBufferContainingLoc(SMLoc Loc) const { + for (unsigned i = 0, e = Buffers.size(); i != e; ++i) + if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() && + // Use <= here so that a pointer to the null at the end of the buffer + // is included as part of the buffer. + Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd()) + return i; + return -1; +} + +/// FindLineNumber - Find the line number for the specified location in the +/// specified file. This is not a fast method. +unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const { + if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc); + assert(BufferID != -1 && "Invalid Location!"); + + MemoryBuffer *Buff = getBufferInfo(BufferID).Buffer; + + // Count the number of \n's between the start of the file and the specified + // location. + unsigned LineNo = 1; + + const char *Ptr = Buff->getBufferStart(); + + // If we have a line number cache, and if the query is to a later point in the + // same file, start searching from the last query location. This optimizes + // for the case when multiple diagnostics come out of one file in order. + if (LineNoCacheTy *Cache = getCache(LineNoCache)) + if (Cache->LastQueryBufferID == BufferID && + Cache->LastQuery <= Loc.getPointer()) { + Ptr = Cache->LastQuery; + LineNo = Cache->LineNoOfQuery; + } + + // Scan for the location being queried, keeping track of the number of lines + // we see. + for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr) + if (*Ptr == '\n') ++LineNo; + + + // Allocate the line number cache if it doesn't exist. + if (LineNoCache == 0) + LineNoCache = new LineNoCacheTy(); + + // Update the line # cache. + LineNoCacheTy &Cache = *getCache(LineNoCache); + Cache.LastQueryBufferID = BufferID; + Cache.LastQuery = Ptr; + Cache.LineNoOfQuery = LineNo; + return LineNo; +} + +void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const { + if (IncludeLoc == SMLoc()) return; // Top of stack. + + int CurBuf = FindBufferContainingLoc(IncludeLoc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); + + OS << "Included from " + << getBufferInfo(CurBuf).Buffer->getBufferIdentifier() + << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n"; +} + + +/// GetMessage - Return an SMDiagnostic at the specified location with the +/// specified string. +/// +/// @param Type - If non-null, the kind of message (e.g., "error") which is +/// prefixed to the message. +SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, const Twine &Msg, + const char *Type, bool ShowLine) const { + + // First thing to do: find the current buffer containing the specified + // location. + int CurBuf = FindBufferContainingLoc(Loc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + + MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer; + + // Scan backward to find the start of the line. + const char *LineStart = Loc.getPointer(); + while (LineStart != CurMB->getBufferStart() && + LineStart[-1] != '\n' && LineStart[-1] != '\r') + --LineStart; + + std::string LineStr; + if (ShowLine) { + // Get the end of the line. + const char *LineEnd = Loc.getPointer(); + while (LineEnd != CurMB->getBufferEnd() && + LineEnd[0] != '\n' && LineEnd[0] != '\r') + ++LineEnd; + LineStr = std::string(LineStart, LineEnd); + } + + std::string PrintedMsg; + raw_string_ostream OS(PrintedMsg); + if (Type) + OS << Type << ": "; + OS << Msg; + + return SMDiagnostic(*this, Loc, + CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), + Loc.getPointer()-LineStart, OS.str(), + LineStr, ShowLine); +} + +void SourceMgr::PrintMessage(SMLoc Loc, const Twine &Msg, + const char *Type, bool ShowLine) const { + // Report the message with the diagnostic handler if present. + if (DiagHandler) { + DiagHandler(GetMessage(Loc, Msg, Type, ShowLine), DiagContext); + return; + } + + raw_ostream &OS = errs(); + + int CurBuf = FindBufferContainingLoc(Loc); + assert(CurBuf != -1 && "Invalid or unspecified location!"); + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); + + GetMessage(Loc, Msg, Type, ShowLine).Print(0, OS); +} + +//===----------------------------------------------------------------------===// +// SMDiagnostic Implementation +//===----------------------------------------------------------------------===// + +void SMDiagnostic::Print(const char *ProgName, raw_ostream &S) const { + if (ProgName && ProgName[0]) + S << ProgName << ": "; + + if (!Filename.empty()) { + if (Filename == "-") + S << ""; + else + S << Filename; + + if (LineNo != -1) { + S << ':' << LineNo; + if (ColumnNo != -1) + S << ':' << (ColumnNo+1); + } + S << ": "; + } + + S << Message << '\n'; + + if (LineNo != -1 && ColumnNo != -1 && ShowLine) { + S << LineContents << '\n'; + + // Print out spaces/tabs before the caret. + for (unsigned i = 0; i != unsigned(ColumnNo); ++i) + S << (LineContents[i] == '\t' ? '\t' : ' '); + S << "^\n"; + } +} + + diff --git a/final/lib/Support/Statistic.cpp b/final/lib/Support/Statistic.cpp new file mode 100644 index 00000000000..1e733d92e61 --- /dev/null +++ b/final/lib/Support/Statistic.cpp @@ -0,0 +1,152 @@ +//===-- Statistic.cpp - Easy way to expose stats information --------------===// +// +// 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 'Statistic' class, which is designed to be an easy +// way to expose various success metrics from passes. These statistics are +// printed at the end of a run, when the -stats command line option is enabled +// on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); +// +// Later, in the code: ++NumInstEliminated; +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Mutex.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +// CreateInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } + +/// -stats - Command line option to cause transformations to emit stats about +/// what they did. +/// +static cl::opt +Enabled("stats", cl::desc("Enable statistics output from program")); + + +namespace { +/// StatisticInfo - This class is used in a ManagedStatic so that it is created +/// on demand (when the first statistic is bumped) and destroyed only when +/// llvm_shutdown is called. We print statistics from the destructor. +class StatisticInfo { + std::vector Stats; + friend void llvm::PrintStatistics(); + friend void llvm::PrintStatistics(raw_ostream &OS); +public: + ~StatisticInfo(); + + void addStatistic(const Statistic *S) { + Stats.push_back(S); + } +}; +} + +static ManagedStatic StatInfo; +static ManagedStatic > StatLock; + +/// RegisterStatistic - The first time a statistic is bumped, this method is +/// called. +void Statistic::RegisterStatistic() { + // If stats are enabled, inform StatInfo that this statistic should be + // printed. + sys::SmartScopedLock Writer(*StatLock); + if (!Initialized) { + if (Enabled) + StatInfo->addStatistic(this); + + sys::MemoryFence(); + // Remember we have been registered. + Initialized = true; + } +} + +namespace { + +struct NameCompare { + bool operator()(const Statistic *LHS, const Statistic *RHS) const { + int Cmp = std::strcmp(LHS->getName(), RHS->getName()); + if (Cmp != 0) return Cmp < 0; + + // Secondary key is the description. + return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; + } +}; + +} + +// Print information when destroyed, iff command line option is specified. +StatisticInfo::~StatisticInfo() { + llvm::PrintStatistics(); +} + +void llvm::EnableStatistics() { + Enabled.setValue(true); +} + +bool llvm::AreStatisticsEnabled() { + return Enabled; +} + +void llvm::PrintStatistics(raw_ostream &OS) { + StatisticInfo &Stats = *StatInfo; + + // Figure out how long the biggest Value and Name fields are. + unsigned MaxNameLen = 0, MaxValLen = 0; + for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { + MaxValLen = std::max(MaxValLen, + (unsigned)utostr(Stats.Stats[i]->getValue()).size()); + MaxNameLen = std::max(MaxNameLen, + (unsigned)std::strlen(Stats.Stats[i]->getName())); + } + + // Sort the fields by name. + std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare()); + + // Print out the statistics header... + OS << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; + + // Print all of the statistics. + for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { + std::string CountStr = utostr(Stats.Stats[i]->getValue()); + OS << std::string(MaxValLen-CountStr.size(), ' ') + << CountStr << " " << Stats.Stats[i]->getName() + << std::string(MaxNameLen-std::strlen(Stats.Stats[i]->getName()), ' ') + << " - " << Stats.Stats[i]->getDesc() << "\n"; + } + + OS << '\n'; // Flush the output stream. + OS.flush(); + +} + +void llvm::PrintStatistics() { + StatisticInfo &Stats = *StatInfo; + + // Statistics not enabled? + if (Stats.Stats.empty()) return; + + // Get the stream to write to. + raw_ostream &OutStream = *CreateInfoOutputFile(); + PrintStatistics(OutStream); + delete &OutStream; // Close the file. +} diff --git a/final/lib/Support/StringExtras.cpp b/final/lib/Support/StringExtras.cpp new file mode 100644 index 00000000000..eb2fa084218 --- /dev/null +++ b/final/lib/Support/StringExtras.cpp @@ -0,0 +1,81 @@ +//===-- StringExtras.cpp - Implement the StringExtras header --------------===// +// +// 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 StringExtras.h header +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +/// StrInStrNoCase - Portable version of strcasestr. Locates the first +/// occurrence of string 's1' in string 's2', ignoring case. Returns +/// the offset of s2 in s1 or npos if s2 cannot be found. +StringRef::size_type llvm::StrInStrNoCase(StringRef s1, StringRef s2) { + size_t N = s2.size(), M = s1.size(); + if (N > M) + return StringRef::npos; + for (size_t i = 0, e = M - N + 1; i != e; ++i) + if (s1.substr(i, N).equals_lower(s2)) + return i; + return StringRef::npos; +} + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The function returns a pair containing the extracted token and the +/// remaining tail string. +std::pair llvm::getToken(StringRef Source, + StringRef Delimiters) { + // Figure out where the token starts. + StringRef::size_type Start = Source.find_first_not_of(Delimiters); + + // Find the next occurrence of the delimiter. + StringRef::size_type End = Source.find_first_of(Delimiters, Start); + + return std::make_pair(Source.slice(Start, End), Source.substr(End)); +} + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void llvm::SplitString(StringRef Source, + SmallVectorImpl &OutFragments, + StringRef Delimiters) { + StringRef S2, S; + tie(S2, S) = getToken(Source, Delimiters); + while (!S2.empty()) { + OutFragments.push_back(S2); + tie(S2, S) = getToken(S, Delimiters); + } +} + +void llvm::StringRef::split(SmallVectorImpl &A, + StringRef Separators, int MaxSplit, + bool KeepEmpty) const { + StringRef rest = *this; + + // rest.data() is used to distinguish cases like "a," that splits into + // "a" + "" and "a" that splits into "a" + 0. + for (int splits = 0; + rest.data() != NULL && (MaxSplit < 0 || splits < MaxSplit); + ++splits) { + std::pair p = rest.split(Separators); + + if (p.first.size() != 0 || KeepEmpty) + A.push_back(p.first); + rest = p.second; + } + // If we have a tail left, add it. + if (rest.data() != NULL && (rest.size() != 0 || KeepEmpty)) + A.push_back(rest); +} diff --git a/final/lib/Support/StringMap.cpp b/final/lib/Support/StringMap.cpp new file mode 100644 index 00000000000..90ec2995026 --- /dev/null +++ b/final/lib/Support/StringMap.cpp @@ -0,0 +1,215 @@ +//===--- StringMap.cpp - String Hash table map implementation -------------===// +// +// 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 StringMap class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringExtras.h" +#include +using namespace llvm; + +StringMapImpl::StringMapImpl(unsigned InitSize, unsigned itemSize) { + ItemSize = itemSize; + + // If a size is specified, initialize the table with that many buckets. + if (InitSize) { + init(InitSize); + return; + } + + // Otherwise, initialize it with zero buckets to avoid the allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; +} + +void StringMapImpl::init(unsigned InitSize) { + assert((InitSize & (InitSize-1)) == 0 && + "Init Size must be a power of 2 or zero!"); + NumBuckets = InitSize ? InitSize : 16; + NumItems = 0; + NumTombstones = 0; + + TheTable = (ItemBucket*)calloc(NumBuckets+1, sizeof(ItemBucket)); + + // Allocate one extra bucket, set it to look filled so the iterators stop at + // end. + TheTable[NumBuckets].Item = (StringMapEntryBase*)2; +} + + +/// LookupBucketFor - Look up the bucket that the specified string should end +/// up in. If it already exists as a key in the map, the Item pointer for the +/// specified bucket will be non-null. Otherwise, it will be null. In either +/// case, the FullHashValue field of the bucket will be set to the hash value +/// of the string. +unsigned StringMapImpl::LookupBucketFor(StringRef Name) { + unsigned HTSize = NumBuckets; + if (HTSize == 0) { // Hash table unallocated so far? + init(16); + HTSize = NumBuckets; + } + unsigned FullHashValue = HashString(Name); + unsigned BucketNo = FullHashValue & (HTSize-1); + + unsigned ProbeAmt = 1; + int FirstTombstone = -1; + while (1) { + ItemBucket &Bucket = TheTable[BucketNo]; + StringMapEntryBase *BucketItem = Bucket.Item; + // If we found an empty bucket, this key isn't in the table yet, return it. + if (BucketItem == 0) { + // If we found a tombstone, we want to reuse the tombstone instead of an + // empty bucket. This reduces probing. + if (FirstTombstone != -1) { + TheTable[FirstTombstone].FullHashValue = FullHashValue; + return FirstTombstone; + } + + Bucket.FullHashValue = FullHashValue; + return BucketNo; + } + + if (BucketItem == getTombstoneVal()) { + // Skip over tombstones. However, remember the first one we see. + if (FirstTombstone == -1) FirstTombstone = BucketNo; + } else if (Bucket.FullHashValue == FullHashValue) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because Name isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Name == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + + +/// FindKey - Look up the bucket that contains the specified key. If it exists +/// in the map, return the bucket number of the key. Otherwise return -1. +/// This does not modify the map. +int StringMapImpl::FindKey(StringRef Key) const { + unsigned HTSize = NumBuckets; + if (HTSize == 0) return -1; // Really empty table? + unsigned FullHashValue = HashString(Key); + unsigned BucketNo = FullHashValue & (HTSize-1); + + unsigned ProbeAmt = 1; + while (1) { + ItemBucket &Bucket = TheTable[BucketNo]; + StringMapEntryBase *BucketItem = Bucket.Item; + // If we found an empty bucket, this key isn't in the table yet, return. + if (BucketItem == 0) + return -1; + + if (BucketItem == getTombstoneVal()) { + // Ignore tombstones. + } else if (Bucket.FullHashValue == FullHashValue) { + // If the full hash value matches, check deeply for a match. The common + // case here is that we are only looking at the buckets (for item info + // being non-null and for the full hash value) not at the items. This + // is important for cache locality. + + // Do the comparison like this because NameStart isn't necessarily + // null-terminated! + char *ItemStr = (char*)BucketItem+ItemSize; + if (Key == StringRef(ItemStr, BucketItem->getKeyLength())) { + // We found a match! + return BucketNo; + } + } + + // Okay, we didn't find the item. Probe to the next bucket. + BucketNo = (BucketNo+ProbeAmt) & (HTSize-1); + + // Use quadratic probing, it has fewer clumping artifacts than linear + // probing and has good cache behavior in the common case. + ++ProbeAmt; + } +} + +/// RemoveKey - Remove the specified StringMapEntry from the table, but do not +/// delete it. This aborts if the value isn't in the table. +void StringMapImpl::RemoveKey(StringMapEntryBase *V) { + const char *VStr = (char*)V + ItemSize; + StringMapEntryBase *V2 = RemoveKey(StringRef(VStr, V->getKeyLength())); + (void)V2; + assert(V == V2 && "Didn't find key?"); +} + +/// RemoveKey - Remove the StringMapEntry for the specified key from the +/// table, returning it. If the key is not in the table, this returns null. +StringMapEntryBase *StringMapImpl::RemoveKey(StringRef Key) { + int Bucket = FindKey(Key); + if (Bucket == -1) return 0; + + StringMapEntryBase *Result = TheTable[Bucket].Item; + TheTable[Bucket].Item = getTombstoneVal(); + --NumItems; + ++NumTombstones; + return Result; +} + + + +/// RehashTable - Grow the table, redistributing values into the buckets with +/// the appropriate mod-of-hashtable-size. +void StringMapImpl::RehashTable() { + unsigned NewSize = NumBuckets*2; + // Allocate one extra bucket which will always be non-empty. This allows the + // iterators to stop at end. + ItemBucket *NewTableArray =(ItemBucket*)calloc(NewSize+1, sizeof(ItemBucket)); + NewTableArray[NewSize].Item = (StringMapEntryBase*)2; + + // Rehash all the items into their new buckets. Luckily :) we already have + // the hash values available, so we don't have to rehash any strings. + for (ItemBucket *IB = TheTable, *E = TheTable+NumBuckets; IB != E; ++IB) { + if (IB->Item && IB->Item != getTombstoneVal()) { + // Fast case, bucket available. + unsigned FullHash = IB->FullHashValue; + unsigned NewBucket = FullHash & (NewSize-1); + if (NewTableArray[NewBucket].Item == 0) { + NewTableArray[FullHash & (NewSize-1)].Item = IB->Item; + NewTableArray[FullHash & (NewSize-1)].FullHashValue = FullHash; + continue; + } + + // Otherwise probe for a spot. + unsigned ProbeSize = 1; + do { + NewBucket = (NewBucket + ProbeSize++) & (NewSize-1); + } while (NewTableArray[NewBucket].Item); + + // Finally found a slot. Fill it in. + NewTableArray[NewBucket].Item = IB->Item; + NewTableArray[NewBucket].FullHashValue = FullHash; + } + } + + free(TheTable); + + TheTable = NewTableArray; + NumBuckets = NewSize; +} diff --git a/final/lib/Support/StringPool.cpp b/final/lib/Support/StringPool.cpp new file mode 100644 index 00000000000..ff607cf8c4a --- /dev/null +++ b/final/lib/Support/StringPool.cpp @@ -0,0 +1,35 @@ +//===-- StringPool.cpp - Interned string pool -----------------------------===// +// +// 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 StringPool class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StringPool.h" +#include "llvm/ADT/StringRef.h" + +using namespace llvm; + +StringPool::StringPool() {} + +StringPool::~StringPool() { + assert(InternTable.empty() && "PooledStringPtr leaked!"); +} + +PooledStringPtr StringPool::intern(StringRef Key) { + table_t::iterator I = InternTable.find(Key); + if (I != InternTable.end()) + return PooledStringPtr(&*I); + + entry_t *S = entry_t::Create(Key.begin(), Key.end()); + S->getValue().Pool = this; + InternTable.insert(S); + + return PooledStringPtr(S); +} diff --git a/final/lib/Support/StringRef.cpp b/final/lib/Support/StringRef.cpp new file mode 100644 index 00000000000..53980519645 --- /dev/null +++ b/final/lib/Support/StringRef.cpp @@ -0,0 +1,415 @@ +//===-- StringRef.cpp - Lightweight String References ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/OwningPtr.h" +#include + +using namespace llvm; + +// MSVC emits references to this into the translation units which reference it. +#ifndef _MSC_VER +const size_t StringRef::npos; +#endif + +static char ascii_tolower(char x) { + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + return x; +} + +static bool ascii_isdigit(char x) { + return x >= '0' && x <= '9'; +} + +/// compare_lower - Compare strings, ignoring case. +int StringRef::compare_lower(StringRef RHS) const { + for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { + unsigned char LHC = ascii_tolower(Data[I]); + unsigned char RHC = ascii_tolower(RHS.Data[I]); + if (LHC != RHC) + return LHC < RHC ? -1 : 1; + } + + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + +/// compare_numeric - Compare strings, handle embedded numbers. +int StringRef::compare_numeric(StringRef RHS) const { + for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { + if (Data[I] == RHS.Data[I]) + continue; + if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { + // The longer sequence of numbers is larger. This doesn't really handle + // prefixed zeros well. + for (size_t J = I+1; J != E+1; ++J) { + bool ld = J < Length && ascii_isdigit(Data[J]); + bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]); + if (ld != rd) + return rd ? -1 : 1; + if (!rd) + break; + } + } + return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1; + } + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + +// Compute the edit distance between the two given strings. +unsigned StringRef::edit_distance(llvm::StringRef Other, + bool AllowReplacements, + unsigned MaxEditDistance) { + // The algorithm implemented below is the "classic" + // dynamic-programming algorithm for computing the Levenshtein + // distance, which is described here: + // + // http://en.wikipedia.org/wiki/Levenshtein_distance + // + // Although the algorithm is typically described using an m x n + // array, only two rows are used at a time, so this implemenation + // just keeps two separate vectors for those two rows. + size_type m = size(); + size_type n = Other.size(); + + const unsigned SmallBufferSize = 64; + unsigned SmallBuffer[SmallBufferSize]; + llvm::OwningArrayPtr Allocated; + unsigned *previous = SmallBuffer; + if (2*(n + 1) > SmallBufferSize) { + previous = new unsigned [2*(n+1)]; + Allocated.reset(previous); + } + unsigned *current = previous + (n + 1); + + for (unsigned i = 0; i <= n; ++i) + previous[i] = i; + + for (size_type y = 1; y <= m; ++y) { + current[0] = y; + unsigned BestThisRow = current[0]; + + for (size_type x = 1; x <= n; ++x) { + if (AllowReplacements) { + current[x] = min(previous[x-1] + ((*this)[y-1] == Other[x-1]? 0u:1u), + min(current[x-1], previous[x])+1); + } + else { + if ((*this)[y-1] == Other[x-1]) current[x] = previous[x-1]; + else current[x] = min(current[x-1], previous[x]) + 1; + } + BestThisRow = min(BestThisRow, current[x]); + } + + if (MaxEditDistance && BestThisRow > MaxEditDistance) + return MaxEditDistance + 1; + + unsigned *tmp = current; + current = previous; + previous = tmp; + } + + unsigned Result = previous[n]; + return Result; +} + +//===----------------------------------------------------------------------===// +// String Searching +//===----------------------------------------------------------------------===// + + +/// find - Search for the first string \arg Str in the string. +/// +/// \return - The index of the first occurence of \arg Str, or npos if not +/// found. +size_t StringRef::find(StringRef Str, size_t From) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t e = Length - N + 1, i = min(From, e); i != e; ++i) + if (substr(i, N).equals(Str)) + return i; + return npos; +} + +/// rfind - Search for the last string \arg Str in the string. +/// +/// \return - The index of the last occurence of \arg Str, or npos if not +/// found. +size_t StringRef::rfind(StringRef Str) const { + size_t N = Str.size(); + if (N > Length) + return npos; + for (size_t i = Length - N + 1, e = 0; i != e;) { + --i; + if (substr(i, N).equals(Str)) + return i; + } + return npos; +} + +/// find_first_of - Find the first character in the string that is in \arg +/// Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_first_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// \arg C or npos if not found. +StringRef::size_type StringRef::find_first_not_of(char C, size_t From) const { + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (Data[i] != C) + return i; + return npos; +} + +/// find_first_not_of - Find the first character in the string that is not +/// in the string \arg Chars, or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_first_not_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = min(From, Length), e = Length; i != e; ++i) + if (!CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +/// find_last_of - Find the last character in the string that is in \arg C, +/// or npos if not found. +/// +/// Note: O(size() + Chars.size()) +StringRef::size_type StringRef::find_last_of(StringRef Chars, + size_t From) const { + std::bitset<1 << CHAR_BIT> CharBits; + for (size_type i = 0; i != Chars.size(); ++i) + CharBits.set((unsigned char)Chars[i]); + + for (size_type i = min(From, Length) - 1, e = -1; i != e; --i) + if (CharBits.test((unsigned char)Data[i])) + return i; + return npos; +} + +//===----------------------------------------------------------------------===// +// Helpful Algorithms +//===----------------------------------------------------------------------===// + +/// count - Return the number of non-overlapped occurrences of \arg Str in +/// the string. +size_t StringRef::count(StringRef Str) const { + size_t Count = 0; + size_t N = Str.size(); + if (N > Length) + return 0; + for (size_t i = 0, e = Length - N + 1; i != e; ++i) + if (substr(i, N).equals(Str)) + ++Count; + return Count; +} + +static unsigned GetAutoSenseRadix(StringRef &Str) { + if (Str.startswith("0x")) { + Str = Str.substr(2); + return 16; + } else if (Str.startswith("0b")) { + Str = Str.substr(2); + return 2; + } else if (Str.startswith("0")) { + return 8; + } else { + return 10; + } +} + + +/// GetAsUnsignedInteger - Workhorse method that converts a integer character +/// sequence of radix up to 36 to an unsigned long long value. +static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix, + unsigned long long &Result) { + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Parse all the bytes of the string given this radix. Watch for overflow. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + unsigned long long PrevResult = Result; + Result = Result*Radix+CharVal; + + // Check for overflow. + if (Result < PrevResult) + return true; + + Str = Str.substr(1); + } + + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, unsigned long long &Result) const { + return GetAsUnsignedInteger(*this, Radix, Result); +} + + +bool StringRef::getAsInteger(unsigned Radix, long long &Result) const { + unsigned long long ULLVal; + + // Handle positive strings first. + if (empty() || front() != '-') { + if (GetAsUnsignedInteger(*this, Radix, ULLVal) || + // Check for value so large it overflows a signed value. + (long long)ULLVal < 0) + return true; + Result = ULLVal; + return false; + } + + // Get the positive part of the value. + if (GetAsUnsignedInteger(substr(1), Radix, ULLVal) || + // Reject values so large they'd overflow as negative signed, but allow + // "-0". This negates the unsigned so that the negative isn't undefined + // on signed overflow. + (long long)-ULLVal > 0) + return true; + + Result = -ULLVal; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, int &Result) const { + long long Val; + if (getAsInteger(Radix, Val) || + (int)Val != Val) + return true; + Result = Val; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const { + unsigned long long Val; + if (getAsInteger(Radix, Val) || + (unsigned)Val != Val) + return true; + Result = Val; + return false; +} + +bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { + StringRef Str = *this; + + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + assert(Radix > 1 && Radix <= 36); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Skip leading zeroes. This can be a significant improvement if + // it means we don't need > 64 bits. + while (!Str.empty() && Str.front() == '0') + Str = Str.substr(1); + + // If it was nothing but zeroes.... + if (Str.empty()) { + Result = APInt(64, 0); + return false; + } + + // (Over-)estimate the required number of bits. + unsigned Log2Radix = 0; + while ((1U << Log2Radix) < Radix) Log2Radix++; + bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix); + + unsigned BitWidth = Log2Radix * Str.size(); + if (BitWidth < Result.getBitWidth()) + BitWidth = Result.getBitWidth(); // don't shrink the result + else + Result = Result.zext(BitWidth); + + APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix + if (!IsPowerOf2Radix) { + // These must have the same bit-width as Result. + RadixAP = APInt(BitWidth, Radix); + CharAP = APInt(BitWidth, 0); + } + + // Parse all the bytes of the string given this radix. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + if (IsPowerOf2Radix) { + Result <<= Log2Radix; + Result |= CharVal; + } else { + Result *= RadixAP; + CharAP = CharVal; + Result += CharAP; + } + + Str = Str.substr(1); + } + + return false; +} diff --git a/final/lib/Support/SystemUtils.cpp b/final/lib/Support/SystemUtils.cpp new file mode 100644 index 00000000000..54b5e97bfe1 --- /dev/null +++ b/final/lib/Support/SystemUtils.cpp @@ -0,0 +1,55 @@ +//===- SystemUtils.cpp - Utilities for low-level system tasks -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions used to do a variety of low-level, often +// system-specific, tasks. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +bool llvm::CheckBitcodeOutputToConsole(raw_ostream &stream_to_check, + bool print_warning) { + if (stream_to_check.is_displayed()) { + if (print_warning) { + errs() << "WARNING: You're attempting to print out a bitcode file.\n" + "This is inadvisable as it may cause display problems. If\n" + "you REALLY want to taste LLVM bitcode first-hand, you\n" + "can force output with the `-f' option.\n\n"; + } + return true; + } + return false; +} + +/// PrependMainExecutablePath - Prepend the path to the program being executed +/// to \p ExeName, given the value of argv[0] and the address of main() +/// itself. This allows us to find another LLVM tool if it is built in the same +/// directory. An empty string is returned on error; note that this function +/// just mainpulates the path and doesn't check for executability. +/// @brief Find a named executable. +sys::Path llvm::PrependMainExecutablePath(const std::string &ExeName, + const char *Argv0, void *MainAddr) { + // Check the directory that the calling program is in. We can do + // this if ProgramPath contains at least one / character, indicating that it + // is a relative path to the executable itself. + sys::Path Result = sys::Path::GetMainExecutable(Argv0, MainAddr); + Result.eraseComponent(); + + if (!Result.isEmpty()) { + Result.appendComponent(ExeName); + Result.appendSuffix(sys::Path::GetEXESuffix()); + } + + return Result; +} diff --git a/final/lib/Support/TargetRegistry.cpp b/final/lib/Support/TargetRegistry.cpp new file mode 100644 index 00000000000..293a5d7a016 --- /dev/null +++ b/final/lib/Support/TargetRegistry.cpp @@ -0,0 +1,92 @@ +//===--- TargetRegistry.cpp - Target registration -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Host.h" +#include +using namespace llvm; + +// Clients are responsible for avoid race conditions in registration. +static Target *FirstTarget = 0; + +TargetRegistry::iterator TargetRegistry::begin() { + return iterator(FirstTarget); +} + +const Target *TargetRegistry::lookupTarget(const std::string &TT, + std::string &Error) { + // Provide special warning when no targets are initialized. + if (begin() == end()) { + Error = "Unable to find target for this triple (no targets are registered)"; + return 0; + } + const Target *Best = 0, *EquallyBest = 0; + unsigned BestQuality = 0; + for (iterator it = begin(), ie = end(); it != ie; ++it) { + if (unsigned Qual = it->TripleMatchQualityFn(TT)) { + if (!Best || Qual > BestQuality) { + Best = &*it; + EquallyBest = 0; + BestQuality = Qual; + } else if (Qual == BestQuality) + EquallyBest = &*it; + } + } + + if (!Best) { + Error = "No available targets are compatible with this triple, " + "see -version for the available targets."; + return 0; + } + + // Otherwise, take the best target, but make sure we don't have two equally + // good best targets. + if (EquallyBest) { + Error = std::string("Cannot choose between targets \"") + + Best->Name + "\" and \"" + EquallyBest->Name + "\""; + return 0; + } + + return Best; +} + +void TargetRegistry::RegisterTarget(Target &T, + const char *Name, + const char *ShortDesc, + Target::TripleMatchQualityFnTy TQualityFn, + bool HasJIT) { + assert(Name && ShortDesc && TQualityFn && + "Missing required target information!"); + + // Check if this target has already been initialized, we allow this as a + // convenience to some clients. + if (T.Name) + return; + + // Add to the list of targets. + T.Next = FirstTarget; + FirstTarget = &T; + + T.Name = Name; + T.ShortDesc = ShortDesc; + T.TripleMatchQualityFn = TQualityFn; + T.HasJIT = HasJIT; +} + +const Target *TargetRegistry::getClosestTargetForJIT(std::string &Error) { + const Target *TheTarget = lookupTarget(sys::getHostTriple(), Error); + + if (TheTarget && !TheTarget->hasJIT()) { + Error = "No JIT compatible target available for this host"; + return 0; + } + + return TheTarget; +} + diff --git a/final/lib/Support/ThreadLocal.cpp b/final/lib/Support/ThreadLocal.cpp new file mode 100644 index 00000000000..6b43048da15 --- /dev/null +++ b/final/lib/Support/ThreadLocal.cpp @@ -0,0 +1,84 @@ +//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/Support/ThreadLocal.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(const void* d) { data = const_cast(d);} +const void* ThreadLocalImpl::getInstance() { return data; } +void ThreadLocalImpl::removeInstance() { data = 0; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC) + +#include +#include +#include + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() : data(0) { + pthread_key_t* key = new pthread_key_t; + int errorcode = pthread_key_create(key, NULL); + assert(errorcode == 0); + (void) errorcode; + data = (void*)key; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_key_delete(*key); + assert(errorcode == 0); + (void) errorcode; + delete key; +} + +void ThreadLocalImpl::setInstance(const void* d) { + pthread_key_t* key = static_cast(data); + int errorcode = pthread_setspecific(*key, d); + assert(errorcode == 0); + (void) errorcode; +} + +const void* ThreadLocalImpl::getInstance() { + pthread_key_t* key = static_cast(data); + return pthread_getspecific(*key); +} + +void ThreadLocalImpl::removeInstance() { + setInstance(0); +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/ThreadLocal.inc" +#elif defined( LLVM_ON_WIN32) +#include "Windows/ThreadLocal.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp +#endif +#endif diff --git a/final/lib/Support/Threading.cpp b/final/lib/Support/Threading.cpp new file mode 100644 index 00000000000..29579567ac6 --- /dev/null +++ b/final/lib/Support/Threading.cpp @@ -0,0 +1,116 @@ +//===-- llvm/Support/Threading.cpp- Control multithreading mode --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Threading.h" +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Config/config.h" +#include + +using namespace llvm; + +static bool multithreaded_mode = false; + +static sys::Mutex* global_lock = 0; + +bool llvm::llvm_start_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(!multithreaded_mode && "Already multithreaded!"); + multithreaded_mode = true; + global_lock = new sys::Mutex(true); + + // We fence here to ensure that all initialization is complete BEFORE we + // return from llvm_start_multithreaded(). + sys::MemoryFence(); + return true; +#else + return false; +#endif +} + +void llvm::llvm_stop_multithreaded() { +#ifdef LLVM_MULTITHREADED + assert(multithreaded_mode && "Not currently multithreaded!"); + + // We fence here to insure that all threaded operations are complete BEFORE we + // return from llvm_stop_multithreaded(). + sys::MemoryFence(); + + multithreaded_mode = false; + delete global_lock; +#endif +} + +bool llvm::llvm_is_multithreaded() { + return multithreaded_mode; +} + +void llvm::llvm_acquire_global_lock() { + if (multithreaded_mode) global_lock->acquire(); +} + +void llvm::llvm_release_global_lock() { + if (multithreaded_mode) global_lock->release(); +} + +#if defined(LLVM_MULTITHREADED) && defined(HAVE_PTHREAD_H) +#include + +struct ThreadInfo { + void (*UserFn)(void *); + void *UserData; +}; +static void *ExecuteOnThread_Dispatch(void *Arg) { + ThreadInfo *TI = reinterpret_cast(Arg); + TI->UserFn(TI->UserData); + return 0; +} + +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + ThreadInfo Info = { Fn, UserData }; + pthread_attr_t Attr; + pthread_t Thread; + + // Construct the attributes object. + if (::pthread_attr_init(&Attr) != 0) + return; + + // Set the requested stack size, if given. + if (RequestedStackSize != 0) { + if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0) + goto error; + } + + // Construct and execute the thread. + if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0) + goto error; + + // Wait for the thread and clean up. + ::pthread_join(Thread, 0); + + error: + ::pthread_attr_destroy(&Attr); +} + +#else + +// No non-pthread implementation, currently. + +void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize) { + (void) RequestedStackSize; + Fn(UserData); +} + +#endif diff --git a/final/lib/Support/TimeValue.cpp b/final/lib/Support/TimeValue.cpp new file mode 100644 index 00000000000..1a0f7bc3639 --- /dev/null +++ b/final/lib/Support/TimeValue.cpp @@ -0,0 +1,57 @@ +//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/TimeValue.h" +#include "llvm/Config/config.h" + +namespace llvm { +using namespace sys; + +const TimeValue TimeValue::MinTime = TimeValue ( INT64_MIN,0 ); +const TimeValue TimeValue::MaxTime = TimeValue ( INT64_MAX,0 ); +const TimeValue TimeValue::ZeroTime = TimeValue ( 0,0 ); +const TimeValue TimeValue::PosixZeroTime = TimeValue ( -946684800,0 ); +const TimeValue TimeValue::Win32ZeroTime = TimeValue ( -12591158400ULL,0 ); + +void +TimeValue::normalize( void ) { + if ( nanos_ >= NANOSECONDS_PER_SECOND ) { + do { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } while ( nanos_ >= NANOSECONDS_PER_SECOND ); + } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) { + do { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } while (nanos_ <= -NANOSECONDS_PER_SECOND); + } + + if (seconds_ >= 1 && nanos_ < 0) { + seconds_--; + nanos_ += NANOSECONDS_PER_SECOND; + } else if (seconds_ < 0 && nanos_ > 0) { + seconds_++; + nanos_ -= NANOSECONDS_PER_SECOND; + } +} + +} + +/// Include the platform specific portion of TimeValue class +#ifdef LLVM_ON_UNIX +#include "Unix/TimeValue.inc" +#endif +#ifdef LLVM_ON_WIN32 +#include "Windows/TimeValue.inc" +#endif diff --git a/final/lib/Support/Timer.cpp b/final/lib/Support/Timer.cpp new file mode 100644 index 00000000000..a9ed5eecfa7 --- /dev/null +++ b/final/lib/Support/Timer.cpp @@ -0,0 +1,393 @@ +//===-- Timer.cpp - Interval Timing Support -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interval Timing implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Timer.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/Process.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +using namespace llvm; + +// CreateInfoOutputFile - Return a file stream to print our output on. +namespace llvm { extern raw_ostream *CreateInfoOutputFile(); } + +// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy +// of constructor/destructor ordering being unspecified by C++. Basically the +// problem is that a Statistic object gets destroyed, which ends up calling +// 'GetLibSupportInfoOutputFile()' (below), which calls this function. +// LibSupportInfoOutputFilename used to be a global variable, but sometimes it +// would get destroyed before the Statistic, causing havoc to ensue. We "fix" +// this by creating the string the first time it is needed and never destroying +// it. +static ManagedStatic LibSupportInfoOutputFilename; +static std::string &getLibSupportInfoOutputFilename() { + return *LibSupportInfoOutputFilename; +} + +static ManagedStatic > TimerLock; + +namespace { + static cl::opt + TrackSpace("track-memory", cl::desc("Enable -time-passes memory " + "tracking (this may be slow)"), + cl::Hidden); + + static cl::opt + InfoOutputFilename("info-output-file", cl::value_desc("filename"), + cl::desc("File to append -stats and -timer output to"), + cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); +} + +// CreateInfoOutputFile - Return a file stream to print our output on. +raw_ostream *llvm::CreateInfoOutputFile() { + const std::string &OutputFilename = getLibSupportInfoOutputFilename(); + if (OutputFilename.empty()) + return new raw_fd_ostream(2, false); // stderr. + if (OutputFilename == "-") + return new raw_fd_ostream(1, false); // stdout. + + // Append mode is used because the info output file is opened and closed + // each time -stats or -time-passes wants to print output to it. To + // compensate for this, the test-suite Makefiles have code to delete the + // info output file before running commands which write to it. + std::string Error; + raw_ostream *Result = new raw_fd_ostream(OutputFilename.c_str(), + Error, raw_fd_ostream::F_Append); + if (Error.empty()) + return Result; + + errs() << "Error opening info-output-file '" + << OutputFilename << " for appending!\n"; + delete Result; + return new raw_fd_ostream(2, false); // stderr. +} + + +static TimerGroup *DefaultTimerGroup = 0; +static TimerGroup *getDefaultTimerGroup() { + TimerGroup *tmp = DefaultTimerGroup; + sys::MemoryFence(); + if (tmp) return tmp; + + llvm_acquire_global_lock(); + tmp = DefaultTimerGroup; + if (!tmp) { + tmp = new TimerGroup("Miscellaneous Ungrouped Timers"); + sys::MemoryFence(); + DefaultTimerGroup = tmp; + } + llvm_release_global_lock(); + + return tmp; +} + +//===----------------------------------------------------------------------===// +// Timer Implementation +//===----------------------------------------------------------------------===// + +void Timer::init(StringRef N) { + assert(TG == 0 && "Timer already initialized"); + Name.assign(N.begin(), N.end()); + Started = false; + TG = getDefaultTimerGroup(); + TG->addTimer(*this); +} + +void Timer::init(StringRef N, TimerGroup &tg) { + assert(TG == 0 && "Timer already initialized"); + Name.assign(N.begin(), N.end()); + Started = false; + TG = &tg; + TG->addTimer(*this); +} + +Timer::~Timer() { + if (!TG) return; // Never initialized, or already cleared. + TG->removeTimer(*this); +} + +static inline size_t getMemUsage() { + if (!TrackSpace) return 0; + return sys::Process::GetMallocUsage(); +} + +TimeRecord TimeRecord::getCurrentTime(bool Start) { + TimeRecord Result; + sys::TimeValue now(0,0), user(0,0), sys(0,0); + + if (Start) { + Result.MemUsed = getMemUsage(); + sys::Process::GetTimeUsage(now, user, sys); + } else { + sys::Process::GetTimeUsage(now, user, sys); + Result.MemUsed = getMemUsage(); + } + + Result.WallTime = now.seconds() + now.microseconds() / 1000000.0; + Result.UserTime = user.seconds() + user.microseconds() / 1000000.0; + Result.SystemTime = sys.seconds() + sys.microseconds() / 1000000.0; + return Result; +} + +static ManagedStatic > ActiveTimers; + +void Timer::startTimer() { + Started = true; + ActiveTimers->push_back(this); + Time -= TimeRecord::getCurrentTime(true); +} + +void Timer::stopTimer() { + Time += TimeRecord::getCurrentTime(false); + + if (ActiveTimers->back() == this) { + ActiveTimers->pop_back(); + } else { + std::vector::iterator I = + std::find(ActiveTimers->begin(), ActiveTimers->end(), this); + assert(I != ActiveTimers->end() && "stop but no startTimer?"); + ActiveTimers->erase(I); + } +} + +static void printVal(double Val, double Total, raw_ostream &OS) { + if (Total < 1e-7) // Avoid dividing by zero. + OS << " ----- "; + else { + OS << " " << format("%7.4f", Val) << " ("; + OS << format("%5.1f", Val*100/Total) << "%)"; + } +} + +void TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const { + if (Total.getUserTime()) + printVal(getUserTime(), Total.getUserTime(), OS); + if (Total.getSystemTime()) + printVal(getSystemTime(), Total.getSystemTime(), OS); + if (Total.getProcessTime()) + printVal(getProcessTime(), Total.getProcessTime(), OS); + printVal(getWallTime(), Total.getWallTime(), OS); + + OS << " "; + + if (Total.getMemUsed()) + OS << format("%9lld", (long long)getMemUsed()) << " "; +} + + +//===----------------------------------------------------------------------===// +// NamedRegionTimer Implementation +//===----------------------------------------------------------------------===// + +namespace { + +typedef StringMap Name2TimerMap; + +class Name2PairMap { + StringMap > Map; +public: + ~Name2PairMap() { + for (StringMap >::iterator + I = Map.begin(), E = Map.end(); I != E; ++I) + delete I->second.first; + } + + Timer &get(StringRef Name, StringRef GroupName) { + sys::SmartScopedLock L(*TimerLock); + + std::pair &GroupEntry = Map[GroupName]; + + if (!GroupEntry.first) + GroupEntry.first = new TimerGroup(GroupName); + + Timer &T = GroupEntry.second[Name]; + if (!T.isInitialized()) + T.init(Name, *GroupEntry.first); + return T; + } +}; + +} + +static ManagedStatic NamedTimers; +static ManagedStatic NamedGroupedTimers; + +static Timer &getNamedRegionTimer(StringRef Name) { + sys::SmartScopedLock L(*TimerLock); + + Timer &T = (*NamedTimers)[Name]; + if (!T.isInitialized()) + T.init(Name); + return T; +} + +NamedRegionTimer::NamedRegionTimer(StringRef Name, + bool Enabled) + : TimeRegion(!Enabled ? 0 : &getNamedRegionTimer(Name)) {} + +NamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName, + bool Enabled) + : TimeRegion(!Enabled ? 0 : &NamedGroupedTimers->get(Name, GroupName)) {} + +//===----------------------------------------------------------------------===// +// TimerGroup Implementation +//===----------------------------------------------------------------------===// + +/// TimerGroupList - This is the global list of TimerGroups, maintained by the +/// TimerGroup ctor/dtor and is protected by the TimerLock lock. +static TimerGroup *TimerGroupList = 0; + +TimerGroup::TimerGroup(StringRef name) + : Name(name.begin(), name.end()), FirstTimer(0) { + + // Add the group to TimerGroupList. + sys::SmartScopedLock L(*TimerLock); + if (TimerGroupList) + TimerGroupList->Prev = &Next; + Next = TimerGroupList; + Prev = &TimerGroupList; + TimerGroupList = this; +} + +TimerGroup::~TimerGroup() { + // If the timer group is destroyed before the timers it owns, accumulate and + // print the timing data. + while (FirstTimer != 0) + removeTimer(*FirstTimer); + + // Remove the group from the TimerGroupList. + sys::SmartScopedLock L(*TimerLock); + *Prev = Next; + if (Next) + Next->Prev = Prev; +} + + +void TimerGroup::removeTimer(Timer &T) { + sys::SmartScopedLock L(*TimerLock); + + // If the timer was started, move its data to TimersToPrint. + if (T.Started) + TimersToPrint.push_back(std::make_pair(T.Time, T.Name)); + + T.TG = 0; + + // Unlink the timer from our list. + *T.Prev = T.Next; + if (T.Next) + T.Next->Prev = T.Prev; + + // Print the report when all timers in this group are destroyed if some of + // them were started. + if (FirstTimer != 0 || TimersToPrint.empty()) + return; + + raw_ostream *OutStream = CreateInfoOutputFile(); + PrintQueuedTimers(*OutStream); + delete OutStream; // Close the file. +} + +void TimerGroup::addTimer(Timer &T) { + sys::SmartScopedLock L(*TimerLock); + + // Add the timer to our list. + if (FirstTimer) + FirstTimer->Prev = &T.Next; + T.Next = FirstTimer; + T.Prev = &FirstTimer; + FirstTimer = &T; +} + +void TimerGroup::PrintQueuedTimers(raw_ostream &OS) { + // Sort the timers in descending order by amount of time taken. + std::sort(TimersToPrint.begin(), TimersToPrint.end()); + + TimeRecord Total; + for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) + Total += TimersToPrint[i].first; + + // Print out timing header. + OS << "===" << std::string(73, '-') << "===\n"; + // Figure out how many spaces to indent TimerGroup name. + unsigned Padding = (80-Name.length())/2; + if (Padding > 80) Padding = 0; // Don't allow "negative" numbers + OS.indent(Padding) << Name << '\n'; + OS << "===" << std::string(73, '-') << "===\n"; + + // If this is not an collection of ungrouped times, print the total time. + // Ungrouped timers don't really make sense to add up. We still print the + // TOTAL line to make the percentages make sense. + if (this != DefaultTimerGroup) { + OS << " Total Execution Time: "; + OS << format("%5.4f", Total.getProcessTime()) << " seconds ("; + OS << format("%5.4f", Total.getWallTime()) << " wall clock)\n"; + } + OS << '\n'; + + if (Total.getUserTime()) + OS << " ---User Time---"; + if (Total.getSystemTime()) + OS << " --System Time--"; + if (Total.getProcessTime()) + OS << " --User+System--"; + OS << " ---Wall Time---"; + if (Total.getMemUsed()) + OS << " ---Mem---"; + OS << " --- Name ---\n"; + + // Loop through all of the timing data, printing it out. + for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) { + const std::pair &Entry = TimersToPrint[e-i-1]; + Entry.first.print(Total, OS); + OS << Entry.second << '\n'; + } + + Total.print(Total, OS); + OS << "Total\n\n"; + OS.flush(); + + TimersToPrint.clear(); +} + +/// print - Print any started timers in this group and zero them. +void TimerGroup::print(raw_ostream &OS) { + sys::SmartScopedLock L(*TimerLock); + + // See if any of our timers were started, if so add them to TimersToPrint and + // reset them. + for (Timer *T = FirstTimer; T; T = T->Next) { + if (!T->Started) continue; + TimersToPrint.push_back(std::make_pair(T->Time, T->Name)); + + // Clear out the time. + T->Started = 0; + T->Time = TimeRecord(); + } + + // If any timers were started, print the group. + if (!TimersToPrint.empty()) + PrintQueuedTimers(OS); +} + +/// printAll - This static method prints all timers and clears them all out. +void TimerGroup::printAll(raw_ostream &OS) { + sys::SmartScopedLock L(*TimerLock); + + for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next) + TG->print(OS); +} diff --git a/final/lib/Support/ToolOutputFile.cpp b/final/lib/Support/ToolOutputFile.cpp new file mode 100644 index 00000000000..e7ca927ea53 --- /dev/null +++ b/final/lib/Support/ToolOutputFile.cpp @@ -0,0 +1,43 @@ +//===--- ToolOutputFile.cpp - Implement the tool_output_file class --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements the tool_output_file class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +using namespace llvm; + +tool_output_file::CleanupInstaller::CleanupInstaller(const char *filename) + : Filename(filename), Keep(false) { + // Arrange for the file to be deleted if the process is killed. + if (Filename != "-") + sys::RemoveFileOnSignal(sys::Path(Filename)); +} + +tool_output_file::CleanupInstaller::~CleanupInstaller() { + // Delete the file if the client hasn't told us not to. + if (!Keep && Filename != "-") + sys::Path(Filename).eraseFromDisk(); + + // Ok, the file is successfully written and closed, or deleted. There's no + // further need to clean it up on signals. + if (Filename != "-") + sys::DontRemoveFileOnSignal(sys::Path(Filename)); +} + +tool_output_file::tool_output_file(const char *filename, std::string &ErrorInfo, + unsigned Flags) + : Installer(filename), + OS(filename, ErrorInfo, Flags) { + // If open fails, no cleanup is needed. + if (!ErrorInfo.empty()) + Installer.Keep = true; +} diff --git a/final/lib/Support/Triple.cpp b/final/lib/Support/Triple.cpp new file mode 100644 index 00000000000..36edf6eefa7 --- /dev/null +++ b/final/lib/Support/Triple.cpp @@ -0,0 +1,640 @@ +//===--- Triple.cpp - Target triple helper class --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Triple.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include +#include +using namespace llvm; + +// + +const char *Triple::getArchTypeName(ArchType Kind) { + switch (Kind) { + case InvalidArch: return ""; + case UnknownArch: return "unknown"; + + case alpha: return "alpha"; + case arm: return "arm"; + case bfin: return "bfin"; + case cellspu: return "cellspu"; + case mips: return "mips"; + case mipsel: return "mipsel"; + case msp430: return "msp430"; + case ppc64: return "powerpc64"; + case ppc: return "powerpc"; + case sparc: return "sparc"; + case sparcv9: return "sparcv9"; + case systemz: return "s390x"; + case tce: return "tce"; + case thumb: return "thumb"; + case x86: return "i386"; + case x86_64: return "x86_64"; + case xcore: return "xcore"; + case mblaze: return "mblaze"; + case ptx: return "ptx"; + } + + return ""; +} + +const char *Triple::getArchTypePrefix(ArchType Kind) { + switch (Kind) { + default: + return 0; + + case alpha: return "alpha"; + + case arm: + case thumb: return "arm"; + + case bfin: return "bfin"; + + case cellspu: return "spu"; + + case ppc64: + case ppc: return "ppc"; + + case mblaze: return "mblaze"; + + case sparcv9: + case sparc: return "sparc"; + + case x86: + case x86_64: return "x86"; + + case xcore: return "xcore"; + + case ptx: return "ptx"; + } +} + +const char *Triple::getVendorTypeName(VendorType Kind) { + switch (Kind) { + case UnknownVendor: return "unknown"; + + case Apple: return "apple"; + case PC: return "pc"; + } + + return ""; +} + +const char *Triple::getOSTypeName(OSType Kind) { + switch (Kind) { + case UnknownOS: return "unknown"; + + case AuroraUX: return "auroraux"; + case Cygwin: return "cygwin"; + case Darwin: return "darwin"; + case DragonFly: return "dragonfly"; + case FreeBSD: return "freebsd"; + case Linux: return "linux"; + case Lv2: return "lv2"; + case MinGW32: return "mingw32"; + case NetBSD: return "netbsd"; + case OpenBSD: return "openbsd"; + case Psp: return "psp"; + case Solaris: return "solaris"; + case Win32: return "win32"; + case Haiku: return "haiku"; + case Minix: return "minix"; + } + + return ""; +} + +const char *Triple::getEnvironmentTypeName(EnvironmentType Kind) { + switch (Kind) { + case UnknownEnvironment: return "unknown"; + case GNU: return "gnu"; + case GNUEABI: return "gnueabi"; + case EABI: return "eabi"; + case MachO: return "macho"; + } + + return ""; +} + +Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { + if (Name == "alpha") + return alpha; + if (Name == "arm") + return arm; + if (Name == "bfin") + return bfin; + if (Name == "cellspu") + return cellspu; + if (Name == "mips") + return mips; + if (Name == "mipsel") + return mipsel; + if (Name == "msp430") + return msp430; + if (Name == "ppc64") + return ppc64; + if (Name == "ppc") + return ppc; + if (Name == "mblaze") + return mblaze; + if (Name == "sparc") + return sparc; + if (Name == "sparcv9") + return sparcv9; + if (Name == "systemz") + return systemz; + if (Name == "tce") + return tce; + if (Name == "thumb") + return thumb; + if (Name == "x86") + return x86; + if (Name == "x86-64") + return x86_64; + if (Name == "xcore") + return xcore; + if (Name == "ptx") + return ptx; + + return UnknownArch; +} + +Triple::ArchType Triple::getArchTypeForDarwinArchName(StringRef Str) { + // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for + // archs which Darwin doesn't use. + + // The matching this routine does is fairly pointless, since it is neither the + // complete architecture list, nor a reasonable subset. The problem is that + // historically the driver driver accepts this and also ties its -march= + // handling to the architecture name, so we need to be careful before removing + // support for it. + + // This code must be kept in sync with Clang's Darwin specific argument + // translation. + + if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" || + Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" || + Str == "ppc7450" || Str == "ppc970") + return Triple::ppc; + + if (Str == "ppc64") + return Triple::ppc64; + + if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" || + Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" || + Str == "pentIIm5" || Str == "pentium4") + return Triple::x86; + + if (Str == "x86_64") + return Triple::x86_64; + + // This is derived from the driver driver. + if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" || + Str == "armv6" || Str == "armv7") + return Triple::arm; + + if (Str == "ptx") + return Triple::ptx; + + return Triple::UnknownArch; +} + +// Returns architecture name that is understood by the target assembler. +const char *Triple::getArchNameForAssembler() { + if (getOS() != Triple::Darwin && getVendor() != Triple::Apple) + return NULL; + + StringRef Str = getArchName(); + if (Str == "i386") + return "i386"; + if (Str == "x86_64") + return "x86_64"; + if (Str == "powerpc") + return "ppc"; + if (Str == "powerpc64") + return "ppc64"; + if (Str == "mblaze" || Str == "microblaze") + return "mblaze"; + if (Str == "arm") + return "arm"; + if (Str == "armv4t" || Str == "thumbv4t") + return "armv4t"; + if (Str == "armv5" || Str == "armv5e" || Str == "thumbv5" + || Str == "thumbv5e") + return "armv5"; + if (Str == "armv6" || Str == "thumbv6") + return "armv6"; + if (Str == "armv7" || Str == "thumbv7") + return "armv7"; + if (Str == "ptx") + return "ptx"; + return NULL; +} + +// + +Triple::ArchType Triple::ParseArch(StringRef ArchName) { + if (ArchName.size() == 4 && ArchName[0] == 'i' && + ArchName[2] == '8' && ArchName[3] == '6' && + ArchName[1] - '3' < 6) // i[3-9]86 + return x86; + else if (ArchName == "amd64" || ArchName == "x86_64") + return x86_64; + else if (ArchName == "bfin") + return bfin; + else if (ArchName == "powerpc") + return ppc; + else if ((ArchName == "powerpc64") || (ArchName == "ppu")) + return ppc64; + else if (ArchName == "mblaze") + return mblaze; + else if (ArchName == "arm" || + ArchName.startswith("armv") || + ArchName == "xscale") + return arm; + else if (ArchName == "thumb" || + ArchName.startswith("thumbv")) + return thumb; + else if (ArchName.startswith("alpha")) + return alpha; + else if (ArchName == "spu" || ArchName == "cellspu") + return cellspu; + else if (ArchName == "msp430") + return msp430; + else if (ArchName == "mips" || ArchName == "mipsallegrex") + return mips; + else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" || + ArchName == "psp") + return mipsel; + else if (ArchName == "sparc") + return sparc; + else if (ArchName == "sparcv9") + return sparcv9; + else if (ArchName == "s390x") + return systemz; + else if (ArchName == "tce") + return tce; + else if (ArchName == "xcore") + return xcore; + else if (ArchName == "ptx") + return ptx; + else + return UnknownArch; +} + +Triple::VendorType Triple::ParseVendor(StringRef VendorName) { + if (VendorName == "apple") + return Apple; + else if (VendorName == "pc") + return PC; + else + return UnknownVendor; +} + +Triple::OSType Triple::ParseOS(StringRef OSName) { + if (OSName.startswith("auroraux")) + return AuroraUX; + else if (OSName.startswith("cygwin")) + return Cygwin; + else if (OSName.startswith("darwin")) + return Darwin; + else if (OSName.startswith("dragonfly")) + return DragonFly; + else if (OSName.startswith("freebsd")) + return FreeBSD; + else if (OSName.startswith("linux")) + return Linux; + else if (OSName.startswith("lv2")) + return Lv2; + else if (OSName.startswith("mingw32")) + return MinGW32; + else if (OSName.startswith("netbsd")) + return NetBSD; + else if (OSName.startswith("openbsd")) + return OpenBSD; + else if (OSName.startswith("psp")) + return Psp; + else if (OSName.startswith("solaris")) + return Solaris; + else if (OSName.startswith("win32")) + return Win32; + else if (OSName.startswith("haiku")) + return Haiku; + else if (OSName.startswith("minix")) + return Minix; + else + return UnknownOS; +} + +Triple::EnvironmentType Triple::ParseEnvironment(StringRef EnvironmentName) { + if (EnvironmentName.startswith("eabi")) + return EABI; + else if (EnvironmentName.startswith("gnueabi")) + return GNUEABI; + else if (EnvironmentName.startswith("gnu")) + return GNU; + else if (EnvironmentName.startswith("macho")) + return MachO; + else + return UnknownEnvironment; +} + +void Triple::Parse() const { + assert(!isInitialized() && "Invalid parse call."); + + Arch = ParseArch(getArchName()); + Vendor = ParseVendor(getVendorName()); + OS = ParseOS(getOSName()); + Environment = ParseEnvironment(getEnvironmentName()); + + assert(isInitialized() && "Failed to initialize!"); +} + +std::string Triple::normalize(StringRef Str) { + // Parse into components. + SmallVector Components; + for (size_t First = 0, Last = 0; Last != StringRef::npos; First = Last + 1) { + Last = Str.find('-', First); + Components.push_back(Str.slice(First, Last)); + } + + // If the first component corresponds to a known architecture, preferentially + // use it for the architecture. If the second component corresponds to a + // known vendor, preferentially use it for the vendor, etc. This avoids silly + // component movement when a component parses as (eg) both a valid arch and a + // valid os. + ArchType Arch = UnknownArch; + if (Components.size() > 0) + Arch = ParseArch(Components[0]); + VendorType Vendor = UnknownVendor; + if (Components.size() > 1) + Vendor = ParseVendor(Components[1]); + OSType OS = UnknownOS; + if (Components.size() > 2) + OS = ParseOS(Components[2]); + EnvironmentType Environment = UnknownEnvironment; + if (Components.size() > 3) + Environment = ParseEnvironment(Components[3]); + + // Note which components are already in their final position. These will not + // be moved. + bool Found[4]; + Found[0] = Arch != UnknownArch; + Found[1] = Vendor != UnknownVendor; + Found[2] = OS != UnknownOS; + Found[3] = Environment != UnknownEnvironment; + + // If they are not there already, permute the components into their canonical + // positions by seeing if they parse as a valid architecture, and if so moving + // the component to the architecture position etc. + for (unsigned Pos = 0; Pos != array_lengthof(Found); ++Pos) { + if (Found[Pos]) + continue; // Already in the canonical position. + + for (unsigned Idx = 0; Idx != Components.size(); ++Idx) { + // Do not reparse any components that already matched. + if (Idx < array_lengthof(Found) && Found[Idx]) + continue; + + // Does this component parse as valid for the target position? + bool Valid = false; + StringRef Comp = Components[Idx]; + switch (Pos) { + default: + assert(false && "unexpected component type!"); + case 0: + Arch = ParseArch(Comp); + Valid = Arch != UnknownArch; + break; + case 1: + Vendor = ParseVendor(Comp); + Valid = Vendor != UnknownVendor; + break; + case 2: + OS = ParseOS(Comp); + Valid = OS != UnknownOS; + break; + case 3: + Environment = ParseEnvironment(Comp); + Valid = Environment != UnknownEnvironment; + break; + } + if (!Valid) + continue; // Nope, try the next component. + + // Move the component to the target position, pushing any non-fixed + // components that are in the way to the right. This tends to give + // good results in the common cases of a forgotten vendor component + // or a wrongly positioned environment. + if (Pos < Idx) { + // Insert left, pushing the existing components to the right. For + // example, a-b-i386 -> i386-a-b when moving i386 to the front. + StringRef CurrentComponent(""); // The empty component. + // Replace the component we are moving with an empty component. + std::swap(CurrentComponent, Components[Idx]); + // Insert the component being moved at Pos, displacing any existing + // components to the right. + for (unsigned i = Pos; !CurrentComponent.empty(); ++i) { + // Skip over any fixed components. + while (i < array_lengthof(Found) && Found[i]) ++i; + // Place the component at the new position, getting the component + // that was at this position - it will be moved right. + std::swap(CurrentComponent, Components[i]); + } + } else if (Pos > Idx) { + // Push right by inserting empty components until the component at Idx + // reaches the target position Pos. For example, pc-a -> -pc-a when + // moving pc to the second position. + do { + // Insert one empty component at Idx. + StringRef CurrentComponent(""); // The empty component. + for (unsigned i = Idx; i < Components.size();) { + // Place the component at the new position, getting the component + // that was at this position - it will be moved right. + std::swap(CurrentComponent, Components[i]); + // If it was placed on top of an empty component then we are done. + if (CurrentComponent.empty()) + break; + // Advance to the next component, skipping any fixed components. + while (++i < array_lengthof(Found) && Found[i]) + ; + } + // The last component was pushed off the end - append it. + if (!CurrentComponent.empty()) + Components.push_back(CurrentComponent); + + // Advance Idx to the component's new position. + while (++Idx < array_lengthof(Found) && Found[Idx]) {} + } while (Idx < Pos); // Add more until the final position is reached. + } + assert(Pos < Components.size() && Components[Pos] == Comp && + "Component moved wrong!"); + Found[Pos] = true; + break; + } + } + + // Special case logic goes here. At this point Arch, Vendor and OS have the + // correct values for the computed components. + + // Stick the corrected components back together to form the normalized string. + std::string Normalized; + for (unsigned i = 0, e = Components.size(); i != e; ++i) { + if (i) Normalized += '-'; + Normalized += Components[i]; + } + return Normalized; +} + +StringRef Triple::getArchName() const { + return StringRef(Data).split('-').first; // Isolate first component +} + +StringRef Triple::getVendorName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').first; // Isolate second component +} + +StringRef Triple::getOSName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').first; // Isolate third component +} + +StringRef Triple::getEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + Tmp = Tmp.split('-').second; // Strip second component + return Tmp.split('-').second; // Strip third component +} + +StringRef Triple::getOSAndEnvironmentName() const { + StringRef Tmp = StringRef(Data).split('-').second; // Strip first component + return Tmp.split('-').second; // Strip second component +} + +static unsigned EatNumber(StringRef &Str) { + assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number"); + unsigned Result = Str[0]-'0'; + + // Eat the digit. + Str = Str.substr(1); + + // Handle "darwin11". + if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') { + Result = Result*10 + (Str[0] - '0'); + // Eat the digit. + Str = Str.substr(1); + } + + return Result; +} + +/// getDarwinNumber - Parse the 'darwin number' out of the specific target +/// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is +/// not defined, return 0's. This requires that the triple have an OSType of +/// darwin before it is called. +void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min, + unsigned &Revision) const { + assert(getOS() == Darwin && "Not a darwin target triple!"); + StringRef OSName = getOSName(); + assert(OSName.startswith("darwin") && "Unknown darwin target triple!"); + + // Strip off "darwin". + OSName = OSName.substr(6); + + Maj = Min = Revision = 0; + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + // The major version is the first digit. + Maj = EatNumber(OSName); + if (OSName.empty()) return; + + // Handle minor version: 10.4.9 -> darwin8.9. + if (OSName[0] != '.') + return; + + // Eat the '.'. + OSName = OSName.substr(1); + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + Min = EatNumber(OSName); + if (OSName.empty()) return; + + // Handle revision darwin8.9.1 + if (OSName[0] != '.') + return; + + // Eat the '.'. + OSName = OSName.substr(1); + + if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9') + return; + + Revision = EatNumber(OSName); +} + +void Triple::setTriple(const Twine &Str) { + Data = Str.str(); + Arch = InvalidArch; +} + +void Triple::setArch(ArchType Kind) { + setArchName(getArchTypeName(Kind)); +} + +void Triple::setVendor(VendorType Kind) { + setVendorName(getVendorTypeName(Kind)); +} + +void Triple::setOS(OSType Kind) { + setOSName(getOSTypeName(Kind)); +} + +void Triple::setEnvironment(EnvironmentType Kind) { + setEnvironmentName(getEnvironmentTypeName(Kind)); +} + +void Triple::setArchName(StringRef Str) { + // Work around a miscompilation bug for Twines in gcc 4.0.3. + SmallString<64> Triple; + Triple += Str; + Triple += "-"; + Triple += getVendorName(); + Triple += "-"; + Triple += getOSAndEnvironmentName(); + setTriple(Triple.str()); +} + +void Triple::setVendorName(StringRef Str) { + setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName()); +} + +void Triple::setOSName(StringRef Str) { + if (hasEnvironment()) + setTriple(getArchName() + "-" + getVendorName() + "-" + Str + + "-" + getEnvironmentName()); + else + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} + +void Triple::setEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() + + "-" + Str); +} + +void Triple::setOSAndEnvironmentName(StringRef Str) { + setTriple(getArchName() + "-" + getVendorName() + "-" + Str); +} diff --git a/final/lib/Support/Twine.cpp b/final/lib/Support/Twine.cpp new file mode 100644 index 00000000000..75cea2961a9 --- /dev/null +++ b/final/lib/Support/Twine.cpp @@ -0,0 +1,160 @@ +//===-- Twine.cpp - Fast Temporary String Concatenation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +std::string Twine::str() const { + SmallString<256> Vec; + return toStringRef(Vec).str(); +} + +void Twine::toVector(SmallVectorImpl &Out) const { + raw_svector_ostream OS(Out); + print(OS); +} + +StringRef Twine::toStringRef(SmallVectorImpl &Out) const { + if (isSingleStringRef()) + return getSingleStringRef(); + toVector(Out); + return StringRef(Out.data(), Out.size()); +} + +StringRef Twine::toNullTerminatedStringRef(SmallVectorImpl &Out) const { + if (isUnary()) { + switch (getLHSKind()) { + case CStringKind: + // Already null terminated, yay! + return StringRef(static_cast(LHS)); + case StdStringKind: { + const std::string *str = static_cast(LHS); + return StringRef(str->c_str(), str->size()); + } + default: + break; + } + } + toVector(Out); + Out.push_back(0); + Out.pop_back(); + return StringRef(Out.data(), Out.size()); +} + +void Twine::printOneChild(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: break; + case Twine::EmptyKind: break; + case Twine::TwineKind: + static_cast(Ptr)->print(OS); + break; + case Twine::CStringKind: + OS << static_cast(Ptr); + break; + case Twine::StdStringKind: + OS << *static_cast(Ptr); + break; + case Twine::StringRefKind: + OS << *static_cast(Ptr); + break; + case Twine::DecUIKind: + OS << (unsigned)(uintptr_t)Ptr; + break; + case Twine::DecIKind: + OS << (int)(intptr_t)Ptr; + break; + case Twine::DecULKind: + OS << *static_cast(Ptr); + break; + case Twine::DecLKind: + OS << *static_cast(Ptr); + break; + case Twine::DecULLKind: + OS << *static_cast(Ptr); + break; + case Twine::DecLLKind: + OS << *static_cast(Ptr); + break; + case Twine::UHexKind: + OS.write_hex(*static_cast(Ptr)); + break; + } +} + +void Twine::printOneChildRepr(raw_ostream &OS, const void *Ptr, + NodeKind Kind) const { + switch (Kind) { + case Twine::NullKind: + OS << "null"; break; + case Twine::EmptyKind: + OS << "empty"; break; + case Twine::TwineKind: + OS << "rope:"; + static_cast(Ptr)->printRepr(OS); + break; + case Twine::CStringKind: + OS << "cstring:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::StdStringKind: + OS << "std::string:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::StringRefKind: + OS << "stringref:\"" + << static_cast(Ptr) << "\""; + break; + case Twine::DecUIKind: + OS << "decUI:\"" << (unsigned)(uintptr_t)Ptr << "\""; + break; + case Twine::DecIKind: + OS << "decI:\"" << (int)(intptr_t)Ptr << "\""; + break; + case Twine::DecULKind: + OS << "decUL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecLKind: + OS << "decL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecULLKind: + OS << "decULL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::DecLLKind: + OS << "decLL:\"" << *static_cast(Ptr) << "\""; + break; + case Twine::UHexKind: + OS << "uhex:\"" << static_cast(Ptr) << "\""; + break; + } +} + +void Twine::print(raw_ostream &OS) const { + printOneChild(OS, LHS, getLHSKind()); + printOneChild(OS, RHS, getRHSKind()); +} + +void Twine::printRepr(raw_ostream &OS) const { + OS << "(Twine "; + printOneChildRepr(OS, LHS, getLHSKind()); + OS << " "; + printOneChildRepr(OS, RHS, getRHSKind()); + OS << ")"; +} + +void Twine::dump() const { + print(llvm::dbgs()); +} + +void Twine::dumpRepr() const { + printRepr(llvm::dbgs()); +} diff --git a/final/lib/Support/Unix/Host.inc b/final/lib/Support/Unix/Host.inc new file mode 100644 index 00000000000..ed74b675990 --- /dev/null +++ b/final/lib/Support/Unix/Host.inc @@ -0,0 +1,97 @@ + //===- llvm/Support/Unix/Host.inc -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the UNIX Host support. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/ADT/StringRef.h" +#include "Unix.h" +#include +#include +#include + +using namespace llvm; + +static std::string getOSVersion() { + struct utsname info; + + if (uname(&info)) + return ""; + + return info.release; +} + +std::string sys::getHostTriple() { + // FIXME: Derive directly instead of relying on the autoconf generated + // variable. + + StringRef HostTripleString(LLVM_HOSTTRIPLE); + std::pair ArchSplit = HostTripleString.split('-'); + + // Normalize the arch, since the host triple may not actually match the host. + std::string Arch = ArchSplit.first; + + // It would be nice to do this in terms of llvm::Triple, but that is in + // Support which is layered above us. +#if defined(__x86_64__) + Arch = "x86_64"; +#elif defined(__i386__) + Arch = "i386"; +#elif defined(__ppc64__) + Arch = "powerpc64"; +#elif defined(__ppc__) + Arch = "powerpc"; +#elif defined(__arm__) + + // FIXME: We need to pick the right ARM triple (which involves querying the + // chip). However, for now this is most important for LLVM arch selection, so + // we only need to make sure to distinguish ARM and Thumb. +# if defined(__thumb__) + Arch = "thumb"; +# else + Arch = "arm"; +# endif + +#else + + // FIXME: When enough auto-detection is in place, this should just + // #error. Then at least the arch selection is done, and we only need the OS + // etc selection to kill off the use of LLVM_HOSTTRIPLE. + +#endif + + std::string Triple(Arch); + Triple += '-'; + Triple += ArchSplit.second; + + // Force i86 to i386. + if (Triple[0] == 'i' && isdigit(Triple[1]) && + Triple[2] == '8' && Triple[3] == '6') + Triple[1] = '3'; + + // On darwin, we want to update the version to match that of the + // host. + std::string::size_type DarwinDashIdx = Triple.find("-darwin"); + if (DarwinDashIdx != std::string::npos) { + Triple.resize(DarwinDashIdx + strlen("-darwin")); + + // Only add the major part of the os version. + std::string Version = getOSVersion(); + Triple += Version.substr(0, Version.find('.')); + } + + return Triple; +} diff --git a/final/lib/Support/Unix/Memory.inc b/final/lib/Support/Unix/Memory.inc new file mode 100644 index 00000000000..4312d67183c --- /dev/null +++ b/final/lib/Support/Unix/Memory.inc @@ -0,0 +1,151 @@ +//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- 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 some functions for various memory management utilities. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Process.h" + +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#ifdef __APPLE__ +#include +#endif + +/// AllocateRWX - Allocate a slab of memory with read/write/execute +/// permissions. This is typically used for JIT applications where we want +/// to emit code to the memory then jump to it. Getting this type of memory +/// is very OS specific. +/// +llvm::sys::MemoryBlock +llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, + std::string *ErrMsg) { + if (NumBytes == 0) return MemoryBlock(); + + size_t pageSize = Process::GetPageSize(); + size_t NumPages = (NumBytes+pageSize-1)/pageSize; + + int fd = -1; +#ifdef NEED_DEV_ZERO_FOR_MMAP + static int zero_fd = open("/dev/zero", O_RDWR); + if (zero_fd == -1) { + MakeErrMsg(ErrMsg, "Can't open /dev/zero device"); + return MemoryBlock(); + } + fd = zero_fd; +#endif + + int flags = MAP_PRIVATE | +#ifdef HAVE_MMAP_ANONYMOUS + MAP_ANONYMOUS +#else + MAP_ANON +#endif + ; + + void* start = NearBlock ? (unsigned char*)NearBlock->base() + + NearBlock->size() : 0; + +#if defined(__APPLE__) && defined(__arm__) + void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC, + flags, fd, 0); +#else + void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + flags, fd, 0); +#endif + if (pa == MAP_FAILED) { + if (NearBlock) //Try again without a near hint + return AllocateRWX(NumBytes, 0); + + MakeErrMsg(ErrMsg, "Can't allocate RWX Memory"); + return MemoryBlock(); + } + +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa, + (vm_size_t)(pageSize*NumPages), 0, + VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + if (KERN_SUCCESS != kr) { + MakeErrMsg(ErrMsg, "vm_protect max RX failed"); + return sys::MemoryBlock(); + } + + kr = vm_protect(mach_task_self(), (vm_address_t)pa, + (vm_size_t)(pageSize*NumPages), 0, + VM_PROT_READ | VM_PROT_WRITE); + if (KERN_SUCCESS != kr) { + MakeErrMsg(ErrMsg, "vm_protect RW failed"); + return sys::MemoryBlock(); + } +#endif + + MemoryBlock result; + result.Address = pa; + result.Size = NumPages*pageSize; + + return result; +} + +bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + if (M.Address == 0 || M.Size == 0) return false; + if (0 != ::munmap(M.Address, M.Size)) + return MakeErrMsg(ErrMsg, "Can't release RWX Memory"); + return false; +} + +bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) { +#if defined(__APPLE__) && defined(__arm__) + if (M.Address == 0 || M.Size == 0) return false; + sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, + (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} + +bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) { +#if defined(__APPLE__) && defined(__arm__) + if (M.Address == 0 || M.Size == 0) return false; + sys::Memory::InvalidateInstructionCache(M.Address, M.Size); + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address, + (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + return KERN_SUCCESS == kr; +#else + return false; +#endif +} + +bool llvm::sys::Memory::setRangeWritable(const void *Addr, size_t Size) { +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, + (vm_size_t)Size, 0, + VM_PROT_READ | VM_PROT_WRITE); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} + +bool llvm::sys::Memory::setRangeExecutable(const void *Addr, size_t Size) { +#if defined(__APPLE__) && defined(__arm__) + kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr, + (vm_size_t)Size, 0, + VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); + return KERN_SUCCESS == kr; +#else + return true; +#endif +} diff --git a/final/lib/Support/Unix/Mutex.inc b/final/lib/Support/Unix/Mutex.inc new file mode 100644 index 00000000000..fe6b1704145 --- /dev/null +++ b/final/lib/Support/Unix/Mutex.inc @@ -0,0 +1,43 @@ +//===- llvm/Support/Unix/Mutex.inc - Unix Mutex Implementation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific (non-pthread) Mutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm +{ +using namespace sys; + +MutexImpl::MutexImpl( bool recursive) +{ +} + +MutexImpl::~MutexImpl() +{ +} + +bool +MutexImpl::release() +{ + return true; +} + +bool +MutexImpl::tryacquire( void ) +{ + return true; +} + +} diff --git a/final/lib/Support/Unix/Path.inc b/final/lib/Support/Unix/Path.inc new file mode 100644 index 00000000000..0f6e800505e --- /dev/null +++ b/final/lib/Support/Unix/Path.inc @@ -0,0 +1,887 @@ +//===- llvm/Support/Unix/Path.cpp - Unix Path Implementation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific portion of the Path class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UTIME_H +#include +#endif +#if HAVE_TIME_H +#include +#endif +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#if HAVE_DLFCN_H +#include +#endif + +#ifdef __APPLE__ +#include +#endif + +// Put in a hack for Cygwin which falsely reports that the mkdtemp function +// is available when it is not. +#ifdef __CYGWIN__ +# undef HAVE_MKDTEMP +#endif + +namespace { +inline bool lastIsSlash(const std::string& path) { + return !path.empty() && path[path.length() - 1] == '/'; +} + +} + +namespace llvm { +using namespace sys; + +const char sys::PathSeparator = ':'; + +StringRef Path::GetEXESuffix() { + return StringRef(); +} + +Path::Path(StringRef p) + : path(p) {} + +Path::Path(const char *StrStart, unsigned StrLen) + : path(StrStart, StrLen) {} + +Path& +Path::operator=(StringRef that) { + path.assign(that.data(), that.size()); + return *this; +} + +bool +Path::isValid() const { + // Empty paths are considered invalid here. + // This code doesn't check MAXPATHLEN because there's no need. Nothing in + // LLVM manipulates Paths with fixed-sizes arrays, and if the OS can't + // handle names longer than some limit, it'll report this on demand using + // ENAMETOLONG. + return !path.empty(); +} + +bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + if (NameLen == 0) + return false; + return NameStart[0] == '/'; +} + +bool +Path::isAbsolute() const { + if (path.empty()) + return false; + return path[0] == '/'; +} + +Path +Path::GetRootDirectory() { + Path result; + result.set("/"); + return result; +} + +Path +Path::GetTemporaryDirectory(std::string *ErrMsg) { +#if defined(HAVE_MKDTEMP) + // The best way is with mkdtemp but that's not available on many systems, + // Linux and FreeBSD have it. Others probably won't. + char pathname[] = "/tmp/llvm_XXXXXX"; + if (0 == mkdtemp(pathname)) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + return Path(pathname); +#elif defined(HAVE_MKSTEMP) + // If no mkdtemp is available, mkstemp can be used to create a temporary file + // which is then removed and created as a directory. We prefer this over + // mktemp because of mktemp's inherent security and threading risks. We still + // have a slight race condition from the time the temporary file is created to + // the time it is re-created as a directoy. + char pathname[] = "/tmp/llvm_XXXXXX"; + int fd = 0; + if (-1 == (fd = mkstemp(pathname))) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + ::close(fd); + ::unlink(pathname); // start race condition, ignore errors + if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + return Path(pathname); +#elif defined(HAVE_MKTEMP) + // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have + // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable + // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing + // the XXXXXX with the pid of the process and a letter. That leads to only + // twenty six temporary files that can be generated. + char pathname[] = "/tmp/llvm_XXXXXX"; + char *TmpName = ::mktemp(pathname); + if (TmpName == 0) { + MakeErrMsg(ErrMsg, + std::string(TmpName) + ": can't create unique directory name"); + return Path(); + } + if (-1 == ::mkdir(TmpName, S_IRWXU)) { + MakeErrMsg(ErrMsg, + std::string(TmpName) + ": can't create temporary directory"); + return Path(); + } + return Path(TmpName); +#else + // This is the worst case implementation. tempnam(3) leaks memory unless its + // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread + // issues. The mktemp(3) function doesn't have enough variability in the + // temporary name generated. So, we provide our own implementation that + // increments an integer from a random number seeded by the current time. This + // should be sufficiently unique that we don't have many collisions between + // processes. Generally LLVM processes don't run very long and don't use very + // many temporary files so this shouldn't be a big issue for LLVM. + static time_t num = ::time(0); + char pathname[MAXPATHLEN]; + do { + num++; + sprintf(pathname, "/tmp/llvm_%010u", unsigned(num)); + } while ( 0 == access(pathname, F_OK ) ); + if (-1 == ::mkdir(pathname, S_IRWXU)) { + MakeErrMsg(ErrMsg, + std::string(pathname) + ": can't create temporary directory"); + return Path(); + } + return Path(pathname); +#endif +} + +void +Path::GetSystemLibraryPaths(std::vector& Paths) { +#ifdef LTDL_SHLIBPATH_VAR + char* env_var = getenv(LTDL_SHLIBPATH_VAR); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#endif + // FIXME: Should this look at LD_LIBRARY_PATH too? + Paths.push_back(sys::Path("/usr/local/lib/")); + Paths.push_back(sys::Path("/usr/X11R6/lib/")); + Paths.push_back(sys::Path("/usr/lib/")); + Paths.push_back(sys::Path("/lib/")); +} + +void +Path::GetBitcodeLibraryPaths(std::vector& Paths) { + char * env_var = getenv("LLVM_LIB_SEARCH_PATH"); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#ifdef LLVM_LIBDIR + { + Path tmpPath; + if (tmpPath.set(LLVM_LIBDIR)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + } +#endif + GetSystemLibraryPaths(Paths); +} + +Path +Path::GetLLVMDefaultConfigDir() { + return Path("/etc/llvm/"); +} + +Path +Path::GetUserHomeDirectory() { + const char* home = getenv("HOME"); + Path result; + if (home && result.set(home)) + return result; + result.set("/"); + return result; +} + +Path +Path::GetCurrentDirectory() { + char pathname[MAXPATHLEN]; + if (!getcwd(pathname,MAXPATHLEN)) { + assert (false && "Could not query current working directory."); + return Path(); + } + + return Path(pathname); +} + +#if defined(__FreeBSD__) || defined (__NetBSD__) || \ + defined(__OpenBSD__) || defined(__minix) +static int +test_dir(char buf[PATH_MAX], char ret[PATH_MAX], + const char *dir, const char *bin) +{ + struct stat sb; + + snprintf(buf, PATH_MAX, "%s/%s", dir, bin); + if (realpath(buf, ret) == NULL) + return (1); + if (stat(buf, &sb) != 0) + return (1); + + return (0); +} + +static char * +getprogpath(char ret[PATH_MAX], const char *bin) +{ + char *pv, *s, *t, buf[PATH_MAX]; + + /* First approach: absolute path. */ + if (bin[0] == '/') { + if (test_dir(buf, ret, "/", bin) == 0) + return (ret); + return (NULL); + } + + /* Second approach: relative path. */ + if (strchr(bin, '/') != NULL) { + if (getcwd(buf, PATH_MAX) == NULL) + return (NULL); + if (test_dir(buf, ret, buf, bin) == 0) + return (ret); + return (NULL); + } + + /* Third approach: $PATH */ + if ((pv = getenv("PATH")) == NULL) + return (NULL); + s = pv = strdup(pv); + if (pv == NULL) + return (NULL); + while ((t = strsep(&s, ":")) != NULL) { + if (test_dir(buf, ret, t, bin) == 0) { + free(pv); + return (ret); + } + } + free(pv); + return (NULL); +} +#endif // __FreeBSD__ || __NetBSD__ + +/// GetMainExecutable - Return the path to the main executable, given the +/// value of argv[0] from program startup. +Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { +#if defined(__APPLE__) + // On OS X the executable path is saved to the stack by dyld. Reading it + // from there is much faster than calling dladdr, especially for large + // binaries with symbols. + char exe_path[MAXPATHLEN]; + uint32_t size = sizeof(exe_path); + if (_NSGetExecutablePath(exe_path, &size) == 0) { + char link_path[MAXPATHLEN]; + if (realpath(exe_path, link_path)) + return Path(link_path); + } +#elif defined(__FreeBSD__) || defined (__NetBSD__) || \ + defined(__OpenBSD__) || defined(__minix) + char exe_path[PATH_MAX]; + + if (getprogpath(exe_path, argv0) != NULL) + return Path(exe_path); +#elif defined(__linux__) || defined(__CYGWIN__) + char exe_path[MAXPATHLEN]; + ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); + if (len >= 0) + return Path(StringRef(exe_path, len)); +#elif defined(HAVE_DLFCN_H) + // Use dladdr to get executable path if available. + Dl_info DLInfo; + int err = dladdr(MainAddr, &DLInfo); + if (err == 0) + return Path(); + + // If the filename is a symlink, we need to resolve and return the location of + // the actual executable. + char link_path[MAXPATHLEN]; + if (realpath(DLInfo.dli_fname, link_path)) + return Path(link_path); +#else +#error GetMainExecutable is not implemented on this host yet. +#endif + return Path(); +} + + +StringRef Path::getDirname() const { + return getDirnameCharSep(path, "/"); +} + +StringRef +Path::getBasename() const { + // Find the last slash + std::string::size_type slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + std::string::size_type dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return StringRef(path).substr(slash); + else + return StringRef(path).substr(slash, dot - slash); +} + +StringRef +Path::getSuffix() const { + // Find the last slash + std::string::size_type slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + std::string::size_type dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return StringRef(); + else + return StringRef(path).substr(dot + 1); +} + +bool Path::getMagicNumber(std::string &Magic, unsigned len) const { + assert(len < 1024 && "Request for magic string too long"); + char Buf[1025]; + int fd = ::open(path.c_str(), O_RDONLY); + if (fd < 0) + return false; + ssize_t bytes_read = ::read(fd, Buf, len); + ::close(fd); + if (ssize_t(len) != bytes_read) + return false; + Magic.assign(Buf, len); + return true; +} + +bool +Path::exists() const { + return 0 == access(path.c_str(), F_OK ); +} + +bool +Path::isDirectory() const { + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return false; + return ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false; +} + +bool +Path::isSymLink() const { + struct stat buf; + if (0 != lstat(path.c_str(), &buf)) + return false; + return S_ISLNK(buf.st_mode); +} + + +bool +Path::canRead() const { + return 0 == access(path.c_str(), R_OK); +} + +bool +Path::canWrite() const { + return 0 == access(path.c_str(), W_OK); +} + +bool +Path::isRegularFile() const { + // Get the status so we can determine if it's a file or directory + struct stat buf; + + if (0 != stat(path.c_str(), &buf)) + return false; + + if (S_ISREG(buf.st_mode)) + return true; + + return false; +} + +bool +Path::canExecute() const { + if (0 != access(path.c_str(), R_OK | X_OK )) + return false; + struct stat buf; + if (0 != stat(path.c_str(), &buf)) + return false; + if (!S_ISREG(buf.st_mode)) + return false; + return true; +} + +StringRef +Path::getLast() const { + // Find the last slash + size_t pos = path.rfind('/'); + + // Handle the corner cases + if (pos == std::string::npos) + return path; + + // If the last character is a slash + if (pos == path.length()-1) { + // Find the second to last slash + size_t pos2 = path.rfind('/', pos-1); + if (pos2 == std::string::npos) + return StringRef(path).substr(0,pos); + else + return StringRef(path).substr(pos2+1,pos-pos2-1); + } + // Return everything after the last slash + return StringRef(path).substr(pos+1); +} + +const FileStatus * +PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { + if (!fsIsValid || update) { + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrStr, path + ": can't get status of file"); + return 0; + } + status.fileSize = buf.st_size; + status.modTime.fromEpochTime(buf.st_mtime); + status.mode = buf.st_mode; + status.user = buf.st_uid; + status.group = buf.st_gid; + status.uniqueID = uint64_t(buf.st_ino); + status.isDir = S_ISDIR(buf.st_mode); + status.isFile = S_ISREG(buf.st_mode); + fsIsValid = true; + } + return &status; +} + +static bool AddPermissionBits(const Path &File, int bits) { + // Get the umask value from the operating system. We want to use it + // when changing the file's permissions. Since calling umask() sets + // the umask and returns its old value, we must call it a second + // time to reset it to the user's preference. + int mask = umask(0777); // The arg. to umask is arbitrary. + umask(mask); // Restore the umask. + + // Get the file's current mode. + struct stat buf; + if (0 != stat(File.c_str(), &buf)) + return false; + // Change the file to have whichever permissions bits from 'bits' + // that the umask would not disable. + if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1) + return false; + return true; +} + +bool Path::makeReadableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0444)) + return MakeErrMsg(ErrMsg, path + ": can't make file readable"); + return false; +} + +bool Path::makeWriteableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0222)) + return MakeErrMsg(ErrMsg, path + ": can't make file writable"); + return false; +} + +bool Path::makeExecutableOnDisk(std::string* ErrMsg) { + if (!AddPermissionBits(*this, 0111)) + return MakeErrMsg(ErrMsg, path + ": can't make file executable"); + return false; +} + +bool +Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const { + DIR* direntries = ::opendir(path.c_str()); + if (direntries == 0) + return MakeErrMsg(ErrMsg, path + ": can't open directory"); + + std::string dirPath = path; + if (!lastIsSlash(dirPath)) + dirPath += '/'; + + result.clear(); + struct dirent* de = ::readdir(direntries); + for ( ; de != 0; de = ::readdir(direntries)) { + if (de->d_name[0] != '.') { + Path aPath(dirPath + (const char*)de->d_name); + struct stat st; + if (0 != lstat(aPath.path.c_str(), &st)) { + if (S_ISLNK(st.st_mode)) + continue; // dangling symlink -- ignore + return MakeErrMsg(ErrMsg, + aPath.path + ": can't determine file object type"); + } + result.insert(aPath); + } + } + + closedir(direntries); + return false; +} + +bool +Path::set(StringRef a_path) { + if (a_path.empty()) + return false; + path = a_path; + return true; +} + +bool +Path::appendComponent(StringRef name) { + if (name.empty()) + return false; + if (!lastIsSlash(path)) + path += '/'; + path += name; + return true; +} + +bool +Path::eraseComponent() { + size_t slashpos = path.rfind('/',path.size()); + if (slashpos == 0 || slashpos == std::string::npos) { + path.erase(); + return true; + } + if (slashpos == path.size() - 1) + slashpos = path.rfind('/',slashpos-1); + if (slashpos == std::string::npos) { + path.erase(); + return true; + } + path.erase(slashpos); + return true; +} + +bool +Path::eraseSuffix() { + size_t dotpos = path.rfind('.',path.size()); + size_t slashpos = path.rfind('/',path.size()); + if (dotpos != std::string::npos) { + if (slashpos == std::string::npos || dotpos > slashpos+1) { + path.erase(dotpos, path.size()-dotpos); + return true; + } + } + return false; +} + +static bool createDirectoryHelper(char* beg, char* end, bool create_parents) { + + if (access(beg, R_OK | W_OK) == 0) + return false; + + if (create_parents) { + + char* c = end; + + for (; c != beg; --c) + if (*c == '/') { + + // Recurse to handling the parent directory. + *c = '\0'; + bool x = createDirectoryHelper(beg, c, create_parents); + *c = '/'; + + // Return if we encountered an error. + if (x) + return true; + + break; + } + } + + return mkdir(beg, S_IRWXU | S_IRWXG) != 0; +} + +bool +Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) { + // Get a writeable copy of the path name + std::string pathname(path); + + // Null-terminate the last component + size_t lastchar = path.length() - 1 ; + + if (pathname[lastchar] != '/') + ++lastchar; + + pathname[lastchar] = '\0'; + + if (createDirectoryHelper(&pathname[0], &pathname[lastchar], create_parents)) + return MakeErrMsg(ErrMsg, pathname + ": can't create directory"); + + return false; +} + +bool +Path::createFileOnDisk(std::string* ErrMsg) { + // Create the file + int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR); + if (fd < 0) + return MakeErrMsg(ErrMsg, path + ": can't create file"); + ::close(fd); + return false; +} + +bool +Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { + // Make this into a unique file name + if (makeUnique( reuse_current, ErrMsg )) + return true; + + // create the file + int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (fd < 0) + return MakeErrMsg(ErrMsg, path + ": can't create temporary file"); + ::close(fd); + return false; +} + +bool +Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { + // Get the status so we can determine if it's a file or directory. + struct stat buf; + if (0 != stat(path.c_str(), &buf)) { + MakeErrMsg(ErrStr, path + ": can't get status of file"); + return true; + } + + // Note: this check catches strange situations. In all cases, LLVM should + // only be involved in the creation and deletion of regular files. This + // check ensures that what we're trying to erase is a regular file. It + // effectively prevents LLVM from erasing things like /dev/null, any block + // special file, or other things that aren't "regular" files. + if (S_ISREG(buf.st_mode)) { + if (unlink(path.c_str()) != 0) + return MakeErrMsg(ErrStr, path + ": can't destroy file"); + return false; + } + + if (!S_ISDIR(buf.st_mode)) { + if (ErrStr) *ErrStr = "not a file or directory"; + return true; + } + + if (remove_contents) { + // Recursively descend the directory to remove its contents. + std::string cmd = "/bin/rm -rf " + path; + if (system(cmd.c_str()) != 0) { + MakeErrMsg(ErrStr, path + ": failed to recursively remove directory."); + return true; + } + return false; + } + + // Otherwise, try to just remove the one directory. + std::string pathname(path); + size_t lastchar = path.length() - 1; + if (pathname[lastchar] == '/') + pathname[lastchar] = '\0'; + else + pathname[lastchar+1] = '\0'; + + if (rmdir(pathname.c_str()) != 0) + return MakeErrMsg(ErrStr, pathname + ": can't erase directory"); + return false; +} + +bool +Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { + if (0 != ::rename(path.c_str(), newName.c_str())) + return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + + newName.str() + "'"); + return false; +} + +bool +Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const { + struct utimbuf utb; + utb.actime = si.modTime.toPosixTime(); + utb.modtime = utb.actime; + if (0 != ::utime(path.c_str(),&utb)) + return MakeErrMsg(ErrStr, path + ": can't set file modification time"); + if (0 != ::chmod(path.c_str(),si.mode)) + return MakeErrMsg(ErrStr, path + ": can't set mode"); + return false; +} + +bool +sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){ + int inFile = -1; + int outFile = -1; + inFile = ::open(Src.c_str(), O_RDONLY); + if (inFile == -1) + return MakeErrMsg(ErrMsg, Src.str() + + ": can't open source file to copy"); + + outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666); + if (outFile == -1) { + ::close(inFile); + return MakeErrMsg(ErrMsg, Dest.str() + + ": can't create destination file for copy"); + } + + char Buffer[16*1024]; + while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) { + if (Amt == -1) { + if (errno != EINTR && errno != EAGAIN) { + ::close(inFile); + ::close(outFile); + return MakeErrMsg(ErrMsg, Src.str()+": can't read source file"); + } + } else { + char *BufPtr = Buffer; + while (Amt) { + ssize_t AmtWritten = ::write(outFile, BufPtr, Amt); + if (AmtWritten == -1) { + if (errno != EINTR && errno != EAGAIN) { + ::close(inFile); + ::close(outFile); + return MakeErrMsg(ErrMsg, Dest.str() + + ": can't write destination file"); + } + } else { + Amt -= AmtWritten; + BufPtr += AmtWritten; + } + } + } + } + ::close(inFile); + ::close(outFile); + return false; +} + +bool +Path::makeUnique(bool reuse_current, std::string* ErrMsg) { + bool Exists; + if (reuse_current && (fs::exists(path, Exists) || !Exists)) + return false; // File doesn't exist already, just use it! + + // Append an XXXXXX pattern to the end of the file for use with mkstemp, + // mktemp or our own implementation. + // This uses std::vector instead of SmallVector to avoid a dependence on + // libSupport. And performance isn't critical here. + std::vector Buf; + Buf.resize(path.size()+8); + char *FNBuffer = &Buf[0]; + path.copy(FNBuffer,path.size()); + bool isdir; + if (!fs::is_directory(path, isdir) && isdir) + strcpy(FNBuffer+path.size(), "/XXXXXX"); + else + strcpy(FNBuffer+path.size(), "-XXXXXX"); + +#if defined(HAVE_MKSTEMP) + int TempFD; + if ((TempFD = mkstemp(FNBuffer)) == -1) + return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); + + // We don't need to hold the temp file descriptor... we will trust that no one + // will overwrite/delete the file before we can open it again. + close(TempFD); + + // Save the name + path = FNBuffer; +#elif defined(HAVE_MKTEMP) + // If we don't have mkstemp, use the old and obsolete mktemp function. + if (mktemp(FNBuffer) == 0) + return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); + + // Save the name + path = FNBuffer; +#else + // Okay, looks like we have to do it all by our lonesome. + static unsigned FCounter = 0; + // Try to initialize with unique value. + if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8; + char* pos = strstr(FNBuffer, "XXXXXX"); + do { + if (++FCounter > 0xFFFFFF) { + return MakeErrMsg(ErrMsg, + path + ": can't make unique filename: too many files"); + } + sprintf(pos, "%06X", FCounter); + path = FNBuffer; + } while (exists()); + // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit + // LLVM. +#endif + return false; +} + +const char *Path::MapInFilePages(int FD, uint64_t FileSize) { + int Flags = MAP_PRIVATE; +#ifdef MAP_FILE + Flags |= MAP_FILE; +#endif + void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0); + if (BasePtr == MAP_FAILED) + return 0; + return (const char*)BasePtr; +} + +void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) { + ::munmap((void*)BasePtr, FileSize); +} + +} // end llvm namespace diff --git a/final/lib/Support/Unix/PathV2.inc b/final/lib/Support/Unix/PathV2.inc new file mode 100644 index 00000000000..03ff28367e4 --- /dev/null +++ b/final/lib/Support/Unix/PathV2.inc @@ -0,0 +1,507 @@ +//===- llvm/Support/Unix/PathV2.cpp - Unix Path Implementation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific implementation of the PathV2 API. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif +#if HAVE_STDIO_H +#include +#endif + +using namespace llvm; + +namespace { + /// This class automatically closes the given file descriptor when it goes out + /// of scope. You can take back explicit ownership of the file descriptor by + /// calling take(). The destructor does not verify that close was successful. + /// Therefore, never allow this class to call close on a file descriptor that + /// has been read from or written to. + struct AutoFD { + int FileDescriptor; + + AutoFD(int fd) : FileDescriptor(fd) {} + ~AutoFD() { + if (FileDescriptor >= 0) + ::close(FileDescriptor); + } + + int take() { + int ret = FileDescriptor; + FileDescriptor = -1; + return ret; + } + + operator int() const {return FileDescriptor;} + }; + + error_code TempDir(SmallVectorImpl &result) { + // FIXME: Don't use TMPDIR if program is SUID or SGID enabled. + const char *dir = 0; + (dir = std::getenv("TMPDIR" )) || + (dir = std::getenv("TMP" )) || + (dir = std::getenv("TEMP" )) || + (dir = std::getenv("TEMPDIR")) || +#ifdef P_tmpdir + (dir = P_tmpdir) || +#endif + (dir = "/tmp"); + + result.clear(); + StringRef d(dir); + result.append(d.begin(), d.end()); + return success; + } +} + +namespace llvm { +namespace sys { +namespace fs { + +error_code current_path(SmallVectorImpl &result) { + result.reserve(MAXPATHLEN); + + while (true) { + if (::getcwd(result.data(), result.capacity()) == 0) { + // See if there was a real error. + if (errno != errc::not_enough_memory) + return error_code(errno, system_category()); + // Otherwise there just wasn't enough space. + result.reserve(result.capacity() * 2); + } else + break; + } + + result.set_size(strlen(result.data())); + return success; +} + +error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toNullTerminatedStringRef(from_storage); + StringRef t = to.toNullTerminatedStringRef(to_storage); + + const size_t buf_sz = 32768; + char buffer[buf_sz]; + int from_file = -1, to_file = -1; + + // Open from. + if ((from_file = ::open(f.begin(), O_RDONLY)) < 0) + return error_code(errno, system_category()); + AutoFD from_fd(from_file); + + // Stat from. + struct stat from_stat; + if (::stat(f.begin(), &from_stat) != 0) + return error_code(errno, system_category()); + + // Setup to flags. + int to_flags = O_CREAT | O_WRONLY; + if (copt == copy_option::fail_if_exists) + to_flags |= O_EXCL; + + // Open to. + if ((to_file = ::open(t.begin(), to_flags, from_stat.st_mode)) < 0) + return error_code(errno, system_category()); + AutoFD to_fd(to_file); + + // Copy! + ssize_t sz, sz_read = 1, sz_write; + while (sz_read > 0 && + (sz_read = ::read(from_fd, buffer, buf_sz)) > 0) { + // Allow for partial writes - see Advanced Unix Programming (2nd Ed.), + // Marc Rochkind, Addison-Wesley, 2004, page 94 + sz_write = 0; + do { + if ((sz = ::write(to_fd, buffer + sz_write, sz_read - sz_write)) < 0) { + sz_read = sz; // cause read loop termination. + break; // error. + } + sz_write += sz; + } while (sz_write < sz_read); + } + + // After all the file operations above the return value of close actually + // matters. + if (::close(from_fd.take()) < 0) sz_read = -1; + if (::close(to_fd.take()) < 0) sz_read = -1; + + // Check for errors. + if (sz_read < 0) + return error_code(errno, system_category()); + + return success; +} + +error_code create_directory(const Twine &path, bool &existed) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { + if (errno != errc::file_exists) + return error_code(errno, system_category()); + existed = true; + } else + existed = false; + + return success; +} + +error_code create_hard_link(const Twine &to, const Twine &from) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toNullTerminatedStringRef(from_storage); + StringRef t = to.toNullTerminatedStringRef(to_storage); + + if (::link(t.begin(), f.begin()) == -1) + return error_code(errno, system_category()); + + return success; +} + +error_code create_symlink(const Twine &to, const Twine &from) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toNullTerminatedStringRef(from_storage); + StringRef t = to.toNullTerminatedStringRef(to_storage); + + if (::symlink(t.begin(), f.begin()) == -1) + return error_code(errno, system_category()); + + return success; +} + +error_code remove(const Twine &path, bool &existed) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + if (::remove(p.begin()) == -1) { + if (errno != errc::no_such_file_or_directory) + return error_code(errno, system_category()); + existed = false; + } else + existed = true; + + return success; +} + +error_code rename(const Twine &from, const Twine &to) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toNullTerminatedStringRef(from_storage); + StringRef t = to.toNullTerminatedStringRef(to_storage); + + if (::rename(f.begin(), t.begin()) == -1) { + // If it's a cross device link, copy then delete, otherwise return the error + if (errno == EXDEV) { + if (error_code ec = copy_file(from, to, copy_option::overwrite_if_exists)) + return ec; + bool Existed; + if (error_code ec = remove(from, Existed)) + return ec; + } else + return error_code(errno, system_category()); + } + + return success; +} + +error_code resize_file(const Twine &path, uint64_t size) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + if (::truncate(p.begin(), size) == -1) + return error_code(errno, system_category()); + + return success; +} + +error_code exists(const Twine &path, bool &result) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + struct stat status; + if (::stat(p.begin(), &status) == -1) { + if (errno != errc::no_such_file_or_directory) + return error_code(errno, system_category()); + result = false; + } else + result = true; + + return success; +} + +error_code equivalent(const Twine &A, const Twine &B, bool &result) { + // Get arguments. + SmallString<128> a_storage; + SmallString<128> b_storage; + StringRef a = A.toNullTerminatedStringRef(a_storage); + StringRef b = B.toNullTerminatedStringRef(b_storage); + + struct stat stat_a, stat_b; + int error_b = ::stat(b.begin(), &stat_b); + int error_a = ::stat(a.begin(), &stat_a); + + // If both are invalid, it's an error. If only one is, the result is false. + if (error_a != 0 || error_b != 0) { + if (error_a == error_b) + return error_code(errno, system_category()); + result = false; + } else { + result = + stat_a.st_dev == stat_b.st_dev && + stat_a.st_ino == stat_b.st_ino; + } + + return success; +} + +error_code file_size(const Twine &path, uint64_t &result) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + struct stat status; + if (::stat(p.begin(), &status) == -1) + return error_code(errno, system_category()); + if (!S_ISREG(status.st_mode)) + return make_error_code(errc::operation_not_permitted); + + result = status.st_size; + return success; +} + +error_code status(const Twine &path, file_status &result) { + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + + struct stat status; + if (::stat(p.begin(), &status) != 0) { + error_code ec(errno, system_category()); + if (ec == errc::no_such_file_or_directory) + result = file_status(file_type::file_not_found); + else + result = file_status(file_type::status_error); + return ec; + } + + if (S_ISDIR(status.st_mode)) + result = file_status(file_type::directory_file); + else if (S_ISREG(status.st_mode)) + result = file_status(file_type::regular_file); + else if (S_ISBLK(status.st_mode)) + result = file_status(file_type::block_file); + else if (S_ISCHR(status.st_mode)) + result = file_status(file_type::character_file); + else if (S_ISFIFO(status.st_mode)) + result = file_status(file_type::fifo_file); + else if (S_ISSOCK(status.st_mode)) + result = file_status(file_type::socket_file); + else + result = file_status(file_type::type_unknown); + + return success; +} + +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl &result_path) { + SmallString<128> Model; + model.toVector(Model); + // Null terminate. + Model.c_str(); + + // Make model absolute by prepending a temp directory if it's not already. + bool absolute = path::is_absolute(Twine(Model)); + if (!absolute) { + SmallString<128> TDir; + if (error_code ec = TempDir(TDir)) return ec; + path::append(TDir, Twine(Model)); + Model.swap(TDir); + } + + // Replace '%' with random chars. From here on, DO NOT modify model. It may be + // needed if the randomly chosen path already exists. + SmallString<128> RandomPath; + RandomPath.reserve(Model.size() + 1); + ::srand(::time(NULL)); + +retry_random_path: + // This is opened here instead of above to make it easier to track when to + // close it. Collisions should be rare enough for the possible extra syscalls + // not to matter. + FILE *RandomSource = ::fopen("/dev/urandom", "r"); + RandomPath.set_size(0); + for (SmallVectorImpl::const_iterator i = Model.begin(), + e = Model.end(); i != e; ++i) { + if (*i == '%') { + char val = 0; + if (RandomSource) + val = fgetc(RandomSource); + else + val = ::rand(); + RandomPath.push_back("0123456789abcdef"[val & 15]); + } else + RandomPath.push_back(*i); + } + + if (RandomSource) + ::fclose(RandomSource); + + // Try to open + create the file. +rety_open_create: + int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); + if (RandomFD == -1) { + // If the file existed, try again, otherwise, error. + if (errno == errc::file_exists) + goto retry_random_path; + // The path prefix doesn't exist. + if (errno == errc::no_such_file_or_directory) { + StringRef p(RandomPath.begin(), RandomPath.size()); + SmallString<64> dir_to_create; + for (path::const_iterator i = path::begin(p), + e = --path::end(p); i != e; ++i) { + path::append(dir_to_create, *i); + bool Exists; + if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec; + if (!Exists) { + // Don't try to create network paths. + if (i->size() > 2 && (*i)[0] == '/' && + (*i)[1] == '/' && + (*i)[2] != '/') + return make_error_code(errc::no_such_file_or_directory); + if (::mkdir(dir_to_create.c_str(), 0700) == -1) + return error_code(errno, system_category()); + } + } + goto rety_open_create; + } + return error_code(errno, system_category()); + } + + // Make the path absolute. + char real_path_buff[PATH_MAX + 1]; + if (realpath(RandomPath.c_str(), real_path_buff) == NULL) { + int error = errno; + ::close(RandomFD); + ::unlink(RandomPath.c_str()); + return error_code(error, system_category()); + } + + result_path.clear(); + StringRef d(real_path_buff); + result_path.append(d.begin(), d.end()); + + result_fd = RandomFD; + return success; +} + +error_code directory_iterator_construct(directory_iterator &it, StringRef path){ + SmallString<128> path_null(path); + DIR *directory = ::opendir(path_null.c_str()); + if (directory == 0) + return error_code(errno, system_category()); + + it.IterationHandle = reinterpret_cast(directory); + // Add something for replace_filename to replace. + path::append(path_null, "."); + it.CurrentEntry = directory_entry(path_null.str()); + return directory_iterator_increment(it); +} + +error_code directory_iterator_destruct(directory_iterator& it) { + if (it.IterationHandle) + ::closedir(reinterpret_cast(it.IterationHandle)); + it.IterationHandle = 0; + it.CurrentEntry = directory_entry(); + return success; +} + +error_code directory_iterator_increment(directory_iterator& it) { + errno = 0; + dirent *cur_dir = ::readdir(reinterpret_cast(it.IterationHandle)); + if (cur_dir == 0 && errno != 0) { + return error_code(errno, system_category()); + } else if (cur_dir != 0) { + StringRef name(cur_dir->d_name, NAMLEN(cur_dir)); + if ((name.size() == 1 && name[0] == '.') || + (name.size() == 2 && name[0] == '.' && name[1] == '.')) + return directory_iterator_increment(it); + it.CurrentEntry.replace_filename(name); + } else + return directory_iterator_destruct(it); + + return success; +} + +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl &result) { + SmallString<128> PathStorage; + StringRef Path = path.toNullTerminatedStringRef(PathStorage); + result.set_size(0); + + // Open path. + std::FILE *file = std::fopen(Path.data(), "rb"); + if (file == 0) + return error_code(errno, system_category()); + + // Reserve storage. + result.reserve(len); + + // Read magic! + size_t size = std::fread(result.data(), 1, len, file); + if (std::ferror(file) != 0) { + std::fclose(file); + return error_code(errno, system_category()); + } else if (size != result.size()) { + if (std::feof(file) != 0) { + std::fclose(file); + result.set_size(size); + return make_error_code(errc::value_too_large); + } + } + std::fclose(file); + result.set_size(len); + return success; +} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm diff --git a/final/lib/Support/Unix/Process.inc b/final/lib/Support/Unix/Process.inc new file mode 100644 index 00000000000..5cdb11ccebc --- /dev/null +++ b/final/lib/Support/Unix/Process.inc @@ -0,0 +1,295 @@ +//===- Unix/Process.cpp - Unix Process Implementation --------- -*- 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 the generic Unix implementation of the Process class. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +// DragonFly BSD has deprecated for instead, +// Unix.h includes this for us already. +#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) +#include +#endif +#ifdef HAVE_MALLOC_MALLOC_H +#include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_TERMIOS_H +# include +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +using namespace llvm; +using namespace sys; + +unsigned +Process::GetPageSize() +{ +#if defined(__CYGWIN__) + // On Cygwin, getpagesize() returns 64k but the page size for the purposes of + // memory protection and mmap() is 4k. + // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492 + const int page_size = 0x1000; +#elif defined(HAVE_GETPAGESIZE) + const int page_size = ::getpagesize(); +#elif defined(HAVE_SYSCONF) + long page_size = ::sysconf(_SC_PAGE_SIZE); +#else +#warning Cannot get the page size on this machine +#endif + return static_cast(page_size); +} + +size_t Process::GetMallocUsage() { +#if defined(HAVE_MALLINFO) + struct mallinfo mi; + mi = ::mallinfo(); + return mi.uordblks; +#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) + malloc_statistics_t Stats; + malloc_zone_statistics(malloc_default_zone(), &Stats); + return Stats.size_in_use; // darwin +#elif defined(HAVE_SBRK) + // Note this is only an approximation and more closely resembles + // the value returned by mallinfo in the arena field. + static char *StartOfMemory = reinterpret_cast(::sbrk(0)); + char *EndOfMemory = (char*)sbrk(0); + if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1)) + return EndOfMemory - StartOfMemory; + else + return 0; +#else +#warning Cannot get malloc info on this platform + return 0; +#endif +} + +size_t +Process::GetTotalMemoryUsage() +{ +#if defined(HAVE_MALLINFO) + struct mallinfo mi = ::mallinfo(); + return mi.uordblks + mi.hblkhd; +#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) + malloc_statistics_t Stats; + malloc_zone_statistics(malloc_default_zone(), &Stats); + return Stats.size_allocated; // darwin +#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__) + struct rusage usage; + ::getrusage(RUSAGE_SELF, &usage); + return usage.ru_maxrss; +#else +#warning Cannot get total memory size on this platform + return 0; +#endif +} + +void +Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, + TimeValue& sys_time) +{ + elapsed = TimeValue::now(); +#if defined(HAVE_GETRUSAGE) + struct rusage usage; + ::getrusage(RUSAGE_SELF, &usage); + user_time = TimeValue( + static_cast( usage.ru_utime.tv_sec ), + static_cast( usage.ru_utime.tv_usec * + TimeValue::NANOSECONDS_PER_MICROSECOND ) ); + sys_time = TimeValue( + static_cast( usage.ru_stime.tv_sec ), + static_cast( usage.ru_stime.tv_usec * + TimeValue::NANOSECONDS_PER_MICROSECOND ) ); +#else +#warning Cannot get usage times on this platform + user_time.seconds(0); + user_time.microseconds(0); + sys_time.seconds(0); + sys_time.microseconds(0); +#endif +} + +int Process::GetCurrentUserId() { + return getuid(); +} + +int Process::GetCurrentGroupId() { + return getgid(); +} + +#ifdef HAVE_MACH_MACH_H +#include +#endif + +// Some LLVM programs such as bugpoint produce core files as a normal part of +// their operation. To prevent the disk from filling up, this function +// does what's necessary to prevent their generation. +void Process::PreventCoreFiles() { +#if HAVE_SETRLIMIT + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); +#endif + +#ifdef HAVE_MACH_MACH_H + // Disable crash reporting on Mac OS X 10.0-10.4 + + // get information about the original set of exception ports for the task + mach_msg_type_number_t Count = 0; + exception_mask_t OriginalMasks[EXC_TYPES_COUNT]; + exception_port_t OriginalPorts[EXC_TYPES_COUNT]; + exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT]; + kern_return_t err = + task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks, + &Count, OriginalPorts, OriginalBehaviors, + OriginalFlavors); + if (err == KERN_SUCCESS) { + // replace each with MACH_PORT_NULL. + for (unsigned i = 0; i != Count; ++i) + task_set_exception_ports(mach_task_self(), OriginalMasks[i], + MACH_PORT_NULL, OriginalBehaviors[i], + OriginalFlavors[i]); + } + + // Disable crash reporting on Mac OS X 10.5 + signal(SIGABRT, _exit); + signal(SIGILL, _exit); + signal(SIGFPE, _exit); + signal(SIGSEGV, _exit); + signal(SIGBUS, _exit); +#endif +} + +bool Process::StandardInIsUserInput() { + return FileDescriptorIsDisplayed(STDIN_FILENO); +} + +bool Process::StandardOutIsDisplayed() { + return FileDescriptorIsDisplayed(STDOUT_FILENO); +} + +bool Process::StandardErrIsDisplayed() { + return FileDescriptorIsDisplayed(STDERR_FILENO); +} + +bool Process::FileDescriptorIsDisplayed(int fd) { +#if HAVE_ISATTY + return isatty(fd); +#else + // If we don't have isatty, just return false. + return false; +#endif +} + +static unsigned getColumns(int FileID) { + // If COLUMNS is defined in the environment, wrap to that many columns. + if (const char *ColumnsStr = std::getenv("COLUMNS")) { + int Columns = std::atoi(ColumnsStr); + if (Columns > 0) + return Columns; + } + + unsigned Columns = 0; + +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H) + // Try to determine the width of the terminal. + struct winsize ws; + if (ioctl(FileID, TIOCGWINSZ, &ws) == 0) + Columns = ws.ws_col; +#endif + + return Columns; +} + +unsigned Process::StandardOutColumns() { + if (!StandardOutIsDisplayed()) + return 0; + + return getColumns(1); +} + +unsigned Process::StandardErrColumns() { + if (!StandardErrIsDisplayed()) + return 0; + + return getColumns(2); +} + +static bool terminalHasColors() { + if (const char *term = std::getenv("TERM")) { + // Most modern terminals support ANSI escape sequences for colors. + // We could check terminfo, or have a list of known terms that support + // colors, but that would be overkill. + // The user can always ask for no colors by setting TERM to dumb, or + // using a commandline flag. + return strcmp(term, "dumb") != 0; + } + return false; +} + +bool Process::StandardOutHasColors() { + if (!StandardOutIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::StandardErrHasColors() { + if (!StandardErrIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::ColorNeedsFlush() { + // No, we use ANSI escape sequences. + return false; +} + +#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" + +#define ALLCOLORS(FGBG,BOLD) {\ + COLOR(FGBG, "0", BOLD),\ + COLOR(FGBG, "1", BOLD),\ + COLOR(FGBG, "2", BOLD),\ + COLOR(FGBG, "3", BOLD),\ + COLOR(FGBG, "4", BOLD),\ + COLOR(FGBG, "5", BOLD),\ + COLOR(FGBG, "6", BOLD),\ + COLOR(FGBG, "7", BOLD)\ + } + +static const char colorcodes[2][2][8][10] = { + { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, + { ALLCOLORS("4",""), ALLCOLORS("4","1;") } +}; + +const char *Process::OutputColor(char code, bool bold, bool bg) { + return colorcodes[bg?1:0][bold?1:0][code&7]; +} + +const char *Process::OutputBold(bool bg) { + return "\033[1m"; +} + +const char *Process::ResetColor() { + return "\033[0m"; +} diff --git a/final/lib/Support/Unix/Program.inc b/final/lib/Support/Unix/Program.inc new file mode 100644 index 00000000000..1104bc7503e --- /dev/null +++ b/final/lib/Support/Unix/Program.inc @@ -0,0 +1,424 @@ +//===- llvm/Support/Unix/Program.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific portion of the Program class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include +#include "llvm/Support/FileSystem.h" +#include "Unix.h" +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SYS_RESOURCE_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_POSIX_SPAWN +#include +#if !defined(__APPLE__) + extern char **environ; +#else +#include // _NSGetEnviron +#endif +#endif + +namespace llvm { +using namespace sys; + +Program::Program() : Data_(0) {} + +Program::~Program() {} + +unsigned Program::GetPid() const { + uint64_t pid = reinterpret_cast(Data_); + return static_cast(pid); +} + +// This function just uses the PATH environment variable to find the program. +Path +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Path(); + Path temp; + if (!temp.set(progName)) // invalid name + return Path(); + // Use the given path verbatim if it contains any slashes; this matches + // the behavior of sh(1) and friends. + if (progName.find('/') != std::string::npos) + return temp; + + // At this point, the file name is valid and does not contain slashes. Search + // for it through the directories specified in the PATH environment variable. + + // Get the path. If its empty, we can't do anything to find it. + const char *PathStr = getenv("PATH"); + if (PathStr == 0) + return Path(); + + // Now we have a colon separated list of directories to search; try them. + size_t PathLen = strlen(PathStr); + while (PathLen) { + // Find the first colon... + const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); + + // Check to see if this first directory contains the executable... + Path FilePath; + if (FilePath.set(std::string(PathStr,Colon))) { + FilePath.appendComponent(progName); + if (FilePath.canExecute()) + return FilePath; // Found the executable! + } + + // Nope it wasn't in this directory, check the next path in the list! + PathLen -= Colon-PathStr; + PathStr = Colon; + + // Advance past duplicate colons + while (*PathStr == ':') { + PathStr++; + PathLen--; + } + } + return Path(); +} + +static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) { + if (Path == 0) // Noop + return false; + const char *File; + if (Path->isEmpty()) + // Redirect empty paths to /dev/null + File = "/dev/null"; + else + File = Path->c_str(); + + // Open the file + int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); + if (InFD == -1) { + MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for " + + (FD == 0 ? "input" : "output")); + return true; + } + + // Install it as the requested FD + if (dup2(InFD, FD) == -1) { + MakeErrMsg(ErrMsg, "Cannot dup2"); + close(InFD); + return true; + } + close(InFD); // Close the original FD + return false; +} + +#ifdef HAVE_POSIX_SPAWN +static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg, + posix_spawn_file_actions_t &FileActions) { + if (Path == 0) // Noop + return false; + const char *File; + if (Path->isEmpty()) + // Redirect empty paths to /dev/null + File = "/dev/null"; + else + File = Path->c_str(); + + if (int Err = posix_spawn_file_actions_addopen(&FileActions, FD, + File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666)) + return MakeErrMsg(ErrMsg, "Cannot dup2", Err); + return false; +} +#endif + +static void TimeOutHandler(int Sig) { +} + +static void SetMemoryLimits (unsigned size) +{ +#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT + struct rlimit r; + __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; + + // Heap size + getrlimit (RLIMIT_DATA, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_DATA, &r); +#ifdef RLIMIT_RSS + // Resident set size. + getrlimit (RLIMIT_RSS, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_RSS, &r); +#endif +#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. + // Virtual memory. + getrlimit (RLIMIT_AS, &r); + r.rlim_cur = limit; + setrlimit (RLIMIT_AS, &r); +#endif +#endif +} + +bool +Program::Execute(const Path &path, const char **args, const char **envp, + const Path **redirects, unsigned memoryLimit, + std::string *ErrMsg) { + // If this OS has posix_spawn and there is no memory limit being implied, use + // posix_spawn. It is more efficient than fork/exec. +#ifdef HAVE_POSIX_SPAWN + if (memoryLimit == 0) { + posix_spawn_file_actions_t FileActions; + posix_spawn_file_actions_init(&FileActions); + + if (redirects) { + // Redirect stdin/stdout. + if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) || + RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions)) + return false; + if (redirects[1] == 0 || redirects[2] == 0 || + *redirects[1] != *redirects[2]) { + // Just redirect stderr + if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false; + } else { + // If stdout and stderr should go to the same place, redirect stderr + // to the FD already open for stdout. + if (int Err = posix_spawn_file_actions_adddup2(&FileActions, 1, 2)) + return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err); + } + } + + if (!envp) +#if !defined(__APPLE__) + envp = const_cast(environ); +#else + // environ is missing in dylibs. + envp = const_cast(*_NSGetEnviron()); +#endif + + // Explicitly initialized to prevent what appears to be a valgrind false + // positive. + pid_t PID = 0; + int Err = posix_spawn(&PID, path.c_str(), &FileActions, /*attrp*/0, + const_cast(args), const_cast(envp)); + + posix_spawn_file_actions_destroy(&FileActions); + + if (Err) + return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err); + + Data_ = reinterpret_cast(PID); + return true; + } +#endif + + // Create a child process. + int child = fork(); + switch (child) { + // An error occured: Return to the caller. + case -1: + MakeErrMsg(ErrMsg, "Couldn't fork"); + return false; + + // Child process: Execute the program. + case 0: { + // Redirect file descriptors... + if (redirects) { + // Redirect stdin + if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; } + // Redirect stdout + if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; } + if (redirects[1] && redirects[2] && + *(redirects[1]) == *(redirects[2])) { + // If stdout and stderr should go to the same place, redirect stderr + // to the FD already open for stdout. + if (-1 == dup2(1,2)) { + MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout"); + return false; + } + } else { + // Just redirect stderr + if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; } + } + } + + // Set memory limits + if (memoryLimit!=0) { + SetMemoryLimits(memoryLimit); + } + + // Execute! + if (envp != 0) + execve(path.c_str(), + const_cast(args), + const_cast(envp)); + else + execv(path.c_str(), + const_cast(args)); + // If the execve() failed, we should exit. Follow Unix protocol and + // return 127 if the executable was not found, and 126 otherwise. + // Use _exit rather than exit so that atexit functions and static + // object destructors cloned from the parent process aren't + // redundantly run, and so that any data buffered in stdio buffers + // cloned from the parent aren't redundantly written out. + _exit(errno == ENOENT ? 127 : 126); + } + + // Parent process: Break out of the switch to do our processing. + default: + break; + } + + Data_ = reinterpret_cast(child); + + return true; +} + +int +Program::Wait(const sys::Path &path, + unsigned secondsToWait, + std::string* ErrMsg) +{ +#ifdef HAVE_SYS_WAIT_H + struct sigaction Act, Old; + + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return -1; + } + + // Install a timeout handler. The handler itself does nothing, but the simple + // fact of having a handler at all causes the wait below to return with EINTR, + // unlike if we used SIG_IGN. + if (secondsToWait) { + memset(&Act, 0, sizeof(Act)); + Act.sa_handler = TimeOutHandler; + sigemptyset(&Act.sa_mask); + sigaction(SIGALRM, &Act, &Old); + alarm(secondsToWait); + } + + // Parent process: Wait for the child process to terminate. + int status; + uint64_t pid = reinterpret_cast(Data_); + pid_t child = static_cast(pid); + while (waitpid(pid, &status, 0) != child) + if (secondsToWait && errno == EINTR) { + // Kill the child. + kill(child, SIGKILL); + + // Turn off the alarm and restore the signal handler + alarm(0); + sigaction(SIGALRM, &Old, 0); + + // Wait for child to die + if (wait(&status) != child) + MakeErrMsg(ErrMsg, "Child timed out but wouldn't die"); + else + MakeErrMsg(ErrMsg, "Child timed out", 0); + + return -1; // Timeout detected + } else if (errno != EINTR) { + MakeErrMsg(ErrMsg, "Error waiting for child process"); + return -1; + } + + // We exited normally without timeout, so turn off the timer. + if (secondsToWait) { + alarm(0); + sigaction(SIGALRM, &Old, 0); + } + + // Return the proper exit status. Detect error conditions + // so we can return -1 for them and set ErrMsg informatively. + int result = 0; + if (WIFEXITED(status)) { + result = WEXITSTATUS(status); +#ifdef HAVE_POSIX_SPAWN + // The posix_spawn child process returns 127 on any kind of error. + // Following the POSIX convention for command-line tools (which posix_spawn + // itself apparently does not), check to see if the failure was due to some + // reason other than the file not existing, and return 126 in this case. + bool Exists; + if (result == 127 && !llvm::sys::fs::exists(path.str(), Exists) && Exists) + result = 126; +#endif + if (result == 127) { + if (ErrMsg) + *ErrMsg = llvm::sys::StrError(ENOENT); + return -1; + } + if (result == 126) { + if (ErrMsg) + *ErrMsg = "Program could not be executed"; + return -1; + } + } else if (WIFSIGNALED(status)) { + if (ErrMsg) { + *ErrMsg = strsignal(WTERMSIG(status)); +#ifdef WCOREDUMP + if (WCOREDUMP(status)) + *ErrMsg += " (core dumped)"; +#endif + } + return -1; + } + return result; +#else + if (ErrMsg) + *ErrMsg = "Program::Wait is not implemented on this platform yet!"; + return -1; +#endif +} + +bool +Program::Kill(std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return true; + } + + uint64_t pid64 = reinterpret_cast(Data_); + pid_t pid = static_cast(pid64); + + if (kill(pid, SIGKILL) != 0) { + MakeErrMsg(ErrMsg, "The process couldn't be killed!"); + return true; + } + + return false; +} + +bool Program::ChangeStdinToBinary(){ + // Do nothing, as Unix doesn't differentiate between text and binary. + return false; +} + +bool Program::ChangeStdoutToBinary(){ + // Do nothing, as Unix doesn't differentiate between text and binary. + return false; +} + +bool Program::ChangeStderrToBinary(){ + // Do nothing, as Unix doesn't differentiate between text and binary. + return false; +} + +} diff --git a/final/lib/Support/Unix/README.txt b/final/lib/Support/Unix/README.txt new file mode 100644 index 00000000000..3d547c2990d --- /dev/null +++ b/final/lib/Support/Unix/README.txt @@ -0,0 +1,16 @@ +llvm/lib/Support/Unix README +=========================== + +This directory provides implementations of the lib/System classes that +are common to two or more variants of UNIX. For example, the directory +structure underneath this directory could look like this: + +Unix - only code that is truly generic to all UNIX platforms + Posix - code that is specific to Posix variants of UNIX + SUS - code that is specific to the Single Unix Specification + SysV - code that is specific to System V variants of UNIX + +As a rule, only those directories actually needing to be created should be +created. Also, further subdirectories could be created to reflect versions of +the various standards. For example, under SUS there could be v1, v2, and v3 +subdirectories to reflect the three major versions of SUS. diff --git a/final/lib/Support/Unix/RWMutex.inc b/final/lib/Support/Unix/RWMutex.inc new file mode 100644 index 00000000000..40e87ff1311 --- /dev/null +++ b/final/lib/Support/Unix/RWMutex.inc @@ -0,0 +1,43 @@ +//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =// +// +// 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 Unix specific (non-pthread) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { + +using namespace sys; + +RWMutexImpl::RWMutexImpl() { } + +RWMutexImpl::~RWMutexImpl() { } + +bool RWMutexImpl::reader_acquire() { + return true; +} + +bool RWMutexImpl::reader_release() { + return true; +} + +bool RWMutexImpl::writer_acquire() { + return true; +} + +bool RWMutexImpl::writer_release() { + return true; +} + +} diff --git a/final/lib/Support/Unix/Signals.inc b/final/lib/Support/Unix/Signals.inc new file mode 100644 index 00000000000..0a617591551 --- /dev/null +++ b/final/lib/Support/Unix/Signals.inc @@ -0,0 +1,303 @@ +//===- Signals.cpp - Generic Unix Signals Implementation -----*- 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 some helpful functions for dealing with the possibility of +// Unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#include "Unix.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Mutex.h" +#include +#include +#if HAVE_EXECINFO_H +# include // For backtrace(). +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_DLFCN_H && __GNUG__ +#include +#include +#endif +using namespace llvm; + +static RETSIGTYPE SignalHandler(int Sig); // defined below. + +static SmartMutex SignalsMutex; + +/// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + +static std::vector FilesToRemove; +static std::vector > CallBacksToRun; + +// IntSigs - Signals that may interrupt the program at any time. +static const int IntSigs[] = { + SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 +}; +static const int *const IntSigsEnd = + IntSigs + sizeof(IntSigs) / sizeof(IntSigs[0]); + +// KillSigs - Signals that are synchronous with the program that will cause it +// to die. +static const int KillSigs[] = { + SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV +#ifdef SIGSYS + , SIGSYS +#endif +#ifdef SIGXCPU + , SIGXCPU +#endif +#ifdef SIGXFSZ + , SIGXFSZ +#endif +#ifdef SIGEMT + , SIGEMT +#endif +}; +static const int *const KillSigsEnd = + KillSigs + sizeof(KillSigs) / sizeof(KillSigs[0]); + +static unsigned NumRegisteredSignals = 0; +static struct { + struct sigaction SA; + int SigNo; +} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])]; + + +static void RegisterHandler(int Signal) { + assert(NumRegisteredSignals < + sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) && + "Out of space for signal handlers!"); + + struct sigaction NewHandler; + + NewHandler.sa_handler = SignalHandler; + NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND; + sigemptyset(&NewHandler.sa_mask); + + // Install the new handler, save the old one in RegisteredSignalInfo. + sigaction(Signal, &NewHandler, + &RegisteredSignalInfo[NumRegisteredSignals].SA); + RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal; + ++NumRegisteredSignals; +} + +static void RegisterHandlers() { + // If the handlers are already registered, we're done. + if (NumRegisteredSignals != 0) return; + + std::for_each(IntSigs, IntSigsEnd, RegisterHandler); + std::for_each(KillSigs, KillSigsEnd, RegisterHandler); +} + +static void UnregisterHandlers() { + // Restore all of the signal handlers to how they were before we showed up. + for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i) + sigaction(RegisteredSignalInfo[i].SigNo, + &RegisteredSignalInfo[i].SA, 0); + NumRegisteredSignals = 0; +} + + +/// RemoveFilesToRemove - Process the FilesToRemove list. This function +/// should be called with the SignalsMutex lock held. +static void RemoveFilesToRemove() { + while (!FilesToRemove.empty()) { + FilesToRemove.back().eraseFromDisk(true); + FilesToRemove.pop_back(); + } +} + +// SignalHandler - The signal handler that runs. +static RETSIGTYPE SignalHandler(int Sig) { + // Restore the signal behavior to default, so that the program actually + // crashes when we return and the signal reissues. This also ensures that if + // we crash in our signal handler that the program will terminate immediately + // instead of recursing in the signal handler. + UnregisterHandlers(); + + // Unmask all potentially blocked kill signals. + sigset_t SigMask; + sigfillset(&SigMask); + sigprocmask(SIG_UNBLOCK, &SigMask, 0); + + SignalsMutex.acquire(); + RemoveFilesToRemove(); + + if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) { + if (InterruptFunction) { + void (*IF)() = InterruptFunction; + SignalsMutex.release(); + InterruptFunction = 0; + IF(); // run the interrupt function. + return; + } + + SignalsMutex.release(); + raise(Sig); // Execute the default handler. + return; + } + + SignalsMutex.release(); + + // Otherwise if it is a fault (like SEGV) run any handler. + for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i) + CallBacksToRun[i].first(CallBacksToRun[i].second); +} + +void llvm::sys::RunInterruptHandlers() { + SignalsMutex.acquire(); + RemoveFilesToRemove(); + SignalsMutex.release(); +} + +void llvm::sys::SetInterruptFunction(void (*IF)()) { + SignalsMutex.acquire(); + InterruptFunction = IF; + SignalsMutex.release(); + RegisterHandlers(); +} + +// RemoveFileOnSignal - The public API +bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, + std::string* ErrMsg) { + SignalsMutex.acquire(); + FilesToRemove.push_back(Filename); + + SignalsMutex.release(); + + RegisterHandlers(); + return false; +} + +// DontRemoveFileOnSignal - The public API +void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) { + SignalsMutex.acquire(); + std::vector::reverse_iterator I = + std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename); + if (I != FilesToRemove.rend()) + FilesToRemove.erase(I.base()-1); + SignalsMutex.release(); +} + +/// AddSignalHandler - Add a function to be called when a signal is delivered +/// to the process. The handler can have a cookie passed to it to identify +/// what instance of the handler it is. +void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { + CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie)); + RegisterHandlers(); +} + + +// PrintStackTrace - In the case of a program crash or fault, print out a stack +// trace so that the user has an indication of why and where we died. +// +// On glibc systems we have the 'backtrace' function, which works nicely, but +// doesn't demangle symbols. +static void PrintStackTrace(void *) { +#ifdef HAVE_BACKTRACE + static void* StackTrace[256]; + // Use backtrace() to output a backtrace on Linux systems with glibc. + int depth = backtrace(StackTrace, + static_cast(array_lengthof(StackTrace))); +#if HAVE_DLFCN_H && __GNUG__ + int width = 0; + for (int i = 0; i < depth; ++i) { + Dl_info dlinfo; + dladdr(StackTrace[i], &dlinfo); + const char* name = strrchr(dlinfo.dli_fname, '/'); + + int nwidth; + if (name == NULL) nwidth = strlen(dlinfo.dli_fname); + else nwidth = strlen(name) - 1; + + if (nwidth > width) width = nwidth; + } + + for (int i = 0; i < depth; ++i) { + Dl_info dlinfo; + dladdr(StackTrace[i], &dlinfo); + + fprintf(stderr, "%-2d", i); + + const char* name = strrchr(dlinfo.dli_fname, '/'); + if (name == NULL) fprintf(stderr, " %-*s", width, dlinfo.dli_fname); + else fprintf(stderr, " %-*s", width, name+1); + + fprintf(stderr, " %#0*lx", + (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]); + + if (dlinfo.dli_sname != NULL) { + int res; + fputc(' ', stderr); + char* d = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &res); + if (d == NULL) fputs(dlinfo.dli_sname, stderr); + else fputs(d, stderr); + free(d); + + fprintf(stderr, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr); + } + fputc('\n', stderr); + } +#else + backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO); +#endif +#endif +} + +/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or +/// SIGSEGV) is delivered to the process, print a stack trace and then exit. +void llvm::sys::PrintStackTraceOnErrorSignal() { + AddSignalHandler(PrintStackTrace, 0); +} + + +/***/ + +// On Darwin, raise sends a signal to the main thread instead of the current +// thread. This has the unfortunate effect that assert() and abort() will end up +// bypassing our crash recovery attempts. We work around this for anything in +// the same linkage unit by just defining our own versions of the assert handler +// and abort. + +#ifdef __APPLE__ + +int raise(int sig) { + return pthread_kill(pthread_self(), sig); +} + +void __assert_rtn(const char *func, + const char *file, + int line, + const char *expr) { + if (func) + fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n", + expr, func, file, line); + else + fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n", + expr, file, line); + abort(); +} + +#include +#include + +void abort() { + raise(SIGABRT); + usleep(1000); + __builtin_trap(); +} + +#endif diff --git a/final/lib/Support/Unix/ThreadLocal.inc b/final/lib/Support/Unix/ThreadLocal.inc new file mode 100644 index 00000000000..2b4c9017cd9 --- /dev/null +++ b/final/lib/Support/Unix/ThreadLocal.inc @@ -0,0 +1,26 @@ +//=== llvm/Support/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +namespace llvm { +using namespace sys; +ThreadLocalImpl::ThreadLocalImpl() { } +ThreadLocalImpl::~ThreadLocalImpl() { } +void ThreadLocalImpl::setInstance(const void* d) { data = const_cast(d);} +const void* ThreadLocalImpl::getInstance() { return data; } +void ThreadLocalImpl::removeInstance() { setInstance(0); } +} diff --git a/final/lib/Support/Unix/TimeValue.inc b/final/lib/Support/Unix/TimeValue.inc new file mode 100644 index 00000000000..5cf5a9d44ed --- /dev/null +++ b/final/lib/Support/Unix/TimeValue.inc @@ -0,0 +1,56 @@ +//===- Unix/TimeValue.cpp - Unix TimeValue Implementation -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Unix specific portion of the TimeValue class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +#include "Unix.h" + +namespace llvm { + using namespace sys; + +std::string TimeValue::str() const { + char buffer[32]; + + time_t ourTime = time_t(this->toEpochTime()); +#ifdef __hpux +// note that the following line needs -D_REENTRANT on HP-UX to be picked up + asctime_r(localtime(&ourTime), buffer); +#else + ::asctime_r(::localtime(&ourTime), buffer); +#endif + + std::string result(buffer); + return result.substr(0,24); +} + +TimeValue TimeValue::now() { + struct timeval the_time; + timerclear(&the_time); + if (0 != ::gettimeofday(&the_time,0)) { + // This is *really* unlikely to occur because the only gettimeofday + // errors concern the timezone parameter which we're passing in as 0. + // In the unlikely case it does happen, just return MinTime, no error + // message needed. + return MinTime; + } + + return TimeValue( + static_cast( the_time.tv_sec + PosixZeroTime.seconds_ ), + static_cast( the_time.tv_usec * + NANOSECONDS_PER_MICROSECOND ) ); +} + +} diff --git a/final/lib/Support/Unix/Unix.h b/final/lib/Support/Unix/Unix.h new file mode 100644 index 00000000000..b7be3111d43 --- /dev/null +++ b/final/lib/Support/Unix/Unix.h @@ -0,0 +1,87 @@ +//===- llvm/Support/Unix/Unix.h - Common Unix Include 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 defines things specific to Unix implementations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_UNIX_UNIX_H +#define LLVM_SYSTEM_UNIX_UNIX_H + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on all UNIX variants. +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" // Get autoconf configuration settings +#include "llvm/Support/Errno.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif + +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif + +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +/// This function builds an error message into \p ErrMsg using the \p prefix +/// string and the Unix error number given by \p errnum. If errnum is -1, the +/// default then the value of errno is used. +/// @brief Make an error message +/// +/// If the error number can be converted to a string, it will be +/// separated from prefix by ": ". +static inline bool MakeErrMsg( + std::string* ErrMsg, const std::string& prefix, int errnum = -1) { + if (!ErrMsg) + return true; + if (errnum == -1) + errnum = errno; + *ErrMsg = prefix + ": " + llvm::sys::StrError(errnum); + return true; +} + +#endif diff --git a/final/lib/Support/Unix/system_error.inc b/final/lib/Support/Unix/system_error.inc new file mode 100644 index 00000000000..681e919edb4 --- /dev/null +++ b/final/lib/Support/Unix/system_error.inc @@ -0,0 +1,34 @@ +//===- llvm/Support/Unix/system_error.inc - Unix error_code ------*- 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 the Unix specific implementation of the error_code +// and error_condition classes. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic UNIX code that +//=== is guaranteed to work on *all* UNIX variants. +//===----------------------------------------------------------------------===// + +using namespace llvm; + +std::string +_system_error_category::message(int ev) const { + return _do_message::message(ev); +} + +error_condition +_system_error_category::default_error_condition(int ev) const { +#ifdef ELAST + if (ev > ELAST) + return error_condition(ev, system_category()); +#endif // ELAST + return error_condition(ev, generic_category()); +} diff --git a/final/lib/Support/Valgrind.cpp b/final/lib/Support/Valgrind.cpp new file mode 100644 index 00000000000..703448524ed --- /dev/null +++ b/final/lib/Support/Valgrind.cpp @@ -0,0 +1,54 @@ +//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is +// defined. If we have valgrind.h but valgrind isn't running, its macros are +// no-ops. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Valgrind.h" +#include "llvm/Config/config.h" + +#if HAVE_VALGRIND_VALGRIND_H +#include + +static bool InitNotUnderValgrind() { + return !RUNNING_ON_VALGRIND; +} + +// This bool is negated from what we'd expect because code may run before it +// gets initialized. If that happens, it will appear to be 0 (false), and we +// want that to cause the rest of the code in this file to run the +// Valgrind-provided macros. +static const bool NotUnderValgrind = InitNotUnderValgrind(); + +bool llvm::sys::RunningOnValgrind() { + if (NotUnderValgrind) + return false; + return RUNNING_ON_VALGRIND; +} + +void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { + if (NotUnderValgrind) + return; + + VALGRIND_DISCARD_TRANSLATIONS(Addr, Len); +} + +#else // !HAVE_VALGRIND_VALGRIND_H + +bool llvm::sys::RunningOnValgrind() { + return false; +} + +void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) { +} + +#endif // !HAVE_VALGRIND_VALGRIND_H diff --git a/final/lib/Support/Windows/DynamicLibrary.inc b/final/lib/Support/Windows/DynamicLibrary.inc new file mode 100644 index 00000000000..2c14366c076 --- /dev/null +++ b/final/lib/Support/Windows/DynamicLibrary.inc @@ -0,0 +1,166 @@ +//===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- 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 the Win32 specific implementation of DynamicLibrary. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" + +#ifdef __MINGW32__ + #include +#else + #include +#endif + +#ifdef _MSC_VER + #include +#endif + +#ifdef __MINGW32__ + #if (HAVE_LIBIMAGEHLP != 1) + #error "libimagehlp.a should be present" + #endif +#else + #pragma comment(lib, "dbghelp.lib") +#endif + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code. +//===----------------------------------------------------------------------===// + +static std::vector OpenedHandles; + +#ifdef _WIN64 + typedef DWORD64 ModuleBaseType; +#else + typedef ULONG ModuleBaseType; +#endif + +extern "C" { +// Use old callback if: +// - Not using Visual Studio +// - Visual Studio 2005 or earlier but only if we are not using the Windows SDK +// or Windows SDK version is older than 6.0 +// Use new callback if: +// - Newer Visual Studio (comes with newer SDK). +// - Visual Studio 2005 with Windows SDK 6.0+ +#if defined(_MSC_VER) + #if _MSC_VER < 1500 && (!defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 6000) + #define OLD_ELM_CALLBACK_DECL 1 + #endif +#elif defined(__MINGW64__) + // Use new callback. +#elif defined(__MINGW32__) + #define OLD_ELM_CALLBACK_DECL 1 +#endif + +#ifdef OLD_ELM_CALLBACK_DECL + static BOOL CALLBACK ELM_Callback(PSTR ModuleName, + ModuleBaseType ModuleBase, + ULONG ModuleSize, + PVOID UserContext) +#else + static BOOL CALLBACK ELM_Callback(PCSTR ModuleName, + ModuleBaseType ModuleBase, + ULONG ModuleSize, + PVOID UserContext) +#endif + { + // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded + // into the process. + if (stricmp(ModuleName, "msvci70") != 0 && + stricmp(ModuleName, "msvcirt") != 0 && + stricmp(ModuleName, "msvcp50") != 0 && + stricmp(ModuleName, "msvcp60") != 0 && + stricmp(ModuleName, "msvcp70") != 0 && + stricmp(ModuleName, "msvcr70") != 0 && +#ifndef __MINGW32__ + // Mingw32 uses msvcrt.dll by default. Don't ignore it. + // Otherwise, user should be aware, what he's doing :) + stricmp(ModuleName, "msvcrt") != 0 && +#endif + stricmp(ModuleName, "msvcrt20") != 0 && + stricmp(ModuleName, "msvcrt40") != 0) { + OpenedHandles.push_back((HMODULE)ModuleBase); + } + return TRUE; + } +} + +bool DynamicLibrary::LoadLibraryPermanently(const char *filename, + std::string *ErrMsg) { + if (filename) { + HMODULE a_handle = LoadLibrary(filename); + + if (a_handle == 0) + return MakeErrMsg(ErrMsg, std::string(filename) + ": Can't open : "); + + OpenedHandles.push_back(a_handle); + } else { + // When no file is specified, enumerate all DLLs and EXEs in the + // process. + EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0); + } + + // Because we don't remember the handle, we will never free it; hence, + // it is loaded permanently. + return false; +} + +// Stack probing routines are in the support library (e.g. libgcc), but we don't +// have dynamic linking on windows. Provide a hook. +#define EXPLICIT_SYMBOL(SYM) \ + extern "C" { extern void *SYM; } +#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) + +#include "explicit_symbols.inc" + +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 + +void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { + // First check symbols added via AddSymbol(). + if (ExplicitSymbols) { + std::map::iterator I = + ExplicitSymbols->find(symbolName); + std::map::iterator E = ExplicitSymbols->end(); + if (I != E) + return I->second; + } + + // Now search the libraries. + for (std::vector::iterator I = OpenedHandles.begin(), + E = OpenedHandles.end(); I != E; ++I) { + FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName); + if (ptr) { + return (void *) ptr; + } + } + + #define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) return (void*)&SYM; + #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ + if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO; + + { + #include "explicit_symbols.inc" + } + + #undef EXPLICIT_SYMBOL + #undef EXPLICIT_SYMBOL2 + + return 0; +} + +} diff --git a/final/lib/Support/Windows/Host.inc b/final/lib/Support/Windows/Host.inc new file mode 100644 index 00000000000..733830e82f0 --- /dev/null +++ b/final/lib/Support/Windows/Host.inc @@ -0,0 +1,23 @@ +//===- llvm/Support/Win32/Host.inc -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 Host support. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include + +using namespace llvm; + +std::string sys::getHostTriple() { + // FIXME: Adapt to running version. + return LLVM_HOSTTRIPLE; +} diff --git a/final/lib/Support/Windows/Memory.inc b/final/lib/Support/Windows/Memory.inc new file mode 100644 index 00000000000..9f69e7367e6 --- /dev/null +++ b/final/lib/Support/Windows/Memory.inc @@ -0,0 +1,73 @@ +//===- Win32/Memory.cpp - Win32 Memory Implementation -----------*- 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 the Win32 specific implementation of various Memory +// management utilities +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Process.h" + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +MemoryBlock Memory::AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg) { + if (NumBytes == 0) return MemoryBlock(); + + static const size_t pageSize = Process::GetPageSize(); + size_t NumPages = (NumBytes+pageSize-1)/pageSize; + + //FIXME: support NearBlock if ever needed on Win64. + + void *pa = VirtualAlloc(NULL, NumPages*pageSize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE); + if (pa == NULL) { + MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: "); + return MemoryBlock(); + } + + MemoryBlock result; + result.Address = pa; + result.Size = NumPages*pageSize; + return result; +} + +bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) { + if (M.Address == 0 || M.Size == 0) return false; + if (!VirtualFree(M.Address, 0, MEM_RELEASE)) + return MakeErrMsg(ErrMsg, "Can't release RWX Memory: "); + return false; +} + +bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) { + return true; +} + +bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) { + return false; +} + +bool Memory::setRangeWritable(const void *Addr, size_t Size) { + return true; +} + +bool Memory::setRangeExecutable(const void *Addr, size_t Size) { + return false; +} + +} diff --git a/final/lib/Support/Windows/Mutex.inc b/final/lib/Support/Windows/Mutex.inc new file mode 100644 index 00000000000..583dc6359a1 --- /dev/null +++ b/final/lib/Support/Windows/Mutex.inc @@ -0,0 +1,58 @@ +//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 specific (non-pthread) Mutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include "llvm/Support/Mutex.h" + +namespace llvm { +using namespace sys; + +MutexImpl::MutexImpl(bool /*recursive*/) +{ + data_ = new CRITICAL_SECTION; + InitializeCriticalSection((LPCRITICAL_SECTION)data_); +} + +MutexImpl::~MutexImpl() +{ + DeleteCriticalSection((LPCRITICAL_SECTION)data_); + delete (LPCRITICAL_SECTION)data_; + data_ = 0; +} + +bool +MutexImpl::acquire() +{ + EnterCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::release() +{ + LeaveCriticalSection((LPCRITICAL_SECTION)data_); + return true; +} + +bool +MutexImpl::tryacquire() +{ + return TryEnterCriticalSection((LPCRITICAL_SECTION)data_); +} + +} diff --git a/final/lib/Support/Windows/Path.inc b/final/lib/Support/Windows/Path.inc new file mode 100644 index 00000000000..d6b582318d7 --- /dev/null +++ b/final/lib/Support/Windows/Path.inc @@ -0,0 +1,931 @@ +//===- llvm/Support/Win32/Path.cpp - Win32 Path Implementation ---*- 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 the Win32 specific implementation of the Path class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include + +// We need to undo a macro defined in Windows.h, otherwise we won't compile: +#undef CopyFile +#undef GetCurrentDirectory + +// Windows happily accepts either forward or backward slashes, though any path +// returned by a Win32 API will have backward slashes. As LLVM code basically +// assumes forward slashes are used, backward slashs are converted where they +// can be introduced into a path. +// +// Another invariant is that a path ends with a slash if and only if the path +// is a root directory. Any other use of a trailing slash is stripped. Unlike +// in Unix, Windows has a rather complicated notion of a root path and this +// invariant helps simply the code. + +static void FlipBackSlashes(std::string& s) { + for (size_t i = 0; i < s.size(); i++) + if (s[i] == '\\') + s[i] = '/'; +} + +namespace llvm { +namespace sys { + +const char PathSeparator = ';'; + +StringRef Path::GetEXESuffix() { + return "exe"; +} + +Path::Path(llvm::StringRef p) + : path(p) { + FlipBackSlashes(path); +} + +Path::Path(const char *StrStart, unsigned StrLen) + : path(StrStart, StrLen) { + FlipBackSlashes(path); +} + +Path& +Path::operator=(StringRef that) { + path.assign(that.data(), that.size()); + FlipBackSlashes(path); + return *this; +} + +// push_back 0 on create, and pop_back on delete. +struct ScopedNullTerminator { + std::string &str; + ScopedNullTerminator(std::string &s) : str(s) { str.push_back(0); } + ~ScopedNullTerminator() { + // str.pop_back(); But wait, C++03 doesn't have this... + assert(!str.empty() && str[str.size() - 1] == 0 + && "Null char not present!"); + str.resize(str.size() - 1); + } +}; + +bool +Path::isValid() const { + if (path.empty()) + return false; + + // If there is a colon, it must be the second character, preceded by a letter + // and followed by something. + size_t len = path.size(); + // This code assumes that path is null terminated, so make sure it is. + ScopedNullTerminator snt(path); + size_t pos = path.rfind(':',len); + size_t rootslash = 0; + if (pos != std::string::npos) { + if (pos != 1 || !isalpha(path[0]) || len < 3) + return false; + rootslash = 2; + } + + // Look for a UNC path, and if found adjust our notion of the root slash. + if (len > 3 && path[0] == '/' && path[1] == '/') { + rootslash = path.find('/', 2); + if (rootslash == std::string::npos) + rootslash = 0; + } + + // Check for illegal characters. + if (path.find_first_of("\\<>\"|\001\002\003\004\005\006\007\010\011\012" + "\013\014\015\016\017\020\021\022\023\024\025\026" + "\027\030\031\032\033\034\035\036\037") + != std::string::npos) + return false; + + // Remove trailing slash, unless it's a root slash. + if (len > rootslash+1 && path[len-1] == '/') + path.erase(--len); + + // Check each component for legality. + for (pos = 0; pos < len; ++pos) { + // A component may not end in a space. + if (path[pos] == ' ') { + if (path[pos+1] == '/' || path[pos+1] == '\0') + return false; + } + + // A component may not end in a period. + if (path[pos] == '.') { + if (path[pos+1] == '/' || path[pos+1] == '\0') { + // Unless it is the pseudo-directory "."... + if (pos == 0 || path[pos-1] == '/' || path[pos-1] == ':') + return true; + // or "..". + if (pos > 0 && path[pos-1] == '.') { + if (pos == 1 || path[pos-2] == '/' || path[pos-2] == ':') + return true; + } + return false; + } + } + } + + return true; +} + +void Path::makeAbsolute() { + TCHAR FullPath[MAX_PATH + 1] = {0}; + LPTSTR FilePart = NULL; + + DWORD RetLength = ::GetFullPathNameA(path.c_str(), + sizeof(FullPath)/sizeof(FullPath[0]), + FullPath, &FilePart); + + if (0 == RetLength) { + // FIXME: Report the error GetLastError() + assert(0 && "Unable to make absolute path!"); + } else if (RetLength > MAX_PATH) { + // FIXME: Report too small buffer (needed RetLength bytes). + assert(0 && "Unable to make absolute path!"); + } else { + path = FullPath; + } +} + +bool +Path::isAbsolute(const char *NameStart, unsigned NameLen) { + assert(NameStart); + // FIXME: This does not handle correctly an absolute path starting from + // a drive letter or in UNC format. + switch (NameLen) { + case 0: + return false; + case 1: + case 2: + return NameStart[0] == '/'; + default: + return + (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) || + (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\')); + } +} + +bool +Path::isAbsolute() const { + // FIXME: This does not handle correctly an absolute path starting from + // a drive letter or in UNC format. + switch (path.length()) { + case 0: + return false; + case 1: + case 2: + return path[0] == '/'; + default: + return path[0] == '/' || (path[1] == ':' && path[2] == '/'); + } +} + +static Path *TempDirectory; + +Path +Path::GetTemporaryDirectory(std::string* ErrMsg) { + if (TempDirectory) + return *TempDirectory; + + char pathname[MAX_PATH]; + if (!GetTempPath(MAX_PATH, pathname)) { + if (ErrMsg) + *ErrMsg = "Can't determine temporary directory"; + return Path(); + } + + Path result; + result.set(pathname); + + // Append a subdirectory passed on our process id so multiple LLVMs don't + // step on each other's toes. +#ifdef __MINGW32__ + // Mingw's Win32 header files are broken. + sprintf(pathname, "LLVM_%u", unsigned(GetCurrentProcessId())); +#else + sprintf(pathname, "LLVM_%u", GetCurrentProcessId()); +#endif + result.appendComponent(pathname); + + // If there's a directory left over from a previous LLVM execution that + // happened to have the same process id, get rid of it. + result.eraseFromDisk(true); + + // And finally (re-)create the empty directory. + result.createDirectoryOnDisk(false); + TempDirectory = new Path(result); + return *TempDirectory; +} + +// FIXME: the following set of functions don't map to Windows very well. +Path +Path::GetRootDirectory() { + // This is the only notion that that Windows has of a root directory. Nothing + // is here except for drives. + return Path("file:///"); +} + +void +Path::GetSystemLibraryPaths(std::vector& Paths) { + char buff[MAX_PATH]; + // Generic form of C:\Windows\System32 + HRESULT res = SHGetFolderPathA(NULL, + CSIDL_FLAG_CREATE | CSIDL_SYSTEM, + NULL, + SHGFP_TYPE_CURRENT, + buff); + if (res != S_OK) { + assert(0 && "Failed to get system directory"); + return; + } + Paths.push_back(sys::Path(buff)); + + // Reset buff. + buff[0] = 0; + // Generic form of C:\Windows + res = SHGetFolderPathA(NULL, + CSIDL_FLAG_CREATE | CSIDL_WINDOWS, + NULL, + SHGFP_TYPE_CURRENT, + buff); + if (res != S_OK) { + assert(0 && "Failed to get windows directory"); + return; + } + Paths.push_back(sys::Path(buff)); +} + +void +Path::GetBitcodeLibraryPaths(std::vector& Paths) { + char * env_var = getenv("LLVM_LIB_SEARCH_PATH"); + if (env_var != 0) { + getPathList(env_var,Paths); + } +#ifdef LLVM_LIBDIR + { + Path tmpPath; + if (tmpPath.set(LLVM_LIBDIR)) + if (tmpPath.canRead()) + Paths.push_back(tmpPath); + } +#endif + GetSystemLibraryPaths(Paths); +} + +Path +Path::GetLLVMDefaultConfigDir() { + Path ret = GetUserHomeDirectory(); + if (!ret.appendComponent(".llvm")) + assert(0 && "Failed to append .llvm"); + return ret; +} + +Path +Path::GetUserHomeDirectory() { + char buff[MAX_PATH]; + HRESULT res = SHGetFolderPathA(NULL, + CSIDL_FLAG_CREATE | CSIDL_APPDATA, + NULL, + SHGFP_TYPE_CURRENT, + buff); + if (res != S_OK) + assert(0 && "Failed to get user home directory"); + return Path(buff); +} + +Path +Path::GetCurrentDirectory() { + char pathname[MAX_PATH]; + ::GetCurrentDirectoryA(MAX_PATH,pathname); + return Path(pathname); +} + +/// GetMainExecutable - Return the path to the main executable, given the +/// value of argv[0] from program startup. +Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { + char pathname[MAX_PATH]; + DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH); + return ret != MAX_PATH ? Path(pathname) : Path(); +} + + +// FIXME: the above set of functions don't map to Windows very well. + + +StringRef Path::getDirname() const { + return getDirnameCharSep(path, "/"); +} + +StringRef +Path::getBasename() const { + // Find the last slash + size_t slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + size_t dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return StringRef(path).substr(slash); + else + return StringRef(path).substr(slash, dot - slash); +} + +StringRef +Path::getSuffix() const { + // Find the last slash + size_t slash = path.rfind('/'); + if (slash == std::string::npos) + slash = 0; + else + slash++; + + size_t dot = path.rfind('.'); + if (dot == std::string::npos || dot < slash) + return StringRef(""); + else + return StringRef(path).substr(dot + 1); +} + +bool +Path::exists() const { + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::isDirectory() const { + DWORD attr = GetFileAttributes(path.c_str()); + return (attr != INVALID_FILE_ATTRIBUTES) && + (attr & FILE_ATTRIBUTE_DIRECTORY); +} + +bool +Path::isSymLink() const { + DWORD attributes = GetFileAttributes(path.c_str()); + + if (attributes == INVALID_FILE_ATTRIBUTES) + // There's no sane way to report this :(. + assert(0 && "GetFileAttributes returned INVALID_FILE_ATTRIBUTES"); + + // This isn't exactly what defines a NTFS symlink, but it is only true for + // paths that act like a symlink. + return attributes & FILE_ATTRIBUTE_REPARSE_POINT; +} + +bool +Path::canRead() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::canWrite() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_READONLY); +} + +bool +Path::canExecute() const { + // FIXME: take security attributes into account. + DWORD attr = GetFileAttributes(path.c_str()); + return attr != INVALID_FILE_ATTRIBUTES; +} + +bool +Path::isRegularFile() const { + bool res; + if (fs::is_regular_file(path, res)) + return false; + return res; +} + +StringRef +Path::getLast() const { + // Find the last slash + size_t pos = path.rfind('/'); + + // Handle the corner cases + if (pos == std::string::npos) + return path; + + // If the last character is a slash, we have a root directory + if (pos == path.length()-1) + return path; + + // Return everything after the last slash + return StringRef(path).substr(pos+1); +} + +const FileStatus * +PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { + if (!fsIsValid || update) { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) { + MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) + + ": Can't get status: "); + return 0; + } + + status.fileSize = fi.nFileSizeHigh; + status.fileSize <<= sizeof(fi.nFileSizeHigh)*8; + status.fileSize += fi.nFileSizeLow; + + status.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777; + status.user = 9999; // Not applicable to Windows, so... + status.group = 9999; // Not applicable to Windows, so... + + // FIXME: this is only unique if the file is accessed by the same file path. + // How do we do this for C:\dir\file and ..\dir\file ? Unix has inode + // numbers, but the concept doesn't exist in Windows. + status.uniqueID = 0; + for (unsigned i = 0; i < path.length(); ++i) + status.uniqueID += path[i]; + + ULARGE_INTEGER ui; + ui.LowPart = fi.ftLastWriteTime.dwLowDateTime; + ui.HighPart = fi.ftLastWriteTime.dwHighDateTime; + status.modTime.fromWin32Time(ui.QuadPart); + + status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + fsIsValid = true; + } + return &status; +} + +bool Path::makeReadableOnDisk(std::string* ErrMsg) { + // All files are readable on Windows (ignoring security attributes). + return false; +} + +bool Path::makeWriteableOnDisk(std::string* ErrMsg) { + DWORD attr = GetFileAttributes(path.c_str()); + + // If it doesn't exist, we're done. + if (attr == INVALID_FILE_ATTRIBUTES) + return false; + + if (attr & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) { + MakeErrMsg(ErrMsg, std::string(path) + ": Can't make file writable: "); + return true; + } + } + return false; +} + +bool Path::makeExecutableOnDisk(std::string* ErrMsg) { + // All files are executable on Windows (ignoring security attributes). + return false; +} + +bool +Path::getDirectoryContents(std::set& result, std::string* ErrMsg) const { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) { + MakeErrMsg(ErrMsg, path + ": can't get status of file"); + return true; + } + + if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + if (ErrMsg) + *ErrMsg = path + ": not a directory"; + return true; + } + + result.clear(); + WIN32_FIND_DATA fd; + std::string searchpath = path; + if (path.size() == 0 || searchpath[path.size()-1] == '/') + searchpath += "*"; + else + searchpath += "/*"; + + HANDLE h = FindFirstFile(searchpath.c_str(), &fd); + if (h == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + return true; // not really an error, now is it? + MakeErrMsg(ErrMsg, path + ": Can't read directory: "); + return true; + } + + do { + if (fd.cFileName[0] == '.') + continue; + Path aPath(path); + aPath.appendComponent(&fd.cFileName[0]); + result.insert(aPath); + } while (FindNextFile(h, &fd)); + + DWORD err = GetLastError(); + FindClose(h); + if (err != ERROR_NO_MORE_FILES) { + SetLastError(err); + MakeErrMsg(ErrMsg, path + ": Can't read directory: "); + return true; + } + return false; +} + +bool +Path::set(StringRef a_path) { + if (a_path.empty()) + return false; + std::string save(path); + path = a_path; + FlipBackSlashes(path); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::appendComponent(StringRef name) { + if (name.empty()) + return false; + std::string save(path); + if (!path.empty()) { + size_t last = path.size() - 1; + if (path[last] != '/') + path += '/'; + } + path += name; + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseComponent() { + size_t slashpos = path.rfind('/',path.size()); + if (slashpos == path.size() - 1 || slashpos == std::string::npos) + return false; + std::string save(path); + path.erase(slashpos); + if (!isValid()) { + path = save; + return false; + } + return true; +} + +bool +Path::eraseSuffix() { + size_t dotpos = path.rfind('.',path.size()); + size_t slashpos = path.rfind('/',path.size()); + if (dotpos != std::string::npos) { + if (slashpos == std::string::npos || dotpos > slashpos+1) { + std::string save(path); + path.erase(dotpos, path.size()-dotpos); + if (!isValid()) { + path = save; + return false; + } + return true; + } + } + return false; +} + +inline bool PathMsg(std::string* ErrMsg, const char* pathname, const char*msg) { + if (ErrMsg) + *ErrMsg = std::string(pathname) + ": " + std::string(msg); + return true; +} + +bool +Path::createDirectoryOnDisk(bool create_parents, std::string* ErrMsg) { + // Get a writeable copy of the path name + size_t len = path.length(); + char *pathname = reinterpret_cast(_alloca(len+2)); + path.copy(pathname, len); + pathname[len] = 0; + + // Make sure it ends with a slash. + if (len == 0 || pathname[len - 1] != '/') { + pathname[len] = '/'; + pathname[++len] = 0; + } + + // Determine starting point for initial / search. + char *next = pathname; + if (pathname[0] == '/' && pathname[1] == '/') { + // Skip host name. + next = strchr(pathname+2, '/'); + if (next == NULL) + return PathMsg(ErrMsg, pathname, "badly formed remote directory"); + + // Skip share name. + next = strchr(next+1, '/'); + if (next == NULL) + return PathMsg(ErrMsg, pathname,"badly formed remote directory"); + + next++; + if (*next == 0) + return PathMsg(ErrMsg, pathname, "badly formed remote directory"); + + } else { + if (pathname[1] == ':') + next += 2; // skip drive letter + if (*next == '/') + next++; // skip root directory + } + + // If we're supposed to create intermediate directories + if (create_parents) { + // Loop through the directory components until we're done + while (*next) { + next = strchr(next, '/'); + *next = 0; + if (!CreateDirectory(pathname, NULL) && + GetLastError() != ERROR_ALREADY_EXISTS) + return MakeErrMsg(ErrMsg, + std::string(pathname) + ": Can't create directory: "); + *next++ = '/'; + } + } else { + // Drop trailing slash. + pathname[len-1] = 0; + if (!CreateDirectory(pathname, NULL) && + GetLastError() != ERROR_ALREADY_EXISTS) { + return MakeErrMsg(ErrMsg, std::string(pathname) + + ": Can't create directory: "); + } + } + return false; +} + +bool +Path::createFileOnDisk(std::string* ErrMsg) { + // Create the file + HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return MakeErrMsg(ErrMsg, path + ": Can't create file: "); + + CloseHandle(h); + return false; +} + +bool +Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { + WIN32_FILE_ATTRIBUTE_DATA fi; + if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) + return true; + + if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + // If it doesn't exist, we're done. + bool Exists; + if (fs::exists(path, Exists) || !Exists) + return false; + + char *pathname = reinterpret_cast(_alloca(path.length()+3)); + int lastchar = path.length() - 1 ; + path.copy(pathname, lastchar+1); + + // Make path end with '/*'. + if (pathname[lastchar] != '/') + pathname[++lastchar] = '/'; + pathname[lastchar+1] = '*'; + pathname[lastchar+2] = 0; + + if (remove_contents) { + WIN32_FIND_DATA fd; + HANDLE h = FindFirstFile(pathname, &fd); + + // It's a bad idea to alter the contents of a directory while enumerating + // its contents. So build a list of its contents first, then destroy them. + + if (h != INVALID_HANDLE_VALUE) { + std::vector list; + + do { + if (strcmp(fd.cFileName, ".") == 0) + continue; + if (strcmp(fd.cFileName, "..") == 0) + continue; + + Path aPath(path); + aPath.appendComponent(&fd.cFileName[0]); + list.push_back(aPath); + } while (FindNextFile(h, &fd)); + + DWORD err = GetLastError(); + FindClose(h); + if (err != ERROR_NO_MORE_FILES) { + SetLastError(err); + return MakeErrMsg(ErrStr, path + ": Can't read directory: "); + } + + for (std::vector::iterator I = list.begin(); I != list.end(); + ++I) { + Path &aPath = *I; + aPath.eraseFromDisk(true); + } + } else { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + return MakeErrMsg(ErrStr, path + ": Can't read directory: "); + } + } + + pathname[lastchar] = 0; + if (!RemoveDirectory(pathname)) + return MakeErrMsg(ErrStr, + std::string(pathname) + ": Can't destroy directory: "); + return false; + } else { + // Read-only files cannot be deleted on Windows. Must remove the read-only + // attribute first. + if (fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), + fi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrStr, path + ": Can't destroy file: "); + } + + if (!DeleteFile(path.c_str())) + return MakeErrMsg(ErrStr, path + ": Can't destroy file: "); + return false; + } +} + +bool Path::getMagicNumber(std::string& Magic, unsigned len) const { + assert(len < 1024 && "Request for magic string too long"); + char* buf = reinterpret_cast(alloca(len)); + + HANDLE h = CreateFile(path.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (h == INVALID_HANDLE_VALUE) + return false; + + DWORD nRead = 0; + BOOL ret = ReadFile(h, buf, len, &nRead, NULL); + CloseHandle(h); + + if (!ret || nRead != len) + return false; + + Magic = std::string(buf, len); + return true; +} + +bool +Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { + if (!MoveFileEx(path.c_str(), newName.c_str(), MOVEFILE_REPLACE_EXISTING)) + return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path + + "': "); + return false; +} + +bool +Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrMsg) const { + // FIXME: should work on directories also. + if (!si.isFile) { + return true; + } + + HANDLE h = CreateFile(path.c_str(), + FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (h == INVALID_HANDLE_VALUE) + return true; + + BY_HANDLE_FILE_INFORMATION bhfi; + if (!GetFileInformationByHandle(h, &bhfi)) { + DWORD err = GetLastError(); + CloseHandle(h); + SetLastError(err); + return MakeErrMsg(ErrMsg, path + ": GetFileInformationByHandle: "); + } + + ULARGE_INTEGER ui; + ui.QuadPart = si.modTime.toWin32Time(); + FILETIME ft; + ft.dwLowDateTime = ui.LowPart; + ft.dwHighDateTime = ui.HighPart; + BOOL ret = SetFileTime(h, NULL, &ft, &ft); + DWORD err = GetLastError(); + CloseHandle(h); + if (!ret) { + SetLastError(err); + return MakeErrMsg(ErrMsg, path + ": SetFileTime: "); + } + + // Best we can do with Unix permission bits is to interpret the owner + // writable bit. + if (si.mode & 0200) { + if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributes(path.c_str(), + bhfi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: "); + } + } else { + if (!(bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { + if (!SetFileAttributes(path.c_str(), + bhfi.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) + return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: "); + } + } + + return false; +} + +bool +CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg) { + // Can't use CopyFile macro defined in Windows.h because it would mess up the + // above line. We use the expansion it would have in a non-UNICODE build. + if (!::CopyFileA(Src.c_str(), Dest.c_str(), false)) + return MakeErrMsg(ErrMsg, "Can't copy '" + Src.str() + + "' to '" + Dest.str() + "': "); + return false; +} + +bool +Path::makeUnique(bool reuse_current, std::string* ErrMsg) { + bool Exists; + if (reuse_current && (fs::exists(path, Exists) || !Exists)) + return false; // File doesn't exist already, just use it! + + // Reserve space for -XXXXXX at the end. + char *FNBuffer = (char*) alloca(path.size()+8); + unsigned offset = path.size(); + path.copy(FNBuffer, offset); + + // Find a numeric suffix that isn't used by an existing file. Assume there + // won't be more than 1 million files with the same prefix. Probably a safe + // bet. + static int FCounter = -1; + if (FCounter < 0) { + // Give arbitrary initial seed. + // FIXME: We should use sys::fs::unique_file() in future. + LARGE_INTEGER cnt64; + DWORD x = GetCurrentProcessId(); + x = (x << 16) | (x >> 16); + if (QueryPerformanceCounter(&cnt64)) // RDTSC + x ^= cnt64.HighPart ^ cnt64.LowPart; + FCounter = x % 1000000; + } + do { + sprintf(FNBuffer+offset, "-%06u", FCounter); + if (++FCounter > 999999) + FCounter = 0; + path = FNBuffer; + } while (!fs::exists(path, Exists) && Exists); + return false; +} + +bool +Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { + // Make this into a unique file name + makeUnique(reuse_current, ErrMsg); + + // Now go and create it + HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + return MakeErrMsg(ErrMsg, path + ": can't create file"); + + CloseHandle(h); + return false; +} + +/// MapInFilePages - Not yet implemented on win32. +const char *Path::MapInFilePages(int FD, uint64_t FileSize) { + return 0; +} + +/// MapInFilePages - Not yet implemented on win32. +void Path::UnMapFilePages(const char *Base, uint64_t FileSize) { + assert(0 && "NOT IMPLEMENTED"); +} + +} +} diff --git a/final/lib/Support/Windows/PathV2.inc b/final/lib/Support/Windows/PathV2.inc new file mode 100644 index 00000000000..8f306d19fe1 --- /dev/null +++ b/final/lib/Support/Windows/PathV2.inc @@ -0,0 +1,750 @@ +//===- llvm/Support/Windows/PathV2.inc - Windows Path Impl ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Windows specific implementation of the PathV2 API. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Windows code that +//=== is guaranteed to work on *all* Windows variants. +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include +#include +#include +#include + +// MinGW doesn't define this. +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +using namespace llvm; + +namespace { + typedef BOOLEAN (WINAPI *PtrCreateSymbolicLinkW)( + /*__in*/ LPCWSTR lpSymlinkFileName, + /*__in*/ LPCWSTR lpTargetFileName, + /*__in*/ DWORD dwFlags); + + PtrCreateSymbolicLinkW create_symbolic_link_api = PtrCreateSymbolicLinkW( + ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), + "CreateSymbolicLinkW")); + + error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl &utf16) { + int len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + utf8.begin(), utf8.size(), + utf16.begin(), 0); + + if (len == 0) + return windows_error(::GetLastError()); + + utf16.reserve(len + 1); + utf16.set_size(len); + + len = ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + utf8.begin(), utf8.size(), + utf16.begin(), utf16.size()); + + if (len == 0) + return windows_error(::GetLastError()); + + // Make utf16 null terminated. + utf16.push_back(0); + utf16.pop_back(); + + return success; + } + + error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl &utf8) { + // Get length. + int len = ::WideCharToMultiByte(CP_UTF8, 0, + utf16, utf16_len, + utf8.begin(), 0, + NULL, NULL); + + if (len == 0) + return windows_error(::GetLastError()); + + utf8.reserve(len); + utf8.set_size(len); + + // Now do the actual conversion. + len = ::WideCharToMultiByte(CP_UTF8, 0, + utf16, utf16_len, + utf8.data(), utf8.size(), + NULL, NULL); + + if (len == 0) + return windows_error(::GetLastError()); + + // Make utf8 null terminated. + utf8.push_back(0); + utf8.pop_back(); + + return success; + } + + error_code TempDir(SmallVectorImpl &result) { + retry_temp_dir: + DWORD len = ::GetTempPathW(result.capacity(), result.begin()); + + if (len == 0) + return windows_error(::GetLastError()); + + if (len > result.capacity()) { + result.reserve(len); + goto retry_temp_dir; + } + + result.set_size(len); + return success; + } + + // Forwarder for ScopedHandle. + BOOL WINAPI CryptReleaseContext(HCRYPTPROV Provider) { + return ::CryptReleaseContext(Provider, 0); + } + + typedef ScopedHandle + ScopedCryptContext; + bool is_separator(const wchar_t value) { + switch (value) { + case L'\\': + case L'/': + return true; + default: + return false; + } + } +} + +namespace llvm { +namespace sys { +namespace fs { + +error_code current_path(SmallVectorImpl &result) { + SmallVector cur_path; + cur_path.reserve(128); +retry_cur_dir: + DWORD len = ::GetCurrentDirectoryW(cur_path.capacity(), cur_path.data()); + + // A zero return value indicates a failure other than insufficient space. + if (len == 0) + return windows_error(::GetLastError()); + + // If there's insufficient space, the len returned is larger than the len + // given. + if (len > cur_path.capacity()) { + cur_path.reserve(len); + goto retry_cur_dir; + } + + cur_path.set_size(len); + // cur_path now holds the current directory in utf-16. Convert to utf-8. + + // Find out how much space we need. Sadly, this function doesn't return the + // size needed unless you tell it the result size is 0, which means you + // _always_ have to call it twice. + len = ::WideCharToMultiByte(CP_UTF8, 0, + cur_path.data(), cur_path.size(), + result.data(), 0, + NULL, NULL); + + if (len == 0) + return make_error_code(windows_error(::GetLastError())); + + result.reserve(len); + result.set_size(len); + // Now do the actual conversion. + len = ::WideCharToMultiByte(CP_UTF8, 0, + cur_path.data(), cur_path.size(), + result.data(), result.size(), + NULL, NULL); + if (len == 0) + return windows_error(::GetLastError()); + + return success; +} + +error_code copy_file(const Twine &from, const Twine &to, copy_option copt) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toStringRef(from_storage); + StringRef t = to.toStringRef(to_storage); + + // Convert to utf-16. + SmallVector wide_from; + SmallVector wide_to; + if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; + if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; + + // Copy the file. + BOOL res = ::CopyFileW(wide_from.begin(), wide_to.begin(), + copt != copy_option::overwrite_if_exists); + + if (res == 0) + return windows_error(::GetLastError()); + + return success; +} + +error_code create_directory(const Twine &path, bool &existed) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + if (!::CreateDirectoryW(path_utf16.begin(), NULL)) { + error_code ec = windows_error(::GetLastError()); + if (ec == windows_error::already_exists) + existed = true; + else + return ec; + } else + existed = false; + + return success; +} + +error_code create_hard_link(const Twine &to, const Twine &from) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toStringRef(from_storage); + StringRef t = to.toStringRef(to_storage); + + // Convert to utf-16. + SmallVector wide_from; + SmallVector wide_to; + if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; + if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; + + if (!::CreateHardLinkW(wide_from.begin(), wide_to.begin(), NULL)) + return windows_error(::GetLastError()); + + return success; +} + +error_code create_symlink(const Twine &to, const Twine &from) { + // Only do it if the function is available at runtime. + if (!create_symbolic_link_api) + return make_error_code(errc::function_not_supported); + + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toStringRef(from_storage); + StringRef t = to.toStringRef(to_storage); + + // Convert to utf-16. + SmallVector wide_from; + SmallVector wide_to; + if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; + if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; + + if (!create_symbolic_link_api(wide_from.begin(), wide_to.begin(), 0)) + return windows_error(::GetLastError()); + + return success; +} + +error_code remove(const Twine &path, bool &existed) { + SmallString<128> path_storage; + SmallVector path_utf16; + + file_status st; + if (error_code ec = status(path, st)) + return ec; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + if (st.type() == file_type::directory_file) { + if (!::RemoveDirectoryW(c_str(path_utf16))) { + error_code ec = windows_error(::GetLastError()); + if (ec != windows_error::file_not_found) + return ec; + existed = false; + } else + existed = true; + } else { + if (!::DeleteFileW(c_str(path_utf16))) { + error_code ec = windows_error(::GetLastError()); + if (ec != windows_error::file_not_found) + return ec; + existed = false; + } else + existed = true; + } + + return success; +} + +error_code rename(const Twine &from, const Twine &to) { + // Get arguments. + SmallString<128> from_storage; + SmallString<128> to_storage; + StringRef f = from.toStringRef(from_storage); + StringRef t = to.toStringRef(to_storage); + + // Convert to utf-16. + SmallVector wide_from; + SmallVector wide_to; + if (error_code ec = UTF8ToUTF16(f, wide_from)) return ec; + if (error_code ec = UTF8ToUTF16(t, wide_to)) return ec; + + if (!::MoveFileExW(wide_from.begin(), wide_to.begin(), + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) + return windows_error(::GetLastError()); + + return success; +} + +error_code resize_file(const Twine &path, uint64_t size) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + int fd = ::_wopen(path_utf16.begin(), O_BINARY, S_IREAD | S_IWRITE); + if (fd == -1) + return error_code(errno, generic_category()); +#ifdef HAVE__CHSIZE_S + errno_t error = ::_chsize_s(fd, size); +#else + errno_t error = ::_chsize(fd, size); +#endif + ::close(fd); + return error_code(error, generic_category()); +} + +error_code exists(const Twine &path, bool &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + DWORD attributes = ::GetFileAttributesW(path_utf16.begin()); + + if (attributes == INVALID_FILE_ATTRIBUTES) { + // See if the file didn't actually exist. + error_code ec = make_error_code(windows_error(::GetLastError())); + if (ec != windows_error::file_not_found && + ec != windows_error::path_not_found) + return ec; + result = false; + } else + result = true; + return success; +} + +error_code equivalent(const Twine &A, const Twine &B, bool &result) { + // Get arguments. + SmallString<128> a_storage; + SmallString<128> b_storage; + StringRef a = A.toStringRef(a_storage); + StringRef b = B.toStringRef(b_storage); + + // Convert to utf-16. + SmallVector wide_a; + SmallVector wide_b; + if (error_code ec = UTF8ToUTF16(a, wide_a)) return ec; + if (error_code ec = UTF8ToUTF16(b, wide_b)) return ec; + + AutoHandle HandleB( + ::CreateFileW(wide_b.begin(), + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0)); + + AutoHandle HandleA( + ::CreateFileW(wide_a.begin(), + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0)); + + // If both handles are invalid, it's an error. + if (HandleA == INVALID_HANDLE_VALUE && + HandleB == INVALID_HANDLE_VALUE) + return windows_error(::GetLastError()); + + // If only one is invalid, it's false. + if (HandleA == INVALID_HANDLE_VALUE && + HandleB == INVALID_HANDLE_VALUE) { + result = false; + return success; + } + + // Get file information. + BY_HANDLE_FILE_INFORMATION InfoA, InfoB; + if (!::GetFileInformationByHandle(HandleA, &InfoA)) + return windows_error(::GetLastError()); + if (!::GetFileInformationByHandle(HandleB, &InfoB)) + return windows_error(::GetLastError()); + + // See if it's all the same. + result = + InfoA.dwVolumeSerialNumber == InfoB.dwVolumeSerialNumber && + InfoA.nFileIndexHigh == InfoB.nFileIndexHigh && + InfoA.nFileIndexLow == InfoB.nFileIndexLow && + InfoA.nFileSizeHigh == InfoB.nFileSizeHigh && + InfoA.nFileSizeLow == InfoB.nFileSizeLow && + InfoA.ftLastWriteTime.dwLowDateTime == + InfoB.ftLastWriteTime.dwLowDateTime && + InfoA.ftLastWriteTime.dwHighDateTime == + InfoB.ftLastWriteTime.dwHighDateTime; + + return success; +} + +error_code file_size(const Twine &path, uint64_t &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + WIN32_FILE_ATTRIBUTE_DATA FileData; + if (!::GetFileAttributesExW(path_utf16.begin(), + ::GetFileExInfoStandard, + &FileData)) + return windows_error(::GetLastError()); + + result = + (uint64_t(FileData.nFileSizeHigh) << (sizeof(FileData.nFileSizeLow) * 8)) + + FileData.nFileSizeLow; + + return success; +} + +error_code status(const Twine &path, file_status &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + DWORD attr = ::GetFileAttributesW(path_utf16.begin()); + if (attr == INVALID_FILE_ATTRIBUTES) + goto handle_status_error; + + // Handle reparse points. + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { + AutoHandle h( + ::CreateFileW(path_utf16.begin(), + 0, // Attributes only. + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + 0)); + if (h == INVALID_HANDLE_VALUE) + goto handle_status_error; + } + + if (attr & FILE_ATTRIBUTE_DIRECTORY) + result = file_status(file_type::directory_file); + else + result = file_status(file_type::regular_file); + + return success; + +handle_status_error: + error_code ec = windows_error(::GetLastError()); + if (ec == windows_error::file_not_found || + ec == windows_error::path_not_found) + result = file_status(file_type::file_not_found); + else if (ec == windows_error::sharing_violation) + result = file_status(file_type::type_unknown); + else { + result = file_status(file_type::status_error); + return ec; + } + + return success; +} + +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl &result_path) { + // Use result_path as temp storage. + result_path.set_size(0); + StringRef m = model.toStringRef(result_path); + + SmallVector model_utf16; + if (error_code ec = UTF8ToUTF16(m, model_utf16)) return ec; + + // Make model absolute by prepending a temp directory if it's not already. + bool absolute = path::is_absolute(m); + + if (!absolute) { + SmallVector temp_dir; + if (error_code ec = TempDir(temp_dir)) return ec; + // Handle c: by removing it. + if (model_utf16.size() > 2 && model_utf16[1] == L':') { + model_utf16.erase(model_utf16.begin(), model_utf16.begin() + 2); + } + model_utf16.insert(model_utf16.begin(), temp_dir.begin(), temp_dir.end()); + } + + // Replace '%' with random chars. From here on, DO NOT modify model. It may be + // needed if the randomly chosen path already exists. + SmallVector random_path_utf16; + + // Get a Crypto Provider for CryptGenRandom. + HCRYPTPROV HCPC; + if (!::CryptAcquireContextW(&HCPC, + NULL, + NULL, + PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return windows_error(::GetLastError()); + ScopedCryptContext CryptoProvider(HCPC); + +retry_random_path: + random_path_utf16.set_size(0); + for (SmallVectorImpl::const_iterator i = model_utf16.begin(), + e = model_utf16.end(); + i != e; ++i) { + if (*i == L'%') { + BYTE val = 0; + if (!::CryptGenRandom(CryptoProvider, 1, &val)) + return windows_error(::GetLastError()); + random_path_utf16.push_back("0123456789abcdef"[val & 15]); + } + else + random_path_utf16.push_back(*i); + } + // Make random_path_utf16 null terminated. + random_path_utf16.push_back(0); + random_path_utf16.pop_back(); + + // Try to create + open the path. +retry_create_file: + HANDLE TempFileHandle = ::CreateFileW(random_path_utf16.begin(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + // Return ERROR_FILE_EXISTS if the file + // already exists. + CREATE_NEW, + FILE_ATTRIBUTE_TEMPORARY, + NULL); + if (TempFileHandle == INVALID_HANDLE_VALUE) { + // If the file existed, try again, otherwise, error. + error_code ec = windows_error(::GetLastError()); + if (ec == windows_error::file_exists) + goto retry_random_path; + // Check for non-existing parent directories. + if (ec == windows_error::path_not_found) { + // Create the directories using result_path as temp storage. + if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(), + random_path_utf16.size(), result_path)) + return ec; + StringRef p(result_path.begin(), result_path.size()); + SmallString<64> dir_to_create; + for (path::const_iterator i = path::begin(p), + e = --path::end(p); i != e; ++i) { + path::append(dir_to_create, *i); + bool Exists; + if (error_code ec = exists(Twine(dir_to_create), Exists)) return ec; + if (!Exists) { + // If c: doesn't exist, bail. + if (i->endswith(":")) + return ec; + + SmallVector dir_to_create_utf16; + if (error_code ec = UTF8ToUTF16(dir_to_create, dir_to_create_utf16)) + return ec; + + // Create the directory. + if (!::CreateDirectoryW(dir_to_create_utf16.begin(), NULL)) + return windows_error(::GetLastError()); + } + } + goto retry_create_file; + } + return ec; + } + + // Set result_path to the utf-8 representation of the path. + if (error_code ec = UTF16ToUTF8(random_path_utf16.begin(), + random_path_utf16.size(), result_path)) { + ::CloseHandle(TempFileHandle); + ::DeleteFileW(random_path_utf16.begin()); + return ec; + } + + // Convert the Windows API file handle into a C-runtime handle. + int fd = ::_open_osfhandle(intptr_t(TempFileHandle), 0); + if (fd == -1) { + ::CloseHandle(TempFileHandle); + ::DeleteFileW(random_path_utf16.begin()); + // MSDN doesn't say anything about _open_osfhandle setting errno or + // GetLastError(), so just return invalid_handle. + return windows_error::invalid_handle; + } + + result_fd = fd; + return success; +} + +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl &result) { + SmallString<128> path_storage; + SmallVector path_utf16; + result.set_size(0); + + // Convert path to UTF-16. + if (error_code ec = UTF8ToUTF16(path.toStringRef(path_storage), + path_utf16)) + return ec; + + // Open file. + HANDLE file = ::CreateFileW(c_str(path_utf16), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, + NULL); + if (file == INVALID_HANDLE_VALUE) + return windows_error(::GetLastError()); + + // Allocate buffer. + result.reserve(len); + + // Get magic! + DWORD bytes_read = 0; + BOOL read_success = ::ReadFile(file, result.data(), len, &bytes_read, NULL); + error_code ec = windows_error(::GetLastError()); + ::CloseHandle(file); + if (!read_success || (bytes_read != len)) { + // Set result size to the number of bytes read if it's valid. + if (bytes_read <= len) + result.set_size(bytes_read); + // ERROR_HANDLE_EOF is mapped to errc::value_too_large. + return ec; + } + + result.set_size(len); + return success; +} + +error_code directory_iterator_construct(directory_iterator &it, StringRef path){ + SmallVector path_utf16; + + if (error_code ec = UTF8ToUTF16(path, + path_utf16)) + return ec; + + // Convert path to the format that Windows is happy with. + if (path_utf16.size() > 0 && + !is_separator(path_utf16[path.size() - 1]) && + path_utf16[path.size() - 1] != L':') { + path_utf16.push_back(L'\\'); + path_utf16.push_back(L'*'); + } else { + path_utf16.push_back(L'*'); + } + + // Get the first directory entry. + WIN32_FIND_DATAW FirstFind; + ScopedFindHandle FindHandle(::FindFirstFileW(c_str(path_utf16), &FirstFind)); + if (!FindHandle) + return windows_error(::GetLastError()); + + size_t FilenameLen = ::wcslen(FirstFind.cFileName); + while ((FilenameLen == 1 && FirstFind.cFileName[0] == L'.') || + (FilenameLen == 2 && FirstFind.cFileName[0] == L'.' && + FirstFind.cFileName[1] == L'.')) + if (!::FindNextFileW(FindHandle, &FirstFind)) { + error_code ec = windows_error(::GetLastError()); + // Check for end. + if (ec == windows_error::no_more_files) + return directory_iterator_destruct(it); + return ec; + } else + FilenameLen = ::wcslen(FirstFind.cFileName); + + // Construct the current directory entry. + SmallString<128> directory_entry_name_utf8; + if (error_code ec = UTF16ToUTF8(FirstFind.cFileName, + ::wcslen(FirstFind.cFileName), + directory_entry_name_utf8)) + return ec; + + it.IterationHandle = intptr_t(FindHandle.take()); + SmallString<128> directory_entry_path(path); + path::append(directory_entry_path, directory_entry_name_utf8.str()); + it.CurrentEntry = directory_entry(directory_entry_path.str()); + + return success; +} + +error_code directory_iterator_destruct(directory_iterator& it) { + if (it.IterationHandle != 0) + // Closes the handle if it's valid. + ScopedFindHandle close(HANDLE(it.IterationHandle)); + it.IterationHandle = 0; + it.CurrentEntry = directory_entry(); + return success; +} + +error_code directory_iterator_increment(directory_iterator& it) { + WIN32_FIND_DATAW FindData; + if (!::FindNextFileW(HANDLE(it.IterationHandle), &FindData)) { + error_code ec = windows_error(::GetLastError()); + // Check for end. + if (ec == windows_error::no_more_files) + return directory_iterator_destruct(it); + return ec; + } + + size_t FilenameLen = ::wcslen(FindData.cFileName); + if ((FilenameLen == 1 && FindData.cFileName[0] == L'.') || + (FilenameLen == 2 && FindData.cFileName[0] == L'.' && + FindData.cFileName[1] == L'.')) + return directory_iterator_increment(it); + + SmallString<128> directory_entry_path_utf8; + if (error_code ec = UTF16ToUTF8(FindData.cFileName, + ::wcslen(FindData.cFileName), + directory_entry_path_utf8)) + return ec; + + it.CurrentEntry.replace_filename(Twine(directory_entry_path_utf8)); + return success; +} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm diff --git a/final/lib/Support/Windows/Process.inc b/final/lib/Support/Windows/Process.inc new file mode 100644 index 00000000000..06a7f0054d5 --- /dev/null +++ b/final/lib/Support/Windows/Process.inc @@ -0,0 +1,222 @@ +//===- Win32/Process.cpp - Win32 Process Implementation ------- -*- 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 the Win32 specific implementation of the Process class. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include +#include + +#ifdef __MINGW32__ + #if (HAVE_LIBPSAPI != 1) + #error "libpsapi.a should be present" + #endif +#else + #pragma comment(lib, "psapi.lib") +#endif + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef __MINGW32__ +// This ban should be lifted when MinGW 1.0+ has defined this value. +# define _HEAPOK (-2) +#endif + +namespace llvm { +using namespace sys; + +// This function retrieves the page size using GetSystemInfo and is present +// solely so it can be called once in Process::GetPageSize to initialize the +// static variable PageSize. +inline unsigned GetPageSizeOnce() { + // NOTE: A 32-bit application running under WOW64 is supposed to use + // GetNativeSystemInfo. However, this interface is not present prior + // to Windows XP so to use it requires dynamic linking. It is not clear + // how this affects the reported page size, if at all. One could argue + // that LLVM ought to run as 64-bits on a 64-bit system, anyway. + SYSTEM_INFO info; + GetSystemInfo(&info); + return static_cast(info.dwPageSize); +} + +unsigned +Process::GetPageSize() { + static const unsigned PageSize = GetPageSizeOnce(); + return PageSize; +} + +size_t +Process::GetMallocUsage() +{ + _HEAPINFO hinfo; + hinfo._pentry = NULL; + + size_t size = 0; + + while (_heapwalk(&hinfo) == _HEAPOK) + size += hinfo._size; + + return size; +} + +size_t +Process::GetTotalMemoryUsage() +{ + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); + return pmc.PagefileUsage; +} + +void +Process::GetTimeUsage( + TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) +{ + elapsed = TimeValue::now(); + + uint64_t ProcCreate, ProcExit, KernelTime, UserTime; + GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate, + (FILETIME*)&ProcExit, (FILETIME*)&KernelTime, + (FILETIME*)&UserTime); + + // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond) + user_time.seconds( UserTime / 10000000 ); + user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 ); + sys_time.seconds( KernelTime / 10000000 ); + sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 ); +} + +int Process::GetCurrentUserId() +{ + return 65536; +} + +int Process::GetCurrentGroupId() +{ + return 65536; +} + +// Some LLVM programs such as bugpoint produce core files as a normal part of +// their operation. To prevent the disk from filling up, this configuration item +// does what's necessary to prevent their generation. +void Process::PreventCoreFiles() { + // Windows doesn't do core files, but it does do modal pop-up message + // boxes. As this method is used by bugpoint, preventing these pop-ups + // is the moral equivalent of suppressing core files. + SetErrorMode(SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); +} + +bool Process::StandardInIsUserInput() { + return FileDescriptorIsDisplayed(0); +} + +bool Process::StandardOutIsDisplayed() { + return FileDescriptorIsDisplayed(1); +} + +bool Process::StandardErrIsDisplayed() { + return FileDescriptorIsDisplayed(2); +} + +bool Process::FileDescriptorIsDisplayed(int fd) { + DWORD Mode; // Unused + return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0); +} + +unsigned Process::StandardOutColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +unsigned Process::StandardErrColumns() { + unsigned Columns = 0; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) + Columns = csbi.dwSize.X; + return Columns; +} + +// It always has colors. +bool Process::StandardErrHasColors() { + return StandardErrIsDisplayed(); +} + +bool Process::StandardOutHasColors() { + return StandardOutIsDisplayed(); +} + +namespace { +class DefaultColors +{ + private: + WORD defaultColor; + public: + DefaultColors() + :defaultColor(GetCurrentColor()) {} + static unsigned GetCurrentColor() { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return csbi.wAttributes; + return 0; + } + WORD operator()() const { return defaultColor; } +}; + +DefaultColors defaultColors; +} + +bool Process::ColorNeedsFlush() { + return true; +} + +const char *Process::OutputBold(bool bg) { + WORD colors = DefaultColors::GetCurrentColor(); + if (bg) + colors |= BACKGROUND_INTENSITY; + else + colors |= FOREGROUND_INTENSITY; + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::OutputColor(char code, bool bold, bool bg) { + WORD colors; + if (bg) { + colors = ((code&1) ? BACKGROUND_RED : 0) | + ((code&2) ? BACKGROUND_GREEN : 0 ) | + ((code&4) ? BACKGROUND_BLUE : 0); + if (bold) + colors |= BACKGROUND_INTENSITY; + } else { + colors = ((code&1) ? FOREGROUND_RED : 0) | + ((code&2) ? FOREGROUND_GREEN : 0 ) | + ((code&4) ? FOREGROUND_BLUE : 0); + if (bold) + colors |= FOREGROUND_INTENSITY; + } + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::ResetColor() { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); + return 0; +} + +} diff --git a/final/lib/Support/Windows/Program.inc b/final/lib/Support/Windows/Program.inc new file mode 100644 index 00000000000..350363cf710 --- /dev/null +++ b/final/lib/Support/Windows/Program.inc @@ -0,0 +1,403 @@ +//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- 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 the Win32 specific implementation of the Program class. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include +#include +#include + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +namespace { + struct Win32ProcessInfo { + HANDLE hProcess; + DWORD dwProcessId; + }; +} + +namespace llvm { +using namespace sys; + +Program::Program() : Data_(0) {} + +Program::~Program() { + if (Data_) { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + CloseHandle(wpi->hProcess); + delete wpi; + Data_ = 0; + } +} + +unsigned Program::GetPid() const { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + return wpi->dwProcessId; +} + +// This function just uses the PATH environment variable to find the program. +Path +Program::FindProgramByName(const std::string& progName) { + + // Check some degenerate cases + if (progName.length() == 0) // no program + return Path(); + Path temp; + if (!temp.set(progName)) // invalid name + return Path(); + // Return paths with slashes verbatim. + if (progName.find('\\') != std::string::npos || + progName.find('/') != std::string::npos) + return temp; + + // At this point, the file name is valid and does not contain slashes. + // Let Windows search for it. + char buffer[MAX_PATH]; + char *dummy = NULL; + DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH, + buffer, &dummy); + + // See if it wasn't found. + if (len == 0) + return Path(); + + // See if we got the entire path. + if (len < MAX_PATH) + return Path(buffer); + + // Buffer was too small; grow and retry. + while (true) { + char *b = reinterpret_cast(_alloca(len+1)); + DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy); + + // It is unlikely the search failed, but it's always possible some file + // was added or removed since the last search, so be paranoid... + if (len2 == 0) + return Path(); + else if (len2 <= len) + return Path(b); + + len = len2; + } +} + +static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) { + HANDLE h; + if (path == 0) { + DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd), + GetCurrentProcess(), &h, + 0, TRUE, DUPLICATE_SAME_ACCESS); + return h; + } + + const char *fname; + if (path->isEmpty()) + fname = "NUL"; + else + fname = path->c_str(); + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = 0; + sa.bInheritHandle = TRUE; + + h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, + &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " + + (fd ? "input: " : "output: ")); + } + + return h; +} + +/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling +/// CreateProcess. +static bool ArgNeedsQuotes(const char *Str) { + return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0; +} + + +/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling +/// CreateProcess and returns length of quoted arg with escaped quotes +static unsigned int ArgLenWithQuotes(const char *Str) { + unsigned int len = ArgNeedsQuotes(Str) ? 2 : 0; + + while (*Str != '\0') { + if (*Str == '\"') + ++len; + + ++len; + ++Str; + } + + return len; +} + + +bool +Program::Execute(const Path& path, + const char** args, + const char** envp, + const Path** redirects, + unsigned memoryLimit, + std::string* ErrMsg) { + if (Data_) { + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + CloseHandle(wpi->hProcess); + delete wpi; + Data_ = 0; + } + + if (!path.canExecute()) { + if (ErrMsg) + *ErrMsg = "program not executable"; + return false; + } + + // Windows wants a command line, not an array of args, to pass to the new + // process. We have to concatenate them all, while quoting the args that + // have embedded spaces (or are empty). + + // First, determine the length of the command line. + unsigned len = 0; + for (unsigned i = 0; args[i]; i++) { + len += ArgLenWithQuotes(args[i]) + 1; + } + + // Now build the command line. + char *command = reinterpret_cast(_alloca(len+1)); + char *p = command; + + for (unsigned i = 0; args[i]; i++) { + const char *arg = args[i]; + + bool needsQuoting = ArgNeedsQuotes(arg); + if (needsQuoting) + *p++ = '"'; + + while (*arg != '\0') { + if (*arg == '\"') + *p++ = '\\'; + + *p++ = *arg++; + } + + if (needsQuoting) + *p++ = '"'; + *p++ = ' '; + } + + *p = 0; + + // The pointer to the environment block for the new process. + char *envblock = 0; + + if (envp) { + // An environment block consists of a null-terminated block of + // null-terminated strings. Convert the array of environment variables to + // an environment block by concatenating them. + + // First, determine the length of the environment block. + len = 0; + for (unsigned i = 0; envp[i]; i++) + len += strlen(envp[i]) + 1; + + // Now build the environment block. + envblock = reinterpret_cast(_alloca(len+1)); + p = envblock; + + for (unsigned i = 0; envp[i]; i++) { + const char *ev = envp[i]; + size_t len = strlen(ev) + 1; + memcpy(p, ev, len); + p += len; + } + + *p = 0; + } + + // Create a child process. + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = INVALID_HANDLE_VALUE; + si.hStdOutput = INVALID_HANDLE_VALUE; + si.hStdError = INVALID_HANDLE_VALUE; + + if (redirects) { + si.dwFlags = STARTF_USESTDHANDLES; + + si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg); + if (si.hStdInput == INVALID_HANDLE_VALUE) { + MakeErrMsg(ErrMsg, "can't redirect stdin"); + return false; + } + si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg); + if (si.hStdOutput == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + MakeErrMsg(ErrMsg, "can't redirect stdout"); + return false; + } + if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) { + // If stdout and stderr should go to the same place, redirect stderr + // to the handle already open for stdout. + DuplicateHandle(GetCurrentProcess(), si.hStdOutput, + GetCurrentProcess(), &si.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } else { + // Just redirect stderr + si.hStdError = RedirectIO(redirects[2], 2, ErrMsg); + if (si.hStdError == INVALID_HANDLE_VALUE) { + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + MakeErrMsg(ErrMsg, "can't redirect stderr"); + return false; + } + } + } + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + + fflush(stdout); + fflush(stderr); + BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0, + envblock, NULL, &si, &pi); + DWORD err = GetLastError(); + + // Regardless of whether the process got created or not, we are done with + // the handles we created for it to inherit. + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + // Now return an error if the process didn't get created. + if (!rc) { + SetLastError(err); + MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") + + path.str() + "'"); + return false; + } + Win32ProcessInfo* wpi = new Win32ProcessInfo; + wpi->hProcess = pi.hProcess; + wpi->dwProcessId = pi.dwProcessId; + Data_ = wpi; + + // Make sure these get closed no matter what. + AutoHandle hThread(pi.hThread); + + // Assign the process to a job if a memory limit is defined. + AutoHandle hJob(0); + if (memoryLimit != 0) { + hJob = CreateJobObject(0, 0); + bool success = false; + if (hJob != 0) { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli; + memset(&jeli, 0, sizeof(jeli)); + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY; + jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576; + if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, + &jeli, sizeof(jeli))) { + if (AssignProcessToJobObject(hJob, pi.hProcess)) + success = true; + } + } + if (!success) { + SetLastError(GetLastError()); + MakeErrMsg(ErrMsg, std::string("Unable to set memory limit")); + TerminateProcess(pi.hProcess, 1); + WaitForSingleObject(pi.hProcess, INFINITE); + return false; + } + } + + return true; +} + +int +Program::Wait(const Path &path, + unsigned secondsToWait, + std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return -1; + } + + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + HANDLE hProcess = wpi->hProcess; + + // Wait for the process to terminate. + DWORD millisecondsToWait = INFINITE; + if (secondsToWait > 0) + millisecondsToWait = secondsToWait * 1000; + + if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) { + if (!TerminateProcess(hProcess, 1)) { + MakeErrMsg(ErrMsg, "Failed to terminate timed-out program."); + return -1; + } + WaitForSingleObject(hProcess, INFINITE); + } + + // Get its exit status. + DWORD status; + BOOL rc = GetExitCodeProcess(hProcess, &status); + DWORD err = GetLastError(); + + if (!rc) { + SetLastError(err); + MakeErrMsg(ErrMsg, "Failed getting status for program."); + return -1; + } + + return status; +} + +bool +Program::Kill(std::string* ErrMsg) { + if (Data_ == 0) { + MakeErrMsg(ErrMsg, "Process not started!"); + return true; + } + + Win32ProcessInfo* wpi = reinterpret_cast(Data_); + HANDLE hProcess = wpi->hProcess; + if (TerminateProcess(hProcess, 1) == 0) { + MakeErrMsg(ErrMsg, "The process couldn't be killed!"); + return true; + } + + return false; +} + +bool Program::ChangeStdinToBinary(){ + int result = _setmode( _fileno(stdin), _O_BINARY ); + return result == -1; +} + +bool Program::ChangeStdoutToBinary(){ + int result = _setmode( _fileno(stdout), _O_BINARY ); + return result == -1; +} + +bool Program::ChangeStderrToBinary(){ + int result = _setmode( _fileno(stderr), _O_BINARY ); + return result == -1; +} + +} diff --git a/final/lib/Support/Windows/RWMutex.inc b/final/lib/Support/Windows/RWMutex.inc new file mode 100644 index 00000000000..471f8fa294b --- /dev/null +++ b/final/lib/Support/Windows/RWMutex.inc @@ -0,0 +1,58 @@ +//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// +// +// 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 Win32 specific (non-pthread) RWMutex class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Windows.h" + +// FIXME: Windows does not have reader-writer locks pre-Vista. If you want +// real reader-writer locks, you a threads implementation for Windows. + +namespace llvm { +using namespace sys; + +RWMutexImpl::RWMutexImpl() { + data_ = calloc(1, sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(static_cast(data_)); +} + +RWMutexImpl::~RWMutexImpl() { + DeleteCriticalSection(static_cast(data_)); + free(data_); +} + +bool RWMutexImpl::reader_acquire() { + EnterCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::reader_release() { + LeaveCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::writer_acquire() { + EnterCriticalSection(static_cast(data_)); + return true; +} + +bool RWMutexImpl::writer_release() { + LeaveCriticalSection(static_cast(data_)); + return true; +} + + +} diff --git a/final/lib/Support/Windows/Signals.inc b/final/lib/Support/Windows/Signals.inc new file mode 100644 index 00000000000..14f3f21f02a --- /dev/null +++ b/final/lib/Support/Windows/Signals.inc @@ -0,0 +1,328 @@ +//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- 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 the Win32 specific implementation of the Signals class. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include +#include +#include + +#ifdef __MINGW32__ + #include +#else + #include +#endif +#include + +#ifdef __MINGW32__ + #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) + #error "libimagehlp.a & libpsapi.a should be present" + #endif +#else + #pragma comment(lib, "psapi.lib") + #pragma comment(lib, "dbghelp.lib") +#endif + +// Forward declare. +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); + +// InterruptFunction - The function to call if ctrl-c is pressed. +static void (*InterruptFunction)() = 0; + +static std::vector *FilesToRemove = NULL; +static std::vector > *CallBacksToRun = 0; +static bool RegisteredUnhandledExceptionFilter = false; +static bool CleanupExecuted = false; +static bool ExitOnUnhandledExceptions = false; +static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; + +// Windows creates a new thread to execute the console handler when an event +// (such as CTRL/C) occurs. This causes concurrency issues with the above +// globals which this critical section addresses. +static CRITICAL_SECTION CriticalSection; + +namespace llvm { + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code +//=== and must not be UNIX code +//===----------------------------------------------------------------------===// + +#ifdef _MSC_VER +/// CRTReportHook - Function called on a CRT debugging event. +static int CRTReportHook(int ReportType, char *Message, int *Return) { + // Don't cause a DebugBreak() on return. + if (Return) + *Return = 0; + + switch (ReportType) { + default: + case _CRT_ASSERT: + fprintf(stderr, "CRT assert: %s\n", Message); + // FIXME: Is there a way to just crash? Perhaps throw to the unhandled + // exception code? Perhaps SetErrorMode() handles this. + _exit(3); + break; + case _CRT_ERROR: + fprintf(stderr, "CRT error: %s\n", Message); + // FIXME: Is there a way to just crash? Perhaps throw to the unhandled + // exception code? Perhaps SetErrorMode() handles this. + _exit(3); + break; + case _CRT_WARN: + fprintf(stderr, "CRT warn: %s\n", Message); + break; + } + + // Don't call _CrtDbgReport. + return TRUE; +} +#endif + +static void RegisterHandler() { + if (RegisteredUnhandledExceptionFilter) { + EnterCriticalSection(&CriticalSection); + return; + } + + // Now's the time to create the critical section. This is the first time + // through here, and there's only one thread. + InitializeCriticalSection(&CriticalSection); + + // Enter it immediately. Now if someone hits CTRL/C, the console handler + // can't proceed until the globals are updated. + EnterCriticalSection(&CriticalSection); + + RegisteredUnhandledExceptionFilter = true; + OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); + SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); + + // Environment variable to disable any kind of crash dialog. + if (getenv("LLVM_DISABLE_CRT_DEBUG")) { +#ifdef _MSC_VER + _CrtSetReportHook(CRTReportHook); +#endif + SetErrorMode(SEM_FAILCRITICALERRORS | + SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); + ExitOnUnhandledExceptions = true; + } + + // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or + // else multi-threading problems will ensue. +} + +// RemoveFileOnSignal - The public API +bool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { + RegisterHandler(); + + if (CleanupExecuted) { + if (ErrMsg) + *ErrMsg = "Process terminating -- cannot register for removal"; + return true; + } + + if (FilesToRemove == NULL) + FilesToRemove = new std::vector; + + FilesToRemove->push_back(Filename); + + LeaveCriticalSection(&CriticalSection); + return false; +} + +// DontRemoveFileOnSignal - The public API +void sys::DontRemoveFileOnSignal(const sys::Path &Filename) { + if (FilesToRemove == NULL) + return; + + RegisterHandler(); + + FilesToRemove->push_back(Filename); + std::vector::reverse_iterator I = + std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); + if (I != FilesToRemove->rend()) + FilesToRemove->erase(I.base()-1); + + LeaveCriticalSection(&CriticalSection); +} + +/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or +/// SIGSEGV) is delivered to the process, print a stack trace and then exit. +void sys::PrintStackTraceOnErrorSignal() { + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); +} + + +void sys::SetInterruptFunction(void (*IF)()) { + RegisterHandler(); + InterruptFunction = IF; + LeaveCriticalSection(&CriticalSection); +} + + +/// AddSignalHandler - Add a function to be called when a signal is delivered +/// to the process. The handler can have a cookie passed to it to identify +/// what instance of the handler it is. +void sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { + if (CallBacksToRun == 0) + CallBacksToRun = new std::vector >(); + CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); + RegisterHandler(); + LeaveCriticalSection(&CriticalSection); +} +} + +static void Cleanup() { + EnterCriticalSection(&CriticalSection); + + // Prevent other thread from registering new files and directories for + // removal, should we be executing because of the console handler callback. + CleanupExecuted = true; + + // FIXME: open files cannot be deleted. + + if (FilesToRemove != NULL) + while (!FilesToRemove->empty()) { + FilesToRemove->back().eraseFromDisk(); + FilesToRemove->pop_back(); + } + + if (CallBacksToRun) + for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) + (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); + + LeaveCriticalSection(&CriticalSection); +} + +void llvm::sys::RunInterruptHandlers() { + Cleanup(); +} + +static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { + Cleanup(); + +#ifdef _WIN64 + // TODO: provide a x64 friendly version of the following +#else + + // Initialize the STACKFRAME structure. + STACKFRAME StackFrame; + memset(&StackFrame, 0, sizeof(StackFrame)); + + StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; + StackFrame.AddrFrame.Mode = AddrModeFlat; + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + // Initialize the symbol handler. + SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); + SymInitialize(hProcess, NULL, TRUE); + + while (true) { + if (!StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &StackFrame, + ep->ContextRecord, NULL, SymFunctionTableAccess, + SymGetModuleBase, NULL)) { + break; + } + + if (StackFrame.AddrFrame.Offset == 0) + break; + + // Print the PC in hexadecimal. + DWORD PC = StackFrame.AddrPC.Offset; + fprintf(stderr, "%08lX", PC); + + // Print the parameters. Assume there are four. + fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", + StackFrame.Params[0], + StackFrame.Params[1], StackFrame.Params[2], StackFrame.Params[3]); + + // Verify the PC belongs to a module in this process. + if (!SymGetModuleBase(hProcess, PC)) { + fputs(" \n", stderr); + continue; + } + + // Print the symbol name. + char buffer[512]; + IMAGEHLP_SYMBOL *symbol = reinterpret_cast(buffer); + memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL)); + symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); + symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL); + + DWORD dwDisp; + if (!SymGetSymFromAddr(hProcess, PC, &dwDisp, symbol)) { + fputc('\n', stderr); + continue; + } + + buffer[511] = 0; + if (dwDisp > 0) + fprintf(stderr, ", %s()+%04lu bytes(s)", symbol->Name, dwDisp); + else + fprintf(stderr, ", %s", symbol->Name); + + // Print the source file and line number information. + IMAGEHLP_LINE line; + memset(&line, 0, sizeof(line)); + line.SizeOfStruct = sizeof(line); + if (SymGetLineFromAddr(hProcess, PC, &dwDisp, &line)) { + fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); + if (dwDisp > 0) + fprintf(stderr, "+%04lu byte(s)", dwDisp); + } + + fputc('\n', stderr); + } + +#endif + + if (ExitOnUnhandledExceptions) + _exit(-3); + + // Allow dialog box to pop up allowing choice to start debugger. + if (OldFilter) + return (*OldFilter)(ep); + else + return EXCEPTION_CONTINUE_SEARCH; +} + +static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { + // We are running in our very own thread, courtesy of Windows. + EnterCriticalSection(&CriticalSection); + Cleanup(); + + // If an interrupt function has been set, go and run one it; otherwise, + // the process dies. + void (*IF)() = InterruptFunction; + InterruptFunction = 0; // Don't run it on another CTRL-C. + + if (IF) { + // Note: if the interrupt function throws an exception, there is nothing + // to catch it in this thread so it will kill the process. + IF(); // Run it now. + LeaveCriticalSection(&CriticalSection); + return TRUE; // Don't kill the process. + } + + // Allow normal processing to take place; i.e., the process dies. + LeaveCriticalSection(&CriticalSection); + return FALSE; +} diff --git a/final/lib/Support/Windows/ThreadLocal.inc b/final/lib/Support/Windows/ThreadLocal.inc new file mode 100644 index 00000000000..512462d8900 --- /dev/null +++ b/final/lib/Support/Windows/ThreadLocal.inc @@ -0,0 +1,54 @@ +//= llvm/Support/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Win32 specific (non-pthread) ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include "llvm/Support/ThreadLocal.h" + +namespace llvm { +using namespace sys; + +ThreadLocalImpl::ThreadLocalImpl() { + DWORD* tls = new DWORD; + *tls = TlsAlloc(); + assert(*tls != TLS_OUT_OF_INDEXES); + data = tls; +} + +ThreadLocalImpl::~ThreadLocalImpl() { + DWORD* tls = static_cast(data); + TlsFree(*tls); + delete tls; +} + +const void* ThreadLocalImpl::getInstance() { + DWORD* tls = static_cast(data); + return TlsGetValue(*tls); +} + +void ThreadLocalImpl::setInstance(const void* d){ + DWORD* tls = static_cast(data); + int errorcode = TlsSetValue(*tls, const_cast(d)); + assert(errorcode != 0); + (void)errorcode; +} + +void ThreadLocalImpl::removeInstance() { + setInstance(0); +} + +} diff --git a/final/lib/Support/Windows/TimeValue.inc b/final/lib/Support/Windows/TimeValue.inc new file mode 100644 index 00000000000..12275526f1c --- /dev/null +++ b/final/lib/Support/Windows/TimeValue.inc @@ -0,0 +1,51 @@ +//===- Win32/TimeValue.cpp - Win32 TimeValue Implementation -----*- 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 the Win32 implementation of the TimeValue class. +// +//===----------------------------------------------------------------------===// + +#include "Windows.h" +#include + +namespace llvm { +using namespace sys; + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only Win32 specific code. +//===----------------------------------------------------------------------===// + +TimeValue TimeValue::now() { + uint64_t ft; + GetSystemTimeAsFileTime(reinterpret_cast(&ft)); + + TimeValue t(0, 0); + t.fromWin32Time(ft); + return t; +} + +std::string TimeValue::str() const { +#ifdef __MINGW32__ + // This ban may be lifted by either: + // (i) a future MinGW version other than 1.0 inherents the __time64_t type, or + // (ii) configure tests for either the time_t or __time64_t type. + time_t ourTime = time_t(this->toEpochTime()); + struct tm *lt = ::localtime(&ourTime); +#else + __time64_t ourTime = this->toEpochTime(); + struct tm *lt = ::_localtime64(&ourTime); +#endif + + char buffer[25]; + strftime(buffer, 25, "%a %b %d %H:%M:%S %Y", lt); + return std::string(buffer); +} + + +} diff --git a/final/lib/Support/Windows/Windows.h b/final/lib/Support/Windows/Windows.h new file mode 100644 index 00000000000..4a1553b599d --- /dev/null +++ b/final/lib/Support/Windows/Windows.h @@ -0,0 +1,120 @@ +//===- Win32/Win32.h - Common Win32 Include 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 defines things specific to Win32 implementations. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Win32 code that +//=== is guaranteed to work on *all* Win32 variants. +//===----------------------------------------------------------------------===// + +// mingw-w64 tends to define it as 0x0502 in its headers. +#undef _WIN32_WINNT + +// Require at least Windows 2000 API. +#define _WIN32_WINNT 0x0500 +#define _WIN32_IE 0x0500 // MinGW at it again. +#define WIN32_LEAN_AND_MEAN + +#include "llvm/Config/config.h" // Get build system configuration settings +#include +#include +#include +#include + +inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) { + if (!ErrMsg) + return true; + char *buffer = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, GetLastError(), 0, (LPSTR)&buffer, 1, NULL); + *ErrMsg = prefix + buffer; + LocalFree(buffer); + return true; +} + +class AutoHandle { + HANDLE handle; + +public: + AutoHandle(HANDLE h) : handle(h) {} + + ~AutoHandle() { + if (handle) + CloseHandle(handle); + } + + operator HANDLE() { + return handle; + } + + AutoHandle &operator=(HANDLE h) { + handle = h; + return *this; + } +}; + +template +class ScopedHandle { + HandleType Handle; + +public: + ScopedHandle() : Handle(InvalidHandle) {} + ScopedHandle(HandleType handle) : Handle(handle) {} + + ~ScopedHandle() { + if (Handle != HandleType(InvalidHandle)) + D(Handle); + } + + HandleType take() { + HandleType temp = Handle; + Handle = HandleType(InvalidHandle); + return temp; + } + + operator HandleType() const { return Handle; } + + ScopedHandle &operator=(HandleType handle) { + Handle = handle; + return *this; + } + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + // True if Handle is valid. + operator unspecified_bool_type() const { + return Handle == HandleType(InvalidHandle) ? 0 : unspecified_bool_true; + } + + bool operator!() const { + return Handle == HandleType(InvalidHandle); + } +}; + +typedef ScopedHandle + ScopedFindHandle; + +namespace llvm { +template +class SmallVectorImpl; + +template +typename SmallVectorImpl::const_pointer +c_str(SmallVectorImpl &str) { + str.push_back(0); + str.pop_back(); + return str.data(); +} +} // end namespace llvm. diff --git a/final/lib/Support/Windows/explicit_symbols.inc b/final/lib/Support/Windows/explicit_symbols.inc new file mode 100644 index 00000000000..84862d69e2b --- /dev/null +++ b/final/lib/Support/Windows/explicit_symbols.inc @@ -0,0 +1,66 @@ +/* in libgcc.a */ + +#ifdef HAVE__ALLOCA + EXPLICIT_SYMBOL(_alloca) + EXPLICIT_SYMBOL2(alloca, _alloca); +#endif +#ifdef HAVE___ALLOCA + EXPLICIT_SYMBOL(__alloca) +#endif +#ifdef HAVE___CHKSTK + EXPLICIT_SYMBOL(__chkstk) +#endif +#ifdef HAVE____CHKSTK + EXPLICIT_SYMBOL(___chkstk) +#endif +#ifdef HAVE___MAIN + EXPLICIT_SYMBOL(__main) // FIXME: Don't call it. +#endif + +#ifdef HAVE___ASHLDI3 + EXPLICIT_SYMBOL(__ashldi3) +#endif +#ifdef HAVE___ASHRDI3 + EXPLICIT_SYMBOL(__ashrdi3) +#endif +#ifdef HAVE___CMPDI2 // FIXME: unused + EXPLICIT_SYMBOL(__cmpdi2) +#endif +#ifdef HAVE___DIVDI3 + EXPLICIT_SYMBOL(__divdi3) +#endif +#ifdef HAVE___FIXDFDI + EXPLICIT_SYMBOL(__fixdfdi) +#endif +#ifdef HAVE___FIXSFDI + EXPLICIT_SYMBOL(__fixsfdi) +#endif +#ifdef HAVE___FIXUNSDFDI + EXPLICIT_SYMBOL(__fixunsdfdi) +#endif +#ifdef HAVE___FIXUNSSFDI + EXPLICIT_SYMBOL(__fixunssfdi) +#endif +#ifdef HAVE___FLOATDIDF + EXPLICIT_SYMBOL(__floatdidf) +#endif +#ifdef HAVE___FLOATDISF + EXPLICIT_SYMBOL(__floatdisf) +#endif +#ifdef HAVE___LSHRDI3 + EXPLICIT_SYMBOL(__lshrdi3) +#endif +#ifdef HAVE___MODDI3 + EXPLICIT_SYMBOL(__moddi3) +#endif +#ifdef HAVE___UDIVDI3 + EXPLICIT_SYMBOL(__udivdi3) +#endif +#ifdef HAVE___UMODDI3 + EXPLICIT_SYMBOL(__umoddi3) +#endif + +/* msvcrt */ +#if defined(_MSC_VER) + EXPLICIT_SYMBOL2(alloca, _alloca_probe); +#endif diff --git a/final/lib/Support/Windows/system_error.inc b/final/lib/Support/Windows/system_error.inc new file mode 100644 index 00000000000..37ec81dd363 --- /dev/null +++ b/final/lib/Support/Windows/system_error.inc @@ -0,0 +1,142 @@ +//===- llvm/Support/Win32/system_error.inc - Windows error_code --*- 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 the Windows specific implementation of the error_code +// and error_condition classes. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only generic Windows code that +//=== is guaranteed to work on *all* Windows variants. +//===----------------------------------------------------------------------===// + +#include +#include + +using namespace llvm; + +std::string +_system_error_category::message(int ev) const { + LPVOID lpMsgBuf = 0; + DWORD retval = ::FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + ev, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPSTR) &lpMsgBuf, + 0, + NULL); + if (retval == 0) { + ::LocalFree(lpMsgBuf); + return std::string("Unknown error"); + } + + std::string str( static_cast(lpMsgBuf) ); + ::LocalFree(lpMsgBuf); + + while (str.size() + && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r')) + str.erase( str.size()-1 ); + if (str.size() && str[str.size()-1] == '.') + str.erase( str.size()-1 ); + return str; +} + +// I'd rather not double the line count of the following. +#define MAP_ERR_TO_COND(x, y) case x: return make_error_condition(errc::y) + +error_condition +_system_error_category::default_error_condition(int ev) const { + switch (ev) { + MAP_ERR_TO_COND(0, success); + // Windows system -> posix_errno decode table ---------------------------// + // see WinError.h comments for descriptions of errors + MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied); + MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists); + MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device); + MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long); + MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied); + MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error); + MAP_ERR_TO_COND(ERROR_CANTREAD, io_error); + MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error); + MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied); + MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device); + MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty); + MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument); + MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device); + MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists); + MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device); + MAP_ERR_TO_COND(ERROR_HANDLE_EOF, value_too_large); + MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied); + MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device); + MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported); + MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument); + MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument); + MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available); + MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available); + MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument); + MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied); + MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory); + MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again); + MAP_ERR_TO_COND(ERROR_NOT_SAME_DEVICE, cross_device_link); + MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error); + MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy); + MAP_ERR_TO_COND(ERROR_OPERATION_ABORTED, operation_canceled); + MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory); + MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory); + MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error); + MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again); + MAP_ERR_TO_COND(ERROR_SEEK, io_error); + MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied); + MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open); + MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error); + MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied); + MAP_ERR_TO_COND(ERROR_SEM_TIMEOUT, timed_out); + MAP_ERR_TO_COND(WSAEACCES, permission_denied); + MAP_ERR_TO_COND(WSAEADDRINUSE, address_in_use); + MAP_ERR_TO_COND(WSAEADDRNOTAVAIL, address_not_available); + MAP_ERR_TO_COND(WSAEAFNOSUPPORT, address_family_not_supported); + MAP_ERR_TO_COND(WSAEALREADY, connection_already_in_progress); + MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor); + MAP_ERR_TO_COND(WSAECONNABORTED, connection_aborted); + MAP_ERR_TO_COND(WSAECONNREFUSED, connection_refused); + MAP_ERR_TO_COND(WSAECONNRESET, connection_reset); + MAP_ERR_TO_COND(WSAEDESTADDRREQ, destination_address_required); + MAP_ERR_TO_COND(WSAEFAULT, bad_address); + MAP_ERR_TO_COND(WSAEHOSTUNREACH, host_unreachable); + MAP_ERR_TO_COND(WSAEINPROGRESS, operation_in_progress); + MAP_ERR_TO_COND(WSAEINTR, interrupted); + MAP_ERR_TO_COND(WSAEINVAL, invalid_argument); + MAP_ERR_TO_COND(WSAEISCONN, already_connected); + MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open); + MAP_ERR_TO_COND(WSAEMSGSIZE, message_size); + MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long); + MAP_ERR_TO_COND(WSAENETDOWN, network_down); + MAP_ERR_TO_COND(WSAENETRESET, network_reset); + MAP_ERR_TO_COND(WSAENETUNREACH, network_unreachable); + MAP_ERR_TO_COND(WSAENOBUFS, no_buffer_space); + MAP_ERR_TO_COND(WSAENOPROTOOPT, no_protocol_option); + MAP_ERR_TO_COND(WSAENOTCONN, not_connected); + MAP_ERR_TO_COND(WSAENOTSOCK, not_a_socket); + MAP_ERR_TO_COND(WSAEOPNOTSUPP, operation_not_supported); + MAP_ERR_TO_COND(WSAEPROTONOSUPPORT, protocol_not_supported); + MAP_ERR_TO_COND(WSAEPROTOTYPE, wrong_protocol_type); + MAP_ERR_TO_COND(WSAETIMEDOUT, timed_out); + MAP_ERR_TO_COND(WSAEWOULDBLOCK, operation_would_block); + default: return error_condition(ev, system_category()); + } +} diff --git a/final/lib/Support/circular_raw_ostream.cpp b/final/lib/Support/circular_raw_ostream.cpp new file mode 100644 index 00000000000..ca0d30db388 --- /dev/null +++ b/final/lib/Support/circular_raw_ostream.cpp @@ -0,0 +1,45 @@ +//===- circular_raw_ostream.cpp - Implement circular_raw_ostream ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support for circular buffered streams. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/circular_raw_ostream.h" +#include +using namespace llvm; + +void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) { + if (BufferSize == 0) { + TheStream->write(Ptr, Size); + return; + } + + // Write into the buffer, wrapping if necessary. + while (Size != 0) { + unsigned Bytes = + std::min(unsigned(Size), unsigned(BufferSize - (Cur - BufferArray))); + memcpy(Cur, Ptr, Bytes); + Size -= Bytes; + Cur += Bytes; + if (Cur == BufferArray + BufferSize) { + // Reset the output pointer to the start of the buffer. + Cur = BufferArray; + Filled = true; + } + } +} + +void circular_raw_ostream::flushBufferWithBanner() { + if (BufferSize != 0) { + // Write out the buffer + TheStream->write(Banner, std::strlen(Banner)); + flushBuffer(); + } +} diff --git a/final/lib/Support/raw_os_ostream.cpp b/final/lib/Support/raw_os_ostream.cpp new file mode 100644 index 00000000000..44f2325d7f8 --- /dev/null +++ b/final/lib/Support/raw_os_ostream.cpp @@ -0,0 +1,30 @@ +//===--- raw_os_ostream.cpp - Implement the raw_os_ostream class ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support adapting raw_ostream to std::ostream. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_os_ostream.h" +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// raw_os_ostream +//===----------------------------------------------------------------------===// + +raw_os_ostream::~raw_os_ostream() { + flush(); +} + +void raw_os_ostream::write_impl(const char *Ptr, size_t Size) { + OS.write(Ptr, Size); +} + +uint64_t raw_os_ostream::current_pos() const { return OS.tellp(); } diff --git a/final/lib/Support/raw_ostream.cpp b/final/lib/Support/raw_ostream.cpp new file mode 100644 index 00000000000..5a71fa3d8ce --- /dev/null +++ b/final/lib/Support/raw_ostream.cpp @@ -0,0 +1,763 @@ +//===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements support for bulk buffered stream output. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Process.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +#include +#include + +#if defined(HAVE_UNISTD_H) +# include +#endif +#if defined(HAVE_FCNTL_H) +# include +#endif +#if defined(HAVE_SYS_UIO_H) && defined(HAVE_WRITEV) +# include +#endif + +#if defined(__CYGWIN__) +#include +#endif + +#if defined(_MSC_VER) +#include +#include +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif +#endif + +using namespace llvm; + +raw_ostream::~raw_ostream() { + // raw_ostream's subclasses should take care to flush the buffer + // in their destructors. + assert(OutBufCur == OutBufStart && + "raw_ostream destructor called with non-empty buffer!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; +} + +// An out of line virtual method to provide a home for the class vtable. +void raw_ostream::handle() {} + +size_t raw_ostream::preferred_buffer_size() const { + // BUFSIZ is intended to be a reasonable default. + return BUFSIZ; +} + +void raw_ostream::SetBuffered() { + // Ask the subclass to determine an appropriate buffer size. + if (size_t Size = preferred_buffer_size()) + SetBufferSize(Size); + else + // It may return 0, meaning this stream should be unbuffered. + SetUnbuffered(); +} + +void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, + BufferKind Mode) { + assert(((Mode == Unbuffered && BufferStart == 0 && Size == 0) || + (Mode != Unbuffered && BufferStart && Size)) && + "stream must be unbuffered or have at least one byte"); + // Make sure the current buffer is free of content (we can't flush here; the + // child buffer management logic will be in write_impl). + assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); + + if (BufferMode == InternalBuffer) + delete [] OutBufStart; + OutBufStart = BufferStart; + OutBufEnd = OutBufStart+Size; + OutBufCur = OutBufStart; + BufferMode = Mode; + + assert(OutBufStart <= OutBufEnd && "Invalid size!"); +} + +raw_ostream &raw_ostream::operator<<(unsigned long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long N) { + if (N < 0) { + *this << '-'; + N = -N; + } + + return this->operator<<(static_cast(N)); +} + +raw_ostream &raw_ostream::operator<<(unsigned long long N) { + // Output using 32-bit div/mod when possible. + if (N == static_cast(N)) + return this->operator<<(static_cast(N)); + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + *--CurPtr = '0' + char(N % 10); + N /= 10; + } + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::operator<<(long long N) { + if (N < 0) { + *this << '-'; + // Avoid undefined behavior on INT64_MIN with a cast. + N = -(unsigned long long)N; + } + + return this->operator<<(static_cast(N)); +} + +raw_ostream &raw_ostream::write_hex(unsigned long long N) { + // Zero is a special case. + if (N == 0) + return *this << '0'; + + char NumberBuffer[20]; + char *EndPtr = NumberBuffer+sizeof(NumberBuffer); + char *CurPtr = EndPtr; + + while (N) { + uintptr_t x = N % 16; + *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10); + N /= 16; + } + + return write(CurPtr, EndPtr-CurPtr); +} + +raw_ostream &raw_ostream::write_escaped(StringRef Str, + bool UseHexEscapes) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + unsigned char c = Str[i]; + + switch (c) { + case '\\': + *this << '\\' << '\\'; + break; + case '\t': + *this << '\\' << 't'; + break; + case '\n': + *this << '\\' << 'n'; + break; + case '"': + *this << '\\' << '"'; + break; + default: + if (std::isprint(c)) { + *this << c; + break; + } + + // Write out the escaped representation. + if (UseHexEscapes) { + *this << '\\' << 'x'; + *this << hexdigit((c >> 4 & 0xF)); + *this << hexdigit((c >> 0) & 0xF); + } else { + // Always use a full 3-character octal escape. + *this << '\\'; + *this << char('0' + ((c >> 6) & 7)); + *this << char('0' + ((c >> 3) & 7)); + *this << char('0' + ((c >> 0) & 7)); + } + } + } + + return *this; +} + +raw_ostream &raw_ostream::operator<<(const void *P) { + *this << '0' << 'x'; + + return write_hex((uintptr_t) P); +} + +raw_ostream &raw_ostream::operator<<(double N) { +#ifdef _WIN32 + // On MSVCRT and compatible, output of %e is incompatible to Posix + // by default. Number of exponent digits should be at least 2. "%+03d" + // FIXME: Implement our formatter to here or Support/Format.h! + int fpcl = _fpclass(N); + + // negative zero + if (fpcl == _FPCLASS_NZ) + return *this << "-0.000000e+00"; + + char buf[16]; + unsigned len; + len = snprintf(buf, sizeof(buf), "%e", N); + if (len <= sizeof(buf) - 2) { + if (len >= 5 && buf[len - 5] == 'e' && buf[len - 3] == '0') { + int cs = buf[len - 4]; + if (cs == '+' || cs == '-') { + int c1 = buf[len - 2]; + int c0 = buf[len - 1]; + if (isdigit(c1) && isdigit(c0)) { + // Trim leading '0': "...e+012" -> "...e+12\0" + buf[len - 3] = c1; + buf[len - 2] = c0; + buf[--len] = 0; + } + } + } + return this->operator<<(buf); + } +#endif + return this->operator<<(format("%e", N)); +} + + + +void raw_ostream::flush_nonempty() { + assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); + size_t Length = OutBufCur - OutBufStart; + OutBufCur = OutBufStart; + write_impl(OutBufStart, Length); +} + +raw_ostream &raw_ostream::write(unsigned char C) { + // Group exceptional cases into a single branch. + if (BUILTIN_EXPECT(OutBufCur >= OutBufEnd, false)) { + if (BUILTIN_EXPECT(!OutBufStart, false)) { + if (BufferMode == Unbuffered) { + write_impl(reinterpret_cast(&C), 1); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(C); + } + + flush_nonempty(); + } + + *OutBufCur++ = C; + return *this; +} + +raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { + // Group exceptional cases into a single branch. + if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) { + if (BUILTIN_EXPECT(!OutBufStart, false)) { + if (BufferMode == Unbuffered) { + write_impl(Ptr, Size); + return *this; + } + // Set up a buffer and start over. + SetBuffered(); + return write(Ptr, Size); + } + + size_t NumBytes = OutBufEnd - OutBufCur; + + // If the buffer is empty at this point we have a string that is larger + // than the buffer. Directly write the chunk that is a multiple of the + // preferred buffer size and put the remainder in the buffer. + if (BUILTIN_EXPECT(OutBufCur == OutBufStart, false)) { + size_t BytesToWrite = Size - (Size % NumBytes); + write_impl(Ptr, BytesToWrite); + copy_to_buffer(Ptr + BytesToWrite, Size - BytesToWrite); + return *this; + } + + // We don't have enough space in the buffer to fit the string in. Insert as + // much as possible, flush and start over with the remainder. + copy_to_buffer(Ptr, NumBytes); + flush_nonempty(); + return write(Ptr + NumBytes, Size - NumBytes); + } + + copy_to_buffer(Ptr, Size); + + return *this; +} + +void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { + assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); + + // Handle short strings specially, memcpy isn't very good at very short + // strings. + switch (Size) { + case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH + case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH + case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH + case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH + case 0: break; + default: + memcpy(OutBufCur, Ptr, Size); + break; + } + + OutBufCur += Size; +} + +// Formatted output. +raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { + // If we have more than a few bytes left in our output buffer, try + // formatting directly onto its end. + size_t NextBufferSize = 127; + size_t BufferBytesLeft = OutBufEnd - OutBufCur; + if (BufferBytesLeft > 3) { + size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); + + // Common case is that we have plenty of space. + if (BytesUsed <= BufferBytesLeft) { + OutBufCur += BytesUsed; + return *this; + } + + // Otherwise, we overflowed and the return value tells us the size to try + // again with. + NextBufferSize = BytesUsed; + } + + // If we got here, we didn't have enough space in the output buffer for the + // string. Try printing into a SmallVector that is resized to have enough + // space. Iterate until we win. + SmallVector V; + + while (1) { + V.resize(NextBufferSize); + + // Try formatting into the SmallVector. + size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); + + // If BytesUsed fit into the vector, we win. + if (BytesUsed <= NextBufferSize) + return write(V.data(), BytesUsed); + + // Otherwise, try again with a new size. + assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); + NextBufferSize = BytesUsed; + } +} + +/// indent - Insert 'NumSpaces' spaces. +raw_ostream &raw_ostream::indent(unsigned NumSpaces) { + static const char Spaces[] = " " + " " + " "; + + // Usually the indentation is small, handle it with a fastpath. + if (NumSpaces < array_lengthof(Spaces)) + return write(Spaces, NumSpaces); + + while (NumSpaces) { + unsigned NumToWrite = std::min(NumSpaces, + (unsigned)array_lengthof(Spaces)-1); + write(Spaces, NumToWrite); + NumSpaces -= NumToWrite; + } + return *this; +} + + +//===----------------------------------------------------------------------===// +// Formatted Output +//===----------------------------------------------------------------------===// + +// Out of line virtual method. +void format_object_base::home() { +} + +//===----------------------------------------------------------------------===// +// raw_fd_ostream +//===----------------------------------------------------------------------===// + +/// raw_fd_ostream - Open the specified file for writing. If an error +/// occurs, information about the error is put into ErrorInfo, and the +/// stream should be immediately destroyed; the string will be empty +/// if no error occurred. +raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, + unsigned Flags) + : Error(false), UseAtomicWrites(false), pos(0) +{ + assert(Filename != 0 && "Filename is null"); + // Verify that we don't have both "append" and "excl". + assert((!(Flags & F_Excl) || !(Flags & F_Append)) && + "Cannot specify both 'excl' and 'append' file creation flags!"); + + ErrorInfo.clear(); + + // Handle "-" as stdout. Note that when we do this, we consider ourself + // the owner of stdout. This means that we can do things like close the + // file descriptor when we're done and set the "binary" flag globally. + if (Filename[0] == '-' && Filename[1] == 0) { + FD = STDOUT_FILENO; + // If user requested binary then put stdout into binary mode if + // possible. + if (Flags & F_Binary) + sys::Program::ChangeStdoutToBinary(); + // Close stdout when we're done, to detect any output errors. + ShouldClose = true; + return; + } + + int OpenFlags = O_WRONLY|O_CREAT; +#ifdef O_BINARY + if (Flags & F_Binary) + OpenFlags |= O_BINARY; +#endif + + if (Flags & F_Append) + OpenFlags |= O_APPEND; + else + OpenFlags |= O_TRUNC; + if (Flags & F_Excl) + OpenFlags |= O_EXCL; + + while ((FD = open(Filename, OpenFlags, 0664)) < 0) { + if (errno != EINTR) { + ErrorInfo = "Error opening output file '" + std::string(Filename) + "'"; + ShouldClose = false; + return; + } + } + + // Ok, we successfully opened the file, so it'll need to be closed. + ShouldClose = true; +} + +/// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If +/// ShouldClose is true, this closes the file when the stream is destroyed. +raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered) + : raw_ostream(unbuffered), FD(fd), + ShouldClose(shouldClose), Error(false), UseAtomicWrites(false) { +#ifdef O_BINARY + // Setting STDOUT and STDERR to binary mode is necessary in Win32 + // to avoid undesirable linefeed conversion. + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) + setmode(fd, O_BINARY); +#endif + + // Get the starting position. + off_t loc = ::lseek(FD, 0, SEEK_CUR); + if (loc == (off_t)-1) + pos = 0; + else + pos = static_cast(loc); +} + +raw_fd_ostream::~raw_fd_ostream() { + if (FD >= 0) { + flush(); + if (ShouldClose) + while (::close(FD) != 0) + if (errno != EINTR) { + error_detected(); + break; + } + } + +#ifdef __MINGW32__ + // On mingw, global dtors should not call exit(). + // report_fatal_error() invokes exit(). We know report_fatal_error() + // might not write messages to stderr when any errors were detected + // on FD == 2. + if (FD == 2) return; +#endif + + // If there are any pending errors, report them now. Clients wishing + // to avoid report_fatal_error calls should check for errors with + // has_error() and clear the error flag with clear_error() before + // destructing raw_ostream objects which may have errors. + if (has_error()) + report_fatal_error("IO failure on output stream."); +} + + +void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { + assert(FD >= 0 && "File already closed."); + pos += Size; + + do { + ssize_t ret; + + // Check whether we should attempt to use atomic writes. + if (BUILTIN_EXPECT(!UseAtomicWrites, true)) { + ret = ::write(FD, Ptr, Size); + } else { + // Use ::writev() where available. +#if defined(HAVE_WRITEV) + struct iovec IOV = { (void*) Ptr, Size }; + ret = ::writev(FD, &IOV, 1); +#else + ret = ::write(FD, Ptr, Size); +#endif + } + + if (ret < 0) { + // If it's a recoverable error, swallow it and retry the write. + // + // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since + // raw_ostream isn't designed to do non-blocking I/O. However, some + // programs, such as old versions of bjam, have mistakenly used + // O_NONBLOCK. For compatibility, emulate blocking semantics by + // spinning until the write succeeds. If you don't want spinning, + // don't use O_NONBLOCK file descriptors with raw_ostream. + if (errno == EINTR || errno == EAGAIN +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ) + continue; + + // Otherwise it's a non-recoverable error. Note it and quit. + error_detected(); + break; + } + + // The write may have written some or all of the data. Update the + // size and buffer pointer to reflect the remainder that needs + // to be written. If there are no bytes left, we're done. + Ptr += ret; + Size -= ret; + } while (Size > 0); +} + +void raw_fd_ostream::close() { + assert(ShouldClose); + ShouldClose = false; + flush(); + while (::close(FD) != 0) + if (errno != EINTR) { + error_detected(); + break; + } + FD = -1; +} + +uint64_t raw_fd_ostream::seek(uint64_t off) { + flush(); + pos = ::lseek(FD, off, SEEK_SET); + if (pos != off) + error_detected(); + return pos; +} + +size_t raw_fd_ostream::preferred_buffer_size() const { +#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix) + // Windows and Minix have no st_blksize. + assert(FD >= 0 && "File not yet open!"); + struct stat statbuf; + if (fstat(FD, &statbuf) != 0) + return 0; + + // If this is a terminal, don't use buffering. Line buffering + // would be a more traditional thing to do, but it's not worth + // the complexity. + if (S_ISCHR(statbuf.st_mode) && isatty(FD)) + return 0; + // Return the preferred block size. + return statbuf.st_blksize; +#else + return raw_ostream::preferred_buffer_size(); +#endif +} + +raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, + bool bg) { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = + (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) + : sys::Process::OutputColor(colors, bold, bg); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +raw_ostream &raw_fd_ostream::resetColor() { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = sys::Process::ResetColor(); + if (colorcode) { + size_t len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +bool raw_fd_ostream::is_displayed() const { + return sys::Process::FileDescriptorIsDisplayed(FD); +} + +//===----------------------------------------------------------------------===// +// outs(), errs(), nulls() +//===----------------------------------------------------------------------===// + +/// outs() - This returns a reference to a raw_ostream for standard output. +/// Use it like: outs() << "foo" << "bar"; +raw_ostream &llvm::outs() { + // Set buffer settings to model stdout behavior. + // Delete the file descriptor when the program exists, forcing error + // detection. If you don't want this behavior, don't use outs(). + static raw_fd_ostream S(STDOUT_FILENO, true); + return S; +} + +/// errs() - This returns a reference to a raw_ostream for standard error. +/// Use it like: errs() << "foo" << "bar"; +raw_ostream &llvm::errs() { + // Set standard error to be unbuffered by default. + static raw_fd_ostream S(STDERR_FILENO, false, true); + return S; +} + +/// nulls() - This returns a reference to a raw_ostream which discards output. +raw_ostream &llvm::nulls() { + static raw_null_ostream S; + return S; +} + + +//===----------------------------------------------------------------------===// +// raw_string_ostream +//===----------------------------------------------------------------------===// + +raw_string_ostream::~raw_string_ostream() { + flush(); +} + +void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { + OS.append(Ptr, Size); +} + +//===----------------------------------------------------------------------===// +// raw_svector_ostream +//===----------------------------------------------------------------------===// + +// The raw_svector_ostream implementation uses the SmallVector itself as the +// buffer for the raw_ostream. We guarantee that the raw_ostream buffer is +// always pointing past the end of the vector, but within the vector +// capacity. This allows raw_ostream to write directly into the correct place, +// and we only need to set the vector size when the data is flushed. + +raw_svector_ostream::raw_svector_ostream(SmallVectorImpl &O) : OS(O) { + // Set up the initial external buffer. We make sure that the buffer has at + // least 128 bytes free; raw_ostream itself only requires 64, but we want to + // make sure that we don't grow the buffer unnecessarily on destruction (when + // the data is flushed). See the FIXME below. + OS.reserve(OS.size() + 128); + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + +raw_svector_ostream::~raw_svector_ostream() { + // FIXME: Prevent resizing during this flush(). + flush(); +} + +/// resync - This is called when the SmallVector we're appending to is changed +/// outside of the raw_svector_ostream's control. It is only safe to do this +/// if the raw_svector_ostream has previously been flushed. +void raw_svector_ostream::resync() { + assert(GetNumBytesInBuffer() == 0 && "Didn't flush before mutating vector"); + + if (OS.capacity() - OS.size() < 64) + OS.reserve(OS.capacity() * 2); + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + +void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { + // If we're writing bytes from the end of the buffer into the smallvector, we + // don't need to copy the bytes, just commit the bytes because they are + // already in the right place. + if (Ptr == OS.end()) { + assert(OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!"); + OS.set_size(OS.size() + Size); + } else { + assert(GetNumBytesInBuffer() == 0 && + "Should be writing from buffer if some bytes in it"); + // Otherwise, do copy the bytes. + OS.append(Ptr, Ptr+Size); + } + + // Grow the vector if necessary. + if (OS.capacity() - OS.size() < 64) + OS.reserve(OS.capacity() * 2); + + // Update the buffer position. + SetBuffer(OS.end(), OS.capacity() - OS.size()); +} + +uint64_t raw_svector_ostream::current_pos() const { + return OS.size(); +} + +StringRef raw_svector_ostream::str() { + flush(); + return StringRef(OS.begin(), OS.size()); +} + +//===----------------------------------------------------------------------===// +// raw_null_ostream +//===----------------------------------------------------------------------===// + +raw_null_ostream::~raw_null_ostream() { +#ifndef NDEBUG + // ~raw_ostream asserts that the buffer is empty. This isn't necessary + // with raw_null_ostream, but it's better to have raw_null_ostream follow + // the rules than to change the rules just for raw_null_ostream. + flush(); +#endif +} + +void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { +} + +uint64_t raw_null_ostream::current_pos() const { + return 0; +} diff --git a/final/lib/Support/regcclass.h b/final/lib/Support/regcclass.h new file mode 100644 index 00000000000..2cea3e4e540 --- /dev/null +++ b/final/lib/Support/regcclass.h @@ -0,0 +1,70 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)cclass.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-class table */ +static struct cclass { + const char *name; + const char *chars; + const char *multis; +} cclasses[] = { + { "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789", ""} , + { "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + ""} , + { "blank", " \t", ""} , + { "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ +\25\26\27\30\31\32\33\34\35\36\37\177", ""} , + { "digit", "0123456789", ""} , + { "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""} , + { "lower", "abcdefghijklmnopqrstuvwxyz", + ""} , + { "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ +0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", + ""} , + { "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", + ""} , + { "space", "\t\n\v\f\r ", ""} , + { "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + ""} , + { "xdigit", "0123456789ABCDEFabcdef", + ""} , + { NULL, 0, "" } +}; diff --git a/final/lib/Support/regcname.h b/final/lib/Support/regcname.h new file mode 100644 index 00000000000..3c0bb248ffa --- /dev/null +++ b/final/lib/Support/regcname.h @@ -0,0 +1,139 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)cname.h 8.3 (Berkeley) 3/20/94 + */ + +/* character-name table */ +static struct cname { + const char *name; + char code; +} cnames[] = { + { "NUL", '\0' }, + { "SOH", '\001' }, + { "STX", '\002' }, + { "ETX", '\003' }, + { "EOT", '\004' }, + { "ENQ", '\005' }, + { "ACK", '\006' }, + { "BEL", '\007' }, + { "alert", '\007' }, + { "BS", '\010' }, + { "backspace", '\b' }, + { "HT", '\011' }, + { "tab", '\t' }, + { "LF", '\012' }, + { "newline", '\n' }, + { "VT", '\013' }, + { "vertical-tab", '\v' }, + { "FF", '\014' }, + { "form-feed", '\f' }, + { "CR", '\015' }, + { "carriage-return", '\r' }, + { "SO", '\016' }, + { "SI", '\017' }, + { "DLE", '\020' }, + { "DC1", '\021' }, + { "DC2", '\022' }, + { "DC3", '\023' }, + { "DC4", '\024' }, + { "NAK", '\025' }, + { "SYN", '\026' }, + { "ETB", '\027' }, + { "CAN", '\030' }, + { "EM", '\031' }, + { "SUB", '\032' }, + { "ESC", '\033' }, + { "IS4", '\034' }, + { "FS", '\034' }, + { "IS3", '\035' }, + { "GS", '\035' }, + { "IS2", '\036' }, + { "RS", '\036' }, + { "IS1", '\037' }, + { "US", '\037' }, + { "space", ' ' }, + { "exclamation-mark", '!' }, + { "quotation-mark", '"' }, + { "number-sign", '#' }, + { "dollar-sign", '$' }, + { "percent-sign", '%' }, + { "ampersand", '&' }, + { "apostrophe", '\'' }, + { "left-parenthesis", '(' }, + { "right-parenthesis", ')' }, + { "asterisk", '*' }, + { "plus-sign", '+' }, + { "comma", ',' }, + { "hyphen", '-' }, + { "hyphen-minus", '-' }, + { "period", '.' }, + { "full-stop", '.' }, + { "slash", '/' }, + { "solidus", '/' }, + { "zero", '0' }, + { "one", '1' }, + { "two", '2' }, + { "three", '3' }, + { "four", '4' }, + { "five", '5' }, + { "six", '6' }, + { "seven", '7' }, + { "eight", '8' }, + { "nine", '9' }, + { "colon", ':' }, + { "semicolon", ';' }, + { "less-than-sign", '<' }, + { "equals-sign", '=' }, + { "greater-than-sign", '>' }, + { "question-mark", '?' }, + { "commercial-at", '@' }, + { "left-square-bracket", '[' }, + { "backslash", '\\' }, + { "reverse-solidus", '\\' }, + { "right-square-bracket", ']' }, + { "circumflex", '^' }, + { "circumflex-accent", '^' }, + { "underscore", '_' }, + { "low-line", '_' }, + { "grave-accent", '`' }, + { "left-brace", '{' }, + { "left-curly-bracket", '{' }, + { "vertical-line", '|' }, + { "right-brace", '}' }, + { "right-curly-bracket", '}' }, + { "tilde", '~' }, + { "DEL", '\177' }, + { NULL, 0 } +}; diff --git a/final/lib/Support/regcomp.c b/final/lib/Support/regcomp.c new file mode 100644 index 00000000000..46c91a9c497 --- /dev/null +++ b/final/lib/Support/regcomp.c @@ -0,0 +1,1525 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regcomp.c 8.5 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +#include "regcclass.h" +#include "regcname.h" + +/* + * parse structure, passed up and down to avoid global variables and + * other clumsinesses + */ +struct parse { + char *next; /* next character in RE */ + char *end; /* end of string (-> NUL normally) */ + int error; /* has an error been seen? */ + sop *strip; /* malloced strip */ + sopno ssize; /* malloced strip size (allocated) */ + sopno slen; /* malloced strip length (used) */ + int ncsalloc; /* number of csets allocated */ + struct re_guts *g; +# define NPAREN 10 /* we need to remember () 1-9 for back refs */ + sopno pbegin[NPAREN]; /* -> ( ([0] unused) */ + sopno pend[NPAREN]; /* -> ) ([0] unused) */ +}; + +static void p_ere(struct parse *, int); +static void p_ere_exp(struct parse *); +static void p_str(struct parse *); +static void p_bre(struct parse *, int, int); +static int p_simp_re(struct parse *, int); +static int p_count(struct parse *); +static void p_bracket(struct parse *); +static void p_b_term(struct parse *, cset *); +static void p_b_cclass(struct parse *, cset *); +static void p_b_eclass(struct parse *, cset *); +static char p_b_symbol(struct parse *); +static char p_b_coll_elem(struct parse *, int); +static char othercase(int); +static void bothcases(struct parse *, int); +static void ordinary(struct parse *, int); +static void nonnewline(struct parse *); +static void repeat(struct parse *, sopno, int, int); +static int seterr(struct parse *, int); +static cset *allocset(struct parse *); +static void freeset(struct parse *, cset *); +static int freezeset(struct parse *, cset *); +static int firstch(struct parse *, cset *); +static int nch(struct parse *, cset *); +static void mcadd(struct parse *, cset *, const char *); +static void mcinvert(struct parse *, cset *); +static void mccase(struct parse *, cset *); +static int isinsets(struct re_guts *, int); +static int samesets(struct re_guts *, int, int); +static void categorize(struct parse *, struct re_guts *); +static sopno dupl(struct parse *, sopno, sopno); +static void doemit(struct parse *, sop, size_t); +static void doinsert(struct parse *, sop, size_t, sopno); +static void dofwd(struct parse *, sopno, sop); +static void enlarge(struct parse *, sopno); +static void stripsnug(struct parse *, struct re_guts *); +static void findmust(struct parse *, struct re_guts *); +static sopno pluscount(struct parse *, struct re_guts *); + +static char nuls[10]; /* place to point scanner in event of error */ + +/* + * macros for use with parse structure + * BEWARE: these know that the parse structure is named `p' !!! + */ +#define PEEK() (*p->next) +#define PEEK2() (*(p->next+1)) +#define MORE() (p->next < p->end) +#define MORE2() (p->next+1 < p->end) +#define SEE(c) (MORE() && PEEK() == (c)) +#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b)) +#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0) +#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0) +#define NEXT() (p->next++) +#define NEXT2() (p->next += 2) +#define NEXTn(n) (p->next += (n)) +#define GETNEXT() (*p->next++) +#define SETERROR(e) seterr(p, (e)) +#define REQUIRE(co, e) (void)((co) || SETERROR(e)) +#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e)) +#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e)) +#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e)) +#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd)) +#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos) +#define AHEAD(pos) dofwd(p, pos, HERE()-(pos)) +#define ASTERN(sop, pos) EMIT(sop, HERE()-pos) +#define HERE() (p->slen) +#define THERE() (p->slen - 1) +#define THERETHERE() (p->slen - 2) +#define DROP(n) (p->slen -= (n)) + +#ifdef _POSIX2_RE_DUP_MAX +#define DUPMAX _POSIX2_RE_DUP_MAX +#else +#define DUPMAX 255 +#endif +#define INFINITY (DUPMAX + 1) + +#ifndef NDEBUG +static int never = 0; /* for use in asserts; shuts lint up */ +#else +#define never 0 /* some s have bugs too */ +#endif + +/* + - llvm_regcomp - interface for parser and compilation + */ +int /* 0 success, otherwise REG_something */ +llvm_regcomp(llvm_regex_t *preg, const char *pattern, int cflags) +{ + struct parse pa; + struct re_guts *g; + struct parse *p = &pa; + int i; + size_t len; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&~REG_DUMP) +#endif + + cflags = GOODFLAGS(cflags); + if ((cflags®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_PEND) { + if (preg->re_endp < pattern) + return(REG_INVARG); + len = preg->re_endp - pattern; + } else + len = strlen((const char *)pattern); + + /* do the mallocs early so failure handling is easy */ + g = (struct re_guts *)malloc(sizeof(struct re_guts) + + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); + p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ + p->strip = (sop *)calloc(p->ssize, sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { + free((char *)g); + return(REG_ESPACE); + } + + /* set things up */ + p->g = g; + p->next = (char *)pattern; /* convenience; we do not modify it */ + p->end = p->next + len; + p->error = 0; + p->ncsalloc = 0; + for (i = 0; i < NPAREN; i++) { + p->pbegin[i] = 0; + p->pend[i] = 0; + } + g->csetsize = NC; + g->sets = NULL; + g->setbits = NULL; + g->ncsets = 0; + g->cflags = cflags; + g->iflags = 0; + g->nbol = 0; + g->neol = 0; + g->must = NULL; + g->mlen = 0; + g->nsub = 0; + g->ncategories = 1; /* category 0 is "everything else" */ + g->categories = &g->catspace[-(CHAR_MIN)]; + (void) memset((char *)g->catspace, 0, NC*sizeof(cat_t)); + g->backrefs = 0; + + /* do it */ + EMIT(OEND, 0); + g->firststate = THERE(); + if (cflags®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_NOSPEC) + p_str(p); + else + p_bre(p, OUT, OUT); + EMIT(OEND, 0); + g->laststate = THERE(); + + /* tidy up loose ends and fill things in */ + categorize(p, g); + stripsnug(p, g); + findmust(p, g); + g->nplus = pluscount(p, g); + g->magic = MAGIC2; + preg->re_nsub = g->nsub; + preg->re_g = g; + preg->re_magic = MAGIC1; +#ifndef REDEBUG + /* not debugging, so can't rely on the assert() in llvm_regexec() */ + if (g->iflags®EX_BAD) + SETERROR(REG_ASSERT); +#endif + + /* win or lose, we're done */ + if (p->error != 0) /* lose */ + llvm_regfree(preg); + return(p->error); +} + +/* + - p_ere - ERE parser top level, concatenation and alternation + */ +static void +p_ere(struct parse *p, int stop) /* character this ERE should end at */ +{ + char c; + sopno prevback = 0; + sopno prevfwd = 0; + sopno conc; + int first = 1; /* is this the first alternative? */ + + for (;;) { + /* do a bunch of concatenated expressions */ + conc = HERE(); + while (MORE() && (c = PEEK()) != '|' && c != stop) + p_ere_exp(p); + REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */ + + if (!EAT('|')) + break; /* NOTE BREAK OUT */ + + if (first) { + INSERT(OCH_, conc); /* offset is wrong */ + prevfwd = conc; + prevback = conc; + first = 0; + } + ASTERN(OOR1, prevback); + prevback = THERE(); + AHEAD(prevfwd); /* fix previous offset */ + prevfwd = HERE(); + EMIT(OOR2, 0); /* offset is very wrong */ + } + + if (!first) { /* tail-end fixups */ + AHEAD(prevfwd); + ASTERN(O_CH, prevback); + } + + assert(!MORE() || SEE(stop)); +} + +/* + - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op + */ +static void +p_ere_exp(struct parse *p) +{ + char c; + sopno pos; + int count; + int count2; + sopno subno; + int wascaret = 0; + + assert(MORE()); /* caller should have ensured this */ + c = GETNEXT(); + + pos = HERE(); + switch (c) { + case '(': + REQUIRE(MORE(), REG_EPAREN); + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + if (!SEE(')')) + p_ere(p, ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + MUSTEAT(')', REG_EPAREN); + break; +#ifndef POSIX_MISTAKE + case ')': /* happens only if no current unmatched ( */ + /* + * You may ask, why the ifndef? Because I didn't notice + * this until slightly too late for 1003.2, and none of the + * other 1003.2 regular-expression reviewers noticed it at + * all. So an unmatched ) is legal POSIX, at least until + * we can get it fixed. + */ + SETERROR(REG_EPAREN); + break; +#endif + case '^': + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + wascaret = 1; + break; + case '$': + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + break; + case '|': + SETERROR(REG_EMPTY); + break; + case '*': + case '+': + case '?': + SETERROR(REG_BADRPT); + break; + case '.': + if (p->g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case '\\': + REQUIRE(MORE(), REG_EESCAPE); + c = GETNEXT(); + ordinary(p, c); + break; + case '{': /* okay as ordinary except if digit follows */ + REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, c); + break; + } + + if (!MORE()) + return; + c = PEEK(); + /* we call { a repetition if followed by a digit */ + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit((uch)PEEK2())) )) + return; /* no repetition, we're done */ + NEXT(); + + REQUIRE(!wascaret, REG_BADRPT); + switch (c) { + case '*': /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + break; + case '+': + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + break; + case '?': + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, pos); /* offset slightly wrong */ + ASTERN(OOR1, pos); /* this one's right */ + AHEAD(pos); /* fix the OCH_ */ + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + break; + case '{': + count = p_count(p); + if (EAT(',')) { + if (isdigit((uch)PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EAT('}')) { /* error heuristics */ + while (MORE() && PEEK() != '}') + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + break; + } + + if (!MORE()) + return; + c = PEEK(); + if (!( c == '*' || c == '+' || c == '?' || + (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) ) + return; + SETERROR(REG_BADRPT); +} + +/* + - p_str - string (no metacharacters) "parser" + */ +static void +p_str(struct parse *p) +{ + REQUIRE(MORE(), REG_EMPTY); + while (MORE()) + ordinary(p, GETNEXT()); +} + +/* + - p_bre - BRE parser top level, anchoring and concatenation + * Giving end1 as OUT essentially eliminates the end1/end2 check. + * + * This implementation is a bit of a kludge, in that a trailing $ is first + * taken as an ordinary character and then revised to be an anchor. The + * only undesirable side effect is that '$' gets included as a character + * category in such cases. This is fairly harmless; not worth fixing. + * The amount of lookahead needed to avoid this kludge is excessive. + */ +static void +p_bre(struct parse *p, + int end1, /* first terminating character */ + int end2) /* second terminating character */ +{ + sopno start = HERE(); + int first = 1; /* first subexpression? */ + int wasdollar = 0; + + if (EAT('^')) { + EMIT(OBOL, 0); + p->g->iflags |= USEBOL; + p->g->nbol++; + } + while (MORE() && !SEETWO(end1, end2)) { + wasdollar = p_simp_re(p, first); + first = 0; + } + if (wasdollar) { /* oops, that was a trailing anchor */ + DROP(1); + EMIT(OEOL, 0); + p->g->iflags |= USEEOL; + p->g->neol++; + } + + REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */ +} + +/* + - p_simp_re - parse a simple RE, an atom possibly followed by a repetition + */ +static int /* was the simple RE an unbackslashed $? */ +p_simp_re(struct parse *p, + int starordinary) /* is a leading * an ordinary character? */ +{ + int c; + int count; + int count2; + sopno pos; + int i; + sopno subno; +# define BACKSL (1<g->cflags®_NEWLINE) + nonnewline(p); + else + EMIT(OANY, 0); + break; + case '[': + p_bracket(p); + break; + case BACKSL|'{': + SETERROR(REG_BADRPT); + break; + case BACKSL|'(': + p->g->nsub++; + subno = p->g->nsub; + if (subno < NPAREN) + p->pbegin[subno] = HERE(); + EMIT(OLPAREN, subno); + /* the MORE here is an error heuristic */ + if (MORE() && !SEETWO('\\', ')')) + p_bre(p, '\\', ')'); + if (subno < NPAREN) { + p->pend[subno] = HERE(); + assert(p->pend[subno] != 0); + } + EMIT(ORPAREN, subno); + REQUIRE(EATTWO('\\', ')'), REG_EPAREN); + break; + case BACKSL|')': /* should not get here -- must be user */ + case BACKSL|'}': + SETERROR(REG_EPAREN); + break; + case BACKSL|'1': + case BACKSL|'2': + case BACKSL|'3': + case BACKSL|'4': + case BACKSL|'5': + case BACKSL|'6': + case BACKSL|'7': + case BACKSL|'8': + case BACKSL|'9': + i = (c&~BACKSL) - '0'; + assert(i < NPAREN); + if (p->pend[i] != 0) { + assert(i <= p->g->nsub); + EMIT(OBACK_, i); + assert(p->pbegin[i] != 0); + assert(OP(p->strip[p->pbegin[i]]) == OLPAREN); + assert(OP(p->strip[p->pend[i]]) == ORPAREN); + (void) dupl(p, p->pbegin[i]+1, p->pend[i]); + EMIT(O_BACK, i); + } else + SETERROR(REG_ESUBREG); + p->g->backrefs = 1; + break; + case '*': + REQUIRE(starordinary, REG_BADRPT); + /* FALLTHROUGH */ + default: + ordinary(p, (char)c); + break; + } + + if (EAT('*')) { /* implemented as +? */ + /* this case does not require the (y|) trick, noKLUDGE */ + INSERT(OPLUS_, pos); + ASTERN(O_PLUS, pos); + INSERT(OQUEST_, pos); + ASTERN(O_QUEST, pos); + } else if (EATTWO('\\', '{')) { + count = p_count(p); + if (EAT(',')) { + if (MORE() && isdigit((uch)PEEK())) { + count2 = p_count(p); + REQUIRE(count <= count2, REG_BADBR); + } else /* single number with comma */ + count2 = INFINITY; + } else /* just a single number */ + count2 = count; + repeat(p, pos, count, count2); + if (!EATTWO('\\', '}')) { /* error heuristics */ + while (MORE() && !SEETWO('\\', '}')) + NEXT(); + REQUIRE(MORE(), REG_EBRACE); + SETERROR(REG_BADBR); + } + } else if (c == '$') /* $ (but not \$) ends it */ + return(1); + + return(0); +} + +/* + - p_count - parse a repetition count + */ +static int /* the value */ +p_count(struct parse *p) +{ + int count = 0; + int ndigits = 0; + + while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) { + count = count*10 + (GETNEXT() - '0'); + ndigits++; + } + + REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR); + return(count); +} + +/* + - p_bracket - parse a bracketed character list + * + * Note a significant property of this code: if the allocset() did SETERROR, + * no set operations are done. + */ +static void +p_bracket(struct parse *p) +{ + cset *cs; + int invert = 0; + + /* Dept of Truly Sickening Special-Case Kludges */ + if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) { + EMIT(OBOW, 0); + NEXTn(6); + return; + } + if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) { + EMIT(OEOW, 0); + NEXTn(6); + return; + } + + if ((cs = allocset(p)) == NULL) { + /* allocset did set error status in p */ + return; + } + + if (EAT('^')) + invert++; /* make note to invert set at end */ + if (EAT(']')) + CHadd(cs, ']'); + else if (EAT('-')) + CHadd(cs, '-'); + while (MORE() && PEEK() != ']' && !SEETWO('-', ']')) + p_b_term(p, cs); + if (EAT('-')) + CHadd(cs, '-'); + MUSTEAT(']', REG_EBRACK); + + if (p->error != 0) { /* don't mess things up further */ + freeset(p, cs); + return; + } + + if (p->g->cflags®_ICASE) { + int i; + int ci; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i) && isalpha(i)) { + ci = othercase(i); + if (ci != i) + CHadd(cs, ci); + } + if (cs->multis != NULL) + mccase(p, cs); + } + if (invert) { + int i; + + for (i = p->g->csetsize - 1; i >= 0; i--) + if (CHIN(cs, i)) + CHsub(cs, i); + else + CHadd(cs, i); + if (p->g->cflags®_NEWLINE) + CHsub(cs, '\n'); + if (cs->multis != NULL) + mcinvert(p, cs); + } + + assert(cs->multis == NULL); /* xxx */ + + if (nch(p, cs) == 1) { /* optimize singleton sets */ + ordinary(p, firstch(p, cs)); + freeset(p, cs); + } else + EMIT(OANYOF, freezeset(p, cs)); +} + +/* + - p_b_term - parse one term of a bracketed character list + */ +static void +p_b_term(struct parse *p, cset *cs) +{ + char c; + char start, finish; + int i; + + /* classify what we've got */ + switch ((MORE()) ? PEEK() : '\0') { + case '[': + c = (MORE2()) ? PEEK2() : '\0'; + break; + case '-': + SETERROR(REG_ERANGE); + return; /* NOTE RETURN */ + break; + default: + c = '\0'; + break; + } + + switch (c) { + case ':': /* character class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECTYPE); + p_b_cclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO(':', ']'), REG_ECTYPE); + break; + case '=': /* equivalence class */ + NEXT2(); + REQUIRE(MORE(), REG_EBRACK); + c = PEEK(); + REQUIRE(c != '-' && c != ']', REG_ECOLLATE); + p_b_eclass(p, cs); + REQUIRE(MORE(), REG_EBRACK); + REQUIRE(EATTWO('=', ']'), REG_ECOLLATE); + break; + default: /* symbol, ordinary character, or range */ +/* xxx revision needed for multichar stuff */ + start = p_b_symbol(p); + if (SEE('-') && MORE2() && PEEK2() != ']') { + /* range */ + NEXT(); + if (EAT('-')) + finish = '-'; + else + finish = p_b_symbol(p); + } else + finish = start; +/* xxx what about signed chars here... */ + REQUIRE(start <= finish, REG_ERANGE); + for (i = start; i <= finish; i++) + CHadd(cs, i); + break; + } +} + +/* + - p_b_cclass - parse a character-class name and deal with it + */ +static void +p_b_cclass(struct parse *p, cset *cs) +{ + char *sp = p->next; + struct cclass *cp; + size_t len; + const char *u; + char c; + + while (MORE() && isalpha((uch)PEEK())) + NEXT(); + len = p->next - sp; + for (cp = cclasses; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + break; + if (cp->name == NULL) { + /* oops, didn't find it */ + SETERROR(REG_ECTYPE); + return; + } + + u = cp->chars; + while ((c = *u++) != '\0') + CHadd(cs, c); + for (u = cp->multis; *u != '\0'; u += strlen(u) + 1) + MCadd(p, cs, u); +} + +/* + - p_b_eclass - parse an equivalence-class name and deal with it + * + * This implementation is incomplete. xxx + */ +static void +p_b_eclass(struct parse *p, cset *cs) +{ + char c; + + c = p_b_coll_elem(p, '='); + CHadd(cs, c); +} + +/* + - p_b_symbol - parse a character or [..]ed multicharacter collating symbol + */ +static char /* value of symbol */ +p_b_symbol(struct parse *p) +{ + char value; + + REQUIRE(MORE(), REG_EBRACK); + if (!EATTWO('[', '.')) + return(GETNEXT()); + + /* collating symbol */ + value = p_b_coll_elem(p, '.'); + REQUIRE(EATTWO('.', ']'), REG_ECOLLATE); + return(value); +} + +/* + - p_b_coll_elem - parse a collating-element name and look it up + */ +static char /* value of collating element */ +p_b_coll_elem(struct parse *p, + int endc) /* name ended by endc,']' */ +{ + char *sp = p->next; + struct cname *cp; + int len; + + while (MORE() && !SEETWO(endc, ']')) + NEXT(); + if (!MORE()) { + SETERROR(REG_EBRACK); + return(0); + } + len = p->next - sp; + for (cp = cnames; cp->name != NULL; cp++) + if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0') + return(cp->code); /* known name */ + if (len == 1) + return(*sp); /* single character */ + SETERROR(REG_ECOLLATE); /* neither */ + return(0); +} + +/* + - othercase - return the case counterpart of an alphabetic + */ +static char /* if no counterpart, return ch */ +othercase(int ch) +{ + ch = (uch)ch; + assert(isalpha(ch)); + if (isupper(ch)) + return ((uch)tolower(ch)); + else if (islower(ch)) + return ((uch)toupper(ch)); + else /* peculiar, but could happen */ + return(ch); +} + +/* + - bothcases - emit a dualcase version of a two-case character + * + * Boy, is this implementation ever a kludge... + */ +static void +bothcases(struct parse *p, int ch) +{ + char *oldnext = p->next; + char *oldend = p->end; + char bracket[3]; + + ch = (uch)ch; + assert(othercase(ch) != ch); /* p_bracket() would recurse */ + p->next = bracket; + p->end = bracket+2; + bracket[0] = ch; + bracket[1] = ']'; + bracket[2] = '\0'; + p_bracket(p); + assert(p->next == bracket+2); + p->next = oldnext; + p->end = oldend; +} + +/* + - ordinary - emit an ordinary character + */ +static void +ordinary(struct parse *p, int ch) +{ + cat_t *cap = p->g->categories; + + if ((p->g->cflags®_ICASE) && isalpha((uch)ch) && othercase(ch) != ch) + bothcases(p, ch); + else { + EMIT(OCHAR, (uch)ch); + if (cap[ch] == 0) + cap[ch] = p->g->ncategories++; + } +} + +/* + - nonnewline - emit REG_NEWLINE version of OANY + * + * Boy, is this implementation ever a kludge... + */ +static void +nonnewline(struct parse *p) +{ + char *oldnext = p->next; + char *oldend = p->end; + char bracket[4]; + + p->next = bracket; + p->end = bracket+3; + bracket[0] = '^'; + bracket[1] = '\n'; + bracket[2] = ']'; + bracket[3] = '\0'; + p_bracket(p); + assert(p->next == bracket+3); + p->next = oldnext; + p->end = oldend; +} + +/* + - repeat - generate code for a bounded repetition, recursively if needed + */ +static void +repeat(struct parse *p, + sopno start, /* operand from here to end of strip */ + int from, /* repeated from this number */ + int to) /* to this number of times (maybe INFINITY) */ +{ + sopno finish = HERE(); +# define N 2 +# define INF 3 +# define REP(f, t) ((f)*8 + (t)) +# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N) + sopno copy; + + if (p->error != 0) /* head off possible runaway recursion */ + return; + + assert(from <= to); + + switch (REP(MAP(from), MAP(to))) { + case REP(0, 0): /* must be user doing this */ + DROP(finish-start); /* drop the operand */ + break; + case REP(0, 1): /* as x{1,1}? */ + case REP(0, N): /* as x{1,n}? */ + case REP(0, INF): /* as x{1,}? */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); /* offset is wrong... */ + repeat(p, start+1, 1, to); + ASTERN(OOR1, start); + AHEAD(start); /* ... fix it */ + EMIT(OOR2, 0); + AHEAD(THERE()); + ASTERN(O_CH, THERETHERE()); + break; + case REP(1, 1): /* trivial case */ + /* done */ + break; + case REP(1, N): /* as x?x{1,n-1} */ + /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */ + INSERT(OCH_, start); + ASTERN(OOR1, start); + AHEAD(start); + EMIT(OOR2, 0); /* offset very wrong... */ + AHEAD(THERE()); /* ...so fix it */ + ASTERN(O_CH, THERETHERE()); + copy = dupl(p, start+1, finish+1); + assert(copy == finish+4); + repeat(p, copy, 1, to-1); + break; + case REP(1, INF): /* as x+ */ + INSERT(OPLUS_, start); + ASTERN(O_PLUS, start); + break; + case REP(N, N): /* as xx{m-1,n-1} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to-1); + break; + case REP(N, INF): /* as xx{n-1,INF} */ + copy = dupl(p, start, finish); + repeat(p, copy, from-1, to); + break; + default: /* "can't happen" */ + SETERROR(REG_ASSERT); /* just in case */ + break; + } +} + +/* + - seterr - set an error condition + */ +static int /* useless but makes type checking happy */ +seterr(struct parse *p, int e) +{ + if (p->error == 0) /* keep earliest error condition */ + p->error = e; + p->next = nuls; /* try to bring things to a halt */ + p->end = nuls; + return(0); /* make the return value well-defined */ +} + +/* + - allocset - allocate a set of characters for [] + */ +static cset * +allocset(struct parse *p) +{ + int no = p->g->ncsets++; + size_t nc; + size_t nbytes; + cset *cs; + size_t css = (size_t)p->g->csetsize; + int i; + + if (no >= p->ncsalloc) { /* need another column of space */ + void *ptr; + + p->ncsalloc += CHAR_BIT; + nc = p->ncsalloc; + assert(nc % CHAR_BIT == 0); + nbytes = nc / CHAR_BIT * css; + + ptr = (cset *)realloc((char *)p->g->sets, nc * sizeof(cset)); + if (ptr == NULL) + goto nomem; + p->g->sets = ptr; + + ptr = (uch *)realloc((char *)p->g->setbits, nbytes); + if (ptr == NULL) + goto nomem; + p->g->setbits = ptr; + + for (i = 0; i < no; i++) + p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); + + (void) memset((char *)p->g->setbits + (nbytes - css), 0, css); + } + /* XXX should not happen */ + if (p->g->sets == NULL || p->g->setbits == NULL) + goto nomem; + + cs = &p->g->sets[no]; + cs->ptr = p->g->setbits + css*((no)/CHAR_BIT); + cs->mask = 1 << ((no) % CHAR_BIT); + cs->hash = 0; + cs->smultis = 0; + cs->multis = NULL; + + return(cs); +nomem: + free(p->g->sets); + p->g->sets = NULL; + free(p->g->setbits); + p->g->setbits = NULL; + + SETERROR(REG_ESPACE); + /* caller's responsibility not to do set ops */ + return(NULL); +} + +/* + - freeset - free a now-unused set + */ +static void +freeset(struct parse *p, cset *cs) +{ + size_t i; + cset *top = &p->g->sets[p->g->ncsets]; + size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + CHsub(cs, i); + if (cs == top-1) /* recover only the easy case */ + p->g->ncsets--; +} + +/* + - freezeset - final processing on a set of characters + * + * The main task here is merging identical sets. This is usually a waste + * of time (although the hash code minimizes the overhead), but can win + * big if REG_ICASE is being used. REG_ICASE, by the way, is why the hash + * is done using addition rather than xor -- all ASCII [aA] sets xor to + * the same value! + */ +static int /* set number */ +freezeset(struct parse *p, cset *cs) +{ + uch h = cs->hash; + size_t i; + cset *top = &p->g->sets[p->g->ncsets]; + cset *cs2; + size_t css = (size_t)p->g->csetsize; + + /* look for an earlier one which is the same */ + for (cs2 = &p->g->sets[0]; cs2 < top; cs2++) + if (cs2->hash == h && cs2 != cs) { + /* maybe */ + for (i = 0; i < css; i++) + if (!!CHIN(cs2, i) != !!CHIN(cs, i)) + break; /* no */ + if (i == css) + break; /* yes */ + } + + if (cs2 < top) { /* found one */ + freeset(p, cs); + cs = cs2; + } + + return((int)(cs - p->g->sets)); +} + +/* + - firstch - return first character in a set (which must have at least one) + */ +static int /* character; there is no "none" value */ +firstch(struct parse *p, cset *cs) +{ + size_t i; + size_t css = (size_t)p->g->csetsize; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + return((char)i); + assert(never); + return(0); /* arbitrary */ +} + +/* + - nch - number of characters in a set + */ +static int +nch(struct parse *p, cset *cs) +{ + size_t i; + size_t css = (size_t)p->g->csetsize; + int n = 0; + + for (i = 0; i < css; i++) + if (CHIN(cs, i)) + n++; + return(n); +} + +/* + - mcadd - add a collating element to a cset + */ +static void +mcadd( struct parse *p, cset *cs, const char *cp) +{ + size_t oldend = cs->smultis; + void *np; + + cs->smultis += strlen(cp) + 1; + np = realloc(cs->multis, cs->smultis); + if (np == NULL) { + if (cs->multis) + free(cs->multis); + cs->multis = NULL; + SETERROR(REG_ESPACE); + return; + } + cs->multis = np; + + llvm_strlcpy(cs->multis + oldend - 1, cp, cs->smultis - oldend + 1); +} + +/* + - mcinvert - invert the list of collating elements in a cset + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +/* ARGSUSED */ +static void +mcinvert(struct parse *p, cset *cs) +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - mccase - add case counterparts of the list of collating elements in a cset + * + * This would have to know the set of possibilities. Implementation + * is deferred. + */ +/* ARGSUSED */ +static void +mccase(struct parse *p, cset *cs) +{ + assert(cs->multis == NULL); /* xxx */ +} + +/* + - isinsets - is this character in any sets? + */ +static int /* predicate */ +isinsets(struct re_guts *g, int c) +{ + uch *col; + int i; + int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + unsigned uc = (uch)c; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc] != 0) + return(1); + return(0); +} + +/* + - samesets - are these two characters in exactly the same sets? + */ +static int /* predicate */ +samesets(struct re_guts *g, int c1, int c2) +{ + uch *col; + int i; + int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT; + unsigned uc1 = (uch)c1; + unsigned uc2 = (uch)c2; + + for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize) + if (col[uc1] != col[uc2]) + return(0); + return(1); +} + +/* + - categorize - sort out character categories + */ +static void +categorize(struct parse *p, struct re_guts *g) +{ + cat_t *cats = g->categories; + int c; + int c2; + cat_t cat; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (cats[c] == 0 && isinsets(g, c)) { + cat = g->ncategories++; + cats[c] = cat; + for (c2 = c+1; c2 <= CHAR_MAX; c2++) + if (cats[c2] == 0 && samesets(g, c, c2)) + cats[c2] = cat; + } +} + +/* + - dupl - emit a duplicate of a bunch of sops + */ +static sopno /* start of duplicate */ +dupl(struct parse *p, + sopno start, /* from here */ + sopno finish) /* to this less one */ +{ + sopno ret = HERE(); + sopno len = finish - start; + + assert(finish >= start); + if (len == 0) + return(ret); + enlarge(p, p->ssize + len); /* this many unexpected additions */ + assert(p->ssize >= p->slen + len); + (void) memmove((char *)(p->strip + p->slen), + (char *)(p->strip + start), (size_t)len*sizeof(sop)); + p->slen += len; + return(ret); +} + +/* + - doemit - emit a strip operator + * + * It might seem better to implement this as a macro with a function as + * hard-case backup, but it's just too big and messy unless there are + * some changes to the data structures. Maybe later. + */ +static void +doemit(struct parse *p, sop op, size_t opnd) +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* deal with oversize operands ("can't happen", more or less) */ + assert(opnd < 1<slen >= p->ssize) + enlarge(p, (p->ssize+1) / 2 * 3); /* +50% */ + assert(p->slen < p->ssize); + + /* finally, it's all reduced to the easy case */ + p->strip[p->slen++] = SOP(op, opnd); +} + +/* + - doinsert - insert a sop into the strip + */ +static void +doinsert(struct parse *p, sop op, size_t opnd, sopno pos) +{ + sopno sn; + sop s; + int i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + sn = HERE(); + EMIT(op, opnd); /* do checks, ensure space */ + assert(HERE() == sn+1); + s = p->strip[sn]; + + /* adjust paren pointers */ + assert(pos > 0); + for (i = 1; i < NPAREN; i++) { + if (p->pbegin[i] >= pos) { + p->pbegin[i]++; + } + if (p->pend[i] >= pos) { + p->pend[i]++; + } + } + + memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos], + (HERE()-pos-1)*sizeof(sop)); + p->strip[pos] = s; +} + +/* + - dofwd - complete a forward reference + */ +static void +dofwd(struct parse *p, sopno pos, sop value) +{ + /* avoid making error situations worse */ + if (p->error != 0) + return; + + assert(value < 1<strip[pos] = OP(p->strip[pos]) | value; +} + +/* + - enlarge - enlarge the strip + */ +static void +enlarge(struct parse *p, sopno size) +{ + sop *sp; + + if (p->ssize >= size) + return; + + sp = (sop *)realloc(p->strip, size*sizeof(sop)); + if (sp == NULL) { + SETERROR(REG_ESPACE); + return; + } + p->strip = sp; + p->ssize = size; +} + +/* + - stripsnug - compact the strip + */ +static void +stripsnug(struct parse *p, struct re_guts *g) +{ + g->nstates = p->slen; + g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop)); + if (g->strip == NULL) { + SETERROR(REG_ESPACE); + g->strip = p->strip; + } +} + +/* + - findmust - fill in must and mlen with longest mandatory literal string + * + * This algorithm could do fancy things like analyzing the operands of | + * for common subsequences. Someday. This code is simple and finds most + * of the interesting cases. + * + * Note that must and mlen got initialized during setup. + */ +static void +findmust(struct parse *p, struct re_guts *g) +{ + sop *scan; + sop *start = 0; /* start initialized in the default case, after that */ + sop *newstart = 0; /* newstart was initialized in the OCHAR case */ + sopno newlen; + sop s; + char *cp; + sopno i; + + /* avoid making error situations worse */ + if (p->error != 0) + return; + + /* find the longest OCHAR sequence in strip */ + newlen = 0; + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OCHAR: /* sequence member */ + if (newlen == 0) /* new sequence */ + newstart = scan - 1; + newlen++; + break; + case OPLUS_: /* things that don't break one */ + case OLPAREN: + case ORPAREN: + break; + case OQUEST_: /* things that must be skipped */ + case OCH_: + scan--; + do { + scan += OPND(s); + s = *scan; + /* assert() interferes w debug printouts */ + if (OP(s) != O_QUEST && OP(s) != O_CH && + OP(s) != OOR2) { + g->iflags |= REGEX_BAD; + return; + } + } while (OP(s) != O_QUEST && OP(s) != O_CH); + /* fallthrough */ + default: /* things that break a sequence */ + if (newlen > g->mlen) { /* ends one */ + start = newstart; + g->mlen = newlen; + } + newlen = 0; + break; + } + } while (OP(s) != OEND); + + if (g->mlen == 0) /* there isn't one */ + return; + + /* turn it into a character string */ + g->must = malloc((size_t)g->mlen + 1); + if (g->must == NULL) { /* argh; just forget it */ + g->mlen = 0; + return; + } + cp = g->must; + scan = start; + for (i = g->mlen; i > 0; i--) { + while (OP(s = *scan++) != OCHAR) + continue; + assert(cp < g->must + g->mlen); + *cp++ = (char)OPND(s); + } + assert(cp == g->must + g->mlen); + *cp++ = '\0'; /* just on general principles */ +} + +/* + - pluscount - count + nesting + */ +static sopno /* nesting depth */ +pluscount(struct parse *p, struct re_guts *g) +{ + sop *scan; + sop s; + sopno plusnest = 0; + sopno maxnest = 0; + + if (p->error != 0) + return(0); /* there may not be an OEND */ + + scan = g->strip + 1; + do { + s = *scan++; + switch (OP(s)) { + case OPLUS_: + plusnest++; + break; + case O_PLUS: + if (plusnest > maxnest) + maxnest = plusnest; + plusnest--; + break; + } + } while (OP(s) != OEND); + if (plusnest != 0) + g->iflags |= REGEX_BAD; + return(maxnest); +} diff --git a/final/lib/Support/regengine.inc b/final/lib/Support/regengine.inc new file mode 100644 index 00000000000..7e41f96f359 --- /dev/null +++ b/final/lib/Support/regengine.inc @@ -0,0 +1,1034 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)engine.c 8.5 (Berkeley) 3/20/94 + */ + +/* + * The matching engine and friends. This file is #included by regexec.c + * after suitable #defines of a variety of macros used herein, so that + * different state representations can be used without duplicating masses + * of code. + */ + +#ifdef SNAMES +#define matcher smatcher +#define fast sfast +#define slow sslow +#define dissect sdissect +#define backref sbackref +#define step sstep +#define print sprint +#define at sat +#define match smat +#define nope snope +#endif +#ifdef LNAMES +#define matcher lmatcher +#define fast lfast +#define slow lslow +#define dissect ldissect +#define backref lbackref +#define step lstep +#define print lprint +#define at lat +#define match lmat +#define nope lnope +#endif + +/* another structure passed up and down to avoid zillions of parameters */ +struct match { + struct re_guts *g; + int eflags; + llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ + const char *offp; /* offsets work from here */ + const char *beginp; /* start of string -- virtual NUL precedes */ + const char *endp; /* end of string -- virtual NUL here */ + const char *coldp; /* can be no match starting before here */ + const char **lastpos; /* [nplus+1] */ + STATEVARS; + states st; /* current states */ + states fresh; /* states for a fresh start */ + states tmp; /* temporary */ + states empty; /* empty set of states */ +}; + +static int matcher(struct re_guts *, const char *, size_t, + llvm_regmatch_t[], int); +static const char *dissect(struct match *, const char *, const char *, sopno, + sopno); +static const char *backref(struct match *, const char *, const char *, sopno, + sopno, sopno, int); +static const char *fast(struct match *, const char *, const char *, sopno, sopno); +static const char *slow(struct match *, const char *, const char *, sopno, sopno); +static states step(struct re_guts *, sopno, sopno, states, int, states); +#define MAX_RECURSION 100 +#define BOL (OUT+1) +#define EOL (BOL+1) +#define BOLEOL (BOL+2) +#define NOTHING (BOL+3) +#define BOW (BOL+4) +#define EOW (BOL+5) +#define CODEMAX (BOL+5) /* highest code used */ +#define NONCHAR(c) ((c) > CHAR_MAX) +#define NNONCHAR (CODEMAX-CHAR_MAX) +#ifdef REDEBUG +static void print(struct match *, char *, states, int, FILE *); +#endif +#ifdef REDEBUG +static void at(struct match *, char *, char *, char *, sopno, sopno); +#endif +#ifdef REDEBUG +static char *pchar(int); +#endif + +#ifdef REDEBUG +#define SP(t, s, c) print(m, t, s, c, stdout) +#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) +#define NOTE(str) { if (m->eflags®_TRACE) (void)printf("=%s\n", (str)); } +static int nope = 0; +#else +#define SP(t, s, c) /* nothing */ +#define AT(t, p1, p2, s1, s2) /* nothing */ +#define NOTE(s) /* nothing */ +#endif + +/* + - matcher - the actual matching engine + */ +static int /* 0 success, REG_NOMATCH failure */ +matcher(struct re_guts *g, const char *string, size_t nmatch, + llvm_regmatch_t pmatch[], + int eflags) +{ + const char *endp; + size_t i; + struct match mv; + struct match *m = &mv; + const char *dp; + const sopno gf = g->firststate+1; /* +1 for OEND */ + const sopno gl = g->laststate; + const char *start; + const char *stop; + + /* simplify the situation where possible */ + if (g->cflags®_NOSUB) + nmatch = 0; + if (eflags®_STARTEND) { + start = string + pmatch[0].rm_so; + stop = string + pmatch[0].rm_eo; + } else { + start = string; + stop = start + strlen(start); + } + if (stop < start) + return(REG_INVARG); + + /* prescreening; this does wonders for this rather slow code */ + if (g->must != NULL) { + for (dp = start; dp < stop; dp++) + if (*dp == g->must[0] && stop - dp >= g->mlen && + memcmp(dp, g->must, (size_t)g->mlen) == 0) + break; + if (dp == stop) /* we didn't find g->must */ + return(REG_NOMATCH); + } + + /* match struct setup */ + m->g = g; + m->eflags = eflags; + m->pmatch = NULL; + m->lastpos = NULL; + m->offp = string; + m->beginp = start; + m->endp = stop; + STATESETUP(m, 4); + SETUP(m->st); + SETUP(m->fresh); + SETUP(m->tmp); + SETUP(m->empty); + CLEAR(m->empty); + + /* this loop does only one repetition except for backrefs */ + for (;;) { + endp = fast(m, start, stop, gf, gl); + if (endp == NULL) { /* a miss */ + free(m->pmatch); + free((void*)m->lastpos); + STATETEARDOWN(m); + return(REG_NOMATCH); + } + if (nmatch == 0 && !g->backrefs) + break; /* no further info needed */ + + /* where? */ + assert(m->coldp != NULL); + for (;;) { + NOTE("finding start"); + endp = slow(m, m->coldp, stop, gf, gl); + if (endp != NULL) + break; + assert(m->coldp < m->endp); + m->coldp++; + } + if (nmatch == 1 && !g->backrefs) + break; /* no further info needed */ + + /* oh my, he wants the subexpressions... */ + if (m->pmatch == NULL) + m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) * + sizeof(llvm_regmatch_t)); + if (m->pmatch == NULL) { + STATETEARDOWN(m); + return(REG_ESPACE); + } + for (i = 1; i <= m->g->nsub; i++) + m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; + if (!g->backrefs && !(m->eflags®_BACKR)) { + NOTE("dissecting"); + dp = dissect(m, m->coldp, endp, gf, gl); + } else { + if (g->nplus > 0 && m->lastpos == NULL) + m->lastpos = (const char **)malloc((g->nplus+1) * + sizeof(char *)); + if (g->nplus > 0 && m->lastpos == NULL) { + free(m->pmatch); + STATETEARDOWN(m); + return(REG_ESPACE); + } + NOTE("backref dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); + } + if (dp != NULL) + break; + + /* uh-oh... we couldn't find a subexpression-level match */ + assert(g->backrefs); /* must be back references doing it */ + assert(g->nplus == 0 || m->lastpos != NULL); + for (;;) { + if (dp != NULL || endp <= m->coldp) + break; /* defeat */ + NOTE("backoff"); + endp = slow(m, m->coldp, endp-1, gf, gl); + if (endp == NULL) + break; /* defeat */ + /* try it on a shorter possibility */ +#ifndef NDEBUG + for (i = 1; i <= m->g->nsub; i++) { + assert(m->pmatch[i].rm_so == -1); + assert(m->pmatch[i].rm_eo == -1); + } +#endif + NOTE("backoff dissect"); + dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); + } + assert(dp == NULL || dp == endp); + if (dp != NULL) /* found a shorter one */ + break; + + /* despite initial appearances, there is no match here */ + NOTE("false alarm"); + if (m->coldp == stop) + break; + start = m->coldp + 1; /* recycle starting later */ + } + + /* fill in the details if requested */ + if (nmatch > 0) { + pmatch[0].rm_so = m->coldp - m->offp; + pmatch[0].rm_eo = endp - m->offp; + } + if (nmatch > 1) { + assert(m->pmatch != NULL); + for (i = 1; i < nmatch; i++) + if (i <= m->g->nsub) + pmatch[i] = m->pmatch[i]; + else { + pmatch[i].rm_so = -1; + pmatch[i].rm_eo = -1; + } + } + + if (m->pmatch != NULL) + free((char *)m->pmatch); + if (m->lastpos != NULL) + free((char *)m->lastpos); + STATETEARDOWN(m); + return(0); +} + +/* + - dissect - figure out what matched what, no back references + */ +static const char * /* == stop (success) always */ +dissect(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) +{ + int i; + sopno ss; /* start sop of current subRE */ + sopno es; /* end sop of current subRE */ + const char *sp; /* start of string matched by it */ + const char *stp; /* string matched by it cannot pass here */ + const char *rest; /* start of rest of string */ + const char *tail; /* string unmatched by rest of RE */ + sopno ssub; /* start sop of subsubRE */ + sopno esub; /* end sop of subsubRE */ + const char *ssp; /* start of string matched by subsubRE */ + const char *sep; /* end of string matched by subsubRE */ + const char *oldssp; /* previous ssp */ + + AT("diss", start, stop, startst, stopst); + sp = start; + for (ss = startst; ss < stopst; ss = es) { + /* identify end of subRE */ + es = ss; + switch (OP(m->g->strip[es])) { + case OPLUS_: + case OQUEST_: + es += OPND(m->g->strip[es]); + break; + case OCH_: + while (OP(m->g->strip[es]) != O_CH) + es += OPND(m->g->strip[es]); + break; + } + es++; + + /* figure out what it matched */ + switch (OP(m->g->strip[ss])) { + case OEND: + assert(nope); + break; + case OCHAR: + sp++; + break; + case OBOL: + case OEOL: + case OBOW: + case OEOW: + break; + case OANY: + case OANYOF: + sp++; + break; + case OBACK_: + case O_BACK: + assert(nope); + break; + /* cases where length of match is hard to find */ + case OQUEST_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + /* did innards match? */ + if (slow(m, sp, rest, ssub, esub) != NULL) { + const char *dp = dissect(m, sp, rest, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == rest); + } else /* no */ + assert(sp == rest); + sp = rest; + break; + case OPLUS_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = es - 1; + ssp = sp; + oldssp = ssp; + for (;;) { /* find last match of innards */ + sep = slow(m, ssp, rest, ssub, esub); + if (sep == NULL || sep == ssp) + break; /* failed or matched null */ + oldssp = ssp; /* on to next try */ + ssp = sep; + } + if (sep == NULL) { + /* last successful match */ + sep = ssp; + ssp = oldssp; + } + assert(sep == rest); /* must exhaust substring */ + assert(slow(m, ssp, sep, ssub, esub) == rest); + { + const char *dp = dissect(m, ssp, sep, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == sep); + } + sp = rest; + break; + case OCH_: + stp = stop; + for (;;) { + /* how long could this one be? */ + rest = slow(m, sp, stp, ss, es); + assert(rest != NULL); /* it did match */ + /* could the rest match the rest? */ + tail = slow(m, rest, stop, es, stopst); + if (tail == stop) + break; /* yes! */ + /* no -- try a shorter match for this one */ + stp = rest - 1; + assert(stp >= sp); /* it did work */ + } + ssub = ss + 1; + esub = ss + OPND(m->g->strip[ss]) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + if (slow(m, sp, rest, ssub, esub) == rest) + break; /* it matched all of it */ + /* that one missed, try next one */ + assert(OP(m->g->strip[esub]) == OOR1); + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + { + const char *dp = dissect(m, sp, rest, ssub, esub); + (void)dp; /* avoid warning if assertions off */ + assert(dp == rest); + } + sp = rest; + break; + case O_PLUS: + case O_QUEST: + case OOR1: + case OOR2: + case O_CH: + assert(nope); + break; + case OLPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_so = sp - m->offp; + break; + case ORPAREN: + i = OPND(m->g->strip[ss]); + assert(0 < i && i <= m->g->nsub); + m->pmatch[i].rm_eo = sp - m->offp; + break; + default: /* uh oh */ + assert(nope); + break; + } + } + + assert(sp == stop); + return(sp); +} + +/* + - backref - figure out what matched what, figuring in back references + */ +static const char * /* == stop (success) or NULL (failure) */ +backref(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst, sopno lev, int rec) /* PLUS nesting level */ +{ + int i; + sopno ss; /* start sop of current subRE */ + const char *sp; /* start of string matched by it */ + sopno ssub; /* start sop of subsubRE */ + sopno esub; /* end sop of subsubRE */ + const char *ssp; /* start of string matched by subsubRE */ + const char *dp; + size_t len; + int hard; + sop s; + llvm_regoff_t offsave; + cset *cs; + + AT("back", start, stop, startst, stopst); + sp = start; + + /* get as far as we can with easy stuff */ + hard = 0; + for (ss = startst; !hard && ss < stopst; ss++) + switch (OP(s = m->g->strip[ss])) { + case OCHAR: + if (sp == stop || *sp++ != (char)OPND(s)) + return(NULL); + break; + case OANY: + if (sp == stop) + return(NULL); + sp++; + break; + case OANYOF: + cs = &m->g->sets[OPND(s)]; + if (sp == stop || !CHIN(cs, *sp++)) + return(NULL); + break; + case OBOL: + if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp > m->beginp && + !ISWORD(*(sp-1))) ) && + (sp < m->endp && ISWORD(*sp)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOW: + if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) || + (sp < m->endp && !ISWORD(*sp)) ) && + (sp > m->beginp && ISWORD(*(sp-1))) ) + { /* yes */ } + else + return(NULL); + break; + case O_QUEST: + break; + case OOR1: /* matches null but needs to skip */ + ss++; + s = m->g->strip[ss]; + do { + assert(OP(s) == OOR2); + ss += OPND(s); + } while (OP(s = m->g->strip[ss]) != O_CH); + /* note that the ss++ gets us past the O_CH */ + break; + default: /* have to make a choice */ + hard = 1; + break; + } + if (!hard) { /* that was it! */ + if (sp != stop) + return(NULL); + return(sp); + } + ss--; /* adjust for the for's final increment */ + + /* the hard stuff */ + AT("hard", sp, stop, ss, stopst); + s = m->g->strip[ss]; + switch (OP(s)) { + case OBACK_: /* the vilest depths */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + if (m->pmatch[i].rm_eo == -1) + return(NULL); + assert(m->pmatch[i].rm_so != -1); + len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; + if (len == 0 && rec++ > MAX_RECURSION) + return(NULL); + assert(stop - m->beginp >= len); + if (sp > stop - len) + return(NULL); /* not enough left to match */ + ssp = m->offp + m->pmatch[i].rm_so; + if (memcmp(sp, ssp, len) != 0) + return(NULL); + while (m->g->strip[ss] != SOP(O_BACK, i)) + ss++; + return(backref(m, sp+len, stop, ss+1, stopst, lev, rec)); + break; + case OQUEST_: /* to null or not */ + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); /* not */ + return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec)); + break; + case OPLUS_: + assert(m->lastpos != NULL); + assert(lev+1 <= m->g->nplus); + m->lastpos[lev+1] = sp; + return(backref(m, sp, stop, ss+1, stopst, lev+1, rec)); + break; + case O_PLUS: + if (sp == m->lastpos[lev]) /* last pass matched null */ + return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); + /* try another pass */ + m->lastpos[lev] = sp; + dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec); + if (dp == NULL) + return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); + else + return(dp); + break; + case OCH_: /* find the right one, if any */ + ssub = ss + 1; + esub = ss + OPND(s) - 1; + assert(OP(m->g->strip[esub]) == OOR1); + for (;;) { /* find first matching branch */ + dp = backref(m, sp, stop, ssub, esub, lev, rec); + if (dp != NULL) + return(dp); + /* that one missed, try next one */ + if (OP(m->g->strip[esub]) == O_CH) + return(NULL); /* there is none */ + esub++; + assert(OP(m->g->strip[esub]) == OOR2); + ssub = esub + 1; + esub += OPND(m->g->strip[esub]); + if (OP(m->g->strip[esub]) == OOR2) + esub--; + else + assert(OP(m->g->strip[esub]) == O_CH); + } + break; + case OLPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_so; + m->pmatch[i].rm_so = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_so = offsave; + return(NULL); + break; + case ORPAREN: /* must undo assignment if rest fails */ + i = OPND(s); + assert(0 < i && i <= m->g->nsub); + offsave = m->pmatch[i].rm_eo; + m->pmatch[i].rm_eo = sp - m->offp; + dp = backref(m, sp, stop, ss+1, stopst, lev, rec); + if (dp != NULL) + return(dp); + m->pmatch[i].rm_eo = offsave; + return(NULL); + break; + default: /* uh oh */ + assert(nope); + break; + } + + /* "can't happen" */ + assert(nope); + /* NOTREACHED */ + return NULL; +} + +/* + - fast - step through the string at top speed + */ +static const char * /* where tentative match ended, or NULL */ +fast(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) +{ + states st = m->st; + states fresh = m->fresh; + states tmp = m->tmp; + const char *p = start; + int c = (start == m->beginp) ? OUT : *(start-1); + int lastc; /* previous c */ + int flagch; + int i; + const char *coldp; /* last p after which no match was underway */ + + CLEAR(st); + SET1(st, startst); + st = step(m->g, startst, stopst, st, NOTHING, st); + ASSIGN(fresh, st); + SP("start", st, *p); + coldp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + if (EQ(st, fresh)) + coldp = p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("boleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("boweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, fresh); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("aft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + assert(coldp != NULL); + m->coldp = coldp; + if (ISSET(st, stopst)) + return(p+1); + else + return(NULL); +} + +/* + - slow - step through the string more deliberately + */ +static const char * /* where it ended */ +slow(struct match *m, const char *start, const char *stop, sopno startst, + sopno stopst) +{ + states st = m->st; + states empty = m->empty; + states tmp = m->tmp; + const char *p = start; + int c = (start == m->beginp) ? OUT : *(start-1); + int lastc; /* previous c */ + int flagch; + int i; + const char *matchp; /* last p at which a match ended */ + + AT("slow", start, stop, startst, stopst); + CLEAR(st); + SET1(st, startst); + SP("sstart", st, *p); + st = step(m->g, startst, stopst, st, NOTHING, st); + matchp = NULL; + for (;;) { + /* next character */ + lastc = c; + c = (p == m->endp) ? OUT : *p; + + /* is there an EOL and/or BOL between lastc and c? */ + flagch = '\0'; + i = 0; + if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_NOTEOL)) ) { + flagch = (flagch == BOL) ? BOLEOL : EOL; + i += m->g->neol; + } + if (i != 0) { + for (; i > 0; i--) + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboleol", st, c); + } + + /* how about a word boundary? */ + if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && + (c != OUT && ISWORD(c)) ) { + flagch = BOW; + } + if ( (lastc != OUT && ISWORD(lastc)) && + (flagch == EOL || (c != OUT && !ISWORD(c))) ) { + flagch = EOW; + } + if (flagch == BOW || flagch == EOW) { + st = step(m->g, startst, stopst, st, flagch, st); + SP("sboweow", st, c); + } + + /* are we done? */ + if (ISSET(st, stopst)) + matchp = p; + if (EQ(st, empty) || p == stop) + break; /* NOTE BREAK OUT */ + + /* no, we must deal with this character */ + ASSIGN(tmp, st); + ASSIGN(st, empty); + assert(c != OUT); + st = step(m->g, startst, stopst, tmp, c, st); + SP("saft", st, c); + assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); + p++; + } + + return(matchp); +} + + +/* + - step - map set of states reachable before char to set reachable after + */ +static states +step(struct re_guts *g, + sopno start, /* start state within strip */ + sopno stop, /* state after stop state within strip */ + states bef, /* states reachable before */ + int ch, /* character or NONCHAR code */ + states aft) /* states already known reachable after */ +{ + cset *cs; + sop s; + sopno pc; + onestate here; /* note, macros know this name */ + sopno look; + int i; + + for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { + s = g->strip[pc]; + switch (OP(s)) { + case OEND: + assert(pc == stop-1); + break; + case OCHAR: + /* only characters can match */ + assert(!NONCHAR(ch) || ch != (char)OPND(s)); + if (ch == (char)OPND(s)) + FWD(aft, bef, 1); + break; + case OBOL: + if (ch == BOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OEOL: + if (ch == EOL || ch == BOLEOL) + FWD(aft, bef, 1); + break; + case OBOW: + if (ch == BOW) + FWD(aft, bef, 1); + break; + case OEOW: + if (ch == EOW) + FWD(aft, bef, 1); + break; + case OANY: + if (!NONCHAR(ch)) + FWD(aft, bef, 1); + break; + case OANYOF: + cs = &g->sets[OPND(s)]; + if (!NONCHAR(ch) && CHIN(cs, ch)) + FWD(aft, bef, 1); + break; + case OBACK_: /* ignored here */ + case O_BACK: + FWD(aft, aft, 1); + break; + case OPLUS_: /* forward, this is just an empty */ + FWD(aft, aft, 1); + break; + case O_PLUS: /* both forward and back */ + FWD(aft, aft, 1); + i = ISSETBACK(aft, OPND(s)); + BACK(aft, aft, OPND(s)); + if (!i && ISSETBACK(aft, OPND(s))) { + /* oho, must reconsider loop body */ + pc -= OPND(s) + 1; + INIT(here, pc); + } + break; + case OQUEST_: /* two branches, both forward */ + FWD(aft, aft, 1); + FWD(aft, aft, OPND(s)); + break; + case O_QUEST: /* just an empty */ + FWD(aft, aft, 1); + break; + case OLPAREN: /* not significant here */ + case ORPAREN: + FWD(aft, aft, 1); + break; + case OCH_: /* mark the first two branches */ + FWD(aft, aft, 1); + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + break; + case OOR1: /* done a branch, find the O_CH */ + if (ISSTATEIN(aft, here)) { + for (look = 1; + OP(s = g->strip[pc+look]) != O_CH; + look += OPND(s)) + assert(OP(s) == OOR2); + FWD(aft, aft, look); + } + break; + case OOR2: /* propagate OCH_'s marking */ + FWD(aft, aft, 1); + if (OP(g->strip[pc+OPND(s)]) != O_CH) { + assert(OP(g->strip[pc+OPND(s)]) == OOR2); + FWD(aft, aft, OPND(s)); + } + break; + case O_CH: /* just empty */ + FWD(aft, aft, 1); + break; + default: /* ooooops... */ + assert(nope); + break; + } + } + + return(aft); +} + +#ifdef REDEBUG +/* + - print - print a set of states + */ +static void +print(struct match *m, char *caption, states st, int ch, FILE *d) +{ + struct re_guts *g = m->g; + int i; + int first = 1; + + if (!(m->eflags®_TRACE)) + return; + + (void)fprintf(d, "%s", caption); + if (ch != '\0') + (void)fprintf(d, " %s", pchar(ch)); + for (i = 0; i < g->nstates; i++) + if (ISSET(st, i)) { + (void)fprintf(d, "%s%d", (first) ? "\t" : ", ", i); + first = 0; + } + (void)fprintf(d, "\n"); +} + +/* + - at - print current situation + */ +static void +at(struct match *m, char *title, char *start, char *stop, sopno startst, + sopno stopst) +{ + if (!(m->eflags®_TRACE)) + return; + + (void)printf("%s %s-", title, pchar(*start)); + (void)printf("%s ", pchar(*stop)); + (void)printf("%ld-%ld\n", (long)startst, (long)stopst); +} + +#ifndef PCHARDONE +#define PCHARDONE /* never again */ +/* + - pchar - make a character printable + * + * Is this identical to regchar() over in debug.c? Well, yes. But a + * duplicate here avoids having a debugging-capable regexec.o tied to + * a matching debug.o, and this is convenient. It all disappears in + * the non-debug compilation anyway, so it doesn't matter much. + */ +static char * /* -> representation */ +pchar(int ch) +{ + static char pbuf[10]; + + if (isprint(ch) || ch == ' ') + (void)snprintf(pbuf, sizeof pbuf, "%c", ch); + else + (void)snprintf(pbuf, sizeof pbuf, "\\%o", ch); + return(pbuf); +} +#endif +#endif + +#undef matcher +#undef fast +#undef slow +#undef dissect +#undef backref +#undef step +#undef print +#undef at +#undef match +#undef nope diff --git a/final/lib/Support/regerror.c b/final/lib/Support/regerror.c new file mode 100644 index 00000000000..1d67c9a2b03 --- /dev/null +++ b/final/lib/Support/regerror.c @@ -0,0 +1,135 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regerror.c 8.4 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +static const char *regatoi(const llvm_regex_t *, char *, int); + +static struct rerr { + int code; + const char *name; + const char *explain; +} rerrs[] = { + { REG_NOMATCH, "REG_NOMATCH", "llvm_regexec() failed to match" }, + { REG_BADPAT, "REG_BADPAT", "invalid regular expression" }, + { REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element" }, + { REG_ECTYPE, "REG_ECTYPE", "invalid character class" }, + { REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)" }, + { REG_ESUBREG, "REG_ESUBREG", "invalid backreference number" }, + { REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced" }, + { REG_EPAREN, "REG_EPAREN", "parentheses not balanced" }, + { REG_EBRACE, "REG_EBRACE", "braces not balanced" }, + { REG_BADBR, "REG_BADBR", "invalid repetition count(s)" }, + { REG_ERANGE, "REG_ERANGE", "invalid character range" }, + { REG_ESPACE, "REG_ESPACE", "out of memory" }, + { REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid" }, + { REG_EMPTY, "REG_EMPTY", "empty (sub)expression" }, + { REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug" }, + { REG_INVARG, "REG_INVARG", "invalid argument to regex routine" }, + { 0, "", "*** unknown regexp error code ***" } +}; + +/* + - llvm_regerror - the interface to error numbers + = extern size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); + */ +/* ARGSUSED */ +size_t +llvm_regerror(int errcode, const llvm_regex_t *preg, char *errbuf, size_t errbuf_size) +{ + struct rerr *r; + size_t len; + int target = errcode &~ REG_ITOA; + const char *s; + char convbuf[50]; + + if (errcode == REG_ATOI) + s = regatoi(preg, convbuf, sizeof convbuf); + else { + for (r = rerrs; r->code != 0; r++) + if (r->code == target) + break; + + if (errcode®_ITOA) { + if (r->code != 0) { + assert(strlen(r->name) < sizeof(convbuf)); + (void) llvm_strlcpy(convbuf, r->name, sizeof convbuf); + } else + (void)snprintf(convbuf, sizeof convbuf, + "REG_0x%x", target); + s = convbuf; + } else + s = r->explain; + } + + len = strlen(s) + 1; + if (errbuf_size > 0) { + llvm_strlcpy(errbuf, s, errbuf_size); + } + + return(len); +} + +/* + - regatoi - internal routine to implement REG_ATOI + */ +static const char * +regatoi(const llvm_regex_t *preg, char *localbuf, int localbufsize) +{ + struct rerr *r; + + for (r = rerrs; r->code != 0; r++) + if (strcmp(r->name, preg->re_endp) == 0) + break; + if (r->code == 0) + return("0"); + + (void)snprintf(localbuf, localbufsize, "%d", r->code); + return(localbuf); +} diff --git a/final/lib/Support/regex2.h b/final/lib/Support/regex2.h new file mode 100644 index 00000000000..21659c34449 --- /dev/null +++ b/final/lib/Support/regex2.h @@ -0,0 +1,157 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regex2.h 8.4 (Berkeley) 3/20/94 + */ + +/* + * internals of regex_t + */ +#define MAGIC1 ((('r'^0200)<<8) | 'e') + +/* + * The internal representation is a *strip*, a sequence of + * operators ending with an endmarker. (Some terminology etc. is a + * historical relic of earlier versions which used multiple strips.) + * Certain oddities in the representation are there to permit running + * the machinery backwards; in particular, any deviation from sequential + * flow must be marked at both its source and its destination. Some + * fine points: + * + * - OPLUS_ and O_PLUS are *inside* the loop they create. + * - OQUEST_ and O_QUEST are *outside* the bypass they create. + * - OCH_ and O_CH are *outside* the multi-way branch they create, while + * OOR1 and OOR2 are respectively the end and the beginning of one of + * the branches. Note that there is an implicit OOR2 following OCH_ + * and an implicit OOR1 preceding O_CH. + * + * In state representations, an operator's bit is on to signify a state + * immediately *preceding* "execution" of that operator. + */ +typedef unsigned long sop; /* strip operator */ +typedef long sopno; +#define OPRMASK 0xf8000000LU +#define OPDMASK 0x07ffffffLU +#define OPSHIFT ((unsigned)27) +#define OP(n) ((n)&OPRMASK) +#define OPND(n) ((n)&OPDMASK) +#define SOP(op, opnd) ((op)|(opnd)) +/* operators meaning operand */ +/* (back, fwd are offsets) */ +#define OEND (1LU< uch [csetsize] */ + uch mask; /* bit within array */ + uch hash; /* hash code */ + size_t smultis; + char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ +} cset; +/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ +#define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) +#define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) +#define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) +#define MCadd(p, cs, cp) mcadd(p, cs, cp) /* llvm_regcomp() internal fns */ +#define MCsub(p, cs, cp) mcsub(p, cs, cp) +#define MCin(p, cs, cp) mcin(p, cs, cp) + +/* stuff for character categories */ +typedef unsigned char cat_t; + +/* + * main compiled-expression structure + */ +struct re_guts { + int magic; +# define MAGIC2 ((('R'^0200)<<8)|'E') + sop *strip; /* malloced area for strip */ + int csetsize; /* number of bits in a cset vector */ + int ncsets; /* number of csets in use */ + cset *sets; /* -> cset [ncsets] */ + uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ + int cflags; /* copy of llvm_regcomp() cflags argument */ + sopno nstates; /* = number of sops */ + sopno firststate; /* the initial OEND (normally 0) */ + sopno laststate; /* the final OEND */ + int iflags; /* internal flags */ +# define USEBOL 01 /* used ^ */ +# define USEEOL 02 /* used $ */ +# define REGEX_BAD 04 /* something wrong */ + int nbol; /* number of ^ used */ + int neol; /* number of $ used */ + int ncategories; /* how many character categories */ + cat_t *categories; /* ->catspace[-CHAR_MIN] */ + char *must; /* match must contain this string */ + int mlen; /* length of must */ + size_t nsub; /* copy of re_nsub */ + int backrefs; /* does it use back references? */ + sopno nplus; /* how deep does it nest +s? */ + /* catspace must be last */ + cat_t catspace[1]; /* actually [NC] */ +}; + +/* misc utilities */ +#define OUT (CHAR_MAX+1) /* a non-character value */ +#define ISWORD(c) (isalnum(c&0xff) || (c) == '_') diff --git a/final/lib/Support/regex_impl.h b/final/lib/Support/regex_impl.h new file mode 100644 index 00000000000..f8296c9ff75 --- /dev/null +++ b/final/lib/Support/regex_impl.h @@ -0,0 +1,108 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992 Henry Spencer. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer of the University of Toronto. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regex.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _REGEX_H_ +#define _REGEX_H_ + +#include +typedef off_t llvm_regoff_t; +typedef struct { + llvm_regoff_t rm_so; /* start of match */ + llvm_regoff_t rm_eo; /* end of match */ +} llvm_regmatch_t; + +typedef struct llvm_regex { + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + struct re_guts *re_g; /* none of your business :-) */ +} llvm_regex_t; + +/* llvm_regcomp() flags */ +#define REG_BASIC 0000 +#define REG_EXTENDED 0001 +#define REG_ICASE 0002 +#define REG_NOSUB 0004 +#define REG_NEWLINE 0010 +#define REG_NOSPEC 0020 +#define REG_PEND 0040 +#define REG_DUMP 0200 + +/* llvm_regerror() flags */ +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 +#define REG_EMPTY 14 +#define REG_ASSERT 15 +#define REG_INVARG 16 +#define REG_ATOI 255 /* convert name to number (!) */ +#define REG_ITOA 0400 /* convert number to name (!) */ + +/* llvm_regexec() flags */ +#define REG_NOTBOL 00001 +#define REG_NOTEOL 00002 +#define REG_STARTEND 00004 +#define REG_TRACE 00400 /* tracing of execution */ +#define REG_LARGE 01000 /* force large representation */ +#define REG_BACKR 02000 /* force use of backref code */ + +#ifdef __cplusplus +extern "C" { +#endif + +int llvm_regcomp(llvm_regex_t *, const char *, int); +size_t llvm_regerror(int, const llvm_regex_t *, char *, size_t); +int llvm_regexec(const llvm_regex_t *, const char *, size_t, + llvm_regmatch_t [], int); +void llvm_regfree(llvm_regex_t *); +size_t llvm_strlcpy(char *dst, const char *src, size_t siz); + +#ifdef __cplusplus +} +#endif + +#endif /* !_REGEX_H_ */ diff --git a/final/lib/Support/regexec.c b/final/lib/Support/regexec.c new file mode 100644 index 00000000000..007861675ba --- /dev/null +++ b/final/lib/Support/regexec.c @@ -0,0 +1,162 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regexec.c 8.3 (Berkeley) 3/20/94 + */ + +/* + * the outer shell of llvm_regexec() + * + * This file includes engine.inc *twice*, after muchos fiddling with the + * macros that code uses. This lets the same code operate on two different + * representations for state sets. + */ +#include +#include +#include +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +/* macros for manipulating states, small version */ +/* FIXME: 'states' is assumed as 'long' on small version. */ +#define states1 long /* for later use in llvm_regexec() decision */ +#define states states1 +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) +#define SET1(v, n) ((v) |= (unsigned long)1 << (n)) +#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) +#define ASSIGN(d, s) ((d) = (s)) +#define EQ(a, b) ((a) == (b)) +#define STATEVARS long dummy /* dummy version */ +#define STATESETUP(m, n) /* nothing */ +#define STATETEARDOWN(m) /* nothing */ +#define SETUP(v) ((v) = 0) +#define onestate long +#define INIT(o, n) ((o) = (unsigned long)1 << (n)) +#define INC(o) ((o) <<= 1) +#define ISSTATEIN(v, o) (((v) & (o)) != 0) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) +/* function names */ +#define SNAMES /* engine.inc looks after details */ + +#include "regengine.inc" + +/* now undo things */ +#undef states +#undef CLEAR +#undef SET0 +#undef SET1 +#undef ISSET +#undef ASSIGN +#undef EQ +#undef STATEVARS +#undef STATESETUP +#undef STATETEARDOWN +#undef SETUP +#undef onestate +#undef INIT +#undef INC +#undef ISSTATEIN +#undef FWD +#undef BACK +#undef ISSETBACK +#undef SNAMES + +/* macros for manipulating states, large version */ +#define states char * +#define CLEAR(v) memset(v, 0, m->g->nstates) +#define SET0(v, n) ((v)[n] = 0) +#define SET1(v, n) ((v)[n] = 1) +#define ISSET(v, n) ((v)[n]) +#define ASSIGN(d, s) memmove(d, s, m->g->nstates) +#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) +#define STATEVARS long vn; char *space +#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ + if ((m)->space == NULL) return(REG_ESPACE); \ + (m)->vn = 0; } +#define STATETEARDOWN(m) { free((m)->space); } +#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) +#define onestate long +#define INIT(o, n) ((o) = (n)) +#define INC(o) ((o)++) +#define ISSTATEIN(v, o) ((v)[o]) +/* some abbreviations; note that some of these know variable names! */ +/* do "if I'm here, I can also be there" etc without branches */ +#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) +#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) +#define ISSETBACK(v, n) ((v)[here - (n)]) +/* function names */ +#define LNAMES /* flag */ + +#include "regengine.inc" + +/* + - llvm_regexec - interface for matching + * + * We put this here so we can exploit knowledge of the state representation + * when choosing which matcher to call. Also, by this point the matchers + * have been prototyped. + */ +int /* 0 success, REG_NOMATCH failure */ +llvm_regexec(const llvm_regex_t *preg, const char *string, size_t nmatch, + llvm_regmatch_t pmatch[], int eflags) +{ + struct re_guts *g = preg->re_g; +#ifdef REDEBUG +# define GOODFLAGS(f) (f) +#else +# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) +#endif + + if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) + return(REG_BADPAT); + assert(!(g->iflags®EX_BAD)); + if (g->iflags®EX_BAD) /* backstop for no-debug case */ + return(REG_BADPAT); + eflags = GOODFLAGS(eflags); + + if (g->nstates <= (long)(CHAR_BIT*sizeof(states1)) && !(eflags®_LARGE)) + return(smatcher(g, string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, string, nmatch, pmatch, eflags)); +} diff --git a/final/lib/Support/regfree.c b/final/lib/Support/regfree.c new file mode 100644 index 00000000000..dc2b4af90fa --- /dev/null +++ b/final/lib/Support/regfree.c @@ -0,0 +1,72 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)regfree.c 8.3 (Berkeley) 3/20/94 + */ + +#include +#include +#include +#include "regex_impl.h" + +#include "regutils.h" +#include "regex2.h" + +/* + - llvm_regfree - free everything + */ +void +llvm_regfree(llvm_regex_t *preg) +{ + struct re_guts *g; + + if (preg->re_magic != MAGIC1) /* oops */ + return; /* nice to complain, but hard */ + + g = preg->re_g; + if (g == NULL || g->magic != MAGIC2) /* oops again */ + return; + preg->re_magic = 0; /* mark it invalid */ + g->magic = 0; /* mark it invalid */ + + if (g->strip != NULL) + free((char *)g->strip); + if (g->sets != NULL) + free((char *)g->sets); + if (g->setbits != NULL) + free((char *)g->setbits); + if (g->must != NULL) + free(g->must); + free((char *)g); +} diff --git a/final/lib/Support/regstrlcpy.c b/final/lib/Support/regstrlcpy.c new file mode 100644 index 00000000000..8b68afdf75f --- /dev/null +++ b/final/lib/Support/regstrlcpy.c @@ -0,0 +1,52 @@ +/* + * This code is derived from OpenBSD's libc, original license follows: + * + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "regex_impl.h" +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +llvm_strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + + return(s - src - 1); /* count does not include NUL */ +} diff --git a/final/lib/Support/regutils.h b/final/lib/Support/regutils.h new file mode 100644 index 00000000000..d0ee100a382 --- /dev/null +++ b/final/lib/Support/regutils.h @@ -0,0 +1,53 @@ +/*- + * This code is derived from OpenBSD's libc/regex, original license follows: + * + * Copyright (c) 1992, 1993, 1994 Henry Spencer. + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Henry Spencer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)utils.h 8.3 (Berkeley) 3/20/94 + */ + +/* utility definitions */ +#define NC (CHAR_MAX - CHAR_MIN + 1) +typedef unsigned char uch; + +/* switch off assertions (if not already off) if no REDEBUG */ +#ifndef REDEBUG +#ifndef NDEBUG +#define NDEBUG /* no assertions please */ +#endif +#endif +#include + +/* for old systems with bcopy() but no memmove() */ +#ifdef USEBCOPY +#define memmove(d, s, c) bcopy(s, d, c) +#endif diff --git a/final/lib/Support/system_error.cpp b/final/lib/Support/system_error.cpp new file mode 100644 index 00000000000..56898de3152 --- /dev/null +++ b/final/lib/Support/system_error.cpp @@ -0,0 +1,130 @@ +//===---------------------- system_error.cpp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This was lifted from libc++ and modified for C++03. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/system_error.h" +#include "llvm/Support/Errno.h" +#include +#include + +namespace llvm { + +// class error_category + +error_category::error_category() { +} + +error_category::~error_category() { +} + +error_condition +error_category::default_error_condition(int ev) const { + return error_condition(ev, *this); +} + +bool +error_category::equivalent(int code, const error_condition& condition) const { + return default_error_condition(code) == condition; +} + +bool +error_category::equivalent(const error_code& code, int condition) const { + return *this == code.category() && code.value() == condition; +} + +std::string +_do_message::message(int ev) const { + return std::string(sys::StrError(ev)); +} + +class _generic_error_category : public _do_message { +public: + virtual const char* name() const; + virtual std::string message(int ev) const; +}; + +const char* +_generic_error_category::name() const { + return "generic"; +} + +std::string +_generic_error_category::message(int ev) const { +#ifdef ELAST + if (ev > ELAST) + return std::string("unspecified generic_category error"); +#endif // ELAST + return _do_message::message(ev); +} + +const error_category& +generic_category() { + static _generic_error_category s; + return s; +} + +class _system_error_category : public _do_message { +public: + virtual const char* name() const; + virtual std::string message(int ev) const; + virtual error_condition default_error_condition(int ev) const; +}; + +const char* +_system_error_category::name() const { + return "system"; +} + +// std::string _system_error_category::message(int ev) const { +// Is in Platform/system_error.inc + +// error_condition _system_error_category::default_error_condition(int ev) const +// Is in Platform/system_error.inc + +const error_category& +system_category() { + static _system_error_category s; + return s; +} + +const error_category& +posix_category() { +#ifdef LLVM_ON_WIN32 + return generic_category(); +#else + return system_category(); +#endif +} + +// error_condition + +std::string +error_condition::message() const { + return _cat_->message(_val_); +} + +// error_code + +std::string +error_code::message() const { + return _cat_->message(_val_); +} + +} // end namespace llvm + +// Include the truly platform-specific parts of this class. +#if defined(LLVM_ON_UNIX) +#include "Unix/system_error.inc" +#endif +#if defined(LLVM_ON_WIN32) +#include "Windows/system_error.inc" +#endif diff --git a/final/lib/Target/ARM/ARM.h b/final/lib/Target/ARM/ARM.h new file mode 100644 index 00000000000..4679f7443bf --- /dev/null +++ b/final/lib/Target/ARM/ARM.h @@ -0,0 +1,63 @@ +//===-- ARM.h - Top-level interface for ARM representation---- --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// ARM back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_ARM_H +#define TARGET_ARM_H + +#include "ARMBaseInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetMachine.h" +#include + +namespace llvm { + +class ARMBaseTargetMachine; +class FunctionPass; +class JITCodeEmitter; +class formatted_raw_ostream; +class MCCodeEmitter; +class TargetAsmBackend; +class MachineInstr; +class ARMAsmPrinter; +class MCInst; + +MCCodeEmitter *createARMMCCodeEmitter(const Target &, + TargetMachine &TM, + MCContext &Ctx); + +TargetAsmBackend *createARMAsmBackend(const Target &, const std::string &); + +FunctionPass *createARMISelDag(ARMBaseTargetMachine &TM, + CodeGenOpt::Level OptLevel); + +FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, + JITCodeEmitter &JCE); + +FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false); +FunctionPass *createARMExpandPseudoPass(); +FunctionPass *createARMGlobalMergePass(const TargetLowering* tli); +FunctionPass *createARMConstantIslandPass(); +FunctionPass *createNEONMoveFixPass(); +FunctionPass *createMLxExpansionPass(); +FunctionPass *createThumb2ITBlockPass(); +FunctionPass *createThumb2SizeReductionPass(); + +extern Target TheARMTarget, TheThumbTarget; + +void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + ARMAsmPrinter &AP); + +} // end namespace llvm; + +#endif diff --git a/final/lib/Target/ARM/ARM.td b/final/lib/Target/ARM/ARM.td new file mode 100644 index 00000000000..bf4315fc6c3 --- /dev/null +++ b/final/lib/Target/ARM/ARM.td @@ -0,0 +1,215 @@ +//===- ARM.td - Describe the ARM Target Machine ------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + + +//===----------------------------------------------------------------------===// +// ARM Subtarget features. +// + +def FeatureVFP2 : SubtargetFeature<"vfp2", "ARMFPUType", "VFPv2", + "Enable VFP2 instructions">; +def FeatureVFP3 : SubtargetFeature<"vfp3", "ARMFPUType", "VFPv3", + "Enable VFP3 instructions">; +def FeatureNEON : SubtargetFeature<"neon", "ARMFPUType", "NEON", + "Enable NEON instructions">; +def FeatureThumb2 : SubtargetFeature<"thumb2", "ThumbMode", "Thumb2", + "Enable Thumb2 instructions">; +def FeatureNoARM : SubtargetFeature<"noarm", "NoARM", "true", + "Does not support ARM mode execution">; +def FeatureFP16 : SubtargetFeature<"fp16", "HasFP16", "true", + "Enable half-precision floating point">; +def FeatureD16 : SubtargetFeature<"d16", "HasD16", "true", + "Restrict VFP3 to 16 double registers">; +def FeatureHWDiv : SubtargetFeature<"hwdiv", "HasHardwareDivide", "true", + "Enable divide instructions">; +def FeatureT2XtPk : SubtargetFeature<"t2xtpk", "HasT2ExtractPack", "true", + "Enable Thumb2 extract and pack instructions">; +def FeatureDB : SubtargetFeature<"db", "HasDataBarrier", "true", + "Has data barrier (dmb / dsb) instructions">; +def FeatureSlowFPBrcc : SubtargetFeature<"slow-fp-brcc", "SlowFPBrcc", "true", + "FP compare + branch is slow">; +def FeatureVFPOnlySP : SubtargetFeature<"fp-only-sp", "FPOnlySP", "true", + "Floating point unit supports single precision only">; + +// Some processors have FP multiply-accumulate instructions that don't +// play nicely with other VFP / NEON instructions, and it's generally better +// to just not use them. +def FeatureHasSlowFPVMLx : SubtargetFeature<"slowfpvmlx", "SlowFPVMLx", "true", + "Disable VFP / NEON MAC instructions">; +// Some processors benefit from using NEON instructions for scalar +// single-precision FP operations. +def FeatureNEONForFP : SubtargetFeature<"neonfp", "UseNEONForSinglePrecisionFP", + "true", + "Use NEON for single precision FP">; + +// Disable 32-bit to 16-bit narrowing for experimentation. +def FeaturePref32BitThumb : SubtargetFeature<"32bit", "Pref32BitThumb", "true", + "Prefer 32-bit Thumb instrs">; + +// Multiprocessing extension. +def FeatureMP : SubtargetFeature<"mp", "HasMPExtension", "true", + "Supports Multiprocessing extension">; + +// ARM architectures. +def ArchV4T : SubtargetFeature<"v4t", "ARMArchVersion", "V4T", + "ARM v4T">; +def ArchV5T : SubtargetFeature<"v5t", "ARMArchVersion", "V5T", + "ARM v5T">; +def ArchV5TE : SubtargetFeature<"v5te", "ARMArchVersion", "V5TE", + "ARM v5TE, v5TEj, v5TExp">; +def ArchV6 : SubtargetFeature<"v6", "ARMArchVersion", "V6", + "ARM v6">; +def ArchV6M : SubtargetFeature<"v6m", "ARMArchVersion", "V6M", + "ARM v6m", + [FeatureNoARM, FeatureDB]>; +def ArchV6T2 : SubtargetFeature<"v6t2", "ARMArchVersion", "V6T2", + "ARM v6t2", + [FeatureThumb2]>; +def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A", + "ARM v7A", + [FeatureThumb2, FeatureNEON, FeatureDB]>; +def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M", + "ARM v7M", + [FeatureThumb2, FeatureNoARM, FeatureDB, + FeatureHWDiv]>; + +//===----------------------------------------------------------------------===// +// ARM Processors supported. +// + +include "ARMSchedule.td" + +// ARM processor families. +def ProcOthers : SubtargetFeature<"others", "ARMProcFamily", "Others", + "One of the other ARM processor families">; +def ProcA8 : SubtargetFeature<"a8", "ARMProcFamily", "CortexA8", + "Cortex-A8 ARM processors", + [FeatureSlowFPBrcc, FeatureNEONForFP, + FeatureHasSlowFPVMLx, FeatureT2XtPk]>; +def ProcA9 : SubtargetFeature<"a9", "ARMProcFamily", "CortexA9", + "Cortex-A9 ARM processors", + [FeatureHasSlowFPVMLx, FeatureT2XtPk, + FeatureFP16]>; + +class ProcNoItin Features> + : Processor; + +// V4 Processors. +def : ProcNoItin<"generic", []>; +def : ProcNoItin<"arm8", []>; +def : ProcNoItin<"arm810", []>; +def : ProcNoItin<"strongarm", []>; +def : ProcNoItin<"strongarm110", []>; +def : ProcNoItin<"strongarm1100", []>; +def : ProcNoItin<"strongarm1110", []>; + +// V4T Processors. +def : ProcNoItin<"arm7tdmi", [ArchV4T]>; +def : ProcNoItin<"arm7tdmi-s", [ArchV4T]>; +def : ProcNoItin<"arm710t", [ArchV4T]>; +def : ProcNoItin<"arm720t", [ArchV4T]>; +def : ProcNoItin<"arm9", [ArchV4T]>; +def : ProcNoItin<"arm9tdmi", [ArchV4T]>; +def : ProcNoItin<"arm920", [ArchV4T]>; +def : ProcNoItin<"arm920t", [ArchV4T]>; +def : ProcNoItin<"arm922t", [ArchV4T]>; +def : ProcNoItin<"arm940t", [ArchV4T]>; +def : ProcNoItin<"ep9312", [ArchV4T]>; + +// V5T Processors. +def : ProcNoItin<"arm10tdmi", [ArchV5T]>; +def : ProcNoItin<"arm1020t", [ArchV5T]>; + +// V5TE Processors. +def : ProcNoItin<"arm9e", [ArchV5TE]>; +def : ProcNoItin<"arm926ej-s", [ArchV5TE]>; +def : ProcNoItin<"arm946e-s", [ArchV5TE]>; +def : ProcNoItin<"arm966e-s", [ArchV5TE]>; +def : ProcNoItin<"arm968e-s", [ArchV5TE]>; +def : ProcNoItin<"arm10e", [ArchV5TE]>; +def : ProcNoItin<"arm1020e", [ArchV5TE]>; +def : ProcNoItin<"arm1022e", [ArchV5TE]>; +def : ProcNoItin<"xscale", [ArchV5TE]>; +def : ProcNoItin<"iwmmxt", [ArchV5TE]>; + +// V6 Processors. +def : Processor<"arm1136j-s", ARMV6Itineraries, [ArchV6]>; +def : Processor<"arm1136jf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2, + FeatureHasSlowFPVMLx]>; +def : Processor<"arm1176jz-s", ARMV6Itineraries, [ArchV6]>; +def : Processor<"arm1176jzf-s", ARMV6Itineraries, [ArchV6, FeatureVFP2, + FeatureHasSlowFPVMLx]>; +def : Processor<"mpcorenovfp", ARMV6Itineraries, [ArchV6]>; +def : Processor<"mpcore", ARMV6Itineraries, [ArchV6, FeatureVFP2, + FeatureHasSlowFPVMLx]>; + +// V6M Processors. +def : Processor<"cortex-m0", ARMV6Itineraries, [ArchV6M]>; + +// V6T2 Processors. +def : Processor<"arm1156t2-s", ARMV6Itineraries, [ArchV6T2]>; +def : Processor<"arm1156t2f-s", ARMV6Itineraries, [ArchV6T2, FeatureVFP2, + FeatureHasSlowFPVMLx]>; + +// V7 Processors. +def : Processor<"cortex-a8", CortexA8Itineraries, + [ArchV7A, ProcA8]>; +def : Processor<"cortex-a9", CortexA9Itineraries, + [ArchV7A, ProcA9]>; + +// V7M Processors. +def : ProcNoItin<"cortex-m3", [ArchV7M]>; +def : ProcNoItin<"cortex-m4", [ArchV7M, FeatureVFP2, FeatureVFPOnlySP]>; + +//===----------------------------------------------------------------------===// +// Register File Description +//===----------------------------------------------------------------------===// + +include "ARMRegisterInfo.td" + +include "ARMCallingConv.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "ARMInstrInfo.td" + +def ARMInstrInfo : InstrInfo; + + +//===----------------------------------------------------------------------===// +// Assembly printer +//===----------------------------------------------------------------------===// +// ARM Uses the MC printer for asm output, so make sure the TableGen +// AsmWriter bits get associated with the correct class. +def ARMAsmWriter : AsmWriter { + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; +} + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def ARM : Target { + // Pull in Instruction Info: + let InstructionSet = ARMInstrInfo; + + let AssemblyWriters = [ARMAsmWriter]; +} diff --git a/final/lib/Target/ARM/ARMAddressingModes.h b/final/lib/Target/ARM/ARMAddressingModes.h new file mode 100644 index 00000000000..19fbf0548b0 --- /dev/null +++ b/final/lib/Target/ARM/ARMAddressingModes.h @@ -0,0 +1,585 @@ +//===- ARMAddressingModes.h - ARM Addressing Modes --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM addressing mode implementation stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_ARMADDRESSINGMODES_H +#define LLVM_TARGET_ARM_ARMADDRESSINGMODES_H + +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/MathExtras.h" +#include + +namespace llvm { + +/// ARM_AM - ARM Addressing Mode Stuff +namespace ARM_AM { + enum ShiftOpc { + no_shift = 0, + asr, + lsl, + lsr, + ror, + rrx + }; + + enum AddrOpc { + add = '+', sub = '-' + }; + + static inline const char *getAddrOpcStr(AddrOpc Op) { + return Op == sub ? "-" : ""; + } + + static inline const char *getShiftOpcStr(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return "asr"; + case ARM_AM::lsl: return "lsl"; + case ARM_AM::lsr: return "lsr"; + case ARM_AM::ror: return "ror"; + case ARM_AM::rrx: return "rrx"; + } + } + + static inline unsigned getShiftOpcEncoding(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return 2; + case ARM_AM::lsl: return 0; + case ARM_AM::lsr: return 1; + case ARM_AM::ror: return 3; + } + } + + static inline ShiftOpc getShiftOpcForNode(SDValue N) { + switch (N.getOpcode()) { + default: return ARM_AM::no_shift; + case ISD::SHL: return ARM_AM::lsl; + case ISD::SRL: return ARM_AM::lsr; + case ISD::SRA: return ARM_AM::asr; + case ISD::ROTR: return ARM_AM::ror; + //case ISD::ROTL: // Only if imm -> turn into ROTR. + // Can't handle RRX here, because it would require folding a flag into + // the addressing mode. :( This causes us to miss certain things. + //case ARMISD::RRX: return ARM_AM::rrx; + } + } + + enum AMSubMode { + bad_am_submode = 0, + ia, + ib, + da, + db + }; + + static inline const char *getAMSubModeStr(AMSubMode Mode) { + switch (Mode) { + default: assert(0 && "Unknown addressing sub-mode!"); + case ARM_AM::ia: return "ia"; + case ARM_AM::ib: return "ib"; + case ARM_AM::da: return "da"; + case ARM_AM::db: return "db"; + } + } + + /// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits. + /// + static inline unsigned rotr32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val >> Amt) | (Val << ((32-Amt)&31)); + } + + /// rotl32 - Rotate a 32-bit unsigned value left by a specified # bits. + /// + static inline unsigned rotl32(unsigned Val, unsigned Amt) { + assert(Amt < 32 && "Invalid rotate amount"); + return (Val << Amt) | (Val >> ((32-Amt)&31)); + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #1: shift_operand with registers + //===--------------------------------------------------------------------===// + // + // This 'addressing mode' is used for arithmetic instructions. It can + // represent things like: + // reg + // reg [asr|lsl|lsr|ror|rrx] reg + // reg [asr|lsl|lsr|ror|rrx] imm + // + // This is stored three operands [rega, regb, opc]. The first is the base + // reg, the second is the shift amount (or reg0 if not present or imm). The + // third operand encodes the shift opcode and the imm if a reg isn't present. + // + static inline unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm) { + return ShOp | (Imm << 3); + } + static inline unsigned getSORegOffset(unsigned Op) { + return Op >> 3; + } + static inline ShiftOpc getSORegShOp(unsigned Op) { + return (ShiftOpc)(Op & 7); + } + + /// getSOImmValImm - Given an encoded imm field for the reg/imm form, return + /// the 8-bit imm value. + static inline unsigned getSOImmValImm(unsigned Imm) { + return Imm & 0xFF; + } + /// getSOImmValRot - Given an encoded imm field for the reg/imm form, return + /// the rotate amount. + static inline unsigned getSOImmValRot(unsigned Imm) { + return (Imm >> 8) * 2; + } + + /// getSOImmValRotate - Try to handle Imm with an immediate shifter operand, + /// computing the rotate amount to use. If this immediate value cannot be + /// handled with a single shifter-op, determine a good rotate amount that will + /// take a maximal chunk of bits out of the immediate. + static inline unsigned getSOImmValRotate(unsigned Imm) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the rotate amount. + unsigned TZ = CountTrailingZeros_32(Imm); + + // Rotate amount must be even. Something like 0x200 must be rotated 8 bits, + // not 9. + unsigned RotAmt = TZ & ~1; + + // If we can handle this spread, return it. + if ((rotr32(Imm, RotAmt) & ~255U) == 0) + return (32-RotAmt)&31; // HW rotates right, not left. + + // For values like 0xF000000F, we should ignore the low 6 bits, then + // retry the hunt. + if (Imm & 63U) { + unsigned TZ2 = CountTrailingZeros_32(Imm & ~63U); + unsigned RotAmt2 = TZ2 & ~1; + if ((rotr32(Imm, RotAmt2) & ~255U) == 0) + return (32-RotAmt2)&31; // HW rotates right, not left. + } + + // Otherwise, we have no way to cover this span of bits with a single + // shifter_op immediate. Return a chunk of bits that will be useful to + // handle. + return (32-RotAmt)&31; // HW rotates right, not left. + } + + /// getSOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into an shifter_operand immediate operand, return the 12-bit encoding for + /// it. If not, return -1. + static inline int getSOImmVal(unsigned Arg) { + // 8-bit (or less) immediates are trivially shifter_operands with a rotate + // of zero. + if ((Arg & ~255U) == 0) return Arg; + + unsigned RotAmt = getSOImmValRotate(Arg); + + // If this cannot be handled with a single shifter_op, bail out. + if (rotr32(~255U, RotAmt) & Arg) + return -1; + + // Encode this correctly. + return rotl32(Arg, RotAmt) | ((RotAmt>>1) << 8); + } + + /// isSOImmTwoPartVal - Return true if the specified value can be obtained by + /// or'ing together two SOImmVal's. + static inline bool isSOImmTwoPartVal(unsigned V) { + // If this can be handled with a single shifter_op, bail out. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled with two shifter_op's, accept. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + return V == 0; + } + + /// getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, + /// return the first chunk of it. + static inline unsigned getSOImmTwoPartFirst(unsigned V) { + return rotr32(255U, getSOImmValRotate(V)) & V; + } + + /// getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, + /// return the second chunk of it. + static inline unsigned getSOImmTwoPartSecond(unsigned V) { + // Mask out the first hunk. + V = rotr32(~255U, getSOImmValRotate(V)) & V; + + // Take what's left. + assert(V == (rotr32(255U, getSOImmValRotate(V)) & V)); + return V; + } + + /// getThumbImmValShift - Try to handle Imm with a 8-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImmValShift(unsigned Imm) { + // 8-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~255U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImmShiftedVal - Return true if the specified value can be obtained + /// by left shifting a 8-bit immediate. + static inline bool isThumbImmShiftedVal(unsigned V) { + // If this can be handled with + V = (~255U << getThumbImmValShift(V)) & V; + return V == 0; + } + + /// getThumbImm16ValShift - Try to handle Imm with a 16-bit immediate followed + /// by a left shift. Returns the shift amount to use. + static inline unsigned getThumbImm16ValShift(unsigned Imm) { + // 16-bit (or less) immediates are trivially immediate operand with a shift + // of zero. + if ((Imm & ~65535U) == 0) return 0; + + // Use CTZ to compute the shift amount. + return CountTrailingZeros_32(Imm); + } + + /// isThumbImm16ShiftedVal - Return true if the specified value can be + /// obtained by left shifting a 16-bit immediate. + static inline bool isThumbImm16ShiftedVal(unsigned V) { + // If this can be handled with + V = (~65535U << getThumbImm16ValShift(V)) & V; + return V == 0; + } + + /// getThumbImmNonShiftedVal - If V is a value that satisfies + /// isThumbImmShiftedVal, return the non-shiftd value. + static inline unsigned getThumbImmNonShiftedVal(unsigned V) { + return V >> getThumbImmValShift(V); + } + + + /// getT2SOImmValSplat - Return the 12-bit encoded representation + /// if the specified value can be obtained by splatting the low 8 bits + /// into every other byte or every byte of a 32-bit value. i.e., + /// 00000000 00000000 00000000 abcdefgh control = 0 + /// 00000000 abcdefgh 00000000 abcdefgh control = 1 + /// abcdefgh 00000000 abcdefgh 00000000 control = 2 + /// abcdefgh abcdefgh abcdefgh abcdefgh control = 3 + /// Return -1 if none of the above apply. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValSplatVal(unsigned V) { + unsigned u, Vs, Imm; + // control = 0 + if ((V & 0xffffff00) == 0) + return V; + + // If the value is zeroes in the first byte, just shift those off + Vs = ((V & 0xff) == 0) ? V >> 8 : V; + // Any passing value only has 8 bits of payload, splatted across the word + Imm = Vs & 0xff; + // Likewise, any passing values have the payload splatted into the 3rd byte + u = Imm | (Imm << 16); + + // control = 1 or 2 + if (Vs == u) + return (((Vs == V) ? 1 : 2) << 8) | Imm; + + // control = 3 + if (Vs == (u | (u << 8))) + return (3 << 8) | Imm; + + return -1; + } + + /// getT2SOImmValRotateVal - Return the 12-bit encoded representation if the + /// specified value is a rotated 8-bit value. Return -1 if no rotation + /// encoding is possible. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmValRotateVal(unsigned V) { + unsigned RotAmt = CountLeadingZeros_32(V); + if (RotAmt >= 24) + return -1; + + // If 'Arg' can be handled with a single shifter_op return the value. + if ((rotr32(0xff000000U, RotAmt) & V) == V) + return (rotr32(V, 24 - RotAmt) & 0x7f) | ((RotAmt + 8) << 7); + + return -1; + } + + /// getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit + /// into a Thumb-2 shifter_operand immediate operand, return the 12-bit + /// encoding for it. If not, return -1. + /// See ARM Reference Manual A6.3.2. + static inline int getT2SOImmVal(unsigned Arg) { + // If 'Arg' is an 8-bit splat, then get the encoded value. + int Splat = getT2SOImmValSplatVal(Arg); + if (Splat != -1) + return Splat; + + // If 'Arg' can be handled with a single shifter_op return the value. + int Rot = getT2SOImmValRotateVal(Arg); + if (Rot != -1) + return Rot; + + return -1; + } + + static inline unsigned getT2SOImmValRotate(unsigned V) { + if ((V & ~255U) == 0) return 0; + // Use CTZ to compute the rotate amount. + unsigned RotAmt = CountTrailingZeros_32(V); + return (32 - RotAmt) & 31; + } + + static inline bool isT2SOImmTwoPartVal (unsigned Imm) { + unsigned V = Imm; + // Passing values can be any combination of splat values and shifter + // values. If this can be handled with a single shifter or splat, bail + // out. Those should be handled directly, not with a two-part val. + if (getT2SOImmValSplatVal(V) != -1) + return false; + V = rotr32 (~255U, getT2SOImmValRotate(V)) & V; + if (V == 0) + return false; + + // If this can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Likewise, try masking out a splat value first. + V = Imm; + if (getT2SOImmValSplatVal(V & 0xff00ff00U) != -1) + V &= ~0xff00ff00U; + else if (getT2SOImmValSplatVal(V & 0x00ff00ffU) != -1) + V &= ~0x00ff00ffU; + // If what's left can be handled as an immediate, accept. + if (getT2SOImmVal(V) != -1) return true; + + // Otherwise, do not accept. + return false; + } + + static inline unsigned getT2SOImmTwoPartFirst(unsigned Imm) { + assert (isT2SOImmTwoPartVal(Imm) && + "Immedate cannot be encoded as two part immediate!"); + // Try a shifter operand as one part + unsigned V = rotr32 (~255, getT2SOImmValRotate(Imm)) & Imm; + // If the rest is encodable as an immediate, then return it. + if (getT2SOImmVal(V) != -1) return V; + + // Try masking out a splat value first. + if (getT2SOImmValSplatVal(Imm & 0xff00ff00U) != -1) + return Imm & 0xff00ff00U; + + // The other splat is all that's left as an option. + assert (getT2SOImmValSplatVal(Imm & 0x00ff00ffU) != -1); + return Imm & 0x00ff00ffU; + } + + static inline unsigned getT2SOImmTwoPartSecond(unsigned Imm) { + // Mask out the first hunk + Imm ^= getT2SOImmTwoPartFirst(Imm); + // Return what's left + assert (getT2SOImmVal(Imm) != -1 && + "Unable to encode second part of T2 two part SO immediate"); + return Imm; + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #2 + //===--------------------------------------------------------------------===// + // + // This is used for most simple load/store instructions. + // + // addrmode2 := reg +/- reg shop imm + // addrmode2 := reg +/- imm12 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 12, the immediate in bits 0-11, and the shift op in 13-15. + // + // If this addressing mode is a frame index (before prolog/epilog insertion + // and code rewriting), this operand will have the form: FI#, reg0, + // with no shift amount for the frame offset. + // + static inline unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO) { + assert(Imm12 < (1 << 12) && "Imm too large!"); + bool isSub = Opc == sub; + return Imm12 | ((int)isSub << 12) | (SO << 13); + } + static inline unsigned getAM2Offset(unsigned AM2Opc) { + return AM2Opc & ((1 << 12)-1); + } + static inline AddrOpc getAM2Op(unsigned AM2Opc) { + return ((AM2Opc >> 12) & 1) ? sub : add; + } + static inline ShiftOpc getAM2ShiftOpc(unsigned AM2Opc) { + return (ShiftOpc)(AM2Opc >> 13); + } + + + //===--------------------------------------------------------------------===// + // Addressing Mode #3 + //===--------------------------------------------------------------------===// + // + // This is used for sign-extending loads, and load/store-pair instructions. + // + // addrmode3 := reg +/- reg + // addrmode3 := reg +/- imm8 + // + // The first operand is always a Reg. The second operand is a reg if in + // reg/reg form, otherwise it's reg#0. The third field encodes the operation + // in bit 8, the immediate in bits 0-7. + + /// getAM3Opc - This function encodes the addrmode3 opc field. + static inline unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset; + } + static inline unsigned char getAM3Offset(unsigned AM3Opc) { + return AM3Opc & 0xFF; + } + static inline AddrOpc getAM3Op(unsigned AM3Opc) { + return ((AM3Opc >> 8) & 1) ? sub : add; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #4 + //===--------------------------------------------------------------------===// + // + // This is used for load / store multiple instructions. + // + // addrmode4 := reg, + // + // The four modes are: + // IA - Increment after + // IB - Increment before + // DA - Decrement after + // DB - Decrement before + // For VFP instructions, only the IA and DB modes are valid. + + static inline AMSubMode getAM4SubMode(unsigned Mode) { + return (AMSubMode)(Mode & 0x7); + } + + static inline unsigned getAM4ModeImm(AMSubMode SubMode) { + return (int)SubMode; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #5 + //===--------------------------------------------------------------------===// + // + // This is used for coprocessor instructions, such as FP load/stores. + // + // addrmode5 := reg +/- imm8*4 + // + // The first operand is always a Reg. The second operand encodes the + // operation in bit 8 and the immediate in bits 0-7. + + /// getAM5Opc - This function encodes the addrmode5 opc field. + static inline unsigned getAM5Opc(AddrOpc Opc, unsigned char Offset) { + bool isSub = Opc == sub; + return ((int)isSub << 8) | Offset; + } + static inline unsigned char getAM5Offset(unsigned AM5Opc) { + return AM5Opc & 0xFF; + } + static inline AddrOpc getAM5Op(unsigned AM5Opc) { + return ((AM5Opc >> 8) & 1) ? sub : add; + } + + //===--------------------------------------------------------------------===// + // Addressing Mode #6 + //===--------------------------------------------------------------------===// + // + // This is used for NEON load / store instructions. + // + // addrmode6 := reg with optional alignment + // + // This is stored in two operands [regaddr, align]. The first is the + // address register. The second operand is the value of the alignment + // specifier in bytes or zero if no explicit alignment. + // Valid alignments depend on the specific instruction. + + //===--------------------------------------------------------------------===// + // NEON Modified Immediates + //===--------------------------------------------------------------------===// + // + // Several NEON instructions (e.g., VMOV) take a "modified immediate" + // vector operand, where a small immediate encoded in the instruction + // specifies a full NEON vector value. These modified immediates are + // represented here as encoded integers. The low 8 bits hold the immediate + // value; bit 12 holds the "Op" field of the instruction, and bits 11-8 hold + // the "Cmode" field of the instruction. The interfaces below treat the + // Op and Cmode values as a single 5-bit value. + + static inline unsigned createNEONModImm(unsigned OpCmode, unsigned Val) { + return (OpCmode << 8) | Val; + } + static inline unsigned getNEONModImmOpCmode(unsigned ModImm) { + return (ModImm >> 8) & 0x1f; + } + static inline unsigned getNEONModImmVal(unsigned ModImm) { + return ModImm & 0xff; + } + + /// decodeNEONModImm - Decode a NEON modified immediate value into the + /// element value and the element size in bits. (If the element size is + /// smaller than the vector, it is splatted into all the elements.) + static inline uint64_t decodeNEONModImm(unsigned ModImm, unsigned &EltBits) { + unsigned OpCmode = getNEONModImmOpCmode(ModImm); + unsigned Imm8 = getNEONModImmVal(ModImm); + uint64_t Val = 0; + + if (OpCmode == 0xe) { + // 8-bit vector elements + Val = Imm8; + EltBits = 8; + } else if ((OpCmode & 0xc) == 0x8) { + // 16-bit vector elements + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 16; + } else if ((OpCmode & 0x8) == 0) { + // 32-bit vector elements, zero with one byte set + unsigned ByteNum = (OpCmode & 0x6) >> 1; + Val = Imm8 << (8 * ByteNum); + EltBits = 32; + } else if ((OpCmode & 0xe) == 0xc) { + // 32-bit vector elements, one byte with low bits set + unsigned ByteNum = 1 + (OpCmode & 0x1); + Val = (Imm8 << (8 * ByteNum)) | (0xffff >> (8 * (2 - ByteNum))); + EltBits = 32; + } else if (OpCmode == 0x1e) { + // 64-bit vector elements + for (unsigned ByteNum = 0; ByteNum < 8; ++ByteNum) { + if ((ModImm >> ByteNum) & 1) + Val |= (uint64_t)0xff << (8 * ByteNum); + } + EltBits = 64; + } else { + assert(false && "Unsupported NEON immediate"); + } + return Val; + } + + AMSubMode getLoadStoreMultipleSubMode(int Opcode); + +} // end namespace ARM_AM +} // end namespace llvm + +#endif + diff --git a/final/lib/Target/ARM/ARMAsmBackend.cpp b/final/lib/Target/ARM/ARMAsmBackend.cpp new file mode 100644 index 00000000000..ec23449d7d4 --- /dev/null +++ b/final/lib/Target/ARM/ARMAsmBackend.cpp @@ -0,0 +1,512 @@ +//===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ELF.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetAsmBackend.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +namespace { +class ARMMachObjectWriter : public MCMachObjectTargetWriter { +public: + ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, + uint32_t CPUSubtype) + : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, + /*UseAggressiveSymbolFolding=*/true) {} +}; + +class ARMELFObjectWriter : public MCELFObjectTargetWriter { +public: + ARMELFObjectWriter(Triple::OSType OSType) + : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSType, ELF::EM_ARM, + /*HasRelocationAddend*/ false) {} +}; + +class ARMAsmBackend : public TargetAsmBackend { + bool isThumbMode; // Currently emitting Thumb code. +public: + ARMAsmBackend(const Target &T) : TargetAsmBackend(), isThumbMode(false) {} + + unsigned getNumFixupKinds() const { return ARM::NumTargetFixupKinds; } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[ARM::NumTargetFixupKinds] = { +// This table *must* be in the order that the fixup_* kinds are defined in +// ARMFixupKinds.h. +// +// Name Offset (bits) Size (bits) Flags +{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_thumb_adr_pcrel_10",0, 8, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel | + MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, +{ "fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_blx", 7, 21, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_thumb_bcc", 1, 8, MCFixupKindInfo::FKF_IsPCRel }, +// movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16 - 19. +{ "fixup_arm_movt_hi16", 0, 20, 0 }, +{ "fixup_arm_movw_lo16", 0, 20, 0 }, +{ "fixup_t2_movt_hi16", 0, 20, 0 }, +{ "fixup_t2_movw_lo16", 0, 20, 0 }, +{ "fixup_arm_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_arm_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_movt_hi16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, +{ "fixup_t2_movw_lo16_pcrel", 0, 20, MCFixupKindInfo::FKF_IsPCRel }, + }; + + if (Kind < FirstTargetFixupKind) + return TargetAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; + } + + bool MayNeedRelaxation(const MCInst &Inst) const; + + void RelaxInstruction(const MCInst &Inst, MCInst &Res) const; + + bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const; + + void HandleAssemblerFlag(MCAssemblerFlag Flag) { + switch (Flag) { + default: break; + case MCAF_Code16: + setIsThumb(true); + break; + case MCAF_Code32: + setIsThumb(false); + break; + } + } + + unsigned getPointerSize() const { return 4; } + bool isThumb() const { return isThumbMode; } + void setIsThumb(bool it) { isThumbMode = it; } +}; +} // end anonymous namespace + +bool ARMAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { + // FIXME: Thumb targets, different move constant targets.. + return false; +} + +void ARMAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { + assert(0 && "ARMAsmBackend::RelaxInstruction() unimplemented"); + return; +} + +bool ARMAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { + if (isThumb()) { + // FIXME: 0xbf00 is the ARMv7 value. For v6 and before, we'll need to + // use 0x46c0 (which is a 'mov r8, r8' insn). + uint64_t NumNops = Count / 2; + for (uint64_t i = 0; i != NumNops; ++i) + OW->Write16(0xbf00); + if (Count & 1) + OW->Write8(0); + return true; + } + // ARM mode + uint64_t NumNops = Count / 4; + for (uint64_t i = 0; i != NumNops; ++i) + OW->Write32(0xe1a00000); + switch (Count % 4) { + default: break; // No leftover bytes to write + case 1: OW->Write8(0); break; + case 2: OW->Write16(0); break; + case 3: OW->Write16(0); OW->Write8(0xa0); break; + } + + return true; +} + +static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + return Value; + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movt_hi16_pcrel: + Value >>= 16; + // Fallthrough + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movw_lo16_pcrel: { + unsigned Hi4 = (Value & 0xF000) >> 12; + unsigned Lo12 = Value & 0x0FFF; + // inst{19-16} = Hi4; + // inst{11-0} = Lo12; + Value = (Hi4 << 16) | (Lo12); + return Value; + } + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movt_hi16_pcrel: + Value >>= 16; + // Fallthrough + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movw_lo16_pcrel: { + unsigned Hi4 = (Value & 0xF000) >> 12; + unsigned i = (Value & 0x800) >> 11; + unsigned Mid3 = (Value & 0x700) >> 8; + unsigned Lo8 = Value & 0x0FF; + // inst{19-16} = Hi4; + // inst{26} = i; + // inst{14-12} = Mid3; + // inst{7-0} = Lo8; + Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); + + uint64_t swapped = (Value & 0xFFFF0000) >> 16; + swapped |= (Value & 0x0000FFFF) << 16; + return swapped; + } + case ARM::fixup_arm_ldst_pcrel_12: + // ARM PC-relative values are offset by 8. + Value -= 4; + // FALLTHROUGH + case ARM::fixup_t2_ldst_pcrel_12: { + // Offset by 4, adjusted by two due to the half-word ordering of thumb. + Value -= 4; + bool isAdd = true; + if ((int64_t)Value < 0) { + Value = -Value; + isAdd = false; + } + assert ((Value < 4096) && "Out of range pc-relative fixup value!"); + Value |= isAdd << 23; + + // Same addressing mode as fixup_arm_pcrel_10, + // but with 16-bit halfwords swapped. + if (Kind == ARM::fixup_t2_ldst_pcrel_12) { + uint64_t swapped = (Value & 0xFFFF0000) >> 16; + swapped |= (Value & 0x0000FFFF) << 16; + return swapped; + } + + return Value; + } + case ARM::fixup_thumb_adr_pcrel_10: + return ((Value - 4) >> 2) & 0xff; + case ARM::fixup_arm_adr_pcrel_12: { + // ARM PC-relative values are offset by 8. + Value -= 8; + unsigned opc = 4; // bits {24-21}. Default to add: 0b0100 + if ((int64_t)Value < 0) { + Value = -Value; + opc = 2; // 0b0010 + } + assert(ARM_AM::getSOImmVal(Value) != -1 && + "Out of range pc-relative fixup value!"); + // Encode the immediate and shift the opcode into place. + return ARM_AM::getSOImmVal(Value) | (opc << 21); + } + + case ARM::fixup_t2_adr_pcrel_12: { + Value -= 4; + unsigned opc = 0; + if ((int64_t)Value < 0) { + Value = -Value; + opc = 5; + } + + uint32_t out = (opc << 21); + out |= (Value & 0x800) << 14; + out |= (Value & 0x700) << 4; + out |= (Value & 0x0FF); + + uint64_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } + + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + // These values don't encode the low two bits since they're always zero. + // Offset by 8 just as above. + return 0xffffff & ((Value - 8) >> 2); + case ARM::fixup_t2_uncondbranch: { + Value = Value - 4; + Value >>= 1; // Low bit is not encoded. + + uint32_t out = 0; + bool I = Value & 0x800000; + bool J1 = Value & 0x400000; + bool J2 = Value & 0x200000; + J1 ^= I; + J2 ^= I; + + out |= I << 26; // S bit + out |= !J1 << 13; // J1 bit + out |= !J2 << 11; // J2 bit + out |= (Value & 0x1FF800) << 5; // imm6 field + out |= (Value & 0x0007FF); // imm11 field + + uint64_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } + case ARM::fixup_t2_condbranch: { + Value = Value - 4; + Value >>= 1; // Low bit is not encoded. + + uint64_t out = 0; + out |= (Value & 0x80000) << 7; // S bit + out |= (Value & 0x40000) >> 7; // J2 bit + out |= (Value & 0x20000) >> 4; // J1 bit + out |= (Value & 0x1F800) << 5; // imm6 field + out |= (Value & 0x007FF); // imm11 field + + uint32_t swapped = (out & 0xFFFF0000) >> 16; + swapped |= (out & 0x0000FFFF) << 16; + return swapped; + } + case ARM::fixup_arm_thumb_bl: { + // The value doesn't encode the low bit (always zero) and is offset by + // four. The value is encoded into disjoint bit positions in the destination + // opcode. x = unchanged, I = immediate value bit, S = sign extension bit + // + // BL: xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII + // + // Note that the halfwords are stored high first, low second; so we need + // to transpose the fixup value here to map properly. + unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0; + uint32_t Binary = 0; + Value = 0x3fffff & ((Value - 4) >> 1); + Binary = (Value & 0x7ff) << 16; // Low imm11 value. + Binary |= (Value & 0x1ffc00) >> 11; // High imm10 value. + Binary |= isNeg << 10; // Sign bit. + return Binary; + } + case ARM::fixup_arm_thumb_blx: { + // The value doesn't encode the low two bits (always zero) and is offset by + // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit + // positions in the destination opcode. x = unchanged, I = immediate value + // bit, S = sign extension bit, 0 = zero. + // + // BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0 + // + // Note that the halfwords are stored high first, low second; so we need + // to transpose the fixup value here to map properly. + unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0; + uint32_t Binary = 0; + Value = 0xfffff & ((Value - 2) >> 2); + Binary = (Value & 0x3ff) << 17; // Low imm10L value. + Binary |= (Value & 0xffc00) >> 10; // High imm10H value. + Binary |= isNeg << 10; // Sign bit. + return Binary; + } + case ARM::fixup_arm_thumb_cp: + // Offset by 4, and don't encode the low two bits. Two bytes of that + // 'off by 4' is implicitly handled by the half-word ordering of the + // Thumb encoding, so we only need to adjust by 2 here. + return ((Value - 2) >> 2) & 0xff; + case ARM::fixup_arm_thumb_cb: { + // Offset by 4 and don't encode the lower bit, which is always 0. + uint32_t Binary = (Value - 4) >> 1; + return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); + } + case ARM::fixup_arm_thumb_br: + // Offset by 4 and don't encode the lower bit, which is always 0. + return ((Value - 4) >> 1) & 0x7ff; + case ARM::fixup_arm_thumb_bcc: + // Offset by 4 and don't encode the lower bit, which is always 0. + return ((Value - 4) >> 1) & 0xff; + case ARM::fixup_arm_pcrel_10: + Value = Value - 4; // ARM fixups offset by an additional word and don't + // need to adjust for the half-word ordering. + // Fall through. + case ARM::fixup_t2_pcrel_10: { + // Offset by 4, adjusted by two due to the half-word ordering of thumb. + Value = Value - 4; + bool isAdd = true; + if ((int64_t)Value < 0) { + Value = -Value; + isAdd = false; + } + // These values don't encode the low two bits since they're always zero. + Value >>= 2; + assert ((Value < 256) && "Out of range pc-relative fixup value!"); + Value |= isAdd << 23; + + // Same addressing mode as fixup_arm_pcrel_10, + // but with 16-bit halfwords swapped. + if (Kind == ARM::fixup_t2_pcrel_10) { + uint32_t swapped = (Value & 0xFFFF0000) >> 16; + swapped |= (Value & 0x0000FFFF) << 16; + return swapped; + } + + return Value; + } + } +} + +namespace { + +// FIXME: This should be in a separate file. +// ELF is an ELF of course... +class ELFARMAsmBackend : public ARMAsmBackend { +public: + Triple::OSType OSType; + ELFARMAsmBackend(const Target &T, Triple::OSType _OSType) + : ARMAsmBackend(T), OSType(_OSType) { } + + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const; + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createELFObjectWriter(new ARMELFObjectWriter(OSType), OS, + /*IsLittleEndian*/ true); + } +}; + +// FIXME: Raise this to share code between Darwin and ELF. +void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value) const { + unsigned NumBytes = 4; // FIXME: 2 for Thumb + Value = adjustFixupValue(Fixup.getKind(), Value); + if (!Value) return; // Doesn't change encoding. + + unsigned Offset = Fixup.getOffset(); + assert(Offset % NumBytes == 0 && "Offset mod NumBytes is nonzero!"); + + // For each byte of the fragment that the fixup touches, mask in the bits from + // the fixup value. The Value has been "split up" into the appropriate + // bitfields above. + for (unsigned i = 0; i != NumBytes; ++i) + Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); +} + +// FIXME: This should be in a separate file. +class DarwinARMAsmBackend : public ARMAsmBackend { +public: + DarwinARMAsmBackend(const Target &T) : ARMAsmBackend(T) { } + + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value) const; + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + // FIXME: Subtarget info should be derived. Force v7 for now. + return createMachObjectWriter(new ARMMachObjectWriter( + /*Is64Bit=*/false, + object::mach::CTM_ARM, + object::mach::CSARM_V7), + OS, + /*IsLittleEndian=*/true); + } + + virtual bool doesSectionRequireSymbols(const MCSection &Section) const { + return false; + } +}; + +/// getFixupKindNumBytes - The number of bytes the fixup may change. +static unsigned getFixupKindNumBytes(unsigned Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + case ARM::fixup_arm_thumb_bcc: + case ARM::fixup_arm_thumb_cp: + case ARM::fixup_thumb_adr_pcrel_10: + return 1; + + case FK_Data_2: + case ARM::fixup_arm_thumb_br: + case ARM::fixup_arm_thumb_cb: + return 2; + + case ARM::fixup_arm_ldst_pcrel_12: + case ARM::fixup_arm_pcrel_10: + case ARM::fixup_arm_adr_pcrel_12: + case ARM::fixup_arm_condbranch: + case ARM::fixup_arm_uncondbranch: + return 3; + + case FK_Data_4: + case ARM::fixup_t2_ldst_pcrel_12: + case ARM::fixup_t2_condbranch: + case ARM::fixup_t2_uncondbranch: + case ARM::fixup_t2_pcrel_10: + case ARM::fixup_t2_adr_pcrel_12: + case ARM::fixup_arm_thumb_bl: + case ARM::fixup_arm_thumb_blx: + case ARM::fixup_arm_movt_hi16: + case ARM::fixup_arm_movw_lo16: + case ARM::fixup_arm_movt_hi16_pcrel: + case ARM::fixup_arm_movw_lo16_pcrel: + case ARM::fixup_t2_movt_hi16: + case ARM::fixup_t2_movw_lo16: + case ARM::fixup_t2_movt_hi16_pcrel: + case ARM::fixup_t2_movw_lo16_pcrel: + return 4; + } +} + +void DarwinARMAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value) const { + unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); + Value = adjustFixupValue(Fixup.getKind(), Value); + if (!Value) return; // Doesn't change encoding. + + unsigned Offset = Fixup.getOffset(); + assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); + + // For each byte of the fragment that the fixup touches, mask in the + // bits from the fixup value. + for (unsigned i = 0; i != NumBytes; ++i) + Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); +} + +} // end anonymous namespace + +TargetAsmBackend *llvm::createARMAsmBackend(const Target &T, + const std::string &TT) { + switch (Triple(TT).getOS()) { + case Triple::Darwin: + return new DarwinARMAsmBackend(T); + case Triple::MinGW32: + case Triple::Cygwin: + case Triple::Win32: + assert(0 && "Windows not supported on ARM"); + default: + return new ELFARMAsmBackend(T, Triple(TT).getOS()); + } +} diff --git a/final/lib/Target/ARM/ARMAsmPrinter.cpp b/final/lib/Target/ARM/ARMAsmPrinter.cpp new file mode 100644 index 00000000000..e1a2cc57abf --- /dev/null +++ b/final/lib/Target/ARM/ARMAsmPrinter.cpp @@ -0,0 +1,1725 @@ +//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format ARM assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "ARM.h" +#include "ARMAsmPrinter.h" +#include "ARMAddressingModes.h" +#include "ARMBuildAttrs.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMConstantPoolValue.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMMCExpr.h" +#include "ARMTargetMachine.h" +#include "ARMTargetObjectFile.h" +#include "InstPrinter/ARMInstPrinter.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Constants.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +namespace { + + // Per section and per symbol attributes are not supported. + // To implement them we would need the ability to delay this emission + // until the assembly file is fully parsed/generated as only then do we + // know the symbol and section numbers. + class AttributeEmitter { + public: + virtual void MaybeSwitchVendor(StringRef Vendor) = 0; + virtual void EmitAttribute(unsigned Attribute, unsigned Value) = 0; + virtual void EmitTextAttribute(unsigned Attribute, StringRef String) = 0; + virtual void Finish() = 0; + virtual ~AttributeEmitter() {} + }; + + class AsmAttributeEmitter : public AttributeEmitter { + MCStreamer &Streamer; + + public: + AsmAttributeEmitter(MCStreamer &Streamer_) : Streamer(Streamer_) {} + void MaybeSwitchVendor(StringRef Vendor) { } + + void EmitAttribute(unsigned Attribute, unsigned Value) { + Streamer.EmitRawText("\t.eabi_attribute " + + Twine(Attribute) + ", " + Twine(Value)); + } + + void EmitTextAttribute(unsigned Attribute, StringRef String) { + switch (Attribute) { + case ARMBuildAttrs::CPU_name: + Streamer.EmitRawText(StringRef("\t.cpu ") + LowercaseString(String)); + break; + /* GAS requires .fpu to be emitted regardless of EABI attribute */ + case ARMBuildAttrs::Advanced_SIMD_arch: + case ARMBuildAttrs::VFP_arch: + Streamer.EmitRawText(StringRef("\t.fpu ") + LowercaseString(String)); + break; + default: assert(0 && "Unsupported Text attribute in ASM Mode"); break; + } + } + void Finish() { } + }; + + class ObjectAttributeEmitter : public AttributeEmitter { + MCObjectStreamer &Streamer; + StringRef CurrentVendor; + SmallString<64> Contents; + + public: + ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : + Streamer(Streamer_), CurrentVendor("") { } + + void MaybeSwitchVendor(StringRef Vendor) { + assert(!Vendor.empty() && "Vendor cannot be empty."); + + if (CurrentVendor.empty()) + CurrentVendor = Vendor; + else if (CurrentVendor == Vendor) + return; + else + Finish(); + + CurrentVendor = Vendor; + + assert(Contents.size() == 0); + } + + void EmitAttribute(unsigned Attribute, unsigned Value) { + // FIXME: should be ULEB + Contents += Attribute; + Contents += Value; + } + + void EmitTextAttribute(unsigned Attribute, StringRef String) { + Contents += Attribute; + Contents += UppercaseString(String); + Contents += 0; + } + + void Finish() { + const size_t ContentsSize = Contents.size(); + + // Vendor size + Vendor name + '\0' + const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; + + // Tag + Tag Size + const size_t TagHeaderSize = 1 + 4; + + Streamer.EmitIntValue(VendorHeaderSize + TagHeaderSize + ContentsSize, 4); + Streamer.EmitBytes(CurrentVendor, 0); + Streamer.EmitIntValue(0, 1); // '\0' + + Streamer.EmitIntValue(ARMBuildAttrs::File, 1); + Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); + + Streamer.EmitBytes(Contents, 0); + + Contents.clear(); + } + }; + +} // end of anonymous namespace + +MachineLocation ARMAsmPrinter:: +getDebugValueLocation(const MachineInstr *MI) const { + MachineLocation Location; + assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); + // Frame address. Currently handles register +- offset only. + if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) + Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); + else { + DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); + } + return Location; +} + +void ARMAsmPrinter::EmitFunctionEntryLabel() { + if (AFI->isThumbFunction()) { + OutStreamer.EmitAssemblerFlag(MCAF_Code16); + OutStreamer.EmitThumbFunc(Subtarget->isTargetDarwin()? CurrentFnSym : 0); + } + + OutStreamer.EmitLabel(CurrentFnSym); +} + +/// runOnMachineFunction - This uses the EmitInstruction() +/// method to print assembly for each instruction. +/// +bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { + AFI = MF.getInfo(); + MCP = MF.getConstantPool(); + + return AsmPrinter::runOnMachineFunction(MF); +} + +void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + unsigned TF = MO.getTargetFlags(); + + switch (MO.getType()) { + default: + assert(0 && ""); + case MachineOperand::MO_Register: { + unsigned Reg = MO.getReg(); + assert(TargetRegisterInfo::isPhysicalRegister(Reg)); + assert(!MO.getSubReg() && "Subregs should be eliminated!"); + O << ARMInstPrinter::getRegisterName(Reg); + break; + } + case MachineOperand::MO_Immediate: { + int64_t Imm = MO.getImm(); + O << '#'; + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF == ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF == ARMII::MO_HI16)) + O << ":upper16:"; + O << Imm; + break; + } + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: { + const GlobalValue *GV = MO.getGlobal(); + if ((Modifier && strcmp(Modifier, "lo16") == 0) || + (TF & ARMII::MO_LO16)) + O << ":lower16:"; + else if ((Modifier && strcmp(Modifier, "hi16") == 0) || + (TF & ARMII::MO_HI16)) + O << ":upper16:"; + O << *Mang->getSymbol(GV); + + printOffset(MO.getOffset(), O); + if (TF == ARMII::MO_PLT) + O << "(PLT)"; + break; + } + case MachineOperand::MO_ExternalSymbol: { + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + if (TF == ARMII::MO_PLT) + O << "(PLT)"; + break; + } + case MachineOperand::MO_ConstantPoolIndex: + O << *GetCPISymbol(MO.getIndex()); + break; + case MachineOperand::MO_JumpTableIndex: + O << *GetJTISymbol(MO.getIndex()); + break; + } +} + +//===--------------------------------------------------------------------===// + +MCSymbol *ARMAsmPrinter:: +GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << getFunctionNumber() << '_' << uid << '_' << uid2 + << "_set_" << MBB->getNumber(); + return OutContext.GetOrCreateSymbol(Name.str()); +} + +MCSymbol *ARMAsmPrinter:: +GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI" + << getFunctionNumber() << '_' << uid << '_' << uid2; + return OutContext.GetOrCreateSymbol(Name.str()); +} + + +MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel(void) const { + SmallString<60> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "SJLJEH" + << getFunctionNumber(); + return OutContext.GetOrCreateSymbol(Name.str()); +} + +bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O) { + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: return true; // Unknown modifier. + case 'a': // Print as a memory address. + if (MI->getOperand(OpNum).isReg()) { + O << "[" + << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()) + << "]"; + return false; + } + // Fallthrough + case 'c': // Don't print "#" before an immediate operand. + if (!MI->getOperand(OpNum).isImm()) + return true; + O << MI->getOperand(OpNum).getImm(); + return false; + case 'P': // Print a VFP double precision register. + case 'q': // Print a NEON quad precision register. + printOperand(MI, OpNum, O); + return false; + case 'Q': + case 'R': + case 'H': + // These modifiers are not yet supported. + return true; + } + } + + printOperand(MI, OpNum, O); + return false; +} + +bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNum, unsigned AsmVariant, + const char *ExtraCode, + raw_ostream &O) { + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isReg() && "unexpected inline asm memory operand"); + O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; + return false; +} + +void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + Reloc::Model RelocM = TM.getRelocationModel(); + if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) { + // Declare all the text sections up front (before the DWARF sections + // emitted by AsmPrinter::doInitialization) so the assembler will keep + // them together at the beginning of the object file. This helps + // avoid out-of-range branches that are due a fundamental limitation of + // the way symbol offsets are encoded with the current Darwin ARM + // relocations. + const TargetLoweringObjectFileMachO &TLOFMacho = + static_cast( + getObjFileLowering()); + OutStreamer.SwitchSection(TLOFMacho.getTextSection()); + OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection()); + OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection()); + if (RelocM == Reloc::DynamicNoPIC) { + const MCSection *sect = + OutContext.getMachOSection("__TEXT", "__symbol_stub4", + MCSectionMachO::S_SYMBOL_STUBS, + 12, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } else { + const MCSection *sect = + OutContext.getMachOSection("__TEXT", "__picsymbolstub4", + MCSectionMachO::S_SYMBOL_STUBS, + 16, SectionKind::getText()); + OutStreamer.SwitchSection(sect); + } + const MCSection *StaticInitSect = + OutContext.getMachOSection("__TEXT", "__StaticInit", + MCSectionMachO::S_REGULAR | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + OutStreamer.SwitchSection(StaticInitSect); + } + } + + // Use unified assembler syntax. + OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); + + // Emit ARM Build Attributes + if (Subtarget->isTargetELF()) { + + emitAttributes(); + } +} + + +void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { + if (Subtarget->isTargetDarwin()) { + // All darwin targets use mach-o. + const TargetLoweringObjectFileMachO &TLOFMacho = + static_cast(getObjFileLowering()); + MachineModuleInfoMachO &MMIMacho = + MMI->getObjFileInfo(); + + // Output non-lazy-pointers for external and common global variables. + MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); + + if (!Stubs.empty()) { + // Switch with ".non_lazy_symbol_pointer" directive. + OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); + EmitAlignment(2); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .indirect_symbol _foo + MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second; + OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol); + + if (MCSym.getInt()) + // External to current translation unit. + OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); + else + // Internal to current translation unit. + // + // When we place the LSDA into the TEXT section, the type info + // pointers need to be indirect and pc-rel. We accomplish this by + // using NLPs; however, sometimes the types are local to the file. + // We need to fill in the value for the NLP in those cases. + OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(), + OutContext), + 4/*size*/, 0/*addrspace*/); + } + + Stubs.clear(); + OutStreamer.AddBlankLine(); + } + + Stubs = MMIMacho.GetHiddenGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(getObjFileLowering().getDataSection()); + EmitAlignment(2); + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { + // L_foo$stub: + OutStreamer.EmitLabel(Stubs[i].first); + // .long _foo + OutStreamer.EmitValue(MCSymbolRefExpr:: + Create(Stubs[i].second.getPointer(), + OutContext), + 4/*size*/, 0/*addrspace*/); + } + + Stubs.clear(); + OutStreamer.AddBlankLine(); + } + + // Funny Darwin hack: This flag tells the linker that no global symbols + // contain code that falls through to other global symbols (e.g. the obvious + // implementation of multiple entry points). If this doesn't occur, the + // linker can safely perform dead code stripping. Since LLVM never + // generates code that does this, it is always safe to set. + OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); + } +} + +//===----------------------------------------------------------------------===// +// Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() +// FIXME: +// The following seem like one-off assembler flags, but they actually need +// to appear in the .ARM.attributes section in ELF. +// Instead of subclassing the MCELFStreamer, we do the work here. + +void ARMAsmPrinter::emitAttributes() { + + emitARMAttributeSection(); + + /* GAS expect .fpu to be emitted, regardless of VFP build attribute */ + bool emitFPU = false; + AttributeEmitter *AttrEmitter; + if (OutStreamer.hasRawTextSupport()) { + AttrEmitter = new AsmAttributeEmitter(OutStreamer); + emitFPU = true; + } else { + MCObjectStreamer &O = static_cast(OutStreamer); + AttrEmitter = new ObjectAttributeEmitter(O); + } + + AttrEmitter->MaybeSwitchVendor("aeabi"); + + std::string CPUString = Subtarget->getCPUString(); + + if (CPUString == "cortex-a8" || + Subtarget->isCortexA8()) { + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::CPU_name, "cortex-a8"); + AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v7); + AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch_profile, + ARMBuildAttrs::ApplicationProfile); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, + ARMBuildAttrs::Allowed); + AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, + ARMBuildAttrs::AllowThumb32); + // Fixme: figure out when this is emitted. + //AttrEmitter->EmitAttribute(ARMBuildAttrs::WMMX_arch, + // ARMBuildAttrs::AllowWMMXv1); + // + + /// ADD additional Else-cases here! + } else if (CPUString == "generic") { + // FIXME: Why these defaults? + AttrEmitter->EmitAttribute(ARMBuildAttrs::CPU_arch, ARMBuildAttrs::v4T); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ARM_ISA_use, + ARMBuildAttrs::Allowed); + AttrEmitter->EmitAttribute(ARMBuildAttrs::THUMB_ISA_use, + ARMBuildAttrs::Allowed); + } + + if (Subtarget->hasNEON() && emitFPU) { + /* NEON is not exactly a VFP architecture, but GAS emit one of + * neon/vfpv3/vfpv2 for .fpu parameters */ + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::Advanced_SIMD_arch, "neon"); + /* If emitted for NEON, omit from VFP below, since you can have both + * NEON and VFP in build attributes but only one .fpu */ + emitFPU = false; + } + + /* VFPv3 + .fpu */ + if (Subtarget->hasVFP3()) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, + ARMBuildAttrs::AllowFPv3A); + if (emitFPU) + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv3"); + + /* VFPv2 + .fpu */ + } else if (Subtarget->hasVFP2()) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::VFP_arch, + ARMBuildAttrs::AllowFPv2); + if (emitFPU) + AttrEmitter->EmitTextAttribute(ARMBuildAttrs::VFP_arch, "vfpv2"); + } + + /* TODO: ARMBuildAttrs::Allowed is not completely accurate, + * since NEON can have 1 (allowed) or 2 (fused MAC operations) */ + if (Subtarget->hasNEON()) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::Advanced_SIMD_arch, + ARMBuildAttrs::Allowed); + } + + // Signal various FP modes. + if (!UnsafeFPMath) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_denormal, + ARMBuildAttrs::Allowed); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_exceptions, + ARMBuildAttrs::Allowed); + } + + if (NoInfsFPMath && NoNaNsFPMath) + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, + ARMBuildAttrs::Allowed); + else + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_FP_number_model, + ARMBuildAttrs::AllowIEE754); + + // FIXME: add more flags to ARMBuildAttrs.h + // 8-bytes alignment stuff. + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); + + // Hard float. Use both S and D registers and conform to AAPCS-VFP. + if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); + AttrEmitter->EmitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); + } + // FIXME: Should we signal R9 usage? + + if (Subtarget->hasDivide()) + AttrEmitter->EmitAttribute(ARMBuildAttrs::DIV_use, 1); + + AttrEmitter->Finish(); + delete AttrEmitter; +} + +void ARMAsmPrinter::emitARMAttributeSection() { + // + // [ "vendor-name" + // [ * + // | * 0 * + // | * 0 * + // ]+ + // ]* + + if (OutStreamer.hasRawTextSupport()) + return; + + const ARMElfTargetObjectFile &TLOFELF = + static_cast + (getObjFileLowering()); + + OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); + + // Format version + OutStreamer.EmitIntValue(0x41, 1); +} + +//===----------------------------------------------------------------------===// + +static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, + unsigned LabelId, MCContext &Ctx) { + + MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) + + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); + return Label; +} + +static MCSymbolRefExpr::VariantKind +getModifierVariantKind(ARMCP::ARMCPModifier Modifier) { + switch (Modifier) { + default: llvm_unreachable("Unknown modifier!"); + case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None; + case ARMCP::TLSGD: return MCSymbolRefExpr::VK_ARM_TLSGD; + case ARMCP::TPOFF: return MCSymbolRefExpr::VK_ARM_TPOFF; + case ARMCP::GOTTPOFF: return MCSymbolRefExpr::VK_ARM_GOTTPOFF; + case ARMCP::GOT: return MCSymbolRefExpr::VK_ARM_GOT; + case ARMCP::GOTOFF: return MCSymbolRefExpr::VK_ARM_GOTOFF; + } + return MCSymbolRefExpr::VK_None; +} + +MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV) { + bool isIndirect = Subtarget->isTargetDarwin() && + Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); + if (!isIndirect) + return Mang->getSymbol(GV); + + // FIXME: Remove this when Darwin transition to @GOT like syntax. + MCSymbol *MCSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); + MachineModuleInfoMachO &MMIMachO = + MMI->getObjFileInfo(); + MachineModuleInfoImpl::StubValueTy &StubSym = + GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym) : + MMIMachO.getGVStubEntry(MCSym); + if (StubSym.getPointer() == 0) + StubSym = MachineModuleInfoImpl:: + StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); + return MCSym; +} + +void ARMAsmPrinter:: +EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { + int Size = TM.getTargetData()->getTypeAllocSize(MCPV->getType()); + + ARMConstantPoolValue *ACPV = static_cast(MCPV); + + MCSymbol *MCSym; + if (ACPV->isLSDA()) { + SmallString<128> Str; + raw_svector_ostream OS(Str); + OS << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber(); + MCSym = OutContext.GetOrCreateSymbol(OS.str()); + } else if (ACPV->isBlockAddress()) { + MCSym = GetBlockAddressSymbol(ACPV->getBlockAddress()); + } else if (ACPV->isGlobalValue()) { + const GlobalValue *GV = ACPV->getGV(); + MCSym = GetARMGVSymbol(GV); + } else { + assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); + MCSym = GetExternalSymbolSymbol(ACPV->getSymbol()); + } + + // Create an MCSymbol for the reference. + const MCExpr *Expr = + MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()), + OutContext); + + if (ACPV->getPCAdjustment()) { + MCSymbol *PCLabel = getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), + ACPV->getLabelId(), + OutContext); + const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext); + PCRelExpr = + MCBinaryExpr::CreateAdd(PCRelExpr, + MCConstantExpr::Create(ACPV->getPCAdjustment(), + OutContext), + OutContext); + if (ACPV->mustAddCurrentAddress()) { + // We want "( - .)", but MC doesn't have a concept of the '.' + // label, so just emit a local label end reference that instead. + MCSymbol *DotSym = OutContext.CreateTempSymbol(); + OutStreamer.EmitLabel(DotSym); + const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext); + PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext); + } + Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext); + } + OutStreamer.EmitValue(Expr, Size); +} + +void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) { + unsigned Opcode = MI->getOpcode(); + int OpNum = 1; + if (Opcode == ARM::BR_JTadd) + OpNum = 2; + else if (Opcode == ARM::BR_JTm) + OpNum = 3; + + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id + unsigned JTI = MO1.getIndex(); + + // Emit a label for the jump table. + MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); + OutStreamer.EmitLabel(JTISymbol); + + // Emit each entry of the table. + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + // Construct an MCExpr for the entry. We want a value of the form: + // (BasicBlockAddr - TableBeginAddr) + // + // For example, a table with entries jumping to basic blocks BB0 and BB1 + // would look like: + // LJTI_0_0: + // .word (LBB0 - LJTI_0_0) + // .word (LBB1 - LJTI_0_0) + const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); + + if (TM.getRelocationModel() == Reloc::PIC_) + Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol, + OutContext), + OutContext); + OutStreamer.EmitValue(Expr, 4); + } +} + +void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) { + unsigned Opcode = MI->getOpcode(); + int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1; + const MachineOperand &MO1 = MI->getOperand(OpNum); + const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id + unsigned JTI = MO1.getIndex(); + + // Emit a label for the jump table. + MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm()); + OutStreamer.EmitLabel(JTISymbol); + + // Emit each entry of the table. + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + unsigned OffsetWidth = 4; + if (MI->getOpcode() == ARM::t2TBB_JT) + OffsetWidth = 1; + else if (MI->getOpcode() == ARM::t2TBH_JT) + OffsetWidth = 2; + + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(), + OutContext); + // If this isn't a TBB or TBH, the entries are direct branch instructions. + if (OffsetWidth == 4) { + MCInst BrInst; + BrInst.setOpcode(ARM::t2B); + BrInst.addOperand(MCOperand::CreateExpr(MBBSymbolExpr)); + OutStreamer.EmitInstruction(BrInst); + continue; + } + // Otherwise it's an offset from the dispatch instruction. Construct an + // MCExpr for the entry. We want a value of the form: + // (BasicBlockAddr - TableBeginAddr) / 2 + // + // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 + // would look like: + // LJTI_0_0: + // .byte (LBB0 - LJTI_0_0) / 2 + // .byte (LBB1 - LJTI_0_0) / 2 + const MCExpr *Expr = + MCBinaryExpr::CreateSub(MBBSymbolExpr, + MCSymbolRefExpr::Create(JTISymbol, OutContext), + OutContext); + Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext), + OutContext); + OutStreamer.EmitValue(Expr, OffsetWidth); + } +} + +void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, + raw_ostream &OS) { + unsigned NOps = MI->getNumOperands(); + assert(NOps==4); + OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: "; + // cast away const; DIetc do not take const operands for some reason. + DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata())); + OS << V.getName(); + OS << " <- "; + // Frame address. Currently handles register +- offset only. + assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm()); + OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS); + OS << ']'; + OS << "+"; + printOperand(MI, NOps-2, OS); +} + +static void populateADROperands(MCInst &Inst, unsigned Dest, + const MCSymbol *Label, + unsigned pred, unsigned ccreg, + MCContext &Ctx) { + const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, Ctx); + Inst.addOperand(MCOperand::CreateReg(Dest)); + Inst.addOperand(MCOperand::CreateExpr(SymbolExpr)); + // Add predicate operands. + Inst.addOperand(MCOperand::CreateImm(pred)); + Inst.addOperand(MCOperand::CreateReg(ccreg)); +} + +void ARMAsmPrinter::EmitPatchedInstruction(const MachineInstr *MI, + unsigned Opcode) { + MCInst TmpInst; + + // Emit the instruction as usual, just patch the opcode. + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + TmpInst.setOpcode(Opcode); + OutStreamer.EmitInstruction(TmpInst); +} + +void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { + assert(MI->getFlag(MachineInstr::FrameSetup) && + "Only instruction which are involved into frame setup code are allowed"); + + const MachineFunction &MF = *MI->getParent()->getParent(); + const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + const ARMFunctionInfo &AFI = *MF.getInfo(); + + unsigned FramePtr = RegInfo->getFrameRegister(MF); + unsigned Opc = MI->getOpcode(); + unsigned SrcReg, DstReg; + + if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) { + // Two special cases: + // 1) tPUSH does not have src/dst regs. + // 2) for Thumb1 code we sometimes materialize the constant via constpool + // load. Yes, this is pretty fragile, but for now I don't see better + // way... :( + SrcReg = DstReg = ARM::SP; + } else { + SrcReg = MI->getOperand(1).getReg(); + DstReg = MI->getOperand(0).getReg(); + } + + // Try to figure out the unwinding opcode out of src / dst regs. + if (MI->getDesc().mayStore()) { + // Register saves. + assert(DstReg == ARM::SP && + "Only stack pointer as a destination reg is supported"); + + SmallVector RegList; + // Skip src & dst reg, and pred ops. + unsigned StartOp = 2 + 2; + // Use all the operands. + unsigned NumOffset = 0; + + switch (Opc) { + default: + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + case ARM::tPUSH: + // Special case here: no src & dst reg, but two extra imp ops. + StartOp = 2; NumOffset = 2; + case ARM::STMDB_UPD: + case ARM::t2STMDB_UPD: + case ARM::VSTMDDB_UPD: + assert(SrcReg == ARM::SP && + "Only stack pointer as a source reg is supported"); + for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; + i != NumOps; ++i) + RegList.push_back(MI->getOperand(i).getReg()); + break; + case ARM::STR_PRE: + assert(MI->getOperand(2).getReg() == ARM::SP && + "Only stack pointer as a source reg is supported"); + RegList.push_back(SrcReg); + break; + } + OutStreamer.EmitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); + } else { + // Changes of stack / frame pointer. + if (SrcReg == ARM::SP) { + int64_t Offset = 0; + switch (Opc) { + default: + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + case ARM::MOVr: + case ARM::tMOVgpr2gpr: + case ARM::tMOVgpr2tgpr: + Offset = 0; + break; + case ARM::ADDri: + Offset = -MI->getOperand(2).getImm(); + break; + case ARM::SUBri: + case ARM::t2SUBrSPi: + Offset = MI->getOperand(2).getImm(); + break; + case ARM::tSUBspi: + Offset = MI->getOperand(2).getImm()*4; + break; + case ARM::tADDspi: + case ARM::tADDrSPi: + Offset = -MI->getOperand(2).getImm()*4; + break; + case ARM::tLDRpci: { + // Grab the constpool index and check, whether it corresponds to + // original or cloned constpool entry. + unsigned CPI = MI->getOperand(1).getIndex(); + const MachineConstantPool *MCP = MF.getConstantPool(); + if (CPI >= MCP->getConstants().size()) + CPI = AFI.getOriginalCPIdx(CPI); + assert(CPI != -1U && "Invalid constpool index"); + + // Derive the actual offset. + const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; + assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); + // FIXME: Check for user, it should be "add" instruction! + Offset = -cast(CPE.Val.ConstVal)->getSExtValue(); + break; + } + } + + if (DstReg == FramePtr && FramePtr != ARM::SP) + // Set-up of the frame pointer. Positive values correspond to "add" + // instruction. + OutStreamer.EmitSetFP(FramePtr, ARM::SP, -Offset); + else if (DstReg == ARM::SP) { + // Change of SP by an offset. Positive values correspond to "sub" + // instruction. + OutStreamer.EmitPad(Offset); + } else { + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + } else if (DstReg == ARM::SP) { + // FIXME: .movsp goes here + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + else { + MI->dump(); + assert(0 && "Unsupported opcode for unwinding information"); + } + } +} + +extern cl::opt EnableARMEHABI; + +void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { + unsigned Opc = MI->getOpcode(); + switch (Opc) { + default: break; + case ARM::t2ADDrSPi: + case ARM::t2ADDrSPi12: + case ARM::t2SUBrSPi: + case ARM::t2SUBrSPi12: + assert ((MI->getOperand(1).getReg() == ARM::SP) && + "Unexpected source register!"); + break; + + case ARM::t2MOVi32imm: assert(0 && "Should be lowered by thumb2it pass"); + case ARM::DBG_VALUE: { + if (isVerbose() && OutStreamer.hasRawTextSupport()) { + SmallString<128> TmpStr; + raw_svector_ostream OS(TmpStr); + PrintDebugValueComment(MI, OS); + OutStreamer.EmitRawText(StringRef(OS.str())); + } + return; + } + case ARM::tBfar: { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tBL); + TmpInst.addOperand(MCOperand::CreateExpr(MCSymbolRefExpr::Create( + MI->getOperand(0).getMBB()->getSymbol(), OutContext))); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::LEApcrel: + case ARM::tLEApcrel: + case ARM::t2LEApcrel: { + // FIXME: Need to also handle globals and externals + MCInst TmpInst; + TmpInst.setOpcode(MI->getOpcode() == ARM::t2LEApcrel ? ARM::t2ADR + : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR + : ARM::ADR)); + populateADROperands(TmpInst, MI->getOperand(0).getReg(), + GetCPISymbol(MI->getOperand(1).getIndex()), + MI->getOperand(2).getImm(), MI->getOperand(3).getReg(), + OutContext); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::LEApcrelJT: + case ARM::tLEApcrelJT: + case ARM::t2LEApcrelJT: { + MCInst TmpInst; + TmpInst.setOpcode(MI->getOpcode() == ARM::t2LEApcrelJT ? ARM::t2ADR + : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR + : ARM::ADR)); + populateADROperands(TmpInst, MI->getOperand(0).getReg(), + GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(), + MI->getOperand(2).getImm()), + MI->getOperand(3).getImm(), MI->getOperand(4).getReg(), + OutContext); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::MOVPCRX: { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::BXr9_CALL: + case ARM::BX_CALL: { + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::LR)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::BX); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + OutStreamer.EmitInstruction(TmpInst); + } + return; + } + case ARM::BMOVPCRXr9_CALL: + case ARM::BMOVPCRX_CALL: { + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::LR)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + return; + } + case ARM::MOVi16_ga_pcrel: + case ARM::t2MOVi16_ga_pcrel: { + MCInst TmpInst; + TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + + unsigned TF = MI->getOperand(1).getTargetFlags(); + bool isPIC = TF == ARMII::MO_LO16_NONLAZY_PIC; + const GlobalValue *GV = MI->getOperand(1).getGlobal(); + MCSymbol *GVSym = GetARMGVSymbol(GV); + const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); + if (isPIC) { + MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), + MI->getOperand(2).getImm(), OutContext); + const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); + unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4; + const MCExpr *PCRelExpr = + ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr, + MCBinaryExpr::CreateAdd(LabelSymExpr, + MCConstantExpr::Create(PCAdj, OutContext), + OutContext), OutContext), OutContext); + TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); + } else { + const MCExpr *RefExpr= ARMMCExpr::CreateLower16(GVSymExpr, OutContext); + TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); + } + + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::MOVTi16_ga_pcrel: + case ARM::t2MOVTi16_ga_pcrel: { + MCInst TmpInst; + TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel + ? ARM::MOVTi16 : ARM::t2MOVTi16); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + + unsigned TF = MI->getOperand(2).getTargetFlags(); + bool isPIC = TF == ARMII::MO_HI16_NONLAZY_PIC; + const GlobalValue *GV = MI->getOperand(2).getGlobal(); + MCSymbol *GVSym = GetARMGVSymbol(GV); + const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext); + if (isPIC) { + MCSymbol *LabelSym = getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), + MI->getOperand(3).getImm(), OutContext); + const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext); + unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4; + const MCExpr *PCRelExpr = + ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr, + MCBinaryExpr::CreateAdd(LabelSymExpr, + MCConstantExpr::Create(PCAdj, OutContext), + OutContext), OutContext), OutContext); + TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr)); + } else { + const MCExpr *RefExpr= ARMMCExpr::CreateUpper16(GVSymExpr, OutContext); + TmpInst.addOperand(MCOperand::CreateExpr(RefExpr)); + } + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + return; + } + case ARM::tPICADD: { + // This is a pseudo op for a label + instruction sequence, which looks like: + // LPC0: + // add r0, pc + // This adds the address of LPC0 to r0. + + // Emit the label. + OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), MI->getOperand(2).getImm(), + OutContext)); + + // Form and emit the add. + MCInst AddInst; + AddInst.setOpcode(ARM::tADDhirr); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // Add predicate operands. + AddInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + AddInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(AddInst); + return; + } + case ARM::PICADD: { + // This is a pseudo op for a label + instruction sequence, which looks like: + // LPC0: + // add r0, pc, r0 + // This adds the address of LPC0 to r0. + + // Emit the label. + OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), MI->getOperand(2).getImm(), + OutContext)); + + // Form and emit the add. + MCInst AddInst; + AddInst.setOpcode(ARM::ADDrr); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + AddInst.addOperand(MCOperand::CreateReg(ARM::PC)); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + // Add predicate operands. + AddInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); + AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg())); + // Add 's' bit operand (always reg0 for this) + AddInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(AddInst); + return; + } + case ARM::PICSTR: + case ARM::PICSTRB: + case ARM::PICSTRH: + case ARM::PICLDR: + case ARM::PICLDRB: + case ARM::PICLDRH: + case ARM::PICLDRSB: + case ARM::PICLDRSH: { + // This is a pseudo op for a label + instruction sequence, which looks like: + // LPC0: + // OP r0, [pc, r0] + // The LCP0 label is referenced by a constant pool entry in order to get + // a PC-relative address at the ldr instruction. + + // Emit the label. + OutStreamer.EmitLabel(getPICLabel(MAI->getPrivateGlobalPrefix(), + getFunctionNumber(), MI->getOperand(2).getImm(), + OutContext)); + + // Form and emit the load + unsigned Opcode; + switch (MI->getOpcode()) { + default: + llvm_unreachable("Unexpected opcode!"); + case ARM::PICSTR: Opcode = ARM::STRrs; break; + case ARM::PICSTRB: Opcode = ARM::STRBrs; break; + case ARM::PICSTRH: Opcode = ARM::STRH; break; + case ARM::PICLDR: Opcode = ARM::LDRrs; break; + case ARM::PICLDRB: Opcode = ARM::LDRBrs; break; + case ARM::PICLDRH: Opcode = ARM::LDRH; break; + case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; + case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; + } + MCInst LdStInst; + LdStInst.setOpcode(Opcode); + LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + LdStInst.addOperand(MCOperand::CreateReg(ARM::PC)); + LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + LdStInst.addOperand(MCOperand::CreateImm(0)); + // Add predicate operands. + LdStInst.addOperand(MCOperand::CreateImm(MI->getOperand(3).getImm())); + LdStInst.addOperand(MCOperand::CreateReg(MI->getOperand(4).getReg())); + OutStreamer.EmitInstruction(LdStInst); + + return; + } + case ARM::CONSTPOOL_ENTRY: { + /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool + /// in the function. The first operand is the ID# for this instruction, the + /// second is the index into the MachineConstantPool that this is, the third + /// is the size in bytes of this constant pool entry. + unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); + unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); + + EmitAlignment(2); + OutStreamer.EmitLabel(GetCPISymbol(LabelId)); + + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; + if (MCPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + else + EmitGlobalConstant(MCPE.Val.ConstVal); + + return; + } + case ARM::t2BR_JT: { + // Lower and emit the instruction itself, then the jump table following it. + MCInst TmpInst; + TmpInst.setOpcode(ARM::tMOVgpr2gpr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + // Output the data for the jump table itself + EmitJump2Table(MI); + return; + } + case ARM::t2TBB_JT: { + // Lower and emit the instruction itself, then the jump table following it. + MCInst TmpInst; + + TmpInst.setOpcode(ARM::t2TBB); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + // Output the data for the jump table itself + EmitJump2Table(MI); + // Make sure the next instruction is 2-byte aligned. + EmitAlignment(1); + return; + } + case ARM::t2TBH_JT: { + // Lower and emit the instruction itself, then the jump table following it. + MCInst TmpInst; + + TmpInst.setOpcode(ARM::t2TBH); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + // Output the data for the jump table itself + EmitJump2Table(MI); + return; + } + case ARM::tBR_JTr: + case ARM::BR_JTr: { + // Lower and emit the instruction itself, then the jump table following it. + // mov pc, target + MCInst TmpInst; + unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? + ARM::MOVr : ARM::tMOVgpr2gpr; + TmpInst.setOpcode(Opc); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + if (Opc == ARM::MOVr) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + + // Make sure the Thumb jump table is 4-byte aligned. + if (Opc == ARM::tMOVgpr2gpr) + EmitAlignment(2); + + // Output the data for the jump table itself + EmitJumpTable(MI); + return; + } + case ARM::BR_JTm: { + // Lower and emit the instruction itself, then the jump table following it. + // ldr pc, target + MCInst TmpInst; + if (MI->getOperand(1).getReg() == 0) { + // literal offset + TmpInst.setOpcode(ARM::LDRi12); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm())); + } else { + TmpInst.setOpcode(ARM::LDRrs); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + TmpInst.addOperand(MCOperand::CreateImm(0)); + } + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + + // Output the data for the jump table itself + EmitJumpTable(MI); + return; + } + case ARM::BR_JTadd: { + // Lower and emit the instruction itself, then the jump table following it. + // add pc, target, idx + MCInst TmpInst; + TmpInst.setOpcode(ARM::ADDrr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg())); + // Add predicate operands. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Add 's' bit operand (always reg0 for this) + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + + // Output the data for the jump table itself + EmitJumpTable(MI); + return; + } + case ARM::TRAP: { + // Non-Darwin binutils don't yet support the "trap" mnemonic. + // FIXME: Remove this special case when they do. + if (!Subtarget->isTargetDarwin()) { + //.long 0xe7ffdefe @ trap + uint32_t Val = 0xe7ffdefeUL; + OutStreamer.AddComment("trap"); + OutStreamer.EmitIntValue(Val, 4); + return; + } + break; + } + case ARM::tTRAP: { + // Non-Darwin binutils don't yet support the "trap" mnemonic. + // FIXME: Remove this special case when they do. + if (!Subtarget->isTargetDarwin()) { + //.short 57086 @ trap + uint16_t Val = 0xdefe; + OutStreamer.AddComment("trap"); + OutStreamer.EmitIntValue(Val, 2); + return; + } + break; + } + case ARM::t2Int_eh_sjlj_setjmp: + case ARM::t2Int_eh_sjlj_setjmp_nofp: + case ARM::tInt_eh_sjlj_setjmp: { + // Two incoming args: GPR:$src, GPR:$val + // mov $val, pc + // adds $val, #7 + // str $val, [$src, #4] + // movs r0, #0 + // b 1f + // movs r0, #1 + // 1: + unsigned SrcReg = MI->getOperand(0).getReg(); + unsigned ValReg = MI->getOperand(1).getReg(); + MCSymbol *Label = GetARMSJLJEHLabel(); + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tMOVgpr2tgpr); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + // 's' bit operand + TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + OutStreamer.AddComment("eh_setjmp begin"); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tADDi3); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + // 's' bit operand + TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + TmpInst.addOperand(MCOperand::CreateImm(7)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tSTRi); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + // The offset immediate is #4. The operand value is scaled by 4 for the + // tSTR instruction. + TmpInst.addOperand(MCOperand::CreateImm(1)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tMOVi8); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + TmpInst.addOperand(MCOperand::CreateImm(0)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext); + MCInst TmpInst; + TmpInst.setOpcode(ARM::tB); + TmpInst.addOperand(MCOperand::CreateExpr(SymbolExpr)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tMOVi8); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + TmpInst.addOperand(MCOperand::CreateImm(1)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.AddComment("eh_setjmp end"); + OutStreamer.EmitInstruction(TmpInst); + } + OutStreamer.EmitLabel(Label); + return; + } + + case ARM::Int_eh_sjlj_setjmp_nofp: + case ARM::Int_eh_sjlj_setjmp: { + // Two incoming args: GPR:$src, GPR:$val + // add $val, pc, #8 + // str $val, [$src, #+4] + // mov r0, #0 + // add pc, pc, #0 + // mov r0, #1 + unsigned SrcReg = MI->getOperand(0).getReg(); + unsigned ValReg = MI->getOperand(1).getReg(); + + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::ADDri); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateImm(8)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // 's' bit operand (always reg0 for this). + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.AddComment("eh_setjmp begin"); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::STRi12); + TmpInst.addOperand(MCOperand::CreateReg(ValReg)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateImm(4)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); + TmpInst.addOperand(MCOperand::CreateImm(0)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // 's' bit operand (always reg0 for this). + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::ADDri); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateReg(ARM::PC)); + TmpInst.addOperand(MCOperand::CreateImm(0)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // 's' bit operand (always reg0 for this). + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::MOVi); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R0)); + TmpInst.addOperand(MCOperand::CreateImm(1)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // 's' bit operand (always reg0 for this). + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.AddComment("eh_setjmp end"); + OutStreamer.EmitInstruction(TmpInst); + } + return; + } + case ARM::Int_eh_sjlj_longjmp: { + // ldr sp, [$src, #8] + // ldr $scratch, [$src, #4] + // ldr r7, [$src] + // bx $scratch + unsigned SrcReg = MI->getOperand(0).getReg(); + unsigned ScratchReg = MI->getOperand(1).getReg(); + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::LDRi12); + TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateImm(8)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::LDRi12); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateImm(4)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::LDRi12); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateImm(0)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::BX); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + return; + } + case ARM::tInt_eh_sjlj_longjmp: { + // ldr $scratch, [$src, #8] + // mov sp, $scratch + // ldr $scratch, [$src, #4] + // ldr r7, [$src] + // bx $scratch + unsigned SrcReg = MI->getOperand(0).getReg(); + unsigned ScratchReg = MI->getOperand(1).getReg(); + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tLDRi); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + // The offset immediate is #8. The operand value is scaled by 4 for the + // tLDR instruction. + TmpInst.addOperand(MCOperand::CreateImm(2)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tMOVtgpr2gpr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::SP)); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tLDRi); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateImm(1)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tLDRr); + TmpInst.addOperand(MCOperand::CreateReg(ARM::R7)); + TmpInst.addOperand(MCOperand::CreateReg(SrcReg)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + { + MCInst TmpInst; + TmpInst.setOpcode(ARM::tBX_RET_vararg); + TmpInst.addOperand(MCOperand::CreateReg(ScratchReg)); + // Predicate. + TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL)); + TmpInst.addOperand(MCOperand::CreateReg(0)); + OutStreamer.EmitInstruction(TmpInst); + } + return; + } + // These are the pseudos created to comply with stricter operand restrictions + // on ARMv5. Lower them now to "normal" instructions, since all the + // restrictions are already satisfied. + case ARM::MULv5: + EmitPatchedInstruction(MI, ARM::MUL); + return; + case ARM::MLAv5: + EmitPatchedInstruction(MI, ARM::MLA); + return; + case ARM::SMULLv5: + EmitPatchedInstruction(MI, ARM::SMULL); + return; + case ARM::UMULLv5: + EmitPatchedInstruction(MI, ARM::UMULL); + return; + case ARM::SMLALv5: + EmitPatchedInstruction(MI, ARM::SMLAL); + return; + case ARM::UMLALv5: + EmitPatchedInstruction(MI, ARM::UMLAL); + return; + case ARM::UMAALv5: + EmitPatchedInstruction(MI, ARM::UMAAL); + return; + } + + MCInst TmpInst; + LowerARMMachineInstrToMCInst(MI, TmpInst, *this); + + // Emit unwinding stuff for frame-related instructions + if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup)) + EmitUnwindingInstruction(MI); + + OutStreamer.EmitInstruction(TmpInst); +} + +//===----------------------------------------------------------------------===// +// Target Registry Stuff +//===----------------------------------------------------------------------===// + +static MCInstPrinter *createARMMCInstPrinter(const Target &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI) { + if (SyntaxVariant == 0) + return new ARMInstPrinter(MAI); + return 0; +} + +// Force static initialization. +extern "C" void LLVMInitializeARMAsmPrinter() { + RegisterAsmPrinter X(TheARMTarget); + RegisterAsmPrinter Y(TheThumbTarget); + + TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); + TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); +} + diff --git a/final/lib/Target/ARM/ARMAsmPrinter.h b/final/lib/Target/ARM/ARMAsmPrinter.h new file mode 100644 index 00000000000..9db139b672c --- /dev/null +++ b/final/lib/Target/ARM/ARMAsmPrinter.h @@ -0,0 +1,114 @@ +//===-- ARMAsmPrinter.h - Print machine code to an ARM .s file ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ARM Assembly printer class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMASMPRINTER_H +#define ARMASMPRINTER_H + +#include "ARM.h" +#include "ARMTargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +namespace ARM { + enum DW_ISA { + DW_ISA_ARM_thumb = 1, + DW_ISA_ARM_arm = 2 + }; +} + +class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { + + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when printing asm code for different targets. + const ARMSubtarget *Subtarget; + + /// AFI - Keep a pointer to ARMFunctionInfo for the current + /// MachineFunction. + ARMFunctionInfo *AFI; + + /// MCP - Keep a pointer to constantpool entries of the current + /// MachineFunction. + const MachineConstantPool *MCP; + +public: + explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) + : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { + Subtarget = &TM.getSubtarget(); + } + + virtual const char *getPassName() const { + return "ARM Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, + const char *Modifier = 0); + + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &O); + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O); + + void EmitJumpTable(const MachineInstr *MI); + void EmitJump2Table(const MachineInstr *MI); + virtual void EmitInstruction(const MachineInstr *MI); + bool runOnMachineFunction(MachineFunction &F); + + virtual void EmitConstantPool() {} // we emit constant pools customly! + virtual void EmitFunctionEntryLabel(); + void EmitStartOfAsmFile(Module &M); + void EmitEndOfAsmFile(Module &M); + +private: + // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() + void emitAttributes(); + + // Helper for ELF .o only + void emitARMAttributeSection(); + + // Generic helper used to emit e.g. ARMv5 mul pseudos + void EmitPatchedInstruction(const MachineInstr *MI, unsigned TargetOpc); + + void EmitUnwindingInstruction(const MachineInstr *MI); + +public: + void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); + + MachineLocation getDebugValueLocation(const MachineInstr *MI) const; + + virtual unsigned getISAEncoding() { + // ARM/Darwin adds ISA to the DWARF info for each function. + if (!Subtarget->isTargetDarwin()) + return 0; + return Subtarget->isThumb() ? + llvm::ARM::DW_ISA_ARM_thumb : llvm::ARM::DW_ISA_ARM_arm; + } + + MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const; + MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const; + + MCSymbol *GetARMSJLJEHLabel(void) const; + + MCSymbol *GetARMGVSymbol(const GlobalValue *GV); + + /// EmitMachineConstantPoolValue - Print a machine constantpool value to + /// the .s file. + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); +}; +} // end namespace llvm + +#endif diff --git a/final/lib/Target/ARM/ARMBaseInfo.h b/final/lib/Target/ARM/ARMBaseInfo.h new file mode 100644 index 00000000000..a56cc1a9f24 --- /dev/null +++ b/final/lib/Target/ARM/ARMBaseInfo.h @@ -0,0 +1,249 @@ +//===-- ARMBaseInfo.h - Top level definitions for ARM -------- --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains small standalone helper functions and enum definitions for +// the ARM target useful for the compiler back-end and the MC libraries. +// As such, it deliberately does not include references to LLVM core +// code gen types, passes, etc.. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMBASEINFO_H +#define ARMBASEINFO_H + +#include "llvm/Support/ErrorHandling.h" + +// Note that the following auto-generated files only defined enum types, and +// so are safe to include here. + +// Defines symbolic names for ARM registers. This defines a mapping from +// register name to register number. +// +#include "ARMGenRegisterNames.inc" + +// Defines symbolic names for the ARM instructions. +// +#include "ARMGenInstrNames.inc" + +namespace llvm { + +// Enums corresponding to ARM condition codes +namespace ARMCC { + // The CondCodes constants map directly to the 4-bit encoding of the + // condition field for predicated instructions. + enum CondCodes { // Meaning (integer) Meaning (floating-point) + EQ, // Equal Equal + NE, // Not equal Not equal, or unordered + HS, // Carry set >, ==, or unordered + LO, // Carry clear Less than + MI, // Minus, negative Less than + PL, // Plus, positive or zero >, ==, or unordered + VS, // Overflow Unordered + VC, // No overflow Not unordered + HI, // Unsigned higher Greater than, or unordered + LS, // Unsigned lower or same Less than or equal + GE, // Greater than or equal Greater than or equal + LT, // Less than Less than, or unordered + GT, // Greater than Greater than + LE, // Less than or equal <, ==, or unordered + AL // Always (unconditional) Always (unconditional) + }; + + inline static CondCodes getOppositeCondition(CondCodes CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case EQ: return NE; + case NE: return EQ; + case HS: return LO; + case LO: return HS; + case MI: return PL; + case PL: return MI; + case VS: return VC; + case VC: return VS; + case HI: return LS; + case LS: return HI; + case GE: return LT; + case LT: return GE; + case GT: return LE; + case LE: return GT; + } + } +} // namespace ARMCC + +inline static const char *ARMCondCodeToString(ARMCC::CondCodes CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case ARMCC::EQ: return "eq"; + case ARMCC::NE: return "ne"; + case ARMCC::HS: return "hs"; + case ARMCC::LO: return "lo"; + case ARMCC::MI: return "mi"; + case ARMCC::PL: return "pl"; + case ARMCC::VS: return "vs"; + case ARMCC::VC: return "vc"; + case ARMCC::HI: return "hi"; + case ARMCC::LS: return "ls"; + case ARMCC::GE: return "ge"; + case ARMCC::LT: return "lt"; + case ARMCC::GT: return "gt"; + case ARMCC::LE: return "le"; + case ARMCC::AL: return "al"; + } +} + +namespace ARM_PROC { + enum IMod { + IE = 2, + ID = 3 + }; + + enum IFlags { + F = 1, + I = 2, + A = 4 + }; + + inline static const char *IFlagsToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown iflags operand"); + case F: return "f"; + case I: return "i"; + case A: return "a"; + } + } + + inline static const char *IModToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown imod operand"); + case IE: return "ie"; + case ID: return "id"; + } + } +} + +namespace ARM_MB { + // The Memory Barrier Option constants map directly to the 4-bit encoding of + // the option field for memory barrier operations. + enum MemBOpt { + SY = 15, + ST = 14, + ISH = 11, + ISHST = 10, + NSH = 7, + NSHST = 6, + OSH = 3, + OSHST = 2 + }; + + inline static const char *MemBOptToString(unsigned val) { + switch (val) { + default: llvm_unreachable("Unknown memory operation"); + case SY: return "sy"; + case ST: return "st"; + case ISH: return "ish"; + case ISHST: return "ishst"; + case NSH: return "nsh"; + case NSHST: return "nshst"; + case OSH: return "osh"; + case OSHST: return "oshst"; + } + } +} // namespace ARM_MB + +/// getARMRegisterNumbering - Given the enum value for some register, e.g. +/// ARM::LR, return the number that it corresponds to (e.g. 14). +inline static unsigned getARMRegisterNumbering(unsigned Reg) { + using namespace ARM; + switch (Reg) { + default: + llvm_unreachable("Unknown ARM register!"); + case R0: case S0: case D0: case Q0: return 0; + case R1: case S1: case D1: case Q1: return 1; + case R2: case S2: case D2: case Q2: return 2; + case R3: case S3: case D3: case Q3: return 3; + case R4: case S4: case D4: case Q4: return 4; + case R5: case S5: case D5: case Q5: return 5; + case R6: case S6: case D6: case Q6: return 6; + case R7: case S7: case D7: case Q7: return 7; + case R8: case S8: case D8: case Q8: return 8; + case R9: case S9: case D9: case Q9: return 9; + case R10: case S10: case D10: case Q10: return 10; + case R11: case S11: case D11: case Q11: return 11; + case R12: case S12: case D12: case Q12: return 12; + case SP: case S13: case D13: case Q13: return 13; + case LR: case S14: case D14: case Q14: return 14; + case PC: case S15: case D15: case Q15: return 15; + + case S16: case D16: return 16; + case S17: case D17: return 17; + case S18: case D18: return 18; + case S19: case D19: return 19; + case S20: case D20: return 20; + case S21: case D21: return 21; + case S22: case D22: return 22; + case S23: case D23: return 23; + case S24: case D24: return 24; + case S25: case D25: return 25; + case S26: case D26: return 26; + case S27: case D27: return 27; + case S28: case D28: return 28; + case S29: case D29: return 29; + case S30: case D30: return 30; + case S31: case D31: return 31; + } +} + +namespace ARMII { + /// Target Operand Flag enum. + enum TOF { + //===------------------------------------------------------------------===// + // ARM Specific MachineOperand flags. + + MO_NO_FLAG, + + /// MO_LO16 - On a symbol operand, this represents a relocation containing + /// lower 16 bit of the address. Used only via movw instruction. + MO_LO16, + + /// MO_HI16 - On a symbol operand, this represents a relocation containing + /// higher 16 bit of the address. Used only via movt instruction. + MO_HI16, + + /// MO_LO16_NONLAZY - On a symbol operand "FOO", this represents a + /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol, + /// i.e. "FOO$non_lazy_ptr". + /// Used only via movw instruction. + MO_LO16_NONLAZY, + + /// MO_HI16_NONLAZY - On a symbol operand "FOO", this represents a + /// relocation containing lower 16 bit of the non-lazy-ptr indirect symbol, + /// i.e. "FOO$non_lazy_ptr". Used only via movt instruction. + MO_HI16_NONLAZY, + + /// MO_LO16_NONLAZY_PIC - On a symbol operand "FOO", this represents a + /// relocation containing lower 16 bit of the PC relative address of the + /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL". + /// Used only via movw instruction. + MO_LO16_NONLAZY_PIC, + + /// MO_HI16_NONLAZY_PIC - On a symbol operand "FOO", this represents a + /// relocation containing lower 16 bit of the PC relative address of the + /// non-lazy-ptr indirect symbol, i.e. "FOO$non_lazy_ptr - LABEL". + /// Used only via movt instruction. + MO_HI16_NONLAZY_PIC, + + /// MO_PLT - On a symbol operand, this represents an ELF PLT reference on a + /// call operand. + MO_PLT + }; +} // end namespace ARMII + +} // end namespace llvm; + +#endif diff --git a/final/lib/Target/ARM/ARMBaseInstrInfo.cpp b/final/lib/Target/ARM/ARMBaseInstrInfo.cpp new file mode 100644 index 00000000000..012eb280b06 --- /dev/null +++ b/final/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -0,0 +1,2331 @@ +//===- ARMBaseInstrInfo.cpp - ARM Instruction Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Base ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARMBaseInstrInfo.h" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMHazardRecognizer.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMRegisterInfo.h" +#include "ARMGenInstrInfo.inc" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/STLExtras.h" +using namespace llvm; + +static cl::opt +EnableARM3Addr("enable-arm-3-addr-conv", cl::Hidden, + cl::desc("Enable ARM 2-addr to 3-addr conv")); + +/// ARM_MLxEntry - Record information about MLA / MLS instructions. +struct ARM_MLxEntry { + unsigned MLxOpc; // MLA / MLS opcode + unsigned MulOpc; // Expanded multiplication opcode + unsigned AddSubOpc; // Expanded add / sub opcode + bool NegAcc; // True if the acc is negated before the add / sub. + bool HasLane; // True if instruction has an extra "lane" operand. +}; + +static const ARM_MLxEntry ARM_MLxTable[] = { + // MLxOpc, MulOpc, AddSubOpc, NegAcc, HasLane + // fp scalar ops + { ARM::VMLAS, ARM::VMULS, ARM::VADDS, false, false }, + { ARM::VMLSS, ARM::VMULS, ARM::VSUBS, false, false }, + { ARM::VMLAD, ARM::VMULD, ARM::VADDD, false, false }, + { ARM::VMLSD, ARM::VMULD, ARM::VSUBD, false, false }, + { ARM::VNMLAS, ARM::VNMULS, ARM::VSUBS, true, false }, + { ARM::VNMLSS, ARM::VMULS, ARM::VSUBS, true, false }, + { ARM::VNMLAD, ARM::VNMULD, ARM::VSUBD, true, false }, + { ARM::VNMLSD, ARM::VMULD, ARM::VSUBD, true, false }, + + // fp SIMD ops + { ARM::VMLAfd, ARM::VMULfd, ARM::VADDfd, false, false }, + { ARM::VMLSfd, ARM::VMULfd, ARM::VSUBfd, false, false }, + { ARM::VMLAfq, ARM::VMULfq, ARM::VADDfq, false, false }, + { ARM::VMLSfq, ARM::VMULfq, ARM::VSUBfq, false, false }, + { ARM::VMLAslfd, ARM::VMULslfd, ARM::VADDfd, false, true }, + { ARM::VMLSslfd, ARM::VMULslfd, ARM::VSUBfd, false, true }, + { ARM::VMLAslfq, ARM::VMULslfq, ARM::VADDfq, false, true }, + { ARM::VMLSslfq, ARM::VMULslfq, ARM::VSUBfq, false, true }, +}; + +ARMBaseInstrInfo::ARMBaseInstrInfo(const ARMSubtarget& STI) + : TargetInstrInfoImpl(ARMInsts, array_lengthof(ARMInsts)), + Subtarget(STI) { + for (unsigned i = 0, e = array_lengthof(ARM_MLxTable); i != e; ++i) { + if (!MLxEntryMap.insert(std::make_pair(ARM_MLxTable[i].MLxOpc, i)).second) + assert(false && "Duplicated entries?"); + MLxHazardOpcodes.insert(ARM_MLxTable[i].AddSubOpc); + MLxHazardOpcodes.insert(ARM_MLxTable[i].MulOpc); + } +} + +// Use a ScoreboardHazardRecognizer for prepass ARM scheduling. TargetInstrImpl +// currently defaults to no prepass hazard recognizer. +ScheduleHazardRecognizer *ARMBaseInstrInfo:: +CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const { + if (usePreRAHazardRecognizer()) { + const InstrItineraryData *II = TM->getInstrItineraryData(); + return new ScoreboardHazardRecognizer(II, DAG, "pre-RA-sched"); + } + return TargetInstrInfoImpl::CreateTargetHazardRecognizer(TM, DAG); +} + +ScheduleHazardRecognizer *ARMBaseInstrInfo:: +CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, + const ScheduleDAG *DAG) const { + if (Subtarget.isThumb2() || Subtarget.hasVFP2()) + return (ScheduleHazardRecognizer *) + new ARMHazardRecognizer(II, *this, getRegisterInfo(), Subtarget, DAG); + return TargetInstrInfoImpl::CreateTargetPostRAHazardRecognizer(II, DAG); +} + +MachineInstr * +ARMBaseInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const { + // FIXME: Thumb2 support. + + if (!EnableARM3Addr) + return NULL; + + MachineInstr *MI = MBBI; + MachineFunction &MF = *MI->getParent()->getParent(); + uint64_t TSFlags = MI->getDesc().TSFlags; + bool isPre = false; + switch ((TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift) { + default: return NULL; + case ARMII::IndexModePre: + isPre = true; + break; + case ARMII::IndexModePost: + break; + } + + // Try splitting an indexed load/store to an un-indexed one plus an add/sub + // operation. + unsigned MemOpc = getUnindexedOpcode(MI->getOpcode()); + if (MemOpc == 0) + return NULL; + + MachineInstr *UpdateMI = NULL; + MachineInstr *MemMI = NULL; + unsigned AddrMode = (TSFlags & ARMII::AddrModeMask); + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + bool isLoad = !TID.mayStore(); + const MachineOperand &WB = isLoad ? MI->getOperand(1) : MI->getOperand(0); + const MachineOperand &Base = MI->getOperand(2); + const MachineOperand &Offset = MI->getOperand(NumOps-3); + unsigned WBReg = WB.getReg(); + unsigned BaseReg = Base.getReg(); + unsigned OffReg = Offset.getReg(); + unsigned OffImm = MI->getOperand(NumOps-2).getImm(); + ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NumOps-1).getImm(); + switch (AddrMode) { + default: + assert(false && "Unknown indexed op!"); + return NULL; + case ARMII::AddrMode2: { + bool isSub = ARM_AM::getAM2Op(OffImm) == ARM_AM::sub; + unsigned Amt = ARM_AM::getAM2Offset(OffImm); + if (OffReg == 0) { + if (ARM_AM::getSOImmVal(Amt) == -1) + // Can't encode it in a so_imm operand. This transformation will + // add more than 1 instruction. Abandon! + return NULL; + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) + .addReg(BaseReg).addImm(Amt) + .addImm(Pred).addReg(0).addReg(0); + } else if (Amt != 0) { + ARM_AM::ShiftOpc ShOpc = ARM_AM::getAM2ShiftOpc(OffImm); + unsigned SOOpc = ARM_AM::getSORegOpc(ShOpc, Amt); + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrs : ARM::ADDrs), WBReg) + .addReg(BaseReg).addReg(OffReg).addReg(0).addImm(SOOpc) + .addImm(Pred).addReg(0).addReg(0); + } else + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) + .addReg(BaseReg).addReg(OffReg) + .addImm(Pred).addReg(0).addReg(0); + break; + } + case ARMII::AddrMode3 : { + bool isSub = ARM_AM::getAM3Op(OffImm) == ARM_AM::sub; + unsigned Amt = ARM_AM::getAM3Offset(OffImm); + if (OffReg == 0) + // Immediate is 8-bits. It's guaranteed to fit in a so_imm operand. + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBri : ARM::ADDri), WBReg) + .addReg(BaseReg).addImm(Amt) + .addImm(Pred).addReg(0).addReg(0); + else + UpdateMI = BuildMI(MF, MI->getDebugLoc(), + get(isSub ? ARM::SUBrr : ARM::ADDrr), WBReg) + .addReg(BaseReg).addReg(OffReg) + .addImm(Pred).addReg(0).addReg(0); + break; + } + } + + std::vector NewMIs; + if (isPre) { + if (isLoad) + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc), MI->getOperand(0).getReg()) + .addReg(WBReg).addImm(0).addImm(Pred); + else + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc)).addReg(MI->getOperand(1).getReg()) + .addReg(WBReg).addReg(0).addImm(0).addImm(Pred); + NewMIs.push_back(MemMI); + NewMIs.push_back(UpdateMI); + } else { + if (isLoad) + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc), MI->getOperand(0).getReg()) + .addReg(BaseReg).addImm(0).addImm(Pred); + else + MemMI = BuildMI(MF, MI->getDebugLoc(), + get(MemOpc)).addReg(MI->getOperand(1).getReg()) + .addReg(BaseReg).addReg(0).addImm(0).addImm(Pred); + if (WB.isDead()) + UpdateMI->getOperand(0).setIsDead(); + NewMIs.push_back(UpdateMI); + NewMIs.push_back(MemMI); + } + + // Transfer LiveVariables states, kill / dead info. + if (LV) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + unsigned Reg = MO.getReg(); + + LiveVariables::VarInfo &VI = LV->getVarInfo(Reg); + if (MO.isDef()) { + MachineInstr *NewMI = (Reg == WBReg) ? UpdateMI : MemMI; + if (MO.isDead()) + LV->addVirtualRegisterDead(Reg, NewMI); + } + if (MO.isUse() && MO.isKill()) { + for (unsigned j = 0; j < 2; ++j) { + // Look at the two new MI's in reverse order. + MachineInstr *NewMI = NewMIs[j]; + if (!NewMI->readsRegister(Reg)) + continue; + LV->addVirtualRegisterKilled(Reg, NewMI); + if (VI.removeKill(MI)) + VI.Kills.push_back(NewMI); + break; + } + } + } + } + } + + MFI->insert(MBBI, NewMIs[1]); + MFI->insert(MBBI, NewMIs[0]); + return NewMIs[0]; +} + +// Branch analysis. +bool +ARMBaseInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) + return false; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return false; + --I; + } + if (!isUnpredicatedTerminator(I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + unsigned LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (isUncondBranchOpcode(LastOpc)) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + if (isCondBranchOpcode(LastOpc)) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(0).getMBB(); + Cond.push_back(LastInst->getOperand(1)); + Cond.push_back(LastInst->getOperand(2)); + return false; + } + return true; // Can't handle indirect branch. + } + + // Get the instruction before it if it is a terminator. + MachineInstr *SecondLastInst = I; + unsigned SecondLastOpc = SecondLastInst->getOpcode(); + + // If AllowModify is true and the block ends with two or more unconditional + // branches, delete all but the first unconditional branch. + if (AllowModify && isUncondBranchOpcode(LastOpc)) { + while (isUncondBranchOpcode(SecondLastOpc)) { + LastInst->eraseFromParent(); + LastInst = SecondLastInst; + LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + // Return now the only terminator is an unconditional branch. + TBB = LastInst->getOperand(0).getMBB(); + return false; + } else { + SecondLastInst = I; + SecondLastOpc = SecondLastInst->getOpcode(); + } + } + } + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with a B and a Bcc, handle it. + if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + Cond.push_back(SecondLastInst->getOperand(1)); + Cond.push_back(SecondLastInst->getOperand(2)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two unconditional branches, handle it. The second + // one is not executed, so remove it. + if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // ...likewise if it ends with a branch table followed by an unconditional + // branch. The branch folder can create these, and we must get rid of them for + // correctness of Thumb constant islands. + if ((isJumpTableBranchOpcode(SecondLastOpc) || + isIndirectBranchOpcode(SecondLastOpc)) && + isUncondBranchOpcode(LastOpc)) { + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return true; + } + + // Otherwise, can't handle this. + return true; +} + + +unsigned ARMBaseInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return 0; + --I; + } + if (!isUncondBranchOpcode(I->getOpcode()) && + !isCondBranchOpcode(I->getOpcode())) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (!isCondBranchOpcode(I->getOpcode())) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +unsigned +ARMBaseInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const { + ARMFunctionInfo *AFI = MBB.getParent()->getInfo(); + int BOpc = !AFI->isThumbFunction() + ? ARM::B : (AFI->isThumb2Function() ? ARM::t2B : ARM::tB); + int BccOpc = !AFI->isThumbFunction() + ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc); + + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "ARM branch conditions have two components!"); + + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch? + BuildMI(&MBB, DL, get(BOpc)).addMBB(TBB); + else + BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); + return 1; + } + + // Two-way conditional branch. + BuildMI(&MBB, DL, get(BccOpc)).addMBB(TBB) + .addImm(Cond[0].getImm()).addReg(Cond[1].getReg()); + BuildMI(&MBB, DL, get(BOpc)).addMBB(FBB); + return 2; +} + +bool ARMBaseInstrInfo:: +ReverseBranchCondition(SmallVectorImpl &Cond) const { + ARMCC::CondCodes CC = (ARMCC::CondCodes)(int)Cond[0].getImm(); + Cond[0].setImm(ARMCC::getOppositeCondition(CC)); + return false; +} + +bool ARMBaseInstrInfo:: +PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const { + unsigned Opc = MI->getOpcode(); + if (isUncondBranchOpcode(Opc)) { + MI->setDesc(get(getMatchingCondBranchOpcode(Opc))); + MI->addOperand(MachineOperand::CreateImm(Pred[0].getImm())); + MI->addOperand(MachineOperand::CreateReg(Pred[1].getReg(), false)); + return true; + } + + int PIdx = MI->findFirstPredOperandIdx(); + if (PIdx != -1) { + MachineOperand &PMO = MI->getOperand(PIdx); + PMO.setImm(Pred[0].getImm()); + MI->getOperand(PIdx+1).setReg(Pred[1].getReg()); + return true; + } + return false; +} + +bool ARMBaseInstrInfo:: +SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const { + if (Pred1.size() > 2 || Pred2.size() > 2) + return false; + + ARMCC::CondCodes CC1 = (ARMCC::CondCodes)Pred1[0].getImm(); + ARMCC::CondCodes CC2 = (ARMCC::CondCodes)Pred2[0].getImm(); + if (CC1 == CC2) + return true; + + switch (CC1) { + default: + return false; + case ARMCC::AL: + return true; + case ARMCC::HS: + return CC2 == ARMCC::HI; + case ARMCC::LS: + return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; + case ARMCC::GE: + return CC2 == ARMCC::GT; + case ARMCC::LE: + return CC2 == ARMCC::LT; + } +} + +bool ARMBaseInstrInfo::DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const { + // FIXME: This confuses implicit_def with optional CPSR def. + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.getImplicitDefs() && !TID.hasOptionalDef()) + return false; + + bool Found = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.getReg() == ARM::CPSR) { + Pred.push_back(MO); + Found = true; + } + } + + return Found; +} + +/// isPredicable - Return true if the specified instruction can be predicated. +/// By default, this returns true for every instruction with a +/// PredicateOperand. +bool ARMBaseInstrInfo::isPredicable(MachineInstr *MI) const { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isPredicable()) + return false; + + if ((TID.TSFlags & ARMII::DomainMask) == ARMII::DomainNEON) { + ARMFunctionInfo *AFI = + MI->getParent()->getParent()->getInfo(); + return AFI->isThumb2Function(); + } + return true; +} + +/// FIXME: Works around a gcc miscompilation with -fstrict-aliasing. +LLVM_ATTRIBUTE_NOINLINE +static unsigned getNumJTEntries(const std::vector &JT, + unsigned JTI); +static unsigned getNumJTEntries(const std::vector &JT, + unsigned JTI) { + assert(JTI < JT.size()); + return JT[JTI].MBBs.size(); +} + +/// GetInstSize - Return the size of the specified MachineInstr. +/// +unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const MachineBasicBlock &MBB = *MI->getParent(); + const MachineFunction *MF = MBB.getParent(); + const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); + + // Basic size info comes from the TSFlags field. + const TargetInstrDesc &TID = MI->getDesc(); + uint64_t TSFlags = TID.TSFlags; + + unsigned Opc = MI->getOpcode(); + switch ((TSFlags & ARMII::SizeMask) >> ARMII::SizeShift) { + default: { + // If this machine instr is an inline asm, measure it. + if (MI->getOpcode() == ARM::INLINEASM) + return getInlineAsmLength(MI->getOperand(0).getSymbolName(), *MAI); + if (MI->isLabel()) + return 0; + switch (Opc) { + default: + llvm_unreachable("Unknown or unset size field for instr!"); + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::DBG_VALUE: + return 0; + } + break; + } + case ARMII::Size8Bytes: return 8; // ARM instruction x 2. + case ARMII::Size4Bytes: return 4; // ARM / Thumb2 instruction. + case ARMII::Size2Bytes: return 2; // Thumb1 instruction. + case ARMII::SizeSpecial: { + switch (Opc) { + case ARM::MOVi16_ga_pcrel: + case ARM::MOVTi16_ga_pcrel: + case ARM::t2MOVi16_ga_pcrel: + case ARM::t2MOVTi16_ga_pcrel: + return 4; + case ARM::MOVi32imm: + case ARM::t2MOVi32imm: + return 8; + case ARM::CONSTPOOL_ENTRY: + // If this machine instr is a constant pool entry, its size is recorded as + // operand #2. + return MI->getOperand(2).getImm(); + case ARM::Int_eh_sjlj_longjmp: + return 16; + case ARM::tInt_eh_sjlj_longjmp: + return 10; + case ARM::Int_eh_sjlj_setjmp: + case ARM::Int_eh_sjlj_setjmp_nofp: + return 20; + case ARM::tInt_eh_sjlj_setjmp: + case ARM::t2Int_eh_sjlj_setjmp: + case ARM::t2Int_eh_sjlj_setjmp_nofp: + return 12; + case ARM::BR_JTr: + case ARM::BR_JTm: + case ARM::BR_JTadd: + case ARM::tBR_JTr: + case ARM::t2BR_JT: + case ARM::t2TBB_JT: + case ARM::t2TBH_JT: { + // These are jumptable branches, i.e. a branch followed by an inlined + // jumptable. The size is 4 + 4 * number of entries. For TBB, each + // entry is one byte; TBH two byte each. + unsigned EntrySize = (Opc == ARM::t2TBB_JT) + ? 1 : ((Opc == ARM::t2TBH_JT) ? 2 : 4); + unsigned NumOps = TID.getNumOperands(); + MachineOperand JTOP = + MI->getOperand(NumOps - (TID.isPredicable() ? 3 : 2)); + unsigned JTI = JTOP.getIndex(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + assert(MJTI != 0); + const std::vector &JT = MJTI->getJumpTables(); + assert(JTI < JT.size()); + // Thumb instructions are 2 byte aligned, but JT entries are 4 byte + // 4 aligned. The assembler / linker may add 2 byte padding just before + // the JT entries. The size does not include this padding; the + // constant islands pass does separate bookkeeping for it. + // FIXME: If we know the size of the function is less than (1 << 16) *2 + // bytes, we can use 16-bit entries instead. Then there won't be an + // alignment issue. + unsigned InstSize = (Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT) ? 2 : 4; + unsigned NumEntries = getNumJTEntries(JT, JTI); + if (Opc == ARM::t2TBB_JT && (NumEntries & 1)) + // Make sure the instruction that follows TBB is 2-byte aligned. + // FIXME: Constant island pass should insert an "ALIGN" instruction + // instead. + ++NumEntries; + return NumEntries * EntrySize + InstSize; + } + default: + // Otherwise, pseudo-instruction sizes are zero. + return 0; + } + } + } + return 0; // Not reached +} + +void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + bool GPRDest = ARM::GPRRegClass.contains(DestReg); + bool GPRSrc = ARM::GPRRegClass.contains(SrcReg); + + if (GPRDest && GPRSrc) { + AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)))); + return; + } + + bool SPRDest = ARM::SPRRegClass.contains(DestReg); + bool SPRSrc = ARM::SPRRegClass.contains(SrcReg); + + unsigned Opc; + if (SPRDest && SPRSrc) + Opc = ARM::VMOVS; + else if (GPRDest && SPRSrc) + Opc = ARM::VMOVRS; + else if (SPRDest && GPRSrc) + Opc = ARM::VMOVSR; + else if (ARM::DPRRegClass.contains(DestReg, SrcReg)) + Opc = ARM::VMOVD; + else if (ARM::QPRRegClass.contains(DestReg, SrcReg)) + Opc = ARM::VMOVQ; + else if (ARM::QQPRRegClass.contains(DestReg, SrcReg)) + Opc = ARM::VMOVQQ; + else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) + Opc = ARM::VMOVQQQQ; + else + llvm_unreachable("Impossible reg-to-reg copy"); + + MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opc), DestReg); + MIB.addReg(SrcReg, getKillRegState(KillSrc)); + if (Opc != ARM::VMOVQQ && Opc != ARM::VMOVQQQQ) + AddDefaultPred(MIB); +} + +static const +MachineInstrBuilder &AddDReg(MachineInstrBuilder &MIB, + unsigned Reg, unsigned SubIdx, unsigned State, + const TargetRegisterInfo *TRI) { + if (!SubIdx) + return MIB.addReg(Reg, State); + + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State); + return MIB.addReg(Reg, State, SubIdx); +} + +void ARMBaseInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) DL = I->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + + MachineMemOperand *MMO = + MF.getMachineMemOperand(MachinePointerInfo( + PseudoSourceValue::getFixedStack(FI)), + MachineMemOperand::MOStore, + MFI.getObjectSize(FI), + Align); + + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. Likewise, rGPR. + if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass + || RC == ARM::rGPRRegisterClass) + RC = ARM::GPRRegisterClass; + + switch (RC->getID()) { + case ARM::GPRRegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::SPRRegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::DPRRegClassID: + case ARM::DPR_VFP2RegClassID: + case ARM::DPR_8RegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::QPRRegClassID: + case ARM::QPR_VFP2RegClassID: + case ARM::QPR_8RegClassID: + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64Pseudo)) + .addFrameIndex(FI).addImm(16) + .addReg(SrcReg, getKillRegState(isKill)) + .addMemOperand(MMO)); + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) + .addReg(SrcReg, getKillRegState(isKill)) + .addFrameIndex(FI) + .addMemOperand(MMO)); + } + break; + case ARM::QQPRRegClassID: + case ARM::QQPR_VFP2RegClassID: + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + // FIXME: It's possible to only store part of the QQ register if the + // spilled def has a sub-register index. + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1d64QPseudo)) + .addFrameIndex(FI).addImm(16) + .addReg(SrcReg, getKillRegState(isKill)) + .addMemOperand(MMO)); + } else { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + } + break; + case ARM::QQQQPRRegClassID: { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_7, 0, TRI); + break; + } + default: + llvm_unreachable("Unknown regclass!"); + } +} + +unsigned +ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case ARM::STRrs: + case ARM::t2STRs: // FIXME: don't use t2STRs to access frame. + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isReg() && + MI->getOperand(3).isImm() && + MI->getOperand(2).getReg() == 0 && + MI->getOperand(3).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::STRi12: + case ARM::t2STRi12: + case ARM::tSpill: + case ARM::VSTRD: + case ARM::VSTRS: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::VST1q64Pseudo: + if (MI->getOperand(0).isFI() && + MI->getOperand(2).getSubReg() == 0) { + FrameIndex = MI->getOperand(0).getIndex(); + return MI->getOperand(2).getReg(); + } + break; + case ARM::VSTMQIA: + if (MI->getOperand(1).isFI() && + MI->getOperand(0).getSubReg() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + + return 0; +} + +void ARMBaseInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) DL = I->getDebugLoc(); + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFI = *MF.getFrameInfo(); + unsigned Align = MFI.getObjectAlignment(FI); + MachineMemOperand *MMO = + MF.getMachineMemOperand( + MachinePointerInfo(PseudoSourceValue::getFixedStack(FI)), + MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), + Align); + + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. + if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass + || RC == ARM::rGPRRegisterClass) + RC = ARM::GPRRegisterClass; + + switch (RC->getID()) { + case ARM::GPRRegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::SPRRegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::DPRRegClassID: + case ARM::DPR_VFP2RegClassID: + case ARM::DPR_8RegClassID: + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) + .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + break; + case ARM::QPRRegClassID: + case ARM::QPR_VFP2RegClassID: + case ARM::QPR_8RegClassID: + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64Pseudo), DestReg) + .addFrameIndex(FI).addImm(16) + .addMemOperand(MMO)); + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) + .addFrameIndex(FI) + .addMemOperand(MMO)); + } + break; + case ARM::QQPRRegClassID: + case ARM::QQPR_VFP2RegClassID: + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1d64QPseudo), DestReg) + .addFrameIndex(FI).addImm(16) + .addMemOperand(MMO)); + } else { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + } + break; + case ARM::QQQQPRRegClassID: { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_4, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_5, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_6, RegState::Define, TRI); + AddDReg(MIB, DestReg, ARM::dsub_7, RegState::Define, TRI); + break; + } + default: + llvm_unreachable("Unknown regclass!"); + } +} + +unsigned +ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case ARM::LDRrs: + case ARM::t2LDRs: // FIXME: don't use t2LDRs to access frame. + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isReg() && + MI->getOperand(3).isImm() && + MI->getOperand(2).getReg() == 0 && + MI->getOperand(3).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::LDRi12: + case ARM::t2LDRi12: + case ARM::tRestore: + case ARM::VLDRD: + case ARM::VLDRS: + if (MI->getOperand(1).isFI() && + MI->getOperand(2).isImm() && + MI->getOperand(2).getImm() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::VLD1q64Pseudo: + if (MI->getOperand(1).isFI() && + MI->getOperand(0).getSubReg() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + case ARM::VLDMQIA: + if (MI->getOperand(1).isFI() && + MI->getOperand(0).getSubReg() == 0) { + FrameIndex = MI->getOperand(1).getIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + + return 0; +} + +MachineInstr* +ARMBaseInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const { + MachineInstrBuilder MIB = BuildMI(MF, DL, get(ARM::DBG_VALUE)) + .addFrameIndex(FrameIx).addImm(0).addImm(Offset).addMetadata(MDPtr); + return &*MIB; +} + +/// Create a copy of a const pool value. Update CPI to the new index and return +/// the label UID. +static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI) { + MachineConstantPool *MCP = MF.getConstantPool(); + ARMFunctionInfo *AFI = MF.getInfo(); + + const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI]; + assert(MCPE.isMachineConstantPoolEntry() && + "Expecting a machine constantpool entry!"); + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); + + unsigned PCLabelId = AFI->createPICLabelUId(); + ARMConstantPoolValue *NewCPV = 0; + // FIXME: The below assumes PIC relocation model and that the function + // is Thumb mode (t1 or t2). PCAdjustment would be 8 for ARM mode PIC, and + // zero for non-PIC in ARM or Thumb. The callers are all of thumb LDR + // instructions, so that's probably OK, but is PIC always correct when + // we get here? + if (ACPV->isGlobalValue()) + NewCPV = new ARMConstantPoolValue(ACPV->getGV(), PCLabelId, + ARMCP::CPValue, 4); + else if (ACPV->isExtSymbol()) + NewCPV = new ARMConstantPoolValue(MF.getFunction()->getContext(), + ACPV->getSymbol(), PCLabelId, 4); + else if (ACPV->isBlockAddress()) + NewCPV = new ARMConstantPoolValue(ACPV->getBlockAddress(), PCLabelId, + ARMCP::CPBlockAddress, 4); + else if (ACPV->isLSDA()) + NewCPV = new ARMConstantPoolValue(MF.getFunction(), PCLabelId, + ARMCP::CPLSDA, 4); + else + llvm_unreachable("Unexpected ARM constantpool value type!!"); + CPI = MCP->getConstantPoolIndex(NewCPV, MCPE.getAlignment()); + return PCLabelId; +} + +void ARMBaseInstrInfo:: +reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo &TRI) const { + unsigned Opcode = Orig->getOpcode(); + switch (Opcode) { + default: { + MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig); + MI->substituteRegister(Orig->getOperand(0).getReg(), DestReg, SubIdx, TRI); + MBB.insert(I, MI); + break; + } + case ARM::tLDRpci_pic: + case ARM::t2LDRpci_pic: { + MachineFunction &MF = *MBB.getParent(); + unsigned CPI = Orig->getOperand(1).getIndex(); + unsigned PCLabelId = duplicateCPV(MF, CPI); + MachineInstrBuilder MIB = BuildMI(MBB, I, Orig->getDebugLoc(), get(Opcode), + DestReg) + .addConstantPoolIndex(CPI).addImm(PCLabelId); + (*MIB).setMemRefs(Orig->memoperands_begin(), Orig->memoperands_end()); + break; + } + } +} + +MachineInstr * +ARMBaseInstrInfo::duplicate(MachineInstr *Orig, MachineFunction &MF) const { + MachineInstr *MI = TargetInstrInfoImpl::duplicate(Orig, MF); + switch(Orig->getOpcode()) { + case ARM::tLDRpci_pic: + case ARM::t2LDRpci_pic: { + unsigned CPI = Orig->getOperand(1).getIndex(); + unsigned PCLabelId = duplicateCPV(MF, CPI); + Orig->getOperand(1).setIndex(CPI); + Orig->getOperand(2).setImm(PCLabelId); + break; + } + } + return MI; +} + +bool ARMBaseInstrInfo::produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const { + int Opcode = MI0->getOpcode(); + if (Opcode == ARM::t2LDRpci || + Opcode == ARM::t2LDRpci_pic || + Opcode == ARM::tLDRpci || + Opcode == ARM::tLDRpci_pic || + Opcode == ARM::MOV_ga_dyn || + Opcode == ARM::MOV_ga_pcrel || + Opcode == ARM::MOV_ga_pcrel_ldr || + Opcode == ARM::t2MOV_ga_dyn || + Opcode == ARM::t2MOV_ga_pcrel) { + if (MI1->getOpcode() != Opcode) + return false; + if (MI0->getNumOperands() != MI1->getNumOperands()) + return false; + + const MachineOperand &MO0 = MI0->getOperand(1); + const MachineOperand &MO1 = MI1->getOperand(1); + if (MO0.getOffset() != MO1.getOffset()) + return false; + + if (Opcode == ARM::MOV_ga_dyn || + Opcode == ARM::MOV_ga_pcrel || + Opcode == ARM::MOV_ga_pcrel_ldr || + Opcode == ARM::t2MOV_ga_dyn || + Opcode == ARM::t2MOV_ga_pcrel) + // Ignore the PC labels. + return MO0.getGlobal() == MO1.getGlobal(); + + const MachineFunction *MF = MI0->getParent()->getParent(); + const MachineConstantPool *MCP = MF->getConstantPool(); + int CPI0 = MO0.getIndex(); + int CPI1 = MO1.getIndex(); + const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0]; + const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1]; + bool isARMCP0 = MCPE0.isMachineConstantPoolEntry(); + bool isARMCP1 = MCPE1.isMachineConstantPoolEntry(); + if (isARMCP0 && isARMCP1) { + ARMConstantPoolValue *ACPV0 = + static_cast(MCPE0.Val.MachineCPVal); + ARMConstantPoolValue *ACPV1 = + static_cast(MCPE1.Val.MachineCPVal); + return ACPV0->hasSameValue(ACPV1); + } else if (!isARMCP0 && !isARMCP1) { + return MCPE0.Val.ConstVal == MCPE1.Val.ConstVal; + } + return false; + } else if (Opcode == ARM::PICLDR) { + if (MI1->getOpcode() != Opcode) + return false; + if (MI0->getNumOperands() != MI1->getNumOperands()) + return false; + + unsigned Addr0 = MI0->getOperand(1).getReg(); + unsigned Addr1 = MI1->getOperand(1).getReg(); + if (Addr0 != Addr1) { + if (!MRI || + !TargetRegisterInfo::isVirtualRegister(Addr0) || + !TargetRegisterInfo::isVirtualRegister(Addr1)) + return false; + + // This assumes SSA form. + MachineInstr *Def0 = MRI->getVRegDef(Addr0); + MachineInstr *Def1 = MRI->getVRegDef(Addr1); + // Check if the loaded value, e.g. a constantpool of a global address, are + // the same. + if (!produceSameValue(Def0, Def1, MRI)) + return false; + } + + for (unsigned i = 3, e = MI0->getNumOperands(); i != e; ++i) { + // %vreg12 = PICLDR %vreg11, 0, pred:14, pred:%noreg + const MachineOperand &MO0 = MI0->getOperand(i); + const MachineOperand &MO1 = MI1->getOperand(i); + if (!MO0.isIdenticalTo(MO1)) + return false; + } + return true; + } + + return MI0->isIdenticalTo(MI1, MachineInstr::IgnoreVRegDefs); +} + +/// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to +/// determine if two loads are loading from the same base address. It should +/// only return true if the base pointers are the same and the only differences +/// between the two addresses is the offset. It also returns the offsets by +/// reference. +bool ARMBaseInstrInfo::areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, + int64_t &Offset2) const { + // Don't worry about Thumb: just ARM and Thumb2. + if (Subtarget.isThumb1Only()) return false; + + if (!Load1->isMachineOpcode() || !Load2->isMachineOpcode()) + return false; + + switch (Load1->getMachineOpcode()) { + default: + return false; + case ARM::LDRi12: + case ARM::LDRBi12: + case ARM::LDRD: + case ARM::LDRH: + case ARM::LDRSB: + case ARM::LDRSH: + case ARM::VLDRD: + case ARM::VLDRS: + case ARM::t2LDRi8: + case ARM::t2LDRDi8: + case ARM::t2LDRSHi8: + case ARM::t2LDRi12: + case ARM::t2LDRSHi12: + break; + } + + switch (Load2->getMachineOpcode()) { + default: + return false; + case ARM::LDRi12: + case ARM::LDRBi12: + case ARM::LDRD: + case ARM::LDRH: + case ARM::LDRSB: + case ARM::LDRSH: + case ARM::VLDRD: + case ARM::VLDRS: + case ARM::t2LDRi8: + case ARM::t2LDRDi8: + case ARM::t2LDRSHi8: + case ARM::t2LDRi12: + case ARM::t2LDRSHi12: + break; + } + + // Check if base addresses and chain operands match. + if (Load1->getOperand(0) != Load2->getOperand(0) || + Load1->getOperand(4) != Load2->getOperand(4)) + return false; + + // Index should be Reg0. + if (Load1->getOperand(3) != Load2->getOperand(3)) + return false; + + // Determine the offsets. + if (isa(Load1->getOperand(1)) && + isa(Load2->getOperand(1))) { + Offset1 = cast(Load1->getOperand(1))->getSExtValue(); + Offset2 = cast(Load2->getOperand(1))->getSExtValue(); + return true; + } + + return false; +} + +/// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to +/// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should +/// be scheduled togther. On some targets if two loads are loading from +/// addresses in the same cache line, it's better if they are scheduled +/// together. This function takes two integers that represent the load offsets +/// from the common base address. It returns true if it decides it's desirable +/// to schedule the two loads together. "NumLoads" is the number of loads that +/// have already been scheduled after Load1. +bool ARMBaseInstrInfo::shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const { + // Don't worry about Thumb: just ARM and Thumb2. + if (Subtarget.isThumb1Only()) return false; + + assert(Offset2 > Offset1); + + if ((Offset2 - Offset1) / 8 > 64) + return false; + + if (Load1->getMachineOpcode() != Load2->getMachineOpcode()) + return false; // FIXME: overly conservative? + + // Four loads in a row should be sufficient. + if (NumLoads >= 3) + return false; + + return true; +} + +bool ARMBaseInstrInfo::isSchedulingBoundary(const MachineInstr *MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const { + // Debug info is never a scheduling boundary. It's necessary to be explicit + // due to the special treatment of IT instructions below, otherwise a + // dbg_value followed by an IT will result in the IT instruction being + // considered a scheduling hazard, which is wrong. It should be the actual + // instruction preceding the dbg_value instruction(s), just like it is + // when debug info is not present. + if (MI->isDebugValue()) + return false; + + // Terminators and labels can't be scheduled around. + if (MI->getDesc().isTerminator() || MI->isLabel()) + return true; + + // Treat the start of the IT block as a scheduling boundary, but schedule + // t2IT along with all instructions following it. + // FIXME: This is a big hammer. But the alternative is to add all potential + // true and anti dependencies to IT block instructions as implicit operands + // to the t2IT instruction. The added compile time and complexity does not + // seem worth it. + MachineBasicBlock::const_iterator I = MI; + // Make sure to skip any dbg_value instructions + while (++I != MBB->end() && I->isDebugValue()) + ; + if (I != MBB->end() && I->getOpcode() == ARM::t2IT) + return true; + + // Don't attempt to schedule around any instruction that defines + // a stack-oriented pointer, as it's unlikely to be profitable. This + // saves compile time, because it doesn't require every single + // stack slot reference to depend on the instruction that does the + // modification. + if (MI->definesRegister(ARM::SP)) + return true; + + return false; +} + +bool ARMBaseInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumCyles, + unsigned ExtraPredCycles, + float Probability, + float Confidence) const { + if (!NumCyles) + return false; + + // Attempt to estimate the relative costs of predication versus branching. + float UnpredCost = Probability * NumCyles; + UnpredCost += 1.0; // The branch itself + UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); + + return (float)(NumCyles + ExtraPredCycles) < UnpredCost; +} + +bool ARMBaseInstrInfo:: +isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned TCycles, unsigned TExtra, + MachineBasicBlock &FMBB, + unsigned FCycles, unsigned FExtra, + float Probability, float Confidence) const { + if (!TCycles || !FCycles) + return false; + + // Attempt to estimate the relative costs of predication versus branching. + float UnpredCost = Probability * TCycles + (1.0 - Probability) * FCycles; + UnpredCost += 1.0; // The branch itself + UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); + + return (float)(TCycles + FCycles + TExtra + FExtra) < UnpredCost; +} + +/// getInstrPredicate - If instruction is predicated, returns its predicate +/// condition, otherwise returns AL. It also returns the condition code +/// register by reference. +ARMCC::CondCodes +llvm::getInstrPredicate(const MachineInstr *MI, unsigned &PredReg) { + int PIdx = MI->findFirstPredOperandIdx(); + if (PIdx == -1) { + PredReg = 0; + return ARMCC::AL; + } + + PredReg = MI->getOperand(PIdx+1).getReg(); + return (ARMCC::CondCodes)MI->getOperand(PIdx).getImm(); +} + + +int llvm::getMatchingCondBranchOpcode(int Opc) { + if (Opc == ARM::B) + return ARM::Bcc; + else if (Opc == ARM::tB) + return ARM::tBcc; + else if (Opc == ARM::t2B) + return ARM::t2Bcc; + + llvm_unreachable("Unknown unconditional branch opcode!"); + return 0; +} + + +void llvm::emitARMRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII, unsigned MIFlags) { + bool isSub = NumBytes < 0; + if (isSub) NumBytes = -NumBytes; + + while (NumBytes) { + unsigned RotAmt = ARM_AM::getSOImmValRotate(NumBytes); + unsigned ThisVal = NumBytes & ARM_AM::rotr32(0xFF, RotAmt); + assert(ThisVal && "Didn't extract field correctly"); + + // We will handle these bits from offset, clear them. + NumBytes &= ~ThisVal; + + assert(ARM_AM::getSOImmVal(ThisVal) != -1 && "Bit extraction didn't work?"); + + // Build the new ADD / SUB. + unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri; + BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg) + .addReg(BaseReg, RegState::Kill).addImm(ThisVal) + .addImm((unsigned)Pred).addReg(PredReg).addReg(0) + .setMIFlags(MIFlags); + BaseReg = DestReg; + } +} + +bool llvm::rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII) { + unsigned Opcode = MI.getOpcode(); + const TargetInstrDesc &Desc = MI.getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + bool isSub = false; + + // Memory operands in inline assembly always use AddrMode2. + if (Opcode == ARM::INLINEASM) + AddrMode = ARMII::AddrMode2; + + if (Opcode == ARM::ADDri) { + Offset += MI.getOperand(FrameRegIdx+1).getImm(); + if (Offset == 0) { + // Turn it into a move. + MI.setDesc(TII.get(ARM::MOVr)); + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.RemoveOperand(FrameRegIdx+1); + Offset = 0; + return true; + } else if (Offset < 0) { + Offset = -Offset; + isSub = true; + MI.setDesc(TII.get(ARM::SUBri)); + } + + // Common case: small offset, fits into instruction. + if (ARM_AM::getSOImmVal(Offset) != -1) { + // Replace the FrameIndex with sp / fp + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset); + Offset = 0; + return true; + } + + // Otherwise, pull as much of the immedidate into this ADDri/SUBri + // as possible. + unsigned RotAmt = ARM_AM::getSOImmValRotate(Offset); + unsigned ThisImmVal = Offset & ARM_AM::rotr32(0xFF, RotAmt); + + // We will handle these bits from offset, clear them. + Offset &= ~ThisImmVal; + + // Get the properly encoded SOImmVal field. + assert(ARM_AM::getSOImmVal(ThisImmVal) != -1 && + "Bit extraction didn't work?"); + MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal); + } else { + unsigned ImmIdx = 0; + int InstrOffs = 0; + unsigned NumBits = 0; + unsigned Scale = 1; + switch (AddrMode) { + case ARMII::AddrMode_i12: { + ImmIdx = FrameRegIdx + 1; + InstrOffs = MI.getOperand(ImmIdx).getImm(); + NumBits = 12; + break; + } + case ARMII::AddrMode2: { + ImmIdx = FrameRegIdx+2; + InstrOffs = ARM_AM::getAM2Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM2Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 12; + break; + } + case ARMII::AddrMode3: { + ImmIdx = FrameRegIdx+2; + InstrOffs = ARM_AM::getAM3Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM3Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 8; + break; + } + case ARMII::AddrMode4: + case ARMII::AddrMode6: + // Can't fold any offset even if it's zero. + return false; + case ARMII::AddrMode5: { + ImmIdx = FrameRegIdx+1; + InstrOffs = ARM_AM::getAM5Offset(MI.getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM5Op(MI.getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs *= -1; + NumBits = 8; + Scale = 4; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + Offset += InstrOffs * Scale; + assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + if (Offset < 0) { + Offset = -Offset; + isSub = true; + } + + // Attempt to fold address comp. if opcode has offset bits + if (NumBits > 0) { + // Common case: small offset, fits into instruction. + MachineOperand &ImmOp = MI.getOperand(ImmIdx); + int ImmedOffset = Offset / Scale; + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) { + // Replace the FrameIndex with sp + MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); + // FIXME: When addrmode2 goes away, this will simplify (like the + // T2 version), as the LDR.i12 versions don't need the encoding + // tricks for the offset value. + if (isSub) { + if (AddrMode == ARMII::AddrMode_i12) + ImmedOffset = -ImmedOffset; + else + ImmedOffset |= 1 << NumBits; + } + ImmOp.ChangeToImmediate(ImmedOffset); + Offset = 0; + return true; + } + + // Otherwise, it didn't fit. Pull in what we can to simplify the immed. + ImmedOffset = ImmedOffset & Mask; + if (isSub) { + if (AddrMode == ARMII::AddrMode_i12) + ImmedOffset = -ImmedOffset; + else + ImmedOffset |= 1 << NumBits; + } + ImmOp.ChangeToImmediate(ImmedOffset); + Offset &= ~(Mask*Scale); + } + } + + Offset = (isSub) ? -Offset : Offset; + return Offset == 0; +} + +bool ARMBaseInstrInfo:: +AnalyzeCompare(const MachineInstr *MI, unsigned &SrcReg, int &CmpMask, + int &CmpValue) const { + switch (MI->getOpcode()) { + default: break; + case ARM::CMPri: + case ARM::t2CMPri: + SrcReg = MI->getOperand(0).getReg(); + CmpMask = ~0; + CmpValue = MI->getOperand(1).getImm(); + return true; + case ARM::TSTri: + case ARM::t2TSTri: + SrcReg = MI->getOperand(0).getReg(); + CmpMask = MI->getOperand(1).getImm(); + CmpValue = 0; + return true; + } + + return false; +} + +/// isSuitableForMask - Identify a suitable 'and' instruction that +/// operates on the given source register and applies the same mask +/// as a 'tst' instruction. Provide a limited look-through for copies. +/// When successful, MI will hold the found instruction. +static bool isSuitableForMask(MachineInstr *&MI, unsigned SrcReg, + int CmpMask, bool CommonUse) { + switch (MI->getOpcode()) { + case ARM::ANDri: + case ARM::t2ANDri: + if (CmpMask != MI->getOperand(2).getImm()) + return false; + if (SrcReg == MI->getOperand(CommonUse ? 1 : 0).getReg()) + return true; + break; + case ARM::COPY: { + // Walk down one instruction which is potentially an 'and'. + const MachineInstr &Copy = *MI; + MachineBasicBlock::iterator AND( + llvm::next(MachineBasicBlock::iterator(MI))); + if (AND == MI->getParent()->end()) return false; + MI = AND; + return isSuitableForMask(MI, Copy.getOperand(0).getReg(), + CmpMask, true); + } + } + + return false; +} + +/// OptimizeCompareInstr - Convert the instruction supplying the argument to the +/// comparison into one that sets the zero bit in the flags register. +bool ARMBaseInstrInfo:: +OptimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, int CmpMask, + int CmpValue, const MachineRegisterInfo *MRI) const { + if (CmpValue != 0) + return false; + + MachineRegisterInfo::def_iterator DI = MRI->def_begin(SrcReg); + if (llvm::next(DI) != MRI->def_end()) + // Only support one definition. + return false; + + MachineInstr *MI = &*DI; + + // Masked compares sometimes use the same register as the corresponding 'and'. + if (CmpMask != ~0) { + if (!isSuitableForMask(MI, SrcReg, CmpMask, false)) { + MI = 0; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg), + UE = MRI->use_end(); UI != UE; ++UI) { + if (UI->getParent() != CmpInstr->getParent()) continue; + MachineInstr *PotentialAND = &*UI; + if (!isSuitableForMask(PotentialAND, SrcReg, CmpMask, true)) + continue; + MI = PotentialAND; + break; + } + if (!MI) return false; + } + } + + // Conservatively refuse to convert an instruction which isn't in the same BB + // as the comparison. + if (MI->getParent() != CmpInstr->getParent()) + return false; + + // Check that CPSR isn't set between the comparison instruction and the one we + // want to change. + MachineBasicBlock::const_iterator I = CmpInstr, E = MI, + B = MI->getParent()->begin(); + + // Early exit if CmpInstr is at the beginning of the BB. + if (I == B) return false; + + --I; + for (; I != E; --I) { + const MachineInstr &Instr = *I; + + for (unsigned IO = 0, EO = Instr.getNumOperands(); IO != EO; ++IO) { + const MachineOperand &MO = Instr.getOperand(IO); + if (!MO.isReg()) continue; + + // This instruction modifies or uses CPSR after the one we want to + // change. We can't do this transformation. + if (MO.getReg() == ARM::CPSR) + return false; + } + + if (I == B) + // The 'and' is below the comparison instruction. + return false; + } + + // Set the "zero" bit in CPSR. + switch (MI->getOpcode()) { + default: break; + case ARM::ADDri: + case ARM::ANDri: + case ARM::t2ANDri: + case ARM::SUBri: + case ARM::t2ADDri: + case ARM::t2SUBri: + // Toggle the optional operand to CPSR. + MI->getOperand(5).setReg(ARM::CPSR); + MI->getOperand(5).setIsDef(true); + CmpInstr->eraseFromParent(); + return true; + } + + return false; +} + +bool ARMBaseInstrInfo::FoldImmediate(MachineInstr *UseMI, + MachineInstr *DefMI, unsigned Reg, + MachineRegisterInfo *MRI) const { + // Fold large immediates into add, sub, or, xor. + unsigned DefOpc = DefMI->getOpcode(); + if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm) + return false; + if (!DefMI->getOperand(1).isImm()) + // Could be t2MOVi32imm + return false; + + if (!MRI->hasOneNonDBGUse(Reg)) + return false; + + unsigned UseOpc = UseMI->getOpcode(); + unsigned NewUseOpc = 0; + uint32_t ImmVal = (uint32_t)DefMI->getOperand(1).getImm(); + uint32_t SOImmValV1 = 0, SOImmValV2 = 0; + bool Commute = false; + switch (UseOpc) { + default: return false; + case ARM::SUBrr: + case ARM::ADDrr: + case ARM::ORRrr: + case ARM::EORrr: + case ARM::t2SUBrr: + case ARM::t2ADDrr: + case ARM::t2ORRrr: + case ARM::t2EORrr: { + Commute = UseMI->getOperand(2).getReg() != Reg; + switch (UseOpc) { + default: break; + case ARM::SUBrr: { + if (Commute) + return false; + ImmVal = -ImmVal; + NewUseOpc = ARM::SUBri; + // Fallthrough + } + case ARM::ADDrr: + case ARM::ORRrr: + case ARM::EORrr: { + if (!ARM_AM::isSOImmTwoPartVal(ImmVal)) + return false; + SOImmValV1 = (uint32_t)ARM_AM::getSOImmTwoPartFirst(ImmVal); + SOImmValV2 = (uint32_t)ARM_AM::getSOImmTwoPartSecond(ImmVal); + switch (UseOpc) { + default: break; + case ARM::ADDrr: NewUseOpc = ARM::ADDri; break; + case ARM::ORRrr: NewUseOpc = ARM::ORRri; break; + case ARM::EORrr: NewUseOpc = ARM::EORri; break; + } + break; + } + case ARM::t2SUBrr: { + if (Commute) + return false; + ImmVal = -ImmVal; + NewUseOpc = ARM::t2SUBri; + // Fallthrough + } + case ARM::t2ADDrr: + case ARM::t2ORRrr: + case ARM::t2EORrr: { + if (!ARM_AM::isT2SOImmTwoPartVal(ImmVal)) + return false; + SOImmValV1 = (uint32_t)ARM_AM::getT2SOImmTwoPartFirst(ImmVal); + SOImmValV2 = (uint32_t)ARM_AM::getT2SOImmTwoPartSecond(ImmVal); + switch (UseOpc) { + default: break; + case ARM::t2ADDrr: NewUseOpc = ARM::t2ADDri; break; + case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri; break; + case ARM::t2EORrr: NewUseOpc = ARM::t2EORri; break; + } + break; + } + } + } + } + + unsigned OpIdx = Commute ? 2 : 1; + unsigned Reg1 = UseMI->getOperand(OpIdx).getReg(); + bool isKill = UseMI->getOperand(OpIdx).isKill(); + unsigned NewReg = MRI->createVirtualRegister(MRI->getRegClass(Reg)); + AddDefaultCC(AddDefaultPred(BuildMI(*UseMI->getParent(), + *UseMI, UseMI->getDebugLoc(), + get(NewUseOpc), NewReg) + .addReg(Reg1, getKillRegState(isKill)) + .addImm(SOImmValV1))); + UseMI->setDesc(get(NewUseOpc)); + UseMI->getOperand(1).setReg(NewReg); + UseMI->getOperand(1).setIsKill(); + UseMI->getOperand(2).ChangeToImmediate(SOImmValV2); + DefMI->eraseFromParent(); + return true; +} + +unsigned +ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, + const MachineInstr *MI) const { + if (!ItinData || ItinData->isEmpty()) + return 1; + + const TargetInstrDesc &Desc = MI->getDesc(); + unsigned Class = Desc.getSchedClass(); + unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; + if (UOps) + return UOps; + + unsigned Opc = MI->getOpcode(); + switch (Opc) { + default: + llvm_unreachable("Unexpected multi-uops instruction!"); + break; + case ARM::VLDMQIA: + case ARM::VLDMQDB: + case ARM::VSTMQIA: + case ARM::VSTMQDB: + return 2; + + // The number of uOps for load / store multiple are determined by the number + // registers. + // + // On Cortex-A8, each pair of register loads / stores can be scheduled on the + // same cycle. The scheduling for the first load / store must be done + // separately by assuming the the address is not 64-bit aligned. + // + // On Cortex-A9, the formula is simply (#reg / 2) + (#reg % 2). If the address + // is not 64-bit aligned, then AGU would take an extra cycle. For VFP / NEON + // load / store multiple, the formula is (#reg / 2) + (#reg % 2) + 1. + case ARM::VLDMDIA: + case ARM::VLDMDDB: + case ARM::VLDMDIA_UPD: + case ARM::VLDMDDB_UPD: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: + case ARM::VSTMDIA: + case ARM::VSTMDDB: + case ARM::VSTMDIA_UPD: + case ARM::VSTMDDB_UPD: + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: { + unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands(); + return (NumRegs / 2) + (NumRegs % 2) + 1; + } + + case ARM::LDMIA_RET: + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + case ARM::LDMIA_UPD: + case ARM::LDMDA_UPD: + case ARM::LDMDB_UPD: + case ARM::LDMIB_UPD: + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + case ARM::STMIA_UPD: + case ARM::STMDA_UPD: + case ARM::STMDB_UPD: + case ARM::STMIB_UPD: + case ARM::tLDMIA: + case ARM::tLDMIA_UPD: + case ARM::tSTMIA: + case ARM::tSTMIA_UPD: + case ARM::tPOP_RET: + case ARM::tPOP: + case ARM::tPUSH: + case ARM::t2LDMIA_RET: + case ARM::t2LDMIA: + case ARM::t2LDMDB: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: + case ARM::t2STMIA: + case ARM::t2STMDB: + case ARM::t2STMIA_UPD: + case ARM::t2STMDB_UPD: { + unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands() + 1; + if (Subtarget.isCortexA8()) { + if (NumRegs < 4) + return 2; + // 4 registers would be issued: 2, 2. + // 5 registers would be issued: 2, 2, 1. + UOps = (NumRegs / 2); + if (NumRegs % 2) + ++UOps; + return UOps; + } else if (Subtarget.isCortexA9()) { + UOps = (NumRegs / 2); + // If there are odd number of registers or if it's not 64-bit aligned, + // then it takes an extra AGU (Address Generation Unit) cycle. + if ((NumRegs % 2) || + !MI->hasOneMemOperand() || + (*MI->memoperands_begin())->getAlignment() < 8) + ++UOps; + return UOps; + } else { + // Assume the worst. + return NumRegs; + } + } + } +} + +int +ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefClass, + unsigned DefIdx, unsigned DefAlign) const { + int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + if (RegNo <= 0) + // Def is the address writeback. + return ItinData->getOperandCycle(DefClass, DefIdx); + + int DefCycle; + if (Subtarget.isCortexA8()) { + // (regno / 2) + (regno % 2) + 1 + DefCycle = RegNo / 2 + 1; + if (RegNo % 2) + ++DefCycle; + } else if (Subtarget.isCortexA9()) { + DefCycle = RegNo; + bool isSLoad = false; + + switch (DefTID.getOpcode()) { + default: break; + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: + isSLoad = true; + break; + } + + // If there are odd number of 'S' registers or if it's not 64-bit aligned, + // then it takes an extra cycle. + if ((isSLoad && (RegNo % 2)) || DefAlign < 8) + ++DefCycle; + } else { + // Assume the worst. + DefCycle = RegNo + 2; + } + + return DefCycle; +} + +int +ARMBaseInstrInfo::getLDMDefCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefClass, + unsigned DefIdx, unsigned DefAlign) const { + int RegNo = (int)(DefIdx+1) - DefTID.getNumOperands() + 1; + if (RegNo <= 0) + // Def is the address writeback. + return ItinData->getOperandCycle(DefClass, DefIdx); + + int DefCycle; + if (Subtarget.isCortexA8()) { + // 4 registers would be issued: 1, 2, 1. + // 5 registers would be issued: 1, 2, 2. + DefCycle = RegNo / 2; + if (DefCycle < 1) + DefCycle = 1; + // Result latency is issue cycle + 2: E2. + DefCycle += 2; + } else if (Subtarget.isCortexA9()) { + DefCycle = (RegNo / 2); + // If there are odd number of registers or if it's not 64-bit aligned, + // then it takes an extra AGU (Address Generation Unit) cycle. + if ((RegNo % 2) || DefAlign < 8) + ++DefCycle; + // Result latency is AGU cycles + 2. + DefCycle += 2; + } else { + // Assume the worst. + DefCycle = RegNo + 2; + } + + return DefCycle; +} + +int +ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &UseTID, + unsigned UseClass, + unsigned UseIdx, unsigned UseAlign) const { + int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + if (RegNo <= 0) + return ItinData->getOperandCycle(UseClass, UseIdx); + + int UseCycle; + if (Subtarget.isCortexA8()) { + // (regno / 2) + (regno % 2) + 1 + UseCycle = RegNo / 2 + 1; + if (RegNo % 2) + ++UseCycle; + } else if (Subtarget.isCortexA9()) { + UseCycle = RegNo; + bool isSStore = false; + + switch (UseTID.getOpcode()) { + default: break; + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: + isSStore = true; + break; + } + + // If there are odd number of 'S' registers or if it's not 64-bit aligned, + // then it takes an extra cycle. + if ((isSStore && (RegNo % 2)) || UseAlign < 8) + ++UseCycle; + } else { + // Assume the worst. + UseCycle = RegNo + 2; + } + + return UseCycle; +} + +int +ARMBaseInstrInfo::getSTMUseCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &UseTID, + unsigned UseClass, + unsigned UseIdx, unsigned UseAlign) const { + int RegNo = (int)(UseIdx+1) - UseTID.getNumOperands() + 1; + if (RegNo <= 0) + return ItinData->getOperandCycle(UseClass, UseIdx); + + int UseCycle; + if (Subtarget.isCortexA8()) { + UseCycle = RegNo / 2; + if (UseCycle < 2) + UseCycle = 2; + // Read in E3. + UseCycle += 2; + } else if (Subtarget.isCortexA9()) { + UseCycle = (RegNo / 2); + // If there are odd number of registers or if it's not 64-bit aligned, + // then it takes an extra AGU (Address Generation Unit) cycle. + if ((RegNo % 2) || UseAlign < 8) + ++UseCycle; + } else { + // Assume the worst. + UseCycle = 1; + } + return UseCycle; +} + +int +ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefIdx, unsigned DefAlign, + const TargetInstrDesc &UseTID, + unsigned UseIdx, unsigned UseAlign) const { + unsigned DefClass = DefTID.getSchedClass(); + unsigned UseClass = UseTID.getSchedClass(); + + if (DefIdx < DefTID.getNumDefs() && UseIdx < UseTID.getNumOperands()) + return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx); + + // This may be a def / use of a variable_ops instruction, the operand + // latency might be determinable dynamically. Let the target try to + // figure it out. + int DefCycle = -1; + bool LdmBypass = false; + switch (DefTID.getOpcode()) { + default: + DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); + break; + + case ARM::VLDMDIA: + case ARM::VLDMDDB: + case ARM::VLDMDIA_UPD: + case ARM::VLDMDDB_UPD: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: + DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + break; + + case ARM::LDMIA_RET: + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + case ARM::LDMIA_UPD: + case ARM::LDMDA_UPD: + case ARM::LDMDB_UPD: + case ARM::LDMIB_UPD: + case ARM::tLDMIA: + case ARM::tLDMIA_UPD: + case ARM::tPUSH: + case ARM::t2LDMIA_RET: + case ARM::t2LDMIA: + case ARM::t2LDMDB: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: + LdmBypass = 1; + DefCycle = getLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); + break; + } + + if (DefCycle == -1) + // We can't seem to determine the result latency of the def, assume it's 2. + DefCycle = 2; + + int UseCycle = -1; + switch (UseTID.getOpcode()) { + default: + UseCycle = ItinData->getOperandCycle(UseClass, UseIdx); + break; + + case ARM::VSTMDIA: + case ARM::VSTMDDB: + case ARM::VSTMDIA_UPD: + case ARM::VSTMDDB_UPD: + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: + UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + break; + + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + case ARM::STMIA_UPD: + case ARM::STMDA_UPD: + case ARM::STMDB_UPD: + case ARM::STMIB_UPD: + case ARM::tSTMIA: + case ARM::tSTMIA_UPD: + case ARM::tPOP_RET: + case ARM::tPOP: + case ARM::t2STMIA: + case ARM::t2STMDB: + case ARM::t2STMIA_UPD: + case ARM::t2STMDB_UPD: + UseCycle = getSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); + break; + } + + if (UseCycle == -1) + // Assume it's read in the first stage. + UseCycle = 1; + + UseCycle = DefCycle - UseCycle + 1; + if (UseCycle > 0) { + if (LdmBypass) { + // It's a variable_ops instruction so we can't use DefIdx here. Just use + // first def operand. + if (ItinData->hasPipelineForwarding(DefClass, DefTID.getNumOperands()-1, + UseClass, UseIdx)) + --UseCycle; + } else if (ItinData->hasPipelineForwarding(DefClass, DefIdx, + UseClass, UseIdx)) { + --UseCycle; + } + } + + return UseCycle; +} + +int +ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const { + if (DefMI->isCopyLike() || DefMI->isInsertSubreg() || + DefMI->isRegSequence() || DefMI->isImplicitDef()) + return 1; + + const TargetInstrDesc &DefTID = DefMI->getDesc(); + if (!ItinData || ItinData->isEmpty()) + return DefTID.mayLoad() ? 3 : 1; + + const TargetInstrDesc &UseTID = UseMI->getDesc(); + const MachineOperand &DefMO = DefMI->getOperand(DefIdx); + if (DefMO.getReg() == ARM::CPSR) { + if (DefMI->getOpcode() == ARM::FMSTAT) { + // fpscr -> cpsr stalls over 20 cycles on A8 (and earlier?) + return Subtarget.isCortexA9() ? 1 : 20; + } + + // CPSR set and branch can be paired in the same cycle. + if (UseTID.isBranch()) + return 0; + } + + unsigned DefAlign = DefMI->hasOneMemOperand() + ? (*DefMI->memoperands_begin())->getAlignment() : 0; + unsigned UseAlign = UseMI->hasOneMemOperand() + ? (*UseMI->memoperands_begin())->getAlignment() : 0; + int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, + UseTID, UseIdx, UseAlign); + + if (Latency > 1 && + (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { + // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] + // variants are one cycle cheaper. + switch (DefTID.getOpcode()) { + default: break; + case ARM::LDRrs: + case ARM::LDRBrs: { + unsigned ShOpVal = DefMI->getOperand(3).getImm(); + unsigned ShImm = ARM_AM::getAM2Offset(ShOpVal); + if (ShImm == 0 || + (ShImm == 2 && ARM_AM::getAM2ShiftOpc(ShOpVal) == ARM_AM::lsl)) + --Latency; + break; + } + case ARM::t2LDRs: + case ARM::t2LDRBs: + case ARM::t2LDRHs: + case ARM::t2LDRSHs: { + // Thumb2 mode: lsl only. + unsigned ShAmt = DefMI->getOperand(3).getImm(); + if (ShAmt == 0 || ShAmt == 2) + --Latency; + break; + } + } + } + + return Latency; +} + +int +ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, unsigned UseIdx) const { + if (!DefNode->isMachineOpcode()) + return 1; + + const TargetInstrDesc &DefTID = get(DefNode->getMachineOpcode()); + + if (isZeroCost(DefTID.Opcode)) + return 0; + + if (!ItinData || ItinData->isEmpty()) + return DefTID.mayLoad() ? 3 : 1; + + if (!UseNode->isMachineOpcode()) { + int Latency = ItinData->getOperandCycle(DefTID.getSchedClass(), DefIdx); + if (Subtarget.isCortexA9()) + return Latency <= 2 ? 1 : Latency - 1; + else + return Latency <= 3 ? 1 : Latency - 2; + } + + const TargetInstrDesc &UseTID = get(UseNode->getMachineOpcode()); + const MachineSDNode *DefMN = dyn_cast(DefNode); + unsigned DefAlign = !DefMN->memoperands_empty() + ? (*DefMN->memoperands_begin())->getAlignment() : 0; + const MachineSDNode *UseMN = dyn_cast(UseNode); + unsigned UseAlign = !UseMN->memoperands_empty() + ? (*UseMN->memoperands_begin())->getAlignment() : 0; + int Latency = getOperandLatency(ItinData, DefTID, DefIdx, DefAlign, + UseTID, UseIdx, UseAlign); + + if (Latency > 1 && + (Subtarget.isCortexA8() || Subtarget.isCortexA9())) { + // FIXME: Shifter op hack: no shift (i.e. [r +/- r]) or [r + r << 2] + // variants are one cycle cheaper. + switch (DefTID.getOpcode()) { + default: break; + case ARM::LDRrs: + case ARM::LDRBrs: { + unsigned ShOpVal = + cast(DefNode->getOperand(2))->getZExtValue(); + unsigned ShImm = ARM_AM::getAM2Offset(ShOpVal); + if (ShImm == 0 || + (ShImm == 2 && ARM_AM::getAM2ShiftOpc(ShOpVal) == ARM_AM::lsl)) + --Latency; + break; + } + case ARM::t2LDRs: + case ARM::t2LDRBs: + case ARM::t2LDRHs: + case ARM::t2LDRSHs: { + // Thumb2 mode: lsl only. + unsigned ShAmt = + cast(DefNode->getOperand(2))->getZExtValue(); + if (ShAmt == 0 || ShAmt == 2) + --Latency; + break; + } + } + } + + return Latency; +} + +int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, + unsigned *PredCost) const { + if (MI->isCopyLike() || MI->isInsertSubreg() || + MI->isRegSequence() || MI->isImplicitDef()) + return 1; + + if (!ItinData || ItinData->isEmpty()) + return 1; + + const TargetInstrDesc &TID = MI->getDesc(); + unsigned Class = TID.getSchedClass(); + unsigned UOps = ItinData->Itineraries[Class].NumMicroOps; + if (PredCost && TID.hasImplicitDefOfPhysReg(ARM::CPSR)) + // When predicated, CPSR is an additional source operand for CPSR updating + // instructions, this apparently increases their latencies. + *PredCost = 1; + if (UOps) + return ItinData->getStageLatency(Class); + return getNumMicroOps(ItinData, MI); +} + +int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, + SDNode *Node) const { + if (!Node->isMachineOpcode()) + return 1; + + if (!ItinData || ItinData->isEmpty()) + return 1; + + unsigned Opcode = Node->getMachineOpcode(); + switch (Opcode) { + default: + return ItinData->getStageLatency(get(Opcode).getSchedClass()); + case ARM::VLDMQIA: + case ARM::VLDMQDB: + case ARM::VSTMQIA: + case ARM::VSTMQDB: + return 2; + } +} + +bool ARMBaseInstrInfo:: +hasHighOperandLatency(const InstrItineraryData *ItinData, + const MachineRegisterInfo *MRI, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const { + unsigned DDomain = DefMI->getDesc().TSFlags & ARMII::DomainMask; + unsigned UDomain = UseMI->getDesc().TSFlags & ARMII::DomainMask; + if (Subtarget.isCortexA8() && + (DDomain == ARMII::DomainVFP || UDomain == ARMII::DomainVFP)) + // CortexA8 VFP instructions are not pipelined. + return true; + + // Hoist VFP / NEON instructions with 4 or higher latency. + int Latency = getOperandLatency(ItinData, DefMI, DefIdx, UseMI, UseIdx); + if (Latency <= 3) + return false; + return DDomain == ARMII::DomainVFP || DDomain == ARMII::DomainNEON || + UDomain == ARMII::DomainVFP || UDomain == ARMII::DomainNEON; +} + +bool ARMBaseInstrInfo:: +hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const { + if (!ItinData || ItinData->isEmpty()) + return false; + + unsigned DDomain = DefMI->getDesc().TSFlags & ARMII::DomainMask; + if (DDomain == ARMII::DomainGeneral) { + unsigned DefClass = DefMI->getDesc().getSchedClass(); + int DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); + return (DefCycle != -1 && DefCycle <= 2); + } + return false; +} + +bool +ARMBaseInstrInfo::isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc, + unsigned &AddSubOpc, + bool &NegAcc, bool &HasLane) const { + DenseMap::const_iterator I = MLxEntryMap.find(Opcode); + if (I == MLxEntryMap.end()) + return false; + + const ARM_MLxEntry &Entry = ARM_MLxTable[I->second]; + MulOpc = Entry.MulOpc; + AddSubOpc = Entry.AddSubOpc; + NegAcc = Entry.NegAcc; + HasLane = Entry.HasLane; + return true; +} diff --git a/final/lib/Target/ARM/ARMBaseInstrInfo.h b/final/lib/Target/ARM/ARMBaseInstrInfo.h new file mode 100644 index 00000000000..228b6cd9141 --- /dev/null +++ b/final/lib/Target/ARM/ARMBaseInstrInfo.h @@ -0,0 +1,528 @@ +//===- ARMBaseInstrInfo.h - ARM Base Instruction Information ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the Base ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMBASEINSTRUCTIONINFO_H +#define ARMBASEINSTRUCTIONINFO_H + +#include "ARM.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" + +namespace llvm { + class ARMSubtarget; + class ARMBaseRegisterInfo; + +/// ARMII - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace ARMII { + enum { + //===------------------------------------------------------------------===// + // Instruction Flags. + + //===------------------------------------------------------------------===// + // This four-bit field describes the addressing mode used. + + AddrModeMask = 0x1f, + AddrModeNone = 0, + AddrMode1 = 1, + AddrMode2 = 2, + AddrMode3 = 3, + AddrMode4 = 4, + AddrMode5 = 5, + AddrMode6 = 6, + AddrModeT1_1 = 7, + AddrModeT1_2 = 8, + AddrModeT1_4 = 9, + AddrModeT1_s = 10, // i8 * 4 for pc and sp relative data + AddrModeT2_i12 = 11, + AddrModeT2_i8 = 12, + AddrModeT2_so = 13, + AddrModeT2_pc = 14, // +/- i12 for pc relative data + AddrModeT2_i8s4 = 15, // i8 * 4 + AddrMode_i12 = 16, + + // Size* - Flags to keep track of the size of an instruction. + SizeShift = 5, + SizeMask = 7 << SizeShift, + SizeSpecial = 1, // 0 byte pseudo or special case. + Size8Bytes = 2, + Size4Bytes = 3, + Size2Bytes = 4, + + // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load + // and store ops only. Generic "updating" flag is used for ld/st multiple. + IndexModeShift = 8, + IndexModeMask = 3 << IndexModeShift, + IndexModePre = 1, + IndexModePost = 2, + IndexModeUpd = 3, + + //===------------------------------------------------------------------===// + // Instruction encoding formats. + // + FormShift = 10, + FormMask = 0x3f << FormShift, + + // Pseudo instructions + Pseudo = 0 << FormShift, + + // Multiply instructions + MulFrm = 1 << FormShift, + + // Branch instructions + BrFrm = 2 << FormShift, + BrMiscFrm = 3 << FormShift, + + // Data Processing instructions + DPFrm = 4 << FormShift, + DPSoRegFrm = 5 << FormShift, + + // Load and Store + LdFrm = 6 << FormShift, + StFrm = 7 << FormShift, + LdMiscFrm = 8 << FormShift, + StMiscFrm = 9 << FormShift, + LdStMulFrm = 10 << FormShift, + + LdStExFrm = 11 << FormShift, + + // Miscellaneous arithmetic instructions + ArithMiscFrm = 12 << FormShift, + SatFrm = 13 << FormShift, + + // Extend instructions + ExtFrm = 14 << FormShift, + + // VFP formats + VFPUnaryFrm = 15 << FormShift, + VFPBinaryFrm = 16 << FormShift, + VFPConv1Frm = 17 << FormShift, + VFPConv2Frm = 18 << FormShift, + VFPConv3Frm = 19 << FormShift, + VFPConv4Frm = 20 << FormShift, + VFPConv5Frm = 21 << FormShift, + VFPLdStFrm = 22 << FormShift, + VFPLdStMulFrm = 23 << FormShift, + VFPMiscFrm = 24 << FormShift, + + // Thumb format + ThumbFrm = 25 << FormShift, + + // Miscelleaneous format + MiscFrm = 26 << FormShift, + + // NEON formats + NGetLnFrm = 27 << FormShift, + NSetLnFrm = 28 << FormShift, + NDupFrm = 29 << FormShift, + NLdStFrm = 30 << FormShift, + N1RegModImmFrm= 31 << FormShift, + N2RegFrm = 32 << FormShift, + NVCVTFrm = 33 << FormShift, + NVDupLnFrm = 34 << FormShift, + N2RegVShLFrm = 35 << FormShift, + N2RegVShRFrm = 36 << FormShift, + N3RegFrm = 37 << FormShift, + N3RegVShFrm = 38 << FormShift, + NVExtFrm = 39 << FormShift, + NVMulSLFrm = 40 << FormShift, + NVTBLFrm = 41 << FormShift, + + //===------------------------------------------------------------------===// + // Misc flags. + + // UnaryDP - Indicates this is a unary data processing instruction, i.e. + // it doesn't have a Rn operand. + UnaryDP = 1 << 16, + + // Xform16Bit - Indicates this Thumb2 instruction may be transformed into + // a 16-bit Thumb instruction if certain conditions are met. + Xform16Bit = 1 << 17, + + //===------------------------------------------------------------------===// + // Code domain. + DomainShift = 18, + DomainMask = 7 << DomainShift, + DomainGeneral = 0 << DomainShift, + DomainVFP = 1 << DomainShift, + DomainNEON = 2 << DomainShift, + DomainNEONA8 = 4 << DomainShift, + + //===------------------------------------------------------------------===// + // Field shifts - such shifts are used to set field while generating + // machine instructions. + // + // FIXME: This list will need adjusting/fixing as the MC code emitter + // takes shape and the ARMCodeEmitter.cpp bits go away. + ShiftTypeShift = 4, + + M_BitShift = 5, + ShiftImmShift = 5, + ShiftShift = 7, + N_BitShift = 7, + ImmHiShift = 8, + SoRotImmShift = 8, + RegRsShift = 8, + ExtRotImmShift = 10, + RegRdLoShift = 12, + RegRdShift = 12, + RegRdHiShift = 16, + RegRnShift = 16, + S_BitShift = 20, + W_BitShift = 21, + AM3_I_BitShift = 22, + D_BitShift = 22, + U_BitShift = 23, + P_BitShift = 24, + I_BitShift = 25, + CondShift = 28 + }; +} + +class ARMBaseInstrInfo : public TargetInstrInfoImpl { + const ARMSubtarget &Subtarget; + +protected: + // Can be only subclassed. + explicit ARMBaseInstrInfo(const ARMSubtarget &STI); + +public: + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + virtual unsigned getUnindexedOpcode(unsigned Opc) const =0; + + virtual MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const; + + virtual const ARMBaseRegisterInfo &getRegisterInfo() const =0; + const ARMSubtarget &getSubtarget() const { return Subtarget; } + + ScheduleHazardRecognizer * + CreateTargetHazardRecognizer(const TargetMachine *TM, + const ScheduleDAG *DAG) const; + + ScheduleHazardRecognizer * + CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, + const ScheduleDAG *DAG) const; + + // Branch analysis. + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify = false) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond, + DebugLoc DL) const; + + virtual + bool ReverseBranchCondition(SmallVectorImpl &Cond) const; + + // Predication support. + bool isPredicated(const MachineInstr *MI) const { + int PIdx = MI->findFirstPredOperandIdx(); + return PIdx != -1 && MI->getOperand(PIdx).getImm() != ARMCC::AL; + } + + ARMCC::CondCodes getPredicate(const MachineInstr *MI) const { + int PIdx = MI->findFirstPredOperandIdx(); + return PIdx != -1 ? (ARMCC::CondCodes)MI->getOperand(PIdx).getImm() + : ARMCC::AL; + } + + virtual + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl &Pred) const; + + virtual + bool SubsumesPredicate(const SmallVectorImpl &Pred1, + const SmallVectorImpl &Pred2) const; + + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector &Pred) const; + + virtual bool isPredicable(MachineInstr *MI) const; + + /// GetInstSize - Returns the size of the specified MachineInstr. + /// + virtual unsigned GetInstSizeInBytes(const MachineInstr* MI) const; + + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + virtual void copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const; + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const; + + virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, + int FrameIx, + uint64_t Offset, + const MDNode *MDPtr, + DebugLoc DL) const; + + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SubIdx, + const MachineInstr *Orig, + const TargetRegisterInfo &TRI) const; + + MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; + + virtual bool produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1, + const MachineRegisterInfo *MRI) const; + + /// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to + /// determine if two loads are loading from the same base address. It should + /// only return true if the base pointers are the same and the only + /// differences between the two addresses is the offset. It also returns the + /// offsets by reference. + virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, + int64_t &Offset1, int64_t &Offset2)const; + + /// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to + /// determine (in conjuction with areLoadsFromSameBasePtr) if two loads should + /// be scheduled togther. On some targets if two loads are loading from + /// addresses in the same cache line, it's better if they are scheduled + /// together. This function takes two integers that represent the load offsets + /// from the common base address. It returns true if it decides it's desirable + /// to schedule the two loads together. "NumLoads" is the number of loads that + /// have already been scheduled after Load1. + virtual bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, + int64_t Offset1, int64_t Offset2, + unsigned NumLoads) const; + + virtual bool isSchedulingBoundary(const MachineInstr *MI, + const MachineBasicBlock *MBB, + const MachineFunction &MF) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, + unsigned NumCyles, unsigned ExtraPredCycles, + float Prob, float Confidence) const; + + virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumT, unsigned ExtraT, + MachineBasicBlock &FMBB, + unsigned NumF, unsigned ExtraF, + float Probability, float Confidence) const; + + virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, + unsigned NumCyles, + float Probability, + float Confidence) const { + return NumCyles == 1; + } + + /// AnalyzeCompare - For a comparison instruction, return the source register + /// in SrcReg and the value it compares against in CmpValue. Return true if + /// the comparison instruction can be analyzed. + virtual bool AnalyzeCompare(const MachineInstr *MI, unsigned &SrcReg, + int &CmpMask, int &CmpValue) const; + + /// OptimizeCompareInstr - Convert the instruction to set the zero flag so + /// that we can remove a "comparison with zero". + virtual bool OptimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, + int CmpMask, int CmpValue, + const MachineRegisterInfo *MRI) const; + + /// FoldImmediate - 'Reg' is known to be defined by a move immediate + /// instruction, try to fold the immediate into the use instruction. + virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, + unsigned Reg, MachineRegisterInfo *MRI) const; + + virtual unsigned getNumMicroOps(const InstrItineraryData *ItinData, + const MachineInstr *MI) const; + + virtual + int getOperandLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const; + virtual + int getOperandLatency(const InstrItineraryData *ItinData, + SDNode *DefNode, unsigned DefIdx, + SDNode *UseNode, unsigned UseIdx) const; +private: + int getVLDMDefCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefClass, + unsigned DefIdx, unsigned DefAlign) const; + int getLDMDefCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefClass, + unsigned DefIdx, unsigned DefAlign) const; + int getVSTMUseCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &UseTID, + unsigned UseClass, + unsigned UseIdx, unsigned UseAlign) const; + int getSTMUseCycle(const InstrItineraryData *ItinData, + const TargetInstrDesc &UseTID, + unsigned UseClass, + unsigned UseIdx, unsigned UseAlign) const; + int getOperandLatency(const InstrItineraryData *ItinData, + const TargetInstrDesc &DefTID, + unsigned DefIdx, unsigned DefAlign, + const TargetInstrDesc &UseTID, + unsigned UseIdx, unsigned UseAlign) const; + + int getInstrLatency(const InstrItineraryData *ItinData, + const MachineInstr *MI, unsigned *PredCost = 0) const; + + int getInstrLatency(const InstrItineraryData *ItinData, + SDNode *Node) const; + + bool hasHighOperandLatency(const InstrItineraryData *ItinData, + const MachineRegisterInfo *MRI, + const MachineInstr *DefMI, unsigned DefIdx, + const MachineInstr *UseMI, unsigned UseIdx) const; + bool hasLowDefLatency(const InstrItineraryData *ItinData, + const MachineInstr *DefMI, unsigned DefIdx) const; + +private: + /// Modeling special VFP / NEON fp MLA / MLS hazards. + + /// MLxEntryMap - Map fp MLA / MLS to the corresponding entry in the internal + /// MLx table. + DenseMap MLxEntryMap; + + /// MLxHazardOpcodes - Set of add / sub and multiply opcodes that would cause + /// stalls when scheduled together with fp MLA / MLS opcodes. + SmallSet MLxHazardOpcodes; + +public: + /// isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS + /// instruction. + bool isFpMLxInstruction(unsigned Opcode) const { + return MLxEntryMap.count(Opcode); + } + + /// isFpMLxInstruction - This version also returns the multiply opcode and the + /// addition / subtraction opcode to expand to. Return true for 'HasLane' for + /// the MLX instructions with an extra lane operand. + bool isFpMLxInstruction(unsigned Opcode, unsigned &MulOpc, + unsigned &AddSubOpc, bool &NegAcc, + bool &HasLane) const; + + /// canCauseFpMLxStall - Return true if an instruction of the specified opcode + /// will cause stalls when scheduled after (within 4-cycle window) a fp + /// MLA / MLS instruction. + bool canCauseFpMLxStall(unsigned Opcode) const { + return MLxHazardOpcodes.count(Opcode); + } +}; + +static inline +const MachineInstrBuilder &AddDefaultPred(const MachineInstrBuilder &MIB) { + return MIB.addImm((int64_t)ARMCC::AL).addReg(0); +} + +static inline +const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) { + return MIB.addReg(0); +} + +static inline +const MachineInstrBuilder &AddDefaultT1CC(const MachineInstrBuilder &MIB, + bool isDead = false) { + return MIB.addReg(ARM::CPSR, getDefRegState(true) | getDeadRegState(isDead)); +} + +static inline +const MachineInstrBuilder &AddNoT1CC(const MachineInstrBuilder &MIB) { + return MIB.addReg(0); +} + +static inline +bool isUncondBranchOpcode(int Opc) { + return Opc == ARM::B || Opc == ARM::tB || Opc == ARM::t2B; +} + +static inline +bool isCondBranchOpcode(int Opc) { + return Opc == ARM::Bcc || Opc == ARM::tBcc || Opc == ARM::t2Bcc; +} + +static inline +bool isJumpTableBranchOpcode(int Opc) { + return Opc == ARM::BR_JTr || Opc == ARM::BR_JTm || Opc == ARM::BR_JTadd || + Opc == ARM::tBR_JTr || Opc == ARM::t2BR_JT; +} + +static inline +bool isIndirectBranchOpcode(int Opc) { + return Opc == ARM::BX || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND; +} + +/// getInstrPredicate - If instruction is predicated, returns its predicate +/// condition, otherwise returns AL. It also returns the condition code +/// register by reference. +ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg); + +int getMatchingCondBranchOpcode(int Opc); + +/// emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of +/// instructions to materializea destreg = basereg + immediate in ARM / Thumb2 +/// code. +void emitARMRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII, unsigned MIFlags = 0); + +void emitT2RegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, int NumBytes, + ARMCC::CondCodes Pred, unsigned PredReg, + const ARMBaseInstrInfo &TII, unsigned MIFlags = 0); +void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, DebugLoc dl, + unsigned DestReg, unsigned BaseReg, + int NumBytes, const TargetInstrInfo &TII, + const ARMBaseRegisterInfo& MRI, + unsigned MIFlags = 0); + + +/// rewriteARMFrameIndex / rewriteT2FrameIndex - +/// Rewrite MI to access 'Offset' bytes from the FP. Return false if the +/// offset could not be handled directly in MI, and return the left-over +/// portion by reference. +bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII); + +bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, + unsigned FrameReg, int &Offset, + const ARMBaseInstrInfo &TII); + +} // End llvm namespace + +#endif diff --git a/final/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/final/lib/Target/ARM/ARMBaseRegisterInfo.cpp new file mode 100644 index 00000000000..9d7be660109 --- /dev/null +++ b/final/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -0,0 +1,1248 @@ +//===- ARMBaseRegisterInfo.cpp - ARM Register Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the base ARM implementation of TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMFrameLowering.h" +#include "ARMInstrInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMSubtarget.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +static cl::opt +ForceAllBaseRegAlloc("arm-force-base-reg-alloc", cl::Hidden, cl::init(false), + cl::desc("Force use of virtual base registers for stack load/store")); +static cl::opt +EnableLocalStackAlloc("enable-local-stack-alloc", cl::init(true), cl::Hidden, + cl::desc("Enable pre-regalloc stack frame index allocation")); +static cl::opt +EnableBasePointer("arm-use-base-pointer", cl::Hidden, cl::init(true), + cl::desc("Enable use of a base pointer for complex stack frames")); + +ARMBaseRegisterInfo::ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &sti) + : ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP), + TII(tii), STI(sti), + FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11), + BasePtr(ARM::R6) { +} + +const unsigned* +ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + static const unsigned CalleeSavedRegs[] = { + ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8, + ARM::R7, ARM::R6, ARM::R5, ARM::R4, + + ARM::D15, ARM::D14, ARM::D13, ARM::D12, + ARM::D11, ARM::D10, ARM::D9, ARM::D8, + 0 + }; + + static const unsigned DarwinCalleeSavedRegs[] = { + // Darwin ABI deviates from ARM standard ABI. R9 is not a callee-saved + // register. + ARM::LR, ARM::R7, ARM::R6, ARM::R5, ARM::R4, + ARM::R11, ARM::R10, ARM::R8, + + ARM::D15, ARM::D14, ARM::D13, ARM::D12, + ARM::D11, ARM::D10, ARM::D9, ARM::D8, + 0 + }; + return STI.isTargetDarwin() ? DarwinCalleeSavedRegs : CalleeSavedRegs; +} + +BitVector ARMBaseRegisterInfo:: +getReservedRegs(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + // FIXME: avoid re-calculating this everytime. + BitVector Reserved(getNumRegs()); + Reserved.set(ARM::SP); + Reserved.set(ARM::PC); + Reserved.set(ARM::FPSCR); + if (TFI->hasFP(MF)) + Reserved.set(FramePtr); + if (hasBasePointer(MF)) + Reserved.set(BasePtr); + // Some targets reserve R9. + if (STI.isR9Reserved()) + Reserved.set(ARM::R9); + return Reserved; +} + +bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF, + unsigned Reg) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + switch (Reg) { + default: break; + case ARM::SP: + case ARM::PC: + return true; + case ARM::R6: + if (hasBasePointer(MF)) + return true; + break; + case ARM::R7: + case ARM::R11: + if (FramePtr == Reg && TFI->hasFP(MF)) + return true; + break; + case ARM::R9: + return STI.isR9Reserved(); + } + + return false; +} + +const TargetRegisterClass * +ARMBaseRegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, + unsigned SubIdx) const { + switch (SubIdx) { + default: return 0; + case ARM::ssub_0: + case ARM::ssub_1: + case ARM::ssub_2: + case ARM::ssub_3: { + // S sub-registers. + if (A->getSize() == 8) { + if (B == &ARM::SPR_8RegClass) + return &ARM::DPR_8RegClass; + assert(B == &ARM::SPRRegClass && "Expecting SPR register class!"); + if (A == &ARM::DPR_8RegClass) + return A; + return &ARM::DPR_VFP2RegClass; + } + + if (A->getSize() == 16) { + if (B == &ARM::SPR_8RegClass) + return &ARM::QPR_8RegClass; + return &ARM::QPR_VFP2RegClass; + } + + if (A->getSize() == 32) { + if (B == &ARM::SPR_8RegClass) + return 0; // Do not allow coalescing! + return &ARM::QQPR_VFP2RegClass; + } + + assert(A->getSize() == 64 && "Expecting a QQQQ register class!"); + return 0; // Do not allow coalescing! + } + case ARM::dsub_0: + case ARM::dsub_1: + case ARM::dsub_2: + case ARM::dsub_3: { + // D sub-registers. + if (A->getSize() == 16) { + if (B == &ARM::DPR_VFP2RegClass) + return &ARM::QPR_VFP2RegClass; + if (B == &ARM::DPR_8RegClass) + return 0; // Do not allow coalescing! + return A; + } + + if (A->getSize() == 32) { + if (B == &ARM::DPR_VFP2RegClass) + return &ARM::QQPR_VFP2RegClass; + if (B == &ARM::DPR_8RegClass) + return 0; // Do not allow coalescing! + return A; + } + + assert(A->getSize() == 64 && "Expecting a QQQQ register class!"); + if (B != &ARM::DPRRegClass) + return 0; // Do not allow coalescing! + return A; + } + case ARM::dsub_4: + case ARM::dsub_5: + case ARM::dsub_6: + case ARM::dsub_7: { + // D sub-registers of QQQQ registers. + if (A->getSize() == 64 && B == &ARM::DPRRegClass) + return A; + return 0; // Do not allow coalescing! + } + + case ARM::qsub_0: + case ARM::qsub_1: { + // Q sub-registers. + if (A->getSize() == 32) { + if (B == &ARM::QPR_VFP2RegClass) + return &ARM::QQPR_VFP2RegClass; + if (B == &ARM::QPR_8RegClass) + return 0; // Do not allow coalescing! + return A; + } + + assert(A->getSize() == 64 && "Expecting a QQQQ register class!"); + if (B == &ARM::QPRRegClass) + return A; + return 0; // Do not allow coalescing! + } + case ARM::qsub_2: + case ARM::qsub_3: { + // Q sub-registers of QQQQ registers. + if (A->getSize() == 64 && B == &ARM::QPRRegClass) + return A; + return 0; // Do not allow coalescing! + } + } + return 0; +} + +bool +ARMBaseRegisterInfo::canCombineSubRegIndices(const TargetRegisterClass *RC, + SmallVectorImpl &SubIndices, + unsigned &NewSubIdx) const { + + unsigned Size = RC->getSize() * 8; + if (Size < 6) + return 0; + + NewSubIdx = 0; // Whole register. + unsigned NumRegs = SubIndices.size(); + if (NumRegs == 8) { + // 8 D registers -> 1 QQQQ register. + return (Size == 512 && + SubIndices[0] == ARM::dsub_0 && + SubIndices[1] == ARM::dsub_1 && + SubIndices[2] == ARM::dsub_2 && + SubIndices[3] == ARM::dsub_3 && + SubIndices[4] == ARM::dsub_4 && + SubIndices[5] == ARM::dsub_5 && + SubIndices[6] == ARM::dsub_6 && + SubIndices[7] == ARM::dsub_7); + } else if (NumRegs == 4) { + if (SubIndices[0] == ARM::qsub_0) { + // 4 Q registers -> 1 QQQQ register. + return (Size == 512 && + SubIndices[1] == ARM::qsub_1 && + SubIndices[2] == ARM::qsub_2 && + SubIndices[3] == ARM::qsub_3); + } else if (SubIndices[0] == ARM::dsub_0) { + // 4 D registers -> 1 QQ register. + if (Size >= 256 && + SubIndices[1] == ARM::dsub_1 && + SubIndices[2] == ARM::dsub_2 && + SubIndices[3] == ARM::dsub_3) { + if (Size == 512) + NewSubIdx = ARM::qqsub_0; + return true; + } + } else if (SubIndices[0] == ARM::dsub_4) { + // 4 D registers -> 1 QQ register (2nd). + if (Size == 512 && + SubIndices[1] == ARM::dsub_5 && + SubIndices[2] == ARM::dsub_6 && + SubIndices[3] == ARM::dsub_7) { + NewSubIdx = ARM::qqsub_1; + return true; + } + } else if (SubIndices[0] == ARM::ssub_0) { + // 4 S registers -> 1 Q register. + if (Size >= 128 && + SubIndices[1] == ARM::ssub_1 && + SubIndices[2] == ARM::ssub_2 && + SubIndices[3] == ARM::ssub_3) { + if (Size >= 256) + NewSubIdx = ARM::qsub_0; + return true; + } + } + } else if (NumRegs == 2) { + if (SubIndices[0] == ARM::qsub_0) { + // 2 Q registers -> 1 QQ register. + if (Size >= 256 && SubIndices[1] == ARM::qsub_1) { + if (Size == 512) + NewSubIdx = ARM::qqsub_0; + return true; + } + } else if (SubIndices[0] == ARM::qsub_2) { + // 2 Q registers -> 1 QQ register (2nd). + if (Size == 512 && SubIndices[1] == ARM::qsub_3) { + NewSubIdx = ARM::qqsub_1; + return true; + } + } else if (SubIndices[0] == ARM::dsub_0) { + // 2 D registers -> 1 Q register. + if (Size >= 128 && SubIndices[1] == ARM::dsub_1) { + if (Size >= 256) + NewSubIdx = ARM::qsub_0; + return true; + } + } else if (SubIndices[0] == ARM::dsub_2) { + // 2 D registers -> 1 Q register (2nd). + if (Size >= 256 && SubIndices[1] == ARM::dsub_3) { + NewSubIdx = ARM::qsub_1; + return true; + } + } else if (SubIndices[0] == ARM::dsub_4) { + // 2 D registers -> 1 Q register (3rd). + if (Size == 512 && SubIndices[1] == ARM::dsub_5) { + NewSubIdx = ARM::qsub_2; + return true; + } + } else if (SubIndices[0] == ARM::dsub_6) { + // 2 D registers -> 1 Q register (3rd). + if (Size == 512 && SubIndices[1] == ARM::dsub_7) { + NewSubIdx = ARM::qsub_3; + return true; + } + } else if (SubIndices[0] == ARM::ssub_0) { + // 2 S registers -> 1 D register. + if (SubIndices[1] == ARM::ssub_1) { + if (Size >= 128) + NewSubIdx = ARM::dsub_0; + return true; + } + } else if (SubIndices[0] == ARM::ssub_2) { + // 2 S registers -> 1 D register (2nd). + if (Size >= 128 && SubIndices[1] == ARM::ssub_3) { + NewSubIdx = ARM::dsub_1; + return true; + } + } + } + return false; +} + + +const TargetRegisterClass * +ARMBaseRegisterInfo::getPointerRegClass(unsigned Kind) const { + return ARM::GPRRegisterClass; +} + +unsigned +ARMBaseRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + switch (RC->getID()) { + default: + return 0; + case ARM::tGPRRegClassID: + return TFI->hasFP(MF) ? 4 : 5; + case ARM::GPRRegClassID: { + unsigned FP = TFI->hasFP(MF) ? 1 : 0; + return 10 - FP - (STI.isR9Reserved() ? 1 : 0); + } + case ARM::SPRRegClassID: // Currently not used as 'rep' register class. + case ARM::DPRRegClassID: + return 32 - 10; + } +} + +/// getAllocationOrder - Returns the register allocation order for a specified +/// register class in the form of a pair of TargetRegisterClass iterators. +std::pair +ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + // Alternative register allocation orders when favoring even / odd registers + // of register pairs. + + // No FP, R9 is available. + static const unsigned GPREven1[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, + ARM::R9, ARM::R11 + }; + static const unsigned GPROdd1[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, + ARM::R8, ARM::R10 + }; + + // FP is R7, R9 is available. + static const unsigned GPREven2[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R8, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, + ARM::R9, ARM::R11 + }; + static const unsigned GPROdd2[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R9, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, + ARM::R8, ARM::R10 + }; + + // FP is R11, R9 is available. + static const unsigned GPREven3[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, + ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, + ARM::R9 + }; + static const unsigned GPROdd3[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9, + ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7, + ARM::R8 + }; + + // No FP, R9 is not available. + static const unsigned GPREven4[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8, + ARM::R11 + }; + static const unsigned GPROdd4[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8, + ARM::R10 + }; + + // FP is R7, R9 is not available. + static const unsigned GPREven5[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R10, + ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8, + ARM::R11 + }; + static const unsigned GPROdd5[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R11, + ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8, + ARM::R10 + }; + + // FP is R11, R9 is not available. + static const unsigned GPREven6[] = { + ARM::R0, ARM::R2, ARM::R4, ARM::R6, + ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8 + }; + static const unsigned GPROdd6[] = { + ARM::R1, ARM::R3, ARM::R5, ARM::R7, + ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8 + }; + + + if (HintType == ARMRI::RegPairEven) { + if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + + if (!TFI->hasFP(MF)) { + if (!STI.isR9Reserved()) + return std::make_pair(GPREven1, + GPREven1 + (sizeof(GPREven1)/sizeof(unsigned))); + else + return std::make_pair(GPREven4, + GPREven4 + (sizeof(GPREven4)/sizeof(unsigned))); + } else if (FramePtr == ARM::R7) { + if (!STI.isR9Reserved()) + return std::make_pair(GPREven2, + GPREven2 + (sizeof(GPREven2)/sizeof(unsigned))); + else + return std::make_pair(GPREven5, + GPREven5 + (sizeof(GPREven5)/sizeof(unsigned))); + } else { // FramePtr == ARM::R11 + if (!STI.isR9Reserved()) + return std::make_pair(GPREven3, + GPREven3 + (sizeof(GPREven3)/sizeof(unsigned))); + else + return std::make_pair(GPREven6, + GPREven6 + (sizeof(GPREven6)/sizeof(unsigned))); + } + } else if (HintType == ARMRI::RegPairOdd) { + if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + + if (!TFI->hasFP(MF)) { + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd1, + GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned))); + else + return std::make_pair(GPROdd4, + GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned))); + } else if (FramePtr == ARM::R7) { + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd2, + GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned))); + else + return std::make_pair(GPROdd5, + GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned))); + } else { // FramePtr == ARM::R11 + if (!STI.isR9Reserved()) + return std::make_pair(GPROdd3, + GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned))); + else + return std::make_pair(GPROdd6, + GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned))); + } + } + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); +} + +/// ResolveRegAllocHint - Resolves the specified register allocation hint +/// to a physical register. Returns the physical register if it is successful. +unsigned +ARMBaseRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const { + if (Reg == 0 || !isPhysicalRegister(Reg)) + return 0; + if (Type == 0) + return Reg; + else if (Type == (unsigned)ARMRI::RegPairOdd) + // Odd register. + return getRegisterPairOdd(Reg, MF); + else if (Type == (unsigned)ARMRI::RegPairEven) + // Even register. + return getRegisterPairEven(Reg, MF); + return 0; +} + +void +ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + MachineRegisterInfo *MRI = &MF.getRegInfo(); + std::pair Hint = MRI->getRegAllocationHint(Reg); + if ((Hint.first == (unsigned)ARMRI::RegPairOdd || + Hint.first == (unsigned)ARMRI::RegPairEven) && + TargetRegisterInfo::isVirtualRegister(Hint.second)) { + // If 'Reg' is one of the even / odd register pair and it's now changed + // (e.g. coalesced) into a different register. The other register of the + // pair allocation hint must be updated to reflect the relationship + // change. + unsigned OtherReg = Hint.second; + Hint = MRI->getRegAllocationHint(OtherReg); + if (Hint.second == Reg) + // Make sure the pair has not already divorced. + MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg); + } +} + +bool ARMBaseRegisterInfo::hasBasePointer(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const ARMFunctionInfo *AFI = MF.getInfo(); + + if (!EnableBasePointer) + return false; + + if (needsStackRealignment(MF) && MFI->hasVarSizedObjects()) + return true; + + // Thumb has trouble with negative offsets from the FP. Thumb2 has a limited + // negative range for ldr/str (255), and thumb1 is positive offsets only. + // It's going to be better to use the SP or Base Pointer instead. When there + // are variable sized objects, we can't reference off of the SP, so we + // reserve a Base Pointer. + if (AFI->isThumbFunction() && MFI->hasVarSizedObjects()) { + // Conservatively estimate whether the negative offset from the frame + // pointer will be sufficient to reach. If a function has a smallish + // frame, it's less likely to have lots of spills and callee saved + // space, so it's all more likely to be within range of the frame pointer. + // If it's wrong, the scavenger will still enable access to work, it just + // won't be optimal. + if (AFI->isThumb2Function() && MFI->getLocalFrameSize() < 128) + return false; + return true; + } + + return false; +} + +bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const ARMFunctionInfo *AFI = MF.getInfo(); + // We can't realign the stack if: + // 1. Dynamic stack realignment is explicitly disabled, + // 2. This is a Thumb1 function (it's not useful, so we don't bother), or + // 3. There are VLAs in the function and the base pointer is disabled. + return (RealignStack && !AFI->isThumb1OnlyFunction() && + (!MFI->hasVarSizedObjects() || EnableBasePointer)); +} + +bool ARMBaseRegisterInfo:: +needsStackRealignment(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const Function *F = MF.getFunction(); + unsigned StackAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); + bool requiresRealignment = ((MFI->getLocalFrameMaxAlign() > StackAlign) || + F->hasFnAttr(Attribute::StackAlignment)); + + return requiresRealignment && canRealignStack(MF); +} + +bool ARMBaseRegisterInfo:: +cannotEliminateFrame(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + if (DisableFramePointerElim(MF) && MFI->adjustsStack()) + return true; + return MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken() + || needsStackRealignment(MF); +} + +unsigned ARMBaseRegisterInfo::getRARegister() const { + return ARM::LR; +} + +unsigned +ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + if (TFI->hasFP(MF)) + return FramePtr; + return ARM::SP; +} + +unsigned ARMBaseRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned ARMBaseRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +int ARMBaseRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + return ARMGenRegisterInfo::getDwarfRegNumFull(RegNum, 0); +} + +unsigned ARMBaseRegisterInfo::getRegisterPairEven(unsigned Reg, + const MachineFunction &MF) const { + switch (Reg) { + default: break; + // Return 0 if either register of the pair is a special register. + // So no R12, etc. + case ARM::R1: + return ARM::R0; + case ARM::R3: + return ARM::R2; + case ARM::R5: + return ARM::R4; + case ARM::R7: + return (isReservedReg(MF, ARM::R7) || isReservedReg(MF, ARM::R6)) + ? 0 : ARM::R6; + case ARM::R9: + return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8; + case ARM::R11: + return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10; + + case ARM::S1: + return ARM::S0; + case ARM::S3: + return ARM::S2; + case ARM::S5: + return ARM::S4; + case ARM::S7: + return ARM::S6; + case ARM::S9: + return ARM::S8; + case ARM::S11: + return ARM::S10; + case ARM::S13: + return ARM::S12; + case ARM::S15: + return ARM::S14; + case ARM::S17: + return ARM::S16; + case ARM::S19: + return ARM::S18; + case ARM::S21: + return ARM::S20; + case ARM::S23: + return ARM::S22; + case ARM::S25: + return ARM::S24; + case ARM::S27: + return ARM::S26; + case ARM::S29: + return ARM::S28; + case ARM::S31: + return ARM::S30; + + case ARM::D1: + return ARM::D0; + case ARM::D3: + return ARM::D2; + case ARM::D5: + return ARM::D4; + case ARM::D7: + return ARM::D6; + case ARM::D9: + return ARM::D8; + case ARM::D11: + return ARM::D10; + case ARM::D13: + return ARM::D12; + case ARM::D15: + return ARM::D14; + case ARM::D17: + return ARM::D16; + case ARM::D19: + return ARM::D18; + case ARM::D21: + return ARM::D20; + case ARM::D23: + return ARM::D22; + case ARM::D25: + return ARM::D24; + case ARM::D27: + return ARM::D26; + case ARM::D29: + return ARM::D28; + case ARM::D31: + return ARM::D30; + } + + return 0; +} + +unsigned ARMBaseRegisterInfo::getRegisterPairOdd(unsigned Reg, + const MachineFunction &MF) const { + switch (Reg) { + default: break; + // Return 0 if either register of the pair is a special register. + // So no R12, etc. + case ARM::R0: + return ARM::R1; + case ARM::R2: + return ARM::R3; + case ARM::R4: + return ARM::R5; + case ARM::R6: + return (isReservedReg(MF, ARM::R7) || isReservedReg(MF, ARM::R6)) + ? 0 : ARM::R7; + case ARM::R8: + return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9; + case ARM::R10: + return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11; + + case ARM::S0: + return ARM::S1; + case ARM::S2: + return ARM::S3; + case ARM::S4: + return ARM::S5; + case ARM::S6: + return ARM::S7; + case ARM::S8: + return ARM::S9; + case ARM::S10: + return ARM::S11; + case ARM::S12: + return ARM::S13; + case ARM::S14: + return ARM::S15; + case ARM::S16: + return ARM::S17; + case ARM::S18: + return ARM::S19; + case ARM::S20: + return ARM::S21; + case ARM::S22: + return ARM::S23; + case ARM::S24: + return ARM::S25; + case ARM::S26: + return ARM::S27; + case ARM::S28: + return ARM::S29; + case ARM::S30: + return ARM::S31; + + case ARM::D0: + return ARM::D1; + case ARM::D2: + return ARM::D3; + case ARM::D4: + return ARM::D5; + case ARM::D6: + return ARM::D7; + case ARM::D8: + return ARM::D9; + case ARM::D10: + return ARM::D11; + case ARM::D12: + return ARM::D13; + case ARM::D14: + return ARM::D15; + case ARM::D16: + return ARM::D17; + case ARM::D18: + return ARM::D19; + case ARM::D20: + return ARM::D21; + case ARM::D22: + return ARM::D23; + case ARM::D24: + return ARM::D25; + case ARM::D26: + return ARM::D27; + case ARM::D28: + return ARM::D29; + case ARM::D30: + return ARM::D31; + } + + return 0; +} + +/// emitLoadConstPool - Emits a load from constpool to materialize the +/// specified immediate. +void ARMBaseRegisterInfo:: +emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, int Val, + ARMCC::CondCodes Pred, + unsigned PredReg, unsigned MIFlags) const { + MachineFunction &MF = *MBB.getParent(); + MachineConstantPool *ConstantPool = MF.getConstantPool(); + const Constant *C = + ConstantInt::get(Type::getInt32Ty(MF.getFunction()->getContext()), Val); + unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); + + BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp)) + .addReg(DestReg, getDefRegState(true), SubIdx) + .addConstantPoolIndex(Idx) + .addImm(0).addImm(Pred).addReg(PredReg) + .setMIFlags(MIFlags); +} + +bool ARMBaseRegisterInfo:: +requiresRegisterScavenging(const MachineFunction &MF) const { + return true; +} + +bool ARMBaseRegisterInfo:: +requiresFrameIndexScavenging(const MachineFunction &MF) const { + return true; +} + +bool ARMBaseRegisterInfo:: +requiresVirtualBaseRegisters(const MachineFunction &MF) const { + return EnableLocalStackAlloc; +} + +static void +emitSPUpdate(bool isARM, + MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + DebugLoc dl, const ARMBaseInstrInfo &TII, + int NumBytes, + ARMCC::CondCodes Pred = ARMCC::AL, unsigned PredReg = 0) { + if (isARM) + emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + Pred, PredReg, TII); + else + emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + Pred, PredReg, TII); +} + + +void ARMBaseRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + if (!TFI->hasReservedCallFrame(MF)) { + // If we have alloca, convert as follows: + // ADJCALLSTACKDOWN -> sub, sp, sp, amount + // ADJCALLSTACKUP -> add, sp, sp, amount + MachineInstr *Old = I; + DebugLoc dl = Old->getDebugLoc(); + unsigned Amount = Old->getOperand(0).getImm(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = TFI->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This eliminateCallFramePseudoInstr does not support Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + + // Replace the pseudo instruction with a new instruction... + unsigned Opc = Old->getOpcode(); + int PIdx = Old->findFirstPredOperandIdx(); + ARMCC::CondCodes Pred = (PIdx == -1) + ? ARMCC::AL : (ARMCC::CondCodes)Old->getOperand(PIdx).getImm(); + if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { + // Note: PredReg is operand 2 for ADJCALLSTACKDOWN. + unsigned PredReg = Old->getOperand(2).getReg(); + emitSPUpdate(isARM, MBB, I, dl, TII, -Amount, Pred, PredReg); + } else { + // Note: PredReg is operand 3 for ADJCALLSTACKUP. + unsigned PredReg = Old->getOperand(3).getReg(); + assert(Opc == ARM::ADJCALLSTACKUP || Opc == ARM::tADJCALLSTACKUP); + emitSPUpdate(isARM, MBB, I, dl, TII, Amount, Pred, PredReg); + } + } + } + MBB.erase(I); +} + +int64_t ARMBaseRegisterInfo:: +getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const { + const TargetInstrDesc &Desc = MI->getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + int64_t InstrOffs = 0;; + int Scale = 1; + unsigned ImmIdx = 0; + switch (AddrMode) { + case ARMII::AddrModeT2_i8: + case ARMII::AddrModeT2_i12: + case ARMII::AddrMode_i12: + InstrOffs = MI->getOperand(Idx+1).getImm(); + Scale = 1; + break; + case ARMII::AddrMode5: { + // VFP address mode. + const MachineOperand &OffOp = MI->getOperand(Idx+1); + InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm()); + if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + Scale = 4; + break; + } + case ARMII::AddrMode2: { + ImmIdx = Idx+2; + InstrOffs = ARM_AM::getAM2Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM2Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + break; + } + case ARMII::AddrMode3: { + ImmIdx = Idx+2; + InstrOffs = ARM_AM::getAM3Offset(MI->getOperand(ImmIdx).getImm()); + if (ARM_AM::getAM3Op(MI->getOperand(ImmIdx).getImm()) == ARM_AM::sub) + InstrOffs = -InstrOffs; + break; + } + case ARMII::AddrModeT1_s: { + ImmIdx = Idx+1; + InstrOffs = MI->getOperand(ImmIdx).getImm(); + Scale = 4; + break; + } + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + return InstrOffs * Scale; +} + +/// needsFrameBaseReg - Returns true if the instruction's frame index +/// reference would be better served by a base register other than FP +/// or SP. Used by LocalStackFrameAllocation to determine which frame index +/// references it should create new base registers for. +bool ARMBaseRegisterInfo:: +needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { + for (unsigned i = 0; !MI->getOperand(i).isFI(); ++i) { + assert(i < MI->getNumOperands() &&"Instr doesn't have FrameIndex operand!"); + } + + // It's the load/store FI references that cause issues, as it can be difficult + // to materialize the offset if it won't fit in the literal field. Estimate + // based on the size of the local frame and some conservative assumptions + // about the rest of the stack frame (note, this is pre-regalloc, so + // we don't know everything for certain yet) whether this offset is likely + // to be out of range of the immediate. Return true if so. + + // We only generate virtual base registers for loads and stores, so + // return false for everything else. + unsigned Opc = MI->getOpcode(); + switch (Opc) { + case ARM::LDRi12: case ARM::LDRH: case ARM::LDRBi12: + case ARM::STRi12: case ARM::STRH: case ARM::STRBi12: + case ARM::t2LDRi12: case ARM::t2LDRi8: + case ARM::t2STRi12: case ARM::t2STRi8: + case ARM::VLDRS: case ARM::VLDRD: + case ARM::VSTRS: case ARM::VSTRD: + case ARM::tSTRspi: case ARM::tLDRspi: + if (ForceAllBaseRegAlloc) + return true; + break; + default: + return false; + } + + // Without a virtual base register, if the function has variable sized + // objects, all fixed-size local references will be via the frame pointer, + // Approximate the offset and see if it's legal for the instruction. + // Note that the incoming offset is based on the SP value at function entry, + // so it'll be negative. + MachineFunction &MF = *MI->getParent()->getParent(); + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + + // Estimate an offset from the frame pointer. + // Conservatively assume all callee-saved registers get pushed. R4-R6 + // will be earlier than the FP, so we ignore those. + // R7, LR + int64_t FPOffset = Offset - 8; + // ARM and Thumb2 functions also need to consider R8-R11 and D8-D15 + if (!AFI->isThumbFunction() || !AFI->isThumb1OnlyFunction()) + FPOffset -= 80; + // Estimate an offset from the stack pointer. + // The incoming offset is relating to the SP at the start of the function, + // but when we access the local it'll be relative to the SP after local + // allocation, so adjust our SP-relative offset by that allocation size. + Offset = -Offset; + Offset += MFI->getLocalFrameSize(); + // Assume that we'll have at least some spill slots allocated. + // FIXME: This is a total SWAG number. We should run some statistics + // and pick a real one. + Offset += 128; // 128 bytes of spill slots + + // If there is a frame pointer, try using it. + // The FP is only available if there is no dynamic realignment. We + // don't know for sure yet whether we'll need that, so we guess based + // on whether there are any local variables that would trigger it. + unsigned StackAlign = TFI->getStackAlignment(); + if (TFI->hasFP(MF) && + !((MFI->getLocalFrameMaxAlign() > StackAlign) && canRealignStack(MF))) { + if (isFrameOffsetLegal(MI, FPOffset)) + return false; + } + // If we can reference via the stack pointer, try that. + // FIXME: This (and the code that resolves the references) can be improved + // to only disallow SP relative references in the live range of + // the VLA(s). In practice, it's unclear how much difference that + // would make, but it may be worth doing. + if (!MFI->hasVarSizedObjects() && isFrameOffsetLegal(MI, Offset)) + return false; + + // The offset likely isn't legal, we want to allocate a virtual base register. + return true; +} + +/// materializeFrameBaseRegister - Insert defining instruction(s) for BaseReg to +/// be a pointer to FrameIdx at the beginning of the basic block. +void ARMBaseRegisterInfo:: +materializeFrameBaseRegister(MachineBasicBlock *MBB, + unsigned BaseReg, int FrameIdx, + int64_t Offset) const { + ARMFunctionInfo *AFI = MBB->getParent()->getInfo(); + unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : + (AFI->isThumb1OnlyFunction() ? ARM::tADDrSPi : ARM::t2ADDri); + + MachineBasicBlock::iterator Ins = MBB->begin(); + DebugLoc DL; // Defaults to "unknown" + if (Ins != MBB->end()) + DL = Ins->getDebugLoc(); + + MachineInstrBuilder MIB = + BuildMI(*MBB, Ins, DL, TII.get(ADDriOpc), BaseReg) + .addFrameIndex(FrameIdx).addImm(Offset); + + if (!AFI->isThumb1OnlyFunction()) + AddDefaultCC(AddDefaultPred(MIB)); +} + +void +ARMBaseRegisterInfo::resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const { + MachineInstr &MI = *I; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + int Off = Offset; // ARM doesn't need the general 64-bit offsets + unsigned i = 0; + + assert(!AFI->isThumb1OnlyFunction() && + "This resolveFrameIndex does not support Thumb1!"); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + bool Done = false; + if (!AFI->isThumbFunction()) + Done = rewriteARMFrameIndex(MI, i, BaseReg, Off, TII); + else { + assert(AFI->isThumb2Function()); + Done = rewriteT2FrameIndex(MI, i, BaseReg, Off, TII); + } + assert (Done && "Unable to resolve frame index!"); +} + +bool ARMBaseRegisterInfo::isFrameOffsetLegal(const MachineInstr *MI, + int64_t Offset) const { + const TargetInstrDesc &Desc = MI->getDesc(); + unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask); + unsigned i = 0; + + while (!MI->getOperand(i).isFI()) { + ++i; + assert(i < MI->getNumOperands() &&"Instr doesn't have FrameIndex operand!"); + } + + // AddrMode4 and AddrMode6 cannot handle any offset. + if (AddrMode == ARMII::AddrMode4 || AddrMode == ARMII::AddrMode6) + return Offset == 0; + + unsigned NumBits = 0; + unsigned Scale = 1; + bool isSigned = true; + switch (AddrMode) { + case ARMII::AddrModeT2_i8: + case ARMII::AddrModeT2_i12: + // i8 supports only negative, and i12 supports only positive, so + // based on Offset sign, consider the appropriate instruction + Scale = 1; + if (Offset < 0) { + NumBits = 8; + Offset = -Offset; + } else { + NumBits = 12; + } + break; + case ARMII::AddrMode5: + // VFP address mode. + NumBits = 8; + Scale = 4; + break; + case ARMII::AddrMode_i12: + case ARMII::AddrMode2: + NumBits = 12; + break; + case ARMII::AddrMode3: + NumBits = 8; + break; + case ARMII::AddrModeT1_s: + NumBits = 5; + Scale = 4; + isSigned = false; + break; + default: + llvm_unreachable("Unsupported addressing mode!"); + break; + } + + Offset += getFrameIndexInstrOffset(MI, i); + // Make sure the offset is encodable for instructions that scale the + // immediate. + if ((Offset & (Scale-1)) != 0) + return false; + + if (isSigned && Offset < 0) + Offset = -Offset; + + unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) + return true; + + return false; +} + +void +ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS) const { + unsigned i = 0; + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + const ARMFrameLowering *TFI = + static_cast(MF.getTarget().getFrameLowering()); + ARMFunctionInfo *AFI = MF.getInfo(); + assert(!AFI->isThumb1OnlyFunction() && + "This eliminateFrameIndex does not support Thumb1!"); + + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getIndex(); + unsigned FrameReg; + + int Offset = TFI->ResolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj); + + // Special handling of dbg_value instructions. + if (MI.isDebugValue()) { + MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/); + MI.getOperand(i+1).ChangeToImmediate(Offset); + return; + } + + // Modify MI as necessary to handle as much of 'Offset' as possible + bool Done = false; + if (!AFI->isThumbFunction()) + Done = rewriteARMFrameIndex(MI, i, FrameReg, Offset, TII); + else { + assert(AFI->isThumb2Function()); + Done = rewriteT2FrameIndex(MI, i, FrameReg, Offset, TII); + } + if (Done) + return; + + // If we get here, the immediate doesn't fit into the instruction. We folded + // as much as possible above, handle the rest, providing a register that is + // SP+LargeImm. + assert((Offset || + (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode4 || + (MI.getDesc().TSFlags & ARMII::AddrModeMask) == ARMII::AddrMode6) && + "This code isn't needed if offset already handled!"); + + unsigned ScratchReg = 0; + int PIdx = MI.findFirstPredOperandIdx(); + ARMCC::CondCodes Pred = (PIdx == -1) + ? ARMCC::AL : (ARMCC::CondCodes)MI.getOperand(PIdx).getImm(); + unsigned PredReg = (PIdx == -1) ? 0 : MI.getOperand(PIdx+1).getReg(); + if (Offset == 0) + // Must be addrmode4/6. + MI.getOperand(i).ChangeToRegister(FrameReg, false, false, false); + else { + ScratchReg = MF.getRegInfo().createVirtualRegister(ARM::GPRRegisterClass); + if (!AFI->isThumbFunction()) + emitARMRegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, + Offset, Pred, PredReg, TII); + else { + assert(AFI->isThumb2Function()); + emitT2RegPlusImmediate(MBB, II, MI.getDebugLoc(), ScratchReg, FrameReg, + Offset, Pred, PredReg, TII); + } + // Update the original instruction to use the scratch register. + MI.getOperand(i).ChangeToRegister(ScratchReg, false, false, true); + if (MI.getOpcode() == ARM::t2ADDrSPi) + MI.setDesc(TII.get(ARM::t2ADDri)); + else if (MI.getOpcode() == ARM::t2SUBrSPi) + MI.setDesc(TII.get(ARM::t2SUBri)); + } +} + +#include "ARMGenRegisterInfo.inc" diff --git a/final/lib/Target/ARM/ARMBaseRegisterInfo.h b/final/lib/Target/ARM/ARMBaseRegisterInfo.h new file mode 100644 index 00000000000..0507396f2c8 --- /dev/null +++ b/final/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -0,0 +1,209 @@ +//===- ARMBaseRegisterInfo.h - ARM Register Information Impl ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the base ARM implementation of TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMBASEREGISTERINFO_H +#define ARMBASEREGISTERINFO_H + +#include "ARM.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "ARMGenRegisterInfo.h.inc" + +namespace llvm { + class ARMSubtarget; + class ARMBaseInstrInfo; + class Type; + +/// Register allocation hints. +namespace ARMRI { + enum { + RegPairOdd = 1, + RegPairEven = 2 + }; +} + +/// isARMLowRegister - Returns true if the register is low register r0-r7. +/// +static inline bool isARMLowRegister(unsigned Reg) { + using namespace ARM; + switch (Reg) { + case R0: case R1: case R2: case R3: + case R4: case R5: case R6: case R7: + return true; + default: + return false; + } +} + +/// isARMArea1Register - Returns true if the register is a low register (r0-r7) +/// or a stack/pc register that we should push/pop. +static inline bool isARMArea1Register(unsigned Reg, bool isDarwin) { + using namespace ARM; + switch (Reg) { + case R0: case R1: case R2: case R3: + case R4: case R5: case R6: case R7: + case LR: case SP: case PC: + return true; + case R8: case R9: case R10: case R11: + // For darwin we want r7 and lr to be next to each other. + return !isDarwin; + default: + return false; + } +} + +static inline bool isARMArea2Register(unsigned Reg, bool isDarwin) { + using namespace ARM; + switch (Reg) { + case R8: case R9: case R10: case R11: + // Darwin has this second area. + return isDarwin; + default: + return false; + } +} + +static inline bool isARMArea3Register(unsigned Reg, bool isDarwin) { + using namespace ARM; + switch (Reg) { + case D15: case D14: case D13: case D12: + case D11: case D10: case D9: case D8: + return true; + default: + return false; + } +} + +class ARMBaseRegisterInfo : public ARMGenRegisterInfo { +protected: + const ARMBaseInstrInfo &TII; + const ARMSubtarget &STI; + + /// FramePtr - ARM physical register used as frame ptr. + unsigned FramePtr; + + /// BasePtr - ARM physical register used as a base ptr in complex stack + /// frames. I.e., when we need a 3rd base, not just SP and FP, due to + /// variable size stack objects. + unsigned BasePtr; + + // Can be only subclassed. + explicit ARMBaseRegisterInfo(const ARMBaseInstrInfo &tii, + const ARMSubtarget &STI); + + // Return the opcode that implements 'Op', or 0 if no opcode + unsigned getOpcode(int Op) const; + +public: + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + /// getMatchingSuperRegClass - Return a subclass of the specified register + /// class A so that each register in it has a sub-register of the + /// specified sub-register index which is in the specified register class B. + virtual const TargetRegisterClass * + getMatchingSuperRegClass(const TargetRegisterClass *A, + const TargetRegisterClass *B, unsigned Idx) const; + + /// canCombineSubRegIndices - Given a register class and a list of + /// subregister indices, return true if it's possible to combine the + /// subregister indices into one that corresponds to a larger + /// subregister. Return the new subregister index by reference. Note the + /// new index may be zero if the given subregisters can be combined to + /// form the whole register. + virtual bool canCombineSubRegIndices(const TargetRegisterClass *RC, + SmallVectorImpl &SubIndices, + unsigned &NewSubIdx) const; + + const TargetRegisterClass *getPointerRegClass(unsigned Kind = 0) const; + + unsigned getRegPressureLimit(const TargetRegisterClass *RC, + MachineFunction &MF) const; + + std::pair + getAllocationOrder(const TargetRegisterClass *RC, + unsigned HintType, unsigned HintReg, + const MachineFunction &MF) const; + + unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const; + + void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const; + + bool hasBasePointer(const MachineFunction &MF) const; + + bool canRealignStack(const MachineFunction &MF) const; + bool needsStackRealignment(const MachineFunction &MF) const; + int64_t getFrameIndexInstrOffset(const MachineInstr *MI, int Idx) const; + bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const; + void materializeFrameBaseRegister(MachineBasicBlock *MBB, + unsigned BaseReg, int FrameIdx, + int64_t Offset) const; + void resolveFrameIndex(MachineBasicBlock::iterator I, + unsigned BaseReg, int64_t Offset) const; + bool isFrameOffsetLegal(const MachineInstr *MI, int64_t Offset) const; + + bool cannotEliminateFrame(const MachineFunction &MF) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + unsigned getBaseRegister() const { return BasePtr; } + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; + + bool isLowRegister(unsigned Reg) const; + + + /// emitLoadConstPool - Emits a load from constpool to materialize the + /// specified immediate. + virtual void emitLoadConstPool(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + DebugLoc dl, + unsigned DestReg, unsigned SubIdx, + int Val, + ARMCC::CondCodes Pred = ARMCC::AL, + unsigned PredReg = 0, + unsigned MIFlags = MachineInstr::NoFlags)const; + + /// Code Generation virtual methods... + virtual bool isReservedReg(const MachineFunction &MF, unsigned Reg) const; + + virtual bool requiresRegisterScavenging(const MachineFunction &MF) const; + + virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const; + + virtual bool requiresVirtualBaseRegisters(const MachineFunction &MF) const; + + virtual void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + virtual void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; + +private: + unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const; + + unsigned getRegisterPairOdd(unsigned Reg, const MachineFunction &MF) const; +}; + +} // end namespace llvm + +#endif diff --git a/final/lib/Target/ARM/ARMBuildAttrs.h b/final/lib/Target/ARM/ARMBuildAttrs.h new file mode 100644 index 00000000000..69eddf03ec9 --- /dev/null +++ b/final/lib/Target/ARM/ARMBuildAttrs.h @@ -0,0 +1,131 @@ +//===-------- ARMBuildAttrs.h - ARM Build Attributes ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains enumerations and support routines for ARM build attributes +// as defined in ARM ABI addenda document (ABI release 2.08). +// +//===----------------------------------------------------------------------===// + +#ifndef __TARGET_ARMBUILDATTRS_H__ +#define __TARGET_ARMBUILDATTRS_H__ + +namespace ARMBuildAttrs { + enum SpecialAttr { + // This is for the .cpu asm attr. It translates into one or more + // AttrType (below) entries in the .ARM.attributes section in the ELF. + SEL_CPU + }; + + enum AttrType { + // Rest correspond to ELF/.ARM.attributes + File = 1, + Section = 2, + Symbol = 3, + CPU_raw_name = 4, + CPU_name = 5, + CPU_arch = 6, + CPU_arch_profile = 7, + ARM_ISA_use = 8, + THUMB_ISA_use = 9, + VFP_arch = 10, + WMMX_arch = 11, + Advanced_SIMD_arch = 12, + PCS_config = 13, + ABI_PCS_R9_use = 14, + ABI_PCS_RW_data = 15, + ABI_PCS_RO_data = 16, + ABI_PCS_GOT_use = 17, + ABI_PCS_wchar_t = 18, + ABI_FP_rounding = 19, + ABI_FP_denormal = 20, + ABI_FP_exceptions = 21, + ABI_FP_user_exceptions = 22, + ABI_FP_number_model = 23, + ABI_align8_needed = 24, + ABI_align8_preserved = 25, + ABI_enum_size = 26, + ABI_HardFP_use = 27, + ABI_VFP_args = 28, + ABI_WMMX_args = 29, + ABI_optimization_goals = 30, + ABI_FP_optimization_goals = 31, + compatibility = 32, + CPU_unaligned_access = 34, + VFP_HP_extension = 36, + ABI_FP_16bit_format = 38, + MPextension_use = 42, // was 70, 2.08 ABI + DIV_use = 44, + nodefaults = 64, + also_compatible_with = 65, + T2EE_use = 66, + conformance = 67, + Virtualization_use = 68, + MPextension_use_old = 70 + }; + + // Magic numbers for .ARM.attributes + enum AttrMagic { + Format_Version = 0x41 + }; + + // Legal Values for CPU_arch, (=6), uleb128 + enum CPUArch { + Pre_v4 = 0, + v4 = 1, // e.g. SA110 + v4T = 2, // e.g. ARM7TDMI + v5T = 3, // e.g. ARM9TDMI + v5TE = 4, // e.g. ARM946E_S + v5TEJ = 5, // e.g. ARM926EJ_S + v6 = 6, // e.g. ARM1136J_S + v6KZ = 7, // e.g. ARM1176JZ_S + v6T2 = 8, // e.g. ARM1156T2F_S + v6K = 9, // e.g. ARM1136J_S + v7 = 10, // e.g. Cortex A8, Cortex M3 + v6_M = 11, // e.g. Cortex M1 + v6S_M = 12, // v6_M with the System extensions + v7E_M = 13 // v7_M with DSP extensions + }; + + enum CPUArchProfile { // (=7), uleb128 + Not_Applicable = 0, // pre v7, or cross-profile code + ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8) + RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4) + MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3) + SystemProfile = (0x53) // 'S' Application or real-time profile + }; + + // The following have a lot of common use cases + enum { + //ARMISAUse (=8), uleb128 and THUMBISAUse (=9), uleb128 + Not_Allowed = 0, + Allowed = 1, + + // FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) + AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) + AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA) + AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31 + AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA) + AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31 + + // Tag_WMMX_arch, (=11), uleb128 + AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + + // Tag_WMMX_arch, (=11), uleb128 + AllowWMMXv1 = 2, // The user permitted this entity to use WMMX v2 + + // Tag_ABI_FP_denormal, (=20), uleb128 + PreserveFPSign = 2, // sign when flushed-to-zero is preserved + + // Tag_ABI_FP_number_model, (=23), uleb128 + AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI]) + AllowIEE754 = 3 // this code to use all the IEEE 754-defined FP encodings + }; +} + +#endif // __TARGET_ARMBUILDATTRS_H__ diff --git a/final/lib/Target/ARM/ARMCallingConv.h b/final/lib/Target/ARM/ARMCallingConv.h new file mode 100644 index 00000000000..ff7db1ff62e --- /dev/null +++ b/final/lib/Target/ARM/ARMCallingConv.h @@ -0,0 +1,160 @@ +//===-- ARMCallingConv.h - ARM Custom Calling Convention Routines ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the custom routines for the ARM Calling Convention that +// aren't done by tablegen. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMCALLINGCONV_H +#define ARMCALLINGCONV_H + +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "ARMBaseInstrInfo.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "ARM.h" + +namespace llvm { + +// APCS f64 is in register pairs, possibly split to stack +static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + CCState &State, bool CanFail) { + static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; + + // Try to get the first register. + if (unsigned Reg = State.AllocateReg(RegList, 4)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else { + // For the 2nd half of a v2f64, do not fail. + if (CanFail) + return false; + + // Put the whole thing on the stack. + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(8, 4), + LocVT, LocInfo)); + return true; + } + + // Try to get the second register. + if (unsigned Reg = State.AllocateReg(RegList, 4)) + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + else + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(4, 4), + LocVT, LocInfo)); + return true; +} + +static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) + return false; + if (LocVT == MVT::v2f64 && + !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) + return false; + return true; // we handled it +} + +// AAPCS f64 is in aligned register pairs +static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + CCState &State, bool CanFail) { + static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; + static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; + static const unsigned ShadowRegList[] = { ARM::R0, ARM::R1 }; + + unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2); + if (Reg == 0) { + // For the 2nd half of a v2f64, do not just fail. + if (CanFail) + return false; + + // Put the whole thing on the stack. + State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, + State.AllocateStack(8, 8), + LocVT, LocInfo)); + return true; + } + + unsigned i; + for (i = 0; i < 2; ++i) + if (HiRegList[i] == Reg) + break; + + unsigned T = State.AllocateReg(LoRegList[i]); + (void)T; + assert(T == LoRegList[i] && "Could not allocate register"); + + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], + LocVT, LocInfo)); + return true; +} + +static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true)) + return false; + if (LocVT == MVT::v2f64 && + !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false)) + return false; + return true; // we handled it +} + +static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, CCState &State) { + static const unsigned HiRegList[] = { ARM::R0, ARM::R2 }; + static const unsigned LoRegList[] = { ARM::R1, ARM::R3 }; + + unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2); + if (Reg == 0) + return false; // we didn't handle it + + unsigned i; + for (i = 0; i < 2; ++i) + if (HiRegList[i] == Reg) + break; + + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i], + LocVT, LocInfo)); + return true; +} + +static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) + return false; + if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State)) + return false; + return true; // we handled it +} + +static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, + State); +} + +} // End llvm namespace + +#endif diff --git a/final/lib/Target/ARM/ARMCallingConv.td b/final/lib/Target/ARM/ARMCallingConv.td new file mode 100644 index 00000000000..1e6b95e875f --- /dev/null +++ b/final/lib/Target/ARM/ARMCallingConv.td @@ -0,0 +1,164 @@ +//===- ARMCallingConv.td - Calling Conventions for ARM -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This describes the calling conventions for ARM architecture. +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget: + CCIf().", F), A>; + +/// CCIfAlign - Match of the original alignment of the arg +class CCIfAlign: + CCIf; + +//===----------------------------------------------------------------------===// +// ARM APCS Calling Convention +//===----------------------------------------------------------------------===// +def CC_ARM_APCS : CallingConv<[ + + // Handles byval parameters. + CCIfByVal>, + + CCIfType<[i8, i16], CCPromoteToType>, + + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + // f64 and v2f64 are passed in adjacent GPRs, possibly split onto the stack + CCIfType<[f64, v2f64], CCCustom<"CC_ARM_APCS_Custom_f64">>, + + CCIfType<[f32], CCBitConvertToType>, + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + + CCIfType<[i32], CCAssignToStack<4, 4>>, + CCIfType<[f64], CCAssignToStack<8, 4>>, + CCIfType<[v2f64], CCAssignToStack<16, 4>> +]>; + +def RetCC_ARM_APCS : CallingConv<[ + CCIfType<[f32], CCBitConvertToType>, + + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"RetCC_ARM_APCS_Custom_f64">>, + + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>> +]>; + +//===----------------------------------------------------------------------===// +// ARM APCS Calling Convention for FastCC (when VFP2 or later is available) +//===----------------------------------------------------------------------===// +def FastCC_ARM_APCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; + +def RetFastCC_ARM_APCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; + + +//===----------------------------------------------------------------------===// +// ARM AAPCS (EABI) Calling Convention, common parts +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS_Common : CallingConv<[ + + CCIfType<[i8, i16], CCPromoteToType>, + + // i64/f64 is passed in even pairs of GPRs + // i64 is 8-aligned i32 here, so we may need to eat R1 as a pad register + // (and the same is true for f64 if VFP is not enabled) + CCIfType<[i32], CCIfAlign<"8", CCAssignToRegWithShadow<[R0, R2], [R0, R1]>>>, + CCIfType<[i32], CCIf<"State.getNextStackOffset() == 0 &&" + "ArgFlags.getOrigAlign() != 8", + CCAssignToReg<[R0, R1, R2, R3]>>>, + + CCIfType<[i32], CCIfAlign<"8", CCAssignToStackWithShadow<4, 8, R3>>>, + CCIfType<[i32, f32], CCAssignToStack<4, 4>>, + CCIfType<[f64], CCAssignToStack<8, 8>>, + CCIfType<[v2f64], CCAssignToStack<16, 8>> +]>; + +def RetCC_ARM_AAPCS_Common : CallingConv<[ + CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>, + CCIfType<[i64], CCAssignToRegWithShadow<[R0, R2], [R1, R3]>> +]>; + +//===----------------------------------------------------------------------===// +// ARM AAPCS (EABI) Calling Convention +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"CC_ARM_AAPCS_Custom_f64">>, + CCIfType<[f32], CCBitConvertToType>, + CCDelegateTo +]>; + +def RetCC_ARM_AAPCS : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[f64, v2f64], CCCustom<"RetCC_ARM_AAPCS_Custom_f64">>, + CCIfType<[f32], CCBitConvertToType>, + CCDelegateTo +]>; + +//===----------------------------------------------------------------------===// +// ARM AAPCS-VFP (EABI) Calling Convention +// Also used for FastCC (when VFP2 or later is available) +//===----------------------------------------------------------------------===// + +def CC_ARM_AAPCS_VFP : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; + +def RetCC_ARM_AAPCS_VFP : CallingConv<[ + // Handle all vector types as either f64 or v2f64. + CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32], CCBitConvertToType>, + CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32], CCBitConvertToType>, + + CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>, + CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>, + CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8, + S9, S10, S11, S12, S13, S14, S15]>>, + CCDelegateTo +]>; diff --git a/final/lib/Target/ARM/ARMCodeEmitter.cpp b/final/lib/Target/ARM/ARMCodeEmitter.cpp new file mode 100644 index 00000000000..fa7371626f2 --- /dev/null +++ b/final/lib/Target/ARM/ARMCodeEmitter.cpp @@ -0,0 +1,1887 @@ +//===-- ARM/ARMCodeEmitter.cpp - Convert ARM code to machine code ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the pass that transforms the ARM machine instructions into +// relocatable machine code. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMConstantPoolValue.h" +#include "ARMInstrInfo.h" +#include "ARMRelocations.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" +#include "llvm/CodeGen/JITCodeEmitter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#ifndef NDEBUG +#include +#endif +using namespace llvm; + +STATISTIC(NumEmitted, "Number of machine instructions emitted"); + +namespace { + + class ARMCodeEmitter : public MachineFunctionPass { + ARMJITInfo *JTI; + const ARMInstrInfo *II; + const TargetData *TD; + const ARMSubtarget *Subtarget; + TargetMachine &TM; + JITCodeEmitter &MCE; + MachineModuleInfo *MMI; + const std::vector *MCPEs; + const std::vector *MJTEs; + bool IsPIC; + bool IsThumb; + + void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + static char ID; + public: + ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) + : MachineFunctionPass(ID), JTI(0), + II((const ARMInstrInfo *)tm.getInstrInfo()), + TD(tm.getTargetData()), TM(tm), + MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_), IsThumb(false) {} + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + unsigned getBinaryCodeForInstr(const MachineInstr &MI) const; + + bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "ARM Machine Code Emitter"; + } + + void emitInstruction(const MachineInstr &MI); + + private: + + void emitWordLE(unsigned Binary); + void emitDWordLE(uint64_t Binary); + void emitConstPoolInstruction(const MachineInstr &MI); + void emitMOVi32immInstruction(const MachineInstr &MI); + void emitMOVi2piecesInstruction(const MachineInstr &MI); + void emitLEApcrelJTInstruction(const MachineInstr &MI); + void emitPseudoMoveInstruction(const MachineInstr &MI); + void addPCLabel(unsigned LabelID); + void emitPseudoInstruction(const MachineInstr &MI); + unsigned getMachineSoRegOpValue(const MachineInstr &MI, + const TargetInstrDesc &TID, + const MachineOperand &MO, + unsigned OpIdx); + + unsigned getMachineSoImmOpValue(unsigned SoImm); + unsigned getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const; + + void emitDataProcessingInstruction(const MachineInstr &MI, + unsigned ImplicitRd = 0, + unsigned ImplicitRn = 0); + + void emitLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRd = 0, + unsigned ImplicitRn = 0); + + void emitMiscLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRn = 0); + + void emitLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitMulFrmInstruction(const MachineInstr &MI); + + void emitExtendInstruction(const MachineInstr &MI); + + void emitMiscArithInstruction(const MachineInstr &MI); + + void emitSaturateInstruction(const MachineInstr &MI); + + void emitBranchInstruction(const MachineInstr &MI); + + void emitInlineJumpTable(unsigned JTIndex); + + void emitMiscBranchInstruction(const MachineInstr &MI); + + void emitVFPArithInstruction(const MachineInstr &MI); + + void emitVFPConversionInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreInstruction(const MachineInstr &MI); + + void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI); + + void emitNEONLaneInstruction(const MachineInstr &MI); + void emitNEONDupInstruction(const MachineInstr &MI); + void emitNEON1RegModImmInstruction(const MachineInstr &MI); + void emitNEON2RegInstruction(const MachineInstr &MI); + void emitNEON3RegInstruction(const MachineInstr &MI); + + /// getMachineOpValue - Return binary encoding of operand. If the machine + /// operand requires relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const; + unsigned getMachineOpValue(const MachineInstr &MI, unsigned OpIdx) const { + return getMachineOpValue(MI, MI.getOperand(OpIdx)); + } + + // FIXME: The legacy JIT ARMCodeEmitter doesn't rely on the the + // TableGen'erated getBinaryCodeForInstr() function to encode any + // operand values, instead querying getMachineOpValue() directly for + // each operand it needs to encode. Thus, any of the new encoder + // helper functions can simply return 0 as the values the return + // are already handled elsewhere. They are placeholders to allow this + // encoder to continue to function until the MC encoder is sufficiently + // far along that this one can be eliminated entirely. + unsigned NEONThumb2DataIPostEncoder(const MachineInstr &MI, unsigned Val) + const { return 0; } + unsigned NEONThumb2LoadStorePostEncoder(const MachineInstr &MI,unsigned Val) + const { return 0; } + unsigned NEONThumb2DupPostEncoder(const MachineInstr &MI,unsigned Val) + const { return 0; } + unsigned VFPThumb2PostEncoder(const MachineInstr&MI, unsigned Val) + const { return 0; } + unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbAdrLabelOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbBLXTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbBRTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbBCCTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbCBTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI, + unsigned Op) const { return 0; } + unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getThumbAddrModeRegRegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op) + const { return 0; } + unsigned getT2AddrModeSORegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getAddrMode6OffsetOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getBitfieldInvertedMaskOpValue(const MachineInstr &MI, + unsigned Op) const { return 0; } + unsigned getMsbOpValue(const MachineInstr &MI, + unsigned Op) const { return 0; } + uint32_t getLdStmModeOpValue(const MachineInstr &MI, unsigned OpIdx) + const {return 0; } + uint32_t getLdStSORegOpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0; } + + unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) + const { + // {17-13} = reg + // {12} = (U)nsigned (add == '1', sub == '0') + // {11-0} = imm12 + const MachineOperand &MO = MI.getOperand(Op); + const MachineOperand &MO1 = MI.getOperand(Op + 1); + if (!MO.isReg()) { + emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry); + return 0; + } + unsigned Reg = getARMRegisterNumbering(MO.getReg()); + int32_t Imm12 = MO1.getImm(); + uint32_t Binary; + Binary = Imm12 & 0xfff; + if (Imm12 >= 0) + Binary |= (1 << 12); + Binary |= (Reg << 13); + return Binary; + } + + unsigned getHiLo16ImmOpValue(const MachineInstr &MI, unsigned Op) const { + return 0; + } + + uint32_t getAddrMode2OpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0;} + uint32_t getAddrMode2OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0;} + uint32_t getAddrMode3OffsetOpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0;} + uint32_t getAddrMode3OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModeThumbSPOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModeSOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModeISOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrModePCOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + uint32_t getAddrMode5OpValue(const MachineInstr &MI, unsigned Op) const { + // {17-13} = reg + // {12} = (U)nsigned (add == '1', sub == '0') + // {11-0} = imm12 + const MachineOperand &MO = MI.getOperand(Op); + const MachineOperand &MO1 = MI.getOperand(Op + 1); + if (!MO.isReg()) { + emitConstPoolAddress(MO.getIndex(), ARM::reloc_arm_cp_entry); + return 0; + } + unsigned Reg = getARMRegisterNumbering(MO.getReg()); + int32_t Imm12 = MO1.getImm(); + + // Special value for #-0 + if (Imm12 == INT32_MIN) + Imm12 = 0; + + // Immediate is always encoded as positive. The 'U' bit controls add vs + // sub. + bool isAdd = true; + if (Imm12 < 0) { + Imm12 = -Imm12; + isAdd = false; + } + + uint32_t Binary = Imm12 & 0xfff; + if (isAdd) + Binary |= (1 << 12); + Binary |= (Reg << 13); + return Binary; + } + unsigned getNEONVcvtImm32OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + + unsigned getRegisterListOpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } + + unsigned getShiftRight8Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight16Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight32Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + unsigned getShiftRight64Imm(const MachineInstr &MI, unsigned Op) + const { return 0; } + + /// getMovi32Value - Return binary encoding of operand for movw/movt. If the + /// machine operand requires relocation, record the relocation and return + /// zero. + unsigned getMovi32Value(const MachineInstr &MI,const MachineOperand &MO, + unsigned Reloc); + + /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. + /// + unsigned getShiftOp(unsigned Imm) const ; + + /// Routines that handle operands which add machine relocations which are + /// fixed up by the relocation stage. + void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub, bool Indirect, + intptr_t ACPV = 0) const; + void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; + void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; + void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; + void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc, + intptr_t JTBase = 0) const; + }; +} + +char ARMCodeEmitter::ID = 0; + +/// createARMJITCodeEmitterPass - Return a pass that emits the collected ARM +/// code to the specified MCE object. +FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM, + JITCodeEmitter &JCE) { + return new ARMCodeEmitter(TM, JCE); +} + +bool ARMCodeEmitter::runOnMachineFunction(MachineFunction &MF) { + assert((MF.getTarget().getRelocationModel() != Reloc::Default || + MF.getTarget().getRelocationModel() != Reloc::Static) && + "JIT relocation model must be set to static or default!"); + JTI = ((ARMTargetMachine &)MF.getTarget()).getJITInfo(); + II = ((const ARMTargetMachine &)MF.getTarget()).getInstrInfo(); + TD = ((const ARMTargetMachine &)MF.getTarget()).getTargetData(); + Subtarget = &TM.getSubtarget(); + MCPEs = &MF.getConstantPool()->getConstants(); + MJTEs = 0; + if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); + IsPIC = TM.getRelocationModel() == Reloc::PIC_; + IsThumb = MF.getInfo()->isThumbFunction(); + JTI->Initialize(MF, IsPIC); + MMI = &getAnalysis(); + MCE.setModuleInfo(MMI); + + do { + DEBUG(errs() << "JITTing function '" + << MF.getFunction()->getName() << "'\n"); + MCE.startFunction(MF); + for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); + MBB != E; ++MBB) { + MCE.StartMachineBasicBlock(MBB); + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) + emitInstruction(*I); + } + } while (MCE.finishFunction(MF)); + + return false; +} + +/// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. +/// +unsigned ARMCodeEmitter::getShiftOp(unsigned Imm) const { + switch (ARM_AM::getAM2ShiftOpc(Imm)) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::asr: return 2; + case ARM_AM::lsl: return 0; + case ARM_AM::lsr: return 1; + case ARM_AM::ror: + case ARM_AM::rrx: return 3; + } + return 0; +} + +/// getMovi32Value - Return binary encoding of operand for movw/movt. If the +/// machine operand requires relocation, record the relocation and return zero. +unsigned ARMCodeEmitter::getMovi32Value(const MachineInstr &MI, + const MachineOperand &MO, + unsigned Reloc) { + assert(((Reloc == ARM::reloc_arm_movt) || (Reloc == ARM::reloc_arm_movw)) + && "Relocation to this function should be for movt or movw"); + + if (MO.isImm()) + return static_cast(MO.getImm()); + else if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), Reloc, true, false); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), Reloc); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), Reloc); + else { +#ifndef NDEBUG + errs() << MO; +#endif + llvm_unreachable("Unsupported operand type for movw/movt"); + } + return 0; +} + +/// getMachineOpValue - Return binary encoding of operand. If the machine +/// operand requires relocation, record the relocation and return zero. +unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, + const MachineOperand &MO) const { + if (MO.isReg()) + return getARMRegisterNumbering(MO.getReg()); + else if (MO.isImm()) + return static_cast(MO.getImm()); + else if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); + else if (MO.isCPI()) { + const TargetInstrDesc &TID = MI.getDesc(); + // For VFP load, the immediate offset is multiplied by 4. + unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) + ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; + emitConstPoolAddress(MO.getIndex(), Reloc); + } else if (MO.isJTI()) + emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch); + else + llvm_unreachable("Unable to encode MachineOperand!"); + return 0; +} + +/// emitGlobalAddress - Emit the specified address to the code stream. +/// +void ARMCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, + bool MayNeedFarStub, bool Indirect, + intptr_t ACPV) const { + MachineRelocation MR = Indirect + ? MachineRelocation::getIndirectSymbol(MCE.getCurrentPCOffset(), Reloc, + const_cast(GV), + ACPV, MayNeedFarStub) + : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + const_cast(GV), ACPV, + MayNeedFarStub); + MCE.addRelocation(MR); +} + +/// emitExternalSymbolAddress - Arrange for the address of an external symbol to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +void ARMCodeEmitter:: +emitExternalSymbolAddress(const char *ES, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), + Reloc, ES)); +} + +/// emitConstPoolAddress - Arrange for the address of an constant pool +/// to be emitted to the current location in the function, and allow it to be PC +/// relative. +void ARMCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { + // Tell JIT emitter we'll resolve the address. + MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), + Reloc, CPI, 0, true)); +} + +/// emitJumpTableAddress - Arrange for the address of a jump table to +/// be emitted to the current location in the function, and allow it to be PC +/// relative. +void ARMCodeEmitter:: +emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { + MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), + Reloc, JTIndex, 0, true)); +} + +/// emitMachineBasicBlock - Emit the specified address basic block. +void ARMCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, + unsigned Reloc, + intptr_t JTBase) const { + MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), + Reloc, BB, JTBase)); +} + +void ARMCodeEmitter::emitWordLE(unsigned Binary) { + DEBUG(errs() << " 0x"; + errs().write_hex(Binary) << "\n"); + MCE.emitWordLE(Binary); +} + +void ARMCodeEmitter::emitDWordLE(uint64_t Binary) { + DEBUG(errs() << " 0x"; + errs().write_hex(Binary) << "\n"); + MCE.emitDWordLE(Binary); +} + +void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) { + DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); + + MCE.processDebugLoc(MI.getDebugLoc(), true); + + ++NumEmitted; // Keep track of the # of mi's emitted + switch (MI.getDesc().TSFlags & ARMII::FormMask) { + default: { + llvm_unreachable("Unhandled instruction encoding format!"); + break; + } + case ARMII::MiscFrm: + if (MI.getOpcode() == ARM::LEApcrelJT) { + // Materialize jumptable address. + emitLEApcrelJTInstruction(MI); + break; + } + llvm_unreachable("Unhandled instruction encoding!"); + break; + case ARMII::Pseudo: + emitPseudoInstruction(MI); + break; + case ARMII::DPFrm: + case ARMII::DPSoRegFrm: + emitDataProcessingInstruction(MI); + break; + case ARMII::LdFrm: + case ARMII::StFrm: + emitLoadStoreInstruction(MI); + break; + case ARMII::LdMiscFrm: + case ARMII::StMiscFrm: + emitMiscLoadStoreInstruction(MI); + break; + case ARMII::LdStMulFrm: + emitLoadStoreMultipleInstruction(MI); + break; + case ARMII::MulFrm: + emitMulFrmInstruction(MI); + break; + case ARMII::ExtFrm: + emitExtendInstruction(MI); + break; + case ARMII::ArithMiscFrm: + emitMiscArithInstruction(MI); + break; + case ARMII::SatFrm: + emitSaturateInstruction(MI); + break; + case ARMII::BrFrm: + emitBranchInstruction(MI); + break; + case ARMII::BrMiscFrm: + emitMiscBranchInstruction(MI); + break; + // VFP instructions. + case ARMII::VFPUnaryFrm: + case ARMII::VFPBinaryFrm: + emitVFPArithInstruction(MI); + break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + emitVFPConversionInstruction(MI); + break; + case ARMII::VFPLdStFrm: + emitVFPLoadStoreInstruction(MI); + break; + case ARMII::VFPLdStMulFrm: + emitVFPLoadStoreMultipleInstruction(MI); + break; + + // NEON instructions. + case ARMII::NGetLnFrm: + case ARMII::NSetLnFrm: + emitNEONLaneInstruction(MI); + break; + case ARMII::NDupFrm: + emitNEONDupInstruction(MI); + break; + case ARMII::N1RegModImmFrm: + emitNEON1RegModImmInstruction(MI); + break; + case ARMII::N2RegFrm: + emitNEON2RegInstruction(MI); + break; + case ARMII::N3RegFrm: + emitNEON3RegInstruction(MI); + break; + } + MCE.processDebugLoc(MI.getDebugLoc(), false); +} + +void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { + unsigned CPI = MI.getOperand(0).getImm(); // CP instruction index. + unsigned CPIndex = MI.getOperand(1).getIndex(); // Actual cp entry index. + const MachineConstantPoolEntry &MCPE = (*MCPEs)[CPIndex]; + + // Remember the CONSTPOOL_ENTRY address for later relocation. + JTI->addConstantPoolEntryAddr(CPI, MCE.getCurrentPCValue()); + + // Emit constpool island entry. In most cases, the actual values will be + // resolved and relocated after code emission. + if (MCPE.isMachineConstantPoolEntry()) { + ARMConstantPoolValue *ACPV = + static_cast(MCPE.Val.MachineCPVal); + + DEBUG(errs() << " ** ARM constant pool #" << CPI << " @ " + << (void*)MCE.getCurrentPCValue() << " " << *ACPV << '\n'); + + assert(ACPV->isGlobalValue() && "unsupported constant pool value"); + const GlobalValue *GV = ACPV->getGV(); + if (GV) { + Reloc::Model RelocM = TM.getRelocationModel(); + emitGlobalAddress(GV, ARM::reloc_arm_machine_cp_entry, + isa(GV), + Subtarget->GVIsIndirectSymbol(GV, RelocM), + (intptr_t)ACPV); + } else { + emitExternalSymbolAddress(ACPV->getSymbol(), ARM::reloc_arm_absolute); + } + emitWordLE(0); + } else { + const Constant *CV = MCPE.Val.ConstVal; + + DEBUG({ + errs() << " ** Constant pool #" << CPI << " @ " + << (void*)MCE.getCurrentPCValue() << " "; + if (const Function *F = dyn_cast(CV)) + errs() << F->getName(); + else + errs() << *CV; + errs() << '\n'; + }); + + if (const GlobalValue *GV = dyn_cast(CV)) { + emitGlobalAddress(GV, ARM::reloc_arm_absolute, isa(GV), false); + emitWordLE(0); + } else if (const ConstantInt *CI = dyn_cast(CV)) { + uint32_t Val = uint32_t(*CI->getValue().getRawData()); + emitWordLE(Val); + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + if (CFP->getType()->isFloatTy()) + emitWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else if (CFP->getType()->isDoubleTy()) + emitDWordLE(CFP->getValueAPF().bitcastToAPInt().getZExtValue()); + else { + llvm_unreachable("Unable to handle this constantpool entry!"); + } + } else { + llvm_unreachable("Unable to handle this constantpool entry!"); + } + } +} + +void ARMCodeEmitter::emitMOVi32immInstruction(const MachineInstr &MI) { + const MachineOperand &MO0 = MI.getOperand(0); + const MachineOperand &MO1 = MI.getOperand(1); + + // Emit the 'movw' instruction. + unsigned Binary = 0x30 << 20; // mov: Insts{27-20} = 0b00110000 + + unsigned Lo16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movw) & 0xFFFF; + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode imm16 as imm4:imm12 + Binary |= Lo16 & 0xFFF; // Insts{11-0} = imm12 + Binary |= ((Lo16 >> 12) & 0xF) << 16; // Insts{19-16} = imm4 + emitWordLE(Binary); + + unsigned Hi16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movt) >> 16; + // Emit the 'movt' instruction. + Binary = 0x34 << 20; // movt: Insts{27-20} = 0b00110100 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode imm16 as imm4:imm1, same as movw above. + Binary |= Hi16 & 0xFFF; + Binary |= ((Hi16 >> 12) & 0xF) << 16; + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { + const MachineOperand &MO0 = MI.getOperand(0); + const MachineOperand &MO1 = MI.getOperand(1); + assert(MO1.isImm() && ARM_AM::isSOImmTwoPartVal(MO1.getImm()) && + "Not a valid so_imm value!"); + unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO1.getImm()); + unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO1.getImm()); + + // Emit the 'mov' instruction. + unsigned Binary = 0xd << 21; // mov: Insts{24-21} = 0b1101 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(V1); + emitWordLE(Binary); + + // Now the 'orr' instruction. + Binary = 0xc << 21; // orr: Insts{24-21} = 0b1100 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode Rn. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRnShift; + + // Encode so_imm. + // Set bit I(25) to identify this is the immediate form of + Binary |= 1 << ARMII::I_BitShift; + Binary |= getMachineSoImmOpValue(V2); + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitLEApcrelJTInstruction(const MachineInstr &MI) { + // It's basically add r, pc, (LJTI - $+8) + + const TargetInstrDesc &TID = MI.getDesc(); + + // Emit the 'add' instruction. + unsigned Binary = 0x4 << 21; // add: Insts{24-21} = 0b0100 + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // Encode Rd. + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode Rn which is PC. + Binary |= getARMRegisterNumbering(ARM::PC) << ARMII::RegRnShift; + + // Encode the displacement. + Binary |= 1 << ARMII::I_BitShift; + emitJumpTableAddress(MI.getOperand(1).getIndex(), ARM::reloc_arm_jt_base); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitPseudoMoveInstruction(const MachineInstr &MI) { + unsigned Opcode = MI.getDesc().Opcode; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + if (Opcode == ARM::MOVsrl_flag || Opcode == ARM::MOVsra_flag) + Binary |= 1 << ARMII::S_BitShift; + + // Encode register def if there is one. + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode the shift operation. + switch (Opcode) { + default: break; + case ARM::RRX: + // rrx + Binary |= 0x6 << 4; + break; + case ARM::MOVsrl_flag: + // lsr #1 + Binary |= (0x2 << 4) | (1 << 7); + break; + case ARM::MOVsra_flag: + // asr #1 + Binary |= (0x4 << 4) | (1 << 7); + break; + } + + // Encode register Rm. + Binary |= getMachineOpValue(MI, 1); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::addPCLabel(unsigned LabelID) { + DEBUG(errs() << " ** LPC" << LabelID << " @ " + << (void*)MCE.getCurrentPCValue() << '\n'); + JTI->addPCLabelAddr(LabelID, MCE.getCurrentPCValue()); +} + +void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { + unsigned Opcode = MI.getDesc().Opcode; + switch (Opcode) { + default: + llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction"); + case ARM::BX_CALL: + case ARM::BMOVPCRX_CALL: + case ARM::BXr9_CALL: + case ARM::BMOVPCRXr9_CALL: { + // First emit mov lr, pc + unsigned Binary = 0x01a0e00f; + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + emitWordLE(Binary); + + // and then emit the branch. + emitMiscBranchInstruction(MI); + break; + } + case TargetOpcode::INLINEASM: { + // We allow inline assembler nodes with empty bodies - they can + // implicitly define registers, which is ok for JIT. + if (MI.getOperand(0).getSymbolName()[0]) { + report_fatal_error("JIT does not support inline asm!"); + } + break; + } + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + MCE.emitLabel(MI.getOperand(0).getMCSymbol()); + break; + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + // Do nothing. + break; + case ARM::CONSTPOOL_ENTRY: + emitConstPoolInstruction(MI); + break; + case ARM::PICADD: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // PICADD is just an add instruction that implicitly read pc. + emitDataProcessingInstruction(MI, 0, ARM::PC); + break; + } + case ARM::PICLDR: + case ARM::PICLDRB: + case ARM::PICSTR: + case ARM::PICSTRB: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // These are just load / store instructions that implicitly read pc. + emitLoadStoreInstruction(MI, 0, ARM::PC); + break; + } + case ARM::PICLDRH: + case ARM::PICLDRSH: + case ARM::PICLDRSB: + case ARM::PICSTRH: { + // Remember of the address of the PC label for relocation later. + addPCLabel(MI.getOperand(2).getImm()); + // These are just load / store instructions that implicitly read pc. + emitMiscLoadStoreInstruction(MI, ARM::PC); + break; + } + + case ARM::MOVi32imm: + // Two instructions to materialize a constant. + if (Subtarget->hasV6T2Ops()) + emitMOVi32immInstruction(MI); + else + emitMOVi2piecesInstruction(MI); + break; + + case ARM::LEApcrelJT: + // Materialize jumptable address. + emitLEApcrelJTInstruction(MI); + break; + case ARM::RRX: + case ARM::MOVsrl_flag: + case ARM::MOVsra_flag: + emitPseudoMoveInstruction(MI); + break; + } +} + +unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI, + const TargetInstrDesc &TID, + const MachineOperand &MO, + unsigned OpIdx) { + unsigned Binary = getMachineOpValue(MI, MO); + + const MachineOperand &MO1 = MI.getOperand(OpIdx + 1); + const MachineOperand &MO2 = MI.getOperand(OpIdx + 2); + ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm()); + + // Encode the shift opcode. + unsigned SBits = 0; + unsigned Rs = MO1.getReg(); + if (Rs) { + // Set shift operand (bit[7:4]). + // LSL - 0001 + // LSR - 0011 + // ASR - 0101 + // ROR - 0111 + // RRX - 0110 and bit[11:8] clear. + switch (SOpc) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::lsl: SBits = 0x1; break; + case ARM_AM::lsr: SBits = 0x3; break; + case ARM_AM::asr: SBits = 0x5; break; + case ARM_AM::ror: SBits = 0x7; break; + case ARM_AM::rrx: SBits = 0x6; break; + } + } else { + // Set shift operand (bit[6:4]). + // LSL - 000 + // LSR - 010 + // ASR - 100 + // ROR - 110 + switch (SOpc) { + default: llvm_unreachable("Unknown shift opc!"); + case ARM_AM::lsl: SBits = 0x0; break; + case ARM_AM::lsr: SBits = 0x2; break; + case ARM_AM::asr: SBits = 0x4; break; + case ARM_AM::ror: SBits = 0x6; break; + } + } + Binary |= SBits << 4; + if (SOpc == ARM_AM::rrx) + return Binary; + + // Encode the shift operation Rs or shift_imm (except rrx). + if (Rs) { + // Encode Rs bit[11:8]. + assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); + return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift); + } + + // Encode shift_imm bit[11:7]. + return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7; +} + +unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) { + int SoImmVal = ARM_AM::getSOImmVal(SoImm); + assert(SoImmVal != -1 && "Not a valid so_imm value!"); + + // Encode rotate_imm. + unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) + << ARMII::SoRotImmShift; + + // Encode immed_8. + Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); + return Binary; +} + +unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI, + const TargetInstrDesc &TID) const { + for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i >= e; --i){ + const MachineOperand &MO = MI.getOperand(i-1); + if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR) + return 1 << ARMII::S_BitShift; + } + return 0; +} + +void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI, + unsigned ImplicitRd, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // Encode register def if there is one. + unsigned NumDefs = TID.getNumDefs(); + unsigned OpIdx = 0; + if (NumDefs) + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + else if (ImplicitRd) + // Special handling for implicit use (e.g. PC). + Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); + + if (TID.Opcode == ARM::MOVi16) { + // Get immediate from MI. + unsigned Lo16 = getMovi32Value(MI, MI.getOperand(OpIdx), + ARM::reloc_arm_movw); + // Encode imm which is the same as in emitMOVi32immInstruction(). + Binary |= Lo16 & 0xFFF; + Binary |= ((Lo16 >> 12) & 0xF) << 16; + emitWordLE(Binary); + return; + } else if(TID.Opcode == ARM::MOVTi16) { + unsigned Hi16 = (getMovi32Value(MI, MI.getOperand(OpIdx), + ARM::reloc_arm_movt) >> 16); + Binary |= Hi16 & 0xFFF; + Binary |= ((Hi16 >> 12) & 0xF) << 16; + emitWordLE(Binary); + return; + } else if ((TID.Opcode == ARM::BFC) || (TID.Opcode == ARM::BFI)) { + uint32_t v = ~MI.getOperand(2).getImm(); + int32_t lsb = CountTrailingZeros_32(v); + int32_t msb = (32 - CountLeadingZeros_32(v)) - 1; + // Instr{20-16} = msb, Instr{11-7} = lsb + Binary |= (msb & 0x1F) << 16; + Binary |= (lsb & 0x1F) << 7; + emitWordLE(Binary); + return; + } else if ((TID.Opcode == ARM::UBFX) || (TID.Opcode == ARM::SBFX)) { + // Encode Rn in Instr{0-3} + Binary |= getMachineOpValue(MI, OpIdx++); + + uint32_t lsb = MI.getOperand(OpIdx++).getImm(); + uint32_t widthm1 = MI.getOperand(OpIdx++).getImm() - 1; + + // Instr{20-16} = widthm1, Instr{11-7} = lsb + Binary |= (widthm1 & 0x1F) << 16; + Binary |= (lsb & 0x1F) << 7; + emitWordLE(Binary); + return; + } + + // If this is a two-address operand, skip it. e.g. MOVCCr operand 1. + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + // Encode first non-shifter register operand if there is one. + bool isUnary = TID.TSFlags & ARMII::UnaryDP; + if (!isUnary) { + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); + else { + Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift; + ++OpIdx; + } + } + + // Encode shifter operand. + const MachineOperand &MO = MI.getOperand(OpIdx); + if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) { + // Encode SoReg. + emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx)); + return; + } + + if (MO.isReg()) { + // Encode register Rm. + emitWordLE(Binary | getARMRegisterNumbering(MO.getReg())); + return; + } + + // Encode so_imm. + Binary |= getMachineSoImmOpValue((unsigned)MO.getImm()); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRd, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // If this is an LDRi12, STRi12 or LDRcp, nothing more needs be done. + if (MI.getOpcode() == ARM::LDRi12 || MI.getOpcode() == ARM::LDRcp || + MI.getOpcode() == ARM::STRi12) { + emitWordLE(Binary); + return; + } + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StFrm) { + ++OpIdx; + Skipped = true; + } + + // Set first operand + if (ImplicitRd) + // Special handling for implicit use (e.g. PC). + Binary |= (getARMRegisterNumbering(ImplicitRd) << ARMII::RegRdShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + // Set second operand + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // If this is a two-address operand, skip it. e.g. LDR_PRE. + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + const MachineOperand &MO2 = MI.getOperand(OpIdx); + unsigned AM2Opc = (ImplicitRn == ARM::PC) + ? 0 : MI.getOperand(OpIdx+1).getImm(); + + // Set bit U(23) according to sign of immed value (positive or negative). + Binary |= ((ARM_AM::getAM2Op(AM2Opc) == ARM_AM::add ? 1 : 0) << + ARMII::U_BitShift); + if (!MO2.getReg()) { // is immediate + if (ARM_AM::getAM2Offset(AM2Opc)) + // Set the value of offset_12 field + Binary |= ARM_AM::getAM2Offset(AM2Opc); + emitWordLE(Binary); + return; + } + + // Set bit I(25), because this is not in immediate encoding. + Binary |= 1 << ARMII::I_BitShift; + assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg())); + // Set bit[3:0] to the corresponding Rm register + Binary |= getARMRegisterNumbering(MO2.getReg()); + + // If this instr is in scaled register offset/index instruction, set + // shift_immed(bit[11:7]) and shift(bit[6:5]) fields. + if (unsigned ShImm = ARM_AM::getAM2Offset(AM2Opc)) { + Binary |= getShiftOp(AM2Opc) << ARMII::ShiftImmShift; // shift + Binary |= ShImm << ARMII::ShiftShift; // shift_immed + } + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI, + unsigned ImplicitRn) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Operand 0 of a pre- and post-indexed store is the address base + // writeback. Skip it. + bool Skipped = false; + if (IsPrePost && Form == ARMII::StMiscFrm) { + ++OpIdx; + Skipped = true; + } + + // Set first operand + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + // Skip LDRD and STRD's second operand. + if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD) + ++OpIdx; + + // Set second operand + if (ImplicitRn) + // Special handling for implicit use (e.g. PC). + Binary |= (getARMRegisterNumbering(ImplicitRn) << ARMII::RegRnShift); + else + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // If this is a two-address operand, skip it. e.g. LDRH_POST. + if (!Skipped && TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + const MachineOperand &MO2 = MI.getOperand(OpIdx); + unsigned AM3Opc = (ImplicitRn == ARM::PC) + ? 0 : MI.getOperand(OpIdx+1).getImm(); + + // Set bit U(23) according to sign of immed value (positive or negative) + Binary |= ((ARM_AM::getAM3Op(AM3Opc) == ARM_AM::add ? 1 : 0) << + ARMII::U_BitShift); + + // If this instr is in register offset/index encoding, set bit[3:0] + // to the corresponding Rm register. + if (MO2.getReg()) { + Binary |= getARMRegisterNumbering(MO2.getReg()); + emitWordLE(Binary); + return; + } + + // This instr is in immediate offset/index encoding, set bit 22 to 1. + Binary |= 1 << ARMII::AM3_I_BitShift; + if (unsigned ImmOffs = ARM_AM::getAM3Offset(AM3Opc)) { + // Set operands + Binary |= (ImmOffs >> 4) << ARMII::ImmHiShift; // immedH + Binary |= (ImmOffs & 0xF); // immedL + } + + emitWordLE(Binary); +} + +static unsigned getAddrModeUPBits(unsigned Mode) { + unsigned Binary = 0; + + // Set addressing mode by modifying bits U(23) and P(24) + // IA - Increment after - bit U = 1 and bit P = 0 + // IB - Increment before - bit U = 1 and bit P = 1 + // DA - Decrement after - bit U = 0 and bit P = 0 + // DB - Decrement before - bit U = 0 and bit P = 1 + switch (Mode) { + default: llvm_unreachable("Unknown addressing sub-mode!"); + case ARM_AM::da: break; + case ARM_AM::db: Binary |= 0x1 << ARMII::P_BitShift; break; + case ARM_AM::ia: Binary |= 0x1 << ARMII::U_BitShift; break; + case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break; + } + + return Binary; +} + +void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Skip operand 0 of an instruction with base register update. + unsigned OpIdx = 0; + if (IsUpdating) + ++OpIdx; + + // Set base address operand + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode()); + Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode)); + + // Set bit W(21) + if (IsUpdating) + Binary |= 0x1 << ARMII::W_BitShift; + + // Set registers + for (unsigned i = OpIdx+2, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + break; + unsigned RegNum = getARMRegisterNumbering(MO.getReg()); + assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + RegNum < 16); + Binary |= 0x1 << RegNum; + } + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMulFrmInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode S bit if MI modifies CPSR. + Binary |= getAddrModeSBit(MI, TID); + + // 32x32->64bit operations have two destination registers. The number + // of register definitions will tell us if that's what we're dealing with. + unsigned OpIdx = 0; + if (TID.getNumDefs() == 2) + Binary |= getMachineOpValue (MI, OpIdx++) << ARMII::RegRdLoShift; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdHiShift; + + // Encode Rm + Binary |= getMachineOpValue(MI, OpIdx++); + + // Encode Rs + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift; + + // Many multiple instructions (e.g. MLA) have three src operands. Encode + // it as Rn (for multiply, that's in the same offset as RdLo. + if (TID.getNumOperands() > OpIdx && + !TID.OpInfo[OpIdx].isPredicate() && + !TID.OpInfo[OpIdx].isOptionalDef()) + Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdLoShift; + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + const MachineOperand &MO1 = MI.getOperand(OpIdx++); + const MachineOperand &MO2 = MI.getOperand(OpIdx); + if (MO2.isReg()) { + // Two register operand form. + // Encode Rn. + Binary |= getMachineOpValue(MI, MO1) << ARMII::RegRnShift; + + // Encode Rm. + Binary |= getMachineOpValue(MI, MO2); + ++OpIdx; + } else { + Binary |= getMachineOpValue(MI, MO1); + } + + // Encode rot imm (0, 8, 16, or 24) if it has a rotate immediate operand. + if (MI.getOperand(OpIdx).isImm() && + !TID.OpInfo[OpIdx].isPredicate() && + !TID.OpInfo[OpIdx].isOptionalDef()) + Binary |= (getMachineOpValue(MI, OpIdx) / 8) << ARMII::ExtRotImmShift; + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitMiscArithInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Rd + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift; + + const MachineOperand &MO = MI.getOperand(OpIdx++); + if (OpIdx == TID.getNumOperands() || + TID.OpInfo[OpIdx].isPredicate() || + TID.OpInfo[OpIdx].isOptionalDef()) { + // Encode Rm and it's done. + Binary |= getMachineOpValue(MI, MO); + emitWordLE(Binary); + return; + } + + // Encode Rn. + Binary |= getMachineOpValue(MI, MO) << ARMII::RegRnShift; + + // Encode Rm. + Binary |= getMachineOpValue(MI, OpIdx++); + + // Encode shift_imm. + unsigned ShiftAmt = MI.getOperand(OpIdx).getImm(); + if (TID.Opcode == ARM::PKHTB) { + assert(ShiftAmt != 0 && "PKHTB shift_imm is 0!"); + if (ShiftAmt == 32) + ShiftAmt = 0; + } + assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); + Binary |= ShiftAmt << ARMII::ShiftShift; + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGen. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd + Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift; + + // Encode saturate bit position. + unsigned Pos = MI.getOperand(1).getImm(); + if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16) + Pos -= 1; + assert((Pos < 16 || (Pos < 32 && + TID.Opcode != ARM::SSAT16 && + TID.Opcode != ARM::USAT16)) && + "saturate bit position out of range"); + Binary |= Pos << 16; + + // Encode Rm + Binary |= getMachineOpValue(MI, 2); + + // Encode shift_imm. + if (TID.getNumOperands() == 4) { + unsigned ShiftOp = MI.getOperand(3).getImm(); + ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp); + if (Opc == ARM_AM::asr) + Binary |= (1 << 6); + unsigned ShiftAmt = MI.getOperand(3).getImm(); + if (ShiftAmt == 32 && Opc == ARM_AM::asr) + ShiftAmt = 0; + assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!"); + Binary |= ShiftAmt << ARMII::ShiftShift; + } + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + if (TID.Opcode == ARM::TPsoft) { + llvm_unreachable("ARM::TPsoft FIXME"); // FIXME + } + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Set signed_immed_24 field + Binary |= getMachineOpValue(MI, 0); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitInlineJumpTable(unsigned JTIndex) { + // Remember the base address of the inline jump table. + uintptr_t JTBase = MCE.getCurrentPCValue(); + JTI->addJumpTableBaseAddr(JTIndex, JTBase); + DEBUG(errs() << " ** Jump Table #" << JTIndex << " @ " << (void*)JTBase + << '\n'); + + // Now emit the jump table entries. + const std::vector &MBBs = (*MJTEs)[JTIndex].MBBs; + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) { + if (IsPIC) + // DestBB address - JT base. + emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_pic_jt, JTBase); + else + // Absolute DestBB address. + emitMachineBasicBlock(MBBs[i], ARM::reloc_arm_absolute); + emitWordLE(0); + } +} + +void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Handle jump tables. + if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { + // First emit a ldr pc, [] instruction. + emitDataProcessingInstruction(MI, ARM::PC); + + // Then emit the inline jump table. + unsigned JTIndex = + (TID.Opcode == ARM::BR_JTr) + ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); + emitInlineJumpTable(JTIndex); + return; + } else if (TID.Opcode == ARM::BR_JTm) { + // First emit a ldr pc, [] instruction. + emitLoadStoreInstruction(MI, ARM::PC); + + // Then emit the inline jump table. + emitInlineJumpTable(MI.getOperand(3).getIndex()); + return; + } + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) + // The return register is LR. + Binary |= getARMRegisterNumbering(ARM::LR); + else + // otherwise, set the return register + Binary |= getMachineOpValue(MI, 0); + + emitWordLE(Binary); +} + +static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegD = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = ARM::SPRRegisterClass->contains(RegD); + RegD = getARMRegisterNumbering(RegD); + if (!isSPVFP) + Binary |= RegD << ARMII::RegRdShift; + else { + Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; + Binary |= (RegD & 0x01) << ARMII::D_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegN = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = ARM::SPRRegisterClass->contains(RegN); + RegN = getARMRegisterNumbering(RegN); + if (!isSPVFP) + Binary |= RegN << ARMII::RegRnShift; + else { + Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; + Binary |= (RegN & 0x01) << ARMII::N_BitShift; + } + return Binary; +} + +static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + bool isSPVFP = ARM::SPRRegisterClass->contains(RegM); + RegM = getARMRegisterNumbering(RegM); + if (!isSPVFP) + Binary |= RegM; + else { + Binary |= ((RegM & 0x1E) >> 1); + Binary |= (RegM & 0x01) << ARMII::M_BitShift; + } + return Binary; +} + +void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + assert((Binary & ARMII::D_BitShift) == 0 && + (Binary & ARMII::N_BitShift) == 0 && + (Binary & ARMII::M_BitShift) == 0 && "VFP encoding bug!"); + + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, OpIdx++); + + // If this is a two-address operand, skip it, e.g. FMACD. + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + + // Encode Dn / Sn. + if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) + Binary |= encodeVFPRn(MI, OpIdx++); + + if (OpIdx == TID.getNumOperands() || + TID.OpInfo[OpIdx].isPredicate() || + TID.OpInfo[OpIdx].isOptionalDef()) { + // FCMPEZD etc. has only one operand. + emitWordLE(Binary); + return; + } + + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, OpIdx); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Form = TID.TSFlags & ARMII::FormMask; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 0); + break; + case ARMII::VFPConv4Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 0); + break; + case ARMII::VFPConv5Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 0); + break; + } + + switch (Form) { + default: break; + case ARMII::VFPConv1Frm: + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 1); + break; + case ARMII::VFPConv2Frm: + case ARMII::VFPConv3Frm: + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 1); + break; + case ARMII::VFPConv4Frm: + case ARMII::VFPConv5Frm: + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, 1); + break; + } + + if (Form == ARMII::VFPConv5Frm) + // Encode Dn / Sn. + Binary |= encodeVFPRn(MI, 2); + else if (Form == ARMII::VFPConv3Frm) + // Encode Dm / Sm. + Binary |= encodeVFPRm(MI, 2); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) { + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + unsigned OpIdx = 0; + + // Encode Dd / Sd. + Binary |= encodeVFPRd(MI, OpIdx++); + + // Encode address base. + const MachineOperand &Base = MI.getOperand(OpIdx++); + Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift; + + // If there is a non-zero immediate offset, encode it. + if (Base.isReg()) { + const MachineOperand &Offset = MI.getOperand(OpIdx); + if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) { + if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add) + Binary |= 1 << ARMII::U_BitShift; + Binary |= ImmOffs; + emitWordLE(Binary); + return; + } + } + + // If immediate offset is omitted, default to +0. + Binary |= 1 << ARMII::U_BitShift; + + emitWordLE(Binary); +} + +void +ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0; + + // Part of binary is determined by TableGn. + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Skip operand 0 of an instruction with base register update. + unsigned OpIdx = 0; + if (IsUpdating) + ++OpIdx; + + // Set base address operand + Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift; + + // Set addressing mode by modifying bits U(23) and P(24) + ARM_AM::AMSubMode Mode = ARM_AM::getLoadStoreMultipleSubMode(MI.getOpcode()); + Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(Mode)); + + // Set bit W(21) + if (IsUpdating) + Binary |= 0x1 << ARMII::W_BitShift; + + // First register is encoded in Dd. + Binary |= encodeVFPRd(MI, OpIdx+2); + + // Count the number of registers. + unsigned NumRegs = 1; + for (unsigned i = OpIdx+3, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (!MO.isReg() || MO.isImplicit()) + break; + ++NumRegs; + } + // Bit 8 will be set if is consecutive 64-bit registers (e.g., D0) + // Otherwise, it will be 0, in the case of 32-bit registers. + if(Binary & 0x100) + Binary |= NumRegs * 2; + else + Binary |= NumRegs; + + emitWordLE(Binary); +} + +static unsigned encodeNEONRd(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegD = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + RegD = getARMRegisterNumbering(RegD); + Binary |= (RegD & 0xf) << ARMII::RegRdShift; + Binary |= ((RegD >> 4) & 1) << ARMII::D_BitShift; + return Binary; +} + +static unsigned encodeNEONRn(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegN = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + RegN = getARMRegisterNumbering(RegN); + Binary |= (RegN & 0xf) << ARMII::RegRnShift; + Binary |= ((RegN >> 4) & 1) << ARMII::N_BitShift; + return Binary; +} + +static unsigned encodeNEONRm(const MachineInstr &MI, unsigned OpIdx) { + unsigned RegM = MI.getOperand(OpIdx).getReg(); + unsigned Binary = 0; + RegM = getARMRegisterNumbering(RegM); + Binary |= (RegM & 0xf); + Binary |= ((RegM >> 4) & 1) << ARMII::M_BitShift; + return Binary; +} + +/// convertNEONDataProcToThumb - Convert the ARM mode encoding for a NEON +/// data-processing instruction to the corresponding Thumb encoding. +static unsigned convertNEONDataProcToThumb(unsigned Binary) { + assert((Binary & 0xfe000000) == 0xf2000000 && + "not an ARM NEON data-processing instruction"); + unsigned UBit = (Binary >> 24) & 1; + return 0xef000000 | (UBit << 28) | (Binary & 0xffffff); +} + +void ARMCodeEmitter::emitNEONLaneInstruction(const MachineInstr &MI) { + unsigned Binary = getBinaryCodeForInstr(MI); + + unsigned RegTOpIdx, RegNOpIdx, LnOpIdx; + const TargetInstrDesc &TID = MI.getDesc(); + if ((TID.TSFlags & ARMII::FormMask) == ARMII::NGetLnFrm) { + RegTOpIdx = 0; + RegNOpIdx = 1; + LnOpIdx = 2; + } else { // ARMII::NSetLnFrm + RegTOpIdx = 2; + RegNOpIdx = 0; + LnOpIdx = 3; + } + + // Set the conditional execution predicate + Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; + + unsigned RegT = MI.getOperand(RegTOpIdx).getReg(); + RegT = getARMRegisterNumbering(RegT); + Binary |= (RegT << ARMII::RegRdShift); + Binary |= encodeNEONRn(MI, RegNOpIdx); + + unsigned LaneShift; + if ((Binary & (1 << 22)) != 0) + LaneShift = 0; // 8-bit elements + else if ((Binary & (1 << 5)) != 0) + LaneShift = 1; // 16-bit elements + else + LaneShift = 2; // 32-bit elements + + unsigned Lane = MI.getOperand(LnOpIdx).getImm() << LaneShift; + unsigned Opc1 = Lane >> 2; + unsigned Opc2 = Lane & 3; + assert((Opc1 & 3) == 0 && "out-of-range lane number operand"); + Binary |= (Opc1 << 21); + Binary |= (Opc2 << 5); + + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitNEONDupInstruction(const MachineInstr &MI) { + unsigned Binary = getBinaryCodeForInstr(MI); + + // Set the conditional execution predicate + Binary |= (IsThumb ? ARMCC::AL : II->getPredicate(&MI)) << ARMII::CondShift; + + unsigned RegT = MI.getOperand(1).getReg(); + RegT = getARMRegisterNumbering(RegT); + Binary |= (RegT << ARMII::RegRdShift); + Binary |= encodeNEONRn(MI, 0); + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitNEON1RegModImmInstruction(const MachineInstr &MI) { + unsigned Binary = getBinaryCodeForInstr(MI); + // Destination register is encoded in Dd. + Binary |= encodeNEONRd(MI, 0); + // Immediate fields: Op, Cmode, I, Imm3, Imm4 + unsigned Imm = MI.getOperand(1).getImm(); + unsigned Op = (Imm >> 12) & 1; + unsigned Cmode = (Imm >> 8) & 0xf; + unsigned I = (Imm >> 7) & 1; + unsigned Imm3 = (Imm >> 4) & 0x7; + unsigned Imm4 = Imm & 0xf; + Binary |= (I << 24) | (Imm3 << 16) | (Cmode << 8) | (Op << 5) | Imm4; + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitNEON2RegInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Binary = getBinaryCodeForInstr(MI); + // Destination register is encoded in Dd; source register in Dm. + unsigned OpIdx = 0; + Binary |= encodeNEONRd(MI, OpIdx++); + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + Binary |= encodeNEONRm(MI, OpIdx); + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); + // FIXME: This does not handle VDUPfdf or VDUPfqf. + emitWordLE(Binary); +} + +void ARMCodeEmitter::emitNEON3RegInstruction(const MachineInstr &MI) { + const TargetInstrDesc &TID = MI.getDesc(); + unsigned Binary = getBinaryCodeForInstr(MI); + // Destination register is encoded in Dd; source registers in Dn and Dm. + unsigned OpIdx = 0; + Binary |= encodeNEONRd(MI, OpIdx++); + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + Binary |= encodeNEONRn(MI, OpIdx++); + if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) + ++OpIdx; + Binary |= encodeNEONRm(MI, OpIdx); + if (IsThumb) + Binary = convertNEONDataProcToThumb(Binary); + // FIXME: This does not handle VMOVDneon or VMOVQ. + emitWordLE(Binary); +} + +#include "ARMGenCodeEmitter.inc" diff --git a/final/lib/Target/ARM/ARMConstantIslandPass.cpp b/final/lib/Target/ARM/ARMConstantIslandPass.cpp new file mode 100644 index 00000000000..13d1b33d116 --- /dev/null +++ b/final/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -0,0 +1,1900 @@ +//===-- ARMConstantIslandPass.cpp - ARM constant islands ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that splits the constant pool up into 'islands' +// which are scattered through-out the function. This is required due to the +// limited pc-relative displacements that ARM has. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-cp-islands" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMInstrInfo.h" +#include "Thumb2InstrInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include +using namespace llvm; + +STATISTIC(NumCPEs, "Number of constpool entries"); +STATISTIC(NumSplit, "Number of uncond branches inserted"); +STATISTIC(NumCBrFixed, "Number of cond branches fixed"); +STATISTIC(NumUBrFixed, "Number of uncond branches fixed"); +STATISTIC(NumTBs, "Number of table branches generated"); +STATISTIC(NumT2CPShrunk, "Number of Thumb2 constantpool instructions shrunk"); +STATISTIC(NumT2BrShrunk, "Number of Thumb2 immediate branches shrunk"); +STATISTIC(NumCBZ, "Number of CBZ / CBNZ formed"); +STATISTIC(NumJTMoved, "Number of jump table destination blocks moved"); +STATISTIC(NumJTInserted, "Number of jump table intermediate blocks inserted"); + + +static cl::opt +AdjustJumpTableBlocks("arm-adjust-jump-tables", cl::Hidden, cl::init(true), + cl::desc("Adjust basic block layout to better use TB[BH]")); + +namespace { + /// ARMConstantIslands - Due to limited PC-relative displacements, ARM + /// requires constant pool entries to be scattered among the instructions + /// inside a function. To do this, it completely ignores the normal LLVM + /// constant pool; instead, it places constants wherever it feels like with + /// special instructions. + /// + /// The terminology used in this pass includes: + /// Islands - Clumps of constants placed in the function. + /// Water - Potential places where an island could be formed. + /// CPE - A constant pool entry that has been placed somewhere, which + /// tracks a list of users. + class ARMConstantIslands : public MachineFunctionPass { + /// BBSizes - The size of each MachineBasicBlock in bytes of code, indexed + /// by MBB Number. The two-byte pads required for Thumb alignment are + /// counted as part of the following block (i.e., the offset and size for + /// a padded block will both be ==2 mod 4). + std::vector BBSizes; + + /// BBOffsets - the offset of each MBB in bytes, starting from 0. + /// The two-byte pads required for Thumb alignment are counted as part of + /// the following block. + std::vector BBOffsets; + + /// WaterList - A sorted list of basic blocks where islands could be placed + /// (i.e. blocks that don't fall through to the following block, due + /// to a return, unreachable, or unconditional branch). + std::vector WaterList; + + /// NewWaterList - The subset of WaterList that was created since the + /// previous iteration by inserting unconditional branches. + SmallSet NewWaterList; + + typedef std::vector::iterator water_iterator; + + /// CPUser - One user of a constant pool, keeping the machine instruction + /// pointer, the constant pool being referenced, and the max displacement + /// allowed from the instruction to the CP. The HighWaterMark records the + /// highest basic block where a new CPEntry can be placed. To ensure this + /// pass terminates, the CP entries are initially placed at the end of the + /// function and then move monotonically to lower addresses. The + /// exception to this rule is when the current CP entry for a particular + /// CPUser is out of range, but there is another CP entry for the same + /// constant value in range. We want to use the existing in-range CP + /// entry, but if it later moves out of range, the search for new water + /// should resume where it left off. The HighWaterMark is used to record + /// that point. + struct CPUser { + MachineInstr *MI; + MachineInstr *CPEMI; + MachineBasicBlock *HighWaterMark; + unsigned MaxDisp; + bool NegOk; + bool IsSoImm; + CPUser(MachineInstr *mi, MachineInstr *cpemi, unsigned maxdisp, + bool neg, bool soimm) + : MI(mi), CPEMI(cpemi), MaxDisp(maxdisp), NegOk(neg), IsSoImm(soimm) { + HighWaterMark = CPEMI->getParent(); + } + }; + + /// CPUsers - Keep track of all of the machine instructions that use various + /// constant pools and their max displacement. + std::vector CPUsers; + + /// CPEntry - One per constant pool entry, keeping the machine instruction + /// pointer, the constpool index, and the number of CPUser's which + /// reference this entry. + struct CPEntry { + MachineInstr *CPEMI; + unsigned CPI; + unsigned RefCount; + CPEntry(MachineInstr *cpemi, unsigned cpi, unsigned rc = 0) + : CPEMI(cpemi), CPI(cpi), RefCount(rc) {} + }; + + /// CPEntries - Keep track of all of the constant pool entry machine + /// instructions. For each original constpool index (i.e. those that + /// existed upon entry to this pass), it keeps a vector of entries. + /// Original elements are cloned as we go along; the clones are + /// put in the vector of the original element, but have distinct CPIs. + std::vector > CPEntries; + + /// ImmBranch - One per immediate branch, keeping the machine instruction + /// pointer, conditional or unconditional, the max displacement, + /// and (if isCond is true) the corresponding unconditional branch + /// opcode. + struct ImmBranch { + MachineInstr *MI; + unsigned MaxDisp : 31; + bool isCond : 1; + int UncondBr; + ImmBranch(MachineInstr *mi, unsigned maxdisp, bool cond, int ubr) + : MI(mi), MaxDisp(maxdisp), isCond(cond), UncondBr(ubr) {} + }; + + /// ImmBranches - Keep track of all the immediate branch instructions. + /// + std::vector ImmBranches; + + /// PushPopMIs - Keep track of all the Thumb push / pop instructions. + /// + SmallVector PushPopMIs; + + /// T2JumpTables - Keep track of all the Thumb2 jumptable instructions. + SmallVector T2JumpTables; + + /// HasFarJump - True if any far jump instruction has been emitted during + /// the branch fix up pass. + bool HasFarJump; + + /// HasInlineAsm - True if the function contains inline assembly. + bool HasInlineAsm; + + const ARMInstrInfo *TII; + const ARMSubtarget *STI; + ARMFunctionInfo *AFI; + bool isThumb; + bool isThumb1; + bool isThumb2; + public: + static char ID; + ARMConstantIslands() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual const char *getPassName() const { + return "ARM constant island placement and branch shortening pass"; + } + + private: + void DoInitialPlacement(MachineFunction &MF, + std::vector &CPEMIs); + CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); + void JumpTableFunctionScan(MachineFunction &MF); + void InitialFunctionScan(MachineFunction &MF, + const std::vector &CPEMIs); + MachineBasicBlock *SplitBlockBeforeInstr(MachineInstr *MI); + void UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB); + void AdjustBBOffsetsAfter(MachineBasicBlock *BB, int delta); + bool DecrementOldEntry(unsigned CPI, MachineInstr* CPEMI); + int LookForExistingCPEntry(CPUser& U, unsigned UserOffset); + bool LookForWater(CPUser&U, unsigned UserOffset, water_iterator &WaterIter); + void CreateNewWater(unsigned CPUserIndex, unsigned UserOffset, + MachineBasicBlock *&NewMBB); + bool HandleConstantPoolUser(MachineFunction &MF, unsigned CPUserIndex); + void RemoveDeadCPEMI(MachineInstr *CPEMI); + bool RemoveUnusedCPEntries(); + bool CPEIsInRange(MachineInstr *MI, unsigned UserOffset, + MachineInstr *CPEMI, unsigned Disp, bool NegOk, + bool DoDump = false); + bool WaterIsInRange(unsigned UserOffset, MachineBasicBlock *Water, + CPUser &U); + bool OffsetIsInRange(unsigned UserOffset, unsigned TrialOffset, + unsigned Disp, bool NegativeOK, bool IsSoImm = false); + bool BBIsInRange(MachineInstr *MI, MachineBasicBlock *BB, unsigned Disp); + bool FixUpImmediateBr(MachineFunction &MF, ImmBranch &Br); + bool FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br); + bool FixUpUnconditionalBr(MachineFunction &MF, ImmBranch &Br); + bool UndoLRSpillRestore(); + bool OptimizeThumb2Instructions(MachineFunction &MF); + bool OptimizeThumb2Branches(MachineFunction &MF); + bool ReorderThumb2JumpTables(MachineFunction &MF); + bool OptimizeThumb2JumpTables(MachineFunction &MF); + MachineBasicBlock *AdjustJTTargetBlockForward(MachineBasicBlock *BB, + MachineBasicBlock *JTBB); + + unsigned GetOffsetOf(MachineInstr *MI) const; + void dumpBBs(); + void verify(MachineFunction &MF); + }; + char ARMConstantIslands::ID = 0; +} + +/// verify - check BBOffsets, BBSizes, alignment of islands +void ARMConstantIslands::verify(MachineFunction &MF) { + assert(BBOffsets.size() == BBSizes.size()); + for (unsigned i = 1, e = BBOffsets.size(); i != e; ++i) + assert(BBOffsets[i-1]+BBSizes[i-1] == BBOffsets[i]); + if (!isThumb) + return; +#ifndef NDEBUG + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock *MBB = MBBI; + if (!MBB->empty() && + MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) { + unsigned MBBId = MBB->getNumber(); + assert(HasInlineAsm || + (BBOffsets[MBBId]%4 == 0 && BBSizes[MBBId]%4 == 0) || + (BBOffsets[MBBId]%4 != 0 && BBSizes[MBBId]%4 != 0)); + } + } + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) { + CPUser &U = CPUsers[i]; + unsigned UserOffset = GetOffsetOf(U.MI) + (isThumb ? 4 : 8); + unsigned CPEOffset = GetOffsetOf(U.CPEMI); + unsigned Disp = UserOffset < CPEOffset ? CPEOffset - UserOffset : + UserOffset - CPEOffset; + assert(Disp <= U.MaxDisp || "Constant pool entry out of range!"); + } +#endif +} + +/// print block size and offset information - debugging +void ARMConstantIslands::dumpBBs() { + for (unsigned J = 0, E = BBOffsets.size(); J !=E; ++J) { + DEBUG(errs() << "block " << J << " offset " << BBOffsets[J] + << " size " << BBSizes[J] << "\n"); + } +} + +/// createARMConstantIslandPass - returns an instance of the constpool +/// island pass. +FunctionPass *llvm::createARMConstantIslandPass() { + return new ARMConstantIslands(); +} + +bool ARMConstantIslands::runOnMachineFunction(MachineFunction &MF) { + MachineConstantPool &MCP = *MF.getConstantPool(); + + TII = (const ARMInstrInfo*)MF.getTarget().getInstrInfo(); + AFI = MF.getInfo(); + STI = &MF.getTarget().getSubtarget(); + + isThumb = AFI->isThumbFunction(); + isThumb1 = AFI->isThumb1OnlyFunction(); + isThumb2 = AFI->isThumb2Function(); + + HasFarJump = false; + HasInlineAsm = false; + + // Renumber all of the machine basic blocks in the function, guaranteeing that + // the numbers agree with the position of the block in the function. + MF.RenumberBlocks(); + + // Try to reorder and otherwise adjust the block layout to make good use + // of the TB[BH] instructions. + bool MadeChange = false; + if (isThumb2 && AdjustJumpTableBlocks) { + JumpTableFunctionScan(MF); + MadeChange |= ReorderThumb2JumpTables(MF); + // Data is out of date, so clear it. It'll be re-computed later. + T2JumpTables.clear(); + // Blocks may have shifted around. Keep the numbering up to date. + MF.RenumberBlocks(); + } + + // Thumb1 functions containing constant pools get 4-byte alignment. + // This is so we can keep exact track of where the alignment padding goes. + + // ARM and Thumb2 functions need to be 4-byte aligned. + if (!isThumb1) + MF.EnsureAlignment(2); // 2 = log2(4) + + // Perform the initial placement of the constant pool entries. To start with, + // we put them all at the end of the function. + std::vector CPEMIs; + if (!MCP.isEmpty()) { + DoInitialPlacement(MF, CPEMIs); + if (isThumb1) + MF.EnsureAlignment(2); // 2 = log2(4) + } + + /// The next UID to take is the first unused one. + AFI->initPICLabelUId(CPEMIs.size()); + + // Do the initial scan of the function, building up information about the + // sizes of each block, the location of all the water, and finding all of the + // constant pool users. + InitialFunctionScan(MF, CPEMIs); + CPEMIs.clear(); + DEBUG(dumpBBs()); + + + /// Remove dead constant pool entries. + MadeChange |= RemoveUnusedCPEntries(); + + // Iteratively place constant pool entries and fix up branches until there + // is no change. + unsigned NoCPIters = 0, NoBRIters = 0; + while (true) { + bool CPChange = false; + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) + CPChange |= HandleConstantPoolUser(MF, i); + if (CPChange && ++NoCPIters > 30) + llvm_unreachable("Constant Island pass failed to converge!"); + DEBUG(dumpBBs()); + + // Clear NewWaterList now. If we split a block for branches, it should + // appear as "new water" for the next iteration of constant pool placement. + NewWaterList.clear(); + + bool BRChange = false; + for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) + BRChange |= FixUpImmediateBr(MF, ImmBranches[i]); + if (BRChange && ++NoBRIters > 30) + llvm_unreachable("Branch Fix Up pass failed to converge!"); + DEBUG(dumpBBs()); + + if (!CPChange && !BRChange) + break; + MadeChange = true; + } + + // Shrink 32-bit Thumb2 branch, load, and store instructions. + if (isThumb2 && !STI->prefers32BitThumb()) + MadeChange |= OptimizeThumb2Instructions(MF); + + // After a while, this might be made debug-only, but it is not expensive. + verify(MF); + + // If LR has been forced spilled and no far jump (i.e. BL) has been issued, + // undo the spill / restore of LR if possible. + if (isThumb && !HasFarJump && AFI->isLRSpilledForFarJump()) + MadeChange |= UndoLRSpillRestore(); + + // Save the mapping between original and cloned constpool entries. + for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { + for (unsigned j = 0, je = CPEntries[i].size(); j != je; ++j) { + const CPEntry & CPE = CPEntries[i][j]; + AFI->recordCPEClone(i, CPE.CPI); + } + } + + DEBUG(errs() << '\n'; dumpBBs()); + + BBSizes.clear(); + BBOffsets.clear(); + WaterList.clear(); + CPUsers.clear(); + CPEntries.clear(); + ImmBranches.clear(); + PushPopMIs.clear(); + T2JumpTables.clear(); + + return MadeChange; +} + +/// DoInitialPlacement - Perform the initial placement of the constant pool +/// entries. To start with, we put them all at the end of the function. +void ARMConstantIslands::DoInitialPlacement(MachineFunction &MF, + std::vector &CPEMIs) { + // Create the basic block to hold the CPE's. + MachineBasicBlock *BB = MF.CreateMachineBasicBlock(); + MF.push_back(BB); + + // Add all of the constants from the constant pool to the end block, use an + // identity mapping of CPI's to CPE's. + const std::vector &CPs = + MF.getConstantPool()->getConstants(); + + const TargetData &TD = *MF.getTarget().getTargetData(); + for (unsigned i = 0, e = CPs.size(); i != e; ++i) { + unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); + // Verify that all constant pool entries are a multiple of 4 bytes. If not, + // we would have to pad them out or something so that instructions stay + // aligned. + assert((Size & 3) == 0 && "CP Entry not multiple of 4 bytes!"); + MachineInstr *CPEMI = + BuildMI(BB, DebugLoc(), TII->get(ARM::CONSTPOOL_ENTRY)) + .addImm(i).addConstantPoolIndex(i).addImm(Size); + CPEMIs.push_back(CPEMI); + + // Add a new CPEntry, but no corresponding CPUser yet. + std::vector CPEs; + CPEs.push_back(CPEntry(CPEMI, i)); + CPEntries.push_back(CPEs); + ++NumCPEs; + DEBUG(errs() << "Moved CPI#" << i << " to end of function as #" << i + << "\n"); + } +} + +/// BBHasFallthrough - Return true if the specified basic block can fallthrough +/// into the block immediately after it. +static bool BBHasFallthrough(MachineBasicBlock *MBB) { + // Get the next machine basic block in the function. + MachineFunction::iterator MBBI = MBB; + // Can't fall off end of function. + if (llvm::next(MBBI) == MBB->getParent()->end()) + return false; + + MachineBasicBlock *NextBB = llvm::next(MBBI); + for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), + E = MBB->succ_end(); I != E; ++I) + if (*I == NextBB) + return true; + + return false; +} + +/// findConstPoolEntry - Given the constpool index and CONSTPOOL_ENTRY MI, +/// look up the corresponding CPEntry. +ARMConstantIslands::CPEntry +*ARMConstantIslands::findConstPoolEntry(unsigned CPI, + const MachineInstr *CPEMI) { + std::vector &CPEs = CPEntries[CPI]; + // Number of entries per constpool index should be small, just do a + // linear search. + for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { + if (CPEs[i].CPEMI == CPEMI) + return &CPEs[i]; + } + return NULL; +} + +/// JumpTableFunctionScan - Do a scan of the function, building up +/// information about the sizes of each block and the locations of all +/// the jump tables. +void ARMConstantIslands::JumpTableFunctionScan(MachineFunction &MF) { + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) + if (I->getDesc().isBranch() && I->getOpcode() == ARM::t2BR_JT) + T2JumpTables.push_back(I); + } +} + +/// InitialFunctionScan - Do the initial scan of the function, building up +/// information about the sizes of each block, the location of all the water, +/// and finding all of the constant pool users. +void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF, + const std::vector &CPEMIs) { + // First thing, see if the function has any inline assembly in it. If so, + // we have to be conservative about alignment assumptions, as we don't + // know for sure the size of any instructions in the inline assembly. + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) + if (I->getOpcode() == ARM::INLINEASM) + HasInlineAsm = true; + } + + // Now go back through the instructions and build up our data structures. + unsigned Offset = 0; + for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + MachineBasicBlock &MBB = *MBBI; + + // If this block doesn't fall through into the next MBB, then this is + // 'water' that a constant pool island could be placed. + if (!BBHasFallthrough(&MBB)) + WaterList.push_back(&MBB); + + unsigned MBBSize = 0; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + if (I->isDebugValue()) + continue; + // Add instruction size to MBBSize. + MBBSize += TII->GetInstSizeInBytes(I); + + int Opc = I->getOpcode(); + if (I->getDesc().isBranch()) { + bool isCond = false; + unsigned Bits = 0; + unsigned Scale = 1; + int UOpc = Opc; + switch (Opc) { + default: + continue; // Ignore other JT branches + case ARM::tBR_JTr: + // A Thumb1 table jump may involve padding; for the offsets to + // be right, functions containing these must be 4-byte aligned. + // tBR_JTr expands to a mov pc followed by .align 2 and then the jump + // table entries. So this code checks whether offset of tBR_JTr + 2 + // is aligned. That is held in Offset+MBBSize, which already has + // 2 added in for the size of the mov pc instruction. + MF.EnsureAlignment(2U); + if ((Offset+MBBSize)%4 != 0 || HasInlineAsm) + // FIXME: Add a pseudo ALIGN instruction instead. + MBBSize += 2; // padding + continue; // Does not get an entry in ImmBranches + case ARM::t2BR_JT: + T2JumpTables.push_back(I); + continue; // Does not get an entry in ImmBranches + case ARM::Bcc: + isCond = true; + UOpc = ARM::B; + // Fallthrough + case ARM::B: + Bits = 24; + Scale = 4; + break; + case ARM::tBcc: + isCond = true; + UOpc = ARM::tB; + Bits = 8; + Scale = 2; + break; + case ARM::tB: + Bits = 11; + Scale = 2; + break; + case ARM::t2Bcc: + isCond = true; + UOpc = ARM::t2B; + Bits = 20; + Scale = 2; + break; + case ARM::t2B: + Bits = 24; + Scale = 2; + break; + } + + // Record this immediate branch. + unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc)); + } + + if (Opc == ARM::tPUSH || Opc == ARM::tPOP_RET) + PushPopMIs.push_back(I); + + if (Opc == ARM::CONSTPOOL_ENTRY) + continue; + + // Scan the instructions for constant pool operands. + for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) + if (I->getOperand(op).isCPI()) { + // We found one. The addressing mode tells us the max displacement + // from the PC that this instruction permits. + + // Basic size info comes from the TSFlags field. + unsigned Bits = 0; + unsigned Scale = 1; + bool NegOk = false; + bool IsSoImm = false; + + switch (Opc) { + default: + llvm_unreachable("Unknown addressing mode for CP reference!"); + break; + + // Taking the address of a CP entry. + case ARM::LEApcrel: + // This takes a SoImm, which is 8 bit immediate rotated. We'll + // pretend the maximum offset is 255 * 4. Since each instruction + // 4 byte wide, this is always correct. We'll check for other + // displacements that fits in a SoImm as well. + Bits = 8; + Scale = 4; + NegOk = true; + IsSoImm = true; + break; + case ARM::t2LEApcrel: + Bits = 12; + NegOk = true; + break; + case ARM::tLEApcrel: + Bits = 8; + Scale = 4; + break; + + case ARM::LDRi12: + case ARM::LDRcp: + case ARM::t2LDRpci: + Bits = 12; // +-offset_12 + NegOk = true; + break; + + case ARM::tLDRpci: + Bits = 8; + Scale = 4; // +(offset_8*4) + break; + + case ARM::VLDRD: + case ARM::VLDRS: + Bits = 8; + Scale = 4; // +-(offset_8*4) + NegOk = true; + break; + } + + // Remember that this is a user of a CP entry. + unsigned CPI = I->getOperand(op).getIndex(); + MachineInstr *CPEMI = CPEMIs[CPI]; + unsigned MaxOffs = ((1 << Bits)-1) * Scale; + CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, IsSoImm)); + + // Increment corresponding CPEntry reference count. + CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); + assert(CPE && "Cannot find a corresponding CPEntry!"); + CPE->RefCount++; + + // Instructions can only use one CP entry, don't bother scanning the + // rest of the operands. + break; + } + } + + // In thumb mode, if this block is a constpool island, we may need padding + // so it's aligned on 4 byte boundary. + if (isThumb && + !MBB.empty() && + MBB.begin()->getOpcode() == ARM::CONSTPOOL_ENTRY && + ((Offset%4) != 0 || HasInlineAsm)) + MBBSize += 2; + + BBSizes.push_back(MBBSize); + BBOffsets.push_back(Offset); + Offset += MBBSize; + } +} + +/// GetOffsetOf - Return the current offset of the specified machine instruction +/// from the start of the function. This offset changes as stuff is moved +/// around inside the function. +unsigned ARMConstantIslands::GetOffsetOf(MachineInstr *MI) const { + MachineBasicBlock *MBB = MI->getParent(); + + // The offset is composed of two things: the sum of the sizes of all MBB's + // before this instruction's block, and the offset from the start of the block + // it is in. + unsigned Offset = BBOffsets[MBB->getNumber()]; + + // If we're looking for a CONSTPOOL_ENTRY in Thumb, see if this block has + // alignment padding, and compensate if so. + if (isThumb && + MI->getOpcode() == ARM::CONSTPOOL_ENTRY && + (Offset%4 != 0 || HasInlineAsm)) + Offset += 2; + + // Sum instructions before MI in MBB. + for (MachineBasicBlock::iterator I = MBB->begin(); ; ++I) { + assert(I != MBB->end() && "Didn't find MI in its own basic block?"); + if (&*I == MI) return Offset; + Offset += TII->GetInstSizeInBytes(I); + } +} + +/// CompareMBBNumbers - Little predicate function to sort the WaterList by MBB +/// ID. +static bool CompareMBBNumbers(const MachineBasicBlock *LHS, + const MachineBasicBlock *RHS) { + return LHS->getNumber() < RHS->getNumber(); +} + +/// UpdateForInsertedWaterBlock - When a block is newly inserted into the +/// machine function, it upsets all of the block numbers. Renumber the blocks +/// and update the arrays that parallel this numbering. +void ARMConstantIslands::UpdateForInsertedWaterBlock(MachineBasicBlock *NewBB) { + // Renumber the MBB's to keep them consecutive. + NewBB->getParent()->RenumberBlocks(NewBB); + + // Insert a size into BBSizes to align it properly with the (newly + // renumbered) block numbers. + BBSizes.insert(BBSizes.begin()+NewBB->getNumber(), 0); + + // Likewise for BBOffsets. + BBOffsets.insert(BBOffsets.begin()+NewBB->getNumber(), 0); + + // Next, update WaterList. Specifically, we need to add NewMBB as having + // available water after it. + water_iterator IP = + std::lower_bound(WaterList.begin(), WaterList.end(), NewBB, + CompareMBBNumbers); + WaterList.insert(IP, NewBB); +} + + +/// Split the basic block containing MI into two blocks, which are joined by +/// an unconditional branch. Update data structures and renumber blocks to +/// account for this change and returns the newly created block. +MachineBasicBlock *ARMConstantIslands::SplitBlockBeforeInstr(MachineInstr *MI) { + MachineBasicBlock *OrigBB = MI->getParent(); + MachineFunction &MF = *OrigBB->getParent(); + + // Create a new MBB for the code after the OrigBB. + MachineBasicBlock *NewBB = + MF.CreateMachineBasicBlock(OrigBB->getBasicBlock()); + MachineFunction::iterator MBBI = OrigBB; ++MBBI; + MF.insert(MBBI, NewBB); + + // Splice the instructions starting with MI over to NewBB. + NewBB->splice(NewBB->end(), OrigBB, MI, OrigBB->end()); + + // Add an unconditional branch from OrigBB to NewBB. + // Note the new unconditional branch is not being recorded. + // There doesn't seem to be meaningful DebugInfo available; this doesn't + // correspond to anything in the source. + unsigned Opc = isThumb ? (isThumb2 ? ARM::t2B : ARM::tB) : ARM::B; + BuildMI(OrigBB, DebugLoc(), TII->get(Opc)).addMBB(NewBB); + ++NumSplit; + + // Update the CFG. All succs of OrigBB are now succs of NewBB. + while (!OrigBB->succ_empty()) { + MachineBasicBlock *Succ = *OrigBB->succ_begin(); + OrigBB->removeSuccessor(Succ); + NewBB->addSuccessor(Succ); + + // This pass should be run after register allocation, so there should be no + // PHI nodes to update. + assert((Succ->empty() || !Succ->begin()->isPHI()) + && "PHI nodes should be eliminated by now!"); + } + + // OrigBB branches to NewBB. + OrigBB->addSuccessor(NewBB); + + // Update internal data structures to account for the newly inserted MBB. + // This is almost the same as UpdateForInsertedWaterBlock, except that + // the Water goes after OrigBB, not NewBB. + MF.RenumberBlocks(NewBB); + + // Insert a size into BBSizes to align it properly with the (newly + // renumbered) block numbers. + BBSizes.insert(BBSizes.begin()+NewBB->getNumber(), 0); + + // Likewise for BBOffsets. + BBOffsets.insert(BBOffsets.begin()+NewBB->getNumber(), 0); + + // Next, update WaterList. Specifically, we need to add OrigMBB as having + // available water after it (but not if it's already there, which happens + // when splitting before a conditional branch that is followed by an + // unconditional branch - in that case we want to insert NewBB). + water_iterator IP = + std::lower_bound(WaterList.begin(), WaterList.end(), OrigBB, + CompareMBBNumbers); + MachineBasicBlock* WaterBB = *IP; + if (WaterBB == OrigBB) + WaterList.insert(llvm::next(IP), NewBB); + else + WaterList.insert(IP, OrigBB); + NewWaterList.insert(OrigBB); + + unsigned OrigBBI = OrigBB->getNumber(); + unsigned NewBBI = NewBB->getNumber(); + + int delta = isThumb1 ? 2 : 4; + + // Figure out how large the OrigBB is. As the first half of the original + // block, it cannot contain a tablejump. The size includes + // the new jump we added. (It should be possible to do this without + // recounting everything, but it's very confusing, and this is rarely + // executed.) + unsigned OrigBBSize = 0; + for (MachineBasicBlock::iterator I = OrigBB->begin(), E = OrigBB->end(); + I != E; ++I) + OrigBBSize += TII->GetInstSizeInBytes(I); + BBSizes[OrigBBI] = OrigBBSize; + + // ...and adjust BBOffsets for NewBB accordingly. + BBOffsets[NewBBI] = BBOffsets[OrigBBI] + BBSizes[OrigBBI]; + + // Figure out how large the NewMBB is. As the second half of the original + // block, it may contain a tablejump. + unsigned NewBBSize = 0; + for (MachineBasicBlock::iterator I = NewBB->begin(), E = NewBB->end(); + I != E; ++I) + NewBBSize += TII->GetInstSizeInBytes(I); + // Set the size of NewBB in BBSizes. It does not include any padding now. + BBSizes[NewBBI] = NewBBSize; + + MachineInstr* ThumbJTMI = prior(NewBB->end()); + if (ThumbJTMI->getOpcode() == ARM::tBR_JTr) { + // We've added another 2-byte instruction before this tablejump, which + // means we will always need padding if we didn't before, and vice versa. + + // The original offset of the jump instruction was: + unsigned OrigOffset = BBOffsets[OrigBBI] + BBSizes[OrigBBI] - delta; + if (OrigOffset%4 == 0) { + // We had padding before and now we don't. No net change in code size. + delta = 0; + } else { + // We didn't have padding before and now we do. + BBSizes[NewBBI] += 2; + delta = 4; + } + } + + // All BBOffsets following these blocks must be modified. + if (delta) + AdjustBBOffsetsAfter(NewBB, delta); + + return NewBB; +} + +/// OffsetIsInRange - Checks whether UserOffset (the location of a constant pool +/// reference) is within MaxDisp of TrialOffset (a proposed location of a +/// constant pool entry). +bool ARMConstantIslands::OffsetIsInRange(unsigned UserOffset, + unsigned TrialOffset, unsigned MaxDisp, + bool NegativeOK, bool IsSoImm) { + // On Thumb offsets==2 mod 4 are rounded down by the hardware for + // purposes of the displacement computation; compensate for that here. + // Effectively, the valid range of displacements is 2 bytes smaller for such + // references. + unsigned TotalAdj = 0; + if (isThumb && UserOffset%4 !=0) { + UserOffset -= 2; + TotalAdj = 2; + } + // CPEs will be rounded up to a multiple of 4. + if (isThumb && TrialOffset%4 != 0) { + TrialOffset += 2; + TotalAdj += 2; + } + + // In Thumb2 mode, later branch adjustments can shift instructions up and + // cause alignment change. In the worst case scenario this can cause the + // user's effective address to be subtracted by 2 and the CPE's address to + // be plus 2. + if (isThumb2 && TotalAdj != 4) + MaxDisp -= (4 - TotalAdj); + + if (UserOffset <= TrialOffset) { + // User before the Trial. + if (TrialOffset - UserOffset <= MaxDisp) + return true; + // FIXME: Make use full range of soimm values. + } else if (NegativeOK) { + if (UserOffset - TrialOffset <= MaxDisp) + return true; + // FIXME: Make use full range of soimm values. + } + return false; +} + +/// WaterIsInRange - Returns true if a CPE placed after the specified +/// Water (a basic block) will be in range for the specific MI. + +bool ARMConstantIslands::WaterIsInRange(unsigned UserOffset, + MachineBasicBlock* Water, CPUser &U) { + unsigned MaxDisp = U.MaxDisp; + unsigned CPEOffset = BBOffsets[Water->getNumber()] + + BBSizes[Water->getNumber()]; + + // If the CPE is to be inserted before the instruction, that will raise + // the offset of the instruction. + if (CPEOffset < UserOffset) + UserOffset += U.CPEMI->getOperand(2).getImm(); + + return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, U.NegOk, U.IsSoImm); +} + +/// CPEIsInRange - Returns true if the distance between specific MI and +/// specific ConstPool entry instruction can fit in MI's displacement field. +bool ARMConstantIslands::CPEIsInRange(MachineInstr *MI, unsigned UserOffset, + MachineInstr *CPEMI, unsigned MaxDisp, + bool NegOk, bool DoDump) { + unsigned CPEOffset = GetOffsetOf(CPEMI); + assert((CPEOffset%4 == 0 || HasInlineAsm) && "Misaligned CPE"); + + if (DoDump) { + DEBUG(errs() << "User of CPE#" << CPEMI->getOperand(0).getImm() + << " max delta=" << MaxDisp + << " insn address=" << UserOffset + << " CPE address=" << CPEOffset + << " offset=" << int(CPEOffset-UserOffset) << "\t" << *MI); + } + + return OffsetIsInRange(UserOffset, CPEOffset, MaxDisp, NegOk); +} + +#ifndef NDEBUG +/// BBIsJumpedOver - Return true of the specified basic block's only predecessor +/// unconditionally branches to its only successor. +static bool BBIsJumpedOver(MachineBasicBlock *MBB) { + if (MBB->pred_size() != 1 || MBB->succ_size() != 1) + return false; + + MachineBasicBlock *Succ = *MBB->succ_begin(); + MachineBasicBlock *Pred = *MBB->pred_begin(); + MachineInstr *PredMI = &Pred->back(); + if (PredMI->getOpcode() == ARM::B || PredMI->getOpcode() == ARM::tB + || PredMI->getOpcode() == ARM::t2B) + return PredMI->getOperand(0).getMBB() == Succ; + return false; +} +#endif // NDEBUG + +void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB, + int delta) { + MachineFunction::iterator MBBI = BB; MBBI = llvm::next(MBBI); + for(unsigned i = BB->getNumber()+1, e = BB->getParent()->getNumBlockIDs(); + i < e; ++i) { + BBOffsets[i] += delta; + // If some existing blocks have padding, adjust the padding as needed, a + // bit tricky. delta can be negative so don't use % on that. + if (!isThumb) + continue; + MachineBasicBlock *MBB = MBBI; + if (!MBB->empty() && !HasInlineAsm) { + // Constant pool entries require padding. + if (MBB->begin()->getOpcode() == ARM::CONSTPOOL_ENTRY) { + unsigned OldOffset = BBOffsets[i] - delta; + if ((OldOffset%4) == 0 && (BBOffsets[i]%4) != 0) { + // add new padding + BBSizes[i] += 2; + delta += 2; + } else if ((OldOffset%4) != 0 && (BBOffsets[i]%4) == 0) { + // remove existing padding + BBSizes[i] -= 2; + delta -= 2; + } + } + // Thumb1 jump tables require padding. They should be at the end; + // following unconditional branches are removed by AnalyzeBranch. + // tBR_JTr expands to a mov pc followed by .align 2 and then the jump + // table entries. So this code checks whether offset of tBR_JTr + // is aligned; if it is, the offset of the jump table following the + // instruction will not be aligned, and we need padding. + MachineInstr *ThumbJTMI = prior(MBB->end()); + if (ThumbJTMI->getOpcode() == ARM::tBR_JTr) { + unsigned NewMIOffset = GetOffsetOf(ThumbJTMI); + unsigned OldMIOffset = NewMIOffset - delta; + if ((OldMIOffset%4) == 0 && (NewMIOffset%4) != 0) { + // remove existing padding + BBSizes[i] -= 2; + delta -= 2; + } else if ((OldMIOffset%4) != 0 && (NewMIOffset%4) == 0) { + // add new padding + BBSizes[i] += 2; + delta += 2; + } + } + if (delta==0) + return; + } + MBBI = llvm::next(MBBI); + } +} + +/// DecrementOldEntry - find the constant pool entry with index CPI +/// and instruction CPEMI, and decrement its refcount. If the refcount +/// becomes 0 remove the entry and instruction. Returns true if we removed +/// the entry, false if we didn't. + +bool ARMConstantIslands::DecrementOldEntry(unsigned CPI, MachineInstr *CPEMI) { + // Find the old entry. Eliminate it if it is no longer used. + CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); + assert(CPE && "Unexpected!"); + if (--CPE->RefCount == 0) { + RemoveDeadCPEMI(CPEMI); + CPE->CPEMI = NULL; + --NumCPEs; + return true; + } + return false; +} + +/// LookForCPEntryInRange - see if the currently referenced CPE is in range; +/// if not, see if an in-range clone of the CPE is in range, and if so, +/// change the data structures so the user references the clone. Returns: +/// 0 = no existing entry found +/// 1 = entry found, and there were no code insertions or deletions +/// 2 = entry found, and there were code insertions or deletions +int ARMConstantIslands::LookForExistingCPEntry(CPUser& U, unsigned UserOffset) +{ + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + + // Check to see if the CPE is already in-range. + if (CPEIsInRange(UserMI, UserOffset, CPEMI, U.MaxDisp, U.NegOk, true)) { + DEBUG(errs() << "In range\n"); + return 1; + } + + // No. Look for previously created clones of the CPE that are in range. + unsigned CPI = CPEMI->getOperand(1).getIndex(); + std::vector &CPEs = CPEntries[CPI]; + for (unsigned i = 0, e = CPEs.size(); i != e; ++i) { + // We already tried this one + if (CPEs[i].CPEMI == CPEMI) + continue; + // Removing CPEs can leave empty entries, skip + if (CPEs[i].CPEMI == NULL) + continue; + if (CPEIsInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.MaxDisp, U.NegOk)) { + DEBUG(errs() << "Replacing CPE#" << CPI << " with CPE#" + << CPEs[i].CPI << "\n"); + // Point the CPUser node to the replacement + U.CPEMI = CPEs[i].CPEMI; + // Change the CPI in the instruction operand to refer to the clone. + for (unsigned j = 0, e = UserMI->getNumOperands(); j != e; ++j) + if (UserMI->getOperand(j).isCPI()) { + UserMI->getOperand(j).setIndex(CPEs[i].CPI); + break; + } + // Adjust the refcount of the clone... + CPEs[i].RefCount++; + // ...and the original. If we didn't remove the old entry, none of the + // addresses changed, so we don't need another pass. + return DecrementOldEntry(CPI, CPEMI) ? 2 : 1; + } + } + return 0; +} + +/// getUnconditionalBrDisp - Returns the maximum displacement that can fit in +/// the specific unconditional branch instruction. +static inline unsigned getUnconditionalBrDisp(int Opc) { + switch (Opc) { + case ARM::tB: + return ((1<<10)-1)*2; + case ARM::t2B: + return ((1<<23)-1)*2; + default: + break; + } + + return ((1<<23)-1)*4; +} + +/// LookForWater - Look for an existing entry in the WaterList in which +/// we can place the CPE referenced from U so it's within range of U's MI. +/// Returns true if found, false if not. If it returns true, WaterIter +/// is set to the WaterList entry. For Thumb, prefer water that will not +/// introduce padding to water that will. To ensure that this pass +/// terminates, the CPE location for a particular CPUser is only allowed to +/// move to a lower address, so search backward from the end of the list and +/// prefer the first water that is in range. +bool ARMConstantIslands::LookForWater(CPUser &U, unsigned UserOffset, + water_iterator &WaterIter) { + if (WaterList.empty()) + return false; + + bool FoundWaterThatWouldPad = false; + water_iterator IPThatWouldPad; + for (water_iterator IP = prior(WaterList.end()), + B = WaterList.begin();; --IP) { + MachineBasicBlock* WaterBB = *IP; + // Check if water is in range and is either at a lower address than the + // current "high water mark" or a new water block that was created since + // the previous iteration by inserting an unconditional branch. In the + // latter case, we want to allow resetting the high water mark back to + // this new water since we haven't seen it before. Inserting branches + // should be relatively uncommon and when it does happen, we want to be + // sure to take advantage of it for all the CPEs near that block, so that + // we don't insert more branches than necessary. + if (WaterIsInRange(UserOffset, WaterBB, U) && + (WaterBB->getNumber() < U.HighWaterMark->getNumber() || + NewWaterList.count(WaterBB))) { + unsigned WBBId = WaterBB->getNumber(); + if (isThumb && + (BBOffsets[WBBId] + BBSizes[WBBId])%4 != 0) { + // This is valid Water, but would introduce padding. Remember + // it in case we don't find any Water that doesn't do this. + if (!FoundWaterThatWouldPad) { + FoundWaterThatWouldPad = true; + IPThatWouldPad = IP; + } + } else { + WaterIter = IP; + return true; + } + } + if (IP == B) + break; + } + if (FoundWaterThatWouldPad) { + WaterIter = IPThatWouldPad; + return true; + } + return false; +} + +/// CreateNewWater - No existing WaterList entry will work for +/// CPUsers[CPUserIndex], so create a place to put the CPE. The end of the +/// block is used if in range, and the conditional branch munged so control +/// flow is correct. Otherwise the block is split to create a hole with an +/// unconditional branch around it. In either case NewMBB is set to a +/// block following which the new island can be inserted (the WaterList +/// is not adjusted). +void ARMConstantIslands::CreateNewWater(unsigned CPUserIndex, + unsigned UserOffset, + MachineBasicBlock *&NewMBB) { + CPUser &U = CPUsers[CPUserIndex]; + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + MachineBasicBlock *UserMBB = UserMI->getParent(); + unsigned OffsetOfNextBlock = BBOffsets[UserMBB->getNumber()] + + BBSizes[UserMBB->getNumber()]; + assert(OffsetOfNextBlock== BBOffsets[UserMBB->getNumber()+1]); + + // If the block does not end in an unconditional branch already, and if the + // end of the block is within range, make new water there. (The addition + // below is for the unconditional branch we will be adding: 4 bytes on ARM + + // Thumb2, 2 on Thumb1. Possible Thumb1 alignment padding is allowed for + // inside OffsetIsInRange. + if (BBHasFallthrough(UserMBB) && + OffsetIsInRange(UserOffset, OffsetOfNextBlock + (isThumb1 ? 2: 4), + U.MaxDisp, U.NegOk, U.IsSoImm)) { + DEBUG(errs() << "Split at end of block\n"); + if (&UserMBB->back() == UserMI) + assert(BBHasFallthrough(UserMBB) && "Expected a fallthrough BB!"); + NewMBB = llvm::next(MachineFunction::iterator(UserMBB)); + // Add an unconditional branch from UserMBB to fallthrough block. + // Record it for branch lengthening; this new branch will not get out of + // range, but if the preceding conditional branch is out of range, the + // targets will be exchanged, and the altered branch may be out of + // range, so the machinery has to know about it. + int UncondBr = isThumb ? ((isThumb2) ? ARM::t2B : ARM::tB) : ARM::B; + BuildMI(UserMBB, DebugLoc(), TII->get(UncondBr)).addMBB(NewMBB); + unsigned MaxDisp = getUnconditionalBrDisp(UncondBr); + ImmBranches.push_back(ImmBranch(&UserMBB->back(), + MaxDisp, false, UncondBr)); + int delta = isThumb1 ? 2 : 4; + BBSizes[UserMBB->getNumber()] += delta; + AdjustBBOffsetsAfter(UserMBB, delta); + } else { + // What a big block. Find a place within the block to split it. + // This is a little tricky on Thumb1 since instructions are 2 bytes + // and constant pool entries are 4 bytes: if instruction I references + // island CPE, and instruction I+1 references CPE', it will + // not work well to put CPE as far forward as possible, since then + // CPE' cannot immediately follow it (that location is 2 bytes + // farther away from I+1 than CPE was from I) and we'd need to create + // a new island. So, we make a first guess, then walk through the + // instructions between the one currently being looked at and the + // possible insertion point, and make sure any other instructions + // that reference CPEs will be able to use the same island area; + // if not, we back up the insertion point. + + // The 4 in the following is for the unconditional branch we'll be + // inserting (allows for long branch on Thumb1). Alignment of the + // island is handled inside OffsetIsInRange. + unsigned BaseInsertOffset = UserOffset + U.MaxDisp -4; + // This could point off the end of the block if we've already got + // constant pool entries following this block; only the last one is + // in the water list. Back past any possible branches (allow for a + // conditional and a maximally long unconditional). + if (BaseInsertOffset >= BBOffsets[UserMBB->getNumber()+1]) + BaseInsertOffset = BBOffsets[UserMBB->getNumber()+1] - + (isThumb1 ? 6 : 8); + unsigned EndInsertOffset = BaseInsertOffset + + CPEMI->getOperand(2).getImm(); + MachineBasicBlock::iterator MI = UserMI; + ++MI; + unsigned CPUIndex = CPUserIndex+1; + unsigned NumCPUsers = CPUsers.size(); + MachineInstr *LastIT = 0; + for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI); + Offset < BaseInsertOffset; + Offset += TII->GetInstSizeInBytes(MI), + MI = llvm::next(MI)) { + if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { + CPUser &U = CPUsers[CPUIndex]; + if (!OffsetIsInRange(Offset, EndInsertOffset, + U.MaxDisp, U.NegOk, U.IsSoImm)) { + BaseInsertOffset -= (isThumb1 ? 2 : 4); + EndInsertOffset -= (isThumb1 ? 2 : 4); + } + // This is overly conservative, as we don't account for CPEMIs + // being reused within the block, but it doesn't matter much. + EndInsertOffset += CPUsers[CPUIndex].CPEMI->getOperand(2).getImm(); + CPUIndex++; + } + + // Remember the last IT instruction. + if (MI->getOpcode() == ARM::t2IT) + LastIT = MI; + } + + DEBUG(errs() << "Split in middle of big block\n"); + --MI; + + // Avoid splitting an IT block. + if (LastIT) { + unsigned PredReg = 0; + ARMCC::CondCodes CC = llvm::getITInstrPredicate(MI, PredReg); + if (CC != ARMCC::AL) + MI = LastIT; + } + NewMBB = SplitBlockBeforeInstr(MI); + } +} + +/// HandleConstantPoolUser - Analyze the specified user, checking to see if it +/// is out-of-range. If so, pick up the constant pool value and move it some +/// place in-range. Return true if we changed any addresses (thus must run +/// another pass of branch lengthening), false otherwise. +bool ARMConstantIslands::HandleConstantPoolUser(MachineFunction &MF, + unsigned CPUserIndex) { + CPUser &U = CPUsers[CPUserIndex]; + MachineInstr *UserMI = U.MI; + MachineInstr *CPEMI = U.CPEMI; + unsigned CPI = CPEMI->getOperand(1).getIndex(); + unsigned Size = CPEMI->getOperand(2).getImm(); + // Compute this only once, it's expensive. The 4 or 8 is the value the + // hardware keeps in the PC. + unsigned UserOffset = GetOffsetOf(UserMI) + (isThumb ? 4 : 8); + + // See if the current entry is within range, or there is a clone of it + // in range. + int result = LookForExistingCPEntry(U, UserOffset); + if (result==1) return false; + else if (result==2) return true; + + // No existing clone of this CPE is within range. + // We will be generating a new clone. Get a UID for it. + unsigned ID = AFI->createPICLabelUId(); + + // Look for water where we can place this CPE. + MachineBasicBlock *NewIsland = MF.CreateMachineBasicBlock(); + MachineBasicBlock *NewMBB; + water_iterator IP; + if (LookForWater(U, UserOffset, IP)) { + DEBUG(errs() << "found water in range\n"); + MachineBasicBlock *WaterBB = *IP; + + // If the original WaterList entry was "new water" on this iteration, + // propagate that to the new island. This is just keeping NewWaterList + // updated to match the WaterList, which will be updated below. + if (NewWaterList.count(WaterBB)) { + NewWaterList.erase(WaterBB); + NewWaterList.insert(NewIsland); + } + // The new CPE goes before the following block (NewMBB). + NewMBB = llvm::next(MachineFunction::iterator(WaterBB)); + + } else { + // No water found. + DEBUG(errs() << "No water found\n"); + CreateNewWater(CPUserIndex, UserOffset, NewMBB); + + // SplitBlockBeforeInstr adds to WaterList, which is important when it is + // called while handling branches so that the water will be seen on the + // next iteration for constant pools, but in this context, we don't want + // it. Check for this so it will be removed from the WaterList. + // Also remove any entry from NewWaterList. + MachineBasicBlock *WaterBB = prior(MachineFunction::iterator(NewMBB)); + IP = std::find(WaterList.begin(), WaterList.end(), WaterBB); + if (IP != WaterList.end()) + NewWaterList.erase(WaterBB); + + // We are adding new water. Update NewWaterList. + NewWaterList.insert(NewIsland); + } + + // Remove the original WaterList entry; we want subsequent insertions in + // this vicinity to go after the one we're about to insert. This + // considerably reduces the number of times we have to move the same CPE + // more than once and is also important to ensure the algorithm terminates. + if (IP != WaterList.end()) + WaterList.erase(IP); + + // Okay, we know we can put an island before NewMBB now, do it! + MF.insert(NewMBB, NewIsland); + + // Update internal data structures to account for the newly inserted MBB. + UpdateForInsertedWaterBlock(NewIsland); + + // Decrement the old entry, and remove it if refcount becomes 0. + DecrementOldEntry(CPI, CPEMI); + + // Now that we have an island to add the CPE to, clone the original CPE and + // add it to the island. + U.HighWaterMark = NewIsland; + U.CPEMI = BuildMI(NewIsland, DebugLoc(), TII->get(ARM::CONSTPOOL_ENTRY)) + .addImm(ID).addConstantPoolIndex(CPI).addImm(Size); + CPEntries[CPI].push_back(CPEntry(U.CPEMI, ID, 1)); + ++NumCPEs; + + BBOffsets[NewIsland->getNumber()] = BBOffsets[NewMBB->getNumber()]; + // Compensate for .align 2 in thumb mode. + if (isThumb && (BBOffsets[NewIsland->getNumber()]%4 != 0 || HasInlineAsm)) + Size += 2; + // Increase the size of the island block to account for the new entry. + BBSizes[NewIsland->getNumber()] += Size; + AdjustBBOffsetsAfter(NewIsland, Size); + + // Finally, change the CPI in the instruction operand to be ID. + for (unsigned i = 0, e = UserMI->getNumOperands(); i != e; ++i) + if (UserMI->getOperand(i).isCPI()) { + UserMI->getOperand(i).setIndex(ID); + break; + } + + DEBUG(errs() << " Moved CPE to #" << ID << " CPI=" << CPI + << '\t' << *UserMI); + + return true; +} + +/// RemoveDeadCPEMI - Remove a dead constant pool entry instruction. Update +/// sizes and offsets of impacted basic blocks. +void ARMConstantIslands::RemoveDeadCPEMI(MachineInstr *CPEMI) { + MachineBasicBlock *CPEBB = CPEMI->getParent(); + unsigned Size = CPEMI->getOperand(2).getImm(); + CPEMI->eraseFromParent(); + BBSizes[CPEBB->getNumber()] -= Size; + // All succeeding offsets have the current size value added in, fix this. + if (CPEBB->empty()) { + // In thumb1 mode, the size of island may be padded by two to compensate for + // the alignment requirement. Then it will now be 2 when the block is + // empty, so fix this. + // All succeeding offsets have the current size value added in, fix this. + if (BBSizes[CPEBB->getNumber()] != 0) { + Size += BBSizes[CPEBB->getNumber()]; + BBSizes[CPEBB->getNumber()] = 0; + } + } + AdjustBBOffsetsAfter(CPEBB, -Size); + // An island has only one predecessor BB and one successor BB. Check if + // this BB's predecessor jumps directly to this BB's successor. This + // shouldn't happen currently. + assert(!BBIsJumpedOver(CPEBB) && "How did this happen?"); + // FIXME: remove the empty blocks after all the work is done? +} + +/// RemoveUnusedCPEntries - Remove constant pool entries whose refcounts +/// are zero. +bool ARMConstantIslands::RemoveUnusedCPEntries() { + unsigned MadeChange = false; + for (unsigned i = 0, e = CPEntries.size(); i != e; ++i) { + std::vector &CPEs = CPEntries[i]; + for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) { + if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) { + RemoveDeadCPEMI(CPEs[j].CPEMI); + CPEs[j].CPEMI = NULL; + MadeChange = true; + } + } + } + return MadeChange; +} + +/// BBIsInRange - Returns true if the distance between specific MI and +/// specific BB can fit in MI's displacement field. +bool ARMConstantIslands::BBIsInRange(MachineInstr *MI,MachineBasicBlock *DestBB, + unsigned MaxDisp) { + unsigned PCAdj = isThumb ? 4 : 8; + unsigned BrOffset = GetOffsetOf(MI) + PCAdj; + unsigned DestOffset = BBOffsets[DestBB->getNumber()]; + + DEBUG(errs() << "Branch of destination BB#" << DestBB->getNumber() + << " from BB#" << MI->getParent()->getNumber() + << " max delta=" << MaxDisp + << " from " << GetOffsetOf(MI) << " to " << DestOffset + << " offset " << int(DestOffset-BrOffset) << "\t" << *MI); + + if (BrOffset <= DestOffset) { + // Branch before the Dest. + if (DestOffset-BrOffset <= MaxDisp) + return true; + } else { + if (BrOffset-DestOffset <= MaxDisp) + return true; + } + return false; +} + +/// FixUpImmediateBr - Fix up an immediate branch whose destination is too far +/// away to fit in its displacement field. +bool ARMConstantIslands::FixUpImmediateBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); + + // Check to see if the DestBB is already in-range. + if (BBIsInRange(MI, DestBB, Br.MaxDisp)) + return false; + + if (!Br.isCond) + return FixUpUnconditionalBr(MF, Br); + return FixUpConditionalBr(MF, Br); +} + +/// FixUpUnconditionalBr - Fix up an unconditional branch whose destination is +/// too far away to fit in its displacement field. If the LR register has been +/// spilled in the epilogue, then we can use BL to implement a far jump. +/// Otherwise, add an intermediate branch instruction to a branch. +bool +ARMConstantIslands::FixUpUnconditionalBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *MBB = MI->getParent(); + if (!isThumb1) + llvm_unreachable("FixUpUnconditionalBr is Thumb1 only!"); + + // Use BL to implement far jump. + Br.MaxDisp = (1 << 21) * 2; + MI->setDesc(TII->get(ARM::tBfar)); + BBSizes[MBB->getNumber()] += 2; + AdjustBBOffsetsAfter(MBB, 2); + HasFarJump = true; + ++NumUBrFixed; + + DEBUG(errs() << " Changed B to long jump " << *MI); + + return true; +} + +/// FixUpConditionalBr - Fix up a conditional branch whose destination is too +/// far away to fit in its displacement field. It is converted to an inverse +/// conditional branch + an unconditional branch to the destination. +bool +ARMConstantIslands::FixUpConditionalBr(MachineFunction &MF, ImmBranch &Br) { + MachineInstr *MI = Br.MI; + MachineBasicBlock *DestBB = MI->getOperand(0).getMBB(); + + // Add an unconditional branch to the destination and invert the branch + // condition to jump over it: + // blt L1 + // => + // bge L2 + // b L1 + // L2: + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(1).getImm(); + CC = ARMCC::getOppositeCondition(CC); + unsigned CCReg = MI->getOperand(2).getReg(); + + // If the branch is at the end of its MBB and that has a fall-through block, + // direct the updated conditional branch to the fall-through block. Otherwise, + // split the MBB before the next instruction. + MachineBasicBlock *MBB = MI->getParent(); + MachineInstr *BMI = &MBB->back(); + bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); + + ++NumCBrFixed; + if (BMI != MI) { + if (llvm::next(MachineBasicBlock::iterator(MI)) == prior(MBB->end()) && + BMI->getOpcode() == Br.UncondBr) { + // Last MI in the BB is an unconditional branch. Can we simply invert the + // condition and swap destinations: + // beq L1 + // b L2 + // => + // bne L2 + // b L1 + MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB(); + if (BBIsInRange(MI, NewDest, Br.MaxDisp)) { + DEBUG(errs() << " Invert Bcc condition and swap its destination with " + << *BMI); + BMI->getOperand(0).setMBB(DestBB); + MI->getOperand(0).setMBB(NewDest); + MI->getOperand(1).setImm(CC); + return true; + } + } + } + + if (NeedSplit) { + SplitBlockBeforeInstr(MI); + // No need for the branch to the next block. We're adding an unconditional + // branch to the destination. + int delta = TII->GetInstSizeInBytes(&MBB->back()); + BBSizes[MBB->getNumber()] -= delta; + MachineBasicBlock* SplitBB = llvm::next(MachineFunction::iterator(MBB)); + AdjustBBOffsetsAfter(SplitBB, -delta); + MBB->back().eraseFromParent(); + // BBOffsets[SplitBB] is wrong temporarily, fixed below + } + MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(MBB)); + + DEBUG(errs() << " Insert B to BB#" << DestBB->getNumber() + << " also invert condition and change dest. to BB#" + << NextBB->getNumber() << "\n"); + + // Insert a new conditional branch and a new unconditional branch. + // Also update the ImmBranch as well as adding a new entry for the new branch. + BuildMI(MBB, DebugLoc(), TII->get(MI->getOpcode())) + .addMBB(NextBB).addImm(CC).addReg(CCReg); + Br.MI = &MBB->back(); + BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); + BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); + BBSizes[MBB->getNumber()] += TII->GetInstSizeInBytes(&MBB->back()); + unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); + ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); + + // Remove the old conditional branch. It may or may not still be in MBB. + BBSizes[MI->getParent()->getNumber()] -= TII->GetInstSizeInBytes(MI); + MI->eraseFromParent(); + + // The net size change is an addition of one unconditional branch. + int delta = TII->GetInstSizeInBytes(&MBB->back()); + AdjustBBOffsetsAfter(MBB, delta); + return true; +} + +/// UndoLRSpillRestore - Remove Thumb push / pop instructions that only spills +/// LR / restores LR to pc. FIXME: This is done here because it's only possible +/// to do this if tBfar is not used. +bool ARMConstantIslands::UndoLRSpillRestore() { + bool MadeChange = false; + for (unsigned i = 0, e = PushPopMIs.size(); i != e; ++i) { + MachineInstr *MI = PushPopMIs[i]; + // First two operands are predicates. + if (MI->getOpcode() == ARM::tPOP_RET && + MI->getOperand(2).getReg() == ARM::PC && + MI->getNumExplicitOperands() == 3) { + BuildMI(MI->getParent(), MI->getDebugLoc(), TII->get(ARM::tBX_RET)); + MI->eraseFromParent(); + MadeChange = true; + } + } + return MadeChange; +} + +bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) { + bool MadeChange = false; + + // Shrink ADR and LDR from constantpool. + for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) { + CPUser &U = CPUsers[i]; + unsigned Opcode = U.MI->getOpcode(); + unsigned NewOpc = 0; + unsigned Scale = 1; + unsigned Bits = 0; + switch (Opcode) { + default: break; + case ARM::t2LEApcrel: + if (isARMLowRegister(U.MI->getOperand(0).getReg())) { + NewOpc = ARM::tLEApcrel; + Bits = 8; + Scale = 4; + } + break; + case ARM::t2LDRpci: + if (isARMLowRegister(U.MI->getOperand(0).getReg())) { + NewOpc = ARM::tLDRpci; + Bits = 8; + Scale = 4; + } + break; + } + + if (!NewOpc) + continue; + + unsigned UserOffset = GetOffsetOf(U.MI) + 4; + unsigned MaxOffs = ((1 << Bits) - 1) * Scale; + // FIXME: Check if offset is multiple of scale if scale is not 4. + if (CPEIsInRange(U.MI, UserOffset, U.CPEMI, MaxOffs, false, true)) { + U.MI->setDesc(TII->get(NewOpc)); + MachineBasicBlock *MBB = U.MI->getParent(); + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumT2CPShrunk; + MadeChange = true; + } + } + + MadeChange |= OptimizeThumb2Branches(MF); + MadeChange |= OptimizeThumb2JumpTables(MF); + return MadeChange; +} + +bool ARMConstantIslands::OptimizeThumb2Branches(MachineFunction &MF) { + bool MadeChange = false; + + for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) { + ImmBranch &Br = ImmBranches[i]; + unsigned Opcode = Br.MI->getOpcode(); + unsigned NewOpc = 0; + unsigned Scale = 1; + unsigned Bits = 0; + switch (Opcode) { + default: break; + case ARM::t2B: + NewOpc = ARM::tB; + Bits = 11; + Scale = 2; + break; + case ARM::t2Bcc: { + NewOpc = ARM::tBcc; + Bits = 8; + Scale = 2; + break; + } + } + if (NewOpc) { + unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; + MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); + if (BBIsInRange(Br.MI, DestBB, MaxOffs)) { + Br.MI->setDesc(TII->get(NewOpc)); + MachineBasicBlock *MBB = Br.MI->getParent(); + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumT2BrShrunk; + MadeChange = true; + } + } + + Opcode = Br.MI->getOpcode(); + if (Opcode != ARM::tBcc) + continue; + + NewOpc = 0; + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(Br.MI, PredReg); + if (Pred == ARMCC::EQ) + NewOpc = ARM::tCBZ; + else if (Pred == ARMCC::NE) + NewOpc = ARM::tCBNZ; + if (!NewOpc) + continue; + MachineBasicBlock *DestBB = Br.MI->getOperand(0).getMBB(); + // Check if the distance is within 126. Subtract starting offset by 2 + // because the cmp will be eliminated. + unsigned BrOffset = GetOffsetOf(Br.MI) + 4 - 2; + unsigned DestOffset = BBOffsets[DestBB->getNumber()]; + if (BrOffset < DestOffset && (DestOffset - BrOffset) <= 126) { + MachineBasicBlock::iterator CmpMI = Br.MI; --CmpMI; + if (CmpMI->getOpcode() == ARM::tCMPi8) { + unsigned Reg = CmpMI->getOperand(0).getReg(); + Pred = llvm::getInstrPredicate(CmpMI, PredReg); + if (Pred == ARMCC::AL && + CmpMI->getOperand(1).getImm() == 0 && + isARMLowRegister(Reg)) { + MachineBasicBlock *MBB = Br.MI->getParent(); + MachineInstr *NewBR = + BuildMI(*MBB, CmpMI, Br.MI->getDebugLoc(), TII->get(NewOpc)) + .addReg(Reg).addMBB(DestBB, Br.MI->getOperand(0).getTargetFlags()); + CmpMI->eraseFromParent(); + Br.MI->eraseFromParent(); + Br.MI = NewBR; + BBSizes[MBB->getNumber()] -= 2; + AdjustBBOffsetsAfter(MBB, -2); + ++NumCBZ; + MadeChange = true; + } + } + } + } + + return MadeChange; +} + +/// OptimizeThumb2JumpTables - Use tbb / tbh instructions to generate smaller +/// jumptables when it's possible. +bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) { + bool MadeChange = false; + + // FIXME: After the tables are shrunk, can we get rid some of the + // constantpool tables? + MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + if (MJTI == 0) return false; + + const std::vector &JT = MJTI->getJumpTables(); + for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { + MachineInstr *MI = T2JumpTables[i]; + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + MachineOperand JTOP = MI->getOperand(JTOpIdx); + unsigned JTI = JTOP.getIndex(); + assert(JTI < JT.size()); + + bool ByteOk = true; + bool HalfWordOk = true; + unsigned JTOffset = GetOffsetOf(MI) + 4; + const std::vector &JTBBs = JT[JTI].MBBs; + for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) { + MachineBasicBlock *MBB = JTBBs[j]; + unsigned DstOffset = BBOffsets[MBB->getNumber()]; + // Negative offset is not ok. FIXME: We should change BB layout to make + // sure all the branches are forward. + if (ByteOk && (DstOffset - JTOffset) > ((1<<8)-1)*2) + ByteOk = false; + unsigned TBHLimit = ((1<<16)-1)*2; + if (HalfWordOk && (DstOffset - JTOffset) > TBHLimit) + HalfWordOk = false; + if (!ByteOk && !HalfWordOk) + break; + } + + if (ByteOk || HalfWordOk) { + MachineBasicBlock *MBB = MI->getParent(); + unsigned BaseReg = MI->getOperand(0).getReg(); + bool BaseRegKill = MI->getOperand(0).isKill(); + if (!BaseRegKill) + continue; + unsigned IdxReg = MI->getOperand(1).getReg(); + bool IdxRegKill = MI->getOperand(1).isKill(); + + // Scan backwards to find the instruction that defines the base + // register. Due to post-RA scheduling, we can't count on it + // immediately preceding the branch instruction. + MachineBasicBlock::iterator PrevI = MI; + MachineBasicBlock::iterator B = MBB->begin(); + while (PrevI != B && !PrevI->definesRegister(BaseReg)) + --PrevI; + + // If for some reason we didn't find it, we can't do anything, so + // just skip this one. + if (!PrevI->definesRegister(BaseReg)) + continue; + + MachineInstr *AddrMI = PrevI; + bool OptOk = true; + // Examine the instruction that calculates the jumptable entry address. + // Make sure it only defines the base register and kills any uses + // other than the index register. + for (unsigned k = 0, eee = AddrMI->getNumOperands(); k != eee; ++k) { + const MachineOperand &MO = AddrMI->getOperand(k); + if (!MO.isReg() || !MO.getReg()) + continue; + if (MO.isDef() && MO.getReg() != BaseReg) { + OptOk = false; + break; + } + if (MO.isUse() && !MO.isKill() && MO.getReg() != IdxReg) { + OptOk = false; + break; + } + } + if (!OptOk) + continue; + + // Now scan back again to find the tLEApcrel or t2LEApcrelJT instruction + // that gave us the initial base register definition. + for (--PrevI; PrevI != B && !PrevI->definesRegister(BaseReg); --PrevI) + ; + + // The instruction should be a tLEApcrel or t2LEApcrelJT; we want + // to delete it as well. + MachineInstr *LeaMI = PrevI; + if ((LeaMI->getOpcode() != ARM::tLEApcrelJT && + LeaMI->getOpcode() != ARM::t2LEApcrelJT) || + LeaMI->getOperand(0).getReg() != BaseReg) + OptOk = false; + + if (!OptOk) + continue; + + unsigned Opc = ByteOk ? ARM::t2TBB_JT : ARM::t2TBH_JT; + MachineInstr *NewJTMI = BuildMI(MBB, MI->getDebugLoc(), TII->get(Opc)) + .addReg(IdxReg, getKillRegState(IdxRegKill)) + .addJumpTableIndex(JTI, JTOP.getTargetFlags()) + .addImm(MI->getOperand(JTOpIdx+1).getImm()); + // FIXME: Insert an "ALIGN" instruction to ensure the next instruction + // is 2-byte aligned. For now, asm printer will fix it up. + unsigned NewSize = TII->GetInstSizeInBytes(NewJTMI); + unsigned OrigSize = TII->GetInstSizeInBytes(AddrMI); + OrigSize += TII->GetInstSizeInBytes(LeaMI); + OrigSize += TII->GetInstSizeInBytes(MI); + + AddrMI->eraseFromParent(); + LeaMI->eraseFromParent(); + MI->eraseFromParent(); + + int delta = OrigSize - NewSize; + BBSizes[MBB->getNumber()] -= delta; + AdjustBBOffsetsAfter(MBB, -delta); + + ++NumTBs; + MadeChange = true; + } + } + + return MadeChange; +} + +/// ReorderThumb2JumpTables - Adjust the function's block layout to ensure that +/// jump tables always branch forwards, since that's what tbb and tbh need. +bool ARMConstantIslands::ReorderThumb2JumpTables(MachineFunction &MF) { + bool MadeChange = false; + + MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + if (MJTI == 0) return false; + + const std::vector &JT = MJTI->getJumpTables(); + for (unsigned i = 0, e = T2JumpTables.size(); i != e; ++i) { + MachineInstr *MI = T2JumpTables[i]; + const TargetInstrDesc &TID = MI->getDesc(); + unsigned NumOps = TID.getNumOperands(); + unsigned JTOpIdx = NumOps - (TID.isPredicable() ? 3 : 2); + MachineOperand JTOP = MI->getOperand(JTOpIdx); + unsigned JTI = JTOP.getIndex(); + assert(JTI < JT.size()); + + // We prefer if target blocks for the jump table come after the jump + // instruction so we can use TB[BH]. Loop through the target blocks + // and try to adjust them such that that's true. + int JTNumber = MI->getParent()->getNumber(); + const std::vector &JTBBs = JT[JTI].MBBs; + for (unsigned j = 0, ee = JTBBs.size(); j != ee; ++j) { + MachineBasicBlock *MBB = JTBBs[j]; + int DTNumber = MBB->getNumber(); + + if (DTNumber < JTNumber) { + // The destination precedes the switch. Try to move the block forward + // so we have a positive offset. + MachineBasicBlock *NewBB = + AdjustJTTargetBlockForward(MBB, MI->getParent()); + if (NewBB) + MJTI->ReplaceMBBInJumpTable(JTI, JTBBs[j], NewBB); + MadeChange = true; + } + } + } + + return MadeChange; +} + +MachineBasicBlock *ARMConstantIslands:: +AdjustJTTargetBlockForward(MachineBasicBlock *BB, MachineBasicBlock *JTBB) +{ + MachineFunction &MF = *BB->getParent(); + + // If the destination block is terminated by an unconditional branch, + // try to move it; otherwise, create a new block following the jump + // table that branches back to the actual target. This is a very simple + // heuristic. FIXME: We can definitely improve it. + MachineBasicBlock *TBB = 0, *FBB = 0; + SmallVector Cond; + SmallVector CondPrior; + MachineFunction::iterator BBi = BB; + MachineFunction::iterator OldPrior = prior(BBi); + + // If the block terminator isn't analyzable, don't try to move the block + bool B = TII->AnalyzeBranch(*BB, TBB, FBB, Cond); + + // If the block ends in an unconditional branch, move it. The prior block + // has to have an analyzable terminator for us to move this one. Be paranoid + // and make sure we're not trying to move the entry block of the function. + if (!B && Cond.empty() && BB != MF.begin() && + !TII->AnalyzeBranch(*OldPrior, TBB, FBB, CondPrior)) { + BB->moveAfter(JTBB); + OldPrior->updateTerminator(); + BB->updateTerminator(); + // Update numbering to account for the block being moved. + MF.RenumberBlocks(); + ++NumJTMoved; + return NULL; + } + + // Create a new MBB for the code after the jump BB. + MachineBasicBlock *NewBB = + MF.CreateMachineBasicBlock(JTBB->getBasicBlock()); + MachineFunction::iterator MBBI = JTBB; ++MBBI; + MF.insert(MBBI, NewBB); + + // Add an unconditional branch from NewBB to BB. + // There doesn't seem to be meaningful DebugInfo available; this doesn't + // correspond directly to anything in the source. + assert (isThumb2 && "Adjusting for TB[BH] but not in Thumb2?"); + BuildMI(NewBB, DebugLoc(), TII->get(ARM::t2B)).addMBB(BB); + + // Update internal data structures to account for the newly inserted MBB. + MF.RenumberBlocks(NewBB); + + // Update the CFG. + NewBB->addSuccessor(BB); + JTBB->removeSuccessor(BB); + JTBB->addSuccessor(NewBB); + + ++NumJTInserted; + return NewBB; +} diff --git a/final/lib/Target/ARM/ARMConstantPoolValue.cpp b/final/lib/Target/ARM/ARMConstantPoolValue.cpp new file mode 100644 index 00000000000..165a1d849ad --- /dev/null +++ b/final/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -0,0 +1,130 @@ +//===- ARMConstantPoolValue.cpp - ARM constantpool value --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ARM specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#include "ARMConstantPoolValue.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Constant.h" +#include "llvm/Constants.h" +#include "llvm/GlobalValue.h" +#include "llvm/Type.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +ARMConstantPoolValue::ARMConstantPoolValue(const Constant *cval, unsigned id, + ARMCP::ARMCPKind K, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modif, + bool AddCA) + : MachineConstantPoolValue((const Type*)cval->getType()), + CVal(cval), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, + const char *s, unsigned id, + unsigned char PCAdj, + ARMCP::ARMCPModifier Modif, + bool AddCA) + : MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)), + CVal(NULL), S(strdup(s)), LabelId(id), Kind(ARMCP::CPExtSymbol), + PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {} + +ARMConstantPoolValue::ARMConstantPoolValue(const GlobalValue *gv, + ARMCP::ARMCPModifier Modif) + : MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())), + CVal(gv), S(NULL), LabelId(0), Kind(ARMCP::CPValue), PCAdjust(0), + Modifier(Modif), AddCurrentAddress(false) {} + +const GlobalValue *ARMConstantPoolValue::getGV() const { + return dyn_cast_or_null(CVal); +} + +const BlockAddress *ARMConstantPoolValue::getBlockAddress() const { + return dyn_cast_or_null(CVal); +} + +static bool CPV_streq(const char *S1, const char *S2) { + if (S1 == S2) + return true; + if (S1 && S2 && strcmp(S1, S2) == 0) + return true; + return false; +} + +int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = Alignment - 1; + const std::vector Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].getAlignment() & AlignMask) == 0) { + ARMConstantPoolValue *CPV = + (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; + if (CPV->CVal == CVal && + CPV->LabelId == LabelId && + CPV->PCAdjust == PCAdjust && + CPV_streq(CPV->S, S) && + CPV->Modifier == Modifier) + return i; + } + } + + return -1; +} + +ARMConstantPoolValue::~ARMConstantPoolValue() { + free((void*)S); +} + +void +ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(CVal); + ID.AddPointer(S); + ID.AddInteger(LabelId); + ID.AddInteger(PCAdjust); +} + +bool +ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) { + if (ACPV->Kind == Kind && + ACPV->CVal == CVal && + ACPV->PCAdjust == PCAdjust && + CPV_streq(ACPV->S, S) && + ACPV->Modifier == Modifier) { + if (ACPV->LabelId == LabelId) + return true; + // Two PC relative constpool entries containing the same GV address or + // external symbols. FIXME: What about blockaddress? + if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol) + return true; + } + return false; +} + +void ARMConstantPoolValue::dump() const { + errs() << " " << *this; +} + + +void ARMConstantPoolValue::print(raw_ostream &O) const { + if (CVal) + O << CVal->getName(); + else + O << S; + if (Modifier) O << "(" << getModifierText() << ")"; + if (PCAdjust != 0) { + O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; + if (AddCurrentAddress) O << "-."; + O << ")"; + } +} diff --git a/final/lib/Target/ARM/ARMConstantPoolValue.h b/final/lib/Target/ARM/ARMConstantPoolValue.h new file mode 100644 index 00000000000..d008811c40e --- /dev/null +++ b/final/lib/Target/ARM/ARMConstantPoolValue.h @@ -0,0 +1,122 @@ +//===- ARMConstantPoolValue.h - ARM constantpool value ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ARM specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H +#define LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H + +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/Support/ErrorHandling.h" +#include + +namespace llvm { + +class Constant; +class BlockAddress; +class GlobalValue; +class LLVMContext; + +namespace ARMCP { + enum ARMCPKind { + CPValue, + CPExtSymbol, + CPBlockAddress, + CPLSDA + }; + + enum ARMCPModifier { + no_modifier, + TLSGD, + GOT, + GOTOFF, + GOTTPOFF, + TPOFF + }; +} + +/// ARMConstantPoolValue - ARM specific constantpool value. This is used to +/// represent PC-relative displacement between the address of the load +/// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)). +class ARMConstantPoolValue : public MachineConstantPoolValue { + const Constant *CVal; // Constant being loaded. + const char *S; // ExtSymbol being loaded. + unsigned LabelId; // Label id of the load. + ARMCP::ARMCPKind Kind; // Kind of constant. + unsigned char PCAdjust; // Extra adjustment if constantpool is pc-relative. + // 8 for ARM, 4 for Thumb. + ARMCP::ARMCPModifier Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) + bool AddCurrentAddress; + +public: + ARMConstantPoolValue(const Constant *cval, unsigned id, + ARMCP::ARMCPKind Kind = ARMCP::CPValue, + unsigned char PCAdj = 0, + ARMCP::ARMCPModifier Modifier = ARMCP::no_modifier, + bool AddCurrentAddress = false); + ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id, + unsigned char PCAdj = 0, + ARMCP::ARMCPModifier Modifier = ARMCP::no_modifier, + bool AddCurrentAddress = false); + ARMConstantPoolValue(const GlobalValue *GV, ARMCP::ARMCPModifier Modifier); + ARMConstantPoolValue(); + ~ARMConstantPoolValue(); + + const GlobalValue *getGV() const; + const char *getSymbol() const { return S; } + const BlockAddress *getBlockAddress() const; + ARMCP::ARMCPModifier getModifier() const { return Modifier; } + const char *getModifierText() const { + switch (Modifier) { + default: llvm_unreachable("Unknown modifier!"); + // FIXME: Are these case sensitive? It'd be nice to lower-case all the + // strings if that's legal. + case ARMCP::no_modifier: return "none"; + case ARMCP::TLSGD: return "tlsgd"; + case ARMCP::GOT: return "GOT"; + case ARMCP::GOTOFF: return "GOTOFF"; + case ARMCP::GOTTPOFF: return "gottpoff"; + case ARMCP::TPOFF: return "tpoff"; + } + } + bool hasModifier() const { return Modifier != ARMCP::no_modifier; } + bool mustAddCurrentAddress() const { return AddCurrentAddress; } + unsigned getLabelId() const { return LabelId; } + unsigned char getPCAdjustment() const { return PCAdjust; } + bool isGlobalValue() const { return Kind == ARMCP::CPValue; } + bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; } + bool isBlockAddress() { return Kind == ARMCP::CPBlockAddress; } + bool isLSDA() { return Kind == ARMCP::CPLSDA; } + + virtual unsigned getRelocationInfo() const { return 2; } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment); + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID); + + /// hasSameValue - Return true if this ARM constpool value + /// can share the same constantpool entry as another ARM constpool value. + bool hasSameValue(ARMConstantPoolValue *ACPV); + + void print(raw_ostream *O) const { if (O) print(*O); } + void print(raw_ostream &O) const; + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) { + V.print(O); + return O; +} + +} // End llvm namespace + +#endif diff --git a/final/lib/Target/ARM/ARMELFWriterInfo.cpp b/final/lib/Target/ARM/ARMELFWriterInfo.cpp new file mode 100644 index 00000000000..51e68b4553f --- /dev/null +++ b/final/lib/Target/ARM/ARMELFWriterInfo.cpp @@ -0,0 +1,83 @@ +//===-- ARMELFWriterInfo.cpp - ELF Writer Info for the ARM backend --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the ARM backend. +// +//===----------------------------------------------------------------------===// + +#include "ARMELFWriterInfo.h" +#include "ARMRelocations.h" +#include "llvm/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/ELF.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Implementation of the ARMELFWriterInfo class +//===----------------------------------------------------------------------===// + +ARMELFWriterInfo::ARMELFWriterInfo(TargetMachine &TM) + : TargetELFWriterInfo(TM.getTargetData()->getPointerSizeInBits() == 64, + TM.getTargetData()->isLittleEndian()) { +} + +ARMELFWriterInfo::~ARMELFWriterInfo() {} + +unsigned ARMELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { + switch (MachineRelTy) { + case ARM::reloc_arm_absolute: + case ARM::reloc_arm_relative: + case ARM::reloc_arm_cp_entry: + case ARM::reloc_arm_vfp_cp_entry: + case ARM::reloc_arm_machine_cp_entry: + case ARM::reloc_arm_jt_base: + case ARM::reloc_arm_pic_jt: + assert(0 && "unsupported ARM relocation type"); break; + + case ARM::reloc_arm_branch: return ELF::R_ARM_CALL; break; + case ARM::reloc_arm_movt: return ELF::R_ARM_MOVT_ABS; break; + case ARM::reloc_arm_movw: return ELF::R_ARM_MOVW_ABS_NC; break; + default: + llvm_unreachable("unknown ARM relocation type"); break; + } + return 0; +} + +long int ARMELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier) const { + assert(0 && "ARMELFWriterInfo::getDefaultAddendForRelTy() not implemented"); + return 0; +} + +unsigned ARMELFWriterInfo::getRelocationTySize(unsigned RelTy) const { + assert(0 && "ARMELFWriterInfo::getRelocationTySize() not implemented"); + return 0; +} + +bool ARMELFWriterInfo::isPCRelativeRel(unsigned RelTy) const { + assert(0 && "ARMELFWriterInfo::isPCRelativeRel() not implemented"); + return 1; +} + +unsigned ARMELFWriterInfo::getAbsoluteLabelMachineRelTy() const { + assert(0 && + "ARMELFWriterInfo::getAbsoluteLabelMachineRelTy() not implemented"); + return 0; +} + +long int ARMELFWriterInfo::computeRelocation(unsigned SymOffset, + unsigned RelOffset, + unsigned RelTy) const { + assert(0 && + "ARMELFWriterInfo::getAbsoluteLabelMachineRelTy() not implemented"); + return 0; +} diff --git a/final/lib/Target/ARM/ARMELFWriterInfo.h b/final/lib/Target/ARM/ARMELFWriterInfo.h new file mode 100644 index 00000000000..1c4e5329ac6 --- /dev/null +++ b/final/lib/Target/ARM/ARMELFWriterInfo.h @@ -0,0 +1,58 @@ +//===-- ARMELFWriterInfo.h - ELF Writer Info for ARM ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements ELF writer information for the ARM backend. +// +//===----------------------------------------------------------------------===// + +#ifndef ARM_ELF_WRITER_INFO_H +#define ARM_ELF_WRITER_INFO_H + +#include "llvm/Target/TargetELFWriterInfo.h" + +namespace llvm { + + class ARMELFWriterInfo : public TargetELFWriterInfo { + public: + ARMELFWriterInfo(TargetMachine &TM); + virtual ~ARMELFWriterInfo(); + + /// getRelocationType - Returns the target specific ELF Relocation type. + /// 'MachineRelTy' contains the object code independent relocation type + virtual unsigned getRelocationType(unsigned MachineRelTy) const; + + /// hasRelocationAddend - True if the target uses an addend in the + /// ELF relocation entry. + virtual bool hasRelocationAddend() const { return false; } + + /// getDefaultAddendForRelTy - Gets the default addend value for a + /// relocation entry based on the target ELF relocation type. + virtual long int getDefaultAddendForRelTy(unsigned RelTy, + long int Modifier = 0) const; + + /// getRelTySize - Returns the size of relocatable field in bits + virtual unsigned getRelocationTySize(unsigned RelTy) const; + + /// isPCRelativeRel - True if the relocation type is pc relative + virtual bool isPCRelativeRel(unsigned RelTy) const; + + /// getJumpTableRelocationTy - Returns the machine relocation type used + /// to reference a jumptable. + virtual unsigned getAbsoluteLabelMachineRelTy() const; + + /// computeRelocation - Some relocatable fields could be relocated + /// directly, avoiding the relocation symbol emission, compute the + /// final relocation value for this symbol. + virtual long int computeRelocation(unsigned SymOffset, unsigned RelOffset, + unsigned RelTy) const; + }; + +} // end llvm namespace + +#endif // ARM_ELF_WRITER_INFO_H diff --git a/final/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/final/lib/Target/ARM/ARMExpandPseudoInsts.cpp new file mode 100644 index 00000000000..de87ec359d9 --- /dev/null +++ b/final/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -0,0 +1,1241 @@ +//===-- ARMExpandPseudoInsts.cpp - Expand pseudo instructions -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that expands pseudo instructions into target +// instructions to allow proper scheduling, if-conversion, and other late +// optimizations. This pass should be run after register allocation but before +// the post-regalloc scheduling pass. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-pseudo" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMRegisterInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/raw_ostream.h" // FIXME: for debug only. remove! +using namespace llvm; + +namespace { + class ARMExpandPseudo : public MachineFunctionPass { + public: + static char ID; + ARMExpandPseudo() : MachineFunctionPass(ID) {} + + const ARMBaseInstrInfo *TII; + const TargetRegisterInfo *TRI; + const ARMSubtarget *STI; + ARMFunctionInfo *AFI; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "ARM pseudo instruction expansion pass"; + } + + private: + void TransferImpOps(MachineInstr &OldMI, + MachineInstrBuilder &UseMI, MachineInstrBuilder &DefMI); + bool ExpandMI(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI); + bool ExpandMBB(MachineBasicBlock &MBB); + void ExpandVLD(MachineBasicBlock::iterator &MBBI); + void ExpandVST(MachineBasicBlock::iterator &MBBI); + void ExpandLaneOp(MachineBasicBlock::iterator &MBBI); + void ExpandVTBL(MachineBasicBlock::iterator &MBBI, + unsigned Opc, bool IsExt, unsigned NumRegs); + void ExpandMOV32BitImm(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI); + }; + char ARMExpandPseudo::ID = 0; +} + +/// TransferImpOps - Transfer implicit operands on the pseudo instruction to +/// the instructions created from the expansion. +void ARMExpandPseudo::TransferImpOps(MachineInstr &OldMI, + MachineInstrBuilder &UseMI, + MachineInstrBuilder &DefMI) { + const TargetInstrDesc &Desc = OldMI.getDesc(); + for (unsigned i = Desc.getNumOperands(), e = OldMI.getNumOperands(); + i != e; ++i) { + const MachineOperand &MO = OldMI.getOperand(i); + assert(MO.isReg() && MO.getReg()); + if (MO.isUse()) + UseMI.addOperand(MO); + else + DefMI.addOperand(MO); + } +} + +namespace { + // Constants for register spacing in NEON load/store instructions. + // For quad-register load-lane and store-lane pseudo instructors, the + // spacing is initially assumed to be EvenDblSpc, and that is changed to + // OddDblSpc depending on the lane number operand. + enum NEONRegSpacing { + SingleSpc, + EvenDblSpc, + OddDblSpc + }; + + // Entries for NEON load/store information table. The table is sorted by + // PseudoOpc for fast binary-search lookups. + struct NEONLdStTableEntry { + unsigned PseudoOpc; + unsigned RealOpc; + bool IsLoad; + bool HasWriteBack; + NEONRegSpacing RegSpacing; + unsigned char NumRegs; // D registers loaded or stored + unsigned char RegElts; // elements per D register; used for lane ops + + // Comparison methods for binary search of the table. + bool operator<(const NEONLdStTableEntry &TE) const { + return PseudoOpc < TE.PseudoOpc; + } + friend bool operator<(const NEONLdStTableEntry &TE, unsigned PseudoOpc) { + return TE.PseudoOpc < PseudoOpc; + } + friend bool LLVM_ATTRIBUTE_UNUSED operator<(unsigned PseudoOpc, + const NEONLdStTableEntry &TE) { + return PseudoOpc < TE.PseudoOpc; + } + }; +} + +static const NEONLdStTableEntry NEONLdStTable[] = { +{ ARM::VLD1DUPq16Pseudo, ARM::VLD1DUPq16, true, false, SingleSpc, 2, 4}, +{ ARM::VLD1DUPq16Pseudo_UPD, ARM::VLD1DUPq16_UPD, true, true, SingleSpc, 2, 4}, +{ ARM::VLD1DUPq32Pseudo, ARM::VLD1DUPq32, true, false, SingleSpc, 2, 2}, +{ ARM::VLD1DUPq32Pseudo_UPD, ARM::VLD1DUPq32_UPD, true, true, SingleSpc, 2, 2}, +{ ARM::VLD1DUPq8Pseudo, ARM::VLD1DUPq8, true, false, SingleSpc, 2, 8}, +{ ARM::VLD1DUPq8Pseudo_UPD, ARM::VLD1DUPq8_UPD, true, true, SingleSpc, 2, 8}, + +{ ARM::VLD1LNq16Pseudo, ARM::VLD1LNd16, true, false, EvenDblSpc, 1, 4 }, +{ ARM::VLD1LNq16Pseudo_UPD, ARM::VLD1LNd16_UPD, true, true, EvenDblSpc, 1, 4 }, +{ ARM::VLD1LNq32Pseudo, ARM::VLD1LNd32, true, false, EvenDblSpc, 1, 2 }, +{ ARM::VLD1LNq32Pseudo_UPD, ARM::VLD1LNd32_UPD, true, true, EvenDblSpc, 1, 2 }, +{ ARM::VLD1LNq8Pseudo, ARM::VLD1LNd8, true, false, EvenDblSpc, 1, 8 }, +{ ARM::VLD1LNq8Pseudo_UPD, ARM::VLD1LNd8_UPD, true, true, EvenDblSpc, 1, 8 }, + +{ ARM::VLD1d64QPseudo, ARM::VLD1d64Q, true, false, SingleSpc, 4, 1 }, +{ ARM::VLD1d64QPseudo_UPD, ARM::VLD1d64Q_UPD, true, true, SingleSpc, 4, 1 }, +{ ARM::VLD1d64TPseudo, ARM::VLD1d64T, true, false, SingleSpc, 3, 1 }, +{ ARM::VLD1d64TPseudo_UPD, ARM::VLD1d64T_UPD, true, true, SingleSpc, 3, 1 }, + +{ ARM::VLD1q16Pseudo, ARM::VLD1q16, true, false, SingleSpc, 2, 4 }, +{ ARM::VLD1q16Pseudo_UPD, ARM::VLD1q16_UPD, true, true, SingleSpc, 2, 4 }, +{ ARM::VLD1q32Pseudo, ARM::VLD1q32, true, false, SingleSpc, 2, 2 }, +{ ARM::VLD1q32Pseudo_UPD, ARM::VLD1q32_UPD, true, true, SingleSpc, 2, 2 }, +{ ARM::VLD1q64Pseudo, ARM::VLD1q64, true, false, SingleSpc, 2, 1 }, +{ ARM::VLD1q64Pseudo_UPD, ARM::VLD1q64_UPD, true, true, SingleSpc, 2, 1 }, +{ ARM::VLD1q8Pseudo, ARM::VLD1q8, true, false, SingleSpc, 2, 8 }, +{ ARM::VLD1q8Pseudo_UPD, ARM::VLD1q8_UPD, true, true, SingleSpc, 2, 8 }, + +{ ARM::VLD2DUPd16Pseudo, ARM::VLD2DUPd16, true, false, SingleSpc, 2, 4}, +{ ARM::VLD2DUPd16Pseudo_UPD, ARM::VLD2DUPd16_UPD, true, true, SingleSpc, 2, 4}, +{ ARM::VLD2DUPd32Pseudo, ARM::VLD2DUPd32, true, false, SingleSpc, 2, 2}, +{ ARM::VLD2DUPd32Pseudo_UPD, ARM::VLD2DUPd32_UPD, true, true, SingleSpc, 2, 2}, +{ ARM::VLD2DUPd8Pseudo, ARM::VLD2DUPd8, true, false, SingleSpc, 2, 8}, +{ ARM::VLD2DUPd8Pseudo_UPD, ARM::VLD2DUPd8_UPD, true, true, SingleSpc, 2, 8}, + +{ ARM::VLD2LNd16Pseudo, ARM::VLD2LNd16, true, false, SingleSpc, 2, 4 }, +{ ARM::VLD2LNd16Pseudo_UPD, ARM::VLD2LNd16_UPD, true, true, SingleSpc, 2, 4 }, +{ ARM::VLD2LNd32Pseudo, ARM::VLD2LNd32, true, false, SingleSpc, 2, 2 }, +{ ARM::VLD2LNd32Pseudo_UPD, ARM::VLD2LNd32_UPD, true, true, SingleSpc, 2, 2 }, +{ ARM::VLD2LNd8Pseudo, ARM::VLD2LNd8, true, false, SingleSpc, 2, 8 }, +{ ARM::VLD2LNd8Pseudo_UPD, ARM::VLD2LNd8_UPD, true, true, SingleSpc, 2, 8 }, +{ ARM::VLD2LNq16Pseudo, ARM::VLD2LNq16, true, false, EvenDblSpc, 2, 4 }, +{ ARM::VLD2LNq16Pseudo_UPD, ARM::VLD2LNq16_UPD, true, true, EvenDblSpc, 2, 4 }, +{ ARM::VLD2LNq32Pseudo, ARM::VLD2LNq32, true, false, EvenDblSpc, 2, 2 }, +{ ARM::VLD2LNq32Pseudo_UPD, ARM::VLD2LNq32_UPD, true, true, EvenDblSpc, 2, 2 }, + +{ ARM::VLD2d16Pseudo, ARM::VLD2d16, true, false, SingleSpc, 2, 4 }, +{ ARM::VLD2d16Pseudo_UPD, ARM::VLD2d16_UPD, true, true, SingleSpc, 2, 4 }, +{ ARM::VLD2d32Pseudo, ARM::VLD2d32, true, false, SingleSpc, 2, 2 }, +{ ARM::VLD2d32Pseudo_UPD, ARM::VLD2d32_UPD, true, true, SingleSpc, 2, 2 }, +{ ARM::VLD2d8Pseudo, ARM::VLD2d8, true, false, SingleSpc, 2, 8 }, +{ ARM::VLD2d8Pseudo_UPD, ARM::VLD2d8_UPD, true, true, SingleSpc, 2, 8 }, + +{ ARM::VLD2q16Pseudo, ARM::VLD2q16, true, false, SingleSpc, 4, 4 }, +{ ARM::VLD2q16Pseudo_UPD, ARM::VLD2q16_UPD, true, true, SingleSpc, 4, 4 }, +{ ARM::VLD2q32Pseudo, ARM::VLD2q32, true, false, SingleSpc, 4, 2 }, +{ ARM::VLD2q32Pseudo_UPD, ARM::VLD2q32_UPD, true, true, SingleSpc, 4, 2 }, +{ ARM::VLD2q8Pseudo, ARM::VLD2q8, true, false, SingleSpc, 4, 8 }, +{ ARM::VLD2q8Pseudo_UPD, ARM::VLD2q8_UPD, true, true, SingleSpc, 4, 8 }, + +{ ARM::VLD3DUPd16Pseudo, ARM::VLD3DUPd16, true, false, SingleSpc, 3, 4}, +{ ARM::VLD3DUPd16Pseudo_UPD, ARM::VLD3DUPd16_UPD, true, true, SingleSpc, 3, 4}, +{ ARM::VLD3DUPd32Pseudo, ARM::VLD3DUPd32, true, false, SingleSpc, 3, 2}, +{ ARM::VLD3DUPd32Pseudo_UPD, ARM::VLD3DUPd32_UPD, true, true, SingleSpc, 3, 2}, +{ ARM::VLD3DUPd8Pseudo, ARM::VLD3DUPd8, true, false, SingleSpc, 3, 8}, +{ ARM::VLD3DUPd8Pseudo_UPD, ARM::VLD3DUPd8_UPD, true, true, SingleSpc, 3, 8}, + +{ ARM::VLD3LNd16Pseudo, ARM::VLD3LNd16, true, false, SingleSpc, 3, 4 }, +{ ARM::VLD3LNd16Pseudo_UPD, ARM::VLD3LNd16_UPD, true, true, SingleSpc, 3, 4 }, +{ ARM::VLD3LNd32Pseudo, ARM::VLD3LNd32, true, false, SingleSpc, 3, 2 }, +{ ARM::VLD3LNd32Pseudo_UPD, ARM::VLD3LNd32_UPD, true, true, SingleSpc, 3, 2 }, +{ ARM::VLD3LNd8Pseudo, ARM::VLD3LNd8, true, false, SingleSpc, 3, 8 }, +{ ARM::VLD3LNd8Pseudo_UPD, ARM::VLD3LNd8_UPD, true, true, SingleSpc, 3, 8 }, +{ ARM::VLD3LNq16Pseudo, ARM::VLD3LNq16, true, false, EvenDblSpc, 3, 4 }, +{ ARM::VLD3LNq16Pseudo_UPD, ARM::VLD3LNq16_UPD, true, true, EvenDblSpc, 3, 4 }, +{ ARM::VLD3LNq32Pseudo, ARM::VLD3LNq32, true, false, EvenDblSpc, 3, 2 }, +{ ARM::VLD3LNq32Pseudo_UPD, ARM::VLD3LNq32_UPD, true, true, EvenDblSpc, 3, 2 }, + +{ ARM::VLD3d16Pseudo, ARM::VLD3d16, true, false, SingleSpc, 3, 4 }, +{ ARM::VLD3d16Pseudo_UPD, ARM::VLD3d16_UPD, true, true, SingleSpc, 3, 4 }, +{ ARM::VLD3d32Pseudo, ARM::VLD3d32, true, false, SingleSpc, 3, 2 }, +{ ARM::VLD3d32Pseudo_UPD, ARM::VLD3d32_UPD, true, true, SingleSpc, 3, 2 }, +{ ARM::VLD3d8Pseudo, ARM::VLD3d8, true, false, SingleSpc, 3, 8 }, +{ ARM::VLD3d8Pseudo_UPD, ARM::VLD3d8_UPD, true, true, SingleSpc, 3, 8 }, + +{ ARM::VLD3q16Pseudo_UPD, ARM::VLD3q16_UPD, true, true, EvenDblSpc, 3, 4 }, +{ ARM::VLD3q16oddPseudo, ARM::VLD3q16, true, false, OddDblSpc, 3, 4 }, +{ ARM::VLD3q16oddPseudo_UPD, ARM::VLD3q16_UPD, true, true, OddDblSpc, 3, 4 }, +{ ARM::VLD3q32Pseudo_UPD, ARM::VLD3q32_UPD, true, true, EvenDblSpc, 3, 2 }, +{ ARM::VLD3q32oddPseudo, ARM::VLD3q32, true, false, OddDblSpc, 3, 2 }, +{ ARM::VLD3q32oddPseudo_UPD, ARM::VLD3q32_UPD, true, true, OddDblSpc, 3, 2 }, +{ ARM::VLD3q8Pseudo_UPD, ARM::VLD3q8_UPD, true, true, EvenDblSpc, 3, 8 }, +{ ARM::VLD3q8oddPseudo, ARM::VLD3q8, true, false, OddDblSpc, 3, 8 }, +{ ARM::VLD3q8oddPseudo_UPD, ARM::VLD3q8_UPD, true, true, OddDblSpc, 3, 8 }, + +{ ARM::VLD4DUPd16Pseudo, ARM::VLD4DUPd16, true, false, SingleSpc, 4, 4}, +{ ARM::VLD4DUPd16Pseudo_UPD, ARM::VLD4DUPd16_UPD, true, true, SingleSpc, 4, 4}, +{ ARM::VLD4DUPd32Pseudo, ARM::VLD4DUPd32, true, false, SingleSpc, 4, 2}, +{ ARM::VLD4DUPd32Pseudo_UPD, ARM::VLD4DUPd32_UPD, true, true, SingleSpc, 4, 2}, +{ ARM::VLD4DUPd8Pseudo, ARM::VLD4DUPd8, true, false, SingleSpc, 4, 8}, +{ ARM::VLD4DUPd8Pseudo_UPD, ARM::VLD4DUPd8_UPD, true, true, SingleSpc, 4, 8}, + +{ ARM::VLD4LNd16Pseudo, ARM::VLD4LNd16, true, false, SingleSpc, 4, 4 }, +{ ARM::VLD4LNd16Pseudo_UPD, ARM::VLD4LNd16_UPD, true, true, SingleSpc, 4, 4 }, +{ ARM::VLD4LNd32Pseudo, ARM::VLD4LNd32, true, false, SingleSpc, 4, 2 }, +{ ARM::VLD4LNd32Pseudo_UPD, ARM::VLD4LNd32_UPD, true, true, SingleSpc, 4, 2 }, +{ ARM::VLD4LNd8Pseudo, ARM::VLD4LNd8, true, false, SingleSpc, 4, 8 }, +{ ARM::VLD4LNd8Pseudo_UPD, ARM::VLD4LNd8_UPD, true, true, SingleSpc, 4, 8 }, +{ ARM::VLD4LNq16Pseudo, ARM::VLD4LNq16, true, false, EvenDblSpc, 4, 4 }, +{ ARM::VLD4LNq16Pseudo_UPD, ARM::VLD4LNq16_UPD, true, true, EvenDblSpc, 4, 4 }, +{ ARM::VLD4LNq32Pseudo, ARM::VLD4LNq32, true, false, EvenDblSpc, 4, 2 }, +{ ARM::VLD4LNq32Pseudo_UPD, ARM::VLD4LNq32_UPD, true, true, EvenDblSpc, 4, 2 }, + +{ ARM::VLD4d16Pseudo, ARM::VLD4d16, true, false, SingleSpc, 4, 4 }, +{ ARM::VLD4d16Pseudo_UPD, ARM::VLD4d16_UPD, true, true, SingleSpc, 4, 4 }, +{ ARM::VLD4d32Pseudo, ARM::VLD4d32, true, false, SingleSpc, 4, 2 }, +{ ARM::VLD4d32Pseudo_UPD, ARM::VLD4d32_UPD, true, true, SingleSpc, 4, 2 }, +{ ARM::VLD4d8Pseudo, ARM::VLD4d8, true, false, SingleSpc, 4, 8 }, +{ ARM::VLD4d8Pseudo_UPD, ARM::VLD4d8_UPD, true, true, SingleSpc, 4, 8 }, + +{ ARM::VLD4q16Pseudo_UPD, ARM::VLD4q16_UPD, true, true, EvenDblSpc, 4, 4 }, +{ ARM::VLD4q16oddPseudo, ARM::VLD4q16, true, false, OddDblSpc, 4, 4 }, +{ ARM::VLD4q16oddPseudo_UPD, ARM::VLD4q16_UPD, true, true, OddDblSpc, 4, 4 }, +{ ARM::VLD4q32Pseudo_UPD, ARM::VLD4q32_UPD, true, true, EvenDblSpc, 4, 2 }, +{ ARM::VLD4q32oddPseudo, ARM::VLD4q32, true, false, OddDblSpc, 4, 2 }, +{ ARM::VLD4q32oddPseudo_UPD, ARM::VLD4q32_UPD, true, true, OddDblSpc, 4, 2 }, +{ ARM::VLD4q8Pseudo_UPD, ARM::VLD4q8_UPD, true, true, EvenDblSpc, 4, 8 }, +{ ARM::VLD4q8oddPseudo, ARM::VLD4q8, true, false, OddDblSpc, 4, 8 }, +{ ARM::VLD4q8oddPseudo_UPD, ARM::VLD4q8_UPD, true, true, OddDblSpc, 4, 8 }, + +{ ARM::VST1LNq16Pseudo, ARM::VST1LNd16, false, false, EvenDblSpc, 1, 4 }, +{ ARM::VST1LNq16Pseudo_UPD, ARM::VST1LNd16_UPD,false, true, EvenDblSpc, 1, 4 }, +{ ARM::VST1LNq32Pseudo, ARM::VST1LNd32, false, false, EvenDblSpc, 1, 2 }, +{ ARM::VST1LNq32Pseudo_UPD, ARM::VST1LNd32_UPD,false, true, EvenDblSpc, 1, 2 }, +{ ARM::VST1LNq8Pseudo, ARM::VST1LNd8, false, false, EvenDblSpc, 1, 8 }, +{ ARM::VST1LNq8Pseudo_UPD, ARM::VST1LNd8_UPD, false, true, EvenDblSpc, 1, 8 }, + +{ ARM::VST1d64QPseudo, ARM::VST1d64Q, false, false, SingleSpc, 4, 1 }, +{ ARM::VST1d64QPseudo_UPD, ARM::VST1d64Q_UPD, false, true, SingleSpc, 4, 1 }, +{ ARM::VST1d64TPseudo, ARM::VST1d64T, false, false, SingleSpc, 3, 1 }, +{ ARM::VST1d64TPseudo_UPD, ARM::VST1d64T_UPD, false, true, SingleSpc, 3, 1 }, + +{ ARM::VST1q16Pseudo, ARM::VST1q16, false, false, SingleSpc, 2, 4 }, +{ ARM::VST1q16Pseudo_UPD, ARM::VST1q16_UPD, false, true, SingleSpc, 2, 4 }, +{ ARM::VST1q32Pseudo, ARM::VST1q32, false, false, SingleSpc, 2, 2 }, +{ ARM::VST1q32Pseudo_UPD, ARM::VST1q32_UPD, false, true, SingleSpc, 2, 2 }, +{ ARM::VST1q64Pseudo, ARM::VST1q64, false, false, SingleSpc, 2, 1 }, +{ ARM::VST1q64Pseudo_UPD, ARM::VST1q64_UPD, false, true, SingleSpc, 2, 1 }, +{ ARM::VST1q8Pseudo, ARM::VST1q8, false, false, SingleSpc, 2, 8 }, +{ ARM::VST1q8Pseudo_UPD, ARM::VST1q8_UPD, false, true, SingleSpc, 2, 8 }, + +{ ARM::VST2LNd16Pseudo, ARM::VST2LNd16, false, false, SingleSpc, 2, 4 }, +{ ARM::VST2LNd16Pseudo_UPD, ARM::VST2LNd16_UPD, false, true, SingleSpc, 2, 4 }, +{ ARM::VST2LNd32Pseudo, ARM::VST2LNd32, false, false, SingleSpc, 2, 2 }, +{ ARM::VST2LNd32Pseudo_UPD, ARM::VST2LNd32_UPD, false, true, SingleSpc, 2, 2 }, +{ ARM::VST2LNd8Pseudo, ARM::VST2LNd8, false, false, SingleSpc, 2, 8 }, +{ ARM::VST2LNd8Pseudo_UPD, ARM::VST2LNd8_UPD, false, true, SingleSpc, 2, 8 }, +{ ARM::VST2LNq16Pseudo, ARM::VST2LNq16, false, false, EvenDblSpc, 2, 4}, +{ ARM::VST2LNq16Pseudo_UPD, ARM::VST2LNq16_UPD, false, true, EvenDblSpc, 2, 4}, +{ ARM::VST2LNq32Pseudo, ARM::VST2LNq32, false, false, EvenDblSpc, 2, 2}, +{ ARM::VST2LNq32Pseudo_UPD, ARM::VST2LNq32_UPD, false, true, EvenDblSpc, 2, 2}, + +{ ARM::VST2d16Pseudo, ARM::VST2d16, false, false, SingleSpc, 2, 4 }, +{ ARM::VST2d16Pseudo_UPD, ARM::VST2d16_UPD, false, true, SingleSpc, 2, 4 }, +{ ARM::VST2d32Pseudo, ARM::VST2d32, false, false, SingleSpc, 2, 2 }, +{ ARM::VST2d32Pseudo_UPD, ARM::VST2d32_UPD, false, true, SingleSpc, 2, 2 }, +{ ARM::VST2d8Pseudo, ARM::VST2d8, false, false, SingleSpc, 2, 8 }, +{ ARM::VST2d8Pseudo_UPD, ARM::VST2d8_UPD, false, true, SingleSpc, 2, 8 }, + +{ ARM::VST2q16Pseudo, ARM::VST2q16, false, false, SingleSpc, 4, 4 }, +{ ARM::VST2q16Pseudo_UPD, ARM::VST2q16_UPD, false, true, SingleSpc, 4, 4 }, +{ ARM::VST2q32Pseudo, ARM::VST2q32, false, false, SingleSpc, 4, 2 }, +{ ARM::VST2q32Pseudo_UPD, ARM::VST2q32_UPD, false, true, SingleSpc, 4, 2 }, +{ ARM::VST2q8Pseudo, ARM::VST2q8, false, false, SingleSpc, 4, 8 }, +{ ARM::VST2q8Pseudo_UPD, ARM::VST2q8_UPD, false, true, SingleSpc, 4, 8 }, + +{ ARM::VST3LNd16Pseudo, ARM::VST3LNd16, false, false, SingleSpc, 3, 4 }, +{ ARM::VST3LNd16Pseudo_UPD, ARM::VST3LNd16_UPD, false, true, SingleSpc, 3, 4 }, +{ ARM::VST3LNd32Pseudo, ARM::VST3LNd32, false, false, SingleSpc, 3, 2 }, +{ ARM::VST3LNd32Pseudo_UPD, ARM::VST3LNd32_UPD, false, true, SingleSpc, 3, 2 }, +{ ARM::VST3LNd8Pseudo, ARM::VST3LNd8, false, false, SingleSpc, 3, 8 }, +{ ARM::VST3LNd8Pseudo_UPD, ARM::VST3LNd8_UPD, false, true, SingleSpc, 3, 8 }, +{ ARM::VST3LNq16Pseudo, ARM::VST3LNq16, false, false, EvenDblSpc, 3, 4}, +{ ARM::VST3LNq16Pseudo_UPD, ARM::VST3LNq16_UPD, false, true, EvenDblSpc, 3, 4}, +{ ARM::VST3LNq32Pseudo, ARM::VST3LNq32, false, false, EvenDblSpc, 3, 2}, +{ ARM::VST3LNq32Pseudo_UPD, ARM::VST3LNq32_UPD, false, true, EvenDblSpc, 3, 2}, + +{ ARM::VST3d16Pseudo, ARM::VST3d16, false, false, SingleSpc, 3, 4 }, +{ ARM::VST3d16Pseudo_UPD, ARM::VST3d16_UPD, false, true, SingleSpc, 3, 4 }, +{ ARM::VST3d32Pseudo, ARM::VST3d32, false, false, SingleSpc, 3, 2 }, +{ ARM::VST3d32Pseudo_UPD, ARM::VST3d32_UPD, false, true, SingleSpc, 3, 2 }, +{ ARM::VST3d8Pseudo, ARM::VST3d8, false, false, SingleSpc, 3, 8 }, +{ ARM::VST3d8Pseudo_UPD, ARM::VST3d8_UPD, false, true, SingleSpc, 3, 8 }, + +{ ARM::VST3q16Pseudo_UPD, ARM::VST3q16_UPD, false, true, EvenDblSpc, 3, 4 }, +{ ARM::VST3q16oddPseudo, ARM::VST3q16, false, false, OddDblSpc, 3, 4 }, +{ ARM::VST3q16oddPseudo_UPD, ARM::VST3q16_UPD, false, true, OddDblSpc, 3, 4 }, +{ ARM::VST3q32Pseudo_UPD, ARM::VST3q32_UPD, false, true, EvenDblSpc, 3, 2 }, +{ ARM::VST3q32oddPseudo, ARM::VST3q32, false, false, OddDblSpc, 3, 2 }, +{ ARM::VST3q32oddPseudo_UPD, ARM::VST3q32_UPD, false, true, OddDblSpc, 3, 2 }, +{ ARM::VST3q8Pseudo_UPD, ARM::VST3q8_UPD, false, true, EvenDblSpc, 3, 8 }, +{ ARM::VST3q8oddPseudo, ARM::VST3q8, false, false, OddDblSpc, 3, 8 }, +{ ARM::VST3q8oddPseudo_UPD, ARM::VST3q8_UPD, false, true, OddDblSpc, 3, 8 }, + +{ ARM::VST4LNd16Pseudo, ARM::VST4LNd16, false, false, SingleSpc, 4, 4 }, +{ ARM::VST4LNd16Pseudo_UPD, ARM::VST4LNd16_UPD, false, true, SingleSpc, 4, 4 }, +{ ARM::VST4LNd32Pseudo, ARM::VST4LNd32, false, false, SingleSpc, 4, 2 }, +{ ARM::VST4LNd32Pseudo_UPD, ARM::VST4LNd32_UPD, false, true, SingleSpc, 4, 2 }, +{ ARM::VST4LNd8Pseudo, ARM::VST4LNd8, false, false, SingleSpc, 4, 8 }, +{ ARM::VST4LNd8Pseudo_UPD, ARM::VST4LNd8_UPD, false, true, SingleSpc, 4, 8 }, +{ ARM::VST4LNq16Pseudo, ARM::VST4LNq16, false, false, EvenDblSpc, 4, 4}, +{ ARM::VST4LNq16Pseudo_UPD, ARM::VST4LNq16_UPD, false, true, EvenDblSpc, 4, 4}, +{ ARM::VST4LNq32Pseudo, ARM::VST4LNq32, false, false, EvenDblSpc, 4, 2}, +{ ARM::VST4LNq32Pseudo_UPD, ARM::VST4LNq32_UPD, false, true, EvenDblSpc, 4, 2}, + +{ ARM::VST4d16Pseudo, ARM::VST4d16, false, false, SingleSpc, 4, 4 }, +{ ARM::VST4d16Pseudo_UPD, ARM::VST4d16_UPD, false, true, SingleSpc, 4, 4 }, +{ ARM::VST4d32Pseudo, ARM::VST4d32, false, false, SingleSpc, 4, 2 }, +{ ARM::VST4d32Pseudo_UPD, ARM::VST4d32_UPD, false, true, SingleSpc, 4, 2 }, +{ ARM::VST4d8Pseudo, ARM::VST4d8, false, false, SingleSpc, 4, 8 }, +{ ARM::VST4d8Pseudo_UPD, ARM::VST4d8_UPD, false, true, SingleSpc, 4, 8 }, + +{ ARM::VST4q16Pseudo_UPD, ARM::VST4q16_UPD, false, true, EvenDblSpc, 4, 4 }, +{ ARM::VST4q16oddPseudo, ARM::VST4q16, false, false, OddDblSpc, 4, 4 }, +{ ARM::VST4q16oddPseudo_UPD, ARM::VST4q16_UPD, false, true, OddDblSpc, 4, 4 }, +{ ARM::VST4q32Pseudo_UPD, ARM::VST4q32_UPD, false, true, EvenDblSpc, 4, 2 }, +{ ARM::VST4q32oddPseudo, ARM::VST4q32, false, false, OddDblSpc, 4, 2 }, +{ ARM::VST4q32oddPseudo_UPD, ARM::VST4q32_UPD, false, true, OddDblSpc, 4, 2 }, +{ ARM::VST4q8Pseudo_UPD, ARM::VST4q8_UPD, false, true, EvenDblSpc, 4, 8 }, +{ ARM::VST4q8oddPseudo, ARM::VST4q8, false, false, OddDblSpc, 4, 8 }, +{ ARM::VST4q8oddPseudo_UPD, ARM::VST4q8_UPD, false, true, OddDblSpc, 4, 8 } +}; + +/// LookupNEONLdSt - Search the NEONLdStTable for information about a NEON +/// load or store pseudo instruction. +static const NEONLdStTableEntry *LookupNEONLdSt(unsigned Opcode) { + unsigned NumEntries = array_lengthof(NEONLdStTable); + +#ifndef NDEBUG + // Make sure the table is sorted. + static bool TableChecked = false; + if (!TableChecked) { + for (unsigned i = 0; i != NumEntries-1; ++i) + assert(NEONLdStTable[i] < NEONLdStTable[i+1] && + "NEONLdStTable is not sorted!"); + TableChecked = true; + } +#endif + + const NEONLdStTableEntry *I = + std::lower_bound(NEONLdStTable, NEONLdStTable + NumEntries, Opcode); + if (I != NEONLdStTable + NumEntries && I->PseudoOpc == Opcode) + return I; + return NULL; +} + +/// GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register, +/// corresponding to the specified register spacing. Not all of the results +/// are necessarily valid, e.g., a Q register only has 2 D subregisters. +static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc, + const TargetRegisterInfo *TRI, unsigned &D0, + unsigned &D1, unsigned &D2, unsigned &D3) { + if (RegSpc == SingleSpc) { + D0 = TRI->getSubReg(Reg, ARM::dsub_0); + D1 = TRI->getSubReg(Reg, ARM::dsub_1); + D2 = TRI->getSubReg(Reg, ARM::dsub_2); + D3 = TRI->getSubReg(Reg, ARM::dsub_3); + } else if (RegSpc == EvenDblSpc) { + D0 = TRI->getSubReg(Reg, ARM::dsub_0); + D1 = TRI->getSubReg(Reg, ARM::dsub_2); + D2 = TRI->getSubReg(Reg, ARM::dsub_4); + D3 = TRI->getSubReg(Reg, ARM::dsub_6); + } else { + assert(RegSpc == OddDblSpc && "unknown register spacing"); + D0 = TRI->getSubReg(Reg, ARM::dsub_1); + D1 = TRI->getSubReg(Reg, ARM::dsub_3); + D2 = TRI->getSubReg(Reg, ARM::dsub_5); + D3 = TRI->getSubReg(Reg, ARM::dsub_7); + } +} + +/// ExpandVLD - Translate VLD pseudo instructions with Q, QQ or QQQQ register +/// operands to real VLD instructions with D register operands. +void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { + MachineInstr &MI = *MBBI; + MachineBasicBlock &MBB = *MI.getParent(); + + const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); + assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed"); + NEONRegSpacing RegSpc = TableEntry->RegSpacing; + unsigned NumRegs = TableEntry->NumRegs; + + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(TableEntry->RealOpc)); + unsigned OpIdx = 0; + + bool DstIsDead = MI.getOperand(OpIdx).isDead(); + unsigned DstReg = MI.getOperand(OpIdx++).getReg(); + unsigned D0, D1, D2, D3; + GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3); + MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(D1, RegState::Define | getDeadRegState(DstIsDead)); + if (NumRegs > 2) + MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead)); + if (NumRegs > 3) + MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead)); + + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the addrmode6 operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + // Copy the am6offset operand. + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + // For an instruction writing double-spaced subregs, the pseudo instruction + // has an extra operand that is a use of the super-register. Record the + // operand index and skip over it. + unsigned SrcOpIdx = 0; + if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc) + SrcOpIdx = OpIdx++; + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the super-register source operand used for double-spaced subregs over + // to the new instruction as an implicit operand. + if (SrcOpIdx != 0) { + MachineOperand MO = MI.getOperand(SrcOpIdx); + MO.setImplicit(true); + MIB.addOperand(MO); + } + // Add an implicit def for the super-register. + MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead)); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); +} + +/// ExpandVST - Translate VST pseudo instructions with Q, QQ or QQQQ register +/// operands to real VST instructions with D register operands. +void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { + MachineInstr &MI = *MBBI; + MachineBasicBlock &MBB = *MI.getParent(); + + const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); + assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed"); + NEONRegSpacing RegSpc = TableEntry->RegSpacing; + unsigned NumRegs = TableEntry->NumRegs; + + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(TableEntry->RealOpc)); + unsigned OpIdx = 0; + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the addrmode6 operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + // Copy the am6offset operand. + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + bool SrcIsKill = MI.getOperand(OpIdx).isKill(); + unsigned SrcReg = MI.getOperand(OpIdx++).getReg(); + unsigned D0, D1, D2, D3; + GetDSubRegs(SrcReg, RegSpc, TRI, D0, D1, D2, D3); + MIB.addReg(D0).addReg(D1); + if (NumRegs > 2) + MIB.addReg(D2); + if (NumRegs > 3) + MIB.addReg(D3); + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + if (SrcIsKill) + // Add an implicit kill for the super-reg. + (*MIB).addRegisterKilled(SrcReg, TRI, true); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); +} + +/// ExpandLaneOp - Translate VLD*LN and VST*LN instructions with Q, QQ or QQQQ +/// register operands to real instructions with D register operands. +void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) { + MachineInstr &MI = *MBBI; + MachineBasicBlock &MBB = *MI.getParent(); + + const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode()); + assert(TableEntry && "NEONLdStTable lookup failed"); + NEONRegSpacing RegSpc = TableEntry->RegSpacing; + unsigned NumRegs = TableEntry->NumRegs; + unsigned RegElts = TableEntry->RegElts; + + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(TableEntry->RealOpc)); + unsigned OpIdx = 0; + // The lane operand is always the 3rd from last operand, before the 2 + // predicate operands. + unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm(); + + // Adjust the lane and spacing as needed for Q registers. + assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane"); + if (RegSpc == EvenDblSpc && Lane >= RegElts) { + RegSpc = OddDblSpc; + Lane -= RegElts; + } + assert(Lane < RegElts && "out of range lane for VLD/VST-lane"); + + unsigned D0 = 0, D1 = 0, D2 = 0, D3 = 0; + unsigned DstReg = 0; + bool DstIsDead = false; + if (TableEntry->IsLoad) { + DstIsDead = MI.getOperand(OpIdx).isDead(); + DstReg = MI.getOperand(OpIdx++).getReg(); + GetDSubRegs(DstReg, RegSpc, TRI, D0, D1, D2, D3); + MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead)); + if (NumRegs > 1) + MIB.addReg(D1, RegState::Define | getDeadRegState(DstIsDead)); + if (NumRegs > 2) + MIB.addReg(D2, RegState::Define | getDeadRegState(DstIsDead)); + if (NumRegs > 3) + MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead)); + } + + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the addrmode6 operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + // Copy the am6offset operand. + if (TableEntry->HasWriteBack) + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Grab the super-register source. + MachineOperand MO = MI.getOperand(OpIdx++); + if (!TableEntry->IsLoad) + GetDSubRegs(MO.getReg(), RegSpc, TRI, D0, D1, D2, D3); + + // Add the subregs as sources of the new instruction. + unsigned SrcFlags = (getUndefRegState(MO.isUndef()) | + getKillRegState(MO.isKill())); + MIB.addReg(D0, SrcFlags); + if (NumRegs > 1) + MIB.addReg(D1, SrcFlags); + if (NumRegs > 2) + MIB.addReg(D2, SrcFlags); + if (NumRegs > 3) + MIB.addReg(D3, SrcFlags); + + // Add the lane number operand. + MIB.addImm(Lane); + OpIdx += 1; + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the super-register source to be an implicit source. + MO.setImplicit(true); + MIB.addOperand(MO); + if (TableEntry->IsLoad) + // Add an implicit def for the super-register. + MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead)); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); +} + +/// ExpandVTBL - Translate VTBL and VTBX pseudo instructions with Q or QQ +/// register operands to real instructions with D register operands. +void ARMExpandPseudo::ExpandVTBL(MachineBasicBlock::iterator &MBBI, + unsigned Opc, bool IsExt, unsigned NumRegs) { + MachineInstr &MI = *MBBI; + MachineBasicBlock &MBB = *MI.getParent(); + + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)); + unsigned OpIdx = 0; + + // Transfer the destination register operand. + MIB.addOperand(MI.getOperand(OpIdx++)); + if (IsExt) + MIB.addOperand(MI.getOperand(OpIdx++)); + + bool SrcIsKill = MI.getOperand(OpIdx).isKill(); + unsigned SrcReg = MI.getOperand(OpIdx++).getReg(); + unsigned D0, D1, D2, D3; + GetDSubRegs(SrcReg, SingleSpc, TRI, D0, D1, D2, D3); + MIB.addReg(D0).addReg(D1); + if (NumRegs > 2) + MIB.addReg(D2); + if (NumRegs > 3) + MIB.addReg(D3); + + // Copy the other source register operand. + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + if (SrcIsKill) + // Add an implicit kill for the super-reg. + (*MIB).addRegisterKilled(SrcReg, TRI, true); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); +} + +void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI) { + MachineInstr &MI = *MBBI; + unsigned Opcode = MI.getOpcode(); + unsigned PredReg = 0; + ARMCC::CondCodes Pred = llvm::getInstrPredicate(&MI, PredReg); + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm; + const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1); + MachineInstrBuilder LO16, HI16; + + if (!STI->hasV6T2Ops() && + (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) { + // Expand into a movi + orr. + LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVi), DstReg); + HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::ORRri)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg); + + assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!"); + unsigned ImmVal = (unsigned)MO.getImm(); + unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal); + unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal); + LO16 = LO16.addImm(SOImmValV1); + HI16 = HI16.addImm(SOImmValV2); + (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + LO16.addImm(Pred).addReg(PredReg).addReg(0); + HI16.addImm(Pred).addReg(PredReg).addReg(0); + TransferImpOps(MI, LO16, HI16); + MI.eraseFromParent(); + return; + } + + unsigned LO16Opc = 0; + unsigned HI16Opc = 0; + if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) { + LO16Opc = ARM::t2MOVi16; + HI16Opc = ARM::t2MOVTi16; + } else { + LO16Opc = ARM::MOVi16; + HI16Opc = ARM::MOVTi16; + } + + LO16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LO16Opc), DstReg); + HI16 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(HI16Opc)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg); + + if (MO.isImm()) { + unsigned Imm = MO.getImm(); + unsigned Lo16 = Imm & 0xffff; + unsigned Hi16 = (Imm >> 16) & 0xffff; + LO16 = LO16.addImm(Lo16); + HI16 = HI16.addImm(Hi16); + } else { + const GlobalValue *GV = MO.getGlobal(); + unsigned TF = MO.getTargetFlags(); + LO16 = LO16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_LO16); + HI16 = HI16.addGlobalAddress(GV, MO.getOffset(), TF | ARMII::MO_HI16); + } + + (*LO16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + (*HI16).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + LO16.addImm(Pred).addReg(PredReg); + HI16.addImm(Pred).addReg(PredReg); + + TransferImpOps(MI, LO16, HI16); + MI.eraseFromParent(); +} + +bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI) { + MachineInstr &MI = *MBBI; + unsigned Opcode = MI.getOpcode(); + switch (Opcode) { + default: + return false; + case ARM::Int_eh_sjlj_dispatchsetup: { + MachineFunction &MF = *MI.getParent()->getParent(); + const ARMBaseInstrInfo *AII = + static_cast(TII); + const ARMBaseRegisterInfo &RI = AII->getRegisterInfo(); + // For functions using a base pointer, we rematerialize it (via the frame + // pointer) here since eh.sjlj.setjmp and eh.sjlj.longjmp don't do it + // for us. Otherwise, expand to nothing. + if (RI.hasBasePointer(MF)) { + int32_t NumBytes = AFI->getFramePtrSpillOffset(); + unsigned FramePtr = RI.getFrameRegister(MF); + assert(MF.getTarget().getFrameLowering()->hasFP(MF) && + "base pointer without frame pointer?"); + + if (AFI->isThumb2Function()) { + llvm::emitT2RegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, ARMCC::AL, 0, *TII); + } else if (AFI->isThumbFunction()) { + llvm::emitThumbRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, *TII, RI); + } else { + llvm::emitARMRegPlusImmediate(MBB, MBBI, MI.getDebugLoc(), ARM::R6, + FramePtr, -NumBytes, ARMCC::AL, 0, + *TII); + } + // If there's dynamic realignment, adjust for it. + if (RI.needsStackRealignment(MF)) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned MaxAlign = MFI->getMaxAlignment(); + assert (!AFI->isThumb1OnlyFunction()); + // Emit bic r6, r6, MaxAlign + unsigned bicOpc = AFI->isThumbFunction() ? + ARM::t2BICri : ARM::BICri; + AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(bicOpc), ARM::R6) + .addReg(ARM::R6, RegState::Kill) + .addImm(MaxAlign-1))); + } + + } + MI.eraseFromParent(); + return true; + } + + case ARM::MOVsrl_flag: + case ARM::MOVsra_flag: { + // These are just fancy MOVs insructions. + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + MI.getOperand(0).getReg()) + .addOperand(MI.getOperand(1)) + .addReg(0) + .addImm(ARM_AM::getSORegOpc((Opcode == ARM::MOVsrl_flag ? ARM_AM::lsr + : ARM_AM::asr), 1))) + .addReg(ARM::CPSR, RegState::Define); + MI.eraseFromParent(); + return true; + } + case ARM::RRX: { + // This encodes as "MOVs Rd, Rm, rrx + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::MOVs), + MI.getOperand(0).getReg()) + .addOperand(MI.getOperand(1)) + .addOperand(MI.getOperand(1)) + .addImm(ARM_AM::getSORegOpc(ARM_AM::rrx, 0))) + .addReg(0); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } + case ARM::TPsoft: { + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(ARM::BL)) + .addExternalSymbol("__aeabi_read_tp", 0); + + (*MIB).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } + case ARM::tLDRpci_pic: + case ARM::t2LDRpci_pic: { + unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic) + ? ARM::tLDRpci : ARM::t2LDRpci; + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + MachineInstrBuilder MIB1 = + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(NewLdOpc), DstReg) + .addOperand(MI.getOperand(1))); + (*MIB1).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(ARM::tPICADD)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg) + .addOperand(MI.getOperand(2)); + TransferImpOps(MI, MIB1, MIB2); + MI.eraseFromParent(); + return true; + } + + case ARM::MOV_ga_dyn: + case ARM::MOV_ga_pcrel: + case ARM::MOV_ga_pcrel_ldr: + case ARM::t2MOV_ga_dyn: + case ARM::t2MOV_ga_pcrel: { + // Expand into movw + movw. Also "add pc" / ldr [pc] in PIC mode. + unsigned LabelId = AFI->createPICLabelUId(); + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + const MachineOperand &MO1 = MI.getOperand(1); + const GlobalValue *GV = MO1.getGlobal(); + unsigned TF = MO1.getTargetFlags(); + bool isARM = Opcode != ARM::t2MOV_ga_pcrel; + bool isPIC = (Opcode != ARM::MOV_ga_dyn && Opcode != ARM::t2MOV_ga_dyn); + unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel; + unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel : ARM::t2MOVTi16_ga_pcrel; + unsigned LO16TF = isPIC + ? ARMII::MO_LO16_NONLAZY_PIC : ARMII::MO_LO16_NONLAZY; + unsigned HI16TF = isPIC + ? ARMII::MO_HI16_NONLAZY_PIC : ARMII::MO_HI16_NONLAZY; + unsigned PICAddOpc = isARM + ? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD) + : ARM::tPICADD; + MachineInstrBuilder MIB1 = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(LO16Opc), DstReg) + .addGlobalAddress(GV, MO1.getOffset(), TF | LO16TF) + .addImm(LabelId); + MachineInstrBuilder MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(HI16Opc), DstReg) + .addReg(DstReg) + .addGlobalAddress(GV, MO1.getOffset(), TF | HI16TF) + .addImm(LabelId); + if (!isPIC) { + TransferImpOps(MI, MIB1, MIB2); + MI.eraseFromParent(); + return true; + } + + MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(PICAddOpc)) + .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(DstReg).addImm(LabelId); + if (isARM) { + AddDefaultPred(MIB3); + if (Opcode == ARM::MOV_ga_pcrel_ldr) + (*MIB2).setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); + } + TransferImpOps(MI, MIB1, MIB3); + MI.eraseFromParent(); + return true; + } + + case ARM::MOVi32imm: + case ARM::MOVCCi32imm: + case ARM::t2MOVi32imm: + case ARM::t2MOVCCi32imm: + ExpandMOV32BitImm(MBB, MBBI); + return true; + + case ARM::VMOVQQ: { + unsigned DstReg = MI.getOperand(0).getReg(); + bool DstIsDead = MI.getOperand(0).isDead(); + unsigned EvenDst = TRI->getSubReg(DstReg, ARM::qsub_0); + unsigned OddDst = TRI->getSubReg(DstReg, ARM::qsub_1); + unsigned SrcReg = MI.getOperand(1).getReg(); + bool SrcIsKill = MI.getOperand(1).isKill(); + unsigned EvenSrc = TRI->getSubReg(SrcReg, ARM::qsub_0); + unsigned OddSrc = TRI->getSubReg(SrcReg, ARM::qsub_1); + MachineInstrBuilder Even = + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(ARM::VMOVQ)) + .addReg(EvenDst, + RegState::Define | getDeadRegState(DstIsDead)) + .addReg(EvenSrc, getKillRegState(SrcIsKill))); + MachineInstrBuilder Odd = + AddDefaultPred(BuildMI(MBB, MBBI, MI.getDebugLoc(), + TII->get(ARM::VMOVQ)) + .addReg(OddDst, + RegState::Define | getDeadRegState(DstIsDead)) + .addReg(OddSrc, getKillRegState(SrcIsKill))); + TransferImpOps(MI, Even, Odd); + MI.eraseFromParent(); + return true; + } + + case ARM::VLDMQIA: + case ARM::VLDMQDB: { + unsigned NewOpc = (Opcode == ARM::VLDMQIA) ? ARM::VLDMDIA : ARM::VLDMDDB; + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); + unsigned OpIdx = 0; + + // Grab the Q register destination. + bool DstIsDead = MI.getOperand(OpIdx).isDead(); + unsigned DstReg = MI.getOperand(OpIdx++).getReg(); + + // Copy the source register. + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Add the destination operands (D subregs). + unsigned D0 = TRI->getSubReg(DstReg, ARM::dsub_0); + unsigned D1 = TRI->getSubReg(DstReg, ARM::dsub_1); + MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead)) + .addReg(D1, RegState::Define | getDeadRegState(DstIsDead)); + + // Add an implicit def for the super-register. + MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead)); + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } + + case ARM::VSTMQIA: + case ARM::VSTMQDB: { + unsigned NewOpc = (Opcode == ARM::VSTMQIA) ? ARM::VSTMDIA : ARM::VSTMDDB; + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); + unsigned OpIdx = 0; + + // Grab the Q register source. + bool SrcIsKill = MI.getOperand(OpIdx).isKill(); + unsigned SrcReg = MI.getOperand(OpIdx++).getReg(); + + // Copy the destination register. + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + // Add the source operands (D subregs). + unsigned D0 = TRI->getSubReg(SrcReg, ARM::dsub_0); + unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1); + MIB.addReg(D0).addReg(D1); + + if (SrcIsKill) + // Add an implicit kill for the Q register. + (*MIB).addRegisterKilled(SrcReg, TRI, true); + + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } + case ARM::VDUPfqf: + case ARM::VDUPfdf:{ + unsigned NewOpc = Opcode == ARM::VDUPfqf ? ARM::VDUPLNfq : ARM::VDUPLNfd; + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); + unsigned OpIdx = 0; + unsigned SrcReg = MI.getOperand(1).getReg(); + unsigned Lane = getARMRegisterNumbering(SrcReg) & 1; + unsigned DReg = TRI->getMatchingSuperReg(SrcReg, + Lane & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass); + // The lane is [0,1] for the containing DReg superregister. + // Copy the dst/src register operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addReg(DReg); + ++OpIdx; + // Add the lane select operand. + MIB.addImm(Lane); + // Add the predicate operands. + MIB.addOperand(MI.getOperand(OpIdx++)); + MIB.addOperand(MI.getOperand(OpIdx++)); + + TransferImpOps(MI, MIB, MIB); + MI.eraseFromParent(); + return true; + } + + case ARM::VLD1q8Pseudo: + case ARM::VLD1q16Pseudo: + case ARM::VLD1q32Pseudo: + case ARM::VLD1q64Pseudo: + case ARM::VLD1q8Pseudo_UPD: + case ARM::VLD1q16Pseudo_UPD: + case ARM::VLD1q32Pseudo_UPD: + case ARM::VLD1q64Pseudo_UPD: + case ARM::VLD2d8Pseudo: + case ARM::VLD2d16Pseudo: + case ARM::VLD2d32Pseudo: + case ARM::VLD2q8Pseudo: + case ARM::VLD2q16Pseudo: + case ARM::VLD2q32Pseudo: + case ARM::VLD2d8Pseudo_UPD: + case ARM::VLD2d16Pseudo_UPD: + case ARM::VLD2d32Pseudo_UPD: + case ARM::VLD2q8Pseudo_UPD: + case ARM::VLD2q16Pseudo_UPD: + case ARM::VLD2q32Pseudo_UPD: + case ARM::VLD3d8Pseudo: + case ARM::VLD3d16Pseudo: + case ARM::VLD3d32Pseudo: + case ARM::VLD1d64TPseudo: + case ARM::VLD3d8Pseudo_UPD: + case ARM::VLD3d16Pseudo_UPD: + case ARM::VLD3d32Pseudo_UPD: + case ARM::VLD1d64TPseudo_UPD: + case ARM::VLD3q8Pseudo_UPD: + case ARM::VLD3q16Pseudo_UPD: + case ARM::VLD3q32Pseudo_UPD: + case ARM::VLD3q8oddPseudo: + case ARM::VLD3q16oddPseudo: + case ARM::VLD3q32oddPseudo: + case ARM::VLD3q8oddPseudo_UPD: + case ARM::VLD3q16oddPseudo_UPD: + case ARM::VLD3q32oddPseudo_UPD: + case ARM::VLD4d8Pseudo: + case ARM::VLD4d16Pseudo: + case ARM::VLD4d32Pseudo: + case ARM::VLD1d64QPseudo: + case ARM::VLD4d8Pseudo_UPD: + case ARM::VLD4d16Pseudo_UPD: + case ARM::VLD4d32Pseudo_UPD: + case ARM::VLD1d64QPseudo_UPD: + case ARM::VLD4q8Pseudo_UPD: + case ARM::VLD4q16Pseudo_UPD: + case ARM::VLD4q32Pseudo_UPD: + case ARM::VLD4q8oddPseudo: + case ARM::VLD4q16oddPseudo: + case ARM::VLD4q32oddPseudo: + case ARM::VLD4q8oddPseudo_UPD: + case ARM::VLD4q16oddPseudo_UPD: + case ARM::VLD4q32oddPseudo_UPD: + case ARM::VLD1DUPq8Pseudo: + case ARM::VLD1DUPq16Pseudo: + case ARM::VLD1DUPq32Pseudo: + case ARM::VLD1DUPq8Pseudo_UPD: + case ARM::VLD1DUPq16Pseudo_UPD: + case ARM::VLD1DUPq32Pseudo_UPD: + case ARM::VLD2DUPd8Pseudo: + case ARM::VLD2DUPd16Pseudo: + case ARM::VLD2DUPd32Pseudo: + case ARM::VLD2DUPd8Pseudo_UPD: + case ARM::VLD2DUPd16Pseudo_UPD: + case ARM::VLD2DUPd32Pseudo_UPD: + case ARM::VLD3DUPd8Pseudo: + case ARM::VLD3DUPd16Pseudo: + case ARM::VLD3DUPd32Pseudo: + case ARM::VLD3DUPd8Pseudo_UPD: + case ARM::VLD3DUPd16Pseudo_UPD: + case ARM::VLD3DUPd32Pseudo_UPD: + case ARM::VLD4DUPd8Pseudo: + case ARM::VLD4DUPd16Pseudo: + case ARM::VLD4DUPd32Pseudo: + case ARM::VLD4DUPd8Pseudo_UPD: + case ARM::VLD4DUPd16Pseudo_UPD: + case ARM::VLD4DUPd32Pseudo_UPD: + ExpandVLD(MBBI); + return true; + + case ARM::VST1q8Pseudo: + case ARM::VST1q16Pseudo: + case ARM::VST1q32Pseudo: + case ARM::VST1q64Pseudo: + case ARM::VST1q8Pseudo_UPD: + case ARM::VST1q16Pseudo_UPD: + case ARM::VST1q32Pseudo_UPD: + case ARM::VST1q64Pseudo_UPD: + case ARM::VST2d8Pseudo: + case ARM::VST2d16Pseudo: + case ARM::VST2d32Pseudo: + case ARM::VST2q8Pseudo: + case ARM::VST2q16Pseudo: + case ARM::VST2q32Pseudo: + case ARM::VST2d8Pseudo_UPD: + case ARM::VST2d16Pseudo_UPD: + case ARM::VST2d32Pseudo_UPD: + case ARM::VST2q8Pseudo_UPD: + case ARM::VST2q16Pseudo_UPD: + case ARM::VST2q32Pseudo_UPD: + case ARM::VST3d8Pseudo: + case ARM::VST3d16Pseudo: + case ARM::VST3d32Pseudo: + case ARM::VST1d64TPseudo: + case ARM::VST3d8Pseudo_UPD: + case ARM::VST3d16Pseudo_UPD: + case ARM::VST3d32Pseudo_UPD: + case ARM::VST1d64TPseudo_UPD: + case ARM::VST3q8Pseudo_UPD: + case ARM::VST3q16Pseudo_UPD: + case ARM::VST3q32Pseudo_UPD: + case ARM::VST3q8oddPseudo: + case ARM::VST3q16oddPseudo: + case ARM::VST3q32oddPseudo: + case ARM::VST3q8oddPseudo_UPD: + case ARM::VST3q16oddPseudo_UPD: + case ARM::VST3q32oddPseudo_UPD: + case ARM::VST4d8Pseudo: + case ARM::VST4d16Pseudo: + case ARM::VST4d32Pseudo: + case ARM::VST1d64QPseudo: + case ARM::VST4d8Pseudo_UPD: + case ARM::VST4d16Pseudo_UPD: + case ARM::VST4d32Pseudo_UPD: + case ARM::VST1d64QPseudo_UPD: + case ARM::VST4q8Pseudo_UPD: + case ARM::VST4q16Pseudo_UPD: + case ARM::VST4q32Pseudo_UPD: + case ARM::VST4q8oddPseudo: + case ARM::VST4q16oddPseudo: + case ARM::VST4q32oddPseudo: + case ARM::VST4q8oddPseudo_UPD: + case ARM::VST4q16oddPseudo_UPD: + case ARM::VST4q32oddPseudo_UPD: + ExpandVST(MBBI); + return true; + + case ARM::VLD1LNq8Pseudo: + case ARM::VLD1LNq16Pseudo: + case ARM::VLD1LNq32Pseudo: + case ARM::VLD1LNq8Pseudo_UPD: + case ARM::VLD1LNq16Pseudo_UPD: + case ARM::VLD1LNq32Pseudo_UPD: + case ARM::VLD2LNd8Pseudo: + case ARM::VLD2LNd16Pseudo: + case ARM::VLD2LNd32Pseudo: + case ARM::VLD2LNq16Pseudo: + case ARM::VLD2LNq32Pseudo: + case ARM::VLD2LNd8Pseudo_UPD: + case ARM::VLD2LNd16Pseudo_UPD: + case ARM::VLD2LNd32Pseudo_UPD: + case ARM::VLD2LNq16Pseudo_UPD: + case ARM::VLD2LNq32Pseudo_UPD: + case ARM::VLD3LNd8Pseudo: + case ARM::VLD3LNd16Pseudo: + case ARM::VLD3LNd32Pseudo: + case ARM::VLD3LNq16Pseudo: + case ARM::VLD3LNq32Pseudo: + case ARM::VLD3LNd8Pseudo_UPD: + case ARM::VLD3LNd16Pseudo_UPD: + case ARM::VLD3LNd32Pseudo_UPD: + case ARM::VLD3LNq16Pseudo_UPD: + case ARM::VLD3LNq32Pseudo_UPD: + case ARM::VLD4LNd8Pseudo: + case ARM::VLD4LNd16Pseudo: + case ARM::VLD4LNd32Pseudo: + case ARM::VLD4LNq16Pseudo: + case ARM::VLD4LNq32Pseudo: + case ARM::VLD4LNd8Pseudo_UPD: + case ARM::VLD4LNd16Pseudo_UPD: + case ARM::VLD4LNd32Pseudo_UPD: + case ARM::VLD4LNq16Pseudo_UPD: + case ARM::VLD4LNq32Pseudo_UPD: + case ARM::VST1LNq8Pseudo: + case ARM::VST1LNq16Pseudo: + case ARM::VST1LNq32Pseudo: + case ARM::VST1LNq8Pseudo_UPD: + case ARM::VST1LNq16Pseudo_UPD: + case ARM::VST1LNq32Pseudo_UPD: + case ARM::VST2LNd8Pseudo: + case ARM::VST2LNd16Pseudo: + case ARM::VST2LNd32Pseudo: + case ARM::VST2LNq16Pseudo: + case ARM::VST2LNq32Pseudo: + case ARM::VST2LNd8Pseudo_UPD: + case ARM::VST2LNd16Pseudo_UPD: + case ARM::VST2LNd32Pseudo_UPD: + case ARM::VST2LNq16Pseudo_UPD: + case ARM::VST2LNq32Pseudo_UPD: + case ARM::VST3LNd8Pseudo: + case ARM::VST3LNd16Pseudo: + case ARM::VST3LNd32Pseudo: + case ARM::VST3LNq16Pseudo: + case ARM::VST3LNq32Pseudo: + case ARM::VST3LNd8Pseudo_UPD: + case ARM::VST3LNd16Pseudo_UPD: + case ARM::VST3LNd32Pseudo_UPD: + case ARM::VST3LNq16Pseudo_UPD: + case ARM::VST3LNq32Pseudo_UPD: + case ARM::VST4LNd8Pseudo: + case ARM::VST4LNd16Pseudo: + case ARM::VST4LNd32Pseudo: + case ARM::VST4LNq16Pseudo: + case ARM::VST4LNq32Pseudo: + case ARM::VST4LNd8Pseudo_UPD: + case ARM::VST4LNd16Pseudo_UPD: + case ARM::VST4LNd32Pseudo_UPD: + case ARM::VST4LNq16Pseudo_UPD: + case ARM::VST4LNq32Pseudo_UPD: + ExpandLaneOp(MBBI); + return true; + + case ARM::VTBL2Pseudo: ExpandVTBL(MBBI, ARM::VTBL2, false, 2); return true; + case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false, 3); return true; + case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false, 4); return true; + case ARM::VTBX2Pseudo: ExpandVTBL(MBBI, ARM::VTBX2, true, 2); return true; + case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true, 3); return true; + case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true, 4); return true; + } + + return false; +} + +bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + MachineBasicBlock::iterator NMBBI = llvm::next(MBBI); + Modified |= ExpandMI(MBB, MBBI); + MBBI = NMBBI; + } + + return Modified; +} + +bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) { + const TargetMachine &TM = MF.getTarget(); + TII = static_cast(TM.getInstrInfo()); + TRI = TM.getRegisterInfo(); + STI = &TM.getSubtarget(); + AFI = MF.getInfo(); + + bool Modified = false; + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) + Modified |= ExpandMBB(*MFI); + return Modified; +} + +/// createARMExpandPseudoPass - returns an instance of the pseudo instruction +/// expansion pass. +FunctionPass *llvm::createARMExpandPseudoPass() { + return new ARMExpandPseudo(); +} diff --git a/final/lib/Target/ARM/ARMFastISel.cpp b/final/lib/Target/ARM/ARMFastISel.cpp new file mode 100644 index 00000000000..c7385b7a78d --- /dev/null +++ b/final/lib/Target/ARM/ARMFastISel.cpp @@ -0,0 +1,1920 @@ +//===-- ARMFastISel.cpp - ARM FastISel implementation ---------------------===// +// +// 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 ARM-specific support for the FastISel class. Some +// of the target-specific code is generated by tablegen in the file +// ARMGenFastISel.inc, which is #included here. +// +//===----------------------------------------------------------------------===// + +#include "ARM.h" +#include "ARMBaseInstrInfo.h" +#include "ARMCallingConv.h" +#include "ARMRegisterInfo.h" +#include "ARMTargetMachine.h" +#include "ARMSubtarget.h" +#include "ARMConstantPoolValue.h" +#include "llvm/CallingConv.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Support/CallSite.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GetElementPtrTypeIterator.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +static cl::opt +DisableARMFastISel("disable-arm-fast-isel", + cl::desc("Turn off experimental ARM fast-isel support"), + cl::init(false), cl::Hidden); + +extern cl::opt EnableARMLongCalls; + +namespace { + + // All possible address modes, plus some. + typedef struct Address { + enum { + RegBase, + FrameIndexBase + } BaseType; + + union { + unsigned Reg; + int FI; + } Base; + + int Offset; + unsigned Scale; + unsigned PlusReg; + + // Innocuous defaults for our address. + Address() + : BaseType(RegBase), Offset(0), Scale(0), PlusReg(0) { + Base.Reg = 0; + } + } Address; + +class ARMFastISel : public FastISel { + + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when generating code for different targets. + const ARMSubtarget *Subtarget; + const TargetMachine &TM; + const TargetInstrInfo &TII; + const TargetLowering &TLI; + ARMFunctionInfo *AFI; + + // Convenience variables to avoid some queries. + bool isThumb; + LLVMContext *Context; + + public: + explicit ARMFastISel(FunctionLoweringInfo &funcInfo) + : FastISel(funcInfo), + TM(funcInfo.MF->getTarget()), + TII(*TM.getInstrInfo()), + TLI(*TM.getTargetLowering()) { + Subtarget = &TM.getSubtarget(); + AFI = funcInfo.MF->getInfo(); + isThumb = AFI->isThumbFunction(); + Context = &funcInfo.Fn->getContext(); + } + + // Code from FastISel.cpp. + virtual unsigned FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass *RC); + virtual unsigned FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill); + virtual unsigned FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); + virtual unsigned FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm); + virtual unsigned FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm); + virtual unsigned FastEmitInst_i(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm); + virtual unsigned FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm); + virtual unsigned FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, bool Op0IsKill, + uint32_t Idx); + + // Backend specific FastISel code. + virtual bool TargetSelectInstruction(const Instruction *I); + virtual unsigned TargetMaterializeConstant(const Constant *C); + virtual unsigned TargetMaterializeAlloca(const AllocaInst *AI); + + #include "ARMGenFastISel.inc" + + // Instruction selection routines. + private: + bool SelectLoad(const Instruction *I); + bool SelectStore(const Instruction *I); + bool SelectBranch(const Instruction *I); + bool SelectCmp(const Instruction *I); + bool SelectFPExt(const Instruction *I); + bool SelectFPTrunc(const Instruction *I); + bool SelectBinaryOp(const Instruction *I, unsigned ISDOpcode); + bool SelectSIToFP(const Instruction *I); + bool SelectFPToSI(const Instruction *I); + bool SelectSDiv(const Instruction *I); + bool SelectSRem(const Instruction *I); + bool SelectCall(const Instruction *I); + bool SelectSelect(const Instruction *I); + bool SelectRet(const Instruction *I); + + // Utility routines. + private: + bool isTypeLegal(const Type *Ty, MVT &VT); + bool isLoadTypeLegal(const Type *Ty, MVT &VT); + bool ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr); + bool ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr); + bool ARMComputeAddress(const Value *Obj, Address &Addr); + void ARMSimplifyAddress(Address &Addr, EVT VT); + unsigned ARMMaterializeFP(const ConstantFP *CFP, EVT VT); + unsigned ARMMaterializeInt(const Constant *C, EVT VT); + unsigned ARMMaterializeGV(const GlobalValue *GV, EVT VT); + unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg); + unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg); + unsigned ARMSelectCallOp(const GlobalValue *GV); + + // Call handling routines. + private: + bool FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, EVT SrcVT, + unsigned &ResultReg); + CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool Return); + bool ProcessCallArgs(SmallVectorImpl &Args, + SmallVectorImpl &ArgRegs, + SmallVectorImpl &ArgVTs, + SmallVectorImpl &ArgFlags, + SmallVectorImpl &RegArgs, + CallingConv::ID CC, + unsigned &NumBytes); + bool FinishCall(MVT RetVT, SmallVectorImpl &UsedRegs, + const Instruction *I, CallingConv::ID CC, + unsigned &NumBytes); + bool ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call); + + // OptionalDef handling routines. + private: + bool DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR); + const MachineInstrBuilder &AddOptionalDefs(const MachineInstrBuilder &MIB); + void AddLoadStoreOperands(EVT VT, Address &Addr, + const MachineInstrBuilder &MIB); +}; + +} // end anonymous namespace + +#include "ARMGenCallingConv.inc" + +// DefinesOptionalPredicate - This is different from DefinesPredicate in that +// we don't care about implicit defs here, just places we'll need to add a +// default CCReg argument. Sets CPSR if we're setting CPSR instead of CCR. +bool ARMFastISel::DefinesOptionalPredicate(MachineInstr *MI, bool *CPSR) { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.hasOptionalDef()) + return false; + + // Look to see if our OptionalDef is defining CPSR or CCR. + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) continue; + if (MO.getReg() == ARM::CPSR) + *CPSR = true; + } + return true; +} + +// If the machine is predicable go ahead and add the predicate operands, if +// it needs default CC operands add those. +// TODO: If we want to support thumb1 then we'll need to deal with optional +// CPSR defs that need to be added before the remaining operands. See s_cc_out +// for descriptions why. +const MachineInstrBuilder & +ARMFastISel::AddOptionalDefs(const MachineInstrBuilder &MIB) { + MachineInstr *MI = &*MIB; + + // Do we use a predicate? + if (TII.isPredicable(MI)) + AddDefaultPred(MIB); + + // Do we optionally set a predicate? Preds is size > 0 iff the predicate + // defines CPSR. All other OptionalDefines in ARM are the CCR register. + bool CPSR = false; + if (DefinesOptionalPredicate(MI, &CPSR)) { + if (CPSR) + AddDefaultT1CC(MIB); + else + AddDefaultCC(MIB); + } + return MIB; +} + +unsigned ARMFastISel::FastEmitInst_(unsigned MachineInstOpcode, + const TargetRegisterClass* RC) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg)); + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addImm(Imm)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addFPImm(FPImm)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addFPImm(FPImm)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addImm(Imm)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addReg(Op0, Op0IsKill * RegState::Kill) + .addReg(Op1, Op1IsKill * RegState::Kill) + .addImm(Imm)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_i(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + uint64_t Imm) { + unsigned ResultReg = createResultReg(RC); + const TargetInstrDesc &II = TII.get(MachineInstOpcode); + + if (II.getNumDefs() >= 1) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II, ResultReg) + .addImm(Imm)); + else { + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, II) + .addImm(Imm)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(II.ImplicitDefs[0])); + } + return ResultReg; +} + +unsigned ARMFastISel::FastEmitInst_extractsubreg(MVT RetVT, + unsigned Op0, bool Op0IsKill, + uint32_t Idx) { + unsigned ResultReg = createResultReg(TLI.getRegClassFor(RetVT)); + assert(TargetRegisterInfo::isVirtualRegister(Op0) && + "Cannot yet extract from physregs"); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, + DL, TII.get(TargetOpcode::COPY), ResultReg) + .addReg(Op0, getKillRegState(Op0IsKill), Idx)); + return ResultReg; +} + +// TODO: Don't worry about 64-bit now, but when this is fixed remove the +// checks from the various callers. +unsigned ARMFastISel::ARMMoveToFPReg(EVT VT, unsigned SrcReg) { + if (VT == MVT::f64) return 0; + + unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VMOVRS), MoveReg) + .addReg(SrcReg)); + return MoveReg; +} + +unsigned ARMFastISel::ARMMoveToIntReg(EVT VT, unsigned SrcReg) { + if (VT == MVT::i64) return 0; + + unsigned MoveReg = createResultReg(TLI.getRegClassFor(VT)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VMOVSR), MoveReg) + .addReg(SrcReg)); + return MoveReg; +} + +// For double width floating point we need to materialize two constants +// (the high and the low) into integer registers then use a move to get +// the combined constant into an FP reg. +unsigned ARMFastISel::ARMMaterializeFP(const ConstantFP *CFP, EVT VT) { + const APFloat Val = CFP->getValueAPF(); + bool is64bit = VT == MVT::f64; + + // This checks to see if we can use VFP3 instructions to materialize + // a constant, otherwise we have to go through the constant pool. + if (TLI.isFPImmLegal(Val, VT)) { + unsigned Opc = is64bit ? ARM::FCONSTD : ARM::FCONSTS; + unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), + DestReg) + .addFPImm(CFP)); + return DestReg; + } + + // Require VFP2 for loading fp constants. + if (!Subtarget->hasVFP2()) return false; + + // MachineConstantPool wants an explicit alignment. + unsigned Align = TD.getPrefTypeAlignment(CFP->getType()); + if (Align == 0) { + // TODO: Figure out if this is correct. + Align = TD.getTypeAllocSize(CFP->getType()); + } + unsigned Idx = MCP.getConstantPoolIndex(cast(CFP), Align); + unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); + unsigned Opc = is64bit ? ARM::VLDRD : ARM::VLDRS; + + // The extra reg is for addrmode5. + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), + DestReg) + .addConstantPoolIndex(Idx) + .addReg(0)); + return DestReg; +} + +unsigned ARMFastISel::ARMMaterializeInt(const Constant *C, EVT VT) { + + // For now 32-bit only. + if (VT != MVT::i32) return false; + + unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); + + // If we can do this in a single instruction without a constant pool entry + // do so now. + const ConstantInt *CI = cast(C); + if (Subtarget->hasV6T2Ops() && isUInt<16>(CI->getSExtValue())) { + unsigned Opc = isThumb ? ARM::t2MOVi16 : ARM::MOVi16; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), DestReg) + .addImm(CI->getSExtValue())); + return DestReg; + } + + // MachineConstantPool wants an explicit alignment. + unsigned Align = TD.getPrefTypeAlignment(C->getType()); + if (Align == 0) { + // TODO: Figure out if this is correct. + Align = TD.getTypeAllocSize(C->getType()); + } + unsigned Idx = MCP.getConstantPoolIndex(C, Align); + + if (isThumb) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::t2LDRpci), DestReg) + .addConstantPoolIndex(Idx)); + else + // The extra immediate is for addrmode2. + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::LDRcp), DestReg) + .addConstantPoolIndex(Idx) + .addImm(0)); + + return DestReg; +} + +unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) { + // For now 32-bit only. + if (VT != MVT::i32) return 0; + + Reloc::Model RelocM = TM.getRelocationModel(); + + // TODO: No external globals for now. + if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) return 0; + + // TODO: Need more magic for ARM PIC. + if (!isThumb && (RelocM == Reloc::PIC_)) return 0; + + // MachineConstantPool wants an explicit alignment. + unsigned Align = TD.getPrefTypeAlignment(GV->getType()); + if (Align == 0) { + // TODO: Figure out if this is correct. + Align = TD.getTypeAllocSize(GV->getType()); + } + + // Grab index. + unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb() ? 4 : 8); + unsigned Id = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, Id, + ARMCP::CPValue, PCAdj); + unsigned Idx = MCP.getConstantPoolIndex(CPV, Align); + + // Load value. + MachineInstrBuilder MIB; + unsigned DestReg = createResultReg(TLI.getRegClassFor(VT)); + if (isThumb) { + unsigned Opc = (RelocM != Reloc::PIC_) ? ARM::t2LDRpci : ARM::t2LDRpci_pic; + MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), DestReg) + .addConstantPoolIndex(Idx); + if (RelocM == Reloc::PIC_) + MIB.addImm(Id); + } else { + // The extra immediate is for addrmode2. + MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(ARM::LDRcp), + DestReg) + .addConstantPoolIndex(Idx) + .addImm(0); + } + AddOptionalDefs(MIB); + return DestReg; +} + +unsigned ARMFastISel::TargetMaterializeConstant(const Constant *C) { + EVT VT = TLI.getValueType(C->getType(), true); + + // Only handle simple types. + if (!VT.isSimple()) return 0; + + if (const ConstantFP *CFP = dyn_cast(C)) + return ARMMaterializeFP(CFP, VT); + else if (const GlobalValue *GV = dyn_cast(C)) + return ARMMaterializeGV(GV, VT); + else if (isa(C)) + return ARMMaterializeInt(C, VT); + + return 0; +} + +unsigned ARMFastISel::TargetMaterializeAlloca(const AllocaInst *AI) { + // Don't handle dynamic allocas. + if (!FuncInfo.StaticAllocaMap.count(AI)) return 0; + + MVT VT; + if (!isLoadTypeLegal(AI->getType(), VT)) return false; + + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + + // This will get lowered later into the correct offsets and registers + // via rewriteXFrameIndex. + if (SI != FuncInfo.StaticAllocaMap.end()) { + TargetRegisterClass* RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, *FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg) + .addFrameIndex(SI->second) + .addImm(0)); + return ResultReg; + } + + return 0; +} + +bool ARMFastISel::isTypeLegal(const Type *Ty, MVT &VT) { + EVT evt = TLI.getValueType(Ty, true); + + // Only handle simple types. + if (evt == MVT::Other || !evt.isSimple()) return false; + VT = evt.getSimpleVT(); + + // Handle all legal types, i.e. a register that will directly hold this + // value. + return TLI.isTypeLegal(VT); +} + +bool ARMFastISel::isLoadTypeLegal(const Type *Ty, MVT &VT) { + if (isTypeLegal(Ty, VT)) return true; + + // If this is a type than can be sign or zero-extended to a basic operation + // go ahead and accept it now. + if (VT == MVT::i8 || VT == MVT::i16) + return true; + + return false; +} + +// Computes the address to get to an object. +bool ARMFastISel::ARMComputeAddress(const Value *Obj, Address &Addr) { + // Some boilerplate from the X86 FastISel. + const User *U = NULL; + unsigned Opcode = Instruction::UserOp1; + if (const Instruction *I = dyn_cast(Obj)) { + // Don't walk into other basic blocks unless the object is an alloca from + // another block, otherwise it may not have a virtual register assigned. + if (FuncInfo.StaticAllocaMap.count(static_cast(Obj)) || + FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { + Opcode = I->getOpcode(); + U = I; + } + } else if (const ConstantExpr *C = dyn_cast(Obj)) { + Opcode = C->getOpcode(); + U = C; + } + + if (const PointerType *Ty = dyn_cast(Obj->getType())) + if (Ty->getAddressSpace() > 255) + // Fast instruction selection doesn't support the special + // address spaces. + return false; + + switch (Opcode) { + default: + break; + case Instruction::BitCast: { + // Look through bitcasts. + return ARMComputeAddress(U->getOperand(0), Addr); + } + case Instruction::IntToPtr: { + // Look past no-op inttoptrs. + if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy()) + return ARMComputeAddress(U->getOperand(0), Addr); + break; + } + case Instruction::PtrToInt: { + // Look past no-op ptrtoints. + if (TLI.getValueType(U->getType()) == TLI.getPointerTy()) + return ARMComputeAddress(U->getOperand(0), Addr); + break; + } + case Instruction::GetElementPtr: { + Address SavedAddr = Addr; + int TmpOffset = Addr.Offset; + + // Iterate through the GEP folding the constants into offsets where + // we can. + gep_type_iterator GTI = gep_type_begin(U); + for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); + i != e; ++i, ++GTI) { + const Value *Op = *i; + if (const StructType *STy = dyn_cast(*GTI)) { + const StructLayout *SL = TD.getStructLayout(STy); + unsigned Idx = cast(Op)->getZExtValue(); + TmpOffset += SL->getElementOffset(Idx); + } else { + uint64_t S = TD.getTypeAllocSize(GTI.getIndexedType()); + for (;;) { + if (const ConstantInt *CI = dyn_cast(Op)) { + // Constant-offset addressing. + TmpOffset += CI->getSExtValue() * S; + break; + } + if (isa(Op) && + (!isa(Op) || + FuncInfo.MBBMap[cast(Op)->getParent()] + == FuncInfo.MBB) && + isa(cast(Op)->getOperand(1))) { + // An add (in the same block) with a constant operand. Fold the + // constant. + ConstantInt *CI = + cast(cast(Op)->getOperand(1)); + TmpOffset += CI->getSExtValue() * S; + // Iterate on the other operand. + Op = cast(Op)->getOperand(0); + continue; + } + // Unsupported + goto unsupported_gep; + } + } + } + + // Try to grab the base operand now. + Addr.Offset = TmpOffset; + if (ARMComputeAddress(U->getOperand(0), Addr)) return true; + + // We failed, restore everything and try the other options. + Addr = SavedAddr; + + unsupported_gep: + break; + } + case Instruction::Alloca: { + const AllocaInst *AI = cast(Obj); + DenseMap::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + Addr.BaseType = Address::FrameIndexBase; + Addr.Base.FI = SI->second; + return true; + } + break; + } + } + + // Materialize the global variable's address into a reg which can + // then be used later to load the variable. + if (const GlobalValue *GV = dyn_cast(Obj)) { + unsigned Tmp = ARMMaterializeGV(GV, TLI.getValueType(Obj->getType())); + if (Tmp == 0) return false; + + Addr.Base.Reg = Tmp; + return true; + } + + // Try to get this in a register if nothing else has worked. + if (Addr.Base.Reg == 0) Addr.Base.Reg = getRegForValue(Obj); + return Addr.Base.Reg != 0; +} + +void ARMFastISel::ARMSimplifyAddress(Address &Addr, EVT VT) { + + assert(VT.isSimple() && "Non-simple types are invalid here!"); + + bool needsLowering = false; + switch (VT.getSimpleVT().SimpleTy) { + default: + assert(false && "Unhandled load/store type!"); + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + // Integer loads/stores handle 12-bit offsets. + needsLowering = ((Addr.Offset & 0xfff) != Addr.Offset); + break; + case MVT::f32: + case MVT::f64: + // Floating point operands handle 8-bit offsets. + needsLowering = ((Addr.Offset & 0xff) != Addr.Offset); + break; + } + + // If this is a stack pointer and the offset needs to be simplified then + // put the alloca address into a register, set the base type back to + // register and continue. This should almost never happen. + if (needsLowering && Addr.BaseType == Address::FrameIndexBase) { + TargetRegisterClass *RC = isThumb ? ARM::tGPRRegisterClass : + ARM::GPRRegisterClass; + unsigned ResultReg = createResultReg(RC); + unsigned Opc = isThumb ? ARM::t2ADDri : ARM::ADDri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, *FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg) + .addFrameIndex(Addr.Base.FI) + .addImm(0)); + Addr.Base.Reg = ResultReg; + Addr.BaseType = Address::RegBase; + } + + // Since the offset is too large for the load/store instruction + // get the reg+offset into a register. + if (needsLowering) { + ARMCC::CondCodes Pred = ARMCC::AL; + unsigned PredReg = 0; + + TargetRegisterClass *RC = isThumb ? ARM::tGPRRegisterClass : + ARM::GPRRegisterClass; + unsigned BaseReg = createResultReg(RC); + + if (!isThumb) + emitARMRegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + BaseReg, Addr.Base.Reg, Addr.Offset, + Pred, PredReg, + static_cast(TII)); + else { + assert(AFI->isThumb2Function()); + emitT2RegPlusImmediate(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + BaseReg, Addr.Base.Reg, Addr.Offset, Pred, PredReg, + static_cast(TII)); + } + Addr.Offset = 0; + Addr.Base.Reg = BaseReg; + } +} + +void ARMFastISel::AddLoadStoreOperands(EVT VT, Address &Addr, + const MachineInstrBuilder &MIB) { + // addrmode5 output depends on the selection dag addressing dividing the + // offset by 4 that it then later multiplies. Do this here as well. + if (VT.getSimpleVT().SimpleTy == MVT::f32 || + VT.getSimpleVT().SimpleTy == MVT::f64) + Addr.Offset /= 4; + + // Frame base works a bit differently. Handle it separately. + if (Addr.BaseType == Address::FrameIndexBase) { + int FI = Addr.Base.FI; + int Offset = Addr.Offset; + MachineMemOperand *MMO = + FuncInfo.MF->getMachineMemOperand( + MachinePointerInfo::getFixedStack(FI, Offset), + MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), + MFI.getObjectAlignment(FI)); + // Now add the rest of the operands. + MIB.addFrameIndex(FI); + + // ARM halfword load/stores need an additional operand. + if (!isThumb && VT.getSimpleVT().SimpleTy == MVT::i16) MIB.addReg(0); + + MIB.addImm(Addr.Offset); + MIB.addMemOperand(MMO); + } else { + // Now add the rest of the operands. + MIB.addReg(Addr.Base.Reg); + + // ARM halfword load/stores need an additional operand. + if (!isThumb && VT.getSimpleVT().SimpleTy == MVT::i16) MIB.addReg(0); + + MIB.addImm(Addr.Offset); + } + AddOptionalDefs(MIB); +} + +bool ARMFastISel::ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr) { + + assert(VT.isSimple() && "Non-simple types are invalid here!"); + unsigned Opc; + TargetRegisterClass *RC; + switch (VT.getSimpleVT().SimpleTy) { + // This is mostly going to be Neon/vector support. + default: return false; + case MVT::i16: + Opc = isThumb ? ARM::t2LDRHi12 : ARM::LDRH; + RC = ARM::GPRRegisterClass; + break; + case MVT::i8: + Opc = isThumb ? ARM::t2LDRBi12 : ARM::LDRBi12; + RC = ARM::GPRRegisterClass; + break; + case MVT::i32: + Opc = isThumb ? ARM::t2LDRi12 : ARM::LDRi12; + RC = ARM::GPRRegisterClass; + break; + case MVT::f32: + Opc = ARM::VLDRS; + RC = TLI.getRegClassFor(VT); + break; + case MVT::f64: + Opc = ARM::VLDRD; + RC = TLI.getRegClassFor(VT); + break; + } + // Simplify this down to something we can handle. + ARMSimplifyAddress(Addr, VT); + + // Create the base instruction, then add the operands. + ResultReg = createResultReg(RC); + MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg); + AddLoadStoreOperands(VT, Addr, MIB); + return true; +} + +bool ARMFastISel::SelectLoad(const Instruction *I) { + // Verify we have a legal type before going any further. + MVT VT; + if (!isLoadTypeLegal(I->getType(), VT)) + return false; + + // See if we can handle this address. + Address Addr; + if (!ARMComputeAddress(I->getOperand(0), Addr)) return false; + + unsigned ResultReg; + if (!ARMEmitLoad(VT, ResultReg, Addr)) return false; + UpdateValueMap(I, ResultReg); + return true; +} + +bool ARMFastISel::ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr) { + unsigned StrOpc; + switch (VT.getSimpleVT().SimpleTy) { + // This is mostly going to be Neon/vector support. + default: return false; + case MVT::i1: { + unsigned Res = createResultReg(isThumb ? ARM::tGPRRegisterClass : + ARM::GPRRegisterClass); + unsigned Opc = isThumb ? ARM::t2ANDri : ARM::ANDri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), Res) + .addReg(SrcReg).addImm(1)); + SrcReg = Res; + } // Fallthrough here. + case MVT::i8: + StrOpc = isThumb ? ARM::t2STRBi12 : ARM::STRBi12; + break; + case MVT::i16: + StrOpc = isThumb ? ARM::t2STRHi12 : ARM::STRH; + break; + case MVT::i32: + StrOpc = isThumb ? ARM::t2STRi12 : ARM::STRi12; + break; + case MVT::f32: + if (!Subtarget->hasVFP2()) return false; + StrOpc = ARM::VSTRS; + break; + case MVT::f64: + if (!Subtarget->hasVFP2()) return false; + StrOpc = ARM::VSTRD; + break; + } + // Simplify this down to something we can handle. + ARMSimplifyAddress(Addr, VT); + + // Create the base instruction, then add the operands. + MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(StrOpc)) + .addReg(SrcReg, getKillRegState(true)); + AddLoadStoreOperands(VT, Addr, MIB); + return true; +} + +bool ARMFastISel::SelectStore(const Instruction *I) { + Value *Op0 = I->getOperand(0); + unsigned SrcReg = 0; + + // Verify we have a legal type before going any further. + MVT VT; + if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT)) + return false; + + // Get the value to be stored into a register. + SrcReg = getRegForValue(Op0); + if (SrcReg == 0) return false; + + // See if we can handle this address. + Address Addr; + if (!ARMComputeAddress(I->getOperand(1), Addr)) + return false; + + if (!ARMEmitStore(VT, SrcReg, Addr)) return false; + return true; +} + +static ARMCC::CondCodes getComparePred(CmpInst::Predicate Pred) { + switch (Pred) { + // Needs two compares... + case CmpInst::FCMP_ONE: + case CmpInst::FCMP_UEQ: + default: + // AL is our "false" for now. The other two need more compares. + return ARMCC::AL; + case CmpInst::ICMP_EQ: + case CmpInst::FCMP_OEQ: + return ARMCC::EQ; + case CmpInst::ICMP_SGT: + case CmpInst::FCMP_OGT: + return ARMCC::GT; + case CmpInst::ICMP_SGE: + case CmpInst::FCMP_OGE: + return ARMCC::GE; + case CmpInst::ICMP_UGT: + case CmpInst::FCMP_UGT: + return ARMCC::HI; + case CmpInst::FCMP_OLT: + return ARMCC::MI; + case CmpInst::ICMP_ULE: + case CmpInst::FCMP_OLE: + return ARMCC::LS; + case CmpInst::FCMP_ORD: + return ARMCC::VC; + case CmpInst::FCMP_UNO: + return ARMCC::VS; + case CmpInst::FCMP_UGE: + return ARMCC::PL; + case CmpInst::ICMP_SLT: + case CmpInst::FCMP_ULT: + return ARMCC::LT; + case CmpInst::ICMP_SLE: + case CmpInst::FCMP_ULE: + return ARMCC::LE; + case CmpInst::FCMP_UNE: + case CmpInst::ICMP_NE: + return ARMCC::NE; + case CmpInst::ICMP_UGE: + return ARMCC::HS; + case CmpInst::ICMP_ULT: + return ARMCC::LO; + } +} + +bool ARMFastISel::SelectBranch(const Instruction *I) { + const BranchInst *BI = cast(I); + MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; + MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; + + // Simple branch support. + + // If we can, avoid recomputing the compare - redoing it could lead to wonky + // behavior. + // TODO: Factor this out. + if (const CmpInst *CI = dyn_cast(BI->getCondition())) { + if (CI->hasOneUse() && (CI->getParent() == I->getParent())) { + MVT VT; + const Type *Ty = CI->getOperand(0)->getType(); + if (!isTypeLegal(Ty, VT)) + return false; + + bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); + if (isFloat && !Subtarget->hasVFP2()) + return false; + + unsigned CmpOpc; + switch (VT.SimpleTy) { + default: return false; + // TODO: Verify compares. + case MVT::f32: + CmpOpc = ARM::VCMPES; + break; + case MVT::f64: + CmpOpc = ARM::VCMPED; + break; + case MVT::i32: + CmpOpc = isThumb ? ARM::t2CMPrr : ARM::CMPrr; + break; + } + + // Get the compare predicate. + ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate()); + + // We may not handle every CC for now. + if (ARMPred == ARMCC::AL) return false; + + unsigned Arg1 = getRegForValue(CI->getOperand(0)); + if (Arg1 == 0) return false; + + unsigned Arg2 = getRegForValue(CI->getOperand(1)); + if (Arg2 == 0) return false; + + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(CmpOpc)) + .addReg(Arg1).addReg(Arg2)); + + // For floating point we need to move the result to a comparison register + // that we can then use for branches. + if (isFloat) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::FMSTAT))); + + unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(BrOpc)) + .addMBB(TBB).addImm(ARMPred).addReg(ARM::CPSR); + FastEmitBranch(FBB, DL); + FuncInfo.MBB->addSuccessor(TBB); + return true; + } + } + + unsigned CmpReg = getRegForValue(BI->getCondition()); + if (CmpReg == 0) return false; + + // Re-set the flags just in case. + unsigned CmpOpc = isThumb ? ARM::t2CMPri : ARM::CMPri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc)) + .addReg(CmpReg).addImm(0)); + + unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(BrOpc)) + .addMBB(TBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + FastEmitBranch(FBB, DL); + FuncInfo.MBB->addSuccessor(TBB); + return true; +} + +bool ARMFastISel::SelectCmp(const Instruction *I) { + const CmpInst *CI = cast(I); + + MVT VT; + const Type *Ty = CI->getOperand(0)->getType(); + if (!isTypeLegal(Ty, VT)) + return false; + + bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); + if (isFloat && !Subtarget->hasVFP2()) + return false; + + unsigned CmpOpc; + unsigned CondReg; + switch (VT.SimpleTy) { + default: return false; + // TODO: Verify compares. + case MVT::f32: + CmpOpc = ARM::VCMPES; + CondReg = ARM::FPSCR; + break; + case MVT::f64: + CmpOpc = ARM::VCMPED; + CondReg = ARM::FPSCR; + break; + case MVT::i32: + CmpOpc = isThumb ? ARM::t2CMPrr : ARM::CMPrr; + CondReg = ARM::CPSR; + break; + } + + // Get the compare predicate. + ARMCC::CondCodes ARMPred = getComparePred(CI->getPredicate()); + + // We may not handle every CC for now. + if (ARMPred == ARMCC::AL) return false; + + unsigned Arg1 = getRegForValue(CI->getOperand(0)); + if (Arg1 == 0) return false; + + unsigned Arg2 = getRegForValue(CI->getOperand(1)); + if (Arg2 == 0) return false; + + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc)) + .addReg(Arg1).addReg(Arg2)); + + // For floating point we need to move the result to a comparison register + // that we can then use for branches. + if (isFloat) + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::FMSTAT))); + + // Now set a register based on the comparison. Explicitly set the predicates + // here. + unsigned MovCCOpc = isThumb ? ARM::t2MOVCCi : ARM::MOVCCi; + TargetRegisterClass *RC = isThumb ? ARM::rGPRRegisterClass + : ARM::GPRRegisterClass; + unsigned DestReg = createResultReg(RC); + Constant *Zero + = ConstantInt::get(Type::getInt32Ty(*Context), 0); + unsigned ZeroReg = TargetMaterializeConstant(Zero); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(MovCCOpc), DestReg) + .addReg(ZeroReg).addImm(1) + .addImm(ARMPred).addReg(CondReg); + + UpdateValueMap(I, DestReg); + return true; +} + +bool ARMFastISel::SelectFPExt(const Instruction *I) { + // Make sure we have VFP and that we're extending float to double. + if (!Subtarget->hasVFP2()) return false; + + Value *V = I->getOperand(0); + if (!I->getType()->isDoubleTy() || + !V->getType()->isFloatTy()) return false; + + unsigned Op = getRegForValue(V); + if (Op == 0) return false; + + unsigned Result = createResultReg(ARM::DPRRegisterClass); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VCVTDS), Result) + .addReg(Op)); + UpdateValueMap(I, Result); + return true; +} + +bool ARMFastISel::SelectFPTrunc(const Instruction *I) { + // Make sure we have VFP and that we're truncating double to float. + if (!Subtarget->hasVFP2()) return false; + + Value *V = I->getOperand(0); + if (!(I->getType()->isFloatTy() && + V->getType()->isDoubleTy())) return false; + + unsigned Op = getRegForValue(V); + if (Op == 0) return false; + + unsigned Result = createResultReg(ARM::SPRRegisterClass); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VCVTSD), Result) + .addReg(Op)); + UpdateValueMap(I, Result); + return true; +} + +bool ARMFastISel::SelectSIToFP(const Instruction *I) { + // Make sure we have VFP. + if (!Subtarget->hasVFP2()) return false; + + MVT DstVT; + const Type *Ty = I->getType(); + if (!isTypeLegal(Ty, DstVT)) + return false; + + unsigned Op = getRegForValue(I->getOperand(0)); + if (Op == 0) return false; + + // The conversion routine works on fp-reg to fp-reg and the operand above + // was an integer, move it to the fp registers if possible. + unsigned FP = ARMMoveToFPReg(MVT::f32, Op); + if (FP == 0) return false; + + unsigned Opc; + if (Ty->isFloatTy()) Opc = ARM::VSITOS; + else if (Ty->isDoubleTy()) Opc = ARM::VSITOD; + else return 0; + + unsigned ResultReg = createResultReg(TLI.getRegClassFor(DstVT)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), + ResultReg) + .addReg(FP)); + UpdateValueMap(I, ResultReg); + return true; +} + +bool ARMFastISel::SelectFPToSI(const Instruction *I) { + // Make sure we have VFP. + if (!Subtarget->hasVFP2()) return false; + + MVT DstVT; + const Type *RetTy = I->getType(); + if (!isTypeLegal(RetTy, DstVT)) + return false; + + unsigned Op = getRegForValue(I->getOperand(0)); + if (Op == 0) return false; + + unsigned Opc; + const Type *OpTy = I->getOperand(0)->getType(); + if (OpTy->isFloatTy()) Opc = ARM::VTOSIZS; + else if (OpTy->isDoubleTy()) Opc = ARM::VTOSIZD; + else return 0; + + // f64->s32 or f32->s32 both need an intermediate f32 reg. + unsigned ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(Opc), + ResultReg) + .addReg(Op)); + + // This result needs to be in an integer register, but the conversion only + // takes place in fp-regs. + unsigned IntReg = ARMMoveToIntReg(DstVT, ResultReg); + if (IntReg == 0) return false; + + UpdateValueMap(I, IntReg); + return true; +} + +bool ARMFastISel::SelectSelect(const Instruction *I) { + MVT VT; + if (!isTypeLegal(I->getType(), VT)) + return false; + + // Things need to be register sized for register moves. + if (VT != MVT::i32) return false; + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + + unsigned CondReg = getRegForValue(I->getOperand(0)); + if (CondReg == 0) return false; + unsigned Op1Reg = getRegForValue(I->getOperand(1)); + if (Op1Reg == 0) return false; + unsigned Op2Reg = getRegForValue(I->getOperand(2)); + if (Op2Reg == 0) return false; + + unsigned CmpOpc = isThumb ? ARM::t2TSTri : ARM::TSTri; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc)) + .addReg(CondReg).addImm(1)); + unsigned ResultReg = createResultReg(RC); + unsigned MovCCOpc = isThumb ? ARM::t2MOVCCr : ARM::MOVCCr; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(MovCCOpc), ResultReg) + .addReg(Op1Reg).addReg(Op2Reg) + .addImm(ARMCC::EQ).addReg(ARM::CPSR); + UpdateValueMap(I, ResultReg); + return true; +} + +bool ARMFastISel::SelectSDiv(const Instruction *I) { + MVT VT; + const Type *Ty = I->getType(); + if (!isTypeLegal(Ty, VT)) + return false; + + // If we have integer div support we should have selected this automagically. + // In case we have a real miss go ahead and return false and we'll pick + // it up later. + if (Subtarget->hasDivide()) return false; + + // Otherwise emit a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i8) + LC = RTLIB::SDIV_I8; + else if (VT == MVT::i16) + LC = RTLIB::SDIV_I16; + else if (VT == MVT::i32) + LC = RTLIB::SDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::SDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::SDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!"); + + return ARMEmitLibcall(I, LC); +} + +bool ARMFastISel::SelectSRem(const Instruction *I) { + MVT VT; + const Type *Ty = I->getType(); + if (!isTypeLegal(Ty, VT)) + return false; + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i8) + LC = RTLIB::SREM_I8; + else if (VT == MVT::i16) + LC = RTLIB::SREM_I16; + else if (VT == MVT::i32) + LC = RTLIB::SREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::SREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::SREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!"); + + return ARMEmitLibcall(I, LC); +} + +bool ARMFastISel::SelectBinaryOp(const Instruction *I, unsigned ISDOpcode) { + EVT VT = TLI.getValueType(I->getType(), true); + + // We can get here in the case when we want to use NEON for our fp + // operations, but can't figure out how to. Just use the vfp instructions + // if we have them. + // FIXME: It'd be nice to use NEON instructions. + const Type *Ty = I->getType(); + bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); + if (isFloat && !Subtarget->hasVFP2()) + return false; + + unsigned Op1 = getRegForValue(I->getOperand(0)); + if (Op1 == 0) return false; + + unsigned Op2 = getRegForValue(I->getOperand(1)); + if (Op2 == 0) return false; + + unsigned Opc; + bool is64bit = VT == MVT::f64 || VT == MVT::i64; + switch (ISDOpcode) { + default: return false; + case ISD::FADD: + Opc = is64bit ? ARM::VADDD : ARM::VADDS; + break; + case ISD::FSUB: + Opc = is64bit ? ARM::VSUBD : ARM::VSUBS; + break; + case ISD::FMUL: + Opc = is64bit ? ARM::VMULD : ARM::VMULS; + break; + } + unsigned ResultReg = createResultReg(TLI.getRegClassFor(VT)); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(Opc), ResultReg) + .addReg(Op1).addReg(Op2)); + UpdateValueMap(I, ResultReg); + return true; +} + +// Call Handling Code + +bool ARMFastISel::FastEmitExtend(ISD::NodeType Opc, EVT DstVT, unsigned Src, + EVT SrcVT, unsigned &ResultReg) { + unsigned RR = FastEmit_r(SrcVT.getSimpleVT(), DstVT.getSimpleVT(), Opc, + Src, /*TODO: Kill=*/false); + + if (RR != 0) { + ResultReg = RR; + return true; + } else + return false; +} + +// This is largely taken directly from CCAssignFnForNode - we don't support +// varargs in FastISel so that part has been removed. +// TODO: We may not support all of this. +CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC, bool Return) { + switch (CC) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::Fast: + // Ignore fastcc. Silence compiler warnings. + (void)RetFastCC_ARM_APCS; + (void)FastCC_ARM_APCS; + // Fallthrough + case CallingConv::C: + // Use target triple & subtarget features to do actual dispatch. + if (Subtarget->isAAPCS_ABI()) { + if (Subtarget->hasVFP2() && + FloatABIType == FloatABI::Hard) + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + else + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + } else + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + case CallingConv::ARM_AAPCS_VFP: + return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP); + case CallingConv::ARM_AAPCS: + return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS); + case CallingConv::ARM_APCS: + return (Return ? RetCC_ARM_APCS: CC_ARM_APCS); + } +} + +bool ARMFastISel::ProcessCallArgs(SmallVectorImpl &Args, + SmallVectorImpl &ArgRegs, + SmallVectorImpl &ArgVTs, + SmallVectorImpl &ArgFlags, + SmallVectorImpl &RegArgs, + CallingConv::ID CC, + unsigned &NumBytes) { + SmallVector ArgLocs; + CCState CCInfo(CC, false, TM, ArgLocs, *Context); + CCInfo.AnalyzeCallOperands(ArgVTs, ArgFlags, CCAssignFnForCall(CC, false)); + + // Get a count of how many bytes are to be pushed on the stack. + NumBytes = CCInfo.getNextStackOffset(); + + // Issue CALLSEQ_START + unsigned AdjStackDown = TM.getRegisterInfo()->getCallFrameSetupOpcode(); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(AdjStackDown)) + .addImm(NumBytes)); + + // Process the args. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + unsigned Arg = ArgRegs[VA.getValNo()]; + MVT ArgVT = ArgVTs[VA.getValNo()]; + + // We don't handle NEON/vector parameters yet. + if (ArgVT.isVector() || ArgVT.getSizeInBits() > 64) + return false; + + // Handle arg promotion, etc. + switch (VA.getLocInfo()) { + case CCValAssign::Full: break; + case CCValAssign::SExt: { + bool Emitted = FastEmitExtend(ISD::SIGN_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + assert(Emitted && "Failed to emit a sext!"); (void)Emitted; + Emitted = true; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::ZExt: { + bool Emitted = FastEmitExtend(ISD::ZERO_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + assert(Emitted && "Failed to emit a zext!"); (void)Emitted; + Emitted = true; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::AExt: { + bool Emitted = FastEmitExtend(ISD::ANY_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + if (!Emitted) + Emitted = FastEmitExtend(ISD::ZERO_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + if (!Emitted) + Emitted = FastEmitExtend(ISD::SIGN_EXTEND, VA.getLocVT(), + Arg, ArgVT, Arg); + + assert(Emitted && "Failed to emit a aext!"); (void)Emitted; + ArgVT = VA.getLocVT(); + break; + } + case CCValAssign::BCvt: { + unsigned BC = FastEmit_r(ArgVT, VA.getLocVT(), ISD::BITCAST, Arg, + /*TODO: Kill=*/false); + assert(BC != 0 && "Failed to emit a bitcast!"); + Arg = BC; + ArgVT = VA.getLocVT(); + break; + } + default: llvm_unreachable("Unknown arg promotion!"); + } + + // Now copy/store arg to correct locations. + if (VA.isRegLoc() && !VA.needsCustom()) { + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + VA.getLocReg()) + .addReg(Arg); + RegArgs.push_back(VA.getLocReg()); + } else if (VA.needsCustom()) { + // TODO: We need custom lowering for vector (v2f64) args. + if (VA.getLocVT() != MVT::f64) return false; + + CCValAssign &NextVA = ArgLocs[++i]; + + // TODO: Only handle register args for now. + if(!(VA.isRegLoc() && NextVA.isRegLoc())) return false; + + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VMOVRRD), VA.getLocReg()) + .addReg(NextVA.getLocReg(), RegState::Define) + .addReg(Arg)); + RegArgs.push_back(VA.getLocReg()); + RegArgs.push_back(NextVA.getLocReg()); + } else { + assert(VA.isMemLoc()); + // Need to store on the stack. + Address Addr; + Addr.BaseType = Address::RegBase; + Addr.Base.Reg = ARM::SP; + Addr.Offset = VA.getLocMemOffset(); + + if (!ARMEmitStore(ArgVT, Arg, Addr)) return false; + } + } + return true; +} + +bool ARMFastISel::FinishCall(MVT RetVT, SmallVectorImpl &UsedRegs, + const Instruction *I, CallingConv::ID CC, + unsigned &NumBytes) { + // Issue CALLSEQ_END + unsigned AdjStackUp = TM.getRegisterInfo()->getCallFrameDestroyOpcode(); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(AdjStackUp)) + .addImm(NumBytes).addImm(0)); + + // Now the return value. + if (RetVT != MVT::isVoid) { + SmallVector RVLocs; + CCState CCInfo(CC, false, TM, RVLocs, *Context); + CCInfo.AnalyzeCallResult(RetVT, CCAssignFnForCall(CC, true)); + + // Copy all of the result registers out of their specified physreg. + if (RVLocs.size() == 2 && RetVT == MVT::f64) { + // For this move we copy into two registers and then move into the + // double fp reg we want. + EVT DestVT = RVLocs[0].getValVT(); + TargetRegisterClass* DstRC = TLI.getRegClassFor(DestVT); + unsigned ResultReg = createResultReg(DstRC); + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(ARM::VMOVDRR), ResultReg) + .addReg(RVLocs[0].getLocReg()) + .addReg(RVLocs[1].getLocReg())); + + UsedRegs.push_back(RVLocs[0].getLocReg()); + UsedRegs.push_back(RVLocs[1].getLocReg()); + + // Finally update the result. + UpdateValueMap(I, ResultReg); + } else { + assert(RVLocs.size() == 1 &&"Can't handle non-double multi-reg retvals!"); + EVT CopyVT = RVLocs[0].getValVT(); + TargetRegisterClass* DstRC = TLI.getRegClassFor(CopyVT); + + unsigned ResultReg = createResultReg(DstRC); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + ResultReg).addReg(RVLocs[0].getLocReg()); + UsedRegs.push_back(RVLocs[0].getLocReg()); + + // Finally update the result. + UpdateValueMap(I, ResultReg); + } + } + + return true; +} + +bool ARMFastISel::SelectRet(const Instruction *I) { + const ReturnInst *Ret = cast(I); + const Function &F = *I->getParent()->getParent(); + + if (!FuncInfo.CanLowerReturn) + return false; + + if (F.isVarArg()) + return false; + + CallingConv::ID CC = F.getCallingConv(); + if (Ret->getNumOperands() > 0) { + SmallVector Outs; + GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(), + Outs, TLI); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ValLocs; + CCState CCInfo(CC, F.isVarArg(), TM, ValLocs, I->getContext()); + CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC, true /* is Ret */)); + + const Value *RV = Ret->getOperand(0); + unsigned Reg = getRegForValue(RV); + if (Reg == 0) + return false; + + // Only handle a single return value for now. + if (ValLocs.size() != 1) + return false; + + CCValAssign &VA = ValLocs[0]; + + // Don't bother handling odd stuff for now. + if (VA.getLocInfo() != CCValAssign::Full) + return false; + // Only handle register returns for now. + if (!VA.isRegLoc()) + return false; + // TODO: For now, don't try to handle cases where getLocInfo() + // says Full but the types don't match. + if (TLI.getValueType(RV->getType()) != VA.getValVT()) + return false; + + // Make the copy. + unsigned SrcReg = Reg + VA.getValNo(); + unsigned DstReg = VA.getLocReg(); + const TargetRegisterClass* SrcRC = MRI.getRegClass(SrcReg); + // Avoid a cross-class copy. This is very unlikely. + if (!SrcRC->contains(DstReg)) + return false; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY), + DstReg).addReg(SrcReg); + + // Mark the register as live out of the function. + MRI.addLiveOut(VA.getLocReg()); + } + + unsigned RetOpc = isThumb ? ARM::tBX_RET : ARM::BX_RET; + AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(RetOpc))); + return true; +} + +unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) { + + // Depend our opcode for thumb on whether or not we're targeting an + // externally callable function. For libcalls we'll just pass a NULL GV + // in here. + bool isExternal = false; + if (!GV || GV->hasExternalLinkage()) isExternal = true; + + // Darwin needs the r9 versions of the opcodes. + bool isDarwin = Subtarget->isTargetDarwin(); + if (isThumb && isExternal) { + return isDarwin ? ARM::tBLXi_r9 : ARM::tBLXi; + } else if (isThumb) { + return isDarwin ? ARM::tBLr9 : ARM::tBL; + } else { + return isDarwin ? ARM::BLr9 : ARM::BL; + } +} + +// A quick function that will emit a call for a named libcall in F with the +// vector of passed arguments for the Instruction in I. We can assume that we +// can emit a call for any libcall we can produce. This is an abridged version +// of the full call infrastructure since we won't need to worry about things +// like computed function pointers or strange arguments at call sites. +// TODO: Try to unify this and the normal call bits for ARM, then try to unify +// with X86. +bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) { + CallingConv::ID CC = TLI.getLibcallCallingConv(Call); + + // Handle *simple* calls for now. + const Type *RetTy = I->getType(); + MVT RetVT; + if (RetTy->isVoidTy()) + RetVT = MVT::isVoid; + else if (!isTypeLegal(RetTy, RetVT)) + return false; + + // For now we're using BLX etc on the assumption that we have v5t ops. + if (!Subtarget->hasV5TOps()) return false; + + // TODO: For now if we have long calls specified we don't handle the call. + if (EnableARMLongCalls) return false; + + // Set up the argument vectors. + SmallVector Args; + SmallVector ArgRegs; + SmallVector ArgVTs; + SmallVector ArgFlags; + Args.reserve(I->getNumOperands()); + ArgRegs.reserve(I->getNumOperands()); + ArgVTs.reserve(I->getNumOperands()); + ArgFlags.reserve(I->getNumOperands()); + for (unsigned i = 0; i < I->getNumOperands(); ++i) { + Value *Op = I->getOperand(i); + unsigned Arg = getRegForValue(Op); + if (Arg == 0) return false; + + const Type *ArgTy = Op->getType(); + MVT ArgVT; + if (!isTypeLegal(ArgTy, ArgVT)) return false; + + ISD::ArgFlagsTy Flags; + unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy); + Flags.setOrigAlign(OriginalAlignment); + + Args.push_back(Op); + ArgRegs.push_back(Arg); + ArgVTs.push_back(ArgVT); + ArgFlags.push_back(Flags); + } + + // Handle the arguments now that we've gotten them. + SmallVector RegArgs; + unsigned NumBytes; + if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes)) + return false; + + // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. + // TODO: Turn this into the table of arm call ops. + MachineInstrBuilder MIB; + unsigned CallOpc = ARMSelectCallOp(NULL); + if(isThumb) + // Explicitly adding the predicate here. + MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(CallOpc))) + .addExternalSymbol(TLI.getLibcallName(Call)); + else + // Explicitly adding the predicate here. + MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(CallOpc)) + .addExternalSymbol(TLI.getLibcallName(Call))); + + // Add implicit physical register uses to the call. + for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) + MIB.addReg(RegArgs[i]); + + // Finish off the call including any return values. + SmallVector UsedRegs; + if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes)) return false; + + // Set all unused physreg defs as dead. + static_cast(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI); + + return true; +} + +bool ARMFastISel::SelectCall(const Instruction *I) { + const CallInst *CI = cast(I); + const Value *Callee = CI->getCalledValue(); + + // Can't handle inline asm or worry about intrinsics yet. + if (isa(Callee) || isa(CI)) return false; + + // Only handle global variable Callees that are direct calls. + const GlobalValue *GV = dyn_cast(Callee); + if (!GV || Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel())) + return false; + + // Check the calling convention. + ImmutableCallSite CS(CI); + CallingConv::ID CC = CS.getCallingConv(); + + // TODO: Avoid some calling conventions? + + // Let SDISel handle vararg functions. + const PointerType *PT = cast(CS.getCalledValue()->getType()); + const FunctionType *FTy = cast(PT->getElementType()); + if (FTy->isVarArg()) + return false; + + // Handle *simple* calls for now. + const Type *RetTy = I->getType(); + MVT RetVT; + if (RetTy->isVoidTy()) + RetVT = MVT::isVoid; + else if (!isTypeLegal(RetTy, RetVT)) + return false; + + // For now we're using BLX etc on the assumption that we have v5t ops. + // TODO: Maybe? + if (!Subtarget->hasV5TOps()) return false; + + // TODO: For now if we have long calls specified we don't handle the call. + if (EnableARMLongCalls) return false; + + // Set up the argument vectors. + SmallVector Args; + SmallVector ArgRegs; + SmallVector ArgVTs; + SmallVector ArgFlags; + Args.reserve(CS.arg_size()); + ArgRegs.reserve(CS.arg_size()); + ArgVTs.reserve(CS.arg_size()); + ArgFlags.reserve(CS.arg_size()); + for (ImmutableCallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end(); + i != e; ++i) { + unsigned Arg = getRegForValue(*i); + + if (Arg == 0) + return false; + ISD::ArgFlagsTy Flags; + unsigned AttrInd = i - CS.arg_begin() + 1; + if (CS.paramHasAttr(AttrInd, Attribute::SExt)) + Flags.setSExt(); + if (CS.paramHasAttr(AttrInd, Attribute::ZExt)) + Flags.setZExt(); + + // FIXME: Only handle *easy* calls for now. + if (CS.paramHasAttr(AttrInd, Attribute::InReg) || + CS.paramHasAttr(AttrInd, Attribute::StructRet) || + CS.paramHasAttr(AttrInd, Attribute::Nest) || + CS.paramHasAttr(AttrInd, Attribute::ByVal)) + return false; + + const Type *ArgTy = (*i)->getType(); + MVT ArgVT; + if (!isTypeLegal(ArgTy, ArgVT)) + return false; + unsigned OriginalAlignment = TD.getABITypeAlignment(ArgTy); + Flags.setOrigAlign(OriginalAlignment); + + Args.push_back(*i); + ArgRegs.push_back(Arg); + ArgVTs.push_back(ArgVT); + ArgFlags.push_back(Flags); + } + + // Handle the arguments now that we've gotten them. + SmallVector RegArgs; + unsigned NumBytes; + if (!ProcessCallArgs(Args, ArgRegs, ArgVTs, ArgFlags, RegArgs, CC, NumBytes)) + return false; + + // Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops. + // TODO: Turn this into the table of arm call ops. + MachineInstrBuilder MIB; + unsigned CallOpc = ARMSelectCallOp(GV); + // Explicitly adding the predicate here. + if(isThumb) + // Explicitly adding the predicate here. + MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(CallOpc))) + .addGlobalAddress(GV, 0, 0); + else + // Explicitly adding the predicate here. + MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, + TII.get(CallOpc)) + .addGlobalAddress(GV, 0, 0)); + + // Add implicit physical register uses to the call. + for (unsigned i = 0, e = RegArgs.size(); i != e; ++i) + MIB.addReg(RegArgs[i]); + + // Finish off the call including any return values. + SmallVector UsedRegs; + if (!FinishCall(RetVT, UsedRegs, I, CC, NumBytes)) return false; + + // Set all unused physreg defs as dead. + static_cast(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI); + + return true; + +} + +// TODO: SoftFP support. +bool ARMFastISel::TargetSelectInstruction(const Instruction *I) { + + switch (I->getOpcode()) { + case Instruction::Load: + return SelectLoad(I); + case Instruction::Store: + return SelectStore(I); + case Instruction::Br: + return SelectBranch(I); + case Instruction::ICmp: + case Instruction::FCmp: + return SelectCmp(I); + case Instruction::FPExt: + return SelectFPExt(I); + case Instruction::FPTrunc: + return SelectFPTrunc(I); + case Instruction::SIToFP: + return SelectSIToFP(I); + case Instruction::FPToSI: + return SelectFPToSI(I); + case Instruction::FAdd: + return SelectBinaryOp(I, ISD::FADD); + case Instruction::FSub: + return SelectBinaryOp(I, ISD::FSUB); + case Instruction::FMul: + return SelectBinaryOp(I, ISD::FMUL); + case Instruction::SDiv: + return SelectSDiv(I); + case Instruction::SRem: + return SelectSRem(I); + case Instruction::Call: + return SelectCall(I); + case Instruction::Select: + return SelectSelect(I); + case Instruction::Ret: + return SelectRet(I); + default: break; + } + return false; +} + +namespace llvm { + llvm::FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo) { + // Completely untested on non-darwin. + const TargetMachine &TM = funcInfo.MF->getTarget(); + + // Darwin and thumb1 only for now. + const ARMSubtarget *Subtarget = &TM.getSubtarget(); + if (Subtarget->isTargetDarwin() && !Subtarget->isThumb1Only() && + !DisableARMFastISel) + return new ARMFastISel(funcInfo); + return 0; + } +} diff --git a/final/lib/Target/ARM/ARMFixupKinds.h b/final/lib/Target/ARM/ARMFixupKinds.h new file mode 100644 index 00000000000..3d175e38690 --- /dev/null +++ b/final/lib/Target/ARM/ARMFixupKinds.h @@ -0,0 +1,97 @@ +//===-- ARM/ARMFixupKinds.h - ARM Specific Fixup Entries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ARM_ARMFIXUPKINDS_H +#define LLVM_ARM_ARMFIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace ARM { +enum Fixups { + // fixup_arm_ldst_pcrel_12 - 12-bit PC relative relocation for symbol + // addresses + fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind, + + // fixup_t2_ldst_pcrel_12 - Equivalent to fixup_arm_ldst_pcrel_12, with + // the 16-bit halfwords reordered. + fixup_t2_ldst_pcrel_12, + + // fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses + // used in VFP instructions where the lower 2 bits are not encoded + // (so it's encoded as an 8-bit immediate). + fixup_arm_pcrel_10, + // fixup_t2_pcrel_10 - Equivalent to fixup_arm_pcrel_10, accounting for + // the short-swapped encoding of Thumb2 instructions. + fixup_t2_pcrel_10, + // fixup_thumb_adr_pcrel_10 - 10-bit PC relative relocation for symbol + // addresses where the lower 2 bits are not encoded (so it's encoded as an + // 8-bit immediate). + fixup_thumb_adr_pcrel_10, + // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR + // instruction. + fixup_arm_adr_pcrel_12, + // fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR + // instruction. + fixup_t2_adr_pcrel_12, + // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch + // instructions. + fixup_arm_condbranch, + // fixup_arm_uncondbranch - 24-bit PC relative relocation for + // branch instructions. (unconditional) + fixup_arm_uncondbranch, + // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct + // uconditional branch instructions. + fixup_t2_condbranch, + // fixup_t2_uncondbranch - 20-bit PC relative relocation for Thumb2 direct + // branch unconditional branch instructions. + fixup_t2_uncondbranch, + + // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions. + fixup_arm_thumb_br, + + // fixup_arm_thumb_blx - Fixup for Thumb BL instructions. + fixup_arm_thumb_bl, + + // fixup_arm_thumb_blx - Fixup for Thumb BLX instructions. + fixup_arm_thumb_blx, + + // fixup_arm_thumb_cb - Fixup for Thumb branch instructions. + fixup_arm_thumb_cb, + + // fixup_arm_thumb_cp - Fixup for Thumb load/store from constant pool instrs. + fixup_arm_thumb_cp, + + // fixup_arm_thumb_bcc - Fixup for Thumb conditional branching instructions. + fixup_arm_thumb_bcc, + + // The next two are for the movt/movw pair + // the 16bit imm field are split into imm{15-12} and imm{11-0} + fixup_arm_movt_hi16, // :upper16: + fixup_arm_movw_lo16, // :lower16: + fixup_t2_movt_hi16, // :upper16: + fixup_t2_movw_lo16, // :lower16: + + // It is possible to create an "immediate" that happens to be pcrel. + // movw r0, :lower16:Foo-(Bar+8) and movt r0, :upper16:Foo-(Bar+8) + // result in different reloc tags than the above two. + // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC + fixup_arm_movt_hi16_pcrel, // :upper16: + fixup_arm_movw_lo16_pcrel, // :lower16: + fixup_t2_movt_hi16_pcrel, // :upper16: + fixup_t2_movw_lo16_pcrel, // :lower16: + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +}; +} +} + +#endif diff --git a/final/lib/Target/ARM/ARMFrameLowering.cpp b/final/lib/Target/ARM/ARMFrameLowering.cpp new file mode 100644 index 00000000000..4ade29c2d15 --- /dev/null +++ b/final/lib/Target/ARM/ARMFrameLowering.cpp @@ -0,0 +1,1041 @@ +//=======- ARMFrameLowering.cpp - ARM Frame Information --------*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "ARMFrameLowering.h" +#include "ARMAddressingModes.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMMachineFunctionInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +/// hasFP - Return true if the specified function should have a dedicated frame +/// pointer register. This is true if the function has variable sized allocas +/// or if frame pointer elimination is disabled. +bool ARMFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + + // Mac OS X requires FP not to be clobbered for backtracing purpose. + if (STI.isTargetDarwin()) + return true; + + const MachineFrameInfo *MFI = MF.getFrameInfo(); + // Always eliminate non-leaf frame pointers. + return ((DisableFramePointerElim(MF) && MFI->hasCalls()) || + RegInfo->needsStackRealignment(MF) || + MFI->hasVarSizedObjects() || + MFI->isFrameAddressTaken()); +} + +/// hasReservedCallFrame - Under normal circumstances, when a frame pointer is +/// not required, we reserve argument space for call sites in the function +/// immediately on entry to the current function. This eliminates the need for +/// add/sub sp brackets around call sites. Returns true if the call frame is +/// included as part of the stack frame. +bool ARMFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { + const MachineFrameInfo *FFI = MF.getFrameInfo(); + unsigned CFSize = FFI->getMaxCallFrameSize(); + // It's not always a good idea to include the call frame as part of the + // stack frame. ARM (especially Thumb) has small immediate offset to + // address the stack frame. So a large call frame can cause poor codegen + // and may even makes it impossible to scavenge a register. + if (CFSize >= ((1 << 12) - 1) / 2) // Half of imm12 + return false; + + return !MF.getFrameInfo()->hasVarSizedObjects(); +} + +/// canSimplifyCallFramePseudos - If there is a reserved call frame, the +/// call frame pseudos can be simplified. Unlike most targets, having a FP +/// is not sufficient here since we still may reference some objects via SP +/// even when FP is available in Thumb2 mode. +bool +ARMFrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const { + return hasReservedCallFrame(MF) || MF.getFrameInfo()->hasVarSizedObjects(); +} + +static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { + for (unsigned i = 0; CSRegs[i]; ++i) + if (Reg == CSRegs[i]) + return true; + return false; +} + +static bool isCSRestore(MachineInstr *MI, + const ARMBaseInstrInfo &TII, + const unsigned *CSRegs) { + // Integer spill area is handled with "pop". + if (MI->getOpcode() == ARM::LDMIA_RET || + MI->getOpcode() == ARM::t2LDMIA_RET || + MI->getOpcode() == ARM::LDMIA_UPD || + MI->getOpcode() == ARM::t2LDMIA_UPD || + MI->getOpcode() == ARM::VLDMDIA_UPD) { + // The first two operands are predicates. The last two are + // imp-def and imp-use of SP. Check everything in between. + for (int i = 5, e = MI->getNumOperands(); i != e; ++i) + if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs)) + return false; + return true; + } + if ((MI->getOpcode() == ARM::LDR_POST || + MI->getOpcode() == ARM::t2LDR_POST) && + isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs) && + MI->getOperand(1).getReg() == ARM::SP) + return true; + + return false; +} + +static void +emitSPUpdate(bool isARM, + MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + DebugLoc dl, const ARMBaseInstrInfo &TII, + int NumBytes, unsigned MIFlags = MachineInstr::NoFlags) { + if (isARM) + emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + ARMCC::AL, 0, TII, MIFlags); + else + emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, ARM::SP, NumBytes, + ARMCC::AL, 0, TII, MIFlags); +} + +void ARMFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + const ARMBaseRegisterInfo *RegInfo = + static_cast(MF.getTarget().getRegisterInfo()); + const ARMBaseInstrInfo &TII = + *static_cast(MF.getTarget().getInstrInfo()); + assert(!AFI->isThumb1OnlyFunction() && + "This emitPrologue does not support Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + unsigned NumBytes = MFI->getStackSize(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + unsigned FramePtr = RegInfo->getFrameRegister(MF); + + // Determine the sizes of each callee-save spill areas and record which frame + // belongs to which callee-save spill areas. + unsigned GPRCS1Size = 0, GPRCS2Size = 0, DPRCSSize = 0; + int FramePtrSpillFI = 0; + + // Allocate the vararg register save area. This is not counted in NumBytes. + if (VARegSaveSize) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -VARegSaveSize, + MachineInstr::FrameSetup); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, + MachineInstr::FrameSetup); + return; + } + + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + int FI = CSI[i].getFrameIdx(); + switch (Reg) { + case ARM::R4: + case ARM::R5: + case ARM::R6: + case ARM::R7: + case ARM::LR: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + break; + case ARM::R8: + case ARM::R9: + case ARM::R10: + case ARM::R11: + if (Reg == FramePtr) + FramePtrSpillFI = FI; + if (STI.isTargetDarwin()) { + AFI->addGPRCalleeSavedArea2Frame(FI); + GPRCS2Size += 4; + } else { + AFI->addGPRCalleeSavedArea1Frame(FI); + GPRCS1Size += 4; + } + break; + default: + AFI->addDPRCalleeSavedAreaFrame(FI); + DPRCSSize += 8; + } + } + + // Move past area 1. + if (GPRCS1Size > 0) MBBI++; + + // Set FP to point to the stack slot that contains the previous FP. + // For Darwin, FP is R7, which has now been stored in spill area 1. + // Otherwise, if this is not Darwin, all the callee-saved registers go + // into spill area 1, including the FP in R11. In either case, it is + // now safe to emit this assignment. + bool HasFP = hasFP(MF); + if (HasFP) { + unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri; + MachineInstrBuilder MIB = + BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr) + .addFrameIndex(FramePtrSpillFI).addImm(0) + .setMIFlag(MachineInstr::FrameSetup); + AddDefaultCC(AddDefaultPred(MIB)); + } + + // Move past area 2. + if (GPRCS2Size > 0) MBBI++; + + // Determine starting offsets of spill areas. + unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); + unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; + unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; + if (HasFP) + AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + + NumBytes); + AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); + AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); + AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); + + // Move past area 3. + if (DPRCSSize > 0) { + MBBI++; + // Since vpush register list cannot have gaps, there may be multiple vpush + // instructions in the prologue. + while (MBBI->getOpcode() == ARM::VSTMDDB_UPD) + MBBI++; + } + + NumBytes = DPRCSOffset; + if (NumBytes) { + // Adjust SP after all the callee-save spills. + emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes, + MachineInstr::FrameSetup); + if (HasFP && isARM) + // Restore from fp only in ARM mode: e.g. sub sp, r7, #24 + // Note it's not safe to do this in Thumb2 mode because it would have + // taken two instructions: + // mov sp, r7 + // sub sp, #24 + // If an interrupt is taken between the two instructions, then sp is in + // an inconsistent state (pointing to the middle of callee-saved area). + // The interrupt handler can end up clobbering the registers. + AFI->setShouldRestoreSPFromFP(true); + } + + if (STI.isTargetELF() && hasFP(MF)) + MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - + AFI->getFramePtrSpillOffset()); + + AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); + AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); + AFI->setDPRCalleeSavedAreaSize(DPRCSSize); + + // If we need dynamic stack realignment, do it here. Be paranoid and make + // sure if we also have VLAs, we have a base pointer for frame access. + if (RegInfo->needsStackRealignment(MF)) { + unsigned MaxAlign = MFI->getMaxAlignment(); + assert (!AFI->isThumb1OnlyFunction()); + if (!AFI->isThumbFunction()) { + // Emit bic sp, sp, MaxAlign + AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, + TII.get(ARM::BICri), ARM::SP) + .addReg(ARM::SP, RegState::Kill) + .addImm(MaxAlign-1))); + } else { + // We cannot use sp as source/dest register here, thus we're emitting the + // following sequence: + // mov r4, sp + // bic r4, r4, MaxAlign + // mov sp, r4 + // FIXME: It will be better just to find spare register here. + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2tgpr), ARM::R4) + .addReg(ARM::SP, RegState::Kill); + AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, + TII.get(ARM::t2BICri), ARM::R4) + .addReg(ARM::R4, RegState::Kill) + .addImm(MaxAlign-1))); + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) + .addReg(ARM::R4, RegState::Kill); + } + + AFI->setShouldRestoreSPFromFP(true); + } + + // If we need a base pointer, set it up here. It's whatever the value + // of the stack pointer is at this point. Any variable size objects + // will be allocated after this, so we can still use the base pointer + // to reference locals. + // FIXME: Clarify FrameSetup flags here. + if (RegInfo->hasBasePointer(MF)) { + if (isARM) + BuildMI(MBB, MBBI, dl, + TII.get(ARM::MOVr), RegInfo->getBaseRegister()) + .addReg(ARM::SP) + .addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); + else + BuildMI(MBB, MBBI, dl, + TII.get(ARM::tMOVgpr2gpr), RegInfo->getBaseRegister()) + .addReg(ARM::SP); + } + + // If the frame has variable sized objects then the epilogue must restore + // the sp from fp. We can assume there's an FP here since hasFP already + // checks for hasVarSizedObjects. + if (MFI->hasVarSizedObjects()) + AFI->setShouldRestoreSPFromFP(true); +} + +void ARMFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + assert(MBBI->getDesc().isReturn() && + "Can only insert epilog into returning blocks"); + unsigned RetOpcode = MBBI->getOpcode(); + DebugLoc dl = MBBI->getDebugLoc(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + const ARMBaseInstrInfo &TII = + *static_cast(MF.getTarget().getInstrInfo()); + assert(!AFI->isThumb1OnlyFunction() && + "This emitEpilogue does not support Thumb1!"); + bool isARM = !AFI->isThumbFunction(); + + unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); + int NumBytes = (int)MFI->getStackSize(); + unsigned FramePtr = RegInfo->getFrameRegister(MF); + + if (!AFI->hasStackFrame()) { + if (NumBytes != 0) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); + } else { + // Unwind MBBI to point to first LDR / VLDRD. + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); + if (MBBI != MBB.begin()) { + do + --MBBI; + while (MBBI != MBB.begin() && isCSRestore(MBBI, TII, CSRegs)); + if (!isCSRestore(MBBI, TII, CSRegs)) + ++MBBI; + } + + // Move SP to start of FP callee save spill area. + NumBytes -= (AFI->getGPRCalleeSavedArea1Size() + + AFI->getGPRCalleeSavedArea2Size() + + AFI->getDPRCalleeSavedAreaSize()); + + // Reset SP based on frame pointer only if the stack frame extends beyond + // frame pointer stack slot or target is ELF and the function has FP. + if (AFI->shouldRestoreSPFromFP()) { + NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; + if (NumBytes) { + if (isARM) + emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, + ARMCC::AL, 0, TII); + else { + // It's not possible to restore SP from FP in a single instruction. + // For Darwin, this looks like: + // mov sp, r7 + // sub sp, #24 + // This is bad, if an interrupt is taken after the mov, sp is in an + // inconsistent state. + // Use the first callee-saved register as a scratch register. + assert(MF.getRegInfo().isPhysRegUsed(ARM::R4) && + "No scratch register to restore SP from FP!"); + emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, + ARMCC::AL, 0, TII); + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) + .addReg(ARM::R4); + } + } else { + // Thumb2 or ARM. + if (isARM) + BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP) + .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0); + else + BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP) + .addReg(FramePtr); + } + } else if (NumBytes) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); + + // Increment past our save areas. + if (AFI->getDPRCalleeSavedAreaSize()) { + MBBI++; + // Since vpop register list cannot have gaps, there may be multiple vpop + // instructions in the epilogue. + while (MBBI->getOpcode() == ARM::VLDMDIA_UPD) + MBBI++; + } + if (AFI->getGPRCalleeSavedArea2Size()) MBBI++; + if (AFI->getGPRCalleeSavedArea1Size()) MBBI++; + } + + if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND || + RetOpcode == ARM::TCRETURNri || RetOpcode == ARM::TCRETURNriND) { + // Tail call return: adjust the stack pointer and jump to callee. + MBBI = MBB.getLastNonDebugInstr(); + MachineOperand &JumpTarget = MBBI->getOperand(0); + + // Jump to label or value in register. + if (RetOpcode == ARM::TCRETURNdi || RetOpcode == ARM::TCRETURNdiND) { + unsigned TCOpcode = (RetOpcode == ARM::TCRETURNdi) + ? (STI.isThumb() ? ARM::TAILJMPdt : ARM::TAILJMPd) + : (STI.isThumb() ? ARM::TAILJMPdNDt : ARM::TAILJMPdND); + MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(TCOpcode)); + if (JumpTarget.isGlobal()) + MIB.addGlobalAddress(JumpTarget.getGlobal(), JumpTarget.getOffset(), + JumpTarget.getTargetFlags()); + else { + assert(JumpTarget.isSymbol()); + MIB.addExternalSymbol(JumpTarget.getSymbolName(), + JumpTarget.getTargetFlags()); + } + } else if (RetOpcode == ARM::TCRETURNri) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPr)). + addReg(JumpTarget.getReg(), RegState::Kill); + } else if (RetOpcode == ARM::TCRETURNriND) { + BuildMI(MBB, MBBI, dl, TII.get(ARM::TAILJMPrND)). + addReg(JumpTarget.getReg(), RegState::Kill); + } + + MachineInstr *NewMI = prior(MBBI); + for (unsigned i = 1, e = MBBI->getNumOperands(); i != e; ++i) + NewMI->addOperand(MBBI->getOperand(i)); + + // Delete the pseudo instruction TCRETURN. + MBB.erase(MBBI); + } + + if (VARegSaveSize) + emitSPUpdate(isARM, MBB, MBBI, dl, TII, VARegSaveSize); +} + +/// getFrameIndexReference - Provide a base+offset reference to an FI slot for +/// debug info. It's the same as what we use for resolving the code-gen +/// references for now. FIXME: This can go wrong when references are +/// SP-relative and simple call frames aren't used. +int +ARMFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { + return ResolveFrameIndexReference(MF, FI, FrameReg, 0); +} + +int +ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF, + int FI, + unsigned &FrameReg, + int SPAdj) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const ARMBaseRegisterInfo *RegInfo = + static_cast(MF.getTarget().getRegisterInfo()); + const ARMFunctionInfo *AFI = MF.getInfo(); + int Offset = MFI->getObjectOffset(FI) + MFI->getStackSize(); + int FPOffset = Offset - AFI->getFramePtrSpillOffset(); + bool isFixed = MFI->isFixedObjectIndex(FI); + + FrameReg = ARM::SP; + Offset += SPAdj; + if (AFI->isGPRCalleeSavedArea1Frame(FI)) + return Offset - AFI->getGPRCalleeSavedArea1Offset(); + else if (AFI->isGPRCalleeSavedArea2Frame(FI)) + return Offset - AFI->getGPRCalleeSavedArea2Offset(); + else if (AFI->isDPRCalleeSavedAreaFrame(FI)) + return Offset - AFI->getDPRCalleeSavedAreaOffset(); + + // When dynamically realigning the stack, use the frame pointer for + // parameters, and the stack/base pointer for locals. + if (RegInfo->needsStackRealignment(MF)) { + assert (hasFP(MF) && "dynamic stack realignment without a FP!"); + if (isFixed) { + FrameReg = RegInfo->getFrameRegister(MF); + Offset = FPOffset; + } else if (MFI->hasVarSizedObjects()) { + assert(RegInfo->hasBasePointer(MF) && + "VLAs and dynamic stack alignment, but missing base pointer!"); + FrameReg = RegInfo->getBaseRegister(); + } + return Offset; + } + + // If there is a frame pointer, use it when we can. + if (hasFP(MF) && AFI->hasStackFrame()) { + // Use frame pointer to reference fixed objects. Use it for locals if + // there are VLAs (and thus the SP isn't reliable as a base). + if (isFixed || (MFI->hasVarSizedObjects() && + !RegInfo->hasBasePointer(MF))) { + FrameReg = RegInfo->getFrameRegister(MF); + return FPOffset; + } else if (MFI->hasVarSizedObjects()) { + assert(RegInfo->hasBasePointer(MF) && "missing base pointer!"); + // Try to use the frame pointer if we can, else use the base pointer + // since it's available. This is handy for the emergency spill slot, in + // particular. + if (AFI->isThumb2Function()) { + if (FPOffset >= -255 && FPOffset < 0) { + FrameReg = RegInfo->getFrameRegister(MF); + return FPOffset; + } + } else + FrameReg = RegInfo->getBaseRegister(); + } else if (AFI->isThumb2Function()) { + // In Thumb2 mode, the negative offset is very limited. Try to avoid + // out of range references. + if (FPOffset >= -255 && FPOffset < 0) { + FrameReg = RegInfo->getFrameRegister(MF); + return FPOffset; + } + } else if (Offset > (FPOffset < 0 ? -FPOffset : FPOffset)) { + // Otherwise, use SP or FP, whichever is closer to the stack slot. + FrameReg = RegInfo->getFrameRegister(MF); + return FPOffset; + } + } + // Use the base pointer if we have one. + if (RegInfo->hasBasePointer(MF)) + FrameReg = RegInfo->getBaseRegister(); + return Offset; +} + +int ARMFrameLowering::getFrameIndexOffset(const MachineFunction &MF, + int FI) const { + unsigned FrameReg; + return getFrameIndexReference(MF, FI, FrameReg); +} + +void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + unsigned StmOpc, unsigned StrOpc, + bool NoGap, + bool(*Func)(unsigned, bool), + unsigned MIFlags) const { + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + + DebugLoc DL; + if (MI != MBB.end()) DL = MI->getDebugLoc(); + + SmallVector, 4> Regs; + unsigned i = CSI.size(); + while (i != 0) { + unsigned LastReg = 0; + for (; i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (!(Func)(Reg, STI.isTargetDarwin())) continue; + + // Add the callee-saved register as live-in unless it's LR and + // @llvm.returnaddress is called. If LR is returned for + // @llvm.returnaddress then it's already added to the function and + // entry block live-in sets. + bool isKill = true; + if (Reg == ARM::LR) { + if (MF.getFrameInfo()->isReturnAddressTaken() && + MF.getRegInfo().isLiveIn(Reg)) + isKill = false; + } + + if (isKill) + MBB.addLiveIn(Reg); + + // If NoGap is true, push consecutive registers and then leave the rest + // for other instructions. e.g. + // vpush {d8, d10, d11} -> vpush {d8}, vpush {d10, d11} + if (NoGap && LastReg && LastReg != Reg-1) + break; + LastReg = Reg; + Regs.push_back(std::make_pair(Reg, isKill)); + } + + if (Regs.empty()) + continue; + if (Regs.size() > 1 || StrOpc== 0) { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(StmOpc), ARM::SP) + .addReg(ARM::SP).setMIFlags(MIFlags)); + for (unsigned i = 0, e = Regs.size(); i < e; ++i) + MIB.addReg(Regs[i].first, getKillRegState(Regs[i].second)); + } else if (Regs.size() == 1) { + MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc), + ARM::SP) + .addReg(Regs[0].first, getKillRegState(Regs[0].second)) + .addReg(ARM::SP).setMIFlags(MIFlags); + // ARM mode needs an extra reg0 here due to addrmode2. Will go away once + // that refactoring is complete (eventually). + if (StrOpc == ARM::STR_PRE) { + MIB.addReg(0); + MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::sub, 4, ARM_AM::no_shift)); + } else + MIB.addImm(-4); + AddDefaultPred(MIB); + } + Regs.clear(); + } +} + +void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + unsigned LdmOpc, unsigned LdrOpc, + bool isVarArg, bool NoGap, + bool(*Func)(unsigned, bool)) const { + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + DebugLoc DL = MI->getDebugLoc(); + unsigned RetOpcode = MI->getOpcode(); + bool isTailCall = (RetOpcode == ARM::TCRETURNdi || + RetOpcode == ARM::TCRETURNdiND || + RetOpcode == ARM::TCRETURNri || + RetOpcode == ARM::TCRETURNriND); + + SmallVector Regs; + unsigned i = CSI.size(); + while (i != 0) { + unsigned LastReg = 0; + bool DeleteRet = false; + for (; i != 0; --i) { + unsigned Reg = CSI[i-1].getReg(); + if (!(Func)(Reg, STI.isTargetDarwin())) continue; + + if (Reg == ARM::LR && !isTailCall && !isVarArg && STI.hasV5TOps()) { + Reg = ARM::PC; + LdmOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_RET : ARM::LDMIA_RET; + // Fold the return instruction into the LDM. + DeleteRet = true; + } + + // If NoGap is true, pop consecutive registers and then leave the rest + // for other instructions. e.g. + // vpop {d8, d10, d11} -> vpop {d8}, vpop {d10, d11} + if (NoGap && LastReg && LastReg != Reg-1) + break; + + LastReg = Reg; + Regs.push_back(Reg); + } + + if (Regs.empty()) + continue; + if (Regs.size() > 1 || LdrOpc == 0) { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, MI, DL, TII.get(LdmOpc), ARM::SP) + .addReg(ARM::SP)); + for (unsigned i = 0, e = Regs.size(); i < e; ++i) + MIB.addReg(Regs[i], getDefRegState(true)); + if (DeleteRet) + MI->eraseFromParent(); + MI = MIB; + } else if (Regs.size() == 1) { + // If we adjusted the reg to PC from LR above, switch it back here. We + // only do that for LDM. + if (Regs[0] == ARM::PC) + Regs[0] = ARM::LR; + MachineInstrBuilder MIB = + BuildMI(MBB, MI, DL, TII.get(LdrOpc), Regs[0]) + .addReg(ARM::SP, RegState::Define) + .addReg(ARM::SP); + // ARM mode needs an extra reg0 here due to addrmode2. Will go away once + // that refactoring is complete (eventually). + if (LdrOpc == ARM::LDR_POST) { + MIB.addReg(0); + MIB.addImm(ARM_AM::getAM2Opc(ARM_AM::add, 4, ARM_AM::no_shift)); + } else + MIB.addImm(4); + AddDefaultPred(MIB); + } + Regs.clear(); + } +} + +bool ARMFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + + unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD; + unsigned PushOneOpc = AFI->isThumbFunction() ? ARM::t2STR_PRE : ARM::STR_PRE; + unsigned FltOpc = ARM::VSTMDDB_UPD; + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea1Register, + MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false, &isARMArea2Register, + MachineInstr::FrameSetup); + emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register, + MachineInstr::FrameSetup); + + return true; +} + +bool ARMFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) + return false; + + MachineFunction &MF = *MBB.getParent(); + ARMFunctionInfo *AFI = MF.getInfo(); + bool isVarArg = AFI->getVarArgsRegSaveSize() > 0; + + unsigned PopOpc = AFI->isThumbFunction() ? ARM::t2LDMIA_UPD : ARM::LDMIA_UPD; + unsigned LdrOpc = AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST; + unsigned FltOpc = ARM::VLDMDIA_UPD; + emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register); + emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, + &isARMArea2Register); + emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false, + &isARMArea1Register); + + return true; +} + +// FIXME: Make generic? +static unsigned GetFunctionSizeInBytes(const MachineFunction &MF, + const ARMBaseInstrInfo &TII) { + unsigned FnSize = 0; + for (MachineFunction::const_iterator MBBI = MF.begin(), E = MF.end(); + MBBI != E; ++MBBI) { + const MachineBasicBlock &MBB = *MBBI; + for (MachineBasicBlock::const_iterator I = MBB.begin(),E = MBB.end(); + I != E; ++I) + FnSize += TII.GetInstSizeInBytes(I); + } + return FnSize; +} + +/// estimateStackSize - Estimate and return the size of the frame. +/// FIXME: Make generic? +static unsigned estimateStackSize(MachineFunction &MF) { + const MachineFrameInfo *FFI = MF.getFrameInfo(); + int Offset = 0; + for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { + int FixedOff = -FFI->getObjectOffset(i); + if (FixedOff > Offset) Offset = FixedOff; + } + for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) { + if (FFI->isDeadObjectIndex(i)) + continue; + Offset += FFI->getObjectSize(i); + unsigned Align = FFI->getObjectAlignment(i); + // Adjust to alignment boundary + Offset = (Offset+Align-1)/Align*Align; + } + return (unsigned)Offset; +} + +/// estimateRSStackSizeLimit - Look at each instruction that references stack +/// frames and return the stack size limit beyond which some of these +/// instructions will require a scratch register during their expansion later. +// FIXME: Move to TII? +static unsigned estimateRSStackSizeLimit(MachineFunction &MF, + const TargetFrameLowering *TFI) { + const ARMFunctionInfo *AFI = MF.getInfo(); + unsigned Limit = (1 << 12) - 1; + for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) { + for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); + I != E; ++I) { + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + if (!I->getOperand(i).isFI()) continue; + + // When using ADDri to get the address of a stack object, 255 is the + // largest offset guaranteed to fit in the immediate offset. + if (I->getOpcode() == ARM::ADDri) { + Limit = std::min(Limit, (1U << 8) - 1); + break; + } + + // Otherwise check the addressing mode. + switch (I->getDesc().TSFlags & ARMII::AddrModeMask) { + case ARMII::AddrMode3: + case ARMII::AddrModeT2_i8: + Limit = std::min(Limit, (1U << 8) - 1); + break; + case ARMII::AddrMode5: + case ARMII::AddrModeT2_i8s4: + Limit = std::min(Limit, ((1U << 8) - 1) * 4); + break; + case ARMII::AddrModeT2_i12: + // i12 supports only positive offset so these will be converted to + // i8 opcodes. See llvm::rewriteT2FrameIndex. + if (TFI->hasFP(MF) && AFI->hasStackFrame()) + Limit = std::min(Limit, (1U << 8) - 1); + break; + case ARMII::AddrMode4: + case ARMII::AddrMode6: + // Addressing modes 4 & 6 (load/store) instructions can't encode an + // immediate offset for stack references. + return 0; + default: + break; + } + break; // At most one FI per instruction + } + } + } + + return Limit; +} + +void +ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + // This tells PEI to spill the FP as if it is any other callee-save register + // to take advantage the eliminateFrameIndex machinery. This also ensures it + // is spilled in the order specified by getCalleeSavedRegs() to make it easier + // to combine multiple loads / stores. + bool CanEliminateFrame = true; + bool CS1Spilled = false; + bool LRSpilled = false; + unsigned NumGPRSpills = 0; + SmallVector UnspilledCS1GPRs; + SmallVector UnspilledCS2GPRs; + const ARMBaseRegisterInfo *RegInfo = + static_cast(MF.getTarget().getRegisterInfo()); + const ARMBaseInstrInfo &TII = + *static_cast(MF.getTarget().getInstrInfo()); + ARMFunctionInfo *AFI = MF.getInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + unsigned FramePtr = RegInfo->getFrameRegister(MF); + + // Spill R4 if Thumb2 function requires stack realignment - it will be used as + // scratch register. Also spill R4 if Thumb2 function has varsized objects, + // since it's not always possible to restore sp from fp in a single + // instruction. + // FIXME: It will be better just to find spare register here. + if (AFI->isThumb2Function() && + (MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(MF))) + MF.getRegInfo().setPhysRegUsed(ARM::R4); + + if (AFI->isThumb1OnlyFunction()) { + // Spill LR if Thumb1 function uses variable length argument lists. + if (AFI->getVarArgsRegSaveSize() > 0) + MF.getRegInfo().setPhysRegUsed(ARM::LR); + + // Spill R4 if Thumb1 epilogue has to restore SP from FP since + // FIXME: It will be better just to find spare register here. + if (MFI->hasVarSizedObjects()) + MF.getRegInfo().setPhysRegUsed(ARM::R4); + } + + // Spill the BasePtr if it's used. + if (RegInfo->hasBasePointer(MF)) + MF.getRegInfo().setPhysRegUsed(RegInfo->getBaseRegister()); + + // Don't spill FP if the frame can be eliminated. This is determined + // by scanning the callee-save registers to see if any is used. + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); + for (unsigned i = 0; CSRegs[i]; ++i) { + unsigned Reg = CSRegs[i]; + bool Spilled = false; + if (MF.getRegInfo().isPhysRegUsed(Reg)) { + Spilled = true; + CanEliminateFrame = false; + } else { + // Check alias registers too. + for (const unsigned *Aliases = + RegInfo->getAliasSet(Reg); *Aliases; ++Aliases) { + if (MF.getRegInfo().isPhysRegUsed(*Aliases)) { + Spilled = true; + CanEliminateFrame = false; + } + } + } + + if (!ARM::GPRRegisterClass->contains(Reg)) + continue; + + if (Spilled) { + NumGPRSpills++; + + if (!STI.isTargetDarwin()) { + if (Reg == ARM::LR) + LRSpilled = true; + CS1Spilled = true; + continue; + } + + // Keep track if LR and any of R4, R5, R6, and R7 is spilled. + switch (Reg) { + case ARM::LR: + LRSpilled = true; + // Fallthrough + case ARM::R4: case ARM::R5: + case ARM::R6: case ARM::R7: + CS1Spilled = true; + break; + default: + break; + } + } else { + if (!STI.isTargetDarwin()) { + UnspilledCS1GPRs.push_back(Reg); + continue; + } + + switch (Reg) { + case ARM::R4: case ARM::R5: + case ARM::R6: case ARM::R7: + case ARM::LR: + UnspilledCS1GPRs.push_back(Reg); + break; + default: + UnspilledCS2GPRs.push_back(Reg); + break; + } + } + } + + bool ForceLRSpill = false; + if (!LRSpilled && AFI->isThumb1OnlyFunction()) { + unsigned FnSize = GetFunctionSizeInBytes(MF, TII); + // Force LR to be spilled if the Thumb function size is > 2048. This enables + // use of BL to implement far jump. If it turns out that it's not needed + // then the branch fix up path will undo it. + if (FnSize >= (1 << 11)) { + CanEliminateFrame = false; + ForceLRSpill = true; + } + } + + // If any of the stack slot references may be out of range of an immediate + // offset, make sure a register (or a spill slot) is available for the + // register scavenger. Note that if we're indexing off the frame pointer, the + // effective stack size is 4 bytes larger since the FP points to the stack + // slot of the previous FP. Also, if we have variable sized objects in the + // function, stack slot references will often be negative, and some of + // our instructions are positive-offset only, so conservatively consider + // that case to want a spill slot (or register) as well. Similarly, if + // the function adjusts the stack pointer during execution and the + // adjustments aren't already part of our stack size estimate, our offset + // calculations may be off, so be conservative. + // FIXME: We could add logic to be more precise about negative offsets + // and which instructions will need a scratch register for them. Is it + // worth the effort and added fragility? + bool BigStack = + (RS && + (estimateStackSize(MF) + ((hasFP(MF) && AFI->hasStackFrame()) ? 4:0) >= + estimateRSStackSizeLimit(MF, this))) + || MFI->hasVarSizedObjects() + || (MFI->adjustsStack() && !canSimplifyCallFramePseudos(MF)); + + bool ExtraCSSpill = false; + if (BigStack || !CanEliminateFrame || RegInfo->cannotEliminateFrame(MF)) { + AFI->setHasStackFrame(true); + + // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled. + // Spill LR as well so we can fold BX_RET to the registers restore (LDM). + if (!LRSpilled && CS1Spilled) { + MF.getRegInfo().setPhysRegUsed(ARM::LR); + NumGPRSpills++; + UnspilledCS1GPRs.erase(std::find(UnspilledCS1GPRs.begin(), + UnspilledCS1GPRs.end(), (unsigned)ARM::LR)); + ForceLRSpill = false; + ExtraCSSpill = true; + } + + if (hasFP(MF)) { + MF.getRegInfo().setPhysRegUsed(FramePtr); + NumGPRSpills++; + } + + // If stack and double are 8-byte aligned and we are spilling an odd number + // of GPRs, spill one extra callee save GPR so we won't have to pad between + // the integer and double callee save areas. + unsigned TargetAlign = getStackAlignment(); + if (TargetAlign == 8 && (NumGPRSpills & 1)) { + if (CS1Spilled && !UnspilledCS1GPRs.empty()) { + for (unsigned i = 0, e = UnspilledCS1GPRs.size(); i != e; ++i) { + unsigned Reg = UnspilledCS1GPRs[i]; + // Don't spill high register if the function is thumb1 + if (!AFI->isThumb1OnlyFunction() || + isARMLowRegister(Reg) || Reg == ARM::LR) { + MF.getRegInfo().setPhysRegUsed(Reg); + if (!RegInfo->isReservedReg(MF, Reg)) + ExtraCSSpill = true; + break; + } + } + } else if (!UnspilledCS2GPRs.empty() && !AFI->isThumb1OnlyFunction()) { + unsigned Reg = UnspilledCS2GPRs.front(); + MF.getRegInfo().setPhysRegUsed(Reg); + if (!RegInfo->isReservedReg(MF, Reg)) + ExtraCSSpill = true; + } + } + + // Estimate if we might need to scavenge a register at some point in order + // to materialize a stack offset. If so, either spill one additional + // callee-saved register or reserve a special spill slot to facilitate + // register scavenging. Thumb1 needs a spill slot for stack pointer + // adjustments also, even when the frame itself is small. + if (BigStack && !ExtraCSSpill) { + // If any non-reserved CS register isn't spilled, just spill one or two + // extra. That should take care of it! + unsigned NumExtras = TargetAlign / 4; + SmallVector Extras; + while (NumExtras && !UnspilledCS1GPRs.empty()) { + unsigned Reg = UnspilledCS1GPRs.back(); + UnspilledCS1GPRs.pop_back(); + if (!RegInfo->isReservedReg(MF, Reg) && + (!AFI->isThumb1OnlyFunction() || isARMLowRegister(Reg) || + Reg == ARM::LR)) { + Extras.push_back(Reg); + NumExtras--; + } + } + // For non-Thumb1 functions, also check for hi-reg CS registers + if (!AFI->isThumb1OnlyFunction()) { + while (NumExtras && !UnspilledCS2GPRs.empty()) { + unsigned Reg = UnspilledCS2GPRs.back(); + UnspilledCS2GPRs.pop_back(); + if (!RegInfo->isReservedReg(MF, Reg)) { + Extras.push_back(Reg); + NumExtras--; + } + } + } + if (Extras.size() && NumExtras == 0) { + for (unsigned i = 0, e = Extras.size(); i != e; ++i) { + MF.getRegInfo().setPhysRegUsed(Extras[i]); + } + } else if (!AFI->isThumb1OnlyFunction()) { + // note: Thumb1 functions spill to R12, not the stack. Reserve a slot + // closest to SP or frame pointer. + const TargetRegisterClass *RC = ARM::GPRRegisterClass; + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); + } + } + } + + if (ForceLRSpill) { + MF.getRegInfo().setPhysRegUsed(ARM::LR); + AFI->setLRIsSpilledForFarJump(true); + } +} diff --git a/final/lib/Target/ARM/ARMFrameLowering.h b/final/lib/Target/ARM/ARMFrameLowering.h new file mode 100644 index 00000000000..a7b7f15449d --- /dev/null +++ b/final/lib/Target/ARM/ARMFrameLowering.h @@ -0,0 +1,75 @@ +//==-- ARMTargetFrameLowering.h - Define frame lowering for ARM --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// +//===----------------------------------------------------------------------===// + +#ifndef ARM_FRAMEINFO_H +#define ARM_FRAMEINFO_H + +#include "ARM.h" +#include "ARMSubtarget.h" +#include "llvm/Target/TargetFrameLowering.h" + +namespace llvm { + class ARMSubtarget; + +class ARMFrameLowering : public TargetFrameLowering { +protected: + const ARMSubtarget &STI; + +public: + explicit ARMFrameLowering(const ARMSubtarget &sti) + : TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, 4), + STI(sti) { + } + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const; + + bool hasFP(const MachineFunction &MF) const; + bool hasReservedCallFrame(const MachineFunction &MF) const; + bool canSimplifyCallFramePseudos(const MachineFunction &MF) const; + int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const; + int ResolveFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg, int SPAdj) const; + int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const; + + private: + void emitPushInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, unsigned StmOpc, + unsigned StrOpc, bool NoGap, + bool(*Func)(unsigned, bool), + unsigned MIFlags = 0) const; + void emitPopInst(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, unsigned LdmOpc, + unsigned LdrOpc, bool isVarArg, bool NoGap, + bool(*Func)(unsigned, bool)) const; +}; + +} // End llvm namespace + +#endif diff --git a/final/lib/Target/ARM/ARMGlobalMerge.cpp b/final/lib/Target/ARM/ARMGlobalMerge.cpp new file mode 100644 index 00000000000..ab6c00e6e1a --- /dev/null +++ b/final/lib/Target/ARM/ARMGlobalMerge.cpp @@ -0,0 +1,223 @@ +//===-- ARMGlobalMerge.cpp - Internal globals merging --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This pass merges globals with internal linkage into one. This way all the +// globals which were merged into a biggest one can be addressed using offsets +// from the same base pointer (no need for separate base pointer for each of the +// global). Such a transformation can significantly reduce the register pressure +// when many globals are involved. +// +// For example, consider the code which touches several global variables at +// once: +// +// static int foo[N], bar[N], baz[N]; +// +// for (i = 0; i < N; ++i) { +// foo[i] = bar[i] * baz[i]; +// } +// +// On ARM the addresses of 3 arrays should be kept in the registers, thus +// this code has quite large register pressure (loop body): +// +// ldr r1, [r5], #4 +// ldr r2, [r6], #4 +// mul r1, r2, r1 +// str r1, [r0], #4 +// +// Pass converts the code to something like: +// +// static struct { +// int foo[N]; +// int bar[N]; +// int baz[N]; +// } merged; +// +// for (i = 0; i < N; ++i) { +// merged.foo[i] = merged.bar[i] * merged.baz[i]; +// } +// +// and in ARM code this becomes: +// +// ldr r0, [r5, #40] +// ldr r1, [r5, #80] +// mul r0, r1, r0 +// str r0, [r5], #4 +// +// note that we saved 2 registers here almostly "for free". +// ===---------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-global-merge" +#include "ARM.h" +#include "ARMTargetMachine.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Attributes.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +using namespace llvm; + +namespace { + class ARMGlobalMerge : public FunctionPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// target type sizes. + const TargetLowering *TLI; + + bool doMerge(SmallVectorImpl &Globals, + Module &M, bool isConst) const; + + public: + static char ID; // Pass identification, replacement for typeid. + explicit ARMGlobalMerge(const TargetLowering *tli) + : FunctionPass(ID), TLI(tli) {} + + virtual bool doInitialization(Module &M); + virtual bool runOnFunction(Function &F); + + const char *getPassName() const { + return "Merge internal globals"; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); + } + + struct GlobalCmp { + const TargetData *TD; + + GlobalCmp(const TargetData *td) : TD(td) { } + + bool operator()(const GlobalVariable *GV1, const GlobalVariable *GV2) { + const Type *Ty1 = cast(GV1->getType())->getElementType(); + const Type *Ty2 = cast(GV2->getType())->getElementType(); + + return (TD->getTypeAllocSize(Ty1) < TD->getTypeAllocSize(Ty2)); + } + }; + }; +} // end anonymous namespace + +char ARMGlobalMerge::ID = 0; + +bool ARMGlobalMerge::doMerge(SmallVectorImpl &Globals, + Module &M, bool isConst) const { + const TargetData *TD = TLI->getTargetData(); + + // FIXME: Infer the maximum possible offset depending on the actual users + // (these max offsets are different for the users inside Thumb or ARM + // functions) + unsigned MaxOffset = TLI->getMaximalGlobalOffset(); + + // FIXME: Find better heuristics + std::stable_sort(Globals.begin(), Globals.end(), GlobalCmp(TD)); + + const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + + for (size_t i = 0, e = Globals.size(); i != e; ) { + size_t j = 0; + uint64_t MergedSize = 0; + std::vector Tys; + std::vector Inits; + for (j = i; j != e; ++j) { + const Type *Ty = Globals[j]->getType()->getElementType(); + MergedSize += TD->getTypeAllocSize(Ty); + if (MergedSize > MaxOffset) { + break; + } + Tys.push_back(Ty); + Inits.push_back(Globals[j]->getInitializer()); + } + + StructType *MergedTy = StructType::get(M.getContext(), Tys); + Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); + GlobalVariable *MergedGV = new GlobalVariable(M, MergedTy, isConst, + GlobalValue::InternalLinkage, + MergedInit, "_MergedGlobals"); + for (size_t k = i; k < j; ++k) { + Constant *Idx[2] = { + ConstantInt::get(Int32Ty, 0), + ConstantInt::get(Int32Ty, k-i) + }; + Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx, 2); + Globals[k]->replaceAllUsesWith(GEP); + Globals[k]->eraseFromParent(); + } + i = j; + } + + return true; +} + + +bool ARMGlobalMerge::doInitialization(Module &M) { + SmallVector Globals, ConstGlobals, BSSGlobals; + const TargetData *TD = TLI->getTargetData(); + unsigned MaxOffset = TLI->getMaximalGlobalOffset(); + bool Changed = false; + + // Disable this pass on darwin. The debugger is not yet ready to extract + // variable's info from a merged global. + if (TLI->getTargetMachine().getSubtarget().isTargetDarwin()) + return false; + + // Grab all non-const globals. + for (Module::global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) { + // Merge is safe for "normal" internal globals only + if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) + continue; + + // Ignore fancy-aligned globals for now. + if (I->getAlignment() != 0) + continue; + + // Ignore all 'special' globals. + if (I->getName().startswith("llvm.") || + I->getName().startswith(".llvm.")) + continue; + + if (TD->getTypeAllocSize(I->getType()->getElementType()) < MaxOffset) { + const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); + if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) + BSSGlobals.push_back(I); + else if (I->isConstant()) + ConstGlobals.push_back(I); + else + Globals.push_back(I); + } + } + + if (Globals.size() > 1) + Changed |= doMerge(Globals, M, false); + if (BSSGlobals.size() > 1) + Changed |= doMerge(BSSGlobals, M, false); + + // FIXME: This currently breaks the EH processing due to way how the + // typeinfo detection works. We might want to detect the TIs and ignore + // them in the future. + // if (ConstGlobals.size() > 1) + // Changed |= doMerge(ConstGlobals, M, true); + + return Changed; +} + +bool ARMGlobalMerge::runOnFunction(Function &F) { + return false; +} + +FunctionPass *llvm::createARMGlobalMergePass(const TargetLowering *tli) { + return new ARMGlobalMerge(tli); +} diff --git a/final/lib/Target/ARM/ARMHazardRecognizer.cpp b/final/lib/Target/ARM/ARMHazardRecognizer.cpp new file mode 100644 index 00000000000..e97ce50bc42 --- /dev/null +++ b/final/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -0,0 +1,118 @@ +//===-- ARMHazardRecognizer.cpp - ARM postra hazard recognizer ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARMHazardRecognizer.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "ARMSubtarget.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Target/TargetRegisterInfo.h" +using namespace llvm; + +static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI, + const TargetRegisterInfo &TRI) { + // FIXME: Detect integer instructions properly. + const TargetInstrDesc &TID = MI->getDesc(); + unsigned Domain = TID.TSFlags & ARMII::DomainMask; + if (TID.mayStore()) + return false; + unsigned Opcode = TID.getOpcode(); + if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) + return false; + if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON)) + return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI); + return false; +} + +ScheduleHazardRecognizer::HazardType +ARMHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { + assert(Stalls == 0 && "ARM hazards don't support scoreboard lookahead"); + + MachineInstr *MI = SU->getInstr(); + + if (!MI->isDebugValue()) { + if (ITBlockSize && MI != ITBlockMIs[ITBlockSize-1]) + return Hazard; + + // Look for special VMLA / VMLS hazards. A VMUL / VADD / VSUB following + // a VMLA / VMLS will cause 4 cycle stall. + const TargetInstrDesc &TID = MI->getDesc(); + if (LastMI && (TID.TSFlags & ARMII::DomainMask) != ARMII::DomainGeneral) { + MachineInstr *DefMI = LastMI; + const TargetInstrDesc &LastTID = LastMI->getDesc(); + // Skip over one non-VFP / NEON instruction. + if (!LastTID.isBarrier() && + (LastTID.TSFlags & ARMII::DomainMask) == ARMII::DomainGeneral) { + MachineBasicBlock::iterator I = LastMI; + if (I != LastMI->getParent()->begin()) { + I = llvm::prior(I); + DefMI = &*I; + } + } + + if (TII.isFpMLxInstruction(DefMI->getOpcode()) && + (TII.canCauseFpMLxStall(MI->getOpcode()) || + hasRAWHazard(DefMI, MI, TRI))) { + // Try to schedule another instruction for the next 4 cycles. + if (FpMLxStalls == 0) + FpMLxStalls = 4; + return Hazard; + } + } + } + + return ScoreboardHazardRecognizer::getHazardType(SU, Stalls); +} + +void ARMHazardRecognizer::Reset() { + LastMI = 0; + FpMLxStalls = 0; + ITBlockSize = 0; + ScoreboardHazardRecognizer::Reset(); +} + +void ARMHazardRecognizer::EmitInstruction(SUnit *SU) { + MachineInstr *MI = SU->getInstr(); + unsigned Opcode = MI->getOpcode(); + if (ITBlockSize) { + --ITBlockSize; + } else if (Opcode == ARM::t2IT) { + unsigned Mask = MI->getOperand(1).getImm(); + unsigned NumTZ = CountTrailingZeros_32(Mask); + assert(NumTZ <= 3 && "Invalid IT mask!"); + ITBlockSize = 4 - NumTZ; + MachineBasicBlock::iterator I = MI; + for (unsigned i = 0; i < ITBlockSize; ++i) { + // Advance to the next instruction, skipping any dbg_value instructions. + do { + ++I; + } while (I->isDebugValue()); + ITBlockMIs[ITBlockSize-1-i] = &*I; + } + } + + if (!MI->isDebugValue()) { + LastMI = MI; + FpMLxStalls = 0; + } + + ScoreboardHazardRecognizer::EmitInstruction(SU); +} + +void ARMHazardRecognizer::AdvanceCycle() { + if (FpMLxStalls && --FpMLxStalls == 0) + // Stalled for 4 cycles but still can't schedule any other instructions. + LastMI = 0; + ScoreboardHazardRecognizer::AdvanceCycle(); +} + +void ARMHazardRecognizer::RecedeCycle() { + llvm_unreachable("reverse ARM hazard checking unsupported"); +} diff --git a/final/lib/Target/ARM/ARMHazardRecognizer.h b/final/lib/Target/ARM/ARMHazardRecognizer.h new file mode 100644 index 00000000000..2bc218d8566 --- /dev/null +++ b/final/lib/Target/ARM/ARMHazardRecognizer.h @@ -0,0 +1,54 @@ +//===-- ARMHazardRecognizer.h - ARM Hazard Recognizers ----------*- 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 hazard recognizers for scheduling ARM functions. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMHAZARDRECOGNIZER_H +#define ARMHAZARDRECOGNIZER_H + +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" + +namespace llvm { + +class ARMBaseInstrInfo; +class ARMBaseRegisterInfo; +class ARMSubtarget; +class MachineInstr; + +class ARMHazardRecognizer : public ScoreboardHazardRecognizer { + const ARMBaseInstrInfo &TII; + const ARMBaseRegisterInfo &TRI; + const ARMSubtarget &STI; + + MachineInstr *LastMI; + unsigned FpMLxStalls; + unsigned ITBlockSize; // No. of MIs in current IT block yet to be scheduled. + MachineInstr *ITBlockMIs[4]; + +public: + ARMHazardRecognizer(const InstrItineraryData *ItinData, + const ARMBaseInstrInfo &tii, + const ARMBaseRegisterInfo &tri, + const ARMSubtarget &sti, + const ScheduleDAG *DAG) : + ScoreboardHazardRecognizer(ItinData, DAG, "post-RA-sched"), TII(tii), + TRI(tri), STI(sti), LastMI(0), ITBlockSize(0) {} + + virtual HazardType getHazardType(SUnit *SU, int Stalls); + virtual void Reset(); + virtual void EmitInstruction(SUnit *SU); + virtual void AdvanceCycle(); + virtual void RecedeCycle(); +}; + +} // end namespace llvm + +#endif // ARMHAZARDRECOGNIZER_H diff --git a/final/lib/Target/ARM/ARMISelDAGToDAG.cpp b/final/lib/Target/ARM/ARMISelDAGToDAG.cpp new file mode 100644 index 00000000000..edf74387b15 --- /dev/null +++ b/final/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -0,0 +1,2869 @@ +//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the ARM target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-isel" +#include "ARM.h" +#include "ARMBaseInstrInfo.h" +#include "ARMAddressingModes.h" +#include "ARMTargetMachine.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/LLVMContext.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +static cl::opt +DisableShifterOp("disable-shifter-op", cl::Hidden, + cl::desc("Disable isel of shifter-op"), + cl::init(false)); + +static cl::opt +CheckVMLxHazard("check-vmlx-hazard", cl::Hidden, + cl::desc("Check fp vmla / vmls hazard at isel time"), + cl::init(false)); + +//===--------------------------------------------------------------------===// +/// ARMDAGToDAGISel - ARM specific code to select ARM machine +/// instructions for SelectionDAG operations. +/// +namespace { + +enum AddrMode2Type { + AM2_BASE, // Simple AM2 (+-imm12) + AM2_SHOP // Shifter-op AM2 +}; + +class ARMDAGToDAGISel : public SelectionDAGISel { + ARMBaseTargetMachine &TM; + const ARMBaseInstrInfo *TII; + + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when generating code for different targets. + const ARMSubtarget *Subtarget; + +public: + explicit ARMDAGToDAGISel(ARMBaseTargetMachine &tm, + CodeGenOpt::Level OptLevel) + : SelectionDAGISel(tm, OptLevel), TM(tm), + TII(static_cast(TM.getInstrInfo())), + Subtarget(&TM.getSubtarget()) { + } + + virtual const char *getPassName() const { + return "ARM Instruction Selection"; + } + + /// getI32Imm - Return a target constant of type i32 with the specified + /// value. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + SDNode *Select(SDNode *N); + + + bool hasNoVMLxHazardUse(SDNode *N) const; + bool isShifterOpProfitable(const SDValue &Shift, + ARM_AM::ShiftOpc ShOpcVal, unsigned ShAmt); + bool SelectShifterOperandReg(SDValue N, SDValue &A, + SDValue &B, SDValue &C); + bool SelectShiftShifterOperandReg(SDValue N, SDValue &A, + SDValue &B, SDValue &C); + bool SelectAddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); + bool SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, SDValue &Opc); + + AddrMode2Type SelectAddrMode2Worker(SDValue N, SDValue &Base, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode2Base(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Opc) { + return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_BASE; + } + + bool SelectAddrMode2ShOp(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Opc) { + return SelectAddrMode2Worker(N, Base, Offset, Opc) == AM2_SHOP; + } + + bool SelectAddrMode2(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Opc) { + SelectAddrMode2Worker(N, Base, Offset, Opc); +// return SelectAddrMode2ShOp(N, Base, Offset, Opc); + // This always matches one way or another. + return true; + } + + bool SelectAddrMode2Offset(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode3(SDValue N, SDValue &Base, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode3Offset(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc); + bool SelectAddrMode5(SDValue N, SDValue &Base, + SDValue &Offset); + bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align); + bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset); + + bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label); + + // Thumb Addressing Modes: + bool SelectThumbAddrModeRR(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeRI(SDValue N, SDValue &Base, SDValue &Offset, + unsigned Scale); + bool SelectThumbAddrModeRI5S1(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeRI5S2(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeRI5S4(SDValue N, SDValue &Base, SDValue &Offset); + bool SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectThumbAddrModeSP(SDValue N, SDValue &Base, SDValue &OffImm); + + // Thumb 2 Addressing Modes: + bool SelectT2ShifterOperandReg(SDValue N, + SDValue &BaseReg, SDValue &Opc); + bool SelectT2AddrModeImm12(SDValue N, SDValue &Base, SDValue &OffImm); + bool SelectT2AddrModeImm8(SDValue N, SDValue &Base, + SDValue &OffImm); + bool SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, + SDValue &OffImm); + bool SelectT2AddrModeSoReg(SDValue N, SDValue &Base, + SDValue &OffReg, SDValue &ShImm); + + inline bool is_so_imm(unsigned Imm) const { + return ARM_AM::getSOImmVal(Imm) != -1; + } + + inline bool is_so_imm_not(unsigned Imm) const { + return ARM_AM::getSOImmVal(~Imm) != -1; + } + + inline bool is_t2_so_imm(unsigned Imm) const { + return ARM_AM::getT2SOImmVal(Imm) != -1; + } + + inline bool is_t2_so_imm_not(unsigned Imm) const { + return ARM_AM::getT2SOImmVal(~Imm) != -1; + } + + inline bool Pred_so_imm(SDNode *inN) const { + ConstantSDNode *N = cast(inN); + return is_so_imm(N->getZExtValue()); + } + + inline bool Pred_t2_so_imm(SDNode *inN) const { + ConstantSDNode *N = cast(inN); + return is_t2_so_imm(N->getZExtValue()); + } + + // Include the pieces autogenerated from the target description. +#include "ARMGenDAGISel.inc" + +private: + /// SelectARMIndexedLoad - Indexed (pre/post inc/dec) load matching code for + /// ARM. + SDNode *SelectARMIndexedLoad(SDNode *N); + SDNode *SelectT2IndexedLoad(SDNode *N); + + /// SelectVLD - Select NEON load intrinsics. NumVecs should be + /// 1, 2, 3 or 4. The opcode arrays specify the instructions used for + /// loads of D registers and even subregs and odd subregs of Q registers. + /// For NumVecs <= 2, QOpcodes1 is not used. + SDNode *SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, + unsigned *QOpcodes0, unsigned *QOpcodes1); + + /// SelectVST - Select NEON store intrinsics. NumVecs should + /// be 1, 2, 3 or 4. The opcode arrays specify the instructions used for + /// stores of D registers and even subregs and odd subregs of Q registers. + /// For NumVecs <= 2, QOpcodes1 is not used. + SDNode *SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, + unsigned *QOpcodes0, unsigned *QOpcodes1); + + /// SelectVLDSTLane - Select NEON load/store lane intrinsics. NumVecs should + /// be 2, 3 or 4. The opcode arrays specify the instructions used for + /// load/store of D registers and Q registers. + SDNode *SelectVLDSTLane(SDNode *N, bool IsLoad, + bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes); + + /// SelectVLDDup - Select NEON load-duplicate intrinsics. NumVecs + /// should be 2, 3 or 4. The opcode array specifies the instructions used + /// for loading D registers. (Q registers are not supported.) + SDNode *SelectVLDDup(SDNode *N, bool isUpdating, unsigned NumVecs, + unsigned *Opcodes); + + /// SelectVTBL - Select NEON VTBL and VTBX intrinsics. NumVecs should be 2, + /// 3 or 4. These are custom-selected so that a REG_SEQUENCE can be + /// generated to force the table registers to be consecutive. + SDNode *SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, unsigned Opc); + + /// SelectV6T2BitfieldExtractOp - Select SBFX/UBFX instructions for ARM. + SDNode *SelectV6T2BitfieldExtractOp(SDNode *N, bool isSigned); + + /// SelectCMOVOp - Select CMOV instructions for ARM. + SDNode *SelectCMOVOp(SDNode *N); + SDNode *SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + SDNode *SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, + SDValue InFlag); + + SDNode *SelectConcatVector(SDNode *N); + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps); + + // Form pairs of consecutive S, D, or Q registers. + SDNode *PairSRegs(EVT VT, SDValue V0, SDValue V1); + SDNode *PairDRegs(EVT VT, SDValue V0, SDValue V1); + SDNode *PairQRegs(EVT VT, SDValue V0, SDValue V1); + + // Form sequences of 4 consecutive S, D, or Q registers. + SDNode *QuadSRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); + SDNode *QuadDRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); + SDNode *QuadQRegs(EVT VT, SDValue V0, SDValue V1, SDValue V2, SDValue V3); + + // Get the alignment operand for a NEON VLD or VST instruction. + SDValue GetVLDSTAlign(SDValue Align, unsigned NumVecs, bool is64BitVector); +}; +} + +/// isInt32Immediate - This method tests to see if the node is a 32-bit constant +/// operand. If so Imm will receive the 32-bit value. +static bool isInt32Immediate(SDNode *N, unsigned &Imm) { + if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { + Imm = cast(N)->getZExtValue(); + return true; + } + return false; +} + +// isInt32Immediate - This method tests to see if a constant operand. +// If so Imm will receive the 32 bit value. +static bool isInt32Immediate(SDValue N, unsigned &Imm) { + return isInt32Immediate(N.getNode(), Imm); +} + +// isOpcWithIntImmediate - This method tests to see if the node is a specific +// opcode and that it has a immediate integer right operand. +// If so Imm will receive the 32 bit value. +static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { + return N->getOpcode() == Opc && + isInt32Immediate(N->getOperand(1).getNode(), Imm); +} + +/// \brief Check whether a particular node is a constant value representable as +/// (N * Scale) where (N in [\arg RangeMin, \arg RangeMax). +/// +/// \param ScaledConstant [out] - On success, the pre-scaled constant value. +static bool isScaledConstantInRange(SDValue Node, unsigned Scale, + int RangeMin, int RangeMax, + int &ScaledConstant) { + assert(Scale && "Invalid scale!"); + + // Check that this is a constant. + const ConstantSDNode *C = dyn_cast(Node); + if (!C) + return false; + + ScaledConstant = (int) C->getZExtValue(); + if ((ScaledConstant % Scale) != 0) + return false; + + ScaledConstant /= Scale; + return ScaledConstant >= RangeMin && ScaledConstant < RangeMax; +} + +/// hasNoVMLxHazardUse - Return true if it's desirable to select a FP MLA / MLS +/// node. VFP / NEON fp VMLA / VMLS instructions have special RAW hazards (at +/// least on current ARM implementations) which should be avoidded. +bool ARMDAGToDAGISel::hasNoVMLxHazardUse(SDNode *N) const { + if (OptLevel == CodeGenOpt::None) + return true; + + if (!CheckVMLxHazard) + return true; + + if (!Subtarget->isCortexA8() && !Subtarget->isCortexA9()) + return true; + + if (!N->hasOneUse()) + return false; + + SDNode *Use = *N->use_begin(); + if (Use->getOpcode() == ISD::CopyToReg) + return true; + if (Use->isMachineOpcode()) { + const TargetInstrDesc &TID = TII->get(Use->getMachineOpcode()); + if (TID.mayStore()) + return true; + unsigned Opcode = TID.getOpcode(); + if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD) + return true; + // vmlx feeding into another vmlx. We actually want to unfold + // the use later in the MLxExpansion pass. e.g. + // vmla + // vmla (stall 8 cycles) + // + // vmul (5 cycles) + // vadd (5 cycles) + // vmla + // This adds up to about 18 - 19 cycles. + // + // vmla + // vmul (stall 4 cycles) + // vadd adds up to about 14 cycles. + return TII->isFpMLxInstruction(Opcode); + } + + return false; +} + +bool ARMDAGToDAGISel::isShifterOpProfitable(const SDValue &Shift, + ARM_AM::ShiftOpc ShOpcVal, + unsigned ShAmt) { + if (!Subtarget->isCortexA9()) + return true; + if (Shift.hasOneUse()) + return true; + // R << 2 is free. + return ShOpcVal == ARM_AM::lsl && ShAmt == 2; +} + +bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue N, + SDValue &BaseReg, + SDValue &ShReg, + SDValue &Opc) { + if (DisableShifterOp) + return false; + + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + ShReg = CurDAG->getRegister(0, MVT::i32); + ShImmVal = RHS->getZExtValue() & 31; + } else { + ShReg = N.getOperand(1); + if (!isShifterOpProfitable(N, ShOpcVal, ShImmVal)) + return false; + } + Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectShiftShifterOperandReg(SDValue N, + SDValue &BaseReg, + SDValue &ShReg, + SDValue &Opc) { + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + // Do not check isShifterOpProfitable. This must return true. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + ShReg = CurDAG->getRegister(0, MVT::i32); + ShImmVal = RHS->getZExtValue() & 31; + } else { + ShReg = N.getOperand(1); + } + Opc = CurDAG->getTargetConstant(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrModeImm12(SDValue N, + SDValue &Base, + SDValue &OffImm) { + // Match simple R + imm12 operands. + + // Base only. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && + !CurDAG->isBaseWithConstantOffset(N)) { + if (N.getOpcode() == ISD::FrameIndex) { + // Match frame index. + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } else + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + // Base only. + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + + + +bool ARMDAGToDAGISel::SelectLdStSOReg(SDValue N, SDValue &Base, SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::MUL && + (!Subtarget->isCortexA9() || N.hasOneUse())) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + // X * [3,5,9] -> X + X * [2,4,8] etc. + int RHSC = (int)RHS->getZExtValue(); + if (RHSC & 1) { + RHSC = RHSC & ~1; + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + if (isPowerOf2_32(RHSC)) { + unsigned ShAmt = Log2_32(RHSC); + Base = Offset = N.getOperand(0); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, + ARM_AM::lsl), + MVT::i32); + return true; + } + } + } + } + + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && + // ISD::OR that is equivalent to an ISD::ADD. + !CurDAG->isBaseWithConstantOffset(N)) + return false; + + // Leave simple R +/- imm12 operands for LDRi12 + if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, + -0x1000+1, 0x1000, RHSC)) // 12 bits. + return false; + } + + if (Subtarget->isCortexA9() && !N.hasOneUse()) + // Compute R +/- (R << N) and reuse it. + return false; + + // Otherwise this is R +/- [possibly shifted] R. + ARM_AM::AddrOpc AddSub = N.getOpcode() == ISD::SUB ? ARM_AM::sub:ARM_AM::add; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + unsigned ShAmt = 0; + + Base = N.getOperand(0); + Offset = N.getOperand(1); + + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(1).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) + Offset = N.getOperand(1).getOperand(0); + else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + // Try matching (R shl C) + (R). + if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && + !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't + // fold it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(0).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (!Subtarget->isCortexA9() || + (N.hasOneUse() && + isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt))) { + Offset = N.getOperand(0).getOperand(0); + Base = N.getOperand(1); + } else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return true; +} + + + + +//----- + +AddrMode2Type ARMDAGToDAGISel::SelectAddrMode2Worker(SDValue N, + SDValue &Base, + SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::MUL && + (!Subtarget->isCortexA9() || N.hasOneUse())) { + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + // X * [3,5,9] -> X + X * [2,4,8] etc. + int RHSC = (int)RHS->getZExtValue(); + if (RHSC & 1) { + RHSC = RHSC & ~1; + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + if (isPowerOf2_32(RHSC)) { + unsigned ShAmt = Log2_32(RHSC); + Base = Offset = N.getOperand(0); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, + ARM_AM::lsl), + MVT::i32); + return AM2_SHOP; + } + } + } + } + + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && + // ISD::OR that is equivalent to an ADD. + !CurDAG->isBaseWithConstantOffset(N)) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, + ARM_AM::no_shift), + MVT::i32); + return AM2_BASE; + } + + // Match simple R +/- imm12 operands. + if (N.getOpcode() != ISD::SUB) { + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, + -0x1000+1, 0x1000, RHSC)) { // 12 bits. + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = - RHSC; + } + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, RHSC, + ARM_AM::no_shift), + MVT::i32); + return AM2_BASE; + } + } + + if (Subtarget->isCortexA9() && !N.hasOneUse()) { + // Compute R +/- (R << N) and reuse it. + Base = N; + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(ARM_AM::add, 0, + ARM_AM::no_shift), + MVT::i32); + return AM2_BASE; + } + + // Otherwise this is R +/- [possibly shifted] R. + ARM_AM::AddrOpc AddSub = N.getOpcode() != ISD::SUB ? ARM_AM::add:ARM_AM::sub; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(1)); + unsigned ShAmt = 0; + + Base = N.getOperand(0); + Offset = N.getOperand(1); + + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(1).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (isShifterOpProfitable(Offset, ShOpcVal, ShAmt)) + Offset = N.getOperand(1).getOperand(0); + else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + // Try matching (R shl C) + (R). + if (N.getOpcode() != ISD::SUB && ShOpcVal == ARM_AM::no_shift && + !(Subtarget->isCortexA9() || N.getOperand(0).hasOneUse())) { + ShOpcVal = ARM_AM::getShiftOpcForNode(N.getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't + // fold it. + if (ConstantSDNode *Sh = + dyn_cast(N.getOperand(0).getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (!Subtarget->isCortexA9() || + (N.hasOneUse() && + isShifterOpProfitable(N.getOperand(0), ShOpcVal, ShAmt))) { + Offset = N.getOperand(0).getOperand(0); + Base = N.getOperand(1); + } else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return AM2_SHOP; +} + +bool ARMDAGToDAGISel::SelectAddrMode2Offset(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + int Val; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x1000, Val)) { // 12 bits. + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, Val, + ARM_AM::no_shift), + MVT::i32); + return true; + } + + Offset = N; + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + unsigned ShAmt = 0; + if (ShOpcVal != ARM_AM::no_shift) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = dyn_cast(N.getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (isShifterOpProfitable(N, ShOpcVal, ShAmt)) + Offset = N.getOperand(0); + else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + Opc = CurDAG->getTargetConstant(ARM_AM::getAM2Opc(AddSub, ShAmt, ShOpcVal), + MVT::i32); + return true; +} + + +bool ARMDAGToDAGISel::SelectAddrMode3(SDValue N, + SDValue &Base, SDValue &Offset, + SDValue &Opc) { + if (N.getOpcode() == ISD::SUB) { + // X - C is canonicalize to X + -C, no need to handle it here. + Base = N.getOperand(0); + Offset = N.getOperand(1); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::sub, 0),MVT::i32); + return true; + } + + if (!CurDAG->isBaseWithConstantOffset(N)) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0),MVT::i32); + return true; + } + + // If the RHS is +/- imm8, fold into addr mode. + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/1, + -256 + 1, 256, RHSC)) { // 8 bits. + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + Offset = CurDAG->getRegister(0, MVT::i32); + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = -RHSC; + } + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, RHSC),MVT::i32); + return true; + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(ARM_AM::add, 0), MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode3Offset(SDNode *Op, SDValue N, + SDValue &Offset, SDValue &Opc) { + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + ARM_AM::AddrOpc AddSub = (AM == ISD::PRE_INC || AM == ISD::POST_INC) + ? ARM_AM::add : ARM_AM::sub; + int Val; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 256, Val)) { // 12 bits. + Offset = CurDAG->getRegister(0, MVT::i32); + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, Val), MVT::i32); + return true; + } + + Offset = N; + Opc = CurDAG->getTargetConstant(ARM_AM::getAM3Opc(AddSub, 0), MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode5(SDValue N, + SDValue &Base, SDValue &Offset) { + if (!CurDAG->isBaseWithConstantOffset(N)) { + Base = N; + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } else if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), + MVT::i32); + return true; + } + + // If the RHS is +/- imm8, fold into addr mode. + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, + -256 + 1, 256, RHSC)) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + + ARM_AM::AddrOpc AddSub = ARM_AM::add; + if (RHSC < 0) { + AddSub = ARM_AM::sub; + RHSC = -RHSC; + } + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(AddSub, RHSC), + MVT::i32); + return true; + } + + Base = N; + Offset = CurDAG->getTargetConstant(ARM_AM::getAM5Opc(ARM_AM::add, 0), + MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr, + SDValue &Align) { + Addr = N; + + unsigned Alignment = 0; + if (LSBaseSDNode *LSN = dyn_cast(Parent)) { + // This case occurs only for VLD1-lane/dup and VST1-lane instructions. + // The maximum alignment is equal to the memory size being referenced. + unsigned LSNAlign = LSN->getAlignment(); + unsigned MemSize = LSN->getMemoryVT().getSizeInBits() / 8; + if (LSNAlign > MemSize && MemSize > 1) + Alignment = MemSize; + } else { + // All other uses of addrmode6 are for intrinsics. For now just record + // the raw alignment value; it will be refined later based on the legal + // alignment operands for the intrinsic. + Alignment = cast(Parent)->getAlignment(); + } + + Align = CurDAG->getTargetConstant(Alignment, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N, + SDValue &Offset) { + LSBaseSDNode *LdSt = cast(Op); + ISD::MemIndexedMode AM = LdSt->getAddressingMode(); + if (AM != ISD::POST_INC) + return false; + Offset = N; + if (ConstantSDNode *NC = dyn_cast(N)) { + if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits()) + Offset = CurDAG->getRegister(0, MVT::i32); + } + return true; +} + +bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N, + SDValue &Offset, SDValue &Label) { + if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) { + Offset = N.getOperand(0); + SDValue N1 = N.getOperand(1); + Label = CurDAG->getTargetConstant(cast(N1)->getZExtValue(), + MVT::i32); + return true; + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Thumb Addressing Modes +//===----------------------------------------------------------------------===// + +bool ARMDAGToDAGISel::SelectThumbAddrModeRR(SDValue N, + SDValue &Base, SDValue &Offset){ + if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) { + ConstantSDNode *NC = dyn_cast(N); + if (!NC || !NC->isNullValue()) + return false; + + Base = Offset = N; + return true; + } + + Base = N.getOperand(0); + Offset = N.getOperand(1); + return true; +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI(SDValue N, SDValue &Base, + SDValue &Offset, unsigned Scale) { + if (Scale == 4) { + SDValue TmpBase, TmpOffImm; + if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) + return false; // We want to select tLDRspi / tSTRspi instead. + + if (N.getOpcode() == ARMISD::Wrapper && + N.getOperand(0).getOpcode() == ISD::TargetConstantPool) + return false; // We want to select tLDRpci instead. + } + + if (!CurDAG->isBaseWithConstantOffset(N)) + return false; + + // Thumb does not have [sp, r] address mode. + RegisterSDNode *LHSR = dyn_cast(N.getOperand(0)); + RegisterSDNode *RHSR = dyn_cast(N.getOperand(1)); + if ((LHSR && LHSR->getReg() == ARM::SP) || + (RHSR && RHSR->getReg() == ARM::SP)) + return false; + + // FIXME: Why do we explicitly check for a match here and then return false? + // Presumably to allow something else to match, but shouldn't this be + // documented? + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) + return false; + + Base = N.getOperand(0); + Offset = N.getOperand(1); + return true; +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S1(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 1); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S2(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 2); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeRI5S4(SDValue N, + SDValue &Base, + SDValue &Offset) { + return SelectThumbAddrModeRI(N, Base, Offset, 4); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S(SDValue N, unsigned Scale, + SDValue &Base, SDValue &OffImm) { + if (Scale == 4) { + SDValue TmpBase, TmpOffImm; + if (SelectThumbAddrModeSP(N, TmpBase, TmpOffImm)) + return false; // We want to select tLDRspi / tSTRspi instead. + + if (N.getOpcode() == ARMISD::Wrapper && + N.getOperand(0).getOpcode() == ISD::TargetConstantPool) + return false; // We want to select tLDRpci instead. + } + + if (!CurDAG->isBaseWithConstantOffset(N)) { + if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + } else { + Base = N; + } + + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + RegisterSDNode *LHSR = dyn_cast(N.getOperand(0)); + RegisterSDNode *RHSR = dyn_cast(N.getOperand(1)); + if ((LHSR && LHSR->getReg() == ARM::SP) || + (RHSR && RHSR->getReg() == ARM::SP)) { + ConstantSDNode *LHS = dyn_cast(N.getOperand(0)); + ConstantSDNode *RHS = dyn_cast(N.getOperand(1)); + unsigned LHSC = LHS ? LHS->getZExtValue() : 0; + unsigned RHSC = RHS ? RHS->getZExtValue() : 0; + + // Thumb does not have [sp, #imm5] address mode for non-zero imm5. + if (LHSC != 0 || RHSC != 0) return false; + + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // If the RHS is + imm5 * scale, fold into addr mode. + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), Scale, 0, 32, RHSC)) { + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + + Base = N.getOperand(0); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S4(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 4, Base, OffImm); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S2(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 2, Base, OffImm); +} + +bool +ARMDAGToDAGISel::SelectThumbAddrModeImm5S1(SDValue N, SDValue &Base, + SDValue &OffImm) { + return SelectThumbAddrModeImm5S(N, 1, Base, OffImm); +} + +bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue N, + SDValue &Base, SDValue &OffImm) { + if (N.getOpcode() == ISD::FrameIndex) { + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (!CurDAG->isBaseWithConstantOffset(N)) + return false; + + RegisterSDNode *LHSR = dyn_cast(N.getOperand(0)); + if (N.getOperand(0).getOpcode() == ISD::FrameIndex || + (LHSR && LHSR->getReg() == ARM::SP)) { + // If the RHS is + imm8 * scale, fold into addr mode. + int RHSC; + if (isScaledConstantInRange(N.getOperand(1), /*Scale=*/4, 0, 256, RHSC)) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Thumb 2 Addressing Modes +//===----------------------------------------------------------------------===// + + +bool ARMDAGToDAGISel::SelectT2ShifterOperandReg(SDValue N, SDValue &BaseReg, + SDValue &Opc) { + if (DisableShifterOp) + return false; + + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N); + + // Don't match base register only case. That is matched to a separate + // lower complexity pattern with explicit register operand. + if (ShOpcVal == ARM_AM::no_shift) return false; + + BaseReg = N.getOperand(0); + unsigned ShImmVal = 0; + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + ShImmVal = RHS->getZExtValue() & 31; + Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal)); + return true; + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm12(SDValue N, + SDValue &Base, SDValue &OffImm) { + // Match simple R + imm12 operands. + + // Base only. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && + !CurDAG->isBaseWithConstantOffset(N)) { + if (N.getOpcode() == ISD::FrameIndex) { + // Match frame index. + int FI = cast(N)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (N.getOpcode() == ARMISD::Wrapper && + !(Subtarget->useMovt() && + N.getOperand(0).getOpcode() == ISD::TargetGlobalAddress)) { + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::TargetConstantPool) + return false; // We want to select t2LDRpci instead. + } else + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + if (SelectT2AddrModeImm8(N, Base, OffImm)) + // Let t2LDRi8 handle (R - imm8). + return false; + + int RHSC = (int)RHS->getZExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if (RHSC >= 0 && RHSC < 0x1000) { // 12 bits (unsigned) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + // Base only. + Base = N; + OffImm = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue N, + SDValue &Base, SDValue &OffImm) { + // Match simple R - imm8 operands. + if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB && + !CurDAG->isBaseWithConstantOffset(N)) + return false; + + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getSExtValue(); + if (N.getOpcode() == ISD::SUB) + RHSC = -RHSC; + + if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative) + Base = N.getOperand(0); + if (Base.getOpcode() == ISD::FrameIndex) { + int FI = cast(Base)->getIndex(); + Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + } + OffImm = CurDAG->getTargetConstant(RHSC, MVT::i32); + return true; + } + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeImm8Offset(SDNode *Op, SDValue N, + SDValue &OffImm){ + unsigned Opcode = Op->getOpcode(); + ISD::MemIndexedMode AM = (Opcode == ISD::LOAD) + ? cast(Op)->getAddressingMode() + : cast(Op)->getAddressingMode(); + int RHSC; + if (isScaledConstantInRange(N, /*Scale=*/1, 0, 0x100, RHSC)) { // 8 bits. + OffImm = ((AM == ISD::PRE_INC) || (AM == ISD::POST_INC)) + ? CurDAG->getTargetConstant(RHSC, MVT::i32) + : CurDAG->getTargetConstant(-RHSC, MVT::i32); + return true; + } + + return false; +} + +bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue N, + SDValue &Base, + SDValue &OffReg, SDValue &ShImm) { + // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12. + if (N.getOpcode() != ISD::ADD && !CurDAG->isBaseWithConstantOffset(N)) + return false; + + // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8. + if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned) + return false; + else if (RHSC < 0 && RHSC >= -255) // 8 bits + return false; + } + + if (Subtarget->isCortexA9() && !N.hasOneUse()) { + // Compute R + (R << [1,2,3]) and reuse it. + Base = N; + return false; + } + + // Look for (R + R) or (R + (R << [1,2,3])). + unsigned ShAmt = 0; + Base = N.getOperand(0); + OffReg = N.getOperand(1); + + // Swap if it is ((R << c) + R). + ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(OffReg); + if (ShOpcVal != ARM_AM::lsl) { + ShOpcVal = ARM_AM::getShiftOpcForNode(Base); + if (ShOpcVal == ARM_AM::lsl) + std::swap(Base, OffReg); + } + + if (ShOpcVal == ARM_AM::lsl) { + // Check to see if the RHS of the shift is a constant, if not, we can't fold + // it. + if (ConstantSDNode *Sh = dyn_cast(OffReg.getOperand(1))) { + ShAmt = Sh->getZExtValue(); + if (ShAmt < 4 && isShifterOpProfitable(OffReg, ShOpcVal, ShAmt)) + OffReg = OffReg.getOperand(0); + else { + ShAmt = 0; + ShOpcVal = ARM_AM::no_shift; + } + } else { + ShOpcVal = ARM_AM::no_shift; + } + } + + ShImm = CurDAG->getTargetConstant(ShAmt, MVT::i32); + + return true; +} + +//===--------------------------------------------------------------------===// + +/// getAL - Returns a ARMCC::AL immediate node. +static inline SDValue getAL(SelectionDAG *CurDAG) { + return CurDAG->getTargetConstant((uint64_t)ARMCC::AL, MVT::i32); +} + +SDNode *ARMDAGToDAGISel::SelectARMIndexedLoad(SDNode *N) { + LoadSDNode *LD = cast(N); + ISD::MemIndexedMode AM = LD->getAddressingMode(); + if (AM == ISD::UNINDEXED) + return NULL; + + EVT LoadedVT = LD->getMemoryVT(); + SDValue Offset, AMOpc; + bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); + unsigned Opcode = 0; + bool Match = false; + if (LoadedVT == MVT::i32 && + SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { + Opcode = isPre ? ARM::LDR_PRE : ARM::LDR_POST; + Match = true; + } else if (LoadedVT == MVT::i16 && + SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = (LD->getExtensionType() == ISD::SEXTLOAD) + ? (isPre ? ARM::LDRSH_PRE : ARM::LDRSH_POST) + : (isPre ? ARM::LDRH_PRE : ARM::LDRH_POST); + } else if (LoadedVT == MVT::i8 || LoadedVT == MVT::i1) { + if (LD->getExtensionType() == ISD::SEXTLOAD) { + if (SelectAddrMode3Offset(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = isPre ? ARM::LDRSB_PRE : ARM::LDRSB_POST; + } + } else { + if (SelectAddrMode2Offset(N, LD->getOffset(), Offset, AMOpc)) { + Match = true; + Opcode = isPre ? ARM::LDRB_PRE : ARM::LDRB_POST; + } + } + } + + if (Match) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, Offset, AMOpc, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, + MVT::Other, Ops, 6); + } + + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectT2IndexedLoad(SDNode *N) { + LoadSDNode *LD = cast(N); + ISD::MemIndexedMode AM = LD->getAddressingMode(); + if (AM == ISD::UNINDEXED) + return NULL; + + EVT LoadedVT = LD->getMemoryVT(); + bool isSExtLd = LD->getExtensionType() == ISD::SEXTLOAD; + SDValue Offset; + bool isPre = (AM == ISD::PRE_INC) || (AM == ISD::PRE_DEC); + unsigned Opcode = 0; + bool Match = false; + if (SelectT2AddrModeImm8Offset(N, LD->getOffset(), Offset)) { + switch (LoadedVT.getSimpleVT().SimpleTy) { + case MVT::i32: + Opcode = isPre ? ARM::t2LDR_PRE : ARM::t2LDR_POST; + break; + case MVT::i16: + if (isSExtLd) + Opcode = isPre ? ARM::t2LDRSH_PRE : ARM::t2LDRSH_POST; + else + Opcode = isPre ? ARM::t2LDRH_PRE : ARM::t2LDRH_POST; + break; + case MVT::i8: + case MVT::i1: + if (isSExtLd) + Opcode = isPre ? ARM::t2LDRSB_PRE : ARM::t2LDRSB_POST; + else + Opcode = isPre ? ARM::t2LDRB_PRE : ARM::t2LDRB_POST; + break; + default: + return NULL; + } + Match = true; + } + + if (Match) { + SDValue Chain = LD->getChain(); + SDValue Base = LD->getBasePtr(); + SDValue Ops[]= { Base, Offset, getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), Chain }; + return CurDAG->getMachineNode(Opcode, N->getDebugLoc(), MVT::i32, MVT::i32, + MVT::Other, Ops, 5); + } + + return NULL; +} + +/// PairSRegs - Form a D register from a pair of S registers. +/// +SDNode *ARMDAGToDAGISel::PairSRegs(EVT VT, SDValue V0, SDValue V1) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); +} + +/// PairDRegs - Form a quad register from a pair of D registers. +/// +SDNode *ARMDAGToDAGISel::PairDRegs(EVT VT, SDValue V0, SDValue V1) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); +} + +/// PairQRegs - Form 4 consecutive D registers from a pair of Q registers. +/// +SDNode *ARMDAGToDAGISel::PairQRegs(EVT VT, SDValue V0, SDValue V1) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 4); +} + +/// QuadSRegs - Form 4 consecutive S registers. +/// +SDNode *ARMDAGToDAGISel::QuadSRegs(EVT VT, SDValue V0, SDValue V1, + SDValue V2, SDValue V3) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::ssub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::ssub_1, MVT::i32); + SDValue SubReg2 = CurDAG->getTargetConstant(ARM::ssub_2, MVT::i32); + SDValue SubReg3 = CurDAG->getTargetConstant(ARM::ssub_3, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); +} + +/// QuadDRegs - Form 4 consecutive D registers. +/// +SDNode *ARMDAGToDAGISel::QuadDRegs(EVT VT, SDValue V0, SDValue V1, + SDValue V2, SDValue V3) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::dsub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::dsub_1, MVT::i32); + SDValue SubReg2 = CurDAG->getTargetConstant(ARM::dsub_2, MVT::i32); + SDValue SubReg3 = CurDAG->getTargetConstant(ARM::dsub_3, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); +} + +/// QuadQRegs - Form 4 consecutive Q registers. +/// +SDNode *ARMDAGToDAGISel::QuadQRegs(EVT VT, SDValue V0, SDValue V1, + SDValue V2, SDValue V3) { + DebugLoc dl = V0.getNode()->getDebugLoc(); + SDValue SubReg0 = CurDAG->getTargetConstant(ARM::qsub_0, MVT::i32); + SDValue SubReg1 = CurDAG->getTargetConstant(ARM::qsub_1, MVT::i32); + SDValue SubReg2 = CurDAG->getTargetConstant(ARM::qsub_2, MVT::i32); + SDValue SubReg3 = CurDAG->getTargetConstant(ARM::qsub_3, MVT::i32); + const SDValue Ops[] = { V0, SubReg0, V1, SubReg1, V2, SubReg2, V3, SubReg3 }; + return CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl, VT, Ops, 8); +} + +/// GetVLDSTAlign - Get the alignment (in bytes) for the alignment operand +/// of a NEON VLD or VST instruction. The supported values depend on the +/// number of registers being loaded. +SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs, + bool is64BitVector) { + unsigned NumRegs = NumVecs; + if (!is64BitVector && NumVecs < 3) + NumRegs *= 2; + + unsigned Alignment = cast(Align)->getZExtValue(); + if (Alignment >= 32 && NumRegs == 4) + Alignment = 32; + else if (Alignment >= 16 && (NumRegs == 2 || NumRegs == 4)) + Alignment = 16; + else if (Alignment >= 8) + Alignment = 8; + else + Alignment = 0; + + return CurDAG->getTargetConstant(Alignment, MVT::i32); +} + +SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes0, + unsigned *QOpcodes1) { + assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range"); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, Align; + unsigned AddrOpIdx = isUpdating ? 1 : 2; + if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + EVT VT = N->getValueType(0); + bool is64BitVector = VT.is64BitVector(); + Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vld type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + case MVT::v1i64: OpcodeIndex = 3; break; + // Quad-register operations: + case MVT::v16i8: OpcodeIndex = 0; break; + case MVT::v8i16: OpcodeIndex = 1; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 2; break; + case MVT::v2i64: OpcodeIndex = 3; + assert(NumVecs == 1 && "v2i64 type only supported for VLD1"); + break; + } + + EVT ResTy; + if (NumVecs == 1) + ResTy = VT; + else { + unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; + if (!is64BitVector) + ResTyElts *= 2; + ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts); + } + std::vector ResTys; + ResTys.push_back(ResTy); + if (isUpdating) + ResTys.push_back(MVT::i32); + ResTys.push_back(MVT::Other); + + SDValue Pred = getAL(CurDAG); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SDNode *VLd; + SmallVector Ops; + + // Double registers and VLD1/VLD2 quad registers are directly supported. + if (is64BitVector || NumVecs <= 2) { + unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : + QOpcodes0[OpcodeIndex]); + Ops.push_back(MemAddr); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(AddrOpIdx + 1); + Ops.push_back(isa(Inc.getNode()) ? Reg0 : Inc); + } + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + + } else { + // Otherwise, quad registers are loaded with two separate instructions, + // where one loads the even registers and the other loads the odd registers. + EVT AddrTy = MemAddr.getValueType(); + + // Load the even subregs. This is always an updating load, so that it + // provides the address to the second load for the odd subregs. + SDValue ImplDef = + SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy), 0); + const SDValue OpsA[] = { MemAddr, Align, Reg0, ImplDef, Pred, Reg0, Chain }; + SDNode *VLdA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, + ResTy, AddrTy, MVT::Other, OpsA, 7); + Chain = SDValue(VLdA, 2); + + // Load the odd subregs. + Ops.push_back(SDValue(VLdA, 1)); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(AddrOpIdx + 1); + assert(isa(Inc.getNode()) && + "only constant post-increment update allowed for VLD3/4"); + (void)Inc; + Ops.push_back(Reg0); + } + Ops.push_back(SDValue(VLdA, 0)); + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + VLd = CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, + Ops.data(), Ops.size()); + } + + if (NumVecs == 1) + return VLd; + + // Extract out the subregisters. + SDValue SuperReg = SDValue(VLd, 0); + assert(ARM::dsub_7 == ARM::dsub_0+7 && + ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); + unsigned Sub0 = (is64BitVector ? ARM::dsub_0 : ARM::qsub_0); + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + ReplaceUses(SDValue(N, Vec), + CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); + ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1)); + if (isUpdating) + ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2)); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, unsigned *QOpcodes0, + unsigned *QOpcodes1) { + assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range"); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, Align; + unsigned AddrOpIdx = isUpdating ? 1 : 2; + unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) + if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + EVT VT = N->getOperand(Vec0Idx).getValueType(); + bool is64BitVector = VT.is64BitVector(); + Align = GetVLDSTAlign(Align, NumVecs, is64BitVector); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vst type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + case MVT::v1i64: OpcodeIndex = 3; break; + // Quad-register operations: + case MVT::v16i8: OpcodeIndex = 0; break; + case MVT::v8i16: OpcodeIndex = 1; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 2; break; + case MVT::v2i64: OpcodeIndex = 3; + assert(NumVecs == 1 && "v2i64 type only supported for VST1"); + break; + } + + std::vector ResTys; + if (isUpdating) + ResTys.push_back(MVT::i32); + ResTys.push_back(MVT::Other); + + SDValue Pred = getAL(CurDAG); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SmallVector Ops; + + // Double registers and VST1/VST2 quad registers are directly supported. + if (is64BitVector || NumVecs <= 2) { + SDValue SrcReg; + if (NumVecs == 1) { + SrcReg = N->getOperand(Vec0Idx); + } else if (is64BitVector) { + // Form a REG_SEQUENCE to force register allocation. + SDValue V0 = N->getOperand(Vec0Idx + 0); + SDValue V1 = N->getOperand(Vec0Idx + 1); + if (NumVecs == 2) + SrcReg = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); + else { + SDValue V2 = N->getOperand(Vec0Idx + 2); + // If it's a vst3, form a quad D-register and leave the last part as + // an undef. + SDValue V3 = (NumVecs == 3) + ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,dl,VT), 0) + : N->getOperand(Vec0Idx + 3); + SrcReg = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); + } + } else { + // Form a QQ register. + SDValue Q0 = N->getOperand(Vec0Idx); + SDValue Q1 = N->getOperand(Vec0Idx + 1); + SrcReg = SDValue(PairQRegs(MVT::v4i64, Q0, Q1), 0); + } + + unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : + QOpcodes0[OpcodeIndex]); + Ops.push_back(MemAddr); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(AddrOpIdx + 1); + Ops.push_back(isa(Inc.getNode()) ? Reg0 : Inc); + } + Ops.push_back(SrcReg); + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + return CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + } + + // Otherwise, quad registers are stored with two separate instructions, + // where one stores the even registers and the other stores the odd registers. + + // Form the QQQQ REG_SEQUENCE. + SDValue V0 = N->getOperand(Vec0Idx + 0); + SDValue V1 = N->getOperand(Vec0Idx + 1); + SDValue V2 = N->getOperand(Vec0Idx + 2); + SDValue V3 = (NumVecs == 3) + ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) + : N->getOperand(Vec0Idx + 3); + SDValue RegSeq = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0); + + // Store the even D registers. This is always an updating store, so that it + // provides the address to the second store for the odd subregs. + const SDValue OpsA[] = { MemAddr, Align, Reg0, RegSeq, Pred, Reg0, Chain }; + SDNode *VStA = CurDAG->getMachineNode(QOpcodes0[OpcodeIndex], dl, + MemAddr.getValueType(), + MVT::Other, OpsA, 7); + Chain = SDValue(VStA, 1); + + // Store the odd D registers. + Ops.push_back(SDValue(VStA, 0)); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(AddrOpIdx + 1); + assert(isa(Inc.getNode()) && + "only constant post-increment update allowed for VST3/4"); + (void)Inc; + Ops.push_back(Reg0); + } + Ops.push_back(RegSeq); + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + return CurDAG->getMachineNode(QOpcodes1[OpcodeIndex], dl, ResTys, + Ops.data(), Ops.size()); +} + +SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad, + bool isUpdating, unsigned NumVecs, + unsigned *DOpcodes, + unsigned *QOpcodes) { + assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range"); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, Align; + unsigned AddrOpIdx = isUpdating ? 1 : 2; + unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1) + if (!SelectAddrMode6(N, N->getOperand(AddrOpIdx), MemAddr, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + unsigned Lane = + cast(N->getOperand(Vec0Idx + NumVecs))->getZExtValue(); + EVT VT = N->getOperand(Vec0Idx).getValueType(); + bool is64BitVector = VT.is64BitVector(); + + unsigned Alignment = 0; + if (NumVecs != 3) { + Alignment = cast(Align)->getZExtValue(); + unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; + if (Alignment > NumBytes) + Alignment = NumBytes; + if (Alignment < 8 && Alignment < NumBytes) + Alignment = 0; + // Alignment must be a power of two; make sure of that. + Alignment = (Alignment & -Alignment); + if (Alignment == 1) + Alignment = 0; + } + Align = CurDAG->getTargetConstant(Alignment, MVT::i32); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vld/vst lane type"); + // Double-register operations: + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + // Quad-register operations: + case MVT::v8i16: OpcodeIndex = 0; break; + case MVT::v4f32: + case MVT::v4i32: OpcodeIndex = 1; break; + } + + std::vector ResTys; + if (IsLoad) { + unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; + if (!is64BitVector) + ResTyElts *= 2; + ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), + MVT::i64, ResTyElts)); + } + if (isUpdating) + ResTys.push_back(MVT::i32); + ResTys.push_back(MVT::Other); + + SDValue Pred = getAL(CurDAG); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + + SmallVector Ops; + Ops.push_back(MemAddr); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(AddrOpIdx + 1); + Ops.push_back(isa(Inc.getNode()) ? Reg0 : Inc); + } + + SDValue SuperReg; + SDValue V0 = N->getOperand(Vec0Idx + 0); + SDValue V1 = N->getOperand(Vec0Idx + 1); + if (NumVecs == 2) { + if (is64BitVector) + SuperReg = SDValue(PairDRegs(MVT::v2i64, V0, V1), 0); + else + SuperReg = SDValue(PairQRegs(MVT::v4i64, V0, V1), 0); + } else { + SDValue V2 = N->getOperand(Vec0Idx + 2); + SDValue V3 = (NumVecs == 3) + ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) + : N->getOperand(Vec0Idx + 3); + if (is64BitVector) + SuperReg = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); + else + SuperReg = SDValue(QuadQRegs(MVT::v8i64, V0, V1, V2, V3), 0); + } + Ops.push_back(SuperReg); + Ops.push_back(getI32Imm(Lane)); + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + + unsigned Opc = (is64BitVector ? DOpcodes[OpcodeIndex] : + QOpcodes[OpcodeIndex]); + SDNode *VLdLn = CurDAG->getMachineNode(Opc, dl, ResTys, + Ops.data(), Ops.size()); + if (!IsLoad) + return VLdLn; + + // Extract the subregisters. + SuperReg = SDValue(VLdLn, 0); + assert(ARM::dsub_7 == ARM::dsub_0+7 && + ARM::qsub_3 == ARM::qsub_0+3 && "Unexpected subreg numbering"); + unsigned Sub0 = is64BitVector ? ARM::dsub_0 : ARM::qsub_0; + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + ReplaceUses(SDValue(N, Vec), + CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg)); + ReplaceUses(SDValue(N, NumVecs), SDValue(VLdLn, 1)); + if (isUpdating) + ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdLn, 2)); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectVLDDup(SDNode *N, bool isUpdating, + unsigned NumVecs, unsigned *Opcodes) { + assert(NumVecs >=2 && NumVecs <= 4 && "VLDDup NumVecs out-of-range"); + DebugLoc dl = N->getDebugLoc(); + + SDValue MemAddr, Align; + if (!SelectAddrMode6(N, N->getOperand(1), MemAddr, Align)) + return NULL; + + SDValue Chain = N->getOperand(0); + EVT VT = N->getValueType(0); + + unsigned Alignment = 0; + if (NumVecs != 3) { + Alignment = cast(Align)->getZExtValue(); + unsigned NumBytes = NumVecs * VT.getVectorElementType().getSizeInBits()/8; + if (Alignment > NumBytes) + Alignment = NumBytes; + if (Alignment < 8 && Alignment < NumBytes) + Alignment = 0; + // Alignment must be a power of two; make sure of that. + Alignment = (Alignment & -Alignment); + if (Alignment == 1) + Alignment = 0; + } + Align = CurDAG->getTargetConstant(Alignment, MVT::i32); + + unsigned OpcodeIndex; + switch (VT.getSimpleVT().SimpleTy) { + default: llvm_unreachable("unhandled vld-dup type"); + case MVT::v8i8: OpcodeIndex = 0; break; + case MVT::v4i16: OpcodeIndex = 1; break; + case MVT::v2f32: + case MVT::v2i32: OpcodeIndex = 2; break; + } + + SDValue Pred = getAL(CurDAG); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SDValue SuperReg; + unsigned Opc = Opcodes[OpcodeIndex]; + SmallVector Ops; + Ops.push_back(MemAddr); + Ops.push_back(Align); + if (isUpdating) { + SDValue Inc = N->getOperand(2); + Ops.push_back(isa(Inc.getNode()) ? Reg0 : Inc); + } + Ops.push_back(Pred); + Ops.push_back(Reg0); + Ops.push_back(Chain); + + unsigned ResTyElts = (NumVecs == 3) ? 4 : NumVecs; + std::vector ResTys; + ResTys.push_back(EVT::getVectorVT(*CurDAG->getContext(), MVT::i64, ResTyElts)); + if (isUpdating) + ResTys.push_back(MVT::i32); + ResTys.push_back(MVT::Other); + SDNode *VLdDup = + CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), Ops.size()); + SuperReg = SDValue(VLdDup, 0); + + // Extract the subregisters. + assert(ARM::dsub_7 == ARM::dsub_0+7 && "Unexpected subreg numbering"); + unsigned SubIdx = ARM::dsub_0; + for (unsigned Vec = 0; Vec < NumVecs; ++Vec) + ReplaceUses(SDValue(N, Vec), + CurDAG->getTargetExtractSubreg(SubIdx+Vec, dl, VT, SuperReg)); + ReplaceUses(SDValue(N, NumVecs), SDValue(VLdDup, 1)); + if (isUpdating) + ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLdDup, 2)); + return NULL; +} + +SDNode *ARMDAGToDAGISel::SelectVTBL(SDNode *N, bool IsExt, unsigned NumVecs, + unsigned Opc) { + assert(NumVecs >= 2 && NumVecs <= 4 && "VTBL NumVecs out-of-range"); + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + unsigned FirstTblReg = IsExt ? 2 : 1; + + // Form a REG_SEQUENCE to force register allocation. + SDValue RegSeq; + SDValue V0 = N->getOperand(FirstTblReg + 0); + SDValue V1 = N->getOperand(FirstTblReg + 1); + if (NumVecs == 2) + RegSeq = SDValue(PairDRegs(MVT::v16i8, V0, V1), 0); + else { + SDValue V2 = N->getOperand(FirstTblReg + 2); + // If it's a vtbl3, form a quad D-register and leave the last part as + // an undef. + SDValue V3 = (NumVecs == 3) + ? SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, VT), 0) + : N->getOperand(FirstTblReg + 3); + RegSeq = SDValue(QuadDRegs(MVT::v4i64, V0, V1, V2, V3), 0); + } + + SmallVector Ops; + if (IsExt) + Ops.push_back(N->getOperand(1)); + Ops.push_back(RegSeq); + Ops.push_back(N->getOperand(FirstTblReg + NumVecs)); + Ops.push_back(getAL(CurDAG)); // predicate + Ops.push_back(CurDAG->getRegister(0, MVT::i32)); // predicate register + return CurDAG->getMachineNode(Opc, dl, VT, Ops.data(), Ops.size()); +} + +SDNode *ARMDAGToDAGISel::SelectV6T2BitfieldExtractOp(SDNode *N, + bool isSigned) { + if (!Subtarget->hasV6T2Ops()) + return NULL; + + unsigned Opc = isSigned ? (Subtarget->isThumb() ? ARM::t2SBFX : ARM::SBFX) + : (Subtarget->isThumb() ? ARM::t2UBFX : ARM::UBFX); + + + // For unsigned extracts, check for a shift right and mask + unsigned And_imm = 0; + if (N->getOpcode() == ISD::AND) { + if (isOpcWithIntImmediate(N, ISD::AND, And_imm)) { + + // The immediate is a mask of the low bits iff imm & (imm+1) == 0 + if (And_imm & (And_imm + 1)) + return NULL; + + unsigned Srl_imm = 0; + if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SRL, + Srl_imm)) { + assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); + + unsigned Width = CountTrailingOnes_32(And_imm); + unsigned LSB = Srl_imm; + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0).getOperand(0), + CurDAG->getTargetConstant(LSB, MVT::i32), + CurDAG->getTargetConstant(Width, MVT::i32), + getAL(CurDAG), Reg0 }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + } + return NULL; + } + + // Otherwise, we're looking for a shift of a shift + unsigned Shl_imm = 0; + if (isOpcWithIntImmediate(N->getOperand(0).getNode(), ISD::SHL, Shl_imm)) { + assert(Shl_imm > 0 && Shl_imm < 32 && "bad amount in shift node!"); + unsigned Srl_imm = 0; + if (isInt32Immediate(N->getOperand(1), Srl_imm)) { + assert(Srl_imm > 0 && Srl_imm < 32 && "bad amount in shift node!"); + unsigned Width = 32 - Srl_imm; + int LSB = Srl_imm - Shl_imm; + if (LSB < 0) + return NULL; + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0).getOperand(0), + CurDAG->getTargetConstant(LSB, MVT::i32), + CurDAG->getTargetConstant(Width, MVT::i32), + getAL(CurDAG), Reg0 }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + } + return NULL; +} + +SDNode *ARMDAGToDAGISel:: +SelectT2CMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + SDValue CPTmp0; + SDValue CPTmp1; + if (SelectT2ShifterOperandReg(TrueVal, CPTmp0, CPTmp1)) { + unsigned SOVal = cast(CPTmp1)->getZExtValue(); + unsigned SOShOp = ARM_AM::getSORegShOp(SOVal); + unsigned Opc = 0; + switch (SOShOp) { + case ARM_AM::lsl: Opc = ARM::t2MOVCClsl; break; + case ARM_AM::lsr: Opc = ARM::t2MOVCClsr; break; + case ARM_AM::asr: Opc = ARM::t2MOVCCasr; break; + case ARM_AM::ror: Opc = ARM::t2MOVCCror; break; + default: + llvm_unreachable("Unknown so_reg opcode!"); + break; + } + SDValue SOShImm = + CurDAG->getTargetConstant(ARM_AM::getSORegOffset(SOVal), MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, CPTmp0, SOShImm, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32,Ops, 6); + } + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectARMCMOVShiftOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + SDValue CPTmp0; + SDValue CPTmp1; + SDValue CPTmp2; + if (SelectShifterOperandReg(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(N, ARM::MOVCCs, MVT::i32, Ops, 7); + } + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectT2CMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + ConstantSDNode *T = dyn_cast(TrueVal); + if (!T) + return 0; + + unsigned Opc = 0; + unsigned TrueImm = T->getZExtValue(); + if (is_t2_so_imm(TrueImm)) { + Opc = ARM::t2MOVCCi; + } else if (TrueImm <= 0xffff) { + Opc = ARM::t2MOVCCi16; + } else if (is_t2_so_imm_not(TrueImm)) { + TrueImm = ~TrueImm; + Opc = ARM::t2MVNCCi; + } else if (TrueVal.getNode()->hasOneUse() && Subtarget->hasV6T2Ops()) { + // Large immediate. + Opc = ARM::t2MOVCCi32imm; + } + + if (Opc) { + SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + + return 0; +} + +SDNode *ARMDAGToDAGISel:: +SelectARMCMOVImmOp(SDNode *N, SDValue FalseVal, SDValue TrueVal, + ARMCC::CondCodes CCVal, SDValue CCR, SDValue InFlag) { + ConstantSDNode *T = dyn_cast(TrueVal); + if (!T) + return 0; + + unsigned Opc = 0; + unsigned TrueImm = T->getZExtValue(); + bool isSoImm = is_so_imm(TrueImm); + if (isSoImm) { + Opc = ARM::MOVCCi; + } else if (Subtarget->hasV6T2Ops() && TrueImm <= 0xffff) { + Opc = ARM::MOVCCi16; + } else if (is_so_imm_not(TrueImm)) { + TrueImm = ~TrueImm; + Opc = ARM::MVNCCi; + } else if (TrueVal.getNode()->hasOneUse() && + (Subtarget->hasV6T2Ops() || ARM_AM::isSOImmTwoPartVal(TrueImm))) { + // Large immediate. + Opc = ARM::MOVCCi32imm; + } + + if (Opc) { + SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); + SDValue CC = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, True, CC, CCR, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + + return 0; +} + +SDNode *ARMDAGToDAGISel::SelectCMOVOp(SDNode *N) { + EVT VT = N->getValueType(0); + SDValue FalseVal = N->getOperand(0); + SDValue TrueVal = N->getOperand(1); + SDValue CC = N->getOperand(2); + SDValue CCR = N->getOperand(3); + SDValue InFlag = N->getOperand(4); + assert(CC.getOpcode() == ISD::Constant); + assert(CCR.getOpcode() == ISD::Register); + ARMCC::CondCodes CCVal = + (ARMCC::CondCodes)cast(CC)->getZExtValue(); + + if (!Subtarget->isThumb1Only() && VT == MVT::i32) { + // Pattern: (ARMcmov:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) + // Emits: (MOVCCs:i32 GPR:i32:$false, so_reg:i32:$true, (imm:i32):$cc) + // Pattern complexity = 18 cost = 1 size = 0 + SDValue CPTmp0; + SDValue CPTmp1; + SDValue CPTmp2; + if (Subtarget->isThumb()) { + SDNode *Res = SelectT2CMOVShiftOp(N, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectT2CMOVShiftOp(N, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } else { + SDNode *Res = SelectARMCMOVShiftOp(N, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectARMCMOVShiftOp(N, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } + + // Pattern: (ARMcmov:i32 GPR:i32:$false, + // (imm:i32)<>:$true, + // (imm:i32):$cc) + // Emits: (MOVCCi:i32 GPR:i32:$false, + // (so_imm:i32 (imm:i32):$true), (imm:i32):$cc) + // Pattern complexity = 10 cost = 1 size = 0 + if (Subtarget->isThumb()) { + SDNode *Res = SelectT2CMOVImmOp(N, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectT2CMOVImmOp(N, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } else { + SDNode *Res = SelectARMCMOVImmOp(N, FalseVal, TrueVal, + CCVal, CCR, InFlag); + if (!Res) + Res = SelectARMCMOVImmOp(N, TrueVal, FalseVal, + ARMCC::getOppositeCondition(CCVal), CCR, InFlag); + if (Res) + return Res; + } + } + + // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Emits: (MOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + // + // Pattern: (ARMcmov:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Emits: (tMOVCCr:i32 GPR:i32:$false, GPR:i32:$true, (imm:i32):$cc) + // Pattern complexity = 6 cost = 11 size = 0 + // + // Also FCPYScc and FCPYDcc. + SDValue Tmp2 = CurDAG->getTargetConstant(CCVal, MVT::i32); + SDValue Ops[] = { FalseVal, TrueVal, Tmp2, CCR, InFlag }; + unsigned Opc = 0; + switch (VT.getSimpleVT().SimpleTy) { + default: assert(false && "Illegal conditional move type!"); + break; + case MVT::i32: + Opc = Subtarget->isThumb() + ? (Subtarget->hasThumb2() ? ARM::t2MOVCCr : ARM::tMOVCCr_pseudo) + : ARM::MOVCCr; + break; + case MVT::f32: + Opc = ARM::VMOVScc; + break; + case MVT::f64: + Opc = ARM::VMOVDcc; + break; + } + return CurDAG->SelectNodeTo(N, Opc, VT, Ops, 5); +} + +SDNode *ARMDAGToDAGISel::SelectConcatVector(SDNode *N) { + // The only time a CONCAT_VECTORS operation can have legal types is when + // two 64-bit vectors are concatenated to a 128-bit vector. + EVT VT = N->getValueType(0); + if (!VT.is128BitVector() || N->getNumOperands() != 2) + llvm_unreachable("unexpected CONCAT_VECTORS"); + return PairDRegs(VT, N->getOperand(0), N->getOperand(1)); +} + +SDNode *ARMDAGToDAGISel::Select(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); + + if (N->isMachineOpcode()) + return NULL; // Already selected. + + switch (N->getOpcode()) { + default: break; + case ISD::Constant: { + unsigned Val = cast(N)->getZExtValue(); + bool UseCP = true; + if (Subtarget->hasThumb2()) + // Thumb2-aware targets have the MOVT instruction, so all immediates can + // be done with MOV + MOVT, at worst. + UseCP = 0; + else { + if (Subtarget->isThumb()) { + UseCP = (Val > 255 && // MOV + ~Val > 255 && // MOV + MVN + !ARM_AM::isThumbImmShiftedVal(Val)); // MOV + LSL + } else + UseCP = (ARM_AM::getSOImmVal(Val) == -1 && // MOV + ARM_AM::getSOImmVal(~Val) == -1 && // MVN + !ARM_AM::isSOImmTwoPartVal(Val)); // two instrs. + } + + if (UseCP) { + SDValue CPIdx = + CurDAG->getTargetConstantPool(ConstantInt::get( + Type::getInt32Ty(*CurDAG->getContext()), Val), + TLI.getPointerTy()); + + SDNode *ResNode; + if (Subtarget->isThumb1Only()) { + SDValue Pred = getAL(CurDAG); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { CPIdx, Pred, PredReg, CurDAG->getEntryNode() }; + ResNode = CurDAG->getMachineNode(ARM::tLDRpci, dl, MVT::i32, MVT::Other, + Ops, 4); + } else { + SDValue Ops[] = { + CPIdx, + CurDAG->getTargetConstant(0, MVT::i32), + getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32), + CurDAG->getEntryNode() + }; + ResNode=CurDAG->getMachineNode(ARM::LDRcp, dl, MVT::i32, MVT::Other, + Ops, 5); + } + ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0)); + return NULL; + } + + // Other cases are autogenerated. + break; + } + case ISD::FrameIndex: { + // Selects to ADDri FI, 0 which in turn will become ADDri SP, imm. + int FI = cast(N)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + if (Subtarget->isThumb1Only()) { + return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI, + CurDAG->getTargetConstant(0, MVT::i32)); + } else { + unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ? + ARM::t2ADDri : ARM::ADDri); + SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 5); + } + } + case ISD::SRL: + if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) + return I; + break; + case ISD::SRA: + if (SDNode *I = SelectV6T2BitfieldExtractOp(N, true)) + return I; + break; + case ISD::MUL: + if (Subtarget->isThumb1Only()) + break; + if (ConstantSDNode *C = dyn_cast(N->getOperand(1))) { + unsigned RHSV = C->getZExtValue(); + if (!RHSV) break; + if (isPowerOf2_32(RHSV-1)) { // 2^n+1? + unsigned ShImm = Log2_32(RHSV-1); + if (ShImm >= 32) + break; + SDValue V = N->getOperand(0); + ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); + SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + if (Subtarget->isThumb()) { + SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::t2ADDrs, MVT::i32, Ops, 6); + } else { + SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::ADDrs, MVT::i32, Ops, 7); + } + } + if (isPowerOf2_32(RHSV+1)) { // 2^n-1? + unsigned ShImm = Log2_32(RHSV+1); + if (ShImm >= 32) + break; + SDValue V = N->getOperand(0); + ShImm = ARM_AM::getSORegOpc(ARM_AM::lsl, ShImm); + SDValue ShImmOp = CurDAG->getTargetConstant(ShImm, MVT::i32); + SDValue Reg0 = CurDAG->getRegister(0, MVT::i32); + if (Subtarget->isThumb()) { + SDValue Ops[] = { V, V, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::t2RSBrs, MVT::i32, Ops, 6); + } else { + SDValue Ops[] = { V, V, Reg0, ShImmOp, getAL(CurDAG), Reg0, Reg0 }; + return CurDAG->SelectNodeTo(N, ARM::RSBrs, MVT::i32, Ops, 7); + } + } + } + break; + case ISD::AND: { + // Check for unsigned bitfield extract + if (SDNode *I = SelectV6T2BitfieldExtractOp(N, false)) + return I; + + // (and (or x, c2), c1) and top 16-bits of c1 and c2 match, lower 16-bits + // of c1 are 0xffff, and lower 16-bit of c2 are 0. That is, the top 16-bits + // are entirely contributed by c2 and lower 16-bits are entirely contributed + // by x. That's equal to (or (and x, 0xffff), (and c1, 0xffff0000)). + // Select it to: "movt x, ((c1 & 0xffff) >> 16) + EVT VT = N->getValueType(0); + if (VT != MVT::i32) + break; + unsigned Opc = (Subtarget->isThumb() && Subtarget->hasThumb2()) + ? ARM::t2MOVTi16 + : (Subtarget->hasV6T2Ops() ? ARM::MOVTi16 : 0); + if (!Opc) + break; + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + if (!N1C) + break; + if (N0.getOpcode() == ISD::OR && N0.getNode()->hasOneUse()) { + SDValue N2 = N0.getOperand(1); + ConstantSDNode *N2C = dyn_cast(N2); + if (!N2C) + break; + unsigned N1CVal = N1C->getZExtValue(); + unsigned N2CVal = N2C->getZExtValue(); + if ((N1CVal & 0xffff0000U) == (N2CVal & 0xffff0000U) && + (N1CVal & 0xffffU) == 0xffffU && + (N2CVal & 0xffffU) == 0x0U) { + SDValue Imm16 = CurDAG->getTargetConstant((N2CVal & 0xFFFF0000U) >> 16, + MVT::i32); + SDValue Ops[] = { N0.getOperand(0), Imm16, + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(Opc, dl, VT, Ops, 4); + } + } + break; + } + case ARMISD::VMOVRRD: + return CurDAG->getMachineNode(ARM::VMOVRRD, dl, MVT::i32, MVT::i32, + N->getOperand(0), getAL(CurDAG), + CurDAG->getRegister(0, MVT::i32)); + case ISD::UMUL_LOHI: { + if (Subtarget->isThumb1Only()) + break; + if (Subtarget->isThumb()) { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::t2UMULL, dl, MVT::i32, MVT::i32,Ops,4); + } else { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? + ARM::UMULL : ARM::UMULLv5, + dl, MVT::i32, MVT::i32, Ops, 5); + } + } + case ISD::SMUL_LOHI: { + if (Subtarget->isThumb1Only()) + break; + if (Subtarget->isThumb()) { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(ARM::t2SMULL, dl, MVT::i32, MVT::i32,Ops,4); + } else { + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), + getAL(CurDAG), CurDAG->getRegister(0, MVT::i32), + CurDAG->getRegister(0, MVT::i32) }; + return CurDAG->getMachineNode(Subtarget->hasV6Ops() ? + ARM::SMULL : ARM::SMULLv5, + dl, MVT::i32, MVT::i32, Ops, 5); + } + } + case ISD::LOAD: { + SDNode *ResNode = 0; + if (Subtarget->isThumb() && Subtarget->hasThumb2()) + ResNode = SelectT2IndexedLoad(N); + else + ResNode = SelectARMIndexedLoad(N); + if (ResNode) + return ResNode; + // Other cases are autogenerated. + break; + } + case ARMISD::BRCOND: { + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (Bcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (tBcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + // Pattern: (ARMbrcond:void (bb:Other):$dst, (imm:i32):$cc) + // Emits: (t2Bcc:void (bb:Other):$dst, (imm:i32):$cc) + // Pattern complexity = 6 cost = 1 size = 0 + + unsigned Opc = Subtarget->isThumb() ? + ((Subtarget->hasThumb2()) ? ARM::t2Bcc : ARM::tBcc) : ARM::Bcc; + SDValue Chain = N->getOperand(0); + SDValue N1 = N->getOperand(1); + SDValue N2 = N->getOperand(2); + SDValue N3 = N->getOperand(3); + SDValue InFlag = N->getOperand(4); + assert(N1.getOpcode() == ISD::BasicBlock); + assert(N2.getOpcode() == ISD::Constant); + assert(N3.getOpcode() == ISD::Register); + + SDValue Tmp2 = CurDAG->getTargetConstant(((unsigned) + cast(N2)->getZExtValue()), + MVT::i32); + SDValue Ops[] = { N1, Tmp2, N3, Chain, InFlag }; + SDNode *ResNode = CurDAG->getMachineNode(Opc, dl, MVT::Other, + MVT::Glue, Ops, 5); + Chain = SDValue(ResNode, 0); + if (N->getNumValues() == 2) { + InFlag = SDValue(ResNode, 1); + ReplaceUses(SDValue(N, 1), InFlag); + } + ReplaceUses(SDValue(N, 0), + SDValue(Chain.getNode(), Chain.getResNo())); + return NULL; + } + case ARMISD::CMOV: + return SelectCMOVOp(N); + case ARMISD::VZIP: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VZIPd8; break; + case MVT::v4i16: Opc = ARM::VZIPd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VZIPd32; break; + case MVT::v16i8: Opc = ARM::VZIPq8; break; + case MVT::v8i16: Opc = ARM::VZIPq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VZIPq32; break; + } + SDValue Pred = getAL(CurDAG); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + case ARMISD::VUZP: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VUZPd8; break; + case MVT::v4i16: Opc = ARM::VUZPd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VUZPd32; break; + case MVT::v16i8: Opc = ARM::VUZPq8; break; + case MVT::v8i16: Opc = ARM::VUZPq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VUZPq32; break; + } + SDValue Pred = getAL(CurDAG); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + case ARMISD::VTRN: { + unsigned Opc = 0; + EVT VT = N->getValueType(0); + switch (VT.getSimpleVT().SimpleTy) { + default: return NULL; + case MVT::v8i8: Opc = ARM::VTRNd8; break; + case MVT::v4i16: Opc = ARM::VTRNd16; break; + case MVT::v2f32: + case MVT::v2i32: Opc = ARM::VTRNd32; break; + case MVT::v16i8: Opc = ARM::VTRNq8; break; + case MVT::v8i16: Opc = ARM::VTRNq16; break; + case MVT::v4f32: + case MVT::v4i32: Opc = ARM::VTRNq32; break; + } + SDValue Pred = getAL(CurDAG); + SDValue PredReg = CurDAG->getRegister(0, MVT::i32); + SDValue Ops[] = { N->getOperand(0), N->getOperand(1), Pred, PredReg }; + return CurDAG->getMachineNode(Opc, dl, VT, VT, Ops, 4); + } + case ARMISD::BUILD_VECTOR: { + EVT VecVT = N->getValueType(0); + EVT EltVT = VecVT.getVectorElementType(); + unsigned NumElts = VecVT.getVectorNumElements(); + if (EltVT == MVT::f64) { + assert(NumElts == 2 && "unexpected type for BUILD_VECTOR"); + return PairDRegs(VecVT, N->getOperand(0), N->getOperand(1)); + } + assert(EltVT == MVT::f32 && "unexpected type for BUILD_VECTOR"); + if (NumElts == 2) + return PairSRegs(VecVT, N->getOperand(0), N->getOperand(1)); + assert(NumElts == 4 && "unexpected type for BUILD_VECTOR"); + return QuadSRegs(VecVT, N->getOperand(0), N->getOperand(1), + N->getOperand(2), N->getOperand(3)); + } + + case ARMISD::VLD2DUP: { + unsigned Opcodes[] = { ARM::VLD2DUPd8Pseudo, ARM::VLD2DUPd16Pseudo, + ARM::VLD2DUPd32Pseudo }; + return SelectVLDDup(N, false, 2, Opcodes); + } + + case ARMISD::VLD3DUP: { + unsigned Opcodes[] = { ARM::VLD3DUPd8Pseudo, ARM::VLD3DUPd16Pseudo, + ARM::VLD3DUPd32Pseudo }; + return SelectVLDDup(N, false, 3, Opcodes); + } + + case ARMISD::VLD4DUP: { + unsigned Opcodes[] = { ARM::VLD4DUPd8Pseudo, ARM::VLD4DUPd16Pseudo, + ARM::VLD4DUPd32Pseudo }; + return SelectVLDDup(N, false, 4, Opcodes); + } + + case ARMISD::VLD2DUP_UPD: { + unsigned Opcodes[] = { ARM::VLD2DUPd8Pseudo_UPD, ARM::VLD2DUPd16Pseudo_UPD, + ARM::VLD2DUPd32Pseudo_UPD }; + return SelectVLDDup(N, true, 2, Opcodes); + } + + case ARMISD::VLD3DUP_UPD: { + unsigned Opcodes[] = { ARM::VLD3DUPd8Pseudo_UPD, ARM::VLD3DUPd16Pseudo_UPD, + ARM::VLD3DUPd32Pseudo_UPD }; + return SelectVLDDup(N, true, 3, Opcodes); + } + + case ARMISD::VLD4DUP_UPD: { + unsigned Opcodes[] = { ARM::VLD4DUPd8Pseudo_UPD, ARM::VLD4DUPd16Pseudo_UPD, + ARM::VLD4DUPd32Pseudo_UPD }; + return SelectVLDDup(N, true, 4, Opcodes); + } + + case ARMISD::VLD1_UPD: { + unsigned DOpcodes[] = { ARM::VLD1d8_UPD, ARM::VLD1d16_UPD, + ARM::VLD1d32_UPD, ARM::VLD1d64_UPD }; + unsigned QOpcodes[] = { ARM::VLD1q8Pseudo_UPD, ARM::VLD1q16Pseudo_UPD, + ARM::VLD1q32Pseudo_UPD, ARM::VLD1q64Pseudo_UPD }; + return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0); + } + + case ARMISD::VLD2_UPD: { + unsigned DOpcodes[] = { ARM::VLD2d8Pseudo_UPD, ARM::VLD2d16Pseudo_UPD, + ARM::VLD2d32Pseudo_UPD, ARM::VLD1q64Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VLD2q8Pseudo_UPD, ARM::VLD2q16Pseudo_UPD, + ARM::VLD2q32Pseudo_UPD }; + return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0); + } + + case ARMISD::VLD3_UPD: { + unsigned DOpcodes[] = { ARM::VLD3d8Pseudo_UPD, ARM::VLD3d16Pseudo_UPD, + ARM::VLD3d32Pseudo_UPD, ARM::VLD1d64TPseudo_UPD }; + unsigned QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, + ARM::VLD3q16Pseudo_UPD, + ARM::VLD3q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VLD3q8oddPseudo_UPD, + ARM::VLD3q16oddPseudo_UPD, + ARM::VLD3q32oddPseudo_UPD }; + return SelectVLD(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case ARMISD::VLD4_UPD: { + unsigned DOpcodes[] = { ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, + ARM::VLD4d32Pseudo_UPD, ARM::VLD1d64QPseudo_UPD }; + unsigned QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, + ARM::VLD4q16Pseudo_UPD, + ARM::VLD4q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VLD4q8oddPseudo_UPD, + ARM::VLD4q16oddPseudo_UPD, + ARM::VLD4q32oddPseudo_UPD }; + return SelectVLD(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case ARMISD::VLD2LN_UPD: { + unsigned DOpcodes[] = { ARM::VLD2LNd8Pseudo_UPD, ARM::VLD2LNd16Pseudo_UPD, + ARM::VLD2LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VLD2LNq16Pseudo_UPD, + ARM::VLD2LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, true, true, 2, DOpcodes, QOpcodes); + } + + case ARMISD::VLD3LN_UPD: { + unsigned DOpcodes[] = { ARM::VLD3LNd8Pseudo_UPD, ARM::VLD3LNd16Pseudo_UPD, + ARM::VLD3LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VLD3LNq16Pseudo_UPD, + ARM::VLD3LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, true, true, 3, DOpcodes, QOpcodes); + } + + case ARMISD::VLD4LN_UPD: { + unsigned DOpcodes[] = { ARM::VLD4LNd8Pseudo_UPD, ARM::VLD4LNd16Pseudo_UPD, + ARM::VLD4LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VLD4LNq16Pseudo_UPD, + ARM::VLD4LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, true, true, 4, DOpcodes, QOpcodes); + } + + case ARMISD::VST1_UPD: { + unsigned DOpcodes[] = { ARM::VST1d8_UPD, ARM::VST1d16_UPD, + ARM::VST1d32_UPD, ARM::VST1d64_UPD }; + unsigned QOpcodes[] = { ARM::VST1q8Pseudo_UPD, ARM::VST1q16Pseudo_UPD, + ARM::VST1q32Pseudo_UPD, ARM::VST1q64Pseudo_UPD }; + return SelectVST(N, true, 1, DOpcodes, QOpcodes, 0); + } + + case ARMISD::VST2_UPD: { + unsigned DOpcodes[] = { ARM::VST2d8Pseudo_UPD, ARM::VST2d16Pseudo_UPD, + ARM::VST2d32Pseudo_UPD, ARM::VST1q64Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VST2q8Pseudo_UPD, ARM::VST2q16Pseudo_UPD, + ARM::VST2q32Pseudo_UPD }; + return SelectVST(N, true, 2, DOpcodes, QOpcodes, 0); + } + + case ARMISD::VST3_UPD: { + unsigned DOpcodes[] = { ARM::VST3d8Pseudo_UPD, ARM::VST3d16Pseudo_UPD, + ARM::VST3d32Pseudo_UPD, ARM::VST1d64TPseudo_UPD }; + unsigned QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, + ARM::VST3q16Pseudo_UPD, + ARM::VST3q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VST3q8oddPseudo_UPD, + ARM::VST3q16oddPseudo_UPD, + ARM::VST3q32oddPseudo_UPD }; + return SelectVST(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case ARMISD::VST4_UPD: { + unsigned DOpcodes[] = { ARM::VST4d8Pseudo_UPD, ARM::VST4d16Pseudo_UPD, + ARM::VST4d32Pseudo_UPD, ARM::VST1d64QPseudo_UPD }; + unsigned QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, + ARM::VST4q16Pseudo_UPD, + ARM::VST4q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VST4q8oddPseudo_UPD, + ARM::VST4q16oddPseudo_UPD, + ARM::VST4q32oddPseudo_UPD }; + return SelectVST(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case ARMISD::VST2LN_UPD: { + unsigned DOpcodes[] = { ARM::VST2LNd8Pseudo_UPD, ARM::VST2LNd16Pseudo_UPD, + ARM::VST2LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VST2LNq16Pseudo_UPD, + ARM::VST2LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, false, true, 2, DOpcodes, QOpcodes); + } + + case ARMISD::VST3LN_UPD: { + unsigned DOpcodes[] = { ARM::VST3LNd8Pseudo_UPD, ARM::VST3LNd16Pseudo_UPD, + ARM::VST3LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VST3LNq16Pseudo_UPD, + ARM::VST3LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, false, true, 3, DOpcodes, QOpcodes); + } + + case ARMISD::VST4LN_UPD: { + unsigned DOpcodes[] = { ARM::VST4LNd8Pseudo_UPD, ARM::VST4LNd16Pseudo_UPD, + ARM::VST4LNd32Pseudo_UPD }; + unsigned QOpcodes[] = { ARM::VST4LNq16Pseudo_UPD, + ARM::VST4LNq32Pseudo_UPD }; + return SelectVLDSTLane(N, false, true, 4, DOpcodes, QOpcodes); + } + + case ISD::INTRINSIC_VOID: + case ISD::INTRINSIC_W_CHAIN: { + unsigned IntNo = cast(N->getOperand(1))->getZExtValue(); + switch (IntNo) { + default: + break; + + case Intrinsic::arm_neon_vld1: { + unsigned DOpcodes[] = { ARM::VLD1d8, ARM::VLD1d16, + ARM::VLD1d32, ARM::VLD1d64 }; + unsigned QOpcodes[] = { ARM::VLD1q8Pseudo, ARM::VLD1q16Pseudo, + ARM::VLD1q32Pseudo, ARM::VLD1q64Pseudo }; + return SelectVLD(N, false, 1, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vld2: { + unsigned DOpcodes[] = { ARM::VLD2d8Pseudo, ARM::VLD2d16Pseudo, + ARM::VLD2d32Pseudo, ARM::VLD1q64Pseudo }; + unsigned QOpcodes[] = { ARM::VLD2q8Pseudo, ARM::VLD2q16Pseudo, + ARM::VLD2q32Pseudo }; + return SelectVLD(N, false, 2, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vld3: { + unsigned DOpcodes[] = { ARM::VLD3d8Pseudo, ARM::VLD3d16Pseudo, + ARM::VLD3d32Pseudo, ARM::VLD1d64TPseudo }; + unsigned QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, + ARM::VLD3q16Pseudo_UPD, + ARM::VLD3q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VLD3q8oddPseudo, + ARM::VLD3q16oddPseudo, + ARM::VLD3q32oddPseudo }; + return SelectVLD(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld4: { + unsigned DOpcodes[] = { ARM::VLD4d8Pseudo, ARM::VLD4d16Pseudo, + ARM::VLD4d32Pseudo, ARM::VLD1d64QPseudo }; + unsigned QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, + ARM::VLD4q16Pseudo_UPD, + ARM::VLD4q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VLD4q8oddPseudo, + ARM::VLD4q16oddPseudo, + ARM::VLD4q32oddPseudo }; + return SelectVLD(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vld2lane: { + unsigned DOpcodes[] = { ARM::VLD2LNd8Pseudo, ARM::VLD2LNd16Pseudo, + ARM::VLD2LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VLD2LNq16Pseudo, ARM::VLD2LNq32Pseudo }; + return SelectVLDSTLane(N, true, false, 2, DOpcodes, QOpcodes); + } + + case Intrinsic::arm_neon_vld3lane: { + unsigned DOpcodes[] = { ARM::VLD3LNd8Pseudo, ARM::VLD3LNd16Pseudo, + ARM::VLD3LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VLD3LNq16Pseudo, ARM::VLD3LNq32Pseudo }; + return SelectVLDSTLane(N, true, false, 3, DOpcodes, QOpcodes); + } + + case Intrinsic::arm_neon_vld4lane: { + unsigned DOpcodes[] = { ARM::VLD4LNd8Pseudo, ARM::VLD4LNd16Pseudo, + ARM::VLD4LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VLD4LNq16Pseudo, ARM::VLD4LNq32Pseudo }; + return SelectVLDSTLane(N, true, false, 4, DOpcodes, QOpcodes); + } + + case Intrinsic::arm_neon_vst1: { + unsigned DOpcodes[] = { ARM::VST1d8, ARM::VST1d16, + ARM::VST1d32, ARM::VST1d64 }; + unsigned QOpcodes[] = { ARM::VST1q8Pseudo, ARM::VST1q16Pseudo, + ARM::VST1q32Pseudo, ARM::VST1q64Pseudo }; + return SelectVST(N, false, 1, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vst2: { + unsigned DOpcodes[] = { ARM::VST2d8Pseudo, ARM::VST2d16Pseudo, + ARM::VST2d32Pseudo, ARM::VST1q64Pseudo }; + unsigned QOpcodes[] = { ARM::VST2q8Pseudo, ARM::VST2q16Pseudo, + ARM::VST2q32Pseudo }; + return SelectVST(N, false, 2, DOpcodes, QOpcodes, 0); + } + + case Intrinsic::arm_neon_vst3: { + unsigned DOpcodes[] = { ARM::VST3d8Pseudo, ARM::VST3d16Pseudo, + ARM::VST3d32Pseudo, ARM::VST1d64TPseudo }; + unsigned QOpcodes0[] = { ARM::VST3q8Pseudo_UPD, + ARM::VST3q16Pseudo_UPD, + ARM::VST3q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VST3q8oddPseudo, + ARM::VST3q16oddPseudo, + ARM::VST3q32oddPseudo }; + return SelectVST(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst4: { + unsigned DOpcodes[] = { ARM::VST4d8Pseudo, ARM::VST4d16Pseudo, + ARM::VST4d32Pseudo, ARM::VST1d64QPseudo }; + unsigned QOpcodes0[] = { ARM::VST4q8Pseudo_UPD, + ARM::VST4q16Pseudo_UPD, + ARM::VST4q32Pseudo_UPD }; + unsigned QOpcodes1[] = { ARM::VST4q8oddPseudo, + ARM::VST4q16oddPseudo, + ARM::VST4q32oddPseudo }; + return SelectVST(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1); + } + + case Intrinsic::arm_neon_vst2lane: { + unsigned DOpcodes[] = { ARM::VST2LNd8Pseudo, ARM::VST2LNd16Pseudo, + ARM::VST2LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VST2LNq16Pseudo, ARM::VST2LNq32Pseudo }; + return SelectVLDSTLane(N, false, false, 2, DOpcodes, QOpcodes); + } + + case Intrinsic::arm_neon_vst3lane: { + unsigned DOpcodes[] = { ARM::VST3LNd8Pseudo, ARM::VST3LNd16Pseudo, + ARM::VST3LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VST3LNq16Pseudo, ARM::VST3LNq32Pseudo }; + return SelectVLDSTLane(N, false, false, 3, DOpcodes, QOpcodes); + } + + case Intrinsic::arm_neon_vst4lane: { + unsigned DOpcodes[] = { ARM::VST4LNd8Pseudo, ARM::VST4LNd16Pseudo, + ARM::VST4LNd32Pseudo }; + unsigned QOpcodes[] = { ARM::VST4LNq16Pseudo, ARM::VST4LNq32Pseudo }; + return SelectVLDSTLane(N, false, false, 4, DOpcodes, QOpcodes); + } + } + break; + } + + case ISD::INTRINSIC_WO_CHAIN: { + unsigned IntNo = cast(N->getOperand(0))->getZExtValue(); + switch (IntNo) { + default: + break; + + case Intrinsic::arm_neon_vtbl2: + return SelectVTBL(N, false, 2, ARM::VTBL2Pseudo); + case Intrinsic::arm_neon_vtbl3: + return SelectVTBL(N, false, 3, ARM::VTBL3Pseudo); + case Intrinsic::arm_neon_vtbl4: + return SelectVTBL(N, false, 4, ARM::VTBL4Pseudo); + + case Intrinsic::arm_neon_vtbx2: + return SelectVTBL(N, true, 2, ARM::VTBX2Pseudo); + case Intrinsic::arm_neon_vtbx3: + return SelectVTBL(N, true, 3, ARM::VTBX3Pseudo); + case Intrinsic::arm_neon_vtbx4: + return SelectVTBL(N, true, 4, ARM::VTBX4Pseudo); + } + break; + } + + case ISD::CONCAT_VECTORS: + return SelectConcatVector(N); + } + + return SelectCode(N); +} + +bool ARMDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector &OutOps) { + assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); + // Require the address to be in a register. That is safe for all ARM + // variants and it is hard to do anything much smarter without knowing + // how the operand is used. + OutOps.push_back(Op); + return false; +} + +/// createARMISelDag - This pass converts a legalized DAG into a +/// ARM-specific DAG, ready for instruction scheduling. +/// +FunctionPass *llvm::createARMISelDag(ARMBaseTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new ARMDAGToDAGISel(TM, OptLevel); +} diff --git a/final/lib/Target/ARM/ARMISelLowering.cpp b/final/lib/Target/ARM/ARMISelLowering.cpp new file mode 100644 index 00000000000..82e37c7075c --- /dev/null +++ b/final/lib/Target/ARM/ARMISelLowering.cpp @@ -0,0 +1,7055 @@ +//===-- ARMISelLowering.cpp - ARM DAG Lowering Implementation -------------===// +// +// 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 interfaces that ARM uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "arm-isel" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMCallingConv.h" +#include "ARMConstantPoolValue.h" +#include "ARMISelLowering.h" +#include "ARMMachineFunctionInfo.h" +#include "ARMPerfectShuffle.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "ARMTargetObjectFile.h" +#include "llvm/CallingConv.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instruction.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/IntrinsicLowering.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include +using namespace llvm; + +STATISTIC(NumTailCalls, "Number of tail calls"); +STATISTIC(NumMovwMovt, "Number of GAs materialized with movw + movt"); + +// This option should go away when tail calls fully work. +static cl::opt +EnableARMTailCalls("arm-tail-calls", cl::Hidden, + cl::desc("Generate tail calls (TEMPORARY OPTION)."), + cl::init(false)); + +cl::opt +EnableARMLongCalls("arm-long-calls", cl::Hidden, + cl::desc("Generate calls via indirect call instructions"), + cl::init(false)); + +static cl::opt +ARMInterworking("arm-interworking", cl::Hidden, + cl::desc("Enable / disable ARM interworking (for debugging only)"), + cl::init(true)); + +void ARMTargetLowering::addTypeForNEON(EVT VT, EVT PromotedLdStVT, + EVT PromotedBitwiseVT) { + if (VT != PromotedLdStVT) { + setOperationAction(ISD::LOAD, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::LOAD, VT.getSimpleVT(), + PromotedLdStVT.getSimpleVT()); + + setOperationAction(ISD::STORE, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::STORE, VT.getSimpleVT(), + PromotedLdStVT.getSimpleVT()); + } + + EVT ElemTy = VT.getVectorElementType(); + if (ElemTy != MVT::i64 && ElemTy != MVT::f64) + setOperationAction(ISD::VSETCC, VT.getSimpleVT(), Custom); + setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT.getSimpleVT(), Custom); + if (ElemTy != MVT::i32) { + setOperationAction(ISD::SINT_TO_FP, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UINT_TO_FP, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FP_TO_SINT, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FP_TO_UINT, VT.getSimpleVT(), Expand); + } + setOperationAction(ISD::BUILD_VECTOR, VT.getSimpleVT(), Custom); + setOperationAction(ISD::VECTOR_SHUFFLE, VT.getSimpleVT(), Custom); + setOperationAction(ISD::CONCAT_VECTORS, VT.getSimpleVT(), Legal); + setOperationAction(ISD::EXTRACT_SUBVECTOR, VT.getSimpleVT(), Legal); + setOperationAction(ISD::SELECT, VT.getSimpleVT(), Expand); + setOperationAction(ISD::SELECT_CC, VT.getSimpleVT(), Expand); + if (VT.isInteger()) { + setOperationAction(ISD::SHL, VT.getSimpleVT(), Custom); + setOperationAction(ISD::SRA, VT.getSimpleVT(), Custom); + setOperationAction(ISD::SRL, VT.getSimpleVT(), Custom); + setLoadExtAction(ISD::SEXTLOAD, VT.getSimpleVT(), Expand); + setLoadExtAction(ISD::ZEXTLOAD, VT.getSimpleVT(), Expand); + for (unsigned InnerVT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; + InnerVT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++InnerVT) + setTruncStoreAction(VT.getSimpleVT(), + (MVT::SimpleValueType)InnerVT, Expand); + } + setLoadExtAction(ISD::EXTLOAD, VT.getSimpleVT(), Expand); + + // Promote all bit-wise operations. + if (VT.isInteger() && VT != PromotedBitwiseVT) { + setOperationAction(ISD::AND, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::AND, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + setOperationAction(ISD::OR, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::OR, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + setOperationAction(ISD::XOR, VT.getSimpleVT(), Promote); + AddPromotedToType (ISD::XOR, VT.getSimpleVT(), + PromotedBitwiseVT.getSimpleVT()); + } + + // Neon does not support vector divide/remainder operations. + setOperationAction(ISD::SDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FDIV, VT.getSimpleVT(), Expand); + setOperationAction(ISD::SREM, VT.getSimpleVT(), Expand); + setOperationAction(ISD::UREM, VT.getSimpleVT(), Expand); + setOperationAction(ISD::FREM, VT.getSimpleVT(), Expand); +} + +void ARMTargetLowering::addDRTypeForNEON(EVT VT) { + addRegisterClass(VT, ARM::DPRRegisterClass); + addTypeForNEON(VT, MVT::f64, MVT::v2i32); +} + +void ARMTargetLowering::addQRTypeForNEON(EVT VT) { + addRegisterClass(VT, ARM::QPRRegisterClass); + addTypeForNEON(VT, MVT::v2f64, MVT::v4i32); +} + +static TargetLoweringObjectFile *createTLOF(TargetMachine &TM) { + if (TM.getSubtarget().isTargetDarwin()) + return new TargetLoweringObjectFileMachO(); + + return new ARMElfTargetObjectFile(); +} + +ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) + : TargetLowering(TM, createTLOF(TM)) { + Subtarget = &TM.getSubtarget(); + RegInfo = TM.getRegisterInfo(); + Itins = TM.getInstrItineraryData(); + + if (Subtarget->isTargetDarwin()) { + // Uses VFP for Thumb libfuncs if available. + if (Subtarget->isThumb() && Subtarget->hasVFP2()) { + // Single-precision floating-point arithmetic. + setLibcallName(RTLIB::ADD_F32, "__addsf3vfp"); + setLibcallName(RTLIB::SUB_F32, "__subsf3vfp"); + setLibcallName(RTLIB::MUL_F32, "__mulsf3vfp"); + setLibcallName(RTLIB::DIV_F32, "__divsf3vfp"); + + // Double-precision floating-point arithmetic. + setLibcallName(RTLIB::ADD_F64, "__adddf3vfp"); + setLibcallName(RTLIB::SUB_F64, "__subdf3vfp"); + setLibcallName(RTLIB::MUL_F64, "__muldf3vfp"); + setLibcallName(RTLIB::DIV_F64, "__divdf3vfp"); + + // Single-precision comparisons. + setLibcallName(RTLIB::OEQ_F32, "__eqsf2vfp"); + setLibcallName(RTLIB::UNE_F32, "__nesf2vfp"); + setLibcallName(RTLIB::OLT_F32, "__ltsf2vfp"); + setLibcallName(RTLIB::OLE_F32, "__lesf2vfp"); + setLibcallName(RTLIB::OGE_F32, "__gesf2vfp"); + setLibcallName(RTLIB::OGT_F32, "__gtsf2vfp"); + setLibcallName(RTLIB::UO_F32, "__unordsf2vfp"); + setLibcallName(RTLIB::O_F32, "__unordsf2vfp"); + + setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE); + setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ); + + // Double-precision comparisons. + setLibcallName(RTLIB::OEQ_F64, "__eqdf2vfp"); + setLibcallName(RTLIB::UNE_F64, "__nedf2vfp"); + setLibcallName(RTLIB::OLT_F64, "__ltdf2vfp"); + setLibcallName(RTLIB::OLE_F64, "__ledf2vfp"); + setLibcallName(RTLIB::OGE_F64, "__gedf2vfp"); + setLibcallName(RTLIB::OGT_F64, "__gtdf2vfp"); + setLibcallName(RTLIB::UO_F64, "__unorddf2vfp"); + setLibcallName(RTLIB::O_F64, "__unorddf2vfp"); + + setCmpLibcallCC(RTLIB::OEQ_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::UNE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLT_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OLE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGE_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::OGT_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::UO_F64, ISD::SETNE); + setCmpLibcallCC(RTLIB::O_F64, ISD::SETEQ); + + // Floating-point to integer conversions. + // i64 conversions are done via library routines even when generating VFP + // instructions, so use the same ones. + setLibcallName(RTLIB::FPTOSINT_F64_I32, "__fixdfsivfp"); + setLibcallName(RTLIB::FPTOUINT_F64_I32, "__fixunsdfsivfp"); + setLibcallName(RTLIB::FPTOSINT_F32_I32, "__fixsfsivfp"); + setLibcallName(RTLIB::FPTOUINT_F32_I32, "__fixunssfsivfp"); + + // Conversions between floating types. + setLibcallName(RTLIB::FPROUND_F64_F32, "__truncdfsf2vfp"); + setLibcallName(RTLIB::FPEXT_F32_F64, "__extendsfdf2vfp"); + + // Integer to floating-point conversions. + // i64 conversions are done via library routines even when generating VFP + // instructions, so use the same ones. + // FIXME: There appears to be some naming inconsistency in ARM libgcc: + // e.g., __floatunsidf vs. __floatunssidfvfp. + setLibcallName(RTLIB::SINTTOFP_I32_F64, "__floatsidfvfp"); + setLibcallName(RTLIB::UINTTOFP_I32_F64, "__floatunssidfvfp"); + setLibcallName(RTLIB::SINTTOFP_I32_F32, "__floatsisfvfp"); + setLibcallName(RTLIB::UINTTOFP_I32_F32, "__floatunssisfvfp"); + } + } + + // These libcalls are not available in 32-bit. + setLibcallName(RTLIB::SHL_I128, 0); + setLibcallName(RTLIB::SRL_I128, 0); + setLibcallName(RTLIB::SRA_I128, 0); + + if (Subtarget->isAAPCS_ABI()) { + // Double-precision floating-point arithmetic helper functions + // RTABI chapter 4.1.2, Table 2 + setLibcallName(RTLIB::ADD_F64, "__aeabi_dadd"); + setLibcallName(RTLIB::DIV_F64, "__aeabi_ddiv"); + setLibcallName(RTLIB::MUL_F64, "__aeabi_dmul"); + setLibcallName(RTLIB::SUB_F64, "__aeabi_dsub"); + setLibcallCallingConv(RTLIB::ADD_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::DIV_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::MUL_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SUB_F64, CallingConv::ARM_AAPCS); + + // Double-precision floating-point comparison helper functions + // RTABI chapter 4.1.2, Table 3 + setLibcallName(RTLIB::OEQ_F64, "__aeabi_dcmpeq"); + setCmpLibcallCC(RTLIB::OEQ_F64, ISD::SETNE); + setLibcallName(RTLIB::UNE_F64, "__aeabi_dcmpeq"); + setCmpLibcallCC(RTLIB::UNE_F64, ISD::SETEQ); + setLibcallName(RTLIB::OLT_F64, "__aeabi_dcmplt"); + setCmpLibcallCC(RTLIB::OLT_F64, ISD::SETNE); + setLibcallName(RTLIB::OLE_F64, "__aeabi_dcmple"); + setCmpLibcallCC(RTLIB::OLE_F64, ISD::SETNE); + setLibcallName(RTLIB::OGE_F64, "__aeabi_dcmpge"); + setCmpLibcallCC(RTLIB::OGE_F64, ISD::SETNE); + setLibcallName(RTLIB::OGT_F64, "__aeabi_dcmpgt"); + setCmpLibcallCC(RTLIB::OGT_F64, ISD::SETNE); + setLibcallName(RTLIB::UO_F64, "__aeabi_dcmpun"); + setCmpLibcallCC(RTLIB::UO_F64, ISD::SETNE); + setLibcallName(RTLIB::O_F64, "__aeabi_dcmpun"); + setCmpLibcallCC(RTLIB::O_F64, ISD::SETEQ); + setLibcallCallingConv(RTLIB::OEQ_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UNE_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OLT_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OLE_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OGE_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OGT_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UO_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::O_F64, CallingConv::ARM_AAPCS); + + // Single-precision floating-point arithmetic helper functions + // RTABI chapter 4.1.2, Table 4 + setLibcallName(RTLIB::ADD_F32, "__aeabi_fadd"); + setLibcallName(RTLIB::DIV_F32, "__aeabi_fdiv"); + setLibcallName(RTLIB::MUL_F32, "__aeabi_fmul"); + setLibcallName(RTLIB::SUB_F32, "__aeabi_fsub"); + setLibcallCallingConv(RTLIB::ADD_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::DIV_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::MUL_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SUB_F32, CallingConv::ARM_AAPCS); + + // Single-precision floating-point comparison helper functions + // RTABI chapter 4.1.2, Table 5 + setLibcallName(RTLIB::OEQ_F32, "__aeabi_fcmpeq"); + setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE); + setLibcallName(RTLIB::UNE_F32, "__aeabi_fcmpeq"); + setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETEQ); + setLibcallName(RTLIB::OLT_F32, "__aeabi_fcmplt"); + setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE); + setLibcallName(RTLIB::OLE_F32, "__aeabi_fcmple"); + setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE); + setLibcallName(RTLIB::OGE_F32, "__aeabi_fcmpge"); + setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE); + setLibcallName(RTLIB::OGT_F32, "__aeabi_fcmpgt"); + setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE); + setLibcallName(RTLIB::UO_F32, "__aeabi_fcmpun"); + setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE); + setLibcallName(RTLIB::O_F32, "__aeabi_fcmpun"); + setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ); + setLibcallCallingConv(RTLIB::OEQ_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UNE_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OLT_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OLE_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OGE_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::OGT_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UO_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::O_F32, CallingConv::ARM_AAPCS); + + // Floating-point to integer conversions. + // RTABI chapter 4.1.2, Table 6 + setLibcallName(RTLIB::FPTOSINT_F64_I32, "__aeabi_d2iz"); + setLibcallName(RTLIB::FPTOUINT_F64_I32, "__aeabi_d2uiz"); + setLibcallName(RTLIB::FPTOSINT_F64_I64, "__aeabi_d2lz"); + setLibcallName(RTLIB::FPTOUINT_F64_I64, "__aeabi_d2ulz"); + setLibcallName(RTLIB::FPTOSINT_F32_I32, "__aeabi_f2iz"); + setLibcallName(RTLIB::FPTOUINT_F32_I32, "__aeabi_f2uiz"); + setLibcallName(RTLIB::FPTOSINT_F32_I64, "__aeabi_f2lz"); + setLibcallName(RTLIB::FPTOUINT_F32_I64, "__aeabi_f2ulz"); + setLibcallCallingConv(RTLIB::FPTOSINT_F64_I32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOUINT_F64_I32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOSINT_F64_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOUINT_F64_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOSINT_F32_I32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOUINT_F32_I32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOSINT_F32_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPTOUINT_F32_I64, CallingConv::ARM_AAPCS); + + // Conversions between floating types. + // RTABI chapter 4.1.2, Table 7 + setLibcallName(RTLIB::FPROUND_F64_F32, "__aeabi_d2f"); + setLibcallName(RTLIB::FPEXT_F32_F64, "__aeabi_f2d"); + setLibcallCallingConv(RTLIB::FPROUND_F64_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::FPEXT_F32_F64, CallingConv::ARM_AAPCS); + + // Integer to floating-point conversions. + // RTABI chapter 4.1.2, Table 8 + setLibcallName(RTLIB::SINTTOFP_I32_F64, "__aeabi_i2d"); + setLibcallName(RTLIB::UINTTOFP_I32_F64, "__aeabi_ui2d"); + setLibcallName(RTLIB::SINTTOFP_I64_F64, "__aeabi_l2d"); + setLibcallName(RTLIB::UINTTOFP_I64_F64, "__aeabi_ul2d"); + setLibcallName(RTLIB::SINTTOFP_I32_F32, "__aeabi_i2f"); + setLibcallName(RTLIB::UINTTOFP_I32_F32, "__aeabi_ui2f"); + setLibcallName(RTLIB::SINTTOFP_I64_F32, "__aeabi_l2f"); + setLibcallName(RTLIB::UINTTOFP_I64_F32, "__aeabi_ul2f"); + setLibcallCallingConv(RTLIB::SINTTOFP_I32_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UINTTOFP_I32_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SINTTOFP_I64_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UINTTOFP_I64_F64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SINTTOFP_I32_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UINTTOFP_I32_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SINTTOFP_I64_F32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UINTTOFP_I64_F32, CallingConv::ARM_AAPCS); + + // Long long helper functions + // RTABI chapter 4.2, Table 9 + setLibcallName(RTLIB::MUL_I64, "__aeabi_lmul"); + setLibcallName(RTLIB::SDIV_I64, "__aeabi_ldivmod"); + setLibcallName(RTLIB::UDIV_I64, "__aeabi_uldivmod"); + setLibcallName(RTLIB::SHL_I64, "__aeabi_llsl"); + setLibcallName(RTLIB::SRL_I64, "__aeabi_llsr"); + setLibcallName(RTLIB::SRA_I64, "__aeabi_lasr"); + setLibcallCallingConv(RTLIB::MUL_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SDIV_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UDIV_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SHL_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SRL_I64, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SRA_I64, CallingConv::ARM_AAPCS); + + // Integer division functions + // RTABI chapter 4.3.1 + setLibcallName(RTLIB::SDIV_I8, "__aeabi_idiv"); + setLibcallName(RTLIB::SDIV_I16, "__aeabi_idiv"); + setLibcallName(RTLIB::SDIV_I32, "__aeabi_idiv"); + setLibcallName(RTLIB::UDIV_I8, "__aeabi_uidiv"); + setLibcallName(RTLIB::UDIV_I16, "__aeabi_uidiv"); + setLibcallName(RTLIB::UDIV_I32, "__aeabi_uidiv"); + setLibcallCallingConv(RTLIB::SDIV_I8, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SDIV_I16, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SDIV_I32, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UDIV_I8, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UDIV_I16, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::UDIV_I32, CallingConv::ARM_AAPCS); + } + + if (Subtarget->isThumb1Only()) + addRegisterClass(MVT::i32, ARM::tGPRRegisterClass); + else + addRegisterClass(MVT::i32, ARM::GPRRegisterClass); + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + addRegisterClass(MVT::f32, ARM::SPRRegisterClass); + if (!Subtarget->isFPOnlySP()) + addRegisterClass(MVT::f64, ARM::DPRRegisterClass); + + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + } + + if (Subtarget->hasNEON()) { + addDRTypeForNEON(MVT::v2f32); + addDRTypeForNEON(MVT::v8i8); + addDRTypeForNEON(MVT::v4i16); + addDRTypeForNEON(MVT::v2i32); + addDRTypeForNEON(MVT::v1i64); + + addQRTypeForNEON(MVT::v4f32); + addQRTypeForNEON(MVT::v2f64); + addQRTypeForNEON(MVT::v16i8); + addQRTypeForNEON(MVT::v8i16); + addQRTypeForNEON(MVT::v4i32); + addQRTypeForNEON(MVT::v2i64); + + // v2f64 is legal so that QR subregs can be extracted as f64 elements, but + // neither Neon nor VFP support any arithmetic operations on it. + setOperationAction(ISD::FADD, MVT::v2f64, Expand); + setOperationAction(ISD::FSUB, MVT::v2f64, Expand); + setOperationAction(ISD::FMUL, MVT::v2f64, Expand); + setOperationAction(ISD::FDIV, MVT::v2f64, Expand); + setOperationAction(ISD::FREM, MVT::v2f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::v2f64, Expand); + setOperationAction(ISD::VSETCC, MVT::v2f64, Expand); + setOperationAction(ISD::FNEG, MVT::v2f64, Expand); + setOperationAction(ISD::FABS, MVT::v2f64, Expand); + setOperationAction(ISD::FSQRT, MVT::v2f64, Expand); + setOperationAction(ISD::FSIN, MVT::v2f64, Expand); + setOperationAction(ISD::FCOS, MVT::v2f64, Expand); + setOperationAction(ISD::FPOWI, MVT::v2f64, Expand); + setOperationAction(ISD::FPOW, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG2, MVT::v2f64, Expand); + setOperationAction(ISD::FLOG10, MVT::v2f64, Expand); + setOperationAction(ISD::FEXP, MVT::v2f64, Expand); + setOperationAction(ISD::FEXP2, MVT::v2f64, Expand); + setOperationAction(ISD::FCEIL, MVT::v2f64, Expand); + setOperationAction(ISD::FTRUNC, MVT::v2f64, Expand); + setOperationAction(ISD::FRINT, MVT::v2f64, Expand); + setOperationAction(ISD::FNEARBYINT, MVT::v2f64, Expand); + setOperationAction(ISD::FFLOOR, MVT::v2f64, Expand); + + setTruncStoreAction(MVT::v2f64, MVT::v2f32, Expand); + + // Neon does not support some operations on v1i64 and v2i64 types. + setOperationAction(ISD::MUL, MVT::v1i64, Expand); + // Custom handling for some quad-vector types to detect VMULL. + setOperationAction(ISD::MUL, MVT::v8i16, Custom); + setOperationAction(ISD::MUL, MVT::v4i32, Custom); + setOperationAction(ISD::MUL, MVT::v2i64, Custom); + // Custom handling for some vector types to avoid expensive expansions + setOperationAction(ISD::SDIV, MVT::v4i16, Custom); + setOperationAction(ISD::SDIV, MVT::v8i8, Custom); + setOperationAction(ISD::UDIV, MVT::v4i16, Custom); + setOperationAction(ISD::UDIV, MVT::v8i8, Custom); + setOperationAction(ISD::VSETCC, MVT::v1i64, Expand); + setOperationAction(ISD::VSETCC, MVT::v2i64, Expand); + + setTargetDAGCombine(ISD::INTRINSIC_VOID); + setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN); + setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN); + setTargetDAGCombine(ISD::SHL); + setTargetDAGCombine(ISD::SRL); + setTargetDAGCombine(ISD::SRA); + setTargetDAGCombine(ISD::SIGN_EXTEND); + setTargetDAGCombine(ISD::ZERO_EXTEND); + setTargetDAGCombine(ISD::ANY_EXTEND); + setTargetDAGCombine(ISD::SELECT_CC); + setTargetDAGCombine(ISD::BUILD_VECTOR); + setTargetDAGCombine(ISD::VECTOR_SHUFFLE); + setTargetDAGCombine(ISD::INSERT_VECTOR_ELT); + setTargetDAGCombine(ISD::STORE); + } + + computeRegisterProperties(); + + // ARM does not have f32 extending load. + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + + // ARM does not have i1 sign extending load. + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // ARM supports all 4 flavors of integer indexed load / store. + if (!Subtarget->isThumb1Only()) { + for (unsigned im = (unsigned)ISD::PRE_INC; + im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) { + setIndexedLoadAction(im, MVT::i1, Legal); + setIndexedLoadAction(im, MVT::i8, Legal); + setIndexedLoadAction(im, MVT::i16, Legal); + setIndexedLoadAction(im, MVT::i32, Legal); + setIndexedStoreAction(im, MVT::i1, Legal); + setIndexedStoreAction(im, MVT::i8, Legal); + setIndexedStoreAction(im, MVT::i16, Legal); + setIndexedStoreAction(im, MVT::i32, Legal); + } + } + + // i64 operation support. + if (Subtarget->isThumb1Only()) { + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + setOperationAction(ISD::MULHS, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + } else { + setOperationAction(ISD::MUL, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + if (!Subtarget->hasV6Ops()) + setOperationAction(ISD::MULHS, MVT::i32, Expand); + } + setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); + setOperationAction(ISD::SRL, MVT::i64, Custom); + setOperationAction(ISD::SRA, MVT::i64, Custom); + + // ARM does not have ROTL. + setOperationAction(ISD::ROTL, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Custom); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + + // Only ARMv6 has BSWAP. + if (!Subtarget->hasV6Ops()) + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + // These are expanded into libcalls. + if (!Subtarget->hasDivide() || !Subtarget->isThumb2()) { + // v7M has a hardware divider + setOperationAction(ISD::SDIV, MVT::i32, Expand); + setOperationAction(ISD::UDIV, MVT::i32, Expand); + } + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::BlockAddress, MVT::i32, Custom); + + setOperationAction(ISD::TRAP, MVT::Other, Legal); + + // Use the default implementation. + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); + setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); + setExceptionPointerRegister(ARM::R0); + setExceptionSelectorRegister(ARM::R1); + + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + // ARMv6 Thumb1 (except for CPUs that support dmb / dsb) and earlier use + // the default expansion. + if (Subtarget->hasDataBarrier() || + (Subtarget->hasV6Ops() && !Subtarget->isThumb())) { + // membarrier needs custom lowering; the rest are legal and handled + // normally. + setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom); + } else { + // Set them all for expansion, which will force libcalls. + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i32, Expand); + setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i8, Expand); + setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i16, Expand); + setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i32, Expand); + // Since the libcalls include locking, fold in the fences + setShouldFoldAtomicFences(true); + } + // 64-bit versions are always libcalls (for now) + setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Expand); + setOperationAction(ISD::ATOMIC_LOAD_NAND, MVT::i64, Expand); + + setOperationAction(ISD::PREFETCH, MVT::Other, Custom); + + // Requires SXTB/SXTH, available on v6 and up in both ARM and Thumb modes. + if (!Subtarget->hasV6Ops()) { + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + } + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + // Turn f64->i64 into VMOVRRD, i64 -> f64 to VMOVDRR + // iff target supports vfp2. + setOperationAction(ISD::BITCAST, MVT::i64, Custom); + setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); + } + + // We want to custom lower some of our intrinsics. + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + if (Subtarget->isTargetDarwin()) { + setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom); + setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom); + setOperationAction(ISD::EH_SJLJ_DISPATCHSETUP, MVT::Other, Custom); + } + + setOperationAction(ISD::SETCC, MVT::i32, Expand); + setOperationAction(ISD::SETCC, MVT::f32, Expand); + setOperationAction(ISD::SETCC, MVT::f64, Expand); + setOperationAction(ISD::SELECT, MVT::i32, Custom); + setOperationAction(ISD::SELECT, MVT::f32, Custom); + setOperationAction(ISD::SELECT, MVT::f64, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); + setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); + + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i32, Custom); + setOperationAction(ISD::BR_CC, MVT::f32, Custom); + setOperationAction(ISD::BR_CC, MVT::f64, Custom); + setOperationAction(ISD::BR_JT, MVT::Other, Custom); + + // We don't support sin/cos/fmod/copysign/pow + setOperationAction(ISD::FSIN, MVT::f64, Expand); + setOperationAction(ISD::FSIN, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f64, Expand); + setOperationAction(ISD::FREM, MVT::f64, Expand); + setOperationAction(ISD::FREM, MVT::f32, Expand); + if (!UseSoftFloat && Subtarget->hasVFP2() && !Subtarget->isThumb1Only()) { + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom); + } + setOperationAction(ISD::FPOW, MVT::f64, Expand); + setOperationAction(ISD::FPOW, MVT::f32, Expand); + + // Various VFP goodness + if (!UseSoftFloat && !Subtarget->isThumb1Only()) { + // int <-> fp are custom expanded into bit_convert + ARMISD ops. + if (Subtarget->hasVFP2()) { + setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom); + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); + setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); + } + // Special handling for half-precision FP. + if (!Subtarget->hasFP16()) { + setOperationAction(ISD::FP16_TO_FP32, MVT::f32, Expand); + setOperationAction(ISD::FP32_TO_FP16, MVT::i32, Expand); + } + } + + // We have target-specific dag combine patterns for the following nodes: + // ARMISD::VMOVRRD - No need to call setTargetDAGCombine + setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::SUB); + setTargetDAGCombine(ISD::MUL); + + if (Subtarget->hasV6T2Ops() || Subtarget->hasNEON()) + setTargetDAGCombine(ISD::OR); + if (Subtarget->hasNEON()) + setTargetDAGCombine(ISD::AND); + + setStackPointerRegisterToSaveRestore(ARM::SP); + + if (UseSoftFloat || Subtarget->isThumb1Only() || !Subtarget->hasVFP2()) + setSchedulingPreference(Sched::RegPressure); + else + setSchedulingPreference(Sched::Hybrid); + + //// temporary - rewrite interface to use type + maxStoresPerMemcpy = maxStoresPerMemcpyOptSize = 1; + + // On ARM arguments smaller than 4 bytes are extended, so all arguments + // are at least 4 bytes aligned. + setMinStackArgumentAlignment(4); + + benefitFromCodePlacementOpt = true; +} + +// FIXME: It might make sense to define the representative register class as the +// nearest super-register that has a non-null superset. For example, DPR_VFP2 is +// a super-register of SPR, and DPR is a superset if DPR_VFP2. Consequently, +// SPR's representative would be DPR_VFP2. This should work well if register +// pressure tracking were modified such that a register use would increment the +// pressure of the register class's representative and all of it's super +// classes' representatives transitively. We have not implemented this because +// of the difficulty prior to coalescing of modeling operand register classes +// due to the common occurence of cross class copies and subregister insertions +// and extractions. +std::pair +ARMTargetLowering::findRepresentativeClass(EVT VT) const{ + const TargetRegisterClass *RRC = 0; + uint8_t Cost = 1; + switch (VT.getSimpleVT().SimpleTy) { + default: + return TargetLowering::findRepresentativeClass(VT); + // Use DPR as representative register class for all floating point + // and vector types. Since there are 32 SPR registers and 32 DPR registers so + // the cost is 1 for both f32 and f64. + case MVT::f32: case MVT::f64: case MVT::v8i8: case MVT::v4i16: + case MVT::v2i32: case MVT::v1i64: case MVT::v2f32: + RRC = ARM::DPRRegisterClass; + // When NEON is used for SP, only half of the register file is available + // because operations that define both SP and DP results will be constrained + // to the VFP2 class (D0-D15). We currently model this constraint prior to + // coalescing by double-counting the SP regs. See the FIXME above. + if (Subtarget->useNEONForSinglePrecisionFP()) + Cost = 2; + break; + case MVT::v16i8: case MVT::v8i16: case MVT::v4i32: case MVT::v2i64: + case MVT::v4f32: case MVT::v2f64: + RRC = ARM::DPRRegisterClass; + Cost = 2; + break; + case MVT::v4i64: + RRC = ARM::DPRRegisterClass; + Cost = 4; + break; + case MVT::v8i64: + RRC = ARM::DPRRegisterClass; + Cost = 8; + break; + } + return std::make_pair(RRC, Cost); +} + +const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: return 0; + case ARMISD::Wrapper: return "ARMISD::Wrapper"; + case ARMISD::WrapperDYN: return "ARMISD::WrapperDYN"; + case ARMISD::WrapperPIC: return "ARMISD::WrapperPIC"; + case ARMISD::WrapperJT: return "ARMISD::WrapperJT"; + case ARMISD::CALL: return "ARMISD::CALL"; + case ARMISD::CALL_PRED: return "ARMISD::CALL_PRED"; + case ARMISD::CALL_NOLINK: return "ARMISD::CALL_NOLINK"; + case ARMISD::tCALL: return "ARMISD::tCALL"; + case ARMISD::BRCOND: return "ARMISD::BRCOND"; + case ARMISD::BR_JT: return "ARMISD::BR_JT"; + case ARMISD::BR2_JT: return "ARMISD::BR2_JT"; + case ARMISD::RET_FLAG: return "ARMISD::RET_FLAG"; + case ARMISD::PIC_ADD: return "ARMISD::PIC_ADD"; + case ARMISD::CMP: return "ARMISD::CMP"; + case ARMISD::CMPZ: return "ARMISD::CMPZ"; + case ARMISD::CMPFP: return "ARMISD::CMPFP"; + case ARMISD::CMPFPw0: return "ARMISD::CMPFPw0"; + case ARMISD::BCC_i64: return "ARMISD::BCC_i64"; + case ARMISD::FMSTAT: return "ARMISD::FMSTAT"; + case ARMISD::CMOV: return "ARMISD::CMOV"; + + case ARMISD::RBIT: return "ARMISD::RBIT"; + + case ARMISD::FTOSI: return "ARMISD::FTOSI"; + case ARMISD::FTOUI: return "ARMISD::FTOUI"; + case ARMISD::SITOF: return "ARMISD::SITOF"; + case ARMISD::UITOF: return "ARMISD::UITOF"; + + case ARMISD::SRL_FLAG: return "ARMISD::SRL_FLAG"; + case ARMISD::SRA_FLAG: return "ARMISD::SRA_FLAG"; + case ARMISD::RRX: return "ARMISD::RRX"; + + case ARMISD::VMOVRRD: return "ARMISD::VMOVRRD"; + case ARMISD::VMOVDRR: return "ARMISD::VMOVDRR"; + + case ARMISD::EH_SJLJ_SETJMP: return "ARMISD::EH_SJLJ_SETJMP"; + case ARMISD::EH_SJLJ_LONGJMP:return "ARMISD::EH_SJLJ_LONGJMP"; + case ARMISD::EH_SJLJ_DISPATCHSETUP:return "ARMISD::EH_SJLJ_DISPATCHSETUP"; + + case ARMISD::TC_RETURN: return "ARMISD::TC_RETURN"; + + case ARMISD::THREAD_POINTER:return "ARMISD::THREAD_POINTER"; + + case ARMISD::DYN_ALLOC: return "ARMISD::DYN_ALLOC"; + + case ARMISD::MEMBARRIER: return "ARMISD::MEMBARRIER"; + case ARMISD::MEMBARRIER_MCR: return "ARMISD::MEMBARRIER_MCR"; + + case ARMISD::PRELOAD: return "ARMISD::PRELOAD"; + + case ARMISD::VCEQ: return "ARMISD::VCEQ"; + case ARMISD::VCEQZ: return "ARMISD::VCEQZ"; + case ARMISD::VCGE: return "ARMISD::VCGE"; + case ARMISD::VCGEZ: return "ARMISD::VCGEZ"; + case ARMISD::VCLEZ: return "ARMISD::VCLEZ"; + case ARMISD::VCGEU: return "ARMISD::VCGEU"; + case ARMISD::VCGT: return "ARMISD::VCGT"; + case ARMISD::VCGTZ: return "ARMISD::VCGTZ"; + case ARMISD::VCLTZ: return "ARMISD::VCLTZ"; + case ARMISD::VCGTU: return "ARMISD::VCGTU"; + case ARMISD::VTST: return "ARMISD::VTST"; + + case ARMISD::VSHL: return "ARMISD::VSHL"; + case ARMISD::VSHRs: return "ARMISD::VSHRs"; + case ARMISD::VSHRu: return "ARMISD::VSHRu"; + case ARMISD::VSHLLs: return "ARMISD::VSHLLs"; + case ARMISD::VSHLLu: return "ARMISD::VSHLLu"; + case ARMISD::VSHLLi: return "ARMISD::VSHLLi"; + case ARMISD::VSHRN: return "ARMISD::VSHRN"; + case ARMISD::VRSHRs: return "ARMISD::VRSHRs"; + case ARMISD::VRSHRu: return "ARMISD::VRSHRu"; + case ARMISD::VRSHRN: return "ARMISD::VRSHRN"; + case ARMISD::VQSHLs: return "ARMISD::VQSHLs"; + case ARMISD::VQSHLu: return "ARMISD::VQSHLu"; + case ARMISD::VQSHLsu: return "ARMISD::VQSHLsu"; + case ARMISD::VQSHRNs: return "ARMISD::VQSHRNs"; + case ARMISD::VQSHRNu: return "ARMISD::VQSHRNu"; + case ARMISD::VQSHRNsu: return "ARMISD::VQSHRNsu"; + case ARMISD::VQRSHRNs: return "ARMISD::VQRSHRNs"; + case ARMISD::VQRSHRNu: return "ARMISD::VQRSHRNu"; + case ARMISD::VQRSHRNsu: return "ARMISD::VQRSHRNsu"; + case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu"; + case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs"; + case ARMISD::VMOVIMM: return "ARMISD::VMOVIMM"; + case ARMISD::VMVNIMM: return "ARMISD::VMVNIMM"; + case ARMISD::VDUP: return "ARMISD::VDUP"; + case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE"; + case ARMISD::VEXT: return "ARMISD::VEXT"; + case ARMISD::VREV64: return "ARMISD::VREV64"; + case ARMISD::VREV32: return "ARMISD::VREV32"; + case ARMISD::VREV16: return "ARMISD::VREV16"; + case ARMISD::VZIP: return "ARMISD::VZIP"; + case ARMISD::VUZP: return "ARMISD::VUZP"; + case ARMISD::VTRN: return "ARMISD::VTRN"; + case ARMISD::VMULLs: return "ARMISD::VMULLs"; + case ARMISD::VMULLu: return "ARMISD::VMULLu"; + case ARMISD::BUILD_VECTOR: return "ARMISD::BUILD_VECTOR"; + case ARMISD::FMAX: return "ARMISD::FMAX"; + case ARMISD::FMIN: return "ARMISD::FMIN"; + case ARMISD::BFI: return "ARMISD::BFI"; + case ARMISD::VORRIMM: return "ARMISD::VORRIMM"; + case ARMISD::VBICIMM: return "ARMISD::VBICIMM"; + case ARMISD::VLD2DUP: return "ARMISD::VLD2DUP"; + case ARMISD::VLD3DUP: return "ARMISD::VLD3DUP"; + case ARMISD::VLD4DUP: return "ARMISD::VLD4DUP"; + case ARMISD::VLD1_UPD: return "ARMISD::VLD1_UPD"; + case ARMISD::VLD2_UPD: return "ARMISD::VLD2_UPD"; + case ARMISD::VLD3_UPD: return "ARMISD::VLD3_UPD"; + case ARMISD::VLD4_UPD: return "ARMISD::VLD4_UPD"; + case ARMISD::VLD2LN_UPD: return "ARMISD::VLD2LN_UPD"; + case ARMISD::VLD3LN_UPD: return "ARMISD::VLD3LN_UPD"; + case ARMISD::VLD4LN_UPD: return "ARMISD::VLD4LN_UPD"; + case ARMISD::VLD2DUP_UPD: return "ARMISD::VLD2DUP_UPD"; + case ARMISD::VLD3DUP_UPD: return "ARMISD::VLD3DUP_UPD"; + case ARMISD::VLD4DUP_UPD: return "ARMISD::VLD4DUP_UPD"; + case ARMISD::VST1_UPD: return "ARMISD::VST1_UPD"; + case ARMISD::VST2_UPD: return "ARMISD::VST2_UPD"; + case ARMISD::VST3_UPD: return "ARMISD::VST3_UPD"; + case ARMISD::VST4_UPD: return "ARMISD::VST4_UPD"; + case ARMISD::VST2LN_UPD: return "ARMISD::VST2LN_UPD"; + case ARMISD::VST3LN_UPD: return "ARMISD::VST3LN_UPD"; + case ARMISD::VST4LN_UPD: return "ARMISD::VST4LN_UPD"; + } +} + +/// getRegClassFor - Return the register class that should be used for the +/// specified value type. +TargetRegisterClass *ARMTargetLowering::getRegClassFor(EVT VT) const { + // Map v4i64 to QQ registers but do not make the type legal. Similarly map + // v8i64 to QQQQ registers. v4i64 and v8i64 are only used for REG_SEQUENCE to + // load / store 4 to 8 consecutive D registers. + if (Subtarget->hasNEON()) { + if (VT == MVT::v4i64) + return ARM::QQPRRegisterClass; + else if (VT == MVT::v8i64) + return ARM::QQQQPRRegisterClass; + } + return TargetLowering::getRegClassFor(VT); +} + +// Create a fast isel object. +FastISel * +ARMTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo) const { + return ARM::createFastISel(funcInfo); +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned ARMTargetLowering::getFunctionAlignment(const Function *F) const { + return getTargetMachine().getSubtarget().isThumb() ? 1 : 2; +} + +/// getMaximalGlobalOffset - Returns the maximal possible offset which can +/// be used for loads / stores from the global. +unsigned ARMTargetLowering::getMaximalGlobalOffset() const { + return (Subtarget->isThumb1Only() ? 127 : 4095); +} + +Sched::Preference ARMTargetLowering::getSchedulingPreference(SDNode *N) const { + unsigned NumVals = N->getNumValues(); + if (!NumVals) + return Sched::RegPressure; + + for (unsigned i = 0; i != NumVals; ++i) { + EVT VT = N->getValueType(i); + if (VT == MVT::Glue || VT == MVT::Other) + continue; + if (VT.isFloatingPoint() || VT.isVector()) + return Sched::Latency; + } + + if (!N->isMachineOpcode()) + return Sched::RegPressure; + + // Load are scheduled for latency even if there instruction itinerary + // is not available. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + const TargetInstrDesc &TID = TII->get(N->getMachineOpcode()); + + if (TID.getNumDefs() == 0) + return Sched::RegPressure; + if (!Itins->isEmpty() && + Itins->getOperandCycle(TID.getSchedClass(), 0) > 2) + return Sched::Latency; + + return Sched::RegPressure; +} + +//===----------------------------------------------------------------------===// +// Lowering Code +//===----------------------------------------------------------------------===// + +/// IntCCToARMCC - Convert a DAG integer condition code to an ARM CC +static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code!"); + case ISD::SETNE: return ARMCC::NE; + case ISD::SETEQ: return ARMCC::EQ; + case ISD::SETGT: return ARMCC::GT; + case ISD::SETGE: return ARMCC::GE; + case ISD::SETLT: return ARMCC::LT; + case ISD::SETLE: return ARMCC::LE; + case ISD::SETUGT: return ARMCC::HI; + case ISD::SETUGE: return ARMCC::HS; + case ISD::SETULT: return ARMCC::LO; + case ISD::SETULE: return ARMCC::LS; + } +} + +/// FPCCToARMCC - Convert a DAG fp condition code to an ARM CC. +static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, + ARMCC::CondCodes &CondCode2) { + CondCode2 = ARMCC::AL; + switch (CC) { + default: llvm_unreachable("Unknown FP condition!"); + case ISD::SETEQ: + case ISD::SETOEQ: CondCode = ARMCC::EQ; break; + case ISD::SETGT: + case ISD::SETOGT: CondCode = ARMCC::GT; break; + case ISD::SETGE: + case ISD::SETOGE: CondCode = ARMCC::GE; break; + case ISD::SETOLT: CondCode = ARMCC::MI; break; + case ISD::SETOLE: CondCode = ARMCC::LS; break; + case ISD::SETONE: CondCode = ARMCC::MI; CondCode2 = ARMCC::GT; break; + case ISD::SETO: CondCode = ARMCC::VC; break; + case ISD::SETUO: CondCode = ARMCC::VS; break; + case ISD::SETUEQ: CondCode = ARMCC::EQ; CondCode2 = ARMCC::VS; break; + case ISD::SETUGT: CondCode = ARMCC::HI; break; + case ISD::SETUGE: CondCode = ARMCC::PL; break; + case ISD::SETLT: + case ISD::SETULT: CondCode = ARMCC::LT; break; + case ISD::SETLE: + case ISD::SETULE: CondCode = ARMCC::LE; break; + case ISD::SETNE: + case ISD::SETUNE: CondCode = ARMCC::NE; break; + } +} + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "ARMGenCallingConv.inc" + +/// CCAssignFnForNode - Selects the correct CCAssignFn for a the +/// given CallingConvention value. +CCAssignFn *ARMTargetLowering::CCAssignFnForNode(CallingConv::ID CC, + bool Return, + bool isVarArg) const { + switch (CC) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::Fast: + if (Subtarget->hasVFP2() && !isVarArg) { + if (!Subtarget->isAAPCS_ABI()) + return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS); + // For AAPCS ABI targets, just use VFP variant of the calling convention. + return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP); + } + // Fallthrough + case CallingConv::C: { + // Use target triple & subtarget features to do actual dispatch. + if (!Subtarget->isAAPCS_ABI()) + return (Return ? RetCC_ARM_APCS : CC_ARM_APCS); + else if (Subtarget->hasVFP2() && + FloatABIType == FloatABI::Hard && !isVarArg) + return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP); + return (Return ? RetCC_ARM_AAPCS : CC_ARM_AAPCS); + } + case CallingConv::ARM_AAPCS_VFP: + return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP); + case CallingConv::ARM_AAPCS: + return (Return ? RetCC_ARM_AAPCS : CC_ARM_AAPCS); + case CallingConv::ARM_APCS: + return (Return ? RetCC_ARM_APCS : CC_ARM_APCS); + } +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +SDValue +ARMTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + CCInfo.AnalyzeCallResult(Ins, + CCAssignFnForNode(CallConv, /* Return*/ true, + isVarArg)); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign VA = RVLocs[i]; + + SDValue Val; + if (VA.needsCustom()) { + // Handle f64 or half of a v2f64. + SDValue Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, + InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); + VA = RVLocs[++i]; // skip ahead to next loc + SDValue Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, + InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); + Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + + if (VA.getLocVT() == MVT::v2f64) { + SDValue Vec = DAG.getNode(ISD::UNDEF, dl, MVT::v2f64); + Vec = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Vec, Val, + DAG.getConstant(0, MVT::i32)); + + VA = RVLocs[++i]; // skip ahead to next loc + Lo = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); + Chain = Lo.getValue(1); + InFlag = Lo.getValue(2); + VA = RVLocs[++i]; // skip ahead to next loc + Hi = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), MVT::i32, InFlag); + Chain = Hi.getValue(1); + InFlag = Hi.getValue(2); + Val = DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Vec, Val, + DAG.getConstant(1, MVT::i32)); + } + } else { + Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(), + InFlag); + Chain = Val.getValue(1); + InFlag = Val.getValue(2); + } + + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + Val = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), Val); + break; + } + + InVals.push_back(Val); + } + + return Chain; +} + +/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified +/// by "Src" to address "Dst" of size "Size". Alignment information is +/// specified by the specific parameter attribute. The copy will be passed as +/// a byval function parameter. +/// Sometimes what we are copying is the end of a larger object, the part that +/// does not fit in registers. +static SDValue +CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, + ISD::ArgFlagsTy Flags, SelectionDAG &DAG, + DebugLoc dl) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); + return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), + /*isVolatile=*/false, /*AlwaysInline=*/false, + MachinePointerInfo(0), MachinePointerInfo(0)); +} + +/// LowerMemOpCallTo - Store the argument to the stack. +SDValue +ARMTargetLowering::LowerMemOpCallTo(SDValue Chain, + SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags) const { + unsigned LocMemOffset = VA.getLocMemOffset(); + SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); + PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); + if (Flags.isByVal()) + return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); + + return DAG.getStore(Chain, dl, Arg, PtrOff, + MachinePointerInfo::getStack(LocMemOffset), + false, false, 0); +} + +void ARMTargetLowering::PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG, + SDValue Chain, SDValue &Arg, + RegsToPassVector &RegsToPass, + CCValAssign &VA, CCValAssign &NextVA, + SDValue &StackPtr, + SmallVector &MemOpChains, + ISD::ArgFlagsTy Flags) const { + + SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), Arg); + RegsToPass.push_back(std::make_pair(VA.getLocReg(), fmrrd)); + + if (NextVA.isRegLoc()) + RegsToPass.push_back(std::make_pair(NextVA.getLocReg(), fmrrd.getValue(1))); + else { + assert(NextVA.isMemLoc()); + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, fmrrd.getValue(1), + dl, DAG, NextVA, + Flags)); + } +} + +/// LowerCall - Lowering a call into a callseq_start <- +/// ARMISD:CALL <- callseq_end chain. Also add input and output parameter +/// nodes. +SDValue +ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); + bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet(); + bool IsSibCall = false; + // Temporarily disable tail calls so things don't break. + if (!EnableARMTailCalls) + isTailCall = false; + if (isTailCall) { + // Check if it's really possible to do a tail call. + isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, + isVarArg, IsStructRet, MF.getFunction()->hasStructRetAttr(), + Outs, OutVals, Ins, DAG); + // We don't support GuaranteedTailCallOpt for ARM, only automatically + // detected sibcalls. + if (isTailCall) { + ++NumTailCalls; + IsSibCall = true; + } + } + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallOperands(Outs, + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + // For tail calls, memory operands are available in our caller's stack. + if (IsSibCall) + NumBytes = 0; + + // Adjust the stack pointer for the new arguments... + // These operations are automatically eliminated by the prolog/epilog pass + if (!IsSibCall) + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + + SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); + + RegsToPassVector RegsToPass; + SmallVector MemOpChains; + + // Walk the register/memloc assignments, inserting copies/loads. In the case + // of tail call optimization, arguments are handled later. + for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size(); + i != e; + ++i, ++realArgIdx) { + CCValAssign &VA = ArgLocs[i]; + SDValue Arg = OutVals[realArgIdx]; + ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + bool isByVal = Flags.isByVal(); + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); + break; + } + + // f64 and v2f64 might be passed in i32 pairs and must be split into pieces + if (VA.needsCustom()) { + if (VA.getLocVT() == MVT::v2f64) { + SDValue Op0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(0, MVT::i32)); + SDValue Op1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(1, MVT::i32)); + + PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, + VA, ArgLocs[++i], StackPtr, MemOpChains, Flags); + + VA = ArgLocs[++i]; // skip ahead to next loc + if (VA.isRegLoc()) { + PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, + VA, ArgLocs[++i], StackPtr, MemOpChains, Flags); + } else { + assert(VA.isMemLoc()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Op1, + dl, DAG, VA, Flags)); + } + } else { + PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i], + StackPtr, MemOpChains, Flags); + } + } else if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else if (!IsSibCall || isByVal) { + assert(VA.isMemLoc()); + + MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, + dl, DAG, VA, Flags)); + } + } + + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDValue InFlag; + // Tail call byval lowering might overwrite argument registers so in case of + // tail call optimization the copies to registers are lowered later. + if (!isTailCall) + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // For tail calls lower the arguments to the 'real' stack slot. + if (isTailCall) { + // Force all the incoming stack arguments to be loaded from the stack + // before any new outgoing arguments are stored to the stack, because the + // outgoing stack slots may alias the incoming argument stack slots, and + // the alias isn't otherwise explicit. This is slightly more conservative + // than necessary, because it means that each store effectively depends + // on every argument instead of just those arguments it would clobber. + + // Do not flag preceeding copytoreg stuff together with the following stuff. + InFlag = SDValue(); + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + InFlag =SDValue(); + } + + // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. + bool isDirect = false; + bool isARMFunc = false; + bool isLocalARMFunc = false; + ARMFunctionInfo *AFI = MF.getInfo(); + + if (EnableARMLongCalls) { + assert (getTargetMachine().getRelocationModel() == Reloc::Static + && "long-calls with non-static relocation model!"); + // Handle a global address or an external symbol. If it's not one of + // those, the target's already in a register, so we don't need to do + // anything extra. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + const GlobalValue *GV = G->getGlobal(); + // Create a constant pool entry for the callee address + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, + ARMPCLabelIndex, + ARMCP::CPValue, 0); + // Get the address of the callee into a register + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + } else if (ExternalSymbolSDNode *S=dyn_cast(Callee)) { + const char *Sym = S->getSymbol(); + + // Create a constant pool entry for the callee address + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), + Sym, ARMPCLabelIndex, 0); + // Get the address of the callee into a register + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + } + } else if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + const GlobalValue *GV = G->getGlobal(); + isDirect = true; + bool isExt = GV->isDeclaration() || GV->isWeakForLinker(); + bool isStub = (isExt && Subtarget->isTargetDarwin()) && + getTargetMachine().getRelocationModel() != Reloc::Static; + isARMFunc = !Subtarget->isThumb() || isStub; + // ARM call to a local ARM function is predicable. + isLocalARMFunc = !Subtarget->isThumb() && (!isExt || !ARMInterworking); + // tBX takes a register source operand. + if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, + ARMPCLabelIndex, + ARMCP::CPValue, 4); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, dl, + getPointerTy(), Callee, PICLabel); + } else { + // On ELF targets for PIC code, direct calls should go through the PLT + unsigned OpFlags = 0; + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_) + OpFlags = ARMII::MO_PLT; + Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), 0, OpFlags); + } + } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { + isDirect = true; + bool isStub = Subtarget->isTargetDarwin() && + getTargetMachine().getRelocationModel() != Reloc::Static; + isARMFunc = !Subtarget->isThumb() || isStub; + // tBX takes a register source operand. + const char *Sym = S->getSymbol(); + if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) { + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), + Sym, ARMPCLabelIndex, 4); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, getPointerTy(), 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + Callee = DAG.getLoad(getPointerTy(), dl, + DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Callee = DAG.getNode(ARMISD::PIC_ADD, dl, + getPointerTy(), Callee, PICLabel); + } else { + unsigned OpFlags = 0; + // On ELF targets for PIC code, direct calls should go through the PLT + if (Subtarget->isTargetELF() && + getTargetMachine().getRelocationModel() == Reloc::PIC_) + OpFlags = ARMII::MO_PLT; + Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), OpFlags); + } + } + + // FIXME: handle tail calls differently. + unsigned CallOpc; + if (Subtarget->isThumb()) { + if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps()) + CallOpc = ARMISD::CALL_NOLINK; + else + CallOpc = isARMFunc ? ARMISD::CALL : ARMISD::tCALL; + } else { + CallOpc = (isDirect || Subtarget->hasV5TOps()) + ? (isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL) + : ARMISD::CALL_NOLINK; + } + + std::vector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are known live + // into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + if (isTailCall) + return DAG.getNode(ARMISD::TC_RETURN, dl, NodeTys, &Ops[0], Ops.size()); + + // Returns a chain and a flag for retval copy to use. + Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + if (!Ins.empty()) + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, + dl, DAG, InVals); +} + +/// HandleByVal - Every parameter *after* a byval parameter is passed +/// on the stack. Confiscate all the parameter registers to insure +/// this. +void +llvm::ARMTargetLowering::HandleByVal(CCState *State) const { + static const unsigned RegList1[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3 + }; + do {} while (State->AllocateReg(RegList1, 4)); +} + +/// MatchingStackOffset - Return true if the given stack call argument is +/// already available in the same position (relatively) of the caller's +/// incoming argument stack. +static +bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, + MachineFrameInfo *MFI, const MachineRegisterInfo *MRI, + const ARMInstrInfo *TII) { + unsigned Bytes = Arg.getValueType().getSizeInBits() / 8; + int FI = INT_MAX; + if (Arg.getOpcode() == ISD::CopyFromReg) { + unsigned VR = cast(Arg.getOperand(1))->getReg(); + if (!TargetRegisterInfo::isVirtualRegister(VR)) + return false; + MachineInstr *Def = MRI->getVRegDef(VR); + if (!Def) + return false; + if (!Flags.isByVal()) { + if (!TII->isLoadFromStackSlot(Def, FI)) + return false; + } else { + return false; + } + } else if (LoadSDNode *Ld = dyn_cast(Arg)) { + if (Flags.isByVal()) + // ByVal argument is passed in as a pointer but it's now being + // dereferenced. e.g. + // define @foo(%struct.X* %A) { + // tail call @bar(%struct.X* byval %A) + // } + return false; + SDValue Ptr = Ld->getBasePtr(); + FrameIndexSDNode *FINode = dyn_cast(Ptr); + if (!FINode) + return false; + FI = FINode->getIndex(); + } else + return false; + + assert(FI != INT_MAX); + if (!MFI->isFixedObjectIndex(FI)) + return false; + return Offset == MFI->getObjectOffset(FI) && Bytes == MFI->getObjectSize(FI); +} + +/// IsEligibleForTailCallOptimization - Check whether the call is eligible +/// for tail call optimization. Targets which want to do tail call +/// optimization should implement this function. +bool +ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + bool isCalleeStructRet, + bool isCallerStructRet, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const { + const Function *CallerF = DAG.getMachineFunction().getFunction(); + CallingConv::ID CallerCC = CallerF->getCallingConv(); + bool CCMatch = CallerCC == CalleeCC; + + // Look for obvious safe cases to perform tail call optimization that do not + // require ABI changes. This is what gcc calls sibcall. + + // Do not sibcall optimize vararg calls unless the call site is not passing + // any arguments. + if (isVarArg && !Outs.empty()) + return false; + + // Also avoid sibcall optimization if either caller or callee uses struct + // return semantics. + if (isCalleeStructRet || isCallerStructRet) + return false; + + // FIXME: Completely disable sibcall for Thumb1 since Thumb1RegisterInfo:: + // emitEpilogue is not ready for them. + // Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take + // LR. This means if we need to reload LR, it takes an extra instructions, + // which outweighs the value of the tail call; but here we don't know yet + // whether LR is going to be used. Probably the right approach is to + // generate the tail call here and turn it back into CALL/RET in + // emitEpilogue if LR is used. + + // Thumb1 PIC calls to external symbols use BX, so they can be tail calls, + // but we need to make sure there are enough registers; the only valid + // registers are the 4 used for parameters. We don't currently do this + // case. + if (Subtarget->isThumb1Only()) + return false; + + // If the calling conventions do not match, then we'd better make sure the + // results are returned in the same way as what the caller expects. + if (!CCMatch) { + SmallVector RVLocs1; + CCState CCInfo1(CalleeCC, false, getTargetMachine(), + RVLocs1, *DAG.getContext()); + CCInfo1.AnalyzeCallResult(Ins, CCAssignFnForNode(CalleeCC, true, isVarArg)); + + SmallVector RVLocs2; + CCState CCInfo2(CallerCC, false, getTargetMachine(), + RVLocs2, *DAG.getContext()); + CCInfo2.AnalyzeCallResult(Ins, CCAssignFnForNode(CallerCC, true, isVarArg)); + + if (RVLocs1.size() != RVLocs2.size()) + return false; + for (unsigned i = 0, e = RVLocs1.size(); i != e; ++i) { + if (RVLocs1[i].isRegLoc() != RVLocs2[i].isRegLoc()) + return false; + if (RVLocs1[i].getLocInfo() != RVLocs2[i].getLocInfo()) + return false; + if (RVLocs1[i].isRegLoc()) { + if (RVLocs1[i].getLocReg() != RVLocs2[i].getLocReg()) + return false; + } else { + if (RVLocs1[i].getLocMemOffset() != RVLocs2[i].getLocMemOffset()) + return false; + } + } + } + + // If the callee takes no arguments then go on to check the results of the + // call. + if (!Outs.empty()) { + // Check if stack adjustment is needed. For now, do not do this if any + // argument is passed on the stack. + SmallVector ArgLocs; + CCState CCInfo(CalleeCC, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeCallOperands(Outs, + CCAssignFnForNode(CalleeCC, false, isVarArg)); + if (CCInfo.getNextStackOffset()) { + MachineFunction &MF = DAG.getMachineFunction(); + + // Check if the arguments are already laid out in the right way as + // the caller's fixed stack objects. + MachineFrameInfo *MFI = MF.getFrameInfo(); + const MachineRegisterInfo *MRI = &MF.getRegInfo(); + const ARMInstrInfo *TII = + ((ARMTargetMachine&)getTargetMachine()).getInstrInfo(); + for (unsigned i = 0, realArgIdx = 0, e = ArgLocs.size(); + i != e; + ++i, ++realArgIdx) { + CCValAssign &VA = ArgLocs[i]; + EVT RegVT = VA.getLocVT(); + SDValue Arg = OutVals[realArgIdx]; + ISD::ArgFlagsTy Flags = Outs[realArgIdx].Flags; + if (VA.getLocInfo() == CCValAssign::Indirect) + return false; + if (VA.needsCustom()) { + // f64 and vector types are split into multiple registers or + // register/stack-slot combinations. The types will not match + // the registers; give up on memory f64 refs until we figure + // out what to do about this. + if (!VA.isRegLoc()) + return false; + if (!ArgLocs[++i].isRegLoc()) + return false; + if (RegVT == MVT::v2f64) { + if (!ArgLocs[++i].isRegLoc()) + return false; + if (!ArgLocs[++i].isRegLoc()) + return false; + } + } else if (!VA.isRegLoc()) { + if (!MatchingStackOffset(Arg, VA.getLocMemOffset(), Flags, + MFI, MRI, TII)) + return false; + } + } + } + } + + return true; +} + +SDValue +ARMTargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + DebugLoc dl, SelectionDAG &DAG) const { + + // CCValAssign - represent the assignment of the return value to a location. + SmallVector RVLocs; + + // CCState - Info about the registers and stack slots. + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, + *DAG.getContext()); + + // Analyze outgoing return values. + CCInfo.AnalyzeReturn(Outs, CCAssignFnForNode(CallConv, /* Return */ true, + isVarArg)); + + // If this is the first return lowered for this function, add + // the regs to the liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0, realRVLocIdx = 0; + i != RVLocs.size(); + ++i, ++realRVLocIdx) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + SDValue Arg = OutVals[realRVLocIdx]; + + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + Arg = DAG.getNode(ISD::BITCAST, dl, VA.getLocVT(), Arg); + break; + } + + if (VA.needsCustom()) { + if (VA.getLocVT() == MVT::v2f64) { + // Extract the first half and return it in two registers. + SDValue Half = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(0, MVT::i32)); + SDValue HalfGPRs = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), Half); + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), HalfGPRs, Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + HalfGPRs.getValue(1), Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + + // Extract the 2nd half and fall through to handle it as an f64 value. + Arg = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, Arg, + DAG.getConstant(1, MVT::i32)); + } + // Legalize ret f64 -> ret 2 x i32. We always have fmrrd if f64 is + // available. + SDValue fmrrd = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), &Arg, 1); + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd, Flag); + Flag = Chain.getValue(1); + VA = RVLocs[++i]; // skip ahead to next loc + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), fmrrd.getValue(1), + Flag); + } else + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Arg, Flag); + + // Guarantee that all emitted copies are + // stuck together, avoiding something bad. + Flag = Chain.getValue(1); + } + + SDValue result; + if (Flag.getNode()) + result = DAG.getNode(ARMISD::RET_FLAG, dl, MVT::Other, Chain, Flag); + else // Return Void + result = DAG.getNode(ARMISD::RET_FLAG, dl, MVT::Other, Chain); + + return result; +} + +bool ARMTargetLowering::isUsedByReturnOnly(SDNode *N) const { + if (N->getNumValues() != 1) + return false; + if (!N->hasNUsesOfValue(1, 0)) + return false; + + unsigned NumCopies = 0; + SDNode* Copies[2]; + SDNode *Use = *N->use_begin(); + if (Use->getOpcode() == ISD::CopyToReg) { + Copies[NumCopies++] = Use; + } else if (Use->getOpcode() == ARMISD::VMOVRRD) { + // f64 returned in a pair of GPRs. + for (SDNode::use_iterator UI = Use->use_begin(), UE = Use->use_end(); + UI != UE; ++UI) { + if (UI->getOpcode() != ISD::CopyToReg) + return false; + Copies[UI.getUse().getResNo()] = *UI; + ++NumCopies; + } + } else if (Use->getOpcode() == ISD::BITCAST) { + // f32 returned in a single GPR. + if (!Use->hasNUsesOfValue(1, 0)) + return false; + Use = *Use->use_begin(); + if (Use->getOpcode() != ISD::CopyToReg || !Use->hasNUsesOfValue(1, 0)) + return false; + Copies[NumCopies++] = Use; + } else { + return false; + } + + if (NumCopies != 1 && NumCopies != 2) + return false; + + bool HasRet = false; + for (unsigned i = 0; i < NumCopies; ++i) { + SDNode *Copy = Copies[i]; + for (SDNode::use_iterator UI = Copy->use_begin(), UE = Copy->use_end(); + UI != UE; ++UI) { + if (UI->getOpcode() == ISD::CopyToReg) { + SDNode *Use = *UI; + if (Use == Copies[0] || Use == Copies[1]) + continue; + return false; + } + if (UI->getOpcode() != ARMISD::RET_FLAG) + return false; + HasRet = true; + } + } + + return HasRet; +} + +bool ARMTargetLowering::mayBeEmittedAsTailCall(CallInst *CI) const { + if (!EnableARMTailCalls) + return false; + + if (!CI->isTailCall()) + return false; + + return !Subtarget->isThumb1Only(); +} + +// ConstantPool, JumpTable, GlobalAddress, and ExternalSymbol are lowered as +// their target counterpart wrapped in the ARMISD::Wrapper node. Suppose N is +// one of the above mentioned nodes. It has to be wrapped because otherwise +// Select(N) returns N. So the raw TargetGlobalAddress nodes, etc. can only +// be used to form addressing mode. These wrapped nodes will be selected +// into MOVi. +static SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) { + EVT PtrVT = Op.getValueType(); + // FIXME there is no actual debug info here + DebugLoc dl = Op.getDebugLoc(); + ConstantPoolSDNode *CP = cast(Op); + SDValue Res; + if (CP->isMachineConstantPoolEntry()) + Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, + CP->getAlignment()); + else + Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, + CP->getAlignment()); + return DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Res); +} + +unsigned ARMTargetLowering::getJumpTableEncoding() const { + return MachineJumpTableInfo::EK_Inline; +} + +SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op, + SelectionDAG &DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = 0; + DebugLoc DL = Op.getDebugLoc(); + EVT PtrVT = getPointerTy(); + const BlockAddress *BA = cast(Op)->getBlockAddress(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + SDValue CPAddr; + if (RelocM == Reloc::Static) { + CPAddr = DAG.getTargetConstantPool(BA, PtrVT, 4); + } else { + unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(BA, ARMPCLabelIndex, + ARMCP::CPBlockAddress, + PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + } + CPAddr = DAG.getNode(ARMISD::Wrapper, DL, PtrVT, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + if (RelocM == Reloc::Static) + return Result; + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + return DAG.getNode(ARMISD::PIC_ADD, DL, PtrVT, Result, PICLabel); +} + +// Lower ISD::GlobalTLSAddress using the "general dynamic" model +SDValue +ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG) const { + DebugLoc dl = GA->getDebugLoc(); + EVT PtrVT = getPointerTy(); + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, ARMCP::TLSGD, true); + SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument); + Argument = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Argument, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue Chain = Argument.getValue(1); + + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Argument = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel); + + // call __tls_get_addr. + ArgListTy Args; + ArgListEntry Entry; + Entry.Node = Argument; + Entry.Ty = (const Type *) Type::getInt32Ty(*DAG.getContext()); + Args.push_back(Entry); + // FIXME: is there useful debug info available here? + std::pair CallResult = + LowerCallTo(Chain, (const Type *) Type::getInt32Ty(*DAG.getContext()), + false, false, false, false, + 0, CallingConv::C, false, /*isReturnValueUsed=*/true, + DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); + return CallResult.first; +} + +// Lower ISD::GlobalTLSAddress using the "initial exec" or +// "local exec" model. +SDValue +ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG) const { + const GlobalValue *GV = GA->getGlobal(); + DebugLoc dl = GA->getDebugLoc(); + SDValue Offset; + SDValue Chain = DAG.getEntryNode(); + EVT PtrVT = getPointerTy(); + // Get the Thread Pointer + SDValue ThreadPointer = DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + + if (GV->isDeclaration()) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + // Initial exec model. + unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GA->getGlobal(), ARMPCLabelIndex, + ARMCP::CPValue, PCAdj, ARMCP::GOTTPOFF, true); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + MachinePointerInfo::getConstantPool(), + false, false, 0); + Chain = Offset.getValue(1); + + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Offset = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Offset, PICLabel); + + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + MachinePointerInfo::getConstantPool(), + false, false, 0); + } else { + // local exec model + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, ARMCP::TPOFF); + Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); + Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); + Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, + MachinePointerInfo::getConstantPool(), + false, false, 0); + } + + // The address of the thread local variable is the add of the thread + // pointer with the offset of the variable. + return DAG.getNode(ISD::ADD, dl, PtrVT, ThreadPointer, Offset); +} + +SDValue +ARMTargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const { + // TODO: implement the "local dynamic" model + assert(Subtarget->isTargetELF() && + "TLS not implemented for non-ELF targets"); + GlobalAddressSDNode *GA = cast(Op); + // If the relocation model is PIC, use the "General Dynamic" TLS Model, + // otherwise use the "Local Exec" TLS Model + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) + return LowerToTLSGeneralDynamicModel(GA, DAG); + else + return LowerToTLSExecModels(GA, DAG); +} + +SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, + SelectionDAG &DAG) const { + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + const GlobalValue *GV = cast(Op)->getGlobal(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + if (RelocM == Reloc::PIC_) { + bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility(); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), + CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue Chain = Result.getValue(1); + SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT); + Result = DAG.getNode(ISD::ADD, dl, PtrVT, Result, GOT); + if (!UseGOTOFF) + Result = DAG.getLoad(PtrVT, dl, Chain, Result, + MachinePointerInfo::getGOT(), false, false, 0); + return Result; + } + + // If we have T2 ops, we can materialize the address directly via movt/movw + // pair. This is always cheaper. + if (Subtarget->useMovt()) { + ++NumMovwMovt; + // FIXME: Once remat is capable of dealing with instructions with register + // operands, expand this into two nodes. + return DAG.getNode(ARMISD::Wrapper, dl, PtrVT, + DAG.getTargetGlobalAddress(GV, dl, PtrVT)); + } else { + SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + } +} + +SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, + SelectionDAG &DAG) const { + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + const GlobalValue *GV = cast(Op)->getGlobal(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + + if (Subtarget->useMovt()) { + ++NumMovwMovt; + // FIXME: Once remat is capable of dealing with instructions with register + // operands, expand this into two nodes. + if (RelocM == Reloc::Static) + return DAG.getNode(ARMISD::Wrapper, dl, PtrVT, + DAG.getTargetGlobalAddress(GV, dl, PtrVT)); + + unsigned Wrapper = (RelocM == Reloc::PIC_) + ? ARMISD::WrapperPIC : ARMISD::WrapperDYN; + SDValue Result = DAG.getNode(Wrapper, dl, PtrVT, + DAG.getTargetGlobalAddress(GV, dl, PtrVT)); + if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) + Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Result, + MachinePointerInfo::getGOT(), false, false, 0); + return Result; + } + + unsigned ARMPCLabelIndex = 0; + SDValue CPAddr; + if (RelocM == Reloc::Static) { + CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4); + } else { + ARMPCLabelIndex = AFI->createPICLabelUId(); + unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 : (Subtarget->isThumb()?4:8); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + } + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue Chain = Result.getValue(1); + + if (RelocM == Reloc::PIC_) { + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); + } + + if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) + Result = DAG.getLoad(PtrVT, dl, Chain, Result, MachinePointerInfo::getGOT(), + false, false, 0); + + return Result; +} + +SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, + SelectionDAG &DAG) const { + assert(Subtarget->isTargetELF() && + "GLOBAL OFFSET TABLE not implemented for non-ELF targets"); + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + unsigned PCAdj = Subtarget->isThumb() ? 4 : 8; + ARMConstantPoolValue *CPV = new ARMConstantPoolValue(*DAG.getContext(), + "_GLOBAL_OFFSET_TABLE_", + ARMPCLabelIndex, PCAdj); + SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); +} + +SDValue +ARMTargetLowering::LowerEH_SJLJ_DISPATCHSETUP(SDValue Op, SelectionDAG &DAG) + const { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ARMISD::EH_SJLJ_DISPATCHSETUP, dl, MVT::Other, + Op.getOperand(0), Op.getOperand(1)); +} + +SDValue +ARMTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const { + DebugLoc dl = Op.getDebugLoc(); + SDValue Val = DAG.getConstant(0, MVT::i32); + return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, MVT::i32, Op.getOperand(0), + Op.getOperand(1), Val); +} + +SDValue +ARMTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other, Op.getOperand(0), + Op.getOperand(1), DAG.getConstant(0, MVT::i32)); +} + +SDValue +ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) const { + unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); + DebugLoc dl = Op.getDebugLoc(); + switch (IntNo) { + default: return SDValue(); // Don't custom lower most intrinsics. + case Intrinsic::arm_thread_pointer: { + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT); + } + case Intrinsic::eh_sjlj_lsda: { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + unsigned ARMPCLabelIndex = AFI->createPICLabelUId(); + EVT PtrVT = getPointerTy(); + DebugLoc dl = Op.getDebugLoc(); + Reloc::Model RelocM = getTargetMachine().getRelocationModel(); + SDValue CPAddr; + unsigned PCAdj = (RelocM != Reloc::PIC_) + ? 0 : (Subtarget->isThumb() ? 4 : 8); + ARMConstantPoolValue *CPV = + new ARMConstantPoolValue(MF.getFunction(), ARMPCLabelIndex, + ARMCP::CPLSDA, PCAdj); + CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); + CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); + SDValue Result = + DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, + MachinePointerInfo::getConstantPool(), + false, false, 0); + + if (RelocM == Reloc::PIC_) { + SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); + Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); + } + return Result; + } + } +} + +static SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { + DebugLoc dl = Op.getDebugLoc(); + if (!Subtarget->hasDataBarrier()) { + // Some ARMv6 cpus can support data barriers with an mcr instruction. + // Thumb1 and pre-v6 ARM mode use a libcall instead and should never get + // here. + assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() && + "Unexpected ISD::MEMBARRIER encountered. Should be libcall!"); + return DAG.getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(0, MVT::i32)); + } + + SDValue Op5 = Op.getOperand(5); + bool isDeviceBarrier = cast(Op5)->getZExtValue() != 0; + unsigned isLL = cast(Op.getOperand(1))->getZExtValue(); + unsigned isLS = cast(Op.getOperand(2))->getZExtValue(); + bool isOnlyStoreBarrier = (isLL == 0 && isLS == 0); + + ARM_MB::MemBOpt DMBOpt; + if (isDeviceBarrier) + DMBOpt = isOnlyStoreBarrier ? ARM_MB::ST : ARM_MB::SY; + else + DMBOpt = isOnlyStoreBarrier ? ARM_MB::ISHST : ARM_MB::ISH; + return DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(DMBOpt, MVT::i32)); +} + +static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { + // ARM pre v5TE and Thumb1 does not have preload instructions. + if (!(Subtarget->isThumb2() || + (!Subtarget->isThumb1Only() && Subtarget->hasV5TEOps()))) + // Just preserve the chain. + return Op.getOperand(0); + + DebugLoc dl = Op.getDebugLoc(); + unsigned isRead = ~cast(Op.getOperand(2))->getZExtValue() & 1; + if (!isRead && + (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension())) + // ARMv7 with MP extension has PLDW. + return Op.getOperand(0); + + if (Subtarget->isThumb()) + // Invert the bits. + isRead = ~isRead & 1; + unsigned isData = Subtarget->isThumb() ? 0 : 1; + + // Currently there is no intrinsic that matches pli. + return DAG.getNode(ARMISD::PRELOAD, dl, MVT::Other, Op.getOperand(0), + Op.getOperand(1), DAG.getConstant(isRead, MVT::i32), + DAG.getConstant(isData, MVT::i32)); +} + +static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *FuncInfo = MF.getInfo(); + + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + DebugLoc dl = Op.getDebugLoc(); + EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); + const Value *SV = cast(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), + MachinePointerInfo(SV), false, false, 0); +} + +SDValue +ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, + SDValue &Root, SelectionDAG &DAG, + DebugLoc dl) const { + MachineFunction &MF = DAG.getMachineFunction(); + ARMFunctionInfo *AFI = MF.getInfo(); + + TargetRegisterClass *RC; + if (AFI->isThumb1OnlyFunction()) + RC = ARM::tGPRRegisterClass; + else + RC = ARM::GPRRegisterClass; + + // Transform the arguments stored in physical registers into virtual ones. + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); + + SDValue ArgValue2; + if (NextVA.isMemLoc()) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + int FI = MFI->CreateFixedObject(4, NextVA.getLocMemOffset(), true); + + // Create load node to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + ArgValue2 = DAG.getLoad(MVT::i32, dl, Root, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, 0); + } else { + Reg = MF.addLiveIn(NextVA.getLocReg(), RC); + ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); + } + + return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2); +} + +SDValue +ARMTargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl + &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) + const { + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + ARMFunctionInfo *AFI = MF.getInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, + CCAssignFnForNode(CallConv, /* Return*/ false, + isVarArg)); + + SmallVector ArgValues; + int lastInsIndex = -1; + + SDValue ArgValue; + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments stored in registers. + if (VA.isRegLoc()) { + EVT RegVT = VA.getLocVT(); + + if (VA.needsCustom()) { + // f64 and vector types are split up into multiple registers or + // combinations of registers and stack slots. + if (VA.getLocVT() == MVT::v2f64) { + SDValue ArgValue1 = GetF64FormalArgument(VA, ArgLocs[++i], + Chain, DAG, dl); + VA = ArgLocs[++i]; // skip ahead to next loc + SDValue ArgValue2; + if (VA.isMemLoc()) { + int FI = MFI->CreateFixedObject(8, VA.getLocMemOffset(), true); + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + ArgValue2 = DAG.getLoad(MVT::f64, dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, 0); + } else { + ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], + Chain, DAG, dl); + } + ArgValue = DAG.getNode(ISD::UNDEF, dl, MVT::v2f64); + ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, + ArgValue, ArgValue1, DAG.getIntPtrConstant(0)); + ArgValue = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, + ArgValue, ArgValue2, DAG.getIntPtrConstant(1)); + } else + ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl); + + } else { + TargetRegisterClass *RC; + + if (RegVT == MVT::f32) + RC = ARM::SPRRegisterClass; + else if (RegVT == MVT::f64) + RC = ARM::DPRRegisterClass; + else if (RegVT == MVT::v2f64) + RC = ARM::QPRRegisterClass; + else if (RegVT == MVT::i32) + RC = (AFI->isThumb1OnlyFunction() ? + ARM::tGPRRegisterClass : ARM::GPRRegisterClass); + else + llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering"); + + // Transform the arguments in physical registers into virtual ones. + unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); + ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + } + + // If this is an 8 or 16-bit value, it is really passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::BCvt: + ArgValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), ArgValue); + break; + case CCValAssign::SExt: + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + break; + case CCValAssign::ZExt: + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + break; + } + + InVals.push_back(ArgValue); + + } else { // VA.isRegLoc() + + // sanity check + assert(VA.isMemLoc()); + assert(VA.getValVT() != MVT::i64 && "i64 should already be lowered"); + + int index = ArgLocs[i].getValNo(); + + // Some Ins[] entries become multiple ArgLoc[] entries. + // Process them only once. + if (index != lastInsIndex) + { + ISD::ArgFlagsTy Flags = Ins[index].Flags; + // FIXME: For now, all byval parameter objects are marked mutable. This can be + // changed with more analysis. + // In case of tail call optimization mark all arguments mutable. Since they + // could be overwritten by lowering of arguments in case of a tail call. + if (Flags.isByVal()) { + int FI = MFI->CreateFixedObject(Flags.getByValSize(), + VA.getLocMemOffset(), false); + InVals.push_back(DAG.getFrameIndex(FI, getPointerTy())); + } else { + int FI = MFI->CreateFixedObject(VA.getLocVT().getSizeInBits()/8, + VA.getLocMemOffset(), true); + + // Create load nodes to retrieve arguments from the stack. + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(FI), + false, false, 0)); + } + lastInsIndex = index; + } + } + } + + // varargs + if (isVarArg) { + static const unsigned GPRArgRegs[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3 + }; + + unsigned NumGPRs = CCInfo.getFirstUnallocated + (GPRArgRegs, sizeof(GPRArgRegs) / sizeof(GPRArgRegs[0])); + + unsigned Align = MF.getTarget().getFrameLowering()->getStackAlignment(); + unsigned VARegSize = (4 - NumGPRs) * 4; + unsigned VARegSaveSize = (VARegSize + Align - 1) & ~(Align - 1); + unsigned ArgOffset = CCInfo.getNextStackOffset(); + if (VARegSaveSize) { + // If this function is vararg, store any remaining integer argument regs + // to their spots on the stack so that they may be loaded by deferencing + // the result of va_next. + AFI->setVarArgsRegSaveSize(VARegSaveSize); + AFI->setVarArgsFrameIndex( + MFI->CreateFixedObject(VARegSaveSize, + ArgOffset + VARegSaveSize - VARegSize, + false)); + SDValue FIN = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), + getPointerTy()); + + SmallVector MemOps; + for (; NumGPRs < 4; ++NumGPRs) { + TargetRegisterClass *RC; + if (AFI->isThumb1OnlyFunction()) + RC = ARM::tGPRRegisterClass; + else + RC = ARM::GPRRegisterClass; + + unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); + SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); + SDValue Store = + DAG.getStore(Val.getValue(1), dl, Val, FIN, + MachinePointerInfo::getFixedStack(AFI->getVarArgsFrameIndex()), + false, false, 0); + MemOps.push_back(Store); + FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, + DAG.getConstant(4, getPointerTy())); + } + if (!MemOps.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOps[0], MemOps.size()); + } else + // This will point to the next argument passed via stack. + AFI->setVarArgsFrameIndex(MFI->CreateFixedObject(4, ArgOffset, true)); + } + + return Chain; +} + +/// isFloatingPointZero - Return true if this is +0.0. +static bool isFloatingPointZero(SDValue Op) { + if (ConstantFPSDNode *CFP = dyn_cast(Op)) + return CFP->getValueAPF().isPosZero(); + else if (ISD::isEXTLoad(Op.getNode()) || ISD::isNON_EXTLoad(Op.getNode())) { + // Maybe this has already been legalized into the constant pool? + if (Op.getOperand(1).getOpcode() == ARMISD::Wrapper) { + SDValue WrapperOp = Op.getOperand(1).getOperand(0); + if (ConstantPoolSDNode *CP = dyn_cast(WrapperOp)) + if (const ConstantFP *CFP = dyn_cast(CP->getConstVal())) + return CFP->getValueAPF().isPosZero(); + } + } + return false; +} + +/// Returns appropriate ARM CMP (cmp) and corresponding condition code for +/// the given operands. +SDValue +ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, + SDValue &ARMcc, SelectionDAG &DAG, + DebugLoc dl) const { + if (ConstantSDNode *RHSC = dyn_cast(RHS.getNode())) { + unsigned C = RHSC->getZExtValue(); + if (!isLegalICmpImmediate(C)) { + // Constant does not fit, try adjusting it by one? + switch (CC) { + default: break; + case ISD::SETLT: + case ISD::SETGE: + if (C != 0x80000000 && isLegalICmpImmediate(C-1)) { + CC = (CC == ISD::SETLT) ? ISD::SETLE : ISD::SETGT; + RHS = DAG.getConstant(C-1, MVT::i32); + } + break; + case ISD::SETULT: + case ISD::SETUGE: + if (C != 0 && isLegalICmpImmediate(C-1)) { + CC = (CC == ISD::SETULT) ? ISD::SETULE : ISD::SETUGT; + RHS = DAG.getConstant(C-1, MVT::i32); + } + break; + case ISD::SETLE: + case ISD::SETGT: + if (C != 0x7fffffff && isLegalICmpImmediate(C+1)) { + CC = (CC == ISD::SETLE) ? ISD::SETLT : ISD::SETGE; + RHS = DAG.getConstant(C+1, MVT::i32); + } + break; + case ISD::SETULE: + case ISD::SETUGT: + if (C != 0xffffffff && isLegalICmpImmediate(C+1)) { + CC = (CC == ISD::SETULE) ? ISD::SETULT : ISD::SETUGE; + RHS = DAG.getConstant(C+1, MVT::i32); + } + break; + } + } + } + + ARMCC::CondCodes CondCode = IntCCToARMCC(CC); + ARMISD::NodeType CompareType; + switch (CondCode) { + default: + CompareType = ARMISD::CMP; + break; + case ARMCC::EQ: + case ARMCC::NE: + // Uses only Z Flag + CompareType = ARMISD::CMPZ; + break; + } + ARMcc = DAG.getConstant(CondCode, MVT::i32); + return DAG.getNode(CompareType, dl, MVT::Glue, LHS, RHS); +} + +/// Returns a appropriate VFP CMP (fcmp{s|d}+fmstat) for the given operands. +SDValue +ARMTargetLowering::getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, + DebugLoc dl) const { + SDValue Cmp; + if (!isFloatingPointZero(RHS)) + Cmp = DAG.getNode(ARMISD::CMPFP, dl, MVT::Glue, LHS, RHS); + else + Cmp = DAG.getNode(ARMISD::CMPFPw0, dl, MVT::Glue, LHS); + return DAG.getNode(ARMISD::FMSTAT, dl, MVT::Glue, Cmp); +} + +/// duplicateCmp - Glue values can have only one use, so this function +/// duplicates a comparison node. +SDValue +ARMTargetLowering::duplicateCmp(SDValue Cmp, SelectionDAG &DAG) const { + unsigned Opc = Cmp.getOpcode(); + DebugLoc DL = Cmp.getDebugLoc(); + if (Opc == ARMISD::CMP || Opc == ARMISD::CMPZ) + return DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0),Cmp.getOperand(1)); + + assert(Opc == ARMISD::FMSTAT && "unexpected comparison operation"); + Cmp = Cmp.getOperand(0); + Opc = Cmp.getOpcode(); + if (Opc == ARMISD::CMPFP) + Cmp = DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0),Cmp.getOperand(1)); + else { + assert(Opc == ARMISD::CMPFPw0 && "unexpected operand of FMSTAT"); + Cmp = DAG.getNode(Opc, DL, MVT::Glue, Cmp.getOperand(0)); + } + return DAG.getNode(ARMISD::FMSTAT, DL, MVT::Glue, Cmp); +} + +SDValue ARMTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { + SDValue Cond = Op.getOperand(0); + SDValue SelectTrue = Op.getOperand(1); + SDValue SelectFalse = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + // Convert: + // + // (select (cmov 1, 0, cond), t, f) -> (cmov t, f, cond) + // (select (cmov 0, 1, cond), t, f) -> (cmov f, t, cond) + // + if (Cond.getOpcode() == ARMISD::CMOV && Cond.hasOneUse()) { + const ConstantSDNode *CMOVTrue = + dyn_cast(Cond.getOperand(0)); + const ConstantSDNode *CMOVFalse = + dyn_cast(Cond.getOperand(1)); + + if (CMOVTrue && CMOVFalse) { + unsigned CMOVTrueVal = CMOVTrue->getZExtValue(); + unsigned CMOVFalseVal = CMOVFalse->getZExtValue(); + + SDValue True; + SDValue False; + if (CMOVTrueVal == 1 && CMOVFalseVal == 0) { + True = SelectTrue; + False = SelectFalse; + } else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) { + True = SelectFalse; + False = SelectTrue; + } + + if (True.getNode() && False.getNode()) { + EVT VT = Cond.getValueType(); + SDValue ARMcc = Cond.getOperand(2); + SDValue CCR = Cond.getOperand(3); + SDValue Cmp = duplicateCmp(Cond.getOperand(4), DAG); + return DAG.getNode(ARMISD::CMOV, dl, VT, True, False, ARMcc, CCR, Cmp); + } + } + } + + return DAG.getSelectCC(dl, Cond, + DAG.getConstant(0, Cond.getValueType()), + SelectTrue, SelectFalse, ISD::SETNE); +} + +SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { + EVT VT = Op.getValueType(); + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + ISD::CondCode CC = cast(Op.getOperand(4))->get(); + SDValue TrueVal = Op.getOperand(2); + SDValue FalseVal = Op.getOperand(3); + DebugLoc dl = Op.getDebugLoc(); + + if (LHS.getValueType() == MVT::i32) { + SDValue ARMcc; + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl); + return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR,Cmp); + } + + ARMCC::CondCodes CondCode, CondCode2; + FPCCToARMCC(CC, CondCode, CondCode2); + + SDValue ARMcc = DAG.getConstant(CondCode, MVT::i32); + SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Result = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, + ARMcc, CCR, Cmp); + if (CondCode2 != ARMCC::AL) { + SDValue ARMcc2 = DAG.getConstant(CondCode2, MVT::i32); + // FIXME: Needs another CMP because flag can have but one use. + SDValue Cmp2 = getVFPCmp(LHS, RHS, DAG, dl); + Result = DAG.getNode(ARMISD::CMOV, dl, VT, + Result, TrueVal, ARMcc2, CCR, Cmp2); + } + return Result; +} + +/// canChangeToInt - Given the fp compare operand, return true if it is suitable +/// to morph to an integer compare sequence. +static bool canChangeToInt(SDValue Op, bool &SeenZero, + const ARMSubtarget *Subtarget) { + SDNode *N = Op.getNode(); + if (!N->hasOneUse()) + // Otherwise it requires moving the value from fp to integer registers. + return false; + if (!N->getNumValues()) + return false; + EVT VT = Op.getValueType(); + if (VT != MVT::f32 && !Subtarget->isFPBrccSlow()) + // f32 case is generally profitable. f64 case only makes sense when vcmpe + + // vmrs are very slow, e.g. cortex-a8. + return false; + + if (isFloatingPointZero(Op)) { + SeenZero = true; + return true; + } + return ISD::isNormalLoad(N); +} + +static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG) { + if (isFloatingPointZero(Op)) + return DAG.getConstant(0, MVT::i32); + + if (LoadSDNode *Ld = dyn_cast(Op)) + return DAG.getLoad(MVT::i32, Op.getDebugLoc(), + Ld->getChain(), Ld->getBasePtr(), Ld->getPointerInfo(), + Ld->isVolatile(), Ld->isNonTemporal(), + Ld->getAlignment()); + + llvm_unreachable("Unknown VFP cmp argument!"); +} + +static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, + SDValue &RetVal1, SDValue &RetVal2) { + if (isFloatingPointZero(Op)) { + RetVal1 = DAG.getConstant(0, MVT::i32); + RetVal2 = DAG.getConstant(0, MVT::i32); + return; + } + + if (LoadSDNode *Ld = dyn_cast(Op)) { + SDValue Ptr = Ld->getBasePtr(); + RetVal1 = DAG.getLoad(MVT::i32, Op.getDebugLoc(), + Ld->getChain(), Ptr, + Ld->getPointerInfo(), + Ld->isVolatile(), Ld->isNonTemporal(), + Ld->getAlignment()); + + EVT PtrType = Ptr.getValueType(); + unsigned NewAlign = MinAlign(Ld->getAlignment(), 4); + SDValue NewPtr = DAG.getNode(ISD::ADD, Op.getDebugLoc(), + PtrType, Ptr, DAG.getConstant(4, PtrType)); + RetVal2 = DAG.getLoad(MVT::i32, Op.getDebugLoc(), + Ld->getChain(), NewPtr, + Ld->getPointerInfo().getWithOffset(4), + Ld->isVolatile(), Ld->isNonTemporal(), + NewAlign); + return; + } + + llvm_unreachable("Unknown VFP cmp argument!"); +} + +/// OptimizeVFPBrcond - With -enable-unsafe-fp-math, it's legal to optimize some +/// f32 and even f64 comparisons to integer ones. +SDValue +ARMTargetLowering::OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue Dest = Op.getOperand(4); + DebugLoc dl = Op.getDebugLoc(); + + bool SeenZero = false; + if (canChangeToInt(LHS, SeenZero, Subtarget) && + canChangeToInt(RHS, SeenZero, Subtarget) && + // If one of the operand is zero, it's safe to ignore the NaN case since + // we only care about equality comparisons. + (SeenZero || (DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS)))) { + // If unsafe fp math optimization is enabled and there are no other uses of + // the CMP operands, and the condition code is EQ or NE, we can optimize it + // to an integer comparison. + if (CC == ISD::SETOEQ) + CC = ISD::SETEQ; + else if (CC == ISD::SETUNE) + CC = ISD::SETNE; + + SDValue ARMcc; + if (LHS.getValueType() == MVT::f32) { + LHS = bitcastf32Toi32(LHS, DAG); + RHS = bitcastf32Toi32(RHS, DAG); + SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other, + Chain, Dest, ARMcc, CCR, Cmp); + } + + SDValue LHS1, LHS2; + SDValue RHS1, RHS2; + expandf64Toi32(LHS, DAG, LHS1, LHS2); + expandf64Toi32(RHS, DAG, RHS1, RHS2); + ARMCC::CondCodes CondCode = IntCCToARMCC(CC); + ARMcc = DAG.getConstant(CondCode, MVT::i32); + SDVTList VTList = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest }; + return DAG.getNode(ARMISD::BCC_i64, dl, VTList, Ops, 7); + } + + return SDValue(); +} + +SDValue ARMTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue Dest = Op.getOperand(4); + DebugLoc dl = Op.getDebugLoc(); + + if (LHS.getValueType() == MVT::i32) { + SDValue ARMcc; + SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other, + Chain, Dest, ARMcc, CCR, Cmp); + } + + assert(LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64); + + if (UnsafeFPMath && + (CC == ISD::SETEQ || CC == ISD::SETOEQ || + CC == ISD::SETNE || CC == ISD::SETUNE)) { + SDValue Result = OptimizeVFPBrcond(Op, DAG); + if (Result.getNode()) + return Result; + } + + ARMCC::CondCodes CondCode, CondCode2; + FPCCToARMCC(CC, CondCode, CondCode2); + + SDValue ARMcc = DAG.getConstant(CondCode, MVT::i32); + SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDVTList VTList = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue Ops[] = { Chain, Dest, ARMcc, CCR, Cmp }; + SDValue Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5); + if (CondCode2 != ARMCC::AL) { + ARMcc = DAG.getConstant(CondCode2, MVT::i32); + SDValue Ops[] = { Res, Dest, ARMcc, CCR, Res.getValue(1) }; + Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5); + } + return Res; +} + +SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Table = Op.getOperand(1); + SDValue Index = Op.getOperand(2); + DebugLoc dl = Op.getDebugLoc(); + + EVT PTy = getPointerTy(); + JumpTableSDNode *JT = cast(Table); + ARMFunctionInfo *AFI = DAG.getMachineFunction().getInfo(); + SDValue UId = DAG.getConstant(AFI->createJumpTableUId(), PTy); + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy); + Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI, UId); + Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, PTy)); + SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); + if (Subtarget->isThumb2()) { + // Thumb2 uses a two-level jump. That is, it jumps into the jump table + // which does another jump to the destination. This also makes it easier + // to translate it to TBB / TBH later. + // FIXME: This might not work if the function is extremely large. + return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain, + Addr, Op.getOperand(2), JTI, UId); + } + if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { + Addr = DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr, + MachinePointerInfo::getJumpTable(), + false, false, 0); + Chain = Addr.getValue(1); + Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, Table); + return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); + } else { + Addr = DAG.getLoad(PTy, dl, Chain, Addr, + MachinePointerInfo::getJumpTable(), false, false, 0); + Chain = Addr.getValue(1); + return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); + } +} + +static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + unsigned Opc; + + switch (Op.getOpcode()) { + default: + assert(0 && "Invalid opcode!"); + case ISD::FP_TO_SINT: + Opc = ARMISD::FTOSI; + break; + case ISD::FP_TO_UINT: + Opc = ARMISD::FTOUI; + break; + } + Op = DAG.getNode(Opc, dl, MVT::f32, Op.getOperand(0)); + return DAG.getNode(ISD::BITCAST, dl, MVT::i32, Op); +} + +static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Opc; + + switch (Op.getOpcode()) { + default: + assert(0 && "Invalid opcode!"); + case ISD::SINT_TO_FP: + Opc = ARMISD::SITOF; + break; + case ISD::UINT_TO_FP: + Opc = ARMISD::UITOF; + break; + } + + Op = DAG.getNode(ISD::BITCAST, dl, MVT::f32, Op.getOperand(0)); + return DAG.getNode(Opc, dl, VT, Op); +} + +SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { + // Implement fcopysign with a fabs and a conditional fneg. + SDValue Tmp0 = Op.getOperand(0); + SDValue Tmp1 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + EVT SrcVT = Tmp1.getValueType(); + bool InGPR = Tmp0.getOpcode() == ISD::BITCAST || + Tmp0.getOpcode() == ARMISD::VMOVDRR; + bool UseNEON = !InGPR && Subtarget->hasNEON(); + + if (UseNEON) { + // Use VBSL to copy the sign bit. + unsigned EncodedVal = ARM_AM::createNEONModImm(0x6, 0x80); + SDValue Mask = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v2i32, + DAG.getTargetConstant(EncodedVal, MVT::i32)); + EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64; + if (VT == MVT::f64) + Mask = DAG.getNode(ARMISD::VSHL, dl, OpVT, + DAG.getNode(ISD::BITCAST, dl, OpVT, Mask), + DAG.getConstant(32, MVT::i32)); + else /*if (VT == MVT::f32)*/ + Tmp0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp0); + if (SrcVT == MVT::f32) { + Tmp1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp1); + if (VT == MVT::f64) + Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT, + DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1), + DAG.getConstant(32, MVT::i32)); + } + Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0); + Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1); + + SDValue AllOnes = DAG.getTargetConstant(ARM_AM::createNEONModImm(0xe, 0xff), + MVT::i32); + AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes); + SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask, + DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes)); + + SDValue Res = DAG.getNode(ISD::OR, dl, OpVT, + DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask), + DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot)); + if (VT == MVT::f32) { + Res = DAG.getNode(ISD::BITCAST, dl, MVT::v2f32, Res); + Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, Res, + DAG.getConstant(0, MVT::i32)); + } else { + Res = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Res); + } + + return Res; + } + + // Bitcast operand 1 to i32. + if (SrcVT == MVT::f64) + Tmp1 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32), + &Tmp1, 1).getValue(1); + Tmp1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp1); + + // Or in the signbit with integer operations. + SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32); + SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32); + Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1); + if (VT == MVT::f32) { + Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32, + DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2); + return DAG.getNode(ISD::BITCAST, dl, MVT::f32, + DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1)); + } + + // f64: Or the high part with signbit and then combine two parts. + Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32), + &Tmp0, 1); + SDValue Lo = Tmp0.getValue(0); + SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2); + Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1); + return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi); +} + +SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{ + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MFI->setReturnAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + if (Depth) { + SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + SDValue Offset = DAG.getConstant(4, MVT::i32); + return DAG.getLoad(VT, dl, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset), + MachinePointerInfo(), false, false, 0); + } + + // Return LR, which contains the return address. Mark it an implicit live-in. + unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32)); + return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT); +} + +SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { + MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); + MFI->setFrameAddressIsTaken(true); + + EVT VT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + unsigned FrameReg = (Subtarget->isThumb() || Subtarget->isTargetDarwin()) + ? ARM::R7 : ARM::R11; + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); + while (Depth--) + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, + MachinePointerInfo(), + false, false, 0); + return FrameAddr; +} + +/// ExpandBITCAST - If the target supports VFP, this function is called to +/// expand a bit convert where either the source or destination type is i64 to +/// use a VMOVDRR or VMOVRRD node. This should not be done when the non-i64 +/// operand type is illegal (e.g., v2f32 for a target that doesn't support +/// vectors), since the legalizer won't know what to do with that. +static SDValue ExpandBITCAST(SDNode *N, SelectionDAG &DAG) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + DebugLoc dl = N->getDebugLoc(); + SDValue Op = N->getOperand(0); + + // This function is only supposed to be called for i64 types, either as the + // source or destination of the bit convert. + EVT SrcVT = Op.getValueType(); + EVT DstVT = N->getValueType(0); + assert((SrcVT == MVT::i64 || DstVT == MVT::i64) && + "ExpandBITCAST called for non-i64 type"); + + // Turn i64->f64 into VMOVDRR. + if (SrcVT == MVT::i64 && TLI.isTypeLegal(DstVT)) { + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op, + DAG.getConstant(0, MVT::i32)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op, + DAG.getConstant(1, MVT::i32)); + return DAG.getNode(ISD::BITCAST, dl, DstVT, + DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi)); + } + + // Turn f64->i64 into VMOVRRD. + if (DstVT == MVT::i64 && TLI.isTypeLegal(SrcVT)) { + SDValue Cvt = DAG.getNode(ARMISD::VMOVRRD, dl, + DAG.getVTList(MVT::i32, MVT::i32), &Op, 1); + // Merge the pieces into a single i64 value. + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Cvt, Cvt.getValue(1)); + } + + return SDValue(); +} + +/// getZeroVector - Returns a vector of specified type with all zero elements. +/// Zero vectors are used to represent vector negation and in those cases +/// will be implemented with the NEON VNEG instruction. However, VNEG does +/// not support i64 elements, so sometimes the zero vectors will need to be +/// explicitly constructed. Regardless, use a canonical VMOV to create the +/// zero vector. +static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) { + assert(VT.isVector() && "Expected a vector type"); + // The canonical modified immediate encoding of a zero vector is....0! + SDValue EncodedVal = DAG.getTargetConstant(0, MVT::i32); + EVT VmovVT = VT.is128BitVector() ? MVT::v4i32 : MVT::v2i32; + SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal); + return DAG.getNode(ISD::BITCAST, dl, VT, Vmov); +} + +/// LowerShiftRightParts - Lower SRA_PARTS, which returns two +/// i32 values and take a 2 x i32 value to shift plus a shift amount. +SDValue ARMTargetLowering::LowerShiftRightParts(SDValue Op, + SelectionDAG &DAG) const { + assert(Op.getNumOperands() == 3 && "Not a double-shift!"); + EVT VT = Op.getValueType(); + unsigned VTBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue ARMcc; + unsigned Opc = (Op.getOpcode() == ISD::SRA_PARTS) ? ISD::SRA : ISD::SRL; + + assert(Op.getOpcode() == ISD::SRA_PARTS || Op.getOpcode() == ISD::SRL_PARTS); + + SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, + DAG.getConstant(VTBits, MVT::i32), ShAmt); + SDValue Tmp1 = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, ShAmt); + SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt, + DAG.getConstant(VTBits, MVT::i32)); + SDValue Tmp2 = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, RevShAmt); + SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + SDValue TrueVal = DAG.getNode(Opc, dl, VT, ShOpHi, ExtraShAmt); + + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE, + ARMcc, DAG, dl); + SDValue Hi = DAG.getNode(Opc, dl, VT, ShOpHi, ShAmt); + SDValue Lo = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, + CCR, Cmp); + + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +/// LowerShiftLeftParts - Lower SHL_PARTS, which returns two +/// i32 values and take a 2 x i32 value to shift plus a shift amount. +SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op, + SelectionDAG &DAG) const { + assert(Op.getNumOperands() == 3 && "Not a double-shift!"); + EVT VT = Op.getValueType(); + unsigned VTBits = VT.getSizeInBits(); + DebugLoc dl = Op.getDebugLoc(); + SDValue ShOpLo = Op.getOperand(0); + SDValue ShOpHi = Op.getOperand(1); + SDValue ShAmt = Op.getOperand(2); + SDValue ARMcc; + + assert(Op.getOpcode() == ISD::SHL_PARTS); + SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, + DAG.getConstant(VTBits, MVT::i32), ShAmt); + SDValue Tmp1 = DAG.getNode(ISD::SRL, dl, VT, ShOpLo, RevShAmt); + SDValue ExtraShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32, ShAmt, + DAG.getConstant(VTBits, MVT::i32)); + SDValue Tmp2 = DAG.getNode(ISD::SHL, dl, VT, ShOpHi, ShAmt); + SDValue Tmp3 = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ExtraShAmt); + + SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2); + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32); + SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE, + ARMcc, DAG, dl); + SDValue Lo = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ShAmt); + SDValue Hi = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, Tmp3, ARMcc, + CCR, Cmp); + + SDValue Ops[2] = { Lo, Hi }; + return DAG.getMergeValues(Ops, 2, dl); +} + +SDValue ARMTargetLowering::LowerFLT_ROUNDS_(SDValue Op, + SelectionDAG &DAG) const { + // The rounding mode is in bits 23:22 of the FPSCR. + // The ARM rounding mode value to FLT_ROUNDS mapping is 0->1, 1->2, 2->3, 3->0 + // The formula we use to implement this is (((FPSCR + 1 << 22) >> 22) & 3) + // so that the shift + and get folded into a bitfield extract. + DebugLoc dl = Op.getDebugLoc(); + SDValue FPSCR = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, + DAG.getConstant(Intrinsic::arm_get_fpscr, + MVT::i32)); + SDValue FltRounds = DAG.getNode(ISD::ADD, dl, MVT::i32, FPSCR, + DAG.getConstant(1U << 22, MVT::i32)); + SDValue RMODE = DAG.getNode(ISD::SRL, dl, MVT::i32, FltRounds, + DAG.getConstant(22, MVT::i32)); + return DAG.getNode(ISD::AND, dl, MVT::i32, RMODE, + DAG.getConstant(3, MVT::i32)); +} + +static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + if (!ST->hasV6T2Ops()) + return SDValue(); + + SDValue rbit = DAG.getNode(ARMISD::RBIT, dl, VT, N->getOperand(0)); + return DAG.getNode(ISD::CTLZ, dl, VT, rbit); +} + +static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + if (!VT.isVector()) + return SDValue(); + + // Lower vector shifts on NEON to use VSHL. + assert(ST->hasNEON() && "unexpected vector shift"); + + // Left shifts translate directly to the vshiftu intrinsic. + if (N->getOpcode() == ISD::SHL) + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(Intrinsic::arm_neon_vshiftu, MVT::i32), + N->getOperand(0), N->getOperand(1)); + + assert((N->getOpcode() == ISD::SRA || + N->getOpcode() == ISD::SRL) && "unexpected vector shift opcode"); + + // NEON uses the same intrinsics for both left and right shifts. For + // right shifts, the shift amounts are negative, so negate the vector of + // shift amounts. + EVT ShiftVT = N->getOperand(1).getValueType(); + SDValue NegatedCount = DAG.getNode(ISD::SUB, dl, ShiftVT, + getZeroVector(ShiftVT, DAG, dl), + N->getOperand(1)); + Intrinsic::ID vshiftInt = (N->getOpcode() == ISD::SRA ? + Intrinsic::arm_neon_vshifts : + Intrinsic::arm_neon_vshiftu); + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, + DAG.getConstant(vshiftInt, MVT::i32), + N->getOperand(0), NegatedCount); +} + +static SDValue Expand64BitShift(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); + + // We can get here for a node like i32 = ISD::SHL i32, i64 + if (VT != MVT::i64) + return SDValue(); + + assert((N->getOpcode() == ISD::SRL || N->getOpcode() == ISD::SRA) && + "Unknown shift to lower!"); + + // We only lower SRA, SRL of 1 here, all others use generic lowering. + if (!isa(N->getOperand(1)) || + cast(N->getOperand(1))->getZExtValue() != 1) + return SDValue(); + + // If we are in thumb mode, we don't have RRX. + if (ST->isThumb1Only()) return SDValue(); + + // Okay, we have a 64-bit SRA or SRL of 1. Lower this to an RRX expr. + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0), + DAG.getConstant(0, MVT::i32)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(0), + DAG.getConstant(1, MVT::i32)); + + // First, build a SRA_FLAG/SRL_FLAG op, which shifts the top part by one and + // captures the result into a carry flag. + unsigned Opc = N->getOpcode() == ISD::SRL ? ARMISD::SRL_FLAG:ARMISD::SRA_FLAG; + Hi = DAG.getNode(Opc, dl, DAG.getVTList(MVT::i32, MVT::Glue), &Hi, 1); + + // The low part is an ARMISD::RRX operand, which shifts the carry in. + Lo = DAG.getNode(ARMISD::RRX, dl, MVT::i32, Lo, Hi.getValue(1)); + + // Merge the pieces into a single i64 value. + return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); +} + +static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) { + SDValue TmpOp0, TmpOp1; + bool Invert = false; + bool Swap = false; + unsigned Opc = 0; + + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + SDValue CC = Op.getOperand(2); + EVT VT = Op.getValueType(); + ISD::CondCode SetCCOpcode = cast(CC)->get(); + DebugLoc dl = Op.getDebugLoc(); + + if (Op.getOperand(1).getValueType().isFloatingPoint()) { + switch (SetCCOpcode) { + default: llvm_unreachable("Illegal FP comparison"); break; + case ISD::SETUNE: + case ISD::SETNE: Invert = true; // Fallthrough + case ISD::SETOEQ: + case ISD::SETEQ: Opc = ARMISD::VCEQ; break; + case ISD::SETOLT: + case ISD::SETLT: Swap = true; // Fallthrough + case ISD::SETOGT: + case ISD::SETGT: Opc = ARMISD::VCGT; break; + case ISD::SETOLE: + case ISD::SETLE: Swap = true; // Fallthrough + case ISD::SETOGE: + case ISD::SETGE: Opc = ARMISD::VCGE; break; + case ISD::SETUGE: Swap = true; // Fallthrough + case ISD::SETULE: Invert = true; Opc = ARMISD::VCGT; break; + case ISD::SETUGT: Swap = true; // Fallthrough + case ISD::SETULT: Invert = true; Opc = ARMISD::VCGE; break; + case ISD::SETUEQ: Invert = true; // Fallthrough + case ISD::SETONE: + // Expand this to (OLT | OGT). + TmpOp0 = Op0; + TmpOp1 = Op1; + Opc = ISD::OR; + Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0); + Op1 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp0, TmpOp1); + break; + case ISD::SETUO: Invert = true; // Fallthrough + case ISD::SETO: + // Expand this to (OLT | OGE). + TmpOp0 = Op0; + TmpOp1 = Op1; + Opc = ISD::OR; + Op0 = DAG.getNode(ARMISD::VCGT, dl, VT, TmpOp1, TmpOp0); + Op1 = DAG.getNode(ARMISD::VCGE, dl, VT, TmpOp0, TmpOp1); + break; + } + } else { + // Integer comparisons. + switch (SetCCOpcode) { + default: llvm_unreachable("Illegal integer comparison"); break; + case ISD::SETNE: Invert = true; + case ISD::SETEQ: Opc = ARMISD::VCEQ; break; + case ISD::SETLT: Swap = true; + case ISD::SETGT: Opc = ARMISD::VCGT; break; + case ISD::SETLE: Swap = true; + case ISD::SETGE: Opc = ARMISD::VCGE; break; + case ISD::SETULT: Swap = true; + case ISD::SETUGT: Opc = ARMISD::VCGTU; break; + case ISD::SETULE: Swap = true; + case ISD::SETUGE: Opc = ARMISD::VCGEU; break; + } + + // Detect VTST (Vector Test Bits) = icmp ne (and (op0, op1), zero). + if (Opc == ARMISD::VCEQ) { + + SDValue AndOp; + if (ISD::isBuildVectorAllZeros(Op1.getNode())) + AndOp = Op0; + else if (ISD::isBuildVectorAllZeros(Op0.getNode())) + AndOp = Op1; + + // Ignore bitconvert. + if (AndOp.getNode() && AndOp.getOpcode() == ISD::BITCAST) + AndOp = AndOp.getOperand(0); + + if (AndOp.getNode() && AndOp.getOpcode() == ISD::AND) { + Opc = ARMISD::VTST; + Op0 = DAG.getNode(ISD::BITCAST, dl, VT, AndOp.getOperand(0)); + Op1 = DAG.getNode(ISD::BITCAST, dl, VT, AndOp.getOperand(1)); + Invert = !Invert; + } + } + } + + if (Swap) + std::swap(Op0, Op1); + + // If one of the operands is a constant vector zero, attempt to fold the + // comparison to a specialized compare-against-zero form. + SDValue SingleOp; + if (ISD::isBuildVectorAllZeros(Op1.getNode())) + SingleOp = Op0; + else if (ISD::isBuildVectorAllZeros(Op0.getNode())) { + if (Opc == ARMISD::VCGE) + Opc = ARMISD::VCLEZ; + else if (Opc == ARMISD::VCGT) + Opc = ARMISD::VCLTZ; + SingleOp = Op1; + } + + SDValue Result; + if (SingleOp.getNode()) { + switch (Opc) { + case ARMISD::VCEQ: + Result = DAG.getNode(ARMISD::VCEQZ, dl, VT, SingleOp); break; + case ARMISD::VCGE: + Result = DAG.getNode(ARMISD::VCGEZ, dl, VT, SingleOp); break; + case ARMISD::VCLEZ: + Result = DAG.getNode(ARMISD::VCLEZ, dl, VT, SingleOp); break; + case ARMISD::VCGT: + Result = DAG.getNode(ARMISD::VCGTZ, dl, VT, SingleOp); break; + case ARMISD::VCLTZ: + Result = DAG.getNode(ARMISD::VCLTZ, dl, VT, SingleOp); break; + default: + Result = DAG.getNode(Opc, dl, VT, Op0, Op1); + } + } else { + Result = DAG.getNode(Opc, dl, VT, Op0, Op1); + } + + if (Invert) + Result = DAG.getNOT(dl, Result, VT); + + return Result; +} + +/// isNEONModifiedImm - Check if the specified splat value corresponds to a +/// valid vector constant for a NEON instruction with a "modified immediate" +/// operand (e.g., VMOV). If so, return the encoded value. +static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, + unsigned SplatBitSize, SelectionDAG &DAG, + EVT &VT, bool is128Bits, NEONModImmType type) { + unsigned OpCmode, Imm; + + // SplatBitSize is set to the smallest size that splats the vector, so a + // zero vector will always have SplatBitSize == 8. However, NEON modified + // immediate instructions others than VMOV do not support the 8-bit encoding + // of a zero vector, and the default encoding of zero is supposed to be the + // 32-bit version. + if (SplatBits == 0) + SplatBitSize = 32; + + switch (SplatBitSize) { + case 8: + if (type != VMOVModImm) + return SDValue(); + // Any 1-byte value is OK. Op=0, Cmode=1110. + assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big"); + OpCmode = 0xe; + Imm = SplatBits; + VT = is128Bits ? MVT::v16i8 : MVT::v8i8; + break; + + case 16: + // NEON's 16-bit VMOV supports splat values where only one byte is nonzero. + VT = is128Bits ? MVT::v8i16 : MVT::v4i16; + if ((SplatBits & ~0xff) == 0) { + // Value = 0x00nn: Op=x, Cmode=100x. + OpCmode = 0x8; + Imm = SplatBits; + break; + } + if ((SplatBits & ~0xff00) == 0) { + // Value = 0xnn00: Op=x, Cmode=101x. + OpCmode = 0xa; + Imm = SplatBits >> 8; + break; + } + return SDValue(); + + case 32: + // NEON's 32-bit VMOV supports splat values where: + // * only one byte is nonzero, or + // * the least significant byte is 0xff and the second byte is nonzero, or + // * the least significant 2 bytes are 0xff and the third is nonzero. + VT = is128Bits ? MVT::v4i32 : MVT::v2i32; + if ((SplatBits & ~0xff) == 0) { + // Value = 0x000000nn: Op=x, Cmode=000x. + OpCmode = 0; + Imm = SplatBits; + break; + } + if ((SplatBits & ~0xff00) == 0) { + // Value = 0x0000nn00: Op=x, Cmode=001x. + OpCmode = 0x2; + Imm = SplatBits >> 8; + break; + } + if ((SplatBits & ~0xff0000) == 0) { + // Value = 0x00nn0000: Op=x, Cmode=010x. + OpCmode = 0x4; + Imm = SplatBits >> 16; + break; + } + if ((SplatBits & ~0xff000000) == 0) { + // Value = 0xnn000000: Op=x, Cmode=011x. + OpCmode = 0x6; + Imm = SplatBits >> 24; + break; + } + + // cmode == 0b1100 and cmode == 0b1101 are not supported for VORR or VBIC + if (type == OtherModImm) return SDValue(); + + if ((SplatBits & ~0xffff) == 0 && + ((SplatBits | SplatUndef) & 0xff) == 0xff) { + // Value = 0x0000nnff: Op=x, Cmode=1100. + OpCmode = 0xc; + Imm = SplatBits >> 8; + SplatBits |= 0xff; + break; + } + + if ((SplatBits & ~0xffffff) == 0 && + ((SplatBits | SplatUndef) & 0xffff) == 0xffff) { + // Value = 0x00nnffff: Op=x, Cmode=1101. + OpCmode = 0xd; + Imm = SplatBits >> 16; + SplatBits |= 0xffff; + break; + } + + // Note: there are a few 32-bit splat values (specifically: 00ffff00, + // ff000000, ff0000ff, and ffff00ff) that are valid for VMOV.I64 but not + // VMOV.I32. A (very) minor optimization would be to replicate the value + // and fall through here to test for a valid 64-bit splat. But, then the + // caller would also need to check and handle the change in size. + return SDValue(); + + case 64: { + if (type != VMOVModImm) + return SDValue(); + // NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff. + uint64_t BitMask = 0xff; + uint64_t Val = 0; + unsigned ImmMask = 1; + Imm = 0; + for (int ByteNum = 0; ByteNum < 8; ++ByteNum) { + if (((SplatBits | SplatUndef) & BitMask) == BitMask) { + Val |= BitMask; + Imm |= ImmMask; + } else if ((SplatBits & BitMask) != 0) { + return SDValue(); + } + BitMask <<= 8; + ImmMask <<= 1; + } + // Op=1, Cmode=1110. + OpCmode = 0x1e; + SplatBits = Val; + VT = is128Bits ? MVT::v2i64 : MVT::v1i64; + break; + } + + default: + llvm_unreachable("unexpected size for isNEONModifiedImm"); + return SDValue(); + } + + unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm); + return DAG.getTargetConstant(EncodedVal, MVT::i32); +} + +static bool isVEXTMask(const SmallVectorImpl &M, EVT VT, + bool &ReverseVEXT, unsigned &Imm) { + unsigned NumElts = VT.getVectorNumElements(); + ReverseVEXT = false; + + // Assume that the first shuffle index is not UNDEF. Fail if it is. + if (M[0] < 0) + return false; + + Imm = M[0]; + + // If this is a VEXT shuffle, the immediate value is the index of the first + // element. The other shuffle indices must be the successive elements after + // the first one. + unsigned ExpectedElt = Imm; + for (unsigned i = 1; i < NumElts; ++i) { + // Increment the expected index. If it wraps around, it may still be + // a VEXT but the source vectors must be swapped. + ExpectedElt += 1; + if (ExpectedElt == NumElts * 2) { + ExpectedElt = 0; + ReverseVEXT = true; + } + + if (M[i] < 0) continue; // ignore UNDEF indices + if (ExpectedElt != static_cast(M[i])) + return false; + } + + // Adjust the index value if the source operands will be swapped. + if (ReverseVEXT) + Imm -= NumElts; + + return true; +} + +/// isVREVMask - Check if a vector shuffle corresponds to a VREV +/// instruction with the specified blocksize. (The order of the elements +/// within each block of the vector is reversed.) +static bool isVREVMask(const SmallVectorImpl &M, EVT VT, + unsigned BlockSize) { + assert((BlockSize==16 || BlockSize==32 || BlockSize==64) && + "Only possible block sizes for VREV are: 16, 32, 64"); + + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + unsigned BlockElts = M[0] + 1; + // If the first shuffle index is UNDEF, be optimistic. + if (M[0] < 0) + BlockElts = BlockSize / EltSz; + + if (BlockSize <= EltSz || BlockSize != BlockElts * EltSz) + return false; + + for (unsigned i = 0; i < NumElts; ++i) { + if (M[i] < 0) continue; // ignore UNDEF indices + if ((unsigned) M[i] != (i - i%BlockElts) + (BlockElts - 1 - i%BlockElts)) + return false; + } + + return true; +} + +static bool isVTRNMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned i = 0; i < NumElts; i += 2) { + if ((M[i] >= 0 && (unsigned) M[i] != i + WhichResult) || + (M[i+1] >= 0 && (unsigned) M[i+1] != i + NumElts + WhichResult)) + return false; + } + return true; +} + +/// isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of +/// "vector_shuffle v, v", i.e., "vector_shuffle v, undef". +/// Mask is e.g., <0, 0, 2, 2> instead of <0, 4, 2, 6>. +static bool isVTRN_v_undef_Mask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned i = 0; i < NumElts; i += 2) { + if ((M[i] >= 0 && (unsigned) M[i] != i + WhichResult) || + (M[i+1] >= 0 && (unsigned) M[i+1] != i + WhichResult)) + return false; + } + return true; +} + +static bool isVUZPMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned i = 0; i != NumElts; ++i) { + if (M[i] < 0) continue; // ignore UNDEF indices + if ((unsigned) M[i] != 2 * i + WhichResult) + return false; + } + + // VUZP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +/// isVUZP_v_undef_Mask - Special case of isVUZPMask for canonical form of +/// "vector_shuffle v, v", i.e., "vector_shuffle v, undef". +/// Mask is e.g., <0, 2, 0, 2> instead of <0, 2, 4, 6>, +static bool isVUZP_v_undef_Mask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned Half = VT.getVectorNumElements() / 2; + WhichResult = (M[0] == 0 ? 0 : 1); + for (unsigned j = 0; j != 2; ++j) { + unsigned Idx = WhichResult; + for (unsigned i = 0; i != Half; ++i) { + int MIdx = M[i + j * Half]; + if (MIdx >= 0 && (unsigned) MIdx != Idx) + return false; + Idx += 2; + } + } + + // VUZP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +static bool isVZIPMask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + unsigned Idx = WhichResult * NumElts / 2; + for (unsigned i = 0; i != NumElts; i += 2) { + if ((M[i] >= 0 && (unsigned) M[i] != Idx) || + (M[i+1] >= 0 && (unsigned) M[i+1] != Idx + NumElts)) + return false; + Idx += 1; + } + + // VZIP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +/// isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of +/// "vector_shuffle v, v", i.e., "vector_shuffle v, undef". +/// Mask is e.g., <0, 0, 1, 1> instead of <0, 4, 1, 5>. +static bool isVZIP_v_undef_Mask(const SmallVectorImpl &M, EVT VT, + unsigned &WhichResult) { + unsigned EltSz = VT.getVectorElementType().getSizeInBits(); + if (EltSz == 64) + return false; + + unsigned NumElts = VT.getVectorNumElements(); + WhichResult = (M[0] == 0 ? 0 : 1); + unsigned Idx = WhichResult * NumElts / 2; + for (unsigned i = 0; i != NumElts; i += 2) { + if ((M[i] >= 0 && (unsigned) M[i] != Idx) || + (M[i+1] >= 0 && (unsigned) M[i+1] != Idx)) + return false; + Idx += 1; + } + + // VZIP.32 for 64-bit vectors is a pseudo-instruction alias for VTRN.32. + if (VT.is64BitVector() && EltSz == 32) + return false; + + return true; +} + +// If N is an integer constant that can be moved into a register in one +// instruction, return an SDValue of such a constant (will become a MOV +// instruction). Otherwise return null. +static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, + const ARMSubtarget *ST, DebugLoc dl) { + uint64_t Val; + if (!isa(N)) + return SDValue(); + Val = cast(N)->getZExtValue(); + + if (ST->isThumb1Only()) { + if (Val <= 255 || ~Val <= 255) + return DAG.getConstant(Val, MVT::i32); + } else { + if (ARM_AM::getSOImmVal(Val) != -1 || ARM_AM::getSOImmVal(~Val) != -1) + return DAG.getConstant(Val, MVT::i32); + } + return SDValue(); +} + +// If this is a case we can't handle, return null and let the default +// expansion code take care of it. +SDValue ARMTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *ST) const { + BuildVectorSDNode *BVN = cast(Op.getNode()); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) { + if (SplatBitSize <= 64) { + // Check if an immediate VMOV works. + EVT VmovVT; + SDValue Val = isNEONModifiedImm(SplatBits.getZExtValue(), + SplatUndef.getZExtValue(), SplatBitSize, + DAG, VmovVT, VT.is128BitVector(), + VMOVModImm); + if (Val.getNode()) { + SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, Val); + return DAG.getNode(ISD::BITCAST, dl, VT, Vmov); + } + + // Try an immediate VMVN. + uint64_t NegatedImm = (SplatBits.getZExtValue() ^ + ((1LL << SplatBitSize) - 1)); + Val = isNEONModifiedImm(NegatedImm, + SplatUndef.getZExtValue(), SplatBitSize, + DAG, VmovVT, VT.is128BitVector(), + VMVNModImm); + if (Val.getNode()) { + SDValue Vmov = DAG.getNode(ARMISD::VMVNIMM, dl, VmovVT, Val); + return DAG.getNode(ISD::BITCAST, dl, VT, Vmov); + } + } + } + + // Scan through the operands to see if only one value is used. + unsigned NumElts = VT.getVectorNumElements(); + bool isOnlyLowElement = true; + bool usesOnlyOneValue = true; + bool isConstant = true; + SDValue Value; + for (unsigned i = 0; i < NumElts; ++i) { + SDValue V = Op.getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + if (i > 0) + isOnlyLowElement = false; + if (!isa(V) && !isa(V)) + isConstant = false; + + if (!Value.getNode()) + Value = V; + else if (V != Value) + usesOnlyOneValue = false; + } + + if (!Value.getNode()) + return DAG.getUNDEF(VT); + + if (isOnlyLowElement) + return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Value); + + unsigned EltSize = VT.getVectorElementType().getSizeInBits(); + + // Use VDUP for non-constant splats. For f32 constant splats, reduce to + // i32 and try again. + if (usesOnlyOneValue && EltSize <= 32) { + if (!isConstant) + return DAG.getNode(ARMISD::VDUP, dl, VT, Value); + if (VT.getVectorElementType().isFloatingPoint()) { + SmallVector Ops; + for (unsigned i = 0; i < NumElts; ++i) + Ops.push_back(DAG.getNode(ISD::BITCAST, dl, MVT::i32, + Op.getOperand(i))); + EVT VecVT = EVT::getVectorVT(*DAG.getContext(), MVT::i32, NumElts); + SDValue Val = DAG.getNode(ISD::BUILD_VECTOR, dl, VecVT, &Ops[0], NumElts); + Val = LowerBUILD_VECTOR(Val, DAG, ST); + if (Val.getNode()) + return DAG.getNode(ISD::BITCAST, dl, VT, Val); + } + SDValue Val = IsSingleInstrConstant(Value, DAG, ST, dl); + if (Val.getNode()) + return DAG.getNode(ARMISD::VDUP, dl, VT, Val); + } + + // If all elements are constants and the case above didn't get hit, fall back + // to the default expansion, which will generate a load from the constant + // pool. + if (isConstant) + return SDValue(); + + // Empirical tests suggest this is rarely worth it for vectors of length <= 2. + if (NumElts >= 4) { + SDValue shuffle = ReconstructShuffle(Op, DAG); + if (shuffle != SDValue()) + return shuffle; + } + + // Vectors with 32- or 64-bit elements can be built by directly assigning + // the subregisters. Lower it to an ARMISD::BUILD_VECTOR so the operands + // will be legalized. + if (EltSize >= 32) { + // Do the expansion with floating-point types, since that is what the VFP + // registers are defined to use, and since i64 is not legal. + EVT EltVT = EVT::getFloatingPointVT(EltSize); + EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts); + SmallVector Ops; + for (unsigned i = 0; i < NumElts; ++i) + Ops.push_back(DAG.getNode(ISD::BITCAST, dl, EltVT, Op.getOperand(i))); + SDValue Val = DAG.getNode(ARMISD::BUILD_VECTOR, dl, VecVT, &Ops[0],NumElts); + return DAG.getNode(ISD::BITCAST, dl, VT, Val); + } + + return SDValue(); +} + +// Gather data to see if the operation can be modelled as a +// shuffle in combination with VEXTs. +SDValue ARMTargetLowering::ReconstructShuffle(SDValue Op, + SelectionDAG &DAG) const { + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + unsigned NumElts = VT.getVectorNumElements(); + + SmallVector SourceVecs; + SmallVector MinElts; + SmallVector MaxElts; + + for (unsigned i = 0; i < NumElts; ++i) { + SDValue V = Op.getOperand(i); + if (V.getOpcode() == ISD::UNDEF) + continue; + else if (V.getOpcode() != ISD::EXTRACT_VECTOR_ELT) { + // A shuffle can only come from building a vector from various + // elements of other vectors. + return SDValue(); + } + + // Record this extraction against the appropriate vector if possible... + SDValue SourceVec = V.getOperand(0); + unsigned EltNo = cast(V.getOperand(1))->getZExtValue(); + bool FoundSource = false; + for (unsigned j = 0; j < SourceVecs.size(); ++j) { + if (SourceVecs[j] == SourceVec) { + if (MinElts[j] > EltNo) + MinElts[j] = EltNo; + if (MaxElts[j] < EltNo) + MaxElts[j] = EltNo; + FoundSource = true; + break; + } + } + + // Or record a new source if not... + if (!FoundSource) { + SourceVecs.push_back(SourceVec); + MinElts.push_back(EltNo); + MaxElts.push_back(EltNo); + } + } + + // Currently only do something sane when at most two source vectors + // involved. + if (SourceVecs.size() > 2) + return SDValue(); + + SDValue ShuffleSrcs[2] = {DAG.getUNDEF(VT), DAG.getUNDEF(VT) }; + int VEXTOffsets[2] = {0, 0}; + + // This loop extracts the usage patterns of the source vectors + // and prepares appropriate SDValues for a shuffle if possible. + for (unsigned i = 0; i < SourceVecs.size(); ++i) { + if (SourceVecs[i].getValueType() == VT) { + // No VEXT necessary + ShuffleSrcs[i] = SourceVecs[i]; + VEXTOffsets[i] = 0; + continue; + } else if (SourceVecs[i].getValueType().getVectorNumElements() < NumElts) { + // It probably isn't worth padding out a smaller vector just to + // break it down again in a shuffle. + return SDValue(); + } + + // Since only 64-bit and 128-bit vectors are legal on ARM and + // we've eliminated the other cases... + assert(SourceVecs[i].getValueType().getVectorNumElements() == 2*NumElts && + "unexpected vector sizes in ReconstructShuffle"); + + if (MaxElts[i] - MinElts[i] >= NumElts) { + // Span too large for a VEXT to cope + return SDValue(); + } + + if (MinElts[i] >= NumElts) { + // The extraction can just take the second half + VEXTOffsets[i] = NumElts; + ShuffleSrcs[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, + SourceVecs[i], + DAG.getIntPtrConstant(NumElts)); + } else if (MaxElts[i] < NumElts) { + // The extraction can just take the first half + VEXTOffsets[i] = 0; + ShuffleSrcs[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, + SourceVecs[i], + DAG.getIntPtrConstant(0)); + } else { + // An actual VEXT is needed + VEXTOffsets[i] = MinElts[i]; + SDValue VEXTSrc1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, + SourceVecs[i], + DAG.getIntPtrConstant(0)); + SDValue VEXTSrc2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, + SourceVecs[i], + DAG.getIntPtrConstant(NumElts)); + ShuffleSrcs[i] = DAG.getNode(ARMISD::VEXT, dl, VT, VEXTSrc1, VEXTSrc2, + DAG.getConstant(VEXTOffsets[i], MVT::i32)); + } + } + + SmallVector Mask; + + for (unsigned i = 0; i < NumElts; ++i) { + SDValue Entry = Op.getOperand(i); + if (Entry.getOpcode() == ISD::UNDEF) { + Mask.push_back(-1); + continue; + } + + SDValue ExtractVec = Entry.getOperand(0); + int ExtractElt = cast(Op.getOperand(i) + .getOperand(1))->getSExtValue(); + if (ExtractVec == SourceVecs[0]) { + Mask.push_back(ExtractElt - VEXTOffsets[0]); + } else { + Mask.push_back(ExtractElt + NumElts - VEXTOffsets[1]); + } + } + + // Final check before we try to produce nonsense... + if (isShuffleMaskLegal(Mask, VT)) + return DAG.getVectorShuffle(VT, dl, ShuffleSrcs[0], ShuffleSrcs[1], + &Mask[0]); + + return SDValue(); +} + +/// isShuffleMaskLegal - Targets can use this to indicate that they only +/// support *some* VECTOR_SHUFFLE operations, those with specific masks. +/// By default, if a target supports the VECTOR_SHUFFLE node, all mask values +/// are assumed to be legal. +bool +ARMTargetLowering::isShuffleMaskLegal(const SmallVectorImpl &M, + EVT VT) const { + if (VT.getVectorNumElements() == 4 && + (VT.is128BitVector() || VT.is64BitVector())) { + unsigned PFIndexes[4]; + for (unsigned i = 0; i != 4; ++i) { + if (M[i] < 0) + PFIndexes[i] = 8; + else + PFIndexes[i] = M[i]; + } + + // Compute the index in the perfect shuffle table. + unsigned PFTableIndex = + PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; + unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; + unsigned Cost = (PFEntry >> 30); + + if (Cost <= 4) + return true; + } + + bool ReverseVEXT; + unsigned Imm, WhichResult; + + unsigned EltSize = VT.getVectorElementType().getSizeInBits(); + return (EltSize >= 32 || + ShuffleVectorSDNode::isSplatMask(&M[0], VT) || + isVREVMask(M, VT, 64) || + isVREVMask(M, VT, 32) || + isVREVMask(M, VT, 16) || + isVEXTMask(M, VT, ReverseVEXT, Imm) || + isVTRNMask(M, VT, WhichResult) || + isVUZPMask(M, VT, WhichResult) || + isVZIPMask(M, VT, WhichResult) || + isVTRN_v_undef_Mask(M, VT, WhichResult) || + isVUZP_v_undef_Mask(M, VT, WhichResult) || + isVZIP_v_undef_Mask(M, VT, WhichResult)); +} + +/// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit +/// the specified operations to build the shuffle. +static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, + SDValue RHS, SelectionDAG &DAG, + DebugLoc dl) { + unsigned OpNum = (PFEntry >> 26) & 0x0F; + unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1); + unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1); + + enum { + OP_COPY = 0, // Copy, used for things like 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 + }; + + if (OpNum == OP_COPY) { + if (LHSID == (1*9+2)*9+3) return LHS; + assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); + return RHS; + } + + SDValue OpLHS, OpRHS; + OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); + OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); + EVT VT = OpLHS.getValueType(); + + switch (OpNum) { + default: llvm_unreachable("Unknown shuffle opcode!"); + case OP_VREV: + return DAG.getNode(ARMISD::VREV64, dl, VT, OpLHS); + case OP_VDUP0: + case OP_VDUP1: + case OP_VDUP2: + case OP_VDUP3: + return DAG.getNode(ARMISD::VDUPLANE, dl, VT, + OpLHS, DAG.getConstant(OpNum-OP_VDUP0, MVT::i32)); + case OP_VEXT1: + case OP_VEXT2: + case OP_VEXT3: + return DAG.getNode(ARMISD::VEXT, dl, VT, + OpLHS, OpRHS, + DAG.getConstant(OpNum-OP_VEXT1+1, MVT::i32)); + case OP_VUZPL: + case OP_VUZPR: + return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VUZPL); + case OP_VZIPL: + case OP_VZIPR: + return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VZIPL); + case OP_VTRNL: + case OP_VTRNR: + return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT), + OpLHS, OpRHS).getValue(OpNum-OP_VTRNL); + } +} + +static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) { + SDValue V1 = Op.getOperand(0); + SDValue V2 = Op.getOperand(1); + DebugLoc dl = Op.getDebugLoc(); + EVT VT = Op.getValueType(); + ShuffleVectorSDNode *SVN = cast(Op.getNode()); + SmallVector ShuffleMask; + + // Convert shuffles that are directly supported on NEON to target-specific + // DAG nodes, instead of keeping them as shuffles and matching them again + // during code selection. This is more efficient and avoids the possibility + // of inconsistencies between legalization and selection. + // FIXME: floating-point vectors should be canonicalized to integer vectors + // of the same time so that they get CSEd properly. + SVN->getMask(ShuffleMask); + + unsigned EltSize = VT.getVectorElementType().getSizeInBits(); + if (EltSize <= 32) { + if (ShuffleVectorSDNode::isSplatMask(&ShuffleMask[0], VT)) { + int Lane = SVN->getSplatIndex(); + // If this is undef splat, generate it via "just" vdup, if possible. + if (Lane == -1) Lane = 0; + + if (Lane == 0 && V1.getOpcode() == ISD::SCALAR_TO_VECTOR) { + return DAG.getNode(ARMISD::VDUP, dl, VT, V1.getOperand(0)); + } + return DAG.getNode(ARMISD::VDUPLANE, dl, VT, V1, + DAG.getConstant(Lane, MVT::i32)); + } + + bool ReverseVEXT; + unsigned Imm; + if (isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) { + if (ReverseVEXT) + std::swap(V1, V2); + return DAG.getNode(ARMISD::VEXT, dl, VT, V1, V2, + DAG.getConstant(Imm, MVT::i32)); + } + + if (isVREVMask(ShuffleMask, VT, 64)) + return DAG.getNode(ARMISD::VREV64, dl, VT, V1); + if (isVREVMask(ShuffleMask, VT, 32)) + return DAG.getNode(ARMISD::VREV32, dl, VT, V1); + if (isVREVMask(ShuffleMask, VT, 16)) + return DAG.getNode(ARMISD::VREV16, dl, VT, V1); + + // Check for Neon shuffles that modify both input vectors in place. + // If both results are used, i.e., if there are two shuffles with the same + // source operands and with masks corresponding to both results of one of + // these operations, DAG memoization will ensure that a single node is + // used for both shuffles. + unsigned WhichResult; + if (isVTRNMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + if (isVUZPMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + if (isVZIPMask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT), + V1, V2).getValue(WhichResult); + + if (isVTRN_v_undef_Mask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VTRN, dl, DAG.getVTList(VT, VT), + V1, V1).getValue(WhichResult); + if (isVUZP_v_undef_Mask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VUZP, dl, DAG.getVTList(VT, VT), + V1, V1).getValue(WhichResult); + if (isVZIP_v_undef_Mask(ShuffleMask, VT, WhichResult)) + return DAG.getNode(ARMISD::VZIP, dl, DAG.getVTList(VT, VT), + V1, V1).getValue(WhichResult); + } + + // If the shuffle is not directly supported and it has 4 elements, use + // the PerfectShuffle-generated table to synthesize it from other shuffles. + unsigned NumElts = VT.getVectorNumElements(); + if (NumElts == 4) { + unsigned PFIndexes[4]; + for (unsigned i = 0; i != 4; ++i) { + if (ShuffleMask[i] < 0) + PFIndexes[i] = 8; + else + PFIndexes[i] = ShuffleMask[i]; + } + + // Compute the index in the perfect shuffle table. + unsigned PFTableIndex = + PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; + unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; + unsigned Cost = (PFEntry >> 30); + + if (Cost <= 4) + return GeneratePerfectShuffle(PFEntry, V1, V2, DAG, dl); + } + + // Implement shuffles with 32- or 64-bit elements as ARMISD::BUILD_VECTORs. + if (EltSize >= 32) { + // Do the expansion with floating-point types, since that is what the VFP + // registers are defined to use, and since i64 is not legal. + EVT EltVT = EVT::getFloatingPointVT(EltSize); + EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NumElts); + V1 = DAG.getNode(ISD::BITCAST, dl, VecVT, V1); + V2 = DAG.getNode(ISD::BITCAST, dl, VecVT, V2); + SmallVector Ops; + for (unsigned i = 0; i < NumElts; ++i) { + if (ShuffleMask[i] < 0) + Ops.push_back(DAG.getUNDEF(EltVT)); + else + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, + ShuffleMask[i] < (int)NumElts ? V1 : V2, + DAG.getConstant(ShuffleMask[i] & (NumElts-1), + MVT::i32))); + } + SDValue Val = DAG.getNode(ARMISD::BUILD_VECTOR, dl, VecVT, &Ops[0],NumElts); + return DAG.getNode(ISD::BITCAST, dl, VT, Val); + } + + return SDValue(); +} + +static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) { + // EXTRACT_VECTOR_ELT is legal only for immediate indexes. + SDValue Lane = Op.getOperand(1); + if (!isa(Lane)) + return SDValue(); + + SDValue Vec = Op.getOperand(0); + if (Op.getValueType() == MVT::i32 && + Vec.getValueType().getVectorElementType().getSizeInBits() < 32) { + DebugLoc dl = Op.getDebugLoc(); + return DAG.getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane); + } + + return Op; +} + +static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) { + // The only time a CONCAT_VECTORS operation can have legal types is when + // two 64-bit vectors are concatenated to a 128-bit vector. + assert(Op.getValueType().is128BitVector() && Op.getNumOperands() == 2 && + "unexpected CONCAT_VECTORS"); + DebugLoc dl = Op.getDebugLoc(); + SDValue Val = DAG.getUNDEF(MVT::v2f64); + SDValue Op0 = Op.getOperand(0); + SDValue Op1 = Op.getOperand(1); + if (Op0.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Val, + DAG.getNode(ISD::BITCAST, dl, MVT::f64, Op0), + DAG.getIntPtrConstant(0)); + if (Op1.getOpcode() != ISD::UNDEF) + Val = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, MVT::v2f64, Val, + DAG.getNode(ISD::BITCAST, dl, MVT::f64, Op1), + DAG.getIntPtrConstant(1)); + return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Val); +} + +/// isExtendedBUILD_VECTOR - Check if N is a constant BUILD_VECTOR where each +/// element has been zero/sign-extended, depending on the isSigned parameter, +/// from an integer type half its size. +static bool isExtendedBUILD_VECTOR(SDNode *N, SelectionDAG &DAG, + bool isSigned) { + // A v2i64 BUILD_VECTOR will have been legalized to a BITCAST from v4i32. + EVT VT = N->getValueType(0); + if (VT == MVT::v2i64 && N->getOpcode() == ISD::BITCAST) { + SDNode *BVN = N->getOperand(0).getNode(); + if (BVN->getValueType(0) != MVT::v4i32 || + BVN->getOpcode() != ISD::BUILD_VECTOR) + return false; + unsigned LoElt = DAG.getTargetLoweringInfo().isBigEndian() ? 1 : 0; + unsigned HiElt = 1 - LoElt; + ConstantSDNode *Lo0 = dyn_cast(BVN->getOperand(LoElt)); + ConstantSDNode *Hi0 = dyn_cast(BVN->getOperand(HiElt)); + ConstantSDNode *Lo1 = dyn_cast(BVN->getOperand(LoElt+2)); + ConstantSDNode *Hi1 = dyn_cast(BVN->getOperand(HiElt+2)); + if (!Lo0 || !Hi0 || !Lo1 || !Hi1) + return false; + if (isSigned) { + if (Hi0->getSExtValue() == Lo0->getSExtValue() >> 32 && + Hi1->getSExtValue() == Lo1->getSExtValue() >> 32) + return true; + } else { + if (Hi0->isNullValue() && Hi1->isNullValue()) + return true; + } + return false; + } + + if (N->getOpcode() != ISD::BUILD_VECTOR) + return false; + + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { + SDNode *Elt = N->getOperand(i).getNode(); + if (ConstantSDNode *C = dyn_cast(Elt)) { + unsigned EltSize = VT.getVectorElementType().getSizeInBits(); + unsigned HalfSize = EltSize / 2; + if (isSigned) { + int64_t SExtVal = C->getSExtValue(); + if ((SExtVal >> HalfSize) != (SExtVal >> EltSize)) + return false; + } else { + if ((C->getZExtValue() >> HalfSize) != 0) + return false; + } + continue; + } + return false; + } + + return true; +} + +/// isSignExtended - Check if a node is a vector value that is sign-extended +/// or a constant BUILD_VECTOR with sign-extended elements. +static bool isSignExtended(SDNode *N, SelectionDAG &DAG) { + if (N->getOpcode() == ISD::SIGN_EXTEND || ISD::isSEXTLoad(N)) + return true; + if (isExtendedBUILD_VECTOR(N, DAG, true)) + return true; + return false; +} + +/// isZeroExtended - Check if a node is a vector value that is zero-extended +/// or a constant BUILD_VECTOR with zero-extended elements. +static bool isZeroExtended(SDNode *N, SelectionDAG &DAG) { + if (N->getOpcode() == ISD::ZERO_EXTEND || ISD::isZEXTLoad(N)) + return true; + if (isExtendedBUILD_VECTOR(N, DAG, false)) + return true; + return false; +} + +/// SkipExtension - For a node that is a SIGN_EXTEND, ZERO_EXTEND, extending +/// load, or BUILD_VECTOR with extended elements, return the unextended value. +static SDValue SkipExtension(SDNode *N, SelectionDAG &DAG) { + if (N->getOpcode() == ISD::SIGN_EXTEND || N->getOpcode() == ISD::ZERO_EXTEND) + return N->getOperand(0); + if (LoadSDNode *LD = dyn_cast(N)) + return DAG.getLoad(LD->getMemoryVT(), N->getDebugLoc(), LD->getChain(), + LD->getBasePtr(), LD->getPointerInfo(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); + // Otherwise, the value must be a BUILD_VECTOR. For v2i64, it will + // have been legalized as a BITCAST from v4i32. + if (N->getOpcode() == ISD::BITCAST) { + SDNode *BVN = N->getOperand(0).getNode(); + assert(BVN->getOpcode() == ISD::BUILD_VECTOR && + BVN->getValueType(0) == MVT::v4i32 && "expected v4i32 BUILD_VECTOR"); + unsigned LowElt = DAG.getTargetLoweringInfo().isBigEndian() ? 1 : 0; + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), MVT::v2i32, + BVN->getOperand(LowElt), BVN->getOperand(LowElt+2)); + } + // Construct a new BUILD_VECTOR with elements truncated to half the size. + assert(N->getOpcode() == ISD::BUILD_VECTOR && "expected BUILD_VECTOR"); + EVT VT = N->getValueType(0); + unsigned EltSize = VT.getVectorElementType().getSizeInBits() / 2; + unsigned NumElts = VT.getVectorNumElements(); + MVT TruncVT = MVT::getIntegerVT(EltSize); + SmallVector Ops; + for (unsigned i = 0; i != NumElts; ++i) { + ConstantSDNode *C = cast(N->getOperand(i)); + const APInt &CInt = C->getAPIntValue(); + Ops.push_back(DAG.getConstant(CInt.trunc(EltSize), TruncVT)); + } + return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), + MVT::getVectorVT(TruncVT, NumElts), Ops.data(), NumElts); +} + +static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) { + // Multiplications are only custom-lowered for 128-bit vectors so that + // VMULL can be detected. Otherwise v2i64 multiplications are not legal. + EVT VT = Op.getValueType(); + assert(VT.is128BitVector() && "unexpected type for custom-lowering ISD::MUL"); + SDNode *N0 = Op.getOperand(0).getNode(); + SDNode *N1 = Op.getOperand(1).getNode(); + unsigned NewOpc = 0; + if (isSignExtended(N0, DAG) && isSignExtended(N1, DAG)) + NewOpc = ARMISD::VMULLs; + else if (isZeroExtended(N0, DAG) && isZeroExtended(N1, DAG)) + NewOpc = ARMISD::VMULLu; + else if (VT == MVT::v2i64) + // Fall through to expand this. It is not legal. + return SDValue(); + else + // Other vector multiplications are legal. + return Op; + + // Legalize to a VMULL instruction. + DebugLoc DL = Op.getDebugLoc(); + SDValue Op0 = SkipExtension(N0, DAG); + SDValue Op1 = SkipExtension(N1, DAG); + + assert(Op0.getValueType().is64BitVector() && + Op1.getValueType().is64BitVector() && + "unexpected types for extended operands to VMULL"); + return DAG.getNode(NewOpc, DL, VT, Op0, Op1); +} + +static SDValue +LowerSDIV_v4i8(SDValue X, SDValue Y, DebugLoc dl, SelectionDAG &DAG) { + // Convert to float + // float4 xf = vcvt_f32_s32(vmovl_s16(a.lo)); + // float4 yf = vcvt_f32_s32(vmovl_s16(b.lo)); + X = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, X); + Y = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, Y); + X = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, X); + Y = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Y); + // Get reciprocal estimate. + // float4 recip = vrecpeq_f32(yf); + Y = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), Y); + // Because char has a smaller range than uchar, we can actually get away + // without any newton steps. This requires that we use a weird bias + // of 0xb000, however (again, this has been exhaustively tested). + // float4 result = as_float4(as_int4(xf*recip) + 0xb000); + X = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, X, Y); + X = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, X); + Y = DAG.getConstant(0xb000, MVT::i32); + Y = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Y, Y, Y, Y); + X = DAG.getNode(ISD::ADD, dl, MVT::v4i32, X, Y); + X = DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, X); + // Convert back to short. + X = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::v4i32, X); + X = DAG.getNode(ISD::TRUNCATE, dl, MVT::v4i16, X); + return X; +} + +static SDValue +LowerSDIV_v4i16(SDValue N0, SDValue N1, DebugLoc dl, SelectionDAG &DAG) { + SDValue N2; + // Convert to float. + // float4 yf = vcvt_f32_s32(vmovl_s16(y)); + // float4 xf = vcvt_f32_s32(vmovl_s16(x)); + N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, N0); + N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, N1); + N0 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N0); + N1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N1); + + // Use reciprocal estimate and one refinement step. + // float4 recip = vrecpeq_f32(yf); + // recip *= vrecpsq_f32(yf, recip); + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), + N1, N2); + N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); + // Because short has a smaller range than ushort, we can actually get away + // with only a single newton step. This requires that we use a weird bias + // of 89, however (again, this has been exhaustively tested). + // float4 result = as_float4(as_int4(xf*recip) + 89); + N0 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N0, N2); + N0 = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, N0); + N1 = DAG.getConstant(89, MVT::i32); + N1 = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, N1, N1, N1, N1); + N0 = DAG.getNode(ISD::ADD, dl, MVT::v4i32, N0, N1); + N0 = DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, N0); + // Convert back to integer and return. + // return vmovn_s32(vcvt_s32_f32(result)); + N0 = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::v4i32, N0); + N0 = DAG.getNode(ISD::TRUNCATE, dl, MVT::v4i16, N0); + return N0; +} + +static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + assert((VT == MVT::v4i16 || VT == MVT::v8i8) && + "unexpected type for custom-lowering ISD::SDIV"); + + DebugLoc dl = Op.getDebugLoc(); + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2, N3; + + if (VT == MVT::v8i8) { + N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N0); + N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N1); + + N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, + DAG.getIntPtrConstant(4)); + N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, + DAG.getIntPtrConstant(4)); + N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, + DAG.getIntPtrConstant(0)); + N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, + DAG.getIntPtrConstant(0)); + + N0 = LowerSDIV_v4i8(N0, N1, dl, DAG); // v4i16 + N2 = LowerSDIV_v4i8(N2, N3, dl, DAG); // v4i16 + + N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); + N0 = LowerCONCAT_VECTORS(N0, DAG); + + N0 = DAG.getNode(ISD::TRUNCATE, dl, MVT::v8i8, N0); + return N0; + } + return LowerSDIV_v4i16(N0, N1, dl, DAG); +} + +static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG) { + EVT VT = Op.getValueType(); + assert((VT == MVT::v4i16 || VT == MVT::v8i8) && + "unexpected type for custom-lowering ISD::UDIV"); + + DebugLoc dl = Op.getDebugLoc(); + SDValue N0 = Op.getOperand(0); + SDValue N1 = Op.getOperand(1); + SDValue N2, N3; + + if (VT == MVT::v8i8) { + N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N0); + N1 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N1); + + N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, + DAG.getIntPtrConstant(4)); + N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, + DAG.getIntPtrConstant(4)); + N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, + DAG.getIntPtrConstant(0)); + N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, + DAG.getIntPtrConstant(0)); + + N0 = LowerSDIV_v4i16(N0, N1, dl, DAG); // v4i16 + N2 = LowerSDIV_v4i16(N2, N3, dl, DAG); // v4i16 + + N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); + N0 = LowerCONCAT_VECTORS(N0, DAG); + + N0 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v8i8, + DAG.getConstant(Intrinsic::arm_neon_vqmovnsu, MVT::i32), + N0); + return N0; + } + + // v4i16 sdiv ... Convert to float. + // float4 yf = vcvt_f32_s32(vmovl_u16(y)); + // float4 xf = vcvt_f32_s32(vmovl_u16(x)); + N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v4i32, N0); + N1 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v4i32, N1); + N0 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N0); + N1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N1); + + // Use reciprocal estimate and two refinement steps. + // float4 recip = vrecpeq_f32(yf); + // recip *= vrecpsq_f32(yf, recip); + // recip *= vrecpsq_f32(yf, recip); + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), + N1, N2); + N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, + DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), + N1, N2); + N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); + // Simply multiplying by the reciprocal estimate can leave us a few ulps + // too low, so we add 2 ulps (exhaustive testing shows that this is enough, + // and that it will never cause us to return an answer too large). + // float4 result = as_float4(as_int4(xf*recip) + 89); + N0 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N0, N2); + N0 = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, N0); + N1 = DAG.getConstant(2, MVT::i32); + N1 = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, N1, N1, N1, N1); + N0 = DAG.getNode(ISD::ADD, dl, MVT::v4i32, N0, N1); + N0 = DAG.getNode(ISD::BITCAST, dl, MVT::v4f32, N0); + // Convert back to integer and return. + // return vmovn_u32(vcvt_s32_f32(result)); + N0 = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::v4i32, N0); + N0 = DAG.getNode(ISD::TRUNCATE, dl, MVT::v4i16, N0); + return N0; +} + +SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: llvm_unreachable("Don't know how to custom lower this!"); + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); + case ISD::GlobalAddress: + return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) : + LowerGlobalAddressELF(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::SELECT: return LowerSELECT(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::BR_CC: return LowerBR_CC(Op, DAG); + case ISD::BR_JT: return LowerBR_JT(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); + case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG, Subtarget); + case ISD::PREFETCH: return LowerPREFETCH(Op, DAG, Subtarget); + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG); + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG); + case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG); + case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG); + case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG); + case ISD::EH_SJLJ_DISPATCHSETUP: return LowerEH_SJLJ_DISPATCHSETUP(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG, + Subtarget); + case ISD::BITCAST: return ExpandBITCAST(Op.getNode(), DAG); + case ISD::SHL: + case ISD::SRL: + case ISD::SRA: return LowerShift(Op.getNode(), DAG, Subtarget); + case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); + case ISD::SRL_PARTS: + case ISD::SRA_PARTS: return LowerShiftRightParts(Op, DAG); + case ISD::CTTZ: return LowerCTTZ(Op.getNode(), DAG, Subtarget); + case ISD::VSETCC: return LowerVSETCC(Op, DAG); + case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG, Subtarget); + case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); + case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); + case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG); + case ISD::MUL: return LowerMUL(Op, DAG); + case ISD::SDIV: return LowerSDIV(Op, DAG); + case ISD::UDIV: return LowerUDIV(Op, DAG); + } + return SDValue(); +} + +/// ReplaceNodeResults - Replace the results of node with an illegal result +/// type with new values built out of custom code. +void ARMTargetLowering::ReplaceNodeResults(SDNode *N, + SmallVectorImpl&Results, + SelectionDAG &DAG) const { + SDValue Res; + switch (N->getOpcode()) { + default: + llvm_unreachable("Don't know how to custom expand this!"); + break; + case ISD::BITCAST: + Res = ExpandBITCAST(N, DAG); + break; + case ISD::SRL: + case ISD::SRA: + Res = Expand64BitShift(N, DAG, Subtarget); + break; + } + if (Res.getNode()) + Results.push_back(Res); +} + +//===----------------------------------------------------------------------===// +// ARM Scheduler Hooks +//===----------------------------------------------------------------------===// + +MachineBasicBlock * +ARMTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size) const { + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptr = MI->getOperand(1).getReg(); + unsigned oldval = MI->getOperand(2).getReg(); + unsigned newval = MI->getOperand(3).getReg(); + unsigned scratch = BB->getParent()->getRegInfo() + .createVirtualRegister(ARM::GPRRegisterClass); + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); + + unsigned ldrOpc, strOpc; + switch (Size) { + default: llvm_unreachable("unsupported size for AtomicCmpSwap!"); + case 1: + ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; + strOpc = isThumb2 ? ARM::t2STREXB : ARM::STREXB; + break; + case 2: + ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; + strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; + break; + case 4: + ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; + strOpc = isThumb2 ? ARM::t2STREX : ARM::STREX; + break; + } + + MachineFunction *MF = BB->getParent(); + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; // insert the new blocks after the current block + + MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MF->insert(It, loop1MBB); + MF->insert(It, loop2MBB); + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + exitMBB->transferSuccessorsAndUpdatePHIs(BB); + + // thisMBB: + // ... + // fallthrough --> loop1MBB + BB->addSuccessor(loop1MBB); + + // loop1MBB: + // ldrex dest, [ptr] + // cmp dest, oldval + // bne exitMBB + BB = loop1MBB; + AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) + .addReg(dest).addReg(oldval)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(exitMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + BB->addSuccessor(loop2MBB); + BB->addSuccessor(exitMBB); + + // loop2MBB: + // strex scratch, newval, [ptr] + // cmp scratch, #0 + // bne loop1MBB + BB = loop2MBB; + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval) + .addReg(ptr)); + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(scratch).addImm(0)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loop1MBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + BB->addSuccessor(loop1MBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + + MI->eraseFromParent(); // The instruction is gone now. + + return BB; +} + +MachineBasicBlock * +ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, + unsigned Size, unsigned BinOpcode) const { + // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction *MF = BB->getParent(); + MachineFunction::iterator It = BB; + ++It; + + unsigned dest = MI->getOperand(0).getReg(); + unsigned ptr = MI->getOperand(1).getReg(); + unsigned incr = MI->getOperand(2).getReg(); + DebugLoc dl = MI->getDebugLoc(); + + bool isThumb2 = Subtarget->isThumb2(); + unsigned ldrOpc, strOpc; + switch (Size) { + default: llvm_unreachable("unsupported size for AtomicCmpSwap!"); + case 1: + ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; + strOpc = isThumb2 ? ARM::t2STREXB : ARM::STREXB; + break; + case 2: + ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; + strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; + break; + case 4: + ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; + strOpc = isThumb2 ? ARM::t2STREX : ARM::STREX; + break; + } + + MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MF->insert(It, loopMBB); + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + exitMBB->transferSuccessorsAndUpdatePHIs(BB); + + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + unsigned scratch = RegInfo.createVirtualRegister(ARM::GPRRegisterClass); + unsigned scratch2 = (!BinOpcode) ? incr : + RegInfo.createVirtualRegister(ARM::GPRRegisterClass); + + // thisMBB: + // ... + // fallthrough --> loopMBB + BB->addSuccessor(loopMBB); + + // loopMBB: + // ldrex dest, ptr + // scratch2, dest, incr + // strex scratch, scratch2, ptr + // cmp scratch, #0 + // bne- loopMBB + // fallthrough --> exitMBB + BB = loopMBB; + AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); + if (BinOpcode) { + // operand order needs to go the other way for NAND + if (BinOpcode == ARM::BICrr || BinOpcode == ARM::t2BICrr) + AddDefaultPred(BuildMI(BB, dl, TII->get(BinOpcode), scratch2). + addReg(incr).addReg(dest)).addReg(0); + else + AddDefaultPred(BuildMI(BB, dl, TII->get(BinOpcode), scratch2). + addReg(dest).addReg(incr)).addReg(0); + } + + AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) + .addReg(ptr)); + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(scratch).addImm(0)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loopMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); + + BB->addSuccessor(loopMBB); + BB->addSuccessor(exitMBB); + + // exitMBB: + // ... + BB = exitMBB; + + MI->eraseFromParent(); // The instruction is gone now. + + return BB; +} + +static +MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) { + for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(), + E = MBB->succ_end(); I != E; ++I) + if (*I != Succ) + return *I; + llvm_unreachable("Expecting a BB with two successors!"); +} + +MachineBasicBlock * +ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); + switch (MI->getOpcode()) { + default: + MI->dump(); + llvm_unreachable("Unexpected instr type to insert"); + + case ARM::ATOMIC_LOAD_ADD_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + case ARM::ATOMIC_LOAD_ADD_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + case ARM::ATOMIC_LOAD_ADD_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + + case ARM::ATOMIC_LOAD_AND_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + case ARM::ATOMIC_LOAD_AND_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + case ARM::ATOMIC_LOAD_AND_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + + case ARM::ATOMIC_LOAD_OR_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + case ARM::ATOMIC_LOAD_OR_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + case ARM::ATOMIC_LOAD_OR_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + + case ARM::ATOMIC_LOAD_XOR_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + case ARM::ATOMIC_LOAD_XOR_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + case ARM::ATOMIC_LOAD_XOR_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + + case ARM::ATOMIC_LOAD_NAND_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + case ARM::ATOMIC_LOAD_NAND_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + case ARM::ATOMIC_LOAD_NAND_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + + case ARM::ATOMIC_LOAD_SUB_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + case ARM::ATOMIC_LOAD_SUB_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + case ARM::ATOMIC_LOAD_SUB_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + + case ARM::ATOMIC_SWAP_I8: return EmitAtomicBinary(MI, BB, 1, 0); + case ARM::ATOMIC_SWAP_I16: return EmitAtomicBinary(MI, BB, 2, 0); + case ARM::ATOMIC_SWAP_I32: return EmitAtomicBinary(MI, BB, 4, 0); + + case ARM::ATOMIC_CMP_SWAP_I8: return EmitAtomicCmpSwap(MI, BB, 1); + case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(MI, BB, 2); + case ARM::ATOMIC_CMP_SWAP_I32: return EmitAtomicCmpSwap(MI, BB, 4); + + case ARM::tMOVCCr_pseudo: { + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *thisMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, copy0MBB); + F->insert(It, sinkMBB); + + // Transfer the remainder of BB and its successor edges to sinkMBB. + sinkMBB->splice(sinkMBB->begin(), BB, + llvm::next(MachineBasicBlock::iterator(MI)), + BB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(BB); + + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + BuildMI(BB, dl, TII->get(ARM::tBcc)).addMBB(sinkMBB) + .addImm(MI->getOperand(3).getImm()).addReg(MI->getOperand(4).getReg()); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(*BB, BB->begin(), dl, + TII->get(ARM::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB) + .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + return BB; + } + + case ARM::BCCi64: + case ARM::BCCZi64: { + // If there is an unconditional branch to the other successor, remove it. + BB->erase(llvm::next(MachineBasicBlock::iterator(MI)), BB->end()); + + // Compare both parts that make up the double comparison separately for + // equality. + bool RHSisZero = MI->getOpcode() == ARM::BCCZi64; + + unsigned LHS1 = MI->getOperand(1).getReg(); + unsigned LHS2 = MI->getOperand(2).getReg(); + if (RHSisZero) { + AddDefaultPred(BuildMI(BB, dl, + TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(LHS1).addImm(0)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) + .addReg(LHS2).addImm(0) + .addImm(ARMCC::EQ).addReg(ARM::CPSR); + } else { + unsigned RHS1 = MI->getOperand(3).getReg(); + unsigned RHS2 = MI->getOperand(4).getReg(); + AddDefaultPred(BuildMI(BB, dl, + TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) + .addReg(LHS1).addReg(RHS1)); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) + .addReg(LHS2).addReg(RHS2) + .addImm(ARMCC::EQ).addReg(ARM::CPSR); + } + + MachineBasicBlock *destMBB = MI->getOperand(RHSisZero ? 3 : 5).getMBB(); + MachineBasicBlock *exitMBB = OtherSucc(BB, destMBB); + if (MI->getOperand(0).getImm() == ARMCC::NE) + std::swap(destMBB, exitMBB); + + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B)) + .addMBB(exitMBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + return BB; + } + } +} + +//===----------------------------------------------------------------------===// +// ARM Optimization Hooks +//===----------------------------------------------------------------------===// + +static +SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, + TargetLowering::DAGCombinerInfo &DCI) { + SelectionDAG &DAG = DCI.DAG; + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT VT = N->getValueType(0); + unsigned Opc = N->getOpcode(); + bool isSlctCC = Slct.getOpcode() == ISD::SELECT_CC; + SDValue LHS = isSlctCC ? Slct.getOperand(2) : Slct.getOperand(1); + SDValue RHS = isSlctCC ? Slct.getOperand(3) : Slct.getOperand(2); + ISD::CondCode CC = ISD::SETCC_INVALID; + + if (isSlctCC) { + CC = cast(Slct.getOperand(4))->get(); + } else { + SDValue CCOp = Slct.getOperand(0); + if (CCOp.getOpcode() == ISD::SETCC) + CC = cast(CCOp.getOperand(2))->get(); + } + + bool DoXform = false; + bool InvCC = false; + assert ((Opc == ISD::ADD || (Opc == ISD::SUB && Slct == N->getOperand(1))) && + "Bad input!"); + + if (LHS.getOpcode() == ISD::Constant && + cast(LHS)->isNullValue()) { + DoXform = true; + } else if (CC != ISD::SETCC_INVALID && + RHS.getOpcode() == ISD::Constant && + cast(RHS)->isNullValue()) { + std::swap(LHS, RHS); + SDValue Op0 = Slct.getOperand(0); + EVT OpVT = isSlctCC ? Op0.getValueType() : + Op0.getOperand(0).getValueType(); + bool isInt = OpVT.isInteger(); + CC = ISD::getSetCCInverse(CC, isInt); + + if (!TLI.isCondCodeLegal(CC, OpVT)) + return SDValue(); // Inverse operator isn't legal. + + DoXform = true; + InvCC = true; + } + + if (DoXform) { + SDValue Result = DAG.getNode(Opc, RHS.getDebugLoc(), VT, OtherOp, RHS); + if (isSlctCC) + return DAG.getSelectCC(N->getDebugLoc(), OtherOp, Result, + Slct.getOperand(0), Slct.getOperand(1), CC); + SDValue CCOp = Slct.getOperand(0); + if (InvCC) + CCOp = DAG.getSetCC(Slct.getDebugLoc(), CCOp.getValueType(), + CCOp.getOperand(0), CCOp.getOperand(1), CC); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, + CCOp, OtherOp, Result); + } + return SDValue(); +} + +/// PerformADDCombineWithOperands - Try DAG combinations for an ADD with +/// operands N0 and N1. This is a helper for PerformADDCombine that is +/// called with the default operands, and if that fails, with commuted +/// operands. +static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, + TargetLowering::DAGCombinerInfo &DCI) { + // fold (add (select cc, 0, c), x) -> (select cc, x, (add, x, c)) + if (N0.getOpcode() == ISD::SELECT && N0.getNode()->hasOneUse()) { + SDValue Result = combineSelectAndUse(N, N0, N1, DCI); + if (Result.getNode()) return Result; + } + return SDValue(); +} + +/// PerformADDCombine - Target-specific dag combine xforms for ISD::ADD. +/// +static SDValue PerformADDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + // First try with the default operand order. + SDValue Result = PerformADDCombineWithOperands(N, N0, N1, DCI); + if (Result.getNode()) + return Result; + + // If that didn't work, try again with the operands commuted. + return PerformADDCombineWithOperands(N, N1, N0, DCI); +} + +/// PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB. +/// +static SDValue PerformSUBCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + + // fold (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c)) + if (N1.getOpcode() == ISD::SELECT && N1.getNode()->hasOneUse()) { + SDValue Result = combineSelectAndUse(N, N1, N0, DCI); + if (Result.getNode()) return Result; + } + + return SDValue(); +} + +static SDValue PerformMULCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + SelectionDAG &DAG = DCI.DAG; + + if (Subtarget->isThumb1Only()) + return SDValue(); + + if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) + return SDValue(); + + EVT VT = N->getValueType(0); + if (VT != MVT::i32) + return SDValue(); + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + if (!C) + return SDValue(); + + uint64_t MulAmt = C->getZExtValue(); + unsigned ShiftAmt = CountTrailingZeros_64(MulAmt); + ShiftAmt = ShiftAmt & (32 - 1); + SDValue V = N->getOperand(0); + DebugLoc DL = N->getDebugLoc(); + + SDValue Res; + MulAmt >>= ShiftAmt; + if (isPowerOf2_32(MulAmt - 1)) { + // (mul x, 2^N + 1) => (add (shl x, N), x) + Res = DAG.getNode(ISD::ADD, DL, VT, + V, DAG.getNode(ISD::SHL, DL, VT, + V, DAG.getConstant(Log2_32(MulAmt-1), + MVT::i32))); + } else if (isPowerOf2_32(MulAmt + 1)) { + // (mul x, 2^N - 1) => (sub (shl x, N), x) + Res = DAG.getNode(ISD::SUB, DL, VT, + DAG.getNode(ISD::SHL, DL, VT, + V, DAG.getConstant(Log2_32(MulAmt+1), + MVT::i32)), + V); + } else + return SDValue(); + + if (ShiftAmt != 0) + Res = DAG.getNode(ISD::SHL, DL, VT, Res, + DAG.getConstant(ShiftAmt, MVT::i32)); + + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, Res, false); + return SDValue(); +} + +static SDValue PerformANDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // Attempt to use immediate-form VBIC + BuildVectorSDNode *BVN = dyn_cast(N->getOperand(1)); + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SelectionDAG &DAG = DCI.DAG; + + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (BVN && + BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) { + if (SplatBitSize <= 64) { + EVT VbicVT; + SDValue Val = isNEONModifiedImm((~SplatBits).getZExtValue(), + SplatUndef.getZExtValue(), SplatBitSize, + DAG, VbicVT, VT.is128BitVector(), + OtherModImm); + if (Val.getNode()) { + SDValue Input = + DAG.getNode(ISD::BITCAST, dl, VbicVT, N->getOperand(0)); + SDValue Vbic = DAG.getNode(ARMISD::VBICIMM, dl, VbicVT, Input, Val); + return DAG.getNode(ISD::BITCAST, dl, VT, Vbic); + } + } + } + + return SDValue(); +} + +/// PerformORCombine - Target-specific dag combine xforms for ISD::OR +static SDValue PerformORCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI, + const ARMSubtarget *Subtarget) { + // Attempt to use immediate-form VORR + BuildVectorSDNode *BVN = dyn_cast(N->getOperand(1)); + DebugLoc dl = N->getDebugLoc(); + EVT VT = N->getValueType(0); + SelectionDAG &DAG = DCI.DAG; + + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (BVN && Subtarget->hasNEON() && + BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) { + if (SplatBitSize <= 64) { + EVT VorrVT; + SDValue Val = isNEONModifiedImm(SplatBits.getZExtValue(), + SplatUndef.getZExtValue(), SplatBitSize, + DAG, VorrVT, VT.is128BitVector(), + OtherModImm); + if (Val.getNode()) { + SDValue Input = + DAG.getNode(ISD::BITCAST, dl, VorrVT, N->getOperand(0)); + SDValue Vorr = DAG.getNode(ARMISD::VORRIMM, dl, VorrVT, Input, Val); + return DAG.getNode(ISD::BITCAST, dl, VT, Vorr); + } + } + } + + // Try to use the ARM/Thumb2 BFI (bitfield insert) instruction when + // reasonable. + + // BFI is only available on V6T2+ + if (Subtarget->isThumb1Only() || !Subtarget->hasV6T2Ops()) + return SDValue(); + + SDValue N0 = N->getOperand(0), N1 = N->getOperand(1); + DebugLoc DL = N->getDebugLoc(); + // 1) or (and A, mask), val => ARMbfi A, val, mask + // iff (val & mask) == val + // + // 2) or (and A, mask), (and B, mask2) => ARMbfi A, (lsr B, amt), mask + // 2a) iff isBitFieldInvertedMask(mask) && isBitFieldInvertedMask(~mask2) + // && CountPopulation_32(mask) == CountPopulation_32(~mask2) + // 2b) iff isBitFieldInvertedMask(~mask) && isBitFieldInvertedMask(mask2) + // && CountPopulation_32(mask) == CountPopulation_32(~mask2) + // (i.e., copy a bitfield value into another bitfield of the same width) + if (N0.getOpcode() != ISD::AND) + return SDValue(); + + if (VT != MVT::i32) + return SDValue(); + + SDValue N00 = N0.getOperand(0); + + // The value and the mask need to be constants so we can verify this is + // actually a bitfield set. If the mask is 0xffff, we can do better + // via a movt instruction, so don't use BFI in that case. + SDValue MaskOp = N0.getOperand(1); + ConstantSDNode *MaskC = dyn_cast(MaskOp); + if (!MaskC) + return SDValue(); + unsigned Mask = MaskC->getZExtValue(); + if (Mask == 0xffff) + return SDValue(); + SDValue Res; + // Case (1): or (and A, mask), val => ARMbfi A, val, mask + ConstantSDNode *N1C = dyn_cast(N1); + if (N1C) { + unsigned Val = N1C->getZExtValue(); + if ((Val & ~Mask) != Val) + return SDValue(); + + if (ARM::isBitFieldInvertedMask(Mask)) { + Val >>= CountTrailingZeros_32(~Mask); + + Res = DAG.getNode(ARMISD::BFI, DL, VT, N00, + DAG.getConstant(Val, MVT::i32), + DAG.getConstant(Mask, MVT::i32)); + + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, Res, false); + return SDValue(); + } + } else if (N1.getOpcode() == ISD::AND) { + // case (2) or (and A, mask), (and B, mask2) => ARMbfi A, (lsr B, amt), mask + ConstantSDNode *N11C = dyn_cast(N1.getOperand(1)); + if (!N11C) + return SDValue(); + unsigned Mask2 = N11C->getZExtValue(); + + if (ARM::isBitFieldInvertedMask(Mask) && + ARM::isBitFieldInvertedMask(~Mask2) && + (CountPopulation_32(Mask) == CountPopulation_32(~Mask2))) { + // The pack halfword instruction works better for masks that fit it, + // so use that when it's available. + if (Subtarget->hasT2ExtractPack() && + (Mask == 0xffff || Mask == 0xffff0000)) + return SDValue(); + // 2a + unsigned lsb = CountTrailingZeros_32(Mask2); + Res = DAG.getNode(ISD::SRL, DL, VT, N1.getOperand(0), + DAG.getConstant(lsb, MVT::i32)); + Res = DAG.getNode(ARMISD::BFI, DL, VT, N00, Res, + DAG.getConstant(Mask, MVT::i32)); + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, Res, false); + return SDValue(); + } else if (ARM::isBitFieldInvertedMask(~Mask) && + ARM::isBitFieldInvertedMask(Mask2) && + (CountPopulation_32(~Mask) == CountPopulation_32(Mask2))) { + // The pack halfword instruction works better for masks that fit it, + // so use that when it's available. + if (Subtarget->hasT2ExtractPack() && + (Mask2 == 0xffff || Mask2 == 0xffff0000)) + return SDValue(); + // 2b + unsigned lsb = CountTrailingZeros_32(Mask); + Res = DAG.getNode(ISD::SRL, DL, VT, N00, + DAG.getConstant(lsb, MVT::i32)); + Res = DAG.getNode(ARMISD::BFI, DL, VT, N1.getOperand(0), Res, + DAG.getConstant(Mask2, MVT::i32)); + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, Res, false); + return SDValue(); + } + } + + if (DAG.MaskedValueIsZero(N1, MaskC->getAPIntValue()) && + N00.getOpcode() == ISD::SHL && isa(N00.getOperand(1)) && + ARM::isBitFieldInvertedMask(~Mask)) { + // Case (3): or (and (shl A, #shamt), mask), B => ARMbfi B, A, ~mask + // where lsb(mask) == #shamt and masked bits of B are known zero. + SDValue ShAmt = N00.getOperand(1); + unsigned ShAmtC = cast(ShAmt)->getZExtValue(); + unsigned LSB = CountTrailingZeros_32(Mask); + if (ShAmtC != LSB) + return SDValue(); + + Res = DAG.getNode(ARMISD::BFI, DL, VT, N1, N00.getOperand(0), + DAG.getConstant(~Mask, MVT::i32)); + + // Do not add new nodes to DAG combiner worklist. + DCI.CombineTo(N, Res, false); + } + + return SDValue(); +} + +/// PerformBFICombine - (bfi A, (and B, C1), C2) -> (bfi A, B, C2) iff +/// C1 & C2 == C1. +static SDValue PerformBFICombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + SDValue N1 = N->getOperand(1); + if (N1.getOpcode() == ISD::AND) { + ConstantSDNode *N11C = dyn_cast(N1.getOperand(1)); + if (!N11C) + return SDValue(); + unsigned Mask = cast(N->getOperand(2))->getZExtValue(); + unsigned Mask2 = N11C->getZExtValue(); + if ((Mask & Mask2) == Mask2) + return DCI.DAG.getNode(ARMISD::BFI, N->getDebugLoc(), N->getValueType(0), + N->getOperand(0), N1.getOperand(0), + N->getOperand(2)); + } + return SDValue(); +} + +/// PerformVMOVRRDCombine - Target-specific dag combine xforms for +/// ARMISD::VMOVRRD. +static SDValue PerformVMOVRRDCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // vmovrrd(vmovdrr x, y) -> x,y + SDValue InDouble = N->getOperand(0); + if (InDouble.getOpcode() == ARMISD::VMOVDRR) + return DCI.CombineTo(N, InDouble.getOperand(0), InDouble.getOperand(1)); + return SDValue(); +} + +/// PerformVMOVDRRCombine - Target-specific dag combine xforms for +/// ARMISD::VMOVDRR. This is also used for BUILD_VECTORs with 2 operands. +static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG) { + // N=vmovrrd(X); vmovdrr(N:0, N:1) -> bit_convert(X) + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + if (Op0.getOpcode() == ISD::BITCAST) + Op0 = Op0.getOperand(0); + if (Op1.getOpcode() == ISD::BITCAST) + Op1 = Op1.getOperand(0); + if (Op0.getOpcode() == ARMISD::VMOVRRD && + Op0.getNode() == Op1.getNode() && + Op0.getResNo() == 0 && Op1.getResNo() == 1) + return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), + N->getValueType(0), Op0.getOperand(0)); + return SDValue(); +} + +/// PerformSTORECombine - Target-specific dag combine xforms for +/// ISD::STORE. +static SDValue PerformSTORECombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // Bitcast an i64 store extracted from a vector to f64. + // Otherwise, the i64 value will be legalized to a pair of i32 values. + StoreSDNode *St = cast(N); + SDValue StVal = St->getValue(); + if (!ISD::isNormalStore(St) || St->isVolatile() || + StVal.getValueType() != MVT::i64 || + StVal.getNode()->getOpcode() != ISD::EXTRACT_VECTOR_ELT) + return SDValue(); + + SelectionDAG &DAG = DCI.DAG; + DebugLoc dl = StVal.getDebugLoc(); + SDValue IntVec = StVal.getOperand(0); + EVT FloatVT = EVT::getVectorVT(*DAG.getContext(), MVT::f64, + IntVec.getValueType().getVectorNumElements()); + SDValue Vec = DAG.getNode(ISD::BITCAST, dl, FloatVT, IntVec); + SDValue ExtElt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f64, + Vec, StVal.getOperand(1)); + dl = N->getDebugLoc(); + SDValue V = DAG.getNode(ISD::BITCAST, dl, MVT::i64, ExtElt); + // Make the DAGCombiner fold the bitcasts. + DCI.AddToWorklist(Vec.getNode()); + DCI.AddToWorklist(ExtElt.getNode()); + DCI.AddToWorklist(V.getNode()); + return DAG.getStore(St->getChain(), dl, V, St->getBasePtr(), + St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), St->getAlignment(), + St->getTBAAInfo()); +} + +/// hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node +/// are normal, non-volatile loads. If so, it is profitable to bitcast an +/// i64 vector to have f64 elements, since the value can then be loaded +/// directly into a VFP register. +static bool hasNormalLoadOperand(SDNode *N) { + unsigned NumElts = N->getValueType(0).getVectorNumElements(); + for (unsigned i = 0; i < NumElts; ++i) { + SDNode *Elt = N->getOperand(i).getNode(); + if (ISD::isNormalLoad(Elt) && !cast(Elt)->isVolatile()) + return true; + } + return false; +} + +/// PerformBUILD_VECTORCombine - Target-specific dag combine xforms for +/// ISD::BUILD_VECTOR. +static SDValue PerformBUILD_VECTORCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI){ + // build_vector(N=ARMISD::VMOVRRD(X), N:1) -> bit_convert(X): + // VMOVRRD is introduced when legalizing i64 types. It forces the i64 value + // into a pair of GPRs, which is fine when the value is used as a scalar, + // but if the i64 value is converted to a vector, we need to undo the VMOVRRD. + SelectionDAG &DAG = DCI.DAG; + if (N->getNumOperands() == 2) { + SDValue RV = PerformVMOVDRRCombine(N, DAG); + if (RV.getNode()) + return RV; + } + + // Load i64 elements as f64 values so that type legalization does not split + // them up into i32 values. + EVT VT = N->getValueType(0); + if (VT.getVectorElementType() != MVT::i64 || !hasNormalLoadOperand(N)) + return SDValue(); + DebugLoc dl = N->getDebugLoc(); + SmallVector Ops; + unsigned NumElts = VT.getVectorNumElements(); + for (unsigned i = 0; i < NumElts; ++i) { + SDValue V = DAG.getNode(ISD::BITCAST, dl, MVT::f64, N->getOperand(i)); + Ops.push_back(V); + // Make the DAGCombiner fold the bitcast. + DCI.AddToWorklist(V.getNode()); + } + EVT FloatVT = EVT::getVectorVT(*DAG.getContext(), MVT::f64, NumElts); + SDValue BV = DAG.getNode(ISD::BUILD_VECTOR, dl, FloatVT, Ops.data(), NumElts); + return DAG.getNode(ISD::BITCAST, dl, VT, BV); +} + +/// PerformInsertEltCombine - Target-specific dag combine xforms for +/// ISD::INSERT_VECTOR_ELT. +static SDValue PerformInsertEltCombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + // Bitcast an i64 load inserted into a vector to f64. + // Otherwise, the i64 value will be legalized to a pair of i32 values. + EVT VT = N->getValueType(0); + SDNode *Elt = N->getOperand(1).getNode(); + if (VT.getVectorElementType() != MVT::i64 || + !ISD::isNormalLoad(Elt) || cast(Elt)->isVolatile()) + return SDValue(); + + SelectionDAG &DAG = DCI.DAG; + DebugLoc dl = N->getDebugLoc(); + EVT FloatVT = EVT::getVectorVT(*DAG.getContext(), MVT::f64, + VT.getVectorNumElements()); + SDValue Vec = DAG.getNode(ISD::BITCAST, dl, FloatVT, N->getOperand(0)); + SDValue V = DAG.getNode(ISD::BITCAST, dl, MVT::f64, N->getOperand(1)); + // Make the DAGCombiner fold the bitcasts. + DCI.AddToWorklist(Vec.getNode()); + DCI.AddToWorklist(V.getNode()); + SDValue InsElt = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, FloatVT, + Vec, V, N->getOperand(2)); + return DAG.getNode(ISD::BITCAST, dl, VT, InsElt); +} + +/// PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for +/// ISD::VECTOR_SHUFFLE. +static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG) { + // The LLVM shufflevector instruction does not require the shuffle mask + // length to match the operand vector length, but ISD::VECTOR_SHUFFLE does + // have that requirement. When translating to ISD::VECTOR_SHUFFLE, if the + // operands do not match the mask length, they are extended by concatenating + // them with undef vectors. That is probably the right thing for other + // targets, but for NEON it is better to concatenate two double-register + // size vector operands into a single quad-register size vector. Do that + // transformation here: + // shuffle(concat(v1, undef), concat(v2, undef)) -> + // shuffle(concat(v1, v2), undef) + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + if (Op0.getOpcode() != ISD::CONCAT_VECTORS || + Op1.getOpcode() != ISD::CONCAT_VECTORS || + Op0.getNumOperands() != 2 || + Op1.getNumOperands() != 2) + return SDValue(); + SDValue Concat0Op1 = Op0.getOperand(1); + SDValue Concat1Op1 = Op1.getOperand(1); + if (Concat0Op1.getOpcode() != ISD::UNDEF || + Concat1Op1.getOpcode() != ISD::UNDEF) + return SDValue(); + // Skip the transformation if any of the types are illegal. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT VT = N->getValueType(0); + if (!TLI.isTypeLegal(VT) || + !TLI.isTypeLegal(Concat0Op1.getValueType()) || + !TLI.isTypeLegal(Concat1Op1.getValueType())) + return SDValue(); + + SDValue NewConcat = DAG.getNode(ISD::CONCAT_VECTORS, N->getDebugLoc(), VT, + Op0.getOperand(0), Op1.getOperand(0)); + // Translate the shuffle mask. + SmallVector NewMask; + unsigned NumElts = VT.getVectorNumElements(); + unsigned HalfElts = NumElts/2; + ShuffleVectorSDNode *SVN = cast(N); + for (unsigned n = 0; n < NumElts; ++n) { + int MaskElt = SVN->getMaskElt(n); + int NewElt = -1; + if (MaskElt < (int)HalfElts) + NewElt = MaskElt; + else if (MaskElt >= (int)NumElts && MaskElt < (int)(NumElts + HalfElts)) + NewElt = HalfElts + MaskElt - NumElts; + NewMask.push_back(NewElt); + } + return DAG.getVectorShuffle(VT, N->getDebugLoc(), NewConcat, + DAG.getUNDEF(VT), NewMask.data()); +} + +/// CombineBaseUpdate - Target-specific DAG combine function for VLDDUP and +/// NEON load/store intrinsics to merge base address updates. +static SDValue CombineBaseUpdate(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) + return SDValue(); + + SelectionDAG &DAG = DCI.DAG; + bool isIntrinsic = (N->getOpcode() == ISD::INTRINSIC_VOID || + N->getOpcode() == ISD::INTRINSIC_W_CHAIN); + unsigned AddrOpIdx = (isIntrinsic ? 2 : 1); + SDValue Addr = N->getOperand(AddrOpIdx); + + // Search for a use of the address operand that is an increment. + for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), + UE = Addr.getNode()->use_end(); UI != UE; ++UI) { + SDNode *User = *UI; + if (User->getOpcode() != ISD::ADD || + UI.getUse().getResNo() != Addr.getResNo()) + continue; + + // Check that the add is independent of the load/store. Otherwise, folding + // it would create a cycle. + if (User->isPredecessorOf(N) || N->isPredecessorOf(User)) + continue; + + // Find the new opcode for the updating load/store. + bool isLoad = true; + bool isLaneOp = false; + unsigned NewOpc = 0; + unsigned NumVecs = 0; + if (isIntrinsic) { + unsigned IntNo = cast(N->getOperand(1))->getZExtValue(); + switch (IntNo) { + default: assert(0 && "unexpected intrinsic for Neon base update"); + case Intrinsic::arm_neon_vld1: NewOpc = ARMISD::VLD1_UPD; + NumVecs = 1; break; + case Intrinsic::arm_neon_vld2: NewOpc = ARMISD::VLD2_UPD; + NumVecs = 2; break; + case Intrinsic::arm_neon_vld3: NewOpc = ARMISD::VLD3_UPD; + NumVecs = 3; break; + case Intrinsic::arm_neon_vld4: NewOpc = ARMISD::VLD4_UPD; + NumVecs = 4; break; + case Intrinsic::arm_neon_vld2lane: NewOpc = ARMISD::VLD2LN_UPD; + NumVecs = 2; isLaneOp = true; break; + case Intrinsic::arm_neon_vld3lane: NewOpc = ARMISD::VLD3LN_UPD; + NumVecs = 3; isLaneOp = true; break; + case Intrinsic::arm_neon_vld4lane: NewOpc = ARMISD::VLD4LN_UPD; + NumVecs = 4; isLaneOp = true; break; + case Intrinsic::arm_neon_vst1: NewOpc = ARMISD::VST1_UPD; + NumVecs = 1; isLoad = false; break; + case Intrinsic::arm_neon_vst2: NewOpc = ARMISD::VST2_UPD; + NumVecs = 2; isLoad = false; break; + case Intrinsic::arm_neon_vst3: NewOpc = ARMISD::VST3_UPD; + NumVecs = 3; isLoad = false; break; + case Intrinsic::arm_neon_vst4: NewOpc = ARMISD::VST4_UPD; + NumVecs = 4; isLoad = false; break; + case Intrinsic::arm_neon_vst2lane: NewOpc = ARMISD::VST2LN_UPD; + NumVecs = 2; isLoad = false; isLaneOp = true; break; + case Intrinsic::arm_neon_vst3lane: NewOpc = ARMISD::VST3LN_UPD; + NumVecs = 3; isLoad = false; isLaneOp = true; break; + case Intrinsic::arm_neon_vst4lane: NewOpc = ARMISD::VST4LN_UPD; + NumVecs = 4; isLoad = false; isLaneOp = true; break; + } + } else { + isLaneOp = true; + switch (N->getOpcode()) { + default: assert(0 && "unexpected opcode for Neon base update"); + case ARMISD::VLD2DUP: NewOpc = ARMISD::VLD2DUP_UPD; NumVecs = 2; break; + case ARMISD::VLD3DUP: NewOpc = ARMISD::VLD3DUP_UPD; NumVecs = 3; break; + case ARMISD::VLD4DUP: NewOpc = ARMISD::VLD4DUP_UPD; NumVecs = 4; break; + } + } + + // Find the size of memory referenced by the load/store. + EVT VecTy; + if (isLoad) + VecTy = N->getValueType(0); + else + VecTy = N->getOperand(AddrOpIdx+1).getValueType(); + unsigned NumBytes = NumVecs * VecTy.getSizeInBits() / 8; + if (isLaneOp) + NumBytes /= VecTy.getVectorNumElements(); + + // If the increment is a constant, it must match the memory ref size. + SDValue Inc = User->getOperand(User->getOperand(0) == Addr ? 1 : 0); + if (ConstantSDNode *CInc = dyn_cast(Inc.getNode())) { + uint64_t IncVal = CInc->getZExtValue(); + if (IncVal != NumBytes) + continue; + } else if (NumBytes >= 3 * 16) { + // VLD3/4 and VST3/4 for 128-bit vectors are implemented with two + // separate instructions that make it harder to use a non-constant update. + continue; + } + + // Create the new updating load/store node. + EVT Tys[6]; + unsigned NumResultVecs = (isLoad ? NumVecs : 0); + unsigned n; + for (n = 0; n < NumResultVecs; ++n) + Tys[n] = VecTy; + Tys[n++] = MVT::i32; + Tys[n] = MVT::Other; + SDVTList SDTys = DAG.getVTList(Tys, NumResultVecs+2); + SmallVector Ops; + Ops.push_back(N->getOperand(0)); // incoming chain + Ops.push_back(N->getOperand(AddrOpIdx)); + Ops.push_back(Inc); + for (unsigned i = AddrOpIdx + 1; i < N->getNumOperands(); ++i) { + Ops.push_back(N->getOperand(i)); + } + MemIntrinsicSDNode *MemInt = cast(N); + SDValue UpdN = DAG.getMemIntrinsicNode(NewOpc, N->getDebugLoc(), SDTys, + Ops.data(), Ops.size(), + MemInt->getMemoryVT(), + MemInt->getMemOperand()); + + // Update the uses. + std::vector NewResults; + for (unsigned i = 0; i < NumResultVecs; ++i) { + NewResults.push_back(SDValue(UpdN.getNode(), i)); + } + NewResults.push_back(SDValue(UpdN.getNode(), NumResultVecs+1)); // chain + DCI.CombineTo(N, NewResults); + DCI.CombineTo(User, SDValue(UpdN.getNode(), NumResultVecs)); + + break; + } + return SDValue(); +} + +/// CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a +/// vldN-lane (N > 1) intrinsic, and if all the other uses of that intrinsic +/// are also VDUPLANEs. If so, combine them to a vldN-dup operation and +/// return true. +static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { + SelectionDAG &DAG = DCI.DAG; + EVT VT = N->getValueType(0); + // vldN-dup instructions only support 64-bit vectors for N > 1. + if (!VT.is64BitVector()) + return false; + + // Check if the VDUPLANE operand is a vldN-dup intrinsic. + SDNode *VLD = N->getOperand(0).getNode(); + if (VLD->getOpcode() != ISD::INTRINSIC_W_CHAIN) + return false; + unsigned NumVecs = 0; + unsigned NewOpc = 0; + unsigned IntNo = cast(VLD->getOperand(1))->getZExtValue(); + if (IntNo == Intrinsic::arm_neon_vld2lane) { + NumVecs = 2; + NewOpc = ARMISD::VLD2DUP; + } else if (IntNo == Intrinsic::arm_neon_vld3lane) { + NumVecs = 3; + NewOpc = ARMISD::VLD3DUP; + } else if (IntNo == Intrinsic::arm_neon_vld4lane) { + NumVecs = 4; + NewOpc = ARMISD::VLD4DUP; + } else { + return false; + } + + // First check that all the vldN-lane uses are VDUPLANEs and that the lane + // numbers match the load. + unsigned VLDLaneNo = + cast(VLD->getOperand(NumVecs+3))->getZExtValue(); + for (SDNode::use_iterator UI = VLD->use_begin(), UE = VLD->use_end(); + UI != UE; ++UI) { + // Ignore uses of the chain result. + if (UI.getUse().getResNo() == NumVecs) + continue; + SDNode *User = *UI; + if (User->getOpcode() != ARMISD::VDUPLANE || + VLDLaneNo != cast(User->getOperand(1))->getZExtValue()) + return false; + } + + // Create the vldN-dup node. + EVT Tys[5]; + unsigned n; + for (n = 0; n < NumVecs; ++n) + Tys[n] = VT; + Tys[n] = MVT::Other; + SDVTList SDTys = DAG.getVTList(Tys, NumVecs+1); + SDValue Ops[] = { VLD->getOperand(0), VLD->getOperand(2) }; + MemIntrinsicSDNode *VLDMemInt = cast(VLD); + SDValue VLDDup = DAG.getMemIntrinsicNode(NewOpc, VLD->getDebugLoc(), SDTys, + Ops, 2, VLDMemInt->getMemoryVT(), + VLDMemInt->getMemOperand()); + + // Update the uses. + for (SDNode::use_iterator UI = VLD->use_begin(), UE = VLD->use_end(); + UI != UE; ++UI) { + unsigned ResNo = UI.getUse().getResNo(); + // Ignore uses of the chain result. + if (ResNo == NumVecs) + continue; + SDNode *User = *UI; + DCI.CombineTo(User, SDValue(VLDDup.getNode(), ResNo)); + } + + // Now the vldN-lane intrinsic is dead except for its chain result. + // Update uses of the chain. + std::vector VLDDupResults; + for (unsigned n = 0; n < NumVecs; ++n) + VLDDupResults.push_back(SDValue(VLDDup.getNode(), n)); + VLDDupResults.push_back(SDValue(VLDDup.getNode(), NumVecs)); + DCI.CombineTo(VLD, VLDDupResults); + + return true; +} + +/// PerformVDUPLANECombine - Target-specific dag combine xforms for +/// ARMISD::VDUPLANE. +static SDValue PerformVDUPLANECombine(SDNode *N, + TargetLowering::DAGCombinerInfo &DCI) { + SDValue Op = N->getOperand(0); + + // If the source is a vldN-lane (N > 1) intrinsic, and all the other uses + // of that intrinsic are also VDUPLANEs, combine them to a vldN-dup operation. + if (CombineVLDDUP(N, DCI)) + return SDValue(N, 0); + + // If the source is already a VMOVIMM or VMVNIMM splat, the VDUPLANE is + // redundant. Ignore bit_converts for now; element sizes are checked below. + while (Op.getOpcode() == ISD::BITCAST) + Op = Op.getOperand(0); + if (Op.getOpcode() != ARMISD::VMOVIMM && Op.getOpcode() != ARMISD::VMVNIMM) + return SDValue(); + + // Make sure the VMOV element size is not bigger than the VDUPLANE elements. + unsigned EltSize = Op.getValueType().getVectorElementType().getSizeInBits(); + // The canonical VMOV for a zero vector uses a 32-bit element size. + unsigned Imm = cast(Op.getOperand(0))->getZExtValue(); + unsigned EltBits; + if (ARM_AM::decodeNEONModImm(Imm, EltBits) == 0) + EltSize = 8; + EVT VT = N->getValueType(0); + if (EltSize > VT.getVectorElementType().getSizeInBits()) + return SDValue(); + + return DCI.DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, Op); +} + +/// getVShiftImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift operation, where all the elements of the +/// build_vector must have the same constant integer value. +static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) { + // Ignore bit_converts. + while (Op.getOpcode() == ISD::BITCAST) + Op = Op.getOperand(0); + BuildVectorSDNode *BVN = dyn_cast(Op.getNode()); + APInt SplatBits, SplatUndef; + unsigned SplatBitSize; + bool HasAnyUndefs; + if (! BVN || ! BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, + HasAnyUndefs, ElementBits) || + SplatBitSize > ElementBits) + return false; + Cnt = SplatBits.getSExtValue(); + return true; +} + +/// isVShiftLImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift left operation. That value must be in the range: +/// 0 <= Value < ElementBits for a left shift; or +/// 0 <= Value <= ElementBits for a long left shift. +static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt) { + assert(VT.isVector() && "vector shift count is not a vector type"); + unsigned ElementBits = VT.getVectorElementType().getSizeInBits(); + if (! getVShiftImm(Op, ElementBits, Cnt)) + return false; + return (Cnt >= 0 && (isLong ? Cnt-1 : Cnt) < ElementBits); +} + +/// isVShiftRImm - Check if this is a valid build_vector for the immediate +/// operand of a vector shift right operation. For a shift opcode, the value +/// is positive, but for an intrinsic the value count must be negative. The +/// absolute value must be in the range: +/// 1 <= |Value| <= ElementBits for a right shift; or +/// 1 <= |Value| <= ElementBits/2 for a narrow right shift. +static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, bool isIntrinsic, + int64_t &Cnt) { + assert(VT.isVector() && "vector shift count is not a vector type"); + unsigned ElementBits = VT.getVectorElementType().getSizeInBits(); + if (! getVShiftImm(Op, ElementBits, Cnt)) + return false; + if (isIntrinsic) + Cnt = -Cnt; + return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits/2 : ElementBits)); +} + +/// PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics. +static SDValue PerformIntrinsicCombine(SDNode *N, SelectionDAG &DAG) { + unsigned IntNo = cast(N->getOperand(0))->getZExtValue(); + switch (IntNo) { + default: + // Don't do anything for most intrinsics. + break; + + // Vector shifts: check for immediate versions and lower them. + // Note: This is done during DAG combining instead of DAG legalizing because + // the build_vectors for 64-bit vector element shift counts are generally + // not legal, and it is hard to see their values after they get legalized to + // loads from a constant pool. + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + case Intrinsic::arm_neon_vshiftn: + case Intrinsic::arm_neon_vrshifts: + case Intrinsic::arm_neon_vrshiftu: + case Intrinsic::arm_neon_vrshiftn: + case Intrinsic::arm_neon_vqshifts: + case Intrinsic::arm_neon_vqshiftu: + case Intrinsic::arm_neon_vqshiftsu: + case Intrinsic::arm_neon_vqshiftns: + case Intrinsic::arm_neon_vqshiftnu: + case Intrinsic::arm_neon_vqshiftnsu: + case Intrinsic::arm_neon_vqrshiftns: + case Intrinsic::arm_neon_vqrshiftnu: + case Intrinsic::arm_neon_vqrshiftnsu: { + EVT VT = N->getOperand(1).getValueType(); + int64_t Cnt; + unsigned VShiftOpc = 0; + + switch (IntNo) { + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) { + VShiftOpc = ARMISD::VSHL; + break; + } + if (isVShiftRImm(N->getOperand(2), VT, false, true, Cnt)) { + VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? + ARMISD::VSHRs : ARMISD::VSHRu); + break; + } + return SDValue(); + + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + if (isVShiftLImm(N->getOperand(2), VT, true, Cnt)) + break; + llvm_unreachable("invalid shift count for vshll intrinsic"); + + case Intrinsic::arm_neon_vrshifts: + case Intrinsic::arm_neon_vrshiftu: + if (isVShiftRImm(N->getOperand(2), VT, false, true, Cnt)) + break; + return SDValue(); + + case Intrinsic::arm_neon_vqshifts: + case Intrinsic::arm_neon_vqshiftu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) + break; + return SDValue(); + + case Intrinsic::arm_neon_vqshiftsu: + if (isVShiftLImm(N->getOperand(2), VT, false, Cnt)) + break; + llvm_unreachable("invalid shift count for vqshlu intrinsic"); + + case Intrinsic::arm_neon_vshiftn: + case Intrinsic::arm_neon_vrshiftn: + case Intrinsic::arm_neon_vqshiftns: + case Intrinsic::arm_neon_vqshiftnu: + case Intrinsic::arm_neon_vqshiftnsu: + case Intrinsic::arm_neon_vqrshiftns: + case Intrinsic::arm_neon_vqrshiftnu: + case Intrinsic::arm_neon_vqrshiftnsu: + // Narrowing shifts require an immediate right shift. + if (isVShiftRImm(N->getOperand(2), VT, true, true, Cnt)) + break; + llvm_unreachable("invalid shift count for narrowing vector shift " + "intrinsic"); + + default: + llvm_unreachable("unhandled vector shift"); + } + + switch (IntNo) { + case Intrinsic::arm_neon_vshifts: + case Intrinsic::arm_neon_vshiftu: + // Opcode already set above. + break; + case Intrinsic::arm_neon_vshiftls: + case Intrinsic::arm_neon_vshiftlu: + if (Cnt == VT.getVectorElementType().getSizeInBits()) + VShiftOpc = ARMISD::VSHLLi; + else + VShiftOpc = (IntNo == Intrinsic::arm_neon_vshiftls ? + ARMISD::VSHLLs : ARMISD::VSHLLu); + break; + case Intrinsic::arm_neon_vshiftn: + VShiftOpc = ARMISD::VSHRN; break; + case Intrinsic::arm_neon_vrshifts: + VShiftOpc = ARMISD::VRSHRs; break; + case Intrinsic::arm_neon_vrshiftu: + VShiftOpc = ARMISD::VRSHRu; break; + case Intrinsic::arm_neon_vrshiftn: + VShiftOpc = ARMISD::VRSHRN; break; + case Intrinsic::arm_neon_vqshifts: + VShiftOpc = ARMISD::VQSHLs; break; + case Intrinsic::arm_neon_vqshiftu: + VShiftOpc = ARMISD::VQSHLu; break; + case Intrinsic::arm_neon_vqshiftsu: + VShiftOpc = ARMISD::VQSHLsu; break; + case Intrinsic::arm_neon_vqshiftns: + VShiftOpc = ARMISD::VQSHRNs; break; + case Intrinsic::arm_neon_vqshiftnu: + VShiftOpc = ARMISD::VQSHRNu; break; + case Intrinsic::arm_neon_vqshiftnsu: + VShiftOpc = ARMISD::VQSHRNsu; break; + case Intrinsic::arm_neon_vqrshiftns: + VShiftOpc = ARMISD::VQRSHRNs; break; + case Intrinsic::arm_neon_vqrshiftnu: + VShiftOpc = ARMISD::VQRSHRNu; break; + case Intrinsic::arm_neon_vqrshiftnsu: + VShiftOpc = ARMISD::VQRSHRNsu; break; + } + + return DAG.getNode(VShiftOpc, N->getDebugLoc(), N->getValueType(0), + N->getOperand(1), DAG.getConstant(Cnt, MVT::i32)); + } + + case Intrinsic::arm_neon_vshiftins: { + EVT VT = N->getOperand(1).getValueType(); + int64_t Cnt; + unsigned VShiftOpc = 0; + + if (isVShiftLImm(N->getOperand(3), VT, false, Cnt)) + VShiftOpc = ARMISD::VSLI; + else if (isVShiftRImm(N->getOperand(3), VT, false, true, Cnt)) + VShiftOpc = ARMISD::VSRI; + else { + llvm_unreachable("invalid shift count for vsli/vsri intrinsic"); + } + + return DAG.getNode(VShiftOpc, N->getDebugLoc(), N->getValueType(0), + N->getOperand(1), N->getOperand(2), + DAG.getConstant(Cnt, MVT::i32)); + } + + case Intrinsic::arm_neon_vqrshifts: + case Intrinsic::arm_neon_vqrshiftu: + // No immediate versions of these to check for. + break; + } + + return SDValue(); +} + +/// PerformShiftCombine - Checks for immediate versions of vector shifts and +/// lowers them. As with the vector shift intrinsics, this is done during DAG +/// combining instead of DAG legalizing because the build_vectors for 64-bit +/// vector element shift counts are generally not legal, and it is hard to see +/// their values after they get legalized to loads from a constant pool. +static SDValue PerformShiftCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + EVT VT = N->getValueType(0); + + // Nothing to be done for scalar shifts. + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (!VT.isVector() || !TLI.isTypeLegal(VT)) + return SDValue(); + + assert(ST->hasNEON() && "unexpected vector shift"); + int64_t Cnt; + + switch (N->getOpcode()) { + default: llvm_unreachable("unexpected shift opcode"); + + case ISD::SHL: + if (isVShiftLImm(N->getOperand(1), VT, false, Cnt)) + return DAG.getNode(ARMISD::VSHL, N->getDebugLoc(), VT, N->getOperand(0), + DAG.getConstant(Cnt, MVT::i32)); + break; + + case ISD::SRA: + case ISD::SRL: + if (isVShiftRImm(N->getOperand(1), VT, false, false, Cnt)) { + unsigned VShiftOpc = (N->getOpcode() == ISD::SRA ? + ARMISD::VSHRs : ARMISD::VSHRu); + return DAG.getNode(VShiftOpc, N->getDebugLoc(), VT, N->getOperand(0), + DAG.getConstant(Cnt, MVT::i32)); + } + } + return SDValue(); +} + +/// PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, +/// ISD::ZERO_EXTEND, and ISD::ANY_EXTEND. +static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + SDValue N0 = N->getOperand(0); + + // Check for sign- and zero-extensions of vector extract operations of 8- + // and 16-bit vector elements. NEON supports these directly. They are + // handled during DAG combining because type legalization will promote them + // to 32-bit types and it is messy to recognize the operations after that. + if (ST->hasNEON() && N0.getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + SDValue Vec = N0.getOperand(0); + SDValue Lane = N0.getOperand(1); + EVT VT = N->getValueType(0); + EVT EltVT = N0.getValueType(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + + if (VT == MVT::i32 && + (EltVT == MVT::i8 || EltVT == MVT::i16) && + TLI.isTypeLegal(Vec.getValueType()) && + isa(Lane)) { + + unsigned Opc = 0; + switch (N->getOpcode()) { + default: llvm_unreachable("unexpected opcode"); + case ISD::SIGN_EXTEND: + Opc = ARMISD::VGETLANEs; + break; + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: + Opc = ARMISD::VGETLANEu; + break; + } + return DAG.getNode(Opc, N->getDebugLoc(), VT, Vec, Lane); + } + } + + return SDValue(); +} + +/// PerformSELECT_CCCombine - Target-specific DAG combining for ISD::SELECT_CC +/// to match f32 max/min patterns to use NEON vmax/vmin instructions. +static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + // If the target supports NEON, try to use vmax/vmin instructions for f32 + // selects like "x < y ? x : y". Unless the NoNaNsFPMath option is set, + // be careful about NaNs: NEON's vmax/vmin return NaN if either operand is + // a NaN; only do the transformation when it matches that behavior. + + // For now only do this when using NEON for FP operations; if using VFP, it + // is not obvious that the benefit outweighs the cost of switching to the + // NEON pipeline. + if (!ST->hasNEON() || !ST->useNEONForSinglePrecisionFP() || + N->getValueType(0) != MVT::f32) + return SDValue(); + + SDValue CondLHS = N->getOperand(0); + SDValue CondRHS = N->getOperand(1); + SDValue LHS = N->getOperand(2); + SDValue RHS = N->getOperand(3); + ISD::CondCode CC = cast(N->getOperand(4))->get(); + + unsigned Opcode = 0; + bool IsReversed; + if (DAG.isEqualTo(LHS, CondLHS) && DAG.isEqualTo(RHS, CondRHS)) { + IsReversed = false; // x CC y ? x : y + } else if (DAG.isEqualTo(LHS, CondRHS) && DAG.isEqualTo(RHS, CondLHS)) { + IsReversed = true ; // x CC y ? y : x + } else { + return SDValue(); + } + + bool IsUnordered; + switch (CC) { + default: break; + case ISD::SETOLT: + case ISD::SETOLE: + case ISD::SETLT: + case ISD::SETLE: + case ISD::SETULT: + case ISD::SETULE: + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmin(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETULT || CC == ISD::SETULE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For less-than-or-equal comparisons, "+0 <= -0" will be true but vmin + // will return -0, so vmin can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN; + break; + + case ISD::SETOGT: + case ISD::SETOGE: + case ISD::SETGT: + case ISD::SETGE: + case ISD::SETUGT: + case ISD::SETUGE: + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmax(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETUGT || CC == ISD::SETUGE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For greater-than-or-equal comparisons, "-0 >= +0" will be true but vmax + // will return +0, so vmax can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX; + break; + } + + if (!Opcode) + return SDValue(); + return DAG.getNode(Opcode, N->getDebugLoc(), N->getValueType(0), LHS, RHS); +} + +SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + switch (N->getOpcode()) { + default: break; + case ISD::ADD: return PerformADDCombine(N, DCI); + case ISD::SUB: return PerformSUBCombine(N, DCI); + case ISD::MUL: return PerformMULCombine(N, DCI, Subtarget); + case ISD::OR: return PerformORCombine(N, DCI, Subtarget); + case ISD::AND: return PerformANDCombine(N, DCI); + case ARMISD::BFI: return PerformBFICombine(N, DCI); + case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI); + case ARMISD::VMOVDRR: return PerformVMOVDRRCombine(N, DCI.DAG); + case ISD::STORE: return PerformSTORECombine(N, DCI); + case ISD::BUILD_VECTOR: return PerformBUILD_VECTORCombine(N, DCI); + case ISD::INSERT_VECTOR_ELT: return PerformInsertEltCombine(N, DCI); + case ISD::VECTOR_SHUFFLE: return PerformVECTOR_SHUFFLECombine(N, DCI.DAG); + case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI); + case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG); + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: return PerformShiftCombine(N, DCI.DAG, Subtarget); + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: return PerformExtendCombine(N, DCI.DAG, Subtarget); + case ISD::SELECT_CC: return PerformSELECT_CCCombine(N, DCI.DAG, Subtarget); + case ARMISD::VLD2DUP: + case ARMISD::VLD3DUP: + case ARMISD::VLD4DUP: + return CombineBaseUpdate(N, DCI); + case ISD::INTRINSIC_VOID: + case ISD::INTRINSIC_W_CHAIN: + switch (cast(N->getOperand(1))->getZExtValue()) { + case Intrinsic::arm_neon_vld1: + case Intrinsic::arm_neon_vld2: + case Intrinsic::arm_neon_vld3: + case Intrinsic::arm_neon_vld4: + case Intrinsic::arm_neon_vld2lane: + case Intrinsic::arm_neon_vld3lane: + case Intrinsic::arm_neon_vld4lane: + case Intrinsic::arm_neon_vst1: + case Intrinsic::arm_neon_vst2: + case Intrinsic::arm_neon_vst3: + case Intrinsic::arm_neon_vst4: + case Intrinsic::arm_neon_vst2lane: + case Intrinsic::arm_neon_vst3lane: + case Intrinsic::arm_neon_vst4lane: + return CombineBaseUpdate(N, DCI); + default: break; + } + break; + } + return SDValue(); +} + +bool ARMTargetLowering::isDesirableToTransformToIntegerOp(unsigned Opc, + EVT VT) const { + return (VT == MVT::f32) && (Opc == ISD::LOAD || Opc == ISD::STORE); +} + +bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { + if (!Subtarget->allowsUnalignedMem()) + return false; + + switch (VT.getSimpleVT().SimpleTy) { + default: + return false; + case MVT::i8: + case MVT::i16: + case MVT::i32: + return true; + // FIXME: VLD1 etc with standard alignment is legal. + } +} + +static bool isLegalT1AddressImmediate(int64_t V, EVT VT) { + if (V < 0) + return false; + + unsigned Scale = 1; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + // Scale == 1; + break; + case MVT::i16: + // Scale == 2; + Scale = 2; + break; + case MVT::i32: + // Scale == 4; + Scale = 4; + break; + } + + if ((V & (Scale - 1)) != 0) + return false; + V /= Scale; + return V == (V & ((1LL << 5) - 1)); +} + +static bool isLegalT2AddressImmediate(int64_t V, EVT VT, + const ARMSubtarget *Subtarget) { + bool isNeg = false; + if (V < 0) { + isNeg = true; + V = - V; + } + + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + // + imm12 or - imm8 + if (isNeg) + return V == (V & ((1LL << 8) - 1)); + return V == (V & ((1LL << 12) - 1)); + case MVT::f32: + case MVT::f64: + // Same as ARM mode. FIXME: NEON? + if (!Subtarget->hasVFP2()) + return false; + if ((V & 3) != 0) + return false; + V >>= 2; + return V == (V & ((1LL << 8) - 1)); + } +} + +/// isLegalAddressImmediate - Return true if the integer value can be used +/// as the offset of the target addressing mode for load / store of the +/// given type. +static bool isLegalAddressImmediate(int64_t V, EVT VT, + const ARMSubtarget *Subtarget) { + if (V == 0) + return true; + + if (!VT.isSimple()) + return false; + + if (Subtarget->isThumb1Only()) + return isLegalT1AddressImmediate(V, VT); + else if (Subtarget->isThumb2()) + return isLegalT2AddressImmediate(V, VT, Subtarget); + + // ARM mode. + if (V < 0) + V = - V; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + // +- imm12 + return V == (V & ((1LL << 12) - 1)); + case MVT::i16: + // +- imm8 + return V == (V & ((1LL << 8) - 1)); + case MVT::f32: + case MVT::f64: + if (!Subtarget->hasVFP2()) // FIXME: NEON? + return false; + if ((V & 3) != 0) + return false; + V >>= 2; + return V == (V & ((1LL << 8) - 1)); + } +} + +bool ARMTargetLowering::isLegalT2ScaledAddressingMode(const AddrMode &AM, + EVT VT) const { + int Scale = AM.Scale; + if (Scale < 0) + return false; + + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i16: + case MVT::i32: + if (Scale == 1) + return true; + // r + r << imm + Scale = Scale & ~1; + return Scale == 2 || Scale == 4 || Scale == 8; + case MVT::i64: + // r + r + if (((unsigned)AM.HasBaseReg + Scale) <= 2) + return true; + return false; + case MVT::isVoid: + // Note, we allow "void" uses (basically, uses that aren't loads or + // stores), because arm allows folding a scale into many arithmetic + // operations. This should be made more precise and revisited later. + + // Allow r << imm, but the imm has to be a multiple of two. + if (Scale & 1) return false; + return isPowerOf2_32(Scale); + } +} + +/// isLegalAddressingMode - Return true if the addressing mode represented +/// by AM is legal for this target, for a load/store of the specified type. +bool ARMTargetLowering::isLegalAddressingMode(const AddrMode &AM, + const Type *Ty) const { + EVT VT = getValueType(Ty, true); + if (!isLegalAddressImmediate(AM.BaseOffs, VT, Subtarget)) + return false; + + // Can never fold addr of global into load/store. + if (AM.BaseGV) + return false; + + switch (AM.Scale) { + case 0: // no scale reg, must be "r+i" or "r", or "i". + break; + case 1: + if (Subtarget->isThumb1Only()) + return false; + // FALL THROUGH. + default: + // ARM doesn't support any R+R*scale+imm addr modes. + if (AM.BaseOffs) + return false; + + if (!VT.isSimple()) + return false; + + if (Subtarget->isThumb2()) + return isLegalT2ScaledAddressingMode(AM, VT); + + int Scale = AM.Scale; + switch (VT.getSimpleVT().SimpleTy) { + default: return false; + case MVT::i1: + case MVT::i8: + case MVT::i32: + if (Scale < 0) Scale = -Scale; + if (Scale == 1) + return true; + // r + r << imm + return isPowerOf2_32(Scale & ~1); + case MVT::i16: + case MVT::i64: + // r + r + if (((unsigned)AM.HasBaseReg + Scale) <= 2) + return true; + return false; + + case MVT::isVoid: + // Note, we allow "void" uses (basically, uses that aren't loads or + // stores), because arm allows folding a scale into many arithmetic + // operations. This should be made more precise and revisited later. + + // Allow r << imm, but the imm has to be a multiple of two. + if (Scale & 1) return false; + return isPowerOf2_32(Scale); + } + break; + } + return true; +} + +/// isLegalICmpImmediate - Return true if the specified immediate is legal +/// icmp immediate, that is the target has icmp instructions which can compare +/// a register against the immediate without having to materialize the +/// immediate into a register. +bool ARMTargetLowering::isLegalICmpImmediate(int64_t Imm) const { + if (!Subtarget->isThumb()) + return ARM_AM::getSOImmVal(Imm) != -1; + if (Subtarget->isThumb2()) + return ARM_AM::getT2SOImmVal(Imm) != -1; + return Imm >= 0 && Imm <= 255; +} + +static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, + bool isSEXTLoad, SDValue &Base, + SDValue &Offset, bool &isInc, + SelectionDAG &DAG) { + if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB) + return false; + + if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) { + // AddressingMode 3 + Base = Ptr->getOperand(0); + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -256) { + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + return true; + } + } + isInc = (Ptr->getOpcode() == ISD::ADD); + Offset = Ptr->getOperand(1); + return true; + } else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) { + // AddressingMode 2 + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -0x1000) { + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + Base = Ptr->getOperand(0); + return true; + } + } + + if (Ptr->getOpcode() == ISD::ADD) { + isInc = true; + ARM_AM::ShiftOpc ShOpcVal= ARM_AM::getShiftOpcForNode(Ptr->getOperand(0)); + if (ShOpcVal != ARM_AM::no_shift) { + Base = Ptr->getOperand(1); + Offset = Ptr->getOperand(0); + } else { + Base = Ptr->getOperand(0); + Offset = Ptr->getOperand(1); + } + return true; + } + + isInc = (Ptr->getOpcode() == ISD::ADD); + Base = Ptr->getOperand(0); + Offset = Ptr->getOperand(1); + return true; + } + + // FIXME: Use VLDM / VSTM to emulate indexed FP load / store. + return false; +} + +static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, + bool isSEXTLoad, SDValue &Base, + SDValue &Offset, bool &isInc, + SelectionDAG &DAG) { + if (Ptr->getOpcode() != ISD::ADD && Ptr->getOpcode() != ISD::SUB) + return false; + + Base = Ptr->getOperand(0); + if (ConstantSDNode *RHS = dyn_cast(Ptr->getOperand(1))) { + int RHSC = (int)RHS->getZExtValue(); + if (RHSC < 0 && RHSC > -0x100) { // 8 bits. + assert(Ptr->getOpcode() == ISD::ADD); + isInc = false; + Offset = DAG.getConstant(-RHSC, RHS->getValueType(0)); + return true; + } else if (RHSC > 0 && RHSC < 0x100) { // 8 bit, no zero. + isInc = Ptr->getOpcode() == ISD::ADD; + Offset = DAG.getConstant(RHSC, RHS->getValueType(0)); + return true; + } + } + + return false; +} + +/// getPreIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if the node's address +/// can be legally represented as pre-indexed load / store address. +bool +ARMTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + if (Subtarget->isThumb1Only()) + return false; + + EVT VT; + SDValue Ptr; + bool isSEXTLoad = false; + if (LoadSDNode *LD = dyn_cast(N)) { + Ptr = LD->getBasePtr(); + VT = LD->getMemoryVT(); + isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; + } else if (StoreSDNode *ST = dyn_cast(N)) { + Ptr = ST->getBasePtr(); + VT = ST->getMemoryVT(); + } else + return false; + + bool isInc; + bool isLegal = false; + if (Subtarget->isThumb2()) + isLegal = getT2IndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base, + Offset, isInc, DAG); + else + isLegal = getARMIndexedAddressParts(Ptr.getNode(), VT, isSEXTLoad, Base, + Offset, isInc, DAG); + if (!isLegal) + return false; + + AM = isInc ? ISD::PRE_INC : ISD::PRE_DEC; + return true; +} + +/// getPostIndexedAddressParts - returns true by value, base pointer and +/// offset pointer and addressing mode by reference if this node can be +/// combined with a load / store to form a post-indexed load / store. +bool ARMTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const { + if (Subtarget->isThumb1Only()) + return false; + + EVT VT; + SDValue Ptr; + bool isSEXTLoad = false; + if (LoadSDNode *LD = dyn_cast(N)) { + VT = LD->getMemoryVT(); + Ptr = LD->getBasePtr(); + isSEXTLoad = LD->getExtensionType() == ISD::SEXTLOAD; + } else if (StoreSDNode *ST = dyn_cast(N)) { + VT = ST->getMemoryVT(); + Ptr = ST->getBasePtr(); + } else + return false; + + bool isInc; + bool isLegal = false; + if (Subtarget->isThumb2()) + isLegal = getT2IndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, + isInc, DAG); + else + isLegal = getARMIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset, + isInc, DAG); + if (!isLegal) + return false; + + if (Ptr != Base) { + // Swap base ptr and offset to catch more post-index load / store when + // it's legal. In Thumb2 mode, offset must be an immediate. + if (Ptr == Offset && Op->getOpcode() == ISD::ADD && + !Subtarget->isThumb2()) + std::swap(Base, Offset); + + // Post-indexed load / store update the base pointer. + if (Ptr != Base) + return false; + } + + AM = isInc ? ISD::POST_INC : ISD::POST_DEC; + return true; +} + +void ARMTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const { + KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); + switch (Op.getOpcode()) { + default: break; + case ARMISD::CMOV: { + // Bits are known zero/one if known on the LHS and RHS. + DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero, KnownOne, Depth+1); + if (KnownZero == 0 && KnownOne == 0) return; + + APInt KnownZeroRHS, KnownOneRHS; + DAG.ComputeMaskedBits(Op.getOperand(1), Mask, + KnownZeroRHS, KnownOneRHS, Depth+1); + KnownZero &= KnownZeroRHS; + KnownOne &= KnownOneRHS; + return; + } + } +} + +//===----------------------------------------------------------------------===// +// ARM Inline Assembly Support +//===----------------------------------------------------------------------===// + +bool ARMTargetLowering::ExpandInlineAsm(CallInst *CI) const { + // Looking for "rev" which is V6+. + if (!Subtarget->hasV6Ops()) + return false; + + InlineAsm *IA = cast(CI->getCalledValue()); + std::string AsmStr = IA->getAsmString(); + SmallVector AsmPieces; + SplitString(AsmStr, AsmPieces, ";\n"); + + switch (AsmPieces.size()) { + default: return false; + case 1: + AsmStr = AsmPieces[0]; + AsmPieces.clear(); + SplitString(AsmStr, AsmPieces, " \t,"); + + // rev $0, $1 + if (AsmPieces.size() == 3 && + AsmPieces[0] == "rev" && AsmPieces[1] == "$0" && AsmPieces[2] == "$1" && + IA->getConstraintString().compare(0, 4, "=l,l") == 0) { + const IntegerType *Ty = dyn_cast(CI->getType()); + if (Ty && Ty->getBitWidth() == 32) + return IntrinsicLowering::LowerToByteSwap(CI); + } + break; + } + + return false; +} + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +ARMTargetLowering::ConstraintType +ARMTargetLowering::getConstraintType(const std::string &Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: break; + case 'l': return C_RegisterClass; + case 'w': return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +/// Examine constraint type and operand type and determine a weight value. +/// This object must already have been set up with the operand type +/// and the current alternative constraint selected. +TargetLowering::ConstraintWeight +ARMTargetLowering::getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const { + ConstraintWeight weight = CW_Invalid; + Value *CallOperandVal = info.CallOperandVal; + // If we don't have a value, we can't do a match, + // but allow it at the lowest weight. + if (CallOperandVal == NULL) + return CW_Default; + const Type *type = CallOperandVal->getType(); + // Look at the constraint type. + switch (*constraint) { + default: + weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); + break; + case 'l': + if (type->isIntegerTy()) { + if (Subtarget->isThumb()) + weight = CW_SpecificReg; + else + weight = CW_Register; + } + break; + case 'w': + if (type->isFloatingPointTy()) + weight = CW_Register; + break; + } + return weight; +} + +std::pair +ARMTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() == 1) { + // GCC ARM Constraint Letters + switch (Constraint[0]) { + case 'l': + if (Subtarget->isThumb()) + return std::make_pair(0U, ARM::tGPRRegisterClass); + else + return std::make_pair(0U, ARM::GPRRegisterClass); + case 'r': + return std::make_pair(0U, ARM::GPRRegisterClass); + case 'w': + if (VT == MVT::f32) + return std::make_pair(0U, ARM::SPRRegisterClass); + if (VT.getSizeInBits() == 64) + return std::make_pair(0U, ARM::DPRRegisterClass); + if (VT.getSizeInBits() == 128) + return std::make_pair(0U, ARM::QPRRegisterClass); + break; + } + } + if (StringRef("{cc}").equals_lower(Constraint)) + return std::make_pair(unsigned(ARM::CPSR), ARM::CCRRegisterClass); + + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +std::vector ARMTargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const { + if (Constraint.size() != 1) + return std::vector(); + + switch (Constraint[0]) { // GCC ARM Constraint Letters + default: break; + case 'l': + return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + 0); + case 'r': + return make_vector(ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R9, ARM::R10, ARM::R11, + ARM::R12, ARM::LR, 0); + case 'w': + if (VT == MVT::f32) + return make_vector(ARM::S0, ARM::S1, ARM::S2, ARM::S3, + ARM::S4, ARM::S5, ARM::S6, ARM::S7, + ARM::S8, ARM::S9, ARM::S10, ARM::S11, + ARM::S12,ARM::S13,ARM::S14,ARM::S15, + ARM::S16,ARM::S17,ARM::S18,ARM::S19, + ARM::S20,ARM::S21,ARM::S22,ARM::S23, + ARM::S24,ARM::S25,ARM::S26,ARM::S27, + ARM::S28,ARM::S29,ARM::S30,ARM::S31, 0); + if (VT.getSizeInBits() == 64) + return make_vector(ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10,ARM::D11, + ARM::D12,ARM::D13,ARM::D14,ARM::D15, 0); + if (VT.getSizeInBits() == 128) + return make_vector(ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, + ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7, 0); + break; + } + + return std::vector(); +} + +/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops +/// vector. If it is invalid, don't add anything to Ops. +void ARMTargetLowering::LowerAsmOperandForConstraint(SDValue Op, + char Constraint, + std::vector&Ops, + SelectionDAG &DAG) const { + SDValue Result(0, 0); + + switch (Constraint) { + default: break; + case 'I': case 'J': case 'K': case 'L': + case 'M': case 'N': case 'O': + ConstantSDNode *C = dyn_cast(Op); + if (!C) + return; + + int64_t CVal64 = C->getSExtValue(); + int CVal = (int) CVal64; + // None of these constraints allow values larger than 32 bits. Check + // that the value fits in an int. + if (CVal != CVal64) + return; + + switch (Constraint) { + case 'I': + if (Subtarget->isThumb1Only()) { + // This must be a constant between 0 and 255, for ADD + // immediates. + if (CVal >= 0 && CVal <= 255) + break; + } else if (Subtarget->isThumb2()) { + // A constant that can be used as an immediate value in a + // data-processing instruction. + if (ARM_AM::getT2SOImmVal(CVal) != -1) + break; + } else { + // A constant that can be used as an immediate value in a + // data-processing instruction. + if (ARM_AM::getSOImmVal(CVal) != -1) + break; + } + return; + + case 'J': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a constant between -255 and -1, for negated ADD + // immediates. This can be used in GCC with an "n" modifier that + // prints the negated value, for use with SUB instructions. It is + // not useful otherwise but is implemented for compatibility. + if (CVal >= -255 && CVal <= -1) + break; + } else { + // This must be a constant between -4095 and 4095. It is not clear + // what this constraint is intended for. Implemented for + // compatibility with GCC. + if (CVal >= -4095 && CVal <= 4095) + break; + } + return; + + case 'K': + if (Subtarget->isThumb1Only()) { + // A 32-bit value where only one byte has a nonzero value. Exclude + // zero to match GCC. This constraint is used by GCC internally for + // constants that can be loaded with a move/shift combination. + // It is not useful otherwise but is implemented for compatibility. + if (CVal != 0 && ARM_AM::isThumbImmShiftedVal(CVal)) + break; + } else if (Subtarget->isThumb2()) { + // A constant whose bitwise inverse can be used as an immediate + // value in a data-processing instruction. This can be used in GCC + // with a "B" modifier that prints the inverted value, for use with + // BIC and MVN instructions. It is not useful otherwise but is + // implemented for compatibility. + if (ARM_AM::getT2SOImmVal(~CVal) != -1) + break; + } else { + // A constant whose bitwise inverse can be used as an immediate + // value in a data-processing instruction. This can be used in GCC + // with a "B" modifier that prints the inverted value, for use with + // BIC and MVN instructions. It is not useful otherwise but is + // implemented for compatibility. + if (ARM_AM::getSOImmVal(~CVal) != -1) + break; + } + return; + + case 'L': + if (Subtarget->isThumb1Only()) { + // This must be a constant between -7 and 7, + // for 3-operand ADD/SUB immediate instructions. + if (CVal >= -7 && CVal < 7) + break; + } else if (Subtarget->isThumb2()) { + // A constant whose negation can be used as an immediate value in a + // data-processing instruction. This can be used in GCC with an "n" + // modifier that prints the negated value, for use with SUB + // instructions. It is not useful otherwise but is implemented for + // compatibility. + if (ARM_AM::getT2SOImmVal(-CVal) != -1) + break; + } else { + // A constant whose negation can be used as an immediate value in a + // data-processing instruction. This can be used in GCC with an "n" + // modifier that prints the negated value, for use with SUB + // instructions. It is not useful otherwise but is implemented for + // compatibility. + if (ARM_AM::getSOImmVal(-CVal) != -1) + break; + } + return; + + case 'M': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a multiple of 4 between 0 and 1020, for + // ADD sp + immediate. + if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0)) + break; + } else { + // A power of two or a constant between 0 and 32. This is used in + // GCC for the shift amount on shifted register operands, but it is + // useful in general for any shift amounts. + if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0)) + break; + } + return; + + case 'N': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a constant between 0 and 31, for shift amounts. + if (CVal >= 0 && CVal <= 31) + break; + } + return; + + case 'O': + if (Subtarget->isThumb()) { // FIXME thumb2 + // This must be a multiple of 4 between -508 and 508, for + // ADD/SUB sp = sp + immediate. + if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0)) + break; + } + return; + } + Result = DAG.getTargetConstant(CVal, Op.getValueType()); + break; + } + + if (Result.getNode()) { + Ops.push_back(Result); + return; + } + return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); +} + +bool +ARMTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The ARM target isn't yet aware of offsets. + return false; +} + +int ARM::getVFPf32Imm(const APFloat &FPImm) { + APInt Imm = FPImm.bitcastToAPInt(); + uint32_t Sign = Imm.lshr(31).getZExtValue() & 1; + int32_t Exp = (Imm.lshr(23).getSExtValue() & 0xff) - 127; // -126 to 127 + int64_t Mantissa = Imm.getZExtValue() & 0x7fffff; // 23 bits + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0x7ffff) + return -1; + Mantissa >>= 19; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; +} + +int ARM::getVFPf64Imm(const APFloat &FPImm) { + APInt Imm = FPImm.bitcastToAPInt(); + uint64_t Sign = Imm.lshr(63).getZExtValue() & 1; + int64_t Exp = (Imm.lshr(52).getSExtValue() & 0x7ff) - 1023; // -1022 to 1023 + uint64_t Mantissa = Imm.getZExtValue() & 0xfffffffffffffLL; + + // We can handle 4 bits of mantissa. + // mantissa = (16+UInt(e:f:g:h))/16. + if (Mantissa & 0xffffffffffffLL) + return -1; + Mantissa >>= 48; + if ((Mantissa & 0xf) != Mantissa) + return -1; + + // We can handle 3 bits of exponent: exp == UInt(NOT(b):c:d)-3 + if (Exp < -3 || Exp > 4) + return -1; + Exp = ((Exp+3) & 0x7) ^ 4; + + return ((int)Sign << 7) | (Exp << 4) | Mantissa; +} + +bool ARM::isBitFieldInvertedMask(unsigned v) { + if (v == 0xffffffff) + return 0; + // there can be 1's on either or both "outsides", all the "inside" + // bits must be 0's + unsigned int lsb = 0, msb = 31; + while (v & (1 << msb)) --msb; + while (v & (1 << lsb)) ++lsb; + for (unsigned int i = lsb; i <= msb; ++i) { + if (v & (1 << i)) + return 0; + } + return 1; +} + +/// isFPImmLegal - Returns true if the target can instruction select the +/// specified FP immediate natively. If false, the legalizer will +/// materialize the FP immediate as a load from a constant pool. +bool ARMTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { + if (!Subtarget->hasVFP3()) + return false; + if (VT == MVT::f32) + return ARM::getVFPf32Imm(Imm) != -1; + if (VT == MVT::f64) + return ARM::getVFPf64Imm(Imm) != -1; + return false; +} + +/// getTgtMemIntrinsic - Represent NEON load and store intrinsics as +/// MemIntrinsicNodes. The associated MachineMemOperands record the alignment +/// specified in the intrinsic calls. +bool ARMTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, + const CallInst &I, + unsigned Intrinsic) const { + switch (Intrinsic) { + case Intrinsic::arm_neon_vld1: + case Intrinsic::arm_neon_vld2: + case Intrinsic::arm_neon_vld3: + case Intrinsic::arm_neon_vld4: + case Intrinsic::arm_neon_vld2lane: + case Intrinsic::arm_neon_vld3lane: + case Intrinsic::arm_neon_vld4lane: { + Info.opc = ISD::INTRINSIC_W_CHAIN; + // Conservatively set memVT to the entire set of vectors loaded. + uint64_t NumElts = getTargetData()->getTypeAllocSize(I.getType()) / 8; + Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts); + Info.ptrVal = I.getArgOperand(0); + Info.offset = 0; + Value *AlignArg = I.getArgOperand(I.getNumArgOperands() - 1); + Info.align = cast(AlignArg)->getZExtValue(); + Info.vol = false; // volatile loads with NEON intrinsics not supported + Info.readMem = true; + Info.writeMem = false; + return true; + } + case Intrinsic::arm_neon_vst1: + case Intrinsic::arm_neon_vst2: + case Intrinsic::arm_neon_vst3: + case Intrinsic::arm_neon_vst4: + case Intrinsic::arm_neon_vst2lane: + case Intrinsic::arm_neon_vst3lane: + case Intrinsic::arm_neon_vst4lane: { + Info.opc = ISD::INTRINSIC_VOID; + // Conservatively set memVT to the entire set of vectors stored. + unsigned NumElts = 0; + for (unsigned ArgI = 1, ArgE = I.getNumArgOperands(); ArgI < ArgE; ++ArgI) { + const Type *ArgTy = I.getArgOperand(ArgI)->getType(); + if (!ArgTy->isVectorTy()) + break; + NumElts += getTargetData()->getTypeAllocSize(ArgTy) / 8; + } + Info.memVT = EVT::getVectorVT(I.getType()->getContext(), MVT::i64, NumElts); + Info.ptrVal = I.getArgOperand(0); + Info.offset = 0; + Value *AlignArg = I.getArgOperand(I.getNumArgOperands() - 1); + Info.align = cast(AlignArg)->getZExtValue(); + Info.vol = false; // volatile stores with NEON intrinsics not supported + Info.readMem = false; + Info.writeMem = true; + return true; + } + default: + break; + } + + return false; +} diff --git a/final/lib/Target/ARM/ARMISelLowering.h b/final/lib/Target/ARM/ARMISelLowering.h new file mode 100644 index 00000000000..9ab2bdbf86c --- /dev/null +++ b/final/lib/Target/ARM/ARMISelLowering.h @@ -0,0 +1,490 @@ +//===-- ARMISelLowering.h - ARM DAG Lowering Interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that ARM uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMISELLOWERING_H +#define ARMISELLOWERING_H + +#include "ARMSubtarget.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include + +namespace llvm { + class ARMConstantPoolValue; + + namespace ARMISD { + // ARM Specific DAG Nodes + enum NodeType { + // Start the numbering where the builtin ops and target ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + Wrapper, // Wrapper - A wrapper node for TargetConstantPool, + // TargetExternalSymbol, and TargetGlobalAddress. + WrapperDYN, // WrapperDYN - A wrapper node for TargetGlobalAddress in + // DYN mode. + WrapperPIC, // WrapperPIC - A wrapper node for TargetGlobalAddress in + // PIC mode. + WrapperJT, // WrapperJT - A wrapper node for TargetJumpTable + + CALL, // Function call. + CALL_PRED, // Function call that's predicable. + CALL_NOLINK, // Function call with branch not branch-and-link. + tCALL, // Thumb function call. + BRCOND, // Conditional branch. + BR_JT, // Jumptable branch. + BR2_JT, // Jumptable branch (2 level - jumptable entry is a jump). + RET_FLAG, // Return with a flag operand. + + PIC_ADD, // Add with a PC operand and a PIC label. + + CMP, // ARM compare instructions. + CMPZ, // ARM compare that sets only Z flag. + CMPFP, // ARM VFP compare instruction, sets FPSCR. + CMPFPw0, // ARM VFP compare against zero instruction, sets FPSCR. + FMSTAT, // ARM fmstat instruction. + CMOV, // ARM conditional move instructions. + + BCC_i64, + + RBIT, // ARM bitreverse instruction + + FTOSI, // FP to sint within a FP register. + FTOUI, // FP to uint within a FP register. + SITOF, // sint to FP within a FP register. + UITOF, // uint to FP within a FP register. + + SRL_FLAG, // V,Flag = srl_flag X -> srl X, 1 + save carry out. + SRA_FLAG, // V,Flag = sra_flag X -> sra X, 1 + save carry out. + RRX, // V = RRX X, Flag -> srl X, 1 + shift in carry flag. + + VMOVRRD, // double to two gprs. + VMOVDRR, // Two gprs to double. + + EH_SJLJ_SETJMP, // SjLj exception handling setjmp. + EH_SJLJ_LONGJMP, // SjLj exception handling longjmp. + EH_SJLJ_DISPATCHSETUP, // SjLj exception handling dispatch setup. + + TC_RETURN, // Tail call return pseudo. + + THREAD_POINTER, + + DYN_ALLOC, // Dynamic allocation on the stack. + + MEMBARRIER, // Memory barrier (DMB) + MEMBARRIER_MCR, // Memory barrier (MCR) + + PRELOAD, // Preload + + VCEQ, // Vector compare equal. + VCEQZ, // Vector compare equal to zero. + VCGE, // Vector compare greater than or equal. + VCGEZ, // Vector compare greater than or equal to zero. + VCLEZ, // Vector compare less than or equal to zero. + VCGEU, // Vector compare unsigned greater than or equal. + VCGT, // Vector compare greater than. + VCGTZ, // Vector compare greater than zero. + VCLTZ, // Vector compare less than zero. + VCGTU, // Vector compare unsigned greater than. + VTST, // Vector test bits. + + // Vector shift by immediate: + VSHL, // ...left + VSHRs, // ...right (signed) + VSHRu, // ...right (unsigned) + VSHLLs, // ...left long (signed) + VSHLLu, // ...left long (unsigned) + VSHLLi, // ...left long (with maximum shift count) + VSHRN, // ...right narrow + + // Vector rounding shift by immediate: + VRSHRs, // ...right (signed) + VRSHRu, // ...right (unsigned) + VRSHRN, // ...right narrow + + // Vector saturating shift by immediate: + VQSHLs, // ...left (signed) + VQSHLu, // ...left (unsigned) + VQSHLsu, // ...left (signed to unsigned) + VQSHRNs, // ...right narrow (signed) + VQSHRNu, // ...right narrow (unsigned) + VQSHRNsu, // ...right narrow (signed to unsigned) + + // Vector saturating rounding shift by immediate: + VQRSHRNs, // ...right narrow (signed) + VQRSHRNu, // ...right narrow (unsigned) + VQRSHRNsu, // ...right narrow (signed to unsigned) + + // Vector shift and insert: + VSLI, // ...left + VSRI, // ...right + + // Vector get lane (VMOV scalar to ARM core register) + // (These are used for 8- and 16-bit element types only.) + VGETLANEu, // zero-extend vector extract element + VGETLANEs, // sign-extend vector extract element + + // Vector move immediate and move negated immediate: + VMOVIMM, + VMVNIMM, + + // Vector duplicate: + VDUP, + VDUPLANE, + + // Vector shuffles: + VEXT, // extract + VREV64, // reverse elements within 64-bit doublewords + VREV32, // reverse elements within 32-bit words + VREV16, // reverse elements within 16-bit halfwords + VZIP, // zip (interleave) + VUZP, // unzip (deinterleave) + VTRN, // transpose + + // Vector multiply long: + VMULLs, // ...signed + VMULLu, // ...unsigned + + // Operands of the standard BUILD_VECTOR node are not legalized, which + // is fine if BUILD_VECTORs are always lowered to shuffles or other + // operations, but for ARM some BUILD_VECTORs are legal as-is and their + // operands need to be legalized. Define an ARM-specific version of + // BUILD_VECTOR for this purpose. + BUILD_VECTOR, + + // Floating-point max and min: + FMAX, + FMIN, + + // Bit-field insert + BFI, + + // Vector OR with immediate + VORRIMM, + // Vector AND with NOT of immediate + VBICIMM, + + // Vector load N-element structure to all lanes: + VLD2DUP = ISD::FIRST_TARGET_MEMORY_OPCODE, + VLD3DUP, + VLD4DUP, + + // NEON loads with post-increment base updates: + VLD1_UPD, + VLD2_UPD, + VLD3_UPD, + VLD4_UPD, + VLD2LN_UPD, + VLD3LN_UPD, + VLD4LN_UPD, + VLD2DUP_UPD, + VLD3DUP_UPD, + VLD4DUP_UPD, + + // NEON stores with post-increment base updates: + VST1_UPD, + VST2_UPD, + VST3_UPD, + VST4_UPD, + VST2LN_UPD, + VST3LN_UPD, + VST4LN_UPD + }; + } + + /// Define some predicates that are used for node matching. + namespace ARM { + /// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be + /// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd) + /// instruction, returns its 8-bit integer representation. Otherwise, + /// returns -1. + int getVFPf32Imm(const APFloat &FPImm); + int getVFPf64Imm(const APFloat &FPImm); + bool isBitFieldInvertedMask(unsigned v); + } + + //===--------------------------------------------------------------------===// + // ARMTargetLowering - ARM Implementation of the TargetLowering interface + + class ARMTargetLowering : public TargetLowering { + public: + explicit ARMTargetLowering(TargetMachine &TM); + + virtual unsigned getJumpTableEncoding(void) const; + + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, + SelectionDAG &DAG) const; + + virtual const char *getTargetNodeName(unsigned Opcode) const; + + virtual MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB) const; + + virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const; + + /// allowsUnalignedMemoryAccesses - Returns true if the target allows + /// unaligned memory accesses. of the specified type. + /// FIXME: Add getOptimalMemOpType to implement memcpy with NEON? + virtual bool allowsUnalignedMemoryAccesses(EVT VT) const; + + /// isLegalAddressingMode - Return true if the addressing mode represented + /// by AM is legal for this target, for a load/store of the specified type. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const; + bool isLegalT2ScaledAddressingMode(const AddrMode &AM, EVT VT) const; + + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can + /// compare a register against the immediate without having to materialize + /// the immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const; + + /// getPreIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if the node's address + /// can be legally represented as pre-indexed load / store address. + virtual bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, + SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + /// getPostIndexedAddressParts - returns true by value, base pointer and + /// offset pointer and addressing mode by reference if this node can be + /// combined with a load / store to form a post-indexed load / store. + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDValue &Base, SDValue &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) const; + + virtual void computeMaskedBitsForTargetNode(const SDValue Op, + const APInt &Mask, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth) const; + + + virtual bool ExpandInlineAsm(CallInst *CI) const; + + ConstraintType getConstraintType(const std::string &Constraint) const; + + /// Examine constraint string and operand type and determine a weight value. + /// The operand object must already have been set up with the operand type. + ConstraintWeight getSingleConstraintMatchWeight( + AsmOperandInfo &info, const char *constraint) const; + + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops + /// vector. If it is invalid, don't add anything to Ops. If hasMemory is + /// true it means one of the asm constraint of the inline asm instruction + /// being processed is 'm'. + virtual void LowerAsmOperandForConstraint(SDValue Op, + char ConstraintLetter, + std::vector &Ops, + SelectionDAG &DAG) const; + + const ARMSubtarget* getSubtarget() const { + return Subtarget; + } + + /// getRegClassFor - Return the register class that should be used for the + /// specified value type. + virtual TargetRegisterClass *getRegClassFor(EVT VT) const; + + /// getFunctionAlignment - Return the Log2 alignment of this function. + virtual unsigned getFunctionAlignment(const Function *F) const; + + /// getMaximalGlobalOffset - Returns the maximal possible offset which can + /// be used for loads / stores from the global. + virtual unsigned getMaximalGlobalOffset() const; + + /// createFastISel - This method returns a target specific FastISel object, + /// or null if the target does not support "fast" ISel. + virtual FastISel *createFastISel(FunctionLoweringInfo &funcInfo) const; + + Sched::Preference getSchedulingPreference(SDNode *N) const; + + bool isShuffleMaskLegal(const SmallVectorImpl &M, EVT VT) const; + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will + /// materialize the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + + virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info, + const CallInst &I, + unsigned Intrinsic) const; + protected: + std::pair + findRepresentativeClass(EVT VT) const; + + private: + /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can + /// make the right decision when generating code for different targets. + const ARMSubtarget *Subtarget; + + const TargetRegisterInfo *RegInfo; + + const InstrItineraryData *Itins; + + /// ARMPCLabelIndex - Keep track of the number of ARM PC labels created. + /// + unsigned ARMPCLabelIndex; + + void addTypeForNEON(EVT VT, EVT PromotedLdStVT, EVT PromotedBitwiseVT); + void addDRTypeForNEON(EVT VT); + void addQRTypeForNEON(EVT VT); + + typedef SmallVector, 8> RegsToPassVector; + void PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG, + SDValue Chain, SDValue &Arg, + RegsToPassVector &RegsToPass, + CCValAssign &VA, CCValAssign &NextVA, + SDValue &StackPtr, + SmallVector &MemOpChains, + ISD::ArgFlagsTy Flags) const; + SDValue GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, + SDValue &Root, SelectionDAG &DAG, + DebugLoc dl) const; + + CCAssignFn *CCAssignFnForNode(CallingConv::ID CC, bool Return, + bool isVarArg) const; + SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg, + DebugLoc dl, SelectionDAG &DAG, + const CCValAssign &VA, + ISD::ArgFlagsTy Flags) const; + SDValue LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEH_SJLJ_DISPATCHSETUP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) const; + SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, + SelectionDAG &DAG) const; + SDValue LowerToTLSExecModels(GlobalAddressSDNode *GA, + SelectionDAG &DAG) const; + SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *ST) const; + + SDValue ReconstructShuffle(SDValue Op, SelectionDAG &DAG) const; + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + /// HandleByVal - Target-specific cleanup for ByVal support. + virtual void HandleByVal(CCState *) const; + + /// IsEligibleForTailCallOptimization - Check whether the call is eligible + /// for tail call optimization. Targets which want to do tail call + /// optimization should implement this function. + bool IsEligibleForTailCallOptimization(SDValue Callee, + CallingConv::ID CalleeCC, + bool isVarArg, + bool isCalleeStructRet, + bool isCallerStructRet, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + SelectionDAG& DAG) const; + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + DebugLoc dl, SelectionDAG &DAG) const; + + virtual bool isUsedByReturnOnly(SDNode *N) const; + + virtual bool mayBeEmittedAsTailCall(CallInst *CI) const; + + SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, + SDValue &ARMcc, SelectionDAG &DAG, DebugLoc dl) const; + SDValue getVFPCmp(SDValue LHS, SDValue RHS, + SelectionDAG &DAG, DebugLoc dl) const; + SDValue duplicateCmp(SDValue Cmp, SelectionDAG &DAG) const; + + SDValue OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const; + + MachineBasicBlock *EmitAtomicCmpSwap(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size) const; + MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size, + unsigned BinOpcode) const; + + }; + + enum NEONModImmType { + VMOVModImm, + VMVNModImm, + OtherModImm + }; + + + namespace ARM { + FastISel *createFastISel(FunctionLoweringInfo &funcInfo); + } +} + +#endif // ARMISELLOWERING_H diff --git a/final/lib/Target/ARM/ARMInstrFormats.td b/final/lib/Target/ARM/ARMInstrFormats.td new file mode 100644 index 00000000000..1c3476c0a92 --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrFormats.td @@ -0,0 +1,1815 @@ +//===- ARMInstrFormats.td - ARM Instruction Formats ----------*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// ARM Instruction Format Definitions. +// + +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format val> { + bits<6> Value = val; +} + +def Pseudo : Format<0>; +def MulFrm : Format<1>; +def BrFrm : Format<2>; +def BrMiscFrm : Format<3>; + +def DPFrm : Format<4>; +def DPSoRegFrm : Format<5>; + +def LdFrm : Format<6>; +def StFrm : Format<7>; +def LdMiscFrm : Format<8>; +def StMiscFrm : Format<9>; +def LdStMulFrm : Format<10>; + +def LdStExFrm : Format<11>; + +def ArithMiscFrm : Format<12>; +def SatFrm : Format<13>; +def ExtFrm : Format<14>; + +def VFPUnaryFrm : Format<15>; +def VFPBinaryFrm : Format<16>; +def VFPConv1Frm : Format<17>; +def VFPConv2Frm : Format<18>; +def VFPConv3Frm : Format<19>; +def VFPConv4Frm : Format<20>; +def VFPConv5Frm : Format<21>; +def VFPLdStFrm : Format<22>; +def VFPLdStMulFrm : Format<23>; +def VFPMiscFrm : Format<24>; + +def ThumbFrm : Format<25>; +def MiscFrm : Format<26>; + +def NGetLnFrm : Format<27>; +def NSetLnFrm : Format<28>; +def NDupFrm : Format<29>; +def NLdStFrm : Format<30>; +def N1RegModImmFrm: Format<31>; +def N2RegFrm : Format<32>; +def NVCVTFrm : Format<33>; +def NVDupLnFrm : Format<34>; +def N2RegVShLFrm : Format<35>; +def N2RegVShRFrm : Format<36>; +def N3RegFrm : Format<37>; +def N3RegVShFrm : Format<38>; +def NVExtFrm : Format<39>; +def NVMulSLFrm : Format<40>; +def NVTBLFrm : Format<41>; + +// Misc flags. + +// The instruction has an Rn register operand. +// UnaryDP - Indicates this is a unary data processing instruction, i.e. +// it doesn't have a Rn operand. +class UnaryDP { bit isUnaryDataProc = 1; } + +// Xform16Bit - Indicates this Thumb2 instruction may be transformed into +// a 16-bit Thumb instruction if certain conditions are met. +class Xform16Bit { bit canXformTo16Bit = 1; } + +//===----------------------------------------------------------------------===// +// ARM Instruction flags. These need to match ARMBaseInstrInfo.h. +// + +// FIXME: Once the JIT is MC-ized, these can go away. +// Addressing mode. +class AddrMode val> { + bits<5> Value = val; +} +def AddrModeNone : AddrMode<0>; +def AddrMode1 : AddrMode<1>; +def AddrMode2 : AddrMode<2>; +def AddrMode3 : AddrMode<3>; +def AddrMode4 : AddrMode<4>; +def AddrMode5 : AddrMode<5>; +def AddrMode6 : AddrMode<6>; +def AddrModeT1_1 : AddrMode<7>; +def AddrModeT1_2 : AddrMode<8>; +def AddrModeT1_4 : AddrMode<9>; +def AddrModeT1_s : AddrMode<10>; +def AddrModeT2_i12 : AddrMode<11>; +def AddrModeT2_i8 : AddrMode<12>; +def AddrModeT2_so : AddrMode<13>; +def AddrModeT2_pc : AddrMode<14>; +def AddrModeT2_i8s4 : AddrMode<15>; +def AddrMode_i12 : AddrMode<16>; + +// Instruction size. +class SizeFlagVal val> { + bits<3> Value = val; +} +def SizeInvalid : SizeFlagVal<0>; // Unset. +def SizeSpecial : SizeFlagVal<1>; // Pseudo or special. +def Size8Bytes : SizeFlagVal<2>; +def Size4Bytes : SizeFlagVal<3>; +def Size2Bytes : SizeFlagVal<4>; + +// Load / store index mode. +class IndexMode val> { + bits<2> Value = val; +} +def IndexModeNone : IndexMode<0>; +def IndexModePre : IndexMode<1>; +def IndexModePost : IndexMode<2>; +def IndexModeUpd : IndexMode<3>; + +// Instruction execution domain. +class Domain val> { + bits<3> Value = val; +} +def GenericDomain : Domain<0>; +def VFPDomain : Domain<1>; // Instructions in VFP domain only +def NeonDomain : Domain<2>; // Instructions in Neon domain only +def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains +def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8 + +//===----------------------------------------------------------------------===// +// ARM special operands. +// + +def CondCodeOperand : AsmOperandClass { + let Name = "CondCode"; + let SuperClasses = []; +} + +def CCOutOperand : AsmOperandClass { + let Name = "CCOut"; + let SuperClasses = []; +} + +def MemBarrierOptOperand : AsmOperandClass { + let Name = "MemBarrierOpt"; + let SuperClasses = []; + let ParserMethod = "tryParseMemBarrierOptOperand"; +} + +def ProcIFlagsOperand : AsmOperandClass { + let Name = "ProcIFlags"; + let SuperClasses = []; + let ParserMethod = "tryParseProcIFlagsOperand"; +} + +def MSRMaskOperand : AsmOperandClass { + let Name = "MSRMask"; + let SuperClasses = []; + let ParserMethod = "tryParseMSRMaskOperand"; +} + +// ARM imod and iflag operands, used only by the CPS instruction. +def imod_op : Operand { + let PrintMethod = "printCPSIMod"; +} + +def iflags_op : Operand { + let PrintMethod = "printCPSIFlag"; + let ParserMatchClass = ProcIFlagsOperand; +} + +// ARM Predicate operand. Default to 14 = always (AL). Second part is CC +// register whose default is 0 (no register). +def pred : PredicateOperand { + let PrintMethod = "printPredicateOperand"; + let ParserMatchClass = CondCodeOperand; +} + +// Conditional code result for instructions whose 's' bit is set, e.g. subs. +def cc_out : OptionalDefOperand { + let EncoderMethod = "getCCOutOpValue"; + let PrintMethod = "printSBitModifierOperand"; + let ParserMatchClass = CCOutOperand; +} + +// Same as cc_out except it defaults to setting CPSR. +def s_cc_out : OptionalDefOperand { + let EncoderMethod = "getCCOutOpValue"; + let PrintMethod = "printSBitModifierOperand"; + let ParserMatchClass = CCOutOperand; +} + +// ARM special operands for disassembly only. +// +def setend_op : Operand { + let PrintMethod = "printSetendOperand"; +} + +def cps_opt : Operand { + let PrintMethod = "printCPSOptionOperand"; +} + +def msr_mask : Operand { + let PrintMethod = "printMSRMaskOperand"; + let ParserMatchClass = MSRMaskOperand; +} + +// A8.6.117, A8.6.118. Different instructions are generated for #0 and #-0. +// The neg_zero operand translates -0 to -1, -1 to -2, ..., etc. +def neg_zero : Operand { + let PrintMethod = "printNegZeroOperand"; +} + +// Shift Right Immediate - A shift right immediate is encoded differently from +// other shift immediates. The imm6 field is encoded like so: +// +// Offset Encoding +// 8 imm6<5:3> = '001', 8 - is encoded in imm6<2:0> +// 16 imm6<5:4> = '01', 16 - is encoded in imm6<3:0> +// 32 imm6<5> = '1', 32 - is encoded in imm6<4:0> +// 64 64 - is encoded in imm6<5:0> +def shr_imm8 : Operand { + let EncoderMethod = "getShiftRight8Imm"; +} +def shr_imm16 : Operand { + let EncoderMethod = "getShiftRight16Imm"; +} +def shr_imm32 : Operand { + let EncoderMethod = "getShiftRight32Imm"; +} +def shr_imm64 : Operand { + let EncoderMethod = "getShiftRight64Imm"; +} + +//===----------------------------------------------------------------------===// +// ARM Instruction templates. +// + +class InstTemplate + : Instruction { + let Namespace = "ARM"; + + AddrMode AM = am; + SizeFlagVal SZ = sz; + IndexMode IM = im; + bits<2> IndexModeBits = IM.Value; + Format F = f; + bits<6> Form = F.Value; + Domain D = d; + bit isUnaryDataProc = 0; + bit canXformTo16Bit = 0; + + // If this is a pseudo instruction, mark it isCodeGenOnly. + let isCodeGenOnly = !eq(!cast(f), "Pseudo"); + + // The layout of TSFlags should be kept in sync with ARMBaseInstrInfo.h. + let TSFlags{4-0} = AM.Value; + let TSFlags{7-5} = SZ.Value; + let TSFlags{9-8} = IndexModeBits; + let TSFlags{15-10} = Form; + let TSFlags{16} = isUnaryDataProc; + let TSFlags{17} = canXformTo16Bit; + let TSFlags{20-18} = D.Value; + + let Constraints = cstr; + let Itinerary = itin; +} + +class Encoding { + field bits<32> Inst; +} + +class InstARM + : InstTemplate, Encoding; + +// This Encoding-less class is used by Thumb1 to specify the encoding bits later +// on by adding flavors to specific instructions. +class InstThumb + : InstTemplate; + +class PseudoInst pattern> + // FIXME: This really should derive from InstTemplate instead, as pseudos + // don't need encoding information. TableGen doesn't like that + // currently. Need to figure out why and fix it. + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let Pattern = pattern; +} + +// PseudoInst that's ARM-mode only. +class ARMPseudoInst pattern> + : PseudoInst { + let SZ = sz; + list Predicates = [IsARM]; +} + +// PseudoInst that's Thumb-mode only. +class tPseudoInst pattern> + : PseudoInst { + let SZ = sz; + list Predicates = [IsThumb]; +} + +// PseudoInst that's Thumb2-mode only. +class t2PseudoInst pattern> + : PseudoInst { + let SZ = sz; + list Predicates = [IsThumb2]; +} +// Almost all ARM instructions are predicable. +class I pattern> + : InstARM { + bits<4> p; + let Inst{31-28} = p; + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + list Predicates = [IsARM]; +} + +// A few are not predicable +class InoP pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = !strconcat(opc, asm); + let Pattern = pattern; + let isPredicable = 0; + list Predicates = [IsARM]; +} + +// Same as I except it can optionally modify CPSR. Note it's modeled as an input +// operand since by default it's a zero register. It will become an implicit def +// once it's "flipped". +class sI pattern> + : InstARM { + bits<4> p; // Predicate operand + bits<1> s; // condition-code set flag ('1' if the insn should set the flags) + let Inst{31-28} = p; + let Inst{20} = s; + + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p, cc_out:$s)); + let AsmString = !strconcat(opc, "${s}${p}", asm); + let Pattern = pattern; + list Predicates = [IsARM]; +} + +// Special cases +class XI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsARM]; +} + +class AI pattern> + : I; +class AsI pattern> + : sI; +class AXI pattern> + : XI; +class AInoP pattern> + : InoP; + +// Ctrl flow instructions +class ABI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{27-24} = opcod; +} +class ABXI opcod, dag oops, dag iops, InstrItinClass itin, + string asm, list pattern> + : XI { + let Inst{27-24} = opcod; +} + +// BR_JT instructions +class JTI pattern> + : XI; + +// Atomic load/store instructions +class AIldrex opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + bits<4> Rt; + bits<4> Rn; + let Inst{27-23} = 0b00011; + let Inst{22-21} = opcod; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = Rt; + let Inst{11-0} = 0b111110011111; +} +class AIstrex opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + bits<4> Rd; + bits<4> Rt; + bits<4> Rn; + let Inst{27-23} = 0b00011; + let Inst{22-21} = opcod; + let Inst{20} = 0; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-4} = 0b11111001; + let Inst{3-0} = Rt; +} +class AIswp pattern> + : AI { + bits<4> Rt; + bits<4> Rt2; + bits<4> Rn; + let Inst{27-23} = 0b00010; + let Inst{22} = b; + let Inst{21-20} = 0b00; + let Inst{19-16} = Rn; + let Inst{15-12} = Rt; + let Inst{11-4} = 0b00001001; + let Inst{3-0} = Rt2; +} + +// addrmode1 instructions +class AI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{24-21} = opcod; + let Inst{27-26} = 0b00; +} +class AsI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, list pattern> + : sI { + let Inst{24-21} = opcod; + let Inst{27-26} = 0b00; +} +class AXI1 opcod, dag oops, dag iops, Format f, InstrItinClass itin, + string asm, list pattern> + : XI { + let Inst{24-21} = opcod; + let Inst{27-26} = 0b00; +} + +// loads + +// LDR/LDRB/STR/STRB/... +class AI2ldst op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am, + Format f, InstrItinClass itin, string opc, string asm, + list pattern> + : I { + let Inst{27-25} = op; + let Inst{24} = 1; // 24 == P + // 23 == U + let Inst{22} = isByte; + let Inst{21} = 0; // 21 == W + let Inst{20} = isLd; +} +// Indexed load/stores +class AI2ldstidx pattern> + : I { + bits<4> Rt; + let Inst{27-26} = 0b01; + let Inst{24} = isPre; // P bit + let Inst{22} = isByte; // B bit + let Inst{21} = isPre; // W bit + let Inst{20} = isLd; // L bit + let Inst{15-12} = Rt; +} +class AI2stridx pattern> + : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, + pattern> { + // AM2 store w/ two operands: (GPR, am2offset) + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> Rn; + let Inst{25} = offset{13}; + let Inst{23} = offset{12}; + let Inst{19-16} = Rn; + let Inst{11-0} = offset{11-0}; +} + +// addrmode3 instructions +class AI3ld op, bit op20, dag oops, dag iops, Format f, + InstrItinClass itin, string opc, string asm, list pattern> + : I { + bits<14> addr; + bits<4> Rt; + let Inst{27-25} = 0b000; + let Inst{24} = 1; // P bit + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{21} = 0; // W bit + let Inst{20} = op20; // L bit + let Inst{19-16} = addr{12-9}; // Rn + let Inst{15-12} = Rt; // Rt + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{7-4} = op; + let Inst{3-0} = addr{3-0}; // imm3_0/Rm +} + +class AI3ldstidx op, bit op20, bit isLd, bit isPre, dag oops, dag iops, + IndexMode im, Format f, InstrItinClass itin, string opc, + string asm, string cstr, list pattern> + : I { + bits<4> Rt; + let Inst{27-25} = 0b000; + let Inst{24} = isPre; // P bit + let Inst{21} = isPre; // W bit + let Inst{20} = op20; // L bit + let Inst{15-12} = Rt; // Rt + let Inst{7-4} = op; +} +class AI3stridx op, bit isByte, bit isPre, dag oops, dag iops, + IndexMode im, Format f, InstrItinClass itin, string opc, + string asm, string cstr, list pattern> + : AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr, + pattern> { + // AM3 store w/ two operands: (GPR, am3offset) + bits<14> offset; + bits<4> Rt; + bits<4> Rn; + let Inst{27-25} = 0b000; + let Inst{23} = offset{8}; + let Inst{22} = offset{9}; + let Inst{19-16} = Rn; + let Inst{15-12} = Rt; // Rt + let Inst{11-8} = offset{7-4}; // imm7_4/zero + let Inst{7-4} = op; + let Inst{3-0} = offset{3-0}; // imm3_0/Rm +} + +// stores +class AI3str op, dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + bits<14> addr; + bits<4> Rt; + let Inst{27-25} = 0b000; + let Inst{24} = 1; // P bit + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{21} = 0; // W bit + let Inst{20} = 0; // L bit + let Inst{19-16} = addr{12-9}; // Rn + let Inst{15-12} = Rt; // Rt + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{7-4} = op; + let Inst{3-0} = addr{3-0}; // imm3_0/Rm +} + +// Pre-indexed stores +class AI3sthpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} +class AI3stdpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + +// Post-indexed stores +class AI3sthpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 0; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} +class AI3stdpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit + let Inst{24} = 0; // P bit + let Inst{27-25} = 0b000; +} + +// addrmode4 instructions +class AXI4 pattern> + : XI { + bits<4> p; + bits<16> regs; + bits<4> Rn; + let Inst{31-28} = p; + let Inst{27-25} = 0b100; + let Inst{22} = 0; // S bit + let Inst{19-16} = Rn; + let Inst{15-0} = regs; +} + +// Unsigned multiply, multiply-accumulate instructions. +class AMul1I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + let Inst{7-4} = 0b1001; + let Inst{20} = 0; // S bit + let Inst{27-21} = opcod; +} +class AsMul1I opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : sI { + let Inst{7-4} = 0b1001; + let Inst{27-21} = opcod; +} + +// Most significant word multiply +class AMul2I opcod, bits<4> opc7_4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : I { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{7-4} = opc7_4; + let Inst{20} = 1; + let Inst{27-21} = opcod; + let Inst{19-16} = Rd; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +// MSW multiple w/ Ra operand +class AMul2Ia opcod, bits<4> opc7_4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AMul2I { + bits<4> Ra; + let Inst{15-12} = Ra; +} + +// SMUL / SMULW / SMLA / SMLAW +class AMulxyIbase opcod, bits<2> bit6_5, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : I { + bits<4> Rn; + bits<4> Rm; + let Inst{4} = 0; + let Inst{7} = 1; + let Inst{20} = 0; + let Inst{27-21} = opcod; + let Inst{6-5} = bit6_5; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +class AMulxyI opcod, bits<2> bit6_5, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AMulxyIbase { + bits<4> Rd; + let Inst{19-16} = Rd; +} + +// AMulxyI with Ra operand +class AMulxyIa opcod, bits<2> bit6_5, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AMulxyI { + bits<4> Ra; + let Inst{15-12} = Ra; +} +// SMLAL* +class AMulxyI64 opcod, bits<2> bit6_5, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AMulxyIbase { + bits<4> RdLo; + bits<4> RdHi; + let Inst{19-16} = RdHi; + let Inst{15-12} = RdLo; +} + +// Extend instructions. +class AExtI opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + // All AExtI instructions have Rd and Rm register operands. + bits<4> Rd; + bits<4> Rm; + let Inst{15-12} = Rd; + let Inst{3-0} = Rm; + let Inst{7-4} = 0b0111; + let Inst{9-8} = 0b00; + let Inst{27-20} = opcod; +} + +// Misc Arithmetic instructions. +class AMiscA1I opcod, bits<4> opc7_4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : I { + bits<4> Rd; + bits<4> Rm; + let Inst{27-20} = opcod; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-8} = 0b1111; + let Inst{7-4} = opc7_4; + let Inst{3-0} = Rm; +} + +// PKH instructions +class APKHI opcod, bit tb, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : I { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + bits<8> sh; + let Inst{27-20} = opcod; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-7} = sh{7-3}; + let Inst{6} = tb; + let Inst{5-4} = 0b01; + let Inst{3-0} = Rm; +} + +//===----------------------------------------------------------------------===// + +// ARMPat - Same as Pat<>, but requires that the compiler be in ARM mode. +class ARMPat : Pat { + list Predicates = [IsARM]; +} +class ARMV5TEPat : Pat { + list Predicates = [IsARM, HasV5TE]; +} +class ARMV6Pat : Pat { + list Predicates = [IsARM, HasV6]; +} + +//===----------------------------------------------------------------------===// +// Thumb Instruction Format Definitions. +// + +class ThumbI pattern> + : InstThumb { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb]; +} + +// TI - Thumb instruction. +class TI pattern> + : ThumbI; + +// Two-address instructions +class TIt pattern> + : ThumbI; + +// tBL, tBX 32-bit instructions +class TIx2 opcod1, bits<2> opcod2, bit opcod3, + dag oops, dag iops, InstrItinClass itin, string asm, + list pattern> + : ThumbI, + Encoding { + let Inst{31-27} = opcod1; + let Inst{15-14} = opcod2; + let Inst{12} = opcod3; +} + +// Move to/from coprocessor instructions +class T1Cop pattern> + : ThumbI, + Encoding, Requires<[IsThumb, HasV6]> { + let Inst{31-28} = 0b1110; +} + +// BR_JT instructions +class TJTI pattern> + : ThumbI; + +// Thumb1 only +class Thumb1I pattern> + : InstThumb { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb, IsThumb1Only]; +} + +class T1I pattern> + : Thumb1I; +class T1Ix2 pattern> + : Thumb1I; + +// Two-address instructions +class T1It pattern> + : Thumb1I; + +// Thumb1 instruction that can either be predicated or set CPSR. +class Thumb1sI pattern> + : InstThumb { + let OutOperandList = !con(oops, (outs s_cc_out:$s)); + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${s}${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb, IsThumb1Only]; +} + +class T1sI pattern> + : Thumb1sI; + +// Two-address instructions +class T1sIt pattern> + : Thumb1sI; + +// Thumb1 instruction that can be predicated. +class Thumb1pI pattern> + : InstThumb { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb, IsThumb1Only]; +} + +class T1pI pattern> + : Thumb1pI; + +// Two-address instructions +class T1pIt pattern> + : Thumb1pI; + +class T1pIs pattern> + : Thumb1pI; + +class Encoding16 : Encoding { + let Inst{31-16} = 0x0000; +} + +// A6.2 16-bit Thumb instruction encoding +class T1Encoding opcode> : Encoding16 { + let Inst{15-10} = opcode; +} + +// A6.2.1 Shift (immediate), add, subtract, move, and compare encoding. +class T1General opcode> : Encoding16 { + let Inst{15-14} = 0b00; + let Inst{13-9} = opcode; +} + +// A6.2.2 Data-processing encoding. +class T1DataProcessing opcode> : Encoding16 { + let Inst{15-10} = 0b010000; + let Inst{9-6} = opcode; +} + +// A6.2.3 Special data instructions and branch and exchange encoding. +class T1Special opcode> : Encoding16 { + let Inst{15-10} = 0b010001; + let Inst{9-6} = opcode; +} + +// A6.2.4 Load/store single data item encoding. +class T1LoadStore opA, bits<3> opB> : Encoding16 { + let Inst{15-12} = opA; + let Inst{11-9} = opB; +} +class T1LdStSP opB> : T1LoadStore<0b1001, opB>; // SP relative + +// Helper classes to encode Thumb1 loads and stores. For immediates, the +// following bits are used for "opA" (see A6.2.4): +// +// 0b0110 => Immediate, 4 bytes +// 0b1000 => Immediate, 2 bytes +// 0b0111 => Immediate, 1 byte +class T1pILdStEncode opcode, dag oops, dag iops, AddrMode am, + InstrItinClass itin, string opc, string asm, + list pattern> + : Thumb1pI, + T1LoadStore<0b0101, opcode> { + bits<3> Rt; + bits<8> addr; + let Inst{8-6} = addr{5-3}; // Rm + let Inst{5-3} = addr{2-0}; // Rn + let Inst{2-0} = Rt; +} +class T1pILdStEncodeImm opA, bit opB, dag oops, dag iops, AddrMode am, + InstrItinClass itin, string opc, string asm, + list pattern> + : Thumb1pI, + T1LoadStore { + bits<3> Rt; + bits<8> addr; + let Inst{10-6} = addr{7-3}; // imm5 + let Inst{5-3} = addr{2-0}; // Rn + let Inst{2-0} = Rt; +} + +// A6.2.5 Miscellaneous 16-bit instructions encoding. +class T1Misc opcode> : Encoding16 { + let Inst{15-12} = 0b1011; + let Inst{11-5} = opcode; +} + +// Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable. +class Thumb2I pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +// Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as an +// input operand since by default it's a zero register. It will become an +// implicit def once it's "flipped". +// +// FIXME: This uses unified syntax so {s} comes before {p}. We should make it +// more consistent. +class Thumb2sI pattern> + : InstARM { + bits<1> s; // condition-code set flag ('1' if the insn should set the flags) + let Inst{20} = s; + + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p, cc_out:$s)); + let AsmString = !strconcat(opc, "${s}${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +// Special cases +class Thumb2XI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb2]; +} + +class ThumbXI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + list Predicates = [IsThumb, IsThumb1Only]; +} + +class T2I pattern> + : Thumb2I; +class T2Ii12 pattern> + : Thumb2I; +class T2Ii8 pattern> + : Thumb2I; +class T2Iso pattern> + : Thumb2I; +class T2Ipc pattern> + : Thumb2I; +class T2Ii8s4 pattern> + : Thumb2I { + bits<4> Rt; + bits<4> Rt2; + bits<13> addr; + let Inst{31-25} = 0b1110100; + let Inst{24} = P; + let Inst{23} = addr{8}; + let Inst{22} = 1; + let Inst{21} = W; + let Inst{20} = isLoad; + let Inst{19-16} = addr{12-9}; + let Inst{15-12} = Rt{3-0}; + let Inst{11-8} = Rt2{3-0}; + let Inst{7-0} = addr{7-0}; +} + +class T2sI pattern> + : Thumb2sI; + +class T2XI pattern> + : Thumb2XI; +class T2JTI pattern> + : Thumb2XI; + +// Move to/from coprocessor instructions +class T2Cop pattern> + : T2XI, Requires<[IsThumb2, HasV6]> { + let Inst{31-28} = 0b1111; +} + +// Two-address instructions +class T2XIt pattern> + : Thumb2XI; + +// T2Iidxldst - Thumb2 indexed load / store instructions. +class T2Iidxldst opcod, bit load, bit pre, + dag oops, dag iops, + AddrMode am, IndexMode im, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + list Predicates = [IsThumb2]; + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = opcod; + let Inst{20} = load; + let Inst{11} = 1; + // (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed + let Inst{10} = pre; // The P bit. + let Inst{8} = 1; // The W bit. + + bits<9> addr; + let Inst{7-0} = addr{7-0}; + let Inst{9} = addr{8}; // Sign bit + + bits<4> Rt; + bits<4> Rn; + let Inst{15-12} = Rt{3-0}; + let Inst{19-16} = Rn{3-0}; +} + +// Tv5Pat - Same as Pat<>, but requires V5T Thumb mode. +class Tv5Pat : Pat { + list Predicates = [IsThumb, IsThumb1Only, HasV5T]; +} + +// T1Pat - Same as Pat<>, but requires that the compiler be in Thumb1 mode. +class T1Pat : Pat { + list Predicates = [IsThumb, IsThumb1Only]; +} + +// T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode. +class T2Pat : Pat { + list Predicates = [IsThumb2]; +} + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM VFP Instruction templates. +// + +// Almost all VFP instructions are predicable. +class VFPI pattern> + : InstARM { + bits<4> p; + let Inst{31-28} = p; + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", asm); + let Pattern = pattern; + let PostEncoderMethod = "VFPThumb2PostEncoder"; + list Predicates = [HasVFP2]; +} + +// Special cases +class VFPXI pattern> + : InstARM { + bits<4> p; + let Inst{31-28} = p; + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = asm; + let Pattern = pattern; + let PostEncoderMethod = "VFPThumb2PostEncoder"; + list Predicates = [HasVFP2]; +} + +class VFPAI pattern> + : VFPI { + let PostEncoderMethod = "VFPThumb2PostEncoder"; +} + +// ARM VFP addrmode5 loads and stores +class ADI5 opcod1, bits<2> opcod2, dag oops, dag iops, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPI { + // Instruction operands. + bits<5> Dd; + bits<13> addr; + + // Encode instruction operands. + let Inst{23} = addr{8}; // U (add = (U == '1')) + let Inst{22} = Dd{4}; + let Inst{19-16} = addr{12-9}; // Rn + let Inst{15-12} = Dd{3-0}; + let Inst{7-0} = addr{7-0}; // imm8 + + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-9} = 0b101; + let Inst{8} = 1; // Double precision + + // Loads & stores operate on both NEON and VFP pipelines. + let D = VFPNeonDomain; +} + +class ASI5 opcod1, bits<2> opcod2, dag oops, dag iops, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPI { + // Instruction operands. + bits<5> Sd; + bits<13> addr; + + // Encode instruction operands. + let Inst{23} = addr{8}; // U (add = (U == '1')) + let Inst{22} = Sd{0}; + let Inst{19-16} = addr{12-9}; // Rn + let Inst{15-12} = Sd{4-1}; + let Inst{7-0} = addr{7-0}; // imm8 + + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-24} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision + + // Loads & stores operate on both NEON and VFP pipelines. + let D = VFPNeonDomain; +} + +// VFP Load / store multiple pseudo instructions. +class PseudoVFPLdStM pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let Pattern = pattern; + list Predicates = [HasVFP2]; +} + +// Load / store multiple +class AXDI4 pattern> + : VFPXI { + // Instruction operands. + bits<4> Rn; + bits<13> regs; + + // Encode instruction operands. + let Inst{19-16} = Rn; + let Inst{22} = regs{12}; + let Inst{15-12} = regs{11-8}; + let Inst{7-0} = regs{7-0}; + + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-9} = 0b101; + let Inst{8} = 1; // Double precision +} + +class AXSI4 pattern> + : VFPXI { + // Instruction operands. + bits<4> Rn; + bits<13> regs; + + // Encode instruction operands. + let Inst{19-16} = Rn; + let Inst{22} = regs{8}; + let Inst{15-12} = regs{12-9}; + let Inst{7-0} = regs{7-0}; + + // TODO: Mark the instructions with the appropriate subtarget info. + let Inst{27-25} = 0b110; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision +} + +// Double precision, unary +class ADuI opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, + bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc, + string asm, list pattern> + : VFPAI { + // Instruction operands. + bits<5> Dd; + bits<5> Dm; + + // Encode instruction operands. + let Inst{3-0} = Dm{3-0}; + let Inst{5} = Dm{4}; + let Inst{15-12} = Dd{3-0}; + let Inst{22} = Dd{4}; + + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{19-16} = opcod3; + let Inst{11-9} = 0b101; + let Inst{8} = 1; // Double precision + let Inst{7-6} = opcod4; + let Inst{4} = opcod5; +} + +// Double precision, binary +class ADbI opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, + dag iops, InstrItinClass itin, string opc, string asm, + list pattern> + : VFPAI { + // Instruction operands. + bits<5> Dd; + bits<5> Dn; + bits<5> Dm; + + // Encode instruction operands. + let Inst{3-0} = Dm{3-0}; + let Inst{5} = Dm{4}; + let Inst{19-16} = Dn{3-0}; + let Inst{7} = Dn{4}; + let Inst{15-12} = Dd{3-0}; + let Inst{22} = Dd{4}; + + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-9} = 0b101; + let Inst{8} = 1; // Double precision + let Inst{6} = op6; + let Inst{4} = op4; +} + +// Single precision, unary +class ASuI opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, + bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc, + string asm, list pattern> + : VFPAI { + // Instruction operands. + bits<5> Sd; + bits<5> Sm; + + // Encode instruction operands. + let Inst{3-0} = Sm{4-1}; + let Inst{5} = Sm{0}; + let Inst{15-12} = Sd{4-1}; + let Inst{22} = Sd{0}; + + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{19-16} = opcod3; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision + let Inst{7-6} = opcod4; + let Inst{4} = opcod5; +} + +// Single precision unary, if no NEON. Same as ASuI except not available if +// NEON is enabled. +class ASuIn opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4, + bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc, + string asm, list pattern> + : ASuI { + list Predicates = [HasVFP2,DontUseNEONForFP]; +} + +// Single precision, binary +class ASbI opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : VFPAI { + // Instruction operands. + bits<5> Sd; + bits<5> Sn; + bits<5> Sm; + + // Encode instruction operands. + let Inst{3-0} = Sm{4-1}; + let Inst{5} = Sm{0}; + let Inst{19-16} = Sn{4-1}; + let Inst{7} = Sn{0}; + let Inst{15-12} = Sd{4-1}; + let Inst{22} = Sd{0}; + + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{11-9} = 0b101; + let Inst{8} = 0; // Single precision + let Inst{6} = op6; + let Inst{4} = op4; +} + +// Single precision binary, if no NEON. Same as ASbI except not available if +// NEON is enabled. +class ASbIn opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, + dag iops, InstrItinClass itin, string opc, string asm, + list pattern> + : ASbI { + list Predicates = [HasVFP2,DontUseNEONForFP]; + + // Instruction operands. + bits<5> Sd; + bits<5> Sn; + bits<5> Sm; + + // Encode instruction operands. + let Inst{3-0} = Sm{4-1}; + let Inst{5} = Sm{0}; + let Inst{19-16} = Sn{4-1}; + let Inst{7} = Sn{0}; + let Inst{15-12} = Sd{4-1}; + let Inst{22} = Sd{0}; +} + +// VFP conversion instructions +class AVConv1I opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4, + dag oops, dag iops, InstrItinClass itin, string opc, string asm, + list pattern> + : VFPAI { + let Inst{27-23} = opcod1; + let Inst{21-20} = opcod2; + let Inst{19-16} = opcod3; + let Inst{11-8} = opcod4; + let Inst{6} = 1; + let Inst{4} = 0; +} + +// VFP conversion between floating-point and fixed-point +class AVConv1XI op1, bits<2> op2, bits<4> op3, bits<4> op4, bit op5, + dag oops, dag iops, InstrItinClass itin, string opc, string asm, + list pattern> + : AVConv1I { + // size (fixed-point number): sx == 0 ? 16 : 32 + let Inst{7} = op5; // sx +} + +// VFP conversion instructions, if no NEON +class AVConv1In opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : AVConv1I { + list Predicates = [HasVFP2,DontUseNEONForFP]; +} + +class AVConvXI opcod1, bits<4> opcod2, dag oops, dag iops, Format f, + InstrItinClass itin, + string opc, string asm, list pattern> + : VFPAI { + let Inst{27-20} = opcod1; + let Inst{11-8} = opcod2; + let Inst{4} = 1; +} + +class AVConv2I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv3I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv4I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +class AVConv5I opcod1, bits<4> opcod2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : AVConvXI; + +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM NEON Instruction templates. +// + +class NeonI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm); + let Pattern = pattern; + list Predicates = [HasNEON]; +} + +// Same as NeonI except it does not have a "data type" specifier. +class NeonXI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", "\t", asm); + let Pattern = pattern; + list Predicates = [HasNEON]; +} + +class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NeonI { + let Inst{31-24} = 0b11110100; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{7-4} = op7_4; + + let PostEncoderMethod = "NEONThumb2LoadStorePostEncoder"; + + bits<5> Vd; + bits<6> Rn; + bits<4> Rm; + + let Inst{22} = Vd{4}; + let Inst{15-12} = Vd{3-0}; + let Inst{19-16} = Rn{3-0}; + let Inst{3-0} = Rm{3-0}; +} + +class NLdStLn op21_20, bits<4> op11_8, bits<4> op7_4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NLdSt { + bits<3> lane; +} + +class PseudoNLdSt + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + list Predicates = [HasNEON]; +} + +class PseudoNeonI pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let Pattern = pattern; + list Predicates = [HasNEON]; +} + +class NDataI pattern> + : NeonI { + let Inst{31-25} = 0b1111001; + let PostEncoderMethod = "NEONThumb2DataIPostEncoder"; +} + +class NDataXI pattern> + : NeonXI { + let Inst{31-25} = 0b1111001; + let PostEncoderMethod = "NEONThumb2DataIPostEncoder"; +} + +// NEON "one register and a modified immediate" format. +class N1ModImm op21_19, bits<4> op11_8, bit op7, bit op6, + bit op5, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, + list pattern> + : NDataI { + let Inst{23} = op23; + let Inst{21-19} = op21_19; + let Inst{11-8} = op11_8; + let Inst{7} = op7; + let Inst{6} = op6; + let Inst{5} = op5; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<13> SIMM; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{24} = SIMM{7}; + let Inst{18-16} = SIMM{6-4}; + let Inst{3-0} = SIMM{3-0}; +} + +// NEON 2 vector register format. +class N2V op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24-23} = op24_23; + let Inst{21-20} = op21_20; + let Inst{19-18} = op19_18; + let Inst{17-16} = op17_16; + let Inst{11-7} = op11_7; + let Inst{6} = op6; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<5> Vm; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = Vm{4}; +} + +// Same as N2V except it doesn't have a datatype suffix. +class N2VX op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + dag oops, dag iops, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : NDataXI { + let Inst{24-23} = op24_23; + let Inst{21-20} = op21_20; + let Inst{19-18} = op19_18; + let Inst{17-16} = op17_16; + let Inst{11-7} = op11_7; + let Inst{6} = op6; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<5> Vm; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = Vm{4}; +} + +// NEON 2 vector register with immediate. +class N2VImm op11_8, bit op7, bit op6, bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{11-8} = op11_8; + let Inst{7} = op7; + let Inst{6} = op6; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<5> Vm; + bits<6> SIMM; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = Vm{4}; + let Inst{21-16} = SIMM{5-0}; +} + +// NEON 3 vector register format. +class N3V op21_20, bits<4> op11_8, bit op6, bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, string cstr, list pattern> + : NDataI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{6} = op6; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<5> Vn; + bits<5> Vm; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{19-16} = Vn{3-0}; + let Inst{7} = Vn{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = Vm{4}; +} + +// Same as N3V except it doesn't have a data type suffix. +class N3VX op21_20, bits<4> op11_8, bit op6, + bit op4, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string asm, string cstr, list pattern> + : NDataXI { + let Inst{24} = op24; + let Inst{23} = op23; + let Inst{21-20} = op21_20; + let Inst{11-8} = op11_8; + let Inst{6} = op6; + let Inst{4} = op4; + + // Instruction operands. + bits<5> Vd; + bits<5> Vn; + bits<5> Vm; + + let Inst{15-12} = Vd{3-0}; + let Inst{22} = Vd{4}; + let Inst{19-16} = Vn{3-0}; + let Inst{7} = Vn{4}; + let Inst{3-0} = Vm{3-0}; + let Inst{5} = Vm{4}; +} + +// NEON VMOVs between scalar and core registers. +class NVLaneOp opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, Format f, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : InstARM { + let Inst{27-20} = opcod1; + let Inst{11-8} = opcod2; + let Inst{6-5} = opcod3; + let Inst{4} = 1; + + let OutOperandList = oops; + let InOperandList = !con(iops, (ins pred:$p)); + let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm); + let Pattern = pattern; + list Predicates = [HasNEON]; + + let PostEncoderMethod = "NEONThumb2DupPostEncoder"; + + bits<5> V; + bits<4> R; + bits<4> p; + bits<4> lane; + + let Inst{31-28} = p{3-0}; + let Inst{7} = V{4}; + let Inst{19-16} = V{3-0}; + let Inst{15-12} = R{3-0}; +} +class NVGetLane opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; +class NVSetLane opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; +class NVDup opcod1, bits<4> opcod2, bits<2> opcod3, + dag oops, dag iops, InstrItinClass itin, + string opc, string dt, string asm, list pattern> + : NVLaneOp; + +// Vector Duplicate Lane (from scalar to all elements) +class NVDupLane op19_16, bit op6, dag oops, dag iops, + InstrItinClass itin, string opc, string dt, string asm, + list pattern> + : NDataI { + let Inst{24-23} = 0b11; + let Inst{21-20} = 0b11; + let Inst{19-16} = op19_16; + let Inst{11-7} = 0b11000; + let Inst{6} = op6; + let Inst{4} = 0; + + bits<5> Vd; + bits<5> Vm; + bits<4> lane; + + let Inst{22} = Vd{4}; + let Inst{15-12} = Vd{3-0}; + let Inst{5} = Vm{4}; + let Inst{3-0} = Vm{3-0}; +} + +// NEONFPPat - Same as Pat<>, but requires that the compiler be using NEON +// for single-precision FP. +class NEONFPPat : Pat { + list Predicates = [HasNEON,UseNEONForFP]; +} diff --git a/final/lib/Target/ARM/ARMInstrInfo.cpp b/final/lib/Target/ARM/ARMInstrInfo.cpp new file mode 100644 index 00000000000..6f48d967f91 --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrInfo.cpp @@ -0,0 +1,61 @@ +//===- ARMInstrInfo.cpp - ARM Instruction Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "ARMInstrInfo.h" +#include "ARM.h" +#include "ARMAddressingModes.h" +#include "ARMGenInstrInfo.inc" +#include "ARMMachineFunctionInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/MC/MCAsmInfo.h" +using namespace llvm; + +ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI) + : ARMBaseInstrInfo(STI), RI(*this, STI) { +} + +unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const { + switch (Opc) { + default: break; + case ARM::LDR_PRE: + case ARM::LDR_POST: + return ARM::LDRi12; + case ARM::LDRH_PRE: + case ARM::LDRH_POST: + return ARM::LDRH; + case ARM::LDRB_PRE: + case ARM::LDRB_POST: + return ARM::LDRBi12; + case ARM::LDRSH_PRE: + case ARM::LDRSH_POST: + return ARM::LDRSH; + case ARM::LDRSB_PRE: + case ARM::LDRSB_POST: + return ARM::LDRSB; + case ARM::STR_PRE: + case ARM::STR_POST: + return ARM::STRi12; + case ARM::STRH_PRE: + case ARM::STRH_POST: + return ARM::STRH; + case ARM::STRB_PRE: + case ARM::STRB_POST: + return ARM::STRBi12; + } + + return 0; +} diff --git a/final/lib/Target/ARM/ARMInstrInfo.h b/final/lib/Target/ARM/ARMInstrInfo.h new file mode 100644 index 00000000000..f2c7bdc31be --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrInfo.h @@ -0,0 +1,44 @@ +//===- ARMInstrInfo.h - ARM Instruction Information -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the ARM implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef ARMINSTRUCTIONINFO_H +#define ARMINSTRUCTIONINFO_H + +#include "llvm/Target/TargetInstrInfo.h" +#include "ARMBaseInstrInfo.h" +#include "ARMRegisterInfo.h" +#include "ARMSubtarget.h" +#include "ARM.h" + +namespace llvm { + class ARMSubtarget; + +class ARMInstrInfo : public ARMBaseInstrInfo { + ARMRegisterInfo RI; +public: + explicit ARMInstrInfo(const ARMSubtarget &STI); + + // Return the non-pre/post incrementing version of 'Opc'. Return 0 + // if there is not such an opcode. + unsigned getUnindexedOpcode(unsigned Opc) const; + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + const ARMRegisterInfo &getRegisterInfo() const { return RI; } +}; + +} + +#endif diff --git a/final/lib/Target/ARM/ARMInstrInfo.td b/final/lib/Target/ARM/ARMInstrInfo.td new file mode 100644 index 00000000000..e0de65b865f --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrInfo.td @@ -0,0 +1,3940 @@ +//===- ARMInstrInfo.td - Target Description for ARM Target -*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// ARM specific DAG Nodes. +// + +// Type profiles. +def SDT_ARMCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>; +def SDT_ARMCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>, SDTCisVT<1, i32> ]>; + +def SDT_ARMSaveCallPC : SDTypeProfile<0, 1, []>; + +def SDT_ARMcall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>; + +def SDT_ARMCMov : SDTypeProfile<1, 3, + [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, + SDTCisVT<3, i32>]>; + +def SDT_ARMBrcond : SDTypeProfile<0, 2, + [SDTCisVT<0, OtherVT>, SDTCisVT<1, i32>]>; + +def SDT_ARMBrJT : SDTypeProfile<0, 3, + [SDTCisPtrTy<0>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>]>; + +def SDT_ARMBr2JT : SDTypeProfile<0, 4, + [SDTCisPtrTy<0>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; + +def SDT_ARMBCC_i64 : SDTypeProfile<0, 6, + [SDTCisVT<0, i32>, + SDTCisVT<1, i32>, SDTCisVT<2, i32>, + SDTCisVT<3, i32>, SDTCisVT<4, i32>, + SDTCisVT<5, OtherVT>]>; + +def SDT_ARMAnd : SDTypeProfile<1, 2, + [SDTCisVT<0, i32>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>]>; + +def SDT_ARMCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>; + +def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, + SDTCisPtrTy<1>, SDTCisVT<2, i32>]>; + +def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; +def SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisPtrTy<1>, + SDTCisInt<2>]>; +def SDT_ARMEH_SJLJ_Longjmp: SDTypeProfile<0, 2, [SDTCisPtrTy<0>, SDTCisInt<1>]>; + +def SDT_ARMEH_SJLJ_DispatchSetup: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + +def SDT_ARMMEMBARRIER : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + +def SDT_ARMTCRET : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>; + +def SDT_ARMBFI : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>]>; + +// Node definitions. +def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; +def ARMWrapperDYN : SDNode<"ARMISD::WrapperDYN", SDTIntUnaryOp>; +def ARMWrapperPIC : SDNode<"ARMISD::WrapperPIC", SDTIntUnaryOp>; +def ARMWrapperJT : SDNode<"ARMISD::WrapperJT", SDTIntBinOp>; + +def ARMcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARMCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def ARMcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_ARMCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def ARMcall : SDNode<"ARMISD::CALL", SDT_ARMcall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; +def ARMcall_pred : SDNode<"ARMISD::CALL_PRED", SDT_ARMcall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; +def ARMcall_nolink : SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; + +def ARMretflag : SDNode<"ARMISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; + +def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov, + [SDNPInGlue]>; + +def ARMbrcond : SDNode<"ARMISD::BRCOND", SDT_ARMBrcond, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>; + +def ARMbrjt : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT, + [SDNPHasChain]>; +def ARMbr2jt : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT, + [SDNPHasChain]>; + +def ARMBcci64 : SDNode<"ARMISD::BCC_i64", SDT_ARMBCC_i64, + [SDNPHasChain]>; + +def ARMcmp : SDNode<"ARMISD::CMP", SDT_ARMCmp, + [SDNPOutGlue]>; + +def ARMcmpZ : SDNode<"ARMISD::CMPZ", SDT_ARMCmp, + [SDNPOutGlue, SDNPCommutative]>; + +def ARMpic_add : SDNode<"ARMISD::PIC_ADD", SDT_ARMPICAdd>; + +def ARMsrl_flag : SDNode<"ARMISD::SRL_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>; +def ARMsra_flag : SDNode<"ARMISD::SRA_FLAG", SDTIntUnaryOp, [SDNPOutGlue]>; +def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInGlue ]>; + +def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>; +def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP", + SDT_ARMEH_SJLJ_Setjmp, [SDNPHasChain]>; +def ARMeh_sjlj_longjmp: SDNode<"ARMISD::EH_SJLJ_LONGJMP", + SDT_ARMEH_SJLJ_Longjmp, [SDNPHasChain]>; +def ARMeh_sjlj_dispatchsetup: SDNode<"ARMISD::EH_SJLJ_DISPATCHSETUP", + SDT_ARMEH_SJLJ_DispatchSetup, [SDNPHasChain]>; + + +def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER, + [SDNPHasChain]>; +def ARMMemBarrierMCR : SDNode<"ARMISD::MEMBARRIER_MCR", SDT_ARMMEMBARRIER, + [SDNPHasChain]>; +def ARMPreload : SDNode<"ARMISD::PRELOAD", SDTPrefetch, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore]>; + +def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>; + +def ARMtcret : SDNode<"ARMISD::TC_RETURN", SDT_ARMTCRET, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + + +def ARMbfi : SDNode<"ARMISD::BFI", SDT_ARMBFI>; + +//===----------------------------------------------------------------------===// +// ARM Instruction Predicate Definitions. +// +def HasV4T : Predicate<"Subtarget->hasV4TOps()">, AssemblerPredicate; +def NoV4T : Predicate<"!Subtarget->hasV4TOps()">; +def HasV5T : Predicate<"Subtarget->hasV5TOps()">; +def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">, AssemblerPredicate; +def HasV6 : Predicate<"Subtarget->hasV6Ops()">, AssemblerPredicate; +def NoV6 : Predicate<"!Subtarget->hasV6Ops()">; +def HasV6T2 : Predicate<"Subtarget->hasV6T2Ops()">, AssemblerPredicate; +def NoV6T2 : Predicate<"!Subtarget->hasV6T2Ops()">; +def HasV7 : Predicate<"Subtarget->hasV7Ops()">, AssemblerPredicate; +def NoVFP : Predicate<"!Subtarget->hasVFP2()">; +def HasVFP2 : Predicate<"Subtarget->hasVFP2()">, AssemblerPredicate; +def HasVFP3 : Predicate<"Subtarget->hasVFP3()">, AssemblerPredicate; +def HasNEON : Predicate<"Subtarget->hasNEON()">, AssemblerPredicate; +def HasFP16 : Predicate<"Subtarget->hasFP16()">, AssemblerPredicate; +def HasDivide : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate; +def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">, + AssemblerPredicate; +def HasDB : Predicate<"Subtarget->hasDataBarrier()">, + AssemblerPredicate; +def HasMP : Predicate<"Subtarget->hasMPExtension()">, + AssemblerPredicate; +def UseNEONForFP : Predicate<"Subtarget->useNEONForSinglePrecisionFP()">; +def DontUseNEONForFP : Predicate<"!Subtarget->useNEONForSinglePrecisionFP()">; +def IsThumb : Predicate<"Subtarget->isThumb()">, AssemblerPredicate; +def IsThumb1Only : Predicate<"Subtarget->isThumb1Only()">; +def IsThumb2 : Predicate<"Subtarget->isThumb2()">, AssemblerPredicate; +def IsARM : Predicate<"!Subtarget->isThumb()">, AssemblerPredicate; +def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">; +def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">; + +// FIXME: Eventually this will be just "hasV6T2Ops". +def UseMovt : Predicate<"Subtarget->useMovt()">; +def DontUseMovt : Predicate<"!Subtarget->useMovt()">; +def UseFPVMLx : Predicate<"Subtarget->useFPVMLx()">; + +//===----------------------------------------------------------------------===// +// ARM Flag Definitions. + +class RegConstraint { + string Constraints = C; +} + +//===----------------------------------------------------------------------===// +// ARM specific transformation functions and pattern fragments. +// + +// so_imm_neg_XFORM - Return a so_imm value packed into the format described for +// so_imm_neg def below. +def so_imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); +}]>; + +// so_imm_not_XFORM - Return a so_imm value packed into the format described for +// so_imm_not def below. +def so_imm_not_XFORM : SDNodeXFormgetTargetConstant(~(int)N->getZExtValue(), MVT::i32); +}]>; + +/// imm1_15 predicate - True if the 32-bit immediate is in the range [1,15]. +def imm1_15 : PatLeaf<(i32 imm), [{ + return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 16; +}]>; + +/// imm16_31 predicate - True if the 32-bit immediate is in the range [16,31]. +def imm16_31 : PatLeaf<(i32 imm), [{ + return (int32_t)N->getZExtValue() >= 16 && (int32_t)N->getZExtValue() < 32; +}]>; + +def so_imm_neg : + PatLeaf<(imm), [{ + return ARM_AM::getSOImmVal(-(uint32_t)N->getZExtValue()) != -1; + }], so_imm_neg_XFORM>; + +def so_imm_not : + PatLeaf<(imm), [{ + return ARM_AM::getSOImmVal(~(uint32_t)N->getZExtValue()) != -1; + }], so_imm_not_XFORM>; + +// sext_16_node predicate - True if the SDNode is sign-extended 16 or more bits. +def sext_16_node : PatLeaf<(i32 GPR:$a), [{ + return CurDAG->ComputeNumSignBits(SDValue(N,0)) >= 17; +}]>; + +/// Split a 32-bit immediate into two 16 bit parts. +def hi16 : SDNodeXFormgetTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32); +}]>; + +def lo16AllZero : PatLeaf<(i32 imm), [{ + // Returns true if all low 16-bits are 0. + return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0; +}], hi16>; + +/// imm0_65535 predicate - True if the 32-bit immediate is in the range +/// [0.65535]. +def imm0_65535 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 65536; +}]>; + +class BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; +class UnOpFrag : PatFrag<(ops node:$Src), res>; + +/// adde and sube predicates - True based on whether the carry flag output +/// will be needed or not. +def adde_dead_carry : + PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), + [{return !N->hasAnyUseOfValue(1);}]>; +def sube_dead_carry : + PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), + [{return !N->hasAnyUseOfValue(1);}]>; +def adde_live_carry : + PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), + [{return N->hasAnyUseOfValue(1);}]>; +def sube_live_carry : + PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), + [{return N->hasAnyUseOfValue(1);}]>; + +// An 'and' node with a single use. +def and_su : PatFrag<(ops node:$lhs, node:$rhs), (and node:$lhs, node:$rhs), [{ + return N->hasOneUse(); +}]>; + +// An 'xor' node with a single use. +def xor_su : PatFrag<(ops node:$lhs, node:$rhs), (xor node:$lhs, node:$rhs), [{ + return N->hasOneUse(); +}]>; + +// An 'fmul' node with a single use. +def fmul_su : PatFrag<(ops node:$lhs, node:$rhs), (fmul node:$lhs, node:$rhs),[{ + return N->hasOneUse(); +}]>; + +// An 'fadd' node which checks for single non-hazardous use. +def fadd_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fadd node:$lhs, node:$rhs),[{ + return hasNoVMLxHazardUse(N); +}]>; + +// An 'fsub' node which checks for single non-hazardous use. +def fsub_mlx : PatFrag<(ops node:$lhs, node:$rhs),(fsub node:$lhs, node:$rhs),[{ + return hasNoVMLxHazardUse(N); +}]>; + +//===----------------------------------------------------------------------===// +// Operand Definitions. +// + +// Branch target. +// FIXME: rename brtarget to t2_brtarget +def brtarget : Operand { + let EncoderMethod = "getBranchTargetOpValue"; +} + +// FIXME: get rid of this one? +def uncondbrtarget : Operand { + let EncoderMethod = "getUnconditionalBranchTargetOpValue"; +} + +// Branch target for ARM. Handles conditional/unconditional +def br_target : Operand { + let EncoderMethod = "getARMBranchTargetOpValue"; +} + +// Call target. +// FIXME: rename bltarget to t2_bl_target? +def bltarget : Operand { + // Encoded the same as branch targets. + let EncoderMethod = "getBranchTargetOpValue"; +} + +// Call target for ARM. Handles conditional/unconditional +// FIXME: rename bl_target to t2_bltarget? +def bl_target : Operand { + // Encoded the same as branch targets. + let EncoderMethod = "getARMBranchTargetOpValue"; +} + + +// A list of registers separated by comma. Used by load/store multiple. +def RegListAsmOperand : AsmOperandClass { + let Name = "RegList"; + let SuperClasses = []; +} + +def DPRRegListAsmOperand : AsmOperandClass { + let Name = "DPRRegList"; + let SuperClasses = []; +} + +def SPRRegListAsmOperand : AsmOperandClass { + let Name = "SPRRegList"; + let SuperClasses = []; +} + +def reglist : Operand { + let EncoderMethod = "getRegisterListOpValue"; + let ParserMatchClass = RegListAsmOperand; + let PrintMethod = "printRegisterList"; +} + +def dpr_reglist : Operand { + let EncoderMethod = "getRegisterListOpValue"; + let ParserMatchClass = DPRRegListAsmOperand; + let PrintMethod = "printRegisterList"; +} + +def spr_reglist : Operand { + let EncoderMethod = "getRegisterListOpValue"; + let ParserMatchClass = SPRRegListAsmOperand; + let PrintMethod = "printRegisterList"; +} + +// An operand for the CONSTPOOL_ENTRY pseudo-instruction. +def cpinst_operand : Operand { + let PrintMethod = "printCPInstOperand"; +} + +// Local PC labels. +def pclabel : Operand { + let PrintMethod = "printPCLabel"; +} + +// ADR instruction labels. +def adrlabel : Operand { + let EncoderMethod = "getAdrLabelOpValue"; +} + +def neon_vcvt_imm32 : Operand { + let EncoderMethod = "getNEONVcvtImm32OpValue"; +} + +// rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24. +def rot_imm : Operand, PatLeaf<(i32 imm), [{ + int32_t v = (int32_t)N->getZExtValue(); + return v == 8 || v == 16 || v == 24; }]> { + let EncoderMethod = "getRotImmOpValue"; +} + +// shift_imm: An integer that encodes a shift amount and the type of shift +// (currently either asr or lsl) using the same encoding used for the +// immediates in so_reg operands. +def shift_imm : Operand { + let PrintMethod = "printShiftImmOperand"; +} + +// shifter_operand operands: so_reg and so_imm. +def so_reg : Operand, // reg reg imm + ComplexPattern { + let EncoderMethod = "getSORegOpValue"; + let PrintMethod = "printSORegOperand"; + let MIOperandInfo = (ops GPR, GPR, i32imm); +} +def shift_so_reg : Operand, // reg reg imm + ComplexPattern { + let EncoderMethod = "getSORegOpValue"; + let PrintMethod = "printSORegOperand"; + let MIOperandInfo = (ops GPR, GPR, i32imm); +} + +// so_imm - Match a 32-bit shifter_operand immediate operand, which is an +// 8-bit immediate rotated by an arbitrary number of bits. +def so_imm : Operand, PatLeaf<(imm), [{ return Pred_so_imm(N); }]> { + let EncoderMethod = "getSOImmOpValue"; + let PrintMethod = "printSOImmOperand"; +} + +// Break so_imm's up into two pieces. This handles immediates with up to 16 +// bits set in them. This uses so_imm2part to match and so_imm2part_[12] to +// get the first/second pieces. +def so_imm2part : PatLeaf<(imm), [{ + return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); +}]>; + +/// arm_i32imm - True for +V6T2, or true only if so_imm2part is true. +/// +def arm_i32imm : PatLeaf<(imm), [{ + if (Subtarget->hasV6T2Ops()) + return true; + return ARM_AM::isSOImmTwoPartVal((unsigned)N->getZExtValue()); +}]>; + +/// imm0_31 predicate - True if the 32-bit immediate is in the range [0,31]. +def imm0_31 : Operand, PatLeaf<(imm), [{ + return (int32_t)N->getZExtValue() < 32; +}]>; + +/// imm0_31_m1 - Matches and prints like imm0_31, but encodes as 'value - 1'. +def imm0_31_m1 : Operand, PatLeaf<(imm), [{ + return (int32_t)N->getZExtValue() < 32; +}]> { + let EncoderMethod = "getImmMinusOneOpValue"; +} + +// i32imm_hilo16 - For movt/movw - sets the MC Encoder method. +// The imm is split into imm{15-12}, imm{11-0} +// +def i32imm_hilo16 : Operand { + let EncoderMethod = "getHiLo16ImmOpValue"; +} + +/// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield +/// e.g., 0xf000ffff +def bf_inv_mask_imm : Operand, + PatLeaf<(imm), [{ + return ARM::isBitFieldInvertedMask(N->getZExtValue()); +}] > { + let EncoderMethod = "getBitfieldInvertedMaskOpValue"; + let PrintMethod = "printBitfieldInvMaskImmOperand"; +} + +/// lsb_pos_imm - position of the lsb bit, used by BFI4p and t2BFI4p +def lsb_pos_imm : Operand, PatLeaf<(imm), [{ + return isInt<5>(N->getSExtValue()); +}]>; + +/// width_imm - number of bits to be copied, used by BFI4p and t2BFI4p +def width_imm : Operand, PatLeaf<(imm), [{ + return N->getSExtValue() > 0 && N->getSExtValue() <= 32; +}] > { + let EncoderMethod = "getMsbOpValue"; +} + +// Define ARM specific addressing modes. + + +// addrmode_imm12 := reg +/- imm12 +// +def addrmode_imm12 : Operand, + ComplexPattern { + // 12-bit immediate operand. Note that instructions using this encode + // #0 and #-0 differently. We flag #-0 as the magic value INT32_MIN. All other + // immediate values are as normal. + + let EncoderMethod = "getAddrModeImm12OpValue"; + let PrintMethod = "printAddrModeImm12Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); +} +// ldst_so_reg := reg +/- reg shop imm +// +def ldst_so_reg : Operand, + ComplexPattern { + let EncoderMethod = "getLdStSORegOpValue"; + // FIXME: Simplify the printer + let PrintMethod = "printAddrMode2Operand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + +// addrmode2 := reg +/- imm12 +// := reg +/- reg shop imm +// +def addrmode2 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrMode2OpValue"; + let PrintMethod = "printAddrMode2Operand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + +def am2offset : Operand, + ComplexPattern { + let EncoderMethod = "getAddrMode2OffsetOpValue"; + let PrintMethod = "printAddrMode2OffsetOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// addrmode3 := reg +/- reg +// addrmode3 := reg +/- imm8 +// +def addrmode3 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrMode3OpValue"; + let PrintMethod = "printAddrMode3Operand"; + let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); +} + +def am3offset : Operand, + ComplexPattern { + let EncoderMethod = "getAddrMode3OffsetOpValue"; + let PrintMethod = "printAddrMode3OffsetOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +// ldstm_mode := {ia, ib, da, db} +// +def ldstm_mode : OptionalDefOperand { + let EncoderMethod = "getLdStmModeOpValue"; + let PrintMethod = "printLdStmModeOperand"; +} + +def MemMode5AsmOperand : AsmOperandClass { + let Name = "MemMode5"; + let SuperClasses = []; +} + +// addrmode5 := reg +/- imm8*4 +// +def addrmode5 : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode5Operand"; + let MIOperandInfo = (ops GPR:$base, i32imm); + let ParserMatchClass = MemMode5AsmOperand; + let EncoderMethod = "getAddrMode5OpValue"; +} + +// addrmode6 := reg with optional alignment +// +def addrmode6 : Operand, + ComplexPattern{ + let PrintMethod = "printAddrMode6Operand"; + let MIOperandInfo = (ops GPR:$addr, i32imm); + let EncoderMethod = "getAddrMode6AddressOpValue"; +} + +def am6offset : Operand, + ComplexPattern { + let PrintMethod = "printAddrMode6OffsetOperand"; + let MIOperandInfo = (ops GPR); + let EncoderMethod = "getAddrMode6OffsetOpValue"; +} + +// Special version of addrmode6 to handle alignment encoding for VLD-dup +// instructions, specifically VLD4-dup. +def addrmode6dup : Operand, + ComplexPattern{ + let PrintMethod = "printAddrMode6Operand"; + let MIOperandInfo = (ops GPR:$addr, i32imm); + let EncoderMethod = "getAddrMode6DupAddressOpValue"; +} + +// addrmodepc := pc + reg +// +def addrmodepc : Operand, + ComplexPattern { + let PrintMethod = "printAddrModePCOperand"; + let MIOperandInfo = (ops GPR, i32imm); +} + +def nohash_imm : Operand { + let PrintMethod = "printNoHashImmediate"; +} + +def CoprocNumAsmOperand : AsmOperandClass { + let Name = "CoprocNum"; + let SuperClasses = []; + let ParserMethod = "tryParseCoprocNumOperand"; +} + +def CoprocRegAsmOperand : AsmOperandClass { + let Name = "CoprocReg"; + let SuperClasses = []; + let ParserMethod = "tryParseCoprocRegOperand"; +} + +def p_imm : Operand { + let PrintMethod = "printPImmediate"; + let ParserMatchClass = CoprocNumAsmOperand; +} + +def c_imm : Operand { + let PrintMethod = "printCImmediate"; + let ParserMatchClass = CoprocRegAsmOperand; +} + +//===----------------------------------------------------------------------===// + +include "ARMInstrFormats.td" + +//===----------------------------------------------------------------------===// +// Multiclass helpers... +// + +/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a +/// binop that produces a value. +multiclass AsI1_bin_irs opcod, string opc, + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, + PatFrag opnode, bit Commutable = 0> { + // The register-immediate version is re-materializable. This is useful + // in particular for taking the address of a local. + let isReMaterializable = 1 in { + def ri : AsI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-0} = imm; + } + } + def rr : AsI1 { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{25} = 0; + let isCommutable = Commutable; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rm; + } + def rs : AsI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-0} = shift; + } +} + +/// AI1_bin_s_irs - Similar to AsI1_bin_irs except it sets the 's' bit so the +/// instruction modifies the CPSR register. +let isCodeGenOnly = 1, Defs = [CPSR] in { +multiclass AI1_bin_s_irs opcod, string opc, + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, + PatFrag opnode, bit Commutable = 0> { + def ri : AI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-0} = imm; + } + def rr : AI1 { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let isCommutable = Commutable; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rm; + } + def rs : AI1 { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-0} = shift; + } +} +} + +/// AI1_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test +/// patterns. Similar to AsI1_bin_irs except the instruction does not produce +/// a explicit result, only implicitly set CPSR. +let isCompare = 1, Defs = [CPSR] in { +multiclass AI1_cmp_irs opcod, string opc, + InstrItinClass iii, InstrItinClass iir, InstrItinClass iis, + PatFrag opnode, bit Commutable = 0> { + def ri : AI1 { + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = 0b0000; + let Inst{11-0} = imm; + } + def rr : AI1 { + bits<4> Rn; + bits<4> Rm; + let isCommutable = Commutable; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = 0b0000; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rm; + } + def rs : AI1 { + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{19-16} = Rn; + let Inst{15-12} = 0b0000; + let Inst{11-0} = shift; + } +} +} + +/// AI_ext_rrot - A unary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +/// FIXME: Remove the 'r' variant. Its rot_imm is zero. +multiclass AI_ext_rrot opcod, string opc, PatFrag opnode> { + def r : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-10} = 0b00; + let Inst{3-0} = Rm; + } + def r_rot : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + bits<2> rot; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-10} = rot; + let Inst{3-0} = Rm; + } +} + +multiclass AI_ext_rrot_np opcod, string opc> { + def r : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{19-16} = 0b1111; + let Inst{11-10} = 0b00; + } + def r_rot : AExtI, + Requires<[IsARM, HasV6]> { + bits<2> rot; + let Inst{19-16} = 0b1111; + let Inst{11-10} = rot; + } +} + +/// AI_exta_rrot - A binary operation with two forms: one whose operand is a +/// register and one whose operand is a register rotated by 8/16/24. +multiclass AI_exta_rrot opcod, string opc, PatFrag opnode> { + def rr : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-10} = 0b00; + let Inst{9-4} = 0b000111; + let Inst{3-0} = Rm; + } + def rr_rot : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + bits<2> rot; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-10} = rot; + let Inst{9-4} = 0b000111; + let Inst{3-0} = Rm; + } +} + +// For disassembly only. +multiclass AI_exta_rrot_np opcod, string opc> { + def rr : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{11-10} = 0b00; + } + def rr_rot : AExtI, + Requires<[IsARM, HasV6]> { + bits<4> Rn; + bits<2> rot; + let Inst{19-16} = Rn; + let Inst{11-10} = rot; + } +} + +/// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. +let Uses = [CPSR] in { +multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def ri : AsI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; + } + def rr : AsI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let isCommutable = Commutable; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + } + def rs : AsI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + } +} +// Carry setting variants +let isCodeGenOnly = 1, Defs = [CPSR] in { +multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { + def Sri : AXI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; + let Inst{20} = 1; + let Inst{25} = 1; + } + def Srr : AXI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{11-4} = 0b00000000; + let isCommutable = Commutable; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{20} = 1; + let Inst{25} = 0; + } + def Srs : AXI1, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{20} = 1; + let Inst{25} = 0; + } +} +} +} + +let canFoldAsLoad = 1, isReMaterializable = 1 in { +multiclass AI_ldr1 { + // Note: We use the complex addrmode_imm12 rather than just an input + // GPR and a constrained immediate so that we can use this to match + // frame index references and avoid matching constant pool references. + def i12: AI2ldst<0b010, 1, isByte, (outs GPR:$Rt), (ins addrmode_imm12:$addr), + AddrMode_i12, LdFrm, iii, opc, "\t$Rt, $addr", + [(set GPR:$Rt, (opnode addrmode_imm12:$addr))]> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 + } + def rs : AI2ldst<0b011, 1, isByte, (outs GPR:$Rt), (ins ldst_so_reg:$shift), + AddrModeNone, LdFrm, iir, opc, "\t$Rt, $shift", + [(set GPR:$Rt, (opnode ldst_so_reg:$shift))]> { + bits<4> Rt; + bits<17> shift; + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{19-16} = shift{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = shift{11-0}; + } +} +} + +multiclass AI_str1 { + // Note: We use the complex addrmode_imm12 rather than just an input + // GPR and a constrained immediate so that we can use this to match + // frame index references and avoid matching constant pool references. + def i12 : AI2ldst<0b010, 0, isByte, (outs), + (ins GPR:$Rt, addrmode_imm12:$addr), + AddrMode_i12, StFrm, iii, opc, "\t$Rt, $addr", + [(opnode GPR:$Rt, addrmode_imm12:$addr)]> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 + } + def rs : AI2ldst<0b011, 0, isByte, (outs), (ins GPR:$Rt, ldst_so_reg:$shift), + AddrModeNone, StFrm, iir, opc, "\t$Rt, $shift", + [(opnode GPR:$Rt, ldst_so_reg:$shift)]> { + bits<4> Rt; + bits<17> shift; + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{19-16} = shift{16-13}; // Rn + let Inst{15-12} = Rt; + let Inst{11-0} = shift{11-0}; + } +} +//===----------------------------------------------------------------------===// +// Instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Miscellaneous Instructions. +// + +/// CONSTPOOL_ENTRY - This instruction represents a floating constant pool in +/// the function. The first operand is the ID# for this instruction, the second +/// is the index into the MachineConstantPool that this is, the third is the +/// size in bytes of this constant pool entry. +let neverHasSideEffects = 1, isNotDuplicable = 1 in +def CONSTPOOL_ENTRY : +PseudoInst<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, + i32imm:$size), NoItinerary, []>; + +// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE +// from removing one half of the matched pairs. That breaks PEI, which assumes +// these will always be in pairs, and asserts if it finds otherwise. Better way? +let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { +def ADJCALLSTACKUP : +PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2, pred:$p), NoItinerary, + [(ARMcallseq_end timm:$amt1, timm:$amt2)]>; + +def ADJCALLSTACKDOWN : +PseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary, + [(ARMcallseq_start timm:$amt)]>; +} + +def NOP : AI<(outs), (ins), MiscFrm, NoItinerary, "nop", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{15-8} = 0b11110000; + let Inst{7-0} = 0b00000000; +} + +def YIELD : AI<(outs), (ins), MiscFrm, NoItinerary, "yield", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{15-8} = 0b11110000; + let Inst{7-0} = 0b00000001; +} + +def WFE : AI<(outs), (ins), MiscFrm, NoItinerary, "wfe", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{15-8} = 0b11110000; + let Inst{7-0} = 0b00000010; +} + +def WFI : AI<(outs), (ins), MiscFrm, NoItinerary, "wfi", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{15-8} = 0b11110000; + let Inst{7-0} = 0b00000011; +} + +def SEL : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, NoItinerary, "sel", + "\t$dst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{27-20} = 0b01101000; + let Inst{7-4} = 0b1011; + let Inst{11-8} = 0b1111; +} + +def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{15-8} = 0b11110000; + let Inst{7-0} = 0b00000100; +} + +// The i32imm operand $val can be used by a debugger to store more information +// about the breakpoint. +def BKPT : AI<(outs), (ins i32imm:$val), MiscFrm, NoItinerary, "bkpt", "\t$val", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + bits<16> val; + let Inst{3-0} = val{3-0}; + let Inst{19-8} = val{15-4}; + let Inst{27-20} = 0b00010010; + let Inst{7-4} = 0b0111; +} + +// Change Processor State is a system instruction -- for disassembly and +// parsing only. +// FIXME: Since the asm parser has currently no clean way to handle optional +// operands, create 3 versions of the same instruction. Once there's a clean +// framework to represent optional operands, change this behavior. +class CPS + : AXI<(outs), iops, MiscFrm, NoItinerary, !strconcat("cps", asm_ops), + [/* For disassembly only; pattern left blank */]>, Requires<[IsARM]> { + bits<2> imod; + bits<3> iflags; + bits<5> mode; + bit M; + + let Inst{31-28} = 0b1111; + let Inst{27-20} = 0b00010000; + let Inst{19-18} = imod; + let Inst{17} = M; // Enabled if mode is set; + let Inst{16} = 0; + let Inst{8-6} = iflags; + let Inst{5} = 0; + let Inst{4-0} = mode; +} + +let M = 1 in + def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, i32imm:$mode), + "$imod\t$iflags, $mode">; +let mode = 0, M = 0 in + def CPS2p : CPS<(ins imod_op:$imod, iflags_op:$iflags), "$imod\t$iflags">; + +let imod = 0, iflags = 0, M = 1 in + def CPS1p : CPS<(ins i32imm:$mode), "\t$mode">; + +// Preload signals the memory system of possible future data/instruction access. +// These are for disassembly only. +multiclass APreLoad read, bits<1> data, string opc> { + + def i12 : AXI<(outs), (ins addrmode_imm12:$addr), MiscFrm, IIC_Preload, + !strconcat(opc, "\t$addr"), + [(ARMPreload addrmode_imm12:$addr, (i32 read), (i32 data))]> { + bits<4> Rt; + bits<17> addr; + let Inst{31-26} = 0b111101; + let Inst{25} = 0; // 0 for immediate form + let Inst{24} = data; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{22} = read; + let Inst{21-20} = 0b01; + let Inst{19-16} = addr{16-13}; // Rn + let Inst{15-12} = 0b1111; + let Inst{11-0} = addr{11-0}; // imm12 + } + + def rs : AXI<(outs), (ins ldst_so_reg:$shift), MiscFrm, IIC_Preload, + !strconcat(opc, "\t$shift"), + [(ARMPreload ldst_so_reg:$shift, (i32 read), (i32 data))]> { + bits<17> shift; + let Inst{31-26} = 0b111101; + let Inst{25} = 1; // 1 for register form + let Inst{24} = data; + let Inst{23} = shift{12}; // U (add = ('U' == 1)) + let Inst{22} = read; + let Inst{21-20} = 0b01; + let Inst{19-16} = shift{16-13}; // Rn + let Inst{15-12} = 0b1111; + let Inst{11-0} = shift{11-0}; + } +} + +defm PLD : APreLoad<1, 1, "pld">, Requires<[IsARM]>; +defm PLDW : APreLoad<0, 1, "pldw">, Requires<[IsARM,HasV7,HasMP]>; +defm PLI : APreLoad<1, 0, "pli">, Requires<[IsARM,HasV7]>; + +def SETEND : AXI<(outs),(ins setend_op:$end), MiscFrm, NoItinerary, + "setend\t$end", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + bits<1> end; + let Inst{31-10} = 0b1111000100000001000000; + let Inst{9} = end; + let Inst{8-0} = 0; +} + +def DBG : AI<(outs), (ins i32imm:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + bits<4> opt; + let Inst{27-4} = 0b001100100000111100001111; + let Inst{3-0} = opt; +} + +// A5.4 Permanently UNDEFINED instructions. +let isBarrier = 1, isTerminator = 1 in +def TRAP : AXI<(outs), (ins), MiscFrm, NoItinerary, + "trap", [(trap)]>, + Requires<[IsARM]> { + let Inst = 0xe7ffdefe; +} + +// Address computation and loads and stores in PIC mode. +let isNotDuplicable = 1 in { +def PICADD : ARMPseudoInst<(outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p), + Size4Bytes, IIC_iALUr, + [(set GPR:$dst, (ARMpic_add GPR:$a, imm:$cp))]>; + +let AddedComplexity = 10 in { +def PICLDR : ARMPseudoInst<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iLoad_r, + [(set GPR:$dst, (load addrmodepc:$addr))]>; + +def PICLDRH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iLoad_bh_r, + [(set GPR:$Rt, (zextloadi16 addrmodepc:$addr))]>; + +def PICLDRB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iLoad_bh_r, + [(set GPR:$Rt, (zextloadi8 addrmodepc:$addr))]>; + +def PICLDRSH : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iLoad_bh_r, + [(set GPR:$Rt, (sextloadi16 addrmodepc:$addr))]>; + +def PICLDRSB : ARMPseudoInst<(outs GPR:$Rt), (ins addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iLoad_bh_r, + [(set GPR:$Rt, (sextloadi8 addrmodepc:$addr))]>; +} +let AddedComplexity = 10 in { +def PICSTR : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iStore_r, [(store GPR:$src, addrmodepc:$addr)]>; + +def PICSTRH : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iStore_bh_r, [(truncstorei16 GPR:$src, + addrmodepc:$addr)]>; + +def PICSTRB : ARMPseudoInst<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p), + Size4Bytes, IIC_iStore_bh_r, [(truncstorei8 GPR:$src, addrmodepc:$addr)]>; +} +} // isNotDuplicable = 1 + + +// LEApcrel - Load a pc-relative address into a register without offending the +// assembler. +let neverHasSideEffects = 1, isReMaterializable = 1 in +// The 'adr' mnemonic encodes differently if the label is before or after +// the instruction. The {24-21} opcode bits are set by the fixup, as we don't +// know until then which form of the instruction will be used. +def ADR : AI1<0, (outs GPR:$Rd), (ins adrlabel:$label), + MiscFrm, IIC_iALUi, "adr", "\t$Rd, #$label", []> { + bits<4> Rd; + bits<12> label; + let Inst{27-25} = 0b001; + let Inst{20} = 0; + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rd; + let Inst{11-0} = label; +} +def LEApcrel : ARMPseudoInst<(outs GPR:$Rd), (ins i32imm:$label, pred:$p), + Size4Bytes, IIC_iALUi, []>; + +def LEApcrelJT : ARMPseudoInst<(outs GPR:$Rd), + (ins i32imm:$label, nohash_imm:$id, pred:$p), + Size4Bytes, IIC_iALUi, []>; + +//===----------------------------------------------------------------------===// +// Control Flow Instructions. +// + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + // ARMV4T and above + def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "bx", "\tlr", [(ARMretflag)]>, + Requires<[IsARM, HasV4T]> { + let Inst{27-0} = 0b0001001011111111111100011110; + } + + // ARMV4 only + def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "mov", "\tpc, lr", [(ARMretflag)]>, + Requires<[IsARM, NoV4T]> { + let Inst{27-0} = 0b0001101000001111000000001110; + } +} + +// Indirect branches +let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + // ARMV4T and above + def BX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst", + [(brind GPR:$dst)]>, + Requires<[IsARM, HasV4T]> { + bits<4> dst; + let Inst{31-4} = 0b1110000100101111111111110001; + let Inst{3-0} = dst; + } + + // ARMV4 only + // FIXME: We would really like to define this as a vanilla ARMPat like: + // ARMPat<(brind GPR:$dst), (MOVr PC, GPR:$dst)> + // With that, however, we can't set isBranch, isTerminator, etc.. + def MOVPCRX : ARMPseudoInst<(outs), (ins GPR:$dst), + Size4Bytes, IIC_Br, [(brind GPR:$dst)]>, + Requires<[IsARM, NoV4T]>; +} + +// All calls clobber the non-callee saved registers. SP is marked as +// a use to prevent stack-pointer assignments that appear immediately +// before calls from potentially appearing dead. +let isCall = 1, + // On non-Darwin platforms R9 is callee-saved. + Defs = [R0, R1, R2, R3, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR], + Uses = [SP] in { + def BL : ABXI<0b1011, (outs), (ins bl_target:$func, variable_ops), + IIC_Br, "bl\t$func", + [(ARMcall tglobaladdr:$func)]>, + Requires<[IsARM, IsNotDarwin]> { + let Inst{31-28} = 0b1110; + bits<24> func; + let Inst{23-0} = func; + } + + def BL_pred : ABI<0b1011, (outs), (ins bl_target:$func, variable_ops), + IIC_Br, "bl", "\t$func", + [(ARMcall_pred tglobaladdr:$func)]>, + Requires<[IsARM, IsNotDarwin]> { + bits<24> func; + let Inst{23-0} = func; + } + + // ARMv5T and above + def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx\t$func", + [(ARMcall GPR:$func)]>, + Requires<[IsARM, HasV5T, IsNotDarwin]> { + bits<4> func; + let Inst{31-4} = 0b1110000100101111111111110011; + let Inst{3-0} = func; + } + + def BLX_pred : AI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx", "\t$func", + [(ARMcall_pred GPR:$func)]>, + Requires<[IsARM, HasV5T, IsNotDarwin]> { + bits<4> func; + let Inst{27-4} = 0b000100101111111111110011; + let Inst{3-0} = func; + } + + // ARMv4T + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), + Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, HasV4T, IsNotDarwin]>; + + // ARMv4 + def BMOVPCRX_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), + Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsNotDarwin]>; +} + +let isCall = 1, + // On Darwin R9 is call-clobbered. + // R7 is marked as a use to prevent frame-pointer assignments from being + // moved above / below calls. + Defs = [R0, R1, R2, R3, R9, R12, LR, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR], + Uses = [R7, SP] in { + def BLr9 : ABXI<0b1011, (outs), (ins bltarget:$func, variable_ops), + IIC_Br, "bl\t$func", + [(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]> { + let Inst{31-28} = 0b1110; + bits<24> func; + let Inst{23-0} = func; + } + + def BLr9_pred : ABI<0b1011, (outs), (ins bltarget:$func, variable_ops), + IIC_Br, "bl", "\t$func", + [(ARMcall_pred tglobaladdr:$func)]>, + Requires<[IsARM, IsDarwin]> { + bits<24> func; + let Inst{23-0} = func; + } + + // ARMv5T and above + def BLXr9 : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx\t$func", + [(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]> { + bits<4> func; + let Inst{31-4} = 0b1110000100101111111111110011; + let Inst{3-0} = func; + } + + def BLXr9_pred : AI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm, + IIC_Br, "blx", "\t$func", + [(ARMcall_pred GPR:$func)]>, + Requires<[IsARM, HasV5T, IsDarwin]> { + bits<4> func; + let Inst{27-4} = 0b000100101111111111110011; + let Inst{3-0} = func; + } + + // ARMv4T + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), + Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, HasV4T, IsDarwin]>; + + // ARMv4 + def BMOVPCRXr9_CALL : ARMPseudoInst<(outs), (ins tGPR:$func, variable_ops), + Size8Bytes, IIC_Br, [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsDarwin]>; +} + +// Tail calls. + +// FIXME: These should probably be xformed into the non-TC versions of the +// instructions as part of MC lowering. +// FIXME: These seem to be used for both Thumb and ARM instruction selection. +// Thumb should have its own version since the instruction is actually +// different, even though the mnemonic is the same. +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in { + // Darwin versions. + let Defs = [R0, R1, R2, R3, R9, R12, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, + D27, D28, D29, D30, D31, PC], + Uses = [SP] in { + def TCRETURNdi : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), + IIC_Br, []>, Requires<[IsDarwin]>; + + def TCRETURNri : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + IIC_Br, []>, Requires<[IsDarwin]>; + + def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), + IIC_Br, "b\t$dst @ TAILCALL", + []>, Requires<[IsARM, IsDarwin]>; + + def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), + IIC_Br, "b.w\t$dst @ TAILCALL", + []>, Requires<[IsThumb, IsDarwin]>; + + def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops), + BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL", + []>, Requires<[IsDarwin]> { + bits<4> dst; + let Inst{31-4} = 0b1110000100101111111111110001; + let Inst{3-0} = dst; + } + } + + // Non-Darwin versions (the difference is R9). + let Defs = [R0, R1, R2, R3, R12, + D0, D1, D2, D3, D4, D5, D6, D7, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, + D27, D28, D29, D30, D31, PC], + Uses = [SP] in { + def TCRETURNdiND : PseudoInst<(outs), (ins i32imm:$dst, variable_ops), + IIC_Br, []>, Requires<[IsNotDarwin]>; + + def TCRETURNriND : PseudoInst<(outs), (ins tcGPR:$dst, variable_ops), + IIC_Br, []>, Requires<[IsNotDarwin]>; + + def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), + IIC_Br, "b\t$dst @ TAILCALL", + []>, Requires<[IsARM, IsNotDarwin]>; + + def TAILJMPdNDt : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops), + IIC_Br, "b.w\t$dst @ TAILCALL", + []>, Requires<[IsThumb, IsNotDarwin]>; + + def TAILJMPrND : AXI<(outs), (ins tcGPR:$dst, variable_ops), + BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL", + []>, Requires<[IsNotDarwin]> { + bits<4> dst; + let Inst{31-4} = 0b1110000100101111111111110001; + let Inst{3-0} = dst; + } + } +} + +let isBranch = 1, isTerminator = 1 in { + // B is "predicable" since it can be xformed into a Bcc. + let isBarrier = 1 in { + let isPredicable = 1 in + def B : ABXI<0b1010, (outs), (ins brtarget:$target), IIC_Br, + "b\t$target", [(br bb:$target)]> { + bits<24> target; + let Inst{31-28} = 0b1110; + let Inst{23-0} = target; + } + + let isNotDuplicable = 1, isIndirectBranch = 1 in { + def BR_JTr : ARMPseudoInst<(outs), + (ins GPR:$target, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, + [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>; + // FIXME: This shouldn't use the generic "addrmode2," but rather be split + // into i12 and rs suffixed versions. + def BR_JTm : ARMPseudoInst<(outs), + (ins addrmode2:$target, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, + [(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt, + imm:$id)]>; + def BR_JTadd : ARMPseudoInst<(outs), + (ins GPR:$target, GPR:$idx, i32imm:$jt, i32imm:$id), + SizeSpecial, IIC_Br, + [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, + imm:$id)]>; + } // isNotDuplicable = 1, isIndirectBranch = 1 + } // isBarrier = 1 + + // FIXME: should be able to write a pattern for ARMBrcond, but can't use + // a two-value operand where a dag node expects two operands. :( + def Bcc : ABI<0b1010, (outs), (ins br_target:$target), + IIC_Br, "b", "\t$target", + [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { + bits<24> target; + let Inst{23-0} = target; + } +} + +// Branch and Exchange Jazelle -- for disassembly only +def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0010; + //let Inst{19-8} = 0xfff; + let Inst{7-4} = 0b0010; +} + +// Secure Monitor Call is a system instruction -- for disassembly only +def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", + [/* For disassembly only; pattern left blank */]> { + bits<4> opt; + let Inst{23-4} = 0b01100000000000000111; + let Inst{3-0} = opt; +} + +// Supervisor Call (Software Interrupt) -- for disassembly only +let isCall = 1, Uses = [SP] in { +def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", + [/* For disassembly only; pattern left blank */]> { + bits<24> svc; + let Inst{23-0} = svc; +} +} + +// Store Return State is a system instruction -- for disassembly only +let isCodeGenOnly = 1 in { // FIXME: This should not use submode! +def SRSW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), + NoItinerary, "srs${amode}\tsp!, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b110; // W = 1 +} + +def SRS : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, i32imm:$mode), + NoItinerary, "srs${amode}\tsp, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b100; // W = 0 +} + +// Return From Exception is a system instruction -- for disassembly only +def RFEW : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), + NoItinerary, "rfe${amode}\t$base!", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b011; // W = 1 +} + +def RFE : ABXI<{1,0,0,?}, (outs), (ins ldstm_mode:$amode, GPR:$base), + NoItinerary, "rfe${amode}\t$base", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b001; // W = 0 +} +} // isCodeGenOnly = 1 + +//===----------------------------------------------------------------------===// +// Load / store Instructions. +// + +// Load + + +defm LDR : AI_ldr1<0, "ldr", IIC_iLoad_r, IIC_iLoad_si, + UnOpFrag<(load node:$Src)>>; +defm LDRB : AI_ldr1<1, "ldrb", IIC_iLoad_bh_r, IIC_iLoad_bh_si, + UnOpFrag<(zextloadi8 node:$Src)>>; +defm STR : AI_str1<0, "str", IIC_iStore_r, IIC_iStore_si, + BinOpFrag<(store node:$LHS, node:$RHS)>>; +defm STRB : AI_str1<1, "strb", IIC_iStore_bh_r, IIC_iStore_bh_si, + BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; + +// Special LDR for loads from non-pc-relative constpools. +let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1, + isReMaterializable = 1 in +def LDRcp : AI2ldst<0b010, 1, 0, (outs GPR:$Rt), (ins addrmode_imm12:$addr), + AddrMode_i12, LdFrm, IIC_iLoad_r, "ldr", "\t$Rt, $addr", + []> { + bits<4> Rt; + bits<17> addr; + let Inst{23} = addr{12}; // U (add = ('U' == 1)) + let Inst{19-16} = 0b1111; + let Inst{15-12} = Rt; + let Inst{11-0} = addr{11-0}; // imm12 +} + +// Loads with zero extension +def LDRH : AI3ld<0b1011, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoad_bh_r, "ldrh", "\t$Rt, $addr", + [(set GPR:$Rt, (zextloadi16 addrmode3:$addr))]>; + +// Loads with sign extension +def LDRSH : AI3ld<0b1111, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoad_bh_r, "ldrsh", "\t$Rt, $addr", + [(set GPR:$Rt, (sextloadi16 addrmode3:$addr))]>; + +def LDRSB : AI3ld<0b1101, 1, (outs GPR:$Rt), (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoad_bh_r, "ldrsb", "\t$Rt, $addr", + [(set GPR:$Rt, (sextloadi8 addrmode3:$addr))]>; + +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, + isCodeGenOnly = 1 in { // $dst2 doesn't exist in asmstring? +// FIXME: $dst2 isn't in the asm string as it's implied by $Rd (dst2 = Rd+1) +// how to represent that such that tblgen is happy and we don't +// mark this codegen only? +// Load doubleword +def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rd, GPR:$dst2), + (ins addrmode3:$addr), LdMiscFrm, + IIC_iLoad_d_r, "ldrd", "\t$Rd, $addr", + []>, Requires<[IsARM, HasV5TE]>; +} + +// Indexed loads +multiclass AI2_ldridx { + def _PRE : AI2ldstidx<1, isByte, 1, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addrmode2:$addr), IndexModePre, LdFrm, itin, + opc, "\t$Rt, $addr!", "$addr.base = $Rn_wb", []> { + // {17-14} Rn + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<18> addr; + let Inst{25} = addr{13}; + let Inst{23} = addr{12}; + let Inst{19-16} = addr{17-14}; + let Inst{11-0} = addr{11-0}; + } + def _POST : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins GPR:$Rn, am2offset:$offset), + IndexModePost, LdFrm, itin, + opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> { + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> Rn; + let Inst{25} = offset{13}; + let Inst{23} = offset{12}; + let Inst{19-16} = Rn; + let Inst{11-0} = offset{11-0}; + } +} + +let mayLoad = 1, neverHasSideEffects = 1 in { +defm LDR : AI2_ldridx<0, "ldr", IIC_iLoad_ru>; +defm LDRB : AI2_ldridx<1, "ldrb", IIC_iLoad_bh_ru>; +} + +multiclass AI3_ldridx op, bit op20, string opc, InstrItinClass itin> { + def _PRE : AI3ldstidx { + bits<14> addr; + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + let Inst{19-16} = addr{12-9}; // Rn + let Inst{11-8} = addr{7-4}; // imm7_4/zero + let Inst{3-0} = addr{3-0}; // imm3_0/Rm + } + def _POST : AI3ldstidx { + bits<10> offset; + bits<4> Rn; + let Inst{23} = offset{8}; // U bit + let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm + let Inst{19-16} = Rn; + let Inst{11-8} = offset{7-4}; // imm7_4/zero + let Inst{3-0} = offset{3-0}; // imm3_0/Rm + } +} + +let mayLoad = 1, neverHasSideEffects = 1 in { +defm LDRH : AI3_ldridx<0b1011, 1, "ldrh", IIC_iLoad_bh_ru>; +defm LDRSH : AI3_ldridx<0b1111, 1, "ldrsh", IIC_iLoad_bh_ru>; +defm LDRSB : AI3_ldridx<0b1101, 1, "ldrsb", IIC_iLoad_bh_ru>; +let hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in +defm LDRD : AI3_ldridx<0b1101, 0, "ldrd", IIC_iLoad_d_ru>; +} // mayLoad = 1, neverHasSideEffects = 1 + +// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only. +let mayLoad = 1, neverHasSideEffects = 1 in { +def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am2offset:$offset), IndexModeNone, + LdFrm, IIC_iLoad_ru, + "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} +def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am2offset:$offset), IndexModeNone, + LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} +def LDRSBT : AI3ldstidx<0b1101, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am3offset:$offset), IndexModePost, + LdMiscFrm, IIC_iLoad_bh_ru, + "ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} +def LDRHT : AI3ldstidx<0b1011, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am3offset:$offset), IndexModePost, + LdMiscFrm, IIC_iLoad_bh_ru, + "ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} +def LDRSHT : AI3ldstidx<0b1111, 1, 1, 0, (outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am3offset:$offset), IndexModePost, + LdMiscFrm, IIC_iLoad_bh_ru, + "ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} +} + +// Store + +// Stores with truncate +def STRH : AI3str<0b1011, (outs), (ins GPR:$Rt, addrmode3:$addr), StMiscFrm, + IIC_iStore_bh_r, "strh", "\t$Rt, $addr", + [(truncstorei16 GPR:$Rt, addrmode3:$addr)]>; + +// Store doubleword +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, + isCodeGenOnly = 1 in // $src2 doesn't exist in asm string +def STRD : AI3str<0b1111, (outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr), + StMiscFrm, IIC_iStore_d_r, + "strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>; + +// Indexed stores +def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + IndexModePre, StFrm, IIC_iStore_ru, + "str", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, + (pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; + +def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + IndexModePost, StFrm, IIC_iStore_ru, + "str", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, + (post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; + +def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + IndexModePre, StFrm, IIC_iStore_bh_ru, + "strb", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, + GPR:$Rn, am2offset:$offset))]>; +def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + IndexModePost, StFrm, IIC_iStore_bh_ru, + "strb", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, + GPR:$Rn, am2offset:$offset))]>; + +def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), + IndexModePre, StMiscFrm, IIC_iStore_ru, + "strh", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, + (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; + +def STRH_POST: AI3stridx<0b1011, 0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), + IndexModePost, StMiscFrm, IIC_iStore_bh_ru, + "strh", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, + GPR:$Rn, am3offset:$offset))]>; + +// For disassembly only +def STRD_PRE : AI3stdpr<(outs GPR:$base_wb), + (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), + StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$src1, $src2, [$base, $offset]!", + "$base = $base_wb", []>; + +// For disassembly only +def STRD_POST: AI3stdpo<(outs GPR:$base_wb), + (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), + StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$src1, $src2, [$base], $offset", + "$base = $base_wb", []>; + +// STRT, STRBT, and STRHT are for disassembly only. + +def STRT : AI2stridx<0, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn,am2offset:$offset), + IndexModeNone, StFrm, IIC_iStore_ru, + "strt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + +def STRBT : AI2stridx<1, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), + IndexModeNone, StFrm, IIC_iStore_bh_ru, + "strbt", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + +def STRHT: AI3sthpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am3offset:$offset), + StMiscFrm, IIC_iStore_bh_ru, + "strht", "\t$src, [$base], $offset", "$base = $base_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +multiclass arm_ldst_mult { + def IA : + AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeNone, f, itin, + !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 0; // No writeback + let Inst{20} = L_bit; + } + def IA_UPD : + AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeUpd, f, itin_upd, + !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 1; // Writeback + let Inst{20} = L_bit; + } + def DA : + AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeNone, f, itin, + !strconcat(asm, "da${p}\t$Rn, $regs"), "", []> { + let Inst{24-23} = 0b00; // Decrement After + let Inst{21} = 0; // No writeback + let Inst{20} = L_bit; + } + def DA_UPD : + AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeUpd, f, itin_upd, + !strconcat(asm, "da${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b00; // Decrement After + let Inst{21} = 1; // Writeback + let Inst{20} = L_bit; + } + def DB : + AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeNone, f, itin, + !strconcat(asm, "db${p}\t$Rn, $regs"), "", []> { + let Inst{24-23} = 0b10; // Decrement Before + let Inst{21} = 0; // No writeback + let Inst{20} = L_bit; + } + def DB_UPD : + AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeUpd, f, itin_upd, + !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b10; // Decrement Before + let Inst{21} = 1; // Writeback + let Inst{20} = L_bit; + } + def IB : + AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeNone, f, itin, + !strconcat(asm, "ib${p}\t$Rn, $regs"), "", []> { + let Inst{24-23} = 0b11; // Increment Before + let Inst{21} = 0; // No writeback + let Inst{20} = L_bit; + } + def IB_UPD : + AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + IndexModeUpd, f, itin_upd, + !strconcat(asm, "ib${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + let Inst{24-23} = 0b11; // Increment Before + let Inst{21} = 1; // Writeback + let Inst{20} = L_bit; + } +} + +let neverHasSideEffects = 1 in { + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +defm LDM : arm_ldst_mult<"ldm", 1, LdStMulFrm, IIC_iLoad_m, IIC_iLoad_mu>; + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>; + +} // neverHasSideEffects + +// Load / Store Multiple Mnemonic Aliases +def : MnemonicAlias<"ldm", "ldmia">; +def : MnemonicAlias<"stm", "stmia">; + +// FIXME: remove when we have a way to marking a MI with these properties. +// FIXME: Should pc be an implicit operand like PICADD, etc? +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in +// FIXME: Should be a pseudo-instruction. +def LDMIA_RET : AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$regs, variable_ops), + IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr, + "ldmia${p}\t$Rn!, $regs", + "$Rn = $wb", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 1; // Writeback + let Inst{20} = 1; // Load +} + +//===----------------------------------------------------------------------===// +// Move Instructions. +// + +let neverHasSideEffects = 1 in +def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr, + "mov", "\t$Rd, $Rm", []>, UnaryDP { + bits<4> Rd; + bits<4> Rm; + + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; +} + +// A version for the smaller set of tail call registers. +let neverHasSideEffects = 1 in +def MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm, + IIC_iMOVr, "mov", "\t$Rd, $Rm", []>, UnaryDP { + bits<4> Rd; + bits<4> Rm; + + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; +} + +def MOVs : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg:$src), + DPSoRegFrm, IIC_iMOVsr, + "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg:$src)]>, + UnaryDP { + bits<4> Rd; + bits<12> src; + let Inst{15-12} = Rd; + let Inst{11-0} = src; + let Inst{25} = 0; +} + +let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in +def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, + "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP { + bits<4> Rd; + bits<12> imm; + let Inst{25} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = 0b0000; + let Inst{11-0} = imm; +} + +let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in +def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm_hilo16:$imm), + DPFrm, IIC_iMOVi, + "movw", "\t$Rd, $imm", + [(set GPR:$Rd, imm0_65535:$imm)]>, + Requires<[IsARM, HasV6T2]>, UnaryDP { + bits<4> Rd; + bits<16> imm; + let Inst{15-12} = Rd; + let Inst{11-0} = imm{11-0}; + let Inst{19-16} = imm{15-12}; + let Inst{20} = 0; + let Inst{25} = 1; +} + +def MOVi16_ga_pcrel : PseudoInst<(outs GPR:$Rd), + (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>; + +let Constraints = "$src = $Rd" in { +def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm_hilo16:$imm), + DPFrm, IIC_iMOVi, + "movt", "\t$Rd, $imm", + [(set GPR:$Rd, + (or (and GPR:$src, 0xffff), + lo16AllZero:$imm))]>, UnaryDP, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<16> imm; + let Inst{15-12} = Rd; + let Inst{11-0} = imm{11-0}; + let Inst{19-16} = imm{15-12}; + let Inst{20} = 0; + let Inst{25} = 1; +} + +def MOVTi16_ga_pcrel : PseudoInst<(outs GPR:$Rd), + (ins GPR:$src, i32imm:$addr, pclabel:$id), IIC_iMOVi, []>; + +} // Constraints + +def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>, + Requires<[IsARM, HasV6T2]>; + +let Uses = [CPSR] in +def RRX: PseudoInst<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVsi, + [(set GPR:$Rd, (ARMrrx GPR:$Rm))]>, UnaryDP, + Requires<[IsARM]>; + +// These aren't really mov instructions, but we have to define them this way +// due to flag operands. + +let Defs = [CPSR] in { +def MOVsrl_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP, + Requires<[IsARM]>; +def MOVsra_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, + [(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP, + Requires<[IsARM]>; +} + +//===----------------------------------------------------------------------===// +// Extend Instructions. +// + +// Sign extenders + +defm SXTB : AI_ext_rrot<0b01101010, + "sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; +defm SXTH : AI_ext_rrot<0b01101011, + "sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; + +defm SXTAB : AI_exta_rrot<0b01101010, + "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; +defm SXTAH : AI_exta_rrot<0b01101011, + "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; + +// For disassembly only +defm SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">; + +// For disassembly only +defm SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">; + +// Zero extenders + +let AddedComplexity = 16 in { +defm UXTB : AI_ext_rrot<0b01101110, + "uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; +defm UXTH : AI_ext_rrot<0b01101111, + "uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; +defm UXTB16 : AI_ext_rrot<0b01101100, + "uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; + +// FIXME: This pattern incorrectly assumes the shl operator is a rotate. +// The transformation should probably be done as a combiner action +// instead so we can include a check for masking back in the upper +// eight bits of the source into the lower eight bits of the result. +//def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), +// (UXTB16r_rot GPR:$Src, 24)>; +def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), + (UXTB16r_rot GPR:$Src, 8)>; + +defm UXTAB : AI_exta_rrot<0b01101110, "uxtab", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; +defm UXTAH : AI_exta_rrot<0b01101111, "uxtah", + BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; +} + +// This isn't safe in general, the add is two 16-bit units, not a 32-bit add. +// For disassembly only +defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">; + + +def SBFX : I<(outs GPR:$Rd), + (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<4> Rn; + bits<5> lsb; + bits<5> width; + let Inst{27-21} = 0b0111101; + let Inst{6-4} = 0b101; + let Inst{20-16} = width; + let Inst{15-12} = Rd; + let Inst{11-7} = lsb; + let Inst{3-0} = Rn; +} + +def UBFX : I<(outs GPR:$Rd), + (ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<4> Rn; + bits<5> lsb; + bits<5> width; + let Inst{27-21} = 0b0111111; + let Inst{6-4} = 0b101; + let Inst{20-16} = width; + let Inst{15-12} = Rd; + let Inst{11-7} = lsb; + let Inst{3-0} = Rn; +} + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions. +// + +defm ADD : AsI1_bin_irs<0b0100, "add", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; +defm SUB : AsI1_bin_irs<0b0010, "sub", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(sub node:$LHS, node:$RHS)>>; + +// ADD and SUB with 's' bit set. +defm ADDS : AI1_bin_s_irs<0b0100, "adds", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; +defm SUBS : AI1_bin_s_irs<0b0010, "subs", + IIC_iALUi, IIC_iALUr, IIC_iALUsr, + BinOpFrag<(subc node:$LHS, node:$RHS)>>; + +defm ADC : AI1_adde_sube_irs<0b0101, "adc", + BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; +defm SBC : AI1_adde_sube_irs<0b0110, "sbc", + BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; + +// ADC and SUBC with 's' bit set. +defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs", + BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; +defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs", + BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; + +def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, + IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm", + [(set GPR:$Rd, (sub so_imm:$imm, GPR:$Rn))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; +} + +// The reg/reg form is only defined for the disassembler; for codegen it is +// equivalent to SUBrr. +def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, + IIC_iALUr, "rsb", "\t$Rd, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} + +def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift", + [(set GPR:$Rd, (sub so_reg:$shift, GPR:$Rn))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} + +// RSB with 's' bit set. +let isCodeGenOnly = 1, Defs = [CPSR] in { +def RSBSri : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, + IIC_iALUi, "rsbs", "\t$Rd, $Rn, $imm", + [(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; +} +def RSBSrr : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, + IIC_iALUr, "rsbs", "\t$Rd, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} +def RSBSrs : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + DPSoRegFrm, IIC_iALUsr, "rsbs", "\t$Rd, $Rn, $shift", + [(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} +} + +let Uses = [CPSR] in { +def RSCri : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), + DPFrm, IIC_iALUi, "rsc", "\t$Rd, $Rn, $imm", + [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; +} +// The reg/reg form is only defined for the disassembler; for codegen it is +// equivalent to SUBrr. +def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + DPFrm, IIC_iALUr, "rsc", "\t$Rd, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{11-4} = 0b00000000; + let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} +def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift", + [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} +} + +// FIXME: Allow these to be predicated. +let isCodeGenOnly = 1, Defs = [CPSR], Uses = [CPSR] in { +def RSCSri : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), + DPFrm, IIC_iALUi, "rscs\t$Rd, $Rn, $imm", + [(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; + let Inst{11-0} = imm; +} +def RSCSrs : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), + DPSoRegFrm, IIC_iALUsr, "rscs\t$Rd, $Rn, $shift", + [(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>, + Requires<[IsARM]> { + bits<4> Rd; + bits<4> Rn; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 1; + let Inst{11-0} = shift; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; +} +} + +// (sub X, imm) gets canonicalized to (add X, -imm). Match this form. +// The assume-no-carry-in form uses the negation of the input since add/sub +// assume opposite meanings of the carry flag (i.e., carry == !borrow). +// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory +// details. +def : ARMPat<(add GPR:$src, so_imm_neg:$imm), + (SUBri GPR:$src, so_imm_neg:$imm)>; +def : ARMPat<(addc GPR:$src, so_imm_neg:$imm), + (SUBSri GPR:$src, so_imm_neg:$imm)>; +// The with-carry-in form matches bitwise not instead of the negation. +// Effectively, the inverse interpretation of the carry flag already accounts +// for part of the negation. +def : ARMPat<(adde GPR:$src, so_imm_not:$imm), + (SBCri GPR:$src, so_imm_not:$imm)>; + +// Note: These are implemented in C++ code, because they have to generate +// ADD/SUBrs instructions, which use a complex pattern that a xform function +// cannot produce. +// (mul X, 2^n+1) -> (add (X << n), X) +// (mul X, 2^n-1) -> (rsb X, (X << n)) + +// ARM Arithmetic Instruction -- for disassembly only +// GPR:$dst = GPR:$a op GPR:$b +class AAI op27_20, bits<8> op11_4, string opc, + list pattern = [/* For disassembly only; pattern left blank */], + dag iops = (ins GPR:$Rn, GPR:$Rm), string asm = "\t$Rd, $Rn, $Rm"> + : AI<(outs GPR:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern> { + bits<4> Rn; + bits<4> Rd; + bits<4> Rm; + let Inst{27-20} = op27_20; + let Inst{11-4} = op11_4; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{3-0} = Rm; +} + +// Saturating add/subtract -- for disassembly only + +def QADD : AAI<0b00010000, 0b00000101, "qadd", + [(set GPR:$Rd, (int_arm_qadd GPR:$Rm, GPR:$Rn))], + (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">; +def QSUB : AAI<0b00010010, 0b00000101, "qsub", + [(set GPR:$Rd, (int_arm_qsub GPR:$Rm, GPR:$Rn))], + (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">; +def QDADD : AAI<0b00010100, 0b00000101, "qdadd", [], (ins GPR:$Rm, GPR:$Rn), + "\t$Rd, $Rm, $Rn">; +def QDSUB : AAI<0b00010110, 0b00000101, "qdsub", [], (ins GPR:$Rm, GPR:$Rn), + "\t$Rd, $Rm, $Rn">; + +def QADD16 : AAI<0b01100010, 0b11110001, "qadd16">; +def QADD8 : AAI<0b01100010, 0b11111001, "qadd8">; +def QASX : AAI<0b01100010, 0b11110011, "qasx">; +def QSAX : AAI<0b01100010, 0b11110101, "qsax">; +def QSUB16 : AAI<0b01100010, 0b11110111, "qsub16">; +def QSUB8 : AAI<0b01100010, 0b11111111, "qsub8">; +def UQADD16 : AAI<0b01100110, 0b11110001, "uqadd16">; +def UQADD8 : AAI<0b01100110, 0b11111001, "uqadd8">; +def UQASX : AAI<0b01100110, 0b11110011, "uqasx">; +def UQSAX : AAI<0b01100110, 0b11110101, "uqsax">; +def UQSUB16 : AAI<0b01100110, 0b11110111, "uqsub16">; +def UQSUB8 : AAI<0b01100110, 0b11111111, "uqsub8">; + +// Signed/Unsigned add/subtract -- for disassembly only + +def SASX : AAI<0b01100001, 0b11110011, "sasx">; +def SADD16 : AAI<0b01100001, 0b11110001, "sadd16">; +def SADD8 : AAI<0b01100001, 0b11111001, "sadd8">; +def SSAX : AAI<0b01100001, 0b11110101, "ssax">; +def SSUB16 : AAI<0b01100001, 0b11110111, "ssub16">; +def SSUB8 : AAI<0b01100001, 0b11111111, "ssub8">; +def UASX : AAI<0b01100101, 0b11110011, "uasx">; +def UADD16 : AAI<0b01100101, 0b11110001, "uadd16">; +def UADD8 : AAI<0b01100101, 0b11111001, "uadd8">; +def USAX : AAI<0b01100101, 0b11110101, "usax">; +def USUB16 : AAI<0b01100101, 0b11110111, "usub16">; +def USUB8 : AAI<0b01100101, 0b11111111, "usub8">; + +// Signed/Unsigned halving add/subtract -- for disassembly only + +def SHASX : AAI<0b01100011, 0b11110011, "shasx">; +def SHADD16 : AAI<0b01100011, 0b11110001, "shadd16">; +def SHADD8 : AAI<0b01100011, 0b11111001, "shadd8">; +def SHSAX : AAI<0b01100011, 0b11110101, "shsax">; +def SHSUB16 : AAI<0b01100011, 0b11110111, "shsub16">; +def SHSUB8 : AAI<0b01100011, 0b11111111, "shsub8">; +def UHASX : AAI<0b01100111, 0b11110011, "uhasx">; +def UHADD16 : AAI<0b01100111, 0b11110001, "uhadd16">; +def UHADD8 : AAI<0b01100111, 0b11111001, "uhadd8">; +def UHSAX : AAI<0b01100111, 0b11110101, "uhsax">; +def UHSUB16 : AAI<0b01100111, 0b11110111, "uhsub16">; +def UHSUB8 : AAI<0b01100111, 0b11111111, "uhsub8">; + +// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only + +def USAD8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + MulFrm /* for convenience */, NoItinerary, "usad8", + "\t$Rd, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + let Inst{27-20} = 0b01111000; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b0001; + let Inst{19-16} = Rd; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +def USADA8 : AI<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + MulFrm /* for convenience */, NoItinerary, "usada8", + "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[IsARM, HasV6]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + bits<4> Ra; + let Inst{27-20} = 0b01111000; + let Inst{7-4} = 0b0001; + let Inst{19-16} = Rd; + let Inst{15-12} = Ra; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} + +// Signed/Unsigned saturate -- for disassembly only + +def SSAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh), + SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $a$sh", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<5> sat_imm; + bits<4> Rn; + bits<8> sh; + let Inst{27-21} = 0b0110101; + let Inst{5-4} = 0b01; + let Inst{20-16} = sat_imm; + let Inst{15-12} = Rd; + let Inst{11-7} = sh{7-3}; + let Inst{6} = sh{0}; + let Inst{3-0} = Rn; +} + +def SSAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$Rn), SatFrm, + NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<4> sat_imm; + bits<4> Rn; + let Inst{27-20} = 0b01101010; + let Inst{11-4} = 0b11110011; + let Inst{15-12} = Rd; + let Inst{19-16} = sat_imm; + let Inst{3-0} = Rn; +} + +def USAT : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a, shift_imm:$sh), + SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $a$sh", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<5> sat_imm; + bits<4> Rn; + bits<8> sh; + let Inst{27-21} = 0b0110111; + let Inst{5-4} = 0b01; + let Inst{15-12} = Rd; + let Inst{11-7} = sh{7-3}; + let Inst{6} = sh{0}; + let Inst{20-16} = sat_imm; + let Inst{3-0} = Rn; +} + +def USAT16 : AI<(outs GPR:$Rd), (ins i32imm:$sat_imm, GPR:$a), SatFrm, + NoItinerary, "usat16", "\t$Rd, $sat_imm, $a", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + bits<4> sat_imm; + bits<4> Rn; + let Inst{27-20} = 0b01101110; + let Inst{11-4} = 0b11110011; + let Inst{15-12} = Rd; + let Inst{19-16} = sat_imm; + let Inst{3-0} = Rn; +} + +def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>; +def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>; + +//===----------------------------------------------------------------------===// +// Bitwise Instructions. +// + +defm AND : AsI1_bin_irs<0b0000, "and", + IIC_iBITi, IIC_iBITr, IIC_iBITsr, + BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; +defm ORR : AsI1_bin_irs<0b1100, "orr", + IIC_iBITi, IIC_iBITr, IIC_iBITsr, + BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; +defm EOR : AsI1_bin_irs<0b0001, "eor", + IIC_iBITi, IIC_iBITr, IIC_iBITsr, + BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; +defm BIC : AsI1_bin_irs<0b1110, "bic", + IIC_iBITi, IIC_iBITr, IIC_iBITsr, + BinOpFrag<(and node:$LHS, (not node:$RHS))>>; + +def BFC : I<(outs GPR:$Rd), (ins GPR:$src, bf_inv_mask_imm:$imm), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfc", "\t$Rd, $imm", "$src = $Rd", + [(set GPR:$Rd, (and GPR:$src, bf_inv_mask_imm:$imm))]>, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<10> imm; + let Inst{27-21} = 0b0111110; + let Inst{6-0} = 0b0011111; + let Inst{15-12} = Rd; + let Inst{11-7} = imm{4-0}; // lsb + let Inst{20-16} = imm{9-5}; // width +} + +// A8.6.18 BFI - Bitfield insert (Encoding A1) +def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd", + [(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn, + bf_inv_mask_imm:$imm))]>, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<4> Rn; + bits<10> imm; + let Inst{27-21} = 0b0111110; + let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15 + let Inst{15-12} = Rd; + let Inst{11-7} = imm{4-0}; // lsb + let Inst{20-16} = imm{9-5}; // width + let Inst{3-0} = Rn; +} + +// GNU as only supports this form of bfi (w/ 4 arguments) +let isAsmParserOnly = 1 in +def BFI4p : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, + lsb_pos_imm:$lsb, width_imm:$width), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfi", "\t$Rd, $Rn, $lsb, $width", "$src = $Rd", + []>, Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<4> Rn; + bits<5> lsb; + bits<5> width; + let Inst{27-21} = 0b0111110; + let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15 + let Inst{15-12} = Rd; + let Inst{11-7} = lsb; + let Inst{20-16} = width; // Custom encoder => lsb+width-1 + let Inst{3-0} = Rn; +} + +def MVNr : AsI1<0b1111, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMVNr, + "mvn", "\t$Rd, $Rm", + [(set GPR:$Rd, (not GPR:$Rm))]>, UnaryDP { + bits<4> Rd; + bits<4> Rm; + let Inst{25} = 0; + let Inst{19-16} = 0b0000; + let Inst{11-4} = 0b00000000; + let Inst{15-12} = Rd; + let Inst{3-0} = Rm; +} +def MVNs : AsI1<0b1111, (outs GPR:$Rd), (ins so_reg:$shift), DPSoRegFrm, + IIC_iMVNsr, "mvn", "\t$Rd, $shift", + [(set GPR:$Rd, (not so_reg:$shift))]>, UnaryDP { + bits<4> Rd; + bits<12> shift; + let Inst{25} = 0; + let Inst{19-16} = 0b0000; + let Inst{15-12} = Rd; + let Inst{11-0} = shift; +} +let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in +def MVNi : AsI1<0b1111, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, + IIC_iMVNi, "mvn", "\t$Rd, $imm", + [(set GPR:$Rd, so_imm_not:$imm)]>,UnaryDP { + bits<4> Rd; + bits<12> imm; + let Inst{25} = 1; + let Inst{19-16} = 0b0000; + let Inst{15-12} = Rd; + let Inst{11-0} = imm; +} + +def : ARMPat<(and GPR:$src, so_imm_not:$imm), + (BICri GPR:$src, so_imm_not:$imm)>; + +//===----------------------------------------------------------------------===// +// Multiply Instructions. +// +class AsMul1I32 opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : AsMul1I { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + let Inst{19-16} = Rd; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +class AsMul1I64 opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : AsMul1I { + bits<4> RdLo; + bits<4> RdHi; + bits<4> Rm; + bits<4> Rn; + let Inst{19-16} = RdHi; + let Inst{15-12} = RdLo; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} + +let isCommutable = 1 in { +let Constraints = "@earlyclobber $Rd" in +def MULv5: ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, + pred:$p, cc_out:$s), + Size4Bytes, IIC_iMUL32, + [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>, + Requires<[IsARM, NoV6]>; + +def MUL : AsMul1I32<0b0000000, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL32, "mul", "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (mul GPR:$Rn, GPR:$Rm))]>, + Requires<[IsARM, HasV6]>; +} + +let Constraints = "@earlyclobber $Rd" in +def MLAv5: ARMPseudoInst<(outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMAC32, + [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, + Requires<[IsARM, NoV6]> { + bits<4> Ra; + let Inst{15-12} = Ra; +} +def MLA : AsMul1I32<0b0000001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "mla", "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add (mul GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, + Requires<[IsARM, HasV6]> { + bits<4> Ra; + let Inst{15-12} = Ra; +} + +def MLS : AMul1I<0b0000011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "mls", "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (sub GPR:$Ra, (mul GPR:$Rn, GPR:$Rm)))]>, + Requires<[IsARM, HasV6T2]> { + bits<4> Rd; + bits<4> Rm; + bits<4> Rn; + bits<4> Ra; + let Inst{19-16} = Rd; + let Inst{15-12} = Ra; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} + +// Extra precision multiplies with low / high results + +let neverHasSideEffects = 1 in { +let isCommutable = 1 in { +let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { +def SMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMUL64, []>, + Requires<[IsARM, NoV6]>; + +def UMULLv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMUL64, []>, + Requires<[IsARM, NoV6]>; +} + +def SMULL : AsMul1I64<0b0000110, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, + "smull", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]>; + +def UMULL : AsMul1I64<0b0000100, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), IIC_iMUL64, + "umull", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]>; +} + +// Multiply + accumulate +let Constraints = "@earlyclobber $RdLo,@earlyclobber $RdHi" in { +def SMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMAC64, []>, + Requires<[IsARM, NoV6]>; +def UMLALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMAC64, []>, + Requires<[IsARM, NoV6]>; +def UMAALv5 : ARMPseudoInst<(outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + Size4Bytes, IIC_iMAC64, []>, + Requires<[IsARM, NoV6]>; + +} + +def SMLAL : AsMul1I64<0b0000111, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64, + "smlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]>; +def UMLAL : AsMul1I64<0b0000101, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64, + "umlal", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]>; + +def UMAAL : AMul1I <0b0000010, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), IIC_iMAC64, + "umaal", "\t$RdLo, $RdHi, $Rn, $Rm", []>, + Requires<[IsARM, HasV6]> { + bits<4> RdLo; + bits<4> RdHi; + bits<4> Rm; + bits<4> Rn; + let Inst{19-16} = RdLo; + let Inst{15-12} = RdHi; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +} // neverHasSideEffects + +// Most significant word multiply +def SMMUL : AMul2I <0b0111010, 0b0001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (mulhs GPR:$Rn, GPR:$Rm))]>, + Requires<[IsARM, HasV6]> { + let Inst{15-12} = 0b1111; +} + +def SMMULR : AMul2I <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + let Inst{15-12} = 0b1111; +} + +def SMMLA : AMul2Ia <0b0111010, 0b0001, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add (mulhs GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, + Requires<[IsARM, HasV6]>; + +def SMMLAR : AMul2Ia <0b0111010, 0b0011, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]>; + +def SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (sub GPR:$Ra, (mulhs GPR:$Rn, GPR:$Rm)))]>, + Requires<[IsARM, HasV6]>; + +def SMMLSR : AMul2Ia <0b0111010, 0b1111, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]>; + +multiclass AI_smul { + def BB : AMulxyI<0b0001011, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16), + (sext_inreg GPR:$Rm, i16)))]>, + Requires<[IsARM, HasV5TE]>; + + def BT : AMulxyI<0b0001011, 0b10, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (opnode (sext_inreg GPR:$Rn, i16), + (sra GPR:$Rm, (i32 16))))]>, + Requires<[IsARM, HasV5TE]>; + + def TB : AMulxyI<0b0001011, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)), + (sext_inreg GPR:$Rm, i16)))]>, + Requires<[IsARM, HasV5TE]>; + + def TT : AMulxyI<0b0001011, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (opnode (sra GPR:$Rn, (i32 16)), + (sra GPR:$Rm, (i32 16))))]>, + Requires<[IsARM, HasV5TE]>; + + def WB : AMulxyI<0b0001001, 0b01, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (sra (opnode GPR:$Rn, + (sext_inreg GPR:$Rm, i16)), (i32 16)))]>, + Requires<[IsARM, HasV5TE]>; + + def WT : AMulxyI<0b0001001, 0b11, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + IIC_iMUL16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm", + [(set GPR:$Rd, (sra (opnode GPR:$Rn, + (sra GPR:$Rm, (i32 16))), (i32 16)))]>, + Requires<[IsARM, HasV5TE]>; +} + + +multiclass AI_smla { + def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, + (opnode (sext_inreg GPR:$Rn, i16), + (sext_inreg GPR:$Rm, i16))))]>, + Requires<[IsARM, HasV5TE]>; + + def BT : AMulxyIa<0b0001000, 0b10, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, (opnode (sext_inreg GPR:$Rn, i16), + (sra GPR:$Rm, (i32 16)))))]>, + Requires<[IsARM, HasV5TE]>; + + def TB : AMulxyIa<0b0001000, 0b01, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)), + (sext_inreg GPR:$Rm, i16))))]>, + Requires<[IsARM, HasV5TE]>; + + def TT : AMulxyIa<0b0001000, 0b11, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)), + (sra GPR:$Rm, (i32 16)))))]>, + Requires<[IsARM, HasV5TE]>; + + def WB : AMulxyIa<0b0001001, 0b00, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn, + (sext_inreg GPR:$Rm, i16)), (i32 16))))]>, + Requires<[IsARM, HasV5TE]>; + + def WT : AMulxyIa<0b0001001, 0b10, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra", + [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn, + (sra GPR:$Rm, (i32 16))), (i32 16))))]>, + Requires<[IsARM, HasV5TE]>; +} + +defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; +defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; + +// Halfword multiply accumulate long: SMLAL -- for disassembly only +def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), + IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]>; + +def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), + IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]>; + +def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), + IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]>; + +def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPR:$RdLo, GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), + IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]>; + +// Helper class for AI_smld -- for disassembly only +class AMulDualIbase + : AI, Requires<[IsARM, HasV6]> { + bits<4> Rn; + bits<4> Rm; + let Inst{4} = 1; + let Inst{5} = swap; + let Inst{6} = sub; + let Inst{7} = 0; + let Inst{21-20} = 0b00; + let Inst{22} = long; + let Inst{27-23} = 0b01110; + let Inst{11-8} = Rm; + let Inst{3-0} = Rn; +} +class AMulDualI + : AMulDualIbase { + bits<4> Rd; + let Inst{15-12} = 0b1111; + let Inst{19-16} = Rd; +} +class AMulDualIa + : AMulDualIbase { + bits<4> Ra; + let Inst{15-12} = Ra; +} +class AMulDualI64 + : AMulDualIbase { + bits<4> RdLo; + bits<4> RdHi; + let Inst{19-16} = RdHi; + let Inst{15-12} = RdLo; +} + +multiclass AI_smld { + + def D : AMulDualIa<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm, $Ra">; + + def DX: AMulDualIa<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), + NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm, $Ra">; + + def LD: AMulDualI64<1, sub, 0, (outs GPR:$RdLo,GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), NoItinerary, + !strconcat(opc, "ld"), "\t$RdLo, $RdHi, $Rn, $Rm">; + + def LDX : AMulDualI64<1, sub, 1, (outs GPR:$RdLo,GPR:$RdHi), + (ins GPR:$Rn, GPR:$Rm), NoItinerary, + !strconcat(opc, "ldx"),"\t$RdLo, $RdHi, $Rn, $Rm">; + +} + +defm SMLA : AI_smld<0, "smla">; +defm SMLS : AI_smld<1, "smls">; + +multiclass AI_sdml { + + def D : AMulDualI<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">; + def DX : AMulDualI<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), + NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">; +} + +defm SMUA : AI_sdml<0, "smua">; +defm SMUS : AI_sdml<1, "smus">; + +//===----------------------------------------------------------------------===// +// Misc. Arithmetic Instructions. +// + +def CLZ : AMiscA1I<0b000010110, 0b0001, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "clz", "\t$Rd, $Rm", + [(set GPR:$Rd, (ctlz GPR:$Rm))]>, Requires<[IsARM, HasV5T]>; + +def RBIT : AMiscA1I<0b01101111, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rbit", "\t$Rd, $Rm", + [(set GPR:$Rd, (ARMrbit GPR:$Rm))]>, + Requires<[IsARM, HasV6T2]>; + +def REV : AMiscA1I<0b01101011, 0b0011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rev", "\t$Rd, $Rm", + [(set GPR:$Rd, (bswap GPR:$Rm))]>, Requires<[IsARM, HasV6]>; + +def REV16 : AMiscA1I<0b01101011, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "rev16", "\t$Rd, $Rm", + [(set GPR:$Rd, + (or (and (srl GPR:$Rm, (i32 8)), 0xFF), + (or (and (shl GPR:$Rm, (i32 8)), 0xFF00), + (or (and (srl GPR:$Rm, (i32 8)), 0xFF0000), + (and (shl GPR:$Rm, (i32 8)), 0xFF000000)))))]>, + Requires<[IsARM, HasV6]>; + +def REVSH : AMiscA1I<0b01101111, 0b1011, (outs GPR:$Rd), (ins GPR:$Rm), + IIC_iUNAr, "revsh", "\t$Rd, $Rm", + [(set GPR:$Rd, + (sext_inreg + (or (srl (and GPR:$Rm, 0xFF00), (i32 8)), + (shl GPR:$Rm, (i32 8))), i16))]>, + Requires<[IsARM, HasV6]>; + +def lsl_shift_imm : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(Sh, MVT::i32); +}]>; + +def lsl_amt : PatLeaf<(i32 imm), [{ + return (N->getZExtValue() < 32); +}], lsl_shift_imm>; + +def PKHBT : APKHI<0b01101000, 0, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), + IIC_iALUsi, "pkhbt", "\t$Rd, $Rn, $Rm$sh", + [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF), + (and (shl GPR:$Rm, lsl_amt:$sh), + 0xFFFF0000)))]>, + Requires<[IsARM, HasV6]>; + +// Alternate cases for PKHBT where identities eliminate some nodes. +def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (and GPR:$Rm, 0xFFFF0000)), + (PKHBT GPR:$Rn, GPR:$Rm, 0)>; +def : ARMV6Pat<(or (and GPR:$Rn, 0xFFFF), (shl GPR:$Rm, imm16_31:$sh)), + (PKHBT GPR:$Rn, GPR:$Rm, (lsl_shift_imm imm16_31:$sh))>; + +def asr_shift_imm : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(Sh, MVT::i32); +}]>; + +def asr_amt : PatLeaf<(i32 imm), [{ + return (N->getZExtValue() <= 32); +}], asr_shift_imm>; + +// Note: Shifts of 1-15 bits will be transformed to srl instead of sra and +// will match the pattern below. +def PKHTB : APKHI<0b01101000, 1, (outs GPR:$Rd), + (ins GPR:$Rn, GPR:$Rm, shift_imm:$sh), + IIC_iBITsi, "pkhtb", "\t$Rd, $Rn, $Rm$sh", + [(set GPR:$Rd, (or (and GPR:$Rn, 0xFFFF0000), + (and (sra GPR:$Rm, asr_amt:$sh), + 0xFFFF)))]>, + Requires<[IsARM, HasV6]>; + +// Alternate cases for PKHTB where identities eliminate some nodes. Note that +// a shift amount of 0 is *not legal* here, it is PKHBT instead. +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, imm16_31:$sh)), + (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm16_31:$sh))>; +def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), + (and (srl GPR:$src2, imm1_15:$sh), 0xFFFF)), + (PKHTB GPR:$src1, GPR:$src2, (asr_shift_imm imm1_15:$sh))>; + +//===----------------------------------------------------------------------===// +// Comparison Instructions... +// + +defm CMP : AI1_cmp_irs<0b1010, "cmp", + IIC_iCMPi, IIC_iCMPr, IIC_iCMPsr, + BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; + +// ARMcmpZ can re-use the above instruction definitions. +def : ARMPat<(ARMcmpZ GPR:$src, so_imm:$imm), + (CMPri GPR:$src, so_imm:$imm)>; +def : ARMPat<(ARMcmpZ GPR:$src, GPR:$rhs), + (CMPrr GPR:$src, GPR:$rhs)>; +def : ARMPat<(ARMcmpZ GPR:$src, so_reg:$rhs), + (CMPrs GPR:$src, so_reg:$rhs)>; + +// FIXME: We have to be careful when using the CMN instruction and comparison +// with 0. One would expect these two pieces of code should give identical +// results: +// +// rsbs r1, r1, 0 +// cmp r0, r1 +// mov r0, #0 +// it ls +// mov r0, #1 +// +// and: +// +// cmn r0, r1 +// mov r0, #0 +// it ls +// mov r0, #1 +// +// However, the CMN gives the *opposite* result when r1 is 0. This is because +// the carry flag is set in the CMP case but not in the CMN case. In short, the +// CMP instruction doesn't perform a truncate of the (logical) NOT of 0 plus the +// value of r0 and the carry bit (because the "carry bit" parameter to +// AddWithCarry is defined as 1 in this case, the carry flag will always be set +// when r0 >= 0). The CMN instruction doesn't perform a NOT of 0 so there is +// never a "carry" when this AddWithCarry is performed (because the "carry bit" +// parameter to AddWithCarry is defined as 0). +// +// When x is 0 and unsigned: +// +// x = 0 +// ~x = 0xFFFF FFFF +// ~x + 1 = 0x1 0000 0000 +// (-x = 0) != (0x1 0000 0000 = ~x + 1) +// +// Therefore, we should disable CMN when comparing against zero, until we can +// limit when the CMN instruction is used (when we know that the RHS is not 0 or +// when it's a comparison which doesn't look at the 'carry' flag). +// +// (See the ARM docs for the "AddWithCarry" pseudo-code.) +// +// This is related to . +// +//defm CMN : AI1_cmp_irs<0b1011, "cmn", +// BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; + +// Note that TST/TEQ don't set all the same flags that CMP does! +defm TST : AI1_cmp_irs<0b1000, "tst", + IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr, + BinOpFrag<(ARMcmpZ (and_su node:$LHS, node:$RHS), 0)>, 1>; +defm TEQ : AI1_cmp_irs<0b1001, "teq", + IIC_iTSTi, IIC_iTSTr, IIC_iTSTsr, + BinOpFrag<(ARMcmpZ (xor_su node:$LHS, node:$RHS), 0)>, 1>; + +defm CMNz : AI1_cmp_irs<0b1011, "cmn", + IIC_iCMPi, IIC_iCMPr, IIC_iCMPsr, + BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; + +//def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), +// (CMNri GPR:$src, so_imm_neg:$imm)>; + +def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm), + (CMNzri GPR:$src, so_imm_neg:$imm)>; + +// Pseudo i64 compares for some floating point compares. +let usesCustomInserter = 1, isBranch = 1, isTerminator = 1, + Defs = [CPSR] in { +def BCCi64 : PseudoInst<(outs), + (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, brtarget:$dst), + IIC_Br, + [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, bb:$dst)]>; + +def BCCZi64 : PseudoInst<(outs), + (ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, brtarget:$dst), IIC_Br, + [(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, 0, 0, bb:$dst)]>; +} // usesCustomInserter + + +// Conditional moves +// FIXME: should be able to write a pattern for ARMcmov, but can't use +// a two-value operand where a dag node expects two operands. :( +// FIXME: These should all be pseudo-instructions that get expanded to +// the normal MOV instructions. That would fix the dependency on +// special casing them in tblgen. +let neverHasSideEffects = 1 in { +def MOVCCr : AI1<0b1101, (outs GPR:$Rd), (ins GPR:$false, GPR:$Rm), DPFrm, + IIC_iCMOVr, "mov", "\t$Rd, $Rm", + [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">, UnaryDP { + bits<4> Rd; + bits<4> Rm; + let Inst{25} = 0; + let Inst{20} = 0; + let Inst{15-12} = Rd; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rm; +} + +def MOVCCs : AI1<0b1101, (outs GPR:$Rd), + (ins GPR:$false, so_reg:$shift), DPSoRegFrm, IIC_iCMOVsr, + "mov", "\t$Rd, $shift", + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_reg:$shift, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">, UnaryDP { + bits<4> Rd; + bits<12> shift; + let Inst{25} = 0; + let Inst{20} = 0; + let Inst{19-16} = 0; + let Inst{15-12} = Rd; + let Inst{11-0} = shift; +} + +let isMoveImm = 1 in +def MOVCCi16 : AI1<0b1000, (outs GPR:$Rd), (ins GPR:$false, i32imm_hilo16:$imm), + DPFrm, IIC_iMOVi, + "movw", "\t$Rd, $imm", + []>, + RegConstraint<"$false = $Rd">, Requires<[IsARM, HasV6T2]>, + UnaryDP { + bits<4> Rd; + bits<16> imm; + let Inst{25} = 1; + let Inst{20} = 0; + let Inst{19-16} = imm{15-12}; + let Inst{15-12} = Rd; + let Inst{11-0} = imm{11-0}; +} + +let isMoveImm = 1 in +def MOVCCi : AI1<0b1101, (outs GPR:$Rd), + (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi, + "mov", "\t$Rd, $imm", + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm:$imm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">, UnaryDP { + bits<4> Rd; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 0; + let Inst{19-16} = 0b0000; + let Inst{15-12} = Rd; + let Inst{11-0} = imm; +} + +// Two instruction predicate mov immediate. +let isMoveImm = 1 in +def MOVCCi32imm : PseudoInst<(outs GPR:$Rd), + (ins GPR:$false, i32imm:$src, pred:$p), + IIC_iCMOVix2, []>, RegConstraint<"$false = $Rd">; + +let isMoveImm = 1 in +def MVNCCi : AI1<0b1111, (outs GPR:$Rd), + (ins GPR:$false, so_imm:$imm), DPFrm, IIC_iCMOVi, + "mvn", "\t$Rd, $imm", + [/*(set GPR:$Rd, (ARMcmov GPR:$false, so_imm_not:$imm, imm:$cc, CCR:$ccr))*/]>, + RegConstraint<"$false = $Rd">, UnaryDP { + bits<4> Rd; + bits<12> imm; + let Inst{25} = 1; + let Inst{20} = 0; + let Inst{19-16} = 0b0000; + let Inst{15-12} = Rd; + let Inst{11-0} = imm; +} +} // neverHasSideEffects + +//===----------------------------------------------------------------------===// +// Atomic operations intrinsics +// + +def memb_opt : Operand { + let PrintMethod = "printMemBOption"; + let ParserMatchClass = MemBarrierOptOperand; +} + +// memory barriers protect the atomic sequences +let hasSideEffects = 1 in { +def DMB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, + "dmb", "\t$opt", [(ARMMemBarrier (i32 imm:$opt))]>, + Requires<[IsARM, HasDB]> { + bits<4> opt; + let Inst{31-4} = 0xf57ff05; + let Inst{3-0} = opt; +} + +def DMB_MCR : AInoP<(outs), (ins GPR:$zero), MiscFrm, NoItinerary, + "mcr", "\tp15, 0, $zero, c7, c10, 5", + [(ARMMemBarrierMCR GPR:$zero)]>, + Requires<[IsARM, HasV6]> { + // FIXME: add encoding +} +} + +def DSB : AInoP<(outs), (ins memb_opt:$opt), MiscFrm, NoItinerary, + "dsb", "\t$opt", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasDB]> { + bits<4> opt; + let Inst{31-4} = 0xf57ff04; + let Inst{3-0} = opt; +} + +// ISB has only full system option -- for disassembly only +def ISB : AInoP<(outs), (ins), MiscFrm, NoItinerary, "isb", "", []>, + Requires<[IsARM, HasDB]> { + let Inst{31-4} = 0xf57ff06; + let Inst{3-0} = 0b1111; +} + +let usesCustomInserter = 1 in { + let Uses = [CPSR] in { + def ATOMIC_LOAD_ADD_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_add_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_SUB_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_sub_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_AND_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_and_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_OR_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_or_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_XOR_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_xor_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_NAND_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_nand_8 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_ADD_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_add_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_SUB_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_sub_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_AND_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_and_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_OR_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_or_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_XOR_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_xor_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_NAND_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_nand_16 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_ADD_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_SUB_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_sub_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_AND_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_and_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_OR_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_or_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_XOR_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_xor_32 GPR:$ptr, GPR:$incr))]>; + def ATOMIC_LOAD_NAND_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$incr), NoItinerary, + [(set GPR:$dst, (atomic_load_nand_32 GPR:$ptr, GPR:$incr))]>; + + def ATOMIC_SWAP_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_swap_8 GPR:$ptr, GPR:$new))]>; + def ATOMIC_SWAP_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_swap_16 GPR:$ptr, GPR:$new))]>; + def ATOMIC_SWAP_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_swap_32 GPR:$ptr, GPR:$new))]>; + + def ATOMIC_CMP_SWAP_I8 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_cmp_swap_8 GPR:$ptr, GPR:$old, GPR:$new))]>; + def ATOMIC_CMP_SWAP_I16 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_cmp_swap_16 GPR:$ptr, GPR:$old, GPR:$new))]>; + def ATOMIC_CMP_SWAP_I32 : PseudoInst< + (outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, + [(set GPR:$dst, (atomic_cmp_swap_32 GPR:$ptr, GPR:$old, GPR:$new))]>; +} +} + +let mayLoad = 1 in { +def LDREXB : AIldrex<0b10, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, + "ldrexb", "\t$Rt, [$Rn]", + []>; +def LDREXH : AIldrex<0b11, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, + "ldrexh", "\t$Rt, [$Rn]", + []>; +def LDREX : AIldrex<0b00, (outs GPR:$Rt), (ins GPR:$Rn), NoItinerary, + "ldrex", "\t$Rt, [$Rn]", + []>; +def LDREXD : AIldrex<0b01, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$Rn), + NoItinerary, + "ldrexd", "\t$Rt, $Rt2, [$Rn]", + []>; +} + +let mayStore = 1, Constraints = "@earlyclobber $Rd" in { +def STREXB : AIstrex<0b10, (outs GPR:$Rd), (ins GPR:$src, GPR:$Rn), + NoItinerary, + "strexb", "\t$Rd, $src, [$Rn]", + []>; +def STREXH : AIstrex<0b11, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn), + NoItinerary, + "strexh", "\t$Rd, $Rt, [$Rn]", + []>; +def STREX : AIstrex<0b00, (outs GPR:$Rd), (ins GPR:$Rt, GPR:$Rn), + NoItinerary, + "strex", "\t$Rd, $Rt, [$Rn]", + []>; +def STREXD : AIstrex<0b01, (outs GPR:$Rd), + (ins GPR:$Rt, GPR:$Rt2, GPR:$Rn), + NoItinerary, + "strexd", "\t$Rd, $Rt, $Rt2, [$Rn]", + []>; +} + +// Clear-Exclusive is for disassembly only. +def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + let Inst{31-0} = 0b11110101011111111111000000011111; +} + +// SWP/SWPB are deprecated in V6/V7 and for disassembly only. +let mayLoad = 1 in { +def SWP : AIswp<0, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swp", + [/* For disassembly only; pattern left blank */]>; +def SWPB : AIswp<1, (outs GPR:$Rt), (ins GPR:$Rt2, GPR:$Rn), "swpb", + [/* For disassembly only; pattern left blank */]>; +} + +//===----------------------------------------------------------------------===// +// TLS Instructions +// + +// __aeabi_read_tp preserves the registers r1-r3. +// This is a pseudo inst so that we can get the encoding right, +// complete with fixup for the aeabi_read_tp function. +let isCall = 1, + Defs = [R0, R12, LR, CPSR], Uses = [SP] in { + def TPsoft : PseudoInst<(outs), (ins), IIC_Br, + [(set R0, ARMthread_pointer)]>; +} + +//===----------------------------------------------------------------------===// +// SJLJ Exception handling intrinsics +// eh_sjlj_setjmp() is an instruction sequence to store the return +// address and save #0 in R0 for the non-longjmp case. +// Since by its nature we may be coming from some other function to get +// here, and we're using the stack frame for the containing function to +// save/restore registers, we can't keep anything live in regs across +// the eh_sjlj_setjmp(), else it will almost certainly have been tromped upon +// when we get here from a longjmp(). We force everthing out of registers +// except for our own input by listing the relevant registers in Defs. By +// doing so, we also cause the prologue/epilogue code to actively preserve +// all of the callee-saved resgisters, which is exactly what we want. +// A constant value is passed in $val, and we use the location as a scratch. +// +// These are pseudo-instructions and are lowered to individual MC-insts, so +// no encoding information is necessary. +let Defs = + [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0, + D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, + D31 ], hasSideEffects = 1, isBarrier = 1 in { + def Int_eh_sjlj_setjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$val), + NoItinerary, + [(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>, + Requires<[IsARM, HasVFP2]>; +} + +let Defs = + [ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR ], + hasSideEffects = 1, isBarrier = 1 in { + def Int_eh_sjlj_setjmp_nofp : PseudoInst<(outs), (ins GPR:$src, GPR:$val), + NoItinerary, + [(set R0, (ARMeh_sjlj_setjmp GPR:$src, GPR:$val))]>, + Requires<[IsARM, NoVFP]>; +} + +// FIXME: Non-Darwin version(s) +let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, + Defs = [ R7, LR, SP ] in { +def Int_eh_sjlj_longjmp : PseudoInst<(outs), (ins GPR:$src, GPR:$scratch), + NoItinerary, + [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, + Requires<[IsARM, IsDarwin]>; +} + +// eh.sjlj.dispatchsetup pseudo-instruction. +// This pseudo is used for ARM, Thumb1 and Thumb2. Any differences are +// handled when the pseudo is expanded (which happens before any passes +// that need the instruction size). +let isBarrier = 1, hasSideEffects = 1 in +def Int_eh_sjlj_dispatchsetup : + PseudoInst<(outs), (ins GPR:$src), NoItinerary, + [(ARMeh_sjlj_dispatchsetup GPR:$src)]>, + Requires<[IsDarwin]>; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +// + +// Large immediate handling. + +// 32-bit immediate using two piece so_imms or movw + movt. +// This is a single pseudo instruction, the benefit is that it can be remat'd +// as a single unit instead of having to handle reg inputs. +// FIXME: Remove this when we can do generalized remat. +let isReMaterializable = 1, isMoveImm = 1 in +def MOVi32imm : PseudoInst<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVix2, + [(set GPR:$dst, (arm_i32imm:$src))]>, + Requires<[IsARM]>; + +// Pseudo instruction that combines movw + movt + add pc (if PIC). +// It also makes it possible to rematerialize the instructions. +// FIXME: Remove this when we can do generalized remat and when machine licm +// can properly the instructions. +let isReMaterializable = 1 in { +def MOV_ga_pcrel : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), + IIC_iMOVix2addpc, + [(set GPR:$dst, (ARMWrapperPIC tglobaladdr:$addr))]>, + Requires<[IsARM, UseMovt]>; + +def MOV_ga_dyn : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), + IIC_iMOVix2, + [(set GPR:$dst, (ARMWrapperDYN tglobaladdr:$addr))]>, + Requires<[IsARM, UseMovt]>; + +let AddedComplexity = 10 in +def MOV_ga_pcrel_ldr : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr), + IIC_iMOVix2ld, + [(set GPR:$dst, (load (ARMWrapperPIC tglobaladdr:$addr)))]>, + Requires<[IsARM, UseMovt]>; +} // isReMaterializable + +// ConstantPool, GlobalAddress, and JumpTable +def : ARMPat<(ARMWrapper tglobaladdr :$dst), (LEApcrel tglobaladdr :$dst)>, + Requires<[IsARM, DontUseMovt]>; +def : ARMPat<(ARMWrapper tconstpool :$dst), (LEApcrel tconstpool :$dst)>; +def : ARMPat<(ARMWrapper tglobaladdr :$dst), (MOVi32imm tglobaladdr :$dst)>, + Requires<[IsARM, UseMovt]>; +def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id), + (LEApcrelJT tjumptable:$dst, imm:$id)>; + +// TODO: add,sub,and, 3-instr forms? + +// Tail calls +def : ARMPat<(ARMtcret tcGPR:$dst), + (TCRETURNri tcGPR:$dst)>, Requires<[IsDarwin]>; + +def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)), + (TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>; + +def : ARMPat<(ARMtcret (i32 texternalsym:$dst)), + (TCRETURNdi texternalsym:$dst)>, Requires<[IsDarwin]>; + +def : ARMPat<(ARMtcret tcGPR:$dst), + (TCRETURNriND tcGPR:$dst)>, Requires<[IsNotDarwin]>; + +def : ARMPat<(ARMtcret (i32 tglobaladdr:$dst)), + (TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>; + +def : ARMPat<(ARMtcret (i32 texternalsym:$dst)), + (TCRETURNdiND texternalsym:$dst)>, Requires<[IsNotDarwin]>; + +// Direct calls +def : ARMPat<(ARMcall texternalsym:$func), (BL texternalsym:$func)>, + Requires<[IsARM, IsNotDarwin]>; +def : ARMPat<(ARMcall texternalsym:$func), (BLr9 texternalsym:$func)>, + Requires<[IsARM, IsDarwin]>; + +// zextload i1 -> zextload i8 +def : ARMPat<(zextloadi1 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>; +def : ARMPat<(zextloadi1 ldst_so_reg:$addr), (LDRBrs ldst_so_reg:$addr)>; + +// extload -> zextload +def : ARMPat<(extloadi1 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>; +def : ARMPat<(extloadi1 ldst_so_reg:$addr), (LDRBrs ldst_so_reg:$addr)>; +def : ARMPat<(extloadi8 addrmode_imm12:$addr), (LDRBi12 addrmode_imm12:$addr)>; +def : ARMPat<(extloadi8 ldst_so_reg:$addr), (LDRBrs ldst_so_reg:$addr)>; + +def : ARMPat<(extloadi16 addrmode3:$addr), (LDRH addrmode3:$addr)>; + +def : ARMPat<(extloadi8 addrmodepc:$addr), (PICLDRB addrmodepc:$addr)>; +def : ARMPat<(extloadi16 addrmodepc:$addr), (PICLDRH addrmodepc:$addr)>; + +// smul* and smla* +def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16))), + (SMULBB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul sext_16_node:$a, sext_16_node:$b), + (SMULBB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra GPR:$b, (i32 16))), + (SMULBT GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul sext_16_node:$a, (sra GPR:$b, (i32 16))), + (SMULBT GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16))), + (SMULTB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(mul (sra GPR:$a, (i32 16)), sext_16_node:$b), + (SMULTB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))), + (i32 16)), + (SMULWB GPR:$a, GPR:$b)>; +def : ARMV5TEPat<(sra (mul GPR:$a, sext_16_node:$b), (i32 16)), + (SMULWB GPR:$a, GPR:$b)>; + +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16)))), + (SMLABB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul sext_16_node:$a, sext_16_node:$b)), + (SMLABB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra (shl GPR:$a, (i32 16)), (i32 16)), + (sra GPR:$b, (i32 16)))), + (SMLABT GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul sext_16_node:$a, (sra GPR:$b, (i32 16)))), + (SMLABT GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra GPR:$a, (i32 16)), + (sra (shl GPR:$b, (i32 16)), (i32 16)))), + (SMLATB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (mul (sra GPR:$a, (i32 16)), sext_16_node:$b)), + (SMLATB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (sra (mul GPR:$a, (sra (shl GPR:$b, (i32 16)), (i32 16))), + (i32 16))), + (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>; +def : ARMV5TEPat<(add GPR:$acc, + (sra (mul GPR:$a, sext_16_node:$b), (i32 16))), + (SMLAWB GPR:$a, GPR:$b, GPR:$acc)>; + +//===----------------------------------------------------------------------===// +// Thumb Support +// + +include "ARMInstrThumb.td" + +//===----------------------------------------------------------------------===// +// Thumb2 Support +// + +include "ARMInstrThumb2.td" + +//===----------------------------------------------------------------------===// +// Floating Point Support +// + +include "ARMInstrVFP.td" + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) Support +// + +include "ARMInstrNEON.td" + +//===----------------------------------------------------------------------===// +// Coprocessor Instructions. For disassembly only. +// + +def CDP : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp", "\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; +} + +def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + c_imm:$CRd, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp2\t$cop, $opc1, $CRd, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + bits<4> opc1; + bits<4> CRn; + bits<4> CRd; + bits<4> cop; + bits<3> opc2; + bits<4> CRm; + + let Inst{3-0} = CRm; + let Inst{4} = 0; + let Inst{7-5} = opc2; + let Inst{11-8} = cop; + let Inst{15-12} = CRd; + let Inst{19-16} = CRn; + let Inst{23-20} = opc1; +} + +class ACI + : I { + let Inst{27-25} = 0b110; +} + +multiclass LdStCop op31_28, bit load, string opc> { + + def _OFFSET : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _PRE : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "\tp$cop, cr$CRd, $addr!"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _POST : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), + opc, "\tp$cop, cr$CRd, [$base], $offset"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _OPTION : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option), + opc, "\tp$cop, cr$CRd, [$base], $option"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def L_OFFSET : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_PRE : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + !strconcat(opc, "l"), "\tp$cop, cr$CRd, $addr!"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_POST : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), + !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $offset"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_OPTION : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option), + !strconcat(opc, "l"), "\tp$cop, cr$CRd, [$base], $option"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } +} + +defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">; +defm LDC2 : LdStCop<0b1111, 1, "ldc2">; +defm STC : LdStCop<{?,?,?,?}, 0, "stc">; +defm STC2 : LdStCop<0b1111, 0, "stc2">; + +//===----------------------------------------------------------------------===// +// Move between coprocessor and ARM core register -- for disassembly only +// + +class MovRCopro + : ABI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def MCR : MovRCopro<"mcr", 0 /* from ARM core register to coprocessor */>; +def MRC : MovRCopro<"mrc", 1 /* from coprocessor to ARM core register */>; + +class MovRCopro2 + : ABXI<0b1110, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, c_imm:$CRn, c_imm:$CRm, i32imm:$opc2), + NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $CRn, $CRm, $opc2"), + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{20} = direction; + let Inst{4} = 1; + + bits<4> Rt; + bits<4> cop; + bits<3> opc1; + bits<3> opc2; + bits<4> CRm; + bits<4> CRn; + + let Inst{15-12} = Rt; + let Inst{11-8} = cop; + let Inst{23-21} = opc1; + let Inst{7-5} = opc2; + let Inst{3-0} = CRm; + let Inst{19-16} = CRn; +} + +def MCR2 : MovRCopro2<"mcr2", 0 /* from ARM core register to coprocessor */>; +def MRC2 : MovRCopro2<"mrc2", 1 /* from coprocessor to ARM core register */>; + +class MovRRCopro + : ABI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + NoItinerary, opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def MCRR : MovRRCopro<"mcrr", 0 /* from ARM core register to coprocessor */>; +def MRRC : MovRRCopro<"mrrc", 1 /* from coprocessor to ARM core register */>; + +class MovRRCopro2 + : ABXI<0b1100, (outs), (ins p_imm:$cop, i32imm:$opc1, + GPR:$Rt, GPR:$Rt2, c_imm:$CRm), + NoItinerary, !strconcat(opc, "\t$cop, $opc1, $Rt, $Rt2, $CRm"), + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{23-21} = 0b010; + let Inst{20} = direction; + + bits<4> Rt; + bits<4> Rt2; + bits<4> cop; + bits<4> opc1; + bits<4> CRm; + + let Inst{15-12} = Rt; + let Inst{19-16} = Rt2; + let Inst{11-8} = cop; + let Inst{7-4} = opc1; + let Inst{3-0} = CRm; +} + +def MCRR2 : MovRRCopro2<"mcrr2", 0 /* from ARM core register to coprocessor */>; +def MRRC2 : MovRRCopro2<"mrrc2", 1 /* from coprocessor to ARM core register */>; + +//===----------------------------------------------------------------------===// +// Move between special register and ARM core register -- for disassembly only +// + +// Move to ARM core register from Special Register +def MRS : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary, "mrs", "\t$Rd, cpsr", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + let Inst{23-16} = 0b00001111; + let Inst{15-12} = Rd; + let Inst{7-4} = 0b0000; +} + +def MRSsys : ABI<0b0001, (outs GPR:$Rd), (ins), NoItinerary,"mrs","\t$Rd, spsr", + [/* For disassembly only; pattern left blank */]> { + bits<4> Rd; + let Inst{23-16} = 0b01001111; + let Inst{15-12} = Rd; + let Inst{7-4} = 0b0000; +} + +// Move from ARM core register to Special Register +// +// No need to have both system and application versions, the encodings are the +// same and the assembly parser has no way to distinguish between them. The mask +// operand contains the special register (R Bit) in bit 4 and bits 3-0 contains +// the mask with the fields to be accessed in the special register. +def MSR : ABI<0b0001, (outs), (ins msr_mask:$mask, GPR:$Rn), NoItinerary, + "msr", "\t$mask, $Rn", + [/* For disassembly only; pattern left blank */]> { + bits<5> mask; + bits<4> Rn; + + let Inst{23} = 0; + let Inst{22} = mask{4}; // R bit + let Inst{21-20} = 0b10; + let Inst{19-16} = mask{3-0}; + let Inst{15-12} = 0b1111; + let Inst{11-4} = 0b00000000; + let Inst{3-0} = Rn; +} + +def MSRi : ABI<0b0011, (outs), (ins msr_mask:$mask, so_imm:$a), NoItinerary, + "msr", "\t$mask, $a", + [/* For disassembly only; pattern left blank */]> { + bits<5> mask; + bits<12> a; + + let Inst{23} = 0; + let Inst{22} = mask{4}; // R bit + let Inst{21-20} = 0b10; + let Inst{19-16} = mask{3-0}; + let Inst{15-12} = 0b1111; + let Inst{11-0} = a; +} diff --git a/final/lib/Target/ARM/ARMInstrNEON.td b/final/lib/Target/ARM/ARMInstrNEON.td new file mode 100644 index 00000000000..b979232d466 --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrNEON.td @@ -0,0 +1,4852 @@ +//===- ARMInstrNEON.td - NEON support for ARM -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM NEON instruction set. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// NEON-specific DAG Nodes. +//===----------------------------------------------------------------------===// + +def SDTARMVCMP : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<1, 2>]>; +def SDTARMVCMPZ : SDTypeProfile<1, 1, []>; + +def NEONvceq : SDNode<"ARMISD::VCEQ", SDTARMVCMP>; +def NEONvceqz : SDNode<"ARMISD::VCEQZ", SDTARMVCMPZ>; +def NEONvcge : SDNode<"ARMISD::VCGE", SDTARMVCMP>; +def NEONvcgez : SDNode<"ARMISD::VCGEZ", SDTARMVCMPZ>; +def NEONvclez : SDNode<"ARMISD::VCLEZ", SDTARMVCMPZ>; +def NEONvcgeu : SDNode<"ARMISD::VCGEU", SDTARMVCMP>; +def NEONvcgt : SDNode<"ARMISD::VCGT", SDTARMVCMP>; +def NEONvcgtz : SDNode<"ARMISD::VCGTZ", SDTARMVCMPZ>; +def NEONvcltz : SDNode<"ARMISD::VCLTZ", SDTARMVCMPZ>; +def NEONvcgtu : SDNode<"ARMISD::VCGTU", SDTARMVCMP>; +def NEONvtst : SDNode<"ARMISD::VTST", SDTARMVCMP>; + +// Types for vector shift by immediates. The "SHX" version is for long and +// narrow operations where the source and destination vectors have different +// types. The "SHINS" version is for shift and insert operations. +def SDTARMVSH : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>]>; +def SDTARMVSHX : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, + SDTCisVT<2, i32>]>; +def SDTARMVSHINS : SDTypeProfile<1, 3, [SDTCisInt<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; + +def NEONvshl : SDNode<"ARMISD::VSHL", SDTARMVSH>; +def NEONvshrs : SDNode<"ARMISD::VSHRs", SDTARMVSH>; +def NEONvshru : SDNode<"ARMISD::VSHRu", SDTARMVSH>; +def NEONvshlls : SDNode<"ARMISD::VSHLLs", SDTARMVSHX>; +def NEONvshllu : SDNode<"ARMISD::VSHLLu", SDTARMVSHX>; +def NEONvshlli : SDNode<"ARMISD::VSHLLi", SDTARMVSHX>; +def NEONvshrn : SDNode<"ARMISD::VSHRN", SDTARMVSHX>; + +def NEONvrshrs : SDNode<"ARMISD::VRSHRs", SDTARMVSH>; +def NEONvrshru : SDNode<"ARMISD::VRSHRu", SDTARMVSH>; +def NEONvrshrn : SDNode<"ARMISD::VRSHRN", SDTARMVSHX>; + +def NEONvqshls : SDNode<"ARMISD::VQSHLs", SDTARMVSH>; +def NEONvqshlu : SDNode<"ARMISD::VQSHLu", SDTARMVSH>; +def NEONvqshlsu : SDNode<"ARMISD::VQSHLsu", SDTARMVSH>; +def NEONvqshrns : SDNode<"ARMISD::VQSHRNs", SDTARMVSHX>; +def NEONvqshrnu : SDNode<"ARMISD::VQSHRNu", SDTARMVSHX>; +def NEONvqshrnsu : SDNode<"ARMISD::VQSHRNsu", SDTARMVSHX>; + +def NEONvqrshrns : SDNode<"ARMISD::VQRSHRNs", SDTARMVSHX>; +def NEONvqrshrnu : SDNode<"ARMISD::VQRSHRNu", SDTARMVSHX>; +def NEONvqrshrnsu : SDNode<"ARMISD::VQRSHRNsu", SDTARMVSHX>; + +def NEONvsli : SDNode<"ARMISD::VSLI", SDTARMVSHINS>; +def NEONvsri : SDNode<"ARMISD::VSRI", SDTARMVSHINS>; + +def SDTARMVGETLN : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>, + SDTCisVT<2, i32>]>; +def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>; +def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>; + +def SDTARMVMOVIMM : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVT<1, i32>]>; +def NEONvmovImm : SDNode<"ARMISD::VMOVIMM", SDTARMVMOVIMM>; +def NEONvmvnImm : SDNode<"ARMISD::VMVNIMM", SDTARMVMOVIMM>; + +def SDTARMVORRIMM : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisVT<2, i32>]>; +def NEONvorrImm : SDNode<"ARMISD::VORRIMM", SDTARMVORRIMM>; +def NEONvbicImm : SDNode<"ARMISD::VBICIMM", SDTARMVORRIMM>; + +def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>; + +// VDUPLANE can produce a quad-register result from a double-register source, +// so the result is not constrained to match the source. +def NEONvduplane : SDNode<"ARMISD::VDUPLANE", + SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, + SDTCisVT<2, i32>]>>; + +def SDTARMVEXT : SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, SDTCisVT<3, i32>]>; +def NEONvext : SDNode<"ARMISD::VEXT", SDTARMVEXT>; + +def SDTARMVSHUF : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisSameAs<0, 1>]>; +def NEONvrev64 : SDNode<"ARMISD::VREV64", SDTARMVSHUF>; +def NEONvrev32 : SDNode<"ARMISD::VREV32", SDTARMVSHUF>; +def NEONvrev16 : SDNode<"ARMISD::VREV16", SDTARMVSHUF>; + +def SDTARMVSHUF2 : SDTypeProfile<2, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>]>; +def NEONzip : SDNode<"ARMISD::VZIP", SDTARMVSHUF2>; +def NEONuzp : SDNode<"ARMISD::VUZP", SDTARMVSHUF2>; +def NEONtrn : SDNode<"ARMISD::VTRN", SDTARMVSHUF2>; + +def SDTARMVMULL : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, + SDTCisSameAs<1, 2>]>; +def NEONvmulls : SDNode<"ARMISD::VMULLs", SDTARMVMULL>; +def NEONvmullu : SDNode<"ARMISD::VMULLu", SDTARMVMULL>; + +def SDTARMFMAX : SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>]>; +def NEONfmax : SDNode<"ARMISD::FMAX", SDTARMFMAX>; +def NEONfmin : SDNode<"ARMISD::FMIN", SDTARMFMAX>; + +def NEONimmAllZerosV: PatLeaf<(NEONvmovImm (i32 timm)), [{ + ConstantSDNode *ConstVal = cast(N->getOperand(0)); + unsigned EltBits = 0; + uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits); + return (EltBits == 32 && EltVal == 0); +}]>; + +def NEONimmAllOnesV: PatLeaf<(NEONvmovImm (i32 timm)), [{ + ConstantSDNode *ConstVal = cast(N->getOperand(0)); + unsigned EltBits = 0; + uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits); + return (EltBits == 8 && EltVal == 0xff); +}]>; + +//===----------------------------------------------------------------------===// +// NEON operand definitions +//===----------------------------------------------------------------------===// + +def nModImm : Operand { + let PrintMethod = "printNEONModImmOperand"; +} + +//===----------------------------------------------------------------------===// +// NEON load / store instructions +//===----------------------------------------------------------------------===// + +// Use VLDM to load a Q register as a D register pair. +// This is a pseudo instruction that is expanded to VLDMD after reg alloc. +def VLDMQIA + : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), + IIC_fpLoad_m, "", + [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; +def VLDMQDB + : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), + IIC_fpLoad_m, "", + [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; + +// Use VSTM to store a Q register as a D register pair. +// This is a pseudo instruction that is expanded to VSTMD after reg alloc. +def VSTMQIA + : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), + IIC_fpStore_m, "", + [(store (v2f64 QPR:$src), GPR:$Rn)]>; +def VSTMQDB + : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), + IIC_fpStore_m, "", + [(store (v2f64 QPR:$src), GPR:$Rn)]>; + +// Classes for VLD* pseudo-instructions with multi-register operands. +// These are expanded to real instructions after register allocation. +class VLDQPseudo + : PseudoNLdSt<(outs QPR:$dst), (ins addrmode6:$addr), itin, "">; +class VLDQWBPseudo + : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset), itin, + "$addr.addr = $wb">; +class VLDQQPseudo + : PseudoNLdSt<(outs QQPR:$dst), (ins addrmode6:$addr), itin, "">; +class VLDQQWBPseudo + : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset), itin, + "$addr.addr = $wb">; +class VLDQQQQPseudo + : PseudoNLdSt<(outs QQQQPR:$dst), (ins addrmode6:$addr, QQQQPR:$src), itin,"">; +class VLDQQQQWBPseudo + : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, + "$addr.addr = $wb, $src = $dst">; + +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { + +// VLD1 : Vector Load (multiple single elements) +class VLD1D op7_4, string Dt> + : NLdSt<0,0b10,0b0111,op7_4, (outs DPR:$Vd), + (ins addrmode6:$Rn), IIC_VLD1, + "vld1", Dt, "\\{$Vd\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} +class VLD1Q op7_4, string Dt> + : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2), + (ins addrmode6:$Rn), IIC_VLD1x2, + "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VLD1d8 : VLD1D<{0,0,0,?}, "8">; +def VLD1d16 : VLD1D<{0,1,0,?}, "16">; +def VLD1d32 : VLD1D<{1,0,0,?}, "32">; +def VLD1d64 : VLD1D<{1,1,0,?}, "64">; + +def VLD1q8 : VLD1Q<{0,0,?,?}, "8">; +def VLD1q16 : VLD1Q<{0,1,?,?}, "16">; +def VLD1q32 : VLD1Q<{1,0,?,?}, "32">; +def VLD1q64 : VLD1Q<{1,1,?,?}, "64">; + +def VLD1q8Pseudo : VLDQPseudo; +def VLD1q16Pseudo : VLDQPseudo; +def VLD1q32Pseudo : VLDQPseudo; +def VLD1q64Pseudo : VLDQPseudo; + +// ...with address register writeback: +class VLD1DWB op7_4, string Dt> + : NLdSt<0,0b10,0b0111,op7_4, (outs DPR:$Vd, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1u, + "vld1", Dt, "\\{$Vd\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} +class VLD1QWB op7_4, string Dt> + : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x2u, + "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VLD1d8_UPD : VLD1DWB<{0,0,0,?}, "8">; +def VLD1d16_UPD : VLD1DWB<{0,1,0,?}, "16">; +def VLD1d32_UPD : VLD1DWB<{1,0,0,?}, "32">; +def VLD1d64_UPD : VLD1DWB<{1,1,0,?}, "64">; + +def VLD1q8_UPD : VLD1QWB<{0,0,?,?}, "8">; +def VLD1q16_UPD : VLD1QWB<{0,1,?,?}, "16">; +def VLD1q32_UPD : VLD1QWB<{1,0,?,?}, "32">; +def VLD1q64_UPD : VLD1QWB<{1,1,?,?}, "64">; + +def VLD1q8Pseudo_UPD : VLDQWBPseudo; +def VLD1q16Pseudo_UPD : VLDQWBPseudo; +def VLD1q32Pseudo_UPD : VLDQWBPseudo; +def VLD1q64Pseudo_UPD : VLDQWBPseudo; + +// ...with 3 registers (some of these are only for the disassembler): +class VLD1D3 op7_4, string Dt> + : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$Rn), IIC_VLD1x3, "vld1", Dt, + "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} +class VLD1D3WB op7_4, string Dt> + : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt, + "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD1d8T : VLD1D3<{0,0,0,?}, "8">; +def VLD1d16T : VLD1D3<{0,1,0,?}, "16">; +def VLD1d32T : VLD1D3<{1,0,0,?}, "32">; +def VLD1d64T : VLD1D3<{1,1,0,?}, "64">; + +def VLD1d8T_UPD : VLD1D3WB<{0,0,0,?}, "8">; +def VLD1d16T_UPD : VLD1D3WB<{0,1,0,?}, "16">; +def VLD1d32T_UPD : VLD1D3WB<{1,0,0,?}, "32">; +def VLD1d64T_UPD : VLD1D3WB<{1,1,0,?}, "64">; + +def VLD1d64TPseudo : VLDQQPseudo; +def VLD1d64TPseudo_UPD : VLDQQWBPseudo; + +// ...with 4 registers (some of these are only for the disassembler): +class VLD1D4 op7_4, string Dt> + : NLdSt<0,0b10,0b0010,op7_4,(outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$Rn), IIC_VLD1x4, "vld1", Dt, + "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} +class VLD1D4WB op7_4, string Dt> + : NLdSt<0,0b10,0b0010,op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x4u, "vld1", Dt, + "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", + []> { + let Inst{5-4} = Rn{5-4}; +} + +def VLD1d8Q : VLD1D4<{0,0,?,?}, "8">; +def VLD1d16Q : VLD1D4<{0,1,?,?}, "16">; +def VLD1d32Q : VLD1D4<{1,0,?,?}, "32">; +def VLD1d64Q : VLD1D4<{1,1,?,?}, "64">; + +def VLD1d8Q_UPD : VLD1D4WB<{0,0,?,?}, "8">; +def VLD1d16Q_UPD : VLD1D4WB<{0,1,?,?}, "16">; +def VLD1d32Q_UPD : VLD1D4WB<{1,0,?,?}, "32">; +def VLD1d64Q_UPD : VLD1D4WB<{1,1,?,?}, "64">; + +def VLD1d64QPseudo : VLDQQPseudo; +def VLD1d64QPseudo_UPD : VLDQQWBPseudo; + +// VLD2 : Vector Load (multiple 2-element structures) +class VLD2D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2), + (ins addrmode6:$Rn), IIC_VLD2, + "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} +class VLD2Q op7_4, string Dt> + : NLdSt<0, 0b10, 0b0011, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$Rn), IIC_VLD2x2, + "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VLD2d8 : VLD2D<0b1000, {0,0,?,?}, "8">; +def VLD2d16 : VLD2D<0b1000, {0,1,?,?}, "16">; +def VLD2d32 : VLD2D<0b1000, {1,0,?,?}, "32">; + +def VLD2q8 : VLD2Q<{0,0,?,?}, "8">; +def VLD2q16 : VLD2Q<{0,1,?,?}, "16">; +def VLD2q32 : VLD2Q<{1,0,?,?}, "32">; + +def VLD2d8Pseudo : VLDQPseudo; +def VLD2d16Pseudo : VLDQPseudo; +def VLD2d32Pseudo : VLDQPseudo; + +def VLD2q8Pseudo : VLDQQPseudo; +def VLD2q16Pseudo : VLDQQPseudo; +def VLD2q32Pseudo : VLDQQPseudo; + +// ...with address register writeback: +class VLD2DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD2u, + "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} +class VLD2QWB op7_4, string Dt> + : NLdSt<0, 0b10, 0b0011, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD2x2u, + "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VLD2d8_UPD : VLD2DWB<0b1000, {0,0,?,?}, "8">; +def VLD2d16_UPD : VLD2DWB<0b1000, {0,1,?,?}, "16">; +def VLD2d32_UPD : VLD2DWB<0b1000, {1,0,?,?}, "32">; + +def VLD2q8_UPD : VLD2QWB<{0,0,?,?}, "8">; +def VLD2q16_UPD : VLD2QWB<{0,1,?,?}, "16">; +def VLD2q32_UPD : VLD2QWB<{1,0,?,?}, "32">; + +def VLD2d8Pseudo_UPD : VLDQWBPseudo; +def VLD2d16Pseudo_UPD : VLDQWBPseudo; +def VLD2d32Pseudo_UPD : VLDQWBPseudo; + +def VLD2q8Pseudo_UPD : VLDQQWBPseudo; +def VLD2q16Pseudo_UPD : VLDQQWBPseudo; +def VLD2q32Pseudo_UPD : VLDQQWBPseudo; + +// ...with double-spaced registers (for disassembly only): +def VLD2b8 : VLD2D<0b1001, {0,0,?,?}, "8">; +def VLD2b16 : VLD2D<0b1001, {0,1,?,?}, "16">; +def VLD2b32 : VLD2D<0b1001, {1,0,?,?}, "32">; +def VLD2b8_UPD : VLD2DWB<0b1001, {0,0,?,?}, "8">; +def VLD2b16_UPD : VLD2DWB<0b1001, {0,1,?,?}, "16">; +def VLD2b32_UPD : VLD2DWB<0b1001, {1,0,?,?}, "32">; + +// VLD3 : Vector Load (multiple 3-element structures) +class VLD3D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$Rn), IIC_VLD3, + "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD3d8 : VLD3D<0b0100, {0,0,0,?}, "8">; +def VLD3d16 : VLD3D<0b0100, {0,1,0,?}, "16">; +def VLD3d32 : VLD3D<0b0100, {1,0,0,?}, "32">; + +def VLD3d8Pseudo : VLDQQPseudo; +def VLD3d16Pseudo : VLDQQPseudo; +def VLD3d32Pseudo : VLDQQPseudo; + +// ...with address register writeback: +class VLD3DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD3u, + "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD3d8_UPD : VLD3DWB<0b0100, {0,0,0,?}, "8">; +def VLD3d16_UPD : VLD3DWB<0b0100, {0,1,0,?}, "16">; +def VLD3d32_UPD : VLD3DWB<0b0100, {1,0,0,?}, "32">; + +def VLD3d8Pseudo_UPD : VLDQQWBPseudo; +def VLD3d16Pseudo_UPD : VLDQQWBPseudo; +def VLD3d32Pseudo_UPD : VLDQQWBPseudo; + +// ...with double-spaced registers: +def VLD3q8 : VLD3D<0b0101, {0,0,0,?}, "8">; +def VLD3q16 : VLD3D<0b0101, {0,1,0,?}, "16">; +def VLD3q32 : VLD3D<0b0101, {1,0,0,?}, "32">; +def VLD3q8_UPD : VLD3DWB<0b0101, {0,0,0,?}, "8">; +def VLD3q16_UPD : VLD3DWB<0b0101, {0,1,0,?}, "16">; +def VLD3q32_UPD : VLD3DWB<0b0101, {1,0,0,?}, "32">; + +def VLD3q8Pseudo_UPD : VLDQQQQWBPseudo; +def VLD3q16Pseudo_UPD : VLDQQQQWBPseudo; +def VLD3q32Pseudo_UPD : VLDQQQQWBPseudo; + +// ...alternate versions to be allocated odd register numbers: +def VLD3q8oddPseudo : VLDQQQQPseudo; +def VLD3q16oddPseudo : VLDQQQQPseudo; +def VLD3q32oddPseudo : VLDQQQQPseudo; + +def VLD3q8oddPseudo_UPD : VLDQQQQWBPseudo; +def VLD3q16oddPseudo_UPD : VLDQQQQWBPseudo; +def VLD3q32oddPseudo_UPD : VLDQQQQWBPseudo; + +// VLD4 : Vector Load (multiple 4-element structures) +class VLD4D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$Rn), IIC_VLD4, + "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VLD4d8 : VLD4D<0b0000, {0,0,?,?}, "8">; +def VLD4d16 : VLD4D<0b0000, {0,1,?,?}, "16">; +def VLD4d32 : VLD4D<0b0000, {1,0,?,?}, "32">; + +def VLD4d8Pseudo : VLDQQPseudo; +def VLD4d16Pseudo : VLDQQPseudo; +def VLD4d32Pseudo : VLDQQPseudo; + +// ...with address register writeback: +class VLD4DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD4u, + "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VLD4d8_UPD : VLD4DWB<0b0000, {0,0,?,?}, "8">; +def VLD4d16_UPD : VLD4DWB<0b0000, {0,1,?,?}, "16">; +def VLD4d32_UPD : VLD4DWB<0b0000, {1,0,?,?}, "32">; + +def VLD4d8Pseudo_UPD : VLDQQWBPseudo; +def VLD4d16Pseudo_UPD : VLDQQWBPseudo; +def VLD4d32Pseudo_UPD : VLDQQWBPseudo; + +// ...with double-spaced registers: +def VLD4q8 : VLD4D<0b0001, {0,0,?,?}, "8">; +def VLD4q16 : VLD4D<0b0001, {0,1,?,?}, "16">; +def VLD4q32 : VLD4D<0b0001, {1,0,?,?}, "32">; +def VLD4q8_UPD : VLD4DWB<0b0001, {0,0,?,?}, "8">; +def VLD4q16_UPD : VLD4DWB<0b0001, {0,1,?,?}, "16">; +def VLD4q32_UPD : VLD4DWB<0b0001, {1,0,?,?}, "32">; + +def VLD4q8Pseudo_UPD : VLDQQQQWBPseudo; +def VLD4q16Pseudo_UPD : VLDQQQQWBPseudo; +def VLD4q32Pseudo_UPD : VLDQQQQWBPseudo; + +// ...alternate versions to be allocated odd register numbers: +def VLD4q8oddPseudo : VLDQQQQPseudo; +def VLD4q16oddPseudo : VLDQQQQPseudo; +def VLD4q32oddPseudo : VLDQQQQPseudo; + +def VLD4q8oddPseudo_UPD : VLDQQQQWBPseudo; +def VLD4q16oddPseudo_UPD : VLDQQQQWBPseudo; +def VLD4q32oddPseudo_UPD : VLDQQQQWBPseudo; + +} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 + +// Classes for VLD*LN pseudo-instructions with multi-register operands. +// These are expanded to real instructions after register allocation. +class VLDQLNPseudo + : PseudoNLdSt<(outs QPR:$dst), + (ins addrmode6:$addr, QPR:$src, nohash_imm:$lane), + itin, "$src = $dst">; +class VLDQLNWBPseudo + : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; +class VLDQQLNPseudo + : PseudoNLdSt<(outs QQPR:$dst), + (ins addrmode6:$addr, QQPR:$src, nohash_imm:$lane), + itin, "$src = $dst">; +class VLDQQLNWBPseudo + : PseudoNLdSt<(outs QQPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; +class VLDQQQQLNPseudo + : PseudoNLdSt<(outs QQQQPR:$dst), + (ins addrmode6:$addr, QQQQPR:$src, nohash_imm:$lane), + itin, "$src = $dst">; +class VLDQQQQLNWBPseudo + : PseudoNLdSt<(outs QQQQPR:$dst, GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb, $src = $dst">; + +// VLD1LN : Vector Load (single element to one lane) +class VLD1LN op11_8, bits<4> op7_4, string Dt, ValueType Ty, + PatFrag LoadOp> + : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd), + (ins addrmode6:$Rn, DPR:$src, nohash_imm:$lane), + IIC_VLD1ln, "vld1", Dt, "\\{$Vd[$lane]\\}, $Rn", + "$src = $Vd", + [(set DPR:$Vd, (vector_insert (Ty DPR:$src), + (i32 (LoadOp addrmode6:$Rn)), + imm:$lane))]> { + let Rm = 0b1111; +} +class VLD1QLNPseudo : VLDQLNPseudo { + let Pattern = [(set QPR:$dst, (vector_insert (Ty QPR:$src), + (i32 (LoadOp addrmode6:$addr)), + imm:$lane))]; +} + +def VLD1LNd8 : VLD1LN<0b0000, {?,?,?,0}, "8", v8i8, extloadi8> { + let Inst{7-5} = lane{2-0}; +} +def VLD1LNd16 : VLD1LN<0b0100, {?,?,0,?}, "16", v4i16, extloadi16> { + let Inst{7-6} = lane{1-0}; + let Inst{4} = Rn{4}; +} +def VLD1LNd32 : VLD1LN<0b1000, {?,0,?,?}, "32", v2i32, load> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{4}; + let Inst{4} = Rn{4}; +} + +def VLD1LNq8Pseudo : VLD1QLNPseudo; +def VLD1LNq16Pseudo : VLD1QLNPseudo; +def VLD1LNq32Pseudo : VLD1QLNPseudo; + +def : Pat<(vector_insert (v2f32 DPR:$src), + (f32 (load addrmode6:$addr)), imm:$lane), + (VLD1LNd32 addrmode6:$addr, DPR:$src, imm:$lane)>; +def : Pat<(vector_insert (v4f32 QPR:$src), + (f32 (load addrmode6:$addr)), imm:$lane), + (VLD1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; + +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { + +// ...with address register writeback: +class VLD1LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$src, nohash_imm:$lane), IIC_VLD1lnu, "vld1", Dt, + "\\{$Vd[$lane]\\}, $Rn$Rm", + "$src = $Vd, $Rn.addr = $wb", []>; + +def VLD1LNd8_UPD : VLD1LNWB<0b0000, {?,?,?,0}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD1LNd16_UPD : VLD1LNWB<0b0100, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; + let Inst{4} = Rn{4}; +} +def VLD1LNd32_UPD : VLD1LNWB<0b1000, {?,0,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{4}; + let Inst{4} = Rn{4}; +} + +def VLD1LNq8Pseudo_UPD : VLDQLNWBPseudo; +def VLD1LNq16Pseudo_UPD : VLDQLNWBPseudo; +def VLD1LNq32Pseudo_UPD : VLDQLNWBPseudo; + +// VLD2LN : Vector Load (single 2-element structure to one lane) +class VLD2LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2), + (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, nohash_imm:$lane), + IIC_VLD2ln, "vld2", Dt, "\\{$Vd[$lane], $dst2[$lane]\\}, $Rn", + "$src1 = $Vd, $src2 = $dst2", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD2LNd8 : VLD2LN<0b0001, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD2LNd16 : VLD2LN<0b0101, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD2LNd32 : VLD2LN<0b1001, {?,0,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD2LNd8Pseudo : VLDQLNPseudo; +def VLD2LNd16Pseudo : VLDQLNPseudo; +def VLD2LNd32Pseudo : VLDQLNPseudo; + +// ...with double-spaced registers: +def VLD2LNq16 : VLD2LN<0b0101, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD2LNq32 : VLD2LN<0b1001, {?,1,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD2LNq16Pseudo : VLDQQLNPseudo; +def VLD2LNq32Pseudo : VLDQQLNPseudo; + +// ...with address register writeback: +class VLD2LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$src1, DPR:$src2, nohash_imm:$lane), IIC_VLD2lnu, "vld2", Dt, + "\\{$Vd[$lane], $dst2[$lane]\\}, $Rn$Rm", + "$src1 = $Vd, $src2 = $dst2, $Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD2LNd8_UPD : VLD2LNWB<0b0001, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD2LNd16_UPD : VLD2LNWB<0b0101, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD2LNd32_UPD : VLD2LNWB<0b1001, {?,0,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD2LNd8Pseudo_UPD : VLDQLNWBPseudo; +def VLD2LNd16Pseudo_UPD : VLDQLNWBPseudo; +def VLD2LNd32Pseudo_UPD : VLDQLNWBPseudo; + +def VLD2LNq16_UPD : VLD2LNWB<0b0101, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD2LNq32_UPD : VLD2LNWB<0b1001, {?,1,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD2LNq16Pseudo_UPD : VLDQQLNWBPseudo; +def VLD2LNq32Pseudo_UPD : VLDQQLNWBPseudo; + +// VLD3LN : Vector Load (single 3-element structure to one lane) +class VLD3LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, DPR:$src3, + nohash_imm:$lane), IIC_VLD3ln, "vld3", Dt, + "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn", + "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3", []> { + let Rm = 0b1111; +} + +def VLD3LNd8 : VLD3LN<0b0010, {?,?,?,0}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD3LNd16 : VLD3LN<0b0110, {?,?,0,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD3LNd32 : VLD3LN<0b1010, {?,0,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD3LNd8Pseudo : VLDQQLNPseudo; +def VLD3LNd16Pseudo : VLDQQLNPseudo; +def VLD3LNd32Pseudo : VLDQQLNPseudo; + +// ...with double-spaced registers: +def VLD3LNq16 : VLD3LN<0b0110, {?,?,1,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD3LNq32 : VLD3LN<0b1010, {?,1,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD3LNq16Pseudo : VLDQQQQLNPseudo; +def VLD3LNq32Pseudo : VLDQQQQLNPseudo; + +// ...with address register writeback: +class VLD3LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$src1, DPR:$src2, DPR:$src3, nohash_imm:$lane), + IIC_VLD3lnu, "vld3", Dt, + "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane]\\}, $Rn$Rm", + "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $Rn.addr = $wb", + []>; + +def VLD3LNd8_UPD : VLD3LNWB<0b0010, {?,?,?,0}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD3LNd16_UPD : VLD3LNWB<0b0110, {?,?,0,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD3LNd32_UPD : VLD3LNWB<0b1010, {?,0,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD3LNd8Pseudo_UPD : VLDQQLNWBPseudo; +def VLD3LNd16Pseudo_UPD : VLDQQLNWBPseudo; +def VLD3LNd32Pseudo_UPD : VLDQQLNWBPseudo; + +def VLD3LNq16_UPD : VLD3LNWB<0b0110, {?,?,1,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD3LNq32_UPD : VLD3LNWB<0b1010, {?,1,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VLD3LNq16Pseudo_UPD : VLDQQQQLNWBPseudo; +def VLD3LNq32Pseudo_UPD : VLDQQQQLNWBPseudo; + +// VLD4LN : Vector Load (single 4-element structure to one lane) +class VLD4LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$Rn, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, + nohash_imm:$lane), IIC_VLD4ln, "vld4", Dt, + "\\{$Vd[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $Rn", + "$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD4LNd8 : VLD4LN<0b0011, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD4LNd16 : VLD4LN<0b0111, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD4LNd32 : VLD4LN<0b1011, {?,0,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VLD4LNd8Pseudo : VLDQQLNPseudo; +def VLD4LNd16Pseudo : VLDQQLNPseudo; +def VLD4LNd32Pseudo : VLDQQLNPseudo; + +// ...with double-spaced registers: +def VLD4LNq16 : VLD4LN<0b0111, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD4LNq32 : VLD4LN<0b1011, {?,1,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VLD4LNq16Pseudo : VLDQQQQLNPseudo; +def VLD4LNq32Pseudo : VLDQQQQLNPseudo; + +// ...with address register writeback: +class VLD4LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b10, op11_8, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, nohash_imm:$lane), + IIC_VLD4lnu, "vld4", Dt, +"\\{$Vd[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $Rn$Rm", +"$src1 = $Vd, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4, $Rn.addr = $wb", + []> { + let Inst{4} = Rn{4}; +} + +def VLD4LNd8_UPD : VLD4LNWB<0b0011, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VLD4LNd16_UPD : VLD4LNWB<0b0111, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD4LNd32_UPD : VLD4LNWB<0b1011, {?,0,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VLD4LNd8Pseudo_UPD : VLDQQLNWBPseudo; +def VLD4LNd16Pseudo_UPD : VLDQQLNWBPseudo; +def VLD4LNd32Pseudo_UPD : VLDQQLNWBPseudo; + +def VLD4LNq16_UPD : VLD4LNWB<0b0111, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VLD4LNq32_UPD : VLD4LNWB<0b1011, {?,1,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VLD4LNq16Pseudo_UPD : VLDQQQQLNWBPseudo; +def VLD4LNq32Pseudo_UPD : VLDQQQQLNWBPseudo; + +} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 + +// VLD1DUP : Vector Load (single element to all lanes) +class VLD1DUP op7_4, string Dt, ValueType Ty, PatFrag LoadOp> + : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd), (ins addrmode6dup:$Rn), + IIC_VLD1dup, "vld1", Dt, "\\{$Vd[]\\}, $Rn", "", + [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} +class VLD1QDUPPseudo : VLDQPseudo { + let Pattern = [(set QPR:$dst, + (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$addr)))))]; +} + +def VLD1DUPd8 : VLD1DUP<{0,0,0,?}, "8", v8i8, extloadi8>; +def VLD1DUPd16 : VLD1DUP<{0,1,0,?}, "16", v4i16, extloadi16>; +def VLD1DUPd32 : VLD1DUP<{1,0,0,?}, "32", v2i32, load>; + +def VLD1DUPq8Pseudo : VLD1QDUPPseudo; +def VLD1DUPq16Pseudo : VLD1QDUPPseudo; +def VLD1DUPq32Pseudo : VLD1QDUPPseudo; + +def : Pat<(v2f32 (NEONvdup (f32 (load addrmode6dup:$addr)))), + (VLD1DUPd32 addrmode6:$addr)>; +def : Pat<(v4f32 (NEONvdup (f32 (load addrmode6dup:$addr)))), + (VLD1DUPq32Pseudo addrmode6:$addr)>; + +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { + +class VLD1QDUP op7_4, string Dt> + : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2), + (ins addrmode6dup:$Rn), IIC_VLD1dup, + "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD1DUPq8 : VLD1QDUP<{0,0,1,0}, "8">; +def VLD1DUPq16 : VLD1QDUP<{0,1,1,?}, "16">; +def VLD1DUPq32 : VLD1QDUP<{1,0,1,?}, "32">; + +// ...with address register writeback: +class VLD1DUPWB op7_4, string Dt> + : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, GPR:$wb), + (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, + "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} +class VLD1QDUPWB op7_4, string Dt> + : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), + (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, + "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD1DUPd8_UPD : VLD1DUPWB<{0,0,0,0}, "8">; +def VLD1DUPd16_UPD : VLD1DUPWB<{0,1,0,?}, "16">; +def VLD1DUPd32_UPD : VLD1DUPWB<{1,0,0,?}, "32">; + +def VLD1DUPq8_UPD : VLD1QDUPWB<{0,0,1,0}, "8">; +def VLD1DUPq16_UPD : VLD1QDUPWB<{0,1,1,?}, "16">; +def VLD1DUPq32_UPD : VLD1QDUPWB<{1,0,1,?}, "32">; + +def VLD1DUPq8Pseudo_UPD : VLDQWBPseudo; +def VLD1DUPq16Pseudo_UPD : VLDQWBPseudo; +def VLD1DUPq32Pseudo_UPD : VLDQWBPseudo; + +// VLD2DUP : Vector Load (single 2-element structure to all lanes) +class VLD2DUP op7_4, string Dt> + : NLdSt<1, 0b10, 0b1101, op7_4, (outs DPR:$Vd, DPR:$dst2), + (ins addrmode6dup:$Rn), IIC_VLD2dup, + "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD2DUPd8 : VLD2DUP<{0,0,0,?}, "8">; +def VLD2DUPd16 : VLD2DUP<{0,1,0,?}, "16">; +def VLD2DUPd32 : VLD2DUP<{1,0,0,?}, "32">; + +def VLD2DUPd8Pseudo : VLDQPseudo; +def VLD2DUPd16Pseudo : VLDQPseudo; +def VLD2DUPd32Pseudo : VLDQPseudo; + +// ...with double-spaced registers (not used for codegen): +def VLD2DUPd8x2 : VLD2DUP<{0,0,1,?}, "8">; +def VLD2DUPd16x2 : VLD2DUP<{0,1,1,?}, "16">; +def VLD2DUPd32x2 : VLD2DUP<{1,0,1,?}, "32">; + +// ...with address register writeback: +class VLD2DUPWB op7_4, string Dt> + : NLdSt<1, 0b10, 0b1101, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), + (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu, + "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD2DUPd8_UPD : VLD2DUPWB<{0,0,0,0}, "8">; +def VLD2DUPd16_UPD : VLD2DUPWB<{0,1,0,?}, "16">; +def VLD2DUPd32_UPD : VLD2DUPWB<{1,0,0,?}, "32">; + +def VLD2DUPd8x2_UPD : VLD2DUPWB<{0,0,1,0}, "8">; +def VLD2DUPd16x2_UPD : VLD2DUPWB<{0,1,1,?}, "16">; +def VLD2DUPd32x2_UPD : VLD2DUPWB<{1,0,1,?}, "32">; + +def VLD2DUPd8Pseudo_UPD : VLDQWBPseudo; +def VLD2DUPd16Pseudo_UPD : VLDQWBPseudo; +def VLD2DUPd32Pseudo_UPD : VLDQWBPseudo; + +// VLD3DUP : Vector Load (single 3-element structure to all lanes) +class VLD3DUP op7_4, string Dt> + : NLdSt<1, 0b10, 0b1110, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3), + (ins addrmode6dup:$Rn), IIC_VLD3dup, + "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD3DUPd8 : VLD3DUP<{0,0,0,?}, "8">; +def VLD3DUPd16 : VLD3DUP<{0,1,0,?}, "16">; +def VLD3DUPd32 : VLD3DUP<{1,0,0,?}, "32">; + +def VLD3DUPd8Pseudo : VLDQQPseudo; +def VLD3DUPd16Pseudo : VLDQQPseudo; +def VLD3DUPd32Pseudo : VLDQQPseudo; + +// ...with double-spaced registers (not used for codegen): +def VLD3DUPd8x2 : VLD3DUP<{0,0,1,?}, "8">; +def VLD3DUPd16x2 : VLD3DUP<{0,1,1,?}, "16">; +def VLD3DUPd32x2 : VLD3DUP<{1,0,1,?}, "32">; + +// ...with address register writeback: +class VLD3DUPWB op7_4, string Dt> + : NLdSt<1, 0b10, 0b1110, op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), + (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD3dupu, + "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD3DUPd8_UPD : VLD3DUPWB<{0,0,0,0}, "8">; +def VLD3DUPd16_UPD : VLD3DUPWB<{0,1,0,?}, "16">; +def VLD3DUPd32_UPD : VLD3DUPWB<{1,0,0,?}, "32">; + +def VLD3DUPd8x2_UPD : VLD3DUPWB<{0,0,1,0}, "8">; +def VLD3DUPd16x2_UPD : VLD3DUPWB<{0,1,1,?}, "16">; +def VLD3DUPd32x2_UPD : VLD3DUPWB<{1,0,1,?}, "32">; + +def VLD3DUPd8Pseudo_UPD : VLDQQWBPseudo; +def VLD3DUPd16Pseudo_UPD : VLDQQWBPseudo; +def VLD3DUPd32Pseudo_UPD : VLDQQWBPseudo; + +// VLD4DUP : Vector Load (single 4-element structure to all lanes) +class VLD4DUP op7_4, string Dt> + : NLdSt<1, 0b10, 0b1111, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6dup:$Rn), IIC_VLD4dup, + "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VLD4DUPd8 : VLD4DUP<{0,0,0,?}, "8">; +def VLD4DUPd16 : VLD4DUP<{0,1,0,?}, "16">; +def VLD4DUPd32 : VLD4DUP<{1,?,0,?}, "32"> { let Inst{6} = Rn{5}; } + +def VLD4DUPd8Pseudo : VLDQQPseudo; +def VLD4DUPd16Pseudo : VLDQQPseudo; +def VLD4DUPd32Pseudo : VLDQQPseudo; + +// ...with double-spaced registers (not used for codegen): +def VLD4DUPd8x2 : VLD4DUP<{0,0,1,?}, "8">; +def VLD4DUPd16x2 : VLD4DUP<{0,1,1,?}, "16">; +def VLD4DUPd32x2 : VLD4DUP<{1,?,1,?}, "32"> { let Inst{6} = Rn{5}; } + +// ...with address register writeback: +class VLD4DUPWB op7_4, string Dt> + : NLdSt<1, 0b10, 0b1111, op7_4, + (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, DPR:$dst4, GPR:$wb), + (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD4dupu, + "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VLD4DUPd8_UPD : VLD4DUPWB<{0,0,0,0}, "8">; +def VLD4DUPd16_UPD : VLD4DUPWB<{0,1,0,?}, "16">; +def VLD4DUPd32_UPD : VLD4DUPWB<{1,?,0,?}, "32"> { let Inst{6} = Rn{5}; } + +def VLD4DUPd8x2_UPD : VLD4DUPWB<{0,0,1,0}, "8">; +def VLD4DUPd16x2_UPD : VLD4DUPWB<{0,1,1,?}, "16">; +def VLD4DUPd32x2_UPD : VLD4DUPWB<{1,?,1,?}, "32"> { let Inst{6} = Rn{5}; } + +def VLD4DUPd8Pseudo_UPD : VLDQQWBPseudo; +def VLD4DUPd16Pseudo_UPD : VLDQQWBPseudo; +def VLD4DUPd32Pseudo_UPD : VLDQQWBPseudo; + +} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 + +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { + +// Classes for VST* pseudo-instructions with multi-register operands. +// These are expanded to real instructions after register allocation. +class VSTQPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QPR:$src), itin, "">; +class VSTQWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QPR:$src), itin, + "$addr.addr = $wb">; +class VSTQQPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQPR:$src), itin, "">; +class VSTQQWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQPR:$src), itin, + "$addr.addr = $wb">; +class VSTQQQQPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQQQPR:$src), itin, "">; +class VSTQQQQWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src), itin, + "$addr.addr = $wb">; + +// VST1 : Vector Store (multiple single elements) +class VST1D op7_4, string Dt> + : NLdSt<0,0b00,0b0111,op7_4, (outs), (ins addrmode6:$Rn, DPR:$Vd), + IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} +class VST1Q op7_4, string Dt> + : NLdSt<0,0b00,0b1010,op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2), IIC_VST1x2, + "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VST1d8 : VST1D<{0,0,0,?}, "8">; +def VST1d16 : VST1D<{0,1,0,?}, "16">; +def VST1d32 : VST1D<{1,0,0,?}, "32">; +def VST1d64 : VST1D<{1,1,0,?}, "64">; + +def VST1q8 : VST1Q<{0,0,?,?}, "8">; +def VST1q16 : VST1Q<{0,1,?,?}, "16">; +def VST1q32 : VST1Q<{1,0,?,?}, "32">; +def VST1q64 : VST1Q<{1,1,?,?}, "64">; + +def VST1q8Pseudo : VSTQPseudo; +def VST1q16Pseudo : VSTQPseudo; +def VST1q32Pseudo : VSTQPseudo; +def VST1q64Pseudo : VSTQPseudo; + +// ...with address register writeback: +class VST1DWB op7_4, string Dt> + : NLdSt<0, 0b00, 0b0111, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u, + "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} +class VST1QWB op7_4, string Dt> + : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd, DPR:$src2), + IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VST1d8_UPD : VST1DWB<{0,0,0,?}, "8">; +def VST1d16_UPD : VST1DWB<{0,1,0,?}, "16">; +def VST1d32_UPD : VST1DWB<{1,0,0,?}, "32">; +def VST1d64_UPD : VST1DWB<{1,1,0,?}, "64">; + +def VST1q8_UPD : VST1QWB<{0,0,?,?}, "8">; +def VST1q16_UPD : VST1QWB<{0,1,?,?}, "16">; +def VST1q32_UPD : VST1QWB<{1,0,?,?}, "32">; +def VST1q64_UPD : VST1QWB<{1,1,?,?}, "64">; + +def VST1q8Pseudo_UPD : VSTQWBPseudo; +def VST1q16Pseudo_UPD : VSTQWBPseudo; +def VST1q32Pseudo_UPD : VSTQWBPseudo; +def VST1q64Pseudo_UPD : VSTQWBPseudo; + +// ...with 3 registers (some of these are only for the disassembler): +class VST1D3 op7_4, string Dt> + : NLdSt<0, 0b00, 0b0110, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3), + IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} +class VST1D3WB op7_4, string Dt> + : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3), + IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VST1d8T : VST1D3<{0,0,0,?}, "8">; +def VST1d16T : VST1D3<{0,1,0,?}, "16">; +def VST1d32T : VST1D3<{1,0,0,?}, "32">; +def VST1d64T : VST1D3<{1,1,0,?}, "64">; + +def VST1d8T_UPD : VST1D3WB<{0,0,0,?}, "8">; +def VST1d16T_UPD : VST1D3WB<{0,1,0,?}, "16">; +def VST1d32T_UPD : VST1D3WB<{1,0,0,?}, "32">; +def VST1d64T_UPD : VST1D3WB<{1,1,0,?}, "64">; + +def VST1d64TPseudo : VSTQQPseudo; +def VST1d64TPseudo_UPD : VSTQQWBPseudo; + +// ...with 4 registers (some of these are only for the disassembler): +class VST1D4 op7_4, string Dt> + : NLdSt<0, 0b00, 0b0010, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST1x4, "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn", "", + []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} +class VST1D4WB op7_4, string Dt> + : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST1x4u, + "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VST1d8Q : VST1D4<{0,0,?,?}, "8">; +def VST1d16Q : VST1D4<{0,1,?,?}, "16">; +def VST1d32Q : VST1D4<{1,0,?,?}, "32">; +def VST1d64Q : VST1D4<{1,1,?,?}, "64">; + +def VST1d8Q_UPD : VST1D4WB<{0,0,?,?}, "8">; +def VST1d16Q_UPD : VST1D4WB<{0,1,?,?}, "16">; +def VST1d32Q_UPD : VST1D4WB<{1,0,?,?}, "32">; +def VST1d64Q_UPD : VST1D4WB<{1,1,?,?}, "64">; + +def VST1d64QPseudo : VSTQQPseudo; +def VST1d64QPseudo_UPD : VSTQQWBPseudo; + +// VST2 : Vector Store (multiple 2-element structures) +class VST2D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2), + IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} +class VST2Q op7_4, string Dt> + : NLdSt<0, 0b00, 0b0011, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST2x2, "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn", + "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VST2d8 : VST2D<0b1000, {0,0,?,?}, "8">; +def VST2d16 : VST2D<0b1000, {0,1,?,?}, "16">; +def VST2d32 : VST2D<0b1000, {1,0,?,?}, "32">; + +def VST2q8 : VST2Q<{0,0,?,?}, "8">; +def VST2q16 : VST2Q<{0,1,?,?}, "16">; +def VST2q32 : VST2Q<{1,0,?,?}, "32">; + +def VST2d8Pseudo : VSTQPseudo; +def VST2d16Pseudo : VSTQPseudo; +def VST2d32Pseudo : VSTQPseudo; + +def VST2q8Pseudo : VSTQQPseudo; +def VST2q16Pseudo : VSTQQPseudo; +def VST2q32Pseudo : VSTQQPseudo; + +// ...with address register writeback: +class VST2DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd, DPR:$src2), + IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} +class VST2QWB op7_4, string Dt> + : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST2x2u, + "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VST2d8_UPD : VST2DWB<0b1000, {0,0,?,?}, "8">; +def VST2d16_UPD : VST2DWB<0b1000, {0,1,?,?}, "16">; +def VST2d32_UPD : VST2DWB<0b1000, {1,0,?,?}, "32">; + +def VST2q8_UPD : VST2QWB<{0,0,?,?}, "8">; +def VST2q16_UPD : VST2QWB<{0,1,?,?}, "16">; +def VST2q32_UPD : VST2QWB<{1,0,?,?}, "32">; + +def VST2d8Pseudo_UPD : VSTQWBPseudo; +def VST2d16Pseudo_UPD : VSTQWBPseudo; +def VST2d32Pseudo_UPD : VSTQWBPseudo; + +def VST2q8Pseudo_UPD : VSTQQWBPseudo; +def VST2q16Pseudo_UPD : VSTQQWBPseudo; +def VST2q32Pseudo_UPD : VSTQQWBPseudo; + +// ...with double-spaced registers (for disassembly only): +def VST2b8 : VST2D<0b1001, {0,0,?,?}, "8">; +def VST2b16 : VST2D<0b1001, {0,1,?,?}, "16">; +def VST2b32 : VST2D<0b1001, {1,0,?,?}, "32">; +def VST2b8_UPD : VST2DWB<0b1001, {0,0,?,?}, "8">; +def VST2b16_UPD : VST2DWB<0b1001, {0,1,?,?}, "16">; +def VST2b32_UPD : VST2DWB<0b1001, {1,0,?,?}, "32">; + +// VST3 : Vector Store (multiple 3-element structures) +class VST3D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3), IIC_VST3, + "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VST3d8 : VST3D<0b0100, {0,0,0,?}, "8">; +def VST3d16 : VST3D<0b0100, {0,1,0,?}, "16">; +def VST3d32 : VST3D<0b0100, {1,0,0,?}, "32">; + +def VST3d8Pseudo : VSTQQPseudo; +def VST3d16Pseudo : VSTQQPseudo; +def VST3d32Pseudo : VSTQQPseudo; + +// ...with address register writeback: +class VST3DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3), IIC_VST3u, + "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VST3d8_UPD : VST3DWB<0b0100, {0,0,0,?}, "8">; +def VST3d16_UPD : VST3DWB<0b0100, {0,1,0,?}, "16">; +def VST3d32_UPD : VST3DWB<0b0100, {1,0,0,?}, "32">; + +def VST3d8Pseudo_UPD : VSTQQWBPseudo; +def VST3d16Pseudo_UPD : VSTQQWBPseudo; +def VST3d32Pseudo_UPD : VSTQQWBPseudo; + +// ...with double-spaced registers: +def VST3q8 : VST3D<0b0101, {0,0,0,?}, "8">; +def VST3q16 : VST3D<0b0101, {0,1,0,?}, "16">; +def VST3q32 : VST3D<0b0101, {1,0,0,?}, "32">; +def VST3q8_UPD : VST3DWB<0b0101, {0,0,0,?}, "8">; +def VST3q16_UPD : VST3DWB<0b0101, {0,1,0,?}, "16">; +def VST3q32_UPD : VST3DWB<0b0101, {1,0,0,?}, "32">; + +def VST3q8Pseudo_UPD : VSTQQQQWBPseudo; +def VST3q16Pseudo_UPD : VSTQQQQWBPseudo; +def VST3q32Pseudo_UPD : VSTQQQQWBPseudo; + +// ...alternate versions to be allocated odd register numbers: +def VST3q8oddPseudo : VSTQQQQPseudo; +def VST3q16oddPseudo : VSTQQQQPseudo; +def VST3q32oddPseudo : VSTQQQQPseudo; + +def VST3q8oddPseudo_UPD : VSTQQQQWBPseudo; +def VST3q16oddPseudo_UPD : VSTQQQQWBPseudo; +def VST3q32oddPseudo_UPD : VSTQQQQWBPseudo; + +// VST4 : Vector Store (multiple 4-element structures) +class VST4D op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST4, "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn", + "", []> { + let Rm = 0b1111; + let Inst{5-4} = Rn{5-4}; +} + +def VST4d8 : VST4D<0b0000, {0,0,?,?}, "8">; +def VST4d16 : VST4D<0b0000, {0,1,?,?}, "16">; +def VST4d32 : VST4D<0b0000, {1,0,?,?}, "32">; + +def VST4d8Pseudo : VSTQQPseudo; +def VST4d16Pseudo : VSTQQPseudo; +def VST4d32Pseudo : VSTQQPseudo; + +// ...with address register writeback: +class VST4DWB op11_8, bits<4> op7_4, string Dt> + : NLdSt<0, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4), IIC_VST4u, + "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; +} + +def VST4d8_UPD : VST4DWB<0b0000, {0,0,?,?}, "8">; +def VST4d16_UPD : VST4DWB<0b0000, {0,1,?,?}, "16">; +def VST4d32_UPD : VST4DWB<0b0000, {1,0,?,?}, "32">; + +def VST4d8Pseudo_UPD : VSTQQWBPseudo; +def VST4d16Pseudo_UPD : VSTQQWBPseudo; +def VST4d32Pseudo_UPD : VSTQQWBPseudo; + +// ...with double-spaced registers: +def VST4q8 : VST4D<0b0001, {0,0,?,?}, "8">; +def VST4q16 : VST4D<0b0001, {0,1,?,?}, "16">; +def VST4q32 : VST4D<0b0001, {1,0,?,?}, "32">; +def VST4q8_UPD : VST4DWB<0b0001, {0,0,?,?}, "8">; +def VST4q16_UPD : VST4DWB<0b0001, {0,1,?,?}, "16">; +def VST4q32_UPD : VST4DWB<0b0001, {1,0,?,?}, "32">; + +def VST4q8Pseudo_UPD : VSTQQQQWBPseudo; +def VST4q16Pseudo_UPD : VSTQQQQWBPseudo; +def VST4q32Pseudo_UPD : VSTQQQQWBPseudo; + +// ...alternate versions to be allocated odd register numbers: +def VST4q8oddPseudo : VSTQQQQPseudo; +def VST4q16oddPseudo : VSTQQQQPseudo; +def VST4q32oddPseudo : VSTQQQQPseudo; + +def VST4q8oddPseudo_UPD : VSTQQQQWBPseudo; +def VST4q16oddPseudo_UPD : VSTQQQQWBPseudo; +def VST4q32oddPseudo_UPD : VSTQQQQWBPseudo; + +} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 + +// Classes for VST*LN pseudo-instructions with multi-register operands. +// These are expanded to real instructions after register allocation. +class VSTQLNPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QPR:$src, nohash_imm:$lane), + itin, "">; +class VSTQLNWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb">; +class VSTQQLNPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQPR:$src, nohash_imm:$lane), + itin, "">; +class VSTQQLNWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb">; +class VSTQQQQLNPseudo + : PseudoNLdSt<(outs), (ins addrmode6:$addr, QQQQPR:$src, nohash_imm:$lane), + itin, "">; +class VSTQQQQLNWBPseudo + : PseudoNLdSt<(outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, QQQQPR:$src, + nohash_imm:$lane), itin, "$addr.addr = $wb">; + +// VST1LN : Vector Store (single element from one lane) +class VST1LN op11_8, bits<4> op7_4, string Dt, ValueType Ty, + PatFrag StoreOp, SDNode ExtractOp> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, nohash_imm:$lane), + IIC_VST1ln, "vst1", Dt, "\\{$Vd[$lane]\\}, $Rn", "", + [(StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), addrmode6:$Rn)]> { + let Rm = 0b1111; +} +class VST1QLNPseudo + : VSTQLNPseudo { + let Pattern = [(StoreOp (ExtractOp (Ty QPR:$src), imm:$lane), + addrmode6:$addr)]; +} + +def VST1LNd8 : VST1LN<0b0000, {?,?,?,0}, "8", v8i8, truncstorei8, + NEONvgetlaneu> { + let Inst{7-5} = lane{2-0}; +} +def VST1LNd16 : VST1LN<0b0100, {?,?,0,?}, "16", v4i16, truncstorei16, + NEONvgetlaneu> { + let Inst{7-6} = lane{1-0}; + let Inst{4} = Rn{5}; +} +def VST1LNd32 : VST1LN<0b1000, {?,0,?,?}, "32", v2i32, store, extractelt> { + let Inst{7} = lane{0}; + let Inst{5-4} = Rn{5-4}; +} + +def VST1LNq8Pseudo : VST1QLNPseudo; +def VST1LNq16Pseudo : VST1QLNPseudo; +def VST1LNq32Pseudo : VST1QLNPseudo; + +def : Pat<(store (extractelt (v2f32 DPR:$src), imm:$lane), addrmode6:$addr), + (VST1LNd32 addrmode6:$addr, DPR:$src, imm:$lane)>; +def : Pat<(store (extractelt (v4f32 QPR:$src), imm:$lane), addrmode6:$addr), + (VST1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>; + +// ...with address register writeback: +class VST1LNWB op11_8, bits<4> op7_4, string Dt, ValueType Ty, + PatFrag StoreOp, SDNode ExtractOp> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, nohash_imm:$lane), IIC_VST1lnu, "vst1", Dt, + "\\{$Vd[$lane]\\}, $Rn$Rm", + "$Rn.addr = $wb", + [(set GPR:$wb, (StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane), + addrmode6:$Rn, am6offset:$Rm))]>; +class VST1QLNWBPseudo + : VSTQLNWBPseudo { + let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane), + addrmode6:$addr, am6offset:$offset))]; +} + +def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8", v8i8, post_truncsti8, + NEONvgetlaneu> { + let Inst{7-5} = lane{2-0}; +} +def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16", v4i16, post_truncsti16, + NEONvgetlaneu> { + let Inst{7-6} = lane{1-0}; + let Inst{4} = Rn{5}; +} +def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32", v2i32, post_store, + extractelt> { + let Inst{7} = lane{0}; + let Inst{5-4} = Rn{5-4}; +} + +def VST1LNq8Pseudo_UPD : VST1QLNWBPseudo; +def VST1LNq16Pseudo_UPD : VST1QLNWBPseudo; +def VST1LNq32Pseudo_UPD : VST1QLNWBPseudo; + +let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { + +// VST2LN : Vector Store (single 2-element structure from one lane) +class VST2LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, nohash_imm:$lane), + IIC_VST2ln, "vst2", Dt, "\\{$Vd[$lane], $src2[$lane]\\}, $Rn", + "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VST2LNd8 : VST2LN<0b0001, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST2LNd16 : VST2LN<0b0101, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST2LNd32 : VST2LN<0b1001, {?,0,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VST2LNd8Pseudo : VSTQLNPseudo; +def VST2LNd16Pseudo : VSTQLNPseudo; +def VST2LNd32Pseudo : VSTQLNPseudo; + +// ...with double-spaced registers: +def VST2LNq16 : VST2LN<0b0101, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; + let Inst{4} = Rn{4}; +} +def VST2LNq32 : VST2LN<0b1001, {?,1,0,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{4} = Rn{4}; +} + +def VST2LNq16Pseudo : VSTQQLNPseudo; +def VST2LNq32Pseudo : VSTQQLNPseudo; + +// ...with address register writeback: +class VST2LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$addr, am6offset:$offset, + DPR:$src1, DPR:$src2, nohash_imm:$lane), IIC_VST2lnu, "vst2", Dt, + "\\{$src1[$lane], $src2[$lane]\\}, $addr$offset", + "$addr.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VST2LNd8_UPD : VST2LNWB<0b0001, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST2LNd16_UPD : VST2LNWB<0b0101, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST2LNd32_UPD : VST2LNWB<0b1001, {?,0,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VST2LNd8Pseudo_UPD : VSTQLNWBPseudo; +def VST2LNd16Pseudo_UPD : VSTQLNWBPseudo; +def VST2LNd32Pseudo_UPD : VSTQLNWBPseudo; + +def VST2LNq16_UPD : VST2LNWB<0b0101, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST2LNq32_UPD : VST2LNWB<0b1001, {?,1,0,?}, "32"> { + let Inst{7} = lane{0}; +} + +def VST2LNq16Pseudo_UPD : VSTQQLNWBPseudo; +def VST2LNq32Pseudo_UPD : VSTQQLNWBPseudo; + +// VST3LN : Vector Store (single 3-element structure from one lane) +class VST3LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, + nohash_imm:$lane), IIC_VST3ln, "vst3", Dt, + "\\{$Vd[$lane], $src2[$lane], $src3[$lane]\\}, $Rn", "", []> { + let Rm = 0b1111; +} + +def VST3LNd8 : VST3LN<0b0010, {?,?,?,0}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST3LNd16 : VST3LN<0b0110, {?,?,0,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST3LNd32 : VST3LN<0b1010, {?,0,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VST3LNd8Pseudo : VSTQQLNPseudo; +def VST3LNd16Pseudo : VSTQQLNPseudo; +def VST3LNd32Pseudo : VSTQQLNPseudo; + +// ...with double-spaced registers: +def VST3LNq16 : VST3LN<0b0110, {?,?,1,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST3LNq32 : VST3LN<0b1010, {?,1,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VST3LNq16Pseudo : VSTQQQQLNPseudo; +def VST3LNq32Pseudo : VSTQQQQLNPseudo; + +// ...with address register writeback: +class VST3LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3, nohash_imm:$lane), + IIC_VST3lnu, "vst3", Dt, + "\\{$Vd[$lane], $src2[$lane], $src3[$lane]\\}, $Rn$Rm", + "$Rn.addr = $wb", []>; + +def VST3LNd8_UPD : VST3LNWB<0b0010, {?,?,?,0}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST3LNd16_UPD : VST3LNWB<0b0110, {?,?,0,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST3LNd32_UPD : VST3LNWB<0b1010, {?,0,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VST3LNd8Pseudo_UPD : VSTQQLNWBPseudo; +def VST3LNd16Pseudo_UPD : VSTQQLNWBPseudo; +def VST3LNd32Pseudo_UPD : VSTQQLNWBPseudo; + +def VST3LNq16_UPD : VST3LNWB<0b0110, {?,?,1,0}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST3LNq32_UPD : VST3LNWB<0b1010, {?,1,0,0}, "32"> { + let Inst{7} = lane{0}; +} + +def VST3LNq16Pseudo_UPD : VSTQQQQLNWBPseudo; +def VST3LNq32Pseudo_UPD : VSTQQQQLNWBPseudo; + +// VST4LN : Vector Store (single 4-element structure from one lane) +class VST4LN op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs), + (ins addrmode6:$Rn, DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4, + nohash_imm:$lane), IIC_VST4ln, "vst4", Dt, + "\\{$Vd[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $Rn", + "", []> { + let Rm = 0b1111; + let Inst{4} = Rn{4}; +} + +def VST4LNd8 : VST4LN<0b0011, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST4LNd16 : VST4LN<0b0111, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST4LNd32 : VST4LN<0b1011, {?,0,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VST4LNd8Pseudo : VSTQQLNPseudo; +def VST4LNd16Pseudo : VSTQQLNPseudo; +def VST4LNd32Pseudo : VSTQQLNPseudo; + +// ...with double-spaced registers: +def VST4LNq16 : VST4LN<0b0111, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST4LNq32 : VST4LN<0b1011, {?,1,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VST4LNq16Pseudo : VSTQQQQLNPseudo; +def VST4LNq32Pseudo : VSTQQQQLNPseudo; + +// ...with address register writeback: +class VST4LNWB op11_8, bits<4> op7_4, string Dt> + : NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb), + (ins addrmode6:$Rn, am6offset:$Rm, + DPR:$Vd, DPR:$src2, DPR:$src3, DPR:$src4, nohash_imm:$lane), + IIC_VST4lnu, "vst4", Dt, + "\\{$Vd[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $Rn$Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; +} + +def VST4LNd8_UPD : VST4LNWB<0b0011, {?,?,?,?}, "8"> { + let Inst{7-5} = lane{2-0}; +} +def VST4LNd16_UPD : VST4LNWB<0b0111, {?,?,0,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST4LNd32_UPD : VST4LNWB<0b1011, {?,0,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VST4LNd8Pseudo_UPD : VSTQQLNWBPseudo; +def VST4LNd16Pseudo_UPD : VSTQQLNWBPseudo; +def VST4LNd32Pseudo_UPD : VSTQQLNWBPseudo; + +def VST4LNq16_UPD : VST4LNWB<0b0111, {?,?,1,?}, "16"> { + let Inst{7-6} = lane{1-0}; +} +def VST4LNq32_UPD : VST4LNWB<0b1011, {?,1,?,?}, "32"> { + let Inst{7} = lane{0}; + let Inst{5} = Rn{5}; +} + +def VST4LNq16Pseudo_UPD : VSTQQQQLNWBPseudo; +def VST4LNq32Pseudo_UPD : VSTQQQQLNWBPseudo; + +} // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 + + +//===----------------------------------------------------------------------===// +// NEON pattern fragments +//===----------------------------------------------------------------------===// + +// Extract D sub-registers of Q registers. +def DSubReg_i8_reg : SDNodeXFormgetTargetConstant(ARM::dsub_0 + N->getZExtValue()/8, MVT::i32); +}]>; +def DSubReg_i16_reg : SDNodeXFormgetTargetConstant(ARM::dsub_0 + N->getZExtValue()/4, MVT::i32); +}]>; +def DSubReg_i32_reg : SDNodeXFormgetTargetConstant(ARM::dsub_0 + N->getZExtValue()/2, MVT::i32); +}]>; +def DSubReg_f64_reg : SDNodeXFormgetTargetConstant(ARM::dsub_0 + N->getZExtValue(), MVT::i32); +}]>; + +// Extract S sub-registers of Q/D registers. +def SSubReg_f32_reg : SDNodeXFormgetTargetConstant(ARM::ssub_0 + N->getZExtValue(), MVT::i32); +}]>; + +// Translate lane numbers from Q registers to D subregs. +def SubReg_i8_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 7, MVT::i32); +}]>; +def SubReg_i16_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 3, MVT::i32); +}]>; +def SubReg_i32_lane : SDNodeXFormgetTargetConstant(N->getZExtValue() & 1, MVT::i32); +}]>; + +//===----------------------------------------------------------------------===// +// Instruction Classes +//===----------------------------------------------------------------------===// + +// Basic 2-register operations: double- and quad-register. +class N2VD op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr, + string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; +class N2VQ op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr, + string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; + +// Basic 2-register intrinsics, both double- and quad-register. +class N2VDInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Narrow 2-register operations. +class N2VN op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyD, ValueType TyQ, SDNode OpNode> + : N2V; + +// Narrow 2-register intrinsics. +class N2VNInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyD, ValueType TyQ, Intrinsic IntOp> + : N2V; + +// Long 2-register operations (currently only used for VMOVL). +class N2VL op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode OpNode> + : N2V; + +// Long 2-register intrinsics. +class N2VLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp> + : N2V; + +// 2-register shuffles (VTRN/VZIP/VUZP), both double- and quad-register. +class N2VDShuffle op19_18, bits<5> op11_7, string OpcodeStr, string Dt> + : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 0, 0, (outs DPR:$Vd, DPR:$Vm), + (ins DPR:$src1, DPR:$src2), IIC_VPERMD, + OpcodeStr, Dt, "$Vd, $Vm", + "$src1 = $Vd, $src2 = $Vm", []>; +class N2VQShuffle op19_18, bits<5> op11_7, + InstrItinClass itin, string OpcodeStr, string Dt> + : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 1, 0, (outs QPR:$Vd, QPR:$Vm), + (ins QPR:$src1, QPR:$src2), itin, OpcodeStr, Dt, "$Vd, $Vm", + "$src1 = $Vd, $src2 = $Vm", []>; + +// Basic 3-register operations: double- and quad-register. +class N3VD op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +// Same as N3VD but no data type. +class N3VDX op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, + ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3VX{ + let isCommutable = Commutable; +} + +class N3VDSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), (ins DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (Ty DPR:$Vd), + (Ty (ShOp (Ty DPR:$Vn), + (Ty (NEONvduplane (Ty DPR_VFP2:$Vm),imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VDSL16 op21_20, bits<4> op11_8, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), (ins DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, IIC_VMULi16D, OpcodeStr, Dt,"$Vd, $Vn, $Vm[$lane]","", + [(set (Ty DPR:$Vd), + (Ty (ShOp (Ty DPR:$Vn), + (Ty (NEONvduplane (Ty DPR_8:$Vm), imm:$lane)))))]> { + let isCommutable = 0; +} + +class N3VQ op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VQX op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> + : N3VX{ + let isCommutable = Commutable; +} +class N3VQSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (ResTy QPR:$Vd), + (ResTy (ShOp (ResTy QPR:$Vn), + (ResTy (NEONvduplane (OpTy DPR_VFP2:$Vm), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VQSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, IIC_VMULi16Q, OpcodeStr, Dt,"$Vd, $Vn, $Vm[$lane]","", + [(set (ResTy QPR:$Vd), + (ResTy (ShOp (ResTy QPR:$Vn), + (ResTy (NEONvduplane (OpTy DPR_8:$Vm), + imm:$lane)))))]> { + let isCommutable = 0; +} + +// Basic 3-register intrinsics, both double- and quad-register. +class N3VDInt op21_20, bits<4> op11_8, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VDIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), (ins DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (Ty DPR:$Vd), + (Ty (IntOp (Ty DPR:$Vn), + (Ty (NEONvduplane (Ty DPR_VFP2:$Vm), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VDIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType Ty, Intrinsic IntOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), (ins DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (Ty DPR:$Vd), + (Ty (IntOp (Ty DPR:$Vn), + (Ty (NEONvduplane (Ty DPR_8:$Vm), imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VDIntSh op21_20, bits<4> op11_8, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V { + let isCommutable = 0; +} + +class N3VQInt op21_20, bits<4> op11_8, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VQIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (ResTy QPR:$Vd), + (ResTy (IntOp (ResTy QPR:$Vn), + (ResTy (NEONvduplane (OpTy DPR_VFP2:$Vm), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VQIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "", + [(set (ResTy QPR:$Vd), + (ResTy (IntOp (ResTy QPR:$Vn), + (ResTy (NEONvduplane (OpTy DPR_8:$Vm), + imm:$lane)))))]> { + let isCommutable = 0; +} +class N3VQIntSh op21_20, bits<4> op11_8, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V { + let isCommutable = 0; +} + +// Multiply-Add/Sub operations: double- and quad-register. +class N3VDMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDPatternOperator MulOp, SDPatternOperator OpNode> + : N3V; + +class N3VDMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType Ty, SDPatternOperator MulOp, SDPatternOperator ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, + OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "$src1 = $Vd", + [(set (Ty DPR:$Vd), + (Ty (ShOp (Ty DPR:$src1), + (Ty (MulOp DPR:$Vn, + (Ty (NEONvduplane (Ty DPR_VFP2:$Vm), + imm:$lane)))))))]>; +class N3VDMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode ShOp> + : N3V<0, 1, op21_20, op11_8, 1, 0, + (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, + OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "$src1 = $Vd", + [(set (Ty DPR:$Vd), + (Ty (ShOp (Ty DPR:$src1), + (Ty (MulOp DPR:$Vn, + (Ty (NEONvduplane (Ty DPR_8:$Vm), + imm:$lane)))))))]>; + +class N3VQMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, + SDPatternOperator MulOp, SDPatternOperator OpNode> + : N3V; +class N3VQMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + SDPatternOperator MulOp, SDPatternOperator ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, DPR_VFP2:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, + OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "$src1 = $Vd", + [(set (ResTy QPR:$Vd), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (MulOp QPR:$Vn, + (ResTy (NEONvduplane (OpTy DPR_VFP2:$Vm), + imm:$lane)))))))]>; +class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, + SDNode MulOp, SDNode ShOp> + : N3V<1, 1, op21_20, op11_8, 1, 0, + (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, DPR_8:$Vm, nohash_imm:$lane), + NVMulSLFrm, itin, + OpcodeStr, Dt, "$Vd, $Vn, $Vm[$lane]", "$src1 = $Vd", + [(set (ResTy QPR:$Vd), + (ResTy (ShOp (ResTy QPR:$src1), + (ResTy (MulOp QPR:$Vn, + (ResTy (NEONvduplane (OpTy DPR_8:$Vm), + imm:$lane)))))))]>; + +// Neon Intrinsic-Op instructions (VABA): double- and quad-register. +class N3VDIntOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp, SDNode OpNode> + : N3V; +class N3VQIntOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, Intrinsic IntOp, SDNode OpNode> + : N3V; + +// Neon 3-argument intrinsics, both double- and quad-register. +// The destination register is also used as the first source operand register. +class N3VDInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VQInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; + +// Long Multiply-Add/Sub operations. +class N3VLMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode MulOp, SDNode OpNode> + : N3V; +class N3VLMulOpSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode MulOp, SDNode OpNode> + : N3V; +class N3VLMulOpSL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode MulOp, SDNode OpNode> + : N3V; + +// Long Intrinsic-Op vector operations with explicit extend (VABAL). +class N3VLIntExtOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp, SDNode ExtOp, + SDNode OpNode> + : N3V; + +// Neon Long 3-argument intrinsic. The destination register is +// a quad-register and is also used as the first source operand register. +class N3VLInt3 op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp> + : N3V; +class N3VLInt3SL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VLInt3SL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; + +// Narrowing 3-register intrinsics. +class N3VNInt op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType TyD, ValueType TyQ, + Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Long 3-register operations. +class N3VL op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VLSL op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode OpNode> + : N3V; +class N3VLSL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode OpNode> + : N3V; + +// Long 3-register operations with explicitly extended operands. +class N3VLExt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, SDNode OpNode, SDNode ExtOp, + bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Long 3-register intrinsics with explicit extend (VABDL). +class N3VLIntExt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp, SDNode ExtOp, + bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Long 3-register intrinsics. +class N3VLInt op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType TyQ, ValueType TyD, Intrinsic IntOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} +class N3VLIntSL op21_20, bits<4> op11_8, InstrItinClass itin, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; +class N3VLIntSL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N3V; + +// Wide 3-register operations. +class N3VW op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType TyQ, ValueType TyD, + SDNode OpNode, SDNode ExtOp, bit Commutable> + : N3V { + let isCommutable = Commutable; +} + +// Pairwise long 2-register intrinsics, both double- and quad-register. +class N2VDPLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQPLInt op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Pairwise long 2-register accumulate intrinsics, +// both double- and quad-register. +// The destination register is also used as the first source operand register. +class N2VDPLInt2 op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; +class N2VQPLInt2 op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> + : N2V; + +// Shift by immediate, +// both double- and quad-register. +class N2VDSh op11_8, bit op7, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode OpNode> + : N2VImm; +class N2VQSh op11_8, bit op7, bit op4, + Format f, InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode OpNode> + : N2VImm; + +// Long shift by immediate. +class N2VLSh op11_8, bit op7, bit op6, bit op4, + string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2VImm; + +// Narrow shift by immediate. +class N2VNSh op11_8, bit op7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Operand ImmTy, SDNode OpNode> + : N2VImm; + +// Shift right by immediate and accumulate, +// both double- and quad-register. +class N2VDShAdd op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; +class N2VQShAdd op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> + : N2VImm; + +// Shift by immediate and insert, +// both double- and quad-register. +class N2VDShIns op11_8, bit op7, bit op4, + Format f, string OpcodeStr, string Dt, ValueType Ty,SDNode ShOp> + : N2VImm; +class N2VQShIns op11_8, bit op7, bit op4, + Format f, string OpcodeStr, string Dt, ValueType Ty,SDNode ShOp> + : N2VImm; + +// Convert, with fractional bits immediate, +// both double- and quad-register. +class N2VCvtD op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N2VImm; +class N2VCvtQ op11_8, bit op7, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + Intrinsic IntOp> + : N2VImm; + +//===----------------------------------------------------------------------===// +// Multiclasses +//===----------------------------------------------------------------------===// + +// Abbreviations used in multiclass suffixes: +// Q = quarter int (8 bit) elements +// H = half int (16 bit) elements +// S = single int (32 bit) elements +// D = double int (64 bit) elements + +// Neon 2-register vector operations and intrinsics. + +// Neon 2-register comparisons. +// source operand element sizes of 8, 16 and 32 bits: +multiclass N2V_QHS_cmp op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, string opc, string Dt, + string asm, SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N2V; + def v4i16 : N2V; + def v2i32 : N2V; + def v2f32 : N2V { + let Inst{10} = 1; // overwrite F = 1 + } + + // 128-bit vector types. + def v16i8 : N2V; + def v8i16 : N2V; + def v4i32 : N2V; + def v4f32 : N2V { + let Inst{10} = 1; // overwrite F = 1 + } +} + + +// Neon 2-register vector intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VInt_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDInt; + def v4i16 : N2VDInt; + def v2i32 : N2VDInt; + + // 128-bit vector types. + def v16i8 : N2VQInt; + def v8i16 : N2VQInt; + def v4i32 : N2VQInt; +} + + +// Neon Narrowing 2-register vector operations, +// source operand element sizes of 16, 32 and 64 bits: +multiclass N2VN_HSD op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + def v8i8 : N2VN; + def v4i16 : N2VN; + def v2i32 : N2VN; +} + +// Neon Narrowing 2-register vector intrinsics, +// source operand element sizes of 16, 32 and 64 bits: +multiclass N2VNInt_HSD op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op6, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp> { + def v8i8 : N2VNInt; + def v4i16 : N2VNInt; + def v2i32 : N2VNInt; +} + + +// Neon Lengthening 2-register vector intrinsic (currently specific to VMOVL). +// source operand element sizes of 16, 32 and 64 bits: +multiclass N2VL_QHS op24_23, bits<5> op11_7, bit op6, bit op4, + string OpcodeStr, string Dt, SDNode OpNode> { + def v8i16 : N2VL; + def v4i32 : N2VL; + def v2i64 : N2VL; +} + + +// Neon 3-register vector operations. + +// First with only element sizes of 8, 16 and 32 bits: +multiclass N3V_QHS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + SDNode OpNode, bit Commutable = 0> { + // 64-bit vector types. + def v8i8 : N3VD; + def v4i16 : N3VD; + def v2i32 : N3VD; + + // 128-bit vector types. + def v16i8 : N3VQ; + def v8i16 : N3VQ; + def v4i32 : N3VQ; +} + +multiclass N3VSL_HS op11_8, string OpcodeStr, string Dt, SDNode ShOp> { + def v4i16 : N3VDSL16<0b01, op11_8, OpcodeStr, !strconcat(Dt, "16"), + v4i16, ShOp>; + def v2i32 : N3VDSL<0b10, op11_8, IIC_VMULi32D, OpcodeStr, !strconcat(Dt,"32"), + v2i32, ShOp>; + def v8i16 : N3VQSL16<0b01, op11_8, OpcodeStr, !strconcat(Dt, "16"), + v8i16, v4i16, ShOp>; + def v4i32 : N3VQSL<0b10, op11_8, IIC_VMULi32Q, OpcodeStr, !strconcat(Dt,"32"), + v4i32, v2i32, ShOp>; +} + +// ....then also with element size 64 bits: +multiclass N3V_QHSD op11_8, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, + SDNode OpNode, bit Commutable = 0> + : N3V_QHS { + def v1i64 : N3VD; + def v2i64 : N3VQ; +} + + +// Neon 3-register vector intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VInt_HS op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + // 64-bit vector types. + def v4i16 : N3VDInt; + def v2i32 : N3VDInt; + + // 128-bit vector types. + def v8i16 : N3VQInt; + def v4i32 : N3VQInt; +} +multiclass N3VInt_HSSh op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp> { + // 64-bit vector types. + def v4i16 : N3VDIntSh; + def v2i32 : N3VDIntSh; + + // 128-bit vector types. + def v8i16 : N3VQIntSh; + def v4i32 : N3VQIntSh; +} + +multiclass N3VIntSL_HS op11_8, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i16 : N3VDIntSL16<0b01, op11_8, itinD16, + OpcodeStr, !strconcat(Dt, "16"), v4i16, IntOp>; + def v2i32 : N3VDIntSL<0b10, op11_8, itinD32, + OpcodeStr, !strconcat(Dt, "32"), v2i32, IntOp>; + def v8i16 : N3VQIntSL16<0b01, op11_8, itinQ16, + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, IntOp>; + def v4i32 : N3VQIntSL<0b10, op11_8, itinQ32, + OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, IntOp>; +} + +// ....then also with element size of 8 bits: +multiclass N3VInt_QHS op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VInt_HS { + def v8i8 : N3VDInt; + def v16i8 : N3VQInt; +} +multiclass N3VInt_QHSSh op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp> + : N3VInt_HSSh { + def v8i8 : N3VDIntSh; + def v16i8 : N3VQIntSh; +} + + +// ....then also with element size of 64 bits: +multiclass N3VInt_QHSD op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VInt_QHS { + def v1i64 : N3VDInt; + def v2i64 : N3VQInt; +} +multiclass N3VInt_QHSDSh op11_8, bit op4, Format f, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, + Intrinsic IntOp> + : N3VInt_QHSSh { + def v1i64 : N3VDIntSh; + def v2i64 : N3VQIntSh; +} + +// Neon Narrowing 3-register vector intrinsics, +// source operand element sizes of 16, 32 and 64 bits: +multiclass N3VNInt_HSD op11_8, bit op4, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + def v8i8 : N3VNInt; + def v4i16 : N3VNInt; + def v2i32 : N3VNInt; +} + + +// Neon Long 3-register vector operations. + +multiclass N3VL_QHS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, + SDNode OpNode, bit Commutable = 0> { + def v8i16 : N3VL; + def v4i32 : N3VL; + def v2i64 : N3VL; +} + +multiclass N3VLSL_HS op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + def v4i16 : N3VLSL16; + def v2i32 : N3VLSL; +} + +multiclass N3VLExt_QHS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, + SDNode OpNode, SDNode ExtOp, bit Commutable = 0> { + def v8i16 : N3VLExt; + def v4i32 : N3VLExt; + def v2i64 : N3VLExt; +} + +// Neon Long 3-register vector intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VLInt_HS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> { + def v4i32 : N3VLInt; + def v2i64 : N3VLInt; +} + +multiclass N3VLIntSL_HS op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp> { + def v4i16 : N3VLIntSL16; + def v2i32 : N3VLIntSL; +} + +// ....then also with element size of 8 bits: +multiclass N3VLInt_QHS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, + Intrinsic IntOp, bit Commutable = 0> + : N3VLInt_HS { + def v8i16 : N3VLInt; +} + +// ....with explicit extend (VABDL). +multiclass N3VLIntExt_QHS op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp, SDNode ExtOp, bit Commutable = 0> { + def v8i16 : N3VLIntExt; + def v4i32 : N3VLIntExt; + def v2i64 : N3VLIntExt; +} + + +// Neon Wide 3-register vector intrinsics, +// source operand element sizes of 8, 16 and 32 bits: +multiclass N3VW_QHS op11_8, bit op4, + string OpcodeStr, string Dt, + SDNode OpNode, SDNode ExtOp, bit Commutable = 0> { + def v8i16 : N3VW; + def v4i32 : N3VW; + def v2i64 : N3VW; +} + + +// Neon Multiply-Op vector operations, +// element sizes of 8, 16 and 32 bits: +multiclass N3VMulOp_QHS op11_8, bit op4, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N3VDMulOp; + def v4i16 : N3VDMulOp; + def v2i32 : N3VDMulOp; + + // 128-bit vector types. + def v16i8 : N3VQMulOp; + def v8i16 : N3VQMulOp; + def v4i32 : N3VQMulOp; +} + +multiclass N3VMulOpSL_HS op11_8, + InstrItinClass itinD16, InstrItinClass itinD32, + InstrItinClass itinQ16, InstrItinClass itinQ32, + string OpcodeStr, string Dt, SDNode ShOp> { + def v4i16 : N3VDMulOpSL16<0b01, op11_8, itinD16, + OpcodeStr, !strconcat(Dt, "16"), v4i16, mul, ShOp>; + def v2i32 : N3VDMulOpSL<0b10, op11_8, itinD32, + OpcodeStr, !strconcat(Dt, "32"), v2i32, mul, ShOp>; + def v8i16 : N3VQMulOpSL16<0b01, op11_8, itinQ16, + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, + mul, ShOp>; + def v4i32 : N3VQMulOpSL<0b10, op11_8, itinQ32, + OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, + mul, ShOp>; +} + +// Neon Intrinsic-Op vector operations, +// element sizes of 8, 16 and 32 bits: +multiclass N3VIntOp_QHS op11_8, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, Intrinsic IntOp, + SDNode OpNode> { + // 64-bit vector types. + def v8i8 : N3VDIntOp; + def v4i16 : N3VDIntOp; + def v2i32 : N3VDIntOp; + + // 128-bit vector types. + def v16i8 : N3VQIntOp; + def v8i16 : N3VQIntOp; + def v4i32 : N3VQIntOp; +} + +// Neon 3-argument intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N3VInt3_QHS op11_8, bit op4, + InstrItinClass itinD, InstrItinClass itinQ, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N3VDInt3; + def v4i16 : N3VDInt3; + def v2i32 : N3VDInt3; + + // 128-bit vector types. + def v16i8 : N3VQInt3; + def v8i16 : N3VQInt3; + def v4i32 : N3VQInt3; +} + + +// Neon Long Multiply-Op vector operations, +// element sizes of 8, 16 and 32 bits: +multiclass N3VLMulOp_QHS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, SDNode MulOp, + SDNode OpNode> { + def v8i16 : N3VLMulOp; + def v4i32 : N3VLMulOp; + def v2i64 : N3VLMulOp; +} + +multiclass N3VLMulOpSL_HS op11_8, string OpcodeStr, + string Dt, SDNode MulOp, SDNode OpNode> { + def v4i16 : N3VLMulOpSL16; + def v2i32 : N3VLMulOpSL; +} + + +// Neon Long 3-argument intrinsics. + +// First with only element sizes of 16 and 32 bits: +multiclass N3VLInt3_HS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i32 : N3VLInt3; + def v2i64 : N3VLInt3; +} + +multiclass N3VLInt3SL_HS op11_8, + string OpcodeStr, string Dt, Intrinsic IntOp> { + def v4i16 : N3VLInt3SL16; + def v2i32 : N3VLInt3SL; +} + +// ....then also with element size of 8 bits: +multiclass N3VLInt3_QHS op11_8, bit op4, + InstrItinClass itin16, InstrItinClass itin32, + string OpcodeStr, string Dt, Intrinsic IntOp> + : N3VLInt3_HS { + def v8i16 : N3VLInt3; +} + +// ....with explicit extend (VABAL). +multiclass N3VLIntExtOp_QHS op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + Intrinsic IntOp, SDNode ExtOp, SDNode OpNode> { + def v8i16 : N3VLIntExtOp; + def v4i32 : N3VLIntExtOp; + def v2i64 : N3VLIntExtOp; +} + + +// Neon Pairwise long 2-register intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VPLInt_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDPLInt; + def v4i16 : N2VDPLInt; + def v2i32 : N2VDPLInt; + + // 128-bit vector types. + def v16i8 : N2VQPLInt; + def v8i16 : N2VQPLInt; + def v4i32 : N2VQPLInt; +} + + +// Neon Pairwise long 2-register accumulate intrinsics, +// element sizes of 8, 16 and 32 bits: +multiclass N2VPLInt2_QHS op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, + string OpcodeStr, string Dt, Intrinsic IntOp> { + // 64-bit vector types. + def v8i8 : N2VDPLInt2; + def v4i16 : N2VDPLInt2; + def v2i32 : N2VDPLInt2; + + // 128-bit vector types. + def v16i8 : N2VQPLInt2; + def v8i16 : N2VQPLInt2; + def v4i32 : N2VQPLInt2; +} + + +// Neon 2-register vector shift by immediate, +// with f of either N2RegVShLFrm or N2RegVShRFrm +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VSh_QHSD op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode, Format f> { + // 64-bit vector types. + def v8i8 : N2VDSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDSh; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQSh; + // imm6 = xxxxxx +} + +// Neon Shift-Accumulate vector operations, +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VShAdd_QHSD op11_8, bit op4, + string OpcodeStr, string Dt, SDNode ShOp> { + // 64-bit vector types. + def v8i8 : N2VDShAdd { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDShAdd { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDShAdd { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDShAdd; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQShAdd { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQShAdd { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQShAdd { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQShAdd; + // imm6 = xxxxxx +} + + +// Neon Shift-Insert vector operations, +// with f of either N2RegVShLFrm or N2RegVShRFrm +// element sizes of 8, 16, 32 and 64 bits: +multiclass N2VShIns_QHSD op11_8, bit op4, + string OpcodeStr, SDNode ShOp, + Format f> { + // 64-bit vector types. + def v8i8 : N2VDShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VDShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VDShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v1i64 : N2VDShIns; + // imm6 = xxxxxx + + // 128-bit vector types. + def v16i8 : N2VQShIns { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v8i16 : N2VQShIns { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v4i32 : N2VQShIns { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } + def v2i64 : N2VQShIns; + // imm6 = xxxxxx +} + +// Neon Shift Long operations, +// element sizes of 8, 16, 32 bits: +multiclass N2VLSh_QHS op11_8, bit op7, bit op6, + bit op4, string OpcodeStr, string Dt, SDNode OpNode> { + def v8i16 : N2VLSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i32 : N2VLSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i64 : N2VLSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } +} + +// Neon Shift Narrow operations, +// element sizes of 16, 32, 64 bits: +multiclass N2VNSh_HSD op11_8, bit op7, bit op6, + bit op4, InstrItinClass itin, string OpcodeStr, string Dt, + SDNode OpNode> { + def v8i8 : N2VNSh { + let Inst{21-19} = 0b001; // imm6 = 001xxx + } + def v4i16 : N2VNSh { + let Inst{21-20} = 0b01; // imm6 = 01xxxx + } + def v2i32 : N2VNSh { + let Inst{21} = 0b1; // imm6 = 1xxxxx + } +} + +//===----------------------------------------------------------------------===// +// Instruction Definitions. +//===----------------------------------------------------------------------===// + +// Vector Add Operations. + +// VADD : Vector Add (integer and floating-point) +defm VADD : N3V_QHSD<0, 0, 0b1000, 0, IIC_VBINiD, IIC_VBINiQ, "vadd", "i", + add, 1>; +def VADDfd : N3VD<0, 0, 0b00, 0b1101, 0, IIC_VBIND, "vadd", "f32", + v2f32, v2f32, fadd, 1>; +def VADDfq : N3VQ<0, 0, 0b00, 0b1101, 0, IIC_VBINQ, "vadd", "f32", + v4f32, v4f32, fadd, 1>; +// VADDL : Vector Add Long (Q = D + D) +defm VADDLs : N3VLExt_QHS<0,1,0b0000,0, IIC_VSHLiD, IIC_VSHLiD, + "vaddl", "s", add, sext, 1>; +defm VADDLu : N3VLExt_QHS<1,1,0b0000,0, IIC_VSHLiD, IIC_VSHLiD, + "vaddl", "u", add, zext, 1>; +// VADDW : Vector Add Wide (Q = Q + D) +defm VADDWs : N3VW_QHS<0,1,0b0001,0, "vaddw", "s", add, sext, 0>; +defm VADDWu : N3VW_QHS<1,1,0b0001,0, "vaddw", "u", add, zext, 0>; +// VHADD : Vector Halving Add +defm VHADDs : N3VInt_QHS<0, 0, 0b0000, 0, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vhadd", "s", int_arm_neon_vhadds, 1>; +defm VHADDu : N3VInt_QHS<1, 0, 0b0000, 0, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vhadd", "u", int_arm_neon_vhaddu, 1>; +// VRHADD : Vector Rounding Halving Add +defm VRHADDs : N3VInt_QHS<0, 0, 0b0001, 0, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vrhadd", "s", int_arm_neon_vrhadds, 1>; +defm VRHADDu : N3VInt_QHS<1, 0, 0b0001, 0, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vrhadd", "u", int_arm_neon_vrhaddu, 1>; +// VQADD : Vector Saturating Add +defm VQADDs : N3VInt_QHSD<0, 0, 0b0000, 1, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vqadd", "s", int_arm_neon_vqadds, 1>; +defm VQADDu : N3VInt_QHSD<1, 0, 0b0000, 1, N3RegFrm, + IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, + "vqadd", "u", int_arm_neon_vqaddu, 1>; +// VADDHN : Vector Add and Narrow Returning High Half (D = Q + Q) +defm VADDHN : N3VNInt_HSD<0,1,0b0100,0, "vaddhn", "i", + int_arm_neon_vaddhn, 1>; +// VRADDHN : Vector Rounding Add and Narrow Returning High Half (D = Q + Q) +defm VRADDHN : N3VNInt_HSD<1,1,0b0100,0, "vraddhn", "i", + int_arm_neon_vraddhn, 1>; + +// Vector Multiply Operations. + +// VMUL : Vector Multiply (integer, polynomial and floating-point) +defm VMUL : N3V_QHS<0, 0, 0b1001, 1, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, "vmul", "i", mul, 1>; +def VMULpd : N3VDInt<1, 0, 0b00, 0b1001, 1, N3RegFrm, IIC_VMULi16D, "vmul", + "p8", v8i8, v8i8, int_arm_neon_vmulp, 1>; +def VMULpq : N3VQInt<1, 0, 0b00, 0b1001, 1, N3RegFrm, IIC_VMULi16Q, "vmul", + "p8", v16i8, v16i8, int_arm_neon_vmulp, 1>; +def VMULfd : N3VD<1, 0, 0b00, 0b1101, 1, IIC_VFMULD, "vmul", "f32", + v2f32, v2f32, fmul, 1>; +def VMULfq : N3VQ<1, 0, 0b00, 0b1101, 1, IIC_VFMULQ, "vmul", "f32", + v4f32, v4f32, fmul, 1>; +defm VMULsl : N3VSL_HS<0b1000, "vmul", "i", mul>; +def VMULslfd : N3VDSL<0b10, 0b1001, IIC_VBIND, "vmul", "f32", v2f32, fmul>; +def VMULslfq : N3VQSL<0b10, 0b1001, IIC_VBINQ, "vmul", "f32", v4f32, + v2f32, fmul>; + +def : Pat<(v8i16 (mul (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), imm:$lane)))), + (v8i16 (VMULslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (mul (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), imm:$lane)))), + (v4i32 (VMULslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; +def : Pat<(v4f32 (fmul (v4f32 QPR:$src1), + (v4f32 (NEONvduplane (v4f32 QPR:$src2), imm:$lane)))), + (v4f32 (VMULslfq (v4f32 QPR:$src1), + (v2f32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VQDMULH : Vector Saturating Doubling Multiply Returning High Half +defm VQDMULH : N3VInt_HS<0, 0, 0b1011, 0, N3RegFrm, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqdmulh", "s", int_arm_neon_vqdmulh, 1>; +defm VQDMULHsl: N3VIntSL_HS<0b1100, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqdmulh", "s", int_arm_neon_vqdmulh>; +def : Pat<(v8i16 (int_arm_neon_vqdmulh (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), + imm:$lane)))), + (v8i16 (VQDMULHslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (int_arm_neon_vqdmulh (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), + imm:$lane)))), + (v4i32 (VQDMULHslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VQRDMULH : Vector Rounding Saturating Doubling Multiply Returning High Half +defm VQRDMULH : N3VInt_HS<1, 0, 0b1011, 0, N3RegFrm, + IIC_VMULi16D,IIC_VMULi32D,IIC_VMULi16Q,IIC_VMULi32Q, + "vqrdmulh", "s", int_arm_neon_vqrdmulh, 1>; +defm VQRDMULHsl : N3VIntSL_HS<0b1101, IIC_VMULi16D, IIC_VMULi32D, + IIC_VMULi16Q, IIC_VMULi32Q, + "vqrdmulh", "s", int_arm_neon_vqrdmulh>; +def : Pat<(v8i16 (int_arm_neon_vqrdmulh (v8i16 QPR:$src1), + (v8i16 (NEONvduplane (v8i16 QPR:$src2), + imm:$lane)))), + (v8i16 (VQRDMULHslv8i16 (v8i16 QPR:$src1), + (v4i16 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (int_arm_neon_vqrdmulh (v4i32 QPR:$src1), + (v4i32 (NEONvduplane (v4i32 QPR:$src2), + imm:$lane)))), + (v4i32 (VQRDMULHslv4i32 (v4i32 QPR:$src1), + (v2i32 (EXTRACT_SUBREG QPR:$src2, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +// VMULL : Vector Multiply Long (integer and polynomial) (Q = D * D) +defm VMULLs : N3VL_QHS<0,1,0b1100,0, IIC_VMULi16D, IIC_VMULi32D, + "vmull", "s", NEONvmulls, 1>; +defm VMULLu : N3VL_QHS<1,1,0b1100,0, IIC_VMULi16D, IIC_VMULi32D, + "vmull", "u", NEONvmullu, 1>; +def VMULLp : N3VLInt<0, 1, 0b00, 0b1110, 0, IIC_VMULi16D, "vmull", "p8", + v8i16, v8i8, int_arm_neon_vmullp, 1>; +defm VMULLsls : N3VLSL_HS<0, 0b1010, IIC_VMULi16D, "vmull", "s", NEONvmulls>; +defm VMULLslu : N3VLSL_HS<1, 0b1010, IIC_VMULi16D, "vmull", "u", NEONvmullu>; + +// VQDMULL : Vector Saturating Doubling Multiply Long (Q = D * D) +defm VQDMULL : N3VLInt_HS<0,1,0b1101,0, IIC_VMULi16D, IIC_VMULi32D, + "vqdmull", "s", int_arm_neon_vqdmull, 1>; +defm VQDMULLsl: N3VLIntSL_HS<0, 0b1011, IIC_VMULi16D, + "vqdmull", "s", int_arm_neon_vqdmull>; + +// Vector Multiply-Accumulate and Multiply-Subtract Operations. + +// VMLA : Vector Multiply Accumulate (integer and floating-point) +defm VMLA : N3VMulOp_QHS<0, 0, 0b1001, 0, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmla", "i", add>; +def VMLAfd : N3VDMulOp<0, 0, 0b00, 0b1101, 1, IIC_VMACD, "vmla", "f32", + v2f32, fmul_su, fadd_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +def VMLAfq : N3VQMulOp<0, 0, 0b00, 0b1101, 1, IIC_VMACQ, "vmla", "f32", + v4f32, fmul_su, fadd_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +defm VMLAsl : N3VMulOpSL_HS<0b0000, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmla", "i", add>; +def VMLAslfd : N3VDMulOpSL<0b10, 0b0001, IIC_VMACD, "vmla", "f32", + v2f32, fmul_su, fadd_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +def VMLAslfq : N3VQMulOpSL<0b10, 0b0001, IIC_VMACQ, "vmla", "f32", + v4f32, v2f32, fmul_su, fadd_mlx>, + Requires<[HasNEON, UseFPVMLx]>; + +def : Pat<(v8i16 (add (v8i16 QPR:$src1), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLAslv8i16 (v8i16 QPR:$src1), (v8i16 QPR:$src2), + (v4i16 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; + +def : Pat<(v4i32 (add (v4i32 QPR:$src1), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLAslv4i32 (v4i32 QPR:$src1), (v4i32 QPR:$src2), + (v2i32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def : Pat<(v4f32 (fadd_mlx (v4f32 QPR:$src1), + (fmul_su (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (v4f32 (VMLAslfq (v4f32 QPR:$src1), + (v4f32 QPR:$src2), + (v2f32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>, + Requires<[HasNEON, UseFPVMLx]>; + +// VMLAL : Vector Multiply Accumulate Long (Q += D * D) +defm VMLALs : N3VLMulOp_QHS<0,1,0b1000,0, IIC_VMACi16D, IIC_VMACi32D, + "vmlal", "s", NEONvmulls, add>; +defm VMLALu : N3VLMulOp_QHS<1,1,0b1000,0, IIC_VMACi16D, IIC_VMACi32D, + "vmlal", "u", NEONvmullu, add>; + +defm VMLALsls : N3VLMulOpSL_HS<0, 0b0010, "vmlal", "s", NEONvmulls, add>; +defm VMLALslu : N3VLMulOpSL_HS<1, 0b0010, "vmlal", "u", NEONvmullu, add>; + +// VQDMLAL : Vector Saturating Doubling Multiply Accumulate Long (Q += D * D) +defm VQDMLAL : N3VLInt3_HS<0, 1, 0b1001, 0, IIC_VMACi16D, IIC_VMACi32D, + "vqdmlal", "s", int_arm_neon_vqdmlal>; +defm VQDMLALsl: N3VLInt3SL_HS<0, 0b0011, "vqdmlal", "s", int_arm_neon_vqdmlal>; + +// VMLS : Vector Multiply Subtract (integer and floating-point) +defm VMLS : N3VMulOp_QHS<1, 0, 0b1001, 0, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmls", "i", sub>; +def VMLSfd : N3VDMulOp<0, 0, 0b10, 0b1101, 1, IIC_VMACD, "vmls", "f32", + v2f32, fmul_su, fsub_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +def VMLSfq : N3VQMulOp<0, 0, 0b10, 0b1101, 1, IIC_VMACQ, "vmls", "f32", + v4f32, fmul_su, fsub_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +defm VMLSsl : N3VMulOpSL_HS<0b0100, IIC_VMACi16D, IIC_VMACi32D, + IIC_VMACi16Q, IIC_VMACi32Q, "vmls", "i", sub>; +def VMLSslfd : N3VDMulOpSL<0b10, 0b0101, IIC_VMACD, "vmls", "f32", + v2f32, fmul_su, fsub_mlx>, + Requires<[HasNEON, UseFPVMLx]>; +def VMLSslfq : N3VQMulOpSL<0b10, 0b0101, IIC_VMACQ, "vmls", "f32", + v4f32, v2f32, fmul_su, fsub_mlx>, + Requires<[HasNEON, UseFPVMLx]>; + +def : Pat<(v8i16 (sub (v8i16 QPR:$src1), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLSslv8i16 (v8i16 QPR:$src1), (v8i16 QPR:$src2), + (v4i16 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; + +def : Pat<(v4i32 (sub (v4i32 QPR:$src1), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLSslv4i32 (v4i32 QPR:$src1), (v4i32 QPR:$src2), + (v2i32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def : Pat<(v4f32 (fsub_mlx (v4f32 QPR:$src1), + (fmul_su (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (v4f32 (VMLSslfq (v4f32 QPR:$src1), (v4f32 QPR:$src2), + (v2f32 (EXTRACT_SUBREG QPR:$src3, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>, + Requires<[HasNEON, UseFPVMLx]>; + +// VMLSL : Vector Multiply Subtract Long (Q -= D * D) +defm VMLSLs : N3VLMulOp_QHS<0,1,0b1010,0, IIC_VMACi16D, IIC_VMACi32D, + "vmlsl", "s", NEONvmulls, sub>; +defm VMLSLu : N3VLMulOp_QHS<1,1,0b1010,0, IIC_VMACi16D, IIC_VMACi32D, + "vmlsl", "u", NEONvmullu, sub>; + +defm VMLSLsls : N3VLMulOpSL_HS<0, 0b0110, "vmlsl", "s", NEONvmulls, sub>; +defm VMLSLslu : N3VLMulOpSL_HS<1, 0b0110, "vmlsl", "u", NEONvmullu, sub>; + +// VQDMLSL : Vector Saturating Doubling Multiply Subtract Long (Q -= D * D) +defm VQDMLSL : N3VLInt3_HS<0, 1, 0b1011, 0, IIC_VMACi16D, IIC_VMACi32D, + "vqdmlsl", "s", int_arm_neon_vqdmlsl>; +defm VQDMLSLsl: N3VLInt3SL_HS<0, 0b111, "vqdmlsl", "s", int_arm_neon_vqdmlsl>; + +// Vector Subtract Operations. + +// VSUB : Vector Subtract (integer and floating-point) +defm VSUB : N3V_QHSD<1, 0, 0b1000, 0, IIC_VSUBiD, IIC_VSUBiQ, + "vsub", "i", sub, 0>; +def VSUBfd : N3VD<0, 0, 0b10, 0b1101, 0, IIC_VBIND, "vsub", "f32", + v2f32, v2f32, fsub, 0>; +def VSUBfq : N3VQ<0, 0, 0b10, 0b1101, 0, IIC_VBINQ, "vsub", "f32", + v4f32, v4f32, fsub, 0>; +// VSUBL : Vector Subtract Long (Q = D - D) +defm VSUBLs : N3VLExt_QHS<0,1,0b0010,0, IIC_VSHLiD, IIC_VSHLiD, + "vsubl", "s", sub, sext, 0>; +defm VSUBLu : N3VLExt_QHS<1,1,0b0010,0, IIC_VSHLiD, IIC_VSHLiD, + "vsubl", "u", sub, zext, 0>; +// VSUBW : Vector Subtract Wide (Q = Q - D) +defm VSUBWs : N3VW_QHS<0,1,0b0011,0, "vsubw", "s", sub, sext, 0>; +defm VSUBWu : N3VW_QHS<1,1,0b0011,0, "vsubw", "u", sub, zext, 0>; +// VHSUB : Vector Halving Subtract +defm VHSUBs : N3VInt_QHS<0, 0, 0b0010, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vhsub", "s", int_arm_neon_vhsubs, 0>; +defm VHSUBu : N3VInt_QHS<1, 0, 0b0010, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vhsub", "u", int_arm_neon_vhsubu, 0>; +// VQSUB : Vector Saturing Subtract +defm VQSUBs : N3VInt_QHSD<0, 0, 0b0010, 1, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vqsub", "s", int_arm_neon_vqsubs, 0>; +defm VQSUBu : N3VInt_QHSD<1, 0, 0b0010, 1, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vqsub", "u", int_arm_neon_vqsubu, 0>; +// VSUBHN : Vector Subtract and Narrow Returning High Half (D = Q - Q) +defm VSUBHN : N3VNInt_HSD<0,1,0b0110,0, "vsubhn", "i", + int_arm_neon_vsubhn, 0>; +// VRSUBHN : Vector Rounding Subtract and Narrow Returning High Half (D=Q-Q) +defm VRSUBHN : N3VNInt_HSD<1,1,0b0110,0, "vrsubhn", "i", + int_arm_neon_vrsubhn, 0>; + +// Vector Comparisons. + +// VCEQ : Vector Compare Equal +defm VCEQ : N3V_QHS<1, 0, 0b1000, 1, IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, + IIC_VSUBi4Q, "vceq", "i", NEONvceq, 1>; +def VCEQfd : N3VD<0,0,0b00,0b1110,0, IIC_VBIND, "vceq", "f32", v2i32, v2f32, + NEONvceq, 1>; +def VCEQfq : N3VQ<0,0,0b00,0b1110,0, IIC_VBINQ, "vceq", "f32", v4i32, v4f32, + NEONvceq, 1>; + +defm VCEQz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00010, 0, "vceq", "i", + "$Vd, $Vm, #0", NEONvceqz>; + +// VCGE : Vector Compare Greater Than or Equal +defm VCGEs : N3V_QHS<0, 0, 0b0011, 1, IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, + IIC_VSUBi4Q, "vcge", "s", NEONvcge, 0>; +defm VCGEu : N3V_QHS<1, 0, 0b0011, 1, IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, + IIC_VSUBi4Q, "vcge", "u", NEONvcgeu, 0>; +def VCGEfd : N3VD<1,0,0b00,0b1110,0, IIC_VBIND, "vcge", "f32", v2i32, v2f32, + NEONvcge, 0>; +def VCGEfq : N3VQ<1,0,0b00,0b1110,0, IIC_VBINQ, "vcge", "f32", v4i32, v4f32, + NEONvcge, 0>; + +defm VCGEz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00001, 0, "vcge", "s", + "$Vd, $Vm, #0", NEONvcgez>; +defm VCLEz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00011, 0, "vcle", "s", + "$Vd, $Vm, #0", NEONvclez>; + +// VCGT : Vector Compare Greater Than +defm VCGTs : N3V_QHS<0, 0, 0b0011, 0, IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, + IIC_VSUBi4Q, "vcgt", "s", NEONvcgt, 0>; +defm VCGTu : N3V_QHS<1, 0, 0b0011, 0, IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, + IIC_VSUBi4Q, "vcgt", "u", NEONvcgtu, 0>; +def VCGTfd : N3VD<1,0,0b10,0b1110,0, IIC_VBIND, "vcgt", "f32", v2i32, v2f32, + NEONvcgt, 0>; +def VCGTfq : N3VQ<1,0,0b10,0b1110,0, IIC_VBINQ, "vcgt", "f32", v4i32, v4f32, + NEONvcgt, 0>; + +defm VCGTz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00000, 0, "vcgt", "s", + "$Vd, $Vm, #0", NEONvcgtz>; +defm VCLTz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00100, 0, "vclt", "s", + "$Vd, $Vm, #0", NEONvcltz>; + +// VACGE : Vector Absolute Compare Greater Than or Equal (aka VCAGE) +def VACGEd : N3VDInt<1, 0, 0b00, 0b1110, 1, N3RegFrm, IIC_VBIND, "vacge", + "f32", v2i32, v2f32, int_arm_neon_vacged, 0>; +def VACGEq : N3VQInt<1, 0, 0b00, 0b1110, 1, N3RegFrm, IIC_VBINQ, "vacge", + "f32", v4i32, v4f32, int_arm_neon_vacgeq, 0>; +// VACGT : Vector Absolute Compare Greater Than (aka VCAGT) +def VACGTd : N3VDInt<1, 0, 0b10, 0b1110, 1, N3RegFrm, IIC_VBIND, "vacgt", + "f32", v2i32, v2f32, int_arm_neon_vacgtd, 0>; +def VACGTq : N3VQInt<1, 0, 0b10, 0b1110, 1, N3RegFrm, IIC_VBINQ, "vacgt", + "f32", v4i32, v4f32, int_arm_neon_vacgtq, 0>; +// VTST : Vector Test Bits +defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, + IIC_VBINi4Q, "vtst", "", NEONvtst, 1>; + +// Vector Bitwise Operations. + +def vnotd : PatFrag<(ops node:$in), + (xor node:$in, (bitconvert (v8i8 NEONimmAllOnesV)))>; +def vnotq : PatFrag<(ops node:$in), + (xor node:$in, (bitconvert (v16i8 NEONimmAllOnesV)))>; + + +// VAND : Vector Bitwise AND +def VANDd : N3VDX<0, 0, 0b00, 0b0001, 1, IIC_VBINiD, "vand", + v2i32, v2i32, and, 1>; +def VANDq : N3VQX<0, 0, 0b00, 0b0001, 1, IIC_VBINiQ, "vand", + v4i32, v4i32, and, 1>; + +// VEOR : Vector Bitwise Exclusive OR +def VEORd : N3VDX<1, 0, 0b00, 0b0001, 1, IIC_VBINiD, "veor", + v2i32, v2i32, xor, 1>; +def VEORq : N3VQX<1, 0, 0b00, 0b0001, 1, IIC_VBINiQ, "veor", + v4i32, v4i32, xor, 1>; + +// VORR : Vector Bitwise OR +def VORRd : N3VDX<0, 0, 0b10, 0b0001, 1, IIC_VBINiD, "vorr", + v2i32, v2i32, or, 1>; +def VORRq : N3VQX<0, 0, 0b10, 0b0001, 1, IIC_VBINiQ, "vorr", + v4i32, v4i32, or, 1>; + +def VORRiv4i16 : N1ModImm<1, 0b000, {1,0,?,1}, 0, 0, 0, 1, + (outs DPR:$Vd), (ins nModImm:$SIMM, DPR:$src), + IIC_VMOVImm, + "vorr", "i16", "$Vd, $SIMM", "$src = $Vd", + [(set DPR:$Vd, + (v4i16 (NEONvorrImm DPR:$src, timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VORRiv2i32 : N1ModImm<1, 0b000, {0,?,?,1}, 0, 0, 0, 1, + (outs DPR:$Vd), (ins nModImm:$SIMM, DPR:$src), + IIC_VMOVImm, + "vorr", "i32", "$Vd, $SIMM", "$src = $Vd", + [(set DPR:$Vd, + (v2i32 (NEONvorrImm DPR:$src, timm:$SIMM)))]> { + let Inst{10-9} = SIMM{10-9}; +} + +def VORRiv8i16 : N1ModImm<1, 0b000, {1,0,?,1}, 0, 1, 0, 1, + (outs QPR:$Vd), (ins nModImm:$SIMM, QPR:$src), + IIC_VMOVImm, + "vorr", "i16", "$Vd, $SIMM", "$src = $Vd", + [(set QPR:$Vd, + (v8i16 (NEONvorrImm QPR:$src, timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VORRiv4i32 : N1ModImm<1, 0b000, {0,?,?,1}, 0, 1, 0, 1, + (outs QPR:$Vd), (ins nModImm:$SIMM, QPR:$src), + IIC_VMOVImm, + "vorr", "i32", "$Vd, $SIMM", "$src = $Vd", + [(set QPR:$Vd, + (v4i32 (NEONvorrImm QPR:$src, timm:$SIMM)))]> { + let Inst{10-9} = SIMM{10-9}; +} + + +// VBIC : Vector Bitwise Bit Clear (AND NOT) +def VBICd : N3VX<0, 0, 0b01, 0b0001, 0, 1, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm), N3RegFrm, IIC_VBINiD, + "vbic", "$Vd, $Vn, $Vm", "", + [(set DPR:$Vd, (v2i32 (and DPR:$Vn, + (vnotd DPR:$Vm))))]>; +def VBICq : N3VX<0, 0, 0b01, 0b0001, 1, 1, (outs QPR:$Vd), + (ins QPR:$Vn, QPR:$Vm), N3RegFrm, IIC_VBINiQ, + "vbic", "$Vd, $Vn, $Vm", "", + [(set QPR:$Vd, (v4i32 (and QPR:$Vn, + (vnotq QPR:$Vm))))]>; + +def VBICiv4i16 : N1ModImm<1, 0b000, {1,0,?,1}, 0, 0, 1, 1, + (outs DPR:$Vd), (ins nModImm:$SIMM, DPR:$src), + IIC_VMOVImm, + "vbic", "i16", "$Vd, $SIMM", "$src = $Vd", + [(set DPR:$Vd, + (v4i16 (NEONvbicImm DPR:$src, timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VBICiv2i32 : N1ModImm<1, 0b000, {0,?,?,1}, 0, 0, 1, 1, + (outs DPR:$Vd), (ins nModImm:$SIMM, DPR:$src), + IIC_VMOVImm, + "vbic", "i32", "$Vd, $SIMM", "$src = $Vd", + [(set DPR:$Vd, + (v2i32 (NEONvbicImm DPR:$src, timm:$SIMM)))]> { + let Inst{10-9} = SIMM{10-9}; +} + +def VBICiv8i16 : N1ModImm<1, 0b000, {1,0,?,1}, 0, 1, 1, 1, + (outs QPR:$Vd), (ins nModImm:$SIMM, QPR:$src), + IIC_VMOVImm, + "vbic", "i16", "$Vd, $SIMM", "$src = $Vd", + [(set QPR:$Vd, + (v8i16 (NEONvbicImm QPR:$src, timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VBICiv4i32 : N1ModImm<1, 0b000, {0,?,?,1}, 0, 1, 1, 1, + (outs QPR:$Vd), (ins nModImm:$SIMM, QPR:$src), + IIC_VMOVImm, + "vbic", "i32", "$Vd, $SIMM", "$src = $Vd", + [(set QPR:$Vd, + (v4i32 (NEONvbicImm QPR:$src, timm:$SIMM)))]> { + let Inst{10-9} = SIMM{10-9}; +} + +// VORN : Vector Bitwise OR NOT +def VORNd : N3VX<0, 0, 0b11, 0b0001, 0, 1, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm), N3RegFrm, IIC_VBINiD, + "vorn", "$Vd, $Vn, $Vm", "", + [(set DPR:$Vd, (v2i32 (or DPR:$Vn, + (vnotd DPR:$Vm))))]>; +def VORNq : N3VX<0, 0, 0b11, 0b0001, 1, 1, (outs QPR:$Vd), + (ins QPR:$Vn, QPR:$Vm), N3RegFrm, IIC_VBINiQ, + "vorn", "$Vd, $Vn, $Vm", "", + [(set QPR:$Vd, (v4i32 (or QPR:$Vn, + (vnotq QPR:$Vm))))]>; + +// VMVN : Vector Bitwise NOT (Immediate) + +let isReMaterializable = 1 in { + +def VMVNv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 1, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmvn", "i16", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v4i16 (NEONvmvnImm timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VMVNv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 1, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmvn", "i16", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v8i16 (NEONvmvnImm timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VMVNv2i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 0, 1, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmvn", "i32", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v2i32 (NEONvmvnImm timm:$SIMM)))]> { + let Inst{11-8} = SIMM{11-8}; +} + +def VMVNv4i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 1, 1, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmvn", "i32", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v4i32 (NEONvmvnImm timm:$SIMM)))]> { + let Inst{11-8} = SIMM{11-8}; +} +} + +// VMVN : Vector Bitwise NOT +def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0, + (outs DPR:$Vd), (ins DPR:$Vm), IIC_VSUBiD, + "vmvn", "$Vd, $Vm", "", + [(set DPR:$Vd, (v2i32 (vnotd DPR:$Vm)))]>; +def VMVNq : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vm), IIC_VSUBiD, + "vmvn", "$Vd, $Vm", "", + [(set QPR:$Vd, (v4i32 (vnotq QPR:$Vm)))]>; +def : Pat<(v2i32 (vnotd DPR:$src)), (VMVNd DPR:$src)>; +def : Pat<(v4i32 (vnotq QPR:$src)), (VMVNq QPR:$src)>; + +// VBSL : Vector Bitwise Select +def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$Vd), + (ins DPR:$src1, DPR:$Vn, DPR:$Vm), + N3RegFrm, IIC_VCNTiD, + "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [(set DPR:$Vd, + (v2i32 (or (and DPR:$Vn, DPR:$src1), + (and DPR:$Vm, (vnotd DPR:$src1)))))]>; +def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$Vd), + (ins QPR:$src1, QPR:$Vn, QPR:$Vm), + N3RegFrm, IIC_VCNTiQ, + "vbsl", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [(set QPR:$Vd, + (v4i32 (or (and QPR:$Vn, QPR:$src1), + (and QPR:$Vm, (vnotq QPR:$src1)))))]>; + +// VBIF : Vector Bitwise Insert if False +// like VBSL but with: "vbif $dst, $src3, $src1", "$src2 = $dst", +// FIXME: This instruction's encoding MAY NOT BE correct. +def VBIFd : N3VX<1, 0, 0b11, 0b0001, 0, 1, + (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR:$Vm), + N3RegFrm, IIC_VBINiD, + "vbif", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [/* For disassembly only; pattern left blank */]>; +def VBIFq : N3VX<1, 0, 0b11, 0b0001, 1, 1, + (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, QPR:$Vm), + N3RegFrm, IIC_VBINiQ, + "vbif", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [/* For disassembly only; pattern left blank */]>; + +// VBIT : Vector Bitwise Insert if True +// like VBSL but with: "vbit $dst, $src2, $src1", "$src3 = $dst", +// FIXME: This instruction's encoding MAY NOT BE correct. +def VBITd : N3VX<1, 0, 0b10, 0b0001, 0, 1, + (outs DPR:$Vd), (ins DPR:$src1, DPR:$Vn, DPR:$Vm), + N3RegFrm, IIC_VBINiD, + "vbit", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [/* For disassembly only; pattern left blank */]>; +def VBITq : N3VX<1, 0, 0b10, 0b0001, 1, 1, + (outs QPR:$Vd), (ins QPR:$src1, QPR:$Vn, QPR:$Vm), + N3RegFrm, IIC_VBINiQ, + "vbit", "$Vd, $Vn, $Vm", "$src1 = $Vd", + [/* For disassembly only; pattern left blank */]>; + +// VBIT/VBIF are not yet implemented. The TwoAddress pass will not go looking +// for equivalent operations with different register constraints; it just +// inserts copies. + +// Vector Absolute Differences. + +// VABD : Vector Absolute Difference +defm VABDs : N3VInt_QHS<0, 0, 0b0111, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vabd", "s", int_arm_neon_vabds, 1>; +defm VABDu : N3VInt_QHS<1, 0, 0b0111, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vabd", "u", int_arm_neon_vabdu, 1>; +def VABDfd : N3VDInt<1, 0, 0b10, 0b1101, 0, N3RegFrm, IIC_VBIND, + "vabd", "f32", v2f32, v2f32, int_arm_neon_vabds, 1>; +def VABDfq : N3VQInt<1, 0, 0b10, 0b1101, 0, N3RegFrm, IIC_VBINQ, + "vabd", "f32", v4f32, v4f32, int_arm_neon_vabds, 1>; + +// VABDL : Vector Absolute Difference Long (Q = | D - D |) +defm VABDLs : N3VLIntExt_QHS<0,1,0b0111,0, IIC_VSUBi4Q, + "vabdl", "s", int_arm_neon_vabds, zext, 1>; +defm VABDLu : N3VLIntExt_QHS<1,1,0b0111,0, IIC_VSUBi4Q, + "vabdl", "u", int_arm_neon_vabdu, zext, 1>; + +// VABA : Vector Absolute Difference and Accumulate +defm VABAs : N3VIntOp_QHS<0,0,0b0111,1, IIC_VABAD, IIC_VABAQ, + "vaba", "s", int_arm_neon_vabds, add>; +defm VABAu : N3VIntOp_QHS<1,0,0b0111,1, IIC_VABAD, IIC_VABAQ, + "vaba", "u", int_arm_neon_vabdu, add>; + +// VABAL : Vector Absolute Difference and Accumulate Long (Q += | D - D |) +defm VABALs : N3VLIntExtOp_QHS<0,1,0b0101,0, IIC_VABAD, + "vabal", "s", int_arm_neon_vabds, zext, add>; +defm VABALu : N3VLIntExtOp_QHS<1,1,0b0101,0, IIC_VABAD, + "vabal", "u", int_arm_neon_vabdu, zext, add>; + +// Vector Maximum and Minimum. + +// VMAX : Vector Maximum +defm VMAXs : N3VInt_QHS<0, 0, 0b0110, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vmax", "s", int_arm_neon_vmaxs, 1>; +defm VMAXu : N3VInt_QHS<1, 0, 0b0110, 0, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vmax", "u", int_arm_neon_vmaxu, 1>; +def VMAXfd : N3VDInt<0, 0, 0b00, 0b1111, 0, N3RegFrm, IIC_VBIND, + "vmax", "f32", + v2f32, v2f32, int_arm_neon_vmaxs, 1>; +def VMAXfq : N3VQInt<0, 0, 0b00, 0b1111, 0, N3RegFrm, IIC_VBINQ, + "vmax", "f32", + v4f32, v4f32, int_arm_neon_vmaxs, 1>; + +// VMIN : Vector Minimum +defm VMINs : N3VInt_QHS<0, 0, 0b0110, 1, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vmin", "s", int_arm_neon_vmins, 1>; +defm VMINu : N3VInt_QHS<1, 0, 0b0110, 1, N3RegFrm, + IIC_VSUBi4D, IIC_VSUBi4D, IIC_VSUBi4Q, IIC_VSUBi4Q, + "vmin", "u", int_arm_neon_vminu, 1>; +def VMINfd : N3VDInt<0, 0, 0b10, 0b1111, 0, N3RegFrm, IIC_VBIND, + "vmin", "f32", + v2f32, v2f32, int_arm_neon_vmins, 1>; +def VMINfq : N3VQInt<0, 0, 0b10, 0b1111, 0, N3RegFrm, IIC_VBINQ, + "vmin", "f32", + v4f32, v4f32, int_arm_neon_vmins, 1>; + +// Vector Pairwise Operations. + +// VPADD : Vector Pairwise Add +def VPADDi8 : N3VDInt<0, 0, 0b00, 0b1011, 1, N3RegFrm, IIC_VSHLiD, + "vpadd", "i8", + v8i8, v8i8, int_arm_neon_vpadd, 0>; +def VPADDi16 : N3VDInt<0, 0, 0b01, 0b1011, 1, N3RegFrm, IIC_VSHLiD, + "vpadd", "i16", + v4i16, v4i16, int_arm_neon_vpadd, 0>; +def VPADDi32 : N3VDInt<0, 0, 0b10, 0b1011, 1, N3RegFrm, IIC_VSHLiD, + "vpadd", "i32", + v2i32, v2i32, int_arm_neon_vpadd, 0>; +def VPADDf : N3VDInt<1, 0, 0b00, 0b1101, 0, N3RegFrm, + IIC_VPBIND, "vpadd", "f32", + v2f32, v2f32, int_arm_neon_vpadd, 0>; + +// VPADDL : Vector Pairwise Add Long +defm VPADDLs : N2VPLInt_QHS<0b11, 0b11, 0b00, 0b00100, 0, "vpaddl", "s", + int_arm_neon_vpaddls>; +defm VPADDLu : N2VPLInt_QHS<0b11, 0b11, 0b00, 0b00101, 0, "vpaddl", "u", + int_arm_neon_vpaddlu>; + +// VPADAL : Vector Pairwise Add and Accumulate Long +defm VPADALs : N2VPLInt2_QHS<0b11, 0b11, 0b00, 0b01100, 0, "vpadal", "s", + int_arm_neon_vpadals>; +defm VPADALu : N2VPLInt2_QHS<0b11, 0b11, 0b00, 0b01101, 0, "vpadal", "u", + int_arm_neon_vpadalu>; + +// VPMAX : Vector Pairwise Maximum +def VPMAXs8 : N3VDInt<0, 0, 0b00, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "s8", v8i8, v8i8, int_arm_neon_vpmaxs, 0>; +def VPMAXs16 : N3VDInt<0, 0, 0b01, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "s16", v4i16, v4i16, int_arm_neon_vpmaxs, 0>; +def VPMAXs32 : N3VDInt<0, 0, 0b10, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "s32", v2i32, v2i32, int_arm_neon_vpmaxs, 0>; +def VPMAXu8 : N3VDInt<1, 0, 0b00, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "u8", v8i8, v8i8, int_arm_neon_vpmaxu, 0>; +def VPMAXu16 : N3VDInt<1, 0, 0b01, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "u16", v4i16, v4i16, int_arm_neon_vpmaxu, 0>; +def VPMAXu32 : N3VDInt<1, 0, 0b10, 0b1010, 0, N3RegFrm, IIC_VSUBi4D, "vpmax", + "u32", v2i32, v2i32, int_arm_neon_vpmaxu, 0>; +def VPMAXf : N3VDInt<1, 0, 0b00, 0b1111, 0, N3RegFrm, IIC_VPBIND, "vpmax", + "f32", v2f32, v2f32, int_arm_neon_vpmaxs, 0>; + +// VPMIN : Vector Pairwise Minimum +def VPMINs8 : N3VDInt<0, 0, 0b00, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "s8", v8i8, v8i8, int_arm_neon_vpmins, 0>; +def VPMINs16 : N3VDInt<0, 0, 0b01, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "s16", v4i16, v4i16, int_arm_neon_vpmins, 0>; +def VPMINs32 : N3VDInt<0, 0, 0b10, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "s32", v2i32, v2i32, int_arm_neon_vpmins, 0>; +def VPMINu8 : N3VDInt<1, 0, 0b00, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "u8", v8i8, v8i8, int_arm_neon_vpminu, 0>; +def VPMINu16 : N3VDInt<1, 0, 0b01, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "u16", v4i16, v4i16, int_arm_neon_vpminu, 0>; +def VPMINu32 : N3VDInt<1, 0, 0b10, 0b1010, 1, N3RegFrm, IIC_VSUBi4D, "vpmin", + "u32", v2i32, v2i32, int_arm_neon_vpminu, 0>; +def VPMINf : N3VDInt<1, 0, 0b10, 0b1111, 0, N3RegFrm, IIC_VPBIND, "vpmin", + "f32", v2f32, v2f32, int_arm_neon_vpmins, 0>; + +// Vector Reciprocal and Reciprocal Square Root Estimate and Step. + +// VRECPE : Vector Reciprocal Estimate +def VRECPEd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01000, 0, + IIC_VUNAD, "vrecpe", "u32", + v2i32, v2i32, int_arm_neon_vrecpe>; +def VRECPEq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01000, 0, + IIC_VUNAQ, "vrecpe", "u32", + v4i32, v4i32, int_arm_neon_vrecpe>; +def VRECPEfd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01010, 0, + IIC_VUNAD, "vrecpe", "f32", + v2f32, v2f32, int_arm_neon_vrecpe>; +def VRECPEfq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01010, 0, + IIC_VUNAQ, "vrecpe", "f32", + v4f32, v4f32, int_arm_neon_vrecpe>; + +// VRECPS : Vector Reciprocal Step +def VRECPSfd : N3VDInt<0, 0, 0b00, 0b1111, 1, N3RegFrm, + IIC_VRECSD, "vrecps", "f32", + v2f32, v2f32, int_arm_neon_vrecps, 1>; +def VRECPSfq : N3VQInt<0, 0, 0b00, 0b1111, 1, N3RegFrm, + IIC_VRECSQ, "vrecps", "f32", + v4f32, v4f32, int_arm_neon_vrecps, 1>; + +// VRSQRTE : Vector Reciprocal Square Root Estimate +def VRSQRTEd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01001, 0, + IIC_VUNAD, "vrsqrte", "u32", + v2i32, v2i32, int_arm_neon_vrsqrte>; +def VRSQRTEq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01001, 0, + IIC_VUNAQ, "vrsqrte", "u32", + v4i32, v4i32, int_arm_neon_vrsqrte>; +def VRSQRTEfd : N2VDInt<0b11, 0b11, 0b10, 0b11, 0b01011, 0, + IIC_VUNAD, "vrsqrte", "f32", + v2f32, v2f32, int_arm_neon_vrsqrte>; +def VRSQRTEfq : N2VQInt<0b11, 0b11, 0b10, 0b11, 0b01011, 0, + IIC_VUNAQ, "vrsqrte", "f32", + v4f32, v4f32, int_arm_neon_vrsqrte>; + +// VRSQRTS : Vector Reciprocal Square Root Step +def VRSQRTSfd : N3VDInt<0, 0, 0b10, 0b1111, 1, N3RegFrm, + IIC_VRECSD, "vrsqrts", "f32", + v2f32, v2f32, int_arm_neon_vrsqrts, 1>; +def VRSQRTSfq : N3VQInt<0, 0, 0b10, 0b1111, 1, N3RegFrm, + IIC_VRECSQ, "vrsqrts", "f32", + v4f32, v4f32, int_arm_neon_vrsqrts, 1>; + +// Vector Shifts. + +// VSHL : Vector Shift +defm VSHLs : N3VInt_QHSDSh<0, 0, 0b0100, 0, N3RegVShFrm, + IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ, IIC_VSHLiQ, + "vshl", "s", int_arm_neon_vshifts>; +defm VSHLu : N3VInt_QHSDSh<1, 0, 0b0100, 0, N3RegVShFrm, + IIC_VSHLiD, IIC_VSHLiD, IIC_VSHLiQ, IIC_VSHLiQ, + "vshl", "u", int_arm_neon_vshiftu>; +// VSHL : Vector Shift Left (Immediate) +defm VSHLi : N2VSh_QHSD<0, 1, 0b0101, 1, IIC_VSHLiD, "vshl", "i", NEONvshl, + N2RegVShLFrm>; +// VSHR : Vector Shift Right (Immediate) +defm VSHRs : N2VSh_QHSD<0, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "s", NEONvshrs, + N2RegVShRFrm>; +defm VSHRu : N2VSh_QHSD<1, 1, 0b0000, 1, IIC_VSHLiD, "vshr", "u", NEONvshru, + N2RegVShRFrm>; + +// VSHLL : Vector Shift Left Long +defm VSHLLs : N2VLSh_QHS<0, 1, 0b1010, 0, 0, 1, "vshll", "s", NEONvshlls>; +defm VSHLLu : N2VLSh_QHS<1, 1, 0b1010, 0, 0, 1, "vshll", "u", NEONvshllu>; + +// VSHLL : Vector Shift Left Long (with maximum shift count) +class N2VLShMax op21_16, bits<4> op11_8, bit op7, + bit op6, bit op4, string OpcodeStr, string Dt, ValueType ResTy, + ValueType OpTy, SDNode OpNode> + : N2VLSh { + let Inst{21-16} = op21_16; +} +def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8", + v8i16, v8i8, NEONvshlli>; +def VSHLLi16 : N2VLShMax<1, 1, 0b110110, 0b0011, 0, 0, 0, "vshll", "i16", + v4i32, v4i16, NEONvshlli>; +def VSHLLi32 : N2VLShMax<1, 1, 0b111010, 0b0011, 0, 0, 0, "vshll", "i32", + v2i64, v2i32, NEONvshlli>; + +// VSHRN : Vector Shift Right and Narrow +defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i", + NEONvshrn>; + +// VRSHL : Vector Rounding Shift +defm VRSHLs : N3VInt_QHSDSh<0, 0, 0b0101, 0, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vrshl", "s", int_arm_neon_vrshifts>; +defm VRSHLu : N3VInt_QHSDSh<1, 0, 0b0101, 0, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vrshl", "u", int_arm_neon_vrshiftu>; +// VRSHR : Vector Rounding Shift Right +defm VRSHRs : N2VSh_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs, + N2RegVShRFrm>; +defm VRSHRu : N2VSh_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru, + N2RegVShRFrm>; + +// VRSHRN : Vector Rounding Shift Right and Narrow +defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i", + NEONvrshrn>; + +// VQSHL : Vector Saturating Shift +defm VQSHLs : N3VInt_QHSDSh<0, 0, 0b0100, 1, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vqshl", "s", int_arm_neon_vqshifts>; +defm VQSHLu : N3VInt_QHSDSh<1, 0, 0b0100, 1, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vqshl", "u", int_arm_neon_vqshiftu>; +// VQSHL : Vector Saturating Shift Left (Immediate) +defm VQSHLsi : N2VSh_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s",NEONvqshls, + N2RegVShLFrm>; +defm VQSHLui : N2VSh_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u",NEONvqshlu, + N2RegVShLFrm>; +// VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned) +defm VQSHLsu : N2VSh_QHSD<1,1,0b0110,1, IIC_VSHLi4D,"vqshlu","s",NEONvqshlsu, + N2RegVShLFrm>; + +// VQSHRN : Vector Saturating Shift Right and Narrow +defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s", + NEONvqshrns>; +defm VQSHRNu : N2VNSh_HSD<1, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "u", + NEONvqshrnu>; + +// VQSHRUN : Vector Saturating Shift Right and Narrow (Unsigned) +defm VQSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 0, 1, IIC_VSHLi4D, "vqshrun", "s", + NEONvqshrnsu>; + +// VQRSHL : Vector Saturating Rounding Shift +defm VQRSHLs : N3VInt_QHSDSh<0, 0, 0b0101, 1, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vqrshl", "s", int_arm_neon_vqrshifts>; +defm VQRSHLu : N3VInt_QHSDSh<1, 0, 0b0101, 1, N3RegVShFrm, + IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, + "vqrshl", "u", int_arm_neon_vqrshiftu>; + +// VQRSHRN : Vector Saturating Rounding Shift Right and Narrow +defm VQRSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "s", + NEONvqrshrns>; +defm VQRSHRNu : N2VNSh_HSD<1, 1, 0b1001, 0, 1, 1, IIC_VSHLi4D, "vqrshrn", "u", + NEONvqrshrnu>; + +// VQRSHRUN : Vector Saturating Rounding Shift Right and Narrow (Unsigned) +defm VQRSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vqrshrun", "s", + NEONvqrshrnsu>; + +// VSRA : Vector Shift Right and Accumulate +defm VSRAs : N2VShAdd_QHSD<0, 1, 0b0001, 1, "vsra", "s", NEONvshrs>; +defm VSRAu : N2VShAdd_QHSD<1, 1, 0b0001, 1, "vsra", "u", NEONvshru>; +// VRSRA : Vector Rounding Shift Right and Accumulate +defm VRSRAs : N2VShAdd_QHSD<0, 1, 0b0011, 1, "vrsra", "s", NEONvrshrs>; +defm VRSRAu : N2VShAdd_QHSD<1, 1, 0b0011, 1, "vrsra", "u", NEONvrshru>; + +// VSLI : Vector Shift Left and Insert +defm VSLI : N2VShIns_QHSD<1, 1, 0b0101, 1, "vsli", NEONvsli, N2RegVShLFrm>; +// VSRI : Vector Shift Right and Insert +defm VSRI : N2VShIns_QHSD<1, 1, 0b0100, 1, "vsri", NEONvsri, N2RegVShRFrm>; + +// Vector Absolute and Saturating Absolute. + +// VABS : Vector Absolute Value +defm VABS : N2VInt_QHS<0b11, 0b11, 0b01, 0b00110, 0, + IIC_VUNAiD, IIC_VUNAiQ, "vabs", "s", + int_arm_neon_vabs>; +def VABSfd : N2VDInt<0b11, 0b11, 0b10, 0b01, 0b01110, 0, + IIC_VUNAD, "vabs", "f32", + v2f32, v2f32, int_arm_neon_vabs>; +def VABSfq : N2VQInt<0b11, 0b11, 0b10, 0b01, 0b01110, 0, + IIC_VUNAQ, "vabs", "f32", + v4f32, v4f32, int_arm_neon_vabs>; + +// VQABS : Vector Saturating Absolute Value +defm VQABS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01110, 0, + IIC_VQUNAiD, IIC_VQUNAiQ, "vqabs", "s", + int_arm_neon_vqabs>; + +// Vector Negate. + +def vnegd : PatFrag<(ops node:$in), + (sub (bitconvert (v2i32 NEONimmAllZerosV)), node:$in)>; +def vnegq : PatFrag<(ops node:$in), + (sub (bitconvert (v4i32 NEONimmAllZerosV)), node:$in)>; + +class VNEGD size, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, size, 0b01, 0b00111, 0, 0, (outs DPR:$Vd), (ins DPR:$Vm), + IIC_VSHLiD, OpcodeStr, Dt, "$Vd, $Vm", "", + [(set DPR:$Vd, (Ty (vnegd DPR:$Vm)))]>; +class VNEGQ size, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, size, 0b01, 0b00111, 1, 0, (outs QPR:$Vd), (ins QPR:$Vm), + IIC_VSHLiQ, OpcodeStr, Dt, "$Vd, $Vm", "", + [(set QPR:$Vd, (Ty (vnegq QPR:$Vm)))]>; + +// VNEG : Vector Negate (integer) +def VNEGs8d : VNEGD<0b00, "vneg", "s8", v8i8>; +def VNEGs16d : VNEGD<0b01, "vneg", "s16", v4i16>; +def VNEGs32d : VNEGD<0b10, "vneg", "s32", v2i32>; +def VNEGs8q : VNEGQ<0b00, "vneg", "s8", v16i8>; +def VNEGs16q : VNEGQ<0b01, "vneg", "s16", v8i16>; +def VNEGs32q : VNEGQ<0b10, "vneg", "s32", v4i32>; + +// VNEG : Vector Negate (floating-point) +def VNEGfd : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, + (outs DPR:$Vd), (ins DPR:$Vm), IIC_VUNAD, + "vneg", "f32", "$Vd, $Vm", "", + [(set DPR:$Vd, (v2f32 (fneg DPR:$Vm)))]>; +def VNEGf32q : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vm), IIC_VUNAQ, + "vneg", "f32", "$Vd, $Vm", "", + [(set QPR:$Vd, (v4f32 (fneg QPR:$Vm)))]>; + +def : Pat<(v8i8 (vnegd DPR:$src)), (VNEGs8d DPR:$src)>; +def : Pat<(v4i16 (vnegd DPR:$src)), (VNEGs16d DPR:$src)>; +def : Pat<(v2i32 (vnegd DPR:$src)), (VNEGs32d DPR:$src)>; +def : Pat<(v16i8 (vnegq QPR:$src)), (VNEGs8q QPR:$src)>; +def : Pat<(v8i16 (vnegq QPR:$src)), (VNEGs16q QPR:$src)>; +def : Pat<(v4i32 (vnegq QPR:$src)), (VNEGs32q QPR:$src)>; + +// VQNEG : Vector Saturating Negate +defm VQNEG : N2VInt_QHS<0b11, 0b11, 0b00, 0b01111, 0, + IIC_VQUNAiD, IIC_VQUNAiQ, "vqneg", "s", + int_arm_neon_vqneg>; + +// Vector Bit Counting Operations. + +// VCLS : Vector Count Leading Sign Bits +defm VCLS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01000, 0, + IIC_VCNTiD, IIC_VCNTiQ, "vcls", "s", + int_arm_neon_vcls>; +// VCLZ : Vector Count Leading Zeros +defm VCLZ : N2VInt_QHS<0b11, 0b11, 0b00, 0b01001, 0, + IIC_VCNTiD, IIC_VCNTiQ, "vclz", "i", + int_arm_neon_vclz>; +// VCNT : Vector Count One Bits +def VCNTd : N2VDInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0, + IIC_VCNTiD, "vcnt", "8", + v8i8, v8i8, int_arm_neon_vcnt>; +def VCNTq : N2VQInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0, + IIC_VCNTiQ, "vcnt", "8", + v16i8, v16i8, int_arm_neon_vcnt>; + +// Vector Swap -- for disassembly only. +def VSWPd : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 0, 0, + (outs DPR:$Vd), (ins DPR:$Vm), NoItinerary, + "vswp", "$Vd, $Vm", "", []>; +def VSWPq : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 1, 0, + (outs QPR:$Vd), (ins QPR:$Vm), NoItinerary, + "vswp", "$Vd, $Vm", "", []>; + +// Vector Move Operations. + +// VMOV : Vector Move (Register) + +let neverHasSideEffects = 1 in { +def VMOVDneon: N3VX<0, 0, 0b10, 0b0001, 0, 1, (outs DPR:$Vd), (ins DPR:$Vm), + N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> { + let Vn{4-0} = Vm{4-0}; +} +def VMOVQ : N3VX<0, 0, 0b10, 0b0001, 1, 1, (outs QPR:$Vd), (ins QPR:$Vm), + N3RegFrm, IIC_VMOV, "vmov", "$Vd, $Vm", "", []> { + let Vn{4-0} = Vm{4-0}; +} + +// Pseudo vector move instructions for QQ and QQQQ registers. This should +// be expanded after register allocation is completed. +def VMOVQQ : PseudoInst<(outs QQPR:$dst), (ins QQPR:$src), + NoItinerary, []>; + +def VMOVQQQQ : PseudoInst<(outs QQQQPR:$dst), (ins QQQQPR:$src), + NoItinerary, []>; +} // neverHasSideEffects + +// VMOV : Vector Move (Immediate) + +let isReMaterializable = 1 in { +def VMOVv8i8 : N1ModImm<1, 0b000, 0b1110, 0, 0, 0, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i8", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v8i8 (NEONvmovImm timm:$SIMM)))]>; +def VMOVv16i8 : N1ModImm<1, 0b000, 0b1110, 0, 1, 0, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i8", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v16i8 (NEONvmovImm timm:$SIMM)))]>; + +def VMOVv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 0, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i16", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v4i16 (NEONvmovImm timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VMOVv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 0, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i16", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v8i16 (NEONvmovImm timm:$SIMM)))]> { + let Inst{9} = SIMM{9}; +} + +def VMOVv2i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 0, 0, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i32", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v2i32 (NEONvmovImm timm:$SIMM)))]> { + let Inst{11-8} = SIMM{11-8}; +} + +def VMOVv4i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 1, 0, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i32", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v4i32 (NEONvmovImm timm:$SIMM)))]> { + let Inst{11-8} = SIMM{11-8}; +} + +def VMOVv1i64 : N1ModImm<1, 0b000, 0b1110, 0, 0, 1, 1, (outs DPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i64", "$Vd, $SIMM", "", + [(set DPR:$Vd, (v1i64 (NEONvmovImm timm:$SIMM)))]>; +def VMOVv2i64 : N1ModImm<1, 0b000, 0b1110, 0, 1, 1, 1, (outs QPR:$Vd), + (ins nModImm:$SIMM), IIC_VMOVImm, + "vmov", "i64", "$Vd, $SIMM", "", + [(set QPR:$Vd, (v2i64 (NEONvmovImm timm:$SIMM)))]>; +} // isReMaterializable + +// VMOV : Vector Get Lane (move scalar to ARM core register) + +def VGETLNs8 : NVGetLane<{1,1,1,0,0,1,?,1}, 0b1011, {?,?}, + (outs GPR:$R), (ins DPR:$V, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "s8", "$R, $V[$lane]", + [(set GPR:$R, (NEONvgetlanes (v8i8 DPR:$V), + imm:$lane))]> { + let Inst{21} = lane{2}; + let Inst{6-5} = lane{1-0}; +} +def VGETLNs16 : NVGetLane<{1,1,1,0,0,0,?,1}, 0b1011, {?,1}, + (outs GPR:$R), (ins DPR:$V, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "s16", "$R, $V[$lane]", + [(set GPR:$R, (NEONvgetlanes (v4i16 DPR:$V), + imm:$lane))]> { + let Inst{21} = lane{1}; + let Inst{6} = lane{0}; +} +def VGETLNu8 : NVGetLane<{1,1,1,0,1,1,?,1}, 0b1011, {?,?}, + (outs GPR:$R), (ins DPR:$V, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "u8", "$R, $V[$lane]", + [(set GPR:$R, (NEONvgetlaneu (v8i8 DPR:$V), + imm:$lane))]> { + let Inst{21} = lane{2}; + let Inst{6-5} = lane{1-0}; +} +def VGETLNu16 : NVGetLane<{1,1,1,0,1,0,?,1}, 0b1011, {?,1}, + (outs GPR:$R), (ins DPR:$V, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "u16", "$R, $V[$lane]", + [(set GPR:$R, (NEONvgetlaneu (v4i16 DPR:$V), + imm:$lane))]> { + let Inst{21} = lane{1}; + let Inst{6} = lane{0}; +} +def VGETLNi32 : NVGetLane<{1,1,1,0,0,0,?,1}, 0b1011, 0b00, + (outs GPR:$R), (ins DPR:$V, nohash_imm:$lane), + IIC_VMOVSI, "vmov", "32", "$R, $V[$lane]", + [(set GPR:$R, (extractelt (v2i32 DPR:$V), + imm:$lane))]> { + let Inst{21} = lane{0}; +} +// def VGETLNf32: see FMRDH and FMRDL in ARMInstrVFP.td +def : Pat<(NEONvgetlanes (v16i8 QPR:$src), imm:$lane), + (VGETLNs8 (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane))>; +def : Pat<(NEONvgetlanes (v8i16 QPR:$src), imm:$lane), + (VGETLNs16 (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane))>; +def : Pat<(NEONvgetlaneu (v16i8 QPR:$src), imm:$lane), + (VGETLNu8 (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane))>; +def : Pat<(NEONvgetlaneu (v8i16 QPR:$src), imm:$lane), + (VGETLNu16 (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane))>; +def : Pat<(extractelt (v4i32 QPR:$src), imm:$lane), + (VGETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane))>; +def : Pat<(extractelt (v2f32 DPR:$src1), imm:$src2), + (EXTRACT_SUBREG (v2f32 (COPY_TO_REGCLASS (v2f32 DPR:$src1),DPR_VFP2)), + (SSubReg_f32_reg imm:$src2))>; +def : Pat<(extractelt (v4f32 QPR:$src1), imm:$src2), + (EXTRACT_SUBREG (v4f32 (COPY_TO_REGCLASS (v4f32 QPR:$src1),QPR_VFP2)), + (SSubReg_f32_reg imm:$src2))>; +//def : Pat<(extractelt (v2i64 QPR:$src1), imm:$src2), +// (EXTRACT_SUBREG QPR:$src1, (DSubReg_f64_reg imm:$src2))>; +def : Pat<(extractelt (v2f64 QPR:$src1), imm:$src2), + (EXTRACT_SUBREG QPR:$src1, (DSubReg_f64_reg imm:$src2))>; + + +// VMOV : Vector Set Lane (move ARM core register to scalar) + +let Constraints = "$src1 = $V" in { +def VSETLNi8 : NVSetLane<{1,1,1,0,0,1,?,0}, 0b1011, {?,?}, (outs DPR:$V), + (ins DPR:$src1, GPR:$R, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "8", "$V[$lane], $R", + [(set DPR:$V, (vector_insert (v8i8 DPR:$src1), + GPR:$R, imm:$lane))]> { + let Inst{21} = lane{2}; + let Inst{6-5} = lane{1-0}; +} +def VSETLNi16 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, {?,1}, (outs DPR:$V), + (ins DPR:$src1, GPR:$R, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "16", "$V[$lane], $R", + [(set DPR:$V, (vector_insert (v4i16 DPR:$src1), + GPR:$R, imm:$lane))]> { + let Inst{21} = lane{1}; + let Inst{6} = lane{0}; +} +def VSETLNi32 : NVSetLane<{1,1,1,0,0,0,?,0}, 0b1011, 0b00, (outs DPR:$V), + (ins DPR:$src1, GPR:$R, nohash_imm:$lane), + IIC_VMOVISL, "vmov", "32", "$V[$lane], $R", + [(set DPR:$V, (insertelt (v2i32 DPR:$src1), + GPR:$R, imm:$lane))]> { + let Inst{21} = lane{0}; +} +} +def : Pat<(vector_insert (v16i8 QPR:$src1), GPR:$src2, imm:$lane), + (v16i8 (INSERT_SUBREG QPR:$src1, + (v8i8 (VSETLNi8 (v8i8 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i8_reg imm:$lane))), + GPR:$src2, (SubReg_i8_lane imm:$lane))), + (DSubReg_i8_reg imm:$lane)))>; +def : Pat<(vector_insert (v8i16 QPR:$src1), GPR:$src2, imm:$lane), + (v8i16 (INSERT_SUBREG QPR:$src1, + (v4i16 (VSETLNi16 (v4i16 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i16_reg imm:$lane))), + GPR:$src2, (SubReg_i16_lane imm:$lane))), + (DSubReg_i16_reg imm:$lane)))>; +def : Pat<(insertelt (v4i32 QPR:$src1), GPR:$src2, imm:$lane), + (v4i32 (INSERT_SUBREG QPR:$src1, + (v2i32 (VSETLNi32 (v2i32 (EXTRACT_SUBREG QPR:$src1, + (DSubReg_i32_reg imm:$lane))), + GPR:$src2, (SubReg_i32_lane imm:$lane))), + (DSubReg_i32_reg imm:$lane)))>; + +def : Pat<(v2f32 (insertelt DPR:$src1, SPR:$src2, imm:$src3)), + (INSERT_SUBREG (v2f32 (COPY_TO_REGCLASS DPR:$src1, DPR_VFP2)), + SPR:$src2, (SSubReg_f32_reg imm:$src3))>; +def : Pat<(v4f32 (insertelt QPR:$src1, SPR:$src2, imm:$src3)), + (INSERT_SUBREG (v4f32 (COPY_TO_REGCLASS QPR:$src1, QPR_VFP2)), + SPR:$src2, (SSubReg_f32_reg imm:$src3))>; + +//def : Pat<(v2i64 (insertelt QPR:$src1, DPR:$src2, imm:$src3)), +// (INSERT_SUBREG QPR:$src1, DPR:$src2, (DSubReg_f64_reg imm:$src3))>; +def : Pat<(v2f64 (insertelt QPR:$src1, DPR:$src2, imm:$src3)), + (INSERT_SUBREG QPR:$src1, DPR:$src2, (DSubReg_f64_reg imm:$src3))>; + +def : Pat<(v2f32 (scalar_to_vector SPR:$src)), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$src, ssub_0)>; +def : Pat<(v2f64 (scalar_to_vector (f64 DPR:$src))), + (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), DPR:$src, dsub_0)>; +def : Pat<(v4f32 (scalar_to_vector SPR:$src)), + (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), SPR:$src, ssub_0)>; + +def : Pat<(v8i8 (scalar_to_vector GPR:$src)), + (VSETLNi8 (v8i8 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; +def : Pat<(v4i16 (scalar_to_vector GPR:$src)), + (VSETLNi16 (v4i16 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; +def : Pat<(v2i32 (scalar_to_vector GPR:$src)), + (VSETLNi32 (v2i32 (IMPLICIT_DEF)), GPR:$src, (i32 0))>; + +def : Pat<(v16i8 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v16i8 (IMPLICIT_DEF)), + (VSETLNi8 (v8i8 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + dsub_0)>; +def : Pat<(v8i16 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v8i16 (IMPLICIT_DEF)), + (VSETLNi16 (v4i16 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + dsub_0)>; +def : Pat<(v4i32 (scalar_to_vector GPR:$src)), + (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), + (VSETLNi32 (v2i32 (IMPLICIT_DEF)), GPR:$src, (i32 0)), + dsub_0)>; + +// VDUP : Vector Duplicate (from ARM core register to all elements) + +class VDUPD opcod1, bits<2> opcod3, string Dt, ValueType Ty> + : NVDup; +class VDUPQ opcod1, bits<2> opcod3, string Dt, ValueType Ty> + : NVDup; + +def VDUP8d : VDUPD<0b11101100, 0b00, "8", v8i8>; +def VDUP16d : VDUPD<0b11101000, 0b01, "16", v4i16>; +def VDUP32d : VDUPD<0b11101000, 0b00, "32", v2i32>; +def VDUP8q : VDUPQ<0b11101110, 0b00, "8", v16i8>; +def VDUP16q : VDUPQ<0b11101010, 0b01, "16", v8i16>; +def VDUP32q : VDUPQ<0b11101010, 0b00, "32", v4i32>; + +def VDUPfd : NVDup<0b11101000, 0b1011, 0b00, (outs DPR:$V), (ins GPR:$R), + IIC_VMOVIS, "vdup", "32", "$V, $R", + [(set DPR:$V, (v2f32 (NEONvdup + (f32 (bitconvert GPR:$R)))))]>; +def VDUPfq : NVDup<0b11101010, 0b1011, 0b00, (outs QPR:$V), (ins GPR:$R), + IIC_VMOVIS, "vdup", "32", "$V, $R", + [(set QPR:$V, (v4f32 (NEONvdup + (f32 (bitconvert GPR:$R)))))]>; + +// VDUP : Vector Duplicate Lane (from scalar to all elements) + +class VDUPLND op19_16, string OpcodeStr, string Dt, + ValueType Ty> + : NVDupLane; + +class VDUPLNQ op19_16, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy> + : NVDupLane; + +// Inst{19-16} is partially specified depending on the element size. + +def VDUPLN8d : VDUPLND<{?,?,?,1}, "vdup", "8", v8i8> { + let Inst{19-17} = lane{2-0}; +} +def VDUPLN16d : VDUPLND<{?,?,1,0}, "vdup", "16", v4i16> { + let Inst{19-18} = lane{1-0}; +} +def VDUPLN32d : VDUPLND<{?,1,0,0}, "vdup", "32", v2i32> { + let Inst{19} = lane{0}; +} +def VDUPLNfd : VDUPLND<{?,1,0,0}, "vdup", "32", v2f32> { + let Inst{19} = lane{0}; +} +def VDUPLN8q : VDUPLNQ<{?,?,?,1}, "vdup", "8", v16i8, v8i8> { + let Inst{19-17} = lane{2-0}; +} +def VDUPLN16q : VDUPLNQ<{?,?,1,0}, "vdup", "16", v8i16, v4i16> { + let Inst{19-18} = lane{1-0}; +} +def VDUPLN32q : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4i32, v2i32> { + let Inst{19} = lane{0}; +} +def VDUPLNfq : VDUPLNQ<{?,1,0,0}, "vdup", "32", v4f32, v2f32> { + let Inst{19} = lane{0}; +} + +def : Pat<(v16i8 (NEONvduplane (v16i8 QPR:$src), imm:$lane)), + (v16i8 (VDUPLN8q (v8i8 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i8_reg imm:$lane))), + (SubReg_i8_lane imm:$lane)))>; +def : Pat<(v8i16 (NEONvduplane (v8i16 QPR:$src), imm:$lane)), + (v8i16 (VDUPLN16q (v4i16 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i16_reg imm:$lane))), + (SubReg_i16_lane imm:$lane)))>; +def : Pat<(v4i32 (NEONvduplane (v4i32 QPR:$src), imm:$lane)), + (v4i32 (VDUPLN32q (v2i32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; +def : Pat<(v4f32 (NEONvduplane (v4f32 QPR:$src), imm:$lane)), + (v4f32 (VDUPLNfq (v2f32 (EXTRACT_SUBREG QPR:$src, + (DSubReg_i32_reg imm:$lane))), + (SubReg_i32_lane imm:$lane)))>; + +def VDUPfdf : PseudoNeonI<(outs DPR:$dst), (ins SPR:$src), IIC_VMOVD, "", + [(set DPR:$dst, (v2f32 (NEONvdup (f32 SPR:$src))))]>; +def VDUPfqf : PseudoNeonI<(outs QPR:$dst), (ins SPR:$src), IIC_VMOVD, "", + [(set QPR:$dst, (v4f32 (NEONvdup (f32 SPR:$src))))]>; + +// VMOVN : Vector Narrowing Move +defm VMOVN : N2VN_HSD<0b11,0b11,0b10,0b00100,0,0, IIC_VMOVN, + "vmovn", "i", trunc>; +// VQMOVN : Vector Saturating Narrowing Move +defm VQMOVNs : N2VNInt_HSD<0b11,0b11,0b10,0b00101,0,0, IIC_VQUNAiD, + "vqmovn", "s", int_arm_neon_vqmovns>; +defm VQMOVNu : N2VNInt_HSD<0b11,0b11,0b10,0b00101,1,0, IIC_VQUNAiD, + "vqmovn", "u", int_arm_neon_vqmovnu>; +defm VQMOVNsu : N2VNInt_HSD<0b11,0b11,0b10,0b00100,1,0, IIC_VQUNAiD, + "vqmovun", "s", int_arm_neon_vqmovnsu>; +// VMOVL : Vector Lengthening Move +defm VMOVLs : N2VL_QHS<0b01,0b10100,0,1, "vmovl", "s", sext>; +defm VMOVLu : N2VL_QHS<0b11,0b10100,0,1, "vmovl", "u", zext>; + +// Vector Conversions. + +// VCVT : Vector Convert Between Floating-Point and Integers +def VCVTf2sd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v2i32, v2f32, fp_to_sint>; +def VCVTf2ud : N2VD<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v2i32, v2f32, fp_to_uint>; +def VCVTs2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v2f32, v2i32, sint_to_fp>; +def VCVTu2fd : N2VD<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v2f32, v2i32, uint_to_fp>; + +def VCVTf2sq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v4i32, v4f32, fp_to_sint>; +def VCVTf2uq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v4i32, v4f32, fp_to_uint>; +def VCVTs2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v4f32, v4i32, sint_to_fp>; +def VCVTu2fq : N2VQ<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v4f32, v4i32, uint_to_fp>; + +// VCVT : Vector Convert Between Floating-Point and Fixed-Point. +def VCVTf2xsd : N2VCvtD<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32", + v2i32, v2f32, int_arm_neon_vcvtfp2fxs>; +def VCVTf2xud : N2VCvtD<1, 1, 0b1111, 0, 1, "vcvt", "u32.f32", + v2i32, v2f32, int_arm_neon_vcvtfp2fxu>; +def VCVTxs2fd : N2VCvtD<0, 1, 0b1110, 0, 1, "vcvt", "f32.s32", + v2f32, v2i32, int_arm_neon_vcvtfxs2fp>; +def VCVTxu2fd : N2VCvtD<1, 1, 0b1110, 0, 1, "vcvt", "f32.u32", + v2f32, v2i32, int_arm_neon_vcvtfxu2fp>; + +def VCVTf2xsq : N2VCvtQ<0, 1, 0b1111, 0, 1, "vcvt", "s32.f32", + v4i32, v4f32, int_arm_neon_vcvtfp2fxs>; +def VCVTf2xuq : N2VCvtQ<1, 1, 0b1111, 0, 1, "vcvt", "u32.f32", + v4i32, v4f32, int_arm_neon_vcvtfp2fxu>; +def VCVTxs2fq : N2VCvtQ<0, 1, 0b1110, 0, 1, "vcvt", "f32.s32", + v4f32, v4i32, int_arm_neon_vcvtfxs2fp>; +def VCVTxu2fq : N2VCvtQ<1, 1, 0b1110, 0, 1, "vcvt", "f32.u32", + v4f32, v4i32, int_arm_neon_vcvtfxu2fp>; + +// VCVT : Vector Convert Between Half-Precision and Single-Precision. +def VCVTf2h : N2VNInt<0b11, 0b11, 0b01, 0b10, 0b01100, 0, 0, + IIC_VUNAQ, "vcvt", "f16.f32", + v4i16, v4f32, int_arm_neon_vcvtfp2hf>, + Requires<[HasNEON, HasFP16]>; +def VCVTh2f : N2VLInt<0b11, 0b11, 0b01, 0b10, 0b01110, 0, 0, + IIC_VUNAQ, "vcvt", "f32.f16", + v4f32, v4i16, int_arm_neon_vcvthf2fp>, + Requires<[HasNEON, HasFP16]>; + +// Vector Reverse. + +// VREV64 : Vector Reverse elements within 64-bit doublewords + +class VREV64D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 0, 0, (outs DPR:$Vd), + (ins DPR:$Vm), IIC_VMOVD, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set DPR:$Vd, (Ty (NEONvrev64 (Ty DPR:$Vm))))]>; +class VREV64Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00000, 1, 0, (outs QPR:$Vd), + (ins QPR:$Vm), IIC_VMOVQ, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set QPR:$Vd, (Ty (NEONvrev64 (Ty QPR:$Vm))))]>; + +def VREV64d8 : VREV64D<0b00, "vrev64", "8", v8i8>; +def VREV64d16 : VREV64D<0b01, "vrev64", "16", v4i16>; +def VREV64d32 : VREV64D<0b10, "vrev64", "32", v2i32>; +def VREV64df : VREV64D<0b10, "vrev64", "32", v2f32>; + +def VREV64q8 : VREV64Q<0b00, "vrev64", "8", v16i8>; +def VREV64q16 : VREV64Q<0b01, "vrev64", "16", v8i16>; +def VREV64q32 : VREV64Q<0b10, "vrev64", "32", v4i32>; +def VREV64qf : VREV64Q<0b10, "vrev64", "32", v4f32>; + +// VREV32 : Vector Reverse elements within 32-bit words + +class VREV32D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 0, 0, (outs DPR:$Vd), + (ins DPR:$Vm), IIC_VMOVD, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set DPR:$Vd, (Ty (NEONvrev32 (Ty DPR:$Vm))))]>; +class VREV32Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00001, 1, 0, (outs QPR:$Vd), + (ins QPR:$Vm), IIC_VMOVQ, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set QPR:$Vd, (Ty (NEONvrev32 (Ty QPR:$Vm))))]>; + +def VREV32d8 : VREV32D<0b00, "vrev32", "8", v8i8>; +def VREV32d16 : VREV32D<0b01, "vrev32", "16", v4i16>; + +def VREV32q8 : VREV32Q<0b00, "vrev32", "8", v16i8>; +def VREV32q16 : VREV32Q<0b01, "vrev32", "16", v8i16>; + +// VREV16 : Vector Reverse elements within 16-bit halfwords + +class VREV16D op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 0, 0, (outs DPR:$Vd), + (ins DPR:$Vm), IIC_VMOVD, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set DPR:$Vd, (Ty (NEONvrev16 (Ty DPR:$Vm))))]>; +class VREV16Q op19_18, string OpcodeStr, string Dt, ValueType Ty> + : N2V<0b11, 0b11, op19_18, 0b00, 0b00010, 1, 0, (outs QPR:$Vd), + (ins QPR:$Vm), IIC_VMOVQ, + OpcodeStr, Dt, "$Vd, $Vm", "", + [(set QPR:$Vd, (Ty (NEONvrev16 (Ty QPR:$Vm))))]>; + +def VREV16d8 : VREV16D<0b00, "vrev16", "8", v8i8>; +def VREV16q8 : VREV16Q<0b00, "vrev16", "8", v16i8>; + +// Other Vector Shuffles. + +// Aligned extractions: really just dropping registers + +class AlignedVEXTq + : Pat<(DestTy (vector_extract_subvec (SrcTy QPR:$src), (i32 imm:$start))), + (EXTRACT_SUBREG (SrcTy QPR:$src), (LaneCVT imm:$start))>; + +def : AlignedVEXTq; + +def : AlignedVEXTq; + +def : AlignedVEXTq; + +def : AlignedVEXTq; + +def : AlignedVEXTq; + + +// VEXT : Vector Extract + +class VEXTd + : N3V<0,1,0b11,{?,?,?,?},0,0, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm, i32imm:$index), NVExtFrm, + IIC_VEXTD, OpcodeStr, Dt, "$Vd, $Vn, $Vm, $index", "", + [(set DPR:$Vd, (Ty (NEONvext (Ty DPR:$Vn), + (Ty DPR:$Vm), imm:$index)))]> { + bits<4> index; + let Inst{11-8} = index{3-0}; +} + +class VEXTq + : N3V<0,1,0b11,{?,?,?,?},1,0, (outs QPR:$Vd), + (ins QPR:$Vn, QPR:$Vm, i32imm:$index), NVExtFrm, + IIC_VEXTQ, OpcodeStr, Dt, "$Vd, $Vn, $Vm, $index", "", + [(set QPR:$Vd, (Ty (NEONvext (Ty QPR:$Vn), + (Ty QPR:$Vm), imm:$index)))]> { + bits<4> index; + let Inst{11-8} = index{3-0}; +} + +def VEXTd8 : VEXTd<"vext", "8", v8i8> { + let Inst{11-8} = index{3-0}; +} +def VEXTd16 : VEXTd<"vext", "16", v4i16> { + let Inst{11-9} = index{2-0}; + let Inst{8} = 0b0; +} +def VEXTd32 : VEXTd<"vext", "32", v2i32> { + let Inst{11-10} = index{1-0}; + let Inst{9-8} = 0b00; +} +def VEXTdf : VEXTd<"vext", "32", v2f32> { + let Inst{11} = index{0}; + let Inst{10-8} = 0b000; +} + +def VEXTq8 : VEXTq<"vext", "8", v16i8> { + let Inst{11-8} = index{3-0}; +} +def VEXTq16 : VEXTq<"vext", "16", v8i16> { + let Inst{11-9} = index{2-0}; + let Inst{8} = 0b0; +} +def VEXTq32 : VEXTq<"vext", "32", v4i32> { + let Inst{11-10} = index{1-0}; + let Inst{9-8} = 0b00; +} +def VEXTqf : VEXTq<"vext", "32", v4f32> { + let Inst{11} = index{0}; + let Inst{10-8} = 0b000; +} + +// VTRN : Vector Transpose + +def VTRNd8 : N2VDShuffle<0b00, 0b00001, "vtrn", "8">; +def VTRNd16 : N2VDShuffle<0b01, 0b00001, "vtrn", "16">; +def VTRNd32 : N2VDShuffle<0b10, 0b00001, "vtrn", "32">; + +def VTRNq8 : N2VQShuffle<0b00, 0b00001, IIC_VPERMQ, "vtrn", "8">; +def VTRNq16 : N2VQShuffle<0b01, 0b00001, IIC_VPERMQ, "vtrn", "16">; +def VTRNq32 : N2VQShuffle<0b10, 0b00001, IIC_VPERMQ, "vtrn", "32">; + +// VUZP : Vector Unzip (Deinterleave) + +def VUZPd8 : N2VDShuffle<0b00, 0b00010, "vuzp", "8">; +def VUZPd16 : N2VDShuffle<0b01, 0b00010, "vuzp", "16">; +def VUZPd32 : N2VDShuffle<0b10, 0b00010, "vuzp", "32">; + +def VUZPq8 : N2VQShuffle<0b00, 0b00010, IIC_VPERMQ3, "vuzp", "8">; +def VUZPq16 : N2VQShuffle<0b01, 0b00010, IIC_VPERMQ3, "vuzp", "16">; +def VUZPq32 : N2VQShuffle<0b10, 0b00010, IIC_VPERMQ3, "vuzp", "32">; + +// VZIP : Vector Zip (Interleave) + +def VZIPd8 : N2VDShuffle<0b00, 0b00011, "vzip", "8">; +def VZIPd16 : N2VDShuffle<0b01, 0b00011, "vzip", "16">; +def VZIPd32 : N2VDShuffle<0b10, 0b00011, "vzip", "32">; + +def VZIPq8 : N2VQShuffle<0b00, 0b00011, IIC_VPERMQ3, "vzip", "8">; +def VZIPq16 : N2VQShuffle<0b01, 0b00011, IIC_VPERMQ3, "vzip", "16">; +def VZIPq32 : N2VQShuffle<0b10, 0b00011, IIC_VPERMQ3, "vzip", "32">; + +// Vector Table Lookup and Table Extension. + +// VTBL : Vector Table Lookup +def VTBL1 + : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1, + "vtbl", "8", "$Vd, \\{$Vn\\}, $Vm", "", + [(set DPR:$Vd, (v8i8 (int_arm_neon_vtbl1 DPR:$Vn, DPR:$Vm)))]>; +let hasExtraSrcRegAllocReq = 1 in { +def VTBL2 + : N3V<1,1,0b11,0b1001,0,0, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$tbl2, DPR:$Vm), NVTBLFrm, IIC_VTB2, + "vtbl", "8", "$Vd, \\{$Vn, $tbl2\\}, $Vm", "", []>; +def VTBL3 + : N3V<1,1,0b11,0b1010,0,0, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$tbl2, DPR:$tbl3, DPR:$Vm), NVTBLFrm, IIC_VTB3, + "vtbl", "8", "$Vd, \\{$Vn, $tbl2, $tbl3\\}, $Vm", "", []>; +def VTBL4 + : N3V<1,1,0b11,0b1011,0,0, (outs DPR:$Vd), + (ins DPR:$Vn, DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$Vm), + NVTBLFrm, IIC_VTB4, + "vtbl", "8", "$Vd, \\{$Vn, $tbl2, $tbl3, $tbl4\\}, $Vm", "", []>; +} // hasExtraSrcRegAllocReq = 1 + +def VTBL2Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins QPR:$tbl, DPR:$src), IIC_VTB2, "", []>; +def VTBL3Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins QQPR:$tbl, DPR:$src), IIC_VTB3, "", []>; +def VTBL4Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins QQPR:$tbl, DPR:$src), IIC_VTB4, "", []>; + +// VTBX : Vector Table Extension +def VTBX1 + : N3V<1,1,0b11,0b1000,1,0, (outs DPR:$Vd), + (ins DPR:$orig, DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTBX1, + "vtbx", "8", "$Vd, \\{$Vn\\}, $Vm", "$orig = $Vd", + [(set DPR:$Vd, (v8i8 (int_arm_neon_vtbx1 + DPR:$orig, DPR:$Vn, DPR:$Vm)))]>; +let hasExtraSrcRegAllocReq = 1 in { +def VTBX2 + : N3V<1,1,0b11,0b1001,1,0, (outs DPR:$Vd), + (ins DPR:$orig, DPR:$Vn, DPR:$tbl2, DPR:$Vm), NVTBLFrm, IIC_VTBX2, + "vtbx", "8", "$Vd, \\{$Vn, $tbl2\\}, $Vm", "$orig = $Vd", []>; +def VTBX3 + : N3V<1,1,0b11,0b1010,1,0, (outs DPR:$Vd), + (ins DPR:$orig, DPR:$Vn, DPR:$tbl2, DPR:$tbl3, DPR:$Vm), + NVTBLFrm, IIC_VTBX3, + "vtbx", "8", "$Vd, \\{$Vn, $tbl2, $tbl3\\}, $Vm", + "$orig = $Vd", []>; +def VTBX4 + : N3V<1,1,0b11,0b1011,1,0, (outs DPR:$Vd), (ins DPR:$orig, DPR:$Vn, + DPR:$tbl2, DPR:$tbl3, DPR:$tbl4, DPR:$Vm), NVTBLFrm, IIC_VTBX4, + "vtbx", "8", "$Vd, \\{$Vn, $tbl2, $tbl3, $tbl4\\}, $Vm", + "$orig = $Vd", []>; +} // hasExtraSrcRegAllocReq = 1 + +def VTBX2Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QPR:$tbl, DPR:$src), + IIC_VTBX2, "$orig = $dst", []>; +def VTBX3Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src), + IIC_VTBX3, "$orig = $dst", []>; +def VTBX4Pseudo + : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src), + IIC_VTBX4, "$orig = $dst", []>; + +//===----------------------------------------------------------------------===// +// NEON instructions for single-precision FP math +//===----------------------------------------------------------------------===// + +class N2VSPat + : NEONFPPat<(f32 (OpNode SPR:$a)), + (EXTRACT_SUBREG + (v2f32 (COPY_TO_REGCLASS (Inst + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$a, ssub_0)), DPR_VFP2)), ssub_0)>; + +class N3VSPat + : NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)), + (EXTRACT_SUBREG + (v2f32 (COPY_TO_REGCLASS (Inst + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$a, ssub_0), + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$b, ssub_0)), DPR_VFP2)), ssub_0)>; + +class N3VSMulOpPat + : NEONFPPat<(f32 (OpNode SPR:$acc, (f32 (MulNode SPR:$a, SPR:$b)))), + (EXTRACT_SUBREG + (v2f32 (COPY_TO_REGCLASS (Inst + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$acc, ssub_0), + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$a, ssub_0), + (INSERT_SUBREG + (v2f32 (COPY_TO_REGCLASS (v2f32 (IMPLICIT_DEF)), DPR_VFP2)), + SPR:$b, ssub_0)), DPR_VFP2)), ssub_0)>; + +def : N3VSPat; +def : N3VSPat; +def : N3VSPat; +def : N3VSMulOpPat, + Requires<[HasNEON, UseNEONForFP, UseFPVMLx]>; +def : N3VSMulOpPat, + Requires<[HasNEON, UseNEONForFP, UseFPVMLx]>; +def : N2VSPat; +def : N2VSPat; +def : N3VSPat; +def : N3VSPat; +def : N2VSPat; +def : N2VSPat; +def : N2VSPat; +def : N2VSPat; + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns +//===----------------------------------------------------------------------===// + +// bit_convert +def : Pat<(v1i64 (bitconvert (v2i32 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v4i16 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v8i8 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (f64 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v1i64 (bitconvert (v2f32 DPR:$src))), (v1i64 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v1i64 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v4i16 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v8i8 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (f64 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v2i32 (bitconvert (v2f32 DPR:$src))), (v2i32 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v1i64 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v2i32 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v8i8 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (f64 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v4i16 (bitconvert (v2f32 DPR:$src))), (v4i16 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v1i64 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v2i32 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v4i16 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (f64 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(v8i8 (bitconvert (v2f32 DPR:$src))), (v8i8 DPR:$src)>; +def : Pat<(f64 (bitconvert (v1i64 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v2i32 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v4i16 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v8i8 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(f64 (bitconvert (v2f32 DPR:$src))), (f64 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (f64 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v1i64 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v2i32 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v4i16 DPR:$src))), (v2f32 DPR:$src)>; +def : Pat<(v2f32 (bitconvert (v8i8 DPR:$src))), (v2f32 DPR:$src)>; + +def : Pat<(v2i64 (bitconvert (v4i32 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v8i16 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v16i8 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v2f64 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v2i64 (bitconvert (v4f32 QPR:$src))), (v2i64 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v2i64 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v8i16 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v16i8 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v2f64 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v4i32 (bitconvert (v4f32 QPR:$src))), (v4i32 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v2i64 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v4i32 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v16i8 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v2f64 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v8i16 (bitconvert (v4f32 QPR:$src))), (v8i16 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v2i64 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v4i32 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v8i16 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v2f64 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v16i8 (bitconvert (v4f32 QPR:$src))), (v16i8 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v2i64 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v4i32 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v8i16 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v16i8 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v4f32 (bitconvert (v2f64 QPR:$src))), (v4f32 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v2i64 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v4i32 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v8i16 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v16i8 QPR:$src))), (v2f64 QPR:$src)>; +def : Pat<(v2f64 (bitconvert (v4f32 QPR:$src))), (v2f64 QPR:$src)>; diff --git a/final/lib/Target/ARM/ARMInstrThumb.td b/final/lib/Target/ARM/ARMInstrThumb.td new file mode 100644 index 00000000000..826ef46bcdb --- /dev/null +++ b/final/lib/Target/ARM/ARMInstrThumb.td @@ -0,0 +1,1550 @@ +//===- ARMInstrThumb.td - Thumb support for ARM ------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the Thumb instruction set. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Thumb specific DAG Nodes. +// + +def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; + +def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); +}]>; +def imm_comp_XFORM : SDNodeXFormgetTargetConstant(~((uint32_t)N->getZExtValue()), MVT::i32); +}]>; + +/// imm0_7 predicate - True if the 32-bit immediate is in the range [0,7]. +def imm0_7 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 8; +}]>; +def imm0_7_neg : PatLeaf<(i32 imm), [{ + return (uint32_t)-N->getZExtValue() < 8; +}], imm_neg_XFORM>; + +def imm0_255 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() < 256; +}]>; +def imm0_255_comp : PatLeaf<(i32 imm), [{ + return ~((uint32_t)N->getZExtValue()) < 256; +}]>; + +def imm8_255 : PatLeaf<(i32 imm), [{ + return (uint32_t)N->getZExtValue() >= 8 && (uint32_t)N->getZExtValue() < 256; +}]>; +def imm8_255_neg : PatLeaf<(i32 imm), [{ + unsigned Val = -N->getZExtValue(); + return Val >= 8 && Val < 256; +}], imm_neg_XFORM>; + +// Break imm's up into two pieces: an immediate + a left shift. This uses +// thumb_immshifted to match and thumb_immshifted_val and thumb_immshifted_shamt +// to get the val/shift pieces. +def thumb_immshifted : PatLeaf<(imm), [{ + return ARM_AM::isThumbImmShiftedVal((unsigned)N->getZExtValue()); +}]>; + +def thumb_immshifted_val : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +def thumb_immshifted_shamt : SDNodeXFormgetZExtValue()); + return CurDAG->getTargetConstant(V, MVT::i32); +}]>; + +// ADR instruction labels. +def t_adrlabel : Operand { + let EncoderMethod = "getThumbAdrLabelOpValue"; +} + +// Scaled 4 immediate. +def t_imm_s4 : Operand { + let PrintMethod = "printThumbS4ImmOperand"; +} + +// Define Thumb specific addressing modes. + +def t_brtarget : Operand { + let EncoderMethod = "getThumbBRTargetOpValue"; +} + +def t_bcctarget : Operand { + let EncoderMethod = "getThumbBCCTargetOpValue"; +} + +def t_cbtarget : Operand { + let EncoderMethod = "getThumbCBTargetOpValue"; +} + +def t_bltarget : Operand { + let EncoderMethod = "getThumbBLTargetOpValue"; +} + +def t_blxtarget : Operand { + let EncoderMethod = "getThumbBLXTargetOpValue"; +} + +def MemModeRegThumbAsmOperand : AsmOperandClass { + let Name = "MemModeRegThumb"; + let SuperClasses = []; +} + +def MemModeImmThumbAsmOperand : AsmOperandClass { + let Name = "MemModeImmThumb"; + let SuperClasses = []; +} + +// t_addrmode_rr := reg + reg +// +def t_addrmode_rr : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); +} + +// t_addrmode_rrs := reg + reg +// +def t_addrmode_rrs1 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; +} +def t_addrmode_rrs2 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; +} +def t_addrmode_rrs4 : Operand, + ComplexPattern { + let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let PrintMethod = "printThumbAddrModeRROperand"; + let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); + let ParserMatchClass = MemModeRegThumbAsmOperand; +} + +// t_addrmode_is4 := reg + imm5 * 4 +// +def t_addrmode_is4 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S4Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_is2 := reg + imm5 * 2 +// +def t_addrmode_is2 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S2Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_is1 := reg + imm5 +// +def t_addrmode_is1 : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeISOpValue"; + let PrintMethod = "printThumbAddrModeImm5S1Operand"; + let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_sp := sp + imm8 * 4 +// +def t_addrmode_sp : Operand, + ComplexPattern { + let EncoderMethod = "getAddrModeThumbSPOpValue"; + let PrintMethod = "printThumbAddrModeSPOperand"; + let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); + let ParserMatchClass = MemModeImmThumbAsmOperand; +} + +// t_addrmode_pc :=
} + +define void @getAndMoveToFrontDecode() { + br label %endif.2 + +endif.2: ; preds = %loopexit.5, %0 + br i1 false, label %loopentry.5, label %UnifiedExitNode + +loopentry.5: ; preds = %loopexit.6, %endif.2 + br i1 false, label %loopentry.6, label %UnifiedExitNode + +loopentry.6: ; preds = %loopentry.7, %loopentry.5 + br i1 false, label %loopentry.7, label %loopexit.6 + +loopentry.7: ; preds = %loopentry.7, %loopentry.6 + br i1 false, label %loopentry.7, label %loopentry.6 + +loopexit.6: ; preds = %loopentry.6 + br i1 false, label %loopentry.5, label %loopexit.5 + +loopexit.5: ; preds = %loopexit.6 + br i1 false, label %endif.2, label %UnifiedExitNode + +UnifiedExitNode: ; preds = %loopexit.5, %loopentry.5, %endif.2 + ret void +} diff --git a/final/test/Analysis/LoopInfo/dg.exp b/final/test/Analysis/LoopInfo/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Analysis/LoopInfo/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll b/final/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll new file mode 100644 index 00000000000..b73b7f03f7e --- /dev/null +++ b/final/test/Analysis/PostDominators/2006-09-26-PostDominanceFrontier.ll @@ -0,0 +1,97 @@ +; RUN: opt < %s -analyze -postdomfrontier \ +; RUN: -disable-verify +; ModuleID = '2006-09-26-PostDominanceFrontier.bc' +target datalayout = "e-p:64:64" +target triple = "alphaev67-unknown-linux-gnu" + %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i32, [44 x i8] } + %struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, i32 } +@TOP = external global i64* ; [#uses=1] +@BOT = external global i64* ; [#uses=1] +@str = external global [2 x i8] ; <[2 x i8]*> [#uses=0] + +declare void @fopen() + +define void @main(i8** %argv) { +entry: + %netSelect.i507 = alloca i64, align 8 ; [#uses=0] + %topStart.i = alloca i64, align 8 ; [#uses=0] + %topEnd.i = alloca i64, align 8 ; [#uses=0] + %botStart.i = alloca i64, align 8 ; [#uses=0] + %botEnd.i = alloca i64, align 8 ; [#uses=0] + %c1.i154 = alloca i32, align 4 ; [#uses=0] + %b1.i155 = alloca i32, align 4 ; [#uses=0] + %t1.i156 = alloca i32, align 4 ; [#uses=0] + %c1.i = alloca i32, align 4 ; [#uses=0] + %b1.i = alloca i32, align 4 ; [#uses=0] + %t1.i = alloca i32, align 4 ; [#uses=0] + %netSelect.i5 = alloca i64, align 8 ; [#uses=0] + %netSelect.i = alloca i64, align 8 ; [#uses=0] + %tmp2.i = getelementptr i8** %argv, i32 1 ; [#uses=1] + %tmp3.i4 = load i8** %tmp2.i ; [#uses=0] + call void @fopen( ) + br i1 false, label %DimensionChannel.exit, label %bb.backedge.i + +bb.backedge.i: ; preds = %entry + ret void + +DimensionChannel.exit: ; preds = %entry + %tmp13.i137 = malloc i64, i32 0 ; [#uses=1] + %tmp610.i = malloc i64, i32 0 ; [#uses=1] + br label %cond_true.i143 + +cond_true.i143: ; preds = %cond_true.i143, %DimensionChannel.exit + %tmp9.i140 = getelementptr i64* %tmp13.i137, i64 0 ; [#uses=0] + %tmp12.i = getelementptr i64* %tmp610.i, i64 0 ; [#uses=0] + br i1 false, label %bb18.i144, label %cond_true.i143 + +bb18.i144: ; preds = %cond_true.i143 + call void @fopen( ) + %tmp76.i105 = malloc i64, i32 0 ; [#uses=3] + %tmp674.i = malloc i64, i32 0 ; [#uses=2] + %tmp1072.i = malloc i64, i32 0 ; [#uses=2] + %tmp1470.i = malloc i64, i32 0 ; [#uses=1] + br label %cond_true.i114 + +cond_true.i114: ; preds = %cond_true.i114, %bb18.i144 + %tmp17.i108 = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + %tmp20.i = getelementptr i64* %tmp674.i, i64 0 ; [#uses=0] + %tmp23.i111 = getelementptr i64* %tmp1470.i, i64 0 ; [#uses=0] + br i1 false, label %cond_true40.i, label %cond_true.i114 + +cond_true40.i: ; preds = %cond_true40.i, %cond_true.i114 + %tmp33.i115 = getelementptr i64* %tmp1072.i, i64 0 ; [#uses=0] + br i1 false, label %bb142.i, label %cond_true40.i + +cond_next54.i: ; preds = %cond_true76.i + %tmp57.i = getelementptr i64* %tmp55.i, i64 0 ; [#uses=0] + br i1 false, label %bb64.i, label %bb69.i + +bb64.i: ; preds = %cond_true76.i, %cond_next54.i + %tmp67.i117 = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + br i1 false, label %bb114.i, label %cond_true111.i + +bb69.i: ; preds = %cond_next54.i + br i1 false, label %bb79.i, label %cond_true76.i + +cond_true76.i: ; preds = %bb142.i, %bb69.i + %tmp48.i = getelementptr i64* %tmp46.i, i64 0 ; [#uses=0] + br i1 false, label %bb64.i, label %cond_next54.i + +bb79.i: ; preds = %bb69.i + br i1 false, label %bb114.i, label %cond_true111.i + +cond_true111.i: ; preds = %bb79.i, %bb64.i + %tmp84.i127 = getelementptr i64* %tmp46.i, i64 0 ; [#uses=0] + ret void + +bb114.i: ; preds = %bb142.i, %bb79.i, %bb64.i + %tmp117.i = getelementptr i64* %tmp76.i105, i64 0 ; [#uses=0] + %tmp132.i131 = getelementptr i64* %tmp674.i, i64 0 ; [#uses=0] + %tmp122.i = getelementptr i64* %tmp1072.i, i64 0 ; [#uses=0] + ret void + +bb142.i: ; preds = %cond_true40.i + %tmp46.i = load i64** @BOT ; [#uses=2] + %tmp55.i = load i64** @TOP ; [#uses=1] + br i1 false, label %bb114.i, label %cond_true76.i +} diff --git a/final/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll b/final/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll new file mode 100644 index 00000000000..1ec056bc34e --- /dev/null +++ b/final/test/Analysis/PostDominators/2007-04-17-PostDominanceFrontier.ll @@ -0,0 +1,692 @@ +; RUN: opt < %s -postdomfrontier -disable-output + +define void @SManager() { +entry: + br label %bb.outer + +bb.outer: ; preds = %bb193, %entry + br label %bb.outer156 + +bb.loopexit: ; preds = %bb442 + br label %bb.outer156 + +bb.outer156: ; preds = %bb.loopexit, %bb.outer + br label %bb + +bb: ; preds = %bb.backedge, %bb.outer156 + br i1 false, label %cond_true, label %bb.cond_next_crit_edge + +bb.cond_next_crit_edge: ; preds = %bb + br label %cond_next + +cond_true: ; preds = %bb + br label %cond_next + +cond_next: ; preds = %cond_true, %bb.cond_next_crit_edge + br i1 false, label %cond_next.bb.backedge_crit_edge, label %cond_next107 + +cond_next.bb.backedge_crit_edge: ; preds = %cond_next + br label %bb.backedge + +bb.backedge: ; preds = %cond_true112.bb.backedge_crit_edge, %cond_next.bb.backedge_crit_edge + br label %bb + +cond_next107: ; preds = %cond_next + br i1 false, label %cond_true112, label %cond_next197 + +cond_true112: ; preds = %cond_next107 + br i1 false, label %cond_true118, label %cond_true112.bb.backedge_crit_edge + +cond_true112.bb.backedge_crit_edge: ; preds = %cond_true112 + br label %bb.backedge + +cond_true118: ; preds = %cond_true112 + br i1 false, label %bb123.preheader, label %cond_true118.bb148_crit_edge + +cond_true118.bb148_crit_edge: ; preds = %cond_true118 + br label %bb148 + +bb123.preheader: ; preds = %cond_true118 + br label %bb123 + +bb123: ; preds = %bb142.bb123_crit_edge, %bb123.preheader + br i1 false, label %bb123.bb142_crit_edge, label %cond_next.i57 + +bb123.bb142_crit_edge: ; preds = %bb123 + br label %bb142 + +cond_next.i57: ; preds = %bb123 + br i1 false, label %cond_true135, label %cond_next.i57.bb142_crit_edge + +cond_next.i57.bb142_crit_edge: ; preds = %cond_next.i57 + br label %bb142 + +cond_true135: ; preds = %cond_next.i57 + br label %bb142 + +bb142: ; preds = %cond_true135, %cond_next.i57.bb142_crit_edge, %bb123.bb142_crit_edge + br i1 false, label %bb148.loopexit, label %bb142.bb123_crit_edge + +bb142.bb123_crit_edge: ; preds = %bb142 + br label %bb123 + +bb148.loopexit: ; preds = %bb142 + br label %bb148 + +bb148: ; preds = %bb148.loopexit, %cond_true118.bb148_crit_edge + br i1 false, label %bb151.preheader, label %bb148.bb177_crit_edge + +bb148.bb177_crit_edge: ; preds = %bb148 + br label %bb177 + +bb151.preheader: ; preds = %bb148 + br label %bb151 + +bb151: ; preds = %bb171.bb151_crit_edge, %bb151.preheader + br i1 false, label %bb151.bb171_crit_edge, label %cond_next.i49 + +bb151.bb171_crit_edge: ; preds = %bb151 + br label %bb171 + +cond_next.i49: ; preds = %bb151 + br i1 false, label %cond_true164, label %cond_next.i49.bb171_crit_edge + +cond_next.i49.bb171_crit_edge: ; preds = %cond_next.i49 + br label %bb171 + +cond_true164: ; preds = %cond_next.i49 + br label %bb171 + +bb171: ; preds = %cond_true164, %cond_next.i49.bb171_crit_edge, %bb151.bb171_crit_edge + br i1 false, label %bb177.loopexit, label %bb171.bb151_crit_edge + +bb171.bb151_crit_edge: ; preds = %bb171 + br label %bb151 + +bb177.loopexit: ; preds = %bb171 + br label %bb177 + +bb177: ; preds = %bb177.loopexit, %bb148.bb177_crit_edge + br i1 false, label %bb180.preheader, label %bb177.bb193_crit_edge + +bb177.bb193_crit_edge: ; preds = %bb177 + br label %bb193 + +bb180.preheader: ; preds = %bb177 + br label %bb180 + +bb180: ; preds = %bb180.bb180_crit_edge, %bb180.preheader + br i1 false, label %bb193.loopexit, label %bb180.bb180_crit_edge + +bb180.bb180_crit_edge: ; preds = %bb180 + br label %bb180 + +bb193.loopexit: ; preds = %bb180 + br label %bb193 + +bb193: ; preds = %bb193.loopexit, %bb177.bb193_crit_edge + br label %bb.outer + +cond_next197: ; preds = %cond_next107 + br i1 false, label %cond_next210, label %cond_true205 + +cond_true205: ; preds = %cond_next197 + br i1 false, label %cond_true205.bb213_crit_edge, label %cond_true205.bb299_crit_edge + +cond_true205.bb299_crit_edge: ; preds = %cond_true205 + br label %bb299 + +cond_true205.bb213_crit_edge: ; preds = %cond_true205 + br label %bb213 + +cond_next210: ; preds = %cond_next197 + br label %bb293 + +bb213: ; preds = %bb293.bb213_crit_edge, %cond_true205.bb213_crit_edge + br i1 false, label %bb213.cond_next290_crit_edge, label %cond_true248 + +bb213.cond_next290_crit_edge: ; preds = %bb213 + br label %cond_next290 + +cond_true248: ; preds = %bb213 + br i1 false, label %cond_true248.cond_next290_crit_edge, label %cond_true255 + +cond_true248.cond_next290_crit_edge: ; preds = %cond_true248 + br label %cond_next290 + +cond_true255: ; preds = %cond_true248 + br i1 false, label %cond_true266, label %cond_true255.cond_next271_crit_edge + +cond_true255.cond_next271_crit_edge: ; preds = %cond_true255 + br label %cond_next271 + +cond_true266: ; preds = %cond_true255 + br label %cond_next271 + +cond_next271: ; preds = %cond_true266, %cond_true255.cond_next271_crit_edge + br label %cond_next290 + +cond_next290: ; preds = %cond_next271, %cond_true248.cond_next290_crit_edge, %bb213.cond_next290_crit_edge + br label %bb293 + +bb293: ; preds = %cond_next290, %cond_next210 + br i1 false, label %bb293.bb213_crit_edge, label %bb293.bb299_crit_edge + +bb293.bb299_crit_edge: ; preds = %bb293 + br label %bb299 + +bb293.bb213_crit_edge: ; preds = %bb293 + br label %bb213 + +bb299: ; preds = %bb293.bb299_crit_edge, %cond_true205.bb299_crit_edge + br i1 false, label %bb302.preheader, label %bb299.bb390_crit_edge + +bb299.bb390_crit_edge: ; preds = %bb299 + br label %bb390 + +bb302.preheader: ; preds = %bb299 + br label %bb302 + +bb302: ; preds = %bb384.bb302_crit_edge, %bb302.preheader + br i1 false, label %bb302.bb384_crit_edge, label %cond_true339 + +bb302.bb384_crit_edge: ; preds = %bb302 + br label %bb384 + +cond_true339: ; preds = %bb302 + br i1 false, label %cond_true339.bb384_crit_edge, label %cond_true346 + +cond_true339.bb384_crit_edge: ; preds = %cond_true339 + br label %bb384 + +cond_true346: ; preds = %cond_true339 + br i1 false, label %cond_true357, label %cond_true346.cond_next361_crit_edge + +cond_true346.cond_next361_crit_edge: ; preds = %cond_true346 + br label %cond_next361 + +cond_true357: ; preds = %cond_true346 + br label %cond_next361 + +cond_next361: ; preds = %cond_true357, %cond_true346.cond_next361_crit_edge + br label %bb384 + +bb384: ; preds = %cond_next361, %cond_true339.bb384_crit_edge, %bb302.bb384_crit_edge + br i1 false, label %bb390.loopexit, label %bb384.bb302_crit_edge + +bb384.bb302_crit_edge: ; preds = %bb384 + br label %bb302 + +bb390.loopexit: ; preds = %bb384 + br label %bb390 + +bb390: ; preds = %bb390.loopexit, %bb299.bb390_crit_edge + br i1 false, label %bb391.preheader, label %bb390.bb442.preheader_crit_edge + +bb390.bb442.preheader_crit_edge: ; preds = %bb390 + br label %bb442.preheader + +bb391.preheader: ; preds = %bb390 + br label %bb391 + +bb391: ; preds = %bb413.bb391_crit_edge, %bb391.preheader + br i1 false, label %bb391.bb413_crit_edge, label %cond_next404 + +bb391.bb413_crit_edge: ; preds = %bb391 + br label %bb413 + +cond_next404: ; preds = %bb391 + br i1 false, label %cond_next404.HWrite.exit_crit_edge, label %cond_next.i13 + +cond_next404.HWrite.exit_crit_edge: ; preds = %cond_next404 + br label %HWrite.exit + +cond_next.i13: ; preds = %cond_next404 + br i1 false, label %cond_next.i13.cond_next13.i_crit_edge, label %cond_true12.i + +cond_next.i13.cond_next13.i_crit_edge: ; preds = %cond_next.i13 + br label %cond_next13.i + +cond_true12.i: ; preds = %cond_next.i13 + br label %cond_next13.i + +cond_next13.i: ; preds = %cond_true12.i, %cond_next.i13.cond_next13.i_crit_edge + br i1 false, label %cond_next13.i.bb.i22_crit_edge, label %cond_next43.i + +cond_next13.i.bb.i22_crit_edge: ; preds = %cond_next13.i + br label %bb.i22 + +cond_next43.i: ; preds = %cond_next13.i + br i1 false, label %cond_next43.i.bb.i22_crit_edge, label %bb60.i + +cond_next43.i.bb.i22_crit_edge: ; preds = %cond_next43.i + br label %bb.i22 + +bb.i22: ; preds = %cond_next43.i.bb.i22_crit_edge, %cond_next13.i.bb.i22_crit_edge + br label %bb413 + +bb60.i: ; preds = %cond_next43.i + br i1 false, label %bb60.i.HWrite.exit_crit_edge, label %cond_true81.i + +bb60.i.HWrite.exit_crit_edge: ; preds = %bb60.i + br label %HWrite.exit + +cond_true81.i: ; preds = %bb60.i + br label %bb413 + +HWrite.exit: ; preds = %bb60.i.HWrite.exit_crit_edge, %cond_next404.HWrite.exit_crit_edge + br label %bb413 + +bb413: ; preds = %HWrite.exit, %cond_true81.i, %bb.i22, %bb391.bb413_crit_edge + br i1 false, label %bb442.preheader.loopexit, label %bb413.bb391_crit_edge + +bb413.bb391_crit_edge: ; preds = %bb413 + br label %bb391 + +bb442.preheader.loopexit: ; preds = %bb413 + br label %bb442.preheader + +bb442.preheader: ; preds = %bb442.preheader.loopexit, %bb390.bb442.preheader_crit_edge + br label %bb442.outer + +bb420: ; preds = %bb442 + br i1 false, label %bb439.loopexit, label %cond_next433 + +cond_next433: ; preds = %bb420 + br i1 false, label %cond_next433.HRead.exit.loopexit_crit_edge, label %cond_next.i + +cond_next433.HRead.exit.loopexit_crit_edge: ; preds = %cond_next433 + br label %HRead.exit.loopexit + +cond_next.i: ; preds = %cond_next433 + br i1 false, label %cond_true9.i, label %cond_false223.i + +cond_true9.i: ; preds = %cond_next.i + switch i32 0, label %cond_false.i [ + i32 1, label %cond_true9.i.cond_true15.i_crit_edge + i32 5, label %cond_true9.i.cond_true15.i_crit_edge9 + ] + +cond_true9.i.cond_true15.i_crit_edge9: ; preds = %cond_true9.i + br label %cond_true15.i + +cond_true9.i.cond_true15.i_crit_edge: ; preds = %cond_true9.i + br label %cond_true15.i + +cond_true15.i: ; preds = %cond_true9.i.cond_true15.i_crit_edge, %cond_true9.i.cond_true15.i_crit_edge9 + br i1 false, label %cond_true15.i.cond_true44.i_crit_edge, label %cond_true15.i.cond_false49.i_crit_edge + +cond_true15.i.cond_false49.i_crit_edge: ; preds = %cond_true15.i + br label %cond_false49.i + +cond_true15.i.cond_true44.i_crit_edge: ; preds = %cond_true15.i + br label %cond_true44.i + +cond_false.i: ; preds = %cond_true9.i + br i1 false, label %cond_false.i.cond_next39.i_crit_edge, label %cond_true30.i + +cond_false.i.cond_next39.i_crit_edge: ; preds = %cond_false.i + br label %cond_next39.i + +cond_true30.i: ; preds = %cond_false.i + br label %cond_next39.i + +cond_next39.i: ; preds = %cond_true30.i, %cond_false.i.cond_next39.i_crit_edge + br i1 false, label %cond_next39.i.cond_true44.i_crit_edge, label %cond_next39.i.cond_false49.i_crit_edge + +cond_next39.i.cond_false49.i_crit_edge: ; preds = %cond_next39.i + br label %cond_false49.i + +cond_next39.i.cond_true44.i_crit_edge: ; preds = %cond_next39.i + br label %cond_true44.i + +cond_true44.i: ; preds = %cond_next39.i.cond_true44.i_crit_edge, %cond_true15.i.cond_true44.i_crit_edge + br i1 false, label %cond_true44.i.cond_next70.i_crit_edge, label %cond_true44.i.cond_true61.i_crit_edge + +cond_true44.i.cond_true61.i_crit_edge: ; preds = %cond_true44.i + br label %cond_true61.i + +cond_true44.i.cond_next70.i_crit_edge: ; preds = %cond_true44.i + br label %cond_next70.i + +cond_false49.i: ; preds = %cond_next39.i.cond_false49.i_crit_edge, %cond_true15.i.cond_false49.i_crit_edge + br i1 false, label %cond_false49.i.cond_next70.i_crit_edge, label %cond_false49.i.cond_true61.i_crit_edge + +cond_false49.i.cond_true61.i_crit_edge: ; preds = %cond_false49.i + br label %cond_true61.i + +cond_false49.i.cond_next70.i_crit_edge: ; preds = %cond_false49.i + br label %cond_next70.i + +cond_true61.i: ; preds = %cond_false49.i.cond_true61.i_crit_edge, %cond_true44.i.cond_true61.i_crit_edge + br i1 false, label %cond_true61.i.cond_next70.i_crit_edge, label %cond_true67.i + +cond_true61.i.cond_next70.i_crit_edge: ; preds = %cond_true61.i + br label %cond_next70.i + +cond_true67.i: ; preds = %cond_true61.i + br label %cond_next70.i + +cond_next70.i: ; preds = %cond_true67.i, %cond_true61.i.cond_next70.i_crit_edge, %cond_false49.i.cond_next70.i_crit_edge, %cond_true44.i.cond_next70.i_crit_edge + br i1 false, label %cond_true77.i, label %cond_next81.i + +cond_true77.i: ; preds = %cond_next70.i + br label %bb442.outer.backedge + +cond_next81.i: ; preds = %cond_next70.i + br i1 false, label %cond_true87.i, label %cond_false94.i + +cond_true87.i: ; preds = %cond_next81.i + br i1 false, label %cond_true87.i.cond_true130.i_crit_edge, label %cond_true87.i.cond_next135.i_crit_edge + +cond_true87.i.cond_next135.i_crit_edge: ; preds = %cond_true87.i + br label %cond_next135.i + +cond_true87.i.cond_true130.i_crit_edge: ; preds = %cond_true87.i + br label %cond_true130.i + +cond_false94.i: ; preds = %cond_next81.i + switch i32 0, label %cond_false94.i.cond_next125.i_crit_edge [ + i32 1, label %cond_false94.i.cond_true100.i_crit_edge + i32 5, label %cond_false94.i.cond_true100.i_crit_edge10 + ] + +cond_false94.i.cond_true100.i_crit_edge10: ; preds = %cond_false94.i + br label %cond_true100.i + +cond_false94.i.cond_true100.i_crit_edge: ; preds = %cond_false94.i + br label %cond_true100.i + +cond_false94.i.cond_next125.i_crit_edge: ; preds = %cond_false94.i + br label %cond_next125.i + +cond_true100.i: ; preds = %cond_false94.i.cond_true100.i_crit_edge, %cond_false94.i.cond_true100.i_crit_edge10 + br i1 false, label %cond_true107.i, label %cond_true100.i.cond_next109.i_crit_edge + +cond_true100.i.cond_next109.i_crit_edge: ; preds = %cond_true100.i + br label %cond_next109.i + +cond_true107.i: ; preds = %cond_true100.i + br label %cond_next109.i + +cond_next109.i: ; preds = %cond_true107.i, %cond_true100.i.cond_next109.i_crit_edge + br i1 false, label %cond_next109.i.cond_next125.i_crit_edge, label %cond_true116.i + +cond_next109.i.cond_next125.i_crit_edge: ; preds = %cond_next109.i + br label %cond_next125.i + +cond_true116.i: ; preds = %cond_next109.i + br label %cond_next125.i + +cond_next125.i: ; preds = %cond_true116.i, %cond_next109.i.cond_next125.i_crit_edge, %cond_false94.i.cond_next125.i_crit_edge + br i1 false, label %cond_next125.i.cond_true130.i_crit_edge, label %cond_next125.i.cond_next135.i_crit_edge + +cond_next125.i.cond_next135.i_crit_edge: ; preds = %cond_next125.i + br label %cond_next135.i + +cond_next125.i.cond_true130.i_crit_edge: ; preds = %cond_next125.i + br label %cond_true130.i + +cond_true130.i: ; preds = %cond_next125.i.cond_true130.i_crit_edge, %cond_true87.i.cond_true130.i_crit_edge + br label %cond_next135.i + +cond_next135.i: ; preds = %cond_true130.i, %cond_next125.i.cond_next135.i_crit_edge, %cond_true87.i.cond_next135.i_crit_edge + br i1 false, label %cond_true142.i, label %cond_next135.i.cond_next149.i_crit_edge + +cond_next135.i.cond_next149.i_crit_edge: ; preds = %cond_next135.i + br label %cond_next149.i + +cond_true142.i: ; preds = %cond_next135.i + br label %cond_next149.i + +cond_next149.i: ; preds = %cond_true142.i, %cond_next135.i.cond_next149.i_crit_edge + br i1 false, label %cond_true156.i, label %cond_next149.i.cond_next163.i_crit_edge + +cond_next149.i.cond_next163.i_crit_edge: ; preds = %cond_next149.i + br label %cond_next163.i + +cond_true156.i: ; preds = %cond_next149.i + br label %cond_next163.i + +cond_next163.i: ; preds = %cond_true156.i, %cond_next149.i.cond_next163.i_crit_edge + br i1 false, label %cond_true182.i, label %cond_next163.i.cond_next380.i_crit_edge + +cond_next163.i.cond_next380.i_crit_edge: ; preds = %cond_next163.i + br label %cond_next380.i + +cond_true182.i: ; preds = %cond_next163.i + br i1 false, label %cond_true182.i.cond_next380.i_crit_edge, label %cond_true196.i + +cond_true182.i.cond_next380.i_crit_edge: ; preds = %cond_true182.i + br label %cond_next380.i + +cond_true196.i: ; preds = %cond_true182.i + br i1 false, label %cond_true210.i, label %cond_true196.i.cond_next380.i_crit_edge + +cond_true196.i.cond_next380.i_crit_edge: ; preds = %cond_true196.i + br label %cond_next380.i + +cond_true210.i: ; preds = %cond_true196.i + br i1 false, label %cond_true216.i, label %cond_true210.i.cond_next380.i_crit_edge + +cond_true210.i.cond_next380.i_crit_edge: ; preds = %cond_true210.i + br label %cond_next380.i + +cond_true216.i: ; preds = %cond_true210.i + br label %cond_next380.i + +cond_false223.i: ; preds = %cond_next.i + br i1 false, label %cond_true229.i, label %cond_false355.i + +cond_true229.i: ; preds = %cond_false223.i + br i1 false, label %cond_true229.i.HRead.exit.loopexit_crit_edge, label %cond_next243.i + +cond_true229.i.HRead.exit.loopexit_crit_edge: ; preds = %cond_true229.i + br label %HRead.exit.loopexit + +cond_next243.i: ; preds = %cond_true229.i + br i1 false, label %cond_true248.i, label %cond_false255.i + +cond_true248.i: ; preds = %cond_next243.i + br label %cond_next260.i + +cond_false255.i: ; preds = %cond_next243.i + br label %cond_next260.i + +cond_next260.i: ; preds = %cond_false255.i, %cond_true248.i + br i1 false, label %cond_true267.i, label %cond_next273.i + +cond_true267.i: ; preds = %cond_next260.i + br label %bb442.backedge + +bb442.backedge: ; preds = %bb.i, %cond_true267.i + br label %bb442 + +cond_next273.i: ; preds = %cond_next260.i + br i1 false, label %cond_true281.i, label %cond_next273.i.cond_next288.i_crit_edge + +cond_next273.i.cond_next288.i_crit_edge: ; preds = %cond_next273.i + br label %cond_next288.i + +cond_true281.i: ; preds = %cond_next273.i + br label %cond_next288.i + +cond_next288.i: ; preds = %cond_true281.i, %cond_next273.i.cond_next288.i_crit_edge + br i1 false, label %cond_true295.i, label %cond_next288.i.cond_next302.i_crit_edge + +cond_next288.i.cond_next302.i_crit_edge: ; preds = %cond_next288.i + br label %cond_next302.i + +cond_true295.i: ; preds = %cond_next288.i + br label %cond_next302.i + +cond_next302.i: ; preds = %cond_true295.i, %cond_next288.i.cond_next302.i_crit_edge + br i1 false, label %cond_next302.i.cond_next380.i_crit_edge, label %cond_true328.i + +cond_next302.i.cond_next380.i_crit_edge: ; preds = %cond_next302.i + br label %cond_next380.i + +cond_true328.i: ; preds = %cond_next302.i + br i1 false, label %cond_true343.i, label %cond_true328.i.cond_next380.i_crit_edge + +cond_true328.i.cond_next380.i_crit_edge: ; preds = %cond_true328.i + br label %cond_next380.i + +cond_true343.i: ; preds = %cond_true328.i + br i1 false, label %cond_true349.i, label %cond_true343.i.cond_next380.i_crit_edge + +cond_true343.i.cond_next380.i_crit_edge: ; preds = %cond_true343.i + br label %cond_next380.i + +cond_true349.i: ; preds = %cond_true343.i + br label %cond_next380.i + +cond_false355.i: ; preds = %cond_false223.i + br i1 false, label %cond_false355.i.bb.i_crit_edge, label %cond_next363.i + +cond_false355.i.bb.i_crit_edge: ; preds = %cond_false355.i + br label %bb.i + +cond_next363.i: ; preds = %cond_false355.i + br i1 false, label %bb377.i, label %cond_next363.i.bb.i_crit_edge + +cond_next363.i.bb.i_crit_edge: ; preds = %cond_next363.i + br label %bb.i + +bb.i: ; preds = %cond_next363.i.bb.i_crit_edge, %cond_false355.i.bb.i_crit_edge + br label %bb442.backedge + +bb377.i: ; preds = %cond_next363.i + br label %cond_next380.i + +cond_next380.i: ; preds = %bb377.i, %cond_true349.i, %cond_true343.i.cond_next380.i_crit_edge, %cond_true328.i.cond_next380.i_crit_edge, %cond_next302.i.cond_next380.i_crit_edge, %cond_true216.i, %cond_true210.i.cond_next380.i_crit_edge, %cond_true196.i.cond_next380.i_crit_edge, %cond_true182.i.cond_next380.i_crit_edge, %cond_next163.i.cond_next380.i_crit_edge + br i1 false, label %cond_next380.i.HRead.exit_crit_edge, label %cond_true391.i + +cond_next380.i.HRead.exit_crit_edge: ; preds = %cond_next380.i + br label %HRead.exit + +cond_true391.i: ; preds = %cond_next380.i + br label %bb442.outer.backedge + +bb442.outer.backedge: ; preds = %bb439, %cond_true391.i, %cond_true77.i + br label %bb442.outer + +HRead.exit.loopexit: ; preds = %cond_true229.i.HRead.exit.loopexit_crit_edge, %cond_next433.HRead.exit.loopexit_crit_edge + br label %HRead.exit + +HRead.exit: ; preds = %HRead.exit.loopexit, %cond_next380.i.HRead.exit_crit_edge + br label %bb439 + +bb439.loopexit: ; preds = %bb420 + br label %bb439 + +bb439: ; preds = %bb439.loopexit, %HRead.exit + br label %bb442.outer.backedge + +bb442.outer: ; preds = %bb442.outer.backedge, %bb442.preheader + br label %bb442 + +bb442: ; preds = %bb442.outer, %bb442.backedge + br i1 false, label %bb420, label %bb.loopexit +} + +define void @Invalidate() { +entry: + br i1 false, label %cond_false, label %cond_true + +cond_true: ; preds = %entry + br i1 false, label %cond_true40, label %cond_true.cond_next_crit_edge + +cond_true.cond_next_crit_edge: ; preds = %cond_true + br label %cond_next + +cond_true40: ; preds = %cond_true + br label %cond_next + +cond_next: ; preds = %cond_true40, %cond_true.cond_next_crit_edge + br i1 false, label %cond_true68, label %cond_next.cond_next73_crit_edge + +cond_next.cond_next73_crit_edge: ; preds = %cond_next + br label %cond_next73 + +cond_true68: ; preds = %cond_next + br label %cond_next73 + +cond_next73: ; preds = %cond_true68, %cond_next.cond_next73_crit_edge + br i1 false, label %cond_true91, label %cond_next73.cond_next96_crit_edge + +cond_next73.cond_next96_crit_edge: ; preds = %cond_next73 + br label %cond_next96 + +cond_true91: ; preds = %cond_next73 + br label %cond_next96 + +cond_next96: ; preds = %cond_true91, %cond_next73.cond_next96_crit_edge + br i1 false, label %cond_next96.cond_next112_crit_edge, label %cond_true105 + +cond_next96.cond_next112_crit_edge: ; preds = %cond_next96 + br label %cond_next112 + +cond_true105: ; preds = %cond_next96 + br label %cond_next112 + +cond_next112: ; preds = %cond_true105, %cond_next96.cond_next112_crit_edge + br i1 false, label %cond_next112.cond_next127_crit_edge, label %cond_true119 + +cond_next112.cond_next127_crit_edge: ; preds = %cond_next112 + br label %cond_next127 + +cond_true119: ; preds = %cond_next112 + br label %cond_next127 + +cond_next127: ; preds = %cond_true119, %cond_next112.cond_next127_crit_edge + br i1 false, label %cond_next141, label %cond_true134 + +cond_true134: ; preds = %cond_next127 + br i1 false, label %cond_true134.bb161_crit_edge, label %cond_true134.bb_crit_edge + +cond_true134.bb_crit_edge: ; preds = %cond_true134 + br label %bb + +cond_true134.bb161_crit_edge: ; preds = %cond_true134 + br label %bb161 + +cond_next141: ; preds = %cond_next127 + br label %bb154 + +bb: ; preds = %bb154.bb_crit_edge, %cond_true134.bb_crit_edge + br label %bb154 + +bb154: ; preds = %bb, %cond_next141 + br i1 false, label %bb154.bb161_crit_edge, label %bb154.bb_crit_edge + +bb154.bb_crit_edge: ; preds = %bb154 + br label %bb + +bb154.bb161_crit_edge: ; preds = %bb154 + br label %bb161 + +bb161: ; preds = %bb154.bb161_crit_edge, %cond_true134.bb161_crit_edge + br i1 false, label %bb161.cond_next201_crit_edge, label %cond_true198 + +bb161.cond_next201_crit_edge: ; preds = %bb161 + br label %cond_next201 + +cond_true198: ; preds = %bb161 + br label %cond_next201 + +cond_next201: ; preds = %cond_true198, %bb161.cond_next201_crit_edge + br i1 false, label %cond_next212, label %cond_true206 + +cond_true206: ; preds = %cond_next201 + br label %UnifiedReturnBlock + +cond_false: ; preds = %entry + br label %UnifiedReturnBlock + +cond_next212: ; preds = %cond_next201 + br label %UnifiedReturnBlock + +UnifiedReturnBlock: ; preds = %cond_next212, %cond_false, %cond_true206 + ret void +} diff --git a/final/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll b/final/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll new file mode 100644 index 00000000000..767e5db94ce --- /dev/null +++ b/final/test/Analysis/PostDominators/2007-04-20-PostDom-Reset.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -postdomfrontier -disable-output + +define void @args_out_of_range() { +entry: + br label %bb + +bb: ; preds = %bb, %entry + br label %bb +} + +define void @args_out_of_range_3() { +entry: + br label %bb + +bb: ; preds = %bb, %entry + br label %bb +} + +define void @Feq() { +entry: + br i1 false, label %cond_true, label %cond_next + +cond_true: ; preds = %entry + unreachable + +cond_next: ; preds = %entry + unreachable +} diff --git a/final/test/Analysis/PostDominators/dg.exp b/final/test/Analysis/PostDominators/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Analysis/PostDominators/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Analysis/PostDominators/pr1098.ll b/final/test/Analysis/PostDominators/pr1098.ll new file mode 100644 index 00000000000..afb47769ee4 --- /dev/null +++ b/final/test/Analysis/PostDominators/pr1098.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -postdomtree -analyze | grep entry +; PR932 + +define void @foo(i1 %x) { +entry: + br i1 %x, label %bb1, label %bb0 +bb0: ; preds = %entry, bb0 + br label %bb0 +bb1: ; preds = %entry + br label %bb2 +bb2: ; preds = %bb1 + ret void +} + diff --git a/final/test/Analysis/PostDominators/pr6047_a.ll b/final/test/Analysis/PostDominators/pr6047_a.ll new file mode 100644 index 00000000000..ec1455b46fe --- /dev/null +++ b/final/test/Analysis/PostDominators/pr6047_a.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [3] %entry diff --git a/final/test/Analysis/PostDominators/pr6047_b.ll b/final/test/Analysis/PostDominators/pr6047_b.ll new file mode 100644 index 00000000000..7bd2c86b737 --- /dev/null +++ b/final/test/Analysis/PostDominators/pr6047_b.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %a, label %bb3.i + +a: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [4] %entry diff --git a/final/test/Analysis/PostDominators/pr6047_c.ll b/final/test/Analysis/PostDominators/pr6047_c.ll new file mode 100644 index 00000000000..08c9551f156 --- /dev/null +++ b/final/test/Analysis/PostDominators/pr6047_c.ll @@ -0,0 +1,147 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb: + br label %bb35 + +bb.i: + br label %bb35 + +_float32_unpack.exit: + br label %bb35 + +bb.i5: + br label %bb35 + +_float32_unpack.exit8: + br label %bb35 + +bb32.preheader: + br label %bb35 + +bb3: + br label %bb35 + +bb3.split.us: + br label %bb35 + +bb.i4.us: + br label %bb35 + +bb7.i.us: + br label %bb35 + +bb.i4.us.backedge: + br label %bb35 + +bb1.i.us: + br label %bb35 + +bb6.i.us: + br label %bb35 + +bb4.i.us: + br label %bb35 + +bb8.i.us: + br label %bb35 + +bb3.i.loopexit.us: + br label %bb35 + +bb.nph21: + br label %bb35 + +bb4: + br label %bb35 + +bb5: + br label %bb35 + +bb14.preheader: + br label %bb35 + +bb.nph18: + br label %bb35 + +bb8.us.preheader: + br label %bb35 + +bb8.preheader: + br label %bb35 + +bb8.us: + br label %bb35 + +bb8: + br label %bb35 + +bb15.loopexit: + br label %bb35 + +bb15.loopexit2: + br label %bb35 + +bb15: + br label %bb35 + +bb16: + br label %bb35 + +bb17.loopexit.split: + br label %bb35 + +bb.nph14: + br label %bb35 + +bb19: + br label %bb35 + +bb20: + br label %bb35 + +bb29.preheader: + br label %bb35 + +bb.nph: + br label %bb35 + +bb23.us.preheader: + br label %bb35 + +bb23.preheader: + br label %bb35 + +bb23.us: + br label %bb35 + +bb23: + br label %bb35 + +bb30.loopexit: + br label %bb35 + +bb30.loopexit1: + br label %bb35 + +bb30: + br label %bb35 + +bb31: + br label %bb35 + +bb35.loopexit: + br label %bb35 + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [3] %entry diff --git a/final/test/Analysis/PostDominators/pr6047_d.ll b/final/test/Analysis/PostDominators/pr6047_d.ll new file mode 100644 index 00000000000..4cfa88029ae --- /dev/null +++ b/final/test/Analysis/PostDominators/pr6047_d.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -postdomtree -analyze | FileCheck %s +define internal void @f() { +entry: + br i1 1, label %a, label %b + +a: +br label %c + +b: +br label %c + +c: + br i1 undef, label %bb35, label %bb3.i + +bb3.i: + br label %bb3.i + +bb35.loopexit3: + br label %bb35 + +bb35: + ret void +} +; CHECK: [4] %entry diff --git a/final/test/Analysis/Profiling/dg.exp b/final/test/Analysis/Profiling/dg.exp new file mode 100644 index 00000000000..1eb4755c410 --- /dev/null +++ b/final/test/Analysis/Profiling/dg.exp @@ -0,0 +1,4 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] + diff --git a/final/test/Analysis/Profiling/edge-profiling.ll b/final/test/Analysis/Profiling/edge-profiling.ll new file mode 100644 index 00000000000..cbaf47617fb --- /dev/null +++ b/final/test/Analysis/Profiling/edge-profiling.ll @@ -0,0 +1,139 @@ +; Test the edge profiling instrumentation. +; RUN: opt < %s -insert-edge-profiling -S | FileCheck %s + +; ModuleID = '' + +@.str = private constant [12 x i8] c"hello world\00", align 1 ; <[12 x i8]*> [#uses=1] +@.str1 = private constant [6 x i8] c"franz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str2 = private constant [9 x i8] c"argc > 2\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str3 = private constant [9 x i8] c"argc = 1\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str4 = private constant [6 x i8] c"fritz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str5 = private constant [10 x i8] c"argc <= 1\00", align 1 ; <[10 x i8]*> [#uses=1] +; CHECK:@EdgeProfCounters +; CHECK:[19 x i32] +; CHECK:zeroinitializer + +define void @oneblock() nounwind { +entry: +; CHECK:entry: +; CHECK:%OldFuncCounter +; CHECK:load +; CHECK:getelementptr +; CHECK:@EdgeProfCounters +; CHECK:i32 0 +; CHECK:i32 0 +; CHECK:%NewFuncCounter +; CHECK:add +; CHECK:%OldFuncCounter +; CHECK:store +; CHECK:%NewFuncCounter +; CHECK:getelementptr +; CHECK:@EdgeProfCounters + %0 = call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.str, i64 0, i64 0)) nounwind ; [#uses=0] + ret void +} + +declare i32 @puts(i8*) + +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: +; CHECK:entry: + %argc_addr = alloca i32 ; [#uses=4] + %argv_addr = alloca i8** ; [#uses=1] + %retval = alloca i32 ; [#uses=2] + %j = alloca i32 ; [#uses=4] + %i = alloca i32 ; [#uses=4] + %0 = alloca i32 ; [#uses=2] +; CHECK:call +; CHECK:@llvm_start_edge_profiling +; CHECK:@EdgeProfCounters + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + store i32 0, i32* %i, align 4 + br label %bb10 + +bb: ; preds = %bb10 +; CHECK:bb: + %1 = load i32* %argc_addr, align 4 ; [#uses=1] + %2 = icmp sgt i32 %1, 1 ; [#uses=1] + br i1 %2, label %bb1, label %bb8 + +bb1: ; preds = %bb +; CHECK:bb1: + store i32 0, i32* %j, align 4 + br label %bb6 + +bb2: ; preds = %bb6 +; CHECK:bb2: + %3 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str1, i64 0, i64 0)) nounwind ; [#uses=0] + %4 = load i32* %argc_addr, align 4 ; [#uses=1] + %5 = icmp sgt i32 %4, 2 ; [#uses=1] + br i1 %5, label %bb3, label %bb4 + +bb3: ; preds = %bb2 +; CHECK:bb3: + %6 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str2, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb5 + +bb4: ; preds = %bb2 +; CHECK:bb4: + %7 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str3, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb11 + +bb5: ; preds = %bb3 +; CHECK:bb5: + %8 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str4, i64 0, i64 0)) nounwind ; [#uses=0] + %9 = load i32* %j, align 4 ; [#uses=1] + %10 = add nsw i32 %9, 1 ; [#uses=1] + store i32 %10, i32* %j, align 4 + br label %bb6 + +bb6: ; preds = %bb5, %bb1 +; CHECK:bb6: + %11 = load i32* %j, align 4 ; [#uses=1] + %12 = load i32* %argc_addr, align 4 ; [#uses=1] + %13 = icmp slt i32 %11, %12 ; [#uses=1] + br i1 %13, label %bb2, label %bb7 + +bb7: ; preds = %bb6 +; CHECK:bb7: + br label %bb9 + +bb8: ; preds = %bb +; CHECK:bb8: + %14 = call i32 @puts(i8* getelementptr inbounds ([10 x i8]* @.str5, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb9 + +bb9: ; preds = %bb8, %bb7 +; CHECK:bb9: + %15 = load i32* %i, align 4 ; [#uses=1] + %16 = add nsw i32 %15, 1 ; [#uses=1] + store i32 %16, i32* %i, align 4 + br label %bb10 + +bb10: ; preds = %bb9, %entry +; CHECK:bb10: + %17 = load i32* %i, align 4 ; [#uses=1] + %18 = icmp ne i32 %17, 3 ; [#uses=1] + br i1 %18, label %bb, label %bb11 +; CHECK:br +; CHECK:label %bb10.bb11_crit_edge + +; CHECK:bb10.bb11_crit_edge: +; CHECK:br +; CHECK:label %bb11 + +bb11: ; preds = %bb10, %bb4 +; CHECK:bb11: + call void @oneblock() nounwind + store i32 0, i32* %0, align 4 + %19 = load i32* %0, align 4 ; [#uses=1] + store i32 %19, i32* %retval, align 4 + br label %return + +return: ; preds = %bb11 +; CHECK:return: + %retval12 = load i32* %retval ; [#uses=1] + ret i32 %retval12 +} diff --git a/final/test/Analysis/Profiling/profiling-tool-chain.ll b/final/test/Analysis/Profiling/profiling-tool-chain.ll new file mode 100644 index 00000000000..9135a85dc3a --- /dev/null +++ b/final/test/Analysis/Profiling/profiling-tool-chain.ll @@ -0,0 +1,212 @@ +; RUN: llvm-as %s -o %t1 + +; FIXME: The RUX parts of the test are disabled for now, they aren't working on +; llvm-gcc-x86_64-darwin10-selfhost. + +; Test the edge optimal profiling instrumentation. +; RUN: opt %t1 -insert-optimal-edge-profiling -o %t2 +; RUX: llvm-dis < %t2 | FileCheck --check-prefix=INST %s + +; Test the creation, reading and displaying of profile +; RUX: rm -f llvmprof.out +; RUX: lli -load %llvmshlibdir/profile_rt%shlibext %t2 +; RUX: lli -load %llvmshlibdir/profile_rt%shlibext %t2 1 2 +; RUX: llvm-prof -print-all-code %t1 | FileCheck --check-prefix=PROF %s + +; Test the loaded profile also with verifier. +; RUX opt %t1 -profile-loader -profile-verifier -o %t3 + +; Test profile estimator. +; RUN: opt %t1 -profile-estimator -profile-verifier -o %t3 + +; PROF: 1. 2/4 oneblock +; PROF: 2. 2/4 main +; PROF: 1. 15.7895% 12/76 main() - bb6 +; PROF: 2. 11.8421% 9/76 main() - bb2 +; PROF: 3. 11.8421% 9/76 main() - bb3 +; PROF: 4. 11.8421% 9/76 main() - bb5 +; PROF: 5. 10.5263% 8/76 main() - bb10 +; PROF: 6. 7.89474% 6/76 main() - bb +; PROF: 7. 7.89474% 6/76 main() - bb9 +; PROF: 8. 3.94737% 3/76 main() - bb1 +; PROF: 9. 3.94737% 3/76 main() - bb7 +; PROF: 10. 3.94737% 3/76 main() - bb8 +; PROF: 11. 2.63158% 2/76 oneblock() - entry +; PROF: 12. 2.63158% 2/76 main() - entry +; PROF: 13. 2.63158% 2/76 main() - bb11 +; PROF: 14. 2.63158% 2/76 main() - return + +; ModuleID = '' + +@.str = private constant [12 x i8] c"hello world\00", align 1 ; <[12 x i8]*> [#uses=1] +@.str1 = private constant [6 x i8] c"franz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str2 = private constant [9 x i8] c"argc > 2\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str3 = private constant [9 x i8] c"argc = 1\00", align 1 ; <[9 x i8]*> [#uses=1] +@.str4 = private constant [6 x i8] c"fritz\00", align 1 ; <[6 x i8]*> [#uses=1] +@.str5 = private constant [10 x i8] c"argc <= 1\00", align 1 ; <[10 x i8]*> [#uses=1] +; INST:@OptEdgeProfCounters +; INST:[21 x i32] +; INST:[i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1, +; INST:i32 0, +; INST:i32 -1, +; INST:i32 -1] + +; PROF:;;; %oneblock called 2 times. +; PROF:;;; +define void @oneblock() nounwind { +entry: +; PROF:entry: +; PROF: ;;; Basic block executed 2 times. + %0 = call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @.str, i64 0, i64 0)) nounwind ; [#uses=0] + ret void +} + +declare i32 @puts(i8*) + +; PROF:;;; %main called 2 times. +; PROF:;;; +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: +; PROF:entry: +; PROF: ;;; Basic block executed 2 times. + %argc_addr = alloca i32 ; [#uses=4] + %argv_addr = alloca i8** ; [#uses=1] + %retval = alloca i32 ; [#uses=2] + %j = alloca i32 ; [#uses=4] + %i = alloca i32 ; [#uses=4] + %0 = alloca i32 ; [#uses=2] +; INST:call +; INST:@llvm_start_opt_edge_profiling +; INST:@OptEdgeProfCounters + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %argc, i32* %argc_addr + store i8** %argv, i8*** %argv_addr + store i32 0, i32* %i, align 4 + br label %bb10 +; PROF: ;;; Out-edge counts: [2.000000e+00 -> bb10] + +bb: ; preds = %bb10 +; PROF:bb: +; PROF: ;;; Basic block executed 6 times. + %1 = load i32* %argc_addr, align 4 ; [#uses=1] + %2 = icmp sgt i32 %1, 1 ; [#uses=1] + br i1 %2, label %bb1, label %bb8 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb1] [3.000000e+00 -> bb8] + +bb1: ; preds = %bb +; PROF:bb1: +; PROF: ;;; Basic block executed 3 times. + store i32 0, i32* %j, align 4 + br label %bb6 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb6] + +bb2: ; preds = %bb6 +; PROF:bb2: +; PROF: ;;; Basic block executed 9 times. + %3 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str1, i64 0, i64 0)) nounwind ; [#uses=0] + %4 = load i32* %argc_addr, align 4 ; [#uses=1] + %5 = icmp sgt i32 %4, 2 ; [#uses=1] + br i1 %5, label %bb3, label %bb4 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb3] + +bb3: ; preds = %bb2 +; PROF:bb3: +; PROF: ;;; Basic block executed 9 times. + %6 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str2, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb5 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb5] + +bb4: ; preds = %bb2 +; PROF:bb4: +; PROF: ;;; Never executed! + %7 = call i32 @puts(i8* getelementptr inbounds ([9 x i8]* @.str3, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb11 + +bb5: ; preds = %bb3 +; PROF:bb5: +; PROF: ;;; Basic block executed 9 times. + %8 = call i32 @puts(i8* getelementptr inbounds ([6 x i8]* @.str4, i64 0, i64 0)) nounwind ; [#uses=0] + %9 = load i32* %j, align 4 ; [#uses=1] + %10 = add nsw i32 %9, 1 ; [#uses=1] + store i32 %10, i32* %j, align 4 + br label %bb6 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb6] + +bb6: ; preds = %bb5, %bb1 +; PROF:bb6: +; PROF: ;;; Basic block executed 12 times. + %11 = load i32* %j, align 4 ; [#uses=1] + %12 = load i32* %argc_addr, align 4 ; [#uses=1] + %13 = icmp slt i32 %11, %12 ; [#uses=1] + br i1 %13, label %bb2, label %bb7 +; PROF: ;;; Out-edge counts: [9.000000e+00 -> bb2] [3.000000e+00 -> bb7] + +bb7: ; preds = %bb6 +; PROF:bb7: +; PROF: ;;; Basic block executed 3 times. + br label %bb9 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb9] + +bb8: ; preds = %bb +; PROF:bb8: +; PROF: ;;; Basic block executed 3 times. + %14 = call i32 @puts(i8* getelementptr inbounds ([10 x i8]* @.str5, i64 0, i64 0)) nounwind ; [#uses=0] + br label %bb9 +; PROF: ;;; Out-edge counts: [3.000000e+00 -> bb9] + +bb9: ; preds = %bb8, %bb7 +; PROF:bb9: +; PROF: ;;; Basic block executed 6 times. + %15 = load i32* %i, align 4 ; [#uses=1] + %16 = add nsw i32 %15, 1 ; [#uses=1] + store i32 %16, i32* %i, align 4 + br label %bb10 +; PROF: ;;; Out-edge counts: [6.000000e+00 -> bb10] + +bb10: ; preds = %bb9, %entry +; PROF:bb10: +; PROF: ;;; Basic block executed 8 times. + %17 = load i32* %i, align 4 ; [#uses=1] + %18 = icmp ne i32 %17, 3 ; [#uses=1] + br i1 %18, label %bb, label %bb11 +; INST:br +; INST:label %bb10.bb11_crit_edge +; PROF: ;;; Out-edge counts: [6.000000e+00 -> bb] [2.000000e+00 -> bb11] + +; INST:bb10.bb11_crit_edge: +; INST:br +; INST:label %bb11 + +bb11: ; preds = %bb10, %bb4 +; PROF:bb11: +; PROF: ;;; Basic block executed 2 times. + call void @oneblock() nounwind + store i32 0, i32* %0, align 4 + %19 = load i32* %0, align 4 ; [#uses=1] + store i32 %19, i32* %retval, align 4 + br label %return +; PROF: ;;; Out-edge counts: [2.000000e+00 -> return] + +return: ; preds = %bb11 +; PROF:return: +; PROF: ;;; Basic block executed 2 times. + %retval12 = load i32* %retval ; [#uses=1] + ret i32 %retval12 +} diff --git a/final/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll b/final/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll new file mode 100644 index 00000000000..218b4375f70 --- /dev/null +++ b/final/test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll @@ -0,0 +1,20 @@ +; RUN: opt -regions %s +define i32 @main() nounwind { +entry: + br label %for.cond + +test: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + br i1 true, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %for.inc + +for.inc: ; preds = %for.body + br label %for.cond + +for.end: ; preds = %for.cond + ret i32 0 +} diff --git a/final/test/Analysis/RegionInfo/block_sort.ll b/final/test/Analysis/RegionInfo/block_sort.ll new file mode 100644 index 00000000000..faec45a911f --- /dev/null +++ b/final/test/Analysis/RegionInfo/block_sort.ll @@ -0,0 +1,42 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats -analyze < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @BZ2_blockSort() nounwind { +start: + br label %while + +while: + br label %while.body134.i.i + +while.body134.i.i: + br i1 1, label %end, label %w + +w: + br label %if.end140.i.i + +if.end140.i.i: + br i1 1, label %while.end186.i.i, label %if.end183.i.i + +if.end183.i.i: + br label %while.body134.i.i + +while.end186.i.i: + br label %while + +end: + ret void +} +; CHECK-NOT: => +; CHECK: [0] start => +; CHECK: [1] while => end + +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: start, while, while.body134.i.i, end, w, if.end140.i.i, while.end186.i.i, if.end183.i.i, +; BBIT: while, while.body134.i.i, w, if.end140.i.i, while.end186.i.i, if.end183.i.i, + +; RNIT: start, while => end, end, +; RNIT: while, while.body134.i.i, w, if.end140.i.i, while.end186.i.i, if.end183.i.i, diff --git a/final/test/Analysis/RegionInfo/cond_loop.ll b/final/test/Analysis/RegionInfo/cond_loop.ll new file mode 100644 index 00000000000..2ce57c3c5f3 --- /dev/null +++ b/final/test/Analysis/RegionInfo/cond_loop.ll @@ -0,0 +1,33 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +5: + br label %"0" + +0: + br label %"1" +1: + br i1 1, label %"2", label %"3" +2: + ret void +3: + br i1 1, label %"1", label %"4" +4: + br label %"0" +} + +; CHECK-NOT: => +; CHECK: [0] 5 => +; CHECK: [1] 0 => 2 + +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 5, 0, 1, 2, 3, 4, +; BBIT: 0, 1, 3, 4, + +; RNIT: 5, 0 => 2, 2, +; RNIT: 0, 1, 3, 4, diff --git a/final/test/Analysis/RegionInfo/condition_complicated.ll b/final/test/Analysis/RegionInfo/condition_complicated.ll new file mode 100644 index 00000000000..7ca5c7c7b53 --- /dev/null +++ b/final/test/Analysis/RegionInfo/condition_complicated.ll @@ -0,0 +1,60 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc zeroext i8 @handle_compress() nounwind { +end165: + br i1 1, label %false239, label %true181 + +true181: + br i1 1, label %then187, label %else232 + +then187: + br label %end265 + +else232: + br i1 1, label %false239, label %then245 + +false239: + br i1 1, label %then245, label %else259 + +then245: + br i1 1, label %then251, label %end253 + +then251: + br label %end253 + +end253: + br label %end265 + +else259: + br label %end265 + +end265: + br i1 1, label %then291, label %end298 + +then291: + br label %end298 + +end298: + ret i8 1 +} + +; CHECK-NOT: => +; CHECK: [0] end165 => +; CHECK-NEXT: [1] end165 => end265 +; CHECK-NEXT: [2] then245 => end253 +; CHECK-NEXT: [1] end265 => end298 + +; STAT: 4 region - The # of regions + +; BBIT: end165, false239, then245, then251, end253, end265, then291, end298, else259, true181, then187, else232, +; BBIT: end165, false239, then245, then251, end253, else259, true181, then187, else232, +; BBIT: then245, then251, +; BBIT: end265, then291, + +; RNIT: end165 => end265, end265 => end298, end298, +; RNIT: end165, false239, then245 => end253, end253, else259, true181, then187, else232, +; RNIT: then245, then251, +; RNIT: end265, then291, diff --git a/final/test/Analysis/RegionInfo/condition_complicated_2.ll b/final/test/Analysis/RegionInfo/condition_complicated_2.ll new file mode 100644 index 00000000000..5fa940a61ef --- /dev/null +++ b/final/test/Analysis/RegionInfo/condition_complicated_2.ll @@ -0,0 +1,44 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc void @compress() nounwind { +end33: + br i1 1, label %end124, label %lor.lhs.false95 + +lor.lhs.false95: + br i1 1, label %then107, label %end172 + +then107: + br i1 1, label %end124, label %then113 + +then113: + br label %end124 + +end124: + br label %exit + +end172: + br label %exit + + +exit: + unreachable + + +} +; CHECK-NOT: => +; CHECK: [0] end33 => +; CHECK-NEXT: [1] end33 => exit +; CHECK-NEXT: [2] then107 => end124 + +; STAT: 3 region - The # of regions + +; BBIT: end33, end124, exit, lor.lhs.false95, then107, then113, end172, +; BBIT: end33, end124, lor.lhs.false95, then107, then113, end172, +; BBIT: then107, then113, + +; RNIT: end33 => exit, exit, +; RNIT: end33, end124, lor.lhs.false95, then107 => end124, end172, +; RNIT: then107, then113, diff --git a/final/test/Analysis/RegionInfo/condition_forward_edge.ll b/final/test/Analysis/RegionInfo/condition_forward_edge.ll new file mode 100644 index 00000000000..098c9b6b461 --- /dev/null +++ b/final/test/Analysis/RegionInfo/condition_forward_edge.ll @@ -0,0 +1,26 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"1" +1: + br i1 1, label %"2", label %"3" +2: + br label %"3" +3: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK: [1] 1 => 3 + +; STAT: 2 region - The # of regions + +; BBIT: 0, 1, 2, 3, +; BBIT: 1, 2, + +; RNIT: 0, 1 => 3, 3, +; RNIT: 1, 2, diff --git a/final/test/Analysis/RegionInfo/condition_same_exit.ll b/final/test/Analysis/RegionInfo/condition_same_exit.ll new file mode 100644 index 00000000000..1b88596c0f8 --- /dev/null +++ b/final/test/Analysis/RegionInfo/condition_same_exit.ll @@ -0,0 +1,31 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br i1 1, label %"1", label %"4" + +1: + br i1 1, label %"2", label %"3" +2: + br label %"4" +3: + br label %"4" +4: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 0 => 4 +; CHECK-NEXT: [2] 1 => 4 +; STAT: 3 region - The # of regions + +; BBIT: 0, 1, 2, 4, 3, +; BBIT: 0, 1, 2, 3, +; BBIT: 1, 2, 3, + +; RNIT: 0 => 4, 4, +; RNIT: 0, 1 => 4, +; RNIT: 1, 2, 3, diff --git a/final/test/Analysis/RegionInfo/condition_simple.ll b/final/test/Analysis/RegionInfo/condition_simple.ll new file mode 100644 index 00000000000..19b154b6476 --- /dev/null +++ b/final/test/Analysis/RegionInfo/condition_simple.ll @@ -0,0 +1,28 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"1" +1: + br i1 1, label %"2", label %"3" +2: + br label %"4" +3: + br label %"4" +4: + ret void +} + +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 1 => 4 +; STAT: 2 region - The # of regions + +; BBIT: 0, 1, 2, 4, 3, +; BBIT: 1, 2, 3, + +; RNIT: 0, 1 => 4, 4, +; RNIT: 1, 2, 3, diff --git a/final/test/Analysis/RegionInfo/dg.exp b/final/test/Analysis/RegionInfo/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Analysis/RegionInfo/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Analysis/RegionInfo/exit_in_condition.ll b/final/test/Analysis/RegionInfo/exit_in_condition.ll new file mode 100644 index 00000000000..3b152d2f565 --- /dev/null +++ b/final/test/Analysis/RegionInfo/exit_in_condition.ll @@ -0,0 +1,38 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc zeroext i8 @handle_compress() nounwind { +entry: + br label %outer + +outer: + br label %body + +body: + br i1 1, label %body.i, label %if.end + +body.i: + br i1 1, label %end, label %if.end + +if.end: + br label %if.then64 + +if.then64: + br label %outer + +end: + ret i8 1 +} +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK-NEXT: [1] outer => end +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: entry, outer, body, body.i, end, if.end, if.then64, +; BBIT: outer, body, body.i, if.end, if.then64, + +; RNIT: entry, outer => end, end, +; RNIT: outer, body, body.i, if.end, if.then64, diff --git a/final/test/Analysis/RegionInfo/infinite_loop.ll b/final/test/Analysis/RegionInfo/infinite_loop.ll new file mode 100644 index 00000000000..59cead49261 --- /dev/null +++ b/final/test/Analysis/RegionInfo/infinite_loop.ll @@ -0,0 +1,20 @@ +; RUN: opt -regions -analyze < %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s + +define void @normal_condition() nounwind { +0: + br label %"1" +1: + br i1 1, label %"2", label %"3" +2: + br label %"2" +3: + br label %"4" +4: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK: [1] 1 => 4 +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions diff --git a/final/test/Analysis/RegionInfo/infinite_loop_2.ll b/final/test/Analysis/RegionInfo/infinite_loop_2.ll new file mode 100644 index 00000000000..80c69b7ab2e --- /dev/null +++ b/final/test/Analysis/RegionInfo/infinite_loop_2.ll @@ -0,0 +1,36 @@ +; RUN: opt -regions -analyze < %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"1" +1: + br i1 1, label %"2", label %"3" +2: + br label %"5" +5: + br i1 1, label %"11", label %"12" +11: + br label %"6" +12: + br label %"6" +6: + br label %"2" +3: + br label %"4" +4: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK: [1] 1 => 3 +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 0, 1, 2, 5, 11, 6, 12, 3, 4, +; BBIT: 1, 2, 5, 11, 6, 12, + +; RNIT: 0, 1 => 3, 3, 4, +; RNIT: 1, 2, 5, 11, 6, 12, diff --git a/final/test/Analysis/RegionInfo/infinite_loop_3.ll b/final/test/Analysis/RegionInfo/infinite_loop_3.ll new file mode 100644 index 00000000000..74ceafb8495 --- /dev/null +++ b/final/test/Analysis/RegionInfo/infinite_loop_3.ll @@ -0,0 +1,52 @@ +; RUN: opt -regions -analyze < %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s + +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"7" +7: + br i1 1, label %"1", label %"8" +1: + br i1 1, label %"2", label %"3" +2: + br label %"5" +5: + br i1 1, label %"11", label %"12" +11: + br label %"6" +12: + br label %"6" +6: + br label %"2" +8: + br label %"9" +9: + br i1 1, label %"13", label %"14" +13: + br label %"10" +14: + br label %"10" +10: + br label %"8" +3: + br label %"4" +4: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 1 => 3 +; CHECK-NEXT: [1] 7 => 1 +; STAT: 3 region - The # of regions +; STAT: 2 region - The # of simple regions + +; BBIT: 0, 7, 1, 2, 5, 11, 6, 12, 3, 4, 8, 9, 13, 10, 14, +; BBIT: 7, 8, 9, 13, 10, 14, +; BBIT: 1, 2, 5, 11, 6, 12, + +; RNIT: 0, 7 => 1, 1 => 3, 3, 4, +; RNIT: 7, 8, 9, 13, 10, 14, +; RNIT: 1, 2, 5, 11, 6, 12, diff --git a/final/test/Analysis/RegionInfo/infinite_loop_4.ll b/final/test/Analysis/RegionInfo/infinite_loop_4.ll new file mode 100644 index 00000000000..fd56af1d3b8 --- /dev/null +++ b/final/test/Analysis/RegionInfo/infinite_loop_4.ll @@ -0,0 +1,48 @@ +; RUN: opt -regions -analyze < %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"7" +7: + br i1 1, label %"1", label %"8" +1: + br i1 1, label %"2", label %"3" +2: + br label %"5" +5: + br i1 1, label %"11", label %"12" +11: + br label %"6" +12: + br label %"6" +6: + br i1 1, label %"2", label %"10" +8: + br label %"9" +9: + br i1 1, label %"13", label %"14" +13: + br label %"10" +14: + br label %"10" +10: + br label %"8" +3: + br label %"4" +4: + ret void +} +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 7 => 3 +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 0, 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, 3, 4, +; BBIT: 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, + +; RNIT: 0, 7 => 3, 3, 4, +; RNIT: 7, 1, 2, 5, 11, 6, 10, 8, 9, 13, 14, 12, diff --git a/final/test/Analysis/RegionInfo/loop_with_condition.ll b/final/test/Analysis/RegionInfo/loop_with_condition.ll new file mode 100644 index 00000000000..d1d68982eec --- /dev/null +++ b/final/test/Analysis/RegionInfo/loop_with_condition.ll @@ -0,0 +1,46 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s + +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition() nounwind { +0: + br label %"1" +1: + br i1 1, label %"6", label %"2" +2: + br i1 1, label %"3", label %"4" +3: + br label %"5" +4: + br label %"5" +5: + br label %"8" +8: + br i1 1, label %"7", label %"9" +9: + br label %"2" +7: + br label %"6" +6: + ret void +} + +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 1 => 6 +; CHECK-NEXT: [2] 2 => 7 +; CHECK-NEXT: [3] 2 => 5 +; STAT: 4 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 0, 1, 6, 2, 3, 5, 8, 7, 9, 4, +; BBIT: 1, 2, 3, 5, 8, 7, 9, 4, +; BBIT: 2, 3, 5, 8, 9, 4, +; BBIT: 2, 3, 4, + +; RNIT: 0, 1 => 6, 6, +; RNIT: 1, 2 => 7, 7, +; RNIT: 2 => 5, 5, 8, 9, +; RNIT: 2, 3, 4, diff --git a/final/test/Analysis/RegionInfo/loops_1.ll b/final/test/Analysis/RegionInfo/loops_1.ll new file mode 100644 index 00000000000..d4bf3cc5011 --- /dev/null +++ b/final/test/Analysis/RegionInfo/loops_1.ll @@ -0,0 +1,40 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc zeroext i8 @loops_1() nounwind { +entry: + br i1 1, label %outer , label %a + +a: + br label %body + +outer: + br label %body + +body: + br i1 1, label %land, label %if + +land: + br i1 1, label %exit, label %end + +exit: + br i1 1, label %if, label %end + +if: + br label %outer + +end: + ret i8 1 +} +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK-NEXT: [1] entry => end +; STAT: 2 region - The # of regions + +; BBIT: entry, outer, body, land, exit, if, end, a, +; BBIT: entry, outer, body, land, exit, if, a, + +; RNIT: entry => end, end, +; RNIT: entry, outer, body, land, exit, if, a, diff --git a/final/test/Analysis/RegionInfo/loops_2.ll b/final/test/Analysis/RegionInfo/loops_2.ll new file mode 100644 index 00000000000..07aa7c31101 --- /dev/null +++ b/final/test/Analysis/RegionInfo/loops_2.ll @@ -0,0 +1,49 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @meread_() nounwind { +entry: + br label %bb23 + +bb23: + br label %bb.i + +bb.i: ; preds = %bb.i, %bb54 + br label %pflini_.exit + +pflini_.exit: ; preds = %bb.i + br label %bb58thread-split + +bb58thread-split: ; preds = %bb64, %bb61, %pflini_.exit + br label %bb58 + +bb58: ; preds = %bb60, %bb58thread-split + br i1 1, label %bb59, label %bb23 + +bb59: ; preds = %bb58 + switch i32 1, label %bb60 [ + i32 1, label %l98 + ] + +bb60: ; preds = %bb59 + br i1 1, label %bb61, label %bb58 + +bb61: ; preds = %bb60 + br label %bb58thread-split + +l98: ; preds = %bb69, %bb59 + ret void +} +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK: [1] bb23 => l98 +; STAT: 2 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: entry, bb23, bb.i, pflini_.exit, bb58thread-split, bb58, bb59, bb60, bb61, l98, +; BBIT: bb23, bb.i, pflini_.exit, bb58thread-split, bb58, bb59, bb60, bb61, + +; RNIT: entry, bb23 => l98, l98, +; RNIT: bb23, bb.i, pflini_.exit, bb58thread-split, bb58, bb59, bb60, bb61, diff --git a/final/test/Analysis/RegionInfo/mix_1.ll b/final/test/Analysis/RegionInfo/mix_1.ll new file mode 100644 index 00000000000..829c157c2c6 --- /dev/null +++ b/final/test/Analysis/RegionInfo/mix_1.ll @@ -0,0 +1,69 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s + +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @a_linear_impl_fig_1() nounwind { +0: + + br i1 1, label %"1", label %"15" +1: + switch i32 0, label %"2" [ i32 0, label %"3" + i32 1, label %"7"] +2: + br label %"4" +3: + br label %"5" +4: + br label %"6" +5: + br label %"6" +6: + br label %"7" +7: + br label %"15" +15: + br label %"8" +8: + br label %"16" +16: + br label %"9" +9: + br i1 1, label %"10", label %"11" +11: + br i1 1, label %"13", label %"12" +13: + br label %"14" +12: + br label %"14" +14: + br label %"8" +10: + br label %"17" +17: + br label %"18" +18: + ret void +} + +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 0 => 15 +; CHECK-NEXT: [2] 1 => 7 +; CHECK-NEXT: [1] 8 => 10 +; CHECK-NEXT: [2] 11 => 14 +; STAT: 5 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 0, 1, 2, 4, 6, 7, 15, 8, 16, 9, 10, 17, 18, 11, 13, 14, 12, 3, 5, +; BBIT: 0, 1, 2, 4, 6, 7, 3, 5, +; BBIT: 1, 2, 4, 6, 3, 5, +; BBIT: 8, 16, 9, 11, 13, 14, 12, +; BBIT: 11, 13, 12, + +; RNIT: 0 => 15, 15, 8 => 10, 10, 17, 18, +; RNIT: 0, 1 => 7, 7, +; RNIT: 1, 2, 4, 6, 3, 5, +; RNIT: 8, 16, 9, 11 => 14, 14, +; RNIT: 11, 13, 12, diff --git a/final/test/Analysis/RegionInfo/multiple_exiting_edge.ll b/final/test/Analysis/RegionInfo/multiple_exiting_edge.ll new file mode 100644 index 00000000000..7bc0e4607d6 --- /dev/null +++ b/final/test/Analysis/RegionInfo/multiple_exiting_edge.ll @@ -0,0 +1,38 @@ +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @normal_condition_0() nounwind { +bb38: ; preds = %bb34, %bb34, %bb37 + switch i32 undef, label %bb42 [ + i32 67, label %bb42 + i32 90, label %bb41 + ] +bb41: ; preds = %bb38 + br label %bb42 +bb42: ; preds = %bb38, %bb38, %bb41 + ret void +} + +; BBIT: bb38, bb42, bb41, +; BBIT: bb38, bb41, + +; RNIT: bb38 => bb42, bb42, +; RNIT: bb38, bb41, + +define void @normal_condition_1() nounwind { +bb38: ; preds = %bb34, %bb34, %bb37 + switch i32 undef, label %bb41 [ + i32 67, label %bb42 + i32 90, label %bb42 + ] +bb41: ; preds = %bb38 + br label %bb42 +bb42: ; preds = %bb38, %bb38, %bb41 + ret void +} + +; BBIT: bb38, bb41, bb42, +; BBIT: bb38, bb41, + +; RNIT: bb38 => bb42, bb42, +; RNIT: bb38, bb41, diff --git a/final/test/Analysis/RegionInfo/nested_loops.ll b/final/test/Analysis/RegionInfo/nested_loops.ll new file mode 100644 index 00000000000..9d8c4558f04 --- /dev/null +++ b/final/test/Analysis/RegionInfo/nested_loops.ll @@ -0,0 +1,33 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s + +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc zeroext i8 @handle_compress() nounwind { +entry: + br label %outer + +outer: + br label %body + +body: + br i1 1, label %exit172, label %end + +exit172: + br i1 1, label %end, label %outer + +end: + ret i8 1 +} +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK-NEXT: [1] outer => end + +; STAT: 2 region - The # of regions + +; BBIT: entry, outer, body, exit172, end, +; BBIT: outer, body, exit172, + +; RNIT: entry, outer => end, end, +; RNIT: outer, body, exit172, diff --git a/final/test/Analysis/RegionInfo/next.ll b/final/test/Analysis/RegionInfo/next.ll new file mode 100644 index 00000000000..d986387099c --- /dev/null +++ b/final/test/Analysis/RegionInfo/next.ll @@ -0,0 +1,49 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @MAIN__() nounwind { +entry: + br label %__label_002001.outer + +__label_002001.outer: ; preds = %bb236, %bb92 + br label %__label_002001 + +__label_002001: ; preds = %bb229, %__label_002001.outer + br i1 1, label %bb93, label %__label_000020 + +bb93: ; preds = %__label_002001 + br i1 1, label %__label_000020, label %bb197 + +bb197: ; preds = %bb193 + br i1 1, label %bb229, label %bb224 + +bb224: ; preds = %bb223, %bb227 + br i1 1, label %bb229, label %bb224 + +bb229: ; preds = %bb227, %bb223 + br i1 1, label %__label_002001, label %__label_002001.outer + +__label_000020: ; preds = %__label_002001, %bb194 + ret void +} + +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK-NEXT: [1] __label_002001.outer => __label_000020 +; CHECK-NEXT; [2] bb197 => bb229 +; CHECK-NEXT; [3] bb224 => bb229 + +; STAT: 4 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: entry, __label_002001.outer, __label_002001, bb93, __label_000020, bb197, bb229, bb224, +; BBIT: __label_002001.outer, __label_002001, bb93, bb197, bb229, bb224, +; BBIT: bb197, bb224, +; BBIT: bb224, + +; RNIT: entry, __label_002001.outer => __label_000020, __label_000020, +; RNIT: __label_002001.outer, __label_002001, bb93, bb197 => bb229, bb229, +; RNIT: bb197, bb224 => bb229, +; RNIT: bb224, diff --git a/final/test/Analysis/RegionInfo/paper.ll b/final/test/Analysis/RegionInfo/paper.ll new file mode 100644 index 00000000000..00b544bc691 --- /dev/null +++ b/final/test/Analysis/RegionInfo/paper.ll @@ -0,0 +1,55 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define void @a_linear_impl_fig_1() nounwind { +0: + br label %"1" +1: + br label %"2" +2: + br label %"3" +3: + br i1 1, label %"13", label %"4" +4: + br i1 1, label %"5", label %"1" +5: + br i1 1, label %"8", label %"6" +6: + br i1 1, label %"7", label %"4" +7: + ret void +8: + br i1 1, label %"9", label %"1" +9: + br label %"10" +10: + br i1 1, label %"12", label %"11" +11: + br i1 1, label %"9", label %"8" +13: + br i1 1, label %"2", label %"1" +12: + switch i32 0, label %"1" [ i32 0, label %"9" + i32 1, label %"8"] +} + +; CHECK-NOT: => +; CHECK: [0] 0 => +; CHECK-NEXT: [1] 1 => 7 +; CHECK-NEXT: [2] 1 => 4 +; CHECK-NEXT: [2] 8 => 1 + +; STAT: 4 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: 0, 1, 2, 3, 13, 4, 5, 8, 9, 10, 12, 11, 6, 7, +; BBIT: 1, 2, 3, 13, 4, 5, 8, 9, 10, 12, 11, 6, +; BBIT: 1, 2, 3, 13, +; BBIT: 8, 9, 10, 12, 11, + +; RNIT: 0, 1 => 7, 7, +; RNIT: 1 => 4, 4, 5, 8 => 1, 6, +; RNIT: 1, 2, 3, 13, +; RNIT: 8, 9, 10, 12, 11, diff --git a/final/test/Analysis/RegionInfo/two_loops_same_header.ll b/final/test/Analysis/RegionInfo/two_loops_same_header.ll new file mode 100644 index 00000000000..a97182b81a2 --- /dev/null +++ b/final/test/Analysis/RegionInfo/two_loops_same_header.ll @@ -0,0 +1,46 @@ +; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt -regions -stats < %s |& FileCheck -check-prefix=STAT %s +; RUN: opt -regions -print-region-style=bb -analyze < %s |& FileCheck -check-prefix=BBIT %s +; RUN: opt -regions -print-region-style=rn -analyze < %s |& FileCheck -check-prefix=RNIT %s + +define internal fastcc zeroext i8 @handle_compress() nounwind { +entry: + br label %outer + +outer: + br label %body + +body: + br i1 1, label %else, label %true77 + +true77: + br i1 1, label %then83, label %else + +then83: + br label %outer + +else: + br label %else106 + +else106: + br i1 1, label %end, label %outer + +end: + ret i8 1 +} + +; CHECK-NOT: => +; CHECK: [0] entry => +; CHECK-NEXT: [1] outer => end +; CHECK-NEXT: [2] outer => else + +; STAT: 3 region - The # of regions +; STAT: 1 region - The # of simple regions + +; BBIT: entry, outer, body, else, else106, end, true77, then83, +; BBIT: outer, body, else, else106, true77, then83, +; BBIT: outer, body, true77, then83, + +; RNIT: entry, outer => end, end, +; RNIT: outer => else, else, else106, +; RNIT: outer, body, true77, then83, diff --git a/final/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll b/final/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll new file mode 100644 index 00000000000..7ff130f201b --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {Loop %bb: backedge-taken count is 100} +; PR1533 + +@array = weak global [101 x i32] zeroinitializer, align 32 ; <[100 x i32]*> [#uses=1] + +define void @loop(i32 %x) { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %i.01.0 = phi i32 [ 100, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %tmp1 = getelementptr [101 x i32]* @array, i32 0, i32 %i.01.0 ; [#uses=1] + store i32 %x, i32* %tmp1 + %tmp4 = add i32 %i.01.0, -1 ; [#uses=2] + %tmp7 = icmp sgt i32 %tmp4, -1 ; [#uses=1] + br i1 %tmp7, label %bb, label %return + +return: ; preds = %bb + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll b/final/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll new file mode 100644 index 00000000000..e67e4d00d62 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-08-06-MisinterpretBranch.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -indvars -adce -simplifycfg -S | grep "icmp s" +; PR1598 + +define i32 @f(i32 %a, i32 %b, i32 %x, i32 %y) { +entry: + %tmp3 = icmp eq i32 %a, %b ; [#uses=1] + br i1 %tmp3, label %return, label %bb + +bb: ; preds = %bb, %entry + %x_addr.0 = phi i32 [ %tmp6, %bb ], [ %x, %entry ] ; [#uses=1] + %tmp6 = add i32 %x_addr.0, 1 ; [#uses=3] + %tmp9 = icmp slt i32 %tmp6, %y ; [#uses=1] + br i1 %tmp9, label %bb, label %return + +return: ; preds = %bb, %entry + %x_addr.1 = phi i32 [ %x, %entry ], [ %tmp6, %bb ] ; [#uses=1] + ret i32 %x_addr.1 +} diff --git a/final/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll b/final/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll new file mode 100644 index 00000000000..ab96243ef1f --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -scalar-evolution -analyze | grep {Loop %bb: backedge-taken count is (-1 + (-1 \\* %x) + %y)} +; PR1597 + +define i32 @f(i32 %x, i32 %y) { +entry: + %tmp63 = icmp ult i32 %x, %y ; [#uses=1] + br i1 %tmp63, label %bb.preheader, label %bb8 + +bb.preheader: ; preds = %entry + br label %bb + +bb: ; preds = %bb3, %bb.preheader + %x_addr.0 = phi i32 [ %tmp2, %bb3 ], [ %x, %bb.preheader ] ; [#uses=1] + %tmp2 = add i32 %x_addr.0, 1 ; [#uses=3] + br label %bb3 + +bb3: ; preds = %bb + %tmp6 = icmp ult i32 %tmp2, %y ; [#uses=1] + br i1 %tmp6, label %bb, label %bb8.loopexit + +bb8.loopexit: ; preds = %bb3 + br label %bb8 + +bb8: ; preds = %bb8.loopexit, %entry + %x_addr.1 = phi i32 [ %x, %entry ], [ %tmp2, %bb8.loopexit ] ; [#uses=1] + br label %return + +return: ; preds = %bb8 + ret i32 %x_addr.1 +} diff --git a/final/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll b/final/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll new file mode 100644 index 00000000000..b678fee22cb --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 13} +; PR1706 + +define i32 @f() { +entry: + br label %bb5 + +bb: ; preds = %bb5 + %tmp2 = shl i32 %j.0, 1 ; [#uses=1] + %tmp4 = add i32 %i.0, 268435456 ; [#uses=1] + br label %bb5 + +bb5: ; preds = %bb, %entry + %j.0 = phi i32 [ 1, %entry ], [ %tmp2, %bb ] ; [#uses=2] + %i.0 = phi i32 [ -1879048192, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %tmp7 = icmp slt i32 %i.0, 1610612736 ; [#uses=1] + br i1 %tmp7, label %bb, label %return + +return: ; preds = %bb5 + ret i32 %j.0 +} diff --git a/final/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll b/final/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll new file mode 100644 index 00000000000..514920f0f6f --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-11-14-SignedAddRec.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -indvars -S | grep printd | grep 1206807378 +; PR1798 + +declare void @printd(i32) + +define i32 @test() { +entry: + br label %bb6 + +bb: ; preds = %bb6 + %tmp3 = add i32 %x.0, %i.0 ; [#uses=1] + %tmp5 = add i32 %i.0, 1 ; [#uses=1] + br label %bb6 + +bb6: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp5, %bb ] ; [#uses=3] + %x.0 = phi i32 [ 0, %entry ], [ %tmp3, %bb ] ; [#uses=3] + %tmp8 = icmp slt i32 %i.0, 123456789 ; [#uses=1] + br i1 %tmp8, label %bb, label %bb10 + +bb10: ; preds = %bb6 + call void @printd(i32 %x.0) + ret i32 0 +} diff --git a/final/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll b/final/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll new file mode 100644 index 00000000000..c12721d82f0 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s +; PR1810 + +define void @fun() { +entry: + br label %header +header: + %i = phi i32 [ 1, %entry ], [ %i.next, %body ] + %cond = icmp eq i32 %i, 10 + br i1 %cond, label %exit, label %body +body: + %a = mul i32 %i, 5 + %b = or i32 %a, 1 + %i.next = add i32 %i, 1 + br label %header +exit: + ret void +} + +; CHECK: --> %b + diff --git a/final/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll b/final/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll new file mode 100644 index 00000000000..fe3a7f4191d --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -scalar-evolution -analyze | grep {Loop %header: backedge-taken count is (0 smax %n)} + +define void @foo(i32 %n) { +entry: + br label %header +header: + %i = phi i32 [ 0, %entry ], [ %i.inc, %next ] + %cond = icmp sgt i32 %n, %i + br i1 %cond, label %next, label %return +next: + %i.inc = add i32 %i, 1 + br label %header +return: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll b/final/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll new file mode 100644 index 00000000000..4f14a0d9a5e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -scalar-evolution -analyze | grep {Loop %loop: backedge-taken count is (100 + (-100 smax %n))} +; PR2002 + +define void @foo(i8 %n) { +entry: + br label %loop +loop: + %i = phi i8 [ -100, %entry ], [ %i.inc, %next ] + %cond = icmp slt i8 %i, %n + br i1 %cond, label %next, label %return +next: + %i.inc = add i8 %i, 1 + br label %loop +return: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll b/final/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll new file mode 100644 index 00000000000..52c7985045d --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-02-15-UMax.ll @@ -0,0 +1,17 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep umax +; PR2003 + +define i32 @foo(i32 %n) { +entry: + br label %header +header: + %i = phi i32 [ 100, %entry ], [ %i.inc, %next ] + %cond = icmp ult i32 %i, %n + br i1 %cond, label %next, label %return +next: + %i.inc = add i32 %i, 1 + br label %header +return: + ret i32 %i +} + diff --git a/final/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll b/final/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll new file mode 100644 index 00000000000..bcc124d1ecd --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 61} +; PR2364 + +define i32 @func_6() nounwind { +entry: + br label %bb5 + +bb: ; preds = %bb5 + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + %tmp4 = add i8 %x.0, -4 ; [#uses=1] + br label %bb5 + +bb5: ; preds = %bb, %entry + %x.0 = phi i8 [ 0, %entry ], [ %tmp4, %bb ] ; [#uses=2] + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=2] + %tmp7 = icmp eq i8 %x.0, 12 ; [#uses=1] + br i1 %tmp7, label %return, label %bb + +return: ; preds = %bb5 + ret i32 %i.0 +} diff --git a/final/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll b/final/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll new file mode 100644 index 00000000000..d503329292c --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-06-12-BinomialInt64.ll @@ -0,0 +1,43 @@ +; RUN: opt < %s -analyze -scalar-evolution 2>/dev/null +; PR2433 + +define i32 @main1(i32 %argc, i8** %argv) nounwind { +entry: + br i1 false, label %bb10, label %bb23 + +bb10: ; preds = %bb10, %entry + %accum.03 = phi i64 [ %tmp14, %bb10 ], [ 0, %entry ] ; [#uses=1] + %i.02 = phi i32 [ %tmp16, %bb10 ], [ 0, %entry ] ; [#uses=1] + %d.1.01 = phi i64 [ %tmp5.i, %bb10 ], [ 0, %entry ] ; [#uses=1] + %tmp5.i = add i64 %d.1.01, 1 ; [#uses=2] + %tmp14 = add i64 %accum.03, %tmp5.i ; [#uses=2] + %tmp16 = add i32 %i.02, 1 ; [#uses=2] + %tmp20 = icmp slt i32 %tmp16, 0 ; [#uses=1] + br i1 %tmp20, label %bb10, label %bb23 + +bb23: ; preds = %bb10, %entry + %accum.0.lcssa = phi i64 [ 0, %entry ], [ %tmp14, %bb10 ] ; [#uses=0] + ret i32 0 +} + +define i32 @main2(i32 %argc, i8** %argv) { +entry: + %tmp8 = tail call i32 @atoi( i8* null ) nounwind readonly ; [#uses=1] + br i1 false, label %bb9, label %bb21 + +bb9: ; preds = %bb9, %entry + %accum.03 = phi i64 [ %tmp12, %bb9 ], [ 0, %entry ] ; [#uses=1] + %i.02 = phi i32 [ %tmp14, %bb9 ], [ 0, %entry ] ; [#uses=1] + %d.1.01 = phi i64 [ %tmp4.i, %bb9 ], [ 0, %entry ] ; [#uses=1] + %tmp4.i = add i64 %d.1.01, 1 ; [#uses=2] + %tmp12 = add i64 %accum.03, %tmp4.i ; [#uses=2] + %tmp14 = add i32 %i.02, 1 ; [#uses=2] + %tmp18 = icmp slt i32 %tmp14, %tmp8 ; [#uses=1] + br i1 %tmp18, label %bb9, label %bb21 + +bb21: ; preds = %bb9, %entry + %accum.0.lcssa = phi i64 [ 0, %entry ], [ %tmp12, %bb9 ] ; [#uses=0] + ret i32 0 +} + +declare i32 @atoi(i8*) nounwind readonly diff --git a/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll b/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll new file mode 100644 index 00000000000..9db9b71c7c7 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -analyze -scalar-evolution |& not grep smax +; PR2261 + +@lut = common global [256 x i8] zeroinitializer, align 32 ; <[256 x i8]*> [#uses=1] + +define void @foo(i32 %count, i32* %srcptr, i32* %dstptr) nounwind { +entry: + icmp sgt i32 %count, 0 ; :0 [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %j.01 = phi i32 [ %8, %bb1 ], [ 0, %bb.nph ] ; [#uses=1] + load i32* %srcptr, align 4 ; :1 [#uses=2] + and i32 %1, 255 ; :2 [#uses=1] + and i32 %1, -256 ; :3 [#uses=1] + getelementptr [256 x i8]* @lut, i32 0, i32 %2 ; :4 [#uses=1] + load i8* %4, align 1 ; :5 [#uses=1] + zext i8 %5 to i32 ; :6 [#uses=1] + or i32 %6, %3 ; :7 [#uses=1] + store i32 %7, i32* %dstptr, align 4 + add i32 %j.01, 1 ; :8 [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + icmp slt i32 %8, %count ; :9 [#uses=1] + br i1 %9, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll b/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll new file mode 100644 index 00000000000..18476655525 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution |& not grep smax +; PR2070 + +define i32 @a(i32 %x) nounwind { +entry: + icmp sgt i32 %x, 1 ; :0 [#uses=1] + br i1 %0, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %z.02 = phi i32 [ %1, %bb1 ], [ 1, %bb.nph ] ; [#uses=1] + %i.01 = phi i32 [ %2, %bb1 ], [ 1, %bb.nph ] ; [#uses=2] + mul i32 %z.02, %i.01 ; :1 [#uses=2] + add i32 %i.01, 1 ; :2 [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + icmp slt i32 %2, %x ; :3 [#uses=1] + br i1 %3, label %bb, label %bb1.bb2_crit_edge + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %z.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 1, %entry ] ; [#uses=1] + ret i32 %z.0.lcssa +} diff --git a/final/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll b/final/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll new file mode 100644 index 00000000000..1865c059a99 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep Unpredictable +; PR2088 + +define void @fun() { +entry: + br label %loop +loop: + %i = phi i8 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i8 %i, 4 + %cond = icmp ne i8 %i.next, 6 + br i1 %cond, label %loop, label %exit +exit: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll b/final/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll new file mode 100644 index 00000000000..86e07ec41b9 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll @@ -0,0 +1,15 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 113} +; PR2088 + +define void @fun() { +entry: + br label %loop +loop: + %i = phi i8 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i8 %i, 18 + %cond = icmp ne i8 %i.next, 4 + br i1 %cond, label %loop, label %exit +exit: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll b/final/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll new file mode 100644 index 00000000000..75bd634b3ef --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-29-SGTTripCount.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2607 + +define i32 @_Z1aj(i32 %j) nounwind { +entry: + icmp sgt i32 0, %j ; :0 [#uses=1] + br i1 %0, label %bb.preheader, label %return + +bb.preheader: ; preds = %entry + br label %bb + +bb: ; preds = %bb, %bb.preheader + %i.01 = phi i32 [ %1, %bb ], [ 0, %bb.preheader ] ; [#uses=1] + add i32 %i.01, -1 ; :1 [#uses=3] + icmp sgt i32 %1, %j ; :2 [#uses=1] + br i1 %2, label %bb, label %return.loopexit + +return.loopexit: ; preds = %bb + br label %return + +return: ; preds = %return.loopexit, %entry + %i.0.lcssa = phi i32 [ 0, %entry ], [ %1, %return.loopexit ] ; [#uses=1] + ret i32 %i.0.lcssa +} + +; CHECK: backedge-taken count is (-1 + (-1 * %j)) + diff --git a/final/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll b/final/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll new file mode 100644 index 00000000000..3542ad2a41e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-07-29-SMinExpr.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2607 + +define i32 @b(i32 %x, i32 %y) nounwind { +entry: + %cmp2 = icmp slt i32 %y, %x + %cond3 = select i1 %cmp2, i32 %y, i32 %x + %cmp54 = icmp slt i32 %cond3, -2147483632 + br i1 %cmp54, label %forinc, label %afterfor + +forinc: ; preds = %forinc, %entry + %j.01 = phi i32 [ %dec, %forinc ], [ -2147483632, %entry ] + %dec = add i32 %j.01, -1 + %cmp = icmp slt i32 %y, %x + %cond = select i1 %cmp, i32 %y, i32 %x + %cmp5 = icmp sgt i32 %dec, %cond + br i1 %cmp5, label %forinc, label %afterfor + +afterfor: ; preds = %forinc, %entry + %j.0.lcssa = phi i32 [ -2147483632, %entry ], [ %dec, %forinc ] + ret i32 %j.0.lcssa +} + +; CHECK: backedge-taken count is (-2147483632 + ((-1 + (-1 * %{{[xy]}})) smax (-1 + (-1 * %{{[xy]}})))) + diff --git a/final/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll b/final/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll new file mode 100644 index 00000000000..3b31d797cf4 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-08-04-IVOverflow.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2621 + +define i32 @a() nounwind { +entry: + br label %bb1 + +bb: + trunc i32 %i.0 to i16 + add i16 %0, %x16.0 + add i32 %i.0, 1 + br label %bb1 + +bb1: + %i.0 = phi i32 [ 0, %entry ], [ %2, %bb ] + %x16.0 = phi i16 [ 0, %entry ], [ %1, %bb ] + icmp ult i32 %i.0, 888888 + br i1 %3, label %bb, label %bb2 + +bb2: + zext i16 %x16.0 to i32 + ret i32 %4 +} + +; CHECK: Exits: 20028 + diff --git a/final/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll b/final/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll new file mode 100644 index 00000000000..b296a19716c --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-08-04-LongAddRec.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | FileCheck %s +; PR2621 + +define i32 @a() nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + add i16 %x17.0, 1 ; :0 [#uses=2] + add i16 %0, %x16.0 ; :1 [#uses=2] + add i16 %1, %x15.0 ; :2 [#uses=2] + add i16 %2, %x14.0 ; :3 [#uses=2] + add i16 %3, %x13.0 ; :4 [#uses=2] + add i16 %4, %x12.0 ; :5 [#uses=2] + add i16 %5, %x11.0 ; :6 [#uses=2] + add i16 %6, %x10.0 ; :7 [#uses=2] + add i16 %7, %x9.0 ; :8 [#uses=2] + add i16 %8, %x8.0 ; :9 [#uses=2] + add i16 %9, %x7.0 ; :10 [#uses=2] + add i16 %10, %x6.0 ; :11 [#uses=2] + add i16 %11, %x5.0 ; :12 [#uses=2] + add i16 %12, %x4.0 ; :13 [#uses=2] + add i16 %13, %x3.0 ; :14 [#uses=2] + add i16 %14, %x2.0 ; :15 [#uses=2] + add i16 %15, %x1.0 ; :16 [#uses=1] + add i32 %i.0, 1 ; :17 [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %x2.0 = phi i16 [ 0, %entry ], [ %15, %bb ] ; [#uses=1] + %x3.0 = phi i16 [ 0, %entry ], [ %14, %bb ] ; [#uses=1] + %x4.0 = phi i16 [ 0, %entry ], [ %13, %bb ] ; [#uses=1] + %x5.0 = phi i16 [ 0, %entry ], [ %12, %bb ] ; [#uses=1] + %x6.0 = phi i16 [ 0, %entry ], [ %11, %bb ] ; [#uses=1] + %x7.0 = phi i16 [ 0, %entry ], [ %10, %bb ] ; [#uses=1] + %x8.0 = phi i16 [ 0, %entry ], [ %9, %bb ] ; [#uses=1] + %x9.0 = phi i16 [ 0, %entry ], [ %8, %bb ] ; [#uses=1] + %x10.0 = phi i16 [ 0, %entry ], [ %7, %bb ] ; [#uses=1] + %x11.0 = phi i16 [ 0, %entry ], [ %6, %bb ] ; [#uses=1] + %x12.0 = phi i16 [ 0, %entry ], [ %5, %bb ] ; [#uses=1] + %x13.0 = phi i16 [ 0, %entry ], [ %4, %bb ] ; [#uses=1] + %x14.0 = phi i16 [ 0, %entry ], [ %3, %bb ] ; [#uses=1] + %x15.0 = phi i16 [ 0, %entry ], [ %2, %bb ] ; [#uses=1] + %x16.0 = phi i16 [ 0, %entry ], [ %1, %bb ] ; [#uses=1] + %x17.0 = phi i16 [ 0, %entry ], [ %0, %bb ] ; [#uses=1] + %i.0 = phi i32 [ 0, %entry ], [ %17, %bb ] ; [#uses=2] + %x1.0 = phi i16 [ 0, %entry ], [ %16, %bb ] ; [#uses=2] + icmp ult i32 %i.0, 8888 ; :18 [#uses=1] + br i1 %18, label %bb, label %bb2 + +bb2: ; preds = %bb1 + zext i16 %x1.0 to i32 ; :19 [#uses=1] + ret i32 %19 +} + +; CHECK: Exits: -19168 + diff --git a/final/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll b/final/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll new file mode 100644 index 00000000000..7722122117d --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution +; PR1827 + +declare void @use(i32) + +define void @foo() { +entry: + br label %loop_1 + +loop_1: ; preds = %loop_1, %entry + %a = phi i32 [ 2, %entry ], [ %b, %loop_1 ] ; [#uses=2] + %c = phi i32 [ 5, %entry ], [ %d, %loop_1 ] ; [#uses=1] + %b = add i32 %a, 1 ; [#uses=1] + %d = add i32 %c, %a ; [#uses=3] + %A = icmp ult i32 %d, 50 ; [#uses=1] + br i1 %A, label %loop_1, label %endloop + +endloop: ; preds = %loop_1 + call void @use(i32 %d) + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll b/final/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll new file mode 100644 index 00000000000..2e2aabc475a --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -analyze -scalar-evolution +; PR2602 + +define i32 @a() nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %w.0 = phi i32 [ 0, %entry ], [ %tmp, %bb ] ; [#uses=2] + %e.0 = phi i32 [ 0, %entry ], [ %e.1, %bb ] ; [#uses=2] + %w.1 = add i32 0, %w.0 ; :0 [#uses=1] + %tmp = add i32 %e.0, %w.0 ; :1 [#uses=1] + %e.1 = add i32 %e.0, 1 ; :2 [#uses=1] + %cond = icmp eq i32 %w.1, -1 ; :3 [#uses=1] + br i1 %cond, label %return, label %bb + +return: ; preds = %bb + ret i32 undef +} diff --git a/final/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll b/final/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll new file mode 100644 index 00000000000..335bbaf9ad0 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -analyze -scalar-evolution |& \ +; RUN: grep {Loop %bb: backedge-taken count is (7 + (-1 \\* %argc))} + +define i32 @main(i32 %argc, i8** %argv) nounwind { +entry: + %0 = icmp ugt i32 %argc, 7 ; [#uses=1] + br i1 %0, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %argc_addr.04 = add i32 %indvar, %argc ; [#uses=1] + tail call void (...)* @Test() nounwind + %1 = add i32 %argc_addr.04, 1 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb + %phitmp = icmp ugt i32 %1, 7 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %phitmp, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + ret i32 0 +} + +declare void @Test(...) diff --git a/final/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll b/final/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll new file mode 100644 index 00000000000..db527fefa97 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | grep {Loop %bb: Unpredictable backedge-taken count\\.} + +; ScalarEvolution can't compute a trip count because it doesn't know if +; dividing by the stride will have a remainder. This could theoretically +; be teaching it how to use a more elaborate trip count computation. + +define i32 @f(i32 %x) nounwind readnone { +entry: + %0 = icmp ugt i32 %x, 4 ; [#uses=1] + br i1 %0, label %bb.nph, label %bb2 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %tmp = mul i32 %indvar, -3 ; [#uses=1] + %x_addr.04 = add i32 %tmp, %x ; [#uses=1] + %1 = add i32 %x_addr.04, -3 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %2 = icmp ugt i32 %1, 4 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %2, label %bb, label %bb1.bb2_crit_edge + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x, %entry ] ; [#uses=1] + ret i32 %x_addr.0.lcssa +} diff --git a/final/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll b/final/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll new file mode 100644 index 00000000000..fa9f21af371 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -analyze -scalar-evolution |& grep {/u 3} +; XFAIL: * + +; This is a tricky testcase for unsigned wrap detection which ScalarEvolution +; doesn't yet know how to do. + +define i32 @f(i32 %x) nounwind readnone { +entry: + %0 = icmp ugt i32 %x, 999 ; [#uses=1] + br i1 %0, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] + %tmp = mul i32 %indvar, 3 ; [#uses=1] + %x_addr.04 = add i32 %tmp, %x ; [#uses=1] + %1 = add i32 %x_addr.04, 3 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %2 = icmp ugt i32 %1, 999 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %2, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + %.lcssa = phi i32 [ %1, %bb1 ] ; [#uses=1] + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x, %entry ] ; [#uses=1] + ret i32 %x_addr.0.lcssa +} diff --git a/final/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll b/final/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll new file mode 100644 index 00000000000..25a0434b29e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep {backedge-taken count is 255} + +define i32 @foo(i32 %x, i32 %y, i32* %lam, i32* %alp) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %indvar = phi i32 [ 0, %bb1.thread ], [ %indvar.next, %bb1 ] ; [#uses=4] + %i.0.reg2mem.0 = sub i32 255, %indvar ; [#uses=2] + %0 = getelementptr i32* %alp, i32 %i.0.reg2mem.0 ; [#uses=1] + %1 = load i32* %0, align 4 ; [#uses=1] + %2 = getelementptr i32* %lam, i32 %i.0.reg2mem.0 ; [#uses=1] + store i32 %1, i32* %2, align 4 + %3 = sub i32 254, %indvar ; [#uses=1] + %4 = icmp slt i32 %3, 0 ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %4, label %bb2, label %bb1 + +bb2: ; preds = %bb1 + %tmp10 = mul i32 %indvar, %x ; [#uses=1] + %z.0.reg2mem.0 = add i32 %tmp10, %y ; [#uses=1] + %5 = add i32 %z.0.reg2mem.0, %x ; [#uses=1] + ret i32 %5 +} diff --git a/final/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll b/final/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll new file mode 100644 index 00000000000..12254e37dcc --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; CHECK: @f +; CHECK: Loop %bb16.preheader: backedge-taken count is (-1 + %c.idx.val) + +define i32 @f(i32 %c.idx.val) { + +bb2: + %k.018 = add i32 %c.idx.val, -1 ; [#uses=2] + %a14 = icmp slt i32 %k.018, 0 ; [#uses=1] + br i1 %a14, label %bb19, label %bb16.preheader + +bb16.preheader: + %k.019 = phi i32 [ %k.0, %bb18 ], [ %k.018, %bb2 ] ; [#uses=5] + %x = phi i32 [ 0, %bb2 ], [ %x.1, %bb18] + br label %bb18 + +bb18: ; preds = %bb18.loopexit + %x.1 = add i32 %x, 1 + %k.0 = add i32 %k.019, -1 ; [#uses=2] + %a107 = icmp slt i32 %k.0, 0 ; [#uses=1] + br i1 %a107, label %bb18.bb19_crit_edge, label %bb16.preheader + +bb18.bb19_crit_edge: + ret i32 %x + +bb19: + ret i32 0 + +} diff --git a/final/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll b/final/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll new file mode 100644 index 00000000000..8152e988ffc --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -analyze -scalar-evolution |& \ +; RUN: grep {(((-1 \\* %i0) + (100005 smax %i0)) /u 5)} +; XFAIL: * + +define i32 @foo0(i32 %i0) nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + %0 = add i32 %j.0, 1 ; [#uses=1] + %1 = add i32 %i.0, 5 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %j.0 = phi i32 [ 0, %entry ], [ %0, %bb ] ; [#uses=2] + %i.0 = phi i32 [ %i0, %entry ], [ %1, %bb ] ; [#uses=2] + %2 = icmp sgt i32 %i.0, 100000 ; [#uses=1] + br i1 %2, label %return, label %bb + +return: ; preds = %bb1 + ret i32 %j.0 +} diff --git a/final/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll b/final/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll new file mode 100644 index 00000000000..3eaa49212e7 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -analyze -scalar-evolution |& grep {/u 5} +; XFAIL: * + +define i8 @foo0(i8 %i0) nounwind { +entry: + br label %bb1 + +bb: ; preds = %bb1 + %0 = add i8 %j.0, 1 ; [#uses=1] + %1 = add i8 %i.0, 5 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb, %entry + %j.0 = phi i8 [ 0, %entry ], [ %0, %bb ] ; [#uses=2] + %i.0 = phi i8 [ %i0, %entry ], [ %1, %bb ] ; [#uses=2] + %2 = icmp sgt i8 %i.0, 100 ; [#uses=1] + br i1 %2, label %return, label %bb + +return: ; preds = %bb1 + ret i8 %j.0 +} diff --git a/final/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll b/final/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll new file mode 100644 index 00000000000..cc2a2e42bc9 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll @@ -0,0 +1,40 @@ +; RUN: opt < %s -analyze -scalar-evolution | not grep {/u -1} +; PR3275 + +@g_16 = external global i16 ; [#uses=3] +@.str = external constant [4 x i8] ; <[4 x i8]*> [#uses=0] + +define void @func_15() nounwind { +entry: + %0 = load i16* @g_16, align 2 ; [#uses=1] + %1 = icmp sgt i16 %0, 0 ; [#uses=1] + br i1 %1, label %bb2, label %bb.nph + +bb.nph: ; preds = %entry + %g_16.promoted = load i16* @g_16 ; [#uses=1] + br label %bb + +bb: ; preds = %bb1, %bb.nph + %g_16.tmp.0 = phi i16 [ %g_16.promoted, %bb.nph ], [ %2, %bb1 ] ; [#uses=1] + %2 = add i16 %g_16.tmp.0, -1 ; [#uses=3] + br label %bb1 + +bb1: ; preds = %bb + %3 = icmp sgt i16 %2, 0 ; [#uses=1] + br i1 %3, label %bb1.bb2_crit_edge, label %bb + +bb1.bb2_crit_edge: ; preds = %bb1 + store i16 %2, i16* @g_16 + br label %bb2 + +bb2: ; preds = %bb1.bb2_crit_edge, %entry + br label %return + +return: ; preds = %bb2 + ret void +} + +declare i32 @main() nounwind + +declare i32 @printf(i8*, ...) nounwind + diff --git a/final/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll b/final/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll new file mode 100644 index 00000000000..c2e108aa9c0 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep {(trunc i} | not grep ext + +define i16 @test1(i8 %x) { + %A = sext i8 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i8 @test2(i16 %x) { + %A = sext i16 %x to i32 + %B = trunc i32 %A to i8 + ret i8 %B +} + +define i16 @test3(i16 %x) { + %A = sext i16 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i16 @test4(i8 %x) { + %A = zext i8 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} + +define i8 @test5(i16 %x) { + %A = zext i16 %x to i32 + %B = trunc i32 %A to i8 + ret i8 %B +} + +define i16 @test6(i16 %x) { + %A = zext i16 %x to i32 + %B = trunc i32 %A to i16 + ret i16 %B +} diff --git a/final/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll b/final/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll new file mode 100644 index 00000000000..dc7bd29c57e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep {count is 2} +; PR3171 +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + + %struct.Foo = type { i32 } + %struct.NonPod = type { [2 x %struct.Foo] } + +define void @_Z3foov() nounwind { +entry: + %x = alloca %struct.NonPod, align 8 ; <%struct.NonPod*> [#uses=2] + %0 = getelementptr %struct.NonPod* %x, i32 0, i32 0 ; <[2 x %struct.Foo]*> [#uses=1] + %1 = getelementptr [2 x %struct.Foo]* %0, i32 1, i32 0 ; <%struct.Foo*> [#uses=1] + br label %bb1.i + +bb1.i: ; preds = %bb2.i, %entry + %.0.i = phi %struct.Foo* [ %1, %entry ], [ %4, %bb2.i ] ; <%struct.Foo*> [#uses=2] + %2 = getelementptr %struct.NonPod* %x, i32 0, i32 0, i32 0 ; <%struct.Foo*> [#uses=1] + %3 = icmp eq %struct.Foo* %.0.i, %2 ; [#uses=1] + br i1 %3, label %_ZN6NonPodD1Ev.exit, label %bb2.i + +bb2.i: ; preds = %bb1.i + %4 = getelementptr %struct.Foo* %.0.i, i32 -1 ; <%struct.Foo*> [#uses=1] + br label %bb1.i + +_ZN6NonPodD1Ev.exit: ; preds = %bb1.i + ret void +} + diff --git a/final/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll b/final/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll new file mode 100644 index 00000000000..a4358aa6321 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2009-07-04-GroupConstantsWidthMismatch.ll @@ -0,0 +1,16 @@ +; RUN: opt < %s -analyze -scalar-evolution +; PR4501 + +define void @test() { +entry: + %0 = load i16* undef, align 1 + %1 = lshr i16 %0, 8 + %2 = and i16 %1, 3 + %3 = zext i16 %2 to i32 + %4 = load i8* undef, align 1 + %5 = lshr i8 %4, 4 + %6 = and i8 %5, 1 + %7 = zext i8 %6 to i32 + %t1 = add i32 %3, %7 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/2010-09-03-RequiredTransitive.ll b/final/test/Analysis/ScalarEvolution/2010-09-03-RequiredTransitive.ll new file mode 100644 index 00000000000..aba0ce74678 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/2010-09-03-RequiredTransitive.ll @@ -0,0 +1,24 @@ +; RUN: opt -indvars -scalar-evolution -analyze %s +; This test checks if the SCEV analysis is printed out at all. +; It failed once as the RequiredTransitive option was not implemented +; correctly. + +define i32 @main() nounwind { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %indvar1 = phi i64 [ %indvar.next2, %for.inc ], [ 0, %entry ] ; [#uses=3] + %exitcond = icmp ne i64 %indvar1, 1024 ; [#uses=1] + br i1 %exitcond, label %for.body, label %for.end + +for.body: ; preds = %for.cond + br label %for.inc + +for.inc: ; preds = %for.body + %indvar.next2 = add i64 %indvar1, 1 ; [#uses=1] + br label %for.cond + +for.end: ; preds = %for.cond + ret i32 0 +} diff --git a/final/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll b/final/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll new file mode 100644 index 00000000000..9573aed1d73 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 100} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 2, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %SQ = mul i32 %i.0, %i.0 + %tmp4 = mul i32 %i.0, 2 + %tmp5 = sub i32 %SQ, %tmp4 + %tmp3 = icmp sle i32 %tmp5, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/and-xor.ll b/final/test/Analysis/ScalarEvolution/and-xor.ll new file mode 100644 index 00000000000..17725735a7c --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/and-xor.ll @@ -0,0 +1,8 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep {\\--> (zext} | count 2 + +define i32 @foo(i32 %x) { + %n = and i32 %x, 255 + %y = xor i32 %n, 255 + ret i32 %y +} diff --git a/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll b/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll new file mode 100644 index 00000000000..7eeb3084958 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-0.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution +; PR4537 + +; ModuleID = 'b.bc' +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @test() { +entry: + %0 = load i32** undef, align 8 ; [#uses=1] + %1 = ptrtoint i32* %0 to i64 ; [#uses=1] + %2 = sub i64 undef, %1 ; [#uses=1] + %3 = lshr i64 %2, 3 ; [#uses=1] + %4 = trunc i64 %3 to i32 ; [#uses=2] + br i1 undef, label %bb10, label %bb4.i + +bb4.i: ; preds = %bb4.i, %entry + %i.0.i6 = phi i32 [ %8, %bb4.i ], [ 0, %entry ] ; [#uses=2] + %5 = sub i32 %4, %i.0.i6 ; [#uses=1] + %6 = sext i32 %5 to i64 ; [#uses=1] + %7 = udiv i64 undef, %6 ; [#uses=1] + %8 = add i32 %i.0.i6, 1 ; [#uses=2] + %phitmp = icmp eq i64 %7, 0 ; [#uses=1] + %.not.i = icmp sge i32 %8, %4 ; [#uses=1] + %or.cond.i = or i1 %phitmp, %.not.i ; [#uses=1] + br i1 %or.cond.i, label %bb10, label %bb4.i + +bb10: ; preds = %bb4.i, %entry + unreachable +} diff --git a/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll b/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll new file mode 100644 index 00000000000..31b95e1470b --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/avoid-infinite-recursion-1.ll @@ -0,0 +1,354 @@ +; RUN: opt < %s -iv-users +; PR4538 + +; ModuleID = 'bugpoint-reduced-simplified.bc' +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-freebsd8.0" +module asm ".ident\09\22$FreeBSD: head/sys/kern/vfs_subr.c 195285 2009-07-02 14:19:33Z jamie $\22" +module asm ".section set_pcpu, \22aw\22, @progbits" +module asm ".previous" + type <{ [40 x i8] }> ; type %0 + type <{ %struct.vm_object*, %struct.vm_object** }> ; type %1 + type <{ %struct.vm_object* }> ; type %2 + type <{ %struct.vm_page*, %struct.vm_page** }> ; type %3 + type <{ %struct.pv_entry*, %struct.pv_entry** }> ; type %4 + type <{ %struct.vm_reserv* }> ; type %5 + type <{ %struct.bufobj*, %struct.bufobj** }> ; type %6 + type <{ %struct.proc*, %struct.proc** }> ; type %7 + type <{ %struct.thread*, %struct.thread** }> ; type %8 + type <{ %struct.prison*, %struct.prison** }> ; type %9 + type <{ %struct.prison* }> ; type %10 + type <{ %struct.task* }> ; type %11 + type <{ %struct.osd*, %struct.osd** }> ; type %12 + type <{ %struct.proc* }> ; type %13 + type <{ %struct.ksiginfo*, %struct.ksiginfo** }> ; type %14 + type <{ %struct.pv_chunk*, %struct.pv_chunk** }> ; type %15 + type <{ %struct.pgrp*, %struct.pgrp** }> ; type %16 + type <{ %struct.knote*, %struct.knote** }> ; type %17 + type <{ %struct.ktr_request*, %struct.ktr_request** }> ; type %18 + type <{ %struct.mqueue_notifier* }> ; type %19 + type <{ %struct.turnstile* }> ; type %20 + type <{ %struct.namecache* }> ; type %21 + type <{ %struct.namecache*, %struct.namecache** }> ; type %22 + type <{ %struct.lockf*, %struct.lockf** }> ; type %23 + type <{ %struct.lockf_entry*, %struct.lockf_entry** }> ; type %24 + type <{ %struct.lockf_edge*, %struct.lockf_edge** }> ; type %25 + %struct.__siginfo = type <{ i32, i32, i32, i32, i32, i32, i8*, %union.sigval, %0 }> + %struct.__sigset = type <{ [4 x i32] }> + %struct.acl = type <{ i32, i32, [4 x i32], [254 x %struct.acl_entry] }> + %struct.acl_entry = type <{ i32, i32, i32, i16, i16 }> + %struct.au_mask = type <{ i32, i32 }> + %struct.au_tid_addr = type <{ i32, i32, [4 x i32] }> + %struct.auditinfo_addr = type <{ i32, %struct.au_mask, %struct.au_tid_addr, i32, i64 }> + %struct.bintime = type <{ i64, i64 }> + %struct.buf = type <{ %struct.bufobj*, i64, i8*, i8*, i32, i8, i8, i8, i8, i64, i64, void (%struct.buf*)*, i64, i64, %struct.buflists, %struct.buf*, %struct.buf*, i32, i8, i8, i8, i8, %struct.buflists, i16, i8, i8, i32, i8, i8, i8, i8, i8, i8, i8, i8, %struct.lock, i64, i64, i8*, i32, i8, i8, i8, i8, i64, %struct.vnode*, i32, i32, %struct.ucred*, %struct.ucred*, i8*, %union.pager_info, i8, i8, i8, i8, %union.anon, [32 x %struct.vm_page*], i32, i8, i8, i8, i8, %struct.workhead, i8*, i8*, i8*, i32, i8, i8, i8, i8 }> + %struct.buf_ops = type <{ i8*, i32 (%struct.buf*)*, void (%struct.bufobj*, %struct.buf*)*, i32 (%struct.bufobj*, i32)*, void (%struct.bufobj*, %struct.buf*)* }> + %struct.buflists = type <{ %struct.buf*, %struct.buf** }> + %struct.bufobj = type <{ %struct.mtx, %struct.bufv, %struct.bufv, i64, i32, i8, i8, i8, i8, %struct.buf_ops*, i32, i8, i8, i8, i8, %struct.vm_object*, %6, i8*, %struct.vnode* }> + %struct.bufv = type <{ %struct.buflists, %struct.buf*, i32, i8, i8, i8, i8 }> + %struct.callout = type <{ %union.anon, i32, i8, i8, i8, i8, i8*, void (i8*)*, %struct.lock_object*, i32, i32 }> + %struct.cdev_privdata = type opaque + %struct.cluster_save = type <{ i64, i64, i8*, i32, i8, i8, i8, i8, %struct.buf** }> + %struct.componentname = type <{ i64, i64, %struct.thread*, %struct.ucred*, i32, i8, i8, i8, i8, i8*, i8*, i64, i64 }> + %struct.cpuset = type opaque + %struct.cv = type <{ i8*, i32, i8, i8, i8, i8 }> + %struct.fid = type <{ i16, i16, [16 x i8] }> + %struct.file = type <{ i8*, %struct.fileops*, %struct.ucred*, %struct.vnode*, i16, i16, i32, i32, i32, i64, %struct.cdev_privdata*, i64, i8* }> + %struct.filedesc = type opaque + %struct.filedesc_to_leader = type opaque + %struct.fileops = type <{ i32 (%struct.file*, %struct.uio*, %struct.ucred*, i32, %struct.thread*)*, i32 (%struct.file*, %struct.uio*, %struct.ucred*, i32, %struct.thread*)*, i32 (%struct.file*, i64, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, i64, i8*, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, i32, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, %struct.knote*)*, i32 (%struct.file*, %struct.stat*, %struct.ucred*, %struct.thread*)*, i32 (%struct.file*, %struct.thread*)*, i32, i8, i8, i8, i8 }> + %struct.filterops = type <{ i32, i8, i8, i8, i8, i32 (%struct.knote*)*, void (%struct.knote*)*, i32 (%struct.knote*, i64)* }> + %struct.flock = type <{ i64, i64, i32, i16, i16, i32, i8, i8, i8, i8 }> + %struct.freelst = type <{ %struct.vnode*, %struct.vnode** }> + %struct.fsid = type <{ [2 x i32] }> + %struct.in6_addr = type opaque + %struct.in_addr = type opaque + %struct.inode = type opaque + %struct.iovec = type <{ i8*, i64 }> + %struct.itimers = type opaque + %struct.itimerval = type <{ %struct.bintime, %struct.bintime }> + %struct.kaioinfo = type opaque + %struct.kaudit_record = type opaque + %struct.kdtrace_proc = type opaque + %struct.kdtrace_thread = type opaque + %struct.kevent = type <{ i64, i16, i16, i32, i64, i8* }> + %struct.klist = type <{ %struct.knote* }> + %struct.knlist = type <{ %struct.klist, void (i8*)*, void (i8*)*, void (i8*)*, void (i8*)*, i8* }> + %struct.knote = type <{ %struct.klist, %struct.klist, %struct.knlist*, %17, %struct.kqueue*, %struct.kevent, i32, i32, i64, %union.sigval, %struct.filterops*, i8* }> + %struct.kqueue = type opaque + %struct.ksiginfo = type <{ %14, %struct.__siginfo, i32, i8, i8, i8, i8, %struct.sigqueue* }> + %struct.ktr_request = type opaque + %struct.label = type opaque + %struct.lock = type <{ %struct.lock_object, i64, i32, i32 }> + %struct.lock_list_entry = type opaque + %struct.lock_object = type <{ i8*, i32, i32, %struct.witness* }> + %struct.lock_owner = type opaque + %struct.lock_profile_object = type opaque + %struct.lockf = type <{ %23, %struct.mtx, %struct.lockf_entry_list, %struct.lockf_entry_list, i32, i8, i8, i8, i8 }> + %struct.lockf_edge = type <{ %25, %25, %struct.lockf_entry*, %struct.lockf_entry* }> + %struct.lockf_edge_list = type <{ %struct.lockf_edge* }> + %struct.lockf_entry = type <{ i16, i16, i8, i8, i8, i8, i64, i64, %struct.lock_owner*, %struct.vnode*, %struct.inode*, %struct.task*, %24, %struct.lockf_edge_list, %struct.lockf_edge_list, i32, i8, i8, i8, i8 }> + %struct.lockf_entry_list = type <{ %struct.lockf_entry* }> + %struct.lpohead = type <{ %struct.lock_profile_object* }> + %struct.md_page = type <{ %4 }> + %struct.mdproc = type <{ %struct.cv*, %struct.system_segment_descriptor }> + %struct.mdthread = type <{ i32, i8, i8, i8, i8, i64 }> + %struct.mntarg = type opaque + %struct.mntlist = type <{ %struct.mount*, %struct.mount** }> + %struct.mount = type <{ %struct.mtx, i32, i8, i8, i8, i8, %struct.mntlist, %struct.vfsops*, %struct.vfsconf*, %struct.vnode*, %struct.vnode*, i32, i8, i8, i8, i8, %struct.freelst, i32, i32, i32, i32, i32, i32, %struct.vfsoptlist*, %struct.vfsoptlist*, i32, i8, i8, i8, i8, %struct.statfs, %struct.ucred*, i8*, i64, i32, i8, i8, i8, i8, %struct.netexport*, %struct.label*, i32, i32, i32, i32, %struct.thread*, i8*, %struct.lock }> + %struct.mqueue_notifier = type opaque + %struct.mtx = type <{ %struct.lock_object, i64 }> + %struct.namecache = type opaque + %struct.netexport = type opaque + %struct.nlminfo = type opaque + %struct.osd = type <{ i32, i8, i8, i8, i8, i8**, %12 }> + %struct.p_sched = type opaque + %struct.pargs = type <{ i32, i32, [1 x i8], i8, i8, i8 }> + %struct.pcb = type opaque + %struct.pgrp = type <{ %16, %13, %struct.session*, %struct.sigiolst, i32, i32, %struct.mtx }> + %struct.plimit = type opaque + %struct.pmap = type <{ %struct.mtx, i64*, %15, i32, i8, i8, i8, i8, %struct.bintime, %struct.vm_page* }> + %struct.prison = type <{ %9, i32, i32, i32, i32, %10, %9, %struct.prison*, %struct.mtx, %struct.task, %struct.osd, %struct.cpuset*, %struct.vnet*, %struct.vnode*, i32, i32, %struct.in_addr*, %struct.in6_addr*, [4 x i8*], i32, i32, i32, i32, i32, [5 x i32], i64, [256 x i8], [1024 x i8], [256 x i8], [256 x i8], [64 x i8] }> + %struct.proc = type <{ %7, %8, %struct.mtx, %struct.ucred*, %struct.filedesc*, %struct.filedesc_to_leader*, %struct.pstats*, %struct.plimit*, %struct.callout, %struct.sigacts*, i32, i32, i32, i8, i8, i8, i8, %7, %7, %struct.proc*, %7, %13, %struct.mtx, %struct.ksiginfo*, %struct.sigqueue, i32, i8, i8, i8, i8, %struct.vmspace*, i32, i8, i8, i8, i8, %struct.itimerval, %struct.rusage, %struct.rusage_ext, %struct.rusage_ext, i32, i32, i32, i8, i8, i8, i8, %struct.vnode*, %struct.ucred*, %struct.vnode*, i32, i8, i8, i8, i8, %struct.sigiolst, i32, i32, i64, i32, i32, i8, i8, i8, i8, i8, i8, i8, i8, %struct.nlminfo*, %struct.kaioinfo*, %struct.thread*, i32, i8, i8, i8, i8, %struct.thread*, i32, i32, %struct.itimers*, i32, i32, [20 x i8], i8, i8, i8, i8, %struct.pgrp*, %struct.sysentvec*, %struct.pargs*, i64, i8, i8, i8, i8, i32, i16, i8, i8, i8, i8, i8, i8, %struct.knlist, i32, i8, i8, i8, i8, %struct.mdproc, %struct.callout, i16, i8, i8, i8, i8, i8, i8, %struct.proc*, %struct.proc*, i8*, %struct.label*, %struct.p_sched*, %18, %19, %struct.kdtrace_proc*, %struct.cv }> + %struct.pstats = type opaque + %struct.pv_chunk = type <{ %struct.pmap*, %15, [3 x i64], [2 x i64], [168 x %struct.pv_entry] }> + %struct.pv_entry = type <{ i64, %4 }> + %struct.rusage = type <{ %struct.bintime, %struct.bintime, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64 }> + %struct.rusage_ext = type <{ i64, i64, i64, i64, i64, i64, i64 }> + %struct.selfd = type opaque + %struct.selfdlist = type <{ %struct.selfd*, %struct.selfd** }> + %struct.selinfo = type <{ %struct.selfdlist, %struct.knlist, %struct.mtx* }> + %struct.seltd = type opaque + %struct.session = type <{ i32, i8, i8, i8, i8, %struct.proc*, %struct.vnode*, %struct.tty*, i32, [24 x i8], i8, i8, i8, i8, %struct.mtx }> + %struct.shmmap_state = type opaque + %struct.sigacts = type <{ [128 x void (i32)*], [128 x %struct.__sigset], %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, %struct.__sigset, i32, i32, %struct.mtx }> + %struct.sigaltstack = type <{ i8*, i64, i32, i8, i8, i8, i8 }> + %struct.sigio = type <{ %union.sigval, %struct.sigiolst, %struct.sigio**, %struct.ucred*, i32, i8, i8, i8, i8 }> + %struct.sigiolst = type <{ %struct.sigio* }> + %struct.sigqueue = type <{ %struct.__sigset, %struct.__sigset, %14, %struct.proc*, i32, i8, i8, i8, i8 }> + %struct.sleepqueue = type opaque + %struct.sockaddr = type opaque + %struct.stat = type <{ i32, i32, i16, i16, i32, i32, i32, %struct.bintime, %struct.bintime, %struct.bintime, i64, i64, i32, i32, i32, i32, %struct.bintime }> + %struct.statfs = type <{ i32, i32, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, [10 x i64], i32, i32, %struct.fsid, [80 x i8], [16 x i8], [88 x i8], [88 x i8] }> + %struct.sysctl_req = type <{ %struct.thread*, i32, i8, i8, i8, i8, i8*, i64, i64, i32 (%struct.sysctl_req*, i8*, i64)*, i8*, i64, i64, i32 (%struct.sysctl_req*, i8*, i64)*, i64, i32, i8, i8, i8, i8 }> + %struct.sysentvec = type opaque + %struct.system_segment_descriptor = type <{ i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 }> + %struct.task = type <{ %11, i16, i16, i8, i8, i8, i8, void (i8*, i32)*, i8* }> + %struct.td_sched = type opaque + %struct.thread = type <{ %struct.mtx*, %struct.proc*, %8, %8, %8, %8, %struct.cpuset*, %struct.seltd*, %struct.sleepqueue*, %struct.turnstile*, %struct.umtx_q*, i32, i8, i8, i8, i8, %struct.sigqueue, i32, i32, i32, i32, i32, i8, i8, i8, i8, i8*, i8*, i8, i8, i8, i8, i16, i16, i16, i8, i8, i8, i8, i8, i8, %struct.turnstile*, i8*, %20, %struct.lock_list_entry*, i32, i32, %struct.ucred*, i32, i32, %struct.rusage, i64, i64, i32, i32, i32, i32, i32, %struct.__sigset, %struct.__sigset, i32, %struct.sigaltstack, i32, i8, i8, i8, i8, i64, i32, [20 x i8], %struct.file*, i32, i32, %struct.osd, i8, i8, i8, i8, i8, i8, i8, i8, %struct.pcb*, i32, i8, i8, i8, i8, [2 x i64], %struct.callout, %struct.trapframe*, %struct.vm_object*, i64, i32, i8, i8, i8, i8, %struct.vm_object*, i64, i32, i32, %struct.mdthread, %struct.td_sched*, %struct.kaudit_record*, i32, i8, i8, i8, i8, [2 x %struct.lpohead], %struct.kdtrace_thread*, i32, i8, i8, i8, i8, %struct.vnet*, i8* }> + %struct.trapframe = type <{ i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, i32, i16, i16, i64, i32, i16, i16, i64, i64, i64, i64, i64, i64 }> + %struct.tty = type opaque + %struct.turnstile = type opaque + %struct.ucred = type <{ i32, i32, i32, i32, i32, i32, i32, i8, i8, i8, i8, %struct.uidinfo*, %struct.uidinfo*, %struct.prison*, %struct.vimage*, i32, i8, i8, i8, i8, [2 x i8*], %struct.label*, %struct.auditinfo_addr, i32*, i32, i8, i8, i8, i8 }> + %struct.uidinfo = type opaque + %struct.uio = type <{ %struct.iovec*, i32, i8, i8, i8, i8, i64, i64, i32, i32, %struct.thread* }> + %struct.umtx_q = type opaque + %struct.vattr = type <{ i32, i16, i16, i32, i32, i32, i8, i8, i8, i8, i64, i64, i64, %struct.bintime, %struct.bintime, %struct.bintime, %struct.bintime, i64, i64, i32, i8, i8, i8, i8, i64, i64, i32, i8, i8, i8, i8, i64 }> + %struct.vfsconf = type <{ i32, [16 x i8], i8, i8, i8, i8, %struct.vfsops*, i32, i32, i32, i8, i8, i8, i8, %struct.vfsoptdecl*, %struct.vfsconfhead }> + %struct.vfsconfhead = type <{ %struct.vfsconf*, %struct.vfsconf** }> + %struct.vfsops = type <{ i32 (%struct.mount*)*, i32 (%struct.mntarg*, i8*, i32)*, i32 (%struct.mount*, i32)*, i32 (%struct.mount*, i32, %struct.vnode**)*, i32 (%struct.mount*, i32, i32, i8*)*, i32 (%struct.mount*, %struct.statfs*)*, i32 (%struct.mount*, i32)*, i32 (%struct.mount*, i32, i32, %struct.vnode**)*, i32 (%struct.mount*, %struct.fid*, %struct.vnode**)*, i32 (%struct.mount*, %struct.sockaddr*, i32*, %struct.ucred**, i32*, i32**)*, i32 (%struct.vfsconf*)*, i32 (%struct.vfsconf*)*, i32 (%struct.mount*, i32, %struct.vnode*, i32, i8*)*, i32 (%struct.mount*, i32, %struct.sysctl_req*)*, void (%struct.mount*)* }> + %struct.vfsopt = type <{ %struct.vfsoptlist, i8*, i8*, i32, i32, i32, i8, i8, i8, i8 }> + %struct.vfsoptdecl = type opaque + %struct.vfsoptlist = type <{ %struct.vfsopt*, %struct.vfsopt** }> + %struct.vimage = type opaque + %struct.vm_map = type <{ %struct.vm_map_entry, %struct.mtx, %struct.mtx, i32, i8, i8, i8, i8, i64, i32, i8, i8, i8, i8, %struct.vm_map_entry*, %struct.pmap*, %struct.vm_map_entry* }> + %struct.vm_map_entry = type <{ %struct.vm_map_entry*, %struct.vm_map_entry*, %struct.vm_map_entry*, %struct.vm_map_entry*, i64, i64, i64, i64, i64, %union.sigval, i64, i32, i8, i8, i8, i8, i32, i8, i8, i8, i8, i64, %struct.uidinfo* }> + %struct.vm_object = type <{ %struct.mtx, %1, %2, %1, %3, %struct.vm_page*, i64, i32, i32, i32, i8, i8, i16, i16, i16, i32, %struct.vm_object*, i64, %1, %5, %struct.vm_page*, i8*, %union.anon, %struct.uidinfo*, i64 }> + %struct.vm_page = type <{ %3, %3, %struct.vm_page*, %struct.vm_page*, %struct.vm_object*, i64, i64, %struct.md_page, i8, i8, i16, i8, i8, i16, i32, i16, i16, i8, i8, i8, i8, i8, i8, i8, i8 }> + %struct.vm_reserv = type opaque + %struct.vmspace = type <{ %struct.vm_map, %struct.shmmap_state*, i64, i64, i64, i64, i8*, i8*, i8*, i32, i8, i8, i8, i8, %struct.pmap }> + %struct.vnet = type opaque + %struct.vnode = type <{ i32, i8, i8, i8, i8, i8*, %struct.vop_vector*, i8*, %struct.mount*, %struct.freelst, %union.sigval, %struct.freelst, i32, i8, i8, i8, i8, %21, %22, %struct.namecache*, i64, i64, i64, i32, i8, i8, i8, i8, %struct.lock, %struct.mtx, %struct.lock*, i32, i32, i64, i64, i32, i8, i8, i8, i8, %struct.freelst, %struct.bufobj, %struct.vpollinfo*, %struct.label*, %struct.lockf* }> + %struct.vnodeop_desc = type <{ i8*, i32, i8, i8, i8, i8, i32 (%struct.vop_generic_args*)*, i32*, i32, i32, i32, i32 }> + %struct.vop_access_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread* }> + %struct.vop_aclcheck_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.acl*, %struct.ucred*, %struct.thread* }> + %struct.vop_advlock_args = type <{ %struct.vop_generic_args, %struct.vnode*, i8*, i32, i8, i8, i8, i8, %struct.flock*, i32, i8, i8, i8, i8 }> + %struct.vop_advlockasync_args = type <{ %struct.vop_generic_args, %struct.vnode*, i8*, i32, i8, i8, i8, i8, %struct.flock*, i32, i8, i8, i8, i8, %struct.task*, i8** }> + %struct.vop_bmap_args = type <{ %struct.vop_generic_args, %struct.vnode*, i64, %struct.bufobj**, i64*, i32*, i32* }> + %struct.vop_cachedlookup_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname* }> + %struct.vop_create_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname*, %struct.vattr* }> + %struct.vop_deleteextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.ucred*, %struct.thread* }> + %struct.vop_fsync_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.thread* }> + %struct.vop_generic_args = type <{ %struct.vnodeop_desc* }> + %struct.vop_getattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vattr*, %struct.ucred* }> + %struct.vop_getextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.uio*, i64*, %struct.ucred*, %struct.thread* }> + %struct.vop_getpages_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vm_page**, i32, i32, i64 }> + %struct.vop_getwritemount_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.mount** }> + %struct.vop_inactive_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.thread* }> + %struct.vop_ioctl_args = type <{ %struct.vop_generic_args, %struct.vnode*, i64, i8*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread* }> + %struct.vop_islocked_args = type <{ %struct.vop_generic_args, %struct.vnode* }> + %struct.vop_kqfilter_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.knote* }> + %struct.vop_link_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode*, %struct.componentname* }> + %struct.vop_listextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.uio*, i64*, %struct.ucred*, %struct.thread* }> + %struct.vop_lock1_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, i32, i8, i8, i8, i8 }> + %struct.vop_open_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, %struct.ucred*, %struct.thread*, %struct.file* }> + %struct.vop_openextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.ucred*, %struct.thread* }> + %struct.vop_pathconf_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i64* }> + %struct.vop_putpages_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vm_page**, i32, i32, i32*, i64 }> + %struct.vop_read_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, i32, i8, i8, i8, i8, %struct.ucred* }> + %struct.vop_readdir_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, %struct.ucred*, i32*, i32*, i64** }> + %struct.vop_readlink_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.uio*, %struct.ucred* }> + %struct.vop_reallocblks_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.cluster_save* }> + %struct.vop_rename_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode*, %struct.componentname*, %struct.vnode*, %struct.vnode*, %struct.componentname* }> + %struct.vop_revoke_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8 }> + %struct.vop_setextattr_args = type <{ %struct.vop_generic_args, %struct.vnode*, i32, i8, i8, i8, i8, i8*, %struct.uio*, %struct.ucred*, %struct.thread* }> + %struct.vop_setlabel_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.label*, %struct.ucred*, %struct.thread* }> + %struct.vop_strategy_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.buf* }> + %struct.vop_symlink_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.componentname*, %struct.vattr*, i8* }> + %struct.vop_vector = type <{ %struct.vop_vector*, i32 (%struct.vop_generic_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_cachedlookup_args*)*, i32 (%struct.vop_cachedlookup_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_whiteout_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_open_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_getattr_args*)*, i32 (%struct.vop_getattr_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_read_args*)*, i32 (%struct.vop_read_args*)*, i32 (%struct.vop_ioctl_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_kqfilter_args*)*, i32 (%struct.vop_revoke_args*)*, i32 (%struct.vop_fsync_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_rename_args*)*, i32 (%struct.vop_create_args*)*, i32 (%struct.vop_link_args*)*, i32 (%struct.vop_symlink_args*)*, i32 (%struct.vop_readdir_args*)*, i32 (%struct.vop_readlink_args*)*, i32 (%struct.vop_inactive_args*)*, i32 (%struct.vop_inactive_args*)*, i32 (%struct.vop_lock1_args*)*, i32 (%struct.vop_revoke_args*)*, i32 (%struct.vop_bmap_args*)*, i32 (%struct.vop_strategy_args*)*, i32 (%struct.vop_getwritemount_args*)*, i32 (%struct.vop_islocked_args*)*, i32 (%struct.vop_pathconf_args*)*, i32 (%struct.vop_advlock_args*)*, i32 (%struct.vop_advlockasync_args*)*, i32 (%struct.vop_reallocblks_args*)*, i32 (%struct.vop_getpages_args*)*, i32 (%struct.vop_putpages_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_aclcheck_args*)*, i32 (%struct.vop_access_args*)*, i32 (%struct.vop_getextattr_args*)*, i32 (%struct.vop_listextattr_args*)*, i32 (%struct.vop_openextattr_args*)*, i32 (%struct.vop_deleteextattr_args*)*, i32 (%struct.vop_setextattr_args*)*, i32 (%struct.vop_setlabel_args*)*, i32 (%struct.vop_vptofh_args*)*, i32 (%struct.vop_vptocnp_args*)* }> + %struct.vop_vptocnp_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.vnode**, %struct.ucred*, i8*, i32* }> + %struct.vop_vptofh_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.fid* }> + %struct.vop_whiteout_args = type <{ %struct.vop_generic_args, %struct.vnode*, %struct.componentname*, i32, i8, i8, i8, i8 }> + %struct.vpollinfo = type <{ %struct.mtx, %struct.selinfo, i16, i16, i8, i8, i8, i8 }> + %struct.witness = type opaque + %struct.workhead = type <{ %struct.worklist* }> + %struct.worklist = type opaque + %union.anon = type <{ [16 x i8] }> + %union.pager_info = type <{ [4 x i8] }> + %union.sigval = type <{ [8 x i8] }> + +define i32 @vlrureclaim(%struct.mount* %mp) nounwind { +entry: + br i1 undef, label %if.then11, label %do.end + +if.then11: ; preds = %entry + br label %do.end + +do.end: ; preds = %if.then11, %entry + br label %while.cond.outer + +while.cond.outer: ; preds = %while.cond.outer.backedge, %do.end + %count.0.ph = phi i32 [ undef, %do.end ], [ undef, %while.cond.outer.backedge ] ; [#uses=1] + br label %while.cond + +while.cond: ; preds = %next_iter, %while.cond.outer + %count.0 = phi i32 [ %dec, %next_iter ], [ %count.0.ph, %while.cond.outer ] ; [#uses=2] + %cmp21 = icmp eq i32 %count.0, 0 ; [#uses=1] + br i1 %cmp21, label %do.body288.loopexit4, label %while.body + +while.body: ; preds = %while.cond + br label %while.cond27 + +while.cond27: ; preds = %while.body36, %while.body + br i1 undef, label %do.body288.loopexit, label %land.rhs + +land.rhs: ; preds = %while.cond27 + br i1 undef, label %while.body36, label %while.end + +while.body36: ; preds = %land.rhs + br label %while.cond27 + +while.end: ; preds = %land.rhs + br i1 undef, label %do.body288.loopexit4, label %do.body46 + +do.body46: ; preds = %while.end + br i1 undef, label %if.else64, label %if.then53 + +if.then53: ; preds = %do.body46 + br label %if.end72 + +if.else64: ; preds = %do.body46 + br label %if.end72 + +if.end72: ; preds = %if.else64, %if.then53 + %dec = add i32 %count.0, -1 ; [#uses=2] + br i1 undef, label %next_iter, label %if.end111 + +if.end111: ; preds = %if.end72 + br i1 undef, label %lor.lhs.false, label %do.body145 + +lor.lhs.false: ; preds = %if.end111 + br i1 undef, label %lor.lhs.false122, label %do.body145 + +lor.lhs.false122: ; preds = %lor.lhs.false + br i1 undef, label %lor.lhs.false128, label %do.body145 + +lor.lhs.false128: ; preds = %lor.lhs.false122 + br i1 undef, label %do.body162, label %land.lhs.true + +land.lhs.true: ; preds = %lor.lhs.false128 + br i1 undef, label %do.body145, label %do.body162 + +do.body145: ; preds = %land.lhs.true, %lor.lhs.false122, %lor.lhs.false, %if.end111 + br i1 undef, label %if.then156, label %next_iter + +if.then156: ; preds = %do.body145 + br label %next_iter + +do.body162: ; preds = %land.lhs.true, %lor.lhs.false128 + br i1 undef, label %if.then173, label %do.end177 + +if.then173: ; preds = %do.body162 + br label %do.end177 + +do.end177: ; preds = %if.then173, %do.body162 + br i1 undef, label %do.body185, label %if.then182 + +if.then182: ; preds = %do.end177 + br label %next_iter_mntunlocked + +do.body185: ; preds = %do.end177 + br i1 undef, label %if.then196, label %do.end202 + +if.then196: ; preds = %do.body185 + br label %do.end202 + +do.end202: ; preds = %if.then196, %do.body185 + br i1 undef, label %lor.lhs.false207, label %if.then231 + +lor.lhs.false207: ; preds = %do.end202 + br i1 undef, label %lor.lhs.false214, label %if.then231 + +lor.lhs.false214: ; preds = %lor.lhs.false207 + br i1 undef, label %do.end236, label %land.lhs.true221 + +land.lhs.true221: ; preds = %lor.lhs.false214 + br i1 undef, label %if.then231, label %do.end236 + +if.then231: ; preds = %land.lhs.true221, %lor.lhs.false207, %do.end202 + br label %next_iter_mntunlocked + +do.end236: ; preds = %land.lhs.true221, %lor.lhs.false214 + br label %next_iter_mntunlocked + +next_iter_mntunlocked: ; preds = %do.end236, %if.then231, %if.then182 + br i1 undef, label %yield, label %do.body269 + +next_iter: ; preds = %if.then156, %do.body145, %if.end72 + %rem2482 = and i32 %dec, 255 ; [#uses=1] + %cmp249 = icmp eq i32 %rem2482, 0 ; [#uses=1] + br i1 %cmp249, label %do.body253, label %while.cond + +do.body253: ; preds = %next_iter + br i1 undef, label %if.then264, label %yield + +if.then264: ; preds = %do.body253 + br label %yield + +yield: ; preds = %if.then264, %do.body253, %next_iter_mntunlocked + br label %do.body269 + +do.body269: ; preds = %yield, %next_iter_mntunlocked + br i1 undef, label %if.then280, label %while.cond.outer.backedge + +if.then280: ; preds = %do.body269 + br label %while.cond.outer.backedge + +while.cond.outer.backedge: ; preds = %if.then280, %do.body269 + br label %while.cond.outer + +do.body288.loopexit: ; preds = %while.cond27 + br label %do.body288 + +do.body288.loopexit4: ; preds = %while.end, %while.cond + br label %do.body288 + +do.body288: ; preds = %do.body288.loopexit4, %do.body288.loopexit + br i1 undef, label %if.then299, label %do.end303 + +if.then299: ; preds = %do.body288 + br label %do.end303 + +do.end303: ; preds = %if.then299, %do.body288 + ret i32 undef +} diff --git a/final/test/Analysis/ScalarEvolution/avoid-smax-0.ll b/final/test/Analysis/ScalarEvolution/avoid-smax-0.ll new file mode 100644 index 00000000000..24275f9fc4a --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/avoid-smax-0.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -scalar-evolution -analyze | grep {Loop %bb3: backedge-taken count is (-1 + %n)} + +; We don't want to use a max in the trip count expression in +; this testcase. + +define void @foo(i32 %n, i32* %p, i32* %q) nounwind { +entry: + icmp sgt i32 %n, 0 + br i1 %0, label %bb, label %return + +bb: + load i32* %q, align 4 + icmp eq i32 %1, 0 + br i1 %2, label %return, label %bb3.preheader + +bb3.preheader: + br label %bb3 + +bb3: + %i.0 = phi i32 [ %7, %bb3 ], [ 0, %bb3.preheader ] + getelementptr i32* %p, i32 %i.0 + load i32* %3, align 4 + add i32 %4, 1 + getelementptr i32* %p, i32 %i.0 + store i32 %5, i32* %6, align 4 + add i32 %i.0, 1 + icmp slt i32 %7, %n + br i1 %8, label %bb3, label %return.loopexit + +return.loopexit: + br label %return + +return: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/avoid-smax-1.ll b/final/test/Analysis/ScalarEvolution/avoid-smax-1.ll new file mode 100644 index 00000000000..89e8b983c0c --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/avoid-smax-1.ll @@ -0,0 +1,236 @@ +; RUN: opt < %s -indvars -S > %t +; RUN: grep select %t | count 2 +; RUN: grep {icmp ne i32.\* } %t + +; Indvars should be able to insert a canonical induction variable +; for the bb6 loop without using a maximum calculation (icmp, select) +; because it should be able to prove that the comparison is guarded +; by an appropriate conditional branch. Unfortunately, indvars is +; not yet able to find the comparison for the other two loops in +; this testcase. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin9" + +define void @foo(i8* %r, i32 %s, i32 %w, i32 %x, i8* %j, i32 %d) nounwind { +entry: + %0 = mul i32 %x, %w ; [#uses=2] + %1 = mul i32 %x, %w ; [#uses=1] + %2 = sdiv i32 %1, 4 ; [#uses=1] + %.sum2 = add i32 %2, %0 ; [#uses=2] + %cond = icmp eq i32 %d, 1 ; [#uses=1] + br i1 %cond, label %bb29, label %bb10.preheader + +bb10.preheader: ; preds = %entry + %3 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %3, label %bb.nph9, label %bb18.loopexit + +bb.nph7: ; preds = %bb7.preheader + %4 = mul i32 %y.08, %w ; [#uses=1] + %5 = mul i32 %y.08, %s ; [#uses=1] + %6 = add i32 %5, 1 ; [#uses=1] + br label %bb6 + +bb6: ; preds = %bb7, %bb.nph7 + %x.06 = phi i32 [ %13, %bb7 ], [ 0, %bb.nph7 ] ; [#uses=3] + %7 = add i32 %x.06, %4 ; [#uses=1] + %8 = shl i32 %x.06, 1 ; [#uses=1] + %9 = add i32 %6, %8 ; [#uses=1] + %10 = getelementptr i8* %r, i32 %9 ; [#uses=1] + %11 = load i8* %10, align 1 ; [#uses=1] + %12 = getelementptr i8* %j, i32 %7 ; [#uses=1] + store i8 %11, i8* %12, align 1 + %13 = add i32 %x.06, 1 ; [#uses=2] + br label %bb7 + +bb7: ; preds = %bb6 + %14 = icmp slt i32 %13, %w ; [#uses=1] + br i1 %14, label %bb6, label %bb7.bb9_crit_edge + +bb7.bb9_crit_edge: ; preds = %bb7 + br label %bb9 + +bb9: ; preds = %bb7.preheader, %bb7.bb9_crit_edge + %15 = add i32 %y.08, 1 ; [#uses=2] + br label %bb10 + +bb10: ; preds = %bb9 + %16 = icmp slt i32 %15, %x ; [#uses=1] + br i1 %16, label %bb7.preheader, label %bb10.bb18.loopexit_crit_edge + +bb10.bb18.loopexit_crit_edge: ; preds = %bb10 + br label %bb10.bb18.loopexit_crit_edge.split + +bb10.bb18.loopexit_crit_edge.split: ; preds = %bb.nph9, %bb10.bb18.loopexit_crit_edge + br label %bb18.loopexit + +bb.nph9: ; preds = %bb10.preheader + %17 = icmp sgt i32 %w, 0 ; [#uses=1] + br i1 %17, label %bb.nph9.split, label %bb10.bb18.loopexit_crit_edge.split + +bb.nph9.split: ; preds = %bb.nph9 + br label %bb7.preheader + +bb7.preheader: ; preds = %bb.nph9.split, %bb10 + %y.08 = phi i32 [ %15, %bb10 ], [ 0, %bb.nph9.split ] ; [#uses=3] + br i1 true, label %bb.nph7, label %bb9 + +bb.nph5: ; preds = %bb18.loopexit + %18 = sdiv i32 %w, 2 ; [#uses=1] + %19 = icmp slt i32 %w, 2 ; [#uses=1] + %20 = sdiv i32 %x, 2 ; [#uses=1] + br i1 %19, label %bb18.bb20_crit_edge.split, label %bb.nph5.split + +bb.nph5.split: ; preds = %bb.nph5 + br label %bb13 + +bb13: ; preds = %bb18, %bb.nph5.split + %y.14 = phi i32 [ %42, %bb18 ], [ 0, %bb.nph5.split ] ; [#uses=4] + %21 = mul i32 %18, %y.14 ; [#uses=2] + %22 = shl i32 %y.14, 1 ; [#uses=1] + %23 = srem i32 %y.14, 2 ; [#uses=1] + %24 = add i32 %23, %22 ; [#uses=1] + %25 = mul i32 %24, %s ; [#uses=2] + br i1 true, label %bb.nph3, label %bb17 + +bb.nph3: ; preds = %bb13 + %26 = add i32 %21, %0 ; [#uses=1] + %27 = add i32 %21, %.sum2 ; [#uses=1] + %28 = sdiv i32 %w, 2 ; [#uses=1] + br label %bb14 + +bb14: ; preds = %bb15, %bb.nph3 + %x.12 = phi i32 [ %40, %bb15 ], [ 0, %bb.nph3 ] ; [#uses=5] + %29 = shl i32 %x.12, 2 ; [#uses=1] + %30 = add i32 %29, %25 ; [#uses=1] + %31 = getelementptr i8* %r, i32 %30 ; [#uses=1] + %32 = load i8* %31, align 1 ; [#uses=1] + %.sum = add i32 %26, %x.12 ; [#uses=1] + %33 = getelementptr i8* %j, i32 %.sum ; [#uses=1] + store i8 %32, i8* %33, align 1 + %34 = shl i32 %x.12, 2 ; [#uses=1] + %35 = or i32 %34, 2 ; [#uses=1] + %36 = add i32 %35, %25 ; [#uses=1] + %37 = getelementptr i8* %r, i32 %36 ; [#uses=1] + %38 = load i8* %37, align 1 ; [#uses=1] + %.sum6 = add i32 %27, %x.12 ; [#uses=1] + %39 = getelementptr i8* %j, i32 %.sum6 ; [#uses=1] + store i8 %38, i8* %39, align 1 + %40 = add i32 %x.12, 1 ; [#uses=2] + br label %bb15 + +bb15: ; preds = %bb14 + %41 = icmp sgt i32 %28, %40 ; [#uses=1] + br i1 %41, label %bb14, label %bb15.bb17_crit_edge + +bb15.bb17_crit_edge: ; preds = %bb15 + br label %bb17 + +bb17: ; preds = %bb15.bb17_crit_edge, %bb13 + %42 = add i32 %y.14, 1 ; [#uses=2] + br label %bb18 + +bb18.loopexit: ; preds = %bb10.bb18.loopexit_crit_edge.split, %bb10.preheader + %43 = icmp slt i32 %x, 2 ; [#uses=1] + br i1 %43, label %bb20, label %bb.nph5 + +bb18: ; preds = %bb17 + %44 = icmp sgt i32 %20, %42 ; [#uses=1] + br i1 %44, label %bb13, label %bb18.bb20_crit_edge + +bb18.bb20_crit_edge: ; preds = %bb18 + br label %bb18.bb20_crit_edge.split + +bb18.bb20_crit_edge.split: ; preds = %bb18.bb20_crit_edge, %bb.nph5 + br label %bb20 + +bb20: ; preds = %bb18.bb20_crit_edge.split, %bb18.loopexit + switch i32 %d, label %return [ + i32 3, label %bb22 + i32 1, label %bb29 + ] + +bb22: ; preds = %bb20 + %45 = mul i32 %x, %w ; [#uses=1] + %46 = sdiv i32 %45, 4 ; [#uses=1] + %.sum3 = add i32 %46, %.sum2 ; [#uses=2] + %47 = add i32 %x, 15 ; [#uses=1] + %48 = and i32 %47, -16 ; [#uses=1] + %49 = add i32 %w, 15 ; [#uses=1] + %50 = and i32 %49, -16 ; [#uses=1] + %51 = mul i32 %48, %s ; [#uses=1] + %52 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %52, label %bb.nph, label %bb26 + +bb.nph: ; preds = %bb22 + br label %bb23 + +bb23: ; preds = %bb24, %bb.nph + %y.21 = phi i32 [ %57, %bb24 ], [ 0, %bb.nph ] ; [#uses=3] + %53 = mul i32 %y.21, %50 ; [#uses=1] + %.sum1 = add i32 %53, %51 ; [#uses=1] + %54 = getelementptr i8* %r, i32 %.sum1 ; [#uses=1] + %55 = mul i32 %y.21, %w ; [#uses=1] + %.sum5 = add i32 %55, %.sum3 ; [#uses=1] + %56 = getelementptr i8* %j, i32 %.sum5 ; [#uses=1] + tail call void @llvm.memcpy.i32(i8* %56, i8* %54, i32 %w, i32 1) + %57 = add i32 %y.21, 1 ; [#uses=2] + br label %bb24 + +bb24: ; preds = %bb23 + %58 = icmp slt i32 %57, %x ; [#uses=1] + br i1 %58, label %bb23, label %bb24.bb26_crit_edge + +bb24.bb26_crit_edge: ; preds = %bb24 + br label %bb26 + +bb26: ; preds = %bb24.bb26_crit_edge, %bb22 + %59 = mul i32 %x, %w ; [#uses=1] + %.sum4 = add i32 %.sum3, %59 ; [#uses=1] + %60 = getelementptr i8* %j, i32 %.sum4 ; [#uses=1] + %61 = mul i32 %x, %w ; [#uses=1] + %62 = sdiv i32 %61, 2 ; [#uses=1] + tail call void @llvm.memset.i32(i8* %60, i8 -128, i32 %62, i32 1) + ret void + +bb29: ; preds = %bb20, %entry + %63 = add i32 %w, 15 ; [#uses=1] + %64 = and i32 %63, -16 ; [#uses=1] + %65 = icmp sgt i32 %x, 0 ; [#uses=1] + br i1 %65, label %bb.nph11, label %bb33 + +bb.nph11: ; preds = %bb29 + br label %bb30 + +bb30: ; preds = %bb31, %bb.nph11 + %y.310 = phi i32 [ %70, %bb31 ], [ 0, %bb.nph11 ] ; [#uses=3] + %66 = mul i32 %y.310, %64 ; [#uses=1] + %67 = getelementptr i8* %r, i32 %66 ; [#uses=1] + %68 = mul i32 %y.310, %w ; [#uses=1] + %69 = getelementptr i8* %j, i32 %68 ; [#uses=1] + tail call void @llvm.memcpy.i32(i8* %69, i8* %67, i32 %w, i32 1) + %70 = add i32 %y.310, 1 ; [#uses=2] + br label %bb31 + +bb31: ; preds = %bb30 + %71 = icmp slt i32 %70, %x ; [#uses=1] + br i1 %71, label %bb30, label %bb31.bb33_crit_edge + +bb31.bb33_crit_edge: ; preds = %bb31 + br label %bb33 + +bb33: ; preds = %bb31.bb33_crit_edge, %bb29 + %72 = mul i32 %x, %w ; [#uses=1] + %73 = getelementptr i8* %j, i32 %72 ; [#uses=1] + %74 = mul i32 %x, %w ; [#uses=1] + %75 = sdiv i32 %74, 2 ; [#uses=1] + tail call void @llvm.memset.i32(i8* %73, i8 -128, i32 %75, i32 1) + ret void + +return: ; preds = %bb20 + ret void +} + +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind + +declare void @llvm.memset.i32(i8*, i8, i32, i32) nounwind diff --git a/final/test/Analysis/ScalarEvolution/dg.exp b/final/test/Analysis/ScalarEvolution/dg.exp new file mode 100644 index 00000000000..b65a2503ac6 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.ll]] diff --git a/final/test/Analysis/ScalarEvolution/div-overflow.ll b/final/test/Analysis/ScalarEvolution/div-overflow.ll new file mode 100644 index 00000000000..4f6f1e2a300 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/div-overflow.ll @@ -0,0 +1,10 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep {\\--> ((-128 \\* %a) /u -128)} + +; Don't let ScalarEvolution fold this div away. + +define i8 @foo(i8 %a) { + %t0 = shl i8 %a, 7 + %t1 = lshr i8 %t0, 7 + ret i8 %t1 +} diff --git a/final/test/Analysis/ScalarEvolution/do-loop.ll b/final/test/Analysis/ScalarEvolution/do-loop.ll new file mode 100644 index 00000000000..6e3295a920b --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/do-loop.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep smax +; PR1614 + +define i32 @f(i32 %x, i32 %y) { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %x_addr.0 = add i32 %indvar, %x ; [#uses=1] + %tmp2 = add i32 %x_addr.0, 1 ; [#uses=2] + %tmp5 = icmp slt i32 %tmp2, %y ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br i1 %tmp5, label %bb, label %bb7 + +bb7: ; preds = %bb + ret i32 %tmp2 +} diff --git a/final/test/Analysis/ScalarEvolution/fold.ll b/final/test/Analysis/ScalarEvolution/fold.ll new file mode 100644 index 00000000000..4e2adf187e8 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/fold.ll @@ -0,0 +1,62 @@ +; RUN: opt -analyze -scalar-evolution %s -S | FileCheck %s + +define i16 @test1(i8 %x) { + %A = zext i8 %x to i12 + %B = sext i12 %A to i16 +; CHECK: zext i8 %x to i16 + ret i16 %B +} + +define i8 @test2(i8 %x) { + %A = zext i8 %x to i16 + %B = add i16 %A, 1025 + %C = trunc i16 %B to i8 +; CHECK: (1 + %x) + ret i8 %C +} + +define i8 @test3(i8 %x) { + %A = zext i8 %x to i16 + %B = mul i16 %A, 1027 + %C = trunc i16 %B to i8 +; CHECK: (3 * %x) + ret i8 %C +} + +define void @test4(i32 %x, i32 %y) { +entry: + %Y = and i32 %y, 3 + br label %loop +loop: + %A = phi i32 [0, %entry], [%I, %loop] + %rand1 = icmp sgt i32 %A, %Y + %Z1 = select i1 %rand1, i32 %A, i32 %Y + %rand2 = icmp ugt i32 %A, %Z1 + %Z2 = select i1 %rand2, i32 %A, i32 %Z1 +; CHECK: %Z2 = +; CHECK-NEXT: --> ([[EXPR:.*]]){{ +}}Exits: 20 + %B = trunc i32 %Z2 to i16 + %C = sext i16 %B to i30 +; CHECK: %C = +; CHECK-NEXT: (trunc i32 ([[EXPR]]) to i30) + %D = sext i16 %B to i32 +; CHECK: %D = +; CHECK-NEXT: ([[EXPR]]) + %E = sext i16 %B to i34 +; CHECK: %E = +; CHECK-NEXT: (zext i32 ([[EXPR]]) to i34) + %F = zext i16 %B to i30 +; CHECK: %F = +; CHECK-NEXT: (trunc i32 ([[EXPR]]) to i30 + %G = zext i16 %B to i32 +; CHECK: %G = +; CHECK-NEXT: ([[EXPR]]) + %H = zext i16 %B to i34 +; CHECK: %H = +; CHECK-NEXT: (zext i32 ([[EXPR]]) to i34) + %I = add i32 %A, 1 + %0 = icmp ne i32 %A, 20 + br i1 %0, label %loop, label %exit +exit: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/max-trip-count.ll b/final/test/Analysis/ScalarEvolution/max-trip-count.ll new file mode 100644 index 00000000000..843fb073087 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/max-trip-count.ll @@ -0,0 +1,72 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; ScalarEvolution should be able to understand the loop and eliminate the casts. + +; CHECK: {%d,+,sizeof(i32)} + +define void @foo(i32* nocapture %d, i32 %n) nounwind { +entry: + %0 = icmp sgt i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %i.02 = phi i32 [ %5, %bb1 ], [ 0, %bb.nph ] ; [#uses=2] + %p.01 = phi i8 [ %4, %bb1 ], [ -1, %bb.nph ] ; [#uses=2] + %1 = sext i8 %p.01 to i32 ; [#uses=1] + %2 = sext i32 %i.02 to i64 ; [#uses=1] + %3 = getelementptr i32* %d, i64 %2 ; [#uses=1] + store i32 %1, i32* %3, align 4 + %4 = add i8 %p.01, 1 ; [#uses=1] + %5 = add i32 %i.02, 1 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %6 = icmp slt i32 %5, %n ; [#uses=1] + br i1 %6, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} + +; ScalarEvolution should be able to find the maximum tripcount +; of this multiple-exit loop, and if it doesn't know the exact +; count, it should say so. + +; PR7845 +; CHECK: Loop %for.cond: Unpredictable backedge-taken count. +; CHECK: Loop %for.cond: max backedge-taken count is 5 + +@.str = private constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=2] + +define i32 @main() nounwind { +entry: + br label %for.cond + +for.cond: ; preds = %for.inc, %entry + %g_4.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] ; [#uses=5] + %cmp = icmp slt i32 %g_4.0, 5 ; [#uses=1] + br i1 %cmp, label %for.body, label %for.end + +for.body: ; preds = %for.cond + %conv = trunc i32 %g_4.0 to i16 ; [#uses=1] + %tobool.not = icmp eq i16 %conv, 0 ; [#uses=1] + %tobool3 = icmp ne i32 %g_4.0, 0 ; [#uses=1] + %or.cond = and i1 %tobool.not, %tobool3 ; [#uses=1] + br i1 %or.cond, label %for.end, label %for.inc + +for.inc: ; preds = %for.body + %add = add nsw i32 %g_4.0, 1 ; [#uses=1] + br label %for.cond + +for.end: ; preds = %for.body, %for.cond + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %g_4.0) nounwind ; [#uses=0] + ret i32 0 +} + +declare i32 @printf(i8*, ...) diff --git a/final/test/Analysis/ScalarEvolution/nsw-offset.ll b/final/test/Analysis/ScalarEvolution/nsw-offset.ll new file mode 100644 index 00000000000..4cd9a6de48c --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/nsw-offset.ll @@ -0,0 +1,77 @@ +; RUN: opt < %s -S -analyze -scalar-evolution | FileCheck %s + +; ScalarEvolution should be able to fold away the sign-extensions +; on this loop with a primary induction variable incremented with +; a nsw add of 2. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define void @foo(i32 %no, double* nocapture %d, double* nocapture %q) nounwind { +entry: + %n = and i32 %no, 4294967294 + %0 = icmp sgt i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb.nph, %bb1 + %i.01 = phi i32 [ %16, %bb1 ], [ 0, %bb.nph ] ; [#uses=5] + +; CHECK: %1 = sext i32 %i.01 to i64 +; CHECK: --> {0,+,2}<%bb> + %1 = sext i32 %i.01 to i64 ; [#uses=1] + +; CHECK: %2 = getelementptr inbounds double* %d, i64 %1 +; CHECK: --> {%d,+,16}<%bb> + %2 = getelementptr inbounds double* %d, i64 %1 ; [#uses=1] + + %3 = load double* %2, align 8 ; [#uses=1] + %4 = sext i32 %i.01 to i64 ; [#uses=1] + %5 = getelementptr inbounds double* %q, i64 %4 ; [#uses=1] + %6 = load double* %5, align 8 ; [#uses=1] + %7 = or i32 %i.01, 1 ; [#uses=1] + +; CHECK: %8 = sext i32 %7 to i64 +; CHECK: --> {1,+,2}<%bb> + %8 = sext i32 %7 to i64 ; [#uses=1] + +; CHECK: %9 = getelementptr inbounds double* %q, i64 %8 +; CHECK: {(8 + %q),+,16}<%bb> + %9 = getelementptr inbounds double* %q, i64 %8 ; [#uses=1] + +; Artificially repeat the above three instructions, this time using +; add nsw instead of or. + %t7 = add nsw i32 %i.01, 1 ; [#uses=1] + +; CHECK: %t8 = sext i32 %t7 to i64 +; CHECK: --> {1,+,2}<%bb> + %t8 = sext i32 %t7 to i64 ; [#uses=1] + +; CHECK: %t9 = getelementptr inbounds double* %q, i64 %t8 +; CHECK: {(8 + %q),+,16}<%bb> + %t9 = getelementptr inbounds double* %q, i64 %t8 ; [#uses=1] + + %10 = load double* %9, align 8 ; [#uses=1] + %11 = fadd double %6, %10 ; [#uses=1] + %12 = fadd double %11, 3.200000e+00 ; [#uses=1] + %13 = fmul double %3, %12 ; [#uses=1] + %14 = sext i32 %i.01 to i64 ; [#uses=1] + %15 = getelementptr inbounds double* %d, i64 %14 ; [#uses=1] + store double %13, double* %15, align 8 + %16 = add nsw i32 %i.01, 2 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %17 = icmp slt i32 %16, %n ; [#uses=1] + br i1 %17, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} + +; CHECK: Loop %bb: backedge-taken count is ((-1 + %n) /u 2) +; CHECK: Loop %bb: max backedge-taken count is 1073741822 diff --git a/final/test/Analysis/ScalarEvolution/nsw.ll b/final/test/Analysis/ScalarEvolution/nsw.ll new file mode 100644 index 00000000000..9d8e2b62a9d --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/nsw.ll @@ -0,0 +1,106 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; The addrecs in this loop are analyzable only by using nsw information. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +; CHECK: Classifying expressions for: @test1 +define void @test1(double* %p) nounwind { +entry: + %tmp = load double* %p, align 8 ; [#uses=1] + %tmp1 = fcmp ogt double %tmp, 2.000000e+00 ; [#uses=1] + br i1 %tmp1, label %bb.nph, label %return + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %i.01 = phi i32 [ %tmp8, %bb1 ], [ 0, %bb.nph ] ; [#uses=3] +; CHECK: %i.01 +; CHECK-NEXT: --> {0,+,1}<%bb> + %tmp2 = sext i32 %i.01 to i64 ; [#uses=1] + %tmp3 = getelementptr double* %p, i64 %tmp2 ; [#uses=1] + %tmp4 = load double* %tmp3, align 8 ; [#uses=1] + %tmp5 = fmul double %tmp4, 9.200000e+00 ; [#uses=1] + %tmp6 = sext i32 %i.01 to i64 ; [#uses=1] + %tmp7 = getelementptr double* %p, i64 %tmp6 ; [#uses=1] +; CHECK: %tmp7 +; CHECK-NEXT: --> {%p,+,8}<%bb> + store double %tmp5, double* %tmp7, align 8 + %tmp8 = add nsw i32 %i.01, 1 ; [#uses=2] +; CHECK: %tmp8 +; CHECK-NEXT: --> {1,+,1}<%bb> + br label %bb1 + +bb1: ; preds = %bb + %phitmp = sext i32 %tmp8 to i64 ; [#uses=1] +; CHECK: %phitmp +; CHECK-NEXT: --> {1,+,1}<%bb> + %tmp9 = getelementptr double* %p, i64 %phitmp ; [#uses=1] +; CHECK: %tmp9 +; CHECK-NEXT: --> {(8 + %p),+,8}<%bb> + %tmp10 = load double* %tmp9, align 8 ; [#uses=1] + %tmp11 = fcmp ogt double %tmp10, 2.000000e+00 ; [#uses=1] + br i1 %tmp11, label %bb, label %bb1.return_crit_edge + +bb1.return_crit_edge: ; preds = %bb1 + br label %return + +return: ; preds = %bb1.return_crit_edge, %entry + ret void +} + +; CHECK: Classifying expressions for: @test2 +define void @test2(i32* %begin, i32* %end) ssp { +entry: + %cmp1.i.i = icmp eq i32* %begin, %end + br i1 %cmp1.i.i, label %_ZSt4fillIPiiEvT_S1_RKT0_.exit, label %for.body.lr.ph.i.i + +for.body.lr.ph.i.i: ; preds = %entry + br label %for.body.i.i + +for.body.i.i: ; preds = %for.body.i.i, %for.body.lr.ph.i.i + %__first.addr.02.i.i = phi i32* [ %begin, %for.body.lr.ph.i.i ], [ %ptrincdec.i.i, %for.body.i.i ] +; CHECK: %__first.addr.02.i.i +; CHECK-NEXT: --> {%begin,+,4}<%for.body.i.i> + store i32 0, i32* %__first.addr.02.i.i, align 4 + %ptrincdec.i.i = getelementptr inbounds i32* %__first.addr.02.i.i, i64 1 +; CHECK: %ptrincdec.i.i +; CHECK-NEXT: --> {(4 + %begin),+,4}<%for.body.i.i> + %cmp.i.i = icmp eq i32* %ptrincdec.i.i, %end + br i1 %cmp.i.i, label %for.cond.for.end_crit_edge.i.i, label %for.body.i.i + +for.cond.for.end_crit_edge.i.i: ; preds = %for.body.i.i + br label %_ZSt4fillIPiiEvT_S1_RKT0_.exit + +_ZSt4fillIPiiEvT_S1_RKT0_.exit: ; preds = %entry, %for.cond.for.end_crit_edge.i.i + ret void +} + +; Various checks for inbounds geps. +define void @test3(i32* %begin, i32* %end) nounwind ssp { +entry: + %cmp7.i.i = icmp eq i32* %begin, %end + br i1 %cmp7.i.i, label %_ZSt4fillIPiiEvT_S1_RKT0_.exit, label %for.body.i.i + +for.body.i.i: ; preds = %entry, %for.body.i.i + %indvar.i.i = phi i64 [ %tmp, %for.body.i.i ], [ 0, %entry ] +; CHECK: %indvar.i.i +; CHECK: {0,+,1}<%for.body.i.i> + %tmp = add nsw i64 %indvar.i.i, 1 +; CHECK: %tmp = +; CHECK: {1,+,1}<%for.body.i.i> + %ptrincdec.i.i = getelementptr inbounds i32* %begin, i64 %tmp +; CHECK: %ptrincdec.i.i = +; CHECK: {(4 + %begin),+,4}<%for.body.i.i> + %__first.addr.08.i.i = getelementptr inbounds i32* %begin, i64 %indvar.i.i +; CHECK: %__first.addr.08.i.i +; CHECK: {%begin,+,4}<%for.body.i.i> + store i32 0, i32* %__first.addr.08.i.i, align 4 + %cmp.i.i = icmp eq i32* %ptrincdec.i.i, %end + br i1 %cmp.i.i, label %_ZSt4fillIPiiEvT_S1_RKT0_.exit, label %for.body.i.i +; CHECK: Loop %for.body.i.i: Unpredictable backedge-taken count. +; CHECK: Loop %for.body.i.i: Unpredictable max backedge-taken count. +_ZSt4fillIPiiEvT_S1_RKT0_.exit: ; preds = %for.body.i.i, %entry + ret void +} \ No newline at end of file diff --git a/final/test/Analysis/ScalarEvolution/pointer-sign-bits.ll b/final/test/Analysis/ScalarEvolution/pointer-sign-bits.ll new file mode 100644 index 00000000000..b2cec2d9fc8 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/pointer-sign-bits.ll @@ -0,0 +1,220 @@ +; RUN: opt < %s -analyze -scalar-evolution + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" + %JavaObject = type { [0 x i32 (...)*]*, i8* } + +define void @JnJVM_antlr_CSharpCodeGenerator_genBitSet__Lantlr_collections_impl_BitSet_2I(%JavaObject*, %JavaObject*, i32) { +start: + br i1 undef, label %"stack overflow", label %"no stack overflow" + +"GOTO or IF*2": ; preds = %"true verifyAndComputePtr89", %verifyNullCont84 + unreachable + +"GOTO or IF*5": ; preds = %"true verifyAndComputePtr127", %"GOTO or IF*6" + unreachable + +"GOTO or IF*6": ; preds = %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge", %"true verifyAndComputePtr89" + %indvar = phi i32 [ %indvar.next, %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge" ], [ 0, %"true verifyAndComputePtr89" ] ; [#uses=2] + %.0.in = add i32 %indvar, 0 ; [#uses=1] + %.0 = add i32 %.0.in, 1 ; [#uses=1] + %3 = icmp slt i32 %.0, %4 ; [#uses=1] + br i1 %3, label %verifyNullCont126, label %"GOTO or IF*5" + +end: ; preds = %"no exception block35" + ret void + +"stack overflow": ; preds = %start + ret void + +"no stack overflow": ; preds = %start + br i1 undef, label %verifyNullCont, label %"no stack overflow.end_crit_edge" + +"no stack overflow.end_crit_edge": ; preds = %"no stack overflow" + ret void + +verifyNullCont: ; preds = %"no stack overflow" + br i1 undef, label %verifyNullCont9, label %verifyNullCont.end_crit_edge + +verifyNullCont.end_crit_edge: ; preds = %verifyNullCont + ret void + +verifyNullCont9: ; preds = %verifyNullCont + br i1 undef, label %verifyNullCont12, label %verifyNullCont9.end_crit_edge + +verifyNullCont9.end_crit_edge: ; preds = %verifyNullCont9 + ret void + +verifyNullCont12: ; preds = %verifyNullCont9 + br i1 undef, label %"no exception block13", label %verifyNullCont12.end_crit_edge + +verifyNullCont12.end_crit_edge: ; preds = %verifyNullCont12 + ret void + +"no exception block13": ; preds = %verifyNullCont12 + br i1 undef, label %verifyNullExit14, label %verifyNullCont15 + +verifyNullExit14: ; preds = %"no exception block13" + ret void + +verifyNullCont15: ; preds = %"no exception block13" + br i1 undef, label %"no exception block16", label %verifyNullCont15.end_crit_edge + +verifyNullCont15.end_crit_edge: ; preds = %verifyNullCont15 + ret void + +"no exception block16": ; preds = %verifyNullCont15 + br i1 undef, label %verifyNullExit17, label %verifyNullCont18 + +verifyNullExit17: ; preds = %"no exception block16" + ret void + +verifyNullCont18: ; preds = %"no exception block16" + br i1 undef, label %"no exception block19", label %verifyNullCont18.end_crit_edge + +verifyNullCont18.end_crit_edge: ; preds = %verifyNullCont18 + ret void + +"no exception block19": ; preds = %verifyNullCont18 + br i1 undef, label %verifyNullExit20, label %verifyNullCont21 + +verifyNullExit20: ; preds = %"no exception block19" + ret void + +verifyNullCont21: ; preds = %"no exception block19" + br i1 undef, label %verifyNullCont24, label %verifyNullCont21.end_crit_edge + +verifyNullCont21.end_crit_edge: ; preds = %verifyNullCont21 + ret void + +verifyNullCont24: ; preds = %verifyNullCont21 + br i1 undef, label %verifyNullCont27, label %verifyNullCont24.end_crit_edge + +verifyNullCont24.end_crit_edge: ; preds = %verifyNullCont24 + ret void + +verifyNullCont27: ; preds = %verifyNullCont24 + br i1 undef, label %verifyNullCont32, label %verifyNullCont27.end_crit_edge + +verifyNullCont27.end_crit_edge: ; preds = %verifyNullCont27 + ret void + +verifyNullCont32: ; preds = %verifyNullCont27 + br i1 undef, label %verifyNullExit33, label %verifyNullCont34 + +verifyNullExit33: ; preds = %verifyNullCont32 + ret void + +verifyNullCont34: ; preds = %verifyNullCont32 + br i1 undef, label %"no exception block35", label %verifyNullCont34.end_crit_edge + +verifyNullCont34.end_crit_edge: ; preds = %verifyNullCont34 + ret void + +"no exception block35": ; preds = %verifyNullCont34 + br i1 undef, label %end, label %verifyNullCont60 + +verifyNullCont60: ; preds = %"no exception block35" + br i1 undef, label %verifyNullCont63, label %verifyNullCont60.end_crit_edge + +verifyNullCont60.end_crit_edge: ; preds = %verifyNullCont60 + ret void + +verifyNullCont63: ; preds = %verifyNullCont60 + br i1 undef, label %"no exception block64", label %verifyNullCont63.end_crit_edge + +verifyNullCont63.end_crit_edge: ; preds = %verifyNullCont63 + ret void + +"no exception block64": ; preds = %verifyNullCont63 + br i1 undef, label %verifyNullExit65, label %verifyNullCont66 + +verifyNullExit65: ; preds = %"no exception block64" + ret void + +verifyNullCont66: ; preds = %"no exception block64" + br i1 undef, label %"no exception block67", label %verifyNullCont66.end_crit_edge + +verifyNullCont66.end_crit_edge: ; preds = %verifyNullCont66 + ret void + +"no exception block67": ; preds = %verifyNullCont66 + br i1 undef, label %verifyNullExit68, label %verifyNullCont69 + +verifyNullExit68: ; preds = %"no exception block67" + ret void + +verifyNullCont69: ; preds = %"no exception block67" + br i1 undef, label %"no exception block70", label %verifyNullCont69.end_crit_edge + +verifyNullCont69.end_crit_edge: ; preds = %verifyNullCont69 + ret void + +"no exception block70": ; preds = %verifyNullCont69 + br i1 undef, label %verifyNullExit71, label %verifyNullCont72 + +verifyNullExit71: ; preds = %"no exception block70" + ret void + +verifyNullCont72: ; preds = %"no exception block70" + br i1 undef, label %verifyNullCont75, label %verifyNullCont72.end_crit_edge + +verifyNullCont72.end_crit_edge: ; preds = %verifyNullCont72 + ret void + +verifyNullCont75: ; preds = %verifyNullCont72 + br i1 undef, label %verifyNullCont78, label %verifyNullCont75.end_crit_edge + +verifyNullCont75.end_crit_edge: ; preds = %verifyNullCont75 + ret void + +verifyNullCont78: ; preds = %verifyNullCont75 + br i1 undef, label %"verifyNullCont78.GOTO or IF*4_crit_edge", label %verifyNullCont78.end_crit_edge + +"verifyNullCont78.GOTO or IF*4_crit_edge": ; preds = %verifyNullCont78 + br i1 undef, label %verifyNullExit80, label %verifyNullCont81 + +verifyNullCont78.end_crit_edge: ; preds = %verifyNullCont78 + ret void + +verifyNullExit80: ; preds = %"verifyNullCont78.GOTO or IF*4_crit_edge" + ret void + +verifyNullCont81: ; preds = %"verifyNullCont78.GOTO or IF*4_crit_edge" + %4 = ptrtoint i8* undef to i32 ; [#uses=2] + %5 = icmp slt i32 0, %4 ; [#uses=1] + br i1 %5, label %verifyNullCont84, label %verifyNullCont172 + +verifyNullCont84: ; preds = %verifyNullCont81 + br i1 undef, label %"GOTO or IF*2", label %verifyNullCont86 + +verifyNullCont86: ; preds = %verifyNullCont84 + br i1 undef, label %"true verifyAndComputePtr", label %"false verifyAndComputePtr" + +"true verifyAndComputePtr": ; preds = %verifyNullCont86 + br i1 undef, label %"true verifyAndComputePtr89", label %"false verifyAndComputePtr90" + +"false verifyAndComputePtr": ; preds = %verifyNullCont86 + ret void + +"true verifyAndComputePtr89": ; preds = %"true verifyAndComputePtr" + br i1 undef, label %"GOTO or IF*6", label %"GOTO or IF*2" + +"false verifyAndComputePtr90": ; preds = %"true verifyAndComputePtr" + ret void + +verifyNullCont126: ; preds = %"GOTO or IF*6" + br i1 undef, label %"true verifyAndComputePtr127", label %"false verifyAndComputePtr128" + +"true verifyAndComputePtr127": ; preds = %verifyNullCont126 + br i1 undef, label %"true verifyAndComputePtr131.GOTO or IF*6_crit_edge", label %"GOTO or IF*5" + +"false verifyAndComputePtr128": ; preds = %verifyNullCont126 + ret void + +"true verifyAndComputePtr131.GOTO or IF*6_crit_edge": ; preds = %"true verifyAndComputePtr127" + %indvar.next = add i32 %indvar, 1 ; [#uses=1] + br label %"GOTO or IF*6" + +verifyNullCont172: ; preds = %verifyNullCont81 + unreachable +} diff --git a/final/test/Analysis/ScalarEvolution/pr3909.ll b/final/test/Analysis/ScalarEvolution/pr3909.ll new file mode 100644 index 00000000000..10e328ddf7e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/pr3909.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -indvars -disable-output +; PR 3909 + + + type { i32, %1* } ; type %0 + type { i32, i8* } ; type %1 + +define x86_stdcallcc i32 @_Dmain(%0 %unnamed) { +entry: + br label %whilebody + +whilebody: ; preds = %endwhile5, %entry + %i.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ] ; [#uses=1] + %m.0 = phi i64 [ 0, %entry ], [ %tmp11, %endwhile5 ] ; [#uses=2] + %tmp2 = mul i64 %m.0, %m.0 ; [#uses=1] + br label %whilecond3 + +whilecond3: ; preds = %whilebody4, %whilebody + %j.0 = phi i64 [ %tmp2, %whilebody ], [ %tmp9, %whilebody4 ] ; [#uses=2] + %tmp7 = icmp ne i64 %j.0, 0 ; [#uses=1] + br i1 %tmp7, label %whilebody4, label %endwhile5 + +whilebody4: ; preds = %whilecond3 + %tmp9 = add i64 %j.0, 1 ; [#uses=1] + br label %whilecond3 + +endwhile5: ; preds = %whilecond3 + %tmp11 = add i64 %i.0, 1 ; [#uses=2] + br label %whilebody +} diff --git a/final/test/Analysis/ScalarEvolution/scev-aa.ll b/final/test/Analysis/ScalarEvolution/scev-aa.ll new file mode 100644 index 00000000000..dd5a66ccb44 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/scev-aa.ll @@ -0,0 +1,215 @@ +; RUN: opt < %s -scev-aa -aa-eval -print-all-alias-modref-info \ +; RUN: |& FileCheck %s + +; At the time of this writing, -basicaa misses the example of the form +; A[i+(j+1)] != A[i+j], which can arise from multi-dimensional array references, +; and the example of the form A[0] != A[i+1], where i+1 is known to be positive. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +; p[i] and p[i+1] don't alias. + +; CHECK: Function: loop: 3 pointers, 0 call sites +; CHECK: NoAlias: double* %pi, double* %pi.next + +define void @loop(double* nocapture %p, i64 %n) nounwind { +entry: + %j = icmp sgt i64 %n, 0 + br i1 %j, label %bb, label %return + +bb: + %i = phi i64 [ 0, %entry ], [ %i.next, %bb ] + %pi = getelementptr double* %p, i64 %i + %i.next = add i64 %i, 1 + %pi.next = getelementptr double* %p, i64 %i.next + %x = load double* %pi + %y = load double* %pi.next + %z = fmul double %x, %y + store double %z, double* %pi + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %bb + +return: + ret void +} + +; Slightly more involved: p[j][i], p[j][i+1], and p[j+1][i] don't alias. + +; CHECK: Function: nestedloop: 4 pointers, 0 call sites +; CHECK: NoAlias: double* %pi.j, double* %pi.next.j +; CHECK: NoAlias: double* %pi.j, double* %pi.j.next +; CHECK: NoAlias: double* %pi.j.next, double* %pi.next.j + +define void @nestedloop(double* nocapture %p, i64 %m) nounwind { +entry: + %k = icmp sgt i64 %m, 0 + br i1 %k, label %guard, label %return + +guard: + %l = icmp sgt i64 91, 0 + br i1 %l, label %outer.loop, label %return + +outer.loop: + %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ] + br label %bb + +bb: + %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] + %i.next = add i64 %i, 1 + + %e = add i64 %i, %j + %pi.j = getelementptr double* %p, i64 %e + %f = add i64 %i.next, %j + %pi.next.j = getelementptr double* %p, i64 %f + %x = load double* %pi.j + %y = load double* %pi.next.j + %z = fmul double %x, %y + store double %z, double* %pi.j + + %o = add i64 %j, 91 + %g = add i64 %i, %o + %pi.j.next = getelementptr double* %p, i64 %g + %a = load double* %pi.j.next + %b = fmul double %x, %a + store double %b, double* %pi.j.next + + %exitcond = icmp eq i64 %i.next, 91 + br i1 %exitcond, label %outer.latch, label %bb + +outer.latch: + %j.next = add i64 %j, 91 + %h = icmp eq i64 %j.next, %m + br i1 %h, label %return, label %outer.loop + +return: + ret void +} + +; Even more involved: same as nestedloop, but with a variable extent. +; When n is 1, p[j+1][i] does alias p[j][i+1], and there's no way to +; prove whether n will be greater than 1, so that relation will always +; by MayAlias. The loop is guarded by a n > 0 test though, so +; p[j+1][i] and p[j][i] can theoretically be determined to be NoAlias, +; however the analysis currently doesn't do that. +; TODO: Make the analysis smarter and turn that MayAlias into a NoAlias. + +; CHECK: Function: nestedloop_more: 4 pointers, 0 call sites +; CHECK: NoAlias: double* %pi.j, double* %pi.next.j +; CHECK: MayAlias: double* %pi.j, double* %pi.j.next + +define void @nestedloop_more(double* nocapture %p, i64 %n, i64 %m) nounwind { +entry: + %k = icmp sgt i64 %m, 0 + br i1 %k, label %guard, label %return + +guard: + %l = icmp sgt i64 %n, 0 + br i1 %l, label %outer.loop, label %return + +outer.loop: + %j = phi i64 [ 0, %guard ], [ %j.next, %outer.latch ] + br label %bb + +bb: + %i = phi i64 [ 0, %outer.loop ], [ %i.next, %bb ] + %i.next = add i64 %i, 1 + + %e = add i64 %i, %j + %pi.j = getelementptr double* %p, i64 %e + %f = add i64 %i.next, %j + %pi.next.j = getelementptr double* %p, i64 %f + %x = load double* %pi.j + %y = load double* %pi.next.j + %z = fmul double %x, %y + store double %z, double* %pi.j + + %o = add i64 %j, %n + %g = add i64 %i, %o + %pi.j.next = getelementptr double* %p, i64 %g + %a = load double* %pi.j.next + %b = fmul double %x, %a + store double %b, double* %pi.j.next + + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %outer.latch, label %bb + +outer.latch: + %j.next = add i64 %j, %n + %h = icmp eq i64 %j.next, %m + br i1 %h, label %return, label %outer.loop + +return: + ret void +} + +; ScalarEvolution expands field offsets into constants, which allows it to +; do aggressive analysis. Contrast this with BasicAA, which works by +; recognizing GEP idioms. + +%struct.A = type { %struct.B, i32, i32 } +%struct.B = type { double } + +; CHECK: Function: foo: 7 pointers, 0 call sites +; CHECK: NoAlias: %struct.B* %B, i32* %Z +; CHECK: NoAlias: %struct.B* %B, %struct.B* %C +; CHECK: MustAlias: %struct.B* %C, i32* %Z +; CHECK: NoAlias: %struct.B* %B, i32* %X +; CHECK: MustAlias: i32* %X, i32* %Z +; CHECK: MustAlias: %struct.B* %C, i32* %Y +; CHECK: MustAlias: i32* %X, i32* %Y + +define void @foo() { +entry: + %A = alloca %struct.A + %B = getelementptr %struct.A* %A, i32 0, i32 0 + %Q = bitcast %struct.B* %B to %struct.A* + %Z = getelementptr %struct.A* %Q, i32 0, i32 1 + %C = getelementptr %struct.B* %B, i32 1 + %X = bitcast %struct.B* %C to i32* + %Y = getelementptr %struct.A* %A, i32 0, i32 1 + ret void +} + +; CHECK: Function: bar: 7 pointers, 0 call sites +; CHECK: NoAlias: %struct.B* %N, i32* %P +; CHECK: NoAlias: %struct.B* %N, %struct.B* %R +; CHECK: MustAlias: %struct.B* %R, i32* %P +; CHECK: NoAlias: %struct.B* %N, i32* %W +; CHECK: MustAlias: i32* %P, i32* %W +; CHECK: MustAlias: %struct.B* %R, i32* %V +; CHECK: MustAlias: i32* %V, i32* %W + +define void @bar() { + %M = alloca %struct.A + %N = getelementptr %struct.A* %M, i32 0, i32 0 + %O = bitcast %struct.B* %N to %struct.A* + %P = getelementptr %struct.A* %O, i32 0, i32 1 + %R = getelementptr %struct.B* %N, i32 1 + %W = bitcast %struct.B* %R to i32* + %V = getelementptr %struct.A* %M, i32 0, i32 1 + ret void +} + +; CHECK: Function: nonnegative: 2 pointers, 0 call sites +; CHECK: NoAlias: i64* %arrayidx, i64* %p + +define void @nonnegative(i64* %p) nounwind { +entry: + br label %for.body + +for.body: ; preds = %entry, %for.body + %i = phi i64 [ %inc, %for.body ], [ 0, %entry ] ; [#uses=2] + %inc = add nsw i64 %i, 1 ; [#uses=2] + %arrayidx = getelementptr inbounds i64* %p, i64 %inc + store i64 0, i64* %arrayidx + %tmp6 = load i64* %p ; [#uses=1] + %cmp = icmp slt i64 %inc, %tmp6 ; [#uses=1] + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body, %entry + ret void +} + +; CHECK: 14 no alias responses +; CHECK: 26 may alias responses +; CHECK: 18 must alias responses diff --git a/final/test/Analysis/ScalarEvolution/sext-inreg.ll b/final/test/Analysis/ScalarEvolution/sext-inreg.ll new file mode 100644 index 00000000000..23e1210dba5 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/sext-inreg.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -analyze -scalar-evolution > %t +; RUN: grep {sext i57 \{0,+,199\}<%bb> to i64} %t | count 1 +; RUN: grep {sext i59 \{0,+,199\}<%bb> to i64} %t | count 1 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin9.6" + +define i64 @foo(i64* nocapture %x, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 ; [#uses=1] + br i1 %t0, label %bb, label %return + +bb: ; preds = %bb, %entry + %i.01 = phi i64 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %t1 = shl i64 %i.01, 7 ; [#uses=1] + %t2 = ashr i64 %t1, 7 ; [#uses=1] + %s1 = shl i64 %i.01, 5 ; [#uses=1] + %s2 = ashr i64 %s1, 5 ; [#uses=1] + %t3 = getelementptr i64* %x, i64 %i.01 ; [#uses=1] + store i64 0, i64* %t3, align 1 + %indvar.next = add i64 %i.01, 199 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, %n ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb, %entry + %p = phi i64 [ 0, %entry ], [ %t2, %bb ] + %q = phi i64 [ 0, %entry ], [ %s2, %bb ] + %v = xor i64 %p, %q + ret i64 %v +} diff --git a/final/test/Analysis/ScalarEvolution/sext-iv-0.ll b/final/test/Analysis/ScalarEvolution/sext-iv-0.ll new file mode 100644 index 00000000000..2af794fbbc3 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/sext-iv-0.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep { --> \{-128,+,1\}<%bb1> Exits: 127} | count 5 + +; Convert (sext {-128,+,1}) to {sext(-128),+,sext(1)}, since the +; trip count is within range where this is safe. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/sext-iv-1.ll b/final/test/Analysis/ScalarEvolution/sext-iv-1.ll new file mode 100644 index 00000000000..9063cbb22a7 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/sext-iv-1.ll @@ -0,0 +1,100 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep { --> (sext i. \{.\*,+,.\*\}<%bb1> to i64)} | count 5 + +; Don't convert (sext {...,+,...}) to {sext(...),+,sext(...)} in cases +; where the trip count is not within range. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define void @foo0(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i7 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i7 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo1(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 128 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo2(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -129, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, 1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} + +define void @foo3(double* nocapture %x) nounwind { +bb1.thread: + br label %bb1 + +bb1: ; preds = %bb1, %bb1.thread + %i.0.reg2mem.0 = phi i64 [ -128, %bb1.thread ], [ %8, %bb1 ] ; [#uses=3] + %0 = trunc i64 %i.0.reg2mem.0 to i8 ; [#uses=1] + %1 = trunc i64 %i.0.reg2mem.0 to i9 ; [#uses=1] + %2 = sext i9 %1 to i64 ; [#uses=1] + %3 = getelementptr double* %x, i64 %2 ; [#uses=1] + %4 = load double* %3, align 8 ; [#uses=1] + %5 = fmul double %4, 3.900000e+00 ; [#uses=1] + %6 = sext i8 %0 to i64 ; [#uses=1] + %7 = getelementptr double* %x, i64 %6 ; [#uses=1] + store double %5, double* %7, align 8 + %8 = add i64 %i.0.reg2mem.0, -1 ; [#uses=2] + %9 = icmp sgt i64 %8, 127 ; [#uses=1] + br i1 %9, label %return, label %bb1 + +return: ; preds = %bb1 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/sext-iv-2.ll b/final/test/Analysis/ScalarEvolution/sext-iv-2.ll new file mode 100644 index 00000000000..97e252c1fb3 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/sext-iv-2.ll @@ -0,0 +1,74 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; CHECK: %tmp3 = sext i8 %tmp2 to i32 +; CHECK: --> (sext i8 {0,+,1}<%bb1> to i32) Exits: -1 +; CHECK: %tmp4 = mul i32 %tmp3, %i.02 +; CHECK: --> ((sext i8 {0,+,1}<%bb1> to i32) * {0,+,1}<%bb>) Exits: {0,+,-1}<%bb> + +; These sexts are not foldable. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + +@table = common global [32 x [256 x i32]] zeroinitializer, align 32 ; <[32 x [256 x i32]]*> [#uses=2] + +define i32 @main() nounwind { +entry: + br i1 false, label %bb5, label %bb.nph3 + +bb.nph3: ; preds = %entry + br label %bb + +bb: ; preds = %bb4, %bb.nph3 + %i.02 = phi i32 [ %tmp10, %bb4 ], [ 0, %bb.nph3 ] ; [#uses=3] + br i1 false, label %bb3, label %bb.nph + +bb.nph: ; preds = %bb + br label %bb1 + +bb1: ; preds = %bb2, %bb.nph + %j.01 = phi i32 [ %tmp8, %bb2 ], [ 0, %bb.nph ] ; [#uses=3] + %tmp2 = trunc i32 %j.01 to i8 ; [#uses=1] + %tmp3 = sext i8 %tmp2 to i32 ; [#uses=1] + %tmp4 = mul i32 %tmp3, %i.02 ; [#uses=1] + %tmp5 = sext i32 %i.02 to i64 ; [#uses=1] + %tmp6 = sext i32 %j.01 to i64 ; [#uses=1] + %tmp7 = getelementptr [32 x [256 x i32]]* @table, i64 0, i64 %tmp5, i64 %tmp6 ; [#uses=1] + store i32 %tmp4, i32* %tmp7, align 4 + %tmp8 = add i32 %j.01, 1 ; [#uses=2] + br label %bb2 + +bb2: ; preds = %bb1 + %phitmp1 = icmp sgt i32 %tmp8, 255 ; [#uses=1] + br i1 %phitmp1, label %bb2.bb3_crit_edge, label %bb1 + +bb2.bb3_crit_edge: ; preds = %bb2 + br label %bb3 + +bb3: ; preds = %bb2.bb3_crit_edge, %bb + %tmp10 = add i32 %i.02, 1 ; [#uses=2] + br label %bb4 + +bb4: ; preds = %bb3 + %phitmp = icmp sgt i32 %tmp10, 31 ; [#uses=1] + br i1 %phitmp, label %bb4.bb5_crit_edge, label %bb + +bb4.bb5_crit_edge: ; preds = %bb4 + br label %bb5 + +bb5: ; preds = %bb4.bb5_crit_edge, %entry + %tmp12 = load i32* getelementptr ([32 x [256 x i32]]* @table, i64 0, i64 9, i64 132), align 16 ; [#uses=1] + %tmp13 = icmp eq i32 %tmp12, -1116 ; [#uses=1] + br i1 %tmp13, label %bb7, label %bb6 + +bb6: ; preds = %bb5 + call void @abort() noreturn nounwind + unreachable + +bb7: ; preds = %bb5 + br label %return + +return: ; preds = %bb7 + ret i32 0 +} + +declare void @abort() noreturn nounwind diff --git a/final/test/Analysis/ScalarEvolution/sle.ll b/final/test/Analysis/ScalarEvolution/sle.ll new file mode 100644 index 00000000000..f38f6b63dce --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/sle.ll @@ -0,0 +1,27 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +; ScalarEvolution should be able to use nsw information to prove that +; this loop has a finite trip count. + +; CHECK: @le +; CHECK: Loop %for.body: backedge-taken count is %n +; CHECK: Loop %for.body: max backedge-taken count is 9223372036854775807 + +define void @le(i64 %n, double* nocapture %p) nounwind { +entry: + %cmp6 = icmp slt i64 %n, 0 ; [#uses=1] + br i1 %cmp6, label %for.end, label %for.body + +for.body: ; preds = %for.body, %entry + %i = phi i64 [ %i.next, %for.body ], [ 0, %entry ] ; [#uses=2] + %arrayidx = getelementptr double* %p, i64 %i ; [#uses=2] + %t4 = load double* %arrayidx ; [#uses=1] + %mul = fmul double %t4, 2.200000e+00 ; [#uses=1] + store double %mul, double* %arrayidx + %i.next = add nsw i64 %i, 1 ; [#uses=2] + %cmp = icmp sgt i64 %i.next, %n ; [#uses=1] + br i1 %cmp, label %for.end, label %for.body + +for.end: ; preds = %for.body, %entry + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/smax.ll b/final/test/Analysis/ScalarEvolution/smax.ll new file mode 100644 index 00000000000..15dd744c8fd --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/smax.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -analyze -scalar-evolution | grep smax | count 2 +; RUN: opt < %s -analyze -scalar-evolution | grep \ +; RUN: {%. smax %. smax %.} +; PR1614 + +define i32 @x(i32 %a, i32 %b, i32 %c) { + %A = icmp sgt i32 %a, %b + %B = select i1 %A, i32 %a, i32 %b + %C = icmp sle i32 %c, %B + %D = select i1 %C, i32 %B, i32 %c + ret i32 %D +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count.ll b/final/test/Analysis/ScalarEvolution/trip-count.ll new file mode 100644 index 00000000000..d750d4a1f37 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: -scalar-evolution-max-iterations=0 | grep {backedge-taken count is 10000} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp2 = add i32 %i.0, 1 ; [#uses=1] + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %tmp3 = icmp sle i32 %i.0, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count10.ll b/final/test/Analysis/ScalarEvolution/trip-count10.ll new file mode 100644 index 00000000000..546e1dc7d8f --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count10.ll @@ -0,0 +1,126 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; Trip counts with trivial exit conditions. + +; CHECK: Determining loop execution counts for: @a +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; CHECK: Determining loop execution counts for: @b +; CHECK: Loop %loop: backedge-taken count is false +; CHECK: Loop %loop: max backedge-taken count is false + +; CHECK: Determining loop execution counts for: @c +; CHECK: Loop %loop: backedge-taken count is false +; CHECK: Loop %loop: max backedge-taken count is false + +; CHECK: Determining loop execution counts for: @d +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +define void @a(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 false, label %return, label %loop + +return: + ret void +} +define void @b(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 true, label %return, label %loop + +return: + ret void +} +define void @c(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 false, label %loop, label %return + +return: + ret void +} +define void @d(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 true, label %loop, label %return + +return: + ret void +} + +; Trip counts for non-polynomial iterations. It's theoretically possible +; to compute a maximum count for these, but short of that, ScalarEvolution +; should return unknown. + +; PR7416 +; CHECK: Determining loop execution counts for: @nonpolynomial +; CHECK-NEXT: Loop %loophead: Unpredictable backedge-taken count +; CHECK-NEXT: Loop %loophead: Unpredictable max backedge-taken count + +declare i1 @g() nounwind + +define void @nonpolynomial() { +entry: + br label %loophead +loophead: + %x = phi i32 [0, %entry], [%x.1, %bb1], [%x.2, %bb2] + %y = icmp slt i32 %x, 100 + br i1 %y, label %loopbody, label %retbb +loopbody: + %z = call i1 @g() + br i1 %z, label %bb1, label %bb2 +bb1: + %x.1 = add i32 %x, 2 + br label %loophead +bb2: + %x.2 = add i32 %x, 3 + br label %loophead +retbb: + ret void +} + +; PHI nodes with all constant operands. + +; CHECK: Determining loop execution counts for: @constant_phi_operands +; CHECK: Loop %loop: backedge-taken count is 1 +; CHECK: Loop %loop: max backedge-taken count is 1 + +define void @constant_phi_operands() nounwind { +entry: + br label %loop + +loop: + %i = phi i64 [ 1, %loop ], [ 0, %entry ] + %exitcond = icmp eq i64 %i, 1 + br i1 %exitcond, label %return, label %loop + +return: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count2.ll b/final/test/Analysis/ScalarEvolution/trip-count2.ll new file mode 100644 index 00000000000..79f31619fd8 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count2.ll @@ -0,0 +1,35 @@ +; RUN: opt < %s -analyze -scalar-evolution | \ +; RUN: grep {backedge-taken count is 4} +; PR1101 + +@A = weak global [1000 x i32] zeroinitializer, align 32 + + +define void @test(i32 %N) { +entry: + "alloca point" = bitcast i32 0 to i32 ; [#uses=0] + br label %bb3 + +bb: ; preds = %bb3 + %tmp = getelementptr [1000 x i32]* @A, i32 0, i32 %i.0 ; [#uses=1] + store i32 123, i32* %tmp + %tmp4 = mul i32 %i.0, 4 ; [#uses=1] + %tmp5 = or i32 %tmp4, 1 + %tmp61 = xor i32 %tmp5, -2147483648 + %tmp6 = trunc i32 %tmp61 to i16 + %tmp71 = shl i16 %tmp6, 2 + %tmp7 = zext i16 %tmp71 to i32 + %tmp2 = add i32 %tmp7, %i.0 + br label %bb3 + +bb3: ; preds = %bb, %entry + %i.0 = phi i32 [ 0, %entry ], [ %tmp2, %bb ] ; [#uses=3] + %tmp3 = icmp sle i32 %i.0, 9999 ; [#uses=1] + br i1 %tmp3, label %bb, label %bb5 + +bb5: ; preds = %bb3 + br label %return + +return: ; preds = %bb5 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count3.ll b/final/test/Analysis/ScalarEvolution/trip-count3.ll new file mode 100644 index 00000000000..10b798b5067 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count3.ll @@ -0,0 +1,78 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep {Loop %bb3\\.i: Unpredictable backedge-taken count\\.} + +; ScalarEvolution can't compute a trip count because it doesn't know if +; dividing by the stride will have a remainder. This could theoretically +; be teaching it how to use a more elaborate trip count computation. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + %struct.FILE = type { i32, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, %struct._IO_marker*, %struct.FILE*, i32, i32, i64, i16, i8, [1 x i8], i8*, i64, i8*, i8*, i8*, i8*, i64, i32, [20 x i8] } + %struct.SHA_INFO = type { [5 x i32], i32, i32, [16 x i32] } + %struct._IO_marker = type { %struct._IO_marker*, %struct.FILE*, i32 } +@_2E_str = external constant [26 x i8] ; <[26 x i8]*> [#uses=0] +@stdin = external global %struct.FILE* ; <%struct.FILE**> [#uses=0] +@_2E_str1 = external constant [3 x i8] ; <[3 x i8]*> [#uses=0] +@_2E_str12 = external constant [30 x i8] ; <[30 x i8]*> [#uses=0] + +declare void @sha_init(%struct.SHA_INFO* nocapture) nounwind + +declare fastcc void @sha_transform(%struct.SHA_INFO* nocapture) nounwind + +declare void @sha_print(%struct.SHA_INFO* nocapture) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind + +declare void @sha_final(%struct.SHA_INFO* nocapture) nounwind + +declare void @llvm.memset.i64(i8* nocapture, i8, i64, i32) nounwind + +declare void @sha_update(%struct.SHA_INFO* nocapture, i8* nocapture, i32) nounwind + +declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind + +declare i64 @fread(i8* noalias nocapture, i64, i64, %struct.FILE* noalias nocapture) nounwind + +declare i32 @main(i32, i8** nocapture) nounwind + +declare noalias %struct.FILE* @fopen(i8* noalias nocapture, i8* noalias nocapture) nounwind + +declare i32 @fclose(%struct.FILE* nocapture) nounwind + +declare void @sha_stream(%struct.SHA_INFO* nocapture, %struct.FILE* nocapture) nounwind + +define void @sha_stream_bb3_2E_i(%struct.SHA_INFO* %sha_info, i8* %data1, i32, i8** %buffer_addr.0.i.out, i32* %count_addr.0.i.out) nounwind { +newFuncRoot: + br label %bb3.i + +sha_update.exit.exitStub: ; preds = %bb3.i + store i8* %buffer_addr.0.i, i8** %buffer_addr.0.i.out + store i32 %count_addr.0.i, i32* %count_addr.0.i.out + ret void + +bb2.i: ; preds = %bb3.i + %1 = getelementptr %struct.SHA_INFO* %sha_info, i64 0, i32 3 ; <[16 x i32]*> [#uses=1] + %2 = bitcast [16 x i32]* %1 to i8* ; [#uses=1] + call void @llvm.memcpy.i64(i8* %2, i8* %buffer_addr.0.i, i64 64, i32 1) nounwind + %3 = getelementptr %struct.SHA_INFO* %sha_info, i64 0, i32 3, i64 0 ; [#uses=1] + %4 = bitcast i32* %3 to i8* ; [#uses=1] + br label %codeRepl + +codeRepl: ; preds = %bb2.i + call void @sha_stream_bb3_2E_i_bb1_2E_i_2E_i(i8* %4) + br label %byte_reverse.exit.i + +byte_reverse.exit.i: ; preds = %codeRepl + call fastcc void @sha_transform(%struct.SHA_INFO* %sha_info) nounwind + %5 = getelementptr i8* %buffer_addr.0.i, i64 64 ; [#uses=1] + %6 = add i32 %count_addr.0.i, -64 ; [#uses=1] + br label %bb3.i + +bb3.i: ; preds = %byte_reverse.exit.i, %newFuncRoot + %buffer_addr.0.i = phi i8* [ %data1, %newFuncRoot ], [ %5, %byte_reverse.exit.i ] ; [#uses=3] + %count_addr.0.i = phi i32 [ %0, %newFuncRoot ], [ %6, %byte_reverse.exit.i ] ; [#uses=3] + %7 = icmp sgt i32 %count_addr.0.i, 63 ; [#uses=1] + br i1 %7, label %bb2.i, label %sha_update.exit.exitStub +} + +declare void @sha_stream_bb3_2E_i_bb1_2E_i_2E_i(i8*) nounwind diff --git a/final/test/Analysis/ScalarEvolution/trip-count4.ll b/final/test/Analysis/ScalarEvolution/trip-count4.ll new file mode 100644 index 00000000000..116f62dbdbf --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count4.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | grep {sext.*trunc.*Exits: 11} + +; ScalarEvolution should be able to compute a loop exit value for %indvar.i8. + +define void @another_count_down_signed(double* %d, i64 %n) nounwind { +entry: + br label %loop + +loop: ; preds = %loop, %entry + %indvar = phi i64 [ %n, %entry ], [ %indvar.next, %loop ] ; [#uses=4] + %s0 = shl i64 %indvar, 8 ; [#uses=1] + %indvar.i8 = ashr i64 %s0, 8 ; [#uses=1] + %t0 = getelementptr double* %d, i64 %indvar.i8 ; [#uses=2] + %t1 = load double* %t0 ; [#uses=1] + %t2 = fmul double %t1, 1.000000e-01 ; [#uses=1] + store double %t2, double* %t0 + %indvar.next = sub i64 %indvar, 1 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next, 10 ; [#uses=1] + br i1 %exitcond, label %return, label %loop + +return: ; preds = %loop + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count5.ll b/final/test/Analysis/ScalarEvolution/trip-count5.ll new file mode 100644 index 00000000000..1194a1da66e --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count5.ll @@ -0,0 +1,48 @@ +; RUN: opt < %s -analyze -scalar-evolution > %t +; RUN: grep sext %t | count 2 +; RUN: not grep {(sext} %t + +; ScalarEvolution should be able to compute a maximum trip count +; value sufficient to fold away both sext casts. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define float @t(float* %pTmp1, float* %peakWeight, float* %nrgReducePeakrate, i32 %bim) nounwind { +entry: + %tmp3 = load float* %peakWeight, align 4 ; [#uses=2] + %tmp2538 = icmp sgt i32 %bim, 0 ; [#uses=1] + br i1 %tmp2538, label %bb.nph, label %bb4 + +bb.nph: ; preds = %entry + br label %bb + +bb: ; preds = %bb1, %bb.nph + %distERBhi.036 = phi float [ %tmp10, %bb1 ], [ 0.000000e+00, %bb.nph ] ; [#uses=1] + %hiPart.035 = phi i32 [ %tmp12, %bb1 ], [ 0, %bb.nph ] ; [#uses=2] + %peakCount.034 = phi float [ %tmp19, %bb1 ], [ %tmp3, %bb.nph ] ; [#uses=1] + %tmp6 = sext i32 %hiPart.035 to i64 ; [#uses=1] + %tmp7 = getelementptr float* %pTmp1, i64 %tmp6 ; [#uses=1] + %tmp8 = load float* %tmp7, align 4 ; [#uses=1] + %tmp10 = fadd float %tmp8, %distERBhi.036 ; [#uses=3] + %tmp12 = add i32 %hiPart.035, 1 ; [#uses=3] + %tmp15 = sext i32 %tmp12 to i64 ; [#uses=1] + %tmp16 = getelementptr float* %peakWeight, i64 %tmp15 ; [#uses=1] + %tmp17 = load float* %tmp16, align 4 ; [#uses=1] + %tmp19 = fadd float %tmp17, %peakCount.034 ; [#uses=2] + br label %bb1 + +bb1: ; preds = %bb + %tmp21 = fcmp olt float %tmp10, 2.500000e+00 ; [#uses=1] + %tmp25 = icmp slt i32 %tmp12, %bim ; [#uses=1] + %tmp27 = and i1 %tmp21, %tmp25 ; [#uses=1] + br i1 %tmp27, label %bb, label %bb1.bb4_crit_edge + +bb1.bb4_crit_edge: ; preds = %bb1 + br label %bb4 + +bb4: ; preds = %bb1.bb4_crit_edge, %entry + %distERBhi.0.lcssa = phi float [ %tmp10, %bb1.bb4_crit_edge ], [ 0.000000e+00, %entry ] ; [#uses=1] + %peakCount.0.lcssa = phi float [ %tmp19, %bb1.bb4_crit_edge ], [ %tmp3, %entry ] ; [#uses=1] + %tmp31 = fdiv float %peakCount.0.lcssa, %distERBhi.0.lcssa ; [#uses=1] + ret float %tmp31 +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count6.ll b/final/test/Analysis/ScalarEvolution/trip-count6.ll new file mode 100644 index 00000000000..956fb81b0ed --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count6.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | grep {max backedge-taken count is 1\$} + +@mode_table = global [4 x i32] zeroinitializer ; <[4 x i32]*> [#uses=1] + +define i8 @f() { +entry: + tail call i32 @fegetround( ) ; :0 [#uses=1] + br label %bb + +bb: ; preds = %bb4, %entry + %mode.0 = phi i8 [ 0, %entry ], [ %indvar.next, %bb4 ] ; [#uses=4] + zext i8 %mode.0 to i32 ; :1 [#uses=1] + getelementptr [4 x i32]* @mode_table, i32 0, i32 %1 ; :2 [#uses=1] + load i32* %2, align 4 ; :3 [#uses=1] + icmp eq i32 %3, %0 ; :4 [#uses=1] + br i1 %4, label %bb1, label %bb2 + +bb1: ; preds = %bb + ret i8 %mode.0 + +bb2: ; preds = %bb + icmp eq i8 %mode.0, 1 ; :5 [#uses=1] + br i1 %5, label %bb5, label %bb4 + +bb4: ; preds = %bb2 + %indvar.next = add i8 %mode.0, 1 ; [#uses=1] + br label %bb + +bb5: ; preds = %bb2 + tail call void @raise_exception( ) noreturn + unreachable +} + +declare i32 @fegetround() + +declare void @raise_exception() noreturn diff --git a/final/test/Analysis/ScalarEvolution/trip-count7.ll b/final/test/Analysis/ScalarEvolution/trip-count7.ll new file mode 100644 index 00000000000..a8b797e142f --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count7.ll @@ -0,0 +1,150 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | grep {Loop %bb7.i: Unpredictable backedge-taken count\\.} + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + + %struct.complex = type { float, float } + %struct.element = type { i32, i32 } + %struct.node = type { %struct.node*, %struct.node*, i32 } +@seed = external global i64 ; [#uses=0] +@_2E_str = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0] +@_2E_str1 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0] +@value = external global float ; [#uses=0] +@fixed = external global float ; [#uses=0] +@floated = external global float ; [#uses=0] +@permarray = external global [11 x i32], align 32 ; <[11 x i32]*> [#uses=0] +@pctr = external global i32 ; [#uses=0] +@tree = external global %struct.node* ; <%struct.node**> [#uses=0] +@stack = external global [4 x i32], align 16 ; <[4 x i32]*> [#uses=0] +@cellspace = external global [19 x %struct.element], align 32 ; <[19 x %struct.element]*> [#uses=0] +@freelist = external global i32 ; [#uses=0] +@movesdone = external global i32 ; [#uses=0] +@ima = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@imb = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@imr = external global [41 x [41 x i32]], align 32 ; <[41 x [41 x i32]]*> [#uses=0] +@rma = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@rmb = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@rmr = external global [41 x [41 x float]], align 32 ; <[41 x [41 x float]]*> [#uses=0] +@piececount = external global [4 x i32], align 16 ; <[4 x i32]*> [#uses=0] +@class = external global [13 x i32], align 32 ; <[13 x i32]*> [#uses=0] +@piecemax = external global [13 x i32], align 32 ; <[13 x i32]*> [#uses=0] +@puzzl = external global [512 x i32], align 32 ; <[512 x i32]*> [#uses=0] +@p = external global [13 x [512 x i32]], align 32 ; <[13 x [512 x i32]]*> [#uses=0] +@n = external global i32 ; [#uses=0] +@kount = external global i32 ; [#uses=0] +@sortlist = external global [5001 x i32], align 32 ; <[5001 x i32]*> [#uses=0] +@biggest = external global i32 ; [#uses=0] +@littlest = external global i32 ; [#uses=0] +@top = external global i32 ; [#uses=0] +@z = external global [257 x %struct.complex], align 32 ; <[257 x %struct.complex]*> [#uses=0] +@w = external global [257 x %struct.complex], align 32 ; <[257 x %struct.complex]*> [#uses=0] +@e = external global [130 x %struct.complex], align 32 ; <[130 x %struct.complex]*> [#uses=0] +@zr = external global float ; [#uses=0] +@zi = external global float ; [#uses=0] + +declare void @Initrand() nounwind + +declare i32 @Rand() nounwind + +declare void @Try(i32, i32*, i32*, i32*, i32*, i32*) nounwind + +declare i32 @puts(i8* nocapture) nounwind + +declare void @Queens(i32) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind + +declare i32 @main() nounwind + +declare void @Doit() nounwind + +declare void @Doit_bb7([15 x i32]*, [17 x i32]*, [9 x i32]*) nounwind + +define void @Doit_bb7_2E_i([9 x i32]* %x1, [15 x i32]* %c, [17 x i32]* %b, [9 x i32]* %a, i32* %q, i32* %x1.sub, i32* %b9, i32* %a10, i32* %c11) nounwind { +newFuncRoot: + br label %bb7.i + +Try.exit.exitStub: ; preds = %bb7.i + ret void + +bb.i: ; preds = %bb7.i + %tmp = add i32 %j.0.i, 1 ; [#uses=5] + store i32 0, i32* %q, align 4 + %tmp1 = sext i32 %tmp to i64 ; [#uses=1] + %tmp2 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp1 ; [#uses=1] + %tmp3 = load i32* %tmp2, align 4 ; [#uses=1] + %tmp4 = icmp eq i32 %tmp3, 0 ; [#uses=1] + br i1 %tmp4, label %bb.i.bb7.i.backedge_crit_edge, label %bb1.i + +bb1.i: ; preds = %bb.i + %tmp5 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp6 = sext i32 %tmp5 to i64 ; [#uses=1] + %tmp7 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp6 ; [#uses=1] + %tmp8 = load i32* %tmp7, align 4 ; [#uses=1] + %tmp9 = icmp eq i32 %tmp8, 0 ; [#uses=1] + br i1 %tmp9, label %bb1.i.bb7.i.backedge_crit_edge, label %bb2.i + +bb2.i: ; preds = %bb1.i + %tmp10 = sub i32 7, %j.0.i ; [#uses=1] + %tmp11 = sext i32 %tmp10 to i64 ; [#uses=1] + %tmp12 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp11 ; [#uses=1] + %tmp13 = load i32* %tmp12, align 4 ; [#uses=1] + %tmp14 = icmp eq i32 %tmp13, 0 ; [#uses=1] + br i1 %tmp14, label %bb2.i.bb7.i.backedge_crit_edge, label %bb3.i + +bb3.i: ; preds = %bb2.i + %tmp15 = getelementptr [9 x i32]* %x1, i64 0, i64 1 ; [#uses=1] + store i32 %tmp, i32* %tmp15, align 4 + %tmp16 = sext i32 %tmp to i64 ; [#uses=1] + %tmp17 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp16 ; [#uses=1] + store i32 0, i32* %tmp17, align 4 + %tmp18 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp19 = sext i32 %tmp18 to i64 ; [#uses=1] + %tmp20 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp19 ; [#uses=1] + store i32 0, i32* %tmp20, align 4 + %tmp21 = sub i32 7, %j.0.i ; [#uses=1] + %tmp22 = sext i32 %tmp21 to i64 ; [#uses=1] + %tmp23 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp22 ; [#uses=1] + store i32 0, i32* %tmp23, align 4 + call void @Try(i32 2, i32* %q, i32* %b9, i32* %a10, i32* %c11, i32* %x1.sub) nounwind + %tmp24 = load i32* %q, align 4 ; [#uses=1] + %tmp25 = icmp eq i32 %tmp24, 0 ; [#uses=1] + br i1 %tmp25, label %bb5.i, label %bb3.i.bb7.i.backedge_crit_edge + +bb5.i: ; preds = %bb3.i + %tmp26 = sext i32 %tmp to i64 ; [#uses=1] + %tmp27 = getelementptr [9 x i32]* %a, i64 0, i64 %tmp26 ; [#uses=1] + store i32 1, i32* %tmp27, align 4 + %tmp28 = add i32 %j.0.i, 2 ; [#uses=1] + %tmp29 = sext i32 %tmp28 to i64 ; [#uses=1] + %tmp30 = getelementptr [17 x i32]* %b, i64 0, i64 %tmp29 ; [#uses=1] + store i32 1, i32* %tmp30, align 4 + %tmp31 = sub i32 7, %j.0.i ; [#uses=1] + %tmp32 = sext i32 %tmp31 to i64 ; [#uses=1] + %tmp33 = getelementptr [15 x i32]* %c, i64 0, i64 %tmp32 ; [#uses=1] + store i32 1, i32* %tmp33, align 4 + br label %bb7.i.backedge + +bb7.i.backedge: ; preds = %bb3.i.bb7.i.backedge_crit_edge, %bb2.i.bb7.i.backedge_crit_edge, %bb1.i.bb7.i.backedge_crit_edge, %bb.i.bb7.i.backedge_crit_edge, %bb5.i + br label %bb7.i + +bb7.i: ; preds = %bb7.i.backedge, %newFuncRoot + %j.0.i = phi i32 [ 0, %newFuncRoot ], [ %tmp, %bb7.i.backedge ] ; [#uses=8] + %tmp34 = load i32* %q, align 4 ; [#uses=1] + %tmp35 = icmp eq i32 %tmp34, 0 ; [#uses=1] + %tmp36 = icmp ne i32 %j.0.i, 8 ; [#uses=1] + %tmp37 = and i1 %tmp35, %tmp36 ; [#uses=1] + br i1 %tmp37, label %bb.i, label %Try.exit.exitStub + +bb.i.bb7.i.backedge_crit_edge: ; preds = %bb.i + br label %bb7.i.backedge + +bb1.i.bb7.i.backedge_crit_edge: ; preds = %bb1.i + br label %bb7.i.backedge + +bb2.i.bb7.i.backedge_crit_edge: ; preds = %bb2.i + br label %bb7.i.backedge + +bb3.i.bb7.i.backedge_crit_edge: ; preds = %bb3.i + br label %bb7.i.backedge +} diff --git a/final/test/Analysis/ScalarEvolution/trip-count8.ll b/final/test/Analysis/ScalarEvolution/trip-count8.ll new file mode 100644 index 00000000000..ac5ee607ec4 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count8.ll @@ -0,0 +1,37 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | grep {Loop %for\\.body: backedge-taken count is (-1 + \[%\]ecx)} +; PR4599 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" + +define i32 @foo(i32 %ecx) nounwind { +entry: + %cmp2 = icmp eq i32 %ecx, 0 ; [#uses=1] + br i1 %cmp2, label %for.end, label %bb.nph + +for.cond: ; preds = %for.inc + %cmp = icmp ult i32 %inc, %ecx ; [#uses=1] + br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge + +for.cond.for.end_crit_edge: ; preds = %for.cond + %phitmp = add i32 %i.01, 2 ; [#uses=1] + br label %for.end + +bb.nph: ; preds = %entry + br label %for.body + +for.body: ; preds = %bb.nph, %for.cond + %i.01 = phi i32 [ %inc, %for.cond ], [ 0, %bb.nph ] ; [#uses=3] + %call = call i32 @bar(i32 %i.01) nounwind ; [#uses=0] + br label %for.inc + +for.inc: ; preds = %for.body + %inc = add i32 %i.01, 1 ; [#uses=2] + br label %for.cond + +for.end: ; preds = %for.cond.for.end_crit_edge, %entry + %i.0.lcssa = phi i32 [ %phitmp, %for.cond.for.end_crit_edge ], [ 1, %entry ] ; [#uses=1] + ret i32 %i.0.lcssa +} + +declare i32 @bar(i32) diff --git a/final/test/Analysis/ScalarEvolution/trip-count9.ll b/final/test/Analysis/ScalarEvolution/trip-count9.ll new file mode 100644 index 00000000000..9180f2b8dd7 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/trip-count9.ll @@ -0,0 +1,408 @@ +; RUN: opt -analyze -scalar-evolution -S < %s | FileCheck %s + +; Every combination of +; - starting at 0, 1, or %x +; - steping by 1 or 2 +; - stopping at %n or %n*2 +; - using nsw, or not + +; Some of these represent missed opportunities. + +; CHECK: Determining loop execution counts for: @foo +; CHECK: Loop %loop: backedge-taken count is (-1 + %n) +; CHECK: Loop %loop: max backedge-taken count is 6 +define void @foo(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @step2(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @start1 +; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax %n)) +; CHECK: Loop %loop: max backedge-taken count is 5 +define void @start1(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @start1_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @start1_step2(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @startx +; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n)) +; CHECK: Loop %loop: max backedge-taken count is -1 +define void @startx(i4 %n, i4 %x) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @startx_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @startx_step2(i4 %n, i4 %x) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @nsw +; CHECK: Loop %loop: backedge-taken count is (-1 + %n) +; CHECK: Loop %loop: max backedge-taken count is 6 +define void @nsw(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; Be careful with this one. If %n is INT4_MAX, %i.next will wrap. The nsw bit +; says that the result is undefined, but ScalarEvolution must respect that +; subsequent passes may result the undefined behavior in predictable ways. +; CHECK: Determining loop execution counts for: @nsw_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @nsw_step2(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @nsw_start1 +; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax %n)) +; CHECK: Loop %loop: max backedge-taken count is 5 +define void @nsw_start1(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @nsw_start1_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @nsw_start1_step2(i4 %n) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @nsw_startx +; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n)) +; CHECK: Loop %loop: max backedge-taken count is -1 +define void @nsw_startx(i4 %n, i4 %x) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @nsw_startx_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. +define void @nsw_startx_step2(i4 %n, i4 %x) { +entry: + %s = icmp sgt i4 %n, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %n + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even +; CHECK: Loop %loop: backedge-taken count is (-1 + (2 * %n)) +; CHECK: Loop %loop: max backedge-taken count is 5 +define void @even(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: max backedge-taken count is 2 +define void @even_step2(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_start1 +; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax (2 * %n))) +; CHECK: Loop %loop: max backedge-taken count is 4 +define void @even_start1(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_start1_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: max backedge-taken count is 2 +define void @even_start1_step2(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_startx +; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n))) +; CHECK: Loop %loop: max backedge-taken count is -1 +define void @even_startx(i4 %n, i4 %x) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_startx_step2 +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: max backedge-taken count is 7 +define void @even_startx_step2(i4 %n, i4 %x) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw +; CHECK: Loop %loop: backedge-taken count is (-1 + (2 * %n)) +; CHECK: Loop %loop: max backedge-taken count is 5 +define void @even_nsw(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw_step2 +; CHECK: Loop %loop: backedge-taken count is ((-1 + (2 * %n)) /u 2) +; CHECK: Loop %loop: max backedge-taken count is 2 +define void @even_nsw_step2(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 0, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw_start1 +; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax (2 * %n))) +; CHECK: Loop %loop: max backedge-taken count is 4 +define void @even_nsw_start1(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw_start1_step2 +; CHECK: Loop %loop: backedge-taken count is ((-2 + (3 smax (2 * %n))) /u 2) +; CHECK: Loop %loop: max backedge-taken count is 2 +define void @even_nsw_start1_step2(i4 %n) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ 1, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw_startx +; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n))) +; CHECK: Loop %loop: max backedge-taken count is -1 +define void @even_nsw_startx(i4 %n, i4 %x) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 1 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} + +; CHECK: Determining loop execution counts for: @even_nsw_startx_step2 +; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax (2 * %n))) /u 2) +; CHECK: Loop %loop: max backedge-taken count is 7 +define void @even_nsw_startx_step2(i4 %n, i4 %x) { +entry: + %m = shl i4 %n, 1 + %s = icmp sgt i4 %m, 0 + br i1 %s, label %loop, label %exit +loop: + %i = phi i4 [ %x, %entry ], [ %i.next, %loop ] + %i.next = add nsw i4 %i, 2 + %t = icmp slt i4 %i.next, %m + br i1 %t, label %loop, label %exit +exit: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/undefined.ll b/final/test/Analysis/ScalarEvolution/undefined.ll new file mode 100644 index 00000000000..b1f44460af6 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/undefined.ll @@ -0,0 +1,39 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +; ScalarEvolution shouldn't attempt to interpret expressions which have +; undefined results. + +define void @foo(i64 %x) { + + %a = udiv i64 %x, 0 +; CHECK: --> (%x /u 0) + + %B = shl i64 %x, 64 +; CHECK: --> %B + + %b = ashr i64 %B, 64 +; CHECK: --> %b + + %c = lshr i64 %x, 64 +; CHECK: --> %c + + %d = shl i64 %x, 64 +; CHECK: --> %d + + %E = shl i64 %x, -1 +; CHECK: --> %E + + %e = ashr i64 %E, -1 +; CHECK: --> %e + + %f = lshr i64 %x, -1 +; CHECK: --> %f + + %g = shl i64 %x, -1 +; CHECK: --> %g + + %h = bitcast i64 undef to i64 +; CHECK: --> undef + + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/unreachable-code.ll b/final/test/Analysis/ScalarEvolution/unreachable-code.ll new file mode 100644 index 00000000000..51d93981800 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/unreachable-code.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; CHECK: %t = add i64 %t, 1 +; CHECK: --> %t + +define void @foo() { +entry: + ret void + +dead: + %t = add i64 %t, 1 + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/unsimplified-loop.ll b/final/test/Analysis/ScalarEvolution/unsimplified-loop.ll new file mode 100644 index 00000000000..a3175077b68 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/unsimplified-loop.ll @@ -0,0 +1,29 @@ +; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s + +; This loop has no preheader, multiple backedges, etc., but ScalarEvolution +; should still be able to analyze it. + +; CHECK: %i = phi i64 [ 5, %entry ], [ 5, %alt ], [ %i.next, %loop.a ], [ %i.next, %loop.b ] +; CHECK-NEXT: --> {5,+,1}<%loop> + +define void @foo(i1 %p, i1 %q, i1 %s, i1 %u) { +entry: + br i1 %p, label %loop, label %alt + +alt: + br i1 %s, label %loop, label %exit + +loop: + %i = phi i64 [ 5, %entry ], [ 5, %alt ], [ %i.next, %loop.a ], [ %i.next, %loop.b ] + %i.next = add i64 %i, 1 + br i1 %q, label %loop.a, label %loop.b + +loop.a: + br label %loop + +loop.b: + br i1 %u, label %loop, label %exit + +exit: + ret void +} diff --git a/final/test/Analysis/ScalarEvolution/xor-and.ll b/final/test/Analysis/ScalarEvolution/xor-and.ll new file mode 100644 index 00000000000..c0530bbc3cc --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/xor-and.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -scalar-evolution -analyze \ +; RUN: | grep {\\--> (zext i4 (-8 + (trunc i64 (8 \\* %x) to i4)) to i64)} + +; ScalarEvolution shouldn't try to analyze %z into something like +; --> (zext i4 (-1 + (-1 * (trunc i64 (8 * %x) to i4))) to i64) + +define i64 @foo(i64 %x) { + %a = shl i64 %x, 3 + %t = and i64 %a, 8 + %z = xor i64 %t, 8 + ret i64 %z +} diff --git a/final/test/Analysis/ScalarEvolution/zext-wrap.ll b/final/test/Analysis/ScalarEvolution/zext-wrap.ll new file mode 100644 index 00000000000..38d15ffbd88 --- /dev/null +++ b/final/test/Analysis/ScalarEvolution/zext-wrap.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -analyze -scalar-evolution \ +; RUN: | FileCheck %s +; PR4569 + +define i16 @main() nounwind { +entry: + br label %bb.i + +bb.i: ; preds = %bb1.i, %bb.nph + %l_95.0.i1 = phi i8 [ %tmp1, %bb.i ], [ 0, %entry ] + +; This cast shouldn't be folded into the addrec. +; CHECK: %tmp = zext i8 %l_95.0.i1 to i16 +; CHECK: --> (zext i8 {0,+,-1}<%bb.i> to i16) Exits: 2 + + %tmp = zext i8 %l_95.0.i1 to i16 + + %tmp1 = add i8 %l_95.0.i1, -1 + %phitmp = icmp eq i8 %tmp1, 1 + br i1 %phitmp, label %bb1.i.func_36.exit_crit_edge, label %bb.i + +bb1.i.func_36.exit_crit_edge: + ret i16 %tmp +} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/aliastest.ll b/final/test/Analysis/TypeBasedAliasAnalysis/aliastest.ll new file mode 100644 index 00000000000..d59e3924acd --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/aliastest.ll @@ -0,0 +1,62 @@ +; RUN: opt < %s -tbaa -basicaa -gvn -S | FileCheck %s + +; Test that basic alias queries work. + +; CHECK: @test0_yes +; CHECK: add i8 %x, %x +define i8 @test0_yes(i8* %a, i8* %b) nounwind { + %x = load i8* %a, !tbaa !1 + store i8 0, i8* %b, !tbaa !2 + %y = load i8* %a, !tbaa !1 + %z = add i8 %x, %y + ret i8 %z +} + +; CHECK: @test0_no +; CHECK: add i8 %x, %y +define i8 @test0_no(i8* %a, i8* %b) nounwind { + %x = load i8* %a, !tbaa !3 + store i8 0, i8* %b, !tbaa !4 + %y = load i8* %a, !tbaa !3 + %z = add i8 %x, %y + ret i8 %z +} + +; Test that basic invariant-memory queries work. + +; CHECK: @test1_yes +; CHECK: add i8 %x, %x +define i8 @test1_yes(i8* %a, i8* %b) nounwind { + %x = load i8* %a, !tbaa !5 + store i8 0, i8* %b + %y = load i8* %a, !tbaa !5 + %z = add i8 %x, %y + ret i8 %z +} + +; CHECK: @test1_no +; CHECK: add i8 %x, %y +define i8 @test1_no(i8* %a, i8* %b) nounwind { + %x = load i8* %a, !tbaa !6 + store i8 0, i8* %b + %y = load i8* %a, !tbaa !6 + %z = add i8 %x, %y + ret i8 %z +} + +; Root note. +!0 = metadata !{ } +; Some type. +!1 = metadata !{ metadata !"foo", metadata !0 } +; Some other non-aliasing type. +!2 = metadata !{ metadata !"bar", metadata !0 } + +; Some type. +!3 = metadata !{ metadata !"foo", metadata !0 } +; Some type in a different type system. +!4 = metadata !{ metadata !"bar", metadata !"different" } + +; Invariant memory. +!5 = metadata !{ metadata !"qux", metadata !0, i1 1 } +; Not invariant memory. +!6 = metadata !{ metadata !"qux", metadata !0, i1 0 } diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/argument-promotion.ll b/final/test/Analysis/TypeBasedAliasAnalysis/argument-promotion.ll new file mode 100644 index 00000000000..3b5211e5999 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/argument-promotion.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -tbaa -basicaa -argpromotion -mem2reg -S | not grep alloca + +target datalayout = "E-p:64:64:64" + +define internal i32 @test(i32* %X, i32* %Y, i32* %Q) { + store i32 77, i32* %Q, !tbaa !2 + %A = load i32* %X, !tbaa !1 + %B = load i32* %Y, !tbaa !1 + %C = add i32 %A, %B + ret i32 %C +} + +define internal i32 @caller(i32* %B, i32* %Q) { + %A = alloca i32 + store i32 78, i32* %Q, !tbaa !2 + store i32 1, i32* %A, !tbaa !1 + %C = call i32 @test(i32* %A, i32* %B, i32* %Q) + ret i32 %C +} + +define i32 @callercaller(i32* %Q) { + %B = alloca i32 + store i32 2, i32* %B, !tbaa !1 + store i32 79, i32* %Q, !tbaa !2 + %X = call i32 @caller(i32* %B, i32* %Q) + ret i32 %X +} + +!0 = metadata !{metadata !"test"} +!1 = metadata !{metadata !"green", metadata !0} +!2 = metadata !{metadata !"blue", metadata !0} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/dg.exp b/final/test/Analysis/TypeBasedAliasAnalysis/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/dse.ll b/final/test/Analysis/TypeBasedAliasAnalysis/dse.ll new file mode 100644 index 00000000000..6b44eb63842 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/dse.ll @@ -0,0 +1,66 @@ +; RUN: opt < %s -tbaa -basicaa -dse -S | FileCheck %s + +; DSE should make use of TBAA. + +; CHECK: @test0_yes +; CHECK-NEXT: load i8* %b +; CHECK-NEXT: store i8 1, i8* %a +; CHECK-NEXT: ret i8 %y +define i8 @test0_yes(i8* %a, i8* %b) nounwind { + store i8 0, i8* %a, !tbaa !1 + %y = load i8* %b, !tbaa !2 + store i8 1, i8* %a, !tbaa !1 + ret i8 %y +} + +; CHECK: @test0_no +; CHECK-NEXT: store i8 0, i8* %a +; CHECK-NEXT: load i8* %b +; CHECK-NEXT: store i8 1, i8* %a +; CHECK-NEXT: ret i8 %y +define i8 @test0_no(i8* %a, i8* %b) nounwind { + store i8 0, i8* %a, !tbaa !3 + %y = load i8* %b, !tbaa !4 + store i8 1, i8* %a, !tbaa !3 + ret i8 %y +} + +; CHECK: @test1_yes +; CHECK-NEXT: load i8* %b +; CHECK-NEXT: store i8 1, i8* %a +; CHECK-NEXT: ret i8 %y +define i8 @test1_yes(i8* %a, i8* %b) nounwind { + store i8 0, i8* %a + %y = load i8* %b, !tbaa !5 + store i8 1, i8* %a + ret i8 %y +} + +; CHECK: @test1_no +; CHECK-NEXT: store i8 0, i8* %a +; CHECK-NEXT: load i8* %b +; CHECK-NEXT: store i8 1, i8* %a +; CHECK-NEXT: ret i8 %y +define i8 @test1_no(i8* %a, i8* %b) nounwind { + store i8 0, i8* %a + %y = load i8* %b, !tbaa !6 + store i8 1, i8* %a + ret i8 %y +} + +; Root note. +!0 = metadata !{ } +; Some type. +!1 = metadata !{ metadata !"foo", metadata !0 } +; Some other non-aliasing type. +!2 = metadata !{ metadata !"bar", metadata !0 } + +; Some type. +!3 = metadata !{ metadata !"foo", metadata !0 } +; Some type in a different type system. +!4 = metadata !{ metadata !"bar", metadata !"different" } + +; Invariant memory. +!5 = metadata !{ metadata !"qux", metadata !0, i1 1 } +; Not invariant memory. +!6 = metadata !{ metadata !"qux", metadata !0, i1 0 } diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll b/final/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll new file mode 100644 index 00000000000..8fb5ffffbae --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll @@ -0,0 +1,81 @@ +; RUN: opt < %s -tbaa -basicaa -functionattrs -S | FileCheck %s + +; FunctionAttrs should make use of TBAA. + +; Add the readnone attribute, since the only access is a store which TBAA +; says is to constant memory. +; +; It's unusual to see a store to constant memory, but it isn't necessarily +; invalid, as it's possible that this only happens after optimization on a +; code path which isn't ever executed. + +; CHECK: define void @test0_yes(i32* nocapture %p) nounwind readnone { +define void @test0_yes(i32* %p) nounwind { + store i32 0, i32* %p, !tbaa !1 + ret void +} + +; CHECK: define void @test0_no(i32* nocapture %p) nounwind { +define void @test0_no(i32* %p) nounwind { + store i32 0, i32* %p, !tbaa !2 + ret void +} + +; Add the readonly attribute, since there's just a call to a function which +; TBAA says doesn't modify any memory. + +; CHECK: define void @test1_yes(i32* %p) nounwind readonly { +define void @test1_yes(i32* %p) nounwind { + call void @callee(i32* %p), !tbaa !1 + ret void +} + +; CHECK: define void @test1_no(i32* %p) nounwind { +define void @test1_no(i32* %p) nounwind { + call void @callee(i32* %p), !tbaa !2 + ret void +} + +; Add the readonly attribute, as above, but this time BasicAA will say +; that the function accesses memory through its arguments, which TBAA +; still says that the function doesn't write to memory. +; +; This is unusual, since the function is memcpy, but as above, this +; isn't necessarily invalid. + +; CHECK: define void @test2_yes(i8* nocapture %p, i8* nocapture %q, i64 %n) nounwind readnone { +define void @test2_yes(i8* %p, i8* %q, i64 %n) nounwind { + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !1 + ret void +} + +; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture %q, i64 %n) nounwind { +define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind { + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i32 1, i1 false), !tbaa !2 + ret void +} + +; Similar to the others, va_arg only accesses memory through its operand. + +; CHECK: define i32 @test3_yes(i8* nocapture %p) nounwind readnone { +define i32 @test3_yes(i8* %p) nounwind { + %t = va_arg i8* %p, i32, !tbaa !1 + ret i32 %t +} + +; CHECK: define i32 @test3_no(i8* nocapture %p) nounwind { +define i32 @test3_no(i8* %p) nounwind { + %t = va_arg i8* %p, i32, !tbaa !2 + ret i32 %t +} + +declare void @callee(i32* %p) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1) nounwind + +; Root note. +!0 = metadata !{ } + +; Invariant memory. +!1 = metadata !{ metadata !"foo", metadata !0, i1 1 } +; Not invariant memory. +!2 = metadata !{ metadata !"foo", metadata !0, i1 0 } diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/gvn-nonlocal-type-mismatch.ll b/final/test/Analysis/TypeBasedAliasAnalysis/gvn-nonlocal-type-mismatch.ll new file mode 100644 index 00000000000..eceaa2cf02d --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/gvn-nonlocal-type-mismatch.ll @@ -0,0 +1,91 @@ +; RUN: opt -tbaa -basicaa -gvn -S < %s | FileCheck %s + +target datalayout = "e-p:64:64:64" + +; GVN should ignore the store to p1 to see that the load from p is +; fully redundant. + +; CHECK: @yes +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* %q +; CHECK-NEXT: ret void + +define void @yes(i1 %c, i32* %p, i32* %p1, i32* %q) nounwind { +entry: + store i32 0, i32* %p, !tbaa !1 + store i32 1, i32* %p1, !tbaa !2 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32* %p, !tbaa !1 + store i32 %t, i32* %q + ret void + +if.else: + ret void +} + +; GVN should ignore the store to p1 to see that the first load from p is +; fully redundant. However, the second load uses a different type. Theoretically +; the other type could be unified with the first type, however for now, GVN +; should just be conservative. + +; CHECK: @watch_out_for_type_change +; CHECK: if.then: +; CHECK: %t = load i32* %p +; CHECK: store i32 %t, i32* %q +; CHECK: ret void +; CHECK: if.else: +; CHECK: %u = load i32* %p +; CHECK: store i32 %u, i32* %q + +define void @watch_out_for_type_change(i1 %c, i32* %p, i32* %p1, i32* %q) nounwind { +entry: + store i32 0, i32* %p, !tbaa !1 + store i32 1, i32* %p1, !tbaa !2 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32* %p, !tbaa !4 + store i32 %t, i32* %q + ret void + +if.else: + %u = load i32* %p, !tbaa !3 + store i32 %u, i32* %q + ret void +} + +; As before, but the types are swapped. This time GVN does managed to +; eliminate one of the loads before noticing the type mismatch. + +; CHECK: @watch_out_for_another_type_change +; CHECK: if.then: +; CHECK: %t = load i32* %p +; CHECK: store i32 %t, i32* %q +; CHECK: ret void +; CHECK: if.else: +; CHECK: store i32 0, i32* %q + +define void @watch_out_for_another_type_change(i1 %c, i32* %p, i32* %p1, i32* %q) nounwind { +entry: + store i32 0, i32* %p, !tbaa !1 + store i32 1, i32* %p1, !tbaa !2 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32* %p, !tbaa !3 + store i32 %t, i32* %q + ret void + +if.else: + %u = load i32* %p, !tbaa !4 + store i32 %u, i32* %q + ret void +} + +!0 = metadata !{} +!1 = metadata !{metadata !"red", metadata !0} +!2 = metadata !{metadata !"blu", metadata !0} +!3 = metadata !{metadata !"outer space"} +!4 = metadata !{metadata !"brick red", metadata !1} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/licm.ll b/final/test/Analysis/TypeBasedAliasAnalysis/licm.ll new file mode 100644 index 00000000000..12a9c1dc564 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/licm.ll @@ -0,0 +1,61 @@ +; RUN: opt -tbaa -licm -S < %s | FileCheck %s + +; LICM should be able to hoist the address load out of the loop +; by using TBAA information. + +; CHECK: @foo +; CHECK: entry: +; CHECK-NEXT: %tmp3 = load double** @P, !tbaa !0 +; CHECK-NEXT: br label %for.body + +@P = common global double* null + +define void @foo(i64 %n) nounwind { +entry: + br label %for.body + +for.body: ; preds = %entry, %for.body + %i.07 = phi i64 [ %inc, %for.body ], [ 0, %entry ] + %tmp3 = load double** @P, !tbaa !1 + %scevgep = getelementptr double* %tmp3, i64 %i.07 + %tmp4 = load double* %scevgep, !tbaa !2 + %mul = fmul double %tmp4, 2.300000e+00 + store double %mul, double* %scevgep, !tbaa !2 + %inc = add i64 %i.07, 1 + %exitcond = icmp eq i64 %inc, %n + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body, %entry + ret void +} + +!0 = metadata !{metadata !"root", null} +!1 = metadata !{metadata !"pointer", metadata !0} +!2 = metadata !{metadata !"double", metadata !0} + +; LICM shouldn't hoist anything here. + +; CHECK: @bar +; CHECK: loop: +; CHECK: load +; CHECK: store +; CHECK: load +; CHECK: store +; CHECK: br label %loop + +define void @bar(i8** %p) nounwind { +entry: + %q = bitcast i8** %p to i8* + br label %loop + +loop: + %tmp51 = load i8** %p, !tbaa !4 + store i8* %tmp51, i8** %p + %tmp40 = load i8* %q, !tbaa !5 + store i8 %tmp40, i8* %q + br label %loop +} + +!3 = metadata !{metadata !"pointer", metadata !4} +!4 = metadata !{metadata !"char", metadata !5} +!5 = metadata !{metadata !"root", null} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll b/final/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll new file mode 100644 index 00000000000..c2407dfd4c8 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll @@ -0,0 +1,23 @@ +; RUN: opt -S -tbaa -basicaa -memcpyopt -instcombine < %s | FileCheck %s + +target datalayout = "e-p:64:64:64" + +; The second memcpy is redundant and can be deleted. There's an intervening store, but +; it has a TBAA tag which declares that it is unrelated. + +; CHECK: @foo +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 16, i32 1, i1 false), !tbaa !0 +; CHECK-NEXT: store i8 2, i8* %s, align 1, !tbaa !2 +; CHECK-NEXT: ret void +define void @foo(i8* nocapture %p, i8* nocapture %q, i8* nocapture %s) nounwind { + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 16, i32 1, i1 false), !tbaa !2 + store i8 2, i8* %s, align 1, !tbaa !1 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %q, i8* %p, i64 16, i32 1, i1 false), !tbaa !2 + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +!0 = metadata !{metadata !"tbaa root", null} +!1 = metadata !{metadata !"A", metadata !0} +!2 = metadata !{metadata !"B", metadata !0} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/precedence.ll b/final/test/Analysis/TypeBasedAliasAnalysis/precedence.ll new file mode 100644 index 00000000000..47cb5f2256d --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/precedence.ll @@ -0,0 +1,46 @@ +; RUN: opt -basicaa -tbaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=TBAA +; RUN: opt -tbaa -basicaa -gvn -instcombine -S < %s | FileCheck %s --check-prefix=BASICAA + +; According to the TBAA metadata the load and store don't alias. However, +; according to the actual code, they do. The order of the alias analysis +; passes should determine which of these takes precedence. + +target datalayout = "e-p:64:64:64" + +; Test for simple MustAlias aliasing. + +; TBAA: @trouble +; TBAA: ret i32 0 +; BASICAA: @trouble +; BASICAA: ret i32 1075000115 +define i32 @trouble(i32* %x) nounwind { +entry: + store i32 0, i32* %x, !tbaa !0 + %0 = bitcast i32* %x to float* + store float 0x4002666660000000, float* %0, !tbaa !3 + %tmp3 = load i32* %x, !tbaa !0 + ret i32 %tmp3 +} + +; Test for PartialAlias aliasing. GVN doesn't yet eliminate the load +; in the BasicAA case. + +; TBAA: @offset +; TBAA: ret i64 0 +; BASICAA: @offset +; BASICAA: ret i64 %tmp3 +define i64 @offset(i64* %x) nounwind { +entry: + store i64 0, i64* %x, !tbaa !4 + %0 = bitcast i64* %x to i8* + %1 = getelementptr i8* %0, i64 1 + store i8 1, i8* %1, !tbaa !5 + %tmp3 = load i64* %x, !tbaa !4 + ret i64 %tmp3 +} + +!0 = metadata !{metadata !"int", metadata !1} +!1 = metadata !{metadata !"simple"} +!3 = metadata !{metadata !"float", metadata !1} +!4 = metadata !{metadata !"long", metadata !1} +!5 = metadata !{metadata !"small", metadata !1} diff --git a/final/test/Analysis/TypeBasedAliasAnalysis/sink.ll b/final/test/Analysis/TypeBasedAliasAnalysis/sink.ll new file mode 100644 index 00000000000..fd32d6a7a58 --- /dev/null +++ b/final/test/Analysis/TypeBasedAliasAnalysis/sink.ll @@ -0,0 +1,20 @@ +; RUN: opt -tbaa -sink -S < %s | FileCheck %s + +; CHECK: a: +; CHECK: %f = load float* %p, !tbaa !2 +; CHECK: store float %f, float* %q + +define void @foo(float* %p, i1 %c, float* %q, float* %r) { + %f = load float* %p, !tbaa !0 + store float 0.0, float* %r, !tbaa !1 + br i1 %c, label %a, label %b +a: + store float %f, float* %q + br label %b +b: + ret void +} + +!0 = metadata !{metadata !"A", metadata !2} +!1 = metadata !{metadata !"B", metadata !2} +!2 = metadata !{metadata !"test"} diff --git a/final/test/Archive/GNU.a b/final/test/Archive/GNU.a new file mode 100644 index 0000000000000000000000000000000000000000..4c09881eb39dc513184462952d414396b3f4a0c0 GIT binary patch literal 4210 zcma)92V9d!8^4zfLrB07P{5$CLO@g!0%3@w3=xp2fJH__7BeK61Q2T#L{zXY(28gQ zw^9dG>%jJNfFcTtKtXA7wHBpAq}p2Sr@ae#CE9+!ug{P7o_YVf=egtVGI6F@Elr(G z=i_gaK;Yuy<>n@w?tM{p$MS=!QF&}BZ;0PSLcZoDrJgDlBbnRRWi9KIZYuKDaDy`o-|iv2SD-q>lLpd6|A_QP!tEA zyuO>I4b=koRl@v8N`!e=@0p`#zo?DGm~^qQymJ4c%cuD=*}jfj@>M#cXeILxbN_FezSx$V*V+`I4s84E zJ~J~tb3?GCf>uHEOuy65EjnK9o-wbnHfYb{X|ufT{3IdwI6c$6gqGL#b$0%D(YGD` z3qxycG74k34@106zY~A^)5_q2t3C}uf_!(YT}9pZv>VfJGXz!#n8JF`eY;Bs<4D^X zqqvckeW8iP7C4(McP@Lf@kVfmPgHeeG~br&Q=Vj0cQiJB^TkyyL4BcBAEw1moPMLE zmGuKNaEkTS;>IzrqV|`U6bfJ7zLpx_z-`=@a4AHpWDK+o)vR3F*JQ)JCg~ivb#%+6 z#BrRH&0>zl=NSUalFO3Zi1F*r)UhsW)>Sd?uMW#FeNMk6=`$I-k}Q7S!Q`m3B%Zm? zH45%S$HZHtsi{A7pC7&1LdHt-&F{`yx_;TIFEMf{eP_$5__g;NEd4E>4}H`1%=!EB zhyNLKd79Iy#C=J=rUhZ!TpKvEwfktb=0UOj4ce6IgFQT}hJ&vQ27B>0$; zN6E8q%#FDFXG3}8!ofe9<~bxS^mIzMjP(xjYq{HNl2u>e;#qLj`2*#IO*tDm3Eo~O zo~E6Xm$la1jTa}48H#>%@xqQ1Gq;B3Q+uW<+EZiku9LeRN^B!Z2QN)4w|t%Z>-aey zT?ySbzkl36_oD1gNEwSUsH{1v8_DPv{e?9E|<4;$;%uXjRzw=3r4Rgj7YdSkJ zVSd0=c}so!&9f$chYG`1N`pm}!dE?=_+rnq;9^(7x# z-8yb{H8=BFx|}iA{0cq#&;qA9KL=0VUK(BIT0Dtm7C3OZEa<%NI{Q6Km}MW%KS1Z! zCzN(u=C@Ndt|?#M;MI0_1M2x$Yf|{KGxaW8*RbYX-+jD%!qZ&)s3K!y$CuWd=(IefQFroo)o-}ONoyuS`umt8Hrubpu zPqcLbv|_UTqd(#8(A=;|XS3=Jp!Fuc=nZ($%OO0lJI2CBQ_W$^rLj#&Gkm7SHPQfv9cWtV1U0VDJ{z-6jzi9!w-WTP~t7LX}M(p0e; zU{oW$gGMIZgJU98fZ3AIKpE3v0BpiL@0Dbbj=U5U52!>G{!WxkAC-rqfKjqSC5GdY zM;XKXHtK8uz`_A6hL#M+xQBu^(||D=*#ds30?;P|7>*!}HZK7{gaih&;1feWEl(of7Ep?~PA}Tfj-b{(z^+%hZY` zkZaY$Je82tas^K-U!ny(nOG|ZJc&jFMY$w9MI@F;)bbp_Lm|VKG-a~NP*0BOqe6Seb%MN|jd5gVS`@XvNYDz>}&nGv#oX{cD;4BhhkD^*w}; z8&-m-&p2o|*2f?g3;$iwdg=BN8PK0gB)x%=UVb^t+yI2#%a^GJo0@PRgz2dV*)#{wu5eV_T)oM6Ha%@55Nix9)uHe??;2X;qmU<9Y>h&Tj98Dp>vC=(2=72o;z4`yPY`cGYegKTK?^2Q~lT^}7eP zy9dYBgLP)bEa!`OpY}@y*B5b4iR%{%7YZWo)5ers|9s&YC|&^NxrJ1{x#4e@o?Q^h z2|O7D$%6VZB~LH)w-Ri^73Rj9E{@1_IT&wPS6+*#pw?E zd*$X}5_Ma$;5nUsEMCrO?1v*Uc_(xDo_hy-5>?D2-j|R~f+6Na{k5Gc9Zx2PT3asD zn`6A>HL841R5OdZ&M0x(-9dL=8H@IJIcs`z&IoNos$b++?r2DF_+_ro2+f?o3NB@x2?H#CVm(x|QJ6?R}oZj!03uL%C832~l^s61~%CDw)CuimNjKc!A^`mJ01 zp1)38>h;dJANC;}{cAPVgXQdjgJV8M4nSsXPzGjV*eh~0kY^zOJ>!35dE})2lB2Z9T+**s$MWotV?9wen<@OfF7ISIEUm zNtT=^O$G`@ZnD5PE=|PuSz;fxq2_6?4m+E6VJtriwW zk|WG|`p+Ia_gQ@;#-K@rmDL9hp9rn0XdSHH+kNZ6&fwZR-qxU_>oNe?NNsm_MomRn z)bI|6t?xt@GAM-tXs)Fc0&8NFt#4S^T<_K=^zM!hAVeJ$0-`rN4HBiWnSpHvlqz5i z8KB$w`v@yH5dDX3=ZA%D6#@p|+KM6Uu(rYuY_Qm}HHyYdIKRAVSQ)o?&Q8;B_<=2( zJ|;Tt2A!_^eK^&ti3M)YThGUre@PW~TC`io9trJI4!x+!EBuKsj=!a`W}k81&d}W5 zKyr7ee?8+usbg%!>425ezOClJ{Zt-Yu-&k{6dlC?vmd7+D#dE=zPnA3}K`D{ypWxal{?;aoou2fzZTKa}J9n zcdB^0>1J@3cT{a;w6hJ#yE2K;a4a@{%ca$AK?9*R@2AI4^}Jcu&isxMIK%2%Y4e2F zQ3oo^iiNN4Tu+N{;x_M3xEzwKqz`qB)U8@R&|=NKF72MQZG7A1#7XQ^trE8RrRy->Eh0lbGC&RQu<~oI@4k~J*W2Am)S%T4_%&BY4IlS=gIzVJqf+mzkWD4|B~!n zxrW@bk=4jM^>IYc2-!2Nq}uUp1esGqc-B7klabp6A6{fBwtDZXZy9>t5M9c(GFzDa z!J@11NbEfN755>lb6VEDpO1Kb|HCy8(=&+$cR#ALX3V~7MPo%KEDV?_Z)@zlb_jdNSg#c<~!JD+)ZLm-WhVJ=l0zgWH$Y5T=t_(@v4q5 zvCq0LKB|2Bi>;}9&h(awzzz0Yth6N~rj&fzyP?5!U;)fPOzETIAE@gCsHG&k$G^ju zqP1zW&Su#kKXm7%UPO}u8=wNc%zyk zUFsZ_lbx+nYn?~in4Fyr2IBu6oTGCB@yq#H4!Sn zY)EIJjOj1{Hbop4E<_HI&Jd6SGLV;y;sFJZ;`}8_rjN=;QGk%5P)Xprq;W>DzD+tC z0I+cYi=n2#HSVLJEmUBHRyKzp>Hze~0LDQOge}Ve5F-HuA`kY;ga$|5;lTcNTL2jA zi>}XPUDJt^vE=U41O@~I;~_fwgMk5T1(i-Bt%GqWADmFmJ|@%>f-i%N+Yz@iuup^X z=x*A>*-xN0+DcUWs02-b{Wgk(R2|{_u2Ta2{Jc2R;Sq4u??2#a^0TxODdbx9C{M#B zwOql|%9m*YPbSey08gsXKv6EuNfk?^Qnfr6@KDI8C0&`KGSn66O1Yt)qK5y$3=P>i zQuMbBLXLq*)DmSXGAUJBIS;1kq|r)}GXXDIm6aujr|e(T6c~xNgQA}ygxs(bcz-5A zyOBNyu~_(XMf;^YN06g9XaZdLAw2!{0Ax@$Bph!hG@|(b7v}}KFsvgDCgBZjs1DQvypBas#^*p0jE9FR83}sAec@0y#5)A>P+bTQ zaU4$yWqb}4ffnNVBSB9n4$*t?GsLThARK5zc<}0ai>HCIA>J8?XAf;S;XZVm8{%~s zU@SDEdx8N!lpo3$)nJHc3F|;-11Ef4T*tYg zodlk}!R?6u`GrKf;R;B{cX@Oc5s(e1Lq9r!V?@-QAVVFUfH5Khw1Zg zBcA_* z;py%U=OgrhEutg_tfAD^FD}*H#dnE))ROX*4Lbl(y!~qBTS!GKA0(8-fv0cpWobe+ zzghdVSaM=1@WFd=I=nBoXv_fD_j!B059ylPk(w|MqW z({Eh@TQ+?{cG?X(-S+$9)vL(`9?x6P$CrOa7j{~-TgM&=?NScCsL3n**+mq8OKr_P zBiPPT-`zm*bf|wb?Lw(zY{cn+m6E=#=D+>CEvofptCM(0=6ce7BUNg<+^LG4@Kt&k zK1aU2oSU*^J+JJ`bY{sa*6(KiU$=a|Jukn#E#B5E=1BIS!_!=gWfq+#$CY&_F1g2d zyvVdNU;dfPf~EqW|`xvYJ9ZkfhHgR}-{tq>qtG{`s%B?xL{nH1m%=FBS z!ICO^72Pxa?jWz^M6G+qg68_5y-R1z@wWAogxu%$&F~UhT;Jc_{huY@bonn1t+UQ3 zj^RBD@iO^V{LPQ6f{U*CGzGa7x?Aop>AkPnlzxZlVtJ4yZ1mi}r+he$yn{K07g;?J znpkR%b0~7Bil>`y26y>H)ka1OY$!gJNu-8jvGH3jt!@h%2(9@rEq?OMn`Q0n?^%J< ztge+dk9!k!pt7u3`1;QE)c7V|^Zta(AyOrCsN+@Ls^tSM*1YSI?g`t*wp~t~z&+I} z=9+(&;bKvCMUodWasAl__7(N|8s>vFVHqYb7`G(@#^YB}#4oy7-0UogXWk37g7?TF z@iuvS>i4}D#%?i}vD17Dd$X2rSaJFbj8e|n)pk05-Ge3zfAbfwzV3PM^j+nne~-H| z!|`oY$C~rF3+g6c$@dj#CaY)3BA_8 zeKa`#lI&c$n%c6F)5t&dNkq>p>ddf`YR9t?RJ?}ttbOvQuWlE7bdjUj>a(l9W$1ZB zbScluY+=^F7F~r~V&~DXc@H_AQ!?-Ua>Vf^&3fy^ z+?|y11N({|PQD^KvzivN^sHZl^C{z9tM*Mj$hG>OxzH#@ZRf$^?W<$4-(RpuT9EUE zw0Eg-?p2}uv7c~wGgoj-Z1Vi|q4;Ud1w{`in_PX(cW}>mn#7#EGvrXu>$@??Zu-Tz z>?fJxb)AdYKJ&WhsPgHrwx*srQ(GzmH`sS^QkT3ktvq6r-aJQgFDUSM@|Fo6S0^rG zhfmAMbve3DReHqFyFZZ4{FlnyHs@qg!|w$)yF+d@N-hLlxoETNWkmFGJnLoc%=cAQ zAHSbJ&T7T|&w54sG=2OYukQxiBu@gGsWY9*QiL+ZwGtxxMjvpSFeC#moqo<+; zW(?cK*<|5v6E1I0*WPE3<9@)$uX8tc<}c({M+*Cv4xd_GTzGQ+jh?W`4YRf#dwoAD z`VM{j&2!!LnMGpkiyIa34=ojL(}UccY|J=oYcB4!54SB*G#ss%=H44NkbHPe`-C;M zyv*n6a^`rmtBmNwiyY_u6g+iDd31$q=@hnU;Lw$dpbNh1?e;EXReZScAcNPKP~K}% z*hy2nrhIXeU*FpcXcuCw$l)u_Hac%x%bs^*&xy)O&+_b|N{oygUR!NuXfHm#>L1@e zuC8ACdm@RkG9Yw5hGFQ;)e;8CU{nL(0$FF*p2}b<@U^&m}ytJI2Pw(#&AXqjQYOba;2$0W#g#c&;%3 z^?@lcE%<1FMA0Vbq?G{(43EM6r%%V-_(Hxjpa`%TN&?)5ma7=^> zFdNEQC}Ua-fK7Vm&5{h#k(Y|%0gZ^l--(jxqw-M{ASEkQVmK~kj1kOllhy_REF8dM z=*e)5`zUA&9T=gJ&EbbC0DUrm;Ru4XWf=e>B!EEV!Csp%V5{96*gq}{0Hbx$)|sj; zI(Z@{?LJLnK|nATqN7Iz2Cx-$CWW#N#-aHTgy!sPLN6itv8aR{aVrD+6e#Of(;oJI z0ySMJQSLekngDksih@)v5$mp10{#8H@u_eNIO^9Q@YVU58nFa&O}37w5>mEY!Pm%_ zX#ig))`$ULqEC9 zf39e~wEGBh6bDU!2S0?TKOTS#%7#SXO@~Gl|95fDFb3ffgz(l73gm>(&p<}*LHMB^ zKoB9$g$BbsQsE?gpbh1LYCz-x|3ZvlLlKOHn@WlVJrQ`}P&dRo1o2Q_2oG@rPXcA4 z4-|n0;>|;Xo=_a358!8rR}VpOXhV4L=o-OOL)j4T48*gCHi8JB3K|UYIt=Cq&(IOP zwNNJdAdI^Z4@ZKY2wySO4e@S6JYpZ1Kp&Cs$51BvAc!{*&yWb;0ca#-Lj&{H(kpWu4Q6dAh0;5FMW@@Oj0lZDM zg!YpetUNji2|{&2zhB}^MSc&$2|4l`oZ|1?I`9v+C{3*tEC1r3w%!A~qctGGX*wVd z0a3;nECb2}Lu-XNTtGAj#E13#S3Ng@3xMoqdLFH}TOtnE5aomX&U#&_*R|uohTz0F F{{`)U>mUFC literal 0 HcmV?d00001 diff --git a/final/test/Archive/dg.exp b/final/test/Archive/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Archive/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Archive/evenlen b/final/test/Archive/evenlen new file mode 100644 index 00000000000..59ee8d552e3 --- /dev/null +++ b/final/test/Archive/evenlen @@ -0,0 +1 @@ +evenlen diff --git a/final/test/Archive/extract.ll b/final/test/Archive/extract.ll new file mode 100644 index 00000000000..714c5f1ed98 --- /dev/null +++ b/final/test/Archive/extract.ll @@ -0,0 +1,16 @@ +; This isn't really an assembly file, its just here to run the test. + +; This test just makes sure that llvm-ar can extract bytecode members +; from various style archives. + +; RUN: llvm-ar x %p/GNU.a very_long_bytecode_file_name.bc +; RUN: cmp -s %p/very_long_bytecode_file_name.bc very_long_bytecode_file_name.bc + +; RUN: llvm-ar x %p/MacOSX.a very_long_bytecode_file_name.bc +; RUN: cmp -s %p/very_long_bytecode_file_name.bc very_long_bytecode_file_name.bc + +; RUN: llvm-ar x %p/SVR4.a very_long_bytecode_file_name.bc +; RUN: cmp -s %p/very_long_bytecode_file_name.bc very_long_bytecode_file_name.bc + +; RUN: llvm-ar x %p/xpg4.a very_long_bytecode_file_name.bc +; RUN: cmp -s %p/very_long_bytecode_file_name.bc very_long_bytecode_file_name.bc diff --git a/final/test/Archive/oddlen b/final/test/Archive/oddlen new file mode 100644 index 00000000000..8cf5bd181b1 --- /dev/null +++ b/final/test/Archive/oddlen @@ -0,0 +1 @@ +oddlen diff --git a/final/test/Archive/toc_GNU.ll b/final/test/Archive/toc_GNU.ll new file mode 100644 index 00000000000..9ed7d8eb8cb --- /dev/null +++ b/final/test/Archive/toc_GNU.ll @@ -0,0 +1,8 @@ +;This isn't really an assembly file, its just here to run the test. +;This test just makes sure that llvm-ar can generate a table of contents for +;GNU style archives +;RUN: llvm-ar t %p/GNU.a | FileCheck %s +;CHECK: evenlen +;CHECK-NEXT: oddlen +;CHECK-NEXT: very_long_bytecode_file_name.bc +;CHECK-NEXT: IsNAN.o diff --git a/final/test/Archive/toc_MacOSX.ll b/final/test/Archive/toc_MacOSX.ll new file mode 100644 index 00000000000..6dbc9d2ea4a --- /dev/null +++ b/final/test/Archive/toc_MacOSX.ll @@ -0,0 +1,9 @@ +;This isn't really an assembly file, its just here to run the test. +;This test just makes sure that llvm-ar can generate a table of contents for +;MacOSX style archives +;RUN: llvm-ar t %p/MacOSX.a | FileCheck %s +;CHECK: __.SYMDEF SORTED +;CHECK-NEXT: evenlen +;CHECK-NEXT: oddlen +;CHECK-NEXT: very_long_bytecode_file_name.bc +;CHECK-NEXT: IsNAN.o diff --git a/final/test/Archive/toc_SVR4.ll b/final/test/Archive/toc_SVR4.ll new file mode 100644 index 00000000000..d447b921999 --- /dev/null +++ b/final/test/Archive/toc_SVR4.ll @@ -0,0 +1,8 @@ +;This isn't really an assembly file, its just here to run the test. +;This test just makes sure that llvm-ar can generate a table of contents for +;SVR4 style archives +;RUN: llvm-ar t %p/SVR4.a | FileCheck %s +;CHECK: evenlen +;CHECK-NEXT: oddlen +;CHECK-NEXT: very_long_bytecode_file_name.bc +;CHECK-NEXT: IsNAN.o diff --git a/final/test/Archive/toc_xpg4.ll b/final/test/Archive/toc_xpg4.ll new file mode 100644 index 00000000000..fd875eebdaa --- /dev/null +++ b/final/test/Archive/toc_xpg4.ll @@ -0,0 +1,8 @@ +;This isn't really an assembly file, its just here to run the test. +;This test just makes sure that llvm-ar can generate a table of contents for +;xpg4 style archives +;RUN: llvm-ar t %p/xpg4.a | FileCheck %s +CHECK: evenlen +CHECK-NEXT: oddlen +CHECK-NEXT: very_long_bytecode_file_name.bc +CHECK-NEXT: IsNAN.o diff --git a/final/test/Archive/very_long_bytecode_file_name.bc b/final/test/Archive/very_long_bytecode_file_name.bc new file mode 100644 index 0000000000000000000000000000000000000000..f7fce249020a07869e8259f81ea74739b0b4c06c GIT binary patch literal 1465 zcmV;q1xEU8Y<6QZLRx4wF+o`-Q(2OKv6%n>Z2#4N|NsC0fq&s#g<1gb|KD(QOmqM> zgfxIq1y2&z-MOy2wXjeD4GLj2n4YGovrL+k$?Be?)X}D!Nub$48UWDK#Q*>S`k>U* zYM+x$Q}UT7ls`~_4F-TR0004?27mw>15+bHO-(&O$>|K#(9i%h00000GynrY9B620 zXa<194FQk<2ATjG0gwOy3?xKBG?O-+k2sF|a%^Fy&Ow(@g^`Ccu z?lE6m(Q_IcxG$FtbKZ>vHz%;SWmY_e`4B{6!-3xQ_1+rEn)CvGPE_01!E(6 zEt(Nr)oM*3J!O}Y9A}w}C5pXj426OX`4U6h$F-MtdCkmQBREy8a_T4Vb`^LP(hjd~ zsWi6BMkIzZdKvSSlR4*L_K$u_xv94HKk-~(`NaswSdudxCInRpC5#|j? zDjCX{TjrkIL@H2c}hXj{W2#HC!tOJi;f@X-3If_mr28YRnO)Eku$%*9`NYYz1a*kb1k7lH&~_0tU;a&TfdclC2@CFLhw z*aItQ=GVXwkrZSRX+eP3aC(h=x4Z!ak_w#6w_Awe!xcjm_4?b^^eyC=<-QiiEGf5L zrC>o0flZe(!yGsPx-PbzPuBVcIZcJ0DY;JtAfE#9%^|D$*nW(`6Ks?~oUq66^s!WlB^eS?aD7t9 zp4{=9t=lEy6Vf7W-}9_G>+H%n54c@^-j=Ew4Lisg3KLLVQAI0d%(~Liy9+|8gH3{C zNejJ+UN4VUbJB9@@(G15wHeaSb&G7z<8eMjq1Q+L|f#M;?U$}$@ zOL4hEu`sp^oPwk%ryLpP3{eSZb0jtsC8Vki5m!o5V}5n%0;6#YcE~hk=t4B|kQ^_r zVGi{Bs9P$;eu3cxk1|0NnH;z`4pp?-@F%b(+Ro|`!}AM@?PP5Gsxe_EZOdP+ZtwOZ z4>xrv$CF2mCessWS^5u{tQ~5^J!0QTN3Uj)8#c%uco9x2Yj!cMh;NCkLOR_?5e$8A z6eD%CV6pjr9idCnx?;dc#=#w&_)k=?AaMAgIahC*mRETe8GPWf*I%S`+Ah{OgoA*zM$XnvP>nm4uKVCqRM`lZ&%4yHZGm9{yv~zb;uvf*D@Zdf z9TF3VpTVOhP9ueEv8|ITHP=n&W~qkF8-}1IZS-no3>Ol}3RJ05DMal_D4CK}lQM}S z5f4Z3#*;|EL5n1#cny<#QKt$ex?Gai6@bzPb24YV&n~dn*8m2tD0gEgR*;qq@B!E~Sf`|&%4YVR! zz+I^eRO^E6a{)yZ6oG=$;?`P}E+W;|YM;KDkPE4=-)qnJ-8t+0Gv~}?W-@uUBukbu zmm$FaOhTcvv!|<@tEU@|JL_DAEsl#kiTFeY0DuI*m__Il$A*cN%A5?hAWfK0n12#@ z#~_Enf_Db{yRlr|N5{%hWaWvKYE`mWnx|FB)N+M5DOITut0Wl;zEmb)KvLu=R7!?$ohjut@eJ`SbMJsTD<{DZ7uqH>^`i6$i@oss->}qcZBDh|#A$xOEAkhk%SlDJj zs|41N0jAwNA5p~y^1LD2`Jtg(MSvx=wql9et*x*F8!WbLjb!lS&o8eWQpGNwz0>qt zVL{Z&)XtfUbZ+%2IVd%-8NEXw#%I=+3{bch2nD* z+snAgJJ$0`zf5BmuVVdf=J$2;=i77h+FIjmJ)@6g4LCf_u~=r&VRBqmd*YH?T>Fa* zEA!=_2^Tcxdna8MFdq4>d)UiZ?dNDBF|~=srOVr@8e^1#^EO`fW3@@UpKO~{V z9OqCJPUTNG-3;pVj;x7@64+3@D-ucd$715PTw2{4*dJ2;VQSpunKw(@*x$1PrdeGp zX&Uz?@<2stk?8fE>nU-Kyr%u}mxE<0=3x7)+EvT@o2_}*rCk%YjcvW0FoAojMZz`z zEL~_(dPSNWK5_lodiE8~`fBEbHKFMyFBrF_{l?>0Q6w)qS=_8lsYmV$jgt4sA>lT8 zddl}b7shTem$OrS3VJe^Z&-2q3yf06*wuPEZry`M3qSK0ufFbn?(|*7qkoUPGQ;t7 z!u~`blfuyLE{)u|+Wqu8v%r{vMs0G zqp_lC@zC$h3+xjYdpM?9#CQe!w%+SA&TJ@j_9(pO^nq&9=A2F3crVYB&r;7T%G+x1 z#Yqy!y^4B#>Eh0lv$us5(0XSmJ5pls?o)g0OKl>^hc3^kuy~vM%fxx^-SIuvzkM_? z|C0P%nTFcDk<-9G^+|a5E9%V9;ws0p;Z(eu^sH_2r>}13e{_+f-0Honu6gizeN+k0 z%4}igzZPAETVm(YuXztS9aA#y{c^zx#2mHEY&YD+VVbexd(#MQcOH zt#ih{hl@g2$%2f(Ecrn2Nql0?AFfVQYJ0n*i?U~}p$cy?o8NO6ADG)V_-4IzLe5Ug z`2Kx`4<}y{pIJ={UV7HI-uaaAu2uV{9^_hm&s=Dftg&6t- z`MOppvCp_JKB{{9tF5U=_SEL`fDQJYoRlT6Oe>Dqq&3Zv-U|#kp0s6x`_+ld*kRMs zbA(6NsY{Oddi4dcng3Fo+h(6ktp7dVW_R$d2I+;sD;I5cy$p{!j%U8CnfboD^5ggO z##ybn|5=ZCpSG9Z?fKn6tMrL~6ZHljT~!@CD`9rCX?m)7+3~~ulaC#yee_hkz>HzL zIEyUWZNla4>D>G5aqJKH_;qf^&isYkst8f<(xFqUiwaK8ztJ5Uv0>J>W3TT=M%|%r zzj>~!E~8L_eQ~2a?xCg9b$XzylZ_c?ZS}>y_F=Zg%KD?_)7*MO`;!i@X`8U7hL`a? zO~D**c9juzc#-40pMs|DD2pn0DVf4H4H&#q9(ciLz1`krtnv>R9%S$u;>&t03OZ;S zm*g*Q^6Pqf0PRAI6*+9h*#_rrYuWQ|>^V^}=~=E_WU-Nv!)vR}4Bf@YSO4SN$Hm1{ ze@`SbR{Dp`$1n_?xjMoC8H{QGTp$nIb*D0z3M_ybh%R|l^do(}KfQ!v_xKNZJG3-z z*4Zrk{ONrOFZ=vo_HhXh?2fUqu{1N-^5`66G9BLCc7RMbHlAw?0C^^camaKp<5^Il z@S*Y^b68#LO%LMCW&%K^f*=k6G(Pq}t}&=X0Edm4VczgjK&L`n1Qo;~LDh(ljrzb8 zm==6AK%(dpbkfNH1cXK7e$%Jpu6z;S8Bhe7S?V-Ft~x7SfL;{>X?ChoF5vTrHD#() z5Sg8ssm{_0hRZI?%mgI#Jiz7ZY^hQKm=sc~N((4dk}O4%1uz;(@1Rr2_u-fb6<{`$ zvrxu#7yz5}&YL9(q#-XA#RD1I{ik_4Zauh_8 zB~c|KlS-{s@ZmI_G+K!)9q?u9j0^?bW&fBa!AP_mG<^>dN5e_jr1{y#lW8{ zS})x`f*i#`6X3xQ;pvYDAcwLc5qQ&~5yk&qoHL9;cmyH5HG~2=;qx_+k$V7sXa^8P zh;yOAFpm^C32$gad7v5)dBDFABiK*`W8tQfAwf?BUKrF3@eV;elo!H7oWPSpndk#W zpoMtzkf0|Nhv)r zi9QJ9F2uu;peMpt1a(8a+Ypb~2PV)*3&7q;0a}4kBI`0W)Y$;uraD6V z$qZH=orDCTx}e`Lai$`_JK=;J`3+9-cWxc{2V0z~QAt#P@lRXtf!)y>kl-{O5Ql&$ zV+@u7WrCr#LL4q2ngilPdj6}Po4^G?b~8PX(%UT&hii!PL4IewF4F6|abQDmVx0d1 D&r$0x literal 0 HcmV?d00001 diff --git a/final/test/Assembler/2002-01-24-BadSymbolTableAssert.ll b/final/test/Assembler/2002-01-24-BadSymbolTableAssert.ll new file mode 100644 index 00000000000..7c49e2bd993 --- /dev/null +++ b/final/test/Assembler/2002-01-24-BadSymbolTableAssert.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as %s -o /dev/null + +; This testcase failed due to a bad assertion in SymbolTable.cpp, removed in +; the 1.20 revision. Basically the symbol table assumed that if there was an +; abstract type in the symbol table, [in this case for the entry %foo of type +; void(opaque)* ], that there should have also been named types by now. This +; was obviously not the case here, and this is valid. Assertion disabled. + +%bb = type i32 + +declare void @foo(i32) diff --git a/final/test/Assembler/2002-01-24-ValueRefineAbsType.ll b/final/test/Assembler/2002-01-24-ValueRefineAbsType.ll new file mode 100644 index 00000000000..6e49674a32f --- /dev/null +++ b/final/test/Assembler/2002-01-24-ValueRefineAbsType.ll @@ -0,0 +1,23 @@ +; RUN: llvm-as %s -o /dev/null + +; This testcase used to fail due to a lack of this diff in Value.cpp: +; diff -r1.16 Value.cpp +; 11c11 +; < #include "llvm/Type.h" +; --- +; > #include "llvm/DerivedTypes.h" +; 74c74,76 +; < assert(Ty.get() == (const Type*)OldTy &&"Can't refine anything but my type!"); +; --- +; > assert(Ty.get() == OldTy &&"Can't refine anything but my type!"); +; > if (OldTy == NewTy && !OldTy->isAbstract()) +; > Ty.removeUserFromConcrete(); +; +; This was causing an assertion failure, due to the "foo" Method object never +; releasing it's reference to the opaque %bb value. +; + +%bb = type i32 +%exception_descriptor = type i32 + +declare void @foo(i32) diff --git a/final/test/Assembler/2002-02-19-TypeParsing.ll b/final/test/Assembler/2002-02-19-TypeParsing.ll new file mode 100644 index 00000000000..0df67849784 --- /dev/null +++ b/final/test/Assembler/2002-02-19-TypeParsing.ll @@ -0,0 +1,3 @@ +; RUN: llvm-as %s -o /dev/null + +%Hosp = type { i32, i32, i32, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* }, { \2*, { i32, i32, i32, { [4 x \3], \2, \5, %Hosp, i32, i32 }* }*, \2* } } diff --git a/final/test/Assembler/2002-03-08-NameCollision.ll b/final/test/Assembler/2002-03-08-NameCollision.ll new file mode 100644 index 00000000000..b49789b2902 --- /dev/null +++ b/final/test/Assembler/2002-03-08-NameCollision.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as %s -o /dev/null + +; Method arguments were being checked for collisions at the global scope before +; the method object was created by the parser. Because of this, false +; collisions could occur that would cause the following error message to be +; produced: +; +; Redefinition of value named 'X' in the 'int *' type plane! +; +; Fixed by delaying binding of variable names until _after_ the method symtab is +; created. +; +@X = global i32 4 ; [#uses=0] + +declare i32 @xxx(i32*) diff --git a/final/test/Assembler/2002-03-08-NameCollision2.ll b/final/test/Assembler/2002-03-08-NameCollision2.ll new file mode 100644 index 00000000000..1f7a4e16f8b --- /dev/null +++ b/final/test/Assembler/2002-03-08-NameCollision2.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as %s -o /dev/null + +; Another name collision problem. Here the problem was that if a forward +; declaration for a method was found, that this would cause spurious conflicts +; to be detected between locals and globals. +; +@Var = external global i32 ; [#uses=0] + +define void @foo() { + %Var = alloca i32 ; [#uses=0] + ret void +} diff --git a/final/test/Assembler/2002-04-04-PureVirtMethCall.ll b/final/test/Assembler/2002-04-04-PureVirtMethCall.ll new file mode 100644 index 00000000000..29aed55a3a9 --- /dev/null +++ b/final/test/Assembler/2002-04-04-PureVirtMethCall.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as %s -o /dev/null + + type { { \2 *, \4 ** }, + { \2 *, \4 ** } + } + diff --git a/final/test/Assembler/2002-04-04-PureVirtMethCall2.ll b/final/test/Assembler/2002-04-04-PureVirtMethCall2.ll new file mode 100644 index 00000000000..a0968999a92 --- /dev/null +++ b/final/test/Assembler/2002-04-04-PureVirtMethCall2.ll @@ -0,0 +1,5 @@ +; RUN: llvm-as %s -o /dev/null + +%t = type { { \2*, \2 }, + { \2*, \2 } + } diff --git a/final/test/Assembler/2002-04-05-TypeParsing.ll b/final/test/Assembler/2002-04-05-TypeParsing.ll new file mode 100644 index 00000000000..f725944b921 --- /dev/null +++ b/final/test/Assembler/2002-04-05-TypeParsing.ll @@ -0,0 +1,3 @@ +; RUN: llvm-as %s -o /dev/null + + %Hosp = type { { \2*, { \2, %Hosp }* }, { \2*, { \2, %Hosp }* } } diff --git a/final/test/Assembler/2002-04-07-HexFloatConstants.ll b/final/test/Assembler/2002-04-07-HexFloatConstants.ll new file mode 100644 index 00000000000..b0d7cc0e43a --- /dev/null +++ b/final/test/Assembler/2002-04-07-HexFloatConstants.ll @@ -0,0 +1,16 @@ +; This testcase checks to make sure that the assembler can handle floating +; point constants in IEEE hex format. This also checks that the disassembler, +; when presented with a FP constant that cannot be represented exactly in +; exponential form, outputs it correctly in hex format. This is a distillation +; of the bug that was causing the Olden Health benchmark to output incorrect +; results! +; +; RUN: opt -constprop -S > %t.1 < %s +; RUN: llvm-as < %s | llvm-dis | llvm-as | opt -constprop | \ +; RUN: llvm-dis > %t.2 +; RUN: diff %t.1 %t.2 + +define double @test() { + %tmp = fmul double 7.200000e+101, 0x427F4000 ; [#uses=1] + ret double %tmp +} diff --git a/final/test/Assembler/2002-04-07-InfConstant.ll b/final/test/Assembler/2002-04-07-InfConstant.ll new file mode 100644 index 00000000000..71837c94378 --- /dev/null +++ b/final/test/Assembler/2002-04-07-InfConstant.ll @@ -0,0 +1,9 @@ +; The output formater prints out 1.0e100 as Inf! +; +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | grep 0x7FF0000000000000 + +define float @test() { + %tmp = fmul float 0x7FF0000000000000, 1.000000e+01 ; [#uses=1] + ret float %tmp +} + diff --git a/final/test/Assembler/2002-04-29-NameBinding.ll b/final/test/Assembler/2002-04-29-NameBinding.ll new file mode 100644 index 00000000000..7960c20ddce --- /dev/null +++ b/final/test/Assembler/2002-04-29-NameBinding.ll @@ -0,0 +1,18 @@ +; There should be NO references to the global v1. The local v1 should +; have all of the references! +; +; Check by running globaldce, which will remove the constant if there are +; no references to it! +; +; RUN: opt < %s -globaldce -S | \ +; RUN: not grep constant +; + +@v1 = internal constant i32 5 + +define i32 @createtask() { + %v1 = alloca i32 ;; Alloca should have one use! + %reg112 = load i32* %v1 ;; This load should not use the global! + ret i32 %reg112 +} + diff --git a/final/test/Assembler/2002-05-02-InvalidForwardRef.ll b/final/test/Assembler/2002-05-02-InvalidForwardRef.ll new file mode 100644 index 00000000000..234545c2936 --- /dev/null +++ b/final/test/Assembler/2002-05-02-InvalidForwardRef.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as %s -o /dev/null +; It looks like the assembler is not forward resolving the function declaraion +; correctly. + +define void @test() { + call void @foo( ) + ret void +} + +declare void @foo() diff --git a/final/test/Assembler/2002-05-02-ParseError.ll b/final/test/Assembler/2002-05-02-ParseError.ll new file mode 100644 index 00000000000..5a9817c1eaa --- /dev/null +++ b/final/test/Assembler/2002-05-02-ParseError.ll @@ -0,0 +1,7 @@ +; RUN: llvm-as %s -o /dev/null + +%T = type i32 * + +define %T @test() { + ret %T null +} diff --git a/final/test/Assembler/2002-07-08-HugePerformanceProblem.ll b/final/test/Assembler/2002-07-08-HugePerformanceProblem.ll new file mode 100644 index 00000000000..52c90af18c8 --- /dev/null +++ b/final/test/Assembler/2002-07-08-HugePerformanceProblem.ll @@ -0,0 +1,67 @@ +; This file takes about 48 __MINUTES__ to assemble using as. This is WAY too +; long. The type resolution code needs to be sped up a lot. +; RUN: llvm-as %s -o /dev/null + %ALL_INTERSECTIONS_METHOD = type i32 (%OBJECT*, %RAY*, %ISTACK*)* + %BBOX = type { %BBOX_VECT, %BBOX_VECT } + %BBOX_TREE = type { i16, i16, %BBOX, %BBOX_TREE** } + %BBOX_VECT = type [3 x float] + %BLEND_MAP = type { i16, i16, i16, i32, %BLEND_MAP_ENTRY* } + %BLEND_MAP_ENTRY = type { float, i8, { %COLOUR, %PIGMENT*, %TNORMAL*, %TEXTURE*, %UV_VECT } } + %CAMERA = type { %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, double, double, i32, double, double, i32, double, %TNORMAL* } + %COLOUR = type [5 x float] + %COPY_METHOD = type i8* (%OBJECT*)* + %COUNTER = type { i32, i32 } + %DENSITY_FILE = type { i32, %DENSITY_FILE_DATA* } + %DENSITY_FILE_DATA = type { i32, i8*, i32, i32, i32, i8*** } + %DESTROY_METHOD = type void (%OBJECT*)* + %FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 } + %FILE_HANDLE = type { i8*, i32, i32, i32, i32, i8*, %FILE*, i32, i32 (%FILE_HANDLE*, i8*, i32*, i32*, i32, i32)*, void (%FILE_HANDLE*, %COLOUR*, i32)*, i32 (%FILE_HANDLE*, %COLOUR*, i32*)*, void (%IMAGE*, i8*)*, void (%FILE_HANDLE*)* } + %FINISH = type { float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, %BBOX_VECT, %BBOX_VECT } + %FOG = type { i32, double, double, double, %COLOUR, %VECTOR, %TURB*, float, %FOG* } + %FRAME = type { %CAMERA*, i32, i32, i32, %LIGHT_SOURCE*, %OBJECT*, double, double, %COLOUR, %COLOUR, %COLOUR, %IMEDIA*, %FOG*, %RAINBOW*, %SKYSPHERE* } + %FRAMESEQ = type { i32, double, i32, i32, double, i32, i32, double, i32, double, i32, double, i32, i32 } + %IMAGE = type { i32, i32, i32, i32, i32, i16, i16, %VECTOR, float, float, i32, i32, i16, %IMAGE_COLOUR*, { %IMAGE_LINE*, i8** } } + %IMAGE_COLOUR = type { i16, i16, i16, i16, i16 } + %IMAGE_LINE = type { i8*, i8*, i8*, i8* } + %IMEDIA = type { i32, i32, i32, i32, i32, double, double, i32, i32, i32, i32, %COLOUR, %COLOUR, %COLOUR, %COLOUR, double, double, double, double*, %PIGMENT*, %IMEDIA* } + %INSIDE_METHOD = type i32 (double*, %OBJECT*)* + %INTERIOR = type { i32, i32, float, float, float, float, float, %IMEDIA* } + %INTERSECTION = type { double, %VECTOR, %VECTOR, %OBJECT*, i32, i32, double, double, i8* } + %INVERT_METHOD = type void (%OBJECT*)* + %ISTACK = type { %ISTACK*, %INTERSECTION*, i32 } + %LIGHT_SOURCE = type { %METHODS*, i32, %OBJECT*, %TEXTURE*, %INTERIOR*, %OBJECT*, %OBJECT*, %BBOX, i32, %OBJECT*, %COLOUR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, %VECTOR, double, double, double, double, double, %LIGHT_SOURCE*, i8, i8, i8, i8, i32, i32, i32, i32, i32, %COLOUR**, %OBJECT*, [6 x %PROJECT_TREE_NODE*] } + %MATRIX = type [4 x %VECTOR_4D] + %METHODS = type { %ALL_INTERSECTIONS_METHOD, %INSIDE_METHOD, %NORMAL_METHOD, %COPY_METHOD, %ROTATE_METHOD, %ROTATE_METHOD, %ROTATE_METHOD, %TRANSFORM_METHOD, %DESTROY_METHOD, %DESTROY_METHOD } + %NORMAL_METHOD = type void (double*, %OBJECT*, %INTERSECTION*)* + %OBJECT = type { %METHODS*, i32, %OBJECT*, %TEXTURE*, %INTERIOR*, %OBJECT*, %OBJECT*, %BBOX, i32 } + %Opts = type { i32, i32, i8, i8, i8, i32, [150 x i8], [150 x i8], [150 x i8], [150 x i8], [150 x i8], double, double, i32, i32, double, double, i32, [25 x i8*], i32, i32, i32, double, double, i32, i32, double, double, double, i32, i32, i32, i32, i32, %FRAMESEQ, double, i32, double, double, double, double, double, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [150 x i8], %SHELLDATA*, [150 x i8], i32, i32 } + %PIGMENT = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, %COLOUR } + %PRIORITY_QUEUE = type { i32, i32, %QELEM* } + %PROJECT = type { i32, i32, i32, i32 } + %PROJECT_QUEUE = type { i32, i32, %PROJECT_TREE_NODE** } + %PROJECT_TREE_NODE = type { i16, %BBOX_TREE*, %PROJECT, i16, %PROJECT_TREE_NODE** } + %QELEM = type { double, %BBOX_TREE* } + %RAINBOW = type { double, double, double, double, double, double, double, %VECTOR, %VECTOR, %VECTOR, %PIGMENT*, %RAINBOW* } + %RAY = type { %VECTOR, %VECTOR, i32, [100 x %INTERIOR*] } + %RAYINFO = type { %VECTOR, %VECTOR, %VECTORI, %VECTORI } + %RGB = type [3 x float] + %ROTATE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %SCALE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %SHELLDATA = type { i32, i32, [250 x i8] } + %SKYSPHERE = type { i32, %PIGMENT**, %TRANSFORM* } + %SNGL_VECT = type [3 x float] + %TEXTURE = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, %TEXTURE*, %PIGMENT*, %TNORMAL*, %FINISH*, %TEXTURE*, i32 } + %TNORMAL = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float }, float } + %TPATTERN = type { i16, i16, i16, i32, float, float, float, %WARP*, %TPATTERN*, %BLEND_MAP*, { %DENSITY_FILE*, %IMAGE*, %VECTOR, float, i16, i16, i16, { float, %VECTOR }, %complex.float } } + %TRANSFORM = type { %MATRIX, %MATRIX } + %TRANSFORM_METHOD = type void (%OBJECT*, %TRANSFORM*)* + %TRANSLATE_METHOD = type void (%OBJECT*, double*, %TRANSFORM*)* + %TURB = type { i16, %WARP*, %VECTOR, i32, float, float } + %UV_VECT = type [2 x double] + %VECTOR = type [3 x double] + %VECTORI = type [3 x i32] + %VECTOR_4D = type [4 x double] + %WARP = type { i16, %WARP* } + %__FILE = type { i32, i8*, i8*, i8, i8, i32, i32, i32 } + %_h_val = type { [2 x i32], double } + %complex.float = type { float, float } diff --git a/final/test/Assembler/2002-07-14-InternalLossage.ll b/final/test/Assembler/2002-07-14-InternalLossage.ll new file mode 100644 index 00000000000..f93f1c4a5fb --- /dev/null +++ b/final/test/Assembler/2002-07-14-InternalLossage.ll @@ -0,0 +1,9 @@ +; Test to make sure that the 'internal' tag is not lost! +; +; RUN: llvm-as < %s | llvm-dis | grep internal + +declare void @foo() + +define internal void @foo() { + ret void +} diff --git a/final/test/Assembler/2002-07-14-OpaqueType.ll b/final/test/Assembler/2002-07-14-OpaqueType.ll new file mode 100644 index 00000000000..662fb0f31c1 --- /dev/null +++ b/final/test/Assembler/2002-07-14-OpaqueType.ll @@ -0,0 +1,10 @@ +; Test that opaque types are preserved correctly +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; + +%Ty = type opaque + +define %Ty* @func() { + ret %Ty* null +} + diff --git a/final/test/Assembler/2002-07-25-ParserAssertionFailure.ll b/final/test/Assembler/2002-07-25-ParserAssertionFailure.ll new file mode 100644 index 00000000000..3c5c5546b43 --- /dev/null +++ b/final/test/Assembler/2002-07-25-ParserAssertionFailure.ll @@ -0,0 +1,13 @@ +; Make sure we don't get an assertion failure, even though this is a parse +; error +; RUN: not llvm-as %s -o /dev/null |& grep {'@foo' defined with} + +%ty = type void (i32) + +declare %ty* @foo() + +define void @test() { + call %ty* @foo( ) ; <%ty*>:0 [#uses=0] + ret void +} + diff --git a/final/test/Assembler/2002-07-25-QuoteInString.ll b/final/test/Assembler/2002-07-25-QuoteInString.ll new file mode 100644 index 00000000000..facc5bdae62 --- /dev/null +++ b/final/test/Assembler/2002-07-25-QuoteInString.ll @@ -0,0 +1,5 @@ +; Test double quotes in strings work correctly! +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis +; +@str = internal global [6 x i8] c"\22foo\22\00" ; <[6 x i8]*> [#uses=0] + diff --git a/final/test/Assembler/2002-07-25-ReturnPtrFunction.ll b/final/test/Assembler/2002-07-25-ReturnPtrFunction.ll new file mode 100644 index 00000000000..515d105c14c --- /dev/null +++ b/final/test/Assembler/2002-07-25-ReturnPtrFunction.ll @@ -0,0 +1,15 @@ +; Test that returning a pointer to a function causes the disassembler to print +; the right thing. +; +; RUN: llvm-as < %s | llvm-dis | llvm-as + +%ty = type void (i32) + +declare %ty* @foo() + +define void @test() { + call %ty* ()* @foo( ) ; <%ty*>:1 [#uses=0] + ret void +} + + diff --git a/final/test/Assembler/2002-07-31-SlashInString.ll b/final/test/Assembler/2002-07-31-SlashInString.ll new file mode 100644 index 00000000000..ff48258870d --- /dev/null +++ b/final/test/Assembler/2002-07-31-SlashInString.ll @@ -0,0 +1,5 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as + +; Make sure that \\ works in a string initializer +@Slashtest = internal global [8 x i8] c"\5Cbegin{\00" + diff --git a/final/test/Assembler/2002-08-15-CastAmbiguity.ll b/final/test/Assembler/2002-08-15-CastAmbiguity.ll new file mode 100644 index 00000000000..c71652446d6 --- /dev/null +++ b/final/test/Assembler/2002-08-15-CastAmbiguity.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as %s -o /dev/null + +define void @test(i32 %X) { + call void @test( i32 6 ) + ret void +} diff --git a/final/test/Assembler/2002-08-15-ConstantExprProblem.ll b/final/test/Assembler/2002-08-15-ConstantExprProblem.ll new file mode 100644 index 00000000000..02b9ea9adb8 --- /dev/null +++ b/final/test/Assembler/2002-08-15-ConstantExprProblem.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as %s -o /dev/null + +@.LC0 = internal global [12 x i8] c"hello world\00" ; <[12 x i8]*> [#uses=1] + +define i8* @test() { +; +}; diff --git a/final/test/FrontendC++/2009-09-04-modify-crash.cpp b/final/test/FrontendC++/2009-09-04-modify-crash.cpp new file mode 100644 index 00000000000..89274e09c7e --- /dev/null +++ b/final/test/FrontendC++/2009-09-04-modify-crash.cpp @@ -0,0 +1,7 @@ +// RUN: %llvmgxx %s -fapple-kext -S -o - +// The extra check in 71555 caused this to crash on Darwin X86 +// in an assert build. +class foo { + virtual ~foo (); +}; +foo::~foo(){} diff --git a/final/test/FrontendC++/2009-09-09-packed-layout.cpp b/final/test/FrontendC++/2009-09-09-packed-layout.cpp new file mode 100644 index 00000000000..921aad79f73 --- /dev/null +++ b/final/test/FrontendC++/2009-09-09-packed-layout.cpp @@ -0,0 +1,18 @@ +// RUN: %llvmgxx -S -m32 %s -o /dev/null +class X { + public: + virtual ~X(); + short y; +}; +#pragma pack(push, 1) +class Z : public X { + public: enum { foo = ('x') }; + virtual int y() const; +}; +#pragma pack(pop) +class Y : public X { +public: enum { foo = ('y'), bar = 0 }; +}; +X x; +Y y; +Z z; diff --git a/final/test/FrontendC++/2009-10-27-crash.cpp b/final/test/FrontendC++/2009-10-27-crash.cpp new file mode 100644 index 00000000000..da73988b697 --- /dev/null +++ b/final/test/FrontendC++/2009-10-27-crash.cpp @@ -0,0 +1,43 @@ +// RUN: %llvmgxx -S %s -o /dev/null +// Radar 7328944 + +typedef struct +{ + unsigned short a : 1; + unsigned short b : 2; + unsigned short c : 1; + unsigned short d : 1; + unsigned short e : 1; + unsigned short f : 1; + unsigned short g : 2; + unsigned short : 7; + union + { + struct + { + unsigned char h : 1; + unsigned char i : 1; + unsigned char j : 1; + unsigned char : 5; + }; + struct + { + unsigned char k : 3; + unsigned char : 5; + }; + }; + unsigned char : 8; +} tt; + +typedef struct +{ + unsigned char s; + tt t; + unsigned int u; +} ttt; + +ttt X = { + 4, + { 0 }, + 55, +}; diff --git a/final/test/FrontendC++/2009-12-23-MissingSext.cpp b/final/test/FrontendC++/2009-12-23-MissingSext.cpp new file mode 100644 index 00000000000..ee978812c29 --- /dev/null +++ b/final/test/FrontendC++/2009-12-23-MissingSext.cpp @@ -0,0 +1,16 @@ +// RUN: %llvmgxx %s -S -o - | FileCheck %s +// The store of p.y into the temporary was not +// getting extended to 32 bits, so uninitialized +// bits of the temporary were used. 7366161. +struct foo { + char x:8; + signed int y:24; +}; +int bar(struct foo p, int x) { +// CHECK: bar +// CHECK: sext +// CHECK: sext + x = (p.y > x ? x : p.y); + return x; +// CHECK: return +} diff --git a/final/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp b/final/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp new file mode 100644 index 00000000000..ff45412b441 --- /dev/null +++ b/final/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -g -S %s -o - | FileCheck %s +// Here, second to last argument "i32 64" indicates that artificial type is set. +// Test to artificial attribute attahed to "this" pointer type. +// Radar 7655792 and 7655002 + +class A { +public: + int fn1(int i) const { return i + 2; }; +}; + +int foo() { + A a; + // Matching "i32 64, metadata !} ; [ DW_TAG_pointer_type ]" + // CHECK: i32 64, metadata {{![0-9]+\} ; \[ DW_TAG_pointer_type \]}} + return a.fn1(1); +} diff --git a/final/test/FrontendC++/2010-03-22-empty-baseclass.cpp b/final/test/FrontendC++/2010-03-22-empty-baseclass.cpp new file mode 100644 index 00000000000..bb741c42c84 --- /dev/null +++ b/final/test/FrontendC++/2010-03-22-empty-baseclass.cpp @@ -0,0 +1,134 @@ +// RUN: %llvmgxx -S %s -o - -O2 | FileCheck %s +namespace boost { + namespace detail { + template struct cv_traits_imp {}; + template struct cv_traits_imp {typedef T unqualified_type;}; + } +} +namespace mpl_ {} +namespace boost { + namespace mpl {using namespace mpl_;} + template< typename T > struct remove_cv {typedef typename boost::detail::cv_traits_imp::unqualified_type type;}; + namespace type_traits { + typedef char yes_type; + struct no_type {char padding[8];}; + } +} +namespace mpl_ { + template< bool C_ > struct bool_; + typedef bool_ true_; + typedef bool_ false_; + template< bool C_ > struct bool_ {static const bool value = C_;}; + template< typename T, T N > struct integral_c; +} +namespace boost{ + template struct integral_constant : + public mpl::integral_c {}; + template<> struct integral_constant : public mpl::true_ {}; + template<> struct integral_constant : public mpl::false_ {}; + namespace type_traits { + template struct ice_or; + template + struct ice_or {static const bool value = true; }; + template <> struct ice_or + {static const bool value = false;}; + template struct ice_and; + template + struct ice_and {static const bool value = false;}; + template <> struct ice_and + {static const bool value = true;}; + template struct ice_not {static const bool value = true;}; + }; + namespace detail { + template struct is_union_impl {static const bool value = false;}; + } + template< typename T > struct is_union : + ::boost::integral_constant::value> {}; + namespace detail { + template ::boost::type_traits::yes_type is_class_tester(void(U::*)(void)); + template ::boost::type_traits::no_type is_class_tester(...); + template struct is_class_impl { + static const bool value = (::boost::type_traits::ice_and< sizeof(is_class_tester(0)) + == sizeof(::boost::type_traits::yes_type), + ::boost::type_traits::ice_not< ::boost::is_union::value >::value >::value);}; +} + template struct is_class: + ::boost::integral_constant::value> { }; +namespace detail { + template struct empty_helper_t1: public T {int i[256];}; + struct empty_helper_t2 {int i[256];}; + template struct empty_helper + {static const bool value = false;}; + template struct empty_helper + {static const bool value = (sizeof(empty_helper_t1) == sizeof(empty_helper_t2));}; + template struct is_empty_impl { + typedef typename remove_cv::type cvt; + static const bool value = (::boost::type_traits::ice_or< ::boost::detail::empty_helper + ::value>::value, false>::value); + }; +} +template struct is_empty: +::boost::integral_constant::value> {}; +template struct is_same: +::boost::integral_constant {}; +template struct call_traits {typedef T& reference;}; +namespace details { + template + struct compressed_pair_switch; + template + struct compressed_pair_switch + {static const int value = 1;}; + template class compressed_pair_imp; + template class compressed_pair_imp: + protected ::boost::remove_cv::type { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + first_reference first() {return *this;} + second_reference second() {return second_;} + second_type second_; + }; +} +template class compressed_pair: + private ::boost::details::compressed_pair_imp::type, + typename remove_cv::type>::value, + ::boost::is_empty::value, ::boost::is_empty::value>::value> + { + private: + typedef details::compressed_pair_imp::type, + typename remove_cv::type>::value, + ::boost::is_empty::value, ::boost::is_empty::value>::value> base; + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + first_reference first() {return base::first();} + second_reference second() {return base::second();} + }; +} +struct empty_base_t {}; +struct empty_t : empty_base_t {}; +typedef boost::compressed_pair data_t; +extern "C" {int printf(const char * , ...);} +extern "C" {void abort(void);} +int main (int argc, char * const argv[]) { + data_t x; + x.second() = -3; + // This store should be elided: + x.first() = empty_t(); + // If x.second() has been clobbered by the elided store, fail. + if (x.second() != -3) { + printf("x.second() was clobbered\n"); + // CHECK-NOT: x.second() was clobbered + abort(); + } + return 0; +} +// CHECK: ret i32 diff --git a/final/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp b/final/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp new file mode 100644 index 00000000000..761c0dc097a --- /dev/null +++ b/final/test/FrontendC++/2010-04-30-OptimizedMethod-Dbg.cpp @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -g -S -O2 %s -o - | FileCheck %s + +class foo { +public: + int bar(int x); + static int baz(int x); +}; + +int foo::bar(int x) { + // CHECK: {{i32 [0-9]+, i1 true(, i[0-9]+ [^\}]+[}]|[}]) ; \[ DW_TAG_subprogram \]}} + return x*4 + 1; +} + +int foo::baz(int x) { + // CHECK: {{i32 [0-9]+, i1 true(, i[0-9]+ [^\},]+[}]|[}]) ; \[ DW_TAG_subprogram \]}} + return x*4 + 1; +} + diff --git a/final/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp b/final/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp new file mode 100644 index 00000000000..e6165c0cce2 --- /dev/null +++ b/final/test/FrontendC++/2010-05-10-Var-DbgInfo.cpp @@ -0,0 +1,43 @@ +// RUN: %llvmgcc -S -O0 -g %s -o /dev/null +// PR 7104 + +struct A { + int Ai; +}; + +struct B : public A {}; +struct C : public B {}; + +const char * f(int C::*){ return ""; } +int f(int B::*) { return 1; } + +struct D : public C {}; + +const char * g(int B::*){ return ""; } +int g(int D::*) { return 1; } + +void test() +{ + int i = f(&A::Ai); + + const char * str = g(&A::Ai); +} + +// conversion of B::* to C::* is better than conversion of A::* to C::* +typedef void (A::*pmfa)(); +typedef void (B::*pmfb)(); +typedef void (C::*pmfc)(); + +struct X { + operator pmfa(); + operator pmfb(); +}; + + +void g(pmfc); + +void test2(X x) +{ + g(x); +} + diff --git a/final/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp b/final/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp new file mode 100644 index 00000000000..9203dbd0bd9 --- /dev/null +++ b/final/test/FrontendC++/2010-05-11-alwaysinlineinstantiation.cpp @@ -0,0 +1,31 @@ +// RUN: %llvmgxx -xc++ %s -S -o - | not grep ZN12basic_stringIcEC1Ev +// RUN: %llvmgxx -xc++ %s -S -o - | grep ZN12basic_stringIcED1Ev | count 2 + +template +class basic_string +{ +public: + basic_string(); + ~basic_string(); +}; + +template +__attribute__ ((__visibility__("hidden"), __always_inline__)) inline +basic_string::basic_string() +{ +} + +template +inline +basic_string::~basic_string() +{ +} + +typedef basic_string string; + +extern template class basic_string; + +int main() +{ + string s; +} diff --git a/final/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp b/final/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp new file mode 100644 index 00000000000..c2d6abe97fc --- /dev/null +++ b/final/test/FrontendC++/2010-05-12-PtrToMember-Dbg.cpp @@ -0,0 +1,17 @@ +//RUN: %llvmgxx -O0 -S -g -o - %s | grep DW_TAG_auto_variable +class Foo +{ + public: + int x; + int y; + Foo (int i, int j) { x = i; y = j; } +}; + + +Foo foo(10, 11); + +int main() { + int Foo::* pmi = &Foo::y; + return foo.*pmi; +} + diff --git a/final/test/FrontendC++/2010-06-21-LocalVarDbg.cpp b/final/test/FrontendC++/2010-06-21-LocalVarDbg.cpp new file mode 100644 index 00000000000..48d821508dd --- /dev/null +++ b/final/test/FrontendC++/2010-06-21-LocalVarDbg.cpp @@ -0,0 +1,13 @@ +// RUN: %llvmgxx -g -Os -S %s -o - | llvm-as -disable-output +// Do not use function name to create named metadata used to hold +// local variable info. For example. llvm.dbg.lv.~A is an invalid name. +class A { +public: + ~A() { int i = 0; i++; } +}; + +int foo(int i) { + A a; + return 0; +} + diff --git a/final/test/FrontendC++/2010-06-22-BitfieldInit.cpp b/final/test/FrontendC++/2010-06-22-BitfieldInit.cpp new file mode 100644 index 00000000000..8dceb78bfc6 --- /dev/null +++ b/final/test/FrontendC++/2010-06-22-BitfieldInit.cpp @@ -0,0 +1,20 @@ +// RUN: %llvmgxx -g -S %s +struct TEST2 +{ + int subid:32; + int :0; +}; + +typedef struct _TEST3 +{ + TEST2 foo; + TEST2 foo2; +} TEST3; + +TEST3 test = + { + {0}, + {0} + }; + +int main() { return 0; } diff --git a/final/test/FrontendC++/2010-06-22-ZeroBitfield.cpp b/final/test/FrontendC++/2010-06-22-ZeroBitfield.cpp new file mode 100644 index 00000000000..9c4f2629f74 --- /dev/null +++ b/final/test/FrontendC++/2010-06-22-ZeroBitfield.cpp @@ -0,0 +1,5 @@ +// RUN: %llvmgxx -g -S %s +struct s8_0 { unsigned : 0; }; +struct s8_1 { double x; }; +struct s8 { s8_0 a; s8_1 b; }; +s8 f8() { return s8(); } diff --git a/final/test/FrontendC++/2010-07-19-nowarn.cpp b/final/test/FrontendC++/2010-07-19-nowarn.cpp new file mode 100644 index 00000000000..a61a84ff28b --- /dev/null +++ b/final/test/FrontendC++/2010-07-19-nowarn.cpp @@ -0,0 +1,21 @@ +// RUN: %llvmgcc %s -S -m32 -fasm-blocks -o /dev/null +// This should not warn about unreferenced label. 8195660. +// XFAIL: * +// XTARGET: x86,i386,i686 + +void quarterAsm(int array[], int len) +{ + __asm + { + mov esi, array; + mov ecx, len; + shr ecx, 2; +loop: + movdqa xmm0, [esi]; + psrad xmm0, 2; + movdqa [esi], xmm0; + add esi, 16; + sub ecx, 1; + jnz loop; + } +} diff --git a/final/test/FrontendC++/2010-07-23-DeclLoc.cpp b/final/test/FrontendC++/2010-07-23-DeclLoc.cpp new file mode 100644 index 00000000000..9bf432beb72 --- /dev/null +++ b/final/test/FrontendC++/2010-07-23-DeclLoc.cpp @@ -0,0 +1,86 @@ +// RUN: %llvmgxx -S -g %s -o - | FileCheck %s +// Require the template function declaration refer to the correct filename. +// First, locate the function decl in metadata, and pluck out the file handle: +// CHECK: {{extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*extract_dwarf_data_from_header.*[^ ]+", metadata !}}[[filehandle:[0-9]+]], +// Second: Require that filehandle refer to the correct filename: +// CHECK: {{^!}}[[filehandle]] = metadata {{![{].*}} metadata !"decl_should_be_here.hpp", +typedef long unsigned int __darwin_size_t; +typedef __darwin_size_t size_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +namespace std { + template class auto_ptr { + _Tp* _M_ptr; + public: + typedef _Tp element_type; + auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } + element_type& operator*() const throw() { } + }; +} +class Pointer32 { +public: + typedef uint32_t ptr_t; + typedef uint32_t size_t; +}; +class Pointer64 { +public: + typedef uint64_t ptr_t; + typedef uint64_t size_t; +}; +class BigEndian {}; +class LittleEndian {}; +template class SizeAndEndianness { +public: + typedef _SIZE SIZE; +}; +typedef SizeAndEndianness ISA32Little; +typedef SizeAndEndianness ISA32Big; +typedef SizeAndEndianness ISA64Little; +typedef SizeAndEndianness ISA64Big; +template class TRange { +protected: + typename SIZE::ptr_t _location; + typename SIZE::size_t _length; + TRange(typename SIZE::ptr_t location, typename SIZE::size_t length) : _location(location), _length(length) { } +}; +template class TRangeValue : public TRange { + T _value; +public: + TRangeValue(typename SIZE::ptr_t location, typename SIZE::size_t length, T value) : TRange(location, length), _value(value) {}; +}; +template class TAddressRelocator {}; +class CSCppSymbolOwner{}; +class CSCppSymbolOwnerData{}; +template class TRawSymbolOwnerData +{ + TRangeValue< SIZE, uint8_t* > _TEXT_text_section; + const char* _dsym_path; + uint32_t _dylib_current_version; + uint32_t _dylib_compatibility_version; +public: + TRawSymbolOwnerData() : + _TEXT_text_section(0, 0, __null), _dsym_path(__null), _dylib_current_version(0), _dylib_compatibility_version(0) {} +}; +template class TExtendedMachOHeader {}; +# 16 "decl_should_be_here.hpp" +template void extract_dwarf_data_from_header(TExtendedMachOHeader& header, + TRawSymbolOwnerData& symbol_owner_data, + TAddressRelocator* address_relocator) {} +struct CSCppSymbolOwnerHashFunctor { + size_t operator()(const CSCppSymbolOwner& symbol_owner) const { +# 97 "wrong_place_for_decl.cpp" + } +}; +template CSCppSymbolOwnerData* create_symbol_owner_data_arch_specific(CSCppSymbolOwner* symbol_owner, const char* dsym_path) { + typedef typename SIZE_AND_ENDIANNESS::SIZE SIZE; + std::auto_ptr< TRawSymbolOwnerData > data(new TRawSymbolOwnerData()); + std::auto_ptr< TExtendedMachOHeader > header; + extract_dwarf_data_from_header(*header, *data, (TAddressRelocator*)__null); +} +CSCppSymbolOwnerData* create_symbol_owner_data2(CSCppSymbolOwner* symbol_owner, const char* dsym_path) { + create_symbol_owner_data_arch_specific< ISA32Little >(symbol_owner, dsym_path); + create_symbol_owner_data_arch_specific< ISA32Big >(symbol_owner, dsym_path); + create_symbol_owner_data_arch_specific< ISA64Little >(symbol_owner, dsym_path); + create_symbol_owner_data_arch_specific< ISA64Big >(symbol_owner, dsym_path); +} diff --git a/final/test/FrontendC++/2010-08-31-ByValArg.cpp b/final/test/FrontendC++/2010-08-31-ByValArg.cpp new file mode 100644 index 00000000000..be0d354b1d9 --- /dev/null +++ b/final/test/FrontendC++/2010-08-31-ByValArg.cpp @@ -0,0 +1,53 @@ +// This regression test checks byval arguments' debug info. +// Radar 8367011 +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o %t.s -O0 -relocation-model=pic +// RUN: %compile_c %t.s -o %t.o +// RUN: %link %t.o -o %t.exe +// RUN: echo {break get\nrun\np missing_arg.b} > %t.in +// RUN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \ +// RUN: grep {1 = 4242} + +// XTARGET: x86_64-apple-darwin + +class EVT { +public: + int a; + int b; + int c; +}; + +class VAL { +public: + int x; + int y; +}; +void foo(EVT e); +EVT bar(); + +void get(int *i, unsigned dl, VAL v, VAL *p, unsigned n, EVT missing_arg) { +//CHECK: .ascii "missing_arg" + EVT e = bar(); + if (dl == n) + foo(missing_arg); +} + + +EVT bar() { + EVT e; + return e; +} + +void foo(EVT e) {} + +int main(){ + VAL v; + EVT ma; + ma.a = 1; + ma.b = 4242; + ma.c = 3; + int i = 42; + get (&i, 1, v, &v, 2, ma); + return 0; +} + diff --git a/final/test/FrontendC++/alignstack.cpp b/final/test/FrontendC++/alignstack.cpp new file mode 100644 index 00000000000..4f993d669bf --- /dev/null +++ b/final/test/FrontendC++/alignstack.cpp @@ -0,0 +1,23 @@ +// RUN: %llvmgxx %s -fasm-blocks -S -o - | FileCheck %s +// Complicated expression as jump target +// XFAIL: * +// XTARGET: x86,i386,i686,darwin + +void Method3() +{ +// CHECK: Method3 +// CHECK-NOT: alignstack + asm("foo:"); +// CHECK: return +} + +void Method4() +{ +// CHECK: Method4 +// CHECK: alignstack + asm { + bar: + } +// CHECK: return +} + diff --git a/final/test/FrontendC++/dg.exp b/final/test/FrontendC++/dg.exp new file mode 100644 index 00000000000..fc852e30acf --- /dev/null +++ b/final/test/FrontendC++/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if [ llvm_gcc_supports c++ ] then { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] +} diff --git a/final/test/FrontendC++/integration-O2.cpp b/final/test/FrontendC++/integration-O2.cpp new file mode 100644 index 00000000000..bb65ac21033 --- /dev/null +++ b/final/test/FrontendC++/integration-O2.cpp @@ -0,0 +1,19 @@ +// RUN: %llvmgxx %s -O2 -S -o - | FileCheck %s + +// This test verifies that we get expected codegen out of the -O2 optimization +// level from the full optimizer. + + + +// Verify that ipsccp is running and can eliminate globals. +static int test1g = 42; +void test1f1() { + if (test1g == 0) test1g = 0; +} +int test1f2() { + return test1g; +} + +// CHECK: @_Z7test1f2v() +// CHECK: entry: +// CHECK-NEXT: ret i32 42 diff --git a/final/test/FrontendC++/m64-ptr.cpp b/final/test/FrontendC++/m64-ptr.cpp new file mode 100644 index 00000000000..f91e2f4f858 --- /dev/null +++ b/final/test/FrontendC++/m64-ptr.cpp @@ -0,0 +1,19 @@ +// RUN: %llvmgxx %s -S -o - | FileCheck %s +// XFAIL: powerpc-apple-darwin + +// Make sure pointers are passed as pointers, not converted to int. +// The first load should be of type i8** in either 32 or 64 bit mode. +// This formerly happened on x86-64, 7375899. + +class StringRef { +public: + const char *Data; + long Len; +}; +void foo(StringRef X); +void bar(StringRef &A) { +// CHECK: @_Z3barR9StringRef +// CHECK: load i8** + foo(A); +// CHECK: ret void +} diff --git a/final/test/FrontendC++/member-alignment.cpp b/final/test/FrontendC++/member-alignment.cpp new file mode 100644 index 00000000000..c5b20b27932 --- /dev/null +++ b/final/test/FrontendC++/member-alignment.cpp @@ -0,0 +1,20 @@ +// RUN: %llvmgxx -S %s -o - | FileCheck %s +// XFAIL: arm,powerpc + +// rdar://7268289 + +class t { +public: + virtual void foo(void); + void bar(void); +}; + +void +t::bar(void) { +// CHECK: _ZN1t3barEv{{.*}} align 2 +} + +void +t::foo(void) { +// CHECK: _ZN1t3fooEv{{.*}} align 2 +} diff --git a/final/test/FrontendC++/ptr-to-method-devirt.cpp b/final/test/FrontendC++/ptr-to-method-devirt.cpp new file mode 100644 index 00000000000..a5ca5c76559 --- /dev/null +++ b/final/test/FrontendC++/ptr-to-method-devirt.cpp @@ -0,0 +1,14 @@ +// PR1602 +// RUN: %llvmgxx -S %s -o - -O3 | not grep ptrtoint +// RUN: %llvmgxx -S %s -o - -O3 | grep getelementptr | count 1 + + +struct S { virtual void f(); }; + +typedef void (S::*P)(void); + +const P p = &S::f; + +void g(S s) { + (s.*p)(); + } diff --git a/final/test/FrontendC++/thunk-linkonce-odr.cpp b/final/test/FrontendC++/thunk-linkonce-odr.cpp new file mode 100644 index 00000000000..ad72e64aa86 --- /dev/null +++ b/final/test/FrontendC++/thunk-linkonce-odr.cpp @@ -0,0 +1,33 @@ +// RUN: %llvmgxx %s -S -o - | FileCheck %s +// & + +struct A { + virtual int f() { return 1; } +}; + +struct B { + virtual int f() { return 2; } +}; + +struct C : A, B { + virtual int f() { return 3; } +}; + +struct D : C { + virtual int f() { return 4; } +}; + +static int f(D* d) { + B* b = d; + return b->f(); +}; + +int g() { + D d; + return f(&d); +} + +// Thunks should be marked as "linkonce ODR" not "weak". +// +// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1C1fEv +// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv diff --git a/final/test/FrontendC++/varargs.cpp b/final/test/FrontendC++/varargs.cpp new file mode 100644 index 00000000000..c4de76acc30 --- /dev/null +++ b/final/test/FrontendC++/varargs.cpp @@ -0,0 +1,19 @@ +// RUN: %llvmgxx -S %s -o - | FileCheck %s +// rdar://7309675 +// PR4678 + +// test1 should be compmiled to be a varargs function in the IR even +// though there is no way to do a va_begin. Otherwise, the optimizer +// will warn about 'dropped arguments' at the call site. + +// CHECK: define i32 @_Z5test1z(...) +int test1(...) { + return -1; +} + +// CHECK: call i32 (...)* @_Z5test1z(i32 0) +void test() { + test1(0); +} + + diff --git a/final/test/FrontendC++/weak-external.cpp b/final/test/FrontendC++/weak-external.cpp new file mode 100644 index 00000000000..f4f0ba19ef3 --- /dev/null +++ b/final/test/FrontendC++/weak-external.cpp @@ -0,0 +1,17 @@ +// RUN: %llvmgxx %s -S -O2 -o - | not grep {_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag} +// PR4262 + +// The "basic_string" extern template instantiation declaration is supposed to +// suppress the implicit instantiation of non-inline member functions. Make sure +// that we suppress the implicit instantiation of non-inline member functions +// defined out-of-line. That we aren't instantiating the basic_string +// constructor when we shouldn't be. Such an instantiation forces the implicit +// instantiation of _S_construct. Since _S_construct is a member +// template, it's instantiation is *not* suppressed (despite being in +// basic_string), so we would emit it as a weak definition. + +#include + +void dummysymbol() { + throw(std::runtime_error("string")); +} diff --git a/final/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp b/final/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp new file mode 100644 index 00000000000..f81854e0cb9 --- /dev/null +++ b/final/test/FrontendC++/x86-64-abi-sret-vs-2word-struct-param.cpp @@ -0,0 +1,27 @@ +// RUN: %llvmgxx -S %s -o - | grep byval | count 2 +// XTARGET: x86 +// PR4242 +// (PR 4242 bug is on 64-bit only, test passes on x86-32 as well) + +struct S { + void* data[3]; +}; + +struct T { + void* data[2]; +}; + +extern "C" S fail(int, int, int, int, T t, void* p) { + S s; + s.data[0] = t.data[0]; + s.data[1] = t.data[1]; + s.data[2] = p; + return s; +} + +extern "C" S* succeed(S* sret, int, int, int, int, T t, void* p) { + sret->data[0] = t.data[0]; + sret->data[1] = t.data[1]; + sret->data[2] = p; + return sret; +} diff --git a/final/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c b/final/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c new file mode 100644 index 00000000000..1779a99942e --- /dev/null +++ b/final/test/FrontendC/2002-01-23-LoadQISIReloadFailure.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* Regression test. Just compile .c -> .ll to test */ +int foo(void) { + unsigned char *pp; + unsigned w_cnt; + + w_cnt += *pp; + + return w_cnt; +} diff --git a/final/test/FrontendC/2002-01-24-ComplexSpaceInType.c b/final/test/FrontendC/2002-01-24-ComplexSpaceInType.c new file mode 100644 index 00000000000..13d92c7306e --- /dev/null +++ b/final/test/FrontendC/2002-01-24-ComplexSpaceInType.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +// This caused generation of the following type name: +// %Array = uninitialized global [10 x %complex int] +// +// which caused problems because of the space int the complex int type +// + +struct { int X, Y; } Array[10]; + +void foo() {} diff --git a/final/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c b/final/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c new file mode 100644 index 00000000000..e619cf46992 --- /dev/null +++ b/final/test/FrontendC/2002-01-24-HandleCallInsnSEGV.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void *dlclose(void*); + +void ap_os_dso_unload(void *handle) +{ + dlclose(handle); + return; /* This return triggers the bug: Weird */ +} diff --git a/final/test/FrontendC/2002-02-13-ConditionalInCall.c b/final/test/FrontendC/2002-02-13-ConditionalInCall.c new file mode 100644 index 00000000000..f361088c1cf --- /dev/null +++ b/final/test/FrontendC/2002-02-13-ConditionalInCall.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* Test problem where bad code was generated with a ?: statement was + in a function call argument */ + +void foo(int, double, float); + +void bar(int x) { + foo(x, x ? 1.0 : 12.5, 1.0f); +} + diff --git a/final/test/FrontendC/2002-02-13-ReloadProblem.c b/final/test/FrontendC/2002-02-13-ReloadProblem.c new file mode 100644 index 00000000000..2ae97b72276 --- /dev/null +++ b/final/test/FrontendC/2002-02-13-ReloadProblem.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* This triggered a problem in reload, fixed by disabling most of the + * steps of compilation in GCC. Before this change, the code went through + * the entire backend of GCC, even though it was unnecessary for LLVM output + * now it is skipped entirely, and since reload doesn't run, it can't cause + * a problem. + */ + +extern int tolower(int); + +const char *rangematch(const char *pattern, int test, int c) { + + if ((c <= test) | (tolower(c) <= tolower((unsigned char)test))) + return 0; + + return pattern; +} diff --git a/final/test/FrontendC/2002-02-13-TypeVarNameCollision.c b/final/test/FrontendC/2002-02-13-TypeVarNameCollision.c new file mode 100644 index 00000000000..2dede68a38d --- /dev/null +++ b/final/test/FrontendC/2002-02-13-TypeVarNameCollision.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* This testcase causes a symbol table collision. Type names and variable + * names should be in distinct namespaces + */ + +typedef struct foo { + int X, Y; +} FOO; + +static FOO foo[100]; + +int test() { + return foo[4].Y; +} + diff --git a/final/test/FrontendC/2002-02-13-UnnamedLocal.c b/final/test/FrontendC/2002-02-13-UnnamedLocal.c new file mode 100644 index 00000000000..85aa615205c --- /dev/null +++ b/final/test/FrontendC/2002-02-13-UnnamedLocal.c @@ -0,0 +1,21 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* Testcase for a problem where GCC allocated xqic to a register, + * and did not have a VAR_DECL that explained the stack slot to LLVM. + * Now the LLVM code synthesizes a stack slot if one is presented that + * has not been previously recognized. This is where alloca's named + * 'local' come from now. + */ + +typedef struct { + short x; +} foostruct; + +int foo(foostruct ic); + +void test() { + foostruct xqic; + foo(xqic); +} + + diff --git a/final/test/FrontendC/2002-02-14-EntryNodePreds.c b/final/test/FrontendC/2002-02-14-EntryNodePreds.c new file mode 100644 index 00000000000..851af912174 --- /dev/null +++ b/final/test/FrontendC/2002-02-14-EntryNodePreds.c @@ -0,0 +1,37 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC Used to generate code that contained a branch to the entry node of + * the do_merge function. This is illegal LLVM code. To fix this, GCC now + * inserts an entry node regardless of whether or not it has to insert allocas. + */ + +struct edge_rec +{ + struct VERTEX *v; + struct edge_rec *next; + int wasseen; + int more_data; +}; + +typedef struct edge_rec *QUAD_EDGE; + +typedef struct { + QUAD_EDGE left, right; +} EDGE_PAIR; + +struct EDGE_STACK { + int ptr; + QUAD_EDGE *elts; + int stack_size; +}; + +int do_merge(QUAD_EDGE ldo, QUAD_EDGE rdo) { + int lvalid; + QUAD_EDGE basel,rcand; + while (1) { + if (!lvalid) { + return (int)basel->next; + } + } +} + diff --git a/final/test/FrontendC/2002-02-16-RenamingTest.c b/final/test/FrontendC/2002-02-16-RenamingTest.c new file mode 100644 index 00000000000..6042b67dc0c --- /dev/null +++ b/final/test/FrontendC/2002-02-16-RenamingTest.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* test that locals are renamed with . notation */ + +void abc(void *); + +void Test5(double X) { + abc(&X); + { + int X; + abc(&X); + { + float X; + abc(&X); + } + } +} + diff --git a/final/test/FrontendC/2002-02-17-ArgumentAddress.c b/final/test/FrontendC/2002-02-17-ArgumentAddress.c new file mode 100644 index 00000000000..acd7e37a756 --- /dev/null +++ b/final/test/FrontendC/2002-02-17-ArgumentAddress.c @@ -0,0 +1,39 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int test(int X) { + return X; +} + +void abc(int *X); +int def(int Y, int Z) { + abc(&Z); + return Y; +} + +struct Test { short X, x; int Y, Z; }; + +int Testing(struct Test *A) { + return A->X+A->Y; +} + +int Test2(int X, struct Test A, int Y) { + return X+Y+A.X+A.Y; +} +int Test3(struct Test A, struct Test B) { + return A.X+A.Y+B.Y+B.Z; +} + +struct Test Test4(struct Test A) { + return A; +} + +int Test6() { + int B[200]; + return B[4]; +} + +struct STest2 { int X; short Y[4]; double Z; }; + +struct STest2 Test7(struct STest2 X) { + return X; +} diff --git a/final/test/FrontendC/2002-02-18-64bitConstant.c b/final/test/FrontendC/2002-02-18-64bitConstant.c new file mode 100644 index 00000000000..a88587a960d --- /dev/null +++ b/final/test/FrontendC/2002-02-18-64bitConstant.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC wasn't handling 64 bit constants right fixed */ + +#include + +int main() { + long long Var = 123455678902ll; + printf("%lld\n", Var); +} diff --git a/final/test/FrontendC/2002-02-18-StaticData.c b/final/test/FrontendC/2002-02-18-StaticData.c new file mode 100644 index 00000000000..76cb0e670a7 --- /dev/null +++ b/final/test/FrontendC/2002-02-18-StaticData.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +double FOO = 17; +double BAR = 12.0; +float XX = 12.0f; + +static char *procnames[] = { + "EXIT" +}; + +void *Data[] = { &FOO, &BAR, &XX }; + diff --git a/final/test/FrontendC/2002-03-11-LargeCharInString.c b/final/test/FrontendC/2002-03-11-LargeCharInString.c new file mode 100644 index 00000000000..b383d03f799 --- /dev/null +++ b/final/test/FrontendC/2002-03-11-LargeCharInString.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include + +int test(char *X) { + /* LLVM-GCC used to emit: + %.LC0 = internal global [3 x sbyte] c"\1F\FFFFFF8B\00" + */ + return strcmp(X, "\037\213"); +} diff --git a/final/test/FrontendC/2002-03-12-ArrayInitialization.c b/final/test/FrontendC/2002-03-12-ArrayInitialization.c new file mode 100644 index 00000000000..1997a3cd0d9 --- /dev/null +++ b/final/test/FrontendC/2002-03-12-ArrayInitialization.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC would generate bad code if not enough initializers are + specified for an array. + */ + +int a[10] = { 0, 2}; + +char str[10] = "x"; + +void *Arr[5] = { 0, 0 }; + +float F[12] = { 1.23f, 34.7f }; + +struct Test { int X; double Y; }; + +struct Test Array[10] = { { 2, 12.0 }, { 3, 24.0 } }; + +int B[4][4] = { { 1, 2, 3, 4}, { 5, 6, 7 }, { 8, 9 } }; diff --git a/final/test/FrontendC/2002-03-12-StructInitialize.c b/final/test/FrontendC/2002-03-12-StructInitialize.c new file mode 100644 index 00000000000..9eb11e187a1 --- /dev/null +++ b/final/test/FrontendC/2002-03-12-StructInitialize.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +typedef struct Connection_Type { + long to; + char type[10]; + long length; +} Connection; + +Connection link[3] += { {1, "link1", 10}, + {2, "link2", 20}, + {3, "link3", 30} }; + diff --git a/final/test/FrontendC/2002-03-12-StructInitializer.c b/final/test/FrontendC/2002-03-12-StructInitializer.c new file mode 100644 index 00000000000..fa333b78a95 --- /dev/null +++ b/final/test/FrontendC/2002-03-12-StructInitializer.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC was not emitting string constants of the correct length when + * embedded into a structure field like this. It thought the strlength + * was -1. + */ + +typedef struct Connection_Type { + long to; + char type[10]; + long length; +} Connection; + +Connection link[3] += { {1, "link1", 10}, + {2, "link2", 20}, + {3, "link3", 30} }; + diff --git a/final/test/FrontendC/2002-03-14-BrokenPHINode.c b/final/test/FrontendC/2002-03-14-BrokenPHINode.c new file mode 100644 index 00000000000..48d9ab705a7 --- /dev/null +++ b/final/test/FrontendC/2002-03-14-BrokenPHINode.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC was generating PHI nodes with an arity < #pred of the basic block the + * PHI node lived in. This was breaking LLVM because the number of entries + * in a PHI node must equal the number of predecessors for a basic block. + */ + +int trys(char *s, int x) +{ + int asa; + double Val; + int LLS; + if (x) { + asa = LLS + asa; + } else { + } + return asa+(int)Val; +} + diff --git a/final/test/FrontendC/2002-03-14-BrokenSSA.c b/final/test/FrontendC/2002-03-14-BrokenSSA.c new file mode 100644 index 00000000000..9dc674aea27 --- /dev/null +++ b/final/test/FrontendC/2002-03-14-BrokenSSA.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* This code used to break GCC's SSA computation code. It would create + uses of B & C that are not dominated by their definitions. See: + http://gcc.gnu.org/ml/gcc/2002-03/msg00697.html + */ +int bar(); +int foo() +{ + int a,b,c; + + a = b + c; + b = bar(); + c = bar(); + return a + b + c; +} + diff --git a/final/test/FrontendC/2002-03-14-QuotesInStrConst.c b/final/test/FrontendC/2002-03-14-QuotesInStrConst.c new file mode 100644 index 00000000000..63eaeef46a4 --- /dev/null +++ b/final/test/FrontendC/2002-03-14-QuotesInStrConst.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC was not escaping quotes in string constants correctly, so this would + * get emitted: + * %.LC1 = internal global [32 x sbyte] c"*** Word "%s" on line %d is not\00" + */ + +const char *Foo() { + return "*** Word \"%s\" on line %d is not"; +} diff --git a/final/test/FrontendC/2002-04-07-SwitchStmt.c b/final/test/FrontendC/2002-04-07-SwitchStmt.c new file mode 100644 index 00000000000..33e9c3d7a78 --- /dev/null +++ b/final/test/FrontendC/2002-04-07-SwitchStmt.c @@ -0,0 +1,22 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int printf(const char *, ...); +int foo(); + +int main() { + while (foo()) { + switch (foo()) { + case 0: + case 1: + case 2: + case 3: + printf("3"); + case 4: printf("4"); + case 5: + case 6: + default: + break; + } + } + return 0; +} diff --git a/final/test/FrontendC/2002-04-08-LocalArray.c b/final/test/FrontendC/2002-04-08-LocalArray.c new file mode 100644 index 00000000000..1dc51a09284 --- /dev/null +++ b/final/test/FrontendC/2002-04-08-LocalArray.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* GCC is not outputting the static array to the LLVM backend, so bad things + * happen. Note that if this is defined static, everything seems fine. + */ +double test(unsigned X) { + double student_t[30]={0.0 , 12.706 , 4.303 , 3.182 , 2.776 , 2.571 , + 2.447 , 2.365 , 2.306 , 2.262 , 2.228 , + 2.201 , 2.179 , 2.160 , 2.145 , 2.131 , + 2.120 , 2.110 , 2.101 , 2.093 , 2.086 , + 2.080 , 2.074 , 2.069 , 2.064 , 2.060 , + 2.056 , 2.052 , 2.048 , 2.045 }; + return student_t[X]; +} diff --git a/final/test/FrontendC/2002-04-09-StructRetVal.c b/final/test/FrontendC/2002-04-09-StructRetVal.c new file mode 100644 index 00000000000..de3b6fc26e0 --- /dev/null +++ b/final/test/FrontendC/2002-04-09-StructRetVal.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct S { + int i; + short s1, s2; +}; + +struct S func_returning_struct(void); + +void loop(void) { + func_returning_struct(); +} diff --git a/final/test/FrontendC/2002-04-10-StructParameters.c b/final/test/FrontendC/2002-04-10-StructParameters.c new file mode 100644 index 00000000000..aaaba2abdde --- /dev/null +++ b/final/test/FrontendC/2002-04-10-StructParameters.c @@ -0,0 +1,25 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +typedef struct { + char p; + short q; + char r; + int X; + short Y, Z; + int Q; +} foo; + +int test(foo X, float); +int testE(char,short,char,int,int,float); +void test3(foo *X) { + X->q = 1; +} + +void test2(foo Y) { + testE(Y.p, Y.q, Y.r, Y.X, Y.Y, 0.1f); + test(Y, 0.1f); + test2(Y); + test3(&Y); +} + diff --git a/final/test/FrontendC/2002-05-23-StaticValues.c b/final/test/FrontendC/2002-05-23-StaticValues.c new file mode 100644 index 00000000000..a5753b95f16 --- /dev/null +++ b/final/test/FrontendC/2002-05-23-StaticValues.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* Make sure the frontend is correctly marking static stuff as internal! */ + +int X; +static int Y = 12; + +static void foo(int Z) { + Y = Z; +} + +void *test() { + foo(12); + return &Y; +} diff --git a/final/test/FrontendC/2002-05-23-TypeNameCollision.c b/final/test/FrontendC/2002-05-23-TypeNameCollision.c new file mode 100644 index 00000000000..25d114965d4 --- /dev/null +++ b/final/test/FrontendC/2002-05-23-TypeNameCollision.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* Testcase for when struct tag conflicts with typedef name... grr */ + +typedef struct foo { + struct foo *X; + int Y; +} * foo; + +foo F1; +struct foo *F2; + +enum bar { test1, test2 }; + +typedef float bar; + +enum bar B1; +bar B2; + diff --git a/final/test/FrontendC/2002-05-24-Alloca.c b/final/test/FrontendC/2002-05-24-Alloca.c new file mode 100644 index 00000000000..128bc8b7cfc --- /dev/null +++ b/final/test/FrontendC/2002-05-24-Alloca.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include +#include +#include + +int main(int argc, char **argv) { + char *C = (char*)alloca(argc); + strcpy(C, argv[0]); + puts(C); +} diff --git a/final/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c b/final/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c new file mode 100644 index 00000000000..4380dc7b227 --- /dev/null +++ b/final/test/FrontendC/2002-06-25-FWriteInterfaceFailure.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include + +void test() { + fprintf(stderr, "testing\n"); +} diff --git a/final/test/FrontendC/2002-07-14-MiscListTests.c b/final/test/FrontendC/2002-07-14-MiscListTests.c new file mode 100644 index 00000000000..4a5459ad713 --- /dev/null +++ b/final/test/FrontendC/2002-07-14-MiscListTests.c @@ -0,0 +1,71 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +// Test list stuff + +void *malloc(unsigned); + +// Test opaque structure support. the list type is defined later +struct list; + +struct list *PassThroughList(struct list *L) { + return L; +} + + +// Recursive data structure tests... + +typedef struct list { + int Data; + struct list *Next; +} list; + +list *Data; + +void foo() { + static int Foo = 0; // Test static local variable + Foo += 1; // Increment static variable + + Data = (list*)malloc(12); // This is not a proper list allocation +} + +extern list ListNode1; +list ListNode3 = { 4, 0 }; +list ListNode2 = { 3, &ListNode3 }; +list ListNode0 = { 1, &ListNode1 }; +list ListNode1 = { 2, &ListNode2 }; + + +list ListArray[10]; + +// Iterative insert fn +void InsertIntoListTail(list **L, int Data) { + while (*L) + L = &(*L)->Next; + *L = (list*)malloc(sizeof(list)); + (*L)->Data = Data; + (*L)->Next = 0; +} + +// Recursive list search fn +list *FindData(list *L, int Data) { + if (L == 0) return 0; + if (L->Data == Data) return L; + return FindData(L->Next, Data); +} + +void foundIt(void); + +// Driver fn... +void DoListStuff() { + list *MyList = 0; + InsertIntoListTail(&MyList, 100); + InsertIntoListTail(&MyList, 12); + InsertIntoListTail(&MyList, 42); + InsertIntoListTail(&MyList, 1123); + InsertIntoListTail(&MyList, 1213); + + if (FindData(MyList, 75)) foundIt(); + if (FindData(MyList, 42)) foundIt(); + if (FindData(MyList, 700)) foundIt(); +} + diff --git a/final/test/FrontendC/2002-07-14-MiscTests.c b/final/test/FrontendC/2002-07-14-MiscTests.c new file mode 100644 index 00000000000..57c412083a6 --- /dev/null +++ b/final/test/FrontendC/2002-07-14-MiscTests.c @@ -0,0 +1,57 @@ +// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null + +/* These are random tests that I used when working on the GCC frontend + originally. */ + +// test floating point comparison! +int floatcomptest(double *X, double *Y, float *x, float *y) { + return *X < *Y || *x < *y; +} + +extern void *malloc(unsigned); + +// Exposed a bug +void *memset_impl(void *dstpp, int c, unsigned len) { + long long int dstp = (long long int) dstpp; + + while (dstp % 4 != 0) + { + ((unsigned char *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + return dstpp; +} + +// TEST problem with signed/unsigned versions of the same constants being shared +// incorrectly! +// +static char *temp; +static int remaining; +static char *localmalloc(int size) { + char *blah; + + if (size>remaining) + { + temp = (char *) malloc(32768); + remaining = 32768; + return temp; + } + return 0; +} + +typedef struct { double X; double Y; int Z; } PBVTest; + +PBVTest testRetStruct(float X, double Y, int Z) { + PBVTest T = { X, Y, Z }; + return T; +} +PBVTest testRetStruct2(void); // external func no inlining + + +double CallRetStruct(float X, double Y, int Z) { + PBVTest T = testRetStruct2(); + return T.X+X+Y+Z; +} + + diff --git a/final/test/FrontendC/2002-07-14-MiscTests2.c b/final/test/FrontendC/2002-07-14-MiscTests2.c new file mode 100644 index 00000000000..f2c7c81c4da --- /dev/null +++ b/final/test/FrontendC/2002-07-14-MiscTests2.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +// Test ?: in function calls +extern fp(int, char*); +char *Ext; +void +__bb_exit_func (void) +{ + fp (12, Ext ? Ext : ""); +} + + diff --git a/final/test/FrontendC/2002-07-14-MiscTests3.c b/final/test/FrontendC/2002-07-14-MiscTests3.c new file mode 100644 index 00000000000..7ef7e232d99 --- /dev/null +++ b/final/test/FrontendC/2002-07-14-MiscTests3.c @@ -0,0 +1,187 @@ +// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null + + + +void *malloc(unsigned); + +//#include +int puts(const char *s); + +struct FunStructTest { + int Test1; + char *Pointer; + int Array[12]; +}; + +struct SubStruct { + short X, Y; +}; + +struct Quad { + int w; + struct SubStruct SS; + struct SubStruct *SSP; + char c; + int y; +}; + +struct Quad GlobalQuad = { 4, {1, 2}, 0, 3, 156 }; + +typedef int (*FuncPtr)(int); + +unsigned PtrFunc(int (*Func)(int), int X) { + return Func(X); +} + +char PtrFunc2(FuncPtr FuncTab[30], int Num) { + return FuncTab[Num]('b'); +} + +extern char SmallArgs2(char w, char x, long long Zrrk, char y, char z); +extern int SomeFunc(void); +char SmallArgs(char w, char x, char y, char z) { + SomeFunc(); + return SmallArgs2(w-1, x+1, y, z, w); +} + +static int F0(struct Quad Q, int i) { /* Pass Q by value */ + struct Quad R; + if (i) R.SS = Q.SS; + Q.SSP = &R.SS; + Q.w = Q.y = Q.c = 1; + return Q.SS.Y + i + R.y - Q.c; +} + +int F1(struct Quad *Q, int i) { /* Pass Q by address */ + struct Quad R; +#if 0 + if (i) R.SS = Q->SS; +#else + if (i) R = *Q; +#endif + Q->w = Q->y = Q->c = 1; + return Q->SS.Y+i+R.y-Q->c; +} + + +int BadFunc(float Val) { + int Result; + if (Val > 12.345) Result = 4; + return Result; /* Test use of undefined value */ +} + +int RealFunc(void) { + return SomeUndefinedFunction(1, 4, 5); +} + +extern int EF1(int *, char *, int *); + +int Func(int Param, long long Param2) { + int Result = Param; + + {{{{ + char c; int X; + EF1(&Result, &c, &X); + }}} + + { // c & X are duplicate names! + char c; int X; + EF1(&Result, &c, &X); + } + + } + return Result; +} + + +short FunFunc(long long x, char z) { + return x+z; +} + +unsigned castTest(int X) { return X; } + +double TestAdd(double X, float Y) { + return X+Y+.5; +} + +int func(int i, int j) { + while (i != 20) + i += 2; + + j += func(2, i); + return (i * 3 + j*2)*j; +} + +int SumArray(int Array[], int Num) { + int i, Result = 0; + for (i = 0; i < Num; ++i) + Result += Array[i]; + + return Result; +} + +int ArrayParam(int Values[100]) { + return EF1((int*)Values[50], (char*)1, &Values[50]); +} + +int ArrayToSum(void) { + int A[100], i; + for (i = 0; i < 100; ++i) + A[i] = i*4; + + return A[A[0]]; //SumArray(A, 100); +} + + +int ExternFunc(long long, unsigned*, short, unsigned char); + +int main(int argc, char *argv[]) { + unsigned i; + puts("Hello world!\n"); + + ExternFunc(-1, 0, (short)argc, 2); + //func(argc, argc); + + for (i = 0; i < 10; i++) + puts(argv[3]); + return 0; +} + +double MathFunc(double X, double Y, double Z, + double AA, double BB, double CC, double DD, + double EE, double FF, double GG, double HH, + double aAA, double aBB, double aCC, double aDD, + double aEE, double aFF) { + return X + Y + Z + AA + BB + CC + DD + EE + FF + GG + HH + + aAA + aBB + aCC + aDD + aEE + aFF; +} + + + +void strcpy(char *s1, char *s2) { + while (*s1++ = *s2++); +} + +void strcat(char *s1, char *s2) { + while (*s1++); + s1--; + while (*s1++ = *s2++); +} + +int strcmp(char *s1, char *s2) { + while (*s1++ == *s2++); + if (*s1 == 0) { + if (*s2 == 0) { + return 0; + } else { + return -1; + } + } else { + if (*s2 == 0) { + return 1; + } else { + return (*(--s1) - *(--s2)); + } + } +} + diff --git a/final/test/FrontendC/2002-07-16-HardStringInit.c b/final/test/FrontendC/2002-07-16-HardStringInit.c new file mode 100644 index 00000000000..2785e5189d9 --- /dev/null +++ b/final/test/FrontendC/2002-07-16-HardStringInit.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + char auto_kibitz_list[100][20] = { + {"diepx"}, + {"ferret"}, + {"knightc"}, + {"knightcap"}}; + diff --git a/final/test/FrontendC/2002-07-17-StringConstant.c b/final/test/FrontendC/2002-07-17-StringConstant.c new file mode 100644 index 00000000000..9ba0c25213d --- /dev/null +++ b/final/test/FrontendC/2002-07-17-StringConstant.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +char * foo() { return "\\begin{"; } diff --git a/final/test/FrontendC/2002-07-29-Casts.c b/final/test/FrontendC/2002-07-29-Casts.c new file mode 100644 index 00000000000..44bb6101955 --- /dev/null +++ b/final/test/FrontendC/2002-07-29-Casts.c @@ -0,0 +1,86 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include +#include +#include + +int +main(int argc, char** argv) +{ + char c1; + short s1, ssf1, ssd1; + unsigned char ubs0; + signed char bs0; + unsigned char ubc0, uc2; + unsigned short us2, usf1, usd1; + int ic3, is3, sif1, sid1; + unsigned int uic4, uis4, uif1, uid1; + long slf1, sld1; + unsigned long ulf1, uld1; + float f1; + double d1; + + /* Test integer to integer conversions */ + + c1 = (char) (argc >= 2)? atoi(argv[1]) : 0xff64; /* 100 = 'd' */ + s1 = (short) (argc >= 3)? atoi(argv[2]) : -769; /* 0xf7ff = -769 */ + + ubc0 = (unsigned char) c1; /* 100 = 'd' */ + ubs0 = (unsigned char) s1; /* 0xff = 255 */ + bs0 = (signed char) s1; /* 0xff = -1 */ + + uc2 = (unsigned char) c1; /* 100 = 'd' */ + us2 = (unsigned short) s1; /* 0xf7ff = 64767 */ + + ic3 = (int) c1; /* 100 = 'd' */ + is3 = (int) s1; /* 0xfffff7ff = -769 */ + + uic4 = (unsigned int) c1; /* 100 = 'd' */ + uis4 = (unsigned int) s1; /* 0xfffff7ff = 4294966527 */ + + printf("ubc0 = '%c'\n", ubc0); + printf("ubs0 = %u\n", ubs0); + printf("bs0 = %d\n", bs0); + printf("c1 = '%c'\n", c1); + printf("s1 = %d\n", s1); + printf("uc2 = '%c'\n", uc2); + printf("us2 = %u\n", us2); + printf("ic3 = '%c'\n", ic3); + printf("is3 = %d\n", is3); + printf("uic4 = '%c'\n", uic4); + printf("uis4 = %u\n", uis4); + + /* Test floating-point to integer conversions */ + f1 = (float) (argc >= 4)? atof(argv[3]) : 1.0; + d1 = (argc >= 5)? atof(argv[4]) : 2.0; + + usf1 = (unsigned short) f1; + usd1 = (unsigned short) d1; + uif1 = (unsigned int) f1; + uid1 = (unsigned int) d1; + ulf1 = (unsigned long) f1; + uld1 = (unsigned long) d1; + + ssf1 = (short) f1; + ssd1 = (short) d1; + sif1 = (int) f1; + sid1 = (int) d1; + slf1 = (long) f1; + sld1 = (long) d1; + + printf("usf1 = %u\n", usf1); + printf("usd1 = %u\n", usd1); + printf("uif1 = %u\n", uif1); + printf("uid1 = %u\n", uid1); + printf("ulf1 = %u\n", ulf1); + printf("uld1 = %u\n", uld1); + + printf("ssf1 = %d\n", ssf1); + printf("ssd1 = %d\n", ssd1); + printf("sif1 = %d\n", sif1); + printf("sid1 = %d\n", sid1); + printf("slf1 = %d\n", slf1); + printf("sld1 = %d\n", sld1); + + return 0; +} diff --git a/final/test/FrontendC/2002-07-30-SubregSetAssertion.c b/final/test/FrontendC/2002-07-30-SubregSetAssertion.c new file mode 100644 index 00000000000..af72eda6524 --- /dev/null +++ b/final/test/FrontendC/2002-07-30-SubregSetAssertion.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +union X { + void *B; +}; + +union X foo() { + union X A; + A.B = (void*)123; + return A; +} diff --git a/final/test/FrontendC/2002-07-30-UnionTest.c b/final/test/FrontendC/2002-07-30-UnionTest.c new file mode 100644 index 00000000000..c931b8024f0 --- /dev/null +++ b/final/test/FrontendC/2002-07-30-UnionTest.c @@ -0,0 +1,22 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +union X; +struct Empty {}; +union F {}; +union Q { union Q *X; }; +union X { + char C; + int A, Z; + long long B; + void *b1; + struct { int A; long long Z; } Q; +}; + +union X foo(union X A) { + A.C = 123; + A.A = 39249; + //A.B = (void*)123040123321; + A.B = 12301230123123LL; + A.Z = 1; + return A; +} diff --git a/final/test/FrontendC/2002-07-30-VarArgsCallFailure.c b/final/test/FrontendC/2002-07-30-VarArgsCallFailure.c new file mode 100644 index 00000000000..5d93947a727 --- /dev/null +++ b/final/test/FrontendC/2002-07-30-VarArgsCallFailure.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int tcount; +void test(char *, const char*, int); +void foo() { + char Buf[10]; + test(Buf, "n%%%d", tcount++); +} diff --git a/final/test/FrontendC/2002-07-31-BadAssert.c b/final/test/FrontendC/2002-07-31-BadAssert.c new file mode 100644 index 00000000000..5c3d74cfb6b --- /dev/null +++ b/final/test/FrontendC/2002-07-31-BadAssert.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct +{ + unsigned char type; /* Indicates, NORMAL, SUBNORMAL, etc. */ +} InternalFPF; + + +static void SetInternalFPFZero(InternalFPF *dest) { + dest->type=0; +} + +void denormalize(InternalFPF *ptr) { + SetInternalFPFZero(ptr); +} + diff --git a/final/test/FrontendC/2002-07-31-SubregFailure.c b/final/test/FrontendC/2002-07-31-SubregFailure.c new file mode 100644 index 00000000000..72fcb496cb0 --- /dev/null +++ b/final/test/FrontendC/2002-07-31-SubregFailure.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +typedef union { + long (*ap)[4]; +} ptrs; + +void DoAssignIteration() { + ptrs abase; + abase.ap+=27; + Assignment(*abase.ap); +} + + diff --git a/final/test/FrontendC/2002-08-02-UnionTest.c b/final/test/FrontendC/2002-08-02-UnionTest.c new file mode 100644 index 00000000000..e2b8c3dd401 --- /dev/null +++ b/final/test/FrontendC/2002-08-02-UnionTest.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* In this testcase, the return value of foo() is being promotedto a register + * which breaks stuff + */ +#include + +union X { char X; void *B; int a, b, c, d;}; + +union X foo() { + union X Global; + Global.B = (void*)123; /* Interesting part */ + return Global; +} + +int main() { + union X test = foo(); + printf("0x%p", test.B); +} diff --git a/final/test/FrontendC/2002-08-19-RecursiveLocals.c b/final/test/FrontendC/2002-08-19-RecursiveLocals.c new file mode 100644 index 00000000000..59220ac9b0d --- /dev/null +++ b/final/test/FrontendC/2002-08-19-RecursiveLocals.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* This testcase doesn't actually test a bug, it's just the result of me + * figuring out the syntax for forward declaring a static variable. */ +struct list { + int x; + struct list *Next; +}; + +static struct list B; /* Forward declare static */ +static struct list A = { 7, &B }; +static struct list B = { 8, &A }; + +extern struct list D; /* forward declare normal var */ + +struct list C = { 7, &D }; +struct list D = { 8, &C }; + diff --git a/final/test/FrontendC/2002-09-08-PointerShifts.c b/final/test/FrontendC/2002-09-08-PointerShifts.c new file mode 100644 index 00000000000..86ff2f98afc --- /dev/null +++ b/final/test/FrontendC/2002-09-08-PointerShifts.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +int foo(int *A, unsigned X) { + return A[X]; +} diff --git a/final/test/FrontendC/2002-09-18-UnionProblem.c b/final/test/FrontendC/2002-09-18-UnionProblem.c new file mode 100644 index 00000000000..54588f12142 --- /dev/null +++ b/final/test/FrontendC/2002-09-18-UnionProblem.c @@ -0,0 +1,26 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +struct DWstruct { + char high, low; +}; + +typedef union { + struct DWstruct s; + short ll; +} DWunion; + +short __udivmodhi4 (char n1, char bm) { + DWunion rr; + + if (bm == 0) + { + rr.s.high = n1; + } + else + { + rr.s.high = bm; + } + + return rr.ll; +} diff --git a/final/test/FrontendC/2002-09-19-StarInLabel.c b/final/test/FrontendC/2002-09-19-StarInLabel.c new file mode 100644 index 00000000000..171acca2f11 --- /dev/null +++ b/final/test/FrontendC/2002-09-19-StarInLabel.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +extern void start() __asm__("start"); +extern void _start() __asm__("_start"); +extern void __start() __asm__("__start"); +void start() {} +void _start() {} +void __start() {} + diff --git a/final/test/FrontendC/2002-10-12-TooManyArguments.c b/final/test/FrontendC/2002-10-12-TooManyArguments.c new file mode 100644 index 00000000000..73c267ad30d --- /dev/null +++ b/final/test/FrontendC/2002-10-12-TooManyArguments.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +void foo() {} + +void bar() { + foo(1, 2, 3); /* Too many arguments passed */ +} diff --git a/final/test/FrontendC/2002-12-15-GlobalBoolTest.c b/final/test/FrontendC/2002-12-15-GlobalBoolTest.c new file mode 100644 index 00000000000..c27a23abc6e --- /dev/null +++ b/final/test/FrontendC/2002-12-15-GlobalBoolTest.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +_Bool X = 0; + diff --git a/final/test/FrontendC/2002-12-15-GlobalConstantTest.c b/final/test/FrontendC/2002-12-15-GlobalConstantTest.c new file mode 100644 index 00000000000..26de48fbb77 --- /dev/null +++ b/final/test/FrontendC/2002-12-15-GlobalConstantTest.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +const char *W = "foo"; +const int X = 7; +int Y = 8; +const char * const Z = "bar"; + diff --git a/final/test/FrontendC/2002-12-15-GlobalRedefinition.c b/final/test/FrontendC/2002-12-15-GlobalRedefinition.c new file mode 100644 index 00000000000..3b76953b094 --- /dev/null +++ b/final/test/FrontendC/2002-12-15-GlobalRedefinition.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +extern char algbrfile[9]; +char algbrfile[9] = "abcdefgh"; + diff --git a/final/test/FrontendC/2002-12-15-StructParameters.c b/final/test/FrontendC/2002-12-15-StructParameters.c new file mode 100644 index 00000000000..90ab1ff4404 --- /dev/null +++ b/final/test/FrontendC/2002-12-15-StructParameters.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct +{ + void *stack; + unsigned size; + unsigned avail; +} compile_stack_type; + +void foo(void*); +void bar(compile_stack_type T, unsigned); + +void test() { + compile_stack_type CST; + foo(&CST); + + bar(CST, 12); +} diff --git a/final/test/FrontendC/2003-01-30-UnionInit.c b/final/test/FrontendC/2003-01-30-UnionInit.c new file mode 100644 index 00000000000..576958442ae --- /dev/null +++ b/final/test/FrontendC/2003-01-30-UnionInit.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o /dev/null + +union foo { + struct { char A, B; } X; + int C; +}; + +union foo V = { {1, 2} }; diff --git a/final/test/FrontendC/2003-03-03-DeferredType.c b/final/test/FrontendC/2003-03-03-DeferredType.c new file mode 100644 index 00000000000..9e60df6f6a0 --- /dev/null +++ b/final/test/FrontendC/2003-03-03-DeferredType.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + + + +struct foo A; + +struct foo { + int x; +double D; +}; + diff --git a/final/test/FrontendC/2003-06-22-UnionCrash.c b/final/test/FrontendC/2003-06-22-UnionCrash.c new file mode 100644 index 00000000000..54d8dc6dda9 --- /dev/null +++ b/final/test/FrontendC/2003-06-22-UnionCrash.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct Blend_Map_Entry { + union { + float Colour[5]; + double Point_Slope[2]; + } Vals; +}; + +void test(struct Blend_Map_Entry* Foo) +{ +} + diff --git a/final/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c b/final/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c new file mode 100644 index 00000000000..80562c8849b --- /dev/null +++ b/final/test/FrontendC/2003-06-23-GCC-fold-infinite-recursion.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +double Test(double A, double B, double C, double D) { + return -(A-B) - (C-D); +} + diff --git a/final/test/FrontendC/2003-06-26-CFECrash.c b/final/test/FrontendC/2003-06-26-CFECrash.c new file mode 100644 index 00000000000..10a7ed44458 --- /dev/null +++ b/final/test/FrontendC/2003-06-26-CFECrash.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct min_info { + long offset; + unsigned file_attr; +} min_info; + +typedef struct Globals { + char answerbuf; + min_info info[1]; + min_info *pInfo; +} Uz_Globs; + +extern Uz_Globs G; + +int extract_or_test_files() { + G.pInfo = G.info; +} + diff --git a/final/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c b/final/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c new file mode 100644 index 00000000000..be042cedf9f --- /dev/null +++ b/final/test/FrontendC/2003-06-29-MultipleFunctionDefinition.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +/* This is apparently legal C. + */ +extern __inline__ void test() { } + +void test() { +} diff --git a/final/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c b/final/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c new file mode 100644 index 00000000000..51e66c9b839 --- /dev/null +++ b/final/test/FrontendC/2003-07-22-ArrayAccessTypeSafety.c @@ -0,0 +1,7 @@ +/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | not grep bitcast + */ + +void test(int* array, long long N) { + array[N] = N[array] = 33; +} + diff --git a/final/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c b/final/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c new file mode 100644 index 00000000000..12b4f7b9332 --- /dev/null +++ b/final/test/FrontendC/2003-08-06-BuiltinSetjmpLongjmp.c @@ -0,0 +1,14 @@ +/* RUN: %llvmgcc -xc %s -S -o - | not grep __builtin_ + * + * __builtin_longjmp/setjmp should get transformed into llvm.setjmp/longjmp + * just like explicit setjmp/longjmp calls are. + */ + +void jumpaway(int *ptr) { + __builtin_longjmp(ptr,1); +} + +int main(void) { + __builtin_setjmp(0); + jumpaway(0); +} diff --git a/final/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c b/final/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c new file mode 100644 index 00000000000..9ae633ee081 --- /dev/null +++ b/final/test/FrontendC/2003-08-17-DeadCodeShortCircuit.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -xc %s -S -o %t.o + +int test(_Bool pos, _Bool color) { + return 0; + return (pos && color); +} + diff --git a/final/test/FrontendC/2003-08-18-SigSetJmp.c b/final/test/FrontendC/2003-08-18-SigSetJmp.c new file mode 100644 index 00000000000..fc0d7659de6 --- /dev/null +++ b/final/test/FrontendC/2003-08-18-SigSetJmp.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +#include + +sigjmp_buf B; +int foo() { + sigsetjmp(B, 1); + bar(); +} diff --git a/final/test/FrontendC/2003-08-18-StructAsValue.c b/final/test/FrontendC/2003-08-18-StructAsValue.c new file mode 100644 index 00000000000..26cb78a4d24 --- /dev/null +++ b/final/test/FrontendC/2003-08-18-StructAsValue.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +typedef struct { + int op; +} event_t; + +event_t test(int X) { + event_t foo = { 1 }, bar = { 2 }; + return X ? foo : bar; +} diff --git a/final/test/FrontendC/2003-08-20-BadBitfieldRef.c b/final/test/FrontendC/2003-08-20-BadBitfieldRef.c new file mode 100644 index 00000000000..ef54d8ad9c0 --- /dev/null +++ b/final/test/FrontendC/2003-08-20-BadBitfieldRef.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void foo() +{ + char *ap; + ap[1] == '-' && ap[2] == 0; +} + diff --git a/final/test/FrontendC/2003-08-20-PrototypeMismatch.c b/final/test/FrontendC/2003-08-20-PrototypeMismatch.c new file mode 100644 index 00000000000..85c89f694c5 --- /dev/null +++ b/final/test/FrontendC/2003-08-20-PrototypeMismatch.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + + +static int foo(int); + +static int foo(C) +char C; +{ + return C; +} + +void test() { + foo(7); +} diff --git a/final/test/FrontendC/2003-08-20-vfork-bug.c b/final/test/FrontendC/2003-08-20-vfork-bug.c new file mode 100644 index 00000000000..cfe316162ad --- /dev/null +++ b/final/test/FrontendC/2003-08-20-vfork-bug.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +extern int vfork(void); +test() { + vfork(); +} diff --git a/final/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c b/final/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c new file mode 100644 index 00000000000..a1d4574dcdb --- /dev/null +++ b/final/test/FrontendC/2003-08-21-BinOp-Type-Mismatch.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct bar; + +void foo() +{ + unsigned int frame, focus; + (struct bar *) focus == (focus ? ((struct bar *) frame) : 0); +} + diff --git a/final/test/FrontendC/2003-08-21-StmtExpr.c b/final/test/FrontendC/2003-08-21-StmtExpr.c new file mode 100644 index 00000000000..7f7d22ea9d7 --- /dev/null +++ b/final/test/FrontendC/2003-08-21-StmtExpr.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +typedef struct { + unsigned long val; +} structty; + +void bar(structty new_mask); +static void foo() { + bar(({ structty mask; mask; })); +} + diff --git a/final/test/FrontendC/2003-08-21-WideString.c b/final/test/FrontendC/2003-08-21-WideString.c new file mode 100644 index 00000000000..bf67a21896b --- /dev/null +++ b/final/test/FrontendC/2003-08-21-WideString.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include + +struct { + wchar_t *name; +} syms = { L"NUL" }; diff --git a/final/test/FrontendC/2003-08-23-LocalUnionTest.c b/final/test/FrontendC/2003-08-23-LocalUnionTest.c new file mode 100644 index 00000000000..987accca1cc --- /dev/null +++ b/final/test/FrontendC/2003-08-23-LocalUnionTest.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + + +union foo { int X; }; + +int test(union foo* F) { + { + union foo { float X; } A; + } +} diff --git a/final/test/FrontendC/2003-08-29-BitFieldStruct.c b/final/test/FrontendC/2003-08-29-BitFieldStruct.c new file mode 100644 index 00000000000..57273cd8639 --- /dev/null +++ b/final/test/FrontendC/2003-08-29-BitFieldStruct.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct Word { + short bar; + short baz; + int final:1; + short quux; +} *word_limit; + +void foo () +{ + word_limit->final = (word_limit->final && word_limit->final); +} diff --git a/final/test/FrontendC/2003-08-29-HugeCharConst.c b/final/test/FrontendC/2003-08-29-HugeCharConst.c new file mode 100644 index 00000000000..236eb2e2748 --- /dev/null +++ b/final/test/FrontendC/2003-08-29-HugeCharConst.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void foo() { + unsigned char int_latin1[] = "f\200\372b\200\343\200\340"; +} diff --git a/final/test/FrontendC/2003-08-29-StructLayoutBug.c b/final/test/FrontendC/2003-08-29-StructLayoutBug.c new file mode 100644 index 00000000000..16731945b77 --- /dev/null +++ b/final/test/FrontendC/2003-08-29-StructLayoutBug.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct foo { + unsigned int I:1; + unsigned char J[1]; + unsigned int K:1; + }; + +void test(struct foo *X) {} + diff --git a/final/test/FrontendC/2003-08-30-AggregateInitializer.c b/final/test/FrontendC/2003-08-30-AggregateInitializer.c new file mode 100644 index 00000000000..58c77b6aa04 --- /dev/null +++ b/final/test/FrontendC/2003-08-30-AggregateInitializer.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S %s -o /dev/null + +struct istruct { + unsigned char C; +}; + +struct foo { + unsigned int I:1; + struct istruct J; + unsigned char L[1]; + unsigned int K:1; +}; + +struct foo F = { 1, { 7 }, { 123 } , 1 }; + + diff --git a/final/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c b/final/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c new file mode 100644 index 00000000000..e1ca88cdc6f --- /dev/null +++ b/final/test/FrontendC/2003-08-30-LargeIntegerBitfieldMember.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct foo { + unsigned int I:1; + unsigned char J[1][123]; + unsigned int K:1; + }; + +struct foo F; diff --git a/final/test/FrontendC/2003-09-18-BitfieldTests.c b/final/test/FrontendC/2003-09-18-BitfieldTests.c new file mode 100644 index 00000000000..2d74cb401dc --- /dev/null +++ b/final/test/FrontendC/2003-09-18-BitfieldTests.c @@ -0,0 +1,30 @@ +// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null + + +typedef struct BF { + int A : 1; + char B; + int C : 13; +} BF; + +char *test1(BF *b) { + return &b->B; // Must be able to address non-bitfield +} + +void test2(BF *b) { // Increment and decrement operators + b->A++; + --b->C; +} + +void test3(BF *b) { + b->C = 12345; // Store +} + +int test4(BF *b) { + return b->C; // Load +} + +void test5(BF *b, int i) { // array ref + b[i].C = 12345; +} + diff --git a/final/test/FrontendC/2003-09-30-StructLayout.c b/final/test/FrontendC/2003-09-30-StructLayout.c new file mode 100644 index 00000000000..177d1f49b2f --- /dev/null +++ b/final/test/FrontendC/2003-09-30-StructLayout.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +enum En { + ENUM_VAL +}; + +struct St { + unsigned char A; + enum En B; + unsigned char C; + enum En D; + float E; +}; + + +void func(struct St* A) { + A->D = ENUM_VAL; +} diff --git a/final/test/FrontendC/2003-10-02-UnionLValueError.c b/final/test/FrontendC/2003-10-02-UnionLValueError.c new file mode 100644 index 00000000000..a4d17a4a0ba --- /dev/null +++ b/final/test/FrontendC/2003-10-02-UnionLValueError.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include + +union U{ + int i[8]; + char s[80]; +}; + +void format_message(char *buffer, union U *u) { + sprintf(buffer, u->s); +} + diff --git a/final/test/FrontendC/2003-10-06-NegateExprType.c b/final/test/FrontendC/2003-10-06-NegateExprType.c new file mode 100644 index 00000000000..fb8329b344b --- /dev/null +++ b/final/test/FrontendC/2003-10-06-NegateExprType.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +extern int A[10]; +void Func(int *B) { + B - &A[5]; +} + diff --git a/final/test/FrontendC/2003-10-09-UnionInitializerBug.c b/final/test/FrontendC/2003-10-09-UnionInitializerBug.c new file mode 100644 index 00000000000..57e113a7cc2 --- /dev/null +++ b/final/test/FrontendC/2003-10-09-UnionInitializerBug.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct Foo { + unsigned a; + unsigned b; + unsigned c; +}; + +struct Bar { + union { + void **a; + struct Foo b; + }u; +}; + +struct Bar test = {0}; + diff --git a/final/test/FrontendC/2003-10-28-ident.c b/final/test/FrontendC/2003-10-28-ident.c new file mode 100644 index 00000000000..06cacf87a90 --- /dev/null +++ b/final/test/FrontendC/2003-10-28-ident.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +#ident "foo" diff --git a/final/test/FrontendC/2003-10-29-AsmRename.c b/final/test/FrontendC/2003-10-29-AsmRename.c new file mode 100644 index 00000000000..d07ccf7fd2c --- /dev/null +++ b/final/test/FrontendC/2003-10-29-AsmRename.c @@ -0,0 +1,22 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +struct foo { int X; }; +struct bar { int Y; }; + +extern int Func(struct foo*) __asm__("Func64"); +extern int Func64(struct bar*); + +int Func(struct foo *F) { + return 1; +} + +int Func64(struct bar* B) { + return 0; +} + + +int test() { + Func(0); /* should be renamed to call Func64 */ + Func64(0); +} diff --git a/final/test/FrontendC/2003-11-01-C99-CompoundLiteral.c b/final/test/FrontendC/2003-11-01-C99-CompoundLiteral.c new file mode 100644 index 00000000000..2912c97c546 --- /dev/null +++ b/final/test/FrontendC/2003-11-01-C99-CompoundLiteral.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct { int foo; } spinlock_t; +typedef struct wait_queue_head_t { spinlock_t lock; } wait_queue_head_t; +void call_usermodehelper(void) { + struct wait_queue_head_t work = { lock: (spinlock_t) { 0 }, }; +} + diff --git a/final/test/FrontendC/2003-11-01-EmptyStructCrash.c b/final/test/FrontendC/2003-11-01-EmptyStructCrash.c new file mode 100644 index 00000000000..c1161195daf --- /dev/null +++ b/final/test/FrontendC/2003-11-01-EmptyStructCrash.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct { } the_coolest_struct_in_the_world; +extern the_coolest_struct_in_the_world xyzzy; +void *foo() { return &xyzzy; } + diff --git a/final/test/FrontendC/2003-11-01-GlobalUnionInit.c b/final/test/FrontendC/2003-11-01-GlobalUnionInit.c new file mode 100644 index 00000000000..7cd707348ca --- /dev/null +++ b/final/test/FrontendC/2003-11-01-GlobalUnionInit.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +union bdflush_param { + struct { int x; } b_un; + int y[1]; +} bdf_prm = {{30}}; + diff --git a/final/test/FrontendC/2003-11-03-AddrArrayElement.c b/final/test/FrontendC/2003-11-03-AddrArrayElement.c new file mode 100644 index 00000000000..4337da7d1e4 --- /dev/null +++ b/final/test/FrontendC/2003-11-03-AddrArrayElement.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr + +// This should be turned into a tasty getelementptr instruction, not a nasty +// series of casts and address arithmetic. + +char Global[100]; + +char *test1(unsigned i) { + return &Global[i]; +} + diff --git a/final/test/FrontendC/2003-11-04-EmptyStruct.c b/final/test/FrontendC/2003-11-04-EmptyStruct.c new file mode 100644 index 00000000000..b4f37befffa --- /dev/null +++ b/final/test/FrontendC/2003-11-04-EmptyStruct.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct { } rwlock_t; +struct fs_struct { rwlock_t lock; int umask; }; +void __copy_fs_struct(struct fs_struct *fs) { fs->lock = (rwlock_t) { }; } + diff --git a/final/test/FrontendC/2003-11-04-OutOfMemory.c b/final/test/FrontendC/2003-11-04-OutOfMemory.c new file mode 100644 index 00000000000..40cb6c2e21e --- /dev/null +++ b/final/test/FrontendC/2003-11-04-OutOfMemory.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void schedule_timeout(signed long timeout) +{ + switch (timeout) + { + case ((long)(~0UL>>1)): break; + } +} diff --git a/final/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c b/final/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c new file mode 100644 index 00000000000..58f9f82e154 --- /dev/null +++ b/final/test/FrontendC/2003-11-08-PointerSubNotGetelementptr.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr + +char *test(char* C) { + return C-1; // Should turn into a GEP +} + +int *test2(int* I) { + return I-1; +} diff --git a/final/test/FrontendC/2003-11-12-VoidString.c b/final/test/FrontendC/2003-11-12-VoidString.c new file mode 100644 index 00000000000..5770b3661a9 --- /dev/null +++ b/final/test/FrontendC/2003-11-12-VoidString.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void query_newnamebuf(void) { ((void)"query_newnamebuf"); } + diff --git a/final/test/FrontendC/2003-11-13-TypeSafety.c b/final/test/FrontendC/2003-11-13-TypeSafety.c new file mode 100644 index 00000000000..9b76bb11c98 --- /dev/null +++ b/final/test/FrontendC/2003-11-13-TypeSafety.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep getelementptr + +int *test(int *X, int Y) { + return X + Y; +} diff --git a/final/test/FrontendC/2003-11-16-StaticArrayInit.c b/final/test/FrontendC/2003-11-16-StaticArrayInit.c new file mode 100644 index 00000000000..eb83b3ad0c6 --- /dev/null +++ b/final/test/FrontendC/2003-11-16-StaticArrayInit.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +void bar () { + static char x[10]; + static char *xend = x + 10; +} + + diff --git a/final/test/FrontendC/2003-11-18-CondExprLValue.c b/final/test/FrontendC/2003-11-18-CondExprLValue.c new file mode 100644 index 00000000000..68ee622c641 --- /dev/null +++ b/final/test/FrontendC/2003-11-18-CondExprLValue.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +typedef struct { unsigned long pgprot; } pgprot_t; + +void split_large_page(unsigned long addr, pgprot_t prot) +{ + (addr ? prot : ((pgprot_t) { 0x001 } )).pgprot; +} + diff --git a/final/test/FrontendC/2003-11-19-AddressOfRegister.c b/final/test/FrontendC/2003-11-19-AddressOfRegister.c new file mode 100644 index 00000000000..69dc54d9289 --- /dev/null +++ b/final/test/FrontendC/2003-11-19-AddressOfRegister.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -xc %s -S -o /dev/null |& not grep warning + +struct item { + short delta[4]; +}; + +int TEST(int nt) { + register struct item *aa; + aa[nt].delta; + return 1; +} + diff --git a/final/test/FrontendC/2003-11-19-BitFieldArray.c b/final/test/FrontendC/2003-11-19-BitFieldArray.c new file mode 100644 index 00000000000..250268a3b85 --- /dev/null +++ b/final/test/FrontendC/2003-11-19-BitFieldArray.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct _GIOChannel { + int write_buf; + char partial_write_buf[6]; + int d :1; +}; + +void g_io_channel_init (struct _GIOChannel *channel) { + channel->partial_write_buf[0]; +} + diff --git a/final/test/FrontendC/2003-11-20-Bitfields.c b/final/test/FrontendC/2003-11-20-Bitfields.c new file mode 100644 index 00000000000..4be9942ccf3 --- /dev/null +++ b/final/test/FrontendC/2003-11-20-Bitfields.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct face_cachel { + unsigned int reverse :1; + unsigned char font_specified[1]; +}; + +void +ensure_face_cachel_contains_charset (struct face_cachel *cachel) { + cachel->font_specified[0] = 0; +} + diff --git a/final/test/FrontendC/2003-11-20-ComplexDivision.c b/final/test/FrontendC/2003-11-20-ComplexDivision.c new file mode 100644 index 00000000000..172de8c0e19 --- /dev/null +++ b/final/test/FrontendC/2003-11-20-ComplexDivision.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int test() { + __complex__ double C; + double D; + C / D; +} diff --git a/final/test/FrontendC/2003-11-20-UnionBitfield.c b/final/test/FrontendC/2003-11-20-UnionBitfield.c new file mode 100644 index 00000000000..f999c207772 --- /dev/null +++ b/final/test/FrontendC/2003-11-20-UnionBitfield.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct printf_spec { + unsigned int minus_flag:1; + char converter; +}; + +void parse_doprnt_spec () { + struct printf_spec spec; + spec.minus_flag = 1; +} + diff --git a/final/test/FrontendC/2003-11-26-PointerShift.c b/final/test/FrontendC/2003-11-26-PointerShift.c new file mode 100644 index 00000000000..6b5205a6e7e --- /dev/null +++ b/final/test/FrontendC/2003-11-26-PointerShift.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +unsigned long do_csum(const unsigned char *buff, int len, unsigned long result) { + if (2 & (unsigned long) buff) result += 1; + return result; +} diff --git a/final/test/FrontendC/2003-11-27-ConstructorCast.c b/final/test/FrontendC/2003-11-27-ConstructorCast.c new file mode 100644 index 00000000000..15eb7694795 --- /dev/null +++ b/final/test/FrontendC/2003-11-27-ConstructorCast.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct i387_soft_struct { + long cwd; +}; +union i387_union { + struct i387_soft_struct soft; +}; +struct thread_struct { + union i387_union i387; +}; +void _init_task_union(void) { + struct thread_struct thread = (struct thread_struct) { {{0}} }; +} diff --git a/final/test/FrontendC/2003-11-27-UnionCtorInitialization.c b/final/test/FrontendC/2003-11-27-UnionCtorInitialization.c new file mode 100644 index 00000000000..e3ae1e96a68 --- /dev/null +++ b/final/test/FrontendC/2003-11-27-UnionCtorInitialization.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +struct i387_soft_struct { + long cwd; + long twd; + long fip; +}; +union i387_union { + struct i387_soft_struct soft; +}; +struct thread_struct { + union i387_union i387; +}; +void _init_task_union(void) { + struct thread_struct thread = (struct thread_struct) { {{0}} }; +} diff --git a/final/test/FrontendC/2003-12-14-ExternInlineSupport.c b/final/test/FrontendC/2003-12-14-ExternInlineSupport.c new file mode 100644 index 00000000000..a45eb98dca2 --- /dev/null +++ b/final/test/FrontendC/2003-12-14-ExternInlineSupport.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -xc %s -S -o - | not grep dead_function + +extern __inline__ void dead_function() {} diff --git a/final/test/FrontendC/2004-01-01-UnknownInitSize.c b/final/test/FrontendC/2004-01-01-UnknownInitSize.c new file mode 100644 index 00000000000..b26b6cd8756 --- /dev/null +++ b/final/test/FrontendC/2004-01-01-UnknownInitSize.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o /dev/null + +/* + * This regression test ensures that the C front end can compile initializers + * even when it cannot determine the size (as below). +*/ +struct one +{ + int a; + int values []; +}; + +struct one hobbit = {5, {1, 2, 3}}; + diff --git a/final/test/FrontendC/2004-01-08-ExternInlineRedefine.c b/final/test/FrontendC/2004-01-08-ExternInlineRedefine.c new file mode 100644 index 00000000000..4366b9b5659 --- /dev/null +++ b/final/test/FrontendC/2004-01-08-ExternInlineRedefine.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +extern __inline long int +__strtol_l (int a) +{ + return 0; +} + +long int +__strtol_l (int a) +{ + return 0; +} diff --git a/final/test/FrontendC/2004-02-12-LargeAggregateCopy.c b/final/test/FrontendC/2004-02-12-LargeAggregateCopy.c new file mode 100644 index 00000000000..93b7fe44bf6 --- /dev/null +++ b/final/test/FrontendC/2004-02-12-LargeAggregateCopy.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep llvm.memcpy + +struct X { int V[10000]; }; +struct X Global1, Global2; +void test() { + Global2 = Global1; +} + diff --git a/final/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c b/final/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c new file mode 100644 index 00000000000..f115b5a5f01 --- /dev/null +++ b/final/test/FrontendC/2004-02-13-BuiltinFrameReturnAddress.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep llvm.*address | count 4 + +void *test1() { + return __builtin_return_address(1); +} +void *test2() { + return __builtin_frame_address(0); +} diff --git a/final/test/FrontendC/2004-02-13-IllegalVararg.c b/final/test/FrontendC/2004-02-13-IllegalVararg.c new file mode 100644 index 00000000000..0d003c8033c --- /dev/null +++ b/final/test/FrontendC/2004-02-13-IllegalVararg.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -xc %s -w -S -o - | llc +// XFAIL: * +// See PR2452 + +#include + +float test(int X, ...) { + va_list ap; + float F; + va_start(ap, X); + F = va_arg(ap, float); + return F; +} diff --git a/final/test/FrontendC/2004-02-13-Memset.c b/final/test/FrontendC/2004-02-13-Memset.c new file mode 100644 index 00000000000..fb6ed2352ea --- /dev/null +++ b/final/test/FrontendC/2004-02-13-Memset.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep llvm.memset | count 3 + +void *memset(void*, int, long); +void bzero(void*, long); + +void test(int* X, char *Y) { + memset(X, 4, 1000); + bzero(Y, 100); +} diff --git a/final/test/FrontendC/2004-02-14-ZeroInitializer.c b/final/test/FrontendC/2004-02-14-ZeroInitializer.c new file mode 100644 index 00000000000..bede9078741 --- /dev/null +++ b/final/test/FrontendC/2004-02-14-ZeroInitializer.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep zeroinitializer + +int X[1000]; + diff --git a/final/test/FrontendC/2004-02-20-Builtins.c b/final/test/FrontendC/2004-02-20-Builtins.c new file mode 100644 index 00000000000..c056a8405f7 --- /dev/null +++ b/final/test/FrontendC/2004-02-20-Builtins.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -O3 -xc %s -S -o - | not grep builtin + +#include + +void zsqrtxxx(float num) { + num = sqrt(num); +} + diff --git a/final/test/FrontendC/2004-03-07-ComplexDivEquals.c b/final/test/FrontendC/2004-03-07-ComplexDivEquals.c new file mode 100644 index 00000000000..c6c805a7b32 --- /dev/null +++ b/final/test/FrontendC/2004-03-07-ComplexDivEquals.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +void test(__complex__ double D, double X) { + D /= X; +} diff --git a/final/test/FrontendC/2004-03-07-ExternalConstant.c b/final/test/FrontendC/2004-03-07-ExternalConstant.c new file mode 100644 index 00000000000..4a9094bdf34 --- /dev/null +++ b/final/test/FrontendC/2004-03-07-ExternalConstant.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep constant + +extern const int a[]; // 'a' should be marked constant even though it's external! +int foo () { + return a[0]; +} + diff --git a/final/test/FrontendC/2004-03-09-LargeArrayInitializers.c b/final/test/FrontendC/2004-03-09-LargeArrayInitializers.c new file mode 100644 index 00000000000..265206fabb6 --- /dev/null +++ b/final/test/FrontendC/2004-03-09-LargeArrayInitializers.c @@ -0,0 +1,32 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +// Test that these initializers are handled efficiently + +int test(int x) { + const int XX[1000] = { 0, 0 }; + const char S [1000] = "foo"; + + const int array[] = { + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, 17, 23, 123, 123, 49, + }; + return array[x]; +} diff --git a/final/test/FrontendC/2004-03-15-SimpleIndirectGoto.c b/final/test/FrontendC/2004-03-15-SimpleIndirectGoto.c new file mode 100644 index 00000000000..a3f27b2a330 --- /dev/null +++ b/final/test/FrontendC/2004-03-15-SimpleIndirectGoto.c @@ -0,0 +1,23 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int code[]={0,0,0,0,1}; +void foo(int x) { + volatile int b; + b = 0xffffffff; +} +void bar(int *pc) { + static const void *l[] = {&&lab0, &&end}; + + foo(0); + goto *l[*pc]; + lab0: + foo(0); + pc++; + goto *l[*pc]; + end: + return; +} +int main() { + bar(code); + return 0; +} diff --git a/final/test/FrontendC/2004-03-16-AsmRegisterCrash.c b/final/test/FrontendC/2004-03-16-AsmRegisterCrash.c new file mode 100644 index 00000000000..f13368c2562 --- /dev/null +++ b/final/test/FrontendC/2004-03-16-AsmRegisterCrash.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int foo() { +#ifdef __ppc__ + register int X __asm__("r1"); +#else + register int X __asm__("ebx"); +#endif + return X; +} diff --git a/final/test/FrontendC/2004-05-07-VarArrays.c b/final/test/FrontendC/2004-05-07-VarArrays.c new file mode 100644 index 00000000000..3a39c4fe63a --- /dev/null +++ b/final/test/FrontendC/2004-05-07-VarArrays.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +int foo(int len, char arr[][len], int X) { + return arr[X][0]; +} diff --git a/final/test/FrontendC/2004-05-21-IncompleteEnum.c b/final/test/FrontendC/2004-05-21-IncompleteEnum.c new file mode 100644 index 00000000000..958a8d1c0ea --- /dev/null +++ b/final/test/FrontendC/2004-05-21-IncompleteEnum.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -w -S %s -o - | llvm-as -o /dev/null + +void test(enum foo *X) { +} + diff --git a/final/test/FrontendC/2004-06-08-OpaqueStructArg.c b/final/test/FrontendC/2004-06-08-OpaqueStructArg.c new file mode 100644 index 00000000000..5dfdd83c9e2 --- /dev/null +++ b/final/test/FrontendC/2004-06-08-OpaqueStructArg.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + struct fu; + void foo(struct fu); + void bar() { + foo; + } diff --git a/final/test/FrontendC/2004-06-17-UnorderedBuiltins.c b/final/test/FrontendC/2004-06-17-UnorderedBuiltins.c new file mode 100644 index 00000000000..02780f0f057 --- /dev/null +++ b/final/test/FrontendC/2004-06-17-UnorderedBuiltins.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +_Bool A, B, C, D, E, F, G, H; +void TestF(float X, float Y) { + A = __builtin_isgreater(X, Y); + B = __builtin_isgreaterequal(X, Y); + C = __builtin_isless(X, Y); + D = __builtin_islessequal(X, Y); + E = __builtin_islessgreater(X, Y); + F = __builtin_isunordered(X, Y); + //G = __builtin_isordered(X, Y); // Our current snapshot of GCC doesn't include this builtin + H = __builtin_isunordered(X, Y); +} +void TestD(double X, double Y) { + A = __builtin_isgreater(X, Y); + B = __builtin_isgreaterequal(X, Y); + C = __builtin_isless(X, Y); + D = __builtin_islessequal(X, Y); + E = __builtin_islessgreater(X, Y); + F = __builtin_isunordered(X, Y); + //G = __builtin_isordered(X, Y); // Our current snapshot doesn't include this builtin. FIXME + H = __builtin_isunordered(X, Y); +} diff --git a/final/test/FrontendC/2004-06-17-UnorderedCompares.c b/final/test/FrontendC/2004-06-17-UnorderedCompares.c new file mode 100644 index 00000000000..286e7bc7cf7 --- /dev/null +++ b/final/test/FrontendC/2004-06-17-UnorderedCompares.c @@ -0,0 +1,21 @@ +// RUN: %llvmgcc -xc -std=c99 %s -S -o - | grep -v llvm.isunordered | not grep call + +#include + +_Bool A, B, C, D, E, F; +void TestF(float X, float Y) { + A = __builtin_isgreater(X, Y); + B = __builtin_isgreaterequal(X, Y); + C = __builtin_isless(X, Y); + D = __builtin_islessequal(X, Y); + E = __builtin_islessgreater(X, Y); + F = __builtin_isunordered(X, Y); +} +void TestD(double X, double Y) { + A = __builtin_isgreater(X, Y); + B = __builtin_isgreaterequal(X, Y); + C = __builtin_isless(X, Y); + D = __builtin_islessequal(X, Y); + E = __builtin_islessgreater(X, Y); + F = __builtin_isunordered(X, Y); +} diff --git a/final/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c b/final/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c new file mode 100644 index 00000000000..3e450a4b936 --- /dev/null +++ b/final/test/FrontendC/2004-06-18-VariableLengthArrayOfStructures.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +struct S { }; + +int xxxx(int a) { + struct S comps[a]; + comps[0]; +} + diff --git a/final/test/FrontendC/2004-07-06-FunctionCast.c b/final/test/FrontendC/2004-07-06-FunctionCast.c new file mode 100644 index 00000000000..6d80f86fa1e --- /dev/null +++ b/final/test/FrontendC/2004-07-06-FunctionCast.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +static int unused_func(void) { + return 1; +} + +int foo(void) { + (void)unused_func; /* avoid compiler warning */ + return 2; +} diff --git a/final/test/FrontendC/2004-08-06-LargeStructTest.c b/final/test/FrontendC/2004-08-06-LargeStructTest.c new file mode 100644 index 00000000000..8fbb7f8368c --- /dev/null +++ b/final/test/FrontendC/2004-08-06-LargeStructTest.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + + +#define A(X) int X; +#define B(X) A(X##0) A(X##1) A(X##2) A(X##3) A(X##4) A(X##5) A(X##6) A(X##7) \ + A(X##8) A(X##9) A(X##A) A(X##B) A(X##C) A(X##D) A(X##E) A(X##F) +#define C(X) B(X##0) B(X##1) B(X##2) B(X##3) B(X##4) B(X##5) B(X##6) B(X##7) \ + B(X##8) B(X##9) B(X##A) B(X##B) B(X##C) B(X##D) B(X##E) B(X##F) + +struct foo { + C(x); // 256 + C(y); // 256 + C(z); +}; + + +int test(struct foo *F) { + return F->xA1 + F->yFF + F->zC4; +} diff --git a/final/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c b/final/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c new file mode 100644 index 00000000000..b3f4a829a9e --- /dev/null +++ b/final/test/FrontendC/2004-11-25-UnnamedBitfieldPadding.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o /dev/null +// This is a testcase for PR461 +typedef struct { + unsigned min_align: 1; + unsigned : 1; +} addr_diff_vec_flags; + +addr_diff_vec_flags X; diff --git a/final/test/FrontendC/2004-11-27-InvalidConstantExpr.c b/final/test/FrontendC/2004-11-27-InvalidConstantExpr.c new file mode 100644 index 00000000000..ee8642fa3aa --- /dev/null +++ b/final/test/FrontendC/2004-11-27-InvalidConstantExpr.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -S -o - | not grep {foo\\* sub} +// This should not produce a subtrace constantexpr of a pointer +struct foo { + int Y; + char X[100]; +} F; + +int test(char *Y) { + return Y - F.X; +} diff --git a/final/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c b/final/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c new file mode 100644 index 00000000000..994ac8f8436 --- /dev/null +++ b/final/test/FrontendC/2004-11-27-StaticFunctionRedeclare.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -S %s -o - | \ +// RUN: opt -std-compile-opts -S | not grep {declare i32.*func} + +// There should not be an unresolved reference to func here. Believe it or not, +// the "expected result" is a function named 'func' which is internal and +// referenced by bar(). + +// This is PR244 + +static int func(); +void bar() { + int func(); + foo(func); +} +static int func(char** A, char ** B) {} diff --git a/final/test/FrontendC/2004-11-27-VariableSizeInStructure.c b/final/test/FrontendC/2004-11-27-VariableSizeInStructure.c new file mode 100644 index 00000000000..bd63ae3b012 --- /dev/null +++ b/final/test/FrontendC/2004-11-27-VariableSizeInStructure.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o /dev/null + +// GCC allows variable sized arrays in structures, crazy! + +// This is PR360. + +int sub1(int i, char *pi) { + typedef int foo[i]; + struct bar {foo f1; int f2;} *p = (struct bar *) pi; + return p->f2; +} diff --git a/final/test/FrontendC/2005-01-02-ConstantInits.c b/final/test/FrontendC/2005-01-02-ConstantInits.c new file mode 100644 index 00000000000..735278e0f93 --- /dev/null +++ b/final/test/FrontendC/2005-01-02-ConstantInits.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc %s -S -o - + +// This tests all kinds of hard cases with initializers and +// array subscripts. This corresponds to PR487. + +struct X { int a[2]; }; + +int test() { + static int i23 = (int) &(((struct X *)0)->a[1]); + return i23; +} + +int i = (int) &( ((struct X *)0) -> a[1]); + +int Arr[100]; + +int foo(int i) { return bar(&Arr[49])+bar(&Arr[i]); } +int foo2(int i) { + static const int *X = &Arr[49]; + static int i23 = (int) &( ((struct X *)0) -> a[0]); + int *P = Arr; + ++P; + return bar(Arr+i); +} diff --git a/final/test/FrontendC/2005-01-02-PointerDifference.c b/final/test/FrontendC/2005-01-02-PointerDifference.c new file mode 100644 index 00000000000..2c108e5f6ca --- /dev/null +++ b/final/test/FrontendC/2005-01-02-PointerDifference.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep -v div + +int Diff(int *P, int *Q) { return P-Q; } diff --git a/final/test/FrontendC/2005-01-02-VAArgError-ICE.c b/final/test/FrontendC/2005-01-02-VAArgError-ICE.c new file mode 100644 index 00000000000..db825584627 --- /dev/null +++ b/final/test/FrontendC/2005-01-02-VAArgError-ICE.c @@ -0,0 +1,10 @@ +// This file is erroneous, but should not cause the compiler to ICE. +// PR481 +// RUN: %llvmgcc %s -S -o /dev/null |& not grep {internal compiler error} + +#include +int flags(int a, int b, ...) { + va_list args; + va_start(args,a); // not the last named arg + foo(args); +} diff --git a/final/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c b/final/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c new file mode 100644 index 00000000000..7a955330331 --- /dev/null +++ b/final/test/FrontendC/2005-02-20-AggregateSAVEEXPR.c @@ -0,0 +1,19 @@ +// RUN: %llvmgcc %s -o /dev/null -S +// Note: +// We fail this on Sparc because the C library seems to be missing complex.h +// and the corresponding C99 complex support. +// +// We could modify the test to use only GCC extensions, but I don't know if +// that would change the nature of the test. +// +// XFAIL: sparc + +#ifdef __CYGWIN__ + #include +#else + #include +#endif + +int foo(complex float c) { + return creal(c); +} diff --git a/final/test/FrontendC/2005-02-27-MarkGlobalConstant.c b/final/test/FrontendC/2005-02-27-MarkGlobalConstant.c new file mode 100644 index 00000000000..6806c94c10b --- /dev/null +++ b/final/test/FrontendC/2005-02-27-MarkGlobalConstant.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -xc %s -S -o - | grep {private unnamed_addr constant } + +// The synthetic global made by the CFE for big initializer should be marked +// constant. + +void bar(); +void foo() { + char Blah[] = "asdlfkajsdlfkajsd;lfkajds;lfkjasd;flkajsd;lkfja;sdlkfjasd"; + bar(Blah); +} diff --git a/final/test/FrontendC/2005-03-05-OffsetOfHack.c b/final/test/FrontendC/2005-03-05-OffsetOfHack.c new file mode 100644 index 00000000000..8df7231df6a --- /dev/null +++ b/final/test/FrontendC/2005-03-05-OffsetOfHack.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o - + +struct s { + unsigned long int field[0]; +}; + +#define OFFS \ + (((char *) &((struct s *) 0)->field[0]) - (char *) 0) + +int foo[OFFS]; + + diff --git a/final/test/FrontendC/2005-03-06-OffsetOfStructCrash.c b/final/test/FrontendC/2005-03-06-OffsetOfStructCrash.c new file mode 100644 index 00000000000..91e68628023 --- /dev/null +++ b/final/test/FrontendC/2005-03-06-OffsetOfStructCrash.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc %s -S -o - + +struct Y {}; +struct XXX { + struct Y F; +}; + +void test1() { + (int)&((struct XXX*)(((void *)0)))->F; +} + +void test2() { + &((struct XXX*)(((void *)0)))->F; +} diff --git a/final/test/FrontendC/2005-03-11-Prefetch.c b/final/test/FrontendC/2005-03-11-Prefetch.c new file mode 100644 index 00000000000..bf7965304f1 --- /dev/null +++ b/final/test/FrontendC/2005-03-11-Prefetch.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | grep llvm.prefetch + +void foo(int *P) { + __builtin_prefetch(P); + __builtin_prefetch(P, 1); +} diff --git a/final/test/FrontendC/2005-04-09-ComplexOps.c b/final/test/FrontendC/2005-04-09-ComplexOps.c new file mode 100644 index 00000000000..2962b745534 --- /dev/null +++ b/final/test/FrontendC/2005-04-09-ComplexOps.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - + +#include +#define I 1.0iF + +double __complex test(double X) { return ~-(X*I); } + +_Bool EQ(double __complex A, double __complex B) { return A == B; } +_Bool NE(double __complex A, double __complex B) { return A != B; } diff --git a/final/test/FrontendC/2005-05-06-CountBuiltins.c b/final/test/FrontendC/2005-05-06-CountBuiltins.c new file mode 100644 index 00000000000..da40a142ae9 --- /dev/null +++ b/final/test/FrontendC/2005-05-06-CountBuiltins.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | not grep call.*__builtin + +int G, H, I; +void foo(int P) { + G = __builtin_clz(P); + H = __builtin_ctz(P); + I = __builtin_popcount(P); +} + +long long g, h, i; +void fooll(float P) { + g = __builtin_clzll(P); + g = __builtin_clzll(P); + h = __builtin_ctzll(P); + i = __builtin_popcountll(P); +} + diff --git a/final/test/FrontendC/2005-05-10-GlobalUnionInit.c b/final/test/FrontendC/2005-05-10-GlobalUnionInit.c new file mode 100644 index 00000000000..443064c921d --- /dev/null +++ b/final/test/FrontendC/2005-05-10-GlobalUnionInit.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - + +union A { // { uint } + union B { double *C; } D; +} E = { { (double*)12312 } }; + diff --git a/final/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c b/final/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c new file mode 100644 index 00000000000..0f076c9bf79 --- /dev/null +++ b/final/test/FrontendC/2005-06-15-ExpandGotoInternalProblem.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -std=c99 %s -S -o - | \ +// RUN: opt -std-compile-opts -disable-output +// PR580 + +int X, Y; +int foo() { + int i; + for (i=0; i<100; i++ ) + { + break; + i = ( X || Y ) ; + } +} + diff --git a/final/test/FrontendC/2005-07-20-SqrtNoErrno.c b/final/test/FrontendC/2005-07-20-SqrtNoErrno.c new file mode 100644 index 00000000000..a321a3884e8 --- /dev/null +++ b/final/test/FrontendC/2005-07-20-SqrtNoErrno.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o - -fno-math-errno | FileCheck %s +// llvm.sqrt has undefined behavior on negative inputs, so it is +// inappropriate to translate C/C++ sqrt to this. +#include + +float foo(float X) { +// CHECK: foo +// CHECK: sqrtf(float %1) nounwind readonly + // Check that this is marked readonly when errno is ignored. + return sqrtf(X); +} diff --git a/final/test/FrontendC/2005-07-26-UnionInitCrash.c b/final/test/FrontendC/2005-07-26-UnionInitCrash.c new file mode 100644 index 00000000000..563278a9c68 --- /dev/null +++ b/final/test/FrontendC/2005-07-26-UnionInitCrash.c @@ -0,0 +1,3 @@ +// PR607 +// RUN: %llvmgcc %s -S -o - +union { char bytes[8]; double alignment; }EQ1 = {0,0,0,0,0,0,0,0}; diff --git a/final/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c b/final/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c new file mode 100644 index 00000000000..1a8c409439c --- /dev/null +++ b/final/test/FrontendC/2005-07-28-IncorrectWeakGlobal.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc %s -S -o - | grep TheGlobal | not grep weak + +extern int TheGlobal; +int foo() { return TheGlobal; } +int TheGlobal = 1; diff --git a/final/test/FrontendC/2005-09-20-ComplexConstants.c b/final/test/FrontendC/2005-09-20-ComplexConstants.c new file mode 100644 index 00000000000..209adc502fa --- /dev/null +++ b/final/test/FrontendC/2005-09-20-ComplexConstants.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc %s -S -o - | llvm-as -o /dev/null + +const double _Complex x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + diff --git a/final/test/FrontendC/2005-09-24-AsmUserPrefix.c b/final/test/FrontendC/2005-09-24-AsmUserPrefix.c new file mode 100644 index 00000000000..952c7b3c35d --- /dev/null +++ b/final/test/FrontendC/2005-09-24-AsmUserPrefix.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | llc | \ +// RUN: not grep _foo2 + +void foo() __asm__("foo2"); + +void bar() { + foo(); +} diff --git a/final/test/FrontendC/2005-09-24-BitFieldCrash.c b/final/test/FrontendC/2005-09-24-BitFieldCrash.c new file mode 100644 index 00000000000..b4c85ffb2d8 --- /dev/null +++ b/final/test/FrontendC/2005-09-24-BitFieldCrash.c @@ -0,0 +1,33 @@ +// RUN: %llvmgcc %s -S -o - + +struct tree_common {}; + +struct tree_int_cst { + struct tree_common common; + struct tree_int_cst_lowhi { + unsigned long long low; + long long high; + } int_cst; +}; + +enum XXX { yyy }; + +struct tree_function_decl { + struct tree_common common; + long long locus, y; + __extension__ enum XXX built_in_class : 2; + +}; + + +union tree_node { + struct tree_int_cst int_cst; + struct tree_function_decl function_decl; +}; + + +void foo (union tree_node * decl) { + decl->function_decl.built_in_class != 0; +} + + diff --git a/final/test/FrontendC/2005-10-18-VariableSizedElementCrash.c b/final/test/FrontendC/2005-10-18-VariableSizedElementCrash.c new file mode 100644 index 00000000000..b9166621db4 --- /dev/null +++ b/final/test/FrontendC/2005-10-18-VariableSizedElementCrash.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - + +int sub1(int i, char *pi) { + typedef int foo[i]; + struct bar {foo f1; int f2:3; int f3:4;} *p = (struct bar *) pi; + xxx(p->f1); + return p->f3; +} + diff --git a/final/test/FrontendC/2005-12-04-AttributeUsed.c b/final/test/FrontendC/2005-12-04-AttributeUsed.c new file mode 100644 index 00000000000..f47e977f486 --- /dev/null +++ b/final/test/FrontendC/2005-12-04-AttributeUsed.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | \ +// RUN: grep llvm.used | grep foo | grep X + +int X __attribute__((used)); +int Y; + +__attribute__((used)) void foo() {} + diff --git a/final/test/FrontendC/2005-12-04-DeclarationLineNumbers.c b/final/test/FrontendC/2005-12-04-DeclarationLineNumbers.c new file mode 100644 index 00000000000..f3f69ddb0bc --- /dev/null +++ b/final/test/FrontendC/2005-12-04-DeclarationLineNumbers.c @@ -0,0 +1,23 @@ +// RUN: %llvmgcc %s -S -g -o - | grep DW_TAG_compile_unit | count 1 +// PR664: ensure that line #'s are emitted for declarations + + +short test(short br_data_0, +short br_data_1, +short br_data_2, +short br_data_3, +short br_data_4, +short br_data_5, +short br_data_6, +short br_data_7) { + +short sm07 = br_data_0 + br_data_7; +short sm16 = br_data_1 + br_data_6; +short sm25 = br_data_2 + br_data_5; +short sm34 = br_data_3 + br_data_4; +short s0734 = sm07 + sm34; +short s1625 = sm16 + sm25; + +return s0734 + s1625; +} + diff --git a/final/test/FrontendC/2006-01-13-Includes.c b/final/test/FrontendC/2006-01-13-Includes.c new file mode 100644 index 00000000000..7fa0b3b5a6d --- /dev/null +++ b/final/test/FrontendC/2006-01-13-Includes.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -g -S -o - | grep {test/FrontendC} +// PR676 + +#include + +void test() { + printf("Hello World\n"); +} diff --git a/final/test/FrontendC/2006-01-13-StackSave.c b/final/test/FrontendC/2006-01-13-StackSave.c new file mode 100644 index 00000000000..ae8d9082101 --- /dev/null +++ b/final/test/FrontendC/2006-01-13-StackSave.c @@ -0,0 +1,11 @@ +// PR691 +// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \ +// RUN: llvm-dis | grep llvm.stacksave + +void test(int N) { + int i; + for (i = 0; i < N; ++i) { + int VLA[i]; + external(VLA); + } +} diff --git a/final/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c b/final/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c new file mode 100644 index 00000000000..eafcb62814b --- /dev/null +++ b/final/test/FrontendC/2006-01-16-BitCountIntrinsicsUnsigned.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | grep {llvm.ctlz.i32(i32} | count 3 +// RUN: %llvmgcc -S %s -o - | grep {llvm.ctlz.i32(i32} | grep declare | count 1 + +unsigned t2(unsigned X) { + return __builtin_clz(X); +} +int t1(int X) { + return __builtin_clz(X); +} diff --git a/final/test/FrontendC/2006-01-23-FileScopeAsm.c b/final/test/FrontendC/2006-01-23-FileScopeAsm.c new file mode 100644 index 00000000000..80e71955623 --- /dev/null +++ b/final/test/FrontendC/2006-01-23-FileScopeAsm.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \ +// RUN: llvm-dis | grep {foo\[12345\]} | count 5 + +__asm__ ("foo1"); +__asm__ ("foo2"); +__asm__ ("foo3"); +__asm__ ("foo4"); +__asm__ ("foo5"); diff --git a/final/test/FrontendC/2006-03-03-MissingInitializer.c b/final/test/FrontendC/2006-03-03-MissingInitializer.c new file mode 100644 index 00000000000..5e027b1894a --- /dev/null +++ b/final/test/FrontendC/2006-03-03-MissingInitializer.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o - | opt -std-compile-opts | \ +// RUN: llvm-dis | grep {@nate.*internal unnamed_addr global i32 0} + +struct X { int *XX; int Y;}; + +void foo() { + static int nate = 0; + struct X bob = { &nate, 14 }; + bar(&bob); +} + diff --git a/final/test/FrontendC/2006-03-16-VectorCtor.c b/final/test/FrontendC/2006-03-16-VectorCtor.c new file mode 100644 index 00000000000..b95593b1214 --- /dev/null +++ b/final/test/FrontendC/2006-03-16-VectorCtor.c @@ -0,0 +1,10 @@ +// Test that basic generic vector support works +// RUN: %llvmgcc %s -S -o - + +typedef int v4si __attribute__ ((__vector_size__ (16))); +void test(v4si *P, v4si *Q, float X) { + *P = (v4si){ X, X, X, X } * *Q; +} + +v4si G = (v4si){ 0.1, 1.2, 4.2, 17.2 }; + diff --git a/final/test/FrontendC/2006-03-17-KnRMismatch.c b/final/test/FrontendC/2006-03-17-KnRMismatch.c new file mode 100644 index 00000000000..19391122fca --- /dev/null +++ b/final/test/FrontendC/2006-03-17-KnRMismatch.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o - + +void regnode(int op); + +void regnode(op) +char op; +{ +} diff --git a/final/test/FrontendC/2006-05-01-AppleAlignmentPragma.c b/final/test/FrontendC/2006-05-01-AppleAlignmentPragma.c new file mode 100644 index 00000000000..c9050aa9e4e --- /dev/null +++ b/final/test/FrontendC/2006-05-01-AppleAlignmentPragma.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o - + +#ifdef __APPLE__ +/* test that X is layed out correctly when this pragma is used. */ +#pragma options align=mac68k +#endif + +struct S { + unsigned A; + unsigned short B; +} X; + diff --git a/final/test/FrontendC/2006-05-19-SingleEltReturn.c b/final/test/FrontendC/2006-05-19-SingleEltReturn.c new file mode 100644 index 00000000000..70c94c62052 --- /dev/null +++ b/final/test/FrontendC/2006-05-19-SingleEltReturn.c @@ -0,0 +1,23 @@ +// Test returning a single element aggregate value containing a double. +// RUN: %llvmgcc %s -S -o - + +struct X { + double D; +}; + +struct Y { + struct X x; +}; + +struct Y bar(); + +void foo(struct Y *P) { + *P = bar(); +} + +struct Y bar() { + struct Y a; + a.x.D = 0; + return a; +} + diff --git a/final/test/FrontendC/2006-07-31-PR854.c b/final/test/FrontendC/2006-07-31-PR854.c new file mode 100644 index 00000000000..3802de8fc45 --- /dev/null +++ b/final/test/FrontendC/2006-07-31-PR854.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -w %s -S -o - +// PR854 + struct kernel_symbol { + unsigned long value; + }; + unsigned long loops_per_jiffy = (1<<12); + static const char __kstrtab_loops_per_jiffy[] +__attribute__((section("__ksymtab_strings"))) = "loops_per_jiffy"; + static const struct kernel_symbol __ksymtab_loops_per_jiffy +__attribute__((__used__)) __attribute__((section("__ksymtab"))) = { (unsigned +long)&loops_per_jiffy, __kstrtab_loops_per_jiffy }; diff --git a/final/test/FrontendC/2006-09-11-BitfieldRefCrash.c b/final/test/FrontendC/2006-09-11-BitfieldRefCrash.c new file mode 100644 index 00000000000..d06cc3afbf3 --- /dev/null +++ b/final/test/FrontendC/2006-09-11-BitfieldRefCrash.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o - +// PR906 + +struct state_struct { + unsigned long long phys_frame: 50; + unsigned valid : 2; +} s; + +int mem_access(struct state_struct *p) { + return p->valid; +} + diff --git a/final/test/FrontendC/2006-09-18-fwrite-cast-crash.c b/final/test/FrontendC/2006-09-18-fwrite-cast-crash.c new file mode 100644 index 00000000000..a693c5666f2 --- /dev/null +++ b/final/test/FrontendC/2006-09-18-fwrite-cast-crash.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc %s -S -o /dev/null +// PR910 +// XFAIL: * +// See PR2452 + +struct l_struct_2E_FILE { char x; }; +unsigned fwrite(signed char *, unsigned , unsigned , signed char *); +static signed char str301[39]; +static void Usage(signed char *ltmp_611_6) { + struct l_struct_2E_FILE *ltmp_6202_16; + unsigned ltmp_6203_92; + ltmp_6203_92 = /*tail*/ ((unsigned (*) (signed char *, unsigned , unsigned , +struct l_struct_2E_FILE *))(void*)fwrite)((&(str301[0u])), 38u, 1u, ltmp_6202_16); +} + diff --git a/final/test/FrontendC/2006-09-21-IncompleteElementType.c b/final/test/FrontendC/2006-09-21-IncompleteElementType.c new file mode 100644 index 00000000000..a5091821cb6 --- /dev/null +++ b/final/test/FrontendC/2006-09-21-IncompleteElementType.c @@ -0,0 +1,3 @@ +// RUN: not %llvmgcc %s -S -o /dev/null |& not grep {internal compiler error} + +struct A X[(927 - 37) / sizeof(struct A)]; diff --git a/final/test/FrontendC/2006-09-25-DebugFilename.c b/final/test/FrontendC/2006-09-25-DebugFilename.c new file mode 100644 index 00000000000..eea52ba7608 --- /dev/null +++ b/final/test/FrontendC/2006-09-25-DebugFilename.c @@ -0,0 +1,6 @@ +// RUN: not %llvmgcc -xc %s -S -o /dev/null |& \ +// RUN: grep fluffy | grep 2006-09-25-DebugFilename.c +#include "2006-09-25-DebugFilename.h" +int func1() { return hfunc1(); } +int func2() { fluffy; return hfunc1(); } + diff --git a/final/test/FrontendC/2006-09-25-DebugFilename.h b/final/test/FrontendC/2006-09-25-DebugFilename.h new file mode 100644 index 00000000000..9b03666b3c2 --- /dev/null +++ b/final/test/FrontendC/2006-09-25-DebugFilename.h @@ -0,0 +1,6 @@ +extern int exfunc(int a); + +static inline int hfunc1() +{ + return exfunc(1); +} diff --git a/final/test/FrontendC/2006-09-28-SimpleAsm.c b/final/test/FrontendC/2006-09-28-SimpleAsm.c new file mode 100644 index 00000000000..e3040200a60 --- /dev/null +++ b/final/test/FrontendC/2006-09-28-SimpleAsm.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -S -o - | grep {ext: xorl %eax, eax; movl} +// RUN: %llvmgcc %s -S -o - | grep {nonext: xorl %eax, %eax; mov} +// PR924 + +void bar() { + // Extended asm + asm volatile ("ext: xorl %%eax, eax; movl eax, fs; movl eax, gs %%blah %= %% " : : "r"(1)); + // Non-extended asm. + asm volatile ("nonext: xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs %%blah %= %% "); +} diff --git a/final/test/FrontendC/2006-10-30-ArrayCrash.c b/final/test/FrontendC/2006-10-30-ArrayCrash.c new file mode 100644 index 00000000000..09464dd3a06 --- /dev/null +++ b/final/test/FrontendC/2006-10-30-ArrayCrash.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -O3 -S -o - %s +// PR954, PR911 + +extern void foo(); + +struct S { + short f1[3]; + unsigned int f2 : 1; +}; + +void bar() +{ + struct S *A; + + if (A->f2) + foo(); +} diff --git a/final/test/FrontendC/2006-12-14-ordered_expr.c b/final/test/FrontendC/2006-12-14-ordered_expr.c new file mode 100644 index 00000000000..8ff2eb60721 --- /dev/null +++ b/final/test/FrontendC/2006-12-14-ordered_expr.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -O3 -S %s -o - | grep {fcmp ord float %X, %Y} + +int test2(float X, float Y) { + return !__builtin_isunordered(X, Y); +} + diff --git a/final/test/FrontendC/2007-01-06-KNR-Proto.c b/final/test/FrontendC/2007-01-06-KNR-Proto.c new file mode 100644 index 00000000000..6aa74d4cb25 --- /dev/null +++ b/final/test/FrontendC/2007-01-06-KNR-Proto.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S -o - %s +// PR1083 + +int svc_register (void (*dispatch) (int)); + +int svc_register (dispatch) + void (*dispatch) (); +{ +} + diff --git a/final/test/FrontendC/2007-01-20-VectorICE.c b/final/test/FrontendC/2007-01-20-VectorICE.c new file mode 100644 index 00000000000..c2dcdef1944 --- /dev/null +++ b/final/test/FrontendC/2007-01-20-VectorICE.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o - + +typedef float __m128 __attribute__((__vector_size__(16))); +typedef long long __v2di __attribute__((__vector_size__(16))); +typedef int __v4si __attribute__((__vector_size__(16))); + +__v2di bar(void); +void foo(int X, __v4si *P) { + *P = X == 2 ? bar() : bar(); +} + diff --git a/final/test/FrontendC/2007-01-24-InlineAsmCModifier.c b/final/test/FrontendC/2007-01-24-InlineAsmCModifier.c new file mode 100644 index 00000000000..c601ccf2eb1 --- /dev/null +++ b/final/test/FrontendC/2007-01-24-InlineAsmCModifier.c @@ -0,0 +1,10 @@ +// Verify that the %c modifier works and strips off any prefixes from +// immediates. +// RUN: %llvmgcc -S %s -o - | llc | grep {pickANumber: 789514} + +void foo() { + __asm__ volatile("/* " "pickANumber" ": %c0 */"::"i"(0xC0C0A)); + + // Check that non-c modifiers work also (not greped for above). + __asm__ volatile("/* " "pickANumber2 " ": %0 */"::"i"(123)); +} diff --git a/final/test/FrontendC/2007-02-04-AddrLValue-2.c b/final/test/FrontendC/2007-02-04-AddrLValue-2.c new file mode 100644 index 00000000000..fa20faff3e1 --- /dev/null +++ b/final/test/FrontendC/2007-02-04-AddrLValue-2.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc %s -O3 -S -o - +// PR1173 + +struct S { char s; }; +struct T { struct S t; }; + +struct S *const p = &((struct T * const) (0x4000))->t; + +void +foo (void) +{ + p->s = 0; +} diff --git a/final/test/FrontendC/2007-02-04-AddrLValue.c b/final/test/FrontendC/2007-02-04-AddrLValue.c new file mode 100644 index 00000000000..214fce7747c --- /dev/null +++ b/final/test/FrontendC/2007-02-04-AddrLValue.c @@ -0,0 +1,23 @@ +// RUN: %llvmgcc %s -O3 -S -o - +// PR1176 + +typedef struct +{ + char *key; + char *value; +} T1; + +typedef struct +{ + long type; + char *value; +} T3; + +T1 a[] = +{ + { + "", + ((char *)&((T3) {1, (char *) 1})) + } +}; + diff --git a/final/test/FrontendC/2007-02-04-EmptyStruct.c b/final/test/FrontendC/2007-02-04-EmptyStruct.c new file mode 100644 index 00000000000..5ad2c705cce --- /dev/null +++ b/final/test/FrontendC/2007-02-04-EmptyStruct.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -O3 -S -o - +// PR1175 + +struct empty { }; + +void foo(struct empty *p) { + p++; +} + diff --git a/final/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c b/final/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c new file mode 100644 index 00000000000..d5a9fbb0ecc --- /dev/null +++ b/final/test/FrontendC/2007-02-04-WITH_SIZE_EXPR.c @@ -0,0 +1,21 @@ +// RUN: %llvmgcc %s -O3 -S -o - +// PR1174 + +void zzz (char *s1, char *s2, int len, int *q) +{ + int z = 5; + unsigned int i, b; + struct { char a[z]; } x; + + for (i = 0; i < len; i++) + s1[i] = s2[i]; + + b = z & 0x3; + + len += (b == 0 ? 0 : 1) + z; + + *q = len; + + foo (x, x); +} + diff --git a/final/test/FrontendC/2007-02-05-nested.c b/final/test/FrontendC/2007-02-05-nested.c new file mode 100644 index 00000000000..bd6d30695ba --- /dev/null +++ b/final/test/FrontendC/2007-02-05-nested.c @@ -0,0 +1,54 @@ +// RUN: %llvmgcc -S -fnested-functions -O0 -o - %s +// PR915 + +extern void abort(void); + +void nest(int n) +{ + int a = 0; + int b = 5; + int c = 0; + int d = 7; + + void o(int i, int j) + { + if (i!=j) + abort(); + } + + void f(x) + int x; /* K&R style */ + { + int e = 0; + int f = 2; + int g = 0; + + void y(void) + { + c = n; + e = 1; + g = x; + } + + void z(void) + { + a = 4; + g = 3; + } + + a = 5; + y(); + c = x; + z(); + o(1,e); + o(2,f); + o(3,g); + } + + c = 2; + f(6); + o(4,a); + o(5,b); + o(6,c); + o(7,d); +} diff --git a/final/test/FrontendC/2007-02-07-AddrLabel.c b/final/test/FrontendC/2007-02-07-AddrLabel.c new file mode 100644 index 00000000000..03ed4c987e4 --- /dev/null +++ b/final/test/FrontendC/2007-02-07-AddrLabel.c @@ -0,0 +1,10 @@ +// PR947 +// RUN: %llvmgcc %s -S -o - + +void foo() { + void *ptr; + label: + ptr = &&label; + + goto *ptr; + } diff --git a/final/test/FrontendC/2007-02-16-VariableSizeStructArg.c b/final/test/FrontendC/2007-02-16-VariableSizeStructArg.c new file mode 100644 index 00000000000..ec6971acdb1 --- /dev/null +++ b/final/test/FrontendC/2007-02-16-VariableSizeStructArg.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S -w %s -o - +// PR1170 +int f(int a, struct {int b[a];} c) { return c.b[0]; } + +int g(struct {int b[1];} c) { + return c.b[0]; +} diff --git a/final/test/FrontendC/2007-02-16-VoidPtrDiff.c b/final/test/FrontendC/2007-02-16-VoidPtrDiff.c new file mode 100644 index 00000000000..15df28cae3f --- /dev/null +++ b/final/test/FrontendC/2007-02-16-VoidPtrDiff.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc %s -S -o - + +void foo(void *ptr, int test) { + (ptr - ((void *) test + 0x2000)); +} diff --git a/final/test/FrontendC/2007-02-16-WritableStrings.c b/final/test/FrontendC/2007-02-16-WritableStrings.c new file mode 100644 index 00000000000..8fa7f15dc6c --- /dev/null +++ b/final/test/FrontendC/2007-02-16-WritableStrings.c @@ -0,0 +1,7 @@ +// Test the -fwritable-strings option. + +// RUN: %llvmgcc -O3 -S -o - -fwritable-strings %s | \ +// RUN: grep {internal unnamed_addr global} +// RUN: %llvmgcc -O3 -S -o - %s | grep {private unnamed_addr constant} + +char *X = "foo"; diff --git a/final/test/FrontendC/2007-02-25-C-DotDotDot.c b/final/test/FrontendC/2007-02-25-C-DotDotDot.c new file mode 100644 index 00000000000..3f96fd1f9e1 --- /dev/null +++ b/final/test/FrontendC/2007-02-25-C-DotDotDot.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -O0 -S -o - -fno-inline -fno-unit-at-a-time %s | \ +// RUN: grep {call float @foo} + +// Make sure the call to foo is compiled as: +// call float @foo() +// not +// call float (...)* bitcast (float ()* @foo to float (...)*)( ) + +static float foo() { return 0.0; } +float bar() { return foo()*10.0;} + + diff --git a/final/test/FrontendC/2007-03-01-VarSizeArrayIdx.c b/final/test/FrontendC/2007-03-01-VarSizeArrayIdx.c new file mode 100644 index 00000000000..6ebe79672f5 --- /dev/null +++ b/final/test/FrontendC/2007-03-01-VarSizeArrayIdx.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -O3 -S -o - | grep mul +// PR1233 + +float foo(int w, float A[][w], int g, int h) { + return A[g][0]; +} + diff --git a/final/test/FrontendC/2007-03-05-DataLayout.c b/final/test/FrontendC/2007-03-05-DataLayout.c new file mode 100644 index 00000000000..18819f16908 --- /dev/null +++ b/final/test/FrontendC/2007-03-05-DataLayout.c @@ -0,0 +1,53 @@ +// Testcase for PR1242 +// RUN: %llvmgcc -S %s -o - | grep datalayout | \ +// RUN: not grep {"\[Ee\]-p:\[36\]\[24\]:\[36\]\[24\]"} +// END. +#include +#define NDIM 3 +#define BODY 01 +typedef double vector[NDIM]; +typedef struct bnode* bodyptr; +// { i16, double, [3 x double], i32, i32, [3 x double], [3 x double], [3 x +// double], double, \2 *, \2 * } +struct bnode { + short int type; + double mass; + vector pos; + int proc; + int new_proc; + vector vel; + vector acc; + vector new_acc; + double phi; + bodyptr next; + bodyptr proc_next; +} body; + +#define Type(x) ((x)->type) +#define Mass(x) ((x)->mass) +#define Pos(x) ((x)->pos) +#define Proc(x) ((x)->proc) +#define New_Proc(x) ((x)->new_proc) +#define Vel(x) ((x)->vel) +#define Acc(x) ((x)->acc) +#define New_Acc(x) ((x)->new_acc) +#define Phi(x) ((x)->phi) +#define Next(x) ((x)->next) +#define Proc_Next(x) ((x)->proc_next) + +bodyptr ubody_alloc(int p) +{ + register bodyptr tmp; + tmp = (bodyptr)malloc(sizeof(body)); + + Type(tmp) = BODY; + Proc(tmp) = p; + Proc_Next(tmp) = NULL; + New_Proc(tmp) = p; + return tmp; +} + +int main(int argc, char** argv) { + bodyptr b = ubody_alloc(17); + return 0; +} diff --git a/final/test/FrontendC/2007-03-06-VarSizeInStruct1.c b/final/test/FrontendC/2007-03-06-VarSizeInStruct1.c new file mode 100644 index 00000000000..b4ae5654931 --- /dev/null +++ b/final/test/FrontendC/2007-03-06-VarSizeInStruct1.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -w -S -o - +void* p (int n) { + struct f { + char w; char x[n]; char z[]; + } F; + F.x[0]='x'; + return &F; +} diff --git a/final/test/FrontendC/2007-03-06-VarSizeInStruct2.c b/final/test/FrontendC/2007-03-06-VarSizeInStruct2.c new file mode 100644 index 00000000000..13bc3aaf9ae --- /dev/null +++ b/final/test/FrontendC/2007-03-06-VarSizeInStruct2.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o - +char p (int n) { + struct f { + char w; char x[n]; char y[n]; + } F; + + return F.x[0]; +} diff --git a/final/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c b/final/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c new file mode 100644 index 00000000000..9b6a8690a33 --- /dev/null +++ b/final/test/FrontendC/2007-03-26-BitfieldAfterZeroWidth.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - +struct W {}; +struct Y { + struct W w; + int i:1; +} __attribute__ ((packed)) y; diff --git a/final/test/FrontendC/2007-03-26-ZeroWidthBitfield.c b/final/test/FrontendC/2007-03-26-ZeroWidthBitfield.c new file mode 100644 index 00000000000..89bfb8e1cb0 --- /dev/null +++ b/final/test/FrontendC/2007-03-26-ZeroWidthBitfield.c @@ -0,0 +1,2 @@ +// RUN: %llvmgcc %s -S -o - +struct Z { int :0; } z; diff --git a/final/test/FrontendC/2007-03-27-ArrayCompatible.c b/final/test/FrontendC/2007-03-27-ArrayCompatible.c new file mode 100644 index 00000000000..fa3d2db23cc --- /dev/null +++ b/final/test/FrontendC/2007-03-27-ArrayCompatible.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S %s -O2 -o - | grep {ret i8 0} +static char c(int n) { + char x[2][n]; + x[1][0]=0; + return *(n+(char *)x); +} + +char d(void) { + return c(2); +} diff --git a/final/test/FrontendC/2007-03-27-VarLengthArray.c b/final/test/FrontendC/2007-03-27-VarLengthArray.c new file mode 100644 index 00000000000..b555690068d --- /dev/null +++ b/final/test/FrontendC/2007-03-27-VarLengthArray.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | grep {getelementptr inbounds \\\[0 x i32\\\]} +extern void f(int *); +int e(int m, int n) { + int x[n]; + f(x); + return x[m]; +} diff --git a/final/test/FrontendC/2007-04-05-PackedBitFields-2.c b/final/test/FrontendC/2007-04-05-PackedBitFields-2.c new file mode 100644 index 00000000000..d9db4206c16 --- /dev/null +++ b/final/test/FrontendC/2007-04-05-PackedBitFields-2.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc %s -S -o - + +# define pck __attribute__((packed)) + + +struct pck F { + unsigned long long i : 12, + j : 23, + k : 27, + l; +}; +struct F f1; + +void foo() { + f1.l = 5; +} diff --git a/final/test/FrontendC/2007-04-05-PackedBitFields.c b/final/test/FrontendC/2007-04-05-PackedBitFields.c new file mode 100644 index 00000000000..f9de35639b0 --- /dev/null +++ b/final/test/FrontendC/2007-04-05-PackedBitFields.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc %s -S -o - + +# define pck __attribute__((packed)) + + +struct pck E { + unsigned long long l, + i : 12, + j : 23, + k : 29; }; + +struct E e1; + +void foo() { + e1.k = 5; +} diff --git a/final/test/FrontendC/2007-04-05-PackedStruct.c b/final/test/FrontendC/2007-04-05-PackedStruct.c new file mode 100644 index 00000000000..0d524c489ea --- /dev/null +++ b/final/test/FrontendC/2007-04-05-PackedStruct.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc %s -S -o - + +#pragma pack(push, 2) + +enum { + tA = 0, + tB = 1 +}; + +struct MyStruct { + unsigned long A; + char C; + void * B; +}; + +void bar(){ +struct MyStruct MS = { tB, 0 }; +} diff --git a/final/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c b/final/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c new file mode 100644 index 00000000000..acc38219925 --- /dev/null +++ b/final/test/FrontendC/2007-04-05-PadBeforeZeroLengthField.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - +struct c__ { unsigned int type:4; }; +union A { struct c__ c; } __attribute__((aligned(8))); +struct B { + unsigned int retainCount; + union A objects[]; +}; +void foo(union A * objects, struct B *array, unsigned long k) +{ array->objects[k] = objects[k]; } diff --git a/final/test/FrontendC/2007-04-05-UnPackedStruct.c b/final/test/FrontendC/2007-04-05-UnPackedStruct.c new file mode 100644 index 00000000000..9e168ed34fe --- /dev/null +++ b/final/test/FrontendC/2007-04-05-UnPackedStruct.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc %s -S -o - + + +enum { + tA = 0, + tB = 1 +}; + +struct MyStruct { + unsigned long A; + void * B; +}; + +void bar(){ +struct MyStruct MS = { tB, 0 }; +} diff --git a/final/test/FrontendC/2007-04-11-InlineAsmStruct.c b/final/test/FrontendC/2007-04-11-InlineAsmStruct.c new file mode 100644 index 00000000000..6c6c1509903 --- /dev/null +++ b/final/test/FrontendC/2007-04-11-InlineAsmStruct.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - | llc + +struct V { short X, Y; }; +int bar() { + struct V bar; + __asm__ volatile("foo %0\n" : "=r"(bar)); + return bar.X; +} + diff --git a/final/test/FrontendC/2007-04-11-InlineAsmUnion.c b/final/test/FrontendC/2007-04-11-InlineAsmUnion.c new file mode 100644 index 00000000000..014470102d3 --- /dev/null +++ b/final/test/FrontendC/2007-04-11-InlineAsmUnion.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - | llc + +union U { int x; float p; }; +void foo() { + union U bar; + __asm__ volatile("foo %0\n" : "=r"(bar)); +} diff --git a/final/test/FrontendC/2007-04-11-InlineStorageClassC89.c b/final/test/FrontendC/2007-04-11-InlineStorageClassC89.c new file mode 100644 index 00000000000..834fb07a262 --- /dev/null +++ b/final/test/FrontendC/2007-04-11-InlineStorageClassC89.c @@ -0,0 +1,46 @@ +// RUN: %llvmgcc %s -S -O0 -o - | grep define | grep xglobWeak | \ +// RUN: grep weak | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | grep xextWeak | \ +// RUN: grep weak | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | \ +// RUN: grep xWeaknoinline | grep weak | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | \ +// RUN: grep xWeakextnoinline | grep weak | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | \ +// RUN: grep xglobnoWeak | grep -v internal | grep -v weak | \ +// RUN: grep -v linkonce | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | \ +// RUN: grep xstatnoWeak | grep internal | count 1 +// RUN: %llvmgcc %s -S -O0 -o - | grep define | \ +// RUN: grep xextnoWeak | grep available_externally | grep -v weak | \ +// RUN: grep -v linkonce | count 1 +inline int xglobWeak(int) __attribute__((weak)); +inline int xglobWeak (int i) { + return i*2; +} +inline int xextWeak(int) __attribute__((weak)); +extern inline int xextWeak (int i) { + return i*4; +} +int xWeaknoinline(int) __attribute__((weak)); +int xWeaknoinline(int i) { + return i*8; +} +int xWeakextnoinline(int) __attribute__((weak)); +extern int xWeakextnoinline(int i) { + return i*16; +} +inline int xglobnoWeak (int i) { + return i*32; +} +static inline int xstatnoWeak (int i) { + return i*64; +} +extern inline int xextnoWeak (int i) { + return i*128; +} +int j(int y) { + return xglobnoWeak(y)+xstatnoWeak(y)+xextnoWeak(y)+ + xglobWeak(y)+xextWeak(y)+ + xWeakextnoinline(y)+xWeaknoinline(y); +} diff --git a/final/test/FrontendC/2007-04-11-InlineStorageClassC99.c b/final/test/FrontendC/2007-04-11-InlineStorageClassC99.c new file mode 100644 index 00000000000..6031071e346 --- /dev/null +++ b/final/test/FrontendC/2007-04-11-InlineStorageClassC99.c @@ -0,0 +1,46 @@ +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep declare | \ +// RUN: grep xglobWeak | grep extern_weak | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xextWeak | grep weak | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xWeaknoinline | grep weak | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xWeakextnoinline | grep weak | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xglobnoWeak | grep available_externally | grep -v weak | \ +// RUN: grep -v linkonce | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xstatnoWeak | grep internal | count 1 +// RUN: %llvmgcc -std=c99 %s -S -O0 -o - | grep define | \ +// RUN: grep xextnoWeak | grep -v available_externally | grep -v weak | \ +// RUN: grep -v linkonce | count 1 +inline int xglobWeak(int) __attribute__((weak)); +inline int xglobWeak (int i) { + return i*2; +} +inline int xextWeak(int) __attribute__((weak)); +extern inline int xextWeak (int i) { + return i*4; +} +int xWeaknoinline(int) __attribute__((weak)); +int xWeaknoinline(int i) { + return i*8; +} +int xWeakextnoinline(int) __attribute__((weak)); +extern int xWeakextnoinline(int i) { + return i*16; +} +inline int xglobnoWeak (int i) { + return i*32; +} +static inline int xstatnoWeak (int i) { + return i*64; +} +extern inline int xextnoWeak (int i) { + return i*128; +} +int j(int y) { + return xglobnoWeak(y)+xstatnoWeak(y)+xextnoWeak(y)+ + xglobWeak(y)+xextWeak(y)+ + xWeakextnoinline(y)+xWeaknoinline(y); +} diff --git a/final/test/FrontendC/2007-04-11-PR1321.c b/final/test/FrontendC/2007-04-11-PR1321.c new file mode 100644 index 00000000000..f391329a0f1 --- /dev/null +++ b/final/test/FrontendC/2007-04-11-PR1321.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o /dev/null + +struct X { + unsigned int e0 : 17; + unsigned int e1 : 17; + unsigned int e2 : 17; + unsigned int e3 : 17; + unsigned int e4 : 17; + unsigned int e5 : 17; + unsigned int e6 : 17; + unsigned int e7 : 17; +} __attribute__((packed)) x; diff --git a/final/test/FrontendC/2007-04-13-InlineAsmStruct2.c b/final/test/FrontendC/2007-04-13-InlineAsmStruct2.c new file mode 100644 index 00000000000..44ddeb3f95d --- /dev/null +++ b/final/test/FrontendC/2007-04-13-InlineAsmStruct2.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - | grep {call void asm} + +struct V { short X, Y; }; +int bar() { + struct V bar; + __asm__ volatile("foo %0\n" :: "r"(bar)); + return bar.X; +} + diff --git a/final/test/FrontendC/2007-04-13-InlineAsmUnion2.c b/final/test/FrontendC/2007-04-13-InlineAsmUnion2.c new file mode 100644 index 00000000000..a0944a7b640 --- /dev/null +++ b/final/test/FrontendC/2007-04-13-InlineAsmUnion2.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - | grep {call void asm} + +union U { int x; char* p; }; +void foo() { + union U bar; + __asm__ volatile("foo %0\n" :: "r"(bar)); +} diff --git a/final/test/FrontendC/2007-04-14-FNoBuiltin.c b/final/test/FrontendC/2007-04-14-FNoBuiltin.c new file mode 100644 index 00000000000..88bf0e01430 --- /dev/null +++ b/final/test/FrontendC/2007-04-14-FNoBuiltin.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -O2 -fno-builtin -o - | grep call.*printf +// Check that -fno-builtin is honored. + +extern int printf(const char*, ...); +void foo(const char *msg) { + printf("%s\n",msg); +} diff --git a/final/test/FrontendC/2007-04-17-ZeroSizeBitFields.c b/final/test/FrontendC/2007-04-17-ZeroSizeBitFields.c new file mode 100644 index 00000000000..ec7b7ea273f --- /dev/null +++ b/final/test/FrontendC/2007-04-17-ZeroSizeBitFields.c @@ -0,0 +1,4 @@ +// PR 1332 +// RUN: %llvmgcc %s -S -o /dev/null + +struct Z { int a:1; int :0; int c:1; } z; diff --git a/final/test/FrontendC/2007-04-24-VolatileStructCopy.c b/final/test/FrontendC/2007-04-24-VolatileStructCopy.c new file mode 100644 index 00000000000..d49e75e0254 --- /dev/null +++ b/final/test/FrontendC/2007-04-24-VolatileStructCopy.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -O3 -S -o - %s | grep {volatile store} +// PR1352 + +struct foo { + int x; +}; + +void copy(volatile struct foo *p, struct foo *q) { + *p = *q; +} diff --git a/final/test/FrontendC/2007-04-24-bit-not-expr.c b/final/test/FrontendC/2007-04-24-bit-not-expr.c new file mode 100644 index 00000000000..fab0b90bb15 --- /dev/null +++ b/final/test/FrontendC/2007-04-24-bit-not-expr.c @@ -0,0 +1,7 @@ +// PR 1346 +// RUN: %llvmgcc -S %s -o /dev/null +extern bar(void *); + +void f(void *cd) { + bar(((void *)((unsigned long)(cd) ^ -1))); +} diff --git a/final/test/FrontendC/2007-04-24-str-const.c b/final/test/FrontendC/2007-04-24-str-const.c new file mode 100644 index 00000000000..3c3dab372ab --- /dev/null +++ b/final/test/FrontendC/2007-04-24-str-const.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o /dev/null +static char *str; + +static const struct { + const char *name; + unsigned type; +} scan_special[] = { + {"shift", 1}, + {0, 0} +}; + +static void +sb(void) +{ + while (*str == ' ' || *str == '\t') + str++; +} diff --git a/final/test/FrontendC/2007-05-07-NestedStructReturn.c b/final/test/FrontendC/2007-05-07-NestedStructReturn.c new file mode 100644 index 00000000000..aea58e3ae8b --- /dev/null +++ b/final/test/FrontendC/2007-05-07-NestedStructReturn.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc %s -S -fnested-functions -o - | grep {sret *%agg.result} + +struct X { long m, n, o, p; }; + +struct X p(int n) { + struct X c(int m) { + struct X x; + x.m = m; + x.n = n; + return x; + } + return c(n); +} diff --git a/final/test/FrontendC/2007-05-07-PaddingElements.c b/final/test/FrontendC/2007-05-07-PaddingElements.c new file mode 100644 index 00000000000..1e4f4d0a751 --- /dev/null +++ b/final/test/FrontendC/2007-05-07-PaddingElements.c @@ -0,0 +1,12 @@ +// PR 1278 +// RUN: %llvmgcc %s -S -O0 -o - | grep {struct.s} | not grep "4 x i8] zeroinitializer" +// RUN: %llvmgcc %s -S -O0 -o - | not grep "i32 0, i32 2" +struct s { + double d1; + int s1; +}; + +struct s foo(void) { + struct s S = {1.1, 2}; + return S; +} diff --git a/final/test/FrontendC/2007-05-08-PCH.c b/final/test/FrontendC/2007-05-08-PCH.c new file mode 100644 index 00000000000..aa277ece99e --- /dev/null +++ b/final/test/FrontendC/2007-05-08-PCH.c @@ -0,0 +1,7 @@ +// PR 1400 +// RUN: %llvmgcc -x c-header %s -o /dev/null + +int main() { + return 0; +} + diff --git a/final/test/FrontendC/2007-05-11-str-const.c b/final/test/FrontendC/2007-05-11-str-const.c new file mode 100644 index 00000000000..46a74c19e01 --- /dev/null +++ b/final/test/FrontendC/2007-05-11-str-const.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S -g %s -o /dev/null + +static unsigned char out[]={0,1}; +static const unsigned char str1[]="1"; + diff --git a/final/test/FrontendC/2007-05-15-PaddingElement.c b/final/test/FrontendC/2007-05-15-PaddingElement.c new file mode 100644 index 00000000000..bad6a11dae8 --- /dev/null +++ b/final/test/FrontendC/2007-05-15-PaddingElement.c @@ -0,0 +1,23 @@ +// PR 1419 + +// RUN: %llvmgcc -xc -O2 %s -S -o - | grep "ret i32 1" +struct A { + short x; + long long :0; +}; + +struct B { + char a; + char b; + unsigned char i; +}; + +union X { struct A a; struct B b; }; + +int check(void) { + union X x, y; + + y.b.i = 0xff; + x = y; + return (x.b.i == 0xff); +} diff --git a/final/test/FrontendC/2007-05-16-EmptyStruct.c b/final/test/FrontendC/2007-05-16-EmptyStruct.c new file mode 100644 index 00000000000..7b2ab61bcca --- /dev/null +++ b/final/test/FrontendC/2007-05-16-EmptyStruct.c @@ -0,0 +1,5 @@ +// PR 1417 + +// RUN: %llvmgcc -xc %s -S -o - | grep "struct.anon = type \{\}" + +struct { } *X; diff --git a/final/test/FrontendC/2007-05-29-UnionCopy.c b/final/test/FrontendC/2007-05-29-UnionCopy.c new file mode 100644 index 00000000000..95ab388c842 --- /dev/null +++ b/final/test/FrontendC/2007-05-29-UnionCopy.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S -o - %s | grep memcpy +// PR1421 + +struct A { + char c; + int i; +}; + +struct B { + int c; + unsigned char x; +}; + +union U { struct A a; struct B b; }; + +void check(union U *u, union U *v) { + *u = *v; +} diff --git a/final/test/FrontendC/2007-06-05-NoInlineAttribute.c b/final/test/FrontendC/2007-06-05-NoInlineAttribute.c new file mode 100644 index 00000000000..9543538fb1b --- /dev/null +++ b/final/test/FrontendC/2007-06-05-NoInlineAttribute.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -O2 -S %s -o - | grep call + +static int bar(int x, int y) __attribute__((noinline)); + +static int bar(int x, int y) +{ + return x + y; +} + +int foo(int a, int b) { + return bar(b, a); +} + diff --git a/final/test/FrontendC/2007-06-15-AnnotateAttribute.c b/final/test/FrontendC/2007-06-15-AnnotateAttribute.c new file mode 100644 index 00000000000..115c3f73b90 --- /dev/null +++ b/final/test/FrontendC/2007-06-15-AnnotateAttribute.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc -S %s -o - | grep llvm.global.annotations +// RUN: %llvmgcc -S %s -o - | grep llvm.var.annotation | count 3 + +#include + +/* Global variable with attribute */ +int X __attribute__((annotate("GlobalValAnnotation"))); + +/* Function with attribute */ +int foo(int y) __attribute__((annotate("GlobalValAnnotation"))) + __attribute__((noinline)); + +int foo(int y __attribute__((annotate("LocalValAnnotation")))) { + int x __attribute__((annotate("LocalValAnnotation"))); + x = 34; + return y + x; +} + +int main() { + static int a __attribute__((annotate("GlobalValAnnotation"))); + a = foo(2); + printf("hello world%d\n", a); + return 0; +} diff --git a/final/test/FrontendC/2007-06-18-SextAttrAggregate.c b/final/test/FrontendC/2007-06-18-SextAttrAggregate.c new file mode 100644 index 00000000000..c395db220dc --- /dev/null +++ b/final/test/FrontendC/2007-06-18-SextAttrAggregate.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -o - -S -O3 | grep {i8 signext} +// PR1513 + +struct s{ +long a; +long b; +}; + +void f(struct s a, char *b, signed char C) { + +} diff --git a/final/test/FrontendC/2007-07-29-RestrictPtrArg.c b/final/test/FrontendC/2007-07-29-RestrictPtrArg.c new file mode 100644 index 00000000000..5925d972b26 --- /dev/null +++ b/final/test/FrontendC/2007-07-29-RestrictPtrArg.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - | grep noalias + +void foo(int * __restrict myptr1, int * myptr2) { + myptr1[0] = 0; + myptr2[0] = 0; +} diff --git a/final/test/FrontendC/2007-08-01-LoadStoreAlign.c b/final/test/FrontendC/2007-08-01-LoadStoreAlign.c new file mode 100644 index 00000000000..5365c06c257 --- /dev/null +++ b/final/test/FrontendC/2007-08-01-LoadStoreAlign.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -O3 -S -o - %s | grep {align 1} | count 2 +// RUN: %llvmgcc -O3 -S -o - %s | llc + +struct p { + char a; + int b; +} __attribute__ ((packed)); + +struct p t = { 1, 10 }; +struct p u; + +int main () { + int tmp = t.b; + u.b = tmp; + return tmp; + +} diff --git a/final/test/FrontendC/2007-08-21-ComplexCst.c b/final/test/FrontendC/2007-08-21-ComplexCst.c new file mode 100644 index 00000000000..ebdee14bba3 --- /dev/null +++ b/final/test/FrontendC/2007-08-21-ComplexCst.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -O2 -S %s -o /dev/null +void f(_Complex float z); +void g() { f(1.0i); } diff --git a/final/test/FrontendC/2007-08-22-CTTZ.c b/final/test/FrontendC/2007-08-22-CTTZ.c new file mode 100644 index 00000000000..9e74f24cdcb --- /dev/null +++ b/final/test/FrontendC/2007-08-22-CTTZ.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -O2 -S -o - %s | grep {llvm.cttz.i64} | count 2 +// RUN: %llvmgcc -O2 -S -o - %s | not grep {lshr} + +int bork(unsigned long long x) { + return __builtin_ctzll(x); +} diff --git a/final/test/FrontendC/2007-09-05-ConstCtor.c b/final/test/FrontendC/2007-09-05-ConstCtor.c new file mode 100644 index 00000000000..adae4a69b10 --- /dev/null +++ b/final/test/FrontendC/2007-09-05-ConstCtor.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -xc -Os -S %s -o /dev/null +// PR1641 + +struct A { + unsigned long l; +}; + +void bar(struct A *a); + +void bork() { + const unsigned long vcgt = 1234; + struct A a = { vcgt }; + bar(&a); +} diff --git a/final/test/FrontendC/2007-09-12-PragmaPack.c b/final/test/FrontendC/2007-09-12-PragmaPack.c new file mode 100644 index 00000000000..4fc7f48be01 --- /dev/null +++ b/final/test/FrontendC/2007-09-12-PragmaPack.c @@ -0,0 +1,30 @@ +// RUN: %llvmgcc -O3 -S -o - %s | grep {18} + +#include + +#pragma pack(push, 1) +typedef struct +{ + uint32_t a; +} foo; + +typedef struct { + uint8_t major; + uint8_t minor; + uint16_t build; +} VERSION; + +typedef struct { + uint8_t a[5]; + VERSION version; + uint8_t b; + foo d; + uint32_t guard; +} bar; +#pragma pack(pop) + + +unsigned barsize(void) { + return sizeof(bar); +} + diff --git a/final/test/FrontendC/2007-09-14-NegatePointer.c b/final/test/FrontendC/2007-09-14-NegatePointer.c new file mode 100644 index 00000000000..cb49e46ddb1 --- /dev/null +++ b/final/test/FrontendC/2007-09-14-NegatePointer.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - +// PR1662 + +int foo(unsigned char *test) { + return 0U - (unsigned int )test; +} + diff --git a/final/test/FrontendC/2007-09-17-WeakRef.c b/final/test/FrontendC/2007-09-17-WeakRef.c new file mode 100644 index 00000000000..6c420ea38a7 --- /dev/null +++ b/final/test/FrontendC/2007-09-17-WeakRef.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -O1 -S %s -o - | grep icmp +// PR1678 + +extern void B (void); +static __typeof(B) A __attribute__ ((__weakref__("B"))); +int active (void) +{ + static void *const p = __extension__ (void *) &A; + return p != 0; +} diff --git a/final/test/FrontendC/2007-09-20-GcrootAttribute.c b/final/test/FrontendC/2007-09-20-GcrootAttribute.c new file mode 100644 index 00000000000..b67b474c4c1 --- /dev/null +++ b/final/test/FrontendC/2007-09-20-GcrootAttribute.c @@ -0,0 +1,29 @@ +// RUN: %llvmgcc -S %s -o - | grep llvm.gcroot +// RUN: %llvmgcc -S %s -o - | grep llvm.gcroot | count 6 +// RUN: %llvmgcc -S %s -o - | llvm-as + +typedef struct foo_s +{ + int a; +} foo, __attribute__ ((gcroot)) *foo_p; + +foo my_foo; + +int alpha () +{ + foo my_foo2 = my_foo; + + return my_foo2.a; +} + +int bar (foo a) +{ + foo_p b; + return b->a; +} + +foo_p baz (foo_p a, foo_p b, foo_p *c) +{ + a = b = *c; + return a; +} diff --git a/final/test/FrontendC/2007-09-26-Alignment.c b/final/test/FrontendC/2007-09-26-Alignment.c new file mode 100644 index 00000000000..1638fed0587 --- /dev/null +++ b/final/test/FrontendC/2007-09-26-Alignment.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | grep {align 16} +extern p(int *); +int q(void) { + int x __attribute__ ((aligned (16))); + p(&x); + return x; +} diff --git a/final/test/FrontendC/2007-09-27-ComplexIntCompare.c b/final/test/FrontendC/2007-09-27-ComplexIntCompare.c new file mode 100644 index 00000000000..50626e548c6 --- /dev/null +++ b/final/test/FrontendC/2007-09-27-ComplexIntCompare.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o - +// PR1708 + +#include + +struct s { _Complex unsigned short x; }; +struct s gs = { 100 + 200i }; +struct s __attribute__((noinline)) foo (void) { return gs; } + +int main () +{ + if (foo ().x != gs.x) + abort (); + exit (0); +} + + diff --git a/final/test/FrontendC/2007-09-28-PackedUnionMember.c b/final/test/FrontendC/2007-09-28-PackedUnionMember.c new file mode 100644 index 00000000000..79f48ceaeea --- /dev/null +++ b/final/test/FrontendC/2007-09-28-PackedUnionMember.c @@ -0,0 +1,38 @@ +// RUN: %llvmgcc %s -S -o - + +#pragma pack(push, 2) +struct H { + unsigned long f1; + unsigned long f2; + union { + struct opaque1 *f3; + struct opaque2 *f4; + struct { + struct opaque3 *f5; + unsigned short f6; + } f7; + } f8; +}; +#pragma pack(pop) + +struct E { + unsigned long f1; + unsigned long f2; +}; + +typedef long (*FuncPtr) (); + +extern long bork(FuncPtr handler, const struct E *list); + +static long hndlr() +{ + struct H cmd = { 4, 412 }; + return 0; +} +void foo(void *inWindow) { + static const struct E events[] = { + { 123124, 1 } + }; + bork(hndlr, events); +} + diff --git a/final/test/FrontendC/2007-10-01-BuildArrayRef.c b/final/test/FrontendC/2007-10-01-BuildArrayRef.c new file mode 100644 index 00000000000..e87a5b63054 --- /dev/null +++ b/final/test/FrontendC/2007-10-01-BuildArrayRef.c @@ -0,0 +1,20 @@ +// RUN: not %llvmgcc_only -c %s -o /dev/null |& FileCheck %s +// PR 1603 +void func() +{ + const int *arr; + arr[0] = 1; // CHECK: error: assignment of read-only location +} + +struct foo { + int bar; +}; +struct foo sfoo = { 0 }; + +int func2() +{ + const struct foo *fp; + fp = &sfoo; + fp[0].bar = 1; // CHECK: error: assignment of read-only member 'bar' + return sfoo.bar; +} diff --git a/final/test/FrontendC/2007-10-02-VolatileArray.c b/final/test/FrontendC/2007-10-02-VolatileArray.c new file mode 100644 index 00000000000..7e8bf24a84b --- /dev/null +++ b/final/test/FrontendC/2007-10-02-VolatileArray.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | grep volatile +// PR1647 + +void foo(volatile int *p) +{ +p[0] = 0; +} diff --git a/final/test/FrontendC/2007-10-15-VoidPtr.c b/final/test/FrontendC/2007-10-15-VoidPtr.c new file mode 100644 index 00000000000..c5948b93e16 --- /dev/null +++ b/final/test/FrontendC/2007-10-15-VoidPtr.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o /dev/null +void bork(void **data) { + (*(unsigned short *) (&(data[37])[927]) = 0); +} diff --git a/final/test/FrontendC/2007-10-30-Volatile.c b/final/test/FrontendC/2007-10-30-Volatile.c new file mode 100644 index 00000000000..7a75b05d5d2 --- /dev/null +++ b/final/test/FrontendC/2007-10-30-Volatile.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o /dev/null -Wall -Werror +void bork() { + char * volatile p; + volatile int cc; + p += cc; +} diff --git a/final/test/FrontendC/2007-11-07-AlignedMemcpy.c b/final/test/FrontendC/2007-11-07-AlignedMemcpy.c new file mode 100644 index 00000000000..eb9d22c6252 --- /dev/null +++ b/final/test/FrontendC/2007-11-07-AlignedMemcpy.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o /dev/null +void bork() { + int Qux[33] = {0}; +} diff --git a/final/test/FrontendC/2007-11-07-CopyAggregateAlign.c b/final/test/FrontendC/2007-11-07-CopyAggregateAlign.c new file mode 100644 index 00000000000..8bd94b00a78 --- /dev/null +++ b/final/test/FrontendC/2007-11-07-CopyAggregateAlign.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -S %s -o - | grep "align 2" | count 6 +struct A { char s, t, u, v; short a; }; +void q() { struct A a, b; a = b; } diff --git a/final/test/FrontendC/2007-11-07-ZeroAggregateAlign.c b/final/test/FrontendC/2007-11-07-ZeroAggregateAlign.c new file mode 100644 index 00000000000..424120d6c21 --- /dev/null +++ b/final/test/FrontendC/2007-11-07-ZeroAggregateAlign.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -S %s -o - | grep "align 2" +struct A { short s; short t; int i; }; +void q() { struct A a = {0}; } diff --git a/final/test/FrontendC/2007-11-27-SExtZExt.c b/final/test/FrontendC/2007-11-27-SExtZExt.c new file mode 100644 index 00000000000..8ea4786af36 --- /dev/null +++ b/final/test/FrontendC/2007-11-27-SExtZExt.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | grep "signext" | count 4 + +signed char foo1() { return 1; } + +void foo2(signed short a) { } + +signed char foo3(void) { return 1; } + +void foo4(a) signed short a; { } + + + diff --git a/final/test/FrontendC/2007-11-28-GlobalInitializer.c b/final/test/FrontendC/2007-11-28-GlobalInitializer.c new file mode 100644 index 00000000000..c8c7a594d0b --- /dev/null +++ b/final/test/FrontendC/2007-11-28-GlobalInitializer.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s -o - +// PR1744 +typedef struct foo { int x; char *p; } FOO; +extern FOO yy[]; + +int *y = &((yy + 1)->x); +void *z = &((yy + 1)->x); + diff --git a/final/test/FrontendC/2007-12-16-AsmNoUnwind.c b/final/test/FrontendC/2007-12-16-AsmNoUnwind.c new file mode 100644 index 00000000000..b080e6a511e --- /dev/null +++ b/final/test/FrontendC/2007-12-16-AsmNoUnwind.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc %s -S -o - | grep nounwind + +void bar() { asm (""); } diff --git a/final/test/FrontendC/2007-12-VarArrayDebug.c b/final/test/FrontendC/2007-12-VarArrayDebug.c new file mode 100644 index 00000000000..966789eef30 --- /dev/null +++ b/final/test/FrontendC/2007-12-VarArrayDebug.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S -g -O %s -o - | llc +// RUN: %llvmgcc -S -g %s -o - | llc + +extern void foo (void); + +static +void baz (int i) +{ + foo (); + typedef char A[i]; + struct { A b; } *x = 0; +} + +void +bar (i) +{ + baz (i); +} diff --git a/final/test/FrontendC/2008-01-04-WideBitfield.c b/final/test/FrontendC/2008-01-04-WideBitfield.c new file mode 100644 index 00000000000..a0045a40276 --- /dev/null +++ b/final/test/FrontendC/2008-01-04-WideBitfield.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -S -o - %s +// PR1386 +#include + +struct X { + unsigned char pad : 4; + uint64_t a : 64; +} __attribute__((packed)) x; + +uint64_t f(void) +{ + return x.a; +} diff --git a/final/test/FrontendC/2008-01-07-UnusualIntSize.c b/final/test/FrontendC/2008-01-07-UnusualIntSize.c new file mode 100644 index 00000000000..91beaf3528d --- /dev/null +++ b/final/test/FrontendC/2008-01-07-UnusualIntSize.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o - -O | grep i33 +// PR1721 + +struct s { + unsigned long long u33: 33; +} a, b; + +// This should turn into a real 33-bit add, not a 64-bit add. +_Bool test(void) { + return a.u33 + b.u33 != 0; +} diff --git a/final/test/FrontendC/2008-01-11-ChainConsistency.c b/final/test/FrontendC/2008-01-11-ChainConsistency.c new file mode 100644 index 00000000000..13e48a34ac5 --- /dev/null +++ b/final/test/FrontendC/2008-01-11-ChainConsistency.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc -S %s -o - -fnested-functions | not grep nest + +void n1(void) { void a(void) { a(); } a(); } diff --git a/final/test/FrontendC/2008-01-21-PackedBitFields.c b/final/test/FrontendC/2008-01-21-PackedBitFields.c new file mode 100644 index 00000000000..4c38dee408c --- /dev/null +++ b/final/test/FrontendC/2008-01-21-PackedBitFields.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - + +typedef double Al1Double __attribute__((aligned(1))); +struct x { int a:23; Al1Double v; }; +struct x X = { 5, 3.0 }; +double foo() { return X.v; } + diff --git a/final/test/FrontendC/2008-01-21-PackedStructField.c b/final/test/FrontendC/2008-01-21-PackedStructField.c new file mode 100644 index 00000000000..9cc1731063f --- /dev/null +++ b/final/test/FrontendC/2008-01-21-PackedStructField.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc %s -S -o - + +struct X { long double b; unsigned char c; double __attribute__((packed)) d; }; +struct X x = { 3.0L, 5, 3.0 }; + + +struct S2504 { + int e:17; + __attribute__((packed)) unsigned long long int f; +} ; +int fails; + extern struct S2504 s2504; +void check2504va (int z) { + struct S2504 arg, *p; + long long int i = 0; + arg.f = i; +} + diff --git a/final/test/FrontendC/2008-01-24-StructAlignAndBitFields.c b/final/test/FrontendC/2008-01-24-StructAlignAndBitFields.c new file mode 100644 index 00000000000..380a7ef77ca --- /dev/null +++ b/final/test/FrontendC/2008-01-24-StructAlignAndBitFields.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc %s -S -o - + +struct U { char a; short b; int c:25; char d; } u; + diff --git a/final/test/FrontendC/2008-01-25-ByValReadNone.c b/final/test/FrontendC/2008-01-25-ByValReadNone.c new file mode 100644 index 00000000000..4cb1a6394ea --- /dev/null +++ b/final/test/FrontendC/2008-01-25-ByValReadNone.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -O3 -S -o - %s | not grep readonly +// RUN: %llvmgcc -O3 -S -o - %s | not grep readnone + + +// The struct being passed byval means that we cannot mark the +// function readnone. Readnone would allow stores to the arg to +// be deleted in the caller. We also don't allow readonly since +// the callee might write to the byval parameter. The inliner +// would have to assume the worse and introduce an explicit +// temporary when inlining such a function, which is costly for +// the common case in which the byval argument is not written. +struct S { int A[1000]; }; +int __attribute__ ((const)) f(struct S x) { x.A[1] = 0; return x.A[0]; } +int g(struct S x) __attribute__ ((pure)); +int h(struct S x) { return g(x); } diff --git a/final/test/FrontendC/2008-01-25-ZeroSizedAggregate.c b/final/test/FrontendC/2008-01-25-ZeroSizedAggregate.c new file mode 100644 index 00000000000..643caffb6d2 --- /dev/null +++ b/final/test/FrontendC/2008-01-25-ZeroSizedAggregate.c @@ -0,0 +1,39 @@ +// RUN: %llvmgcc %s -S -o - + +// Aggregates of size zero should be dropped from argument list. +typedef long int Tlong; +struct S2411 { + __attribute__((aligned)) Tlong:0; +}; + +extern struct S2411 a2411[5]; +extern void checkx2411(struct S2411); +void test2411(void) { + checkx2411(a2411[0]); +} + +// Proper handling of zero sized fields during type conversion. +typedef unsigned long long int Tal2ullong __attribute__((aligned(2))); +struct S2525 { + Tal2ullong: 0; + struct { + } e; +}; +struct S2525 s2525; + +struct { + signed char f; + char :0; + struct{}h; + char * i[5]; +} data; + +// Taking address of a zero sized field. +struct Z {}; +struct Y { + int i; + struct Z z; +}; +void *f(struct Y *y) { + return &y->z; +} diff --git a/final/test/FrontendC/2008-01-28-PragmaMark.c b/final/test/FrontendC/2008-01-28-PragmaMark.c new file mode 100644 index 00000000000..6a4b5b52ff2 --- /dev/null +++ b/final/test/FrontendC/2008-01-28-PragmaMark.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -Werror -S %s -o /dev/null +#pragma mark LLVM's world +#ifdef DO_ERROR +#error LLVM's world +#endif +int i; diff --git a/final/test/FrontendC/2008-01-28-UnionSize.c b/final/test/FrontendC/2008-01-28-UnionSize.c new file mode 100644 index 00000000000..ea2c863b184 --- /dev/null +++ b/final/test/FrontendC/2008-01-28-UnionSize.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc %s -S -o - +// PR 1861 + +typedef unsigned char __u8; +typedef unsigned int __u32; +typedef unsigned short u16; +typedef __u32 __le32; +struct bcm43xx_plcp_hdr6 { + union { + __le32 data; + __u8 raw[6]; + } + __attribute__((__packed__)); +} + __attribute__((__packed__)); +struct bcm43xx_txhdr { + union { + struct { + struct bcm43xx_plcp_hdr6 plcp; + }; + }; +} + __attribute__((__packed__)); +static void bcm43xx_generate_rts(struct bcm43xx_txhdr *txhdr ) { } diff --git a/final/test/FrontendC/2008-02-11-AnnotateBuiltin.c b/final/test/FrontendC/2008-02-11-AnnotateBuiltin.c new file mode 100644 index 00000000000..32bc7a82745 --- /dev/null +++ b/final/test/FrontendC/2008-02-11-AnnotateBuiltin.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - | llvm-as | llvm-dis | grep llvm.annotation + +int main() { + int x = 0; + return __builtin_annotation(x, "annotate"); +} + diff --git a/final/test/FrontendC/2008-03-03-CtorAttrType.c b/final/test/FrontendC/2008-03-03-CtorAttrType.c new file mode 100644 index 00000000000..96648f4ec5a --- /dev/null +++ b/final/test/FrontendC/2008-03-03-CtorAttrType.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - | grep llvm.global_ctors +int __attribute__((constructor)) foo(void) { + return 0; +} +void __attribute__((constructor)) bar(void) {} + diff --git a/final/test/FrontendC/2008-03-05-syncPtr.c b/final/test/FrontendC/2008-03-05-syncPtr.c new file mode 100644 index 00000000000..7b271f7ee74 --- /dev/null +++ b/final/test/FrontendC/2008-03-05-syncPtr.c @@ -0,0 +1,27 @@ +// RUN: %llvmgcc %s -S -o - | grep llvm.atomic +// XFAIL: sparc-sun-solaris2|arm +// Feature currently implemented only for x86, alpha, powerpc. + +int* foo(int** a, int* b, int* c) { +return __sync_val_compare_and_swap (a, b, c); +} + +int foo2(int** a, int* b, int* c) { +return __sync_bool_compare_and_swap (a, b, c); +} + +int* foo3(int** a, int b) { + return __sync_fetch_and_add (a, b); +} + +int* foo4(int** a, int b) { + return __sync_fetch_and_sub (a, b); +} + +int* foo5(int** a, int* b) { + return __sync_lock_test_and_set (a, b); +} + +int* foo6(int** a, int*** b) { + return __sync_lock_test_and_set (a, b); +} diff --git a/final/test/FrontendC/2008-03-24-BitField-And-Alloca.c b/final/test/FrontendC/2008-03-24-BitField-And-Alloca.c new file mode 100644 index 00000000000..641bcf1dbeb --- /dev/null +++ b/final/test/FrontendC/2008-03-24-BitField-And-Alloca.c @@ -0,0 +1,89 @@ +// RUN: %llvmgcc -O2 -S %s -o - | not grep alloca +// RUN: %llvmgcc -m32 -O2 -S %s -o - | not grep {store } + +enum { + PP_C, + PP_D, + PP_R, + PP_2D, + PP_1D, + PP_SR, + PP_S2D, + PP_S1D, + PP_SC +}; + +enum { + G_VP, + G_FP, + G_VS, + G_GS, + G_FS +}; + +enum { + G_NONE, + G_B, + G_R +}; + +typedef union _Key { + struct { + unsigned int count : 2; + unsigned int Aconst : 1; + unsigned int Bconst : 1; + unsigned int Cconst : 1; + unsigned int Xused : 1; + unsigned int Yused : 1; + unsigned int Zused : 1; + unsigned int Wused : 1; + unsigned int ttype : 3; + unsigned int scalar : 1; + unsigned int AType : 4; + unsigned int BType : 4; + unsigned int CType : 4; + unsigned int RType : 4; + unsigned int Size : 2; + unsigned int prec : 1; + + unsigned int ASize : 2; + unsigned int BSize : 2; + unsigned int CSize : 2; + unsigned int tTex : 4; + unsigned int proj : 1; + unsigned int lod : 2; + unsigned int dvts : 1; + unsigned int uipad : 18; + } key_io; + struct { + unsigned int key0; + unsigned int key1; + } key; + unsigned long long lkey; +} Key; + +static void foo(const Key iospec, int* ret) +{ + *ret=0; + if(((iospec.key_io.lod == G_B) && + (iospec.key_io.ttype != G_VS) && + (iospec.key_io.ttype != G_GS) && + (iospec.key_io.ttype != G_FS)) || + + (((iospec.key_io.tTex == PP_C) || + (iospec.key_io.tTex == PP_SC)) && + ((iospec.key_io.tTex == PP_SR) || + (iospec.key_io.tTex == PP_S2D) || + (iospec.key_io.tTex == PP_S1D) || + (iospec.key_io.tTex == PP_SC)))) + *ret=1; +} + + +extern int bar(unsigned long long key_token2) +{ + int ret; + __attribute__ ((unused)) Key iospec = (Key) key_token2; + foo(iospec, &ret); + return ret; +} diff --git a/final/test/FrontendC/2008-03-26-PackedBitFields.c b/final/test/FrontendC/2008-03-26-PackedBitFields.c new file mode 100644 index 00000000000..7214281d020 --- /dev/null +++ b/final/test/FrontendC/2008-03-26-PackedBitFields.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - + + +struct S1757 { + long double c; + long int __attribute__((packed)) e:28; +} x; diff --git a/final/test/FrontendC/2008-04-08-NoExceptions.c b/final/test/FrontendC/2008-04-08-NoExceptions.c new file mode 100644 index 00000000000..257fee23b06 --- /dev/null +++ b/final/test/FrontendC/2008-04-08-NoExceptions.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S -o - %s | grep nounwind | count 2 +// RUN: %llvmgcc -S -o - %s | not grep {declare.*nounwind} + +void f(void); +void g(void) { + f(); +} diff --git a/final/test/FrontendC/2008-05-06-CFECrash.c b/final/test/FrontendC/2008-05-06-CFECrash.c new file mode 100644 index 00000000000..94d556c1ec2 --- /dev/null +++ b/final/test/FrontendC/2008-05-06-CFECrash.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S -O2 %s -o /dev/null +// PR2292. +__inline__ __attribute__ ((__pure__)) int g (void) {} +void f (int k) { k = g (); } diff --git a/final/test/FrontendC/2008-05-12-TempUsedBeforeDef.c b/final/test/FrontendC/2008-05-12-TempUsedBeforeDef.c new file mode 100644 index 00000000000..21724c1c830 --- /dev/null +++ b/final/test/FrontendC/2008-05-12-TempUsedBeforeDef.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -w -S -o /dev/null %s +// PR2264. +unsigned foo = 8L; +unsigned bar = 0L; +volatile unsigned char baz = 6L; +int test() { + char qux = 1L; + for (; baz >= -29; baz--) + bork(bar && foo, qux); +} diff --git a/final/test/FrontendC/2008-05-19-AlwaysInline.c b/final/test/FrontendC/2008-05-19-AlwaysInline.c new file mode 100644 index 00000000000..8dcb57b1862 --- /dev/null +++ b/final/test/FrontendC/2008-05-19-AlwaysInline.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -fno-unit-at-a-time -O0 -o - | not grep sabrina +// RUN: %llvmgcc %s -S -funit-at-a-time -O0 -o - | not grep sabrina + +static inline int sabrina (void) __attribute__((always_inline)); +static inline int sabrina (void) +{ + return 13; +} +int bar (void) +{ + return sabrina () + 68; +} diff --git a/final/test/FrontendC/2008-07-08-FAbsAttributes.c b/final/test/FrontendC/2008-07-08-FAbsAttributes.c new file mode 100644 index 00000000000..1eb01dcedbe --- /dev/null +++ b/final/test/FrontendC/2008-07-08-FAbsAttributes.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o - | grep readnone +// PR2520 +#include +double f(double *x, double *y) { return fabs(*x + *y); } diff --git a/final/test/FrontendC/2008-07-29-EHLabel.ll b/final/test/FrontendC/2008-07-29-EHLabel.ll new file mode 100644 index 00000000000..7577bc980ec --- /dev/null +++ b/final/test/FrontendC/2008-07-29-EHLabel.ll @@ -0,0 +1,282 @@ +; RUN: llc %s -o - | %llvmgcc -xassembler -c -o /dev/null - +; PR2609 + %struct..0._11 = type { i32 } + %struct..1__pthread_mutex_s = type { i32, i32, i32, i32, i32, %struct..0._11 } + %struct.pthread_attr_t = type { i32, [32 x i8] } + %struct.pthread_mutex_t = type { %struct..1__pthread_mutex_s } + %"struct.std::__ctype_abstract_base" = type { %"struct.std::locale::facet" } + %"struct.std::basic_ios >" = type { %"struct.std::ios_base", %"struct.std::basic_ostream >"*, i8, i8, %"struct.std::basic_streambuf >"*, %"struct.std::ctype"*, %"struct.std::__ctype_abstract_base"*, %"struct.std::__ctype_abstract_base"* } + %"struct.std::basic_istream >" = type { i32 (...)**, i32, %"struct.std::basic_ios >" } + %"struct.std::basic_istream >::sentry" = type { i8 } + %"struct.std::basic_ostream >" = type { i32 (...)**, %"struct.std::basic_ios >" } + %"struct.std::basic_streambuf >" = type { i32 (...)**, i8*, i8*, i8*, i8*, i8*, i8*, %"struct.std::locale" } + %"struct.std::ctype" = type { %"struct.std::locale::facet", i32*, i8, i32*, i32*, i16*, i8, [256 x i8], [256 x i8], i8 } + %"struct.std::ios_base" = type { i32 (...)**, i32, i32, i32, i32, i32, %"struct.std::ios_base::_Callback_list"*, %"struct.std::ios_base::_Words", [8 x %"struct.std::ios_base::_Words"], i32, %"struct.std::ios_base::_Words"*, %"struct.std::locale" } + %"struct.std::ios_base::_Callback_list" = type { %"struct.std::ios_base::_Callback_list"*, void (i32, %"struct.std::ios_base"*, i32)*, i32, i32 } + %"struct.std::ios_base::_Words" = type { i8*, i32 } + %"struct.std::locale" = type { %"struct.std::locale::_Impl"* } + %"struct.std::locale::_Impl" = type { i32, %"struct.std::locale::facet"**, i32, %"struct.std::locale::facet"**, i8** } + %"struct.std::locale::facet" = type { i32 (...)**, i32 } + +@_ZL20__gthrw_pthread_oncePiPFvvE = alias weak i32 (i32*, void ()*)* @pthread_once ; [#uses=0] +@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific ; [#uses=0] +@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific ; [#uses=0] +@_ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_ = alias weak i32 (i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*)* @pthread_create ; [#uses=0] +@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i32)* @pthread_cancel ; [#uses=0] +@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_lock ; [#uses=0] +@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_trylock ; [#uses=0] +@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%struct.pthread_mutex_t*)* @pthread_mutex_unlock ; [#uses=0] +@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak i32 (%struct.pthread_mutex_t*, %struct..0._11*)* @pthread_mutex_init ; [#uses=0] +@_ZL26__gthrw_pthread_key_createPjPFvPvE = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create ; [#uses=0] +@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete ; [#uses=0] +@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%struct..0._11*)* @pthread_mutexattr_init ; [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%struct..0._11*, i32)* @pthread_mutexattr_settype ; [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak i32 (%struct..0._11*)* @pthread_mutexattr_destroy ; [#uses=0] + +define %"struct.std::basic_istream >"* @_ZNSi7getlineEPcic(%"struct.std::basic_istream >"* %this, i8* %__s, i32 %__n, i8 signext %__delim) { +entry: + %__cerb = alloca %"struct.std::basic_istream >::sentry" ; <%"struct.std::basic_istream >::sentry"*> [#uses=2] + getelementptr %"struct.std::basic_istream >"* %this, i32 0, i32 1 ; :0 [#uses=7] + store i32 0, i32* %0, align 4 + call void @_ZNSi6sentryC1ERSib( %"struct.std::basic_istream >::sentry"* %__cerb, %"struct.std::basic_istream >"* %this, i8 zeroext 1 ) + getelementptr %"struct.std::basic_istream >::sentry"* %__cerb, i32 0, i32 0 ; :1 [#uses=1] + load i8* %1, align 8 ; :2 [#uses=1] + %toBool = icmp eq i8 %2, 0 ; [#uses=1] + br i1 %toBool, label %bb162, label %bb + +bb: ; preds = %entry + zext i8 %__delim to i32 ; :3 [#uses=1] + getelementptr %"struct.std::basic_istream >"* %this, i32 0, i32 0 ; :4 [#uses=1] + load i32 (...)*** %4, align 4 ; :5 [#uses=1] + getelementptr i32 (...)** %5, i32 -3 ; :6 [#uses=1] + bitcast i32 (...)** %6 to i32* ; :7 [#uses=1] + load i32* %7, align 4 ; :8 [#uses=1] + bitcast %"struct.std::basic_istream >"* %this to i8* ; :9 [#uses=1] + %ctg2186 = getelementptr i8* %9, i32 %8 ; [#uses=1] + bitcast i8* %ctg2186 to %"struct.std::basic_ios >"* ; <%"struct.std::basic_ios >"*>:10 [#uses=1] + getelementptr %"struct.std::basic_ios >"* %10, i32 0, i32 4 ; <%"struct.std::basic_streambuf >"**>:11 [#uses=1] + load %"struct.std::basic_streambuf >"** %11, align 4 ; <%"struct.std::basic_streambuf >"*>:12 [#uses=9] + getelementptr %"struct.std::basic_streambuf >"* %12, i32 0, i32 2 ; :13 [#uses=10] + load i8** %13, align 4 ; :14 [#uses=2] + getelementptr %"struct.std::basic_streambuf >"* %12, i32 0, i32 3 ; :15 [#uses=6] + load i8** %15, align 4 ; :16 [#uses=1] + icmp ult i8* %14, %16 ; :17 [#uses=1] + br i1 %17, label %bb81, label %bb82 + +bb81: ; preds = %bb + load i8* %14, align 1 ; :18 [#uses=1] + zext i8 %18 to i32 ; :19 [#uses=1] + %.pre = getelementptr %"struct.std::basic_streambuf >"* %12, i32 0, i32 0 ; [#uses=1] + br label %bb119.preheader + +bb82: ; preds = %bb + getelementptr %"struct.std::basic_streambuf >"* %12, i32 0, i32 0 ; :20 [#uses=2] + load i32 (...)*** %20, align 4 ; :21 [#uses=1] + getelementptr i32 (...)** %21, i32 9 ; :22 [#uses=1] + load i32 (...)** %22, align 4 ; :23 [#uses=1] + bitcast i32 (...)* %23 to i32 (%"struct.std::basic_streambuf >"*)* ; >"*)*>:24 [#uses=1] + invoke i32 %24( %"struct.std::basic_streambuf >"* %12 ) + to label %bb119.preheader unwind label %lpad ; :25 [#uses=1] + +bb119.preheader: ; preds = %bb82, %bb81 + %.pre-phi = phi i32 (...)*** [ %.pre, %bb81 ], [ %20, %bb82 ] ; [#uses=4] + %__c79.0.ph = phi i32 [ %19, %bb81 ], [ %25, %bb82 ] ; [#uses=1] + sext i8 %__delim to i32 ; :26 [#uses=1] + br label %bb119 + +bb84: ; preds = %bb119 + sub i32 %__n, %82 ; :27 [#uses=1] + add i32 %27, -1 ; :28 [#uses=2] + load i8** %15, align 4 ; :29 [#uses=1] + ptrtoint i8* %29 to i32 ; :30 [#uses=1] + load i8** %13, align 4 ; :31 [#uses=3] + ptrtoint i8* %31 to i32 ; :32 [#uses=2] + sub i32 %30, %32 ; :33 [#uses=2] + icmp slt i32 %28, %33 ; :34 [#uses=1] + select i1 %34, i32 %28, i32 %33 ; :35 [#uses=3] + icmp sgt i32 %35, 1 ; :36 [#uses=1] + br i1 %36, label %bb90, label %bb99 + +bb90: ; preds = %bb84 + call i8* @memchr( i8* %31, i32 %26, i32 %35 ) nounwind readonly ; :37 [#uses=2] + icmp eq i8* %37, null ; :38 [#uses=1] + br i1 %38, label %bb93, label %bb92 + +bb92: ; preds = %bb90 + ptrtoint i8* %37 to i32 ; :39 [#uses=1] + sub i32 %39, %32 ; :40 [#uses=1] + br label %bb93 + +bb93: ; preds = %bb92, %bb90 + %__size.0 = phi i32 [ %40, %bb92 ], [ %35, %bb90 ] ; [#uses=4] + call void @llvm.memcpy.i32( i8* %__s_addr.0, i8* %31, i32 %__size.0, i32 1 ) + getelementptr i8* %__s_addr.0, i32 %__size.0 ; :41 [#uses=3] + load i8** %13, align 4 ; :42 [#uses=1] + getelementptr i8* %42, i32 %__size.0 ; :43 [#uses=1] + store i8* %43, i8** %13, align 4 + load i32* %0, align 4 ; :44 [#uses=1] + add i32 %44, %__size.0 ; :45 [#uses=1] + store i32 %45, i32* %0, align 4 + load i8** %13, align 4 ; :46 [#uses=2] + load i8** %15, align 4 ; :47 [#uses=1] + icmp ult i8* %46, %47 ; :48 [#uses=1] + br i1 %48, label %bb95, label %bb96 + +bb95: ; preds = %bb93 + load i8* %46, align 1 ; :49 [#uses=1] + zext i8 %49 to i32 ; :50 [#uses=1] + br label %bb119 + +bb96: ; preds = %bb93 + load i32 (...)*** %.pre-phi, align 4 ; :51 [#uses=1] + getelementptr i32 (...)** %51, i32 9 ; :52 [#uses=1] + load i32 (...)** %52, align 4 ; :53 [#uses=1] + bitcast i32 (...)* %53 to i32 (%"struct.std::basic_streambuf >"*)* ; >"*)*>:54 [#uses=1] + invoke i32 %54( %"struct.std::basic_streambuf >"* %12 ) + to label %bb119 unwind label %lpad ; :55 [#uses=1] + +bb99: ; preds = %bb84 + trunc i32 %__c79.0 to i8 ; :56 [#uses=1] + store i8 %56, i8* %__s_addr.0, align 1 + getelementptr i8* %__s_addr.0, i32 1 ; :57 [#uses=5] + load i32* %0, align 4 ; :58 [#uses=1] + add i32 %58, 1 ; :59 [#uses=1] + store i32 %59, i32* %0, align 4 + load i8** %13, align 4 ; :60 [#uses=3] + load i8** %15, align 4 ; :61 [#uses=1] + icmp ult i8* %60, %61 ; :62 [#uses=1] + br i1 %62, label %bb101, label %bb102 + +bb101: ; preds = %bb99 + load i8* %60, align 1 ; :63 [#uses=1] + zext i8 %63 to i32 ; :64 [#uses=1] + getelementptr i8* %60, i32 1 ; :65 [#uses=1] + store i8* %65, i8** %13, align 4 + br label %bb104 + +bb102: ; preds = %bb99 + load i32 (...)*** %.pre-phi, align 4 ; :66 [#uses=1] + getelementptr i32 (...)** %66, i32 10 ; :67 [#uses=1] + load i32 (...)** %67, align 4 ; :68 [#uses=1] + bitcast i32 (...)* %68 to i32 (%"struct.std::basic_streambuf >"*)* ; >"*)*>:69 [#uses=1] + invoke i32 %69( %"struct.std::basic_streambuf >"* %12 ) + to label %bb104 unwind label %lpad ; :70 [#uses=1] + +bb104: ; preds = %bb102, %bb101 + %__ret44.0 = phi i32 [ %64, %bb101 ], [ %70, %bb102 ] ; [#uses=1] + icmp eq i32 %__ret44.0, -1 ; :71 [#uses=1] + br i1 %71, label %bb119, label %bb112 + +bb112: ; preds = %bb104 + load i8** %13, align 4 ; :72 [#uses=2] + load i8** %15, align 4 ; :73 [#uses=1] + icmp ult i8* %72, %73 ; :74 [#uses=1] + br i1 %74, label %bb114, label %bb115 + +bb114: ; preds = %bb112 + load i8* %72, align 1 ; :75 [#uses=1] + zext i8 %75 to i32 ; :76 [#uses=1] + br label %bb119 + +bb115: ; preds = %bb112 + load i32 (...)*** %.pre-phi, align 4 ; :77 [#uses=1] + getelementptr i32 (...)** %77, i32 9 ; :78 [#uses=1] + load i32 (...)** %78, align 4 ; :79 [#uses=1] + bitcast i32 (...)* %79 to i32 (%"struct.std::basic_streambuf >"*)* ; >"*)*>:80 [#uses=1] + invoke i32 %80( %"struct.std::basic_streambuf >"* %12 ) + to label %bb119 unwind label %lpad ; :81 [#uses=1] + +bb119: ; preds = %bb115, %bb114, %bb104, %bb96, %bb95, %bb119.preheader + %__c79.0 = phi i32 [ %__c79.0.ph, %bb119.preheader ], [ %50, %bb95 ], [ %76, %bb114 ], [ %55, %bb96 ], [ -1, %bb104 ], [ %81, %bb115 ] ; [#uses=3] + %__s_addr.0 = phi i8* [ %__s, %bb119.preheader ], [ %41, %bb95 ], [ %57, %bb114 ], [ %41, %bb96 ], [ %57, %bb104 ], [ %57, %bb115 ] ; [#uses=5] + load i32* %0, align 4 ; :82 [#uses=2] + add i32 %82, 1 ; :83 [#uses=2] + %.not = icmp sge i32 %83, %__n ; [#uses=1] + icmp eq i32 %__c79.0, -1 ; :84 [#uses=3] + icmp eq i32 %__c79.0, %3 ; :85 [#uses=2] + %or.cond = or i1 %84, %85 ; [#uses=1] + %or.cond188 = or i1 %or.cond, %.not ; [#uses=1] + br i1 %or.cond188, label %bb141, label %bb84 + +bb141: ; preds = %bb119 + %.not194 = xor i1 %85, true ; [#uses=1] + %brmerge = or i1 %84, %.not194 ; [#uses=1] + %.mux = select i1 %84, i32 2, i32 4 ; [#uses=0] + br i1 %brmerge, label %bb162, label %bb146 + +bb146: ; preds = %bb141 + store i32 %83, i32* %0, align 4 + load i8** %13, align 4 ; :86 [#uses=2] + load i8** %15, align 4 ; :87 [#uses=1] + icmp ult i8* %86, %87 ; :88 [#uses=1] + br i1 %88, label %bb148, label %bb149 + +bb148: ; preds = %bb146 + getelementptr i8* %86, i32 1 ; :89 [#uses=1] + store i8* %89, i8** %13, align 4 + ret %"struct.std::basic_istream >"* %this + +bb149: ; preds = %bb146 + load i32 (...)*** %.pre-phi, align 4 ; :90 [#uses=1] + getelementptr i32 (...)** %90, i32 10 ; :91 [#uses=1] + load i32 (...)** %91, align 4 ; :92 [#uses=1] + bitcast i32 (...)* %92 to i32 (%"struct.std::basic_streambuf >"*)* ; >"*)*>:93 [#uses=1] + invoke i32 %93( %"struct.std::basic_streambuf >"* %12 ) + to label %bb162 unwind label %lpad ; :94 [#uses=0] + +bb162: ; preds = %bb149, %bb141, %entry + ret %"struct.std::basic_istream >"* %this + +lpad: ; preds = %bb149, %bb115, %bb102, %bb96, %bb82 + %__s_addr.1 = phi i8* [ %__s, %bb82 ], [ %__s_addr.0, %bb149 ], [ %41, %bb96 ], [ %57, %bb102 ], [ %57, %bb115 ] ; [#uses=0] + call void @__cxa_rethrow( ) noreturn + unreachable +} + +declare i8* @__cxa_begin_catch(i8*) nounwind + +declare i8* @llvm.eh.exception() nounwind + +declare i32 @llvm.eh.selector.i32(i8*, i8*, ...) nounwind + +declare void @__cxa_rethrow() noreturn + +declare void @__cxa_end_catch() + +declare i32 @__gxx_personality_v0(...) + +declare void @_ZNSi6sentryC1ERSib(%"struct.std::basic_istream >::sentry"*, %"struct.std::basic_istream >"*, i8 zeroext ) + +declare i8* @memchr(i8*, i32, i32) nounwind readonly + +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind + +declare void @_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate(%"struct.std::basic_ios >"*, i32) + +declare extern_weak i32 @pthread_once(i32*, void ()*) + +declare extern_weak i8* @pthread_getspecific(i32) + +declare extern_weak i32 @pthread_setspecific(i32, i8*) + +declare extern_weak i32 @pthread_create(i32*, %struct.pthread_attr_t*, i8* (i8*)*, i8*) + +declare extern_weak i32 @pthread_cancel(i32) + +declare extern_weak i32 @pthread_mutex_lock(%struct.pthread_mutex_t*) + +declare extern_weak i32 @pthread_mutex_trylock(%struct.pthread_mutex_t*) + +declare extern_weak i32 @pthread_mutex_unlock(%struct.pthread_mutex_t*) + +declare extern_weak i32 @pthread_mutex_init(%struct.pthread_mutex_t*, %struct..0._11*) + +declare extern_weak i32 @pthread_key_create(i32*, void (i8*)*) + +declare extern_weak i32 @pthread_key_delete(i32) + +declare extern_weak i32 @pthread_mutexattr_init(%struct..0._11*) + +declare extern_weak i32 @pthread_mutexattr_settype(%struct..0._11*, i32) + +declare extern_weak i32 @pthread_mutexattr_destroy(%struct..0._11*) diff --git a/final/test/FrontendC/2008-08-07-AlignPadding1.c b/final/test/FrontendC/2008-08-07-AlignPadding1.c new file mode 100644 index 00000000000..6be9fe4ed3b --- /dev/null +++ b/final/test/FrontendC/2008-08-07-AlignPadding1.c @@ -0,0 +1,29 @@ +/* RUN: %llvmgcc %s -S -o - -O0 | grep {zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer.*zeroinitializer} + +The FE must generate padding here both at the end of each PyG_Head and +between array elements. Reduced from Python. */ + +typedef union _gc_head { + struct { + union _gc_head *gc_next; + union _gc_head *gc_prev; + long gc_refs; + } gc; + int dummy __attribute__((aligned(16))); +} PyGC_Head; + +struct gc_generation { + PyGC_Head head; + int threshold; + int count; +}; + +#define GEN_HEAD(n) (&generations[n].head) + +/* linked lists of container objects */ +static struct gc_generation generations[3] = { + /* PyGC_Head, threshold, count */ + {{{GEN_HEAD(0), GEN_HEAD(0), 0}}, 700, 0}, + {{{GEN_HEAD(1), GEN_HEAD(1), 0}}, 10, 0}, + {{{GEN_HEAD(2), GEN_HEAD(2), 0}}, 10, 0}, +}; diff --git a/final/test/FrontendC/2008-08-07-AlignPadding2.c b/final/test/FrontendC/2008-08-07-AlignPadding2.c new file mode 100644 index 00000000000..51135ba633a --- /dev/null +++ b/final/test/FrontendC/2008-08-07-AlignPadding2.c @@ -0,0 +1,18 @@ +/* RUN: %llvmgcc %s -S -o - -O0 | grep zeroinitializer | count 1 + +The FE must not generate padding here between array elements. PR 2533. */ + +typedef struct { + const char *name; + int flags; + union { + int x; + } u; +} OptionDef; + +const OptionDef options[] = { + /* main options */ + { "a", 0, {3} }, + { "b", 0, {4} }, + { 0, }, +}; diff --git a/final/test/FrontendC/2008-08-07-GEPIntToPtr.c b/final/test/FrontendC/2008-08-07-GEPIntToPtr.c new file mode 100644 index 00000000000..3ef3b66b88f --- /dev/null +++ b/final/test/FrontendC/2008-08-07-GEPIntToPtr.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - | grep {i8 1} +// PR2603 + +struct A { + char num_fields; +}; + +struct B { + char a, b[1]; +}; + +const struct A Foo = { + (char *)(&( (struct B *)(16) )->b[0]) - (char *)(16) +}; diff --git a/final/test/FrontendC/2008-09-03-WeakAlias.c b/final/test/FrontendC/2008-09-03-WeakAlias.c new file mode 100644 index 00000000000..2e5f3dae8a0 --- /dev/null +++ b/final/test/FrontendC/2008-09-03-WeakAlias.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S -O1 -o - %s | grep icmp +// PR1678 +extern void B (void); +static __typeof(B) A __attribute__ ((__weakref__("B"))); +int active (void) +{ + static void *const p = __extension__ (void *) &A; + return p != 0; +} diff --git a/final/test/FrontendC/2008-10-13-FrontendCrash.c b/final/test/FrontendC/2008-10-13-FrontendCrash.c new file mode 100644 index 00000000000..c9731e34ced --- /dev/null +++ b/final/test/FrontendC/2008-10-13-FrontendCrash.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -o - +// PR2797 + +unsigned int +func_48 (signed char p_49) +{ + signed char l_340; + func_44 (1&((1 ^ 1 == (lshift_u_s (1)) != (l_340 < 1)) & 1L)); +} diff --git a/final/test/FrontendC/2008-10-30-ZeroPlacement.c b/final/test/FrontendC/2008-10-30-ZeroPlacement.c new file mode 100644 index 00000000000..d73442dca8b --- /dev/null +++ b/final/test/FrontendC/2008-10-30-ZeroPlacement.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s +// PR2987 +struct S2045 +{ + unsigned short int a; + union { } b; + union __attribute__ ((aligned (4))) { } c[0]; +}; +struct S2045 s2045; diff --git a/final/test/FrontendC/2008-11-02-WeakAlias.c b/final/test/FrontendC/2008-11-02-WeakAlias.c new file mode 100644 index 00000000000..d10e57f5efe --- /dev/null +++ b/final/test/FrontendC/2008-11-02-WeakAlias.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S -o - %s | grep weak +// PR2691 + +void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); +void native_init_IRQ(void) {} diff --git a/final/test/FrontendC/2008-11-08-InstCombineSelect.c b/final/test/FrontendC/2008-11-08-InstCombineSelect.c new file mode 100644 index 00000000000..b850d3ff6f2 --- /dev/null +++ b/final/test/FrontendC/2008-11-08-InstCombineSelect.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc %s -S -O2 -o - +// PR3028 + +int g_187; +int g_204; +int g_434; + +int func_89 (void) +{ + return 1; +} + +void func_20 (int p_22) +{ + if (1 & p_22 | g_204 & (1 < g_187) - func_89 ()) + g_434 = 1; +} diff --git a/final/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c b/final/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c new file mode 100644 index 00000000000..8af59d54f75 --- /dev/null +++ b/final/test/FrontendC/2008-11-11-AnnotateStructFieldAttribute.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | grep llvm.ptr.annotation | count 3 + +#include + +/* Struct with element X being annotated */ +struct foo { + int X __attribute__((annotate("StructAnnotation"))); + int Y; + int Z; +}; + + +void test(struct foo *F) { + F->X = 42; + F->Z = 1; + F->Y = F->X; +} + diff --git a/final/test/FrontendC/2008-12-23-AsmIntPointerTie.c b/final/test/FrontendC/2008-12-23-AsmIntPointerTie.c new file mode 100644 index 00000000000..57061422b8f --- /dev/null +++ b/final/test/FrontendC/2008-12-23-AsmIntPointerTie.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -O1 -o - + +#include + +int test(void *b) { + intptr_t a; + __asm__ __volatile__ ("%0 %1 " : "=r" (a): "0" (b)); + return a; +} diff --git a/final/test/FrontendC/2009-01-05-BlockInlining.c b/final/test/FrontendC/2009-01-05-BlockInlining.c new file mode 100644 index 00000000000..8fb6e54514a --- /dev/null +++ b/final/test/FrontendC/2009-01-05-BlockInlining.c @@ -0,0 +1,28 @@ +// RUN: %llvmgcc %s -S -O2 -o %t.s +// RUN: grep {call i32 .*printf.*argc} %t.s | count 3 +// RUN: not grep __block_holder_tmp %t.s +// rdar://5865221 + +// All of these should be inlined equivalently into a single printf call. + +static int fun(int x) { + return x+1; +} + +static int block(int x) { + return (^(int x){return x+1;})(x); +} + +static void print(int result) { + printf("%d\n", result); +} + +int main (int argc, const char * argv[]) { + int x = argc-1; + print(fun(x)); + print(block(x)); + int (^block_inline)(int) = ^(int x){return x+1;}; + print(block_inline(x)); + return 0; +} + diff --git a/final/test/FrontendC/2009-01-20-k8.c b/final/test/FrontendC/2009-01-20-k8.c new file mode 100644 index 00000000000..2cd15387390 --- /dev/null +++ b/final/test/FrontendC/2009-01-20-k8.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc %s -S -march=k8 -o /dev/null +// XFAIL: * +// XTARGET: x86,i386,i686 +long double x; diff --git a/final/test/FrontendC/2009-01-21-InvalidIterator.c b/final/test/FrontendC/2009-01-21-InvalidIterator.c new file mode 100644 index 00000000000..6ac61f8a748 --- /dev/null +++ b/final/test/FrontendC/2009-01-21-InvalidIterator.c @@ -0,0 +1,74 @@ +// RUN: %llvmgcc %s -S -g -o /dev/null + +typedef long unsigned int size_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; +typedef uint16_t Elf64_Half; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef struct +{ + Elf64_Word p_type; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Xword p_align; +} +Elf64_Phdr; +struct dl_phdr_info +{ + const char *dlpi_name; + const Elf64_Phdr *dlpi_phdr; + Elf64_Half dlpi_phnum; + unsigned long long int dlpi_adds; +}; +typedef unsigned _Unwind_Ptr; +struct object +{ + union + { + const struct dwarf_fde *single; + struct dwarf_fde **array; + struct fde_vector *sort; + } + u; + union + { + struct + { + } + b; + } + s; + struct object *next; +}; +typedef int sword; +typedef unsigned int uword; +struct dwarf_fde +{ + uword length; + sword CIE_delta; + unsigned char pc_begin[]; +}; +typedef struct dwarf_fde fde; +struct unw_eh_callback_data +{ + const fde *ret; + struct frame_hdr_cache_element *link; +} +frame_hdr_cache[8]; + +_Unwind_Ptr +base_from_cb_data (struct unw_eh_callback_data *data) +{ +} + +void +_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr) +{ + const unsigned char *p; + const struct unw_eh_frame_hdr *hdr; + struct object ob; +} diff --git a/final/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c b/final/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c new file mode 100644 index 00000000000..947166d54ac --- /dev/null +++ b/final/test/FrontendC/2009-02-13-zerosize-union-field-ppc.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 32} | count 3 +// XFAIL: * +// XTARGET: powerpc +// Every printf has 'i32 0' for the GEP of the string; no point counting those. +typedef unsigned int Foo __attribute__((aligned(32))); +typedef union{Foo:0;}a; +typedef union{int x; Foo:0;}b; +extern int printf(const char*, ...); +main() { + printf("%ld\n", sizeof(a)); + printf("%ld\n", __alignof__(a)); + printf("%ld\n", sizeof(b)); + printf("%ld\n", __alignof__(b)); +} diff --git a/final/test/FrontendC/2009-02-13-zerosize-union-field.c b/final/test/FrontendC/2009-02-13-zerosize-union-field.c new file mode 100644 index 00000000000..ad335583d46 --- /dev/null +++ b/final/test/FrontendC/2009-02-13-zerosize-union-field.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 1} | count 1 +// RUN: %llvmgcc %s -m32 -S -o - | grep {i32 4} | count 2 +// XFAIL: powerpc +// Every printf has 'i32 0' for the GEP of the string; no point counting those. +typedef unsigned int Foo __attribute__((aligned(32))); +typedef union{Foo:0;}a; +typedef union{int x; Foo:0;}b; +extern int printf(const char*, ...); +main() { + printf("%ld\n", sizeof(a)); + printf("%ld\n", __alignof__(a)); + printf("%ld\n", sizeof(b)); + printf("%ld\n", __alignof__(b)); +} diff --git a/final/test/FrontendC/2009-02-17-BitField-dbg.c b/final/test/FrontendC/2009-02-17-BitField-dbg.c new file mode 100644 index 00000000000..80ccc4a0ea3 --- /dev/null +++ b/final/test/FrontendC/2009-02-17-BitField-dbg.c @@ -0,0 +1,14 @@ +// Check bitfields. +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o 2009-02-17-BitField-dbg.s +// RUN: %compile_c 2009-02-17-BitField-dbg.s -o 2009-02-17-BitField-dbg.o +// RUN: echo {ptype mystruct} > %t2 +// RUN: gdb -q -batch -n -x %t2 2009-02-17-BitField-dbg.o | \ +// RUN: tee 2009-02-17-BitField-dbg.out | grep "int a : 4" +// + +struct { + int a:4; + int b:2; +} mystruct; + diff --git a/final/test/FrontendC/2009-03-01-MallocNoAlias.c b/final/test/FrontendC/2009-03-01-MallocNoAlias.c new file mode 100644 index 00000000000..22ff6cb5c30 --- /dev/null +++ b/final/test/FrontendC/2009-03-01-MallocNoAlias.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc %s -S -o - | grep noalias + +void * __attribute__ ((malloc)) foo (void) { return 0; } diff --git a/final/test/FrontendC/2009-03-08-ZeroEltStructCrash.c b/final/test/FrontendC/2009-03-08-ZeroEltStructCrash.c new file mode 100644 index 00000000000..454e0fb79c6 --- /dev/null +++ b/final/test/FrontendC/2009-03-08-ZeroEltStructCrash.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S %s -o - +// PR3744 +struct Empty {}; +struct Union { + union { + int zero_arr[0]; + } contents; +}; +static inline void Foo(struct Union *u) { + int *array = u->contents.zero_arr; +} +static void Bar(struct Union *u) { + Foo(u); +} diff --git a/final/test/FrontendC/2009-03-09-WeakDeclarations-1.c b/final/test/FrontendC/2009-03-09-WeakDeclarations-1.c new file mode 100644 index 00000000000..13ea84f7bae --- /dev/null +++ b/final/test/FrontendC/2009-03-09-WeakDeclarations-1.c @@ -0,0 +1,22 @@ +// RUN: %llvmgcc_only %s -c -o /dev/null |& \ +// RUN: egrep {(14|15|22): warning:} | \ +// RUN: wc -l | grep --quiet 3 +// XTARGET: darwin,linux +// XFAIL: * +// END. +// Insist upon warnings for inappropriate weak attributes. +// Note the line numbers (14|15|22) embedded in the check. + +// O.K. +extern int ext_weak_import __attribute__ ((__weak_import__)); + +// These are inappropriate, and should generate warnings: +int decl_weak_import __attribute__ ((__weak_import__)); +int decl_initialized_weak_import __attribute__ ((__weak_import__)) = 13; + +// O.K. +extern int ext_f(void) __attribute__ ((__weak_import__)); + +// These are inappropriate, and should generate warnings: +int def_f(void) __attribute__ ((__weak_import__)); +int __attribute__ ((__weak_import__)) decl_f(void) {return 0;}; diff --git a/final/test/FrontendC/2009-03-13-dbg.c b/final/test/FrontendC/2009-03-13-dbg.c new file mode 100644 index 00000000000..46abd3a9638 --- /dev/null +++ b/final/test/FrontendC/2009-03-13-dbg.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc %s -S -g -o /dev/null +// XTARGET: darwin,linux +// XFAIL: * +void foo() {} + diff --git a/final/test/FrontendC/2009-04-22-UnknownSize.c b/final/test/FrontendC/2009-04-22-UnknownSize.c new file mode 100644 index 00000000000..7db9c0730c8 --- /dev/null +++ b/final/test/FrontendC/2009-04-22-UnknownSize.c @@ -0,0 +1,4 @@ +// RUN: not %llvmgcc -O1 %s -S -o /dev/null |& grep {error: storage size} +// PR2958 +static struct foo s; +struct foo *p = &s; diff --git a/final/test/FrontendC/2009-04-28-UnionArrayCrash.c b/final/test/FrontendC/2009-04-28-UnionArrayCrash.c new file mode 100644 index 00000000000..75851d0f5c0 --- /dev/null +++ b/final/test/FrontendC/2009-04-28-UnionArrayCrash.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S %s -o - +// PR4082 +union U { + int I; + double F; +}; + +union U arr[] = { { .I = 4 }, { .F = 123.} }; +union U *P = &arr[0]; + + diff --git a/final/test/FrontendC/2009-05-04-EnumInreg.c b/final/test/FrontendC/2009-05-04-EnumInreg.c new file mode 100644 index 00000000000..fb0c03e439e --- /dev/null +++ b/final/test/FrontendC/2009-05-04-EnumInreg.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S -m32 -mregparm=3 %s -o - | grep {inreg %action} +// XFAIL: * +// XTARGET: x86,i386,i686 +// PR3967 + +enum kobject_action { + KOBJ_ADD, + KOBJ_REMOVE, + KOBJ_CHANGE, + KOBJ_MOVE, + KOBJ_ONLINE, + KOBJ_OFFLINE, + KOBJ_MAX +}; + +struct kobject; + +int kobject_uevent(struct kobject *kobj, enum kobject_action action) {} diff --git a/final/test/FrontendC/2009-05-17-AlwaysInline.c b/final/test/FrontendC/2009-05-17-AlwaysInline.c new file mode 100644 index 00000000000..a93fabe0525 --- /dev/null +++ b/final/test/FrontendC/2009-05-17-AlwaysInline.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -O0 -o - -mllvm -disable-llvm-optzns | grep bar +// Check that the gcc inliner is turned off. + +#include +static __inline__ __attribute__ ((always_inline)) + int bar (int x) +{ + return 4; +} + +void +foo () +{ + long long b = 1; + int Y = bar (4); + printf ("%d\n", Y); +} diff --git a/final/test/FrontendC/2009-06-14-HighlyAligned.c b/final/test/FrontendC/2009-06-14-HighlyAligned.c new file mode 100644 index 00000000000..227db74f47a --- /dev/null +++ b/final/test/FrontendC/2009-06-14-HighlyAligned.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc %s -S -o /dev/null +// PR4332 + +static int highly_aligned __attribute__((aligned(4096))); + +int f() { + return highly_aligned; +} diff --git a/final/test/FrontendC/2009-06-18-StaticInitTailPadPack.c b/final/test/FrontendC/2009-06-18-StaticInitTailPadPack.c new file mode 100644 index 00000000000..17f35c04a9e --- /dev/null +++ b/final/test/FrontendC/2009-06-18-StaticInitTailPadPack.c @@ -0,0 +1,26 @@ +// RUN: %llvmgcc %s -S -o - +// rdar://6983634 + + typedef struct A *Foo; +#pragma pack(push, 2) + struct Bar { + Foo f1; + unsigned short f2; + float f3; + }; + struct Baz { + struct Bar f1; + struct Bar f2; + }; + struct Qux { + unsigned long f1; + struct Baz f2; + }; +extern const struct Qux Bork; +const struct Qux Bork = { + 0, + { + {0}, + {0} + } +}; diff --git a/final/test/FrontendC/2009-07-14-VoidPtr.c b/final/test/FrontendC/2009-07-14-VoidPtr.c new file mode 100644 index 00000000000..8001c56ad52 --- /dev/null +++ b/final/test/FrontendC/2009-07-14-VoidPtr.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - +// PR4556 + +extern void foo; +void *bar = &foo; + diff --git a/final/test/FrontendC/2009-07-15-pad-wchar_t-array.c b/final/test/FrontendC/2009-07-15-pad-wchar_t-array.c new file mode 100644 index 00000000000..41bdef25ecc --- /dev/null +++ b/final/test/FrontendC/2009-07-15-pad-wchar_t-array.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null + +#include +signed short _iodbcdm_sqlerror( ) +{ + wchar_t _sqlState[6] = { L"\0" }; +} diff --git a/final/test/FrontendC/2009-07-17-VoidParameter.c b/final/test/FrontendC/2009-07-17-VoidParameter.c new file mode 100644 index 00000000000..d5769524386 --- /dev/null +++ b/final/test/FrontendC/2009-07-17-VoidParameter.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc -S %s -o - +// PR4214 +typedef void vt; +void (*func_ptr)(vt my_vt); diff --git a/final/test/FrontendC/2009-07-22-StructLayout.c b/final/test/FrontendC/2009-07-22-StructLayout.c new file mode 100644 index 00000000000..74904da33e0 --- /dev/null +++ b/final/test/FrontendC/2009-07-22-StructLayout.c @@ -0,0 +1,34 @@ +// RUN: %llvmgcc %s -S -o /dev/null +// PR4590 + +typedef unsigned char __u8; +typedef unsigned int __le32; +typedef unsigned int __u32; +typedef unsigned short __le16; +typedef unsigned short __u16; + +struct usb_cdc_ether_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iMACAddress; + __le32 bmEthernetStatistics; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; + __u8 bNumberPowerFilters; +} __attribute__ ((packed)); + + +static struct usb_cdc_ether_desc ecm_desc __attribute__ ((__section__(".init.data"))) = { + .bLength = sizeof ecm_desc, + .bDescriptorType = ((0x01 << 5) | 0x04), + .bDescriptorSubType = 0x0f, + + + + .bmEthernetStatistics = (( __le32)(__u32)(0)), + .wMaxSegmentSize = (( __le16)(__u16)(1514)), + .wNumberMCFilters = (( __le16)(__u16)(0)), + .bNumberPowerFilters = 0, +}; diff --git a/final/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c b/final/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c new file mode 100644 index 00000000000..e141c9a16c8 --- /dev/null +++ b/final/test/FrontendC/2009-08-11-AsmBlocksComplexJumpTarget.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -fasm-blocks -S -o - | grep {\\\*1192} +// Complicated expression as jump target +// XFAIL: * +// XTARGET: x86,i386,i686 + +asm void Method3() +{ + mov eax,[esp+4] + jmp [eax+(299-1)*4] +} diff --git a/final/test/FrontendC/2009-09-24-SqrtErrno.c b/final/test/FrontendC/2009-09-24-SqrtErrno.c new file mode 100644 index 00000000000..09fc8764ea5 --- /dev/null +++ b/final/test/FrontendC/2009-09-24-SqrtErrno.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o - -fmath-errno | FileCheck %s +// llvm.sqrt has undefined behavior on negative inputs, so it is +// inappropriate to translate C/C++ sqrt to this. +#include + +float foo(float X) { +// CHECK: foo +// CHECK-NOT: readonly +// CHECK: return + // Check that this is not marked readonly when errno is used. + return sqrtf(X); +} diff --git a/final/test/FrontendC/2009-12-07-BitFieldAlignment.c b/final/test/FrontendC/2009-12-07-BitFieldAlignment.c new file mode 100644 index 00000000000..02ff8bce182 --- /dev/null +++ b/final/test/FrontendC/2009-12-07-BitFieldAlignment.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -m32 %s -S -o - | FileCheck %s +// Set alignment on bitfield accesses. + +struct S { + int a, b; + void *c; + unsigned d : 8; + unsigned e : 8; +}; + +void f0(struct S *a) { +// CHECK: load {{.*}}, align 4 +// CHECK: store {{.*}}, align 4 + a->e = 0; +} diff --git a/final/test/FrontendC/2010-01-05-LinkageName.c b/final/test/FrontendC/2010-01-05-LinkageName.c new file mode 100644 index 00000000000..9c1a2155032 --- /dev/null +++ b/final/test/FrontendC/2010-01-05-LinkageName.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc -O2 -S -g %s -o - | llc -o 2010-01-05-LinkageName.s -O0 +// RUN: %compile_c 2010-01-05-LinkageName.s -o 2010-01-05-LinkageName.s + +struct tm {}; +long mktime(struct tm *) __asm("_mktime$UNIX2003"); +tzload(name, sp, doextend){} +long mktime(tmp) + struct tm *const tmp; +{ + tzset(); +} +timelocal(tmp) { + return mktime(tmp); +} + diff --git a/final/test/FrontendC/2010-01-13-MemBarrier.c b/final/test/FrontendC/2010-01-13-MemBarrier.c new file mode 100644 index 00000000000..a540e59c6ca --- /dev/null +++ b/final/test/FrontendC/2010-01-13-MemBarrier.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s +// XFAIL: sparc +// rdar://7536390 + +unsigned t(unsigned *ptr, unsigned val) { + // CHECK: @t + // CHECK: call void @llvm.memory.barrier + // CHECK-NEXT: call i32 @llvm.atomic.swap.i32 + // CHECK-NEXT: call void @llvm.memory.barrier + return __sync_lock_test_and_set(ptr, val); +} diff --git a/final/test/FrontendC/2010-01-14-FnType-DebugInfo.c b/final/test/FrontendC/2010-01-14-FnType-DebugInfo.c new file mode 100644 index 00000000000..beaad91330b --- /dev/null +++ b/final/test/FrontendC/2010-01-14-FnType-DebugInfo.c @@ -0,0 +1,4 @@ +// RUN: %llvmgcc %s -S -g -o /dev/null +typedef void (*sigcatch_t)( struct sigcontext *); +sigcatch_t sigcatch[50] = {(sigcatch_t) 0}; + diff --git a/final/test/FrontendC/2010-01-14-StaticVariable.c b/final/test/FrontendC/2010-01-14-StaticVariable.c new file mode 100644 index 00000000000..80dd4d45259 --- /dev/null +++ b/final/test/FrontendC/2010-01-14-StaticVariable.c @@ -0,0 +1,12 @@ +// This is a regression test on debug info to make sure that llvm emitted +// debug info does not crash gdb. +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o %t.s -O0 -relocation-model=pic +// RUN: %compile_c %t.s -o %t.o +// RUN: echo {quit\n} > %t.in +// RUN: gdb -q -batch -n -x %t.in %t.o > /dev/null + +int foo() { + static int i = 42; + return i; +} diff --git a/final/test/FrontendC/2010-01-18-Inlined-Debug.c b/final/test/FrontendC/2010-01-18-Inlined-Debug.c new file mode 100644 index 00000000000..4aec7b26476 --- /dev/null +++ b/final/test/FrontendC/2010-01-18-Inlined-Debug.c @@ -0,0 +1,12 @@ +// PR: 6058 +// RUN: %llvmgcc -g -S %s -o - | llc -O0 -o /dev/null + +static inline int foo(double) __attribute__ ((always_inline)); +static inline int foo(double __x) { return __x; } + +void bar(double x) { + foo(x); +} + + + diff --git a/final/test/FrontendC/2010-02-10-PointerName.c b/final/test/FrontendC/2010-02-10-PointerName.c new file mode 100644 index 00000000000..7880fa8345e --- /dev/null +++ b/final/test/FrontendC/2010-02-10-PointerName.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -g -o - | grep DW_TAG_pointer_type | grep -v char + +char i = 1; +void foo() { + char *cp = &i; +} + diff --git a/final/test/FrontendC/2010-02-15-DbgStaticVar.c b/final/test/FrontendC/2010-02-15-DbgStaticVar.c new file mode 100644 index 00000000000..7827d96ce61 --- /dev/null +++ b/final/test/FrontendC/2010-02-15-DbgStaticVar.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -g -S %s -o - | grep "metadata ..b., metadata ..b., metadata ...," +// Test to check intentionally empty linkage name for a static variable. +// Radar 7651244. +static int foo(int a) +{ + static int b = 1; + return b+a; +} + +int main() { + int j = foo(1); + return 0; +} diff --git a/final/test/FrontendC/2010-02-16-DbgVarScope.c b/final/test/FrontendC/2010-02-16-DbgVarScope.c new file mode 100644 index 00000000000..1d912d0f5e5 --- /dev/null +++ b/final/test/FrontendC/2010-02-16-DbgVarScope.c @@ -0,0 +1,30 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o %t.s -O0 -relocation-model=pic +// RUN: %compile_c %t.s -o %t.o +// RUN: %link %t.o -o %t.exe +// RUN: echo {break 24\nrun\np loc\n} > %t.in +// RN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \ +// RN: grep {$1 = 1} + +int g1 = 1; +int g2 = 2; + +int __attribute__((always_inline)) bar() { + return g2 - g1; +} +void foobar() {} + +void foo(int s) { + unsigned loc = 0; + if (s) { + loc = 1; + foobar(); + } else { + loc = bar(); + foobar(); + } +} + +int main() { + foo(0); +} diff --git a/final/test/FrontendC/2010-02-18-Dbg-VectorType.c b/final/test/FrontendC/2010-02-18-Dbg-VectorType.c new file mode 100644 index 00000000000..d34031f09a1 --- /dev/null +++ b/final/test/FrontendC/2010-02-18-Dbg-VectorType.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_typedef | grep float4 +typedef float float4 __attribute__((vector_size(16))); + +int main(){ + volatile float4 x = (float4) { 0.0f, 1.0f, 2.0f, 3.0f }; + x += x; + return 0; +} + diff --git a/final/test/FrontendC/2010-03-10-arm-asmreg.c b/final/test/FrontendC/2010-03-10-arm-asmreg.c new file mode 100644 index 00000000000..70d3681ea40 --- /dev/null +++ b/final/test/FrontendC/2010-03-10-arm-asmreg.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s +// pr6552 + +// XFAIL: * +// XTARGET: arm + +extern void bar(unsigned int ip); + +// CHECK: mov r0, r12 +void foo(void) +{ + register unsigned int ip __asm ("ip"); + bar(ip); +} + diff --git a/final/test/FrontendC/2010-03-5-LexicalScope.c b/final/test/FrontendC/2010-03-5-LexicalScope.c new file mode 100644 index 00000000000..93a841a8f29 --- /dev/null +++ b/final/test/FrontendC/2010-03-5-LexicalScope.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_lexical_block | count 3 +int foo(int i) { + if (i) { + int j = 2; + } + else { + int j = 3; + } + return i; +} diff --git a/final/test/FrontendC/2010-05-14-Optimized-VarType.c b/final/test/FrontendC/2010-05-14-Optimized-VarType.c new file mode 100644 index 00000000000..2aa85b5846e --- /dev/null +++ b/final/test/FrontendC/2010-05-14-Optimized-VarType.c @@ -0,0 +1,23 @@ +// RUN: %llvmgcc %s -Os -S -g -o - | grep DW_TAG_structure_type | count 1 +// Variable 'a' is optimized but the debug info should preserve its type info. +#include + +struct foo { + int Attribute; +}; + +void *getfoo(void) __attribute__((noinline)); + +void *getfoo(void) +{ + int *x = malloc(sizeof(int)); + *x = 42; + return (void *)x; +} + +int main(int argc, char *argv[]) { + struct foo *a = (struct foo *)getfoo(); + + return a->Attribute; +} + diff --git a/final/test/FrontendC/2010-05-18-asmsched.c b/final/test/FrontendC/2010-05-18-asmsched.c new file mode 100644 index 00000000000..33b87703220 --- /dev/null +++ b/final/test/FrontendC/2010-05-18-asmsched.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc %s -S -O3 -o - | llc -march=x86-64 -mtriple=x86_64-apple-darwin | FileCheck %s +// r9 used to be clobbered before its value was moved to r10. 7993104. + +void foo(int x, int y) { +// CHECK: bar +// CHECK: movq %r9, %r10 +// CHECK: movq %rdi, %r9 +// CHECK: bar + register int lr9 asm("r9") = x; + register int lr10 asm("r10") = y; + int foo; + asm volatile("bar" : "=r"(lr9) : "r"(lr9), "r"(lr10)); + foo = lr9; + lr9 = x; + lr10 = foo; + asm volatile("bar" : "=r"(lr9) : "r"(lr9), "r"(lr10)); +} diff --git a/final/test/FrontendC/2010-05-18-palignr.c b/final/test/FrontendC/2010-05-18-palignr.c new file mode 100644 index 00000000000..0b78eed0dcd --- /dev/null +++ b/final/test/FrontendC/2010-05-18-palignr.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc -mssse3 -S -o - %s | llc -mtriple=x86_64-apple-darwin | FileCheck %s +// XFAIL: * +// XTARGET: x86,i386,i686 + +#include + +int main () +{ +#if defined( __SSSE3__ ) + +#define vec_rld_epi16( _a, _i ) ({ vSInt16 _t = _a; _t = _mm_alignr_epi8( _t, _t, _i ); /*return*/ _t; }) + typedef int16_t vSInt16 __attribute__ ((__vector_size__ (16))); + + short dtbl[] = {1,2,3,4,5,6,7,8}; + vSInt16 *vdtbl = (vSInt16*) dtbl; + + vSInt16 v0; + v0 = *vdtbl; + // CHECK: pshufd $57 + v0 = vec_rld_epi16( v0, 4 ); + + return 0; +#endif +} diff --git a/final/test/FrontendC/2010-05-26-AsmSideEffect.c b/final/test/FrontendC/2010-05-26-AsmSideEffect.c new file mode 100644 index 00000000000..acc38b783ba --- /dev/null +++ b/final/test/FrontendC/2010-05-26-AsmSideEffect.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s +// Radar 8026855 + +int test (void *src) { + register int w0 asm ("0"); + // CHECK: call i32 asm sideeffect + asm ("ldr %0, [%1]": "=r" (w0): "r" (src)); + // The asm to read the value of w0 has a sideeffect for a different reason + // (see 2010-05-18-asmsched.c) but that's not what this is testing for. + // CHECK: call i32 asm + return w0; +} diff --git a/final/test/FrontendC/2010-05-31-palignr.c b/final/test/FrontendC/2010-05-31-palignr.c new file mode 100644 index 00000000000..9da3145153f --- /dev/null +++ b/final/test/FrontendC/2010-05-31-palignr.c @@ -0,0 +1,24 @@ +// RUN: not %llvmgcc -mssse3 -S -o /dev/null %s |& grep "error: mask must be an immediate" +// XFAIL: * +// XTARGET: x86,i386,i686 + +#include + +extern int i; + +int main () +{ +#if defined( __SSSE3__ ) + + typedef int16_t vSInt16 __attribute__ ((__vector_size__ (16))); + + short dtbl[] = {1,2,3,4,5,6,7,8}; + vSInt16 *vdtbl = (vSInt16*) dtbl; + + vSInt16 v0; + v0 = *vdtbl; + v0 = _mm_alignr_epi8(v0, v0, i); + + return 0; +#endif +} diff --git a/final/test/FrontendC/2010-06-11-SaveExpr.c b/final/test/FrontendC/2010-06-11-SaveExpr.c new file mode 100644 index 00000000000..d1c122d79b4 --- /dev/null +++ b/final/test/FrontendC/2010-06-11-SaveExpr.c @@ -0,0 +1,8 @@ +// RUN: %llvmgcc -S %s +// Test case by Eric Postpischil! +void foo(void) +{ + char a[1]; + int t = 1; + ((char (*)[t]) a)[0][0] = 0; +} diff --git a/final/test/FrontendC/2010-06-17-asmcrash.c b/final/test/FrontendC/2010-06-17-asmcrash.c new file mode 100644 index 00000000000..5063054fd46 --- /dev/null +++ b/final/test/FrontendC/2010-06-17-asmcrash.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S -o - %s | llc -mtriple=x86_64-apple-darwin | FileCheck %s +// XFAIL: * +// XTARGET: x86,i386,i686 + +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef int64_t x86_reg; + +void avg_pixels8_mmx2(uint8_t *block, const uint8_t *pixels, int line_size, int h) +{ + __asm__ volatile("# %0 %1 %2 %3" + :"+g"(h), "+S"(pixels), "+D"(block) + :"r" ((x86_reg)line_size) + :"%""rax", "memory"); +// CHECK: # %ecx %rsi %rdi %rdx + } diff --git a/final/test/FrontendC/2010-06-28-DbgLocalVar.c b/final/test/FrontendC/2010-06-28-DbgLocalVar.c new file mode 100644 index 00000000000..e5df8856c0d --- /dev/null +++ b/final/test/FrontendC/2010-06-28-DbgLocalVar.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S -O2 -g %s -o - | llc -O2 -o %t.s +// RUN: grep DW_TAG_structure_type %t.s | count 2 +// Radar 8122864 + +// Code is not generated for function foo, but preserve type information of +// local variable xyz. +static foo() { + struct X { int a; int b; } xyz; +} + +int bar() { + foo(); + return 1; +} diff --git a/final/test/FrontendC/2010-06-28-nowarn.c b/final/test/FrontendC/2010-06-28-nowarn.c new file mode 100644 index 00000000000..3db8df10c18 --- /dev/null +++ b/final/test/FrontendC/2010-06-28-nowarn.c @@ -0,0 +1,21 @@ +// RUN: %llvmgcc %s -S -m32 -fasm-blocks -o /dev/null +// This should not warn about unreferenced label. 7729514. +// XFAIL: * +// XTARGET: x86,i386,i686 + +void quarterAsm(int array[], int len) +{ + __asm + { + mov esi, array; + mov ecx, len; + shr ecx, 2; +loop: + movdqa xmm0, [esi]; + psrad xmm0, 2; + movdqa [esi], xmm0; + add esi, 16; + sub ecx, 1; + jnz loop; + } +} diff --git a/final/test/FrontendC/2010-07-08-DeclDebugLineNo.c b/final/test/FrontendC/2010-07-08-DeclDebugLineNo.c new file mode 100644 index 00000000000..491b7dbe749 --- /dev/null +++ b/final/test/FrontendC/2010-07-08-DeclDebugLineNo.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | FileCheck %s +// Insure that dbg.declare lines for locals refer to correct line number records. +// Radar 8152866. +void foo() { + int l = 0; // line #4: CHECK: {{call.*llvm.dbg.declare.*%l.*\!dbg }}[[variable_l:![0-9]+]] + int p = 0; // line #5: CHECK: {{call.*llvm.dbg.declare.*%p.*\!dbg }}[[variable_p:![0-9]+]] +} +// Now match the line number records: +// CHECK: {{^}}[[variable_l]]{{ = metadata ![{]i32 5,}} +// CHECK: {{^}}[[variable_p]]{{ = metadata ![{]i32 6,}} diff --git a/final/test/FrontendC/2010-07-14-overconservative-align.c b/final/test/FrontendC/2010-07-14-overconservative-align.c new file mode 100644 index 00000000000..c4a9caac666 --- /dev/null +++ b/final/test/FrontendC/2010-07-14-overconservative-align.c @@ -0,0 +1,14 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s +// PR 5995 +struct s { + int word; + struct { + int filler __attribute__ ((aligned (8))); + }; +}; + +void func (struct s *s) +{ +// CHECK: load %struct.s** %s_addr, align {{[48]}} + s->word = 0; +} diff --git a/final/test/FrontendC/2010-07-14-ref-off-end.c b/final/test/FrontendC/2010-07-14-ref-off-end.c new file mode 100644 index 00000000000..c7fdd95a7aa --- /dev/null +++ b/final/test/FrontendC/2010-07-14-ref-off-end.c @@ -0,0 +1,27 @@ +// RUN: %llvmgcc %s -S -m32 -o - | FileCheck %s +// Formerly this generated code that did a load past the end of the structure. +// That was fixed by 46726, but that patch had bad side effects and was +// reverted. This has been fixed another way in the meantime. +extern void abort(); +extern void exit(int); +struct T +{ +unsigned i:8; +unsigned c:24; +}; +f(struct T t) +{ +struct T s[1]; +s[0]=t; +return(char)s->c; +} +main() +{ +// CHECK: getelementptr inbounds %struct.T* %t, i32 0, i32 0 +// CHECK: getelementptr inbounds %struct.T* %t, i32 0, i32 0 +struct T t; +t.i=0xff; +t.c=0xffff11; +if(f(t)!=0x11)abort(); +exit(0); +} diff --git a/final/test/FrontendC/2010-07-27-MinNoFoldConst.c b/final/test/FrontendC/2010-07-27-MinNoFoldConst.c new file mode 100644 index 00000000000..7cd8b4c4376 --- /dev/null +++ b/final/test/FrontendC/2010-07-27-MinNoFoldConst.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - | FileCheck %s +extern int printf(const char *, ...); +static void bad(unsigned int v1, unsigned int v2) { + printf("%u\n", 1631381461u * (((v2 - 1273463329u <= v1 - 1273463329u) ? v2 : v1) - 1273463329u) + 121322179u); +} +// Radar 8198362 +// GCC FE wants to convert the above to +// 1631381461u * MIN(v2 - 1273463329u, v1 - 1273463329u) +// and then to +// MIN(1631381461u * v2 - 4047041419, 1631381461u * v1 - 4047041419) +// +// 1631381461u * 1273463329u = 2077504466193943669, but 32-bit overflow clips +// this to 4047041419. This breaks the comparision implicit in the MIN(). +// Two multiply operations suggests the bad optimization is happening; +// one multiplication, after the MIN(), is correct. +// CHECK: mul +// CHECK-NOT: mul +// CHECK: ret diff --git a/final/test/FrontendC/2010-08-12-asm-aggr-arg.c b/final/test/FrontendC/2010-08-12-asm-aggr-arg.c new file mode 100644 index 00000000000..81ec14b2882 --- /dev/null +++ b/final/test/FrontendC/2010-08-12-asm-aggr-arg.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s +// Radar 8288710: A small aggregate can be passed as an integer. Make sure +// we don't get an error with "input constraint with a matching output +// constraint of incompatible type!" + +struct wrapper { + int i; +}; + +// CHECK: xyz +int test(int i) { + struct wrapper w; + w.i = i; + __asm__("xyz" : "=r" (w) : "0" (w)); + return w.i; +} diff --git a/final/test/FrontendC/2010-11-16-asmblock.c b/final/test/FrontendC/2010-11-16-asmblock.c new file mode 100644 index 00000000000..c2642235cfc --- /dev/null +++ b/final/test/FrontendC/2010-11-16-asmblock.c @@ -0,0 +1,16 @@ +// RUN: %llvmgcc -S %s -fasm-blocks -o - | FileCheck %s +// XFAIL: * +// XTARGET: x86,i386,i686 +// 84282548 + +void foo() +{ +// CHECK: %0 = call i32 asm sideeffect "", "={ecx}"() nounwind +// CHECK: %asmtmp = call i32 asm sideeffect alignstack "sall $$3, $0", "={ecx},{ecx},~{dirflag},~{fpsr},~{flags},~{memory}"(i32 %0) nounwind +// CHECK: store i32 %asmtmp, i32* %"%ecx" + __asm { + sal ecx, 3; + add esi, ecx; + add edi, ecx; + } +} diff --git a/final/test/FrontendC/2010-12-01-CommonGlobal.c b/final/test/FrontendC/2010-12-01-CommonGlobal.c new file mode 100644 index 00000000000..3f6d7e88580 --- /dev/null +++ b/final/test/FrontendC/2010-12-01-CommonGlobal.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -S %s -o - | llvm-as -o /dev/null +// Don't crash on a common-linkage constant global. +extern const int kABSourceTypeProperty; +int foo(void) { + return kABSourceTypeProperty; +} +const int kABSourceTypeProperty; diff --git a/final/test/FrontendC/2011-02-21-DATA-common.c b/final/test/FrontendC/2011-02-21-DATA-common.c new file mode 100644 index 00000000000..650ae7edddb --- /dev/null +++ b/final/test/FrontendC/2011-02-21-DATA-common.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc -S %s -o /dev/null +struct rtxc_snapshot { + int a, b, c, d; +}; +__attribute__ ((section("__DATA, __common"))) static struct rtxc_snapshot rtxc_log_A[4]; diff --git a/final/test/FrontendC/Atomics-no64bit.c b/final/test/FrontendC/Atomics-no64bit.c new file mode 100644 index 00000000000..6fb61098110 --- /dev/null +++ b/final/test/FrontendC/Atomics-no64bit.c @@ -0,0 +1,190 @@ +// Test frontend handling of __sync builtins. +// Modified from a gcc testcase. +// RUN: %llvmgcc -S %s -o - | grep atomic | count 150 +// RUN: %llvmgcc -S %s -o - | grep p0i8 | count 50 +// RUN: %llvmgcc -S %s -o - | grep p0i16 | count 50 +// RUN: %llvmgcc -S %s -o - | grep p0i32 | count 50 +// RUN: %llvmgcc -S %s -o - | grep volatile | count 6 + +// Currently this is implemented only for Alpha, X86, PowerPC. +// Add your target here if it doesn't work. +// This version of the test does not include long long. +// XFAIL: sparc,arm + +signed char sc; +unsigned char uc; +signed short ss; +unsigned short us; +signed int si; +unsigned int ui; + +void test_op_ignore (void) +{ + (void) __sync_fetch_and_add (&sc, 1); + (void) __sync_fetch_and_add (&uc, 1); + (void) __sync_fetch_and_add (&ss, 1); + (void) __sync_fetch_and_add (&us, 1); + (void) __sync_fetch_and_add (&si, 1); + (void) __sync_fetch_and_add (&ui, 1); + + (void) __sync_fetch_and_sub (&sc, 1); + (void) __sync_fetch_and_sub (&uc, 1); + (void) __sync_fetch_and_sub (&ss, 1); + (void) __sync_fetch_and_sub (&us, 1); + (void) __sync_fetch_and_sub (&si, 1); + (void) __sync_fetch_and_sub (&ui, 1); + + (void) __sync_fetch_and_or (&sc, 1); + (void) __sync_fetch_and_or (&uc, 1); + (void) __sync_fetch_and_or (&ss, 1); + (void) __sync_fetch_and_or (&us, 1); + (void) __sync_fetch_and_or (&si, 1); + (void) __sync_fetch_and_or (&ui, 1); + + (void) __sync_fetch_and_xor (&sc, 1); + (void) __sync_fetch_and_xor (&uc, 1); + (void) __sync_fetch_and_xor (&ss, 1); + (void) __sync_fetch_and_xor (&us, 1); + (void) __sync_fetch_and_xor (&si, 1); + (void) __sync_fetch_and_xor (&ui, 1); + + (void) __sync_fetch_and_and (&sc, 1); + (void) __sync_fetch_and_and (&uc, 1); + (void) __sync_fetch_and_and (&ss, 1); + (void) __sync_fetch_and_and (&us, 1); + (void) __sync_fetch_and_and (&si, 1); + (void) __sync_fetch_and_and (&ui, 1); + + (void) __sync_fetch_and_nand (&sc, 1); + (void) __sync_fetch_and_nand (&uc, 1); + (void) __sync_fetch_and_nand (&ss, 1); + (void) __sync_fetch_and_nand (&us, 1); + (void) __sync_fetch_and_nand (&si, 1); + (void) __sync_fetch_and_nand (&ui, 1); +} + +void test_fetch_and_op (void) +{ + sc = __sync_fetch_and_add (&sc, 11); + uc = __sync_fetch_and_add (&uc, 11); + ss = __sync_fetch_and_add (&ss, 11); + us = __sync_fetch_and_add (&us, 11); + si = __sync_fetch_and_add (&si, 11); + ui = __sync_fetch_and_add (&ui, 11); + + sc = __sync_fetch_and_sub (&sc, 11); + uc = __sync_fetch_and_sub (&uc, 11); + ss = __sync_fetch_and_sub (&ss, 11); + us = __sync_fetch_and_sub (&us, 11); + si = __sync_fetch_and_sub (&si, 11); + ui = __sync_fetch_and_sub (&ui, 11); + + sc = __sync_fetch_and_or (&sc, 11); + uc = __sync_fetch_and_or (&uc, 11); + ss = __sync_fetch_and_or (&ss, 11); + us = __sync_fetch_and_or (&us, 11); + si = __sync_fetch_and_or (&si, 11); + ui = __sync_fetch_and_or (&ui, 11); + + sc = __sync_fetch_and_xor (&sc, 11); + uc = __sync_fetch_and_xor (&uc, 11); + ss = __sync_fetch_and_xor (&ss, 11); + us = __sync_fetch_and_xor (&us, 11); + si = __sync_fetch_and_xor (&si, 11); + ui = __sync_fetch_and_xor (&ui, 11); + + sc = __sync_fetch_and_and (&sc, 11); + uc = __sync_fetch_and_and (&uc, 11); + ss = __sync_fetch_and_and (&ss, 11); + us = __sync_fetch_and_and (&us, 11); + si = __sync_fetch_and_and (&si, 11); + ui = __sync_fetch_and_and (&ui, 11); + + sc = __sync_fetch_and_nand (&sc, 11); + uc = __sync_fetch_and_nand (&uc, 11); + ss = __sync_fetch_and_nand (&ss, 11); + us = __sync_fetch_and_nand (&us, 11); + si = __sync_fetch_and_nand (&si, 11); + ui = __sync_fetch_and_nand (&ui, 11); +} + +void test_op_and_fetch (void) +{ + sc = __sync_add_and_fetch (&sc, uc); + uc = __sync_add_and_fetch (&uc, uc); + ss = __sync_add_and_fetch (&ss, uc); + us = __sync_add_and_fetch (&us, uc); + si = __sync_add_and_fetch (&si, uc); + ui = __sync_add_and_fetch (&ui, uc); + + sc = __sync_sub_and_fetch (&sc, uc); + uc = __sync_sub_and_fetch (&uc, uc); + ss = __sync_sub_and_fetch (&ss, uc); + us = __sync_sub_and_fetch (&us, uc); + si = __sync_sub_and_fetch (&si, uc); + ui = __sync_sub_and_fetch (&ui, uc); + + sc = __sync_or_and_fetch (&sc, uc); + uc = __sync_or_and_fetch (&uc, uc); + ss = __sync_or_and_fetch (&ss, uc); + us = __sync_or_and_fetch (&us, uc); + si = __sync_or_and_fetch (&si, uc); + ui = __sync_or_and_fetch (&ui, uc); + + sc = __sync_xor_and_fetch (&sc, uc); + uc = __sync_xor_and_fetch (&uc, uc); + ss = __sync_xor_and_fetch (&ss, uc); + us = __sync_xor_and_fetch (&us, uc); + si = __sync_xor_and_fetch (&si, uc); + ui = __sync_xor_and_fetch (&ui, uc); + + sc = __sync_and_and_fetch (&sc, uc); + uc = __sync_and_and_fetch (&uc, uc); + ss = __sync_and_and_fetch (&ss, uc); + us = __sync_and_and_fetch (&us, uc); + si = __sync_and_and_fetch (&si, uc); + ui = __sync_and_and_fetch (&ui, uc); + + sc = __sync_nand_and_fetch (&sc, uc); + uc = __sync_nand_and_fetch (&uc, uc); + ss = __sync_nand_and_fetch (&ss, uc); + us = __sync_nand_and_fetch (&us, uc); + si = __sync_nand_and_fetch (&si, uc); + ui = __sync_nand_and_fetch (&ui, uc); +} + +void test_compare_and_swap (void) +{ + sc = __sync_val_compare_and_swap (&sc, uc, sc); + uc = __sync_val_compare_and_swap (&uc, uc, sc); + ss = __sync_val_compare_and_swap (&ss, uc, sc); + us = __sync_val_compare_and_swap (&us, uc, sc); + si = __sync_val_compare_and_swap (&si, uc, sc); + ui = __sync_val_compare_and_swap (&ui, uc, sc); + + ui = __sync_bool_compare_and_swap (&sc, uc, sc); + ui = __sync_bool_compare_and_swap (&uc, uc, sc); + ui = __sync_bool_compare_and_swap (&ss, uc, sc); + ui = __sync_bool_compare_and_swap (&us, uc, sc); + ui = __sync_bool_compare_and_swap (&si, uc, sc); + ui = __sync_bool_compare_and_swap (&ui, uc, sc); +} + +void test_lock (void) +{ + sc = __sync_lock_test_and_set (&sc, 1); + uc = __sync_lock_test_and_set (&uc, 1); + ss = __sync_lock_test_and_set (&ss, 1); + us = __sync_lock_test_and_set (&us, 1); + si = __sync_lock_test_and_set (&si, 1); + ui = __sync_lock_test_and_set (&ui, 1); + + __sync_synchronize (); + + __sync_lock_release (&sc); + __sync_lock_release (&uc); + __sync_lock_release (&ss); + __sync_lock_release (&us); + __sync_lock_release (&si); + __sync_lock_release (&ui); +} diff --git a/final/test/FrontendC/Atomics.c b/final/test/FrontendC/Atomics.c new file mode 100644 index 00000000000..2b96ae0f629 --- /dev/null +++ b/final/test/FrontendC/Atomics.c @@ -0,0 +1,236 @@ +// Test frontend handling of __sync builtins. +// Modified from a gcc testcase. +// RUN: %llvmgcc -S %s -o - | grep atomic | count 200 +// RUN: %llvmgcc -S %s -o - | grep p0i8 | count 50 +// RUN: %llvmgcc -S %s -o - | grep p0i16 | count 50 +// RUN: %llvmgcc -S %s -o - | grep p0i32 | count 50 +// RUN: %llvmgcc -S %s -o - | grep volatile | count 8 + +// Currently this is implemented only for Alpha, X86, PowerPC. +// Add your target here if it doesn't work. +// PPC32 does not translate the long long variants, so fails this test. +// XFAIL: sparc,arm,powerpc + +signed char sc; +unsigned char uc; +signed short ss; +unsigned short us; +signed int si; +unsigned int ui; +signed long long sll; +unsigned long long ull; + +void test_op_ignore (void) +{ + (void) __sync_fetch_and_add (&sc, 1); + (void) __sync_fetch_and_add (&uc, 1); + (void) __sync_fetch_and_add (&ss, 1); + (void) __sync_fetch_and_add (&us, 1); + (void) __sync_fetch_and_add (&si, 1); + (void) __sync_fetch_and_add (&ui, 1); + (void) __sync_fetch_and_add (&sll, 1); + (void) __sync_fetch_and_add (&ull, 1); + + (void) __sync_fetch_and_sub (&sc, 1); + (void) __sync_fetch_and_sub (&uc, 1); + (void) __sync_fetch_and_sub (&ss, 1); + (void) __sync_fetch_and_sub (&us, 1); + (void) __sync_fetch_and_sub (&si, 1); + (void) __sync_fetch_and_sub (&ui, 1); + (void) __sync_fetch_and_sub (&sll, 1); + (void) __sync_fetch_and_sub (&ull, 1); + + (void) __sync_fetch_and_or (&sc, 1); + (void) __sync_fetch_and_or (&uc, 1); + (void) __sync_fetch_and_or (&ss, 1); + (void) __sync_fetch_and_or (&us, 1); + (void) __sync_fetch_and_or (&si, 1); + (void) __sync_fetch_and_or (&ui, 1); + (void) __sync_fetch_and_or (&sll, 1); + (void) __sync_fetch_and_or (&ull, 1); + + (void) __sync_fetch_and_xor (&sc, 1); + (void) __sync_fetch_and_xor (&uc, 1); + (void) __sync_fetch_and_xor (&ss, 1); + (void) __sync_fetch_and_xor (&us, 1); + (void) __sync_fetch_and_xor (&si, 1); + (void) __sync_fetch_and_xor (&ui, 1); + (void) __sync_fetch_and_xor (&sll, 1); + (void) __sync_fetch_and_xor (&ull, 1); + + (void) __sync_fetch_and_and (&sc, 1); + (void) __sync_fetch_and_and (&uc, 1); + (void) __sync_fetch_and_and (&ss, 1); + (void) __sync_fetch_and_and (&us, 1); + (void) __sync_fetch_and_and (&si, 1); + (void) __sync_fetch_and_and (&ui, 1); + (void) __sync_fetch_and_and (&sll, 1); + (void) __sync_fetch_and_and (&ull, 1); + + (void) __sync_fetch_and_nand (&sc, 1); + (void) __sync_fetch_and_nand (&uc, 1); + (void) __sync_fetch_and_nand (&ss, 1); + (void) __sync_fetch_and_nand (&us, 1); + (void) __sync_fetch_and_nand (&si, 1); + (void) __sync_fetch_and_nand (&ui, 1); + (void) __sync_fetch_and_nand (&sll, 1); + (void) __sync_fetch_and_nand (&ull, 1); +} + +void test_fetch_and_op (void) +{ + sc = __sync_fetch_and_add (&sc, 11); + uc = __sync_fetch_and_add (&uc, 11); + ss = __sync_fetch_and_add (&ss, 11); + us = __sync_fetch_and_add (&us, 11); + si = __sync_fetch_and_add (&si, 11); + ui = __sync_fetch_and_add (&ui, 11); + sll = __sync_fetch_and_add (&sll, 11); + ull = __sync_fetch_and_add (&ull, 11); + + sc = __sync_fetch_and_sub (&sc, 11); + uc = __sync_fetch_and_sub (&uc, 11); + ss = __sync_fetch_and_sub (&ss, 11); + us = __sync_fetch_and_sub (&us, 11); + si = __sync_fetch_and_sub (&si, 11); + ui = __sync_fetch_and_sub (&ui, 11); + sll = __sync_fetch_and_sub (&sll, 11); + ull = __sync_fetch_and_sub (&ull, 11); + + sc = __sync_fetch_and_or (&sc, 11); + uc = __sync_fetch_and_or (&uc, 11); + ss = __sync_fetch_and_or (&ss, 11); + us = __sync_fetch_and_or (&us, 11); + si = __sync_fetch_and_or (&si, 11); + ui = __sync_fetch_and_or (&ui, 11); + sll = __sync_fetch_and_or (&sll, 11); + ull = __sync_fetch_and_or (&ull, 11); + + sc = __sync_fetch_and_xor (&sc, 11); + uc = __sync_fetch_and_xor (&uc, 11); + ss = __sync_fetch_and_xor (&ss, 11); + us = __sync_fetch_and_xor (&us, 11); + si = __sync_fetch_and_xor (&si, 11); + ui = __sync_fetch_and_xor (&ui, 11); + sll = __sync_fetch_and_xor (&sll, 11); + ull = __sync_fetch_and_xor (&ull, 11); + + sc = __sync_fetch_and_and (&sc, 11); + uc = __sync_fetch_and_and (&uc, 11); + ss = __sync_fetch_and_and (&ss, 11); + us = __sync_fetch_and_and (&us, 11); + si = __sync_fetch_and_and (&si, 11); + ui = __sync_fetch_and_and (&ui, 11); + sll = __sync_fetch_and_and (&sll, 11); + ull = __sync_fetch_and_and (&ull, 11); + + sc = __sync_fetch_and_nand (&sc, 11); + uc = __sync_fetch_and_nand (&uc, 11); + ss = __sync_fetch_and_nand (&ss, 11); + us = __sync_fetch_and_nand (&us, 11); + si = __sync_fetch_and_nand (&si, 11); + ui = __sync_fetch_and_nand (&ui, 11); + sll = __sync_fetch_and_nand (&sll, 11); + ull = __sync_fetch_and_nand (&ull, 11); +} + +void test_op_and_fetch (void) +{ + sc = __sync_add_and_fetch (&sc, uc); + uc = __sync_add_and_fetch (&uc, uc); + ss = __sync_add_and_fetch (&ss, uc); + us = __sync_add_and_fetch (&us, uc); + si = __sync_add_and_fetch (&si, uc); + ui = __sync_add_and_fetch (&ui, uc); + sll = __sync_add_and_fetch (&sll, uc); + ull = __sync_add_and_fetch (&ull, uc); + + sc = __sync_sub_and_fetch (&sc, uc); + uc = __sync_sub_and_fetch (&uc, uc); + ss = __sync_sub_and_fetch (&ss, uc); + us = __sync_sub_and_fetch (&us, uc); + si = __sync_sub_and_fetch (&si, uc); + ui = __sync_sub_and_fetch (&ui, uc); + sll = __sync_sub_and_fetch (&sll, uc); + ull = __sync_sub_and_fetch (&ull, uc); + + sc = __sync_or_and_fetch (&sc, uc); + uc = __sync_or_and_fetch (&uc, uc); + ss = __sync_or_and_fetch (&ss, uc); + us = __sync_or_and_fetch (&us, uc); + si = __sync_or_and_fetch (&si, uc); + ui = __sync_or_and_fetch (&ui, uc); + sll = __sync_or_and_fetch (&sll, uc); + ull = __sync_or_and_fetch (&ull, uc); + + sc = __sync_xor_and_fetch (&sc, uc); + uc = __sync_xor_and_fetch (&uc, uc); + ss = __sync_xor_and_fetch (&ss, uc); + us = __sync_xor_and_fetch (&us, uc); + si = __sync_xor_and_fetch (&si, uc); + ui = __sync_xor_and_fetch (&ui, uc); + sll = __sync_xor_and_fetch (&sll, uc); + ull = __sync_xor_and_fetch (&ull, uc); + + sc = __sync_and_and_fetch (&sc, uc); + uc = __sync_and_and_fetch (&uc, uc); + ss = __sync_and_and_fetch (&ss, uc); + us = __sync_and_and_fetch (&us, uc); + si = __sync_and_and_fetch (&si, uc); + ui = __sync_and_and_fetch (&ui, uc); + sll = __sync_and_and_fetch (&sll, uc); + ull = __sync_and_and_fetch (&ull, uc); + + sc = __sync_nand_and_fetch (&sc, uc); + uc = __sync_nand_and_fetch (&uc, uc); + ss = __sync_nand_and_fetch (&ss, uc); + us = __sync_nand_and_fetch (&us, uc); + si = __sync_nand_and_fetch (&si, uc); + ui = __sync_nand_and_fetch (&ui, uc); + sll = __sync_nand_and_fetch (&sll, uc); + ull = __sync_nand_and_fetch (&ull, uc); +} + +void test_compare_and_swap (void) +{ + sc = __sync_val_compare_and_swap (&sc, uc, sc); + uc = __sync_val_compare_and_swap (&uc, uc, sc); + ss = __sync_val_compare_and_swap (&ss, uc, sc); + us = __sync_val_compare_and_swap (&us, uc, sc); + si = __sync_val_compare_and_swap (&si, uc, sc); + ui = __sync_val_compare_and_swap (&ui, uc, sc); + sll = __sync_val_compare_and_swap (&sll, uc, sc); + ull = __sync_val_compare_and_swap (&ull, uc, sc); + + ui = __sync_bool_compare_and_swap (&sc, uc, sc); + ui = __sync_bool_compare_and_swap (&uc, uc, sc); + ui = __sync_bool_compare_and_swap (&ss, uc, sc); + ui = __sync_bool_compare_and_swap (&us, uc, sc); + ui = __sync_bool_compare_and_swap (&si, uc, sc); + ui = __sync_bool_compare_and_swap (&ui, uc, sc); + ui = __sync_bool_compare_and_swap (&sll, uc, sc); + ui = __sync_bool_compare_and_swap (&ull, uc, sc); +} + +void test_lock (void) +{ + sc = __sync_lock_test_and_set (&sc, 1); + uc = __sync_lock_test_and_set (&uc, 1); + ss = __sync_lock_test_and_set (&ss, 1); + us = __sync_lock_test_and_set (&us, 1); + si = __sync_lock_test_and_set (&si, 1); + ui = __sync_lock_test_and_set (&ui, 1); + sll = __sync_lock_test_and_set (&sll, 1); + ull = __sync_lock_test_and_set (&ull, 1); + + __sync_synchronize (); + + __sync_lock_release (&sc); + __sync_lock_release (&uc); + __sync_lock_release (&ss); + __sync_lock_release (&us); + __sync_lock_release (&si); + __sync_lock_release (&ui); + __sync_lock_release (&sll); + __sync_lock_release (&ull); +} diff --git a/final/test/FrontendC/BasicInstrs.c b/final/test/FrontendC/BasicInstrs.c new file mode 100644 index 00000000000..ceed17c2ba9 --- /dev/null +++ b/final/test/FrontendC/BasicInstrs.c @@ -0,0 +1,26 @@ +// This file can be used to see what a native C compiler is generating for a +// variety of interesting operations. +// +// RUN: %llvmgcc -S %s -o - | llc + +unsigned int udiv(unsigned int X, unsigned int Y) { + return X/Y; +} +int sdiv(int X, int Y) { + return X/Y; +} +unsigned int urem(unsigned int X, unsigned int Y) { + return X%Y; +} +int srem(int X, int Y) { + return X%Y; +} + +_Bool setlt(int X, int Y) { + return X < Y; +} + +_Bool setgt(int X, int Y) { + return X > Y; +} + diff --git a/final/test/FrontendC/alignstack.c b/final/test/FrontendC/alignstack.c new file mode 100644 index 00000000000..30c00ff88e4 --- /dev/null +++ b/final/test/FrontendC/alignstack.c @@ -0,0 +1,23 @@ +// RUN: %llvmgcc %s -fasm-blocks -S -o - | FileCheck %s +// Complicated expression as jump target +// XFAIL: * +// XTARGET: x86,i386,i686,darwin + +void Method3() +{ +// CHECK: Method3 +// CHECK-NOT: alignstack + asm("foo:"); +// CHECK: return +} + +void Method4() +{ +// CHECK: Method4 +// CHECK: alignstack + asm { + bar: + } +// CHECK: return +} + diff --git a/final/test/FrontendC/always-inline.c b/final/test/FrontendC/always-inline.c new file mode 100644 index 00000000000..22f6c7a20ef --- /dev/null +++ b/final/test/FrontendC/always-inline.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - | grep call | not grep foo + +void bar() { +} + +inline void __attribute__((__always_inline__)) foo() { + bar(); +} + +void i_want_bar() { + foo(); +} diff --git a/final/test/FrontendC/arrayderef.c b/final/test/FrontendC/arrayderef.c new file mode 100644 index 00000000000..66c2e0ba416 --- /dev/null +++ b/final/test/FrontendC/arrayderef.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc %s -S -O -o - | FileCheck %s +// The load here was getting lost because this code was close +// enough to the traditional (wrong) implementation of offsetof +// to confuse the gcc FE. 8629268. + +struct foo { + int x; + int *y; +}; + +struct foo Foo[1]; + +int * bar(unsigned int ix) { +// CHECK: load + return &Foo->y[ix]; +} + diff --git a/final/test/FrontendC/asm-reg-var-local.c b/final/test/FrontendC/asm-reg-var-local.c new file mode 100644 index 00000000000..22bd43c076d --- /dev/null +++ b/final/test/FrontendC/asm-reg-var-local.c @@ -0,0 +1,32 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s +// Exercise various use cases for local asm "register variables". +// XFAIL: * +// XTARGET: x86_64,i686,i386 + +int foo() { +// CHECK: %a = alloca i32 + + register int a asm("rsi")=5; +// CHECK: store i32 5, i32* %a, align 4 + + asm volatile("; %0 This asm defines rsi" : "=r"(a)); +// CHECK: %asmtmp = call i32 asm sideeffect "; $0 This asm defines rsi", "={rsi} +// CHECK: store i32 %asmtmp, i32* %a + + a = 42; +// CHECK: store i32 42, i32* %a, align 4 + + asm volatile("; %0 This asm uses rsi" : : "r"(a)); +// CHECK: %1 = load i32* %a, align 4 +// CHECK: call void asm sideeffect "", "{rsi}"(i32 %1) nounwind +// CHECK: %2 = call i32 asm sideeffect "", "={rsi}"() nounwind +// CHECK: call void asm sideeffect "; $0 This asm uses rsi", "{rsi},~{dirflag},~{fpsr},~{flags}"(i32 %2) + + return a; +// CHECK: %3 = load i32* %a, align 4 +// CHECK: call void asm sideeffect "", "{rsi}"(i32 %3) nounwind +// CHECK: %4 = call i32 asm sideeffect "", "={rsi}"() nounwind +// CHECK: store i32 %4, i32* %0, align 4 +// CHECK: %5 = load i32* %0, align 4 +// CHECK: store i32 %5, i32* %retval, align 4 +} diff --git a/final/test/FrontendC/attribute_constructor.c b/final/test/FrontendC/attribute_constructor.c new file mode 100644 index 00000000000..da17a37e260 --- /dev/null +++ b/final/test/FrontendC/attribute_constructor.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - | grep llvm.global_ctors + +void foo() __attribute__((constructor)); +void foo() { + bar(); +} diff --git a/final/test/FrontendC/block-copy.c b/final/test/FrontendC/block-copy.c new file mode 100644 index 00000000000..c088f2dc195 --- /dev/null +++ b/final/test/FrontendC/block-copy.c @@ -0,0 +1,20 @@ +/* RUN: %llvmgcc %s -S -o - -O3 | grep {call.*memcpy} + + This should compile into a memcpy from a global, not 128 stores. */ + + + +void foo(); + +float bar() { + float lookupTable[] = {-1,-1,-1,0, -1,-1,0,-1, -1,-1,0,1, -1,-1,1,0, + -1,0,-1,-1, -1,0,-1,1, -1,0,1,-1, -1,0,1,1, + -1,1,-1,0, -1,1,0,-1, -1,1,0,1, -1,1,1,0, + 0,-1,-1,-1, 0,-1,-1,1, 0,-1,1,-1, 0,-1,1,1, + 1,-1,-1,0, 1,-1,0,-1, 1,-1,0,1, 1,-1,1,0, + 1,0,-1,-1, 1,0,-1,1, 1,0,1,-1, 1,0,1,1, + 1,1,-1,0, 1,1,0,-1, 1,1,0,1, 1,1,1,0, + 0,1,-1,-1, 0,1,-1,1, 0,1,1,-1, 0,1,1,1}; + foo(lookupTable); +} + diff --git a/final/test/FrontendC/crash-invalid-array.c b/final/test/FrontendC/crash-invalid-array.c new file mode 100644 index 00000000000..d602f785458 --- /dev/null +++ b/final/test/FrontendC/crash-invalid-array.c @@ -0,0 +1,17 @@ +// RUN: not %llvmgcc -O1 %s -S |& grep {error: invalid use of array with unspecified bounds} +// PR6913 + +#include + +int main() +{ + int x[10][10]; + int (*p)[] = x; // <-- this line is what triggered it + + int i; + + for(i = 0; i < 10; ++i) + { + p[i][i] = i; + } +} diff --git a/final/test/FrontendC/cstring-align.c b/final/test/FrontendC/cstring-align.c new file mode 100644 index 00000000000..544c9f3d3fb --- /dev/null +++ b/final/test/FrontendC/cstring-align.c @@ -0,0 +1,11 @@ +// RUN: %llvmgcc %s -S -Os -o - | llc -march=x86 -mtriple=i386-apple-darwin10 | FileCheck %s + +extern void func(const char *, const char *); + +void long_function_name() { + func("%s: the function name", __func__); +} + +// CHECK: .align 4 +// CHECK: ___func__. +// CHECK: .asciz "long_function_name" diff --git a/final/test/FrontendC/dg.exp b/final/test/FrontendC/dg.exp new file mode 100644 index 00000000000..a9be28a63cf --- /dev/null +++ b/final/test/FrontendC/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if [ llvm_gcc_supports c ] then { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] +} diff --git a/final/test/FrontendC/exact-div-expr.c b/final/test/FrontendC/exact-div-expr.c new file mode 100644 index 00000000000..9dce922f953 --- /dev/null +++ b/final/test/FrontendC/exact-div-expr.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - -O1 | grep ashr +// RUN: %llvmgcc -S %s -o - -O1 | not grep sdiv + +long long test(int *A, int *B) { + return A-B; +} diff --git a/final/test/FrontendC/extern-weak.c b/final/test/FrontendC/extern-weak.c new file mode 100644 index 00000000000..73b59cc48c4 --- /dev/null +++ b/final/test/FrontendC/extern-weak.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -O3 -S -o - %s | grep extern_weak +// RUN: %llvmgcc -O3 -S -o - %s | llc + +#if !defined(__linux__) && !defined(__FreeBSD__) && \ + !defined(__OpenBSD__) && !defined(__CYGWIN__) && !defined(__DragonFly__) +void foo() __attribute__((weak_import)); +#else +void foo() __attribute__((weak)); +#endif + +void bar() { foo(); } + diff --git a/final/test/FrontendC/fp-logical.c b/final/test/FrontendC/fp-logical.c new file mode 100644 index 00000000000..60404f67022 --- /dev/null +++ b/final/test/FrontendC/fp-logical.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc %s -S -o - | grep bitcast | count 14 + +typedef float vFloat __attribute__ ((__vector_size__ (16))); +typedef unsigned int vUInt32 __attribute__ ((__vector_size__ (16))); +void foo(vFloat *X) { + vFloat NoSignBit = (vFloat) ~ (vUInt32) (vFloat) { -0.f, -0.f, -0.f, -0.f }; + vFloat ExtremeValue = *X & NoSignBit; + *X = ExtremeValue; +} + +void bar(vFloat *X) { + vFloat NoSignBit = (vFloat) ~ (vUInt32) (vFloat) { -0.f, -0.f, -0.f, -0.f }; + vFloat ExtremeValue = *X & ~NoSignBit; + *X = ExtremeValue; +} diff --git a/final/test/FrontendC/func-aligned.c b/final/test/FrontendC/func-aligned.c new file mode 100644 index 00000000000..477e82418ae --- /dev/null +++ b/final/test/FrontendC/func-aligned.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s + +// rdar://7270273 +void foo() __attribute__((aligned (64))); +void foo() { +// CHECK: define void @foo() {{.*}} align 64 +} diff --git a/final/test/FrontendC/funccall.c b/final/test/FrontendC/funccall.c new file mode 100644 index 00000000000..9735e347057 --- /dev/null +++ b/final/test/FrontendC/funccall.c @@ -0,0 +1,17 @@ + +static int q; + +void foo() { + int t = q; + q = t + 1; +} +int main() { + q = 0; + foo(); + q = q - 1; + + return q; +} + +// This is the source that corresponds to funccall.ll +// RUN: echo foo diff --git a/final/test/FrontendC/hidden-visibility.c b/final/test/FrontendC/hidden-visibility.c new file mode 100644 index 00000000000..589bb53453f --- /dev/null +++ b/final/test/FrontendC/hidden-visibility.c @@ -0,0 +1,3 @@ +// RUN: %llvmgcc %s -S -o - | grep {hidden unnamed_addr global} + +int X __attribute__ ((__visibility__ ("hidden"))) = 123; diff --git a/final/test/FrontendC/implicit-arg.c b/final/test/FrontendC/implicit-arg.c new file mode 100644 index 00000000000..a6cb8bce7ed --- /dev/null +++ b/final/test/FrontendC/implicit-arg.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -S -O0 -o - +// RUN: %llvmgcc %s -S -O1 -o - +// rdar://6518089 + +static int bar(); +void foo() { + int a = bar(); +} +int bar(unsigned a) { +} diff --git a/final/test/FrontendC/inline-asm-function.c b/final/test/FrontendC/inline-asm-function.c new file mode 100644 index 00000000000..e5848409865 --- /dev/null +++ b/final/test/FrontendC/inline-asm-function.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -fasm-blocks -o - -O | grep naked +// 7533078 (partial). + +asm int f() { + xyz +} diff --git a/final/test/FrontendC/inline-asm-mrv.c b/final/test/FrontendC/inline-asm-mrv.c new file mode 100644 index 00000000000..6d1df67af1b --- /dev/null +++ b/final/test/FrontendC/inline-asm-mrv.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -o - -O | not grep alloca +// PR2094 + +int sad16_sse2(void *v, unsigned char *blk2, unsigned char *blk1, + int stride, int h) { + int ret; + asm volatile( "%0 %1 %2 %3" + : "+r" (h), "+r" (blk1), "+r" (blk2) + : "r" ((long)stride)); + asm volatile("set %0 %1" : "=r"(ret) : "r"(blk1)); + return ret; +} diff --git a/final/test/FrontendC/libcalls-d.c b/final/test/FrontendC/libcalls-d.c new file mode 100644 index 00000000000..d92208d89ed --- /dev/null +++ b/final/test/FrontendC/libcalls-d.c @@ -0,0 +1,14 @@ +// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't +// and -fno-builtins shouldn't. +// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not. +// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\.f64} +// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2} +// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp} +// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2} + +double exp2(double); + +double t4(unsigned char x) { + return exp2(x); +} + diff --git a/final/test/FrontendC/libcalls-ld.c b/final/test/FrontendC/libcalls-ld.c new file mode 100644 index 00000000000..cf71d19eaa3 --- /dev/null +++ b/final/test/FrontendC/libcalls-ld.c @@ -0,0 +1,17 @@ +// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't +// and -fno-builtins shouldn't. +// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not. +// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\..*f} +// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2l} +// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp} +// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2l} + +// If this fails for you because your target doesn't support long double, +// please xfail the test. + +long double exp2l(long double); + +long double t4(unsigned char x) { + return exp2l(x); +} + diff --git a/final/test/FrontendC/libcalls.c b/final/test/FrontendC/libcalls.c new file mode 100644 index 00000000000..60e22e7e690 --- /dev/null +++ b/final/test/FrontendC/libcalls.c @@ -0,0 +1,14 @@ +// llvm-gcc -O1+ should run simplify libcalls, O0 shouldn't +// and -fno-builtins shouldn't. +// -fno-math-errno should emit an llvm intrinsic, -fmath-errno should not. +// RUN: %llvmgcc %s -S -fno-math-errno -O0 -o - | grep {call.*exp2\\.f32} +// RUN: %llvmgcc %s -S -fmath-errno -O0 -o - | grep {call.*exp2f} +// RUN: %llvmgcc %s -S -O1 -o - | grep {call.*ldexp} +// RUN: %llvmgcc %s -S -O3 -fno-builtin -o - | grep {call.*exp2f} + +float exp2f(float); + +float t4(unsigned char x) { + return exp2f(x); +} + diff --git a/final/test/FrontendC/misaligned-param.c b/final/test/FrontendC/misaligned-param.c new file mode 100644 index 00000000000..b4fcfe312f5 --- /dev/null +++ b/final/test/FrontendC/misaligned-param.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc %s -m32 -S -o - | FileCheck %s +// Misaligned parameter must be memcpy'd to correctly aligned temporary. +// XFAIL: * +// XTARGET: i386-apple-darwin,i686-apple-darwin,x86_64-apple-darwin + +struct s { int x; long double y; }; +long double foo(struct s x, int i, struct s y) { +// CHECK: foo +// CHECK: %x_addr = alloca %struct.s, align 16 +// CHECK: %y_addr = alloca %struct.s, align 16 +// CHECK: memcpy +// CHECK: memcpy +// CHECK: bar + return bar(&x, &y); +} diff --git a/final/test/FrontendC/nested-functions.c b/final/test/FrontendC/nested-functions.c new file mode 100644 index 00000000000..bccbef3dbdd --- /dev/null +++ b/final/test/FrontendC/nested-functions.c @@ -0,0 +1,18 @@ +// RUN: %llvmgcc -S %s -o - -fnested-functions +// PR1274 + +void Bork() { + void Fork(const int *src, int size) { + int i = 1; + int x; + + while (i < size) + x = src[i]; + } +} + +void foo(void *a){ + inline void foo_bar() { + a += 1; + } +} diff --git a/final/test/FrontendC/pr2394.c b/final/test/FrontendC/pr2394.c new file mode 100644 index 00000000000..ca8b046f72f --- /dev/null +++ b/final/test/FrontendC/pr2394.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc %s -S -o - | FileCheck %s +struct __attribute((packed)) x {int a : 24;}; +int a(struct x* g) { + // CHECK: load i24 + return g->a; +} diff --git a/final/test/FrontendC/pr3518.c b/final/test/FrontendC/pr3518.c new file mode 100644 index 00000000000..112394a651b --- /dev/null +++ b/final/test/FrontendC/pr3518.c @@ -0,0 +1,24 @@ +// RUN: %llvmgcc %s -S -O0 -o - | grep {= internal unnamed_addr global} | count 4 +// PR 3518 +// Some of the objects were coming out as unintialized (external) before 3518 +// was fixed. Internal names are different between llvm-gcc and clang so they +// are not tested. + +extern void abort (void); + +struct A { int i; int j; }; +struct B { struct A *a; struct A *b; }; +struct C { struct B *c; struct A *d; }; +struct C e = { &(struct B) { &(struct A) { 1, 2 }, &(struct A) { 3, 4 } }, &(struct A) { 5, 6 } }; + +int +main (void) +{ + if (e.c->a->i != 1 || e.c->a->j != 2) + abort (); + if (e.c->b->i != 3 || e.c->b->j != 4) + abort (); + if (e.d->i != 5 || e.d->j != 6) + abort (); + return 0; +} diff --git a/final/test/FrontendC/pr4349.c b/final/test/FrontendC/pr4349.c new file mode 100644 index 00000000000..24acd9c950f --- /dev/null +++ b/final/test/FrontendC/pr4349.c @@ -0,0 +1,38 @@ +// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s +// PR 4349 + +union reg +{ + unsigned char b[2][2]; + unsigned short w[2]; + unsigned int d; +}; +struct cpu +{ + union reg pc; +}; +extern struct cpu cpu; +struct svar +{ + void *ptr; +}; +// CHECK: @svars1 = unnamed_addr global [1 x %struct.svar] [%struct.svar { i8* bitcast (%struct.cpu* @cpu to i8*) }] +struct svar svars1[] = +{ + { &((cpu.pc).w[0]) } +}; +// CHECK: @svars2 = unnamed_addr global [1 x %struct.svar] [%struct.svar { i8* getelementptr ([2 x i8]* bitcast (%struct.cpu* @cpu to [2 x i8]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1) }] +struct svar svars2[] = +{ + { &((cpu.pc).b[0][1]) } +}; +// CHECK: @svars3 = unnamed_addr global [1 x %struct.svar] [%struct.svar { i8* bitcast (i16* getelementptr ([2 x i16]* bitcast (%struct.cpu* @cpu to [2 x i16]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1) to i8*) }] +struct svar svars3[] = +{ + { &((cpu.pc).w[1]) } +}; +// CHECK: @svars4 = unnamed_addr global [1 x %struct.svar] [%struct.svar { i8* getelementptr ([2 x [2 x i8]]* bitcast (%struct.cpu* @cpu to [2 x [2 x i8]]*), i{{[0-9]+}} 0, i{{[0-9]+}} 1, i{{[0-9]+}} 1) }] +struct svar svars4[] = +{ + { &((cpu.pc).b[1][1]) } +}; diff --git a/final/test/FrontendC/pr5406.c b/final/test/FrontendC/pr5406.c new file mode 100644 index 00000000000..0b1f277592f --- /dev/null +++ b/final/test/FrontendC/pr5406.c @@ -0,0 +1,20 @@ +// RUN: %llvmgcc %s -S -O0 -o - | FileCheck %s +// PR 5406 + +// XFAIL: * +// XTARGET: arm + +typedef struct { char x[3]; } A0; +void foo (int i, ...); + + +// CHECK: call void (i32, ...)* @foo(i32 1, i32 {{.*}}) nounwind +int main (void) +{ + A0 a3; + a3.x[0] = 0; + a3.x[0] = 0; + a3.x[2] = 26; + foo (1, a3 ); + return 0; +} diff --git a/final/test/FrontendC/ptr-rotate.c b/final/test/FrontendC/ptr-rotate.c new file mode 100644 index 00000000000..36d9755dd67 --- /dev/null +++ b/final/test/FrontendC/ptr-rotate.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -m32 -o /dev/null +// RUN: %llvmgcc %s -S -O1 -m32 -o - | llc -march=x86 -mtriple=i386-apple-darwin9.7 | FileCheck %s -check-prefix=DARWIN + +unsigned int func(void *A) { + // DARWIN: roll $27 + return ((((unsigned long long) A) >> 5) | (((unsigned long long) A) << 27)); +} diff --git a/final/test/FrontendC/redef-ext-inline.c b/final/test/FrontendC/redef-ext-inline.c new file mode 100644 index 00000000000..240beb1f6f6 --- /dev/null +++ b/final/test/FrontendC/redef-ext-inline.c @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S %s -o - +// rdar://7208839 + +extern inline int f1 (void) {return 1;} +int f3 (void) {return f1();} +int f1 (void) {return 0;} diff --git a/final/test/FrontendC/sret.c b/final/test/FrontendC/sret.c new file mode 100644 index 00000000000..42666917a8d --- /dev/null +++ b/final/test/FrontendC/sret.c @@ -0,0 +1,15 @@ +// RUN: %llvmgcc %s -S -O0 -o - | grep sret | count 5 + +struct abc { + long a; + long b; + long c; +}; + +struct abc foo1(void); +struct abc foo2(); + +void bar() { + struct abc dummy1 = foo1(); + struct abc dummy2 = foo2(); +} diff --git a/final/test/FrontendC/sret2.c b/final/test/FrontendC/sret2.c new file mode 100644 index 00000000000..0f35b1c2586 --- /dev/null +++ b/final/test/FrontendC/sret2.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -O0 -o - | grep sret | count 2 + +struct abc { + long a; + long b; + long c; +}; + +struct abc foo2(){} diff --git a/final/test/FrontendC/unaligned-memcpy.c b/final/test/FrontendC/unaligned-memcpy.c new file mode 100644 index 00000000000..8fb84e4f515 --- /dev/null +++ b/final/test/FrontendC/unaligned-memcpy.c @@ -0,0 +1,5 @@ +// RUN: %llvmgcc %s -S -o - | llc + +void bork() { + char Qux[33] = {0}; +} diff --git a/final/test/FrontendC/union-align.c b/final/test/FrontendC/union-align.c new file mode 100644 index 00000000000..f99a7608056 --- /dev/null +++ b/final/test/FrontendC/union-align.c @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o - | grep load | grep "4 x float" | not grep "align 4" +// RUN: %llvmgcc -S %s -o - | grep load | grep "4 x float" | grep "align 16" +// PR3432 +// rdar://6536377 + +typedef float __m128 __attribute__ ((__vector_size__ (16))); + +typedef union +{ + int i[4]; + float f[4]; + __m128 v; +} u_t; + +__m128 t(u_t *a) { + return a->v; +} diff --git a/final/test/FrontendC/vla-1.c b/final/test/FrontendC/vla-1.c new file mode 100644 index 00000000000..77f78a5e3af --- /dev/null +++ b/final/test/FrontendC/vla-1.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc_only -std=gnu99 %s -S |& grep {warning: alignment for} +// ppc does not support this feature, and gets a fatal error at runtime. +// XFAIL: powerpc + +int foo(int a) +{ + int var[a] __attribute__((__aligned__(32))); + return 4; +} diff --git a/final/test/FrontendC/vla-2.c b/final/test/FrontendC/vla-2.c new file mode 100644 index 00000000000..555cfc78925 --- /dev/null +++ b/final/test/FrontendC/vla-2.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -std=gnu99 %s -S -o - | grep ".*alloca.*align 16" + +extern void bar(int[]); + +void foo(int a) +{ + int var[a] __attribute__((__aligned__(16))); + bar(var); + return; +} diff --git a/final/test/FrontendC/wchar-const.c b/final/test/FrontendC/wchar-const.c new file mode 100644 index 00000000000..7cf3322e8cf --- /dev/null +++ b/final/test/FrontendC/wchar-const.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -o - | grep {constant \\\[18 x} | grep { 84, } +// This should pass for any endianness combination of host and target. +#include +extern void foo(const wchar_t* p); +int main (int argc, const char * argv[]) +{ + foo(L"This is some text"); + return 0; +} diff --git a/final/test/FrontendC/weak_constant.c b/final/test/FrontendC/weak_constant.c new file mode 100644 index 00000000000..53379482cb4 --- /dev/null +++ b/final/test/FrontendC/weak_constant.c @@ -0,0 +1,12 @@ +// RUN: %llvmgcc -S %s -O1 -o - | grep {ret.*123} +// Check for bug compatibility with gcc. + +const int x __attribute((weak)) = 123; + +int* f(void) { + return &x; +} + +int g(void) { + return *f(); +} diff --git a/final/test/FrontendFortran/2008-11-03-OptionOverride.f90 b/final/test/FrontendFortran/2008-11-03-OptionOverride.f90 new file mode 100644 index 00000000000..d65ba9b4736 --- /dev/null +++ b/final/test/FrontendFortran/2008-11-03-OptionOverride.f90 @@ -0,0 +1,4 @@ +! RUN: %llvmgcc -S %s -march=k8 +! XTARGET: x86 +! Note: this file intentionally left blank, the problem itself is in +! frontend initialization routines and march flag! diff --git a/final/test/FrontendFortran/2009-02-09-FloorDivExpr.f90 b/final/test/FrontendFortran/2009-02-09-FloorDivExpr.f90 new file mode 100644 index 00000000000..ddd05c54949 --- /dev/null +++ b/final/test/FrontendFortran/2009-02-09-FloorDivExpr.f90 @@ -0,0 +1,32 @@ +! RUN: %llvmgcc -S %s +! PR2437 +program main + implicit none + call build (77) +contains + subroutine build (order) + integer :: order, i, j + + + call test (1, order, 3, (/ (i, i = 1, order, 3) /)) + call test (order, 1, -3, (/ (i, i = order, 1, -3) /)) + + do j = -10, 10 + call test (order + j, order, 5, (/ (i, i = order + j, order, 5) /)) + call test (order + j, order, -5, (/ (i, i = order + j, order, -5) /)) + end do + + end subroutine build + + subroutine test (from, to, step, values) + integer, dimension (:) :: values + integer :: from, to, step, last, i + + last = 0 + do i = from, to, step + last = last + 1 + if (values (last) .ne. i) call abort + end do + if (size (values, dim = 1) .ne. last) call abort + end subroutine test +end program main diff --git a/final/test/FrontendFortran/cpow.f90 b/final/test/FrontendFortran/cpow.f90 new file mode 100644 index 00000000000..25156fd5897 --- /dev/null +++ b/final/test/FrontendFortran/cpow.f90 @@ -0,0 +1,18 @@ +! RUN: %llvmgcc -S %s +! PR2443 + +! Program to test the power (**) operator +program testpow + implicit none + real(kind=4) r, s, two + real(kind=8) :: q + complex(kind=4) :: c, z + real, parameter :: del = 0.0001 + integer i, j + + two = 2.0 + + c = (2.0, 3.0) + c = c ** two + if (abs(c - (-5.0, 12.0)) .gt. del) call abort +end program diff --git a/final/test/FrontendFortran/dg.exp b/final/test/FrontendFortran/dg.exp new file mode 100644 index 00000000000..45bffc6fdcb --- /dev/null +++ b/final/test/FrontendFortran/dg.exp @@ -0,0 +1,6 @@ +load_lib llvm.exp + +if [ llvm_gcc_supports fortran ] then { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{f,f90}]] +} + diff --git a/final/test/FrontendObjC++/2007-10-03-MetadataPointers.mm b/final/test/FrontendObjC++/2007-10-03-MetadataPointers.mm new file mode 100644 index 00000000000..2ab76c1db59 --- /dev/null +++ b/final/test/FrontendObjC++/2007-10-03-MetadataPointers.mm @@ -0,0 +1,7 @@ +// RUN: %llvmgcc -w -x objective-c++ -S %s -o /dev/null + +@class NSImage; +void bork() { + NSImage *nsimage; + [nsimage release]; +} diff --git a/final/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm b/final/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm new file mode 100644 index 00000000000..da47ed0c122 --- /dev/null +++ b/final/test/FrontendObjC++/2010-08-02-NonPODObjectValue.mm @@ -0,0 +1,27 @@ +// RUN: not %llvmgcc %s -S -o - |& FileCheck %s +// This tests for a specific diagnostic in LLVM-GCC. +// Clang compiles this correctly with no diagnostic, +// ergo this test will fail with a Clang-based front-end. +class TFENodeVector { +public: + TFENodeVector(const TFENodeVector& inNodeVector); + TFENodeVector(); +}; + +@interface TWindowHistoryEntry {} +@property (assign, nonatomic) TFENodeVector targetPath; +@end + +@implementation TWindowHistoryEntry +@synthesize targetPath; +- (void) initWithWindowController { + TWindowHistoryEntry* entry; + TFENodeVector newPath; + // CHECK: setting a C++ non-POD object value is not implemented +#ifdef __clang__ +#error setting a C++ non-POD object value is not implemented +#endif + entry.targetPath = newPath; + [entry setTargetPath:newPath]; +} +@end diff --git a/final/test/FrontendObjC++/2010-08-04-Template.mm b/final/test/FrontendObjC++/2010-08-04-Template.mm new file mode 100644 index 00000000000..2ebfd3e17ce --- /dev/null +++ b/final/test/FrontendObjC++/2010-08-04-Template.mm @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -S +struct TRunSoon { + template static void Post() {} +}; + +@implementation TPrivsTableViewMainController +- (void) applyToEnclosed { + TRunSoon::Post(); +} +@end diff --git a/final/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm b/final/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm new file mode 100644 index 00000000000..986094c0723 --- /dev/null +++ b/final/test/FrontendObjC++/2010-08-06-X.Y-syntax.mm @@ -0,0 +1,16 @@ +// RUN: %llvmgcc %s -S +struct TFENode { + TFENode(const TFENode& inNode); +}; + +@interface TIconViewController +- (const TFENode&) target; +@end + +void sortAllChildrenForNode(const TFENode&node); + +@implementation TIconViewController +- (void) setArrangeBy { + sortAllChildrenForNode(self.target); +} +@end diff --git a/final/test/FrontendObjC++/dg.exp b/final/test/FrontendObjC++/dg.exp new file mode 100644 index 00000000000..41c3db2af09 --- /dev/null +++ b/final/test/FrontendObjC++/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if [ llvm_gcc_supports obj-c++ ] then { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{mm}]] +} diff --git a/final/test/FrontendObjC/2007-04-03-ObjcEH.m b/final/test/FrontendObjC/2007-04-03-ObjcEH.m new file mode 100644 index 00000000000..ae744c78500 --- /dev/null +++ b/final/test/FrontendObjC/2007-04-03-ObjcEH.m @@ -0,0 +1,29 @@ +// RUN: %llvmgcc -S %s -o /dev/null + +@interface B +-(int)bar; +@end + +@interface A +-(void) Foo:(int) state; +@end + +@implementation A +- (void) Foo:(int) state { + + int wasResponded = 0; + @try { + if (state) { + B * b = 0; + @try { } + @finally { + wasResponded = ![b bar]; + } + } + } + @finally { + } +} +@end + + diff --git a/final/test/FrontendObjC/2007-05-02-Strong.m b/final/test/FrontendObjC/2007-05-02-Strong.m new file mode 100644 index 00000000000..34b41ad964f --- /dev/null +++ b/final/test/FrontendObjC/2007-05-02-Strong.m @@ -0,0 +1,23 @@ +// RUN: %llvmgcc -S %s -fobjc-gc -o /dev/null +typedef int NSInteger; +typedef struct _NSRect { + int origin; + int size; +} NSRect; + +__attribute__((objc_gc(strong))) NSRect *_cachedRectArray; +extern const NSRect NSZeroRect; +@interface A{ +} +-(void)bar:(NSInteger *)rectCount; +@end + +@implementation A + +-(void)bar:(NSInteger *)rectCount { + NSRect appendRect = NSZeroRect; + + _cachedRectArray[*rectCount - 1] = NSZeroRect; +} + +@end diff --git a/final/test/FrontendObjC/2007-09-25-EH.m b/final/test/FrontendObjC/2007-09-25-EH.m new file mode 100644 index 00000000000..d625584a6c5 --- /dev/null +++ b/final/test/FrontendObjC/2007-09-25-EH.m @@ -0,0 +1,27 @@ +// RUN: %llvmgcc -S -w -m64 -mmacosx-version-min=10.5 %s -o /dev/null +// XFAIL: * +// XTARGET: darwin +@class NSDictionary, DSoBuffer, DSoDirectory, NSMutableArray; +@interface NSException {} +@end +@interface DSoNode { + DSoDirectory *mDirectory; +} +@end +@implementation DSoNode +- (void) _findRecordsOfTypes { + DSoBuffer *dbData; + void *recInfo; + NSMutableArray *results; + @try { + dsGetRecordEntry([dbData dsDataBuffer], (void**)&recInfo); + @try { + [results addObject:37]; + } @finally { + dsDeallocRecordEntry([mDirectory dsDirRef], recInfo); + } + } @catch(NSException * exception) { + } +} + + diff --git a/final/test/FrontendObjC/2007-10-17-SJLJExceptions.m b/final/test/FrontendObjC/2007-10-17-SJLJExceptions.m new file mode 100644 index 00000000000..970207e0d8a --- /dev/null +++ b/final/test/FrontendObjC/2007-10-17-SJLJExceptions.m @@ -0,0 +1,24 @@ +// RUN: %llvmgcc -m32 -x objective-c %s -pipe -std=gnu99 -O2 -fexceptions -S -o - | not grep Unwind_Resume +#import + +@interface Foo { + char c; + short s; + int i; + long l; + float f; + double d; +} +-(Foo*)retain; +@end + +struct Foo *bork(Foo *FooArray) { + struct Foo *result = 0; + @try { + result = [FooArray retain]; + } @catch(id any) { + printf("hello world\n"); + } + + return result; +} diff --git a/final/test/FrontendObjC/2007-10-18-ProDescriptor.m b/final/test/FrontendObjC/2007-10-18-ProDescriptor.m new file mode 100644 index 00000000000..220fdd2c232 --- /dev/null +++ b/final/test/FrontendObjC/2007-10-18-ProDescriptor.m @@ -0,0 +1,19 @@ +// RUN: %llvmgcc -x objective-c -S %s -o /dev/null +@protocol O +@end +@interface O < O > { +} +@end +struct A { +}; +@protocol AB +- (unsigned) ver; +@end +@interface AGy:O < AB > { +} +@end +@implementation AGy +- (unsigned) ver { +} +@end + diff --git a/final/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m b/final/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m new file mode 100644 index 00000000000..4bbe4407bed --- /dev/null +++ b/final/test/FrontendObjC/2007-10-23-GC-WriteBarrier.m @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -x objective-c -S %s -o /dev/null -fobjc-gc +// rdar://5541393 + +typedef unsigned int NSUInteger; +__attribute__((objc_gc(strong))) float *_scores; + +void foo(int i, float f) { + _scores[i] = f; +} diff --git a/final/test/FrontendObjC/2008-10-3-EhValue.m b/final/test/FrontendObjC/2008-10-3-EhValue.m new file mode 100644 index 00000000000..c7aabe271ee --- /dev/null +++ b/final/test/FrontendObjC/2008-10-3-EhValue.m @@ -0,0 +1,50 @@ +// RUN: %llvmgcc -w -x objective-c -S %s -o /dev/null + +@interface Object { +@public + Class isa; +} ++initialize; ++alloc; ++new; ++free; +-free; ++(Class)class; +-(Class)class; +-init; +-superclass; +-(const char *)name; +@end + +@interface Frob: Object +@end + +@implementation Frob: Object +@end + +static Frob* _connection = ((void *)0); + +extern void abort(void); + +void test (Object* sendPort) +{ + int cleanupPorts = 1; + Frob* receivePort = ((void *)0); + + @try { + receivePort = (Frob *) -1; + _connection = (Frob *) -1; + receivePort = ((void *)0); + sendPort = ((void *)0); + cleanupPorts = 0; + @throw [Object new]; + } + @catch(Frob *obj) { + if(!(0)) abort(); + } + @catch(id exc) { + if(!(!receivePort)) abort(); + if(!(!sendPort)) abort(); + if(!(!cleanupPorts)) abort(); + } +} diff --git a/final/test/FrontendObjC/2008-11-12-Metadata.m b/final/test/FrontendObjC/2008-11-12-Metadata.m new file mode 100644 index 00000000000..be8ee41e77a --- /dev/null +++ b/final/test/FrontendObjC/2008-11-12-Metadata.m @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -x objective-c -m64 -S %s -o /dev/null + +@interface A +@end +@protocol P +@end +@interface B : A

+{ +} +@end +@implementation B +- (void)test { +} +@end diff --git a/final/test/FrontendObjC/2008-11-24-ConstCFStrings.m b/final/test/FrontendObjC/2008-11-24-ConstCFStrings.m new file mode 100644 index 00000000000..976adc47f12 --- /dev/null +++ b/final/test/FrontendObjC/2008-11-24-ConstCFStrings.m @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -x objective-c -m64 -S %s -o - | grep {L_unnamed_cfstring_} + +@class NSString; + +@interface A +- (void)bork:(NSString*)msg; +@end + +void func(A *a) { + [a bork:@"Hello world!"]; +} diff --git a/final/test/FrontendObjC/2008-11-25-Blocks.m b/final/test/FrontendObjC/2008-11-25-Blocks.m new file mode 100644 index 00000000000..c5cd3d2a0b2 --- /dev/null +++ b/final/test/FrontendObjC/2008-11-25-Blocks.m @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -S %s -o /dev/null +// rdar://6394879 + +@interface bork +- (id)B:(void (^)())blk; +- (void)C; +@end +@implementation bork +- (id)B:(void (^)())blk { + __attribute__((__blocks__(byref))) bork* new = ((void *)0); + blk(); +} +- (void)C { + __attribute__((__blocks__(byref))) id var; + [self B:^() {}]; +} +@end diff --git a/final/test/FrontendObjC/2009-01-26-WriteBarrier-2.m b/final/test/FrontendObjC/2009-01-26-WriteBarrier-2.m new file mode 100644 index 00000000000..32833a81e16 --- /dev/null +++ b/final/test/FrontendObjC/2009-01-26-WriteBarrier-2.m @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -x objective-c -S %s -fobjc-gc -o - | grep objc_assign_strongCast +// rdar://5541393 + +typedef struct { + void (^ivarBlock)(void); +} StructWithBlock_t; + +int main(char *argc, char *argv[]) { + StructWithBlock_t *swbp = (StructWithBlock_t *)malloc(sizeof(StructWithBlock_t*)); + __block int i = 10; + // assigning a Block into an struct slot should elicit a write-barrier under GC + swbp->ivarBlock = ^ { ++i; }; + return 0; +} diff --git a/final/test/FrontendObjC/2009-02-05-VolatileProp.m b/final/test/FrontendObjC/2009-02-05-VolatileProp.m new file mode 100644 index 00000000000..1deef739bee --- /dev/null +++ b/final/test/FrontendObjC/2009-02-05-VolatileProp.m @@ -0,0 +1,11 @@ +/* RUN: %llvmgcc -w -x objective-c -S %s -o /dev/null -pedantic-errors + rdar://6551276 */ + +void foo(const unsigned short *); +void bar() { + unsigned short *s[3]; + int i; + @try { } @catch (id anException) { } + foo(2+s[i]); +} + diff --git a/final/test/FrontendObjC/2009-04-14-AsmSection.m b/final/test/FrontendObjC/2009-04-14-AsmSection.m new file mode 100644 index 00000000000..aefe0887671 --- /dev/null +++ b/final/test/FrontendObjC/2009-04-14-AsmSection.m @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S %s -fobjc-abi-version=2 -o %t +// RUN: grep {OBJC_CLASS_\\\$_A.*section.*__DATA, __objc_data.*align} %t +// XTARGET: darwin + +@interface A +@end + +@implementation A +@end diff --git a/final/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m b/final/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m new file mode 100644 index 00000000000..cada8438bc9 --- /dev/null +++ b/final/test/FrontendObjC/2009-04-27-bitfield-vs-ivar.m @@ -0,0 +1,44 @@ +// RUN: %llvmgcc -S -x objective-c -m64 -fobjc-abi-version=2 %s -o %t +// RUN: grep {OBJC_CLASS_RO_\\\$_I4} %t | grep {i32 0, i32 1, i32 2, i32 0} +// RUN: grep {OBJC_CLASS_RO_\\\$_I2} %t | grep {i32 0, i32 1, i32 1, i32 0} +// RUN: grep {OBJC_CLASS_RO_\\\$_I5} %t | grep {i32 0, i32 0, i32 0, i32 0} +// XTARGET: darwin + +// Test instance variable sizing when base class ends in bitfield +@interface I3 { + unsigned int _iv2 :1; +} +@end + +@interface I4 : I3 { + char _iv4; +} +@end + +// Test case with no instance variables in derived class +@interface I1 { + unsigned int _iv2 :1; +} +@end + +@interface I2 : I1 { +} +@end + +// Test case with no instance variables anywhere +@interface I6 { +} +@end + +@interface I5 : I6 { +} +@end + +@implementation I4 +@end + +@implementation I2 +@end + +@implementation I5 +@end diff --git a/final/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m b/final/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m new file mode 100644 index 00000000000..8306fcc7e07 --- /dev/null +++ b/final/test/FrontendObjC/2009-04-28-bitfield-vs-vbc.m @@ -0,0 +1,127 @@ +// RUN: %llvmgcc -S -x objective-c -m32 %s -o %t +// This used to crash, 6831493. +#include + +struct s0 { + double x; +}; + +@interface I2 { + struct s0 _iv1; +} +@end + +@interface I3 : I2 { + unsigned int _iv2 :1; + unsigned : 0; + unsigned int _iv3 : 3; +} +@end + +@interface I4 : I3 { + char _iv4; +} +@end + +@interface I5 : I4 { + char _iv5; + int _iv6; + int _iv7; +} + +@property int P1; +@end + +@implementation I2 +@end + +@implementation I3 +@end + +@implementation I4 +@end + +@interface I5 () +@property int P2; +@end + +#if 0 +int g2 = sizeof(I2); +int g3 = sizeof(I3); +int g4 = sizeof(I4); +int g5_0 = sizeof(I5); +#endif + +@implementation I5 +#ifdef __x86_64 +@synthesize P1 = _MadeUpName; +@synthesize P2 = _AnotherMadeUpName; +#else +@synthesize P1 = _iv6; +@synthesize P2 = _iv7; +#endif +@end + +#if 0 +int g5_1 = sizeof(I5); +#endif + +@interface T0_I0 { + double iv_A_0; + char iv_A_1; +} +@end + +@interface T0_I1 : T0_I0 { + char iv_B_0; +} +@end + +@interface T0_I2 : T0_I1 { + char iv_C_0; +} +@end + +#if 0 +int g6 = sizeof(T0_I0); +int g7 = sizeof(T0_I1); +int g8 = sizeof(T0_I2); +#endif + +@implementation T0_I0 @end +@implementation T0_I1 @end +@implementation T0_I2 @end + +void f0(I2*i2,I3*i3,I4*i4,I5*i5,T0_I0*t0_i0,T0_I1*t0_i1,T0_I2*t0_i2) { +} + +// Thomas Wang's ui32 hash. +unsigned hash_ui32_to_ui32(unsigned a) { + a = (a ^ 61) ^ (a >> 16); + a = a + (a << 3); + a = a ^ (a >> 4); + a = a * 0x27d4eb2d; + a = a ^ (a >> 15); + return a; +} + +unsigned char hash_ui32_to_ui8(unsigned ui) { + ui = hash_ui32_to_ui32(ui); + ui ^= ui>>8; + ui ^= ui>>8; + ui ^= ui>>8; + return (unsigned char) ui; +} + +void *init() { + unsigned i, N = 1024; + unsigned char *p = malloc(N); + for (i=0; i != N; ++i) + p[i] = hash_ui32_to_ui8(i); + return p; +} + +int main(){ + void *p = init(); + f0(p,p,p,p,p,p,p); +} diff --git a/final/test/FrontendObjC/2009-08-05-utf16.m b/final/test/FrontendObjC/2009-08-05-utf16.m new file mode 100644 index 00000000000..df3745c4870 --- /dev/null +++ b/final/test/FrontendObjC/2009-08-05-utf16.m @@ -0,0 +1,5 @@ +/* RUN: %llvmgcc -w -x objective-c -S %s -o - | grep {__utf16_string_1} | grep {internal unnamed_addr constant} | grep {12 x i8} + rdar://7095855 rdar://7115749 */ + +void *P = @"iPodâ„¢"; + diff --git a/final/test/FrontendObjC/2009-08-17-DebugInfo.m b/final/test/FrontendObjC/2009-08-17-DebugInfo.m new file mode 100644 index 00000000000..8ed7c24dc13 --- /dev/null +++ b/final/test/FrontendObjC/2009-08-17-DebugInfo.m @@ -0,0 +1,28 @@ +// This is a regression test on debug info to make sure that we can set a +// breakpoint on a objective message. +// RUN: %llvmgcc -S -O0 -g %s -o - | llc -o %t.s -O0 +// RUN: %compile_c %t.s -o %t.o +// RUN: %link %t.o -o %t.exe -framework Foundation +// RUN: echo {break randomFunc\n} > %t.in +// RUN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \ +// RUN: grep {Breakpoint 1 at 0x.*: file .*2009-08-17-DebugInfo.m, line 21} +// XTARGET: darwin +@interface MyClass +{ + int my; +} ++ init; +- randomFunc; +@end + +@implementation MyClass ++ init { +} +- randomFunc { my = 42; } +@end + +int main() { + id o = [MyClass init]; + [o randomFunc]; + return 0; +} diff --git a/final/test/FrontendObjC/2009-11-30-Objc-ID.m b/final/test/FrontendObjC/2009-11-30-Objc-ID.m new file mode 100644 index 00000000000..787bf72efe3 --- /dev/null +++ b/final/test/FrontendObjC/2009-11-30-Objc-ID.m @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o %t.s -O0 +// RUN: grep id %t.s | grep DW_AT_name +@interface A +-(id) blah; +@end + +@implementation A +-(id)blah { + int i = 1; + i++; + return i; +} +@end diff --git a/final/test/FrontendObjC/2010-02-01-utf16-with-null.m b/final/test/FrontendObjC/2010-02-01-utf16-with-null.m new file mode 100644 index 00000000000..86e46376bd2 --- /dev/null +++ b/final/test/FrontendObjC/2010-02-01-utf16-with-null.m @@ -0,0 +1,5 @@ +/* RUN: %llvmgcc -w -x objective-c -S %s -o - | not grep {__ustring} + rdar://7589850 */ + +void *P = @"good\0bye"; + diff --git a/final/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m b/final/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m new file mode 100644 index 00000000000..bb00f6a1e2c --- /dev/null +++ b/final/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -x objective-c -fwritable-strings -S %s -o - | FileCheck %s +// CHECK: @.str = private unnamed_addr constant +// CHECK: @.str1 = internal unnamed_addr global + +// rdar://7634471 + +@class NSString; + +@interface A +- (void)foo:(NSString*)msg; +- (void)bar:(const char*)msg; +@end + +void func(A *a) { + [a foo:@"Hello world!"]; + [a bar:"Goodbye world!"]; +} diff --git a/final/test/FrontendObjC/2010-02-23-DbgInheritance.m b/final/test/FrontendObjC/2010-02-23-DbgInheritance.m new file mode 100644 index 00000000000..7e1cf67b475 --- /dev/null +++ b/final/test/FrontendObjC/2010-02-23-DbgInheritance.m @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -g -o - | grep -v DW_TAG_member +// Interface P should not be a member of interface I in debug info. +@interface P +@end + +@interface I : P +@end + +void fn(I *iptr) {} diff --git a/final/test/FrontendObjC/2010-03-17-StructRef.m b/final/test/FrontendObjC/2010-03-17-StructRef.m new file mode 100644 index 00000000000..3594684a194 --- /dev/null +++ b/final/test/FrontendObjC/2010-03-17-StructRef.m @@ -0,0 +1,43 @@ +// RUN: %llvmgcc %s -m64 -S -o - | FileCheck %s +// Bitfield references must not touch memory outside of the enclosing +// struct. Radar 7639995 +typedef signed char BOOL; +@protocol NSObject +- (id)init; +@end +@interface NSObject {} +@end +@interface IMAVChatParticipant : NSObject { + int _ardRole; + int _state; + int _avRelayStatus; + int _chatEndedReason; + int _chatError; + unsigned _sendingAudio:1; + unsigned _sendingVideo:1; + unsigned _sendingAuxVideo:1; + unsigned _audioMuted:1; + unsigned _videoPaused:1; + unsigned _networkStalled:1; + unsigned _isInitiator:1; + unsigned _isAOLInterop:1; + unsigned _isRecording:1; + unsigned _isUsingICE:1; +} +@end +@implementation IMAVChatParticipant +- (id) init { + self = [super init]; + if ( self ) { + BOOL blah = (BOOL)1; + // We're expecting these three bitfield assignments will generate i8 stores. + _sendingAudio = (BOOL)1; + _isUsingICE = (BOOL)1; + _isUsingICE = blah; + // CHECK: store i8 + // CHECK: store i8 + // CHECK: store i8 + } + return self; +} +@end diff --git a/final/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m b/final/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m new file mode 100644 index 00000000000..bded9ea2a40 --- /dev/null +++ b/final/test/FrontendObjC/2010-06-04-UnnamedCFString-dbg.m @@ -0,0 +1,6 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_variable | count 1 + +// Do not emit debug info for unnamed builtin CFString variable. +@interface Foo +@end +Foo *FooName = @"FooBar"; diff --git a/final/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m b/final/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m new file mode 100644 index 00000000000..a5bd2b73bf0 --- /dev/null +++ b/final/test/FrontendObjC/2011-03-02-ConstCFStringLiteralAlign.m @@ -0,0 +1,11 @@ +// RUN: %llvmgcc -S -w -m64 -mmacosx-version-min=10.5 %s -o - | \ +// RUN: llc --disable-fp-elim -o - | FileCheck %s +// XFAIL: * +// XTARGET: darwin + +@interface Foo +@end +Foo *FooName = @"FooBar"; + +// CHECK: .section __TEXT,__cstring,cstring_literals +// CHECK-NEXT: L_.str: diff --git a/final/test/FrontendObjC/dg.exp b/final/test/FrontendObjC/dg.exp new file mode 100644 index 00000000000..18f73a79787 --- /dev/null +++ b/final/test/FrontendObjC/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if [ llvm_gcc_supports objc ] then { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{m}]] +} diff --git a/final/test/Integer/2007-01-19-TruncSext.ll b/final/test/Integer/2007-01-19-TruncSext.ll new file mode 100644 index 00000000000..3fee6bc8b6e --- /dev/null +++ b/final/test/Integer/2007-01-19-TruncSext.ll @@ -0,0 +1,29 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll +; RUN: llvm-as < %s | lli --force-interpreter=true | grep -- -255 + +@ARRAY = global [ 20 x i17 ] zeroinitializer +@FORMAT = constant [ 4 x i8 ] c"%d\0A\00" + +declare i32 @printf(i8* %format, ...) + +define void @multiply(i32 %index, i32 %X, i32 %Y) { + %Z = mul i32 %X, %Y + %P = getelementptr [20 x i17]* @ARRAY, i32 0, i32 %index + %Result = trunc i32 %Z to i17 + store i17 %Result, i17* %P + ret void +} + +define i32 @main(i32 %argc, i8** %argv) { + %i = bitcast i32 0 to i32 + call void @multiply(i32 %i, i32 -1, i32 255) + %P = getelementptr [20 x i17]* @ARRAY, i32 0, i32 0 + %X = load i17* %P + %result = sext i17 %X to i32 + %fmt = getelementptr [4 x i8]* @FORMAT, i32 0, i32 0 + call i32 (i8*,...)* @printf(i8* %fmt, i32 %result) + ret i32 0 +} + diff --git a/final/test/Integer/BitArith.ll b/final/test/Integer/BitArith.ll new file mode 100644 index 00000000000..350a9849947 --- /dev/null +++ b/final/test/Integer/BitArith.ll @@ -0,0 +1,25 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + + +declare void @"foo"(i31 %i, i63 %j, i10 %k) + + +; foo test basic arith operations +define void @"foo"(i31 %i, i63 %j, i10 %k) +begin + %t1 = trunc i63 %j to i31 + %t2 = add i31 %t1, %i + %t20 = add i31 3, %t1 + %t3 = zext i31 %i to i63 + %t4 = sub i63 %t3, %j + %t40 = sub i63 %j, -100 + %t5 = mul i10 %k, 7 + %t6 = sdiv i63 %j, -2 + %t7 = udiv i63 %j, %t3 + %t8 = urem i10 %k, 10 + %t9 = srem i10 %k, -10 + ret void +end + diff --git a/final/test/Integer/BitBit.ll b/final/test/Integer/BitBit.ll new file mode 100644 index 00000000000..420bbe5a5fc --- /dev/null +++ b/final/test/Integer/BitBit.ll @@ -0,0 +1,24 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +declare void @"foo"(i31 %i, i33 %j) + + +; foo test basic bitwise operations +define void @"foo"(i31 %i, i33 %j) +begin + %t1 = trunc i33 %j to i31 + %t2 = and i31 %t1, %i + %t3 = sext i31 %i to i33 + %t4 = or i33 %t3, %j + %t5 = xor i31 %t2, 7 + %t6 = shl i31 %i, 2 + %t7 = trunc i31 %i to i8 + %t8 = shl i8 %t7, 3 + %t9 = lshr i33 %j, 31 + %t7z = zext i8 %t7 to i33 + %t10 = ashr i33 %j, %t7z + ret void +end + diff --git a/final/test/Integer/BitCast.ll b/final/test/Integer/BitCast.ll new file mode 100644 index 00000000000..0bef0230e95 --- /dev/null +++ b/final/test/Integer/BitCast.ll @@ -0,0 +1,26 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +declare void @"foo"(i31 %i, i1280 %j, i1 %k, float %f) + + +; foo test basic arith operations +define void @"foo"(i31 %i, i1280 %j, i1 %k, float %f) +begin + %t1 = trunc i1280 %j to i31 + %t2 = trunc i31 %t1 to i1 + + %t3 = zext i31 %i to i1280 + %t4 = sext i31 %i to i1280 + + %t5 = fptoui float 0x400921FA00000000 to i31 + %t6 = uitofp i31 %t5 to double + + %t7 = fptosi double 0xC0934A456D5CFAAD to i28 + %t8 = sitofp i8 -1 to double + %t9 = uitofp i8 255 to double + + ret void +end + diff --git a/final/test/Integer/BitIcmp.ll b/final/test/Integer/BitIcmp.ll new file mode 100644 index 00000000000..c22461224d0 --- /dev/null +++ b/final/test/Integer/BitIcmp.ll @@ -0,0 +1,43 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + + +define i55 @"simpleIcmp"(i55 %i0, i55 %j0) +begin + %t1 = icmp eq i55 %i0, %j0 + %t2 = icmp ne i55 %i0, %j0 + %t3 = icmp ult i55 %i0, %j0 + %t4 = icmp sgt i55 %i0, %j0 + %t5 = icmp ule i55 %i0, %j0 + %t6 = icmp sge i55 %i0, %j0 + + %t7 = icmp eq i55 %i0, 1098765432 + %t8 = icmp ne i55 %i0, -31415926 + + %t9 = icmp ult i55 10000, %j0 + %t10 = icmp sgt i55 -10000, %j0 + + ret i55 %i0 +end + +define i31 @"phitest"(i12 %i) +begin + +HasArg: + %n1 = add i12 1, %i + br label %Continue + +Continue: + %n = phi i12 [%n1, %HasArg], [%next, %Continue] + %next = add i12 1, %n + br label %Continue +end + +define i18 @"select"(i18 %i) +begin + %t = icmp sgt i18 %i, 100 + %k = select i1 %t, i18 %i, i18 999 + ret i18 %k +end + diff --git a/final/test/Integer/BitMem.ll b/final/test/Integer/BitMem.ll new file mode 100644 index 00000000000..2c093bc9902 --- /dev/null +++ b/final/test/Integer/BitMem.ll @@ -0,0 +1,29 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +declare void @"foo"() + + +; foo test basic arith operations +define void @"foo"() { + %t1 = malloc i31, i32 4 + %t2 = malloc i31, i32 7, align 1024 + %t3 = malloc [4 x i15] + + %idx = getelementptr [4 x i15]* %t3, i64 0, i64 2 + store i15 -123, i15* %idx + + free [4 x i15]* %t3 + free i31* %t2 + free i31* %t1 + + %t4 = alloca i12, i32 100 + free i12* %t4 + + %t5 = alloca i31 + store i31 -123, i31* %t5 + + free i31* %t5 + ret void +} diff --git a/final/test/Integer/BitMisc.ll b/final/test/Integer/BitMisc.ll new file mode 100644 index 00000000000..8ce4d4add7d --- /dev/null +++ b/final/test/Integer/BitMisc.ll @@ -0,0 +1,24 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + + +@MyVar = external global i19 +@MyIntList = external global { i39 *, i19 } + external global i19 ; i19*:0 + +@AConst = constant i19 -123 + +@AString = constant [4 x i8] c"test" + +@ZeroInit = global { [100 x i19 ], [40 x float ] } { [100 x i19] zeroinitializer, + [40 x float] zeroinitializer } + + +define i19 @"foo"(i19 %blah) +begin + store i19 5, i19* @MyVar + %idx = getelementptr { i39 *, i19 } * @MyIntList, i64 0, i32 1 + store i19 12, i19* %idx + ret i19 %blah +end diff --git a/final/test/Integer/BitPacked.ll b/final/test/Integer/BitPacked.ll new file mode 100644 index 00000000000..e6e453ab0c2 --- /dev/null +++ b/final/test/Integer/BitPacked.ll @@ -0,0 +1,21 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +@foo1 = external global <4 x float> +@foo2 = external global <2 x i10> + + +define void @main() +{ + store <4 x float> , <4 x float>* @foo1 + store <2 x i10> , <2 x i10>* @foo2 + %l1 = load <4 x float>* @foo1 + %l2 = load <2 x i10>* @foo2 + %r1 = extractelement <2 x i10> %l2, i32 1 + %r2 = extractelement <2 x i10> %l2, i32 0 + %t = mul i10 %r1, %r2 + %r3 = insertelement <2 x i10> %l2, i10 %t, i32 0 + store <2 x i10> %r3, <2 x i10>* @foo2 + ret void +} diff --git a/final/test/Integer/alignment_bt.ll b/final/test/Integer/alignment_bt.ll new file mode 100644 index 00000000000..3a9d0511d7f --- /dev/null +++ b/final/test/Integer/alignment_bt.ll @@ -0,0 +1,21 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +@X = global i19 4, align 16 + +define i19 *@test() align 32 { + %X = alloca i19, align 4 + %Y = alloca i51, i32 42, align 16 + %Z = alloca i32, align 1 + ret i19 *%X +} + +define i19 *@test2() { + %X = malloc i19, align 4 + %Y = malloc i51, i32 42, align 16 + %Z = malloc i32, align 1 + ret i19 *%X +} + + diff --git a/final/test/Integer/basictest_bt.ll b/final/test/Integer/basictest_bt.ll new file mode 100644 index 00000000000..5c98856d06b --- /dev/null +++ b/final/test/Integer/basictest_bt.ll @@ -0,0 +1,31 @@ +; RUN: llvm-as %s -o - | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + + +; Test "stripped" format where nothing is symbolic... this is how the bytecode +; format looks anyways (except for negative vs positive offsets)... +; +define void @void(i39, i39) { + add i39 0, 0 ; :3 [#uses=2] + sub i39 0, 4 ; :4 [#uses=2] + br label %5 + +;

} +; +define void @test() { + br label %Top + +Top: ; preds = %Out, %0 + br label %LoopHeader + +Next: ; preds = %LoopHeader + br i1 false, label %Inner, label %Out + +Inner: ; preds = %Inner, %Next + br i1 false, label %Inner, label %LoopHeader + +LoopHeader: ; preds = %Inner, %Top + br label %Next + +Out: ; preds = %Next + br i1 false, label %Top, label %Done + +Done: ; preds = %Out + ret void +} + diff --git a/final/test/Other/2004-08-16-PackedConstantInlineStore.ll b/final/test/Other/2004-08-16-PackedConstantInlineStore.ll new file mode 100644 index 00000000000..36ac4fd5af4 --- /dev/null +++ b/final/test/Other/2004-08-16-PackedConstantInlineStore.ll @@ -0,0 +1,8 @@ +; RUN: llvm-as < %s | llvm-dis +@bar = external global <2 x i32> ; <<2 x i32>*> [#uses=1] + +define void @main() { + store <2 x i32> < i32 0, i32 1 >, <2 x i32>* @bar + ret void +} + diff --git a/final/test/Other/2004-08-16-PackedGlobalConstant.ll b/final/test/Other/2004-08-16-PackedGlobalConstant.ll new file mode 100644 index 00000000000..9130ccba173 --- /dev/null +++ b/final/test/Other/2004-08-16-PackedGlobalConstant.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llvm-dis + +@foo = global <2 x i32> < i32 0, i32 1 > ; <<2 x i32>*> [#uses=1] +@bar = external global <2 x i32> ; <<2 x i32>*> [#uses=1] + +define void @main() { + %t0 = load <2 x i32>* @foo ; <<2 x i32>> [#uses=1] + store <2 x i32> %t0, <2 x i32>* @bar + ret void +} + diff --git a/final/test/Other/2004-08-16-PackedSelect.ll b/final/test/Other/2004-08-16-PackedSelect.ll new file mode 100644 index 00000000000..c1d6214dc63 --- /dev/null +++ b/final/test/Other/2004-08-16-PackedSelect.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llvm-dis + +@foo = external global <4 x float> ; <<4 x float>*> [#uses=1] +@bar = external global <4 x float> ; <<4 x float>*> [#uses=1] + +define void @main() { + %t0 = load <4 x float>* @foo ; <<4 x float>> [#uses=3] + %t1 = fadd <4 x float> %t0, %t0 ; <<4 x float>> [#uses=1] + %t2 = select i1 true, <4 x float> %t0, <4 x float> %t1 ; <<4 x float>> [#uses=1] + store <4 x float> %t2, <4 x float>* @bar + ret void +} + diff --git a/final/test/Other/2004-08-16-PackedSimple.ll b/final/test/Other/2004-08-16-PackedSimple.ll new file mode 100644 index 00000000000..81cecd4235f --- /dev/null +++ b/final/test/Other/2004-08-16-PackedSimple.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llvm-dis + +@foo = external global <4 x float> ; <<4 x float>*> [#uses=1] +@bar = external global <4 x float> ; <<4 x float>*> [#uses=1] + +define void @main() { + %t0 = load <4 x float>* @foo ; <<4 x float>> [#uses=3] + %t2 = fadd <4 x float> %t0, %t0 ; <<4 x float>> [#uses=1] + %t3 = select i1 false, <4 x float> %t0, <4 x float> %t2 ; <<4 x float>> [#uses=1] + store <4 x float> %t3, <4 x float>* @bar + ret void +} + diff --git a/final/test/Other/2004-08-20-PackedControlFlow.ll b/final/test/Other/2004-08-20-PackedControlFlow.ll new file mode 100644 index 00000000000..39435706934 --- /dev/null +++ b/final/test/Other/2004-08-20-PackedControlFlow.ll @@ -0,0 +1,22 @@ +; RUN: llvm-as < %s | llvm-dis | llvm-as > /dev/null + + %v4f = type <4 x float> +@foo = external global %v4f ; <%v4f*> [#uses=1] +@bar = external global %v4f ; <%v4f*> [#uses=1] + +define void @main() { + br label %A + +C: ; preds = %B + store %v4f %t2, %v4f* @bar + ret void + +B: ; preds = %A + %t2 = fadd %v4f %t0, %t0 ; <%v4f> [#uses=1] + br label %C + +A: ; preds = %0 + %t0 = load %v4f* @foo ; <%v4f> [#uses=2] + br label %B +} + diff --git a/final/test/Other/2006-02-05-PassManager.ll b/final/test/Other/2006-02-05-PassManager.ll new file mode 100644 index 00000000000..0ab5411aa19 --- /dev/null +++ b/final/test/Other/2006-02-05-PassManager.ll @@ -0,0 +1,5 @@ +; RUN: opt < %s -domtree -gvn -domtree -constmerge -disable-output + +define i32 @test1() { + unreachable +} diff --git a/final/test/Other/2007-04-24-eliminate-mostly-empty-blocks.ll b/final/test/Other/2007-04-24-eliminate-mostly-empty-blocks.ll new file mode 100644 index 00000000000..c436e07a9ca --- /dev/null +++ b/final/test/Other/2007-04-24-eliminate-mostly-empty-blocks.ll @@ -0,0 +1,309 @@ +;RUN: opt < %s -codegenprepare -disable-output + +define void @foo() { +entry: + br i1 false, label %cond_next31, label %cond_true + +cond_true: ; preds = %entry + br i1 false, label %cond_true19, label %cond_next31 + +cond_true19: ; preds = %cond_true + br i1 false, label %bb510, label %cond_next31 + +cond_next31: ; preds = %cond_true19, %cond_true, %entry + br i1 false, label %cond_true61, label %cond_next78 + +cond_true61: ; preds = %cond_next31 + br label %cond_next78 + +cond_next78: ; preds = %cond_true61, %cond_next31 + br i1 false, label %cond_true93, label %bb.preheader + +cond_true93: ; preds = %cond_next78 + br label %bb.preheader + +bb.preheader: ; preds = %cond_true93, %cond_next78 + %iftmp.11.0.ph.ph = phi i16 [ 0, %cond_true93 ], [ 0, %cond_next78 ] ; [#uses=1] + br label %bb + +bb: ; preds = %cond_next499, %bb.preheader + %n.1 = phi i16 [ %iftmp.11.0.ph.ph, %cond_next499 ], [ 0, %bb.preheader ] ; [#uses=0] + br i1 false, label %bb148.preheader, label %bb493 + +bb148.preheader: ; preds = %bb + br label %bb148 + +bb148: ; preds = %cond_next475, %bb148.preheader + br i1 false, label %cond_next175, label %bb184 + +cond_next175: ; preds = %bb148 + br i1 false, label %bb184, label %bb185 + +bb184: ; preds = %cond_next175, %bb148 + br label %bb185 + +bb185: ; preds = %bb184, %cond_next175 + br i1 false, label %bb420.preheader, label %cond_true198 + +bb420.preheader: ; preds = %bb185 + br label %bb420 + +cond_true198: ; preds = %bb185 + br i1 false, label %bb294, label %cond_next208 + +cond_next208: ; preds = %cond_true198 + br i1 false, label %cond_next249, label %cond_true214 + +cond_true214: ; preds = %cond_next208 + br i1 false, label %bb294, label %cond_next262 + +cond_next249: ; preds = %cond_next208 + br i1 false, label %bb294, label %cond_next262 + +cond_next262: ; preds = %cond_next249, %cond_true214 + br label %bb269 + +bb269: ; preds = %cond_next285, %cond_next262 + br i1 false, label %cond_next285, label %cond_true279 + +cond_true279: ; preds = %bb269 + br label %cond_next285 + +cond_next285: ; preds = %cond_true279, %bb269 + br i1 false, label %bb269, label %cond_next446.loopexit + +bb294: ; preds = %cond_next249, %cond_true214, %cond_true198 + br i1 false, label %cond_next336, label %cond_true301 + +cond_true301: ; preds = %bb294 + br i1 false, label %cond_false398, label %cond_true344 + +cond_next336: ; preds = %bb294 + br i1 false, label %cond_false398, label %cond_true344 + +cond_true344: ; preds = %cond_next336, %cond_true301 + br i1 false, label %cond_false381, label %cond_true351 + +cond_true351: ; preds = %cond_true344 + br label %cond_next387 + +cond_false381: ; preds = %cond_true344 + br label %cond_next387 + +cond_next387: ; preds = %cond_false381, %cond_true351 + br label %cond_next401 + +cond_false398: ; preds = %cond_next336, %cond_true301 + br label %cond_next401 + +cond_next401: ; preds = %cond_false398, %cond_next387 + br i1 false, label %cond_next475, label %cond_true453 + +bb420: ; preds = %cond_next434, %bb420.preheader + br i1 false, label %cond_next434, label %cond_true428 + +cond_true428: ; preds = %bb420 + br label %cond_next434 + +cond_next434: ; preds = %cond_true428, %bb420 + br i1 false, label %bb420, label %cond_next446.loopexit1 + +cond_next446.loopexit: ; preds = %cond_next285 + br label %cond_next446 + +cond_next446.loopexit1: ; preds = %cond_next434 + br label %cond_next446 + +cond_next446: ; preds = %cond_next446.loopexit1, %cond_next446.loopexit + br i1 false, label %cond_next475, label %cond_true453 + +cond_true453: ; preds = %cond_next446, %cond_next401 + br i1 false, label %cond_true458, label %cond_next475 + +cond_true458: ; preds = %cond_true453 + br label %cond_next475 + +cond_next475: ; preds = %cond_true458, %cond_true453, %cond_next446, %cond_next401 + br i1 false, label %bb493.loopexit, label %bb148 + +bb493.loopexit: ; preds = %cond_next475 + br label %bb493 + +bb493: ; preds = %bb493.loopexit, %bb + br i1 false, label %cond_next499, label %bb510.loopexit + +cond_next499: ; preds = %bb493 + br label %bb + +bb510.loopexit: ; preds = %bb493 + br label %bb510 + +bb510: ; preds = %bb510.loopexit, %cond_true19 + br i1 false, label %cond_next524, label %cond_true517 + +cond_true517: ; preds = %bb510 + br label %cond_next524 + +cond_next524: ; preds = %cond_true517, %bb510 + br i1 false, label %cond_next540, label %cond_true533 + +cond_true533: ; preds = %cond_next524 + br label %cond_next540 + +cond_next540: ; preds = %cond_true533, %cond_next524 + br i1 false, label %cond_true554, label %cond_next560 + +cond_true554: ; preds = %cond_next540 + br label %cond_next560 + +cond_next560: ; preds = %cond_true554, %cond_next540 + br i1 false, label %cond_true566, label %cond_next572 + +cond_true566: ; preds = %cond_next560 + br label %cond_next572 + +cond_next572: ; preds = %cond_true566, %cond_next560 + br i1 false, label %bb608.preheader, label %bb791.preheader + +bb608.preheader: ; preds = %cond_next797.us, %cond_next572 + br label %bb608 + +bb608: ; preds = %cond_next771, %bb608.preheader + br i1 false, label %cond_false627, label %cond_true613 + +cond_true613: ; preds = %bb608 + br label %cond_next640 + +cond_false627: ; preds = %bb608 + br label %cond_next640 + +cond_next640: ; preds = %cond_false627, %cond_true613 + br i1 false, label %cond_true653, label %cond_next671 + +cond_true653: ; preds = %cond_next640 + br label %cond_next671 + +cond_next671: ; preds = %cond_true653, %cond_next640 + br i1 false, label %cond_true683, label %cond_next724 + +cond_true683: ; preds = %cond_next671 + br i1 false, label %cond_next724, label %L1 + +cond_next724: ; preds = %cond_true683, %cond_next671 + br i1 false, label %cond_true735, label %L1 + +cond_true735: ; preds = %cond_next724 + br label %L1 + +L1: ; preds = %cond_true735, %cond_next724, %cond_true683 + br i1 false, label %cond_true745, label %cond_next771 + +cond_true745: ; preds = %L1 + br label %cond_next771 + +cond_next771: ; preds = %cond_true745, %L1 + br i1 false, label %bb608, label %bb791.preheader.loopexit + +bb791.preheader.loopexit: ; preds = %cond_next771 + br label %bb791.preheader + +bb791.preheader: ; preds = %bb791.preheader.loopexit, %cond_next572 + br i1 false, label %cond_next797.us, label %bb809.split + +cond_next797.us: ; preds = %bb791.preheader + br label %bb608.preheader + +bb809.split: ; preds = %bb791.preheader + br i1 false, label %cond_next827, label %cond_true820 + +cond_true820: ; preds = %bb809.split + br label %cond_next827 + +cond_next827: ; preds = %cond_true820, %bb809.split + br i1 false, label %cond_true833, label %cond_next840 + +cond_true833: ; preds = %cond_next827 + br label %cond_next840 + +cond_next840: ; preds = %cond_true833, %cond_next827 + br i1 false, label %bb866, label %bb1245 + +bb866: ; preds = %bb1239, %cond_next840 + br i1 false, label %cond_true875, label %bb911 + +cond_true875: ; preds = %bb866 + br label %cond_next1180 + +bb911: ; preds = %bb866 + switch i32 0, label %bb1165 [ + i32 0, label %bb915 + i32 1, label %bb932 + i32 2, label %bb941 + i32 3, label %bb1029 + i32 4, label %bb1036 + i32 5, label %bb1069 + i32 6, label %L3 + ] + +bb915: ; preds = %cond_next1171, %bb911 + br i1 false, label %cond_next1171, label %cond_next1180 + +bb932: ; preds = %cond_next1171, %bb911 + br label %L1970 + +bb941: ; preds = %cond_next1171, %bb911 + br label %L1970 + +L1970: ; preds = %bb941, %bb932 + br label %bb1165 + +bb1029: ; preds = %cond_next1171, %bb911 + br label %L4 + +bb1036: ; preds = %cond_next1171, %bb911 + br label %L4 + +bb1069: ; preds = %cond_next1171, %bb911 + br i1 false, label %cond_next1121, label %cond_true1108 + +L3: ; preds = %cond_next1171, %bb911 + br i1 false, label %cond_next1121, label %cond_true1108 + +cond_true1108: ; preds = %L3, %bb1069 + br label %L4 + +cond_next1121: ; preds = %L3, %bb1069 + br label %L4 + +L4: ; preds = %cond_next1121, %cond_true1108, %bb1036, %bb1029 + br label %bb1165 + +bb1165: ; preds = %cond_next1171, %L4, %L1970, %bb911 + br i1 false, label %cond_next1171, label %cond_next1180 + +cond_next1171: ; preds = %bb1165, %bb915 + switch i32 0, label %bb1165 [ + i32 0, label %bb915 + i32 1, label %bb932 + i32 2, label %bb941 + i32 3, label %bb1029 + i32 4, label %bb1036 + i32 5, label %bb1069 + i32 6, label %L3 + ] + +cond_next1180: ; preds = %bb1165, %bb915, %cond_true875 + br label %bb1239 + +bb1239: ; preds = %cond_next1251, %cond_next1180 + br i1 false, label %bb866, label %bb1245 + +bb1245: ; preds = %bb1239, %cond_next840 + br i1 false, label %cond_next1251, label %bb1257 + +cond_next1251: ; preds = %bb1245 + br label %bb1239 + +bb1257: ; preds = %bb1245 + ret void +} diff --git a/final/test/Other/2007-06-05-PassID.ll b/final/test/Other/2007-06-05-PassID.ll new file mode 100644 index 00000000000..2554b8b9edd --- /dev/null +++ b/final/test/Other/2007-06-05-PassID.ll @@ -0,0 +1,11 @@ +;RUN: opt < %s -analyze -dot-cfg-only 2>/dev/null +;PR 1497 + +define void @foo() { +entry: + br label %return + +return: ; preds = %entry + ret void +} + diff --git a/final/test/Other/2007-06-28-PassManager.ll b/final/test/Other/2007-06-28-PassManager.ll new file mode 100644 index 00000000000..0ed275948db --- /dev/null +++ b/final/test/Other/2007-06-28-PassManager.ll @@ -0,0 +1,7 @@ +; RUN: opt < %s -analyze -inline +; PR1526 +; RUN: opt < %s -analyze -indvars +; PR1539 +define i32 @test1() { + ret i32 0 +} diff --git a/final/test/Other/2007-09-10-PassManager.ll b/final/test/Other/2007-09-10-PassManager.ll new file mode 100644 index 00000000000..ded15e56951 --- /dev/null +++ b/final/test/Other/2007-09-10-PassManager.ll @@ -0,0 +1,32 @@ +; RUN: opt < %s -loop-unswitch -indvars -disable-output +; Require SCEV before LCSSA. +define void @foo() { +entry: + %i = alloca i32, align 4 ; [#uses=5] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 0, i32* %i, align 4 + br label %bb3 + +bb: ; preds = %bb3 + %tmp = load i32* %i, align 4 ; [#uses=1] + call void @bar( i32 %tmp ) + %tmp1 = load i32* %i, align 4 ; [#uses=1] + %tmp2 = add i32 %tmp1, 1 ; [#uses=1] + store i32 %tmp2, i32* %i, align 4 + br label %bb3 + +bb3: ; preds = %bb, %entry + %tmp4 = load i32* %i, align 4 ; [#uses=1] + %tmp5 = icmp sle i32 %tmp4, 9 ; [#uses=1] + %tmp56 = zext i1 %tmp5 to i8 ; [#uses=1] + %toBool = icmp ne i8 %tmp56, 0 ; [#uses=1] + br i1 %toBool, label %bb, label %bb7 + +bb7: ; preds = %bb3 + br label %return + +return: ; preds = %bb7 + ret void +} + +declare void @bar(i32) diff --git a/final/test/Other/2008-02-14-PassManager.ll b/final/test/Other/2008-02-14-PassManager.ll new file mode 100644 index 00000000000..bdaf9330d23 --- /dev/null +++ b/final/test/Other/2008-02-14-PassManager.ll @@ -0,0 +1,5 @@ +; RUN: opt < %s -loop-unroll -loop-rotate -simplifycfg -disable-output +; PR2028 +define i32 @test1() { + ret i32 0 +} diff --git a/final/test/Other/2008-06-04-FieldSizeInPacked.ll b/final/test/Other/2008-06-04-FieldSizeInPacked.ll new file mode 100644 index 00000000000..d90209f6af3 --- /dev/null +++ b/final/test/Other/2008-06-04-FieldSizeInPacked.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -instcombine -S | grep true + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + %packed = type <{ x86_fp80, i8 }> + %unpacked = type { x86_fp80, i8 } + +define i1 @q() nounwind { +entry: + %char_p = getelementptr %packed* null, i32 0, i32 1 ; [#uses=1] + %char_u = getelementptr %unpacked* null, i32 0, i32 1 ; [#uses=1] + %res = icmp eq i8* %char_p, %char_u ; [#uses=1] + ret i1 %res +} diff --git a/final/test/Other/2008-10-06-RemoveDeadPass.ll b/final/test/Other/2008-10-06-RemoveDeadPass.ll new file mode 100644 index 00000000000..7cec2c57c2f --- /dev/null +++ b/final/test/Other/2008-10-06-RemoveDeadPass.ll @@ -0,0 +1,11 @@ +; RUN: opt < %s -inline -internalize -disable-output +define void @foo() nounwind { + ret void +} + +define void @main(...) nounwind { + call void @foo() + ret void +} + + diff --git a/final/test/Other/2008-10-15-MissingSpace.ll b/final/test/Other/2008-10-15-MissingSpace.ll new file mode 100644 index 00000000000..a61fa614213 --- /dev/null +++ b/final/test/Other/2008-10-15-MissingSpace.ll @@ -0,0 +1,7 @@ +; RUN: llvm-as < %s | llvm-dis | not grep {void@} +; PR2894 +declare void @g() +define void @f() { + invoke void @g() to label %c unwind label %c + c: ret void +} diff --git a/final/test/Other/2009-03-31-CallGraph.ll b/final/test/Other/2009-03-31-CallGraph.ll new file mode 100644 index 00000000000..d6653ecbe8e --- /dev/null +++ b/final/test/Other/2009-03-31-CallGraph.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -inline -prune-eh -disable-output +define void @f2() { + invoke void @f6() + to label %ok1 unwind label %lpad1 + +ok1: + ret void + +lpad1: + invoke void @f4() + to label %ok2 unwind label %lpad2 + +ok2: + call void @f8() + unreachable + +lpad2: + unreachable +} + +declare void @f3() + +define void @f4() { + call void @f3() + ret void +} + +declare void @f6() nounwind + +declare void @f8() + diff --git a/final/test/Other/2009-06-05-no-implicit-float.ll b/final/test/Other/2009-06-05-no-implicit-float.ll new file mode 100644 index 00000000000..3f071703167 --- /dev/null +++ b/final/test/Other/2009-06-05-no-implicit-float.ll @@ -0,0 +1,4 @@ + +; RUN: opt < %s -verify -S | grep noimplicitfloat +declare void @f() noimplicitfloat + diff --git a/final/test/Other/2009-09-14-function-elements.ll b/final/test/Other/2009-09-14-function-elements.ll new file mode 100644 index 00000000000..883d76d1075 --- /dev/null +++ b/final/test/Other/2009-09-14-function-elements.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as %s -disable-output 2>/dev/null + +; Arrays and structures with function types (not function pointers) are illegal. + +@foo = external global [4 x i32 (i32)] +@bar = external global { i32 (i32) } diff --git a/final/test/Other/2010-05-06-Printer.ll b/final/test/Other/2010-05-06-Printer.ll new file mode 100644 index 00000000000..1cbe78dab7d --- /dev/null +++ b/final/test/Other/2010-05-06-Printer.ll @@ -0,0 +1,6 @@ +; RUN: llc -O2 -print-after-all < %s 2>/dev/null + +define void @tester(){ + ret void +} + diff --git a/final/test/Other/close-stderr.ll b/final/test/Other/close-stderr.ll new file mode 100644 index 00000000000..40a01cc3143 --- /dev/null +++ b/final/test/Other/close-stderr.ll @@ -0,0 +1,11 @@ +; RUN: sh -c "\ +; RUN: opt --reject-this-option 2>&-; echo \$?; \ +; RUN: opt -o /dev/null /dev/null 2>&-; echo \$?; \ +; RUN: " | FileCheck %s +; CHECK: {{^1$}} +; CHECK: {{^0$}} +; XFAIL: vg_leak +; REQUIRES: shell + +; Test that the error handling when writing to stderr fails exits the +; program cleanly rather than aborting. diff --git a/final/test/Other/constant-fold-gep.ll b/final/test/Other/constant-fold-gep.ll new file mode 100644 index 00000000000..926bdbc1b46 --- /dev/null +++ b/final/test/Other/constant-fold-gep.ll @@ -0,0 +1,459 @@ +; "PLAIN" - No optimizations. This tests the target-independent +; constant folder. +; RUN: opt -S -o - < %s | FileCheck --check-prefix=PLAIN %s + +; "OPT" - Optimizations but no targetdata. This tests target-independent +; folding in the optimizers. +; RUN: opt -S -o - -instcombine -globalopt < %s | FileCheck --check-prefix=OPT %s + +; "TO" - Optimizations and targetdata. This tests target-dependent +; folding in the optimizers. +; RUN: opt -S -o - -instcombine -globalopt -default-data-layout="e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" < %s | FileCheck --check-prefix=TO %s + +; "SCEV" - ScalarEvolution but no targetdata. +; RUN: opt -analyze -scalar-evolution < %s | FileCheck --check-prefix=SCEV %s + +; ScalarEvolution with targetdata isn't interesting on these testcases +; because ScalarEvolution doesn't attempt to duplicate all of instcombine's +; and the constant folders' folding. + +; PLAIN: %0 = type { i1, double } +; PLAIN: %1 = type { double, float, double, double } +; PLAIN: %2 = type { i1, i1* } +; PLAIN: %3 = type { i64, i64 } +; PLAIN: %4 = type { i32, i32 } +; OPT: %0 = type { i1, double } +; OPT: %1 = type { double, float, double, double } +; OPT: %2 = type { i1, i1* } +; OPT: %3 = type { i64, i64 } +; OPT: %4 = type { i32, i32 } + +; The automatic constant folder in opt does not have targetdata access, so +; it can't fold gep arithmetic, in general. However, the constant folder run +; from instcombine and global opt can use targetdata. + +; PLAIN: @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +; PLAIN: @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +; PLAIN: @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +; PLAIN: @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +; PLAIN: @H8 = global i8* getelementptr (i8* null, i32 -1) +; PLAIN: @H1 = global i1* getelementptr (i1* null, i32 -1) +; OPT: @G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +; OPT: @G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +; OPT: @F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +; OPT: @F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +; OPT: @H8 = global i8* getelementptr (i8* null, i32 -1) +; OPT: @H1 = global i1* getelementptr (i1* null, i32 -1) +; TO: @G8 = global i8* null +; TO: @G1 = global i1* null +; TO: @F8 = global i8* inttoptr (i64 -1 to i8*) +; TO: @F1 = global i1* inttoptr (i64 -1 to i1*) +; TO: @H8 = global i8* inttoptr (i64 -1 to i8*) +; TO: @H1 = global i1* inttoptr (i64 -1 to i1*) + +@G8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +@G1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +@F8 = global i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +@F1 = global i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +@H8 = global i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1) +@H1 = global i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1) + +; The target-independent folder should be able to do some clever +; simplifications on sizeof, alignof, and offsetof expressions. The +; target-dependent folder should fold these down to constants. + +; PLAIN: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) +; PLAIN: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; PLAIN: @c = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) +; PLAIN: @d = constant i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) +; PLAIN: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) +; PLAIN: @f = constant i64 1 +; PLAIN: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; PLAIN: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) +; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; OPT: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) +; OPT: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: @c = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) +; OPT: @d = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) +; OPT: @e = constant i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) +; OPT: @f = constant i64 1 +; OPT: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) +; OPT: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; TO: @a = constant i64 18480 +; TO: @b = constant i64 8 +; TO: @c = constant i64 16 +; TO: @d = constant i64 88 +; TO: @e = constant i64 16 +; TO: @f = constant i64 1 +; TO: @g = constant i64 8 +; TO: @h = constant i64 8 +; TO: @i = constant i64 8 + +@a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) +@b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64) +@c = constant i64 ptrtoint (double* getelementptr ({double, double, double, double}* null, i64 0, i32 2) to i64) +@d = constant i64 ptrtoint (double* getelementptr ([13 x double]* null, i64 0, i32 11) to i64) +@e = constant i64 ptrtoint (double* getelementptr ({double, float, double, double}* null, i64 0, i32 2) to i64) +@f = constant i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) +@g = constant i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}* null, i64 0, i32 1) to i64) +@h = constant i64 ptrtoint (double** getelementptr (double** null, i64 1) to i64) +@i = constant i64 ptrtoint (double** getelementptr ({i1, double*}* null, i64 0, i32 1) to i64) + +; The target-dependent folder should cast GEP indices to integer-sized pointers. + +; PLAIN: @M = constant i64* getelementptr (i64* null, i32 1) +; PLAIN: @N = constant i64* getelementptr (%3* null, i32 0, i32 1) +; PLAIN: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1) +; OPT: @M = constant i64* getelementptr (i64* null, i32 1) +; OPT: @N = constant i64* getelementptr (%3* null, i32 0, i32 1) +; OPT: @O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1) +; TO: @M = constant i64* inttoptr (i64 8 to i64*) +; TO: @N = constant i64* inttoptr (i64 8 to i64*) +; TO: @O = constant i64* inttoptr (i64 8 to i64*) + +@M = constant i64* getelementptr (i64* null, i32 1) +@N = constant i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) +@O = constant i64* getelementptr ([2 x i64]* null, i32 0, i32 1) + +; Fold GEP of a GEP. Theoretically some of these cases could be folded +; without using targetdata, however that's not implemented yet. + +; PLAIN: @Z = global i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) +; OPT: @Z = global i32* getelementptr (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) +; TO: @Z = global i32* getelementptr inbounds ([3 x %0]* @ext, i64 0, i64 1, i32 1) + +@ext = external global [3 x { i32, i32 }] +@Z = global i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) + +; Duplicate all of the above as function return values rather than +; global initializers. + +; PLAIN: define i8* @goo8() nounwind { +; PLAIN: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8* +; PLAIN: ret i8* %t +; PLAIN: } +; PLAIN: define i1* @goo1() nounwind { +; PLAIN: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1* +; PLAIN: ret i1* %t +; PLAIN: } +; PLAIN: define i8* @foo8() nounwind { +; PLAIN: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8* +; PLAIN: ret i8* %t +; PLAIN: } +; PLAIN: define i1* @foo1() nounwind { +; PLAIN: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1* +; PLAIN: ret i1* %t +; PLAIN: } +; PLAIN: define i8* @hoo8() nounwind { +; PLAIN: %t = bitcast i8* getelementptr (i8* null, i32 -1) to i8* +; PLAIN: ret i8* %t +; PLAIN: } +; PLAIN: define i1* @hoo1() nounwind { +; PLAIN: %t = bitcast i1* getelementptr (i1* null, i32 -1) to i1* +; PLAIN: ret i1* %t +; PLAIN: } +; OPT: define i8* @goo8() nounwind { +; OPT: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) +; OPT: } +; OPT: define i1* @goo1() nounwind { +; OPT: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) +; OPT: } +; OPT: define i8* @foo8() nounwind { +; OPT: ret i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) +; OPT: } +; OPT: define i1* @foo1() nounwind { +; OPT: ret i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) +; OPT: } +; OPT: define i8* @hoo8() nounwind { +; OPT: ret i8* getelementptr (i8* null, i32 -1) +; OPT: } +; OPT: define i1* @hoo1() nounwind { +; OPT: ret i1* getelementptr (i1* null, i32 -1) +; OPT: } +; TO: define i8* @goo8() nounwind { +; TO: ret i8* null +; TO: } +; TO: define i1* @goo1() nounwind { +; TO: ret i1* null +; TO: } +; TO: define i8* @foo8() nounwind { +; TO: ret i8* inttoptr (i64 -1 to i8*) +; TO: } +; TO: define i1* @foo1() nounwind { +; TO: ret i1* inttoptr (i64 -1 to i1*) +; TO: } +; TO: define i8* @hoo8() nounwind { +; TO: ret i8* inttoptr (i64 -1 to i8*) +; TO: } +; TO: define i1* @hoo1() nounwind { +; TO: ret i1* inttoptr (i64 -1 to i1*) +; TO: } +; SCEV: Classifying expressions for: @goo8 +; SCEV: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8* +; SCEV: --> ((-1 * sizeof(i8)) + inttoptr (i32 1 to i8*)) +; SCEV: Classifying expressions for: @goo1 +; SCEV: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1* +; SCEV: --> ((-1 * sizeof(i1)) + inttoptr (i32 1 to i1*)) +; SCEV: Classifying expressions for: @foo8 +; SCEV: %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8* +; SCEV: --> ((-2 * sizeof(i8)) + inttoptr (i32 1 to i8*)) +; SCEV: Classifying expressions for: @foo1 +; SCEV: %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1* +; SCEV: --> ((-2 * sizeof(i1)) + inttoptr (i32 1 to i1*)) +; SCEV: Classifying expressions for: @hoo8 +; SCEV: --> (-1 * sizeof(i8)) +; SCEV: Classifying expressions for: @hoo1 +; SCEV: --> (-1 * sizeof(i1)) + +define i8* @goo8() nounwind { + %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -1) to i8* + ret i8* %t +} +define i1* @goo1() nounwind { + %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -1) to i1* + ret i1* %t +} +define i8* @foo8() nounwind { + %t = bitcast i8* getelementptr (i8* inttoptr (i32 1 to i8*), i32 -2) to i8* + ret i8* %t +} +define i1* @foo1() nounwind { + %t = bitcast i1* getelementptr (i1* inttoptr (i32 1 to i1*), i32 -2) to i1* + ret i1* %t +} +define i8* @hoo8() nounwind { + %t = bitcast i8* getelementptr (i8* inttoptr (i32 0 to i8*), i32 -1) to i8* + ret i8* %t +} +define i1* @hoo1() nounwind { + %t = bitcast i1* getelementptr (i1* inttoptr (i32 0 to i1*), i32 -1) to i1* + ret i1* %t +} + +; PLAIN: define i64 @fa() nounwind { +; PLAIN: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fb() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fc() nounwind { +; PLAIN: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fd() nounwind { +; PLAIN: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fe() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @ff() nounwind { +; PLAIN: %t = bitcast i64 1 to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fg() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fh() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fi() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; OPT: define i64 @fa() nounwind { +; OPT: ret i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) +; OPT: } +; OPT: define i64 @fb() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: } +; OPT: define i64 @fc() nounwind { +; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) +; OPT: } +; OPT: define i64 @fd() nounwind { +; OPT: ret i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) +; OPT: } +; OPT: define i64 @fe() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) +; OPT: } +; OPT: define i64 @ff() nounwind { +; OPT: ret i64 1 +; OPT: } +; OPT: define i64 @fg() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: } +; OPT: define i64 @fh() nounwind { +; OPT: ret i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) +; OPT: } +; OPT: define i64 @fi() nounwind { +; OPT: ret i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; OPT: } +; TO: define i64 @fa() nounwind { +; TO: ret i64 18480 +; TO: } +; TO: define i64 @fb() nounwind { +; TO: ret i64 8 +; TO: } +; TO: define i64 @fc() nounwind { +; TO: ret i64 16 +; TO: } +; TO: define i64 @fd() nounwind { +; TO: ret i64 88 +; TO: } +; TO: define i64 @fe() nounwind { +; TO: ret i64 16 +; TO: } +; TO: define i64 @ff() nounwind { +; TO: ret i64 1 +; TO: } +; TO: define i64 @fg() nounwind { +; TO: ret i64 8 +; TO: } +; TO: define i64 @fh() nounwind { +; TO: ret i64 8 +; TO: } +; TO: define i64 @fi() nounwind { +; TO: ret i64 8 +; TO: } +; SCEV: Classifying expressions for: @fa +; SCEV: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64 +; SCEV: --> (2310 * sizeof(double)) +; SCEV: Classifying expressions for: @fb +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; SCEV: --> alignof(double) +; SCEV: Classifying expressions for: @fc +; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) to i64 +; SCEV: --> (2 * sizeof(double)) +; SCEV: Classifying expressions for: @fd +; SCEV: %t = bitcast i64 mul nuw (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 11) to i64 +; SCEV: --> (11 * sizeof(double)) +; SCEV: Classifying expressions for: @fe +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%1* null, i64 0, i32 2) to i64) to i64 +; SCEV: --> offsetof({ double, float, double, double }, 2) +; SCEV: Classifying expressions for: @ff +; SCEV: %t = bitcast i64 1 to i64 +; SCEV: --> 1 +; SCEV: Classifying expressions for: @fg +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; SCEV: --> alignof(double) +; SCEV: Classifying expressions for: @fh +; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) to i64 +; SCEV: --> sizeof(i1*) +; SCEV: Classifying expressions for: @fi +; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64 +; SCEV: --> alignof(i1*) + +define i64 @fa() nounwind { + %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64 + ret i64 %t +} +define i64 @fb() nounwind { + %t = bitcast i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} +define i64 @fc() nounwind { + %t = bitcast i64 ptrtoint (double* getelementptr ({double, double, double, double}* null, i64 0, i32 2) to i64) to i64 + ret i64 %t +} +define i64 @fd() nounwind { + %t = bitcast i64 ptrtoint (double* getelementptr ([13 x double]* null, i64 0, i32 11) to i64) to i64 + ret i64 %t +} +define i64 @fe() nounwind { + %t = bitcast i64 ptrtoint (double* getelementptr ({double, float, double, double}* null, i64 0, i32 2) to i64) to i64 + ret i64 %t +} +define i64 @ff() nounwind { + %t = bitcast i64 ptrtoint (<{ i16, i128 }>* getelementptr ({i1, <{ i16, i128 }>}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} +define i64 @fg() nounwind { + %t = bitcast i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} +define i64 @fh() nounwind { + %t = bitcast i64 ptrtoint (double** getelementptr (double** null, i32 1) to i64) to i64 + ret i64 %t +} +define i64 @fi() nounwind { + %t = bitcast i64 ptrtoint (double** getelementptr ({i1, double*}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} + +; PLAIN: define i64* @fM() nounwind { +; PLAIN: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64* +; PLAIN: ret i64* %t +; PLAIN: } +; PLAIN: define i64* @fN() nounwind { +; PLAIN: %t = bitcast i64* getelementptr (%3* null, i32 0, i32 1) to i64* +; PLAIN: ret i64* %t +; PLAIN: } +; PLAIN: define i64* @fO() nounwind { +; PLAIN: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64* +; PLAIN: ret i64* %t +; PLAIN: } +; OPT: define i64* @fM() nounwind { +; OPT: ret i64* getelementptr (i64* null, i32 1) +; OPT: } +; OPT: define i64* @fN() nounwind { +; OPT: ret i64* getelementptr (%3* null, i32 0, i32 1) +; OPT: } +; OPT: define i64* @fO() nounwind { +; OPT: ret i64* getelementptr ([2 x i64]* null, i32 0, i32 1) +; OPT: } +; TO: define i64* @fM() nounwind { +; TO: ret i64* inttoptr (i64 8 to i64*) +; TO: } +; TO: define i64* @fN() nounwind { +; TO: ret i64* inttoptr (i64 8 to i64*) +; TO: } +; TO: define i64* @fO() nounwind { +; TO: ret i64* inttoptr (i64 8 to i64*) +; TO: } +; SCEV: Classifying expressions for: @fM +; SCEV: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64* +; SCEV: --> sizeof(i64) +; SCEV: Classifying expressions for: @fN +; SCEV: %t = bitcast i64* getelementptr (%3* null, i32 0, i32 1) to i64* +; SCEV: --> sizeof(i64) +; SCEV: Classifying expressions for: @fO +; SCEV: %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64* +; SCEV: --> sizeof(i64) + +define i64* @fM() nounwind { + %t = bitcast i64* getelementptr (i64* null, i32 1) to i64* + ret i64* %t +} +define i64* @fN() nounwind { + %t = bitcast i64* getelementptr ({ i64, i64 }* null, i32 0, i32 1) to i64* + ret i64* %t +} +define i64* @fO() nounwind { + %t = bitcast i64* getelementptr ([2 x i64]* null, i32 0, i32 1) to i64* + ret i64* %t +} + +; PLAIN: define i32* @fZ() nounwind { +; PLAIN: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) to i32* +; PLAIN: ret i32* %t +; PLAIN: } +; OPT: define i32* @fZ() nounwind { +; OPT: ret i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) +; OPT: } +; TO: define i32* @fZ() nounwind { +; TO: ret i32* getelementptr inbounds ([3 x %0]* @ext, i64 0, i64 1, i32 1) +; TO: } +; SCEV: Classifying expressions for: @fZ +; SCEV: %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x %4]* @ext, i64 0, i64 1, i32 0), i64 1) to i32* +; SCEV: --> ((3 * sizeof(i32)) + @ext) + +define i32* @fZ() nounwind { + %t = bitcast i32* getelementptr inbounds (i32* getelementptr inbounds ([3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32* + ret i32* %t +} diff --git a/final/test/Other/dg.exp b/final/test/Other/dg.exp new file mode 100644 index 00000000000..f2005891a59 --- /dev/null +++ b/final/test/Other/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] diff --git a/final/test/Other/extract.ll b/final/test/Other/extract.ll new file mode 100644 index 00000000000..57573ed76f9 --- /dev/null +++ b/final/test/Other/extract.ll @@ -0,0 +1,27 @@ +; RUN: llvm-extract -func foo -S < %s | FileCheck %s +; RUN: llvm-extract -delete -func foo -S < %s | FileCheck --check-prefix=DELETE %s +; RUN: llvm-as < %s > %t +; RUN: llvm-extract -func foo -S %t | FileCheck %s +; RUN: llvm-extract -delete -func foo -S %t | FileCheck --check-prefix=DELETE %s + +; llvm-extract uses lazy bitcode loading, so make sure it correctly reads +; from bitcode files in addition to assembly files. + +; CHECK: define void @foo() { +; CHECK: ret void +; CHECK: } + +; The linkonce_odr linkage for foo() should be changed to external linkage. +; DELETE: declare void @foo() +; DELETE: define void @bar() { +; DELETE: call void @foo() +; DELETE: ret void +; DELETE: } + +define linkonce_odr void @foo() { + ret void +} +define void @bar() { + call void @foo() + ret void +} diff --git a/final/test/Other/inline-asm-newline-terminator.ll b/final/test/Other/inline-asm-newline-terminator.ll new file mode 100644 index 00000000000..af93cc0dd2a --- /dev/null +++ b/final/test/Other/inline-asm-newline-terminator.ll @@ -0,0 +1,6 @@ +; RUN: llc -filetype=obj -o - < %s + +; ModuleID = 't.c' +target triple = "x86_64-apple-darwin10.0.0" + +module asm ".desc _f0, 0x10" diff --git a/final/test/Other/invalid-commandline-option.ll b/final/test/Other/invalid-commandline-option.ll new file mode 100644 index 00000000000..60840fa010a --- /dev/null +++ b/final/test/Other/invalid-commandline-option.ll @@ -0,0 +1,3 @@ +; RUN: not opt --foo |& grep {Unknown command line argument} + +; there is no --foo diff --git a/final/test/Other/lint.ll b/final/test/Other/lint.ll new file mode 100644 index 00000000000..4aa984e2e1b --- /dev/null +++ b/final/test/Other/lint.ll @@ -0,0 +1,167 @@ +; RUN: opt -basicaa -lint -disable-output < %s |& FileCheck %s +target datalayout = "e-p:64:64:64" + +declare fastcc void @bar() +declare void @llvm.stackrestore(i8*) +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind +declare void @has_sret(i8* sret %p) +declare void @has_noaliases(i32* noalias %p, i32* %q) +declare void @one_arg(i32) + +@CG = constant i32 7 + +define i32 @foo() noreturn { +; CHECK: Caller and callee calling convention differ + call void @bar() +; CHECK: Null pointer dereference + store i32 0, i32* null +; CHECK: Null pointer dereference + %t = load i32* null +; CHECK: Undef pointer dereference + store i32 0, i32* undef +; CHECK: Undef pointer dereference + %u = load i32* undef +; CHECK: All-ones pointer dereference + store i32 0, i32* inttoptr (i64 -1 to i32*) +; CHECK: Address one pointer dereference + store i32 0, i32* inttoptr (i64 1 to i32*) +; CHECK: Memory reference address is misaligned + %x = inttoptr i32 1 to i32* + load i32* %x, align 4 +; CHECK: Division by zero + %sd = sdiv i32 2, 0 +; CHECK: Division by zero + %ud = udiv i32 2, 0 +; CHECK: Division by zero + %sr = srem i32 2, 0 +; CHECK: Division by zero + %ur = urem i32 2, 0 +; CHECK: extractelement index out of range + %ee = extractelement <4 x i32> zeroinitializer, i32 4 +; CHECK: insertelement index out of range + %ie = insertelement <4 x i32> zeroinitializer, i32 0, i32 4 +; CHECK: Shift count out of range + %r = lshr i32 0, 32 +; CHECK: Shift count out of range + %q = ashr i32 0, 32 +; CHECK: Shift count out of range + %l = shl i32 0, 32 +; CHECK: xor(undef, undef) + %xx = xor i32 undef, undef +; CHECK: sub(undef, undef) + %xs = sub i32 undef, undef + +; CHECK: Write to read-only memory + store i32 8, i32* @CG +; CHECK: Write to text section + store i32 8, i32* bitcast (i32()* @foo to i32*) +; CHECK: Load from block address + %lb = load i32* bitcast (i8* blockaddress(@foo, %next) to i32*) +; CHECK: Call to block address + call void()* bitcast (i8* blockaddress(@foo, %next) to void()*)() +; CHECK: Undefined behavior: Null pointer dereference + call void @llvm.stackrestore(i8* null) +; CHECK: Undefined behavior: Null pointer dereference + call void @has_sret(i8* null) +; CHECK: Unusual: noalias argument aliases another argument + call void @has_noaliases(i32* @CG, i32* @CG) +; CHECK: Call argument count mismatches callee argument count + call void (i32, i32)* bitcast (void (i32)* @one_arg to void (i32, i32)*)(i32 0, i32 0) +; CHECK: Call argument count mismatches callee argument count + call void ()* bitcast (void (i32)* @one_arg to void ()*)() +; CHECK: Call argument type mismatches callee parameter type + call void (float)* bitcast (void (i32)* @one_arg to void (float)*)(float 0.0) + +; CHECK: Write to read-only memory + call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (i32* @CG to i8*), i8* bitcast (i32* @CG to i8*), i64 1, i32 1, i1 0) + + br label %next + +next: +; CHECK: Static alloca outside of entry block + %a = alloca i32 +; CHECK: Return statement in function with noreturn attribute + ret i32 0 + +foo: + %z = add i32 0, 0 +; CHECK: unreachable immediately preceded by instruction without side effects + unreachable +} + +; CHECK: Unnamed function with non-local linkage +define void @0() nounwind { + ret void +} + +; CHECK: va_start called in a non-varargs function +declare void @llvm.va_start(i8*) +define void @not_vararg(i8* %p) nounwind { + call void @llvm.va_start(i8* %p) + ret void +} + +; CHECK: Undefined behavior: Branch to non-blockaddress +define void @use_indbr() { + indirectbr i8* bitcast (i32()* @foo to i8*), [label %block] +block: + unreachable +} + +; CHECK: Undefined behavior: Call with "tail" keyword references alloca +declare void @tailcallee(i8*) +define void @use_tail(i8* %valist) { + %t = alloca i8 + tail call void @tailcallee(i8* %t) + ret void +} + +; CHECK: Unusual: Returning alloca value +define i8* @return_local(i32 %n, i32 %m) { + %t = alloca i8, i32 %n + %s = getelementptr i8* %t, i32 %m + ret i8* %s +} + +; CHECK: Unusual: Returning alloca value +define i32* @return_obscured_local() { +entry: + %retval = alloca i32* + %x = alloca i32 + store i32* %x, i32** %retval + br label %next +next: + %t0 = load i32** %retval + %t1 = insertvalue { i32, i32, i32* } zeroinitializer, i32* %t0, 2 + %t2 = extractvalue { i32, i32, i32* } %t1, 2 + br label %exit +exit: + %t3 = phi i32* [ %t2, %next ] + %t4 = bitcast i32* %t3 to i32* + %t5 = ptrtoint i32* %t4 to i64 + %t6 = add i64 %t5, 0 + %t7 = inttoptr i64 %t6 to i32* + ret i32* %t7 +} + +; CHECK: Undefined behavior: Undef pointer dereference +define i32* @self_reference() { +entry: + unreachable +exit: + %t3 = phi i32* [ %t4, %exit ] + %t4 = bitcast i32* %t3 to i32* + %x = volatile load i32* %t3 + br label %exit +} + +; CHECK: Call return type mismatches callee return type +%struct = type { double, double } +declare i32 @nonstruct_callee() nounwind +define void @struct_caller() nounwind { +entry: + call %struct bitcast (i32 ()* @foo to %struct ()*)() + + ; CHECK: Undefined behavior: indirectbr with no destinations + indirectbr i8* null, [] +} diff --git a/final/test/Scripts/README.txt b/final/test/Scripts/README.txt new file mode 100644 index 00000000000..b0b11050375 --- /dev/null +++ b/final/test/Scripts/README.txt @@ -0,0 +1,2 @@ +This directory contains scripts which are used by the TestRunner style +tests, which allows them to be simpler and more direct. diff --git a/final/test/Scripts/coff-dump.py b/final/test/Scripts/coff-dump.py new file mode 100755 index 00000000000..36ec53932c6 --- /dev/null +++ b/final/test/Scripts/coff-dump.py @@ -0,0 +1,590 @@ +#!/usr/bin/env python +#===-- coff-dump.py - COFF object file dump utility-------------------------===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +# +# COFF File Definition +# + +def string_table_entry (offset): + return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s')) + +def secname(value): + if value[0] == '/': + return string_table_entry(value[1:].rstrip('\0')) + else: + return '%s' + +def symname(value): + parts = struct.unpack("<2L", value) + if parts[0] == 0: + return string_table_entry(parts[1]) + else: + return '%s' + +file = ('struct', [ + ('MachineType', ('enum', '> 4 + ('ComplexType', ('enum', '>> & _Type 240 4', '%d', { + 0: 'IMAGE_SYM_DTYPE_NULL', + 1: 'IMAGE_SYM_DTYPE_POINTER', + 2: 'IMAGE_SYM_DTYPE_FUNCTION', + 3: 'IMAGE_SYM_DTYPE_ARRAY', + })), + ('StorageClass', ('enum', ' 0) + Input.seek(Stack[0]) + del Stack[0] + +def print_binary_data(size): + value = "" + while size > 0: + if size >= 16: + data = Input.read(16) + size -= 16 + else: + data = Input.read(size) + size = 0 + value += data + bytes = "" + text = "" + for index in xrange(16): + if index < len(data): + if index == 8: + bytes += "- " + ch = ord(data[index]) + bytes += "%02X " % ch + if ch >= 0x20 and ch <= 0x7F: + text += data[index] + else: + text += "." + else: + if index == 8: + bytes += " " + bytes += " " + + write("%s|%s|\n" % (bytes, text)) + return value + +idlit = re.compile("[a-zA-Z_][a-zA-Z0-9_-]*") +numlit = re.compile("[0-9]+") + +def read_value(expr): + + input = iter(expr.split()) + + def eval(): + + token = input.next() + + if expr == 'cstr': + return read_cstr() + if expr == 'true': + return True + if expr == 'false': + return False + + if token == '+': + return eval() + eval() + if token == '-': + return eval() - eval() + if token == '*': + return eval() * eval() + if token == '/': + return eval() / eval() + if token == '&': + return eval() & eval() + if token == '|': + return eval() | eval() + if token == '>>': + return eval() >> eval() + if token == '<<': + return eval() << eval() + + if len(token) > 1 and token[0] in ('=', '@', '<', '!', '>'): + val = read(expr) + assert(len(val) == 1) + return val[0] + + if idlit.match(token): + return Fields[token] + if numlit.match(token): + return int(token) + + raise RuntimeError("unexpected token %s" % repr(token)) + + value = eval() + + try: + input.next() + except StopIteration: + return value + raise RuntimeError("unexpected input at end of expression") + +def write_value(format,value): + format_type = type(format) + if format_type is types.StringType: + write(format % value) + elif format_type is types.FunctionType: + write_value(format(value), value) + elif format_type is types.TupleType: + Fields['this'] = value + handle_element(format) + elif format_type is types.NoneType: + pass + else: + raise RuntimeError("unexpected type: %s" % repr(format_type)) + +def handle_scalar(entry): + iformat = entry[1] + oformat = entry[2] + + value = read_value(iformat) + + write_value(oformat, value) + + return value + +def handle_enum(entry): + iformat = entry[1] + oformat = entry[2] + definitions = entry[3] + + value = read_value(iformat) + + if type(definitions) is types.TupleType: + selector = read_value(definitions[0]) + definitions = definitions[1][selector] + + if value in definitions: + description = definitions[value] + else: + description = "unknown" + + write("%s (" % description) + write_value(oformat, value) + write(")") + + return value + +def handle_flags(entry): + iformat = entry[1] + oformat = entry[2] + definitions = entry[3] + + value = read_value(iformat) + + write_value(oformat, value) + + indent() + for entry in definitions: + mask = entry[0] + name = entry[1] + if len (entry) == 3: + map = entry[2] + selection = value & mask + if selection in map: + write("\n%s" % map[selection]) + else: + write("\n%s <%d>" % (name, selection)) + elif len(entry) == 2: + if value & mask != 0: + write("\n%s" % name) + dedent() + + return value + +def handle_struct(entry): + global Fields + members = entry[1] + + newFields = {} + + write("{\n"); + indent() + + for member in members: + name = member[0] + type = member[1] + + if name[0] != "_": + write("%s = " % name.ljust(24)) + + value = handle_element(type) + + if name[0] != "_": + write("\n") + + Fields[name] = value + newFields[name] = value + + dedent() + write("}") + + return newFields + +def handle_array(entry): + start_index = entry[1] + length = entry[2] + element = entry[3] + + newItems = [] + + write("[\n") + indent() + + start_index = read_value(start_index) + value = read_value(length) + + for index in xrange(value): + write("%d = " % (index + start_index)) + value = handle_element(element) + write("\n") + newItems.append(value) + + dedent() + write("]") + + return newItems + +def handle_byte_array(entry): + ent_size = entry[1] + length = entry[2] + element = entry[3] + + newItems = [] + + write("[\n") + indent() + + item_size = read_value(ent_size) + value = read_value(length) + end_of_array = Input.tell() + value + + prev_loc = Input.tell() + index = 0 + while Input.tell() < end_of_array: + write("%d = " % index) + value = handle_element(element) + write("\n") + newItems.append(value) + index += (Input.tell() - prev_loc) / item_size + prev_loc = Input.tell() + + dedent() + write("]") + + return newItems + +def handle_ptr(entry): + offset = entry[1] + element = entry[2] + + value = None + offset = read_value(offset) + + if offset != 0: + + push_pos(offset) + + value = handle_element(element) + + pop_pos() + + else: + write("None") + + return value + +def handle_blob(entry): + length = entry[1] + + write("\n") + indent() + + value = print_binary_data(read_value(length)) + + dedent() + + return value + +def handle_element(entry): + handlers = { + 'struct': handle_struct, + 'scalar': handle_scalar, + 'enum': handle_enum, + 'flags': handle_flags, + 'ptr': handle_ptr, + 'blob': handle_blob, + 'array': handle_array, + 'byte-array': handle_byte_array, + } + + if not entry[0] in handlers: + raise RuntimeError ("unexpected type '%s'" % str (entry[0])) + + return handlers[entry[0]](entry) + +if len(sys.argv) <= 1 or sys.argv[1] == '-': + import StringIO + Input = StringIO.StringIO(sys.stdin.read()) +else: + Input = open (sys.argv[1], "rb") + +try: + handle_element(file) +finally: + Input.close() + Input = None diff --git a/final/test/Scripts/coff-dump.py.bat b/final/test/Scripts/coff-dump.py.bat new file mode 100644 index 00000000000..56428e1a605 --- /dev/null +++ b/final/test/Scripts/coff-dump.py.bat @@ -0,0 +1,7 @@ +@echo off + +@rem We need to set -u to treat stdin as binary. Python 3 has support for doing +@rem this in code, but I haven't found a way to do this in 2.6 yet. + +%PYTHON_EXECUTABLE% -u %LLVM_SRC_ROOT%\test\Scripts\coff-dump.py %1 %2 %3 %4 %5 %6 %7 %8 %9 + diff --git a/final/test/Scripts/common_dump.py b/final/test/Scripts/common_dump.py new file mode 100644 index 00000000000..3d69c3fb27f --- /dev/null +++ b/final/test/Scripts/common_dump.py @@ -0,0 +1,46 @@ +def dataToHex(d): + """ Convert the raw data in 'd' to an hex string with a space every 4 bytes. + """ + bytes = [] + for i,c in enumerate(d): + byte = ord(c) + hex_byte = hex(byte)[2:] + if byte <= 0xf: + hex_byte = '0' + hex_byte + if i % 4 == 3: + hex_byte += ' ' + bytes.append(hex_byte) + return ''.join(bytes).strip() + +def dataToHexUnified(d): + """ Convert the raw data in 'd' to an hex string with a space every 4 bytes. + Each 4byte number is prefixed with 0x for easy sed/rx + Fixme: convert all MC tests to use this routine instead of the above + """ + bytes = [] + for i,c in enumerate(d): + byte = ord(c) + hex_byte = hex(byte)[2:] + if byte <= 0xf: + hex_byte = '0' + hex_byte + if i % 4 == 0: + hex_byte = '0x' + hex_byte + if i % 4 == 3: + hex_byte += ' ' + bytes.append(hex_byte) + return ''.join(bytes).strip() + + +def HexDump(val, numBits=32): + """ + 1. do not print 'L' + 2. Handle negatives and large numbers by mod (2^numBits) + 3. print fixed length, prepend with zeros. + Length is exactly 2+(numBits/4) + 4. Do print 0x Why? + so that they can be easily distinguished using sed/rx + """ + val = val & (( 1 << numBits) - 1) + newFmt = "0x%0" + "%d" % (numBits / 4) + "x" + return newFmt % val + diff --git a/final/test/Scripts/elf-dump b/final/test/Scripts/elf-dump new file mode 100755 index 00000000000..76cdbf91c73 --- /dev/null +++ b/final/test/Scripts/elf-dump @@ -0,0 +1,231 @@ +#!/usr/bin/env python + +import struct +import sys +import StringIO + +import common_dump + +class Reader: + def __init__(self, path): + if path == "-": + # Snarf all the data so we can seek. + self.file = StringIO.StringIO(sys.stdin.read()) + else: + self.file = open(path, "rb") + self.isLSB = None + self.is64Bit = None + + def seek(self, pos): + self.file.seek(pos) + + def read(self, N): + data = self.file.read(N) + if len(data) != N: + raise ValueError, "Out of data!" + return data + + def read8(self): + return ord(self.read(1)) + + def read16(self): + return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0] + + def read32(self): + return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0] + + def read32S(self): + return struct.unpack('><'[self.isLSB] + 'i', self.read(4))[0] + + def read64(self): + return struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0] + + def read64S(self): + return struct.unpack('><'[self.isLSB] + 'q', self.read(8))[0] + + def readWord(self): + if self.is64Bit: + return self.read64() + else: + return self.read32() + + def readWordS(self): + if self.is64Bit: + return self.read64S() + else: + return self.read32S() + +class StringTable: + def __init__(self, strings): + self.string_table = strings + + def __getitem__(self, index): + end = self.string_table.index('\x00', index) + return self.string_table[index:end] + +class Section: + def __init__(self, f): + self.sh_name = f.read32() + self.sh_type = f.read32() + self.sh_flags = f.readWord() + self.sh_addr = f.readWord() + self.sh_offset = f.readWord() + self.sh_size = f.readWord() + self.sh_link = f.read32() + self.sh_info = f.read32() + self.sh_addralign = f.readWord() + self.sh_entsize = f.readWord() + + def dump(self, shstrtab, f, strtab, dumpdata): + print " (('sh_name', %s)" % common_dump.HexDump(self.sh_name), "# %r" % shstrtab[self.sh_name] + print " ('sh_type', %s)" % common_dump.HexDump(self.sh_type) + print " ('sh_flags', %s)" % common_dump.HexDump(self.sh_flags) + print " ('sh_addr', %s)" % common_dump.HexDump(self.sh_addr) + print " ('sh_offset', %s)" % common_dump.HexDump(self.sh_offset) + print " ('sh_size', %s)" % common_dump.HexDump(self.sh_size) + print " ('sh_link', %s)" % common_dump.HexDump(self.sh_link) + print " ('sh_info', %s)" % common_dump.HexDump(self.sh_info) + print " ('sh_addralign', %s)" % common_dump.HexDump(self.sh_addralign) + print " ('sh_entsize', %s)" % common_dump.HexDump(self.sh_entsize) + if self.sh_type == 2: # SHT_SYMTAB + print " ('_symbols', [" + dumpSymtab(f, self, strtab) + print " ])" + elif self.sh_type == 4 or self.sh_type == 9: # SHT_RELA / SHT_REL + print " ('_relocations', [" + dumpRel(f, self, self.sh_type == 4) + print " ])" + elif dumpdata: + f.seek(self.sh_offset) + if self.sh_type != 8: # != SHT_NOBITS + data = f.read(self.sh_size) + print " ('_section_data', '%s')" % common_dump.dataToHex(data) + else: + print " ('_section_data', '')" + print " )," + +def dumpSymtab(f, section, strtab): + entries = section.sh_size // section.sh_entsize + + for index in range(entries): + f.seek(section.sh_offset + index * section.sh_entsize) + print " # Symbol %s" % common_dump.HexDump(index) + name = f.read32() + print " (('st_name', %s)" % common_dump.HexDump(name), "# %r" % strtab[name] + if not f.is64Bit: + print " ('st_value', %s)" % common_dump.HexDump(f.read32()) + print " ('st_size', %s)" % common_dump.HexDump(f.read32()) + st_info = f.read8() + print " ('st_bind', %s)" % common_dump.HexDump((st_info >> 4)) + print " ('st_type', %s)" % common_dump.HexDump((st_info & 0xf)) + print " ('st_other', %s)" % common_dump.HexDump(f.read8()) + print " ('st_shndx', %s)" % common_dump.HexDump(f.read16()) + if f.is64Bit: + print " ('st_value', %s)" % common_dump.HexDump(f.read64(), 64) + print " ('st_size', %s)" % common_dump.HexDump(f.read64(), 64) + print " )," + +def dumpRel(f, section, dumprela = False): + entries = section.sh_size // section.sh_entsize + + for index in range(entries): + f.seek(section.sh_offset + index * section.sh_entsize) + print " # Relocation %s" % common_dump.HexDump(index) + print " (('r_offset', %s)" % common_dump.HexDump(f.readWord()) + r_info = f.readWord() + if f.is64Bit: + print " ('r_sym', %s)" % common_dump.HexDump((r_info >> 32)) + print " ('r_type', %s)" % common_dump.HexDump((r_info & 0xffffffff)) + else: + print " ('r_sym', %s)" % common_dump.HexDump((r_info >> 8)) + print " ('r_type', %s)" % common_dump.HexDump((r_info & 0xff)) + if dumprela: + print " ('r_addend', %s)" % common_dump.HexDump(f.readWordS()) + print " )," + +def dumpELF(path, opts): + f = Reader(path) + + magic = f.read(4) + assert magic == '\x7FELF' + + fileclass = f.read8() + if fileclass == 1: # ELFCLASS32 + f.is64Bit = False + elif fileclass == 2: # ELFCLASS64 + f.is64Bit = True + else: + raise ValueError, "Unknown file class %s" % common_dump.HexDump(fileclass) + print "('e_indent[EI_CLASS]', %s)" % common_dump.HexDump(fileclass) + + byteordering = f.read8() + if byteordering == 1: # ELFDATA2LSB + f.isLSB = True + elif byteordering == 2: # ELFDATA2MSB + f.isLSB = False + else: + raise ValueError, "Unknown byte ordering %s" % common_dump.HexDump(byteordering) + print "('e_indent[EI_DATA]', %s)" % common_dump.HexDump(byteordering) + + print "('e_indent[EI_VERSION]', %s)" % common_dump.HexDump(f.read8()) + print "('e_indent[EI_OSABI]', %s)" % common_dump.HexDump(f.read8()) + print "('e_indent[EI_ABIVERSION]', %s)" % common_dump.HexDump(f.read8()) + + f.seek(16) # Seek to end of e_ident. + + print "('e_type', %s)" % common_dump.HexDump(f.read16()) + print "('e_machine', %s)" % common_dump.HexDump(f.read16()) + print "('e_version', %s)" % common_dump.HexDump(f.read32()) + print "('e_entry', %s)" % common_dump.HexDump(f.readWord()) + print "('e_phoff', %s)" % common_dump.HexDump(f.readWord()) + e_shoff = f.readWord() + print "('e_shoff', %s)" % common_dump.HexDump(e_shoff) + print "('e_flags', %s)" % common_dump.HexDump(f.read32()) + print "('e_ehsize', %s)" % common_dump.HexDump(f.read16()) + print "('e_phentsize', %s)" % common_dump.HexDump(f.read16()) + print "('e_phnum', %s)" % common_dump.HexDump(f.read16()) + e_shentsize = f.read16() + print "('e_shentsize', %s)" % common_dump.HexDump(e_shentsize) + e_shnum = f.read16() + print "('e_shnum', %s)" % common_dump.HexDump(e_shnum) + e_shstrndx = f.read16() + print "('e_shstrndx', %s)" % common_dump.HexDump(e_shstrndx) + + # Read all section headers + sections = [] + for index in range(e_shnum): + f.seek(e_shoff + index * e_shentsize) + s = Section(f) + sections.append(s) + + # Read .shstrtab so we can resolve section names + f.seek(sections[e_shstrndx].sh_offset) + shstrtab = StringTable(f.read(sections[e_shstrndx].sh_size)) + + # Get the symbol string table + strtab = None + for section in sections: + if shstrtab[section.sh_name] == ".strtab": + f.seek(section.sh_offset) + strtab = StringTable(f.read(section.sh_size)) + break + + print "('_sections', [" + for index in range(e_shnum): + print " # Section %s" % common_dump.HexDump(index) + sections[index].dump(shstrtab, f, strtab, opts.dumpSectionData) + print "])" + +if __name__ == "__main__": + from optparse import OptionParser, OptionGroup + parser = OptionParser("usage: %prog [options] {files}") + 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 not args: + args.append('-') + + for arg in args: + dumpELF(arg, opts) diff --git a/final/test/Scripts/elf-dump.bat b/final/test/Scripts/elf-dump.bat new file mode 100644 index 00000000000..9c708083b30 --- /dev/null +++ b/final/test/Scripts/elf-dump.bat @@ -0,0 +1,7 @@ +@echo off + +@rem We need to set -u to treat stdin as binary. Python 3 has support for doing +@rem this in code, but I haven't found a way to do this in 2.6 yet. + +%PYTHON_EXECUTABLE% -u %LLVM_SRC_ROOT%\test\Scripts\elf-dump %1 %2 %3 %4 %5 %6 %7 %8 %9 + diff --git a/final/test/Scripts/ignore b/final/test/Scripts/ignore new file mode 100755 index 00000000000..865ae4df1bd --- /dev/null +++ b/final/test/Scripts/ignore @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Program: ignore +# +# Synopsis: Ignore the result code of the command and always return 0 +# +# Syntax: ignore command + +"$@" || exit 0 && exit 0 +exit 0 diff --git a/final/test/Scripts/macho-dumpx b/final/test/Scripts/macho-dumpx new file mode 100755 index 00000000000..71e06d837b9 --- /dev/null +++ b/final/test/Scripts/macho-dumpx @@ -0,0 +1,294 @@ +#!/usr/bin/env python + +import struct +import sys +import StringIO + +import common_dump + +class Reader: + def __init__(self, path): + if path == '-': + # Snarf all the data so we can seek. + self.file = StringIO.StringIO(sys.stdin.read()) + else: + self.file = open(path,'rb') + self.isLSB = None + self.is64Bit = None + + self.string_table = None + + def tell(self): + return self.file.tell() + + def seek(self, pos): + self.file.seek(pos) + + def read(self, N): + data = self.file.read(N) + if len(data) != N: + raise ValueError,"Out of data!" + return data + + def read8(self): + return ord(self.read(1)) + + def read16(self): + return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0] + + def read32(self): + # Force to 32-bit, if possible; otherwise these might be long ints on a + # big-endian platform. FIXME: Why??? + Value = struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0] + return int(Value) + + def read64(self): + Value = struct.unpack('><'[self.isLSB] + 'Q', self.read(8))[0] + if Value == int(Value): + Value = int(Value) + return Value + + def registerStringTable(self, strings): + if self.string_table is not None: + raise ValueError,"%s: warning: multiple string tables" % sys.argv[0] + + self.string_table = strings + + def getString(self, index): + if self.string_table is None: + raise ValueError,"%s: warning: no string table registered" % sys.argv[0] + + end = self.string_table.index('\x00', index) + return self.string_table[index:end] + +def dumpmacho(path, opts): + f = Reader(path) + + magic = f.read(4) + if magic == '\xFE\xED\xFA\xCE': + f.isLSB, f.is64Bit = False, False + elif magic == '\xCE\xFA\xED\xFE': + f.isLSB, f.is64Bit = True, False + elif magic == '\xFE\xED\xFA\xCF': + f.isLSB, f.is64Bit = False, True + elif magic == '\xCF\xFA\xED\xFE': + f.isLSB, f.is64Bit = True, True + else: + raise ValueError,"Not a Mach-O object file: %r (bad magic)" % path + + print "('cputype', %r)" % f.read32() + print "('cpusubtype', %r)" % f.read32() + filetype = f.read32() + print "('filetype', %r)" % filetype + + numLoadCommands = f.read32() + print "('num_load_commands', %r)" % numLoadCommands + + loadCommandsSize = f.read32() + print "('load_commands_size', %r)" % loadCommandsSize + + print "('flag', %r)" % f.read32() + + if f.is64Bit: + print "('reserved', %r)" % f.read32() + + start = f.tell() + + print "('load_commands', [" + for i in range(numLoadCommands): + dumpLoadCommand(f, i, opts) + print "])" + + if f.tell() - start != loadCommandsSize: + raise ValueError,"%s: warning: invalid load commands size: %r" % ( + sys.argv[0], loadCommandsSize) + +def dumpLoadCommand(f, i, opts): + start = f.tell() + + print " # Load Command %r" % i + cmd = f.read32() + print " (('command', %r)" % cmd + cmdSize = f.read32() + print " ('size', %r)" % cmdSize + + if cmd == 1: + dumpSegmentLoadCommand(f, opts, False) + elif cmd == 2: + dumpSymtabCommand(f, opts) + elif cmd == 11: + dumpDysymtabCommand(f, opts) + elif cmd == 25: + dumpSegmentLoadCommand(f, opts, True) + elif cmd == 27: + import uuid + print " ('uuid', %s)" % uuid.UUID(bytes=f.read(16)) + else: + print >>sys.stderr,"%s: warning: unknown load command: %r" % ( + sys.argv[0], cmd) + f.read(cmdSize - 8) + print " )," + + if f.tell() - start != cmdSize: + raise ValueError,"%s: warning: invalid load command size: %r" % ( + sys.argv[0], cmdSize) + +def dumpSegmentLoadCommand(f, opts, is64Bit): + print " ('segment_name', %r)" % f.read(16) + if is64Bit: + print " ('vm_addr', %r)" % f.read64() + print " ('vm_size', %r)" % f.read64() + print " ('file_offset', %r)" % f.read64() + print " ('file_size', %r)" % f.read64() + else: + print " ('vm_addr', %r)" % f.read32() + print " ('vm_size', %r)" % f.read32() + print " ('file_offset', %r)" % f.read32() + print " ('file_size', %r)" % f.read32() + print " ('maxprot', %r)" % f.read32() + print " ('initprot', %r)" % f.read32() + numSections = f.read32() + print " ('num_sections', %r)" % numSections + print " ('flags', %r)" % f.read32() + + print " ('sections', [" + for i in range(numSections): + dumpSection(f, i, opts, is64Bit) + print " ])" + +def dumpSymtabCommand(f, opts): + symoff = f.read32() + print " ('symoff', %r)" % symoff + nsyms = f.read32() + print " ('nsyms', %r)" % nsyms + stroff = f.read32() + print " ('stroff', %r)" % stroff + strsize = f.read32() + print " ('strsize', %r)" % strsize + + prev_pos = f.tell() + + f.seek(stroff) + string_data = f.read(strsize) + print " ('_string_data', %r)" % string_data + + f.registerStringTable(string_data) + + f.seek(symoff) + print " ('_symbols', [" + for i in range(nsyms): + dumpNlist32(f, i, opts) + print " ])" + + f.seek(prev_pos) + +def dumpNlist32(f, i, opts): + print " # Symbol %r" % i + n_strx = f.read32() + print " (('n_strx', %r)" % n_strx + n_type = f.read8() + print " ('n_type', %#x)" % n_type + n_sect = f.read8() + print " ('n_sect', %r)" % n_sect + n_desc = f.read16() + print " ('n_desc', %r)" % n_desc + if f.is64Bit: + n_value = f.read64() + print " ('n_value', %r)" % n_value + else: + n_value = f.read32() + print " ('n_value', %r)" % n_value + print " ('_string', %r)" % f.getString(n_strx) + print " )," + +def dumpDysymtabCommand(f, opts): + print " ('ilocalsym', %r)" % f.read32() + print " ('nlocalsym', %r)" % f.read32() + print " ('iextdefsym', %r)" % f.read32() + print " ('nextdefsym', %r)" % f.read32() + print " ('iundefsym', %r)" % f.read32() + print " ('nundefsym', %r)" % f.read32() + print " ('tocoff', %r)" % f.read32() + print " ('ntoc', %r)" % f.read32() + print " ('modtaboff', %r)" % f.read32() + print " ('nmodtab', %r)" % f.read32() + print " ('extrefsymoff', %r)" % f.read32() + print " ('nextrefsyms', %r)" % f.read32() + indirectsymoff = f.read32() + print " ('indirectsymoff', %r)" % indirectsymoff + nindirectsyms = f.read32() + print " ('nindirectsyms', %r)" % nindirectsyms + print " ('extreloff', %r)" % f.read32() + print " ('nextrel', %r)" % f.read32() + print " ('locreloff', %r)" % f.read32() + print " ('nlocrel', %r)" % f.read32() + + prev_pos = f.tell() + + f.seek(indirectsymoff) + print " ('_indirect_symbols', [" + for i in range(nindirectsyms): + print " # Indirect Symbol %r" % i + print " (('symbol_index', %#x),)," % f.read32() + print " ])" + + f.seek(prev_pos) + +def dumpSection(f, i, opts, is64Bit): + print " # Section %r" % i + print " (('section_name', %r)" % f.read(16) + print " ('segment_name', %r)" % f.read(16) + if is64Bit: + print " ('address', %r)" % f.read64() + size = f.read64() + print " ('size', %r)" % size + else: + print " ('address', %r)" % f.read32() + size = f.read32() + print " ('size', %r)" % size + offset = f.read32() + print " ('offset', %r)" % offset + print " ('alignment', %r)" % f.read32() + reloc_offset = f.read32() + print " ('reloc_offset', %r)" % reloc_offset + num_reloc = f.read32() + print " ('num_reloc', %r)" % num_reloc + print " ('flags', %#x)" % f.read32() + print " ('reserved1', %r)" % f.read32() + print " ('reserved2', %r)" % f.read32() + if is64Bit: + print " ('reserved3', %r)" % f.read32() + print " )," + + prev_pos = f.tell() + + f.seek(reloc_offset) + print " ('_relocations', [" + for i in range(num_reloc): + print " # Relocation %r" % i + print " (('word-0', %#x)," % f.read32() + print " ('word-1', %#x))," % f.read32() + print " ])" + + if opts.dumpSectionData: + f.seek(offset) + print " ('_section_data', '%s')" % common_dump.dataToHex(f.read(size)) + + f.seek(prev_pos) + +def main(): + from optparse import OptionParser, OptionGroup + parser = OptionParser("usage: %prog [options] {files}") + 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 not args: + args.append('-') + + for arg in args: + dumpmacho(arg, opts) + +if __name__ == '__main__': + main() diff --git a/final/test/Scripts/macho-dumpx.bat b/final/test/Scripts/macho-dumpx.bat new file mode 100644 index 00000000000..81484f67d70 --- /dev/null +++ b/final/test/Scripts/macho-dumpx.bat @@ -0,0 +1,7 @@ +@echo off + +@rem We need to set -u to treat stdin as binary. Python 3 has support for doing +@rem this in code, but I haven't found a way to do this in 2.6 yet. + +%PYTHON_EXECUTABLE% -u %LLVM_SRC_ROOT%\test\Scripts\macho-dump %1 %2 %3 %4 %5 %6 %7 %8 %9 + diff --git a/final/test/TableGen/2003-08-03-PassCode.td b/final/test/TableGen/2003-08-03-PassCode.td new file mode 100644 index 00000000000..c02f499b382 --- /dev/null +++ b/final/test/TableGen/2003-08-03-PassCode.td @@ -0,0 +1,8 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +class test { + code Code = C; +} + +def foo : test<[{ hello world! }]>; diff --git a/final/test/TableGen/2006-09-18-LargeInt.td b/final/test/TableGen/2006-09-18-LargeInt.td new file mode 100644 index 00000000000..194699acc63 --- /dev/null +++ b/final/test/TableGen/2006-09-18-LargeInt.td @@ -0,0 +1,6 @@ +// RUN: tblgen %s | grep -- 4294901760 +// XFAIL: vg_leak + +def X { + int Y = 0xFFFF0000; +} diff --git a/final/test/TableGen/2010-03-24-PrematureDefaults.td b/final/test/TableGen/2010-03-24-PrematureDefaults.td new file mode 100644 index 00000000000..2ff2d42d273 --- /dev/null +++ b/final/test/TableGen/2010-03-24-PrematureDefaults.td @@ -0,0 +1,44 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class A x = 1> { + int K = k; + bits<2> Bits = x; +} + +// CHECK: def a1 +// CHECK: Bits = { 0, 1 } +def a1 : A<12>; + +// CHECK: def a2 +// CHECK: Bits = { 1, 0 } +def a2 : A<13, 2>; + +// Here was the bug: X.Bits would get resolved to the default a1.Bits while +// resolving the first template argument. When the second template argument +// was processed, X would be set correctly, but Bits retained the default +// value. +class B { + A X = x; + bits<2> Bits = X.Bits; +} + +// CHECK: def b1 +// CHECK: Bits = { 0, 1 } +def b1 : B<27>; + +// CHECK: def b2 +// CHECK: Bits = { 1, 0 } +def b2 : B<28, a2>; + +class C { + bits<2> Bits = x.Bits; +} + +// CHECK: def c1 +// CHECK: Bits = { 0, 1 } +def c1 : C; + +// CHECK: def c2 +// CHECK: Bits = { 1, 0 } +def c2 : C; diff --git a/final/test/TableGen/AnonDefinitionOnDemand.td b/final/test/TableGen/AnonDefinitionOnDemand.td new file mode 100644 index 00000000000..b10ad5870de --- /dev/null +++ b/final/test/TableGen/AnonDefinitionOnDemand.td @@ -0,0 +1,13 @@ +// RUN: tblgen < %s +// XFAIL: vg_leak + +class foo { int THEVAL = X; } +def foo_imp : foo<1>; + +def x { + foo Y = foo_imp; // This works. +} + +def X { + foo Y = foo<1>; // This should work too, synthesizing a new foo<1>. +} diff --git a/final/test/TableGen/BitsInitOverflow.td b/final/test/TableGen/BitsInitOverflow.td new file mode 100644 index 00000000000..076b3f6f73e --- /dev/null +++ b/final/test/TableGen/BitsInitOverflow.td @@ -0,0 +1,5 @@ +// RUN: not tblgen %s 2> /dev/null + +def { + bits<2> X = 5; // bitfield is too small, reject +} diff --git a/final/test/TableGen/CStyleComment.td b/final/test/TableGen/CStyleComment.td new file mode 100644 index 00000000000..703ae6837eb --- /dev/null +++ b/final/test/TableGen/CStyleComment.td @@ -0,0 +1,14 @@ +// Test that multiline, nested, comments work correctly. +// +// RUN: tblgen < %s + +/* Foo + bar + /* + blah + */ + + stuff + */ + +def x; diff --git a/final/test/TableGen/Dag.td b/final/test/TableGen/Dag.td new file mode 100644 index 00000000000..d3481a550c3 --- /dev/null +++ b/final/test/TableGen/Dag.td @@ -0,0 +1,71 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak + +//===----------------------------------------------------------------------===// +// Substitution of an int. +def X1; + +class C1 { + dag d = (X1 N); +} + +def VAL1 : C1<13>; + +// CHECK: def VAL1 { +// CHECK-NEXT: dag d = (X1 13) + + +//===----------------------------------------------------------------------===// +// Substitution of a DAG. +def X2; + +class yclass; +def Y2 : yclass; + +class C2 { + dag d = (X2 N); + dag e = (N X2); +} + +def VAL2 : C2; + +// CHECK: def VAL2 { +// CHECK-NEXT: dag d = (X2 Y2) +// CHECK-NEXT: dag e = (Y2 X2) + + +//===----------------------------------------------------------------------===// +// Complex dag operator (F.TheOp). + +class operator; +def somedef1 : operator; +def somedef2 : operator; + +class foo { + operator TheOp = a; +} + +class bar { + dag Dag1 = (somedef1 1); + dag Dag2 = (a 2); + dag Dag3 = (F.TheOp 2); +} + +def foo1 : foo; +def foo2 : foo; + +def VAL3 : bar; + +// CHECK: def VAL3 { // bar +// CHECK-NEXT: dag Dag1 = (somedef1 1); +// CHECK-NEXT: dag Dag2 = (somedef1 2); +// CHECK-NEXT: dag Dag3 = (somedef1 2); +// CHECK-NEXT: } + + +def VAL4 : bar; +// CHECK: def VAL4 { +// CHECK-NEXT: dag Dag1 = (somedef1 1); +// CHECK-NEXT: dag Dag2 = (somedef2 2); +// CHECK-NEXT: dag Dag3 = (somedef2 2); +// CHECK-NEXT: } diff --git a/final/test/TableGen/DefmInherit.td b/final/test/TableGen/DefmInherit.td new file mode 100644 index 00000000000..9e166705269 --- /dev/null +++ b/final/test/TableGen/DefmInherit.td @@ -0,0 +1,33 @@ +// RUN: tblgen %s | grep {zing = 4} | count 4 +// XFAIL: vg_leak + +class C1 { + int bar = A; + string thestr = B; + int zing; +} + +def T : C1<4, "blah">; + +multiclass t { + def S1 : C1 { + int foo = 4; + let bar = 1; + } + def S2 : C1; +} + +multiclass s { + def S3 : C1 { + int moo = 3; + let bar = 1; + } + def S4 : C1; +} + +defm FOO : t<42>, s<24>; + +def T4 : C1<6, "foo">; + +let zing = 4 in + defm BAZ : t<3>, s<4>; diff --git a/final/test/TableGen/DefmInsideMultiClass.td b/final/test/TableGen/DefmInsideMultiClass.td new file mode 100644 index 00000000000..68cc12d5681 --- /dev/null +++ b/final/test/TableGen/DefmInsideMultiClass.td @@ -0,0 +1,25 @@ +// RUN: tblgen %s | grep ADDPSrr | count 1 +// XFAIL: vg_leak + +class Instruction opc, string Name> { + bits<4> opcode = opc; + string name = Name; +} + +multiclass basic_r opc> { + def rr : Instruction; + def rm : Instruction; +} + +multiclass basic_s opc> { + defm SS : basic_r; + defm SD : basic_r; +} + +multiclass basic_p opc> { + defm PS : basic_r; + defm PD : basic_r; +} + +defm ADD : basic_s<0xf>, basic_p<0xf>; +defm SUB : basic_s<0xe>, basic_p<0xe>; diff --git a/final/test/TableGen/FieldAccess.td b/final/test/TableGen/FieldAccess.td new file mode 100644 index 00000000000..8b4dc83e0a5 --- /dev/null +++ b/final/test/TableGen/FieldAccess.td @@ -0,0 +1,16 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +class Bla +{ + string blu = t; +} + +class Bli +{ + Bla bla = t; +} + +def a : Bli>; +def b : Bla(a.bla).blu>; // works +def c : Bla; // doesn't work: Cannot access field 'blu' of value 'a.bla' diff --git a/final/test/TableGen/ForwardRef.td b/final/test/TableGen/ForwardRef.td new file mode 100644 index 00000000000..955cc14248f --- /dev/null +++ b/final/test/TableGen/ForwardRef.td @@ -0,0 +1,16 @@ +// RUN: tblgen %s -o - +// XFAIL: vg_leak + +class bar { + list x; +} + +class foo; +class foo; + +class baz { list y; } + +class foo { + +} + diff --git a/final/test/TableGen/GeneralList.td b/final/test/TableGen/GeneralList.td new file mode 100644 index 00000000000..ca92a213b22 --- /dev/null +++ b/final/test/TableGen/GeneralList.td @@ -0,0 +1,9 @@ +// RUN: tblgen %s +// XFAIL: vg_leak +// +// Test to make sure that lists work with any data-type + +class foo { + list Test = [1, 2, 3]; + list Test2 = ["abc", "xyz", "gtq"]; +} diff --git a/final/test/TableGen/Include.inc b/final/test/TableGen/Include.inc new file mode 100644 index 00000000000..876bf47ca96 --- /dev/null +++ b/final/test/TableGen/Include.inc @@ -0,0 +1,4 @@ +// This is used by the Include.td test +def InInclude; + + diff --git a/final/test/TableGen/Include.td b/final/test/TableGen/Include.td new file mode 100644 index 00000000000..29ed5150c62 --- /dev/null +++ b/final/test/TableGen/Include.td @@ -0,0 +1,7 @@ +// RUN: tblgen -I %p %s +def BeforeInclude; + +include "Include.inc" + +def AfterInclude; + diff --git a/final/test/TableGen/IntBitInit.td b/final/test/TableGen/IntBitInit.td new file mode 100644 index 00000000000..16ac9c8f912 --- /dev/null +++ b/final/test/TableGen/IntBitInit.td @@ -0,0 +1,6 @@ +// RUN: tblgen %s +// XFAIL: vg_leak +def { + bit A = 1; + int B = A; +} diff --git a/final/test/TableGen/LazyChange.td b/final/test/TableGen/LazyChange.td new file mode 100644 index 00000000000..fa53562b8c2 --- /dev/null +++ b/final/test/TableGen/LazyChange.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s | grep {int Y = 3} +// XFAIL: vg_leak + +class C { + int X = 4; + int Y = X; +} + +let X = 3 in +def D : C; // Y should be 3 too! + diff --git a/final/test/TableGen/LetInsideMultiClasses.td b/final/test/TableGen/LetInsideMultiClasses.td new file mode 100644 index 00000000000..9238bf42d9b --- /dev/null +++ b/final/test/TableGen/LetInsideMultiClasses.td @@ -0,0 +1,29 @@ +// RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3 +// XFAIL: vg_leak + +class Instruction opc, string Name> { + bits<4> opcode = opc; + string name = Name; + bit IsDouble = 0; +} + +multiclass basic_r opc> { + let name = "newname" in { + def rr : Instruction; + def rm : Instruction; + } + + let name = "othername" in + def rx : Instruction; +} + +multiclass basic_ss opc> { + let IsDouble = 0 in + defm SS : basic_r; + + let IsDouble = 1 in + defm SD : basic_r; +} + +defm ADD : basic_ss<0xf>; + diff --git a/final/test/TableGen/ListArgs.td b/final/test/TableGen/ListArgs.td new file mode 100644 index 00000000000..a513db6da3c --- /dev/null +++ b/final/test/TableGen/ListArgs.td @@ -0,0 +1,12 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +class B v> { + list vals = v; +} + +class BB> vals> : B; +class BBB> vals> : BB; + +def OneB : BBB<[[1,2,3]]>; +def TwoB : BBB<[[1,2,3],[4,5,6]]>; diff --git a/final/test/TableGen/ListArgsSimple.td b/final/test/TableGen/ListArgsSimple.td new file mode 100644 index 00000000000..f7caed69a99 --- /dev/null +++ b/final/test/TableGen/ListArgsSimple.td @@ -0,0 +1,9 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +class B { + int val = v; +} + +class BB vals> : B; +class BBB vals> : BB; diff --git a/final/test/TableGen/ListConversion.td b/final/test/TableGen/ListConversion.td new file mode 100644 index 00000000000..222b6140564 --- /dev/null +++ b/final/test/TableGen/ListConversion.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s +// XFAIL: vg_leak +class A; +class B : A; + +def b : B; + +def { + list X = [b]; + list Y = X; +} diff --git a/final/test/TableGen/ListManip.td b/final/test/TableGen/ListManip.td new file mode 100644 index 00000000000..6b1e491cd25 --- /dev/null +++ b/final/test/TableGen/ListManip.td @@ -0,0 +1,12 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +class Bli +{ + string t = _t; +} + +class Bla _bli> +: Bli +{ +} diff --git a/final/test/TableGen/ListSlices.td b/final/test/TableGen/ListSlices.td new file mode 100644 index 00000000000..5848a4e4870 --- /dev/null +++ b/final/test/TableGen/ListSlices.td @@ -0,0 +1,19 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +def A { + list B = [10, 20, 30, 4, 1, 1231, 20]; +} + +def B { + list X = [10, 20, 30, 4, 1, 1231, 20] [2-4,2,2,0-6]; + + list Y = X[4,5]; + int Z = X[4]; + + list C = A.B[1-4]; + + list> AA = [X, Y]; + + int BB = AA[0][1]; +} diff --git a/final/test/TableGen/MultiClass.td b/final/test/TableGen/MultiClass.td new file mode 100644 index 00000000000..9f92b73dba6 --- /dev/null +++ b/final/test/TableGen/MultiClass.td @@ -0,0 +1,26 @@ +// RUN: tblgen %s | grep {zing = 4} | count 2 +// XFAIL: vg_leak + +class C1 { + int bar = A; + string thestr = B; + int zing; +} + +def T : C1<4, "blah">; + +multiclass t { + def S1 : C1 { + int foo = 4; + let bar = 1; + } + def S2 : C1; +} + +defm FOO : t<42>; + +def T4 : C1<6, "foo">; + +let zing = 4 in + defm BAZ : t<3>; + diff --git a/final/test/TableGen/MultiClassDefName.td b/final/test/TableGen/MultiClassDefName.td new file mode 100644 index 00000000000..138c93d9bb0 --- /dev/null +++ b/final/test/TableGen/MultiClassDefName.td @@ -0,0 +1,13 @@ +// RUN: tblgen %s | grep WorldHelloCC | count 1 +// XFAIL: vg_leak + +class C { + string name = n; +} + +multiclass Names { + def CC : C; + def World#NAME#CC : C; +} + +defm Hello : Names<"hello", "world">; diff --git a/final/test/TableGen/MultiClassInherit.td b/final/test/TableGen/MultiClassInherit.td new file mode 100644 index 00000000000..9da80bad2d7 --- /dev/null +++ b/final/test/TableGen/MultiClassInherit.td @@ -0,0 +1,65 @@ +// RUN: tblgen %s | grep {zing = 4} | count 28 +// XFAIL: vg_leak + +class C1 { + int bar = A; + string thestr = B; + int zing; +} + +def T : C1<4, "blah">; + +multiclass t1 { + def S1 : C1 { + int foo = 4; + let bar = 1; + } + def S2 : C1; +} + +multiclass t2 { + def S3 : C1 { + int foo = 4; + let bar = 1; + } + def S4 : C1; +} + +multiclass s1 : t1 { + def S5 : C1 { + int moo = 3; + let bar = 1; + } + def S6 : C1; +} + +multiclass s2 : t1, t2; + +multiclass s3 : t1, t2 { + def S7 : C1 { + int moo = 3; + let bar = 1; + } + def S8 : C1; +} + +let zing = 4 in +defm FOO1 : s1<42, 24>; + +let zing = 4 in +defm FOO2 : s2<99>; + +let zing = 4 in +defm FOO3 : s3<84, 48>; + +def T4 : C1<6, "foo">; + +let zing = 4 in + defm BAZ1 : s1<3, 4>; + +let zing = 4 in + defm BAZ2 : s2<5>; + +let zing = 4 in + defm BAZ3 : s3<6, 7>; + diff --git a/final/test/TableGen/Slice.td b/final/test/TableGen/Slice.td new file mode 100644 index 00000000000..13d9da2b9fd --- /dev/null +++ b/final/test/TableGen/Slice.td @@ -0,0 +1,88 @@ +// RUN: tblgen %s | grep {\\\[(set} | count 2 +// RUN: tblgen %s | grep {\\\[\\\]} | count 2 +// XFAIL: vg_leak + +class ValueType { + int Size = size; + int Value = value; +} + +def f32 : ValueType<32, 1>; // 2 x i64 vector value + +class Intrinsic { + string Name = name; +} + +class Inst opcode, dag oopnds, dag iopnds, string asmstr, + list pattern> { + bits<8> Opcode = opcode; + dag OutOperands = oopnds; + dag InOperands = iopnds; + string AssemblyString = asmstr; + list Pattern = pattern; +} + +def ops; +def outs; +def ins; + +def set; + +// Define registers +class Register { + string Name = n; +} + +class RegisterClass regTypes, list regList> { + list RegTypes = regTypes; + list MemberList = regList; +} + +def XMM0: Register<"xmm0">; +def XMM1: Register<"xmm1">; +def XMM2: Register<"xmm2">; +def XMM3: Register<"xmm3">; +def XMM4: Register<"xmm4">; +def XMM5: Register<"xmm5">; +def XMM6: Register<"xmm6">; +def XMM7: Register<"xmm7">; +def XMM8: Register<"xmm8">; +def XMM9: Register<"xmm9">; +def XMM10: Register<"xmm10">; +def XMM11: Register<"xmm11">; +def XMM12: Register<"xmm12">; +def XMM13: Register<"xmm13">; +def XMM14: Register<"xmm14">; +def XMM15: Register<"xmm15">; + +def FR32 : RegisterClass<[f32], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]>; + +class SDNode {} +def not : SDNode; + +multiclass scalar opcode, string asmstr = "", list> patterns = []> { + def SSrr : Inst,patterns[0])>; + def SSrm : Inst,!if(!empty(!tail(patterns)),patterns[0],patterns[1]))>; +} + +multiclass vscalar opcode, string asmstr = "", list> patterns = []> { + def V#NAME#SSrr : Inst,patterns[0])>; + def V#NAME#SSrm : Inst,!if(!empty(!tail(patterns)),patterns[0],patterns[1]))>; +} + +multiclass myscalar opcode, string asmstr = "", list> patterns = []> : + scalar, + vscalar; + +defm NOT : myscalar<0x10, "not", [[], [(set FR32:$dst, (f32 (not FR32:$src)))]]>; diff --git a/final/test/TableGen/String.td b/final/test/TableGen/String.td new file mode 100644 index 00000000000..fc0f5b8eb54 --- /dev/null +++ b/final/test/TableGen/String.td @@ -0,0 +1,6 @@ +// RUN: tblgen %s +// XFAIL: vg_leak +class x { + string y = "missing terminating '\"' character"; +} + diff --git a/final/test/TableGen/SuperSubclassSameName.td b/final/test/TableGen/SuperSubclassSameName.td new file mode 100644 index 00000000000..304c883417f --- /dev/null +++ b/final/test/TableGen/SuperSubclassSameName.td @@ -0,0 +1,21 @@ +// RUN: tblgen < %s +// XFAIL: vg_leak +// Test for template arguments that have the same name as superclass template +// arguments. + + +class Arg { int a; } +def TheArg : Arg { let a = 1; } + + +class Super { + int X = F.a; +} +class Sub : Super; +def inst : Sub; + + +class Super2 { + int X = F; +} +class Sub2 : Super2; diff --git a/final/test/TableGen/TargetInstrInfo.td b/final/test/TableGen/TargetInstrInfo.td new file mode 100644 index 00000000000..146ef6fd768 --- /dev/null +++ b/final/test/TableGen/TargetInstrInfo.td @@ -0,0 +1,148 @@ +// This test describes how we eventually want to describe instructions in +// the target independent code generators. +// RUN: tblgen %s +// XFAIL: vg_leak + +// Target indep stuff. +class Instruction { // Would have other stuff eventually + bit isTwoAddress = 0; + string AssemblyString; +} +class RegisterClass; + +class RTLNode; + +def ops; // Marker for operand list. + +// Various expressions used in RTL descriptions. +def imm8 : RTLNode; +def imm32 : RTLNode; +def addr : RTLNode; + +def set : RTLNode; +def signext : RTLNode; +def zeroext : RTLNode; +def plus : RTLNode; +def and : RTLNode; +def xor : RTLNode; +def shl : RTLNode; +def load : RTLNode; +def store : RTLNode; +def unspec : RTLNode; + +// Start of X86 specific stuff. + +def R8 : RegisterClass; +def R16 : RegisterClass; +def R32 : RegisterClass; + +def CL; // As are currently defined +def AL; +def AX; +def EDX; + +class Format val> { + bits<5> Value = val; +} + +def Pseudo : Format<0>; def RawFrm : Format<1>; +def AddRegFrm : Format<2>; def MRMDestReg : Format<3>; +def MRMDestMem : Format<4>; def MRMSrcReg : Format<5>; +def MRMSrcMem : Format<6>; +def MRM0r : Format<16>; def MRM1r : Format<17>; def MRM2r : Format<18>; +def MRM3r : Format<19>; def MRM4r : Format<20>; def MRM5r : Format<21>; +def MRM6r : Format<22>; def MRM7r : Format<23>; +def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>; +def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>; +def MRM6m : Format<30>; def MRM7m : Format<31>; + + +class Inst opcode, + Format f, list rtl> : Instruction { + dag Operands = opnds; + string AssemblyString = asmstr; + bits<8> Opcode = opcode; + Format Format = f; + list RTL = rtl; +} + + +// Start of instruction definitions, the real point of this file. +// +// Note that these patterns show a couple of important things: +// 1. The order and contents of the operands of the MachineInstr are +// described here. Eventually we can do away with this when everything +// is generated from the description. +// 2. The asm string is captured here, which makes it possible to get rid of +// a ton of hacks in the various printers and a bunch of flags. +// 3. Target specific properties (e.g. Format) can still be captured as +// needed. +// 4. We capture the behavior of the instruction with a simplified RTL-like +// expression. +// 5. The use/def properties for each operand are automatically inferred from +// the pattern. +// 6. Address expressions should become first-class entities. + +// Simple copy instruction. +def MOV8rr : Inst<(ops R8:$dst, R8:$src), + "mov $dst, $src", 0x88, MRMDestReg, + [(set R8:$dst, R8:$src)]>; + +// Simple immediate initialization. +def MOV8ri : Inst<(ops R8:$dst, imm8:$src), + "mov $dst, $src", 0xB0, AddRegFrm, + [(set R8:$dst, imm8:$src)]>; + +// Two address instructions are described as three-addr instructions, with +// the special target-independent isTwoAddress flag set. The asm pattern +// should not refer to the $src1, this would be enforced by the +// TargetInstrInfo tablegen backend. +let isTwoAddress = 1 in +def AND8rr : Inst<(ops R8:$dst, R8:$src1, R8:$src2), + "and $dst, $src2", 0x20, MRMDestReg, + [(set R8:$dst, (and R8:$src1, R8:$src2))]>; + +// Instructions that have explicit uses/defs make them explicit in the RTL. +// Instructions that need extra stuff emitted in the assembly can, trivially. +let isTwoAddress = 1 in +def SHL32rCL : Inst<(ops R32:$dst, R32:$src), + "shl $dst, CL", 0xD2, MRM4r, + [(set R32:$dst, (shl R32:$src, CL))]>; + +// The RTL list is a list, allowing complex instructions to be defined easily. +// Temporary 'internal' registers can be used to break instructions appart. +let isTwoAddress = 1 in +def XOR32mi : Inst<(ops addr:$addr, imm32:$imm), + "xor $dst, $src2", 0x81, MRM6m, + [(set R32:$tmp1, (load addr:$addr)), + (set R32:$tmp2, (xor R32:$tmp1, imm32:$imm)), + (store addr:$addr, R32:$tmp2)]>; + +// Alternatively, if each tmporary register is only used once, the instruction +// can just be described in nested form. This would be the canonical +// representation the target generator would convert the above into. Pick your +// favorite indentation scheme. +let isTwoAddress = 1 in +def AND32mr : Inst<(ops addr:$addr, R32:$src), + "xor $dst, $src2", 0x81, MRM6m, + [(store addr:$addr, + (and + (load addr:$addr), + R32:$src) + ) + ]>; + +// Describing complex instructions is not too hard! Note how implicit uses/defs +// become explicit here. +def CBW : Inst<(ops), + "cbw", 0x98, RawFrm, + [(set AX, (signext AL))]>; + +// Noop, does nothing. +def NOOP : Inst<(ops), "nop", 0x90, RawFrm, []>; + + +// Instructions that don't expect optimization can use unspec. +def IN8rr : Inst<(ops), "in AL, EDX", 0xEC, RawFrm, + [(set AL, (unspec EDX))]>; + diff --git a/final/test/TableGen/TargetInstrSpec.td b/final/test/TableGen/TargetInstrSpec.td new file mode 100644 index 00000000000..a7ca9022f84 --- /dev/null +++ b/final/test/TableGen/TargetInstrSpec.td @@ -0,0 +1,98 @@ +// RUN: tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_pd VR128:\$src1, VR128:\$src2))\\\]} | count 1 +// RUN: tblgen %s | grep {\\\[(set VR128:\$dst, (int_x86_sse2_add_ps VR128:\$src1, VR128:\$src2))\\\]} | count 1 +// XFAIL: vg_leak + +class ValueType { + int Size = size; + int Value = value; +} + +def v2i64 : ValueType<128, 22>; // 2 x i64 vector value +def v2f64 : ValueType<128, 28>; // 2 x f64 vector value + +class Intrinsic { + string Name = name; +} + +class Inst opcode, dag oopnds, dag iopnds, string asmstr, + list pattern> { + bits<8> Opcode = opcode; + dag OutOperands = oopnds; + dag InOperands = iopnds; + string AssemblyString = asmstr; + list Pattern = pattern; +} + +def ops; +def outs; +def ins; + +def set; + +// Define registers +class Register { + string Name = n; +} + +class RegisterClass regTypes, list regList> { + list RegTypes = regTypes; + list MemberList = regList; +} + +def XMM0: Register<"xmm0">; +def XMM1: Register<"xmm1">; +def XMM2: Register<"xmm2">; +def XMM3: Register<"xmm3">; +def XMM4: Register<"xmm4">; +def XMM5: Register<"xmm5">; +def XMM6: Register<"xmm6">; +def XMM7: Register<"xmm7">; +def XMM8: Register<"xmm8">; +def XMM9: Register<"xmm9">; +def XMM10: Register<"xmm10">; +def XMM11: Register<"xmm11">; +def XMM12: Register<"xmm12">; +def XMM13: Register<"xmm13">; +def XMM14: Register<"xmm14">; +def XMM15: Register<"xmm15">; + +def VR128 : RegisterClass<[v2i64, v2f64], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]>; + +// Dummy for subst +def REGCLASS : RegisterClass<[], []>; + +class decls { + // Dummy for foreach + dag pattern; + int operand; +} + +def Decls : decls; + +// Define intrinsics +def int_x86_sse2_add_ps : Intrinsic<"addps">; +def int_x86_sse2_add_pd : Intrinsic<"addpd">; +def INTRINSIC : Intrinsic<"Dummy">; + +multiclass arith opcode, string asmstr, string intr, list patterns> { + def PS : Inst(!subst("SUFFIX", "_ps", intr)), + !subst(REGCLASS, VR128, Decls.operand))))>; + + def PD : Inst(!subst("SUFFIX", "_pd", intr)), + !subst(REGCLASS, VR128, Decls.operand))))>; +} + +defm ADD : arith<0x58, "add", "int_x86_sse2_addSUFFIX", + [(set REGCLASS:$dst, (INTRINSIC REGCLASS:$src1, REGCLASS:$src2))]>; + diff --git a/final/test/TableGen/TemplateArgRename.td b/final/test/TableGen/TemplateArgRename.td new file mode 100644 index 00000000000..ee5d2cf7752 --- /dev/null +++ b/final/test/TableGen/TemplateArgRename.td @@ -0,0 +1,18 @@ +// RUN: tblgen %s +// XFAIL: vg_leak + +// Make sure there is no collision between XX and XX. +def S; + +class Before; +class After : Before<4> { + dag XX = (S); +} + + + +class C1 { + int Y = X; +} +class C2 : C1; + diff --git a/final/test/TableGen/Tree.td b/final/test/TableGen/Tree.td new file mode 100644 index 00000000000..2796cfd3586 --- /dev/null +++ b/final/test/TableGen/Tree.td @@ -0,0 +1,19 @@ +// This tests to make sure we can parse tree patterns. +// RUN: tblgen %s +// XFAIL: vg_leak + +class TreeNode; +class RegisterClass; + +def set : TreeNode; +def plus : TreeNode; +def imm : TreeNode; +def R32 : RegisterClass; + +class Inst { + dag Pattern = T; +} + +def ADDrr32 : Inst<(set R32, (plus R32, R32))>; // a = b + c +def ADDri32 : Inst<(set R32, (plus R32, imm))>; // a = b + imm + diff --git a/final/test/TableGen/TreeNames.td b/final/test/TableGen/TreeNames.td new file mode 100644 index 00000000000..ccdeb88dd02 --- /dev/null +++ b/final/test/TableGen/TreeNames.td @@ -0,0 +1,18 @@ +// This tests to make sure we can parse tree patterns with names. +// RUN: tblgen %s +// XFAIL: vg_leak + +class TreeNode; +class RegisterClass; + +def set : TreeNode; +def plus : TreeNode; +def imm : TreeNode; +def R32 : RegisterClass; + +class Inst { + dag Pattern = T; +} + +def ADDrr32 : Inst<(set R32, (plus R32:$A, R32:$def))>; + diff --git a/final/test/TableGen/UnsetBitInit.td b/final/test/TableGen/UnsetBitInit.td new file mode 100644 index 00000000000..ff7010868bc --- /dev/null +++ b/final/test/TableGen/UnsetBitInit.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s +// XFAIL: vg_leak +class x { + field bits<32> A; +} + +class y B> : x { + let A{21-20} = B; +} + +def z : y<{0,?}>; diff --git a/final/test/TableGen/UnterminatedComment.td b/final/test/TableGen/UnterminatedComment.td new file mode 100644 index 00000000000..158cede2607 --- /dev/null +++ b/final/test/TableGen/UnterminatedComment.td @@ -0,0 +1,6 @@ +// RUN: not tblgen < %s >& /dev/null + +def x; + +/* /* /* */ + diff --git a/final/test/TableGen/cast.td b/final/test/TableGen/cast.td new file mode 100644 index 00000000000..8164e74eae4 --- /dev/null +++ b/final/test/TableGen/cast.td @@ -0,0 +1,91 @@ +// RUN: tblgen %s | grep {add_ps} | count 3 +// XFAIL: vg_leak + +class ValueType { + int Size = size; + int Value = value; +} + +def v2i64 : ValueType<128, 22>; // 2 x i64 vector value +def v2f64 : ValueType<128, 28>; // 2 x f64 vector value + +class Intrinsic { + string Name = name; +} + +class Inst opcode, dag oopnds, dag iopnds, string asmstr, + list pattern> { + bits<8> Opcode = opcode; + dag OutOperands = oopnds; + dag InOperands = iopnds; + string AssemblyString = asmstr; + list Pattern = pattern; +} + +def ops; +def outs; +def ins; + +def set; + +// Define registers +class Register { + string Name = n; +} + +class RegisterClass regTypes, list regList> { + list RegTypes = regTypes; + list MemberList = regList; +} + +def XMM0: Register<"xmm0">; +def XMM1: Register<"xmm1">; +def XMM2: Register<"xmm2">; +def XMM3: Register<"xmm3">; +def XMM4: Register<"xmm4">; +def XMM5: Register<"xmm5">; +def XMM6: Register<"xmm6">; +def XMM7: Register<"xmm7">; +def XMM8: Register<"xmm8">; +def XMM9: Register<"xmm9">; +def XMM10: Register<"xmm10">; +def XMM11: Register<"xmm11">; +def XMM12: Register<"xmm12">; +def XMM13: Register<"xmm13">; +def XMM14: Register<"xmm14">; +def XMM15: Register<"xmm15">; + +def VR128 : RegisterClass<[v2i64, v2f64], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, + XMM12, XMM13, XMM14, XMM15]>; + +// Define intrinsics +def int_x86_sse2_add_ps : Intrinsic<"addps">; +def int_x86_sse2_add_pd : Intrinsic<"addpd">; + +multiclass arith opcode, string asmstr, string Intr> { + def PS : Inst(!strconcat(Intr, "_ps")) VR128:$src1, VR128:$src2))]>; + + def PD : Inst(!strconcat(Intr, "_pd")) VR128:$src1, VR128:$src2))]>; +} + +defm ADD : arith<0x58, "add", "int_x86_sse2_add">; + +class IntInst opcode, string asmstr, Intrinsic Intr> : + Inst; + + +multiclass arith_int opcode, string asmstr, string Intr> { + def PS_Int : IntInst(!strconcat(Intr, "_ps"))>; + + def PD_Int : IntInst(!strconcat(Intr, "_pd"))>; +} + +defm ADD : arith_int<0x58, "add", "int_x86_sse2_add">; diff --git a/final/test/TableGen/defmclass.td b/final/test/TableGen/defmclass.td new file mode 100644 index 00000000000..57972b6dae5 --- /dev/null +++ b/final/test/TableGen/defmclass.td @@ -0,0 +1,50 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class XD { bits<4> Prefix = 11; } +// CHECK: Prefix = { 1, 1, 0, 0 }; +class XS { bits<4> Prefix = 12; } +class VEX { bit hasVEX_4VPrefix = 1; } + +def xd : XD; + +class BaseI { + bits<4> Prefix = 0; + bit hasVEX_4VPrefix = 0; +} + +class I op> : BaseI { + bits<4> opcode = op; + int val = !if(!eq(Prefix, xd.Prefix), 7, 21); + int check = !if(hasVEX_4VPrefix, 0, 10); +} + +multiclass R { + def rr : I<4>; +} + +multiclass M { + def rm : I<2>; +} + +multiclass Y { + defm SS : R, M, XD; +// CHECK: Prefix = { 1, 1, 0, 0 }; +// CHECK: Prefix = { 1, 1, 0, 0 }; + defm SD : R, M, XS; +} + +// CHECK: int check = 0; +defm Instr : Y, VEX; + + +// Anonymous defm. + +multiclass SomeAnonymous { + def rm; + def mr; +} + +// These multiclasses shouldn't conflict. +defm : SomeAnonymous<1>; +defm : SomeAnonymous<2>; \ No newline at end of file diff --git a/final/test/TableGen/dg.exp b/final/test/TableGen/dg.exp new file mode 100644 index 00000000000..f7d275ad8cb --- /dev/null +++ b/final/test/TableGen/dg.exp @@ -0,0 +1,3 @@ +load_lib llvm.exp + +RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{td}]] diff --git a/final/test/TableGen/eq.td b/final/test/TableGen/eq.td new file mode 100644 index 00000000000..518a80ac0d2 --- /dev/null +++ b/final/test/TableGen/eq.td @@ -0,0 +1,14 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak +// CHECK: Value = 0 +// CHECK: Value = 1 + +class Base { + int Value = V; +} + +class Derived : + Base; + +def TRUE : Derived<"true">; +def FALSE : Derived<"false">; diff --git a/final/test/TableGen/eqbit.td b/final/test/TableGen/eqbit.td new file mode 100644 index 00000000000..3953252c417 --- /dev/null +++ b/final/test/TableGen/eqbit.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak +// CHECK: a = 6 +// CHECK: a = 5 + +class A { + int a = !if(!eq(b, 1), 5, 6); +} + +def X : A<0>; +def Y : A; diff --git a/final/test/TableGen/foreach.td b/final/test/TableGen/foreach.td new file mode 100644 index 00000000000..d4d81f829ed --- /dev/null +++ b/final/test/TableGen/foreach.td @@ -0,0 +1,32 @@ +// RUN: tblgen %s | grep {Jr} | count 2 +// RUN: tblgen %s | grep {Sr} | count 2 +// RUN: tblgen %s | grep {NAME} | count 1 +// XFAIL: vg_leak + +// Variables for foreach +class decls { + string name; +} + +def Decls : decls; + +class A names> { + list Names = names; +} + +class B names> : A; + +class C names> : A; + +class D names> : A; + +class Names { + list values = ["Ken Griffey", "Seymour Cray"]; +} + +def People : Names; + +def Seniors : B; +def Juniors : C; +def Smiths : D<["NAME", "Jane Smith"]>; +def Unprocessed : D; diff --git a/final/test/TableGen/if.td b/final/test/TableGen/if.td new file mode 100644 index 00000000000..c4d953ea224 --- /dev/null +++ b/final/test/TableGen/if.td @@ -0,0 +1,45 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak + +// Support for an `!if' operator as part of a `let' statement. +// CHECK: class C +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, ?, ?, ?, !if({ C:x{2} }, 0, 1), !if({ C:x{2} }, 1, 1), !if({ C:x{2} }, 0, 0), !if({ C:x{1} }, C:y{3}, 0), !if({ C:x{1} }, C:y{2}, 1), !if({ C:x{0} }, C:y{3}, C:z), !if({ C:x{0} }, C:y{2}, C:y{2}), !if({ C:x{0} }, C:y{1}, C:y{1}), !if({ C:x{0} }, C:y{0}, C:y{0}) }; +class C x, bits<4> y, bit z> { + bits<16> n; + + let n{8-6} = !if(x{2}, 0b010, 0b110); + let n{5-4} = !if(x{1}, y{3-2}, {0, 1}); + let n{3-0} = !if(x{0}, y{3-0}, {z, y{2}, y{1}, y{0}}); +} + +// CHECK: def One +// CHECK-NEXT: list first = [1, 2, 3]; +// CHECK-NEXT: list rest = [1, 2, 3]; + +// CHECK: def OneB +// CHECK-NEXT: list vals = [1, 2, 3]; + +// CHECK: def Two +// CHECK-NEXT: list first = [1, 2, 3]; +// CHECK-NEXT: list rest = [4, 5, 6]; + +// CHECK: def TwoB +// CHECK-NEXT: list vals = [4, 5, 6]; + +class A> vals> { + list first = vals[0]; + list rest = !if(!empty(!tail(vals)), vals[0], vals[1]); +} + +def One : A<[[1,2,3]]>; +def Two : A<[[1,2,3], [4,5,6]]>; + +class B v> { + list vals = v; +} + +class BB> vals> : B; +class BBB> vals> : BB; + +def OneB : BBB<[[1,2,3]]>; +def TwoB : BBB<[[1,2,3],[4,5,6]]>; diff --git a/final/test/TableGen/ifbit.td b/final/test/TableGen/ifbit.td new file mode 100644 index 00000000000..3b0349e19b4 --- /dev/null +++ b/final/test/TableGen/ifbit.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak +// CHECK: a = 6 +// CHECK: a = 5 + +class A { + int a = !if(b, 5, 6); +} + +def X : A<0>; +def Y : A; diff --git a/final/test/TableGen/lisp.td b/final/test/TableGen/lisp.td new file mode 100644 index 00000000000..bbed8690dd5 --- /dev/null +++ b/final/test/TableGen/lisp.td @@ -0,0 +1,22 @@ +// RUN: tblgen %s | grep {} +// XFAIL: vg_leak + +class List n> { + list names = n; +} + +class CAR { + string element = e; +} + +class CDR r, int n> { + list rest = r; + int null = n; +} + +class NameList Names> : + List, CAR, CDR; + +def Three : NameList<["Tom", "Dick", "Harry"]>; + +def One : NameList<["Jeffrey Sinclair"]>; diff --git a/final/test/TableGen/nested-comment.td b/final/test/TableGen/nested-comment.td new file mode 100644 index 00000000000..68e29581bc7 --- /dev/null +++ b/final/test/TableGen/nested-comment.td @@ -0,0 +1,12 @@ +// RUN: tblgen < %s + +/* foo + +/ foo + + /*NoReg*/, baz + + + */ + +def X; diff --git a/final/test/TableGen/strconcat.td b/final/test/TableGen/strconcat.td new file mode 100644 index 00000000000..38409a99dc4 --- /dev/null +++ b/final/test/TableGen/strconcat.td @@ -0,0 +1,11 @@ +// RUN: tblgen %s | grep fufoo +// XFAIL: vg_leak + +class Y { + string T = !strconcat(S, "foo"); + + // String values concatenate lexically, as in C. + string S = "foo" "bar"; +} + +def Z : Y<"fu">; diff --git a/final/test/TableGen/subst.td b/final/test/TableGen/subst.td new file mode 100644 index 00000000000..05d424f6835 --- /dev/null +++ b/final/test/TableGen/subst.td @@ -0,0 +1,30 @@ +// RUN: tblgen %s | grep {Smith} | count 7 +// RUN: tblgen %s | grep {Johnson} | count 2 +// RUN: tblgen %s | grep {FIRST} | count 1 +// RUN: tblgen %s | grep {LAST} | count 1 +// RUN: tblgen %s | grep {TVAR} | count 2 +// RUN: tblgen %s | grep {Bogus} | count 1 +// XFAIL: vg_leak + +class Honorific { + string honorific = t; +} + +def Mr : Honorific<"Mr.">; +def Ms : Honorific<"Ms.">; +def Mrs : Honorific<"Mrs.">; +def TVAR : Honorific<"Bogus">; + +class Name { + string name = n; + Honorific honorific = t; +} + +class AName : + Name; + +def JohnSmith : AName<"FIRST LAST", TVAR>; +def JaneSmith : AName<"Jane LAST", Ms>; +def JohnSmithJones : AName<"FIRST LAST-Jones", Mr>; +def JimmyJohnson : AName<"Jimmy Johnson", Mr>; diff --git a/final/test/TableGen/subst2.td b/final/test/TableGen/subst2.td new file mode 100644 index 00000000000..584266ef233 --- /dev/null +++ b/final/test/TableGen/subst2.td @@ -0,0 +1,16 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak +// CHECK: No subst +// CHECK: No foo +// CHECK: RECURSE foo + +class Recurse { + string Text = t; +} + +class Text : + Recurse; + +def Ok1 : Text<"No subst">; +def Ok2 : Text<"No NORECURSE">; +def Trouble : Text<"RECURSE NORECURSE">; diff --git a/final/test/TableGen/usevalname.td b/final/test/TableGen/usevalname.td new file mode 100644 index 00000000000..1b31c8f1506 --- /dev/null +++ b/final/test/TableGen/usevalname.td @@ -0,0 +1,24 @@ +// RUN: tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class Instr pat> { + list Pattern = pat; +} + +class Reg { + int a = 3; +} + +def VR128 : Reg; +def mem_frag; +def set; +def addr; +def shufp : Reg; + +multiclass shuffle { + def rri : Instr<[(set RC:$dst, (shufp:$src3 + RC:$src1, RC:$src2))]>; +} + +// CHECK: shufp:src3 +defm ADD : shuffle; diff --git a/final/test/TestRunner.sh b/final/test/TestRunner.sh new file mode 100755 index 00000000000..ab50856af11 --- /dev/null +++ b/final/test/TestRunner.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# Deprecated, use 'llvm-lit'. + +echo "warning: '$0' is deprecated, use 'llvm-lit' instead." +exec llvm-lit "$@" diff --git a/final/test/Transforms/ADCE/2002-01-31-UseStuckAround.ll b/final/test/Transforms/ADCE/2002-01-31-UseStuckAround.ll new file mode 100644 index 00000000000..43462faa47f --- /dev/null +++ b/final/test/Transforms/ADCE/2002-01-31-UseStuckAround.ll @@ -0,0 +1,13 @@ +; RUN: opt < %s -adce + +define i32 @"main"(i32 %argc) +begin + br label %2 + + %retval = phi i32 [ %argc, %2 ] ; [#uses=2] + %two = add i32 %retval, %retval ; [#uses=1] + ret i32 %two + + br label %1 +end + diff --git a/final/test/Transforms/ADCE/2002-05-22-PHITest.ll b/final/test/Transforms/ADCE/2002-05-22-PHITest.ll new file mode 100644 index 00000000000..0095be1f5a1 --- /dev/null +++ b/final/test/Transforms/ADCE/2002-05-22-PHITest.ll @@ -0,0 +1,16 @@ +; It is illegal to remove BB1 because it will mess up the PHI node! +; +; RUN: opt < %s -adce -S | grep BB1 + +define i32 @test(i1 %C, i32 %A, i32 %B) { +;

operation never modifies the archive. + +=item q[Rfz] + +Quickly append files to the end of the archive. The F, F, and F +modifiers apply to this operation. This operation quickly adds the +F to the archive without checking for duplicates that should be +removed first. If no F are specified, the archive is not modified. +Because of the way that B constructs the archive file, its dubious +whether the F operation is any faster than the F operation. + +=item r[Rabfuz] + +Replace or insert file members. The F, F, F, F, F, and F +modifiers apply to this operation. This operation will replace existing +F or insert them at the end of the archive if they do not exist. If no +F are specified, the archive is not modified. + +=item t[v] + +Print the table of contents. Without any modifiers, this operation just prints +the names of the members to the standard output. With the F modifier, +B also prints out the file type (B=bitcode, Z=compressed, S=symbol +table, blank=regular file), the permission mode, the owner and group, the +size, and the date. If any F are specified, the listing is only for +those files. If no F are specified, the table of contents for the +whole archive is printed. + +=item x[oP] + +Extract archive members back to files. The F modifier applies to this +operation. This operation retrieves the indicated F from the archive +and writes them back to the operating system's file system. If no +F are specified, the entire archive is extract. + +=back + +=head2 Modifiers (operation specific) + +The modifiers below are specific to certain operations. See the Operations +section (above) to determine which modifiers are applicable to which operations. + +=over + +=item [a] + +When inserting or moving member files, this option specifies the destination of +the new files as being Cfter the F member. If F is not found, +the files are placed at the end of the archive. + +=item [b] + +When inserting or moving member files, this option specifies the destination of +the new files as being Cefore the F member. If F is not +found, the files are placed at the end of the archive. This modifier is +identical to the the F modifier. + +=item [f] + +Normally, B stores the full path name to a file as presented to it on +the command line. With this option, truncated (15 characters max) names are +used. This ensures name compatibility with older versions of C but may also +thwart correct extraction of the files (duplicates may overwrite). If used with +the F option, the directory recursion will be performed but the file names +will all be Clattened to simple file names. + +=item [i] + +A synonym for the F option. + +=item [k] + +Normally, B will not print the contents of bitcode files when the +F

+
+  void %llvm.dbg.declare(metadata, metadata)
+
+ +

This intrinsic provides information about a local element (ex. variable.) The + first argument is metadata holding alloca for the variable.. The + second argument is metadata containing description of the variable.

+